[
  {
    "path": "CODE/2KEYFBUF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : KEYFBUFF.ASM                             *\n;*                                                                         *\n;*                   Programmer : David R. Dettmer                         *\n;*                                                                         *\n;*                   Start Date : March 3, 1995                            *\n;*                                                                         *\n;*                  Last Update :                                          *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Buffer_Frame_To_Page -- Copies a linear buffer to a virtual viewport  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n;********************** Model & Processor Directives ***********************\nIDEAL\nP386\nMODEL USE32 FLAT\njumps\n\n;******************************** Includes *********************************\nINCLUDE \"gbuffer.inc\"\ninclude\t\"profile.inc\"\n\n\n;******************************** Equates **********************************\n\nTRUE\tequ\t1\t\t\t; Boolean 'true' value\nFALSE\tequ\t0\t\t\t; Boolean 'false' value\n\n;*=========================================================================*/\n;* The following are defines used to control what functions are linked\t   *\n;* in for Buffer_Frame_To_Page.\t\t\t\t\t\t   *\n;*=========================================================================*/\n;USE_NORMAL\t\tEQU\tTRUE\n;USE_HORZ_REV \t\tEQU\tTRUE\n;USE_VERT_REV \t\tEQU\tTRUE\n;USE_SCALING \t\tEQU\tTRUE\n\n\nFLAG_NORMAL\t\tEQU\t0\nFLAG_TRANS\t\tEQU\t1\nFLAG_GHOST\t\tEQU\t2\nFLAG_FADING\t\tEQU\t4\nFLAG_PREDATOR\t\tEQU\t8\n\nFLAG_MASK\t\tEQU\t0Fh\n\n\nSHAPE_NORMAL \t\tEQU\t0000h\t\t; Standard shape\n;SHAPE_HORZ_REV \t\tEQU\t0001h\t\t; Flipped horizontally\n;SHAPE_VERT_REV \t\tEQU\t0002h\t\t; Flipped vertically\n;SHAPE_SCALING \t\tEQU\t0004h\t\t; Scaled (WORD scale_x, WORD scale_y)\n;SHAPE_VIEWPORT_REL \tEQU\t0010h\t\t; Coords are window-relative\n;SHAPE_WIN_REL \t\tEQU\t0010h\t\t; Coordinates are window relative instead of absolute.\nSHAPE_CENTER \t\tEQU\t0020h\t\t; Coords are based on shape's center pt\nSHAPE_TRANS\t\tEQU\t0040h\t\t; has transparency\n\nSHAPE_FADING \t\tEQU\t0100h\t\t; Fading effect (VOID * fading_table,\n\t\t\t\t\t\t;   WORD fading_num)\nSHAPE_PREDATOR \t\tEQU\t0200h\t\t; Transparent warping effect\n;SHAPE_COMPACT \t\tEQU\t0400h\t\t; Never use this bit\n;SHAPE_PRIORITY \t\tEQU\t0800h\t\t; Use priority system when drawing\nSHAPE_GHOST\t\tEQU\t1000h\t\t; Shape is drawn ghosted\n;SHAPE_SHADOW\t\tEQU\t2000h\nSHAPE_PARTIAL  \t\tEQU\t4000h\n;SHAPE_COLOR \t\tEQU\t8000h\t\t; Remap the shape's colors\n\t\t\t\t\t\t;   (VOID * color_table)\n\n\n;\n;.......................... Shadow Effect ..................................\n;\nSHADOW_COL\t\tEQU\t00FFh\t; magic number for shadows\n\n;......................... Priority System .................................\n;\nCLEAR_UNUSED_BITS  \tEQU\t0007h\t; and with 0000-0111 to clear\n\t\t\t\t\t;  non-walkable high bit and\n\t\t\t\t\t;  scaling id bits\nNON_WALKABLE_BIT  \tEQU\t0080h\t; and with 1000-0000 to clear all\n\t\t\t\t\t;  but non-walkable bit\n;\n;......................... Predator Effect .................................\n;\n;PRED_MASK\t\tEQU\t0007h\t; mask used for predator pixel puts\nPRED_MASK\t\tEQU\t000Eh\t; mask used for predator pixel puts\n\n\n;---------------------------------------------------------------------------\n;\n; Use a macro to make code a little cleaner.\n; The parameter varname is optional.\n; Syntax to use macro is :\n;  WANT equ expression\n;  USE func [,varname]\n; If the 'varname' is defined, a table declaration is created like:\n;\tGLOBAL\tTableName:DWORD\n; Then, the table entry is created:\n;  If WANT is true, the table entry is created for the given function:\n;\tvarname\tDD\tfunc\n;  If WANT is not TRUE, a Not_Supported entry is put in the table:\n;\tvarname\tDD\tNot_Supported\n; The resulting tables look like:\n;\n;\tGLOBAL\tExampTable:DWORD\n;\tExampTable\tDD\troutine1\n;\t\t\tDD\troutine2\n;\t\t\tDD\troutine3\n;\t\t\t...\n; Thus, each table is an array of function pointers.\n;\n;---------------------------------------------------------------------------\nMACRO USE func, varname\n IF WANT\n  varname \tDD\tfunc\n ELSE\n  varname\tDD\tNot_Supported\n ENDIF\nENDM\n\n; IFNB <varname>\n;\tGLOBAL\tvarname:DWORD\n; ENDIF\n\n;---------------------------------------------------------------------------\n\n\nDATASEG\n\n;---------------------------------------------------------------------------\n; Predator effect variables\n;---------------------------------------------------------------------------\n; make table for negative offset and use the used space for other variables\n\nBFPredNegTable\tDW\t-1, -3, -2, -5, -2, -4, -3, -1\n\t; 8 words below calculated\n\t\tDW\t0, 0, 0, 0, 0, 0, 0, 0\t; index ffffff00\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff10\nBFPredOffset\tDD\t0, 0, 0, 0\t\t; index ffffff20\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff30\n\t; partially faded predator effect value\nBFPartialPred\tDD\t0, 0, 0, 0\t\t; index ffffff40\nBFPartialCount\tDD\t0, 0, 0, 0\t\t; index ffffff50\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff60\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff70\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff80\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff90\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffa0\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffb0\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffc0\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffd0\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffe0\n\t\tDD\t0, 0, 0, 0\t\t; index fffffff0\nBFPredTable\tDW\t1, 3, 2, 5, 2, 3, 4, 1\n;BFPredTable\tDB\t1, 3, 2, 5, 4, 3, 2, 1\n\n\n\n\n\n\n\t\tglobal\tC BigShapeBufferStart:dword\n\t\tglobal\tC UseBigShapeBuffer:dword\n\t\tglobal\tC UseOldShapeDraw:dword\n\t\tglobal\tC TheaterShapeBufferStart:dword\n\t\tglobal\tC IsTheaterShape:dword\n\t\tglobal\tC Single_Line_Trans_Entry:near\n\t\tglobal\tC Next_Line:near\n\t\tglobal\tC MMX_Done:near\n\t\tglobal\tC MMXAvailable:dword\n\t\tglobal\tEndNewShapeJumpTable:byte\n\t\tglobal\tNewShapeJumpTable:dword\n\n\n;**********************************************************************************\n;\n; Jump tables for new line header system\n;\n; Each line of shape data now has a header byte which describes the data on the line.\n;\n\n;\n; Header byte control bits\n;\nBLIT_TRANSPARENT\t=1\nBLIT_GHOST\t\t=2\nBLIT_FADING\t\t=4\nBLIT_PREDATOR\t\t=8\nBLIT_SKIP\t\t=16\nBLIT_ALL\t\t=BLIT_TRANSPARENT or BLIT_GHOST or BLIT_FADING or BLIT_PREDATOR or BLIT_SKIP\n\n\n\t\tstruc\t\tShapeHeaderType\n\n\t\tdraw_flags\tdd\t?\n\t\tshape_data\tdd\t?\n\t\tshape_buffer\tdd\t?\n\n\t\tends\n\n;\n; Global definitions for routines that draw a single line of a shape\n;\n\t\tglobal\tShort_Single_Line_Copy:near\n\t\tglobal\tSingle_Line_Trans:near\n\t\tglobal\tSingle_Line_Ghost:near\n\t\tglobal\tSingle_Line_Ghost_Trans:near\n\t\tglobal\tSingle_Line_Fading:near\n\t\tglobal\tSingle_Line_Fading_Trans:near\n\t\tglobal\tSingle_Line_Ghost_Fading:near\n\t\tglobal\tSingle_Line_Ghost_Fading_Trans:near\n\t\tglobal\tSingle_Line_Predator:near\n\t\tglobal\tSingle_Line_Predator_Trans:near\n\t\tglobal\tSingle_Line_Predator_Ghost:near\n\t\tglobal\tSingle_Line_Predator_Ghost_Trans:near\n\t\tglobal\tSingle_Line_Predator_Fading:near\n\t\tglobal\tSingle_Line_Predator_Fading_Trans:near\n\t\tglobal\tSingle_Line_Predator_Ghost_Fading:near\n\t\tglobal\tSingle_Line_Predator_Ghost_Fading_Trans:near\n\t\tglobal\tSingle_Line_Skip:near\n\n\t\tglobal\tSingle_Line_Single_Fade:near\n\t\tglobal\tSingle_Line_Single_Fade_Trans:near\n\n\n\nlabel\t\tNewShapeJumpTable\tdword\n\n;\n; Jumptable for shape line drawing with no flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\nlabel\t\tCriticalFadeRedirections dword\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with transparent flags set\n;\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with ghost flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with ghost and transparent flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n\n\n\n;\n; Jumptable for shape line drawing routines with fading flag set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with fading and transparent flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Single_Fade_Trans\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading_Trans\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading_Trans\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with fading and ghost flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n\n;\n; Jumptable for shape line drawing routines with fading, transparent and ghost flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Single_Fade_Trans\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tSingle_Line_Ghost_Fading_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading_Trans\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tSingle_Line_Ghost_Fading_Trans\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n\n\n\n\n;\n; Jumptable for shape line drawing with predator flag set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with transparent and predator flags set\n;\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with ghost and predator flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with ghost and transparent and predator flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Predator_Ghost_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Predator_Ghost_Trans\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n\n\n\n;\n; Jumptable for shape line drawing routines with fading and predator flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with fading and transparent and predator flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Single_Fade_Trans\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Predator_Fading_Trans\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Predator_Fading_Trans\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with fading and ghost and predator flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Predator_Ghost_Fading\n\t\tdd\tSingle_Line_Predator_Ghost_Fading\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n\n\n\n\n\n;\n; Jumptable for shape line drawing routines with all flags set\n;\n\nlabel\t\tAllFlagsJumpTable\tdword\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Single_Fade_Trans\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tSingle_Line_Ghost_Fading_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Predator_Ghost_Trans\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Predator_Fading_Trans\n\t\tdd\tSingle_Line_Predator_Ghost_Fading\n\t\tdd\tSingle_Line_Predator_Ghost_Fading_Trans\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n\nlabel\t\tEndNewShapeJumpTable\tbyte\n\nCODESEG\n\n;---------------------------------------------------------------------------\n; Code Segment Tables:\n; This code uses the USE macro to set up tables of function addresses.\n; The tables have the following format:\n; Tables defined are:\n;\tBufferFrameTable\n;---------------------------------------------------------------------------\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Copy, BufferFrameTable\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Ghost\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Ghost_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Fading\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Fading_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Ghost_Fading\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Ghost_Fading_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Ghost\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Ghost_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Fading\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Fading_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Ghost_Fading\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Ghost_Fading_Trans\n\n\n\n\n\n;---------------------------------------------------------------------------\n\n\n\n\n;*********************************************************************************************\n;* Set_Shape_Header -- create the line header bytes for a shape                              *\n;*                                                                                           *\n;* INPUT:\tShape width                                                                  *\n;*              Shape height                                                                 *\n;*              ptr to raw shape data                                                        *\n;*              ptr to shape headers                                                         *\n;*              shape flags                                                                  *\n;*              ptr to translucency table                                                    *\n;*              IsTranslucent                                                                *\n;*                                                                                           *\n;* OUTPUT:      none                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   11/29/95 10:09AM ST : Created.                                                          *\n;*===========================================================================================*\n\n\t\tproc\tSetup_Shape_Header C near\n\n\t\tARG\tpixel_width \t:DWORD\t\t; width of rectangle to blit\n\t\tARG\tpixel_height\t:DWORD\t\t; height of rectangle to blit\n\t\tARG  \tsrc         \t:DWORD\t\t; this is a member function\n\t\tARG\theaders\t    \t:DWORD\n\t\tARG\tflags\t\t:DWORD\n\t\tARG\tTranslucent\t:DWORD\n\t\tARG\tIsTranslucent\t:DWORD\n\t\tLOCAL\ttrans_count\t:DWORD\n\n\t\tpushad\n\n\n\t\tmov\tesi,[src]\t\t;ptr to raw shape data\n\t\tmov\tedi,[headers]\t\t;ptr to headers we are going to set up\n\t\tmov\teax,[flags]\n\t\tand\teax,SHAPE_TRANS or SHAPE_FADING or SHAPE_PREDATOR or SHAPE_GHOST\n\t\tmov\t[(ShapeHeaderType edi).draw_flags],eax \t;save old flags in header\n\t\tadd\tedi,size ShapeHeaderType\n\t\tmov\tedx,[pixel_height]\t;number of shape lines to scan\n\n??outer_loop:\tmov\tecx,[pixel_width]\t;number of pixels in shape line\n\t\txor\tbl,bl\t\t\t;flag the we dont know anything about this line yet\n\t\tmov\t[trans_count],0\t\t;we havnt scanned any transparent pixels yet\n\n;\n; Scan one shape line to see what kind of data it contains\n;\n??inner_loop:\txor\teax,eax\n\t\tmov\tal,[esi]\n\t\tinc\tesi\n\n;\n; Check for transparent pixel\n;\n\t\ttest\tal,al\n\t\tjnz\t??not_transp\n\t\ttest\t[flags],SHAPE_TRANS\n\t\tjz\t??not_transp\n\t\tor\tbl,BLIT_TRANSPARENT\t;flag that pixel is transparent\n\t\tinc\t[trans_count]\t\t;keep count of the number of transparent pixels on the line\n\t\tjmp\t??end_lp\n\n;\n; Check for predator effect on this line\n;\n??not_transp:\ttest\t[flags],SHAPE_PREDATOR\n\t\tjz\t??not_pred\n\t\tor\tbl,BLIT_PREDATOR\n\n;\n; Check for ghost effects\n;\n??not_pred:\ttest\t[flags],SHAPE_GHOST\n\t\tjz\t??not_ghost\n\t\tpush\tedi\n\t\tmov\tedi,[IsTranslucent]\n\t\tcmp\t[byte edi+eax],-1\n\t\tpop\tedi\n\t\tjz\t??not_ghost\n\t\tor\tbl,BLIT_GHOST\n\n;\n; Check if fading is required\n;\n??not_ghost:\ttest\t[flags],SHAPE_FADING\n\t\tjz\t??end_lp\n\t\tor\tbl,BLIT_FADING\n\n??end_lp:       dec\tecx\n\t\tjnz\t??inner_loop\n\n\n;\n; Interpret the info we have collected and decide which routine will be\n; used to draw this line\n;\n\t\txor\tbh,bh\n\n\t\ttest\tbl,BLIT_TRANSPARENT\n\t\tjz\t??no_transparencies\n\t\tor\tbh,BLIT_TRANSPARENT\n\t\tmov\tecx,[pixel_width]\n\t\tcmp\tecx,[trans_count]\n\t\tjnz\t??not_all_trans\n\n; all pixels in the line were transparent so we dont need to draw it at all\n\t\tmov\tbh,BLIT_SKIP\n\t\tjmp\t??got_line_type\n\n??not_all_trans:\n??no_transparencies:\n\t\tmov\tal,bl\n\t\tand\tal,BLIT_PREDATOR\n\t\tor\tbh,al\n\t\tmov\tal,bl\n\t\tand\tal,BLIT_GHOST\n\t\tor\tbh,al\n\t\tmov\tal,bl\n\t\tand\tal,BLIT_FADING\n\t\tor\tbh,al\n\n;\n; Save the line header and do the next line\n;\n??got_line_type:mov\t[edi],bh\n\t\tinc\tedi\n\n\t\tdec\tedx\n\t\tjnz\t??outer_loop\n\n\n\t\tpopad\n\t\tret\n\n\t\tendp\tSetup_Shape_Header\n\n\n\n\n;**************************************************************\n;\n; Macro to fetch the header of the next line and jump to the appropriate routine\n;\n\t\tmacro\tnext_line\n\n\t\tadd\tedi , [ dest_adjust_width ]\t;add in dest modulo\n\t\tdec\tedx\t\t\t\t;line counter\n\t\tjz\t??real_out\t\t\t;return\n\t\tmov\tecx,[save_ecx]\t\t\t;ecx is pixel count\n\t\tmov\teax,[header_pointer]\t\t;ptr to next header byte\n\t\tmov\tal,[eax]\n\t\tinc\t[header_pointer]\n\t\tand\teax,BLIT_ALL\t\t\t;Make sure we dont jump to some spurious address\n\t\t\t\t\t\t\t; if the header is wrong then its better to draw with the wrong\n\t\t\t\t\t\t\t; shape routine than to die\n\t\tshl\teax,2\n\t\tadd\teax,[ShapeJumpTableAddress]\t;get the address to jump to\n\t\tjmp\t[dword eax]\t\t\t;do the jump\n\n\t\tendm\n\n\n\n\n\n\n;***************************************************************************\n;* VVC::TOPAGE -- Copies a linear buffer to a virtual viewport\t\t   *\n;*                                                                         *\n;* INPUT:\tWORD\tx_pixel\t\t- x pixel on viewport to copy from *\n;*\t\tWORD\ty_pixel \t- y pixel on viewport to copy from *\n;*\t\tWORD\tpixel_width\t- the width of copy region\t   *\n;*\t\tWORD\tpixel_height\t- the height of copy region\t   *\n;*\t\tBYTE *\tsrc\t\t- buffer to copy from\t\t   *\n;*\t\tVVPC *  dest\t\t- virtual viewport to copy to\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    Coordinates and dimensions will be adjusted if they exceed *\n;*\t        the boundaries.  In the event that no adjustment is \t   *\n;*\t        possible this routine will abort.  If the size of the \t   *\n;*\t\tregion to copy exceeds the size passed in for the buffer   *\n;*\t\tthe routine will automatically abort.\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Buffer_Frame_To_Page:NEAR\n\tPROC\tBuffer_Frame_To_Page C near\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\tARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\tARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\tARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\tARG    \tsrc         :DWORD\t\t; this is a member function\n\tARG\tdest        :DWORD\t\t; what are we blitting to\n\n\tARG\tflags       :DWORD\t\t; flags passed\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL\tIsTranslucent\t\t:DWORD\t; ptr to the is_translucent table\n\tLOCAL\tTranslucent\t\t:DWORD\t; ptr to the actual translucent table\n\tLOCAL\tFadingTable\t\t:DWORD\t; extracted fading table pointer\n\tLOCAL\tFadingNum\t\t:DWORD\t; get the number of times to fade\n\n\tLOCAL\tStashECX\t\t:DWORD\t; temp variable for ECX register\n\n\tLOCAL\tjflags\t\t\t:DWORD\t; flags used to goto correct buff frame routine\n\tLOCAL\tBufferFrameRout\t\t:DWORD\t; ptr to the buffer frame routine\n\n\tLOCAL\tjmp_loc\t\t\t:DWORD\t; calculated jump location\n\tLOCAL\tloop_cnt\t\t:DWORD\n\n\tLOCAL \tx1_pixel\t\t:DWORD\n\tLOCAL\ty1_pixel\t\t:DWORD\n\tLOCAL\tscr_x\t\t\t:DWORD\n\tLOCAL\tscr_y\t\t\t:DWORD\n\tLOCAL\tdest_adjust_width\t:DWORD\n\tLOCAL\tscr_adjust_width\t:DWORD\n\tLOCAL\theader_pointer\t\t:DWORD\n\tLOCAL\tuse_old_draw\t\t:DWORD\n\tLOCAL\tsave_ecx\t\t:DWORD\n\tLOCAL\tShapeJumpTableAddress\t:DWORD\n\tLOCAL\tshape_buffer_start\t:DWORD\n\n\n\tprologue\n\tcmp\t[ src ] , 0\n\tjz\t??real_out\n\n\tcmp\t[UseOldShapeDraw],0\n\tjz\t??new_system\n\n\tmov\t[use_old_draw],1\n\tjmp\t??do_args\n\n??new_system:\n\t;\n\t; Save the line attributes pointers and\n\t; Modify the src pointer to point to the actual image\n\t;\n\tcmp\t[UseBigShapeBuffer],0\n\tjz\t??do_args\t\t\t;just use the old shape drawing system\n\tmov\tedi,[src]\n\tmov\t[header_pointer],edi\n\n\tmov\teax,[BigShapeBufferStart]\n\tcmp\t[(ShapeHeaderType edi).shape_buffer],0\n\tjz\t??is_ordinary_shape\n\tmov\teax,[TheaterShapeBufferStart]\n??is_ordinary_shape:\n\tmov\t[shape_buffer_start],eax\n\n\tmov\tedi,[(ShapeHeaderType edi).shape_data]\n\tadd\tedi,[shape_buffer_start]\n\tmov\t[src],edi\n\tmov\t[use_old_draw],0\n\n\n\t;====================================================================\n\t; Pull off optional arguments:\n\t; EDI is used as an offset from the 'flags' parameter, to point\n\t; to the optional argument currently being processed.\n\t;====================================================================\n??do_args:\n\tmov\tedi , 4\t \t\t\t; optional params start past flags\n\tmov\t[ jflags ] , 0\t\t\t; clear jump flags\n\n??check_centering:\n\t;-------------------------------------------------------------------\n\t; See if we need to center the frame\n\t;-------------------------------------------------------------------\n\ttest\t[ flags ] , SHAPE_CENTER\t; does this need to be centered?\n\tje\t??check_trans\t\t\t; if not the skip over this stuff\n\n\tmov\teax , [ pixel_width ]\n\tmov\tebx , [ pixel_height ]\n\tsar\teax , 1\n\tsar\tebx , 1\n\tsub\t[ x_pixel ] , eax\n\tsub\t[ y_pixel ] , ebx\n\n??check_trans:\n\ttest\t[ flags ] , SHAPE_TRANS\n\tjz\t??check_ghost\n\n\tor\t[ jflags ] , FLAG_TRANS\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_GHOST: DWORD is_translucent tbl\n\t;--------------------------------------------------------------------\n??check_ghost:\n\ttest\t[ flags ] , SHAPE_GHOST\t\t; are we ghosting this shape\n\tjz\t??check_fading\n\n\tmov\teax , [ flags + edi ]\n\tor\t[ jflags ] , FLAG_GHOST\n\tmov\t[ IsTranslucent ] , eax\t\t; save ptr to is_trans. tbl\n\tadd\teax , 0100h\t\t\t; add 256 for first table\n\tadd\tedi , 4\t\t\t\t; next argument\n\tmov\t[ Translucent ] , eax\t\t; save ptr to translucent tbl\n\n\n\n??check_fading:\n\t;______________________________________________________________________\n\t; If this is the first time through for this shape then\n\t; set up the shape header\n\t;______________________________________________________________________\n\tpushad\n\n\tcmp\t[UseBigShapeBuffer],0\t\t;no big shape buffer so use old system\n\tjz\t??new_shape\n\tcmp\t[UseOldShapeDraw],0\t\t;use old shape system flag\n\tjnz\t??new_shape\n\n\tmov\tedi,[header_pointer]\n\tcmp\t[(ShapeHeaderType edi).draw_flags],-1\n\tjz\t??setup_headers\n\tmov\teax,[flags]\t\t\t\t\t\t\t ;Redo the shape headers if this shape was\n\tand\teax,SHAPE_TRANS or SHAPE_FADING or SHAPE_PREDATOR or SHAPE_GHOST ;initially set up with different flags\n\tcmp\teax,[(ShapeHeaderType edi).draw_flags]\n\tjz\t??no_header_setup\n??new_shape:\n\tmov\t[use_old_draw],1\n\tjmp\t??no_header_setup\n\n??setup_headers:\n\tpush\t[IsTranslucent]\n\tpush\t[Translucent]\n\tpush\t[flags]\n\tpush\t[header_pointer]\n\tpush\t[src]\n\tpush\t[pixel_height]\n\tpush\t[pixel_width]\n\tcall\tSetup_Shape_Header\n\tadd\tesp,7*4\n\tmov\t[ShapeJumpTableAddress],offset AllFlagsJumpTable\n\tjmp\t??headers_set\n??no_header_setup:\n\n\txor\teax,eax\n\ttest\t[flags],SHAPE_PREDATOR\n\tjz\t??not_shape_predator\n\tor\tal,BLIT_PREDATOR\n\n??not_shape_predator:\n\ttest\t[flags],SHAPE_FADING\n\tjz\t??not_shape_fading\n\tor\tal,BLIT_FADING\n\n??not_shape_fading:\n\n\ttest\t[flags],SHAPE_TRANS\n\tjz\t??not_shape_transparent\n\tor\tal,BLIT_TRANSPARENT\n\n??not_shape_transparent:\n\n\ttest\t[flags],SHAPE_GHOST\n\tjz\t??not_shape_ghost\n\tor\tal,BLIT_GHOST\n\n??not_shape_ghost:\n\n\tshl\teax,7\n\tadd\teax,offset NewShapeJumpTable\n\tmov\t[ShapeJumpTableAddress],eax\n\n\n??headers_set:\n\tpopad\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_FADING: DWORD fade_table[256], DWORD fade_count\n\t;--------------------------------------------------------------------\n\ttest\t[ flags ] , SHAPE_FADING\t; are we fading this shape\n\tjz\t??check_predator\n\n\tmov\teax , [ flags + edi ]\n\tmov\t[ FadingTable ] , eax\t\t; save address of fading tbl\n\tmov\teax , [ flags + edi + 4 ]\t; get fade num\n\tor\t[ jflags ] , FLAG_FADING\n\tand\teax , 03fh\t\t\t; no need for more than 63\n\tadd\tedi , 8\t\t\t\t; next argument\n\tcmp\teax , 0\t\t\t\t; check if it's 0\n\tjnz\t??set_fading\t\t\t; if not, store fade num\n\n\tand\t[ flags ] , NOT SHAPE_FADING\t; otherwise, don't fade\n\n??set_fading:\n\tmov\t[ FadingNum ] , eax\n\n\tmov\tebx,[ShapeJumpTableAddress]\n\tmov\t[dword ebx+CriticalFadeRedirections-NewShapeJumpTable],offset Single_Line_Single_Fade\n\tmov\t[dword ebx+CriticalFadeRedirections-NewShapeJumpTable+4],offset Single_Line_Single_Fade_Trans\n\tcmp\teax,1\n\tjz\t??single_fade\n\tmov\t[dword ebx+CriticalFadeRedirections-NewShapeJumpTable],offset Single_Line_Fading\n\tmov\t[dword ebx+CriticalFadeRedirections-NewShapeJumpTable+4],offset Single_Line_Fading_Trans\n\n??single_fade:\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_PREDATOR: DWORD init_pred_lookup_offset (0-7)\n\t;--------------------------------------------------------------------\n??check_predator:\n\ttest\t[ flags ] , SHAPE_PREDATOR\t; is predator effect on\n\tjz\t??check_partial\n\n\tmov\teax , [ flags + edi ]\t\t; pull the partial value\n\tor\t[ jflags ] , FLAG_PREDATOR\n\tshl\teax , 1\n\tcmp\teax , 0\n\tjge\t??check_range\n\n\tneg\teax\n\tmov\tebx , -1\n\tand\teax , PRED_MASK\t\t\t; keep entries within bounds\n\tmov\tbl , al\n\tmov\teax , ebx\t\t\t; will be ffffff00-ffffff07\n\tjmp\t??pred_cont\n\n??check_range:\n\tand\teax , PRED_MASK\t\t\t; keep entries within bounds\n\n??pred_cont:\n\tadd\tedi , 4\t\t\t\t; next argument\n\tmov\t[ BFPredOffset ] , eax\n\tmov\t[ BFPartialCount ] , 0\t\t; clear the partial count\n\tmov\t[ BFPartialPred ] , 100h\t; init partial to off\n\n??pred_neg_init:\n\tmov  \tesi , [ dest ]\t    ; get ptr to dest\n\tmov\tebx, 7 * 2\n\n??pred_loop:\n\tmovzx\teax , [ WORD PTR BFPredNegTable + ebx ]\n\tadd\teax , [ (GraphicViewPort esi) . GVPWidth ]\t; add width\n\tadd\teax , [ (GraphicViewPort esi) . GVPXAdd ]\t; add x add\n\tadd\teax , [ (GraphicViewPort esi) . GVPPitch ]\t; extra pitch of DD surface\tST - 9/29/95 1:08PM\n\tmov\t[ WORD PTR BFPredNegTable + 16 + ebx ] , ax\n\tdec\tebx\n\tdec\tebx\n\tjge\t??pred_loop\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_PARTIAL: DWORD partial_pred_value (0-255)\n\t;--------------------------------------------------------------------\n??check_partial:\n\ttest\t[ flags ] , SHAPE_PARTIAL\t\t; is this a partial pred?\n\tjz\t??setupfunc\n\n\tmov\teax , [ flags + edi ]\t\t; pull the partial value\n\tadd\tedi , 4\t\t\t\t; next argument\n\tand\teax , 0ffh\t\t\t; make sure 0-255\n\tmov\t[ BFPartialPred ] , eax\t\t; store it off\n\n??setupfunc:\n\tmov\tebx , [ jflags ]\t\t; load flags value\n\tand\tebx , FLAG_MASK\t\t\t; clip high bits\n\tadd\tebx , ebx\t\t\t; mult by 4 to get DWORD offset\n\tadd\tebx , ebx\n\tmov\tebx , [ BufferFrameTable + ebx ]\t; get table value\n\tmov\t[ BufferFrameRout ] , ebx\t\t; store it in the function pointer\n\n; Clip dest Rectangle against source Window boundaries.\n\n\tmov\t[ scr_x ] , 0\n\tmov\t[ scr_y ] , 0\n\tmov  \tesi , [ dest ]\t    ; get ptr to dest\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\n\tor\tal , dl\n\tjz\t??do_blit\n\n\tmov\t[use_old_draw],1\n\ttest\tcl , 1000b\n\tjz\t??dest_left_ok\n\n\tmov\teax , [ x_pixel ]\n\tneg\teax\n\tmov\t[ x_pixel ] , 0\n\tmov\t[ scr_x ] , eax\n\n??dest_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dest_bottom_ok\n\n\tmov\teax , [ y_pixel ]\n\tneg\teax\n\tmov\t[ y_pixel ] , 0\n\tmov\t[ scr_y ] , eax\n\n??dest_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??dest_right_ok\n\n\tmov\teax , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n\n??dest_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\n\tmov\teax , [ (GraphicViewPort esi) . GVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n??do_blit:\n\tcld\n\tmov\teax , [ (GraphicViewPort esi) . GVPXAdd ]\n\tadd\teax , [ (GraphicViewPort esi) . GVPPitch ]\n\tadd\teax , [ (GraphicViewPort esi) . GVPWidth ]\n\tmov\tedi , [ (GraphicViewPort esi) . GVPOffset ]\n\n\tmov\tecx , eax\n\tmul\t[ y_pixel ]\n\tadd\tedi , [ x_pixel ]\n\tadd\tedi , eax\n\n\tadd\tecx , [ x_pixel ]\n\tsub\tecx , [ x1_pixel ]\n\tmov\t[ dest_adjust_width ] , ecx\n\n\tmov\tesi , [ src ]\n\tmov\teax , [ pixel_width ]\n\tsub\teax , [ x1_pixel ]\n\tadd\teax , [ x_pixel ]\n\tmov\t[ scr_adjust_width ] , eax\n\n\tmov\teax , [ scr_y ]\n\tmul\t[ pixel_width ]\n\tadd\teax , [ scr_x ]\n\tadd\tesi , eax\n\n;\n; If the shape needs to be clipped then we cant handle it with the new header systen\n; so draw it with the old shape drawer\n;\n\tcmp\t[use_old_draw],0\n\tjnz\t??use_old_stuff\n\n\tadd\t[header_pointer],size ShapeHeaderType\n\tmov\tedx,[pixel_height]\n\tmov\tecx,[pixel_width]\n\tmov\teax,[header_pointer]\n\tmov\tal,[eax]\n\tmov\t[save_ecx],ecx\n\tinc\t[header_pointer]\n\tand\teax,BLIT_ALL\n\tshl\teax,2\n\tadd\teax,[ShapeJumpTableAddress]\n\tjmp\t[dword eax]\n\n\n??use_old_stuff:\n\tmov\tedx , [ y1_pixel ]\n\tmov\teax , [ x1_pixel ]\n\n\tsub\tedx , [ y_pixel ]\n\tjle\t??real_out\n\n\tsub\teax , [ x_pixel ]\n\tjle\t??real_out\n\n\tjmp\t[ BufferFrameRout ]\t; buffer frame to viewport routine\n\n??real_out:\n\tepilogue\n\n\tret\n\n\n; ********************************************************************\n; Forward bitblit only\n; the inner loop is so efficient that\n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n; ********************************************************************\nglobal\tBF_Copy:near\n\nBF_Copy:\n\tprologue\n\tcmp\teax , 10\n\tjl\t??forward_loop_bytes\n\n??forward_loop_dword:\n\tmov\tecx , edi\n\tmov\tebx , eax\n\tneg\tecx\n\tand\tecx , 3\n\tsub\tebx , ecx\n\trep\tmovsb\n\tmov\tecx , ebx\n\tshr\tecx , 2\n\trep\tmovsd\n\tmov\tecx , ebx\n\tand\tecx , 3\n\trep\tmovsb\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??forward_loop_dword\n\n\tret\n\n??forward_loop_bytes:\n\tmov\tecx , eax\n\trep\tmovsb\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\t\t\t\t\t; decrement the height\n\tjnz\t??forward_loop_bytes\n\tepilogue\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\n\t\tsegment code page public use32 'code'\t; Need stricter segment alignment\n\t\t\t\t\t\t\t; for pentium optimisations\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\n\nSingle_Line_Trans:\n\t\tprologue\n??slt_mask_map_lp:\t\t\t\t; Pentium pipeline usage\n\t\t\t\t\t\t;Pipe\tCycles\n\t\tmov\tal,[esi]\t\t;U\t1\n\t\tinc\tesi\t\t\t;Vee\t1\n\n\t\ttest\tal,al\t\t\t;U\t1\n\t\tjz\t??slt_skip\t\t;Vee\t1/5\n\n??slt_not_trans:mov\t[edi],al\t\t;u \t1\n\n\t\tinc\tedi\t\t\t;vee\t1\n\t\tdec\tecx\t\t\t;u\t1\n\n\t\tjnz\t??slt_mask_map_lp\t;vee  (maybe)\t1\n\n??slt_end_line:\tepilogue\n\t\tnext_line\n\n\t\talign\t32\n\n??slt_skip:\tinc\tedi\n\t\tdec\tecx\n\t\tjz\t??slt_skip_end_line\n\n\t\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\t??slt_skip2\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\t\tdec\tecx\n\t\tjnz\t??slt_mask_map_lp\n\n\t\tepilogue\n\t\tnext_line\n\n\t\talign\t32\n\n??slt_skip2:\tinc\tedi\n\t\tdec\tecx\n\t\tjz\t??slt_end_line\n\n;\n; If we have hit two transparent pixels in a row then we go into\n; the transparent optimised bit\n;\n??slt_round_again:\n\trept\t64\n\t\tmov\tal,[esi]   ;\t;pipe 1\n\t\tinc\tesi\t   ;1\t;pipe 2\n\t\ttest\tal,al\t   ;\t;pipe 1\n\t\tjnz\t??slt_not_trans;pipe 2 (not pairable in 1)\n\t\t\t\t   ;2\n\t\tinc\tedi\t   ;\t;pipe 1\n\t\tdec\tecx\t   ;3\t;pipe 2\n\t\tjz\t??slt_end_line ;4\t;pipe 1 (not pairable)\n\tendm\t\t\t   ; best case is 4 cycles per iteration\n\t\tjmp\t??slt_round_again\n\n\n\n??slt_skip_end_line:\n\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single line with no transparent pixels\n;\n; 11/29/95 10:21AM - ST\n;\n; We have to align the destination for cards that dont bankswitch correctly\n; when you write non-aligned data.\n;\n\t\talign\t32\nLong_Single_Line_Copy:\n\t\tprologue\n\n rept 3\n\t\ttest\tedi,3\n\t\tjz\t??LSLC_aligned\n\t\tmovsb\n\t\tdec\tecx\n endm\n\n??LSLC_aligned:\n\t\tmov\tebx,ecx\n\n\t\tshr\tecx,2\n\t\trep\tmovsd\n\t\tand\tebx,3\n\t\tjz\t??out\n\t\tmovsb\n\t\tdec\tbl\n\t\tjz\t??out\n\t\tmovsb\n\t\tdec\tbl\n\t\tjz\t??out\n\t\tmovsb\n??out:\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single short line with no transparent pixels\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\nShort_Single_Line_Copy:\n\t\tprologue\n\t\tcmp\tecx,16\n\t\tjge\tLong_Single_Line_Copy\n\t\tmov\tebx,ecx\n\t\trep\tmovsb\n\t\tmov\tecx,ebx\n\t\tepilogue\n\t\tnext_line\n\n\n;*****************************************************************************\n; Skip a line of source that is all transparent\n;\n; 11/29/95 10:21AM - ST\n;\n\n\t\talign\t32\nSingle_Line_Skip:\n\t\tprologue\n\t\tadd\tesi,ecx\n\t\tadd\tedi,ecx\n\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single line with ghosting\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\nSingle_Line_Ghost:\n\n\t\tprologue\n\t\txor\teax,eax\n??slg_loop:\tmov\tal,[esi]\n\t\tmov\tebx,[IsTranslucent]\n\t\tinc\tesi\n\t\tmov\tbh,[eax+ebx]\n\t\tcmp\tbh,-1\n\t\tjz\t??slg_store_pixel\n\n\t\tand\tebx,0ff00h\n\t\tmov\tal,[edi]\n\t\tadd\tebx,[Translucent]\n\t\tmov\tal,[eax+ebx]\n\n??slg_store_pixel:\n\t\tmov\t[edi],al\n\n\t\tinc\tedi\n\t\tdec\tecx\n\t\tjnz\t??slg_loop\n\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels and ghosting\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\nSingle_Line_Ghost_Trans:\n\t\tprologue\n\t\txor\teax,eax\n;\t\tcmp\tecx,3\n;\t\tja\t??slgt4\n\n??slgt_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\t??slgt_transparent\n\n??slgt_not_transparent:\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[eax+ebx]\n\t\tcmp\tbh,-1\n\t\tjz\t??slgt_store_pixel\n\n\t\tand\tebx,0ff00h\n\t\tmov\tal,[edi]\n\t\tadd\tebx,[Translucent]\n\t\tmov\tal,[eax+ebx]\n\n??slgt_store_pixel:\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\t\tdec\tecx\n\t\tjnz\t??slgt_loop\n\t\tepilogue\n\t\tnext_line\n\n\n\t\talign\t32\n\n??slgt_transparent:\n\t\tinc\tedi\t\t;1\n\t\tdec\tecx\t\t;2\n\t\tjz\t??slgt_out\t;1 (not pairable)\n\n??slgt_round_again:\n\trept\t64\n\t\tmov\tal,[esi]   ;\t;pipe 1\n\t\tinc\tesi\t   ;1\t;pipe 2\n\t\ttest\tal,al\t   ;\t;pipe 1\n\t\tjnz\t??slgt_not_transparent\t;pipe 2 (not pairable in 1)\n\t\t\t\t   ;2\n\t\tinc\tedi\t   ;\t;pipe 1\n\t\tdec\tecx\t   ;3\t;pipe 2\n\t\tjz\t??slgt_out ;4\t;pipe 1 (not pairable)\n\tendm\t\t\t   ; best case is 4 cycles per iteration\n\t\tjmp\t??slgt_round_again\n\n??slgt_out:\tepilogue\n\t\tnext_line\n\n\n\n;\n; Optimised video memory access version\n;\n\t\talign \t32\n\n??slgt4:        push\tedx\n\t\tmov\tedx,[edi]\n\n\trept\t4\n\tlocal\tslgt4_store1\n\tlocal\tslgt4_trans1\n\t\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\tslgt4_trans1\n\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[eax+ebx]\n\t\tcmp\tbh,-1\n\t\tjz\tslgt4_store1\n\n\t\tand\tebx,0ff00h\n\t\tmov\tal,dl\n\t\tadd\tebx,[Translucent]\n\t\tmov\tal,[eax+ebx]\n\nslgt4_store1:\tmov\tdl,al\n\nslgt4_trans1:\tror\tedx,8\n\tendm\n\t\tmov\t[edi],edx\n\t\tpop\tedx\n\t\tlea\tedi,[edi+4]\n\t\tlea\tecx,[ecx+0fffffffch]\n\t\tcmp\tecx,3\n\t\tja\t??slgt4\n\t\ttest\tecx,ecx\n\t\tjnz\t??slgt_loop\n\n\t\tepilogue\n\t\tnext_line\n\n\n\n\n\n\n\n\n\n\n;*****************************************************************************\n; Draw a single line with fading (colour remapping)\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\n\nSingle_Line_Fading:\n\t\tprologue\n\t\txor\teax,eax\n\t\tmov\tebx,[FadingTable]\n\t\tpush\tebp\n\t\tmov\tebp,[FadingNum]\n\t\tpush\tebp\n\n??slf_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\n\t\tmov\tebp,[esp]\n\n??slf_fade_loop:mov\tal,[ebx+eax]\n\t\tdec\tebp\n\t\tjnz\t??slf_fade_loop\n\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\n\t\tdec\tecx\n\t\tjnz\t??slf_loop\n\t\tadd\tesp,4\n\t\tpop\tebp\n\t\tepilogue\n\t\tnext_line\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels and fading (colour remapping)\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\n\nSingle_Line_Fading_Trans:\n\t\tprologue\n\t\txor\teax,eax\n\t\tmov\tebx,[FadingTable]\n\t\tpush\tebp\n\t\tmov\tebp,[FadingNum]\n\t\tpush\tebp\n\n??slft_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\t??slft_transparent\n\n\t\tmov\tebp,[esp]\n\n??slft_fade_loop:\n\t\tmov\tal,[ebx+eax]\n\t\tdec\tebp\n\t\tjnz\t??slft_fade_loop\n\n\t\tmov\t[edi],al\n??slft_transparent:\n\t\tinc\tedi\n\n\t\tdec\tecx\n\t\tjnz\t??slft_loop\n\t\tadd\tesp,4\n\t\tpop\tebp\n\t\tepilogue\n\t\tnext_line\n\n\n\n\n\n;*****************************************************************************\n; Draw a single line with a single fade level (colour remap)\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\n\nSingle_Line_Single_Fade:\n\t\tprologue\n\t\txor\teax,eax\n\t\tmov\tebx,[FadingTable]\n\n??slsf_loop:\tmov\tal,[esi]\n\t\tmov\tal,[ebx+eax]\n\t\tmov\t[edi],al\n\t\tinc\tesi\n\t\tinc\tedi\n\n\t\tdec\tecx\n\t\tjnz\t??slsf_loop\n\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels and a single fade level (colour remap)\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\n\nSingle_Line_Single_Fade_Trans:\n\t\tprologue\n\t\txor\teax,eax\n\t\tmov\tebx,[FadingTable]\n\n??slsft_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\t??slsft_transparent\n\t\tmov\tal,[ebx+eax]\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\t\tdec\tecx\n\t\tjnz\t??slsft_loop\n\t\tepilogue\n\t\tnext_line\n\n\t\talign\t32\n\n??slsft_transparent:\n\t\tinc\tedi\n\n\t\tdec\tecx\n\t\tjz\t??slsft_next_line\n\t\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\t??slsft_transparent\n\t\tmov\tal,[ebx+eax]\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\t\tdec\tecx\n\t\tjnz\t??slsft_loop\n\n??slsft_next_line:\n\t\tepilogue\n\t\tnext_line\n\n\n\n\n\n;*****************************************************************************\n; Draw a single line with ghosting and fading (colour remapping)\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\n\nSingle_Line_Ghost_Fading:\n\n\t\tprologue\n\t\tmov\t[StashECX],ecx\n\n??SLGF_loop:\txor\teax,eax\n\t\tmov\tal,[esi]\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[eax+ebx]\n\t\tcmp\tbh,-1\n\t\tjz\t??slgf_do_fading\n\n\t\tand\tebx,0ff00h\n\n\t\tmov\tal,[edi]\n\t\tadd\tebx,[Translucent]\n\t\tmov\tal,[ebx+eax]\n\n??slgf_do_fading:\n\t\tmov\tebx,[FadingTable]\n\t\tmov\tecx,[FadingNum]\n\n??slgf_fade_loop:\n\t\tmov\tal,[eax+ebx]\n\t\tdec\tecx\n\t\tjnz\t??slgf_fade_loop\n\n\t\tmov\t[edi],al\n\t\tinc\tesi\n\t\tinc\tedi\n\n\t\tdec\t[StashECX]\n\t\tjnz\t??SLGF_loop\n\t\tepilogue\n\t\tnext_line\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels, ghosting and fading\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\n\nSingle_Line_Ghost_Fading_Trans:\n\t\tprologue\n\t\tmov\t[StashECX],ecx\n\t\txor\teax,eax\n\n;\t\tcmp\tecx,3\n;\t\tja\t??slgft4\n\n??SLGFT_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\t??slgft_trans_pixel\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[eax+ebx]\n\t\tcmp\tbh,-1\n\t\tjz\t??slgft_do_fading\n\n\t\tand\tebx,0ff00h\n\n\t\tmov\tal,[edi]\n\t\tadd\tebx,[Translucent]\n\t\tmov\tal,[ebx+eax]\n\n??slgft_do_fading:\n\t\tmov\tebx,[FadingTable]\n\t\tmov\tecx,[FadingNum]\n\n??slgft_fade_loop:\n\t\tmov\tal,[eax+ebx]\n\t\tdec\tecx\n\t\tjnz\t??slgft_fade_loop\n\n\t\tmov\t[edi],al\n??slgft_trans_pixel:\n\t\tinc\tedi\n\n\t\tdec\t[StashECX]\n\t\tjnz\t??SLGFT_loop\n\t\tepilogue\n\t\tnext_line\n\n\n\t\talign\t32\n\n??slgft4:\tpush\tedx\n\t\tmov\tedx,[edi]\n\n\trept\t4\n\tlocal\tslgft4_fade\n\tlocal\tslgft4_fade_lp\n\tlocal\tslgft4_trans\n\t\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\tslgft4_trans\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[eax+ebx]\n\t\tcmp\tbh,-1\n\t\tjz\tslgft4_fade\n\n\t\tand\tebx,0ff00h\n\n\t\tmov\tal,dl\n\t\tadd\tebx,[Translucent]\n\t\tmov\tal,[ebx+eax]\n\nslgft4_fade:\tmov\tebx,[FadingTable]\n\t\tmov\tecx,[FadingNum]\n\nslgft4_fade_lp:\tmov\tal,[eax+ebx]\n\t\tdec\tecx\n\t\tjnz\tslgft4_fade_lp\n\n\t\tmov\tdl,al\n\nslgft4_trans:\tror\tedx,8\n\tendm\n\t\tmov\t[edi],edx\n\t\tpop\tedx\n\t\tlea\tedi,[edi+4]\n\t\tsub\t[StashECX],4\n\t\tjz\t??slgft4_out\n\t\tcmp\t[StashECX],3\n\t\tja\t??slgft4\n\t\tjmp\t??SLGFT_loop\n\n??slgft4_out:\tepilogue\n\t\tnext_line\n\n\n;*****************************************************************************\n; Draw a single line with predator effect\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\n\nSingle_Line_Predator:\n\n\t\tprologue\n\n??slp_loop:\tmov\tal,[esi]\n\n\t\tmov\tebx,[BFPartialCount]\n\t\tadd\tebx,[BFPartialPred]\n\t\tor\tbh,bh\n\t\tjnz\t??slp_get_pred\n\n\t\tmov\t[BFPartialCount] , ebx\n\t\tjmp\t??slp_skip_pixel\n\n??slp_get_pred:\txor\tbh , bh\n\t\tmov\teax,[BFPredOffset]\n\t\tmov\t[BFPartialCount] , ebx\n\t\tadd\t[BYTE BFPredOffset],2\n\t\tmov\teax,[DWORD BFPredTable+eax]\n\t\tand\t[BYTE BFPredOffset],PRED_MASK\n\t\tand\teax,0ffffh\n\n\t\tmov\tal,[edi+eax]\n\t\tmov\t[edi],al\n\n??slp_skip_pixel:\n\t\tinc\tesi\n\t\tinc\tedi\n\n\t\tdec\tecx\n\t\tjnz\t??slp_loop\n\n\t\tepilogue\n\t\tnext_line\n\n\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels and predator effect\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\n\nSingle_Line_Predator_Trans:\n\n\t\tprologue\n\n??slpt_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\t??slpt_skip_pixel\n\n\t\tmov\tebx,[BFPartialCount]\n\t\tadd\tebx,[BFPartialPred]\n\t\tor\tbh,bh\n\t\tjnz\t??slpt_get_pred\n\n\t\tmov\t[BFPartialCount] , ebx\n\t\tjmp\t??slpt_skip_pixel\n\n??slpt_get_pred:xor\tbh , bh\n\t\tmov\teax,[BFPredOffset]\n\t\tmov\t[BFPartialCount] , ebx\n\t\tadd\t[BYTE BFPredOffset],2\n\t\tmov\teax,[DWORD BFPredTable+eax]\n\t\tand\t[BYTE PTR BFPredOffset ] , PRED_MASK\n\t\tand\teax,0ffffh\n\n\t\tmov\tal,[edi+eax]\n\t\tmov\t[edi],al\n\n??slpt_skip_pixel:\n\t\tinc\tedi\n\n\t\tdec\tecx\n\t\tjnz\t??slpt_loop\n\n\t\tepilogue\n\t\tnext_line\n\n\n;*****************************************************************************\n; Draw a single line with predator and ghosting\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\n\nSingle_Line_Predator_Ghost:\n\n\t\tprologue\n\n??slpg_loop:\tmov\tal,[esi]\n\t\tmov\tebx,[BFPartialCount]\n\t\tadd\tebx,[BFPartialPred]\n\t\ttest\tbh,bh\n\t\tjnz\t??slpg_get_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[BFPartialCount],ebx\n\t\tjmp\t??slpg_check_ghost\n\n??slpg_get_pred:\n\t\txor\tbh,bh\n\t\tmov\teax,[BFPredOffset]\n\t\tmov\t[BFPartialCount],ebx\n\t\tadd\t[BYTE BFPredOffset],2\n\t\tmov\teax,[DWORD BFPredTable+eax ]\n\t\tand\t[BYTE BFPredOffset],PRED_MASK\n\t\tand\teax,0ffffh\n\t\tmov\tal,[edi+eax]\n\n??slpg_check_ghost:\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[ebx+eax]\n\t\tcmp\tbh,0ffh\n\t\tje\t??slpg_store_pixel\n\n\t\txor\teax,eax\n\t\tand\tebx,0FF00h\n\n\t\tmov\tal,[edi]\n\t\tadd\tebx,[Translucent]\n\n\t\tmov\tal,[ebx+eax]\n\n??slpg_store_pixel:\n\t\tmov\t[edi],al\n\t\tinc\tesi\n\t\tinc\tedi\n\n\t\tdec\tecx\n\t\tjnz\t??slpg_loop\n\n\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels, predator and ghosting\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\n\nSingle_Line_Predator_Ghost_Trans:\n\t\tprologue\n\n??slpgt_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\t??slpgt_transparent\n\n\t\tmov\tebx,[BFPartialCount]\n\t\tadd\tebx,[BFPartialPred]\n\t\ttest\tbh,bh\n\t\tjnz\t??slpgt_get_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[BFPartialCount],ebx\n\t\tjmp\t??slpgt_check_ghost\n\n??slpgt_get_pred:\n\t\txor\tbh,bh\n\t\tmov\teax,[BFPredOffset]\n\t\tmov\t[BFPartialCount],ebx\n\t\tadd\t[BYTE BFPredOffset],2\n\t\tmov\teax,[DWORD BFPredTable+eax ]\n\t\tand\t[BYTE BFPredOffset],PRED_MASK\n\t\tand\teax,0ffffh\n\t\tmov\tal,[edi+eax]\n\n??slpgt_check_ghost:\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[ebx+eax]\n\t\tcmp\tbh,0ffh\n\t\tje\t??slpgt_store_pixel\n\n\t\txor\teax,eax\n\t\tand\tebx,0FF00h\n\n\t\tmov\tal,[edi]\n\t\tadd\tebx,[Translucent]\n\n\t\tmov\tal,[ebx+eax]\n\n??slpgt_store_pixel:\n\t\tmov\t[edi],al\n??slpgt_transparent:\n\t\tinc\tedi\n\n\t\tdec\tecx\n\t\tjnz\t??slpgt_loop\n\n\t\tpop\tecx\n\t\tepilogue\n\t\tnext_line\n\n\n;*****************************************************************************\n; Draw a single line with predator and fading\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\n\nSingle_Line_Predator_Fading:\n\n\t\tprologue\n\t\tmov\t[StashECX],ecx\n\n??slpf_loop:\tmov\tal,[esi]\n\t\tmov\tebx,[BFPartialCount]\n\t\tinc\tesi\n\t\tadd\tebx,[BFPartialPred]\n\t\ttest\tbh,bh\n\t\tjnz\t??slpf_get_pred\n\n\t\tmov\t[BFPartialCount],ebx\n\t\tjmp\t??slpf_do_fading\n\n??slpf_get_pred:xor\tbh,bh\n\t\tmov\teax,[BFPredOffset]\n\t\tmov\t[BFPartialCount],ebx\n\t\tand\t[BYTE BFPredOffset],2\n\t\tmov\teax,[DWORD BFPredTable+eax]\n\t\tand\t[BYTE BFPredOffset],PRED_MASK\n\n\t\tand\teax,0ffffh\n\t\tmov\tal,[eax+edi]\n\n??slpf_do_fading:\n\t\tand\teax,255\n\t\tmov\tebx,[FadingTable]\n\t\tmov\tecx,[FadingNum]\n\n??slpf_fade_loop:\n\t\tmov\tal,[eax+ebx]\n\t\tdec\tecx\n\t\tjnz\t??slpf_fade_loop\n\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\n\t\tdec\t[StashECX]\n\t\tjnz\t??slpf_loop\n\n\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels, fading and predator\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\n\nSingle_Line_Predator_Fading_Trans:\n\t\tprologue\n\t\tmov\t[StashECX],ecx\n\n??slpft_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\t??slpft_transparent\n\t\tmov\tebx,[BFPartialCount]\n\t\tadd\tebx,[BFPartialPred]\n\t\ttest\tbh,bh\n\t\tjnz\t??slpft_get_pred\n\n\t\tmov\t[BFPartialCount],ebx\n\t\tjmp\t??slpft_do_fading\n\n??slpft_get_pred:\n\t\txor\tbh,bh\n\t\tmov\teax,[BFPredOffset]\n\t\tmov\t[BFPartialCount],ebx\n\t\tand\t[BYTE BFPredOffset],2\n\t\tmov\teax,[DWORD BFPredTable+eax]\n\t\tand\t[BYTE BFPredOffset],PRED_MASK\n\n\t\tand\teax,0ffffh\n\t\tmov\tal,[eax+edi]\n\n??slpft_do_fading:\n\t\tand\teax,255\n\t\tmov\tebx,[FadingTable]\n\t\tmov\tecx,[FadingNum]\n\n??slpft_fade_loop:\n\t\tmov\tal,[eax+ebx]\n\t\tdec\tecx\n\t\tjnz\t??slpft_fade_loop\n\n\t\tmov\t[edi],al\n??slpft_transparent:\n\t\tinc\tedi\n\n\t\tdec\t[StashECX]\n\t\tjnz\t??slpft_loop\n\n\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single line with predator, ghosting and fading\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\n\nSingle_Line_Predator_Ghost_Fading:\n\n\t\tprologue\n\t\tmov\t[StashECX],ecx\n\n??slpgf_loop:\tmov\tal,[esi]\n\t\tmov\tebx,[BFPartialCount]\n\t\tinc\tesi\n\t\tadd\tebx,[BFPartialPred]\n\t\ttest\tbh , bh\n\t\tjnz\t??slpgf_get_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[BFPartialCount],ebx\n\t\tjmp\t??slpgf_check_ghost\n\n??slpgf_get_pred:\n\t\txor\tbh,bh\n\t\tmov\teax,[BFPredOffset]\n\t\tmov\t[BFPartialCount],ebx\n\t\tadd\t[BYTE BFPredOffset],2\n\t\tmov\teax,[DWORD BFPredTable+eax]\n\t\tand\t[BYTE BFPredOffset],PRED_MASK\n\t\tand\teax,0ffffh\n\n\t\tmov\tal,[edi+eax]\n\n??slpgf_check_ghost:\n\t\tand\teax,255\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[ebx+eax]\n\t\tcmp\tbh,0ffh\n\t\tje\t??slpgf_do_fading\n\n\t\tand\tebx , 0FF00h\n\n\t\tmov\tal,[edi]\n\t\tadd\tebx,[Translucent]\n\n\t\tmov\tal,[ebx+eax]\n\n??slpgf_do_fading:\n\t\txor\teax,eax\n\t\tmov\tebx,[FadingTable]\n\t\tmov\tecx,[FadingNum]\n\n??slpgf_fade_loop:\n\t\tmov\tal,[ebx+eax]\n\t\tdec\tecx\n\t\tjnz\t??slpgf_fade_loop\n\n??slpgf_store_pixel:\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\n\t\tdec\t[StashECX]\n\t\tjnz\t??slpgf_loop\n\n\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels, predator, ghosting and fading\n;\n; 11/29/95 10:21AM - ST\n;\n\t\talign\t32\n\nSingle_Line_Predator_Ghost_Fading_Trans:\n\n\t\tprologue\n\t\tmov\t[StashECX],ecx\n\n??slpgft_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\t??slpgft_transparent\n\n\t\tmov\tebx,[BFPartialCount]\n\t\tadd\tebx,[BFPartialPred]\n\t\ttest\tbh , bh\n\t\tjnz\t??slpgft_get_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[BFPartialCount],ebx\n\t\tjmp\t??slpgft_check_ghost\n\n??slpgft_get_pred:\n\t\txor\tbh,bh\n\t\tmov\teax,[BFPredOffset]\n\t\tmov\t[BFPartialCount],ebx\n\t\tadd\t[BYTE BFPredOffset],2\n\t\tmov\teax,[DWORD BFPredTable+eax]\n\t\tand\t[BYTE BFPredOffset],PRED_MASK\n\t\tand\teax,0ffffh\n\n\t\tmov\tal,[edi+eax]\n\n??slpgft_check_ghost:\n\t\tand\teax,255\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[ebx+eax]\n\t\tcmp\tbh,0ffh\n\t\tje\t??slpgft_do_fading\n\n\t\tand\tebx , 0FF00h\n\n\t\tmov\tal,[edi]\n\t\tadd\tebx,[Translucent]\n\n\t\tmov\tal,[ebx+eax]\n\n??slpgft_do_fading:\n\t\txor\teax,eax\n\t\tmov\tebx,[FadingTable]\n\t\tmov\tecx,[FadingNum]\n\n??slpgft_fade_loop:\n\t\tmov\tal,[ebx+eax]\n\t\tdec\tecx\n\t\tjnz\t??slpgft_fade_loop\n\n??slpgft_store_pixel:\n\t\tmov\t[edi],al\n??slpgft_transparent:\n\t\tinc\tedi\n\n\t\tdec\t[StashECX]\n\t\tjnz\t??slpgft_loop\n\n\t\tepilogue\n\t\tnext_line\n\n\n\n\n\t\tends\t\t;end of strict alignment segment\n\n\t       \tcodeseg\n\n\n\nglobal\tBF_Trans:near\n\nBF_Trans:\n\n\tprologue\n; calc the code location to skip to 10 bytes per REPT below!!!!\n\tmov\tecx , eax\n\tand\tecx , 01fh\n\tlea\tecx , [ ecx + ecx * 4 ]\t\t; quick multiply by 5\n\tneg\tecx\n\tshr\teax , 5\n\tlea\tecx , [ ??trans_reference + ecx * 2 ] ; next multiply by 2\n\tmov\t[ loop_cnt ] , eax\n\tmov\t[ jmp_loc ] , ecx\n\n??trans_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n; the following code should NOT be changed without changing the calculation\n; above!!!!!!\n\n??trans_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\t\tmov\tbl , [ esi ]\n\t\tinc\tesi\n\t\ttest\tbl , bl\n\t\tjz\ttrans_pixel\n\n\t\tmov\t[ edi ] , bl\n\n\ttrans_pixel:\n\t\tinc\tedi\n\tENDM\n\n??trans_reference:\n\tdec\tecx\n\tjge\t??trans_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??trans_loop\n\tepilogue\n\n\tret\n\n;********************************************************************\n;********************************************************************\n\nglobal\tBF_Ghost:near\nBF_Ghost:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??ghost_reference - ??ghost_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??ghost_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??ghost_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??ghost_line:\n\n\tREPT\t32\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tstore_pixel\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??ghost_reference:\n\tdec\tecx\n\tjge\t??ghost_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??ghost_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nglobal\tBF_Ghost_Trans:near\nBF_Ghost_Trans:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??ghost_t_reference - ??ghost_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??ghost_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??ghost_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??ghost_t_line:\n\n\tREPT\t32\n\tlocal\ttransp_pixel\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttransp_pixel\n\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tstore_pixel\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttransp_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??ghost_t_reference:\n\tdec\tecx\n\tjge\t??ghost_t_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??ghost_t_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nglobal\tBF_Fading:near\nBF_Fading:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??fading_reference - ??fading_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??fading_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??fading_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\tjmp\t[ jmp_loc ]\n\n??fading_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??fading_line:\n\n\tREPT\t32\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??fading_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??fading_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??fading_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nglobal\tBF_Fading_Trans:near\nBF_Fading_Trans:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??fading_t_reference - ??fading_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??fading_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??fading_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\tjmp\t[ jmp_loc ]\n\n??fading_t_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??fading_t_line:\n\n\tREPT\t32\n\tlocal\ttransp_pixel\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttransp_pixel\n\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\t\tmov\t[ edi ] , al\n\n\ttransp_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??fading_t_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??fading_t_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??fading_t_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nglobal\tBF_Ghost_Fading:near\nBF_Ghost_Fading:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??ghost_f_reference - ??ghost_f_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??ghost_f_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??ghost_f_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??ghost_f_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??ghost_f_line:\n\n\tREPT\t32\n\tlocal\tstore_pixel\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a lucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tdo_fading\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the lation table\n\t\t\t\t\t\t\t; ((_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (_color * 256) of the lation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n; DRD\t\tjmp\tstore_pixel\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??ghost_f_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??ghost_f_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??ghost_f_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nglobal\tBF_Ghost_Fading_Trans:near\nBF_Ghost_Fading_Trans:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??ghost_f_t_reference - ??ghost_f_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??ghost_f_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??ghost_f_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??ghost_f_t_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??ghost_f_t_line:\n\n\tREPT\t32\n\tlocal\ttransp_pixel\n\tlocal\tstore_pixel\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttransp_pixel\n\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tdo_fading\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n; DRD\t\tjmp\tstore_pixel\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttransp_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??ghost_f_t_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??ghost_f_t_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??ghost_f_t_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nglobal\tBF_Predator:near\nBF_Predator:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_reference - ??predator_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??predator_line:\n\n\tREPT\t32\n\tlocal\tget_pred\n\tlocal\tskip_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tskip_pixel\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n;\t\txor\tbh , bh\n;\t\tmov\teax , [ BFPredValue ]\t; pick up a color offset a pseudo-\n;\t\t\t\t\t\t;  random amount from the current\n;\t\tmov\t[ BFPartialCount ] , ebx\n;\t\tmov\tal , [ edi + eax ]\t;  viewport address\n\n\t\tmov\t[ edi ] , al\n\n\tskip_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??predator_reference:\n\tdec\tecx\n\tjge\t??predator_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nglobal\tBF_Predator_Trans:near\nBF_Predator_Trans:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_t_reference - ??predator_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??predator_t_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\tlocal\tget_pred\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttrans_pixel\n\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tstore_pixel\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttrans_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??predator_t_reference:\n\tdec\tecx\n\tjge\t??predator_t_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_t_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nglobal\tBF_Predator_Ghost:near\nBF_Predator_Ghost:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_g_reference - ??predator_g_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_g_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_g_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??predator_g_line:\n\n\tREPT\t32\n\tlocal\tget_pred\n\tlocal\tcheck_ghost\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tinc\tesi\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tcheck_ghost\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tcheck_ghost:\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tstore_pixel\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??predator_g_reference:\n\tdec\tecx\n\tjge\t??predator_g_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_g_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nglobal\tBF_Predator_Ghost_Trans:near\nBF_Predator_Ghost_Trans:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_g_t_reference - ??predator_g_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_g_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_g_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??predator_g_t_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\tlocal\tget_pred\n\tlocal\tcheck_ghost\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttrans_pixel\n\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tcheck_ghost\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tcheck_ghost:\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tstore_pixel\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttrans_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??predator_g_t_reference:\n\tdec\tecx\n\tjge\t??predator_g_t_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_g_t_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nglobal\tBF_Predator_Fading:near\nBF_Predator_Fading:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_f_reference - ??predator_f_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_f_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_f_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??predator_f_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??predator_f_line:\n\n\tREPT\t32\n\tlocal\tget_pred\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tinc\tesi\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tdo_fading\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??predator_f_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??predator_f_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_f_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nglobal\tBF_Predator_Fading_Trans:near\nBF_Predator_Fading_Trans:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_f_t_reference - ??predator_f_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_f_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_f_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??predator_f_t_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??predator_f_t_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\tlocal\tget_pred\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttrans_pixel\n\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tdo_fading\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\t\tmov\t[ edi ] , al\n\n\ttrans_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??predator_f_t_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??predator_f_t_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_f_t_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nglobal\tBF_Predator_Ghost_Fading:near\nBF_Predator_Ghost_Fading:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_g_f_reference - ??predator_g_f_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_g_f_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_g_f_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??predator_g_f_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??predator_g_f_line:\n\n\tREPT\t32\n\tlocal\tget_pred\n\tlocal\tcheck_ghost\n\tlocal\tstore_pixel\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tinc\tesi\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tcheck_ghost\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tcheck_ghost:\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tdo_fading\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n; DRD\t\tjmp\tstore_pixel\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??predator_g_f_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??predator_g_f_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_g_f_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nglobal\tBF_Predator_Ghost_Fading_Trans:near\nBF_Predator_Ghost_Fading_Trans:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_g_f_t_reference - ??predator_g_f_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_g_f_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_g_f_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??predator_g_f_t_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??predator_g_f_t_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\tlocal\tget_pred\n\tlocal\tcheck_ghost\n\tlocal\tstore_pixel\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttrans_pixel\n\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tcheck_ghost\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tcheck_ghost:\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tdo_fading\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n; DRD\t\tjmp\tstore_pixel\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttrans_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??predator_g_f_t_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??predator_g_f_t_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_g_f_t_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nNot_Supported:\n\tret\n\n\tENDP\tBuffer_Frame_To_Page\nEND\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : KEYFBUFF.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 16, 1992                            *\n;*                                                                         *\n;*                  Last Update : October 2, 1994   [JLB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   BUFFER_FRAME_TO_LOGICPAGE --                                          *\n;*   Normal_Draw -- Function that writes a normal pixel line               *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\tIDEAL\n\tP386\nIDEAL_MODE\tEQU\t1\n\tINCLUDE \"wwlib.i\"\n\n\t;-------------------------------------------------------------------\n\t; Extern all the library variables that this module requires\n\t;-------------------------------------------------------------------\n\n\tEXTRN\tC MaskPage:WORD\n\tEXTRN\tC BackGroundPage:WORD\n\n\t;-------------------------------------------------------------------\n\t; Define all the equates that this module requires\n\t;-------------------------------------------------------------------\n\nWIN_X\t\tEQU\t0\t\t; offset for the x coordinate\nWIN_Y\t\tEQU\t2\t\t; offset for the y coordinate\nWIN_WIDTH\tEQU\t4\t\t; offset for the window width\nWIN_HEIGHT\tEQU\t6\t\t; offset for the window height\nBYTESPERROW\tEQU\t320\t\t; number of bytes per row\n\nFLAG_NORMAL\t\tEQU\t0\t\t; flag for normal draw\n\nFLAG_GHOST\t\tEQU\t1\t\t; This flag enables the ghost\nFLAG_PRIORITY_TRANS\tEQU\t2\t\t; flag for priority and transparent\nFLAG_TRANS\t\tEQU\t4\t\t; flag for transparent draw\nFLAG_PRIORITY\t\tEQU\t8\t\t; flag for priority draw\n\n\t\t\t\t\t\t; fx on the above flags\n\nFLAG_MASK\t\tEQU\t15\t\t; used to and of uneeded bits\n\nSHAPE_NORMAL\t\tEQU\t0000h\t\t; Standard shape.\n;SHAPE_HORZ_REV\t\tEQU\t0001h\t\t; Flipped horizontally.\n;SHAPE_VERT_REV\t\tEQU\t0002h\t\t; Flipped vertically.\n;SHAPE_SCALING\t\tEQU\t0004h\t\t; Scaled (WORD scale_x, WORD scale_y)\n\nSHAPE_WIN_REL\t\tEQU\t0010h\t\t; Coordinates are window relative instead of absolute.\nSHAPE_CENTER\t\tEQU\t0020h\t\t; Coordinates are based on shape's center point.\nSHAPE_TRANS\t\tEQU\t0040h\t\t; has transparency\n\n\n;SHAPE_FADING\t\tEQU\t0100h\t\t; Fading effect active (VOID * fading_table, WORD fading_num).\n;SHAPE_PREDATOR\t\tEQU\t0200h\t\t; Transparent warping effect.\n;SHAPE_COMPACT\t\tEQU\t0400h\t\t; Never use this bit.\nSHAPE_PRIORITY\t\tEQU\t0800h\t\t; Use priority system when drawing.\n\nSHAPE_GHOST\t\tEQU\t1000h\t\t; Transluscent table process.\n;SHAPE_SHADOW\t\tEQU\t2000h\t\t; ????\n;SHAPE_PARTIAL \t\tEQU\t4000h\t\t; ????\n;SHAPE_COLOR\t\tEQU\t8000h\t\t; Remap the shape's colors (VOID * color_table).\n\n\n; MBL MOD 12.1.92\n\nCLEAR_NON_WALK_BIT_AND_SCALE_BITS\tEQU\t7\t; Makes it one AND per pixel in Priority_Trans display\nCLEAR_NON_WALK_BIT    \tEQU\t7fh\t; and with 0111-1111 to clear non-walkable high bit\nCLEAR_SCALE_BITS  \tEQU\t87h\t; and with 1000-0111 to clear scaling id bits\nNON_WALKABLE_BIT  \tEQU\t80h\t; and with 1000-0000 to clear all but non-walkable bit\n\n; END MBL MOD\n\n\n\tCODESEG\n\n\t;   1 = GHOST (all odd entrys are prefixed with Ghost_)\n\t;   2 = BLAAAH\n\t;   4 = Trans (prfx)\n\t;   8 = Prior (prfx)\n\n\n;---------------------------------------------------------------------------\n; Define the table of different line draw types\n;---------------------------------------------------------------------------\n\nLineTable\tDW\tWSA_Normal_Draw\t\t\t;0\n\t\tDW\tGhost_Normal_Draw\t\t;1\n\t\tDW\t0\t\t\t\t;2\n\t\tDW\t0\t\t\t\t;3\n\n\t\tDW\tTransparent_Draw\t\t;4\n\t\tDW\tGhost_Transparent_Draw\t\t;5\n\t\tDW\t0\t\t\t\t;6\n\t\tDW\t0\t\t\t\t;7\n\n\t\tDW\tPriority_Draw\t\t\t;8\n\t\tDW\tGhost_Priority_Draw\t\t;9\n\t\tDW\t0\t\t\t\t;10\n\t\tDW\t0\t\t\t\t;11\n\n\t\tDW\tPriority_Transparent_Draw\t;12\n\t\tDW\tGhost_Priority_Transparent_Draw\t;13\n\t\tDW\t0\t\t\t\t;14\n\t\tDW\t0\t\t\t\t;15\n\n\n\n;***************************************************************************\n;* BUFFER_FRAME_TO_LOGICPAGE --                                            *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/16/1992 PWG : Created.                                             *\n;*=========================================================================*\n\tPUBLIC\tC Buffer_Frame_To_LogicPage\n\tPROC\tC Buffer_Frame_To_LogicPage FAR USES ax bx ecx dx ds esi es edi\n\n\t;-------------------------------------------------------------------\n\t; Define the arguements that our program takes.\n\t;-------------------------------------------------------------------\n\n\tARG\tx_pixel:WORD\t\t; x pixel position to draw at\n\tARG\ty_pixel:WORD\t\t; y pixel position to draw at\n\tARG\tpixel_w:WORD\t\t; pixel width of draw region\n\tARG\tpixel_h:WORD\t\t; pixel height of draw region\n\tARG\twin:WORD\t\t; window to clip around\n\tARG\tflags:WORD\t\t; flags that this routine will take\n\tARG\tbuffer:DWORD\t\t; pointer to the buffer with data\n\tARG\targs:WORD\n\n\t;-------------------------------------------------------------------\n\t; Define the local variables that our program uses\n\t;-------------------------------------------------------------------\n\n\tLOCAL\tIsTranslucent:DWORD\t; ptr to the is_translucent table\n\tLOCAL\tTranslucent:DWORD\t; ptr to the actual translucent table\n\n\tLOCAL\twin_x1:WORD\t\t; clip window left x pixel position\n\tLOCAL\twin_x2:WORD\t\t; clip window right x pixel position\n\tLOCAL\twin_y1:WORD\t\t; clip window top y pixel position\n\tLOCAL\twin_y2:WORD\t\t; clip window bottom y pixel position\n\tLOCAL\tclipleft:WORD\t\t; number of pixels to clip on left\n\tLOCAL\tclipright:WORD\t\t; number of pixels to clip on right\n\tLOCAL\tnextline:WORD\t\t; offset to the next line\n\tLOCAL\tputmiddle:WORD \t\t; routine to call to put the middle\n\tLOCAL\tmaskpage:WORD\t\t; location of the depth masks\n\tLOCAL   background:WORD\t\t; location of the background data\n\tLOCAL   jflags:WORD\t\t; location of the background data\n\n\tLOCAL\tpriority:BYTE\t\t; the priority level of the back\n\n\tpush\tfs\n\n\txor\tecx,ecx\n\n\t;--------------------------------------------------------------------\n\t; Check to see if we have supplied any GHOST tables.\n\t;--------------------------------------------------------------------\n\tpush\tdi\n\n\tmov\tdi,6\n\tmov\t[jflags],0\n\n??ghost:\n\ttest\t[flags],SHAPE_GHOST\t; are we ghosting this shape\n\tjz\tshort ??no_ghost\t; if not then skip and do more\n\n\tor\t[jflags],FLAG_GHOST\n\n\tles\tax,[DWORD PTR buffer + di]\n\n\t; get the \"are we really translucent?\" table\n\tmov\t[WORD PTR IsTranslucent],ax\n\tmov\t[WORD PTR IsTranslucent + 2],es\n\tadd\tax,0100h\t\t; add to offset for tables\n\n\t; get the \"ok we are translucent!!\" table\n\tmov\t[WORD PTR Translucent],ax\n\tmov\t[WORD PTR Translucent + 2],es\n\n\tadd\tdi,4\n\n??no_ghost:\n\n\tpop\tdi\n\n\t;-------------------------------------------------------------------\n\t; See if we need to center the frame\n\t;-------------------------------------------------------------------\n\ttest\t[flags],SHAPE_CENTER\t; does this need to be centered?\n\tje\tshort ??no_centering\t; if not the skip over this stuff\n\n\tmov\tax,[pixel_w]\n\tmov\tbx,[pixel_h]\n\tsar\tax,1\n\tsar\tbx,1\n\tsub\t[x_pixel],ax\n\tsub\t[y_pixel],bx\n\n??no_centering:\n\tmov\tax,[flags]\n\tand\tax,SHAPE_PRIORITY+SHAPE_TRANS\n\tcmp\tax,SHAPE_PRIORITY+SHAPE_TRANS\n\tjne\tshort ??test_trans\n\n\tor\t[jflags],FLAG_PRIORITY_TRANS\n\tjmp\tshort ??priority\n\n\t;-------------------------------------------------------------------\n\t; Get the trans information if we need to get it\n\t;-------------------------------------------------------------------\n??test_trans:\n\ttest\t[flags],SHAPE_TRANS\t; does this draw use transparencies?\n\tje\tshort ??test_priority\t; if not the skip over this junk\n\n\tor\t[jflags],FLAG_TRANS\n\n??test_priority:\n\t;-------------------------------------------------------------------\n\t; Get the priority information if we need to get it\n\t;-------------------------------------------------------------------\n\ttest\t[flags],SHAPE_PRIORITY\t; does this draw use priorities?\n\tje\tshort ??no_priority\t; if not the skip over this junk\n\n\tor\t[jflags],FLAG_PRIORITY\n\n??priority:\n\tmov\tax,[BackGroundPage]\t; get the background page from ds\n\tmov\t[background],ax\t\t;    and store it on the stack\n\tmov\tax,[MaskPage]\t\t; get the mask page from ds\n\tmov\t[maskpage],ax\t\t;    and store it on the stack\n\tmov\tax,[WORD PTR buffer + 4]; get the priority level from args\n\tmov\t[priority],al\t\t;    and store it in a local\n\n\t;-------------------------------------------------------------------\n\t; Get the draw routine that we are going to draw with\n\t;-------------------------------------------------------------------\n??no_priority:\n;\tmov\tbx,[flags]\t\t; load in the current flags byte\n;\tand\tbx,FLAG_MASK\t\t; prevent lockup on bad value\n\tmov\tbx,[jflags]\t\t; load in the jump table flags\n\tshl\tbx,1\n\tmov\tax,[WORD PTR LineTable + bx]\t; get the offset of the skip table\n\tmov\t[putmiddle],ax\t\t; store off the new offset\n\n\t;-------------------------------------------------------------------\n\t; Get a pointer to the logic page to where we will draw our buffer\n\t;-------------------------------------------------------------------\n\tpush\t[LogicPage]\t\t; push the current logic page\n\tcall\tFAR PTR Get_Page\t; get the physical page address\n\tadd\tsp,2\t\t\t; pull the parameter from the stack\n\tmov\tes,dx\t\t\t; store the address in the dest\n\n\t;--------------------------------------------------------------------\n\t; Point DI to the beginning of the window that we need to look at.\n\t;   that way we can access all of the info through di.\n\t;--------------------------------------------------------------------\n\tmov\tsi,OFFSET WindowList\t; get the offset of the window list\n\tmov\tcl,4\t\t\t; shift 3 times = multiply by 16\n\tmov\tax,[win]\t\t; get the window number we are using\n\tshl\tax,cl\t\t\t; each window is 8 words long\n\tadd\tsi,ax\t\t\t; add that into the offset of window\n\n\t;--------------------------------------------------------------------\n\t; Place all the clipping values on the stack so our function will\n\t; be truly re-entrant and will not need to shadow these values.\n\t;--------------------------------------------------------------------\n\tmov\tcl,3\t\t\t; to convert x to pixel mult by 8\n\tmov\tax,[si + WIN_X]\t\t; get the left clip position\n\tshl\tax,cl\t\t\t; convert to a pixel x position\n\tmov\t[win_x1],ax\t\t; store the left edge of window\n\tmov\t[win_x2],ax\n\n\tmov\tax,[si + WIN_WIDTH]\t; get the width of the window\n\tshl\tax,cl\t\t\t; convert to a pixel width\n\tadd\t[win_x2],ax\t\t; add to get the right window edge\n\n\tmov\tax,[si + WIN_Y]\t\t; get the win y coordinate to clip\n\tmov\t[win_y1],ax\t\t; and save it onto the stack\n\n\tadd\tax,[si + WIN_HEIGHT]\t; calculate the bottom win y coord\n\tmov\t[win_y2],ax\t\t; and save it onto the stack\n\n\ttest\t[flags],SHAPE_WIN_REL\t; is this window relative?\n\tje\tshort ??get_buffer\t; if not the skip over\n\n\tmov\tax,[win_x1]\t\t; get left edge of window\n\tadd\t[x_pixel],ax\t\t; add to x pixel position\n\tmov\tax,[win_y1]\t\t; get top edge of window\n\tadd\t[y_pixel],ax\t\t; add to y pixel position\n\n\t;--------------------------------------------------------------------\n\t; Get a pointer to the source buffer so we can handle the clipping\n\t;--------------------------------------------------------------------\n??get_buffer:\n\tlds\tsi,[buffer]\t\t; get a pointer to the buffer\n\n\t;--------------------------------------------------------------------\n\t; Check the top of our shape and clip any lines that are necessary\n\t;--------------------------------------------------------------------\n\tmov\tax,[y_pixel]\t\t; get the y_pixel draw position\n\tsub\tax,[win_y1]\t\t; subtract out the window y top\n\tjns\tshort ??check_bottom\t\t;   skip if y below window top\n\tadd\tax,[pixel_h]\t\t; add in the height of the region\n\tjg\tshort ??clip_top\t\t; if positive then clip top lines\n\n??jump_exit:\n\tjmp\t??exit\t\t\t; otherwise completely clipped\n\n??clip_top:\n\txchg\t[pixel_h],ax\n\tsub\tax,[pixel_h]\n\tadd\t[y_pixel],ax\n\tmul\t[pixel_w]\t\t; convert to number of bytes to skip\n\tadd\tsi,ax\t\t\t; skip past the necessary bytes\n\n\t;--------------------------------------------------------------------\n\t; Check the bottom of our shape and clip it if necessary\n\t;--------------------------------------------------------------------\n??check_bottom:\n\tmov\tax,[win_y2]\t\t; get the bottom y of the window\n\tsub\tax,[y_pixel]\t\t; subtract of the y to draw at\n\tjs\t??jump_exit\t\t; if its signed then nothing to draw\n\tjz\t??jump_exit\t\t; if its zero then nothing to draw\n\n\tcmp\tax,[pixel_h]\t\t; if more room to draw then height\n\tjae\tshort ??clip_x_left\t\t;   then go check the left clip\n\tmov\t[pixel_h],ax\t\t; clip all but amount that will fit\n\n??clip_x_left:\n\tmov\t[clipleft],0\t\t; clear clip on left of region\n\tmov\tax,[x_pixel]\t\t; get the pixel x of draw region\n\tsub\tax,[win_x1]\t\t; pull out the window coordinate\n\tjns\tshort ??clip_x_right\n\tneg\tax\t\t\t; negate to get amnt to skip in buf\n\tmov\t[clipleft],ax\t\t; store it in the left clip info\n\tadd\t[x_pixel],ax\t\t; move to the edge of the window\n\tsub\t[pixel_w],ax\t\t; pull it out of the pixel width\n\n??clip_x_right:\n\tmov\t[clipright],0\t\t; clear clip on right of region\n\tmov\tax,[win_x2]\t\t; get the window x of clip region\n\tsub\tax,[x_pixel]\t\t; subtract the draw edge of region\n\tjs\t??jump_exit\t\t; if its negative then get out\n\tjz\t??jump_exit\t\t; if its zero then get out\n\n\tcmp\tax,[pixel_w]\t\t; is space available larger than w\n\tjae\tshort ??draw_prep\t\t;   if so then go get drawing\n\n\n\txchg\t[pixel_w],ax\t\t; amt to draw in pixel_w (wid in ax)\n\tsub\tax,[pixel_w]\t\t; pull out the amount to draw\n\tmov\t[clipright],ax\t\t; this is the amount to clip on right\n\n??draw_prep:\n\tpush\tsi\t\t\t; save off source pos in buffer\n\tpush\tds\t\t\t;   both offset and segment\n\tmov\tax,@data\n\tmov\tds,ax\n\tmov\tbx,[y_pixel]\n\tshl\tbx,1\t\t\t; shift left by 1 for word table look\n\tlds\tsi,[YTable]\t; get the address of the ytable\n\tmov\tdi,[ds:si+bx]\t\t; look up the multiplied value\n\tpop\tds\t\t\t; restore source pos in buffer\n\tpop\tsi\t\t\t;   both offset and segment\n\n\tadd\tdi,[x_pixel]\t\t; add in the x pixel position\n\tmov\t[nextline],di\t\t; save it off in the next line\n\n \t;--------------------------------------------------------------------\n\t; Now determine the type of the shape and process it in the proper\n\t;   way.\n\t;--------------------------------------------------------------------\n\tmov\tdx,[pixel_h]\n\n\t; Check to see if the WSA is the screen width and there is no\n\t; clipping. In this case, then a special single call to the\n\t; line processing routine is possible.\n\tmov\tax,[clipleft]\n\tadd\tax,[clipright]\n\tjne\tshort ??top_of_loop\n\tcmp\t[pixel_w],BYTESPERROW\n\tjne\tshort ??top_of_loop\n\n\t;------------------------------------\n\t; The width of the WSA is the screen width, so just process as\n\t; one large WSA line.\n\tmov\tax,BYTESPERROW\n\timul\tdx\n\tmov\tcx,ax\n\tcall\t[putmiddle]\n\tjmp\tshort ??exit\n\n\t;------------------------------------\n\t; Process line by line.\n??top_of_loop:\n\tadd\tsi,[clipleft]\t\t; skip whats necessary on left edge\n\tmov\tcx,[pixel_w]\t\t; get the width we need to draw\n\n\t; Copy the source to the destination as appropriate. This routine can\n\t; trash AX, BX, CX, and DI. It must properly modify SI to point one byte past\n\t; the end of the data.\n\tcall\t[putmiddle]\n\n\tadd\tsi,[clipright]\t\t; skip past the left clip\n\tadd\t[nextline],BYTESPERROW\n\tmov\tdi,[nextline]\n\n\tdec\tdx\n\tjnz\t??top_of_loop\n\n??exit:\n\tpop\tfs\n\tret\n\tENDP\n\n\n;***************************************************************************\n;* NORMAL_DRAW -- Function that writes a normal pixel line                 *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tNOLANGUAGE WSA_Normal_Draw NEAR\n\n IF 1\n \t; This version is marginally faster than the later version.\n \tmov\tax,cx\n\tshr\tcx,2\n\trep movsd\n\tand\tax,011b\n\tmov\tcx,ax\n\tshr\tcx,1\n\trep movsw\n\tadc\tcx,cx\n\trep movsb\n\tret\n\n ELSE\n\n\tshr\tcx,1\t\t\t; convert to words (odd pix in carry)\n\trep\tmovsw\t\t\t; write out the needed words\n\tadc\tcx,0\t\t\t; add the carry into cx\n\trep\tmovsb\t\t\t; write out the odd byte if any\n\tret\n ENDIF\n\n\tENDP\n\n\n;***************************************************************************\n;* TRANSPARENT_DRAW -- Function that writes a transparent pixel line       *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   10/02/1994 JLB : Optimized for 250% speed improvement.                *\n;*=========================================================================*\n\tPROC\tNOLANGUAGE Transparent_Draw NEAR\n\n IF 1\n\t; Preserve DX since it is used as a scratch register.\n\tpush\tdx\n\n??loop:\n\t; Swap DS:SI and ES:DI back in preparation for the REP SCASB\n\t; instruction.\n\txchg\tdi,si\n\tmov\tdx,es\n\tmov\tax,ds\n\tmov\tds,dx\n\tmov\tes,ax\n\n\t; Remember the bytes remaining in order to calculate the position\n\t; of the scan when it stops.\n\tmov\tbx,cx\n\n\t; Scan looking for a non-zero value in the source buffer.\n\txor\tal,al\n\trepe scasb\n\n\t; When the loop ends, if the EQ flag is set then the scanning is\n\t; complete. Jump to the end of the routine in order to fixup the\n\t; pointers.\n\tje\tshort ??fini\n\n\t; Advance the destination pointer by the amount necessary to match\n\t; the source movement. DS:SI points to where data should be written.\n\tadd\tsi,bx\n\tinc\tcx\t\t; SCASB leaves CX one too low, fix it.\n\tdec\tdi\t\t; SCASB leaves DI one byte too far, fix it.\n\tsub\tsi,cx\n\n\t; Scan for the duration of non-zero pixels. This yields a count which\n\t; is used to copy the source data to the destination. Preserve DI.\n\tmov\tdx,di\n\tmov\tbx,cx\n\trepne scasb\n\tmov\tdi,dx\n\n\t; Set BX to equal the number of bytes to copy from source to dest.\n\tinc\tcx\t\t; SCASB leaves CX one too low, fix it.\n\tsub\tbx,cx\n\n\t; Move the data from ES:DI to DS:SI for BX bytes.\n\txchg\tcx,bx\t\t; Make CX=bytes to move, BX=bytes remaining.\n\n\t; Swap DS:SI and ES:DI in preparation for the REP MOV instruction.\n\txchg\tdi,si\n\tmov\tdx,es\n\tmov\tax,ds\n\tmov\tds,dx\n\tmov\tes,ax\n\n\t; Move the data from source to dest. First try to move double\n\t; words. Then copy the remainder bytes (if any). Putting jumps in\n\t; this section doesn't result in any savings -- oh well.\n\tmov\tax,cx\n\tshr\tcx,2\n\trep movsd\n\tand\tax,0011b\n\tmov\tcx,ax\n\tshr\tcx,1\n\trep movsw\n\tadc\tcx,cx\n\trep movsb\n\n\t; Restore CX with the remaining bytes to process.\n\tmov\tcx,bx\n\n\t; If there are more bytes to process, then loop back.\n\tor\tcx,cx\n\tjne\tshort ??loop\n\n??fini:\n\t; Swap ES:DI and DS:SI back to original orientation.\n\tmov\tax,ds\n\tmov\tbx,es\n\tmov\tes,ax\n\tmov\tds,bx\n\txchg\tdi,si\n\n\t; Restore DX and return.\n\tpop\tdx\n\tret\n\n ELSE\n\n??loop_top:\n\tlodsb\n\tor\tal,al\n\tjz\tshort ??skip\n\n\tmov\t[es:di],al\t\t; store the pixel to the screen\n??skip:\n\tinc\tdi\n\tloop\t??loop_top\n\tret\n\n ENDIF\n\n\tENDP\n\n\n;***************************************************************************\n;* PRIORITY_DRAW -- Function that writes a pixels if they are in front of  *\n;*\t\t    the given plate.\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   12/01/1992 MBL : Updated to work with latest mask data encoding.      *\n;*   17/01/1993 MCC : Updated for 386, and optimized\t\t\t   *\n;*=========================================================================*\n\n\tPROC\tNOLANGUAGE Priority_Draw NEAR\n\n\tmov\tfs,[background]\t\t; get the SEG of the background page\n\tmov\tgs,[maskpage]\t\t; get the SEG of the mask info\n\tmov\tah,[priority]\t\t; keep a copy of priority varible for faster cmp\n\n\n??loop_top:\n\tlodsb\t\t\t\t; get the pixel to draw on the screen\n\n\t\t\t\t\t; get the mask byte for our pixel\n\tmov\tbl,[ds:di]\n\t\t\t\t\t; get rid of non-walkable bit and\n\t\t\t\t\t; get rid of scaling id bits\n\tand\tbl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS\n\n\tcmp\tah,bl\t\t\t; are we more toward the front?\n\tjge\tshort ??out_pixel\t; if so then write the pixel\n\n\tmov\tal,[fs:di]\t\t; get the pixel to write\n??out_pixel:\n\tstosb\t\t\t\t; write the pixel and inc the DI\n\tloop\t??loop_top\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* PRIORITY_TRANSPARENT_DRAW -- Function that writes a pixels if they are  *\n;*\t\t    in front of the given plate.  It also deals with\t   *\n;*\t\t    transparent pixels.\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   12/01/1992 MBL : Updated to work with latest mask data encoding.      *\n;*   17/01/1993 MCC : Updated for 386, and optimized\t\t\t   *\n;*=========================================================================*\n\n\tPROC\tNOLANGUAGE Priority_Transparent_Draw NEAR\n\n\tmov\tfs,[background]\t\t; get the SEG of the background page\n\tmov\tgs,[maskpage]\t\t; get the SEG of the mask info\n\tmov\tah,[priority]\t\t; keep a copy of priority varible for faster cmp\n\n??loop_top:\n\tlodsb\t\t\t\t; get the pixel on the screen\n\tor\tal,al\t\t\t; check to see if al is transparent\n\tje\tshort ??write_back\t; if it is go write background\n\n\tmov\tbl,[gs:di]\t\t; get the mask byte for our pixel\n\n\t\t\t\t\t; get rid of non-walkable bit and\n\t\t\t\t\t; get rid of scaling id bits\n\tand\tbl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS\n\n\tcmp\tah,bl\t\t\t; are we more toward the front?\n\tjge\tshort ??out_pixel\t; if so then write the pixel\n\n??write_back:\n\tmov\tal,[fs:di]\t\t; get the pixel to write\n??out_pixel:\n\tstosb\t\t\t\t; write the pixel\n\tloop\t??loop_top\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GHOST_NORMAL_DRAW -- Function that writes a normal pixel line           *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   05/27/1993 MCC : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tNOLANGUAGE Ghost_Normal_Draw NEAR\n\n??loop_top:\n\tlodsb\n\n;---\n\t; Ok, find out if the colour is a Translucent colour\n\tpush\tax\n\tpush \tds\n\n\tlds\tbx,[IsTranslucent]\n\tmov\tah,al\t\t\t; preserve real pixel\n\txlat\t\t\t\t; get new al (transluecent pixel\n\txchg\tah,al\t\t\t; get real pixel back into AL just in case\n\tcmp\tah,255\n\tje\tshort ??normal_pixel\t\t; is it a translucent ?\n\t\t\t\t\t; if we get passed here value in\n\t\t\t\t\t; AH should be 0-15\n\n\t; yes, it is a translucent colour so goto our translucent translation\n\t; table and set up a ptr to the correct table\n\n\tmov\tal,[es:di]\n\t\t\t\t\t; mov pixel at destination to al and we have\n\t\t\t\t\t; the index to the translation table\n\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tlds\tbx,[Translucent]\t; get the ptr to it!\n\tadd\tbh,ah\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\t\t\t\t; XLAT only uses AL so no need to clear AH\n\txlat\t\t\t\t; get new pixel in AL\n\n??normal_pixel:\n\tpop\tds\n\tpop\tbx\n\tmov\tah,bh\n;---\n\n\tmov\t[es:di],al\t\t; store the pixel to the screen\n\n??skip:\n\tinc\tdi\n\tloop\t??loop_top\n\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GHOST_TRANSPARENT_DRAW -- Function that writes a transparent pixel line *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   05/27/1993 MCC : Created.                                             *\n;*=========================================================================*\n\tPROC\tNOLANGUAGE Ghost_Transparent_Draw NEAR\n\n??loop_top:\n\tlodsb\n\tor\tal,al\n\tjz\tshort ??skip\n\n;---\n\t; Ok, find out if the colour is a Translucent colour\n\tpush\tax\n\tpush \tds\n\n\tlds\tbx,[IsTranslucent]\n\tmov\tah,al\t\t\t; preserve real pixel\n\txlat\t\t\t\t; get new al (transluecent pixel\n\txchg\tah,al\t\t\t; get real pixel back into AL just in case\n\tcmp\tah,255\n\tje\tshort ??normal_pixel\t\t; is it a translucent ?\n\t\t\t\t\t; if we get passed here value in\n\t\t\t\t\t; AH should be 0-15\n\n\t; yes, it is a translucent colour so goto our translucent translation\n\t; table and set up a ptr to the correct table\n\n\tmov\tal,[es:di]\n\t\t\t\t\t; mov pixel at destination to al and we have\n\t\t\t\t\t; the index to the translation table\n\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tlds\tbx,[Translucent]\t; get the ptr to it!\n\tadd\tbh,ah\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\t\t\t\t; XLAT only uses AL so no need to clear AH\n\txlat\t\t\t\t; get new pixel in AL\n\n??normal_pixel:\n\tpop\tds\n\tpop\tbx\n\tmov\tah,bh\n;---\n\n\tmov\t[es:di],al\t\t; store the pixel to the screen\n\n??skip:\n\tinc\tdi\n\tloop\t??loop_top\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GHOST_PRIORITY_DRAW -- Function that writes a pixels if they are in fron*\n;*\t\t    the given plate.\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   12/01/1992 MBL : Updated to work with latest mask data encoding.      *\n;*   05/27/1993 MCC : Updated to use the new Ghosting fx\t\t   *\n;*   17/01/1993 MCC : Updated for 386, and optimized\t\t\t   *\n;*=========================================================================*\n\tPROC\tNOLANGUAGE Ghost_Priority_Draw NEAR\n\n\tmov\tfs,[background]\t\t; get the SEG of the background page\n\tmov\tgs,[maskpage]\t\t; get the SEG of the mask info\n\tmov\tah,[priority]\t\t; keep a copy of priority varible for faster cmp\n\n\n??loop_top:\n\tlodsb\t\t\t\t; get the pixel to draw on the screen\n\t\t\t\t\t; get the mask byte for our pixel\n\tmov\tbl,[ds:di]\n\t\t\t\t\t; get rid of non-walkable bit and\n\t\t\t\t\t; get rid of scaling id bits\n\tand\tbl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS\n\tcmp\tah,bl\t\t\t; are we more toward the front?\n\tjge\tshort ??out_pixel\t; if so then write the pixel\n\n\tmov\tal,[fs:di]\t\t; get the pixel to write\n??out_pixel:\n\tstosb\t\t\t\t; write the pixel and inc the DI\n\tloop\t??loop_top\n\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GHOST_PRIORITY_TRANSPARENT_DRAW -- Function that writes a pixels if they*\n;*\t\t    in front of the given plate.  It also deals with\t   *\n;*\t\t    transparent pixels.\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   12/01/1992 MBL : Updated to work with latest mask data encoding.      *\n;*   05/27/1993 MCC : Updated to use the new Ghosting fx\t\t   *\n;*   17/01/1993 MCC : Updated for 386, and optimized\t\t\t   *\n;*=========================================================================*\n\tPROC\tNOLANGUAGE Ghost_Priority_Transparent_Draw NEAR\n\n\tmov\tfs,[background]\t\t; get the SEG of the background page\n\tmov\tgs,[maskpage]\t\t; get the SEG of the mask info\n\tmov\tah,[priority]\t\t; keep a copy of priority varible for faster cmp\n\n??loop_top:\n\tlodsb\t\t\t\t; get the pixel on the screen\n\tor\tal,al\t\t\t; check to see if al is transparent\n\tje\tshort ??write_back\t;   if it is go write background\n\tmov\tbl,[gs:di]\t\t; get the mask byte for our pixel\n\t\t\t\t\t; get rid of non-walkable bit and\n\t\t\t\t\t; get rid of scaling id bits\n\tand\tbl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS\n\tcmp\tah,bl\t\t\t; are we more toward the front?\n\tjge\tshort ??out_pixel\t; if so then write the pixel\n??write_back:\n\tmov\tal,[fs:di]\t\t; get the pixel to write\n??out_pixel:\n\tstosb\t\t\t\t; write the pixel\n\tloop\t??loop_top\n\n\tret\n\n\tENDP\n\n\tEND\n"
  },
  {
    "path": "CODE/2KEYFRAM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/2KEYFRAM.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : KEYFRAME.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/25/95                                                     *\n *                                                                                             *\n *                  Last Update : June 25, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Get_Build_Frame_Count -- Fetches the number of frames in data block.                      *\n *   Get_Build_Frame_Width -- Fetches the width of the shape image.                            *\n *   Get_Build_Frame_Height -- Fetches the height of the shape image.                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"function.h\"\n\n#define SUBFRAMEOFFS\t\t\t7\t// 3 1/2 frame offsets loaded (2 offsets/frame)\n\n\n#define\tApply_Delta(buffer, delta)\t\tApply_XOR_Delta((char*)(buffer), (char*)(delta))\n\ntypedef struct {\n\tunsigned short frames;\n\tunsigned short x;\n\tunsigned short y;\n\tunsigned short width;\n\tunsigned short height;\n\tunsigned short largest_frame_size;\n\tshort\t\t\t\tflags;\n} KeyFrameHeaderType;\n\n#define\tINITIAL_BIG_SHAPE_BUFFER_SIZE\t8000000\n#define\tTHEATER_BIG_SHAPE_BUFFER_SIZE 4000000\n#define\tUNCOMPRESS_MAGIC_NUMBER\t\t\t56789\n\nunsigned\tBigShapeBufferLength = INITIAL_BIG_SHAPE_BUFFER_SIZE;\nunsigned\tTheaterShapeBufferLength = THEATER_BIG_SHAPE_BUFFER_SIZE;\nextern \"C\"{\n\tchar\t\t*BigShapeBufferStart = NULL;\n\tchar\t\t*TheaterShapeBufferStart = NULL;\n\tBOOL\t\tUseBigShapeBuffer = FALSE;\n\tbool\t\tIsTheaterShape = false;\n}\n#ifdef FIXIT_SCORE_CRASH\n/*\n** Global required to fix the score screen crash bug by allowing disabling of uncompressed shapes.\n*/\nbool\t\tOriginalUseBigShapeBuffer = false;\n#endif\t//FIXIT\nchar\t\t*BigShapeBufferPtr = NULL;\nint\t\t\tTotalBigShapes=0;\nBOOL\t\tReallocShapeBufferFlag = FALSE;\n\nchar\t\t*TheaterShapeBufferPtr = NULL;\nint\t\t\tTotalTheaterShapes = 0;\n\n\n#define MAX_SLOTS 1500\n#define THEATER_SLOT_START 1000\n\nchar\t**KeyFrameSlots [MAX_SLOTS];\nint \tTotalSlotsUsed=0;\nint\t\tTheaterSlotsUsed = THEATER_SLOT_START;\n\n\n\ntypedef struct tShapeHeaderType{\n\tunsigned draw_flags;\n\tchar\t\t*shape_data;\n\tint\t\tshape_buffer;\t\t//1 if shape is in theater buffer\n} ShapeHeaderType;\n\nstatic int Length;\n\nvoid *Get_Shape_Header_Data(void *ptr)\n{\n\tif (UseBigShapeBuffer) {\n\n\t\tShapeHeaderType *header = (ShapeHeaderType*) ptr;\n\t\treturn ((void*)  (header->shape_data + (long)(header->shape_buffer ? TheaterShapeBufferStart : BigShapeBufferStart) ) );\n\n\t} else {\n\t\treturn (ptr);\n\t}\n}\n\nint Get_Last_Frame_Length(void)\n{\n\treturn(Length);\n}\n\n\nvoid Reset_Theater_Shapes (void)\n{\n\t/*\n\t** Delete any previously allocated slots\n\t*/\n\tfor (int i=THEATER_SLOT_START ; i<TheaterSlotsUsed ; i++) {\n\t\tdelete [] KeyFrameSlots [i];\n\t}\n\n\tTheaterShapeBufferPtr = TheaterShapeBufferStart;\n\tTotalTheaterShapes = 0;\n\tTheaterSlotsUsed = THEATER_SLOT_START;\n}\n\n\nvoid Reallocate_Big_Shape_Buffer(void)\n{\n\tif (ReallocShapeBufferFlag) {\n\t\tBigShapeBufferLength += 2000000;\t\t\t\t\t\t\t//Extra 2 Mb of uncompressed shape space\n\t\tBigShapeBufferPtr -= (unsigned)BigShapeBufferStart;\n\t\tMemory_Error = NULL;\n\t\tBigShapeBufferStart = (char*)Resize_Alloc(BigShapeBufferStart, BigShapeBufferLength);\n\t\tMemory_Error = &Memory_Error_Handler;\n\t\t/*\n\t\t** If we have run out of memory then disable the uncompressed shapes\n\t\t** It may still be possible to continue with compressed shapes\n\t\t*/\n\t\tif (!BigShapeBufferStart) {\n\t\t\tUseBigShapeBuffer = false;\n\t\t\treturn;\n\t\t}\n\t\tBigShapeBufferPtr += (unsigned)BigShapeBufferStart;\n\t\tReallocShapeBufferFlag = FALSE;\n\t}\n}\n\n\n#ifdef FIXIT_SCORE_CRASH\n/***********************************************************************************************\n * Disable_Uncompressed_Shapes -- Temporarily turns off shape decompression                    *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/19/96 2:37PM ST : Created                                                             *\n *=============================================================================================*/\nvoid Disable_Uncompressed_Shapes (void)\n{\n\tUseBigShapeBuffer = false;\n}\n\n\n\n/***********************************************************************************************\n * Enable_Uncompressed_Shapes -- Restores state of shape decompression before it was disabled  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/19/96 2:37PM ST : Created                                                             *\n *=============================================================================================*/\nvoid Enable_Uncompressed_Shapes (void)\n{\n\tUseBigShapeBuffer = OriginalUseBigShapeBuffer;\n}\n#endif\t//FIXIT\n\nvoid Check_Use_Compressed_Shapes (void)\n{\n\tMEMORYSTATUS\tmem_info;\n\n\tmem_info.dwLength=sizeof(mem_info);\n\tGlobalMemoryStatus(&mem_info);\n\n\tUseBigShapeBuffer = (mem_info.dwTotalPhys > 16*1024*1024) ? TRUE : FALSE;\n#ifdef FIXIT_SCORE_CRASH\n\t/*\n\t** Keep track of our original decision about whether to use cached shapes.\n\t** This is needed for the score screen crash fix.\n\t*/\n\tOriginalUseBigShapeBuffer = UseBigShapeBuffer;\n#endif\t//FIXIT\n}\n\n\n\n\n\nunsigned long Build_Frame(void const *dataptr, unsigned short framenumber, void *buffptr)\n{\n#ifdef FIXIT_SCORE_CRASH\n\tchar *ptr;\n\tunsigned long offcurr, offdiff;\n#else\n\tchar *ptr, *lockptr;//, *uncomp_ptr;\n\tunsigned long offcurr, off16, offdiff;\n#endif\n\tunsigned long offset[SUBFRAMEOFFS];\n\tKeyFrameHeaderType *keyfr;\n\tunsigned short buffsize, currframe, subframe;\n\tunsigned long length = 0;\n\tchar frameflags;\n\tunsigned long return_value;\n\tchar *temp_shape_ptr;\n\n\t//\n\t// valid pointer??\n\t//\n\tLength = 0;\n\tif ( !dataptr || !buffptr ) {\n\t\treturn(0);\n\t}\n\n\t//\n\t// look at header then check that frame to build is not greater\n\t// than total frames\n\t//\n\tkeyfr = (KeyFrameHeaderType *) dataptr;\n\n\tif ( framenumber >= keyfr->frames ) {\n\t\treturn(0);\n\t}\n\n\n\tif (UseBigShapeBuffer) {\n\t\t/*\n\t\t** If we havnt yet allocated memory for uncompressed shapes then do so now.\n\t\t**\n\t\t*/\n\t\tif (!BigShapeBufferStart) {\n\t\t\tBigShapeBufferStart = (char*)Alloc(BigShapeBufferLength, MEM_NORMAL);\n\t\t\tBigShapeBufferPtr = BigShapeBufferStart;\n\n\t\t\t/*\n\t\t\t** Allocate memory for theater specific uncompressed shapes\n\t\t\t*/\n\t\t\tTheaterShapeBufferStart = (char*) Alloc (TheaterShapeBufferLength, MEM_NORMAL);\n\t\t\tTheaterShapeBufferPtr = TheaterShapeBufferStart;\n\t\t}\n\n\t\t/*\n\t\t** If we are running out of memory (<10k left) for uncompressed shapes\n\t\t** then allocate some more.\n\t\t*/\n\t\tif (( (unsigned)BigShapeBufferStart + BigShapeBufferLength) - (unsigned)BigShapeBufferPtr < 128000) {\n\t\t\tReallocShapeBufferFlag = TRUE;\n\t\t}\n\n\t\t/*\n\t\t** If this animation was not previously uncompressed then\n\t\t** allocate memory to keep the pointers to the uncompressed data\n\t\t** for these animation frames\n\t\t*/\n\t\tif (keyfr->x != UNCOMPRESS_MAGIC_NUMBER) {\n\t\t\tkeyfr->x = UNCOMPRESS_MAGIC_NUMBER;\n\t\t\tif (IsTheaterShape) {\n\t\t\t\tkeyfr->y = TheaterSlotsUsed;\n\t\t\t\tTheaterSlotsUsed++;\n\t\t\t} else {\n\t\t\t\tkeyfr->y = TotalSlotsUsed;\n\t\t\t\tTotalSlotsUsed++;\n\t\t\t}\n\t\t\t/*\n\t\t\t** Allocate and clear the memory for the shape info\n\t\t\t*/\n\t\t\tKeyFrameSlots[keyfr->y]= new char *[keyfr->frames];\n\t\t\tmemset (KeyFrameSlots[keyfr->y] , 0 , keyfr->frames*4);\n\t\t}\n\n\t\t/*\n\t\t** If this frame was previously uncompressed then just return\n\t\t** a pointer to the raw data\n\t\t*/\n\t\tif (*(KeyFrameSlots[keyfr->y]+framenumber)) {\n\t\t\tif (IsTheaterShape) {\n\t\t\t\treturn ((unsigned long)TheaterShapeBufferStart + (unsigned long)*(KeyFrameSlots[keyfr->y]+framenumber));\n\t\t\t} else {\n\t\t\t\treturn ((unsigned long)BigShapeBufferStart + (unsigned long)*(KeyFrameSlots[keyfr->y]+framenumber));\n\t\t\t}\n\t\t}\n\t}\n\n\t// calc buff size\n\tbuffsize = keyfr->width * keyfr->height;\n\n\t// get offset into data\n\tptr = (char *)Add_Long_To_Pointer( dataptr, (((unsigned long)framenumber << 3) + sizeof(KeyFrameHeaderType)) );\n\tMem_Copy( ptr, &offset[0], 12L );\n\tframeflags = (char)(offset[0] >> 24);\n\n\n\tif ( (frameflags & KF_KEYFRAME) ) {\n\n\t\tptr = (char *)Add_Long_To_Pointer( dataptr, (offset[0] & 0x00FFFFFFL) );\n\n\t\tif (keyfr->flags & 1 ) {\n\t\t\tptr = (char *)Add_Long_To_Pointer( ptr, 768L );\n\t\t}\n\t\tlength = LCW_Uncompress( ptr, buffptr, buffsize );\n\t} else {\t// key delta or delta\n\n\t\tif ( (frameflags & KF_DELTA) ) {\n\t\t\tcurrframe = (unsigned short)offset[1];\n\n\t\t\tptr = (char *)Add_Long_To_Pointer( dataptr, (((unsigned long)currframe << 3) + sizeof(KeyFrameHeaderType)) );\n\t\t\tMem_Copy( ptr, &offset[0], (long)(SUBFRAMEOFFS * sizeof(unsigned long)) );\n\t\t}\n\n\t\t// key frame\n\t\toffcurr = offset[1] & 0x00FFFFFFL;\n\n\t\t// key delta\n\t\toffdiff = (offset[0] & 0x00FFFFFFL) - offcurr;\n\n\t\tptr = (char *)Add_Long_To_Pointer( dataptr, offcurr );\n\n\t\tif (keyfr->flags & 1 ) {\n\t\t\tptr = (char *)Add_Long_To_Pointer( ptr, 768L );\n\t\t}\n\n#ifndef FIXIT_SCORE_CRASH\n\t\toff16 = (unsigned long)lockptr & 0x00003FFFL;\n#endif\n\n\t\tlength = LCW_Uncompress( ptr, buffptr, buffsize );\n\n\t\tif (length > buffsize) {\n\t\t\treturn(0);\n\t\t}\n\n#ifndef FIXIT_SCORE_CRASH\n\t\tif ( ((offset[2] & 0x00FFFFFFL) - offcurr) >= (0x00010000L - off16) ) {\n\n\t\t\tptr = (char *)Add_Long_To_Pointer( ptr, offdiff );\n\t\t\toff16 = (unsigned long)ptr & 0x00003FFFL;\n\n\t\t\toffcurr += offdiff;\n\t\t\toffdiff = 0;\n\t\t}\n#endif\n\n\t\tlength = buffsize;\n\t\tApply_Delta(buffptr, Add_Long_To_Pointer(ptr, offdiff));\n\n\t\tif ( (frameflags & KF_DELTA) ) {\n\t\t\t// adjust to delta after the keydelta\n\n\t\t\tcurrframe++;\n\t\t\tsubframe = 2;\n\n\t\t\twhile (currframe <= framenumber) {\n\t\t\t\toffdiff = (offset[subframe] & 0x00FFFFFFL) - offcurr;\n\n#ifndef FIXIT_SCORE_CRASH\n\t\t\t\tif ( ((offset[subframe+2] & 0x00FFFFFFL) - offcurr) >= (0x00010000L - off16) ) {\n\n\t\t\t\t\tptr = (char *)Add_Long_To_Pointer( ptr, offdiff );\n\t\t\t\t\toff16 = (unsigned long)lockptr & 0x00003FFFL;\n\n\t\t\t\t\toffcurr += offdiff;\n\t\t\t\t\toffdiff = 0;\n\t\t\t\t}\n#endif\n\n\t\t\t\tlength = buffsize;\n\t\t\t\tApply_Delta(buffptr, Add_Long_To_Pointer(ptr, offdiff));\n\n\t\t\t\tcurrframe++;\n\t\t\t\tsubframe += 2;\n\n\t\t\t\tif ( subframe >= (SUBFRAMEOFFS - 1) &&\n\t\t\t\t\tcurrframe <= framenumber ) {\n\t\t\t\t\tMem_Copy( Add_Long_To_Pointer( dataptr,\n\t\t\t\t\t\t\t\t\t(((unsigned long)currframe << 3) +\n\t\t\t\t\t\t\t\t\tsizeof(KeyFrameHeaderType)) ),\n\t\t\t\t\t\t&offset[0], (long)(SUBFRAMEOFFS * sizeof(unsigned long)) );\n\t\t\t\t\tsubframe = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\tif (UseBigShapeBuffer) {\n\t\t/*\n\t\t** Save the uncompressed shape data so we dont have to uncompress it\n\t\t** again next time its drawn.\n\t\t** We keep a space free before the raw shape data so we can add line\n\t\t** header info before the shape is drawn for the first time\n\t\t*/\n\n\t\tif (IsTheaterShape) {\n\t\t\t/*\n\t\t\t** Shape is a theater specific shape\n\t\t\t*/\n\t\t\treturn_value = (unsigned long) TheaterShapeBufferPtr;\n\t\t\ttemp_shape_ptr = TheaterShapeBufferPtr + keyfr->height+sizeof(ShapeHeaderType);\n\t\t\t/*\n\t\t\t** align the actual shape data\n\t\t\t*/\n\t\t\tif (3 & (unsigned)temp_shape_ptr) {\n\t\t\t\ttemp_shape_ptr = (char *) ((unsigned)(temp_shape_ptr + 3) & 0xfffffffc);\n\t\t\t}\n\n\t\t\tmemcpy (temp_shape_ptr , buffptr , length);\n\t\t\t((ShapeHeaderType *)TheaterShapeBufferPtr)->draw_flags = -1;\t\t\t\t\t\t//Flag that headers need to be generated\n\t\t\t((ShapeHeaderType *)TheaterShapeBufferPtr)->shape_data = temp_shape_ptr - (unsigned)TheaterShapeBufferStart;\t\t//pointer to old raw shape data\n\t\t\t((ShapeHeaderType *)TheaterShapeBufferPtr)->shape_buffer = 1;\t//Theater buffer\n\t\t\t*(KeyFrameSlots[keyfr->y]+framenumber) = TheaterShapeBufferPtr - (unsigned)TheaterShapeBufferStart;\n\t\t\tTheaterShapeBufferPtr = (char*)(length + (unsigned)temp_shape_ptr);\n\t\t\t/*\n\t\t\t** Align the next shape\n\t\t\t*/\n\t\t\tif (3 & (unsigned)TheaterShapeBufferPtr) {\n\t\t\t\tTheaterShapeBufferPtr = (char *)((unsigned)(TheaterShapeBufferPtr + 3) & 0xfffffffc);\n\t\t\t}\n\t\t\tLength = length;\n\t\t\treturn (return_value);\n\n\t\t} else {\n\n\n\t\t\treturn_value=(unsigned long)BigShapeBufferPtr;\n\t\t\ttemp_shape_ptr = BigShapeBufferPtr + keyfr->height+sizeof(ShapeHeaderType);\n\t\t\t/*\n\t\t\t** align the actual shape data\n\t\t\t*/\n\t\t\tif (3 & (unsigned)temp_shape_ptr) {\n\t\t\t\ttemp_shape_ptr = (char *) ((unsigned)(temp_shape_ptr + 3) & 0xfffffffc);\n\t\t\t}\n\t\t\tmemcpy (temp_shape_ptr , buffptr , length);\n\t\t\t((ShapeHeaderType *)BigShapeBufferPtr)->draw_flags = -1;\t\t\t\t\t\t//Flag that headers need to be generated\n\t\t\t((ShapeHeaderType *)BigShapeBufferPtr)->shape_data = temp_shape_ptr - (unsigned)BigShapeBufferStart;\t\t//pointer to old raw shape data\n\t\t\t((ShapeHeaderType *)BigShapeBufferPtr)->shape_buffer = 0;\t//Normal Big Shape Buffer\n\t\t\t*(KeyFrameSlots[keyfr->y]+framenumber) = BigShapeBufferPtr - (unsigned)BigShapeBufferStart;\n\t\t\tBigShapeBufferPtr = (char*)(length + (unsigned)temp_shape_ptr);\n\t\t\t// Align the next shape\n\t\t\tif (3 & (unsigned)BigShapeBufferPtr) {\n\t\t\t\tBigShapeBufferPtr = (char *)((unsigned)(BigShapeBufferPtr + 3) & 0xfffffffc);\n\t\t\t}\n\t\t\tLength = length;\n\t\t\treturn (return_value);\n\t\t}\n\n\t} else {\n\t\treturn ((unsigned long)buffptr);\n\t}\n}\n\n\n/***********************************************************************************************\n * Get_Build_Frame_Count -- Fetches the number of frames in data block.                        *\n *                                                                                             *\n *    Use this routine to determine the number of shapes within the data block.                *\n *                                                                                             *\n * INPUT:   dataptr  -- Pointer to the keyframe shape data block.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the number of shapes in the data block.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Commented.                                                               *\n *=============================================================================================*/\nunsigned short Get_Build_Frame_Count(void const *dataptr)\n{\n\tif (dataptr) {\n\t\treturn(((KeyFrameHeaderType const *)dataptr)->frames);\n\t}\n\treturn(0);\n}\n\n\nunsigned short Get_Build_Frame_X(void const *dataptr)\n{\n\tif (dataptr) {\n\t\treturn(((KeyFrameHeaderType const *)dataptr)->x);\n\t}\n\treturn(0);\n}\n\n\nunsigned short Get_Build_Frame_Y(void const *dataptr)\n{\n\tif (dataptr) {\n\t\treturn(((KeyFrameHeaderType const *)dataptr)->y);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * Get_Build_Frame_Width -- Fetches the width of the shape image.                              *\n *                                                                                             *\n *    Use this routine to fetch the width of the shapes within the keyframe shape data block.  *\n *    All shapes within the block have the same width.                                         *\n *                                                                                             *\n * INPUT:   dataptr  -- Pointer to the keyframe shape data block.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the width of the shapes in the block -- expressed in pixels.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Commented                                                                *\n *=============================================================================================*/\nunsigned short Get_Build_Frame_Width(void const *dataptr)\n{\n\tif (dataptr) {\n\t\treturn(((KeyFrameHeaderType const *)dataptr)->width);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * Get_Build_Frame_Height -- Fetches the height of the shape image.                            *\n *                                                                                             *\n *    Use this routine to fetch the height of the shapes within the keyframe shape data block. *\n *    All shapes within the block have the same height.                                        *\n *                                                                                             *\n * INPUT:   dataptr  -- Pointer to the keyframe shape data block.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the height of the shapes in the block -- expressed in pixels.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Commented                                                                *\n *=============================================================================================*/\nunsigned short Get_Build_Frame_Height(void const *dataptr)\n{\n\tif (dataptr) {\n\t\treturn(((KeyFrameHeaderType const *)dataptr)->height);\n\t}\n\treturn(0);\n}\n\n\nbool Get_Build_Frame_Palette(void const * dataptr, void * palette)\n{\n\tif (dataptr && (((KeyFrameHeaderType const *)dataptr)->flags & 1)) {\n\t\tchar const * ptr = (char const *)Add_Long_To_Pointer( dataptr,\n\t\t\t\t\t\t\t( (( (long)sizeof(unsigned long) << 1) *\n\t\t\t\t\t\t\t\t((KeyFrameHeaderType *) dataptr)->frames ) +\n\t\t\t\t\t\t\t16 + sizeof(KeyFrameHeaderType) ) );\n\n\t\tmemcpy(palette, ptr, 768L);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "CODE/2SUPPORT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header:   F:\\projects\\c&c0\\vcs\\code\\2support.asv   5.0   11 Nov 1996 09:40:36   JOE_BOSTIC  $\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : SUPPORT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : September 23, 1993                       *\n;*                                                                         *\n;*                  Last Update : May 10, 1994   [JLB]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   strtrim -- Remove the trailing white space from a string.             *\n;*   Fat_Put_Pixel -- Draws a fat pixel.                                   *\n;*   Conquer_Build_Fading_Table -- Builds custom shadow/light fading table.*\n;*   Remove_From_List -- Removes a pointer from a list of pointers.        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"gbuffer.inc\"\n\tDISPLAY\t\"Command & Conquer assembly support routines.\"\n\n\tCODESEG\n\n\n;***************************************************************************\n;* Fat_Put_Pixel -- Draws a fat pixel.                                     *\n;*                                                                         *\n;*    Use this routine to draw a \"pixel\" that is bigger than 1 pixel       *\n;*    across.  This routine is faster than drawing a similar small shape   *\n;*    and faster than calling Fill_Rect.                                   *\n;*                                                                         *\n;* INPUT:   x,y       -- Screen coordinates to draw the pixel's upper      *\n;*                       left corner.                                      *\n;*                                                                         *\n;*          color     -- The color to render the pixel in.                 *\n;*                                                                         *\n;*          size      -- The number of pixels width of the big \"pixel\".    *\n;*                                                                         *\n;*          page      -- The pointer to a GraphicBuffer class or something *\n;*                                                                         *\n;* OUTPUT:  none                                                           *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/17/1994 JLB : Created.                                             *\n;*=========================================================================*\n; VOID cdecl Fat_Put_Pixel(long x, long y, long color, long size, void *page)\n\tGLOBAL\tC Fat_Put_Pixel:NEAR\n\tPROC\tFat_Put_Pixel C near\n\tUSES\teax, ebx, ecx, edx, edi, esi\n\n\tARG\tx:DWORD\t\t; X coordinate of upper left pixel corner.\n\tARG\ty:DWORD\t\t; Y coordinate of upper left pixel corner.\n\tARG\tcolor:DWORD\t; Color to use for the \"pixel\".\n\tARG\tsiz:DWORD\t; Size of \"pixel\" to plot (square).\n\tARG\tgpage:DWORD\t; graphic page address to plot onto\n\n\tcmp\t[siz],0\n\tje\tshort ??exit\n\n\t; Set EDI to point to start of logical page memory.\n\t;*===================================================================\n\t; Get the viewport information and put bytes per row in ecx\n\t;*===================================================================\n\tmov\tebx,[gpage]\t\t\t\t; get a pointer to viewport\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get the correct offset\n\n\t; Verify the the Y pixel offset is legal.\n\tmov\teax,[y]\n\tcmp\teax,[(GraphicViewPort ebx).GVPHeight]\t;YPIXEL_MAX\n\tjae\tshort ??exit\n\tmov\tecx,[(GraphicViewPort ebx).GVPWidth]\n\tadd\tecx,[(GraphicViewPort ebx).GVPXAdd]\n\tadd\tecx,[(GraphicViewPort ebx).GVPPitch]\n\tmul\tecx\n\tadd\tedi,eax\n\n\t; Verify the the X pixel offset is legal.\n\n\tmov\tedx,[(GraphicViewPort ebx).GVPWidth]\n\tcmp\tedx,[x]\n\tmov\tedx,ecx\n\tjbe\tshort ??exit\n\tadd\tedi,[x]\n\n\t; Write the pixel to the screen.\n\tmov\tebx,[siz]\t\t; Copy of pixel size.\n\tsub\tedx,ebx\t\t\t; Modulo to reach start of next row.\n\tmov\teax,[color]\n??again:\n\tmov\tecx,ebx\n\trep stosb\n\tadd\tedi,edx\t\t\t; EDI points to start of next row.\n\tdec\t[siz]\n\tjnz\tshort ??again\n\n??exit:\n\tret\n\n\tENDP\tFat_Put_Pixel\n\n\nif 0\n\n;***************************************************************************\n;* strtrim -- Remove the trailing white space from a string.               *\n;*                                                                         *\n;*    Use this routine to remove white space characters from the beginning *\n;*    and end of the string.        The string is modified in place by     *\n;*    this routine.                                                        *\n;*                                                                         *\n;* INPUT:   buffer   -- Pointer to the string to modify.                   *\n;*                                                                         *\n;* OUTPUT:     none                                                        *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/07/1992 JLB : Created.                                             *\n;*=========================================================================*\n; VOID cdecl strtrim(BYTE *buffer);\n\tGLOBAL\tC strtrim :NEAR\n\tPROC\tstrtrim C near\n\tUSES\tax, edi, esi\n\n\tARG\tbuffer:DWORD\t\t; Pointer to string to modify.\n\n\tcmp\t[buffer],0\n\tje\tshort ??fini\n\n\t; Prepare for string scanning by loading pointers.\n\tcld\n\tmov\tesi,[buffer]\n\tmov\tedi,esi\n\n\t; Strip white space from the start of the string.\n??looper:\n\tlodsb\n\tcmp\tal,20h\t\t\t; Space\n\tje\tshort ??looper\n\tcmp\tal,9\t\t\t; TAB\n\tje\tshort ??looper\n\tstosb\n\n\t; Copy the rest of the string.\n??gruntloop:\n\tlodsb\n\tstosb\n\tor\tal,al\n\tjnz\tshort ??gruntloop\n\tdec\tedi\n\t; Strip the white space from the end of the string.\n??looper2:\n\tmov\t[edi],al\n\tdec\tedi\n\tmov\tah,[edi]\n\tcmp\tah,20h\n\tje\tshort ??looper2\n\tcmp\tah,9\n\tje\tshort ??looper2\n\n??fini:\n\tret\n\n\tENDP\tstrtrim\n\n\n;***************************************************************************\n;* Conquer_Build_Fading_Table -- Builds custom shadow/light fading table.  *\n;*                                                                         *\n;*    This routine is used to build a special fading table for C&C.  There *\n;*    are certain colors that get faded to and cannot be faded again.      *\n;*    With this rule, it is possible to draw a shadow multiple times and   *\n;*    not have it get any lighter or darker.                               *\n;*                                                                         *\n;* INPUT:   palette  -- Pointer to the 768 byte IBM palette to build from. *\n;*                                                                         *\n;*          dest     -- Pointer to the 256 byte remap table.               *\n;*                                                                         *\n;*          color    -- Color index of the color to \"fade to\".             *\n;*                                                                         *\n;*          frac     -- The fraction to fade to the specified color        *\n;*                                                                         *\n;* OUTPUT:  Returns with pointer to the remap table.                       *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/07/1992 JLB : Created.                                             *\n;*=========================================================================*/\n;VOID * cdecl Conquer_Build_Fading_Table(VOID *palette, VOID *dest, long color, long frac);\n\tGLOBAL\tC Conquer_Build_Fading_Table : NEAR\n\tPROC\tConquer_Build_Fading_Table C near\n\tUSES\tebx, ecx, edi, esi\n\n\tARG\tpalette:DWORD\n\tARG\tdest:DWORD\n\tARG\tcolor:DWORD\n\tARG\tfrac:DWORD\n\n\tLOCAL\tmatchvalue:DWORD\t; Last recorded match value.\n\tLOCAL\ttargetred:BYTE\t\t; Target gun red.\n\tLOCAL\ttargetgreen:BYTE\t; Target gun green.\n\tLOCAL\ttargetblue:BYTE\t\t; Target gun blue.\n\tLOCAL\tidealred:BYTE\n\tLOCAL\tidealgreen:BYTE\n\tLOCAL\tidealblue:BYTE\n\tLOCAL\tmatchcolor:BYTE\t\t; Tentative match color.\n\nALLOWED_COUNT\tEQU\t16\nALLOWED_START\tEQU\t256-ALLOWED_COUNT\n\n\tcld\n\n\t; If the source palette is NULL, then just return with current fading table pointer.\n\tcmp\t[palette],0\n\tje\t??fini1\n\tcmp\t[dest],0\n\tje\t??fini1\n\n\t; Fractions above 255 become 255.\n\tmov\teax,[frac]\n\tcmp\teax,0100h\n\tjb\tshort ??ok\n\tmov\t[frac],0FFh\n??ok:\n\n\t; Record the target gun values.\n\tmov\tesi,[palette]\n\tmov\tebx,[color]\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tlodsb\n\tmov\t[targetred],al\n\tlodsb\n\tmov\t[targetgreen],al\n\tlodsb\n\tmov\t[targetblue],al\n\n\t; Main loop.\n\txor\tebx,ebx\t\t\t; Remap table index.\n\n\t; Transparent black never gets remapped.\n\tmov\tedi,[dest]\n\tmov\t[edi],bl\n\tinc\tedi\n\n\t; EBX = source palette logical number (1..255).\n\t; EDI = running pointer into dest remap table.\n??mainloop:\n\tinc\tebx\n\tmov\tesi,[palette]\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\n\tmov\tedx,[frac]\n\tshr\tedx,1\n\t; new = orig - ((orig-target) * fraction);\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetred]\t\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\teax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealred],dh\t\t; preserve ideal color gun value.\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetgreen]\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\teax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealgreen],dh\t\t; preserve ideal color gun value.\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetblue]\t\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\teax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealblue],dh\t\t; preserve ideal color gun value.\n\n\t; Sweep through a limited set of existing colors to find the closest\n\t; matching color.\n\n\tmov\teax,[color]\n\tmov\t[matchcolor],al\t\t; Default color (self).\n\tmov\t[matchvalue],-1\t\t; Ridiculous match value init.\n\tmov\tecx,ALLOWED_COUNT\n\n\tmov\tesi,[palette]\t\t; Pointer to original palette.\n\tadd\tesi,(ALLOWED_START)*3\n\n\t; BH = color index.\n\tmov\tbh,ALLOWED_START\n??innerloop:\n\n\txor\tedx,edx\t\t\t; Comparison value starts null.\n\n\t; Build the comparison value based on the sum of the differences of the color\n\t; guns squared.\n\tlodsb\n\tsub\tal,[idealred]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\n\tlodsb\n\tsub\tal,[idealgreen]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\n\tlodsb\n\tsub\tal,[idealblue]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\tjz\tshort ??perfect\t\t; If perfect match found then quit early.\n\n\tcmp\tedx,[matchvalue]\n\tjae\tshort ??notclose\n\tmov\t[matchvalue],edx\t; Record new possible color.\n\tmov\t[matchcolor],bh\n??notclose:\n\tinc\tbh\t\t\t; Checking color index.\n\tloop\t??innerloop\n\tmov\tbh,[matchcolor]\n??perfect:\n\tmov\t[matchcolor],bh\n\txor\tbh,bh\t\t\t; Make BX valid main index again.\n\n\t; When the loop exits, we have found the closest match.\n\tmov\tal,[matchcolor]\n\tstosb\n\tcmp\tebx,ALLOWED_START-1\n\tjne\t??mainloop\n\n\t; Fill the remainder of the remap table with values\n\t; that will remap the color to itself.\n\tmov\tecx,ALLOWED_COUNT\n??fillerloop:\n\tinc\tbl\n\tmov\tal,bl\n\tstosb\n\tloop\t??fillerloop\n\n??fini1:\n\tmov\tesi,[dest]\n\tmov\teax,esi\n\tret\n\n\tENDP\tConquer_Build_Fading_Table\n\n\n;***************************************************************************\n;* Remove_From_List -- Removes a pointer from a list of pointers.          *\n;*                                                                         *\n;*    This low level routine is used to remove a pointer from a list of    *\n;*    pointers.  The trailing pointers are moved downward to fill the      *\n;*    hole.                                                                *\n;*                                                                         *\n;* INPUT:   list     -- Pointer to list of pointer.                        *\n;*                                                                         *\n;*          index    -- Pointer to length of pointer list.                 *\n;*                                                                         *\n;*          ptr      -- The pointer value to search for and remove.        *\n;*                                                                         *\n;* OUTPUT:  none                                                           *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/11/1994 JLB : Created.                                             *\n;*   04/22/1994 JLB : Convert to assembly language.                        *\n;*   05/10/1994 JLB : Short pointers now.                                  *\n;*=========================================================================*/\n;VOID cdecl Remove_From_List(VOID **list, long *index, long ptr);\n\tGLOBAL\tC Remove_From_List:NEAR\n\tPROC\tRemove_From_List C near\n\tUSES\tedi, esi, ecx, eax\n\tARG\tlist:DWORD\t\t; Pointer to list.\n\tARG\tindex:DWORD\t\t; Pointer to count.\n\tARG\telement:DWORD\t\t; Element to remove.\n\n\t; Fetch the number of elements in the list.  If there are no\n\t; elements, then just exit quickly.\n\tmov\tedi,[index]\n\tmov\tecx,[edi]\n\tjcxz\tshort ??fini2\n\n\t; Fetch pointer to list.\n\tcmp\t[list],0\n\tje\tshort ??fini2\n\tmov\tedi,[list]\n\n\t; Loop through all elements searching for a match.\n\tmov\teax,[element]\n\trepne scasd\n\tjne\tshort ??fini2\t\t; No match found.\n\n\t; Copy all remaining elements down.  If this is the\n\t; last element in the list then nothing needs to be\n\t; copied -- just decrement the list size.\n\tjcxz\tshort ??nocopy\t\t; No copy necessary.\n\tmov\tesi,edi\n\tsub\tedi,4\n\trep movsd\n\n\t; Reduce the list count by one.\n??nocopy:\n\tmov\tedi,[index]\n\tdec\t[DWORD PTR edi]\n\n??fini2:\n\tret\n\n\tENDP\tRemove_From_List\n\n\n; long cdecl Get_EAX();\n\tGLOBAL\tC Get_EAX :NEAR\n\tPROC\tGet_EAX C near\n\tret\n\n\tENDP\tGet_EAX\nendif\n\n\n\tDATASEG\n\nTabA\tDD 6949350\n\tDD 4913933\n\tDD 3474675\n\tDD 2456966\n\tDD 1737338\n\tDD 1228483\n\tDD 868669\n\tDD 614242\n\tDD 434334\n\tDD 307121\n\tDD 217167\n\tDD 153560\n\tDD 108584\n\tDD 76780\n\tDD 54292\n\tDD 38390\n\tDD 27146\n\tDD 19195\n\tDD 13573\n\tDD 9598\n\tDD 6786\n\tDD 4799\n\tDD 3393\n\tDD 2399\n\tDD 1697\n\tDD 1200\n\tDD 848\n\tDD 600\n\tDD 424\n\tDD 300\n\tDD 212\n\tDD 150\n\tDD 106\n\nTabB\tDD 154\n\tDD 218\n\tDD 309\n\tDD 437\n\tDD 618\n\tDD 874\n\tDD 1236\n\tDD 1748\n\tDD 2472\n\tDD 3496\n\tDD 4944\n\tDD 6992\n\tDD 9888\n\tDD 13983\n\tDD 19775\n\tDD 27967\n\tDD 39551\n\tDD 55933\n\tDD 79101\n\tDD 111866\n\tDD 158203\n\tDD 223732\n\tDD 316405\n\tDD 447465\n\tDD 632811\n\tDD 894929\n\tDD 1265621\n\tDD 1789859\n\tDD 2531243\n\tDD 3579718\n\tDD 5062486\n\tDD 7159436\n\tDD 10124971\n\n\tCODESEG\n\n;***********************************************************************************************\n;* Square_Root -- Finds the square root of the fixed pointer parameter.                        *\n;*                                                                                             *\n;* INPUT:   val   -- The fixed point (16:16) value to find the square root of.                 *\n;*                                                                                             *\n;* OUTPUT:  Returns with the square root of the fixed pointer parameter.                       *\n;*                                                                                             *\n;* WARNINGS:   none                                                                            *\n;*                                                                                             *\n;* HISTORY:                                                                                    *\n;*   10/04/1995 JLB : Adapted.                                                                 *\n;*=============================================================================================*/\n;unsigned Square_Root(unsigned val);\n\tGLOBAL\tC Square_Root :NEAR\n\tPROC\tSquare_Root C near\n\tUSES\tebx,edx\n\n\tbsr ebx,eax\n\tjz ??zero\n\n\tmul [DWORD 4*ebx + OFFSET TabA]\n\tshrd eax,edx,10h\n\tadd eax, [4*ebx + OFFSET TabB]\n??zero:\n\tret\n\n\tENDP\tSquare_Root\n\n;----------------------------------------------------------------------------\n\n\tEND\n\n"
  },
  {
    "path": "CODE/2TXTPRNT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TXTPRNT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 17, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 17, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   MCGA_Print -- Assembly MCGA text print routine                        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n;INCLUDE \"mcgaprim.inc\"\n;INCLUDE \".\\gbuffer.inc\"\n\nGLOBAL C Buffer_Print : NEAR\n\nSTRUC GraphicViewPort\nGVPOffset\t\tDD\t\t?\t\t; offset to virtual viewport\nGVPWidth\t\tDD\t\t?\t\t; width of virtual viewport\nGVPHeight\t\tDD\t\t?\t\t; height of virtual viewport\nGVPXAdd\t\t\tDD\t\t?\t\t; x mod to get to next line\nGVPXPos\t\t\tDD\t\t?\t\t; x pos relative to Graphic Buff\nGVPYPos\t\t\tDD\t\t?\t\t; y pos relative to Graphic Buff\nGVPPitch\t\tdd\t\t?\t\t; modulo of graphic view port\nGVPBuffPtr\t\tDD\t\t?\t\t; ptr to associated Graphic Buff\nENDS\n\n\n\n;*=========================================================================*\n;* Extern the font pointer which is defined by the font class\t\t   *\n;*=========================================================================*\nGLOBAL\tC FontPtr:DWORD\nGLOBAL\tC FontXSpacing:DWORD\nGLOBAL\tC FontYSpacing:DWORD\nGLOBAL\tC ColorXlat:BYTE\n\n;*=========================================================================*\n;* Define the necessary equates for structures and bounds checking\t   *\n;*=========================================================================*\n; The header of the font file looks like this:\n; \tUWORD\tFontLength;\t\t0\n; \tBYTE\tFontCompress;\t\t2\n;\tBYTE\tFontDataBlocks;\t\t3\n;\tUWORD\tInfoBlockOffset;\t4\n;\tUWORD\tOffsetBlockOffset;\t6\n;\tUWORD\tWidthBlockOffset;\t8\n;\tUWORD\tDataBlockOffset;\t10\n;\tUWORD\tHeightOffset;\t\t12\n; For this reason the following equates have these values:\nFONTINFOBLOCK\t\tEQU\t4\nFONTOFFSETBLOCK\t\tEQU\t6\nFONTWIDTHBLOCK\t\tEQU\t8\nFONTDATABLOCK\t\tEQU\t10\nFONTHEIGHTBLOCK\t\tEQU\t12\n\nFONTINFOMAXHEIGHT\tEQU\t4\nFONTINFOMAXWIDTH\tEQU\t5\n\n\nLOCALS ??\n;*=========================================================================*\n;* Define the color xlate table in the data segment\t\t\t   *\n;*=========================================================================*\n\tDATASEG\nColorXlat\tDB\t000H,001H,002H,003H,004H,005H,006H,007H\n\t\tDB\t008H,009H,00AH,00BH,00CH,00DH,00EH,00FH\n\n\t\tDB\t001H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t002H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t003H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t004H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t005H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t006H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t007H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t008H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t009H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00AH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00BH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00CH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00DH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00EH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00FH\n\tCODESEG\n\n\n;***************************************************************************\n;* MCGA_PRINT -- Assembly MCGA text print routine                          *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/17/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_Print C near\n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\tthis:DWORD\n\tARG\tstring:DWORD\n\tARG\tx_pixel:DWORD\n\tARG\ty_pixel:DWORD\n\tARG\tfcolor:DWORD\n\tARG\tbcolor:DWORD\n\n\tLOCAL\tinfoblock:DWORD\t\t; pointer to info block\n\tLOCAL\toffsetblock:DWORD\t; pointer to offset block  (UWORD *)\n\tLOCAL\twidthblock:DWORD\t; pointer to width block   (BYTE  *)\n\tLOCAL\theightblock:DWORD\t; pointer to height block  (UWORD *)\n\n\tLOCAL\tcurline:DWORD\t\t; pointer to first column of current row.\n\tLOCAL\tbufferwidth:DWORD    \t; width of buffer (vpwidth + Xadd)\n\tLOCAL\tnextdraw:DWORD\t\t; bufferwidth - width of cur character.\n\tLOCAL\tstartdraw:DWORD\t\t; where next character will start being drawn.\n\n\tLOCAL\tchar:DWORD\t\t; current character value.\n\n\tLOCAL\tmaxheight:BYTE\t\t; max height of characters in font.\n\tLOCAL\tbottomblank:BYTE\t; amount of empty space below current character.\n\tLOCAL\tcharheight:BYTE\t\t; true height of current character.\n\tLOCAL\tvpwidth:DWORD\n\tLOCAL\tvpheight:DWORD\n\tLOCAL\toriginal_x:DWORD\t; Starting X position.\n\n\n;-------------------------------- Where to draw -----------------------------------------------\n\t; Set up memory location to start drawing.\n\tmov  \tebx,[this]\t\t\t\t; get a pointer to dest\n\tmov\teax,[(GraphicViewPort ebx).GVPHeight]\t; get height of viewport\n\tmov\t[vpheight],eax\t\t\t\t; save off height of viewport\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\t; get width of viewport\n\tmov\t[vpwidth],eax\t\t\t\t; save it off for later\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\t; add in xadd for bytes_per_line\n\tadd\teax,[(GraphicViewPort ebx).GVPPitch]\t; add in pitch of direct draw surface\n\tmov\t[bufferwidth],eax     \t\t\t; save it off for later use.\n\n\tmul\t[y_pixel]\t\t\t\t; multiply rowsize * y_pixel start.\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get start of the viewport\n\tadd\tedi,eax\t\t\t\t\t; add y position to start of vp\n\tmov\t[curline],edi\t\t\t\t; save 0,y address for line feed stuff.\n\tadd\tedi,[x_pixel]\t\t\t\t; add to get starting column in starting row.\n\tmov\t[startdraw],edi\t\t\t\t; save it off.\n\n\tmov\teax,[x_pixel]\n\tmov\t[original_x],eax\n\n;-------------------------------- Create block pointers ----------------------------------------\n\t; Get the pointer to the font.\n\t; We could check for NULL but why waste the time.\n\t; It is up to programmer to make sure it is set.\n\tmov\tesi,[FontPtr]\t\t; Get the font pointer\n\tor\tesi,esi\n\tjz\t??overflow\n\n\t; Set up some pointers to the different memory blocks.\n\t; esi (FontPtr) is added to each to get the true address of each block.\n\t; Many registers are used for P5 optimizations.\n\t; ebx is used for InfoBlock which is then used in the next section.\n\tmovzx\teax,[WORD PTR esi+FONTOFFSETBLOCK]\t; get offset to offset block\n\tmovzx\tebx,[WORD PTR esi+FONTINFOBLOCK]      \t; get offset to info block (must be ebx for height test)\n\tmovzx\tecx,[WORD PTR esi+FONTWIDTHBLOCK] \t; get offset to width block\n\tmovzx\tedx,[WORD PTR esi+FONTHEIGHTBLOCK]\t; get offset to height block\n\n\tadd\teax,esi\t\t\t\t; add offset of FontPtr to offset block\n\tadd\tebx,esi\t\t\t\t; add offset of FontPtr to info block\n\tadd\tecx,esi\t\t\t\t; add offset of FontPtr to width block\n\tadd\tedx,esi\t\t\t\t; add offset of FontPtr to height block\n\n\tmov\t[offsetblock],eax\t\t; save offset to offset block\n\tmov\t[infoblock],ebx\t\t\t; save offset to info block\n\tmov\t[widthblock],ecx   \t\t; save offset to width block\n\tmov\t[heightblock],edx\t\t; save offset to height block\n\n;------------------------------------------ Test for fit ----------------------------------------------\n\t; Test to make sure the height of the max character will fit on this line\n\t; and and not fall out of the viewport.\n\t; remember we set ebx to FONTINFOBLOCK above.\n\tmovzx\teax,[BYTE PTR ebx + FONTINFOMAXHEIGHT]; get the max height in font.\n\tmov\t[maxheight],al\t\t\t; save it for later use.\n\tadd\teax,[y_pixel]\t\t\t; add current y_value.\n\tcmp\teax,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we're outa here.\n\n\tmov\t[y_pixel],eax\t\t\t; save for next line feed. y value for next line.\n\n\tcld\t\t\t\t\t; Make sure we are always forward copying.\n\n;------------------------ Set palette foreground and background ----------------------------------\n\tmov\teax,[fcolor]\t\t; foreground color\n\tmov\t[ColorXlat+1],al\n\tmov\t[ColorXlat+16],al\n\n\tmov\teax,[bcolor]\t\t; background color\n\tmov\t[ColorXlat],al\n\n;-------------------------------------------------------------------------------------------------\n;----------------------------------------- Main loop ----------------------------------------------\n\t; Now we go into the main loop of reading each character in the string and doing\n\t; something with it.\n??next_char:\n\t; while (*string++)\n\txor\teax,eax\t\t\t\t; zero out since we will just load al.\n\tmov\tesi,[string]\t\t\t; get address on next character.\n\tlodsb\t\t\t\t\t; load the character into al.\n\ttest\teax,0FFH\t\t\t; test to see if character is a NULL\n\tjz\t??done\t\t\t\t; character is NULL, get outa here.\n\n\tmov\tedi,[startdraw]\t\t\t; Load the starting address.\n\n\tmov\t[string],esi\t\t\t; save index into string. (incremented by lodsb)\n\n\tcmp\tal,10\t\t\t\t; is the character a line feed?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\n\tcmp\tal,13\t\t\t\t; is the character a line feed?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\n\tmov\t[char],eax\t\t\t; save the character off for later reference.\n\tmov\tebx,eax\t\t\t\t; save it in ebx for later use also.\n\n\tadd\teax,[widthblock]\t\t; figure address of width of character.\n\tmov\tecx,[x_pixel]\t\t\t; get current x_pixel.\n\tmovzx\tedx,[BYTE PTR eax]\t \t; get the width of the character in dl.\n\tadd\tecx,edx\t\t\t\t; add width of char to current x_pixel.\n\tmov\teax,[FontXSpacing]\n\tadd\tecx,eax\n\tadd\t[startdraw],edx\t\t\t; save start draw for next character.\n\tadd\t[startdraw],eax\t\t\t; adjust for the font spacing value\n\n\tcmp\tecx,[vpwidth]\t\t\t; is the pixel greater then the vp width?\n\tjg\t??force_line_feed\t\t; if so, force a line feed.\n\n\tmov\t[x_pixel],ecx\t\t\t; save value of start of next character.\n\tmov\tecx,[bufferwidth]\t\t; get amount to next y same x (one row down)\n\tsub\tecx,edx\t\t\t\t; take the current width off.\n\tmov\t[nextdraw],ecx\t\t\t; save it to add to edi when done with a row.\n\n\t; At this point we got the character. It is now time to find out specifics\n\t; about drawing the darn thing.\n\t; ebx = char so they can be used as an indexes.\n\t; edx = width of character for loop later.\n\n\t; get offset of data for character into esi.\n\tshl\tebx,1\t\t\t\t; mult by 2 to later use as a WORD index.\n\tmov\tesi,[offsetblock]\t\t; get pointer to begining of offset block.\n\tadd\tesi,ebx\t\t\t\t; index into offset block.\n\tmovzx\tesi,[WORD PTR esi]\t\t; get true offset into data block from FontPtr.\n\tadd\tesi,[FontPtr]\t\t\t; Now add FontPtr address to get true address.\n\n\t; Get top and bottom blank sizes and the true height of the character.\n\tadd\tebx,[heightblock]\t\t; point ebx to element in height array.\n\tmov\tal,[ebx+1]\t\t\t; load the data height into dl.\n\tmov\tcl,[ebx]\t\t\t; load the first data row into cl.\n\tmov\tbl,[maxheight]\t\t\t; get the max height of characters.\n\tmov\t[charheight],al\t\t\t; get number of rows with data.\n\tadd\tal,cl\t\t\t\t; add the two heights.\n\tsub\tbl,al\t\t\t\t; subract topblank + char height from maxheight.\n\tmov\t[bottomblank],bl\t\t; save off the number of blank rows on the bottom.\n\t; leaving this section:\n\t; dl is still the width of the character.\n\t; cl is the height of the top blank area.\n\n\tmov\tebx,OFFSET ColorXlat\t\t; setup ebx for xlat commands.\n\tmov\tdh,dl\t\t\t\t; save the width of the character to restore each loop.\n\n\tcmp\tcl,0\t\t\t\t; is there any blank rows on top?\n\tjz\t??draw_char\t\t\t; if not go and draw the real character.\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjnz\t??loop_top\t\t\t; if not go and write the color\n\n;----------------------------------------- skip Top blank area ----------------------------------------\n\t; this case, the top is transparrent, but we need to increase our dest pointer to correct row.\n\tmovzx\teax,cl\t\t\t\t; get number of rows into eax;\n\tmov\tecx,edx\t\t\t\t; save width since edx will be destroyed by mul.\n\tmul\t[bufferwidth]\t\t\t; multiply that by the width of the buffer.\n\tmov\tedx,ecx\t\t\t\t; restore the width\n\tadd\tedi,eax\t\t\t\t; update the pointer.\n\tjmp\tshort ??draw_char\t\t; now go draw the character.\n\n;----------------------------------------- fill Top blank area ----------------------------------------\n\t; edi was set a long time ago.\n\t; al is the translated color\n??loop_top:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_top\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tdec\tcl\t\t\t\t; decrement or row count\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tjz\t??draw_char\t\t\t; we are done here, go draw the character.\n\tjmp\tshort ??loop_top\t\t; go back to top of loop.\n\n\n;----------------------------------------- Draw character ----------------------------------------------\n??draw_char:\n\tmovzx\tecx,[charheight]\t\t; get the height of character to count down rows.\n\ttest\tecx,ecx\t\t\t\t; is there any data? (blank would not have any)\n\tjz\t??next_char\t\t\t; if no data, go on to next character.\n\n??while_data:\n\tlodsb\t\t\t\t\t; get byte value from font data\n\tmov\tah,al\t\t\t\t; save hinibble\n\tand\teax,0F00FH\t       \t\t; mask of low nibble in al hi nibble in ah.\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiplo\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiplo:\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjz\tshort ??nextrow\t\t\t; check if done with width of char\n\n\tmov\tal,ah\t\t\t\t; restore to get\n\t; test the time difference between looking up in a large table when shr al,4 is not done as\n\t; compared to using only a 16 byte table when using the shr al,4\n\t;shr\tal,4\t\t\t\t; shift the hi nibble down to low nibble\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiphi\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiphi:\n\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\tshort ??while_data\t\t; check if done with width of char\n\n??nextrow:\n\tadd\tedi,[nextdraw]\t\t\t; go to next line.\n\tdec\tecx\t\t\t\t; decrement the number of rows to go\n\tmov\tdh,dl\t\t\t\t; restore our column count for row.\n\tjnz\t??while_data\t\t\t; more data for character.\n\n\t; Now it is time to setup for clearing out the bottom of the character.\n\tmovzx\tecx,[bottomblank]\t\t; get amount on bottom that is blank\n\tcmp\tecx,0\t\t\t\t; if there is no blank bottom...\n\tjz\t??next_char\t\t\t; then skip to go to next character\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjz\t??next_char\t\t\t; skip the top black section to let the background through\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\n;----------------------------------------- Blank below character -----------------------------------\n??loop_bottom:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_bottom\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tdec\tcl\t\t\t\t; decrement or row count\n\tjz\t??next_char\t\t\t; we are done here, go to the next character.\n\tjmp\tshort ??loop_bottom\t\t; go back to top of loop.\n\n;----------------------------------- end of next_char (main) loop ------------------------------------\n;-------------------------------------------------------------------------------------------------\n\n\n;----------------------------------- special case line feeds ----------------------------------------\n\n??force_line_feed:\n\t; decrement pointer *string so that it will be back at same character\n\t; when it goes through the loop.\n\tmov\teax,[string]\t\t\t; get string pointer.\n\tdec\teax\t\t\t\t; decrement it to point to previos char\n\tmov\t[string],eax\t\t\t; save it back off.\n\txor\teax,eax\n\t; Now go into the line feed code.....\n\n??line_feed:\n\tmov\tbl,al\n\tmov\tedx,[y_pixel]\t\t\t; get the current y pixel value.\n\tmovzx\tecx,[maxheight]\t\t\t; get max height for later use.\n\tadd\tecx,[FontYSpacing]\n\tadd\tedx,ecx\t\t\t\t; add max height to y_pixel\n\tcmp\tedx,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we are outa here.\n\n\tmov\teax,[bufferwidth]      \t\t; get bytes to next line.\n\tmov\tedi,[curline]\t\t\t; get start of current line.\n\tmul\tecx\t\t\t\t; mult max height * next line.\n\n\tadd\tedi,eax\t\t\t\t; add adjustment to current line.\n\tadd\t[y_pixel],ecx\t\t\t; increment to our next y position.\n;;; DRD\n\tmov\t[curline],edi\t\t\t; save it off for next line_feed.\n\n\t; Move the cursor to either the left edge of the screen\n\t; or the left margin of the print position depending\n\t; on whether <CR> or <LF> was specified. <CR> = left margin\n\t; <LF> = left edge of screen\n\txor\teax,eax\n\tcmp\tbl,10\n\tje\t??lfeed\n\tmov\teax,[original_x]\n??lfeed:\n\tmov\t[x_pixel],eax\t\t\t; zero out x_pixel\n\n\tadd\tedi,eax\n;;; DRD\tmov\t[curline],edi\t\t\t; save it off for next line_feed.\n\tmov\t[startdraw],edi\t\t\t; save it off so we know where to draw next char.w\n\n\tjmp\t??next_char\n\n??overflow:\n\tmov\t[startdraw],0\t\t\t; Indicate that there is no valid next pos.\n??done:\n\tmov\teax,[startdraw]\t\t\t; return this so calling routine\n\tret\t\t\t\t\t; can figure out where to draw next.\n\n\tENDP\tBuffer_Print\n;***************************************************************************\n;* GET_FONT_PALETTE_PTR -- Returns a pointer to the 256 byte font palette  *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tvoid *Get_Font_Palette_Ptr(void);                          *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   08/18/1995 PWG : Created.                                             *\n;*=========================================================================*\n\n\tGLOBAL\tC Get_Font_Palette_Ptr:NEAR\n\tPROC\tGet_Font_Palette_Ptr C near\n\tmov\teax, OFFSET ColorXlat\n\tret\n\tENDP\tGet_Font_Palette_Ptr\n\n\nEND\n"
  },
  {
    "path": "CODE/AADATA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/AADATA.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : AADATA.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 22, 1994                                                *\n *                                                                                             *\n *                  Last Update : July 9, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   AircraftTypeClass::AircraftTypeClass -- Constructor for aircraft objects.                 *\n *   AircraftTypeClass::As_Reference -- Given an aircraft type, find the matching type object. *\n *   AircraftTypeClass::Create_And_Place -- Creates and places aircraft using normal game syste*\n *   AircraftTypeClass::Create_One_Of -- Creates an aircraft object of the appropriate type.   *\n *   AircraftTypeClass::Dimensions -- Fetches the graphic dimensions of the aircraft type.     *\n *   AircraftTypeClass::Display -- Displays a generic version of the aircraft type.            *\n *   AircraftTypeClass::From_Name -- Converts an ASCII name into an aircraft type number.      *\n *   AircraftTypeClass::Init_Heap -- Initialize the aircraft type class heap.                  *\n *   AircraftTypeClass::Max_Pips -- Fetches the maximum number of pips allowed.                *\n *   AircraftTypeClass::Occupy_List -- Returns with occupation list for landed aircraft.       *\n *   AircraftTypeClass::One_Time -- Performs one time initialization of the aircraft type class*\n *   AircraftTypeClass::Overlap_List -- Determines the overlap list for a landed aircraft.     *\n *   AircraftTypeClass::Prep_For_Add -- Prepares the scenario editor for adding an aircraft obj*\n *   AircraftTypeClass::operator delete -- Returns aircraft type to special memory pool.       *\n *   AircraftTypeClass::operator new -- Allocates an aircraft type object from special pool.   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\nvoid const * AircraftTypeClass::LRotorData = NULL;\nvoid const * AircraftTypeClass::RRotorData = NULL;\n\n// Badger bomber\nstatic AircraftTypeClass const BadgerPlane(\n\tAIRCRAFT_BADGER,\t\t// What kind of aircraft is this.\n\tTXT_BADGER,\t\t\t\t// Translated text number for aircraft.\n\t\"BADR\",\t\t\t\t\t// INI name of aircraft.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t// Fixed wing aircraft?\n\t\tfalse,\t\t\t\t// Equipped with a rotor?\n\t\tfalse,\t\t\t\t// Custom rotor sets for each facing?\n\t\tfalse,\t\t\t\t// Can this aircraft land on clear terrain?\n\t\ttrue,\t\t\t\t\t// Is it invisible on radar?\n\t\tfalse,\t\t\t\t// Can the player select it so as to give it orders?\n\t\ttrue,\t\t\t\t\t// Can it be assigned as a target for attack.\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\tSTRUCT_NONE,\t\t\t// Preferred landing building.\n\t0xFF,\t\t\t\t\t\t// Landing speed\n\t16,\t\t\t\t\t\t// Number of rotation stages.\n\tMISSION_HUNT\t\t\t// Default mission for aircraft.\n);\n\n// Photo recon plane.\nstatic AircraftTypeClass const U2Plane(\n\tAIRCRAFT_U2,\t\t\t// What kind of aircraft is this.\n\tTXT_U2,\t\t\t\t\t// Translated text number for aircraft.\n\t\"U2\",\t\t\t\t\t\t// INI name of aircraft.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t// Fixed wing aircraft?\n\t\tfalse,\t\t\t\t// Equipped with a rotor?\n\t\tfalse,\t\t\t\t// Custom rotor sets for each facing?\n\t\tfalse,\t\t\t\t// Can this aircraft land on clear terrain?\n\t\ttrue,\t\t\t\t\t// Is it invisible on radar?\n\t\tfalse,\t\t\t\t// Can the player select it so as to give it orders?\n\t\ttrue,\t\t\t\t\t// Can it be assigned as a target for attack.\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\tSTRUCT_NONE,\t\t\t// Preferred landing building.\n\t0xFF,\t\t\t\t\t\t// Landing speed\n\t16,\t\t\t\t\t\t// Number of rotation stages.\n\tMISSION_HUNT\t\t\t// Default mission for aircraft.\n);\n\n// Mig attack aircraft.\nstatic AircraftTypeClass const MigPlane(\n\tAIRCRAFT_MIG,\t\t\t// What kind of aircraft is this.\n\tTXT_MIG,\t\t\t\t\t// Translated text number for aircraft.\n\t\"MIG\",\t\t\t\t\t// INI name of aircraft.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0020,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0020,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t// Fixed wing aircraft?\n\t\tfalse,\t\t\t\t// Equipped with a rotor?\n\t\tfalse,\t\t\t\t// Custom rotor sets for each facing?\n\t\tfalse,\t\t\t\t// Can this aircraft land on clear terrain?\n\t\ttrue,\t\t\t\t\t// Is it invisible on radar?\n\t\ttrue,\t\t\t\t\t// Can the player select it so as to give it orders?\n\t\ttrue,\t\t\t\t\t// Can it be assigned as a target for attack.\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\tSTRUCT_AIRSTRIP,\t\t// Preferred landing building.\n\t0xC0,\t\t\t\t\t\t// Landing speed\n\t16,\t\t\t\t\t\t// Number of rotation stages.\n\tMISSION_HUNT\t\t\t// Default mission for aircraft.\n);\n\n// Yak attack aircraft.\nstatic AircraftTypeClass const YakPlane(\n\tAIRCRAFT_YAK,\t\t\t// What kind of aircraft is this.\n\tTXT_YAK,\t\t\t\t\t// Translated text number for aircraft.\n\t\"YAK\",\t\t\t\t\t// INI name of aircraft.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0020,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0020,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t// Fixed wing aircraft?\n\t\tfalse,\t\t\t\t// Equipped with a rotor?\n\t\tfalse,\t\t\t\t// Custom rotor sets for each facing?\n\t\tfalse,\t\t\t\t// Can this aircraft land on clear terrain?\n\t\ttrue,\t\t\t\t\t// Is it invisible on radar?\n\t\ttrue,\t\t\t\t\t// Can the player select it so as to give it orders?\n\t\ttrue,\t\t\t\t\t// Can it be assigned as a target for attack.\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\tSTRUCT_AIRSTRIP,\t\t// Preferred landing building.\n\t0xFF,\t\t\t\t\t\t// Landing speed\n\t16,\t\t\t\t\t\t// Number of rotation stages.\n\tMISSION_HUNT\t\t\t// Default mission for aircraft.\n);\n\n// Transport helicopter.\nstatic AircraftTypeClass const TransportHeli(\n\tAIRCRAFT_TRANSPORT,\t// What kind of aircraft is this.\n\tTXT_TRANS,\t\t\t\t// Translated text number for aircraft.\n\t\"TRAN\",\t\t\t\t\t// INI name of aircraft.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t// Fixed wing aircraft?\n\t\ttrue,\t\t\t\t\t// Equipped with a rotor?\n\t\ttrue,\t\t\t\t\t// Custom rotor sets for each facing?\n\t\ttrue,\t\t\t\t\t// Can this aircraft land on clear terrain?\n\t\ttrue,\t\t\t\t\t// Is it invisible on radar?\n\t\ttrue,\t\t\t\t\t// Can the player select it so as to give it orders?\n\t\ttrue,\t\t\t\t\t// Can it be assigned as a target for attack.\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\tSTRUCT_NONE,\t\t\t// Preferred landing building.\n\t0xFF,\t\t\t\t\t\t// Landing speed\n\t32,\t\t\t\t\t\t// Number of rotation stages.\n\tMISSION_HUNT\t\t\t// Default mission for aircraft.\n);\n\n// Longbow attack helicopter\nstatic AircraftTypeClass const AttackHeli(\n\tAIRCRAFT_LONGBOW,\t\t// What kind of aircraft is this.\n\tTXT_HELI,\t\t\t\t// Translated text number for aircraft.\n\t\"HELI\",\t\t\t\t\t// INI name of aircraft.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0040,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t// Fixed wing aircraft?\n\t\ttrue,\t\t\t\t\t// Equipped with a rotor?\n\t\tfalse,\t\t\t\t// Custom rotor sets for each facing?\n\t\tfalse,\t\t\t\t// Can this aircraft land on clear terrain?\n\t\ttrue,\t\t\t\t\t// Is it invisible on radar?\n\t\ttrue,\t\t\t\t\t// Can the player select it so as to give it orders?\n\t\ttrue,\t\t\t\t\t// Can it be assigned as a target for attack.\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\tSTRUCT_HELIPAD,\t\t// Preferred landing building.\n\t0xFF,\t\t\t\t\t\t// Landing speed\n\t32,\t\t\t\t\t\t// Number of rotation stages.\n\tMISSION_HUNT\t\t\t// Default mission for aircraft.\n);\n\n\n// Hind\nstatic AircraftTypeClass const OrcaHeli(\n\tAIRCRAFT_HIND,\t\t\t// What kind of aircraft is this.\n\tTXT_ORCA,\t\t\t\t// Translated text number for aircraft.\n\t\"HIND\",\t\t\t\t\t// INI name of aircraft.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0040,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t// Fixed wing aircraft?\n\t\ttrue,\t\t\t\t\t// Equipped with a rotor?\n\t\tfalse,\t\t\t\t// Custom rotor sets for each facing?\n\t\tfalse,\t\t\t\t// Can this aircraft land on clear terrain?\n\t\ttrue,\t\t\t\t\t// Is it invisible on radar?\n\t\ttrue,\t\t\t\t\t// Can the player select it so as to give it orders?\n\t\ttrue,\t\t\t\t\t// Can it be assigned as a target for attack.\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\tSTRUCT_HELIPAD,\t\t// Preferred landing building.\n\t0xFF,\t\t\t\t\t\t// Landing speed\n\t32,\t\t\t\t\t\t// Number of rotation stages.\n\tMISSION_HUNT\t\t\t// Default mission for aircraft.\n);\n\n\n/***********************************************************************************************\n * AircraftTypeClass::AircraftTypeClass -- Constructor for aircraft objects.                   *\n *                                                                                             *\n *    This is the constructor for the aircraft object.                                         *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nAircraftTypeClass::AircraftTypeClass(\n\t\t\t\tAircraftType airtype,\n\t\t\t\tint name,\n\t\t\t\tchar const * ininame,\n\t\t\t\tint verticaloffset,\n\t\t\t\tint primaryoffset,\n\t\t\t\tint primarylateral,\n\t\t\t\tbool is_fixedwing,\n\t\t\t\tbool is_rotorequipped,\n\t\t\t\tbool is_rotorcustom,\n\t\t\t\tbool is_landable,\n\t\t\t\tbool is_stealthy,\n\t\t\t\tbool is_selectable,\n\t\t\t\tbool is_legal_target,\n\t\t\t\tbool is_insignificant,\n\t\t\t\tbool is_immune,\n\t\t\t\tStructType building,\n\t\t\t\tint landingspeed,\n\t\t\t\tint rotation,\n\t\t\t\tMissionType deforder\n\t\t\t\t) :\n\t\t\t\t\tTechnoTypeClass(RTTI_AIRCRAFTTYPE,\n\t\t\t\t\t\t\t\t\t\tint(airtype),\n\t\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\t\tininame,\n\t\t\t\t\t\t\t\t\t\tREMAP_NORMAL,\n\t\t\t\t\t\t\t\t\t\tverticaloffset,\n\t\t\t\t\t\t\t\t\t\tprimaryoffset,\n\t\t\t\t\t\t\t\t\t\tprimarylateral,\n\t\t\t\t\t\t\t\t\t\tprimaryoffset,\n\t\t\t\t\t\t\t\t\t\tprimarylateral,\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\tis_stealthy,\n\t\t\t\t\t\t\t\t\t\tis_selectable,\n\t\t\t\t\t\t\t\t\t\tis_legal_target,\n\t\t\t\t\t\t\t\t\t\tis_insignificant,\n\t\t\t\t\t\t\t\t\t\tis_immune,\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\trotation,\n\t\t\t\t\t\t\t\t\t\tSPEED_WINGED),\n\tIsFixedWing(is_fixedwing),\n\tIsLandable(is_landable),\n\tIsRotorEquipped(is_rotorequipped),\n\tIsRotorCustom(is_rotorcustom),\n\tType(airtype),\n\tMission(deforder),\n\tBuilding(building),\n\tLandingSpeed(landingspeed)\n{\n\t/*\n\t**\tForced aircraft overrides from the default.\n\t*/\n\tSpeed = SPEED_WINGED;\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::operator new -- Allocates an aircraft type object from special pool.     *\n *                                                                                             *\n *    This will allocate an aircraft type class object from the memory pool of that purpose.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the newly allocated aircraft type class object. If there *\n *          was insufficient memory to fulfill the request, then NULL is returned.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * AircraftTypeClass::operator new(size_t)\n{\n\treturn(AircraftTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::operator delete -- Returns aircraft type to special memory pool.         *\n *                                                                                             *\n *    This will return the aircraft type class object back to the special memory pool that     *\n *    it was allocated from.                                                                   *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to the aircraft type class object to delete.                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftTypeClass::operator delete(void * pointer)\n{\n\tAircraftTypes.Free((AircraftTypeClass *)pointer);\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::Init_Heap -- Initialize the aircraft type class heap.                    *\n *                                                                                             *\n *    This will initialize the aircraft type class heap by pre-allocating all known aircraft   *\n *    types. It should be called once and before the rules.ini file is processed.              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese aircraft type class objects must be allocated in the exact order that they\n\t**\tare specified in the AircraftSmen enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew AircraftTypeClass(TransportHeli);\n\tnew AircraftTypeClass(BadgerPlane);\n\tnew AircraftTypeClass(U2Plane);\n\tnew AircraftTypeClass(MigPlane);\n\tnew AircraftTypeClass(YakPlane);\n\tnew AircraftTypeClass(AttackHeli);\n\tnew AircraftTypeClass(OrcaHeli);\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::From_Name -- Converts an ASCII name into an aircraft type number.        *\n *                                                                                             *\n *    This routine is used to convert an ASCII representation of an aircraft into the          *\n *    matching aircraft type number. This is used by the scenario INI reader code.             *\n *                                                                                             *\n * INPUT:   name  -- Pointer to ASCII name to translate.                                       *\n *                                                                                             *\n * OUTPUT:  Returns the aircraft type number that matches the ASCII name provided. If no       *\n *          match could be found, then AIRCRAFT_NONE is returned.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nAircraftType AircraftTypeClass::From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (AircraftType classid = AIRCRAFT_FIRST; classid < AIRCRAFT_COUNT; classid++) {\n\t\t\tif (stricmp(As_Reference(classid).IniName, name) == 0) {\n\t\t\t\treturn(classid);\n\t\t\t}\n\t\t}\n\t}\n\treturn(AIRCRAFT_NONE);\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::One_Time -- Performs one time initialization of the aircraft type class. *\n *                                                                                             *\n *    This routine is used to perform the onetime initialization of the aircraft type. This    *\n *    includes primarily the shape and other graphic data loading.                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This goes to disk and also must only be called ONCE.                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftTypeClass::One_Time(void)\n{\n\tfor (AircraftType index = AIRCRAFT_FIRST; index < AIRCRAFT_COUNT; index++) {\n\t\tchar fullname[_MAX_FNAME+_MAX_EXT];\n\t\tAircraftTypeClass\tconst & uclass = As_Reference(index);\n\n\t\t/*\n\t\t**\tFetch the supporting data files for the unit.\n\t\t*/\n\t\tchar buffer[_MAX_FNAME];\n\t\tsprintf(buffer, \"%sICON\", uclass.Graphic_Name());\n\t\t_makepath(fullname, NULL, NULL, buffer, \".SHP\");\n\t\t((void const *&)uclass.CameoData) = MFCD::Retrieve(fullname);\n\n\t\t/*\n\t\t**\tGeneric shape for all houses load method.\n\t\t*/\n\t\t_makepath(fullname, NULL, NULL, uclass.Graphic_Name(), \".SHP\");\n\t\t((void const *&)uclass.ImageData) = MFCD::Retrieve(fullname);\n\t}\n\n\tLRotorData = MFCD::Retrieve(\"LROTOR.SHP\");\n\tRRotorData = MFCD::Retrieve(\"RROTOR.SHP\");\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::Create_One_Of -- Creates an aircraft object of the appropriate type.     *\n *                                                                                             *\n *    This routine is used to create an aircraft object that matches the aircraft type. It     *\n *    serves as a shortcut to creating an object using the \"new\" operator and \"if\" checks.     *\n *                                                                                             *\n * INPUT:   house -- The house owner of the aircraft that is to be created.                    *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the aircraft created. If the aircraft could not be       *\n *          created, then a NULL is returned.                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * AircraftTypeClass::Create_One_Of(HouseClass * house) const\n{\n\treturn(new AircraftClass(Type, house->Class->House));\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***********************************************************************************************\n * AircraftTypeClass::Prep_For_Add -- Prepares the scenario editor for adding an aircraft objec*\n *                                                                                             *\n *    This routine is used by the scenario editor to prepare for the adding operation. It      *\n *    builds a list of pointers to object types that can be added.                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftTypeClass::Prep_For_Add(void)\n{\n\tfor (AircraftType index = AIRCRAFT_FIRST; index < AIRCRAFT_COUNT; index++) {\n\t\tif (As_Reference(index).Get_Image_Data()) {\n\t\t\tMap.Add_To_List(&As_Reference(index));\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::Display -- Displays a generic version of the aircraft type.              *\n *                                                                                             *\n *    This routine is used by the scenario editor to display a generic version of the object   *\n *    type. This is displayed in the object selection dialog box.                              *\n *                                                                                             *\n * INPUT:   x,y      -- The coordinates to draw the aircraft at (centered).                    *\n *                                                                                             *\n *          window   -- The window to base the coordinates upon.                               *\n *                                                                                             *\n *          house    -- The owner of this generic aircraft.                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftTypeClass::Display(int x, int y, WindowNumberType window, HousesType ) const\n{\n\tint shape = 0;\n\tvoid const * ptr = Get_Cameo_Data();\n\tif (ptr == NULL) {\n\t\tptr = Get_Image_Data();\n\t\tshape = 5;\n\t}\n\tCC_Draw_Shape(ptr, shape, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL);\n}\n#endif\n\n\n/***********************************************************************************************\n * AircraftTypeClass::Occupy_List -- Returns with occupation list for landed aircraft.         *\n *                                                                                             *\n *    This determines the occupation list for the aircraft (if it was landed).                 *\n *                                                                                             *\n * INPUT:   placement   -- Is this for placement legality checking only? The normal condition  *\n *                         is for marking occupation flags.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a cell offset occupation list for the aircraft.          *\n *                                                                                             *\n * WARNINGS:   This occupation list is only valid if the aircraft is landed.                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * AircraftTypeClass::Occupy_List(bool) const\n{\n\tstatic short const _list[] = {0, REFRESH_EOL};\n\treturn(_list);\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::Overlap_List -- Determines the overlap list for a landed aircraft.       *\n *                                                                                             *\n *    This routine figures out the overlap list for the aircraft as if it were landed.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the cell offset overlap list for the aircraft.                        *\n *                                                                                             *\n * WARNINGS:   This overlap list is only valid when the aircraft is landed.                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * AircraftTypeClass::Overlap_List(void) const\n{\n\tstatic short const _list[] = {-(MAP_CELL_W-1), -MAP_CELL_W, -(MAP_CELL_W+1), -1, 1, (MAP_CELL_W-1), MAP_CELL_W, (MAP_CELL_W+1), REFRESH_EOL};\n\treturn(_list);\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::Max_Pips -- Fetches the maximum number of pips allowed.                  *\n *                                                                                             *\n *    Use this routine to retrieve the maximum pip count allowed for this aircraft. This is    *\n *    the maximum number of passengers.                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the maximum number of pips for this aircraft.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/26/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftTypeClass::Max_Pips(void) const\n{\n\tif (PrimaryWeapon != NULL) {\n\t\treturn(5);\n\t}\n\treturn(Max_Passengers());\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::Create_And_Place -- Creates and places aircraft using normal game system *\n *                                                                                             *\n *    This routine is used to create and place an aircraft through the normal game system.     *\n *    Since creation of aircraft in this fashion is prohibited, this routine does nothing.     *\n *                                                                                             *\n * INPUT:   na                                                                                 *\n *                                                                                             *\n * OUTPUT:  Always returns a failure code (false).                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/07/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AircraftTypeClass::Create_And_Place(CELL, HousesType) const\n{\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::Dimensions -- Fetches the graphic dimensions of the aircraft type.       *\n *                                                                                             *\n *    This routine will fetch the pixel dimensions of this aircraft type. These dimensions     *\n *    are used to control map refresh and select box rendering.                                *\n *                                                                                             *\n * INPUT:   width    -- Reference to variable that will be filled in with aircraft width.      *\n *                                                                                             *\n *          height   -- Reference to variable that will be filled in with aircraft height.     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/07/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftTypeClass::Dimensions(int &width, int &height) const\n{\n\tif (Type == AIRCRAFT_BADGER) {\n\t\twidth = 56;\n\t\theight = 56;\n\t} else {\n\t\twidth = 21;\n\t\theight = 20;\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::As_Reference -- Given an aircraft type, find the matching type object.   *\n *                                                                                             *\n *    This routine is used to fetch a reference to the aircraft type class object that matches *\n *    the aircraft type specified.                                                             *\n *                                                                                             *\n * INPUT:   aircraft -- The aircraft type to fetch a reference to the type class object of.    *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the type class object of this aircraft type.           *\n *                                                                                             *\n * WARNINGS:   Be sure that the aircraft type specified is legal. Illegal values will result   *\n *             in undefined behavior.                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nAircraftTypeClass & AircraftTypeClass::As_Reference(AircraftType aircraft)\n{\n\treturn(*AircraftTypes.Ptr(aircraft));\n}\n"
  },
  {
    "path": "CODE/ABSTRACT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/ABSTRACT.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ABSTRACT.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/26/95                                                     *\n *                                                                                             *\n *                  Last Update : July 10, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   AbstractClass::Debug_Dump -- Display debug information to mono screen.                    *\n *   AbstractClass::Distance -- Determines distance to target.                                 *\n *   AbstractTypeClass::AbstractTypeClass -- Constructor for abstract type objects.            *\n *   AbstractTypeClass::Coord_Fixup -- Performs custom adjustments to location coordinate.     *\n *   AbstractTypeClass::Full_Name -- Returns the full name (number) of this object type.       *\n *   AbstractTypeClass::Get_Ownable -- Fetch the ownable bits for this object.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * AbstractClass::Debug_Dump -- Display debug information to mono screen.                      *\n *                                                                                             *\n *    This debug only routine will display various information about this abstract class       *\n *    object to the monochrome screen specified.                                               *\n *                                                                                             *\n * INPUT:   mono  -- Pointer to the monochrome screen to display the debug information to.     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef CHEAT_KEYS\nvoid AbstractClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(IsActive);\n\n\tmono->Set_Cursor(11, 5);mono->Printf(\"%08X\", As_Target());\n\tmono->Set_Cursor(20, 1);mono->Printf(\"%08X\", Coord);\n\tmono->Set_Cursor(29, 1);mono->Printf(\"%3d\", Height);\n\tif (Owner() != HOUSE_NONE) {\n\t\tmono->Set_Cursor(1, 3);\n\t\tmono->Printf(\"%-18s\", Text_String(HouseTypeClass::As_Reference(Owner()).FullName));\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * AbstractClass::Distance -- Determines distance to target.                                   *\n *                                                                                             *\n *    This will determine the distance (direct line) to the target. The distance is in         *\n *    'leptons'. This routine is typically used for weapon range checks.                       *\n *                                                                                             *\n * INPUT:   target   -- The target to determine range to.                                      *\n *                                                                                             *\n * OUTPUT:  Returns with the range to the specified target (in leptons).                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AbstractClass::Distance(TARGET target) const\n{\n\t/*\n\t**\tShould subtract a fudge-factor distance for building targets.\n\t*/\n\tBuildingClass * obj = As_Building(target);\n\tint dist = Distance(As_Coord(target));\n\n\t/*\n\t** If the object is a building the adjust it by the average radius\n\t** of the object.\n\t*/\n\tif (obj) {\n\t\tdist -= ((obj->Class->Width() + obj->Class->Height()) * (0x100 / 4));\n\t\tif (dist < 0) dist = 0;\n\t}\n\n\t/*\n\t** Return the distance to the target\n\t*/\n\treturn(dist);\n}\n\n\n/***********************************************************************************************\n * AbstractTypeClass::AbstractTypeClass -- Constructor for abstract type objects.              *\n *                                                                                             *\n *    This is the constructor for AbstractTypeClass objects. It initializes the INI name and   *\n *    the text name for this object type.                                                      *\n *                                                                                             *\n * INPUT:   name  -- Text number for the full name of the object.                              *\n *                                                                                             *\n *          ini   -- The ini name for this object type.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nAbstractTypeClass::AbstractTypeClass(RTTIType rtti, int id, int name, char const * ini) :\n\tRTTI(rtti),\n\tID(id),\n\tFullName(name)\n{\n\tstrncpy((char *)IniName, ini, sizeof(IniName));\n\t((char &)IniName[sizeof(IniName)-1]) = '\\0';\n}\n\n\n/***********************************************************************************************\n * AbstractTypeClass::Coord_Fixup -- Performs custom adjustments to location coordinate.       *\n *                                                                                             *\n *    This routine is called when the placement coordinate should be fixed up according        *\n *    to any special rules specific to this object type. At this level, no transformation      *\n *    occurs. Derived classes will transform the coordinate as necessary.                      *\n *                                                                                             *\n * INPUT:   coord -- The proposed coordinate that this object type will be placed down at.     *\n *                                                                                             *\n * OUTPUT:  Returns with the adjusted coordinate that the object should be placed down at.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE AbstractTypeClass::Coord_Fixup(COORDINATE coord) const\n{\n\treturn(coord);\n}\n\n\n/***********************************************************************************************\n * AbstractTypeClass::Full_Name -- Returns the full name (number) of this object type.         *\n *                                                                                             *\n *    This routine is used to fetch the full name of this object type. The name value          *\n *    returned is actually the index number into the text array.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the full name index number for this object type.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AbstractTypeClass::Full_Name(void) const\n{\n#ifdef FIXIT_NAME_OVERRIDE\n\tfor (int index = 0; index < ARRAY_SIZE(NameOverride); index++) {\n\t\tif (NameIDOverride[index] == ((RTTI+1) * 100) + ID)  {\n\t\t\treturn(-(index+1));\n\t\t}\n\t}\n#endif\n\treturn(FullName);\n}\n\n\n/***********************************************************************************************\n * AbstractTypeClass::Get_Ownable -- Fetch the ownable bits for this object.                   *\n *                                                                                             *\n *    This returns a bit flag that indicates which houses are allowed to own this object       *\n *    type. At this level, all houses have ownership rights. This routine will be overridden   *\n *    by object types that restrict ownership.                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a bit flag indicating which houses have ownership rights.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AbstractTypeClass::Get_Ownable(void) const\n{\n\treturn(HOUSEF_ALLIES | HOUSEF_SOVIET | HOUSEF_OTHERS);\n}\n\n\n\n"
  },
  {
    "path": "CODE/ABSTRACT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/ABSTRACT.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ABSTRACT.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/26/95                                                     *\n *                                                                                             *\n *                  Last Update : January 26, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef ABSTRACT_H\n#define ABSTRACT_H\n\nDirType Direction(CELL cell1, CELL cell2);\nDirType Direction(COORDINATE coord1, COORDINATE coord2);\nint Distance(COORDINATE coord1, COORDINATE coord2);\nCOORDINATE As_Coord(TARGET target);\n\nclass AbstractTypeClass;\n\n/*\n**\tThis class is the base class for all game objects that have an existence on the\n**\tbattlefield.\n*/\nclass AbstractClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tThis specifies the type of object and the unique ID number\n\t\t**\tassociated with it. The ID number happens to match the index into\n\t\t**\tthe object heap appropriate for this object type.\n\t\t*/\n\t\tRTTIType RTTI;\n\t\tint ID;\n\n\t\t/*\n\t\t**\tThe coordinate location of the unit. For vehicles, this is the center\n\t\t**\tpoint. For buildings, it is the upper left corner.\n\t\t*/\n\t\tCOORDINATE Coord;\n\n\t\t/*\n\t\t**\tThis is the height of the object above ground (expressed in leptons).\n\t\t*/\n\t\tint Height;\n\n\t\t/*\n\t\t**\tThe actual object ram-space is located in arrays in the data segment. This flag\n\t\t**\tis used to indicate which objects are free to be reused and which are currently\n\t\t**\tin use by the game.\n\t\t*/\n\t\tunsigned IsActive:1;\n\n\t\t/*-----------------------------------------------------------------------------------\n\t\t**\tConstructor & destructors.\n\t\t*/\n\t\tAbstractClass(RTTIType rtti, int id) : RTTI(rtti), ID(id), Coord(0xFFFFFFFFL), Height(0) {};\n\t\tAbstractClass(NoInitClass const & x) {x();};\n\t\tvirtual ~AbstractClass(void) {};\n\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tvirtual char const * Name(void) const {return(\"\");}\n\t\tvirtual HousesType Owner(void) const {return HOUSE_NONE;};\n\t\tTARGET As_Target(void) const {return(Build_Target(RTTI, ID));};\n\t\tRTTIType What_Am_I(void) const {return(RTTI);};\n\n\t\t/*\n\t\t**\tScenario and debug support.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass * mono) const;\n\t\t#endif\n\n\t\t/*\n\t\t**\tCoordinate query support functions.\n\t\t*/\n\t\tvirtual COORDINATE Center_Coord(void) const {return Coord;};\n\t\tvirtual COORDINATE Target_Coord(void) const {return Coord;};\n\n\t\t/*\n\t\t**\tCoordinate inquiry functions. These are used for both display and\n\t\t**\tcombat purposes.\n\t\t*/\n\t\tDirType Direction(AbstractClass const * object) const {return ::Direction(Center_Coord(), object->Target_Coord());};\n\t\tDirType Direction(COORDINATE coord) const {return ::Direction(Center_Coord(), coord);};\n\t\tDirType Direction(TARGET target) const {return ::Direction(Center_Coord(), As_Coord(target));};\n\t\tDirType Direction(CELL cell) const {return ::Direction(Coord_Cell(Center_Coord()), cell);};\n\t\tint Distance(TARGET target) const;\n\t\tint Distance(COORDINATE coord) const {return ::Distance(Center_Coord(), coord);};\n\t\tint Distance(AbstractClass const * object) const {return ::Distance(Center_Coord(), object->Target_Coord());};\n\n\t\t/*\n\t\t**\tObject entry and exit from the game system.\n\t\t*/\n\t\tvirtual MoveType Can_Enter_Cell(CELL , FacingType = FACING_NONE) const {return MOVE_OK;};\n\n\t\t/*\n\t\t**\tAI.\n\t\t*/\n\t\tvirtual void AI(void) {};\n\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/ADAMTEMP.MAK",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n# $Header:   F:\\projects\\c&c0\\vcs\\code\\bfile.mav   5.0   11 Nov 1996 09:40:38   JOE_BOSTIC  $\n#***************************************************************************\n#**   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        **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Command & Conquer                        *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Joe L. Bostic                            *\n#*                                                                         *\n#*                   Start Date : March 25, 1993                           *\n#*                                                                         *\n#*                  Last Update : March 25, 1993   [JLB]                   *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n\n\n# Comment out the following line to disable \"include file autodependency\".\n.AUTODEPEND\n#.SWAP\n\n!include\t\"rules.mak\"\n\n\n##########################################################################\n\nMAPFILES = \\\n\nCACHEMAP = \\\n\tBRIEFING.AUD \\\n\nLOCALFILES = \\\n\tPROLOG.CPS \\\n\tMAP.AUD \\\n\tTITLE.CPS \\\n\tPALETTE.CPS \\\n\tINTRO.AUD \\\n\tEGOPAL.PAL \\\n\tRULES.INI \\\n\tCREDITS.TXT \\\n\tALIPAPER.CPS \\\n\t3POINT.FNT \\\n\t8POINT.FNT \\\n\tEDITFNT.FNT \\\n\tCONQUER.ENG \\\n\tDEBUG.ENG \\\n\tLED.FNT \\\n\tSNOW.PAL \\\n\tTEMPERAT.PAL \\\n\tINTERIOR.PAL \\\n\tVCR.FNT \\\n\tHOLE0000.LUT \\\n\tHOLE0001.LUT \\\n\tHOLE0002.LUT \\\n\tHOLE0003.LUT \\\n\tHOLE0004.LUT \\\n\tHOLE0005.LUT \\\n\tHOLE0006.LUT \\\n\tHOLE0007.LUT \\\n\tHOLE0008.LUT \\\n\tHOLE0009.LUT \\\n\tHOLE0010.LUT \\\n\tHOLE0011.LUT \\\n\tHOLE0012.LUT \\\n\tHOLE0013.LUT \\\n\tHOLE0014.LUT \\\n\tHOLE0015.LUT \\\n\tHOLE0016.LUT \\\n\tHOLE0017.LUT \\\n\tHOLE0018.LUT \\\n\tHOLE0019.LUT \\\n\tHOLE0020.LUT \\\n\tHOLE0021.LUT \\\n\tHOLE0022.LUT \\\n\tHOLE0023.LUT \\\n\tHOLE0024.LUT \\\n\tHOLE0025.LUT \\\n\tHOLE0026.LUT \\\n\tHOLE0027.LUT \\\n\tHOLE0028.LUT \\\n\tHOLE0029.LUT \\\n\tHOLE0030.LUT \\\n\tHOLE0031.LUT \\\n\tHOLE0032.LUT \\\n\tHOLE0033.LUT \\\n\tHOLE0034.LUT \\\n\tHOLE0035.LUT \\\n\tHOLE0036.LUT \\\n\tHOLE0037.LUT \\\n\tHOLE0038.LUT \\\n\tHOLE0039.LUT \\\n\tHOLE0040.LUT \\\n\tHOLE0041.LUT \\\n\tHOLE0042.LUT \\\n\tHOLE0043.LUT \\\n\tHOLE0044.LUT \\\n\tHOLE0045.LUT \\\n\tHOLE0046.LUT \\\n\tHOLE0047.LUT \\\n#\tTEMPSCOR.FNT \\\n#\t6POINT.FNT \\\n#\tGRAD6FNT.FNT \\\n#\tSCOREFNT.FNT \\\n\n\n# Files that have counterparts in both high and low resolutions.\n# These files will be built into the HIRES.MIX and LORES.MIX files.\nHILORES = \\\n\tTRANICON.SHP \\\n\tPIPS.SHP \\\n\tPULSE.SHP \\\n\tATOMICON.SHP \\\n\tWARPICON.SHP \\\n\tC1.SHP \\\n\tC2.SHP \\\n\tCHAN.SHP \\\n\tDELPHI.SHP \\\n\tE1.SHP \\\n\tE2.SHP \\\n\tE3.SHP \\\n\tE4.SHP \\\n\tE5.SHP \\\n\tE6.SHP \\\n\tE7.SHP \\\n\tEINSTEIN.SHP \\\n\tGNRL.SHP \\\n\tMEDI.SHP \\\n\tSPY.SHP \\\n\tTHF.SHP \\\n\tDD-BKGND.SHP \\\n\tDD-BOTM.SHP \\\n\tDD-CRNR.SHP \\\n\tDD-EDGE.SHP \\\n\tDD-LEFT.SHP \\\n\tDD-RIGHT.SHP \\\n\tDD-TOP.SHP \\\n\t12METFNT.FNT \\\n\tGRAD6FNT.FNT \\\n\tHELP.FNT \\\n\t6POINT.FNT \\\n\tTYPE.FNT \\\n\tSCOREFNT.FNT \\\n\t1TNKICON.SHP \\\n\t2TNKICON.SHP \\\n\t3TNKICON.SHP \\\n\t4TNKICON.SHP \\\n\tAFLDICON.SHP \\\n\tAGUNICON.SHP \\\n\tAPCICON.SHP \\\n\tAPWRICON.SHP \\\n\tARTYICON.SHP \\\n\tATEKICON.SHP \\\n\tBADRICON.SHP \\\n\tBARRICON.SHP \\\n\tBRIKICON.SHP \\\n\tBTN-DN.SHP \\\n\tBTN-PL.SHP \\\n\tBTN-ST.SHP \\\n\tBTN-UP.SHP \\\n\tCAICON.SHP \\\n\tCAMICON.SHP \\\n\tCLOCK.SHP \\\n\tDDICON.SHP \\\n\tDOGICON.SHP \\\n\tDOMEICON.SHP \\\n\tDOMFICON.SHP \\\n\tE1ICON.SHP \\\n\tE2ICON.SHP \\\n\tE3ICON.SHP \\\n\tE4ICON.SHP \\\n\tE6ICON.SHP \\\n\tE7ICON.SHP \\\n\tFACFICON.SHP \\\n\tFACTICON.SHP \\\n\tFENCICON.SHP \\\n\tFIXICON.SHP \\\n\tFTURICON.SHP \\\n\tGAPICON.SHP \\\n\tGPSSICON.SHP \\\n\tGUNICON.SHP \\\n\tHARVICON.SHP \\\n\tHBOXICON.SHP \\\n\tHELIICON.SHP \\\n\tHINDICON.SHP \\\n\tHPADICON.SHP \\\n\tINFXICON.SHP \\\n\tIRONICON.SHP \\\n\tJEEPICON.SHP \\\n\tKENNICON.SHP \\\n\tLSTICON.SHP \\\n\tMAP.SHP \\\n\tMCVICON.SHP \\\n\tMEDIICON.SHP \\\n\tMGGICON.SHP \\\n\tMIGICON.SHP \\\n\tMNLYICON.SHP \\\n\tMOUSE.SHP \\\n\tMRJICON.SHP \\\n\tMSLOICON.SHP \\\n\tNATORADR.SHP \\\n\tPBMBICON.SHP \\\n\tPBOXICON.SHP \\\n\tPDOXICON.SHP \\\n\tPINFICON.SHP \\\n\tPOWER.SHP \\\n\tPOWERBAR.SHP \\\n\tPOWRICON.SHP \\\n\tPROCICON.SHP \\\n\tPTICON.SHP \\\n\tREPAIR.SHP \\\n\tSAMICON.SHP \\\n\tSBAGICON.SHP \\\n\tSELL.SHP \\\n\tSIDEBAR.SHP \\\n\tSILOICON.SHP \\\n\tSMIGICON.SHP \\\n\tSONRICON.SHP \\\n\tSOVPAPER.CPS \\\n\tSPEFICON.SHP \\\n\tSPENICON.SHP \\\n\tSPYICON.SHP \\\n\tSSICON.SHP \\\n\tSTEKICON.SHP \\\n\tSTRIP.SHP \\\n\tSTRIPDN.SHP \\\n\tSTRIPUP.SHP \\\n\tSYRDICON.SHP \\\n\tSYRFICON.SHP \\\n\tTABS.SHP \\\n\tTENTICON.SHP \\\n\tTHFICON.SHP \\\n\tTRUKICON.SHP \\\n\tTSLAICON.SHP \\\n\tU2ICON.SHP \\\n\tUSSRRADR.SHP \\\n\tV2RLICON.SHP \\\n\tWEAFICON.SHP \\\n\tWEAPICON.SHP \\\n\tYAKICON.SHP \\\n\tNRADRFRM.SHP \\\n\tURADRFRM.SHP \\\n\tSIDE1NA.SHP \\\n\tSIDE1US.SHP \\\n\tSIDE2NA.SHP \\\n\tSIDE2US.SHP \\\n\tSIDE3NA.SHP \\\n\tSIDE3US.SHP \\\n\tSTRIPNA.SHP \\\n\tSTRIPUS.SHP \\\n\n#\tMOEBICON.SHP \\\n\nHILORES1 = \\\n\tMECH.SHP \\\n\tSHOK.SHP \\\n\tCARRICON.SHP \\\n\tCTNKICON.SHP \\\n\tDTRKICON.SHP \\\n\tMECHICON.SHP \\\n\tMSUBICON.SHP \\\n\tQTNKICON.SHP \\\n\tSHOKICON.SHP \\\n\tSTNKICON.SHP \\\n\tTTNKICON.SHP \\\n\n# These helper macros substitute the extension so that\n# the appropriate art build rule will be invoked.\nxLOHILORES = $(HILORES:.SHP=.LOW)\nLOHILORES = $(xLOHILORES:.FNT=.LNT)\nxHIHILORES = $(HILORES:.SHP=.HI)\nHIHILORES = $(xHIHILORES:.FNT=.HNT)\n\nxLOHILORES1 = $(HILORES1:.SHP=.LOW)\nLOHILORES1 = $(xLOHILORES1:.FNT=.LNT)\nxHIHILORES1 = $(HILORES1:.SHP=.HI)\nHIHILORES1 = $(xHIHILORES1:.FNT=.HNT)\n\n#\n# Files required for hires/Win95 version only\n#\n# This mix file is cached\n#\nHIRESFILES = \\\n\tALIPAPER.PCX \\\n      \tPROLOG.PCX \\\n\tSOVPAPER.PCX \\\n\tAFTR_HI.PCX \\\n\tALY1.PCX \\\n\tAPC_HI.PCX \\\n\tAPHI0049.PCX \\\n\tBNHI0020.PCX \\\n\tDCHI0040.PCX \\\n\tFRHI0166.PCX \\\n\tLAB.PCX \\\n\tLANDSBRG.PCX \\\n\tMAHI0107.PCX \\\n\tMIG_HI.PCX \\\n\tMTFACTHI.PCX \\\n\tNEEDLE.PCX \\\n\tSOV2.PCX \\\n\tSPY.PCX \\\n\tSTALIN.PCX \\\n\tTENT.PCX \\\n#\tENG_HI.PCX \\\n\n\nCONQUERFILES = \\\n\tPARABOMB.SHP \\\n\nGENERALMAPFILES = \\\n\tMISSIONS.PKT \\\n\tCSTRIKE.PKT \\\n\tTUTORIAL.INI \\\n        SCG01EA.INI \\     \n        SCG40EA.INI \\     \n        SCG41EA.INI \\     \n        SCG42EA.INI \\     \n        SCG43EA.INI \\     \n        SCG44EA.INI \\     \n        SCG45EA.INI \\     \n        SCG46EA.INI \\     \n        SCG47EA.INI \\     \n        SCG48EA.INI \\     \n        SCU40EA.INI \\     \n        SCU41EA.INI \\     \n        SCU42EA.INI \\     \n        SCU43EA.INI \\     \n        SCU44EA.INI \\     \n        SCU45EA.INI \\     \n        SCU46EA.INI \\     \n        SCU47EA.INI \\     \n        SCU48EA.INI \\     \n\tSCU01EA.INI \\     \n\tSCM01EA.INI \\      \n\tSCM02EA.INI \\ \n\tSCM03EA.INI \\ \n\tSCM04EA.INI \\ \n\tSCM05EA.INI \\ \n\tSCM06EA.INI \\ \n\tSCM07EA.INI \\ \n\tSCM08EA.INI \\ \n\tSCM09EA.INI \\ \n\tSCM10EA.INI \\ \n\tSCM11EA.INI \\ \n\tSCM12EA.INI \\ \n\tSCM13EA.INI \\ \n\tSCM14EA.INI \\ \n\tSCM15EA.INI \\ \n\tSCM16EA.INI \\ \n\tSCM17EA.INI \\ \n\tSCM18EA.INI \\ \n\tSCM19EA.INI \\ \n\tSCM20EA.INI \\ \n\tSCM21EA.INI \\ \n\tSCM22EA.INI \\ \n\tSCM23EA.INI \\ \n\tSCM24EA.INI \\ \n\tSCMD0EA.INI \\\n\tSCMD1EA.INI \\\n\tSCMD2EA.INI \\\n\tSCMD3EA.INI \\\n\tSCMD4EA.INI \\\n\tSCMD5EA.INI \\\n\tSCMD6EA.INI \\\n\tSCMD7EA.INI \\\n\tSCMD8EA.INI \\\n\tSCMD9EA.INI \\\n\tSCME0EA.INI \\\n\tSCME1EA.INI \\\n\tSCME2EA.INI \\\n\tSCME3EA.INI \\\n\tSCME4EA.INI \\\n\tSCME5EA.INI \\\n\tSCME6EA.INI \\\n\tSCME7EA.INI \\\n\tSCME8EA.INI \\\n\tSCME9EA.INI \\\n\tSCMF0EA.INI \\\n\tSCMF1EA.INI \\\n\tSCMF2EA.INI \\\n\tSCMF3EA.INI \\\n\tSCMF4EA.INI \\\n\tSCMF5EA.INI \\\n\tSCMF6EA.INI \\\n\tSCMF7EA.INI \\\n\tSCMF8EA.INI \\\n\tSCMF9EA.INI \\\n\tSCMG0EA.INI \\\n\tSCMG1EA.INI \\\n\tSCMG2EA.INI \\\n\tSCMG3EA.INI \\\n\tSCMG4EA.INI \\\n\tSCMG5EA.INI \\\n\tSCMG6EA.INI \\\n\tSCMG7EA.INI \\\n\tSCMG8EA.INI \\\n\tSCMG9EA.INI \\\n\tSCMH0EA.INI \\\n\tSCMH1EA.INI \\\n\tSCMH2EA.INI \\\n\tSCMH3EA.INI \\\n\tSCMH4EA.INI \\\n\tSCMH5EA.INI \\\n\tSCMH6EA.INI \\\n\tSCMH7EA.INI \\\n\tSCMH8EA.INI \\\n\tSCMH9EA.INI \\\n\tSCMI0EA.INI \\\n\tSCMI1EA.INI \\\n\tSCMI2EA.INI \\\n\tSCMI3EA.INI \\\n\tSCMI4EA.INI \\\n\tSCMI5EA.INI \\\n\tSCMI6EA.INI \\\n\tSCMI7EA.INI \\\n\tSCMI8EA.INI \\\n\tSCMI9EA.INI \\\n\tSCMJ0EA.INI \\\n\tSCMJ1EA.INI \\\n\tSCMJ2EA.INI \\\n\tSCMJ3EA.INI \\\n\tSCMJ4EA.INI \\\n\tSCMJ5EA.INI \\\n\tSCMJ6EA.INI \\\n\tSCMJ7EA.INI \\\n\tSCMJ8EA.INI \\\n\tSCMJ9EA.INI \\\n\tSCMK0EA.INI \\\n\tSCMK1EA.INI \\\n\tSCMK2EA.INI \\\n\tSCMK3EA.INI \\\n\tSCMK4EA.INI \\\n\tSCMK5EA.INI \\\n\tSCMK6EA.INI \\\n\tSCMK7EA.INI \\\n\tSCMK8EA.INI \\\n\tSCMK9EA.INI \\\n\tSCML0EA.INI \\\n\tSCML1EA.INI \\\n\tSCML2EA.INI \\\n\tSCML3EA.INI \\\n\tSCML4EA.INI \\\n\tSCML5EA.INI \\\n\tSCML6EA.INI \\\n\tSCML7EA.INI \\\n\tSCML8EA.INI \\\n\tSCML9EA.INI \\\n\tSCMM0EA.INI \\\n\tSCMM1EA.INI \\\n\tSCMM2EA.INI \\\n\tSCMM3EA.INI \\\n\tSCMM4EA.INI \\\n\tSCMM5EA.INI \\\n\tSCMM6EA.INI \\\n\tSCMM7EA.INI \\\n\tSCMM8EA.INI \\\n\tSCMM9EA.INI \\\n      \tSCM25EA.INI \\\n\tSCM26EA.INI \\\n\tSCM27EA.INI \\\n\tSCM28EA.INI \\\n\tSCM29EA.INI \\\n\tSCM30EA.INI \\\n\tSCM31EA.INI \\ \n\tSCM32EA.INI \\ \n\tSCM33EA.INI \\\n\tSCM34EA.INI \\\n     \tSCM35EA.INI \\\n\tSCM36EA.INI \\\n\tSCM37EA.INI \\\n\tSCM38EA.INI \\\n\tSCM39EA.INI \\\n\tSCM40EA.INI \\\n\tSCM41EA.INI \\\n\tSCM42EA.INI \\\n\tSCM43EA.INI \\\n\tSCM44EA.INI \\\n\tSCM45EA.INI \\\n\tSCM46EA.INI \\\n\tSCM47EA.INI \\\n\tSCM48EA.INI \\\n\tSCM49EA.INI \\\n\tSCM50EA.INI \\\n\tSCM51EA.INI \\\n\tSCM52EA.INI \\\n\tSCM53EA.INI \\\n\tSCM54EA.INI \\\n\tSCM55EA.INI \\\n\tSCM56EA.INI \\\n\tSCM57EA.INI \\\n\tSCM58EA.INI \\\n\tSCM59EA.INI \\\n\tSCM60EA.INI \\\n\tSCM61EA.INI \\\n\tSCM62EA.INI \\\n\tSCM63EA.INI \\\n\tSCM64EA.INI \\\n\tSCM65EA.INI \\\n\tSCM66EA.INI \\\n\tSCM67EA.INI \\\n\tSCM68EA.INI \\\n\tSCM69EA.INI \\\n\tSCM70EA.INI \\\n\tSCM71EA.INI \\\n\tSCM72EA.INI \\\n\tSCM73EA.INI \\\n\tSCM74EA.INI \\\n\tSCM75EA.INI \\\n\tSCM76EA.INI \\\n\tSCM77EA.INI \\\n\tSCM78EA.INI \\\n\tSCM79EA.INI \\\n\tSCM80EA.INI \\\n\tSCM81EA.INI \\\n\tSCM82EA.INI \\\n\tSCM83EA.INI \\\n\tSCM84EA.INI \\\n\tSCM85EA.INI \\\n\tSCM86EA.INI \\\n\tSCM87EA.INI \\\n\tSCM88EA.INI \\\n\tSCM89EA.INI \\\t\n\tSCM90EA.INI \\\n\tSCM91EA.INI \\\n\tSCM92EA.INI \\\n\tSCM93EA.INI \\\n\tSCM94EA.INI \\\n\tSCM95EA.INI \\\n\tSCM96EA.INI \\\n\tSCM97EA.INI \\\n\tSCM98EA.INI \\\n\tSCM99EA.INI \\\n\tSCM100EA.INI \\\n\tSCM101EA.INI \\\n\tSCM102EA.INI \\\n\tSCM103EA.INI \\\n\tSCM104EA.INI \\\n\tSCM105EA.INI \\\n\tSCM106EA.INI \\\n\tSCM107EA.INI \\\n\tSCM108EA.INI \\\n\tSCM109EA.INI \\\n\tSCM110EA.INI \\\n\tSCM111EA.INI \\\n\tSCM112EA.INI \\\n\tSCM113EA.INI \\\n\tSCM114EA.INI \\\n\tSCM115EA.INI \\\n\tSCM116EA.INI \\\n\tSCM117EA.INI \\\n\tSCM118EA.INI \\\n \tSCM119EA.INI \\    \n\tSCM120EA.INI \\     \n\tSCM121EA.INI \\    \n\tSCM122EA.INI \\     \n\tSCM123EA.INI \\    \n\tSCM124EA.INI \\    \n\tSCM125EA.INI \\    \n\tSCM126EA.INI \\    \n\tSCM127EA.INI \\    \n\tSCM128EA.INI \\    \n\tSCM129EA.INI \\ \n\tSCM130EA.INI \\   \n\nNETMAPFILES = \\\n\n# Files that aren't cached.\nGENERALFILES = \\\n\tAFTR_LO.CPS \\\n\tALY1-LO.CPS \\\n\tAPC_LO.CPS \\\n\tAPLO0049.CPS \\\n\tBNLO0020.CPS \\\n\tDCLO0040.CPS \\\n\tFRLO0166.CPS \\\n\tLAB-LO.CPS \\\n\tLANDS-LO.CPS \\\n\tMALO0107.CPS \\\n\tMIG_LO.CPS \\\n\tMTFACTLO.CPS \\\n\tNEEDL-LO.CPS \\\n\tSOV2-LO.CPS \\\n\tSPY-LO.CPS \\\n\tSTALN-LO.CPS \\\n\tTENT-LO.CPS \\\n\tTITLE.CPS \\\n\tPPAPER.CPS \\\n\tMSAA.WSA \\\n\tMSAB.WSA \\\n\tMSAC.WSA \\\n\tMSAD.WSA \\\n\tMSAE.WSA \\\n\tMSAF.WSA \\\n\tMSAG.WSA \\\n\tMSAH.WSA \\\n\tMSAI.WSA \\\n\tMSAJ.WSA \\\n\tMSAK.WSA \\\n\tMSAL.WSA \\\n\tMSAM.WSA \\\n\tMSAN.WSA \\\n\tMSSA.WSA \\\n\tMSSB.WSA \\\n\tMSSC.WSA \\\n\tMSSD.WSA \\\n\tMSSE.WSA \\\n\tMSSF.WSA \\\n\tMSSG.WSA \\\n\tMSSH.WSA \\\n\tMSSI.WSA \\\n\tMSSJ.WSA \\\n\tMSSK.WSA \\\n\tMSSL.WSA \\\n\tMSSM.WSA \\\n\tMSSN.WSA \\\n\nINTERIORFILES = \\\n\tBOXES01.INT \\\n\tBOXES02.INT \\\n\tBOXES03.INT \\\n\tBOXES04.INT \\\n\tBOXES05.INT \\\n\tBOXES06.INT \\\n\tBOXES07.INT \\\n\tBOXES08.INT \\\n\tBOXES09.INT \\\n\tXTRA0001.INT \\\n\tXTRA0002.INT \\\n\tXTRA0003.INT \\\n\tXTRA0004.INT \\\n\tXTRA0005.INT \\\n\tXTRA0006.INT \\\n\tXTRA0007.INT \\\n\tXTRA0008.INT \\\n\tXTRA0009.INT \\\n\tXTRA0010.INT \\\n\tXTRA0011.INT \\\n\tXTRA0012.INT \\\n\tXTRA0013.INT \\\n\tXTRA0014.INT \\\n\tXTRA0015.INT \\\n\tXTRA0016.INT \\\n\tCLEAR1.INT \\\n\tMOVEFLSH.INT \\\n\tARRO0001.INT \\\n\tARRO0002.INT \\\n\tARRO0003.INT \\\n\tARRO0004.INT \\\n\tARRO0005.INT \\\n\tARRO0006.INT \\\n\tARRO0007.INT \\\n\tARRO0008.INT \\\n\tARRO0009.INT \\\n\tARRO0010.INT \\\n\tARRO0011.INT \\\n\tARRO0012.INT \\\n\tARRO0013.INT \\\n\tARRO0014.INT \\\n\tARRO0015.INT \\\n\tFLOR0001.INT \\\n\tFLOR0002.INT \\\n\tFLOR0003.INT \\\n\tFLOR0004.INT \\\n\tFLOR0005.INT \\\n\tFLOR0006.INT \\\n\tFLOR0007.INT \\\n\tGFLR0001.INT \\\n\tGFLR0002.INT \\\n\tGFLR0003.INT \\\n\tGFLR0004.INT \\\n\tGFLR0005.INT \\\n\tGSTR0001.INT \\\n\tGSTR0002.INT \\\n\tGSTR0003.INT \\\n\tGSTR0004.INT \\\n\tGSTR0005.INT \\\n\tGSTR0006.INT \\\n\tGSTR0007.INT \\\n\tGSTR0008.INT \\\n\tGSTR0009.INT \\\n\tGSTR0010.INT \\\n\tGSTR0011.INT \\\n\tLWAL0001.INT \\\n\tLWAL0002.INT \\\n\tLWAL0003.INT \\\n\tLWAL0004.INT \\\n\tLWAL0005.INT \\\n\tLWAL0006.INT \\\n\tLWAL0007.INT \\\n\tLWAL0008.INT \\\n\tLWAL0009.INT \\\n\tLWAL0010.INT \\\n\tLWAL0011.INT \\\n\tLWAL0012.INT \\\n\tLWAL0013.INT \\\n\tLWAL0014.INT \\\n\tLWAL0015.INT \\\n\tLWAL0016.INT \\\n\tLWAL0017.INT \\\n\tLWAL0018.INT \\\n\tLWAL0019.INT \\\n\tLWAL0020.INT \\\n\tLWAL0021.INT \\\n\tLWAL0022.INT \\\n\tLWAL0023.INT \\\n\tLWAL0024.INT \\\n\tLWAL0025.INT \\\n\tLWAL0026.INT \\\n\tLWAL0027.INT \\\n\tSTRP0001.INT \\\n\tSTRP0002.INT \\\n\tSTRP0003.INT \\\n\tSTRP0004.INT \\\n\tSTRP0005.INT \\\n\tSTRP0006.INT \\\n\tSTRP0007.INT \\\n\tSTRP0008.INT \\\n\tSTRP0009.INT \\\n\tSTRP0010.INT \\\n\tSTRP0011.INT \\\n\tWALL0001.INT \\\n\tWALL0002.INT \\\n\tWALL0003.INT \\\n\tWALL0004.INT \\\n\tWALL0005.INT \\\n\tWALL0006.INT \\\n\tWALL0007.INT \\\n\tWALL0008.INT \\\n\tWALL0009.INT \\\n\tWALL0010.INT \\\n\tWALL0011.INT \\\n\tWALL0012.INT \\\n\tWALL0013.INT \\\n\tWALL0014.INT \\\n\tWALL0015.INT \\\n\tWALL0016.INT \\\n\tWALL0017.INT \\\n\tWALL0018.INT \\\n\tWALL0019.INT \\\n\tWALL0020.INT \\\n\tWALL0021.INT \\\n\tWALL0022.INT \\\n\tWALL0023.INT \\\n\tWALL0024.INT \\\n\tWALL0025.INT \\\n\tWALL0026.INT \\\n\tWALL0027.INT \\\n\tWALL0028.INT \\\n\tWALL0029.INT \\\n\tWALL0030.INT \\\n\tWALL0031.INT \\\n\tWALL0032.INT \\\n\tWALL0033.INT \\\n\tWALL0034.INT \\\n\tWALL0035.INT \\\n\tWALL0036.INT \\\n\tWALL0037.INT \\\n\tWALL0038.INT \\\n\tWALL0039.INT \\\n\tWALL0040.INT \\\n\tWALL0041.INT \\\n\tWALL0042.INT \\\n\tWALL0043.INT \\\n\tWALL0044.INT \\\n\tWALL0045.INT \\\n\tWALL0046.INT \\\n\tWALL0047.INT \\\n\tWALL0048.INT \\\n\tWALL0049.INT \\\n\n# Both the temperate and snow sets have identical template entries.\nTEMPERATEFILES = \\\n\tMINE.TEM \\\n\tICE01.TEM \\\n\tICE02.TEM \\\n\tICE03.TEM \\\n\tICE04.TEM \\\n\tICE05.TEM \\\n\tMOVEFLSH.TEM \\\n\tBR1X.TEM \\\n\tBR2X.TEM \\\n\tBRIDGE1X.TEM \\\n\tBRIDGE2X.TEM \\\n\tBRIDGE1H.TEM \\\n\tBRIDGE2H.TEM \\\n\tF01.TEM \\\n\tF02.TEM \\\n\tF03.TEM \\\n\tF04.TEM \\\n\tF05.TEM \\\n\tF06.TEM \\\n\tELECTRO.TEM \\\n\tB1.TEM \\\n\tB2.TEM \\\n\tB3.TEM \\\n\tBIB1.TEM \\\n\tBIB2.TEM \\\n\tBIB3.TEM \\\n\tBR1A.TEM \\\n\tBR1B.TEM \\\n\tBR1C.TEM \\\n\tBR2A.TEM \\\n\tBR2B.TEM \\\n\tBR2C.TEM \\\n\tBR3A.TEM \\\n\tBR3B.TEM \\\n\tBR3C.TEM \\\n\tBR3D.TEM \\\n\tBR3E.TEM \\\n\tBR3F.TEM \\\n\tBRIDGE1.TEM \\\n\tBRIDGE1D.TEM \\\n\tBRIDGE2.TEM \\\n\tBRIDGE2D.TEM \\\n\tCLEAR1.TEM \\\n\tCORPSE1.TEM \\\n\tCORPSE2.TEM \\\n\tCORPSE3.TEM \\\n\tCR1.TEM \\\n\tCR2.TEM \\\n\tCR3.TEM \\\n\tCR4.TEM \\\n\tCR5.TEM \\\n\tCR6.TEM \\\n\tD01.TEM \\\n\tD02.TEM \\\n\tD03.TEM \\\n\tD04.TEM \\\n\tD05.TEM \\\n\tD06.TEM \\\n\tD07.TEM \\\n\tD08.TEM \\\n\tD09.TEM \\\n\tD10.TEM \\\n\tD11.TEM \\\n\tD12.TEM \\\n\tD13.TEM \\\n\tD14.TEM \\\n\tD15.TEM \\\n\tD16.TEM \\\n\tD17.TEM \\\n\tD18.TEM \\\n\tD19.TEM \\\n\tD20.TEM \\\n\tD21.TEM \\\n\tD22.TEM \\\n\tD23.TEM \\\n\tD24.TEM \\\n\tD25.TEM \\\n\tD26.TEM \\\n\tD27.TEM \\\n\tD28.TEM \\\n\tD29.TEM \\\n\tD30.TEM \\\n\tD31.TEM \\\n\tD32.TEM \\\n\tD33.TEM \\\n\tD34.TEM \\\n\tD35.TEM \\\n\tD36.TEM \\\n\tD37.TEM \\\n\tD38.TEM \\\n\tD39.TEM \\\n\tD40.TEM \\\n\tD41.TEM \\\n\tD42.TEM \\\n\tD43.TEM \\\n\tD44.TEM \\\n\tD45.TEM \\\n\tFALLS1.TEM \\\n\tFALLS1A.TEM \\\n\tFALLS2.TEM \\\n\tFALLS2A.TEM \\\n\tFORD1.TEM \\\n\tFORD2.TEM \\\n\tGEM01.TEM \\\n\tGEM02.TEM \\\n\tGEM03.TEM \\\n\tGEM04.TEM \\\n\tGOLD01.TEM \\\n\tGOLD02.TEM \\\n\tGOLD03.TEM \\\n\tGOLD04.TEM \\\n\tHBOX.TEM \\\n\tMSLOMAKE.TEM \\\n\tHBOXMAKE.TEM \\\n\tMSLO.TEM \\\n\tP01.TEM \\\n\tP02.TEM \\\n\tP03.TEM \\\n\tP04.TEM \\\n\tP07.TEM \\\n\tP08.TEM \\\n\tP13.TEM \\\n\tP14.TEM \\\n\tRC01.TEM \\\n\tRC02.TEM \\\n\tRC03.TEM \\\n\tRC04.TEM \\\n\tRF01.TEM \\\n\tRF02.TEM \\\n\tRF03.TEM \\\n\tRF04.TEM \\\n\tRF05.TEM \\\n\tRF06.TEM \\\n\tRF07.TEM \\\n\tRF08.TEM \\\n\tRF09.TEM \\\n\tRF10.TEM \\\n\tRF11.TEM \\\n\tRV01.TEM \\\n\tRV02.TEM \\\n\tRV03.TEM \\\n\tRV04.TEM \\\n\tRV05.TEM \\\n\tRV06.TEM \\\n\tRV07.TEM \\\n\tRV08.TEM \\\n\tRV09.TEM \\\n\tRV10.TEM \\\n\tRV11.TEM \\\n\tRV12.TEM \\\n\tRV13.TEM \\\n\tRV14.TEM \\\n\tRV15.TEM \\\n\tS01.TEM \\\n\tS02.TEM \\\n\tS03.TEM \\\n\tS04.TEM \\\n\tS05.TEM \\\n\tS06.TEM \\\n\tS07.TEM \\\n\tS08.TEM \\\n\tS09.TEM \\\n\tS10.TEM \\\n\tS11.TEM \\\n\tS12.TEM \\\n\tS13.TEM \\\n\tS14.TEM \\\n\tS15.TEM \\\n\tS16.TEM \\\n\tS17.TEM \\\n\tS18.TEM \\\n\tS19.TEM \\\n\tS20.TEM \\\n\tS21.TEM \\\n\tS22.TEM \\\n\tS23.TEM \\\n\tS24.TEM \\\n\tS25.TEM \\\n\tS26.TEM \\\n\tS27.TEM \\\n\tS28.TEM \\\n\tS29.TEM \\\n\tS30.TEM \\\n\tS31.TEM \\\n\tS32.TEM \\\n\tS33.TEM \\\n\tS34.TEM \\\n\tS35.TEM \\\n\tS36.TEM \\\n\tS37.TEM \\\n\tS38.TEM \\\n\tSC1.TEM \\\n\tSC2.TEM \\\n\tSC3.TEM \\\n\tSC4.TEM \\\n\tSC5.TEM \\\n\tSC6.TEM \\\n\tSH01.TEM \\\n\tSH02.TEM \\\n\tSH03.TEM \\\n\tSH04.TEM \\\n\tSH05.TEM \\\n\tSH06.TEM \\\n\tSH07.TEM \\\n\tSH08.TEM \\\n\tSH09.TEM \\\n\tSH10.TEM \\\n\tSH11.TEM \\\n\tSH12.TEM \\\n\tSH13.TEM \\\n\tSH14.TEM \\\n\tSH15.TEM \\\n\tSH16.TEM \\\n\tSH17.TEM \\\n\tSH18.TEM \\\n\tSH19.TEM \\\n\tSH20.TEM \\\n\tSH21.TEM \\\n\tSH22.TEM \\\n\tSH23.TEM \\\n\tSH24.TEM \\\n\tSH25.TEM \\\n\tSH26.TEM \\\n\tSH27.TEM \\\n\tSH28.TEM \\\n\tSH29.TEM \\\n\tSH30.TEM \\\n\tSH31.TEM \\\n\tSH32.TEM \\\n\tSH33.TEM \\\n\tSH34.TEM \\\n\tSH35.TEM \\\n\tSH36.TEM \\\n\tSH37.TEM \\\n\tSH38.TEM \\\n\tSH39.TEM \\\n\tSH40.TEM \\\n\tSH41.TEM \\\n\tSH42.TEM \\\n\tSH43.TEM \\\n\tSH44.TEM \\\n\tSH45.TEM \\\n\tSH46.TEM \\\n\tSH47.TEM \\\n\tSH48.TEM \\\n\tSH49.TEM \\\n\tSH50.TEM \\\n\tSH51.TEM \\\n\tSH52.TEM \\\n\tSH53.TEM \\\n\tSH54.TEM \\\n\tSH55.TEM \\\n\tSH56.TEM \\\n\tT01.TEM \\\n\tT02.TEM \\\n\tT03.TEM \\\n\tT05.TEM \\\n\tT06.TEM \\\n\tT07.TEM \\\n\tT08.TEM \\\n\tT10.TEM \\\n\tT11.TEM \\\n\tT12.TEM \\\n\tT13.TEM \\\n\tT14.TEM \\\n\tT15.TEM \\\n\tT16.TEM \\\n\tT17.TEM \\\n\tTC01.TEM \\\n\tTC02.TEM \\\n\tTC03.TEM \\\n\tTC04.TEM \\\n\tTC05.TEM \\\n\tV01.TEM \\\n\tV02.TEM \\\n\tV03.TEM \\\n\tV04.TEM \\\n\tV05.TEM \\\n\tV06.TEM \\\n\tV07.TEM \\\n\tV08.TEM \\\n\tV09.TEM \\\n\tV10.TEM \\\n\tV11.TEM \\\n\tV12.TEM \\\n\tV13.TEM \\\n\tV14.TEM \\\n\tV15.TEM \\\n\tV16.TEM \\\n\tV17.TEM \\\n\tV18.TEM \\\n\tW1.TEM \\\n\tW2.TEM \\\n\tWC01.TEM \\\n\tWC02.TEM \\\n\tWC03.TEM \\\n\tWC04.TEM \\\n\tWC05.TEM \\\n\tWC06.TEM \\\n\tWC07.TEM \\\n\tWC08.TEM \\\n\tWC09.TEM \\\n\tWC10.TEM \\\n\tWC11.TEM \\\n\tWC12.TEM \\\n\tWC13.TEM \\\n\tWC14.TEM \\\n\tWC15.TEM \\\n\tWC16.TEM \\\n\tWC17.TEM \\\n\tWC18.TEM \\\n\tWC19.TEM \\\n\tWC20.TEM \\\n\tWC21.TEM \\\n\tWC22.TEM \\\n\tWC23.TEM \\\n\tWC24.TEM \\\n\tWC25.TEM \\\n\tWC26.TEM \\\n\tWC27.TEM \\\n\tWC28.TEM \\\n\tWC29.TEM \\\n\tWC30.TEM \\\n\tWC31.TEM \\\n\tWC32.TEM \\\n\tWC33.TEM \\\n\tWC34.TEM \\\n\tWC35.TEM \\\n\tWC36.TEM \\\n\tWC37.TEM \\\n\tWC38.TEM \\\n\n# Every temperate theater terrain file has a snow theater counterpart.\nSNOWFILES = $(TEMPERATEFILES:.TEM=.SNO)\n\n# Sound effects (Juvenile or Adult)\nSFX = \\\n\n# Generic wave files (never changes).\nWAVFILES = \\\n\tAACANON3.AUD \\\n\tBEEPSLCT.AUD \\\n\tBLEEP11.AUD \\\n\tBLEEP12.AUD \\\n\tBLEEP13.AUD \\\n\tBLEEP17.AUD \\\n\tBLEEP5.AUD \\\n\tBLEEP6.AUD \\\n\tBLEEP9.AUD \\\n\tBOMBIT1.AUD \\\n\tBUILD5.AUD \\\n\tBUZZY1.AUD \\       \n\tCANNON1.AUD \\\n\tCANNON2.AUD \\\n\tCASHDN1.AUD \\\n\tCASHTURN.AUD \\\n\tCASHUP1.AUD \\\n\tCHRONO2.AUD \\\n\tCHROTNK1.AUD \\\n\tCHUTE1.AUD \\\n\tCMON1.AUD \\\n\tCRMBLE2.AUD \\\n\tDEDMAN1.AUD \\\n\tDEDMAN10.AUD \\\n\tDEDMAN2.AUD \\\n\tDEDMAN3.AUD \\\n\tDEDMAN4.AUD \\\n\tDEDMAN5.AUD \\\n\tDEDMAN6.AUD \\\n\tDEDMAN7.AUD \\\n\tDEDMAN8.AUD \\\n\tDOGG5P.AUD \\\n\tDOGW3PX.AUD \\\n\tDOGW5.AUD \\\n\tDOGW6.AUD \\\n\tDOGW7.AUD \\\n\tDOGY1.AUD \\\n\tEAFFIRM1.AUD \\\n\tEENGIN1.AUD \\\n\tEINAH1.AUD \\\n\tEINOK1.AUD \\\n\tEINYES1.AUD \\\n\tEMOVOUT1.AUD \\\n\tEYESSIR1.AUD \\\n\tFIREBL3.AUD \\\n\tFIRETRT1.AUD \\\n\tFIXIT1.AUD \\\n\tGIRLOKAY.AUD \\\n\tGIRLYEAH.AUD \\\n\tGOTIT1.AUD \\\n\tGRENADE1.AUD \\\n\tGUN11.AUD \\\n\tGUN13.AUD \\\n\tGUN27.AUD \\\n\tGUN5.AUD \\\n\tGUYOKAY1.AUD \\\n\tGUYYEAH1.AUD \\\n\tH2OBOMB2.AUD \\\n\tHEAL2.AUD \\\n\tHYDROD1.AUD \\\n\tINVUL2.AUD \\\n\tIRONCUR9.AUD \\\n\tJBURN1.AUD \\\n\tJCHRGE1.AUD \\\n\tJCRISP1.AUD \\\n\tJDANCE1.AUD \\\n\tJJUICE1.AUD \\\n\tJJUMP1.AUD \\\n\tJLIGHT1.AUD \\\n\tJPOWER1.AUD \\\n\tJSHOCK1.AUD \\\n\tJYES1.AUD \\\n\tKABOOM1.AUD \\\n\tKABOOM12.AUD \\\n\tKABOOM15.AUD \\\n\tKABOOM22.AUD \\\n\tKABOOM25.AUD \\\n\tKABOOM30.AUD \\\n\tKEEPEM1.AUD \\\n\tLAUGH1.AUD \\\n\tLEFTY1.AUD \\\n\tMADCHRG2.AUD \\\n\tMADEXPLO.AUD \\\n\tMAFFIRM1.AUD \\\n\tMBOSS1.AUD \\\n\tMHEAR1.AUD \\\n\tMHOTDIG1.AUD \\\n\tMHOWDY1.AUD \\\n\tMHUH1.AUD \\\n\tMGUNINF1.AUD \\\n\tMINE1.AUD \\\n\tMINEBLO1.AUD \\\n\tMINELAY1.AUD \\\n\tMISSILE1.AUD \\\n\tMISSILE6.AUD \\\n\tMISSILE7.AUD \\\n\tMLAFF1.AUD \\\n\tMMOVOUT1.AUD \\\n\tMRESPON1.AUD \\\n\tMRISE1.AUD \\\n\tMWRENCH1.AUD \\\n\tMYEEHAW1.AUD \\\n\tMYES1.AUD \\\n\tMYESSIR1.AUD \\\n\tONIT1.AUD \\\n\tPILLBOX1.AUD \\\n\tPLACBLDG.AUD \\\n\tRABEEP1.AUD \\\n\tRADARDN1.AUD \\\n\tRADARON2.AUD \\\n\tRAMENU1.AUD \\\n\tROKROLL1.AUD \\\n\tSAFFIRM1.AUD \\\n\tSANDBAG2.AUD \\\n\tSCOLDY1.AUD \\\n\tSCOMND1.AUD \\\n\tSHKTROP1.AUD \\\n\tSILENCER.AUD \\\n\tSINDEED1.AUD \\\n\tSKING1.AUD \\\n\tSMOUT1.AUD \\\n\tSOKAY1.AUD \\\n\tSONPULSE.AUD \\\n\tSONWAY1.AUD \\\n\tSPLASH9.AUD \\\n\tSQUISHY2.AUD \\\n\tSUBSHOW1.AUD \\\n\tSWHAT1.AUD \\\n\tSYEAH1.AUD \\\n\tSYESSIR1.AUD \\\n\tTANDETH1.AUD \\\n\tTANK5.AUD \\\n\tTANK6.AUD \\\n\tTESLA1.AUD \\\n\tTORPEDO1.AUD \\\n\tTSLACHG2.AUD \\\n\tTUFFGUY1.AUD \\\n\tTURRET1.AUD \\\n\tWALLKIL2.AUD \\\n\tYEAH1.AUD \\\n\tYES1.AUD \\\n\tYO1.AUD \\\n\n# Vehicle responses\nRESPONSE1 = \\\n\tACKNO.AUD \\\n\tAFFIRM1.AUD \\\n\tAWAIT1.AUD \\\n\tREPORT1.AUD \\\n\tVEHIC1.AUD \\\n\tYESSIR1.AUD \\\n\n# Infantry responses\nRESPONSE2 = \\\n\tACKNO.AUD \\\n\tAFFIRM1.AUD \\\n\tAWAIT1.AUD \\\n\tNOPROB.AUD \\\n\tOVEROUT.AUD \\\n\tREADY.AUD \\\n\tREPORT1.AUD \\\n\tRITAWAY.AUD \\\n\tROGER.AUD \\\n\tUGOTIT.AUD \\\n\tYESSIR1.AUD \\\n\n#TSCOREFILES = \\\n#\tcps\\record.bin \\\n#\tWIN1.AUD \\\n#\tMAP1.AUD \\\n\nVARFILES = \\\n\nSCOREFILES = \\\n\tCREDITS.AUD  \\\n\tAWAIT.AUD    \\\n\tBIGF226M.AUD \\\n\tCRUS226M.AUD \\\n\tDENSE_R.AUD  \\\n\tFAC1226M.AUD \\\n\tFAC2226M.AUD \\\n\tFOGGER1A.AUD \\\n\tHELL226M.AUD \\\n\tMUD1A.AUD \\\n\tRADIO2.AUD \\\n\tROLLOUT.AUD \\\n\tRUN1226M.AUD \\\n\tSCORE.AUD \\\n\tSMSH226M.AUD \\\n\tSNAKE.AUD \\\n\tTERMINAT.AUD \\\n\tTREN226M.AUD \\\n\tTWIN.AUD \\\n\tVECTOR1A.AUD \\\n\tWORK226M.AUD \\\n\t2ND_HAND.AUD \\   \n\tARAZIOD.AUD \\   \n\tBACKSTAB.AUD \\\n\tCHAOS2.AUD \\ \n\tSHUT_IT.AUD \\   \n\tTWINMIX1.AUD \\   \n\tUNDER3.AUD \\   \n\tVR2.AUD \\\n\tBOG.AUD \\\n\tFLOAT_V2.AUD \\\n\tGLOOM.AUD \\\n\tGRNDWIRE.AUD \\\n\tRPT.AUD \\\n\tSEARCH.AUD \\\n\tTRACTION.AUD \\\n\tWASTELND.AUD \\\n\nSPEECHFILES = \\\n\tSTRCKIL1.AUD \\\n\tNOPOWR1.AUD \\\n\tSAVE1.AUD \\\n\tLOAD1.AUD \\\n\t10MINR.AUD \\\n\t1MINR.AUD \\\n\t1OBJMET1.AUD \\\n\t20MINR.AUD \\\n\t2MINR.AUD \\\n\t2OBJMET1.AUD \\\n\t30MINR.AUD \\\n\t3MINR.AUD \\\n\t3OBJMET1.AUD \\\n\t40MINR.AUD \\\n\t4MINR.AUD \\\n\t5MINR.AUD \\\n\tAAPPRO1.AUD \\\n\tAARIVE1.AUD \\\n\tAARIVE1.AUD \\\n\tAARRIVE1.AUD \\\n\tAARRIVN1.AUD \\\n\tAARRIVS1.AUD \\\n\tAARRIVW1.AUD \\\n\tAAVAIL1.AUD \\\n\tABLDGIN1.AUD \\\n\tAFALLEN1.AUD \\\n\tALAUNCH1.AUD \\\n\tAPREP1.AUD \\\n\tAREADY1.AUD \\\n\tARMORUP1.AUD \\\n\tASELECT1.AUD \\\n\tATLNCH1.AUD \\\n\tATPREP1.AUD \\\n\tAUNITL1.AUD \\\n\tBASEATK1.AUD \\\n\tBCT1.AUD \\\n\tBLDGINF1.AUD \\\n\tBLDGPRG1.AUD \\\n\tCANCLD1.AUD \\\n\tCHROCHR1.AUD \\\n\tCHRORDY1.AUD \\\n\tCHROYES1.AUD \\\n\tCMDCNTR1.AUD \\\n\tCNTLDED1.AUD \\\n\tCOMNDOF1.AUD \\\n\tCOMNDOR1.AUD \\\n\tCONSCMP1.AUD \\\n\tCONVLST1.AUD \\\n\tCONVYAP1.AUD \\\n\tCREDIT1.AUD \\\n\tENMYAPP1.AUD \\\n\tFIREPO1.AUD \\\n\tFLARE1.AUD \\\n\tFLAREE1.AUD \\\n\tFLAREN1.AUD \\\n\tFLARES1.AUD \\\n\tFLAREW1.AUD \\\n\tIRONCHG1.AUD \\\n\tIRONRDY1.AUD \\\n\tKOSYFRE1.AUD \\\n\tKOSYRES1.AUD \\\n\tLOPOWER1.AUD \\\n\tMERCF1.AUD \\\n\tMERCR1.AUD \\\n\tMISNLST1.AUD \\\n\tMISNWON1.AUD \\\n\tMTIMEIN1.AUD \\\n\tNAVYLST1.AUD \\\n\tNEWOPT1.AUD \\\n\tNOBUILD1.AUD \\\n\tNODEPLY1.AUD \\\n\tNOFUNDS1.AUD \\\n\tNOFUNDS1.AUD \\\n\tOBJMET1.AUD \\\n\tOBJNMET1.AUD \\\n\tOBJNRCH1.AUD \\\n\tOBJRCH1.AUD \\\n\tONHOLD1.AUD \\\n\tOPTERM1.AUD \\\n\tPRIBLDG1.AUD \\\n\tPROGRES1.AUD \\\n\tPULSE1.AUD \\\n\tREINFOR1.AUD \\\n\tREPAIR1.AUD \\\n\tREPAIR1.AUD \\\n\tSATLNCH1.AUD \\\n\tSILOND1.AUD \\\n\tSLCTTGT1.AUD \\\n\tSOVEFAL1.AUD \\\n\tSOVEMP1.AUD \\\n\tSOVFAPP1.AUD \\\n\tSOVFORC1.AUD \\\n\tSOVREIN1.AUD \\\n\tSPYPLN1.AUD \\\n\tSTRUCAP1.AUD \\\n\tSTRUSLD1.AUD \\\n\tTANYAF1.AUD \\\n\tTANYAR1.AUD \\\n\tTARGFRE1.AUD \\\n\tTARGRES1.AUD \\\n\tTIMERGO1.AUD \\\n\tTIMERNO1.AUD \\\n\tTRAIN1.AUD \\\n\tUNITFUL1.AUD \\\n\tUNITLST1.AUD \\\n\tUNITRDY1.AUD \\\n\tUNITREP1.AUD \\\n\tUNITSLD1.AUD \\\n\tUNITSPD1.AUD \\\n\tXPLOPLC1.AUD \\\n#\tABLDGC1.AUD \\\n#\tSOVBLDG1.AUD \\\n#\tSOVSTRC1.AUD \\\n#\tSOVUNTD1.AUD \\\n#\tAUNITD1.AUD \\\n#\tASTRUCD1.AUD \\\n\n#ALLIESVQ = \\\nDUMMYVQ = \\\n\tAAGUN.VQA \\\n\tAFTRMATH.VQA \\\n\tALLY1.VQA \\\n\tALLY10.VQA \\\n\tALLY10B.VQA \\\n\tALLY11.VQA \\\n\tALLY12.VQA \\\n\tALLY14.VQA \\\n\tALLY2.VQA \\\n\tALLY4.VQA \\\n\tALLY5.VQA \\\n\tALLY6.VQA \\\n\tALLY8.VQA \\\n\tALLY9.VQA \\\n\tALLYEND.VQA \\\n\tALLYMORF.VQA \\\n\tAPCESCPE.VQA \\\n\tASSESS.VQA \\\n\tBATTLE.VQA \\\n\t1BINOC.VQA \\\n\tBMAP.VQA \\\n\tBRDGTILT.VQA \\\n\tCRONTEST.VQA \\\n\tCRONFAIL.VQA \\\n\tDESTROYR.VQA \\\n\tDUD.VQA \\\n\tELEVATOR.VQA \\\n\tFLARE.VQA \\\n\tFROZEN.VQA \\\n\tGRVESTNE.VQA \\\n\tLANDING.VQA \\\n\tMASASSLT.VQA \\\n\tMCV.VQA \\\n\tMCV_LAND.VQA \\\n\tMONTPASS.VQA \\\n\tOILDRUM.VQA \\\n\tOVERRUN.VQA \\\n\tPROLOG.VQA \\\n\tREDINTRO.VQA \\\n\tSHIPSINK.VQA \\\n\tSHORBOM1.VQA \\\n\tSHORBOM2.VQA \\\n\tSHORBOMB.VQA \\\n\tSNOWBOMB.VQA \\\n\tSOVIET1.VQA \\\n\tSOVTSTAR.VQA \\\n\tSPY.VQA \\\n\tTANYA1.VQA \\\n\tTANYA2.VQA \\\n\tTOOFAR.VQA \\\n\tTRINITY.VQA \\\n#\tTRAILER.VQA \\\n\nSOVIETVQ = \\\n       \tAAGUN.VQA \\\n\tCRONFAIL.VQA \\\n\tAIRFIELD.VQA \\\n\tALLY1.VQA \\\n\tALLYMORF.VQA \\\n\tAVERTED.VQA \\\n\tBEACHEAD.VQA \\\n\tBMAP.VQA \\\n\tBOMBRUN.VQA \\\n\tCOUNTDWN.VQA \\\n\tDOUBLE.VQA \\\n\tDPTHCHRG.VQA \\\n\tEXECUTE.VQA \\\n\tFLARE.VQA \\\n\tLANDING.VQA \\\n\tMCVBRDGE.VQA \\\n\tMIG.VQA \\\n\tMOVINGIN.VQA \\\n\tMTNKFACT.VQA \\\n\tNUKESTOK.VQA \\\n\tONTHPRWL.VQA \\\n\tPERISCOP.VQA \\\n\tPROLOG.VQA \\\n\tRADRRAID.VQA \\\n\tREDINTRO.VQA \\\n\tSEARCH.VQA \\\n\tSFROZEN.VQA \\\n\tSITDUCK.VQA \\\n\tSLNTSRVC.VQA \\\n\tSNOWBOMB.VQA \\\n\tSNSTRAFE.VQA \\\n\tSOVBATL.VQA \\\n\tSOVCEMET.VQA \\\n\tSOVFINAL.VQA \\\n\tSOVIET1.VQA \\\n\tSOVIET10.VQA \\\n\tSOVIET11.VQA \\\n\tSOVIET12.VQA \\\n\tSOVIET13.VQA \\\n\tSOVIET14.VQA \\\n\tSOVIET2.VQA \\\n\tSOVIET3.VQA \\\n\tSOVIET4.VQA \\\n\tSOVIET5.VQA \\\n\tSOVIET6.VQA \\\n\tSOVIET7.VQA \\\n\tSOVIET8.VQA \\\n\tSOVIET9.VQA \\\n\tSOVMCV.VQA \\\n\tSOVTSTAR.VQA \\\n\tSPOTTER.VQA \\\n\tSTRAFE.VQA \\\n\tTAKE_OFF.VQA \\\n\tTESLA.VQA \\\n\tV2ROCKET.VQA \\\n#\tTRAILER.VQA \\\n\nALLIESVQ = \\\n\tAFTRMATH.VQA \\\n\tALLY1.VQA \\\n\tALLYMORF.VQA \\\n\tAPCESCPE.VQA \\\n BATTLE.VQA \\\n\tBMAP.VQA \\\t\n\tCRONFAIL.VQA \\\n DPTHCHRG.VQA \\\n\tEXECUTE.VQA \\\n\tFLARE.VQA \\\t\n\tFROZEN.VQA \\\n\tGRVESTNE.VQA \\\n\tLANDING.VQA \\\n\tMASASSLT.VQA \\\n NUKESTOK.VQA \\\n ONTHPRWL.VQA \\\n\tOVERRUN.VQA \\\n\tPROLOG.VQA \\\n\tREDINTRO.VQA \\\n\tSFROZEN.VQA \\\n SLNTSRVC.VQA \\\n\tSNOWBOMB.VQA \\\n SNOWBASE.VQA \\\n SOVMCV.VQA \\\n\tSNSTRAFE.VQA \\\n\tSOVBATL.VQA \\\n\tSOVCEMET.VQA \\\n\tSOVIET1.VQA \\\n\tSOVTSTAR.VQA \\\n\tSPY.VQA \\\n STRAFE.VQA \\\n\tTESLA.VQA \\\n\tTOOFAR.VQA \\\n\tTRINITY.VQA \\\n\tV2ROCKET.VQA \\\t\t\n#\tANTEND.VQA \\\n#\tANTINTRO.VQA \\\n\t\n\n\n# Files required for hires/Win95 version only\n#\n# This mix file is not cached\n#\nNOCACHEHIRESFILES= \\\n\tENGLISH.VQA \\\n\t$(ALLIESVQ:.VQA=.VQP) \\\n\t$(SOVIETVQ:.VQA=.VQP) \\\n       \n\nLINTOBJECTS1 = $(OBJECTS:,=)\nLINTOBJECTS = $(LINTOBJECTS1:.OBJ=.LOB)\n\n# Mixfiles that should reside on the CD-ROM drive.\nCD1MIXFILES = \\\n\tCONQUER.MIX \\\n\t\n\n\n# Mixfiles that should reside on the hard drive.\nLOCALMIXFILES = \\\n\tEDITOR.MIX \\\n\tHIRES.MIX \\\n\tLOCAL.MIX \\\n\tLORES.MIX \\\n\tNCHIRES.MIX \\\n\tSPEECH.MIX \\\n\t\n\n# Mixfiles as they appear on the CD and hard drive.\n\n\n\n# Ant assets SOME ASSETS ARE HERE FOR OVERRIDING\nEXPANDFILES= \\\n\tANT1.SHP \\\n\tANT2.SHP \\\n\tANT3.SHP \\\n\tQUEE.SHP \\\n\tCREDITS.ENG \\\n\tHILL01.TEM \\\n\tANTBITE.AUD \\\n\tANTDIE.AUD \\\n\tANTDIE.SHP \\\n\tLAR1.SHP \\\n\tLAR2.SHP \\\n\tTITLE.PCX \\\t\t\t\t\t\t\t  \n\tMISSION.INI \\\n\tBUZZY1.AUD \\       \n\tSTAVCMDR.AUD \\     \n\tSTAVCRSE.AUD \\     \n\tSTAVYES.AUD \\      \n\tSTAVMOV.AUD \\\n\tCONQUER.ENG \\   \n\tRAMBO1.AUD \\\n\tRAMBO2.AUD \\\n\tRAMBO3.AUD \\\n\tTITLE.CPS \\\n\tTUTORIAL.INI \\\n\tBMAP.VQP \\\n\tANTEND.VQP \\\n\tANTINTRO.VQP \\\n\n# Aftermath expansion files\nEXPAND2FILES= \\\n\tCARR.SHP \\\n\n\n\n#############################################################\n# Rebuilds all the mixfiles.\t\t\t\t  \npackfiles:\talways $(PACKFILES)\n\nalways:\n\tcopy f:\\projects\\c&c0\\editor\\english\\*.mix $(.path.mix) /u\n\n\n####################################################################\n# All mixfiles that exist on the CD-ROM are embedded within this mega-mixfile.\n$(.path.cd1)MAIN.MIX: $(CD1MIXFILES)\n\tUTILS\\MIXFILE -k -I$(.path.mix) &&!\n\t$**\n! $(.path.cd1)$&.mix\n\n\n\n\n####################################################################\n# These are the various sub-mixfiles.\nCONQUER.MIX: $(CONQUERFILES) $(CACHEMAP) .\\key.ini\n\tUTILS\\MIXFILE -k -h -I$(.path.cps) &&!\n\t$(CONQUERFILES) $(CACHEMAP)\n! $(.path.mix)$&.mix\n\nTEMPERAT.MIX: $(TEMPERATEFILES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -I$(.path.cps) &&!\n\t$(TEMPERATEFILES)\n! $(.path.mix)$&.mix\n\nSNOW.MIX: $(SNOWFILES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -I$(.path.cps) &&!\n\t$(SNOWFILES)\n! $(.path.mix)$&.mix\n\nINTERIOR.MIX: $(INTERIORFILES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -I$(.path.cps) &&!\n\t$(INTERIORFILES)\n! $(.path.mix)$&.mix\n\nGENERAL.MIX: $(GENERALFILES) $(GENERALMAPFILES) $(NETMAPFILES) $(MAPFILES) .\\key.ini\n\tUTILS\\MIXFILE -k -I$(.path.cps) -I$(.path.ini) &&!\n\t$(GENERALFILES) $(GENERALMAPFILES) $(NETMAPFILES) $(MAPFILES)\n! $(.path.mix)$&.mix\n\nSCORES.MIX: $(SCOREFILES)\n\tUTILS\\MIXFILE -k -I$(.path.cps) -I$(.path.ini) &&!\n\t$**\n! $(.path.mix)$&.mix\n\nSOUNDS.MIX: $(WAVFILES) $(SFX)\n\tUTILS\\MIXFILE -h -k -EA60=V00 -EA61=V01 -EA62=V02 -EA63=V03 -I$(.path.aud) &&!\n\t$**\n! $(.path.mix)$&.mix\n\nRUSSIAN.MIX: $(RESPONSE1:.AUD=.R00) $(RESPONSE2:.AUD=.R01) $(RESPONSE1:.AUD=.R02) $(RESPONSE2:.AUD=.R03)\n\tUTILS\\MIXFILE -h -k -I$(.path.aud) &&!\n\t$**\n! $(.path.mix)$&.mix\n\nLIMITED.MIX: BLEEP11.AUD\n\tUTILS\\MIXFILE -h -k -I$(.path.aud) &&!\n\t$**\n! $(.path.mix)$&.mix\n\nALLIES.MIX: $(RESPONSE1:.AUD=.V00) $(RESPONSE2:.AUD=.V01) $(RESPONSE1:.AUD=.V02) $(RESPONSE2:.AUD=.V03)\n\tUTILS\\MIXFILE -h -k -I$(.path.aud) &&!\n\t$**\n! $(.path.mix)$&.mix\n\nMOVIES1.MIX: $(ALLIESVQ)\n\tUTILS\\MIXFILE -k -I$(.path.vqa) &&!\n\t$**\n! $(.path.mix)$&.mix\n\n\n\n\n\nNCHIRES.MIX: $(NOCACHEHIRESFILES:.SHP=.HI)\n\tUTILS\\MIXFILE -k -I$(.path.vqp) -I$(.path.cps) &&!\n\t$(NOCACHEHIRESFILES)\n! $(.path.mix)$&.mix\n\nLOCAL.MIX: $(LOCALFILES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -E.A6=.AUD -I$(.path.ini) -I$(.path.txt) -I$(.path.cps) &&!\n\t$(LOCALFILES)\n! $(.path.mix)$&.mix\n\nLORES.MIX: $(LOHILORES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -E.LOW=.SHP -E.LNT=.FNT -I$(.path.cps) &&!\n\t$(LOHILORES)\n! $(.path.mix)$&.mix\n\nHIRES.MIX: $(HIRESFILES:.SHP=.HI) $(HIHILORES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -E.HI=.SHP -E.HNT=.FNT -I$(.path.cps) &&!\n\t$(HIRESFILES:.SHP=.HI) $(HIHILORES)\n! $(.path.mix)$&.mix\n\nLORES1.MIX: $(LOHILORES1) .\\key.ini\n\tUTILS\\MIXFILE -h -k -E.LOW=.SHP -E.LNT=.FNT -I$(.path.cps) &&!\n\t$(LOHILORES1)\n! $(.path.mix)$&.mix\n\nHIRES1.MIX: $(HIHILORES1) .\\key.ini\n\tUTILS\\MIXFILE -h -k -E.HI=.SHP -E.HNT=.FNT -I$(.path.cps) &&!\n\t$(HIHILORES1)\n! $(.path.mix)$&.mix\n\nSPEECH.MIX: $(SPEECHFILES)\n\tUTILS\\MIXFILE -k -I$(.path.aud) &&!\n\t$**\n! $(.path.mix)$&.mix\n\n\nEXPAND.MIX: $(EXPANDFILES)\t\t\t   \n\tUTILS\\MIXFILE -k  -I$(.path.mix)  &&!\n\t$**\n! $(.path.mix)$&.mix\n\nEXPAND2.MIX: $(EXPAND2FILES)\t\t\t   \n\tUTILS\\MIXFILE -k  -I$(.path.mix)  &&!\n\t$**\n! $(.path.mix)$&.mix\n\n#############################################################\n# Special rule to create the mouse shape (which must be a shape file)\nmouse.hi:\t$(.path.anm)hires\\mouse.anm\n\t-utils\\makeshps $(.path.lbm)palettes\\temperat.lbm &&!\n &$(.path.anm)hires\\mouse.anm;\n end;\n! $(.path.hi)$&.hi $(SHAPEBUFFSIZE)\n\n# Special rule to create the mouse shape (which must be a shape file)\nmouse.low:\t$(.path.anm)lores\\mouse.anm\n\t-utils\\makeshps $(.path.lbm)palettes\\temperat.lbm &&!\n &$(.path.anm)lores\\mouse.anm;\n end;\n! $(.path.low)$&.low $(SHAPEBUFFSIZE)\n\n\n#############################################################\n# Special build rule for radar animations so that they won't.\n#\nNATORADR.HI: $(.path.anm)hires\\NATORADR.ANM\n\tutils\\newkeyf $** $(.path.hi)$&.hi -l -k\n\nUSSRRADR.HI: $(.path.anm)hires\\USSRRADR.ANM\n\tutils\\newkeyf $** $(.path.hi)$&.hi -l -k\n\nNATORADR.LOW: $(.path.anm)lores\\NATORADR.ANM\n\tutils\\newkeyf $** $(.path.low)$&.low -l -k\n\nUSSRRADR.LOW: $(.path.anm)lores\\USSRRADR.ANM\n\tutils\\newkeyf $** $(.path.low)$&.low -l -k\n\n\n#############################################################\n# Debug text file creation.\ndebug.eng:\tdebug.txt\n\tutils\\textmake -b1000 eng\\$&.txt $(.path.eng)$&.eng $&.h\n\n\n"
  },
  {
    "path": "CODE/ADATA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/ADATA.CPP 3     3/07/97 4:27p Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ADATA.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 30, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 9, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   AnimTypeClass::AnimTypeClass -- Constructor for animation types.                          *\n *   AnimTypeClass::One_Time -- Performs one time action for animation types.                  *\n *   AnimTypeClass::Init -- Load any animation artwork that is theater specific.               *\n *   Anim_Name -- Fetches the ASCII name of the animation type specified.                      *\n *   AnimTypeClass::As_Reference -- Fetch a reference to the animation type specified.         *\n *   AnimTypeClass::Init_Heap -- Initialize the animation type system.                         *\n *   AnimTypeClass::operator new -- Allocate an animation type object from private pool.       *\n *   AnimTypeClass::operator delete -- Returns an anim type class object back to the pool.     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\nstatic AnimTypeClass const AtomBomb(\n\tANIM_ATOM_BLAST,\t\t\t\t\t\t// Animation number.\n\t\"ATOMSFX\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t72,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t19,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const SputDoor(\n\tANIM_SPUTDOOR,\t\t\t\t\t\t\t// Animation number.\n\t\"SPUTDOOR\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t42,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\n// Electrocution death anim from Tesla coil\nstatic AnimTypeClass const ElectricDie(\n\tANIM_ELECT_DIE,\t\t\t\t\t\t// Animation number.\n\t\"ELECTRO\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t16,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t5,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_FIRE_MED\n);\n\n// Electrocution death anim from Tesla coil for dog\nstatic AnimTypeClass const DogElectricDie(\n\tANIM_DOG_ELECT_DIE,\t\t\t\t\t// Animation number.\n\t\"ELECTDOG\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t17,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t5,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_FIRE_MED\n);\n\nstatic AnimTypeClass const SAMN(\n\tANIM_SAM_N,\t\t\t\t\t\t\t\t// Animation number.\n\t\"SAMFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t55,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18*0,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t18,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const SAMNW(\n\tANIM_SAM_NW,\t\t\t\t\t\t\t// Animation number.\n\t\"SAMFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t55,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t22,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18*1,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t18,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const SAMW(\n\tANIM_SAM_W,\t\t\t\t\t\t\t\t// Animation number.\n\t\"SAMFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t55,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t40,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18*2,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t18,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const SAMSW(\n\tANIM_SAM_SW,\t\t\t\t\t\t\t// Animation number.\n\t\"SAMFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t55,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t58,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18*3,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t18,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const SAMS(\n\tANIM_SAM_S,\t\t\t\t\t\t\t\t// Animation number.\n\t\"SAMFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t55,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t76,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18*4,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t18,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const SAMSE(\n\tANIM_SAM_SE,\t\t\t\t\t\t\t// Animation number.\n\t\"SAMFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t55,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t94,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18*5,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t18,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const SAME(\n\tANIM_SAM_E,\t\t\t\t\t\t\t\t// Animation number.\n\t\"SAMFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t55,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t112,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18*6,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t18,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const SAMNE(\n\tANIM_SAM_NE,\t\t\t\t\t\t\t// Animation number.\n\t\"SAMFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t55,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t130,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18*7,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t18,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const LZSmoke(\n\tANIM_LZ_SMOKE,\t\t\t\t\t\t// Animation number.\n\t\"SMOKLAND\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t32,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t72,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t72,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t91,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t255,\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\n/*\n**\tFlammable object burning animations. Primarily used on trees and buildings.\n*/\nstatic AnimTypeClass const BurnSmall(\n\tANIM_BURN_SMALL,\t\t\t\t\t\t// Animation number.\n\t\"BURN-S\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t11,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t13,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 32),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t30,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t62,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const BurnMed(\n\tANIM_BURN_MED,\t\t\t\t\t\t\t// Animation number.\n\t\"BURN-M\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t14,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t13,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 16),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t30,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t62,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const BurnBig(\n\tANIM_BURN_BIG,\t\t\t\t\t\t\t// Animation number.\n\t\"BURN-L\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t23,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t13,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 10),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t30,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t62,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\n/*\n**\tFlammable object burning animations that trail into smoke. Used for\n**\tbuildings and the gunboat.\n*/\nstatic AnimTypeClass const OnFireSmall(\n\tANIM_ON_FIRE_SMALL,\t\t\t\t\t// Animation number.\n\t\"BURN-S\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t11,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t13,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 32),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t30,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t62,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_SMOKE_M\n);\nstatic AnimTypeClass const OnFireMed(\n\tANIM_ON_FIRE_MED,\t\t\t\t\t\t// Animation number.\n\t\"BURN-M\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t14,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t13,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 16),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t30,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t62,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_ON_FIRE_SMALL\n);\nstatic AnimTypeClass const OnFireBig(\n\tANIM_ON_FIRE_BIG,\t\t\t\t\t\t// Animation number.\n\t\"BURN-L\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t23,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t13,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 10),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t30,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t62,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_ON_FIRE_MED\n);\nstatic AnimTypeClass const Parachute(\n\tANIM_PARACHUTE,\t\t\t\t\t\t// Animation number.\n\t\"PARACH\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t32,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t15,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t7,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Loopback frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t15,\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const ParaBomb(\n\tANIM_PARA_BOMB,\t\t\t\t\t\t// Animation number.\n\t\"PARABOMB\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t32,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t8,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t7,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Loopback frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t15,\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const FBall1(\n\tANIM_FBALL1,\t\t\t\t\t\t\t// Animation number.\n\t\"FBALL1\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t67,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_KABOOM25,\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Frag1(\n\tANIM_FRAG1,\t\t\t\t\t\t\t\t// Animation number.\n\t\"FRAG1\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t45,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Forms a crater?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_KABOOM30,\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const VehHit1(\n\tANIM_VEH_HIT1,\t\t\t\t\t\t\t// Animation number.\n\t\"VEH-HIT1\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t30,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Forms a crater?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_KABOOM25,\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const VehHit2(\n\tANIM_VEH_HIT2,\t\t\t\t\t\t\t// Animation number.\n\t\"VEH-HIT2\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t21,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Forms a crater?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_KABOOM12,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const VehHit3(\n\tANIM_VEH_HIT3,\t\t\t\t\t\t\t// Animation number.\n\t\"VEH-HIT3\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t19,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_KABOOM12,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const ArtExp1(\n\tANIM_ART_EXP1,\t\t\t\t\t\t\t// Animation number.\n\t\"ART-EXP1\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t41,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_KABOOM22,\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Napalm1(\n\tANIM_NAPALM1,\t\t\t\t\t\t\t// Animation number.\n\t\"NAPALM1\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t21,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t5,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_FIRE_EXPLODE,\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Napalm2(\n\tANIM_NAPALM2,\t\t\t\t\t\t\t// Animation number.\n\t\"NAPALM2\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t41,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t5,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_FIRE_EXPLODE,\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Napalm3(\n\tANIM_NAPALM3,\t\t\t\t\t\t\t// Animation number.\n\t\"NAPALM3\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t78,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t5,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_FIRE_LAUNCH,\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const SmokePuff(\n\tANIM_SMOKE_PUFF,\t\t\t\t\t\t// Animation number.\n\t\"SMOKEY\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t24,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const FireBallFade(\n\tANIM_FBALL_FADE,\t\t\t\t\t\t// Animation number.\n\t\"FB2\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t24,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Piff(\n\tANIM_PIFF,\t\t\t\t\t\t\t\t// Animation number.\n\t\"PIFF\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t13,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const PiffPiff(\n\tANIM_PIFFPIFF,\t\t\t\t\t\t\t// Animation number.\n\t\"PIFFPIFF\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t20,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Fire3(\n\tANIM_FIRE_SMALL,\t\t\t\t\t\t// Animation number.\n\t\"FIRE3\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t23,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 32),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Fire1(\n\tANIM_FIRE_MED2,\t\t \t\t\t\t// Animation number.\n\t\"FIRE1\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t23,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 16),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Fire4(\n\tANIM_FIRE_TINY,\t\t \t\t\t\t// Animation number.\n\t\"FIRE4\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t7,\t\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 32),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Fire2(\n\tANIM_FIRE_MED,\t\t\t\t\t\t\t// Animation number.\n\t\"FIRE2\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t23,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 16),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const OilFieldBurn(\n\tANIM_OILFIELD_BURN,\t\t\t\t\t// Animation number.\n\t\"FLMSPT\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t42,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t58,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t33,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t99,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t66,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t65535,\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Gunfire(\n\tANIM_MUZZLE_FLASH,\t\t\t\t\t// Animation number.\n\t\"GUNFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t16,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const SmokeM(\n\tANIM_SMOKE_M,\t\t\t\t\t\t\t// Animation number.\n\t\"SMOKE_M\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t28,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t30,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t67,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Loopback frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\n/*\n**\tMini-gun fire effect -- used by guard towers.\n*/\nstatic AnimTypeClass const GUNN(\n\tANIM_GUN_N,\t\t\t\t\t\t\t\t// Animation number.\n\t\"MINIGUN\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t18,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const GUNNW(\n\tANIM_GUN_NW,\t\t\t\t\t\t\t// Animation number.\n\t\"MINIGUN\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t18,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const GUNW(\n\tANIM_GUN_W,\t\t\t\t\t\t\t\t// Animation number.\n\t\"MINIGUN\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t18,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t12,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const GUNSW(\n\tANIM_GUN_SW,\t\t\t\t\t\t\t// Animation number.\n\t\"MINIGUN\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t18,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const GUNS(\n\tANIM_GUN_S,\t\t\t\t\t\t\t\t// Animation number.\n\t\"MINIGUN\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t18,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t24,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const GUNSE(\n\tANIM_GUN_SE,\t\t\t\t\t\t\t// Animation number.\n\t\"MINIGUN\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t18,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t30,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const GUNE(\n\tANIM_GUN_E,\t\t\t\t\t\t\t\t// Animation number.\n\t\"MINIGUN\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t18,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t36,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const GUNNE(\n\tANIM_GUN_NE,\t\t\t\t\t\t\t// Animation number.\n\t\"MINIGUN\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t18,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t42,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const CDeviator(\n\tANIM_CRATE_DEVIATOR,\t\t\t\t\t// Animation number.\n\t\"DEVIATOR\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\n\nstatic AnimTypeClass const CrateArmor(\n\tANIM_CRATE_ARMOR,\t\t\t\t\t\t// Animation number.\n\t\"ARMOR\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const CrateSpeed(\n\tANIM_CRATE_SPEED,\t\t\t\t\t\t// Animation number.\n\t\"SPEED\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\n\nstatic AnimTypeClass const CrateFPower(\n\tANIM_CRATE_FPOWER,\t\t\t\t\t// Animation number.\n\t\"FPOWER\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const CrateTQuake(\n\tANIM_CRATE_TQUAKE,\t\t\t\t\t// Animation number.\n\t\"TQUAKE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\n\nstatic AnimTypeClass const CDollar(\n\tANIM_CRATE_DOLLAR,\t\t\t\t\t// Animation number.\n\t\"DOLLAR\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const CEarth(\n\tANIM_CRATE_EARTH,\t\t\t\t\t\t// Animation number.\n\t\"EARTH\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const CEmpulse(\n\tANIM_CRATE_EMPULSE,\t\t\t\t\t// Animation number.\n\t\"EMPULSE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const CInvun(\n\tANIM_CRATE_INVUN,\t\t\t\t\t\t// Animation number.\n\t\"INVUN\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const CMine(\n\tANIM_CRATE_MINE,\t\t\t\t\t\t// Animation number.\n\t\"MINE\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const CRapid(\n\tANIM_CRATE_RAPID,\t\t\t\t\t\t// Animation number.\n\t\"RAPID\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const CStealth(\n\tANIM_CRATE_STEALTH,\t\t\t\t\t// Animation number.\n\t\"STEALTH2\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const ChronoBox(\n\tANIM_CHRONO_BOX,\t\t\t\t\t\t// Animation number.\n\t\"CHRONBOX\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const GPSBox(\n\tANIM_GPS_BOX,\t\t\t\t\t\t\t// Animation number.\n\t\"GPSBOX\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const InvulBox(\n\tANIM_INVUL_BOX,\t\t\t\t\t\t// Animation number.\n\t\"INVULBOX\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const ParaBox(\n\tANIM_PARA_BOX,\t\t\t\t\t\t\t// Animation number.\n\t\"PARABOX\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const SonarBox(\n\tANIM_SONAR_BOX,\t\t\t\t\t\t// Animation number.\n\t\"SONARBOX\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\n\nstatic AnimTypeClass const CMissile(\n\tANIM_CRATE_MISSILE,\t\t\t\t\t// Animation number.\n\t\"MISSILE2\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\n\nstatic AnimTypeClass const MoveFlash(\n\tANIM_MOVE_FLASH,\t\t\t\t\t\t\t// Animation number.\n\t\"MOVEFLSH\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t24,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\n\nstatic AnimTypeClass const Corpse1(\n\tANIM_CORPSE1,\t\t\t\t\t\t\t// Animation number.\n\t\"CORPSE1\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t24,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t15,\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Corpse2(\n\tANIM_CORPSE2,\t\t\t\t\t\t\t// Animation number.\n\t\"CORPSE2\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t24,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t15,\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Corpse3(\n\tANIM_CORPSE3,\t\t\t\t\t\t\t// Animation number.\n\t\"CORPSE3\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t24,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t15,\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Twinkle1(\n\tANIM_TWINKLE1,\t\t\t\t\t\t\t// Animation number.\n\t\"TWINKLE1\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t8,\t\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const Twinkle2(\n\tANIM_TWINKLE2,\t\t\t\t\t\t\t// Animation number.\n\t\"TWINKLE2\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t8,\t\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const Twinkle3(\n\tANIM_TWINKLE3,\t\t\t\t\t\t\t// Animation number.\n\t\"TWINKLE3\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t8,\t\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const Flak(\n\tANIM_FLAK,\t\t\t\t\t\t\t\t// Animation number.\n\t\"FLAK\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t8,\t\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t7,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const WaterExp1(\n\tANIM_WATER_EXP1,\t\t\t\t\t\t// Animation number.\n\t\"H2O_EXP1\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t64,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_SPLASH,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const WaterExp2(\n\tANIM_WATER_EXP2,\t\t\t\t\t\t// Animation number.\n\t\"H2O_EXP2\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t40,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_SPLASH,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const WaterExp3(\n\tANIM_WATER_EXP3,\t\t\t\t\t\t// Animation number.\n\t\"H2O_EXP3\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t32,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_SPLASH,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\n\nstatic AnimTypeClass const MineExp1(\n\tANIM_MINE_EXP1,\t\t\t\t\t\t// Animation number.\n\t\"VEH-HIT2\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t21,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_MINEBLOW,\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\n#ifdef FIXIT_ANTS\nstatic AnimTypeClass const AntDeath(\n\tANIM_ANT_DEATH,\t\t\t\t\t\t// Animation number.\n\t\"ANTDIE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t28,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_ANTDIE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n#endif\n\n/***********************************************************************************************\n * AnimTypeClass::AnimTypeClass -- Constructor for animation types.                            *\n *                                                                                             *\n *    This is the constructor for static objects that elaborate the various animation types    *\n *    allowed in the game. Each animation in the game is of one of these types.                *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nAnimTypeClass::AnimTypeClass(\n\t\tAnimType anim,\n\t\tchar const * name,\n\t\tint size,\n\t\tint biggest,\n\t\tbool istheater,\n\t\tbool isnormal,\n\t\tbool iswhitetrans,\n\t\tbool isscorcher,\n\t\tbool iscrater,\n\t\tbool issticky,\n\t\tbool ground,\n\t\tbool istrans,\n\t\tbool isflame,\n\t\tfixed damage,\n\t\tint delaytime,\n\t\tint start,\n\t\tint loopstart,\n\t\tint loopend,\n\t\tint stages,\n\t\tint loops,\n\t\tVocType soundid,\n\t\tAnimType chainto) :\n\tObjectTypeClass(RTTI_ANIMTYPE,\n\t\t\tint(anim),\n\t\t\ttrue,\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t\ttrue,\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t\tTXT_NONE,\n\t\t\tname\n\t\t\t),\n\tIsNormalized(isnormal),\n\tIsGroundLayer(ground),\n\tIsTranslucent(istrans),\n\tIsWhiteTrans(iswhitetrans),\n\tIsFlameThrower(isflame),\n\tIsScorcher(isscorcher),\n\tIsCraterForming(iscrater),\n\tIsSticky(issticky),\n\tIsTheater(istheater),\n\tType(anim),\n\tSize(size),\n\tBiggest(biggest),\n\tDamage(damage),\n\tDelay(delaytime),\n\tStart(start),\n\tLoopStart(loopstart),\n\tLoopEnd(loopend),\n\tStages(stages),\n\tLoops(loops),\n\tSound(soundid),\n\tChainTo(chainto)\n{\n}\n\n\n/***********************************************************************************************\n * AnimTypeClass::operator new -- Allocate an animation type object from private pool.         *\n *                                                                                             *\n *    This routine will allocate an animation type class object.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the newly allocated anim type object. If no anim type    *\n *          could be allocated, then NULL is returned.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * AnimTypeClass::operator new(size_t)\n{\n\treturn(AnimTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * AnimTypeClass::operator delete -- Returns an anim type class object back to the pool.       *\n *                                                                                             *\n *    This will return the anim type class object back to the memory pool from whence it was   *\n *    previously allocated.                                                                    *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to the anim type class object to return to the memory pool.    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimTypeClass::operator delete(void * pointer)\n{\n\tAnimTypes.Free((AnimTypeClass *)pointer);\n}\n\n\n/***********************************************************************************************\n * AnimTypeClass::Init_Heap -- Initialize the animation type system.                           *\n *                                                                                             *\n *    This routine is called to initialize the animation type class heap. It allocates all     *\n *    known animation types.                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese anim type class objects must be allocated in the exact order that they\n\t**\tare specified in the AnimType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew AnimTypeClass(FBall1);\n\tnew AnimTypeClass(FireBallFade);\n\tnew AnimTypeClass(Frag1);\n\tnew AnimTypeClass(VehHit1);\n\tnew AnimTypeClass(VehHit2);\n\tnew AnimTypeClass(VehHit3);\n\tnew AnimTypeClass(ArtExp1);\n\tnew AnimTypeClass(Napalm1);\n\tnew AnimTypeClass(Napalm2);\n\tnew AnimTypeClass(Napalm3);\n\tnew AnimTypeClass(SmokePuff);\n\tnew AnimTypeClass(Piff);\n\tnew AnimTypeClass(PiffPiff);\n\tnew AnimTypeClass(Fire3);\n\tnew AnimTypeClass(Fire2);\n\tnew AnimTypeClass(Fire1);\n\tnew AnimTypeClass(Fire4);\n\tnew AnimTypeClass(Gunfire);\n\tnew AnimTypeClass(SmokeM);\n\tnew AnimTypeClass(BurnSmall);\n\tnew AnimTypeClass(BurnMed);\n\tnew AnimTypeClass(BurnBig);\n\tnew AnimTypeClass(OnFireSmall);\n\tnew AnimTypeClass(OnFireMed);\n\tnew AnimTypeClass(OnFireBig);\n\tnew AnimTypeClass(SAMN);\n\tnew AnimTypeClass(SAMNE);\n\tnew AnimTypeClass(SAME);\n\tnew AnimTypeClass(SAMSE);\n\tnew AnimTypeClass(SAMS);\n\tnew AnimTypeClass(SAMSW);\n\tnew AnimTypeClass(SAMW);\n\tnew AnimTypeClass(SAMNW);\n\tnew AnimTypeClass(GUNN);\n\tnew AnimTypeClass(GUNNE);\n\tnew AnimTypeClass(GUNE);\n\tnew AnimTypeClass(GUNSE);\n\tnew AnimTypeClass(GUNS);\n\tnew AnimTypeClass(GUNSW);\n\tnew AnimTypeClass(GUNW);\n\tnew AnimTypeClass(GUNNW);\n\tnew AnimTypeClass(LZSmoke);\n\tnew AnimTypeClass(CDeviator);\n\tnew AnimTypeClass(CDollar);\n\tnew AnimTypeClass(CEarth);\n\tnew AnimTypeClass(CEmpulse);\n\tnew AnimTypeClass(CInvun);\n\tnew AnimTypeClass(CMine);\n\tnew AnimTypeClass(CRapid);\n\tnew AnimTypeClass(CStealth);\n\tnew AnimTypeClass(CMissile);\n\tnew AnimTypeClass(MoveFlash);\n\tnew AnimTypeClass(OilFieldBurn);\n\tnew AnimTypeClass(ElectricDie);\n\tnew AnimTypeClass(Parachute);\n\tnew AnimTypeClass(DogElectricDie);\n\tnew AnimTypeClass(Corpse1);\n\tnew AnimTypeClass(Corpse2);\n\tnew AnimTypeClass(Corpse3);\n\tnew AnimTypeClass(SputDoor);\n\tnew AnimTypeClass(AtomBomb);\n\tnew AnimTypeClass(ChronoBox);\n\tnew AnimTypeClass(GPSBox);\n\tnew AnimTypeClass(InvulBox);\n\tnew AnimTypeClass(ParaBox);\n\tnew AnimTypeClass(SonarBox);\n\tnew AnimTypeClass(Twinkle1);\n\tnew AnimTypeClass(Twinkle2);\n\tnew AnimTypeClass(Twinkle3);\n\tnew AnimTypeClass(Flak);\n\tnew AnimTypeClass(WaterExp1);\n\tnew AnimTypeClass(WaterExp2);\n\tnew AnimTypeClass(WaterExp3);\n\tnew AnimTypeClass(CrateArmor);\n\tnew AnimTypeClass(CrateSpeed);\n\tnew AnimTypeClass(CrateFPower);\n\tnew AnimTypeClass(CrateTQuake);\n\tnew AnimTypeClass(ParaBomb);\n\tnew AnimTypeClass(MineExp1);\n#ifdef FIXIT_ANTS\n\tnew AnimTypeClass(AntDeath);\n#endif\n}\n\n/***********************************************************************************************\n * AnimTypeClass::One_Time -- Performs one time action for animation types.                    *\n *                                                                                             *\n *    This will load the animation shape data. It is called by the game initialization         *\n *    process.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine should be called ONLY once.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimTypeClass::One_Time(void)\n{\n\tfor (AnimType index = ANIM_FIRST; index < ANIM_COUNT; index++) {\n\t\tchar fullname[_MAX_FNAME+_MAX_EXT];\n\n\t\tAnimTypeClass const & anim = As_Reference(index);\n\n\t\tif (!anim.IsTheater) {\n\n\t\t\t_makepath(fullname, NULL, NULL, As_Reference(index).IniName, \".SHP\");\n\n\t\t\t#ifndef NDEBUG\n\t\t\t\tRawFileClass file(fullname);\n\t\t\t\tif (file.Is_Available()) {\n\t\t\t\t\t((void const *&)As_Reference(index).ImageData) = Load_Alloc_Data(file);\n\t\t\t\t} else {\n\t\t\t\t\t((void const *&)As_Reference(index).ImageData) = MFCD::Retrieve(fullname);\n\t\t\t\t}\n\t\t\t#else\n\t\t\t\t((void const *&)As_Reference(index).ImageData) = MFCD::Retrieve(fullname);\n\t\t\t#endif\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * AnimTypeClass::Init -- Load any animation artwork that is theater specific.                 *\n *                                                                                             *\n *    This routine will examine all the animation types and for any that are theater           *\n *    specific, it will fetch a pointer to the artwork appropriate for the theater specified.  *\n *                                                                                             *\n * INPUT:   theater  -- The theater to align the animation artwork with.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine when the theater changes.                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimTypeClass::Init(TheaterType theater)\n{\n\tif (theater != LastTheater) {\n\t\tfor (AnimType index = ANIM_FIRST; index < ANIM_COUNT; index++) {\n\t\t\tAnimTypeClass const & anim = As_Reference(index);\n\n\t\t\tif (anim.IsTheater) {\n\t\t\t\tchar fullname[_MAX_FNAME+_MAX_EXT];\t// Fully constructed iconset name.\n\t\t\t\t_makepath(fullname, NULL, NULL, anim.IniName, Theaters[theater].Suffix);\n\t\t\t\t((void const *&)anim.ImageData) = MFCD::Retrieve(fullname);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Anim_Name -- Fetches the ASCII name of the animation type specified.                        *\n *                                                                                             *\n *    This will convert the animation type specified into a text name. This name can be used   *\n *    for uniquely identifying the animation.                                                  *\n *                                                                                             *\n * INPUT:   anim  -- The anim type to convert to a text string.                                *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the ASCII string that identifies this animation.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * Anim_Name(AnimType anim)\n{\n\tif (anim == ANIM_NONE) return(\"\");\n\n\treturn(AnimTypeClass::As_Reference(anim).IniName);\n}\n\n\n/***********************************************************************************************\n * AnimTypeClass::As_Reference -- Fetch a reference to the animation type specified.           *\n *                                                                                             *\n *    This routine will convert the animation type specified into a reference to the           *\n *    animation type class object.                                                             *\n *                                                                                             *\n * INPUT:   type  -- The animation type to convert into a reference.                           *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the animation type class object.                       *\n *                                                                                             *\n * WARNINGS:   Be sure that the animation type specified is legal. If it isn't then the        *\n *             results of this routine are undefined.                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nAnimTypeClass & AnimTypeClass::As_Reference(AnimType type)\n{\n\treturn(* AnimTypes.Ptr(type));\n}\n\n"
  },
  {
    "path": "CODE/ADPCM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"function.h\"\n\nextern \"C\" {\n#include \"soscomp.h\"\n#include \"itable.cpp\"\n#include \"dtable.cpp\"\n\n\nvoid sosCODECInitStream(_SOS_COMPRESS_INFO* info)\n{\n\tinfo->dwSampleIndex = 0;\n\tinfo->dwPredicted = 0;\n}\n\n\nunsigned long sosCODECDecompressData(_SOS_COMPRESS_INFO* info, unsigned long numbytes)\n{\n\tunsigned long token;\n\tlong sample;\n\tunsigned int fastindex;\n\tunsigned char *inbuff;\n\tunsigned short *outbuff;\n\n\tinbuff = (unsigned char *)info->lpSource;\n\toutbuff = (unsigned short *)info->lpDest;\n\n\t// Preload variables before the big loop\n\tfastindex = (unsigned int)info->dwSampleIndex;\n\tsample = info->dwPredicted;\n\n\tif (!numbytes)\n\t\tgoto SkipLoop;\n\n\tdo {\n\t\t// First nibble\n\t\ttoken = *inbuff++;\n\t\tfastindex += token & 0x0f;\n\t\tsample += DiffTable[fastindex];\n\t\tfastindex = IndexTable[fastindex];\n\t\tif (sample > 32767L)\n\t\t\tsample = 32767L;\n\t\tif (sample < -32768L)\n\t\t\tsample = -32768L;\n\t\t*outbuff++ = (unsigned short)sample;\n\n\t\t// Second nibble\n\t\tfastindex += token >> 4;\n\t\tsample += DiffTable[fastindex];\n\t\tfastindex = IndexTable[fastindex];\n\t\tif (sample > 32767L)\n\t\t\tsample = 32767L;\n\t\tif (sample < -32768L)\n\t\t\tsample = -32768L;\n\t\t*outbuff++ = (unsigned short)sample;\n\t} while(--numbytes);\n\nSkipLoop:\n\n\t// Put local vars back\n\tinfo->dwSampleIndex = (unsigned long)fastindex;\n\tinfo->dwPredicted = sample;\n\treturn(numbytes << 2);\n}\n\n}\n"
  },
  {
    "path": "CODE/AIRCRAFT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/AIRCRAFT.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : AIRCRAFT.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 22, 1994                                                *\n *                                                                                             *\n *                  Last Update : November 2, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   AircraftClass::AI -- Processes the normal non-graphic AI for the aircraft.                *\n *   AircraftClass::Active_Click_With -- Handles clicking over specified cell.                 *\n *   AircraftClass::Active_Click_With -- Handles clicking over specified object.               *\n *   AircraftClass::AircraftClass -- The constructor for aircraft objects.                     *\n *   AircraftClass::Can_Enter_Cell -- Determines if the aircraft can land at this location.    *\n *   AircraftClass::Can_Fire -- Checks to see if the aircraft can fire.                        *\n *   AircraftClass::Cell_Seems_Ok -- Checks to see if a cell is good to enter.                 *\n *   AircraftClass::Desired_Load_Dir -- Determines where passengers should line up.            *\n *   AircraftClass::Draw_It -- Renders an aircraft object at the location specified.           *\n *   AircraftClass::Draw_Rotors -- Draw rotor blades on the aircraft.                          *\n *   AircraftClass::Edge_Of_World_AI -- Detect if aircraft has exited the map.                 *\n *   AircraftClass::Enter_Idle_Mode -- Gives the aircraft an appropriate mission.              *\n *   AircraftClass::Exit_Object -- Unloads passenger from aircraft.                            *\n *   AircraftClass::Fire_At -- Handles firing a projectile from an aircraft.                   *\n *   AircraftClass::Fire_Direction -- Determines the direction of fire.                        *\n *   AircraftClass::Good_Fire_Location -- Searches for and finds a good spot to fire from.     *\n *   AircraftClass::Good_LZ -- Locates a good spot ot land.                                    *\n *   AircraftClass::In_Which_Layer -- Calculates the display layer of the aircraft.            *\n *   AircraftClass::Init -- Initialize the aircraft system to an empty state.                  *\n *   AircraftClass::Is_LZ_Clear -- Determines if landing zone is free for landing.             *\n *   AircraftClass::Landing_Takeoff_AI -- Handle aircraft take off and landing processing.     *\n *   AircraftClass::Look -- Aircraft will look if they are on the ground always.               *\n *   AircraftClass::Mission_Attack -- Handles the attack mission for aircraft.                 *\n *   AircraftClass::Mission_Enter -- Control aircraft to fly to the helipad or repair center.  *\n *   AircraftClass::Mission_Guard -- Handles aircraft in guard mode.                           *\n *   AircraftClass::Mission_Guard_Area -- Handles the aircraft guard area logic.               *\n *   AircraftClass::Mission_Hunt -- Maintains hunt AI for the aircraft.                        *\n *   AircraftClass::Mission_Move -- Handles movement mission.                                  *\n *   AircraftClass::Mission_Retreat -- Handles the aircraft logic for leaving the battlefield. *\n *   AircraftClass::Mission_Unload -- Handles unloading cargo.                                 *\n *   AircraftClass::Movement_AI -- Handles aircraft physical movement logic.                   *\n *   AircraftClass::New_LZ -- Find a good landing zone.                                        *\n *   AircraftClass::Overlap_List -- Returns with list of cells the aircraft overlaps.          *\n *   AircraftClass::Paradrop_Cargo -- Drop a passenger by parachute.                           *\n *   AircraftClass::Per_Cell_Process -- Handle the aircraft per cell process.                  *\n *   AircraftClass::Pip_Count -- Returns the number of \"objects\" in aircraft.                  *\n *   AircraftClass::Player_Assign_Mission -- Handles player input to assign a mission.         *\n *   AircraftClass::Pose_Dir -- Fetches the natural landing facing.                            *\n *   AircraftClass::Process_Fly_To -- Handles state machine for flying to destination.         *\n *   AircraftClass::Process_Landing -- Landing process state machine handler.                  *\n *   AircraftClass::Process_Take_Off -- State machine support for taking off.                  *\n *   AircraftClass::Read_INI -- Reads aircraft object data from an INI file.                   *\n *   AircraftClass::Receive_Message -- Handles receipt of radio messages.                      *\n *   AircraftClass::Response_Attack -- Gives audio response to attack order.                   *\n *   AircraftClass::Response_Move -- Gives audio response to move request.                     *\n *   AircraftClass::Response_Select -- Gives audio response when selected.                     *\n *   AircraftClass::Rotation_AI -- Handle aircraft body and flight rotation.                   *\n *   AircraftClass::Scatter -- Causes the aircraft to move away a bit.                         *\n *   AircraftClass::Set_Speed -- Sets the speed for the aircraft.                              *\n *   AircraftClass::Shape_Number -- Fetch the shape number to use for the aircraft.            *\n *   AircraftClass::Sort_Y -- Figures the sorting coordinate.                                  *\n *   AircraftClass::Take_Damage -- Applies damage to the aircraft.                             *\n *   AircraftClass::Unlimbo -- Removes an aircraft from the limbo state.                       *\n *   AircraftClass::What_Action -- Determines what action to perform.                          *\n *   AircraftClass::What_Action -- Determines what action to perform.                          *\n *   AircraftClass::operator delete -- Deletes the aircraft object.                            *\n *   AircraftClass::operator new -- Allocates a new aircraft object from the pool              *\n *   AircraftClass::~AircraftClass -- Destructor for aircraft object.                          *\n *   _Counts_As_Civ_Evac -- Is the specified object a candidate for civilian evac logic?       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * _Counts_As_Civ_Evac -- Is the specified object a candidate for civilian evac logic?         *\n *                                                                                             *\n *    Examines the specified object to see if it qualifies to be a civilian evacuation. This   *\n *    can only occur if it is a civilian (or Tanya) and the special evacuation flag has been   *\n *    set in the scenario control structure.                                                   *\n *                                                                                             *\n * INPUT:   candidate   -- Candidate object to examine for civilian evacuation legality.       *\n *                                                                                             *\n * OUTPUT:  bool; Is the specified object considered a civilian that must be auto-evacuated?   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/24/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic bool _Counts_As_Civ_Evac(ObjectClass const * candidate)\n{\n\t/*\n\t**\tIf the candidate pointer is missing, then return with failure code.\n\t*/\n\tif (candidate == NULL) return(false);\n\n\t/*\n\t**\tOnly infantry objects can be considered for civilian evacuation action.\n\t*/\n\tif (candidate->What_Am_I() != RTTI_INFANTRY) return(false);\n\n\t/*\n\t**\tWorking infantry object pointer.\n\t*/\n\tInfantryClass const * inf = (InfantryClass const *)candidate;\n\n\t/*\n\t**\tCertain infantry types will always be considered a civilian evacuation candidate. These\n\t**\tinclude the special one-time infantry that appear in some missions.\n\t*/\n\tif (*inf == INFANTRY_EINSTEIN || *inf == INFANTRY_GENERAL || *inf == INFANTRY_DELPHI || *inf == INFANTRY_CHAN) return(true);\n\n\t/*\n\t**\tConsider Tanya to be part of the civilian evacuation logic if the scenario is\n\t**\tspecially flagged for this.\n\t*/\n\tif (Scen.IsTanyaEvac && *inf == INFANTRY_TANYA) return(true);\n\n\t/*\n\t**\tIf the infantry is not a civilian, then it isn't allowed to be a civilian evacuation.\n\t*/\n\tif (!inf->Class->IsCivilian) return(false);\n\n\t/*\n\t**\tTechnicians look like civilians, but are not considered a legal evacuation candidate.\n\t*/\n\tif (inf->IsTechnician) return(false);\n\n\t/*\n\t**\tAll tests pass, so return the success of the infantry as a civilian evacuation candidate.\n\t*/\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::operator new -- Allocates a new aircraft object from the pool                *\n *                                                                                             *\n *    This routine will allocate an aircraft object from the free aircraft object pool. If     *\n *    there are no free object available, then this routine will fail (return NULL).           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocate aircraft object or NULL if none were        *\n *          available.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * AircraftClass::operator new(size_t)\n{\n\tvoid * ptr = Aircraft.Allocate();\n\tif (ptr) {\n\t\t((AircraftClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::operator delete -- Deletes the aircraft object.                              *\n *                                                                                             *\n *    This routine will return the aircraft object back to the free aircraft object pool.      *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the aircraft object to delete.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::operator delete(void * ptr)\n{\n\tif (ptr) {\n\t\t((AircraftClass *)ptr)->IsActive = false;\n\t}\n\tAircraft.Free((AircraftClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::AircraftClass -- The constructor for aircraft objects.                       *\n *                                                                                             *\n *    This routine is the constructor for aircraft objects. An aircraft object can be          *\n *    created and possibly placed into the game system by this routine.                        *\n *                                                                                             *\n * INPUT:   classid  -- The type of aircraft to create.                                        *\n *                                                                                             *\n *          house    -- The owner of this aircraft.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nAircraftClass::AircraftClass(AircraftType classid, HousesType house) :\n\tFootClass(RTTI_AIRCRAFT, Aircraft.ID(this), house),\n\tClass(AircraftTypes.Ptr((int)classid)),\n\tSecondaryFacing(PrimaryFacing),\n\tPassenger(false),\n\tIsLanding(false),\n\tIsTakingOff(false),\n\tIsHovering(false),\n\tJitter(0),\n\tSightTimer(0),\n\tAttacksRemaining(1)\n{\n\t/*\n\t**\tFor two shooters, clear out the second shot flag -- it will be set the first time\n\t**\tthe object fires. For non two shooters, set the flag since it will never be cleared\n\t**\tand the second shot flag tells the system that normal rearm times apply -- this is\n\t**\twhat is desired for non two shooters.\n\t*/\n\tIsSecondShot = !Class->Is_Two_Shooter();\n\tHouse->Tracking_Add(this);\n\tAmmo = Class->MaxAmmo;\n\tHeight = FLIGHT_LEVEL;\n\tStrength = Class->MaxStrength;\n\tNavCom = TARGET_NONE;\n\n\t/*\n\t** Keep count of the number of units created. Dont track cargo planes as they are created\n\t** automatically, not bought.\n\t*/\n//\tif (/*classid != AIRCRAFT_CARGO && */ Session.Type == GAME_INTERNET) {\n//\t\tHouse->AircraftTotals->Increment_Unit_Total((int)classid);\n//\t}\n\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Unlimbo -- Removes an aircraft from the limbo state.                         *\n *                                                                                             *\n *    This routine is used to transition the aircraft from the limbo to the non limbo state.   *\n *    It occurs when the aircraft is placed on the map for whatever reason. When it is         *\n *    unlimboed, only then will normal game processing recognize it.                           *\n *                                                                                             *\n * INPUT:   coord -- The coordinate that the aircraft should appear at.                        *\n *                                                                                             *\n *          dir   -- The direction it should start facing.                                     *\n *                                                                                             *\n *\t\t\t\tstrength (optional) -- sets initial strength\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *\t\t\t\tmission (optional) -- sets initial mission\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:  bool; Was the aircraft unlimboed successfully?                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AircraftClass::Unlimbo(COORDINATE coord, DirType dir)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (FootClass::Unlimbo(coord, dir)) {\n\n\t\tif (*this == AIRCRAFT_BADGER || (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->IsCamera)) {\n\t\t\tIsALoaner = true;\n\t\t}\n\n\t\t/*\n\t\t**\tEnsure that the owning house knows about the\n\t\t**\tnew object.\n\t\t*/\n\t\tHouse->AScan |= (1L << Class->Type);\n\t\tHouse->ActiveAScan |= (1L << Class->Type);\n\n\t\t/*\n\t\t**\tHack it so that aircraft that are both passenger and cargo carrying\n\t\t**\twill carry passengers at the expense of ammo.\n\t\t*/\n\t\tif (Is_Something_Attached()) {\n\t\t\tAmmo = 0;\n\t\t\tPassenger = true;\n\t\t}\n\n\t\t/*\n\t\t**\tForces the body of the helicopter to face the correct direction.\n\t\t*/\n\t\tSecondaryFacing = dir;\n\n\t\t/*\n\t\t**\tStart rotor animation.\n\t\t*/\n\t\tif (!Class->IsFixedWing) {\n\t\t\tSet_Rate(1);\n\t\t\tSet_Stage(0);\n\t\t}\n\n\t\t/*\n\t\t**\tWhen starting at flight level, then give it speed. When landed\n\t\t**\tthen it must be stationary.\n\t\t*/\n\t\tif (Height == FLIGHT_LEVEL) {\n\t\t\tSet_Speed(0xFF);\n\t\t} else {\n\t\t\tSet_Speed(0);\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Shape_Number -- Fetch the shape number to use for the aircraft.              *\n *                                                                                             *\n *    This will determine what shape number to use for the aircraft in its current state.      *\n *    The shape number can be used for drawing or determine shape rectangle size.              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the shape number to use for the aircraft body.                        *\n *                                                                                             *\n * WARNINGS:   Some aircraft, particularly helicopters, require other shapes attached to it.   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftClass::Shape_Number(void) const\n{\n\tint shapenum = 0;\n\n\tswitch (Class->Rotation) {\n\t\tcase 32:\n\t\t\tshapenum = UnitClass::BodyShape[Dir_To_32(SecondaryFacing)];\n\t\t\tbreak;\n\n\t\tcase 16:\n\t\t\tshapenum = UnitClass::BodyShape[Dir_To_16(SecondaryFacing)*2]/2;\n\t\t\tbreak;\n\n\t\tcase 8:\n\t\t\tshapenum = UnitClass::BodyShape[Dir_To_8(SecondaryFacing)*4]/4;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tIf there is a door on this aircraft (Chinook), then adjust the\n\t**\tshape number to match the door open state.\n\t*/\n\tif (!Is_Door_Closed()) {\n\t\tshapenum = Class->Rotation + Door_Stage();\n\t}\n\n\treturn(shapenum);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Draw_It -- Renders an aircraft object at the location specified.             *\n *                                                                                             *\n *    This routine is used to display the aircraft object at the coordinates specified.        *\n *    The tactical map display uses this routine for all aircraft rendering.                   *\n *                                                                                             *\n * INPUT:   x,y      -- The coordinates to render the aircraft at.                             *\n *                                                                                             *\n *          window   -- The window that the coordinates are based upon.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Draw_It(int x, int y, WindowNumberType window) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tVerify the legality of the unit class.\n\t*/\n\tvoid const * shapefile = Get_Image_Data();\n\tif (!shapefile) return;\n\n\tint shapenum = Shape_Number();\n\n\t/*\n\t**\tCertain aircraft use algorithmic rotation for some stages. Set the\n\t**\trotation value accordingly. A rotation of DIR_N means no rotation at all.\n\t*/\n\tDirType rotation = DIR_N;\n\tif (Class->Rotation == 16) {\n\t\trotation = DirType(Rotation16[SecondaryFacing]);\n\t}\n\n#ifdef TOFIX\n\t/*\n\t**\tThe orca attack helicopter uses a special shape set when it is travelling\n\t**\tforward above a certain speed.\n\t*/\n\tif (*this == AIRCRAFT_HIND && Get_Speed() >= MPH_MEDIUM_FAST) {\n\t\tshapenum += Class->Rotation;\n\t}\n#endif\n\n\t/*\n\t**\tHelicopters that are flying have a \"bobbing\" effect.\n\t*/\n\tint jitter = 0;\n\tif (Height == FLIGHT_LEVEL && Get_Speed() < 3) {\n\t\tstatic int _jitter[] = {0,0,0,0,1,1,1,0,0,0,0,0,-1,-1,-1,0};\n\t\tjitter = _jitter[::Frame % 16];\n\t}\n\n\t/*\n\t**\tSpecial manual shadow draw code.\n\t*/\n\tif (Visual_Character() <= VISUAL_DARKEN) {\n\t\tCC_Draw_Shape(shapefile, shapenum, x+1, y+2, window, SHAPE_PREDATOR|SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_FADING, DisplayClass::FadingShade, NULL);\n\t}\n\n\t/*\n\t**\tActually draw the root body of the unit.\n\t*/\n\tTechno_Draw_Object(shapefile, shapenum, x, y+jitter, window, rotation);\n\n\t/*\n\t**\tIf this aircraft is equipped with rotor blades, then draw them at this time.\n\t*/\n\tif (Class->IsRotorEquipped) {\n\t\tDraw_Rotors(x, y+jitter, window);\n\t}\n\n\t/*\n\t**\tThis draws any overlay graphics on the aircraft.\n\t*/\n\tFootClass::Draw_It(x, y-Lepton_To_Pixel(Height), window);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Draw_Rotors -- Draw rotor blades on the aircraft.                            *\n *                                                                                             *\n *    This routine will draw rotor blades on the aircraft. It is presumed that the aircraft    *\n *    has already been drawn at the X and Y pixel coordinates specified.                       *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y pixel coordinates to draw the rotor blades.                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Draw_Rotors(int x, int y, WindowNumberType window) const\n{\n\tShapeFlags_Type flags = SHAPE_CENTER|SHAPE_WIN_REL;\n\tint shapenum;\n\n\t/*\n\t**\tThe rotor shape number depends on whether the helicopter is idling\n\t**\tor not. A landed helicopter uses slow moving \"idling\" blades.\n\t*/\n\tif (Height == 0) {\n\t\tshapenum = (Fetch_Stage()%8)+4;\n\t\tflags = flags | SHAPE_GHOST;\n\t} else {\n\t\tshapenum = Fetch_Stage()%4;\n\t\tflags = flags | SHAPE_FADING|SHAPE_PREDATOR;\n\t}\n\n\tif (*this == AIRCRAFT_TRANSPORT) {\n\t\tint _stretch[FACING_COUNT] = {8, 9, 10, 9, 8, 9, 10, 9};\n\n\t\t/*\n\t\t**\tDual rotors offset along flight axis.\n\t\t*/\n\t\tshort xx = x;\n\t\tshort yy = y-Lepton_To_Pixel(Height);\n\t\tFacingType face = Dir_Facing(SecondaryFacing);\n\t\tMove_Point(xx, yy, SecondaryFacing.Current(), _stretch[face]);\n\t\tCC_Draw_Shape(AircraftTypeClass::RRotorData, shapenum, xx, yy-2, window, flags, NULL, DisplayClass::UnitShadow);\n\n\t\tMove_Point(xx, yy, SecondaryFacing.Current()+DIR_S, _stretch[face]*2);\n\t\tCC_Draw_Shape(AircraftTypeClass::LRotorData, shapenum, xx, yy-2, window, flags, NULL, DisplayClass::UnitShadow);\n\n\t} else {\n\n\t\t/*\n\t\t**\tSingle rotor centered about shape.\n\t\t*/\n\t\tCC_Draw_Shape(AircraftTypeClass::RRotorData, shapenum, x, ((y-Lepton_To_Pixel(Height))-2), window, flags, NULL, DisplayClass::UnitShadow);\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Read_INI -- Reads aircraft object data from an INI file.                     *\n *                                                                                             *\n *    This routine is used to read the aircraft object data from the INI file buffer           *\n *    specified. This is used by the scenario loader code to interpret the INI file and        *\n *    create the specified objects therein.                                                    *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the INI buffer.                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Read_INI(CCINIClass & ini)\n{\n\tAircraftClass\t* air;\t\t\t// Working unit pointer.\n\tHousesType\t\tinhouse;\t\t\t// Unit house.\n\tAircraftType\tclassid;\t\t\t// Unit class.\n\tchar\t\t\t\tbuf[128];\n\n\tint counter = ini.Entry_Count(INI_Name());\n\tfor (int index = 0; index < counter; index++) {\n\t\tchar const * entry = ini.Get_Entry(INI_Name(), index);\n\n\t\tini.Get_String(INI_Name(), entry, NULL, buf, sizeof(buf)-1);\n\t\tinhouse = HouseTypeClass::From_Name(strtok(buf, \",\"));\n\t\tif (inhouse != HOUSE_NONE) {\n\t\t\tclassid = AircraftTypeClass::From_Name(strtok(NULL, \",\"));\n\n\t\t\tif (classid != AIRCRAFT_NONE) {\n\n\t\t\t\tair = new AircraftClass(classid, inhouse);\n\t\t\t\tif (air) {\n\t\t\t\t\tCOORDINATE\tcoord;\n\t\t\t\t\tint\tstrength;\n\t\t\t\t\tDirType dir;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tRead the raw data.\n\t\t\t\t\t*/\n\t\t\t\t\tchar * token = strtok(NULL, \",\");\n\t\t\t\t\tif (token) {\n\t\t\t\t\t\tstrength = atoi(token);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstrength = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\ttoken = strtok(NULL, \",\");\n\t\t\t\t\tif (token) {\n\t\t\t\t\t\tcoord = Cell_Coord((CELL)atoi(token));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcoord = 0xFFFFFFFFL;\n\t\t\t\t\t}\n\n\t\t\t\t\ttoken = strtok(NULL, \",\");\n\t\t\t\t\tif (token) {\n\t\t\t\t\t\tdir = (DirType)atoi(token);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdir = DIR_N;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!Map.In_Radar(Coord_Cell(coord))) {\n\t\t\t\t\t\tdelete air;\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tair->Strength = air->Class->MaxStrength * fixed(strength, 256);\n\t\t\t\t\t\tif (air->Unlimbo(coord, dir)) {\n\t\t\t\t\t\t\tair->Assign_Mission(AircraftClass::Mission_From_Name(strtok(NULL, \",\\n\\r\")));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdelete air;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Mission_Hunt -- Maintains hunt AI for the aircraft.                          *\n *                                                                                             *\n *    Hunt AI consists of finding a target and attacking it. If there is no target assigned    *\n *    and this unit doesn't automatically hunt for more targets, then it will change           *\n *    mission to a more passive (land and await further orders) type.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of ticks before calling this routine again.                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftClass::Mission_Hunt(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsFixedWing) {\n\n\t\tif (TarCom != NavCom) {\n\t\t\tAssign_Destination(TarCom);\n\t\t}\n\n\t\tenum {\n\t\t\tLOOK_FOR_TARGET,\n\t\t\tTAKE_OFF,\n\t\t\tFLY_TO_TARGET,\n\t\t\tDROP_BOMBS,\n\t\t\tREGROUP\n\t\t};\n\t\tswitch (Status) {\n\n\t\t\t/*\n\t\t\t**\tAcquiring target stage.\n\t\t\t*/\n\t\t\tcase LOOK_FOR_TARGET:\n\t\t\t\tif (Target_Legal(TarCom)) {\n\t\t\t\t\tStatus = TAKE_OFF;\n\t\t\t\t\treturn(1);\n\t\t\t\t} else {\n\t\t\t\t\tif (!Team.Is_Valid()) {\n\t\t\t\t\t\tif (Session.Type != GAME_NORMAL) {\n\t\t\t\t\t\t\tAssign_Target(Greatest_Threat(THREAT_TIBERIUM));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\t\t\t\tAssign_Target(Greatest_Threat(THREAT_NORMAL));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf there is no target, then this aircraft should just do its normal thing.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (!Target_Legal(TarCom) && !Team.Is_Valid()) {\n\t\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tMake the aircraft take off from the airstrip.\n\t\t\t*/\n\t\t\tcase TAKE_OFF:\n\t\t\t\t/*\n\t\t\t\t**\tIf the aircraft is high enough to begin its mission, then do so.\n\t\t\t\t*/\n\t\t\t\tif (Process_Take_Off())  {\n\t\t\t\t\tIsTakingOff = false;\n\t\t\t\t\tSet_Speed(0xFF);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tAfter takeoff is complete, break radio contact.\n\t\t\t\t\t*/\n\t\t\t\t\tif (In_Radio_Contact()/*KO && Map[Coord].Cell_Building() == Contact_With_Whom()*/) {\n\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t}\n\n\t\t\t\t\tStatus = FLY_TO_TARGET;\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\t/*\n\t\t\t**\tHoming in on target stage.\n\t\t\t*/\n\t\t\tcase FLY_TO_TARGET:\n\t\t\t\tswitch (Can_Fire(TarCom, 0)) {\n\t\t\t\t\tcase FIRE_FACING:\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tCatch the case where it is tightly circling the target. In that\n\t\t\t\t\t\t**\tcase, increase the delay so that it has a chance to fly away and\n\t\t\t\t\t\t**\tbreak the circle cycle.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (In_Range(TarCom, 0) || Passenger) {\n\t\t\t\t\t\t\treturn(TICKS_PER_SECOND * 2);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!PrimaryFacing.Is_Rotating() && Target_Legal(TarCom)) {\n\t\t\t\t\t\t\tPrimaryFacing.Set_Desired(Direction(TarCom));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase FIRE_AMMO:\n\t\t\t\t\t\tStatus = REGROUP;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase FIRE_CANT:\n\t\t\t\t\tcase FIRE_ILLEGAL:\n\t\t\t\t\t\tif (Mission == MISSION_ATTACK) {\n\t\t\t\t\t\t\tStatus = REGROUP;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tStatus = LOOK_FOR_TARGET;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase FIRE_OK:\n\t\t\t\t\t\tStatus = DROP_BOMBS;\n\t\t\t\t\t\treturn(1);\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tif (!PrimaryFacing.Is_Rotating() && Target_Legal(TarCom)) {\n\t\t\t\t\t\t\tPrimaryFacing.Set_Desired(Direction(TarCom));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn(TICKS_PER_SECOND/2);\n\n\t\t\t/*\n\t\t\t**\tDropping a stream of bombs phase.\n\t\t\t*/\n\t\t\tcase DROP_BOMBS:\n\t\t\t\tTARGET targ;\n\t\t\t\tswitch (Can_Fire(TarCom, 0)) {\n\t\t\t\t\tcase FIRE_OK:\n\t\t\t\t\t\ttarg = ::As_Target(Coord_Move(Center_Coord(), SecondaryFacing, Weapon_Range(0)-0x0200));\n\t\t\t\t\t\tif (Class->PrimaryWeapon != NULL) {\n\t\t\t\t\t\t\tif (Class->PrimaryWeapon->IsCamera) {\n\t\t\t\t\t\t\t\tStatus = REGROUP;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tMap[::As_Cell(TarCom)].Incoming(Coord, true);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tForce the target to be the actual target if this aircraft is\n\t\t\t\t\t\t\t**\tequipped with homing projectile.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Class->PrimaryWeapon->Bullet != NULL && Class->PrimaryWeapon->Bullet->ROT > 0) {\n\t\t\t\t\t\t\t\ttarg = TarCom;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tFire_At(targ, 0);\n\t\t\t\t\t\tif (Class->Is_Two_Shooter()) {\n\t\t\t\t\t\t\tFire_At(targ, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(Arm);\n\n\t\t\t\t\tcase FIRE_RANGE:\n\t\t\t\t\tcase FIRE_FACING:\n\t\t\t\t\t\tStatus = FLY_TO_TARGET;\n\t\t\t\t\t\treturn(TICKS_PER_SECOND*4);\n\n\t\t\t\t\tcase FIRE_ILLEGAL:\n\t\t\t\t\t\tif (Mission == MISSION_ATTACK) {\n\t\t\t\t\t\t\tStatus = REGROUP;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tStatus = LOOK_FOR_TARGET;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase FIRE_CANT:\n\t\t\t\t\t\tStatus = REGROUP;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase FIRE_AMMO:\n\t\t\t\t\t\tAttacksRemaining--;\n\t\t\t\t\t\tStatus = REGROUP;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\t/*\n\t\t\t**\tPull away to regroup for possibly another attack or a retreat.\n\t\t\t*/\n\t\t\tcase REGROUP:\n\t\t\t\tif (Ammo == 0) {\n\t\t\t\t\tAttacksRemaining = 0;\n\t\t\t\t\tif (Team.Is_Valid()) Team->Remove(this);\n\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t}\n\n\t\t\t\tif (Mission == MISSION_ATTACK || (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->IsCamera) || (!AttacksRemaining && !Is_Something_Attached())) {\n\n\t\t\t\t\tif (IsALoaner)  {\n\t\t\t\t\t\tif (Team) Team->Remove(this);\n\t\t\t\t\t\tAssign_Mission(MISSION_RETREAT);\n\t\t\t\t\t\tCommence();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!Team.Is_Valid()) Enter_Idle_Mode();\n\t\t\t\t\t}\n\t\t\t\t\tCommence();\n\t\t\t\t} else {\n\t\t\t\t\tStatus = LOOK_FOR_TARGET;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t} else {\n\t\tif (!Ammo) {\n\t\t\tif (Team) Team->Remove(this);\n\t\t\tEnter_Idle_Mode();\n\t\t} else {\n\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\tif (Session.Type != GAME_NORMAL) {\n\t\t\t\t\tAssign_Target(Greatest_Threat(THREAT_TIBERIUM));\n\t\t\t\t}\n\t\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\t\tAssign_Target(Greatest_Threat(THREAT_NORMAL));\n\t\t\t\t}\n\t\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tAssign_Mission(MISSION_ATTACK);\n\t\t\treturn(1);\n\t\t}\n\t}\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * AircraftClass::AI -- Processes the normal non-graphic AI for the aircraft.                  *\n *                                                                                             *\n *    This handles the non-graphic AI processing for the aircraft. This usually entails        *\n *    maintenance and other AI functions.                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::AI(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tA Mission change can always occur if the aircraft is landed or flying.\n\t*/\n\tif (!IsLanding && !IsTakingOff) {\n\t\tCommence();\n\t}\n\n\t/*\n\t**\tPerform any base class AI processing. If during this process, the aircraft was\n\t**\tdestroyed, then detect this and bail from this AI routine early.\n\t*/\n\tFootClass::AI();\n\tif (!IsActive) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tA Mission change can always occur if the aircraft is landed or flying.\n\t*/\n\tif (!IsLanding && !IsTakingOff) {\n\t\tCommence();\n\t}\n\n\t/*\n\t**\tHandle any body rotation at this time. Body rotation can occur even if the\n\t**\tflying object is not actually moving.\n\t*/\n\tRotation_AI();\n\n\t/*\n\t**\tHandle any aircraft movement at this time.\n\t*/\n\tMovement_AI();\n\n\t/*\n\t**\tAny aircraft that is not in the ground layer must be redrawn. This is a\n\t**\tperformance hit, but there is no other choice. The cells under an aircraft\n\t**\tdo not know if there is an aircraft above it. Thus, it cannot flag the\n\t**\taircraft to redraw. As a consequence, all aircraft must redraw.\n\t*/\n\tif (In_Which_Layer() != LAYER_GROUND) {\n\t\tMark();\n\t}\n\n\t/*\n\t**\tPerform sighting every so often as controlled by the sight timer.\n\t*/\n\tif (IsOwnedByPlayer && Class->SightRange && SightTimer == 0) {\n\t\tLook();\n\t\tSightTimer = TICKS_PER_SECOND;\n\t}\n\n\t/*\n\t**\tHandle landing and taking off logic. Helicopters are prime users of this technique. The\n\t**\taircraft will either gain or lose altitude as appropriate. As the aircraft transitions\n\t**\tbetween flying level and ground level, it will be moved into the appropriate render\n\t**\tlayer.\n\t*/\n\tif (Landing_Takeoff_AI()) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tAlways flag the map draw process to occur if there is an aircraft in the view.\n\t**\tThis ensures that it will be rendered even if there is nothing else that flagged\n\t**\tthe map to be redrawn.\n\t*/\n\tif (Map.In_View(Coord_Cell(Coord))) {\n\t\tMap.Flag_To_Redraw(false);\n\t\tMap.DisplayClass::IsToRedraw = true;\n\t}\n\n\t/*\n\t**\tWhen aircraft leave the edge of the map, they might get destroyed. This occurs if the\n\t**\taircraft is a non-player produced unit and it has completed its mission. A transport\n\t**\thelicopter that has already delivered reinforcements is a good example of this.\n\t*/\n\tif (Edge_Of_World_AI()) {\n\t\treturn;\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Overlap_List -- Returns with list of cells the aircraft overlaps.            *\n *                                                                                             *\n *    When aircraft are flying, they can overlap quite a number of cells. These cells can      *\n *    be determined from the coordinate where the aircraft is centered and the size of the     *\n *    aircraft's shape. Landed aircraft are a special case and are usually much smaller        *\n *    than when flying.                                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a cell offset list that specifies all cells that         *\n *          the aircraft overlaps given the aircraft's current state.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * AircraftClass::Overlap_List(bool redraw) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tstatic short const _list[] = {\n\t\t-(MAP_CELL_W-1), -MAP_CELL_W, -(MAP_CELL_W+1),\n\t\t-1, 0, 1,\n\t\t(MAP_CELL_W-1), MAP_CELL_W, (MAP_CELL_W+1),\n\t\t-((MAP_CELL_W*2)-1), -(MAP_CELL_W*2), -((MAP_CELL_W*2)+1),\n\t\t-((MAP_CELL_W*3)-1), -(MAP_CELL_W*3), -((MAP_CELL_W*3)+1),\n\t\tREFRESH_EOL\n\t};\n\n\tstatic short const _listbadger[] = {\n\t\t-(MAP_CELL_W-2), -(MAP_CELL_W-1), -MAP_CELL_W, -(MAP_CELL_W+1), -(MAP_CELL_W+2),\n\t\t-2, -1, 0, 1, 2,\n\t\t(MAP_CELL_W-2), (MAP_CELL_W-1), MAP_CELL_W, (MAP_CELL_W+1), (MAP_CELL_W+2),\n\t\t-((MAP_CELL_W*2)-2), -((MAP_CELL_W*2)-1), -(MAP_CELL_W*2), -((MAP_CELL_W*2)+1), -((MAP_CELL_W*2)+2),\n\t\t-((MAP_CELL_W*3)-2), -((MAP_CELL_W*3)-1), -(MAP_CELL_W*3), -((MAP_CELL_W*3)+1), -((MAP_CELL_W*3)+2),\n\t\tREFRESH_EOL\n\t};\n\n\tif (redraw || Height != 0) {\n#ifdef PARTIAL\n\t\tRect rect;\n\t\tif (!IsSelected && Class->DimensionData != NULL && Class->IsFixedWing) {\n\t\t\tint shapenum = min(Shape_Number(), Get_Build_Frame_Count(Class->Get_Image_Data())-1);\n\t\t\tif (!Class->DimensionData[shapenum].Is_Valid()) {\n\t\t\t\tClass->DimensionData[shapenum] = Shape_Dimensions(Class->Get_Image_Data(), shapenum);\n\t\t\t}\n\t\t\trect = Class->DimensionData[shapenum];\n\n\t\t\t/*\n\t\t\t**\tIncrease the rectangle for the aircraft since the aircraft could\n\t\t\t**\thave its shape algorithmically rotated.\n\t\t\t*/\n\t\t\trect.X -= 5;\n\t\t\trect.Y -= 5;\n\t\t\trect.Width += 10;\n\t\t\trect.Height += 10;\n\n\t\t\tRect hrect = rect;\n\n\t\t\threct.Y -= Lepton_To_Pixel(Height);\n\n\t\t\treturn(Coord_Spillage_List(Coord, Union(rect, hrect), true));\n\t\t}\n#endif\n\n\t\tif (*this == AIRCRAFT_BADGER) {\n\t\t\treturn(_listbadger);\n\t\t} else {\n\t\t\treturn(_list);\n\t\t}\n\t}\n\treturn(Class->Overlap_List());\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Init -- Initialize the aircraft system to an empty state.                    *\n *                                                                                             *\n *    This routine is used to clear out the aircraft allocation system. It is called in        *\n *    preparation for a scenario load or save game load.                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Init(void)\n{\n\tAircraft.Free_All();\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Mission_Unload -- Handles unloading cargo.                                   *\n *                                                                                             *\n *    This function is used to handle finding, heading toward, landing, and unloading the      *\n *    cargo from the aircraft. Once unloading of cargo has occurred, then the aircraft follows *\n *    a different mission.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the number of game ticks to delay before calling this function again.      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/31/94   JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftClass::Mission_Unload(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsFixedWing) {\n\n\t\tAssign_Target(NavCom);\n\t\treturn(Mission_Hunt());\n\n\t} else {\n\t\tenum {\n\t\t\tSEARCH_FOR_LZ,\n\t\t\tFLY_TO_LZ,\n\t\t\tLAND_ON_LZ,\n\t\t\tUNLOAD_PASSENGERS,\n\t\t\tTAKE_OFF\n\t\t};\n\n\t\tswitch (Status) {\n\n\t\t\t/*\n\t\t\t**\tSearch for an appropriate destination spot if one isn't already assigned.\n\t\t\t*/\n\t\t\tcase SEARCH_FOR_LZ:\n\t\t\t\tif (Height == 0 && (Target_Legal(NavCom) || Coord == As_Coord(NavCom))) {\n\t\t\t\t\tStatus = UNLOAD_PASSENGERS;\n\t\t\t\t} else {\n\t\t\t\t\tif (!Is_LZ_Clear(NavCom)) {\n\n\t\t\t\t\t\tFootClass * foot = Attached_Object();\n\t\t\t\t\t\tif (foot != NULL && foot->Team && foot->Team->Class->Origin != -1) {\n\t\t\t\t\t\t\tAssign_Destination(::As_Target(Scen.Waypoint[foot->Team->Class->Origin]));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tAssign_Destination(New_LZ(::As_Target(Scen.Waypoint[WAYPT_REINF])));\n\t\t\t\t\t\t\tif (Team.Is_Valid()) {\n\t\t\t\t\t\t\t\tTeam->Assign_Mission_Target(NavCom);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (Height == FLIGHT_LEVEL) {\n\t\t\t\t\t\t\tStatus = FLY_TO_LZ;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tStatus = TAKE_OFF;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tFly to destination.\n\t\t\t*/\n\t\t\tcase FLY_TO_LZ:\n\t\t\t\tif (Is_LZ_Clear(NavCom)) {\n\t\t\t\t\tint distance = Process_Fly_To(true, NavCom);\n\n\t\t\t\t\tif (distance < 0x0100) {\n\t\t\t\t\t\tSecondaryFacing.Set_Desired(Pose_Dir());\n\n\t\t\t\t\t\tif (distance < 0x0010) {\n\t\t\t\t\t\t\tStatus = LAND_ON_LZ;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSecondaryFacing.Set_Desired(PrimaryFacing.Desired());\n\t\t\t\t\t\treturn(5);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tStatus = SEARCH_FOR_LZ;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tLanding phase. Just delay until landing is complete. At that time,\n\t\t\t**\ttransition to the unloading phase.\n\t\t\t*/\n\t\t\tcase LAND_ON_LZ:\n\t\t\t\tif (IsTakingOff) {\n\t\t\t\t\tStatus = TAKE_OFF;\n\t\t\t\t} else {\n\t\t\t\t\tif (Process_Landing()) {\n\t\t\t\t\t\tStatus = UNLOAD_PASSENGERS;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\t/*\n\t\t\t**\tHold while unloading passengers. When passengers are unloaded the order for this\n\t\t\t**\ttransport gets changed to MISSION_RETREAT.\n\t\t\t*/\n\t\t\tcase UNLOAD_PASSENGERS:\n\t\t\t\tif (!IsTethered) {\n\t\t\t\t\tif (Is_Something_Attached()) {\n\t\t\t\t\t\tFootClass * unit = (FootClass *)Detach_Object();\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tFirst thing is to lift the transport off of the map so that the unlimbo\n\t\t\t\t\t\t**\tprocess for the passengers is more likely to succeed.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tMap.Pick_Up(Coord_Cell(Coord), this);\n\n\t\t\t\t\t\tif (!Exit_Object(unit)) {\n\t\t\t\t\t\t\tdelete unit;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tRestore the transport back down on the map.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tMap.Place_Down(Coord_Cell(Coord), this);\n\n\t\t\t\t\t\tif (!Is_Something_Attached()) {\n\t\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else  {\n\n\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tAircraft is now taking off. Once the aircraft reaches flying altitude then it\n\t\t\t**\twill either take off or look for another landing spot to try again.\n\t\t\t*/\n\t\t\tcase TAKE_OFF:  {\n\t\t\t\tif (Process_Take_Off()) {\n\t\t\t\t\tif (Is_Something_Attached()) {\n\t\t\t\t\t\tStatus = SEARCH_FOR_LZ;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tBreak off radio contact with the helipad it is taking off from.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (In_Radio_Contact() && Map[Coord].Cell_Building() == Contact_With_Whom()) {\n\t\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else  {\n\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(1);\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Is_LZ_Clear -- Determines if landing zone is free for landing.               *\n *                                                                                             *\n *    This routine examines the landing zone (as specified by the target parameter) in order   *\n *    to determine if it is free to be landed upon. Call this routine when it is necessary     *\n *    to double check this. Typically this occurs right before a helicopter lands and also     *\n *    when determining the landing zone in the first place.                                    *\n *                                                                                             *\n * INPUT:   target   -- The target that is the \"landing zone\".                                 *\n *                                                                                             *\n * OUTPUT:  bool; Is the landing zone clear for landing?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/31/94   JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AircraftClass::Is_LZ_Clear(TARGET target) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!Target_Legal(target)) return(false);\n\tCELL cell = ::As_Cell(target);\n\tif (!Map.In_Radar(cell)) return(false);\n\n\t/*\n\t**\tIf the requested landing location is occupied, then only consider that location\n\t**\tlegal if the occupying object is in radio contact with the aircraft. This presumes that\n\t**\tthe two objects know what they are doing.\n\t*/\n\tObjectClass * object = Map[cell].Cell_Object();\n\tif (object) {\n\t\tif (object == this) return(true);\n\n\t\tif (In_Radio_Contact() && Contact_With_Whom() == object) {\n\t\t\treturn(true);\n\t\t}\n\t\treturn(false);\n\t}\n\n\tif (!Map[cell].Is_Clear_To_Move(SPEED_TRACK, false, false)) return(false);\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Sort_Y -- Figures the sorting coordinate.                                    *\n *                                                                                             *\n *    This routine is used to determine the coordinate to use for sorting the aircraft. This   *\n *    sorting value is used when the aircraft is on the ground. At that time the aircraft      *\n *    must be rendered in proper relationship to the other ground objects.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate to use when sorting the aircraft with other ground     *\n *          objects.                                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE AircraftClass::Sort_Y(void) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(Coord_Add(Coord, 0x00800000L));\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Mission_Retreat -- Handles the aircraft logic for leaving the battlefield.   *\n *                                                                                             *\n *    This mission will be followed when the aircraft decides that it is time to leave the     *\n *    battle. Typically, this occurs when a loaner transport has dropped off its load or when  *\n *    an attack air vehicle has expended its ordinance.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game ticks to delay before calling this routine again.  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/19/1995 JLB : Created.                                                                 *\n *   08/13/1995 JLB : Handles aircraft altitude gain after takeoff logic.                      *\n *=============================================================================================*/\nint AircraftClass::Mission_Retreat(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsFixedWing) {\n\t\tif (Class->IsFixedWing && Height < FLIGHT_LEVEL) {\n\t\t\tHeight += 1;\n\t\t\treturn(3);\n\t\t}\n\t\treturn(TICKS_PER_SECOND*10);\n\t}\n\n\tenum {\n\t\tTAKE_OFF,\n\t\tFACE_MAP_EDGE,\n\t\tKEEP_FLYING\n\t};\n\tswitch (Status) {\n\n\t\t/*\n\t\t**\tTake off if landed.\n\t\t*/\n\t\tcase TAKE_OFF:\n\t\t\tif (Process_Take_Off()) {\n\t\t\t\tStatus = FACE_MAP_EDGE;\n\t\t\t}\n\t\t\treturn(1);\n\n\t\t/*\n\t\t**\tSet facing and speed toward the friendly map edge.\n\t\t*/\n\t\tcase FACE_MAP_EDGE:\n\t\t\tSet_Speed(0xFF);\n\n\t\t\t/*\n\t\t\t**\tTake advantage of the fact that the source map edge enumerations happen to\n\t\t\t**\toccur in a clockwise order and are the first four enumerations of the map\n\t\t\t**\tedge default for the house. If this value is masked and then shifted, a\n\t\t\t**\tnormalized direction value results. Use this value to head the aircraft\n\t\t\t**\ttoward the \"friendly\" map edge.\n\t\t\t*/\n\t\t\tPrimaryFacing.Set_Desired((DirType)((House->Control.Edge & 0x03) << 6));\n\t\t\tSecondaryFacing.Set_Desired(PrimaryFacing.Desired());\n\t\t\tStatus = KEEP_FLYING;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tJust do nothing since we are headed toward the map edge. When the edge is\n\t\t**\treached, the aircraft should be automatically eliminated.\n\t\t*/\n\t\tcase KEEP_FLYING:\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Exit_Object -- Unloads passenger from aircraft.                              *\n *                                                                                             *\n *    This routine is called when the aircraft is to unload a passenger. The passenger must    *\n *    be able to move under its own power. Typical situation is when a transport helicopter    *\n *    is to unload an infantry unit.                                                           *\n *                                                                                             *\n * INPUT:   unit  -- Pointer to the unit that is to be unloaded from this aircraft.            *\n *                                                                                             *\n * OUTPUT:  bool; Was the unit unloaded successfully?                                          *\n *                                                                                             *\n * WARNINGS:   The unload process is merely started by this routine. Radio contact is          *\n *             established with the unloading unit and when the unit is clear of the aircraft  *\n *             the radio contact will be broken and then the aircraft is free to pursue        *\n *             other.                                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftClass::Exit_Object(TechnoClass * unit)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tstatic FacingType _toface[FACING_COUNT] = {FACING_S, FACING_SW, FACING_SE, FACING_NW, FACING_NE, FACING_N, FACING_W, FACING_E};\n\tCELL\tcell;\n\n\t/*\n\t**\tFind a free cell to drop the unit off at.\n\t*/\n\tfor (FacingType face = FACING_N; face < FACING_COUNT; face++) {\n\t\tcell = Adjacent_Cell(Coord_Cell(Coord), _toface[face]);\n\t\tif (unit->Can_Enter_Cell(cell) == MOVE_OK) break;\n\t}\n\n\t// Should perform a check here to see if no cell could be found.\n\n\t/*\n\t**\tIf the passenger can be placed on the map, then start it moving toward the\n\t**\tdestination cell and establish radio contact with the transport. This is used\n\t**\tto make sure that the transport waits until the passenger is clear before\n\t**\tunloading the next passenger or taking off.\n\t*/\n\tif (unit->Unlimbo(Coord, Facing_Dir(_toface[face]))) {\n\t\tunit->Assign_Mission(MISSION_MOVE);\n\t\tunit->Assign_Destination(::As_Target(cell));\n\t\tif (Transmit_Message(RADIO_HELLO, unit) == RADIO_ROGER) {\n\t\t\tTransmit_Message(RADIO_UNLOAD);\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Paradrop_Cargo -- Drop a passenger by parachute.                             *\n *                                                                                             *\n *    Call this routine when a passenger needs to be dropped off by parachute. One passenger   *\n *    is offloaded by a call to this routine.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay time that it is safe to wait before processing any further  *\n *          paradrop actions.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftClass::Paradrop_Cargo(void)\n{\n\tFootClass * passenger = Detach_Object();\n\tif (passenger) {\n\t\tif (!passenger->Paradrop(Center_Coord())) {\n\t\t\tAttach(passenger);\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tPlay a sound effect of the parachute opening.\n\t\t\t*/\n\t\t\tSound_Effect(VOC_CHUTE1, Coord);\n\n\t\t\tif (Team.Is_Valid()) {\n\t\t\t\tTeam->Remove(passenger);\n\t\t\t\tif (passenger->House->IsHuman) {\n\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t} else {\n\t\t\t\t\tAssign_Mission(MISSION_HUNT);\n\t\t\t\t}\n\t\t\t}\n//\t\t\tArm = Rearm_Delay(IsSecondShot);\n\t\t\tArm = 0;\n\t\t}\n\t}\n\treturn(Arm);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Fire_At -- Handles firing a projectile from an aircraft.                     *\n *                                                                                             *\n *    Sometimes, aircraft firing needs special handling. Example: for napalm bombs, the        *\n *    bomb travels forward at nearly the speed of the delivery aircraft, not necessarily the   *\n *    default speed defined in the BulletTypeClass structure.                                  *\n *                                                                                             *\n * INPUT:   target   -- The target that the projectile is heading for.                         *\n *                                                                                             *\n *          which    -- Which weapon to use in the attack. 0=primary, 1=secondary.             *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the bullet that was created as a result of this attack.  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nBulletClass * AircraftClass::Fire_At(TARGET target, int which)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tPassenger aircraft will actually paradrop their cargo instead of\n\t**\tfiring their weapon.\n\t*/\n\tif (Is_Something_Attached()) {\n\t\tParadrop_Cargo();\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tIf the weapon is actually a camera, then perform the \"snapshot\" of the\n\t**\tground instead of normal weapon fire.\n\t*/\n\tif (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->IsCamera) {\n\t\tif (House->Is_Ally(PlayerPtr)) {\n\t\t\tMap.Sight_From(Coord_Cell(Center_Coord()), 9, House, false);\n\t\t}\n\t\tAmmo = 0;\n\t\tArm = Rearm_Delay(IsSecondShot);\n\t\treturn(0);\n\t}\n\n\n\tBulletClass * bullet = FootClass::Fire_At(target, which);\n\n\tif (bullet) {\n\n\t\t/*\n\t\t**\tFalling bullets move at a speed proportionate to the delivery craft.\n\t\t*/\n\t\tif (bullet->Class->IsDropping) {\n\t\t\tbullet->Fly_Speed(40, MPH_MEDIUM_SLOW);\t\t// TCTC To fix.\n\t\t}\n\t}\n\treturn(bullet);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Take_Damage -- Applies damage to the aircraft.                               *\n *                                                                                             *\n *    This routine is used to apply damage to the specified aircraft. This is where any        *\n *    special crash animation will be initiated.                                               *\n *                                                                                             *\n * INPUT:   damage   -- Reference to the damage that will be applied to the aircraft.          *\n *                      This value will be filled in with the actual damage that was           *\n *                      applied.                                                               *\n *                                                                                             *\n *          distance -- Distance from the source of the explosion to this aircraft.            *\n *                                                                                             *\n *          warhead  -- The warhead type that the damage occurs from.                          *\n *                                                                                             *\n *          source   -- Pointer to the originator of the damage. This can be used so that      *\n *                      proper \"thank you\" can be delivered.                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the result of the damage as it affects this aircraft.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/26/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nResultType AircraftClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, int forced)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tResultType res = RESULT_NONE;\n\n\t/*\n\t**\tFlying aircraft take half damage.\n\t*/\n\tif (Height) {\n\t\tdamage /= 2;\n\t}\n\n\t/*\n\t**\tApply the damage to the aircraft.\n\t*/\n\tres = FootClass::Take_Damage(damage, distance, warhead, source, forced);\n\n\t/*\n\t**\tSpecial action is performed if the aircraft is killed -- the cargo is destroyed\n\t**\tas well.\n\t*/\n\tswitch (res) {\n\t\tcase RESULT_DESTROYED:\n\t\t\tKill_Cargo(source);\n\t\t\tDeath_Announcement();\n\t\t\tnew AnimClass(ANIM_FBALL1, Target_Coord());\n\n\t\t\t/*\n\t\t\t**\tParachute a survivor if possible.\n\t\t\t*/\n\t\t\tif (Class->IsCrew && Percent_Chance(90) && Map[Center_Coord()].Is_Clear_To_Move(SPEED_FOOT, true, false)) {\n\t\t\t\tInfantryClass * infantry = new InfantryClass(INFANTRY_E1, House->Class->House);\n\t\t\t\tif (infantry != NULL) {\n\t\t\t\t\tif (!infantry->Paradrop(Center_Coord())) {\n\t\t\t\t\t\tdelete infantry;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdelete this;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\tcase RESULT_HALF:\n\t\t\tbreak;\n\t}\n\n\treturn(res);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Mission_Move -- Handles movement mission.                                    *\n *                                                                                             *\n *    This state machine routine is used when an aircraft (usually helicopter) is to move      *\n *    from one location to another. It will handle any necessary take off and landing this     *\n *    may require.                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames that should elapse before this routine      *\n *          is called again.                                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftClass::Mission_Move(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsFixedWing) {\n\n\t\tenum  {\n\t\t\tTAKE_OFF,\n\t\t\tFLY_TOWARD_TARGET\n\t\t};\n\n\t\tswitch (Status) {\n\t\t\tint distance;\n\n\t\t\tcase TAKE_OFF:\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the aircraft is high enough to begin its mission, then do so.\n\t\t\t\t*/\n\t\t\t\tif (Process_Take_Off())  {\n\t\t\t\t\tIsTakingOff = false;\n\t\t\t\t\tSet_Speed(0xFF);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tAfter takeoff is complete, break radio contact.\n\t\t\t\t\t*/\n\t\t\t\t\tif (In_Radio_Contact() && Map[Coord].Cell_Building() == Contact_With_Whom()) {\n\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t}\n\n\t\t\t\t\tStatus = FLY_TOWARD_TARGET;\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\tcase FLY_TOWARD_TARGET:\n\t\t\t\tPrimaryFacing.Set_Desired(Direction(NavCom));\n\t\t\t\tdistance = Distance(NavCom);\n\n\t\t\t\tif (distance < 0x00C0) {\n\t\t\t\t\tMissionType mission = MISSION_GUARD;\n\n\t\t\t\t\tif (!IsALoaner) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tNormal aircraft try to find a good landing spot to rest.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tBuildingClass * building = Find_Docking_Bay(Class->Building, false);\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tif (!Class->IsFixedWing) {\n\t\tint dist = 0x7FFFFFFF;\n\t\tif (building) dist=Distance(building);\n\t\tfor (int index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass *ship = Vessels.Ptr(index);\n\t\t\tif (ship != NULL && *ship == VESSEL_CARRIER && !ship->IsInLimbo && ship->IsActive && ship->House == House && ship->How_Many() < ship->Class->Max_Passengers() ) {\n\t\t\t\tif (Distance(ship) < dist || !building) {\n\t\t\t\t\tbuilding = (BuildingClass *)ship;\n\t\t\t\t\tdist = Distance(ship);\n\t\t\t\t}\n//\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n#endif\n\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\tif (building && (Transmit_Message(RADIO_HELLO, building) == RADIO_ROGER || building->What_Am_I() == RTTI_VESSEL) ) {\n#else\n\t\t\t\t\t\tif (building && Transmit_Message(RADIO_HELLO, building) == RADIO_ROGER) {\n#endif\n\t\t\t\t\t\t\tmission = MISSION_ENTER;\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tif (building->What_Am_I() == RTTI_VESSEL) {\n\t\tAssign_Destination(building->As_Target());\n\t}\n#endif\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tAssign_Destination(Good_LZ());\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** If this aircraft has nowhere else to go, meaning that\n\t\t\t\t\t\t\t** there is no airfield available, then it has to crash.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Is_Target_Cell(NavCom)) {\n\n\t\t\t\t\t\t\t\tif (Process_Landing()) {\n\t\t\t\t\t\t\t\t\tStrength = 1;\n\t\t\t\t\t\t\t\t\tint damage = Strength;\n\t\t\t\t\t\t\t\t\tTake_Damage(damage, 0, WARHEAD_AP, 0, true);\n\t\t\t\t\t\t\t\t\treturn(1);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn(500);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tmission = MISSION_MOVE;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tAssign_Mission(mission);\n\t\t\t\t\t\tCommence();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!Team.Is_Valid()) {\n\t\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn(5);\n\t}\n\n\tenum {\n\t\tVALIDATE_LZ,\n\t\tTAKE_OFF,\n\t\tFLY_TO_LZ,\n\t\tLAND\n\t};\n\tswitch (Status) {\n\n\t\t/*\n\t\t**\tDouble check and change LZ if necessary.\n\t\t*/\n\t\tcase VALIDATE_LZ:\n\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\tEnter_Idle_Mode();\n\t\t\t} else {\n\t\t\t\tif (!Is_LZ_Clear(NavCom) || !Cell_Seems_Ok(As_Cell(NavCom))) {\n\t\t\t\t\tAssign_Destination(New_LZ(NavCom));\n\t\t\t\t\tif (Team.Is_Valid()) {\n\t\t\t\t\t\tTeam->Assign_Mission_Target(NavCom);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tStatus = TAKE_OFF;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tTake off if necessary.\n\t\t*/\n\t\tcase TAKE_OFF:\n\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\tStatus = VALIDATE_LZ;\n\t\t\t} else {\n\t\t\t\tif (Process_Take_Off()) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tAfter takeoff is complete, break radio contact with any helipad that this\n\t\t\t\t\t**\thelicopter is taking off from.\n\t\t\t\t\t*/\n\t\t\t\t\tif (In_Radio_Contact() && Map[Coord].Cell_Building() == Contact_With_Whom()) {\n\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t}\n\n\t\t\t\t\tStatus = FLY_TO_LZ;\n\t\t\t\t}\n\t\t\t\treturn(1);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tFly toward target.\n\t\t*/\n\t\tcase FLY_TO_LZ:\n\t\t\tif (Is_LZ_Clear(NavCom)) {\n\t\t\t\tint distance = Process_Fly_To(true, NavCom);\n\n\t\t\t\tif (distance < 0x0080) {\n\t\t\t\t\tif (Target_Legal(TarCom)) {\n\t\t\t\t\t\tSecondaryFacing.Set_Desired(Direction(TarCom));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSecondaryFacing.Set_Desired(Pose_Dir());\n\t\t\t\t\t}\n\n\t\t\t\t\tif (distance < 0x0010) {\n\t\t\t\t\t\tStatus = LAND;\n\t\t\t\t\t}\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\n//\t\t\t\tSecondaryFacing.Set_Desired(::Direction(Fire_Coord(0), As_Coord(NavCom)));\n\t\t\t\tSecondaryFacing.Set_Desired(Direction(NavCom));\n\n\t\t\t} else {\n\t\t\t\tAssign_Destination(New_LZ(NavCom));\n\t\t\t\tif (Team.Is_Valid()) {\n\t\t\t\t\tTeam->Assign_Mission_Target(NavCom);\n\t\t\t\t}\n\t\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\t\tStatus = LAND;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn(1);\n\n\t\t/*\n\t\t**\tLand on target.\n\t\t*/\n\t\tcase LAND:\n\t\t\tif (IsTakingOff) {\n\t\t\t\tAssign_Destination(New_LZ(NavCom));\n\t\t\t\tif (Team.Is_Valid()) {\n\t\t\t\t\tTeam->Assign_Mission_Target(NavCom);\n\t\t\t\t}\n\t\t\t\tStatus = TAKE_OFF;\n\t\t\t}\n\t\t\tif (Process_Landing()) {\n\t\t\t\tif (MissionQueue == MISSION_NONE) {\n\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn(1);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Enter_Idle_Mode -- Gives the aircraft an appropriate mission.                *\n *                                                                                             *\n *    Use this routine when the mission for the aircraft is in doubt. This routine will find   *\n *    an appropriate mission for the aircraft and dispatch it.                                 *\n *                                                                                             *\n * INPUT:   initial  -- Is this called when the unit just leaves a factory or is initially     *\n *                      or is initially placed on the map?                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/05/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Enter_Idle_Mode(bool )\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tMissionType mission = MISSION_GUARD;\n\tif (Class->IsFixedWing) {\n\t\tif (In_Which_Layer() == LAYER_GROUND) {\n\t\t\tif (IsALoaner) {\n\t\t\t\tmission = MISSION_RETREAT;\n\t\t\t} else {\n\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\tmission = MISSION_GUARD;\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf this transport is a loaner and part of a team, then remove it from\n\t\t\t**\tthe team it is attached to.\n\t\t\t*/\n\t\t\tif ((IsALoaner && House->IsHuman) || (!House->IsHuman && !Ammo)) {\n\t\t\t\tif (Team.Is_Valid() && Team->Has_Entered_Map()) {\n\t\t\t\t\tTeam->Remove(this);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (Team.Is_Valid()) return;\n\n\t\t\t/*\n\t\t\t**\tWeapon equipped helicopters that run out of ammo and were\n\t\t\t**\tbrought in as reinforcements will leave the map.\n\t\t\t*/\n\t\t\tif (Mission != MISSION_ATTACK && IsALoaner && Ammo == 0 && Class->PrimaryWeapon != NULL) {\n\t\t\t\tmission = MISSION_HUNT;\n\t\t\t} else {\n\n\t\t\t\tif (!IsALoaner) {\n\t\t\t\t\t/*\n\t\t\t\t\t**\tNormal aircraft try to find a good landing spot to rest.\n\t\t\t\t\t*/\n\t\t\t\t\tBuildingClass * building = Find_Docking_Bay(Class->Building, false);\n\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\tif (building != NULL && Transmit_Message(RADIO_HELLO, building) == RADIO_ROGER) {\n\t\t\t\t\t\tif (Class->IsFixedWing) {\n\t\t\t\t\t\t\tStatus = 0;\t//BG - reset the mission status to avoid landing on the ground next to the airstrip\n\t\t\t\t\t\t\tif (IsLanding) {\n\t\t\t\t\t\t\t\tProcess_Take_Off();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmission = MISSION_ENTER;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmission = MISSION_RETREAT;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\tif (In_Which_Layer() == LAYER_GROUND) {\n\t\t\tif (IsALoaner) {\n\t\t\t\tif (Is_Something_Attached()) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIn the case of a computer controlled helicopter that hold passengers,\n\t\t\t\t\t**\tdon't unload when landing. Wait for specific instructions from the\n\t\t\t\t\t**\tcontrolling team.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Team.Is_Valid()) {\n//\t\t\t\t\tif (Team.Is_Valid() && !House->IsHuman) {\n\t\t\t\t\t\tmission = MISSION_GUARD;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmission = MISSION_UNLOAD;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tmission = MISSION_RETREAT;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\tmission = MISSION_GUARD;\n\t\t\t}\n\t\t} else {\n\t\t\tif (Is_Something_Attached()) {\n\t\t\t\tif (IsALoaner) {\n\t\t\t\t\tif (Team) {\n\t\t\t\t\t\tmission = MISSION_GUARD;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmission = MISSION_UNLOAD;\n\t\t\t\t\t\tAssign_Destination(Good_LZ());\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tAssign_Destination(Good_LZ());\n\t\t\t\t\tmission = MISSION_MOVE;\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this transport is a loaner and part of a team, then remove it from\n\t\t\t\t**\tthe team it is attached to.\n\t\t\t\t*/\n\t\t\t\tif ((IsALoaner && House->IsHuman) || (!House->IsHuman && !Ammo)) {\n\t\t\t\t\tif (Team.Is_Valid() && Team->Has_Entered_Map()) {\n\t\t\t\t\t\tTeam->Remove(this);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (Class->PrimaryWeapon != NULL) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tWeapon equipped helicopters that run out of ammo and were\n\t\t\t\t\t**\tbrought in as reinforcements will leave the map.\n\t\t\t\t\t*/\n\t\t\t\t\tif (IsALoaner) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf it has no ammo, then break off of the team and leave the map.\n\t\t\t\t\t\t**\tIf it can fight, then give it fighting orders.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (Ammo == 0) {\n\t\t\t\t\t\t\tif (Team.Is_Valid()) Team->Remove(this);\n\t\t\t\t\t\t\tmission = MISSION_RETREAT;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (!Team.Is_Valid()) {\n\t\t\t\t\t\t\t\tmission = MISSION_HUNT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tNormal aircraft try to find a good landing spot to rest.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tBuildingClass * building = Find_Docking_Bay(Class->Building, false);\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tif (!Class->IsFixedWing) {\n\t\tint dist = 0x7FFFFFFF;\n\t\tif (building) dist=Distance(building);\n\t\tfor (int index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass *ship = Vessels.Ptr(index);\n\t\t\tif (ship != NULL && *ship == VESSEL_CARRIER && !ship->IsInLimbo && ship->IsActive && ship->House == House && ship->How_Many() < ship->Class->Max_Passengers()/* && !ship->In_Radio_Contact()*/) {\n\t\t\t\tif (Distance(ship) < dist || !building) {\n\t\t\t\t\tbuilding = (BuildingClass *)ship;\n\t\t\t\t\tdist = Distance(ship);\n\t\t\t\t}\n//\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n#endif\n\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\tif (building && (Transmit_Message(RADIO_HELLO, building) == RADIO_ROGER || building->What_Am_I() == RTTI_VESSEL) ) {\n#else\n\t\t\t\t\t\tif (building && Transmit_Message(RADIO_HELLO, building) == RADIO_ROGER) {\n#endif\n\t\t\t\t\t\t\tmission = MISSION_ENTER;\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\t\tif (building->What_Am_I() == RTTI_VESSEL) {\n\t\t\t\t\t\t\t\tAssign_Destination(building->As_Target());\n\t\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tAssign_Destination(Good_LZ());\n\t\t\t\t\t\t\tmission = MISSION_MOVE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (Team) return;\n\n\t\t\t\t\tAssign_Destination(Good_LZ());\n\t\t\t\t\tmission = MISSION_MOVE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tAssign_Mission(mission);\n\tCommence();\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Process_Fly_To -- Handles state machine for flying to destination.           *\n *                                                                                             *\n *    This support routine is used when the helicopter is to fly to the destination. It can    *\n *    optionally slow the helicopter down as it approaches the destination.                    *\n *                                                                                             *\n * INPUT:   slowdown -- Should the aircraft be slowed down when it approaches the dest?        *\n *                                                                                             *\n * OUTPUT:  Returns with the distance remaining between the aircraft and the destination.      *\n *                                                                                             *\n * WARNINGS:   Because the aircraft can move at a fast speed, the distance to target value     *\n *             will probably never be zero. The likely case will be that the aircraft          *\n *             overshoots the target.                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/14/1995 JLB : Created.                                                                 *\n *   03/05/1996 JLB : Specifies destination target value.                                      *\n *=============================================================================================*/\nint AircraftClass::Process_Fly_To(bool slowdown, TARGET dest)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsFixedWing) slowdown = false;\n\n\tCOORDINATE coord;\n\tif (Is_Target_Building(dest)) {\n\t\tcoord = As_Building(dest)->Docking_Coord();\n\t} else {\n\t\tcoord = As_Coord(dest);\n\t}\n\tint distance = Distance(coord);\n\n\tPrimaryFacing.Set_Desired(Direction(coord));\n\n\tif (slowdown) {\n\t\tint speed = min(distance, 0x0300);\n\t\tspeed = Bound(speed/3, 0x0020, 0x00FF);\n\t\tif (Speed != speed) {\n\t\t\tSet_Speed(speed);\n\t\t}\n\t}\n\n\tif (distance < 0x0010) {\n\t\tif (slowdown) {\n\t\t\tSet_Speed(0);\n\t\t}\n\t\tdistance = 0;\n\t}\n\treturn(distance);\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * AircraftClass::Debug_Dump -- Displays the status of the aircraft to the mono monitor.       *\n *                                                                                             *\n *    This displays the current status of the aircraft class to the mono monitor. By this      *\n *    display bugs may be tracked down or prevented.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tmono->Set_Cursor(0, 0);\n\tmono->Print(Text_String(TXT_DEBUG_AIRCRAFT));\n\tmono->Set_Cursor(1, 11);mono->Printf(\"%3d\", AttacksRemaining);\n\n\tFootClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * AircraftClass::Active_Click_With -- Handles clicking over specified object.                 *\n *                                                                                             *\n *    This routine is used when the player clicks over the speicifed object. It will assign    *\n *    the appropriate mission to the aircraft.                                                 *\n *                                                                                             *\n * INPUT:   action   -- The action that was nominally determined by the What_Action function.  *\n *                                                                                             *\n *          object   -- The object over which the mouse was clicked.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine will alter the game sequence and causes an event packet to be      *\n *             propagated to all connected machines.                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Active_Click_With(ActionType action, ObjectClass * object)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\taction = What_Action(object);\n\n\tswitch (action) {\n\t\tcase ACTION_NOMOVE:\n\t\t\treturn;\n\n\t\tcase ACTION_ENTER:\n\t\t\tPlayer_Assign_Mission(MISSION_ENTER, TARGET_NONE, object->As_Target());\n\t\t\tbreak;\n\n\t\tcase ACTION_SELF:\n\t\t\tPlayer_Assign_Mission(MISSION_UNLOAD, TARGET_NONE, TARGET_NONE);\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tFootClass::Active_Click_With(action, object);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Active_Click_With -- Handles clicking over specified cell.                   *\n *                                                                                             *\n *    This routine is used when the player clicks the mouse of the specified cell. It will     *\n *    assign the appropriate mission to the aircraft.                                          *\n *                                                                                             *\n * INPUT:   action   -- The action nominally determined by What_Action().                      *\n *                                                                                             *\n *          cell     -- The cell over which the mouse was clicked.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine will affect the game sequence and causes an event object to be     *\n *             propagated to all connected machines.                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Active_Click_With(ActionType action, CELL cell)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tFootClass::Active_Click_With(action, cell);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Player_Assign_Mission -- Handles player input to assign a mission.           *\n *                                                                                             *\n *    This routine is called as a result of player input with the intent to change the         *\n *    mission of the aircraft.                                                                 *\n *                                                                                             *\n * INPUT:   mission  -- The mission requested of the aircraft.                                 *\n *                                                                                             *\n *          target   -- The value to assign to the aircraft's targeting computer.              *\n *                                                                                             *\n *          dest.    -- The value to assign to the aircraft's navigation computer.             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The mission specified will be executed at an indeterminate future game frame.   *\n *             This is controlled by net/modem propagation delay.                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Player_Assign_Mission(MissionType mission, TARGET target, TARGET destination)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (AllowVoice) {\n\t\tif (mission == MISSION_ATTACK) {\n\t\t\tResponse_Attack();\n\t\t} else {\n\t\t\tResponse_Move();\n\t\t}\n\t}\n\tQueue_Mission(TargetClass(this), mission, target, destination);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::What_Action -- Determines what action to perform.                            *\n *                                                                                             *\n *    This routine is used to determine what action will likely be performed if the mouse      *\n *    were clicked over the object specified. The display system calls this routine to         *\n *    control the mouse shape.                                                                 *\n *                                                                                             *\n * INPUT:   target   -- Pointer to the object that the mouse is currently over.                *\n *                                                                                             *\n * OUTPUT:  Returns with the action that will occur if the mouse were clicked over the         *\n *          object specified.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType AircraftClass::What_Action(ObjectClass const * target) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tActionType action = FootClass::What_Action(target);\n\n\tif (action == ACTION_SELF && !How_Many()) {\n\t\taction = ACTION_NONE;\n\t}\n\n\tif (action == ACTION_ATTACK && Class->PrimaryWeapon == NULL) {\n\t\taction = ACTION_NONE;\n\t}\n\n\tif (House->IsPlayerControl && House->Is_Ally(target) && target->What_Am_I() == RTTI_BUILDING && ((AircraftClass *)this)->Transmit_Message(RADIO_CAN_LOAD, (TechnoClass*)target) == RADIO_ROGER) {\n\t\taction = ACTION_ENTER;\n\t}\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tif (!Class->IsFixedWing && House->IsPlayerControl && House->Is_Ally(target) && target->What_Am_I() == RTTI_VESSEL && *(VesselClass *)target == VESSEL_CARRIER && ((AircraftClass *)this)->Transmit_Message(RADIO_CAN_LOAD, (TechnoClass*)target) == RADIO_ROGER) {\n\t\taction = ACTION_ENTER;\n\t}\n#endif\n\n\tif (Class->IsFixedWing && action == ACTION_MOVE) {\n\t\taction = ACTION_NOMOVE;\n\t}\n\n\tif (action == ACTION_NONE) {\n\t\taction = What_Action(Coord_Cell(target->Center_Coord()));\n\t}\n\n\t/*\n\t**\tSpecial return to friendly repair factory action.\n\t*/\n\tif (House->IsPlayerControl && action == ACTION_SELECT && target->What_Am_I() == RTTI_BUILDING) {\n\t\tBuildingClass * building = (BuildingClass *)target;\n\t\tif (building->Class->Type == STRUCT_REPAIR && !building->In_Radio_Contact() && !building->Is_Something_Attached()) {\n\t\t\taction = ACTION_ENTER;\n\t\t}\n\t}\n\n\treturn(action);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::What_Action -- Determines what action to perform.                            *\n *                                                                                             *\n *    This routine will determine what action would occur if the mouse were clicked over the   *\n *    cell specified. The display system calls this routine to determine what mouse shape      *\n *    to use.                                                                                  *\n *                                                                                             *\n * INPUT:   cell  -- The cell over which the mouse is currently positioned.                    *\n *                                                                                             *\n * OUTPUT:  Returns with the action that will be performed if the mouse were clicked at the    *\n *          specified cell location.                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType AircraftClass::What_Action(CELL cell) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tActionType action = FootClass::What_Action(cell);\n\n\tif (action == ACTION_MOVE && Session.Type == GAME_NORMAL && !Map[cell].IsVisible) {\n\t\taction = ACTION_NOMOVE;\n\t}\n\n\tif (action == ACTION_ATTACK && Class->PrimaryWeapon == NULL) {\n\t\taction = ACTION_NONE;\n\t}\n\n\tif (Class->IsFixedWing && action == ACTION_MOVE) {\n\t\taction = ACTION_NOMOVE;\n\t}\n\n\treturn(action);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Pose_Dir -- Fetches the natural landing facing.                              *\n *                                                                                             *\n *    Use this routine to get the desired facing the aircraft should assume when landing.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the normal default facing the aircraft should have when landed.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *   03/04/1996 JLB : Fixed wing aircraft always face down the runway.                         *\n *=============================================================================================*/\nDirType AircraftClass::Pose_Dir(void) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == AIRCRAFT_TRANSPORT) {\n\t\treturn(DIR_N);\n\t}\n\tif (Class->IsFixedWing)  {\n\t\treturn(DIR_E);\n\t}\n\treturn(DIR_NE);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Mission_Attack -- Handles the attack mission for aircraft.                   *\n *                                                                                             *\n *    This routine is the state machine that handles the attack mission for aircraft. It will  *\n *    handling homing in on and firing on the target in the aircraft's targeting computer.     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game ticks to pass before this routine must be called   *\n *          again.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *   09/22/1995 JLB : Fixes brain dead helicopter for Nod scen #7.                             *\n *=============================================================================================*/\nint AircraftClass::Mission_Attack(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsFixedWing) {\n\t\treturn(Mission_Hunt());\n\t}\n\n\tenum {\n\t\tVALIDATE_AZ,\n\t\tPICK_ATTACK_LOCATION,\n\t\tTAKE_OFF,\n\t\tFLY_TO_POSITION,\n\t\tFIRE_AT_TARGET,\n\t\tFIRE_AT_TARGET2,\n\t\tRETURN_TO_BASE\n\t};\n\tswitch (Status) {\n\n\t\t/*\n\t\t**\tDouble check target and validate the attack zone.\n\t\t*/\n\t\tcase VALIDATE_AZ:\n\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t} else {\n\t\t\t\tStatus = PICK_ATTACK_LOCATION;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tPick a good location to attack from.\n\t\t*/\n\t\tcase PICK_ATTACK_LOCATION:\n\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t} else {\n\t\t\t\tAssign_Destination(Good_Fire_Location(TarCom));\n\t\t\t\tif (Target_Legal(NavCom)) {\n\t\t\t\t\tStatus = TAKE_OFF;\n\t\t\t\t} else {\n\t\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tTake off (if necessary).\n\t\t*/\n\t\tcase TAKE_OFF:\n\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t} else {\n\t\t\t\tif (Process_Take_Off()) {\n\t\t\t\t\tStatus = FLY_TO_POSITION;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tBreak off radio contact with the helipad it is taking off from.\n\t\t\t\t\t*/\n\t\t\t\t\tif (In_Radio_Contact() && Map[Coord].Cell_Building() == Contact_With_Whom()) {\n\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tStart flying toward the destination by skewing at first.\n\t\t\t\t\t**\tAs the flight progresses, the body will rotate to face\n\t\t\t\t\t**\tthe direction of travel.\n\t\t\t\t\t*/\n\t\t\t\t\tint diff = SecondaryFacing.Difference(Direction(NavCom));\n\t\t\t\t\tdiff = Bound(diff, -128, 128);\n\t\t\t\t\tPrimaryFacing = DirType((int)SecondaryFacing.Current()+diff);\n\t\t\t\t}\n\t\t\t\treturn(1);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tFly to attack location.\n\t\t*/\n\t\tcase FLY_TO_POSITION:\n\t\t\tif (Target_Legal(TarCom)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the navcom was cleared mysteriously, then try to pick\n\t\t\t\t**\ta new attack location. This is a likely event if the player\n\t\t\t\t**\tclicks on a new target while in flight to an existing target.\n\t\t\t\t*/\n\t\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\t\tStatus = PICK_ATTACK_LOCATION;\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\n\t\t\t\tint distance = Process_Fly_To(true, NavCom);\n\n\t\t\t\tif (distance < 0x0200) {\n\t\t\t\t\tSecondaryFacing.Set_Desired(Direction(TarCom));\n\n\t\t\t\t\tif (distance < 0x0010) {\n\t\t\t\t\t\tStatus = FIRE_AT_TARGET;\n\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tSecondaryFacing.Set_Desired(::Direction(Fire_Coord(0), As_Coord(NavCom)));\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t}\n\t\t\treturn(1);\n\n\t\t/*\n\t\t**\tFire at the target.\n\t\t*/\n\t\tcase FIRE_AT_TARGET:\n\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t\treturn(1);\n\t\t\t}\n\n\t\t\tPrimaryFacing.Set_Desired(Direction(TarCom));\n\t\t\tSecondaryFacing.Set_Desired(Direction(TarCom));\n\t\t\tswitch (Can_Fire(TarCom, 0)) {\n\t\t\t\tcase FIRE_CLOAKED:\n\t\t\t\t\tDo_Uncloak();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase FIRE_OK:\n\t\t\t\t\tFire_At(TarCom, 0);\n\t\t\t\t\tMap[::As_Cell(TarCom)].Incoming(Coord, true);\n\t\t\t\t\tStatus = FIRE_AT_TARGET2;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase FIRE_REARM:\n\t\t\t\tcase FIRE_FACING:\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tif (!Ammo) {\n\t\t\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tStatus = FIRE_AT_TARGET2;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\treturn(1);\n\n\t\t/*\n\t\t**\tFire at the target.\n\t\t*/\n\t\tcase FIRE_AT_TARGET2:\n\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t\treturn(1);\n\t\t\t}\n\n\t\t\tPrimaryFacing.Set_Desired(Direction(TarCom));\n\t\t\tSecondaryFacing.Set_Desired(Direction(TarCom));\n\t\t\tswitch (Can_Fire(TarCom, 0)) {\n\t\t\t\tcase FIRE_CLOAKED:\n\t\t\t\t\tDo_Uncloak();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase FIRE_REARM:\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase FIRE_OK:\n\t\t\t\t\tFire_At(TarCom, 0);\n\t\t\t\t\tMap[::As_Cell(TarCom)].Incoming(Coord, true);\n\n\t\t\t\t\tif (Ammo) {\n\t\t\t\t\t\tStatus = Rule.IsCurleyShuffle ? PICK_ATTACK_LOCATION : FIRE_AT_TARGET;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tif (!Ammo) {\n\t\t\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!In_Range(TarCom)) {\n\t\t\t\t\t\t\tStatus = PICK_ATTACK_LOCATION;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tStatus = Rule.IsCurleyShuffle ? PICK_ATTACK_LOCATION : FIRE_AT_TARGET;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tFly back to landing spot.\n\t\t*/\n\t\tcase RETURN_TO_BASE:\n\t\t\t/*\n\t\t\t**\tBreak off of firing at the target if there is no more\n\t\t\t**\tpoint in attacking it this mission. The player will\n\t\t\t**\treassign a target for the next mission.\n\t\t\t*/\n\t\t\tif (!Ammo && (IsALoaner || House->IsHuman)) {\n\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t}\n\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\tEnter_Idle_Mode();\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * AircraftClass::New_LZ -- Find a good landing zone.                                          *\n *                                                                                             *\n *    Use this routine to locate a good landing zone that is nearby the location specified.    *\n *    By using this routine it is possible to assign the same landing zone to several          *\n *    aircraft and they will land nearby without conflict.                                     *\n *                                                                                             *\n * INPUT:   oldlz -- Target value of desired landing zone (usually a cell target value).       *\n *                                                                                             *\n * OUTPUT:  Returns with the new good landing zone. It might be the same value passed in.      *\n *                                                                                             *\n * WARNINGS:   The landing zone might be a goodly distance away from the ideal if there is     *\n *             extensive blocking terrain in the vicinity.                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTARGET AircraftClass::New_LZ(TARGET oldlz) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Target_Legal(oldlz) && (!Is_LZ_Clear(oldlz) || !Cell_Seems_Ok(As_Cell(oldlz)))) {\n\t\tCOORDINATE coord = As_Coord(oldlz);\n\n\t\t/*\n\t\t**\tScan outward in a series of concentric rings up to certain distance\n\t\t**\tin cells.\n\t\t*/\n\t\tfor (int radius = 0; radius < Rule.LZScanRadius / CELL_LEPTON_W; radius++) {\n\t\t\tFacingType modifier = Random_Pick(FACING_N, FACING_NW);\n\t\t\tCELL lastcell = -1;\n\n\t\t\t/*\n\t\t\t**\tPerform a radius scan out from the original center location. Try to\n\t\t\t**\tfind a cell that is allowed to be a legal LZ.\n\t\t\t*/\n\t\t\tfor (FacingType facing = FACING_N; facing < FACING_COUNT; facing++) {\n\t\t\t\tCELL newcell = Coord_Cell(Coord_Move(coord, Facing_Dir(facing+modifier), radius * ICON_LEPTON_W));\n\t\t\t\tif (Map.In_Radar(newcell)) {\n\t\t\t\t\tTARGET newtarget = ::As_Target(newcell);\n\n\t\t\t\t\tif (newcell != lastcell && Is_LZ_Clear(newtarget) && Cell_Seems_Ok(newcell)) {\n\t\t\t\t\t\treturn(newtarget);\n\t\t\t\t\t}\n\t\t\t\t\tlastcell = newcell;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(oldlz);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Receive_Message -- Handles receipt of radio messages.                        *\n *                                                                                             *\n *    This routine receives all radio messages directed at this aircraft. It is used to handle *\n *    all inter-object coordination. Typically, this would be for transport helicopters and    *\n *    other complex landing operations required of helicopters.                                *\n *                                                                                             *\n * INPUT:   from     -- The source of this radio message.                                      *\n *                                                                                             *\n *          message  -- The message itself.                                                    *\n *                                                                                             *\n *          param    -- An optional parameter that may be used to transfer additional          *\n *                      data.                                                                  *\n *                                                                                             *\n * OUTPUT:  Returns with the radio response from the aircraft.                                 *\n *                                                                                             *\n * WARNINGS:   Some radio messages are handled by the base classes.                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nRadioMessageType AircraftClass::Receive_Message(RadioClass * from, RadioMessageType message, long & param)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tswitch (message) {\n\n\t\tcase RADIO_PREPARED:\n\t\t\tif (Target_Legal(TarCom)) return(RADIO_NEGATIVE);\n\t\t\tif ((Height == 0 && Ammo == Class->MaxAmmo) || (Height > 0 && Ammo > 0)) return(RADIO_ROGER);\n\t\t\treturn(RADIO_NEGATIVE);\n\n\t\t/*\n\t\t**\tSomething disastrous has happened to the object in contact with. Fall back\n\t\t**\tand regroup. This means that any landing process is immediately aborted.\n\t\t*/\n\t\tcase RADIO_RUN_AWAY:\n\t\t\tif (IsLanding) {\n\t\t\t\tIsLanding = false;\n\t\t\t\tIsTakingOff = true;\n\t\t\t}\n\t\t\tif (Class->IsFixedWing) {\n\t\t\t\tAssign_Destination(Good_LZ());\n\t\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\t\tAssign_Mission(MISSION_RETREAT);\n\t\t\t\t} else {\n\t\t\t\t\tAssign_Mission(MISSION_MOVE);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tScatter(0, true);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThe ground control requests that this specified landing spot be used.\n\t\t*/\n\t\tcase RADIO_MOVE_HERE:\n\t\t\tFootClass::Receive_Message(from, message, param);\n\t\t\tif (Is_Target_Building(param)) {\n\t\t\t\tif (Transmit_Message(RADIO_CAN_LOAD, As_Techno(param)) != RADIO_ROGER) {\n\t\t\t\t\treturn(RADIO_NEGATIVE);\n\t\t\t\t}\n\t\t\t\tAssign_Mission(MISSION_ENTER);\n\t\t\t\tAssign_Destination((TARGET)param);\n\t\t\t} else {\n\t\t\t\tAssign_Mission(MISSION_MOVE);\n\t\t\t\tAssign_Destination((TARGET)param);\n\t\t\t}\n\t\t\tCommence();\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t**\tGround control is requesting if the aircraft requires navigation direction.\n\t\t*/\n\t\tcase RADIO_NEED_TO_MOVE:\n\t\t\tFootClass::Receive_Message(from, message, param);\n\t\t\tif (!Target_Legal(NavCom) && !IsTakingOff && !IsLanding) {\n\t\t\t\treturn(RADIO_ROGER);\n\t\t\t}\n\t\t\treturn(RADIO_NEGATIVE);\n\n\t\t/*\n\t\t**\tThis message is sent by the passenger when it determines that it has\n\t\t**\tentered the transport.\n\t\t*/\n\t\tcase RADIO_IM_IN:\n\t\t\tif (How_Many() == Class->Max_Passengers()) {\n\t\t\t\tClose_Door(5, 4);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf a civilian has entered the transport, then the transport will immediately\n\t\t\t**\tfly off the map.\n\t\t\t*/\n\t\t\tif (_Counts_As_Civ_Evac(from)) {\n\t\t\t\tAssign_Mission(MISSION_RETREAT);\n\t\t\t}\n\t\t\treturn(RADIO_ATTACH);\n\n\t\t/*\n\t\t**\tDocking maintenance message received. Check to see if new orders should be given\n\t\t**\tto the impatient unit.\n\t\t*/\n\t\tcase RADIO_DOCKING:\n\t\t\tif (Class->Max_Passengers() > 0 && How_Many() < Class->Max_Passengers()) {\n\t\t\t\tFootClass::Receive_Message(from, message, param);\n\n\t\t\t\tif (!IsTethered && !IsLanding && !IsTakingOff && Height == 0) {\n\n\t\t\t\t\tOpen_Door(5, 4);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the potential passenger needs someplace to go, then figure out a good\n\t\t\t\t\t**\tspot and tell it to go.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Transmit_Message(RADIO_NEED_TO_MOVE, from) == RADIO_ROGER) {\n\t\t\t\t\t\tCELL cell;\n\t\t\t\t\t\t/*DirType dir =*/ Desired_Load_Dir(from, cell);\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf no adjacent free cells are detected, then passenger loading\n\t\t\t\t\t\t**\tcannot occur. Break radio contact.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (cell == 0) {\n\t\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT, from);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tparam = (long)::As_Target(cell);\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tTell the potential passenger where it should go. If the passenger is\n\t\t\t\t\t\t\t**\talready at the staging location, then tell it to move onto the transport\n\t\t\t\t\t\t\t**\tdirectly.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Transmit_Message(RADIO_MOVE_HERE, param, from) == RADIO_YEA_NOW_WHAT) {\n\t\t\t\t\t\t\t\tparam = (long)As_Target();\n\t\t\t\t\t\t\t\tTransmit_Message(RADIO_TETHER);\n\t\t\t\t\t\t\t\tif (Transmit_Message(RADIO_MOVE_HERE, param, from) != RADIO_ROGER) {\n\t\t\t\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT, from);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tContact_With_Whom()->Unselect();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(RADIO_ROGER);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tAsks if the passenger can load on this transport.\n\t\t*/\n\t\tcase RADIO_CAN_LOAD:\n\t\t\tif (Class->Max_Passengers() == 0 || from == NULL || !House->Is_Ally(from->Owner())) return(RADIO_STATIC);\n\t\t\tif (/*!In_Radio_Contact() &&*/ How_Many() < Class->Max_Passengers()) {\n\t\t\t\treturn(RADIO_ROGER);\n\t\t\t}\n\t\t\treturn(RADIO_NEGATIVE);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tLet the base class take over processing this message.\n\t*/\n\treturn(FootClass::Receive_Message(from, message, param));\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Desired_Load_Dir -- Determines where passengers should line up.              *\n *                                                                                             *\n *    This routine is used by the transport helicopter to determine the location where the     *\n *    infantry passengers should line up before loading.                                       *\n *                                                                                             *\n * INPUT:   object   -- The object that is trying to load up on this transport.                *\n *                                                                                             *\n *                   -- Reference to the cell that the passengers should move to before the    *\n *                      actual load process may begin.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the direction that the helicopter should face for the load operation. *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/12/1995 JLB : Created.                                                                 *\n *   07/30/1995 JLB : Revamped to scan all adjacent cells.                                     *\n *=============================================================================================*/\nDirType AircraftClass::Desired_Load_Dir(ObjectClass * object, CELL & moveto) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tCELL center = Coord_Cell(Center_Coord());\n\tfor (int sweep = FACING_N; sweep < FACING_S; sweep++) {\n\t\tmoveto = Adjacent_Cell(center, FacingType(FACING_S+sweep));\n\t\tif (Map.In_Radar(moveto) && (Coord_Cell(object->Center_Coord()) == moveto || Map[moveto].Is_Clear_To_Move(SPEED_FOOT, false, false))) return(DIR_N);\n\n\t\tmoveto = Adjacent_Cell(center, FacingType(FACING_S-sweep));\n\t\tif (Map.In_Radar(moveto) && (Coord_Cell(object->Center_Coord()) == moveto || Map[moveto].Is_Clear_To_Move(SPEED_FOOT, false, false))) return(DIR_N);\n\t}\n\treturn(DIR_N);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Process_Take_Off -- State machine support for taking off.                    *\n *                                                                                             *\n *    This routine is used by the main game state machine processor. This utility routine      *\n *    handles a helicopter as it transitions from landed to flying state.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Has the helicopter reached flight level now?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/12/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AircraftClass::Process_Take_Off(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tIsLanding = false;\n\tIsTakingOff = true;\n\n\tif (Class->IsFixedWing)  {\n\t\tSet_Speed(0xFF);\n\t\tif (Height == FLIGHT_LEVEL)  {\n\t\t\treturn(true);\n\t\t}\n\n\t} else {\n\n\t\tswitch (Height) {\n\t\t\tcase 0:\n\t\t\t\tClose_Door(5, 4);\n\t\t\t\tPrimaryFacing = SecondaryFacing;\n\t\t\t\tbreak;\n\n\t\t\tcase FLIGHT_LEVEL/2:\n\t\t\t\tPrimaryFacing.Set_Desired(Direction(NavCom));\n\t\t\t\tbreak;\n\n\t\t\tcase FLIGHT_LEVEL-(FLIGHT_LEVEL/3):\n\t\t\t\tSecondaryFacing.Set_Desired(PrimaryFacing.Desired());\n\t\t\t\tSet_Speed(0x20);\n\t\t\t\tbreak;\n\n\t\t\tcase FLIGHT_LEVEL-(FLIGHT_LEVEL/5):\n\t\t\t\tSet_Speed(0x40);\n\t\t\t\tbreak;\n\n\t\t\tcase FLIGHT_LEVEL:\n\t\t\t\tSet_Speed(0xFF);\n\t\t\t\tIsTakingOff = false;\n\t\t\t\treturn(true);\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Process_Landing -- Landing process state machine handler.                    *\n *                                                                                             *\n *    This is a support routine that is called by the main state machine routines. This        *\n *    routine is responsible for handling the helicopter as it transitions from flight to      *\n *    landing.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Has the helicopter completely landed now?                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/12/1995 JLB : Created.                                                                 *\n *   03/04/1996 JLB : Handles fixed wing aircraft.                                             *\n *=============================================================================================*/\nbool AircraftClass::Process_Landing(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tIsTakingOff = false;\n\tIsLanding = true;\n\n\tif (Class->IsFixedWing)  {\n\t\tint distance = Distance(NavCom);\n\n\t\tif (distance > 0x0100)  {\n\t\t\tSecondaryFacing.Set_Desired(::Direction(Fire_Coord(0), As_Coord(NavCom)));\n\t\t}\n\n\t\tswitch (Height) {\n\t\t\tcase 0:\n\t\t\t\tSet_Speed(0);\n\t\t\t\tIsLanding = false;\n\t\t\t\treturn(true);\n\n\t\t\tdefault:\n//\t\t\t\tif (distance*2 > Class->LandingSpeed) {\n//\t\t\t\t\tSet_Speed(Class->LandingSpeed);\n//\t\t\t\t} else {\n//\t\t\t\t\tSet_Speed(distance/2);\n//\t\t\t\t}\n\n\t\t\t\tSet_Speed(Class->LandingSpeed / House->AirspeedBias);\n\t\t\t\tbreak;\n\t\t}\n\n\t} else {\n\t\tswitch (Height) {\n\t\t\tcase 0:\n\t\t\t\tIsLanding = false;\n\t\t\t\treturn(true);\n\n\t\t\tcase FLIGHT_LEVEL/2:\n\t\t\t\tSet_Speed(0);\n\t\t\t\tbreak;\n\n\t\t\tcase FLIGHT_LEVEL:\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Can_Enter_Cell -- Determines if the aircraft can land at this location.      *\n *                                                                                             *\n *    This routine is used when the passability of a cell needs to be determined. This is      *\n *    necessary when scanning for a location that the aircraft can land.                       *\n *                                                                                             *\n * INPUT:   cell  -- The cell location to check for landing.                                   *\n *                                                                                             *\n * OUTPUT:  Returns a value indicating if the cell is a legal landing spot or not.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/12/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nMoveType AircraftClass::Can_Enter_Cell(CELL cell, FacingType ) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!Map.In_Radar(cell)) return(MOVE_NO);\n\n\tCellClass * cellptr = &Map[cell];\n\n\tObjectClass const * occupier = cellptr->Cell_Occupier();\n\n\tif (occupier == NULL ||\n\t\t!occupier->Is_Techno() ||\n\t\t((TechnoClass *)occupier)->House->Is_Ally(House) ||\n\t\t(((TechnoClass *)occupier)->Cloak != CLOAKED &&\n\t\t\t(ScenarioInit == 0 && (occupier->What_Am_I() != RTTI_BUILDING || !((BuildingClass*)occupier)->Class->IsInvisible)) )\n\t\t) {\n\n\t\tif (!cellptr->Is_Clear_To_Move(SPEED_TRACK, false, false)) return(MOVE_NO);\n\t}\n\n\tif (Session.Type == GAME_NORMAL && IsOwnedByPlayer && !cellptr->IsMapped) {\n\t\treturn(MOVE_NO);\n\t}\n\n\treturn(MOVE_OK);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Good_Fire_Location -- Searches for and finds a good spot to fire from.       *\n *                                                                                             *\n *    Given the specified target, this routine will locate a good spot for the aircraft to     *\n *    fire at the target.                                                                      *\n *                                                                                             *\n * INPUT:   target   -- The target that is desired to be attacked.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the target location of the place that firing should be made from.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/12/1995 JLB : Created.                                                                 *\n *   06/14/1995 JLB : Finer resolution on ring scan.                                           *\n *   11/02/1996 JLB : Bias fire position to get closer to moving objects.                      *\n *=============================================================================================*/\nTARGET AircraftClass::Good_Fire_Location(TARGET target) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Target_Legal(target)) {\n\t\tint range = Weapon_Range(0);\n\t\tCOORDINATE tcoord = As_Coord(target);\n\t\tCELL bestcell = 0;\n\t\tCELL best2cell = 0;\n\t\tint bestval = -1;\n\t\tint best2val = -1;\n\n\t\t/*\n\t\t**\tTry to get closer to a target that is moving.\n\t\t*/\n\t\tCOORDINATE altcoord = 0;\n\t\tif (Is_Target_Object(target) && As_Object(target)->Is_Foot()) {\n\t\t\tTARGET alttarg = ((FootClass *)As_Object(target))->NavCom;\n\t\t\tif (Target_Legal(alttarg)) {\n\t\t\t\taltcoord = As_Coord(alttarg);\n\t\t\t}\n\t\t}\n\n\t\tfor (int r = range-0x0100; r > 0x0100; r -= 0x0100) {\n\t\t\tfor (int face = 0; face < 255; face += 16) {\n\t\t\t\tCOORDINATE newcoord = Coord_Move(tcoord, (DirType)face, r);\n\t\t\t\tCELL newcell = Coord_Cell(newcoord);\n\n\t\t\t\tif (Map.In_Radar(newcell) && (Session.Type != GAME_NORMAL || Map[newcell].IsVisible) && Cell_Seems_Ok(newcell, true)) {\n\t\t\t\t\tint dist;\n\t\t\t\t\tif (altcoord != 0) {\n\t\t\t\t\t\tdist = ::Distance(newcoord, altcoord);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdist = Distance(newcoord);\n\t\t\t\t\t}\n\t\t\t\t\tif (bestval == -1 || dist < bestval) {\n\t\t\t\t\t\tbest2val = bestval;\n\t\t\t\t\t\tbest2cell = bestcell;\n\t\t\t\t\t\tbestval = dist;\n\t\t\t\t\t\tbestcell = newcell;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (bestval != -1) break;\n\t\t}\n\n\t\tif (best2val == -1) {\n\t\t\tbest2cell = bestcell;\n\t\t}\n\n\t\t/*\n\t\t**\tIf it found a good firing location, then return this location as\n\t\t**\ta target value.\n\t\t*/\n\t\tif (bestval != -1) {\n\t\t\tif (Percent_Chance(50)) {\n\t\t\t\treturn(::As_Target(bestcell));\n\t\t\t} else {\n\t\t\t\treturn(::As_Target(best2cell));\n\t\t\t}\n\t\t}\n\t}\n\treturn(TARGET_NONE);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Cell_Seems_Ok -- Checks to see if a cell is good to enter.                   *\n *                                                                                             *\n *    This routine examines the navigation computers of other aircraft in order to see if the  *\n *    specified cell is safe to fly to. The intent of this routine is to avoid unnecessary     *\n *    mid-air collisions.                                                                      *\n *                                                                                             *\n * INPUT:   cell     -- The cell to examine for clear airspace.                                *\n *                                                                                             *\n *          strict   -- Should the scan consider the aircraft, that is making this check, a    *\n *                      blocking aircraft. Typically, the aircraft itself is not considered    *\n *                      a blockage -- an aircraft can always exist where it is currently       *\n *                      located. A strict check is useful for helicopters that need to move    *\n *                      around at the slightest provocation.                                   *\n *                                                                                             *\n * OUTPUT:  Is the specified cell free from airspace conflicts?                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AircraftClass::Cell_Seems_Ok(CELL cell, bool strict) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tMake sure that no other aircraft are heading to the selected location. If they\n\t**\tare, then don't consider the location as valid.\n\t*/\n\tTARGET astarget = ::As_Target(cell);\n\tfor (int index = 0; index < Aircraft.Count(); index++) {\n\t\tAircraftClass * air = Aircraft.Ptr(index);\n\t\tif (air && (strict || air != this) && !air->IsInLimbo) {\n\t\t\tif (Coord_Cell(air->Coord) == cell || air->NavCom == astarget) {\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t}\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Pip_Count -- Returns the number of \"objects\" in aircraft.                    *\n *                                                                                             *\n *    This routine is used by the render logic to draw the little container \"pips\". This       *\n *    corresponds to the number of passengers for a transport helicopter or the number of      *\n *    shots remaining for an attack helicopter.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of \"pips\" to render on the aircraft.                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/11/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftClass::Pip_Count(void) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tint retval = 0;\n\n\tif (Class->Max_Passengers() > 0) {\n\t\tretval = How_Many();\n\t} else {\n\t\tif (Ammo) {\n\t\t\tretval = Class->Max_Pips() * fixed(Ammo, Class->MaxAmmo);\n\t\t\tif (!retval) retval = 1;\n\t\t}\n\t}\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Mission_Enter -- Control aircraft to fly to the helipad or repair center.    *\n *                                                                                             *\n *    This routine is used when the aircraft needs to fly for either rearming or repairing.    *\n *    It tries to establish contact with the support building. Once contact is established     *\n *    the ground controller takes care of commanding the aircraft.                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before this routine should be called again.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/12/1995 JLB : Created.                                                                 *\n *   07/04/1995 JLB : Ground controller gives orders.                                          *\n *=============================================================================================*/\nint AircraftClass::Mission_Enter(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tenum {\n\t\tINITIAL,\n\t\tTAKEOFF,\n\t\tALTITUDE,\n\t\tSTACK,\n\t\tDOWNWIND,\n\t\tCROSSWIND,\n\t\tTRAVEL,\n\t\tLANDING\n\t};\n\n\t/*\n\t**\tVerify that it has a valid NavCom. If it doesn't then request one from the\n\t**\tbuilding this building is trying to land upon. If that fails, then enter\n\t**\tidle mode.\n\t*/\n\tif (!Target_Legal(NavCom) && In_Which_Layer() != LAYER_GROUND) {\n\t\tif (Transmit_Message(RADIO_DOCKING) != RADIO_ROGER) {\n\t\t\tEnter_Idle_Mode();\n\t\t\treturn(1);\n\t\t}\n\t}\n\n\tswitch (Status) {\n\t\tcase INITIAL:\n\t\t\tif (Height < FLIGHT_LEVEL || IsLanding) {\n\t\t\t\tStatus = TAKEOFF;\n\t\t\t} else {\n\t\t\t\tStatus = ALTITUDE;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase TAKEOFF:\n\t\t\tif (Process_Take_Off()) {\n\t\t\t\t/*\n\t\t\t\t**\tAfter takeoff is complete, break radio contact with any helipad that this\n\t\t\t\t**\thelicopter is taking off from.\n\t\t\t\t*/\n\t\t\t\tif (In_Radio_Contact() && Map[Coord].Cell_Building() == Contact_With_Whom()) {\n\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t}\n\t\t\t\tStatus = ALTITUDE;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ALTITUDE:\n\t\t\t/*\n\t\t\t**\tEstablish radio contact with the building this helicopter is trying\n\t\t\t**\tto land at.\n\t\t\t*/\n\t\t\tif (In_Radio_Contact()) {\n\t\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\t\tTransmit_Message(RADIO_DOCKING);\n\t\t\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tStatus = STACK;\n\t\t\t} else {\n\t\t\t\tTechnoClass * tech = As_Techno(NavCom);\n\t\t\t\tif (tech && Transmit_Message(RADIO_CAN_LOAD, tech) == RADIO_ROGER) {\n\t\t\t\t\tTransmit_Message(RADIO_HELLO, tech);\n\t\t\t\t\tTransmit_Message(RADIO_DOCKING);\n\t\t\t\t\tStatus = STACK;\n\t\t\t\t} else {\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\tif (tech->What_Am_I() != RTTI_VESSEL) {\n\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t}\n#else\n\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\tEnter_Idle_Mode();\n#endif\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase STACK:\n\t\t\tif (Class->IsFixedWing)  {\n\t\t\t\tint distance;\n\t\t\t\tTARGET togo;\n\n\t\t\t\tBuildingClass const * building = As_Building(NavCom);\n\t\t\t\tif (building)  {\n\t\t\t\t\ttogo = ::As_Target(building->Check_Point(CHECK_STACK));\n\t\t\t\t} else {\n\t\t\t\t\ttogo = NavCom;\n\t\t\t\t}\n\n\t\t\t\tdistance = Process_Fly_To(true, togo);\n\t\t\t\tif (distance < 0x0080)  {\n\t\t\t\t\tStatus = DOWNWIND;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tStatus = DOWNWIND;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase DOWNWIND:\n\t\t\tif (Class->IsFixedWing)  {\n\t\t\t\tint distance;\n\t\t\t\tTARGET togo;\n\n\t\t\t\tSet_Speed(200);\n\t\t\t\tBuildingClass const * building = As_Building(NavCom);\n\t\t\t\tif (building)  {\n\t\t\t\t\ttogo = ::As_Target(building->Check_Point(CHECK_DOWNWIND));\n\t\t\t\t} else {\n\t\t\t\t\ttogo = NavCom;\n\t\t\t\t}\n\n\t\t\t\tdistance = Process_Fly_To(true, togo);\n\t\t\t\tif (distance < 0x0080)  {\n\t\t\t\t\tStatus = CROSSWIND;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tStatus = CROSSWIND;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase CROSSWIND:\n\t\t\tif (Class->IsFixedWing)  {\n\t\t\t\tint distance;\n\t\t\t\tTARGET togo;\n\n\t\t\t\tSet_Speed(140);\n\t\t\t\tBuildingClass const * building = As_Building(NavCom);\n\t\t\t\tif (building)  {\n\t\t\t\t\ttogo = ::As_Target(building->Check_Point(CHECK_CROSSWIND));\n\t\t\t\t} else {\n\t\t\t\t\ttogo = NavCom;\n\t\t\t\t}\n\n\t\t\t\tdistance = Process_Fly_To(true, togo);\n\t\t\t\tif (distance < 0x0080)  {\n\t\t\t\t\tStatus = TRAVEL;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tStatus = TRAVEL;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase TRAVEL:\n\t\t\tTransmit_Message(RADIO_DOCKING);\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\t\tif (!In_Radio_Contact() && !Is_Target_Vessel(NavCom)) {\n#else\n\t\t\tif (!In_Radio_Contact()) {\n#endif\n\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\tEnter_Idle_Mode();\n\t\t\t} else {\n\t\t\t\tint distance = Process_Fly_To(true, NavCom);\n\n\t\t\t\tif (Class->IsFixedWing)  {\n\n\t\t\t\t\tif (distance < 0x0400)  {\n\t\t\t\t\t\tStatus = LANDING;\n\t\t\t\t\t}\n\t\t\t\t\treturn(1);\n\n\t\t\t\t} else {\n\t\t\t\t\tif (distance < 0x0080) {\n\t\t\t\t\t\tif (Target_Legal(TarCom)) {\n\t\t\t\t\t\t\tSecondaryFacing.Set_Desired(Direction(TarCom));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSecondaryFacing.Set_Desired(Pose_Dir());\n\t\t\t\t\t\t}\n\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n if (Is_Target_Vessel(NavCom) && !In_Radio_Contact()) {\n \tEnter_Idle_Mode();\n \tbreak;\n }\n#endif\n\t\t\t\t\t\tif (distance < 0x0010) {\n\t\t\t\t\t\t\tStatus = LANDING;\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tif(Is_Target_Vessel(NavCom) && As_Vessel(NavCom)->NavCom) {\n\t\tStatus = TRAVEL;\n\t}\n#endif\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSecondaryFacing.Set_Desired(Direction(NavCom));\n//\t\t\t\t\t\tSecondaryFacing.Set_Desired(::Direction(Fire_Coord(0), As_Coord(NavCom)));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(3);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase LANDING:\n\t\t\tif (IsTakingOff && !Class->IsFixedWing) {\n\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\tEnter_Idle_Mode();\n\t\t\t}\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n// If we were trying to land on a carrier and it moved, take off again\n\tif ( As_Vessel(NavCom) && !In_Radio_Contact()) {\n\t\tStatus = INITIAL;\n\t\tbreak;\n\t}\n#endif\n\t\t\tif (Process_Landing()) {\n\t\t\t\tswitch (Transmit_Message(RADIO_IM_IN)) {\n\t\t\t\t\tcase RADIO_ROGER:\n\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase RADIO_ATTACH:\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\tif(Contact_With_Whom()->What_Am_I() != RTTI_VESSEL) Limbo();\n#else\n\t\t\t\t\t\tLimbo();\n#endif\n\t\t\t\t\t\tContact_With_Whom()->Attach(this);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Good_LZ -- Locates a good spot to land.                                      *\n *                                                                                             *\n *    This routine is used when helicopters need a place to land, but there are no obvious     *\n *    spots (i.e., helipad) available. It will try to land near a friendly helipad or friendly *\n *    building if there are no helipads anywhere. In the event that there are no friendly      *\n *    buildings anywhere on the map, then just land right where it is flying.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the target location where this aircraft should land. This value may   *\n *          not be a clear cell, but the normal landing logic will resolve that problem.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/12/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTARGET AircraftClass::Good_LZ(void) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tScan through all of the buildings and try to land near\n\t**\tthe helipad (if there is one) or the nearest friendly building.\n\t*/\n\tCELL bestcell = 0;\n\tint bestdist = -1;\n\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\tBuildingClass * building = Buildings.Ptr(index);\n\n\t\tif (building && !building->IsInLimbo && building->House == House) {\n\t\t\tint dist = Distance(building);\n\t\t\tif (*building == Class->Building) {\n\t\t\t\tdist /= 4;\n\t\t\t}\n\t\t\tif (bestdist == -1 || dist < bestdist) {\n\t\t\t\tbestdist = dist;\n\t\t\t\tbestcell = Coord_Cell(building->Center_Coord());\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tReturn with the suitable location if one was found.\n\t*/\n\tif (bestdist != -1) {\n\t\treturn(::As_Target(bestcell));\n\t}\n\n\t/*\n\t**\tNo good location was found. Just try to land here.\n\t*/\n\treturn(::As_Target(Coord_Cell(Coord)));\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Set_Speed -- Sets the speed for the aircraft.                                *\n *                                                                                             *\n *    This routine will set the speed for the aircraft. The speed is specified as a fraction   *\n *    of full speed.                                                                           *\n *                                                                                             *\n * INPUT:   speed -- The fixed point fractional speed setting. 0x00 is stopped, 0xFF is full   *\n *                   speed.                                                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Set_Speed(int speed)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tFootClass::Set_Speed(speed);\n\n\tMPHType sp = MPHType(min(Class->MaxSpeed * SpeedBias * House->AirspeedBias, MPH_LIGHT_SPEED));\n\tFly_Speed(speed, sp);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Fire_Direction -- Determines the direction of fire.                          *\n *                                                                                             *\n *    This routine will determine what direction a projectile would take if it were fired      *\n *    from the aircraft. This is the direction that the aircraft's body is facing.             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the direction of projectile fire.                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nDirType AircraftClass::Fire_Direction(void) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(SecondaryFacing.Current());\n}\n\n\n/***********************************************************************************************\n * AircraftClass::~AircraftClass -- Destructor for aircraft object.                            *\n *                                                                                             *\n *    This is the destructor for aircraft. It will limbo the aircraft if it isn't already      *\n *    and also removes the aircraft from any team it may be attached to.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nAircraftClass::~AircraftClass(void)\n{\n\tif (GameActive && Class) {\n\n\t\t/*\n\t\t**\tRemove this member from any team it may be associated with. This must occur at the\n\t\t**\ttop most level of the inheritance hierarchy because it may call virtual functions.\n\t\t*/\n\t\tif (Team) {\n\t\t\tTeam->Remove(this);\n\t\t\tTeam = NULL;\n\t\t}\n\n\t\tHouse->Tracking_Remove(this);\n\n\t\t/*\n\t\t**\tIf there are any cargo members, delete them.\n\t\t*/\n\t\twhile (Is_Something_Attached()) {\n\t\t\tdelete Detach_Object();\n\t\t}\n\n\t\tAircraftClass::Limbo();\n\t\tClass = 0;\n\t}\n\tID = -1;\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Scatter -- Causes the aircraft to move away a bit.                           *\n *                                                                                             *\n *    This routine will cause the aircraft to move away from its current location and then     *\n *    enter some idle mode. Typically this is called when the aircraft is attacked while on    *\n *    the ground.                                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Scatter(COORDINATE , bool, bool )\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tCertain missions prevent scattering regardless of whether it would be\n\t**\ta good idea or not.\n\t*/\n\tif (!MissionControl[Mission].IsScatter) return;\n\n\t/*\n\t**\tFixed wing aircraft never scatter.\n\t*/\n\tif (Class->IsFixedWing) return;\n\n\tif (IsLanding || Height == 0) {\n\t\tIsLanding = false;\n\t\tIsTakingOff = true;\n\t}\n\tEnter_Idle_Mode();\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Mission_Guard -- Handles aircraft in guard mode.                             *\n *                                                                                             *\n *    Aircraft don't like to be in guard mode if in flight. If this situation is detected,     *\n *    then figure out what the aircraft should be doing and go do it.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine again. *\n *                                                                                             *\n * WARNINGS:   This routine typically calls the normal guard logic for ground units.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1995 JLB : Created.                                                                 *\n *   10/10/1995 JLB : Hunts for harvesters that are unescorted.                                *\n *=============================================================================================*/\nint AircraftClass::Mission_Guard(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Height == FLIGHT_LEVEL) {\n\n\t\t/*\n\t\t**\tIf part of a team, then do nothing, since the team\n\t\t**\thandler will take care of giving this aircraft a\n\t\t**\tmission.\n\t\t*/\n\t\tif (Team) {\n\t\t\tif (Target_Legal(NavCom)) {\n\t\t\t\tAssign_Mission(MISSION_MOVE);\n\t\t\t}\n\t\t\treturn(MissionControl[Mission].Normal_Delay());\n\t\t}\n\n\t\tif (Class->PrimaryWeapon == NULL) {\n\t\t\tAssign_Destination(::As_Target(Coord_Cell(Coord)));\n\t\t\tAssign_Mission(MISSION_MOVE);\n\t\t} else {\n\t\t\tif (!Team.Is_Valid()) Enter_Idle_Mode();\n\t\t}\n\t\treturn(1);\n\t}\n\tif (House->IsHuman) return(MissionControl[Mission].Normal_Delay());\n\n\t/*\n\t**\tIf the aircraft is very badly damaged, then it will search for a\n\t**\trepair bay first.\n\t*/\n\tif (House->Available_Money() >= 100 && Health_Ratio() <= Rule.ConditionYellow) {\n\t\tif (!In_Radio_Contact() ||\n\t\t\t(Height == 0 &&\n\t\t\t\t(Contact_With_Whom()->What_Am_I() != RTTI_BUILDING || *((BuildingClass *)Contact_With_Whom()) != STRUCT_REPAIR))) {\n\n\n\t\t\tBuildingClass * building = Find_Docking_Bay(STRUCT_REPAIR, true);\n\t\t\tif (building != NULL) {\n\t\t\t\tAssign_Destination(building->As_Target());\n\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\tAssign_Mission(MISSION_ENTER);\n\t\t\t\treturn(1);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the aircraft cannot attack anything because of lack of ammo,\n\t**\tabort any normal guard logic in order to look for a helipad\n\t**\tto rearm.\n\t*/\n\tif (Ammo == 0 && Is_Weapon_Equipped()) {\n\t\tif (!In_Radio_Contact()) {\n\t\t\tBuildingClass * building = Find_Docking_Bay(STRUCT_HELIPAD, false);\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tif (!Class->IsFixedWing) {\n\t\tint dist = 0x7FFFFFFF;\n\t\tif (building) dist=Distance(building);\n\t\tfor (int index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass *ship = Vessels.Ptr(index);\n\t\t\tif (ship != NULL && *ship == VESSEL_CARRIER && !ship->IsInLimbo && ship->IsActive && ship->House == House && ship->How_Many() < ship->Class->Max_Passengers()) {\n\t\t\t\tif (Distance(ship) < dist || !building) {\n\t\t\t\t\tbuilding = (BuildingClass *)ship;\n\t\t\t\t\tdist = Distance(ship);\n\t\t\t\t}\n//\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n#endif\n\t\t\tif (building != NULL) {\n\t\t\t\tAssign_Destination(building->As_Target());\n\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\tAssign_Mission(MISSION_ENTER);\n\t\t\t\treturn(1);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the aircraft already has a target, then attack it if possible.\n\t*/\n\tif (Target_Legal(TarCom)) {\n\t\tAssign_Mission(MISSION_ATTACK);\n\t\treturn(1);\n\t}\n\n\t/*\n\t**\tTransport helicopters don't really do anything but just sit there.\n\t*/\n\tif (!Is_Weapon_Equipped()) {\n\t\treturn(TICKS_PER_SECOND*3);\n\t}\n\n\t/*\n\t**\tComputer controlled helicopters will defend themselves by bouncing around\n\t**\tand looking for a free helipad.\n\t*/\n\tif (Height == 0 && !In_Radio_Contact()) {\n\t\tScatter(0, true);\n\t\treturn(TICKS_PER_SECOND*3);\n\t}\n\n\t/*\n\t**\tPerform a special check to hunt for harvesters that are outside of the protective\n\t**\tshield of their base.\n\t*/\n\tif (House->State != STATE_ATTACKED) {\n\t\tTARGET target = House->Find_Juicy_Target(Coord);\n\n\t\tif (Target_Legal(target)) {\n\t\t\tAssign_Target(target);\n\t\t\tAssign_Mission(MISSION_ATTACK);\n\t\t}\n\t}\n\n\treturn(FootClass::Mission_Guard());\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Mission_Guard_Area -- Handles the aircraft guard area logic.                 *\n *                                                                                             *\n *    This routine handles area guard logic for aircraft. Aircraft require special handling    *\n *    for this mode since they are to guard area only if they are in a position to do so.      *\n *    Otherwise they just defend themselves.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine        *\n *          again.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftClass::Mission_Guard_Area(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Height == FLIGHT_LEVEL) {\n\t\tif (!Team.Is_Valid()) Enter_Idle_Mode();\n\t\treturn(1);\n\t}\n\tif (House->IsHuman) return(TICKS_PER_SECOND);\n\n\tif (Height == 0 && !In_Radio_Contact()) {\n\t\tScatter(0, true);\n\t\treturn(TICKS_PER_SECOND*3);\n\t}\n\n\tif (Target_Legal(TarCom)) {\n\t\tAssign_Mission(MISSION_ATTACK);\n\t\treturn(1);\n\t}\n\treturn(FootClass::Mission_Guard_Area());\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Response_Attack -- Gives audio response to attack order.                     *\n *                                                                                             *\n *    This routine is used to give an audio response to an attack order.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Response_Attack(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tstatic VocType _response[] = {\n\t\tVOC_AFFIRM,\n\t\tVOC_ACKNOWL\n\t};\n\tVocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];\n\tif (AllowVoice) {\n\t\tSound_Effect(response, fixed(1), -(ID+1));\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Response_Move -- Gives audio response to move request.                       *\n *                                                                                             *\n *    This routine is used to give an audio response to movement orders.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Response_Move(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tstatic VocType _response[] = {\n\t\tVOC_ACKNOWL,\n\t\tVOC_AFFIRM\n\t};\n\tVocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];\n\tif (AllowVoice) {\n\t\tSound_Effect(response, fixed(1), -(ID+1));\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Response_Select -- Gives audio response when selected.                       *\n *                                                                                             *\n *    This routine is called when an audio response for selection is desired.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Response_Select(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tstatic VocType _response[] = {\n\t\tVOC_VEHIC,\n\t\tVOC_REPORT,\n\t\tVOC_YESSIR,\n\t\tVOC_YESSIR,\n\t\tVOC_YESSIR,\n\t\tVOC_AWAIT\n\t};\n\tVocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];\n\tif (AllowVoice) {\n\t\tSound_Effect(response, fixed(1), -(ID+1));\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Can_Fire -- Checks to see if the aircraft can fire.                          *\n *                                                                                             *\n *    This routine is used to determine if the aircraft can fire its weapon at the target      *\n *    specified. If it cannot, then the reason why is returned.                                *\n *                                                                                             *\n * INPUT:   target   -- The target that the aircraft might fire upon.                          *\n *                                                                                             *\n *          which    -- The weapon that will be used to fire.                                  *\n *                                                                                             *\n * OUTPUT:  Returns with the reason why it can't fire or with FIRE_OK.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/05/1996 JLB : Created.                                                                 *\n *   07/11/1996 JLB : Fixed for camera carrying aircraft.                                      *\n *=============================================================================================*/\nFireErrorType AircraftClass::Can_Fire(TARGET target, int which) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Passenger && !Is_Something_Attached()) {\n\t\treturn(FIRE_AMMO);\n\t}\n\n\tbool camera = (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->IsCamera);\n\tbool fudge = (Passenger || (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->Bullet != NULL && Class->PrimaryWeapon->Bullet->IsParachuted));\n\n\tif (fudge && !camera && !Ammo && !Passenger) {\n\t\treturn(FIRE_AMMO);\n\t}\n\n\t/*\n\t**\tPassenger aircraft that wish to 'fire' actually are requesting to\n\t**\tparadrop or 'throw out' the cargo. This is always allowed if the terrain under the\n\t**\taircraft is generally clear.\n\t*/\n\tif (camera || (fudge && Passenger && Is_Something_Attached()))  {\n\t\tif (Arm != 0) return(FIRE_REARM);\n\n\t\tif (Distance(target) < (camera ? 0x0380 : 0x0200) && Map.In_Radar(Coord_Cell(Center_Coord()))) {\n//\t\tif (Distance(target) < (camera ? 0x0380 : 0x0280) && Map.In_Radar(Coord_Cell(Center_Coord()))) {\n\t\t\treturn(FIRE_OK);\n\t\t}\n\t\treturn(FIRE_RANGE);\n\t}\n\n\tFireErrorType canfire = FootClass::Can_Fire(target, which);\n\n\tif (canfire == FIRE_OK) {\n\n\t\t/*\n\t\t**\tDouble check to make sure that the facing is roughly toward\n\t\t**\tthe target. If the difference is too great, then firing is\n\t\t**\ttemporarily postponed.\n\t\t*/\n\t\tif (Class->IsFixedWing) {\n\n\t\t\tint diff = PrimaryFacing.Difference(Direction(TarCom));\n\t\t\tif (ABS(diff) > (fudge ? 16 : 8)) {\n\t\t\t\treturn(FIRE_FACING);\n\t\t\t}\n\t\t}\n\t}\n\treturn(canfire);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Landing_Takeoff_AI -- Handle aircraft take off and landing processing.       *\n *                                                                                             *\n *    This routine handles the tricky maneuver of taking off and landing. The process of       *\n *    landing is not entirely safe and thus the aircraft may be destroyed as a consequence.    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the aircraft destroyed by this process?                                  *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per aircraft per game logic loop. Be sure to        *\n *             examine the return value and if true, abort all further processing of this      *\n *             aircraft since it is now dead.                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AircraftClass::Landing_Takeoff_AI(void)\n{\n\t/*\n\t**\tHandle landing and taking off logic. Helicopters are prime users of this technique. The\n\t**\taircraft will either gain or lose altitude as appropriate. As the aircraft transitions\n\t**\tbetween flying level and ground level, it will be moved into the appropriate render\n\t**\tlayer.\n\t*/\n\tif (Is_Door_Closed() && (IsLanding || IsTakingOff)) {\n\t\tLayerType layer = In_Which_Layer();\n\n\t\tif (IsLanding) {\n\t\t\tMark(MARK_UP);\n\t\t\tif (Height) Height -= Pixel_To_Lepton(1);\n\t\t\tif (Height <= 0) {\n\t\t\t\tHeight = 0;\n\t\t\t\tIsLanding = false;\n\t\t\t\tSet_Speed(0);\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the NavCom now equals the destination, then clear out the NavCom.\n\t\t\t\t*/\n\t\t\t\tif (Coord_Cell(Center_Coord()) == As_Cell(NavCom)) {\n\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** If a fixed-wing aircraft just landed on the ground, blow him up\n\t\t\t\t*/\n\t\t\t\tif (Class->IsFixedWing && Mission != MISSION_ENTER) {\n\t\t\t\t\tStrength = 1;\n\n\t\t\t\t\tint damage = Strength;\n\t\t\t\t\tMap.Remove(this, layer);\n\t\t\t\t\tTake_Damage(damage, 0, WARHEAD_AP, 0, true);\n\t\t\t\t\treturn(true);\n\t\t\t\t}\n\n\t\t\t\tif (Target_Legal(NavCom) && As_Techno(NavCom) == Contact_With_Whom()) {\n\t\t\t\t\tif (In_Radio_Contact() && Transmit_Message(RADIO_IM_IN) != RADIO_ROGER) {\n\t\t\t\t\t\tScatter(0, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tMark(MARK_DOWN);\n\t\t}\n\t\tif (IsTakingOff) {\n\t\t\tMark(MARK_UP);\n//\t\t\tMap.Remove(this, layer);\n\t\t\tHeight += Pixel_To_Lepton(1);\n\t\t\tif (Height >= FLIGHT_LEVEL) {\n\t\t\t\tHeight = FLIGHT_LEVEL;\n\t\t\t\tIsTakingOff = false;\n\t\t\t}\n//\t\t\tMap.Submit(this, In_Which_Layer());\n\t\t\tMark(MARK_DOWN);\n\t\t}\n\n\t\t/*\n\t\t**\tMake adjustments for altitude by moving from one layer to another as\n\t\t**\tnecessary.\n\t\t*/\n\t\tif (layer != In_Which_Layer()) {\n\n\t\t\t/*\n\t\t\t**\tWhen the aircraft is about to enter the ground layer, perform on last\n\t\t\t**\tcheck to see if it is legal to enter that location. If not, then\n\t\t\t**\tstart the take off process. Let the normal logic handle this\n\t\t\t**\tchange of plans.\n\t\t\t*/\n\t\t\tbool ok = true;\n\t\t\tif (In_Which_Layer() == LAYER_GROUND && !IsTakingOff && !Class->IsFixedWing) {\n\t\t\t\tif (!Is_LZ_Clear(::As_Target(Coord_Cell(Coord)))) {\n\t\t\t\t\tIsTakingOff = true;\n\t\t\t\t\tMark(MARK_UP);\n\t\t\t\t\tHeight += Pixel_To_Lepton(1);\n\t\t\t\t\tMark(MARK_DOWN);\n\t\t\t\t\tok = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (ok) {\n\n\t\t\t\tMap.Remove(this, layer);\n\t\t\t\tMap.Submit(this, In_Which_Layer());\n\n\t\t\t\t/*\n\t\t\t\t**\tWhen the aircraft is close to the ground, it should exist as a ground object.\n\t\t\t\t**\tThis aspect is controlled by the Place_Down and Pick_Up functions.\n\t\t\t\t*/\n\t\t\t\tif (In_Which_Layer() == LAYER_GROUND) {\n\t\t\t\t\tAssign_Destination(TARGET_NONE);\t\t// Clear the navcom.\n\t\t\t\t\tTransmit_Message(RADIO_TETHER);\n\t\t\t\t\tLook();\n//\t\t\t\t\tMap.Sight_From(Coord_Cell(Coord), 1, House, false);\n\t\t\t\t} else  {\n\t\t\t\t\tTransmit_Message(RADIO_UNTETHER);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the navigation computer is not attached to the object this\n\t\t\t\t\t**\taircraft is in radio contact with, then assume that radio\n\t\t\t\t\t**\tcontact is now superfluous. Break radio contact.\n\t\t\t\t\t*/\n\t\t\t\t\tif (In_Radio_Contact() && Target_Legal(NavCom) && NavCom != Contact_With_Whom()->As_Target()) {\n\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Edge_Of_World_AI -- Detect if aircraft has exited the map.                   *\n *                                                                                             *\n *    Certain aircraft will be eliminated when they leave the edge of the world presumably     *\n *    after completing their mission. An exception is for aircraft that have been newly        *\n *    created as reinforcements and have not yet completed their mission.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the aircraft deleted by this routine?                                    *\n *                                                                                             *\n * WARNINGS:   Be sure to call this routine only once per aircraft per game logic loop. If     *\n *             the return value is true, then abort any further processing of this aircraft    *\n *             since it has been eliminated.                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AircraftClass::Edge_Of_World_AI(void)\n{\n\tif (!Map.In_Radar(Coord_Cell(Coord))) {\n\t\tif (Mission == MISSION_RETREAT /*|| (*this == AIRCRAFT_CARGO && !Is_Something_Attached())*/) {\n\n\t\t\t/*\n\t\t\t**\tCheck to see if there are any civilians aboard. If so, then flag the house\n\t\t\t**\tthat the civilian evacuation trigger event has been fulfilled.\n\t\t\t*/\n\t\t\twhile (Is_Something_Attached()) {\n\t\t\t\tFootClass * obj = Detach_Object();\n\n\t\t\t\t/*\n\t\t\t\t**\tFlag the owning house that civ evacuation has occurred.\n\t\t\t\t*/\n\t\t\t\tif (_Counts_As_Civ_Evac(obj)) {\n\t\t\t\t\tobj->House->IsCivEvacuated = true;\n\t\t\t\t}\n\n\t\t\t\tif (obj->Team.Is_Valid()) obj->Team->IsLeaveMap = true;\n\n#ifdef OLD\n\t\t\t\t/*\n\t\t\t\t**\tTransport planes that leave can only be because they carry purchased\n\t\t\t\t**\tequipment and must be have their cost refunded.\n\t\t\t\t*/\n\t\t\t\tif (*this == AIRCRAFT_CARGO) {\n\t\t\t\t\tHouse->Refund_Money(obj->Class_Of().Cost_Of());\n\t\t\t\t}\n#endif\n\t\t\t\tdelete obj;\n\t\t\t}\n\t\t\tif (Team.Is_Valid()) {\n\t\t\t\tTeam->IsLeaveMap = true;\n\t\t\t}\n\t\t\tStun();\n\t\t\tdelete this;\n\t\t\treturn(true);\n\t\t}\n\t} else {\n\t\tIsLocked = true;\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Movement_AI -- Handles aircraft physical movement logic.                     *\n *                                                                                             *\n *    This routine manages the aircraft movement across the map. If any movement occurred, the *\n *    aircraft will be flagged to be redrawn.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per aircraft per game logic loop.                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Movement_AI(void)\n{\n\t/*\n\t**\tIf for some strange reason, there is a valid NavCom, but this aircraft is not\n\t**\tin a movement order, then give it a movement order.\n\t*/\n\tif (Target_Legal(NavCom) && Mission == MISSION_GUARD && MissionQueue == MISSION_NONE) {\n\t\tAssign_Mission(MISSION_MOVE);\n\t}\n\n\tif (Speed != 0) {\n\t\tif (In_Which_Layer() == LAYER_GROUND)  {\n\t\t\tMark(MARK_UP);\n\t\t\tPhysics(Coord, PrimaryFacing);\n\t\t\tMark(MARK_DOWN);\n\t\t} else {\n\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\tif (Physics(Coord, PrimaryFacing) != RESULT_NONE) {\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Rotation_AI -- Handle aircraft body and flight rotation.                     *\n *                                                                                             *\n *    This will process the aircraft visible body and flight model rotation operations. If     *\n *    any rotation occurred, the aircraft will be flagged to be redrawn.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per aircraft per game logic loop.                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Rotation_AI(void)\n{\n\tif (PrimaryFacing.Is_Rotating()) {\n\t\tMark(MARK_CHANGE_REDRAW);\n\t\tif (PrimaryFacing.Rotation_Adjust(Class->ROT)) {\n\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t}\n\t}\n\tif (Class->IsFixedWing) {\n\t\tSecondaryFacing = PrimaryFacing;\n\t}\n\tif (SecondaryFacing.Is_Rotating()) {\n\t\tMark(MARK_CHANGE_REDRAW);\n\t\tif (SecondaryFacing.Rotation_Adjust(Class->ROT)) {\n\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Per_Cell_Process -- Handle the aircraft per cell process.                    *\n *                                                                                             *\n *    This is a seldom used function since its only purpose is to be called when an aircraft   *\n *    lands on the ground.                                                                     *\n *                                                                                             *\n * INPUT:   why   -- Why was this per cell process function called.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/15/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Per_Cell_Process(PCPType why)\n{\n\tBStart(BENCH_PCP);\n\tFootClass::Per_Cell_Process(why);\n\tBEnd(BENCH_PCP);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Assign_Destination -- Assigns movement destination to the object.            *\n *                                                                                             *\n *    This routine is called when the object needs to have a new movement destination          *\n *    assigned.  Aircraft have their own version of this routine because a fixed-wing plane\t  *\n *    trying to land will behave poorly if given a new destinatio while it's landing.\t\t\t  *                                                                                         *\n *                                                                                             *\n * INPUT:   destination -- The destination to assign to this object.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Assign_Destination(TARGET dest)\n{\n\tassert(IsActive);\n\tif (dest == NavCom) return;\n\n\tif (Target_Legal(dest) && Class->IsFixedWing && (IsLanding || (Target_Legal(NavCom) && dest != NavCom))) {\n//\tif (Target_Legal(dest) /*&& Class->IsFixedWing*/ && (IsLanding || (Target_Legal(NavCom) && dest != NavCom))) {\n\n//\t\tif (Class->IsFixedWing || As_Cell(dest) != Coord_Cell(Center_Coord())) {\n\t\t\tProcess_Take_Off();\n\t\t\tStatus = 0;\n//\t\t}\n\t}\n\tFootClass::Assign_Destination(dest);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::In_Which_Layer -- Calculates the display layer of the aircraft.              *\n *                                                                                             *\n *    This examines the aircraft to determine what display layer it should be located          *\n *    in. Fixed wing aircraft must always be in the top layer if they are flying even though   *\n *    they may be low to the ground.                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the layer that this aircraft resides in.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLayerType AircraftClass::In_Which_Layer(void) const\n{\n\tif (Class->IsFixedWing && Height > 0) {\n\t\treturn(LAYER_TOP);\n\t}\n\treturn(FootClass::In_Which_Layer());\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Look -- Aircraft will look if they are on the ground always.                 *\n *                                                                                             *\n *    Aircraft perform a look operation according to their sight range. If the aircraft is     *\n *    on the ground, then it will look a distance of one cell regardless of what its           *\n *    specified sight range is.                                                                *\n *                                                                                             *\n * INPUT:   incremental -- Is this an incremental look?                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Look(bool incremental)\n{\n\tassert(IsActive);\n\tassert(!IsInLimbo);\n\n\tint sight_range = Techno_Type_Class()->SightRange;\n\tif (Height == 0) {\n\t\tsight_range = 1;\n\t}\n\n\tif (sight_range) {\n\t\tMap.Sight_From(Coord_Cell(Coord), sight_range, House, incremental);\n\t}\n}\n"
  },
  {
    "path": "CODE/AIRCRAFT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/AIRCRAFT.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : AIRCRAFT.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 22, 1994                                                *\n *                                                                                             *\n *                  Last Update : November 28, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef AIRCRAFT_H\n#define AIRCRAFT_H\n\n#include\t\"radio.h\"\n#include\t\"fly.h\"\n#include\t\"target.h\"\n\n\n/*\n**\tThis aircraft class is used for all flying sentient objects. This includes fixed wing\n**\taircraft as well as helicopters. It excludes bullets even though some bullets might\n**\tbe considered to be \"flying\" in a loose interpretatin of the word.\n*/\nclass AircraftClass : public FootClass, public FlyClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis is a pointer to the class control structure for the aircraft.\n\t\t*/\n\t\tCCPtr<AircraftTypeClass> Class;\n\n\t\t//-----------------------------------------------------------------------------\n\t\tstatic void * operator new(size_t);\n\t\tstatic void * operator new(size_t, void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *);\n\t\toperator AircraftType(void) const {return Class->Type;};\n\t\tAircraftClass(AircraftType classid, HousesType house);\n\t\tAircraftClass(NoInitClass const & x) : FootClass(x), FlyClass(x), Class(x), SecondaryFacing(x), SightTimer(x) {};\n\t\tvirtual ~AircraftClass(void);\n\n\t\tstatic void Init(void);\n\n\t\tvirtual int Mission_Attack(void);\n\t\tvirtual int Mission_Unload(void);\n\t\tvirtual int Mission_Hunt(void);\n\t\tvirtual int Mission_Retreat(void);\n\t\tvirtual int Mission_Move(void);\n\t\tvirtual int Mission_Enter(void);\n\t\tvirtual int Mission_Guard(void);\n\t\tvirtual int Mission_Guard_Area(void);\n\n\t\tvirtual void Assign_Destination(TARGET target);\n\t\t/*\n\t\t**\tState machine support routines.\n\t\t*/\n\t\tbool Process_Take_Off(void);\n\t\tbool Process_Landing(void);\n\t\tint Process_Fly_To(bool slowdown, TARGET dest);\n\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tvirtual LayerType In_Which_Layer(void) const;\n\t\tvirtual DirType Turret_Facing(void) const {return(SecondaryFacing.Current());}\n\t\tint Shape_Number(void) const;\n\t\tvirtual MoveType Can_Enter_Cell(CELL cell, FacingType facing=FACING_NONE) const;\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const {return *Class;};\n\t\tvirtual ActionType What_Action(ObjectClass const * target) const;\n\t\tvirtual ActionType What_Action(CELL cell) const;\n\t\tvirtual DirType Desired_Load_Dir(ObjectClass * passenger, CELL & moveto) const;\n\t\tvirtual int Pip_Count(void) const;\n\t\tTARGET Good_Fire_Location(TARGET target) const;\n\t\tbool Cell_Seems_Ok(CELL cell, bool landing=false) const;\n\t\tDirType Pose_Dir(void) const;\n\t\tTARGET Good_LZ(void) const;\n\t\tvirtual DirType Fire_Direction(void) const;\n\t\tvirtual FireErrorType Can_Fire(TARGET target, int which) const;\n\n\t\t/*\n\t\t**\tLanding zone support functionality.\n\t\t*/\n\t\tvirtual void Per_Cell_Process(PCPType why);\n\t\tbool Is_LZ_Clear(TARGET target) const;\n\t\tTARGET New_LZ(TARGET oldlz) const;\n\n\t\t/*\n\t\t**\tCoordinate inquiry functions. These are used for both display and\n\t\t**\tcombat purposes.\n\t\t*/\n\t\tvirtual COORDINATE Sort_Y(void) const;\n\n\t\t/*\n\t\t**\tObject entry and exit from the game system.\n\t\t*/\n\t\tvirtual bool Unlimbo(COORDINATE , DirType facing = DIR_N);\n\n\t\t/*\n\t\t**\tDisplay and rendering support functionality. Supports imagery and how\n\t\t**\tobject interacts with the map and thus indirectly controls rendering.\n\t\t*/\n\t\tvirtual void Look(bool incremental=false);\n\t\tvoid Draw_Rotors(int x, int y, WindowNumberType window) const;\n\t\tvirtual int Exit_Object(TechnoClass *);\n\t\tvirtual short const * Overlap_List(bool redraw=false) const;\n\t\tvirtual void Draw_It(int x, int y, WindowNumberType window) const;\n\t\tvirtual void Set_Speed(int speed);\n\n\t\t/*\n\t\t**\tUser I/O.\n\t\t*/\n\t\tvirtual void Active_Click_With(ActionType action, ObjectClass * object);\n\t\tvirtual void Active_Click_With(ActionType action, CELL cell);\n\t\tvirtual void Player_Assign_Mission(MissionType mission, TARGET target=TARGET_NONE, TARGET destination=TARGET_NONE);\n\t\tvirtual void Response_Select(void);\n\t\tvirtual void Response_Move(void);\n\t\tvirtual void Response_Attack(void);\n\n\t\t/*\n\t\t**\tCombat related.\n\t\t*/\n\t\tvirtual ResultType Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, bool forced=false);\n\t\tvirtual BulletClass * Fire_At(TARGET target, int which);\n\n\t\t/*\n\t\t**\tAI.\n\t\t*/\n\t\tbool Landing_Takeoff_AI(void);\n\t\tbool Edge_Of_World_AI(void);\n\t\tvoid Movement_AI(void);\n\t\tvoid Rotation_AI(void);\n\t\tint Paradrop_Cargo(void);\n\t\tvirtual void AI(void);\n\t\tvirtual void Enter_Idle_Mode(bool initial = false);\n\t\tvirtual RadioMessageType Receive_Message(RadioClass * from, RadioMessageType message, long & param);\n\t\tvirtual void Scatter(COORDINATE threat, bool forced=false, bool nokidding=false);\n\n\t\t/*\n\t\t**\tScenario and debug support.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tstatic void Read_INI(CCINIClass & ini);\n\t\tstatic char * INI_Name(void) {return \"AIRCRAFT\";};\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\n\tpublic:\n\n\t\t/*\n\t\t**\tThis is the facing used for the body of the aircraft. Typically, this is the same\n\t\t**\tas the PrimaryFacing, but in the case of helicopters, it can be different.\n\t\t*/\n\t\tFacingClass SecondaryFacing;\n\n\t\t/*\n\t\t**\tIf this is a passenger carrying aircraft then this flag will be set. This is\n\t\t**\tnecessary because once the passengers are unloaded, the fact that it was a\n\t\t**\tpassenger carrier must still be known.\n\t\t*/\n\t\tbool Passenger;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tAircraft can be in either state of landing, taking off, or in steady altitude.\n\t\t**\tThese flags are used to control transition between flying and landing. It is\n\t\t**\tnecessary to handle the transition in this manner so that it occurs smoothly\n\t\t**\tduring the graphic processing section.\n\t\t*/\n\t\tunsigned IsLanding:1;\n\t\tunsigned IsTakingOff:1;\n\n\t\t/*\n\t\t**\tIt is very common for aircraft to be homing in on a target. When this flag is\n\t\t**\ttrue, the aircraft will constantly adjust its facing toward the TarCom. When the\n\t\t**\ttarget is very close (one cell away or less), then this flag is automatically cleared.\n\t\t**\tThis is because the homing algorithm is designed to get the aircraft to the destination\n\t\t**\tbut no more. Checking when this flag is cleared is a way of flagging transition into\n\t\t**\ta new mode. Example: Transport helicopters go into a hovering into correct position\n\t\t**\tmode when the target is reached.\n\t\t*/\n\t\tunsigned IsHoming:1;\n\n\t\t/*\n\t\t**\tHelicopters that are about to land must hover into a position exactly above the landing\n\t\t**\tzone. When this flag is true, the aircraft will be adjusted so that it is exactly over\n\t\t**\tthe TarCom. The facing of the aircraft is not altered by this movement. The affect\n\t\t**\tlike the helicopter is hovering and shifting sideways to position over the landing\n\t\t**\tzone. When the position is over the landing zone, then this flag is set to false.\n\t\t*/\n\t\tunsigned IsHovering:1;\n\n\t\t/*\n\t\t**\tThis is the jitter tracker to be used when the aircraft is a helicopter and\n\t\t**\tis flying. It is most noticeable when the helicopter is hovering.\n\t\t*/\n\t\tunsigned char Jitter;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis timer controls when the aircraft will reveal the terrain around itself.\n\t\t**\tWhen this timer expires and this aircraft has a sight range, then the\n\t\t**\tlook around process will occur.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> SightTimer;\n\n\t\t/*\n\t\t**\tMost attack aircraft can make several attack runs. This value contains the\n\t\t**\tnumber of attack runs the aircraft has left. When this value reaches\n\t\t**\tzero then the aircraft is technically out of ammo.\n\t\t*/\n\t\tchar AttacksRemaining;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/ALLOC.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : ALLOC.CPP                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : February 1, 1992                         *\n *                                                                         *\n *                  Last Update : March 9, 1995 [JLB]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Alloc -- Allocates system RAM.                                        *\n *   Ram_Free -- Determines the largest free chunk of RAM.                 *\n *   Free -- Free an Alloc'ed block of RAM.                                *\n *   Resize_Alloc -- Change the size of an allocated block.                *\n *   Heap_Size -- Size of the heap we have.                                *\n *   Total_Ram_Free -- Total amount of free RAM.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <malloc.h>\n#include <string.h>\n#include <stdlib.h>\n#include <dos.h>\n#include <bios.h>\n#include <stdio.h>\n\n\n#ifndef WWMEM_H\n#include \"wwmem.h\"\n#endif\n\n\nextern \"C\" unsigned long Largest_Mem_Block ( void ) ;\n\n//\n// use double-word alignment for allocs\n//\n#define LONG_ALIGNMENT\t\t\t1\n\n/*\n** Define the equates necessary to call a DPMI interrupt.\n*/\n#define\tDPMI_INT\t\t\t\t\t\t\t\t\t0x0031\n#define\tDPMI_LOCK_MEM\t\t\t\t\t\t\t0x0600\n#define\tDPMI_UNLOCK_MEM\t\t\t\t\t\t0x0601\n#define  LOGGING\t\t\t\t\t\t\t\t\tFALSE\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\nunsigned long MinRam=0L;\t\t// Record of least memory at worst case.\nunsigned long MaxRam=0L;\t\t// Record of total allocated at worst case.\nstatic unsigned long TotalRam = 0L;\nstatic unsigned long Memory_Calls = 0L;\nstatic unsigned long RequestedSystemRam = 8*1024*1024;\nstatic unsigned long LargestRamBlock = 0L;\n\nvoid (*Memory_Error)(void) = NULL;\nvoid (*Memory_Error_Exit)(char *string) = NULL;\n\n/***************************************************************************\n * DPMI_LOCK -- handles locking a block of DPMI memory                     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n#include\"mono.h\"\nvoid DPMI_Lock(VOID const *ptr, long const size)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\n\t/*\n\t** Lock memory\n\t** AX = 0x600\n\t** BX:CX = starting linear address of memory to lock\n\t** SI:DI = size of region to lock (in bytes)\n\t** - If Failure, carry flag is set.\n\t*/\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_LOCK_MEM;\n\tregs.x.ebx = ((long)ptr & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000ffff);\n\tregs.x.esi = ((long)size & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n//\tif (regs.x.cflag) {\n//\t}\n#if(0)\n\tchar *temp = (char *)ptr;\n\tchar hold;\n\tfor (int lp = 0; lp < size; lp += 2048) {\n\t\thold = *temp;\n\t\ttemp += 2048;\n\t}\n#endif\n\n}\n\n/***************************************************************************\n * DPMI_UNLOCK -- Handles unlocking a locked block of DPMI                 *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid DPMI_Unlock(void const *ptr, long const size)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\n\t/*\n\t** Unlock the memory\n\t*/\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_UNLOCK_MEM;\t\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = ((long)ptr & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000ffff);\n\tregs.x.esi = ((long)size & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n//\tif (regs.x.cflag) {\n//\t}\n\n}\n\n/***************************************************************************\n * Alloc -- Allocates system RAM.                                          *\n *                                                                         *\n *    This is the basic RAM allocation function.  It is used for all       *\n *    memory allocations needed by the system or the main program.         *\n *                                                                         *\n * INPUT:   bytes_to_alloc -- LONG value of the number of bytes to alloc.  *\n *                                                                         *\n *          flags          -- Memory allocation control flags.             *\n *             MEM_NORMAL: No special flags.                               *\n *             MEM_CLEAR:  Zero out memory block.                        \t*\n *             MEM_NEW:\t\tCalled by a new.                                *\n *                                                                         *\n * OUTPUT:  Returns with pointer to allocated block.  If NULL was returned *\n *          it indicates a failure to allocate.  Note: NULL will never be  *\n *          returned if the standard library allocation error routine is   *\n *          used.                                                          *\n *                                                                         *\n * WARNINGS:   If you replace the standard memory allocation error routine *\n *             and make it so that Alloc CAN return with a NULL, be sure   *\n *             and check for this in your code.                            *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Documented.                                          *\n *   08/09/1993 JLB : Updated with EMS memory support.                     *\n *   04/28/1994 JAW : Updated to 32bit Protected mode.                     *\n *   03/09/1995 JLB : Fixed                                                *\n *=========================================================================*/\nvoid *Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags)\n{\n\tunion REGS\t\tregs ;\n\tstruct SREGS \tsregs ;\n\tunsigned char *retval=NULL;\t// Pointer to allocated block.\n\tunsigned long\toriginal_size;\t// Original allocation size.\n\tunsigned long\tbytesfree;\t\t// Number of free bytes.\n\tlong \t\t\t\t*longptr=NULL;\t// Pointer used to store selector\n\tstatic unsigned char _allocinit=0;\n\n\n\t//\n\t// Init memory system by finding largest block to alloc\n\t// then allocate it to get one large heap and free it.\n\t// There may be more memory available from DPMI but we only are\n\t// for now allocating and freeing the first largest block.\n\t//\n\tif ( !_allocinit ) {\n\t\tunsigned long largestblock = Largest_Mem_Block();\n\t\tlargestblock -= 1024;\t\t\t\t// subtract for heap header and misc\n\t\tlargestblock &= 0xffff0000;\t\t// forcing to 64K boundary\n\n\t\tif ( largestblock ) {\n\t\t\tLargestRamBlock = MIN( largestblock, RequestedSystemRam );\n\t\t\tunsigned char *lptr = (unsigned char *)malloc( LargestRamBlock );\n\t\t\tif ( lptr ) {\n\t\t\t\tfree( (void *)lptr );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tInitialize the total ram available value.\n\t\t*/\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\n\t\t_allocinit = 1;\n\t}\n\n\t/*\n\t** Save the original allocated space size so that we can clear the\n\t** exact amount of RAM if they specified MEM_CLEAR.\n\t*/\n\toriginal_size = bytes_to_alloc;\n\n\t/*\n\t** Reserve one byte for the header of the memory we allocated.\n\t** We will store the flags variable there for later use.\n\t*/\n#if (LONG_ALIGNMENT)\n\tbytes_to_alloc += (flags & MEM_LOCK) ? 8 : 4;\n#else\n\tbytes_to_alloc += (flags & MEM_LOCK) ? 5 : 1;\n#endif\n\n\n\t// Try to allocate the memory out of the protected mode memory\n\t// chain if we did not require a real mode allocation.  If this\n\t// fails we will have to try to allocate it out of real mode memory.\n\t// Real mode memory is a last resort because some types of applications\n\t// require real mode memory.\n\tif (!(flags & MEM_REAL)) {\n\t\tretval = (unsigned char*)malloc(bytes_to_alloc);\n\t}\n\n\t// Try to allocate the memory out of the real mode memory using DPMI\n\t// service 0x100.  Note that retval will be null if we are requesting\n\t// real mode memory so that we do not have to explicitly check for the\n\t// real mode flag.  Remember we need to reserve room for the dos\n\t// selector value at the beginning of our allocated block so rather than\n\t// adding fifteen and rounding, we need to add 19 and round.\n\tif (!retval) {\n\t\tflags = (MemoryFlagType)(flags | MEM_REAL);\n\t\tregs.x.eax = 0x100;\n\t\tregs.x.ebx = (bytes_to_alloc + 19) >> 4;\n\t\tif (regs.x.ebx & 0xFFFF0000) {\n\t\t\tretval = NULL;\n\t\t} else {\n\t\t\tsegread ( & sregs ) ;\n\t\t\tint386x ( 0x31 , & regs, & regs , & sregs\t) ;\n\t\t\tif (regs.x.cflag)\n\t\t\t\tretval = NULL;\n\t\t\telse {\n#if (LONG_ALIGNMENT)\n\t\t\t\tlongptr\t\t= (long *)(((regs.x.eax & 0xFFFF) << 4)+ 4);\n#else\n\t\t\t\tlongptr\t\t= (long *)(((regs.x.eax & 0xFFFF) << 4)+ 1);\n#endif\n\t\t\t\t*longptr++\t= regs.x.edx & 0xFFFF;\n\t\t\t\tretval\t\t= (unsigned char *)longptr;\n\t\t\t}\n\t\t}\n\t}\n\n\t// If the alloc failed then we need to signify a memory error.\n\tif (retval == NULL) {\n\t\tif (Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\n\t}\n\n\t// If the memory needs to be DPMI locked then we should store the\n\t// original size in the header before we store the flags.\n\tif (flags & MEM_LOCK) {\n\t\tlongptr\t\t= (long *)retval;\n\t\t*longptr++\t= original_size;\n\t\tretval\t\t= (unsigned char *)longptr;\n\t}\n\n\n\t// Now that we know the alloc was sucessful (and for an extra byte\n\t// more than the user wanted) we need to stick in the memory flags.\n#if (LONG_ALIGNMENT)\n\tif ( !(flags & (MEM_LOCK|MEM_REAL)) ) {\n\t\t//\n\t\t// WARNING!!!!!!!!!!\n\t\t// USE this only with the WATCOM malloc ALLOCATION!!!!!!!!!\n\t\t// it reads the actual block size before the ptr returned.\n\t\t// then eors and uses the upper word for a validation later on free.\n\t\t//\n\t\tlongptr = (long *)retval;\n\t\t*longptr = ((*(longptr - 1)) ^ 0xffffffff) & 0xffff0000;\n\t\t*retval++ \t\t= flags;\n\t\t*retval++ \t\t= (unsigned char)(flags ^ 0xff);\n\t\tretval += 2;\n\t}\n\telse {\n\t\t*retval++ \t\t= flags;\n\t\t*retval++ \t\t= (unsigned char)(flags ^ 0xff);\n\t\t*retval++ \t\t= 0;\n\t\t*retval++ \t\t= 0;\n\t}\n#else\n\t*retval++ \t\t= (unsigned char)(flags | (((flags ^ 0x07) & 0x07) << 5));\n#endif\n\n\t// If the memory needed to be DPMI locked then set it up so it\n\t// is locked.\n\tif (flags & MEM_LOCK) {\n\t\tDPMI_Lock(retval, original_size);\n\t}\n\n\t/* Clear the space if they wanted it clear */\n\n\tif (flags & MEM_CLEAR) {\n\t\tunsigned char\t*ptr;\t\t// Working memory block pointer.\n\n\t\tptr = retval;\n\t\tmemset(ptr, '\\0', original_size);\n\t}\n\n\tbytesfree = Total_Ram_Free(MEM_NORMAL);\n\tif (bytesfree < MinRam) {\n\t\tMinRam = bytesfree;\n\t}\n\tif (TotalRam-bytesfree > MaxRam) {\n\t\tMaxRam = TotalRam-bytesfree;\n\t}\n\n\tMemory_Calls++;\n\n#if(LOGGING)\n\tint val = _heapchk();\n\n\tFILE *file = fopen(\"mem.txt\",\"at\");\n\tfprintf(file, \"%P Alloc size = %d, Actual Size = %d, flags = %d, heap = %d\\n\",\n\t\t\t\t\t\tretval,\n\t\t\t\t\t\toriginal_size,\n\t\t\t\t\t\tbytes_to_alloc,\n\t\t\t\t\t\tflags,\n\t\t\t\t\t\tval);\n\tfclose(file);\n#endif\n\n\treturn(retval);\n}\n\n\n/***************************************************************************\n * Free -- Free an Alloc'ed block of RAM.                                  *\n *                                                                         *\n * FUNCTION:                                                               *\n *                                                                         *\n * INPUT:       A pointer to a block of RAM from Alloc.                    *\n *                                                                         *\n * OUTPUT:      None.                                                      *\n *                                                                         *\n * WARNINGS:    Don't use this for an Alloc_Block'ed RAM block.            *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/25/1990     : Created.                                             *\n ***************************************************************************/\nvoid Free(void const *pointer)\n{\n\tunion REGS\t\tregs ;\n\tstruct SREGS \tsregs ;\n\n//\tvoid const *original = pointer;\n\tchar string[80];\n\n\tif (pointer) {\n\t\t/*\n\t\t** Get a pointer to the flags that we stored off.\n\t\t*/\n#if (LONG_ALIGNMENT)\n\t\tunsigned char *byteptr\t= ((unsigned char *)pointer) - 4;\n\n\t\t//\n\t\t// validate the flags with and eor of the flags\n\t\t//\n\t\tif ( *byteptr != ((*(byteptr + 1)) ^ 0xff) ) {\n\t\t\tif (Memory_Error_Exit != NULL) {\n\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n\t\t\t\tMemory_Error_Exit( string );\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif ( !(*byteptr & (MEM_LOCK|MEM_REAL)) ) {\n\t\t\t\tunsigned short *wordptr = (unsigned short *)(byteptr - 2);\n\n\t\t\t\t//\n\t\t\t\t// WARNING!!!!!!!!!!\n\t\t\t\t// USE this only with the WATCOM malloc ALLOCATION!!!!!!!!!\n\t\t\t\t// it reads the actual block size before the ptr to be freed.\n\t\t\t\t// then compares with the EOR to the value stored during allocation.\n\t\t\t\t//\n\t\t\t\tif ( *wordptr != ((*(wordptr + 2)) ^ 0xffff) ) {\n\t\t\t\t\tif (Memory_Error_Exit != NULL) {\n\t\t\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n\t\t\t\t\t\tMemory_Error_Exit( string );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( *(byteptr + 2) || *(byteptr + 3) ) {\n\t\t\t\tif (Memory_Error_Exit != NULL) {\n\t\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n\t\t\t\t\tMemory_Error_Exit( string );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n//\t\tif ( *byteptr != (*(byteptr + 1) ^ 0xff) ||\n//\t\t\t*(byteptr + 2) || *(byteptr + 3) ) {\n//\t\t\tif (Memory_Error_Exit != NULL) {\n//\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n//\t\t\t\tMemory_Error_Exit( string );\n//\t\t\t}\n//\t\t}\n#else\n\t\tunsigned char *byteptr\t= ((unsigned char *)pointer) - 1;\n\n\t\tif ( (*byteptr & 0xe0) != (((*byteptr ^ 0x07) & 0x07) << 5) ) {\n\t\t\tif (Memory_Error_Exit != NULL) {\n\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n\t\t\t\tMemory_Error_Exit( string );\n\t\t\t}\n\t\t}\n#endif\n\n\t\t/*\n\t\t** Check to see if this was locked me and if it was unlock it.\n\t\t*/\n\t\tif (*byteptr & MEM_LOCK) {\n\t\t\tlong *longptr = ((long *)byteptr) - 1;\n\t\t\tDPMI_Unlock(pointer, *longptr);\n\t\t\tpointer = (void *)longptr;\n\t\t} else\n\t\t\tpointer = (void *)byteptr;\n\n#if(LOGGING)\n\t\tint val = _heapchk();\n\t\tFILE *file = fopen(\"mem.txt\",\"at\");\n\t\tfprintf(file, \"%P Free flags = %d, Heap = %d\\n\",\n\t\t\t\t\t\t\toriginal,\n\t\t\t\t\t\t\t*byteptr,\n\t\t\t\t\t\t\tval);\n\t\tfclose(file);\n#endif\n\n\t\t// If the pointer is a real mode pointer than it will point to the\n\t\t// first megabyte of system memory.  If it does than we need to\n\t\t// use DPMI to free it.\n\t\tif (*byteptr & MEM_REAL) {\n\t\t\tregs.x.eax\t= 0x101;\n\t\t\tregs.x.edx\t= *(((long *)pointer) - 1);\n\t\t\tsegread ( & sregs ) ;\n\t\t\tint386x(0x31, &regs, &regs, &sregs);\n\t\t} else {\n\t\t\tfree((void *)pointer);\n\t\t}\n\t\tMemory_Calls--;\n\t}\n}\n\n\n/***************************************************************************\n * Resize_Alloc -- Change the size of an allocated block.                  *\n *                                                                         *\n *    This routine will take a previously allocated block and change its   *\n *    size without unnecessarily altering its contents.                    *\n *                                                                         *\n * INPUT:   pointer  -- Pointer to the original memory allocation.         *\n *                                                                         *\n *          new_size -- Size in bytes that it will be converted to.        *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the new allocation.                  *\n *                                                                         *\n * WARNINGS:   ???                                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/01/1992 JLB : Commented.                                           *\n *=========================================================================*/\nvoid *Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes)\n{\n\n\tunsigned long *temp;\n//\tunsigned long diff, flags;\n\n\ttemp = (unsigned long*)original_ptr;\n\n\t/* ReAlloc the space */\n\ttemp = (unsigned long *)realloc(temp, new_size_in_bytes);\n\tif (temp == NULL) {\n\t\tif (Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\n\t}\n\n\treturn(temp);\n}\n\n\n/***************************************************************************\n * Ram_Free -- Determines the largest free chunk of RAM.                   *\n *                                                                         *\n *    Use this routine to determine the largest free chunk of available    *\n *    RAM for allocation.  It also performs a check of the memory chain.   *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  Returns with the size of the largest free chunk of RAM.        *\n *                                                                         *\n * WARNINGS:   This does not return the TOTAL memory free, only the        *\n *             largest free chunk.                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Commented.                                           *\n *=========================================================================*/\nlong Ram_Free(MemoryFlagType)\n{\n\treturn(_memmax());\n//\treturn Largest_Mem_Block();\n}\n\n\n/***************************************************************************\n * Heap_Size -- Size of the heap we have.                                  *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Heap_Size(MemoryFlagType )\n{\n\tif (!TotalRam) {\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\t}\n\treturn(TotalRam);\n}\n\n\n/***************************************************************************\n * Total_Ram_Free -- Total amount of free RAM.                             *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *   03/09/1995 JLB : Uses prerecorded heap size maximum.                  *\n *=========================================================================*/\nlong Total_Ram_Free(MemoryFlagType )\n{\n\treturn(_memavl());\n//\treturn Largest_Mem_Block () ;\n}\n\n"
  },
  {
    "path": "CODE/ANIM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/ANIM.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Dune                                                         *\n *                                                                                             *\n *                    File Name : ANIM.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 3, 1991                                                 *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   AnimClass::AI -- This is the low level anim processor.                                    *\n *   AnimClass::AnimClass -- The constructor for animation objects.                            *\n *   AnimClass::Attach_To -- Attaches animation to object specified.                           *\n *   AnimClass::Center_Coord -- Determine center of animation.                                 *\n *   AnimClass::Detach -- Remove animation if attached to target.                              *\n *   AnimClass::Do_Atom_Damage -- Do atom bomb damage centered around the cell specified.      *\n *   AnimClass::Draw_It -- Draws the animation at the location specified.                      *\n *   AnimClass::In_Which_Layer -- Determines what render layer the anim should be in.          *\n *   AnimClass::Init -- Performs pre-scenario initialization.                                  *\n *   AnimClass::Mark -- Signals to map that redrawing is necessary.                            *\n *   AnimClass::Middle -- Processes any middle events.                                         *\n *   AnimClass::Occupy_List -- Determines the occupy list for the animation.                   *\n *   AnimClass::Overlap_List -- Determines the overlap list for the animation.                 *\n *   AnimClass::Render -- Draws an animation object.                                           *\n *   AnimClass::Sort_Y -- Returns with the sorting coordinate for the animation.               *\n *   AnimClass::Start -- Processes initial animation side effects.                             *\n *   AnimClass::delete -- Returns an anim object back to the free pool.                        *\n *   AnimClass::new -- Allocates an anim object from the pool.                                 *\n *   AnimClass::~AnimClass -- Destructor for anim objects.                                     *\n *   Anim_From_Name -- Given a name, this finds the corresponding anim type.                   *\n *   Shorten_Attached_Anims -- Reduces attached animation durations.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#define   VIC   1\n\n/***********************************************************************************************\n * Anim_From_Name -- Given a name, this finds the corresponding anim type.                     *\n *                                                                                             *\n *    This routine will convert the supplied ASCII name into the animation type that it        *\n *    represents.                                                                              *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the ASCII name to convert.                                     *\n *                                                                                             *\n * OUTPUT:  Returns with the animation type that matches the name specified. If no match could *\n *          be found, then ANIM_NONE is returned.                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nAnimType Anim_From_Name(char const * name)\n{\n  #ifdef VIC\n\tif (name == NULL) return(ANIM_NONE);\n\n\tfor (AnimType anim = ANIM_FIRST; anim < ANIM_COUNT; anim++) {\n\t\tif (stricmp(AnimTypeClass::As_Reference(anim).IniName, name) == 0) {\n\t\t\treturn(anim);\n\t\t}\n\t}\n#endif\n\treturn(ANIM_NONE);\n}\n\n\n/***********************************************************************************************\n * Shorten_Attached_Anims -- Reduces attached animation durations.                             *\n *                                                                                             *\n *    This routine is used to reduce the amount of time any attached animations will process.  *\n *    Typical use of this is when an object is on fire and the object should now be destroyed  *\n *    but the attached animations are to run until completion before destruction can follow.   *\n *    This routine will make the animation appear to run its course, but in as short of time   *\n *    as possible. The shortening effect is achieved by reducing the number of times the       *\n *    animation will loop.                                                                     *\n *                                                                                             *\n * INPUT:   obj   -- Pointer to the object that all attached animations will be processed.     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/11/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Shorten_Attached_Anims(ObjectClass * obj)\n{\n\tif (obj != NULL) {\n\t\tfor (int index = 0; index < Anims.Count(); index++) {\n\t\t\tAnimClass & anim = * Anims.Ptr(index);\n\n\t\t\tif (As_Object(anim.xObject) == obj) {\n\t\t\t\tanim.Loops = 0;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * AnimClass::Sort_Y -- Returns with the sorting coordinate for the animation.                 *\n *                                                                                             *\n *    This routine is used by the sorting system. Animations that are located in the ground    *\n *    layer will be sorted by this the value returned from this function.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the sort coordinate to use for this animation.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *   12/15/1994 JLB : Handles flat anims (infantry decay anims).                               *\n *=============================================================================================*/\nCOORDINATE AnimClass::Sort_Y(void) const\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (xObject != TARGET_NONE) {\n\t\treturn(Coord_Add(As_Object(xObject)->Sort_Y(), 0x00010000L));\n\t}\n\tif (*this == ANIM_MOVE_FLASH) {\n\t\treturn(Coord_Add(Center_Coord(), XYP_COORD(0, -24)));\n\t}\n\tif (Class->IsGroundLayer || *this == ANIM_LZ_SMOKE) {\n\t\treturn(Coord_Add(Center_Coord(), XYP_COORD(0, 14)));\n\t}\n#endif\n\treturn(Coord);\n}\n\n\n/***********************************************************************************************\n * AnimClass::Center_Coord -- Determine center of animation.                                   *\n *                                                                                             *\n *    This support function will return the \"center\" of the animation. The actual coordinate   *\n *    of the animation may be dependant on if the the animation is attached to an object.      *\n *    In such a case, it must factor in the object's location.                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the coordinate of the center of the animation. The coordinate is in real   *\n *          game coordinates -- taking into consideration if the animation is attached.        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *   02/02/1996 JLB : Coordinate based on visual center of object.                             *\n *=============================================================================================*/\nCOORDINATE AnimClass::Center_Coord(void) const\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (xObject != TARGET_NONE) {\n\t\treturn(Coord_Add(Coord, As_Object(xObject)->Target_Coord()));\n\t}\n#endif\n\treturn(Coord);\n}\n\n\n/***********************************************************************************************\n * AnimClass::Render -- Draws an animation object.                                             *\n *                                                                                             *\n *    This is the working routine that renders the animation shape. It gets called once        *\n *    per animation per frame. It needs to be fast.                                            *\n *                                                                                             *\n * INPUT:   bool; Should the animation be rendered in spite of render flag?                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the animation rendered?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AnimClass::Render(bool forced) const\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Delay) return(false);\n\tif (Map[Center_Coord()].IsVisible) {\n\t\tIsToDisplay = true;\n\t}\n#endif\n\treturn(ObjectClass::Render(forced));\n}\n\n\n/***********************************************************************************************\n * AnimClass::Draw_It -- Draws the animation at the location specified.                        *\n *                                                                                             *\n *    This routine is used to render the animation object at the location specified. This is   *\n *    how the map imagery gets updated.                                                        *\n *                                                                                             *\n * INPUT:   x,y      -- The pixel coordinates to draw the animation at.                        *\n *                                                                                             *\n *          window   -- The to base the draw coordinates upon.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *   05/19/1995 JLB : Added white translucent effect.                                          *\n *=============================================================================================*/\nvoid AnimClass::Draw_It(int x, int y, WindowNumberType window) const\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!IsInvisible) {\n\t\tBStart(BENCH_ANIMS);\n\n\t\tIsTheaterShape = Class->IsTheater;\n\n\t\tvoid const * shapefile = Get_Image_Data();\n\t\tif (shapefile != NULL) {\n\t\t\tvoid const * transtable = NULL;\n\t\t\tint shapenum = Class->Start + Fetch_Stage();\n\t\t\tvoid const * remap = NULL;\n\n\t\t\t/*\n\t\t\t**\tIf the translucent table hasn't been determined yet, then check to see if it\n\t\t\t**\tshould use the white or normal translucent tables.\n\t\t\t*/\n\t\t\tif (transtable == NULL && Class->IsWhiteTrans) transtable = DisplayClass::WhiteTranslucentTable;\n\t\t\tif (transtable == NULL && Class->IsTranslucent) transtable = DisplayClass::TranslucentTable;\n\t\t\tif (Class->Type == ANIM_ATOM_BLAST) transtable = Map.UnitShadow;\n\n\t\t\t/*\n\t\t\t**\tSet the shape flags to properly take into account any fading or ghosting\n\t\t\t**\ttable necessary.\n\t\t\t*/\n\t\t\tShapeFlags_Type flags = SHAPE_CENTER|SHAPE_WIN_REL;\n\t\t\tif (transtable != NULL) flags = flags | SHAPE_GHOST;\n\n\t\t\t/*\n\t\t\t**\tDraw the animation shape.\n\t\t\t*/\n\t\t\tCC_Draw_Shape(shapefile, shapenum, x, y, window, flags, remap, transtable);\n\t\t}\n\t\tIsTheaterShape = false;\n\t\tBEnd(BENCH_ANIMS);\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::Mark -- Signals to map that redrawing is necessary.                              *\n *                                                                                             *\n *    This routine is used by the animation logic system to inform the map that the cells      *\n *    under the animation must be rerendered.                                                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AnimClass::Mark(MarkType mark)\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (ObjectClass::Mark(mark)) {\n\t\tMap.Refresh_Cells(Coord_Cell(Center_Coord()), Overlap_List());\n//\t\tObjectClass::Mark(mark);\n\t\treturn(true);\n\t}\n#endif\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * AnimClass::Overlap_List -- Determines the overlap list for the animation.                   *\n *                                                                                             *\n *    Use this routine to fetch the overlap list for the animation. This overlap list is the   *\n *    cells that this animation spills over.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to the overlap list for this particular instance of the          *\n *          animation.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * AnimClass::Overlap_List(void) const\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\tstatic short const OverlapAtom[] = {\n\t\t(-MAP_CELL_W * 2) - 1, (-MAP_CELL_W * 2), (-MAP_CELL_W * 2) + 1,\n\t\t(-MAP_CELL_W * 1) - 1, (-MAP_CELL_W * 1), (-MAP_CELL_W * 1) + 1,\n\t\t(-MAP_CELL_W * 0) - 1, (-MAP_CELL_W * 0), (-MAP_CELL_W * 0) + 1,\n\t\t( MAP_CELL_W * 1) - 1, ( MAP_CELL_W * 1), ( MAP_CELL_W * 1) + 1,\n\t\t( MAP_CELL_W * 2) - 1, ( MAP_CELL_W * 2), ( MAP_CELL_W * 2) + 1,\n \t\tREFRESH_EOL\n\t};\n\n\tif (IsToDelete) {\n\t\tstatic short const _list[] = {REFRESH_EOL};\n\t\treturn(_list);\n\t}\n\n\tif (Class->Type == ANIM_ATOM_BLAST) {\n\t\treturn(OverlapAtom);\n\t}\n\n#ifdef PARTIAL\nIsTheaterShape = Class->IsTheater;\n\tif (Class->Get_Image_Data() != NULL) {\n\t\tint shapenum = Class->Start + Fetch_Stage();\n\t\tint count = Get_Build_Frame_Count(Class->Get_Image_Data());\n\t\tshapenum = min(shapenum, count-1);\n\n\t\tif (Class->DimensionData == NULL) {\n\t\t\tClass->DimensionData = new Rect [count];\n\t\t}\n\t\tif (Class->DimensionData != NULL && !Class->DimensionData[shapenum].Is_Valid()) {\n\t\t\tClass->DimensionData[shapenum] = Shape_Dimensions(Class->Get_Image_Data(), shapenum);\nIsTheaterShape = false;\n\t\t\treturn(Coord_Spillage_List(Center_Coord(), Class->DimensionData[shapenum]));\n\t\t}\n\t}\nIsTheaterShape = false;\n#endif\n#endif\n\treturn(Coord_Spillage_List(Center_Coord(), Class->Size));\n}\n\n\n/***********************************************************************************************\n * AnimClass::Occupy_List -- Determines the occupy list for the animation.                     *\n *                                                                                             *\n *    Animations always occupy only the cell that their center is located over. As such, this  *\n *    routine always returns a simple (center cell) occupation list.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the occupation list for the animation.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * AnimClass::Occupy_List(bool) const\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tstatic short _simple[] = {REFRESH_EOL};\n\n#endif\n\treturn(_simple);\n}\n\n\n/***********************************************************************************************\n * AnimClass::Init -- Performs pre-scenario initialization.                                    *\n *                                                                                             *\n *    This routine is used to initialize the animation system prior to a scenario being loaded *\n *    or reloaded. It effectively removes all animations from the system.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::Init(void)\n{\n\tAnims.Free_All();\n}\n\n\n/***********************************************************************************************\n * AnimClass::new -- Allocates an anim object from the pool.                                   *\n *                                                                                             *\n *    This routine is used to allocate a free anim class object from the preallocated pool     *\n *    in the near heap. If there are no free animation objects, then null is returned.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a free anim object.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * AnimClass::operator new(size_t)\n{\n\tvoid * ptr = Anims.Allocate();\n\tif (ptr != NULL) {\n\t\t((AnimClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * AnimClass::delete -- Returns an anim object back to the free pool.                          *\n *                                                                                             *\n *    This routine is used to return an anim object back to the pool of free anim objects.     *\n *    Anim objects so returned are available to be reallocated for the next animation.         *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the anim object to return to the pool.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::operator delete(void * ptr)\n{\n\tif (ptr != NULL) {\n\t\t((AnimClass *)ptr)->IsActive = false;\n\t}\n\tAnims.Free((AnimClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * AnimClass::AnimClass -- The constructor for animation objects.                              *\n *                                                                                             *\n *    This routine is used as the constructor of animation objects. It initializes and adds    *\n *    the animation object to the display and logic systems.                                   *\n *                                                                                             *\n * INPUT:   animnum  -- The animation number to start.                                         *\n *                                                                                             *\n *          coord    -- The location of the animation.                                         *\n *                                                                                             *\n *          timedelay-- The delay before the animation starts.                                 *\n *                                                                                             *\n *          loop     -- The number of times to loop this animation.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   08/03/1994 JLB : Added a delayed affect parameter.                                        *\n *=============================================================================================*/\nAnimClass::AnimClass(AnimType animnum, COORDINATE coord, unsigned char timedelay, unsigned char loop) :\n\tObjectClass(RTTI_ANIM, Anims.ID(this)),\n\tClass(AnimTypes.Ptr((int)animnum)),\n\txObject(TARGET_NONE),\n\tOwnerHouse(HOUSE_NONE),\n\tLoops(1),\n\tIsToDelete(false),\n\tIsBrandNew(true),\n\tIsInvisible(false),\n\tDelay(timedelay),\n\tAccum(0)\n{\n#ifdef VIC\n\tif (Class->Stages == -1) {\nIsTheaterShape = Class->IsTheater;\n\t\t((int&)Class->Stages) = Get_Build_Frame_Count(Class->Get_Image_Data());\nIsTheaterShape = false;\n\n\t}\n\tif (Class->LoopEnd == -1) {\n\t\t((int&)Class->LoopEnd) = Class->Stages;\n\t}\n\tif (Class->IsNormalized) {\n\t\tSet_Rate(Options.Normalize_Delay(Class->Delay));\n\t} else {\n\t\tSet_Rate(Class->Delay);\n\t}\n\tSet_Stage(0);\n\n\tif (Class->IsGroundLayer) {\n\t\tHeight = FLIGHT_LEVEL;\n\t}\n\n\tAnimClass::Unlimbo(coord);\n\n\t/*\n\t**\tDrop zone smoke always reveals the map around itself.\n\t*/\n\tif (*this == ANIM_LZ_SMOKE) {\n\t\tMap.Sight_From(Coord_Cell(coord), Rule.DropZoneRadius / CELL_LEPTON_W, PlayerPtr, false);\n\t}\n\n\tLoops = (unsigned char)(max(loop, 1) * Class->Loops);\n\tLoops = (unsigned char)max(Loops, 1);\n\n\t/*\n\t**\tIf the animation starts immediately, then play the associated sound effect now.\n\t*/\n\tif (!Delay) {\n\t\tStart();\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::~AnimClass -- Destructor for anim objects.                                       *\n *                                                                                             *\n *    This destructor handles removing the animation object from the system. It might require  *\n *    informing any object this animation is attached to that it is no longer attached.        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/29/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nAnimClass::~AnimClass(void)\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\tif (GameActive) {\n\n\t\t/*\n\t\t**\tIf this anim is attached to another object\n\t\t**\tthen check to see if this is the last anim attached to it. If this\n\t\t**\tis the case, then inform the object that it is no longer attached to\n\t\t**\tan animation.\n\t\t*/\n\t\tif (Target_Legal(xObject) && As_Object(xObject) != NULL) {\n\t\t\tObjectClass * to = As_Object(xObject);\n\n\t\t\t/*\n\t\t\t**\tRemove the object from the appropriate display list.\n\t\t\t*/\n\t\t\tMap.Remove(this, In_Which_Layer());\n\n\t\t\t/*\n\t\t\t**\tScan for any other animations that are attached to the object that\n\t\t\t**\tthis animation is attached to. If there are no others, then inform the\n\t\t\t**\tattached object of this fact.\n\t\t\t*/\n\t\t\tfor (int index = 0; index < Anims.Count(); index++) {\n\t\t\t\tif (Anims.Ptr(index) != this && Anims.Ptr(index)->xObject == xObject) break;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tTell the object that it is no longer being damaged.\n\t\t\t*/\n\t\t\tif (index == Anims.Count()) {\n\t\t\t\tto->Fire_Out();\n\t\t\t\tto->Mark(MARK_OVERLAP_UP);\n\t\t\t\tto->IsAnimAttached = false;\n\t\t\t\tto->Mark(MARK_OVERLAP_DOWN);\n\t\t\t}\n\t\t\tCoord = Coord_Add(to->Center_Coord(), Coord);\n\t\t\txObject = TARGET_NONE;\n\t\t}\n\n\t\tLimbo();\n\t}\n\n\txObject = TARGET_NONE;\n\tClass = 0;\n\tID = -1;\n\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::AI -- This is the low level anim processor.                                      *\n *                                                                                             *\n *    This routine is called once per frame per animation. It handles transition between       *\n *    animation frames and marks the map for redraw as necessary.                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Speed is of upmost importance.                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::AI(void)\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tFor ground level based animations (ones that can run slowly as well as\n\t**\toccur behind other ground objects) always cause the cell to be redrawn.\n\t*/\n#ifdef PARTIAL\n\tif (!Delay && Class->IsGroundLayer) {\n\t\tMap.Refresh_Cells(Coord_Cell(Center_Coord()), Overlap_List());\n\t}\n#else\n\tMap.Refresh_Cells(Coord_Cell(Center_Coord()), Overlap_List());\n#endif\n\n\t/*\n\t**\tSpecial case check to make sure that building on top of a smoke marker\n\t**\tcauses the smoke marker to vanish.\n\t*/\n\tif (Class->Type == ANIM_LZ_SMOKE && Map[Center_Coord()].Cell_Building()) {\n\t\tIsToDelete = true;\n\t}\n\n\t/*\n\t**\tDelete this animation and bail early if the animation is flagged to be deleted\n\t**\timmediately.\n\t*/\n\tif (IsToDelete) {\n\t\tdelete this;\n\t\treturn;\n\t}\n\n\t/*\n\t**\tIf this is a brand new animation, then don't process it the first logic pass\n\t**\tsince it might end up skipping the first animation frame before it has had a\n\t**\tchance to draw it.\n\t*/\n\tif (IsBrandNew) {\n\t\tIsBrandNew = false;\n\t\treturn;\n\t}\n\n#ifdef FIXIT_MULTI_SAVE\n\tif (Class->Stages == -1) {\n\t\tIsTheaterShape = Class->IsTheater;\n\t\t((int&)Class->Stages) = Get_Build_Frame_Count(Class->Get_Image_Data());\n\t\tIsTheaterShape = false;\n\t}\n\tif (Class->LoopEnd == -1) {\n\t\t((int&)Class->LoopEnd) = Class->Stages;\n\t}\n#endif\n\n\tif (Delay) {\n\t\tDelay--;\n\t\tif (!Delay) {\n\t\t\tStart();\n\t\t}\n\t} else {\n\n#ifdef FIXIT_MULTI_SAVE\n\t\tif (Class->Stages == -1) {\n\t\t\tIsTheaterShape = Class->IsTheater;\n\t\t\t((int&)Class->Stages) = Get_Build_Frame_Count(Class->Get_Image_Data());\n\t\t\tIsTheaterShape = false;\n\t\t}\n\t\tif (Class->LoopEnd == -1) {\n\t\t\t((int&)Class->LoopEnd) = Class->Stages;\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tThis is necessary because there is no recording of animations on the map\n\t\t**\tand thus the animation cannot be intelligently flagged for redraw. Most\n\t\t**\tanimations move fast enough that they would need to be redrawn every\n\t\t**\tgame frame anyway so this isn't TOO bad.\n\t\t*/\n\t\tMark(MARK_CHANGE);\n\n\t\tif (StageClass::Graphic_Logic()) {\n\t\t\tint stage = Fetch_Stage();\n\n\t\t\t/*\n\t\t\t**\tIf this animation is attached to another object and it is a\n\t\t\t**\tdamaging kind of animation, then do the damage to the other\n\t\t\t**\tobject.\n\t\t\t*/\n\t\t\tif (xObject != TARGET_NONE && Class->Damage > 0) {\n\t\t\t\tAccum += Class->Damage;\n\n\t\t\t\tif (Accum >= 1) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tAdminister the damage. If the object was destroyed by this anim,\n\t\t\t\t\t**\tthen the attached damaging anim is also destroyed.\n\t\t\t\t\t*/\n\t\t\t\t\tint damage = Accum;\n\t\t\t\t\tAccum -= damage;\n\t\t\t\t\tif (As_Object(xObject)->Take_Damage(damage, 0, WARHEAD_FIRE) == RESULT_DESTROYED) {\n\t\t\t\t\t\tdelete this;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDuring the biggest stage (covers the most ground), perform any ground altering\n\t\t\t**\taction required. This masks craters and scorch marks, so that they appear\n\t\t\t**\tnaturally rather than \"popping\" into existence while in plain sight.\n\t\t\t*/\n\t\t\tif (Class->Biggest && Class->Start+stage == Class->Biggest) {\n\t\t\t\tMiddle();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCheck to see if the last frame has been displayed. If so, then the\n\t\t\t**\tanimation either ends or loops.\n\t\t\t*/\n\t\t\tif ((Loops <= 1 && stage >= Class->Stages) || (Loops > 1 && stage >= Class->LoopEnd-Class->Start)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDetermine if this animation should loop another time. If so, then start the loop\n\t\t\t\t**\tbut if not, then proceed into the animation termination handler.\n\t\t\t\t*/\n\t\t\t\tif (Loops) Loops--;\n\t\t\t\tif (Loops) {\n\t\t\t\t\tSet_Stage(Class->LoopStart);\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThe animation should end now, but first check to see if\n\t\t\t\t\t**\tit needs to chain into another animation. If so, then the\n\t\t\t\t\t**\tanimation isn't technically over. It metamorphoses into the\n\t\t\t\t\t**\tnew form.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Class->ChainTo != ANIM_NONE) {\n\n\t\t\t\t\t\tClass = (AnimTypeClass *)&AnimTypeClass::As_Reference(Class->ChainTo);\n\n\t\t\t\t\t\tif (Class->Stages == -1) {\nIsTheaterShape = Class->IsTheater;\n\t\t\t\t\t\t\t((int&)Class->Stages) = Get_Build_Frame_Count(Class->Get_Image_Data());\nIsTheaterShape = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Class->LoopEnd == -1) {\n\t\t\t\t\t\t\t((int&)Class->LoopEnd) = Class->Stages;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tIsToDelete = false;\n\t\t\t\t\t\tLoops = Class->Loops;\n\t\t\t\t\t\tAccum = 0;\n\t\t\t\t\t\tif (Class->IsNormalized) {\n\t\t\t\t\t\t\tSet_Rate(Options.Normalize_Delay(Class->Delay));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSet_Rate(Class->Delay);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSet_Stage(Class->Start);\n\t\t\t\t\t\tStart();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdelete this;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::Attach_To -- Attaches animation to object specified.                             *\n *                                                                                             *\n *    An animation can be \"attached\" to an object. In such cases, the animation is rendered    *\n *    as an offset from the center of the object it is attached to. This allows affects such   *\n *    as fire or smoke to be consistently placed on the vehicle it is associated with.         *\n *                                                                                             *\n * INPUT:   obj   -- Pointer to the object to attach the animation to.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::Attach_To(ObjectClass * obj)\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (obj == NULL) return;\n\tassert(obj->IsActive);\n\n\tobj->Mark(MARK_OVERLAP_UP);\n\tobj->IsAnimAttached = true;\n\tobj->Mark(MARK_OVERLAP_DOWN);\n\tMap.Remove(this, In_Which_Layer());\n\txObject = obj->As_Target();\n\tMap.Submit(this, In_Which_Layer());\n\tCoord = Coord_Sub(Coord, obj->Target_Coord());\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::In_Which_Layer -- Determines what render layer the anim should be in.            *\n *                                                                                             *\n *    Use this routine to find out which display layer (ground or air) that the animation      *\n *    should be in. This information is used to place the animation into the correct display   *\n *    list.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the layer that the animation should exist in.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/25/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nLayerType AnimClass::In_Which_Layer(void) const\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->Type >= ANIM_CORPSE1 && Class->Type <= ANIM_CORPSE3) {\n\t\treturn(LAYER_SURFACE);\n\t}\n\n\tif (Target_Legal(xObject) || Class->IsGroundLayer) {\n\t\treturn(LAYER_GROUND);\n\t}\n#endif\n\treturn(LAYER_AIR);\n}\n\n\n/***********************************************************************************************\n * AnimClass::Start -- Processes initial animation side effects.                               *\n *                                                                                             *\n *    This routine is called when the animation first starts. Sometimes there are side effects *\n *    associated with this animation that must occur immediately. Typically, this is the       *\n *    sound effect assigned to this animation. If this animation is supposed to attach itself  *\n *    to any object at its location, then do so at this time as well.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/30/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::Start(void)\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tMark();\n\n\t/*\n\t**\tPlay the sound effect for this animation.\n\t*/\n\tSound_Effect(Class->Sound, Coord);\n\n\t/*\n\t**\tIf the stage where collateral effects occur is the first stage of the animation, then\n\t**\tperform this action now. Subsequent checks against this stage value starts with the\n\t**\tsecond frame of the animation.\n\t*/\n\tif (!Class->Biggest) {\n\t\tMiddle();\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::Middle -- Processes any middle events.                                           *\n *                                                                                             *\n *    This routine is called when the animation as reached its largest stage. Typically, this  *\n *    routine is used to cause scorches or craters to appear at a cosmetically pleasing        *\n *    moment.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/30/1995 JLB : Created.                                                                 *\n *   10/17/1995 JLB : Ion camera added.                                                        *\n *=============================================================================================*/\nvoid AnimClass::Middle(void)\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tCELL cell = Coord_Cell(Center_Coord());\n\tCellClass * cellptr = &Map[cell];\n\n\tif (Class->Type == ANIM_ATOM_BLAST) {\n\t\tDo_Atom_Damage(OwnerHouse, cell);\n\t}\n\n\t/*\n\t**\tIf this animation leaves scorch marks (e.g., napalm), then do so at this time.\n\t*/\n\tif (Class->IsScorcher) {\n\t\tnew SmudgeClass(Random_Pick(SMUDGE_SCORCH1, SMUDGE_SCORCH6), Center_Coord());\n\t}\n\n\t/*\n\t**\tSome animations leave a crater when they occur. Artillery is a good example.\n\t**\tCraters always remove the Tiberium where they occur.\n\t*/\n\tif (Class->IsCraterForming) {\n\n\t\t/*\n\t\t**\tCraters reduce the level of Tiberium in the cell.\n\t\t*/\n\t\tcellptr->Reduce_Tiberium(6);\n\n\t\t/*\n\t\t**\tIf there already is a crater in the cell, then just expand the\n\t\t**\tcrater.\n\t\t*/\n\t\tnew SmudgeClass(SMUDGE_CRATER1, Center_Coord());\n\t}\n\n\tAnimClass * newanim;\n\n\t/*\n\t**\tIf this animation spawns side effects during its lifetime, then\n\t**\tdo so now. Usually, these side effects are in the form of other\n\t**\tanimations.\n\t*/\n\tswitch (Class->Type) {\n\t\tcase ANIM_NAPALM1:\n\t\tcase ANIM_NAPALM2:\n\t\tcase ANIM_NAPALM3:\n\t\t\tnew AnimClass(ANIM_FIRE_SMALL, Map.Closest_Free_Spot(Coord_Scatter(Center_Coord(), 0x0040), true), 0, Random_Pick(1, 2));\n\t\t\tif (Percent_Chance(50)) {\n\t\t\t\tnew AnimClass(ANIM_FIRE_SMALL, Map.Closest_Free_Spot(Coord_Scatter(Center_Coord(), 0x00A0), true), 0, Random_Pick(1, 2));\n\t\t\t}\n\t\t\tif (Percent_Chance(50)) {\n\t\t\t\tnew AnimClass(ANIM_FIRE_MED, Map.Closest_Free_Spot(Coord_Scatter(Center_Coord(), 0x0070), true), 0, Random_Pick(1, 2));\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ANIM_FIRE_MED:\n\t\tcase ANIM_FIRE_MED2:\n\t\t\tnewanim = new AnimClass(ANIM_FIRE_SMALL, Center_Coord(), 0, Random_Pick(1, 2));\n\t\t\tif (newanim != NULL && xObject != TARGET_NONE) {\n\t\t\t\tnewanim->Attach_To(As_Object(xObject));\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::Detach -- Remove animation if attached to target.                                *\n *                                                                                             *\n *    This routine is called when the specified target is being removed from the game. If this *\n *    animation happens to be attached to this object, then the animation must be remove as    *\n *    well.                                                                                    *\n *                                                                                             *\n * INPUT:   target   -- The target that is about to be destroyed.                              *\n *                                                                                             *\n *          all      -- Is the target being destroyed RIGHT NOW? If not, then it will be       *\n *                      destroyed soon. In that case, the animation should continue to remain  *\n *                      attached for cosmetic reasons.                                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/30/1995 JLB : Created.                                                                 *\n *   07/02/1995 JLB : Detach is a precursor to animation destruction.                          *\n *=============================================================================================*/\nvoid AnimClass::Detach(TARGET target, bool all)\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (xObject == target && all) {\n\t\tMap.Remove(this, In_Which_Layer());\n\t\txObject = TARGET_NONE;\n\t\tIsToDelete = true;\n\t\tMark(MARK_UP);\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::Do_Atom_Damage -- Do atom bomb damage centered around the cell specified.        *\n *                                                                                             *\n *    This routine will apply damage around the ground-zero cell specified.                    *\n *                                                                                             *\n * INPUT:   ownerhouse  -- The owner of this atom bomb.                                        *\n *                                                                                             *\n *          cell        -- The ground zero location to apply the atom bomb damage.             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::Do_Atom_Damage(HousesType ownerhouse, CELL cell)\n{\n#ifdef VIC\n\t/*\n\t**\tFind someone to blame the explosion on. This is necessary in\n\t**\torder to properly enact retribution and record the kill for\n\t**\tscore purposes.\n\t*/\n\tBuildingClass * building = NULL;\n\tTechnoClass * backup = NULL;\n\tif (ownerhouse != HOUSE_NONE) {\n\t\tfor (int index = 0; index < Logic.Count(); index++) {\n\t\t\tObjectClass * obj = Logic[index];\n\n\t\t\tif (obj != NULL && obj->Is_Techno() && obj->Owner() == ownerhouse) {\n\t\t\t\tbackup = (TechnoClass *)obj;\n\t\t\t\tif (obj->What_Am_I() == RTTI_BUILDING && *((BuildingClass *)obj) == STRUCT_MSLO) {\n\t\t\t\t\tbuilding = (BuildingClass *)obj;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (building == NULL) building = (BuildingClass *)backup;\n\t}\n\n\tint radius;\n\tint rawdamage;\n\tif (Session.Type == GAME_NORMAL) {\n\t\tradius = 4;\n\t\trawdamage = Rule.AtomDamage;\n\t\tWhitePalette.Set(FADE_PALETTE_SLOW, Call_Back);\n\t} else {\n\t\tradius = 3;\n\t\trawdamage = Rule.AtomDamage/5;\n\t}\n\n\tWide_Area_Damage(Cell_Coord(cell), radius * CELL_LEPTON_W, rawdamage, building, WARHEAD_FIRE);\n\tShake_The_Screen(3);\n\tif (Session.Type == GAME_NORMAL) {\n\t\tGamePalette.Set(FADE_PALETTE_SLOW, Call_Back);\n\t}\n#endif\n}\n\n\n"
  },
  {
    "path": "CODE/ANIM.CPP.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\anim.cpv   4.78   03 Oct 1996 09:20:46   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Dune                                                         *\n *                                                                                             *\n *                    File Name : ANIM.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 3, 1991                                                 *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   AnimClass::AI -- This is the low level anim processor.                                    *\n *   AnimClass::AnimClass -- The constructor for animation objects.                            *\n *   AnimClass::Attach_To -- Attaches animation to object specified.                           *\n *   AnimClass::Center_Coord -- Determine center of animation.                                 *\n *   AnimClass::Detach -- Remove animation if attached to target.                              *\n *   AnimClass::Do_Atom_Damage -- Do atom bomb damage centered around the cell specified.      *\n *   AnimClass::Draw_It -- Draws the animation at the location specified.                      *\n *   AnimClass::In_Which_Layer -- Determines what render layer the anim should be in.          *\n *   AnimClass::Init -- Performs pre-scenario initialization.                                  *\n *   AnimClass::Mark -- Signals to map that redrawing is necessary.                            *\n *   AnimClass::Middle -- Processes any middle events.                                         *\n *   AnimClass::Occupy_List -- Determines the occupy list for the animation.                   *\n *   AnimClass::Overlap_List -- Determines the overlap list for the animation.                 *\n *   AnimClass::Render -- Draws an animation object.                                           *\n *   AnimClass::Sort_Y -- Returns with the sorting coordinate for the animation.               *\n *   AnimClass::Start -- Processes initial animation side effects.                             *\n *   AnimClass::delete -- Returns an anim object back to the free pool.                        *\n *   AnimClass::new -- Allocates an anim object from the pool.                                 *\n *   AnimClass::~AnimClass -- Destructor for anim objects.                                     *\n *   Anim_From_Name -- Given a name, this finds the corresponding anim type.                   *\n *   Shorten_Attached_Anims -- Reduces attached animation durations.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * Anim_From_Name -- Given a name, this finds the corresponding anim type.                     *\n *                                                                                             *\n *    This routine will convert the supplied ASCII name into the animation type that it        *\n *    represents.                                                                              *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the ASCII name to convert.                                     *\n *                                                                                             *\n * OUTPUT:  Returns with the animation type that matches the name specified. If no match could *\n *          be found, then ANIM_NONE is returned.                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nAnimType Anim_From_Name(char const * name)\n{\n  #ifdef 0\n\tif (name == NULL) return(ANIM_NONE);\n\n\tfor (AnimType anim = ANIM_FIRST; anim < ANIM_COUNT; anim++) {\n\t\tif (stricmp(AnimTypeClass::As_Reference(anim).IniName, name) == 0) {\n\t\t\treturn(anim);\n\t\t}\n\t}\n#endif\n\treturn(ANIM_NONE);\n}\n\n\n/***********************************************************************************************\n * Shorten_Attached_Anims -- Reduces attached animation durations.                             *\n *                                                                                             *\n *    This routine is used to reduce the amount of time any attached animations will process.  *\n *    Typical use of this is when an object is on fire and the object should now be destroyed  *\n *    but the attached animations are to run until completion before destruction can follow.   *\n *    This routine will make the animation appear to run its course, but in as short of time   *\n *    as possible. The shortening effect is achieved by reducing the number of times the       *\n *    animation will loop.                                                                     *\n *                                                                                             *\n * INPUT:   obj   -- Pointer to the object that all attached animations will be processed.     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/11/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Shorten_Attached_Anims(ObjectClass * obj)\n{\n\tif (obj != NULL) {\n\t\tfor (int index = 0; index < Anims.Count(); index++) {\n\t\t\tAnimClass & anim = * Anims.Ptr(index);\n\n\t\t\tif (As_Object(anim.xObject) == obj) {\n\t\t\t\tanim.Loops = 0;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * AnimClass::Sort_Y -- Returns with the sorting coordinate for the animation.                 *\n *                                                                                             *\n *    This routine is used by the sorting system. Animations that are located in the ground    *\n *    layer will be sorted by this the value returned from this function.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the sort coordinate to use for this animation.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *   12/15/1994 JLB : Handles flat anims (infantry decay anims).                               *\n *=============================================================================================*/\nCOORDINATE AnimClass::Sort_Y(void) const\n{\n#ifdef 0\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (xObject != TARGET_NONE) {\n\t\treturn(Coord_Add(As_Object(xObject)->Sort_Y(), 0x00010000L));\n\t}\n\tif (*this == ANIM_MOVE_FLASH) {\n\t\treturn(Coord_Add(Center_Coord(), XYP_COORD(0, -24)));\n\t}\n\tif (Class->IsGroundLayer || *this == ANIM_LZ_SMOKE) {\n\t\treturn(Coord_Add(Center_Coord(), XYP_COORD(0, 14)));\n\t}\n#endif\n\treturn(Coord);\n}\n\n\n/***********************************************************************************************\n * AnimClass::Center_Coord -- Determine center of animation.                                   *\n *                                                                                             *\n *    This support function will return the \"center\" of the animation. The actual coordinate   *\n *    of the animation may be dependant on if the the animation is attached to an object.      *\n *    In such a case, it must factor in the object's location.                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the coordinate of the center of the animation. The coordinate is in real   *\n *          game coordinates -- taking into consideration if the animation is attached.        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *   02/02/1996 JLB : Coordinate based on visual center of object.                             *\n *=============================================================================================*/\nCOORDINATE AnimClass::Center_Coord(void) const\n{\n#ifdef 0\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (xObject != TARGET_NONE) {\n\t\treturn(Coord_Add(Coord, As_Object(xObject)->Target_Coord()));\n\t}\n#endif\n\treturn(Coord);\n}\n\n\n/***********************************************************************************************\n * AnimClass::Render -- Draws an animation object.                                             *\n *                                                                                             *\n *    This is the working routine that renders the animation shape. It gets called once        *\n *    per animation per frame. It needs to be fast.                                            *\n *                                                                                             *\n * INPUT:   bool; Should the animation be rendered in spite of render flag?                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the animation rendered?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AnimClass::Render(bool forced) const\n{\n#ifdef 0\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Delay) return(false);\n\tif (Map[Center_Coord()].IsVisible) {\n\t\tIsToDisplay = true;\n\t}\n#endif\n\treturn(ObjectClass::Render(forced));\n}\n\n\n/***********************************************************************************************\n * AnimClass::Draw_It -- Draws the animation at the location specified.                        *\n *                                                                                             *\n *    This routine is used to render the animation object at the location specified. This is   *\n *    how the map imagery gets updated.                                                        *\n *                                                                                             *\n * INPUT:   x,y      -- The pixel coordinates to draw the animation at.                        *\n *                                                                                             *\n *          window   -- The to base the draw coordinates upon.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *   05/19/1995 JLB : Added white translucent effect.                                          *\n *=============================================================================================*/\nvoid AnimClass::Draw_It(int x, int y, WindowNumberType window) const\n{\n#ifdef 0\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!IsInvisible) {\n\t\tBStart(BENCH_ANIMS);\n\n\t\tvoid const * shapefile = Get_Image_Data();\n\t\tif (shapefile != NULL) {\n\t\t\tvoid const * transtable = NULL;\n\t\t\tint shapenum = Class->Start + Fetch_Stage();\n\t\t\tvoid const * remap = NULL;\n\n\t\t\t/*\n\t\t\t**\tIf the translucent table hasn't been determined yet, then check to see if it\n\t\t\t**\tshould use the white or normal translucent tables.\n\t\t\t*/\n\t\t\tif (transtable == NULL && Class->IsWhiteTrans) transtable = DisplayClass::WhiteTranslucentTable;\n\t\t\tif (transtable == NULL && Class->IsTranslucent) transtable = DisplayClass::TranslucentTable;\n\t\t\tif (Class->Type == ANIM_ATOM_BLAST) transtable = Map.UnitShadow;\n\n\t\t\t/*\n\t\t\t**\tSet the shape flags to properly take into account any fading or ghosting\n\t\t\t**\ttable necessary.\n\t\t\t*/\n\t\t\tShapeFlags_Type flags = SHAPE_CENTER|SHAPE_WIN_REL;\n\t\t\tif (transtable != NULL) flags = flags | SHAPE_GHOST;\n\n\t\t\t/*\n\t\t\t**\tDraw the animation shape.\n\t\t\t*/\n\t\t\tCC_Draw_Shape(shapefile, shapenum, x, y, window, flags, remap, transtable);\n\t\t}\n\t\tBEnd(BENCH_ANIMS);\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::Mark -- Signals to map that redrawing is necessary.                              *\n *                                                                                             *\n *    This routine is used by the animation logic system to inform the map that the cells      *\n *    under the animation must be rerendered.                                                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AnimClass::Mark(MarkType mark)\n{\n#ifdef 0\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (ObjectClass::Mark(mark)) {\n\t\tMap.Refresh_Cells(Coord_Cell(Center_Coord()), Overlap_List());\n//\t\tObjectClass::Mark(mark);\n\t\treturn(true);\n\t}\n#endif\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * AnimClass::Overlap_List -- Determines the overlap list for the animation.                   *\n *                                                                                             *\n *    Use this routine to fetch the overlap list for the animation. This overlap list is the   *\n *    cells that this animation spills over.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to the overlap list for this particular instance of the          *\n *          animation.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * AnimClass::Overlap_List(void) const\n{\n#ifdef 0\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\tstatic short const OverlapAtom[] = {\n\t\t(-MAP_CELL_W * 2) - 1, (-MAP_CELL_W * 2), (-MAP_CELL_W * 2) + 1,\n\t\t(-MAP_CELL_W * 1) - 1, (-MAP_CELL_W * 1), (-MAP_CELL_W * 1) + 1,\n\t\t(-MAP_CELL_W * 0) - 1, (-MAP_CELL_W * 0), (-MAP_CELL_W * 0) + 1,\n\t\t( MAP_CELL_W * 1) - 1, ( MAP_CELL_W * 1), ( MAP_CELL_W * 1) + 1,\n\t\t( MAP_CELL_W * 2) - 1, ( MAP_CELL_W * 2), ( MAP_CELL_W * 2) + 1,\n \t\tREFRESH_EOL\n\t};\n\n\tif (IsToDelete) {\n\t\tstatic short const _list[] = {REFRESH_EOL};\n\t\treturn(_list);\n\t}\n\n\tif (Class->Type == ANIM_ATOM_BLAST) {\n\t\treturn(OverlapAtom);\n\t}\n\n#ifdef PARTIAL\n\tif (Class->Get_Image_Data() != NULL) {\n\t\tint shapenum = Class->Start + Fetch_Stage();\n\t\tint count = Get_Build_Frame_Count(Class->Get_Image_Data());\n\t\tshapenum = min(shapenum, count-1);\n\n\t\tif (Class->DimensionData == NULL) {\n\t\t\tClass->DimensionData = new Rect [count];\n\t\t}\n\t\tif (Class->DimensionData != NULL && !Class->DimensionData[shapenum].Is_Valid()) {\n\t\t\tClass->DimensionData[shapenum] = Shape_Dimensions(Class->Get_Image_Data(), shapenum);\n\t\t\treturn(Coord_Spillage_List(Center_Coord(), Class->DimensionData[shapenum]));\n\t\t}\n\t}\n#endif\n#endif\n\treturn(Coord_Spillage_List(Center_Coord(), Class->Size));\n}\n\n\n/***********************************************************************************************\n * AnimClass::Occupy_List -- Determines the occupy list for the animation.                     *\n *                                                                                             *\n *    Animations always occupy only the cell that their center is located over. As such, this  *\n *    routine always returns a simple (center cell) occupation list.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the occupation list for the animation.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * AnimClass::Occupy_List(bool) const\n{\n#ifdef 0\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tstatic short _simple[] = {REFRESH_EOL};\n\n#endif\n\treturn(_simple);\n}\n\n\n/***********************************************************************************************\n * AnimClass::Init -- Performs pre-scenario initialization.                                    *\n *                                                                                             *\n *    This routine is used to initialize the animation system prior to a scenario being loaded *\n *    or reloaded. It effectively removes all animations from the system.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::Init(void)\n{\n\tAnims.Free_All();\n}\n\n\n/***********************************************************************************************\n * AnimClass::new -- Allocates an anim object from the pool.                                   *\n *                                                                                             *\n *    This routine is used to allocate a free anim class object from the preallocated pool     *\n *    in the near heap. If there are no free animation objects, then null is returned.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a free anim object.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * AnimClass::operator new(size_t)\n{\n\tvoid * ptr = Anims.Allocate();\n\tif (ptr != NULL) {\n\t\t((AnimClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * AnimClass::delete -- Returns an anim object back to the free pool.                          *\n *                                                                                             *\n *    This routine is used to return an anim object back to the pool of free anim objects.     *\n *    Anim objects so returned are available to be reallocated for the next animation.         *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the anim object to return to the pool.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::operator delete(void * ptr)\n{\n\tif (ptr != NULL) {\n\t\t((AnimClass *)ptr)->IsActive = false;\n\t}\n\tAnims.Free((AnimClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * AnimClass::AnimClass -- The constructor for animation objects.                              *\n *                                                                                             *\n *    This routine is used as the constructor of animation objects. It initializes and adds    *\n *    the animation object to the display and logic systems.                                   *\n *                                                                                             *\n * INPUT:   animnum  -- The animation number to start.                                         *\n *                                                                                             *\n *          coord    -- The location of the animation.                                         *\n *                                                                                             *\n *          timedelay-- The delay before the animation starts.                                 *\n *                                                                                             *\n *          loop     -- The number of times to loop this animation.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   08/03/1994 JLB : Added a delayed affect parameter.                                        *\n *=============================================================================================*/\nAnimClass::AnimClass(AnimType animnum, COORDINATE coord, unsigned char timedelay, unsigned char loop) :\n\tObjectClass(RTTI_ANIM, Anims.ID(this)),\n\tClass(AnimTypes.Ptr((int)animnum)),\n\txObject(TARGET_NONE),\n\tOwnerHouse(HOUSE_NONE),\n\tLoops(1),\n\tIsToDelete(false),\n\tIsBrandNew(true),\n\tIsInvisible(false),\n\tDelay(timedelay),\n\tAccum(0)\n{\n#ifdef 0\n\tif (Class->Stages == -1) {\n\t\t((int&)Class->Stages) = Get_Build_Frame_Count(Class->Get_Image_Data());\n\t}\n\tif (Class->LoopEnd == -1) {\n\t\t((int&)Class->LoopEnd) = Class->Stages;\n\t}\n\tif (Class->IsNormalized) {\n\t\tSet_Rate(Options.Normalize_Delay(Class->Delay));\n\t} else {\n\t\tSet_Rate(Class->Delay);\n\t}\n\tSet_Stage(0);\n\n\tif (Class->IsGroundLayer) {\n\t\tHeight = FLIGHT_LEVEL;\n\t}\n\n\tAnimClass::Unlimbo(coord);\n\n\t/*\n\t**\tDrop zone smoke always reveals the map around itself.\n\t*/\n\tif (*this == ANIM_LZ_SMOKE) {\n\t\tMap.Sight_From(Coord_Cell(coord), Rule.DropZoneRadius / CELL_LEPTON_W, PlayerPtr, false);\n\t}\n\n\tLoops = (unsigned char)(max(loop, 1) * Class->Loops);\n\tLoops = (unsigned char)max(Loops, 1);\n\n\t/*\n\t**\tIf the animation starts immediately, then play the associated sound effect now.\n\t*/\n\tif (!Delay) {\n\t\tStart();\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::~AnimClass -- Destructor for anim objects.                                       *\n *                                                                                             *\n *    This destructor handles removing the animation object from the system. It might require  *\n *    informing any object this animation is attached to that it is no longer attached.        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/29/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nAnimClass::~AnimClass(void)\n{\n#ifdef 0\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\tif (GameActive) {\n\n\t\t/*\n\t\t**\tIf this anim is attached to another object\n\t\t**\tthen check to see if this is the last anim attached to it. If this\n\t\t**\tis the case, then inform the object that it is no longer attached to\n\t\t**\tan animation.\n\t\t*/\n\t\tif (Target_Legal(xObject) && As_Object(xObject) != NULL) {\n\t\t\tObjectClass * to = As_Object(xObject);\n\n\t\t\t/*\n\t\t\t**\tRemove the object from the appropriate display list.\n\t\t\t*/\n\t\t\tMap.Remove(this, In_Which_Layer());\n\n\t\t\t/*\n\t\t\t**\tScan for any other animations that are attached to the object that\n\t\t\t**\tthis animation is attached to. If there are no others, then inform the\n\t\t\t**\tattached object of this fact.\n\t\t\t*/\n\t\t\tfor (int index = 0; index < Anims.Count(); index++) {\n\t\t\t\tif (Anims.Ptr(index) != this && Anims.Ptr(index)->xObject == xObject) break;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tTell the object that it is no longer being damaged.\n\t\t\t*/\n\t\t\tif (index == Anims.Count()) {\n\t\t\t\tto->Fire_Out();\n\t\t\t\tto->Mark(MARK_OVERLAP_UP);\n\t\t\t\tto->IsAnimAttached = false;\n\t\t\t\tto->Mark(MARK_OVERLAP_DOWN);\n\t\t\t}\n\t\t\tCoord = Coord_Add(to->Center_Coord(), Coord);\n\t\t\txObject = TARGET_NONE;\n\t\t}\n\n\t\tLimbo();\n\t}\n\n\txObject = TARGET_NONE;\n\tClass = 0;\n\tID = -1;\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::AI -- This is the low level anim processor.                                      *\n *                                                                                             *\n *    This routine is called once per frame per animation. It handles transition between       *\n *    animation frames and marks the map for redraw as necessary.                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Speed is of upmost importance.                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::AI(void)\n{\n#ifdef 0\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tFor ground level based animations (ones that can run slowly as well as\n\t**\toccur behind other ground objects) always cause the cell to be redrawn.\n\t*/\n#ifdef PARTIAL\n\tif (!Delay && Class->IsGroundLayer) {\n\t\tMap.Refresh_Cells(Coord_Cell(Center_Coord()), Overlap_List());\n\t}\n#else\n\tMap.Refresh_Cells(Coord_Cell(Center_Coord()), Overlap_List());\n#endif\n\n\t/*\n\t**\tSpecial case check to make sure that building on top of a smoke marker\n\t**\tcauses the smoke marker to vanish.\n\t*/\n\tif (Class->Type == ANIM_LZ_SMOKE && Map[Center_Coord()].Cell_Building()) {\n\t\tIsToDelete = true;\n\t}\n\n\t/*\n\t**\tDelete this animation and bail early if the animation is flagged to be deleted\n\t**\timmediately.\n\t*/\n\tif (IsToDelete) {\n\t\tdelete this;\n\t\treturn;\n\t}\n\n\t/*\n\t**\tIf this is a brand new animation, then don't process it the first logic pass\n\t**\tsince it might end up skipping the first animation frame before it has had a\n\t**\tchance to draw it.\n\t*/\n\tif (IsBrandNew) {\n\t\tIsBrandNew = false;\n\t\treturn;\n\t}\n\n\tif (Delay) {\n\t\tDelay--;\n\t\tif (!Delay) {\n\t\t\tStart();\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tThis is necessary because there is no recording of animations on the map\n\t\t**\tand thus the animation cannot be intelligently flagged for redraw. Most\n\t\t**\tanimations move fast enough that they would need to be redrawn every\n\t\t**\tgame frame anyway so this isn't TOO bad.\n\t\t*/\n\t\tMark(MARK_CHANGE);\n\n\t\tif (StageClass::Graphic_Logic()) {\n\t\t\tint stage = Fetch_Stage();\n\n\t\t\t/*\n\t\t\t**\tIf this animation is attached to another object and it is a\n\t\t\t**\tdamaging kind of animation, then do the damage to the other\n\t\t\t**\tobject.\n\t\t\t*/\n\t\t\tif (xObject != TARGET_NONE && Class->Damage > 0) {\n\t\t\t\tAccum += Class->Damage;\n\n\t\t\t\tif (Accum >= 1) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tAdminister the damage. If the object was destroyed by this anim,\n\t\t\t\t\t**\tthen the attached damaging anim is also destroyed.\n\t\t\t\t\t*/\n\t\t\t\t\tint damage = Accum;\n\t\t\t\t\tAccum -= damage;\n\t\t\t\t\tif (As_Object(xObject)->Take_Damage(damage, 0, WARHEAD_FIRE) == RESULT_DESTROYED) {\n\t\t\t\t\t\tdelete this;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDuring the biggest stage (covers the most ground), perform any ground altering\n\t\t\t**\taction required. This masks craters and scorch marks, so that they appear\n\t\t\t**\tnaturally rather than \"popping\" into existence while in plain sight.\n\t\t\t*/\n\t\t\tif (Class->Biggest && Class->Start+stage == Class->Biggest) {\n\t\t\t\tMiddle();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCheck to see if the last frame has been displayed. If so, then the\n\t\t\t**\tanimation either ends or loops.\n\t\t\t*/\n\t\t\tif ((Loops <= 1 && stage >= Class->Stages) || (Loops > 1 && stage >= Class->LoopEnd-Class->Start)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDetermine if this animation should loop another time. If so, then start the loop\n\t\t\t\t**\tbut if not, then proceed into the animation termination handler.\n\t\t\t\t*/\n\t\t\t\tif (Loops) Loops--;\n\t\t\t\tif (Loops) {\n\t\t\t\t\tSet_Stage(Class->LoopStart);\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThe animation should end now, but first check to see if\n\t\t\t\t\t**\tit needs to chain into another animation. If so, then the\n\t\t\t\t\t**\tanimation isn't technically over. It metamorphoses into the\n\t\t\t\t\t**\tnew form.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Class->ChainTo != ANIM_NONE) {\n\n\t\t\t\t\t\tClass = (AnimTypeClass *)&AnimTypeClass::As_Reference(Class->ChainTo);\n\n\t\t\t\t\t\tif (Class->Stages == -1) {\n\t\t\t\t\t\t\t((int&)Class->Stages) = Get_Build_Frame_Count(Class->Get_Image_Data());\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Class->LoopEnd == -1) {\n\t\t\t\t\t\t\t((int&)Class->LoopEnd) = Class->Stages;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tIsToDelete = false;\n\t\t\t\t\t\tLoops = Class->Loops;\n\t\t\t\t\t\tAccum = 0;\n\t\t\t\t\t\tif (Class->IsNormalized) {\n\t\t\t\t\t\t\tSet_Rate(Options.Normalize_Delay(Class->Delay));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSet_Rate(Class->Delay);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSet_Stage(Class->Start);\n\t\t\t\t\t\tStart();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdelete this;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::Attach_To -- Attaches animation to object specified.                             *\n *                                                                                             *\n *    An animation can be \"attached\" to an object. In such cases, the animation is rendered    *\n *    as an offset from the center of the object it is attached to. This allows affects such   *\n *    as fire or smoke to be consistently placed on the vehicle it is associated with.         *\n *                                                                                             *\n * INPUT:   obj   -- Pointer to the object to attach the animation to.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::Attach_To(ObjectClass * obj)\n{\n#ifdef 0\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (obj == NULL) return;\n\tassert(obj->IsActive);\n\n\tobj->Mark(MARK_OVERLAP_UP);\n\tobj->IsAnimAttached = true;\n\tobj->Mark(MARK_OVERLAP_DOWN);\n\tMap.Remove(this, In_Which_Layer());\n\txObject = obj->As_Target();\n\tMap.Submit(this, In_Which_Layer());\n\tCoord = Coord_Sub(Coord, obj->Target_Coord());\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::In_Which_Layer -- Determines what render layer the anim should be in.            *\n *                                                                                             *\n *    Use this routine to find out which display layer (ground or air) that the animation      *\n *    should be in. This information is used to place the animation into the correct display   *\n *    list.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the layer that the animation should exist in.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/25/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nLayerType AnimClass::In_Which_Layer(void) const\n{\n#ifdef 0\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Target_Legal(xObject) || Class->IsGroundLayer) {\n\t\treturn(LAYER_GROUND);\n\t}\n\n\treturn(LAYER_AIR);\n}\n\n\n/***********************************************************************************************\n * AnimClass::Start -- Processes initial animation side effects.                               *\n *                                                                                             *\n *    This routine is called when the animation first starts. Sometimes there are side effects *\n *    associated with this animation that must occur immediately. Typically, this is the       *\n *    sound effect assigned to this animation. If this animation is supposed to attach itself  *\n *    to any object at its location, then do so at this time as well.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/30/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::Start(void)\n{\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tMark();\n\n\t/*\n\t**\tPlay the sound effect for this animation.\n\t*/\n\tSound_Effect(Class->Sound, Coord);\n\n\t/*\n\t**\tIf the stage where collateral effects occur is the first stage of the animation, then\n\t**\tperform this action now. Subsequent checks against this stage value starts with the\n\t**\tsecond frame of the animation.\n\t*/\n\tif (!Class->Biggest) {\n\t\tMiddle();\n\t}\n}\n\n\n/***********************************************************************************************\n * AnimClass::Middle -- Processes any middle events.                                           *\n *                                                                                             *\n *    This routine is called when the animation as reached its largest stage. Typically, this  *\n *    routine is used to cause scorches or craters to appear at a cosmetically pleasing        *\n *    moment.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/30/1995 JLB : Created.                                                                 *\n *   10/17/1995 JLB : Ion camera added.                                                        *\n *=============================================================================================*/\nvoid AnimClass::Middle(void)\n{\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tCELL cell = Coord_Cell(Center_Coord());\n\tCellClass * cellptr = &Map[cell];\n\n\tif (Class->Type == ANIM_ATOM_BLAST) {\n\t\tDo_Atom_Damage(OwnerHouse, cell);\n\t}\n\n\t/*\n\t**\tIf this animation leaves scorch marks (e.g., napalm), then do so at this time.\n\t*/\n\tif (Class->IsScorcher) {\n\t\tnew SmudgeClass(Random_Pick(SMUDGE_SCORCH1, SMUDGE_SCORCH6), Center_Coord());\n\t}\n\n\t/*\n\t**\tSome animations leave a crater when they occur. Artillery is a good example.\n\t**\tCraters always remove the Tiberium where they occur.\n\t*/\n\tif (Class->IsCraterForming) {\n\n\t\t/*\n\t\t**\tCraters reduce the level of Tiberium in the cell.\n\t\t*/\n\t\tcellptr->Reduce_Tiberium(6);\n\n\t\t/*\n\t\t**\tIf there already is a crater in the cell, then just expand the\n\t\t**\tcrater.\n\t\t*/\n\t\tnew SmudgeClass(SMUDGE_CRATER1, Center_Coord());\n\t}\n\n\tAnimClass * newanim;\n\n\t/*\n\t**\tIf this animation spawns side effects during its lifetime, then\n\t**\tdo so now. Usually, these side effects are in the form of other\n\t**\tanimations.\n\t*/\n\tswitch (Class->Type) {\n\t\tcase ANIM_NAPALM1:\n\t\tcase ANIM_NAPALM2:\n\t\tcase ANIM_NAPALM3:\n\t\t\tnew AnimClass(ANIM_FIRE_SMALL, Map.Closest_Free_Spot(Coord_Scatter(Center_Coord(), 0x0040), true), 0, Random_Pick(1, 2));\n\t\t\tif (Percent_Chance(50)) {\n\t\t\t\tnew AnimClass(ANIM_FIRE_SMALL, Map.Closest_Free_Spot(Coord_Scatter(Center_Coord(), 0x00A0), true), 0, Random_Pick(1, 2));\n\t\t\t}\n\t\t\tif (Percent_Chance(50)) {\n\t\t\t\tnew AnimClass(ANIM_FIRE_MED, Map.Closest_Free_Spot(Coord_Scatter(Center_Coord(), 0x0070), true), 0, Random_Pick(1, 2));\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ANIM_FIRE_MED:\n\t\tcase ANIM_FIRE_MED2:\n\t\t\tnewanim = new AnimClass(ANIM_FIRE_SMALL, Center_Coord(), 0, Random_Pick(1, 2));\n\t\t\tif (newanim != NULL && xObject != TARGET_NONE) {\n\t\t\t\tnewanim->Attach_To(As_Object(xObject));\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * AnimClass::Detach -- Remove animation if attached to target.                                *\n *                                                                                             *\n *    This routine is called when the specified target is being removed from the game. If this *\n *    animation happens to be attached to this object, then the animation must be remove as    *\n *    well.                                                                                    *\n *                                                                                             *\n * INPUT:   target   -- The target that is about to be destroyed.                              *\n *                                                                                             *\n *          all      -- Is the target being destroyed RIGHT NOW? If not, then it will be       *\n *                      destroyed soon. In that case, the animation should continue to remain  *\n *                      attached for cosmetic reasons.                                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/30/1995 JLB : Created.                                                                 *\n *   07/02/1995 JLB : Detach is a precursor to animation destruction.                          *\n *=============================================================================================*/\nvoid AnimClass::Detach(TARGET target, bool all)\n{\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (xObject == target && all) {\n\t\tMap.Remove(this, In_Which_Layer());\n\t\txObject = TARGET_NONE;\n\t\tIsToDelete = true;\n\t\tMark(MARK_UP);\n\t}\n}\n\n\n/***********************************************************************************************\n * AnimClass::Do_Atom_Damage -- Do atom bomb damage centered around the cell specified.        *\n *                                                                                             *\n *    This routine will apply damage around the ground-zero cell specified.                    *\n *                                                                                             *\n * INPUT:   ownerhouse  -- The owner of this atom bomb.                                        *\n *                                                                                             *\n *          cell        -- The ground zero location to apply the atom bomb damage.             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::Do_Atom_Damage(HousesType ownerhouse, CELL cell)\n{\n\t/*\n\t**\tFind someone to blame the explosion on. This is necessary in\n\t**\torder to properly enact retribution and record the kill for\n\t**\tscore purposes.\n\t*/\n\tBuildingClass * building = NULL;\n\tTechnoClass * backup = NULL;\n\tif (ownerhouse != HOUSE_NONE) {\n\t\tfor (int index = 0; index < Logic.Count(); index++) {\n\t\t\tObjectClass * obj = Logic[index];\n\n\t\t\tif (obj != NULL && obj->Is_Techno() && obj->Owner() == ownerhouse) {\n\t\t\t\tbackup = (TechnoClass *)obj;\n\t\t\t\tif (obj->What_Am_I() == RTTI_BUILDING && *((BuildingClass *)obj) == STRUCT_MSLO) {\n\t\t\t\t\tbuilding = (BuildingClass *)obj;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (building == NULL) building = (BuildingClass *)backup;\n\t}\n\n\tint radius;\n\tint rawdamage;\n\tif (Session.Type == GAME_NORMAL) {\n\t\tradius = 4;\n\t\trawdamage = Rule.AtomDamage;\n\t\tWhitePalette.Set(FADE_PALETTE_SLOW, Call_Back);\n\t} else {\n\t\tradius = 3;\n\t\trawdamage = Rule.AtomDamage/5;\n\t}\n\n\tWide_Area_Damage(Cell_Coord(cell), radius * CELL_LEPTON_W, rawdamage, building, WARHEAD_FIRE);\n\tShake_The_Screen(3);\n\tif (Session.Type == GAME_NORMAL) {\n\t\tGamePalette.Set(FADE_PALETTE_SLOW, Call_Back);\n\t}\n}\n\n\n"
  },
  {
    "path": "CODE/ANIM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/ANIM.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ANIM.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 30, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 30, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef ANIM_H\n#define ANIM_H\n\n#include\t\"type.h\"\n\n\n/**********************************************************************************************\n**\tThis is the class that controls the shape animation objects. Shape animation objects are\n**\tdisplayed over the top of the game map. Typically, they are used for explosion and fire\n**\teffects.\n*/\nclass AnimClass : public ObjectClass, public StageClass {\n\t\t/*\n\t\t**\tThis points to the type of animation object this is.\n\t\t*/\n\t\tCCPtr<AnimTypeClass> Class;\n\n\tpublic:\n\n\t\tAnimClass(AnimType animnum, COORDINATE coord, unsigned char timedelay=0, unsigned char loop=1);\n\t\tAnimClass(NoInitClass const & x) : ObjectClass(x), Class(x), StageClass(x) {};\n\t\tvirtual ~AnimClass(void);\n\n\t\toperator AnimType(void) const {return Class->Type;};\n\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tstatic void Init(void);\n\n\t\tvoid Attach_To(ObjectClass *obj);\n\t\tvoid Make_Invisible(void) {IsInvisible = true;};\n\t\tstatic void Do_Atom_Damage(HousesType ownerhouse, CELL cell);\n\n\t\tvirtual bool Can_Place_Here(COORDINATE ) const {return true;}\n\t\tvirtual bool Mark(MarkType mark=MARK_CHANGE);\n\t\tvirtual bool Render(bool forced) const;\n\t\tvirtual COORDINATE Center_Coord(void) const;\n\t\tvirtual COORDINATE Sort_Y(void) const;\n\t\tvirtual LayerType In_Which_Layer(void) const;\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const {return *Class;};\n\t\tvirtual short const * Occupy_List(bool = false) const;\n\t\tvirtual short const * Overlap_List(void) const;\n\t\tvirtual void Draw_It(int x, int y, WindowNumberType window) const;\n\t\tvirtual void AI(void);\n\t\tvirtual void Detach(TARGET target, bool all);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tbool Load(Straw & file);\n\t\tbool Save(FileClass & file);\n\n\t\t/*\n\t\t**\tIf this animation is attached to an object, then this points to that object. An\n\t\t**\tanimation that is attached will follow that object as it moves. This is important\n\t\t**\tfor animations such as flames and smoke.\n\t\t*/\n\t\tTARGET xObject;\n\n\t\t/*\n\t\t**\tIf this animation has an owner, then it will be recorded here. An owner\n\t\t**\tis used when damage is caused by this animation during the middle of its\n\t\t**\tanimation.\n\t\t*/\n\t\tHousesType OwnerHouse;\n\n\t\t/*\n\t\t**\tThis counter tells how many more times the animation should loop before it\n\t\t**\tterminates.\n\t\t*/\n\t\tunsigned char Loops;\n\n\tprotected:\n\t\tvoid Middle(void);\n\t\tvoid Start(void);\n\n\tprivate:\n\t\t/*\n\t\t**\tDelete this animation at the next opportunity. This is flagged when the\n\t\t**\tanimation is to be prematurely ended as a result of some outside event.\n\t\t*/\n\t\tunsigned IsToDelete:1;\n\n\t\t/*\n\t\t**\tIf the animation has just been created, then don't do any animation\n\t\t**\tprocessing until it has been through the render loop at least once.\n\t\t*/\n\t\tunsigned IsBrandNew:1;\n\n\t\t/*\n\t\t**\tIf this animation is invisible, then this flag will be true. An invisible\n\t\t**\tanimation is one that is created for the sole purpose of keeping all\n\t\t**\tmachines synchronized. It will not be displayed.\n\t\t*/\n\t\tunsigned IsInvisible:1;\n\n\t\t/*\n\t\t**\tIs this animation in a temporary suspended state?  If so, then it won't\n\t\t**\tbe rendered until this value is zero. The flag will be set to false\n\t\t**\tafter the first countdown timer reaches 0.\n\t\t*/\n\t\tint Delay;\n\n\t\t/*\n\t\t**\tIf this is an animation that damages whatever it is attached to, then this\n\t\t**\tvalue holds the accumulation of fractional damage points. When the accumulated\n\t\t**\tfractions reach 256, then one damage point is applied to the attached object.\n\t\t*/\n\t\tfixed Accum;\n};\n\n\n\n#endif\n"
  },
  {
    "path": "CODE/AUDIO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/AUDIO.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : AUDIO.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : November 1, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Is_Speaking -- Checks to see if the eva voice is still playing.                           *\n *   Sound_Effect -- General purpose sound player.                                             *\n *   Sound_Effect -- Plays a sound effect in the tactical map.                                 *\n *   Speak -- Computer speaks to the player.                                                   *\n *   Speak_AI -- Handles starting the EVA voices.                                              *\n *   Speech_Name -- Fetches the name for the voice specified.                                  *\n *   Stop_Speaking -- Forces the EVA voice to stop talking.                                    *\n *   Voc_From_Name -- Fetch VocType from ASCII name specified.                                 *\n *   Voc_Name -- Fetches the name for the sound effect.                                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***************************************************************************\n**\tControls what special effects may occur on the sound effect.\n*/\ntypedef enum {\n\tIN_NOVAR,\t\t\t// No variation or alterations allowed.\n\tIN_VAR\t\t\t\t// Infantry variance response modification.\n} ContextType;\n\nstatic struct {\n\tchar const *\tName;\t\t// Digitized voice file name.\n\tint\t\t\t\tPriority;\t// Playback priority of this sample.\n\tContextType\t\tWhere;\t\t// In what game context does this sample exist.\n} SoundEffectName[VOC_COUNT] = {\n\n\t/*\n\t**\tCivilian voices (technicians too).\n\t*/\n\t{\"GIRLOKAY\",\t20,\tIN_NOVAR},\t\t//\tVOC_GIRL_OKAY\n\t{\"GIRLYEAH\",\t20,\tIN_NOVAR},\t\t//\tVOC_GIRL_YEAH\n\t{\"GUYOKAY1\",\t20,\tIN_NOVAR},\t\t//\tVOC_GUY_OKAY\n\t{\"GUYYEAH1\",\t20,\tIN_NOVAR},\t\t//\tVOC_GUY_YEAH\n\n\t{\"MINELAY1\",\t5,\t\tIN_VAR},\t\t\t// VOC_MINELAY1\n\n\t/*\n\t**\tInfantry and vehicle responses.\n\t*/\n\t{\"ACKNO\",\t\t20,\tIN_VAR},\t//\tVOC_ACKNOWL\t\t\t\"acknowledged\"\n\t{\"AFFIRM1\",\t\t20,\tIN_VAR},\t//\tVOC_AFFIRM\t\t\t\"affirmative\"\n\t{\"AWAIT1\",\t\t20,\tIN_VAR},\t//\tVOC_AWAIT1\t\t\t\"awaiting orders\"\n\t{\"EAFFIRM1\",\t20,\tIN_NOVAR},\t// VOC_ENG_AFFIRM\tEngineer: \"affirmative\"\n\t{\"EENGIN1\",\t\t20,\tIN_NOVAR},\t//\tVOC_ENG_ENG\t\t\tEngineer: \"engineering\"\n\t{\"NOPROB\",\t\t20,\tIN_VAR},\t// VOC_NO_PROB\t\t\t\"not a problem\"\n\t{\"READY\",\t\t20,\tIN_VAR},\t// VOC_READY\t\t\t\"ready and waiting\"\n\t{\"REPORT1\",\t\t20,\tIN_VAR},\t//\tVOC_REPORT\t\t\t\"reporting\"\n\t{\"RITAWAY\",\t\t20,\tIN_VAR},\t// VOC_RIGHT_AWAY\t\t\"right away sir\"\n\t{\"ROGER\",\t\t20,\tIN_VAR},\t// VOC_ROGER\t\t\t\"roger\"\n\t{\"UGOTIT\",\t\t20,\tIN_VAR},\t// VOC_UGOTIT\t\t\t\"you got it\"\n\t{\"VEHIC1\",\t\t20,\tIN_VAR},\t//\tVOC_VEHIC1\t\t\t\"vehicle reporting\"\n\t{\"YESSIR1\",\t\t20,\tIN_VAR},\t//\tVOC_YESSIR\t\t\t\"yes sir\"\n\n\t{\"DEDMAN1\", \t10,\tIN_NOVAR},\t// VOC_SCREAM1\t\t\tshort infantry scream\n\t{\"DEDMAN2\", \t10,\tIN_NOVAR},\t// VOC_SCREAM3\t\t\tshort infantry scream\n\t{\"DEDMAN3\", \t10,\tIN_NOVAR},\t// VOC_SCREAM4\t\t\tshort infantry scream\n\t{\"DEDMAN4\", \t10,\tIN_NOVAR},\t// VOC_SCREAM5\t\t\tshort infantry scream\n\t{\"DEDMAN5\", \t10,\tIN_NOVAR},\t// VOC_SCREAM6\t\t\tshort infantry scream\n\t{\"DEDMAN6\", \t10,\tIN_NOVAR},\t// VOC_SCREAM7\t\t\tshort infantry scream\n\t{\"DEDMAN7\", \t10,\tIN_NOVAR},\t// VOC_SCREAM10\t\tshort infantry scream\n\t{\"DEDMAN8\", \t10,\tIN_NOVAR},\t// VOC_SCREAM11\t\tshort infantry scream\n\t{\"DEDMAN10\", \t10,\tIN_NOVAR},\t// VOC_YELL1\t\t\tlong infantry scream\n\n\t{\"CHRONO2\",\t\t5,\t\tIN_NOVAR},\t//\tVOC_CHRONO\t\t\tChronosphere sound\n\t{\"CANNON1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CANNON1\t\t\tCannon sound (medium).\n\t{\"CANNON2\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CANNON2\t\t\tCannon sound (short).\n\t{\"IRONCUR9\",\t10,\tIN_NOVAR},\t// VOC_IRON1\n\t{\"EMOVOUT1\",\t20,\tIN_NOVAR},\t//\tVOC_ENG_MOVEOUT\tEngineer: \"movin' out\"\n\t{\"SONPULSE\",\t10,\tIN_NOVAR},\t//\tVOC_SONAR\n\t{\"SANDBAG2\",\t5,\t\tIN_NOVAR},\t// VOC_SANDBAG\t\t\tsand bag crunch\n\t{\"MINEBLO1\",\t5,\t\tIN_NOVAR},\t// VOC_MINEBLOW\t\tweird mine explosion\n\t{\"CHUTE1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CHUTE1\t\t\tWind swoosh sound.\n\t{\"DOGY1\",\t\t5,\t\tIN_NOVAR},\t//\tVOC_DOG_BARK\t\tDog bark.\n\t{\"DOGW5\",\t\t10,\tIN_NOVAR},\t//\tVOC_DOG_WHINE\t\tDog whine.\n\t{\"DOGG5P\",\t\t10,\tIN_NOVAR},\t//\tVOC_DOG_GROWL2\t\tStrong dog growl.\n\t{\"FIREBL3\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_FIRE_LAUNCH\tFireball launch sound.\n\t{\"FIRETRT1\",\t1,\t\tIN_NOVAR},\t//\tVOC_FIRE_EXPLODE\tFireball explode sound.\n\t{\"GRENADE1\",\t1,\t\tIN_NOVAR},\t//\tVOC_GRENADE_TOSS\tGrenade toss.\n\t{\"GUN11\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_GUN_5\t\t\t5 round gun burst (slow).\n\t{\"GUN13\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_GUN_7\t\t\t7 round gun burst (fast).\n\t{\"EYESSIR1\",\t20,\tIN_NOVAR},\t//\tVOC_ENG_YES,\t\tEngineer: \"yes sir\"\n\t{\"GUN27\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_GUN_RIFLE\t\tRifle shot.\n\t{\"HEAL2\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_HEAL\t\t\t\tHealing effect.\n\t{\"HYDROD1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_DOOR\t\t\t\tHyrdrolic door.\n\t{\"INVUL2\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_INVULNERABLE\tInvulnerability effect.\n\t{\"KABOOM1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_KABOOM1\t\t\tLong explosion (muffled).\n\t{\"KABOOM12\",\t1,\t\tIN_NOVAR},\t//\tVOC_KABOOM12\t\tVery long explosion (muffled).\n\t{\"KABOOM15\",\t1,\t\tIN_NOVAR},\t//\tVOC_KABOOM15\t\tVery long explosion (muffled).\n\t{\"SPLASH9\",\t\t5,\t\tIN_NOVAR},\t// VOC_SPLASH\t\t\twater splash\n\t{\"KABOOM22\",\t1,\t\tIN_NOVAR},\t//\tVOC_KABOOM22\t\tLong explosion (sharp).\n\t{\"AACANON3\",\t1,\t\tIN_NOVAR},\n\t{\"TANDETH1\",\t10,\tIN_NOVAR},\n\t{\"MGUNINF1\",\t1,\t\tIN_NOVAR},\t//\tVOC_GUN_5F\t\t\t5 round gun burst (fast).\n\t{\"MISSILE1\",\t1,\t\tIN_NOVAR},\t//\tVOC_MISSILE_1\t\tMissile with high tech effect.\n\t{\"MISSILE6\",\t1,\t\tIN_NOVAR},\t//\tVOC_MISSILE_2\t\tLong missile launch.\n\t{\"MISSILE7\",\t1,\t\tIN_NOVAR},\t//\tVOC_MISSILE_3\t\tShort missile launch.\n\t{\"x\",\t\t\t\t1,\t\tIN_NOVAR},\n\t{\"PILLBOX1\",\t1,\t\tIN_NOVAR},\t//\tVOC_GUN_5R\t\t\t5 round gun burst (rattles).\n\t{\"RABEEP1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_BEEP\t\t\t\tGeneric beep sound.\n\t{\"RAMENU1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CLICK\t\t\tGeneric click sound.\n\t{\"SILENCER\",\t1,\t\tIN_NOVAR},\t//\tVOC_SILENCER\t\tSilencer.\n\t{\"TANK5\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CANNON6\t\t\tLong muffled cannon shot.\n\t{\"TANK6\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CANNON7\t\t\tSharp mechanical cannon fire.\n\t{\"TORPEDO1\",\t1,\t\tIN_NOVAR},\t//\tVOC_TORPEDO\t\t\tTorpedo launch.\n\t{\"TURRET1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CANNON8\t\t\tSharp cannon fire.\n\t{\"TSLACHG2\",\t10,\tIN_NOVAR},\t//\tVOC_TESLA_POWER_UP\tHum charge up.\n\t{\"TESLA1\",\t\t10,\tIN_NOVAR},\t//\tVOC_TESLA_ZAP\t\tTesla zap effect.\n\t{\"SQUISHY2\",\t10,\tIN_NOVAR},\t//\tVOC_SQUISH\t\t\tSquish effect.\n\t{\"SCOLDY1\",\t\t10,\tIN_NOVAR},\t//\tVOC_SCOLD\t\t\tScold bleep.\n\t{\"RADARON2\",\t20,\tIN_NOVAR},\t//\tVOC_RADAR_ON\t\tPowering up electronics.\n\t{\"RADARDN1\",\t10,\tIN_NOVAR},\t//\tVOC_RADAR_OFF\t\tB movie power down effect.\n\t{\"PLACBLDG\",\t10,\tIN_NOVAR},\t//\tVOC_PLACE_BUILDING_DOWN\tBuilding slam down sound.\n\t{\"KABOOM30\",\t1,\t\tIN_NOVAR},\t//\tVOC_KABOOM30\t\tShort explosion (HE).\n\t{\"KABOOM25\",\t10,\tIN_NOVAR},\t//\tVOC_KABOOM25\t\tShort growling explosion.\n\t{\"x\",\t\t\t\t10,\tIN_NOVAR},\n\t{\"DOGW7\",\t\t10,\tIN_NOVAR},\t//\tVOC_DOG_HURT\t\tDog whine (loud).\n\t{\"DOGW3PX\",\t\t10,\tIN_NOVAR},\t//\tVOC_DOG_YES\t\t\tDog 'yes sir'.\n\t{\"CRMBLE2\",\t\t10,\tIN_NOVAR},\t//\tVOC_CRUMBLE\t\t\tBuilding crumble.\n\t{\"CASHUP1\",\t\t10,\tIN_NOVAR},\t//\tVOC_MONEY_UP\t\tRising money tick.\n\t{\"CASHDN1\",\t\t10,\tIN_NOVAR},\t//\tVOC_MONEY_DOWN\t\tFalling money tick.\n\t{\"BUILD5\",\t\t10,\tIN_NOVAR},\t//\tVOC_CONSTRUCTION\tBuilding construction sound.\n\t{\"BLEEP9\",\t\t10,\tIN_NOVAR},\t//\tVOC_GAME_CLOSED\tLong bleep.\n\t{\"BLEEP6\",\t\t10,\tIN_NOVAR},\t//\tVOC_INCOMING_MESSAGE\tSoft happy warble.\n\t{\"BLEEP5\",\t\t10,\tIN_NOVAR},\t//\tVOC_SYS_ERROR\t\tSharp soft warble.\n\t{\"BLEEP17\",\t\t10,\tIN_NOVAR},\t//\tVOC_OPTIONS_CHANGED\tMid range soft warble.\n\t{\"BLEEP13\",\t\t10,\tIN_NOVAR},\t//\tVOC_GAME_FORMING\tLong warble.\n\t{\"BLEEP12\",\t\t10,\tIN_NOVAR},\t//\tVOC_PLAYER_LEFT\tChirp sequence.\n\t{\"BLEEP11\",\t\t10,\tIN_NOVAR},\t//\tVOC_PLAYER_JOINED\tReverse chirp sequence.\n\t{\"H2OBOMB2\",\t10,\tIN_NOVAR},\t//\tVOC_DEPTH_CHARGE\tDistant explosion sound.\n\t{\"CASHTURN\",\t10,\tIN_NOVAR},\t//\tVOC_CASHTURN\t\tAirbrake.\n\t{\"TUFFGUY1\",\t20,\tIN_NOVAR},\t//\tVOC_TANYA_CHEW\t\t\tTanya: \"Chew on this\"\n\t{\"ROKROLL1\",\t20,\tIN_NOVAR},\t//\tVOC_TANYA_ROCK\t\t\tTanya: \"Let's rock\"\n\t{\"LAUGH1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_LAUGH\t\tTanya: \"ha ha ha\"\n\t{\"CMON1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_SHAKE\t\tTanya: \"Shake it baby\"\n\t{\"BOMBIT1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_CHING\t\tTanya: \"Cha Ching\"\n\t{\"GOTIT1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_GOT\t\t\tTanya: \"That's all you got\"\n\t{\"KEEPEM1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_KISS\t\t\tTanya: \"Kiss it bye bye\"\n\t{\"ONIT1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_THERE\t\tTanya: \"I'm there\"\n\t{\"LEFTY1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_GIVE\t\t\tTanya: \"Give it to me\"\n\t{\"YEAH1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_YEA\t\t\tTanya: \"Yea?\"\n\t{\"YES1\",\t\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_YES\t\t\tTanya: \"Yes sir?\"\n\t{\"YO1\",\t\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_WHATS\t\tTanya: \"What's up.\"\n\t{\"WALLKIL2\",\t5,\t\tIN_NOVAR},\t//\tVOC_WALLKILL2\t\t\tCrushing wall sound.\n\t{\"x\",\t\t\t\t10,\tIN_NOVAR},\n\t{\"GUN5\",\t\t\t5,\t\tIN_NOVAR},\t//\tVOC_TRIPLE_SHOT\t\tThree quick shots in succession.\n\t{\"SUBSHOW1\",\t5,\t\tIN_NOVAR},\t//\tVOC_SUBSHOW\t\t\t\tSubmarine surface sound.\n\t{\"EINAH1\",\t\t20,\tIN_NOVAR},\t//\tVOC_E_AH,\t\t\t\tEinstien \"ah\"\n\t{\"EINOK1\",\t\t20,\tIN_NOVAR},\t//\tVOC_E_OK,\t\t\t\tEinstien \"ok\"\n\t{\"EINYES1\",\t\t20,\tIN_NOVAR},\t//\tVOC_E_YES,\t\t\t\tEinstien \"yes\"\n\t{\"MINE1\",\t\t10,\tIN_NOVAR},\t//\tVOC_TRIP_MINE\t\t\tmine explosion sound\n\n\t{\"SCOMND1\",\t\t20,\tIN_NOVAR},\t//\tVOC_SPY_COMMANDER\t\tSpy: \"commander?\"\n\t{\"SYESSIR1\",\t20,\tIN_NOVAR},\t//\tVOC_SPY_YESSIR\t\t\tSpy: \"yes sir\"\n\t{\"SINDEED1\",\t20,\tIN_NOVAR},\t//\tVOC_SPY_INDEED\t\t\tSpy: \"indeed\"\n\t{\"SONWAY1\",\t\t20,\tIN_NOVAR},\t//\tVOC_SPY_ONWAY\t\t\tSpy: \"on my way\"\n\t{\"SKING1\",\t\t20,\tIN_NOVAR},\t//\tVOC_SPY_KING\t\t\tSpy: \"for king and country\"\n\t{\"MRESPON1\",\t20,\tIN_NOVAR},\t//\tVOC_MED_REPORTING\t\tMedic: \"reporting\"\n\t{\"MYESSIR1\",\t20,\tIN_NOVAR},\t//\tVOC_MED_YESSIR\t\t\tMedic: \"yes sir\"\n\t{\"MAFFIRM1\",\t20,\tIN_NOVAR},\t//\tVOC_MED_AFFIRM\t\t\tMedic: \"affirmative\"\n\t{\"MMOVOUT1\",\t20,\tIN_NOVAR},\t//\tVOC_MED_MOVEOUT\t\tMedic: \"movin' out\"\n\t{\"BEEPSLCT\",\t10,\tIN_NOVAR},\t//\tVOC_BEEP_SELECT\t\tmap selection beep\n\n\t{\"SYEAH1\",\t\t20,\tIN_NOVAR},\t//\tVOC_THIEF_YEA\t\t\tThief: \"yea?\"\n\t{\"ANTDIE\",\t\t20,\tIN_NOVAR},\t//\tVOC_ANTDIE\n\t{\"ANTBITE\",\t\t20,\tIN_NOVAR},\t//\tVOC_ANTBITE\n\t{\"SMOUT1\",\t\t20,\tIN_NOVAR},\t//\tVOC_THIEF_MOVEOUT\t\tThief: \"movin' out\"\n\t{\"SOKAY1\",\t\t20,\tIN_NOVAR},\t//\tVOC_THIEF_OKAY\t\t\tThief: \"ok\"\n\t{\"x\",\t\t\t\t20,\tIN_NOVAR},\n\t{\"SWHAT1\",\t\t20,\tIN_NOVAR},\t//\tVOC_THIEF_WHAT\t\t\tThief: \"what\"\n\t{\"SAFFIRM1\",\t20,\tIN_NOVAR},\t//\tVOC_THIEF_AFFIRM\t\tThief: \"affirmative\"\n//ADDED VG 2/24/97\n\t{\"STAVCMDR\",\t20,\tIN_NOVAR},\t\n\t{\"STAVCRSE\",\t20,\tIN_NOVAR},\t\n\t{\"STAVYES\",\t\t20,\tIN_NOVAR},\t\n\t{\"STAVMOV\",\t\t20,\tIN_NOVAR},\t\n\t{\"BUZZY1\",\t\t20,\tIN_NOVAR},\t\n\t{\"RAMBO1\",     20,   IN_NOVAR},\t\t\t\n\t{\"RAMBO2\", \t\t20,   IN_NOVAR}, \n\t{\"RAMBO3\",     20,   IN_NOVAR},\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t{\"MYES1\",\t\t20,\tIN_NOVAR},\t// VOC_MECHYES1\t\t\tMechanic: \"Yes sir!\"\n\t{\"MHOWDY1\",\t\t20,\tIN_NOVAR},\t// VOC_MECHHOWDY1\t\t\tMechanic: \"Howdy!\"\n\t{\"MRISE1\",\t\t20,\tIN_NOVAR},\t// VOC_MECHRISE1\t\t\tMechanic: \"Rise 'n shine!\"\n\t{\"MHUH1\",\t\t20,\tIN_NOVAR},\t// VOC_MECHHUH1\t\t\tMechanic: \"Huh?\"\n\t{\"MHEAR1\",\t\t20,\tIN_NOVAR},\t// VOC_MECHHEAR1\t\t\tMechanic: \"I Hear Ya!\"\n\t{\"MLAFF1\",\t\t20,\tIN_NOVAR},\t// VOC_MECHLAFF1\t\t\tMechanic: guffaw\n\t{\"MBOSS1\",\t\t20,\tIN_NOVAR},\t// VOC_MECHBOSS1\t\t\tMechanic: \"Sure Thing, Boss!\"\n\t{\"MYEEHAW1\",\t20,\tIN_NOVAR},\t// VOC_MECHYEEHAW1\t\tMechanic: \"Yee Haw!\"\n\t{\"MHOTDIG1\",\t20,\tIN_NOVAR},\t// VOC_MECHHOTDIG1\t\tMechanic: \"Hot Diggity Dog!\"\n\t{\"MWRENCH1\",\t20,\tIN_NOVAR},\t// VOC_MECHWRENCH1\t\tMechanic: \"I'll get my wrench.\"\n\n\t{\"JBURN1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STBURN1\t\t\t\tShock Trooper: \"Burn baby burn!\"\n\t{\"JCHRGE1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STCHRGE1\t\t\tShock Trooper: \"Fully charged!\"\n\t{\"JCRISP1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STCRISP1\t\t\tShock Trooper: \"Extra Crispy!\"\n\t{\"JDANCE1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STDANCE1\t\t\tShock Trooper: \"Let's Dance!\"\n\t{\"JJUICE1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STJUICE1\t\t\tShock Trooper: \"Got juice?\"\n\t{\"JJUMP1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STJUMP1\t\t\t\tShock Trooper: \"Need a jump?\"\n\t{\"JLIGHT1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STLIGHT1\t\t\tShock Trooper: \"Lights out!\"\n\t{\"JPOWER1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STPOWER1\t\t\tShock Trooper: \"Power on!\"\n\t{\"JSHOCK1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STSHOCK1\t\t\tShock Trooper: \"Shocking!\"\n\t{\"JYES1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STYES1\t\t\t\tShock Trooper: \"Yesssss!\"\n\n\t{\"CHROTNK1\",\t20,\tIN_NOVAR},\t// VOC_CHRONOTANK1\t\tChrono tank teleport\n\t{\"FIXIT1\",\t\t20,\tIN_NOVAR},\t// VOC_MECH_FIXIT1\t\tMechanic fixes something\n\t{\"MADCHRG2\",\t20,\tIN_NOVAR},\t// VOC_MAD_CHARGE\t\t\tMAD tank charges up\n\t{\"MADEXPLO\",\t20,\tIN_NOVAR},\t// VOC_MAD_EXPLODE\t\tMAD tank explodes\n\t{\"SHKTROP1\",\t20,\tIN_NOVAR},\t// VOC_SHOCK_TROOP1\t\tShock Trooper fires\n\n#endif\n};\n\n\n/***********************************************************************************************\n * Voc_From_Name -- Fetch VocType from ASCII name specified.                                   *\n *                                                                                             *\n *    This will find the corresponding VocType from the ASCII string specified. It does this   *\n *    by finding a root filename that matches the string.                                      *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the ASCII string that will be converted into a VocType.        *\n *                                                                                             *\n * OUTPUT:  Returns with the VocType that matches the string specified. If no match could be   *\n *          found, then VOC_NONE is returned.                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nVocType Voc_From_Name(char const * name)\n{\n\tif (name == NULL) return(VOC_NONE);\n\n\tfor (VocType voc = VOC_FIRST; voc < VOC_COUNT; voc++) {\n\t\tif (stricmp(name, SoundEffectName[voc].Name) == 0) {\n\t\t\treturn(voc);\n\t\t}\n\t}\n\n\treturn(VOC_NONE);\n}\n\n\n/***********************************************************************************************\n * Voc_Name -- Fetches the name for the sound effect.                                          *\n *                                                                                             *\n *    This routine returns the descriptive name of the sound effect. Currently, this is just   *\n *    the root of the file name.                                                               *\n *                                                                                             *\n * INPUT:   voc   -- The VocType that the corresponding name is requested.                     *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the text string the represents the sound effect.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * Voc_Name(VocType voc)\n{\n\tif (voc == VOC_NONE) return(\"none\");\n\treturn(SoundEffectName[voc].Name);\n}\n\n\n/***********************************************************************************************\n * Sound_Effect -- Plays a sound effect in the tactical map.                                   *\n *                                                                                             *\n *    This routine is used when a sound effect occurs in the game world. It handles fading     *\n *    the sound according to distance.                                                         *\n *                                                                                             *\n * INPUT:   voc   -- The sound effect number to play.                                          *\n *                                                                                             *\n *          coord -- The world location that the sound originates from.                        *\n *                                                                                             *\n *          variation   -- This is the optional variation number to use when playing special   *\n *                         sound effects that have variations. For normal sound effects, this  *\n *                         parameter is ignored.                                               *\n *                                                                                             *\n *          house -- This specifies the optional house override value to use when playing      *\n *                   sound effects that have a variation. If not specified, then the current   *\n *                   player is examined for the house variation to use.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/12/1994 JLB : Created.                                                                 *\n *   01/05/1995 JLB : Reduces sound more dramatically when off screen.                         *\n *   09/15/1996 JLB : Revamped volume logic.                                                   *\n *   11/01/1996 JLB : House override control.                                                  *\n *=============================================================================================*/\nvoid Sound_Effect(VocType voc, COORDINATE coord, int variation, HousesType house)\n{\n\tCELL cell_pos = 0;\n\tint pan_value;\n\n\tif (Debug_Quiet || Options.Volume == 0 || voc == VOC_NONE || !SoundOn || SampleType == SAMPLE_NONE) {\n\t\treturn;\n\t}\n\tif (coord) {\n\t\tcell_pos = Coord_Cell(coord);\n\t}\n\n\tfixed volume = 1;\n\tpan_value = 0;\n\tif (coord && !Map.In_View(cell_pos)) {\n\t\tint distance = Distance(coord, Map.TacticalCoord) / CELL_LEPTON_W;\n\t\tfixed dfixed = fixed(distance, 128+64);\n\t\tdfixed.Sub_Saturate(1);\n\t\tvolume = fixed(1) - dfixed;\n\n\t\tpan_value  = Cell_X(cell_pos);\n\t\tpan_value -= Coord_XCell(Map.TacticalCoord) + (Lepton_To_Cell(Map.TacLeptonWidth) / 2);\n\t\tif (ABS(pan_value) > Lepton_To_Cell(Map.TacLeptonWidth / 2)) {\n\t\t\tpan_value *= 0x8000;\n\t\t\tpan_value /= (MAP_CELL_W >> 2);\n\t\t\tpan_value = Bound(pan_value, -0x7FFF, 0x7FFF);\n\t\t} else {\n\t\t\tpan_value  = 0;\n\t\t}\n\t}\n\n\tSound_Effect(voc, volume, variation, pan_value, house);\n}\n\n\n/***********************************************************************************************\n * Sound_Effect -- General purpose sound player.                                               *\n *                                                                                             *\n *    This is used for general purpose sound effects. These are sounds that occur outside      *\n *    of the game world. They do not have a corresponding game world location as their source. *\n *                                                                                             *\n * INPUT:   voc      -- The sound effect number to play.                                       *\n *                                                                                             *\n *          volume   -- The volume to assign to this sound effect.                             *\n *                                                                                             *\n *          variation   -- This is the optional variation number to use when playing special   *\n *                         sound effects that have variations. For normal sound effects, this  *\n *                         parameter is ignored.                                               *\n *                                                                                             *\n *          house -- This specifies the optional house override value to use when playing      *\n *                   sound effects that have a variation. If not specified, then the current   *\n *                   player is examined for the house variation to use.                        *\n *                                                                                             *\n * OUTPUT:  Returns with the sound handle (-1 if no sound was played).                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/12/1994 JLB : Created.                                                                 *\n *   11/12/1994 JLB : Handles cache logic.                                                     *\n *   05/04/1995 JLB : Variation adjustments.                                                   *\n *   11/01/1996 JLB : House override control.                                                  *\n *=============================================================================================*/\nint Sound_Effect(VocType voc, fixed volume, int variation, signed short pan_value, HousesType house)\n{\n\tchar name[_MAX_FNAME+_MAX_EXT];\t\t\t\t// Working filename of sound effect.\n\n\tif (Debug_Quiet || Options.Volume == 0 || voc == VOC_NONE || !SoundOn || SampleType == SAMPLE_NONE) {\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tAlter the volume according to the game volume setting.\n\t*/\n\tvolume = volume * Options.Volume;\n\n\t/*\n\t**\tFetch a pointer to the sound effect data. Modify the sound as appropriate and desired.\n\t*/\n\tchar const * ext = \".AUD\";\n\tif (SoundEffectName[voc].Where == IN_VAR) {\n\n\t\t/*\n\t\t**\tIf there is no forced house, then use the current player\n\t\t**\tact like house.\n\t\t*/\n\t\tif (house == HOUSE_NONE) {\n\t\t\thouse = PlayerPtr->ActLike;\n\t\t}\n\n\t\t/*\n\t\t**\tChange the extension based on the variation and house accent requested.\n\t\t*/\n\t\tif (((1 << house) & HOUSEF_ALLIES) != 0) {\n\n\t\t\t/*\n\t\t\t**\tFor infantry, use a variation on the response. For vehicles, always\n\t\t\t**\tuse the vehicle response table.\n\t\t\t*/\n\t\t\tif (variation < 0) {\n\t\t\t\tif (ABS(variation) % 2) {\n\t\t\t\t\text = \".V00\";\n\t\t\t\t} else {\n\t\t\t\t\text = \".V02\";\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (variation % 2) {\n\t\t\t\t\text = \".V01\";\n\t\t\t\t} else {\n\t\t\t\t\text = \".V03\";\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (variation < 0) {\n\t\t\t\tif (ABS(variation) % 2) {\n\t\t\t\t\text = \".R00\";\n\t\t\t\t} else {\n\t\t\t\t\text = \".R02\";\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (variation % 2) {\n\t\t\t\t\text = \".R01\";\n\t\t\t\t} else {\n\t\t\t\t\text = \".R03\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t_makepath(name, NULL, NULL, SoundEffectName[voc].Name, ext);\n\tvoid const * ptr = MFCD::Retrieve(name);\n\n\t/*\n\t**\tIf the sound data pointer is not null, then presume that it is valid.\n\t*/\n\tif (ptr != NULL) {\n\t\tvolume.Sub_Saturate(1);\n\t\treturn(Play_Sample(ptr, SoundEffectName[voc].Priority * volume, volume*256, pan_value));\n\t}\n\treturn(-1);\n}\n\n\n/*\n**\tThis elaborates all the EVA speech voices.\n*/\nstatic char const * Speech[VOX_COUNT] =  {\n\t\"MISNWON1\",\t\t//\tVOX_ACCOMPLISHED\t\t\t\t\tmission accomplished\n\t\"MISNLST1\",\t\t//\tVOX_FAIL\t\t\t\t\t\t\t\tyour mission has failed\n\t\"PROGRES1\",\t\t//\tVOX_NO_FACTORY\t\t\t\t\t\tunable to comply, building in progress\n\t\"CONSCMP1\",\t\t//\tVOX_CONSTRUCTION\t\t\t\t\tconstruction complete\n\t\"UNITRDY1\",\t\t//\tVOX_UNIT_READY\t\t\t\t\t\tunit ready\n\t\"NEWOPT1\",\t\t//\tVOX_NEW_CONSTRUCT\t\t\t\t\tnew construction options\n\t\"NODEPLY1\",\t\t//\tVOX_DEPLOY\t\t\t\t\t\t\tcannot deploy here\n\t\"STRCKIL1\",\t\t//\tVOX_STRUCTURE_DESTROYED,\t\tstructure destroyed\n\t\"NOPOWR1\",\t\t//\tVOX_INSUFFICIENT_POWER,\t\t\tinsufficient power\n\t\"NOFUNDS1\",\t\t//\tVOX_NO_CASH\t\t\t\t\t\t\tinsufficient funds\n\t\"BCT1\",\t\t\t//\tVOX_CONTROL_EXIT\t\t\t\t\tbattle control terminated\n\t\"REINFOR1\",\t\t//\tVOX_REINFORCEMENTS\t\t\t\treinforcements have arrived\n\t\"CANCLD1\",\t\t//\tVOX_CANCELED\t\t\t\t\t\tcanceled\n\t\"ABLDGIN1\",\t\t//\tVOX_BUILDING\t\t\t\t\t\tbuilding\n\t\"LOPOWER1\",\t\t//\tVOX_LOW_POWER\t\t\t\t\t\tlow power\n\t\"NOFUNDS1\",\t\t//\tVOX_NEED_MO_MONEY\t\t\t\t\tinsufficent funds\n\t\"BASEATK1\",\t\t//\tVOX_BASE_UNDER_ATTACK\t\t\tour base is under attack\n\t\"NOBUILD1\",\t\t//\tVOX_UNABLE_TO_BUILD\t\t\t\tunable to build more\n\t\"PRIBLDG1\",\t\t//\tVOX_PRIMARY_SELECTED\t\t\t\tprimary building selected\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n#ifdef ENGLISH\n\t\"TANK01\",\t\t// VOX_MADTANK_DEPLOYED\t\t\t\tM.A.D. Tank Deployed\n#else\n\t\"none\",\n#endif\n#else\n\t\"none\",\n#endif\n\t\"none\",\t\t\t//\tVOX_SOVIET_CAPTURED\t\t\t\tAllied building captured\n\t\"UNITLST1\",\t\t// VOX_UNIT_LOST\t\t\t\t\t\tunit lost\n\t\"SLCTTGT1\",\t\t// VOX_SELECT_TARGET\t\t\t\t\tselect target\n\t\"ENMYAPP1\",\t\t//\tVOX_PREPARE\t\t\t\t\t\t\tenemy approaching\n\t\"SILOND1\",\t\t//\tVOX_NEED_MO_CAPACITY\t\t\t\tsilos needed\n\t\"ONHOLD1\",\t\t//\tVOX_SUSPENDED\t\t\t\t\t\ton hold\n\t\"REPAIR1\",\t\t//\tVOX_REPAIRING\t\t\t\t\t\trepairing\n\t\"none\",\n\t\"none\",\n\t\"AUNITL1\",\t\t//\tVOX_AIRCRAFT_LOST\t\t\t\t\tairborne unit lost\n\t\"none\",\n\t\"AAPPRO1\",\t\t//\tVOX_ALLIED_FORCES_APPROACHING\tallied forces approaching\n\t\"AARRIVE1\",\t\t// VOX_ALLIED_APPROACHING\t\t\tallied reinforcements have arrived\n\t\"none\",\n\t\"none\",\n\t\"BLDGINF1\",\t\t// VOX_BUILDING_INFILTRATED\t\tbuilding infiltrated\n\t\"CHROCHR1\",\t\t// VOX_CHRONO_CHARGING\t\t\t\tchronosphere charging\n\t\"CHRORDY1\",\t\t// VOX_CHRONO_READY\t\t\t\t\tchronosphere ready\n\t\"CHROYES1\",\t\t// VOX_CHRONO_TEST\t\t\t\t\tchronosphere test successful\n\t\"CMDCNTR1\",\t\t//\tVOX_HQ_UNDER_ATTACK\t\t\t\tcommand center under attack\n\t\"CNTLDED1\",\t\t//\tVOX_CENTER_DEACTIVATED\t\t\tcontrol center deactivated\n\t\"CONVYAP1\",\t\t//\tVOX_CONVOY_APPROACHING\t\t\tconvoy approaching\n\t\"CONVLST1\",\t\t// VOX_CONVOY_UNIT_LOST\t\t\t\tconvoy unit lost\n\t\"XPLOPLC1\",\t\t//\tVOX_EXPLOSIVE_PLACED\t\t\t\texplosive charge placed\n\t\"CREDIT1\",\t\t// VOX_MONEY_STOLEN\t\t\t\t\tcredits stolen\n\t\"NAVYLST1\",\t\t// VOX_SHIP_LOST\t\t\t\t\t\tnaval unit lost\n\t\"SATLNCH1\",\t\t//\tVOX_SATALITE_LAUNCHED\t\t\tsatalite launched\n\t\"PULSE1\",\t\t//\tVOX_SONAR_AVAILABLE\t\t\t\tsonar pulse available\n\t\"none\",\n\t\"SOVFAPP1\",\t\t//\tVOX_SOVIET_FORCES_APPROACHING\tsoviet forces approaching\n\t\"SOVREIN1\",\t\t// VOX_SOVIET_REINFROCEMENTS\t\tsoviet reinforcements have arrived\n\t\"TRAIN1\",\t\t//\tVOX_TRAINING\t\t\t\t\t\ttraining\n\t\"AREADY1\",\t\t//\tVOX_ABOMB_READY\n\t\"ALAUNCH1\",\t\t//\tVOX_ABOMB_LAUNCH\n\t\"AARRIVN1\",\t\t//\tVOX_ALLIES_N\n\t\"AARRIVS1\",\t\t//\tVOX_ALLIES_S\n\t\"AARIVE1\",\t\t//\tVOX_ALLIES_E\n\t\"AARRIVW1\",\t\t//\tVOX_ALLIES_W\n\t\"1OBJMET1\",\t\t//\tVOX_OBJECTIVE1\n\t\"2OBJMET1\",\t\t//\tVOX_OBJECTIVE2\n\t\"3OBJMET1\",\t\t//\tVOX_OBJECTIVE3\n\t\"IRONCHG1\",\t\t//\tVOX_IRON_CHARGING\n\t\"IRONRDY1\",\t\t//\tVOX_IRON_READY\n\t\"KOSYRES1\",\t\t//\tVOX_RESCUED\n\t\"OBJNMET1\",\t\t//\tVOX_OBJECTIVE_NOT\n\t\"FLAREN1\",\t\t//\tVOX_SIGNAL_N\n\t\"FLARES1\",\t\t//\tVOX_SIGNAL_S\n\t\"FLAREE1\",\t\t//\tVOX_SIGNAL_E\n\t\"FLAREW1\",\t\t//\tVOX_SIGNAL_W\n\t\"SPYPLN1\",\t\t//\tVOX_SPY_PLANE\n\t\"TANYAF1\",\t\t//\tVOX_FREED\n\t\"ARMORUP1\",\t\t//\tVOX_UPGRADE_ARMOR\n\t\"FIREPO1\",\t\t//\tVOX_UPGRADE_FIREPOWER\n\t\"UNITSPD1\",\t\t//\tVOX_UPGRADE_SPEED\n\t\"MTIMEIN1\",\t\t//\tVOX_MISSION_TIMER\n\t\"UNITFUL1\",\t\t//\tVOX_UNIT_FULL\n\t\"UNITREP1\",\t\t//\tVOX_UNIT_REPAIRED\n\t\"40MINR\",\t\t//\tVOX_TIME_40\n\t\"30MINR\",\t\t//\tVOX_TIME_30\n\t\"20MINR\",\t\t//\tVOX_TIME_20\n\t\"10MINR\",\t\t//\tVOX_TIME_10\n\t\"5MINR\",\t\t\t//\tVOX_TIME_5\n\t\"4MINR\",\t\t\t//\tVOX_TIME_4\n\t\"3MINR\",\t\t\t//\tVOX_TIME_3\n\t\"2MINR\",\t\t\t//\tVOX_TIME_2\n\t\"1MINR\",\t\t\t//\tVOX_TIME_1\n\t\"TIMERNO1\",\t\t//\tVOX_TIME_STOP\n\t\"UNITSLD1\",\t\t//\tVOX_UNIT_SOLD\n\t\"TIMERGO1\",\t\t//\tVOX_TIMER_STARTED\n\t\"TARGRES1\",\t\t//\tVOX_TARGET_RESCUED\n\t\"TARGFRE1\",\t\t//\tVOX_TARGET_FREED\n\t\"TANYAR1\",\t\t//\tVOX_TANYA_RESCUED\n\t\"STRUSLD1\",\t\t//\tVOX_STRUCTURE_SOLD\n\t\"SOVFORC1\",\t\t//\tVOX_SOVIET_FORCES_FALLEN\n\t\"SOVEMP1\",\t\t//\tVOX_SOVIET_SELECTED\n\t\"SOVEFAL1\",\t\t//\tVOX_SOVIET_EMPIRE_FALLEN\n\t\"OPTERM1\",\t\t//\tVOX_OPERATION_TERMINATED\n\t\"OBJRCH1\",\t\t//\tVOX_OBJECTIVE_REACHED\n\t\"OBJNRCH1\",\t\t//\tVOX_OBJECTIVE_NOT_REACHED\n\t\"OBJMET1\",\t\t//\tVOX_OBJECTIVE_MET\n\t\"MERCR1\",\t\t//\tVOX_MERCENARY_RESCUED\n\t\"MERCF1\",\t\t//\tVOX_MERCENARY_FREED\n\t\"KOSYFRE1\",\t\t//\tVOX_KOSOYGEN_FREED\n\t\"FLARE1\",\t\t//\tVOX_FLARE_DETECTED\n\t\"COMNDOR1\",\t\t//\tVOX_COMMANDO_RESCUED\n\t\"COMNDOF1\",\t\t//\tVOX_COMMANDO_FREED\n\t\"BLDGPRG1\",\t\t//\tVOX_BUILDING_IN_PROGRESS\n\t\"ATPREP1\",\t\t//\tVOX_ATOM_PREPPING\n\t\"ASELECT1\",\t\t//\tVOX_ALLIED_SELECTED\n\t\"APREP1\",\t\t//\tVOX_ABOMB_PREPPING\n\t\"ATLNCH1\",\t\t//\tVOX_ATOM_LAUNCHED\n\t\"AFALLEN1\",\t\t//\tVOX_ALLIED_FORCES_FALLEN\n\t\"AAVAIL1\",\t\t//\tVOX_ABOMB_AVAILABLE\n\t\"AARRIVE1\",\t\t//\tVOX_ALLIED_REINFORCEMENTS\n\t\"SAVE1\",\t\t\t//\tVOX_MISSION_SAVED\n\t\"LOAD1\"\t\t\t//\tVOX_MISSION_LOADED\n};\n\n\nstatic VoxType CurrentVoice = VOX_NONE;\n\n\n/***********************************************************************************************\n * Speech_Name -- Fetches the name for the voice specified.                                    *\n *                                                                                             *\n *    Use this routine to fetch the ASCII name of the speech id specified. Typical use of this *\n *    would be to build a displayable list of the speech types. The trigger system uses this   *\n *    so that a speech type can be selected.                                                   *\n *                                                                                             *\n * INPUT:   speech   -- The speech type id to convert to ASCII string.                         *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the speech ASCII representation of the speech id type.   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * Speech_Name(VoxType speech)\n{\n\tif (speech == VOX_NONE) return(\"none\");\n\treturn(Speech[speech]);\n}\n\n\n/***********************************************************************************************\n * Speak -- Computer speaks to the player.                                                     *\n *                                                                                             *\n *    This routine is used to have the game computer (EVA) speak to the player.                *\n *                                                                                             *\n * INPUT:   voice -- The voice number to speak (see defines.h).                                *\n *                                                                                             *\n * OUTPUT:  Returns with the handle of the playing speech (-1 if no voice started).            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Speak(VoxType voice)\n{\n\tif (!Debug_Quiet && Options.Volume != 0 && SampleType != 0 && voice != VOX_NONE && voice != SpeakQueue && voice != CurrentVoice && SpeakQueue == VOX_NONE) {\n\t\tSpeakQueue = voice;\n\t\tSpeak_AI();\n\t}\n}\n\n\n/***********************************************************************************************\n * Speak_AI -- Handles starting the EVA voices.                                                *\n *                                                                                             *\n *    This starts the EVA voice talking as well. If there is any speech request in the queue,  *\n *    it will be started when the current voice is finished. Call this routine as often as     *\n *    possible (once per game tick is sufficient).                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *   10/11/1996 JLB : Handles multiple speech buffers.                                         *\n *=============================================================================================*/\nvoid Speak_AI(void)\n{\n\tstatic int _index = 0;\n\tif (Debug_Quiet || SampleType == 0) return;\n\n\tif (!Is_Sample_Playing(SpeechBuffer[_index])) {\n\t\tCurrentVoice = VOX_NONE;\n\t\tif (SpeakQueue != VOX_NONE) {\n\n\t\t\t/*\n\t\t\t**\tTry to find a previously loaded copy of the EVA speech in one of the\n\t\t\t**\tspeech buffers.\n\t\t\t*/\n\t\t\tvoid const * speech = NULL;\n\t\t\tfor (int index = 0; index < ARRAY_SIZE(SpeechRecord); index++) {\n\t\t\t\tif (SpeechRecord[index] == SpeakQueue) break;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf a previous copy could not be located, then load the requested\n\t\t\t**\tvoice into the oldest buffer available.\n\t\t\t*/\n\t\t\tif (speech == NULL) {\n\t\t\t\t_index = (_index + 1) % ARRAY_SIZE(SpeechRecord);\n\n\t\t\t\tchar name[_MAX_FNAME+_MAX_EXT];\n\n\t\t\t\t_makepath(name, NULL, NULL, Speech[SpeakQueue], \".AUD\");\n\t\t\t\tCCFileClass file(name);\n\t\t\t\tif (file.Is_Available() && file.Read(SpeechBuffer[_index], SPEECH_BUFFER_SIZE)) {\n\t\t\t\t\tspeech = SpeechBuffer[_index];\n\t\t\t\t\tSpeechRecord[_index] = SpeakQueue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSince the speech file was loaded, play it.\n\t\t\t*/\n\t\t\tif (speech != NULL) {\n\t\t\t\tPlay_Sample(speech, 254, Options.Volume * 256);\n\t\t\t\tCurrentVoice = SpeakQueue;\n\t\t\t}\n\n\t\t\tSpeakQueue = VOX_NONE;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Stop_Speaking -- Forces the EVA voice to stop talking.                                      *\n *                                                                                             *\n *    Use this routine to immediately stop the EVA voice from speaking. It also clears out     *\n *    the pending voice queue.                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Stop_Speaking(void)\n{\n\tSpeakQueue = VOX_NONE;\n\tStop_Sample_Playing(SpeechBuffer);\n}\n\n\n/***********************************************************************************************\n * Is_Speaking -- Checks to see if the eva voice is still playing.                             *\n *                                                                                             *\n *    Call this routine when the EVA voice being played needs to be checked. A typical use     *\n *    of this would be when some action needs to be delayed until the voice has finished --    *\n *    say the end of the game.                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the EVA voice still playing?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/12/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool Is_Speaking(void)\n{\n\tSpeak_AI();\n\tif (!Debug_Quiet && SampleType != 0 && (SpeakQueue != VOX_NONE || Is_Sample_Playing(SpeechBuffer))) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "CODE/AUDIO.CPP.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\audio.cpv   4.78   03 Oct 1996 09:20:46   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : AUDIO.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : September 15, 1996 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Is_Speaking -- Checks to see if the eva voice is still playing.                           *\n *   Sound_Effect -- General purpose sound player.                                             *\n *   Sound_Effect -- Plays a sound effect in the tactical map.                                 *\n *   Speak -- Computer speaks to the player.                                                   *\n *   Speak_AI -- Handles starting the EVA voices.                                              *\n *   Speech_Name -- Fetches the name for the voice specified.                                  *\n *   Stop_Speaking -- Forces the EVA voice to stop talking.                                    *\n *   Voc_From_Name -- Fetch VocType from ASCII name specified.                                 *\n *   Voc_Name -- Fetches the name for the sound effect.                                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***************************************************************************\n**\tControls what special effects may occur on the sound effect.\n*/\ntypedef enum {\n\tIN_NOVAR,\t\t\t// No variation or alterations allowed.\n\tIN_VAR\t\t\t\t// Infantry variance response modification.\n} ContextType;\n\nstatic struct {\n\tchar const *\tName;\t\t// Digitized voice file name.\n\tint\t\t\t\tPriority;\t// Playback priority of this sample.\n\tContextType\t\tWhere;\t\t// In what game context does this sample exist.\n} SoundEffectName[VOC_COUNT] = {\n\n\t/*\n\t**\tCivilian voices (technicians too).\n\t*/\n\t{\"GIRLOKAY\",\t20,\tIN_NOVAR},\t\t//\tVOC_GIRL_OKAY\n\t{\"GIRLYEAH\",\t20,\tIN_NOVAR},\t\t//\tVOC_GIRL_YEAH\n\t{\"GUYOKAY1\",\t20,\tIN_NOVAR},\t\t//\tVOC_GUY_OKAY\n\t{\"GUYYEAH1\",\t20,\tIN_NOVAR},\t\t//\tVOC_GUY_YEAH\n\n\t{\"MINELAY1\",\t5,\t\tIN_VAR},\t\t\t// VOC_MINELAY1\n\n\t/*\n\t**\tInfantry and vehicle responses.\n\t*/\n\t{\"ACKNO\",\t\t20,\tIN_VAR},\t//\tVOC_ACKNOWL\t\t\t\"acknowledged\"\n\t{\"AFFIRM1\",\t\t20,\tIN_VAR},\t//\tVOC_AFFIRM\t\t\t\"affirmative\"\n\t{\"AWAIT1\",\t\t20,\tIN_VAR},\t//\tVOC_AWAIT1\t\t\t\"awaiting orders\"\n\t{\"EAFFIRM1\",\t20,\tIN_NOVAR},\t// VOC_ENG_AFFIRM\tEngineer: \"affirmative\"\n\t{\"EENGIN1\",\t\t20,\tIN_VAR},\t//\tVOC_ENG_ENG\t\t\tEngineer: \"engineering\"\n\t{\"NOPROB\",\t\t20,\tIN_VAR},\t// VOC_NO_PROB\t\t\t\"not a problem\"\n\t{\"READY\",\t\t20,\tIN_VAR},\t// VOC_READY\t\t\t\"ready and waiting\"\n\t{\"REPORT1\",\t\t20,\tIN_VAR},\t//\tVOC_REPORT\t\t\t\"reporting\"\n\t{\"RITAWAY\",\t\t20,\tIN_VAR},\t// VOC_RIGHT_AWAY\t\t\"right away sir\"\n\t{\"ROGER\",\t\t20,\tIN_VAR},\t// VOC_ROGER\t\t\t\"roger\"\n\t{\"UGOTIT\",\t\t20,\tIN_VAR},\t// VOC_UGOTIT\t\t\t\"you got it\"\n\t{\"VEHIC1\",\t\t20,\tIN_VAR},\t//\tVOC_VEHIC1\t\t\t\"vehicle reporting\"\n\t{\"YESSIR1\",\t\t20,\tIN_VAR},\t//\tVOC_YESSIR\t\t\t\"yes sir\"\n\n\t{\"DEDMAN1\", \t10,\tIN_NOVAR},\t// VOC_SCREAM1\t\t\tshort infantry scream\n\t{\"DEDMAN2\", \t10,\tIN_NOVAR},\t// VOC_SCREAM3\t\t\tshort infantry scream\n\t{\"DEDMAN3\", \t10,\tIN_NOVAR},\t// VOC_SCREAM4\t\t\tshort infantry scream\n\t{\"DEDMAN4\", \t10,\tIN_NOVAR},\t// VOC_SCREAM5\t\t\tshort infantry scream\n\t{\"DEDMAN5\", \t10,\tIN_NOVAR},\t// VOC_SCREAM6\t\t\tshort infantry scream\n\t{\"DEDMAN6\", \t10,\tIN_NOVAR},\t// VOC_SCREAM7\t\t\tshort infantry scream\n\t{\"DEDMAN7\", \t10,\tIN_NOVAR},\t// VOC_SCREAM10\t\tshort infantry scream\n\t{\"DEDMAN8\", \t10,\tIN_NOVAR},\t// VOC_SCREAM11\t\tshort infantry scream\n\t{\"DEDMAN10\", \t10,\tIN_NOVAR},\t// VOC_YELL1\t\t\tlong infantry scream\n\n\t{\"CHRONO2\",\t\t5,\t\tIN_NOVAR},\t//\tVOC_CHRONO\t\t\tChronosphere sound\n\t{\"CANNON1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CANNON1\t\t\tCannon sound (medium).\n\t{\"CANNON2\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CANNON2\t\t\tCannon sound (short).\n\t{\"IRONCUR1\",\t5,\t\tIN_NOVAR},\t// VOC_IRON1\n\t{\"EMOVOUT1\",\t20,\tIN_NOVAR},\t//\tVOC_ENG_MOVEOUT\tEngineer: \"movin' out\"\n\t{\"IRONCUR2\",\t5,\t\tIN_NOVAR},\t//\tVOC_IRON2\n\t{\"x\",\t\t1,\t\tIN_NOVAR},\n\t{\"x\",\t\t1,\t\tIN_NOVAR},\n\t{\"CHUTE1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CHUTE1\t\t\tWind swoosh sound.\n\t{\"DOGY1\",\t\t5,\t\tIN_NOVAR},\t//\tVOC_DOG_BARK\t\tDog bark.\n\t{\"DOGW5\",\t\t10,\tIN_NOVAR},\t//\tVOC_DOG_WHINE\t\tDog whine.\n\t{\"DOGG5P\",\t\t10,\tIN_NOVAR},\t//\tVOC_DOG_GROWL2\t\tStrong dog growl.\n\t{\"FIREBL3\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_FIRE_LAUNCH\tFireball launch sound.\n\t{\"FIRETRT1\",\t1,\t\tIN_NOVAR},\t//\tVOC_FIRE_EXPLODE\tFireball explode sound.\n\t{\"GRENADE1\",\t1,\t\tIN_NOVAR},\t//\tVOC_GRENADE_TOSS\tGrenade toss.\n\t{\"GUN11\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_GUN_5\t\t\t5 round gun burst (slow).\n\t{\"GUN13\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_GUN_7\t\t\t7 round gun burst (fast).\n\t{\"EYESSIR1\",\t20,\tIN_NOVAR},\t//\tVOC_ENG_YES,\t\tEngineer: \"yes sir\"\n\t{\"GUN27\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_GUN_RIFLE\t\tRifle shot.\n\t{\"HEAL2\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_HEAL\t\t\t\tHealing effect.\n\t{\"HYDROD1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_DOOR\t\t\t\tHyrdrolic door.\n\t{\"INVUL2\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_INVULNERABLE\tInvulnerability effect.\n\t{\"KABOOM1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_KABOOM1\t\t\tLong explosion (muffled).\n\t{\"KABOOM12\",\t1,\t\tIN_NOVAR},\t//\tVOC_KABOOM12\t\tVery long explosion (muffled).\n\t{\"KABOOM15\",\t1,\t\tIN_NOVAR},\t//\tVOC_KABOOM15\t\tVery long explosion (muffled).\n\t{\"x\",\t\t\t1,\t\tIN_NOVAR},\n\t{\"KABOOM22\",\t1,\t\tIN_NOVAR},\t//\tVOC_KABOOM22\t\tLong explosion (sharp).\n\t{\"x\",\t\t\t1,\t\tIN_NOVAR},\n\t{\"x\",\t\t\t1,\t\tIN_NOVAR},\n\t{\"MGUNINF1\",\t1,\t\tIN_NOVAR},\t//\tVOC_GUN_5F\t\t\t5 round gun burst (fast).\n\t{\"MISSILE1\",\t1,\t\tIN_NOVAR},\t//\tVOC_MISSILE_1\t\tMissile with high tech effect.\n\t{\"MISSILE6\",\t1,\t\tIN_NOVAR},\t//\tVOC_MISSILE_2\t\tLong missile launch.\n\t{\"MISSILE7\",\t1,\t\tIN_NOVAR},\t//\tVOC_MISSILE_3\t\tShort missile launch.\n\t{\"x\",\t1,\t\tIN_NOVAR},\n\t{\"PILLBOX1\",\t1,\t\tIN_NOVAR},\t//\tVOC_GUN_5R\t\t\t5 round gun burst (rattles).\n\t{\"RABEEP1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_BEEP\t\t\t\tGeneric beep sound.\n\t{\"RAMENU1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CLICK\t\t\tGeneric click sound.\n\t{\"SILENCER\",\t1,\t\tIN_NOVAR},\t//\tVOC_SILENCER\t\tSilencer.\n\t{\"TANK5\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CANNON6\t\t\tLong muffled cannon shot.\n\t{\"TANK6\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CANNON7\t\t\tSharp mechanical cannon fire.\n\t{\"TORPEDO1\",\t1,\t\tIN_NOVAR},\t//\tVOC_TORPEDO\t\t\tTorpedo launch.\n\t{\"TURRET1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CANNON8\t\t\tSharp cannon fire.\n\t{\"TSLACHG2\",\t10,\tIN_NOVAR},\t//\tVOC_TESLA_POWER_UP\tHum charge up.\n\t{\"TESLA1\",\t\t10,\tIN_NOVAR},\t//\tVOC_TESLA_ZAP\t\tTesla zap effect.\n\t{\"SQUISHY2\",\t10,\tIN_NOVAR},\t//\tVOC_SQUISH\t\t\tSquish effect.\n\t{\"SCOLDY1\",\t\t10,\tIN_NOVAR},\t//\tVOC_SCOLD\t\t\tScold bleep.\n\t{\"RADARON2\",\t20,\tIN_NOVAR},\t//\tVOC_RADAR_ON\t\tPowering up electronics.\n\t{\"RADARDN1\",\t10,\tIN_NOVAR},\t//\tVOC_RADAR_OFF\t\tB movie power down effect.\n\t{\"PLACBLDG\",\t10,\tIN_NOVAR},\t//\tVOC_PLACE_BUILDING_DOWN\tBuilding slam down sound.\n\t{\"KABOOM30\",\t1,\t\tIN_NOVAR},\t//\tVOC_KABOOM30\t\tShort explosion (HE).\n\t{\"KABOOM25\",\t10,\tIN_NOVAR},\t//\tVOC_KABOOM25\t\tShort growling explosion.\n\t{\"x\",\t\t\t10,\tIN_NOVAR},\n\t{\"DOGW7\",\t\t10,\tIN_NOVAR},\t//\tVOC_DOG_HURT\t\tDog whine (loud).\n\t{\"DOGW3PX\",\t\t10,\tIN_NOVAR},\t//\tVOC_DOG_YES\t\t\tDog 'yes sir'.\n\t{\"CRMBLE2\",\t\t10,\tIN_NOVAR},\t//\tVOC_CRUMBLE\t\t\tBuilding crumble.\n\t{\"CASHUP1\",\t\t10,\tIN_NOVAR},\t//\tVOC_MONEY_UP\t\tRising money tick.\n\t{\"CASHDN1\",\t\t10,\tIN_NOVAR},\t//\tVOC_MONEY_DOWN\t\tFalling money tick.\n\t{\"BUILD5\",\t\t10,\tIN_NOVAR},\t//\tVOC_CONSTRUCTION\tBuilding construction sound.\n\t{\"BLEEP9\",\t\t10,\tIN_NOVAR},\t//\tVOC_GAME_CLOSED\tLong bleep.\n\t{\"BLEEP6\",\t\t10,\tIN_NOVAR},\t//\tVOC_INCOMING_MESSAGE\tSoft happy warble.\n\t{\"BLEEP5\",\t\t10,\tIN_NOVAR},\t//\tVOC_SYS_ERROR\t\tSharp soft warble.\n\t{\"BLEEP17\",\t\t10,\tIN_NOVAR},\t//\tVOC_OPTIONS_CHANGED\tMid range soft warble.\n\t{\"BLEEP13\",\t\t10,\tIN_NOVAR},\t//\tVOC_GAME_FORMING\tLong warble.\n\t{\"BLEEP12\",\t\t10,\tIN_NOVAR},\t//\tVOC_PLAYER_LEFT\tChirp sequence.\n\t{\"BLEEP11\",\t\t10,\tIN_NOVAR},\t//\tVOC_PLAYER_JOINED\tReverse chirp sequence.\n\t{\"H2OBOMB2\",\t10,\tIN_NOVAR},\t//\tVOC_DEPTH_CHARGE\tDistant explosion sound.\n\t{\"CASHTURN\",\t10,\tIN_NOVAR},\t//\tVOC_CASHTURN\t\tAirbrake.\n\t{\"TUFFGUY1\",\t20,\tIN_NOVAR},\t//\tVOC_TANYA_CHEW\t\t\tTanya: \"Chew on this\"\n\t{\"ROKROLL1\",\t20,\tIN_NOVAR},\t//\tVOC_TANYA_ROCK\t\t\tTanya: \"Let's rock\"\n\t{\"LAUGH1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_LAUGH\t\tTanya: \"ha ha ha\"\n\t{\"CMON1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_SHAKE\t\tTanya: \"Shake it baby\"\n\t{\"BOMBIT1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_CHING\t\tTanya: \"Cha Ching\"\n\t{\"GOTIT1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_GOT\t\t\tTanya: \"That's all you got\"\n\t{\"KEEPEM1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_KISS\t\t\tTanya: \"Kiss it bye bye\"\n\t{\"ONIT1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_THERE\t\tTanya: \"I'm there\"\n\t{\"LEFTY1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_GIVE\t\t\tTanya: \"Give it to me\"\n\t{\"YEAH1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_YEA\t\t\tTanya: \"Yea?\"\n\t{\"YES1\",\t\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_YES\t\t\tTanya: \"Yes sir?\"\n\t{\"YO1\",\t\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_WHATS\t\tTanya: \"What's up.\"\n\t{\"WALLKIL2\",\t5,\t\tIN_NOVAR},\t//\tVOC_WALLKILL2\t\t\tCrushing wall sound.\n\t{\"x\",\t\t\t10,\tIN_NOVAR},\n\t{\"GUN5\",\t\t\t5,\t\tIN_NOVAR},\t//\tVOC_TRIPLE_SHOT\t\tThree quick shots in succession.\n\t{\"SUBSHOW1\",\t5,\t\tIN_NOVAR},\t//\tVOC_SUBSHOW\t\t\t\tSubmarine surface sound.\n\t{\"EINAH1\",\t\t20,\tIN_NOVAR},\t//\tVOC_E_AH,\t\t\t\tEinstien \"ah\"\n\t{\"EINOK1\",\t\t20,\tIN_NOVAR},\t//\tVOC_E_OK,\t\t\t\tEinstien \"ok\"\n\t{\"EINYES1\",\t\t20,\tIN_NOVAR},\t//\tVOC_E_YES,\t\t\t\tEinstien \"yes\"\n\t{\"MINE1\",\t\t10,\tIN_NOVAR},\t//\tVOC_TRIP_MINE\t\t\tmine explosion sound\n\n\t{\"SCOMND1\",\t\t20,\tIN_NOVAR},\t//\tVOC_SPY_COMMANDER\t\tSpy: \"commander?\"\n\t{\"SYESSIR1\",\t20,\tIN_NOVAR},\t//\tVOC_SPY_YESSIR\t\t\tSpy: \"yes sir\"\n\t{\"SINDEED1\",\t20,\tIN_NOVAR},\t//\tVOC_SPY_INDEED\t\t\tSpy: \"indeed\"\n\t{\"SONWAY1\",\t\t20,\tIN_NOVAR},\t//\tVOC_SPY_ONWAY\t\t\tSpy: \"on my way\"\n\t{\"SKING1\",\t\t20,\tIN_NOVAR},\t//\tVOC_SPY_KING\t\t\tSpy: \"for king and country\"\n\t{\"MRESPON1\",\t20,\tIN_NOVAR},\t//\tVOC_MED_REPORTING\t\tMedic: \"reporting\"\n\t{\"MYESSIR1\",\t20,\tIN_NOVAR},\t//\tVOC_MED_YESSIR\t\t\tMedic: \"yes sir\"\n\t{\"MAFFIRM1\",\t20,\tIN_NOVAR},\t//\tVOC_MED_AFFIRM\t\t\tMedic: \"affirmative\"\n\t{\"MMOVOUT1\",\t20,\tIN_NOVAR},\t//\tVOC_MED_MOVEOUT\t\tMedic: \"movin' out\"\n\t{\"BEEPSLCT\",\t10,\tIN_NOVAR},\t//\tVOC_BEEP_SELECT\t\tmap selection beep\n\n\t{\"SYEAH1\",\t\t20,\tIN_NOVAR},\t//\tVOC_THIEF_YEA\t\t\tThief: \"yea?\"\n\t{\"x\",\t\t20,\tIN_NOVAR},\n\t{\"x\",\t\t20,\tIN_NOVAR},\n\t{\"SMOUT1\",\t\t20,\tIN_NOVAR},\t//\tVOC_THIEF_MOVEOUT\t\tThief: \"movin' out\"\n\t{\"SOKAY1\",\t\t20,\tIN_NOVAR},\t//\tVOC_THIEF_OKAY\t\t\tThief: \"ok\"\n\t{\"x\",\t\t20,\tIN_NOVAR},\n\t{\"SWHAT1\",\t\t20,\tIN_NOVAR},\t//\tVOC_THIEF_WHAT\t\t\tThief: \"what\"\n\t{\"SAFFIRM1\",\t20,\tIN_NOVAR},\t//\tVOC_THIEF_AFFIRM\t\tThief: \"affirmative\"\n};\n\n\n/***********************************************************************************************\n * Voc_From_Name -- Fetch VocType from ASCII name specified.                                   *\n *                                                                                             *\n *    This will find the corresponding VocType from the ASCII string specified. It does this   *\n *    by finding a root filename that matches the string.                                      *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the ASCII string that will be converted into a VocType.        *\n *                                                                                             *\n * OUTPUT:  Returns with the VocType that matches the string specified. If no match could be   *\n *          found, then VOC_NONE is returned.                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nVocType Voc_From_Name(char const * name)\n{\n #ifdef 0\n\tif (name == NULL) return(VOC_NONE);\n\n\tfor (VocType voc = VOC_FIRST; voc < VOC_COUNT; voc++) {\n\t\tif (stricmp(name, SoundEffectName[voc].Name) == 0) {\n\t\t\treturn(voc);\n\t\t}\n\t}\n\n#endif\n\treturn(VOC_NONE);\n\n}\n\n\n/***********************************************************************************************\n * Voc_Name -- Fetches the name for the sound effect.                                          *\n *                                                                                             *\n *    This routine returns the descriptive name of the sound effect. Currently, this is just   *\n *    the root of the file name.                                                               *\n *                                                                                             *\n * INPUT:   voc   -- The VocType that the corresponding name is requested.                     *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the text string the represents the sound effect.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * Voc_Name(VocType voc)\n{\n\tif (voc == VOC_NONE) return(\"none\");\n\treturn(SoundEffectName[voc].Name);\n}\n\n\n/***********************************************************************************************\n * Sound_Effect -- Plays a sound effect in the tactical map.                                   *\n *                                                                                             *\n *    This routine is used when a sound effect occurs in the game world. It handles fading     *\n *    the sound according to distance.                                                         *\n *                                                                                             *\n * INPUT:   voc   -- The sound effect number to play.                                          *\n *                                                                                             *\n *          coord -- The world location that the sound originates from.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/12/1994 JLB : Created.                                                                 *\n *   01/05/1995 JLB : Reduces sound more dramatically when off screen.                         *\n *   09/15/1996 JLB : Revamped volume logic.                                                   *\n *=============================================================================================*/\nvoid Sound_Effect(VocType voc, COORDINATE coord, int variation)\n{\n  #ifdef 0\n\tCELL cell_pos = 0;\n\tint pan_value;\n\n\tif (Debug_Quiet || Options.Volume == 0 || voc == VOC_NONE || !SoundOn || SampleType == SAMPLE_NONE) {\n\t\treturn;\n\t}\n\tif (coord) {\n\t\tcell_pos = Coord_Cell(coord);\n\t}\n\n\tfixed volume = 1;\n\tpan_value = 0;\n\tif (coord && !Map.In_View(cell_pos)) {\n\t\tint distance = Distance(coord, Map.TacticalCoord) / CELL_LEPTON_W;\n\t\tfixed dfixed = fixed(distance, 128+64);\n\t\tdfixed.Sub_Saturate(1);\n\t\tvolume = fixed(1) - dfixed;\n\n\t\tpan_value  = Cell_X(cell_pos);\n\t\tpan_value -= Coord_XCell(Map.TacticalCoord) + (Lepton_To_Cell(Map.TacLeptonWidth) / 2);\n\t\tif (ABS(pan_value) > Lepton_To_Cell(Map.TacLeptonWidth / 2)) {\n\t\t\tpan_value *= 0x8000;\n\t\t\tpan_value /= (MAP_CELL_W >> 2);\n\t\t\tpan_value = Bound(pan_value, -0x7FFF, 0x7FFF);\n\t\t} else {\n\t\t\tpan_value  = 0;\n\t\t}\n\t}\n\n\tSound_Effect(voc, volume, variation, pan_value);\n#endif\n}\n\n\n/***********************************************************************************************\n * Sound_Effect -- General purpose sound player.                                               *\n *                                                                                             *\n *    This is used for general purpose sound effects. These are sounds that occur outside      *\n *    of the game world. They do not have a corresponding game world location as their source. *\n *                                                                                             *\n * INPUT:   voc      -- The sound effect number to play.                                       *\n *                                                                                             *\n *          volume   -- The volume to assign to this sound effect.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the sound handle (-1 if no sound was played).                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/12/1994 JLB : Created.                                                                 *\n *   11/12/1994 JLB : Handles cache logic.                                                     *\n *   05/04/1995 JLB : Variation adjustments.                                                   *\n *=============================================================================================*/\nint Sound_Effect(VocType voc, fixed volume, int variation, signed short pan_value)\n{\n #ifdef 0\n\tchar name[_MAX_FNAME+_MAX_EXT];\t\t\t\t// Working filename of sound effect.\n\n\tif (Debug_Quiet || Options.Volume == 0 || voc == VOC_NONE || !SoundOn || SampleType == SAMPLE_NONE) {\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tAlter the volume according to the game volume setting.\n\t*/\n\tvolume = volume * Options.Volume;\n\n\t/*\n\t**\tFetch a pointer to the sound effect data. Modify the sound as appropriate and desired.\n\t*/\n\tchar const * ext = \".AUD\";\n\tif (SoundEffectName[voc].Where == IN_VAR) {\n\n\t\t/*\n\t\t**\tFor infantry, use a variation on the response. For vehicles, always\n\t\t**\tuse the vehicle response table.\n\t\t*/\n\t\tif (variation < 0) {\n\t\t\tif (ABS(variation) % 2) {\n\t\t\t\text = \".V00\";\n\t\t\t} else {\n\t\t\t\text = \".V02\";\n\t\t\t}\n\t\t} else {\n\t\t\tif (variation % 2) {\n\t\t\t\text = \".V01\";\n\t\t\t} else {\n\t\t\t\text = \".V03\";\n\t\t\t}\n\t\t}\n\t}\n\t_makepath(name, NULL, NULL, SoundEffectName[voc].Name, ext);\n\tvoid const * ptr = MFCD::Retrieve(name);\n\n\t/*\n\t**\tIf the sound data pointer is not null, then presume that it is valid.\n\t*/\n\tif (ptr != NULL) {\n\t\tvolume.Sub_Saturate(1);\n\t\treturn(Play_Sample(ptr, SoundEffectName[voc].Priority * volume, volume*256, pan_value));\n//\t} else {\n//\t\tMono_Printf(\"Cannot find '%s'.\\n\", name);\n\t}\n#endif\n\treturn(-1);\n}\n\n\n/*\n**\tThis elaborates all the EVA speech voices.\n*/\nstatic char const * Speech[VOX_COUNT] =  {\n\t\"MISNWON1\",\t\t//\tVOX_ACCOMPLISHED\t\t\t\t\tmission accomplished\n\t\"MISNLST1\",\t\t//\tVOX_FAIL\t\t\t\t\t\t\t\tyour mission has failed\n\t\"PROGRES1\",\t\t//\tVOX_NO_FACTORY\t\t\t\t\t\tunable to comply, building in progress\n\t\"CONSCMP1\",\t\t//\tVOX_CONSTRUCTION\t\t\t\t\tconstruction complete\n\t\"UNITRDY1\",\t\t//\tVOX_UNIT_READY\t\t\t\t\t\tunit ready\n\t\"NEWOPT1\",\t\t//\tVOX_NEW_CONSTRUCT\t\t\t\t\tnew construction options\n\t\"NODEPLY1\",\t\t//\tVOX_DEPLOY\t\t\t\t\t\t\tcannot deploy here\n\t\"STRCKIL1\",\t\t//\tVOX_STRUCTURE_DESTROYED,\t\tstructure destroyed\n\t\"NOPOWR1\",\t\t//\tVOX_INSUFFICIENT_POWER,\t\t\tinsufficient power\n\t\"NOFUNDS1\",\t\t//\tVOX_NO_CASH\t\t\t\t\t\t\tinsufficient funds\n\t\"BCT1\",\t\t\t//\tVOX_CONTROL_EXIT\t\t\t\t\tbattle control terminated\n\t\"REINFOR1\",\t\t//\tVOX_REINFORCEMENTS\t\t\t\treinforcements have arrived\n\t\"CANCLD1\",\t\t//\tVOX_CANCELED\t\t\t\t\t\tcanceled\n\t\"ABLDGIN1\",\t\t//\tVOX_BUILDING\t\t\t\t\t\tbuilding\n\t\"LOPOWER1\",\t\t//\tVOX_LOW_POWER\t\t\t\t\t\tlow power\n\t\"NOFUNDS1\",\t\t//\tVOX_NEED_MO_MONEY\t\t\t\t\tinsufficent funds\n\t\"BASEATK1\",\t\t//\tVOX_BASE_UNDER_ATTACK\t\t\tour base is under attack\n\t\"NOBUILD1\",\t\t//\tVOX_UNABLE_TO_BUILD\t\t\t\tunable to build more\n\t\"PRIBLDG1\",\t\t//\tVOX_PRIMARY_SELECTED\t\t\t\tprimary building selected\n\t\"none\",\n\t\"none\",\t\t\t//\tVOX_SOVIET_CAPTURED\t\t\t\tAllied building captured\n\t\"UNITLST1\",\t\t// VOX_UNIT_LOST\t\t\t\t\t\tunit lost\n\t\"SLCTTGT1\",\t\t// VOX_SELECT_TARGET\t\t\t\t\tselect target\n\t\"ENMYAPP1\",\t\t//\tVOX_PREPARE\t\t\t\t\t\t\tenemy approaching\n\t\"SILOND1\",\t\t//\tVOX_NEED_MO_CAPACITY\t\t\t\tsilos needed\n\t\"ONHOLD1\",\t\t//\tVOX_SUSPENDED\t\t\t\t\t\ton hold\n\t\"REPAIR1\",\t\t//\tVOX_REPAIRING\t\t\t\t\t\trepairing\n\t\"none\",\n\t\"none\",\n\t\"AUNITL1\",\t\t//\tVOX_AIRCRAFT_LOST\t\t\t\t\tairborne unit lost\n\t\"none\",\n\t\"AAPPRO1\",\t\t//\tVOX_ALLIED_FORCES_APPROACHING\tallied forces approaching\n\t\"AARRIVE1\",\t\t// VOX_ALLIED_APPROACHING\t\t\tallied reinforcements have arrived\n\t\"none\",\n\t\"none\",\n\t\"BLDGINF1\",\t\t// VOX_BUILDING_INFILTRATED\t\tbuilding infiltrated\n\t\"CHROCHR1\",\t\t// VOX_CHRONO_CHARGING\t\t\t\tchronosphere charging\n\t\"CHRORDY1\",\t\t// VOX_CHRONO_READY\t\t\t\t\tchronosphere ready\n\t\"CHROYES1\",\t\t// VOX_CHRONO_TEST\t\t\t\t\tchronosphere test successful\n\t\"CMDCNTR1\",\t\t//\tVOX_HQ_UNDER_ATTACK\t\t\t\tcommand center under attack\n\t\"CNTLDED1\",\t\t//\tVOX_CENTER_DEACTIVATED\t\t\tcontrol center deactivated\n\t\"CONVYAP1\",\t\t//\tVOX_CONVOY_APPROACHING\t\t\tconvoy approaching\n\t\"CONVLST1\",\t\t// VOX_CONVOY_UNIT_LOST\t\t\t\tconvoy unit lost\n\t\"XPLOPLC1\",\t\t//\tVOX_EXPLOSIVE_PLACED\t\t\t\texplosive charge placed\n\t\"CREDIT1\",\t\t// VOX_MONEY_STOLEN\t\t\t\t\tcredits stolen\n\t\"NAVYLST1\",\t\t// VOX_SHIP_LOST\t\t\t\t\t\tnaval unit lost\n\t\"SATLNCH1\",\t\t//\tVOX_SATALITE_LAUNCHED\t\t\tsatalite launched\n\t\"PULSE1\",\t\t//\tVOX_SONAR_AVAILABLE\t\t\t\tsonar pulse available\n\t\"none\",\n\t\"SOVFAPP1\",\t\t//\tVOX_SOVIET_FORCES_APPROACHING\tsoviet forces approaching\n\t\"SOVREIN1\",\t\t// VOX_SOVIET_REINFROCEMENTS\t\tsoviet reinforcements have arrived\n\t\"TRAIN1\",\t\t//\tVOX_TRAINING\t\t\t\t\t\ttraining\n\t\"AREADY1\",\t\t//\tVOX_ABOMB_READY\n\t\"ALAUNCH1\",\t\t//\tVOX_ABOMB_LAUNCH\n\t\"AARRIVN1\",\t\t//\tVOX_ALLIES_N\n\t\"AARRIVS1\",\t\t//\tVOX_ALLIES_S\n\t\"AARIVE1\",\t\t//\tVOX_ALLIES_E\n\t\"AARRIVW1\",\t\t//\tVOX_ALLIES_W\n\t\"1OBJMET1\",\t\t//\tVOX_OBJECTIVE1\n\t\"2OBJMET1\",\t\t//\tVOX_OBJECTIVE2\n\t\"3OBJMET1\",\t\t//\tVOX_OBJECTIVE3\n\t\"IRONCHG1\",\t\t//\tVOX_IRON_CHARGING\n\t\"IRONRDY1\",\t\t//\tVOX_IRON_READY\n\t\"KOSYRES1\",\t\t//\tVOX_RESCUED\n\t\"OBJNMET1\",\t\t//\tVOX_OBJECTIVE_NOT\n\t\"FLAREN1\",\t\t//\tVOX_SIGNAL_N\n\t\"FLARES1\",\t\t//\tVOX_SIGNAL_S\n\t\"FLAREE1\",\t\t//\tVOX_SIGNAL_E\n\t\"FLAREW1\",\t\t//\tVOX_SIGNAL_W\n\t\"SPYPLN1\",\t\t//\tVOX_SPY_PLANE\n\t\"TANYAF1\",\t\t//\tVOX_FREED\n\t\"ARMORUP1\",\t\t//\tVOX_UPGRADE_ARMOR\n\t\"FIREPO1\",\t\t//\tVOX_UPGRADE_FIREPOWER\n\t\"UNITSPD1\",\t\t//\tVOX_UPGRADE_SPEED\n\t\"MTIMEIN1\",\t\t//\tVOX_MISSION_TIMER\n\t\"UNITFUL1\",\t\t//\tVOX_UNIT_FULL\n\t\"UNITREP1\",\t\t//\tVOX_UNIT_REPAIRED\n\t\"40MINR\",\t\t//\tVOX_TIME_40\n\t\"30MINR\",\t\t//\tVOX_TIME_30\n\t\"20MINR\",\t\t//\tVOX_TIME_20\n\t\"10MINR\",\t\t//\tVOX_TIME_10\n\t\"5MINR\",\t\t\t//\tVOX_TIME_5\n\t\"4MINR\",\t\t\t//\tVOX_TIME_4\n\t\"3MINR\",\t\t\t//\tVOX_TIME_3\n\t\"2MINR\",\t\t\t//\tVOX_TIME_2\n\t\"1MINR\",\t\t\t//\tVOX_TIME_1\n\t\"TIMERNO1\",\t\t//\tVOX_TIME_STOP\n\t\"UNITSLD1\",\t\t//\tVOX_UNIT_SOLD\n\t\"TIMERGO1\",\t\t//\tVOX_TIMER_STARTED\n\t\"TARGRES1\",\t\t//\tVOX_TARGET_RESCUED\n\t\"TARGFRE1\",\t\t//\tVOX_TARGET_FREED\n\t\"TANYAR1\",\t\t//\tVOX_TANYA_RESCUED\n\t\"STRUSLD1\",\t\t//\tVOX_STRUCTURE_SOLD\n\t\"SOVFORC1\",\t\t//\tVOX_SOVIET_FORCES_FALLEN\n\t\"SOVEMP1\",\t\t//\tVOX_SOVIET_SELECTED\n\t\"SOVEFAL1\",\t\t//\tVOX_SOVIET_EMPIRE_FALLEN\n\t\"OPTERM1\",\t\t//\tVOX_OPERATION_TERMINATED\n\t\"OBJRCH1\",\t\t//\tVOX_OBJECTIVE_REACHED\n\t\"OBJNRCH1\",\t\t//\tVOX_OBJECTIVE_NOT_REACHED\n\t\"OBJMET1\",\t\t//\tVOX_OBJECTIVE_MET\n\t\"MERCR1\",\t\t//\tVOX_MERCENARY_RESCUED\n\t\"MERCF1\",\t\t//\tVOX_MERCENARY_FREED\n\t\"KOSYFRE1\",\t\t//\tVOX_KOSOYGEN_FREED\n\t\"FLARE1\",\t\t//\tVOX_FLARE_DETECTED\n\t\"COMNDOR1\",\t\t//\tVOX_COMMANDO_RESCUED\n\t\"COMNDOF1\",\t\t//\tVOX_COMMANDO_FREED\n\t\"BLDGPRG1\",\t\t//\tVOX_BUILDING_IN_PROGRESS\n\t\"ATPREP1\",\t\t//\tVOX_ATOM_PREPPING\n\t\"ASELECT1\",\t\t//\tVOX_ALLIED_SELECTED\n\t\"APREP1\",\t\t//\tVOX_ABOMB_PREPPING\n\t\"ATLNCH1\",\t\t//\tVOX_ATOM_LAUNCHED\n\t\"AFALLEN1\",\t\t//\tVOX_ALLIED_FORCES_FALLEN\n\t\"AAVAIL1\",\t\t//\tVOX_ABOMB_AVAILABLE\n\t\"AARRIVE1\",\t\t//\tVOX_ALLIED_REINFORCEMENTS\n\t\"SAVE1\",\t\t\t//\tVOX_MISSION_SAVED\n\t\"LOAD1\"\t\t\t//\tVOX_MISSION_LOADED\n};\n\n\nstatic VoxType CurrentVoice = VOX_NONE;\n\n\n/***********************************************************************************************\n * Speech_Name -- Fetches the name for the voice specified.                                    *\n *                                                                                             *\n *    Use this routine to fetch the ASCII name of the speech id specified. Typical use of this *\n *    would be to build a displayable list of the speech types. The trigger system uses this   *\n *    so that a speech type can be selected.                                                   *\n *                                                                                             *\n * INPUT:   speech   -- The speech type id to convert to ASCII string.                         *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the speech ASCII representation of the speech id type.   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * Speech_Name(VoxType speech)\n{\n\tif (speech == VOX_NONE) return(\"none\");\n\treturn(Speech[speech]);\n}\n\n\n/***********************************************************************************************\n * Speak -- Computer speaks to the player.                                                     *\n *                                                                                             *\n *    This routine is used to have the game computer (EVA) speak to the player.                *\n *                                                                                             *\n * INPUT:   voice -- The voice number to speak (see defines.h).                                *\n *                                                                                             *\n * OUTPUT:  Returns with the handle of the playing speech (-1 if no voice started).            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Speak(VoxType voice)\n{\n\tif (!Debug_Quiet && Options.Volume != 0 && SampleType != 0 && voice != VOX_NONE && voice != SpeakQueue && voice != CurrentVoice && SpeakQueue == VOX_NONE) {\n\t\tSpeakQueue = voice;\n\t\tSpeak_AI();\n\t}\n}\n\n\n/***********************************************************************************************\n * Speak_AI -- Handles starting the EVA voices.                                                *\n *                                                                                             *\n *    This starts the EVA voice talking as well. If there is any speech request in the queue,  *\n *    it will be started when the current voice is finished. Call this routine as often as     *\n *    possible (once per game tick is sufficient).                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Speak_AI(void)\n{\n\tstatic VoxType _last = VOX_NONE;\n\tif (Debug_Quiet || SampleType == 0) return;\n\n\tif (!Is_Sample_Playing(SpeechBuffer)) {\n\t\tCurrentVoice = VOX_NONE;\n\t\tif (SpeakQueue != VOX_NONE) {\n\t\t\tif (SpeakQueue != _last) {\n\t\t\t\tchar name[_MAX_FNAME+_MAX_EXT];\n\n\t\t\t\t_makepath(name, NULL, NULL, Speech[SpeakQueue], \".AUD\");\n\t\t\t\tCCFileClass file(name);\n\t\t\t\tif (file.Is_Available() && file.Read(SpeechBuffer, SPEECH_BUFFER_SIZE)) {\n\t\t\t\t\tPlay_Sample(SpeechBuffer, 254, Options.Volume * 256);\n\t\t\t\t\tCurrentVoice = SpeakQueue;\n\t\t\t\t}\n\t\t\t\t_last = SpeakQueue;\n\t\t\t} else {\n\t\t\t\tPlay_Sample(SpeechBuffer, 254, Options.Volume * 256);\n\t\t\t}\n\t\t\tSpeakQueue = VOX_NONE;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Stop_Speaking -- Forces the EVA voice to stop talking.                                      *\n *                                                                                             *\n *    Use this routine to immediately stop the EVA voice from speaking. It also clears out     *\n *    the pending voice queue.                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Stop_Speaking(void)\n{\n\tSpeakQueue = VOX_NONE;\n\tStop_Sample_Playing(SpeechBuffer);\n}\n\n\n/***********************************************************************************************\n * Is_Speaking -- Checks to see if the eva voice is still playing.                             *\n *                                                                                             *\n *    Call this routine when the EVA voice being played needs to be checked. A typical use     *\n *    of this would be when some action needs to be delayed until the voice has finished --    *\n *    say the end of the game.                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the EVA voice still playing?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/12/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool Is_Speaking(void)\n{\n\tSpeak_AI();\n\tif (!Debug_Quiet && SampleType != 0 && (SpeakQueue != VOX_NONE || Is_Sample_Playing(SpeechBuffer))) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "CODE/AUDIO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\audio.h_v   4.43   05 Jul 1996 17:58:10   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               *** \n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : AUDIO.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 21, 1994                                                *\n *                                                                                             *\n *                  Last Update : June 21, 1994   [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef AUDIO_H\n#define AUDIO_H\n\n#include\t\"memory.h\"\n\nclass AudioClass {\n\t\tchar const * Name;\t// Name of audio asset.\n\t\tvoid const * Data;\t// Loaded audio data.\n\t\tint Handle;\t\t\t\t// Handle of asset (as it is playing).\n\t\tMemoryClass *Mem;\t\t// Pointer to memory handler class.\n\t\tunsigned IsMIDI:1;\t// Is this a midi file?\n\n\tpublic:\n\t\tAudioClass(void);\n\t\tAudioClass(char const *name, MemoryClass &mem);\n\t\tvirtual ~AudioClass(void);\n\n\t\tbool Load(char const *name = 0);\n\t\tbool Free(void);\n\t\tbool Play(int volume = 0xFF);\n\t\tbool Stop(void);\n\t\tbool Pause(void);\n\t\tbool Resume(void);\n\t\tbool Set_Name(char const *name);\n\t\tbool Is_Playing(void) const;\n\t\tbool Is_Loaded(void) const;\n\t\tbool Is_MIDI(void) const;\n};\n\ninline AudioClass::AudioClass(void)\n{\n\tName = 0; \n\tData = 0; \n\tMem = 0;\n\tHandle = -1;\n};\n\ninline AudioClass::AudioClass(char const *name, MemoryClass &mem) \n{\n\tif (mem) {\n\t\tMem = &mem;\n\t} else {\n\t\tMem = &::Mem;\t\t// Uses global default memory handler.\n\t}\n\tName = strdup(name);\n\tData = 0;\n\tHandle = -1;\n};\n\ninline AudioClass::~AudioClass(void)\n{\n\tif (GameActive) {\n\t\tif (Name) free(Name);\n\t\tif (Data) Mem->Free(Data);\n\t\tName = 0;\n\t\tData = 0;\n\t\tHandle = -1;\n\t}\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/B64PIPE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/B64PIPE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : B64PIPE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Base64Pipe::Put -- Processes a block of data through the pipe.                            *\n *   Base64Pipe::Flush -- Flushes the final pending data through the pipe.                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"b64pipe.h\"\n#include\t\"base64.h\"\n#include\t<string.h>\n\n\n/***********************************************************************************************\n * Base64Pipe::Put -- Processes a block of data through the pipe.                              *\n *                                                                                             *\n *    This will take the data submitted and either Base64 encode or decode it (as specified    *\n *    in the pipe's constructor). The nature of Base64 encoding means that the data will       *\n *    grow 30% in size when encoding and decrease by a like amount when decoding.              *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the data to be translated.                                  *\n *                                                                                             *\n *          length   -- The number of bytes to translate.                                      *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes output at the far distant final end of     *\n *          the pipe chain.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Base64Pipe::Put(void const * source, int slen)\n{\n\tif (source == NULL || slen < 1) {\n\t\treturn(Pipe::Put(source, slen));\n\t}\n\n\tint total = 0;\n\n\tchar * from;\n\tint fromsize;\n\tchar * to;\n\tint tosize;\n\n\tif (Control == ENCODE) {\n\t\tfrom = PBuffer;\n\t\tfromsize = sizeof(PBuffer);\n\t\tto = CBuffer;\n\t\ttosize = sizeof(CBuffer);\n\t} else {\n\t\tfrom = CBuffer;\n\t\tfromsize = sizeof(CBuffer);\n\t\tto = PBuffer;\n\t\ttosize = sizeof(PBuffer);\n\t}\n\n\tif (Counter > 0) {\n\t\tint len = (slen < (fromsize-Counter)) ? slen : (fromsize-Counter);\n\t\tmemmove(&from[Counter], source, len);\n\t\tCounter += len;\n\t\tslen -= len;\n\t\tsource = ((char *)source) + len;\n\n\t\tif (Counter == fromsize) {\n\t\t\tint outcount;\n\t\t\tif (Control == ENCODE) {\n\t\t\t\toutcount = Base64_Encode(from, fromsize, to, tosize);\n\t\t\t} else {\n\t\t\t\toutcount = Base64_Decode(from, fromsize, to, tosize);\n\t\t\t}\n\t\t\ttotal += Pipe::Put(to, outcount);\n\t\t\tCounter = 0;\n\t\t}\n\t}\n\n\twhile (slen >= fromsize) {\n\t\tint outcount;\n\t\tif (Control == ENCODE) {\n\t\t\toutcount = Base64_Encode(source, fromsize, to, tosize);\n\t\t} else {\n\t\t\toutcount = Base64_Decode(source, fromsize, to, tosize);\n\t\t}\n\t\tsource = ((char *)source) + fromsize;\n\t\ttotal += Pipe::Put(to, outcount);\n\t\tslen -= fromsize;\n\t}\n\n\tif (slen > 0) {\n\t\tmemmove(from, source, slen);\n\t\tCounter = slen;\n\t}\n\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * Base64Pipe::Flush -- Flushes the final pending data through the pipe.                       *\n *                                                                                             *\n *    If there is any non-processed data accumulated in the holding buffer (quite likely when  *\n *    encoding), then it will be processed and flushed out the end of the pipe.                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes output at the far distant final end of the pipe   *\n *          chain.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Base64Pipe::Flush(void)\n{\n\tint len = 0;\n\n\tif (Counter) {\n\t\tif (Control == ENCODE) {\n\t\t\tint chars = Base64_Encode(PBuffer, Counter, CBuffer, sizeof(CBuffer));\n\t\t\tlen += Pipe::Put(CBuffer, chars);\n\t\t} else {\n\t\t\tint chars = Base64_Decode(CBuffer, Counter, PBuffer, sizeof(PBuffer));\n\t\t\tlen += Pipe::Put(PBuffer, chars);\n\t\t}\n\t\tCounter = 0;\n\t}\n\tlen += Pipe::Flush();\n\treturn(len);\n}\n\n\n\n"
  },
  {
    "path": "CODE/B64PIPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/B64PIPE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : B64PIPE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef B64PIPE_H\n#define B64PIPE_H\n\n#include\t\"pipe.h\"\n\n/*\n**\tThis class performs Base64 encoding/decoding to the data that is piped through. Note that\n**\tencoded data will grow in size by about 30%. The reverse occurs when decoding.\n*/\nclass Base64Pipe : public Pipe\n{\n\tpublic:\n\t\ttypedef enum CodeControl {\n\t\t\tENCODE,\n\t\t\tDECODE\n\t\t} CodeControl;\n\n\t\tBase64Pipe(CodeControl control) : Control(control), Counter(0) {}\n\n\t\tvirtual int Flush(void);\n\t\tvirtual int Put(void const * source, int slen);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tIndicates if this is for encoding or decoding of Base64 data.\n\t\t*/\n\t\tCodeControl Control;\n\n\t\t/*\n\t\t**\tThe counter of the number of accumulated bytes pending for processing.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tBuffer that holds the Base64 coded bytes. This will be the staging buffer if\n\t\t**\tthis is for a decoding process. Otherwise, it will be used as a scratch buffer.\n\t\t*/\n\t\tchar CBuffer[4];\n\n\t\t/*\n\t\t**\tBuffer that holds the plain bytes. This will be the staging buffer if this\n\t\t**\tis for an encoding process. Otherwise, it will be used as a scratch buffer.\n\t\t*/\n\t\tchar PBuffer[3];\n\n\t\t/*\n\t\t**\tExplicitly disable the copy constructor and the assignment operator.\n\t\t*/\n\t\tBase64Pipe(Base64Pipe & rvalue);\n\t\tBase64Pipe & operator = (Base64Pipe const & pipe);\n};\n\n#endif\n"
  },
  {
    "path": "CODE/B64STRAW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/B64STRAW.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : B64STRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Base64Straw::Get -- Fetch data and convert it to/from base 64 encoding.                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"b64straw.h\"\n#include\t\"base64.h\"\n#include\t<string.h>\n\n\n/***********************************************************************************************\n * Base64Straw::Get -- Fetch data and convert it to/from base 64 encoding.                     *\n *                                                                                             *\n *    This routine will fetch the number of bytes requested and perform any conversion as      *\n *    necessary upon the data. The nature of Base 64 encoding means that the data will         *\n *    increase in size by 30% when encoding and decrease in like manner when decoding.         *\n *                                                                                             *\n * INPUT:   source   -- The buffer to hold the processed data.                                 *\n *                                                                                             *\n *          length   -- The number of bytes requested.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes stored into the buffer. If the number is less     *\n *          than requested, then this indicates that the data stream has been exhausted.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Base64Straw::Get(void * source, int slen)\n{\n\tint total = 0;\n\n\tchar * from;\n\tint fromsize;\n\tchar * to;\n\tint tosize;\n\n\tif (Control == ENCODE) {\n\t\tfrom = PBuffer;\n\t\tfromsize = sizeof(PBuffer);\n\t\tto = CBuffer;\n\t\ttosize = sizeof(CBuffer);\n\t} else {\n\t\tfrom = CBuffer;\n\t\tfromsize = sizeof(CBuffer);\n\t\tto = PBuffer;\n\t\ttosize = sizeof(PBuffer);\n\t}\n\n\t/*\n\t**\tProcess the byte request in code blocks until there are either\n\t**\tno more source bytes available or the request has been fulfilled.\n\t*/\n\twhile (slen > 0) {\n\n\t\t/*\n\t\t**\tTransfer any processed bytes available to the request buffer.\n\t\t*/\n\t\tif (Counter > 0) {\n\t\t\tint len = (slen < Counter) ? slen : Counter;\n\t\t\tmemmove(source, &to[tosize-Counter], len);\n\t\t\tCounter -= len;\n\t\t\tslen -= len;\n\t\t\tsource = ((char *)source) + len;\n\t\t\ttotal += len;\n\t\t}\n\t\tif (slen == 0) break;\n\n\t\t/*\n\t\t**\tMore bytes are needed, so fetch and process another base 64 block.\n\t\t*/\n\t\tint incount = Straw::Get(from, fromsize);\n\t\tif (Control == ENCODE) {\n\t\t\tCounter = Base64_Encode(from, incount, to, tosize);\n\t\t} else {\n\t\t\tCounter = Base64_Decode(from, incount, to, tosize);\n\t\t}\n\t\tif (Counter == 0) break;\n\t}\n\n\treturn(total);\n}\n"
  },
  {
    "path": "CODE/B64STRAW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/B64STRAW.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : B64STRAW.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef B64STRAW_H\n#define B64STRAW_H\n\n#include\t\"straw.h\"\n\n/*\n**\tPerforms Base 64 encoding/decoding on the data that is drawn through the straw. Note that\n**\tencoding increases the data size by about 30%. The reverse occurs when decoding.\n*/\nclass Base64Straw : public Straw\n{\n\tpublic:\n\t\ttypedef enum CodeControl {\n\t\t\tENCODE,\n\t\t\tDECODE\n\t\t} CodeControl;\n\n\t\tBase64Straw(CodeControl control) : Control(control), Counter(0) {}\n\t\tvirtual int Get(void * source, int slen);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tIndicates if this is for encoding or decoding of Base64 data.\n\t\t*/\n\t\tCodeControl Control;\n\n\t\t/*\n\t\t**\tThe counter of the number of accumulated bytes pending for processing.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tBuffer that holds the Base64 coded bytes. This will be the staging buffer if\n\t\t**\tthis is for a decoding process. Otherwise, it will be used as a scratch buffer.\n\t\t*/\n\t\tchar CBuffer[4];\n\n\t\t/*\n\t\t**\tBuffer that holds the plain bytes. This will be the staging buffer if this\n\t\t**\tis for an encoding process. Otherwise, it will be used as a scratch buffer.\n\t\t*/\n\t\tchar PBuffer[3];\n\n\t\t/*\n\t\t**\tExplicitly disable the copy constructor and the assignment operator.\n\t\t*/\n\t\tBase64Straw(Base64Straw & rvalue);\n\t\tBase64Straw & operator = (Base64Straw const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/BAR.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BAR.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BAR.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 08/16/96                                                     *\n *                                                                                             *\n *                  Last Update : August 16, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ProgressBarClass::Is_Horizontal -- Determines if the bargraph is horizontal or not.       *\n *   ProgressBarClass::Outline -- Draw an outline around the bargraph if supposed to.          *\n *   ProgressBarClass::ProgressBarClass -- Constructor for the bargraph object.                *\n *   ProgressBarClass::Redraw -- Redraw the bargraph.                                          *\n *   ProgressBarClass::Set_Limit -- Set the logic tracking value.                              *\n *   ProgressBarClass::Update -- Update the value and redraw as necessary.                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"bar.h\"\n#include\t\"fixed.h\"\n\n\n/***********************************************************************************************\n * ProgressBarClass::ProgressBarClass -- Constructor for the bargraph object.                  *\n *                                                                                             *\n *    This is the constructor for the bargraph object. It establishes the dimensions and       *\n *    coordinate of the bargraph as well as the colors it will use when drawn.                 *\n *                                                                                             *\n * INPUT:   w,y      -- Pixel coordinate of the upper left corner of the bargraph.             *\n *                                                                                             *\n *          width,height   -- Dimensions of the bargraph.                                      *\n *                                                                                             *\n *          forecolor   -- The color to use for the filled portion of the bargraph.            *\n *                                                                                             *\n *          backcolor   -- The color to use for the non-filled portion of the bargraph.        *\n *                                                                                             *\n *          bordercolor -- Optional border color. If not zero, then the bargraph will be       *\n *                         outlined with this color.                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nProgressBarClass::ProgressBarClass(int x, int y, int width, int height, int forecolor, int backcolor, int bordercolor) :\n\tX(x),\n\tY(y),\n\tWidth(width),\n\tHeight(height),\n\tBarColor(forecolor),\n\tBackColor(backcolor),\n\tBorderColor(bordercolor),\n\tCurrentValue(0),\n\tLastDisplayCurrent(0),\n\tIsDrawn(false)\n{\n}\n\n\n/***********************************************************************************************\n * ProgressBarClass::Is_Horizontal -- Determines if the bargraph is horizontal or not.         *\n *                                                                                             *\n *    If the bargraph is oriented horizontally, then this function will return TRUE.           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is this bargraph horizontal?                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ProgressBarClass::Is_Horizontal(void) const\n{\n\tif (Width > Height) return(true);\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ProgressBarClass::Update -- Update the value and redraw as necessary.                       *\n *                                                                                             *\n *    This will update the value of the bargraph to the fill ratio specified and then          *\n *    redraw it if required. Very small changes to the bargraph value might not result in a    *\n *    visual change.                                                                           *\n *                                                                                             *\n * INPUT:   value -- The new value to assign to this bargraph.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   bool; Did this update result in a redraw?                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ProgressBarClass::Update(fixed value)\n{\n\tCurrentValue = value;\n\n\tif (!IsDrawn || value - LastDisplayCurrent >= fixed(1, 10)) {\n\t\tRedraw();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ProgressBarClass::Outline -- Draw an outline around the bargraph if supposed to.            *\n *                                                                                             *\n *    This routine will draw a border around the bargraph if this bargraph has a color         *\n *    specified for the border.                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ProgressBarClass::Outline(void) const\n{\n\tif (Is_Outlined()) {\n\t\tLogicPage->Draw_Line(X, Y, X+Width, Y, BorderColor);\n\t\tLogicPage->Draw_Line(X, Y, X, Y+Height, BorderColor);\n\t\tLogicPage->Draw_Line(X, Y+Height, X, Y+Height, BorderColor);\n\t\tLogicPage->Draw_Line(X+Width, Y, X+Width, Y+Height, BorderColor);\n\t}\n}\n\n\n/***********************************************************************************************\n * ProgressBarClass::Redraw -- Redraw the bargraph.                                            *\n *                                                                                             *\n *    This will redraw the entire bargraph.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ProgressBarClass::Redraw(void) const\n{\n\tHide_Mouse();\n\n\tOutline();\n\n\t/*\n\t**\tDetermine the inner dimensions of the bargraph. This will be\n\t**\tsomewhat smaller than indicated if it has a border.\n\t*/\n\tint x = X;\n\tint y = Y;\n\tint w = Width;\n\tint h = Height;\n\tif (Is_Outlined()) {\n\t\tx += 1;\n\t\ty += 1;\n\t\tw -= 2;\n\t\th -= 2;\n\t}\n\n\t/*\n\t**\tThe working \"length\" of the bargraph is dependant on whether the\n\t**\tbargraph is horizontal or vertical.\n\t*/\n\tint size = Is_Horizontal() ? w : h;\n\n\t/*\n\t**\tDetermine the number of pixels to fill in the bargraph depending on the\n\t**\tsize of the internal value. The larger the internal value the more\n\t**\tfilled the bargraph becomes.\n\t*/\n\tint fill = CurrentValue * size;\n\n\t/*\n\t**\tDraw the filled portion of the bargraph if there is any pixels to draw.\n\t*/\n\tif (fill > 0) {\n\t\tif (Is_Horizontal()) {\n\t\t\tLogicPage->Fill_Rect(x, y, x+fill, y+h, BarColor);\n\t\t} else {\n\t\t\tLogicPage->Fill_Rect(x, y+fill, x+w, y+h, BarColor);\n\t\t}\n\t}\n\n\t/*\n\t**\tDraw the unfilled portion of the bargraph if there are any pixels to\n\t**\tdraw of it.\n\t*/\n\tif (w-fill > 0) {\n\t\tif (Is_Horizontal()) {\n\t\t\tLogicPage->Fill_Rect(x+fill, y, x+w, y+h, BackColor);\n\t\t} else {\n\t\t\tLogicPage->Fill_Rect(x, y, x+w, y+fill-1, BackColor);\n\t\t}\n\t}\n\n\tShow_Mouse();\n\n\tProgressBarClass * me = (ProgressBarClass *)this;\n\tme->LastDisplayCurrent = CurrentValue;\n\tme->IsDrawn = true;\n}\n"
  },
  {
    "path": "CODE/BAR.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BAR.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BAR.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 08/16/96                                                     *\n *                                                                                             *\n *                  Last Update : August 16, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BAR_H\n#define BAR_H\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n#include \"fixed.h\"\n\n\n/*\n**\tThis is a manager for a progress (or other) bargraph. Such a graph consists of a fill\n**\tand a background region. The fill percentage of the bargraph is controlled by an\n**\tupdate value. The bargraph can be optionally outlined.\n*/\nclass ProgressBarClass\n{\n\tpublic:\n\t\tProgressBarClass(int x, int y, int width, int height, int forecolor, int backcolor, int bordercolor=0);\n\n\t\tbool Update(fixed value);\n\t\tvoid Redraw(void) const;\n\n\tprivate:\n\n\t\tvoid Outline(void) const;\n\t\tbool Is_Horizontal(void) const;\n\t\tbool Is_Outlined(void) const {return(BorderColor != 0);}\n\n\t\t/*\n\t\t**\tThis is the upper left coordinates of the bargraph.\n\t\t*/\n\t\tint X,Y;\n\n\t\t/*\n\t\t**\tThis is the dimensions of the bargraph.\n\t\t*/\n\t\tint Width, Height;\n\n\t\t/*\n\t\t**\tThese are the colors to use when drawing the progress bar.\n\t\t*/\n\t\tint BarColor;\n\t\tint BackColor;\n\t\tint BorderColor;\n\n\t\t/*\n\t\t**\tThis is the current value of the bargraph.\n\t\t*/\n\t\tfixed CurrentValue;\n\n\t\t/*\n\t\t**\tThis is the current value as of the last time the bargraph was rendered.\n\t\t*/\n\t\tfixed LastDisplayCurrent;\n\n\t\t/*\n\t\t**\tIf the bargraph has been drawn at least once, then this flag will\n\t\t**\tbe true.\n\t\t*/\n\t\tunsigned IsDrawn:1;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/BASE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BASE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BASE.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Bill Randolph                                                *\n *                                                                                             *\n *                   Start Date : 03/27/95                                                     *\n *                                                                                             *\n *                  Last Update : July 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BaseClass::Get_Building -- Returns ptr to the built building for the given node           *\n *   BaseClass::Get_Node -- Finds the node that matches the cell specified.                    *\n *   BaseClass::Get_Node -- Returns ptr to the node corresponding to given object              *\n *   BaseClass::Is_Built -- Tells if given item in the list has been built yet                 *\n *   BaseClass::Is_Node -- Tells if the given building is part of our base list                *\n *   BaseClass::Load -- loads from a saved game file                                           *\n *   BaseClass::Next_Buildable -- returns ptr to the next node that needs to be built          *\n *   BaseClass::Read_INI -- INI reading routine                                                *\n *   BaseClass::Save -- saves to a saved game file                                             *\n *   BaseClass::Write_INI -- Writes all the base information to the INI database.              *\n *   BaseNodeClass::operator != -- inequality operator                                         *\n *   BaseNodeClass::operator == -- equality operator                                           *\n *   BaseNodeClass::operator > -- greater-than operator                                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/***********************************************************************************************\n * BaseNodeClass::operator == -- equality operator                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      node      node to test against                                                         *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = equal, false = not equal                                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nint BaseNodeClass::operator == (BaseNodeClass const & node)\n{\n\treturn(Type == node.Type && Cell == node.Cell);\n}\n\n\n/***********************************************************************************************\n * BaseNodeClass::operator != -- inequality operator                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      node      node to test against                                                         *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      comparison result                                                                      *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nint BaseNodeClass::operator !=(BaseNodeClass const & node)\n{\n\treturn(!(*this == node));\n}\n\n\n/***********************************************************************************************\n * BaseNodeClass::operator > -- greater-than operator                                          *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      node      node to test against                                                         *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      comparison result                                                                      *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nint BaseNodeClass::operator > (BaseNodeClass const & )\n{\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * BaseClass::Load -- loads from a saved game file                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      file      open file                                                                    *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = success, false = failure                                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *   07/04/1996 JLB : Converted to demand driven data source.                                  *\n *=============================================================================================*/\nbool BaseClass::Load(Straw & file)\n{\n\tint num_struct;\n\tint i;\n\tBaseNodeClass node;\n\n\t/*\n\t** Read in & check the size of this class\n\t*/\n\tif (file.Get(&i, sizeof(i)) != sizeof(i)) {\n\t\treturn(false);\n\t}\n\n\tif (i != sizeof(*this)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t** Read in the House & the number of structures in the base\n\t*/\n\tif (file.Get(&House, sizeof(House)) != sizeof(House)) {\n\t\treturn(false);\n\t}\n\n\tif (file.Get(&num_struct, sizeof(num_struct)) != sizeof(num_struct)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t** Read each node entry & add it to the list\n\t*/\n\tfor (i = 0; i < num_struct; i++) {\n\t\tif (file.Get(&node, sizeof(node)) != sizeof(node)) {\n\t\t\treturn(false);\n\t\t}\n\t\tNodes.Add(node);\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * BaseClass::Save -- saves to a saved game file                                               *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      file      open file                                                                    *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = success, false = failure                                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *   07/04/1996 JLB : Converted to supply driven data output.                                  *\n *=============================================================================================*/\nbool BaseClass::Save(Pipe & file) const\n{\n\tint num_struct;\n\tint i;\n\tBaseNodeClass node;\n\n\t/*\n\t** Write the size of this class\n\t*/\n\ti = sizeof(*this);\n\tfile.Put(&i, sizeof(i));\n\n\t/*\n\t** Write the House & the number of structures in the base\n\t*/\n\tfile.Put(&House, sizeof(House));\n\n\tnum_struct = Nodes.Count();\n\tfile.Put(&num_struct, sizeof(num_struct));\n\n\t/*\n\t** Write each node entry\n\t*/\n\tfor (i = 0; i < num_struct; i++) {\n\t\tnode = Nodes[i];\n\t\tfile.Put(&node, sizeof(node));\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * BaseClass::Is_Built -- Tells if given item in the list has been built yet                   *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      index      index into base list                                                        *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = yes, false = no                                                                 *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nbool BaseClass::Is_Built(int index) const\n{\n\tif (Get_Building(index) != NULL) {\n\t\treturn(true);\n\t} else {\n\t\treturn(false);\n\t}\n}\n\n\n/***********************************************************************************************\n * BaseClass::Get_Building -- Returns ptr to the built building for the given node             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      obj      pointer to building to test                                                   *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      ptr to already-built building, NULL if none                                            *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *   07/30/1996 JLB : Handle arbitrary overlapper list length.                                 *\n *=============================================================================================*/\nBuildingClass * BaseClass::Get_Building(int index) const\n{\n\tObjectClass * obj[1 + ARRAY_SIZE(Map[(CELL)0].Overlapper)];\n\n\t/*\n\t** Check the location on the map where this building should be; if it's\n\t** there, return a pointer to it.\n\t*/\n\tCELL cell = Nodes[index].Cell;\n\n\tobj[0] = Map[cell].Cell_Building();\n\tint count = 1;\n\tfor (int xindex = 0; xindex < ARRAY_SIZE(Map[cell].Overlapper); xindex++) {\n\t\tif (Map[cell].Overlapper[xindex] != NULL) {\n\t\t\tobj[count++] = Map[cell].Overlapper[xindex];\n\t\t}\n\t}\n\n\tBuildingClass * bldg = NULL;\n\tfor (int i = 0; i < count; i++) {\n\t\tif (obj[i] &&\n\t\t\tCoord_Cell(obj[i]->Coord) == Nodes[index].Cell &&\n\t\t\tobj[i]->What_Am_I() == RTTI_BUILDING &&\n\t\t\t((BuildingClass *)obj[i])->Class->Type == Nodes[index].Type) {\n\n\t\t\t\tbldg = (BuildingClass *)obj[i];\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn(bldg);\n}\n\n\n/***********************************************************************************************\n * BaseClass::Is_Node -- Tells if the given building is part of our base list                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      obj      pointer to building to test                                                   *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = building is a node in the list, false = isn't                                   *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nbool BaseClass::Is_Node(BuildingClass const * obj)\n{\n\tif (Get_Node(obj) != NULL) {\n\t\treturn(true);\n\t} else {\n\t\treturn(false);\n\t}\n}\n\n\n/***********************************************************************************************\n * BaseClass::Get_Node -- Returns ptr to the node corresponding to given object                *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      obj      pointer to building to test                                                   *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      ptr to node                                                                            *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nBaseNodeClass * BaseClass::Get_Node(BuildingClass const * obj)\n{\n\tfor (int i = 0; i < Nodes.Count(); i++) {\n\t\tif (obj->Class->Type == Nodes[i].Type && Coord_Cell(obj->Coord) == Nodes[i].Cell) {\n\t\t\treturn(&Nodes[i]);\n\t\t}\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * BaseClass::Get_Node -- Finds the node that matches the cell specified.                      *\n *                                                                                             *\n *    This routine is used to find a matching node the corresponds to the cell specified.      *\n *                                                                                             *\n * INPUT:   cell  -- The cell to use in finding a match.                                       *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to the matching node if found. If not found, then NULL is        *\n *          returned.                                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBaseNodeClass * BaseClass::Get_Node(CELL cell)\n{\n\tfor (int index = 0; index < Nodes.Count(); index++) {\n\t\tif (cell == Nodes[index].Cell) {\n\t\t\treturn(&Nodes[index]);\n\t\t}\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * BaseClass::Next_Buildable -- returns ptr to the next node that needs to be built            *\n *                                                                                             *\n * If 'type' is not NONE, returns ptr to the next \"hole\" in the list of the given type.        *\n * Otherwise, returns ptr to the next hole in the list of any type.                            *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      type      type of building to check for                                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      ptr to a BaseNodeClass, NULL if none                                                   *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nBaseNodeClass * BaseClass::Next_Buildable(StructType type)\n{\n\t/*\n\t** Loop through all node entries, returning a pointer to the first\n\t** un-built one that matches the requested type.\n\t*/\n\tfor (int i = 0; i < Nodes.Count(); i++) {\n\n\t\t/*\n\t\t** For STRUCT_NONE, return the first hole found\n\t\t*/\n\t\tif (type == STRUCT_NONE) {\n\t\t\tif (!Is_Built(i)) {\n\t\t\t\treturn(&Nodes[i]);\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t** For a \"real\" building type, return the first hold for that type\n\t\t\t*/\n\t\t\tif (Nodes[i].Type==type && !Is_Built(i)) {\n\t\t\t\treturn(&Nodes[i]);\n\t\t\t}\n\t\t}\n\t}\n\n\n// If no entry could be found, then create a fake one that will allow\n// placement of the building. Make it static and reuse the next time this\n// routine is called.\n\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * BaseClass::Read_INI -- INI reading routine                                                  *\n *                                                                                             *\n * INI entry format:                                                                           *\n *      BLDG=COORDINATE                                                                        *\n *      BLDG=COORDINATE                                                                        *\n *        ...                                                                                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      buffer      pointer to loaded INI file                                                 *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      This routines assumes there is only one base defined for the scenario.                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *   02/20/1996 JLB : Fixed to know what house to build base from.                             *\n *=============================================================================================*/\nvoid BaseClass::Read_INI(CCINIClass & ini)\n{\n\tchar buf[128];\n\tchar uname[10];\n\tBaseNodeClass node;\t\t\t\t\t\t// node to add to list\n\t\n\tMono_Clear_Screen();\n\t/*\n\t**\tFirst, determine the house of the human player, and set the Base's house\n\t**\taccordingly.\n\t*/\n\tHouse = ini.Get_HousesType(INI_Name(), \"Player\", PlayerPtr->Class->House);\n\n\t/*\n\t**\tRead the number of buildings that will go into the base node list\n\t*/\n\tint count = ini.Get_Int(INI_Name(), \"Count\", 0);\n\n\t/*\n\t**\tRead each entry in turn, in the same order they were written out.\n\t*/\n\tfor (int i = 0; i < count; i++) {\n\n\t\t/*\n\t\t** Get an INI entry\n\t\t*/\n\t\tsprintf(uname,\"%03d\",i);\n\t\tini.Get_String(INI_Name(), uname, NULL, buf, sizeof(buf));\n\n\t\t/*\n\t\t** Set the node's building type\n\t\t*/\n\t\tnode.Type = BuildingTypeClass::From_Name(strtok(buf,\",\"));\n\n\t\t/*\n\t\t** Read & set the node's coordinate\n\t\t*/\n\t\tnode.Cell = atoi(strtok(NULL,\",\"));\n\n\t\t/*\n\t\t** Add this node to the Base's list\n\t\t*/\n\t\tNodes.Add(node);\n\t}\n}\n\n\n/***********************************************************************************************\n * BaseClass::Write_INI -- Writes all the base information to the INI database.                *\n *                                                                                             *\n *    Use this routine to write all prebuild base information to the INI database specified.   *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to store the data to.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If there was any preexisting prebuild base data in the database, it will be     *\n *             be erased by this routine.                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BaseClass::Write_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tClear out all existing base data from the ini file.\n\t*/\n\tini.Clear(INI_Name());\n\n\tif (House != HOUSE_NONE) {\n\n\t\t/*\n\t\t**\tWrite out the owner of this buildable list.\n\t\t*/\n\t\tini.Put_HousesType(INI_Name(), \"Player\", House);\n\n\t\t/*\n\t\t**\tSave the # of buildings in the Nodes list.  This is essential because\n\t\t**\tthey must be read in the same order they were created, so \"000\" must be\n\t\t**\tread first, etc.\n\t\t*/\n\t\tini.Put_Int(INI_Name(), \"Count\", Nodes.Count());\n\n\t\t/*\n\t\t**\tWrite each entry into the INI\n\t\t*/\n\t\tfor (int i = 0; i < Nodes.Count(); i++) {\n\t\t\tchar buf[128];\n\t\t\tchar uname[10];\n\n\t\t\tsprintf(uname,\"%03d\",i);\n\t\t\tsprintf(buf,\"%s,%d\",\n\t\t\t\tBuildingTypeClass::As_Reference(Nodes[i].Type).IniName,\n\t\t\t\tNodes[i].Cell);\n\n\t\t\tini.Put_String(INI_Name(), uname, buf);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "CODE/BASE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BASE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BASE.H                                                       *\n *                                                                                             *\n *                   Programmer : Bill Randolph\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *                   Start Date : 03/27/95                                                     *\n *                                                                                             *\n *                  Last Update : March 27, 1995\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BASE_H\n#define BASE_H\n\n\n/****************************************************************************\n** This class defines one \"node\" in the pre-built base list.  Each node\n** contains a type of building to build, and the COORDINATE to build it at.\n*/\nclass BaseNodeClass\n{\n\tpublic:\n\t\tBaseNodeClass(void) {};\n\t\tBaseNodeClass(StructType building, CELL cell) : Type(building), Cell(cell) {};\n\t\tint operator == (BaseNodeClass const & node);\n\t\tint operator != (BaseNodeClass const & node);\n\t\tint operator > (BaseNodeClass const & node);\n\n\t\tStructType Type;\n\t\tCELL Cell;\n};\n\n\n/****************************************************************************\n** This is the class that defines a pre-built base for the computer AI.\n** (Despite its name, this is NOT the \"base\" class for C&C's class hierarchy!)\n*/\nclass BaseClass\n{\n\tpublic:\n\n\t\t/*\n\t\t** Constructor/Destructor\n\t\t*/\n\t\tBaseClass(void) {};\n\t\tvirtual ~BaseClass() {Nodes.Clear();}\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvoid Init(void) {House = HOUSE_NONE; Nodes.Clear();}\n\n\t\t/*\n\t\t** The standard suite of load/save support routines\n\t\t*/\n\t\tvoid Read_INI(CCINIClass & ini);\n\t\tvoid Write_INI(CCINIClass & ini);\n\t\tstatic char *INI_Name(void) {return \"Base\";}\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\t\tvirtual void Code_Pointers(void) {};\n\t\tvirtual void Decode_Pointers(void) {};\n\n\t\t/*\n\t\t** Tells if the given node has been built or not\n\t\t*/\n\t\tbool Is_Built(int index) const;\n\n\t\t/*\n\t\t** Returns a pointer to the object for the given node\n\t\t*/\n\t\tBuildingClass * Get_Building(int index) const;\n\n\t\t/*\n\t\t** Tells if the given building ptr is a node in this base's list.\n\t\t*/\n\t\tbool Is_Node(BuildingClass const * obj);\n\n\t\t/*\n\t\t** Returns a pointer to the requested node.\n\t\t*/\n\t\tBaseNodeClass * Get_Node(BuildingClass const * obj);\n\t\tBaseNodeClass * Get_Node(int index) { return (&Nodes[index]); }\n\t\tBaseNodeClass * Get_Node(CELL cell);\n\n\t\t/*\n\t\t** Returns a pointer to the next \"hole\" in the Nodes list.\n\t\t*/\n\t\tBaseNodeClass * Next_Buildable(StructType type = STRUCT_NONE);\n\n\t\t/*\n\t\t** This is the list of \"nodes\" that define the base.  Portions of this\n\t\t** list can be pre-built by simply saving those buildings in the INI\n\t\t** along with non-base buildings, so Is_Built will return true for them.\n\t\t*/\n\t\tDynamicVectorClass<BaseNodeClass> Nodes;\n\n\t\t/*\n\t\t** This is the house this base belongs to.\n\t\t*/\n\t\tHousesType House;\n};\n\n\n#endif\n\n"
  },
  {
    "path": "CODE/BASE64.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BASE64.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BASE64.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/29/96                                                     *\n *                                                                                             *\n *                  Last Update : July 6, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Base64_Decode -- Decodes Base 64 data into its original data form.                        *\n *   Base64_Encode -- Encode data into Base 64 format.                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"base64.h\"\n#include\t<stddef.h>\n\n/*\n**\tThis is the magic padding character used to fill out the encoded data to a multiple of\n**\t4 characters even though the source data is less than necessary to accomplish this.\n**\tThe pad character lets the decoder know of this condition and it will compensate\n**\taccordingly.\n*/\nstatic char const * const _pad = \"=\";\n\n/*\n**\tThis encoder translation table will convert a 6 bit number into an ASCII character.\n*/\nstatic char const * const _encoder = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n/*\n**\tThe decoder translation table takes an ASCII character and converts it into a\n**\t6 bit number.\n*/\n#define\tBAD\t0xFE\t\t\t// Ignore this character in source data.\n#define\tEND\t0xFF\t\t\t// Signifies premature end of input data.\nstatic unsigned char const _decoder[256] = {\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,62,BAD,BAD,BAD,63,\n\t52,53,54,55,56,57,58,59,60,61,BAD,BAD,BAD,END,BAD,BAD,\n\tBAD,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,\n\t15,16,17,18,19,20,21,22,23,24,25,BAD,BAD,BAD,BAD,BAD,\n\tBAD,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,\n\t41,42,43,44,45,46,47,48,49,50,51,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD\n};\n\nint const PacketChars = 4;\n\n\n/*\n**\tThe packet type is used to construct and disect the Base64 data blocks. The data\n**\tconsists of three source data bytes mapped onto four 6 bit Base64 code elements.\n*/\ntypedef union {\n\tstruct {\n#ifdef BIG_ENDIAN\n\t\tunsigned char C1;\n\t\tunsigned char C2;\n\t\tunsigned char C3;\n#else\n\t\tunsigned char C3;\n\t\tunsigned char C2;\n\t\tunsigned char C1;\n#endif\n\t\tunsigned char pad;\n\t} Char;\n\tstruct {\n#ifdef BIG_ENDIAN\n\t\tunsigned O1:6;\n\t\tunsigned O2:6;\n\t\tunsigned O3:6;\n\t\tunsigned O4:6;\n#else\n\t\tunsigned O4:6;\n\t\tunsigned O3:6;\n\t\tunsigned O2:6;\n\t\tunsigned O1:6;\n#endif\n\t\tunsigned pad:8;\n\t} SubCode;\n\tunsigned int Raw;\n}\tPacketType;\n\n\n/***********************************************************************************************\n * Base64_Encode -- Encode data into Base 64 format.                                           *\n *                                                                                             *\n *    This will take an arbitrary length of source data and transform it into base 64 format   *\n *    data. Base 64 format has the property of being very portable across text editors and     *\n *    country character encoding schemes. As such it is ideal for e-mail. Note that the output *\n *    data will be about 33% larger than the source.                                           *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the source data to convert.                                 *\n *                                                                                             *\n *          slen     -- The number of bytes to encode.                                         *\n *                                                                                             *\n *          dest     -- Pointer to the destination buffer that will hold the encoded data.     *\n *                                                                                             *\n *          dlen     -- The size of the destination buffer.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes stored into the destination buffer.               *\n *                                                                                             *\n * WARNINGS:   Be sure that the destination buffer is big enough to hold the encoded output.   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Base64_Encode(void const * source, int slen, void * dest, int dlen)\n{\n\t/*\n\t**\tCheck the parameters for legality.\n\t*/\n\tif (source == NULL || slen == 0 || dest == NULL || dlen == 0) {\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tProcess the source data in blocks of three bytes. Fewer than three bytes\n\t**\tresults in special padding output characters (automatically discarded\n\t**\tduring the decode process).\n\t*/\n\tint total = 0;\n\tunsigned char const * sptr = (unsigned char const *)source;\n\tunsigned char * dptr = (unsigned char *)dest;\n\twhile (slen > 0 && dlen >= PacketChars) {\n\n\t\t/*\n\t\t**\tFetch 24 bits of source data.\n\t\t*/\n\t\tPacketType packet;\n\n\t\tint pad = 0;\n\t\tpacket.Raw = 0;\n\t\tpacket.Char.C1 = *sptr++;\n\t\tslen--;\n\t\tif (slen) {\n\t\t\tpacket.Char.C2 = *sptr++;\n\t\t\tslen--;\n\t\t} else {\n\t\t\tpad++;\n\t\t}\n\t\tif (slen) {\n\t\t\tpacket.Char.C3 = *sptr++;\n\t\t\tslen--;\n\t\t} else {\n\t\t\tpad++;\n\t\t}\n\n\t\t/*\n\t\t**\tTranslate and write 4 characters of Base64 data. Pad with pad\n\t\t**\tcharacters if there is insufficient source data for a full packet.\n\t\t*/\n\t\t*dptr++ = _encoder[packet.SubCode.O1];\n\t\t*dptr++ = _encoder[packet.SubCode.O2];\n\t\tif (pad < 2) {\n\t\t\t*dptr++ = _encoder[packet.SubCode.O3];\n\t\t} else {\n\t\t\t*dptr++ = _pad[0];\n\t\t}\n\t\tif (pad < 1) {\n\t\t\t*dptr++ = _encoder[packet.SubCode.O4];\n\t\t} else {\n\t\t\t*dptr++ = _pad[0];\n\t\t}\n\n\t\tdlen -= PacketChars;\n\t\ttotal += PacketChars;\n\t}\n\n\t/*\n\t**\tAdd a trailing null as a courtesy measure.\n\t*/\n\tif (dlen > 0) {\n\t\t*dptr = '\\0';\n\t}\n\n\t/*\n\t**\tReturn with the total number of characters in the output buffer.\n\t*/\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * Base64_Decode -- Decodes Base 64 data into its original data form.                          *\n *                                                                                             *\n *    Use this routine to decode base 64 data back into the original data. A property of this  *\n *    decode process is that unrecognized input characters are ignored. This allows mangled    *\n *    source (filled with line breaks or spaces) to be correctly decoded. The decode process   *\n *    terminates when the end of the source data has been reached or the special end of data   *\n *    marker is encountered.                                                                   *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the source data to decode.                                  *\n *                                                                                             *\n *          slen     -- The number of bytes in the source data buffer.                         *\n *                                                                                             *\n *          dest     -- Pointer to the destination buffer to be filled with the decoded data.  *\n *                                                                                             *\n *          dlen     -- The maximum size of the destination buffer.                            *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes stored into the destination buffer. This will     *\n *          always be less than the number of source bytes (usually by about 33%).             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Base64_Decode(void const * source, int slen, void * dest, int dlen)\n{\n\t/*\n\t**\tCheck the parameters for legality.\n\t*/\n\tif (source == NULL || slen == 0 || dest == NULL || dlen == 0) {\n\t\treturn(0);\n\t}\n\n\tint total = 0;\n\tunsigned char const * sptr = (unsigned char const *)source;\n\tunsigned char * dptr = (unsigned char *)dest;\n\twhile (slen > 0 && dlen > 0) {\n\n\t\tPacketType packet;\n\t\tpacket.Raw = 0;\n\n\t\t/*\n\t\t**\tProcess input until a full packet has been accumulated or the\n\t\t**\tsource is exhausted.\n\t\t*/\n\t\tint pcount = 0;\n\t\twhile (pcount < PacketChars && slen > 0) {\n\t\t\tunsigned char c = *sptr++;\n\t\t\tslen--;\n\n\t\t\tunsigned char code = _decoder[c];\n\n\t\t\t/*\n\t\t\t**\tAn unrecognized character is skipped.\n\t\t\t*/\n\t\t\tif (code == BAD) continue;\n\n\t\t\t/*\n\t\t\t**\tThe \"=\" character signifies the end of data regardless of what\n\t\t\t**\tthe source buffer length value may be.\n\t\t\t*/\n\t\t\tif (code == END) {\n\t\t\t\tslen = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tA valid Base64 character was found so add it to the packet\n\t\t\t**\tdata.\n\t\t\t*/\n\t\t\tswitch (pcount) {\n\t\t\t\tcase 0:\n\t\t\t\t\tpacket.SubCode.O1 = code;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tpacket.SubCode.O2 = code;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tpacket.SubCode.O3 = code;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tpacket.SubCode.O4 = code;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tpcount++;\n\t\t}\n\n\t\t/*\n\t\t**\tA packet block is ready for output into the destination buffer.\n\t\t*/\n\t\t*dptr++ = packet.Char.C1;\n\t\tdlen--;\n\t\ttotal++;\n\t\tif (dlen > 0 && pcount > 2) {\n\t\t\t*dptr++ = packet.Char.C2;\n\t\t\tdlen--;\n\t\t\ttotal++;\n\t\t}\n\t\tif (dlen > 0 && pcount > 3) {\n\t\t\t*dptr++ = packet.Char.C3;\n\t\t\tdlen--;\n\t\t\ttotal++;\n\t\t}\n\t}\n\n\t/*\n\t**\tReturn with the total number of characters decoded into the\n\t**\toutput buffer.\n\t*/\n\treturn(total);\n}\n\n\n/*\nBase64 Content-Transfer-Encoding\n\nThe Base64 Content-Transfer-Encoding is designed to represent arbitrary\nsequences of octets in a form that need not be humanly readable. The encoding\nand decoding algorithms are simple, but the encoded data are consistently\nonly about 33 percent larger than the unencoded data. This encoding is\nvirtually identical to the one used in Privacy Enhanced Mail (PEM)\napplications, as defined in RFC 1421. The base64 encoding is adapted from\nRFC 1421, with one change: base64 eliminates the \"*\" mechanism for embedded\nclear text.\n\nA 65-character subset of US-ASCII is used, enabling 6 bits to be represented\nper printable character. (The extra 65th character, \"=\", is used to signify a\nspecial processing function.)\n\nNOTE:\n    This subset has the important property that it is represented identically\n    in all versions of ISO 646, including US ASCII, and all characters in the\n    subset are also represented identically in all versions of EBCDIC. Other\n    popular encodings, such as the encoding used by the uuencode utility and\n    the base85 encoding specified as part of Level 2 PostScript, do not share\n    these properties, and thus do not fulfill the portability requirements a\n    binary transport encoding for mail must meet.\n\nThe encoding process represents 24-bit groups of input bits as output strings\nof 4 encoded characters. Proceeding from left to right, a 24-bit input group is\nformed by concatenating 3 8-bit input groups. These 24 bits are then treated as\n4 concatenated 6-bit groups, each of which is translated into a single digit in\nthe base64 alphabet. When encoding a bit stream via the base64 encoding, the\nbit stream must be presumed to be ordered with the most-significant-bit first.\nThat is, the first bit in the stream will be the high-order bit in the first\nbyte, and the eighth bit will be the low-order bit in the first byte, and so on.\n\nEach 6-bit group is used as an index into an array of 64 printable characters.\nThe character referenced by the index is placed in the output string. These\ncharacters, identified in Table 1, below, are selected so as to be universally\nrepresentable, and the set excludes characters with particular significance to\nSMTP (e.g., \".\", CR, LF) and to the encapsulation boundaries defined in this\ndocument (e.g., \"-\").\n\nTable 1: The Base64 Alphabet\n\n  Value Encoding  Value Encoding  Value Encoding  Value Encoding\n       0 A            17 R            34 i            51 z\n       1 B            18 S            35 j            52 0\n       2 C            19 T            36 k            53 1\n       3 D            20 U            37 l            54 2\n       4 E            21 V            38 m            55 3\n       5 F            22 W            39 n            56 4\n       6 G            23 X            40 o            57 5\n       7 H            24 Y            41 p            58 6\n       8 I            25 Z            42 q            59 7\n       9 J            26 a            43 r            60 8\n      10 K            27 b            44 s            61 9\n      11 L            28 c            45 t            62 +\n      12 M            29 d            46 u            63 /\n      13 N            30 e            47 v\n      14 O            31 f            48 w         (pad) =\n      15 P            32 g            49 x\n      16 Q            33 h            50 y\n\nThe output stream (encoded bytes) must be represented in lines of no more than\n76 characters each. All line breaks or other characters not found in Table 1\nmust be ignored by decoding software. In base64 data, characters other than\nthose in Table 1, line breaks, and other white space probably indicate a\ntransmission error, about which a warning message or even a message rejection\nmight be appropriate under some circumstances.\n\nSpecial processing is performed if fewer than 24 bits are available at the end\nof the data being encoded. A full encoding quantum is always completed at the\nend of a body. When fewer than 24 input bits are available in an input group,\nzero bits are added (on the right) to form an integral number of 6-bit groups.\nPadding at the end of the data is performed using the '=' character. Since all\nbase64 input is an integral number of octets, only the following cases can\narise: (1) the final quantum of encoding input is an integral multiple of 24\nbits; here, the final unit of encoded output will be an integral multiple of 4\ncharacters with no \"=\" padding, (2) the final quantum of encoding input is\nexactly 8 bits; here, the final unit of encoded output will be two characters\nfollowed by two \"=\" padding characters, or (3) the final quantum of encoding\ninput is exactly 16 bits; here, the final unit of encoded output will be three\ncharacters followed by one \"=\" padding character.\n\nBecause it is used only for padding at the end of the data, the occurrence of\nany '=' characters may be taken as evidence that the end of the data has been\nreached (without truncation in transit). No such assurance is possible,\nhowever, when the number of octets transmitted was a multiple of three.\n\nAny characters outside of the base64 alphabet are to be ignored in\nbase64-encoded data. The same applies to any illegal sequence of characters in\nthe base64 encoding, such as \"=====\"\n\nCare must be taken to use the proper octets for line breaks if base64 encoding\nis applied directly to text material that has not been converted to canonical\nform. In particular, text line breaks must be converted into CRLF sequences\nprior to base64 encoding. The important thing to note is that this may be done\ndirectly by the encoder rather than in a prior canonicalization step in some\nimplementations.\n\nNOTE:\n    There is no need to worry about quoting apparent encapsulation boundaries\n    within base64-encoded parts of multipart entities because no hyphen\n    characters are used in the base64 encoding.\n\n*/"
  },
  {
    "path": "CODE/BASE64.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BASE64.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BASE64.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/29/96                                                     *\n *                                                                                             *\n *                  Last Update : June 29, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\nint Base64_Encode(void const * source, int slen, void * dest, int dlen);\nint Base64_Decode(void const * source, int slen, void * dest, int dlen);\n"
  },
  {
    "path": "CODE/BBDATA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BBDATA.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BBDATA.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 23, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 19, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BulletTypeClass::As_Reference -- Returns with a reference to the bullet type object specif*\n *   BulletTypeClass::BulletTypeClass -- Constructor for bullet type objects.                  *\n *   BulletTypeClass::Init_Heap -- Initialize the heap objects for the bullet type.            *\n *   BulletTypeClass::Load_Shapes -- Load shape data for bullet types.                         *\n *   BulletTypeClass::One_Time -- Performs the one time processing for bullets.                *\n *   BulletTypeClass::Read_INI -- Fetch the bullet type data from the INI database.            *\n *   BulletTypeClass::operator delete -- Deletes a bullet type object from the special heap.   *\n *   BulletTypeClass::operator new -- Allocates a bullet type object from the special heap.    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n\n/***********************************************************************************************\n * BulletTypeClass::BulletTypeClass -- Constructor for bullet type objects.                    *\n *                                                                                             *\n *    This is basically a constructor for static type objects used by bullets. All bullets     *\n *    are of a type constructed by this routine at game initialization time.                   *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *   07/17/1996 JLB : Uses correct default values.                                             *\n *=============================================================================================*/\nBulletTypeClass::BulletTypeClass(char const * name) :\n\t\tObjectTypeClass(\tRTTI_BULLETTYPE,\n\t\t\t\t\t\t\t\tBulletTypes.ID(this),\n\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\tTXT_NONE,\n\t\t\t\t\t\t\t\tname\n\t\t\t\t\t\t\t\t),\n\tIsHigh(false),\n\tIsShadow(true),\n\tIsArcing(false),\n\tIsDropping(false),\n\tIsInvisible(false),\n\tIsProximityArmed(false),\n\tIsFlameEquipped(false),\n\tIsFueled(false),\n\tIsFaceless(true),\n\tIsInaccurate(false),\n\tIsTranslucent(false),\n\tIsAntiAircraft(false),\n\tIsAntiGround(true),\n\tIsAntiSub(false),\n\tIsDegenerate(false),\n\tIsSubSurface(false),\n\tIsParachuted(false),\n\tIsGigundo(false),\n\tType(BulletType(ID)),\n\tROT(0),\n\tArming(0),\n\tTumble(0)\n{\n}\n\n\n/***********************************************************************************************\n * BulletTypeClass::operator new -- Allocates a bullet type object from the special heap.      *\n *                                                                                             *\n *    This allocates a bullet type object from a special heap that is used just for            *\n *    objects of this type.                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to an allocated block or NULL if the allocation could not   *\n *          occur.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * BulletTypeClass::operator new(size_t)\n{\n\treturn(BulletTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * BulletTypeClass::operator delete -- Deletes a bullet type object from the special heap.     *\n *                                                                                             *\n *    This is the counterpart to the operator new function for bullet type objects. It will    *\n *    return the bullet type object back to the special heap used for bullet type object       *\n *    allocation.                                                                              *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the bullet type object to free.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BulletTypeClass::operator delete(void * ptr)\n{\n\tBulletTypes.Free((BulletTypeClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * BulletTypeClass::Init_Heap -- Initialize the heap objects for the bullet type.              *\n *                                                                                             *\n *    This performs any necessary initialization for the bullet types.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BulletTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese bullet type class objects must be allocated in the exact order that they\n\t**\tare specified in the BulletType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew BulletTypeClass(\"Invisible\");\t//\tBULLET_INVISIBLE\n\tnew BulletTypeClass(\"Cannon\");\t\t//\tBULLET_CANNON\n\tnew BulletTypeClass(\"Ack\");\t\t\t//\tBULLET_ACK\n\tnew BulletTypeClass(\"Torpedo\");\t\t//\tBULLET_TORPEDO\n\tnew BulletTypeClass(\"FROG\");\t\t\t//\tBULLET_FROG\n\tnew BulletTypeClass(\"HeatSeeker\");\t//\tBULLET_HEAT_SEEKER\n\tnew BulletTypeClass(\"LaserGuided\");\t//\tBULLET_LASER_GUIDED\n\tnew BulletTypeClass(\"Lobbed\");\t\t//\tBULLET_LOBBED\n\tnew BulletTypeClass(\"Bomblet\");\t\t//\tBULLET_BOMBLET\n\tnew BulletTypeClass(\"Ballistic\");\t//\tBULLET_BALLISTIC\n\tnew BulletTypeClass(\"Parachute\");\t//\tBULLET_PARACHUTE\n\tnew BulletTypeClass(\"Fireball\");\t\t//\tBULLET_FIREBALL\n\tnew BulletTypeClass(\"LeapDog\");\t\t//\tBULLET_DOG\n\tnew BulletTypeClass(\"Catapult\");\t\t//\tBULLET_CATAPULT\n\tnew BulletTypeClass(\"AAMissile\");\t//\tBULLET_AAMISSILE\n\tnew BulletTypeClass(\"GPSSatellite\");//\tBULLET_GPS_SATELLITE\n\tnew BulletTypeClass(\"NukeUp\");\t\t//\tBULLET_NUKE_UP\n\tnew BulletTypeClass(\"NukeDown\");\t\t//\tBULLET_NUKE_DOWN\n}\n\n\n/***********************************************************************************************\n * BulletTypeClass::One_Time -- Performs the one time processing for bullets.                  *\n *                                                                                             *\n *    This routine is used to perform any one time processing for the bullet type class. It    *\n *    handles loading of the shape files.                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine must be called before any rendering of bullets occurs and should   *\n *             only be called once.                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BulletTypeClass::One_Time(void)\n{\n\t/*\n\t**\tLoad the bullet shapes.\n\t*/\n\tfor (BulletType index = BULLET_FIRST; index < BULLET_COUNT; index++) {\n\t\tBulletTypeClass const & bullet = As_Reference(index);\n\t\tchar\tfullname[_MAX_FNAME+_MAX_EXT];\n\n\t\tif (!bullet.IsInvisible) {\n\t\t\t_makepath(fullname, NULL, NULL, bullet.GraphicName, \".SHP\");\n\n\t\t\t#ifdef NDEBUG\n\t\t\t\t((void const *&)bullet.ImageData) =\tMFCD::Retrieve(fullname);\n\t\t\t#else\n\t\t\t\tRawFileClass file(fullname);\n\n\t\t\t\tif (file.Is_Available()) {\n\t\t\t\t\t((void const *&)bullet.ImageData) = Load_Alloc_Data(file);\n\t\t\t\t} else {\n\t\t\t\t\t((void const *&)bullet.ImageData) =\tMFCD::Retrieve(fullname);\n\t\t\t\t}\n\t\t\t#endif\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BulletTypeClass::As_Reference -- Returns with a reference to the bullet type object specifi *\n *                                                                                             *\n *    Given a bullet type identifier, this routine will return a reference to the bullet type  *\n *    object it refers to.                                                                     *\n *                                                                                             *\n * INPUT:   type  -- The bullet type identifier to convert to a reference.                     *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the bullet type object.                                *\n *                                                                                             *\n * WARNINGS:   Make sure that the type parameter specified is a valid bullet type. If not,     *\n *             then the results are undefined.                                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBulletTypeClass & BulletTypeClass::As_Reference(BulletType type)\n{\n\treturn(*BulletTypes.Ptr(type));\n}\n\n\n/***********************************************************************************************\n * BulletTypeClass::Read_INI -- Fetch the bullet type data from the INI database.              *\n *                                                                                             *\n *    Use this routine to fetch override information about this bullet type class object       *\n *    from the INI database specified.                                                         *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to examine.                                 *\n *                                                                                             *\n * OUTPUT:  bool; Was the section for this bullet found and the data extracted?                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BulletTypeClass::Read_INI(CCINIClass & ini)\n{\n\tif (ini.Is_Present(Name())) {\n\t\tArming = ini.Get_Int(Name(), \"Arm\", Arming);\n\t\tROT = ini.Get_Int(Name(), \"ROT\", ROT);\n\t\tTumble = ini.Get_Int(Name(), \"Frames\", Tumble);\n\t\tIsHigh = ini.Get_Bool(Name(), \"High\", IsHigh);\n\t\tIsShadow = ini.Get_Bool(Name(), \"Shadow\", IsShadow);\n\t\tIsArcing = ini.Get_Bool(Name(), \"Arcing\", IsArcing);\n\t\tIsDropping = ini.Get_Bool(Name(), \"Dropping\", IsDropping);\n\t\tIsInvisible = ini.Get_Bool(Name(), \"Inviso\", IsInvisible);\n\t\tIsProximityArmed = ini.Get_Bool(Name(), \"Proximity\", IsProximityArmed);\n\t\tIsFlameEquipped = ini.Get_Bool(Name(), \"Animates\", IsFlameEquipped);\n\t\tIsFueled = ini.Get_Bool(Name(), \"Ranged\", IsFueled);\n\t\tIsInaccurate = ini.Get_Bool(Name(), \"Inaccuate\", IsInaccurate);\n\t\tIsAntiAircraft = ini.Get_Bool(Name(), \"AA\", IsAntiAircraft);\n\t\tIsAntiGround = ini.Get_Bool(Name(), \"AG\", IsAntiGround);\n\t\tIsAntiSub = ini.Get_Bool(Name(), \"ASW\", IsAntiSub);\n\t\tIsDegenerate = ini.Get_Bool(Name(), \"Degenerates\", IsDegenerate);\n\t\tIsSubSurface = ini.Get_Bool(Name(), \"UnderWater\", IsSubSurface);\n\t\tIsParachuted = ini.Get_Bool(Name(), \"Parachuted\", IsParachuted);\n\t\tIsFaceless = !ini.Get_Bool(Name(), \"Rotates\", !IsFaceless);\n\t\tIsTranslucent = ini.Get_Bool(Name(), \"Translucent\", IsTranslucent);\n\t\tIsGigundo = ini.Get_Bool(Name(), \"Gigundo\", IsGigundo);\n\t\tini.Get_String(Name(), \"Image\", \"none\", GraphicName, sizeof(GraphicName));\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "CODE/BDATA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BDATA.CPP 2     3/03/97 10:37p Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BDATA.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : October 2, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BuildingTypeClass::As_Reference -- Fetches reference to the building type specified.      *\n *   BuildingTypeClass::Bib_And_Offset -- Determines the bib and appropriate cell offset.      *\n *   BuildingTypeClass::BuildingTypeClass -- This is the constructor for the building types.   *\n *   BuildingTypeClass::Coord_Fixup -- Adjusts coordinate to be legal for assignment.          *\n *   BuildingTypeClass::Cost_Of -- Fetches the cost of this building.                          *\n *   BuildingTypeClass::Create_And_Place -- Creates and places a building object onto the map. *\n *   BuildingTypeClass::Create_One_Of -- Creates a building of this type.                      *\n *   BuildingTypeClass::Dimensions -- Fetches the pixel dimensions of the building.            *\n *   BuildingTypeClass::Display -- Renders a generic view of building.                         *\n *   BuildingTypeClass::Flush_For_Placement -- Tries to clear placement area for this building *\n *   BuildingTypeClass::Full_Name -- Fetches the name to give this building.                   *\n *   BuildingTypeClass::Height -- Determines the height of the building in icons.              *\n *   BuildingTypeClass::Init -- Performs theater specific initialization.                      *\n *   BuildingTypeClass::Init_Anim -- Initialize an animation control for a building.           *\n *   BuildingTypeClass::Init_Heap -- Initialize the heap as necessary for the building type obj*\n *   BuildingTypeClass::Max_Pips -- Determines the maximum pips to display.                    *\n *   BuildingTypeClass::Occupy_List -- Fetches the occupy list for the building.               *\n *   BuildingTypeClass::One_Time -- Performs special one time action for buildings.            *\n *   BuildingTypeClass::Overlap_List -- Fetches the overlap list for the building.             *\n *   BuildingTypeClass::Prep_For_Add -- Prepares scenario editor for adding an object.         *\n *   BuildingTypeClass::Raw_Cost -- Fetches the raw (base) cost of this building type.         *\n *   BuildingTypeClass::Read_INI -- Fetch building type data from the INI database.            *\n *   BuildingTypeClass::Width -- Determines width of building in icons.                        *\n *   BuildingTypeClass::operator delete -- Deletes a building type object from the special heap*\n *   BuildingTypeClass::operator new -- Allocates a building type object from the special heap.*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n#define FATSHIP\n\n#define\tMCW\tMAP_CELL_W\n\n#define XYCELL(x,y)\t(y*MAP_CELL_W+x)\nstatic short const ExitPyle[] = {\n\tXYCELL(1,2),\n\tXYCELL(2,2),\n\tXYCELL(0,2),\n\tXYCELL(-1,2),\n\tXYCELL(-1,-1),\n\tXYCELL(0,-1),\n\tXYCELL(1,-1),\n\tXYCELL(2,-1),\n\tXYCELL(2,-1),\n\tXYCELL(-1,0),\n\tXYCELL(2,0),\n\tXYCELL(2,1),\n\tXYCELL(-1,1),\n\tREFRESH_EOL\n};\n\nstatic short const ExitSub[] = {\n\tXYCELL( 0, 2),\n\tXYCELL( 2, 2),\n\tXYCELL(-1, 2),\n\tXYCELL( 1, 2),\n\tXYCELL( 3, 2)\n};\n\nstatic short const ExitWeap[] = {\n\tXYCELL(1,2),\n\tXYCELL(-1,3),\n\tXYCELL(0,3),\n\tXYCELL(1,3),\n\tXYCELL(-2,3),\n\tXYCELL(2,3),\n\tREFRESH_EOL\n};\n\nstatic short const ComList[] = {0, 1, MCW, MCW+1, REFRESH_EOL};\nstatic short const List000111111[] = {(MCW*1), (MCW*1)+1, (MCW*1)+2, (MCW*2), (MCW*2)+1, (MCW*2)+2, REFRESH_EOL};\nstatic short const List0010[] = {MCW, REFRESH_EOL};\nstatic short const List0011[] = {(MCW*1), (MCW*1)+1, REFRESH_EOL};\nstatic short const List010111100[] = {1, (MCW*1), (MCW*1)+1, (MCW*1)+2, (MCW*2), REFRESH_EOL};\nstatic short const List0111[] = {1, (MCW*1), (MCW*1)+1, REFRESH_EOL};\nstatic short const List1000[] = {0, REFRESH_EOL};\nstatic short const List101000011[] = {0, 2, (MCW*2)+1, (MCW*2)+2, REFRESH_EOL};\nstatic short const List1100[] = {0, 1, REFRESH_EOL};\nstatic short const List1101[] = {0, 1, (MCW*1)+1, REFRESH_EOL};\nstatic short const List11[] = {0, 1, REFRESH_EOL};\nstatic short const List12[] = {MCW, REFRESH_EOL};\nstatic short const List1[] = {0, REFRESH_EOL};\nstatic short const List21[] = {0, 1, REFRESH_EOL};\nstatic short const List22[] = {0, 1, MCW, MCW+1, REFRESH_EOL};\nstatic short const List22_0011[] = {MCW, MCW+1, REFRESH_EOL};\nstatic short const List22_1100[] = {0, 1, REFRESH_EOL};\nstatic short const List2[] = {0, 1, MCW+1, MCW, REFRESH_EOL};\nstatic short const List32[] = {0, 1, 2, MCW, MCW+1, MCW+2, REFRESH_EOL};\n//static short const List42[] = {0, 1, 2, 3, MCW, MCW+1, MCW+2, MCW+3, REFRESH_EOL};\nstatic short const ListFix[] = {1, MCW, MCW+1, MCW+2, MCW+MCW+1, REFRESH_EOL};\nstatic short const ListWeap[] = {0, 1, 2, (MCW*1), (MCW*1)+1, (MCW*1)+2, REFRESH_EOL};\nstatic short const ListWestwood[] = {1, 2, 3, MCW+1, MCW+2, MCW+3, REFRESH_EOL};\nstatic short const OListSAM[] = {-MCW, -(MCW-1), REFRESH_EOL};\n#ifdef FATSHIP\nstatic short const ListSPen[] = {0, 1, 2, MCW, MCW+1, MCW+2, MCW+MCW, MCW+MCW+1, MCW+MCW+2, REFRESH_EOL};\nstatic short const OListSPen[] = {REFRESH_EOL};\n#else\nstatic short const ListSPen[] = {1, MCW, MCW+1, MCW+2, MCW+MCW+1, REFRESH_EOL};\nstatic short const OListSPen[] = {0, 2, MCW+MCW, MCW+MCW+2, REFRESH_EOL};\n#endif\nstatic short const OListWestwood[] = {0, MCW, REFRESH_EOL};\nstatic short const StoreList[] = {0, REFRESH_EOL};\n\nstatic short const ListFactory[] = {0, 1, 2, (MCW*1), (MCW*1)+1, (MCW*1)+2, (MCW*2), (MCW*2)+1, (MCW*2)+2, REFRESH_EOL};\n\nstatic short const OListFix[] = {0, 2, MCW+MCW, MCW+MCW+2, REFRESH_EOL};\nstatic short const OListWeap[] = {REFRESH_EOL};\nstatic short const OComList[] = {1, REFRESH_EOL};\nstatic short const OList12[] = {0, REFRESH_EOL};\nstatic short const OListTmpl[] = {0, 1, 2, REFRESH_EOL};\n\n\n/***************************************************************************\n*/\nstatic BuildingTypeClass const ClassBarrel(\n\tSTRUCT_BARREL,\n\tTXT_BARREL,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"BARL\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassBarrel3(\n\tSTRUCT_BARREL3,\n\tTXT_BARREL,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"BRL3\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassAVMine(\n\tSTRUCT_AVMINE,\n\tTXT_AVMINE,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"MINV\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_NONE,\t\t\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\tfalse,\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassAPMine(\n\tSTRUCT_APMINE,\n\tTXT_APMINE,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"MINP\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_NONE,\t\t\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\tfalse,\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassIronCurtain(\n\tSTRUCT_IRON_CURTAIN,\n\tTXT_IRON_CURTAIN,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"IRON\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List22_0011,// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List22_1100\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassForwardCom(\n\tSTRUCT_FORWARD_COM,\n\tTXT_FORWARD_COM,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"FCOM\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List22_0011,// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List22_1100\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassAdvancedTech(\n\tSTRUCT_ADVANCED_TECH,\n\tTXT_ADVANCED_TECH,\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"ATEK\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List22,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassChronosphere(\n\tSTRUCT_CHRONOSPHERE,\n\tTXT_CHRONOSPHERE,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"PDOX\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List22,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassWeapon(\n\tSTRUCT_WEAP,\n\tTXT_WEAPON_FACTORY,\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"WEAP\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXY_Coord(CELL_LEPTON_W+(CELL_LEPTON_W/2), CELL_LEPTON_H),\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_UNITTYPE,\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_32, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\t(short const *)ExitWeap,\t// Preferred exit cell list.\n\t(short const *)ListWeap,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListWeap\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassShipYard(\n\tSTRUCT_SHIP_YARD,\n\tTXT_SHIP_YARD,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"SYRD\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(22+(CELL_PIXEL_W/2), ((CELL_PIXEL_H*2)-(CELL_PIXEL_H/2))),\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_VESSELTYPE,\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)ListSPen,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListSPen\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassSubPen(\n\tSTRUCT_SUB_PEN,\n\tTXT_SUB_PEN,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"SPEN\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(22+(CELL_PIXEL_W/2), ((CELL_PIXEL_H*2)-(CELL_PIXEL_H/2))),\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_VESSELTYPE,\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\t(short const *)ExitSub,\t\t// Preferred exit cell list.\n\t(short const *)ListSPen,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListSPen\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassPillbox(\n\tSTRUCT_PILLBOX,\n\tTXT_PILLBOX,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"PBOX\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0010,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0040,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassCamoPillbox(\n\tSTRUCT_CAMOPILLBOX,\n\tTXT_CAMOPILLBOX,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"HBOX\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0010,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0040,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassTesla(\n\tSTRUCT_TESLA,\n\tTXT_TESLA,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"TSLA\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x00C8,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_12, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List12,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OList12\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassTurret(\n\tSTRUCT_TURRET,\n\tTXT_TURRET,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"GUN\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0030,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0080,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\ttrue,\t\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\t(DirType)208,\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassAAGun(\n\tSTRUCT_AAGUN,\n\tTXT_AAGUN,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"AGUN\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\ttrue,\t\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_NE,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_12, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List12,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OList12\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassFlameTurret(\n\tSTRUCT_FLAME_TURRET,\n\tTXT_FLAME_TURRET,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"FTUR\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassConst(\n\tSTRUCT_CONST,\n\tTXT_CONST_YARD,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"FACT\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_BUILDINGTYPE,\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)ListFactory,// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassFakeConst(\n\tSTRUCT_FAKECONST,\n\tTXT_FAKE_CONST,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"FACF\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)ListFactory,// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassFakeWeapon(\n\tSTRUCT_FAKEWEAP,\n\tTXT_FAKE_WEAP,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"WEAF\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(10+(CELL_PIXEL_W/2), ((CELL_PIXEL_H*3)-(CELL_PIXEL_H/2))-21),\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_32, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\t(short const *)ExitWeap,\t// Preferred exit cell list.\n\t(short const *)ListWeap,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListWeap\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassRefinery(\n\tSTRUCT_REFINERY,\n\tTXT_REFINERY,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"PROC\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List010111100,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List101000011\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassStorage(\n\tSTRUCT_STORAGE,\n\tTXT_STORAGE,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"SILO\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)StoreList,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassHelipad(\n\tSTRUCT_HELIPAD,\n\tTXT_HELIPAD,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"HPAD\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_AIRCRAFTTYPE,\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List2,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassCommand(\n\tSTRUCT_RADAR,\n\tTXT_COMMAND,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"DOME\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)ComList,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassGapGenerator(\n\tSTRUCT_GAP,\n\tTXT_GAP_GENERATOR,\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"GAP\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_12, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List0010,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List1\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassSAM(\n\tSTRUCT_SAM,\n\tTXT_SAM,\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"SAM\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0030,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0080,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\ttrue,\t\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List21,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListSAM\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassMissileSilo(\n\tSTRUCT_MSLO,\n\tTXT_MSLO,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"MSLO\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List21,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListSAM\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassAirStrip(\n\tSTRUCT_AIRSTRIP,\n\tTXT_AIRSTRIP,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"AFLD\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_AIRCRAFTTYPE,\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_32, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List32,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassPower(\n\tSTRUCT_POWER,\n\tTXT_POWER,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"POWR\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List22,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List22_1100\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassAdvancedPower(\n\tSTRUCT_ADVANCED_POWER,\n\tTXT_ADVANCED_POWER,\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"APWR\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List000111111,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListTmpl\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassSovietTech(\n\tSTRUCT_SOVIET_TECH,\n\tTXT_SOVIET_TECH,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"STEK\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List000111111,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListTmpl\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassHospital(\n\tSTRUCT_HOSPITAL,\n\tTXT_HOSPITAL,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"HOSP\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List2,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassBioLab(\n\tSTRUCT_BIO_LAB,\n\tTXT_BIO_LAB,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"BIO\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List2,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassBarracks(\n\tSTRUCT_BARRACKS,\n\tTXT_BARRACKS,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"BARR\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n//\tXYP_COORD(24,47),\t\t\t\t// Exit point for produced units.\n\tXYP_COORD(18,47),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_INFANTRYTYPE,\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\t(short const *)ExitPyle,\t// Preferred exit cell list.\n\t(short const *)List22,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\tNULL\t\t\t\t\t\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassTent(\n\tSTRUCT_TENT,\n\tTXT_BARRACKS,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"TENT\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(24,47),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_INFANTRYTYPE,\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\t(short const *)ExitPyle,\t// Preferred exit cell list.\n\t(short const *)List22,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\tNULL\t\t\t\t\t\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassKennel(\n\tSTRUCT_KENNEL,\n\tTXT_KENNEL,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"KENN\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(8,16),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_INFANTRYTYPE,\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n//\t(short const *)ExitPyle,\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\tNULL\t\t\t\t\t\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassFakeShipYard(\n\tSTRUCT_FAKE_YARD,\n\tTXT_FAKE_YARD,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"SYRF\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(22+(CELL_PIXEL_W/2), ((CELL_PIXEL_H*2)-(CELL_PIXEL_H/2))),\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\t(short const *)ExitWeap,\t// Preferred exit cell list.\n\t(short const *)ListSPen,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListSPen\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassFakeSubPen(\n\tSTRUCT_FAKE_PEN,\n\tTXT_FAKE_PEN,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"SPEF\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(22+(CELL_PIXEL_W/2), ((CELL_PIXEL_H*2)-(CELL_PIXEL_H/2))),\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\t(short const *)ExitSub,\t\t// Preferred exit cell list.\n\t(short const *)ListSPen,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListSPen\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassFakeCommand(\n\tSTRUCT_FAKE_RADAR,\n\tTXT_FAKE_RADAR,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"DOMF\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)ComList,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OComList\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassRepair(\n\tSTRUCT_REPAIR,\n\tTXT_FIX_IT,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"FIX\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)ListFix,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListFix\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV01(\n\tSTRUCT_V01,\n\tTXT_CIV1,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V01\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE: Building size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List0011,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List1100\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV02(\n\tSTRUCT_V02,\n\tTXT_CIV2,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V02\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List0011,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List1100\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV03(\n\tSTRUCT_V03,\n\tTXT_CIV3,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V03\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List0111,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List1000\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV04(\n\tSTRUCT_V04,\n\tTXT_CIV4,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V04\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List0011,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List1100\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV05(\n\tSTRUCT_V05,\n\tTXT_CIV5,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V05\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV06(\n\tSTRUCT_V06,\n\tTXT_CIV6,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V06\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV07(\n\tSTRUCT_V07,\n\tTXT_CIV7,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V07\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV08(\n\tSTRUCT_V08,\n\tTXT_CIV8,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V08\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV09(\n\tSTRUCT_V09,\n\tTXT_CIV9,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V09\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV10(\n\tSTRUCT_V10,\n\tTXT_CIV10,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V10\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV11(\n\tSTRUCT_V11,\n\tTXT_CIV11,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V11\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV12(\n\tSTRUCT_V12,\n\tTXT_CIV12,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V12\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV13(\n\tSTRUCT_V13,\n\tTXT_CIV13,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V13\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV14(\n\tSTRUCT_V14,\n\tTXT_CIV14,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V14\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV15(\n\tSTRUCT_V15,\n\tTXT_CIV15,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V15\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV16(\n\tSTRUCT_V16,\n\tTXT_CIV16,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V16\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV17(\n\tSTRUCT_V17,\n\tTXT_CIV17,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V17\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV18(\n\tSTRUCT_V18,\n\tTXT_CIV18,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V18\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV19(\n\tSTRUCT_PUMP,\n\tTXT_PUMP,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V19\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV20(\n\tSTRUCT_V20,\n\tTXT_CIV20,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V20\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List0011,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List1100\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV21(\n\tSTRUCT_V21,\n\tTXT_CIV21,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V21\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1101,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List0010\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV22(\n\tSTRUCT_V22,\n\tTXT_CIV22,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V22\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV23(\n\tSTRUCT_V23,\n\tTXT_CIV23,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V23\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV24(\n\tSTRUCT_V24,\n\tTXT_CIV24,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V24\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List0011,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List1100\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV25(\n\tSTRUCT_V25,\n\tTXT_CIV25,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V25\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List0111,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List1000\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV26(\n\tSTRUCT_V26,\n\tTXT_CIV26,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V26\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV27(\n\tSTRUCT_V27,\n\tTXT_CIV27,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V27\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV28(\n\tSTRUCT_V28,\n\tTXT_CIV28,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V28\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV29(\n\tSTRUCT_V29,\n\tTXT_CIV29,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V29\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV30(\n\tSTRUCT_V30,\n\tTXT_CIV30,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V30\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV31(\n\tSTRUCT_V31,\n\tTXT_CIV31,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V31\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV32(\n\tSTRUCT_V32,\n\tTXT_CIV32,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V32\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV33(\n\tSTRUCT_V33,\n\tTXT_CIV33,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V33\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV34(\n\tSTRUCT_V34,\n\tTXT_CIV34,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V34\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV35(\n\tSTRUCT_V35,\n\tTXT_CIV35,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V35\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV36(\n\tSTRUCT_V36,\n\tTXT_CIV36,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V36\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\nstatic BuildingTypeClass const ClassV37(\n\tSTRUCT_V37,\n\tTXT_CIV37,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V37\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_42, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)ListWestwood,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListWestwood\t// OVERLAPLIST:List of overlap cell offset.\n);\nstatic BuildingTypeClass const ClassMission(\n\tSTRUCT_MISSION,\n\tTXT_CIVMISS,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"MISS\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_32, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List32,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\n// Sandbag wall\nstatic BuildingTypeClass const Sandbag(\n\tSTRUCT_SANDBAG_WALL,\n\tTXT_SANDBAG_WALL,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"SBAG\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_NONE,\t\t\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n// Cyclone fence\nstatic BuildingTypeClass const Cyclone(\n\tSTRUCT_CYCLONE_WALL,\n\tTXT_CYCLONE_WALL,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"CYCL\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_NONE,\t\t\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n// Brick wall\nstatic BuildingTypeClass const Brick(\n\tSTRUCT_BRICK_WALL,\n\tTXT_BRICK_WALL,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"BRIK\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_NONE,\t\t\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n// Barbwire wall\nstatic BuildingTypeClass const Barbwire(\n\tSTRUCT_BARBWIRE_WALL,\n\tTXT_BARBWIRE_WALL,\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"BARB\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_NONE,\t\t\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n// Wood wall\nstatic BuildingTypeClass const Wood(\n\tSTRUCT_WOOD_WALL,\n\tTXT_WOOD_WALL,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"WOOD\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_NONE,\t\t\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\nstatic BuildingTypeClass const Fence(\n\tSTRUCT_FENCE,\n\tTXT_FENCE,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"FENC\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_NONE,\t\t\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\n\n#ifdef FIXIT_ANTS\nstatic BuildingTypeClass const ClassQueen(\n\tSTRUCT_QUEEN,\n\tTXT_NONE,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"QUEE\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(24,47),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\tNULL\t\t\t\t\t\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\nstatic BuildingTypeClass const ClassLarva1(\n\tSTRUCT_LARVA1,\n\tTXT_NONE,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"LAR1\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\nstatic BuildingTypeClass const ClassLarva2(\n\tSTRUCT_LARVA2,\n\tTXT_NONE,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"LAR2\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n#endif\nvoid const * BuildingTypeClass::WarFactoryOverlay;\nvoid const * LightningShapes;\n\n\n/***********************************************************************************************\n * BuildingTypeClass::BuildingTypeClass -- This is the constructor for the building types.     *\n *                                                                                             *\n *    This is the constructor used to create the building types.                               *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuildingTypeClass::BuildingTypeClass(\n\t\t\t\t\t\tStructType type,\n\t\t\t\t\t\tint name,\n\t\t\t\t\t\tchar const * ininame,\n\t\t\t\t\t\tFacingType foundation,\n\t\t\t\t\t\tCOORDINATE exitpoint,\n\t\t\t\t\t\tRemapType remap,\n\t\t\t\t\t\tint verticaloffset,\n\t\t\t\t\t\tint primaryoffset,\n\t\t\t\t\t\tint primarylateral,\n\t\t\t\t\t\tbool is_fake,\n\t\t\t\t\t\tbool is_regulated,\n\t\t\t\t\t\tbool is_nominal,\n\t\t\t\t\t\tbool is_wall,\n\t\t\t\t\t\tbool is_simpledamage,\n\t\t\t\t\t\tbool is_stealthy,\n\t\t\t\t\t\tbool is_selectable,\n\t\t\t\t\t\tbool is_legal_target,\n\t\t\t\t\t\tbool is_insignificant,\n\t\t\t\t\t\tbool is_theater,\n\t\t\t\t\t\tbool is_turret_equipped,\n\t\t\t\t\t\tbool is_remappable,\n\t\t\t\t\t\tRTTIType tobuild,\n\t\t\t\t\t\tDirType sframe,\n\t\t\t\t\t\tBSizeType size,\n\t\t\t\t\t\tshort const * exitlist,\n\t\t\t\t\t\tshort const * sizelist,\n\t\t\t\t\t\tshort const * overlap) :\n\t\t\t\t\t\t\t\tTechnoTypeClass(RTTI_BUILDINGTYPE,\n\t\t\t\t\t\t\t\t\t\t\t\t\tint(type),\n\t\t\t\t\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\t\t\t\t\tininame,\n\t\t\t\t\t\t\t\t\t\t\t\t\tremap,\n\t\t\t\t\t\t\t\t\t\t\t\t\tverticaloffset,\n\t\t\t\t\t\t\t\t\t\t\t\t\tprimaryoffset,\n\t\t\t\t\t\t\t\t\t\t\t\t\tprimarylateral,\n\t\t\t\t\t\t\t\t\t\t\t\t\tprimaryoffset,\n\t\t\t\t\t\t\t\t\t\t\t\t\tprimarylateral,\n\t\t\t\t\t\t\t\t\t\t\t\t\tis_nominal,\n\t\t\t\t\t\t\t\t\t\t\t\t\tis_stealthy,\n\t\t\t\t\t\t\t\t\t\t\t\t\tis_selectable,\n\t\t\t\t\t\t\t\t\t\t\t\t\tis_legal_target,\n\t\t\t\t\t\t\t\t\t\t\t\t\tis_insignificant,\n\t\t\t\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\t\t\t\tis_theater,\n\t\t\t\t\t\t\t\t\t\t\t\t\tis_turret_equipped,\n\t\t\t\t\t\t\t\t\t\t\t\t\tis_remappable,\n\t\t\t\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\t\t\t\t(is_turret_equipped ? 32 : 1),\n\t\t\t\t\t\t\t\t\t\t\t\t\tSPEED_NONE),\n\tIsBase(true),\n\tIsFake(is_fake),\n\tIsBibbed(false),\n\tIsWall(is_wall),\n\tIsSimpleDamage(is_simpledamage),\n\tIsCaptureable(false),\n\tIsRegulated(is_regulated),\n\tIsPowered(false),\n\tIsUnsellable(false),\n\tFoundationFace(foundation),\n\tAdjacent(1),\n\tToBuild(tobuild),\n\tExitCoordinate(exitpoint),\n\tExitList(exitlist),\n\tType(type),\n\tStartFace(sframe),\n\tCapacity(0),\n\tPower(0),\n\tDrain(0),\n\tSize(size),\n\tOccupyList(sizelist),\n\tOverlapList(overlap),\n\tBuildupData(0)\n{\n\n\tAnims[BSTATE_CONSTRUCTION].Start = 0;\n\tAnims[BSTATE_CONSTRUCTION].Count = 1;\n\tAnims[BSTATE_CONSTRUCTION].Rate = 0;\n\n\tAnims[BSTATE_IDLE].Start = 0;\n\tAnims[BSTATE_IDLE].Count = 1;\n\tAnims[BSTATE_IDLE].Rate = 0;\n\n\tAnims[BSTATE_ACTIVE].Start = 0;\n\tAnims[BSTATE_ACTIVE].Count = 1;\n\tAnims[BSTATE_ACTIVE].Rate = 0;\n\n\tAnims[BSTATE_AUX1].Start = 0;\n\tAnims[BSTATE_AUX1].Count = 1;\n\tAnims[BSTATE_AUX1].Rate = 0;\n\n\tAnims[BSTATE_AUX2].Start = 0;\n\tAnims[BSTATE_AUX2].Count = 1;\n\tAnims[BSTATE_AUX2].Rate = 0;\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::operator new -- Allocates a building type object from the special heap.  *\n *                                                                                             *\n *    This routine will allocate a building type object from the special heap used just for    *\n *    allocation of object of this type.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the newly allocated object. If the allocation could not  *\n *          succeed, then NULL will be returned.                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * BuildingTypeClass::operator new(size_t)\n{\n\treturn(BuildingTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::operator delete -- Deletes a building type object from the special heap. *\n *                                                                                             *\n *    This will delete a previously allocated building type object. The memory is returned     *\n *    to the special heap that is used for that purpose.                                       *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the building type object to return to the special heap.        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingTypeClass::operator delete(void * ptr)\n{\n\tBuildingTypes.Free((BuildingTypeClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Init_Heap -- Initialize the heap as necessary for the building type obje *\n *                                                                                             *\n *    This routine performs the necessary heap initializations. Since we know exactly what     *\n *    building type objects will be needed, they are pre-allocated at this time.               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine only once.                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese building type class objects must be allocated in the exact order that they\n\t**\tare specified in the StructType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew BuildingTypeClass(ClassAdvancedTech);\t// STRUCT_ADVANCED_TECH\n\tnew BuildingTypeClass(ClassIronCurtain);\t// STRUCT_IRON_CURTAIN\n\tnew BuildingTypeClass(ClassWeapon);\t\t\t//\tSTRUCT_WEAP\n\tnew BuildingTypeClass(ClassChronosphere);\t// STRUCT_CHRONOSPHERE\n\tnew BuildingTypeClass(ClassPillbox);\t\t//\tSTRUCT_PILLBOX\n\tnew BuildingTypeClass(ClassCamoPillbox);\t//\tSTRUCT_CAMOPILLBOX\n\tnew BuildingTypeClass(ClassCommand);\t\t//\tSTRUCT_RADAR\n\tnew BuildingTypeClass(ClassGapGenerator);\t// STRUCT_GAP\n\tnew BuildingTypeClass(ClassTurret);\t\t\t//\tSTRUCT_TURRET\n\tnew BuildingTypeClass(ClassAAGun);\t\t\t// STRUCT_AAGUN\n\tnew BuildingTypeClass(ClassFlameTurret);\t//\tSTRUCT_FLAME_TURRET\n\tnew BuildingTypeClass(ClassConst);\t\t\t//\tSTRUCT_CONST\n\tnew BuildingTypeClass(ClassRefinery);\t\t//\tSTRUCT_REFINERY\n\tnew BuildingTypeClass(ClassStorage);\t\t//\tSTRUCT_STORAGE\n\tnew BuildingTypeClass(ClassHelipad);\t\t//\tSTRUCT_HELIPAD\n\tnew BuildingTypeClass(ClassSAM);\t\t\t\t//\tSTRUCT_SAM\n\tnew BuildingTypeClass(ClassAirStrip);\t\t//\tSTRUCT_AIRSTRIP\n\tnew BuildingTypeClass(ClassPower);\t\t\t//\tSTRUCT_POWER\n\tnew BuildingTypeClass(ClassAdvancedPower);//\tSTRUCT_ADVANCED_POWER\n\tnew BuildingTypeClass(ClassSovietTech);\t// STRUCT_SOVIET_TECH\n\tnew BuildingTypeClass(ClassHospital);\t\t//\tSTRUCT_HOSPITAL\n\tnew BuildingTypeClass(ClassBarracks);\t\t//\tSTRUCT_BARRACKS\n\tnew BuildingTypeClass(ClassTent);\t\t\t//\tSTRUCT_TENT\n\tnew BuildingTypeClass(ClassKennel);\t\t\t// STRUCT_KENNEL\n\tnew BuildingTypeClass(ClassRepair);\t\t\t//\tSTRUCT_REPAIR\n\tnew BuildingTypeClass(ClassBioLab);\t\t\t//\tSTRUCT_BIO_LAB\n\tnew BuildingTypeClass(ClassMission);\t\t//\tSTRUCT_MISSION\n\tnew BuildingTypeClass(ClassShipYard);\t\t//\tSTRUCT_SHIP_YARD\n\tnew BuildingTypeClass(ClassSubPen);\t\t\t//\tSTRUCT_SUB_PEN\n\tnew BuildingTypeClass(ClassMissileSilo);\t// STRUCT_MSLO\n\tnew BuildingTypeClass(ClassForwardCom);\t// STRUCT_FORWARD_COM\n\tnew BuildingTypeClass(ClassTesla);\t\t\t//\tSTRUCT_TESLA\n\tnew BuildingTypeClass(ClassFakeWeapon);\t// STRUCT_FAKEWEAP\n\tnew BuildingTypeClass(ClassFakeConst);\t\t// STRUCT_FAKECONST\n\tnew BuildingTypeClass(ClassFakeShipYard);\t// STRUCT_FAKE_YARD\n\tnew BuildingTypeClass(ClassFakeSubPen);\t// STRUCT_FAKE_PEN\n\tnew BuildingTypeClass(ClassFakeCommand);\t// STRUCT_FAKE_RADAR\n\tnew BuildingTypeClass(Sandbag);\t\t\t\t// STRUCT_SANDBAG_WALL\n\tnew BuildingTypeClass(Cyclone);\t\t\t\t//\tSTRUCT_CYCLONE_WALL\n\tnew BuildingTypeClass(Brick);\t\t\t\t\t// STRUCT_BRICK_WALL\n\tnew BuildingTypeClass(Barbwire);\t\t\t\t// STRUCT_BARBWIRE_WALL\n\tnew BuildingTypeClass(Wood);\t\t\t\t\t//\tSTRUCT_WOOD_WALL\n\tnew BuildingTypeClass(Fence);\t\t\t\t\t// STRUCT_FENCE\n\tnew BuildingTypeClass(ClassAVMine);\t\t\t// STRUCT_AVMINE\n\tnew BuildingTypeClass(ClassAPMine);\t\t\t// STRUCT_APMINE\n\tnew BuildingTypeClass(ClassV01);\t\t\t\t//\tSTRUCT_V1\n\tnew BuildingTypeClass(ClassV02);\t\t\t\t//\tSTRUCT_V2\n\tnew BuildingTypeClass(ClassV03);\t\t\t\t//\tSTRUCT_V3\n\tnew BuildingTypeClass(ClassV04);\t\t\t\t//\tSTRUCT_V4\n\tnew BuildingTypeClass(ClassV05);\t\t\t\t//\tSTRUCT_V5\n\tnew BuildingTypeClass(ClassV06);\t\t\t\t//\tSTRUCT_V6\n\tnew BuildingTypeClass(ClassV07);\t\t\t\t//\tSTRUCT_V7\n\tnew BuildingTypeClass(ClassV08);\t\t\t\t//\tSTRUCT_V8\n\tnew BuildingTypeClass(ClassV09);\t\t\t\t//\tSTRUCT_V9\n\tnew BuildingTypeClass(ClassV10);\t\t\t\t//\tSTRUCT_V10\n\tnew BuildingTypeClass(ClassV11);\t\t\t\t//\tSTRUCT_V11\n\tnew BuildingTypeClass(ClassV12);\t\t\t\t//\tSTRUCT_V12\n\tnew BuildingTypeClass(ClassV13);\t\t\t\t//\tSTRUCT_V13\n\tnew BuildingTypeClass(ClassV14);\t\t\t\t//\tSTRUCT_V14\n\tnew BuildingTypeClass(ClassV15);\t\t\t\t//\tSTRUCT_V15\n\tnew BuildingTypeClass(ClassV16);\t\t\t\t//\tSTRUCT_V16\n\tnew BuildingTypeClass(ClassV17);\t\t\t\t//\tSTRUCT_V17\n\tnew BuildingTypeClass(ClassV18);\t\t\t\t//\tSTRUCT_V18\n\tnew BuildingTypeClass(ClassV19);\t\t\t\t//\tSTRUCT_PUMP\n\tnew BuildingTypeClass(ClassV20);\t\t\t\t//\tSTRUCT_V20\n\tnew BuildingTypeClass(ClassV21);\t\t\t\t//\tSTRUCT_V21\n\tnew BuildingTypeClass(ClassV22);\t\t\t\t//\tSTRUCT_V22\n\tnew BuildingTypeClass(ClassV23);\t\t\t\t//\tSTRUCT_V23\n\tnew BuildingTypeClass(ClassV24);\t\t\t\t//\tSTRUCT_V24\n\tnew BuildingTypeClass(ClassV25);\t\t\t\t//\tSTRUCT_V25\n\tnew BuildingTypeClass(ClassV26);\t\t\t\t//\tSTRUCT_V26\n\tnew BuildingTypeClass(ClassV27);\t\t\t\t//\tSTRUCT_V27\n\tnew BuildingTypeClass(ClassV28);\t\t\t\t//\tSTRUCT_V28\n\tnew BuildingTypeClass(ClassV29);\t\t\t\t//\tSTRUCT_V29\n\tnew BuildingTypeClass(ClassV30);\t\t\t\t//\tSTRUCT_V30\n\tnew BuildingTypeClass(ClassV31);\t\t\t\t//\tSTRUCT_V31\n\tnew BuildingTypeClass(ClassV32);\t\t\t\t//\tSTRUCT_V32\n\tnew BuildingTypeClass(ClassV33);\t\t\t\t//\tSTRUCT_V33\n\tnew BuildingTypeClass(ClassV34);\t\t\t\t//\tSTRUCT_V34\n\tnew BuildingTypeClass(ClassV35);\t\t\t\t//\tSTRUCT_V35\n\tnew BuildingTypeClass(ClassV36);\t\t\t\t//\tSTRUCT_V36\n\tnew BuildingTypeClass(ClassV37);\t\t\t\t//\tSTRUCT_V37\n\tnew BuildingTypeClass(ClassBarrel);\t\t\t// STRUCT_BARREL\n\tnew BuildingTypeClass(ClassBarrel3);\t\t// STRUCT_BARREL3\n\n#ifdef FIXIT_ANTS\n\tnew BuildingTypeClass(ClassQueen);\t\t\t// STRUCT_QUEEN\n\tnew BuildingTypeClass(ClassLarva1);\t\t\t// STRUCT_LARVA1\n\tnew BuildingTypeClass(ClassLarva2);\t\t\t// STRUCT_LARVA2\n#endif\n\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::One_Time -- Performs special one time action for buildings.              *\n *                                                                                             *\n *    This routine is used to do the one time action necessary to handle building type class   *\n *    objects. This entails loading of the building shapes and the brain file used by          *\n *    buildings.                                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine should only be called ONCE.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *   06/11/1994 JLB : Updated construction time and frame count logic.                         *\n *=============================================================================================*/\nvoid BuildingTypeClass::One_Time(void)\n{\n\tstatic const struct {\n\t\tStructType\tClass;\t\t\t// Building class number.\n\t\tBStateType\tStage;\t\t\t// Animation sequence to assign animation range to.\n\t\tint\t\t\tStart;\t\t\t// Starting frame number.\n\t\tint\t\t\tLength;\t\t\t// Number of frames (-1 means use all frames).\n\t\tint\t\t\tRate;\t\t\t\t// Rate of animation.\n\t} _anims[] = {\n\t\t{STRUCT_CHRONOSPHERE,\tBSTATE_IDLE,\t0, 4, 3},\t// idling\n\t\t{STRUCT_CHRONOSPHERE,\tBSTATE_ACTIVE,\t4, 16,3},\t// charging up and activating\n\t\t{STRUCT_MSLO,\t\t\t\tBSTATE_IDLE,\t0, 0, 0},\n\t\t{STRUCT_MSLO,\t\t\t\tBSTATE_ACTIVE,\t0, 5, 2},\t// door opening\n\t\t{STRUCT_MSLO,\t\t\t\tBSTATE_AUX1,\t4, 1, 0},\t// door held open\n\t\t{STRUCT_MSLO,\t\t\t\tBSTATE_AUX2,\t5, 3, 2},\t// door closing\n\t\t{STRUCT_CAMOPILLBOX,\t\tBSTATE_ACTIVE,\t0,\t2, 1},\n\t\t{STRUCT_GAP,\t\t\t\tBSTATE_IDLE,\t0,\t32,3},\n\t\t{STRUCT_AIRSTRIP,\t\t\tBSTATE_IDLE,\t0,\t0,\t0},\n\t\t{STRUCT_AIRSTRIP,\t\t\tBSTATE_AUX1,\t0,\t8,\t3},\n\t\t{STRUCT_BARRACKS,\t\t\tBSTATE_ACTIVE,\t0,\t10,3},\n\t\t{STRUCT_BARRACKS,\t\t\tBSTATE_IDLE,\t0,\t10,3},\n\t\t{STRUCT_TENT,\t\t\t\tBSTATE_ACTIVE,\t0,\t10,3},\n\t\t{STRUCT_TENT,\t\t\t\tBSTATE_IDLE,\t0,\t10,3},\n#ifdef FIXIT_ANTS\n\t\t{STRUCT_QUEEN,\t\t\t\tBSTATE_IDLE,\t0,\t10,3},\n#endif\n\t\t{STRUCT_CONST,\t\t\t\tBSTATE_ACTIVE,\t0,\t26,3},\n\t\t{STRUCT_FAKECONST,\t\tBSTATE_ACTIVE,\t0,\t26,3},\n\t\t{STRUCT_HELIPAD,\t\t\tBSTATE_ACTIVE,\t0,\t7,\t4},\n\t\t{STRUCT_HELIPAD,\t\t\tBSTATE_IDLE,\t0,\t0,\t0},\n\t\t{STRUCT_HOSPITAL,\t\t\tBSTATE_IDLE,\t0,\t4,\t3},\n\t\t{STRUCT_PUMP,\t\t\t\tBSTATE_IDLE,\t0,\t14,4},\n\t\t{STRUCT_REPAIR,\t\t\tBSTATE_ACTIVE,\t0,\t7,\t2},\n\t\t{STRUCT_REPAIR,\t\t\tBSTATE_IDLE,\t0,\t1,\t0},\n\t\t{STRUCT_V20,\t\t\t\tBSTATE_IDLE,\t0,\t3,\t3},\n\t\t{STRUCT_V21,\t\t\t\tBSTATE_IDLE,\t0,\t3,\t3},\n\t\t{STRUCT_V22,\t\t\t\tBSTATE_IDLE,\t0,\t3,\t3},\n\t\t{STRUCT_V23,\t\t\t\tBSTATE_IDLE,\t0,\t3,\t3},\n\t\t{STRUCT_WEAP,\t\t\t\tBSTATE_ACTIVE,\t0,\t1,\t0},\n\t\t{STRUCT_WEAP,\t\t\t\tBSTATE_IDLE,\t0,\t1,\t0},\n\t\t{STRUCT_FAKEWEAP,\t\t\tBSTATE_ACTIVE,\t0,\t1,\t0},\n\t\t{STRUCT_FAKEWEAP,\t\t\tBSTATE_IDLE,\t0,\t1,\t0},\n\t\t{STRUCT_IRON_CURTAIN,\tBSTATE_ACTIVE,\t0,\t11,3},\n\t\t{STRUCT_TESLA,\t\t\t\tBSTATE_ACTIVE,\t0,\t10,2},\n\t};\n\n\tfor (StructType sindex = STRUCT_FIRST; sindex < STRUCT_COUNT; sindex++) {\n\t\tchar\tfullname[_MAX_FNAME+_MAX_EXT];\n\t\tchar\tbuffer[_MAX_FNAME];\n\t\tBuildingTypeClass const & building = As_Reference(sindex);\n\t\t/*\n\t\t**\tFetch the sidebar cameo image for this building.\n\t\t*/\n\t\tif (building.Level != -1) {\n//\t\tif (building.IsBuildable) {\n\t\t\tsprintf(buffer, \"%sICON\", building.Graphic_Name());\n\n\t\t\tif (building.IsFake) {\n\t\t\t\tbuffer[3] = 'F';\n\t\t\t}\n\n\t\t\t_makepath(fullname, NULL, NULL, buffer, \".SHP\");\n\t\t\t((void const *&)building.CameoData) = MFCD::Retrieve(fullname);\n\t\t}\n\n\t\t/*\n\t\t**\tFetch the construction animation for this building.\n\t\t*/\n\t\tsprintf(buffer, \"%sMAKE\", building.Graphic_Name());\n\t\t_makepath(fullname, NULL, NULL, buffer, \".SHP\");\n\t\tvoid const * dataptr;\n\t\tdataptr = MFCD::Retrieve(fullname);\n\t\t((void const *&)building.BuildupData) = dataptr;\n\t\tif (dataptr != NULL) {\n\t\t\tint timedelay = 1;\n\t\t\tint count = Get_Build_Frame_Count(dataptr);\n\t\t\tif (count > 0) {\n\t\t\t\ttimedelay = (Rule.BuildupTime * TICKS_PER_MINUTE) / count;\n\t\t\t}\n\t\t\tbuilding.Init_Anim(BSTATE_CONSTRUCTION, 0, count, timedelay);\n\t\t}\n\n\t\t/*\n\t\t**\tFetch the normal game shape for this building.\n\t\t*/\n\t\t_makepath(fullname, NULL, NULL, building.Graphic_Name(), \".SHP\");\n\t\t((void const *&)building.ImageData) = MFCD::Retrieve(fullname);\n\t}\n\n\t// Try to load weap2.shp and tesla coil's lightning shapes\n\tchar fullname[_MAX_FNAME+_MAX_EXT];\n\t_makepath(fullname, NULL, NULL, (char const *)\"WEAP2\",\".SHP\");\n\tWarFactoryOverlay = MFCD::Retrieve(fullname);\n\t_makepath(fullname, NULL, NULL, (char const *)\"LITNING\",\".SHP\");\n\tLightningShapes = MFCD::Retrieve(fullname);\n\n\t/*\n\t**\tInstall all the special animation sequences for the different building types.\n\t*/\n\tfor (unsigned index = 0; index < (sizeof(_anims) / sizeof(_anims[0])); index++) {\n\t\tAs_Reference(_anims[index].Class).Init_Anim(_anims[index].Stage, _anims[index].Start, _anims[index].Length, _anims[index].Rate);\n\t}\n\n}\n\n\n/***********************************************************************************************\n * Struct_From_Name -- Find BData structure from its name.                                     *\n *                                                                                             *\n *    This routine will convert an ASCII name for a building class into                        *\n *    the actual building class it represents.                                                 *\n *                                                                                             *\n * INPUT:   name  -- ASCII representation of a building class.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the actual building class number that the string                      *\n *          represents.                                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *   05/02/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nStructType BuildingTypeClass::From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (StructType classid = STRUCT_FIRST; classid < STRUCT_COUNT; classid++) {\n\t\t\tif (stricmp(As_Reference(classid).IniName, name) == 0) {\n\t\t\t\treturn(classid);\n\t\t\t}\n\t\t}\n\t}\n\treturn(STRUCT_NONE);\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***********************************************************************************************\n * BuildingTypeClass::Display -- Renders a generic view of building.                           *\n *                                                                                             *\n *    This routine is used to display a generic representation of the                          *\n *    building. Typical use of this occurs with the scenario editor.                           *\n *                                                                                             *\n * INPUT:   x,y      -- Coordinate to display the building (centered).                         *\n *                                                                                             *\n *          window   -- The window the building should be rendered                             *\n *                      relative to.                                                           *\n *                                                                                             *\n *          house    -- The house color to use for the building.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingTypeClass::Display(int x, int y, WindowNumberType window, HousesType ) const\n{\n\tvoid const * ptr = Get_Cameo_Data();\n\tif (ptr == NULL) {\n\t\tIsTheaterShape = IsTheater;\n\t\tptr = Get_Image_Data();\n\t}\n\tCC_Draw_Shape(ptr, 0, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL);\n\tIsTheaterShape = false;\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Prep_For_Add -- Prepares scenario editor for adding a                    *\n *                                                                                             *\n *    This routine is used to prepare the scenario editor for the addition                     *\n *    of a building object to the game.                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *   06/04/1994 JLB : Uses map editing interface routines.                                     *\n *=============================================================================================*/\nvoid BuildingTypeClass::Prep_For_Add(void)\n{\n\tfor (StructType index = STRUCT_FIRST; index < STRUCT_COUNT; index++) {\n\t\tif (As_Reference(index).Get_Image_Data()) {\n\t\t\tMap.Add_To_List(&As_Reference(index));\n\t\t}\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Create_And_Place -- Creates and places a building object onto the map.   *\n *                                                                                             *\n *    This routine is used by the scenario editor to create and place buildings on the map.    *\n *                                                                                             *\n * INPUT:   cell     -- The cell that the building is to be placed upon.                       *\n *                                                                                             *\n *          house    -- The owner of the building.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the building successfully created and placed on the map?                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BuildingTypeClass::Create_And_Place(CELL cell, HousesType house) const\n{\n\tBuildingClass * ptr;\n\n\tptr = new BuildingClass(Type, house);\n\tif (ptr != NULL) {\n\t\treturn(ptr->Unlimbo(Cell_Coord(cell), DIR_N));\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Create_One_Of -- Creates a building of this type.                        *\n *                                                                                             *\n *    This routine will create a building object of this type. The building object is in a     *\n *    limbo state. It is presumed that the building object will be unlimboed at the correct    *\n *    place and time. Typical use is when the building is created in a factory situation       *\n *    and will be placed on the map when construction completes.                               *\n *                                                                                             *\n * INPUT:   house -- Pointer to the house that is to be the owner of the building.             *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the building. If the building could not be created       *\n *          then a NULL is returned.                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/07/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * BuildingTypeClass::Create_One_Of(HouseClass * house) const\n{\n\tHousesType htype = HOUSE_NEUTRAL;\n\tif (house != NULL) {\n\t\thtype = house->Class->House;\n\t}\n\treturn(new BuildingClass(Type, htype));\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Init_Anim -- Initialize an animation control for a building.             *\n *                                                                                             *\n *    This routine will initialize one animation control element for a                         *\n *    specified building. This modifies a \"const\" class and thus must                          *\n *    perform some strategic casting to get away with this.                                    *\n *                                                                                             *\n * INPUT:   state -- The animation state to apply these data values to.                        *\n *                                                                                             *\n *          start -- Starting frame for the building's animation.                              *\n *                                                                                             *\n *          count -- The number of frames in this animation.                                   *\n *                                                                                             *\n *          rate  -- The countdown timer between animation frames.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingTypeClass::Init_Anim(BStateType state, int start, int count, int rate) const\n{\n\t((int &)Anims[state].Start) = start;\n\t((int &)Anims[state].Count) = count;\n\t((int &)Anims[state].Rate) = rate;\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Init -- Performs theater specific initialization.                        *\n *                                                                                             *\n *    This routine is used to perform any initialization that is custom per theater.           *\n *    Typically, this is fetching the building shape data for those building types that have   *\n *    theater specific art.                                                                    *\n *                                                                                             *\n * INPUT:   theater  -- The theater to base this initialization on.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingTypeClass::Init(TheaterType theater)\n{\n\tif (theater != LastTheater) {\n\t\tchar fullname[_MAX_FNAME+_MAX_EXT];\n\n\t\tfor (StructType sindex = STRUCT_FIRST; sindex < STRUCT_COUNT; sindex++) {\n\t\t\tBuildingTypeClass const * classptr = &As_Reference(sindex);\n\n\t\t\tif (classptr->IsTheater) {\n\t\t\t\t_makepath(fullname, NULL, NULL, classptr->Graphic_Name(), Theaters[theater].Suffix);\n\t\t\t\t((void const *&)classptr->ImageData) = MFCD::Retrieve(fullname);\n\n\t\t\t\t/*\n\t\t\t\t**\tBuildup data is probably theater specific as well. Fetch a pointer to the\n\t\t\t\t**\tdata at this time as well.\n\t\t\t\t*/\n\t\t\t\tsprintf(fullname, \"%sMAKE.%s\", classptr->Graphic_Name(), Theaters[theater].Suffix);\n\t\t\t\t((void const *&)classptr->BuildupData) = MFCD::Retrieve(fullname);\n\t\t\t\tif (classptr->BuildupData) {\n\t\t\t\t\tint timedelay = 1;\n\t\t\t\t\tint count = Get_Build_Frame_Count(classptr->BuildupData);\n\t\t\t\t\tif (count != 0) {\n\t\t\t\t\t\ttimedelay = (5 * TICKS_PER_SECOND) / count;\n\t\t\t\t\t}\n\t\t\t\t\tclassptr->Init_Anim(BSTATE_CONSTRUCTION, 0, count, timedelay);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Dimensions -- Fetches the pixel dimensions of the building.              *\n *                                                                                             *\n *    This routine will fetch the dimensions of the building (in pixels). These dimensions are *\n *    used to render the selection rectangle and the health bar.                               *\n *                                                                                             *\n * INPUT:   width    -- Reference to the pixel width (to be filled in).                        *\n *                                                                                             *\n *          height   -- Reference to the pixel height (to be filled in).                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingTypeClass::Dimensions(int &width, int &height) const\n{\n\twidth = Width() * ICON_PIXEL_W;\n\twidth -= (width/5);\n\theight = Height() * ICON_PIXEL_H;\n\theight -= (height/5);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::As_Reference -- Fetches reference to the building type specified.        *\n *                                                                                             *\n *    This routine will fetch a reference to the BuildingTypeClass as indicated by the         *\n *    building type number specified.                                                          *\n *                                                                                             *\n * INPUT:   type  -- The building type number to convert into a BuildingTypeClass reference.   *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the building type class as indicated by the            *\n *          parameter.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuildingTypeClass & BuildingTypeClass::As_Reference(StructType type)\n{\n\treturn(*BuildingTypes.Ptr(type));\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Occupy_List -- Fetches the occupy list for the building.                 *\n *                                                                                             *\n *    Use this routine to fetch the occupy list pointer for the building. The occupy list is   *\n *    used to determine what cells the building occupies and thus precludes other buildings    *\n *    or objects from using.                                                                   *\n *                                                                                             *\n * INPUT:   placement   -- Is this for placement legality checking only? The normal condition  *\n *                         is for marking occupation flags.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a cell offset list to be used to determine what cells    *\n *          this building occupies.                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * BuildingTypeClass::Occupy_List(bool placement) const\n{\n\tSmudgeType bib = SMUDGE_NONE;\n\tCELL cell=0;\n\n\tif (placement && Bib_And_Offset(bib, cell)) {\n\n\t\tSmudgeTypeClass const & smudge = SmudgeTypeClass::As_Reference(bib);\n\t\tstatic short _list[25];\n\t\tshort * dest = &_list[0];\n\n\t\t/*\n\t\t**\tCopy the bib overlap list into the working buffer.\n\t\t*/\n\t\tshort const * src = smudge.Occupy_List();\n\t\twhile (*src != REFRESH_EOL) {\n\t\t\t*dest++ = (*src++) + cell;\n\t\t}\n\n\t\t/*\n\t\t**\tAppend the building occupy list to this working buffer.\n\t\t*/\n\t\tsrc = OccupyList;\n\t\twhile (src && *src != REFRESH_EOL) {\n\t\t\t*dest++ = *src++;\n\t\t}\n\t\t*dest = REFRESH_EOL;\n\n\t\treturn(&_list[0]);\n\t}\n\n\tif (OccupyList != NULL) {\n\t\treturn(OccupyList);\n\t}\n\n\tstatic short const _templap[] = {REFRESH_EOL};\n\treturn(&_templap[0]);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Overlap_List -- Fetches the overlap list for the building.               *\n *                                                                                             *\n *    This routine will fetch the overlap list for the building. The overlap list is used      *\n *    to determine what cells the building's graphics cover, but is not considered to occupy   *\n *    for movement purposes.                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the cell offset list that is used to determine the       *\n *          cells that this building overlaps.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * BuildingTypeClass::Overlap_List(void) const\n{\n\tif (OverlapList != NULL) {\n\t\treturn(OverlapList);\n\t}\n\n\tstatic short const _templap[] = {REFRESH_EOL};\n\treturn(&_templap[0]);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Width -- Determines width of building in icons.                          *\n *                                                                                             *\n *    Use this routine to determine the width of the building type in icons.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the building width in icons.                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingTypeClass::Width(void) const\n{\n\tstatic int width[BSIZE_COUNT] = {\n\t\t1,\n\t\t2,\n\t\t1,\n\t\t2,\n\t\t2,\n\t\t3,\n\t\t3,\n\t\t4,\n\t\t5\n\t};\n\treturn(width[Size]);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Height -- Determines the height of the building in icons.                *\n *                                                                                             *\n *    Use this routine to find the height of the building in icons.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the building height in icons.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingTypeClass::Height(bool bib) const\n{\n\tstatic int height[BSIZE_COUNT] = {\n\t\t1,\n\t\t1,\n\t\t2,\n\t\t2,\n\t\t3,\n\t\t2,\n\t\t3,\n\t\t2,\n\t\t5\n\t};\n\treturn(height[Size] + ((bib && IsBibbed) ? 1 : 0));\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Bib_And_Offset -- Determines the bib and appropriate cell offset.        *\n *                                                                                             *\n *    This routine is used to determine what (if any) bib should be used for this building     *\n *    and also the cell offset for the upper left corner of the bib smudge type.               *\n *                                                                                             *\n * INPUT:   bib   -- Reference to the bib that should be used for this building.               *\n *                                                                                             *\n *          cell  -- The cell offset for the upper left corner of the bib. This offset is      *\n *                   relative to the upper left corner of the building.                        *\n *                                                                                             *\n * OUTPUT:  Is a bib required for this building? If the result is true, then the correct       *\n *          bib and cell offset will be filled in.                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BuildingTypeClass::Bib_And_Offset(SmudgeType & bib, CELL & cell) const\n{\n\tbib = SMUDGE_NONE;\n\n\tif (IsBibbed) {\n\t\tswitch (Width()) {\n\t\t\tcase 2:\n\t\t\t\tbib = SMUDGE_BIB3;\n\t\t\t\tbreak;\n\n\t\t\tcase 3:\n\t\t\t\tbib = SMUDGE_BIB2;\n\t\t\t\tbreak;\n\n\t\t\tcase 4:\n\t\t\t\tbib = SMUDGE_BIB1;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbib = SMUDGE_NONE;\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tAdjust the bib position for special buildings that have the bib as part\n\t\t**\tof the building art itself.\n\t\t*/\n\t\tif (bib != SMUDGE_NONE) {\n\t\t\tcell += ((Height()-1)*MAP_CELL_W);\n\t\t}\n\t}\n\treturn(bib != SMUDGE_NONE);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Max_Pips -- Determines the maximum pips to display.                      *\n *                                                                                             *\n *    Use this routine to determine the maximum number of pips to display on this building     *\n *    when it is rendered. Typically, this is the tiberium capacity divided by 100.            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of pips to display on this building when selected.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingTypeClass::Max_Pips(void) const\n{\n\tint maxpips = (Width() * ICON_PIXEL_W) / 4;\n\treturn(Bound((int)(Capacity/100), 0, maxpips));\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Raw_Cost -- Fetches the raw (base) cost of this building type.           *\n *                                                                                             *\n *    This routine is used to fetch the real raw base cost of the building. The raw cost       *\n *    is the cost of the building less any free unit that would come with the building         *\n *    if it were built in the normal fashion. Specifically, the helicopter cost is subtracted  *\n *    from the helipad and the harvester cost is subtracted from the refinery. This cost       *\n *    is used for refunding.                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the raw (base) cost to build the building of this type.                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingTypeClass::Raw_Cost(void) const\n{\n\tint cost = TechnoTypeClass::Raw_Cost();\n\n\tif (Type == STRUCT_HELIPAD && !Rule.IsSeparate) {\n\t\tcost -= (AircraftTypeClass::As_Reference(AIRCRAFT_HIND).Cost + AircraftTypeClass::As_Reference(AIRCRAFT_HIND).Cost)/2;\n\t}\n\tif (Type == STRUCT_REFINERY) {\n\t\tcost -= UnitTypeClass::As_Reference(UNIT_HARVESTER).Cost;\n\t}\n\treturn(cost);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Cost_Of -- Fetches the cost of this building.                            *\n *                                                                                             *\n *    This routine will fetch the cost to build the building of this type.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the cost to produce this building.                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingTypeClass::Cost_Of(void) const\n{\n\tif (Rule.IsSeparate && Type == STRUCT_HELIPAD) {\n\t\treturn(Raw_Cost());\n\t}\n\treturn(TechnoTypeClass::Cost_Of());\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Flush_For_Placement -- Tries to clear placement area for this building t *\n *                                                                                             *\n *    This routine is called when a clear space for placement is desired at the cell location  *\n *    specified. Typical use of this routine is by the computer when it wants to build up      *\n *    its base.                                                                                *\n *                                                                                             *\n * INPUT:   cell  -- The cell that the building of this type would like to be placed down at.  *\n *                                                                                             *\n *          house -- Pointer to the house that want to clear the foundation zone.              *\n *                                                                                             *\n * OUTPUT:  Placement is temporarily blocked, please try again later?                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BuildingTypeClass::Flush_For_Placement(CELL cell, HouseClass * house)  const\n{\n\tbool again = false;\n\tif (cell > 0) {\n\t\tshort const * list = Occupy_List(true);\n\n\t\twhile (*list != REFRESH_EOL) {\n\t\t\tCELL newcell = cell + *list++;\n\n\t\t\tif (Map.In_Radar(newcell)) {\n\t\t\t\tTechnoClass * occupier = Map[newcell].Cell_Techno();\n\t\t\t\tif (occupier != NULL) {\n\t\t\t\t\tagain = true;\n\t\t\t\t\tif (occupier->House->Is_Ally(house) && occupier->Is_Foot() && !Target_Legal(((FootClass *)occupier)->NavCom)) {\n\t\t\t\t\t\tMap[newcell].Incoming(0, true);\n\t\t\t\t\t} else {\n//\t\t\t\t\t\tBase_Is_Attacked(occupier);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(again);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Read_INI -- Fetch building type data from the INI database.              *\n *                                                                                             *\n *    This routine will fetch the building type class data from the INI database file.         *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database that will be examined.                      *\n *                                                                                             *\n * OUTPUT:  bool; Was the building entry found and the data extracted?                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BuildingTypeClass::Read_INI(CCINIClass & ini)\n{\n\tif (TechnoTypeClass::Read_INI(ini)) {\n\t\tSpeed = ini.Get_Bool(Name(), \"WaterBound\", (Speed == SPEED_FLOAT)) ? SPEED_FLOAT : SPEED_NONE;\n\t\tCapacity = ini.Get_Int(Name(), \"Storage\", Capacity);\n\t\tAdjacent = ini.Get_Int(Name(), \"Adjacent\", Adjacent);\n\t\tIsCaptureable = ini.Get_Bool(Name(), \"Capturable\", IsCaptureable);\n\t\tIsPowered = ini.Get_Bool(Name(), \"Powered\", IsPowered);\n\t\tIsBibbed = ini.Get_Bool(Name(), \"Bib\", IsBibbed);\n\t\tIsUnsellable = ini.Get_Bool(Name(), \"Unsellable\", IsUnsellable);\n\t\tIsBase = ini.Get_Bool(Name(), \"BaseNormal\", IsBase);\n\t\tPower = ini.Get_Int(Name(), \"Power\", (Power > 0) ? Power : -Drain);\n\t\tif (Power < 0) {\n\t\t\tDrain = -Power;\n\t\t\tPower = 0;\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Coord_Fixup -- Adjusts coordinate to be legal for assignment.            *\n *                                                                                             *\n *    This routine will adjust the specified coordinate so that it will be legal for assignment*\n *    to this building. All buildings are given a coordinate that is in the upper left corner  *\n *    of a cell. This routine will drop the fractional component of the coordinate.            *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to fixup into a legal to assign value.                     *\n *                                                                                             *\n * OUTPUT:  Returns with a coordinate that can be assigned to the building.                    *\n *                                                                                             *\n * WARNINGS:   The coordinate is not examined to see if the cell is legal for placing the      *\n *             building. It merely adjusts the coordinate so that is legal at first glance.    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE BuildingTypeClass::Coord_Fixup(COORDINATE coord) const\n{\n\treturn Coord_Whole(coord);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Full_Name -- Fetches the name to give this building.                     *\n *                                                                                             *\n *    This routine will return the displayable given name for this building type. Normally,    *\n *    this is the official name as well, however in the case of civilian buildings, the        *\n *    name will just be \"Civilian Building\" unless special options are in place.               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the text number of the building type.                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingTypeClass::Full_Name(void) const\n{\n\tif (Debug_Map || Rule.IsNamed || *this < STRUCT_V01 || *this > STRUCT_V37) {\n\t\treturn(TechnoTypeClass::Full_Name());\n\t}\n\treturn(TXT_CIVILIAN_BUILDING);\n}\n"
  },
  {
    "path": "CODE/BENCH.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BENCH.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BENCH.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/17/96                                                     *\n *                                                                                             *\n *                  Last Update : July 18, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Benchmark::Begin -- Start the benchmark operation.                                        *\n *   Benchmark::Benchmark -- Constructor for the benchmark object.                             *\n *   Benchmark::End -- Mark the end of a benchmarked operation                                 *\n *   Benchmark::Reset -- Clear out the benchmark statistics.                                   *\n *   Benchmark::Value -- Fetch the current average benchmark time.                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"bench.h\"\n#include\t\"mpu.h\"\n\n\n/***********************************************************************************************\n * Benchmark::Benchmark -- Constructor for the benchmark object.                               *\n *                                                                                             *\n *    This will construct the benchmark object.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBenchmark::Benchmark(void) :\n\tAverage(0),\n\tCounter(0),\n\tTotalCount(0)\n{\n}\n\n\n/***********************************************************************************************\n * Benchmark::Reset -- Clear out the benchmark statistics.                                     *\n *                                                                                             *\n *    Use this routine to clear out all the accumulated statistics within this benchmark       *\n *    object. The object is set just as if it was freshly constructed.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Benchmark::Reset(void)\n{\n\tAverage = 0;\n\tCounter = 0;\n\tTotalCount = 0;\n}\n\n\n/***********************************************************************************************\n * Benchmark::Begin -- Start the benchmark operation.                                          *\n *                                                                                             *\n *    Call this routine before the operation to be benchmarked is begun. The corresponding     *\n *    End() function must be called after the operation has completed.                         *\n *                                                                                             *\n * INPUT:   reset -- Should the entire benchmark object be reset at this time as well?         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The Begin() and End() functions are NOT nestable.                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Benchmark::Begin(bool reset)\n{\n\tif (reset) Reset();\n\tClock = 0;\n}\n\n\n/***********************************************************************************************\n * Benchmark::End -- Mark the end of a benchmarked operation                                   *\n *                                                                                             *\n *    This routine is called at the end of the operation that is being benchmarked. It is      *\n *    important to call this routine as soon as possible after the event being benchmarked     *\n *    has completed.                                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The Being() and End() functions are NOT nestable.                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Benchmark::End(void)\n{\n\tunsigned long value = Clock;\n\n\tif (Counter == MAXIMUM_EVENT_COUNT) {\n\t\tAverage -= Average / MAXIMUM_EVENT_COUNT;\n\t\tAverage += value;\n\t} else {\n\t\tAverage += value;\n\t\tCounter++;\n\t}\n\tTotalCount++;\n}\n\n\n/***********************************************************************************************\n * Benchmark::Value -- Fetch the current average benchmark time.                               *\n *                                                                                             *\n *    This routine will take the statistics already accumulated and determine the average      *\n *    time recorded. This value will be returned.                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the average time that all events tracked by this object.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned long Benchmark::Value(void) const\n{\n\tif (Counter) {\n\t\treturn(Average / Counter);\n\t}\n\treturn(0);\n}\n"
  },
  {
    "path": "CODE/BENCH.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BENCH.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BENCH.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/17/96                                                     *\n *                                                                                             *\n *                  Last Update : July 17, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef BENCH_H\n#define BENCH_H\n\n#include\t\"mpu.h\"\n#include\t\"ftimer.h\"\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n/*\n**\tThis is a timer access object that will fetch the internal Pentium\n**\tclock value.\n*/\nclass PentiumTimerClass\n{\n\tpublic:\n\t\tunsigned long operator () (void) const {unsigned long h;unsigned long l = Get_CPU_Clock(h);return((l >> 4) | (h << 28));}\n\t\toperator unsigned long (void) const {unsigned long h;unsigned long l = Get_CPU_Clock(h);return((l >> 4) | (h << 28));}\n};\n\n\n/*\n**\tA performance tracking tool object. It is used to track elapsed time. Unlike a simple clock, this\n**\tclass will keep a running average of the duration. Typical use of this would be to benchmark some\n**\tprocess that occurs multiple times. By benchmarking an average time, inconsistencies in a particular\n**\trun can be overcome.\n*/\nclass Benchmark\n{\n\tpublic:\n\t\tBenchmark(void);\n\n\t\tvoid Begin(bool reset=false);\n\t\tvoid End(void);\n\n\t\tvoid Reset(void);\n\t\tunsigned long Value(void) const;\n\t\tunsigned long Count(void) const {return(TotalCount);}\n\n\tprivate:\n\t\t/*\n\t\t**\tThe maximum number of events to keep running average of. If\n\t\t**\tevents exceed this number, then older events drop off the\n\t\t**\taccumulated time. This number needs to be as small as\n\t\t**\tis reasonable. The larger this number gets, the less magnitude\n\t\t**\tthat the benchmark timer can handle. Example; At a value of\n\t\t**\t256, the magnitude of the timer can only be 24 bits.\n\t\t*/\n\t\tenum {MAXIMUM_EVENT_COUNT=256};\n\n\t\t/*\n\t\t**\tThis is the timer the is used to clock the events.\n\t\t*/\n\t\tBasicTimerClass<PentiumTimerClass> Clock;\n\n\t\t/*\n\t\t**\tThe total time off all events tracked so far.\n\t\t*/\n\t\tunsigned long Average;\n\n\t\t/*\n\t\t**\tThe total number of events tracked so far.\n\t\t*/\n\t\tunsigned long Counter;\n\n\t\t/*\n\t\t**\tAbsolute total number of events (possibly greater than the\n\t\t**\tnumber of events tracked in the average).\n\t\t*/\n\t\tunsigned long TotalCount;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/BFILE.MAK",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n# $Header:   F:\\projects\\c&c0\\vcs\\code\\bfile.mav   5.0   11 Nov 1996 09:40:38   JOE_BOSTIC  $\n#***************************************************************************\n#**   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        **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Command & Conquer                        *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Joe L. Bostic                            *\n#*                                                                         *\n#*                   Start Date : March 25, 1993                           *\n#*                                                                         *\n#*                  Last Update : March 25, 1993   [JLB]                   *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n\n\n# Comment out the following line to disable \"include file autodependency\".\n.AUTODEPEND\n#.SWAP\n\n!include\t\"rules.mak\"\n\n\n##########################################################################\n\nMAPFILES = \\\n\nCACHEMAP = \\\n\tBRIEFING.AUD \\\n\tBAR3RED.SHP \\\n\tBAR3BLU.SHP \\\n\tCOUNTRYA.SHP \\\n\tCOUNTRYE.SHP \\\n\tCREDSA.SHP \\\n\tCREDSU.SHP \\\n\tHISCORE1.SHP \\\n\tHISCORE2.SHP \\\n\tTIME.SHP \\\n\tCLOCK1.AUD \\\n\tCOUNTRY4.AUD \\\n\tMAPWIPE2.AUD \\\n\tMAPWIPE5.AUD \\\n\tTONEY10.AUD \\\n\tTONEY4.AUD \\\n\tTONEY7.AUD \\\n\tSFX4.AUD \\\n\tBEEPY6.AUD \\\n\tKEYSTROK.AUD \\\n\tAPPEAR1.AUD \\\n\tSCOLD1.AUD \\\n\tCOUNTRY1.AUD \\\n\tALI-TRAN.WSA \\\n\tSOV-TRAN.WSA \\\n\tALIBACKH.PCX \\\n\tSOVBACKH.PCX \\\n\tBAR3RHR.SHP \\\n\tBAR3BHR.SHP \\\n\tCREDSAHR.SHP \\\n\tCREDSUHR.SHP \\\n\tHISC1-HR.SHP \\\n\tHISC2-HR.SHP \\\n\tTIMEHR.SHP \\\n\tMLTIPLYR.WSA \\\n\nLOCALFILES = \\\n\tPROLOG.CPS \\\n\tMAP.AUD \\\n\tTITLE.CPS \\\n\tPALETTE.CPS \\\n\tINTRO.AUD \\\n\tEGOPAL.PAL \\\n\tRULES.INI \\\n\tCREDITS.TXT \\\n\tALIPAPER.CPS \\\n\t3POINT.FNT \\\n\t8POINT.FNT \\\n\tEDITFNT.FNT \\\n\tCONQUER.ENG \\\n\tDEBUG.ENG \\\n\tLED.FNT \\\n\tSNOW.PAL \\\n\tTEMPERAT.PAL \\\n\tINTERIOR.PAL \\\n\tVCR.FNT \\\n\tHOLE0000.LUT \\\n\tHOLE0001.LUT \\\n\tHOLE0002.LUT \\\n\tHOLE0003.LUT \\\n\tHOLE0004.LUT \\\n\tHOLE0005.LUT \\\n\tHOLE0006.LUT \\\n\tHOLE0007.LUT \\\n\tHOLE0008.LUT \\\n\tHOLE0009.LUT \\\n\tHOLE0010.LUT \\\n\tHOLE0011.LUT \\\n\tHOLE0012.LUT \\\n\tHOLE0013.LUT \\\n\tHOLE0014.LUT \\\n\tHOLE0015.LUT \\\n\tHOLE0016.LUT \\\n\tHOLE0017.LUT \\\n\tHOLE0018.LUT \\\n\tHOLE0019.LUT \\\n\tHOLE0020.LUT \\\n\tHOLE0021.LUT \\\n\tHOLE0022.LUT \\\n\tHOLE0023.LUT \\\n\tHOLE0024.LUT \\\n\tHOLE0025.LUT \\\n\tHOLE0026.LUT \\\n\tHOLE0027.LUT \\\n\tHOLE0028.LUT \\\n\tHOLE0029.LUT \\\n\tHOLE0030.LUT \\\n\tHOLE0031.LUT \\\n\tHOLE0032.LUT \\\n\tHOLE0033.LUT \\\n\tHOLE0034.LUT \\\n\tHOLE0035.LUT \\\n\tHOLE0036.LUT \\\n\tHOLE0037.LUT \\\n\tHOLE0038.LUT \\\n\tHOLE0039.LUT \\\n\tHOLE0040.LUT \\\n\tHOLE0041.LUT \\\n\tHOLE0042.LUT \\\n\tHOLE0043.LUT \\\n\tHOLE0044.LUT \\\n\tHOLE0045.LUT \\\n\tHOLE0046.LUT \\\n\tHOLE0047.LUT \\\n#\tTEMPSCOR.FNT \\\n#\t6POINT.FNT \\\n#\tGRAD6FNT.FNT \\\n#\tSCOREFNT.FNT \\\n\n\n# Files that have counterparts in both high and low resolutions.\n# These files will be built into the HIRES.MIX and LORES.MIX files.\nHILORES = \\\n\tTRANICON.SHP \\\n\tPIPS.SHP \\\n\tPULSE.SHP \\\n\tATOMICON.SHP \\\n\tWARPICON.SHP \\\n\tC1.SHP \\\n\tC2.SHP \\\n\tCHAN.SHP \\\n\tDELPHI.SHP \\\n\tE1.SHP \\\n\tE2.SHP \\\n\tE3.SHP \\\n\tE4.SHP \\\n\tE5.SHP \\\n\tE6.SHP \\\n\tE7.SHP \\\n\tEINSTEIN.SHP \\\n\tGNRL.SHP \\\n\tMEDI.SHP \\\n\tSPY.SHP \\\n\tTHF.SHP \\\n\tDD-BKGND.SHP \\\n\tDD-BOTM.SHP \\\n\tDD-CRNR.SHP \\\n\tDD-EDGE.SHP \\\n\tDD-LEFT.SHP \\\n\tDD-RIGHT.SHP \\\n\tDD-TOP.SHP \\\n\t12METFNT.FNT \\\n\tGRAD6FNT.FNT \\\n\tHELP.FNT \\\n\t6POINT.FNT \\\n\tTYPE.FNT \\\n\tSCOREFNT.FNT \\\n\t1TNKICON.SHP \\\n\t2TNKICON.SHP \\\n\t3TNKICON.SHP \\\n\t4TNKICON.SHP \\\n\tAFLDICON.SHP \\\n\tAGUNICON.SHP \\\n\tAPCICON.SHP \\\n\tAPWRICON.SHP \\\n\tARTYICON.SHP \\\n\tATEKICON.SHP \\\n\tBADRICON.SHP \\\n\tBARRICON.SHP \\\n\tBRIKICON.SHP \\\n\tBTN-DN.SHP \\\n\tBTN-PL.SHP \\\n\tBTN-ST.SHP \\\n\tBTN-UP.SHP \\\n\tCAICON.SHP \\\n\tCAMICON.SHP \\\n\tCLOCK.SHP \\\n\tDDICON.SHP \\\n\tDOGICON.SHP \\\n\tDOMEICON.SHP \\\n\tDOMFICON.SHP \\\n\tE1ICON.SHP \\\n\tE2ICON.SHP \\\n\tE3ICON.SHP \\\n\tE4ICON.SHP \\\n\tE6ICON.SHP \\\n\tE7ICON.SHP \\\n\tFACFICON.SHP \\\n\tFACTICON.SHP \\\n\tFENCICON.SHP \\\n\tFIXICON.SHP \\\n\tFTURICON.SHP \\\n\tGAPICON.SHP \\\n\tGPSSICON.SHP \\\n\tGUNICON.SHP \\\n\tHARVICON.SHP \\\n\tHBOXICON.SHP \\\n\tHELIICON.SHP \\\n\tHINDICON.SHP \\\n\tHPADICON.SHP \\\n\tINFXICON.SHP \\\n\tIRONICON.SHP \\\n\tJEEPICON.SHP \\\n\tKENNICON.SHP \\\n\tLSTICON.SHP \\\n\tMAP.SHP \\\n\tMCVICON.SHP \\\n\tMEDIICON.SHP \\\n\tMGGICON.SHP \\\n\tMIGICON.SHP \\\n\tMNLYICON.SHP \\\n\tMOUSE.SHP \\\n\tMRJICON.SHP \\\n\tMSLOICON.SHP \\\n\tNATORADR.SHP \\\n\tPBMBICON.SHP \\\n\tPBOXICON.SHP \\\n\tPDOXICON.SHP \\\n\tPINFICON.SHP \\\n\tPOWER.SHP \\\n\tPOWERBAR.SHP \\\n\tPOWRICON.SHP \\\n\tPROCICON.SHP \\\n\tPTICON.SHP \\\n\tREPAIR.SHP \\\n\tSAMICON.SHP \\\n\tSBAGICON.SHP \\\n\tSELL.SHP \\\n\tSIDEBAR.SHP \\\n\tSILOICON.SHP \\\n\tSMIGICON.SHP \\\n\tSONRICON.SHP \\\n\tSOVPAPER.CPS \\\n\tSPEFICON.SHP \\\n\tSPENICON.SHP \\\n\tSPYICON.SHP \\\n\tSSICON.SHP \\\n\tSTEKICON.SHP \\\n\tSTRIP.SHP \\\n\tSTRIPDN.SHP \\\n\tSTRIPUP.SHP \\\n\tSYRDICON.SHP \\\n\tSYRFICON.SHP \\\n\tTABS.SHP \\\n\tTENTICON.SHP \\\n\tTHFICON.SHP \\\n\tTRUKICON.SHP \\\n\tTSLAICON.SHP \\\n\tU2ICON.SHP \\\n\tUSSRRADR.SHP \\\n\tV2RLICON.SHP \\\n\tWEAFICON.SHP \\\n\tWEAPICON.SHP \\\n\tYAKICON.SHP \\\n\tNRADRFRM.SHP \\\n\tURADRFRM.SHP \\\n\tSIDE1NA.SHP \\\n\tSIDE1US.SHP \\\n\tSIDE2NA.SHP \\\n\tSIDE2US.SHP \\\n\tSIDE3NA.SHP \\\n\tSIDE3US.SHP \\\n\tSTRIPNA.SHP \\\n\tSTRIPUS.SHP \\\n\n#\tMOEBICON.SHP \\\n\nHILORES1 = \\\n\tMECH.SHP \\\n\tSHOK.SHP \\\n\tCARRICON.SHP \\\n\tCTNKICON.SHP \\\n\tDTRKICON.SHP \\\n\tMECHICON.SHP \\\n\tMSUBICON.SHP \\\n\tQTNKICON.SHP \\\n\tSHOKICON.SHP \\\n\tSTNKICON.SHP \\\n\tTTNKICON.SHP \\\n\n# These helper macros substitute the extension so that\n# the appropriate art build rule will be invoked.\nxLOHILORES = $(HILORES:.SHP=.LOW)\nLOHILORES = $(xLOHILORES:.FNT=.LNT)\nxHIHILORES = $(HILORES:.SHP=.HI)\nHIHILORES = $(xHIHILORES:.FNT=.HNT)\n\nxLOHILORES1 = $(HILORES1:.SHP=.LOW)\nLOHILORES1 = $(xLOHILORES1:.FNT=.LNT)\nxHIHILORES1 = $(HILORES1:.SHP=.HI)\nHIHILORES1 = $(xHIHILORES1:.FNT=.HNT)\n\n#\n# Files required for hires/Win95 version only\n#\n# This mix file is cached\n#\nHIRESFILES = \\\n\tALIPAPER.PCX \\\n      \tPROLOG.PCX \\\n\tSOVPAPER.PCX \\\n\tAFTR_HI.PCX \\\n\tALY1.PCX \\\n\tAPC_HI.PCX \\\n\tAPHI0049.PCX \\\n\tBNHI0020.PCX \\\n\tDCHI0040.PCX \\\n\tFRHI0166.PCX \\\n\tLAB.PCX \\\n\tLANDSBRG.PCX \\\n\tMAHI0107.PCX \\\n\tMIG_HI.PCX \\\n\tMTFACTHI.PCX \\\n\tNEEDLE.PCX \\\n\tSOV2.PCX \\\n\tSPY.PCX \\\n\tSTALIN.PCX \\\n\tTENT.PCX \\\n#\tENG_HI.PCX \\\n\n\nCONQUERFILES = \\\n\tPARABOMB.SHP \\\n\tRADARFRM.SHP \\\n\tARMOR.SHP \\\n\tFPOWER.SHP \\\n\tSPEED.SHP \\\n\tTQUAKE.SHP \\\n\tH2O_EXP1.SHP \\\n\tH2O_EXP2.SHP \\\n\tH2O_EXP3.SHP \\\n\tFLAK.SHP \\\n\tEBTN-DN.SHP \\\n\tEBTN-UP.SHP \\\n\tATOMSFX.SHP \\\n\tTWINKLE1.SHP \\\n\tTWINKLE2.SHP \\\n\tTWINKLE3.SHP \\\n\tCHRONBOX.SHP \\\n\tGPSBOX.SHP \\\n\tINVULBOX.SHP \\\n\tPARABOX.SHP \\\n\tSONARBOX.SHP \\\n\tSPUTNIK.SHP \\\n\tSPUTDOOR.SHP \\\n\tATOMICDN.SHP \\\n\tATOMICUP.SHP \\\n\tTYPE.FNT \\\n\t120MM.SHP \\\n\t1TNK.SHP \\\n\t2TNK.SHP \\\n\t3TNK.SHP \\\n\t4TNK.SHP \\\n\t50CAL.SHP \\\n\tAFLD.SHP \\\n\tAGUN.SHP \\\n\tAPC.SHP \\\n\tAPWR.SHP \\\n\tART-EXP1.SHP \\\n\tARTY.SHP \\\n\tATEK.SHP \\\n\tBADR.SHP \\\n\tBARB.SHP \\\n\tBARL.SHP \\\n\tBARR.SHP \\\n\tBIO.SHP \\\n\tBOMB.SHP \\\n\tBOMBLET.SHP \\\n\tBRIK.SHP \\\n\tBRL3.SHP \\\n\tBURN-L.SHP \\\n\tBURN-M.SHP \\\n\tBURN-S.SHP \\\n\tCA.SHP \\\n\tCYCL.SHP \\\n\tDD.SHP \\\n\tDEVIATOR.SHP \\\n\tDOG.SHP \\\n\tDOGBULLT.SHP \\\n\tDOLLAR.SHP \\\n\tDOME.SHP \\\n\tDRAGON.SHP \\\n\tEARTH.SHP \\\n\tELECTDOG.SHP \\\n\tEMPULSE.SHP \\\n\tFACT.SHP \\\n\tFB1.SHP \\\n\tFB2.SHP \\\n\tFBALL1.SHP \\\n\tFCOM.SHP \\\n\tFENC.SHP \\\n\tFIRE1.SHP \\\n\tFIRE2.SHP \\\n\tFIRE3.SHP \\\n\tFIRE4.SHP \\\n\tFIX.SHP \\\n\tFLAGFLY.SHP \\\n\tFLMSPT.SHP \\\n\tFPLS.SHP \\\n\tFRAG1.SHP \\\n\tFTNK.SHP \\\n\tFTUR.SHP \\\n\tGAP.SHP \\\n\tGUN.SHP \\\n\tGUNFIRE.SHP \\\n\tHARV.SHP \\\n\tHELI.SHP \\\n\tHIND.SHP \\\n\tHOSP.SHP \\\n\tHPAD.SHP \\\n\tINVUN.SHP \\\n\tIRON.SHP \\\n\tJEEP.SHP \\\n\tKENN.SHP \\\n\tLITNING.SHP \\\n\tLROTOR.SHP \\\n\tLST.SHP \\\n\tMCV.SHP \\\n\tMGG.SHP \\\n\tMGUN.SHP \\\n\tMHQ.SHP \\\n\tMIG.SHP \\\n\tMINE.SHP \\\n\tMINIGUN.SHP \\\n\tMINP.SHP \\\n\tMINV.SHP \\\n\tMISS.SHP \\\n\tMISSILE.SHP \\\n\tMISSILE2.SHP \\\n\tMLRS.SHP \\\n\tMNLY.SHP \\\n\tMRJ.SHP \\\n\tNAPALM1.SHP \\\n\tNAPALM2.SHP \\\n\tNAPALM3.SHP \\\n\tORCA.SHP \\\n\tPARACH.SHP \\\n\tPATRIOT.SHP \\\n\tPBOX.SHP \\\n\tPDOX.SHP \\\n\tPIFF.SHP \\\n\tPIFFPIFF.SHP \\\n\tPOWR.SHP \\\n\tPROC.SHP \\\n\tPT.SHP \\\n\tRAPID.SHP \\\n\tRROTOR.SHP \\\n\tSAM.SHP \\\n\tSAMFIRE.SHP \\\n\tSBAG.SHP \\\n\tSCRATE.SHP \\\n\tSELECT.SHP \\\n\tSHADOW.SHP \\\n\tSILO.SHP \\\n\tSMIG.SHP \\\n\tSMOKEY.SHP \\\n\tSMOKE_M.SHP \\\n\tSMOKLAND.SHP \\\n\tSPEN.SHP \\\n\tSS.SHP \\\n\tSSAM.SHP \\\n\tSTEALTH2.SHP \\\n\tSTEK.SHP \\\n\tSTNK.SHP \\\n\tSYRD.SHP \\\n\tTENT.SHP \\\n\tTRAN.SHP \\\n\tTRANS.ICN \\\n\tTRUK.SHP \\\n\tTSLA.SHP \\\n\tTURR.SHP \\\n\tU2.SHP \\\n\tV19.SHP \\\n\tV2.SHP \\\n\tV2RL.SHP \\\n\tVEH-HIT1.SHP \\\n\tVEH-HIT2.SHP \\\n\tVEH-HIT3.SHP \\\n\tWAKE.SHP \\\n\tWCRATE.SHP \\\n\tWWCRATE.SHP \\\n\tWEAP.SHP \\\n\tWEAP2.SHP \\\n\tWOOD.SHP \\\n\tYAK.SHP \\\n\tAFLDMAKE.SHP \\\n\tAGUNMAKE.SHP \\\n\tAPWRMAKE.SHP \\\n\tATEKMAKE.SHP \\\n\tBARRMAKE.SHP \\\n\tBIOMAKE.SHP \\\n\tDOMEMAKE.SHP \\\n\tFACTMAKE.SHP \\\n\tFIXMAKE.SHP \\\n\tFTURMAKE.SHP \\\n\tGAPMAKE.SHP \\\n\tGUNMAKE.SHP \\\n\tHOSPMAKE.SHP \\\n\tHPADMAKE.SHP \\\n\tIRONMAKE.SHP \\\n\tKENNMAKE.SHP \\\n\tMINPMAKE.SHP \\\n\tMINVMAKE.SHP \\\n\tPBOXMAKE.SHP \\\n\tPOWRMAKE.SHP \\\n\tPDOXMAKE.SHP \\\n\tPROCMAKE.SHP \\\n\tPUMPMAKE.SHP \\\n\tSAMMAKE.SHP \\\n\tSILOMAKE.SHP \\\n\tSPENMAKE.SHP \\\n\tSTEKMAKE.SHP \\\n\tSYRDMAKE.SHP \\\n\tTENTMAKE.SHP \\\n\tTSLAMAKE.SHP \\\n\tWEAPMAKE.SHP \\\n\nGENERALMAPFILES = \\\n\tMISSIONS.PKT \\\n\tCSTRIKE.PKT \\\n\tTUTORIAL.INI \\\n        SCG01EA.INI \\     \n        SCG40EA.INI \\     \n        SCG41EA.INI \\     \n        SCG42EA.INI \\     \n        SCG43EA.INI \\     \n        SCG44EA.INI \\     \n        SCG45EA.INI \\     \n        SCG46EA.INI \\     \n        SCG47EA.INI \\     \n        SCG48EA.INI \\     \n        SCU40EA.INI \\     \n        SCU41EA.INI \\     \n        SCU42EA.INI \\     \n        SCU43EA.INI \\     \n        SCU44EA.INI \\     \n        SCU45EA.INI \\     \n        SCU46EA.INI \\     \n        SCU47EA.INI \\     \n        SCU48EA.INI \\     \n\tSCU01EA.INI \\     \n\tSCM01EA.INI \\      \n\tSCM02EA.INI \\ \n\tSCM03EA.INI \\ \n\tSCM04EA.INI \\ \n\tSCM05EA.INI \\ \n\tSCM06EA.INI \\ \n\tSCM07EA.INI \\ \n\tSCM08EA.INI \\ \n\tSCM09EA.INI \\ \n\tSCM10EA.INI \\ \n\tSCM11EA.INI \\ \n\tSCM12EA.INI \\ \n\tSCM13EA.INI \\ \n\tSCM14EA.INI \\ \n\tSCM15EA.INI \\ \n\tSCM16EA.INI \\ \n\tSCM17EA.INI \\ \n\tSCM18EA.INI \\ \n\tSCM19EA.INI \\ \n\tSCM20EA.INI \\ \n\tSCM21EA.INI \\ \n\tSCM22EA.INI \\ \n\tSCM23EA.INI \\ \n\tSCM24EA.INI \\ \n\tSCMD0EA.INI \\\n\tSCMD1EA.INI \\\n\tSCMD2EA.INI \\\n\tSCMD3EA.INI \\\n\tSCMD4EA.INI \\\n\tSCMD5EA.INI \\\n\tSCMD6EA.INI \\\n\tSCMD7EA.INI \\\n\tSCMD8EA.INI \\\n\tSCMD9EA.INI \\\n\tSCME0EA.INI \\\n\tSCME1EA.INI \\\n\tSCME2EA.INI \\\n\tSCME3EA.INI \\\n\tSCME4EA.INI \\\n\tSCME5EA.INI \\\n\tSCME6EA.INI \\\n\tSCME7EA.INI \\\n\tSCME8EA.INI \\\n\tSCME9EA.INI \\\n\tSCMF0EA.INI \\\n\tSCMF1EA.INI \\\n\tSCMF2EA.INI \\\n\tSCMF3EA.INI \\\n\tSCMF4EA.INI \\\n\tSCMF5EA.INI \\\n\tSCMF6EA.INI \\\n\tSCMF7EA.INI \\\n\tSCMF8EA.INI \\\n\tSCMF9EA.INI \\\n\tSCMG0EA.INI \\\n\tSCMG1EA.INI \\\n\tSCMG2EA.INI \\\n\tSCMG3EA.INI \\\n\tSCMG4EA.INI \\\n\tSCMG5EA.INI \\\n\tSCMG6EA.INI \\\n\tSCMG7EA.INI \\\n\tSCMG8EA.INI \\\n\tSCMG9EA.INI \\\n\tSCMH0EA.INI \\\n\tSCMH1EA.INI \\\n\tSCMH2EA.INI \\\n\tSCMH3EA.INI \\\n\tSCMH4EA.INI \\\n\tSCMH5EA.INI \\\n\tSCMH6EA.INI \\\n\tSCMH7EA.INI \\\n\tSCMH8EA.INI \\\n\tSCMH9EA.INI \\\n\tSCMI0EA.INI \\\n\tSCMI1EA.INI \\\n\tSCMI2EA.INI \\\n\tSCMI3EA.INI \\\n\tSCMI4EA.INI \\\n\tSCMI5EA.INI \\\n\tSCMI6EA.INI \\\n\tSCMI7EA.INI \\\n\tSCMI8EA.INI \\\n\tSCMI9EA.INI \\\n\tSCMJ0EA.INI \\\n\tSCMJ1EA.INI \\\n\tSCMJ2EA.INI \\\n\tSCMJ3EA.INI \\\n\tSCMJ4EA.INI \\\n\tSCMJ5EA.INI \\\n\tSCMJ6EA.INI \\\n\tSCMJ7EA.INI \\\n\tSCMJ8EA.INI \\\n\tSCMJ9EA.INI \\\n\tSCMK0EA.INI \\\n\tSCMK1EA.INI \\\n\tSCMK2EA.INI \\\n\tSCMK3EA.INI \\\n\tSCMK4EA.INI \\\n\tSCMK5EA.INI \\\n\tSCMK6EA.INI \\\n\tSCMK7EA.INI \\\n\tSCMK8EA.INI \\\n\tSCMK9EA.INI \\\n\tSCML0EA.INI \\\n\tSCML1EA.INI \\\n\tSCML2EA.INI \\\n\tSCML3EA.INI \\\n\tSCML4EA.INI \\\n\tSCML5EA.INI \\\n\tSCML6EA.INI \\\n\tSCML7EA.INI \\\n\tSCML8EA.INI \\\n\tSCML9EA.INI \\\n\tSCMM0EA.INI \\\n\tSCMM1EA.INI \\\n\tSCMM2EA.INI \\\n\tSCMM3EA.INI \\\n\tSCMM4EA.INI \\\n\tSCMM5EA.INI \\\n\tSCMM6EA.INI \\\n\tSCMM7EA.INI \\\n\tSCMM8EA.INI \\\n\tSCMM9EA.INI \\\n      \tSCM25EA.INI \\\n\tSCM26EA.INI \\\n\tSCM27EA.INI \\\n\tSCM28EA.INI \\\n\tSCM29EA.INI \\\n\tSCM30EA.INI \\\n\tSCM31EA.INI \\ \n\tSCM32EA.INI \\ \n\tSCM33EA.INI \\\n\tSCM34EA.INI \\\n     \tSCM35EA.INI \\\n\tSCM36EA.INI \\\n\tSCM37EA.INI \\\n\tSCM38EA.INI \\\n\tSCM39EA.INI \\\n\tSCM40EA.INI \\\n\tSCM41EA.INI \\\n\tSCM42EA.INI \\\n\tSCM43EA.INI \\\n\tSCM44EA.INI \\\n\tSCM45EA.INI \\\n\tSCM46EA.INI \\\n\tSCM47EA.INI \\\n\tSCM48EA.INI \\\n\tSCM49EA.INI \\\n\tSCM50EA.INI \\\n\tSCM51EA.INI \\\n\tSCM52EA.INI \\\n\tSCM53EA.INI \\\n\tSCM54EA.INI \\\n\tSCM55EA.INI \\\n\tSCM56EA.INI \\\n\tSCM57EA.INI \\\n\tSCM58EA.INI \\\n\tSCM59EA.INI \\\n\tSCM60EA.INI \\\n\tSCM61EA.INI \\\n\tSCM62EA.INI \\\n\tSCM63EA.INI \\\n\tSCM64EA.INI \\\n\tSCM65EA.INI \\\n\tSCM66EA.INI \\\n\tSCM67EA.INI \\\n\tSCM68EA.INI \\\n\tSCM69EA.INI \\\n\tSCM70EA.INI \\\n\tSCM71EA.INI \\\n\tSCM72EA.INI \\\n\tSCM73EA.INI \\\n\tSCM74EA.INI \\\n\tSCM75EA.INI \\\n\tSCM76EA.INI \\\n\tSCM77EA.INI \\\n\tSCM78EA.INI \\\n\tSCM79EA.INI \\\n\tSCM80EA.INI \\\n\tSCM81EA.INI \\\n\tSCM82EA.INI \\\n\tSCM83EA.INI \\\n\tSCM84EA.INI \\\n\tSCM85EA.INI \\\n\tSCM86EA.INI \\\n\tSCM87EA.INI \\\n\tSCM88EA.INI \\\n\tSCM89EA.INI \\\t\n\tSCM90EA.INI \\\n\tSCM91EA.INI \\\n\tSCM92EA.INI \\\n\tSCM93EA.INI \\\n\tSCM94EA.INI \\\n\tSCM95EA.INI \\\n\tSCM96EA.INI \\\n\tSCM97EA.INI \\\n\tSCM98EA.INI \\\n\tSCM99EA.INI \\\n\tSCM100EA.INI \\\n\tSCM101EA.INI \\\n\tSCM102EA.INI \\\n\tSCM103EA.INI \\\n\tSCM104EA.INI \\\n\tSCM105EA.INI \\\n\tSCM106EA.INI \\\n\tSCM107EA.INI \\\n\tSCM108EA.INI \\\n\tSCM109EA.INI \\\n\tSCM110EA.INI \\\n\tSCM111EA.INI \\\n\tSCM112EA.INI \\\n\tSCM113EA.INI \\\n\tSCM114EA.INI \\\n\tSCM115EA.INI \\\n\tSCM116EA.INI \\\n\tSCM117EA.INI \\\n\tSCM118EA.INI \\\n \tSCM119EA.INI \\    \n\tSCM120EA.INI \\     \n\tSCM121EA.INI \\    \n\tSCM122EA.INI \\     \n\tSCM123EA.INI \\    \n\tSCM124EA.INI \\    \n\tSCM125EA.INI \\    \n\tSCM126EA.INI \\    \n\tSCM127EA.INI \\    \n\tSCM128EA.INI \\    \n\tSCM129EA.INI \\ \n\tSCM130EA.INI \\   \n\nNETMAPFILES = \\\n\n# Files that aren't cached.\nGENERALFILES = \\\n\tAFTR_LO.CPS \\\n\tALY1-LO.CPS \\\n\tAPC_LO.CPS \\\n\tAPLO0049.CPS \\\n\tBNLO0020.CPS \\\n\tDCLO0040.CPS \\\n\tFRLO0166.CPS \\\n\tLAB-LO.CPS \\\n\tLANDS-LO.CPS \\\n\tMALO0107.CPS \\\n\tMIG_LO.CPS \\\n\tMTFACTLO.CPS \\\n\tNEEDL-LO.CPS \\\n\tSOV2-LO.CPS \\\n\tSPY-LO.CPS \\\n\tSTALN-LO.CPS \\\n\tTENT-LO.CPS \\\n\tTITLE.CPS \\\n\tPPAPER.CPS \\\n\tMSAA.WSA \\\n\tMSAB.WSA \\\n\tMSAC.WSA \\\n\tMSAD.WSA \\\n\tMSAE.WSA \\\n\tMSAF.WSA \\\n\tMSAG.WSA \\\n\tMSAH.WSA \\\n\tMSAI.WSA \\\n\tMSAJ.WSA \\\n\tMSAK.WSA \\\n\tMSAL.WSA \\\n\tMSAM.WSA \\\n\tMSAN.WSA \\\n\tMSSA.WSA \\\n\tMSSB.WSA \\\n\tMSSC.WSA \\\n\tMSSD.WSA \\\n\tMSSE.WSA \\\n\tMSSF.WSA \\\n\tMSSG.WSA \\\n\tMSSH.WSA \\\n\tMSSI.WSA \\\n\tMSSJ.WSA \\\n\tMSSK.WSA \\\n\tMSSL.WSA \\\n\tMSSM.WSA \\\n\tMSSN.WSA \\\n\nINTERIORFILES = \\\n\tBOXES01.INT \\\n\tBOXES02.INT \\\n\tBOXES03.INT \\\n\tBOXES04.INT \\\n\tBOXES05.INT \\\n\tBOXES06.INT \\\n\tBOXES07.INT \\\n\tBOXES08.INT \\\n\tBOXES09.INT \\\n\tXTRA0001.INT \\\n\tXTRA0002.INT \\\n\tXTRA0003.INT \\\n\tXTRA0004.INT \\\n\tXTRA0005.INT \\\n\tXTRA0006.INT \\\n\tXTRA0007.INT \\\n\tXTRA0008.INT \\\n\tXTRA0009.INT \\\n\tXTRA0010.INT \\\n\tXTRA0011.INT \\\n\tXTRA0012.INT \\\n\tXTRA0013.INT \\\n\tXTRA0014.INT \\\n\tXTRA0015.INT \\\n\tXTRA0016.INT \\\n\tCLEAR1.INT \\\n\tMOVEFLSH.INT \\\n\tARRO0001.INT \\\n\tARRO0002.INT \\\n\tARRO0003.INT \\\n\tARRO0004.INT \\\n\tARRO0005.INT \\\n\tARRO0006.INT \\\n\tARRO0007.INT \\\n\tARRO0008.INT \\\n\tARRO0009.INT \\\n\tARRO0010.INT \\\n\tARRO0011.INT \\\n\tARRO0012.INT \\\n\tARRO0013.INT \\\n\tARRO0014.INT \\\n\tARRO0015.INT \\\n\tFLOR0001.INT \\\n\tFLOR0002.INT \\\n\tFLOR0003.INT \\\n\tFLOR0004.INT \\\n\tFLOR0005.INT \\\n\tFLOR0006.INT \\\n\tFLOR0007.INT \\\n\tGFLR0001.INT \\\n\tGFLR0002.INT \\\n\tGFLR0003.INT \\\n\tGFLR0004.INT \\\n\tGFLR0005.INT \\\n\tGSTR0001.INT \\\n\tGSTR0002.INT \\\n\tGSTR0003.INT \\\n\tGSTR0004.INT \\\n\tGSTR0005.INT \\\n\tGSTR0006.INT \\\n\tGSTR0007.INT \\\n\tGSTR0008.INT \\\n\tGSTR0009.INT \\\n\tGSTR0010.INT \\\n\tGSTR0011.INT \\\n\tLWAL0001.INT \\\n\tLWAL0002.INT \\\n\tLWAL0003.INT \\\n\tLWAL0004.INT \\\n\tLWAL0005.INT \\\n\tLWAL0006.INT \\\n\tLWAL0007.INT \\\n\tLWAL0008.INT \\\n\tLWAL0009.INT \\\n\tLWAL0010.INT \\\n\tLWAL0011.INT \\\n\tLWAL0012.INT \\\n\tLWAL0013.INT \\\n\tLWAL0014.INT \\\n\tLWAL0015.INT \\\n\tLWAL0016.INT \\\n\tLWAL0017.INT \\\n\tLWAL0018.INT \\\n\tLWAL0019.INT \\\n\tLWAL0020.INT \\\n\tLWAL0021.INT \\\n\tLWAL0022.INT \\\n\tLWAL0023.INT \\\n\tLWAL0024.INT \\\n\tLWAL0025.INT \\\n\tLWAL0026.INT \\\n\tLWAL0027.INT \\\n\tSTRP0001.INT \\\n\tSTRP0002.INT \\\n\tSTRP0003.INT \\\n\tSTRP0004.INT \\\n\tSTRP0005.INT \\\n\tSTRP0006.INT \\\n\tSTRP0007.INT \\\n\tSTRP0008.INT \\\n\tSTRP0009.INT \\\n\tSTRP0010.INT \\\n\tSTRP0011.INT \\\n\tWALL0001.INT \\\n\tWALL0002.INT \\\n\tWALL0003.INT \\\n\tWALL0004.INT \\\n\tWALL0005.INT \\\n\tWALL0006.INT \\\n\tWALL0007.INT \\\n\tWALL0008.INT \\\n\tWALL0009.INT \\\n\tWALL0010.INT \\\n\tWALL0011.INT \\\n\tWALL0012.INT \\\n\tWALL0013.INT \\\n\tWALL0014.INT \\\n\tWALL0015.INT \\\n\tWALL0016.INT \\\n\tWALL0017.INT \\\n\tWALL0018.INT \\\n\tWALL0019.INT \\\n\tWALL0020.INT \\\n\tWALL0021.INT \\\n\tWALL0022.INT \\\n\tWALL0023.INT \\\n\tWALL0024.INT \\\n\tWALL0025.INT \\\n\tWALL0026.INT \\\n\tWALL0027.INT \\\n\tWALL0028.INT \\\n\tWALL0029.INT \\\n\tWALL0030.INT \\\n\tWALL0031.INT \\\n\tWALL0032.INT \\\n\tWALL0033.INT \\\n\tWALL0034.INT \\\n\tWALL0035.INT \\\n\tWALL0036.INT \\\n\tWALL0037.INT \\\n\tWALL0038.INT \\\n\tWALL0039.INT \\\n\tWALL0040.INT \\\n\tWALL0041.INT \\\n\tWALL0042.INT \\\n\tWALL0043.INT \\\n\tWALL0044.INT \\\n\tWALL0045.INT \\\n\tWALL0046.INT \\\n\tWALL0047.INT \\\n\tWALL0048.INT \\\n\tWALL0049.INT \\\n\n# Both the temperate and snow sets have identical template entries.\nTEMPERATEFILES = \\\n\tMINE.TEM \\\n\tICE01.TEM \\\n\tICE02.TEM \\\n\tICE03.TEM \\\n\tICE04.TEM \\\n\tICE05.TEM \\\n\tMOVEFLSH.TEM \\\n\tBR1X.TEM \\\n\tBR2X.TEM \\\n\tBRIDGE1X.TEM \\\n\tBRIDGE2X.TEM \\\n\tBRIDGE1H.TEM \\\n\tBRIDGE2H.TEM \\\n\tF01.TEM \\\n\tF02.TEM \\\n\tF03.TEM \\\n\tF04.TEM \\\n\tF05.TEM \\\n\tF06.TEM \\\n\tELECTRO.TEM \\\n\tB1.TEM \\\n\tB2.TEM \\\n\tB3.TEM \\\n\tBIB1.TEM \\\n\tBIB2.TEM \\\n\tBIB3.TEM \\\n\tBR1A.TEM \\\n\tBR1B.TEM \\\n\tBR1C.TEM \\\n\tBR2A.TEM \\\n\tBR2B.TEM \\\n\tBR2C.TEM \\\n\tBR3A.TEM \\\n\tBR3B.TEM \\\n\tBR3C.TEM \\\n\tBR3D.TEM \\\n\tBR3E.TEM \\\n\tBR3F.TEM \\\n\tBRIDGE1.TEM \\\n\tBRIDGE1D.TEM \\\n\tBRIDGE2.TEM \\\n\tBRIDGE2D.TEM \\\n\tCLEAR1.TEM \\\n\tCORPSE1.TEM \\\n\tCORPSE2.TEM \\\n\tCORPSE3.TEM \\\n\tCR1.TEM \\\n\tCR2.TEM \\\n\tCR3.TEM \\\n\tCR4.TEM \\\n\tCR5.TEM \\\n\tCR6.TEM \\\n\tD01.TEM \\\n\tD02.TEM \\\n\tD03.TEM \\\n\tD04.TEM \\\n\tD05.TEM \\\n\tD06.TEM \\\n\tD07.TEM \\\n\tD08.TEM \\\n\tD09.TEM \\\n\tD10.TEM \\\n\tD11.TEM \\\n\tD12.TEM \\\n\tD13.TEM \\\n\tD14.TEM \\\n\tD15.TEM \\\n\tD16.TEM \\\n\tD17.TEM \\\n\tD18.TEM \\\n\tD19.TEM \\\n\tD20.TEM \\\n\tD21.TEM \\\n\tD22.TEM \\\n\tD23.TEM \\\n\tD24.TEM \\\n\tD25.TEM \\\n\tD26.TEM \\\n\tD27.TEM \\\n\tD28.TEM \\\n\tD29.TEM \\\n\tD30.TEM \\\n\tD31.TEM \\\n\tD32.TEM \\\n\tD33.TEM \\\n\tD34.TEM \\\n\tD35.TEM \\\n\tD36.TEM \\\n\tD37.TEM \\\n\tD38.TEM \\\n\tD39.TEM \\\n\tD40.TEM \\\n\tD41.TEM \\\n\tD42.TEM \\\n\tD43.TEM \\\n\tD44.TEM \\\n\tD45.TEM \\\n\tFALLS1.TEM \\\n\tFALLS1A.TEM \\\n\tFALLS2.TEM \\\n\tFALLS2A.TEM \\\n\tFORD1.TEM \\\n\tFORD2.TEM \\\n\tGEM01.TEM \\\n\tGEM02.TEM \\\n\tGEM03.TEM \\\n\tGEM04.TEM \\\n\tGOLD01.TEM \\\n\tGOLD02.TEM \\\n\tGOLD03.TEM \\\n\tGOLD04.TEM \\\n\tHBOX.TEM \\\n\tMSLOMAKE.TEM \\\n\tHBOXMAKE.TEM \\\n\tMSLO.TEM \\\n\tP01.TEM \\\n\tP02.TEM \\\n\tP03.TEM \\\n\tP04.TEM \\\n\tP07.TEM \\\n\tP08.TEM \\\n\tP13.TEM \\\n\tP14.TEM \\\n\tRC01.TEM \\\n\tRC02.TEM \\\n\tRC03.TEM \\\n\tRC04.TEM \\\n\tRF01.TEM \\\n\tRF02.TEM \\\n\tRF03.TEM \\\n\tRF04.TEM \\\n\tRF05.TEM \\\n\tRF06.TEM \\\n\tRF07.TEM \\\n\tRF08.TEM \\\n\tRF09.TEM \\\n\tRF10.TEM \\\n\tRF11.TEM \\\n\tRV01.TEM \\\n\tRV02.TEM \\\n\tRV03.TEM \\\n\tRV04.TEM \\\n\tRV05.TEM \\\n\tRV06.TEM \\\n\tRV07.TEM \\\n\tRV08.TEM \\\n\tRV09.TEM \\\n\tRV10.TEM \\\n\tRV11.TEM \\\n\tRV12.TEM \\\n\tRV13.TEM \\\n\tRV14.TEM \\\n\tRV15.TEM \\\n\tS01.TEM \\\n\tS02.TEM \\\n\tS03.TEM \\\n\tS04.TEM \\\n\tS05.TEM \\\n\tS06.TEM \\\n\tS07.TEM \\\n\tS08.TEM \\\n\tS09.TEM \\\n\tS10.TEM \\\n\tS11.TEM \\\n\tS12.TEM \\\n\tS13.TEM \\\n\tS14.TEM \\\n\tS15.TEM \\\n\tS16.TEM \\\n\tS17.TEM \\\n\tS18.TEM \\\n\tS19.TEM \\\n\tS20.TEM \\\n\tS21.TEM \\\n\tS22.TEM \\\n\tS23.TEM \\\n\tS24.TEM \\\n\tS25.TEM \\\n\tS26.TEM \\\n\tS27.TEM \\\n\tS28.TEM \\\n\tS29.TEM \\\n\tS30.TEM \\\n\tS31.TEM \\\n\tS32.TEM \\\n\tS33.TEM \\\n\tS34.TEM \\\n\tS35.TEM \\\n\tS36.TEM \\\n\tS37.TEM \\\n\tS38.TEM \\\n\tSC1.TEM \\\n\tSC2.TEM \\\n\tSC3.TEM \\\n\tSC4.TEM \\\n\tSC5.TEM \\\n\tSC6.TEM \\\n\tSH01.TEM \\\n\tSH02.TEM \\\n\tSH03.TEM \\\n\tSH04.TEM \\\n\tSH05.TEM \\\n\tSH06.TEM \\\n\tSH07.TEM \\\n\tSH08.TEM \\\n\tSH09.TEM \\\n\tSH10.TEM \\\n\tSH11.TEM \\\n\tSH12.TEM \\\n\tSH13.TEM \\\n\tSH14.TEM \\\n\tSH15.TEM \\\n\tSH16.TEM \\\n\tSH17.TEM \\\n\tSH18.TEM \\\n\tSH19.TEM \\\n\tSH20.TEM \\\n\tSH21.TEM \\\n\tSH22.TEM \\\n\tSH23.TEM \\\n\tSH24.TEM \\\n\tSH25.TEM \\\n\tSH26.TEM \\\n\tSH27.TEM \\\n\tSH28.TEM \\\n\tSH29.TEM \\\n\tSH30.TEM \\\n\tSH31.TEM \\\n\tSH32.TEM \\\n\tSH33.TEM \\\n\tSH34.TEM \\\n\tSH35.TEM \\\n\tSH36.TEM \\\n\tSH37.TEM \\\n\tSH38.TEM \\\n\tSH39.TEM \\\n\tSH40.TEM \\\n\tSH41.TEM \\\n\tSH42.TEM \\\n\tSH43.TEM \\\n\tSH44.TEM \\\n\tSH45.TEM \\\n\tSH46.TEM \\\n\tSH47.TEM \\\n\tSH48.TEM \\\n\tSH49.TEM \\\n\tSH50.TEM \\\n\tSH51.TEM \\\n\tSH52.TEM \\\n\tSH53.TEM \\\n\tSH54.TEM \\\n\tSH55.TEM \\\n\tSH56.TEM \\\n\tT01.TEM \\\n\tT02.TEM \\\n\tT03.TEM \\\n\tT05.TEM \\\n\tT06.TEM \\\n\tT07.TEM \\\n\tT08.TEM \\\n\tT10.TEM \\\n\tT11.TEM \\\n\tT12.TEM \\\n\tT13.TEM \\\n\tT14.TEM \\\n\tT15.TEM \\\n\tT16.TEM \\\n\tT17.TEM \\\n\tTC01.TEM \\\n\tTC02.TEM \\\n\tTC03.TEM \\\n\tTC04.TEM \\\n\tTC05.TEM \\\n\tV01.TEM \\\n\tV02.TEM \\\n\tV03.TEM \\\n\tV04.TEM \\\n\tV05.TEM \\\n\tV06.TEM \\\n\tV07.TEM \\\n\tV08.TEM \\\n\tV09.TEM \\\n\tV10.TEM \\\n\tV11.TEM \\\n\tV12.TEM \\\n\tV13.TEM \\\n\tV14.TEM \\\n\tV15.TEM \\\n\tV16.TEM \\\n\tV17.TEM \\\n\tV18.TEM \\\n\tW1.TEM \\\n\tW2.TEM \\\n\tWC01.TEM \\\n\tWC02.TEM \\\n\tWC03.TEM \\\n\tWC04.TEM \\\n\tWC05.TEM \\\n\tWC06.TEM \\\n\tWC07.TEM \\\n\tWC08.TEM \\\n\tWC09.TEM \\\n\tWC10.TEM \\\n\tWC11.TEM \\\n\tWC12.TEM \\\n\tWC13.TEM \\\n\tWC14.TEM \\\n\tWC15.TEM \\\n\tWC16.TEM \\\n\tWC17.TEM \\\n\tWC18.TEM \\\n\tWC19.TEM \\\n\tWC20.TEM \\\n\tWC21.TEM \\\n\tWC22.TEM \\\n\tWC23.TEM \\\n\tWC24.TEM \\\n\tWC25.TEM \\\n\tWC26.TEM \\\n\tWC27.TEM \\\n\tWC28.TEM \\\n\tWC29.TEM \\\n\tWC30.TEM \\\n\tWC31.TEM \\\n\tWC32.TEM \\\n\tWC33.TEM \\\n\tWC34.TEM \\\n\tWC35.TEM \\\n\tWC36.TEM \\\n\tWC37.TEM \\\n\tWC38.TEM \\\n\n# Every temperate theater terrain file has a snow theater counterpart.\nSNOWFILES = $(TEMPERATEFILES:.TEM=.SNO)\n\n# Sound effects (Juvenile or Adult)\nSFX = \\\n\n# Generic wave files (never changes).\nWAVFILES = \\\n\tAACANON3.AUD \\\n\tBEEPSLCT.AUD \\\n\tBLEEP11.AUD \\\n\tBLEEP12.AUD \\\n\tBLEEP13.AUD \\\n\tBLEEP17.AUD \\\n\tBLEEP5.AUD \\\n\tBLEEP6.AUD \\\n\tBLEEP9.AUD \\\n\tBOMBIT1.AUD \\\n\tBUILD5.AUD \\\n\tBUZZY1.AUD \\       \n\tCANNON1.AUD \\\n\tCANNON2.AUD \\\n\tCASHDN1.AUD \\\n\tCASHTURN.AUD \\\n\tCASHUP1.AUD \\\n\tCHRONO2.AUD \\\n\tCHROTNK1.AUD \\\n\tCHUTE1.AUD \\\n\tCMON1.AUD \\\n\tCRMBLE2.AUD \\\n\tDEDMAN1.AUD \\\n\tDEDMAN10.AUD \\\n\tDEDMAN2.AUD \\\n\tDEDMAN3.AUD \\\n\tDEDMAN4.AUD \\\n\tDEDMAN5.AUD \\\n\tDEDMAN6.AUD \\\n\tDEDMAN7.AUD \\\n\tDEDMAN8.AUD \\\n\tDOGG5P.AUD \\\n\tDOGW3PX.AUD \\\n\tDOGW5.AUD \\\n\tDOGW6.AUD \\\n\tDOGW7.AUD \\\n\tDOGY1.AUD \\\n\tEAFFIRM1.AUD \\\n\tEENGIN1.AUD \\\n\tEINAH1.AUD \\\n\tEINOK1.AUD \\\n\tEINYES1.AUD \\\n\tEMOVOUT1.AUD \\\n\tEYESSIR1.AUD \\\n\tFIREBL3.AUD \\\n\tFIRETRT1.AUD \\\n\tFIXIT1.AUD \\\n\tGIRLOKAY.AUD \\\n\tGIRLYEAH.AUD \\\n\tGOTIT1.AUD \\\n\tGRENADE1.AUD \\\n\tGUN11.AUD \\\n\tGUN13.AUD \\\n\tGUN27.AUD \\\n\tGUN5.AUD \\\n\tGUYOKAY1.AUD \\\n\tGUYYEAH1.AUD \\\n\tH2OBOMB2.AUD \\\n\tHEAL2.AUD \\\n\tHYDROD1.AUD \\\n\tINVUL2.AUD \\\n\tIRONCUR9.AUD \\\n\tJBURN1.AUD \\\n\tJCHRGE1.AUD \\\n\tJCRISP1.AUD \\\n\tJDANCE1.AUD \\\n\tJJUICE1.AUD \\\n\tJJUMP1.AUD \\\n\tJLIGHT1.AUD \\\n\tJPOWER1.AUD \\\n\tJSHOCK1.AUD \\\n\tJYES1.AUD \\\n\tKABOOM1.AUD \\\n\tKABOOM12.AUD \\\n\tKABOOM15.AUD \\\n\tKABOOM22.AUD \\\n\tKABOOM25.AUD \\\n\tKABOOM30.AUD \\\n\tKEEPEM1.AUD \\\n\tLAUGH1.AUD \\\n\tLEFTY1.AUD \\\n\tMADCHRG2.AUD \\\n\tMADEXPLO.AUD \\\n\tMAFFIRM1.AUD \\\n\tMBOSS1.AUD \\\n\tMHEAR1.AUD \\\n\tMHOTDIG1.AUD \\\n\tMHOWDY1.AUD \\\n\tMHUH1.AUD \\\n\tMGUNINF1.AUD \\\n\tMINE1.AUD \\\n\tMINEBLO1.AUD \\\n\tMINELAY1.AUD \\\n\tMISSILE1.AUD \\\n\tMISSILE6.AUD \\\n\tMISSILE7.AUD \\\n\tMLAFF1.AUD \\\n\tMMOVOUT1.AUD \\\n\tMRESPON1.AUD \\\n\tMRISE1.AUD \\\n\tMWRENCH1.AUD \\\n\tMYEEHAW1.AUD \\\n\tMYES1.AUD \\\n\tMYESSIR1.AUD \\\n\tONIT1.AUD \\\n\tPILLBOX1.AUD \\\n\tPLACBLDG.AUD \\\n\tRABEEP1.AUD \\\n\tRADARDN1.AUD \\\n\tRADARON2.AUD \\\n\tRAMENU1.AUD \\\n\tROKROLL1.AUD \\\n\tSAFFIRM1.AUD \\\n\tSANDBAG2.AUD \\\n\tSCOLDY1.AUD \\\n\tSCOMND1.AUD \\\n\tSHKTROP1.AUD \\\n\tSILENCER.AUD \\\n\tSINDEED1.AUD \\\n\tSKING1.AUD \\\n\tSMOUT1.AUD \\\n\tSOKAY1.AUD \\\n\tSONPULSE.AUD \\\n\tSONWAY1.AUD \\\n\tSPLASH9.AUD \\\n\tSQUISHY2.AUD \\\n\tSUBSHOW1.AUD \\\n\tSWHAT1.AUD \\\n\tSYEAH1.AUD \\\n\tSYESSIR1.AUD \\\n\tTANDETH1.AUD \\\n\tTANK5.AUD \\\n\tTANK6.AUD \\\n\tTESLA1.AUD \\\n\tTORPEDO1.AUD \\\n\tTSLACHG2.AUD \\\n\tTUFFGUY1.AUD \\\n\tTURRET1.AUD \\\n\tWALLKIL2.AUD \\\n\tYEAH1.AUD \\\n\tYES1.AUD \\\n\tYO1.AUD \\\n\n# Vehicle responses\nRESPONSE1 = \\\n\tACKNO.AUD \\\n\tAFFIRM1.AUD \\\n\tAWAIT1.AUD \\\n\tREPORT1.AUD \\\n\tVEHIC1.AUD \\\n\tYESSIR1.AUD \\\n\n# Infantry responses\nRESPONSE2 = \\\n\tACKNO.AUD \\\n\tAFFIRM1.AUD \\\n\tAWAIT1.AUD \\\n\tNOPROB.AUD \\\n\tOVEROUT.AUD \\\n\tREADY.AUD \\\n\tREPORT1.AUD \\\n\tRITAWAY.AUD \\\n\tROGER.AUD \\\n\tUGOTIT.AUD \\\n\tYESSIR1.AUD \\\n\n#TSCOREFILES = \\\n#\tcps\\record.bin \\\n#\tWIN1.AUD \\\n#\tMAP1.AUD \\\n\nVARFILES = \\\n\nSCOREFILES = \\\n\tCREDITS.AUD  \\\n\tAWAIT.AUD    \\\n\tBIGF226M.AUD \\\n\tCRUS226M.AUD \\\n\tDENSE_R.AUD  \\\n\tFAC1226M.AUD \\\n\tFAC2226M.AUD \\\n\tFOGGER1A.AUD \\\n\tHELL226M.AUD \\\n\tMUD1A.AUD \\\n\tRADIO2.AUD \\\n\tROLLOUT.AUD \\\n\tRUN1226M.AUD \\\n\tSCORE.AUD \\\n\tSMSH226M.AUD \\\n\tSNAKE.AUD \\\n\tTERMINAT.AUD \\\n\tTREN226M.AUD \\\n\tTWIN.AUD \\\n\tVECTOR1A.AUD \\\n\tWORK226M.AUD \\\n\t2ND_HAND.AUD \\   \n\tARAZIOD.AUD \\   \n\tBACKSTAB.AUD \\\n\tCHAOS2.AUD \\ \n\tSHUT_IT.AUD \\   \n\tTWINMIX1.AUD \\   \n\tUNDER3.AUD \\   \n\tVR2.AUD \\\n\tBOG.AUD \\\n\tFLOAT_V2.AUD \\\n\tGLOOM.AUD \\\n\tGRNDWIRE.AUD \\\n\tRPT.AUD \\\n\tSEARCH.AUD \\\n\tTRACTION.AUD \\\n\tWASTELND.AUD \\\n\nSPEECHFILES = \\\n\tSTRCKIL1.AUD \\\n\tNOPOWR1.AUD \\\n\tSAVE1.AUD \\\n\tLOAD1.AUD \\\n\t10MINR.AUD \\\n\t1MINR.AUD \\\n\t1OBJMET1.AUD \\\n\t20MINR.AUD \\\n\t2MINR.AUD \\\n\t2OBJMET1.AUD \\\n\t30MINR.AUD \\\n\t3MINR.AUD \\\n\t3OBJMET1.AUD \\\n\t40MINR.AUD \\\n\t4MINR.AUD \\\n\t5MINR.AUD \\\n\tAAPPRO1.AUD \\\n\tAARIVE1.AUD \\\n\tAARIVE1.AUD \\\n\tAARRIVE1.AUD \\\n\tAARRIVN1.AUD \\\n\tAARRIVS1.AUD \\\n\tAARRIVW1.AUD \\\n\tAAVAIL1.AUD \\\n\tABLDGIN1.AUD \\\n\tAFALLEN1.AUD \\\n\tALAUNCH1.AUD \\\n\tAPREP1.AUD \\\n\tAREADY1.AUD \\\n\tARMORUP1.AUD \\\n\tASELECT1.AUD \\\n\tATLNCH1.AUD \\\n\tATPREP1.AUD \\\n\tAUNITL1.AUD \\\n\tBASEATK1.AUD \\\n\tBCT1.AUD \\\n\tBLDGINF1.AUD \\\n\tBLDGPRG1.AUD \\\n\tCANCLD1.AUD \\\n\tCHROCHR1.AUD \\\n\tCHRORDY1.AUD \\\n\tCHROYES1.AUD \\\n\tCMDCNTR1.AUD \\\n\tCNTLDED1.AUD \\\n\tCOMNDOF1.AUD \\\n\tCOMNDOR1.AUD \\\n\tCONSCMP1.AUD \\\n\tCONVLST1.AUD \\\n\tCONVYAP1.AUD \\\n\tCREDIT1.AUD \\\n\tENMYAPP1.AUD \\\n\tFIREPO1.AUD \\\n\tFLARE1.AUD \\\n\tFLAREE1.AUD \\\n\tFLAREN1.AUD \\\n\tFLARES1.AUD \\\n\tFLAREW1.AUD \\\n\tIRONCHG1.AUD \\\n\tIRONRDY1.AUD \\\n\tKOSYFRE1.AUD \\\n\tKOSYRES1.AUD \\\n\tLOPOWER1.AUD \\\n\tMERCF1.AUD \\\n\tMERCR1.AUD \\\n\tMISNLST1.AUD \\\n\tMISNWON1.AUD \\\n\tMTIMEIN1.AUD \\\n\tNAVYLST1.AUD \\\n\tNEWOPT1.AUD \\\n\tNOBUILD1.AUD \\\n\tNODEPLY1.AUD \\\n\tNOFUNDS1.AUD \\\n\tNOFUNDS1.AUD \\\n\tOBJMET1.AUD \\\n\tOBJNMET1.AUD \\\n\tOBJNRCH1.AUD \\\n\tOBJRCH1.AUD \\\n\tONHOLD1.AUD \\\n\tOPTERM1.AUD \\\n\tPRIBLDG1.AUD \\\n\tPROGRES1.AUD \\\n\tPULSE1.AUD \\\n\tREINFOR1.AUD \\\n\tREPAIR1.AUD \\\n\tREPAIR1.AUD \\\n\tSATLNCH1.AUD \\\n\tSILOND1.AUD \\\n\tSLCTTGT1.AUD \\\n\tSOVEFAL1.AUD \\\n\tSOVEMP1.AUD \\\n\tSOVFAPP1.AUD \\\n\tSOVFORC1.AUD \\\n\tSOVREIN1.AUD \\\n\tSPYPLN1.AUD \\\n\tSTRUCAP1.AUD \\\n\tSTRUSLD1.AUD \\\n\tTANYAF1.AUD \\\n\tTANYAR1.AUD \\\n\tTARGFRE1.AUD \\\n\tTARGRES1.AUD \\\n\tTIMERGO1.AUD \\\n\tTIMERNO1.AUD \\\n\tTRAIN1.AUD \\\n\tUNITFUL1.AUD \\\n\tUNITLST1.AUD \\\n\tUNITRDY1.AUD \\\n\tUNITREP1.AUD \\\n\tUNITSLD1.AUD \\\n\tUNITSPD1.AUD \\\n\tXPLOPLC1.AUD \\\n#\tABLDGC1.AUD \\\n#\tSOVBLDG1.AUD \\\n#\tSOVSTRC1.AUD \\\n#\tSOVUNTD1.AUD \\\n#\tAUNITD1.AUD \\\n#\tASTRUCD1.AUD \\\n\n#ALLIESVQ = \\\nDUMMYVQ = \\\n\tAAGUN.VQA \\\n\tAFTRMATH.VQA \\\n\tALLY1.VQA \\\n\tALLY10.VQA \\\n\tALLY10B.VQA \\\n\tALLY11.VQA \\\n\tALLY12.VQA \\\n\tALLY14.VQA \\\n\tALLY2.VQA \\\n\tALLY4.VQA \\\n\tALLY5.VQA \\\n\tALLY6.VQA \\\n\tALLY8.VQA \\\n\tALLY9.VQA \\\n\tALLYEND.VQA \\\n\tALLYMORF.VQA \\\n\tAPCESCPE.VQA \\\n\tASSESS.VQA \\\n\tBATTLE.VQA \\\n\t1BINOC.VQA \\\n\tBMAP.VQA \\\n\tBRDGTILT.VQA \\\n\tCRONTEST.VQA \\\n\tCRONFAIL.VQA \\\n\tDESTROYR.VQA \\\n\tDUD.VQA \\\n\tELEVATOR.VQA \\\n\tFLARE.VQA \\\n\tFROZEN.VQA \\\n\tGRVESTNE.VQA \\\n\tLANDING.VQA \\\n\tMASASSLT.VQA \\\n\tMCV.VQA \\\n\tMCV_LAND.VQA \\\n\tMONTPASS.VQA \\\n\tOILDRUM.VQA \\\n\tOVERRUN.VQA \\\n\tPROLOG.VQA \\\n\tREDINTRO.VQA \\\n\tSHIPSINK.VQA \\\n\tSHORBOM1.VQA \\\n\tSHORBOM2.VQA \\\n\tSHORBOMB.VQA \\\n\tSNOWBOMB.VQA \\\n\tSOVIET1.VQA \\\n\tSOVTSTAR.VQA \\\n\tSPY.VQA \\\n\tTANYA1.VQA \\\n\tTANYA2.VQA \\\n\tTOOFAR.VQA \\\n\tTRINITY.VQA \\\n#\tTRAILER.VQA \\\n\nSOVIETVQ = \\\n       \tAAGUN.VQA \\\n\tCRONFAIL.VQA \\\n\tAIRFIELD.VQA \\\n\tALLY1.VQA \\\n\tALLYMORF.VQA \\\n\tAVERTED.VQA \\\n\tBEACHEAD.VQA \\\n\tBMAP.VQA \\\n\tBOMBRUN.VQA \\\n\tCOUNTDWN.VQA \\\n\tDOUBLE.VQA \\\n\tDPTHCHRG.VQA \\\n\tEXECUTE.VQA \\\n\tFLARE.VQA \\\n\tLANDING.VQA \\\n\tMCVBRDGE.VQA \\\n\tMIG.VQA \\\n\tMOVINGIN.VQA \\\n\tMTNKFACT.VQA \\\n\tNUKESTOK.VQA \\\n\tONTHPRWL.VQA \\\n\tPERISCOP.VQA \\\n\tPROLOG.VQA \\\n\tRADRRAID.VQA \\\n\tREDINTRO.VQA \\\n\tSEARCH.VQA \\\n\tSFROZEN.VQA \\\n\tSITDUCK.VQA \\\n\tSLNTSRVC.VQA \\\n\tSNOWBOMB.VQA \\\n\tSNSTRAFE.VQA \\\n\tSOVBATL.VQA \\\n\tSOVCEMET.VQA \\\n\tSOVFINAL.VQA \\\n\tSOVIET1.VQA \\\n\tSOVIET10.VQA \\\n\tSOVIET11.VQA \\\n\tSOVIET12.VQA \\\n\tSOVIET13.VQA \\\n\tSOVIET14.VQA \\\n\tSOVIET2.VQA \\\n\tSOVIET3.VQA \\\n\tSOVIET4.VQA \\\n\tSOVIET5.VQA \\\n\tSOVIET6.VQA \\\n\tSOVIET7.VQA \\\n\tSOVIET8.VQA \\\n\tSOVIET9.VQA \\\n\tSOVMCV.VQA \\\n\tSOVTSTAR.VQA \\\n\tSPOTTER.VQA \\\n\tSTRAFE.VQA \\\n\tTAKE_OFF.VQA \\\n\tTESLA.VQA \\\n\tV2ROCKET.VQA \\\n#\tTRAILER.VQA \\\n\nALLIESVQ = \\\n\tAFTRMATH.VQA \\\n\tALLY1.VQA \\\n\tALLYMORF.VQA \\\n\tAPCESCPE.VQA \\\n BATTLE.VQA \\\n\tBMAP.VQA \\\t\n\tCRONFAIL.VQA \\\n DPTHCHRG.VQA \\\n\tEXECUTE.VQA \\\n\tFLARE.VQA \\\t\n\tFROZEN.VQA \\\n\tGRVESTNE.VQA \\\n\tLANDING.VQA \\\n\tMASASSLT.VQA \\\n NUKESTOK.VQA \\\n ONTHPRWL.VQA \\\n\tOVERRUN.VQA \\\n\tPROLOG.VQA \\\n\tREDINTRO.VQA \\\n\tSFROZEN.VQA \\\n SLNTSRVC.VQA \\\n\tSNOWBOMB.VQA \\\n SNOWBASE.VQA \\\n SOVMCV.VQA \\\n\tSNSTRAFE.VQA \\\n\tSOVBATL.VQA \\\n\tSOVCEMET.VQA \\\n\tSOVIET1.VQA \\\n\tSOVTSTAR.VQA \\\n\tSPY.VQA \\\n STRAFE.VQA \\\n\tTESLA.VQA \\\n\tTOOFAR.VQA \\\n\tTRINITY.VQA \\\n\tV2ROCKET.VQA \\\t\t\n#\tANTEND.VQA \\\n#\tANTINTRO.VQA \\\n\t\n\n\n# Files required for hires/Win95 version only\n#\n# This mix file is not cached\n#\nNOCACHEHIRESFILES= \\\n\tENGLISH.VQA \\\n\t$(ALLIESVQ:.VQA=.VQP) \\\n\t$(SOVIETVQ:.VQA=.VQP) \\\n       \n\nLINTOBJECTS1 = $(OBJECTS:,=)\nLINTOBJECTS = $(LINTOBJECTS1:.OBJ=.LOB)\n\n# Mixfiles that should reside on the CD-ROM drive.\nCD1MIXFILES = \\\n\tCONQUER.MIX \\\n\tEDHI.MIX \\\n\tEDLO.MIX \\\n\tGENERAL.MIX \\\n\tINTERIOR.MIX \\\n\tMOVIES1.MIX \\\n\tSCORES.MIX \\\n\tSNOW.MIX \\\n\tSOUNDS.MIX \\\n \tRUSSIAN.MIX \\\n\tALLIES.MIX \\\n\tTEMPERAT.MIX \\\n\t\n\n\n# Mixfiles that should reside on the hard drive.\nLOCALMIXFILES = \\\n\tEDITOR.MIX \\\n\tHIRES.MIX \\\n\tLOCAL.MIX \\\n\tLORES.MIX \\\n\tNCHIRES.MIX \\\n\tSPEECH.MIX \\\n\t\n\n# Mixfiles as they appear on the CD and hard drive.\nPACKFILES=\t$(.path.cd1)MAIN.MIX  EXPAND2.MIX  $(.path.cd1)tobreaki\\REDALERT.MIX\n\n\n# Ant assets SOME ASSETS ARE HERE FOR OVERRIDING\nEXPANDFILES= \\\n\tANT1.SHP \\\n\tANT2.SHP \\\n\tANT3.SHP \\\n\tQUEE.SHP \\\n\tCREDITS.ENG \\\n\tHILL01.TEM \\\n\tANTBITE.AUD \\\n\tANTDIE.AUD \\\n\tANTDIE.SHP \\\n\tLAR1.SHP \\\n\tLAR2.SHP \\\n\tTITLE.PCX \\\t\t\t\t\t\t\t  \n\tMISSION.INI \\\n\tBUZZY1.AUD \\       \n\tSTAVCMDR.AUD \\     \n\tSTAVCRSE.AUD \\     \n\tSTAVYES.AUD \\      \n\tSTAVMOV.AUD \\\n\tCONQUER.ENG \\   \n\tRAMBO1.AUD \\\n\tRAMBO2.AUD \\\n\tRAMBO3.AUD \\\n\tTITLE.CPS \\\n\tTUTORIAL.INI \\\n\tBMAP.VQP \\\n\tANTEND.VQP \\\n\tANTINTRO.VQP \\\n\n# Aftermath expansion files\nEXPAND2FILES= \\\n\tCARR.SHP \\\n\tCTNK.SHP \\\n\tDTRK.SHP \\\n\tMSUB.SHP \\\n\tQTNK.SHP \\\n\tTTNK.SHP \\\n\tSTNK.SHP \\\n\tAFTRMATH.INI \\\n\tANT1.SHP \\\n\tANT2.SHP \\\n\tANT3.SHP \\\n\tANTBITE.AUD \\\n\tANTDIE.AUD \\\n\tANTDIE.SHP \\\n\tBUZZY1.AUD \\       \n\tCONQUER.ENG \\   \n\tCREDITS.TXT \\\n\tHILL01.TEM \\\n\tLAR1.SHP \\\n\tLAR2.SHP \\\n\tMISSION.INI \\\n\tMPLAYER.INI \\\n\tQUEE.SHP \\\n\tSTAVCMDR.AUD \\     \n\tSTAVCRSE.AUD \\     \n\tSTAVYES.AUD \\      \n\tSTAVMOV.AUD \\\n TANK01.AUD \\\n\tTITLE.PCX \\\t\t\t\t\t\t\t  \n\tTITLE.CPS \\\n\tTUTORIAL.INI \\\n\tBMAP.VQP \\\n stup_fix.shp \\\n\n\n\n#############################################################\n# Rebuilds all the mixfiles.\t\t\t\t  \npackfiles:\talways $(PACKFILES)\n\nalways:\n\tcopy f:\\projects\\c&c0\\editor\\english\\*.mix $(.path.mix) /u\n\n\n####################################################################\n# All mixfiles that exist on the CD-ROM are embedded within this mega-mixfile.\n$(.path.cd1)MAIN.MIX: $(CD1MIXFILES)\n\tUTILS\\MIXFILE -k -I$(.path.mix) &&!\n\t$**\n! $(.path.cd1)$&.mix\n\n\n# All mixfiles that exist in the local directory are embedded within this mega-mixfile.\n$(.path.cd1)install\\REDALERT.MIX: $(LOCALMIXFILES)\n\tUTILS\\MIXFILE -k  -I$(.path.mix) &&!\n\t$**\n! $(.path.cd1)install\\$&.mix\n\n\n####################################################################\n# These are the various sub-mixfiles.\nCONQUER.MIX: $(CONQUERFILES) $(CACHEMAP) .\\key.ini\n\tUTILS\\MIXFILE -k -h -I$(.path.cps) &&!\n\t$(CONQUERFILES) $(CACHEMAP)\n! $(.path.mix)$&.mix\n\nTEMPERAT.MIX: $(TEMPERATEFILES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -I$(.path.cps) &&!\n\t$(TEMPERATEFILES)\n! $(.path.mix)$&.mix\n\nSNOW.MIX: $(SNOWFILES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -I$(.path.cps) &&!\n\t$(SNOWFILES)\n! $(.path.mix)$&.mix\n\nINTERIOR.MIX: $(INTERIORFILES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -I$(.path.cps) &&!\n\t$(INTERIORFILES)\n! $(.path.mix)$&.mix\n\nGENERAL.MIX: $(GENERALFILES) $(GENERALMAPFILES) $(NETMAPFILES) $(MAPFILES) .\\key.ini\n\tUTILS\\MIXFILE -k -I$(.path.cps) -I$(.path.ini) &&!\n\t$(GENERALFILES) $(GENERALMAPFILES) $(NETMAPFILES) $(MAPFILES)\n! $(.path.mix)$&.mix\n\nSCORES.MIX: $(SCOREFILES)\n\tUTILS\\MIXFILE -k -I$(.path.cps) -I$(.path.ini) &&!\n\t$**\n! $(.path.mix)$&.mix\n\nSOUNDS.MIX: $(WAVFILES) $(SFX)\n\tUTILS\\MIXFILE -h -k -EA60=V00 -EA61=V01 -EA62=V02 -EA63=V03 -I$(.path.aud) &&!\n\t$**\n! $(.path.mix)$&.mix\n\nRUSSIAN.MIX: $(RESPONSE1:.AUD=.R00) $(RESPONSE2:.AUD=.R01) $(RESPONSE1:.AUD=.R02) $(RESPONSE2:.AUD=.R03)\n\tUTILS\\MIXFILE -h -k -I$(.path.aud) &&!\n\t$**\n! $(.path.mix)$&.mix\n\nLIMITED.MIX: BLEEP11.AUD\n\tUTILS\\MIXFILE -h -k -I$(.path.aud) &&!\n\t$**\n! $(.path.mix)$&.mix\n\nALLIES.MIX: $(RESPONSE1:.AUD=.V00) $(RESPONSE2:.AUD=.V01) $(RESPONSE1:.AUD=.V02) $(RESPONSE2:.AUD=.V03)\n\tUTILS\\MIXFILE -h -k -I$(.path.aud) &&!\n\t$**\n! $(.path.mix)$&.mix\n\nMOVIES1.MIX: $(ALLIESVQ)\n\tUTILS\\MIXFILE -k -I$(.path.vqa) &&!\n\t$**\n! $(.path.mix)$&.mix\n\n\n\n\n\nNCHIRES.MIX: $(NOCACHEHIRESFILES:.SHP=.HI)\n\tUTILS\\MIXFILE -k -I$(.path.vqp) -I$(.path.cps) &&!\n\t$(NOCACHEHIRESFILES)\n! $(.path.mix)$&.mix\n\nLOCAL.MIX: $(LOCALFILES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -E.A6=.AUD -I$(.path.ini) -I$(.path.txt) -I$(.path.cps) &&!\n\t$(LOCALFILES)\n! $(.path.mix)$&.mix\n\nLORES.MIX: $(LOHILORES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -E.LOW=.SHP -E.LNT=.FNT -I$(.path.cps) &&!\n\t$(LOHILORES)\n! $(.path.mix)$&.mix\n\nHIRES.MIX: $(HIRESFILES:.SHP=.HI) $(HIHILORES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -E.HI=.SHP -E.HNT=.FNT -I$(.path.cps) &&!\n\t$(HIRESFILES:.SHP=.HI) $(HIHILORES)\n! $(.path.mix)$&.mix\n\nLORES1.MIX: $(LOHILORES1) .\\key.ini\n\tUTILS\\MIXFILE -h -k -E.LOW=.SHP -E.LNT=.FNT -I$(.path.cps) &&!\n\t$(LOHILORES1)\n! $(.path.mix)$&.mix\n\nHIRES1.MIX: $(HIHILORES1) .\\key.ini\n\tUTILS\\MIXFILE -h -k -E.HI=.SHP -E.HNT=.FNT -I$(.path.cps) &&!\n\t$(HIHILORES1)\n! $(.path.mix)$&.mix\n\nSPEECH.MIX: $(SPEECHFILES)\n\tUTILS\\MIXFILE -k -I$(.path.aud) &&!\n\t$**\n! $(.path.mix)$&.mix\n\n\nEXPAND.MIX: $(EXPANDFILES)\t\t\t   \n\tUTILS\\MIXFILE -k  -I$(.path.mix)  &&!\n\t$**\n! $(.path.mix)$&.mix\n\nEXPAND2.MIX: $(EXPAND2FILES)\t\t\t   \n\tUTILS\\MIXFILE -k  -I$(.path.mix)  &&!\n\t$**\n! $(.path.mix)$&.mix\n\n#############################################################\n# Special rule to create the mouse shape (which must be a shape file)\nmouse.hi:\t$(.path.anm)hires\\mouse.anm\n\t-utils\\makeshps $(.path.lbm)palettes\\temperat.lbm &&!\n &$(.path.anm)hires\\mouse.anm;\n end;\n! $(.path.hi)$&.hi $(SHAPEBUFFSIZE)\n\n# Special rule to create the mouse shape (which must be a shape file)\nmouse.low:\t$(.path.anm)lores\\mouse.anm\n\t-utils\\makeshps $(.path.lbm)palettes\\temperat.lbm &&!\n &$(.path.anm)lores\\mouse.anm;\n end;\n! $(.path.low)$&.low $(SHAPEBUFFSIZE)\n\n\n#############################################################\n# Special build rule for radar animations so that they won't.\n#\nNATORADR.HI: $(.path.anm)hires\\NATORADR.ANM\n\tutils\\newkeyf $** $(.path.hi)$&.hi -l -k\n\nUSSRRADR.HI: $(.path.anm)hires\\USSRRADR.ANM\n\tutils\\newkeyf $** $(.path.hi)$&.hi -l -k\n\nNATORADR.LOW: $(.path.anm)lores\\NATORADR.ANM\n\tutils\\newkeyf $** $(.path.low)$&.low -l -k\n\nUSSRRADR.LOW: $(.path.anm)lores\\USSRRADR.ANM\n\tutils\\newkeyf $** $(.path.low)$&.low -l -k\n\n\n#############################################################\n# Debug text file creation.\ndebug.eng:\tdebug.txt\n\tutils\\textmake -b1000 eng\\$&.txt $(.path.eng)$&.eng $&.h\n\n\n"
  },
  {
    "path": "CODE/BFILE2.MAK",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n# $Header:   F:\\projects\\c&c0\\vcs\\code\\bfile.mav   5.0   11 Nov 1996 09:40:38   JOE_BOSTIC  $\n#***************************************************************************\n#**   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        **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Command & Conquer                        *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Joe L. Bostic                            *\n#*                                                                         *\n#*                   Start Date : March 25, 1993                           *\n#*                                                                         *\n#*                  Last Update : March 25, 1993   [JLB]                   *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n\n\n# Comment out the following line to disable \"include file autodependency\".\n.AUTODEPEND\n#.SWAP\n\n!include\t\"rules.mak\"\n\n\n##########################################################################\n\nMAPFILES = \\\n\nCACHEMAP = \\\n\tBRIEFING.AUD \\\n\tBAR3RED.SHP \\\n\tBAR3BLU.SHP \\\n\tCOUNTRYA.SHP \\\n\tCOUNTRYE.SHP \\\n\tCREDSA.SHP \\\n\tCREDSU.SHP \\\n\tHISCORE1.SHP \\\n\tHISCORE2.SHP \\\n\tTIME.SHP \\\n\tCLOCK1.AUD \\\n\tCOUNTRY4.AUD \\\n\tMAPWIPE2.AUD \\\n\tMAPWIPE5.AUD \\\n\tTONEY10.AUD \\\n\tTONEY4.AUD \\\n\tTONEY7.AUD \\\n\tSFX4.AUD \\\n\tBEEPY6.AUD \\\n\tKEYSTROK.AUD \\\n\tAPPEAR1.AUD \\\n\tSCOLD1.AUD \\\n\tCOUNTRY1.AUD \\\n\tALI-TRAN.WSA \\\n\tSOV-TRAN.WSA \\\n\tALIBACKH.PCX \\\n\tSOVBACKH.PCX \\\n\tBAR3RHR.SHP \\\n\tBAR3BHR.SHP \\\n\tCREDSAHR.SHP \\\n\tCREDSUHR.SHP \\\n\tHISC1-HR.SHP \\\n\tHISC2-HR.SHP \\\n\tTIMEHR.SHP \\\n\tMLTIPLYR.WSA \\\n\nLOCALFILES = \\\n\tPROLOG.CPS \\\n\tMAP.AUD \\\n\tTITLE.CPS \\\n\tPALETTE.CPS \\\n\tINTRO.AUD \\\n\tEGOPAL.PAL \\\n\tRULES.INI \\\n\tCREDITS.TXT \\\n\tALIPAPER.CPS \\\n\t3POINT.FNT \\\n\t8POINT.FNT \\\n\tEDITFNT.FNT \\\n\tCONQUER.ENG \\\n\tDEBUG.ENG \\\n\tLED.FNT \\\n\tSNOW.PAL \\\n\tTEMPERAT.PAL \\\n\tINTERIOR.PAL \\\n\tVCR.FNT \\\n\tHOLE0000.LUT \\\n\tHOLE0001.LUT \\\n\tHOLE0002.LUT \\\n\tHOLE0003.LUT \\\n\tHOLE0004.LUT \\\n\tHOLE0005.LUT \\\n\tHOLE0006.LUT \\\n\tHOLE0007.LUT \\\n\tHOLE0008.LUT \\\n\tHOLE0009.LUT \\\n\tHOLE0010.LUT \\\n\tHOLE0011.LUT \\\n\tHOLE0012.LUT \\\n\tHOLE0013.LUT \\\n\tHOLE0014.LUT \\\n\tHOLE0015.LUT \\\n\tHOLE0016.LUT \\\n\tHOLE0017.LUT \\\n\tHOLE0018.LUT \\\n\tHOLE0019.LUT \\\n\tHOLE0020.LUT \\\n\tHOLE0021.LUT \\\n\tHOLE0022.LUT \\\n\tHOLE0023.LUT \\\n\tHOLE0024.LUT \\\n\tHOLE0025.LUT \\\n\tHOLE0026.LUT \\\n\tHOLE0027.LUT \\\n\tHOLE0028.LUT \\\n\tHOLE0029.LUT \\\n\tHOLE0030.LUT \\\n\tHOLE0031.LUT \\\n\tHOLE0032.LUT \\\n\tHOLE0033.LUT \\\n\tHOLE0034.LUT \\\n\tHOLE0035.LUT \\\n\tHOLE0036.LUT \\\n\tHOLE0037.LUT \\\n\tHOLE0038.LUT \\\n\tHOLE0039.LUT \\\n\tHOLE0040.LUT \\\n\tHOLE0041.LUT \\\n\tHOLE0042.LUT \\\n\tHOLE0043.LUT \\\n\tHOLE0044.LUT \\\n\tHOLE0045.LUT \\\n\tHOLE0046.LUT \\\n\tHOLE0047.LUT \\\n#\tTEMPSCOR.FNT \\\n#\t6POINT.FNT \\\n#\tGRAD6FNT.FNT \\\n#\tSCOREFNT.FNT \\\n\n\n# Files that have counterparts in both high and low resolutions.\n# These files will be built into the HIRES.MIX and LORES.MIX files.\nHILORES = \\\n\tTRANICON.SHP \\\n\tPIPS.SHP \\\n\tPULSE.SHP \\\n\tATOMICON.SHP \\\n\tWARPICON.SHP \\\n\tC1.SHP \\\n\tC2.SHP \\\n\tCHAN.SHP \\\n\tDELPHI.SHP \\\n\tE1.SHP \\\n\tE2.SHP \\\n\tE3.SHP \\\n\tE4.SHP \\\n\tE5.SHP \\\n\tE6.SHP \\\n\tE7.SHP \\\n\tEINSTEIN.SHP \\\n\tGNRL.SHP \\\n\tMECH.SHP \\\n\tMEDI.SHP \\\n\tSHOK.SHP \\\n\tSPY.SHP \\\n\tTHF.SHP \\\n\tDD-BKGND.SHP \\\n\tDD-BOTM.SHP \\\n\tDD-CRNR.SHP \\\n\tDD-EDGE.SHP \\\n\tDD-LEFT.SHP \\\n\tDD-RIGHT.SHP \\\n\tDD-TOP.SHP \\\n\t12METFNT.FNT \\\n\tGRAD6FNT.FNT \\\n\tHELP.FNT \\\n\t6POINT.FNT \\\n\tTYPE.FNT \\\n\tSCOREFNT.FNT \\\n\t1TNKICON.SHP \\\n\t2TNKICON.SHP \\\n\t3TNKICON.SHP \\\n\t4TNKICON.SHP \\\n\tAFLDICON.SHP \\\n\tAGUNICON.SHP \\\n\tAPCICON.SHP \\\n\tAPWRICON.SHP \\\n\tARTYICON.SHP \\\n\tATEKICON.SHP \\\n\tBADRICON.SHP \\\n\tBARRICON.SHP \\\n\tBRIKICON.SHP \\\n\tBTN-DN.SHP \\\n\tBTN-PL.SHP \\\n\tBTN-ST.SHP \\\n\tBTN-UP.SHP \\\n\tCAICON.SHP \\\n\tCAMICON.SHP \\\n\tCARRICON.SHP \\\n\tCLOCK.SHP \\\n\tCTNKICON.SHP \\\n\tDDICON.SHP \\\n\tDOGICON.SHP \\\n\tDOMEICON.SHP \\\n\tDOMFICON.SHP \\\n\tDTRKICON.SHP \\\n\tE1ICON.SHP \\\n\tE2ICON.SHP \\\n\tE3ICON.SHP \\\n\tE4ICON.SHP \\\n\tE6ICON.SHP \\\n\tE7ICON.SHP \\\n\tFACFICON.SHP \\\n\tFACTICON.SHP \\\n\tFENCICON.SHP \\\n\tFIXICON.SHP \\\n\tFTURICON.SHP \\\n\tGAPICON.SHP \\\n\tGPSSICON.SHP \\\n\tGUNICON.SHP \\\n\tHARVICON.SHP \\\n\tHBOXICON.SHP \\\n\tHELIICON.SHP \\\n\tHINDICON.SHP \\\n\tHPADICON.SHP \\\n\tINFXICON.SHP \\\n\tIRONICON.SHP \\\n\tJEEPICON.SHP \\\n\tKENNICON.SHP \\\n\tLSTICON.SHP \\\n\tMAP.SHP \\\n\tMCVICON.SHP \\\n\tMECHICON.SHP \\\n\tMEDIICON.SHP \\\n\tMGGICON.SHP \\\n\tMIGICON.SHP \\\n\tMNLYICON.SHP \\\n\tMOUSE.SHP \\\n\tMRJICON.SHP \\\n\tMSLOICON.SHP \\\n\tMSUBICON.SHP \\\n\tNATORADR.SHP \\\n\tPBMBICON.SHP \\\n\tPBOXICON.SHP \\\n\tPDOXICON.SHP \\\n\tPINFICON.SHP \\\n\tPOWER.SHP \\\n\tPOWERBAR.SHP \\\n\tPOWRICON.SHP \\\n\tPROCICON.SHP \\\n\tPTICON.SHP \\\n\tQTNKICON.SHP \\\n\tREPAIR.SHP \\\n\tSAMICON.SHP \\\n\tSBAGICON.SHP \\\n\tSELL.SHP \\\n\tSHOKICON.SHP \\\n\tSIDEBAR.SHP \\\n\tSILOICON.SHP \\\n\tSMIGICON.SHP \\\n\tSONRICON.SHP \\\n\tSOVPAPER.CPS \\\n\tSPEFICON.SHP \\\n\tSPENICON.SHP \\\n\tSPYICON.SHP \\\n\tSSICON.SHP \\\n\tSTEKICON.SHP \\\n\tSTRIP.SHP \\\n\tSTRIPDN.SHP \\\n\tSTRIPUP.SHP \\\n\tSYRDICON.SHP \\\n\tSYRFICON.SHP \\\n\tTABS.SHP \\\n\tTENTICON.SHP \\\n\tTHFICON.SHP \\\n\tTRUKICON.SHP \\\n\tTTNKICON.SHP \\\n\tTSLAICON.SHP \\\n\tU2ICON.SHP \\\n\tUSSRRADR.SHP \\\n\tV2RLICON.SHP \\\n\tWEAFICON.SHP \\\n\tWEAPICON.SHP \\\n\tYAKICON.SHP \\\n\tNRADRFRM.SHP \\\n\tURADRFRM.SHP \\\n\tSIDE1NA.SHP \\\n\tSIDE1US.SHP \\\n\tSIDE2NA.SHP \\\n\tSIDE2US.SHP \\\n\tSIDE3NA.SHP \\\n\tSIDE3US.SHP \\\n\tSTRIPNA.SHP \\\n\tSTRIPUS.SHP \\\n\n#\tMOEBICON.SHP \\\n\n# These helper macros substitute the extension so that\n# the appropriate art build rule will be invoked.\nxLOHILORES = $(HILORES:.SHP=.LOW)\nLOHILORES = $(xLOHILORES:.FNT=.LNT)\nxHIHILORES = $(HILORES:.SHP=.HI)\nHIHILORES = $(xHIHILORES:.FNT=.HNT)\n\n#\n# Files required for hires/Win95 version only\n#\n# This mix file is cached\n#\nHIRESFILES = \\\n\tALIPAPER.PCX \\\n      \tPROLOG.PCX \\\n\tSOVPAPER.PCX \\\n\tAFTR_HI.PCX \\\n\tALY1.PCX \\\n\tAPC_HI.PCX \\\n\tAPHI0049.PCX \\\n\tBNHI0020.PCX \\\n\tDCHI0040.PCX \\\n\tFRHI0166.PCX \\\n\tLAB.PCX \\\n\tLANDSBRG.PCX \\\n\tMAHI0107.PCX \\\n\tMIG_HI.PCX \\\n\tMTFACTHI.PCX \\\n\tNEEDLE.PCX \\\n\tSOV2.PCX \\\n\tSPY.PCX \\\n\tSTALIN.PCX \\\n\tTENT.PCX \\\n#\tENG_HI.PCX \\\n\n\nCONQUERFILES = \\\n\tPARABOMB.SHP \\\n\tRADARFRM.SHP \\\n\tARMOR.SHP \\\n\tFPOWER.SHP \\\n\tSPEED.SHP \\\n\tTQUAKE.SHP \\\n\tH2O_EXP1.SHP \\\n\tH2O_EXP2.SHP \\\n\tH2O_EXP3.SHP \\\n\tFLAK.SHP \\\n\tEBTN-DN.SHP \\\n\tEBTN-UP.SHP \\\n\tATOMSFX.SHP \\\n\tTWINKLE1.SHP \\\n\tTWINKLE2.SHP \\\n\tTWINKLE3.SHP \\\n\tCHRONBOX.SHP \\\n\tGPSBOX.SHP \\\n\tINVULBOX.SHP \\\n\tPARABOX.SHP \\\n\tSONARBOX.SHP \\\n\tSPUTNIK.SHP \\\n\tSPUTDOOR.SHP \\\n\tATOMICDN.SHP \\\n\tATOMICUP.SHP \\\n\tTYPE.FNT \\\n\t120MM.SHP \\\n\t1TNK.SHP \\\n\t2TNK.SHP \\\n\t3TNK.SHP \\\n\t4TNK.SHP \\\n\t50CAL.SHP \\\n\tAFLD.SHP \\\n\tAGUN.SHP \\\n\tAPC.SHP \\\n\tAPWR.SHP \\\n\tART-EXP1.SHP \\\n\tARTY.SHP \\\n\tATEK.SHP \\\n\tBADR.SHP \\\n\tBARB.SHP \\\n\tBARL.SHP \\\n\tBARR.SHP \\\n\tBIO.SHP \\\n\tBOMB.SHP \\\n\tBOMBLET.SHP \\\n\tBRIK.SHP \\\n\tBRL3.SHP \\\n\tBURN-L.SHP \\\n\tBURN-M.SHP \\\n\tBURN-S.SHP \\\n\tCA.SHP \\\n\tCYCL.SHP \\\n\tDD.SHP \\\n\tDEVIATOR.SHP \\\n\tDOG.SHP \\\n\tDOGBULLT.SHP \\\n\tDOLLAR.SHP \\\n\tDOME.SHP \\\n\tDRAGON.SHP \\\n\tEARTH.SHP \\\n\tELECTDOG.SHP \\\n\tEMPULSE.SHP \\\n\tFACT.SHP \\\n\tFB1.SHP \\\n\tFB2.SHP \\\n\tFBALL1.SHP \\\n\tFCOM.SHP \\\n\tFENC.SHP \\\n\tFIRE1.SHP \\\n\tFIRE2.SHP \\\n\tFIRE3.SHP \\\n\tFIRE4.SHP \\\n\tFIX.SHP \\\n\tFLAGFLY.SHP \\\n\tFLMSPT.SHP \\\n\tFPLS.SHP \\\n\tFRAG1.SHP \\\n\tFTNK.SHP \\\n\tFTUR.SHP \\\n\tGAP.SHP \\\n\tGUN.SHP \\\n\tGUNFIRE.SHP \\\n\tHARV.SHP \\\n\tHELI.SHP \\\n\tHIND.SHP \\\n\tHOSP.SHP \\\n\tHPAD.SHP \\\n\tINVUN.SHP \\\n\tIRON.SHP \\\n\tJEEP.SHP \\\n\tKENN.SHP \\\n\tLITNING.SHP \\\n\tLROTOR.SHP \\\n\tLST.SHP \\\n\tMCV.SHP \\\n\tMGG.SHP \\\n\tMGUN.SHP \\\n\tMHQ.SHP \\\n\tMIG.SHP \\\n\tMINE.SHP \\\n\tMINIGUN.SHP \\\n\tMINP.SHP \\\n\tMINV.SHP \\\n\tMISS.SHP \\\n\tMISSILE.SHP \\\n\tMISSILE2.SHP \\\n\tMLRS.SHP \\\n\tMNLY.SHP \\\n\tMRJ.SHP \\\n\tNAPALM1.SHP \\\n\tNAPALM2.SHP \\\n\tNAPALM3.SHP \\\n\tORCA.SHP \\\n\tPARACH.SHP \\\n\tPATRIOT.SHP \\\n\tPBOX.SHP \\\n\tPDOX.SHP \\\n\tPIFF.SHP \\\n\tPIFFPIFF.SHP \\\n\tPOWR.SHP \\\n\tPROC.SHP \\\n\tPT.SHP \\\n\tRAPID.SHP \\\n\tRROTOR.SHP \\\n\tSAM.SHP \\\n\tSAMFIRE.SHP \\\n\tSBAG.SHP \\\n\tSCRATE.SHP \\\n\tSELECT.SHP \\\n\tSHADOW.SHP \\\n\tSILO.SHP \\\n\tSMIG.SHP \\\n\tSMOKEY.SHP \\\n\tSMOKE_M.SHP \\\n\tSMOKLAND.SHP \\\n\tSPEN.SHP \\\n\tSS.SHP \\\n\tSSAM.SHP \\\n\tSTEALTH2.SHP \\\n\tSTEK.SHP \\\n\tSTNK.SHP \\\n\tSYRD.SHP \\\n\tTENT.SHP \\\n\tTRAN.SHP \\\n\tTRANS.ICN \\\n\tTRUK.SHP \\\n\tTSLA.SHP \\\n\tTURR.SHP \\\n\tU2.SHP \\\n\tV19.SHP \\\n\tV2.SHP \\\n\tV2RL.SHP \\\n\tVEH-HIT1.SHP \\\n\tVEH-HIT2.SHP \\\n\tVEH-HIT3.SHP \\\n\tWAKE.SHP \\\n\tWCRATE.SHP \\\n\tWWCRATE.SHP \\\n\tWEAP.SHP \\\n\tWEAP2.SHP \\\n\tWOOD.SHP \\\n\tYAK.SHP \\\n\tAFLDMAKE.SHP \\\n\tAGUNMAKE.SHP \\\n\tAPWRMAKE.SHP \\\n\tATEKMAKE.SHP \\\n\tBARRMAKE.SHP \\\n\tBIOMAKE.SHP \\\n\tDOMEMAKE.SHP \\\n\tFACTMAKE.SHP \\\n\tFIXMAKE.SHP \\\n\tFTURMAKE.SHP \\\n\tGAPMAKE.SHP \\\n\tGUNMAKE.SHP \\\n\tHOSPMAKE.SHP \\\n\tHPADMAKE.SHP \\\n\tIRONMAKE.SHP \\\n\tKENNMAKE.SHP \\\n\tMINPMAKE.SHP \\\n\tMINVMAKE.SHP \\\n\tPBOXMAKE.SHP \\\n\tPOWRMAKE.SHP \\\n\tPDOXMAKE.SHP \\\n\tPROCMAKE.SHP \\\n\tPUMPMAKE.SHP \\\n\tSAMMAKE.SHP \\\n\tSILOMAKE.SHP \\\n\tSPENMAKE.SHP \\\n\tSTEKMAKE.SHP \\\n\tSYRDMAKE.SHP \\\n\tTENTMAKE.SHP \\\n\tTSLAMAKE.SHP \\\n\tWEAPMAKE.SHP \\\n\nGENERALMAPFILES = \\\n\tMISSIONS.PKT \\\n\tTUTORIAL.INI \\\n\tSCA01EA.INI \\\n\tSCA02EA.INI \\\n\tSCA03EA.INI \\\n\tSCA04EA.INI \\\n        SCG01EA.INI \\     \n        SCG40EA.INI \\     \n        SCG41EA.INI \\     \n        SCG42EA.INI \\     \n        SCG43EA.INI \\     \n        SCG44EA.INI \\     \n        SCG45EA.INI \\     \n        SCG46EA.INI \\     \n        SCG47EA.INI \\     \n        SCG48EA.INI \\     \n        SCU40EA.INI \\     \n        SCU41EA.INI \\     \n        SCU42EA.INI \\     \n        SCU43EA.INI \\     \n        SCU44EA.INI \\     \n        SCU45EA.INI \\     \n        SCU46EA.INI \\     \n        SCU47EA.INI \\     \n        SCU48EA.INI \\     \n\tSCU01EA.INI \\     \n\tSCM01EA.INI \\      \n\tSCM02EA.INI \\ \n\tSCM03EA.INI \\ \n\tSCM04EA.INI \\ \n\tSCM05EA.INI \\ \n\tSCM06EA.INI \\ \n\tSCM07EA.INI \\ \n\tSCM08EA.INI \\ \n\tSCM09EA.INI \\ \n\tSCM10EA.INI \\ \n\tSCM11EA.INI \\ \n\tSCM12EA.INI \\ \n\tSCM13EA.INI \\ \n\tSCM14EA.INI \\ \n\tSCM15EA.INI \\ \n\tSCM16EA.INI \\ \n\tSCM17EA.INI \\ \n\tSCM18EA.INI \\ \n\tSCM19EA.INI \\ \n\tSCM20EA.INI \\ \n\tSCM21EA.INI \\ \n\tSCM22EA.INI \\ \n\tSCM23EA.INI \\ \n\tSCM24EA.INI \\ \n    \tSCM25EA.INI \\\n\tSCM26EA.INI \\\n\tSCM27EA.INI \\\n\tSCM28EA.INI \\\n\tSCM29EA.INI \\\n\tSCM30EA.INI \\\n\tSCM31EA.INI \\ \n\tSCM32EA.INI \\ \n\tSCM33EA.INI \\\n\tSCM34EA.INI \\\n     \tSCM35EA.INI \\\n\tSCM36EA.INI \\\n\tSCM37EA.INI \\\n\tSCM38EA.INI \\\n\tSCM39EA.INI \\\n\tSCM40EA.INI \\\n\tSCM41EA.INI \\\n\tSCM42EA.INI \\\n\tSCM43EA.INI \\\n\tSCM44EA.INI \\\n\tSCM45EA.INI \\\n\tSCM46EA.INI \\\n\tSCM47EA.INI \\\n\tSCM48EA.INI \\\n\tSCM49EA.INI \\\n\tSCM50EA.INI \\\n\tSCM51EA.INI \\\n\tSCM52EA.INI \\\n\tSCM53EA.INI \\\n\tSCM54EA.INI \\\n\tSCM55EA.INI \\\n\tSCM56EA.INI \\\n\tSCM57EA.INI \\\n\tSCM58EA.INI \\\n\tSCM59EA.INI \\\n\tSCM60EA.INI \\\n\tSCM61EA.INI \\\n\tSCM62EA.INI \\\n\tSCM63EA.INI \\\n\tSCM64EA.INI \\\n\tSCM65EA.INI \\\n\tSCM66EA.INI \\\n\tSCM67EA.INI \\\n\tSCM68EA.INI \\\n\tSCM69EA.INI \\\n\tSCM70EA.INI \\\n\tSCM71EA.INI \\\n\tSCM72EA.INI \\\n\tSCM73EA.INI \\\n\tSCM74EA.INI \\\n\tSCM75EA.INI \\\n\tSCM76EA.INI \\\n\tSCM77EA.INI \\\n\tSCM78EA.INI \\\n\tSCM79EA.INI \\\n\tSCM80EA.INI \\\n\tSCM81EA.INI \\\n\tSCM82EA.INI \\\n\tSCM83EA.INI \\\n\tSCM84EA.INI \\\n\tSCM85EA.INI \\\n\tSCM86EA.INI \\\n\tSCM87EA.INI \\\n\tSCM88EA.INI \\\n\tSCM89EA.INI \\\t\n\tSCM90EA.INI \\\n\tSCM91EA.INI \\\n\tSCM92EA.INI \\\n\tSCM93EA.INI \\\n\tSCM94EA.INI \\\n\tSCM95EA.INI \\\n\tSCM96EA.INI \\\n\tSCM97EA.INI \\\n\tSCM98EA.INI \\\n\tSCM99EA.INI \\\n\tSCM100EA.INI \\\n\tSCM101EA.INI \\\n\tSCM102EA.INI \\\n\tSCM103EA.INI \\\n\tSCM104EA.INI \\\n\tSCM105EA.INI \\\n\tSCM106EA.INI \\\n\tSCM107EA.INI \\\n\tSCM108EA.INI \\\n\tSCM109EA.INI \\\n\tSCM110EA.INI \\\n\tSCM111EA.INI \\\n\tSCM112EA.INI \\\n\tSCM113EA.INI \\\n\tSCM114EA.INI \\\n\tSCM115EA.INI \\\n\tSCM116EA.INI \\\n\tSCM117EA.INI \\\n\tSCM118EA.INI \\\n \tSCM119EA.INI \\    \n\tSCM120EA.INI \\     \n\tSCM121EA.INI \\    \n\tSCM122EA.INI \\     \n\tSCM123EA.INI \\    \n\tSCM124EA.INI \\    \n\tSCM125EA.INI \\    \n\tSCM126EA.INI \\    \n\tSCM127EA.INI \\    \n\tSCM128EA.INI \\    \n\tSCM129EA.INI \\ \n\tSCM130EA.INI \\   \n\tSCMD0EA.INI \\\n\tSCMD1EA.INI \\\n\tSCMD2EA.INI \\\n\tSCMD3EA.INI \\\n\tSCMD4EA.INI \\\n\tSCMD5EA.INI \\\n\tSCMD6EA.INI \\\n\tSCMD7EA.INI \\\n\tSCMD8EA.INI \\\n\tSCMD9EA.INI \\\n\tSCME0EA.INI \\\n\tSCME1EA.INI \\\n\tSCME2EA.INI \\\n\tSCME3EA.INI \\\n\tSCME4EA.INI \\\n\tSCME5EA.INI \\\n\tSCME6EA.INI \\\n\tSCME7EA.INI \\\n\tSCME8EA.INI \\\n\tSCME9EA.INI \\\n\tSCMF0EA.INI \\\n\tSCMF1EA.INI \\\n\tSCMF2EA.INI \\\n\tSCMF3EA.INI \\\n\tSCMF4EA.INI \\\n\tSCMF5EA.INI \\\n\tSCMF6EA.INI \\\n\tSCMF7EA.INI \\\n\tSCMF8EA.INI \\\n\tSCMF9EA.INI \\\n\tSCMG0EA.INI \\\n\tSCMG1EA.INI \\\n\tSCMG2EA.INI \\\n\tSCMG3EA.INI \\\n\tSCMG4EA.INI \\\n\tSCMG5EA.INI \\\n\tSCMG6EA.INI \\\n\tSCMG7EA.INI \\\n\tSCMG8EA.INI \\\n\tSCMG9EA.INI \\\n\tSCMH0EA.INI \\\n\tSCMH1EA.INI \\\n\tSCMH2EA.INI \\\n\tSCMH3EA.INI \\\n\tSCMH4EA.INI \\\n\tSCMH5EA.INI \\\n\tSCMH6EA.INI \\\n\tSCMH7EA.INI \\\n\tSCMH8EA.INI \\\n\tSCMH9EA.INI \\\n\tSCMI0EA.INI \\\n\tSCMI1EA.INI \\\n\tSCMI2EA.INI \\\n\tSCMI3EA.INI \\\n\tSCMI4EA.INI \\\n\tSCMI5EA.INI \\\n\tSCMI6EA.INI \\\n\tSCMI7EA.INI \\\n\tSCMI8EA.INI \\\n\tSCMI9EA.INI \\\n\tSCMJ0EA.INI \\\n\tSCMJ1EA.INI \\\n\tSCMJ2EA.INI \\\n\tSCMJ3EA.INI \\\n\tSCMJ4EA.INI \\\n\tSCMJ5EA.INI \\\n\tSCMJ6EA.INI \\\n\tSCMJ7EA.INI \\\n\tSCMJ8EA.INI \\\n\tSCMJ9EA.INI \\\n\tSCMK0EA.INI \\\n\tSCMK1EA.INI \\\n\tSCMK2EA.INI \\\n\tSCMK3EA.INI \\\n\tSCMK4EA.INI \\\n\tSCMK5EA.INI \\\n\tSCMK6EA.INI \\\n\tSCMK7EA.INI \\\n\tSCMK8EA.INI \\\n\tSCMK9EA.INI \\\n\tSCML0EA.INI \\\n\tSCML1EA.INI \\\n\tSCML2EA.INI \\\n\tSCML3EA.INI \\\n\tSCML4EA.INI \\\n\tSCML5EA.INI \\\n\tSCML6EA.INI \\\n\tSCML7EA.INI \\\n\tSCML8EA.INI \\\n\tSCML9EA.INI \\\n\tSCMM0EA.INI \\\n\tSCMM1EA.INI \\\n\tSCMM2EA.INI \\\n\tSCMM3EA.INI \\\n\tSCMM4EA.INI \\\n\tSCMM5EA.INI \\\n\tSCMM6EA.INI \\\n\tSCMM7EA.INI \\\n\tSCMM8EA.INI \\\n\tSCMM9EA.INI \\\n   \nNETMAPFILES = \\\n\n# Files that aren't cached.\nGENERALFILES = \\\n\tAFTR_LO.CPS \\\n\tALY1-LO.CPS \\\n\tAPC_LO.CPS \\\n\tAPLO0049.CPS \\\n\tBNLO0020.CPS \\\n\tDCLO0040.CPS \\\n\tFRLO0166.CPS \\\n\tLAB-LO.CPS \\\n\tLANDS-LO.CPS \\\n\tMALO0107.CPS \\\n\tMIG_LO.CPS \\\n\tMTFACTLO.CPS \\\n\tNEEDL-LO.CPS \\\n\tSOV2-LO.CPS \\\n\tSPY-LO.CPS \\\n\tSTALN-LO.CPS \\\n\tTENT-LO.CPS \\\n\tTITLE.CPS \\\n\tPPAPER.CPS \\\n\tMSAA.WSA \\\n\tMSAB.WSA \\\n\tMSAC.WSA \\\n\tMSAD.WSA \\\n\tMSAE.WSA \\\n\tMSAF.WSA \\\n\tMSAG.WSA \\\n\tMSAH.WSA \\\n\tMSAI.WSA \\\n\tMSAJ.WSA \\\n\tMSAK.WSA \\\n\tMSAL.WSA \\\n\tMSAM.WSA \\\n\tMSAN.WSA \\\n\tMSSA.WSA \\\n\tMSSB.WSA \\\n\tMSSC.WSA \\\n\tMSSD.WSA \\\n\tMSSE.WSA \\\n\tMSSF.WSA \\\n\tMSSG.WSA \\\n\tMSSH.WSA \\\n\tMSSI.WSA \\\n\tMSSJ.WSA \\\n\tMSSK.WSA \\\n\tMSSL.WSA \\\n\tMSSM.WSA \\\n\tMSSN.WSA \\\n\nINTERIORFILES = \\\n\tBOXES01.INT \\\n\tBOXES02.INT \\\n\tBOXES03.INT \\\n\tBOXES04.INT \\\n\tBOXES05.INT \\\n\tBOXES06.INT \\\n\tBOXES07.INT \\\n\tBOXES08.INT \\\n\tBOXES09.INT \\\n\tXTRA0001.INT \\\n\tXTRA0002.INT \\\n\tXTRA0003.INT \\\n\tXTRA0004.INT \\\n\tXTRA0005.INT \\\n\tXTRA0006.INT \\\n\tXTRA0007.INT \\\n\tXTRA0008.INT \\\n\tXTRA0009.INT \\\n\tXTRA0010.INT \\\n\tXTRA0011.INT \\\n\tXTRA0012.INT \\\n\tXTRA0013.INT \\\n\tXTRA0014.INT \\\n\tXTRA0015.INT \\\n\tXTRA0016.INT \\\n\tCLEAR1.INT \\\n\tMOVEFLSH.INT \\\n\tARRO0001.INT \\\n\tARRO0002.INT \\\n\tARRO0003.INT \\\n\tARRO0004.INT \\\n\tARRO0005.INT \\\n\tARRO0006.INT \\\n\tARRO0007.INT \\\n\tARRO0008.INT \\\n\tARRO0009.INT \\\n\tARRO0010.INT \\\n\tARRO0011.INT \\\n\tARRO0012.INT \\\n\tARRO0013.INT \\\n\tARRO0014.INT \\\n\tARRO0015.INT \\\n\tFLOR0001.INT \\\n\tFLOR0002.INT \\\n\tFLOR0003.INT \\\n\tFLOR0004.INT \\\n\tFLOR0005.INT \\\n\tFLOR0006.INT \\\n\tFLOR0007.INT \\\n\tGFLR0001.INT \\\n\tGFLR0002.INT \\\n\tGFLR0003.INT \\\n\tGFLR0004.INT \\\n\tGFLR0005.INT \\\n\tGSTR0001.INT \\\n\tGSTR0002.INT \\\n\tGSTR0003.INT \\\n\tGSTR0004.INT \\\n\tGSTR0005.INT \\\n\tGSTR0006.INT \\\n\tGSTR0007.INT \\\n\tGSTR0008.INT \\\n\tGSTR0009.INT \\\n\tGSTR0010.INT \\\n\tGSTR0011.INT \\\n\tLWAL0001.INT \\\n\tLWAL0002.INT \\\n\tLWAL0003.INT \\\n\tLWAL0004.INT \\\n\tLWAL0005.INT \\\n\tLWAL0006.INT \\\n\tLWAL0007.INT \\\n\tLWAL0008.INT \\\n\tLWAL0009.INT \\\n\tLWAL0010.INT \\\n\tLWAL0011.INT \\\n\tLWAL0012.INT \\\n\tLWAL0013.INT \\\n\tLWAL0014.INT \\\n\tLWAL0015.INT \\\n\tLWAL0016.INT \\\n\tLWAL0017.INT \\\n\tLWAL0018.INT \\\n\tLWAL0019.INT \\\n\tLWAL0020.INT \\\n\tLWAL0021.INT \\\n\tLWAL0022.INT \\\n\tLWAL0023.INT \\\n\tLWAL0024.INT \\\n\tLWAL0025.INT \\\n\tLWAL0026.INT \\\n\tLWAL0027.INT \\\n\tSTRP0001.INT \\\n\tSTRP0002.INT \\\n\tSTRP0003.INT \\\n\tSTRP0004.INT \\\n\tSTRP0005.INT \\\n\tSTRP0006.INT \\\n\tSTRP0007.INT \\\n\tSTRP0008.INT \\\n\tSTRP0009.INT \\\n\tSTRP0010.INT \\\n\tSTRP0011.INT \\\n\tWALL0001.INT \\\n\tWALL0002.INT \\\n\tWALL0003.INT \\\n\tWALL0004.INT \\\n\tWALL0005.INT \\\n\tWALL0006.INT \\\n\tWALL0007.INT \\\n\tWALL0008.INT \\\n\tWALL0009.INT \\\n\tWALL0010.INT \\\n\tWALL0011.INT \\\n\tWALL0012.INT \\\n\tWALL0013.INT \\\n\tWALL0014.INT \\\n\tWALL0015.INT \\\n\tWALL0016.INT \\\n\tWALL0017.INT \\\n\tWALL0018.INT \\\n\tWALL0019.INT \\\n\tWALL0020.INT \\\n\tWALL0021.INT \\\n\tWALL0022.INT \\\n\tWALL0023.INT \\\n\tWALL0024.INT \\\n\tWALL0025.INT \\\n\tWALL0026.INT \\\n\tWALL0027.INT \\\n\tWALL0028.INT \\\n\tWALL0029.INT \\\n\tWALL0030.INT \\\n\tWALL0031.INT \\\n\tWALL0032.INT \\\n\tWALL0033.INT \\\n\tWALL0034.INT \\\n\tWALL0035.INT \\\n\tWALL0036.INT \\\n\tWALL0037.INT \\\n\tWALL0038.INT \\\n\tWALL0039.INT \\\n\tWALL0040.INT \\\n\tWALL0041.INT \\\n\tWALL0042.INT \\\n\tWALL0043.INT \\\n\tWALL0044.INT \\\n\tWALL0045.INT \\\n\tWALL0046.INT \\\n\tWALL0047.INT \\\n\tWALL0048.INT \\\n\tWALL0049.INT \\\n\n# Both the temperate and snow sets have identical template entries.\nTEMPERATEFILES = \\\n\tMINE.TEM \\\n\tICE01.TEM \\\n\tICE02.TEM \\\n\tICE03.TEM \\\n\tICE04.TEM \\\n\tICE05.TEM \\\n\tMOVEFLSH.TEM \\\n\tBR1X.TEM \\\n\tBR2X.TEM \\\n\tBRIDGE1X.TEM \\\n\tBRIDGE2X.TEM \\\n\tBRIDGE1H.TEM \\\n\tBRIDGE2H.TEM \\\n\tF01.TEM \\\n\tF02.TEM \\\n\tF03.TEM \\\n\tF04.TEM \\\n\tF05.TEM \\\n\tF06.TEM \\\n\tELECTRO.TEM \\\n\tB1.TEM \\\n\tB2.TEM \\\n\tB3.TEM \\\n\tBIB1.TEM \\\n\tBIB2.TEM \\\n\tBIB3.TEM \\\n\tBR1A.TEM \\\n\tBR1B.TEM \\\n\tBR1C.TEM \\\n\tBR2A.TEM \\\n\tBR2B.TEM \\\n\tBR2C.TEM \\\n\tBR3A.TEM \\\n\tBR3B.TEM \\\n\tBR3C.TEM \\\n\tBR3D.TEM \\\n\tBR3E.TEM \\\n\tBR3F.TEM \\\n\tBRIDGE1.TEM \\\n\tBRIDGE1D.TEM \\\n\tBRIDGE2.TEM \\\n\tBRIDGE2D.TEM \\\n\tCLEAR1.TEM \\\n\tCORPSE1.TEM \\\n\tCORPSE2.TEM \\\n\tCORPSE3.TEM \\\n\tCR1.TEM \\\n\tCR2.TEM \\\n\tCR3.TEM \\\n\tCR4.TEM \\\n\tCR5.TEM \\\n\tCR6.TEM \\\n\tD01.TEM \\\n\tD02.TEM \\\n\tD03.TEM \\\n\tD04.TEM \\\n\tD05.TEM \\\n\tD06.TEM \\\n\tD07.TEM \\\n\tD08.TEM \\\n\tD09.TEM \\\n\tD10.TEM \\\n\tD11.TEM \\\n\tD12.TEM \\\n\tD13.TEM \\\n\tD14.TEM \\\n\tD15.TEM \\\n\tD16.TEM \\\n\tD17.TEM \\\n\tD18.TEM \\\n\tD19.TEM \\\n\tD20.TEM \\\n\tD21.TEM \\\n\tD22.TEM \\\n\tD23.TEM \\\n\tD24.TEM \\\n\tD25.TEM \\\n\tD26.TEM \\\n\tD27.TEM \\\n\tD28.TEM \\\n\tD29.TEM \\\n\tD30.TEM \\\n\tD31.TEM \\\n\tD32.TEM \\\n\tD33.TEM \\\n\tD34.TEM \\\n\tD35.TEM \\\n\tD36.TEM \\\n\tD37.TEM \\\n\tD38.TEM \\\n\tD39.TEM \\\n\tD40.TEM \\\n\tD41.TEM \\\n\tD42.TEM \\\n\tD43.TEM \\\n\tD44.TEM \\\n\tD45.TEM \\\n\tFALLS1.TEM \\\n\tFALLS1A.TEM \\\n\tFALLS2.TEM \\\n\tFALLS2A.TEM \\\n\tFORD1.TEM \\\n\tFORD2.TEM \\\n\tGEM01.TEM \\\n\tGEM02.TEM \\\n\tGEM03.TEM \\\n\tGEM04.TEM \\\n\tGOLD01.TEM \\\n\tGOLD02.TEM \\\n\tGOLD03.TEM \\\n\tGOLD04.TEM \\\n\tHBOX.TEM \\\n\tMSLOMAKE.TEM \\\n\tHBOXMAKE.TEM \\\n\tMSLO.TEM \\\n\tP01.TEM \\\n\tP02.TEM \\\n\tP03.TEM \\\n\tP04.TEM \\\n\tP07.TEM \\\n\tP08.TEM \\\n\tP13.TEM \\\n\tP14.TEM \\\n\tRC01.TEM \\\n\tRC02.TEM \\\n\tRC03.TEM \\\n\tRC04.TEM \\\n\tRF01.TEM \\\n\tRF02.TEM \\\n\tRF03.TEM \\\n\tRF04.TEM \\\n\tRF05.TEM \\\n\tRF06.TEM \\\n\tRF07.TEM \\\n\tRF08.TEM \\\n\tRF09.TEM \\\n\tRF10.TEM \\\n\tRF11.TEM \\\n\tRV01.TEM \\\n\tRV02.TEM \\\n\tRV03.TEM \\\n\tRV04.TEM \\\n\tRV05.TEM \\\n\tRV06.TEM \\\n\tRV07.TEM \\\n\tRV08.TEM \\\n\tRV09.TEM \\\n\tRV10.TEM \\\n\tRV11.TEM \\\n\tRV12.TEM \\\n\tRV13.TEM \\\n\tRV14.TEM \\\n\tRV15.TEM \\\n\tS01.TEM \\\n\tS02.TEM \\\n\tS03.TEM \\\n\tS04.TEM \\\n\tS05.TEM \\\n\tS06.TEM \\\n\tS07.TEM \\\n\tS08.TEM \\\n\tS09.TEM \\\n\tS10.TEM \\\n\tS11.TEM \\\n\tS12.TEM \\\n\tS13.TEM \\\n\tS14.TEM \\\n\tS15.TEM \\\n\tS16.TEM \\\n\tS17.TEM \\\n\tS18.TEM \\\n\tS19.TEM \\\n\tS20.TEM \\\n\tS21.TEM \\\n\tS22.TEM \\\n\tS23.TEM \\\n\tS24.TEM \\\n\tS25.TEM \\\n\tS26.TEM \\\n\tS27.TEM \\\n\tS28.TEM \\\n\tS29.TEM \\\n\tS30.TEM \\\n\tS31.TEM \\\n\tS32.TEM \\\n\tS33.TEM \\\n\tS34.TEM \\\n\tS35.TEM \\\n\tS36.TEM \\\n\tS37.TEM \\\n\tS38.TEM \\\n\tSC1.TEM \\\n\tSC2.TEM \\\n\tSC3.TEM \\\n\tSC4.TEM \\\n\tSC5.TEM \\\n\tSC6.TEM \\\n\tSH01.TEM \\\n\tSH02.TEM \\\n\tSH03.TEM \\\n\tSH04.TEM \\\n\tSH05.TEM \\\n\tSH06.TEM \\\n\tSH07.TEM \\\n\tSH08.TEM \\\n\tSH09.TEM \\\n\tSH10.TEM \\\n\tSH11.TEM \\\n\tSH12.TEM \\\n\tSH13.TEM \\\n\tSH14.TEM \\\n\tSH15.TEM \\\n\tSH16.TEM \\\n\tSH17.TEM \\\n\tSH18.TEM \\\n\tSH19.TEM \\\n\tSH20.TEM \\\n\tSH21.TEM \\\n\tSH22.TEM \\\n\tSH23.TEM \\\n\tSH24.TEM \\\n\tSH25.TEM \\\n\tSH26.TEM \\\n\tSH27.TEM \\\n\tSH28.TEM \\\n\tSH29.TEM \\\n\tSH30.TEM \\\n\tSH31.TEM \\\n\tSH32.TEM \\\n\tSH33.TEM \\\n\tSH34.TEM \\\n\tSH35.TEM \\\n\tSH36.TEM \\\n\tSH37.TEM \\\n\tSH38.TEM \\\n\tSH39.TEM \\\n\tSH40.TEM \\\n\tSH41.TEM \\\n\tSH42.TEM \\\n\tSH43.TEM \\\n\tSH44.TEM \\\n\tSH45.TEM \\\n\tSH46.TEM \\\n\tSH47.TEM \\\n\tSH48.TEM \\\n\tSH49.TEM \\\n\tSH50.TEM \\\n\tSH51.TEM \\\n\tSH52.TEM \\\n\tSH53.TEM \\\n\tSH54.TEM \\\n\tSH55.TEM \\\n\tSH56.TEM \\\n\tT01.TEM \\\n\tT02.TEM \\\n\tT03.TEM \\\n\tT05.TEM \\\n\tT06.TEM \\\n\tT07.TEM \\\n\tT08.TEM \\\n\tT10.TEM \\\n\tT11.TEM \\\n\tT12.TEM \\\n\tT13.TEM \\\n\tT14.TEM \\\n\tT15.TEM \\\n\tT16.TEM \\\n\tT17.TEM \\\n\tTC01.TEM \\\n\tTC02.TEM \\\n\tTC03.TEM \\\n\tTC04.TEM \\\n\tTC05.TEM \\\n\tV01.TEM \\\n\tV02.TEM \\\n\tV03.TEM \\\n\tV04.TEM \\\n\tV05.TEM \\\n\tV06.TEM \\\n\tV07.TEM \\\n\tV08.TEM \\\n\tV09.TEM \\\n\tV10.TEM \\\n\tV11.TEM \\\n\tV12.TEM \\\n\tV13.TEM \\\n\tV14.TEM \\\n\tV15.TEM \\\n\tV16.TEM \\\n\tV17.TEM \\\n\tV18.TEM \\\n\tW1.TEM \\\n\tW2.TEM \\\n\tWC01.TEM \\\n\tWC02.TEM \\\n\tWC03.TEM \\\n\tWC04.TEM \\\n\tWC05.TEM \\\n\tWC06.TEM \\\n\tWC07.TEM \\\n\tWC08.TEM \\\n\tWC09.TEM \\\n\tWC10.TEM \\\n\tWC11.TEM \\\n\tWC12.TEM \\\n\tWC13.TEM \\\n\tWC14.TEM \\\n\tWC15.TEM \\\n\tWC16.TEM \\\n\tWC17.TEM \\\n\tWC18.TEM \\\n\tWC19.TEM \\\n\tWC20.TEM \\\n\tWC21.TEM \\\n\tWC22.TEM \\\n\tWC23.TEM \\\n\tWC24.TEM \\\n\tWC25.TEM \\\n\tWC26.TEM \\\n\tWC27.TEM \\\n\tWC28.TEM \\\n\tWC29.TEM \\\n\tWC30.TEM \\\n\tWC31.TEM \\\n\tWC32.TEM \\\n\tWC33.TEM \\\n\tWC34.TEM \\\n\tWC35.TEM \\\n\tWC36.TEM \\\n\tWC37.TEM \\\n\tWC38.TEM \\\n\n# Every temperate theater terrain file has a snow theater counterpart.\nSNOWFILES = $(TEMPERATEFILES:.TEM=.SNO)\n\n# Sound effects (Juvenile or Adult)\nSFX = \\\n\n# Generic wave files (never changes).\nWAVFILES = \\\n\tAACANON3.AUD \\\n\tBEEPSLCT.AUD \\\n\tBLEEP11.AUD \\\n\tBLEEP12.AUD \\\n\tBLEEP13.AUD \\\n\tBLEEP17.AUD \\\n\tBLEEP5.AUD \\\n\tBLEEP6.AUD \\\n\tBLEEP9.AUD \\\n\tBOMBIT1.AUD \\\n\tBUILD5.AUD \\\n\tBUZZY1.AUD \\       \n\tCANNON1.AUD \\\n\tCANNON2.AUD \\\n\tCASHDN1.AUD \\\n\tCASHTURN.AUD \\\n\tCASHUP1.AUD \\\n\tCHRONO2.AUD \\\n\tCHROTNK1.AUD \\\n\tCHUTE1.AUD \\\n\tCMON1.AUD \\\n\tCRMBLE2.AUD \\\n\tDEDMAN1.AUD \\\n\tDEDMAN10.AUD \\\n\tDEDMAN2.AUD \\\n\tDEDMAN3.AUD \\\n\tDEDMAN4.AUD \\\n\tDEDMAN5.AUD \\\n\tDEDMAN6.AUD \\\n\tDEDMAN7.AUD \\\n\tDEDMAN8.AUD \\\n\tDOGG5P.AUD \\\n\tDOGW3PX.AUD \\\n\tDOGW5.AUD \\\n\tDOGW6.AUD \\\n\tDOGW7.AUD \\\n\tDOGY1.AUD \\\n\tEAFFIRM1.AUD \\\n\tEENGIN1.AUD \\\n\tEINAH1.AUD \\\n\tEINOK1.AUD \\\n\tEINYES1.AUD \\\n\tEMOVOUT1.AUD \\\n\tEYESSIR1.AUD \\\n\tFIREBL3.AUD \\\n\tFIRETRT1.AUD \\\n\tFIXIT1.AUD \\\n\tGIRLOKAY.AUD \\\n\tGIRLYEAH.AUD \\\n\tGOTIT1.AUD \\\n\tGRENADE1.AUD \\\n\tGUN11.AUD \\\n\tGUN13.AUD \\\n\tGUN27.AUD \\\n\tGUN5.AUD \\\n\tGUYOKAY1.AUD \\\n\tGUYYEAH1.AUD \\\n\tH2OBOMB2.AUD \\\n\tHEAL2.AUD \\\n\tHYDROD1.AUD \\\n\tINVUL2.AUD \\\n\tIRONCUR9.AUD \\\n\tJBURN1.AUD \\\n\tJCHRGE1.AUD \\\n\tJCRISP1.AUD \\\n\tJDANCE1.AUD \\\n\tJJUICE1.AUD \\\n\tJJUMP1.AUD \\\n\tJLIGHT1.AUD \\\n\tJPOWER1.AUD \\\n\tJSHOCK1.AUD \\\n\tJYES1.AUD \\\n\tKABOOM1.AUD \\\n\tKABOOM12.AUD \\\n\tKABOOM15.AUD \\\n\tKABOOM22.AUD \\\n\tKABOOM25.AUD \\\n\tKABOOM30.AUD \\\n\tKEEPEM1.AUD \\\n\tLAUGH1.AUD \\\n\tLEFTY1.AUD \\\n\tMADCHRG2.AUD \\\n\tMADEXPLO.AUD \\\n\tMAFFIRM1.AUD \\\n\tMBOSS1.AUD \\\n\tMHEAR1.AUD \\\n\tMHOTDIG1.AUD \\\n\tMHOWDY1.AUD \\\n\tMHUH1.AUD \\\n\tMGUNINF1.AUD \\\n\tMINE1.AUD \\\n\tMINEBLO1.AUD \\\n\tMINELAY1.AUD \\\n\tMISSILE1.AUD \\\n\tMISSILE6.AUD \\\n\tMISSILE7.AUD \\\n\tMLAFF1.AUD \\\n\tMMOVOUT1.AUD \\\n\tMRESPON1.AUD \\\n\tMRISE1.AUD \\\n\tMWRENCH1.AUD \\\n\tMYEEHAW1.AUD \\\n\tMYES1.AUD \\\n\tMYESSIR1.AUD \\\n\tONIT1.AUD \\\n\tPILLBOX1.AUD \\\n\tPLACBLDG.AUD \\\n\tRABEEP1.AUD \\\n\tRADARDN1.AUD \\\n\tRADARON2.AUD \\\n\tRAMENU1.AUD \\\n\tROKROLL1.AUD \\\n\tSAFFIRM1.AUD \\\n\tSANDBAG2.AUD \\\n\tSCOLDY1.AUD \\\n\tSCOMND1.AUD \\\n\tSHKTROP1.AUD \\\n\tSILENCER.AUD \\\n\tSINDEED1.AUD \\\n\tSKING1.AUD \\\n\tSMOUT1.AUD \\\n\tSOKAY1.AUD \\\n\tSONPULSE.AUD \\\n\tSONWAY1.AUD \\\n\tSPLASH9.AUD \\\n\tSQUISHY2.AUD \\\n\tSUBSHOW1.AUD \\\n\tSWHAT1.AUD \\\n\tSYEAH1.AUD \\\n\tSYESSIR1.AUD \\\n\tTANDETH1.AUD \\\n\tTANK5.AUD \\\n\tTANK6.AUD \\\n\tTESLA1.AUD \\\n\tTORPEDO1.AUD \\\n\tTSLACHG2.AUD \\\n\tTUFFGUY1.AUD \\\n\tTURRET1.AUD \\\n\tWALLKIL2.AUD \\\n\tYEAH1.AUD \\\n\tYES1.AUD \\\n\tYO1.AUD \\\n\n# Vehicle responses\nRESPONSE1 = \\\n\tACKNO.AUD \\\n\tAFFIRM1.AUD \\\n\tAWAIT1.AUD \\\n\tREPORT1.AUD \\\n\tVEHIC1.AUD \\\n\tYESSIR1.AUD \\\n\n# Infantry responses\nRESPONSE2 = \\\n\tACKNO.AUD \\\n\tAFFIRM1.AUD \\\n\tAWAIT1.AUD \\\n\tNOPROB.AUD \\\n\tOVEROUT.AUD \\\n\tREADY.AUD \\\n\tREPORT1.AUD \\\n\tRITAWAY.AUD \\\n\tROGER.AUD \\\n\tUGOTIT.AUD \\\n\tYESSIR1.AUD \\\n\n#TSCOREFILES = \\\n#\tcps\\record.bin \\\n#\tWIN1.AUD \\\n#\tMAP1.AUD \\\n\nVARFILES = \\\n\nSCOREFILES = \\\n\tCREDITS.AUD  \\\n\tAWAIT.AUD    \\\n\tBIGF226M.AUD \\\n\tCRUS226M.AUD \\\n\tDENSE_R.AUD  \\\n\tFAC1226M.AUD \\\n\tFAC2226M.AUD \\\n\tFOGGER1A.AUD \\\n\tHELL226M.AUD \\\n\tMUD1A.AUD \\\n\tRADIO2.AUD \\\n\tROLLOUT.AUD \\\n\tRUN1226M.AUD \\\n\tSCORE.AUD \\\n\tSMSH226M.AUD \\\n\tSNAKE.AUD \\\n\tTERMINAT.AUD \\\n\tTREN226M.AUD \\\n\tTWIN.AUD \\\n\tVECTOR1A.AUD \\\n\tWORK226M.AUD \\\n\t2ND_HAND.AUD \\   \n\tARAZIOD.AUD \\   \n\tBACKSTAB.AUD \\\n\tCHAOS2.AUD \\ \n\tSHUT_IT.AUD \\   \n\tTWINMIX1.AUD \\   \n\tUNDER3.AUD \\   \n\tVR2.AUD \\\n\tBOG.AUD \\\n\tFLOAT_V2.AUD \\\n\tGLOOM.AUD \\\n\tGRNDWIRE.AUD \\\n\tRPT.AUD \\\n\tSEARCH.AUD \\\n\tTRACTION.AUD \\\n\tWASTELND.AUD \\\n\nSPEECHFILES = \\\n\tSTRCKIL1.AUD \\\n\tNOPOWR1.AUD \\\n\tSAVE1.AUD \\\n\tLOAD1.AUD \\\n\t10MINR.AUD \\\n\t1MINR.AUD \\\n\t1OBJMET1.AUD \\\n\t20MINR.AUD \\\n\t2MINR.AUD \\\n\t2OBJMET1.AUD \\\n\t30MINR.AUD \\\n\t3MINR.AUD \\\n\t3OBJMET1.AUD \\\n\t40MINR.AUD \\\n\t4MINR.AUD \\\n\t5MINR.AUD \\\n\tAAPPRO1.AUD \\\n\tAARIVE1.AUD \\\n\tAARIVE1.AUD \\\n\tAARRIVE1.AUD \\\n\tAARRIVN1.AUD \\\n\tAARRIVS1.AUD \\\n\tAARRIVW1.AUD \\\n\tAAVAIL1.AUD \\\n\tABLDGIN1.AUD \\\n\tAFALLEN1.AUD \\\n\tALAUNCH1.AUD \\\n\tAPREP1.AUD \\\n\tAREADY1.AUD \\\n\tARMORUP1.AUD \\\n\tASELECT1.AUD \\\n\tATLNCH1.AUD \\\n\tATPREP1.AUD \\\n\tAUNITL1.AUD \\\n\tBASEATK1.AUD \\\n\tBCT1.AUD \\\n\tBLDGINF1.AUD \\\n\tBLDGPRG1.AUD \\\n\tCANCLD1.AUD \\\n\tCHROCHR1.AUD \\\n\tCHRORDY1.AUD \\\n\tCHROYES1.AUD \\\n\tCMDCNTR1.AUD \\\n\tCNTLDED1.AUD \\\n\tCOMNDOF1.AUD \\\n\tCOMNDOR1.AUD \\\n\tCONSCMP1.AUD \\\n\tCONVLST1.AUD \\\n\tCONVYAP1.AUD \\\n\tCREDIT1.AUD \\\n\tENMYAPP1.AUD \\\n\tFIREPO1.AUD \\\n\tFLARE1.AUD \\\n\tFLAREE1.AUD \\\n\tFLAREN1.AUD \\\n\tFLARES1.AUD \\\n\tFLAREW1.AUD \\\n\tIRONCHG1.AUD \\\n\tIRONRDY1.AUD \\\n\tKOSYFRE1.AUD \\\n\tKOSYRES1.AUD \\\n\tLOPOWER1.AUD \\\n\tMERCF1.AUD \\\n\tMERCR1.AUD \\\n\tMISNLST1.AUD \\\n\tMISNWON1.AUD \\\n\tMTIMEIN1.AUD \\\n\tNAVYLST1.AUD \\\n\tNEWOPT1.AUD \\\n\tNOBUILD1.AUD \\\n\tNODEPLY1.AUD \\\n\tNOFUNDS1.AUD \\\n\tNOFUNDS1.AUD \\\n\tOBJMET1.AUD \\\n\tOBJNMET1.AUD \\\n\tOBJNRCH1.AUD \\\n\tOBJRCH1.AUD \\\n\tONHOLD1.AUD \\\n\tOPTERM1.AUD \\\n\tPRIBLDG1.AUD \\\n\tPROGRES1.AUD \\\n\tPULSE1.AUD \\\n\tREINFOR1.AUD \\\n\tREPAIR1.AUD \\\n\tREPAIR1.AUD \\\n\tSATLNCH1.AUD \\\n\tSILOND1.AUD \\\n\tSLCTTGT1.AUD \\\n\tSOVEFAL1.AUD \\\n\tSOVEMP1.AUD \\\n\tSOVFAPP1.AUD \\\n\tSOVFORC1.AUD \\\n\tSOVREIN1.AUD \\\n\tSPYPLN1.AUD \\\n\tSTRUCAP1.AUD \\\n\tSTRUSLD1.AUD \\\n\tTANYAF1.AUD \\\n\tTANYAR1.AUD \\\n\tTARGFRE1.AUD \\\n\tTARGRES1.AUD \\\n\tTIMERGO1.AUD \\\n\tTIMERNO1.AUD \\\n\tTRAIN1.AUD \\\n\tUNITFUL1.AUD \\\n\tUNITLST1.AUD \\\n\tUNITRDY1.AUD \\\n\tUNITREP1.AUD \\\n\tUNITSLD1.AUD \\\n\tUNITSPD1.AUD \\\n\tXPLOPLC1.AUD \\\n#\tABLDGC1.AUD \\\n#\tSOVBLDG1.AUD \\\n#\tSOVSTRC1.AUD \\\n#\tSOVUNTD1.AUD \\\n#\tAUNITD1.AUD \\\n#\tASTRUCD1.AUD \\\n\n#ALLIESVQ = \\\nDUMMYVQ = \\\n\tAAGUN.VQA \\\n\tAFTRMATH.VQA \\\n\tALLY1.VQA \\\n\tALLY10.VQA \\\n\tALLY10B.VQA \\\n\tALLY11.VQA \\\n\tALLY12.VQA \\\n\tALLY14.VQA \\\n\tALLY2.VQA \\\n\tALLY4.VQA \\\n\tALLY5.VQA \\\n\tALLY6.VQA \\\n\tALLY8.VQA \\\n\tALLY9.VQA \\\n\tALLYEND.VQA \\\n\tALLYMORF.VQA \\\n\tAPCESCPE.VQA \\\n\tASSESS.VQA \\\n\tBATTLE.VQA \\\n\t1BINOC.VQA \\\n\tBMAP.VQA \\\n\tBRDGTILT.VQA \\\n\tCRONTEST.VQA \\\n\tCRONFAIL.VQA \\\n\tDESTROYR.VQA \\\n\tDUD.VQA \\\n\tELEVATOR.VQA \\\n\tFLARE.VQA \\\n\tFROZEN.VQA \\\n\tGRVESTNE.VQA \\\n\tLANDING.VQA \\\n\tMASASSLT.VQA \\\n\tMCV.VQA \\\n\tMCV_LAND.VQA \\\n\tMONTPASS.VQA \\\n\tOILDRUM.VQA \\\n\tOVERRUN.VQA \\\n\tPROLOG.VQA \\\n\tREDINTRO.VQA \\\n\tSHIPSINK.VQA \\\n\tSHORBOM1.VQA \\\n\tSHORBOM2.VQA \\\n\tSHORBOMB.VQA \\\n\tSNOWBOMB.VQA \\\n\tSOVIET1.VQA \\\n\tSOVTSTAR.VQA \\\n\tSPY.VQA \\\n\tTANYA1.VQA \\\n\tTANYA2.VQA \\\n\tTOOFAR.VQA \\\n\tTRINITY.VQA \\\n#\tTRAILER.VQA \\\n\nSOVIETVQ = \\\n       \tAAGUN.VQA \\\n\tCRONFAIL.VQA \\\n\tAIRFIELD.VQA \\\n\tALLY1.VQA \\\n\tALLYMORF.VQA \\\n\tAVERTED.VQA \\\n\tBEACHEAD.VQA \\\n\tBMAP.VQA \\\n\tBOMBRUN.VQA \\\n\tCOUNTDWN.VQA \\\n\tDOUBLE.VQA \\\n\tDPTHCHRG.VQA \\\n\tEXECUTE.VQA \\\n\tFLARE.VQA \\\n\tLANDING.VQA \\\n\tMCVBRDGE.VQA \\\n\tMIG.VQA \\\n\tMOVINGIN.VQA \\\n\tMTNKFACT.VQA \\\n\tNUKESTOK.VQA \\\n\tONTHPRWL.VQA \\\n\tPERISCOP.VQA \\\n\tPROLOG.VQA \\\n\tRADRRAID.VQA \\\n\tREDINTRO.VQA \\\n\tSEARCH.VQA \\\n\tSFROZEN.VQA \\\n\tSITDUCK.VQA \\\n\tSLNTSRVC.VQA \\\n\tSNOWBOMB.VQA \\\n\tSNSTRAFE.VQA \\\n\tSOVBATL.VQA \\\n\tSOVCEMET.VQA \\\n\tSOVFINAL.VQA \\\n\tSOVIET1.VQA \\\n\tSOVIET10.VQA \\\n\tSOVIET11.VQA \\\n\tSOVIET12.VQA \\\n\tSOVIET13.VQA \\\n\tSOVIET14.VQA \\\n\tSOVIET2.VQA \\\n\tSOVIET3.VQA \\\n\tSOVIET4.VQA \\\n\tSOVIET5.VQA \\\n\tSOVIET6.VQA \\\n\tSOVIET7.VQA \\\n\tSOVIET8.VQA \\\n\tSOVIET9.VQA \\\n\tSOVMCV.VQA \\\n\tSOVTSTAR.VQA \\\n\tSPOTTER.VQA \\\n\tSTRAFE.VQA \\\n\tTAKE_OFF.VQA \\\n\tTESLA.VQA \\\n\tV2ROCKET.VQA \\\n#\tTRAILER.VQA \\\n\nALLIESVQ = \\\n\tSOVIET1.VQA \\\n\tALLY1.VQA \\\n\tV2ROCKET.VQA \\\t\t\n\tBMAP.VQA \\\t\n\tSNSTRAFE.VQA \\\n\tSOVTSTAR.VQA \\\n\tSOVBATL.VQA \\\n\tSOVCEMET.VQA \\\n\tFLARE.VQA \\\t\n\tALLYMORF.VQA \\\n\tSPY.VQA \\\n\tFROZEN.VQA \\\n\tGRVESTNE.VQA \\\n\tCRONFAIL.VQA \\\n\tAPCESCPE.VQA \\\n\tEXECUTE.VQA \\\n\tTOOFAR.VQA \\\n\tTRINITY.VQA \\\n\tTESLA.VQA \\\n\tMASASSLT.VQA \\\n\tOVERRUN.VQA \\\n\tPROLOG.VQA \\\n\tREDINTRO.VQA \\\n\tAFTRMATH.VQA \\\n\tPROLOG.VQA \\\n\tSNOWBOMB.VQA \\\n\tLANDING.VQA \\\n\tSFROZEN.VQA \\\n\tANTEND.VQA \\\n\tANTINTRO.VQA \\\n\t\n\n\n# Files required for hires/Win95 version only\n#\n# This mix file is not cached\n#\nNOCACHEHIRESFILES= \\\n\tENGLISH.VQA \\\n\t$(ALLIESVQ:.VQA=.VQP) \\\n\t$(SOVIETVQ:.VQA=.VQP) \\\n       \n\nLINTOBJECTS1 = $(OBJECTS:,=)\nLINTOBJECTS = $(LINTOBJECTS1:.OBJ=.LOB)\n\n# Mixfiles that should reside on the CD-ROM drive.\nCD1MIXFILES = \\\n\tCONQUER.MIX \\\n\tEDHI.MIX \\\n\tEDLO.MIX \\\n\tGENERAL.MIX \\\n\tINTERIOR.MIX \\\n\tMOVIES1.MIX \\\n\tSCORES.MIX \\\n\tSNOW.MIX \\\n\tSOUNDS.MIX \\\n \tRUSSIAN.MIX \\\n\tALLIES.MIX \\\n\tTEMPERAT.MIX \\\n\t\n\n\n# Mixfiles that should reside on the hard drive.\nLOCALMIXFILES = \\\n\tEDITOR.MIX \\\n\tHIRES.MIX \\\n\tLOCAL.MIX \\\n\tLORES.MIX \\\n\tNCHIRES.MIX \\\n\tSPEECH.MIX \\\n\t\n\n# Mixfiles as they appear on the CD and hard drive.\nPACKFILES=\t$(.path.cd1)MAIN.MIX  EXPAND2.MIX  $(.path.cd1)tobreaki\\REDALERT.MIX\n\n\n# Ant assets SOME ASSETS ARE HERE FOR OVERRIDING\nEXPANDFILES= \\\n\tANT1.SHP \\\n\tANT2.SHP \\\n\tANT3.SHP \\\n\tQUEE.SHP \\\n\tCREDITS.ENG \\\n\tHILL01.TEM \\\n\tANTBITE.AUD \\\n\tANTDIE.AUD \\\n\tANTDIE.SHP \\\n\tLAR1.SHP \\\n\tLAR2.SHP \\\n\tTITLE.PCX \\\t\t\t\t\t\t\t  \n\tMISSION.INI \\\n\tBUZZY1.AUD \\       \n\tSTAVCMDR.AUD \\     \n\tSTAVCRSE.AUD \\     \n\tSTAVYES.AUD \\      \n\tSTAVMOV.AUD \\\n\tCONQUER.ENG \\   \n\tRAMBO1.AUD \\\n\tRAMBO2.AUD \\\n\tRAMBO3.AUD \\\n\tTITLE.CPS \\\n\tANTEND.VQP \\\n\tTUTORIAL.INI \\\n\tANTINTRO.VQP \\\n\tBMAP.VQP \\\n\n# Aftermath expansion files\nEXPAND2FILES= \\\n\tCARR.SHP \\\n\tCTNK.SHP \\\n\tDTRK.SHP \\\n\tMSUB.SHP \\\n\tQTNK.SHP \\\n\tTTNK.SHP \\\n\tSTNK.SHP \\\n\tAFTRMATH.INI \\\n\tANT1.SHP \\\n\tANT2.SHP \\\n\tANT3.SHP \\\n\tANTBITE.AUD \\\n\tANTDIE.AUD \\\n\tANTDIE.SHP \\\n\tBMAP.VQP \\\n\tBUZZY1.AUD \\       \n\tCONQUER.ENG \\   \n\tCREDITS.ENG \\\n\tHILL01.TEM \\\n\tLAR1.SHP \\\n\tLAR2.SHP \\\n\tMISSION.INI \\\n\tMPLAYER.INI \\\n\tQUEE.SHP \\\n\tSTAVCMDR.AUD \\     \n\tSTAVCRSE.AUD \\     \n\tSTAVYES.AUD \\      \n\tSTAVMOV.AUD \\\n\tTITLE.PCX \\\t\t\t\t\t\t\t  \n\tTITLE.CPS \\\n\tTUTORIAL.INI \\\n\n\n\n#############################################################\n# Rebuilds all the mixfiles.\t\t\t\t  \npackfiles:\talways $(PACKFILES)\n\nalways:\n\tcopy f:\\projects\\c&c0\\editor\\english\\*.mix $(.path.mix) /u\n\n\n####################################################################\n# All mixfiles that exist on the CD-ROM are embedded within this mega-mixfile.\n$(.path.cd1)MAIN.MIX: $(CD1MIXFILES)\n\tUTILS\\MIXFILE -k -I$(.path.mix) &&!\n\t$**\n! $(.path.cd1)$&.mix\n\n\n# All mixfiles that exist in the local directory are embedded within this mega-mixfile.\n$(.path.cd1)install\\REDALERT.MIX: $(LOCALMIXFILES)\n\tUTILS\\MIXFILE -k  -I$(.path.mix) &&!\n\t$**\n! $(.path.cd1)install\\$&.mix\n\n\n####################################################################\n# These are the various sub-mixfiles.\nCONQUER.MIX: $(CONQUERFILES) $(CACHEMAP) .\\key.ini\n\tUTILS\\MIXFILE -k -h -I$(.path.cps) &&!\n\t$(CONQUERFILES) $(CACHEMAP)\n! $(.path.mix)$&.mix\n\nTEMPERAT.MIX: $(TEMPERATEFILES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -I$(.path.cps) &&!\n\t$(TEMPERATEFILES)\n! $(.path.mix)$&.mix\n\nSNOW.MIX: $(SNOWFILES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -I$(.path.cps) &&!\n\t$(SNOWFILES)\n! $(.path.mix)$&.mix\n\nINTERIOR.MIX: $(INTERIORFILES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -I$(.path.cps) &&!\n\t$(INTERIORFILES)\n! $(.path.mix)$&.mix\n\nGENERAL.MIX: $(GENERALFILES) $(GENERALMAPFILES) $(NETMAPFILES) $(MAPFILES) .\\key.ini\n\tUTILS\\MIXFILE -k -I$(.path.cps) -I$(.path.ini) &&!\n\t$(GENERALFILES) $(GENERALMAPFILES) $(NETMAPFILES) $(MAPFILES)\n! $(.path.mix)$&.mix\n\nSCORES.MIX: $(SCOREFILES)\n\tUTILS\\MIXFILE -k -I$(.path.cps) -I$(.path.ini) &&!\n\t$**\n! $(.path.mix)$&.mix\n\nSOUNDS.MIX: $(WAVFILES) $(SFX)\n\tUTILS\\MIXFILE -h -k -EA60=V00 -EA61=V01 -EA62=V02 -EA63=V03 -I$(.path.aud) &&!\n\t$**\n! $(.path.mix)$&.mix\n\nRUSSIAN.MIX: $(RESPONSE1:.AUD=.R00) $(RESPONSE2:.AUD=.R01) $(RESPONSE1:.AUD=.R02) $(RESPONSE2:.AUD=.R03)\n\tUTILS\\MIXFILE -h -k -I$(.path.aud) &&!\n\t$**\n! $(.path.mix)$&.mix\n\nLIMITED.MIX: BLEEP11.AUD\n\tUTILS\\MIXFILE -h -k -I$(.path.aud) &&!\n\t$**\n! $(.path.mix)$&.mix\n\nALLIES.MIX: $(RESPONSE1:.AUD=.V00) $(RESPONSE2:.AUD=.V01) $(RESPONSE1:.AUD=.V02) $(RESPONSE2:.AUD=.V03)\n\tUTILS\\MIXFILE -h -k -I$(.path.aud) &&!\n\t$**\n! $(.path.mix)$&.mix\n\nMOVIES1.MIX: $(ALLIESVQ)\n\tUTILS\\MIXFILE -k -I$(.path.vqa) &&!\n\t$**\n! $(.path.mix)$&.mix\n\n\n\n\n\nNCHIRES.MIX: $(NOCACHEHIRESFILES:.SHP=.HI)\n\tUTILS\\MIXFILE -k -I$(.path.vqp) -I$(.path.cps) &&!\n\t$(NOCACHEHIRESFILES)\n! $(.path.mix)$&.mix\n\nLOCAL.MIX: $(LOCALFILES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -E.A6=.AUD -I$(.path.ini) -I$(.path.txt) -I$(.path.cps) &&!\n\t$(LOCALFILES)\n! $(.path.mix)$&.mix\n\nLORES.MIX: $(LOHILORES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -E.LOW=.SHP -E.LNT=.FNT -I$(.path.cps) &&!\n\t$(LOHILORES)\n! $(.path.mix)$&.mix\n\nHIRES.MIX: $(HIRESFILES:.SHP=.HI) $(HIHILORES) .\\key.ini\n\tUTILS\\MIXFILE -h -k -E.HI=.SHP -E.HNT=.FNT -I$(.path.cps) &&!\n\t$(HIRESFILES:.SHP=.HI) $(HIHILORES)\n! $(.path.mix)$&.mix\n\nSPEECH.MIX: $(SPEECHFILES)\n\tUTILS\\MIXFILE -k -I$(.path.aud) &&!\n\t$**\n! $(.path.mix)$&.mix\n\n\nEXPAND.MIX: $(EXPANDFILES)\t\t\t   \n\tUTILS\\MIXFILE -k  -I$(.path.mix)  &&!\n\t$**\n! $(.path.mix)$&.mix\n\nEXPAND2.MIX: $(EXPAND2FILES)\t\t\t   \n\tUTILS\\MIXFILE -k  -I$(.path.mix)  &&!\n\t$**\n! $(.path.mix)$&.mix\n\n#############################################################\n# Special rule to create the mouse shape (which must be a shape file)\nmouse.hi:\t$(.path.anm)hires\\mouse.anm\n\t-utils\\makeshps $(.path.lbm)palettes\\temperat.lbm &&!\n &$(.path.anm)hires\\mouse.anm;\n end;\n! $(.path.hi)$&.hi $(SHAPEBUFFSIZE)\n\n# Special rule to create the mouse shape (which must be a shape file)\nmouse.low:\t$(.path.anm)lores\\mouse.anm\n\t-utils\\makeshps $(.path.lbm)palettes\\temperat.lbm &&!\n &$(.path.anm)lores\\mouse.anm;\n end;\n! $(.path.low)$&.low $(SHAPEBUFFSIZE)\n\n\n#############################################################\n# Special build rule for radar animations so that they won't.\n#\nNATORADR.HI: $(.path.anm)hires\\NATORADR.ANM\n\tutils\\newkeyf $** $(.path.hi)$&.hi -l -k\n\nUSSRRADR.HI: $(.path.anm)hires\\USSRRADR.ANM\n\tutils\\newkeyf $** $(.path.hi)$&.hi -l -k\n\nNATORADR.LOW: $(.path.anm)lores\\NATORADR.ANM\n\tutils\\newkeyf $** $(.path.low)$&.low -l -k\n\nUSSRRADR.LOW: $(.path.anm)lores\\USSRRADR.ANM\n\tutils\\newkeyf $** $(.path.low)$&.low -l -k\n\n\n#############################################################\n# Debug text file creation.\ndebug.eng:\tdebug.txt\n\tutils\\textmake -b1000 eng\\$&.txt $(.path.eng)$&.eng $&.h\n\n\n"
  },
  {
    "path": "CODE/BFIOFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BFIOFILE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Library                                             *\n *                                                                                             *\n *                    File Name : RAMFILE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : David R. Dettmer                                             *\n *                                                                                             *\n *                   Start Date : November 10, 1995                                            *\n *                                                                                             *\n *                  Last Update : November 10, 1995  [DRD]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BufferIOFileClass::BufferIOFileClass -- Filename based constructor for a file object.     *\n *   BufferIOFileClass::BufferIOFileClass -- default constructor for a file object.            *\n *   BufferIOFileClass::Cache -- Load part or all of a file data into RAM.                     *\n *   BufferIOFileClass::Close -- Perform a closure of the file.                                *\n *   BufferIOFileClass::Commit -- Writes the cache to the file if it has changed.              *\n *   BufferIOFileClass::Free -- Frees the allocated buffer.                                    *\n *   BufferIOFileClass::Is_Available -- Checks for existence of file cached or on disk.        *\n *   BufferIOFileClass::Is_Open -- Determines if the file is open.                             *\n *   BufferIOFileClass::Open -- Assigns name and opens file in one operation.                  *\n *   BufferIOFileClass::Open -- Opens the file object with the rights specified.               *\n *   BufferIOFileClass::Read -- Reads data from the file cache.                                *\n *   BufferIOFileClass::Seek -- Moves the current file pointer in the file.                    *\n *   BufferIOFileClass::Set_Name -- Checks for name changed for a cached file.                 *\n *   BufferIOFileClass::Size -- Determines size of file (in bytes).                            *\n *   BufferIOFileClass::Write -- Writes data to the file cache.                                *\n *   BufferIOFileClass::~BufferIOFileClass -- Destructor for the file object.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"bfiofile.h\"\n#include\t<string.h>\n\n\n/***********************************************************************************************\n * BufferIOFileClass::BufferIOFileClass -- Filename based constructor for a file object.       *\n *                                                                                             *\n *    This constructor is called when a file object is created with a supplied filename, but   *\n *    not opened at the same time. In this case, an assumption is made that the supplied       *\n *    filename is a constant string. A duplicate of the filename string is not created since   *\n *    it would be wasteful in that case.                                                       *\n *                                                                                             *\n * INPUT:   filename -- The filename to assign to this file object.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/10/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nBufferIOFileClass::BufferIOFileClass(char const * filename) :\n\tIsAllocated(false),\n\tIsOpen(false),\n\tIsDiskOpen(false),\n\tIsCached(false),\n\tIsChanged(false),\n\tUseBuffer(false),\n\tBufferRights(0),\n\tBuffer(0),\n\tBufferSize(0),\n\tBufferPos(0),\n\tBufferFilePos(0),\n\tBufferChangeBeg(-1),\n\tBufferChangeEnd(-1),\n\tFileSize(0),\n\tFilePos(0),\n\tTrueFileStart(0)\n{\n\tBufferIOFileClass::Set_Name(filename);\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::BufferIOFileClass -- default constructor for a file object.              *\n *                                                                                             *\n *    This is the default constructor for a file object.                                       *\n *                                                                                             *\n * INPUT:  none                                                                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/10/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nBufferIOFileClass::BufferIOFileClass(void) :\n\tIsAllocated(false),\n\tIsOpen(false),\n\tIsDiskOpen(false),\n\tIsCached(false),\n\tIsChanged(false),\n\tUseBuffer(false),\n\tBufferRights(0),\n\tBuffer(0),\n\tBufferSize(0),\n\tBufferPos(0),\n\tBufferFilePos(0),\n\tBufferChangeBeg(-1),\n\tBufferChangeEnd(-1),\n\tFileSize(0),\n\tFilePos(0),\n\tTrueFileStart(0)\n{\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::~BufferIOFileClass -- Destructor for the file object.                    *\n *                                                                                             *\n *    This destructor will free all memory allocated thru using Cache routines.                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/10/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nBufferIOFileClass::~BufferIOFileClass(void)\n{\n\tFree();\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Cache -- Load part or all of a file data into RAM.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the file load successful?  It could fail if there wasn't enough room     *\n *                to allocate the raw data block.                                              *\n *                                                                                             *\n * WARNINGS:   This routine goes to disk for a potentially very long time.                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/10/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nbool BufferIOFileClass::Cache( long size, void * ptr )\n{\n\tif (Buffer) {\n\t\t//\n\t\t// if trying to cache again with size or ptr fail\n\t\t//\n\t\tif (size || ptr) {\n\t\t\treturn( false );\n\t\t} else {\n\t\t\treturn( true );\n\t\t}\n\t}\n\n\tif ( Is_Available() ) {\n\t\tFileSize = Size();\n\t} else {\n\t\tFileSize = 0;\n\t}\n\n\tif (size) {\n\t\t//\n\t\t// minimum buffer size for performance\n\t\t//\n\t\tif (size < MINIMUM_BUFFER_SIZE) {\n\t\t\tsize = MINIMUM_BUFFER_SIZE;\n\n\t\t\t/*\n\t\t\t**\tSpecifying a size smaller than the minimum is an error\n\t\t\t**\tIF a buffer pointer was also specified. In such a case the\n\t\t\t**\tsystem cannot use the buffer.\n\t\t\t*/\n\t\t\tif (ptr) {\n\t\t\t\tError(EINVAL);\n\t\t\t}\n\t\t}\n\n\t\tBufferSize = size;\n\t} else {\n\t\tBufferSize = FileSize;\n\t}\n\n\t//\n\t// if size == 0 and a ptr to a buffer is specified then that is invalid.\n\t// if the BufferSize is 0 then this must be a new file and no size was\n\t// specified so exit.\n\t//\n\tif ( (size == 0 && ptr) || !BufferSize) {\n\t\treturn( false );\n\t}\n\n\tif (ptr) {\n\t\tBuffer = ptr;\n\t} else {\n\t\tBuffer = new char [BufferSize];\n\t}\n\n\tif (Buffer) {\n\t\tIsAllocated\t\t\t= true;\n\t\tIsDiskOpen\t\t\t= false;\n\t\tBufferPos\t\t\t= 0;\n\t\tBufferFilePos\t\t= 0;\n\t\tBufferChangeBeg\t= -1;\n\t\tBufferChangeEnd\t= -1;\n\t\tFilePos\t\t\t\t= 0;\n\t\tTrueFileStart\t\t= 0;\n\n\t\t//\n\t\t// the file was checked for availability then set the FileSize\n\t\t//\n\t\tif (FileSize) {\n\t\t\tlong readsize;\n\t\t\tint opened = false;\n\t\t\tlong prevpos = 0;\n\n\n\t\t\tif (FileSize <= BufferSize) {\n\t\t\t\treadsize = FileSize;\n\t\t\t} else {\n\t\t\t\treadsize = BufferSize;\n\t\t\t}\n\n\t\t\tif ( Is_Open() ) {\n\t\t\t\t//\n\t\t\t\t// get previous file position\n\t\t\t\t//\n\t\t\t\tprevpos = Seek(0);\n\n\t\t\t\t//\n\t\t\t\t// get true file position\n\t\t\t\t//\n\t\t\t\tif ( RawFileClass::Is_Open() ) {\n\t\t\t\t\tTrueFileStart = RawFileClass::Seek(0);\n\t\t\t\t} else {\n\t\t\t\t\tTrueFileStart = prevpos;\n\t\t\t\t}\n\n\t\t\t\tif (FileSize <= BufferSize) {\n\t\t\t\t\t//\n\t\t\t\t\t// if previous position is non-zero seek to the beginning\n\t\t\t\t\t//\n\t\t\t\t\tif (prevpos) {\n\t\t\t\t\t\tSeek(0, SEEK_SET);\n\t\t\t\t\t}\n\n\t\t\t\t\t//\n\t\t\t\t\t// set the buffer position for future reads/writes\n\t\t\t\t\t//\n\t\t\t\t\tBufferPos = prevpos;\n\t\t\t\t} else {\n\t\t\t\t\tBufferFilePos = prevpos;\n\t\t\t\t}\n\n\t\t\t\tFilePos = prevpos;\n\t\t\t} else {\n\t\t\t\tif ( Open() ) {\n\t\t\t\t\tTrueFileStart = RawFileClass::Seek(0);\n\t\t\t\t\topened = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlong actual = Read(Buffer, readsize);\n\n\t\t\tif (actual != readsize) {\n\t\t\t\tError(EIO);\n\t\t\t}\n\n\t\t\tif (opened) {\n\t\t\t\tClose();\n\t\t\t} else {\n\t\t\t\t//\n\t\t\t\t// seek to the previous position in the file\n\t\t\t\t//\n\t\t\t\tSeek(prevpos, SEEK_SET);\n\t\t\t}\n\n\t\t\tIsCached = true;\n\t\t}\n\n\t\tUseBuffer = true;\n\t\treturn(true);\n\t}\n\n\tError(ENOMEM);\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Free -- Frees the allocated buffer.                                      *\n *                                                                                             *\n *    This routine will free the buffer. By using this in conjunction with the                 *\n *    Cache() function, one can maintain tight control of memory usage.                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/10/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nvoid BufferIOFileClass::Free(void)\n{\n\tif (Buffer) {\n\t\tif (IsAllocated) {\n\t\t\tdelete [] Buffer;\n\t\t\tIsAllocated = false;\n\t\t}\n\n\t\tBuffer = 0;\n\t}\n\n\tBufferSize\t\t= 0;\n\tIsOpen\t\t\t= false;\n\tIsCached\t\t\t= false;\n\tIsChanged\t\t= false;\n\tUseBuffer\t\t= false;\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Commit -- Writes the cache to the file if it has changed.                *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  false, did not need to write the buffer.                                           *\n *          true, wrote the buffer.                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/15/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nbool BufferIOFileClass::Commit( void )\n{\n\tlong size;\n\n\n\tif (UseBuffer) {\n\t\tif (IsChanged) {\n\t\t\tsize = BufferChangeEnd - BufferChangeBeg;\n\n\t\t\tif (IsDiskOpen) {\n\t\t\t\tRawFileClass::Seek( TrueFileStart + BufferFilePos +\n\t\t\t\t\t\t\t\t\t\t  BufferChangeBeg, SEEK_SET );\n\t\t\t\tRawFileClass::Write( Buffer, size );\n\t\t\t\tRawFileClass::Seek( TrueFileStart + FilePos, SEEK_SET );\n\t\t\t} else {\n\t\t\t\tRawFileClass::Open();\n\t\t\t\tRawFileClass::Seek( TrueFileStart + BufferFilePos +\n\t\t\t\t\t\t\t\t\t\t  BufferChangeBeg, SEEK_SET );\n\t\t\t\tRawFileClass::Write( Buffer, size );\n\t\t\t\tRawFileClass::Close();\n\t\t\t}\n\n\t\t\tIsChanged = false;\n\t\t\treturn( true );\n\t\t} else {\n\t\t\treturn( false );\n\t\t}\n\t} else {\n\t\treturn( false );\n\t}\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Set_Name -- Checks for name changed for a cached file.                   *\n *                                                                                             *\n *    Checks for a previous filename and that it is cached.  If so, then check the             *\n *    new filename against the old. If they are the same then return that filename.            *\n *    Otherwise, the file object's name is set with just the raw filename as passed            *\n *    to this routine.                                                                         *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the filename to set as the name of this file object.        *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to the final and complete filename of this file object. This     *\n *          may have a path attached to the file.                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/15/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nchar const * BufferIOFileClass::Set_Name(char const * filename)\n{\n\tif ( File_Name() && UseBuffer) {\n\t\tif ( strcmp(filename, File_Name() ) == 0) {\n\t\t\treturn( File_Name() );\n\t\t} else {\n\t\t\tCommit();\n\t\t\tIsCached = false;\n\t\t}\n\t}\n\n\tRawFileClass::Set_Name(filename);\n\treturn( File_Name() );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Is_Available -- Checks for existence of file cached or on disk.          *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file available for opening?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/16/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nint BufferIOFileClass::Is_Available(int )\n{\n\tif (UseBuffer) {\n\t\treturn(true);\n\t}\n\n\treturn( RawFileClass::Is_Available() );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Is_Open -- Determines if the file is open.                               *\n *                                                                                             *\n *    If part or all of the file is cached, then return that it is opened. A closed file       *\n *    doesn't have a valid pointer.                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file open?                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nint BufferIOFileClass::Is_Open(void) const\n{\n\tif (IsOpen && UseBuffer) {\n\t\treturn( true );\n\t}\n\n\treturn( RawFileClass::Is_Open() );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Open -- Assigns name and opens file in one operation.                    *\n *                                                                                             *\n *    This routine will assign the specified filename to the file object and open it at the    *\n *    same time. If the file object was already open, then it will be closed first. If the     *\n *    file object was previously assigned a filename, then it will be replaced with the new    *\n *    name. Typically, this routine is used when an anonymous file object has been crated and  *\n *    now it needs to be assigned a name and opened.                                           *\n *                                                                                             *\n * INPUT:   filename -- The filename to assign to this file object.                            *\n *                                                                                             *\n *          rights   -- The open file access rights to use.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened? The return value of this is moot, since the open file   *\n *          is designed to never return unless it succeeded.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nint BufferIOFileClass::Open(char const * filename, int rights)\n{\n\tSet_Name(filename);\n\treturn( BufferIOFileClass::Open( rights ) );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Open -- Opens the file object with the rights specified.                 *\n *                                                                                             *\n *    This routine is used to open the specified file object with the access rights indicated. *\n *    This only works if the file has already been assigned a filename. It is guaranteed, by   *\n *    the error handler, that this routine will always return with success.                    *\n *                                                                                             *\n * INPUT:   rights   -- The file access rights to use when opening this file. This is a        *\n *                      combination of READ and/or WRITE bit flags.                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened successfully? This will always return true by reason of  *\n *          the error handler.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nint BufferIOFileClass::Open(int rights)\n{\n\tBufferIOFileClass::Close();\n\n\tif (UseBuffer) {\n\n\t\tBufferRights = rights;\t\t// save rights requested for checks later\n\n\t\tif (rights != READ ||\n\t\t\t (rights == READ && FileSize > BufferSize) ) {\n\n\t\t\tif (rights == WRITE) {\n\t\t\t\tRawFileClass::Open( rights );\n\t\t\t\tRawFileClass::Close();\n\t\t\t\trights = READ | WRITE;\n\t\t\t\tTrueFileStart = 0;\t\t// now writing to single file\n\t\t\t}\n\n\t\t\tif (TrueFileStart) {\n\t\t\t\tUseBuffer = false;\n\t\t\t\tOpen( rights );\n\t\t\t\tUseBuffer = true;\n\t\t\t} else {\n\t\t\t\tRawFileClass::Open( rights );\n\t\t\t}\n\n\t\t\tIsDiskOpen = true;\n\n\t\t\tif (BufferRights == WRITE) {\n\t\t\t\tFileSize = 0;\n\t\t\t}\n\n\t\t} else {\n\t\t\tIsDiskOpen = false;\n\t\t}\n\n\t\tBufferPos\t\t\t= 0;\n\t\tBufferFilePos\t\t= 0;\n\t\tBufferChangeBeg\t= -1;\n\t\tBufferChangeEnd\t= -1;\n\t\tFilePos\t\t\t\t= 0;\n\t\tIsOpen\t\t\t\t= true;\n\t} else {\n\t\tRawFileClass::Open( rights );\n\t}\n\n\treturn( true );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Write -- Writes data to the file cache.                                  *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that holds the data to be written.               *\n *                                                                                             *\n *          size     -- The number of bytes to write.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually written.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/15/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nlong BufferIOFileClass::Write(void const * buffer, long size)\n{\n\tint opened = false;\n\n\tif ( !Is_Open() ) {\n\t\tif (!Open(WRITE)) {\n\t\t\treturn(0);\n\t\t}\n\t\tTrueFileStart = RawFileClass::Seek(0);\n\t\topened = true;\n\t}\n\n\tif (UseBuffer) {\n\t\tlong sizewritten = 0;\n\n\t\tif (BufferRights != READ) {\n\t\t\twhile (size) {\n\t\t\t\tlong sizetowrite;\n\n\t\t\t\tif (size >= (BufferSize - BufferPos) ) {\n\t\t\t\t\tsizetowrite = (BufferSize - BufferPos);\n\t\t\t\t} else {\n\t\t\t\t\tsizetowrite = size;\n\t\t\t\t}\n\n\t\t\t\tif (sizetowrite != BufferSize) {\n\n\t\t\t\t\tif ( !IsCached ) {\n\t\t\t\t\t\tlong readsize;\n\n\t\t\t\t\t\tif (FileSize < BufferSize) {\n\t\t\t\t\t\t\treadsize = FileSize;\n\t\t\t\t\t\t\tBufferFilePos = 0;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treadsize = BufferSize;\n\t\t\t\t\t\t\tBufferFilePos = FilePos;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (TrueFileStart) {\n\t\t\t\t\t\t\tUseBuffer = false;\n\t\t\t\t\t\t\tSeek( FilePos, SEEK_SET );\n\t\t\t\t\t\t\tRead( Buffer, BufferSize );\n\t\t\t\t\t\t\tSeek( FilePos, SEEK_SET );\n\t\t\t\t\t\t\tUseBuffer = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tRawFileClass::Seek( BufferFilePos, SEEK_SET );\n\t\t\t\t\t\t\tRawFileClass::Read( Buffer, readsize );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tBufferPos\t\t\t= 0;\n\t\t\t\t\t\tBufferChangeBeg\t= -1;\n\t\t\t\t\t\tBufferChangeEnd\t= -1;\n\n\t\t\t\t\t\tIsCached = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tmemmove((char *)Buffer + BufferPos, (char *)buffer + sizewritten, sizetowrite);\n\n\t\t\t\tIsChanged = true;\n\t\t\t\tsizewritten += sizetowrite;\n\t\t\t\tsize -= sizetowrite;\n\n\t\t\t\tif (BufferChangeBeg == -1) {\n\t\t\t\t\tBufferChangeBeg = BufferPos;\n\t\t\t\t\tBufferChangeEnd = BufferPos;\n\t\t\t\t} else {\n\t\t\t\t\tif (BufferChangeBeg > BufferPos) {\n\t\t\t\t\t\tBufferChangeBeg = BufferPos;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tBufferPos += sizetowrite;\n\n\t\t\t\tif (BufferChangeEnd < BufferPos) {\n\t\t\t\t\tBufferChangeEnd = BufferPos;\n\t\t\t\t}\n\n\t\t\t\tFilePos = BufferFilePos + BufferPos;\n\n\t\t\t\tif (FileSize < FilePos) {\n\t\t\t\t\tFileSize = FilePos;\n\t\t\t\t}\n\n\t\t\t\t//\n\t\t\t\t// end of buffer reached?\n\t\t\t\t//\n\t\t\t\tif (BufferPos == BufferSize) {\n\t\t\t\t\tCommit();\n\n\t\t\t\t\tBufferPos = 0;\n\t\t\t\t\tBufferFilePos = FilePos;\n\t\t\t\t\tBufferChangeBeg = -1;\n\t\t\t\t\tBufferChangeEnd = -1;\n\n\t\t\t\t\tif (size && FileSize > FilePos) {\n\t\t\t\t\t\tif (TrueFileStart) {\n\t\t\t\t\t\t\tUseBuffer = false;\n\t\t\t\t\t\t\tSeek( FilePos, SEEK_SET );\n\t\t\t\t\t\t\tRead( Buffer, BufferSize );\n\t\t\t\t\t\t\tSeek( FilePos, SEEK_SET );\n\t\t\t\t\t\t\tUseBuffer = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tRawFileClass::Seek( FilePos, SEEK_SET );\n\t\t\t\t\t\t\tRawFileClass::Read( Buffer, BufferSize );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tIsCached = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tError(EACCES);\n\t\t}\n\n\t\tsize = sizewritten;\n\t} else {\n\t\tsize = RawFileClass::Write(buffer, size);\n\t}\n\n\tif (opened) {\n\t\tClose();\n\t}\n\n\treturn( size );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Read -- Reads data from the file cache.                                  *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer to place the read data.                          *\n *                                                                                             *\n *          size     -- The number of bytes to read.                                           *\n *                                                                                             *\n * OUTPUT:  Returns the actual number of bytes read (this could be less than requested).       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/15/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nlong BufferIOFileClass::Read(void * buffer, long size)\n{\n\tint opened = false;\n\n\tif ( !Is_Open() ) {\n\t\tif ( Open() ) {\n\t\t\tTrueFileStart = RawFileClass::Seek(0);\n\t\t\topened = true;\n\t\t}\n\t}\n\n\tif (UseBuffer) {\n\t\tlong sizeread = 0;\n\n\t\tif (BufferRights != WRITE) {\n\t\t\twhile (size) {\n\t\t\t\tlong sizetoread;\n\n\t\t\t\tif (size >= (BufferSize - BufferPos) ) {\n\t\t\t\t\tsizetoread = (BufferSize - BufferPos);\n\t\t\t\t} else {\n\t\t\t\t\tsizetoread = size;\n\t\t\t\t}\n\n\t\t\t\tif ( !IsCached ) {\n\t\t\t\t\tlong readsize;\n\n\t\t\t\t\tif (FileSize < BufferSize) {\n\t\t\t\t\t\treadsize = FileSize;\n\t\t\t\t\t\tBufferFilePos = 0;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treadsize = BufferSize;\n\t\t\t\t\t\tBufferFilePos = FilePos;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (TrueFileStart) {\n\t\t\t\t\t\tUseBuffer = false;\n\t\t\t\t\t\tSeek( FilePos, SEEK_SET );\n\t\t\t\t\t\tRead( Buffer, BufferSize );\n\t\t\t\t\t\tSeek( FilePos, SEEK_SET );\n\t\t\t\t\t\tUseBuffer = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tRawFileClass::Seek( BufferFilePos, SEEK_SET );\n\t\t\t\t\t\tRawFileClass::Read( Buffer, readsize );\n\t\t\t\t\t}\n\n\t\t\t\t\tBufferPos\t\t\t= 0;\n\t\t\t\t\tBufferChangeBeg\t= -1;\n\t\t\t\t\tBufferChangeEnd\t= -1;\n\n\t\t\t\t\tIsCached = true;\n\t\t\t\t}\n\n\t\t\t\tmemmove((char *)buffer + sizeread, (char *)Buffer + BufferPos, sizetoread);\n\n\t\t\t\tsizeread += sizetoread;\n\t\t\t\tsize -= sizetoread;\n\t\t\t\tBufferPos += sizetoread;\n\t\t\t\tFilePos = BufferFilePos + BufferPos;\n\n\t\t\t\t//\n\t\t\t\t// end of buffer reached?\n\t\t\t\t//\n\t\t\t\tif (BufferPos == BufferSize) {\n\t\t\t\t\tCommit();\n\n\t\t\t\t\tBufferPos = 0;\n\t\t\t\t\tBufferFilePos = FilePos;\n\t\t\t\t\tBufferChangeBeg = -1;\n\t\t\t\t\tBufferChangeEnd = -1;\n\n\t\t\t\t\tif (size && FileSize > FilePos) {\n\t\t\t\t\t\tif (TrueFileStart) {\n\t\t\t\t\t\t\tUseBuffer = false;\n\t\t\t\t\t\t\tSeek( FilePos, SEEK_SET );\n\t\t\t\t\t\t\tRead( Buffer, BufferSize );\n\t\t\t\t\t\t\tSeek( FilePos, SEEK_SET );\n\t\t\t\t\t\t\tUseBuffer = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tRawFileClass::Seek( FilePos, SEEK_SET );\n\t\t\t\t\t\t\tRawFileClass::Read( Buffer, BufferSize );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tIsCached = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tError(EACCES);\n\t\t}\n\n\t\tsize = sizeread;\n\t} else {\n\t\tsize = RawFileClass::Read(buffer, size);\n\t}\n\n\tif (opened) {\n\t\tClose();\n\t}\n\n\treturn( size );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Seek -- Moves the current file pointer in the file.                      *\n *                                                                                             *\n *    This routine will change the current file pointer to the position specified. It follows  *\n *    the same rules the a normal Seek() does, but if the file is part of the mixfile system,  *\n *    then only the position value needs to be updated.                                        *\n *                                                                                             *\n * INPUT:   pos      -- The position to move the file to relative to the position indicated    *\n *                      by the \"dir\" parameter.                                                *\n *                                                                                             *\n *          dir      -- The direction to affect the position change against. This can be       *\n *                      either SEEK_CUR, SEEK_END, or SEEK_SET.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the position of the new location.                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/15/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nlong BufferIOFileClass::Seek(long pos, int dir)\n{\n\tif (UseBuffer) {\n\t\tbool adjusted = false;\n\n\t\tswitch (dir) {\n\t\t\tcase SEEK_END:\n\t\t\t\tFilePos = FileSize;\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_SET:\n\t\t\t\tFilePos = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_CUR:\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (TrueFileStart) {\n\t\t\tif (pos >= TrueFileStart) {\n\t\t\t\tpos -= TrueFileStart;\n\t\t\t\tadjusted = true;\n\t\t\t}\n\t\t}\n\n\t\tFilePos += pos;\n\n\t\tif (FilePos < 0) {\n\t\t\tFilePos = 0;\n\t\t}\n\n\t\tif (FilePos > FileSize ) {\n\t\t\tFilePos = FileSize;\n\t\t}\n\n\t\tif (FileSize <= BufferSize) {\n\t\t\tBufferPos = FilePos;\n\t\t} else {\n\t\t\tif (FilePos >= BufferFilePos &&\n\t\t\t\t FilePos < (BufferFilePos + BufferSize) ) {\n\t\t\t\tBufferPos = FilePos - BufferFilePos;\n\t\t\t} else {\n\t\t\t\tCommit();\n// check!!\n\t\t\t\tif (TrueFileStart) {\n\t\t\t\t\tUseBuffer = false;\n\t\t\t\t\tSeek(FilePos, SEEK_SET);\n\t\t\t\t\tUseBuffer = true;\n\t\t\t\t} else {\n\t\t\t\t\tRawFileClass::Seek(FilePos, SEEK_SET);\n\t\t\t\t}\n\n\t\t\t\tIsCached = false;\n\t\t\t}\n\t\t}\n\n\t\tif (TrueFileStart && adjusted) {\n\t\t\treturn( FilePos + TrueFileStart );\n\t\t}\n\n\t\treturn( FilePos );\n\t}\n\n\treturn( RawFileClass::Seek(pos, dir) );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Size -- Determines size of file (in bytes).                              *\n *                                                                                             *\n *    If part or all of the file is cached, then the size of the file is already               *\n *    determined and available. Otherwise, go to the low level system to find the file         *\n *    size.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes in the file.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nlong BufferIOFileClass::Size(void)\n{\n\tif (IsOpen && UseBuffer) {\n\t\treturn( FileSize );\n\t}\n\n\treturn( RawFileClass::Size() );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Close -- Perform a closure of the file.                                  *\n *                                                                                             *\n *    Call Commit() to write the buffer if the file is cached and the buffer has changed,      *\n *    then call lower level Close().                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nvoid BufferIOFileClass::Close(void)\n{\n\tif (UseBuffer) {\n\t\tCommit();\n\n\t\tif (IsDiskOpen) {\n\n\t\t\tif (TrueFileStart) {\n\t\t\t\tUseBuffer = false;\n\t\t\t\tClose();\n\t\t\t\tUseBuffer = true;\n\t\t\t} else {\n\t\t\t\tRawFileClass::Close();\n\t\t\t}\n\n\t\t\tIsDiskOpen = false;\n\t\t}\n\n\t\tIsOpen = false;\n\t} else {\n\t\tRawFileClass::Close();\n\t}\n}\n\n"
  },
  {
    "path": "CODE/BFIOFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BFIOFILE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Library                                             *\n *                                                                                             *\n *                    File Name : BFIOFILE.H                                                   *\n *                                                                                             *\n *                   Programmer : David R. Dettmer                                             *\n *                                                                                             *\n *                   Start Date : November 10, 1995                                            *\n *                                                                                             *\n *                  Last Update : November 10, 1995  [DRD]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BFIOFILE_H\n#define BFIOFILE_H\n\n#include\t\"rawfile.h\"\n\n/*\n**\tThis derivation of the raw file class handles buffering the input/output in order to\n**\tachieve greater speed. The buffering is not active by default. It must be activated\n**\tby setting the appropriate buffer through the Cache() function.\n*/\nclass BufferIOFileClass : public RawFileClass\n{\n\tpublic:\n\n\t\tBufferIOFileClass(char const *filename);\n\t\tBufferIOFileClass(void);\n\t\tvirtual ~BufferIOFileClass(void);\n\n\t\tbool Cache( long size=0, void *ptr=NULL );\n\t\tvoid Free( void );\n\t\tbool Commit( void );\n\t\tvirtual char const * Set_Name(char const *filename);\n\t\tvirtual int Is_Available(int forced=false);\n\t\tvirtual int Is_Open(void) const;\n\t\tvirtual int Open(char const *filename, int rights=READ);\n\t\tvirtual int Open(int rights=READ);\n\t\tvirtual long Read(void *buffer, long size);\n\t\tvirtual long Seek(long pos, int dir=SEEK_CUR);\n\t\tvirtual long Size(void);\n\t\tvirtual long Write(void const *buffer, long size);\n\t\tvirtual void Close(void);\n\n\t\tenum {MINIMUM_BUFFER_SIZE=1024};\n\n\tprivate:\n\n\t\tunsigned IsAllocated:1;\n\t\tunsigned IsOpen:1;\n\t\tunsigned IsDiskOpen:1;\n\t\tunsigned IsCached:1;\n\t\tunsigned IsChanged:1;\n\t\tunsigned UseBuffer:1;\n\n\t\tint BufferRights;\n\n\t\tvoid *Buffer;\n\n\t\tlong BufferSize;\n\t\tlong BufferPos;\n\t\tlong BufferFilePos;\n\t\tlong BufferChangeBeg;\n\t\tlong BufferChangeEnd;\n\t\tlong FileSize;\n\t\tlong FilePos;\n\t\tlong TrueFileStart;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/BIGCHECK.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n//\tBigCheck.cpp\n//\tajw 9/14/98\n\n#ifdef WOLAPI_INTEGRATION\n\n#include\t\"function.h\"\n#include\t\"bigcheck.h\"\n\n//***********************************************************************************************\nint BigCheckBoxClass::Draw_Me( int forced )\n{\n\tif (ToggleClass::Draw_Me(forced))\n\t{\n\t\tHide_Mouse();\n\n\t\tif( !IsOn )\n\t\t{\n\t\t\tif( !IsDisabled )\n\t\t\t\tCC_Draw_Shape( MFCD::Retrieve( \"bigcheck.shp\" ), 0, X, Y, WINDOW_MAIN, SHAPE_NORMAL );\n\t\t\telse\n\t\t\t\tCC_Draw_Shape( MFCD::Retrieve( \"bigcheck.shp\" ), 2, X, Y, WINDOW_MAIN, SHAPE_NORMAL );\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif( !IsDisabled )\n\t\t\t\tCC_Draw_Shape( MFCD::Retrieve( \"bigcheck.shp\" ), 1, X, Y, WINDOW_MAIN, SHAPE_NORMAL );\n\t\t\telse\n\t\t\t\tCC_Draw_Shape( MFCD::Retrieve( \"bigcheck.shp\" ), 3, X, Y, WINDOW_MAIN, SHAPE_NORMAL );\n\t\t}\n\n\t\tTextPrintType flags = TextFlags;\n\t\t\n\t\tRemapControlType* pScheme;\n\t\t\n//\t\tif( !IsDisabled )\n\t\t\tpScheme = GadgetClass::Get_Color_Scheme();\n//\t\telse\n//\t\t{\n//\t\t\tpScheme = &GreyScheme;\n//\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n//\t\t}\n\n\t\tConquer_Clip_Text_Print( szCaption, X + BIGCHECK_OFFSETX, Y + BIGCHECK_OFFSETY, pScheme, TBLACK, flags, Width, 0 );\n\n\t\tShow_Mouse();\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n//***********************************************************************************************\nint BigCheckBoxClass::Action(unsigned flags, KeyNumType & key)\n{\n/*\tif( flags & LEFTPRESS )\n\t{\n\t\tif (IsOn) {\n\t\t\tTurn_Off();\n\t\t} else {\n\t\t\tTurn_On();\n\t\t}\n\t}\n*/\n\treturn(ToggleClass::Action(flags, key));\n}\n\n#endif\n"
  },
  {
    "path": "CODE/BIGCHECK.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n//\tBigcheck.h\n//\tajw 9/14/98\n\n#ifdef WOLAPI_INTEGRATION\n\n#ifndef BIGCHECKBOX_H\n#define BIGCHECKBOX_H\n\n#include\t\"toggle.h\"\n\n#define BIGCHECK_OFFSETX\t20\n#define BIGCHECK_OFFSETY\t0\n\n//***********************************************************************************************\nclass BigCheckBoxClass : public ToggleClass\n{\npublic:\n\tBigCheckBoxClass( unsigned id, int x, int y, int w, int h, const char* szCaptionIn, TextPrintType TextFlags, \n\t\t\t\t\t\t\tbool bInitiallyChecked = false ) :\n\t\tToggleClass( id, x, y, w, h ),\n\t\tTextFlags( TextFlags )\n\t{\n\t\tszCaption = new char[ strlen( szCaptionIn ) + 1 ];\n\t\tstrcpy( szCaption, szCaptionIn );\n\t\tif( bInitiallyChecked )\n\t\t\tTurn_On();\n\t\tIsToggleType = 1;\n\t}\n\tvirtual ~BigCheckBoxClass()\n\t{\n\t\tdelete [] szCaption;\n\t}\n\n\tvirtual int Draw_Me(int forced=false);\n\tvirtual int Action(unsigned flags, KeyNumType & key);\n\n\tbool\tToggle()\n\t{\n\t\tif( IsOn )\n\t\t{\n\t\t\tTurn_Off();\n\t\t\treturn false;\n\t\t}\n\t\tTurn_On();\n\t\treturn true;\n\t}\n\nprotected:\n\tTextPrintType\tTextFlags;\n\tchar*\t\t\tszCaption;\n\n};\n\n#endif\n\n#endif\n"
  },
  {
    "path": "CODE/BLOWFISH.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BLOWFISH.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BLOWFISH.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 04/14/96                                                     *\n *                                                                                             *\n *                  Last Update : July 8, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BlowfishEngine::Decrypt -- Decrypts data using blowfish algorithm.                        *\n *   BlowfishEngine::Encrypt -- Encrypt an arbitrary block of data.                            *\n *   BlowfishEngine::Process_Block -- Process a block of data using Blowfish algorithm.        *\n *   BlowfishEngine::Sub_Key_Encrypt -- Encrypts a block for use in S-Box processing.          *\n *   BlowfishEngine::Submit_Key -- Submit a key that will allow data processing.               *\n *   BlowfishEngine::~BlowfishEngine -- Destructor for the Blowfish engine.                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"blowfish.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/*\n**\tByte order controlled long integer. This integer is constructed\n**\tso that character 0 (C0) is the most significant byte of the\n**\tinteger. This is biased toward big endian architecture, but that\n**\tjust happens to be how the Blowfish algorithm was designed.\n*/\ntypedef union {\n\tunsigned long Long;\n\tstruct {\n\t\tunsigned char C3;\n\t\tunsigned char C2;\n\t\tunsigned char C1;\n\t\tunsigned char C0;\n\t} Char;\n} Int;\n\n\n/***********************************************************************************************\n * BlowfishEngine::~BlowfishEngine -- Destructor for the Blowfish engine.                      *\n *                                                                                             *\n *    This destructor will clear out the s-box tables so that even if the memory for the       *\n *    class remains, it will contain no compromising data.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBlowfishEngine::~BlowfishEngine(void)\n{\n\tif (IsKeyed) {\n\t\tSubmit_Key(NULL, 0);\n\t}\n}\n\n\n/***********************************************************************************************\n * BlowfishEngine::Submit_Key -- Submit a key that will allow data processing.                 *\n *                                                                                             *\n *    This routine must be called before any data can be encrypted or decrypted. This routine  *\n *    need only be called when the key is to be changed or set for the first time. Once the    *\n *    key has been set, the engine may be used to encrypt, decrypt, or both operations         *\n *    indefinitely. The key must be 56 bytes or less in length. This is necessary because      *\n *    any keys longer than that will not correctly affect the encryption process.              *\n *                                                                                             *\n *    If the key pointer is NULL, then the S-Box tables are reset to identity. This will       *\n *    mask the previous key setting. Use this method to clear the engine after processing in   *\n *    order to gain a measure of security.                                                     *\n *                                                                                             *\n * INPUT:   key      -- Pointer to the key data block.                                         *\n *                                                                                             *\n *          length   -- The length of the submitted key.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This is a time consuming process.                                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BlowfishEngine::Submit_Key(void const * key, int length)\n{\n\tassert(length <= MAX_KEY_LENGTH);\n\n\t/*\n\t**\tInitialize the permutation and S-Box tables to a known\n\t**\tconstant value.\n\t*/\n\tmemcpy(P_Encrypt, P_Init, sizeof(P_Init));\n\tmemcpy(P_Decrypt, P_Init, sizeof(P_Init));\n\tmemcpy(bf_S, S_Init, sizeof(S_Init));\n\n\t/*\n\t**\tValidate parameters.\n\t*/\n\tif (key == 0 || length == 0) {\n\t\tIsKeyed = false;\n\t\treturn;\n\t}\n\n\t/*\n\t**\tCombine the key with the permutation table. Wrap the key\n\t**\tas many times as necessary to ensure that the entire\n\t**\tpermutation table has been modified. The key is lifted\n\t**\tinto a long by using endian independent means.\n\t*/\n\tint j = 0;\n\tunsigned char const * key_ptr = (unsigned char const *)key;\n\tunsigned long * p_ptr = &P_Encrypt[0];\n\tfor (int index = 0; index < ROUNDS+2; index++) {\n\t\tunsigned long data = 0;\n\n\t\tdata = (data << CHAR_BIT) | key_ptr[j++ % length];\n\t\tdata = (data << CHAR_BIT) | key_ptr[j++ % length];\n\t\tdata = (data << CHAR_BIT) | key_ptr[j++ % length];\n\t\tdata = (data << CHAR_BIT) | key_ptr[j++ % length];\n\n\t\t*p_ptr++ ^= data;\n\t}\n\n\t/*\n\t**\tThe permutation table must be scrambled by means of the key. This\n\t**\tis how the key is factored into the encryption -- by merely altering\n\t**\tthe permutation (and S-Box) tables. Because this transformation alters\n\t**\tthe table data WHILE it is using the table data, the tables are\n\t**\tthoroughly obfuscated by this process.\n\t*/\n\tunsigned long left = 0x00000000L;\n\tunsigned long right = 0x00000000L;\n\tunsigned long * p_en = &P_Encrypt[0];\t\t\t// Encryption table.\n\tunsigned long * p_de = &P_Decrypt[ROUNDS+1];\t// Decryption table.\n\tfor (int p_index = 0; p_index < ROUNDS+2; p_index += 2) {\n\t\tSub_Key_Encrypt(left, right);\n\n\t\t*p_en++ = left;\n\t\t*p_en++ = right;\n\n\t\t*p_de-- = left;\n\t\t*p_de-- = right;\n\t}\n\n\t/*\n\t**\tPerform a similar transmutation to the S-Box tables. Also notice that the\n\t**\tworking 64 bit number is carried into this process from the previous\n\t**\toperation.\n\t*/\n\tfor (int sbox_index = 0; sbox_index < 4; sbox_index++) {\n\t\tfor (int ss_index = 0; ss_index < UCHAR_MAX+1; ss_index += 2) {\n\t\t\tSub_Key_Encrypt(left, right);\n\t\t\tbf_S[sbox_index][ss_index] = left;\n\t\t\tbf_S[sbox_index][ss_index + 1] = right;\n\t\t}\n\t}\n\n\tIsKeyed = true;\n}\n\n\n/***********************************************************************************************\n * BlowfishEngine::Encrypt -- Encrypt an arbitrary block of data.                              *\n *                                                                                             *\n *    Use this routine to encrypt an arbitrary block of data. The block must be an even        *\n *    multiple of 8 bytes. Any bytes left over will not be encrypted. The 8 byte requirement   *\n *    is necessary because the underlying algorithm processes blocks in 8 byte chunks.         *\n *    Partial blocks are unrecoverable and useless.                                            *\n *                                                                                             *\n * INPUT:   plaintext-- Pointer to the data block to be encrypted.                             *\n *                                                                                             *\n *          length   -- The length of the data block.                                          *\n *                                                                                             *\n *          cyphertext- Pointer to the output buffer that will hold the encrypted data.        *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes encrypted.                                 *\n *                                                                                             *\n * WARNINGS:   You must submit the key before calling this routine. This will only encrypt     *\n *             the plaintext in 8 byte increments. Modulo bytes left over are not processed.   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BlowfishEngine::Encrypt(void const * plaintext, int length, void * cyphertext)\n{\n\tif (plaintext == 0 || length == 0) {\n\t\treturn(0);\n\t}\n\tif (cyphertext == 0) cyphertext = (void *)plaintext;\n\n\tif (IsKeyed) {\n\n\t\t/*\n\t\t**\tValidate parameters.\n\t\t*/\n\t\tint blocks = length / BYTES_PER_BLOCK;\n\n\t\t/*\n\t\t**\tProcess the buffer in 64 bit chunks.\n\t\t*/\n\t\tfor (int index = 0; index < blocks; index++) {\n\t\t\tProcess_Block(plaintext, cyphertext, P_Encrypt);\n\t\t\tplaintext = ((char *)plaintext) + BYTES_PER_BLOCK;\n\t\t\tcyphertext = ((char *)cyphertext) + BYTES_PER_BLOCK;\n\t\t}\n\t\tint encrypted = blocks * BYTES_PER_BLOCK;\n\n\t\t/*\n\t\t**\tCopy over any trailing left over appendix bytes.\n\t\t*/\n\t\tif (encrypted < length) {\n\t\t\tmemmove(cyphertext, plaintext, length - encrypted);\n\t\t}\n\n\t\treturn(encrypted);\n\t}\n\n\t/*\n\t**\tNon-keyed processing merely copies the data.\n\t*/\n\tif (plaintext != cyphertext) {\n\t\tmemmove(cyphertext, plaintext, length);\n\t}\n\treturn(length);\n}\n\n\n/***********************************************************************************************\n * BlowfishEngine::Decrypt -- Decrypt an arbitrary block of data.                              *\n *                                                                                             *\n *    Use this routine to decrypt an arbitrary block of data. The block must be an even        *\n *    multiple of 8 bytes. Any bytes left over will not be decrypted. The 8 byte requirement   *\n *    is necessary because the underlying algorithm processes blocks in 8 byte chunks.         *\n *    Partial blocks are unrecoverable and useless.                                            *\n *                                                                                             *\n * INPUT:   cyphertext- Pointer to the data block to be decrypted.                             *\n *                                                                                             *\n *          length   -- The length of the data block.                                          *\n *                                                                                             *\n *          plaintext-- Pointer to the output buffer that will hold the decrypted data.        *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes decrypted.                                 *\n *                                                                                             *\n * WARNINGS:   You must submit the key before calling this routine. This will only decrypt     *\n *             the cyphertext in 8 byte increments. Modulo bytes left over are not processed.  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BlowfishEngine::Decrypt(void const * cyphertext, int length, void * plaintext)\n{\n\tif (cyphertext == 0 || length == 0) {\n\t\treturn(0);\n\t}\n\tif (plaintext == 0) plaintext = (void *)cyphertext;\n\n\tif (IsKeyed) {\n\n\t\t/*\n\t\t**\tValidate parameters.\n\t\t*/\n\t\tint blocks = length / BYTES_PER_BLOCK;\n\n\t\t/*\n\t\t**\tProcess the buffer in 64 bit chunks.\n\t\t*/\n\t\tfor (int index = 0; index < blocks; index++) {\n\t\t\tProcess_Block(cyphertext, plaintext, P_Decrypt);\n\t\t\tcyphertext = ((char *)cyphertext) + BYTES_PER_BLOCK;\n\t\t\tplaintext = ((char *)plaintext) + BYTES_PER_BLOCK;\n\t\t}\n\t\tint encrypted = blocks * BYTES_PER_BLOCK;\n\n\t\t/*\n\t\t**\tCopy over any trailing left over appendix bytes.\n\t\t*/\n\t\tif (encrypted < length) {\n\t\t\tmemmove(plaintext, cyphertext, length - encrypted);\n\t\t}\n\n\t\treturn(encrypted);\n\t}\n\n\t/*\n\t**\tNon-keyed processing merely copies the data.\n\t*/\n\tif (plaintext != cyphertext) {\n\t\tmemmove(plaintext, cyphertext, length);\n\t}\n\treturn(length);\n}\n\n\n/***********************************************************************************************\n * BlowfishEngine::Process_Block -- Process a block of data using Blowfish algorithm.          *\n *                                                                                             *\n *    This is the main processing routine for encryption and decryption. The algorithm         *\n *    consists of a 16 round Feistal network and uses mathematics from different algebraic     *\n *    groups (strengthens against differential cryptanalysis). The large S-Boxes and the       *\n *    rounds strengthen it against linear cryptanalysis.                                       *\n *                                                                                             *\n * INPUT:   plaintext   -- Pointer to the source text (it actually might be a pointer to       *\n *                         the cyphertext if this is called as a decryption process).          *\n *                                                                                             *\n *          cyphertext  -- Pointer to the output buffer that will hold the processed block.    *\n *                                                                                             *\n *          ptable      -- Pointer to the permutation table. This algorithm will encrypt       *\n *                         and decrypt using the same S-Box tables. The encryption control     *\n *                         is handled by the permutation table.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The source and destination buffers must be 8 bytes long.                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BlowfishEngine::Process_Block(void const * plaintext, void * cyphertext, unsigned long const * ptable)\n{\n\t/*\n\t**\tInput the left and right halves of the source block such that\n\t**\tthe byte order is constant regardless of the endian\n\t**\tpersuasion of the current processor. The blowfish algorithm is\n\t**\tbiased toward \"big endian\" architecture and some optimizations\n\t**\tcould be done for big endian processors in that case.\n\t*/\n\tunsigned char const * source = (unsigned char const *)plaintext;\n\tInt left;\n\tleft.Char.C0 = *source++;\n\tleft.Char.C1 = *source++;\n\tleft.Char.C2 = *source++;\n\tleft.Char.C3 = *source++;\n\n\tInt right;\n\tright.Char.C0 = *source++;\n\tright.Char.C1 = *source++;\n\tright.Char.C2 = *source++;\n\tright.Char.C3 = *source;\n\n\t/*\n\t**\tPerform all Feistal rounds on the block. This is the encryption/decryption\n\t**\tprocess. Since there is an exchange that occurs after each round, two\n\t**\trounds are combined in this loop to avoid unnecessary exchanging.\n\t*/\n\tfor (int index = 0; index < ROUNDS/2; index++) {\n\t\tleft.Long ^= *ptable++;\n\t\tright.Long ^= ((( bf_S[0][left.Char.C0] + bf_S[1][left.Char.C1]) ^ bf_S[2][left.Char.C2]) + bf_S[3][left.Char.C3]);\n\t\tright.Long ^= *ptable++;\n\t\tleft.Long ^= ((( bf_S[0][right.Char.C0] + bf_S[1][right.Char.C1]) ^ bf_S[2][right.Char.C2]) + bf_S[3][right.Char.C3]);\n\t}\n\n\t/*\n\t**\tThe final two longs in the permutation table are processed into the block.\n\t**\tThe left and right halves are still reversed as a side effect of the last\n\t**\tround.\n\t*/\n\tleft.Long ^= *ptable++;\n\tright.Long ^= *ptable;\n\n\t/*\n\t**\tThe final block data is output in endian architecture\n\t**\tindependent format. Notice that the blocks are output as\n\t**\tright first and left second. This is to counteract the final\n\t**\tsuperfluous exchange that occurs as a side effect of the\n\t**\tencryption rounds.\n\t*/\n\tunsigned char * out = (unsigned char *)cyphertext;\n\t*out++ = right.Char.C0;\n\t*out++ = right.Char.C1;\n\t*out++ = right.Char.C2;\n\t*out++ = right.Char.C3;\n\n\t*out++ = left.Char.C0;\n\t*out++ = left.Char.C1;\n\t*out++ = left.Char.C2;\n\t*out = left.Char.C3;\n}\n\n\n/***********************************************************************************************\n * BlowfishEngine::Sub_Key_Encrypt -- Encrypts a block for use in S-Box processing.            *\n *                                                                                             *\n *    This is the same as the normal process block function but it doesn't have the endian     *\n *    fixup logic. Since this routine is only called for S-Box table generation and it is      *\n *    known that the S-Box initial data is already in local machine endian format, the         *\n *    byte order fixups are not needed. This also has a tendency to speed up S-Box generation  *\n *    as well.                                                                                 *\n *                                                                                             *\n * INPUT:   left  -- The left half of the data block.                                          *\n *                                                                                             *\n *          right -- The right half of the data block.                                         *\n *                                                                                             *\n * OUTPUT:  none, but the processed block is stored back into the left and right half          *\n *          integers.                                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BlowfishEngine::Sub_Key_Encrypt(unsigned long & left, unsigned long & right)\n{\n\tInt l;\n\tl.Long = left;\n\n\tInt r;\n\tr.Long = right;\n\n\tfor (int index = 0; index < ROUNDS; index += 2) {\n\t\tl.Long ^= P_Encrypt[index];\n\t\tr.Long ^= ((( bf_S[0][l.Char.C0] + bf_S[1][l.Char.C1]) ^ bf_S[2][l.Char.C2]) + bf_S[3][l.Char.C3]);\n\t\tr.Long ^= P_Encrypt[index+1];\n\t\tl.Long ^= ((( bf_S[0][r.Char.C0] + bf_S[1][r.Char.C1]) ^ bf_S[2][r.Char.C2]) + bf_S[3][r.Char.C3]);\n\t}\n\tleft = r.Long ^ P_Encrypt[ROUNDS+1];\n\tright = l.Long ^ P_Encrypt[ROUNDS];\n}\n\n\n/*\n**\tThese tables have the bytes stored in machine endian format. Because of this,\n**\ta special block cypher routine is needed when the sub-keys are generated.\n**\tThis is kludgier than it otherwise should be. However, storing these\n**\tintegers in machine independent format would be even more painful.\n*/\n\nunsigned long const BlowfishEngine::P_Init[BlowfishEngine::ROUNDS+2] = {\n\t0x243F6A88U,0x85A308D3U,0x13198A2EU,0x03707344U,0xA4093822U,0x299F31D0U,0x082EFA98U,0xEC4E6C89U,\n\t0x452821E6U,0x38D01377U,0xBE5466CFU,0x34E90C6CU,0xC0AC29B7U,0xC97C50DDU,0x3F84D5B5U,0xB5470917U,\n\t0x9216D5D9U,0x8979FB1BU\n} ;\n\nunsigned long const BlowfishEngine::S_Init[4][UCHAR_MAX+1] = {\n\t{\n\t\t0xD1310BA6U,0x98DFB5ACU,0x2FFD72DBU,0xD01ADFB7U,0xB8E1AFEDU,0x6A267E96U,0xBA7C9045U,0xF12C7F99U,\n\t\t0x24A19947U,0xB3916CF7U,0x0801F2E2U,0x858EFC16U,0x636920D8U,0x71574E69U,0xA458FEA3U,0xF4933D7EU,\n\t\t0x0D95748FU,0x728EB658U,0x718BCD58U,0x82154AEEU,0x7B54A41DU,0xC25A59B5U,0x9C30D539U,0x2AF26013U,\n\t\t0xC5D1B023U,0x286085F0U,0xCA417918U,0xB8DB38EFU,0x8E79DCB0U,0x603A180EU,0x6C9E0E8BU,0xB01E8A3EU,\n\t\t0xD71577C1U,0xBD314B27U,0x78AF2FDAU,0x55605C60U,0xE65525F3U,0xAA55AB94U,0x57489862U,0x63E81440U,\n\t\t0x55CA396AU,0x2AAB10B6U,0xB4CC5C34U,0x1141E8CEU,0xA15486AFU,0x7C72E993U,0xB3EE1411U,0x636FBC2AU,\n\t\t0x2BA9C55DU,0x741831F6U,0xCE5C3E16U,0x9B87931EU,0xAFD6BA33U,0x6C24CF5CU,0x7A325381U,0x28958677U,\n\t\t0x3B8F4898U,0x6B4BB9AFU,0xC4BFE81BU,0x66282193U,0x61D809CCU,0xFB21A991U,0x487CAC60U,0x5DEC8032U,\n\t\t0xEF845D5DU,0xE98575B1U,0xDC262302U,0xEB651B88U,0x23893E81U,0xD396ACC5U,0x0F6D6FF3U,0x83F44239U,\n\t\t0x2E0B4482U,0xA4842004U,0x69C8F04AU,0x9E1F9B5EU,0x21C66842U,0xF6E96C9AU,0x670C9C61U,0xABD388F0U,\n\t\t0x6A51A0D2U,0xD8542F68U,0x960FA728U,0xAB5133A3U,0x6EEF0B6CU,0x137A3BE4U,0xBA3BF050U,0x7EFB2A98U,\n\t\t0xA1F1651DU,0x39AF0176U,0x66CA593EU,0x82430E88U,0x8CEE8619U,0x456F9FB4U,0x7D84A5C3U,0x3B8B5EBEU,\n\t\t0xE06F75D8U,0x85C12073U,0x401A449FU,0x56C16AA6U,0x4ED3AA62U,0x363F7706U,0x1BFEDF72U,0x429B023DU,\n\t\t0x37D0D724U,0xD00A1248U,0xDB0FEAD3U,0x49F1C09BU,0x075372C9U,0x80991B7BU,0x25D479D8U,0xF6E8DEF7U,\n\t\t0xE3FE501AU,0xB6794C3BU,0x976CE0BDU,0x04C006BAU,0xC1A94FB6U,0x409F60C4U,0x5E5C9EC2U,0x196A2463U,\n\t\t0x68FB6FAFU,0x3E6C53B5U,0x1339B2EBU,0x3B52EC6FU,0x6DFC511FU,0x9B30952CU,0xCC814544U,0xAF5EBD09U,\n\t\t0xBEE3D004U,0xDE334AFDU,0x660F2807U,0x192E4BB3U,0xC0CBA857U,0x45C8740FU,0xD20B5F39U,0xB9D3FBDBU,\n\t\t0x5579C0BDU,0x1A60320AU,0xD6A100C6U,0x402C7279U,0x679F25FEU,0xFB1FA3CCU,0x8EA5E9F8U,0xDB3222F8U,\n\t\t0x3C7516DFU,0xFD616B15U,0x2F501EC8U,0xAD0552ABU,0x323DB5FAU,0xFD238760U,0x53317B48U,0x3E00DF82U,\n\t\t0x9E5C57BBU,0xCA6F8CA0U,0x1A87562EU,0xDF1769DBU,0xD542A8F6U,0x287EFFC3U,0xAC6732C6U,0x8C4F5573U,\n\t\t0x695B27B0U,0xBBCA58C8U,0xE1FFA35DU,0xB8F011A0U,0x10FA3D98U,0xFD2183B8U,0x4AFCB56CU,0x2DD1D35BU,\n\t\t0x9A53E479U,0xB6F84565U,0xD28E49BCU,0x4BFB9790U,0xE1DDF2DAU,0xA4CB7E33U,0x62FB1341U,0xCEE4C6E8U,\n\t\t0xEF20CADAU,0x36774C01U,0xD07E9EFEU,0x2BF11FB4U,0x95DBDA4DU,0xAE909198U,0xEAAD8E71U,0x6B93D5A0U,\n\t\t0xD08ED1D0U,0xAFC725E0U,0x8E3C5B2FU,0x8E7594B7U,0x8FF6E2FBU,0xF2122B64U,0x8888B812U,0x900DF01CU,\n\t\t0x4FAD5EA0U,0x688FC31CU,0xD1CFF191U,0xB3A8C1ADU,0x2F2F2218U,0xBE0E1777U,0xEA752DFEU,0x8B021FA1U,\n\t\t0xE5A0CC0FU,0xB56F74E8U,0x18ACF3D6U,0xCE89E299U,0xB4A84FE0U,0xFD13E0B7U,0x7CC43B81U,0xD2ADA8D9U,\n\t\t0x165FA266U,0x80957705U,0x93CC7314U,0x211A1477U,0xE6AD2065U,0x77B5FA86U,0xC75442F5U,0xFB9D35CFU,\n\t\t0xEBCDAF0CU,0x7B3E89A0U,0xD6411BD3U,0xAE1E7E49U,0x00250E2DU,0x2071B35EU,0x226800BBU,0x57B8E0AFU,\n\t\t0x2464369BU,0xF009B91EU,0x5563911DU,0x59DFA6AAU,0x78C14389U,0xD95A537FU,0x207D5BA2U,0x02E5B9C5U,\n\t\t0x83260376U,0x6295CFA9U,0x11C81968U,0x4E734A41U,0xB3472DCAU,0x7B14A94AU,0x1B510052U,0x9A532915U,\n\t\t0xD60F573FU,0xBC9BC6E4U,0x2B60A476U,0x81E67400U,0x08BA6FB5U,0x571BE91FU,0xF296EC6BU,0x2A0DD915U,\n\t\t0xB6636521U,0xE7B9F9B6U,0xFF34052EU,0xC5855664U,0x53B02D5DU,0xA99F8FA1U,0x08BA4799U,0x6E85076AU,\n\t},{\n\t\t0x4B7A70E9U,0xB5B32944U,0xDB75092EU,0xC4192623U,0xAD6EA6B0U,0x49A7DF7DU,0x9CEE60B8U,0x8FEDB266U,\n\t\t0xECAA8C71U,0x699A17FFU,0x5664526CU,0xC2B19EE1U,0x193602A5U,0x75094C29U,0xA0591340U,0xE4183A3EU,\n\t\t0x3F54989AU,0x5B429D65U,0x6B8FE4D6U,0x99F73FD6U,0xA1D29C07U,0xEFE830F5U,0x4D2D38E6U,0xF0255DC1U,\n\t\t0x4CDD2086U,0x8470EB26U,0x6382E9C6U,0x021ECC5EU,0x09686B3FU,0x3EBAEFC9U,0x3C971814U,0x6B6A70A1U,\n\t\t0x687F3584U,0x52A0E286U,0xB79C5305U,0xAA500737U,0x3E07841CU,0x7FDEAE5CU,0x8E7D44ECU,0x5716F2B8U,\n\t\t0xB03ADA37U,0xF0500C0DU,0xF01C1F04U,0x0200B3FFU,0xAE0CF51AU,0x3CB574B2U,0x25837A58U,0xDC0921BDU,\n\t\t0xD19113F9U,0x7CA92FF6U,0x94324773U,0x22F54701U,0x3AE5E581U,0x37C2DADCU,0xC8B57634U,0x9AF3DDA7U,\n\t\t0xA9446146U,0x0FD0030EU,0xECC8C73EU,0xA4751E41U,0xE238CD99U,0x3BEA0E2FU,0x3280BBA1U,0x183EB331U,\n\t\t0x4E548B38U,0x4F6DB908U,0x6F420D03U,0xF60A04BFU,0x2CB81290U,0x24977C79U,0x5679B072U,0xBCAF89AFU,\n\t\t0xDE9A771FU,0xD9930810U,0xB38BAE12U,0xDCCF3F2EU,0x5512721FU,0x2E6B7124U,0x501ADDE6U,0x9F84CD87U,\n\t\t0x7A584718U,0x7408DA17U,0xBC9F9ABCU,0xE94B7D8CU,0xEC7AEC3AU,0xDB851DFAU,0x63094366U,0xC464C3D2U,\n\t\t0xEF1C1847U,0x3215D908U,0xDD433B37U,0x24C2BA16U,0x12A14D43U,0x2A65C451U,0x50940002U,0x133AE4DDU,\n\t\t0x71DFF89EU,0x10314E55U,0x81AC77D6U,0x5F11199BU,0x043556F1U,0xD7A3C76BU,0x3C11183BU,0x5924A509U,\n\t\t0xF28FE6EDU,0x97F1FBFAU,0x9EBABF2CU,0x1E153C6EU,0x86E34570U,0xEAE96FB1U,0x860E5E0AU,0x5A3E2AB3U,\n\t\t0x771FE71CU,0x4E3D06FAU,0x2965DCB9U,0x99E71D0FU,0x803E89D6U,0x5266C825U,0x2E4CC978U,0x9C10B36AU,\n\t\t0xC6150EBAU,0x94E2EA78U,0xA5FC3C53U,0x1E0A2DF4U,0xF2F74EA7U,0x361D2B3DU,0x1939260FU,0x19C27960U,\n\t\t0x5223A708U,0xF71312B6U,0xEBADFE6EU,0xEAC31F66U,0xE3BC4595U,0xA67BC883U,0xB17F37D1U,0x018CFF28U,\n\t\t0xC332DDEFU,0xBE6C5AA5U,0x65582185U,0x68AB9802U,0xEECEA50FU,0xDB2F953BU,0x2AEF7DADU,0x5B6E2F84U,\n\t\t0x1521B628U,0x29076170U,0xECDD4775U,0x619F1510U,0x13CCA830U,0xEB61BD96U,0x0334FE1EU,0xAA0363CFU,\n\t\t0xB5735C90U,0x4C70A239U,0xD59E9E0BU,0xCBAADE14U,0xEECC86BCU,0x60622CA7U,0x9CAB5CABU,0xB2F3846EU,\n\t\t0x648B1EAFU,0x19BDF0CAU,0xA02369B9U,0x655ABB50U,0x40685A32U,0x3C2AB4B3U,0x319EE9D5U,0xC021B8F7U,\n\t\t0x9B540B19U,0x875FA099U,0x95F7997EU,0x623D7DA8U,0xF837889AU,0x97E32D77U,0x11ED935FU,0x16681281U,\n\t\t0x0E358829U,0xC7E61FD6U,0x96DEDFA1U,0x7858BA99U,0x57F584A5U,0x1B227263U,0x9B83C3FFU,0x1AC24696U,\n\t\t0xCDB30AEBU,0x532E3054U,0x8FD948E4U,0x6DBC3128U,0x58EBF2EFU,0x34C6FFEAU,0xFE28ED61U,0xEE7C3C73U,\n\t\t0x5D4A14D9U,0xE864B7E3U,0x42105D14U,0x203E13E0U,0x45EEE2B6U,0xA3AAABEAU,0xDB6C4F15U,0xFACB4FD0U,\n\t\t0xC742F442U,0xEF6ABBB5U,0x654F3B1DU,0x41CD2105U,0xD81E799EU,0x86854DC7U,0xE44B476AU,0x3D816250U,\n\t\t0xCF62A1F2U,0x5B8D2646U,0xFC8883A0U,0xC1C7B6A3U,0x7F1524C3U,0x69CB7492U,0x47848A0BU,0x5692B285U,\n\t\t0x095BBF00U,0xAD19489DU,0x1462B174U,0x23820E00U,0x58428D2AU,0x0C55F5EAU,0x1DADF43EU,0x233F7061U,\n\t\t0x3372F092U,0x8D937E41U,0xD65FECF1U,0x6C223BDBU,0x7CDE3759U,0xCBEE7460U,0x4085F2A7U,0xCE77326EU,\n\t\t0xA6078084U,0x19F8509EU,0xE8EFD855U,0x61D99735U,0xA969A7AAU,0xC50C06C2U,0x5A04ABFCU,0x800BCADCU,\n\t\t0x9E447A2EU,0xC3453484U,0xFDD56705U,0x0E1E9EC9U,0xDB73DBD3U,0x105588CDU,0x675FDA79U,0xE3674340U,\n\t\t0xC5C43465U,0x713E38D8U,0x3D28F89EU,0xF16DFF20U,0x153E21E7U,0x8FB03D4AU,0xE6E39F2BU,0xDB83ADF7U,\n\t},{\n\t\t0xE93D5A68U,0x948140F7U,0xF64C261CU,0x94692934U,0x411520F7U,0x7602D4F7U,0xBCF46B2EU,0xD4A20068U,\n\t\t0xD4082471U,0x3320F46AU,0x43B7D4B7U,0x500061AFU,0x1E39F62EU,0x97244546U,0x14214F74U,0xBF8B8840U,\n\t\t0x4D95FC1DU,0x96B591AFU,0x70F4DDD3U,0x66A02F45U,0xBFBC09ECU,0x03BD9785U,0x7FAC6DD0U,0x31CB8504U,\n\t\t0x96EB27B3U,0x55FD3941U,0xDA2547E6U,0xABCA0A9AU,0x28507825U,0x530429F4U,0x0A2C86DAU,0xE9B66DFBU,\n\t\t0x68DC1462U,0xD7486900U,0x680EC0A4U,0x27A18DEEU,0x4F3FFEA2U,0xE887AD8CU,0xB58CE006U,0x7AF4D6B6U,\n\t\t0xAACE1E7CU,0xD3375FECU,0xCE78A399U,0x406B2A42U,0x20FE9E35U,0xD9F385B9U,0xEE39D7ABU,0x3B124E8BU,\n\t\t0x1DC9FAF7U,0x4B6D1856U,0x26A36631U,0xEAE397B2U,0x3A6EFA74U,0xDD5B4332U,0x6841E7F7U,0xCA7820FBU,\n\t\t0xFB0AF54EU,0xD8FEB397U,0x454056ACU,0xBA489527U,0x55533A3AU,0x20838D87U,0xFE6BA9B7U,0xD096954BU,\n\t\t0x55A867BCU,0xA1159A58U,0xCCA92963U,0x99E1DB33U,0xA62A4A56U,0x3F3125F9U,0x5EF47E1CU,0x9029317CU,\n\t\t0xFDF8E802U,0x04272F70U,0x80BB155CU,0x05282CE3U,0x95C11548U,0xE4C66D22U,0x48C1133FU,0xC70F86DCU,\n\t\t0x07F9C9EEU,0x41041F0FU,0x404779A4U,0x5D886E17U,0x325F51EBU,0xD59BC0D1U,0xF2BCC18FU,0x41113564U,\n\t\t0x257B7834U,0x602A9C60U,0xDFF8E8A3U,0x1F636C1BU,0x0E12B4C2U,0x02E1329EU,0xAF664FD1U,0xCAD18115U,\n\t\t0x6B2395E0U,0x333E92E1U,0x3B240B62U,0xEEBEB922U,0x85B2A20EU,0xE6BA0D99U,0xDE720C8CU,0x2DA2F728U,\n\t\t0xD0127845U,0x95B794FDU,0x647D0862U,0xE7CCF5F0U,0x5449A36FU,0x877D48FAU,0xC39DFD27U,0xF33E8D1EU,\n\t\t0x0A476341U,0x992EFF74U,0x3A6F6EABU,0xF4F8FD37U,0xA812DC60U,0xA1EBDDF8U,0x991BE14CU,0xDB6E6B0DU,\n\t\t0xC67B5510U,0x6D672C37U,0x2765D43BU,0xDCD0E804U,0xF1290DC7U,0xCC00FFA3U,0xB5390F92U,0x690FED0BU,\n\t\t0x667B9FFBU,0xCEDB7D9CU,0xA091CF0BU,0xD9155EA3U,0xBB132F88U,0x515BAD24U,0x7B9479BFU,0x763BD6EBU,\n\t\t0x37392EB3U,0xCC115979U,0x8026E297U,0xF42E312DU,0x6842ADA7U,0xC66A2B3BU,0x12754CCCU,0x782EF11CU,\n\t\t0x6A124237U,0xB79251E7U,0x06A1BBE6U,0x4BFB6350U,0x1A6B1018U,0x11CAEDFAU,0x3D25BDD8U,0xE2E1C3C9U,\n\t\t0x44421659U,0x0A121386U,0xD90CEC6EU,0xD5ABEA2AU,0x64AF674EU,0xDA86A85FU,0xBEBFE988U,0x64E4C3FEU,\n\t\t0x9DBC8057U,0xF0F7C086U,0x60787BF8U,0x6003604DU,0xD1FD8346U,0xF6381FB0U,0x7745AE04U,0xD736FCCCU,\n\t\t0x83426B33U,0xF01EAB71U,0xB0804187U,0x3C005E5FU,0x77A057BEU,0xBDE8AE24U,0x55464299U,0xBF582E61U,\n\t\t0x4E58F48FU,0xF2DDFDA2U,0xF474EF38U,0x8789BDC2U,0x5366F9C3U,0xC8B38E74U,0xB475F255U,0x46FCD9B9U,\n\t\t0x7AEB2661U,0x8B1DDF84U,0x846A0E79U,0x915F95E2U,0x466E598EU,0x20B45770U,0x8CD55591U,0xC902DE4CU,\n\t\t0xB90BACE1U,0xBB8205D0U,0x11A86248U,0x7574A99EU,0xB77F19B6U,0xE0A9DC09U,0x662D09A1U,0xC4324633U,\n\t\t0xE85A1F02U,0x09F0BE8CU,0x4A99A025U,0x1D6EFE10U,0x1AB93D1DU,0x0BA5A4DFU,0xA186F20FU,0x2868F169U,\n\t\t0xDCB7DA83U,0x573906FEU,0xA1E2CE9BU,0x4FCD7F52U,0x50115E01U,0xA70683FAU,0xA002B5C4U,0x0DE6D027U,\n\t\t0x9AF88C27U,0x773F8641U,0xC3604C06U,0x61A806B5U,0xF0177A28U,0xC0F586E0U,0x006058AAU,0x30DC7D62U,\n\t\t0x11E69ED7U,0x2338EA63U,0x53C2DD94U,0xC2C21634U,0xBBCBEE56U,0x90BCB6DEU,0xEBFC7DA1U,0xCE591D76U,\n\t\t0x6F05E409U,0x4B7C0188U,0x39720A3DU,0x7C927C24U,0x86E3725FU,0x724D9DB9U,0x1AC15BB4U,0xD39EB8FCU,\n\t\t0xED545578U,0x08FCA5B5U,0xD83D7CD3U,0x4DAD0FC4U,0x1E50EF5EU,0xB161E6F8U,0xA28514D9U,0x6C51133CU,\n\t\t0x6FD5C7E7U,0x56E14EC4U,0x362ABFCEU,0xDDC6C837U,0xD79A3234U,0x92638212U,0x670EFA8EU,0x406000E0U,\n\t},{\n\t\t0x3A39CE37U,0xD3FAF5CFU,0xABC27737U,0x5AC52D1BU,0x5CB0679EU,0x4FA33742U,0xD3822740U,0x99BC9BBEU,\n\t\t0xD5118E9DU,0xBF0F7315U,0xD62D1C7EU,0xC700C47BU,0xB78C1B6BU,0x21A19045U,0xB26EB1BEU,0x6A366EB4U,\n\t\t0x5748AB2FU,0xBC946E79U,0xC6A376D2U,0x6549C2C8U,0x530FF8EEU,0x468DDE7DU,0xD5730A1DU,0x4CD04DC6U,\n\t\t0x2939BBDBU,0xA9BA4650U,0xAC9526E8U,0xBE5EE304U,0xA1FAD5F0U,0x6A2D519AU,0x63EF8CE2U,0x9A86EE22U,\n\t\t0xC089C2B8U,0x43242EF6U,0xA51E03AAU,0x9CF2D0A4U,0x83C061BAU,0x9BE96A4DU,0x8FE51550U,0xBA645BD6U,\n\t\t0x2826A2F9U,0xA73A3AE1U,0x4BA99586U,0xEF5562E9U,0xC72FEFD3U,0xF752F7DAU,0x3F046F69U,0x77FA0A59U,\n\t\t0x80E4A915U,0x87B08601U,0x9B09E6ADU,0x3B3EE593U,0xE990FD5AU,0x9E34D797U,0x2CF0B7D9U,0x022B8B51U,\n\t\t0x96D5AC3AU,0x017DA67DU,0xD1CF3ED6U,0x7C7D2D28U,0x1F9F25CFU,0xADF2B89BU,0x5AD6B472U,0x5A88F54CU,\n\t\t0xE029AC71U,0xE019A5E6U,0x47B0ACFDU,0xED93FA9BU,0xE8D3C48DU,0x283B57CCU,0xF8D56629U,0x79132E28U,\n\t\t0x785F0191U,0xED756055U,0xF7960E44U,0xE3D35E8CU,0x15056DD4U,0x88F46DBAU,0x03A16125U,0x0564F0BDU,\n\t\t0xC3EB9E15U,0x3C9057A2U,0x97271AECU,0xA93A072AU,0x1B3F6D9BU,0x1E6321F5U,0xF59C66FBU,0x26DCF319U,\n\t\t0x7533D928U,0xB155FDF5U,0x03563482U,0x8ABA3CBBU,0x28517711U,0xC20AD9F8U,0xABCC5167U,0xCCAD925FU,\n\t\t0x4DE81751U,0x3830DC8EU,0x379D5862U,0x9320F991U,0xEA7A90C2U,0xFB3E7BCEU,0x5121CE64U,0x774FBE32U,\n\t\t0xA8B6E37EU,0xC3293D46U,0x48DE5369U,0x6413E680U,0xA2AE0810U,0xDD6DB224U,0x69852DFDU,0x09072166U,\n\t\t0xB39A460AU,0x6445C0DDU,0x586CDECFU,0x1C20C8AEU,0x5BBEF7DDU,0x1B588D40U,0xCCD2017FU,0x6BB4E3BBU,\n\t\t0xDDA26A7EU,0x3A59FF45U,0x3E350A44U,0xBCB4CDD5U,0x72EACEA8U,0xFA6484BBU,0x8D6612AEU,0xBF3C6F47U,\n\t\t0xD29BE463U,0x542F5D9EU,0xAEC2771BU,0xF64E6370U,0x740E0D8DU,0xE75B1357U,0xF8721671U,0xAF537D5DU,\n\t\t0x4040CB08U,0x4EB4E2CCU,0x34D2466AU,0x0115AF84U,0xE1B00428U,0x95983A1DU,0x06B89FB4U,0xCE6EA048U,\n\t\t0x6F3F3B82U,0x3520AB82U,0x011A1D4BU,0x277227F8U,0x611560B1U,0xE7933FDCU,0xBB3A792BU,0x344525BDU,\n\t\t0xA08839E1U,0x51CE794BU,0x2F32C9B7U,0xA01FBAC9U,0xE01CC87EU,0xBCC7D1F6U,0xCF0111C3U,0xA1E8AAC7U,\n\t\t0x1A908749U,0xD44FBD9AU,0xD0DADECBU,0xD50ADA38U,0x0339C32AU,0xC6913667U,0x8DF9317CU,0xE0B12B4FU,\n\t\t0xF79E59B7U,0x43F5BB3AU,0xF2D519FFU,0x27D9459CU,0xBF97222CU,0x15E6FC2AU,0x0F91FC71U,0x9B941525U,\n\t\t0xFAE59361U,0xCEB69CEBU,0xC2A86459U,0x12BAA8D1U,0xB6C1075EU,0xE3056A0CU,0x10D25065U,0xCB03A442U,\n\t\t0xE0EC6E0EU,0x1698DB3BU,0x4C98A0BEU,0x3278E964U,0x9F1F9532U,0xE0D392DFU,0xD3A0342BU,0x8971F21EU,\n\t\t0x1B0A7441U,0x4BA3348CU,0xC5BE7120U,0xC37632D8U,0xDF359F8DU,0x9B992F2EU,0xE60B6F47U,0x0FE3F11DU,\n\t\t0xE54CDA54U,0x1EDAD891U,0xCE6279CFU,0xCD3E7E6FU,0x1618B166U,0xFD2C1D05U,0x848FD2C5U,0xF6FB2299U,\n\t\t0xF523F357U,0xA6327623U,0x93A83531U,0x56CCCD02U,0xACF08162U,0x5A75EBB5U,0x6E163697U,0x88D273CCU,\n\t\t0xDE966292U,0x81B949D0U,0x4C50901BU,0x71C65614U,0xE6C6C7BDU,0x327A140AU,0x45E1D006U,0xC3F27B9AU,\n\t\t0xC9AA53FDU,0x62A80F00U,0xBB25BFE2U,0x35BDD2F6U,0x71126905U,0xB2040222U,0xB6CBCF7CU,0xCD769C2BU,\n\t\t0x53113EC0U,0x1640E3D3U,0x38ABBD60U,0x2547ADF0U,0xBA38209CU,0xF746CE76U,0x77AFA1C5U,0x20756060U,\n\t\t0x85CBFE4EU,0x8AE88DD8U,0x7AAAF9B0U,0x4CF9AA7EU,0x1948C25CU,0x02FB8A8CU,0x01C36AE4U,0xD6EBE1F9U,\n\t\t0x90D4F869U,0xA65CDEA0U,0x3F09252DU,0xC208E69FU,0xB74E6132U,0xCE77E25BU,0x578FDFE3U,0x3AC372E6U\n\t}\n};\n\n"
  },
  {
    "path": "CODE/BLOWFISH.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BLOWFISH.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BLOWFISH.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 04/14/96                                                     *\n *                                                                                             *\n *                  Last Update : April 14, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BLOWFISH_H\n#define BLOWFISH_H\n\n#include\t<limits.h>\n\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\n/*\n**\tThis engine will process data blocks by encryption and decryption.\n**\tThe \"Blowfish\" algorithm is in the public domain. It uses\n**\ta Feistal network (similar to IDEA). It has no known\n**\tweaknesses, but is still relatively new. Blowfish is particularly strong\n**\tagainst brute force attacks. It is also quite strong against linear and\n**\tdifferential cryptanalysis. Its weakness is that it takes a relatively\n**\tlong time to set up with a new key (1/100th of a second on a P6-200).\n**\tThe time to set up a key is equivalent to encrypting 4240 bytes.\n*/\nclass BlowfishEngine {\n\tpublic:\n\t\tBlowfishEngine(void) : IsKeyed(false) {}\n\t\t~BlowfishEngine(void);\n\n\t\tvoid Submit_Key(void const * key, int length);\n\n\t\tint Encrypt(void const * plaintext, int length, void * cyphertext);\n\t\tint Decrypt(void const * cyphertext, int length, void * plaintext);\n\n\t\t/*\n\t\t**\tThis is the maximum key length supported.\n\t\t*/\n\t\tenum {MAX_KEY_LENGTH=56};\n\n\tprivate:\n\t\tbool IsKeyed;\n\n\t\tvoid Sub_Key_Encrypt(unsigned long & left, unsigned long & right);\n\n\t\tvoid Process_Block(void const * plaintext, void * cyphertext, unsigned long const * ptable);\n\t\tvoid Initialize_Tables(void);\n\n\t\tenum {\n\t\t\tROUNDS = 16,\t\t// Feistal round count (16 is standard).\n\t\t\tBYTES_PER_BLOCK=8\t// The number of bytes in each cypher block (don't change).\n\t\t};\n\n\t\t/*\n\t\t**\tInitialization data for sub keys. The initial values are constant and\n\t\t**\tfilled with a number generated from pi. Thus they are not random but\n\t\t**\tthey don't hold a weak pattern either.\n\t\t*/\n\t\tstatic unsigned long const P_Init[(int)ROUNDS+2];\n\t\tstatic unsigned long const S_Init[4][UCHAR_MAX+1];\n\n\t\t/*\n\t\t**\tPermutation tables for encryption and decryption.\n\t\t*/\n \t\tunsigned long P_Encrypt[(int)ROUNDS+2];\n \t\tunsigned long P_Decrypt[(int)ROUNDS+2];\n\n\t\t/*\n\t\t**\tS-Box tables (four).\n\t\t*/\n\t\tunsigned long bf_S[4][UCHAR_MAX+1];\n};\n\n#endif\n\n"
  },
  {
    "path": "CODE/BLOWPIPE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BLOWPIPE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BLOWPIPE.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BlowPipe::Flush -- Flushes any pending data out the pipe.                                 *\n *   BlowPipe::Key -- Submit a key to the blowfish pipe handler.                               *\n *   BlowPipe::Put -- Submit a block of data for encrypt/decrypt.                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"blowpipe.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * BlowPipe::Flush -- Flushes any pending data out the pipe.                                   *\n *                                                                                             *\n *    If there is any pending data in the holding buffer, then this routine will force it to   *\n *    be flushed out the end of the pipe.                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes output at the end final distant pipe       *\n *          segment in the chain.                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BlowPipe::Flush(void)\n{\n\tint total = 0;\n\tif (Counter > 0 && BF != NULL) {\n\t\ttotal += Pipe::Put(Buffer, Counter);\n\t}\n\tCounter = 0;\n\ttotal += Pipe::Flush();\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * BlowPipe::Put -- Submit a block of data for encrypt/decrypt.                                *\n *                                                                                             *\n *    This will take the data block specified and process it before passing it on to the next  *\n *    link in the pipe chain. A key must be submitted before this routine will actually perform*\n *    any processing. Prior to key submission, the data is passed through unchanged.           *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer that contains the data to pass through.          *\n *                                                                                             *\n *          length   -- The length of the data in the buffer.                                  *\n *                                                                                             *\n * OUTPUT:  Returns with then actual number of bytes output at the final distant end link in   *\n *          the pipe chain.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BlowPipe::Put(void const * source, int slen)\n{\n\tif (source == NULL || slen < 1) {\n\t\treturn(Pipe::Put(source, slen));\n\t}\n\n\t/*\n\t**\tIf there is no blowfish engine present, then merely pass the data through\n\t**\tunchanged in any way.\n\t*/\n\tif (BF == NULL) {\n\t\treturn(Pipe::Put(source, slen));\n\t}\n\n\tint total = 0;\n\n\t/*\n\t**\tIf there is a partial block accumulated, then tag on the new data to\n\t**\tthis block and process it if the block is full. Proceed with the bulk\n\t**\tprocessing if there are any left over bytes from this step. This step\n\t**\tcan be skipped if there are no pending bytes in the buffer.\n\t*/\n\tif (Counter) {\n\t\tint sublen = (sizeof(Buffer)-Counter < slen) ? (sizeof(Buffer)-Counter) : slen;\n\t\tmemmove(&Buffer[Counter], source, sublen);\n\t\tCounter += sublen;\n\t\tsource = ((char *)source) + sublen;\n\t\tslen -= sublen;\n\n\t\tif (Counter == sizeof(Buffer)) {\n\t\t\tif (Control == DECRYPT) {\n\t\t\t\tBF->Decrypt(Buffer, sizeof(Buffer), Buffer);\n\t\t\t} else {\n\t\t\t\tBF->Encrypt(Buffer, sizeof(Buffer), Buffer);\n\t\t\t}\n\t\t\ttotal += Pipe::Put(Buffer, sizeof(Buffer));\n\t\t\tCounter = 0;\n\t\t}\n\t}\n\n\t/*\n\t**\tProcess the input data in blocks until there is not enough\n\t**\tsource data to fill a full block of data.\n\t*/\n\twhile (slen >= sizeof(Buffer)) {\n\t\tif (Control == DECRYPT) {\n\t\t\tBF->Decrypt(source, sizeof(Buffer), Buffer);\n\t\t} else {\n\t\t\tBF->Encrypt(source, sizeof(Buffer), Buffer);\n\t\t}\n\t\ttotal += Pipe::Put(Buffer, sizeof(Buffer));\n\t\tsource = ((char *)source) + sizeof(Buffer);\n\t\tslen -= sizeof(Buffer);\n\t}\n\n\t/*\n\t**\tIf there are any left over bytes, then they must be less than the size of\n\t**\tthe staging buffer. Store the bytes in the staging buffer for later\n\t**\tprocessing.\n\t*/\n\tif (slen > 0) {\n\t\tmemmove(Buffer, source, slen);\n\t\tCounter = slen;\n\t}\n\n\t/*\n\t**\tReturn with the total number of bytes flushed out to the final end of the\n\t**\tpipe chain.\n\t*/\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * BlowPipe::Key -- Submit a key to the blowfish pipe handler.                                 *\n *                                                                                             *\n *    This routine will take the key provided and use it to process the data that passes       *\n *    through this pipe. Prior to a key being submitted, the data passes through the pipe      *\n *    unchanged.                                                                               *\n *                                                                                             *\n * INPUT:   key   -- Pointer to the key data to use.                                           *\n *                                                                                             *\n *          length-- The length of the key. The key length must not be greater than 56 bytes.  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BlowPipe::Key(void const * key, int length)\n{\n\t/*\n\t**\tCreate the blowfish engine if one isn't already present.\n\t*/\n\tif (BF == NULL) {\n\t\tBF = new BlowfishEngine;\n\t}\n\n\tassert(BF != NULL);\n\n\tif (BF != NULL) {\n\t\tBF->Submit_Key(key, length);\n\t}\n}\n\n\n\n"
  },
  {
    "path": "CODE/BLOWPIPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BLOWPIPE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BLOWPIPE.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef BLOWPIPE_H\n#define BLOWPIPE_H\n\n#include\t\"pipe.h\"\n#include\t\"blowfish.h\"\n\n/*\n**\tPerforms Blowfish encryption/decryption on the data stream that is piped\n**\tthrough this class.\n*/\nclass BlowPipe : public Pipe\n{\n\tpublic:\n\t\ttypedef enum CryptControl {\n\t\t\tENCRYPT,\n\t\t\tDECRYPT\n\t\t} CryptControl;\n\n\t\tBlowPipe(CryptControl control) : BF(NULL), Counter(0), Control(control) {}\n\t\tvirtual ~BlowPipe(void) {delete BF;BF = NULL;}\n\t\tvirtual int Flush(void);\n\n\t\tvirtual int Put(void const * source, int slen);\n\n\t\t// Submit key for blowfish engine.\n\t\tvoid Key(void const * key, int length);\n\n\tprotected:\n\t\t/*\n\t\t**\tThe Blowfish engine used for encryption/decryption. If this pointer is\n\t\t**\tNULL, then this indicates that the blowfish engine is not active and no\n\t\t**\tkey has been submitted. All data would pass through this pipe unchanged\n\t\t**\tin that case.\n\t\t*/\n\t\tBlowfishEngine * BF;\n\n\tprivate:\n\t\tchar Buffer[8];\n\t\tint Counter;\n\t\tCryptControl Control;\n\n\t\tBlowPipe(BlowPipe & rvalue);\n\t\tBlowPipe & operator = (BlowPipe const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/BLWSTRAW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BLWSTRAW.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BLWSTRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BlowStraw::Get -- Fetch a block of data from the straw.                                   *\n *   BlowStraw::Key -- Submit a key to the Blowfish straw.                                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"blwstraw.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * BlowStraw::Get -- Fetch a block of data from the straw.                                     *\n *                                                                                             *\n *    This routine will take a block of data from the straw and process it according to the    *\n *    encrypt/decrypt flag and the key supplied. Prior to a key be supplied, the data passes   *\n *    through this straw unchanged.                                                            *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer to hold the data being requested.                *\n *                                                                                             *\n *          length   -- The length of the data being requested.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes stored into the buffer. If the number      *\n *          returned is less than the number requested, then this indicates that the data      *\n *          source has been exhausted.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BlowStraw::Get(void * source, int slen)\n{\n\t/*\n\t**\tVerify the parameter for legality.\n\t*/\n\tif (source == NULL || slen <= 0) {\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tIf there is no blowfish engine present, then merely pass the data through\n\t**\tunchanged.\n\t*/\n\tif (BF == NULL) {\n\t\treturn(Straw::Get(source, slen));\n\t}\n\n\tint total = 0;\n\n\twhile (slen > 0) {\n\n\t\t/*\n\t\t**\tIf there are any left over bytes in the buffer, pass them\n\t\t**\tthrough first.\n\t\t*/\n\t\tif (Counter > 0) {\n\t\t\tint sublen = (slen < Counter) ? slen : Counter;\n\t\t\tmemmove(source, &Buffer[sizeof(Buffer)-Counter], sublen);\n\t\t\tCounter -= sublen;\n\t\t\tsource = ((char *)source) + sublen;\n\t\t\tslen -= sublen;\n\t\t\ttotal += sublen;\n\t\t}\n\t\tif (slen == 0) break;\n\n\t\t/*\n\t\t**\tFetch and encrypt/decrypt the next block.\n\t\t*/\n\t\tint incount = Straw::Get(Buffer, sizeof(Buffer));\n\t\tif (incount == 0) break;\n\n\t\t/*\n\t\t**\tOnly full blocks are processed. Partial blocks are\n\t\t**\tmerely passed through unchanged.\n\t\t*/\n\t\tif (incount == sizeof(Buffer)) {\n\t\t\tif (Control == DECRYPT) {\n\t\t\t\tBF->Decrypt(Buffer, incount, Buffer);\n\t\t\t} else {\n\t\t\t\tBF->Encrypt(Buffer, incount, Buffer);\n\t\t\t}\n\t\t} else {\n\t\t\tmemmove(&Buffer[sizeof(Buffer)-incount], Buffer, incount);\n\t\t}\n\t\tCounter = incount;\n\t}\n\n\t/*\n\t**\tReturn with the total number of bytes placed into the buffer.\n\t*/\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * BlowStraw::Key -- Submit a key to the Blowfish straw.                                       *\n *                                                                                             *\n *    This will take the key specified and use it to process the data that flows through this  *\n *    straw segment. Prior to a key being submitted, the data will flow through unchanged.     *\n *                                                                                             *\n * INPUT:   key   -- Pointer to the key to submit.                                             *\n *                                                                                             *\n *          length-- The length of the key. The length must not exceed 56 bytes.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BlowStraw::Key(void const * key, int length)\n{\n\t/*\n\t**\tCreate the blowfish engine if one isn't already present.\n\t*/\n\tif (BF == NULL) {\n\t\tBF = new BlowfishEngine;\n\t}\n\n\tassert(BF != NULL);\n\n\tif (BF != NULL) {\n\t\tBF->Submit_Key(key, length);\n\t}\n}\n"
  },
  {
    "path": "CODE/BLWSTRAW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BLWSTRAW.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BLWSTRAW.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef BLWSTRAW_H\n#define BLWSTRAW_H\n\n#include\t\"straw.h\"\n#include\t\"blowfish.h\"\n\n\n/*\n**\tPerforms Blowfish encryption/decryption to the data that is drawn through this straw. The\n**\tprocess is controlled by the key which must be submitted to the class before any data\n**\tmanipulation will occur. The Blowfish algorithm is symmetric, thus the same key is used\n**\tfor encryption as is for decryption.\n*/\nclass BlowStraw : public Straw\n{\n\tpublic:\n\t\ttypedef enum CryptControl {\n\t\t\tENCRYPT,\n\t\t\tDECRYPT\n\t\t} CryptControl;\n\n\t\tBlowStraw(CryptControl control) : BF(NULL), Counter(0), Control(control) {}\n\t\tvirtual ~BlowStraw(void) {delete BF;BF = NULL;}\n\n\t\tvirtual int Get(void * source, int slen);\n\n\t\t// Submit key for blowfish engine.\n\t\tvoid Key(void const * key, int length);\n\n\tprotected:\n\t\t/*\n\t\t**\tThe Blowfish engine used for encryption/decryption. If this pointer is\n\t\t**\tNULL, then this indicates that the blowfish engine is not active and no\n\t\t**\tkey has been submitted. All data would pass through this straw unchanged\n\t\t**\tin that case.\n\t\t*/\n\t\tBlowfishEngine * BF;\n\n\tprivate:\n\t\tchar Buffer[8];\n\t\tint Counter;\n\t\tCryptControl Control;\n\n\t\tBlowStraw(BlowStraw & rvalue);\n\t\tBlowStraw & operator = (BlowStraw const & straw);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/BMP8.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#include \"bmp8.h\"\n\n//***********************************************************************************************\nBMP8::~BMP8()\n{\n\t// free resources\n\tif( hBitmap )\n\t\t::DeleteObject( hBitmap );\n\tif( hPal )\n\t\t::DeleteObject( hPal );\n}\n\n//***********************************************************************************************\nbool BMP8::Init( const char* szFile, HWND hWnd )\n{\n  int                  i;\n  char                 string[128];\n  DWORD                dwRead;\n  BITMAPFILEHEADER     bitmapHeader;\n  BITMAPINFOHEADER     bitmapInfoHeader;\n  LPLOGPALETTE         lpLogPalette;\n  char                *palData;\n  HGLOBAL              hmem2;\n  LPVOID               lpvBits;\n  PAINTSTRUCT          ps;\n  HDC                  hdc;\n  HPALETTE             select;\n  UINT                 realize;\n  RECT                 rect;\n\n\n\t//\tRemember window handle for use later.\n\tthis->hWnd = hWnd;\n\n\t//\tRetrieve a handle identifying the file. \n\tHANDLE hFile = ::CreateFile(\n\t\tszFile,\n\t\tGENERIC_READ,\n\t\tFILE_SHARE_READ,\n\t\t(LPSECURITY_ATTRIBUTES)NULL,\n\t\tOPEN_EXISTING,\n\t\tFILE_ATTRIBUTE_READONLY,\n\t\t(HANDLE)NULL );\n\n\tif(\t!hFile )\n\t\treturn false;\n\n\t// Retrieve the BITMAPFILEHEADER structure. \n\t::ReadFile( hFile, &bitmapHeader, sizeof(BITMAPFILEHEADER), &dwRead, (LPOVERLAPPED)NULL );\n\n\t// Retrieve the BITMAPFILEHEADER structure. \n\t::ReadFile( hFile, &bitmapInfoHeader, sizeof(BITMAPINFOHEADER), &dwRead, (LPOVERLAPPED)NULL );\n \n\t// Allocate memory for the BITMAPINFO structure. \n\tHGLOBAL infoHeaderMem = ::GlobalAlloc( GHND, sizeof(BITMAPINFOHEADER) + ((1<<bitmapInfoHeader.biBitCount) * sizeof(RGBQUAD)) );\n \n\tLPBITMAPINFO lpHeaderMem = (LPBITMAPINFO)::GlobalLock( infoHeaderMem ); \n \n\t// Load BITMAPINFOHEADER into the BITMAPINFO structure. \n\tlpHeaderMem->bmiHeader.biSize          = bitmapInfoHeader.biSize; \n\tlpHeaderMem->bmiHeader.biWidth         = bitmapInfoHeader.biWidth; \n\tlpHeaderMem->bmiHeader.biHeight        = bitmapInfoHeader.biHeight; \n\tlpHeaderMem->bmiHeader.biPlanes        = bitmapInfoHeader.biPlanes; \n\tlpHeaderMem->bmiHeader.biBitCount      = bitmapInfoHeader.biBitCount; \n\tlpHeaderMem->bmiHeader.biCompression   = bitmapInfoHeader.biCompression; \n\tlpHeaderMem->bmiHeader.biSizeImage     = bitmapInfoHeader.biSizeImage; \n\tlpHeaderMem->bmiHeader.biXPelsPerMeter = bitmapInfoHeader.biXPelsPerMeter; \n\tlpHeaderMem->bmiHeader.biYPelsPerMeter = bitmapInfoHeader.biYPelsPerMeter; \n\tlpHeaderMem->bmiHeader.biClrUsed       = bitmapInfoHeader.biClrUsed; \n\tlpHeaderMem->bmiHeader.biClrImportant  = bitmapInfoHeader.biClrImportant; \n\n\t// Retrieve the color table. \n\t// 1 << bitmapInfoHeader.biBitCount == 2 ^ bitmapInfoHeader.biBitCount \n\t::ReadFile( hFile, lpHeaderMem->bmiColors, ((1<<bitmapInfoHeader.biBitCount) * sizeof(RGBQUAD)),\n\t\t\t\t&dwRead, (LPOVERLAPPED)NULL );\n\n\n\tlpLogPalette = (LPLOGPALETTE)new char[ (sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*256) ];\n\tlpLogPalette->palVersion=0x300;\n\tlpLogPalette->palNumEntries=256;\n\n\tpalData = (char*)lpHeaderMem->bmiColors;\n\n\tfor( i = 0; i < 256; i++ )\n\t{\n\t\tlpLogPalette->palPalEntry[i].peRed = *palData++;\n\t\tlpLogPalette->palPalEntry[i].peGreen = *palData++;\n\t\tlpLogPalette->palPalEntry[i].peBlue = *palData++;\n\t\tlpLogPalette->palPalEntry[i].peFlags = *palData++;\n\t}\n\thPal = ::CreatePalette( lpLogPalette );\n\tdelete [] lpLogPalette;\n\n\t// Allocate memory for the required number of bytes. \n\thmem2 = ::GlobalAlloc( GHND, (bitmapHeader.bfSize - bitmapHeader.bfOffBits) );\n \n\tlpvBits = ::GlobalLock( hmem2 );\n \n\t// Retrieve the bitmap data. \n\t::ReadFile( hFile, lpvBits, (bitmapHeader.bfSize - bitmapHeader.bfOffBits), &dwRead, (LPOVERLAPPED)NULL );\n \n\t// Create a bitmap from the data stored in the .BMP file. \n\thdc = ::GetDC( hWnd );\n\tselect = ::SelectPalette( hdc, hPal, 0 );\n\tif( !select )\n\t\treturn false;\n\trealize = ::RealizePalette( hdc );\n\tif( realize == GDI_ERROR )\n\t\treturn false;\n\n\thBMP = ::CreateDIBitmap( hdc, &bitmapInfoHeader, CBM_INIT, lpvBits, lpHeaderMem, DIB_RGB_COLORS );\n\t::ReleaseDC( hWnd, hdc );\n\n\t// Unlock the global memory objects and close the .BMP file.  \n\t::GlobalUnlock( infoHeaderMem );\n\t::GlobalUnlock( hmem2 );\n\t::CloseHandle( hFile );\n \n\tif( !hBMP )\n\t\treturn false;\n \n\treturn true;\n}\n\n\nbit8 BMP8::drawBmp(void)\n{\n  // Paint the window (and draw the bitmap). \n \n  PAINTSTRUCT ps;\n  HDC         hdc;\n  char        string[128];\n\n  InvalidateRect(WindowHandle_,NULL,FALSE); // keep windows from screwing up the\n                                           //  redrawing (as much).\n  hdc=BeginPaint(WindowHandle_,&ps);\n\n  //Do palette stuff\n  HPALETTE select=SelectPalette(ps.hdc,PalHandle_,0);\n  if (select==NULL)\n  {\n    sprintf(string,\"Select Pal Fail: %d\",GetLastError());\n    MessageBox(NULL,string,\"OK\",MB_OK);\n  }\n  UINT realize=RealizePalette(ps.hdc);\n  if (realize==GDI_ERROR)\n  {\n    sprintf(string,\"Realize Pal Fail: %d\",GetLastError());\n    MessageBox(NULL,string,\"OK\",MB_OK);\n  }\n\n  HDC hdcMem = CreateCompatibleDC(ps.hdc); \n  SelectObject(hdcMem, BitmapHandle_); \n  BITMAP bm;\n  GetObject(BitmapHandle_, sizeof(BITMAP), (LPSTR) &bm);\n  \n  /// for non-stretching version\n  ///////BitBlt(ps.hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY); \n\n  RECT clientRect;\n  GetClientRect(WindowHandle_,&clientRect);\n  SetStretchBltMode(ps.hdc,COLORONCOLOR);\n  StretchBlt(ps.hdc,0,0,clientRect.right,clientRect.bottom,hdcMem,0,0,bm.bmWidth,\n    bm.bmHeight,SRCCOPY);\n\n\n  DeleteDC(hdcMem); \n  EndPaint(WindowHandle_,&ps);\n  return(TRUE);\n}\n"
  },
  {
    "path": "CODE/BMP8.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef BMP8_H\n#define BMP8_H\n\n//#include<stdlib.h>\n//#include<stdio.h>\n//#include \"wstypes.h\"\n//#include \"winblows.h\"\n\nclass BMP8\n{\npublic:\n\tBMP8() : hBMP( NULL ), hPal( NULL ), hWnd( NULL )\t{}\n\t~BMP8();\n\n\tbool\tInit( const char* szFile, HWND hWnd );\n\tbool\tDraw(void);  // call this from your WM_PAINT message\n\nprivate:\n\tHBITMAP\t\thBMP;\n\tHPALETTE\thPal;\n\tHWND\t\thWnd;\n};\n\n\n#endif"
  },
  {
    "path": "CODE/BUFF.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BUFF.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BUFF.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/29/96                                                     *\n *                                                                                             *\n *                  Last Update : September 7, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Buffer::Buffer -- Constructor for buffer object.                                          *\n *   Buffer::Buffer -- Copy constructor for buffer object.                                     *\n *   Buffer::Buffer -- Self-allocating constructor for buffer object.                          *\n *   Buffer::Reset -- Clears the buffer object to null state.                                  *\n *   Buffer::operator = -- Assignment operator for the buffer object.                          *\n *   Buffer::~Buffer -- Destructor for buffer object.                                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"buff.h\"\n#include\t<stddef.h>\n\n\n/***********************************************************************************************\n * Buffer::Buffer -- Constructor for buffer object.                                            *\n *                                                                                             *\n *    This is the normal constructor for a buffer object. The buffer pointer and size are      *\n *    specified as parameters.                                                                 *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer.                                                 *\n *                                                                                             *\n *          size     -- The size of the buffer.                                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   It is possible to construct a Buffer object that has a pointer but a size       *\n *             value of zero. The Buffer object can still be used for its pointer, but it      *\n *             any function that requires a size will fail.                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuffer::Buffer(void * buffer, long size) :\n\tBufferPtr(buffer),\n\tSize(size),\n\tIsAllocated(false)\n{\n}\n\n\n// Alternate constructor for char * pointer.\nBuffer::Buffer(char * buffer, long size) :\n\tBufferPtr(buffer),\n\tSize(size),\n\tIsAllocated(false)\n{\n}\n\n\n// Alternate constructor for void const * pointer.\nBuffer::Buffer(void const * buffer, long size) :\n\tBufferPtr((void*)buffer),\n\tSize(size),\n\tIsAllocated(false)\n{\n}\n\n\n/***********************************************************************************************\n * Buffer::Buffer -- Self-allocating constructor for buffer object.                            *\n *                                                                                             *\n *    This construtor for a buffer object will automatically allocate the bytes necessary      *\n *    to fulfill the size requested. This object is also responsible for deleting the buffer   *\n *    it allocated.                                                                            *\n *                                                                                             *\n * INPUT:   size  -- The size of the buffer to allocated.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   There is no way to tell if the allocation failed. To verify, call Get_Buffer    *\n *             and compare with NULL.                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuffer::Buffer(long size) :\n\tBufferPtr(NULL),\n\tSize(size),\n\tIsAllocated(false)\n{\n\tif (size > 0) {\n\t\tBufferPtr = new char[size];\n\t\tIsAllocated = true;\n\t}\n}\n\n\n/***********************************************************************************************\n * Buffer::Buffer -- Copy constructor for buffer object.                                       *\n *                                                                                             *\n *    This will make a duplicate of the specified buffer object. The ownership of the pointer  *\n *    remains with the original object. This prevents multiple deletion of the same pointer.   *\n *                                                                                             *\n * INPUT:   buffer   -- Reference to the buffer object to be dupilcated.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuffer::Buffer(Buffer const & buffer) :\n\tIsAllocated(false)\n{\n\tBufferPtr = buffer.BufferPtr;\n\tSize = buffer.Size;\n}\n\n\n/***********************************************************************************************\n * Buffer::operator = -- Assignment operator for the buffer object.                            *\n *                                                                                             *\n *    This will make a duplicate of the buffer object specified. Any buffer pointed to by the  *\n *    left hand buffer will be lost (possibley freed as a result).                             *\n *                                                                                             *\n * INPUT:   buffer   -- Reference to the right hand buffer object.                             *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the copied buffer object.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuffer & Buffer::operator = (Buffer const & buffer)\n{\n\tif (buffer != this) {\n\t\tif (IsAllocated) {\n\t\t\tdelete [] BufferPtr;\n\t\t}\n\t\tIsAllocated = false;\n\t\tBufferPtr = buffer.BufferPtr;\n\t\tSize = buffer.Size;\n\t}\n\treturn(*this);\n}\n\n\n/***********************************************************************************************\n * Buffer::~Buffer -- Destructor for buffer object.                                            *\n *                                                                                             *\n *    This destructor will free any buffer it is responsible for.                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuffer::~Buffer(void)\n{\n\tReset();\n}\n\n\n/***********************************************************************************************\n * Buffer::Reset -- Clears the buffer object to null state.                                    *\n *                                                                                             *\n *    This routine will bring the buffer object into a null (newly constructed) state. If      *\n *    there was any buffer allocated or referred to by this object, it will be freed or        *\n *    dereferenced as necessary.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine will free the buffer if it is responsible for doing so when        *\n *             it is no longer referenced.                                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/07/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Buffer::Reset(void)\n{\n\tif (IsAllocated) {\n\t\tdelete [] BufferPtr;\n\t}\n\tBufferPtr = NULL;\n\tSize = 0;\n\tIsAllocated = false;\n}\n"
  },
  {
    "path": "CODE/BUFF.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BUFF.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BUFF.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/29/96                                                     *\n *                                                                                             *\n *                  Last Update : July 29, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef CCBUFF_H\n#define CCBUFF_H\n\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n/*\n**\tA general purpose buffer pointer handler object. It holds not only the pointer to the\n**\tbuffer, but its size as well. By using this class instead of separate pointer and size\n**\tvalues, function interfaces and algorithms become simpler to manage and understand.\n*/\nclass Buffer {\n\tpublic:\n\t\tBuffer(char * ptr, long size=0);\n\t\tBuffer(void * ptr=0, long size=0);\n\t\tBuffer(void const * ptr, long size=0);\n\t\tBuffer(long size);\n\t\tBuffer(Buffer const & buffer);\n\t\t~Buffer(void);\n\n\t\tBuffer & operator = (Buffer const & buffer);\n\t\toperator void * (void) const {return(BufferPtr);}\n\t\toperator char * (void) const {return((char *)BufferPtr);}\n\n\t\tvoid Reset(void);\n\t\tvoid * Get_Buffer(void) const {return(BufferPtr);}\n\t\tlong Get_Size(void) const {return(Size);}\n\t\tbool Is_Valid(void) const {return(BufferPtr != 0);}\n\n\tprotected:\n\n\t\t/*\n\t\t**\tPointer to the buffer memory.\n\t\t*/\n\t\tvoid * BufferPtr;\n\n\t\t/*\n\t\t**\tThe size of the buffer memory.\n\t\t*/\n\t\tlong Size;\n\n\t\t/*\n\t\t**\tWas the buffer allocated by this class? If so, then this class\n\t\t**\twill be responsible for freeing the buffer.\n\t\t*/\n\t\tbool IsAllocated;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/BUFFERX.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BUFFERX.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BUFFER.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/04/96                                                     *\n *                                                                                             *\n *                  Last Update : May 4, 1996 [JLB]                                            *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef BUFFERx_H\n#define BUFFERx_H\n\n#include\t\"wwfile.h\"\n\n/*\n**\tThis is a transmuter interface designed to aid implementation of compression, encryption, or\n**\tdata analysis classes. The Transmuter should be derived into a class that performs the necessary\n**\tprocessing.\n*/\nclass Transmuter {\n\tpublic:\n\t\tTransmuter(void) : Output(0) {}\n\t\tvirtual ~Transmuter(void) {}\n\n\t\t/*\n\t\t**\tThese are the interface function that are used to pass data to the transmuter. The\n\t\t**\tdefault implementation of these functions do nothing other than pass the data onto\n\t\t**\tthe subsequent transmuter. For practical use, these functions should be overloaded to\n\t\t**\tdo something more useful.\n\t\t*/\n\t\tvirtual void Attach(Transmuter * transmuter) {Output = transmuter;}\n\t\tvirtual void Flush(void) {if (Output) Output->Flush();}\n\t\tvirtual void Put(const void * input, unsigned length) {if (Output) Output->Put(input, length);}\n\n\tprotected:\n\n\t\t/*\n\t\t**\tPointer to the output transmuter.\n\t\t*/\n\t\tTransmuter * Output;\n};\n\n\nclass FileTransmuter {\n\tpublic:\n\t\tFileTransmuter(FileClass * file = NULL) : OutputFile(file) {}\n\n\t\tvirtual void Attach(FileClass * file) {OutputFile = file;}\n\t\tvirtual void Flush(void) {}\n\t\tvirtual void Put(const void * input, unsigned length) {if (OutputFile) OutputFile->Write(input, length);}\n\n\tprotected:\n\t\tFileClass * OutputFile;\n};\n\n\nclass BufferTransmuter {\n\tpublic:\n\t\tBufferTransmuter(void * buffer = NULL) : BufferPtr(buffer) {}\n\n\t\tvirtual void Attach(void * buffer) {BufferPtr = buffer;}\n\t\tvirtual void Flush(void) {}\n\t\tvirtual void Put(const void * input, unsigned length) {if (BufferPtr) {memcpy(BufferPtr, input, length);((char *&)BufferPtr) += length;}}\n\n\tprotected:\n\t\tvoid * BufferPtr;\n};\n\n\n#endif\n\n\n"
  },
  {
    "path": "CODE/BUGS.TXT",
    "content": "Fixed:\nA415,A436,A437,A446,A447,A453,A466,A475,A488,\nB171,B326,B407,B443,B530,B550,B566,B578,B600,\nB609,B626,B628,B632,B637,B641,B644,B655,B658,\nB675,B678,B684,B685,B688,B690,B698,B711,B715,\nB726,B730,B731,B729,B732,B733,B738,B743,B744,\nB747,B748,B750,B753,B759,B762,B766,B767,B768,\nB770,B774,B775,B777,B778,B780,B781,B786,B795,\nB797,B798,B805,C1001,C1007,C1011,C1012,C1014,\nC1017,C1018,C1020,C1024,C1031,C1037,C1042,C1045,\nC1052,C1061,C1054,C288,C487,C543,C546,\nC666,C671,C697,C702,C773,C841,C856,C869,C871,\nC887,C888,C904,C919,C922,C923,C925,C926\nC927,C930,C932,C936,C938,C939,C942,C945,C947,\nC953,C954,C962,C966,C967,C968,C975,C976,C977\nC981,C982\n\nUnsolved:\nA035,A248,A352,A383,A417,A419,A420,A427,A445,A449,\nA450,A455,A456,A457,A469,A470,A477,A478,A480,B005,\nB042,B206,B207,B247,B284,B356,B418,B430,B467,B536,\nB548,B549,B559,B633,B674,B686,B703,B714,B725,B740,\nB745,B785,B787,B794,B796,B799,B802,B809,B817,B823,\nC033,C072,C1000,C1002,C1004,C1006,C1008,C1009,C1013,C1016,\nC1022,C1026,C1028,C1029,C1030,C1047,C1053,C1054,C1056,C1057,\nC1059,C197,C318,C407,C409,C453,C502,C527,C530,C551,\nC554,C573,C606,C676,C682,C694,C750,C776,C793,C811,\nC821,C834,C867,C872,C877,C881,C896,C898,C901,C921,\nC928,C929,C931,C933,C934,C940,C941,C943,C944,C946,\nC952,C961,C964,C965,C969,C971,C794,C987,C988,C992,\nC997\n\nOld / Need more info / non-repeatable (maybe it's fixed now?):\nA380,A388,A401,A414,A482,B445,B791,\nA342,A402,A413,A434,A443,A460,A461,A462,A463,A468,\nA472,A473,A476,A485,A489,A490,B1044,B513,B524,B608\nB721,B773,B789,B807,B812,C570,C633,C654,C744,C778,\nC853,C913,C963,C991,C998\n\nModem/Net Bug (for Bill):\nA431,A452,A454,A464,A471,A481,A483,A486,A487,\nB742,B760,B761,B764,B765,B772,B792,C1025,C1036,C1038\nC883,C886,C895,C950,C951,C956,C993,C995\n\nDesign Bug (for Erik):\nA432,A433,A448,A479,B041,B414,B659,B717,B719,B720,\nB722,B723,B727,B728,B735,B736,B737,B741,\nB756,B757,B758,B784,B802,B803,B808,B810,B815,\nB816,B818,B822,C1010,C1023,C1027,C1035,C1044,\nC1062,C534,C568,C637,C663,C918,C920,C924,C948,\nC949,C986,C996,C999\n\nSetup/Install/README.TXT Bug:\nA458,A467,A484,B395,C957,C958,C959\n\nNot Bug, repeated bug, suggestion, can't fix, or huh?:\nA459,B1024,B218,B507,B522,B541,B546,B592,B593,B596,\nB687,B724,B739,B746,B749,B763,B776,B779,B782,B783,\nB790,B793,B806,B819,B820,B821,C1003,C1005,C1015,C1019,\nC1032,C1033,C1034,C1039,C1040,C1043,C1048,\nC1050,C1051,C1055,C1058,C1060,C1063,C336,C377,\nC491,C537,C541,C578,C691,C703,C716,C781,C792,C838,\nC854,C860,C879,C912,C915,C935,C937,C955,C970,C978,\nC979,C980,C983,C984,C985,C990"
  },
  {
    "path": "CODE/BUILDING.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BUILDING.CPP 5     3/13/97 5:18p Joe_b $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BUILDING.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : October 27, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BuildingClass::AI -- Handles non-graphic AI processing for buildings.                     *\n *   BuildingClass::Active_Click_With -- Handles cell selection for buildings.                 *\n *   BuildingClass::Animation_AI -- Handles normal building animation processing.              *\n *   BuildingClass::Assign_Target -- Assigns a target to the building.                         *\n *   BuildingClass::Begin_Mode -- Begins an animation mode for the building.                   *\n *   BuildingClass::BuildingClass -- Constructor for buildings.                                *\n *   BuildingClass::Can_Demolish -- Can the player demolish (sell back) the building?          *\n *   BuildingClass::Can_Enter_Cell -- Determines if building can be placed down.               *\n *   BuildingClass::Can_Fire -- Determines if this building can fire.                          *\n *   BuildingClass::Can_Player_Move -- Can this building be moved?                             *\n *   BuildingClass::Captured -- Captures the building.                                         *\n *   BuildingClass::Center_Coord -- Fetches the center coordinate for the building.            *\n *   BuildingClass::Charging_AI -- Handles the special charging logic for Tesla coils.         *\n *   BuildingClass::Check_Point -- Fetches the landing checkpoint for the given flight pattern.*\n *   BuildingClass::Click_With -- Handles clicking on the map while the building is selected.  *\n *   BuildingClass::Crew_Type -- This determines the crew that this object generates.          *\n *   BuildingClass::Death_Announcement -- Announce the death of this building.                 *\n *   BuildingClass::Debug_Dump -- Displays building status to the monochrome screen.           *\n *   BuildingClass::Detach -- Handles target removal from the game system.                     *\n *   BuildingClass::Detach_All -- Possibly abandons production according to factory type.      *\n *   BuildingClass::Docking_Coord -- Fetches the coordinate to use for docking.                *\n *   BuildingClass::Draw_It -- Displays the building at the location specified.                *\n *   BuildingClass::Drop_Debris -- Drops rubble when building is destroyed.                    *\n *   BuildingClass::Enter_Idle_Mode -- The building will enter its idle mode.                  *\n *   BuildingClass::Exit_Coord -- Determines location where object will leave it.              *\n *   BuildingClass::Exit_Object -- Initiates an object to leave the building.                  *\n *   BuildingClass::Factory_AI -- Handle factory production and initiation.                    *\n *   BuildingClass::Find_Exit_Cell -- Find a clear location to exit an object from this buildin*\n *   BuildingClass::Fire_Direction -- Fetches the direction of firing.                         *\n *   BuildingClass::Fire_Out -- Handles when attached animation expires.                       *\n *   BuildingClass::Flush_For_Placement -- Handles clearing a zone for object placement.       *\n *   BuildingClass::Get_Image_Data -- Fetch the image pointer for the building.                *\n *   BuildingClass::Grand_Opening -- Handles construction completed special operations.        *\n *   BuildingClass::Greatest_Threat -- Searches for target that building can fire upon.        *\n *   BuildingClass::How_Many_Survivors -- This determine the maximum number of survivors.      *\n *   BuildingClass::Init -- Initialize the building system to an empty null state.             *\n *   BuildingClass::Limbo -- Handles power adjustment as building goes into limbo.             *\n *   BuildingClass::Mark -- Building interface to map rendering system.                        *\n *   BuildingClass::Mission_Attack -- Handles attack mission for building.                     *\n *   BuildingClass::Mission_Construction -- Handles mission construction.                      *\n *   BuildingClass::Mission_Deconstruction -- Handles building deconstruction.                 *\n *   BuildingClass::Mission_Guard -- Handles guard mission for combat buildings.               *\n *   BuildingClass::Mission_Harvest -- Handles refinery unloading harvesters.                  *\n *   BuildingClass::Mission_Missile -- State machine for nuclear missile launch.               *\n *   BuildingClass::Mission_Repair -- Handles the repair (active) state for building.          *\n *   BuildingClass::Mission_Unload -- Handles the unload mission for a building.               *\n *   BuildingClass::Pip_Count -- Determines \"full\" pips to display for building.               *\n *   BuildingClass::Power_Output -- Fetches the current power output from this building.       *\n *   BuildingClass::Read_INI -- Reads buildings from INI file.                                 *\n *   BuildingClass::Receive_Message -- Handle an incoming message to the building.             *\n *   BuildingClass::Remap_Table -- Fetches the remap table to use for this building.           *\n *   BuildingClass::Remove_Gap_Effect -- Stop a gap generator from jamming cells               *\n *   BuildingClass::Repair -- Initiates or terminates the repair process.                      *\n *   BuildingClass::Repair_AI -- Handle the repair (and sell) logic for the building.          *\n *   BuildingClass::Revealed -- Reveals the building to the specified house.                   *\n *   BuildingClass::Rotation_AI -- Process any turret rotation required of this building.      *\n *   BuildingClass::Sell_Back -- Controls the sell back (demolish) operation.                  *\n *   BuildingClass::Shape_Number -- Fetch the shape number for this building.                  *\n *   BuildingClass::Sort_Y -- Returns the building coordinate used for sorting.                *\n *   BuildingClass::Take_Damage -- Inflicts damage points upon a building.                     *\n *   BuildingClass::Target_Coord -- Return the coordinate to use when firing on this building. *\n *   BuildingClass::Toggle_Primary -- Toggles the primary factory state.                       *\n *   BuildingClass::Turret_Facing -- Fetches the turret facing for this building.              *\n *   BuildingClass::Unlimbo -- Removes a building from limbo state.                            *\n *   BuildingClass::Update_Buildables -- Informs sidebar of additional construction options.   *\n *   BuildingClass::Value -- Determine the value of this building.                             *\n *   BuildingClass::What_Action -- Determines action to perform if click on specified object.  *\n *   BuildingClass::What_Action -- Determines what action will occur.                          *\n *   BuildingClass::Write_INI -- Write out the building data to the INI file specified.        *\n *   BuildingClass::delete -- Deallocates building object.                                     *\n *   BuildingClass::new -- Allocates a building object from building pool.                     *\n *   BuildingClass::~BuildingClass -- Destructor for building type objects.                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\nenum SAMState {\n\tSAM_READY,\t\t\t\t\t// Launcher can be facing any direction tracking targets.\n\tSAM_FIRING\t\t\t\t\t// Stationary while missile is being fired.\n};\n\n\n/***************************************************************************\n**\tCenter of building offset table.\n*/\nCOORDINATE const BuildingClass::CenterOffset[BSIZE_COUNT] = {\n\t0x00800080L,\n\t0x008000FFL,\n\t0x00FF0080L,\n\t0x00FF00FFL,\n\t0x018000FFL,\n\t0x00FF0180L,\n\t0x01800180L,\n\n\t0x00FF0200L,\n\n\t0x02800280L,\n};\n\n\n/***********************************************************************************************\n * BuildingClass::Receive_Message -- Handle an incoming message to the building.               *\n *                                                                                             *\n *    This routine handles an incoming message to the building. Messages regulate the          *\n *    various cooperative ventures between buildings and units. This might include such        *\n *    actions as coordinating the construction yard animation with the actual building's       *\n *    construction animation.                                                                  *\n *                                                                                             *\n * INPUT:   from     -- The originator of the message received.                                *\n *                                                                                             *\n *          message  -- The radio message received.                                            *\n *                                                                                             *\n *          param    -- Reference to an optional parameter that might be used to return        *\n *                      extra information to the message originator.                           *\n *                                                                                             *\n * OUTPUT:  Returns with the response to the message (typically, this is just RADIO_OK).       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/09/1994 JLB : Created.                                                                 *\n *   06/26/1995 JLB : Forces refinery load anim to start immediately.                          *\n *   08/13/1995 JLB : Uses ScenarioInit for special loose \"CAN_LOAD\" check.                    *\n *=============================================================================================*/\nRadioMessageType BuildingClass::Receive_Message(RadioClass * from, RadioMessageType message, long & param)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tswitch (message) {\n\n\t\t/*\n\t\t**\tThis message is received as a request to attach/load/dock with this building.\n\t\t**\tVerify that this is allowed and return the appropriate response.\n\t\t*/\n\t\tcase RADIO_CAN_LOAD:\n\t\t\tTechnoClass::Receive_Message(from, message, param);\n\t\t\tif (!House->Is_Ally(from)) return(RADIO_STATIC);\n\t\t\tif (Mission == MISSION_CONSTRUCTION || Mission == MISSION_DECONSTRUCTION || BState == BSTATE_CONSTRUCTION || (!ScenarioInit && In_Radio_Contact() && Contact_With_Whom() != from)) return(RADIO_NEGATIVE);\n\t\t\tswitch (Class->Type) {\n\t\t\t\tcase STRUCT_AIRSTRIP:\n\t\t\t\t\tif (from->What_Am_I() == RTTI_AIRCRAFT && ((AircraftClass const *)from)->Class->IsFixedWing) {\n\t\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_HELIPAD:\n\t\t\t\t\tif (from->What_Am_I() == RTTI_AIRCRAFT && !((AircraftClass const *)from)->Class->IsFixedWing) {\n\t\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_REPAIR:\n\t\t\t\t\tif (from->What_Am_I() == RTTI_UNIT || (from->What_Am_I() == RTTI_AIRCRAFT)) {\n\t\t\t\t\t\tif (Transmit_Message(RADIO_ON_DEPOT, from) != RADIO_ROGER) {\n\t\t\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn(RADIO_NEGATIVE);\n\n\t\t\t\tcase STRUCT_REFINERY:\n\t\t\t\t\tif (from->What_Am_I() == RTTI_UNIT &&\n\t\t\t\t\t\t*((UnitClass *)from) == UNIT_HARVESTER &&\n\t\t\t\t\t\t(ScenarioInit || !Is_Something_Attached())) {\n\n\t\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\treturn(RADIO_STATIC);\n\n\t\t/*\n\t\t**\tThis message is received when the object has attached itself to this\n\t\t**\tbuilding.\n\t\t*/\n\t\tcase RADIO_IM_IN:\n\t\t\tif (Mission == MISSION_DECONSTRUCTION) {\n\t\t\t\treturn(RADIO_NEGATIVE);\n\t\t\t}\n\t\t\tswitch (Class->Type) {\n\t\t\t\tcase STRUCT_REPAIR:\n\t\t\t\t\tIsReadyToCommence = true;\n\t\t\t\t\tAssign_Mission(MISSION_REPAIR);\n\t\t\t\t\tfrom->Assign_Mission(MISSION_SLEEP);\n\t\t\t\t\treturn(RADIO_ROGER);\n\n\t\t\t\tcase STRUCT_AIRSTRIP:\n\t\t\t\tcase STRUCT_HELIPAD:\n\t\t\t\t\tAssign_Mission(MISSION_REPAIR);\n\t\t\t\t\tfrom->Assign_Mission(MISSION_SLEEP);\n\t\t\t\t\treturn(RADIO_ROGER);\n\n\t\t\t\tcase STRUCT_REFINERY:\n\t\t\t\t\tMark(MARK_CHANGE);\n\t\t\t\t\tfrom->Assign_Mission(MISSION_UNLOAD);\n\t\t\t\t\treturn(RADIO_ROGER);\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tDocking maneuver maintenance message. See if new order should be given to the\n\t\t**\tunit trying to dock.\n\t\t*/\n\t\tcase RADIO_DOCKING:\n\t\t\tTechnoClass::Receive_Message(from, message, param);\n\n\t\t\t/*\n\t\t\t**\tWhen in radio contact for loading, the refinery starts\n\t\t\t**\tflashing the lights.\n\t\t\t*/\n\t\t\tif (*this == STRUCT_REFINERY && BState != BSTATE_FULL) {\n\t\t\t\tBegin_Mode(BSTATE_FULL);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf this building is already in radio contact, then it might\n\t\t\t**\tbe able to satisfy the request to load by bumping off any\n\t\t\t**\tpreoccupying task.\n\t\t\t*/\n\t\t\tif (*this == STRUCT_REPAIR) {\n\t\t\t\tif (Contact_With_Whom() != from) {\n\t\t\t\t\tif (Transmit_Message(RADIO_ON_DEPOT) == RADIO_ROGER) {\n\t\t\t\t\t\tif (Transmit_Message(RADIO_NEED_REPAIR) == RADIO_NEGATIVE) {\n\t\t\t\t\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n\t\t\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t\t\t}\n//\t\t\t\t\t} else {\n//\t\t\t\t\t\tif (Transmit_Message(RADIO_NEED_TO_MOVE, from) == RADIO_ROGER) {\n//\t\t\t\t\t\t\tparam = (long)As_Target();\n//\t\t\t\t\t\t\tTransmit_Message(RADIO_MOVE_HERE, param, from);\n//\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (Transmit_Message(RADIO_NEED_REPAIR) == RADIO_NEGATIVE) {\n\t\t\t\t\t\treturn(RADIO_NEGATIVE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tEstablish contact with the object if this building isn't already in contact\n\t\t\t**\twith another.\n\t\t\t*/\n\t\t\tif (!In_Radio_Contact()) {\n\t\t\t\tTransmit_Message(RADIO_HELLO, from);\n\t\t\t}\n\n\t\t\tif (Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {\n\t\t\t\tswitch (Class->Type) {\n\t\t\t\t\tcase STRUCT_AIRSTRIP:\n\t\t\t\t\t\tparam = As_Target();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRUCT_HELIPAD:\n\t\t\t\t\t\tparam = As_Target();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRUCT_REPAIR:\n\t\t\t\t\t\tTransmit_Message(RADIO_TETHER);\n\t\t\t\t\t\tparam = ::As_Target(Coord_Cell(Center_Coord()));\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRUCT_REFINERY:\n\t\t\t\t\t\tparam = ::As_Target(Coord_Cell(Adjacent_Cell(Center_Coord(), DIR_S)));\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tTell the harvester to move to the docking pad of the building.\n\t\t\t\t*/\n\t\t\t\tif (Transmit_Message(RADIO_MOVE_HERE, param) == RADIO_YEA_NOW_WHAT) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSince the harvester is already there, tell it to begin the backup\n\t\t\t\t\t**\tprocedure now. If it can't, then tell it to get outta here.\n\t\t\t\t\t*/\n\t\t\t\t\tTransmit_Message(RADIO_TETHER);\n\t\t\t\t\tif (*this == STRUCT_REFINERY && Transmit_Message(RADIO_BACKUP_NOW, from) != RADIO_ROGER) {\n\t\t\t\t\t\tfrom->Scatter(NULL, true, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t**\tIf a transport or harvester is requesting permission to head toward, dock\n\t\t**\tand load/unload, check to make sure that this is allowed given the current\n\t\t**\tstate of the building.\n\t\t*/\n\t\tcase RADIO_ARE_REFINERY:\n\t\t\tif (Is_Something_Attached() || In_Radio_Contact() || IsInLimbo || House->Class->House != from->Owner() || (*this != STRUCT_REFINERY/* && *this != STRUCT_REPAIR*/)) {\n\t\t\t\treturn(RADIO_NEGATIVE);\n\t\t\t}\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t**\tSomeone is telling us that it is starting construction. This should only\n\t\t**\toccur if this is a construction yard and a building was just placed on\n\t\t**\tthe map.\n\t\t*/\n\t\tcase RADIO_BUILDING:\n\t\t\tAssign_Mission(MISSION_REPAIR);\n\t\t\tTechnoClass::Receive_Message(from, message, param);\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t**\tSomeone is telling us that they have finished construction. This should\n\t\t**\tonly occur if this is a construction yard and the building that was being\n\t\t**\tconstructed has finished. In this case, stop the construction yard\n\t\t**\tanimation.\n\t\t*/\n\t\tcase RADIO_COMPLETE:\n\t\t\tif (Mission != MISSION_DECONSTRUCTION) {\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t}\n\t\t\tTechnoClass::Receive_Message(from, message, param);\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t**\tThis message may occur unexpectedly if the unit in contact with this\n\t\t**\tbuilding is suddenly destroyed. Handle any cleanup necessary. For example,\n\t\t**\ta construction yard should stop its construction animation in this case.\n\t\t*/\n\t\tcase RADIO_OVER_OUT:\n\t\t\tBegin_Mode(BSTATE_IDLE);\n\t\t\tTechnoClass::Receive_Message(from, message, param);\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t**\tThis message is received when an object has completely left\n\t\t** building. Sometimes special cleanup action is required when\n\t\t**\tthis event occurs.\n\t\t*/\n\t\tcase RADIO_UNLOADED:\n\t\t\tif (*this == STRUCT_REPAIR) {\n\t\t\t\tif (Distance(from) < 0x0180) {\n\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t}\n\t\t\t}\n\t\t\tTechnoClass::Receive_Message(from, message, param);\n\t\t\tif (*this == STRUCT_WEAP || *this == STRUCT_AIRSTRIP || *this == STRUCT_REPAIR) return(RADIO_RUN_AWAY);\n\t\t\treturn(RADIO_ROGER);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tPass along the message to the default message handler in the radio itself.\n\t*/\n\treturn(TechnoClass::Receive_Message(from, message, param));\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * BuildingClass::Debug_Dump -- Displays building status to the monochrome screen.             *\n *                                                                                             *\n *    This utility function will output the current status of the building class to the        *\n *    monochrome screen. It is through this data that bugs may be fixed or detected.           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tmono->Set_Cursor(0, 0);\n\tmono->Print(Text_String(TXT_DEBUG_BUILDING));\n\tmono->Fill_Attrib(66, 13, 12, 1, IsRepairing ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 14, 12, 1, IsToRebuild ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 15, 12, 1, IsAllowedToSell ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 16, 12, 1, IsCharging ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 17, 12, 1, IsCharged ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 18, 12, 1, IsJamming ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 19, 12, 1, IsJammed ? MonoClass::INVERSE : MonoClass::NORMAL);\n\n\tmono->Set_Cursor(1, 11);\n\tif (Factory) {\n\t\tmono->Printf(\"%s %d%%\", Factory->Get_Object()->Class_Of().IniName, (100*Factory->Completion())/FactoryClass::STEP_COUNT);\n\t}\n\n\tTechnoClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * BuildingClass::Draw_It -- Displays the building at the location specified.                  *\n *                                                                                             *\n *    This is the low level graphic routine that displays the building at the location         *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   x,y   -- The coordinate to draw the building at.                                   *\n *                                                                                             *\n *          window   -- The clipping window to use.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1994 JLB : Created.                                                                 *\n *   06/27/1994 JLB : Takes a clipping window parameter.                                       *\n *   07/06/1995 JLB : Handles damaged silos correctly.                                         *\n *=============================================================================================*/\nvoid BuildingClass::Draw_It(int x, int y, WindowNumberType window) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tThe shape file to use for rendering depends on whether the building\n\t**\tis undergoing construction or not.\n\t*/\n\tvoid const * shapefile = Get_Image_Data();\n\tif (shapefile == NULL) return;\n\n\t/*\n\t**\tActually draw the building shape.\n\t*/\n\tIsTheaterShape = Class->IsTheater;\t//Let Build_Frame know if this is a theater specific shape\n\tTechno_Draw_Object(shapefile, Shape_Number(), x, y, window);\n\tIsTheaterShape = false;\n\n\t/*\n\t** Patch for adding overlay onto weapon factory.  Only add the overlay if\n\t** the building has more than 1 hp.  Also, if the building's in radio\n\t** contact, he must be unloading a constructed vehicle, so draw that\n\t** vehicle before drawing the overlay.\n\t*/\n\tif (BState != BSTATE_CONSTRUCTION) {\n\n\t\t/*\n\t\t**\tA Tethered object is always rendered AFTER the building.\n\t\t*/\n\t\tif (IsTethered && In_Radio_Contact() && !Contact_With_Whom()->IsInLimbo && Contact_With_Whom()->What_Am_I() != RTTI_BUILDING) {\n\t\t\tTechnoClass * contact = Contact_With_Whom();\n\n\t\t\tassert(contact->IsActive);\n\t\t\tint xxx = x + ((int)Lepton_To_Pixel((int)Coord_X(contact->Render_Coord())) - (int)Lepton_To_Pixel((int)Coord_X(Render_Coord())));\n\t\t\tint yyy = y + ((int)Lepton_To_Pixel((int)Coord_Y(contact->Render_Coord())) - (int)Lepton_To_Pixel((int)Coord_Y(Render_Coord())));\n\t\t\tcontact->Draw_It(xxx, yyy, window);\n\t\t\tcontact->IsToDisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tDraw the weapon factory custom overlay graphic.\n\t\t*/\n\t\tif ( (*this == STRUCT_WEAP || *this == STRUCT_FAKEWEAP)) {\n\t\t\tint shapenum = Door_Stage();\n\t\t\tif (Health_Ratio() <= Rule.ConditionYellow) shapenum += 4;\n\t\t\tTechno_Draw_Object(Class->WarFactoryOverlay, shapenum, x, y, window);\n\t\t}\n\n\t\t/*\n\t\t**\tDraw any repair feedback graphic required.\n\t\t*/\n\t\tif (IsRepairing && IsWrenchVisible) {\n\t\t\tCC_Draw_Shape(ObjectTypeClass::SelectShapes, SELECT_WRENCH, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL);\n\t\t}\n\t}\n\n\tTechnoClass::Draw_It(x, y, window);\n\n\t/*\n\t** If this is a factory that we're spying on, show what it's producing\n\t*/\n\tif (SpiedBy & (1<<(PlayerPtr->Class->House)) && IsSelected) {\n\n\t\t/*\n\t\t**\tFetch the factory that is associate with this building. For computer controlled buildings, the\n\t\t**\tfactory pointer is integral to the building itself. For human controlled buildings, the factory\n\t\t**\tpointer is part of the house structure and must be retrieved from there.\n\t\t*/\n\t\tFactoryClass * factory = NULL;\n\t\tif (House->IsHuman) {\n\t\t\tfactory = House->Fetch_Factory(Class->ToBuild);\n\t\t} else {\n\t\t\tfactory = Factory;\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is a factory associated with this building, then fetch any attached\n\t\t**\tobject under production and display its cameo image over the top of this building.\n\t\t*/\n\t\tif (factory != NULL) {\n\t\t\tTechnoClass * obj = factory->Get_Object();\n\t\t\tif (obj != NULL) {\n#ifdef FIXIT_CSII\n\t\t\t\tCC_Draw_Shape(obj->Techno_Type_Class()->Get_Cameo_Data(), 0, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_NORMAL, NULL);\n#else\n\t\t\t\tvoid const * remapper = obj->House->Remap_Table(false, obj->Techno_Type_Class()->Remap);\n\t\t\t\tCC_Draw_Shape(obj->Techno_Type_Class()->Get_Cameo_Data(), 0, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL | ((remapper != NULL) ? SHAPE_FADING : SHAPE_NORMAL), remapper);\n#endif\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Shape_Number -- Fetch the shape number for this building.                    *\n *                                                                                             *\n *    This routine will examine the current state of the building and return with the shape    *\n *    number to use. The shape number is subordinate to the building graphic image data.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the shape number to use when rendering this building.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::Shape_Number(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tint shapenum = Fetch_Stage();\n\n\t/*\n\t**\tThe shape file to use for rendering depends on whether the building\n\t**\tis undergoing construction or not.\n\t*/\n\tif (BState == BSTATE_CONSTRUCTION) {\n\n\t\t/*\n\t\t**\tIf the building is deconstructing, then the display frame progresses\n\t\t**\tfrom the end to the beginning. Reverse the shape number accordingly.\n\t\t*/\n\t\tif (Mission == MISSION_DECONSTRUCTION) {\n\t\t\tshapenum = (Class->Anims[BState].Start+Class->Anims[BState].Count-1)-shapenum;\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tIf this is a camouflaged pill box and it is not owned by the player, then\n\t\t**\tit is displayed with the MEGA-camouflaged imagery.\n\t\t*/\n\t\tif ((!IsOwnedByPlayer) && (*this == STRUCT_CAMOPILLBOX)) {\n\t\t\tshapenum += 1;\n\t\t}\n\n\t\t/*\n\t\t**\tThe Tesla Coil has a stage value that can be overridden by\n\t\t**\tits current state.\n\t\t*/\n\t\tif (*this == STRUCT_TESLA) {\n\t\t\tif (IsCharged) {\n\t\t\t\tshapenum = 3;\n\t\t\t} else {\n\t\t\t\tif (IsCharging) {\n\t\t\t\t\tshapenum = Fetch_Stage();\n\t\t\t\t} else {\n\t\t\t\t\tshapenum = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tBuildings that contain a turret handle their shape determination\n\t\t**\tdifferently than normal buildings. They need to take into consideration\n\t\t**\tthe direction the turret is facing.\n\t\t*/\n\t\tif (Class->IsTurretEquipped) {\n\t\t\tshapenum = UnitClass::BodyShape[Dir_To_32(PrimaryFacing.Current())];\n\n\t\t\tif (*this == STRUCT_SAM) {\n\n\t\t\t\t/*\n\t\t\t\t**\tSAM sites that are free to rotate fetch their animation frame\n\t\t\t\t**\tfrom the building's turret facing. All other animation stages\n\t\t\t\t**\tfetch their frame from the embedded animation sequencer.\n\t\t\t\t*/\n//\t\t\t\tif (Status == SAM_READY || Status == SAM_FIRING || Status == SAM_LOCKING) {\n//\t\t\t\t\tshapenum = Fetch_Stage();\n//\t\t\t\t}\n\t\t\t\tif (Health_Ratio() <= Rule.ConditionYellow) {\n\t\t\t\t\tshapenum += 35;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (IsInRecoilState) {\n\t\t\t\t\tshapenum += 32;\n\t\t\t\t}\n\t\t\t\tif (Health_Ratio() <= Rule.ConditionYellow) {\n\t\t\t\t\tshapenum += 64;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf it is a significantly damaged weapons factory, it is shown in\n\t\t\t**\tthe worst state possible.\n\t\t\t*/\n\t\t\tif (*this == STRUCT_WEAP || *this == STRUCT_FAKEWEAP) {\n\t\t\t\tshapenum = 0;\n\t\t\t\tif (Health_Ratio() <= Rule.ConditionYellow) {\n\t\t\t\t\tshapenum = 1;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tSpecial render stage for silos. The stage is dependent on the current\n\t\t\t\t**\tTiberium collected as it relates to Tiberium capacity.\n\t\t\t\t*/\n\t\t\t\tif (*this == STRUCT_STORAGE) {\n\n\t\t\t\t\tint level = 0;\n\t\t\t\t\tif (House->Capacity) {\n\t\t\t\t\t\tlevel = (House->Tiberium * 5) / House->Capacity;\n\t\t\t\t\t}\n\n\t\t\t\t\tshapenum += Bound(level, 0, 4);\n\t\t\t\t\tif (Health_Ratio() <= Rule.ConditionYellow) {\n\t\t\t\t\t\tshapenum += 5;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf below half strenth, then show the damage frames of the\n\t\t\t\t\t**\tbuilding.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Health_Ratio() <= Rule.ConditionYellow) {\n\t\t\t\t\t\tint last1 = Class->Anims[BSTATE_IDLE].Start + Class->Anims[BSTATE_IDLE].Count;\n\t\t\t\t\t\tint last2 = Class->Anims[BSTATE_ACTIVE].Start + Class->Anims[BSTATE_ACTIVE].Count;\n\t\t\t\t\t\tint largest = max(last1, last2);\n\t\t\t\t\t\tlast2 = Class->Anims[BSTATE_AUX1].Start + Class->Anims[BSTATE_AUX1].Count;\n\t\t\t\t\t\tlargest = max(largest, last2);\n\t\t\t\t\t\tlast2 = Class->Anims[BSTATE_AUX2].Start + Class->Anims[BSTATE_AUX2].Count;\n\t\t\t\t\t\tlargest = max(largest, last2);\n\t\t\t\t\t\tshapenum += largest;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(shapenum);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mark -- Building interface to map rendering system.                          *\n *                                                                                             *\n *    This routine is used to mark the map cells so that when it renders                       *\n *    the underlying icons will also be updated as necessary.                                  *\n *                                                                                             *\n * INPUT:   mark  -- Type of image change (MARK_UP, _DOWN, _CHANGE)                            *\n *             MARK_UP  -- Building is removed.                                                *\n *             MARK_CHANGE -- Building changes shape.                                          *\n *             MARK_DOWN -- Building is added.                                                 *\n *                                                                                             *\n * OUTPUT:  bool; Did the mark operation succeed? Failure could be the result of marking down  *\n *                when the building is already marked down, or visa versa.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/31/1994 JLB : Created.                                                                 *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *   04/16/1994 JLB : Added health bar tracking.                                               *\n *   12/23/1994 JLB : Calls low level check before proceeding.                                 *\n *   01/27/1995 JLB : Special road spacer template added.                                      *\n *=============================================================================================*/\nbool BuildingClass::Mark(MarkType mark)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (TechnoClass::Mark(mark)) {\n\t\tshort const * offset = Overlap_List();\n\t\tshort const * occupy = Occupy_List();\n\t\tCELL cell = Coord_Cell(Coord);\n\t\tSmudgeType bib;\n\n\t\tswitch (mark) {\n\t\t\tcase MARK_UP:\n\t\t\t\tMap.Pick_Up(cell, this);\n\t\t\t\tif (Class->Bib_And_Offset(bib, cell)) {\n\t\t\t\t\tSmudgeClass * smudge = new SmudgeClass(bib);\n\t\t\t\t\tif (smudge != NULL) {\n\t\t\t\t\t\tsmudge->Disown(cell);\n\t\t\t\t\t\tdelete smudge;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase MARK_DOWN:\n\n\t\t\t\t/*\n\t\t\t\t**\tSpecial wall logic is handled here. A building that is really a wall\n\t\t\t\t**\tgets converted into an overlay wall type when it is placed down. The\n\t\t\t\t**\tactual building object itself is destroyed.\n\t\t\t\t*/\n\t\t\t\tif (Class->IsWall) {\n\t\t\t\t\tswitch (Class->Type) {\n\t\t\t\t\t\tcase STRUCT_BRICK_WALL:\n\t\t\t\t\t\t\tnew OverlayClass(OVERLAY_BRICK_WALL, cell, House->Class->House);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase STRUCT_BARBWIRE_WALL:\n\t\t\t\t\t\t\tnew OverlayClass(OVERLAY_BARBWIRE_WALL, cell, House->Class->House);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase STRUCT_SANDBAG_WALL:\n\t\t\t\t\t\t\tnew OverlayClass(OVERLAY_SANDBAG_WALL, cell, House->Class->House);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase STRUCT_WOOD_WALL:\n\t\t\t\t\t\t\tnew OverlayClass(OVERLAY_WOOD_WALL, cell, House->Class->House);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase STRUCT_CYCLONE_WALL:\n\t\t\t\t\t\t\tnew OverlayClass(OVERLAY_CYCLONE_WALL, cell, House->Class->House);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase STRUCT_FENCE:\n\t\t\t\t\t\t\tnew OverlayClass(OVERLAY_FENCE, cell, House->Class->House);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\tdelete this;\n\n\t\t\t\t} else {\n\t\t\t\t\tif (Can_Enter_Cell(cell) == MOVE_OK) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDetermine if a bib is required for this building. If one is, then\n\t\t\t\t\t\t**\tcreate and place it.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tCELL newcell = cell;\n\t\t\t\t\t\tif (Class->Bib_And_Offset(bib, newcell)) {\n\t\t\t\t\t\t\tnew SmudgeClass(bib, Cell_Coord(newcell), Class->IsBase ? House->Class->House : HOUSE_NONE);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tMap.Place_Down(cell, this);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn(false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase MARK_CHANGE_REDRAW:\n\t\t\t\tMap.Refresh_Cells(cell, Overlap_List(true));\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tMap.Refresh_Cells(cell, Overlap_List(false));\n\t\t\t\tMap.Refresh_Cells(cell, occupy);\n\t\t\t\tbreak;\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::AI -- Handles non-graphic AI processing for buildings.                       *\n *                                                                                             *\n *    This function is to handle the AI logic for the building. The graphic logic (facing,     *\n *    firing, and animation) is handled elsewhere.                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   12/26/1994 JLB : Handles production.                                                      *\n *   06/11/1995 JLB : Revamped.                                                                *\n *=============================================================================================*/\nvoid BuildingClass::AI(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tProcess building animation state changes. Transition to a following state\n\t**\tif there is one specified and the current animation sequence has expired.\n\t**\tThis process must occur before mission AI since the mission AI relies on\n\t**\tthe bstate change to occur immediately before the MissionClass::AI.\n\t*/\n\tAnimation_AI();\n\n\t/*\n\t**\tIf now is a good time to act on a new mission, then do so. This process occurs\n\t**\there because some outside event may have requested a mission change for the building.\n\t**\tSuch outside requests (player input) must be initiated BEFORE the normal AI process.\n\t*/\n\tif (IsReadyToCommence && BState != BSTATE_CONSTRUCTION) {\n\n\t\t/*\n\t\t**\tClear the commencement flag ONLY if something actually occurred. By acting\n\t\t**\tthis way, a building can set the IsReadyToCommence flag before it goes\n\t\t**\tto \"sleep\" knowing that it will wake up as soon as a new mission comes\n\t\t**\talong.\n\t\t*/\n\t\tif (Commence()) {\n\t\t\tIsReadyToCommence = false;\n\t\t}\n\t}\n\n\t/*\n\t**\tProceed with normal logic processing. This is where the mission processing\n\t**\toccurs. This call must be located after the animation sequence makes the\n\t**\ttransition to the next frame (see above) in order for the mission logic to\n\t**\tact at the exact moment of graphic transition BEFORE it has a chance to\n\t**\tbe displayed.\n\t*/\n\tTechnoClass::AI();\n\n\t/*\n\t**\tBail if the object died in the AI routine.\n\t*/\n\tif (!IsActive) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tBuilding ammo is instantly reloaded.\n\t*/\n\tif (!Ammo) {\n\t\tAmmo = Class->MaxAmmo;\n\t}\n\n\t/*\n\t**\tIf now is a good time to act on a new mission, then do so. This occurs here because\n\t**\tsome AI event may have requested a mission change (usually from another mission\n\t**\tstate machine). This must occur here before it has a chance to render.\n\t*/\n\tif (IsReadyToCommence) {\n\n\t\t/*\n\t\t**\tClear the commencement flag ONLY if something actually occurred. By acting\n\t\t**\tthis way, a building can set the IsReadyToCommence flag before it goes\n\t\t**\tto \"sleep\" knowing that it will wake up as soon as a new mission comes\n\t\t**\talong.\n\t\t*/\n\t\tif (Commence()) {\n\t\t\tIsReadyToCommence = false;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf a change of animation was requested, then make the change\n\t**\tnow. The building animation system acts independently but subordinate\n\t**\tto the mission state machine system. By performing the animation change-up\n\t**\there, the mission AI system is ensured of immediate visual affect when it\n\t**\tdecides to change the animation state of the building.\n\t*/\n\tif (QueueBState != BSTATE_NONE) {\n\t\tif (BState != QueueBState) {\n\t\t\tBState = QueueBState;\n\t\t\tBuildingTypeClass::AnimControlType const * ctrl = Fetch_Anim_Control();\n\t\t\tif (BState == BSTATE_CONSTRUCTION || BState == BSTATE_IDLE) {\n\t\t\t\tSet_Rate(Options.Normalize_Delay(ctrl->Rate));\n\t\t\t} else {\n\t\t\t\tSet_Rate(ctrl->Rate);\n\t\t\t}\n\t\t\tSet_Stage(ctrl->Start);\n\t\t}\n\t\tQueueBState = BSTATE_NONE;\n\t}\n\n\t/*\n\t**\tIf the building's strength has changed, then update the power\n\t**\taccordingly.\n\t*/\n\tif (Strength != LastStrength) {\n\t\tint oldpower = Power_Output();\n\t\tLastStrength = Strength;\n\t\tint newpower = Power_Output();\n\t\tHouse->Adjust_Power(newpower - oldpower);\n\t}\n\n\t/*\n\t**\tCheck to see if the destruction countdown timer is active. If so, then decrement it.\n\t**\tWhen this timer reaches zero, the building is removed from the map. All the explosions\n\t**\tare presumed to be in progress at this time.\n\t*/\n\tif (Strength == 0) {\n\t\tif (CountDown == 0) {\n\t\t\tLimbo();\n\t\t\tDrop_Debris(WhomToRepay);\n\t\t\tdelete this;\n\t\t}\n\t\treturn;\n\t}\n\n\t/*\n\t**\tCharging logic.\n\t*/\n\tCharging_AI();\n\n\t/*\n\t**\tHandle any repair process that may be going on.\n\t*/\n\tRepair_AI();\n\n\t/*\n\t**\tFor computer controlled buildings, determine what should be produced and start\n\t**\tproduction accordingly.\n\t*/\n\tFactory_AI();\n\n\t/*\n\t**\tCheck for demolition timeout. When timeout has expired, the building explodes.\n\t*/\n\tif (IsGoingToBlow && CountDown == 0) {\n\t\tint damage = Strength;\n\t\tTake_Damage(damage, 0, WARHEAD_FIRE, As_Techno(WhomToRepay), true);\n\t\tif (!IsActive) {\n\t\t\treturn;\n\t\t}\n\t\tMark(MARK_CHANGE);\n\t}\n\n\t/*\n\t**\tTurret equiped buildings must handle turret rotation logic here. This entails\n\t**\trotating the turret to the desired facing as well as figuring out what that\n\t**\tdesired facing should be.\n\t*/\n\tRotation_AI();\n\n\t/*\n\t** Gap Generators need to scan if they've just become activated, or if\n\t** the power has just come on enough so they can scan.  Also, they need\n\t** to un-jam if the power has just dropped off.\n\t*/\n\tif (*this == STRUCT_GAP) {\n\t\tif (Arm == 0) {\n\t\t\tIsJamming = false;\n\t\t\tArm = TICKS_PER_MINUTE * Rule.GapRegenInterval + Random_Pick(1, TICKS_PER_SECOND);\n\t\t}\n\n\t\tif (!IsJamming) {\n\t\t\tif (House->Power_Fraction() >= 1) {\n\t\t\t\tMap.Jam_From(Coord_Cell(Center_Coord()), Rule.GapShroudRadius, House);\n\t\t\t\tIsJamming = true;\n\t\t\t}\n\t\t} else {\n\t\t\tif (House->Power_Fraction() < 1) {\n\t\t\t\tIsJamming = false;\n\t\t\t\tMap.UnJam_From(Coord_Cell(Center_Coord()), Rule.GapShroudRadius, House);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Radar facilities and SAMs need to check for the proximity of a mobile\n\t** radar jammer.\n\t*/\n\tif ((*this == STRUCT_RADAR || *this == STRUCT_SAM) && (Frame % TICKS_PER_SECOND) == 0) {\n\t\tIsJammed = false;\n\t\tfor (int index = 0; index < Units.Count(); index++) {\n\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\tif (obj != NULL &&\n\t\t\t\t\t!obj->IsInLimbo &&\n\t\t\t\t\t!obj->House->Is_Ally(House) &&\n\t\t\t\t\tobj->Class->IsJammer &&\n\t\t\t\t\tDistance(obj) <= Rule.RadarJamRadius) {\n\n\t\t\t\tIsJammed = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Unlimbo -- Removes a building from limbo state.                              *\n *                                                                                             *\n *    Use this routine to transform a building that has been held in limbo                     *\n *    state, into one that really exists on the map. Once a building as                        *\n *    been unlimboed, then it becomes a normal object in the game world.                       *\n *                                                                                             *\n * INPUT:   pos   -- The position to place the building on the map.                            *\n *                                                                                             *\n *          dir (optional) -- not used for this class                                          *\n *                                                                                             *\n * OUTPUT:  bool; Was the unlimbo successful?                                                  *\n *                                                                                             *\n * WARNINGS:   The unlimbo operation might not be successful if the                            *\n *             building could not be placed at the location specified.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/16/1994 JLB : Created.                                                                 *\n *   06/07/1994 JLB : Matches virtual function format for base class.                          *\n *   05/09/1995 JLB : Handles wall placement.                                                  *\n *   06/18/1995 JLB : Checks for wall legality before placing down.                            *\n *=============================================================================================*/\nbool BuildingClass::Unlimbo(COORDINATE coord, DirType dir)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tIf this is a wall type building, then it never gets unlimboed. Instead, it gets\n\t**\tconverted to an overlay type.\n\t*/\n\tif (Class->IsWall) {\n\t\tif (Can_Enter_Cell(Coord_Cell(coord), FACING_NONE) == MOVE_OK) {\n\t\t\tOverlayType otype = OVERLAY_NONE;\n\t\t\tswitch (Class->Type) {\n\t\t\t\tcase STRUCT_SANDBAG_WALL:\n\t\t\t\t\totype\t= OVERLAY_SANDBAG_WALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_CYCLONE_WALL:\n\t\t\t\t\totype = OVERLAY_CYCLONE_WALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_BRICK_WALL:\n\t\t\t\t\totype = OVERLAY_BRICK_WALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_BARBWIRE_WALL:\n\t\t\t\t\totype = OVERLAY_BARBWIRE_WALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_WOOD_WALL:\n\t\t\t\t\totype = OVERLAY_WOOD_WALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_FENCE:\n\t\t\t\t\totype = OVERLAY_FENCE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\totype = OVERLAY_NONE;\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\t\t\tif (otype != OVERLAY_NONE) {\n\t\t\t\tObjectClass * o = OverlayTypeClass::As_Reference(otype).Create_One_Of(House);\n\t\t\t\tif (o && o->Unlimbo(coord)) {\n\t\t\t\t\tMap[coord].Owner = House->Class->House;\n\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\tMap.Sight_From(Coord_Cell(coord), Class->SightRange, House);\n\t\t\t\t\tdelete this;\n\t\t\t\t\treturn(true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tNormal building unlimbo process.\n\t*/\n\tif (TechnoClass::Unlimbo(coord, dir)) {\n\n\t\t/*\n\t\t**\tEnsure that the owning house knows about the\n\t\t**\tnew object.\n\t\t*/\n\t\tHouse->BScan |= (1L << Class->Type);\n\t\tHouse->ActiveBScan |= (1L << Class->Type);\n\n\t\t/*\n\t\t**\tRecalculate the center point of the house's base.\n\t\t*/\n\t\tHouse->Recalc_Center();\n\n\t\t/*\n\t\t**\tUpdate the total factory type, assuming this building has a factory.\n\t\t*/\n\t\tHouse->Active_Add(this);\n\n\t\t/*\n\t\t**\tPossibly the sidebar will be affected by this addition.\n\t\t*/\n\t\tHouse->IsRecalcNeeded = true;\n\t\tLastStrength = 0;\n\n\t\tif ((!IsDiscoveredByPlayer && Map[coord].IsVisible) || Session.Type != GAME_NORMAL) {\n\t\t\tRevealed(PlayerPtr);\n\t\t}\n\t\tif (!House->IsHuman) {\n\t\t\tRevealed(House);\n\t\t}\n\n\t\tif (IsOwnedByPlayer) {\n\t\t\tMap.PowerClass::IsToRedraw = true;\n\t\t\tMap.Flag_To_Redraw(false);\n\t\t}\n\n\t\tif ((Class->Ownable & (HOUSEF_GOOD | HOUSEF_BAD)) != (HOUSEF_GOOD | HOUSEF_BAD)) {\n\t\t\tif (Class->Ownable & HOUSEF_GOOD) {\n\t\t\t\tActLike = HOUSE_GREECE;\n\t\t\t} else {\n\t\t\t\tActLike = HOUSE_USSR;\n\t\t\t}\n\t\t}\n\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Take_Damage -- Inflicts damage points upon a building.                       *\n *                                                                                             *\n *    This routine will inflict damage points upon the specified building.                     *\n *    It will handle the damage animation and building destruction. Use                        *\n *    this routine whenever a building is attacked.                                            *\n *                                                                                             *\n * INPUT:   damage   -- Amount of damage to inflict.                                           *\n *                                                                                             *\n *          distance -- The distance from the damage center point to the object's center point.*\n *                                                                                             *\n *          warhead  -- The kind of damage to inflict.                                         *\n *                                                                                             *\n *          source   -- The source of the damage. This is used to change targeting.            *\n *                                                                                             *\n *          forced   -- Is the damage forced upon the object regardless of whether it          *\n *                      is normally immune?                                                    *\n *                                                                                             *\n * OUTPUT:  true/false; Was the building destroyed?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/21/1991     : Created.                                                                 *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *   04/16/1994 JLB : Added warhead modifier to damage.                                        *\n *   06/03/1994 JLB : Added source of damage as target value.                                  *\n *   06/20/1994 JLB : Source is a base class pointer.                                          *\n *   11/22/1994 JLB : Shares base damage handler for techno objects.                           *\n *   07/15/1995 JLB : Power ratio gets adjusted.                                               *\n *=============================================================================================*/\nResultType BuildingClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, int forced)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tResultType res = RESULT_NONE;\n\tint shakes;\n\n\tif (this != source /*&& !Class->IsInsignificant*/) {\n\n\t\tif (source) {\n\t\t\tHouse->LATime = Frame;\n\t\t\tHouse->LAType = source->What_Am_I();\n\t\t\tHouse->LAZone = House->Which_Zone(this);\n\t\t\tHouse->LAEnemy = source->Owner();\n\n\t\t\tif (!House->Is_Ally(source)) {\n\t\t\t\tHouse->Enemy = source->Owner();\n\t\t\t}\n\n\t\t\tBase_Is_Attacked(source);\n\t\t}\n\n\t\tshort const * offset = Occupy_List();\n\n\t\t/*\n\t\t** Memorize who they used to be in radio contact with.\n\t\t*/\n\t\tTechnoClass *tech = Contact_With_Whom();\n\t\t/*\n\t\t**\tPerform the low level damage assessment.\n\t\t*/\n\t\tres = TechnoClass::Take_Damage(damage, distance, warhead, source, forced);\n\t\tswitch (res) {\n\t\t\tcase RESULT_DESTROYED:\n\n\t\t\t\t/*\n\t\t\t\t**\tAdd the building to the base prebuild list if allowed. This will force\n\t\t\t\t**\tthe computer to rebuild this structure if it can.\n\t\t\t\t*/\n\t\t\t\tif (IsToRebuild && Class->Level != -1 && Base.House == House->Class->House && Base.Get_Node(this) == 0) {\n//\t\t\t\tif (IsToRebuild && Class->IsBuildable && Base.House == House->Class->House && Base.Get_Node(this) == 0) {\n\t\t\t\t\tBase.Nodes.Add(BaseNodeClass(Class->Type, Coord_Cell(Coord)));\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tDestroy all attached objects.\n\t\t\t\t*/\n\t\t\t\twhile (Attached_Object()) {\n\t\t\t\t\tFootClass * obj = Detach_Object();\n\n\t\t\t\t\tDetach_All(true);\n\t\t\t\t\tdelete obj;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** If we were in contact with a landed plane, blow the plane up too.\n\t\t\t\t*/\n\t\t\t\tif (tech && tech->IsActive && tech->What_Am_I() == RTTI_AIRCRAFT && ((AircraftClass *)tech)->Class->IsFixedWing && ((AircraftClass *)tech)->In_Which_Layer() == LAYER_GROUND) {\n\t\t\t\t\tint damage = 500;\n\t\t\t\t\ttech->Take_Damage(damage, 0, WARHEAD_AP, source, forced);\n\t\t\t\t}\n\n\t\t\t\tSound_Effect(VOC_KABOOM22, Coord);\n\t\t\t\twhile (*offset != REFRESH_EOL) {\n\t\t\t\t\tCELL cell = Coord_Cell(Coord) + *offset++;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the building is destroyed, then lots of\n\t\t\t\t\t**\texplosions occur.\n\t\t\t\t\t*/\n\t\t\t\t\tnew SmudgeClass(Random_Pick(SMUDGE_CRATER1, SMUDGE_CRATER6), Cell_Coord(cell));\n\t\t\t\t\tif (Percent_Chance(50)) {\n\t\t\t\t\t\tnew AnimClass(ANIM_FIRE_SMALL, Coord_Scatter(Cell_Coord(cell), 0x0080), Random_Pick(0, 7), Random_Pick(1, 3));\n\t\t\t\t\t\tif (Percent_Chance(50)) {\n\t\t\t\t\t\t\tnew AnimClass(ANIM_FIRE_MED, Coord_Scatter(Cell_Coord(cell), 0x0040), Random_Pick(0, 7), Random_Pick(1, 3));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tnew AnimClass(ANIM_FBALL1, Coord_Scatter(Cell_Coord(cell), 0x0040), Random_Pick(0, 3));\n\t\t\t\t}\n\n\t\t\t\tshakes = Class->Cost_Of() / 400;\n\t\t\t\tif (shakes) {\n\t\t\t\t\tShake_The_Screen(shakes);\n\t\t\t\t}\n\t\t\t\tSound_Effect(VOC_CRUMBLE, Coord);\n\t\t\t\tif (Mission == MISSION_DECONSTRUCTION) {\n\t\t\t\t\tCountDown = 0;\n\t\t\t\t\tSet_Rate(0);\n\t\t\t\t} else {\n\t\t\t\t\tCountDown = 8;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf it is in radio contact and the object seems to be attached, then tell\n\t\t\t\t**\tit to run away.\n\t\t\t\t*/\n\t\t\t\tif (In_Radio_Contact() && Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {\n\t\t\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tA force destruction will not generate survivors.\n\t\t\t\t*/\n\t\t\t\tif (forced || *this == STRUCT_KENNEL) {\n\t\t\t\t\tIsSurvivorless = true;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Destruction of a radar facility or advanced communications\n\t\t\t\t** center will cause the spiedby field to change...\n\t\t\t\t*/\n\t\t\t\tif (SpiedBy) {\n\t\t\t\t\tSpiedBy = 0;\n\t\t\t\t\tStructType struc = *this;\n\t\t\t\t\tif (struc == STRUCT_RADAR /* || struc == STRUCT_EYE */) {\n\t\t\t\t\t\tUpdate_Radar_Spied();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Destruction of a gap generator will cause the cells it affects\n\t\t\t\t** to stop being jammed.\n\t\t\t\t*/\n\t\t\t\tif (*this == STRUCT_GAP) {\n\t\t\t\t\tRemove_Gap_Effect();\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Destruction of a shipyard or sub pen may cause attached ships\n\t\t\t\t** who are repairing themselves to discontinue repairs.\n\t\t\t\t*/\n\t\t\t\tif (*this == STRUCT_SHIP_YARD || *this == STRUCT_SUB_PEN) {\n\t\t\t\t\tfor (int index = 0; index < Vessels.Count(); index++) {\n\t\t\t\t\t\tVesselClass *obj = Vessels.Ptr(index);\n\t\t\t\t\t\tif (obj && !obj->IsInLimbo && obj->House == House) {\n\t\t\t\t\t\t\tif (obj->IsSelfRepairing) {\n\t\t\t\t\t\t\t\tif (::Distance(Center_Coord(), obj->Center_Coord()) < 0x0200) {\n\t\t\t\t\t\t\t\t\tobj->IsSelfRepairing = false;\n\t\t\t\t\t\t\t\t\tobj->IsToSelfRepair = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Destruction of a barrel will cause the surrounding squares to\n\t\t\t\t** be hit with damage.\n\t\t\t\t*/\n\t\t\t\tif (*this == STRUCT_BARREL || *this == STRUCT_BARREL3) {\n\t\t\t\t\tCOORDINATE center = Center_Coord();\n\t\t\t\t\tCELL cellcenter = Coord_Cell(center);\n\n\t\t\t\t\tBulletClass * bullet;\n\n\t\t\t\t\tbullet = new BulletClass(BULLET_INVISIBLE, ::As_Target(Adjacent_Cell(cellcenter, FACING_N)), 0, 200, WARHEAD_FIRE, MPH_MEDIUM_FAST);\n\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\tbullet->Unlimbo(center, DIR_N);\n\t\t\t\t\t}\n\n\t\t\t\t\tbullet = new BulletClass(BULLET_INVISIBLE, ::As_Target(Adjacent_Cell(cellcenter, FACING_E)), 0, 200, WARHEAD_FIRE, MPH_MEDIUM_FAST);\n\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\tbullet->Unlimbo(center, DIR_E);\n\t\t\t\t\t}\n\n\t\t\t\t\tbullet = new BulletClass(BULLET_INVISIBLE, ::As_Target(Adjacent_Cell(cellcenter, FACING_S)), 0, 200, WARHEAD_FIRE, MPH_MEDIUM_FAST);\n\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\tbullet->Unlimbo(center, DIR_S);\n\t\t\t\t\t}\n\n\t\t\t\t\tbullet = new BulletClass(BULLET_INVISIBLE, ::As_Target(Adjacent_Cell(cellcenter, FACING_W)), 0, 200, WARHEAD_FIRE, MPH_MEDIUM_FAST);\n\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\tbullet->Unlimbo(center, DIR_W);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RESULT_HALF:\n\t\t\t\tif (*this == STRUCT_PUMP) {\n\t\t\t\t\tAnimClass * anim = new AnimClass(ANIM_OILFIELD_BURN, Coord_Add(Coord, 0x00400130L), 1);\n\t\t\t\t\tif (anim) {\n\t\t\t\t\t\tanim->Attach_To(this);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Fall into next case.\n\n\t\t\tcase RESULT_MAJOR:\n\t\t\t\tSound_Effect(VOC_KABOOM1, Coord);\n\t\t\t\twhile (*offset != REFRESH_EOL) {\n\t\t\t\t\tCELL cell = Coord_Cell(Coord) + *offset++;\n\t\t\t\t\tAnimClass * anim = NULL;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tShow pieces of fire to indicate that a significant change in\n\t\t\t\t\t**\tdamage level has occurred.\n\t\t\t\t\t*/\n\t\t\t\t\tif (warhead == WARHEAD_FIRE) {\n\t\t\t\t\t\tswitch (Random_Pick(0, 5+Class->Width()+Class->Height())) {\n\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\tcase 5:\n\t\t\t\t\t\t\t\tanim = new AnimClass(ANIM_ON_FIRE_SMALL, Coord_Scatter(Cell_Coord(cell), 0x0060), 0, Random_Pick(1, 3));\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 6:\n\t\t\t\t\t\t\tcase 7:\n\t\t\t\t\t\t\tcase 8:\n\t\t\t\t\t\t\t\tanim = new AnimClass(ANIM_ON_FIRE_MED, Coord_Scatter(Cell_Coord(cell), 0x0060), 0, Random_Pick(1, 3));\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 9:\n\t\t\t\t\t\t\t\tanim = new AnimClass(ANIM_ON_FIRE_BIG, Coord_Scatter(Cell_Coord(cell), 0x0060), 0, 1);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (Percent_Chance(50)) {\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Building may catch on fire, but only if it wasn't a\n\t\t\t\t\t\t\t** renovator that caused the damage.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (source == NULL || source->What_Am_I() != RTTI_INFANTRY || *(InfantryClass *)source != INFANTRY_RENOVATOR) {\n\t\t\t\t\t\t\t\tanim = new AnimClass(ANIM_FIRE_SMALL, Coord_Scatter(Cell_Coord(cell), 0x0060), Random_Pick(0, 7), Random_Pick(1, 3));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the animation was created, then attach it to the building.\n\t\t\t\t\t*/\n\t\t\t\t\tif (anim) {\n\t\t\t\t\t\tanim->Attach_To(this);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RESULT_NONE:\n\t\t\t\tbreak;\n\n\t\t\tcase RESULT_LIGHT:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (source && res != RESULT_NONE) {\n\n\t\t\t/*\n\t\t\t**\tIf any damage occurred, then inform the house of this fact. If it is the player's\n\t\t\t**\thouse, it might announce this fact.\n\t\t\t*/\n\t\t\tif (!Class->IsInsignificant) {\n\t\t\t\tHouse->Attacked();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Save the type of the house that's doing the damage, so if the building burns\n\t\t\t** to death credit can still be given for the kill\n\t\t\t*/\n\t\t\tWhoLastHurtMe = source->Owner();\n\n\t\t\t/*\n\t\t\t**\tWhen certain buildings are hit, they \"snap out of it\" and\n\t\t\t**\treturn fire if they are able and allowed.\n\t\t\t*/\n\t\t\tif (*this != STRUCT_SAM && *this != STRUCT_AAGUN &&\n\t\t\t\t!House->Is_Ally(source) &&\n\t\t\t\tClass->PrimaryWeapon != NULL &&\n\t\t\t\t(!Target_Legal(TarCom) || !In_Range(TarCom))) {\n\n\t\t\t\tif (source->What_Am_I() != RTTI_AIRCRAFT && (!House->IsHuman || Rule.IsSmartDefense)) {\n\t\t\t\t\tAssign_Target(source->As_Target());\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tGenerate a random rotation effect since there is nothing else that this\n\t\t\t\t\t**\tbuilding can do.\n\t\t\t\t\t*/\n\t\t\t\t\tif (!PrimaryFacing.Is_Rotating()) {\n\t\t\t\t\t\tPrimaryFacing.Set_Desired(Random_Pick(DIR_N, DIR_MAX));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(res);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::new -- Allocates a building object from building pool.                       *\n *                                                                                             *\n *    This routine will allocate a building slot from the building alloc                       *\n *    system.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocated building. If NULL is                       *\n *          returned, then this indicates a failure to allocate.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/11/1994 JLB : Created.                                                                 *\n *   04/21/1994 JLB : Converted to operator new.                                               *\n *   05/17/1994 JLB : Revamped allocation scheme                                               *\n *   07/29/1994 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid * BuildingClass::operator new(size_t )\n{\n\tvoid * ptr = Buildings.Allocate();\n\tif (ptr) {\n\t\t((BuildingClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::delete -- Deallocates building object.                                       *\n *                                                                                             *\n *    This is the memory deallocation operation for a building object.                         *\n *    Since buildings are allocated out of a fixed memory block, all that                      *\n *    is needed is to flag the unit as inactive.                                               *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to building to deallocate.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/21/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::operator delete(void *ptr)\n{\n\tif (ptr) {\n\t\t((BuildingClass *)ptr)->IsActive = false;\n\t}\n\tBuildings.Free((BuildingClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::BuildingClass -- Constructor for buildings.                                  *\n *                                                                                             *\n *    This routine inserts a building into the object tracking system.                         *\n *    It is placed into a limbo state unless a location is provided for                        *\n *    it to unlimbo at.                                                                        *\n *                                                                                             *\n * INPUT:   type  -- The structure type to make this object.                                   *\n *                                                                                             *\n *          house -- The owner of this building.                                               *\n *                                                                                             *\n *          pos   -- The position to unlimbo the building. If -1 is                            *\n *                   specified, then the building remains in a limbo                           *\n *                   state.                                                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/21/1994 JLB : Created.                                                                 *\n *   08/07/1995 JLB : Fixed act like value to match expected value.                            *\n *=============================================================================================*/\nBuildingClass::BuildingClass(StructType type, HousesType house) :\n\tTechnoClass(RTTI_BUILDING, Buildings.ID(this), house),\n\tClass(BuildingTypes.Ptr((int)type)),\n\tFactory(0),\n\tActLike(House->ActLike),\n\tIsToRebuild(false),\n\tIsToRepair(false),\n\tIsAllowedToSell(true),\n\tIsReadyToCommence(false),\n\tIsRepairing(false),\n\tIsWrenchVisible(false),\n\tIsGoingToBlow(false),\n\tIsSurvivorless(false),\n\tIsCharging(false),\n\tIsCharged(false),\n\tIsCaptured(false),\n\tIsJamming(false),\n\tIsJammed(false),\n\tHasFired(false),\n\tHasOpened(false),\n\tCountDown(0),\n\tBState(BSTATE_NONE),\n\tQueueBState(BSTATE_NONE),\n\tWhoLastHurtMe(house),\n\tWhomToRepay(TARGET_NONE),\n\tAnimToTrack(TARGET_NONE),\n\tLastStrength(0),\n\tPlacementDelay(0)\n{\n\tHouse->Tracking_Add(this);\n\tIsSecondShot = !Class->Is_Two_Shooter();\n\tStrength = Class->MaxStrength;\n\tAmmo = Class->MaxAmmo;\n\n\t/*\n\t**\tIf the building could never be built, then it can never be sold either. This\n\t**\tis due to the lack of buildup animation.\n\t*/\n\tif (Class->Get_Buildup_Data() != NULL) {\n//\tif (!Class->IsBuildable) {\n\t\tIsAllowedToSell = false;\n\t}\n\n//\tif (Session.Type == GAME_INTERNET) {\n//\t\tHouse->BuildingTotals->Increment_Unit_Total( (int) type);\n//\t}\n\n}\n\n\n/***********************************************************************************************\n * BuildingClass::~BuildingClass -- Destructor for building type objects.                      *\n *                                                                                             *\n *    This destructor for building objects will put the building in limbo if possible.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuildingClass::~BuildingClass(void)\n{\n\tif (GameActive && Class) {\n\t\tif (House) {\n\t\t\tHouse->Tracking_Remove(this);\n\t\t}\n\t\tBuildingClass::Limbo();\n\t}\n\tClass = 0;\n\n\tdelete (FactoryClass *)Factory;\n\tFactory = 0;\n\tID = -1;\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Drop_Debris -- Drops rubble when building is destroyed.                      *\n *                                                                                             *\n *    This routine is called when a building is destroyed. It handles                          *\n *    placing the rubble down.                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/14/1994 JLB : Created.                                                                 *\n *   06/13/1995 JLB : Added smoke and normal infantry survivor possibility.                    *\n *   07/16/1995 JLB : Survival rate depends on if captured or sabotaged.                       *\n *=============================================================================================*/\nvoid BuildingClass::Drop_Debris(TARGET source)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tCELL const * offset;\n\tCELL cell;\n\n\t/*\n\t**\tGenerate random survivors from the destroyed building.\n\t*/\n\tcell = Coord_Cell(Coord);\n\toffset = Occupy_List();\n\tint odds = 2;\n\tif (Target_Legal(WhomToRepay)) odds -= 1;\n\tif (IsCaptured) odds += 6;\n\tint count = How_Many_Survivors();\n\twhile (*offset != REFRESH_EOL) {\n\t\tCELL\tnewcell;\n\n\t\tnewcell = cell + *offset++;\n\t\tCellClass const * cellptr = &Map[newcell];\n\n\t\t/*\n\t\t**\tInfantry could run out of a destroyed building.\n\t\t*/\n\t\tif (!House->IsToDie && count > 0) {\n\t\t\tInfantryClass * i = NULL;\n\n\t\t\tif (Random_Pick(0, odds) == 1) {\n\t\t\t\ti = NULL;\n\t\t\t\tInfantryType typ = Crew_Type();\n\t\t\t\tif (typ != INFANTRY_NONE) i = new InfantryClass(typ, House->Class->House);\n\t\t\t\tif (i != NULL) {\n\t\t\t\t\tif (Class->Get_Buildup_Data() != NULL && i->Class->IsNominal) i->IsTechnician = true;\n\t\t\t\t\tScenarioInit++;\n\t\t\t\t\tif (i->Unlimbo(Cell_Coord(newcell), DIR_N)) {\n\t\t\t\t\t\tcount--;\n\t\t\t\t\t\ti->Strength = Random_Pick(5, (int)i->Class->MaxStrength);\n\t\t\t\t\t\ti->Scatter(0, true);\n\t\t\t\t\t\tif (source != TARGET_NONE && !House->Is_Ally(As_Object(source))) {\n\t\t\t\t\t\t\ti->Assign_Mission(MISSION_ATTACK);\n\t\t\t\t\t\t\ti->Assign_Target(source);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (House->IsHuman) {\n\t\t\t\t\t\t\t\ti->Assign_Mission(MISSION_GUARD);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ti->Assign_Mission(MISSION_HUNT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdelete i;\n\t\t\t\t\t}\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tSmoke and fire only appear on terrestrail cells. They should not appear on\n\t\t**\trivers, clifs, or water cells.\n\t\t*/\n\t\tif (cellptr->Is_Clear_To_Move(SPEED_TRACK, true, true)) {\n\n\t\t\t/*\n\t\t\t**\tPossibly add some smoke rising from the ashes of the building.\n\t\t\t*/\n\t\t\tswitch (Random_Pick(0, 5)) {\n\t\t\t\tcase 0:\n\t\t\t\tcase 1:\n\t\t\t\tcase 2:\n\t\t\t\t\tnew AnimClass(ANIM_SMOKE_M, Coord_Scatter(Cell_Coord(newcell), 0x0050, false), Random_Pick(0, 5), Random_Pick(1, 2));\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tThe building always scars the ground in some fashion.\n\t\t\t*/\n\t\t\tif (Percent_Chance(25)) {\n\t\t\t\tnew SmudgeClass(Random_Pick(SMUDGE_SCORCH1, SMUDGE_SCORCH6), Cell_Coord(newcell));\n\t\t\t} else {\n\t\t\t\tnew SmudgeClass(Random_Pick(SMUDGE_CRATER1, SMUDGE_CRATER6), Coord_Scatter(Cell_Coord(newcell), 0x0080, false));\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Active_Click_With -- Handles clicking on the map while the building is selected.*\n *                                                                                             *\n *    This interface routine handles when the player clicks on the map while this building     *\n *    is currently selected. This is used to assign an override target to a turret or          *\n *    guard tower.                                                                             *\n *                                                                                             *\n * INPUT:   target   -- The target that was clicked upon.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Active_Click_With(ActionType action, ObjectClass * object)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (action == ACTION_ATTACK && object != NULL) {\n\t\tPlayer_Assign_Mission(MISSION_ATTACK, object->As_Target());\n\t}\n\n\tif (action == ACTION_SELF && Class->Is_Factory()) {\n\t\tOutList.Add(EventClass(EventClass::PRIMARY, TargetClass(this)));\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Active_Click_With -- Handles cell selection for buildings.                   *\n *                                                                                             *\n *    This routine really only serves one purpose -- to allow targeting of the ground for      *\n *    buildings that are equipped with weapons.                                                *\n *                                                                                             *\n * INPUT:   action   -- The requested action to perform.                                       *\n *                                                                                             *\n *          cell     -- The cell location to perform the action upon.                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *   10/04/1995 JLB : Handles construction yard undeploy to move logic.                        *\n *=============================================================================================*/\nvoid BuildingClass::Active_Click_With(ActionType action, CELL cell)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (action == ACTION_ATTACK) {\n\t\tPlayer_Assign_Mission(MISSION_ATTACK, ::As_Target(cell));\n\t}\n\n\tif (action == ACTION_MOVE && *this == STRUCT_CONST) {\n\t\tOutList.Add(EventClass(EventClass::ARCHIVE, TargetClass(this), TargetClass(cell)));\n\t\tOutList.Add(EventClass(EventClass::SELL, TargetClass(this)));\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Assign_Target -- Assigns a target to the building.                           *\n *                                                                                             *\n *    Assigning of a target to a building makes sense if the building is one that can attack.  *\n *    This routine would be used to assign the attack target to a turret or guard tower.       *\n *                                                                                             *\n * INPUT:   target   -- The target that was clicked on while this building was selected.       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *   11/02/1994 JLB : Checks for range before assigning target.                                *\n *=============================================================================================*/\nvoid BuildingClass::Assign_Target(TARGET target)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this != STRUCT_SAM && *this != STRUCT_AAGUN && !In_Range(target, 0)) {\n\t\ttarget = TARGET_NONE;\n\t}\n\n\tTechnoClass::Assign_Target(target);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Init -- Initialize the building system to an empty null state.               *\n *                                                                                             *\n *    This routine initializes the building system in preparation for a scenario load.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Init(void)\n{\n\tBuildings.Free_All();\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Exit_Object -- Initiates an object to leave the building.                    *\n *                                                                                             *\n *    This function is used to cause an object to exit the building. It is called when a       *\n *    factory produces a vehicle or other mobile object and that object needs to exit the      *\n *    building to join the ranks of a regular unit. Typically, the object is placed down on    *\n *    the map such that it overlaps the building and then it is given a movement order so that *\n *    it will move to an adjacent free cell.                                                   *\n *                                                                                             *\n * INPUT:   base  -- Pointer to the object that is to exit the building.                       *\n *                                                                                             *\n * OUTPUT:  Returns the success rating for the exit attempt;                                   *\n *             0  = complete failure (refund money please)                                     *\n *             1  = temporarily prevented (try again later please)                             *\n *             2  = successful                                                                 *\n *                                                                                             *\n * WARNINGS:   The building is placed in radio contact with the object. The object is in a     *\n *             tethered condition. This condition will be automatically broken when the        *\n *             object reaches the adjacent square.                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/28/1994 JLB : Created.                                                                 *\n *   04/10/1995 JLB : Handles building production by computer.                                 *\n *   06/17/1995 JLB : Handles refinery exit.                                                   *\n *=============================================================================================*/\nint BuildingClass::Exit_Object(TechnoClass * base)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!base) return(0);\n\n\tTechnoTypeClass const * ttype = (TechnoTypeClass const *)&base->Class_Of();\n\n\t/*\n\t**\tA unit exiting a building is always considered to be \"locked\". That means, it\n\t**\twill be considered as to have legally entered the visible map domain.\n\t*/\n\tbase->IsLocked = true;\n\n\t/*\n\t**\tFind a good cell to unload the object to. The object, probably a vehicle\n\t**\twill drive/walk to the adjacent free cell.\n\t*/\n\tCELL cell = 0;\n\n\tswitch (base->What_Am_I()) {\n\n\t\tcase RTTI_AIRCRAFT:\n\t\t\tif (!In_Radio_Contact()) {\n\t\t\t\tAircraftClass * air = (AircraftClass *)base;\n\n\t\t\t\tair->Height = 0;\n\t\t\t\tScenarioInit++;\n\t\t\t\tif (air->Unlimbo(Docking_Coord(), air->Pose_Dir())) {\n\t\t\t\t\tTransmit_Message(RADIO_HELLO, air);\n\t\t\t\t\tTransmit_Message(RADIO_TETHER);\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t\treturn(2);\n\t\t\t\t}\n\t\t\t\tScenarioInit--;\n\t\t\t} else {\n\t\t\t\tAircraftClass * air = (AircraftClass *)base;\n\n\t\t\t\tif (Cell_X(Coord_Cell(Center_Coord())) - Map.MapCellX < Map.MapCellWidth/2) {\n\t\t\t\t\tcell = XY_Cell(Map.MapCellX-1, Random_Pick(0, Map.MapCellHeight-1)+Map.MapCellY);\n\t\t\t\t} else {\n\t\t\t\t\tcell = XY_Cell(Map.MapCellX+Map.MapCellWidth, Random_Pick(0, Map.MapCellHeight-1)+Map.MapCellY);\n\t\t\t\t}\n\t\t\t\tScenarioInit++;\n\t\t\t\tif (air->Unlimbo(Cell_Coord(cell), DIR_N)) {\n//BG\t\t\t\tair->Assign_Destination(::As_Target(Nearby_Location(air)));\n/*BG*/\t\t\tair->Assign_Destination(::As_Target(air->Nearby_Location(this)));\n\t\t\t\t\tair->Assign_Mission(MISSION_MOVE);\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t\treturn(2);\n\t\t\t\t}\n\t\t\t\tScenarioInit--;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\t\tswitch (Class->Type) {\n\t\t\t\tcase STRUCT_SUB_PEN:\n\t\t\t\tcase STRUCT_SHIP_YARD:\n\t\t\t\t\tScenarioInit++;\n\t\t\t\t\tcell = Find_Exit_Cell(base);\n\t\t\t\t\tif (cell != 0 && base->Unlimbo(Cell_Coord(cell), Direction(Cell_Coord(cell)))) {\n\t\t\t\t\t\tbase->Assign_Mission(MISSION_GUARD);\n\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t\treturn(2);\n\t\t\t\t\t}\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_INFANTRY:\n\t\tcase RTTI_UNIT:\n\t\t\tswitch (Class->Type) {\n\t\t\t\tcase STRUCT_REFINERY:\n\t\t\t\t\tif (base->What_Am_I() == RTTI_UNIT) {\n\t\t\t\t\t\tcell = Coord_Cell(Center_Coord());\n\t\t\t\t\t\tUnitClass * unit = (UnitClass *)base;\n\n\t\t\t\t\t\tcell = Adjacent_Cell(cell, FACING_SW);\n\t\t\t\t\t\tScenarioInit++;\n\t\t\t\t\t\tif (unit->Unlimbo(Cell_Coord(Adjacent_Cell(cell, DIR_S)), DIR_SW_X2)) {\n\t\t\t\t\t\t\tunit->PrimaryFacing = DIR_S;\n\t\t\t\t\t\t\tunit->Assign_Mission(MISSION_HARVEST);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbase->Scatter(0, true);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_WEAP:\n\t\t\t\t\tif (Mission == MISSION_UNLOAD) {\n\t\t\t\t\t\tfor(int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\t\t\tBuildingClass *bldg = Buildings.Ptr(index);\n\t\t\t\t\t\t\tif (bldg->Owner() == Owner() && *bldg == STRUCT_WEAP && bldg != this && bldg->Mission == MISSION_GUARD && !bldg->Factory) {\n\t\t\t\t\t\t\t\tFactoryClass * temp = Factory;\n\t\t\t\t\t\t\t\tbldg->Factory = Factory;\n\t\t\t\t\t\t\t\tFactory = 0;\n\t\t\t\t\t\t\t\tint retval = (bldg->Exit_Object(base));\n\t\t\t\t\t\t\t\tbldg->Factory = 0;\n\t\t\t\t\t\t\t\tFactory = temp;\n\t\t\t\t\t\t\t\treturn(retval);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(1);\t// fail while we're still unloading previous\n\t\t\t\t\t}\n\t\t\t\t\tScenarioInit++;\n\t\t\t\t\tif (base->Unlimbo(Exit_Coord(), DIR_S)) {\n\t\t\t\t\t\tbase->Mark(MARK_UP);\n\t\t\t\t\t\tbase->Coord = Exit_Coord();\n\t\t\t\t\t\tbase->Mark(MARK_DOWN);\n\t\t\t\t\t\tTransmit_Message(RADIO_HELLO, base);\n\t\t\t\t\t\tTransmit_Message(RADIO_TETHER);\n\t\t\t\t\t\tAssign_Mission(MISSION_UNLOAD);\n\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t\treturn(2);\n\t\t\t\t\t}\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_BARRACKS:\n\t\t\t\tcase STRUCT_TENT:\n\t\t\t\tcase STRUCT_KENNEL:\n\n\t\t\t\t\tcell = Find_Exit_Cell(base);\n\t\t\t\t\tif (cell != 0) {\n\t\t\t\t\t\tDirType\tdir = Direction(cell);\n\t\t\t\t\t\tCOORDINATE\t\tstart = Exit_Coord();\n\n\t\t\t\t\t\tScenarioInit++;\n\t\t\t\t\t\tif (base->Unlimbo(start, dir)) {\n\n\t\t\t\t\t\t\tbase->Assign_Mission(MISSION_MOVE);\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tWhen disembarking from a transport then guard an area around the\n\t\t\t\t\t\t\t**\tcenter of the base.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tbase->Assign_Destination(::As_Target(cell));\n\t\t\t\t\t\t\tif (House->IQ >= Rule.IQGuardArea) {\n\t\t\t\t\t\t\t\tbase->Assign_Mission(MISSION_GUARD_AREA);\n\t\t\t\t\t\t\t\tbase->ArchiveTarget = ::As_Target(House->Where_To_Go((FootClass *)base));\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tEstablish radio contact so unload coordination can occur. This\n\t\t\t\t\t\t\t**\tradio contact should always succeed.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Transmit_Message(RADIO_HELLO, base) == RADIO_ROGER) {\n\t\t\t\t\t\t\t\tTransmit_Message(RADIO_UNLOAD);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t\t\treturn(2);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tcell = Find_Exit_Cell(base);\n\t\t\t\t\tif (cell != 0) {\n\t\t\t\t\t\tDirType\tdir = Direction(cell);\n\t\t\t\t\t\tCOORDINATE\t\tstart = Exit_Coord();\n\n\t\t\t\t\t\tScenarioInit++;\n\t\t\t\t\t\tif (base->Unlimbo(start, dir)) {\n\n\t\t\t\t\t\t\tbase->Assign_Mission(MISSION_MOVE);\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tWhen disembarking from a transport then guard an area around the\n\t\t\t\t\t\t\t**\tcenter of the base.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tbase->Assign_Destination(::As_Target(cell));\n\t\t\t\t\t\t\tif (House->IQ >= Rule.IQGuardArea) {\n\t\t\t\t\t\t\t\tbase->Assign_Mission(MISSION_GUARD_AREA);\n\t\t\t\t\t\t\t\tbase->ArchiveTarget = ::As_Target(House->Where_To_Go((FootClass *)base));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t\t\treturn(2);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_BUILDING:\n\n\t\t\tif (!House->IsHuman) {\n\n\t\t\t\t/*\n\t\t\t\t**\tFind the next available spot to place this newly created building. If the\n\t\t\t\t**\tbuilding could be placed at the desired location, fine. If not, then this\n\t\t\t\t**\troutine will return failure. The calling routine will probably abandon this\n\t\t\t\t**\tbuilding in preference to building another.\n\t\t\t\t*/\n\t\t\t\tBaseNodeClass * node = Base.Next_Buildable(((BuildingClass *)base)->Class->Type);\n\t\t\t\tCOORDINATE coord = 0;\n\t\t\t\tif (node) {\n\t\t\t\t\tcoord = Cell_Coord(node->Cell);\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tFind a suitable new spot to place.\n\t\t\t\t\t*/\n\t\t\t\t\tcoord = House->Find_Build_Location((BuildingClass *)base);\n\t\t\t\t}\n\n\t\t\t\tif (coord) {\n\t\t\t\t\tif (Flush_For_Placement(base, Coord_Cell(coord))) {\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t}\n\t\t\t\t\tif (base->Unlimbo(coord)) {\n\t\t\t\t\t\tif (node && ((BuildingClass *)base)->Class->Type == House->BuildStructure) {\n\t\t\t\t\t\t\tHouse->BuildStructure = STRUCT_NONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(2);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tFailure to exit the object results in a false return value.\n\t*/\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Update_Buildables -- Informs sidebar of additional construction options.     *\n *                                                                                             *\n *    This routine will tell the sidebar of objects that can be built. The function is called  *\n *    whenever a building matures.                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/11/1994 JLB : Created.                                                                 *\n *   12/23/1994 JLB : Only updates for PLAYER buildings.                                       *\n *=============================================================================================*/\nvoid BuildingClass::Update_Buildables(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (House == PlayerPtr && !IsInLimbo && IsDiscoveredByPlayer) {\n\t\tswitch (Class->ToBuild) {\n\t\t\tStructType i;\n\t\t\tUnitType u;\n\t\t\tInfantryType f;\n\t\t\tAircraftType a;\n\t\t\tVesselType v;\n\n\t\t\tcase RTTI_VESSELTYPE:\n\t\t\t\tfor (v = VESSEL_FIRST; v < VESSEL_COUNT; v++) {\n\t\t\t\t\tif (PlayerPtr->Can_Build(&VesselTypeClass::As_Reference(v), ActLike)) {\n\t\t\t\t\t\tMap.Add(RTTI_VESSELTYPE, v);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_BUILDINGTYPE:\n\t\t\t\tfor (i = STRUCT_FIRST; i < STRUCT_COUNT; i++) {\n\t\t\t\t\tif (PlayerPtr->Can_Build(&BuildingTypeClass::As_Reference(i), ActLike)) {\n\t\t\t\t\t\tMap.Add(RTTI_BUILDINGTYPE, i);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_UNITTYPE:\n\t\t\t\tfor (u = UNIT_FIRST; u < UNIT_COUNT; u++) {\n\t\t\t\t\tif (PlayerPtr->Can_Build(&UnitTypeClass::As_Reference(u), ActLike)) {\n\t\t\t\t\t\tMap.Add(RTTI_UNITTYPE, u);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_INFANTRYTYPE:\n\t\t\t\tfor (f = INFANTRY_FIRST; f < INFANTRY_COUNT; f++) {\n\t\t\t\t\tif (PlayerPtr->Can_Build(&InfantryTypeClass::As_Reference(f), ActLike)) {\n\t\t\t\t\t\tif (InfantryTypeClass::As_Reference(f).IsDog) {\n\t\t\t\t\t\t\tif (*this == STRUCT_KENNEL) {\n\t\t\t\t\t\t\t\tMap.Add(RTTI_INFANTRYTYPE, f);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (*this != STRUCT_KENNEL) {\n\t\t\t\t\t\t\t\tMap.Add(RTTI_INFANTRYTYPE, f);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\t\tfor (a = AIRCRAFT_FIRST; a < AIRCRAFT_COUNT; a++) {\n\t\t\t\t\tif (PlayerPtr->Can_Build(&AircraftTypeClass::As_Reference(a), ActLike)) {\n\t\t\t\t\t\tMap.Add(RTTI_AIRCRAFTTYPE, a);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Fire_Out -- Handles when attached animation expires.                         *\n *                                                                                             *\n *    This routine is used to perform any fixups necessary when the attached animation has     *\n *    terminated. This occurs when the fire & smoke animation that a SAM site produces stops.  *\n *    At that point, normal reload procedures can commence.                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/30/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Fire_Out(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Limbo -- Handles power adjustment as building goes into limbo.               *\n *                                                                                             *\n *    This routine will handle the power adjustments for the associated house when the         *\n *    building goes into limbo. This means that its power drain or production is subtracted    *\n *    from the house accumulated totals.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the building limboed?                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BuildingClass::Limbo(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!IsInLimbo) {\n\n\t\t/*\n\t\t**\tUpdate the total factory type, assuming this building has a factory.\n\t\t*/\n\t\tHouse->Active_Remove(this);\n\t\tHouse->IsRecalcNeeded = true;\n\t\tHouse->Recalc_Center();\n\n\t\t/*\n\t\t**\tUpdate the power status of the owner's house.\n\t\t*/\n\t\tHouse->Adjust_Power(-Power_Output());\n\t\tHouse->Adjust_Drain(-Class->Drain);\n\t\tHouse->Adjust_Capacity(-Class->Capacity, true);\n\t\tif (House == PlayerPtr) {\n\t\t\tMap.PowerClass::IsToRedraw = true;\n\t\t\tMap.Flag_To_Redraw(false);\n\t\t}\n\n\t\t/*\n\t\t**\tThis could be a building that builds. If so, then the sidebar may need adjustment.\n\t\t** Set IsInLimbo to true to \"fool\" the sidebar into knowing that this building\n\t\t** isn't available.  Set it back to false so the rest of the Limbo code works.\n\t\t** Otherwise, the sidebar won't properly remove non-available buildables.\n\t\t*/\n//\t\tif (IsOwnedByPlayer && !ScenarioInit) {\n//\t\t\tIsInLimbo = true;\n//\t\t\tMap.Recalc();\n//\t\t\tIsInLimbo = false;\n//\t\t}\n\t}\n\treturn(TechnoClass::Limbo());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Turret_Facing -- Fetches the turret facing for this building.                *\n *                                                                                             *\n *    This will return the turret facing for this building. Some buildings don't have a        *\n *    visual turret (e.g., pillbox) so they return a turret facing that always faces their     *\n *    current target.                                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current facing of the turret.                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nDirType BuildingClass::Turret_Facing(void) const\n{\n\tif (!Class->IsTurretEquipped && Target_Legal(TarCom)) {\n\t\treturn(::Direction(Center_Coord(), As_Coord(TarCom)));\n\t}\n\treturn(PrimaryFacing.Current());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Greatest_Threat -- Searches for target that building can fire upon.          *\n *                                                                                             *\n *    This routine intercepts the Greatest_Threat function so that it can add the ability      *\n *    to search for ground targets, if this isn't a SAM site.                                  *\n *                                                                                             *\n * INPUT:   threat   -- The base threat control value. Typically, it might be THREAT_RANGE     *\n *                      or THREAT_NORMAL.                                                      *\n *                                                                                             *\n * OUTPUT:  Returns with a suitable target. If none could be found, then TARGET_NONE is        *\n *          returned instead.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/01/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTARGET BuildingClass::Greatest_Threat(ThreatType threat) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->PrimaryWeapon != NULL) {\n\t\tthreat = threat | Class->PrimaryWeapon->Allowed_Threats();\n\t}\n\tif (Class->SecondaryWeapon != NULL) {\n\t\tthreat = threat | Class->SecondaryWeapon->Allowed_Threats();\n\t}\n\tif (House->IsHuman) {\n\t\tthreat = threat & ~THREAT_BUILDINGS;\n\t}\n\tthreat = threat | THREAT_RANGE;\n\n//\tif (Class->PrimaryWeapon != NULL) {\n//\t\tif (Class->PrimaryWeapon->Bullet->IsAntiAircraft) {\n//\t\t\tthreat = threat | THREAT_AIR;\n//\t\t}\n//\t\tif (Class->PrimaryWeapon->Bullet->IsAntiGround) {\n//\t\t\tthreat = threat | THREAT_BUILDINGS|THREAT_INFANTRY|THREAT_BOATS|THREAT_VEHICLES;\n//\t\t}\n//\t\tthreat = threat | THREAT_RANGE;\n//\t}\n\treturn(TechnoClass::Greatest_Threat(threat));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Grand_Opening -- Handles construction completed special operations.          *\n *                                                                                             *\n *    This routine is called when construction has finished. Typically, this enables           *\n *    new production options for factories.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/08/1995 JLB : Created.                                                                 *\n *   06/13/1995 JLB : Added helipad.                                                           *\n *=============================================================================================*/\nvoid BuildingClass::Grand_Opening(bool captured)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!HasOpened || captured) {\n\t\tHasOpened = true;\n\n\t\t/*\n\t\t**\tAdjust the owning house according to the power, drain, and Tiberium capacity that\n\t\t**\tthis building has.\n\t\t*/\n\t\tHouse->Adjust_Drain(Class->Drain);\n\t\tHouse->Adjust_Capacity(Class->Capacity);\n\t\tHouse->IsRecalcNeeded = true;\n\n\t\t/*\tSPECIAL CASE:\n\t\t**\tTiberium Refineries get a free harvester. Add a harvester to the\n\t\t**\treinforcement list at this time.\n\t\t*/\n\t\tif (*this == STRUCT_REFINERY && !ScenarioInit && !captured && !Debug_Map && (!House->IsHuman || PurchasePrice == 0 || PurchasePrice > Class->Raw_Cost())) {\n\t\t\tCELL cell = Coord_Cell(Adjacent_Cell(Center_Coord(), DIR_S));\n\n\t\t\tUnitClass * unit = new UnitClass(UNIT_HARVESTER, House->Class->House);\n\t\t\tif (unit != NULL) {\n\n\t\t\t\t/*\n\t\t\t\t**\tTry to place down the harvesters. If it could not be placed, then try\n\t\t\t\t**\tto place it in a nearby location.\n\t\t\t\t*/\n\t\t\t\tif (!unit->Unlimbo(Cell_Coord(cell), DIR_W)) {\n\t\t\t\t\tcell = unit->Nearby_Location(this);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the harvester could still not be placed, then refund the money\n\t\t\t\t\t**\tto the owner and then bail.\n\t\t\t\t\t*/\n\t\t\t\t\tif (!unit->Unlimbo(Cell_Coord(cell), DIR_SW)) {\n\t\t\t\t\t\tHouse->Refund_Money(unit->Class->Cost_Of());\n\t\t\t\t\t\tdelete unit;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the harvester could not be created in the first place, then give\n\t\t\t\t**\tthe full refund price to the owning player.\n\t\t\t\t*/\n\t\t\t\tHouse->Refund_Money(UnitTypeClass::As_Reference(UNIT_HARVESTER).Cost_Of());\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tHelicopter pads get a free attack helicopter.\n\t\t*/\n\t\tif (!Rule.IsSeparate && *this == STRUCT_HELIPAD && !captured) {\n\t\t\tScenarioInit++;\n\t\t\tAircraftClass * air = 0;\n\t\t\tif (House->ActLike == HOUSE_USSR || House->ActLike == HOUSE_BAD || House->ActLike == HOUSE_UKRAINE) {\n\t\t\t\tair = new AircraftClass(AIRCRAFT_HIND, House->Class->House);\n\t\t\t} else {\n\t\t\t\tair = new AircraftClass(AIRCRAFT_LONGBOW, House->Class->House);\n\t\t\t}\n\t\t\tif (air) {\n\t\t\t\tair->Height = 0;\n\t\t\t\tif (air->Unlimbo(Docking_Coord(), air->Pose_Dir())) {\n\t\t\t\t\tair->Assign_Mission(MISSION_GUARD);\n\t\t\t\t\tair->Transmit_Message(RADIO_HELLO, this);\n\t\t\t\t\tTransmit_Message(RADIO_TETHER);\n\t\t\t\t}\n\t\t\t}\n\t\t\tScenarioInit--;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Repair -- Initiates or terminates the repair process.                        *\n *                                                                                             *\n *    This routine will start, stop, or toggle the repair process. When a building repairs, it *\n *    occurs incrementally over time.                                                          *\n *                                                                                             *\n * INPUT:   control  -- Determines how to control the repair process.                          *\n *                      0: Turns repair process off (if it was on).                            *\n *                      1: Turns repair process on (if it was off).                            *\n *                      -1:Toggles repair process to other state.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Repair(int control)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tswitch (control) {\n\t\tcase -1:\n\t\t\tIsRepairing = (IsRepairing == false);\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tif (IsRepairing) return;\n\t\t\tIsRepairing = true;\n\t\t\tbreak;\n\n\t\tcase 0:\n\t\t\tif (!IsRepairing) return;\n\t\t\tIsRepairing = false;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tAt this point, we know that the repair state has changed. Perform\n\t**\tappropriate action.\n\t*/\n\tVocType soundid = VOC_NONE;\n\tif (IsRepairing) {\n\t\tif (Strength == Class->MaxStrength) {\n\t\t\tsoundid = VOC_SCOLD;\n\t\t} else {\n\t\t\tsoundid = VOC_CLICK;\n\t\t\tif (House->IsPlayerControl) {\n\t\t\t\tClicked_As_Target();\n\t\t\t}\n\t\t\tIsWrenchVisible = true;\n\t\t}\n\t} else {\n\t\tsoundid = VOC_CLICK;\n\t}\n\tif (House->IsPlayerControl) {\n\t\tSound_Effect(soundid, Coord);\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Sell_Back -- Controls the sell back (demolish) operation.                    *\n *                                                                                             *\n *    This routine will initiate or stop the sell back process for a building. It is called    *\n *    when the player clicks on a building when the sell mode is active.                       *\n *                                                                                             *\n * INPUT:   control  -- The action to perform. 0 = turn deconstruction off, 1 = deconstruct,   *\n *                      -1 = toggle deconstruction state.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Sell_Back(int control)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->Get_Buildup_Data()) {\n\t\tbool decon = false;\n\t\tswitch (control) {\n\t\t\tcase -1:\n\t\t\t\tdecon = (Mission != MISSION_DECONSTRUCTION);\n\t\t\t\tbreak;\n\n\t\t\tcase 1:\n\t\t\t\tif (Mission == MISSION_DECONSTRUCTION) return;\n\t\t\t\tif (IsGoingToBlow) return;\n\t\t\t\tdecon = true;\n\t\t\t\tbreak;\n\n\t\t\tcase 0:\n\t\t\t\tif (Mission != MISSION_DECONSTRUCTION) return;\n\t\t\t\tdecon = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tAt this point, we know that the repair state has changed. Perform\n\t\t**\tappropriate action.\n\t\t*/\n\t\tif (decon) {\n\t\t\tAssign_Mission(MISSION_DECONSTRUCTION);\n\t\t\tCommence();\n\t\t\tif (House->IsPlayerControl) {\n\t\t\t\tClicked_As_Target();\n\t\t\t}\n\t\t}\n\t\tif (House->IsPlayerControl) {\n\t\t\tSound_Effect(VOC_CLICK);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::What_Action -- Determines action to perform if click on specified object.    *\n *                                                                                             *\n *    This routine will determine what action to perform if the mouse was clicked on the       *\n *    object specified. This determination is used to control the mouse imagery and the        *\n *    function process when the mouse button is pressed.                                       *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that, if clicked on, will control what action    *\n *                      is to be performed.                                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the ActionType that will occur if the mouse is clicked over the       *\n *          object specified while the building is currently selected.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType BuildingClass::What_Action(ObjectClass const * object) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tActionType action = TechnoClass::What_Action(object);\n\n\tif (action == ACTION_SELF) {\n\t\tint index;\n\t\tif (Class->Is_Factory() && PlayerPtr == House && *House->Factory_Counter(Class->ToBuild) > 1) {\n\t\t\tswitch (Class->ToBuild) {\n\t\t\t\tcase RTTI_INFANTRYTYPE:\n\t\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t\taction = ACTION_NONE;\n\t\t\t\t\tif (*this == STRUCT_KENNEL) {\n\t\t\t\t\t\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\t\t\tBuildingClass *bldg = Buildings.Ptr(index);\n\t\t\t\t\t\t\tif (bldg != this && bldg->Owner() == Owner() && *bldg == STRUCT_KENNEL) {\n\t\t\t\t\t\t\t\taction = ACTION_SELF;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\t\t\tBuildingClass *bldg = Buildings.Ptr(index);\n\t\t\t\t\t\t\tif (bldg != this && bldg->Owner() == Owner() && bldg->Class->ToBuild == RTTI_INFANTRYTYPE && *bldg != STRUCT_KENNEL) {\n\t\t\t\t\t\t\t\taction = ACTION_SELF;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase RTTI_NONE:\n\t\t\t\t\taction = ACTION_NONE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t} else {\n\t\t\taction = ACTION_NONE;\n\t\t}\n\t}\n\n\t/*\n\t**\tDon't allow targeting of SAM sites, even if the CTRL key\n\t**\tis held down. Also don't allow targeting if the object is too\n\t**\tfar away.\n\t*/\n\tif (action == ACTION_ATTACK && (*this == STRUCT_SAM || *this == STRUCT_AAGUN || !In_Range(object, 0))) {\n\t\taction = ACTION_NONE;\n\t}\n\n\tif (action == ACTION_MOVE) {\n\t\taction = ACTION_NONE;\n\t}\n\n\treturn(action);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::What_Action -- Determines what action will occur.                            *\n *                                                                                             *\n *    This routine examines the cell specified and returns with the action that will be        *\n *    performed if that cell were clicked upon while the building is selected.                 *\n *                                                                                             *\n * INPUT:   cell  -- The cell to examine.                                                      *\n *                                                                                             *\n * OUTPUT:  Returns the ActionType that indicates what should occur if the mouse is clicked    *\n *          on this cell.                                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType BuildingClass::What_Action(CELL cell) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tActionType action = TechnoClass::What_Action(cell);\n\n\tif (action == ACTION_MOVE && (*this != STRUCT_CONST || !Rule.IsMCVDeploy)) {\n\t\taction = ACTION_NONE;\n\t}\n\n\t/*\n\t**\tDon't allow targeting of SAM sites, even if the CTRL key\n\t**\tis held down.\n\t*/\n\tif (action == ACTION_ATTACK && Class->PrimaryWeapon != NULL && !Class->PrimaryWeapon->Bullet->IsAntiGround) {\n//\tif (action == ACTION_ATTACK && (*this == STRUCT_SAM || *this == STRUCT_AAGUN)) {\n\t\taction = ACTION_NONE;\n\t}\n\n\treturn(action);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Begin_Mode -- Begins an animation mode for the building.                     *\n *                                                                                             *\n *    This routine will start the building animating. This animation will loop indefinitely    *\n *    until explicitly stopped.                                                                *\n *                                                                                             *\n * INPUT:   bstate   -- The animation state to initiate.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The building graphic state will reflect the first stage of this animation the   *\n *             very next time it is rendered.                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *   07/02/1995 JLB : Uses normalize animation rate where applicable.                          *\n *=============================================================================================*/\nvoid BuildingClass::Begin_Mode(BStateType bstate)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tQueueBState = bstate;\n\tif (BState == BSTATE_NONE || bstate == BSTATE_CONSTRUCTION || ScenarioInit) {\n\t\tBState = bstate;\n\t\tQueueBState = BSTATE_NONE;\n\t\tBuildingTypeClass::AnimControlType const * ctrl = Fetch_Anim_Control();\n\n\t\tint rate = ctrl->Rate;\n\t\tif (Class->IsRegulated && bstate != BSTATE_CONSTRUCTION) {\n\t\t\trate = Options.Normalize_Delay(rate);\n\t\t}\n\t\tSet_Rate(rate);\n\t\tSet_Stage(ctrl->Start);\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Center_Coord -- Fetches the center coordinate for the building.              *\n *                                                                                             *\n *    This routine is used to set the center coordinate for this building.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate for the center location for the building.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE BuildingClass::Center_Coord(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(Coord_Add(Coord, CenterOffset[Class->Size]));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Docking_Coord -- Fetches the coordinate to use for docking.                  *\n *                                                                                             *\n *    This routine will return the coordinate to use when an object wishes to dock with this   *\n *    building. Normally the docking coordinate would be the center of the building.           *\n *    Exceptions to this would be the airfield and helipad. Their docking coordinates are      *\n *    offset to match the building artwork.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate to head to when trying to dock with this building.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE BuildingClass::Docking_Coord(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == STRUCT_HELIPAD) {\n\t\treturn(Coord_Add(Coord, XYP_COORD(24, 18)));\n\t}\n\tif (*this == STRUCT_AIRSTRIP) {\n\t\treturn(Coord_Add(Coord, XYP_COORD(ICON_PIXEL_W + ICON_PIXEL_W/2, 28)));\n\t}\n\treturn(TechnoClass::Docking_Coord());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Can_Fire -- Determines if this building can fire.                            *\n *                                                                                             *\n *    Use this routine to see if the building can fire its weapon.                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   target   -- The target that firing upon is desired.                                *\n *                                                                                             *\n *          which    -- Which weapon to use when firing. 0=primary, 1=secondary.               *\n *                                                                                             *\n * OUTPUT:  Returns with the fire possibility code. If firing is allowed, then FIRE_OK is      *\n *          returned. Other cases will result in appropriate fire code value that indicates    *\n *          why firing is not allowed.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/03/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nFireErrorType BuildingClass::Can_Fire(TARGET target, int which) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tFireErrorType canfire = TechnoClass::Can_Fire(target, which);\n\n\tif (canfire == FIRE_OK) {\n\n\t\t/*\n\t\t**\tDouble check to make sure that the facing is roughly toward\n\t\t**\tthe target. If the difference is too great, then firing is\n\t\t**\ttemporarily postponed.\n\t\t*/\n\t\tif (Class->IsTurretEquipped) {\n\t\t\tint diff = PrimaryFacing.Difference(Direction(TarCom));\n\t\t\tdiff = abs(diff);\n\t\t\tif (ABS(diff) > (*this == STRUCT_SAM ? 64 : 8)) {\n//\t\t\tif (ABS(diff) > 8) {\n\t\t\t\treturn(FIRE_FACING);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the turret is rotating then firing must be delayed.\n\t\t\t*/\n//\t\t\tif (PrimaryFacing.Is_Rotating()) {\n//\t\t\t\treturn(FIRE_ROTATING);\n//\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tCertain buildings cannot fire if there is insufficient power.\n\t\t*/\n\t\tif (Class->IsPowered && House->Power_Fraction() < 1) {\n\t\t\treturn(FIRE_BUSY);\n\t\t}\n\n\t\t/*\n\t\t** If an obelisk can fire, check the state of charge.\n\t\t*/\n\t\tif (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->IsElectric && !IsCharged) {\n\t\t\treturn(FIRE_BUSY);\n\t\t}\n\t}\n\treturn(canfire);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Toggle_Primary -- Toggles the primary factory state.                         *\n *                                                                                             *\n *    This routine will change the primary factory state of this building. The primary         *\n *    factory is the one that units will be produced from (by default).                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Is this building NOW the primary factory?                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/03/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BuildingClass::Toggle_Primary(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (IsLeader) {\n\t\tIsLeader = false;\n\t} else {\n\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass * building = Buildings.Ptr(index);\n\n\t\t\tif (!building->IsInLimbo && building->Owner() == Owner() && building->Class->ToBuild == Class->ToBuild) {\n\t\t\t\tif (Class->ToBuild == RTTI_INFANTRYTYPE) {\n\t\t\t\t\tif (*building == STRUCT_KENNEL && *this == STRUCT_KENNEL) {\n\t\t\t\t\t\tbuilding->IsLeader = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (*building != STRUCT_KENNEL && *this != STRUCT_KENNEL) {\n\t\t\t\t\t\t\tbuilding->IsLeader = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tbuilding->IsLeader = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tIsLeader = true;\n\t\tif ((HouseClass *)House == PlayerPtr) {\n\t\t\tSpeak(VOX_PRIMARY_SELECTED);\n\t\t}\n\t}\n\tMark(MARK_CHANGE);\n\treturn(IsLeader);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Captured -- Captures the building.                                           *\n *                                                                                             *\n *    This routine will change the owner of the building. It handles updating any related      *\n *    game systems as a result. Factories are the most prone to have great game related        *\n *    consequences when captured. This could also affect the sidebar and building ownership.   *\n *                                                                                             *\n * INPUT:   newowner -- Pointer to the house that is now the new owner.                        *\n *                                                                                             *\n * OUTPUT:  Was the capture attempt successful?                                                *\n *                                                                                             *\n * WARNINGS:   Capturing could fail if the house is already owned by the one specified or      *\n *             the building isn't allowed to be captured.                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/03/1995 JLB : Created.                                                                 *\n *   07/05/1995 JLB : Fixed production problem with capturing enemy buildings.                 *\n *=============================================================================================*/\nbool BuildingClass::Captured(HouseClass * newowner)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsCaptureable && newowner != House) {\n#ifdef TOFIX\n\t\tswitch (Owner()) {\n\t\t\tcase HOUSE_GOOD:\n\t\t\t\tSpeak(VOX_GDI_CAPTURED);\n\t\t\t\tbreak;\n\n\t\t\tcase HOUSE_BAD:\n\t\t\t\tSpeak(VOX_NOD_CAPTURED);\n\t\t\t\tbreak;\n\t\t}\n#endif\n\n\t\t/*\n\t\t** Make sure the capturer isn't spying on his own building, and if\n\t\t** it was a radar facility, update the target house's RadarSpied field.\n\t\t*/\n\t\tif (SpiedBy & (1<<(newowner->Class->House)) ) {\n\t\t\tSpiedBy -= (1<<(newowner->Class->House));\n\t\t\tif (*this == STRUCT_RADAR) {\n\t\t\t\tUpdate_Radar_Spied();\n\t\t\t}\n\t\t}\n\n\t\tif (House == PlayerPtr) {\n\t\t\tMap.PowerClass::IsToRedraw = true;\n\t\t\tMap.Flag_To_Redraw(false);\n\t\t}\n\n\t\tif (*this == STRUCT_GAP) {\n\t\t\tRemove_Gap_Effect();\n\t\t\tIsJamming = false;\n\t\t\tArm = 0;\n\t\t}\n\n\t\t/*\n\t\t** Add this building to the list of buildings captured this game. For internet stats purposes.\n\t\t*/\n\t\tif (Session.Type == GAME_INTERNET) {\n\t\t\tnewowner->CapturedBuildings->Increment_Unit_Total (Class->Type);\n\t\t}\n\n\t\tHouse->Adjust_Power(-Power_Output());\n\t\tLastStrength = 0;\n\t\tHouse->Adjust_Drain(-Class->Drain);\n\t\tint booty = House->Adjust_Capacity(-Class->Capacity, true);\n\n\t\t/*\n\t\t**\tIf there is something loaded, then it gets captured as well.\n\t\t*/\n\t\tTechnoClass * tech = Attached_Object();\n\t\tif (tech) tech->Captured(newowner);\n\n\t\t/*\n\t\t**\tIf something isn't technically attached, but is sitting on this\n\t\t**\tbuilding for another reason (e.g., helicopter on helipad), then it\n\t\t**\tgets captured as well.\n\t\t*/\n\t\ttech = Contact_With_Whom();\n\t\tif (tech) {\n\t\t\tif (Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER && (::Distance(tech->Center_Coord(), Docking_Coord()) < 0x0040 ||\n\t\t\t\t(tech->What_Am_I() == RTTI_AIRCRAFT && ((AircraftClass *)tech)->Class->IsFixedWing && ((AircraftClass *)tech)->In_Which_Layer() == LAYER_GROUND)) ) {\n\t\t\t\ttech->Captured(newowner);\n\t\t\t} else {\n\t\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tAbort any computer production in progress.\n\t\t*/\n\t\tif (Factory) {\n\t\t\tdelete (FactoryClass *)Factory;\n\t\t\tFactory = 0;\n\t\t}\n\n\t\t/*\n\t\t**\tDecrement the factory counter for the original owner.\n\t\t*/\n\t\tHouse->Active_Remove(this);\n\n\t\t/*\n\t\t**\tFlag that both owners now need to update their buildable lists.\n\t\t*/\n\t\tHouse->IsRecalcNeeded = true;\n\t\tnewowner->IsRecalcNeeded = true;\n\t\tHouseClass * oldowner = House;\n\t\tTARGET tocap = As_Target();\n\n\t\tIsCaptured = true;\n\t\tTechnoClass::Captured(newowner);\n\n\t\toldowner->ToCapture = tocap;\n\t\toldowner->Recalc_Center();\n\t\tHouse->Recalc_Center();\n\t\tif (House->ToCapture == As_Target()) {\n\t\t\tHouse->ToCapture = TARGET_NONE;\n\t\t}\n\n\t\tSmudgeType bib;\n\t\tCELL cell = Coord_Cell(Coord);\n\t\tif (Class->Bib_And_Offset(bib, cell)) {\n\t\t\tSmudgeClass * smudge = new SmudgeClass(bib);\n\t\t\tif (smudge) {\n\t\t\t\tsmudge->Disown(cell);\n\t\t\t\tdelete smudge;\n\t\t\t}\n#ifdef FIXIT_CAPTURE_BIB\n\t\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\t\tnew SmudgeClass(bib, Cell_Coord(cell), Class->IsBase ? House->Class->House : HOUSE_NONE);\n\t\t\t} else {\n\t\t\t\tnew SmudgeClass(bib, Cell_Coord(cell), House->Class->House);\n\t\t\t}\n#else\n\t\t\tnew SmudgeClass(bib, Cell_Coord(cell), House->Class->House);\n#endif\n\t\t}\n\n\t\tHouse->Harvested(booty);\n\t\tHouse->Stole(Refund_Amount());\n\n\t\t/*\n\t\t**\tIncrement the factory count for the new owner.\n\t\t*/\n\t\tHouse->Active_Add(this);\n\n\t\tIsRepairing = false;\n\t\tGrand_Opening(true);\n\n\t\tMark(MARK_CHANGE);\n\n\t\t/*\n\t\t**\tPerform a look operation when captured if it was the player\n\t\t**\tthat performed the capture.\n\t\t*/\n\t\tif (House == PlayerPtr) {\n\t\t\tLook(false);\n\t\t}\n\t\t/*\n\t\t** If it was spied upon by the player who just captured it, clear the\n\t\t** spiedby flag for that house.\n\t\t*/\n\t\tif (SpiedBy & (1 << (newowner->Class->House))) {\n\t\t\tSpiedBy &= ~(1 << (newowner->Class->House));\n\t\t}\n\n\t\t/*\n\t\t** Update the new building's colors on the radar map.\n\t\t*/\n\t\tshort const * offset = Occupy_List();\n\t\twhile (*offset != REFRESH_EOL) {\n\t\t\tCELL cell = Coord_Cell(Coord) + *offset++;\n\t\t\tMap.Radar_Pixel(cell);\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Sort_Y -- Returns the building coordinate used for sorting.                  *\n *                                                                                             *\n *    The coordinate value returned from this function should be used for sorting purposes.    *\n *    It has special offset adjustment applied so that vehicles don't overlap (as much).       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a coordinate value suitable to be used for sorting.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *   06/19/1995 JLB : Handles buildings that come with bibs built-in.                          *\n *=============================================================================================*/\nCOORDINATE BuildingClass::Sort_Y(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == STRUCT_REPAIR) {\n\t\treturn(Coord);\n\t}\n\tif (*this == STRUCT_BARRACKS /*|| *this == STRUCT_POWER*/) {\n\t\treturn(Center_Coord());\n\t}\n\tif (*this == STRUCT_REFINERY) {\n\t\treturn(Center_Coord());\n\t}\n\n\t/*\n\t**\tMines need to bias their sort location such that they are typically drawn\n\t**\tbefore any objects that might overlap them.\n\t*/\n\tif (*this == STRUCT_AVMINE || *this == STRUCT_APMINE) {\n\t\treturn(Coord_Move(Center_Coord(), DIR_N, CELL_LEPTON_H));\n\t}\n\n\treturn(Coord_Add(Center_Coord(), XY_Coord(0, (Class->Height()*256)/3)));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Can_Enter_Cell -- Determines if building can be placed down.                 *\n *                                                                                             *\n *    This routine will determine if the building can be placed down at the location           *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   cell  -- The cell to examine. This is usually the cell of the upper left corner    *\n *                   of the building if it were to be placed down.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the move legality value for placement at the location specified. This *\n *          will either be MOVE_OK or MOVE_NO.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nMoveType BuildingClass::Can_Enter_Cell(CELL cell, FacingType) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == STRUCT_CONST && IsDown) {\n\t\treturn(Map[cell].Is_Clear_To_Build(Class->Speed) ? MOVE_OK : MOVE_NO);\n\t}\n\n\tif (!Debug_Map && ScenarioInit == 0 && Session.Type == GAME_NORMAL && House->IsPlayerControl && !Map[cell].IsMapped) {\n\t\treturn(MOVE_NO);\n\t}\n\n\treturn(Class->Legal_Placement(cell) ? MOVE_OK : MOVE_NO);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Can_Demolish -- Can the player demolish (sell back) the building?            *\n *                                                                                             *\n *    Determines if the player can sell this building. Selling is possible if the building     *\n *    is not currently in construction or deconstruction animation.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Can the building be demolished at this time?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *   07/01/1995 JLB : If there is no buildup data, then the building can't be sold.            *\n *   07/17/1995 JLB : Cannot sell a refinery that has a harvester attached.                    *\n *=============================================================================================*/\nbool BuildingClass::Can_Demolish(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsUnsellable) return(false);\n\n\tif (Class->Get_Buildup_Data() && BState != BSTATE_CONSTRUCTION && Mission != MISSION_DECONSTRUCTION && Mission != MISSION_CONSTRUCTION) {\n\t\tif (*this == STRUCT_REFINERY && Is_Something_Attached()) return(false);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mission_Guard -- Handles guard mission for combat buildings.                 *\n *                                                                                             *\n *    Buildings that can attack are given this mission. They will wait until a suitable target *\n *    comes within range and then launch into the attack mission. Buildings that have no       *\n *    weaponry will just sit in this routine forever.                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before this routine will be called *\n *          again.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::Mission_Guard(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tIf this building has a weapon, then search for a target to attack. When\n\t**\ta target is found, switch into attack mode to deal with the threat.\n\t*/\n\tif (Is_Weapon_Equipped()) {\n\n\t\t/*\n\t\t**\tWeapon equipped buildings are ALWAYS ready to launch into another mission if\n\t\t**\tthey are sitting around in guard mode.\n\t\t*/\n\t\tIsReadyToCommence = true;\n\n\t\t/*\n\t\t**\tIf there is no target available, then search for one.\n\t\t*/\n\t\tif (!Target_Legal(TarCom)) {\n\t\t\tThreatType threat = THREAT_NORMAL;\n\t\t\tAssign_Target(Greatest_Threat(threat));\n\t\t}\n\n\t\t/*\n\t\t**\tThere is a valid target. Switch into attack mode right away.\n\t\t*/\n\t\tif (Target_Legal(TarCom)) {\n\t\t\tAssign_Mission(MISSION_ATTACK);\n\t\t\tCommence();\n\t\t\treturn(1);\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tThis is the very simple state machine that basically does\n\t\t**\tnothing. This is the mode that non weapon equipped buildings\n\t\t**\tare normally in.\n\t\t*/\n\t\tenum {\n\t\t\tINITIAL_ENTRY,\n\t\t\tIDLE\n\t\t};\n\t\tswitch (Status) {\n\t\t\tcase INITIAL_ENTRY:\n\t\t\t\tBegin_Mode(BSTATE_IDLE);\n\t\t\t\tStatus = IDLE;\n\t\t\t\tbreak;\n\n\t\t\tcase IDLE:\n\t\t\t\t/*\n\t\t\t\t**\tSpecial case to break out of guard mode if this is a repair\n\t\t\t\t**\tfacility and there is a customer waiting at the grease pit.\n\t\t\t\t*/\n\t\t\t\tif (*this == STRUCT_REPAIR &&\n\t\t\t\t\tIn_Radio_Contact() &&\n\t\t\t\t\tContact_With_Whom()->Is_Techno() &&\n\t\t\t\t\t((TechnoClass *)Contact_With_Whom())->Mission == MISSION_ENTER &&\n\t\t\t\t\tDistance(Contact_With_Whom()) < 0x0040 &&\n\t\t\t\t\tTransmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {\n\n\t\t\t\t\tAssign_Mission(MISSION_REPAIR);\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (*this == STRUCT_REPAIR) {\n\t\t\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n\t\t} else {\n\t\t\treturn(MissionControl[Mission].Normal_Delay() * 3 + Random_Pick(0, 2));\n\t\t}\n\t}\n\treturn(MissionControl[Mission].AA_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mission_Construction -- Handles mission construction.                        *\n *                                                                                             *\n *    This routine will handle mission construction. When this mission is complete, the        *\n *    building will begin normal operation.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine        *\n *          again.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::Mission_Construction(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tenum {\n\t\tINITIAL,\n\t\tDURING\n\t};\n\tswitch (Status) {\n\t\tcase INITIAL:\n\t\t\tBegin_Mode(BSTATE_CONSTRUCTION);\n\t\t\tTransmit_Message(RADIO_BUILDING);\n\t\t\tif (House->IsPlayerControl) {\n\t\t\t\tSound_Effect(VOC_CONSTRUCTION, Coord);\n\t\t\t}\n\t\t\tStatus = DURING;\n\t\t\tbreak;\n\n\t\tcase DURING:\n\t\t\tif (IsReadyToCommence) {\n\n\t\t\t\t/*\n\t\t\t\t**\tWhen construction is complete, then transmit this\n\t\t\t\t**\tto the construction yard so that it can stop its\n\t\t\t\t**\tconstruction animation.\n\t\t\t\t*/\n\t\t\t\tTransmit_Message(RADIO_COMPLETE);\t\t// \"I'm finished.\"\n\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\t\t// \"You're free.\"\n\t\t\t\tBegin_Mode(BSTATE_IDLE);\n\t\t\t\tGrand_Opening();\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\tPrimaryFacing = Class->StartFace;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mission_Deconstruction -- Handles building deconstruction.                   *\n *                                                                                             *\n *    This state machine is only used when the building is deconstructing as a result of       *\n *    selling.  When this mission is finished, the building will no longer exist.              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine again. *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *   08/13/1995 JLB : Enable selling of units on a repair bay.                                 *\n *   08/20/1995 JLB : Scatters infantry from scattered starting points.                        *\n *=============================================================================================*/\nint BuildingClass::Mission_Deconstruction(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tAlways force repair off.\n\t*/\n\tRepair(0);\n\n\tenum {\n\t\tINITIAL,\n\t\tHOLDING,\n\t\tDURING\n\t};\n\tswitch (Status) {\n\t\tcase INITIAL:\n\n\t\t\t/*\n\t\t\t**\tSpecial check for the repair bay which has the ability to sell\n\t\t\t**\twhatever is on it. If there is something on the repair bay, then\n\t\t\t**\tit will be sold. If there is nothing on the repair bay, then\n\t\t\t**\tthe repair bay itself will be sold.\n\t\t\t*/\n\t\t\tif ( (*this == STRUCT_REPAIR || *this == STRUCT_AIRSTRIP) && Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER && Distance(Contact_With_Whom()) < 0x0080) {\n\t\t\t\tTechnoClass * tech = Contact_With_Whom();\n\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\tif (IsOwnedByPlayer) Speak(VOX_UNIT_SOLD);\n\t\t\t\ttech->Sell_Back(1);\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\treturn(1);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Selling off a shipyard or sub pen may cause attached ships\n\t\t\t** who are repairing themselves to discontinue repairs.\n\t\t\t*/\n\t\t\tif (*this == STRUCT_SHIP_YARD || *this == STRUCT_SUB_PEN) {\n\t\t\t\tfor (int index = 0; index < Vessels.Count(); index++) {\n\t\t\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\t\t\tif (obj && !obj->IsInLimbo && obj->House == House) {\n\t\t\t\t\t\tif (obj->IsSelfRepairing) {\n\t\t\t\t\t\t\tif (::Distance(Center_Coord(), obj->Center_Coord()) < 0x0200) {\n\t\t\t\t\t\t\t\tobj->IsSelfRepairing = false;\n\t\t\t\t\t\t\t\tobj->IsToSelfRepair = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tIsReadyToCommence = false;\n\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n\t\t\tStatus = HOLDING;\n\t\t\tbreak;\n\n\t\tcase HOLDING:\n\t\t\tif (!IsTethered) {\n\n\t\t\t\t/*\n\t\t\t\t**\tThe crew will evacuate from the building. The number of crew\n\t\t\t\t**\tmembers leaving is equal to the unrecovered cost of the building\n\t\t\t\t**\tdivided by 100 (the typical cost of a minigunner infantryman).\n\t\t\t\t*/\n\t\t\t\tif (!Target_Legal(ArchiveTarget) || !Rule.IsMCVDeploy || *this != STRUCT_CONST) {\n\t\t\t\t\tint count = How_Many_Survivors();\n\t\t\t\t\tbool engine = false;\n\n\t\t\t\t\twhile (count) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tEnsure that the player only gets ONE engineer and not from a captured\n\t\t\t\t\t\t**\tconstruction yard.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tInfantryType typ = Crew_Type();\n\t\t\t\t\t\twhile (typ == INFANTRY_RENOVATOR && engine) {\n\t\t\t\t\t\t\ttyp = Crew_Type();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (typ == INFANTRY_RENOVATOR) engine = true;\n\n\t\t\t\t\t\tInfantryClass * infantry = 0;\n\t\t\t\t\t\tif (typ != INFANTRY_NONE) infantry = new InfantryClass(typ, House->Class->House);\n\t\t\t\t\t\tif (infantry != NULL) {\n\t\t\t\t\t\t\tScenarioInit++;\n\t\t\t\t\t\t\tCOORDINATE coord = Coord_Add(Center_Coord(), XYP_COORD(0, -12));\n\t\t\t\t\t\t\tcoord = Map[coord].Closest_Free_Spot(coord, false);\n\n\t\t\t\t\t\t\tif (infantry->Unlimbo(coord, DIR_N)) {\n\t\t\t\t\t\t\t\tif (infantry->Class->IsNominal) infantry->IsTechnician = true;\n\t\t\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t\t\t\tinfantry->Scatter(0, true);\n\t\t\t\t\t\t\t\tScenarioInit++;\n\t\t\t\t\t\t\t\tinfantry->Assign_Mission(MISSION_GUARD_AREA);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdelete infantry;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcount--;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (House->IsPlayerControl) {\n\t\t\t\t\tSound_Effect(VOC_CASHTURN, Coord);\n\t\t\t\t}\n\t\t\t\tStatus = DURING;\n\t\t\t\tBegin_Mode(BSTATE_CONSTRUCTION);\n\t\t\t\tDetach_All(true);\n\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\tIsReadyToCommence = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n\t\t\tbreak;\n\n\t\tcase DURING:\n\t\t\tif (IsReadyToCommence) {\n\t\t\t\tHouse->IsRecalcNeeded = true;\n\t\t\t\tif (IsOwnedByPlayer) Speak(VOX_STRUCTURE_SOLD);\n\n\t\t\t\t/*\n\t\t\t\t**\tConstruction yards that deconstruct, really just revert back\n\t\t\t\t**\tto an MCV.\n\t\t\t\t*/\n\t\t\t\tif (Target_Legal(ArchiveTarget) && *this == STRUCT_CONST && House->IsHuman && Strength > 0) {\n\t\t\t\t\tScenarioInit++;\n\t\t\t\t\tUnitClass * unit = new UnitClass(UNIT_MCV, House->Class->House);\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t\tif (unit != NULL) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tUnlimbo the MCV onto the map. The MCV should start in the same\n\t\t\t\t\t\t**\thealth condition that the construction yard was in.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tfixed ratio = Health_Ratio();\n\t\t\t\t\t\tint money = Refund_Amount();\n\t\t\t\t\t\tTARGET arch = ArchiveTarget;\n\t\t\t\t\t\tCOORDINATE place = Coord_Snap(Adjacent_Cell(Coord, DIR_SE));\n\n\t\t\t\t\t\tdelete this;\n\n\t\t\t\t\t\tif (unit->Unlimbo(place, DIR_SW)) {\n\t\t\t\t\t\t\tunit->Strength = unit->Class_Of().MaxStrength * ratio;\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tLift the move destination from the building and assign\n\t\t\t\t\t\t\t**\tit to the unit.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Target_Legal(arch)) {\n\t\t\t\t\t\t\t\tunit->Assign_Destination(arch);\n\t\t\t\t\t\t\t\tunit->Assign_Mission(MISSION_MOVE);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf, for some strange reason, the MCV could not be placed on the\n\t\t\t\t\t\t\t**\tmap, then give the player some money to compensate.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tHouse->Refund_Money(money);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tHouse->Refund_Money(Refund_Amount());\n\t\t\t\t\t\tdelete this;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Selling off a gap generator will cause the cells it affects\n\t\t\t\t\t** to stop being jammed.\n\t\t\t\t\t*/\n\t\t\t\t\tif (*this == STRUCT_GAP) {\n\t\t\t\t\t\tRemove_Gap_Effect();\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tA sold building still counts as a kill, but it just isn't directly\n\t\t\t\t\t**\tattributed to the enemy.\n\t\t\t\t\t*/\n\t\t\t\t\tWhoLastHurtMe = HOUSE_NONE;\n\t\t\t\t\tRecord_The_Kill(NULL);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThe player gets part of the money back for the sell.\n\t\t\t\t\t*/\n\t\t\t\t\tHouse->Refund_Money(Refund_Amount());\n\t\t\t\t\tHouse->Stole(-Refund_Amount());\n\t\t\t\t\tLimbo();\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tFinally, delete the building from the game.\n\t\t\t\t\t*/\n\t\t\t\t\tdelete this;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mission_Attack -- Handles attack mission for building.                       *\n *                                                                                             *\n *    Buildings that can attack are processed by this attack mission state machine.            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine        *\n *          again.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *   02/22/1996 JLB : SAM doesn't lower back into ground.                                      *\n *=============================================================================================*/\nint BuildingClass::Mission_Attack(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == STRUCT_SAM) {\n\t\tswitch (Status) {\n\n\t\t\t/*\n\t\t\t**\tThis is the target tracking state of the launcher. It will rotate\n\t\t\t**\tto face the current TarCom of the launcher.\n\t\t\t*/\n\t\t\tcase SAM_READY:\n\t\t\t\tif ((Class->IsPowered && House->Power_Fraction() < 1) || IsJammed) {\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\t\t\t\tif (!Target_Legal(TarCom) || !Is_Target_Aircraft(TarCom) || As_Aircraft(TarCom)->Height == 0) {\n\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\tStatus = SAM_READY;\n\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\tCommence();\n\t\t\t\t\treturn(1);\n\t\t\t\t} else {\n\t\t\t\t\tif (!PrimaryFacing.Is_Rotating()) {\n\t\t\t\t\t\tDirType facing = Direction(TarCom);\n\t\t\t\t\t\tif (PrimaryFacing.Difference(facing)) {\n\t\t\t\t\t\t\tPrimaryFacing.Set_Desired(facing);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tStatus = SAM_FIRING;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\t/*\n\t\t\t**\tThe launcher is in the process of firing.\n\t\t\t*/\n\t\t\tcase SAM_FIRING:\n\t\t\t\tif (!Target_Legal(TarCom) || !Is_Target_Aircraft(TarCom) || As_Aircraft(TarCom)->Height == 0) {\n\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\tStatus = SAM_READY;\n\t\t\t\t} else {\n\t\t\t\t\tFireErrorType error = Can_Fire(TarCom, 0);\n\t\t\t\t\tif (error == FIRE_ILLEGAL || error == FIRE_CANT || error == FIRE_RANGE) {\n\t\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\t\tStatus = SAM_READY;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (error == FIRE_FACING) {\n\t\t\t\t\t\t\tStatus = SAM_READY;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (error == FIRE_OK) {\n\t\t\t\t\t\t\t\tFire_At(TarCom, 0);\n\t\t\t\t\t\t\t\tFire_At(TarCom, 1);\n\t\t\t\t\t\t\t\tStatus = SAM_READY;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\treturn(MissionControl[Mission].AA_Delay() + Random_Pick(0, 2));\n\n\t}\n\n\tif (!Target_Legal(TarCom)) {\n\t\tAssign_Target(TARGET_NONE);\n\t\tAssign_Mission(MISSION_GUARD);\n\t\tCommence();\n\t\treturn(1);\n\t}\n\n\tint primary = What_Weapon_Should_I_Use(TarCom);\n\tIsReadyToCommence = true;\n\tswitch (Can_Fire(TarCom, primary)) {\n\t\tcase FIRE_ILLEGAL:\n\t\tcase FIRE_CANT:\n\t\tcase FIRE_RANGE:\n\t\tcase FIRE_AMMO:\n\t\t\tAssign_Target(TARGET_NONE);\n\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\tCommence();\n\t\t\tbreak;\n\n\t\tcase FIRE_FACING:\n\t\t\tPrimaryFacing.Set_Desired(Direction(TarCom));\n\t\t\treturn(2);\n\n\t\tcase FIRE_REARM:\n\t\t\tPrimaryFacing.Set_Desired(Direction(TarCom));\n\t\t\treturn(Arm);\n\n\t\tcase FIRE_BUSY:\n\t\t\treturn(1);\n\n\t\tcase FIRE_CLOAKED:\n\t\t\tDo_Uncloak();\n\t\t\tbreak;\n\n\t\tcase FIRE_OK:\n\t\t\tFire_At(TarCom, primary);\n\t\t\treturn(1);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tPrimaryFacing.Set_Desired(Direction(TarCom));\n\treturn(1);\n//\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mission_Harvest -- Handles refinery unloading harvesters.                    *\n *                                                                                             *\n *    This state machine handles the refinery when it unloads the harvester.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine        *\n *          again.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::Mission_Harvest(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tenum {\n\t\tINITIAL,\t\t\t\t\t// Dock the Tiberium cannister.\n\t\tWAIT_FOR_DOCK,\t\t\t// Waiting for docking to complete.\n\t\tMIDDLE,\t\t\t\t\t// Offload \"bails\" of tiberium.\n\t\tWAIT_FOR_UNDOCK\t\t// Waiting for undocking to complete.\n\t};\n\tswitch (Status) {\n\t\tcase INITIAL:\n\t\t\tStatus = WAIT_FOR_DOCK;\n\t\t\tbreak;\n\n\t\tcase WAIT_FOR_DOCK:\n\t\t\tif (IsReadyToCommence) {\n\t\t\t\tIsReadyToCommence = false;\n\t\t\t\tStatus = MIDDLE;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase MIDDLE:\n\t\t\tif (IsReadyToCommence) {\n\t\t\t\tIsReadyToCommence = false;\n\n\t\t\t\t/*\n\t\t\t\t**\tForce any bib squatters to scatter.\n\t\t\t\t*/\n\t\t\t\tMap[Adjacent_Cell(Coord_Cell(Center_Coord()), DIR_S)].Incoming(0, true, true);\n\n\t\t\t\tFootClass * techno = Attached_Object();\n\t\t\t\tif (techno) {\n\t\t\t\t\tint bail = techno->Offload_Tiberium_Bail();\n\n\t\t\t\t\tif (bail) {\n\t\t\t\t\t\tHouse->Harvested(bail);\n\t\t\t\t\t\tif (techno->Tiberium_Load() > 0) {\n\t\t\t\t\t\t\treturn(1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tStatus = WAIT_FOR_UNDOCK;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WAIT_FOR_UNDOCK:\n\t\t\tif (IsReadyToCommence) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDetach harvester and go back into idle state.\n\t\t\t\t*/\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mission_Repair -- Handles the repair (active) state for building.            *\n *                                                                                             *\n *    This state machine is used when the building is active in some sort of repair or         *\n *    construction mode. The construction yard will animate. The repair facility will repair   *\n *    anything that it docked on it.                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine again. *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *   06/25/1995 JLB : Handles repair facility                                                  *\n *   07/29/1995 JLB : Repair rate is controlled by power rating.                               *\n *=============================================================================================*/\nint BuildingClass::Mission_Repair(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == STRUCT_CONST) {\n\t\tenum {\n\t\t\tINITIAL,\n\t\t\tDURING\n\t\t};\n\t\tswitch (Status) {\n\t\t\tcase INITIAL:\n\t\t\t\tBegin_Mode(BSTATE_ACTIVE);\n\t\t\t\tStatus = DURING;\n\t\t\t\tbreak;\n\n\t\t\tcase DURING:\n\t\t\t\tif (!In_Radio_Contact()) {\n\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\treturn(1);\n\t}\n\n\tif (*this == STRUCT_REPAIR) {\n\t\tenum {\n\t\t\tINITIAL,\n\t\t\tIDLE,\n\t\t\tDURING\n\t\t};\n\t\tswitch (Status) {\n\t\t\tcase INITIAL:\n\t\t\t\t{\n\t\t\t\t\tif (!In_Radio_Contact()) {\n\t\t\t\t\t\tBegin_Mode(BSTATE_IDLE);\n\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t}\n\t\t\t\t\tIsReadyToCommence = false;\n\t\t\t\t\tint distance = 0x10;\n\t\t\t\t\tTechnoClass *tech = Contact_With_Whom();\n\n\t\t\t\t\t/*\n\t\t\t\t\t** BG: If the unit to repair is an aircraft, and the aircraft is\n\t\t\t\t\t** fixed-wing, and it's landed, be much more liberal with the\n\t\t\t\t\t** distance check.  Fixed-wing aircraft are very inaccurate with\n\t\t\t\t\t** their landings.\n\t\t\t\t\t*/\n\t\t\t\t\tif (tech->What_Am_I() == RTTI_AIRCRAFT) {\n\t\t\t\t\t\tif ( ((AircraftClass *)tech)->Class->IsFixedWing &&\n\t\t\t\t\t\t\t((AircraftClass *)tech)->In_Which_Layer() == LAYER_GROUND) {\n\t\t\t\t\t\t\tdistance = 0x80;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER && Distance(Contact_With_Whom()) < distance) {\n\t\t\t\t\t\tStatus = IDLE;\n\t\t\t\t\t\treturn(TICKS_PER_SECOND/4);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tcase IDLE:\n\t\t\t\tif (!In_Radio_Contact()) {\n\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\n\t\t\t\tif (Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {\n\t\t\t\t\tTechnoClass * radio = Contact_With_Whom();\n\n\t\t\t\t\tif ( ((radio->Health_Ratio() < Rule.ConditionGreen) ||\n\t\t\t\t\t\t   (radio->What_Am_I() == RTTI_UNIT && *(UnitClass *)radio == UNIT_MINELAYER))\n\t\t\t\t\t\t\t&& Transmit_Message(RADIO_REPAIR) == RADIO_ROGER) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf the object over the repair bay is marked as useless, then\n\t\t\t\t\t\t**\tsell it back to get some money.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (radio->IsUseless) {\n\t\t\t\t\t\t\tif (!radio->House->IsHuman) {\n\t\t\t\t\t\t\t\tradio->Sell_Back(1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tStatus = INITIAL;\n\t\t\t\t\t\t\tIsReadyToCommence = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (IsOwnedByPlayer) Speak(VOX_REPAIRING);\n\t\t\t\t\t\t\tStatus = DURING;\n\t\t\t\t\t\t\tBegin_Mode(BSTATE_ACTIVE);\n\t\t\t\t\t\t\tIsReadyToCommence = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n//\t\t\t\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n///*BG*/\t\t\t\t\tif(radio->Health_Ratio() >= Rule.ConditionGreen) {\n//\t\t\t\t\t\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n//\t\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase DURING:\n\t\t\t\tif (!In_Radio_Contact()) {\n\t\t\t\t\tBegin_Mode(BSTATE_IDLE);\n\t\t\t\t\tStatus = IDLE;\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tCheck to see if the repair light blink has completed and the attached\n\t\t\t\t**\tunit is not doing something else. If these conditions are favorable,\n\t\t\t\t**\tthe repair can proceed another step.\n\t\t\t\t*/\n\t\t\t\tif (IsReadyToCommence && Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {\n\t\t\t\t\tIsReadyToCommence = false;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tTell the attached unit to repair one step. It will respond with how\n\t\t\t\t\t**\tit fared.\n\t\t\t\t\t*/\n\t\t\t\t\tswitch (Transmit_Message(RADIO_REPAIR)) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tThe repair step proceeded smoothly. Proceed normally with the\n\t\t\t\t\t\t**\trepair process.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RADIO_ROGER:\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tThe repair operation was aborted because of some reason. Presume\n\t\t\t\t\t\t**\tthat the reason is because of low cash.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RADIO_CANT:\n\t\t\t\t\t\t\tif (IsOwnedByPlayer) Speak(VOX_NO_CASH);\n\t\t\t\t\t\t\tBegin_Mode(BSTATE_IDLE);\n\t\t\t\t\t\t\tStatus = IDLE;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tThe repair step resulted in a completely repaired unit.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RADIO_ALL_DONE:\n\t\t\t\t\t\t\tif (IsOwnedByPlayer) Speak(VOX_UNIT_REPAIRED);\n//\t\t\t\t\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n\t\t\t\t\t\t\tBegin_Mode(BSTATE_IDLE);\n\t\t\t\t\t\t\tStatus = IDLE;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tThe repair step could not be completed because this unit is already\n\t\t\t\t\t\t**\tat full strength.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RADIO_NEGATIVE:\n\t\t\t\t\t\tdefault:\n//\t\t\t\t\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n\t\t\t\t\t\t\tBegin_Mode(BSTATE_IDLE);\n\t\t\t\t\t\t\tStatus = IDLE;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\treturn(MissionControl[Mission].Normal_Delay());\n\t}\n\n\tif (*this == STRUCT_HELIPAD || *this == STRUCT_AIRSTRIP) {\n\t\tenum {\n\t\t\tINITIAL,\n\t\t\tDURING\n\t\t};\n\t\tswitch (Status) {\n\t\t\tcase INITIAL:\n\t\t\t\tif (Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER && Transmit_Message(RADIO_PREPARED) == RADIO_NEGATIVE) {\n\t\t\t\t\tBegin_Mode(BSTATE_ACTIVE);\n\t\t\t\t\tContact_With_Whom()->Assign_Mission(MISSION_SLEEP);\n\t\t\t\t\tStatus = DURING;\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\tbreak;\n\n\t\t\tcase DURING:\n\t\t\t\tif (IsReadyToCommence) {\n\t\t\t\t\tif (!In_Radio_Contact() || Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_NEGATIVE) {\n\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (Transmit_Message(RADIO_PREPARED) == RADIO_ROGER) {\n\t\t\t\t\t\tContact_With_Whom()->Assign_Mission(MISSION_GUARD);\n\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (Transmit_Message(RADIO_RELOAD) != RADIO_ROGER) {\n\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t\tContact_With_Whom()->Assign_Mission(MISSION_GUARD);\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfixed pfrac = Saturate(House->Power_Fraction(), 1);\n\t\t\t\t\t\tif (pfrac < fixed::_1_2) pfrac = fixed::_1_2;\n\t\t\t\t\t\tint time = Inverse(pfrac) * Rule.ReloadRate * TICKS_PER_MINUTE;\n//\t\t\t\t\t\tint time = Bound((int)(TICKS_PER_SECOND * Saturate(House->Power_Fraction(), 1)), 0, TICKS_PER_SECOND);\n//\t\t\t\t\t\ttime = (TICKS_PER_SECOND*3) - time;\n\t\t\t\t\t\tIsReadyToCommence = false;\n\t\t\t\t\t\treturn(time);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\treturn(3);\n\t}\n\treturn(TICKS_PER_SECOND);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mission_Missile -- State machine for nuclear missile launch.                 *\n *                                                                                             *\n *    This handles the Temple of Nod launching its nuclear missile.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of frames to delay before calling this routine again.      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Commented.                                                               *\n *=============================================================================================*/\nint BuildingClass::Mission_Missile(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == STRUCT_ADVANCED_TECH) {\n\t\tenum {\n\t\t\tDOOR_OPENING,\n\t\t\tLAUNCH_UP,\n\t\t\tSATELLITE_DEPLOY,\n\t\t\tDONE_LAUNCH\n\t\t};\n\n\t\tswitch (Status) {\n\n\t\t\t/*\n\t\t\t** The initial case is responsible for starting the door\n\t\t\t** opening on the building, the missile rising, and smoke broiling.\n\t\t\t*/\n\t\t\tcase DOOR_OPENING:\n\t\t\t\t{\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\tCOORDINATE door = Coord_Move(Center_Coord(), (DirType)0xC0, 0x30);\n\t\t\t\t\tAnimClass * sput = new AnimClass(ANIM_SPUTDOOR, door);\n\t\t\t\t\tif (sput) {\n\t\t\t\t\t\tIsReadyToCommence = false;\n\t\t\t\t\t\tStatus = LAUNCH_UP;\n\t\t\t\t\t\tAnimToTrack = sput->As_Target();\n\t\t\t\t\t}\n#else\n\t\t\t\t\tIsReadyToCommence = false;\n\t\t\t\t\tCOORDINATE door = Coord_Move(Center_Coord(), (DirType)0xC0, 0x30);\n\t\t\t\t\tAnimClass * sput = new AnimClass(ANIM_SPUTDOOR, door);\n\t\t\t\t\tStatus = LAUNCH_UP;\n\t\t\t\t\tAnimToTrack = sput->As_Target();\n\t\t\t\t\treturn(1);\n#endif\n\t\t\t\t}\n\n\t\t\t/*\n\t\t\t** Once the smoke has been going for a little while this\n\t\t\t** actually handles launching the missile into the air.\n\t\t\t*/\n\t\t\tcase LAUNCH_UP:\n\t\t\t\t{\n\t\t\t\t\tAnimClass * sput = As_Animation(AnimToTrack);\n\t\t\t\t\tif (sput) {\n\t\t\t\t\t\tif (sput->Fetch_Stage() >= 19) {\n\t\t\t\t\t\t\tCELL center = Coord_Cell(Center_Coord());\n\t\t\t\t\t\t\tCELL cell = XY_Cell( Cell_X(center), 1);\n\t\t\t\t\t\t\tTARGET targ = ::As_Target(cell);\n\n\t\t\t\t\t\t\tBulletClass * bullet = new BulletClass(BULLET_GPS_SATELLITE, targ, this, 200, WARHEAD_FIRE, MPH_ROCKET);\n\t\t\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\t\t\tCOORDINATE launch = Coord_Move(Center_Coord(), (DirType)0xC0, 0x30);\n\t\t\t\t\t\t\t\tif (!bullet->Unlimbo(launch, DIR_N)) {\n\t\t\t\t\t\t\t\t\tdelete bullet;\n\t\t\t\t\t\t\t\t\tbullet = NULL;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(1);\n\t\t}\n\t}\n\n\tif (*this == STRUCT_MSLO) {\n\t\tenum {\n\t\t\tINITIAL,\n\t\t\tDOOR_OPENING,\n\t\t\tLAUNCH_UP,\n\t\t\tLAUNCH_DOWN,\n\t\t\tDONE_LAUNCH\n\t\t};\n\n\t\tswitch (Status) {\n\n\t\t\t/*\n\t\t\t** The initial case is responsible for starting the door\n\t\t\t** opening on the building.\n\t\t\t*/\n\t\t\tcase INITIAL:\n\t\t\t\tIsReadyToCommence = false;\n\t\t\t\tBegin_Mode(BSTATE_ACTIVE);\t// open the door\n\t\t\t\tStatus = DOOR_OPENING;\n\t\t\t\treturn(1);\n\n\t\t\t/*\n\t\t\t** This polls for the case when the door is actually open and\n\t\t\t** then kicks off the missile smoke.\n\t\t\t*/\n\t\t\tcase DOOR_OPENING:\n\t\t\t\tif (IsReadyToCommence) {\n\t\t\t\t\tBegin_Mode(BSTATE_AUX1);\t// hold the door open\n\t\t\t\t\tStatus = LAUNCH_UP;\n\t\t\t\t\treturn(14);\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\t/*\n\t\t\t** Once the smoke has been going for a little while this\n\t\t\t** actually handles launching the missile into the air.\n\t\t\t*/\n\t\t\tcase LAUNCH_UP:\n\t\t\t\t{\n\t\t\t\t\tCELL center = Coord_Cell(Center_Coord());\n\t\t\t\t\tCELL cell = XY_Cell( Cell_X(center), 1);\n\t\t\t\t\tTARGET targ = ::As_Target(cell);\n\t\t\t\t\tBulletClass * bullet = new BulletClass(BULLET_NUKE_UP, targ, this, 200, WARHEAD_HE, MPH_VERY_FAST);\n\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\tCOORDINATE launch = Coord_Move(Center_Coord(), (DirType)28, 0xA0);\n\t\t\t\t\t\tif (!bullet->Unlimbo(launch, DIR_N)) {\n\t\t\t\t\t\t\tdelete bullet;\n\t\t\t\t\t\t\tbullet = NULL;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\tSpeak(VOX_ABOMB_LAUNCH);\n\t\t\t\t\t\tStatus = LAUNCH_DOWN;\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Hack: If it's the artificial nukes, don't let the bullets come down (as\n\t\t\t\t\t\t** they're the only ones that blow up).  We know it's artificial if you're\n\t\t\t\t\t\t** at tech level 10 or below, because you can't build the nuclear silo until\n\t\t\t\t\t\t** tech level 15 or so.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (House->Control.TechLevel <= 10) {\n\t\t\t\t\t\t\treturn(6);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbullet = new BulletClass(BULLET_NUKE_DOWN, ::As_Target(House->NukeDest), this, 200, WARHEAD_NUKE, MPH_VERY_FAST);\n\t\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\t\tint celly = Cell_Y(House->NukeDest);\n\t\t\t\t\t\t\tcelly -= 64;\n\t\t\t\t\t\t\tif (celly < 1) celly = 1;\n\t\t\t\t\t\t\tCOORDINATE start = Cell_Coord(XY_Cell(Cell_X(House->NukeDest), celly));\n\t\t\t\t\t\t\tif (!bullet->Unlimbo(start, DIR_S)) {\n\t\t\t\t\t\t\t\tdelete bullet;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(8 * TICKS_PER_SECOND);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\t/*\n\t\t\t** Once the missile is in the air, this handles waiting for\n\t\t\t** the missile to be off the screen and then launching one down\n\t\t\t** over the target.\n\t\t\t*/\n\t\t\tcase LAUNCH_DOWN:\n\t\t\t\t{\n\t\t\t\t\tBegin_Mode(BSTATE_AUX2);\t// start the door closing\n\n#ifdef OBSOLETE\n\t\t\t\t\t/*\n\t\t\t\t\t** Hack: If it's the artificial nukes, don't let the bullets come down (as\n\t\t\t\t\t** they're the only ones that blow up).  We know it's artificial if you're\n\t\t\t\t\t** at tech level 10 or below, because you can't build the nuclear silo until\n\t\t\t\t\t** tech level 15 or so.\n\t\t\t\t\t*/\n\t\t\t\t\tif (House->Control.TechLevel <= 10) {\n\t\t\t\t\t\tStatus = DONE_LAUNCH;\n\t\t\t\t\t\treturn(6);\n\t\t\t\t\t}\n\t\t\t\t\tBulletClass * bullet = new BulletClass(BULLET_NUKE_DOWN, ::As_Target(House->NukeDest), this, 200, WARHEAD_NUKE, MPH_VERY_FAST);\n\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\tint celly = Cell_Y(House->NukeDest);\n\t\t\t\t\t\tcelly -= 15;\n\t\t\t\t\t\tif (celly < 1) celly = 1;\n\t\t\t\t\t\tCOORDINATE start = Cell_Coord(XY_Cell(Cell_X(House->NukeDest), celly));\n\t\t\t\t\t\tif (!bullet->Unlimbo(start, DIR_S)) {\n\t\t\t\t\t\t\tdelete bullet;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (bullet) {\n#endif\n\t\t\t\t\t\tStatus = DONE_LAUNCH;\n\t\t\t\t\t\treturn(6);\n\t\t\t\t\t}\n#ifdef OBSOLETE\n\t\t\t\t}\n\t\t\t\treturn(1);\n#endif\n\n\t\t\t/*\n\t\t\t** Once the missile is done launching this handles allowing\n\t\t\t** the building to sit there with its door closed.\n\t\t\t*/\n\t\t\tcase DONE_LAUNCH:\n\t\t\t\tBegin_Mode(BSTATE_IDLE);\t// keep the door closed.\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\treturn(60);\n\t\t}\n\t}\n\treturn(MissionControl[Mission].Normal_Delay());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Revealed -- Reveals the building to the specified house.                     *\n *                                                                                             *\n *    This routine will reveal the building to the specified house. It will handle updating    *\n *    the sidebar for player owned buildings. A player owned building that hasn't been         *\n *    revealed, is in a state of pseudo-limbo. It cannot be used for any of its special        *\n *    abilities even though it exists on the map for all other purposes.                       *\n *                                                                                             *\n * INPUT:   house -- The house that this building is being revealed to.                        *\n *                                                                                             *\n * OUTPUT:  Was this building revealed by this procedure?                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BuildingClass::Revealed(HouseClass * house)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (TechnoClass::Revealed(house)) {\n\n\t\tif (!ScenarioInit) {\n\t\t\tHouse->JustBuiltStructure = Class->Type;\n\t\t\tHouse->IsBuiltSomething = true;\n\t\t}\n\t\tHouse->IsRecalcNeeded = true;\n\n\t\t/*\n\t\t**\tPerform any grand opening here so that in the scenarios where a player\n\t\t**\towned house is not yet revealed, it won't be reflected in the sidebar\n\t\t**\tselection icons.\n\t\t*/\n\t\tif (!In_Radio_Contact() && House->IsHuman && Mission != MISSION_CONSTRUCTION) {\n\t\t\tGrand_Opening();\n\t\t} else {\n\t\t\tif (!In_Radio_Contact() && !House->IsHuman && house == House && Mission != MISSION_CONSTRUCTION) {\n\t\t\t\tGrand_Opening();\n\t\t\t}\n\t\t}\n\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Enter_Idle_Mode -- The building will enter its idle mode.                    *\n *                                                                                             *\n *    This routine is called when the exact mode of the building isn't known. By examining     *\n *    the building's condition, this routine will assign an appropriate mission.               *\n *                                                                                             *\n * INPUT:   initial  -- This this being called during scenario init?                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Enter_Idle_Mode(bool initial)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tAssign an appropriate mission for the building. If the ScenarioInit flag is true, then\n\t**\tthis must be an initial building. Start such buildings in idle state. For other buildings\n\t**\tit indicates that it is being placed during game play and thus it must start in\n\t**\tthe \"construction\" mission.\n\t*/\n\tMissionType mission = MISSION_GUARD;\n\n\n\tif (!initial || ScenarioInit || Debug_Map) {\n\t\tBegin_Mode(BSTATE_IDLE);\n\t\tmission = MISSION_GUARD;\n\t} else {\n\t\tBegin_Mode(BSTATE_CONSTRUCTION);\n\t\tmission = MISSION_CONSTRUCTION;\n\t}\n\tAssign_Mission(mission);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Pip_Count -- Determines \"full\" pips to display for building.                 *\n *                                                                                             *\n *    This routine will determine the number of pips that should be filled in when rendering   *\n *    the building.                                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the number of pips to display as filled in.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::Pip_Count(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(Class->Max_Pips() * House->Tiberium_Fraction());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Death_Announcement -- Announce the death of this building.                   *\n *                                                                                             *\n *    This routine is called when the building is destroyed by \"unnatural\" means. Typically    *\n *    as a result of combat. If the building is known to the player, then it should be         *\n *    announced.                                                                               *\n *                                                                                             *\n * INPUT:   source   -- The object most directly responsible for the building's death.         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Death_Announcement(TechnoClass const * source) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (source != NULL && House->IsPlayerControl) {\n\t\tSpeak(VOX_STRUCTURE_DESTROYED);\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Fire_Direction -- Fetches the direction of firing.                           *\n *                                                                                             *\n *    This routine will return with the default direction to use when firing from this         *\n *    building. This is the facing of the turret except for the case of non-turret equipped    *\n *    buildings that have a weapon (e.g., guard tower).                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the default firing direction for this building.                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nDirType BuildingClass::Fire_Direction(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsTurretEquipped) {\n\t\treturn(PrimaryFacing.Current());\n\t}\n\treturn(Direction(TarCom));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Remap_Table -- Fetches the remap table to use for this building.             *\n *                                                                                             *\n *    Use this routine to fetch the remap table to use.  This override function is needed      *\n *    because the default remap table for techno objects presumes the object is a unit.        *\n *    Buildings aren't units.                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the proper remap table to use for this building.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid const * BuildingClass::Remap_Table(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(House->Remap_Table(IsBlushing, Class->Remap));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mission_Unload -- Handles the unload mission for a building.                 *\n *                                                                                             *\n *    This is the unload mission for a building. This really only applies to the weapon's      *\n *    factory, since it needs the sophistication of an unload mission due to the door          *\n *    animation.                                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine        *\n *          again.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::Mission_Unload(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == STRUCT_WEAP) {\n\t\tCELL cell = Coord_Cell(Coord) + Class->ExitList[0];\n\t\tCOORDINATE coord = Cell_Coord(cell);\n\t\tCellClass * cellptr = &Map[cell];\n\t\tenum {\n\t\t\tINITIAL,\n\t\t\tCLEAR_BIB,\n\t\t\tOPEN,\n\t\t\tLEAVE,\n\t\t\tCLOSE\n\t\t};\n\t\tenum {\n\t\t\tDOOR_STAGES = 5,\n\t\t\tDOOR_RATE = 8\n\t\t};\n\t\tUnitClass * unit;\n\t\tswitch (Status) {\n\t\t\t/*\n\t\t\t**\tStart the door opening.\n\t\t\t*/\n\t\t\tcase INITIAL:\n//\t\t\t\tif (cellptr->Cell_Techno()) {\n//\t\t\t\t\tcellptr->Incoming(0, true);\n//\t\t\t\t}\n\t\t\t\tunit = (UnitClass *)Contact_With_Whom();\n\t\t\t\tif (unit) {\n\t\t\t\t\tunit->Assign_Mission(MISSION_GUARD);\n\t\t\t\t\tunit->Commence();\n\t\t\t\t}\n\t\t\t\tOpen_Door(DOOR_RATE, DOOR_STAGES);\n\t\t\t\tStatus = CLEAR_BIB;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tNow that the occupants can peek out the door, they will tell\n\t\t\t**\teveryone that could be blocking the way, that they should\n\t\t\t**\tscatter away.\n\t\t\t*/\n\t\t\tcase CLEAR_BIB:\n\t\t\t\tif (cellptr->Cell_Techno()) {\n\t\t\t\t\tcellptr->Incoming(0, true, true);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tScatter everything around the weapon's factory door.\n\t\t\t\t\t*/\n\t\t\t\t\tfor (FacingType f = FACING_FIRST; f < FACING_COUNT; f++) {\n\t\t\t\t\t\tCellClass * cptr = &cellptr->Adjacent_Cell(f);\n\t\t\t\t\t\tif (cptr->Cell_Building() == NULL) {\n\t\t\t\t\t\t\tcptr->Incoming(coord, true, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tStatus = OPEN;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tWhen the door is finally open and the way is clear, tell the\n\t\t\t**\tunit to drive out.\n\t\t\t*/\n\t\t\tcase OPEN:\n\t\t\t\tif (Is_Door_Open()) {\n\t\t\t\t\tunit = (UnitClass *)Contact_With_Whom();\n\t\t\t\t\tif (unit) {\n\t\t\t\t\t\tunit->Assign_Mission(MISSION_MOVE);\n\n\t\t\t\t\t\tif (House->IQ >= Rule.IQGuardArea) {\n\t\t\t\t\t\t\tunit->Assign_Mission(MISSION_GUARD_AREA);\n\t\t\t\t\t\t\tunit->ArchiveTarget = ::As_Target(House->Where_To_Go(unit));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tunit->Force_Track(DriveClass::OUT_OF_WEAPON_FACTORY, coord);\n//\t\t\t\t\t\tunit->Force_Track(DriveClass::OUT_OF_WEAPON_FACTORY, Adjacent_Cell(Adjacent_Cell(Center_Coord(), FACING_S), FACING_S));\n\t\t\t\t\t\tunit->Set_Speed(128);\n\t\t\t\t\t\tStatus = LEAVE;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tClose_Door(DOOR_RATE, DOOR_STAGES);\n\t\t\t\t\t\tStatus = CLOSE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tWait until the unit has completely left the building.\n\t\t\t*/\n\t\t\tcase LEAVE:\n\t\t\t\tif (!IsTethered) {\n\t\t\t\t\tClose_Door(DOOR_RATE, DOOR_STAGES);\n\t\t\t\t\tStatus = CLOSE;\n\t\t\t\t} else {\n\n//\t\t\t\t\tif (In_Radio_Contact() && !((FootClass *)Contact_With_Whom())->IsDriving) {\n//\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n//\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tWait while the door closes.\n\t\t\t*/\n\t\t\tcase CLOSE:\n\t\t\t\tif (Is_Door_Closed()) {\n\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n\t}\n\n\tAssign_Mission(MISSION_GUARD);\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Power_Output -- Fetches the current power output from this building.         *\n *                                                                                             *\n *    This routine will return the current power output for this building. The power output    *\n *    is adjusted according to the damage level of the building.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the current power output for this building.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::Power_Output(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->Power) {\n\t\treturn(Class->Power * fixed(LastStrength, Class->MaxStrength));\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Detach -- Handles target removal from the game system.                       *\n *                                                                                             *\n *    This routine is called when the specified target is about to be removed from the game    *\n *    system.                                                                                  *\n *                                                                                             *\n * INPUT:   target   -- The target to be removed from this building's targeting computer.      *\n *                                                                                             *\n *          all      -- Is the target about to be completely eliminated?                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Detach(TARGET target, bool all)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tTechnoClass::Detach(target, all);\n\tif (target == WhomToRepay) {\n\t\tWhomToRepay = TARGET_NONE;\n\t}\n\tif (target == AnimToTrack) {\n\t\tAnimToTrack = TARGET_NONE;\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Crew_Type -- This determines the crew that this object generates.            *\n *                                                                                             *\n *    When selling very cheap buildings (such as the silo), a technician will pop out since    *\n *    generating minigunners would be overkill -- the player could use this loophole to        *\n *    gain an advantage.                                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the infantry type that this building will generate as a survivor.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nInfantryType BuildingClass::Crew_Type(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tswitch (Class->Type) {\n\t\tcase STRUCT_STORAGE:\n\t\t\tif (Percent_Chance(50)) {\n\t\t\t\treturn(INFANTRY_C1);\n\t\t\t} else {\n\t\t\t\treturn(INFANTRY_C7);\n\t\t\t}\n\n\t\tcase STRUCT_CONST:\n\t\t\tif (!IsCaptured && House->IsHuman && Percent_Chance(25)) {\n\t\t\t\treturn(INFANTRY_RENOVATOR);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase STRUCT_KENNEL:\n\t\t\tif (Percent_Chance(50)) {\n\t\t\t\treturn(INFANTRY_DOG);\n\t\t\t} else {\n\t\t\t\treturn(INFANTRY_NONE);\n\t\t\t}\n\n\t\tcase STRUCT_TENT:\n\t\tcase STRUCT_BARRACKS:\n\t\t\treturn(INFANTRY_E1);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(TechnoClass::Crew_Type());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Detach_All -- Possibly abandons production according to factory type.        *\n *                                                                                             *\n *    When this routine is called, it indicates that the building is about to be destroyed     *\n *    or captured. In such a case any production it may be doing, must be abandoned.           *\n *                                                                                             *\n * INPUT:   all   -- Is the object about the be completely destroyed?                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Detach_All(bool all)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tIf it is producing something, then it must be abandoned.\n\t*/\n\tif (Factory) {\n\t\tFactory->Abandon();\n\t\tdelete (FactoryClass *)Factory;\n\t\tFactory = 0;\n\t}\n\n\t/*\n\t** If the owner HouseClass is building something, and this building can\n\t** build that thing, we may be the last building for that house that can\n\t** build that thing; if so, abandon production of it.\n\t*/\n\tif (House) {\n\t\tFactoryClass * factory = House->Fetch_Factory(Class->ToBuild);\n\n\t\t/*\n\t\t**\tIf a factory was found, then temporarily disable this building and then\n\t\t**\tdetermine if any object that is being produced can still be produced. If\n\t\t**\tnot, then the object being produced must be abandoned.\n\t\t*/\n\t\tif (factory) {\n\t\t\tTechnoClass * object = factory->Get_Object();\n\t\t\tIsInLimbo = true;\n\t\t\tif (object && !object->Techno_Type_Class()->Who_Can_Build_Me(true, false, House->Class->House)) {\n\t\t\t\tHouse->Abandon_Production(Class->ToBuild);\n\t\t\t}\n\t\t\tIsInLimbo = false;\n\t\t}\n\t}\n\n\tTechnoClass::Detach_All(all);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Flush_For_Placement -- Handles clearing a zone for object placement.         *\n *                                                                                             *\n *    This routine is used to clear the way for placement of the specified object (usually     *\n *    a building). If there are friendly units blocking the placement area, they are told      *\n *    to scatter. Enemy blocking units are attacked.                                           *\n *                                                                                             *\n * INPUT:   techno   -- Pointer to the object that is desired to be placed.                    *\n *                                                                                             *\n *          cell     -- The cell that placement wants to occur at.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1995 JLB : Created.                                                                 *\n *   09/27/1995 JLB : Revised to use type class function.                                      *\n *=============================================================================================*/\nbool BuildingClass::Flush_For_Placement(TechnoClass * techno, CELL cell)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (techno) {\n\t\treturn (((BuildingTypeClass const &)techno->Class_Of()).Flush_For_Placement(cell, House));\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Find_Exit_Cell -- Find a clear location to exit an object from this building *\n *                                                                                             *\n *    This routine is called when the building needs to discharge a unit. It will find a       *\n *    nearby (adjacent) cell that is clear enough for the specified object to enter. Typical   *\n *    use of this routine is when the airfield disgorges its cargo.                            *\n *                                                                                             *\n * INPUT:   techno   -- Pointer to the object that wishes to exit this building.               *\n *                                                                                             *\n * OUTPUT:  Returns with the cell number to use for object placement. If no free location      *\n *          could be found, then zero (0) is returned.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *   02/20/1996 JLB : Added default case for exit cell calculation.                            *\n *=============================================================================================*/\nCELL BuildingClass::Find_Exit_Cell(TechnoClass const * techno) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tCELL const * ptr;\n\tCELL origin = Coord_Cell(Coord);\n\n\tptr = Class->ExitList;\n\tif (ptr != NULL) {\n\t\twhile (*ptr != REFRESH_EOL) {\n\t\t\tCELL cell = origin + *ptr++;\n\t\t\tif (Map.In_Radar(cell) && techno->Can_Enter_Cell(cell) == MOVE_OK) {\n\t\t\t\treturn(cell);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tint x1, x2;\n\t\tint y1, y2;\n\t\tCELL cell;\n\n\t\ty1 = -1;\n\t\ty2 = Class->Height();\n\t\tfor (x1 = -1; x1 <= Class->Width(); x1++) {\n\t\t\tcell = origin + x1 + (y1 * MAP_CELL_W);\n\t\t\tif (Map.In_Radar(cell) && techno->Can_Enter_Cell(cell) == MOVE_OK) {\n\t\t\t\treturn(cell);\n\t\t\t}\n\t\t\tcell = origin + x1 + (y2 * MAP_CELL_W);\n\t\t\tif (Map.In_Radar(cell) && techno->Can_Enter_Cell(cell) == MOVE_OK) {\n\t\t\t\treturn(cell);\n\t\t\t}\n\t\t}\n\n\t\tx1 = -1;\n\t\tx2 = Class->Width();\n\t\tfor (y1 = -1; y1 <= Class->Height(); y1++) {\n\t\t\tcell = origin + (y1 * MAP_CELL_W) + x1;\n\t\t\tif (Map.In_Radar(cell) && techno->Can_Enter_Cell(cell) == MOVE_OK) {\n\t\t\t\treturn(cell);\n\t\t\t}\n\t\t\tcell = origin + (y1 * MAP_CELL_W) + x2;\n\t\t\tif (Map.In_Radar(cell) && techno->Can_Enter_Cell(cell) == MOVE_OK) {\n\t\t\t\treturn(cell);\n\t\t\t}\n\t\t}\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Can_Player_Move -- Can this building be moved?                               *\n *                                                                                             *\n *    This routine answers the question 'can this building be moved?' Typically, only the      *\n *    construction yard can be moved and it does this by undeploying back into a MCV.          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Can the building move to a new location under player control?                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BuildingClass::Can_Player_Move(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(*this == STRUCT_CONST);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Exit_Coord -- Determines location where object will leave it.                *\n *                                                                                             *\n *    This routine will return the coordinate where an object that wishes to leave the         *\n *    building will exit at.                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate that the object should be created at.                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE BuildingClass::Exit_Coord(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->ExitCoordinate) {\n\t\treturn(Coord_Add(Coord, Class->ExitCoordinate));\n\t}\n\treturn(TechnoClass::Exit_Coord());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Check_Point -- Fetches the landing checkpoint for the given flight pattern.  *\n *                                                                                             *\n *    Use this routine to coordinate a landing operation. The specified checkpoint is          *\n *    converted into a cell number. The landing aircraft should fly over that cell and then    *\n *    request the next check point.                                                            *\n *                                                                                             *\n * INPUT:   cp    -- The check point to convert to a cell number.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the cell that the aircraft should fly over in order to complete       *\n *          that portion of the landing pattern.                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL BuildingClass::Check_Point(CheckPointType cp) const\n{\n\tCELL xoffset = 6;\t\t// Downwind offset.\n\tCELL yoffset = 5;\t\t// Crosswind offset.\n\tCELL cell = Coord_Cell(Center_Coord());\n\n\tswitch (cp) {\n\t\tcase CHECK_STACK:\n\t\t\txoffset = 0;\n\t\t\tbreak;\n\n\t\tcase CHECK_CROSSWIND:\n\t\t\tyoffset = 0;\n\t\t\tbreak;\n\n\t\tcase CHECK_DOWNWIND:\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tif ((Cell_X(cell) - Map.MapCellX) > Map.MapCellWidth/2)  {\n\t\txoffset = -xoffset;\n\t}\n\n\tif ((Cell_Y(cell) - Map.MapCellY) > Map.MapCellHeight/2)  {\n\t\tyoffset = -yoffset;\n\t}\n\n\treturn(XY_Cell(Cell_X(cell)+xoffset, Cell_Y(cell)+yoffset));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Update_Radar_Spied - set house's RadarSpied field appropriately.\t\t\t\t  *\n *                                                                                             *\n *    This routine is called when a radar facility is captured or destroyed.  It fills in the  *\n *    RadarSpied field of the house based on whether there's a spied-upon radar facility or not*\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  House->RadarSpied field gets set appropriately.\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/22/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Update_Radar_Spied(void)\n{\n\tHouse->RadarSpied = 0;\n\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\tBuildingClass * obj = Buildings.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == House) {\n\t\t\tif (*obj == STRUCT_RADAR /* || *obj == STRUCT_EYE */) {\n\t\t\t\tHouse->RadarSpied |= obj->SpiedBy;\n\t\t\t}\n\t\t}\n\t}\n\tMap.RadarClass::Flag_To_Redraw(true);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Read_INI -- Reads buildings from INI file.                                   *\n *                                                                                             *\n *    This is the basic scenario initialization of building function. It                       *\n *    is called when reading the scenario startup INI file and it handles                      *\n *    creation of all specified buildings.                                                     *\n *                                                                                             *\n *    INI entry format:                                                                        *\n *      Housename, Typename, Strength, Cell, Facing, Triggername                               *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the loaded INI file data.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Read_INI(CCINIClass & ini)\n{\n\tBuildingClass\t\t\t* b;\t\t\t// Working unit pointer.\n\tHousesType\t\t\t\tbhouse;\t\t// Building house.\n\tStructType\t\t\t\tclassid;\t\t// Building type.\n\tCELL\t\t\t\t\t\tcell;\t\t\t// Cell of building.\n\tchar\t\t\t\t\t\tbuf[128];\n\tchar\t\t\t\t\t\t* trigname;\t// building's trigger's name\n\n\n\tint len = ini.Entry_Count(INI_Name());\n\tfor (int index = 0; index < len; index++) {\n\t\tchar const * entry = ini.Get_Entry(INI_Name(), index);\n\n\t\t/*\n\t\t**\tGet a building entry.\n\t\t*/\n\t\tini.Get_String(INI_Name(), entry, NULL, buf, sizeof(buf));\n\n\t\t/*\n\t\t**\t1st token: house name.\n\t\t*/\n\t\tbhouse = HouseTypeClass::From_Name(strtok(buf, \",\"));\n\n\t\t/*\n\t\t**\t2nd token: building name.\n\t\t*/\n\t\tclassid = BuildingTypeClass::From_Name(strtok(NULL, \",\"));\n\n\t\tif (bhouse != HOUSE_NONE && classid != STRUCT_NONE) {\n\t\t\tint\tstrength;\n\t\t\tDirType facing;\n\n\t\t\t/*\n\t\t\t**\t3rd token: strength.\n\t\t\t*/\n\t\t\tstrength = atoi(strtok(NULL, \",\"));\n\n\t\t\t/*\n\t\t\t**\t4th token: cell #.\n\t\t\t*/\n\t\t\tcell = atoi(strtok(NULL, \",\"));\n\n\t\t\t/*\n\t\t\t**\t5th token: facing.\n\t\t\t*/\n\t\t\tfacing = (DirType)atoi(strtok(NULL, \",\"));\n\n\t\t\t/*\n\t\t\t**\t6th token: triggername (can be NULL).\n\t\t\t*/\n\t\t\ttrigname = strtok(NULL, \",\");\n\n\t\t\tbool sellable = false;\n\t\t\tchar * token_pointer = strtok(NULL, \",\");\n\t\t\tif (token_pointer) {\n\t\t\t\tsellable = atoi(token_pointer);\n\t\t\t}\n\n\t\t\tbool rebuild = false;\n\t\t\ttoken_pointer = strtok(NULL, \",\");\n\t\t\tif (token_pointer) {\n\t\t\t\trebuild = atoi(token_pointer);\n\t\t\t}\n\n\t\t\tb = new BuildingClass(classid, bhouse);\n\t\t\tif (b) {\n\n\t\t\t\tTriggerTypeClass * tp = TriggerTypeClass::From_Name(trigname);\n\t\t\t\tif (tp) {\n\t\t\t\t\tTriggerClass * tt = Find_Or_Make(tp);\n\t\t\t\t\tif (tt) {\n\t\t\t\t\t\ttt->AttachCount++;\n\t\t\t\t\t\tb->Trigger = tt;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tb->IsAllowedToSell = sellable;\n\t\t\t\tb->IsToRebuild = rebuild;\n\t\t\t\tb->IsToRepair = rebuild || *b == STRUCT_CONST;\n\n\t\t\t\tif (b->Unlimbo(Cell_Coord(cell), facing)) {\n\t\t\t\t\tstrength = min(strength, 0x100);\n\t\t\t\t\tstrength = b->Class->MaxStrength * fixed(strength, 256);\n\t\t\t\t\tb->Strength = strength;\n\t\t\t\t\tif (b->Strength > b->Class->MaxStrength-3) b->Strength = b->Class->MaxStrength;\n\t\t\t\t\tb->IsALemon = false;\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the building could not be unlimboed on the map, then this indicates\n\t\t\t\t\t**\ta serious error. Delete the building.\n\t\t\t\t\t*/\n\t\t\t\t\tdelete b;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Write_INI -- Write out the building data to the INI file specified.          *\n *                                                                                             *\n *    This will store the building data (as it relates to scenario initialization) to the      *\n *    INI database specified.                                                                  *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database that the building data will be stored to.   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Write_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tFirst, clear out all existing building data from the ini file.\n\t*/\n\tini.Clear(INI_Name());\n\n\t/*\n\t**\tWrite the data out.\n\t*/\n\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\tBuildingClass * building = Buildings.Ptr(index);\n\t\tif (!building->IsInLimbo) {\n\t\t\tchar\tuname[10];\n\t\t\tchar\tbuf[127];\n\n\t\t\tsprintf(uname, \"%d\", index);\n\t\t\tsprintf(buf, \"%s,%s,%d,%u,%d,%s,%d,%d\",\n\t\t\t\tbuilding->House->Class->IniName,\n\t\t\t\tbuilding->Class->IniName,\n\t\t\t\tbuilding->Health_Ratio()*256,\n\t\t\t\tCoord_Cell(building->Coord),\n\t\t\t\tbuilding->PrimaryFacing.Current(),\n\t\t\t\tbuilding->Trigger.Is_Valid() ? building->Trigger->Class->IniName : \"None\",\n\t\t\t\tbuilding->IsAllowedToSell,\n\t\t\t\tbuilding->IsToRebuild\n\t\t\t\t);\n\t\t\tini.Put_String(INI_Name(), uname, buf);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Target_Coord -- Return the coordinate to use when firing on this building.   *\n *                                                                                             *\n *    This routine will determine the \"center\" location of this building for purposes of       *\n *    targeting. Usually, this location is somewhere near the foundation of the building.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate to use when firing upon this building (or trying to    *\n *          walk onto it).                                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE BuildingClass::Target_Coord(void) const\n{\n\tCOORDINATE coord = Center_Coord();\n\n\tif (Class->FoundationFace != FACING_NONE) {\n\t\treturn(Adjacent_Cell(coord, Class->FoundationFace));\n\t}\n\treturn(coord);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Factory_AI -- Handle factory production and initiation.                      *\n *                                                                                             *\n *    Some building (notably the computer controlled ones) can have a factory object attached. *\n *    This routine handles processing of that factory and also detecting when production       *\n *    should begin in order to initiate production.                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per building per game logic loop.                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Factory_AI(void)\n{\n\t/*\n\t**\tHandle any production tied to this building. Only computer controlled buildings have\n\t**\tproduction attached to the building itself. The player uses the sidebar interface for\n\t**\tall production control.\n\t*/\n\tif (Factory.Is_Valid() && Factory->Has_Completed() && PlacementDelay == 0) {\n\t\tTechnoClass * product = Factory->Get_Object();\n//\t\tFactoryClass * fact = Factory;\n\n\t\tswitch (Exit_Object(product)) {\n\n\t\t\t/*\n\t\t\t**\tIf the object could not leave the factory, then either request\n\t\t\t**\ta transport, place the (what must be a) building using another method, or\n\t\t\t**\tabort the production and refund money.\n\t\t\t*/\n\t\t\tcase 0:\n\t\t\t\tFactory->Abandon();\n\t\t\t\tdelete (FactoryClass *)Factory;\n\t\t\t\tFactory = 0;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tExiting this building is prevented by some temporary blockage. Wait\n\t\t\t**\ta bit before trying again.\n\t\t\t*/\n\t\t\tcase 1:\n\t\t\t\tPlacementDelay = TICKS_PER_SECOND*3;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tThe object was successfully sent from this factory. Inform the house\n\t\t\t**\ttracking logic that the requested object has been produced.\n\t\t\t*/\n\t\t\tcase 2:\n\t\t\t\tswitch (product->What_Am_I()) {\n\t\t\t\t\tcase RTTI_VESSEL:\n\t\t\t\t\t\tHouse->JustBuiltVessel = ((VesselClass*)product)->Class->Type;\n\t\t\t\t\t\tHouse->IsBuiltSomething = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase RTTI_UNIT:\n\t\t\t\t\t\tHouse->JustBuiltUnit = ((UnitClass*)product)->Class->Type;\n\t\t\t\t\t\tHouse->IsBuiltSomething = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t\t\tHouse->JustBuiltInfantry = ((InfantryClass*)product)->Class->Type;\n\t\t\t\t\t\tHouse->IsBuiltSomething = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase RTTI_BUILDING:\n\t\t\t\t\t\tHouse->JustBuiltStructure = ((BuildingClass*)product)->Class->Type;\n\t\t\t\t\t\tHouse->IsBuiltSomething = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\t\t\tHouse->JustBuiltAircraft = ((AircraftClass*)product)->Class->Type;\n\t\t\t\t\t\tHouse->IsBuiltSomething = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n//\t\t\t\tfact->Completed();\n\t\t\t\tFactory->Completed();\n//\t\t\t\tdelete fact;\n\t\t\t\tdelete (FactoryClass *)Factory;\n\t\t\t\tFactory = 0;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tPick something to create for this factory.\n\t*/\n\tif (House->IsStarted && Mission != MISSION_CONSTRUCTION && Mission != MISSION_DECONSTRUCTION) {\n\n\t\t/*\n\t\t**\tBuildings that produce other objects have special factory logic handled here.\n\t\t*/\n\t\tif (Class->ToBuild != RTTI_NONE) {\n\t\t\tif (Factory.Is_Valid()) {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf production has halted, then just abort production and make the\n\t\t\t\t**\tfunds available for something else.\n\t\t\t\t*/\n\t\t\t\tif (PlacementDelay == 0 && !Factory->Is_Building()) {\n\t\t\t\t\tFactory->Abandon();\n\t\t\t\t\tdelete (FactoryClass *)Factory;\n\t\t\t\t\tFactory = 0;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tOnly look to start production if there is at least a small amount of\n\t\t\t\t**\tmoney available. In cases where there is no practical money left, then\n\t\t\t\t**\tproduction can never complete -- don't bother starting it.\n\t\t\t\t*/\n\t\t\t\tif (House->IsStarted && House->Available_Money() > 10) {\n\t\t\t\t\tTechnoTypeClass const * techno = House->Suggest_New_Object(Class->ToBuild, *this == STRUCT_KENNEL);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf a suitable object type was selected for production, then start\n\t\t\t\t\t**\tproducing it now.\n\t\t\t\t\t*/\n\t\t\t\t\tif (techno != NULL) {\n\t\t\t\t\t\tFactory = new FactoryClass;\n\t\t\t\t\t\tif (Factory.Is_Valid()) {\n\t\t\t\t\t\t\tif (!Factory->Set(*techno, *House)) {\n\t\t\t\t\t\t\t\tdelete (FactoryClass *)Factory;\n\t\t\t\t\t\t\t\tFactory = 0;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tHouse->Production_Begun(Factory->Get_Object());\n\t\t\t\t\t\t\t\tFactory->Start();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Rotation_AI -- Process any turret rotation required of this building.        *\n *                                                                                             *\n *    Some buildings have a turret and this routine handles processing the turret rotation.    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per building per game logic loop.                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *   10/27/1996 JLB : Rotation does not occur if power and no power avail.                     *\n *=============================================================================================*/\nvoid BuildingClass::Rotation_AI(void)\n{\n\tif (Class->IsTurretEquipped &&\n\t\t\tMission != MISSION_CONSTRUCTION &&\n\t\t\tMission != MISSION_DECONSTRUCTION &&\n\t\t\t(!Class->IsPowered || House->Power_Fraction() >= 1)) {\n\n\t\t/*\n\t\t**\tRotate turret to match desired facing.\n\t\t*/\n\t\tif (PrimaryFacing.Is_Rotating()) {\n\t\t\tif (PrimaryFacing.Rotation_Adjust(Class->ROT)) {\n\t\t\t\tMark(MARK_CHANGE);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Charging_AI -- Handles the special charging logic for Tesla coils.           *\n *                                                                                             *\n *    This handles the special logic required of the charging tesla coil. It requires special  *\n *    processing since its charge up is dependant upon the target and power surplus of the     *\n *    owning house.                                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Charging_AI(void)\n{\n\tif (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->IsElectric && BState != BSTATE_CONSTRUCTION) {\n\t\tif (Target_Legal(TarCom) && House->Power_Fraction() >= 1) {\n\t\t\tif (!IsCharged) {\n\t\t\t\tif (IsCharging) {\n//\t\t\t\t\tif (stagechange) {\n\t\t\t\t\t\tMark(MARK_CHANGE);\n\t\t\t\t\t\tif (Fetch_Stage() >= 9) {\n\t\t\t\t\t\t\tIsCharged = true;\n\t\t\t\t\t\t\tIsCharging = false;\n\t\t\t\t\t\t\tSet_Rate(0);\n\t\t\t\t\t\t}\n//\t\t\t\t\t}\n\t\t\t\t} else if (!Arm) {\n\t\t\t\t\tIsCharged = false;\n\t\t\t\t\tIsCharging = true;\n\t\t\t\t\tSet_Stage(0);\n\t\t\t\t\tSet_Rate(3);\n\t\t\t\t\tSound_Effect(VOC_TESLA_POWER_UP, Coord);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (IsCharging || IsCharged) {\n\t\t\t\tMark(MARK_CHANGE);\n\t\t\t\tIsCharging = false;\n\t\t\t\tIsCharged = false;\n\t\t\t\tSet_Stage(0);\n\t\t\t\tSet_Rate(0);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Repair_AI -- Handle the repair (and sell) logic for the building.            *\n *                                                                                             *\n *    This routine handle the repair animation and healing logic. It also detects when the     *\n *    (computer controlled) building should begin repair or sell itself.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per building per game logic loop.                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Repair_AI(void)\n{\n\tif (House->IQ >= Rule.IQRepairSell && Mission != MISSION_CONSTRUCTION && Mission != MISSION_DECONSTRUCTION) {\n\t\t/*\n\t\t**\tPossibly start repair process if the building is below half strength.\n\t\t*/\n//\t\tunsigned ratio = MIN(House->Smartness, 0x00F0);\n\t\tif (Can_Repair()) {\n\t\t\tif (House->Available_Money() >= Rule.RepairThreshhold) {\n\t\t\t\tif (!House->DidRepair) {\n\t\t\t\t\tif (!IsRepairing && (IsCaptured || IsToRepair || House->IsHuman || Session.Type != GAME_NORMAL)) {\n\t\t\t\t\t\tHouse->DidRepair = true;\t// flag that this house did its repair allocation for this frame\n\t\t\t\t\t\tRepair(1);\n\n\t\t\t\t\t\tif (!House->IsHuman) {\n\t\t\t\t\t\t\tHouse->RepairTimer = Random_Pick((int)(House->RepairDelay * (TICKS_PER_MINUTE/4)), (int)(House->RepairDelay * TICKS_PER_MINUTE * 2));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ((Session.Type != GAME_NORMAL || IsAllowedToSell) && IsTickedOff && House->Control.TechLevel >= Rule.IQSellBack && Random_Pick(0, 50) < House->Control.TechLevel && !Trigger.Is_Valid() && *this != STRUCT_CONST && Health_Ratio() < Rule.ConditionRed) {\n\t\t\t\t\tSell_Back(1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf it is repairing, then apply any repair effects as necessary.\n\t*/\n\tif (IsRepairing && (Frame % (Rule.RepairRate * TICKS_PER_MINUTE)) == 0) {\n\t\tIsWrenchVisible = (IsWrenchVisible == false);\n\t\tMark(MARK_CHANGE);\n\t\tint cost = Class->Repair_Cost();\n\t\tint step = Class->Repair_Step();\n\n\t\t/*\n\t\t**\tCheck for and expend any necessary monies to continue the repair.\n\t\t*/\n\t\tif (House->Available_Money() >= cost) {\n\t\t\tHouse->Spend_Money(cost);\n\t\t\tStrength += step;\n\n\t\t\tif (Strength >= Class->MaxStrength) {\n\t\t\t\tStrength = Class->MaxStrength;\n\t\t\t\tIsRepairing = false;\n\t\t\t}\n\t\t} else {\n\t\t\tIsRepairing = false;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Animation_AI -- Handles normal building animation processing.                *\n *                                                                                             *\n *    This will process the general building animation mechanism. It detects when the          *\n *    building animation sequence has completed and flags the building to perform mission      *\n *    changes as a result.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine only once per building per game logic loop.                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Animation_AI(void)\n{\n\tbool stagechange = Graphic_Logic();\n\tbool toloop = false;\n\n\t/*\n\t**\tAlways refresh the SAM site if it has an animation change.\n\t*/\n\tif (*this == STRUCT_SAM && stagechange) Mark(MARK_CHANGE);\n\n\tif ((!Class->IsTurretEquipped && *this != STRUCT_TESLA) || Mission == MISSION_CONSTRUCTION || Mission == MISSION_DECONSTRUCTION) {\n\t\tif (stagechange) {\n\n\t\t\t/*\n\t\t\t**\tCheck for animation end or if special case of MCV deconstructing when it is allowed\n\t\t\t**\tto convert back into an MCV.\n\t\t\t*/\n\t\t\tBuildingTypeClass::AnimControlType const * ctrl = Fetch_Anim_Control();\n\n\t\t\t/*\n\t\t\t**\tWhen the last frame of the current animation sequence is reached, flag that\n\t\t\t**\ta new mission may be started. This must occur before the animation actually\n\t\t\t**\tloops so that if a mission change does occur, it will have a chance to change\n\t\t\t**\tthe building graphic before the last frame is replaced by the first frame of\n\t\t\t**\tthe loop.\n\t\t\t*/\n\t\t\tif (Fetch_Stage() == ctrl->Start+ctrl->Count-1  || (!Target_Legal(ArchiveTarget) /*Special.IsMCVDeploy*/ && *this == STRUCT_CONST && Mission == MISSION_DECONSTRUCTION && Fetch_Stage() == (42-19))) {\n\t\t\t\tIsReadyToCommence = true;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the animation advances beyond the last frame, then start the animation\n\t\t\t**\tsequence over from the beginning.\n\t\t\t*/\n\t\t\tif (Fetch_Stage() >= ctrl->Start+ctrl->Count) {\n\t\t\t\ttoloop = true;\n\t\t\t}\n\t\t\tMark(MARK_CHANGE);\n\t\t} else {\n\t\t\tif (BState == BSTATE_NONE || Fetch_Rate() == 0) {\n\t\t\t\tIsReadyToCommence = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is a door that is animating, then it might cause this building\n\t**\tto be redrawn. Check for and flag to redraw as necessary.\n\t*/\n\tif (Time_To_Redraw()) {\n\t\tClear_Redraw_Flag();\n\t\tMark(MARK_CHANGE);\n\t}\n\n\t/*\n\t**\tThe animation sequence has looped. Restart it and flag this loop condition.\n\t**\tThis is used to tell the mission system that the animation has completed. It\n\t**\talso signals that now is a good time to act on any pending mission.\n\t*/\n\tif (toloop) {\n\t\tBuildingTypeClass::AnimControlType const * ctrl = Fetch_Anim_Control();\n\t\tif (BState == BSTATE_CONSTRUCTION || BState == BSTATE_IDLE) {\n\t\t\tSet_Rate(Options.Normalize_Delay(ctrl->Rate));\n\t\t} else {\n\t\t\tSet_Rate(ctrl->Rate);\n\t\t}\n\t\tSet_Stage(ctrl->Start);\n\t\tMark(MARK_CHANGE);\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::How_Many_Survivors -- This determine the maximum number of survivors.        *\n *                                                                                             *\n *    This routine is called to determine how many survivors should run from this building     *\n *    when it is either sold or destroyed. Buildings that are captured have fewer survivors.   *\n *    The number of survivors is a portion of the cost of the building divided by the cost     *\n *    of a minigunner.                                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of soldiers that should run from this building.            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::How_Many_Survivors(void) const\n{\n\tif (IsSurvivorless || !Class->IsCrew) return(0);\n\n\tint divisor = InfantryTypeClass::As_Reference(INFANTRY_E1).Raw_Cost();\n\tif (divisor == 0) return(0);\n\tif (IsCaptured) divisor *= 2;\n\tint count = (Class->Raw_Cost() * Rule.SurvivorFraction) / divisor;\n\treturn(Bound(count, 1, 5));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Get_Image_Data -- Fetch the image pointer for the building.                  *\n *                                                                                             *\n *    This routine will return with a pointer to the shape data for the building. The shape    *\n *    data is different than normal when the building is undergoing construction and           *\n *    disassembly.                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the shape data for this building.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid const * BuildingClass::Get_Image_Data(void) const\n{\n\tif (BState == BSTATE_CONSTRUCTION) {\n\t\treturn(Class->Get_Buildup_Data());\n\t}\n\treturn(TechnoClass::Get_Image_Data());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Value -- Determine the value of this building.                               *\n *                                                                                             *\n *    The value of the building is normally just its ordinary assigned value. However, in the  *\n *    case of fakes, the value is artificially enhanced to match the structure that is         *\n *    being faked.                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the point value of the building type.                                 *\n *                                                                                             *\n * WARNINGS:   The point value returned should not be used for scoring, only for target        *\n *             scanning.                                                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::Value(void) const\n{\n\tif (Class->IsFake) {\n\t\tswitch (Class->Type) {\n\t\t\tcase STRUCT_FAKEWEAP:\n\t\t\t\treturn(BuildingTypeClass::As_Reference(STRUCT_WEAP).Reward + BuildingTypeClass::As_Reference(STRUCT_WEAP).Risk);\n\n\t\t\tcase STRUCT_FAKECONST:\n\t\t\t\treturn(BuildingTypeClass::As_Reference(STRUCT_CONST).Reward + BuildingTypeClass::As_Reference(STRUCT_CONST).Risk);\n\n\t\t\tcase STRUCT_FAKE_YARD:\n\t\t\t\treturn(BuildingTypeClass::As_Reference(STRUCT_SHIP_YARD).Reward + BuildingTypeClass::As_Reference(STRUCT_SHIP_YARD).Risk);\n\n\t\t\tcase STRUCT_FAKE_PEN:\n\t\t\t\treturn(BuildingTypeClass::As_Reference(STRUCT_SUB_PEN).Reward + BuildingTypeClass::As_Reference(STRUCT_SUB_PEN).Risk);\n\n\t\t\tcase STRUCT_FAKE_RADAR:\n\t\t\t\treturn(BuildingTypeClass::As_Reference(STRUCT_RADAR).Reward + BuildingTypeClass::As_Reference(STRUCT_RADAR).Risk);\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn(TechnoClass::Value());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Remove_Gap_Effect -- Stop a gap generator from jamming cells.\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/20/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Remove_Gap_Effect(void)\n{\n\t// unjam this one's field...\n\tMap.UnJam_From(Coord_Cell(Center_Coord()), Rule.GapShroudRadius, House);\n\tif (!House->IsPlayerControl && PlayerPtr->IsGPSActive) {\n\t\tMap.Sight_From(Coord_Cell(Center_Coord()), Rule.GapShroudRadius, PlayerPtr);\n\t}\n\t// and rejam any overlapping buildings' fields\n\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\tBuildingClass *obj = Buildings.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == House && *obj == STRUCT_GAP && obj!=this) {\n\t\t\tobj->IsJamming = false;\n\t\t\tobj->Arm = 0;\n//\t\t\tMap.Jam_From(Coord_Cell(obj->Center_Coord()), Rule.GapShroudRadius, PlayerPtr);\n\t\t}\n\t}\n}\n\n\nshort const * BuildingClass::Overlap_List(bool redraw) const\n{\n\tif ((SpiedBy & (1 << PlayerPtr->Class->House)) != 0 && IsSelected && (*this == STRUCT_BARRACKS || *this == STRUCT_TENT)) {\n\t\tstatic short const _list[] = {\n\t\t\t-1, 2, (MAP_CELL_W*1)-1, (MAP_CELL_W*1)+2, REFRESH_EOL\n\t\t};\n\t\treturn(_list);\n\t}\n\treturn(TechnoClass::Overlap_List(redraw));\n}\n"
  },
  {
    "path": "CODE/BUILDING.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BUILDING.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BUILDING.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 14, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 14, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BUILDING_H\n#define BUILDING_H\n\n#include\t\"radio.h\"\n#include\t\"cargo.h\"\n#include\t\"mission.h\"\n#include\t\"bullet.h\"\n#include\t\"target.h\"\n#include\t\"factory.h\"\n#include\t\"techno.h\"\n\n#define\tMAX_DOOR_STAGE\t18\t// # of frames of door opening on weapons factory\n#define\tDOOR_OPEN_STAGE 9\t// frame on which the door is entirely open\n#define\tMAX_REPAIR_ANIM_STAGE\t5\t// # of stages of anim for repair center cycling\n\n/****************************************************************************\n**\tFor each instance of a building in the game, there is one of\n**\tthese structures. This structure holds information that is specific\n**\tand dynamic for a particular building.\n*/\nclass BuildingClass : public TechnoClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tThis points to the control data that gives this building its characteristics.\n\t\t*/\n\t\tCCPtr<BuildingTypeClass> Class;\n\n\t\t/*\n\t\t**\tIf this building is in the process of producing something, then this\n\t\t**\twill point to the factory manager.\n\t\t*/\n\t\tCCPtr<FactoryClass> Factory;\n\n\t\t/*\n\t\t**\tThis is the house that originally owned this factory. Objects buildable\n\t\t**\tby this house type will be produced from this factory regardless of who\n\t\t**\tthe current owner is.\n\t\t*/\n\t\tHousesType ActLike;\n\n\t\t/*\n\t\t**\tThis building should be rebuilt if it is destroyed. This is in spite\n\t\t**\tof the condition of the prebuilt base list.\n\t\t*/\n\t\tunsigned IsToRebuild:1;\n\n\t\t/*\n\t\t**\tIs the building allowed to repair itself?\n\t\t*/\n\t\tunsigned IsToRepair:1;\n\n\t\t/*\n\t\t**\tIf the computer owns this building, then it is allowed to sell it if\n\t\t**\tthe situation warrants it. In the other case, it cannot sell the\n\t\t**\tbuilding regardless of conditions.\n\t\t*/\n\t\tunsigned IsAllowedToSell:1;\n\n\t\t/*\n\t\t**\tIf the building is at a good point to change orders, then this\n\t\t**\tflag will be set to true.\n\t\t*/\n\t\tunsigned IsReadyToCommence:1;\n\n\t\t/*\n\t\t**\tIf this building is currently spending money to repair itself, then\n\t\t**\tthis flag is true. It will automatically be set to false when the building\n\t\t**\thas reached full strength, when money is exhausted, or if the player\n\t\t**\tspecifically stops the repair process.\n\t\t*/\n\t\tunsigned IsRepairing:1;\n\n\t\t/*\n\t\t**\tIf repair is currently in progress and this flag is true, then a wrench graphic\n\t\t**\twill be overlaid on the building to give visual feedback for the repair process.\n\t\t*/\n\t\tunsigned IsWrenchVisible:1;\n\n\t\t/*\n\t\t** This flag is set when a commando has raided the building and planted\n\t\t** plastic explosives.  When the CommandoCountDown timer expires, the\n\t\t** building takes massive damage.\n\t\t*/\n\t\tunsigned IsGoingToBlow:1;\n\n\t\t/*\n\t\t**\tIf this building was destroyed by some method that would prevent\n\t\t**\tsurvivors, then this flag will be true.\n\t\t*/\n\t\tunsigned IsSurvivorless:1;\n\n\t\t/*\n\t\t**\tThese state control variables are used by the obelisk for the charging\n\t\t**\tanimation.\n\t\t*/\n\t\tunsigned IsCharging:1;\n\t\tunsigned IsCharged:1;\n\n\t\t/*\n\t\t**\tA building that has been captured will not contain the full compliment\n\t\t**\tof crew. This is true even if it subsequently gets captured back.\n\t\t*/\n\t\tunsigned IsCaptured:1;\n\n\t\t/*\n\t\t** Used by the gap generator to decide if it should jam or unjam\n\t\t*/\n\t\tunsigned IsJamming:1;\n\n\t\t/*\n\t\t** Used by radar facilities to know if they're being jammed by a mobile\n\t\t** radar jammer\n\t\t*/\n\t\tunsigned IsJammed:1;\n\n\t\t/*\n\t\t** Used only by advanced tech center, this keeps track of whether the\n\t\t** GPS satellite has been fired or not.\n\t\t*/\n\t\tunsigned HasFired:1;\n\n\t\t/*\n\t\t**\tIf Grand_Opening was already called for this building, then this\n\t\t**\tflag will be true. By utilizing this flag, multiple inadvertant\n\t\t**\tcalls to Grand_Opening won't cause problems.\n\t\t*/\n\t\tunsigned HasOpened:1;\n\n\t\t/*\n\t\t**\tSpecial countdown to destruction value. If the building is destroyed,\n\t\t**\tit won't actually be removed from the map until this value reaches\n\t\t**\tzero. This delay is for cosmetic reasons.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> CountDown;\n\n\t\t/*\n\t\t**\tThis is the current animation processing state that the building is\n\t\t**\tin.\n\t\t*/\n\t\tBStateType BState;\n\t\tBStateType QueueBState;\n\n\t\t/*\n\t\t** For multiplayer games, this keeps track of the last house to damage\n\t\t** this building, so if it burns to death or otherwise gradually dies,\n\t\t** proper credit can be given for the kill.\n\t\t*/\n\t\tHousesType WhoLastHurtMe;\n\n\t\t/*\n\t\t**\tThis is the saboteur responsible for this building's destruction.\n\t\t*/\n\t\tTARGET WhomToRepay;\n\n\t\t/*\n\t\t**\tThis is a record of the last strength of the building. Every so often,\n\t\t**\tit will compare this strength to the current strength. If there is a\n\t\t**\tdiscrepancy, then the owner power is adjusted accordingly.\n\t\t*/\n\t\tint LastStrength;\n\n\t\t/*\n\t\t** This is a target id of an animation we're keeping track of.  Examples\n\t\t** of this usage are the advanced tech center, which needs to know\n\t\t** when the sputdoor animation has reached a certain stage.\n\t\t*/\n\t\tTARGET AnimToTrack;\n\n\t\t/*\n\t\t**\tThis is the countdown timer that regulates placement retry logic\n\t\t**\tfor factory type buildings.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> PlacementDelay;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\t\tBuildingClass(StructType type, HousesType house);\n#ifdef FIXIT_MULTI_SAVE\n\t\tBuildingClass(NoInitClass const & x) : TechnoClass(x), Class(x), Factory(x), CountDown(x), PlacementDelay(x) {};\n#else\n\t\tBuildingClass(NoInitClass const & x) : TechnoClass(x), Class(x), CountDown(x), PlacementDelay(x) {};\n#endif\n\t\tvirtual ~BuildingClass(void);\n\t\toperator StructType(void) const {return Class->Type;};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tstatic void Init(void);\n\n\t\tTARGET Target_Scan(void);\n\t\tBuildingTypeClass::AnimControlType const * Fetch_Anim_Control(void) {return (&Class->Anims[BState]);};\n\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tvirtual int Value(void) const;\n\t\tvirtual void const * Get_Image_Data(void) const;\n\t\tvirtual int How_Many_Survivors(void) const;\n\t\tvirtual DirType Turret_Facing(void) const;\n\t\tvirtual CELL Find_Exit_Cell(TechnoClass const * techno) const;\n\t\tvirtual InfantryType Crew_Type(void) const;\n\t\tvirtual int Pip_Count(void) const;\n\t\tvirtual bool Can_Player_Move(void) const;\n\t\tvirtual ActionType What_Action(ObjectClass const * target) const;\n\t\tvirtual ActionType What_Action(CELL cell) const;\n\t\tvirtual bool Can_Demolish(void) const;\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const {return *Class;};\n\t\tvirtual DirType Fire_Direction(void) const;\n\t\tvirtual short const * Overlap_List(bool redraw=false) const;\n\t\tint Shape_Number(void) const;\n\t\tint Power_Output(void) const;\n\t\tCELL Check_Point(CheckPointType cp) const;\n\n\t\t/*\n\t\t**\tCoordinate inquiry functions. These are used for both display and\n\t\t**\tcombat purposes.\n\t\t*/\n\t\tvirtual COORDINATE Target_Coord(void) const;\n\t\tvirtual COORDINATE Docking_Coord(void) const;\n\t\tvirtual COORDINATE Center_Coord(void) const;\n\t\tvirtual COORDINATE Sort_Y(void) const;\n\t\tvirtual COORDINATE Exit_Coord(void) const;\n\n\t\t/*\n\t\t**\tObject entry and exit from the game system.\n\t\t*/\n\t\tvirtual void Detach(TARGET target, bool all);\n\t\tvirtual void Detach_All(bool all=true);\n\t\tvirtual void Grand_Opening(bool captured = false);\n\t\tvirtual void Update_Buildables(void);\n\t\tvirtual MoveType Can_Enter_Cell(CELL cell, FacingType = FACING_NONE) const;\n\t\tvirtual bool Unlimbo(COORDINATE , DirType dir = DIR_N);\n\t\tvirtual bool Limbo(void);\n\n\t\t/*\n\t\t**\tDisplay and rendering support functionality. Supports imagery and how\n\t\t**\tobject interacts with the map and thus indirectly controls rendering.\n\t\t*/\n\t\tvirtual void const * Remap_Table(void);\n\t\tvirtual int Exit_Object(TechnoClass * base);\n\t\tvirtual void Draw_It(int x, int y, WindowNumberType window) const;\n\t\tvirtual bool Mark(MarkType mark=MARK_CHANGE);\n\t\tvirtual void Fire_Out(void);\n\t\tvoid Begin_Mode(BStateType bstate);\n\n\t\t/*\n\t\t**\tUser I/O.\n\t\t*/\n\t\tvirtual void Active_Click_With(ActionType action, ObjectClass * object);\n\t\tvirtual void Active_Click_With(ActionType action, CELL cell);\n\n\t\t/*\n\t\t**\tCombat related.\n\t\t*/\n\t\tvirtual void Death_Announcement(TechnoClass const * source=0) const;\n\t\tvirtual FireErrorType Can_Fire(TARGET, int which) const;\n\t\tvirtual TARGET Greatest_Threat(ThreatType threat) const;\n\t\tvirtual ResultType Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source=0, bool forced=false);\n\t\tvirtual bool Captured(HouseClass * newowner);\n\t\tvoid Update_Radar_Spied(void);\n\n\t\t/*\n\t\t**\tAI.\n\t\t*/\n\t\tvoid Charging_AI(void);\n\t\tvoid Rotation_AI(void);\n\t\tvoid Factory_AI(void);\n\t\tvoid Repair_AI(void);\n\t\tvoid Animation_AI(void);\n\t\tvirtual bool Revealed(HouseClass * house);\n\t\tvirtual void Repair(int control);\n\t\tvirtual void Sell_Back(int control);\n\t\tvirtual RadioMessageType Receive_Message(RadioClass * from, RadioMessageType message, long & param);\n\t\tvirtual void AI(void);\n\t\tvirtual void Assign_Target(TARGET target);\n\t\tvirtual bool Toggle_Primary(void);\n\t\tbool Flush_For_Placement(TechnoClass * techno, CELL cell);\n\n\t\tvirtual int Mission_Unload(void);\n\t\tvirtual int Mission_Repair(void);\n\t\tvirtual int Mission_Attack(void);\n\t\tvirtual int Mission_Harvest(void);\n\t\tvirtual int Mission_Guard(void);\n\t\tvirtual int Mission_Construction(void);\n\t\tvirtual int Mission_Deconstruction(void);\n\t\tvirtual int Mission_Missile(void);\n\t\tvirtual void Enter_Idle_Mode(bool initial=false);\n\t\tvoid Remove_Gap_Effect(void);\n\n\t\t/*\n\t\t**\tScenario and debug support.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tstatic void Read_INI(CCINIClass & ini);\n\t\tstatic void Write_INI(CCINIClass & ini);\n\t\tstatic char *INI_Name(void) {return \"STRUCTURES\";};\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\n\tprivate:\n\t\tvoid Drop_Debris(TARGET source = TARGET_NONE);\n\n\t\tstatic COORDINATE const CenterOffset[BSIZE_COUNT];\n};\n\n#endif\n"
  },
  {
    "path": "CODE/BULLET.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BULLET.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BULLET.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 10, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BulletClass::AI -- Logic processing for bullet.                                           *\n *   BulletClass::BulletClass -- Bullet constructor.                                           *\n *   BulletClass::Bullet_Explodes -- Performs bullet explosion logic.                          *\n *   BulletClass::Detach -- Removes specified target from this bullet's targeting system.      *\n *   BulletClass::Draw_It -- Displays the bullet at location specified.                        *\n *   BulletClass::In_Which_Layer -- Fetches the layer that the bullet resides in.              *\n *   BulletClass::Init -- Clears the bullets array for scenario preparation.                   *\n *   BulletClass::Is_Forced_To_Explode -- Checks if bullet should explode NOW.                 *\n *   BulletClass::Mark -- Performs related map refreshing under bullet.                        *\n *   BulletClass::Occupy_List -- Determines the bullet occupation list.                        *\n *   BulletClass::Shape_Number -- Fetches the shape number for the bullet object.              *\n *   BulletClass::Sort_Y -- Sort coordinate for bullet rendering.                              *\n *   BulletClass::Target_Coord -- Fetches coordinate to use when firing on this object.        *\n *   BulletClass::Unlimbo -- Transitions a bullet object into the game render/logic system.    *\n *   BulletClass::delete -- Bullet memory delete.                                              *\n *   BulletClass::new -- Allocates memory for bullet object.                                   *\n *   BulletClass::~BulletClass -- Destructor for bullet objects.                               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * BulletClass::BulletClass -- Bullet constructor.                                             *\n *                                                                                             *\n *    This is the constructor for the bullet class. It handles all                             *\n *    initialization of the bullet and starting it in motion toward its                        *\n *    target.                                                                                  *\n *                                                                                             *\n * INPUT:   id       -- The type of bullet this is (could be missile).                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/02/1994 JLB : Created.                                                                 *\n *   06/20/1994 JLB : Firer is a base class pointer.                                           *\n *   12/10/1994 JLB : Auto calculate range optional.                                           *\n *   12/12/1994 JLB : Handles small arms as an instantaneous effect.                           *\n *   12/23/1994 JLB : Fixed scatter algorithm for non-homing projectiles.                      *\n *   12/31/1994 JLB : Removed range parameter (not needed).                                    *\n *=============================================================================================*/\nBulletClass::BulletClass(BulletType id, TARGET target, TechnoClass * payback, int strength, WarheadType warhead, int speed) :\n\tObjectClass(RTTI_BULLET, Bullets.ID(this)),\n\tClass(BulletTypes.Ptr((int)id)),\n\tPayback(payback),\n\tPrimaryFacing(DIR_N),\n\tIsInaccurate(false),\n\tIsToAnimate(false),\n\tIsLocked(true),\n\tTarCom(target),\n\tMaxSpeed(speed),\n\tWarhead(warhead)\n{\n\tStrength = strength;\n\tHeight = FLIGHT_LEVEL;\n}\n\n\n/***********************************************************************************************\n * BulletClass::~BulletClass -- Destructor for bullet objects.                                 *\n *                                                                                             *\n *    The bullet destructor must detect if a dog has been attached to this bullet. If so,      *\n *    then the attached dog must be unlimboed back onto the map. This operation is necessary   *\n *    because, unlike other objects, the dog flies with the bullet it fires.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBulletClass::~BulletClass(void)\n{\n\tif (GameActive) {\n\n\t\t/*\n\t\t**\tSPECIAL CASE:\n\t\t**\tThe dog is attached to the dog bullet in a limbo state. When the bullet is\n\t\t**\tdestroyed, the dog must come back out of limbo at the closest location possible to\n\t\t**\tthe bullet.\n\t\t*/\n\t\tif (Payback != NULL && Payback->What_Am_I() == RTTI_INFANTRY && ((InfantryClass *)Payback)->Class->IsDog) {\n\n\t\t\tInfantryClass * dog = (InfantryClass *)Payback;\n\t\t\tif (dog) {\n\t\t\t\tbool unlimbo = false;\n\t\t\t\tDirType dogface = dog->PrimaryFacing;\n\t\t\t\tCOORDINATE newcoord = Coord;\n\n\t\t\t\t/*\n\t\t\t\t**\tEnsure that the coordinate, that the dog is to appear at, is legal. If not,\n\t\t\t\t**\tthen find a nearby legal location.\n\t\t\t\t*/\n\t\t\t\tif (Can_Enter_Cell(newcoord) != MOVE_OK) {\n\t\t\t\t\tnewcoord = Map.Nearby_Location(Coord_Cell(newcoord), dog->Class->Speed);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Try to put the dog down where the target impacted.  If we can't\n\t\t\t\t** put it in that cell, then scan through the adjacent cells,\n\t\t\t\t** starting with our current heading, until we find a place where\n\t\t\t\t** we can put him down.  If all 8 adjacent cell checks fail, then\n\t\t\t\t** just delete the dog.\n\t\t\t\t*/\n\t\t\t\tfor (int i = -1; i < 8; i++) {\n\t\t\t\t\tif (i != -1) {\n\t\t\t\t\t\tnewcoord = Adjacent_Cell(Coord, FacingType(i));\n\t\t\t\t\t}\n\t\t\t\t\tScenarioInit++;\n\t\t\t\t\tif (dog->Unlimbo(newcoord, dog->PrimaryFacing)) {\n\t\t\t\t\t\tdog->Mark(MARK_DOWN);\n\t\t\t\t\t\tdog->Do_Action(DO_DOG_MAUL, true);\n\t\t\t\t\t\tif (dog->WasSelected) {\n\t\t\t\t\t\t\tdog->Select();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t\tunlimbo = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t}\n\n\t\t\t\tPayback = 0;\n\n\t\t\t\tif (!unlimbo) {\n\t\t\t\t\tdelete dog;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tBulletClass::Limbo();\n\t}\n\n\tClass=0;\n\tPayback=0;\n}\n\n\n/***********************************************************************************************\n * BulletClass::new -- Allocates memory for bullet object.                                     *\n *                                                                                             *\n *    This function will \"allocate\" a block of memory for a bullet object.                     *\n *    This memory block is merely lifted from a fixed pool of blocks.                          *\n *                                                                                             *\n * INPUT:   size  -- The size of the memory block needed.                                      *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to an available bullet object block.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * BulletClass::operator new(size_t )\n{\n\tvoid * ptr = Bullets.Allocate();\n\tif (ptr) {\n\t\t((BulletClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * BulletClass::delete -- Bullet memory delete.                                                *\n *                                                                                             *\n *    Since bullets memory is merely \"allocated\" out of a pool, it never                       *\n *    actually gets deleted.                                                                   *\n *                                                                                             *\n * INPUT:   ptr   -- Generic pointer to bullet object.                                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BulletClass::operator delete(void * ptr)\n{\n\tif (ptr) {\n\t\t((BulletClass *)ptr)->IsActive = false;\n\t}\n\tBullets.Free((BulletClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * BulletClass::Occupy_List -- Determines the bullet occupation list.                          *\n *                                                                                             *\n *    This function will determine the cell occupation list and return a pointer to it. Most   *\n *    bullets are small and the list is usually short, but on occasion, it can be a list that  *\n *    rivals the size of regular vehicles.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the cell offset list that covers all the cells a bullet  *\n *          is over.                                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1994 JLB : Created.                                                                 *\n *   01/05/1995 JLB : Handles projectiles with altitude.                                       *\n *=============================================================================================*/\nshort const * BulletClass::Occupy_List(bool) const\n{\n\tassert(Bullets.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tSuper-gigundo units use the >= 64 coord spillage list logic.\n\t*/\n\tif (Class->IsGigundo) {\n\t\tstatic short _list[] = {\n\t\t\t-1, 0, 1,\n\t\t\tMAP_CELL_W*1-1, MAP_CELL_W*1, MAP_CELL_W*1+1,\n\t\t\t-MAP_CELL_W*1-1, -MAP_CELL_W*1, -MAP_CELL_W*1+1,\n\t\t\tMAP_CELL_W*2-1, MAP_CELL_W*2, MAP_CELL_W*2+1,\n\t\t\t-MAP_CELL_W*2-1, -MAP_CELL_W*2, -MAP_CELL_W*2+1,\n\t\t\t-MAP_CELL_W*3-1, -MAP_CELL_W*3, -MAP_CELL_W*3+1,\n\t\t\tREFRESH_EOL\n\t\t};\n\t\treturn(_list);\n//\t\treturn(Coord_Spillage_List(Coord, 64));\n\t}\n\n\t/*\n\t**\tFlying units need a special adjustment to the spillage list to take into account\n\t**\tthat the bullet imagery and the shadow are widely separated.\n\t*/\n\tif (Height > 0) {\n\t\tstatic short _list[25];\n\t\tconst short * ptr = Coord_Spillage_List(Coord, 5);\n\t\tint index = 0;\n\t\tCELL cell1 = Coord_Cell(Coord);\n\n\t\twhile (ptr[index] != REFRESH_EOL) {\n\t\t\t_list[index] = ptr[index];\n\t\t\tindex++;\n\t\t}\n\n\t\tCOORDINATE coord = Coord_Move(Coord, DIR_N, Height);\n\t\tCELL cell2 = Coord_Cell(coord);\n\t\tptr = Coord_Spillage_List(coord, 5);\n\t\twhile (*ptr != REFRESH_EOL) {\n\t\t\t_list[index++] = *ptr + (cell2 - cell1);\n\t\t\tptr++;\n\t\t}\n\t\t_list[index] = REFRESH_EOL;\n\t\treturn(_list);\n\t}\n\n\treturn(Coord_Spillage_List(Coord, 10));\n}\n\n\n/***********************************************************************************************\n * BulletClass::Mark -- Performs related map refreshing under bullet.                          *\n *                                                                                             *\n *    This routine marks the objects under the bullet so that they will                        *\n *    be redrawn. This is necessary as the bullet moves -- objects under                       *\n *    its path need to be restored.                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BulletClass::Mark(MarkType mark)\n{\n\tassert(Bullets.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (ObjectClass::Mark(mark)) {\n\t\tif (!Class->IsInvisible) {\n\t\t\tMap.Refresh_Cells(Coord_Cell(Coord), Occupy_List());\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BulletClass::AI -- Logic processing for bullet.                                             *\n *                                                                                             *\n *    This routine will perform all logic (flight) logic on the bullet.                        *\n *    Primarily this is motion, fuse tracking, and detonation logic. Call                      *\n *    this routine no more than once per bullet per game tick.                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BulletClass::AI(void)\n{\n\tassert(Bullets.ID(this) == ID);\n\tassert(IsActive);\n\n\tCOORDINATE\tcoord;\n\n\tObjectClass::AI();\n\n\tif (!IsActive) return;\n\n\t/*\n\t**\tBallistic objects are handled here.\n\t*/\n\tbool forced = false;\t\t\t// Forced explosion.\n\tif ((Class->IsArcing || Class->IsDropping) && !IsFalling) {\n\t\tforced = true;\n\t}\n\n\t/*\n\t**\tHoming projectiles constantly change facing to face toward the target but\n\t**\tthey only do so every other game frame (improves game speed and makes\n\t**\tmissiles not so deadly).\n\t*/\n\tif ((Frame & 0x01) && Class->ROT != 0 && Target_Legal(TarCom)) {\n\t\tPrimaryFacing.Set_Desired(Direction256(Coord, ::As_Coord(TarCom)));\n\t}\n\n\t/*\n\t**\tMove the projectile forward according to its speed\n\t**\tand direction.\n\t*/\n\tcoord = Coord;\n\tif (Class->IsFlameEquipped) {\n\t\tif (IsToAnimate) {\n\t\t\tif (stricmp(Class->GraphicName, \"FB1\") == 0) {\n\t\t\t\tnew AnimClass(ANIM_FBALL_FADE, coord, 1);\n\t\t\t} else {\n\t\t\t\tnew AnimClass(ANIM_SMOKE_PUFF, coord, 1);\n\t\t\t}\n\t\t}\n\t\tIsToAnimate = !IsToAnimate;\n\t}\n\n\t/*\n\t**\tHandle any body rotation at this time. This process must\n\t**\toccur every game fame in order to achieve smooth rotation.\n\t*/\n\tif (PrimaryFacing.Is_Rotating()) {\n\t\tPrimaryFacing.Rotation_Adjust(Class->ROT);\n\t}\n\tswitch (Physics(coord, PrimaryFacing)) {\n\t\t/*\n\t\t**\tWhen a projectile reaches the edge of the world, it\n\t\t**\tvanishes from existence -- presumed to explode off\n\t\t**\tmap.\n\t\t*/\n\t\tcase IMPACT_EDGE:\n\t\t\tMark();\n\t\t\tif (Payback != NULL && Class->Type == BULLET_GPS_SATELLITE) {\n\t\t\t\tif (Payback->House == PlayerPtr) {\n\t\t\t\t\tif (!Map.Is_Radar_Active()) {\n\t\t\t\t\t\tMap.Radar_Activate(1);\n\t\t\t\t\t}\n\t\t\t\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\t\t\tMap.Map_Cell(cell, PlayerPtr);\n\t\t\t\t\t}\n\t\t\t\t\tMap.RadarClass::Flag_To_Redraw(true);\n\t\t\t\t}\n\t\t\t\tPayback->House->IsGPSActive = true;\n\t\t\t\tPayback->House->IsVisionary = true;\n\t\t\t}\n#ifdef OBSOLETE\n\t\t\t/*\n\t\t\t** Hack: If it's the artificial nukes, don't let the bullets come down (as\n\t\t\t** they're the only ones that blow up).  We know it's artificial if you're\n\t\t\t** at tech level 10 or below, because you can't build the nuclear silo until\n\t\t\t** tech level 15 or so.\n\t\t\t*/\n\t\t\tif (Payback != NULL && Class->Type == BULLET_NUKE_UP && Payback->House->Control.TechLevel <= 10) {\n\t\t\t\tBulletClass * bullet = new BulletClass(BULLET_NUKE_DOWN, ::As_Target(Payback->House->NukeDest), Payback, 200, WARHEAD_NUKE, MPH_VERY_FAST);\n\t\t\t\tif (bullet) {\n\t\t\t\t\tint celly = Cell_Y(Payback->House->NukeDest);\n\t\t\t\t\tcelly -= 15;\n\t\t\t\t\tif (celly < 1) celly = 1;\n\t\t\t\t\tCOORDINATE start = Cell_Coord(XY_Cell(Cell_X(Payback->House->NukeDest), celly));\n\t\t\t\t\tif (!bullet->Unlimbo(start, DIR_S)) {\n\t\t\t\t\t\tdelete bullet;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n#endif\n\t\t\tdelete this;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\tcase IMPACT_NONE:\n\n\t\t/*\n\t\t**\tThe projectile has moved. Check its fuse. If detonation\n\t\t**\tis signaled, then do so. Otherwise, just move.\n\t\t*/\n\t\tcase IMPACT_NORMAL:\n\t\t\tMark();\n//\t\t\tif(Class->Type == BULLET_NUKE_DOWN) {\n//\t\t\t\tRender(true);\n//\t\t\t}\n\t\t\tif (Class->Type == BULLET_NUKE_UP) {\n\t\t\t\tif (Payback != NULL) {\n\t\t\t\t\tif (Distance(Payback->As_Target()) > 0x0C00) {\n\t\t\t\t\t\tdelete this;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tCoord = coord;\n\n\t\t\t/*\n\t\t\t**\tSee if the bullet should be forced to explode now in spite of what\n\t\t\t**\tthe fuse would otherwise indicate. Maybe the bullet hit a wall?\n\t\t\t*/\n\t\t\tif (!forced) {\n\t\t\t\tforced = Is_Forced_To_Explode(Coord);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the bullet is not to explode, then perform normal flight\n\t\t\t**\tmaintenance (usually nothing). Otherwise, explode and then\n\t\t\t**\tdelete the bullet.\n\t\t\t*/\n\t\t\tif (!forced && (Class->IsDropping || !Fuse_Checkup(Coord))) {\n\t\t\t\t/*\n\t\t\t\t**\tCertain projectiles lose strength when they travel.\n\t\t\t\t*/\n\t\t\t\tif (Class->IsDegenerate && Strength > 5) {\n\t\t\t\t\tStrength--;\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tBullet_Explodes(forced);\n\t\t\t\tdelete this;\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n}\n\n\n/***********************************************************************************************\n * BulletClass::Shape_Number -- Fetches the shape number for the bullet object.                *\n *                                                                                             *\n *    Use this routine to fetch a shape number to use for this bullet object.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the shape number to use when drawing this bullet.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BulletClass::Shape_Number(void) const\n{\n\tint shapenum = 0;\n\n\tif (!Class->IsFaceless) {\n\t\tshapenum = UnitClass::BodyShape[Dir_To_32(PrimaryFacing)];\n\t}\n\n\t/*\n\t**\tFor tumbling projectiles, fetch offset stage.\n\t*/\n\tif (Class->Tumble > 0) {\n\t\tshapenum += (long)Frame % Class->Tumble;\n\t}\n\n\treturn(shapenum);\n}\n\n\n/***********************************************************************************************\n * BulletClass::Draw_It -- Displays the bullet at location specified.                          *\n *                                                                                             *\n *    This routine displays the bullet visual at the location specified.                       *\n *                                                                                             *\n * INPUT:   x,y   -- The center coordinate to render the bullet at.                            *\n *                                                                                             *\n *          window   -- The window to clip to.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1994 JLB : Created.                                                                 *\n *   06/27/1994 JLB : Takes a window clipping parameter.                                       *\n *   01/08/1995 JLB : Handles translucent colors if necessary.                                 *\n *=============================================================================================*/\nvoid BulletClass::Draw_It(int x, int y, WindowNumberType window) const\n{\n\tassert(Bullets.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tCertain projectiles aren't visible. This includes small bullets (which are actually\n\t**\tinvisible) and flame thrower flames (which are rendered as an animation instead of a projectile).\n\t*/\n\tif (Class->IsInvisible) return;\n\n\t/*\n\t**\tIf there is no shape loaded for this object, then\n\t**\tit obviously can't be rendered -- just bail.\n\t*/\n\tvoid const * shapeptr = Get_Image_Data();\n\tif (shapeptr == NULL) return;\n\n\t/*\n\t**\tGet the basic shape number for this projectile.\n\t*/\n\tint shapenum = Shape_Number();\n\n\t/*\n\t**\tFor flying projectiles, draw the shadow and adjust the actual projectile body\n\t**\trender position.\n\t*/\n\tif (Height > 0 && Class->IsShadow) {\n\n\t\tif (Class->IsParachuted) {\n\t\t\tCC_Draw_Shape(AnimTypeClass::As_Reference(ANIM_PARA_BOMB).Get_Image_Data(), 1, x+Lepton_To_Pixel(Height/2), y+10, window, SHAPE_PREDATOR|SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_FADING, NULL, DisplayClass::UnitShadow);\n\t\t} else {\n\t\t\tCC_Draw_Shape(shapeptr, shapenum, x, y, window, SHAPE_PREDATOR|SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_FADING, NULL, DisplayClass::UnitShadow);\n\t\t}\n\t\ty -= Lepton_To_Pixel(Height);\n\t}\n\n\t/*\n\t**\tDraw the main body of the projectile.\n\t*/\n\tShapeFlags_Type flags = SHAPE_NORMAL;\n\tif (Class->IsTranslucent) {\n\t\tflags = SHAPE_GHOST;\n\t}\n\tif (Class->IsSubSurface) {\n\t\tCC_Draw_Shape(shapeptr, shapenum, x, y, window, flags|SHAPE_PREDATOR|SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_FADING, NULL, DisplayClass::FadingShade);\n\t} else {\n\t\tCC_Draw_Shape(shapeptr, shapenum, x, y, window, flags|SHAPE_CENTER|SHAPE_WIN_REL, NULL, DisplayClass::UnitShadow);\n\t}\n}\n\n\n/***********************************************************************************************\n * BulletClass::Init -- Clears the bullets array for scenario preparation.                     *\n *                                                                                             *\n *    This routine will zero out the bullet tracking list and object array in preparation for  *\n *    the start of a new scenario. All bullets cease to exists after this function is          *\n *    called.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BulletClass::Init(void)\n{\n\tBullets.Free_All();\n}\n\n\n/***********************************************************************************************\n * BulletClass::Detach -- Removes specified target from this bullet's targeting system.        *\n *                                                                                             *\n *    When an object is removed from the game system, it must be removed all targeting and     *\n *    tracking systems as well. This routine is used to remove the specified object from the   *\n *    bullet. If the object isn't part of this bullet's tracking system, then no action is     *\n *    performed.                                                                               *\n *                                                                                             *\n * INPUT:   target   -- The target to remove from this tracking system.                        *\n *                                                                                             *\n *          all      -- Is the target going away for good as opposed to just cloaking/hiding?  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BulletClass::Detach(TARGET target, bool all)\n{\n\tassert(Bullets.ID(this) == ID);\n\tassert(IsActive);\n\n\tObjectClass * obj = As_Object(target);\n\tif (Payback != NULL && obj == Payback) {\n\n\t\t/*\n\t\t** If we're being called as a result of the dog that fired us being put\n\t\t** in limbo, then don't detach.  If for any other reason, detach.\n\t\t*/\n\t\tif (Payback->What_Am_I() != RTTI_INFANTRY || !((InfantryClass *)Payback)->Class->IsDog) {\n\t\t\tPayback = 0;\n\t\t}\n\t}\n\n\tif (all && target == TarCom) {\n\t\tTarCom = TARGET_NONE;\n\t}\n}\n\n\n/***********************************************************************************************\n * BulletClass::Unlimbo -- Transitions a bullet object into the game render/logic system.      *\n *                                                                                             *\n *    This routine is used to take a bullet object that is in limbo and transition it to the   *\n *    game system. A bullet object so transitioned, will be drawn and logic processing         *\n *    performed. In effect, it comes into existence.                                           *\n *                                                                                             *\n * INPUT:   coord -- The location where the bullet object is to appear.                        *\n *                                                                                             *\n *          dir   -- The initial facing for the bullet object.                                 *\n *                                                                                             *\n * OUTPUT:  bool; Was the unlimbo successful?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BulletClass::Unlimbo(COORDINATE coord, DirType dir)\n{\n\tassert(Bullets.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tTry to unlimbo the bullet as far as the base class is concerned. Use the already\n\t**\tset direction and strength if the \"punt\" values were passed in. This allows a bullet\n\t**\tto be setup prior to being launched.\n\t*/\n\tif (!Class->IsHigh) {\n\t\tHeight = 0;\n\t}\n\tif (ObjectClass::Unlimbo(coord)) {\n\t\tMap.Remove(this, In_Which_Layer());\n\n\t\tCOORDINATE tcoord = As_Coord(TarCom);\n\n\t\t/*\n\t\t**\tHoming projectiles (missiles) do NOT override facing. They just fire in the\n\t\t**\tdirection specified and let the chips fall where they may.\n\t\t*/\n\t\tif (Class->ROT == 0 && !Class->IsDropping) {\n\t\t\tdir = Direction(tcoord);\n\t\t}\n\n\t\t/*\n\t\t**\tPossibly adjust the target if this projectile is inaccurate. This occurs whenever\n\t\t**\tcertain weapons are trained upon targets they were never designed to attack. Example: when\n\t\t**\tturrets or anti-tank missiles are fired at infantry. Indirect\n\t\t**\tfire is inherently inaccurate.\n\t\t*/\n\t\tif (IsInaccurate || Class->IsInaccurate ||\n\t\t\t((Is_Target_Cell(TarCom) || Is_Target_Infantry(TarCom)) && (Warhead == WARHEAD_AP || Class->IsFueled))) {\n\n\t\t\t/*\n\t\t\t**\tInaccuracy for low velocity or homing projectiles manifests itself as a standard\n\t\t\t**\tCircular Error of Probability (CEP) algorithm. High speed projectiles usually\n\t\t\t**\tjust overshoot the target by extending the straight line flight.\n\t\t\t*/\n\t\t\tif (/*Class->ROT != 0 ||*/ Class->IsArcing) {\n\t\t\t\tint scatterdist = (::Distance(coord, tcoord)/16)-0x0040;\n\t\t\t\tscatterdist = min(scatterdist, Rule.HomingScatter);\n\t\t\t\tscatterdist = max(scatterdist, 0);\n\n\t\t\t\tdir = (DirType)((dir + (Random_Pick(0, 10)-5)) & 0x00FF);\n\t\t\t\ttcoord = Coord_Scatter(tcoord, Random_Pick(0, scatterdist));\n\t\t\t} else {\n\t\t\t\tint scatterdist = (::Distance(coord, tcoord)/16)-0x0040;\n\t\t\t\tscatterdist = min(scatterdist, Rule.BallisticScatter);\n\t\t\t\tscatterdist = max(scatterdist, 0);\n\t\t\t\ttcoord = Coord_Move(tcoord, dir, Random_Pick(0, scatterdist));\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tFor very fast and invisible projectiles, just make the projectile exist at the target\n\t\t**\tlocation and dispense with the actual flight.\n\t\t*/\n\t\tif (MaxSpeed == MPH_LIGHT_SPEED && Class->IsInvisible) {\n\t\t\tCoord = tcoord;\n\t\t}\n\n\t\t/*\n\t\t**\tSet the range equal to either the class defined range or the calculated\n\t\t**\tnumber of game frames it would take for the projectile to reach the target.\n\t\t*/\n\t\tint range = 0xFF;\n\t\tif (!Class->IsDropping) {\n\t\t\trange = (::Distance(tcoord, Coord) / MaxSpeed) + 4;\n\t\t}\n\n\t\t/*\n\t\t**\tProjectile speed is usually the default value for that projectile, but\n\t\t**\tcertain projectiles alter speed according to the distance to the\n\t\t**\ttarget.\n\t\t*/\n\t\tint speed = MaxSpeed;\n\t\tif (speed == MPH_LIGHT_SPEED) speed = MPH_IMMOBILE;\n\t\tif (Class->IsArcing) {\n\t\t\tspeed = MaxSpeed + (Distance(tcoord) / 32);\n\n\t\t\t/*\n\t\t\t**\tSet minimum speed (i.e., distance) for arcing projectiles.\n\t\t\t*/\n\t\t\tspeed = max(speed, 25);\n\t\t}\n\t\tif (!Class->IsDropping) {\n\t\t\tFly_Speed(255, (MPHType)speed);\n\t\t}\n\n\t\t/*\n\t\t**\tArm the fuse.\n\t\t*/\n\t\tArm_Fuse(Coord, tcoord, range, ((As_Aircraft(TarCom)!=0) ? 0 : Class->Arming));\n\n\t\t/*\n\t\t**\tProjectiles that make a ballistic flight to impact point must determine a\n\t\t**\tvertical component for the projectile launch. This is crudely simulated\n\t\t**\tby biasing ground speed according to target distance and then giving\n\t\t**\tenough vertical velocity to keep the projectile airborne for the\n\t\t**\tdesired amount of time. The mathematically correct solution would be to\n\t\t**\tcalculate launch angle (given fixed projectile velocity) and then derive\n\t\t**\tthe vertical and horizontal components. That solution would require a\n\t\t**\tsquare root and an arcsine lookup table. OUCH!\n\t\t*/\n\t\tRiser = 0;\n\t\tif (Class->IsArcing) {\n\t\t\tIsFalling = true;\n\t\t\tHeight = 1;\n\t\t\tRiser = ((Distance(tcoord)/2) / (speed+1)) * Rule.Gravity;\n\t\t\tRiser = max(Riser, 10);\n\t\t}\n\t\tif (Class->IsDropping) {\n\t\t\tIsFalling = true;\n\t\t\tHeight = FLIGHT_LEVEL;\n//\t\t\tHeight = Pixel_To_Lepton(24);\n\t\t\tRiser = 0;\n\t\t\tif (Class->IsParachuted) {\n\t\t\t\tAnimClass * anim = new AnimClass(ANIM_PARA_BOMB, Target_Coord());\n//\t\t\t\tAnimClass * anim = new AnimClass(ANIM_PARACHUTE, Target_Coord());\n\t\t\t\tif (anim) {\n\t\t\t\t\tanim->Attach_To(this);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tMap.Submit(this, In_Which_Layer());\n\n\t\tPrimaryFacing = dir;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BulletClass::Target_Coord -- Fetches coordinate to use when firing on this object.          *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate that should be used when firing at the object.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE BulletClass::Target_Coord(void) const\n{\n\tassert(Bullets.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(Coord_Add(XY_Coord(0, -Height), Coord));\n}\n\n\n/***********************************************************************************************\n * BulletClass::Sort_Y -- Sort coordinate for bullet rendering.                                *\n *                                                                                             *\n *    This will return the coordinate to use when sorting this bullet in the display list.     *\n *    Typically, this only occurs for bullets in the ground layer. Since bullets are to be     *\n *    seen a bit more than the normal sorting order would otherwise imply, bias the sort       *\n *    value such that bullets will tend to be drawn on top of the objects.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate to use when sorting this bullet in the display list.   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE BulletClass::Sort_Y(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(Coord_Move(Coord, DIR_S, CELL_LEPTON_H/2));\n}\n\n\n/***********************************************************************************************\n * BulletClass::In_Which_Layer -- Fetches the layer that the bullet resides in.                *\n *                                                                                             *\n *    This examines the bullet to determine what rendering layer it should be in. The          *\n *    normal logic applies unless this is a torpedo. A torpedo is always in the surface        *\n *    layer.                                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the render layer that this bullet should reside in.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLayerType BulletClass::In_Which_Layer(void) const\n{\n\tif (Class->IsSubSurface) {\n\t\treturn(LAYER_SURFACE);\n\t}\n\treturn(ObjectClass::In_Which_Layer());\n}\n\n\n/***********************************************************************************************\n * BulletClass::Is_Forced_To_Explode -- Checks if bullet should explode NOW.                   *\n *                                                                                             *\n *    This routine will examine the bullet and where it is travelling in order to determine    *\n *    if it should prematurely explode. Typical of this would be when a bullet hits a wall     *\n *    or a torpedo hits a ship -- regardless of where the projectile was originally aimed.     *\n *                                                                                             *\n * INPUT:   coord -- The new coordinate to place the bullet at presuming it is forced to       *\n *                   explode and a modification of the bullet's coordinate is needed.          *\n *                   Otherwise, the coordinate is not modified.                                *\n *                                                                                             *\n * OUTPUT:  bool; Should the bullet explode now?                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BulletClass::Is_Forced_To_Explode(COORDINATE & coord) const\n{\n\tcoord = Coord;\n\tCellClass const * cellptr = &Map[coord];\n\n\t/*\n\t**\tCheck for impact on a wall or other high obstacle.\n\t*/\n\tif (!Class->IsHigh && cellptr->Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(cellptr->Overlay).IsHigh) {\n\t\tcoord = Cell_Coord(Coord_Cell(coord));\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tCheck to make sure that underwater projectiles (torpedoes) will not\n\t**\ttravel in anything but water.\n\t*/\n\tif (Class->IsSubSurface) {\n\t\tint d = ::Distance(Coord_Fraction(coord), XY_Coord(CELL_LEPTON_W/2, CELL_LEPTON_W/2));\n\t\tif (cellptr->Land_Type() != LAND_WATER || (d < CELL_LEPTON_W/3 && cellptr->Cell_Techno() != NULL && cellptr->Cell_Techno() != Payback)) {\n\n\t\t\t/*\n\t\t\t**\tForce explosion to be at center of techno object if one is present.\n\t\t\t*/\n\t\t\tif (cellptr->Cell_Techno() != NULL) {\n\t\t\t\tcoord = cellptr->Cell_Techno()->Target_Coord();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tHowever, if the torpedo was blocked by a bridge, then force the\n\t\t\t**\ttorpedo to explode on top of that bridge cell.\n\t\t\t*/\n\t\t\tif (cellptr->Is_Bridge_Here()) {\n\t\t\t\tcoord = Coord_Snap(coord);\n\t\t\t}\n\n\t\t\treturn(true);\n\t\t}\n\t}\n\n\t/*\n\t**\tBullets are generally more effective when they are fired at aircraft.\n\t*/\n\tif (Class->IsAntiAircraft && As_Aircraft(TarCom) && Distance(TarCom) < 0x0080) {\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tNo reason for forced explosion was detected, so return 'false' to\n\t**\tindicate that no forced explosion is required.\n\t*/\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BulletClass::Bullet_Explodes -- Performs bullet explosion logic.                            *\n *                                                                                             *\n *    This handles the exploding bullet action. It will generate the animation and the         *\n *    damage as necessary.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The bullet should be deleted after this routine is called.                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BulletClass::Bullet_Explodes(bool forced)\n{\n\t/*\n\t**\tWhen the target is reached, explode and do the damage\n\t**\trequired of it. For homing objects, don't force the explosion to\n\t**\tmatch the target position. Non-homing projectiles adjust position so\n\t**\tthat they hit the target. This compensates for the error in line of\n\t**\tflight logic.\n\t*/\n\tif ( (Payback != NULL && Payback->What_Am_I() == RTTI_INFANTRY && ((InfantryClass *)Payback)->Class->IsDog) ||\n\t\t(!forced && !Class->IsArcing && Class->ROT == 0 && Fuse_Target())) {\n\t\tCoord = Fuse_Target();\n\t}\n\n\t/*\n\t**\tNon-aircraft targets apply damage to the ground.\n\t*/\n\tif (!Is_Target_Aircraft(TarCom) || As_Aircraft(TarCom)->In_Which_Layer() == LAYER_GROUND) {\n\t\tExplosion_Damage(Coord, Strength, Payback, Warhead);\n\t\tif (!IsActive) return;\n\n\t} else {\n\n\t\t/*\n\t\t**\tSpecial damage apply for SAM missiles. This is the only way that missile\n\t\t**\tdamage affects the aircraft target.\n\t\t*/\n\t\tif (Distance(TarCom) < 0x0080) {\n\t\t\tAircraftClass * object = As_Aircraft(TarCom);\n\n\t\t\tint str = Strength;\n\t\t\tif (object) object->Take_Damage(str, 0, Warhead, Payback);\n\t\t}\n\t}\n\n\t/*\n\t**\tFor projectiles that are invisible while travelling toward the target,\n\t**\tallow scatter effect for the impact animation.\n\t*/\n\tif (Class->IsInvisible) {\n\t\tCoord = Coord_Scatter(Coord, 0x0020);\n\t}\n\n\t/*\n\t**\tFetch the land type that the explosion will be upon. Special case for\n\t**\tflying aircraft targets, their land type will be LAND_NONE.\n\t*/\n\tCellClass const * cellptr = &Map[Coord];\n\tLandType land = cellptr->Land_Type();\n\tif (Is_Target_Aircraft(TarCom) && As_Aircraft(TarCom)->In_Which_Layer() == LAYER_TOP) {\n\t\tland = LAND_NONE;\n\t}\n\n\tAnimType anim = Combat_Anim(Strength, Warhead, land);\n\n\t/*\n\t** If it's a water explosion that's going to play, don't play it\n\t** if its cell is the same as the center cell of the target ship.\n\t*/\n\tif (anim >= ANIM_WATER_EXP1 && anim <= ANIM_WATER_EXP3 && Is_Target_Vessel(TarCom)) {\n\t\tif (Coord_Cell(Coord) == Coord_Cell(As_Vessel(TarCom)->Center_Coord())) {\n\t\t\tanim = (AnimType) (ANIM_VEH_HIT1 + (anim - ANIM_WATER_EXP1));\n\t\t}\n\t}\n\n\tif (anim != ANIM_NONE) {\n\t\tAnimClass * aptr = new AnimClass(anim, Coord);\n\t\t/*\n\t\t** Special case trap: if they're making the nuclear explosion,\n\t\t** and no anim is available, force the nuclear damage anyway\n\t\t** because nuke damage is done in the middle of the animation\n\t\t** and if there's no animation, there won't be any damage.\n\t\t*/\n\t\tif (!aptr && anim == ANIM_ATOM_BLAST) {\n\t\t\tHousesType house = HOUSE_NONE;\n\t\t\tif (Payback) {\n\t\t\t\thouse = Payback->House->Class->House;\n\t\t\t}\n\t\t\tAnimClass::Do_Atom_Damage(house, Coord_Cell(Coord));\n\t\t}\n\t}\n\n//\t\t\t\tif (Payback && Payback->House == PlayerPtr && stricmp(Class->Name(), \"GPSSATELLITE\") == 0) {\n\tif (Payback && Class->Type == BULLET_GPS_SATELLITE) {\n\t\tif (Payback->House == PlayerPtr) {\n\t\t\tif (!Map.Is_Radar_Active()) {\n\t\t\t\tMap.Radar_Activate(1);\n\t\t\t}\n\t\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\tMap.Map_Cell(cell, PlayerPtr);\n\t\t\t}\n\t\t\tMap.RadarClass::Flag_To_Redraw(true);\n\t\t}\n//\t\t\t\t\tSound_Effect(VOC_SATTACT2);\n\t\tPayback->House->IsGPSActive = true;\n\t\tPayback->House->IsVisionary = true;\n\t}\n}\n"
  },
  {
    "path": "CODE/BULLET.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/BULLET.H 2     3/06/97 1:46p Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BULLET.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 23, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BULLET_H\n#define BULLET_H\n\n#include \"object.h\"\n#include\t\"fly.h\"\n#include\t\"fuse.h\"\n\n\nclass BulletClass :\tpublic ObjectClass,\n\t\t\t\t\t\t\tpublic FlyClass,\n\t\t\t\t\t\t\tpublic FuseClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tThis specifies exactly what kind of bullet this is. All of the static attributes\n\t\t**\tfor this bullet is located in the BulletTypeClass pointed to by this variable.\n\t\t*/\n\t\tCCPtr<BulletTypeClass> Class;\n\n\tprivate:\n\t\t/*\n\t\t**\tRecords who sent this \"present\" so that an appropriate \"thank you\" can\n\t\t**\tbe returned.\n\t\t*/\n\t\tTechnoClass * Payback;\n\n\t\t/*\n\t\t**\tThis is the facing that the projectile is travelling.\n\t\t*/\n\t\tFacingClass PrimaryFacing;\n\n\tpublic:\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\t\tBulletClass(BulletType id, TARGET target, TechnoClass * Payback, int strength, WarheadType warhead, int speed);\n#ifdef FIXIT_MULTI_SAVE\n\t\tBulletClass(NoInitClass const & x) : ObjectClass(x), Class(x), FlyClass(x), FuseClass(x), PrimaryFacing(x) {};\n#else\n\t\tBulletClass(NoInitClass const & x) : ObjectClass(x), Class(x), FlyClass(x), FuseClass(x) {};\n#endif\n\t\tvirtual ~BulletClass(void);\n\t\toperator BulletType(void) const {return Class->Type;};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tstatic void Init(void);\n\n\t\tbool Is_Forced_To_Explode(COORDINATE & coord) const;\n\t\tvoid Bullet_Explodes(bool forced);\n\t\tint Shape_Number(void) const;\n\t\tvirtual LayerType In_Which_Layer(void) const;\n\t\tvirtual COORDINATE Sort_Y(void) const;\n\t\tvirtual void Assign_Target(TARGET target) {TarCom = target;};\n\t\tvirtual bool Unlimbo(COORDINATE , DirType facing = DIR_N);\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const {return *Class;};\n\t\tvirtual void Detach(TARGET target, bool all);\n\t\tvirtual void Draw_It(int x, int y, WindowNumberType window) const;\n\t\tvirtual bool Mark(MarkType mark=MARK_CHANGE);\n\t\tvirtual void AI(void);\n\t\tvirtual short const * Occupy_List(bool = false) const;\n\t\tvirtual short const * Overlap_List(void) const {return Occupy_List(false);};\n\t\tvirtual COORDINATE Target_Coord(void) const;\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n\n\t\t/*\n\t\t**\tIf this bullet is forced to be inaccurate because of some outside means. A tank\n\t\t**\tfiring while moving is a good example.\n\t\t*/\n\t\tunsigned IsInaccurate:1;\n\n\tprivate:\n\t\t// Crude animation flag.\n\t\tunsigned IsToAnimate:1;\n\n\t\t/*\n\t\t** Is this missile allowed to come in from out of bounds?\n\t\t*/\n\t\tunsigned IsLocked:1;\n\n\t\t/*\n\t\t**\tThis is the target of the projectile. It is especially significant for those projectiles\n\t\t**\tthat home in on a target.\n\t\t*/\n\t\tTARGET TarCom;\n\n\t\t/*\n\t\t**\tThe speed of this projectile.\n\t\t*/\n\t\tint MaxSpeed;\n\n\t\t/*\n\t\t**\tThe warhead of this projectile.\n\t\t*/\n\t\tWarheadType Warhead;\n};\n\n#endif\n\n"
  },
  {
    "path": "CODE/C&CZERO.PJT",
    "content": ";Codewright Project File (do not remove or modify this line)\n[ProjInit]\nProjSetConfigFlags=0x00010140\n\n[Files]\nc:\\projects\\c&c\\code\\aadata.cpp\nc:\\projects\\c&czero\\code\\aadata.cpp\nc:\\projects\\c&czero\\code\\abstract.cpp\nc:\\projects\\c&czero\\code\\abstract.h\nc:\\projects\\c&czero\\code\\adata.cpp\nc:\\projects\\c&czero\\code\\ADPCM.CPP\nc:\\projects\\c&czero\\code\\aircraft.cpp\nc:\\projects\\c&czero\\code\\aircraft.h\nc:\\projects\\c&czero\\code\\alloc.cpp\nc:\\projects\\c&czero\\code\\anim.cpp\nc:\\projects\\c&czero\\code\\anim.h\nc:\\projects\\c&czero\\code\\audio.cpp\nc:\\projects\\c&czero\\code\\audio.h\nc:\\projects\\c&czero\\code\\base.cpp\nc:\\projects\\c&czero\\code\\base.h\nc:\\projects\\c&czero\\code\\bbdata.cpp\nc:\\projects\\c&czero\\code\\bdata.cpp\nc:\\projects\\c&czero\\code\\BFIOFILE.CPP\nc:\\projects\\c&czero\\code\\BFIOFILE.H\nc:\\projects\\c&czero\\code\\building.cpp\nc:\\projects\\c&czero\\code\\building.h\nc:\\projects\\c&czero\\code\\bullet.cpp\nc:\\projects\\c&czero\\code\\bullet.h\nc:\\projects\\c&czero\\code\\cargo.cpp\nc:\\projects\\c&czero\\code\\cargo.h\nc:\\projects\\c&czero\\code\\CARRY.CPP\nc:\\projects\\c&czero\\code\\CARRY.H\nc:\\projects\\c&czero\\code\\ccfile.cpp\nc:\\projects\\c&czero\\code\\ccfile.h\nc:\\projects\\c&czero\\code\\cdata.cpp\nc:\\projects\\c&czero\\code\\cdfile.cpp\nc:\\projects\\c&czero\\code\\cdfile.h\nc:\\projects\\c&czero\\code\\cell.cpp\nc:\\projects\\c&czero\\code\\cell.h\nc:\\projects\\c&czero\\code\\checkbox.cpp\nc:\\projects\\c&czero\\code\\checkbox.h\nc:\\projects\\c&czero\\code\\cheklist.cpp\nc:\\projects\\c&czero\\code\\cheklist.h\nc:\\projects\\c&czero\\code\\colrlist.cpp\nc:\\projects\\c&czero\\code\\colrlist.h\nc:\\projects\\c&czero\\code\\combat.cpp\nc:\\projects\\c&czero\\code\\combuf.cpp\nc:\\projects\\c&czero\\code\\combuf.h\nc:\\projects\\c&czero\\code\\compat.h\nc:\\projects\\c&czero\\code\\comqueue.cpp\nc:\\projects\\c&czero\\code\\comqueue.h\nc:\\projects\\c&czero\\code\\confdlg.cpp\nc:\\projects\\c&czero\\code\\confdlg.h\nc:\\projects\\c&czero\\code\\connect.cpp\nc:\\projects\\c&czero\\code\\connect.h\nc:\\projects\\c&czero\\code\\connmgr.h\nc:\\projects\\c&czero\\code\\conquer.cpp\nc:\\projects\\c&czero\\code\\conquer.h\nc:\\projects\\c&czero\\code\\const.cpp\nc:\\projects\\c&czero\\code\\control.cpp\nc:\\projects\\c&czero\\code\\control.h\nc:\\projects\\c&czero\\code\\coord.cpp\nc:\\projects\\c&czero\\code\\crc.cpp\nc:\\projects\\c&czero\\code\\crc.h\nc:\\projects\\c&czero\\code\\credits.cpp\nc:\\projects\\c&czero\\code\\credits.h\nc:\\projects\\c&czero\\code\\crew.cpp\nc:\\projects\\c&czero\\code\\crew.h\nc:\\projects\\c&czero\\code\\cwstub.c\nc:\\projects\\c&czero\\code\\debug.cpp\nc:\\projects\\c&czero\\code\\debug.h\nc:\\projects\\c&czero\\code\\defines.h\nc:\\projects\\c&czero\\code\\descdlg.cpp\nc:\\projects\\c&czero\\code\\descdlg.h\nc:\\projects\\c&czero\\code\\dial8.cpp\nc:\\projects\\c&czero\\code\\dial8.h\nc:\\projects\\c&czero\\code\\dialog.cpp\nc:\\projects\\c&czero\\code\\display.cpp\nc:\\projects\\c&czero\\code\\display.h\nc:\\projects\\c&czero\\code\\door.cpp\nc:\\projects\\c&czero\\code\\door.h\nc:\\projects\\c&czero\\code\\dpmi.cpp\nc:\\projects\\c&czero\\code\\dpmi.h\nc:\\projects\\c&czero\\code\\drive.cpp\nc:\\projects\\c&czero\\code\\drive.h\nc:\\projects\\c&czero\\code\\drop.cpp\nc:\\projects\\c&czero\\code\\drop.h\nc:\\projects\\c&czero\\code\\DTABLE.CPP\nc:\\projects\\c&czero\\code\\edit.cpp\nc:\\projects\\c&czero\\code\\edit.h\nc:\\projects\\c&czero\\code\\ending.cpp\nc:\\projects\\c&czero\\code\\ending.h\nc:\\projects\\c&czero\\code\\event.cpp\nc:\\projects\\c&czero\\code\\event.h\nc:\\projects\\c&czero\\code\\expand.cpp\nc:\\projects\\c&czero\\code\\externs.h\nc:\\projects\\c&czero\\code\\FACE.CPP\nc:\\projects\\c&czero\\code\\FACE.H\nc:\\projects\\c&czero\\code\\facing.cpp\nc:\\projects\\c&czero\\code\\facing.h\nc:\\projects\\c&czero\\code\\factory.cpp\nc:\\projects\\c&czero\\code\\factory.h\nc:\\projects\\c&czero\\code\\findpath.cpp\nc:\\projects\\c&czero\\code\\flasher.cpp\nc:\\projects\\c&czero\\code\\flasher.h\nc:\\projects\\c&czero\\code\\fly.cpp\nc:\\projects\\c&czero\\code\\fly.h\nc:\\projects\\c&czero\\code\\foot.cpp\nc:\\projects\\c&czero\\code\\foot.h\nc:\\projects\\c&czero\\code\\ftimer.h\nc:\\projects\\c&czero\\code\\function.h\nc:\\projects\\c&czero\\code\\fuse.cpp\nc:\\projects\\c&czero\\code\\fuse.h\nc:\\projects\\c&czero\\code\\gadget.cpp\nc:\\projects\\c&czero\\code\\gadget.h\nc:\\projects\\c&czero\\code\\gamedlg.cpp\nc:\\projects\\c&czero\\code\\gamedlg.h\nc:\\projects\\c&czero\\code\\gauge.cpp\nc:\\projects\\c&czero\\code\\gauge.h\nc:\\projects\\c&czero\\code\\globals.cpp\nc:\\projects\\c&czero\\code\\goptions.cpp\nc:\\projects\\c&czero\\code\\goptions.h\nc:\\projects\\c&czero\\code\\gscreen.cpp\nc:\\projects\\c&czero\\code\\gscreen.h\nc:\\projects\\c&czero\\code\\hdata.cpp\nc:\\projects\\c&czero\\code\\heap.cpp\nc:\\projects\\c&czero\\code\\heap.h\nc:\\projects\\c&czero\\code\\help.cpp\nc:\\projects\\c&czero\\code\\help.h\nc:\\projects\\c&czero\\code\\house.cpp\nc:\\projects\\c&czero\\code\\house.h\nc:\\projects\\c&czero\\code\\HSV.CPP\nc:\\projects\\c&czero\\code\\HSV.H\nc:\\projects\\c&czero\\code\\idata.cpp\nc:\\projects\\c&czero\\code\\infantry.cpp\nc:\\projects\\c&czero\\code\\infantry.h\nc:\\projects\\c&czero\\code\\ini.cpp\nc:\\projects\\c&czero\\code\\inibin.cpp\nc:\\projects\\c&czero\\code\\inicode.cpp\nc:\\projects\\c&czero\\code\\init.cpp\nc:\\projects\\c&czero\\code\\intro.cpp\nc:\\projects\\c&czero\\code\\intro.h\nc:\\projects\\c&czero\\code\\iomap.cpp\nc:\\projects\\c&czero\\code\\ioobj.cpp\nc:\\projects\\c&czero\\code\\ipx.cpp\nc:\\projects\\c&czero\\code\\ipx.h\nc:\\projects\\c&czero\\code\\ipxaddr.cpp\nc:\\projects\\c&czero\\code\\ipxaddr.h\nc:\\projects\\c&czero\\code\\ipxconn.cpp\nc:\\projects\\c&czero\\code\\ipxconn.h\nc:\\projects\\c&czero\\code\\ipxgconn.cpp\nc:\\projects\\c&czero\\code\\ipxgconn.h\nc:\\projects\\c&czero\\code\\ipxmgr.cpp\nc:\\projects\\c&czero\\code\\ipxmgr.h\nc:\\projects\\c&czero\\code\\itable.cpp\nc:\\projects\\c&czero\\code\\jshell.cpp\nc:\\projects\\c&czero\\code\\jshell.h\nc:\\projects\\c&czero\\code\\keyframe.cpp\nc:\\projects\\c&czero\\code\\layer.cpp\nc:\\projects\\c&czero\\code\\layer.h\nc:\\projects\\c&czero\\code\\lcwuncmp.cpp\nc:\\projects\\c&czero\\code\\led.h\nc:\\projects\\c&czero\\code\\link.cpp\nc:\\projects\\c&czero\\code\\link.h\nc:\\projects\\c&czero\\code\\lint.h\nc:\\projects\\c&czero\\code\\list.cpp\nc:\\projects\\c&czero\\code\\list.h\nc:\\projects\\c&czero\\code\\loaddlg.cpp\nc:\\projects\\c&czero\\code\\loaddlg.h\nc:\\projects\\c&czero\\code\\logic.cpp\nc:\\projects\\c&czero\\code\\logic.h\nc:\\projects\\c&czero\\code\\map.cpp\nc:\\projects\\c&czero\\code\\map.h\nc:\\projects\\c&czero\\code\\mapeddlg.cpp\nc:\\projects\\c&czero\\code\\mapedit.cpp\nc:\\projects\\c&czero\\code\\mapedit.h\nc:\\projects\\c&czero\\code\\mapedplc.cpp\nc:\\projects\\c&czero\\code\\mapedsel.cpp\nc:\\projects\\c&czero\\code\\mapedtm.cpp\nc:\\projects\\c&czero\\code\\mapsel.cpp\nc:\\projects\\c&czero\\code\\menus.cpp\nc:\\projects\\c&czero\\code\\message.h\nc:\\projects\\c&czero\\code\\mission.cpp\nc:\\projects\\c&czero\\code\\mission.h\nc:\\projects\\c&czero\\code\\mixfile.cpp\nc:\\projects\\c&czero\\code\\mixfile.h\nc:\\projects\\c&czero\\code\\monoc.cpp\nc:\\projects\\c&czero\\code\\monoc.h\nc:\\projects\\c&czero\\code\\mouse.cpp\nc:\\projects\\c&czero\\code\\mouse.h\nc:\\projects\\c&czero\\code\\mplayer.cpp\nc:\\projects\\c&czero\\code\\msgbox.cpp\nc:\\projects\\c&czero\\code\\msgbox.h\nc:\\projects\\c&czero\\code\\msglist.cpp\nc:\\projects\\c&czero\\code\\msglist.h\nc:\\projects\\c&czero\\code\\netdlg.cpp\nc:\\projects\\c&czero\\code\\nullconn.cpp\nc:\\projects\\c&czero\\code\\nullconn.h\nc:\\projects\\c&czero\\code\\nulldlg.cpp\nc:\\projects\\c&czero\\code\\nullmgr.cpp\nc:\\projects\\c&czero\\code\\nullmgr.h\nc:\\projects\\c&czero\\code\\object.cpp\nc:\\projects\\c&czero\\code\\object.h\nc:\\projects\\c&czero\\code\\odata.cpp\nc:\\projects\\c&czero\\code\\options.cpp\nc:\\projects\\c&czero\\code\\options.h\nc:\\projects\\c&czero\\code\\overlay.cpp\nc:\\projects\\c&czero\\code\\overlay.h\nc:\\projects\\c&czero\\code\\PALETTE.CPP\nc:\\projects\\c&czero\\code\\PALETTE.H\nc:\\projects\\c&czero\\code\\phone.h\nc:\\projects\\c&czero\\code\\power.cpp\nc:\\projects\\c&czero\\code\\power.h\nc:\\projects\\c&czero\\code\\profile.cpp\nc:\\projects\\c&czero\\code\\queue.cpp\nc:\\projects\\c&czero\\code\\queue.h\nc:\\projects\\c&czero\\code\\radar.cpp\nc:\\projects\\c&czero\\code\\radar.h\nc:\\projects\\c&czero\\code\\radio.cpp\nc:\\projects\\c&czero\\code\\radio.h\nc:\\projects\\c&czero\\code\\rand.cpp\nc:\\projects\\c&czero\\code\\RANDOM.CPP\nc:\\projects\\c&czero\\code\\RANDOM.H\nc:\\projects\\c&czero\\code\\rawfile.cpp\nc:\\projects\\c&czero\\code\\rawfile.h\nc:\\projects\\c&czero\\code\\region.h\nc:\\projects\\c&czero\\code\\reinf.cpp\nc:\\projects\\c&czero\\code\\RGB.CPP\nc:\\projects\\c&czero\\code\\RGB.H\nc:\\projects\\c&czero\\code\\ROTBMP.CPP\nc:\\projects\\c&czero\\code\\ROTBMP.H\nc:\\projects\\c&czero\\code\\savedlg.h\nc:\\projects\\c&czero\\code\\saveload.cpp\nc:\\projects\\c&czero\\code\\scenario.cpp\nc:\\projects\\c&czero\\code\\SCENARIO.H\nc:\\projects\\c&czero\\code\\score.cpp\nc:\\projects\\c&czero\\code\\score.h\nc:\\projects\\c&czero\\code\\screen.h\nc:\\projects\\c&czero\\code\\scroll.cpp\nc:\\projects\\c&czero\\code\\scroll.h\nc:\\projects\\c&czero\\code\\sdata.cpp\nc:\\projects\\c&czero\\code\\SESSION.CPP\nc:\\projects\\c&czero\\code\\SESSION.H\nc:\\projects\\c&czero\\code\\shapebtn.cpp\nc:\\projects\\c&czero\\code\\shapebtn.h\nc:\\projects\\c&czero\\code\\sidebar.cpp\nc:\\projects\\c&czero\\code\\sidebar.h\nc:\\projects\\c&czero\\code\\slider.cpp\nc:\\projects\\c&czero\\code\\slider.h\nc:\\projects\\c&czero\\code\\smudge.cpp\nc:\\projects\\c&czero\\code\\smudge.h\nc:\\projects\\c&czero\\code\\sounddlg.cpp\nc:\\projects\\c&czero\\code\\sounddlg.h\nc:\\projects\\c&czero\\code\\special.cpp\nc:\\projects\\c&czero\\code\\special.h\nc:\\projects\\c&czero\\code\\SPRITE.CPP\nc:\\projects\\c&czero\\code\\stage.h\nc:\\projects\\c&czero\\code\\startup.cpp\nc:\\projects\\c&czero\\code\\super.cpp\nc:\\projects\\c&czero\\code\\super.h\nc:\\projects\\c&czero\\code\\tab.cpp\nc:\\projects\\c&czero\\code\\tab.h\nc:\\projects\\c&czero\\code\\TACTION.CPP\nc:\\projects\\c&czero\\code\\TACTION.H\nc:\\projects\\c&czero\\code\\target.cpp\nc:\\projects\\c&czero\\code\\target.h\nc:\\projects\\c&czero\\code\\tdata.cpp\nc:\\projects\\c&czero\\code\\team.cpp\nc:\\projects\\c&czero\\code\\team.h\nc:\\projects\\c&czero\\code\\teamtype.cpp\nc:\\projects\\c&czero\\code\\teamtype.h\nc:\\projects\\c&czero\\code\\techno.cpp\nc:\\projects\\c&czero\\code\\techno.h\nc:\\projects\\c&czero\\code\\template.cpp\nc:\\projects\\c&czero\\code\\template.h\nc:\\projects\\c&czero\\code\\terrain.cpp\nc:\\projects\\c&czero\\code\\terrain.h\nc:\\projects\\c&czero\\code\\TEVENT.CPP\nc:\\projects\\c&czero\\code\\TEVENT.H\nc:\\projects\\c&czero\\code\\textbtn.cpp\nc:\\projects\\c&czero\\code\\textbtn.h\nc:\\projects\\c&czero\\code\\theme.cpp\nc:\\projects\\c&czero\\code\\theme.h\nc:\\projects\\c&czero\\code\\toggle.cpp\nc:\\projects\\c&czero\\code\\toggle.h\nc:\\projects\\c&czero\\code\\trigger.cpp\nc:\\projects\\c&czero\\code\\trigger.h\nc:\\projects\\c&czero\\code\\txtlabel.cpp\nc:\\projects\\c&czero\\code\\txtlabel.h\nc:\\projects\\c&czero\\code\\type.h\nc:\\projects\\c&czero\\code\\udata.cpp\nc:\\projects\\c&czero\\code\\unit.cpp\nc:\\projects\\c&czero\\code\\unit.h\nc:\\projects\\c&czero\\code\\vdata.cpp\nc:\\projects\\c&czero\\code\\vector.cpp\nc:\\projects\\c&czero\\code\\vector.h\nc:\\projects\\c&czero\\code\\VERSION.CPP\nc:\\projects\\c&czero\\code\\VERSION.H\nc:\\projects\\c&czero\\code\\vessel.cpp\nc:\\projects\\c&czero\\code\\vessel.h\nc:\\projects\\c&czero\\code\\visudlg.cpp\nc:\\projects\\c&czero\\code\\visudlg.h\nc:\\projects\\c&czero\\code\\watcom.h\nc:\\projects\\c&czero\\code\\wwalloc.h\nc:\\projects\\c&czero\\code\\wwfile.h\nC:\\projects\\c&czero\\code\\2KEYFRAM.CPP\nC:\\projects\\c&czero\\code\\BLOWFISH.CPP\nC:\\projects\\c&czero\\code\\BLOWFISH.H\nC:\\projects\\c&czero\\code\\FILEPCX.H\nC:\\projects\\c&czero\\code\\INT.CPP\nC:\\projects\\c&czero\\code\\INT.H\nC:\\projects\\c&czero\\code\\interpal.cpp\nC:\\projects\\c&czero\\code\\language.h\nC:\\projects\\c&czero\\code\\MP.CPP\nC:\\projects\\c&czero\\code\\MP.H\nC:\\projects\\c&czero\\code\\RNG.H\nC:\\projects\\c&czero\\code\\SHA.CPP\nC:\\projects\\c&czero\\code\\SHA.H\nC:\\projects\\c&czero\\code\\tarcom.cpp\nC:\\projects\\c&czero\\code\\tcpip.h\nC:\\projects\\c&czero\\code\\winstub.cpp\nc:\\projects\\c&czero\\code\\BUFFERX.H\nc:\\projects\\c&czero\\code\\ini.h\nc:\\projects\\c&czero\\code\\listnode.h\nc:\\projects\\c&czero\\code\\rules.cpp\nc:\\projects\\c&czero\\code\\rules.h\nc:\\projects\\c&czero\\code\\tarcom.h\nc:\\projects\\c&czero\\code\\turret.cpp\nc:\\projects\\c&czero\\code\\turret.h\nc:\\projects\\c&czero\\code\\warhead.h\nc:\\projects\\c&czero\\code\\weapon.h\n\n[State]\nSysSetCwd='C:\\projects\\c&czero\\code'\nSrchSetFlags=0x000320aa\nFileSortMode=0x0\nStateWindowFrame=37,16,923,511,0x62c9f5fa\n_StateWindow=0,0,990,647,0x00100018,'C:\\projects\\c&czero\\code\\palette.cpp',240,15,244,32,32,0,32,32,32,32,8,4294967295,4294967295,1,10,'',12,255,48,0,7,243,252,253,247,249,247,93,1,400,0,246,252,248,244,247,15,15,15,15,0,0\n_StateBuffer='C:\\projects\\c&czero\\code\\palette.cpp',0x0400048e,93,1,25,'4 7','',0x0,''\n_StateBuffer='C:\\projects\\c&czero\\code\\jshell.h',0x0400048e,1,2,25,'4 7','',0x0,''\n_StateBuffer='C:\\projects\\c&czero\\code\\sprite.cpp',0x0400048e,35,1,25,'4 7','',0x0,''\n_StateBuffer='C:\\projects\\c&czero\\code\\wwfile.h',0x0400048e,21,1,25,'4 7','',0x0,''\n_StateBuffer='C:\\projects\\c&czero\\win32lib\\INCLUDE\\RAWFILE.H',0x0400048e,1,1,25,'4 7','',0x0,''\n_StateBuffer='C:\\projects\\c&czero\\code\\ROTBMP.H',0x0400048e,9,1,25,'4 7','',0x0,''\n_StateBuffer='C:\\projects\\c&czero\\code\\rotbmp.cpp',0x0400048e,6,1,25,'4 7','',0x0,''\n_StateBuffer='C:\\projects\\c&czero\\code\\function.h',0x0400048e,157,1,25,'4 7','',0x0,''\n_StateBuffer='C:\\projects\\c&czero\\wwflat32\\INCLUDE\\gbuffer.h',0x0400048e,265,26,25,'4 7','',0x0,''\n_StateBuffer='C:\\projects\\c&czero\\code\\anim.cpp',0x0400048e,682,1,25,'4 7','',0x0,''\n_StateBuffer='C:\\projects\\c&czero\\code\\makefile',0x0400048e,420,1,25,'5 9','',0x0,''\n_StateBuffer='C:\\projects\\c&czero\\code\\crc.cpp',0x0400048e,1,1,25,'4 7','',0x0,''\n_StateBuffer='C:\\projects\\c&czero\\code\\PALETTE.H',0x0400048e,1,1,25,'4 7','',0x0,''\n_StateHistory=SEARCH,'::Mission_U','Force_','MOUSE_','jshell','WindowsTim','LINKFILE','game.dat','wwflat','wwlib','Bitmap'\n_StateHistory=REPLACE,'building','bindex','vindex','iindex','AIRCRAFT','AircraftType','aircraft','aindex','_Scale_To_256','tech'\n_StateHistory=XMACRO,'small','sort','SORT','sort','SORT','sort','SORT','sort','SORT','sort'\n_StateHistory=FILELIST,'C:\\projects\\c&czero\\wwflat32\\INCLUDE\\gbuffer.h','C:\\projects\\c&czero\\code\\function.h','C:\\projects\\c&czero\\code\\rotbmp.cpp','C:\\projects\\c&czero\\code\\ROTBMP.H','C:\\projects\\c&czero\\code\\jshell.h','C:\\projects\\c&czero\\code\\palette.cpp','C:\\projects\\c&czero\\code\\crc.cpp','C:\\projects\\c&czero\\code\\makefile','C:\\projects\\c&czero\\code\\PALETTE.H','C:\\projects\\c&czero\\code\\anim.cpp'\n_StateHistory=EDITFILE,'palette.cpp','crc.cpp','makefile','palette.cpp','palette.h','makefile','anim.cpp','palette.cpp','function.h','jshell.h'\n_StateHistory=DIRECTORY,'c:\\\\','c:\\projects\\c&c\\code','e:\\c&czero\\code','e:','c:\\projects\\c&czero\\code','c:','C:\\PROJECTS\\C&Czero\\code','c:\\projects\\C&Czero\\code'\n_StateHistory=GOTOMARK,'2','1','2','1','2','3','1','2','3','1'\n_StateHistory=OUTNAME,'tab.cpp','power.cpp','2txtprnt.asm','display.cpp','scroll.cpp','sidebar.cpp','power.cpp','help.cpp','tab.cpp','mapeddlg.cpp'\n_StateHistory=GOTOLINE,'1665','410','93','375','590','231','246','616','384','686'\n_StateHistory=WBLOCK,'c:\\temp\\face.cpp','c:\\temp\\face.h'\n_StateHistory=FILTER,'sort'\n_StateHistory=DOSHISTORY,'eset path','ndos','eset path','set path=%PATH%;c:\\utils','ts *.cpp Interpolated','n','d:','exit','ts *.cpp Interpolated','exit'\n_StateMark=MARK_POSITION,1,'C:\\projects\\c&czero\\wwflat32\\INCLUDE\\gbuffer.h',265,25,0\n_StateMark=MARK_POSITION,1,'C:\\projects\\c&czero\\code\\jshell.h',1,1,0\n\n[Editor]\nClipboardSetTermStr='\\r\\n',0\nClipboardEnableTermStr=1\nClipboardSetSepStr='\\r\\n',0\nClipboardEnableSepStr=1\nScrapSetCount=1\nVCSProject=''\nVCSProjectPath=''\nVCSProjectLocalPath=''\n_RestoreSysFlags=0x6249f5fa, 0xfffffffc\n\n[Compiler]\nTagSetCmd='${HOME}${WTAGS} -oc -d -t${TAGFILE}.tag -p${TAGFILE}.ptg',0x8000060\nBrowseSetFile='c:\\projects\\c&czero\\code\\c&czero.ptg'\nTagSetFile='c:\\projects\\c&czero\\code\\c&czero.tag'\nCompilerAddCmd='Microsoft Assembler','ftee masm -w2 -zi %r%e;',1073741824,'',0,'',16,'',16,'',0,'',0,'_MicrosoftErrorInfo','','','','%v%p'\nCompilerAddResponse='Microsoft Assembler',\nCompilerAddCmd='Borland C++','ftee bcc -S %r.c',1073741824,'',0,'ftee make %r.obj',16,'ftee make %r.obj',16,'',0,'',0,'_BorlandCppErrorInfo','','','','%v%p'\nCompilerAddResponse='Borland C++',\nCompilerAddCmd='Borland Turbo Assembler','ftee make %r.obj',1073741824,'',0,'ftee make %r.obj',16,'',16,'',0,'',0,'_TasmErrorInfo','','','','%v%p'\nCompilerAddResponse='Borland Turbo Assembler',\nCompilerAddCmd='$_cw_proj_hash_$','',1073741825,'',1,'ftee watcom\\binw\\wmake %r.obj',209,'ftee m.bat',209,'ftee joemake',209,'g.bat -hansolo cheater -xm -editor',224,'_MSLinkErrorInfo','_MicrosoftErrorInfo','_NMakeErrorInfo','proj.err','c:\\projects\\c&czero\\code'\nCompilerAddResponse='$_cw_proj_hash_$',\nCompilerAddCmd='Default Project','',1073741824,'',0,'ftee make',16,'ftee make',16,'',0,'',0,'_ErrorInfoDefault','','','proj.err','%v%p'\nCompilerAddResponse='Default Project',\nCompilerAddCmd='Microsoft C','ftee cl -c -AL -Gsw -Ow -Zpe  %r%e',1073741824,'',0,'',16,'',16,'',0,'',0,'_MicrosoftErrorInfo','','','','%v%p'\nCompilerAddResponse='Microsoft C',\nCompilerAddCmd='Script','ftee make %r.inf',1073741824,'',0,'ftee make',16,'ftee make',16,'',0,'',0,'_BorlandCppErrorInfo','','','',''\nCompilerAddResponse='Script',\nCompilerAddCmd='Zortech C++','ftee ztc -a -b -c -g -ml -W %r%e',1073741824,'',0,'',16,'',16,'',0,'',0,'_ZortechCppErrorInfo','','','','%v%p'\nCompilerAddResponse='Zortech C++',\nCompilerAddCmd='Microsoft C(NT-i386)','${FTEE} cl -DSTRICT -c -W3 -G3 -D_X86_=1 -DWIN32 %r%e',1073741936,'${FTEE} cl -DSTRICT -c -W3 -G3 -D_X86_=1 -DWIN32 %r%e',112,'',144,'',144,'',0,'',0,'_MicrosoftErrorInfo','','','',''\nCompilerAddResponse='Microsoft C(NT-i386)',\nCompilerAssign='Borland C++','.scr'\nCompilerNewExt=.bas\nCompilerAssign='Borland C++','.int'\nCompilerAssign='Borland C++','.c'\nCompilerNewExt=.prg\nCompilerAssign='Microsoft C','.h'\nCompilerAssign='Borland C++','.cpp'\nCompilerAssign='Default Project','.*'\nCompilerAssign='Microsoft C(NT-i386)','.cxx'\nCompilerAssign='Borland Turbo Assembler','.asm'\nCompilerAssign='Microsoft C(NT-i386)','.hpp'\n"
  },
  {
    "path": "CODE/CARGO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CARGO.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CARGO.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : 10/31/94 [JLB]                                               *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CargoClass::Attach -- Add unit to cargo hold.                                             *\n *   CargoClass::Attached_Object -- Determine attached unit pointer.                           *\n *   CargoClass::Debug_Dump -- Displays the cargo value to the monochrome screen.              *\n *   CargoClass::Detach_Object -- Removes a unit from the cargo hold.                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * CargoClass::Debug_Dump -- Displays the cargo value to the monochrome screen.                *\n *                                                                                             *\n *    This routine is used to dump the current cargo value to the monochrome monitor.          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CargoClass::Debug_Dump(MonoClass * mono) const\n{\n\tif (How_Many()) {\n\t\tmono->Set_Cursor(63, 3);\n\t\tmono->Printf(\"(%d)%04X\", How_Many(), Attached_Object());\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * CargoClass::Attach -- Add unit to cargo hold.                                               *\n *                                                                                             *\n *    This routine will add the specified unit to the cargo hold. The                          *\n *    unit will chain to any existing units in the hold. The chaining is                       *\n *    in a LIFO order.                                                                         *\n *                                                                                             *\n * INPUT:   object-- Pointer to the object to attach to the cargo hold.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/23/1994 JLB : Created.                                                                 *\n *   10/31/94   JLB : Handles chained objects.                                                 *\n *=============================================================================================*/\nvoid CargoClass::Attach(FootClass * object)\n{\n\t/*\n\t**\tIf there is no object, then no action is necessary.\n\t*/\n\tif (object == NULL) return;\n\n\tobject->Limbo();\n\n\t/*\n\t**\tAttach any existing cargo hold object to the end of the list as indicated by the\n\t**\tobject pointer passed into this routine. This is necessary because several objects may\n\t**\tbe attached at one time or several objects may be attached as a result of several calls\n\t**\tto this routine. Either case must be handled properly.\n\t*/\n\tObjectClass * o = object->Next;\n\twhile (o != NULL) {\n\t\tif (o->Next == (void*)NULL) break;\n\t\to = o->Next;\n\t}\n\tif (o != NULL) {\n\t\to->Next = CargoHold;\n\t} else {\n\t\tobject->Next = CargoHold;\n\t}\n\n\t/*\n\t**\tFinally, assign the object pointer as the first object attached to this cargo hold.\n\t*/\n\tCargoHold = object;\n\tQuantity = 0;\n\tobject = CargoHold;\n\twhile (object != NULL) {\n\t\tQuantity++;\n\t\tobject = (FootClass *)(ObjectClass *)object->Next;\n\t}\n}\n\n\n/***********************************************************************************************\n * CargoClass::Detach_Object -- Removes a unit from the cargo hold.                            *\n *                                                                                             *\n *    This routine will take a unit from the cargo hold and extract it.                        *\n *    The unit extracted is the last unit added to the hold. If there                          *\n *    is no unit in the hold or the occupant is not a unit, then NULL is                       *\n *    returned.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the unit that has been extracted.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/23/1994 JLB : Created.                                                                 *\n *   06/07/1994 JLB : Handles generic object types.                                            *\n *=============================================================================================*/\nFootClass * CargoClass::Detach_Object(void)\n{\n\tTechnoClass * unit = Attached_Object();\n\n\tif (unit != NULL) {\n\t\tCargoHold = (FootClass *)(ObjectClass *)unit->Next;\n\t\tunit->Next = 0;\n\t\tQuantity--;\n\t}\n\treturn((FootClass *)unit);\n}\n\n\n/***********************************************************************************************\n * CargoClass::Attached_Object -- Determine attached unit pointer.                             *\n *                                                                                             *\n *    This routine will return with a pointer to the attached unit if one                      *\n *    is present. One would need to know this if this is a transport                           *\n *    unit and it needs to unload.                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to the attached unit. If there is no                             *\n *          attached unit, then return NULL.                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/07/1992 JLB : Created.                                                                 *\n *   06/07/1994 JLB : Handles generic object types.                                            *\n *=============================================================================================*/\nFootClass * CargoClass::Attached_Object(void) const\n{\n\tif (Is_Something_Attached()) {\n\t\treturn(CargoHold);\n\t}\n\treturn(NULL);\n}\n\n\n"
  },
  {
    "path": "CODE/CARGO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CARGO.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CARGO.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 23, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CARGO_H\n#define CARGO_H\n\nclass FootClass;\n\n/****************************************************************************\n**\tThis class handles the basic cargo logic.\n*/\nclass CargoClass {\n\tpublic:\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tCargoClass(void) : Quantity(0), CargoHold(0) {};\n\t\tCargoClass(NoInitClass const & ) {};\n\t\t~CargoClass(void) {CargoHold=0;};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\n\t\t#ifdef CHEAT_KEYS\n\t\tvoid Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\t\tvoid AI(void) {};\n\n\t\tint How_Many(void) const {return Quantity;};\n\t\tbool Is_Something_Attached(void) const {return (CargoHold != 0);};\n\t\tFootClass * Attached_Object(void) const;\n\t\tFootClass * Detach_Object(void);\n\t\tvoid Attach(FootClass * object);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvoid Code_Pointers(void);\n\t\tvoid Decode_Pointers(void);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is the number of objects attached to this cargo hold. For transporter\n\t\t**\tobjects, they might contain more than one object.\n\t\t*/\n\t\tunsigned char Quantity;\n\n\t\t/*\n\t\t**\tThis is the target value of any attached object. A value of zero indicates\n\t\t**\tthat no object is attached.\n\t\t*/\n\t\tFootClass * CargoHold;\n};\n\n#endif\n\n"
  },
  {
    "path": "CODE/CARRY.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CARRY.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CARRY.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/26/96                                                     *\n *                                                                                             *\n *                  Last Update : May 10, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CarryoverClass::CarryoverClass -- Constructor for carry over objects.                     *\n *   CarryoverClass::Create -- Creates a carried over object.                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * CarryoverClass::CarryoverClass -- Constructor for carry over objects.                       *\n *                                                                                             *\n *    This is the constructor for a carry over object. Such an object is used to record the    *\n *    object that will be \"carried over\" into a new scenario at some future time.              *\n *                                                                                             *\n * INPUT:   techno   -- Pointer to the object that will be carried over.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCarryoverClass::CarryoverClass(TechnoClass * techno) :\n\tRTTI(RTTI_NONE),\n\tCell(0),\n\tStrength(0),\n\tHouse(HOUSE_NONE)\n{\n\tif (techno) {\n\t\tRTTI = techno->What_Am_I();\n\n\t\tswitch (RTTI) {\n\t\t\tcase RTTI_UNIT:\n\t\t\t\tType.Unit = ((UnitClass *)techno)->Class->Type;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_BUILDING:\n\t\t\t\tType.Building = ((BuildingClass *)techno)->Class->Type;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_INFANTRY:\n\t\t\t\tType.Infantry = ((InfantryClass *)techno)->Class->Type;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_VESSEL:\n\t\t\t\tType.Vessel = ((VesselClass *)techno)->Class->Type;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tHouse = techno->Owner();\n\t\tStrength = techno->Strength;\n\t\tCell = Coord_Cell(techno->Coord);\n\t}\n}\n\n\n/***********************************************************************************************\n * CarryoverClass::Create -- Creates a carried over object.                                    *\n *                                                                                             *\n *    Use this routine to convert a carried over object into an actual object that will be     *\n *    placed on the map.                                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the object successfully created and placed on the map?                   *\n *                                                                                             *\n * WARNINGS:   This routine might not place the object if the old map location was invalid     *\n *             or there are other barriers to the object's creation and placement.             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CarryoverClass::Create(void) const\n{\n\tTechnoClass * techno = 0;\n\tTechnoTypeClass const * ttype = 0;\n\n\tswitch (RTTI) {\n\t\tcase RTTI_UNIT:\n\t\t\tttype = &UnitTypeClass::As_Reference(Type.Unit);\n\t\t\ttechno = new UnitClass(Type.Unit, House);\n\t\t\tbreak;\n\n\t\tcase RTTI_INFANTRY:\n\t\t\tttype = &InfantryTypeClass::As_Reference(Type.Infantry);\n\t\t\ttechno = new InfantryClass(Type.Infantry, House);\n\t\t\tbreak;\n\n\t\tcase RTTI_BUILDING:\n\t\t\tttype = &BuildingTypeClass::As_Reference(Type.Building);\n\t\t\ttechno = new BuildingClass(Type.Building, House);\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\t\tttype = &VesselTypeClass::As_Reference(Type.Vessel);\n\t\t\ttechno = new VesselClass(Type.Vessel, House);\n\t\t\tbreak;\n\t}\n\n\tif (techno) {\n\t\tbool oldscen = ScenarioInit;\n\t\ttechno->Strength = Strength;\n\t\tif (RTTI == RTTI_INFANTRY) {\n\t\t\tScenarioInit = 0;\n\t\t}\n\t\ttechno->Unlimbo(Cell_Coord(Cell));\n\t\tif (RTTI == RTTI_INFANTRY) {\n\t\t\tScenarioInit = oldscen;\n\t\t}\n\t}\n\n\treturn(false);\n}\n\n"
  },
  {
    "path": "CODE/CARRY.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CARRY.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CARRY.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/26/96                                                     *\n *                                                                                             *\n *                  Last Update : February 26, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef CARRY_H\n#define CARRY_H\n\nclass CarryoverClass : public LinkClass {\n\tpublic:\n\t\tCarryoverClass(TechnoClass * techno = 0);\n\t\tCarryoverClass(NoInitClass const & x) : LinkClass(x) {}\n\n\t\tbool Create(void) const;\n\n\tprotected:\n\t\t/*\n\t\t**\tWhat type of object this is.\n\t\t*/\n\t\tRTTIType RTTI;\n\n\t\t/*\n\t\t**\tThis is the object type that is to be carried over. The exact nature of\n\t\t**\tthis type depends on the RTTI value. Only certain object types are\n\t\t**\trecorded.\n\t\t*/\n\t\tunion {\n\t\t\tStructType Building;\n\t\t\tUnitType Unit;\n\t\t\tInfantryType Infantry;\n\t\t\tVesselType Vessel;\n\t\t} Type;\n\n\t\t/*\n\t\t**\tThe location of the object.\n\t\t*/\n\t\tCELL Cell;\n\n\t\t/*\n\t\t**\tThe strength of the object at the time is was recorded.\n\t\t*/\n\t\tint Strength;\n\n\t\t/*\n\t\t**\tThis is the owner of the object.\n\t\t*/\n\t\tHousesType House;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/CCDDE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer - Red Alert                                *\n *                                                                                             *\n *                    File Name : CCDDE.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 10/04/95                                                     *\n *                                                                                             *\n *                  Last Update : August 5th, 1996 [ST]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *   C&C's interface to the DDE class                                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n * DDE_Callback -- DDE server callback function                                                *\n * DDEServerClass::DDEServerClass -- class constructor                                         *\n * DDEServerClass::Enable -- Enables the DDE callback                                          *\n * DDEServerClass::Disable -- Disables the DDE callback                                        *\n * DDEServerClass::~DDEServerClass -- class destructor                                         *\n * DDESC::Callback -- callback function. Called from the DDE_Callback wrapper function         *\n * DDESC::Get_MPlayer_Game_Info -- returns a pointer to the multiplayer setup info from wchat  *\n * DDESC::Delete_MPlayer_Game_Info -- clears out multi player game setup info                  *\n * DDESC::Time_Since_Heartbeat -- returns the time in ticks since the last heartbeat from wchat*\n *                                                                                             *\n * Send_Data_To_DDE_Server -- sends a packet to WChat                                          *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifdef WIN32\n\n#include <WINDOWS.H>\n#include \"ccdde.h\"\n#include <stdio.h>\n#include <timer.h>\n\nDDEServerClass\tDDEServer;\t\t\t\t//Instance of the DDE Server class\n\nInstance_Class\t*DDE_Class = NULL;\t// pointer for client callback\n\t\t\t\t\t\t\t\t\t\t\t\t// this *must* be called DDE_Class\n\nBOOL RA95AlreadyRunning = FALSE;\t\t//Was there an instance of Red Alert 95 already running when we started?\n\n/*\n** Misc externs so we dont have to include FUNCTION.H\n*/\nextern HWND \t\t\tMainWindow;\nextern TimerClass\tGameTimer;\nextern BOOL\t\t\tGameTimerInUse;\nextern void \t\t\tWWDebugString (char *string);\n\n\n/***********************************************************************************************\n * DDE_Callback -- DDE server callback function                                                *\n *                                                                                             *\n *   Just acts as a wrapper for the DDEServerClass callback function                           *\n *                                                                                             *\n * INPUT:    ptr to data from client                                                           *\n *           length of data                                                                    *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/8/96 3:19PM ST : Created                                                               *\n *=============================================================================================*/\nBOOL CALLBACK DDE_Callback (unsigned char *data, long length)\n{\n\treturn (DDEServer.Callback(data, length));\n}\n\n\n\n\n/***********************************************************************************************\n * DDEServerClass::DDEServerClass -- class constructor                                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/8/96 3:20PM ST : Created                                                               *\n *=============================================================================================*/\nDDEServerClass::DDEServerClass(void)\n{\n\tMPlayerGameInfo = NULL;\t\t//Flag that we havnt received a start game info packet yet\n\n\t//DDE_Class = new Instance_Class (\"CONQUER\", \"WCHAT\");\n\tDDE_Class = new Instance_Class (\"REDALERT\", \"WCHAT\");\n\n\tDDE_Class->Enable_Callback( TRUE );\n\tIsEnabled = TRUE;\n\n\tif (DDE_Class->Test_Server_Running(DDE_Class->local_name)){\n\t\tRA95AlreadyRunning = TRUE;\n\t}else{\n\t\tDDE_Class->Register_Server( DDE_Callback );\n\t}\n}\n\n\n\n/***********************************************************************************************\n * DDEServerClass::Enable -- Enables the DDE callback                                          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/5/96 9:44PM ST : Created                                                               *\n *=============================================================================================*/\nvoid DDEServerClass::Enable(void)\n{\n\tif (!IsEnabled){\n\t\tDDE_Class->Enable_Callback( TRUE );\n\t\tIsEnabled = TRUE;\n\t}\n}\n\n\n\n/***********************************************************************************************\n * DDEServerClass::Disable -- Disables the DDE callback                                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/5/96 9:44PM ST : Created                                                               *\n *=============================================================================================*/\nvoid DDEServerClass::Disable(void)\n{\n\tif (IsEnabled){\n\t\tDDE_Class->Enable_Callback( FALSE );\n\t\tIsEnabled = FALSE;\n\t}\n}\n\n\n\n\n\n\n/***********************************************************************************************\n * DDEServerClass::~DDEServerClass -- class destructor                                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/8/96 3:20PM ST : Created                                                               *\n *=============================================================================================*/\nDDEServerClass::~DDEServerClass(void)\n{\n\tDelete_MPlayer_Game_Info();\n\tdelete( DDE_Class );\n}\n\n\n\n/***********************************************************************************************\n * DDESC::Callback -- callback function. Called from the DDE_Callback wrapper function         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    data from DDE client                                                              *\n *           length of data                                                                    *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: Data has length and type as first 2 ints                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/8/96 3:21PM ST : Created                                                               *\n *=============================================================================================*/\nBOOL DDEServerClass::Callback(unsigned char *data, long length)\n{\n\n\t/*\n\t** If the packet length < 0 then this is a special advisory packet\n\t*/\n\tif ( length<0 ) {\n\n\t\tswitch( length ) {\n\n\t\t\tcase\tDDE_ADVISE_CONNECT:\n\t\t\t\tWWDebugString(\"RA95 - DDE advisory: client connect detected.\");\n\t\t\t\treturn TRUE;\n\n\t\t\tcase\tDDE_ADVISE_DISCONNECT:\n\t\t\t\tWWDebugString(\"RA95 - DDE advisory: client disconnect detected.\");\n\t\t\t\treturn TRUE;\n\n\t\t\tdefault:\n\t\t\t\tWWDebugString(\"RA95 - DDE advisory: Unknown DDE advise type.\");\n\t\t\t\treturn FALSE;\n\t\t}\n\n\t}else{\n\n\t\t/*\n\t\t** Packet must be at least the length of the packet type & size fields to be valid\n\t\t*/\n\t\tif (length < 2*sizeof(int)) {\n\t\t\tWWDebugString (\"RA95 - Received invalid packet.\");\n\t\t\treturn (FALSE);\n\t\t}\n\n\t\t/*\n\t\t** Find out what kind of packet this is and its length.\n\t\t*/\n\t\tint *packet_pointer = (int *)data;\n\t\tint  actual_length = ntohl(*packet_pointer++);\n\t\tint  packet_type =  ntohl(*packet_pointer++);\n\n\t\t/*\n\t\t** Strip the ID int from the start of the packet\n\t\t*/\n\t\tdata   += 2*sizeof (int);\n\t\tlength -= 2*sizeof (int);\n\t\tactual_length -= 2*sizeof (int);\n\n\t\t/*\n\t\t** Take the appropriate action for the packet type\n\t\t*/\n\t\tswitch ( packet_type ){\n\n\t\t\t/*\n\t\t\t** This is a packet with the info required for starting a new internet game. This is really\n\t\t \t* just C&CSPAWN.INI sent from WChat instead of read from disk.\n\t\t\t*/\n\t\t\tcase DDE_PACKET_START_MPLAYER_GAME:\n\t\t\t\tWWDebugString(\"RA95 - Received start game packet.\");\n\t\t\t\tDelete_MPlayer_Game_Info();\n\t\t\t\tMPlayerGameInfo = new char [actual_length + 1];\n\t\t\t\tmemcpy (MPlayerGameInfo, data, actual_length);\n\t\t\t\t*(MPlayerGameInfo + actual_length) = 0;\t\t//Terminator in case we treat it as a string\n\t\t\t\tMPlayerGameInfoLength = actual_length;\n\t\t\t\tLastHeartbeat = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase DDE_TICKLE:\n\t\t\t\tWWDebugString(\"RA95 - Received 'tickle' packet.\");\n\t\t\t\t//SetForegroundWindow ( MainWindow );\n\t\t\t\t//ShowWindow ( MainWindow, SW_SHOWMAXIMIZED );\n\t\t\t\tbreak;\n\n\t\t\tcase DDE_PACKET_HEART_BEAT:\n\t\t\t\tWWDebugString(\"RA95 - Received heart beat packet.\");\n\t\t\t\tif (GameTimerInUse){\n\t\t\t\t\tLastHeartbeat = GameTimer.Time();\n\t\t\t\t}else{\n\t\t\t\t\tLastHeartbeat = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tWWDebugString(\"RA95 - Received unrecognised packet.\");\n\t\t\t\tbreak;\n\n\t\t}\n\t}\n\n\treturn (TRUE);\n\n}\n\n\n\n/***********************************************************************************************\n * DDESC::Get_MPlayer_Game_Info -- returns a pointer to the multiplayer setup info from wchat  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   ptr to data in .INI file format                                                   *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/8/96 3:23PM ST : Created                                                               *\n *=============================================================================================*/\nchar *DDEServerClass::Get_MPlayer_Game_Info (void)\n{\n\treturn (MPlayerGameInfo);\n}\n\n\n\n/***********************************************************************************************\n * DDESC::Delete_MPlayer_Game_Info -- clears out multi player game setup info                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/8/96 3:24PM ST : Created                                                               *\n *=============================================================================================*/\nvoid DDEServerClass::Delete_MPlayer_Game_Info(void)\n{\n\tif (MPlayerGameInfo){\n\t\tdelete [] MPlayerGameInfo;\n\t\tMPlayerGameInfo = NULL;\n\t}\n}\n\n\n\n/***********************************************************************************************\n * DDESC::Time_Since_Heartbeat -- returns the time in ticks since the last heartbeat from wchat*\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   time since heartbeat                                                              *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/9/96 11:05PM ST : Created                                                              *\n *=============================================================================================*/\nint DDEServerClass::Time_Since_Heartbeat(void)\n{\n\treturn (GameTimer.Time() - LastHeartbeat);\n}\n\n\n\n\n/***********************************************************************************************\n * Send_Data_To_DDE_Server -- sends a packet to WChat                                          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to the data to send                                                           *\n *           length of data                                                                    *\n *           packet type identifier                                                            *\n *                                                                                             *\n * OUTPUT:   true if packet successfully sent                                                  *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/9/96 11:07PM ST : Created                                                              *\n *=============================================================================================*/\nBOOL Send_Data_To_DDE_Server (char *data, int length, int packet_type)\n{\n\tif( DDE_Class->Open_Poke_Connection(DDE_Class->remote_name) == FALSE) {\n\t\tWWDebugString(\"RA95 - Failed to connect for POKE!\");\n\t\treturn (FALSE);\n\t}\n\n\tchar *poke_data = new char [length + 2*sizeof(int)];\n\n\tint *poke_data_int = (int*)poke_data;\n\n\t*poke_data_int \t= htonl (length + 2*sizeof(int));\n\t*(poke_data_int+1)= htonl (packet_type);\n\n\tmemcpy (poke_data + 8, data, length);\n\n\n\tif(DDE_Class->Poke_Server( (LPBYTE) poke_data, ntohl(*poke_data_int) ) == FALSE) {\n\t\tWWDebugString(\"RA95 - POKE failed!\\n\");\n\t\tDDE_Class->Close_Poke_Connection();\t\t// close down the link\n\t\tdelete poke_data;\n\t\treturn (FALSE);\n\t}\n\n\tDDE_Class->Close_Poke_Connection();\t\t// close down the link\n\n\tdelete poke_data;\n\n\treturn (TRUE);\n}\n\n\n#endif\t//WIN32\n"
  },
  {
    "path": "CODE/CCDDE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer - Red Alert                                *\n *                                                                                             *\n *                    File Name : CCDDE.H                                                      *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 10/04/95                                                     *\n *                                                                                             *\n *                  Last Update : August 5th, 1996 [ST]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *   C&C's interface to the DDE class                                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifdef WIN32\n\n#include \"dde.h\"\n\nclass DDEServerClass {\n\n\tpublic:\n\n\t\tDDEServerClass (void);\n\t\t~DDEServerClass (void);\n\n\n\t\tchar \t*Get_MPlayer_Game_Info (void);\t\t\t\t\t//Returns pointer to game info\n\t\tint    Get_MPlayer_Game_Info_Length(){return(MPlayerGameInfoLength);};\t//Len of game info\n\t\tBOOL\t Callback(unsigned char *data, long length);\t//DDE callback function\n\t\tvoid\t Delete_MPlayer_Game_Info(void);\t\t\t\t\t//release the game info memory\n\t\tvoid\t Enable(void);\t\t\t\t\t\t\t\t\t\t\t//Enable the DDE callback\n\t\tvoid\t Disable(void);\t\t\t\t\t\t\t\t\t\t//Disable the DDE callback\n\t\tint\t Time_Since_Heartbeat(void);\t\t\t\t\t\t//Returns the time since the last hearbeat from WChat\n\n\t\t/*\n\t\t** Enumeration for DDE packet types from WChat\n\t\t*/\n\t\tenum {\n\t\t\tDDE_PACKET_START_MPLAYER_GAME,\t\t//Start game packet. This includes game options\n\t\t\tDDE_PACKET_GAME_RESULTS,\t\t\t\t//Game results packet. The game statistics.\n\t\t\tDDE_PACKET_HEART_BEAT,\t\t\t\t\t//Heart beat packet so we know WChat is still there.\n\t\t\tDDE_TICKLE,\t\t\t\t\t\t\t\t\t//Message to prompt other app to take focus.\n\t\t\tDDE_CONNECTION_FAILED\n\t\t};\n\n\n\tprivate:\n\n\t\tchar \t\t\t\t*MPlayerGameInfo;\t\t\t//Pointer to game start packet\n\t\tint\t\t\t\tMPlayerGameInfoLength;\t//Length of game start packet.\n\t\tBOOL\t\t\t\tIsEnabled;\t\t\t\t\t//Flag for DDE callback enable\n\t\tint\t\t\t\tLastHeartbeat;\t\t// Time since last heartbeat packet was received from WChat\n\n};\n\n\nextern DDEServerClass DDEServer;\nextern BOOL Send_Data_To_DDE_Server (char *data, int length, int packet_type);\n\n\n#endif\t//WIN32\n"
  },
  {
    "path": "CODE/CCFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CCFILE.CPP 2     3/13/97 2:05p Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CCFILE.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : August 5, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CCFileClass::CCFileClass -- Default constructor for file object.                          *\n *   CCFileClass::CCFileClass -- Filename based constructor for C&C file.                      *\n *   CCFileClass::Close -- Closes the file.                                                    *\n *   CCFileClass::Error -- Handles displaying a file error message.                            *\n *   CCFileClass::Is_Available -- Checks for existence of file on disk or in mixfile.          *\n *   CCFileClass::Is_Open -- Determines if the file is open.                                   *\n *   CCFileClass::Open -- Opens a file from either the mixfile system or the rawfile system.   *\n *   CCFileClass::Read -- Reads data from the file.                                            *\n *   CCFileClass::Seek -- Moves the current file pointer in the file.                          *\n *   CCFileClass::Size -- Determines the size of the file.                                     *\n *   CCFileClass::Write -- Writes data to the file (non mixfile files only).                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n#include\t<errno.h>\n#include\t\"ccfile.h\"\n\n\n/***********************************************************************************************\n * CCFileClass::CCFileClass -- Filename based constructor for C&C file.                        *\n *                                                                                             *\n *    Use this constructor for a file when the filename is known at construction time.         *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the filename to use for this file object.                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The filename pointer is presumed to be inviolate throughout the duration of     *\n *             the file object. If this is not guaranteed, then use the default constructor    *\n *             and then set the name manually.                                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCCFileClass::CCFileClass(char const * filename) :\n\tPosition(0)\n{\n\tCCFileClass::Set_Name(filename);\n}\n\n\n/***********************************************************************************************\n * CCFileClass::CCFileClass -- Default constructor for file object.                            *\n *                                                                                             *\n *    This is the default constructor for a C&C file object.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCCFileClass::CCFileClass(void) :\n\tPosition(0)\n{\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Error -- Handles displaying a file error message.                              *\n *                                                                                             *\n *    Display an error message as indicated. If it is allowed to retry, then pressing a key    *\n *    will return from this function. Otherwise, it will exit the program with \"exit()\".       *\n *                                                                                             *\n * INPUT:   error    -- The error number (same as the DOSERR.H error numbers).                 *\n *                                                                                             *\n *          canretry -- Can this routine exit normally so that retrying can occur? If this is  *\n *                      false, then the program WILL exit in this routine.                     *\n *                                                                                             *\n *          filename -- Optional filename to report with this error. If no filename is         *\n *                      supplied, then no filename is listed in the error message.             *\n *                                                                                             *\n * OUTPUT:  none, but this routine might not return at all if the \"canretry\" parameter is      *\n *          false or the player pressed ESC.                                                   *\n *                                                                                             *\n * WARNINGS:   This routine may not return at all. It handles being in text mode as well as    *\n *             if in a graphic mode.                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CCFileClass::Error(int , int , char const * )\n{\n\tif (!Force_CD_Available(RequiredCD)) {\n\t\t//Prog_End();\n\t\tEmergency_Exit(EXIT_FAILURE);\n\t}\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Write -- Writes data to the file (non mixfile files only).                     *\n *                                                                                             *\n *    This routine will write data to the file, but NOT to a file that is part of a mixfile.   *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that holds the data to be written.               *\n *                                                                                             *\n *          size     -- The number of bytes to write.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually written.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCFileClass::Write(void const * buffer, long size)\n{\n\t/*\n\t**\tIf this is part of a mixfile, then writing is not allowed. Error out with a fatal\n\t**\tmessage.\n\t*/\n\tif (Is_Resident()) {\n\t\tError(EACCES, false, File_Name());\n\t}\n\n\treturn(CDFileClass::Write(buffer, size));\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Read -- Reads data from the file.                                              *\n *                                                                                             *\n *    This routine determines if the file is part of the mixfile system. If it is, then        *\n *    the file is copied from RAM if it is located there. Otherwise it is read from disk       *\n *    according to the correct position of the file within the parent mixfile.                 *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer to place the read data.                          *\n *                                                                                             *\n *          size     -- The number of bytes to read.                                           *\n *                                                                                             *\n * OUTPUT:  Returns the actual number of bytes read (this could be less than requested).       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCFileClass::Read(void * buffer, long size)\n{\n\tbool opened = false;\n\n\t/*\n\t**\tIf the file isn't currently open, then open it.\n\t*/\n\tif (!Is_Open()) {\n\t\tif (Open()) {\n\t\t\topened = true;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the file is part of a loaded mixfile, then a mere copy is\n\t**\tall that is required for the read.\n\t*/\n\tif (Is_Resident()) {\n\t\tlong\tmaximum = Data.Get_Size() - Position;\n\n\t\tsize = maximum < size ? maximum : size;\n//\t\tsize = MIN(maximum, size);\n\t\tif (size) {\n\t\t\tmemmove(buffer, (char *)Data + Position, size);\n//\t\t\tMem_Copy((char *)Pointer + Position, buffer, size);\n\t\t\tPosition += size;\n\t\t}\n\t\tif (opened) Close();\n\t\treturn(size);\n\t}\n\n\tlong s = CDFileClass::Read(buffer, size);\n\n\t/*\n\t**\tIf the file was opened by this routine, then close it at this time.\n\t*/\n\tif (opened) Close();\n\n\t/*\n\t**\tReturn with the number of bytes read.\n\t*/\n\treturn(s);\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Seek -- Moves the current file pointer in the file.                            *\n *                                                                                             *\n *    This routine will change the current file pointer to the position specified. It follows  *\n *    the same rules the a normal Seek() does, but if the file is part of the mixfile system,  *\n *    then only the position value needs to be updated.                                        *\n *                                                                                             *\n * INPUT:   pos      -- The position to move the file to relative to the position indicated    *\n *                      by the \"dir\" parameter.                                                *\n *                                                                                             *\n *          dir      -- The direction to affect the position change against. This can be       *\n *                      either SEEK_CUR, SEEK_END, or SEEK_SET.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the position of the new location.                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCFileClass::Seek(long pos, int dir)\n{\n\t/*\n\t**\tWhen the file is resident, a mere adjustment of the virtual file position is\n\t**\tall that is required of a seek.\n\t*/\n\tif (Is_Resident()) {\n\t\tswitch (dir) {\n\t\t\tcase SEEK_END:\n\t\t\t\tPosition = Data.Get_Size();\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_SET:\n\t\t\t\tPosition = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_CUR:\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\tPosition += pos;\n\t\tPosition = Position < 0 ? 0 : Position;\n\t\tPosition = Position > Data.Get_Size() ? Data.Get_Size() : Position;\n//\t\tPosition = Bound(Position+pos, 0L, Length);\n\t\treturn(Position);\n\t}\n\treturn(CDFileClass::Seek(pos, dir));\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Size -- Determines the size of the file.                                       *\n *                                                                                             *\n *    If the file is part of the mixfile system, then the size of the file is already          *\n *    determined and available. Otherwise, go to the low level system to find the file         *\n *    size.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the size of the file in bytes.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *   08/05/1996 JLB : Handles returning size of embedded file.                                 *\n *=============================================================================================*/\nlong CCFileClass::Size(void)\n{\n\t/*\n\t**\tIf the file is resident, the the size is already known. Just return the size in this\n\t**\tcase.\n\t*/\n\tif (Is_Resident()) return(Data.Get_Size());\n\n\t/*\n\t**\tIf the file is not available as a stand alone file, then search for it in the\n\t**\tmixfiles in order to get its size.\n\t*/\n\tif (!CDFileClass::Is_Available()) {\n\t\tlong length = 0;\n\t\tMFCD::Offset(File_Name(), NULL, NULL, NULL, &length);\n\t\treturn(length);\n\t}\n\n\treturn(CDFileClass::Size());\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Is_Available -- Checks for existence of file on disk or in mixfile.            *\n *                                                                                             *\n *    This routine will examine the mixfile system looking for the file. If the file could     *\n *    not be found there, then the disk is examined directly.                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file available for opening?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CCFileClass::Is_Available(int )\n{\n\t/*\n\t**\tA file that is open is presumed available.\n\t*/\n\tif (Is_Open()) return(true);\n\n\t/*\n\t**\tA file that is part of a mixfile is also presumed available.\n\t*/\n\tif (MFCD::Offset(File_Name())) {\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tOtherwise a manual check of the file system is required to\n\t**\tdetermine if the file is actually available.\n\t*/\n\treturn(CDFileClass::Is_Available());\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Is_Open -- Determines if the file is open.                                     *\n *                                                                                             *\n *    A mixfile is open if there is a pointer to the mixfile data. In absence of this,         *\n *    the the file is open if the file handle is valid.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file open?                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CCFileClass::Is_Open(void) const\n{\n\t/*\n\t**\tIf the file is part of a cached file, then return that it is opened. A closed file\n\t**\tdoesn't have a valid pointer.\n\t*/\n\tif (Is_Resident()) return(true);\n\n\t/*\n\t**\tOtherwise, go to a lower level to determine if the file is open.\n\t*/\n\treturn(CDFileClass::Is_Open());\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Close -- Closes the file.                                                      *\n *                                                                                             *\n *    If this is a mixfile file, then only the pointers need to be adjusted.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CCFileClass::Close(void)\n{\n\tnew(&Data) ::Buffer;\n\tPosition = 0;\t\t\t\t// Starts at beginning offset.\n\tCDFileClass::Close();\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Open -- Opens a file from either the mixfile system or the rawfile system.     *\n *                                                                                             *\n *    This routine will open the specified file. It examines the mixfile system to find a      *\n *    match. If one is found then the file is \"opened\" in a special cached way. Otherwise      *\n *    it is opened as a standard DOS file.                                                     *\n *                                                                                             *\n * INPUT:   rights   -- The access rights desired.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened successfully?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CCFileClass::Open(int rights)\n{\n\t/*\n\t**\tAlways close the file if it was open.\n\t*/\n\tClose();\n\n\t/*\n\t**\tPerform a preliminary check to see if the specified file\n\t**\texists on the disk. If it does, then open this file regardless\n\t**\tof whether it also exists in RAM. This is slower, but allows\n\t**\tupgrade files to work.\n\t*/\n\tif ((rights & WRITE) || CDFileClass::Is_Available()) {\n\t\treturn(CDFileClass::Open(rights));\n\t}\n\n\t/*\n\t**\tCheck to see if file is part of a mixfile and that mixfile is currently loaded\n\t**\tinto RAM.\n\t*/\n\tMFCD * mixfile = NULL;\n\tvoid * pointer = NULL;\n\tlong length = 0;\n\tlong start = 0;\n\tif (MFCD::Offset(File_Name(), &pointer, &mixfile, &start, &length)) {\n\n\t\tassert(mixfile != NULL);\n\n\t\t/*\n\t\t**\tIf the mixfile is located on disk, then fake out the file system to read from\n\t\t**\tthe mixfile, but think it is reading from a solitary file.\n\t\t*/\n\t\tif (pointer == NULL && mixfile != NULL) {\n\n\t\t\t/*\n\t\t\t**\tThis is a legitimate open to the file. All access to the file through this\n\t\t\t**\tfile object will be appropriately adjusted for mixfile support however. Also\n\t\t\t**\tnote that the filename attached to this object is NOT the same as the file\n\t\t\t**\tattached to the file handle.\n\t\t\t*/\n\t\t\tchar * dupfile = strdup(File_Name());\n\t\t\tOpen(mixfile->Filename, READ);\n\t\t\tSearching(false);\t\t\t\t// Disable multi-drive search.\n\t\t\tSet_Name(dupfile);\n\t\t\tSearching(true);\n\t\t\tfree(dupfile);\n\t\t\tBias(0);\n\t\t\tBias(start, length);\n\t\t\tSeek(0, SEEK_SET);\n\t\t} else {\n\t\t\tnew (&Data) ::Buffer(pointer, length);\n\t\t\tPosition = 0;\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tThe file cannot be found in any mixfile, so it must reside as\n\t\t** an individual file on the disk. Or else it is just plain missing.\n\t\t*/\n\t\treturn(CDFileClass::Open(rights));\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Get_Date_Time -- Gets the date and time the file was last modified.            *\n *                                                                                             *\n *    Use this routine to get the date and time of the file.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the file date and time as a long.                                     *\n *          Use the YEAR(long), MONTH(),....                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nunsigned long CCFileClass::Get_Date_Time(void)\n{\n\tunsigned long datetime;\n\tMFCD * mixfile;\n\n\tdatetime = CDFileClass::Get_Date_Time();\n\n\tif ( !datetime ) {\n\t\tif (MFCD::Offset(File_Name(), NULL, &mixfile, NULL, NULL)) {\n\t\t\t//\n\t\t\t// check for nested MIX files\n\t\t\t//\n\t\t\treturn( CCFileClass(mixfile->Filename).Get_Date_Time() );\n\t\t}\n\t\t// else return 0 indicating no file\n\t}\n\n\treturn( datetime );\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Set_Date_Time -- Sets the date and time the file was last modified.            *\n *                                                                                             *\n *    Use this routine to set the date and time of the file.                                   *\n *                                                                                             *\n * INPUT:   the file date and time as a long                                                   *\n *                                                                                             *\n * OUTPUT:  successful or not if the file date and time was changed.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nbool CCFileClass::Set_Date_Time( unsigned long datetime )\n{\n\tbool status;\n\tMFCD * mixfile;\n\n\tstatus = CDFileClass::Set_Date_Time( datetime );\n\n\tif ( !status ) {\n\t\tif (MFCD::Offset(File_Name(), NULL, &mixfile, NULL, NULL)) {\n\t\t\t//\n\t\t\t// check for nested MIX files\n\t\t\t//\n\t\t\treturn( CCFileClass(mixfile->Filename).Set_Date_Time( datetime ) );\n\t\t}\n\t\t// else return 0 indicating no file\n\t}\n\n\treturn( status );\n}\n\n\n/***********************************************************************************\n** Backward compatibility section.\n*/\n//extern \"C\" {\n\n\nstatic CCFileClass Handles[10];\n\nint __cdecl Open_File(char const * file_name, int mode)\n{\n\tfor (int index = 0; index < ARRAY_SIZE(Handles); index++) {\n\t\tif (!Handles[index].Is_Open()) {\n\t\t\tif (Handles[index].Open(file_name, mode)) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn(WWERROR);\n}\n\nvoid __cdecl Close_File(int handle)\n{\n\tif (handle != WWERROR && Handles[handle].Is_Open()) {\n\t\tHandles[handle].Close();\n\t}\n}\n\nlong __cdecl Read_File(int handle, void * buf, unsigned long bytes)\n{\n\tif (handle != WWERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Read(buf, bytes));\n\t}\n\treturn(0);\n}\n\nlong __cdecl Write_File(int handle, void const * buf, unsigned long bytes)\n{\n\tif (handle != WWERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Write(buf, bytes));\n\t}\n\treturn(0);\n}\n\nint __cdecl Find_File(char const * file_name)\n{\n\tCCFileClass file(file_name);\n\treturn(file.Is_Available());\n}\n\n#ifdef NEVER\nint __cdecl Delete_File(char const * file_name)\n{\n\treturn(CCFileClass(file_name).Delete());\n}\n\nint __cdecl Create_File(char const * file_name)\n{\n\treturn(CCFileClass(file_name).Create());\n}\n\nunsigned long __cdecl Load_Data(char const * name, void * ptr, unsigned long size)\n{\n\treturn(CCFileClass(name).Read(ptr, size));\n}\n#endif\n\nvoid * __cdecl Load_Alloc_Data(char const * name, int )\n{\n\tCCFileClass file(name);\n\n\treturn(Load_Alloc_Data(file));\n}\n\nunsigned long __cdecl File_Size(int handle)\n{\n\tif (handle != WWERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Size());\n\t}\n\treturn(0);\n}\n\n#ifdef NEVER\nunsigned long __cdecl Write_Data(char const * name, void const * ptr, unsigned long size)\n{\n\treturn(CCFileClass(name).Write(ptr, size));\n}\n#endif\n\nunsigned long __cdecl Seek_File(int handle, long offset, int starting)\n{\n\tif (handle != WWERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Seek(offset, starting));\n\t}\n\treturn(0);\n}\n\n#ifdef NEVER\nbool __cdecl Multi_Drive_Search(bool on)\n{\n//\treturn(CCFileClass::Multi_Drive_Search(on));\n\treturn(on);\n}\n\nvoid __cdecl WWDOS_Init(void)\n{\n}\n\nvoid __cdecl WWDOS_Shutdown(void)\n{\n}\n\nint __cdecl Find_Disk_Number(char const *)\n{\n\treturn(0);\n}\n#endif\n\n//unsigned long __cdecl Load_Uncompress(char const * file, BuffType uncomp_buff, BuffType dest_buff, void * reserved_data)\n//{\n//\treturn(Load_Uncompress(CCFileClass(file), uncomp_buff, dest_buff, reserved_data));\n//\treturn(CCFileClass(file).Load_Uncompress(uncomp_buff, dest_buff, reserved_data));\n//}\n\n#ifdef WIN32\nextern \"C\" {\nint MaxDevice;\nint DefaultDrive;\nchar CallingDOSInt;\n\n}\n#endif\n\n\nvoid Unfragment_File_Cache(void)\n{\n}\n\n\n"
  },
  {
    "path": "CODE/CCFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CCFILE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CCFILE.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : October 17, 1994                                             *\n *                                                                                             *\n *                  Last Update : October 17, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CCFILE_H\n#define CCFILE_H\n\n//#include\t<wwlib32.h>\n#include\t<limits.h>\n#include\t\"mixfile.h\"\n#include\t\"cdfile.h\"\n#include\t\"buff.h\"\n\n\n/*\n**\tThis derived class for file access knows about mixfiles (packed files). It can handle opening\n**\ta file that is embedded within a mixfile. This is true if the mixfile is cached or resides on\n**\tdisk. It is functionally similar to pakfiles, except much faster and less RAM intensive.\n*/\nclass CCFileClass : public CDFileClass\n{\n\tpublic:\n\t\tCCFileClass(char const * filename);\n\t\tCCFileClass(void);\n\t\tvirtual ~CCFileClass(void) {Position = 0;};\n\n\t\t// Delete should be overloaded here as well. Don't allow deletes of mixfiles.\n\n\t\tbool Is_Resident(void) const {return(Data.Get_Buffer() != NULL);}\n\t\tvirtual int Is_Available(int forced=false);\n\t\tvirtual int Is_Open(void) const;\n\t\tvirtual int Open(char const * filename, int rights=READ) {Set_Name(filename);return Open(rights);};\n\t\tvirtual int Open(int rights=READ);\n\t\tvirtual long Read(void * buffer, long size);\n\t\tvirtual long Seek(long pos, int dir=SEEK_CUR);\n\t\tvirtual long Size(void);\n\t\tvirtual long Write(void const * buffer, long size);\n\t\tvirtual void Close(void);\n\t\tvirtual unsigned long Get_Date_Time(void);\n\t\tvirtual bool Set_Date_Time(unsigned long datetime);\n\t\tvirtual void Error(int error, int canretry = false, char const * filename=NULL);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis indicates the file is actually part of a resident image of the mixfile\n\t\t**\titself. In this case, the embedded file handle is invalid. All file access actually\n\t\t**\tgets routed through the cached version of the file. This is a pointer to the start\n\t\t**\tof the RAM image of the file.\n\t\t*/\n\t\t::Buffer Data;\n//\t\tvoid * Pointer;\n\n\t\t/*\n\t\t**\tThis is the size of the file if it was embedded in a mixfile. The size must be manually\n\t\t**\tkept track of because the DOS file size is invalid.\n\t\t*/\n//\t\tlong Length;\n\n\t\t/*\n\t\t**\tThis is the current seek position of the file. It is duplicated here if the file is\n\t\t**\tpart of a mixfile since the DOS seek position is not accurate. This value will\n\t\t**\trange from zero to the size of the file in bytes.\n\t\t*/\n\t\tlong Position;\n\n\t\t// Force these to never be invoked.\n\t\tCCFileClass const & operator = (CCFileClass const & c);\n\t\tCCFileClass (CCFileClass const & );\n};\n\nclass MixFileClass<CDFileClass>;\n\n#endif\n"
  },
  {
    "path": "CODE/CCINI.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CCINI.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CCINI.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/24/96                                                     *\n *                                                                                             *\n *                  Last Update : November 1, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CCINIClass::Calculate_Message_Digest -- Calculate a message digest for the current databas*\n *   CCINIClass::Get_AnimType -- Fetch an animation type number from the INI database.         *\n *   CCINIClass::Get_ArmorType -- Fetches the armor type from the INI database.                *\n *   CCINIClass::Get_Buildings -- Fetch a building bitfield from the INI database.             *\n *   CCINIClass::Get_BulletType -- Fetch the bullet identifier from the INI database.          *\n *   CCINIClass::Get_CrateType -- Fetches a crate type value from the INI database.            *\n *   CCINIClass::Get_HousesType -- Fetch a house identifier from the INI database.             *\n *   CCINIClass::Get_Lepton -- Fetches a lepton value from the INI database.                   *\n *   CCINIClass::Get_MPHType -- Fetches the speed value as a number from 0 to 100.             *\n *   CCINIClass::Get_OverlayType -- Fetch the overlay identifier from the INI database.        *\n *   CCINIClass::Get_Owners -- Fetch the owners (list of house bits).                          *\n *   CCINIClass::Get_SourceType -- Fetch the source (edge) type from the INI database.         *\n *   CCINIClass::Get_TerrainType -- Fetch the terrain type identifier from the INI database.   *\n *   CCINIClass::Get_TheaterType -- Fetch the theater type from the INI database.              *\n *   CCINIClass::Get_ThemeType -- Fetch the theme identifier.                                  *\n *   CCINIClass::Get_TriggerType -- Fetch the trigger type identifier from the INI database.   *\n *   CCINIClass::Get_Unique_ID -- Fetch a unique identifier number for the INI file.           *\n *   CCINIClass::Get_VQType -- Fetch the VQ movie identifier from the INI database.            *\n *   CCINIClass::Get_VocType -- Fetch a voc (sound effect) from the INI database.              *\n *   CCINIClass::Get_WarheadType -- Fetch the warhead type from the INI database.              *\n *   CCINIClass::Get_WeaponType -- Fetches the weapon type from the INI database.              *\n *   CCINIClass::Invalidate_Message_Digest -- Flag message digest as being invalid.            *\n *   CCINIClass::Load -- Load the INI database from the data stream specified.                 *\n *   CCINIClass::Load -- Load the INI database from the file specified.                        *\n *   CCINIClass::Put_AnimType -- Stores the animation identifier to the INI database.          *\n *   CCINIClass::Put_ArmorType -- Store the armor type to the INI database.                    *\n *   CCINIClass::Put_Buildings -- Store a building list to the INI database.                   *\n *   CCINIClass::Put_BulletType -- Store the projectile identifier into the INI database.      *\n *   CCINIClass::Put_CrateType -- Stores the crate value in the section and entry specified.   *\n *   CCINIClass::Put_HousesType -- Store a house identifier to the INI database.               *\n *   CCINIClass::Put_Lepton -- Stores a lepton value to the INI database.                      *\n *   CCINIClass::Put_MPHType -- Stores the speed value to the section & entry specified.       *\n *   CCINIClass::Put_OverlayType -- Store the overlay identifier into the INI database.        *\n *   CCINIClass::Put_Owners -- Store the house bitfield to the INI database.                   *\n *   CCINIClass::Put_SourceType -- Store the source (edge) identifier to the INI database.     *\n *   CCINIClass::Put_TerrainType -- Store the terrain type number to the INI database.         *\n *   CCINIClass::Put_TheaterType -- Store the theater identifier to the INI database.          *\n *   CCINIClass::Put_ThemeType -- Store the theme identifier to the INI database.              *\n *   CCINIClass::Put_TriggerType -- Store the trigger identifier to the INI database.          *\n *   CCINIClass::Put_VQType -- Store the VQ movie identifier into the INI database.            *\n *   CCINIClass::Put_VocType -- Store a sound effect identifier into the INI database.         *\n *   CCINIClass::Put_WarheadType -- Stores the warhead identifier to the INI database.         *\n *   CCINIClass::Put_WeaponType -- Store the weapon identifier to the INI database.            *\n *   CCINIClass::Save -- Pipes the INI database to the pipe specified.                         *\n *   CCINIClass::Save -- Save the INI data to the file specified.                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * CCINIClass::Load -- Load the INI database from the file specified.                          *\n *                                                                                             *\n *    This routine will load the database from the file specified in much the same manner      *\n *    that the INIClass load function works. However, this class will examine the message      *\n *    digest (if present) and compare it to the actual digest. If they differ, a special       *\n *    return value is used. This will allow verification of the integrity of the ini data.     *\n *                                                                                             *\n * INPUT:   file  -- Reference to the file that will be read from.                             *\n *                                                                                             *\n *          withdigest  -- Should a message digest be examined when loaded. If there is a      *\n *                         mismatch detected, then an error will be returned.                  *\n *                                                                                             *\n * OUTPUT:  If the file was not read, returns 0. If the file was read ok, returns 1. If the    *\n *          file was read ok, but the digest doesn't verify, returns 2.                        *\n *                                                                                             *\n * WARNINGS:   If no message digest was present in the INI file, then no verification can      *\n *             be performed.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *   08/21/1996 JLB : Handles digest control.                                                  *\n *=============================================================================================*/\nbool CCINIClass::Load(FileClass & file, bool withdigest)\n{\n\treturn(Load(FileStraw(file), withdigest));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Load -- Load the INI database from the data stream specified.                   *\n *                                                                                             *\n *    This will load the INI database and in the process, it will fetch and verify any         *\n *    message digest present.                                                                  *\n *                                                                                             *\n * INPUT:   straw -- The data stream to fetch the INI data from.                               *\n *                                                                                             *\n *          withdigest  -- Should a message digest be examined when loaded. If there is a      *\n *                         mismatch detected, then an error will be returned.                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the database loaded ok? (hack: returns \"2\" if digest doesn't match).     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *   08/21/1996 JLB : Handles message digest control.                                          *\n *=============================================================================================*/\nbool CCINIClass::Load(Straw & file, bool withdigest)\n{\n\tbool ok = INIClass::Load(file);\n\n\tInvalidate_Message_Digest();\n\tif (ok && withdigest) {\n\n\t\t/*\n\t\t**\tIf a digest is present, fetch it.\n\t\t*/\n\t\tunsigned char digest[20];\n\t\tint len = Get_UUBlock(\"Digest\", digest, sizeof(digest));\n\t\tif (len > 0) {\n\t\t\tClear(\"Digest\");\n\n\t\t\t/*\n\t\t\t**\tCalculate the message digest for the INI data that was read.\n\t\t\t*/\n\t\t\tCalculate_Message_Digest();\n\n\t\t\t/*\n\t\t\t**\tIf the message digests don't match, then return with the special error code.\n\t\t\t*/\n\t\t\tif (memcmp(digest, Digest, sizeof(digest)) != 0) {\n\t\t\t\treturn(2);\n\t\t\t}\n\t\t}\n\t}\n\treturn(ok);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Save -- Save the INI data to the file specified.                                *\n *                                                                                             *\n *    This routine will save the INI data to the file. It will add a message digest so that    *\n *    validity check can be performed when the INI data is subsequently read.                  *\n *                                                                                             *\n * INPUT:   file  -- Reference to the file to write the INI data to.                           *\n *                                                                                             *\n *          withdigest  -- Should a message digest be generated and saved with the INI         *\n *                         data file?                                                          *\n *                                                                                             *\n * OUTPUT:  bool; Was the INI data saved?                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *   08/21/1996 JLB : Handles message digest control.                                          *\n *=============================================================================================*/\nint CCINIClass::Save(FileClass & file, bool withdigest) const\n{\n\treturn(Save(FilePipe(file), withdigest));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Save -- Pipes the INI database to the pipe specified.                           *\n *                                                                                             *\n *    This routine will pipe the INI data to the pipe segment specified. It is functionally    *\n *    the same as the save operation. A message digest is added to the output data so that     *\n *    validity check can occur during a subsequent read.                                       *\n *                                                                                             *\n * INPUT:   straw -- Reference to the pipe that will receive the output ini data stream.       *\n *                                                                                             *\n *          withdigest  -- Should a message digest be generated and saved with the INI         *\n *                         data file?                                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes output to the pipe.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *   08/21/1996 JLB : Handles message digest control.                                          *\n *=============================================================================================*/\nint CCINIClass::Save(Pipe & pipe, bool withdigest) const\n{\n\tif (!withdigest) {\n\t\treturn(INIClass::Save(pipe));\n\t}\n\n\t/*\n\t**\tJust in case these entries are present, clear them out.\n\t*/\n\t((CCINIClass *)this)->Clear(\"Digest\");\n\n\t/*\n\t**\tCalculate what the new digest should be.\n\t*/\n\t((CCINIClass *)this)->Calculate_Message_Digest();\n\n\t/*\n\t**\tStore the actual digest into the INI database.\n\t*/\n\t((CCINIClass *)this)->Put_UUBlock(\"Digest\", Digest, sizeof(Digest));\n\n\t/*\n\t**\tOutput the database to the pipe specified.\n\t*/\n\tint length = INIClass::Save(pipe);\n\n\t/*\n\t**\tRemove the digest from the database. It shouldn't stick around as if it were real data\n\t**\tsince it isn't really part of the INI database proper.\n\t*/\n\t((CCINIClass *)this)->Clear(\"Digest\");\n\n\t/*\n\t**\tFinally, return with the total number of bytes send out the pipe.\n\t*/\n\treturn(length);\n}\n\n\nstatic inline int _Scale_To_256(int val)\n{\n\tval = min(val, 100);\n\tval = max(val, 0);\n\tval = ((val * 256) / 100);\n\tval = min(val, 255);\n\treturn(val);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_Lepton -- Fetches a lepton value from the INI database.                     *\n *                                                                                             *\n *    This routine will fetch the lepton value as if it were expressed as cells. Example;      *\n *    a value of 1 would mean 256 in leptons.                                                  *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to look under.                                  *\n *                                                                                             *\n *          entry    -- The entry identifier to find.                                          *\n *                                                                                             *\n *          defvalue -- The default value to use if the specified section and entry could      *\n *                      not be located.                                                        *\n *                                                                                             *\n * OUTPUT:  Returns with the lepton value of the section & entry specified. If not found, then *\n *          the default value is returned.                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLEPTON CCINIClass::Get_Lepton(char const * section, char const * entry, LEPTON defvalue) const\n{\n\tfixed result = Get_Fixed(section, entry, fixed(defvalue, CELL_LEPTON_W));\n\treturn(result * CELL_LEPTON_W);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_Lepton -- Stores a lepton value to the INI database.                        *\n *                                                                                             *\n *    This routine will store the lepton value as if it were expressed in cells. Example;      *\n *    A lepton of 128 will be stored as \".5\".                                                  *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to store the value under.                       *\n *                                                                                             *\n *          entry    -- The entry to store the lepton value at.                                *\n *                                                                                             *\n *          value    -- The lepton value to store.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the lepton value stored?                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_Lepton(char const * section, char const * entry, LEPTON value)\n{\n\treturn(Put_Fixed(section, entry, fixed(value, CELL_LEPTON_W)));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_MPHType -- Fetches the speed value as a number from 0 to 100.               *\n *                                                                                             *\n *    This routine will fetch the speed value as if it were expressed as a number from 0       *\n *    to 100. The value of 100 would translate into a speed of 256 leptons per game frame.     *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to search for the entry under.                  *\n *                                                                                             *\n *          entry    -- The entry identifier to find.                                          *\n *                                                                                             *\n *          defvalue -- The default speed value to use if the entry could not be located.      *\n *                                                                                             *\n * OUTPUT:  Returns with the speed value. If no entry could be found, then the default value   *\n *          will be returned.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nMPHType CCINIClass::Get_MPHType(char const * section, char const * entry, MPHType defvalue) const\n{\n\tint val = Get_Int(section, entry, ((int)defvalue * 100) / 256);\n\treturn (MPHType(_Scale_To_256(val)));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_MPHType -- Stores the speed value to the section & entry specified.         *\n *                                                                                             *\n *    Use this routine to store a speed value into the INI database. The number stored will    *\n *    be in a 0..100 format. A speed of 256 leptons per tick would be stored as 100.           *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to store the entry under.                       *\n *                                                                                             *\n *          entry    -- The entry identifier to store the speed value to.                      *\n *                                                                                             *\n *          value    -- The speed value to store.                                              *\n *                                                                                             *\n * OUTPUT:  bool; Was the speed value stored?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_MPHType(char const * section, char const * entry, MPHType value)\n{\n\treturn(Put_Int(section, entry, ((int)value * 100) / 256));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_Owners -- Fetch the owners (list of house bits).                            *\n *                                                                                             *\n *    Use this to fetch a house bit array value from the INI database. This value will be      *\n *    various bit positions set (1 << house#) for each house specified in the database.        *\n *    Houses can be specified in series by the house name separated by commas or by the        *\n *    special group names of \"soviet\", and \"allies\" to cover the houses that are members of    *\n *    these groups.                                                                            *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to search for the entry under.                  *\n *                                                                                             *\n *          entry    -- The entry identifier to search for.                                    *\n *                                                                                             *\n *          defvalue -- The default house bitfield to use if the entry could not be found.     *\n *                                                                                             *\n * OUTPUT:  Returns with the house bitfield value. If the entry could not be found, then the   *\n *          default value is returned.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCINIClass::Get_Owners(char const * section, char const * entry, long defvalue) const\n{\n\tchar buffer[128];\n\tlong ownable = defvalue;\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\n\t\townable = 0;\n\t\tchar * name = strtok(buffer, \",\");\n\n\t\twhile (name) {\n\t\t\townable |= Owner_From_Name(name);\n\t\t\tname = strtok(NULL, \",\");\n\t\t}\n\t}\n\treturn(ownable);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_Owners -- Store the house bitfield to the INI database.                     *\n *                                                                                             *\n *    Use this routine to store the house bitfield data into the database. The bitfield format *\n *    matches the format used by the Get_Owners function. Example; if both England and         *\n *    Spain were specified in the bitfield, the entry would be stored as \"England,Spain\".      *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to store the entry under.                       *\n *                                                                                             *\n *          entry    -- The entry identifier that is assigned the value.                       *\n *                                                                                             *\n *          value    -- The value to assign to the entry.                                      *\n *                                                                                             *\n * OUTPUT:  bool; Was the entry stored in the INI database?                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_Owners(char const * section, char const * entry, long value)\n{\n\tchar buffer[128];\n\n\tbuffer[0] = '\\0';\n\n\tif ((value & HOUSEF_ALLIES) == HOUSEF_ALLIES) {\n\t\tstrcat(buffer, \"allies\");\n\t\tvalue &= ~HOUSEF_ALLIES;\n\t}\n\tif ((value & HOUSEF_SOVIET) == HOUSEF_SOVIET) {\n\t\tif (buffer[0] != '\\0') {\n\t\t\tstrcat(buffer, \",\");\n\t\t}\n\t\tstrcat(buffer, \"soviet\");\n\t\tvalue &= ~HOUSEF_SOVIET;\n\t}\n\n\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\tif ((value & (1 << house)) != 0) {\n\t\t\tif (buffer[0] != '\\0') {\n\t\t\t\tstrcat(buffer, \",\");\n\t\t\t}\n\t\t\tstrcat(buffer, HouseTypeClass::As_Reference(house).Name());\n\t\t}\n\t}\n\n\tif (buffer[0] != '\\0') {\n\t\treturn(Put_String(section, entry, buffer));\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_ArmorType -- Fetches the armor type from the INI database.                  *\n *                                                                                             *\n *    This routine will fetch the armor type from the database.                                *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to search for the entry under.              *\n *                                                                                             *\n *          entry    -- Th identifier for the entry to search for.                             *\n *                                                                                             *\n *          defvalue -- The default value to use if the entry could not be located.            *\n *                                                                                             *\n * OUTPUT:  Returns with the armor type specified in the INI database. If it could not be      *\n *          found, then the default value is returned instead.                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nArmorType CCINIClass::Get_ArmorType(char const * section, char const * entry, ArmorType defvalue) const\n{\n\tchar buffer[128];\n\n\tGet_String(section, entry, ArmorName[defvalue], buffer, sizeof(buffer));\n\treturn(Armor_From_Name(buffer));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_ArmorType -- Store the armor type to the INI database.                      *\n *                                                                                             *\n *    Use this routine to store the specified armor type to the INI database.                  *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to store the entry under.                       *\n *                                                                                             *\n *          entry    -- The entry to store the value at.                                       *\n *                                                                                             *\n *          value    -- The value to store in the database.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the entry stored in the database?                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_ArmorType(char const * section, char const * entry, ArmorType value)\n{\n\treturn(Put_String(section, entry, ArmorName[value]));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_VocType -- Fetch a voc (sound effect) from the INI database.                *\n *                                                                                             *\n *    This routine will fetch a voc number from the database. The voc number will either       *\n *    be a valid sound effect or VOC_NONE if no match could be found.                          *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to search for the entry under.              *\n *                                                                                             *\n *          entry    -- The entry to search for.                                               *\n *                                                                                             *\n *          defvalue -- The default value to return if the entry could not be located.         *\n *                                                                                             *\n * OUTPUT:  Returns with the sound effect (VocType) from the INI database. If the entry could  *\n *          not be located, then the default value is returned.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nVocType CCINIClass::Get_VocType(char const * section, char const * entry, VocType defvalue) const\n{\n\tchar buffer[128];\n\n\tGet_String(section, entry, Voc_Name(defvalue), buffer, sizeof(buffer));\n\treturn(Voc_From_Name(buffer));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_VocType -- Store a sound effect identifier into the INI database.           *\n *                                                                                             *\n *    Use this routine to store a voc identifier (stored a the text name of the sound) into    *\n *    the INI database.                                                                        *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to store the entry under.                   *\n *                                                                                             *\n *          entry    -- The entry to assign the value to.                                      *\n *                                                                                             *\n *          value    -- The sound effect to store to the entry.                                *\n *                                                                                             *\n * OUTPUT:  bool; Was the sound effect entry stored?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_VocType(char const * section, char const * entry, VocType value)\n{\n\tif (value == VOC_NONE) {\n\t\treturn(Put_String(section, entry, \"<none>\"));\n\t}\n\treturn(Put_String(section, entry, Voc_Name(value)));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_AnimType -- Fetch an animation type number from the INI database.           *\n *                                                                                             *\n *    This will fetch an AnimType number from the INI database. The anim is stored as a text   *\n *    name of the art file used for that anim.                                                 *\n *                                                                                             *\n * INPUT:   section  -- The section to search for the entry under.                             *\n *                                                                                             *\n *          entry    -- The entry to search for.                                               *\n *                                                                                             *\n *          defvalue -- The default AnimType to use if the entry could not be located.         *\n *                                                                                             *\n * OUTPUT:  Returns with the anim type specified in the database. If it could not be found,    *\n *          then the default value is returned.                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nAnimType CCINIClass::Get_AnimType(char const * section, char const * entry, AnimType defvalue) const\n{\n\tchar buffer[128];\n\n\tGet_String(section, entry, Anim_Name(defvalue), buffer, sizeof(buffer));\n\treturn(Anim_From_Name(buffer));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_AnimType -- Stores the animation identifier to the INI database.            *\n *                                                                                             *\n *    This routine will store the animation identifier (stored as the text name of the art     *\n *    file it uses) to the INI database.                                                       *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to place the entry under.                       *\n *                                                                                             *\n *          entry    -- The entry identifier to assign the animation number to.                *\n *                                                                                             *\n *          value    -- The animation identifier to store with the entry.                      *\n *                                                                                             *\n * OUTPUT:  bool; Was the animation identifier stored?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_AnimType(char const * section, char const * entry, AnimType value)\n{\n\tif (value == ANIM_NONE) {\n\t\treturn(Put_String(section, entry, \"<none>\"));\n\t}\n\treturn(Put_String(section, entry, Anim_Name(value)));\n}\n\n\nUnitType CCINIClass::Get_UnitType(char const * section, char const * entry, UnitType defvalue) const\n{\n\tchar buffer[128];\n\n\tchar const * def = \"<none>\";\n\tif (defvalue != UNIT_NONE) {\n\t\tdef = UnitTypeClass::As_Reference(defvalue).Name();\n\t}\n\tGet_String(section, entry, def, buffer, sizeof(buffer));\n\treturn(UnitTypeClass::From_Name(buffer));\n}\n\n\nbool CCINIClass::Put_UnitType(char const * section, char const * entry, UnitType value)\n{\n\tif (value == UNIT_NONE) {\n\t\treturn(Put_String(section, entry, \"<none>\"));\n\t}\n\treturn(Put_String(section, entry, UnitTypeClass::As_Reference(value).Name()));\n}\n\n\n\n/***********************************************************************************************\n * CCINIClass::Get_WeaponType -- Fetches the weapon type from the INI database.                *\n *                                                                                             *\n *    This routine will fetch the weapon type from the INI database. The weapon type is        *\n *    stored as a custom identifier string.                                                    *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to search for the entry under.                  *\n *                                                                                             *\n *          entry    -- The entry identifier to search for.                                    *\n *                                                                                             *\n *          defvalue -- The default weapon value to return if the entry could not be located.  *\n *                                                                                             *\n * OUTPUT:  Returns with the weapon type specified by the entry. If the entry could not be     *\n *          found then the default value is returned.                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nWeaponType CCINIClass::Get_WeaponType(char const * section, char const * entry, WeaponType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(Weapon_From_Name(buffer));\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_WeaponType -- Store the weapon identifier to the INI database.              *\n *                                                                                             *\n *    Store the weapon identifier (as custom string name) to the INI database.                 *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to store the entry under.                   *\n *                                                                                             *\n *          entry    -- Identifier to store the weapon identifier with.                        *\n *                                                                                             *\n *          value    -- The weapon identifier to store.                                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the weapon identifier stored?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_WeaponType(char const * section, char const * entry, WeaponType value)\n{\n\tif (value == WEAPON_NONE) {\n\t\treturn(Put_String(section, entry, \"<none>\"));\n\t}\n\treturn(Put_String(section, entry, WeaponTypeClass::As_Pointer(value)->Name()));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_WarheadType -- Fetch the warhead type from the INI database.                *\n *                                                                                             *\n *    Will fetch the warhead identifier from the INI database.                                 *\n *                                                                                             *\n * INPUT:   section  -- The identifier for the section to search for the entry under.          *\n *                                                                                             *\n *          entry    -- The entry to search for.                                               *\n *                                                                                             *\n *          defvalue -- The default return value to use if the entry could not be located.     *\n *                                                                                             *\n * OUTPUT:  Returns with the found warhead type. If the entry could not be found then the      *\n *          default warhead value is returned.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nWarheadType CCINIClass::Get_WarheadType(char const * section, char const * entry, WarheadType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\tfor (WarheadType wh = WARHEAD_FIRST; wh < WARHEAD_COUNT; wh++) {\n\t\t\tif (stricmp(WarheadTypeClass::As_Pointer(wh)->Name(), buffer) == 0) {\n\t\t\t\treturn(wh);\n\t\t\t}\n\t\t}\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_WarheadType -- Stores the warhead identifier to the INI database.           *\n *                                                                                             *\n *    This will store the weapon identifier specified to the INI database.                     *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to store the entry under.                       *\n *                                                                                             *\n *          entry    -- The entry to store the warhead identifier.                             *\n *                                                                                             *\n *          value    -- The warhead identifier to store.                                       *\n *                                                                                             *\n * OUTPUT:  bool; Was the warhead identifier stored to the database?                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_WarheadType(char const * section, char const * entry, WarheadType value)\n{\n\tif (value == WARHEAD_NONE) {\n\t\treturn(Put_String(section, entry, \"<none>\"));\n\t}\n\treturn(Put_String(section, entry, WarheadTypeClass::As_Pointer(value)->Name()));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_OverlayType -- Fetch the overlay identifier from the INI database.          *\n *                                                                                             *\n *    This routine will fetch the overlay identifier from the database.                        *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to search for the entry under.              *\n *                                                                                             *\n *          entry    -- The entry to search for.                                               *\n *                                                                                             *\n *          defvalue -- The default value to use if the entry could not be located.            *\n *                                                                                             *\n * OUTPUT:  Returns with the overlay identifier found. If it could not be found, then the      *\n *          default value is returned.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nOverlayType CCINIClass::Get_OverlayType(char const * section, char const * entry, OverlayType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(OverlayTypeClass::From_Name(buffer));\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_OverlayType -- Store the overlay identifier into the INI database.          *\n *                                                                                             *\n *    Use this routine to store the overlay identifier into the INI database.                  *\n *                                                                                             *\n * INPUT:   section  -- Identifier for to search for the entry under.                          *\n *                                                                                             *\n *          entry    -- The entry to search for.                                               *\n *                                                                                             *\n *          value    -- The overlay type value to store with the entry.                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the overlay value stored?                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_OverlayType(char const * section, char const * entry, OverlayType value)\n{\n\tassert(value != OVERLAY_NONE);\n\treturn(Put_String(section, entry, OverlayTypeClass::As_Reference(value).Name()));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_BulletType -- Fetch the bullet identifier from the INI database.            *\n *                                                                                             *\n *    Use this routine to fetch the bullet type identifier from the INI database.              *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to search for the entry under.                  *\n *                                                                                             *\n *          entry    -- The entry to search for.                                               *\n *                                                                                             *\n *          defvalue -- The default bullet type value to return if the entry could not be      *\n *                      located.                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the bullet type identifier found. If the entry could not be found     *\n *          then the default value is returned.                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBulletType CCINIClass::Get_BulletType(char const * section, char const * entry, BulletType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\tfor (BulletType proj = BULLET_FIRST; proj < BULLET_COUNT; proj++) {\n\t\t\tif (stricmp(BulletTypeClass::As_Reference(proj).Name(), buffer) == 0) {\n//\t\t\tif (stricmp(ProjectileNames[proj], buffer) == 0) {\n\t\t\t\treturn(proj);\n\t\t\t}\n\t\t}\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_BulletType -- Store the projectile identifier into the INI database.        *\n *                                                                                             *\n *    This routine will store the projectile name (as the identifier) to the INI database.     *\n *                                                                                             *\n * INPUT:   section  -- The section to store the entry under.                                  *\n *                                                                                             *\n *          entry    -- The entry identifier to store the projectile value with.               *\n *                                                                                             *\n *          value    -- The projectile identifier to store.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the projectile identifier stored?                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_BulletType(char const * section, char const * entry, BulletType value)\n{\n\tif (value == BULLET_NONE) {\n\t\treturn(Put_String(section, entry, \"<none>\"));\n\t}\n\treturn(Put_String(section, entry, BulletTypeClass::As_Reference(value).Name()));\n//\treturn(Put_String(section, entry, ProjectileNames[value]));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_HousesType -- Fetch a house identifier from the INI database.               *\n *                                                                                             *\n *    Use this routine to fetch an individual house identifier from the INI database. This is  *\n *    somewhat similar to the Get_Owners function but is limited to a single house.            *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to search for the entry under.              *\n *                                                                                             *\n *          entry    -- Identifier for the entry to search for.                                *\n *                                                                                             *\n *          defvalue -- The default value to use if the entry could not be located.            *\n *                                                                                             *\n * OUTPUT:  Returns with the house identifier if it was found. If not found, then the default  *\n *          value is returned.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nHousesType CCINIClass::Get_HousesType(char const * section, char const * entry, HousesType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(HouseTypeClass::From_Name(buffer));\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_HousesType -- Store a house identifier to the INI database.                 *\n *                                                                                             *\n *    Use this routine to store the specified house identifier to the INI database.            *\n *                                                                                             *\n * INPUT:   section  -- The section to store the entry under.                                  *\n *                                                                                             *\n *          entry    -- Identifier for the entry to search for.                                *\n *                                                                                             *\n *          value    -- The house identifier to store in the database.                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the house identifier stored?                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_HousesType(char const * section, char const * entry, HousesType value)\n{\n\treturn(Put_String(section, entry, HouseTypeClass::As_Reference(value).Name()));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_VQType -- Fetch the VQ movie identifier from the INI database.              *\n *                                                                                             *\n *    Fetches the VQ movie name (identifier) from the INI database.                            *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to search for the entry under.              *\n *                                                                                             *\n *          entry    -- Identifier for the entry to search for.                                *\n *                                                                                             *\n *          defvalue -- The default value to use if the entry could not be located.            *\n *                                                                                             *\n * OUTPUT:  Returns with the VQ movie identifier found. If the entry could not be located,     *\n *          then the default value is returned.                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nVQType CCINIClass::Get_VQType(char const * section, char const * entry, VQType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\tfor (VQType vq = VQ_FIRST; vq < VQ_COUNT; vq++) {\n\t\t\tif (stricmp(buffer, VQName[vq]) == 0) {\n\t\t\t\treturn(vq);\n\t\t\t}\n\t\t}\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_VQType -- Store the VQ movie identifier into the INI database.              *\n *                                                                                             *\n *    Use this routine to store the VQ movie identifier into the INI database.                 *\n *                                                                                             *\n * INPUT:   section  -- The section to store the entry under.                                  *\n *                                                                                             *\n *          entry    -- Identifier for the entry to store.                                     *\n *                                                                                             *\n *          value    -- The VQ movie identifier to store to the INI database.                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the VQ identifier stored?                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_VQType(char const * section, char const * entry, VQType value)\n{\n\tif (value == VQ_NONE) {\n\t\treturn(Put_String(section, entry, \"<none>\"));\n\t}\n\treturn(Put_String(section, entry, VQName[value]));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_TheaterType -- Fetch the theater type from the INI database.                *\n *                                                                                             *\n *    This will fetch the theater identifier from the INI database.                            *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to search for the entry under.              *\n *                                                                                             *\n *          entry    -- Identifier for the entry to search for.                                *\n *                                                                                             *\n *          defvalue -- The default value to use if the entry could not be located.            *\n *                                                                                             *\n * OUTPUT:  Returns with the theater type found. If the entry could not be found, then the     *\n *          default value is returned.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTheaterType CCINIClass::Get_TheaterType(char const * section, char const * entry, TheaterType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(Theater_From_Name(buffer));\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_TheaterType -- Store the theater identifier to the INI database.            *\n *                                                                                             *\n *    Use this routine to store the theater name to the INI database.                          *\n *                                                                                             *\n * INPUT:   section  -- The section to store the entry under.                                  *\n *                                                                                             *\n *          entry    -- Identifier for the entry to store.                                     *\n *                                                                                             *\n *          value    -- The theater identifier to store.                                       *\n *                                                                                             *\n * OUTPUT:  bool; Was the theater identifier stored?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_TheaterType(char const * section, char const * entry, TheaterType value)\n{\n\treturn(Put_String(section, entry, Theaters[value].Name));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_TriggerType -- Fetch the trigger type identifier from the INI database.     *\n *                                                                                             *\n *    This routine will fetch the trigger type identifier from the INI database.               *\n *                                                                                             *\n * INPUT:   section  -- The section to search for the entry under.                             *\n *                                                                                             *\n *          entry    -- Identifier of the entry to search for.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the trigger type pointer if a match was found. No match found will    *\n *          return a NULL.                                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTriggerTypeClass * CCINIClass::Get_TriggerType(char const * section, char const * entry) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(TriggerTypeClass::From_Name(buffer));\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_TriggerType -- Store the trigger identifier to the INI database.            *\n *                                                                                             *\n *    This routine will store the trigger (as its name) to the INI database.                   *\n *                                                                                             *\n * INPUT:   section  -- The section to store the entry under.                                  *\n *                                                                                             *\n *          entry    -- The entry name to store the trigger identifier to.                     *\n *                                                                                             *\n *          value    -- The trigger type to store. The trigger name will be stored.            *\n *                                                                                             *\n * OUTPUT:  bool; Was the trigger name stored?                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_TriggerType(char const * section, char const * entry, TriggerTypeClass * value)\n{\n\treturn(Put_String(section, entry, value->Name()));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_ThemeType -- Fetch the theme identifier.                                    *\n *                                                                                             *\n *    This routine will fetch the theme identifier from the INI database.                      *\n *                                                                                             *\n * INPUT:   section  -- The section to search for the entry under.                             *\n *                                                                                             *\n *          entry    -- Identifier of the entry to search for.                                 *\n *                                                                                             *\n *          defvalue -- The default theme identifier to return if the entry could not be found.*\n *                                                                                             *\n * OUTPUT:  Returns with the theme identifier if it was found. If not found, then the default  *\n *          value is returned instead.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nThemeType CCINIClass::Get_ThemeType(char const * section, char const * entry, ThemeType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(Theme.From_Name(buffer));\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_ThemeType -- Store the theme identifier to the INI database.                *\n *                                                                                             *\n *    This routine will store the specified theme identifier to the INI database.              *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to store the entry under.                   *\n *                                                                                             *\n *          entry    -- Identifier for the entry to store the value to.                        *\n *                                                                                             *\n *          value    -- The theme identifier to store.                                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the theme identifier stored.                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_ThemeType(char const * section, char const * entry, ThemeType value)\n{\n\treturn(Put_String(section, entry, Theme.Base_Name(value)));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_SourceType -- Fetch the source (edge) type from the INI database.           *\n *                                                                                             *\n *    This routine will fetch the source (reinforcement edge) identifier from the INI          *\n *    database.                                                                                *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section that the entry will be searched under.      *\n *                                                                                             *\n *          entry    -- Identifier for the entry that will be searched for.                    *\n *                                                                                             *\n *          defvalue -- The default value to return if the entry could not be located.         *\n *                                                                                             *\n * OUTPUT:  Returns with the source type of the entry if found. If not found, then the         *\n *          default value is returned.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nSourceType CCINIClass::Get_SourceType(char const * section, char const * entry, SourceType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(Source_From_Name(buffer));\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_SourceType -- Store the source (edge) identifier to the INI database.       *\n *                                                                                             *\n *    This will store the source type (reinforcement edge) to the INI database.                *\n *                                                                                             *\n * INPUT:   section  -- The section to store the entry under.                                  *\n *                                                                                             *\n *          entry    -- Identifier of the entry to store the source identifier to.             *\n *                                                                                             *\n *          value    -- The source (edge) value to store.                                      *\n *                                                                                             *\n * OUTPUT:  bool; Was the source identifier stored?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_SourceType(char const * section, char const * entry, SourceType value)\n{\n\treturn(Put_String(section, entry, SourceName[value]));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_CrateType -- Fetches a crate type value from the INI database.              *\n *                                                                                             *\n *    This will return with the crate type specified in the INI database.                      *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to search under.                            *\n *                                                                                             *\n *          entry    -- The entry to find the matching crate value for.                        *\n *                                                                                             *\n *          defvalue -- The default crate value to return if the entry could not be found.     *\n *                                                                                             *\n * OUTPUT:  Returns with the crate type identified with the specified entry. If the entry      *\n *          could not be located, then the default value is returned.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCrateType CCINIClass::Get_CrateType(char const * section, char const * entry, CrateType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(Crate_From_Name(buffer));\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_CrateType -- Stores the crate value in the section and entry specified.     *\n *                                                                                             *\n *    This will store the specified crate value to the section and entry specified.            *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to store the entry under.                       *\n *                                                                                             *\n *          entry    -- The entry identifier to store the crate value with.                    *\n *                                                                                             *\n *          value    -- The crate value to store.                                              *\n *                                                                                             *\n * OUTPUT:  bool; Was the crate value stored to the INI database?                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_CrateType(char const * section, char const * entry, CrateType value)\n{\n\treturn(Put_String(section, entry, CrateNames[value]));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_TerrainType -- Fetch the terrain type identifier from the INI database.     *\n *                                                                                             *\n *    Fetches the terrain type number from the INI database.                                   *\n *                                                                                             *\n * INPUT:   section  -- The section to search for the entry under.                             *\n *                                                                                             *\n *          entry    -- Identifier for the entry to search for.                                *\n *                                                                                             *\n *          defvalue -- The default value to use if the entry could not be located.            *\n *                                                                                             *\n * OUTPUT:  Returns with the terrain type if found. If the entry wasn't found, then the        *\n *          default value will be returned.                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTerrainType CCINIClass::Get_TerrainType(char const * section, char const * entry, TerrainType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(TerrainTypeClass::From_Name(strtok(buffer, \",\")));\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_TerrainType -- Store the terrain type number to the INI database.           *\n *                                                                                             *\n *    This will store the terrain type identifier to the INI database.                         *\n *                                                                                             *\n * INPUT:   section  -- The section to store the entry under.                                  *\n *                                                                                             *\n *          entry    -- Identifier that the terrain number will be stored to.                  *\n *                                                                                             *\n *          value    -- The terrain type identifier to store.                                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the terrain identifier stored?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_TerrainType(char const * section, char const * entry, TerrainType value)\n{\n\treturn(Put_String(section, entry, TerrainTypeClass::As_Reference(value).Name()));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_Buildings -- Fetch a building bitfield from the INI database.               *\n *                                                                                             *\n *    This routing will fetch the a list of buildings from the INI database. The buildings     *\n *    are expressed as a comma separated list of building identifiers. The return value is     *\n *    a composite of bits that represent these buildings -- one bit per building type.         *\n *                                                                                             *\n * INPUT:   section  -- The section to search for the entry under.                             *\n *                                                                                             *\n *          entry    -- The entry to fetch the building list from.                             *\n *                                                                                             *\n *          defvalue -- The default value to return if the section and entry could not be      *\n *                      located.                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the building list (as a bitfield). If the entry could not be          *\n *          found, the the default value is returned instead.                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCINIClass::Get_Buildings(char const * section, char const * entry, long defvalue) const\n{\n\tchar buffer[128];\n\tlong pre;\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\n\t\tpre = 0;\n\t\tchar * token = strtok(buffer, \",\");\n\t\twhile (token != NULL && *token != '\\0') {\n\t\t\tStructType building = BuildingTypeClass::From_Name(token);\n\t\t\tif (building != STRUCT_NONE) {\n\t\t\t\tpre |= (1L << building);\n\t\t\t}\n\t\t\ttoken = strtok(NULL, \",\");\n\t\t}\n\t} else {\n\t\tpre = defvalue;\n\t}\n\n\treturn(pre);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_Buildings -- Store a building list to the INI database.                     *\n *                                                                                             *\n *    This will store a list of buildings to the INI database. The buildings are listed by     *\n *    their identifier names separated by commas.                                              *\n *                                                                                             *\n * INPUT:   section  -- The identifier for the section to store the entry under.               *\n *                                                                                             *\n *          entry    -- The entry to store the building list to.                               *\n *                                                                                             *\n *          value    -- A list of buildings (in the form of a bit field -- one bit per         *\n *                      building type).                                                        *\n *                                                                                             *\n * OUTPUT:  Was the building list stored to the INI file?                                      *\n *                                                                                             *\n * WARNINGS:   This is limited to the buildings that can be expressed in a bitfield long.      *\n *             Which means, there can be only a maximum of 32 building types listed and        *\n *             even then, the total line length generated must not exceed 128 bytes.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_Buildings(char const * section, char const * entry, long value)\n{\n\tchar buffer[128] = \"\";\n\tint maxi = (32 < STRUCT_COUNT) ? 32 : STRUCT_COUNT;\n\n\tfor (StructType index = STRUCT_FIRST; index < maxi; index++) {\n\t\tif ((value & (1L << index)) != 0) {\n\n\t\t\tif (buffer[0] != '\\0') {\n\t\t\t\tstrcat(buffer, \",\");\n\t\t\t}\n\t\t\tstrcat(buffer, BuildingTypeClass::As_Reference(index).IniName);\n\t\t}\n\t}\n\n\treturn(Put_String(section, entry, buffer));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_Unique_ID -- Fetch a unique identifier number for the INI file.             *\n *                                                                                             *\n *    This is a shorthand version of the message digest. It calculates the ID number from the  *\n *    message digest itself.                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a 32 bit unique identifier number for the INI database.               *\n *                                                                                             *\n * WARNINGS:   Since the return value is only 32 bits, it is much less secure than the         *\n *             complete message digest.                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CCINIClass::Get_Unique_ID(void) const\n{\n\tif (!IsDigestPresent) {\n\t\t((CCINIClass *)this)->Calculate_Message_Digest();\n\t}\n\n\treturn(CRCEngine()(&Digest[0], sizeof(Digest)));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Calculate_Message_Digest -- Calculate a message digest for the current database *\n *                                                                                             *\n *    This will calculate a new message digest according to the current state of the INI       *\n *    database.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If the database is changed in any fashion, this message digest will be rendered *\n *             obsolete.                                                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CCINIClass::Calculate_Message_Digest(void)\n{\n\t/*\n\t**\tCalculate the message digest for the INI data that was read.\n\t*/\n\tSHAPipe sha;\n\tINIClass::Save(sha);\n\tsha.Result(Digest);\n\tIsDigestPresent = true;\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Invalidate_Message_Digest -- Flag message digest as being invalid.              *\n *                                                                                             *\n *    This flags the message digest as being invalid so that it will be recalculated when      *\n *    needed.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CCINIClass::Invalidate_Message_Digest(void)\n{\n\tIsDigestPresent = false;\n}\n"
  },
  {
    "path": "CODE/CCINI.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CCINI.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CCINI.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/24/96                                                     *\n *                                                                                             *\n *                  Last Update : May 24, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CCINI_H\n#define CCINI_H\n\n#include\t\"ini.h\"\n#include\t\"fixed.h\"\n#include\t\"pk.h\"\n\nclass TriggerTypeClass;\n\n/*\n**\tThe advanced version of the INI database manager. It handles the C&C expansion types and\n**\tidentifiers. In addition, it automatically stores a message digest with the INI data\n**\tso that verification can occur.\n*/\nclass CCINIClass : public INIClass\n{\n\tpublic:\n\t\tCCINIClass(void) : IsDigestPresent(false) {}\n\n\t\tbool Load(FileClass & file, bool withdigest);\n\t\tbool Load(Straw & file, bool withdigest);\n\t\tint Save(FileClass & file, bool withdigest) const;\n\t\tint Save(Pipe & pipe, bool withdigest) const;\n\n\t\tlong Get_Buildings(char const * section, char const * entry, long defvalue) const;\n\t\tUnitType Get_UnitType(char const * section, char const * entry, UnitType defvalue) const;\n\t\tAnimType Get_AnimType(char const * section, char const * entry, AnimType defvalue) const;\n\t\tArmorType Get_ArmorType(char const * section, char const * entry, ArmorType defvalue) const;\n\t\tBulletType Get_BulletType(char const * section, char const * entry, BulletType defvalue) const;\n\t\tHousesType Get_HousesType(char const * section, char const * entry, HousesType defvalue) const;\n\t\tLEPTON Get_Lepton(char const * section, char const * entry, LEPTON defvalue) const;\n\t\tMPHType Get_MPHType(char const * section, char const * entry, MPHType defvalue) const;\n\t\tOverlayType Get_OverlayType(char const * section, char const * entry, OverlayType defvalue) const;\n\t\tSourceType Get_SourceType(char const * section, char const * entry, SourceType defvalue) const;\n\t\tTerrainType Get_TerrainType(char const * section, char const * entry, TerrainType defvalue) const;\n\t\tTheaterType Get_TheaterType(char const * section, char const * entry, TheaterType defvalue) const;\n\t\tThemeType Get_ThemeType(char const * section, char const * entry, ThemeType defvalue) const;\n\t\tTriggerTypeClass * Get_TriggerType(char const * section, char const * entry) const;\n\t\tVQType Get_VQType(char const * section, char const * entry, VQType defvalue) const;\n\t\tVocType Get_VocType(char const * section, char const * entry, VocType defvalue) const;\n\t\tWarheadType Get_WarheadType(char const * section, char const * entry, WarheadType defvalue) const;\n\t\tWeaponType Get_WeaponType(char const * section, char const * entry, WeaponType defvalue) const;\n\t\tlong Get_Owners(char const * section, char const * entry, long defvalue) const;\n\t\tCrateType Get_CrateType(char const * section, char const * entry, CrateType defvalue) const;\n\n\n\t\tbool Put_Buildings(char const * section, char const * entry, long value);\n\t\tbool Put_AnimType(char const * section, char const * entry, AnimType value);\n\t\tbool Put_UnitType(char const * section, char const * entry, UnitType value);\n\t\tbool Put_ArmorType(char const * section, char const * entry, ArmorType value);\n\t\tbool Put_BulletType(char const * section, char const * entry, BulletType value);\n\t\tbool Put_HousesType(char const * section, char const * entry, HousesType value);\n\t\tbool Put_Lepton(char const * section, char const * entry, LEPTON value);\n\t\tbool Put_MPHType(char const * section, char const * entry, MPHType value);\n\t\tbool Put_VQType(char const * section, char const * entry, VQType value);\n\t\tbool Put_OverlayType(char const * section, char const * entry, OverlayType value);\n\t\tbool Put_Owners(char const * section, char const * entry, long value);\n\t\tbool Put_SourceType(char const * section, char const * entry, SourceType value);\n\t\tbool Put_TerrainType(char const * section, char const * entry, TerrainType value);\n\t\tbool Put_TheaterType(char const * section, char const * entry, TheaterType value);\n\t\tbool Put_ThemeType(char const * section, char const * entry, ThemeType value);\n\t\tbool Put_TriggerType(char const * section, char const * entry, TriggerTypeClass * value);\n\t\tbool Put_VocType(char const * section, char const * entry, VocType value);\n\t\tbool Put_WarheadType(char const * section, char const * entry, WarheadType value);\n\t\tbool Put_WeaponType(char const * section, char const * entry, WeaponType value);\n\t\tbool Put_CrateType(char const * section, char const * entry, CrateType value);\n\n\t\tint Get_Unique_ID(void) const;\n\n\tprivate:\n\t\tvoid Calculate_Message_Digest(void);\n\t\tvoid Invalidate_Message_Digest(void);\n\n\t\tbool IsDigestPresent:1;\n\n\t\t/*\n\t\t**\tThis is the message digest (SHA) of the INI database that was embedded as part of\n\t\t**\tthe INI file.\n\t\t*/\n\t\tunsigned char Digest[20];\n};\n\n#endif\n"
  },
  {
    "path": "CODE/CCMPATH.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : CCMPATH.CPP                              *\n *                                                                         *\n *                   Programmer : Bill R. Randolph                         *\n *                                                                         *\n *                   Start Date : 01/09/96                                 *\n *                                                                         *\n *                  Last Update : January 11, 1996 [BRR]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Init_MPATH -- Performs MPATH-specific initialization                  *\n *   Shutdown_MPATH -- Shuts down MPATH connections                        *\n *   Connect_MPATH -- Waits for connections to other players               *\n *   Destroy_MPATH_Connection -- Destroys the given connection             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include \"function.h\"\n\n\n/***************************************************************************\n * Init_MPATH -- Performs MPATH-specific initialization                    *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/09/1996 BRR : Created.                                             *\n *=========================================================================*/\nint Init_MPATH(void)\n{\n#if(MPATH)\n\t//------------------------------------------------------------------------\n\t// Allocate a packet buffer for MPATH's use\n\t//------------------------------------------------------------------------\n\tSession.MPathPacket = new char[Session.MPathSize];\n\n\t//------------------------------------------------------------------------\n\t// Read the multiplayer settings from the CONQUER.INI file, and the game\n\t// options from the options file.\n\t//------------------------------------------------------------------------\n\tSession.Read_MultiPlayer_Settings();\n\n\tif (!Read_MPATH_Game_Options()) {\n\t\tWWMessageBox().Process(\"Unable to load game settings!\");\n\t\t//Prog_End();\n\t\tEmergency_Exit(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Flush all incoming packets\n\t//------------------------------------------------------------------------\n\tMPath->Flush_All();\n\n\t//------------------------------------------------------------------------\n\t// Form connections to all other players\n\t//------------------------------------------------------------------------\n\tConnect_MPATH();\n\n\t//------------------------------------------------------------------------\n\t// Set multiplayer values for the local system, and timing values.\n\t//------------------------------------------------------------------------\n\tSession.CommProtocol = COMM_PROTOCOL_MULTI_E_COMP;\n\n\treturn (1);\n#else\n\treturn (1);\n#endif\n\n}\t// end of Init_MPATH\n\n\n/***************************************************************************\n * Shutdown_MPATH -- Shuts down MPATH connections                          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/09/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Shutdown_MPATH(void)\n{\n#if(MPATH)\n\tCDTimerClass<SystemTimerClass> timer;\n\n\t//------------------------------------------------------------------------\n\t// Wait a full second before exiting, to ensure all packets get sent.\n\t//------------------------------------------------------------------------\n\ttimer = 60;\n\twhile (timer) ;\n\n\t//------------------------------------------------------------------------\n\t// Free memory\n\t//------------------------------------------------------------------------\n\tif (Session.MPathPacket) {\n\t\tdelete [] Session.MPathPacket;\n\t\tSession.MPathPacket = NULL;\n\t}\n\n\tif (MPath) {\n\t\tdelete MPath;\n\t\tMPath = NULL;\n\t}\n\n\treturn;\n\n#endif\n}\t// end of Shutdown_MPATH\n\n\n/***************************************************************************\n * Connect_MPATH -- Waits for connections to other players                 *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/10/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Connect_MPATH(void)\n{\n#if(MPATH)\n\ttypedef struct ConnectPacketTag {\n\t\tNetCommandType Dummy;\t\t\t\t// packet type; set to PING\n\t\tchar Name[MPLAYER_NAME_MAX];\t\t// player's name\n\t\tHousesType House;\t\t\t\t\t\t// player's ActLike\n\t\tunsigned char Color;\t\t\t\t\t// player's Color\n\t} ConnectPacketType;\n\tint num_players;\n\tint num_found;\n\tConnectPacketType send_packet;\n\tConnectPacketType receive_packet;\n\tint address;\n\tint found;\n\tint size;\n\tint i;\n\tCDTimerClass<SystemTimerClass> send_timer;\n\tNodeNameType *who;\n\n\tenum {\n\t\tD_TXT6_H = 7,\n\t\tD_MARGIN = 5,\n\t};\n\tstatic int x,y,w,h;\n\tchar const *buf1;\n\tchar const *buf2;\n\n\tint display = 0;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t//\n\t// Clear the Players list\n\t//\n\twhile (Session.Players.Count() > 0) {\n\t\tdelete Session.Players[0];\n\t\tSession.Players.Delete(Session.Players[0]);\n\t}\n\n\t//\n\t// Add myself to the list first thing\n\t//\n\twho = new NodeNameType;\n\tstrcpy(who->Name, Session.Handle);\n\twho->Player.House = Session.House;\n\twho->Player.Color = Session.ColorIdx;\n\tSession.Players.Add (who);\n\n\t//\n\t// Find out how many players to wait for\n\t//\n\tnum_players = MPath->Find_Num_Connections();\n\tnum_found = 0;\n\tSession.NumPlayers = num_players + 1;\n\n\t//\n\t// Send out a packet announcing my presence\n\t//\n\tsend_packet.Dummy = NET_PING;\n\tstrcpy(send_packet.Name, Session.Handle);\n\tsend_packet.House = Session.House;\n\tsend_packet.Color = Session.ColorIdx;\n\tMPath->Send_Global_Message(&send_packet, sizeof(send_packet), 0, 0);\n\n\t//\n\t// Start our packet-sending timer\n\t//\n\tsend_timer = 240;\n\n\t//\n\t// Wait for all players to enter the game\n\t//\n\tdisplay = 1;\n\twhile (num_found < num_players) {\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = 1;\n\t\t}\n\t\t#endif\n\n\t\tif (display) {\n\t\t\tFancy_Text_Print(\"\", 0, 0, 0, 0, TPF_TEXT);\n\t\t\tbuf1 = Text_String(TXT_WAITING_FOR_CONNECTIONS);\n\t\t\tbuf2 = Text_String(TXT_PRESS_ESC);\n\t\t\tw = MAX(String_Pixel_Width(buf1),String_Pixel_Width(buf2));\n\t\t\tw += (D_MARGIN * 2);\n\t\t\th = (D_TXT6_H * 2) + (D_MARGIN * 7);\n\t\t\tx = 160 - (w / 2);\n\t\t\ty = 100 - (h / 2);\n\t\t\tHide_Mouse();\n\t\t\t//Set_Logic_Page(SeenBuff);\n\t\t\tDialog_Box(x * RESFACTOR, y * RESFACTOR, w * RESFACTOR, h * RESFACTOR);\n\n\t\t\tFancy_Text_Print(buf1,\n\t\t\t\t160 * RESFACTOR,\n\t\t\t\t(y + (D_MARGIN * 2)) * RESFACTOR,\n\t\t\t\tscheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\tFancy_Text_Print(buf2,\n\t\t\t\t160 * RESFACTOR,\n\t\t\t\t(y + (D_MARGIN * 2) + D_TXT6_H + D_MARGIN) * RESFACTOR,\n\t\t\t\tscheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\tShow_Mouse();\n\t\t\tdisplay = 0;\n\t\t}\n\n\t\tMPath->Service();\n\n\t\t//\n\t\t// Check for an incoming packet; if a PING comes in, see if we already\n\t\t// have this player in our Players list.  If not, add him.\n\t\t//\n\t\tif (MPath->Get_Global_Message (&receive_packet, &size, &address) &&\n\t\t\treceive_packet.Dummy == NET_PING) {\n\t\t\tfound = 0;\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tif (Session.Players[i]->MPathAddress == address) {\n\t\t\t\t\tfound = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//\n\t\t\t// Create a new connection and a new node in the list.\n\t\t\t//\n\t\t\tif (!found) {\n\n\t\t\t\twho = new NodeNameType;\n\t\t\t\tstrcpy(who->Name, receive_packet.Name);\n\t\t\t\twho->MPathAddress = address;\n\t\t\t\twho->Player.House = receive_packet.House;\n\t\t\t\twho->Player.Color = (PlayerColorType)receive_packet.Color;\n\t\t\t\tSession.Players.Add (who);\n\n\t\t\t\tnum_found++;\n\n\t\t\t\tMPath->Send_Global_Message(&send_packet, sizeof(send_packet), 1,\n\t\t\t\t\taddress);\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t// If the user hits ESC, bail out.\n\t\t//\n\t\tif (Keyboard->Check()) {\n\t\t\tif (Keyboard->Get() == KN_ESC) {\n\t\t\t\t//Prog_End();\n\t\t\t\tEmergency_Exit(0);\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t// When our timer expires, re-send the packet.\n\t\t//\n\t\tif (!send_timer) {\n\t\t\tsend_packet.Dummy = NET_PING;\n\t\t\tMPath->Send_Global_Message(&send_packet, sizeof(send_packet), 0, 0);\n\t\t\tsend_timer = 240;\n\t\t}\n\t}\n\n#else\n\treturn;\n#endif\n}\n\n\n/***************************************************************************\n * Destroy_MPATH_Connection -- Destroys the given connection               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\t\tconnection ID to destroy\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\terror\t\t0 = user signed off; 1 = connection error; otherwise, \t\t*\n *\t\t\t\t\tno error is shown.\t\t  \t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/11/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Destroy_MPATH_Connection(int id, int error)\n{\n#if(MPATH)\n\tint i;\n\tHouseClass *housep;\n\tchar txt[80];\n\n\t//------------------------------------------------------------------------\n\t//\tDo nothing if the house isn't human.\n\t//------------------------------------------------------------------------\n\thousep = HouseClass::As_Pointer((HousesType)id);\n\tif (!housep || !housep->IsHuman)\n\t\treturn;\n\n\t/*------------------------------------------------------------------------\n\tCreate a message to display to the user\n\t------------------------------------------------------------------------*/\n\ttxt[0] = '\\0';\n\tif (error==1) {\n\t\tsprintf(txt,Text_String(TXT_CONNECTION_LOST),MPath->Connection_Name(id));\n\t} else if (error==0) {\n\t\tsprintf(txt,Text_String(TXT_LEFT_GAME),MPath->Connection_Name(id));\n\t}\n\n\tif (strlen(txt)) {\n\t\tSession.Messages.Add_Message (NULL,0, txt, housep->RemapColor,\n\t\t\tTPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Remove this player from the Players vector\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\tif (!stricmp(Session.Players[i]->Name,housep->IniName)) {\n\t\t\tdelete Session.Players[i];\n\t\t\tSession.Players.Delete(Session.Players[i]);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tDelete the MPATH connection\n\t------------------------------------------------------------------------*/\n\tMPath->Delete_Connection(id);\n\n\t//------------------------------------------------------------------------\n\t//\tTurn the player's house over to the computer's AI\n\t//------------------------------------------------------------------------\n\thousep->IsHuman = false;\n\thousep->IQ = Rule.MaxIQ;\n\tstrcpy (housep->IniName,Text_String(TXT_COMPUTER));\n\n\tSession.NumPlayers--;\n\n\t/*------------------------------------------------------------------------\n\tIf we're the last player left, tell the user.\n\t------------------------------------------------------------------------*/\n\tif (Session.NumPlayers == 1) {\n\t\tsprintf(txt,\"%s\",Text_String(TXT_JUST_YOU_AND_ME));\n\t\tSession.Messages.Add_Message (NULL, 0, txt, housep->RemapColor,\n\t\t\tTPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n#else\n\tid = id;\n\terror = error;\n\n#endif\n}\t// end of Destroy_MPATH_Connection\n\n\n/***************************** end of ccmpath.cpp **************************/\n"
  },
  {
    "path": "CODE/CCPTR.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CCPTR.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CCPTR.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/07/96                                                     *\n *                                                                                             *\n *                  Last Update : July 6, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CCPtr<T>::operator > -- Greater than comparison operator.                                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n\n/*\n**\tThese member functions for the CCPtr class cannot be declared inside the\n**\tclass definition since they could refer to other objects that themselves\n**\tcontain CCPtr objects. The recursive nature of this type of declaration\n**\tis not handled by Watcom, hence the body declaration is dislocated here.\n*/\ntemplate<class T>\nCCPtr<T>::CCPtr(T * ptr) : ID(-1)\n{\n\tif (ptr != NULL) {\n\t\tID = ptr->ID;\n\t}\n}\n\n\n/***********************************************************************************************\n * CCPtr<T>::operator > -- Greater than comparison operator.                                   *\n *                                                                                             *\n *    This will compare two pointer value to see if the left hand value is greater than the    *\n *    right hand. The values are compared by comparing based on their Name() functions.        *\n *                                                                                             *\n * INPUT:   rvalue   -- The right handle CCPtr value.                                          *\n *                                                                                             *\n * OUTPUT:  Is the left hand value greater than the right hand value?                          *\n *                                                                                             *\n * WARNINGS:   The values pointed to by CCPtr must have a Name() function defined.             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool CCPtr<T>::operator > (CCPtr<T> const & rvalue) const\n{\n\treturn (stricmp((*this)->Name(), rvalue->Name()) > 0);\n}\n"
  },
  {
    "path": "CODE/CCPTR.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CCPTR.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CCPTR.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/07/96                                                     *\n *                                                                                             *\n *                  Last Update : June 7, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef CCPTR_H\n#define CCPTR_H\n\n/*\n**\tThe CCPtr class is designed for a specific purpose. It functions like a pointer except that\n**\tit requires no fixups for saving and loading. If pointer fixups are not an issue, than using\n**\tregular pointers would be more efficient.\n*/\ntemplate<class T>\nclass CCPtr\n{\n\tpublic:\n\t\tCCPtr(void) : ID(-1) {};\n\t\tCCPtr(NoInitClass const & ) {};\n\t\tCCPtr(T * ptr);\n\n\t\toperator T * (void) const {\n\t\t\tif (ID == -1) return(NULL);\n\t\t\tassert(Heap != NULL && (unsigned)ID < Heap->Length());\n\t\t\treturn((T*) (*Heap)[ID]);\n\t\t}\n\t\tT & operator * (void) const {\n\t\t\tassert(Heap != NULL && (unsigned)ID < Heap->Length());\n\t\t\treturn(*(T*)(*Heap)[ID]);\n\t\t}\n\t\tT * operator -> (void) const {\n\t\t\tif (ID == -1) return(NULL);\n\t\t\tassert(Heap != NULL && (unsigned)ID < Heap->Length());\n\t\t\treturn((T*) (*Heap)[ID]);\n\t\t}\n\n\t\tbool Is_Valid(void) const {return(ID != -1);}\n\n\t\tbool operator == (CCPtr<T> const & rvalue) const {return(ID == rvalue.ID);}\n\t\tbool operator != (CCPtr<T> const & rvalue) const {return(ID != rvalue.ID);}\n\t\tbool operator > (CCPtr<T> const & rvalue) const;\n\t\tbool operator <= (CCPtr<T> const & rvalue) const {return (rvalue > *this);}\n\t\tbool operator < (CCPtr<T> const & rvalue) const {return (*this != rvalue && rvalue > *this);}\n\t\tbool operator >= (CCPtr<T> const & rvalue) const {return (*this == rvalue || rvalue > *this);}\n\n\t\tlong Raw(void) const {return(ID);}\n\t\tvoid Set_Raw(long value) {ID = value;}\n\n\tprivate:\n\n\t\tstatic FixedIHeapClass * Heap;\n\n\t\t/*\n\t\t**\tThis is the ID number of the object it refers to. By using an ID number, this class can\n\t\t**\tbe saved and loaded without pointer fixups.\n\t\t*/\n\t\tint ID;\n};\n\n/*\n**\tThese template helper functions tell the compiler what to do in the\n**\tambiguous case of a CCPtr on one side and a regular type pointer on the\n**\tother side. In such a case the compiler could create a temp CCPtr object\n**\tOR call the conversion operator on the existing CCPtr object. Either way\n**\tis technically valid, but the compiler doesn't know which is better so it\n**\tgenerates an error. These routines force the conversion operator rather than\n**\tcreating a temporary object. This presumes that the conversion operator is\n**\tcheaper than constructing a temporary and that cheaper solutions are desirable.\n*/\ntemplate<class T>\nint operator == (CCPtr<T> & lvalue, T * rvalue)\n{\n\treturn((T*)lvalue == rvalue);\n}\n\ntemplate<class T>\nint operator == (T * lvalue, CCPtr<T> & rvalue)\n{\n\treturn(lvalue == (T*)rvalue);\n}\n\n#endif\n"
  },
  {
    "path": "CODE/CCTEN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : CCTEN.CPP                                *\n *                                                                         *\n *                   Programmer : Bill R. Randolph                         *\n *                                                                         *\n *                   Start Date : 01/09/96                                 *\n *                                                                         *\n *                  Last Update : November 27, 1996 [BRR]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Init_TEN -- Performs TEN-specific initialization                      *\n *   Shutdown_TEN -- Shuts down TEN connections                            *\n *   Connect_TEN -- Waits for connections to other players                 *\n *   Destroy_TEN_Connection -- Destroys the given connection               *\n *   Debug_Mono -- Custom mono prints                                      *\n *   Send_TEN_Win_Packet -- Sends a win packet to server                   *\n *   Send_TEN_Alliance -- Sends an ally/enemy packet to server             *\n *   Send_TEN_Out_Of_Sync -- Announces this game out of sync               *\n *   Send_TEN_Packet_Too_Late -- Announces packet-received-too-late        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include \"function.h\"\n\n#if(TEN)\n#ifdef WIN32\n#define WINDOWS\n#endif\n#include \"ten.h\"\n#endif\n\nvoid Connect_TEN(void);\nvoid Debug_Mono(void);\n\n/***************************************************************************\n * Init_TEN -- Performs TEN-specific initialization                        *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/09/1996 BRR : Created.                                             *\n *=========================================================================*/\nint Init_TEN(void)\n{\n#if(TEN)\n\t//------------------------------------------------------------------------\n\t// Allocate a packet buffer for TEN's use\n\t//------------------------------------------------------------------------\n\tSession.TenPacket = new char[Session.TenSize];\n\n\t//------------------------------------------------------------------------\n\t// Read the multiplayer settings from the CONQUER.INI file, and the game\n\t// options from the options file.\n\t//------------------------------------------------------------------------\n\tSession.Read_MultiPlayer_Settings();\n\n\tif (!Read_TEN_Game_Options()) {\n\t\tWWMessageBox().Process(\"Unable to load game settings!\");\n\t\t//Prog_End();\n\t\tEmergency_Exit(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Flush all incoming packets\n\t//------------------------------------------------------------------------\n\tTen->Flush_All();\n\n\t//------------------------------------------------------------------------\n\t// Form connections to all other players\n\t//------------------------------------------------------------------------\n\tConnect_TEN();\n\n\t//------------------------------------------------------------------------\n\t// Set multiplayer values for the local system, and timing values.\n\t//------------------------------------------------------------------------\n\tSession.CommProtocol = COMM_PROTOCOL_MULTI_E_COMP;\n\n\treturn (1);\n#else\n\treturn (1);\n#endif\n\n}\t// end of Init_TEN\n\n\n/***************************************************************************\n * Shutdown_TEN -- Shuts down TEN connections                              *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/09/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Shutdown_TEN(void)\n{\n#if(TEN)\n\tCDTimerClass<SystemTimerClass> timer;\n\n\t//------------------------------------------------------------------------\n\t// Wait a full second before exiting, to ensure all packets get sent.\n\t//------------------------------------------------------------------------\n\ttimer = 60;\n\twhile (timer) ;\n\n\t//------------------------------------------------------------------------\n\t// Free memory\n\t//------------------------------------------------------------------------\n\tif (Session.TenPacket) {\n\t\tdelete [] Session.TenPacket;\n\t\tSession.TenPacket = NULL;\n\t}\n\n\tif (Ten) {\n\t\tdelete Ten;\n\t\tTen = NULL;\n\t}\n\n\treturn;\n\n#endif\n}\t// end of Shutdown_TEN\n\n\n/***************************************************************************\n * Connect_TEN -- Waits for connections to other players                 \t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tMPlayerCount must have been initialized at this point.\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/10/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Connect_TEN(void)\n{\n#if(TEN)\n\ttypedef struct ConnectPacketTag {\n\t\tNetCommandType Dummy;\t\t\t\t// packet type; set to PING\n\t\tchar Name[MPLAYER_NAME_MAX];\t\t// player's name\n\t\tHousesType House;\t\t\t\t\t\t// player's ActLike\n\t\tunsigned char Color;\t\t\t\t\t// player's Color\n\t} ConnectPacketType;\n\tint num_players;\n\tint num_found;\n\tConnectPacketType send_packet;\n\tConnectPacketType receive_packet;\n\tint address;\n\tint found;\n\tint size;\n\tint i;\n\tCDTimerClass<SystemTimerClass> send_timer;\n\tNodeNameType *who;\n\n\tenum {\n\t\tD_TXT6_H = 7,\n\t\tD_MARGIN = 5,\n\t};\n\tstatic int x,y,w,h;\n\tchar const *buf1;\n\tchar const *buf2;\n\n\tint display = 0;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t//\n\t// Clear the Players list\n\t//\n\twhile (Session.Players.Count() > 0) {\n\t\tdelete Session.Players[0];\n\t\tSession.Players.Delete(Session.Players[0]);\n\t}\n\n\t//\n\t// Add myself to the list first thing\n\t//\n\twho = new NodeNameType;\n\tstrcpy(who->Name, Session.Handle);\n\twho->Player.House = Session.House;\n\twho->Player.Color = Session.ColorIdx;\n\tSession.Players.Add (who);\n\n\t//\n\t// Find out how many players to wait for\n\t//\n\tnum_players = Session.NumPlayers - 1;\n\tnum_found = 0;\n\n\t//\n\t// Send out a packet announcing my presence\n\t//\n\tsend_packet.Dummy = NET_PING;\n\tstrcpy(send_packet.Name, Session.Handle);\n\tsend_packet.House = Session.House;\n\tsend_packet.Color = Session.ColorIdx;\n\tTen->Send_Global_Message(&send_packet, sizeof(send_packet), 0, -1);\n\n\t//\n\t// Start our packet-sending timer\n\t//\n\tsend_timer = 240;\n\n\t//\n\t// Wait for all players to enter the game\n\t//\n\tdisplay = 1;\n\twhile (num_found < num_players) {\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = 1;\n\t\t}\n\t\t#endif\n\n\t\tif (display) {\n\t\t\tFancy_Text_Print(\"\", 0, 0, 0, 0, TPF_TEXT);\n\t\t\tbuf1 = Text_String(TXT_WAITING_FOR_CONNECTIONS);\n\t\t\tbuf2 = Text_String(TXT_PRESS_ESC);\n\t\t\tw = MAX(String_Pixel_Width(buf1),String_Pixel_Width(buf2));\n\t\t\tw += (D_MARGIN * 2);\n\t\t\th = (D_TXT6_H * 2) + (D_MARGIN * 7);\n\t\t\tx = 160 - (w / 2);\n\t\t\ty = 100 - (h / 2);\n\t\t\tHide_Mouse();\n\t\t\t//Set_Logic_Page(SeenBuff);\n\t\t\tDialog_Box(x * RESFACTOR, y * RESFACTOR, w * RESFACTOR, h * RESFACTOR);\n\n\t\t\tFancy_Text_Print(buf1,\n\t\t\t\t160 * RESFACTOR,\n\t\t\t\t(y + (D_MARGIN * 2)) * RESFACTOR,\n\t\t\t\tscheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\tFancy_Text_Print(buf2,\n\t\t\t\t160 * RESFACTOR,\n\t\t\t\t(y + (D_MARGIN * 2) + D_TXT6_H + D_MARGIN) * RESFACTOR,\n\t\t\t\tscheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\tShow_Mouse();\n\t\t\tdisplay = 0;\n\t\t}\n\n\t\tTen->Service();\n\n\t\t//\n\t\t// Check for an incoming packet; if a PING comes in, see if we already\n\t\t// have this player in our Players list.  If not, add him.\n\t\t//\n\t\tif (Ten->Get_Global_Message (&receive_packet, &size, &address) &&\n\t\t\treceive_packet.Dummy == NET_PING) {\n\t\t\tfound = 0;\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tif (Session.Players[i]->TenAddress == address) {\n\t\t\t\t\tfound = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//\n\t\t\t// Create a new connection and a new node in the list.\n\t\t\t//\n\t\t\tif (!found) {\n\n\t\t\t\twho = new NodeNameType;\n\t\t\t\tstrcpy(who->Name, receive_packet.Name);\n\t\t\t\twho->TenAddress = address;\n\t\t\t\twho->Player.House = receive_packet.House;\n\t\t\t\twho->Player.Color = (PlayerColorType)receive_packet.Color;\n\t\t\t\tSession.Players.Add (who);\n\n\t\t\t\tnum_found++;\n\n\t\t\t\tTen->Send_Global_Message(&send_packet, sizeof(send_packet), 1,\n\t\t\t\t\taddress);\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t// If the user hits ESC, bail out.\n\t\t//\n\t\tif (Keyboard->Check()) {\n\t\t\tif (Keyboard->Get() == KN_ESC) {\n\t\t\t\t//Prog_End();\n\t\t\t\tEmergency_Exit(0);\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t// When our timer expires, re-send the packet.\n\t\t//\n\t\tif (!send_timer) {\n\t\t\tsend_packet.Dummy = NET_PING;\n\t\t\tTen->Send_Global_Message(&send_packet, sizeof(send_packet), 0, -1);\n\t\t\tsend_timer = 240;\n\t\t}\n\t}\n\n#else\n\treturn;\n#endif\n}\n\n\n/***************************************************************************\n * Destroy_TEN_Connection -- Destroys the given connection                 *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\t\tconnection ID to destroy (must be a HousesType)\t\t\t\t\t*\n *\t\terror\t\t0 = user signed off; 1 = connection error; otherwise, \t\t*\n *\t\t\t\t\tno error is shown.\t\t  \t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/11/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Destroy_TEN_Connection(int id, int error)\n{\n#if(TEN)\n\tint i;\n\tHouseClass *housep;\n\tchar txt[80];\n\n\t//------------------------------------------------------------------------\n\t//\tDo nothing if the house isn't human.\n\t//------------------------------------------------------------------------\n\thousep = HouseClass::As_Pointer((HousesType)id);\n\tif (!housep || !housep->IsHuman)\n\t\treturn;\n\n\t/*------------------------------------------------------------------------\n\tCreate a message to display to the user\n\t------------------------------------------------------------------------*/\n\ttxt[0] = '\\0';\n\tif (error==1) {\n\t\tsprintf(txt,Text_String(TXT_CONNECTION_LOST),Ten->Connection_Name(id));\n\t} else if (error==0) {\n\t\tsprintf(txt,Text_String(TXT_LEFT_GAME),Ten->Connection_Name(id));\n\t}\n\n\tif (strlen(txt)) {\n\t\tSession.Messages.Add_Message (NULL,0, txt, housep->RemapColor,\n\t\t\tTPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Remove this player from the Players vector\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\tif (!stricmp(Session.Players[i]->Name,housep->IniName)) {\n\t\t\tdelete Session.Players[i];\n\t\t\tSession.Players.Delete(Session.Players[i]);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tDelete the TEN connection\n\t------------------------------------------------------------------------*/\n\tTen->Delete_Connection(id);\n\n\t//------------------------------------------------------------------------\n\t//\tTurn the player's house over to the computer's AI\n\t//------------------------------------------------------------------------\n\thousep->IsHuman = false;\n\thousep->IQ = Rule.MaxIQ;\n\tstrcpy (housep->IniName,Text_String(TXT_COMPUTER));\n\n\tSession.NumPlayers--;\n\n\t/*------------------------------------------------------------------------\n\tIf we're the last player left, tell the user.\n\t------------------------------------------------------------------------*/\n\tif (Session.NumPlayers == 1) {\n\t\tsprintf(txt,\"%s\",Text_String(TXT_JUST_YOU_AND_ME));\n\t\tSession.Messages.Add_Message (NULL, 0, txt, housep->RemapColor,\n\t\t\tTPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n#else\n\tid = id;\n\terror = error;\n\n#endif\n}\t// end of Destroy_TEN_Connection\n\n\n/***************************************************************************\n * Debug_Mono -- Custom mono prints                                        *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/27/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Debug_Mono(void)\n{\n#if(TEN)\n\tint i;\n\tint id;\n\n\tMono_Printf(\"STATE: # Connections:%d\\n\",Ten->Num_Connections());\n\tfor (i=0;i<Ten->Num_Connections();i++) {\n\t\tid = Ten->Connection_ID(i);\n\t\tMono_Printf(\"Connection %d: Name:%s, ID:%d, Address:%d\\n\",\n\t\t\ti,\n\t\t\tTen->Connection_Name(id),\n\t\t\tTen->Connection_ID(i),\n\t\t\tTen->Connection_Address(id));\n\t}\n\n#endif\n}\n\n\n/***************************************************************************\n * Send_TEN_Win_Packet -- Sends a win packet to server                     *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/27/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Send_TEN_Win_Packet(void)\n{\n#if(TEN)\n\tchar winbuf[80];\n\tchar idbuf[20];\n\tint first = 1;\n\tHouseClass *hptr;\n\tint i;\n\n\t//\n\t// Build a special text buffer to send to the TEN server.  Format:\n\t// \"winner 'id id'\", where 'id' is the Ten Player ID of each player\n\t// on the winning team.  (For TEN, the color index is the player ID.)\n\t//\n\tsprintf(winbuf,\"winner '\");\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\thptr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\tif (!hptr->IsDefeated) {\n\t\t\tif (!first) {\n\t\t\t\tstrcat(winbuf,\" \");\n\t\t\t} else {\n\t\t\t\tfirst = 0;\n\t\t\t}\n\t\t\tsprintf(idbuf,\"%d\", Session.Players[i]->Player.Color);\n\t\t\tstrcat (winbuf, idbuf);\n\t\t}\n\t}\n\tstrcat (winbuf,\"' \");\n\ttenArSetPlayerState(winbuf);\n#endif\t// TEN\n\n}\t// end of Send_TEN_Win_Packet\n\n\n/***************************************************************************\n * Send_TEN_Alliance -- Sends an ally/enemy packet to server               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\twhom\t\tname of player we're allying / enemying with\t\t\t\t\t\t*\n *\t\tally\t\t1 = we're allying; 0 = we're breaking the alliance\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/27/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Send_TEN_Alliance(char *whom, int ally)\n{\n#if(TEN)\n\tchar buf[80];\n\n\tif (ally) {\n\t\tsprintf(buf,\"ally '%s' \",whom);\n\t} else {\n\t\tsprintf(buf,\"enemy '%s' \",whom);\n\t}\n\n\ttenArSetPlayerState(buf);\n\n#else\n\twhom = whom;\n\tally = ally;\n#endif\t// TEN\n\n}\t// end of Send_TEN_Alliance\n\n\n/***************************************************************************\n * Send_TEN_Out_Of_Sync -- Announces this game out of sync                 *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/27/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Send_TEN_Out_Of_Sync(void)\n{\n#if(TEN)\n\ttenArSetPlayerState(\"sync '1' \");\n#endif\t// TEN\n\n}\t// end of Send_TEN_Out_Of_Sync\n\n\n/***************************************************************************\n * Send_TEN_Packet_Too_Late -- Announces packet-received-too-late          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/27/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Send_TEN_Packet_Too_Late(void)\n{\n#if(TEN)\n\ttenArSetPlayerState(\"toolate '1' \");\n#endif\t// TEN\n\n}\t// end of Send_TEN_Packet_Too_Late\n\n\n/***************************** end of ccten.cpp *****************************/\n"
  },
  {
    "path": "CODE/CC_ICON.RC",
    "content": "\n#define ICON_1\t1\n\n\nICON_1 ICON \"redalert.ico\"\n\n"
  },
  {
    "path": "CODE/CC_ICON.RH",
    "content": "#define ICON_1\t1\n"
  },
  {
    "path": "CODE/CDATA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CDATA.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CDATA.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 16, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 6, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   TemplateTypeClass::As_Reference -- Fetches a reference to the template specified.         *\n *   TemplateTypeClass::Create_And_Place -- Creates and places a template object on the map.   *\n *   TemplateTypeClass::Create_One_Of -- Creates an object of this template type.              *\n *   TemplateTypeClass::Display -- Displays a generic representation of template.              *\n *   TemplateTypeClass::From_Name -- Determine template from ASCII name.                       *\n *   TemplateTypeClass::Init -- Loads graphic data for templates.                              *\n *   TemplateTypeClass::Land_Type -- Determines land type from template and icon number.       *\n *   TemplateTypeClass::Occupy_List -- Determines occupation list.                             *\n *   TemplateTypeClass::One_Time -- Performs one-time initialization                           *\n *   TemplateTypeClass::Prep_For_Add -- Prepares to add template to scenario.                  *\n *   TemplateTypeClass::TemplateTypeClass -- Constructor for template type objects.            *\n *   TemplateTypeClass::operator delete -- Deletes a template type object.                     *\n *   TemplateTypeClass::operator new -- Allocates a template type from special heap.           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\nstatic TemplateTypeClass const Empty(\n\tTEMPLATE_CLEAR1,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW|THEATERF_INTERIOR,\n\t\"CLEAR1\",\n\tTXT_CLEAR\n);\nstatic TemplateTypeClass const Clear(\n\tTEMPLATE_CLEAR1,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW|THEATERF_INTERIOR,\n\t\"CLEAR1\",\n\tTXT_CLEAR\n);\nstatic TemplateTypeClass const Road01(\n\tTEMPLATE_ROAD01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D01\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road02(\n\tTEMPLATE_ROAD02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D02\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road03(\n\tTEMPLATE_ROAD03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D03\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road04(\n\tTEMPLATE_ROAD04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D04\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road05(\n\tTEMPLATE_ROAD05,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D05\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road06(\n\tTEMPLATE_ROAD06,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D06\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road07(\n\tTEMPLATE_ROAD07,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D07\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road08(\n\tTEMPLATE_ROAD08,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D08\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road09(\n\tTEMPLATE_ROAD09,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D09\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road10(\n\tTEMPLATE_ROAD10,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D10\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road11(\n\tTEMPLATE_ROAD11,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D11\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road12(\n\tTEMPLATE_ROAD12,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D12\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road13(\n\tTEMPLATE_ROAD13,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D13\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road14(\n\tTEMPLATE_ROAD14,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D14\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road15(\n\tTEMPLATE_ROAD15,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D15\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road16(\n\tTEMPLATE_ROAD16,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D16\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road17(\n\tTEMPLATE_ROAD17,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D17\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road18(\n\tTEMPLATE_ROAD18,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D18\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road19(\n\tTEMPLATE_ROAD19,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D19\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road20(\n\tTEMPLATE_ROAD20,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D20\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road21(\n\tTEMPLATE_ROAD21,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D21\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road22(\n\tTEMPLATE_ROAD22,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D22\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road23(\n\tTEMPLATE_ROAD23,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D23\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road24(\n\tTEMPLATE_ROAD24,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D24\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road25(\n\tTEMPLATE_ROAD25,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D25\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road26(\n\tTEMPLATE_ROAD26,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D26\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road27(\n\tTEMPLATE_ROAD27,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D27\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road28(\n\tTEMPLATE_ROAD28,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D28\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road29(\n\tTEMPLATE_ROAD29,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D29\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road30(\n\tTEMPLATE_ROAD30,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D30\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road31(\n\tTEMPLATE_ROAD31,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D31\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road32(\n\tTEMPLATE_ROAD32,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D32\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road33(\n\tTEMPLATE_ROAD33,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D33\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road34(\n\tTEMPLATE_ROAD34,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D34\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road35(\n\tTEMPLATE_ROAD35,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D35\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road36(\n\tTEMPLATE_ROAD36,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D36\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road37(\n\tTEMPLATE_ROAD37,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D37\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road38(\n\tTEMPLATE_ROAD38,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D38\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road39(\n\tTEMPLATE_ROAD39,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D39\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road40(\n\tTEMPLATE_ROAD40,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D40\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road41(\n\tTEMPLATE_ROAD41,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D41\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road42(\n\tTEMPLATE_ROAD42,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D42\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road43(\n\tTEMPLATE_ROAD43,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D43\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road44(\n\tTEMPLATE_ROAD44,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D44\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road45(\n\tTEMPLATE_ROAD45,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D45\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Water(\n\tTEMPLATE_WATER,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"W1\",\n\tTXT_WATER\n);\nstatic TemplateTypeClass const Water2(\n\tTEMPLATE_WATER2,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"W2\",\n\tTXT_WATER\n);\nstatic TemplateTypeClass const Shore01(\n\tTEMPLATE_SHORE01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH01\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore02(\n\tTEMPLATE_SHORE02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH02\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore03(\n\tTEMPLATE_SHORE03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH03\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore04(\n\tTEMPLATE_SHORE04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH04\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore05(\n\tTEMPLATE_SHORE05,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH05\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore06(\n\tTEMPLATE_SHORE06,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH06\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore07(\n\tTEMPLATE_SHORE07,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH07\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore08(\n\tTEMPLATE_SHORE08,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH08\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore09(\n\tTEMPLATE_SHORE09,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH09\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore10(\n\tTEMPLATE_SHORE10,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH10\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore11(\n\tTEMPLATE_SHORE11,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH11\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore12(\n\tTEMPLATE_SHORE12,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH12\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore13(\n\tTEMPLATE_SHORE13,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH13\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore14(\n\tTEMPLATE_SHORE14,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH14\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore15(\n\tTEMPLATE_SHORE15,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH15\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore16(\n\tTEMPLATE_SHORE16,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH16\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore17(\n\tTEMPLATE_SHORE17,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH17\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore18(\n\tTEMPLATE_SHORE18,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH18\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore19(\n\tTEMPLATE_SHORE19,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH19\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore20(\n\tTEMPLATE_SHORE20,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH20\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore21(\n\tTEMPLATE_SHORE21,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH21\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore22(\n\tTEMPLATE_SHORE22,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH22\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore23(\n\tTEMPLATE_SHORE23,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH23\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore24(\n\tTEMPLATE_SHORE24,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH24\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore25(\n\tTEMPLATE_SHORE25,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH25\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore26(\n\tTEMPLATE_SHORE26,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH26\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore27(\n\tTEMPLATE_SHORE27,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH27\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore28(\n\tTEMPLATE_SHORE28,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH28\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore29(\n\tTEMPLATE_SHORE29,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH29\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore30(\n\tTEMPLATE_SHORE30,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH30\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore31(\n\tTEMPLATE_SHORE31,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH31\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore32(\n\tTEMPLATE_SHORE32,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH32\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore33(\n\tTEMPLATE_SHORE33,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH33\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore34(\n\tTEMPLATE_SHORE34,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH34\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore35(\n\tTEMPLATE_SHORE35,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH35\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore36(\n\tTEMPLATE_SHORE36,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH36\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore37(\n\tTEMPLATE_SHORE37,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH37\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore38(\n\tTEMPLATE_SHORE38,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH38\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore39(\n\tTEMPLATE_SHORE39,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH39\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore40(\n\tTEMPLATE_SHORE40,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH40\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore41(\n\tTEMPLATE_SHORE41,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH41\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore42(\n\tTEMPLATE_SHORE42,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH42\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore43(\n\tTEMPLATE_SHORE43,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH43\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore44(\n\tTEMPLATE_SHORE44,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH44\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore45(\n\tTEMPLATE_SHORE45,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH45\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore46(\n\tTEMPLATE_SHORE46,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH46\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore47(\n\tTEMPLATE_SHORE47,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH47\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore48(\n\tTEMPLATE_SHORE48,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH48\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore49(\n\tTEMPLATE_SHORE49,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH49\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore50(\n\tTEMPLATE_SHORE50,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH50\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore51(\n\tTEMPLATE_SHORE51,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH51\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore52(\n\tTEMPLATE_SHORE52,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH52\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore53(\n\tTEMPLATE_SHORE53,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH53\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore54(\n\tTEMPLATE_SHORE54,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH54\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore55(\n\tTEMPLATE_SHORE55,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH55\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore56(\n\tTEMPLATE_SHORE56,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH56\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Boulder1(\n\tTEMPLATE_BOULDER1,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"B1\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Boulder2(\n\tTEMPLATE_BOULDER2,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"B2\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Boulder3(\n\tTEMPLATE_BOULDER3,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"B3\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Boulder4(\n\tTEMPLATE_BOULDER4,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"B4\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Boulder5(\n\tTEMPLATE_BOULDER5,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"B5\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Boulder6(\n\tTEMPLATE_BOULDER6,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"B6\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope01(\n\tTEMPLATE_SLOPE01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S01\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope02(\n\tTEMPLATE_SLOPE02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S02\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope03(\n\tTEMPLATE_SLOPE03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S03\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope04(\n\tTEMPLATE_SLOPE04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S04\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope05(\n\tTEMPLATE_SLOPE05,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S05\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope06(\n\tTEMPLATE_SLOPE06,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S06\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope07(\n\tTEMPLATE_SLOPE07,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S07\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope08(\n\tTEMPLATE_SLOPE08,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S08\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope09(\n\tTEMPLATE_SLOPE09,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S09\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope10(\n\tTEMPLATE_SLOPE10,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S10\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope11(\n\tTEMPLATE_SLOPE11,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S11\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope12(\n\tTEMPLATE_SLOPE12,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S12\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope13(\n\tTEMPLATE_SLOPE13,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S13\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope14(\n\tTEMPLATE_SLOPE14,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S14\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope15(\n\tTEMPLATE_SLOPE15,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S15\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope16(\n\tTEMPLATE_SLOPE16,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S16\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope17(\n\tTEMPLATE_SLOPE17,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S17\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope18(\n\tTEMPLATE_SLOPE18,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S18\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope19(\n\tTEMPLATE_SLOPE19,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S19\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope20(\n\tTEMPLATE_SLOPE20,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S20\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope21(\n\tTEMPLATE_SLOPE21,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S21\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope22(\n\tTEMPLATE_SLOPE22,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S22\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope23(\n\tTEMPLATE_SLOPE23,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S23\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope24(\n\tTEMPLATE_SLOPE24,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S24\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope25(\n\tTEMPLATE_SLOPE25,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S25\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope26(\n\tTEMPLATE_SLOPE26,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S26\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope27(\n\tTEMPLATE_SLOPE27,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S27\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope28(\n\tTEMPLATE_SLOPE28,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S28\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope29(\n\tTEMPLATE_SLOPE29,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S29\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope30(\n\tTEMPLATE_SLOPE30,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S30\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope31(\n\tTEMPLATE_SLOPE31,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S31\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope32(\n\tTEMPLATE_SLOPE32,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S32\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope33(\n\tTEMPLATE_SLOPE33,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S33\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope34(\n\tTEMPLATE_SLOPE34,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S34\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope35(\n\tTEMPLATE_SLOPE35,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S35\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope36(\n\tTEMPLATE_SLOPE36,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S36\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope37(\n\tTEMPLATE_SLOPE37,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S37\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope38(\n\tTEMPLATE_SLOPE38,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S38\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Patch01(\n\tTEMPLATE_PATCH01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P01\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const Patch02(\n\tTEMPLATE_PATCH02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P02\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const Patch03(\n\tTEMPLATE_PATCH03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P03\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const Patch04(\n\tTEMPLATE_PATCH04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P04\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const Patch07(\n\tTEMPLATE_PATCH07,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P07\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const Patch08(\n\tTEMPLATE_PATCH08,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P08\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const Patch13(\n\tTEMPLATE_PATCH13,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P13\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const Patch14(\n\tTEMPLATE_PATCH14,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P14\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const Patch15(\n\tTEMPLATE_PATCH15,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P15\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const River01(\n\tTEMPLATE_RIVER01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV01\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River02(\n\tTEMPLATE_RIVER02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV02\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River03(\n\tTEMPLATE_RIVER03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV03\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River04(\n\tTEMPLATE_RIVER04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV04\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River05(\n\tTEMPLATE_RIVER05,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV05\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River06(\n\tTEMPLATE_RIVER06,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV06\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River07(\n\tTEMPLATE_RIVER07,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV07\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River08(\n\tTEMPLATE_RIVER08,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV08\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River09(\n\tTEMPLATE_RIVER09,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV09\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River10(\n\tTEMPLATE_RIVER10,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV10\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River11(\n\tTEMPLATE_RIVER11,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV11\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River12(\n\tTEMPLATE_RIVER12,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV12\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River13(\n\tTEMPLATE_RIVER13,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV13\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River14(\n\tTEMPLATE_RIVER14,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV14\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River15(\n\tTEMPLATE_RIVER15,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV15\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const Ford1(\n\tTEMPLATE_FORD1,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"FORD1\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const Ford2(\n\tTEMPLATE_FORD2,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"FORD2\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const Falls1(\n\tTEMPLATE_FALLS1,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"FALLS1\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const Falls1a(\n\tTEMPLATE_FALLS1A,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"FALLS1A\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const Falls2(\n\tTEMPLATE_FALLS2,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"FALLS2\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const Falls2a(\n\tTEMPLATE_FALLS2A,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"FALLS2A\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const Bridge1x(\n\tTEMPLATE_BRIDGE1X,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BRIDGE1X\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge1(\n\tTEMPLATE_BRIDGE1,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BRIDGE1\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge1h(\n\tTEMPLATE_BRIDGE1H,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BRIDGE1H\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge1d(\n\tTEMPLATE_BRIDGE1D,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BRIDGE1D\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge2x(\n\tTEMPLATE_BRIDGE2X,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BRIDGE2X\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge2(\n\tTEMPLATE_BRIDGE2,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BRIDGE2\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge2h(\n\tTEMPLATE_BRIDGE2H,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BRIDGE2H\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge2d(\n\tTEMPLATE_BRIDGE2D,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BRIDGE2D\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge1ax(\n\tTEMPLATE_BRIDGE_1AX,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR1X\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge1a(\n\tTEMPLATE_BRIDGE_1A,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR1A\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge1b(\n\tTEMPLATE_BRIDGE_1B,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR1B\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge1c(\n\tTEMPLATE_BRIDGE_1C,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR1C\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge2ax(\n\tTEMPLATE_BRIDGE_2AX,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR2X\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge2a(\n\tTEMPLATE_BRIDGE_2A,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR2A\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge2b(\n\tTEMPLATE_BRIDGE_2B,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR2B\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge2c(\n\tTEMPLATE_BRIDGE_2C,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR2C\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge3a(\n\tTEMPLATE_BRIDGE_3A,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR3A\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge3b(\n\tTEMPLATE_BRIDGE_3B,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR3B\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge3c(\n\tTEMPLATE_BRIDGE_3C,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR3C\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge3d(\n\tTEMPLATE_BRIDGE_3D,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR3D\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge3e(\n\tTEMPLATE_BRIDGE_3E,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR3E\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge3f(\n\tTEMPLATE_BRIDGE_3F,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR3F\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const ShoreCliff01(\n\tTEMPLATE_SHORECLIFF01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC01\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff02(\n\tTEMPLATE_SHORECLIFF02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC02\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff03(\n\tTEMPLATE_SHORECLIFF03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC03\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff04(\n\tTEMPLATE_SHORECLIFF04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC04\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff05(\n\tTEMPLATE_SHORECLIFF05,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC05\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff06(\n\tTEMPLATE_SHORECLIFF06,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC06\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff07(\n\tTEMPLATE_SHORECLIFF07,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC07\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff08(\n\tTEMPLATE_SHORECLIFF08,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC08\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff09(\n\tTEMPLATE_SHORECLIFF09,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC09\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff10(\n\tTEMPLATE_SHORECLIFF10,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC10\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff11(\n\tTEMPLATE_SHORECLIFF11,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC11\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff12(\n\tTEMPLATE_SHORECLIFF12,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC12\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff13(\n\tTEMPLATE_SHORECLIFF13,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC13\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff14(\n\tTEMPLATE_SHORECLIFF14,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC14\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff15(\n\tTEMPLATE_SHORECLIFF15,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC15\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff16(\n\tTEMPLATE_SHORECLIFF16,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC16\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff17(\n\tTEMPLATE_SHORECLIFF17,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC17\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff18(\n\tTEMPLATE_SHORECLIFF18,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC18\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff19(\n\tTEMPLATE_SHORECLIFF19,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC19\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff20(\n\tTEMPLATE_SHORECLIFF20,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC20\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff21(\n\tTEMPLATE_SHORECLIFF21,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC21\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff22(\n\tTEMPLATE_SHORECLIFF22,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC22\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff23(\n\tTEMPLATE_SHORECLIFF23,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC23\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff24(\n\tTEMPLATE_SHORECLIFF24,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC24\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff25(\n\tTEMPLATE_SHORECLIFF25,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC25\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff26(\n\tTEMPLATE_SHORECLIFF26,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC26\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff27(\n\tTEMPLATE_SHORECLIFF27,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC27\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff28(\n\tTEMPLATE_SHORECLIFF28,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC28\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff29(\n\tTEMPLATE_SHORECLIFF29,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC29\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff30(\n\tTEMPLATE_SHORECLIFF30,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC30\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff31(\n\tTEMPLATE_SHORECLIFF31,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC31\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff32(\n\tTEMPLATE_SHORECLIFF32,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC32\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff33(\n\tTEMPLATE_SHORECLIFF33,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC33\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff34(\n\tTEMPLATE_SHORECLIFF34,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC34\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff35(\n\tTEMPLATE_SHORECLIFF35,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC35\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff36(\n\tTEMPLATE_SHORECLIFF36,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC36\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff37(\n\tTEMPLATE_SHORECLIFF37,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC37\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff38(\n\tTEMPLATE_SHORECLIFF38,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC38\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Rough01(\n\tTEMPLATE_ROUGH01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF01\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough02(\n\tTEMPLATE_ROUGH02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF02\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough03(\n\tTEMPLATE_ROUGH03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF03\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough04(\n\tTEMPLATE_ROUGH04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF04\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough05(\n\tTEMPLATE_ROUGH05,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF05\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough06(\n\tTEMPLATE_ROUGH06,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF06\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough07(\n\tTEMPLATE_ROUGH07,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF07\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough08(\n\tTEMPLATE_ROUGH08,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF08\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough09(\n\tTEMPLATE_ROUGH09,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF09\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough10(\n\tTEMPLATE_ROUGH10,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF10\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough11(\n\tTEMPLATE_ROUGH11,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF11\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const RiverCliff01(\n\tTEMPLATE_RIVERCLIFF01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RC01\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const RiverCliff02(\n\tTEMPLATE_RIVERCLIFF02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RC02\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const RiverCliff03(\n\tTEMPLATE_RIVERCLIFF03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RC03\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const RiverCliff04(\n\tTEMPLATE_RIVERCLIFF04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RC04\",\n\tTXT_RIVER\n);\n\nstatic TemplateTypeClass const F01(\n\tTEMPLATE_F01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"F01\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const F02(\n\tTEMPLATE_F02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"F02\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const F03(\n\tTEMPLATE_F03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"F03\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const F04(\n\tTEMPLATE_F04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"F04\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const F05(\n\tTEMPLATE_F05,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"F05\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const F06(\n\tTEMPLATE_F06,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"F06\",\n\tTXT_RIVER\n);\n\nstatic TemplateTypeClass const ARRO0001(\n\tTEMPLATE_ARRO0001,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0001\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0002(\n\tTEMPLATE_ARRO0002,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0002\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0003(\n\tTEMPLATE_ARRO0003,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0003\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0004(\n\tTEMPLATE_ARRO0004,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0004\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0005(\n\tTEMPLATE_ARRO0005,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0005\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0006(\n\tTEMPLATE_ARRO0006,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0006\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0007(\n\tTEMPLATE_ARRO0007,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0007\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0008(\n\tTEMPLATE_ARRO0008,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0008\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0009(\n\tTEMPLATE_ARRO0009,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0009\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0010(\n\tTEMPLATE_ARRO0010,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0010\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0011(\n\tTEMPLATE_ARRO0011,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0011\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0012(\n\tTEMPLATE_ARRO0012,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0012\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0013(\n\tTEMPLATE_ARRO0013,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0013\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0014(\n\tTEMPLATE_ARRO0014,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0014\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0015(\n\tTEMPLATE_ARRO0015,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0015\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const FLOR0001(\n\tTEMPLATE_FLOR0001,\n\tTHEATERF_INTERIOR,\n\t\"FLOR0001\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const FLOR0002(\n\tTEMPLATE_FLOR0002,\n\tTHEATERF_INTERIOR,\n\t\"FLOR0002\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const FLOR0003(\n\tTEMPLATE_FLOR0003,\n\tTHEATERF_INTERIOR,\n\t\"FLOR0003\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const FLOR0004(\n\tTEMPLATE_FLOR0004,\n\tTHEATERF_INTERIOR,\n\t\"FLOR0004\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const FLOR0005(\n\tTEMPLATE_FLOR0005,\n\tTHEATERF_INTERIOR,\n\t\"FLOR0005\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const FLOR0006(\n\tTEMPLATE_FLOR0006,\n\tTHEATERF_INTERIOR,\n\t\"FLOR0006\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const FLOR0007(\n\tTEMPLATE_FLOR0007,\n\tTHEATERF_INTERIOR,\n\t\"FLOR0007\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GFLR0001(\n\tTEMPLATE_GFLR0001,\n\tTHEATERF_INTERIOR,\n\t\"GFLR0001\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GFLR0002(\n\tTEMPLATE_GFLR0002,\n\tTHEATERF_INTERIOR,\n\t\"GFLR0002\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GFLR0003(\n\tTEMPLATE_GFLR0003,\n\tTHEATERF_INTERIOR,\n\t\"GFLR0003\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GFLR0004(\n\tTEMPLATE_GFLR0004,\n\tTHEATERF_INTERIOR,\n\t\"GFLR0004\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GFLR0005(\n\tTEMPLATE_GFLR0005,\n\tTHEATERF_INTERIOR,\n\t\"GFLR0005\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0001(\n\tTEMPLATE_GSTR0001,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0001\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0002(\n\tTEMPLATE_GSTR0002,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0002\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0003(\n\tTEMPLATE_GSTR0003,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0003\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0004(\n\tTEMPLATE_GSTR0004,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0004\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0005(\n\tTEMPLATE_GSTR0005,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0005\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0006(\n\tTEMPLATE_GSTR0006,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0006\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0007(\n\tTEMPLATE_GSTR0007,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0007\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0008(\n\tTEMPLATE_GSTR0008,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0008\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0009(\n\tTEMPLATE_GSTR0009,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0009\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0010(\n\tTEMPLATE_GSTR0010,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0010\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0011(\n\tTEMPLATE_GSTR0011,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0011\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0001(\n\tTEMPLATE_LWAL0001,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0001\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0002(\n\tTEMPLATE_LWAL0002,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0002\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0003(\n\tTEMPLATE_LWAL0003,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0003\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0004(\n\tTEMPLATE_LWAL0004,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0004\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0005(\n\tTEMPLATE_LWAL0005,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0005\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0006(\n\tTEMPLATE_LWAL0006,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0006\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0007(\n\tTEMPLATE_LWAL0007,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0007\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0008(\n\tTEMPLATE_LWAL0008,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0008\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0009(\n\tTEMPLATE_LWAL0009,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0009\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0010(\n\tTEMPLATE_LWAL0010,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0010\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0011(\n\tTEMPLATE_LWAL0011,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0011\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0012(\n\tTEMPLATE_LWAL0012,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0012\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0013(\n\tTEMPLATE_LWAL0013,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0013\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0014(\n\tTEMPLATE_LWAL0014,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0014\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0015(\n\tTEMPLATE_LWAL0015,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0015\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0016(\n\tTEMPLATE_LWAL0016,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0016\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0017(\n\tTEMPLATE_LWAL0017,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0017\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0018(\n\tTEMPLATE_LWAL0018,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0018\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0019(\n\tTEMPLATE_LWAL0019,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0019\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0020(\n\tTEMPLATE_LWAL0020,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0020\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0021(\n\tTEMPLATE_LWAL0021,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0021\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0022(\n\tTEMPLATE_LWAL0022,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0022\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0023(\n\tTEMPLATE_LWAL0023,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0023\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0024(\n\tTEMPLATE_LWAL0024,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0024\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0025(\n\tTEMPLATE_LWAL0025,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0025\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0026(\n\tTEMPLATE_LWAL0026,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0026\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0027(\n\tTEMPLATE_LWAL0027,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0027\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0001(\n\tTEMPLATE_STRP0001,\n\tTHEATERF_INTERIOR,\n\t\"STRP0001\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0002(\n\tTEMPLATE_STRP0002,\n\tTHEATERF_INTERIOR,\n\t\"STRP0002\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0003(\n\tTEMPLATE_STRP0003,\n\tTHEATERF_INTERIOR,\n\t\"STRP0003\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0004(\n\tTEMPLATE_STRP0004,\n\tTHEATERF_INTERIOR,\n\t\"STRP0004\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0005(\n\tTEMPLATE_STRP0005,\n\tTHEATERF_INTERIOR,\n\t\"STRP0005\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0006(\n\tTEMPLATE_STRP0006,\n\tTHEATERF_INTERIOR,\n\t\"STRP0006\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0007(\n\tTEMPLATE_STRP0007,\n\tTHEATERF_INTERIOR,\n\t\"STRP0007\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0008(\n\tTEMPLATE_STRP0008,\n\tTHEATERF_INTERIOR,\n\t\"STRP0008\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0009(\n\tTEMPLATE_STRP0009,\n\tTHEATERF_INTERIOR,\n\t\"STRP0009\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0010(\n\tTEMPLATE_STRP0010,\n\tTHEATERF_INTERIOR,\n\t\"STRP0010\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0011(\n\tTEMPLATE_STRP0011,\n\tTHEATERF_INTERIOR,\n\t\"STRP0011\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0001(\n\tTEMPLATE_WALL0001,\n\tTHEATERF_INTERIOR,\n\t\"WALL0001\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0002(\n\tTEMPLATE_WALL0002,\n\tTHEATERF_INTERIOR,\n\t\"WALL0002\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0003(\n\tTEMPLATE_WALL0003,\n\tTHEATERF_INTERIOR,\n\t\"WALL0003\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0004(\n\tTEMPLATE_WALL0004,\n\tTHEATERF_INTERIOR,\n\t\"WALL0004\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0005(\n\tTEMPLATE_WALL0005,\n\tTHEATERF_INTERIOR,\n\t\"WALL0005\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0006(\n\tTEMPLATE_WALL0006,\n\tTHEATERF_INTERIOR,\n\t\"WALL0006\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0007(\n\tTEMPLATE_WALL0007,\n\tTHEATERF_INTERIOR,\n\t\"WALL0007\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0008(\n\tTEMPLATE_WALL0008,\n\tTHEATERF_INTERIOR,\n\t\"WALL0008\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0009(\n\tTEMPLATE_WALL0009,\n\tTHEATERF_INTERIOR,\n\t\"WALL0009\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0010(\n\tTEMPLATE_WALL0010,\n\tTHEATERF_INTERIOR,\n\t\"WALL0010\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0011(\n\tTEMPLATE_WALL0011,\n\tTHEATERF_INTERIOR,\n\t\"WALL0011\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0012(\n\tTEMPLATE_WALL0012,\n\tTHEATERF_INTERIOR,\n\t\"WALL0012\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0013(\n\tTEMPLATE_WALL0013,\n\tTHEATERF_INTERIOR,\n\t\"WALL0013\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0014(\n\tTEMPLATE_WALL0014,\n\tTHEATERF_INTERIOR,\n\t\"WALL0014\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0015(\n\tTEMPLATE_WALL0015,\n\tTHEATERF_INTERIOR,\n\t\"WALL0015\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0016(\n\tTEMPLATE_WALL0016,\n\tTHEATERF_INTERIOR,\n\t\"WALL0016\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0017(\n\tTEMPLATE_WALL0017,\n\tTHEATERF_INTERIOR,\n\t\"WALL0017\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0018(\n\tTEMPLATE_WALL0018,\n\tTHEATERF_INTERIOR,\n\t\"WALL0018\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0019(\n\tTEMPLATE_WALL0019,\n\tTHEATERF_INTERIOR,\n\t\"WALL0019\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0020(\n\tTEMPLATE_WALL0020,\n\tTHEATERF_INTERIOR,\n\t\"WALL0020\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0021(\n\tTEMPLATE_WALL0021,\n\tTHEATERF_INTERIOR,\n\t\"WALL0021\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0022(\n\tTEMPLATE_WALL0022,\n\tTHEATERF_INTERIOR,\n\t\"WALL0022\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0023(\n\tTEMPLATE_WALL0023,\n\tTHEATERF_INTERIOR,\n\t\"WALL0023\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0024(\n\tTEMPLATE_WALL0024,\n\tTHEATERF_INTERIOR,\n\t\"WALL0024\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0025(\n\tTEMPLATE_WALL0025,\n\tTHEATERF_INTERIOR,\n\t\"WALL0025\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0026(\n\tTEMPLATE_WALL0026,\n\tTHEATERF_INTERIOR,\n\t\"WALL0026\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0027(\n\tTEMPLATE_WALL0027,\n\tTHEATERF_INTERIOR,\n\t\"WALL0027\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0028(\n\tTEMPLATE_WALL0028,\n\tTHEATERF_INTERIOR,\n\t\"WALL0028\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0029(\n\tTEMPLATE_WALL0029,\n\tTHEATERF_INTERIOR,\n\t\"WALL0029\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0030(\n\tTEMPLATE_WALL0030,\n\tTHEATERF_INTERIOR,\n\t\"WALL0030\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0031(\n\tTEMPLATE_WALL0031,\n\tTHEATERF_INTERIOR,\n\t\"WALL0031\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0032(\n\tTEMPLATE_WALL0032,\n\tTHEATERF_INTERIOR,\n\t\"WALL0032\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0033(\n\tTEMPLATE_WALL0033,\n\tTHEATERF_INTERIOR,\n\t\"WALL0033\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0034(\n\tTEMPLATE_WALL0034,\n\tTHEATERF_INTERIOR,\n\t\"WALL0034\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0035(\n\tTEMPLATE_WALL0035,\n\tTHEATERF_INTERIOR,\n\t\"WALL0035\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0036(\n\tTEMPLATE_WALL0036,\n\tTHEATERF_INTERIOR,\n\t\"WALL0036\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0037(\n\tTEMPLATE_WALL0037,\n\tTHEATERF_INTERIOR,\n\t\"WALL0037\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0038(\n\tTEMPLATE_WALL0038,\n\tTHEATERF_INTERIOR,\n\t\"WALL0038\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0039(\n\tTEMPLATE_WALL0039,\n\tTHEATERF_INTERIOR,\n\t\"WALL0039\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0040(\n\tTEMPLATE_WALL0040,\n\tTHEATERF_INTERIOR,\n\t\"WALL0040\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0041(\n\tTEMPLATE_WALL0041,\n\tTHEATERF_INTERIOR,\n\t\"WALL0041\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0042(\n\tTEMPLATE_WALL0042,\n\tTHEATERF_INTERIOR,\n\t\"WALL0042\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0043(\n\tTEMPLATE_WALL0043,\n\tTHEATERF_INTERIOR,\n\t\"WALL0043\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0044(\n\tTEMPLATE_WALL0044,\n\tTHEATERF_INTERIOR,\n\t\"WALL0044\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0045(\n\tTEMPLATE_WALL0045,\n\tTHEATERF_INTERIOR,\n\t\"WALL0045\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0046(\n\tTEMPLATE_WALL0046,\n\tTHEATERF_INTERIOR,\n\t\"WALL0046\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0047(\n\tTEMPLATE_WALL0047,\n\tTHEATERF_INTERIOR,\n\t\"WALL0047\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0048(\n\tTEMPLATE_WALL0048,\n\tTHEATERF_INTERIOR,\n\t\"WALL0048\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0049(\n\tTEMPLATE_WALL0049,\n\tTHEATERF_INTERIOR,\n\t\"WALL0049\",\n\tTXT_INTERIOR\n);\n\nstatic TemplateTypeClass const Xtra0001(\n\tTEMPLATE_XTRA0001,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0001\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0002(\n\tTEMPLATE_XTRA0002,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0002\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0003(\n\tTEMPLATE_XTRA0003,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0003\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0004(\n\tTEMPLATE_XTRA0004,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0004\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0005(\n\tTEMPLATE_XTRA0005,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0005\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0006(\n\tTEMPLATE_XTRA0006,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0006\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0007(\n\tTEMPLATE_XTRA0007,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0007\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0008(\n\tTEMPLATE_XTRA0008,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0008\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0009(\n\tTEMPLATE_XTRA0009,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0009\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0010(\n\tTEMPLATE_XTRA0010,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0010\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0011(\n\tTEMPLATE_XTRA0011,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0011\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0012(\n\tTEMPLATE_XTRA0012,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0012\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0013(\n\tTEMPLATE_XTRA0013,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0013\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0014(\n\tTEMPLATE_XTRA0014,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0014\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0015(\n\tTEMPLATE_XTRA0015,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0015\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0016(\n\tTEMPLATE_XTRA0016,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0016\",\n\tTXT_INTERIOR\n);\n\n#ifdef FIXIT_ANTS\nstatic TemplateTypeClass const AntHill(\n\tTEMPLATE_HILL01,\n\tTHEATERF_TEMPERATE,\n\t\"HILL01\",\n\tTXT_ROCK\n);\n#endif\n\n/***********************************************************************************************\n * TemplateTypeClass::TemplateTypeClass -- Constructor for template type objects.              *\n *                                                                                             *\n *    This is the constructor for the template types.                                          *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTemplateTypeClass::TemplateTypeClass(\n\tTemplateType iconset,\n\tint theater,\n\tchar const * ininame,\n\tint fullname) :\n\t\tObjectTypeClass(\n\t\t\tRTTI_TEMPLATETYPE,\n\t\t\tint(iconset),\n\t\t\tfalse,\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t\ttrue,\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t\tfullname,\n\t\t\tininame),\n\tType(iconset),\n\tTheater(theater),\n\tWidth(0),\n\tHeight(0)\n{\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::operator new -- Allocates a template type from special heap.             *\n *                                                                                             *\n *    This allocates a template type object from the special heap used for that purpose.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the newly allocated template type object. If no object   *\n *          could be allocated, then NULL is returned.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * TemplateTypeClass::operator new(size_t)\n{\n\treturn(TemplateTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::operator delete -- Deletes a template type object.                       *\n *                                                                                             *\n *    This routine will return a template type object back to the special heap it was          *\n *    allocated from.                                                                          *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the template type object to free.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TemplateTypeClass::operator delete(void * ptr)\n{\n\tTemplateTypes.Free((TemplateTypeClass *)ptr);\n}\n\n\nstatic void _Watcom_Ugh_Hack(void)\n{\n\t(void)new TemplateTypeClass(Road37);\t\t\t//\tTEMPLATE_ROAD37\n\t(void)new TemplateTypeClass(Road38);\t\t\t//\tTEMPLATE_ROAD38\n\t(void)new TemplateTypeClass(Road39);\t\t\t//\tTEMPLATE_ROAD39\n\t(void)new TemplateTypeClass(Road40);\t\t\t//\tTEMPLATE_ROAD40\n\t(void)new TemplateTypeClass(Road41);\t\t\t//\tTEMPLATE_ROAD41\n\t(void)new TemplateTypeClass(Road42);\t\t\t//\tTEMPLATE_ROAD42\n\t(void)new TemplateTypeClass(Road43);\t\t\t//\tTEMPLATE_ROAD43\n\t(void)new TemplateTypeClass(Rough01);\t\t\t// TEMPLATE_ROUGH01\n\t(void)new TemplateTypeClass(Rough02);\t\t\t// TEMPLATE_ROUGH02\n\t(void)new TemplateTypeClass(Rough03);\t\t\t// TEMPLATE_ROUGH03\n\t(void)new TemplateTypeClass(Rough04);\t\t\t// TEMPLATE_ROUGH04\n\t(void)new TemplateTypeClass(Rough05);\t\t\t// TEMPLATE_ROUGH05\n\t(void)new TemplateTypeClass(Rough06);\t\t\t// TEMPLATE_ROUGH06\n\t(void)new TemplateTypeClass(Rough07);\t\t\t// TEMPLATE_ROUGH07\n\t(void)new TemplateTypeClass(Rough08);\t\t\t// TEMPLATE_ROUGH08\n\t(void)new TemplateTypeClass(Rough09);\t\t\t// TEMPLATE_ROUGH09\n\t(void)new TemplateTypeClass(Rough10);\t\t\t// TEMPLATE_ROUGH10\n\t(void)new TemplateTypeClass(Rough11);\t\t\t// TEMPLATE_ROUGH11\n\t(void)new TemplateTypeClass(Road44);\t\t\t//\tTEMPLATE_ROAD44\n\t(void)new TemplateTypeClass(Road45);\t\t\t//\tTEMPLATE_ROAD45\n\t(void)new TemplateTypeClass(River14);\t\t\t//\tTEMPLATE_RIVER14\n\t(void)new TemplateTypeClass(River15);\t\t\t//\tTEMPLATE_RIVER15\n\t(void)new TemplateTypeClass(RiverCliff01);\t//\tTEMPLATE_RIVERCLIFF01\n\t(void)new TemplateTypeClass(RiverCliff02);\t//\tTEMPLATE_RIVERCLIFF02\n\t(void)new TemplateTypeClass(RiverCliff03);\t//\tTEMPLATE_RIVERCLIFF03\n\t(void)new TemplateTypeClass(RiverCliff04);\t//\tTEMPLATE_RIVERCLIFF04\n\t(void)new TemplateTypeClass(Bridge1a);\t\t\t//\tTEMPLATE_BRIDGE_1A\n\t(void)new TemplateTypeClass(Bridge1b);\t\t\t//\tTEMPLATE_BRIDGE_1B\n\t(void)new TemplateTypeClass(Bridge1c);\t\t\t//\tTEMPLATE_BRIDGE_1C\n\t(void)new TemplateTypeClass(Bridge2a);\t\t\t//\tTEMPLATE_BRIDGE_2A\n\t(void)new TemplateTypeClass(Bridge2b);\t\t\t//\tTEMPLATE_BRIDGE_2B\n\t(void)new TemplateTypeClass(Bridge2c);\t\t\t//\tTEMPLATE_BRIDGE_2C\n\t(void)new TemplateTypeClass(Bridge3a);\t\t\t//\tTEMPLATE_BRIDGE_3A\n\t(void)new TemplateTypeClass(Bridge3b);\t\t\t//\tTEMPLATE_BRIDGE_3B\n\t(void)new TemplateTypeClass(Bridge3c);\t\t\t//\tTEMPLATE_BRIDGE_3C\n\t(void)new TemplateTypeClass(Bridge3d);\t\t\t//\tTEMPLATE_BRIDGE_3D\n\t(void)new TemplateTypeClass(Bridge3e);\t\t\t//\tTEMPLATE_BRIDGE_3E\n\t(void)new TemplateTypeClass(Bridge3f);\t\t\t//\tTEMPLATE_BRIDGE_3F\n\t(void)new TemplateTypeClass(F01);\t\t\t\t//\tTEMPLATE_F01\n\t(void)new TemplateTypeClass(F02);\t\t\t\t//\tTEMPLATE_F02\n\t(void)new TemplateTypeClass(F03);\t\t\t\t//\tTEMPLATE_F03\n\t(void)new TemplateTypeClass(F04);\t\t\t\t//\tTEMPLATE_F04\n\t(void)new TemplateTypeClass(F05);\t\t\t\t//\tTEMPLATE_F05\n\t(void)new TemplateTypeClass(F06);\t\t\t\t//\tTEMPLATE_F06\n\t(void)new TemplateTypeClass(ARRO0001);\t\t\t//\tTEMPLATE_ARRO0001\n\t(void)new TemplateTypeClass(ARRO0002);\t\t\t//\tTEMPLATE_ARRO0002\n\t(void)new TemplateTypeClass(ARRO0003);\t\t\t//\tTEMPLATE_ARRO0003\n\t(void)new TemplateTypeClass(ARRO0004);\t\t\t//\tTEMPLATE_ARRO0004\n\t(void)new TemplateTypeClass(ARRO0005);\t\t\t//\tTEMPLATE_ARRO0005\n\t(void)new TemplateTypeClass(ARRO0006);\t\t\t//\tTEMPLATE_ARRO0006\n\t(void)new TemplateTypeClass(ARRO0007);\t\t\t//\tTEMPLATE_ARRO0007\n\t(void)new TemplateTypeClass(ARRO0008);\t\t\t//\tTEMPLATE_ARRO0008\n\t(void)new TemplateTypeClass(ARRO0009);\t\t\t//\tTEMPLATE_ARRO0009\n\t(void)new TemplateTypeClass(ARRO0010);\t\t\t//\tTEMPLATE_ARRO0010\n\t(void)new TemplateTypeClass(ARRO0011);\t\t\t//\tTEMPLATE_ARRO0011\n\t(void)new TemplateTypeClass(ARRO0012);\t\t\t//\tTEMPLATE_ARRO0012\n\t(void)new TemplateTypeClass(ARRO0013);\t\t\t//\tTEMPLATE_ARRO0013\n\t(void)new TemplateTypeClass(ARRO0014);\t\t\t//\tTEMPLATE_ARRO0014\n\t(void)new TemplateTypeClass(ARRO0015);\t\t\t//\tTEMPLATE_ARRO0015\n\t(void)new TemplateTypeClass(FLOR0001);\t\t\t//\tTEMPLATE_FLOR0001\n\t(void)new TemplateTypeClass(FLOR0002);\t\t\t//\tTEMPLATE_FLOR0002\n\t(void)new TemplateTypeClass(FLOR0003);\t\t\t//\tTEMPLATE_FLOR0003\n\t(void)new TemplateTypeClass(FLOR0004);\t\t\t//\tTEMPLATE_FLOR0004\n\t(void)new TemplateTypeClass(FLOR0005);\t\t\t//\tTEMPLATE_FLOR0005\n\t(void)new TemplateTypeClass(FLOR0006);\t\t\t//\tTEMPLATE_FLOR0006\n\t(void)new TemplateTypeClass(FLOR0007);\t\t\t//\tTEMPLATE_FLOR0007\n\t(void)new TemplateTypeClass(GFLR0001);\t\t\t//\tTEMPLATE_GFLR0001\n\t(void)new TemplateTypeClass(GFLR0002);\t\t\t//\tTEMPLATE_GFLR0002\n\t(void)new TemplateTypeClass(GFLR0003);\t\t\t//\tTEMPLATE_GFLR0003\n\t(void)new TemplateTypeClass(GFLR0004);\t\t\t//\tTEMPLATE_GFLR0004\n\t(void)new TemplateTypeClass(GFLR0005);\t\t\t//\tTEMPLATE_GFLR0005\n\t(void)new TemplateTypeClass(GSTR0001);\t\t\t//\tTEMPLATE_GSTR0001\n\t(void)new TemplateTypeClass(GSTR0002);\t\t\t//\tTEMPLATE_GSTR0002\n\t(void)new TemplateTypeClass(GSTR0003);\t\t\t//\tTEMPLATE_GSTR0003\n\t(void)new TemplateTypeClass(GSTR0004);\t\t\t//\tTEMPLATE_GSTR0004\n\t(void)new TemplateTypeClass(GSTR0005);\t\t\t//\tTEMPLATE_GSTR0005\n\t(void)new TemplateTypeClass(GSTR0006);\t\t\t//\tTEMPLATE_GSTR0006\n\t(void)new TemplateTypeClass(GSTR0007);\t\t\t//\tTEMPLATE_GSTR0007\n\t(void)new TemplateTypeClass(GSTR0008);\t\t\t//\tTEMPLATE_GSTR0008\n\t(void)new TemplateTypeClass(GSTR0009);\t\t\t//\tTEMPLATE_GSTR0009\n\t(void)new TemplateTypeClass(GSTR0010);\t\t\t//\tTEMPLATE_GSTR0010\n\t(void)new TemplateTypeClass(GSTR0011);\t\t\t//\tTEMPLATE_GSTR0011\n\t(void)new TemplateTypeClass(LWAL0001);\t\t\t//\tTEMPLATE_LWAL0001\n\t(void)new TemplateTypeClass(LWAL0002);\t\t\t//\tTEMPLATE_LWAL0002\n\t(void)new TemplateTypeClass(LWAL0003);\t\t\t//\tTEMPLATE_LWAL0003\n\t(void)new TemplateTypeClass(LWAL0004);\t\t\t//\tTEMPLATE_LWAL0004\n\t(void)new TemplateTypeClass(LWAL0005);\t\t\t//\tTEMPLATE_LWAL0005\n\t(void)new TemplateTypeClass(LWAL0006);\t\t\t//\tTEMPLATE_LWAL0006\n\t(void)new TemplateTypeClass(LWAL0007);\t\t\t//\tTEMPLATE_LWAL0007\n\t(void)new TemplateTypeClass(LWAL0008);\t\t\t//\tTEMPLATE_LWAL0008\n\t(void)new TemplateTypeClass(LWAL0009);\t\t\t//\tTEMPLATE_LWAL0009\n\t(void)new TemplateTypeClass(LWAL0010);\t\t\t//\tTEMPLATE_LWAL0010\n\t(void)new TemplateTypeClass(LWAL0011);\t\t\t//\tTEMPLATE_LWAL0011\n\t(void)new TemplateTypeClass(LWAL0012);\t\t\t//\tTEMPLATE_LWAL0012\n\t(void)new TemplateTypeClass(LWAL0013);\t\t\t//\tTEMPLATE_LWAL0013\n\t(void)new TemplateTypeClass(LWAL0014);\t\t\t//\tTEMPLATE_LWAL0014\n\t(void)new TemplateTypeClass(LWAL0015);\t\t\t//\tTEMPLATE_LWAL0015\n\t(void)new TemplateTypeClass(LWAL0016);\t\t\t//\tTEMPLATE_LWAL0016\n\t(void)new TemplateTypeClass(LWAL0017);\t\t\t//\tTEMPLATE_LWAL0017\n\t(void)new TemplateTypeClass(LWAL0018);\t\t\t//\tTEMPLATE_LWAL0018\n\t(void)new TemplateTypeClass(LWAL0019);\t\t\t//\tTEMPLATE_LWAL0019\n\t(void)new TemplateTypeClass(LWAL0020);\t\t\t//\tTEMPLATE_LWAL0020\n\t(void)new TemplateTypeClass(LWAL0021);\t\t\t//\tTEMPLATE_LWAL0021\n\t(void)new TemplateTypeClass(LWAL0022);\t\t\t//\tTEMPLATE_LWAL0022\n\t(void)new TemplateTypeClass(LWAL0023);\t\t\t//\tTEMPLATE_LWAL0023\n\t(void)new TemplateTypeClass(LWAL0024);\t\t\t//\tTEMPLATE_LWAL0024\n\t(void)new TemplateTypeClass(LWAL0025);\t\t\t//\tTEMPLATE_LWAL0025\n\t(void)new TemplateTypeClass(LWAL0026);\t\t\t//\tTEMPLATE_LWAL0026\n\t(void)new TemplateTypeClass(LWAL0027);\t\t\t//\tTEMPLATE_LWAL0027\n\t(void)new TemplateTypeClass(STRP0001);\t\t\t//\tTEMPLATE_STRP0001\n\t(void)new TemplateTypeClass(STRP0002);\t\t\t//\tTEMPLATE_STRP0002\n\t(void)new TemplateTypeClass(STRP0003);\t\t\t//\tTEMPLATE_STRP0003\n\t(void)new TemplateTypeClass(STRP0004);\t\t\t//\tTEMPLATE_STRP0004\n\t(void)new TemplateTypeClass(STRP0005);\t\t\t//\tTEMPLATE_STRP0005\n\t(void)new TemplateTypeClass(STRP0006);\t\t\t//\tTEMPLATE_STRP0006\n\t(void)new TemplateTypeClass(STRP0007);\t\t\t//\tTEMPLATE_STRP0007\n\t(void)new TemplateTypeClass(STRP0008);\t\t\t//\tTEMPLATE_STRP0008\n\t(void)new TemplateTypeClass(STRP0009);\t\t\t//\tTEMPLATE_STRP0009\n\t(void)new TemplateTypeClass(STRP0010);\t\t\t//\tTEMPLATE_STRP0010\n\t(void)new TemplateTypeClass(STRP0011);\t\t\t//\tTEMPLATE_STRP0011\n\t(void)new TemplateTypeClass(WALL0001);\t\t\t//\tTEMPLATE_WALL0001\n\t(void)new TemplateTypeClass(WALL0002);\t\t\t//\tTEMPLATE_WALL0002\n\t(void)new TemplateTypeClass(WALL0003);\t\t\t//\tTEMPLATE_WALL0003\n\t(void)new TemplateTypeClass(WALL0004);\t\t\t//\tTEMPLATE_WALL0004\n\t(void)new TemplateTypeClass(WALL0005);\t\t\t//\tTEMPLATE_WALL0005\n\t(void)new TemplateTypeClass(WALL0006);\t\t\t//\tTEMPLATE_WALL0006\n\t(void)new TemplateTypeClass(WALL0007);\t\t\t//\tTEMPLATE_WALL0007\n\t(void)new TemplateTypeClass(WALL0008);\t\t\t//\tTEMPLATE_WALL0008\n\t(void)new TemplateTypeClass(WALL0009);\t\t\t//\tTEMPLATE_WALL0009\n\t(void)new TemplateTypeClass(WALL0010);\t\t\t//\tTEMPLATE_WALL0010\n\t(void)new TemplateTypeClass(WALL0011);\t\t\t//\tTEMPLATE_WALL0011\n\t(void)new TemplateTypeClass(WALL0012);\t\t\t//\tTEMPLATE_WALL0012\n\t(void)new TemplateTypeClass(WALL0013);\t\t\t//\tTEMPLATE_WALL0013\n\t(void)new TemplateTypeClass(WALL0014);\t\t\t//\tTEMPLATE_WALL0014\n\t(void)new TemplateTypeClass(WALL0015);\t\t\t//\tTEMPLATE_WALL0015\n\t(void)new TemplateTypeClass(WALL0016);\t\t\t//\tTEMPLATE_WALL0016\n\t(void)new TemplateTypeClass(WALL0017);\t\t\t//\tTEMPLATE_WALL0017\n\t(void)new TemplateTypeClass(WALL0018);\t\t\t//\tTEMPLATE_WALL0018\n\t(void)new TemplateTypeClass(WALL0019);\t\t\t//\tTEMPLATE_WALL0019\n\t(void)new TemplateTypeClass(WALL0020);\t\t\t//\tTEMPLATE_WALL0020\n\t(void)new TemplateTypeClass(WALL0021);\t\t\t//\tTEMPLATE_WALL0021\n\t(void)new TemplateTypeClass(WALL0022);\t\t\t//\tTEMPLATE_WALL0022\n\t(void)new TemplateTypeClass(WALL0023);\t\t\t//\tTEMPLATE_WALL0023\n\t(void)new TemplateTypeClass(WALL0024);\t\t\t//\tTEMPLATE_WALL0024\n\t(void)new TemplateTypeClass(WALL0025);\t\t\t//\tTEMPLATE_WALL0025\n\t(void)new TemplateTypeClass(WALL0026);\t\t\t//\tTEMPLATE_WALL0026\n\t(void)new TemplateTypeClass(WALL0027);\t\t\t//\tTEMPLATE_WALL0027\n\t(void)new TemplateTypeClass(WALL0028);\t\t\t//\tTEMPLATE_WALL0028\n\t(void)new TemplateTypeClass(WALL0029);\t\t\t//\tTEMPLATE_WALL0029\n\t(void)new TemplateTypeClass(WALL0030);\t\t\t//\tTEMPLATE_WALL0030\n\t(void)new TemplateTypeClass(WALL0031);\t\t\t//\tTEMPLATE_WALL0031\n\t(void)new TemplateTypeClass(WALL0032);\t\t\t//\tTEMPLATE_WALL0032\n\t(void)new TemplateTypeClass(WALL0033);\t\t\t//\tTEMPLATE_WALL0033\n\t(void)new TemplateTypeClass(WALL0034);\t\t\t//\tTEMPLATE_WALL0034\n\t(void)new TemplateTypeClass(WALL0035);\t\t\t//\tTEMPLATE_WALL0035\n\t(void)new TemplateTypeClass(WALL0036);\t\t\t//\tTEMPLATE_WALL0036\n\t(void)new TemplateTypeClass(WALL0037);\t\t\t//\tTEMPLATE_WALL0037\n\t(void)new TemplateTypeClass(WALL0038);\t\t\t//\tTEMPLATE_WALL0038\n\t(void)new TemplateTypeClass(WALL0039);\t\t\t//\tTEMPLATE_WALL0039\n\t(void)new TemplateTypeClass(WALL0040);\t\t\t//\tTEMPLATE_WALL0040\n\t(void)new TemplateTypeClass(WALL0041);\t\t\t//\tTEMPLATE_WALL0041\n\t(void)new TemplateTypeClass(WALL0042);\t\t\t//\tTEMPLATE_WALL0042\n\t(void)new TemplateTypeClass(WALL0043);\t\t\t//\tTEMPLATE_WALL0043\n\t(void)new TemplateTypeClass(WALL0044);\t\t\t//\tTEMPLATE_WALL0044\n\t(void)new TemplateTypeClass(WALL0045);\t\t\t//\tTEMPLATE_WALL0045\n\t(void)new TemplateTypeClass(WALL0046);\t\t\t//\tTEMPLATE_WALL0046\n\t(void)new TemplateTypeClass(WALL0047);\t\t\t//\tTEMPLATE_WALL0047\n\t(void)new TemplateTypeClass(WALL0048);\t\t\t//\tTEMPLATE_WALL0048\n\t(void)new TemplateTypeClass(WALL0049);\t\t\t//\tTEMPLATE_WALL0049\n\t(void)new TemplateTypeClass(Bridge1h);\t\t\t//\tTEMPLATE_BRIDGE1H\n\t(void)new TemplateTypeClass(Bridge2h);\t\t\t//\tTEMPLATE_BRIDGE2H\n\n\t(void)new TemplateTypeClass(Bridge1ax);\t\t//\tTEMPLATE_BRIDGE_1AX\n\t(void)new TemplateTypeClass(Bridge2ax);\t\t//\tTEMPLATE_BRIDGE_2AX\n\t(void)new TemplateTypeClass(Bridge1x);\t\t\t//\tTEMPLATE_BRIDGE1X\n\t(void)new TemplateTypeClass(Bridge2x);\t\t\t//\tTEMPLATE_BRIDGE2X\n\n\t(void)new TemplateTypeClass(Xtra0001);\t\t\t//\tTEMPLATE_XTRA0001\n\t(void)new TemplateTypeClass(Xtra0002);\t\t\t//\tTEMPLATE_XTRA0002\n\t(void)new TemplateTypeClass(Xtra0003);\t\t\t//\tTEMPLATE_XTRA0003\n\t(void)new TemplateTypeClass(Xtra0004);\t\t\t//\tTEMPLATE_XTRA0004\n\t(void)new TemplateTypeClass(Xtra0005);\t\t\t//\tTEMPLATE_XTRA0005\n\t(void)new TemplateTypeClass(Xtra0006);\t\t\t//\tTEMPLATE_XTRA0006\n\t(void)new TemplateTypeClass(Xtra0007);\t\t\t//\tTEMPLATE_XTRA0007\n\t(void)new TemplateTypeClass(Xtra0008);\t\t\t//\tTEMPLATE_XTRA0008\n\t(void)new TemplateTypeClass(Xtra0009);\t\t\t//\tTEMPLATE_XTRA0009\n\t(void)new TemplateTypeClass(Xtra0010);\t\t\t//\tTEMPLATE_XTRA0010\n\t(void)new TemplateTypeClass(Xtra0011);\t\t\t//\tTEMPLATE_XTRA0011\n\t(void)new TemplateTypeClass(Xtra0012);\t\t\t//\tTEMPLATE_XTRA0012\n\t(void)new TemplateTypeClass(Xtra0013);\t\t\t//\tTEMPLATE_XTRA0013\n\t(void)new TemplateTypeClass(Xtra0014);\t\t\t//\tTEMPLATE_XTRA0014\n\t(void)new TemplateTypeClass(Xtra0015);\t\t\t//\tTEMPLATE_XTRA0015\n\t(void)new TemplateTypeClass(Xtra0016);\t\t\t//\tTEMPLATE_XTRA0016\n\n#ifdef FIXIT_ANTS\n\t(void)new TemplateTypeClass(AntHill);\t\t\t//\tTEMPLATE_ROAD36\n#endif\n}\n\n\n\nvoid TemplateTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese template type class objects must be allocated in the exact order that they\n\t**\tare specified in the TemplateType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\t(void)new TemplateTypeClass(Clear);\t\t\t\t// TEMPLATE_CLEAR1\n\t(void)new TemplateTypeClass(Water);\t\t\t\t// TEMPLATE_WATER\n\t(void)new TemplateTypeClass(Water2);\t\t\t// TEMPLATE_WATER2\n\t(void)new TemplateTypeClass(Shore01);\t\t\t// TEMPLATE_SHORE1\n\t(void)new TemplateTypeClass(Shore02);\t\t\t// TEMPLATE_SHORE2\n\t(void)new TemplateTypeClass(Shore03);\t\t\t// TEMPLATE_SHORE3\n\t(void)new TemplateTypeClass(Shore04);\t\t\t// TEMPLATE_SHORE4\n\t(void)new TemplateTypeClass(Shore05);\t\t\t// TEMPLATE_SHORE5\n\t(void)new TemplateTypeClass(Shore06);\t\t\t// TEMPLATE_SHORE6\n\t(void)new TemplateTypeClass(Shore07);\t\t\t// TEMPLATE_SHORE7\n\t(void)new TemplateTypeClass(Shore08);\t\t\t// TEMPLATE_SHORE8\n\t(void)new TemplateTypeClass(Shore09);\t\t\t// TEMPLATE_SHORE9\n\t(void)new TemplateTypeClass(Shore10);\t\t\t// TEMPLATE_SHORE10\n\t(void)new TemplateTypeClass(Shore11);\t\t\t//\tTEMPLATE_SHORE11\n\t(void)new TemplateTypeClass(Shore12);\t\t\t// TEMPLATE_SHORE12\n\t(void)new TemplateTypeClass(Shore13);\t\t\t// TEMPLATE_SHORE13\n\t(void)new TemplateTypeClass(Shore14);\t\t\t// TEMPLATE_SHORE14\n\t(void)new TemplateTypeClass(Shore15);\t\t\t// TEMPLATE_SHORE15\n\t(void)new TemplateTypeClass(Shore16);\t\t\t//\tTEMPLATE_SHORE16\n\t(void)new TemplateTypeClass(Shore17);\t\t\t//\tTEMPLATE_SHORE17\n\t(void)new TemplateTypeClass(Shore18);\t\t\t//\tTEMPLATE_SHORE18\n\t(void)new TemplateTypeClass(Shore19);\t\t\t// TEMPLATE_SHORE19\n\t(void)new TemplateTypeClass(Shore20);\t\t\t// TEMPLATE_SHORE20\n\t(void)new TemplateTypeClass(Shore21);\t\t\t// TEMPLATE_SHORE21\n\t(void)new TemplateTypeClass(Shore22);\t\t\t//\tTEMPLATE_SHORE22\n\t(void)new TemplateTypeClass(Shore23);\t\t\t// TEMPLATE_SHORE23\n\t(void)new TemplateTypeClass(Shore24);\t\t\t//\tTEMPLATE_SHORE24\n\t(void)new TemplateTypeClass(Shore25);\t\t\t//\tTEMPLATE_SHORE25\n\t(void)new TemplateTypeClass(Shore26);\t\t\t//\tTEMPLATE_SHORE26\n\t(void)new TemplateTypeClass(Shore27);\t\t\t//\tTEMPLATE_SHORE27\n\t(void)new TemplateTypeClass(Shore28);\t\t\t//\tTEMPLATE_SHORE28\n\t(void)new TemplateTypeClass(Shore29);\t\t\t//\tTEMPLATE_SHORE29\n\t(void)new TemplateTypeClass(Shore30);\t\t\t//\tTEMPLATE_SHORE30\n\t(void)new TemplateTypeClass(Shore31);\t\t\t//\tTEMPLATE_SHORE31\n\t(void)new TemplateTypeClass(Shore32);\t\t\t// TEMPLATE_SHORE32\n\t(void)new TemplateTypeClass(Shore33);\t\t\t// TEMPLATE_SHORE33\n\t(void)new TemplateTypeClass(Shore34);\t\t\t//\tTEMPLATE_SHORE34\n\t(void)new TemplateTypeClass(Shore35);\t\t\t//\tTEMPLATE_SHORE35\n\t(void)new TemplateTypeClass(Shore36);\t\t\t//\tTEMPLATE_SHORE36\n\t(void)new TemplateTypeClass(Shore37);\t\t\t//\tTEMPLATE_SHORE37\n\t(void)new TemplateTypeClass(Shore38);\t\t\t//\tTEMPLATE_SHORE38\n\t(void)new TemplateTypeClass(Shore39);\t\t\t//\tTEMPLATE_SHORE39\n\t(void)new TemplateTypeClass(Shore40);\t\t\t//\tTEMPLATE_SHORE40\n\t(void)new TemplateTypeClass(Shore41);\t\t\t//\tTEMPLATE_SHORE41\n\t(void)new TemplateTypeClass(Shore42);\t\t\t//\tTEMPLATE_SHORE42\n\t(void)new TemplateTypeClass(Shore43);\t\t\t//\tTEMPLATE_SHORE43\n\t(void)new TemplateTypeClass(Shore44);\t\t\t//\tTEMPLATE_SHORE44\n\t(void)new TemplateTypeClass(Shore45);\t\t\t//\tTEMPLATE_SHORE45\n\t(void)new TemplateTypeClass(Shore46);\t\t\t//\tTEMPLATE_SHORE46\n\t(void)new TemplateTypeClass(Shore47);\t\t\t//\tTEMPLATE_SHORE47\n\t(void)new TemplateTypeClass(Shore48);\t\t\t//\tTEMPLATE_SHORE48\n\t(void)new TemplateTypeClass(Shore49);\t\t\t//\tTEMPLATE_SHORE49\n\t(void)new TemplateTypeClass(Shore50);\t\t\t//\tTEMPLATE_SHORE50\n\t(void)new TemplateTypeClass(Shore51);\t\t\t//\tTEMPLATE_SHORE51\n\t(void)new TemplateTypeClass(Shore52);\t\t\t//\tTEMPLATE_SHORE52\n\t(void)new TemplateTypeClass(Shore53);\t\t\t//\tTEMPLATE_SHORE53\n\t(void)new TemplateTypeClass(Shore54);\t\t\t//\tTEMPLATE_SHORE54\n\t(void)new TemplateTypeClass(Shore55);\t\t\t//\tTEMPLATE_SHORE55\n\t(void)new TemplateTypeClass(Shore56);\t\t\t//\tTEMPLATE_SHORE56\n\t(void)new TemplateTypeClass(ShoreCliff01);\t//\tTEMPLATE_SHORECLIFF01\n\t(void)new TemplateTypeClass(ShoreCliff02);\t//\tTEMPLATE_SHORECLIFF02\n\t(void)new TemplateTypeClass(ShoreCliff03);\t//\tTEMPLATE_SHORECLIFF03\n\t(void)new TemplateTypeClass(ShoreCliff04);\t//\tTEMPLATE_SHORECLIFF04\n\t(void)new TemplateTypeClass(ShoreCliff05);\t//\tTEMPLATE_SHORECLIFF05\n\t(void)new TemplateTypeClass(ShoreCliff06);\t//\tTEMPLATE_SHORECLIFF06\n\t(void)new TemplateTypeClass(ShoreCliff07);\t//\tTEMPLATE_SHORECLIFF07\n\t(void)new TemplateTypeClass(ShoreCliff08);\t//\tTEMPLATE_SHORECLIFF08\n\t(void)new TemplateTypeClass(ShoreCliff09);\t//\tTEMPLATE_SHORECLIFF09\n\t(void)new TemplateTypeClass(ShoreCliff10);\t//\tTEMPLATE_SHORECLIFF10\n\t(void)new TemplateTypeClass(ShoreCliff11);\t//\tTEMPLATE_SHORECLIFF11\n\t(void)new TemplateTypeClass(ShoreCliff12);\t//\tTEMPLATE_SHORECLIFF12\n\t(void)new TemplateTypeClass(ShoreCliff13);\t//\tTEMPLATE_SHORECLIFF13\n\t(void)new TemplateTypeClass(ShoreCliff14);\t//\tTEMPLATE_SHORECLIFF14\n\t(void)new TemplateTypeClass(ShoreCliff15);\t//\tTEMPLATE_SHORECLIFF15\n\t(void)new TemplateTypeClass(ShoreCliff16);\t//\tTEMPLATE_SHORECLIFF16\n\t(void)new TemplateTypeClass(ShoreCliff17);\t//\tTEMPLATE_SHORECLIFF17\n\t(void)new TemplateTypeClass(ShoreCliff18);\t//\tTEMPLATE_SHORECLIFF18\n\t(void)new TemplateTypeClass(ShoreCliff19);\t//\tTEMPLATE_SHORECLIFF19\n\t(void)new TemplateTypeClass(ShoreCliff20);\t//\tTEMPLATE_SHORECLIFF20\n\t(void)new TemplateTypeClass(ShoreCliff21);\t//\tTEMPLATE_SHORECLIFF21\n\t(void)new TemplateTypeClass(ShoreCliff22);\t//\tTEMPLATE_SHORECLIFF22\n\t(void)new TemplateTypeClass(ShoreCliff23);\t//\tTEMPLATE_SHORECLIFF23\n\t(void)new TemplateTypeClass(ShoreCliff24);\t//\tTEMPLATE_SHORECLIFF24\n\t(void)new TemplateTypeClass(ShoreCliff25);\t//\tTEMPLATE_SHORECLIFF25\n\t(void)new TemplateTypeClass(ShoreCliff26);\t//\tTEMPLATE_SHORECLIFF26\n\t(void)new TemplateTypeClass(ShoreCliff27);\t//\tTEMPLATE_SHORECLIFF27\n\t(void)new TemplateTypeClass(ShoreCliff28);\t//\tTEMPLATE_SHORECLIFF28\n\t(void)new TemplateTypeClass(ShoreCliff29);\t//\tTEMPLATE_SHORECLIFF29\n\t(void)new TemplateTypeClass(ShoreCliff30);\t//\tTEMPLATE_SHORECLIFF30\n\t(void)new TemplateTypeClass(ShoreCliff31);\t//\tTEMPLATE_SHORECLIFF31\n\t(void)new TemplateTypeClass(ShoreCliff32);\t//\tTEMPLATE_SHORECLIFF32\n\t(void)new TemplateTypeClass(ShoreCliff33);\t//\tTEMPLATE_SHORECLIFF33\n\t(void)new TemplateTypeClass(ShoreCliff34);\t//\tTEMPLATE_SHORECLIFF34\n\t(void)new TemplateTypeClass(ShoreCliff35);\t//\tTEMPLATE_SHORECLIFF35\n\t(void)new TemplateTypeClass(ShoreCliff36);\t//\tTEMPLATE_SHORECLIFF36\n\t(void)new TemplateTypeClass(ShoreCliff37);\t//\tTEMPLATE_SHORECLIFF37\n\t(void)new TemplateTypeClass(ShoreCliff38);\t//\tTEMPLATE_SHORECLIFF38\n\t(void)new TemplateTypeClass(Boulder1);\t\t\t//\tTEMPLATE_BOULDER1\n\t(void)new TemplateTypeClass(Boulder2);\t\t\t//\tTEMPLATE_BOULDER2\n\t(void)new TemplateTypeClass(Boulder3);\t\t\t//\tTEMPLATE_BOULDER3\n\t(void)new TemplateTypeClass(Boulder4);\t\t\t// TEMPLATE_BOULDER4\n\t(void)new TemplateTypeClass(Boulder5);\t\t\t//\tTEMPLATE_BOULDER5\n\t(void)new TemplateTypeClass(Boulder6);\t\t\t//\tTEMPLATE_BOULDER6\n\t(void)new TemplateTypeClass(Patch01);\t\t\t//\tTEMPLATE_PATCH1\n\t(void)new TemplateTypeClass(Patch02);\t\t\t//\tTEMPLATE_PATCH2\n\t(void)new TemplateTypeClass(Patch03);\t\t\t//\tTEMPLATE_PATCH3\n\t(void)new TemplateTypeClass(Patch04);\t\t\t//\tTEMPLATE_PATCH4\n\t(void)new TemplateTypeClass(Patch07);\t\t\t//\tTEMPLATE_PATCH7\n\t(void)new TemplateTypeClass(Patch08);\t\t\t//\tTEMPLATE_PATCH8\n\t(void)new TemplateTypeClass(Patch13);\t\t\t//\tTEMPLATE_PATCH13\n\t(void)new TemplateTypeClass(Patch14);\t\t\t//\tTEMPLATE_PATCH14\n\t(void)new TemplateTypeClass(Patch15);\t\t\t//\tTEMPLATE_PATCH15\n\t(void)new TemplateTypeClass(River01);\t\t\t//\tTEMPLATE_RIVER1\n\t(void)new TemplateTypeClass(River02);\t\t\t//\tTEMPLATE_RIVER2\n\t(void)new TemplateTypeClass(River03);\t\t\t//\tTEMPLATE_RIVER3\n\t(void)new TemplateTypeClass(River04);\t\t\t//\tTEMPLATE_RIVER4\n\t(void)new TemplateTypeClass(River05);\t\t\t//\tTEMPLATE_RIVER5\n\t(void)new TemplateTypeClass(River06);\t\t\t//\tTEMPLATE_RIVER6\n\t(void)new TemplateTypeClass(River07);\t\t\t//\tTEMPLATE_RIVER7\n\t(void)new TemplateTypeClass(River08);\t\t\t//\tTEMPLATE_RIVER8\n\t(void)new TemplateTypeClass(River09);\t\t\t//\tTEMPLATE_RIVER9\n\t(void)new TemplateTypeClass(River10);\t\t\t//\tTEMPLATE_RIVER10\n\t(void)new TemplateTypeClass(River11);\t\t\t//\tTEMPLATE_RIVER11\n\t(void)new TemplateTypeClass(River12);\t\t\t//\tTEMPLATE_RIVER12\n\t(void)new TemplateTypeClass(River13);\t\t\t//\tTEMPLATE_RIVER13\n\t(void)new TemplateTypeClass(Falls1);\t\t\t//\tTEMPLATE_FALLS1\n\t(void)new TemplateTypeClass(Falls1a);\t\t\t//\tTEMPLATE_FALLS1A\n\t(void)new TemplateTypeClass(Falls2);\t\t\t//\tTEMPLATE_FALLS2\n\t(void)new TemplateTypeClass(Falls2a);\t\t\t//\tTEMPLATE_FALLS2A\n\t(void)new TemplateTypeClass(Ford1);\t\t\t\t//\tTEMPLATE_FORD1\n\t(void)new TemplateTypeClass(Ford2);\t\t\t\t//\tTEMPLATE_FORD2\n\t(void)new TemplateTypeClass(Bridge1);\t\t\t//\tTEMPLATE_BRIDGE1\n\t(void)new TemplateTypeClass(Bridge1d);\t\t\t//\tTEMPLATE_BRIDGE1D\n\t(void)new TemplateTypeClass(Bridge2);\t\t\t//\tTEMPLATE_BRIDGE2\n\t(void)new TemplateTypeClass(Bridge2d);\t\t\t//\tTEMPLATE_BRIDGE2D\n\t(void)new TemplateTypeClass(Slope01);\t\t\t//\tTEMPLATE_SLOPE1\n\t(void)new TemplateTypeClass(Slope02);\t\t\t//\tTEMPLATE_SLOPE2\n\t(void)new TemplateTypeClass(Slope03);\t\t\t//\tTEMPLATE_SLOPE3\n\t(void)new TemplateTypeClass(Slope04);\t\t\t//\tTEMPLATE_SLOPE4\n\t(void)new TemplateTypeClass(Slope05);\t\t\t//\tTEMPLATE_SLOPE5\n\t(void)new TemplateTypeClass(Slope06);\t\t\t//\tTEMPLATE_SLOPE6\n\t(void)new TemplateTypeClass(Slope07);\t\t\t//\tTEMPLATE_SLOPE7\n\t(void)new TemplateTypeClass(Slope08);\t\t\t//\tTEMPLATE_SLOPE8\n\t(void)new TemplateTypeClass(Slope09);\t\t\t//\tTEMPLATE_SLOPE9\n\t(void)new TemplateTypeClass(Slope10);\t\t\t//\tTEMPLATE_SLOPE10\n\t(void)new TemplateTypeClass(Slope11);\t\t\t//\tTEMPLATE_SLOPE11\n\t(void)new TemplateTypeClass(Slope12);\t\t\t//\tTEMPLATE_SLOPE12\n\t(void)new TemplateTypeClass(Slope13);\t\t\t//\tTEMPLATE_SLOPE13\n\t(void)new TemplateTypeClass(Slope14);\t\t\t//\tTEMPLATE_SLOPE14\n\t(void)new TemplateTypeClass(Slope15);\t\t\t//\tTEMPLATE_SLOPE15\n\t(void)new TemplateTypeClass(Slope16);\t\t\t//\tTEMPLATE_SLOPE16\n\t(void)new TemplateTypeClass(Slope17);\t\t\t//\tTEMPLATE_SLOPE17\n\t(void)new TemplateTypeClass(Slope18);\t\t\t//\tTEMPLATE_SLOPE18\n\t(void)new TemplateTypeClass(Slope19);\t\t\t//\tTEMPLATE_SLOPE19\n\t(void)new TemplateTypeClass(Slope20);\t\t\t//\tTEMPLATE_SLOPE20\n\t(void)new TemplateTypeClass(Slope21);\t\t\t//\tTEMPLATE_SLOPE21\n\t(void)new TemplateTypeClass(Slope22);\t\t\t//\tTEMPLATE_SLOPE22\n\t(void)new TemplateTypeClass(Slope23);\t\t\t//\tTEMPLATE_SLOPE23\n\t(void)new TemplateTypeClass(Slope24);\t\t\t//\tTEMPLATE_SLOPE24\n\t(void)new TemplateTypeClass(Slope25);\t\t\t//\tTEMPLATE_SLOPE25\n\t(void)new TemplateTypeClass(Slope26);\t\t\t//\tTEMPLATE_SLOPE26\n\t(void)new TemplateTypeClass(Slope27);\t\t\t//\tTEMPLATE_SLOPE27\n\t(void)new TemplateTypeClass(Slope28);\t\t\t//\tTEMPLATE_SLOPE28\n\t(void)new TemplateTypeClass(Slope29);\t\t\t//\tTEMPLATE_SLOPE29\n\t(void)new TemplateTypeClass(Slope30);\t\t\t//\tTEMPLATE_SLOPE30\n\t(void)new TemplateTypeClass(Slope31);\t\t\t//\tTEMPLATE_SLOPE31\n\t(void)new TemplateTypeClass(Slope32);\t\t\t//\tTEMPLATE_SLOPE32\n\t(void)new TemplateTypeClass(Slope33);\t\t\t//\tTEMPLATE_SLOPE33\n\t(void)new TemplateTypeClass(Slope34);\t\t\t//\tTEMPLATE_SLOPE34\n\t(void)new TemplateTypeClass(Slope35);\t\t\t//\tTEMPLATE_SLOPE35\n\t(void)new TemplateTypeClass(Slope36);\t\t\t//\tTEMPLATE_SLOPE36\n\t(void)new TemplateTypeClass(Slope37);\t\t\t//\tTEMPLATE_SLOPE37\n\t(void)new TemplateTypeClass(Slope38);\t\t\t//\tTEMPLATE_SLOPE38\n\t(void)new TemplateTypeClass(Road01);\t\t\t//\tTEMPLATE_ROAD1\n\t(void)new TemplateTypeClass(Road02);\t\t\t//\tTEMPLATE_ROAD2\n\t(void)new TemplateTypeClass(Road03);\t\t\t//\tTEMPLATE_ROAD3\n\t(void)new TemplateTypeClass(Road04);\t\t\t//\tTEMPLATE_ROAD4\n\t(void)new TemplateTypeClass(Road05);\t\t\t//\tTEMPLATE_ROAD5\n\t(void)new TemplateTypeClass(Road06);\t\t\t//\tTEMPLATE_ROAD6\n\t(void)new TemplateTypeClass(Road07);\t\t\t//\tTEMPLATE_ROAD7\n\t(void)new TemplateTypeClass(Road08);\t\t\t//\tTEMPLATE_ROAD8\n\t(void)new TemplateTypeClass(Road09);\t\t\t//\tTEMPLATE_ROAD9\n\t(void)new TemplateTypeClass(Road10);\t\t\t//\tTEMPLATE_ROAD10\n\t(void)new TemplateTypeClass(Road11);\t\t\t//\tTEMPLATE_ROAD11\n\t(void)new TemplateTypeClass(Road12);\t\t\t//\tTEMPLATE_ROAD12\n\t(void)new TemplateTypeClass(Road13);\t\t\t//\tTEMPLATE_ROAD13\n\t(void)new TemplateTypeClass(Road14);\t\t\t//\tTEMPLATE_ROAD14\n\t(void)new TemplateTypeClass(Road15);\t\t\t//\tTEMPLATE_ROAD15\n\t(void)new TemplateTypeClass(Road16);\t\t\t//\tTEMPLATE_ROAD16\n\t(void)new TemplateTypeClass(Road17);\t\t\t//\tTEMPLATE_ROAD17\n\t(void)new TemplateTypeClass(Road18);\t\t\t//\tTEMPLATE_ROAD18\n\t(void)new TemplateTypeClass(Road19);\t\t\t//\tTEMPLATE_ROAD19\n\t(void)new TemplateTypeClass(Road20);\t\t\t//\tTEMPLATE_ROAD20\n\t(void)new TemplateTypeClass(Road21);\t\t\t//\tTEMPLATE_ROAD21\n\t(void)new TemplateTypeClass(Road22);\t\t\t//\tTEMPLATE_ROAD22\n\t(void)new TemplateTypeClass(Road23);\t\t\t//\tTEMPLATE_ROAD23\n\t(void)new TemplateTypeClass(Road24);\t\t\t//\tTEMPLATE_ROAD24\n\t(void)new TemplateTypeClass(Road25);\t\t\t//\tTEMPLATE_ROAD25\n\t(void)new TemplateTypeClass(Road26);\t\t\t//\tTEMPLATE_ROAD26\n\t(void)new TemplateTypeClass(Road27);\t\t\t//\tTEMPLATE_ROAD27\n\t(void)new TemplateTypeClass(Road28);\t\t\t//\tTEMPLATE_ROAD28\n\t(void)new TemplateTypeClass(Road29);\t\t\t//\tTEMPLATE_ROAD29\n\t(void)new TemplateTypeClass(Road30);\t\t\t//\tTEMPLATE_ROAD30\n\t(void)new TemplateTypeClass(Road31);\t\t\t//\tTEMPLATE_ROAD31\n\t(void)new TemplateTypeClass(Road32);\t\t\t//\tTEMPLATE_ROAD32\n\t(void)new TemplateTypeClass(Road33);\t\t\t//\tTEMPLATE_ROAD33\n\t(void)new TemplateTypeClass(Road34);\t\t\t//\tTEMPLATE_ROAD34\n\t(void)new TemplateTypeClass(Road35);\t\t\t//\tTEMPLATE_ROAD35\n\t(void)new TemplateTypeClass(Road36);\t\t\t//\tTEMPLATE_ROAD36\n\n\t/*\n\t**\tSeparate out the list of new operator calls. Watcom bombs\n\t**\tif they are kept together.\n\t*/\n\t_Watcom_Ugh_Hack();\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::Land_Type -- Determines land type from template and icon number.         *\n *                                                                                             *\n *    This routine will convert the specified icon number into the appropriate land type. The  *\n *    land type can be determined from the embedded colors in the \"control template\" section   *\n *    of the original art file. This control information is encoded into the icon data file    *\n *    to be retrieved and interpreted as the program sees fit. The engine only recognizes      *\n *    the first 16 colors as control colors, so the control map color value serves as an       *\n *    index into a simple lookup table.                                                        *\n *                                                                                             *\n * INPUT:   icon  -- The icon number within this template that is to be examined and used      *\n *                   to determine the land type.                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the land type that corresponds to the icon number specified.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/12/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLandType TemplateTypeClass::Land_Type(int icon) const\n{\n\tIconsetClass const * icontrol = (IconsetClass const *)Get_Image_Data();\n\n\tif (icontrol != NULL) {\n\t\tunsigned char const * map = icontrol->Control_Map();\n\t\tif (map != NULL) {\n\t\t\tstatic LandType _land[16] = {\n\t\t\t\tLAND_CLEAR,\n\t\t\t\tLAND_CLEAR,\n\t\t\t\tLAND_CLEAR,\n\t\t\t\tLAND_CLEAR,\t\t\t// Clear\n\t\t\t\tLAND_CLEAR,\n\t\t\t\tLAND_CLEAR,\n\t\t\t\tLAND_BEACH,\t\t\t// Beach\n\t\t\t\tLAND_CLEAR,\n\t\t\t\tLAND_ROCK,\t\t\t// Rock\n\t\t\t\tLAND_ROAD,\t\t\t// Road\n\t\t\t\tLAND_WATER,\t\t\t// Water\n\t\t\t\tLAND_RIVER,\t\t\t//\tRiver\n\t\t\t\tLAND_CLEAR,\n\t\t\t\tLAND_CLEAR,\n\t\t\t\tLAND_ROUGH,\t\t\t// Rough\n\t\t\t\tLAND_CLEAR,\n\t\t\t};\n\n\t\t\treturn(_land[map[icon % (icontrol->Map_Width() * icontrol->Map_Height())]]);\n\t\t}\n\t}\n\treturn(LAND_CLEAR);\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::From_Name -- Determine template from ASCII name.                         *\n *                                                                                             *\n *    This routine is used to determine the template number given only                         *\n *    an ASCII representation. The scenario loader uses this routine                           *\n *    to construct the map from the INI control file.                                          *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the ASCII name of the template.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the template number. If the name had no match,                        *\n *          then returns with TEMPLATE_NONE.                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTemplateType TemplateTypeClass::From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (TemplateType index = TEMPLATE_FIRST; index < TEMPLATE_COUNT; index++) {\n\t\t\tif (stricmp(As_Reference(index).IniName, name) == 0) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t}\n\t}\n\treturn(TEMPLATE_NONE);\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::Occupy_List -- Determines occupation list.                               *\n *                                                                                             *\n *    This routine is used to examine the template map and build an                            *\n *    occupation list. This list is used to render a template cursor as                        *\n *    well as placement of icon numbers.                                                       *\n *                                                                                             *\n * INPUT:   placement   -- Is this for placement legality checking only? The normal condition  *\n *                         is for marking occupation flags.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the template occupation list.                            *\n *                                                                                             *\n * WARNINGS:   The return pointer is valid only until the next time that                       *\n *             this routine is called.                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *   12/12/1995 JLB : Optimized for direct access to iconset data.                             *\n *=============================================================================================*/\nshort const * TemplateTypeClass::Occupy_List(bool) const\n{\n\tstatic short _occupy[13*8+5];\n\tshort\t* ptr;\n\n\tIconsetClass const * iconset = (IconsetClass const *)Get_Image_Data();\n\tunsigned char const * map = iconset->Map_Data();\n\n\tptr = &_occupy[0];\n\tfor (int index = 0; index < Width * Height; index++) {\n\t\tif (*map++ != 0xFF) {\n\t\t\t*ptr++ = (index % Width) + ((index / Width)*MAP_CELL_W);\n\t\t}\n\t}\n\t*ptr = REFRESH_EOL;\n\n\treturn((short const *)&_occupy[0]);\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::Init -- Loads graphic data for templates.                                *\n *                                                                                             *\n *    This routine loads the template graphic data for all the template                        *\n *    type supported for the specified theater. This routine is called                         *\n *    whenever the theater for the scenario is first determined.                               *\n *                                                                                             *\n * INPUT:   theater  -- The theater that the template data is to be                            *\n *                      loaded for.                                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine goes to disk!                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *   06/02/1994 JLB : Only handles iconset loading now (as it should).                         *\n *=============================================================================================*/\nvoid TemplateTypeClass::Init(TheaterType theater)\n{\n\tchar fullname[_MAX_FNAME+_MAX_EXT];\t// Fully constructed iconset name.\n\tvoid const * ptr;\t\t// Working loaded iconset pointer.\n\n\tfor (TemplateType index = TEMPLATE_FIRST; index < TEMPLATE_COUNT; index++) {\n\t\tTemplateTypeClass\tconst & tplate = As_Reference(index);\n\n\t\t((void const *&)tplate.ImageData) = NULL;\n\t\tif (tplate.Theater & (1<<theater)) {\n\t\t\t_makepath(fullname, NULL, NULL, tplate.IniName, Theaters[theater].Suffix);\n\t\t\tptr = MFCD::Retrieve(fullname);\n\t\t\t((void const *&)tplate.ImageData) = ptr;\n\n#ifdef WIN32\n\t\t\tRegister_Icon_Set((void*)ptr, TRUE);\t\t//Register icon set for video memory caching\n#endif\n\n\t\t\t((unsigned char &)tplate.Width) = Get_IconSet_MapWidth(ptr);\n\t\t\t((unsigned char &)tplate.Height) = Get_IconSet_MapHeight(ptr);\n\t\t}\n\t}\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***********************************************************************************************\n * TemplateTypeClass::Display -- Displays a generic representation of template.                *\n *                                                                                             *\n *    This routine is used to display a generic view of the template                           *\n *    object. This is necessary for selection in the scenario editor.                          *\n *                                                                                             *\n * INPUT:   x,y   -- The coordinates to center the display about.                              *\n *                                                                                             *\n *          window-- The window to base the coordinates upon.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TemplateTypeClass::Display(int x, int y, WindowNumberType window, HousesType ) const\n{\n\tint\tw,h;\n\tint\tindex;\n\tbool\tscale;\t\t// Should the template be half sized?\n\n\tw = Bound(Width, 1, 13);\n\th = Bound(Height, 1, 8);\n\tscale = (w > 3 || h > 3);\n\tif (scale) {\n\t\tx -= (w * ICON_PIXEL_W) / 4;\n\t\ty -= (h * ICON_PIXEL_H) / 4;\n\t} else {\n\t\tx -= (w * ICON_PIXEL_W) / 2;\n\t\ty -= (h * ICON_PIXEL_H) / 2;\n\t}\n\tx += WindowList[window][WINDOWX];\n\ty += WindowList[window][WINDOWY];\n\n\tIconsetClass const * iconset = (IconsetClass const *)Get_Image_Data();\n\tunsigned char const * map = iconset->Map_Data();\n\n\tfor (index = 0; index < w*h; index++) {\n\t\tif (map[index] != 0xFF) {\n\t\t\tHidPage.Draw_Stamp(iconset, index, 0, 0, NULL, WINDOW_MAIN);\n\t\t\tif (scale) {\n\n\t\t\t\tHidPage.Scale((*LogicPage), 0, 0,\n\t\t\t\t\tx + ((index % w)*(ICON_PIXEL_W/2)),\n\t\t\t\t\ty + ((index / w)*(ICON_PIXEL_H/2)),\n\t\t\t\t\tICON_PIXEL_W, ICON_PIXEL_H,\n\t\t\t\t\tICON_PIXEL_W/2, ICON_PIXEL_H/2, (char *)NULL);\n\n\t\t\t} else {\n\t\t\t\tHidPage.Blit((*LogicPage), 0, 0, x + ((index % w)*(ICON_PIXEL_W)),\n\t\t\t\t\ty + ((index / w)*(ICON_PIXEL_H)), ICON_PIXEL_W, ICON_PIXEL_H);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::Prep_For_Add -- Prepares to add template to scenario.                    *\n *                                                                                             *\n *    This routine prepares a list of template objects so that the                             *\n *    scenario editor can use this list to display a dialog box. The                           *\n *    selection of a template object will allow its placement upon the                         *\n *    map.                                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *   05/28/1994 JLB : Only handles real templates now.                                         *\n *   06/04/1994 JLB : Uses map editing interface functions.                                    *\n *=============================================================================================*/\nvoid TemplateTypeClass::Prep_For_Add(void)\n{\n\tfor (TemplateType index = TEMPLATE_CLEAR1; index < TEMPLATE_COUNT; index++) {\n\t\tif (As_Reference(index).Get_Image_Data()) {\n\t\t\tMap.Add_To_List(&As_Reference(index));\n\t\t}\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * TemplateTypeClass::Create_And_Place -- Creates and places a template object on the map.     *\n *                                                                                             *\n *    This support routine is used by the scenario editor to add a template object to the map  *\n *    and to the game.                                                                         *\n *                                                                                             *\n * INPUT:   cell  -- The cell to place the template object.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the template object placed successfully?                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TemplateTypeClass::Create_And_Place(CELL cell, HousesType ) const\n{\n\tif (new TemplateClass(Type, cell)) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::Create_One_Of -- Creates an object of this template type.                *\n *                                                                                             *\n *    This routine will create an object of this type. For certain template objects, such      *\n *    as walls, it is actually created as a building. The \"building\" wall is converted into    *\n *    a template at the moment of placing down on the map.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the appropriate object for this template type.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * TemplateTypeClass::Create_One_Of(HouseClass *) const\n{\n\treturn(new TemplateClass(Type, -1));\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::One_Time -- Performs one-time initialization                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TemplateTypeClass::One_Time(void)\n{\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::As_Reference -- Fetches a reference to the template specified.           *\n *                                                                                             *\n *    This will return a reference to the TemplateTypeClass requested.                         *\n *                                                                                             *\n * INPUT:   type  -- The template type to fetch a reference to.                                *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the template type class specified.                     *\n *                                                                                             *\n * WARNINGS:   Be sure to pass a valid type parameter. This routine doesn't check it for       *\n *             legality.                                                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTemplateTypeClass & TemplateTypeClass::As_Reference(TemplateType type)\n{\n\treturn(*TemplateTypes.Ptr(type));\n}\n\n\nCOORDINATE TemplateTypeClass::Coord_Fixup(COORDINATE coord) const\n{\n\treturn Coord_Whole(coord);\n}\n"
  },
  {
    "path": "CODE/CDFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CDFILE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***             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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Library                                             *\n *                                                                                             *\n *                    File Name : CDFILE.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : October 18, 1994                                             *\n *                                                                                             *\n *                  Last Update : September 22, 1995 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CDFileClass::Clear_Search_Drives -- Removes all record of a search path.                  *\n *   CDFileClass::Open -- Opens the file object -- with path search.                           *\n *   CDFileClass::Open -- Opens the file wherever it can be found.                             *\n *   CDFileClass::Set_Name -- Performs a multiple directory scan to set the filename.          *\n *   CDFileClass::Set_Search_Drives -- Sets a list of search paths for file access.            *\n *   Is_Disk_Inserted -- Checks to see if a disk is inserted in specified drive.               *\n *   harderr_handler -- Handles hard DOS errors.                                               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"cdfile.h\"\n#include\t<stdio.h>\n#include\t<string.h>\n\n#ifndef WIN32\n#include\t<wwstd.h>\n#include\t<playcd.h>\n#endif\n\n/*\n**\tPointer to the first search path record.\n*/\nCDFileClass::SearchDriveType * CDFileClass::First = 0;\n\nint  CDFileClass::CurrentCDDrive = 0;\nint  CDFileClass::LastCDDrive = 0;\nchar CDFileClass::RawPath[512] = {0};\n\nCDFileClass::CDFileClass(char const *filename) :\n\tIsDisabled(false)\n{\n\tCDFileClass::Set_Name(filename);\n//\tmemset (RawPath, 0, sizeof(RawPath));\n}\n\n\nCDFileClass::CDFileClass(void) :\n\tIsDisabled(false)\n{\n}\nextern int Get_CD_Index (int cd_drive, int timeout);\n\n/***********************************************************************************************\n * harderr_handler -- Handles hard DOS errors.                                                 *\n *                                                                                             *\n *    This routine will handle the low level DOS error trapper. Instead of displaying the      *\n *    typical \"Abort, Retry, Ignore\" message, it simply returns with the failure code. The     *\n *    cause of the error will fail. The likely case would be with disk I/O.                    *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:  Return the failure code.                                                           *\n *                                                                                             *\n * WARNINGS:   Do no processing in this routine that could possibly generate another           *\n *             hard error condition.                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef WIN32\nint harderr_handler(unsigned int , unsigned int , unsigned int *)\n#else\nint harderr_handler(unsigned int , unsigned int , unsigned int __far *)\n#endif\n{\n\treturn(_HARDERR_FAIL);\n}\n\n\n/***********************************************************************************************\n * Is_Disk_Inserted -- Checks to see if a disk is inserted in specified drive.                 *\n *                                                                                             *\n *    This routine will examine the drive specified to see if there is a disk inserted. It     *\n *    can be used for floppy drives as well as for the CD-ROM.                                 *\n *                                                                                             *\n * INPUT:   disk  -- The drive number to examine. 0=A, 1=B, etc.                               *\n *                                                                                             *\n * OUTPUT:  bool; Is a disk inserted into the specified drive?                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint cdecl Is_Disk_Inserted(int disk)\n{\n#ifndef OBSOLETE\n\tstruct find_t fb;\n\tchar\tscan[] = \"?:\\\\*.*\";\n\n\t#ifndef WIN32\n\t\t_harderr(harderr_handler);\t\t// BG: Install hard error handler\n\t#endif\n\n\tscan[0] = (char)('A' + disk);\n\treturn(_dos_findfirst(scan, _A_SUBDIR, &fb) == 0);\n#else\n\tstruct {\n\t\tstruct {\n\t\t\tchar\tLength;\n\t\t\tchar\tUnit;\n\t\t\tchar\tFunction;\n\t\t\tchar\tStatus;\n\t\t\tchar\tReserved[8];\n\t\t} ReqHdr;\n\t\tchar\tMediaDescriptor;\t\t// Media descriptor byte from BPB.\n\t\tvoid\t*Transfer;\t\t\t\t// Pointer to transfer address block.\n\t\tshort\tLength;\t\t\t\t\t// Number of bytes to transfer.\n\t\tshort Sector;\t\t\t\t\t// Starting sector number.\n\t\tvoid\t*Volume;\t\t\t\t\t// Pointer to requested volume.\n\t} IOCTLI;\n\tchar status[5];\n\n\tmemset(IOCTLI, 0, sizeof(IOCTLI));\n\tIOCTLI.ReqHdr.Length = 26;\n\tIOCTLI.ReqHdr.Unit = 0;\t\t\t// First CD-ROM controlled by this driver.\n\t//IOCTLI.ReqHdr.Unit = 11;\t\t// Hard coded for K:\n\tIOCTLI.ReqHdr.Function = 3;\t// IOCTL read\n\tIOCTLI.Transfer = &status[0];\n\tIOCTLI.Length = sizeof(status);\n\tstatus[0] = 6;\t\t\t\t\t// Fetch device status code.\n\t_AX = 0x440D;\n\t_CX = 0x0003;\n\tgeninterrupt(0x21);\n\treturn(!(_AX & (1<<11)));\n#endif\n}\n\n\n/***********************************************************************************************\n * CDFileClass::Open -- Opens the file object -- with path search.                             *\n *                                                                                             *\n *    This will open the file object, but since the file object could have been constructed    *\n *    with a pathname, this routine will try to find the file first. For files opened for      *\n *    writing, then use the existing filename without performing a path search.                *\n *                                                                                             *\n * INPUT:   rights   -- The access rights to use when opening the file                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the open successful?                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CDFileClass::Open(int rights)\n{\n\treturn(BufferIOFileClass::Open(rights));\n}\n/***********************************************************************************************\n * CDFC::Refresh_Search_Drives -- Updates the search path when a CD changes or is added        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/22/96 9:01AM ST : Created                                                              *\n *=============================================================================================*/\nvoid CDFileClass::Refresh_Search_Drives (void)\n{\n\tClear_Search_Drives();\n\tSet_Search_Drives(RawPath);\n}\n\n#if 0\n/***********************************************************************************************\n * CDFileClass::Set_Search_Drives -- Sets a list of search paths for file access.              *\n *                                                                                             *\n *    This routine sets up a list of search paths to use when accessing files. The path list   *\n *    is scanned if the file could not be found in the current directory. This is the primary  *\n *    method of supporting CD-ROM drives, but is also useful for scanning network and other    *\n *    directories. The pathlist as passed to this routine is of the same format as the path    *\n *    list used by DOS -- paths are separated by semicolons and need not end in an antivirgule.*\n *                                                                                             *\n *    If a path entry begins with \"?:\" then the question mark will be replaced with the first  *\n *    CD-ROM drive letter available. If there is no CD-ROM driver detected, then this path     *\n *    entry will be ignored. By using this feature, you can always pass the CD-ROM path        *\n *    specification to this routine and it will not break if the CD-ROM is not loaded (as in   *\n *    the case during development).                                                            *\n *                                                                                             *\n *    Here is an example path specification:                                                   *\n *                                                                                             *\n *       Set_Search_Drives(\"DATA;?:\\DATA;F:\\PROJECT\\DATA\");                                    *\n *                                                                                             *\n *    In this example, the current directory will be searched first, followed by a the         *\n *    subdirectory \"DATA\" located off of the current directory. If not found, then the CD-ROM  *\n *    will be searched in a directory called \"\\DATA\". If not found or the CD-ROM is not        *\n *    present, then it will look to the hard coded path of \"F:\\PROJECTS\\DATA\" (maybe a         *\n *    network?). If all of these searches fail, the file system will default to the current    *\n *    directory and let the normal file error system take over.                                *\n *                                                                                             *\n * INPUT:   pathlist -- Pointer to string of path specifications (separated by semicolons)     *\n *                      that will be used to search for files.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CDFileClass::Set_Search_Drives(char * pathlist)\n{\n\tint found = false;\n\tint empty = false;\n\n\t/*\n\t**\tIf there is no pathlist to add, then just return.\n\t*/\n\tif (!pathlist) return(0);\n\n\tchar const * ptr = strtok(pathlist, \";\");\n\twhile (ptr) {\n\t\tchar path[PATH_MAX];\t\t\t\t\t\t// Working path buffer.\n\t\tSearchDriveType *srch;\t\t\t\t\t// Working pointer to path object.\n\n\t\t/*\n\t\t**\tFixup the path to be legal. Legal is defined as all that is necessary to\n\t\t**\tcreate a pathname is to append the actual filename submitted to the\n\t\t**\tfile system. This means that it must have either a trailing ':' or '\\'\n\t\t**\tcharacter.\n\t\t*/\n\t\tstrcpy(path, ptr);\n\t\tswitch (path[strlen(path)-1]) {\n\t\t\tcase ':':\n\t\t\tcase '\\\\':\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tstrcat(path, \"\\\\\");\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is a drive letter specified, and this drive letter is '?', then it should\n\t\t**\tbe substituted with the CD-ROM drive letter. In the case of no CD-ROM attached, then\n\t\t**\tmerely ignore this path entry.\n\t\t*/\n\t\tif (strncmp(path, \"?:\", 2) == 0) {\n\t\t\t#ifndef WIN32\n\t\t\t\tGetCDClass temp;\n\t\t\t\tint cd = temp.GetCDDrive();\n\t\t\t#else\n\t\t\t\tint cd = 10;\n\t\t\t#endif\n\t\t\tfound = cd;\n\t\t\tempty = !Is_Disk_Inserted(cd);\n\t\t\tif (!found || empty) goto nextpath;\n\t\t\tpath[0] = (char)('A' + cd);\n\t\t}\n\n\t\t/*\n\t\t**\tAllocate a record structure.\n\t\t*/\n\t\tsrch\t= new SearchDriveType;\n\t\tif (srch) {\n\t\t\tfound\t= true;\n\n\t\t\t/*\n\t\t\t**\tAttach the path to this structure.\n\t\t\t*/\n\t\t\tsrch->Path = strdup(path);\n\t\t\tsrch->Next = NULL;\n\n\t\t\t/*\n\t\t\t**\tAttach this path record to the end of the path chain.\n\t\t\t*/\n\t\t\tif (!First) {\n\t\t\t\tFirst = srch;\n\t\t\t} else {\n\t\t\t\tSearchDriveType * chain = First;\n\n\t\t\t\twhile (chain->Next) {\n\t\t\t\t\tchain = (SearchDriveType *)chain->Next;\n\t\t\t\t}\n\t\t\t\tchain->Next = srch;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tFind the next path string and resubmit.\n\t\t*/\nnextpath:\n\t\tptr = strtok(NULL, \";\");\n\t}\n\tif (!found) return(1);\n\tif (empty) return(2);\n\treturn(0);\n}\n#endif\n\n\n/***********************************************************************************************\n * CDFileClass::Set_Search_Drives -- Sets a list of search paths for file access.              *\n *                                                                                             *\n *    This routine sets up a list of search paths to use when accessing files. The path list   *\n *    is scanned if the file could not be found in the current directory. This is the primary  *\n *    method of supporting CD-ROM drives, but is also useful for scanning network and other    *\n *    directories. The pathlist as passed to this routine is of the same format as the path    *\n *    list used by DOS -- paths are separated by semicolons and need not end in an antivirgule.*\n *                                                                                             *\n *    If a path entry begins with \"?:\" then the question mark will be replaced with the first  *\n *    CD-ROM drive letter available. If there is no CD-ROM driver detected, then this path     *\n *    entry will be ignored. By using this feature, you can always pass the CD-ROM path        *\n *    specification to this routine and it will not break if the CD-ROM is not loaded (as in   *\n *    the case during development).                                                            *\n *                                                                                             *\n *    Here is an example path specification:                                                   *\n *                                                                                             *\n *       Set_Search_Drives(\"DATA;?:\\DATA;F:\\PROJECT\\DATA\");                                    *\n *                                                                                             *\n *    In this example, the current directory will be searched first, followed by a the         *\n *    subdirectory \"DATA\" located off of the current directory. If not found, then the CD-ROM  *\n *    will be searched in a directory called \"\\DATA\". If not found or the CD-ROM is not        *\n *    present, then it will look to the hard coded path of \"F:\\PROJECTS\\DATA\" (maybe a         *\n *    network?). If all of these searches fail, the file system will default to the current    *\n *    directory and let the normal file error system take over.                                *\n *                                                                                             *\n * INPUT:   pathlist -- Pointer to string of path specifications (separated by semicolons)     *\n *                      that will be used to search for files.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *   05/21/1996 ST  : Modified to recognise multiple CD drives                                 *\n *=============================================================================================*/\nint CDFileClass::Set_Search_Drives(char * pathlist)\n{\n\tint found = FALSE;\n\tint empty = FALSE;\n\n\t/*\n\t**\tIf there is no pathlist to add, then just return.\n\t*/\n\tif (!pathlist) return(0);\n\n\t/*\n\t** Save the path as it was passed in so we can parse it again later.\n\t** Check for the case where RawPath was passed in.\n\t*/\n\tif (pathlist != RawPath) {\n\t\tstrcat (RawPath, \";\");\n\t\tstrcat (RawPath, pathlist);\n\t}\n\n\tchar const * ptr = strtok(pathlist, \";\");\n\twhile (ptr != NULL) {\n\t\tif (strlen(ptr) > 0) {\n\n\t\t\tchar path[PATH_MAX];\t\t\t\t\t\t// Working path buffer.\n\n\t\t\t/*\n\t\t\t**\tFixup the path to be legal. Legal is defined as all that is necessary to\n\t\t\t**\tcreate a pathname is to append the actual filename submitted to the\n\t\t\t**\tfile system. This means that it must have either a trailing ':' or '\\'\n\t\t\t**\tcharacter.\n\t\t\t*/\n\t\t\tstrcpy(path, ptr);\n\t\t\tswitch (path[strlen(path)-1]) {\n\t\t\t\tcase ':':\n\t\t\t\tcase '\\\\':\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tstrcat(path, \"\\\\\");\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf there is a drive letter specified, and this drive letter is '?', then it should\n\t\t\t**\tbe substituted with the CD-ROM drive letter. In the case of no CD-ROM attached, then\n\t\t\t**\tmerely ignore this path entry.\n\t\t\t** Adds an extra entry for each CD drive in the system that has a C&C disc inserted.\n\t\t\t** \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tST - 5/21/96 4:40PM\n\t\t\t*/\n\t\t\tif (strncmp(path, \"?:\", 2) == 0) {\n\t\t\t\tif (CurrentCDDrive) {\n\t\t\t\t\tfound = true;\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If the drive has a C&C CD in it then add it to the path\n\t\t\t\t\t*/\n\t\t\t\t\tif (Get_CD_Index(CurrentCDDrive, 2*60) >= 0) {\n\t\t\t\t\t\tpath[0] = (char)(CurrentCDDrive + 'A');\n\t\t\t\t\t\tAdd_Search_Drive(path);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tFind the next path string and resubmit.\n\t\t\t\t*/\n\t\t\t\tptr = strtok(NULL, \";\");\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfound\t= true;\n\t\t\tAdd_Search_Drive(path);\n\t\t}\n\n\t\t/*\n\t\t**\tFind the next path string and resubmit.\n\t\t*/\n\t\tptr = strtok(NULL, \";\");\n\t}\n\tif (!found) return(1);\n\tif (empty) return(2);\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * CDFC::Add_Search_Drive -- Add a new path to the search path list                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    path                                                                              *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/22/96 10:12AM ST : Created                                                             *\n *=============================================================================================*/\nvoid CDFileClass::Add_Search_Drive(char *path)\n{\n\tSearchDriveType *srch;\t\t\t\t\t// Working pointer to path object.\n\t/*\n\t**\tAllocate a record structure.\n\t*/\n\tsrch\t= new SearchDriveType;\n\n\t/*\n\t**\tAttach the path to this structure.\n\t*/\n\tsrch->Path = strdup(path);\n\tsrch->Next = NULL;\n\n\t/*\n\t**\tAttach this path record to the end of the path chain.\n\t*/\n\tif (!First) {\n\t\tFirst = srch;\n\t} else {\n\t\tSearchDriveType * chain = First;\n\n\t\twhile (chain->Next) {\n\t\t\tchain = (SearchDriveType *)chain->Next;\n\t\t}\n\t\tchain->Next = srch;\n\t}\n}\n\n\n/***********************************************************************************************\n * CDFC::Set_CD_Drive -- sets the current CD drive letter                                      *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/22/96 9:39AM ST : Created                                                              *\n *=============================================================================================*/\nvoid CDFileClass::Set_CD_Drive (int drive)\n{\n\tLastCDDrive = CurrentCDDrive;\n\tCurrentCDDrive = drive;\n}\n\n\n/***********************************************************************************************\n * CDFileClass::Clear_Search_Drives -- Removes all record of a search path.                    *\n *                                                                                             *\n *    Use this routine to clear out any previous path(s) set with Set_Search_Drives()          *\n *    function.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CDFileClass::Clear_Search_Drives(void)\n{\n\tSearchDriveType\t* chain;\t\t\t// Working pointer to path chain.\n\n\tchain = First;\n\twhile (chain) {\n\t\tSearchDriveType\t*next;\n\n\t\tnext = (SearchDriveType *)chain->Next;\n\t\tif (chain->Path) {\n\t\t\tfree((char *)chain->Path);\n\t\t}\n\t\tdelete chain;\n\n\t\tchain = next;\n\t}\n\tFirst = 0;\n}\n\n\n/***********************************************************************************************\n * CDFileClass::Set_Name -- Performs a multiple directory scan to set the filename.            *\n *                                                                                             *\n *    This routine will scan all the directories specified in the path list and if the file    *\n *    was found in one of the directories, it will set the filename to a composite of the      *\n *    correct directory and the filename. It is used to allow path searching when searching    *\n *    for files. Typical use is to support CD-ROM drives. This routine examines the current    *\n *    directory first before scanning through the path list. If after scanning the entire      *\n *    path list, the file still could not be found, then the file object's name is set with    *\n *    just the raw filename as passed to this routine.                                         *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the filename to set as the name of this file object.        *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to the final and complete filename of this file object. This     *\n *          may have a path attached to the file.                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * CDFileClass::Set_Name(char const *filename)\n{\n\t/*\n\t**\tTry to find the file in the current directory first. If it can be found, then\n\t**\tjust return with the normal file name setting process. Do the same if there is\n\t**\tno multi-drive search path.\n\t*/\n\tBufferIOFileClass::Set_Name(filename);\n\tif (IsDisabled || !First || BufferIOFileClass::Is_Available()) return(File_Name());\n\n\t/*\n\t**\tAttempt to find the file first. Check the current directory. If not found there, then\n\t**\tsearch all the path specifications available. If it still can't be found, then just\n\t**\tfall into the normal raw file filename setting system.\n\t*/\n\tSearchDriveType * srch = First;\n\n\twhile (srch) {\n\t\tchar path[_MAX_PATH];\n\n\t\t/*\n\t\t**\tBuild a pathname to search for.\n\t\t*/\n\t\tstrcpy(path, srch->Path);\n\t\tstrcat(path, filename);\n\n\t\t/*\n\t\t**\tCheck to see if the file could be found. The low level Is_Available logic will\n\t\t**\tprompt if necessary when the CD-ROM drive has been removed. In all other cases,\n\t\t**\tit will return false and the search process will continue.\n\t\t*/\n\t\tBufferIOFileClass::Set_Name(path);\n\t\tif (BufferIOFileClass::Is_Available()) {\n\t\t\treturn(File_Name());\n\t\t}\n\n\t\t/*\n\t\t**\tIt wasn't found, so try the next path entry.\n\t\t*/\n\t\tsrch = (SearchDriveType *)srch->Next;\n\t}\n\n\t/*\n\t**\tAt this point, all path searching has failed. Just set the file name to the\n\t**\tplain text passed to this routine and be done with it.\n\t*/\n\tBufferIOFileClass::Set_Name(filename);\n\treturn(File_Name());\n}\n\n\n/***********************************************************************************************\n * CDFileClass::Open -- Opens the file wherever it can be found.                               *\n *                                                                                             *\n *    This routine is similar to the RawFileClass open except that if the file is being        *\n *    opened only for READ access, it will search all specified directories looking for the    *\n *    file. If after a complete search the file still couldn't be found, then it is opened     *\n *    using the normal BufferIOFileClass system -- resulting in normal error procedures.       *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the override filename to supply for this file object. It    *\n *                      would be the base filename (sans any directory specification).         *\n *                                                                                             *\n *          rights   -- The access rights to use when opening the file.                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened successfully? If so then the filename may be different   *\n *                than requested. The location of the file can be determined by examining the  *\n *                filename of this file object. The filename will contain the complete         *\n *                pathname used to open the file.                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CDFileClass::Open(char const *filename, int rights)\n{\n\tCDFileClass::Close();\n\n\t/*\n\t**\tVerify that there is a filename associated with this file object. If not, then this is a\n\t**\tbig error condition.\n\t*/\n\tif (!filename) {\n\t\tError(ENOENT, false);\n\t}\n\n\t/*\n\t**\tIf writing is requested, then multiple drive searching is not performed.\n\t*/\n\tif (IsDisabled || rights == WRITE) {\n\n\t\tBufferIOFileClass::Set_Name( filename );\n\t\treturn( BufferIOFileClass::Open( rights ) );\n\t}\n\n\t/*\n\t**\tPerform normal multiple drive searching for the filename and open\n\t**\tusing the normal procedure.\n\t*/\n\tSet_Name(filename);\n\treturn(BufferIOFileClass::Open(rights));\n}\n\n\n#ifdef NEVER\n/*\n** Get the drive letters if the CD's online */\n*/\nWORD cdecl GetCDDrive(VOID)\n{\n\t_ES = FP_SEG(&cdDrive[0]);\n\t_BX = FP_OFF(&cdDrive[0]);\n\t_AX = 0x150d;\n\tgeninterrupt(0x2F);\n\treturn((WORD)(*cdDrive));\n}\n#endif\n\n#if 0\nint Get_CD_Drive(void)\n{\n#ifdef WIN32\n\treturn(10);\n#else\n\n#ifdef NEVER\n\tfor (int index = 0; index < 26; index++) {\n\t\tunion REGS regs;\n\n\t\tregs.w.ax = 0x150B;\n\t\tregs.w.bx = 0;\n\t\tregs.w.cx = index;\n\t\tint386(0x2F, &regs, &regs);\n\t\tif (regs.w.bx == 0xADAD) {\n\t\t\treturn(index);\n\t\t}\n\t}\n\treturn(0);\n#else\n\tGetCDClass temp;\n\treturn(temp.GetCDDrive());\n#endif\n#endif\n}\n\n#endif\n"
  },
  {
    "path": "CODE/CDFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CDFILE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood LIbrary                                             *\n *                                                                                             *\n *                    File Name : CDFILE.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : October 18, 1994                                             *\n *                                                                                             *\n *                  Last Update : October 18, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CDFILE_H\n#define CDFILE_H\n\n#include\t<dos.h>\n#include\t\"bfiofile.h\"\n\n/*\n**\tThis class is derived from the BufferIOFileClass. This class adds the functionality of searching\n**\tacross multiple directories or drives. It is designed for the typical case of a CD-ROM game\n**\twere some data exists in the current directory (hard drive) and the rest exists on the CD-ROM.\n**\tSearching for the file occurs by first examining the current directory. If the file does not\n**\texist there, then all the paths available are examined in turn until the file can be found.\n**\tFor opening files to write, only the current directory is examined. The directory search order\n**\tis controlled by the path list as submitted to Set_Search_Drives(). The format of the path\n**\tstring is the same as the DOS path string.\n*/\nclass CDFileClass : public BufferIOFileClass\n{\n\tpublic:\n\t\tCDFileClass(char const *filename);\n\t\tCDFileClass(void);\n\t\tvirtual ~CDFileClass(void) {};\n\n\t\tvirtual char const * Set_Name(char const *filename);\n\t\tvirtual int Open(char const *filename, int rights=READ);\n\t\tvirtual int Open(int rights=READ);\n\n\t\tvoid Searching(int on) {IsDisabled = !on;};\n\n\t\tstatic bool Is_There_Search_Drives(void) {return(First != NULL);};\n\t\tstatic int Set_Search_Drives(char * pathlist);\n\t\tstatic void Add_Search_Drive(char *path);\n\t\tstatic void Clear_Search_Drives(void);\n\t\tstatic void Refresh_Search_Drives(void);\n\t\tstatic void Set_CD_Drive(int drive);\n\t\tstatic int  Get_CD_Drive(void) {return(CurrentCDDrive);};\n\t\tstatic int  Get_Last_CD_Drive(void) {return(LastCDDrive);};\n\n\tprivate:\n\n\t\t/*\n\t\t**\tIs multi-drive searching disabled for this file object?\n\t\t*/\n\t\tunsigned IsDisabled:1;\n\n\t\t/*\n\t\t**\tThis is the control record for each of the drives specified in the search\n\t\t**\tpath. There can be many such search paths available.\n\t\t*/\n\t\ttypedef struct {\n\t\t\tvoid * Next;\t\t// Pointer to next search record.\n\t\t\tchar const * Path;\t\t\t// Pointer to path string.\n\t\t} SearchDriveType;\n\n\t\t/*\n\t\t**\tThis points to the first path record.\n\t\t*/\n\t\tstatic SearchDriveType * First;\n\t\t/*\n\t\t** This is a copy of the unparsed search path list\n\t\t*/\n\t\tstatic char RawPath[512];\n\n\t\t/*\n\t\t** The drive letter of the current cd drive\n\t\t*/\n\t\tstatic int CurrentCDDrive;\n\n\t\t/*\n\t\t** The drive letter of the last used CD drive\n\t\t*/\n\t\tstatic int LastCDDrive;\n};\n\n#endif\n\n"
  },
  {
    "path": "CODE/CELL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CELL.CPP 4     3/14/97 1:15p Joe_b $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CELL.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 29, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 6, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CellClass::Adjacent_Cell -- Determines the adjacent cell according to facing.             *\n *   CellClass::Adjust_Threat -- Allows adjustment of threat at cell level                     *\n *   CellClass::Can_Tiberium_Germinate -- Determines if Tiberium can begin growth in the cell. *\n *   CellClass::Can_Tiberium_Grow -- Determines if Tiberium can grow in this cell.             *\n *   CellClass::Can_Tiberium_Spread -- Determines if Tiberium can spread from this cell.       *\n *   CellClass::CellClass -- Constructor for cell objects.                                     *\n *   CellClass::Cell_Building -- Return with building at specified cell.                       *\n *   CellClass::Cell_Color   -- Determine what radar color to use for this cell.               *\n *   CellClass::Cell_Coord -- Returns the coordinate of this cell.                             *\n *   CellClass::Cell_Find_Object -- Returns ptr to RTTI type occupying cell                    *\n *   CellClass::Cell_Infantry -- Returns with pointer of first infantry unit.                  *\n *   CellClass::Cell_Object -- Returns with clickable object in cell.                          *\n *   CellClass::Cell_Techno -- Return with the unit/building at specified cell.                *\n *   CellClass::Cell_Terrain -- Determines terrain object in cell.                             *\n *   CellClass::Cell_Unit -- Returns with pointer to unit occupying cell.                      *\n *   CellClass::Cell_Vessel -- Returns with pointer to a vessel located in the cell.           *\n *   CellClass::Clear_Icon -- Calculates what the clear icon number should be.                 *\n *   CellClass::Closest_Free_Spot -- returns free spot closest to given coord                  *\n *   CellClass::Concrete_Calc -- Calculates the concrete icon to use for the cell.             *\n *   CellClass::Draw_It -- Draws the cell imagery at the location specified.                   *\n *   CellClass::Flag_Place -- Places a house flag down on the cell.                            *\n *   CellClass::Flag_Remove -- Removes the house flag from the cell.                           *\n *   CellClass::Goodie_Check -- Performs crate discovery logic.                                *\n *   CellClass::Grow_Tiberium -- Grows the tiberium in the cell.                               *\n *   CellClass::Incoming -- Causes objects in cell to \"run for cover\".                         *\n *   CellClass::Is_Bridge_Here -- Checks to see if this is a bridge occupied cell.             *\n *   CellClass::Is_Clear_To_Build -- Determines if cell can be built upon.                     *\n *   CellClass::Is_Clear_To_Move -- Determines if the cell is generally clear for travel       *\n *   CellClass::Occupy_Down -- Flag occupation of specified cell.                              *\n *   CellClass::Occupy_Up -- Removes occupation flag from the specified cell.                  *\n *   CellClass::Overlap_Down -- This routine is used to mark a cell as being spilled over (over*\n *   CellClass::Overlap_Unit -- Marks cell as being overlapped by unit.                        *\n *   CellClass::Overlap_Up -- Removes overlap flag for the cell.                               *\n *   CellClass::Read -- Reads a particular cell value from a save game file.                   *\n *   CellClass::Recalc_Attributes -- Recalculates the ground type attributes for the cell.     *\n *   CellClass::Redraw_Objects -- Redraws all objects overlapping this cell.                   *\n *   CellClass::Reduce_Tiberium -- Reduces the tiberium in the cell by the amount specified.   *\n *   CellClass::Reduce_Wall -- Damages a wall, if damage is high enough.                       *\n *   CellClass::Reserve_Cell -- Marks a cell as being occupied by the specified unit ID.       *\n *   CellClass::Shimmer -- Causes all objects in the cell to shimmer.                          *\n *   CellClass::Spot_Index -- returns cell sub-coord index for given COORDINATE                *\n *   CellClass::Spread_Tiberium -- Spread Tiberium from this cell to an adjacent cell.         *\n *   CellClass::Tiberium_Adjust -- Adjust the look of the Tiberium for smooth.                 *\n *   CellClass::Wall_Update -- Updates the imagery for wall objects in cell.                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"vortex.h\"\n\n/***********************************************************************************************\n * CellClass::CellClass -- Constructor for cell objects.                                       *\n *                                                                                             *\n *    A cell object is constructed into an empty state. It contains no specific objects,       *\n *    templates, or overlays.                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/09/1994 JLB : Created.                                                                 *\n *   02/20/1996 JLB : Uses initializer list.                                                   *\n *=============================================================================================*/\nCellClass::CellClass(void) :\n\tID(Map.ID(this)),\n\tIsPlot(false),\n\tIsCursorHere(false),\n\tIsMapped(false),\n\tIsVisible(false),\n\tIsWaypoint(false),\n\tIsRadarCursor(false),\n\tIsFlagged(false),\n\tIsToShroud(false),\n\tJammed(0),\n\tTrigger(NULL),\n\tTType(TEMPLATE_NONE),\n\tTIcon(0),\n\tOverlay(OVERLAY_NONE),\n\tOverlayData(0),\n\tSmudge(SMUDGE_NONE),\n\tSmudgeData(0),\n\tOwner(HOUSE_NONE),\n\tInfType(HOUSE_NONE),\n\tOccupierPtr(0),\n\tLand(LAND_CLEAR)\n{\n\tfor (int zone = MZONE_FIRST; zone < MZONE_COUNT; zone++) {\n\t\tZones[zone] = 0;\n\t}\n\tFlag.Composite = 0;\n\tfor (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\tOverlapper[index] = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Color   -- Determine what radar color to use for this cell.                 *\n *                                                                                             *\n *    Use this routine to determine what radar color to render a radar                         *\n *    pixel with. This routine is called many many times to render the                         *\n *    radar map, so it must be fast.                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the color to display the radar pixel with.                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/01/1994 JLB : Created.                                                                 *\n *   04/30/1994 JLB : Converted to member function.                                            *\n *   05/31/1994 JLB : Takes into account any stealth characteristics of object.                *\n *=============================================================================================*/\nint CellClass::Cell_Color(bool override) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tBuildingClass * object = Cell_Building();\n\tif (object && !object->Class->IsInvisible) {\n\t\treturn(ColorRemaps[object->House->RemapColor].Bar);\n\t}\n\n\tif (override) {\n\t\treturn(TBLACK);\n\t}\n\tif (LastTheater == THEATER_SNOW) {\n\t\treturn(::SnowColor[Land_Type()]);\n\t} else {\n\t\treturn(::GroundColor[Land_Type()]);\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Techno -- Return with the unit/building at specified cell.                  *\n *                                                                                             *\n *    Returns an object located in the cell. If there is a                                     *\n *    building present, it returns a pointer to that, otherwise it returns                     *\n *    a pointer to one of the units there. If nothing is present in the                        *\n *    specified cell, then it returns NULL.                                                    *\n *                                                                                             *\n * INPUT:   x,y   -- Coordinate offset (from upper left corner) to use as an aid in selecting  *\n *                   the desired object within the cell.                                       *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to a building or unit located in cell. If                        *\n *          nothing present, just returns NULL.                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1992 JLB : Created.                                                                 *\n *   04/30/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nTechnoClass * CellClass::Cell_Techno(int x, int y) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tObjectClass * object;\n\tCOORDINATE\t\tclick;\t\t\t// Coordinate of click relative to cell corner.\n\tTechnoClass * close = NULL;\n\tlong\t\tdistance = 0;\t// Recorded closest distance.\n\n\t/*\n\t**\tCreate a coordinate value that represent the pixel location within the cell. This is\n\t**\tactually the lower significant bits (leptons) of a regular coordinate value.\n\t*/\n\tclick = XY_Coord(Pixel_To_Lepton(x), Pixel_To_Lepton(y));\n\n\tif (Cell_Occupier()) {\n\t\tobject = Cell_Occupier();\n\t\twhile (object) {\n\t\t\tif (object->Is_Techno()) {\n\t\t\t\tCOORDINATE coord = Coord_Fraction(object->Center_Coord());\n\t\t\t\tlong dist = Distance(coord, click);\n\t\t\t\tif (!close || dist < distance) {\n\t\t\t\t\tclose = (TechnoClass *)object;\n\t\t\t\t\tdistance = dist;\n\t\t\t\t}\n\t\t\t}\n\t\t\tobject = object->Next;\n\t\t}\n\t}\n\treturn(close);\n}\n\n\n/***************************************************************************\n * CellClass::Cell_Find_Object -- Returns ptr to RTTI type occupying cell  *\n *                                                                         *\n * INPUT:\t\tRTTIType the RTTI type we are searching for                 *\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/17/1995 PWG : Created.                                             *\n *   06/12/1995 JLB : Returns object class pointer.                        *\n *=========================================================================*/\nObjectClass * CellClass::Cell_Find_Object(RTTIType rtti) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\tassert(rtti != RTTI_NONE);\n\n\tObjectClass * object = Cell_Occupier();\n\n\twhile (object != NULL) {\n\t\tif (object->What_Am_I() == rtti) {\n\t\t\treturn(object);\n\t\t}\n\t\tobject = object->Next;\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Building -- Return with building at specified cell.                         *\n *                                                                                             *\n *    Given a cell, determine if there is a building associated                                *\n *    and return with a pointer to this building.                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the building associated with the                         *\n *          cell. If there is no building associated, then NULL is                             *\n *          returned.                                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1992 JLB : Created.                                                                 *\n *   04/30/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nBuildingClass * CellClass::Cell_Building(void) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\treturn((BuildingClass *)Cell_Find_Object(RTTI_BUILDING));\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Terrain -- Determines terrain object in cell.                               *\n *                                                                                             *\n *    This routine is used to determine the terrain object (if any) that                       *\n *    overlaps this cell.                                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the terrain object that overlaps                         *\n *          this cell. If there is no terrain object present, then NULL                        *\n *          is returned.                                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTerrainClass * CellClass::Cell_Terrain(void) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\treturn((TerrainClass *)Cell_Find_Object(RTTI_TERRAIN));\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Object -- Returns with clickable object in cell.                            *\n *                                                                                             *\n *    This routine is used to determine which object is to be selected                         *\n *    by a player click upon the cell. Not all objects that overlap the                        *\n *    cell are selectable by the player. This routine sorts out which                          *\n *    is which and returns with the appropriate object pointer.                                *\n *                                                                                             *\n * INPUT:   x,y   -- Coordinate (from upper left corner of cell) to use as a guide when        *\n *                   selecting the object within the cell. This plays a role in those cases    *\n *                   where several objects (such as infantry) exist within the same cell.      *\n *                                                                                             *\n * OUTPUT:  Returns with pointer to the object clickable within the                            *\n *          cell. NULL is returned if there is no clickable object                             *\n *          present.                                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/13/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * CellClass::Cell_Object(int x, int y) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tObjectClass * ptr;\n\n\t/*\n\t**\tHack so that aircraft landed on helipads can still be selected if directly\n\t**\tclicked on.\n\t*/\n\tptr = (ObjectClass *)Cell_Find_Object(RTTI_AIRCRAFT);\n\tif (ptr) {\n\t\treturn(ptr);\n\t}\n\n\tptr = Cell_Techno(x, y);\n\tif (ptr) {\n\t\treturn(ptr);\n\t}\n\tptr = Cell_Terrain();\n\tif (ptr) return(ptr);\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * CellClass::Redraw_Objects -- Redraws all objects overlapping this cell.                     *\n *                                                                                             *\n *    This is a low level routine that marks all objects that overlap this                     *\n *    cell to be redrawn. It is necessary to call this routine whenever                        *\n *    the underlying icon has to be redrawn.                                                   *\n *                                                                                             *\n * INPUT:   forced   -- Should this redraw be forced even if flags                             *\n *                      indicate that it would be redundant?                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1994 JLB : Created.                                                                 *\n *   06/20/1994 JLB : Simplified to use object pointers.                                       *\n *   12/24/1994 JLB : Only checks if cell is in view and not flagged already.                  *\n *=============================================================================================*/\nvoid CellClass::Redraw_Objects(bool forced)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tCELL\tcell = Cell_Number();\n\n\tif (Map.In_View(cell) && (forced || !Map.Is_Cell_Flagged(cell))) {\n\n\t\t/*\n\t\t**\tFlag the icon to be redrawn.\n\t\t*/\n\t\tMap.Flag_Cell(cell);\n\n\t\t/*\n\t\t**\tFlag the main object in the cell to be redrawn.\n\t\t*/\n\t\tif (Cell_Occupier() != NULL) {\n\t\t\tObjectClass * optr = Cell_Occupier();\n\t\t\twhile (optr != NULL && optr->IsActive) {\n\n#ifdef SORTDRAW\n\t\t\t\tif (optr->Is_Techno() && ((TechnoClass *)optr)->Visual_Character() != VISUAL_NORMAL) {\n\t\t\t\t\toptr->Mark(MARK_CHANGE);\n\t\t\t\t}\n#else\n\t\t\t\toptr->Mark(MARK_CHANGE);\n#endif\n\t\t\t\tif (optr->Next != NULL && !optr->Next->IsActive) {\n\t\t\t\t\toptr->Next = NULL;\n\t\t\t\t}\n\t\t\t\toptr = optr->Next;\n\t\t\t}\n\t\t}\n\n#ifdef SORTDRAW\n\t\t/*\n\t\t**\tFlag any overlapping object in this cell to be redrawn.\n\t\t*/\n\t\tfor (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\t\tif (Overlapper[index]) {\n\t\t\t\tassert(Overlapper[index]->IsActive);\n\t\t\t\tif (Overlapper[index]->Is_Techno() && ((TechnoClass *)Overlapper[index])->Visual_Character() != VISUAL_NORMAL) {\n\t\t\t\t\tOverlapper[index]->Mark(MARK_CHANGE);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#else\n\t\t/*\n\t\t**\tFlag any overlapping object in this cell to be redrawn.\n\t\t*/\n\t\tfor (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\t\tif (Overlapper[index] != NULL) {\n\t\t\t\tif (!Overlapper[index]->IsActive) {\n\t\t\t\t\tOverlapper[index] = NULL;\n\t\t\t\t} else {\n\t\t\t\t\tOverlapper[index]->Mark(MARK_CHANGE);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#endif\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Is_Clear_To_Build -- Determines if cell can be built upon.                       *\n *                                                                                             *\n *    This determines if the cell can become a proper foundation for                           *\n *    building placement.                                                                      *\n *                                                                                             *\n * INPUT:   loco     -- The locomotion of the object trying to consider if this cell is        *\n *                      generally clear. Buildings use the value of SPEED_NONE.                *\n *                                                                                             *\n * OUTPUT:  bool; Is this cell generally clear (usually for building purposes)?                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1994 JLB : Created.                                                                 *\n *   06/25/1996 JLB : Handles different locomotion types.                                      *\n *   10/05/1996 JLB : Checks for crushable walls and crushable object.                         *\n *=============================================================================================*/\nbool CellClass::Is_Clear_To_Build(SpeedType loco) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\t/*\n\t**\tDuring scenario initialization, passability is always guaranteed.\n\t*/\n\tif (ScenarioInit) return(true);\n\n\t/*\n\t**\tIf there is an object there, then don't allow building.\n\t*/\n\tif (Cell_Object() != NULL) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tPrevents a building from being placed over a flag object.\n\t*/\n#ifdef FIXIT_FLAG_CHECK\n\tif (IsFlagged)  {\n\t\treturn(false);\n\t}\n#endif\n\n\t/*\n\t**\tWalls are always considered to block the terrain for general passability\n\t**\tpurposes. In normal game mode, all overlays are not buildable.\n\t*/\n\tif (Overlay != OVERLAY_NONE && (Overlay == OVERLAY_FLAG_SPOT || !Debug_Map || OverlayTypeClass::As_Reference(Overlay).IsWall)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tBuilding over a bib is not allowed.\n\t*/\n\tif (Smudge != SMUDGE_NONE && SmudgeTypeClass::As_Reference(Smudge).IsBib /* && Owner != HOUSE_NONE*/) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tBuilding on certain kinds of terrain is prohibited -- bridges in particular.\n\t**\tIf the locomotion type is SPEED_NONE, then this check is presumed to be\n\t**\tfor the purposes of building.\n\t*/\n\tif (loco == SPEED_NONE) {\n\t\tif (Is_Bridge_Here()) {\n\t\t\treturn(false);\n\t\t}\n\n\t\treturn(::Ground[Land_Type()].Build);\n\n\t} else {\n\n\t\tif (::Ground[Land_Type()].Cost[loco] == fixed(0)) {\n//\t\tif (::Ground[Land_Type()].Cost[SPEED_TRACK] == fixed(0)) {\n\t\t\treturn(false);\n\t\t}\n\t\treturn(true);\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Recalc_Attributes -- Recalculates the ground type attributes for the cell.       *\n *                                                                                             *\n *    This routine recalculates the ground type in the cell. The speeds the find path          *\n *    algorithm and other determinations of the cell type.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/29/1994 JLB : Created.                                                                 *\n *   06/20/1994 JLB : Knows about template pointer in cell object.                             *\n *=============================================================================================*/\nvoid CellClass::Recalc_Attributes(void)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\t/*\n\t**\tSpecial override for interior terrain set so that a non-template or a clear template\n\t**\tis equivalent to impassable rock.\n\t*/\n\tif (LastTheater == THEATER_INTERIOR) {\n\t\tif (TType == TEMPLATE_NONE || TType == TEMPLATE_CLEAR1) {\n\t\t\tLand = LAND_ROCK;\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck for wall effects.\n\t*/\n\tif (Overlay != OVERLAY_NONE) {\n\t\tLand = OverlayTypeClass::As_Reference(Overlay).Land;\n\t\tif (Land != LAND_CLEAR) return;\n\t}\n\n\t/*\n\t**\tIf there is a template associated with this cell, then fetch the\n\t**\tland type given the template type and icon number.\n\t*/\n\tif (TType != TEMPLATE_NONE && TType != 255) {\n\t\tTemplateTypeClass const * ttype = &TemplateTypeClass::As_Reference(TType);\n\t\tLand = ttype->Land_Type(TIcon);\n\t\treturn;\n\t}\n\n\t/*\n\t**\tNo template is the same as clear terrain.\n\t*/\n\tLand = LAND_CLEAR;\n}\n\n\n/***********************************************************************************************\n * CellClass::Occupy_Down -- Flag occupation of specified cell.                                *\n *                                                                                             *\n *    This routine is used to mark the cell as being occupied by the specified object.         *\n *                                                                                             *\n * INPUT:   object   -- The object that is to occupy the cell                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *   11/29/1994 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid CellClass::Occupy_Down(ObjectClass * object)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\tassert(object != NULL && object->IsActive);\n\n\tObjectClass * optr;\n\n\tif (object == NULL) return;\n\n\t/*\n\t**\tAlways add buildings to the end of the occupation chain. This is necessary because\n\t**\tthe occupation chain is a single list even though buildings occupy more than one\n\t**\tcell. If more than one building is allowed to occupy the same cell, then this chain\n\t**\tlogic will fail.\n\t*/\n\tif (object->What_Am_I() == RTTI_BUILDING && Cell_Occupier()) {\n\t\toptr = Cell_Occupier();\n\t\twhile (optr->Next != NULL) {\n\t\t\tassert(optr != object);\n\t\t\tassert(optr->What_Am_I() != RTTI_BUILDING);\n\t\t\toptr = optr->Next;\n\t\t}\n\t\toptr->Next = object;\n\t\tobject->Next = 0;\n\t} else {\n\t\tobject->Next = Cell_Occupier();\n\t\tOccupierPtr = object;\n\t}\n\tMap.Radar_Pixel(Cell_Number());\n\n\t/*\n\t**\tIf being placed down on a visible square, then flag this\n\t**\ttechno object as being revealed to the player.\n\t*/\n\tif (IsMapped || Session.Type != GAME_NORMAL) {\n\t\tobject->Revealed(PlayerPtr);\n\t}\n\n\t/*\n\t**\tSpecial occupy bit set.\n\t*/\n\tswitch (object->What_Am_I()) {\n\t\tcase RTTI_BUILDING:\n\t\t\tFlag.Occupy.Building = true;\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\tcase RTTI_AIRCRAFT:\n\t\tcase RTTI_UNIT:\n\t\t\tFlag.Occupy.Vehicle = true;\n\t\t\tbreak;\n\n\t\tcase RTTI_TERRAIN:\n\t\t\tFlag.Occupy.Monolith = true;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Occupy_Up -- Removes occupation flag from the specified cell.                    *\n *                                                                                             *\n *    This routine will lift the object from the cell and free the cell to be occupied by      *\n *    another object. Only if the cell was previously marked with the object specified, will   *\n *    the object be lifted off. This routine is the counterpart to Occupy_Down().              *\n *                                                                                             *\n * INPUT:   object   -- The object that is being lifted off.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *   11/29/1994 JLB : Fixed to handle next pointer in previous object.                         *\n *=============================================================================================*/\nvoid CellClass::Occupy_Up(ObjectClass * object)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\tassert(object != NULL && object->IsActive);\n\n\tif (object == NULL) return;\n\n\tObjectClass * optr = Cell_Occupier();\t\t// Working pointer to the objects in the chain.\n\n\tif (optr == object) {\n\t\tOccupierPtr = object->Next;\n\t\tobject->Next = 0;\n\t} else {\n\t\tbool found = false;\n\t\twhile (optr != NULL) {\n\t\t\tif (optr->Next == object) {\n\t\t\t\toptr->Next = object->Next;\n\t\t\t\tobject->Next = 0;\n\t\t\t\tfound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\toptr = optr->Next;\n\t\t}\n//\t\tassert(found);\n\t}\n\tMap.Radar_Pixel(Cell_Number());\n\n\t/*\n\t**\tSpecial occupy bit clear.\n\t*/\n\tswitch (object->What_Am_I()) {\n\t\tcase RTTI_BUILDING:\n\t\t\tFlag.Occupy.Building = false;\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\tcase RTTI_AIRCRAFT:\n\t\tcase RTTI_UNIT:\n\t\t\tFlag.Occupy.Vehicle = false;\n\t\t\tbreak;\n\n\t\tcase RTTI_TERRAIN:\n\t\t\tFlag.Occupy.Monolith = false;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Overlap_Down -- This routine is used to mark a cell as being spilled over (overla*\n *                                                                                             *\n *    Most game objects can often have their graphic imagery spill into more than one cell     *\n *    even though they are considered to \"occupy\" only one cell. All cells overlapped are      *\n *    flagged by this routine. Using this information it is possible to keep the tactical map  *\n *    display correct.                                                                         *\n *                                                                                             *\n * INPUT:   object   -- The object to mark as overlapping this cell.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *   07/04/1995 JLB : Ensures that buildings are always marked down.                           *\n *=============================================================================================*/\nvoid CellClass::Overlap_Down(ObjectClass * object)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\tassert(object != NULL && object->IsActive);\n\n\tObjectClass ** ptr = 0;\n\n\tif (!object) return;\n\n\tfor (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\tif (Overlapper[index] == object) return;\n\t\tif (!Overlapper[index]) ptr = &Overlapper[index];\n\t}\n\n\t/*\n\t**\tBuildings must ALWAYS succeed in marking the cell as overlapped. Bump somebody\n\t**\telse out in this case.\n\t*/\n\tif (!ptr && object->What_Am_I() == RTTI_BUILDING) {\n\t\tfor (index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\t\tswitch (Overlapper[index]->What_Am_I()) {\n\t\t\t\tcase RTTI_BUILDING:\n\t\t\t\tcase RTTI_TERRAIN:\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tOverlapper[index] = object;\n\t\t\t\t\tindex = ARRAY_SIZE(Overlapper);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tif (ptr) *ptr = object;\n\n\t/*\n\t**\tIf being placed down on a visible square, then flag this\n\t**\ttechno object as being revealed to the player.\n\t*/\n\tif (IsMapped) {\n\t\tobject->Revealed(PlayerPtr);\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Overlap_Up -- Removes overlap flag for the cell.                                 *\n *                                                                                             *\n *    This is the counterpart to Overlap_Down and is used to remove the overlap flag for the   *\n *    specified unit on the cell.                                                              *\n *                                                                                             *\n * INPUT:   object   -- The object to remove the overlap flag for.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CellClass::Overlap_Up(ObjectClass * object)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\tassert(object != NULL && object->IsActive);\n\n\tfor (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\tif (Overlapper[index] == object) {\n\t\t\tOverlapper[index] = 0;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Unit -- Returns with pointer to unit occupying cell.                        *\n *                                                                                             *\n *    This routine will determine if a unit is occupying the cell and if so, return a pointer  *\n *    to it. If there is no unit occupying the cell, then NULL is returned.                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with pointer to unit occupying cell, else NULL.                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nUnitClass * CellClass::Cell_Unit(void) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\treturn((UnitClass*)Cell_Find_Object(RTTI_UNIT));\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Vessel -- Returns with pointer to a vessel located in the cell.             *\n *                                                                                             *\n *    Call this routine to query and return a pointer to a vessel located in the cell. If      *\n *    there is no vessel present, then this routine will return NULL.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the vessel class object if one is present.               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nVesselClass * CellClass::Cell_Vessel(void) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\treturn((VesselClass*)Cell_Find_Object(RTTI_VESSEL));\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Infantry -- Returns with pointer of first infantry unit occupying the cell. *\n *                                                                                             *\n *    This routine examines the cell and returns a pointer to the first infantry unit          *\n *    that occupies it. If there is no infantry unit in the cell, then NULL is returned.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with pointer to infantry unit occupying the cell or NULL if none are       *\n *          present.                                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/21/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nInfantryClass * CellClass::Cell_Infantry(void) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\treturn((InfantryClass*)Cell_Find_Object(RTTI_INFANTRY));\n}\n\n\n#ifdef SORTDRAW\nstatic bool _Calc_Partial_Window(int cellx, int celly, int & drawx, int & drawy)\n{\n\tint & px = WindowList[WINDOW_PARTIAL][WINDOWX];\n\tint & py = WindowList[WINDOW_PARTIAL][WINDOWY];\n\tint & pw = WindowList[WINDOW_PARTIAL][WINDOWWIDTH];\n\tint & ph = WindowList[WINDOW_PARTIAL][WINDOWHEIGHT];\n\tint & tx = WindowList[WINDOW_TACTICAL][WINDOWX];\n\tint & ty = WindowList[WINDOW_TACTICAL][WINDOWY];\n\tint & tw = WindowList[WINDOW_TACTICAL][WINDOWWIDTH];\n\tint & th = WindowList[WINDOW_TACTICAL][WINDOWHEIGHT];\n\n\tpx = cellx + tx;\n\tpy = celly + ty;\n\tpw = CELL_PIXEL_W;\n\tph = CELL_PIXEL_H;\n\n\tif (px < tx) {\n\t\tpw -= tx - px;\n\t\tpx = tx;\n\t}\n\tif (pw < 1) return(false);\n\n\tif (py < ty) {\n\t\tph -= ty - py;\n\t\tpy = ty;\n\t}\n\tif (ph < 1) return(false);\n\n\tif (px + pw > tx + tw) {\n\t\tpw -= (px + pw) - (tx + tw);\n\t}\n\tif (pw < 1) return(false);\n\n\tif (py + ph > ty + th) {\n\t\tph -= (py + ph) - (ty + th);\n\t}\n\tif (ph < 1) return(false);\n\n\tdrawx = drawx - (px-tx);\n\tdrawy = drawy - (py-ty);\n\treturn(true);\n}\n\n\nstatic int _ocompare(const void * left, const void * right)\n{\n\tCOORDINATE lcoord = (*((ObjectClass **)left))->Sort_Y();\n\tCOORDINATE rcoord = (*((ObjectClass **)right))->Sort_Y();\n\tif (lcoord < rcoord) return(-1);\n\tif (lcoord > rcoord) return(1);\n\treturn(0);\n}\n#endif\n\n\n/***********************************************************************************************\n * CellClass::Draw_It -- Draws the cell imagery at the location specified.                     *\n *                                                                                             *\n *    This is the gruntwork cell rendering code. It draws the cell at the screen location      *\n *    specified. This routine doesn't draw any overlapping or occupying units. It only         *\n *    deals with the ground (cell) layer -- icon level.                                        *\n *                                                                                             *\n * INPUT:   x,y   -- The screen coordinates to render the cell imagery at.                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *   08/21/1994 JLB : Revised for simple template objects.                                     *\n *   11/01/1994 BRR : Updated placement cursor; draws actual object                            *\n *   11/14/1994 BRR : Added remapping code to show passable areas                              *\n *   12/02/1994 BRR : Added trigger display                                                    *\n *   12/11/1994 JLB : Mixes up clear terrain through pseudo-random table.                      *\n *   04/25/1995 JLB : Smudges drawn BELOW overlays.                                            *\n *   07/22/1996 JLB : Objects added to draw process.                                           *\n *=============================================================================================*/\nvoid CellClass::Draw_It(int x, int y, bool objects) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tif (!objects) {\n\t\tBStart(BENCH_CELL);\n\n\t\tTemplateTypeClass const * ttype = 0;\n\t\tint\ticon;\t\t// The icon number to use from the template set.\n\t\tCELL\tcell = Cell_Number();\n\t\tvoid * remap = NULL;\n\t#ifdef SCENARIO_EDITOR\n\t\tTemplateTypeClass * tptr;\n//\t\tTriggerClass * trig;\n\t\tint i;\n\t\tchar waypt[3];\n\t#endif\n\n\t\tCellCount++;\n\n\t\t/*\n\t\t**\tFetch a pointer to the template type associated with this cell.\n\t\t*/\n\t\tif (TType != TEMPLATE_NONE && TType != TEMPLATE_CLEAR1 && TType != 255) {\n\t\t\tttype = &TemplateTypeClass::As_Reference(TType);\n\t\t\ticon = TIcon;\n\t\t} else {\n\t\t\tttype = &TemplateTypeClass::As_Reference(TEMPLATE_CLEAR1);\n\t\t\ticon = Clear_Icon();\n\t\t}\n\n\t#ifdef CHEAT_KEYS\n\t\t/*\n\t\t**\tDraw the stamp of the template.\n\t\t*/\n\t\tif (Debug_Icon) {\n\t\t\tLogicPage->Fill_Rect(Map.TacPixelX+x, Map.TacPixelY+y, Map.TacPixelX+x+ICON_PIXEL_W-1, Map.TacPixelY+y+ICON_PIXEL_H-1, Sim_Random_Pick(1, 254));\n\t\t\tFontXSpacing -= 2;\n\t\t\tFancy_Text_Print(\"%02X%02X\\r%d%d%d\\r%d %d\", Map.TacPixelX+x+(ICON_PIXEL_W>>1), Map.TacPixelY+y, &GreyScheme, TBLACK, TPF_EFNT|TPF_CENTER|TPF_BRIGHT_COLOR|TPF_FULLSHADOW,\n\t\t\t\tCell_Y(cell), Cell_X(cell),\n\t\t\t\t//(CurrentObject.Count() && CurrentObject[0]->Is_Techno()) ? ((TechnoClass *)CurrentObject[0])->House->Which_Zone(cell) : -1,\n\t\t\t\tZones[MZONE_NORMAL],Zones[MZONE_CRUSHER],Zones[MZONE_DESTROYER],\n\t\t\t\tOverlay, OverlayData\n\t\t\t\t);\n\t\t\tFontXSpacing += 2;\n\t\t} else {\n\t#endif\n\n\t#ifdef SCENARIO_EDITOR\n\t\t\t/*\n\t\t\t**\tSet up the remap table for this icon.\n\t\t\t*/\n\t\t\tif (Debug_Map && Debug_Passable) {\n\t\t\t\tif (::Ground[Land].Cost[0] == 0 || (Cell_Occupier() != NULL &&\n\t\t\t\t\tCell_Occupier()->What_Am_I() != RTTI_INFANTRY)) {\t// impassable\n\t\t\t\t\tremap = DisplayClass::FadingRed;\n\t\t\t\t} else {\n\t\t\t\t\tif (::Ground[Land].Cost[0] > fixed(1, 3)) {\t// pretty passable\n\t\t\t\t\t\tremap = DisplayClass::FadingGreen;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tremap = DisplayClass::FadingYellow;\t\t\t\t// moderately passable\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t#endif\n\n\t\t\t/*\n\t\t\t**\tThis is the underlying terrain icon.\n\t\t\t*/\n\t\t\tif (ttype->Get_Image_Data()) {\n\t\t\t\tLogicPage->Draw_Stamp(ttype->Get_Image_Data(), icon, x, y, NULL, WINDOW_TACTICAL);\n\t\t\t\tif (remap) {\n\t\t\t\t\tLogicPage->Remap(x+Map.TacPixelX, y+Map.TacPixelY, ICON_PIXEL_W, ICON_PIXEL_H, remap);\n\t\t\t\t}\n\t\t\t}\n\n\t#ifdef SCENARIO_EDITOR\n\t\t\t/*\n\t\t\t**\tDraw the map editor's \"current\" cell. This is the cell that can be\n\t\t\t**\tassigned attributes such as tag labels.\n\t\t\t**\tThis must be draw before the placement cursor, but after drawing the\n\t\t\t**\tobjects in the cell.\n\t\t\t*/\n\t\t\tif (Debug_Map && CurrentCell == Cell_Number()) {\n\t\t\t\tLogicPage->Draw_Rect(x+Map.TacPixelX, y+Map.TacPixelY, Map.TacPixelX + x + CELL_PIXEL_W - 1, Map.TacPixelY + y + CELL_PIXEL_H - 1, YELLOW);\n\t\t\t}\n\t#endif\n\n\t\t\t/*\n\t\t\t**\tRedraw any smudge.\n\t\t\t*/\n\t\t\tif (Smudge != SMUDGE_NONE) {\n\t\t\t\tSmudgeTypeClass::As_Reference(Smudge).Draw_It(x, y, SmudgeData);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDraw the overlay object.\n\t\t\t*/\n\t\t\tif (Overlay != OVERLAY_NONE) {\n\t\t\t\tOverlayTypeClass const & otype = OverlayTypeClass::As_Reference(Overlay);\n\t\t\t\tIsTheaterShape = (bool)otype.IsTheater;\t//Tell Build_Frame if this overlay is theater specific\n\t\t\t\tCC_Draw_Shape(otype.Get_Image_Data(), OverlayData, (x+(CELL_PIXEL_W>>1)), (y+(CELL_PIXEL_H>>1)), WINDOW_TACTICAL, SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_GHOST, NULL, DisplayClass::UnitShadow);\n\t\t\t\tIsTheaterShape = false;\n\t\t\t}\n\n\t#ifdef SCENARIO_EDITOR\n\t\t\tif (Debug_Map) {\n\t\t\t\t/*\n\t\t\t\t**\tDraw the cell's Trigger mnemonic, if it has a trigger\n\t\t\t\t*/\n\t\t\t\tif (Trigger.Is_Valid()) {\n\t\t\t\t\tFancy_Text_Print(Trigger->Class->IniName, x+Map.TacPixelX, y+Map.TacPixelY, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_EFNT|TPF_FULLSHADOW);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tDraw the cell's Waypoint designation if there is one.\n\t\t\t\t*/\n\t\t\t\tif (IsWaypoint) {\n\t\t\t\t\tfor (i = 0; i < WAYPT_HOME; i++) {\n\t\t\t\t\t\tif (Scen.Waypoint[i] == Cell_Number()) {\n\t\t\t\t\t\t\tif (i < 26) {\n\t\t\t\t\t\t\t\twaypt[0] = 'A' + i;\n\t\t\t\t\t\t\t\twaypt[1] = 0;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\twaypt[0] = 'A' + (i/26)-1;\n\t\t\t\t\t\t\t\twaypt[1] = 'A' + (i % 26);\n\t\t\t\t\t\t\t\twaypt[2] = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tFancy_Text_Print(waypt, Map.TacPixelX + x + CELL_PIXEL_W / 2,\n\t\t\t\t\t\t\t\tMap.TacPixelY + y + (CELL_PIXEL_H / 2) - 3,\n\t\t\t\t\t\t\t\t&ColorRemaps[PCOLOR_RED], TBLACK,\n\t\t\t\t\t\t\t\tTPF_EFNT | TPF_CENTER|TPF_FULLSHADOW);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (Scen.Waypoint[WAYPT_HOME] == Cell_Number()) {\n\t\t\t\t\t\t\tFancy_Text_Print(\"Home\", Map.TacPixelX + x, Map.TacPixelY + y + (CELL_PIXEL_H) - 7,\n\t\t\t\t\t\t\t&ColorRemaps[PCOLOR_GREY], TBLACK, TPF_EFNT|TPF_FULLSHADOW);\n\t\t\t\t\t}\n\t\t\t\t\tif (Scen.Waypoint[WAYPT_REINF] == Cell_Number()) {\n\t\t\t\t\t\t\tFancy_Text_Print(\"Reinf\", Map.TacPixelX + x, Map.TacPixelY + y + (CELL_PIXEL_H) - 7,\n\t\t\t\t\t\t\t&ColorRemaps[PCOLOR_GREY], TBLACK, TPF_EFNT|TPF_FULLSHADOW);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t#endif\n\n\t\t\t/*\n\t\t\t**\tDraw the placement cursor:\n\t\t\t**\t- First, draw the hash-mark cursor, so it will appear underneath\n\t\t\t**\t  any cursor being drawn\n\t\t\t**\t- If the PendingObject is a template, overlay, or smudge, draw it\n\t\t\t**\t- Otherwise, it's up to the Display.Refresh_Map() routine to draw it\n\t\t\t*/\n\t\t\tif (IsCursorHere) {\n\t\t\t\tSpeedType loco = SPEED_NONE;\n\t\t\t\tif (Map.PendingObjectPtr) {\n\t\t\t\t\tif (Map.PendingObjectPtr->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\tBuildingClass * obj = (BuildingClass *)(Map.PendingObjectPtr);\n\t\t\t\t\t\tloco = obj->Class->Speed;\n\t//\t\t\t\t\tif (*obj == STRUCT_SUB_PEN || *obj == STRUCT_SHIP_YARD ||\n\t//\t\t\t\t\t    *obj == STRUCT_FAKE_PEN || *obj == STRUCT_FAKE_YARD) loco = SPEED_FLOAT;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tDraw the hash-mark cursor:\n\t\t\t\t*/\n\t\t\t\tif (Map.ProximityCheck && Is_Clear_To_Build(loco)) {\n\t\t\t\t\tLogicPage->Draw_Stamp(DisplayClass::TransIconset, 0, x, y, NULL, WINDOW_TACTICAL);\n\t\t\t\t} else {\n\t\t\t\t\tLogicPage->Draw_Stamp(DisplayClass::TransIconset, 2, x, y, NULL, WINDOW_TACTICAL);\n\t\t\t\t}\n\n\t#ifdef SCENARIO_EDITOR\n\t\t\t\tif (Debug_Map && Map.PendingObject) {\n\n\t\t\t\t\tswitch (Map.PendingObject->What_Am_I()) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDraw a template:\n\t\t\t\t\t\t**\t- Compute the icon offset of this cell for this template, using\n\t\t\t\t\t\t**\t  ZoneCell+ZoneOffset to get the upper-left corner of the placement\n\t\t\t\t\t\t**\t  cursor\n\t\t\t\t\t\t**\t- Draw the icon\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RTTI_TEMPLATETYPE:\n\t\t\t\t\t\t\ttptr = (TemplateTypeClass *)Map.PendingObject;\n\t\t\t\t\t\t\tif (tptr->Get_Image_Data()) {\n\t\t\t\t\t\t\t\ticon = (Cell_X(cell) - Cell_X(Map.ZoneCell + Map.ZoneOffset)) +\n\t\t\t\t\t\t\t\t\t(Cell_Y(cell) - Cell_Y(Map.ZoneCell + Map.ZoneOffset)) *\n\t\t\t\t\t\t\t\t\ttptr->Width;\n\t\t\t\t\t\t\t\tLogicPage->Draw_Stamp(tptr->Get_Image_Data(), icon, x, y, NULL, WINDOW_TACTICAL);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDraw an overlay; just use the existing 'OverlayData' even though\n\t\t\t\t\t\t**\tit means nothing.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RTTI_OVERLAYTYPE:\n\t\t\t\t\t\t\tOverlayTypeClass::As_Reference(((OverlayTypeClass *)Map.PendingObject)->Type).Draw_It(x, y, OverlayData);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDraw a smudge\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RTTI_SMUDGETYPE:\n\t\t\t\t\t\t\tSmudgeTypeClass::As_Reference(((SmudgeTypeClass *)Map.PendingObject)->Type).Draw_It(x, y, 0);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t#endif\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDraw the flag if there is one located at this cell.\n\t\t\t*/\n\t\t\tif (IsFlagged) {\n\t\t\t\tvoid const * flag_remap = HouseClass::As_Pointer(Owner)->Remap_Table(false, REMAP_NORMAL);\n\t\t\t\tCC_Draw_Shape(MFCD::Retrieve(\"FLAGFLY.SHP\"), Frame % 14, x+(ICON_PIXEL_W/2), y+(ICON_PIXEL_H/2), WINDOW_TACTICAL, SHAPE_CENTER|SHAPE_GHOST|SHAPE_FADING, flag_remap, DisplayClass::UnitShadow);\n\t\t\t}\n\n\t#ifdef CHEAT_KEYS\n\t\t}\n\t#endif\n\t\tBEnd(BENCH_CELL);\n\t}\n\n#ifdef SORTDRAW\n\tif (objects) {\n\t\tBStart(BENCH_OBJECTS);\n\n\t\t/*\n\t\t**\tBuild a list of objects to draw into a working buffer. There is a\n\t\t**\tbig presumption here -- it is presumed that if the cell is to be\n\t\t**\tredrawn, then all objects in the cell should properly be flagged to\n\t\t**\tbe redrawn as well. Normally, this isn't a problem, but for subs\n\t\t**\tthe IsToDisplay flag MUST REMAIN SET. This is because there is a\n\t\t**\thack overpass after the cells are redrawn so that subs can be\n\t\t**\tredrawn separately.\n\t\t*/\n\t\tObjectClass * optr[20 + ARRAY_SIZE(Overlapper)];\n\t\tint count = 0;\n\t\tObjectClass * object = Cell_Occupier();\n\t\twhile (object != NULL) {\n\t\t\tif (!object->IsActive) break;\n\t\t\toptr[count] = object;\n\t\t\tobject->IsToDisplay = true;\n\t\t\tobject = object->Next;\n\t\t\tcount++;\n\t\t}\n\t\tfor (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\t\tobject = Overlapper[index];\n\t\t\tif (object != NULL && object->IsActive) {\n\t\t\t\tobject->IsToDisplay = true;\n\t\t\t\toptr[count] = object;\n\t\t\t\tcount++;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tSort the object list so that objects will be drawn from\n\t\t**\tback to front.\n\t\t*/\n\t\tswitch (count) {\n\n\t\t\t/*\n\t\t\t**\tIf there are zero or one object, then sorting is\n\t\t\t**\tunnecessary.\n\t\t\t*/\n\t\t\tcase 0:\n\t\t\tcase 1:\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tTwo objects can be sorted with a single compare and swap.\n\t\t\t*/\n\t\t\tcase 2:\n\t\t\t\tif (optr[0]->Sort_Y() > optr[1]->Sort_Y()) {\n\t\t\t\t\tswap(optr[0], optr[1]);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tThree objects can be sorted with three compares and swaps.\n\t\t\t*/\n\t\t\tcase 3:\n\t\t\t\tif (optr[0]->Sort_Y() > optr[2]->Sort_Y()) {\n\t\t\t\t\tswap(optr[0], optr[2]);\n\t\t\t\t}\n\t\t\t\tif (optr[0]->Sort_Y() > optr[1]->Sort_Y()) {\n\t\t\t\t\tswap(optr[0], optr[1]);\n\t\t\t\t}\n\t\t\t\tif (optr[1]->Sort_Y() > optr[2]->Sort_Y()) {\n\t\t\t\t\tswap(optr[1], optr[2]);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tLarge number of objects can be effeciently sorted by using\n\t\t\t**\ta quicksort.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\tqsort(optr, count, sizeof(optr[0]), _ocompare);\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tDraw any objects that happen to be in or overlapping this cell.\n\t\t*/\n\t\tfor (index = 0; index < count; index++) {\n\t\t\tobject = optr[index];\n\t\t\tint xx,yy;\n\t\t\tif (object->IsToDisplay && (!object->Is_Techno() || ((TechnoClass *)object)->Visual_Character() == VISUAL_NORMAL) && Map.Coord_To_Pixel(object->Render_Coord(), xx, yy)) {\n\t\t\t\tif (_Calc_Partial_Window(x, y, xx, yy)) {\n\t\t\t\t\tobject->Draw_It(xx, yy, WINDOW_PARTIAL);\n\t\t\t\t\tif (Debug_Map) {\n\t\t\t\t\t\tobject->IsToDisplay = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tobject->IsToDisplay = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tobject->IsToDisplay = false;\n\t\t\t}\n\t\t}\n\t\tBEnd(BENCH_OBJECTS);\n\t}\n#endif\n\n}\n\n\n/***********************************************************************************************\n * CellClass::Concrete_Calc -- Calculates the concrete icon to use for the cell.               *\n *                                                                                             *\n *    This routine examines the cells around the current one and from this, determines what    *\n *    concrete icon shape to use (if any). The cell data is adjusted and the cell is marked    *\n *    for redraw if the icon changed.                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CellClass::Concrete_Calc(void)\n{\n#ifdef OBSOLETE\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tstatic FacingType _even[5] = {FACING_N, FACING_S, FACING_SW, FACING_W, FACING_NW};\n\tstatic FacingType _odd[5] = {FACING_N, FACING_NE, FACING_E, FACING_SE, FACING_S};\n\tFacingType * ptr;\t\t// Working pointer into adjacent cell list.\n\tint\tindex;\t// Constructed bit index.\n\tint\ticon;\t\t// Icon number.\n\tbool\tisodd;\t// Is this for the odd column?\n\n#define\tOF_N\t0x01\n#define\tOF_NE\t0x02\n#define\tOF_E\t0x04\n#define\tOF_SE\t0x08\n#define\tOF_S\t0x10\n\n#define\tEF_N\t0x01\n#define\tEF_NW\t0x10\n#define\tEF_W\t0x08\n#define\tEF_SW\t0x04\n#define\tEF_S\t0x02\n\n\t/*\n\t**\tDetermine if the even or odd row logic is necessary.\n\t*/\n\tisodd = ((Cell_Number() & 0x01) != 0);\n\n\t/*\n\t**\tFetch correct pointer depending on whether this is for an\n\t**\todd or even row.\n\t*/\n\tptr = (isodd) ? _odd : _even;\n\n\t/*\n\t**\tBuild an index according to the presence of concrete in the special\n\t**\tadjacent cells. This is a short list of adjacent cell flags since\n\t**\tonly 5 adjacent cells need to be examined. The choice of which 5\n\t**\tdepends on whether this is for an even or odd column.\n\t*/\n\tindex = 0;\n\tfor (int i = 0; i < (sizeof(_even)/sizeof(_even[0])); i++) {\n\t\tCellClass & cellptr = Adjacent_Cell(*ptr++);\n\n\t\tif (cellptr.Overlay == OVERLAY_CONCRETE) {\n\t\t\tindex |= (1<<i);\n\t\t}\n\t}\n\n\t/*\n\t**\tSpecial logic occurs for cells that are concrete filled.\n\t*/\n\tif (Overlay == OVERLAY_CONCRETE) {\n\n\t\t/*\n\t\t**\tProcess the index value and place the appropriate concrete icon\n\t\t**\tin the cell.\n\t\t*/\n\t\tif (isodd) {\n\t\t\tswitch (index) {\n\t\t\t\tcase OF_NE:\n\t\t\t\tcase OF_N|OF_NE:\n\t\t\t\tcase OF_E|OF_N:\n\t\t\t\tcase OF_E|OF_NE:\n\t\t\t\tcase OF_N|OF_NE|OF_E:\n\t\t\t\tcase OF_S|OF_N|OF_NE:\n\t\t\t\t\ticon = C_RIGHT_UP;\t\t// right - up\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OF_SE:\n\t\t\t\tcase OF_E|OF_SE:\n\t\t\t\tcase OF_S|OF_SE:\n\t\t\t\tcase OF_S|OF_E:\n\t\t\t\tcase OF_S|OF_SE|OF_E:\n\t\t\t\tcase OF_S|OF_SE|OF_N:\n\t\t\t\t\ticon = C_RIGHT_DOWN;\t\t// right - down\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OF_SE|OF_NE:\n\t\t\t\tcase OF_SE|OF_NE|OF_N:\n\t\t\t\tcase OF_SE|OF_NE|OF_S:\n\t\t\t\tcase OF_SE|OF_NE|OF_S|OF_N:\n\t\t\t\tcase OF_SE|OF_E|OF_N:\n\t\t\t\tcase OF_SE|OF_E|OF_NE|OF_N:\n\t\t\t\tcase OF_S|OF_E|OF_N:\n\t\t\t\tcase OF_S|OF_E|OF_NE:\n\t\t\t\tcase OF_S|OF_E|OF_NE|OF_N:\n\t\t\t\tcase OF_S|OF_SE|OF_E|OF_N:\n\t\t\t\tcase OF_S|OF_SE|OF_E|OF_NE|OF_N:\n\t\t\t\tcase OF_S|OF_SE|OF_E|OF_NE:\n\t\t\t\t\ticon = C_RIGHT_UPDOWN;\t\t// right - up - down\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\ticon = C_RIGHT;\t\t// right\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\tswitch (index) {\n\t\t\t\tcase EF_NW:\n\t\t\t\tcase EF_NW|EF_N:\n\t\t\t\tcase EF_W|EF_N:\n\t\t\t\tcase EF_NW|EF_W|EF_N:\n\t\t\t\tcase EF_NW|EF_W:\n\t\t\t\tcase EF_NW|EF_S|EF_N:\n\t\t\t\t\ticon = C_LEFT_UP;\t\t// left - up\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase EF_SW:\n\t\t\t\tcase EF_SW|EF_S:\n\t\t\t\tcase EF_W|EF_S:\n\t\t\t\tcase EF_W|EF_SW|EF_S:\n\t\t\t\tcase EF_W|EF_SW:\n\t\t\t\tcase EF_SW|EF_S|EF_N:\n\t\t\t\t\ticon = C_LEFT_DOWN;\t\t// left - down\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase EF_NW|EF_SW:\n\t\t\t\tcase EF_NW|EF_SW|EF_N:\n\t\t\t\tcase EF_NW|EF_SW|EF_S:\n\t\t\t\tcase EF_NW|EF_SW|EF_S|EF_N:\n\t\t\t\tcase EF_W|EF_S|EF_N:\n\t\t\t\tcase EF_W|EF_SW|EF_N:\n\t\t\t\tcase EF_W|EF_SW|EF_S|EF_N:\n\t\t\t\tcase EF_NW|EF_W|EF_S:\n\t\t\t\tcase EF_NW|EF_W|EF_S|EF_N:\n\t\t\t\tcase EF_NW|EF_W|EF_SW|EF_S|EF_N:\n\t\t\t\tcase EF_NW|EF_W|EF_SW|EF_N:\n\t\t\t\tcase EF_NW|EF_W|EF_SW|EF_S:\n\t\t\t\t\ticon = C_LEFT_UPDOWN;\t\t// left - up - down\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\ticon = C_LEFT;\t\t// left\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\t// Presume that no concrete piece is needed.\n\t\ticon = C_NONE;\n\t\tif (isodd) {\n\t\t\tindex &= ~(OF_NE|OF_SE);\t\t// Ignore diagonals.\n\t\t\tswitch (index) {\n\t\t\t\tcase OF_N|OF_E:\n\t\t\t\t\ticon = C_UP_RIGHT;\t\t// up right\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OF_E|OF_S:\n\t\t\t\t\ticon = C_DOWN_RIGHT;\t\t// down right\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OF_N|OF_E|OF_S:\n\t\t\t\t\ticon = C_UPDOWN_RIGHT;\t// up/down right\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\tindex &= ~(EF_NW|EF_SW);\t\t// Ignore diagonals.\n\t\t\tswitch (index) {\n\t\t\t\tcase EF_N|EF_W:\n\t\t\t\t\ticon = C_UP_LEFT;\t\t// up left\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase EF_W|EF_S:\n\t\t\t\t\ticon = C_DOWN_LEFT;\t\t// down left\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase EF_N|EF_W|EF_S:\n\t\t\t\t\ticon = C_UPDOWN_LEFT;\t\t// up/down left\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf any kind of fixup piece is needed, then add concrete\n\t\t**\tto this location RECURSIVELY!\n\t\t*/\n\t\tif (icon != C_NONE) {\n\t\t\tOverlayTypeClass::As_Reference(OVERLAY_CONCRETE).Create_And_Place(Cell_Number());\n\t\t\ticon = C_NONE;\n\t\t}\n\n\t}\n\n\t/*\n\t**\tUpdate the icon on the map.\n\t*/\n\tif (icon != C_NONE && OverlayData != icon) {\n\t\tOverlayData = icon;\n\t\t//Array[cell].Base = 0;\n\t\tRedraw_Objects();\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * CellClass::Wall_Update -- Updates the imagery for wall objects in cell.                     *\n *                                                                                             *\n *    This routine will examine the cell and the adjacent cells to determine what the wall     *\n *    should look like with the cell. It will then update the wall's imagery value and flag    *\n *    the cell to be redrawn if necessary. This routine should be called whenever the wall     *\n *    or an adjacent wall is created or destroyed.                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *   09/19/1994 BWG : Updated to handle partially-damaged walls.                               *\n *=============================================================================================*/\nvoid CellClass::Wall_Update(void)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tstatic FacingType _offsets[5] = {FACING_N, FACING_E, FACING_S, FACING_W, FACING_NONE};\n\n\tfor (unsigned index = 0; index < (sizeof(_offsets)/sizeof(_offsets[0])); index++) {\n\t\tCellClass & newcell = Adjacent_Cell(_offsets[index]);\n\n\t\tif (newcell.Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(newcell.Overlay).IsWall) {\n\t\t\tint\ticon = 0;\n\n\t\t\t/*\n\t\t\t**\tBuild the icon number according to walls located in the adjacent\n\t\t\t**\tcells.\n\t\t\t*/\n\t\t\tfor (unsigned i = 0; i < 4; i++) {\n\t\t\t\tif (newcell.Adjacent_Cell(_offsets[i]).Overlay == newcell.Overlay) {\n\t\t\t\t\ticon |= 1 << i;\n\t\t\t\t}\n\t\t\t}\n\t\t\tnewcell.OverlayData = (newcell.OverlayData & 0xFFF0) | icon;\n\n\t\t\t/*\n\t\t\t**\tHandle special cases for the incomplete damaged wall sets. If a damage stage\n\t\t\t**\tis calculated, but there is no artwork for it, then consider the wall to be\n\t\t\t**\tcompletely destroyed.\n\t\t\t*/\n\t\t\tif (newcell.Overlay == OVERLAY_BRICK_WALL && newcell.OverlayData == 48) {\n\t\t\t\tnewcell.Overlay = OVERLAY_NONE;\n\t\t\t\tnewcell.OverlayData = 0;\n\t\t\t\tDetach_This_From_All(::As_Target(newcell.Cell_Number()), true);\n\t\t\t}\n\t\t\tif (newcell.Overlay == OVERLAY_SANDBAG_WALL && newcell.OverlayData == 16) {\n\t\t\t\tnewcell.Overlay = OVERLAY_NONE;\n\t\t\t\tnewcell.OverlayData = 0;\n\t\t\t\tDetach_This_From_All(::As_Target(newcell.Cell_Number()), true);\n\t\t\t}\n\t\t\tif (newcell.Overlay == OVERLAY_CYCLONE_WALL && newcell.OverlayData == 32) {\n\t\t\t\tnewcell.Overlay = OVERLAY_NONE;\n\t\t\t\tnewcell.OverlayData = 0;\n\t\t\t\tDetach_This_From_All(::As_Target(newcell.Cell_Number()), true);\n\t\t\t}\n\t\t\tif (newcell.Overlay == OVERLAY_FENCE && (newcell.OverlayData == 16 || newcell.OverlayData == 32)) {\n\t\t\t\tnewcell.Overlay = OVERLAY_NONE;\n\t\t\t\tnewcell.OverlayData = 0;\n\t\t\t\tDetach_This_From_All(::As_Target(newcell.Cell_Number()), true);\n\t\t\t}\n\t\t\tif (newcell.Overlay == OVERLAY_BARBWIRE_WALL && newcell.OverlayData == 16) {\n\t\t\t\tnewcell.Overlay = OVERLAY_NONE;\n\t\t\t\tnewcell.OverlayData = 0;\n\t\t\t\tDetach_This_From_All(::As_Target(newcell.Cell_Number()), true);\n\t\t\t}\n\n\t\t\tnewcell.Recalc_Attributes();\n\t\t\tnewcell.Redraw_Objects();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Coord -- Returns the coordinate of this cell.                               *\n *                                                                                             *\n *    This support function will determine the coordinate of this cell and return it.          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with coordinate value of cell.                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE CellClass::Cell_Coord(void) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\treturn(::Cell_Coord(Cell_Number()));\n}\n\n\n/***********************************************************************************************\n * CellClass::Reduce_Tiberium -- Reduces the tiberium in the cell by the amount specified.     *\n *                                                                                             *\n *    This routine will lower the tiberium level in the cell. It is used by the harvesting     *\n *    process as well as by combat damage to the tiberium fields.                              *\n *                                                                                             *\n * INPUT:   levels   -- The number of levels to reduce the tiberium.                           *\n *                                                                                             *\n * OUTPUT:  bool; Was the tiberium level reduced by at least one level?                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CellClass::Reduce_Tiberium(int levels)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tint reducer = 0;\n\n\tif (levels > 0 && Land == LAND_TIBERIUM) {\n\t\tif (OverlayData+1 > levels) {\n\t\t\tOverlayData -= levels;\n\t\t\treducer = levels;\n\t\t} else {\n\t\t\tOverlay = OVERLAY_NONE;\n\t\t\treducer = OverlayData;\n\t\t\tOverlayData = 0;\n\t\t\tRecalc_Attributes();\n\t\t}\n\t}\n\treturn(reducer);\n}\n\n\n/***********************************************************************************************\n * CellClass::Reduce_Wall -- Damages a wall, if damage is high enough.                         *\n *                                                                                             *\n *    This routine will change the wall shape used for a wall if it's damaged.                 *\n *                                                                                             *\n * INPUT:   damage   -- The number of damage points the wall was hit with. If this value is    *\n *                      -1, then the entire wall at this cell will be destroyed.               *\n *                                                                                             *\n * OUTPUT:  bool; Was the wall destroyed?                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/15/1995 BWG : Created.                                                                 *\n *   03/19/1995 JLB : Updates cell information if wall was destroyed.                          *\n *   10/06/1996 JLB : Updates zone as necessary.                                               *\n *=============================================================================================*/\nint CellClass::Reduce_Wall(int damage)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tif (Overlay != OVERLAY_NONE) {\n\t\tbool destroyed = false;\n\t\tOverlayTypeClass const & wall = OverlayTypeClass::As_Reference(Overlay);\n\n\t\tif (wall.IsWall) {\n\n\t\t\t/*\n\t\t\t**\tIf the damage was great enough to ensure wall destruction, reduce the wall by one\n\t\t\t**\tlevel (no more). Otherwise determine wall reduction based on a percentage chance\n\t\t\t**\tproportional to the damage received and the wall's strength.\n\t\t\t*/\n\t\t\tif (damage == -1 || damage >= wall.DamagePoints) {\n\t\t\t\tdestroyed = true;\n\t\t\t} else {\n\t\t\t\tdestroyed = Random_Pick(0, wall.DamagePoints) < damage;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the wall is destroyed, destroy it and check for any adjustments to\n\t\t\t**\tadjacent walls.\n\t\t\t*/\n\t\t\tif (destroyed) {\n\t\t\t\tOverlayData+=16;\n\t\t\t\tif (damage == -1 ||\n\t\t\t\t\t(OverlayData>>4) >= wall.DamageLevels ||\n\t\t\t\t\t((OverlayData>>4) == wall.DamageLevels-1 && (OverlayData & 0xF)==0)\t) {\n\n\t\t\t\t\tOwner = HOUSE_NONE;\n\t\t\t\t\tOverlay = OVERLAY_NONE;\n\t\t\t\t\tOverlayData = 0;\n\t\t\t\t\tRecalc_Attributes();\n\t\t\t\t\tRedraw_Objects();\n\t\t\t\t\tAdjacent_Cell(FACING_N).Wall_Update();\n\t\t\t\t\tAdjacent_Cell(FACING_W).Wall_Update();\n\t\t\t\t\tAdjacent_Cell(FACING_S).Wall_Update();\n\t\t\t\t\tAdjacent_Cell(FACING_E).Wall_Update();\n\t\t\t\t\tDetach_This_From_All(As_Target());\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThe zone calculation changes now for non-crushable zone sensitive\n\t\t\t\t\t**\ttravellers.\n\t\t\t\t\t*/\n\t\t\t\t\tif (wall.IsCrushable) {\n\t\t\t\t\t\tMap.Zone_Reset(MZONEF_NORMAL);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMap.Zone_Reset(MZONEF_CRUSHER|MZONEF_NORMAL);\n\t\t\t\t\t}\n\t\t\t\t\treturn(true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CellClass::Spot_Index -- returns cell sub-coord index for given COORDINATE                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      coord      COORDINATE to compute index for                                             *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      index into StoppingCoord that's closest to this coord                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/21/1994 BR : Created.                                                                  *\n *   12/10/1994 JLB : Uses alternate sub-position algorithm.                                   *\n *=============================================================================================*/\nint CellClass::Spot_Index(COORDINATE coord)\n{\n\tCOORDINATE rel = Coord_Fraction(coord);\t\t// Sub coordinate value within cell.\n\n\t/*\n\t**\tIf the coordinate is close enough to the center of the cell, then return\n\t**\tthe center position index.\n\t*/\n\tif (Distance(rel, (COORDINATE)0x00800080L) < 60) {\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tSince the center cell position has been eliminated, a simple comparison\n\t**\tas related to the center of the cell can be used to determine the sub\n\t**\tposition. Take advantage of the fact that the sub positions are organized\n\t**\tfrom left to right, top to bottom.\n\t*/\n\tint index = 0;\n\tif (Coord_X(rel) > 0x80) index |= 0x01;\n\tif (Coord_Y(rel) > 0x80) index |= 0x02;\n\treturn(index+1);\n}\n\n\n/***********************************************************************************************\n * CellClass::Closest_Free_Spot -- returns free spot closest to given coord                    *\n *                                                                                             *\n * Similar to the CellClass::Free_Spot; this routine finds the spot in                         *\n * the cell closest to the given coordinate, and returns the COORDINATE of                     *\n * that spot if it's available, NULL if it's not.                                              *\n *                                                                                             *\n * INPUT:                                                                                      *\n *  coord   coordinate to check (only sub cell position examined)                              *\n *                                                                                             *\n *          any   -- If only the closest spot is desired regardless of whether it is free or   *\n *                   not, then this parameter will be true.                                    *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *  COORDINATE of free spot, NULL if none. The coordinate return value does not alter the cell *\n *             coordinate data portions of the coordinate passed in. Only the lower sub-cell   *\n *             data is altered.                                                                *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *  none.                                                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/08/1994 BR : Created.                                                                  *\n *   12/10/1994 JLB : Picks best of closest stopping positions.                                *\n *   12/21/1994 JLB : Adds a mix-up factor if center location is occupied.                     *\n *=============================================================================================*/\nCOORDINATE CellClass::Closest_Free_Spot(COORDINATE coord, bool any) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tint spot_index = Spot_Index(coord);\n\n\t/*\n\t**\tThis precalculated sequence table records the closest spots to any given spot. Sequential\n\t**\texamination of these spots for availability ensures that the closest available one is\n\t**\tdiscovered first.\n\t*/\n\tstatic unsigned char _sequence[5][4] = {\n\t\t{1,2,3,4},\n\t\t{0,2,3,4},\n\t\t{0,1,4,3},\n\t\t{0,1,4,2},\n\t\t{0,2,3,1}\n\t};\n\n\t/*\n\t**\tIn the case of the center coordinate being requested, but is occupied, then all other\n\t**\tsublocations are equidistant. Instead of picking a static sequence of examination, the\n\t**\torder is mixed up by way of this table.\n\t*/\n\tstatic unsigned char _alternate[4][4] = {\n\t\t{1,2,3,4},\n\t\t{2,3,4,1},\n\t\t{3,4,1,2},\n\t\t{4,1,2,3},\n\t};\n\tcoord = Coord_Whole(coord);\n\n\t/*\n\t**\tCells occupied by buildings or vehicles don't have any free spots.\n\t*/\n\tif (!any && (Flag.Occupy.Vehicle || Flag.Occupy.Monolith)) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tIf just the nearest position is desired regardless of whether occupied or not,\n\t**\tthen just return with the stopping coordinate value.\n\t*/\n\tif (any || Is_Spot_Free(spot_index)) {\n\t\treturn(Coord_Add(coord, StoppingCoordAbs[spot_index]));\n\t}\n\n\t/*\n\t**\tScan through all available sub-locations in the cell in order to determine\n\t**\tthe closest one to the coordinate requested. Use precalculated table so that\n\t**\twhen the first free position is found, bail.\n\t*/\n\tunsigned char * sequence;\n\tif (spot_index == 0) {\n\t\tsequence = &_alternate[Random_Pick(0, 3)][0];\n\t} else {\n\t\tsequence = &_sequence[spot_index][0];\n\t}\n\tfor (int index = 0; index < 4; index++) {\n\t\tint pos = *sequence++;\n\n\t\tif (Is_Spot_Free(pos)) {\n\t\t\treturn(Coord_Add(coord, StoppingCoordAbs[pos]));\n\t\t}\n\t}\n\n\t/*\n\t**\tNo free spot could be found so return a NULL coordinate.\n\t*/\n\treturn(0x00000000L);\n}\n\n\n/***********************************************************************************************\n * CellClass::Clear_Icon -- Calculates what the clear icon number should be.                   *\n *                                                                                             *\n *    This support routine will determine what the clear icon number would be for the cell.    *\n *    The icon number is determined by converting the cell number into an index into a         *\n *    lookup table. This yields what appears to be a randomized map without the necessity of   *\n *    generating and recording randomized map numbers.                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the icon number for clear terrain if it were displayed at the         *\n *          cell.                                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *   06/09/1995 JLB : Uses 16 entry scramble algorithm.                                        *\n *=============================================================================================*/\nint CellClass::Clear_Icon(void) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tCELL cell = Cell_Number();\n\treturn((Cell_X(cell) & 0x03) | ((Cell_Y(cell) & 0x03) << 2));\n//\treturn((cell & 0x03) | ((unsigned(cell)>>5) & 0x0C));\n}\n\n\n/***********************************************************************************************\n * CellClass::Incoming -- Causes objects in cell to \"run for cover\".                           *\n *                                                                                             *\n *    This routine is called whenever a great, but slow moving, threat is presented to the     *\n *    occupants of a cell. The occupants will, in most cases, stop what they are doing and     *\n *    try to get out of the way.                                                               *\n *                                                                                             *\n * INPUT:   threat      -- The coordinate source of the threat.                                *\n *                                                                                             *\n *          forced      -- If this threat is so major that the occupants should stop what      *\n *                         they are doing, then this parameter should be set to true.          *\n *                                                                                             *\n *          nokidding   -- Override the scatter to also affect human controlled objects.       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/10/1995 JLB : Created.                                                                 *\n *   08/02/1996 JLB : Added the \"nokidding\" parameter.                                         *\n *=============================================================================================*/\nvoid CellClass::Incoming(COORDINATE threat, bool forced, bool nokidding)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tObjectClass * object = NULL;\n\n\tobject = Cell_Occupier();\n\twhile (object != NULL) {\n\n\t\t/*\n\t\t**\tSpecial check to make sure that friendly units never scatter.\n\t\t*/\n\t\tif (nokidding || Rule.IsScatter || (object->Is_Techno() && ((TechnoClass *)object)->House->IQ >= Rule.IQScatter)) {\n\t\t\tobject->Scatter(threat, forced, nokidding);\n\t\t}\n\t\tobject = object->Next;\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Adjacent_Cell -- Determines the adjacent cell according to facing.               *\n *                                                                                             *\n *    Use this routine to return a reference to the adjacent cell in the direction specified.  *\n *                                                                                             *\n * INPUT:   face  -- The direction to use when determining the adjacent cell.                  *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the adjacent cell.                                     *\n *                                                                                             *\n * WARNINGS:   If the facing value is invalid, then a reference to the same cell is returned.  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCellClass const & CellClass::Adjacent_Cell(FacingType face) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tif ((unsigned)face >= FACING_COUNT) {\n\t\treturn(*this);\n\t}\n\n\tCellClass const * ptr = this + AdjacentCell[face];\n\tif ((unsigned)ptr->Cell_Number() > MAP_CELL_TOTAL) return(*this);\n\treturn(*ptr);\n}\n\n\n/***************************************************************************\n * CellClass::Adjust_Threat -- Allows adjustment of threat at cell level   *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/24/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid CellClass::Adjust_Threat(HousesType house, int threat_value)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tint region = Map.Cell_Region(Cell_Number());\n\n\tfor (HousesType lp = HOUSE_FIRST; lp < HOUSE_COUNT; lp ++) {\n\t\tif (lp == house) continue;\n\n\t\tHouseClass * house_ptr = HouseClass::As_Pointer(lp);\n\t\tif (house_ptr && (!house_ptr->IsHuman || !house_ptr->Is_Ally(house))) {\n\t\t\thouse_ptr->Adjust_Threat(region, threat_value);\n\t\t}\n\t}\n\tif (Debug_Threat) {\n\t\tMap.Flag_To_Redraw(true);\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Tiberium_Adjust -- Adjust the look of the Tiberium for smoothing purposes.       *\n *                                                                                             *\n *    This routine will adjust the level of the Tiberium in the cell so that it will           *\n *    smoothly blend with the adjacent Tiberium. This routine should only be called for        *\n *    new Tiberium cells. Existing cells that contain Tiberium follow a different growth       *\n *    pattern.                                                                                 *\n *                                                                                             *\n * INPUT:   pregame  -- Is this a pregame call? Such a call will mixup the Tiberium overlay    *\n *                      used.                                                                  *\n *                                                                                             *\n * OUTPUT:  Returns with the added Tiberium value that is now available for harvesting.        *\n *                                                                                             *\n * WARNINGS:   The return value is only valid for the initial placement. Tiberium growth will  *\n *             increase the net worth of the existing Tiberium.                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/16/1995 JLB : Created.                                                                 *\n *   02/20/1996 JLB : Takes into account the ore type.                                         *\n *=============================================================================================*/\nlong CellClass::Tiberium_Adjust(bool pregame)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\tif (Overlay != OVERLAY_NONE) {\n\t\tif (OverlayTypeClass::As_Reference(Overlay).Land == LAND_TIBERIUM) {\n\t\t\tstatic int _adj[9] = {0,1,3,4,6,7,8,10,11};\n\t\t\tstatic int _adjgem[9] = {0,0,0,1,1,1,2,2,2};\n\t\t\tint\tcount = 0;\n\n\t\t\t/*\n\t\t\t**\tMixup the Tiberium overlays so that they don't look the same.\n\t\t\t**\tSince the type of ore is known, also record the nominal\n\t\t\t**\tvalue per step of that ore type.\n\t\t\t*/\n\t\t\tbool gems = false;\n\t\t\tint value = 0;\n\t\t\tif (pregame) {\n\t\t\t\tswitch (Overlay) {\n\t\t\t\t\tcase OVERLAY_GOLD1:\n\t\t\t\t\tcase OVERLAY_GOLD2:\n\t\t\t\t\tcase OVERLAY_GOLD3:\n\t\t\t\t\tcase OVERLAY_GOLD4:\n\t\t\t\t\t\tvalue = Rule.GoldValue;\n\t\t\t\t\t\tOverlay = Random_Pick(OVERLAY_GOLD1, OVERLAY_GOLD4);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase OVERLAY_GEMS1:\n\t\t\t\t\tcase OVERLAY_GEMS2:\n\t\t\t\t\tcase OVERLAY_GEMS3:\n\t\t\t\t\tcase OVERLAY_GEMS4:\n\t\t\t\t\t\tgems = true;\n\t\t\t\t\t\tvalue = Rule.GemValue*4;\n\t\t\t\t\t\tOverlay = Random_Pick(OVERLAY_GEMS1, OVERLAY_GEMS4);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAdd up all adjacent cells that contain tiberium.\n\t\t\t** (Skip those cells which aren't on the map)\n\t\t\t*/\n\t\t\tfor (FacingType face = FACING_FIRST; face < FACING_COUNT; face++) {\n\t\t\t\tCellClass & adj = Adjacent_Cell(face);\n\n\t\t\t\tif (adj.Overlay != OVERLAY_NONE &&\n\t\t\t\t\tOverlayTypeClass::As_Reference(adj.Overlay).Land == LAND_TIBERIUM) {\n\t\t\t\t\tcount++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (gems) {\n\t\t\t\tOverlayData = _adjgem[count];\n\t\t\t\tOverlayData = min(OverlayData, 2);\n\t\t\t} else {\n\t\t\t\tOverlayData = _adj[count];\n\t\t\t}\n\t\t\treturn((OverlayData+1) * value);\n\t\t}\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * CellClass::Goodie_Check -- Performs crate discovery logic.                                  *\n *                                                                                             *\n *    Call this routine whenever an object enters a cell. It will check for the existence      *\n *    of a crate and generate any \"goodie\" it might contain.                                   *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that is triggering this crate.                   *\n *                                                                                             *\n * OUTPUT:  Can the object continue to enter this cell? A false return value means that the    *\n *          cell is now occupied and must not be entered.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1995 JLB : Created.                                                                 *\n *   07/08/1995 JLB : Added a bunch of goodies to the crates.                                  *\n *   06/17/1996 JLB : Revamped for Red Alert                                                   *\n *=============================================================================================*/\nbool CellClass::Goodie_Check(FootClass * object)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tif (object != NULL && Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(Overlay).IsCrate) {\n\t\tbool force_mcv = false;\n\t\tint force_money = 0;\n\t\tint damage;\n\t\tCOORDINATE coord;\n\n\t\t/*\n\t\t**\tDetermine the total number of shares for all the crate powerups. This is used as\n\t\t**\tthe base pool to determine the odds from.\n\t\t*/\n\t\tint total_shares = 0;\n\t\tfor (int index = CRATE_FIRST; index < CRATE_COUNT; index++) {\n\t\t\ttotal_shares += CrateShares[index];\n\t\t}\n\n\t\t/*\n\t\t**\tPick a random crate powerup according to the shares allotted to each powerup.\n\t\t**\tIn solo play, the bonus item is dependant upon the rules control.\n\t\t*/\n\t\tCrateType powerup;\n\t\tif (Session.Type == GAME_NORMAL) {\n\n\t\t\t/*\n\t\t\t**\tSolo play has money amount determined by rules.ini file.\n\t\t\t*/\n\t\t\tforce_money = Rule.SoloCrateMoney;\n\n\t\t\tif (Overlay == OVERLAY_STEEL_CRATE) {\n\t\t\t\tpowerup = Rule.SilverCrate;\n\t\t\t}\n\n\t\t\tif (Overlay == OVERLAY_WOOD_CRATE) {\n\t\t\t\tpowerup = Rule.WoodCrate;\n\t\t\t}\n\n\t\t\tif (Overlay == OVERLAY_WATER_CRATE) {\n//Mono_Printf(\"%d-%s.\\n\", __LINE__, __FILE__);\n\t\t\t\tpowerup = Rule.WaterCrate;\n\t\t\t}\n\n\t\t} else {\n\t\t\tint pick = Random_Pick(1, total_shares);\n\n\t\t\tint share_count = 0;\n\t\t\tfor (powerup = CRATE_FIRST; powerup < CRATE_COUNT; powerup++) {\n\t\t\t\tshare_count += CrateShares[powerup];\n\t\t\t\tif (pick <= share_count) break;\n\t\t\t}\n\t\t\tassert(powerup != CRATE_COUNT);\n\n\t\t\t/*\n\t\t\t**\tDepending on what was picked, there might be an alternate goodie if the selected\n\t\t\t**\tgoodie would have no effect.\n\t\t\t*/\n\t\t\tswitch (powerup) {\n\t\t\t\tcase CRATE_UNIT:\n\t\t\t\t\tif (object->House->CurUnits > 50) powerup = CRATE_MONEY;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRATE_SQUAD:\n\t\t\t\t\tif (object->House->CurInfantry > 100) powerup = CRATE_MONEY;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRATE_DARKNESS:\n\t\t\t\t\tif (object->House->IsGPSActive) powerup = CRATE_MONEY;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRATE_ARMOR:\n\t\t\t\t\tif (object->ArmorBias != 1) powerup = CRATE_MONEY;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRATE_SPEED:\n\t\t\t\t\tif (object->SpeedBias != 1 || object->What_Am_I() == RTTI_AIRCRAFT) powerup = CRATE_MONEY;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRATE_FIREPOWER:\n\t\t\t\t\tif (object->FirepowerBias != 1 || !object->Is_Weapon_Equipped()) powerup = CRATE_MONEY;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRATE_REVEAL:\n\t\t\t\t\tif (object->House->IsVisionary) {\n\t\t\t\t\t\tif (object->House->IsGPSActive) {\n\t\t\t\t\t\t\tpowerup = CRATE_MONEY;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tpowerup = CRATE_DARKNESS;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRATE_CLOAK:\n\t\t\t\t\tif (object->IsCloakable) powerup = CRATE_MONEY;\n\t\t\t\t\tbreak;\n\n//\t\t\t\tcase CRATE_HEAL_BASE:\n//\t\t\t\t\tif (object->House->BScan == 0) powerup = CRATE_UNIT;\n\n\t\t\t\tcase CRATE_MONEY:\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRATE_TIMEQUAKE:\n\t\t\t\t\t/*\n\t\t\t\t\t** For the time quake crate, scan through and count up all the\n\t\t\t\t\t** units (and infantry and ships and aircraft) and if either\n\t\t\t\t\t** side has very few, allow the time quake.  Otherwise,\n\t\t\t\t\t** change the crate to money or something.  Only do this for\n\t\t\t\t\t** multiplay - for solo play, they get what they get.  First,\n\t\t\t\t\t** check for time - the chance for getting a time quake crate\n\t\t\t\t\t** should be very very low when they first start the mission,\n\t\t\t\t\t** but as time goes on the chance goes up.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Session.Type != GAME_NORMAL) {\n\t\t\t\t\t\tint i,ucount;\n\t\t\t\t\t\tint minunits = 1000;\n\t\t\t\t\t\tbool found = false;\n\t\t\t\t\t\tunsigned long minutes = (Score.ElapsedTime / TIMER_MINUTE);\n\t\t\t\t\t\tif (minutes > 100) minutes = 100;\n\t\t\t\t\t\tif (Random_Pick(0,100-(int)minutes) == 0) {\n\t\t\t\t\t\t\tfor (i=0; i < (Session.Players.Count() + Session.Options.AIPlayers); i++) {\n\t\t\t\t\t\t\t\tucount = 0;\n\t\t\t\t\t\t\t\tHouseClass * hptr = Houses.Ptr(i + HOUSE_MULTI1);\n\t\t\t\t\t\t\t\tif (hptr != NULL && !hptr->IsDefeated) {\n\t\t\t\t\t\t\t\t\tint j;\n\t\t\t\t\t\t\t\t\tfor( j=0; j < UNIT_COUNT; j++) {\n\t\t\t\t\t\t\t\t\t\tucount += hptr->QuantityU(j);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tfor( j=0; j < INFANTRY_COUNT; j++) {\n\t\t\t\t\t\t\t\t\t\tucount += hptr->QuantityI(j);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tfor( j=0; j < AIRCRAFT_COUNT; j++) {\n\t\t\t\t\t\t\t\t\t\tucount += hptr->QuantityA(j);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tfor( j=0; j < VESSEL_COUNT; j++) {\n\t\t\t\t\t\t\t\t\t\tucount += hptr->QuantityV(j);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tint bcount = 0;\n\t\t\t\t\t\t\t\t\tfor( j=0; j < STRUCT_COUNT; j++) {\n\t\t\t\t\t\t\t\t\t\tbcount += hptr->QuantityB(j);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tucount += bcount/2;\t// weight buildings less\n\t\t\t\t\t\t\t\t\tminunits = min(minunits, ucount);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (Random_Pick(0, minunits) == minunits) {\n\t\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!found) {\n\t\t\t\t\t\t\tpowerup = CRATE_MONEY;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/*\n\t\t\t**\tPossibly force it to be an MCV if there is\n\t\t\t**\tsufficient money and no buildings left.\n\t\t\t*/\n\t\t\tif (\tobject->House->BScan == 0 &&\n\t\t\t\t\tobject->House->Available_Money() > ( (BuildingTypeClass::As_Reference(STRUCT_REFINERY).Cost + BuildingTypeClass::As_Reference(STRUCT_POWER).Cost) * object->House->CostBias) &&\n\t\t\t\t\tSession.Options.Bases &&\n\t\t\t\t\t!(object->House->UScan & UNITF_MCV)) {\n\t\t\t\tpowerup = CRATE_UNIT;\n\t\t\t\tforce_mcv = true;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the powerup is money but there is insufficient money to build a refinery but there is a construction\n\t\t\t**\tyard available, then force the money to be enough to rebuild the refinery.\n\t\t\t*/\n\t\t\tif (powerup == CRATE_MONEY && (object->House->BScan & (STRUCTF_CONST|STRUCTF_REFINERY)) == STRUCTF_CONST &&\n\t\t\t\t\t\tobject->House->Available_Money() < BuildingTypeClass::As_Reference(STRUCT_REFINERY).Cost * object->House->CostBias) {\n\n\t\t\t\tforce_money = BuildingTypeClass::As_Reference(STRUCT_REFINERY).Cost * object->House->CostBias;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSpecial override for water crates so that illegal goodies items\n\t\t\t**\twon't appear.\n\t\t\t*/\n\t\t\tif (Overlay == OVERLAY_WATER_CRATE) {\n\t\t\t\tswitch (powerup) {\n\t\t\t\t\tcase CRATE_UNIT:\n\t\t\t\t\tcase CRATE_SQUAD:\n\t\t\t\t\t\tpowerup = CRATE_MONEY;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Keep track of the number of each type of crate found\n\t\t*/\n\t\tif (Session.Type == GAME_INTERNET) {\n\t\t\tobject->House->TotalCrates->Increment_Unit_Total(powerup);\n\t\t}\n\n\t\t/*\n\t\t**\tRemove the crate from the map.\n\t\t*/\n\t\tMap.Remove_Crate(Cell_Number());\n//\t\tMap[Cell_Number()].Overlay = OVERLAY_NONE;\n\n\t\tif (Session.Type != GAME_NORMAL && Rule.IsMPCrates) {\n\t\t\tMap.Place_Random_Crate();\n\t\t}\n\n\t\t/*\n\t\t**\tGenerate any corresponding animation associated with this crate powerup.\n\t\t*/\n\t\tif (CrateAnims[powerup] != ANIM_NONE) {\n\t\t\tnew AnimClass(CrateAnims[powerup], Cell_Coord());\n\t\t}\n\n\t\t/*\n\t\t**\tCreate the effect requested.\n\t\t*/\n\t\tbool tospeak = false;\n\t\tswitch (powerup) {\n\t\t\tcase CRATE_TIMEQUAKE:\n\t\t\t\tTimeQuake = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tGive the player money.\n\t\t\t*/\n\t\t\tcase CRATE_MONEY:\ncrate_money:\n\t\t\t\tif (force_money > 0) {\n\t\t\t\t\tobject->House->Refund_Money(force_money);\n\t\t\t\t} else {\n\t\t\t\t\tobject->House->Refund_Money(Random_Pick(CrateData[powerup], CrateData[powerup]+900));\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tShroud the world in blackness.\n\t\t\t*/\n\t\t\tcase CRATE_DARKNESS:\n\t\t\t\tif (object->House == PlayerPtr) {\n\t\t\t\t\tMap.Shroud_The_Map();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tReveal the entire map.\n\t\t\t*/\n\t\t\tcase CRATE_REVEAL:\n\t\t\t\tobject->House->IsVisionary = true;\n\t\t\t\tif (object->House == PlayerPtr) {\n\t\t\t\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\t\t\tMap.Map_Cell(cell, PlayerPtr);\n\t\t\t\t\t}\n\t\t\t\t\tMap.Flag_To_Redraw(true);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tTry to create a unit where the crate was.\n\t\t\t*/\n\t\t\tcase CRATE_UNIT: {\n\t\t\t\tUnitTypeClass const * utp = NULL;\n\n\t\t\t\t/*\n\t\t\t\t**\tGive the player an MCV if he has no base left but does have more than enough\n\t\t\t\t**\tmoney to rebuild a new base. Of course, if he already has an MCV, then don't\n\t\t\t\t**\tgive him another one.\n\t\t\t\t*/\n\t\t\t\tif (force_mcv) {\n\t\t\t\t\tutp = &UnitTypeClass::As_Reference(UNIT_MCV);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the player has a base and a refinery, but no harvester, then give him\n\t\t\t\t**\ta free one.\n\t\t\t\t*/\n\t\t\t\tif (utp == NULL && (object->House->BScan & STRUCTF_REFINERY) && !(object->House->UScan & UNITF_HARVESTER)) {\n\t\t\t\t\tutp = &UnitTypeClass::As_Reference(UNIT_HARVESTER);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tCheck for special unit type override value.\n\t\t\t\t*/\n\t\t\t\tif (Rule.UnitCrateType != UNIT_NONE) {\n\t\t\t\t\tutp = &UnitTypeClass::As_Reference(Rule.UnitCrateType);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf no unit type has been determined, then pick one at random.\n\t\t\t\t*/\n\t\t\t\twhile (utp == NULL) {\n#ifdef FIXIT_ANTS\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\tUnitType utype = Random_Pick(UNIT_FIRST, (UnitType)(UNIT_RA_COUNT-1 -3));\n#else\n\t\t\t\t\tUnitType utype = Random_Pick(UNIT_FIRST, (UnitType)(UNIT_COUNT-1 -3));\n#endif\n#else\n\t\t\t\t\tUnitType utype = Random_Pick(UNIT_FIRST, (UnitType)(UNIT_COUNT-1));\n#endif\n\t\t\t\t\tif (utype != UNIT_MCV || Session.Options.Bases) {\n\t\t\t\t\t\tutp = &UnitTypeClass::As_Reference(utype);\n\t\t\t\t\t\tif (utp->IsCrateGoodie && (utp->Ownable & (1 << HouseClass::As_Pointer(object->Owner())->ActLike))) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tutp = NULL;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (utp != NULL) {\n\t\t\t\t\tUnitClass * goodie_unit = (UnitClass *)utp->Create_One_Of(object->House);\n\t\t\t\t\tif (goodie_unit != NULL) {\n\t\t\t\t\t\tif (goodie_unit->Unlimbo(Cell_Coord())) {\n\t\t\t\t\t\t\treturn(false);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tTry to place the object into a nearby cell if something is preventing\n\t\t\t\t\t\t**\tplacement at the crate location.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tCELL cell = Map.Nearby_Location(Cell_Number(), goodie_unit->Class->Speed);\n\t\t\t\t\t\tif (goodie_unit->Unlimbo(::Cell_Coord(cell))) {\n\t\t\t\t\t\t\treturn(false);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdelete goodie_unit;\n\t\t\t\t\t\tgoto crate_money;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tCreate a squad of miscellaneous composition.\n\t\t\t*/\n\t\t\tcase CRATE_SQUAD:\n\t\t\t\tfor (index = 0; index < 5; index++) {\n\t\t\t\t\tstatic InfantryType _inf[] = {\n\t\t\t\t\t\tINFANTRY_E1,INFANTRY_E1,INFANTRY_E1,INFANTRY_E1,INFANTRY_E1,INFANTRY_E1,\n\t\t\t\t\t\tINFANTRY_E2,\n\t\t\t\t\t\tINFANTRY_E3,\n\t\t\t\t\t\tINFANTRY_RENOVATOR\n\t\t\t\t\t};\n\t\t\t\t\tif (!InfantryTypeClass::As_Reference(_inf[Random_Pick(0, ARRAY_SIZE(_inf)-1)]).Create_And_Place(Cell_Number(), object->Owner())) {\n\t\t\t\t\t\tif (index == 0) {\n\t\t\t\t\t\t\tgoto crate_money;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(false);\n\n\t\t\t/*\n\t\t\t**\tA one para-bomb mission.\n\t\t\t*/\n\t\t\tcase CRATE_PARA_BOMB:\n\t\t\t\tif (object->House->SuperWeapon[SPC_PARA_BOMB].Enable(true)) {\n\t\t\t\t\tif (object->IsOwnedByPlayer) {\n\t\t\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_PARA_BOMB);\n\t\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tA one time sonar pulse\n\t\t\t*/\n\t\t\tcase CRATE_SONAR:\n\t\t\t\tif (object->House->SuperWeapon[SPC_SONAR_PULSE].Enable(true)) {\n\t\t\t\t\tif (object->IsOwnedByPlayer) {\n\t\t\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_SONAR_PULSE);\n\t\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tA group of explosions are triggered around the crate.\n\t\t\t*/\n\t\t\tcase CRATE_EXPLOSION:\n\t\t\t\tif (object != NULL) {\n\t\t\t\t\tint d = CrateData[powerup];\n\t\t\t\t\tobject->Take_Damage(d, 0, WARHEAD_HE, 0, true);\n\t\t\t\t}\n\t\t\t\tfor (index = 0; index < 5; index++) {\n\t\t\t\t\tCOORDINATE frag_coord = Coord_Scatter(Cell_Coord(), Random_Pick(0, 0x0200));\n\t\t\t\t\tnew AnimClass(ANIM_FBALL1, frag_coord);\n\t\t\t\t\tdamage = CrateData[powerup];\n\t\t\t\t\tExplosion_Damage(frag_coord, damage, NULL, WARHEAD_HE);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tA napalm blast is triggered.\n\t\t\t*/\n\t\t\tcase CRATE_NAPALM:\n\t\t\t\tcoord = Coord_Mid(Cell_Coord(), object->Center_Coord());\n\t\t\t\tnew AnimClass(ANIM_NAPALM3, coord);\n\t\t\t\tif (object != NULL) {\n\t\t\t\t\tint d = CrateData[powerup];\n\t\t\t\t\tobject->Take_Damage(d, 0, WARHEAD_FIRE, 0, true);\n\t\t\t\t}\n\t\t\t\tdamage = CrateData[powerup];\n\t\t\t\tExplosion_Damage(coord, damage, NULL, WARHEAD_FIRE);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tAll objects within a certain range will gain the ability to cloak.\n\t\t\t*/\n\t\t\tcase CRATE_CLOAK:\n\t\t\t\tfor (index = 0; index < DisplayClass::Layer[LAYER_GROUND].Count(); index++) {\n\t\t\t\t\tObjectClass * obj = DisplayClass::Layer[LAYER_GROUND][index];\n\n\t\t\t\t\tif (obj && obj->Is_Techno() && Distance(Cell_Coord(), obj->Center_Coord()) < Rule.CrateRadius) {\n\t\t\t\t\t\t((TechnoClass *)obj)->IsCloakable = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tAll of the player's objects heal up.\n\t\t\t*/\n\t\t\tcase CRATE_HEAL_BASE:\n\t\t\t\tif (object->IsOwnedByPlayer) {\n\t\t\t\t\tSound_Effect(VOC_HEAL, object->Center_Coord());\n\t\t\t\t}\n\t\t\t\tfor (index = 0; index < Logic.Count(); index++) {\n\t\t\t\t\tObjectClass * obj = Logic[index];\n\n\t\t\t\t\tif (obj && object->Is_Techno() && object->House->Class->House == obj->Owner()) {\n\t\t\t\t\t\tobj->Strength = obj->Class_Of().MaxStrength;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\n\t\t\tcase CRATE_ICBM:\n\t\t\t\tif (object->House->SuperWeapon[SPC_NUCLEAR_BOMB].Enable(true)) {\n\t\t\t\t\tif (object->IsOwnedByPlayer) {\n\t\t\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_NUCLEAR_BOMB);\n\t\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase CRATE_ARMOR:\n\t\t\t\tfor (index = 0; index < DisplayClass::Layer[LAYER_GROUND].Count(); index++) {\n\t\t\t\t\tObjectClass * obj = DisplayClass::Layer[LAYER_GROUND][index];\n\n\t\t\t\t\tif (obj != NULL && obj->Is_Techno() && Distance(Cell_Coord(), obj->Center_Coord()) < Rule.CrateRadius && ((TechnoClass *)obj)->ArmorBias == 1) {\n\t\t\t\t\t\tfixed val = ((TechnoClass *)obj)->ArmorBias * Inverse(fixed(CrateData[powerup], 256));\n\t\t\t\t\t\t((TechnoClass *)obj)->ArmorBias = val;\n\t\t\t\t\t\tif (obj->Owner() == PlayerPtr->Class->House) tospeak = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (tospeak) Speak(VOX_UPGRADE_ARMOR);\n\t\t\t\tbreak;\n\n\t\t\tcase CRATE_SPEED:\n\t\t\t\tfor (index = 0; index < DisplayClass::Layer[LAYER_GROUND].Count(); index++) {\n\t\t\t\t\tObjectClass * obj = DisplayClass::Layer[LAYER_GROUND][index];\n\n\t\t\t\t\tif (obj && obj->Is_Foot() && Distance(Cell_Coord(), obj->Center_Coord()) < Rule.CrateRadius && ((FootClass *)obj)->SpeedBias == 1 && obj->What_Am_I() != RTTI_AIRCRAFT) {\n\t\t\t\t\t\tFootClass * foot = (FootClass *)obj;\n\n\t\t\t\t\t\tfixed val = foot->SpeedBias * fixed(CrateData[powerup], 256);\n\t\t\t\t\t\tfoot->SpeedBias = val;\n\t\t\t\t\t\tif (foot->IsOwnedByPlayer) tospeak = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (tospeak) Speak(VOX_UPGRADE_SPEED);\n\t\t\t\tbreak;\n\n\t\t\tcase CRATE_FIREPOWER:\n\t\t\t\tfor (index = 0; index < DisplayClass::Layer[LAYER_GROUND].Count(); index++) {\n\t\t\t\t\tObjectClass * obj = DisplayClass::Layer[LAYER_GROUND][index];\n\n\t\t\t\t\tif (obj && obj->Is_Techno() && Distance(Cell_Coord(), obj->Center_Coord()) < Rule.CrateRadius && ((TechnoClass *)obj)->FirepowerBias == 1) {\n\n\t\t\t\t\t\tfixed val = ((TechnoClass *)obj)->FirepowerBias * fixed(CrateData[powerup], 256);\n\t\t\t\t\t\t((TechnoClass *)obj)->FirepowerBias = val;\n\t\t\t\t\t\tif (obj->Owner() == PlayerPtr->Class->House) tospeak = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (tospeak) Speak(VOX_UPGRADE_FIREPOWER);\n\t\t\t\tbreak;\n\n\t\t\tcase CRATE_INVULN:\n\t\t\t\tfor (index = 0; index < DisplayClass::Layer[LAYER_GROUND].Count(); index++) {\n\t\t\t\t\tObjectClass * obj = DisplayClass::Layer[LAYER_GROUND][index];\n\n\t\t\t\t\tif (obj && obj->Is_Techno() && Distance(Cell_Coord(), obj->Center_Coord()) < Rule.CrateRadius) {\n\t\t\t\t\t\t((TechnoClass *)obj)->IronCurtainCountDown = (TICKS_PER_MINUTE * fixed(CrateData[powerup], 256));\n\t\t\t\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t** A chronal vortex appears targetted at the triggering object.\n\t\t\t*/\n\t\t\tcase CRATE_VORTEX:\n\t\t\t\tif ( !ChronalVortex.Is_Active()) {\n\t\t\t\t\tChronalVortex.Appear ( Cell_Coord() );\n\t\t\t\t\tChronalVortex.Set_Target ( (ObjectClass*) object );\n\t\t\t\t\tSound_Effect(VOC_TESLA_ZAP, object->Center_Coord());\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * CellClass::Flag_Place -- Places a house flag down on the cell.                              *\n *                                                                                             *\n *    This routine will place the house flag at this cell location.                            *\n *                                                                                             *\n * INPUT:   house -- The house that is having its flag placed here.                            *\n *                                                                                             *\n * OUTPUT:  Was the flag successfully placed here?                                             *\n *                                                                                             *\n * WARNINGS:   Failure to place means that the cell is impassable for some reason.             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Flag_Place(HousesType house)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tif (!IsFlagged && Is_Clear_To_Move(SPEED_TRACK, false, false)) {\n\t\tIsFlagged = true;\n\t\tOwner = house;\n\t\tRedraw_Objects();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CellClass::Flag_Remove -- Removes the house flag from the cell.                             *\n *                                                                                             *\n *    This routine will free the cell of any house flag that may be located there.             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was there a flag here that was removed?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Flag_Remove(void)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tif (IsFlagged) {\n\t\tIsFlagged = false;\n\t\tOwner = HOUSE_NONE;\n\t\tRedraw_Objects();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CellClass::Shimmer -- Causes all objects in the cell to shimmer.                            *\n *                                                                                             *\n *    This routine is called when some event would cause a momentary disruption in the         *\n *    cloaking device. All objects that are cloaked in the cell will have their cloaking       *\n *    device shimmer.                                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CellClass::Shimmer(void)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tObjectClass * object = Cell_Occupier();\n\n\twhile (object) {\n\t\tobject->Do_Shimmer();\n\t\tobject = object->Next;\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Is_Clear_To_Move -- Determines if the cell is generally clear for travel         *\n *                                                                                             *\n *    This routine is called when determining general passability for purposes of zone         *\n *    calculation. Only blockages that cannot be circumvented are considered to make a cell    *\n *    impassable. All other obstructions can either be destroyed or are temporary.             *\n *                                                                                             *\n * INPUT:   loco     -- The locomotion type to use when determining passablility.              *\n *                                                                                             *\n *          ignoreinfantry -- Should infantry in the cell be ignored for movement purposes?    *\n *                                                                                             *\n *          ignorevehicles -- If vehicles should be ignored, then this flag will be true.      *\n *                                                                                             *\n *          zone     -- If specified, the zone must match this value or else movement is       *\n *                      presumed disallowed.                                                   *\n *                                                                                             *\n *          check    -- This specifies the zone type that this check applies to.               *\n *                                                                                             *\n * OUTPUT:  Is the cell generally passable to ground targeting?                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/25/1995 JLB : Created.                                                                 *\n *   06/25/1996 JLB : Uses tracked vehicles as a basis for zone check.                         *\n *   10/05/1996 JLB : Allows checking for crushable blockages.                                 *\n *=============================================================================================*/\nbool CellClass::Is_Clear_To_Move(SpeedType loco, bool ignoreinfantry, bool ignorevehicles, int zone, MZoneType check) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\t/*\n\t**\tFlying objects always consider every cell passable since they can fly over everything.\n\t*/\n\tif (loco == SPEED_WINGED) {\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tIf a zone was specified, then see if the cell is in a legal\n\t**\tzone to allow movement.\n\t*/\n\tif (zone != -1) {\n\t\tif (zone != Zones[check]) {\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck the occupy bits for passable legality. If ignore infantry is true, then\n\t**\tdon't consider infnatry.\n\t*/\n\tint composite = Flag.Composite;\n\tif (ignoreinfantry) {\n\t\tcomposite &= 0xE0;\t\t\t// Drop the infantry occupation bits.\n\t}\n\tif (ignorevehicles) {\n\t\tcomposite &= 0x5F;\t\t\t// Drop the vehicle/building bit.\n\t}\n\tif (composite != 0) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tFetch the land type of the cell -- to be modified and used later.\n\t*/\n\tLandType land = Land_Type();\n\n\t/*\n\t**\tWalls are always considered to block the terrain for general passability\n\t**\tpurposes unless this is a wall crushing check or if the checking object\n\t**\tcan destroy walls.\n\t*/\n\tOverlayTypeClass const * overlay = NULL;\n\tif (Overlay != OVERLAY_NONE) {\n\t \toverlay = &OverlayTypeClass::As_Reference(Overlay);\n\t}\n\tif (overlay != NULL && overlay->IsWall) {\n\t\tif (check != MZONE_DESTROYER && (check != MZONE_CRUSHER || !overlay->IsCrushable)) {\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t**\tCrushing objects consider crushable walls as clear rather than the\n\t\t**\ttypical LAND_WALL setting.\n\t\t*/\n\t\tland = LAND_CLEAR;\n\t}\n\n\t/*\n\t**\tSee if the ground type is impassable to this locomotion type and if\n\t**\tso, return the error condition.\n\t*/\n\tif (::Ground[land].Cost[loco] == 0) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tAll checks passed, so this cell must be passable.\n\t*/\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * CellClass::Is_Bridge_Here -- Checks to see if this is a bridge occupied cell.               *\n *                                                                                             *\n *    This routine will examine this cell and if there is a bridge here, it will return        *\n *    true.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is there a bridge located in this cell?                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Is_Bridge_Here(void) const\n{\n\tswitch (TType) {\n\t\tcase TEMPLATE_BRIDGE1:\n\t\tcase TEMPLATE_BRIDGE1H:\n\t\tcase TEMPLATE_BRIDGE1D:\n\t\tcase TEMPLATE_BRIDGE2:\n\t\tcase TEMPLATE_BRIDGE2H:\n\t\tcase TEMPLATE_BRIDGE2D:\n\t\tcase TEMPLATE_BRIDGE_1A:\n\t\tcase TEMPLATE_BRIDGE_1B:\n\t\tcase TEMPLATE_BRIDGE_2A:\n\t\tcase TEMPLATE_BRIDGE_2B:\n\t\tcase TEMPLATE_BRIDGE_3A:\n\t\tcase TEMPLATE_BRIDGE_3B:\n\t\tcase TEMPLATE_BRIDGE_3C:\n\t\tcase TEMPLATE_BRIDGE_3D:\n\t\tcase TEMPLATE_BRIDGE_3E:\n\t\tcase TEMPLATE_BRIDGE_3F:\n\t\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CellClass::Can_Tiberium_Grow -- Determines if Tiberium can grow in this cell.               *\n *                                                                                             *\n *    This checks the cell to see if Tiberium can grow at least one level in it. Tiberium can  *\n *    grow only if there is Tiberium already present. It can only grow to a certain level      *\n *    and then all further growth is suspended.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Can Tiberium grow in this cell?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Can_Tiberium_Grow(void) const\n{\n\tif (!Rule.IsTGrowth) return(false);\n\n\tif (Session.Type != GAME_NORMAL) {\n\t\tif(!Session.Options.Tiberium) return(false);\n\t}\n\n\tif (Land_Type() != LAND_TIBERIUM) return(false);\n\n\tif (OverlayData >= 11) return(false);\n\n\tif (Overlay != OVERLAY_GOLD1 && Overlay != OVERLAY_GOLD2 && Overlay != OVERLAY_GOLD3 && Overlay != OVERLAY_GOLD4) return(false);\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * CellClass::Can_Tiberium_Spread -- Determines if Tiberium can spread from this cell.         *\n *                                                                                             *\n *    This routine will examine the cell and determine if there is sufficient Tiberium         *\n *    present that Tiberium spores will spread to adjacent cells. If the Tiberium level is     *\n *    too low, spreading will not occur.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Can Tiberium spread from this cell into adjacent cells?                      *\n *                                                                                             *\n * WARNINGS:   This routine does not check to see if, in fact, there are any adjacent cells    *\n *             available to spread to.                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Can_Tiberium_Spread(void) const\n{\n\tif (!Rule.IsTSpread) return(false);\n\n\tif (Session.Type != GAME_NORMAL) {\n\t\tif(!Session.Options.Tiberium) return(false);\n\t}\n\n\tif (Land_Type() != LAND_TIBERIUM) return(false);\n\n\tif (OverlayData <= 6) return(false);\n\n\tif (Overlay != OVERLAY_GOLD1 && Overlay != OVERLAY_GOLD2 && Overlay != OVERLAY_GOLD3 && Overlay != OVERLAY_GOLD4) return(false);\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * CellClass::Grow_Tiberium -- Grows the tiberium in the cell.                                 *\n *                                                                                             *\n *    This routine will cause the tiberium to grow in the cell.                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Did Tiberium grow in the cell?                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Grow_Tiberium(void)\n{\n\tif (Can_Tiberium_Grow()) {\n\t\tOverlayData++;\n\t\tRedraw_Objects();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CellClass::Spread_Tiberium -- Spread Tiberium from this cell to an adjacent cell.           *\n *                                                                                             *\n *    This routine will cause the Tiberium to spread from this cell into an adjacent (random)  *\n *    cell.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Did the Tiberium spread?                                                     *\n *                                                                                             *\n * WARNINGS:   If there are no adjacent cells that the tiberium can spread to, then this       *\n *             routine will fail.                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Spread_Tiberium(bool forced)\n{\n\tif (!forced) {\n\t\tif (!Can_Tiberium_Spread()) return(false);\n\t}\n\tFacingType offset = Random_Pick(FACING_N, FACING_NW);\n\tfor (FacingType index = FACING_N; index < FACING_COUNT; index++) {\n\t\tCellClass * newcell = &Adjacent_Cell(index+offset);\n\n\t\tif (newcell != NULL && newcell->Can_Tiberium_Germinate()) {\n\t\t\tnew OverlayClass(Random_Pick(OVERLAY_GOLD1, OVERLAY_GOLD4), newcell->Cell_Number());\n\t\t\tnewcell->OverlayData = 0;\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CellClass::Can_Tiberium_Germinate -- Determines if Tiberium can begin growth in the cell.   *\n *                                                                                             *\n *    This routine will examine the cell and determine if Tiberium can start growth in it.     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Can Tiberium grow in this cell?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Can_Tiberium_Germinate(void) const\n{\n\tif (!Map.In_Radar(Cell_Number())) return(false);\n\n\tif (Is_Bridge_Here()) return(false);\n\n\t/*\n\t**\tDon't allow Tiberium to grow on a cell with a building unless that building is\n\t**\tinvisible. In such a case, the Tiberium must grow or else the location of the\n\t**\tbuilding will be revealed.\n\t*/\n\tBuildingClass const * building = Cell_Building();\n\tif (building != NULL && !building->Class->IsInvisible) return(false);\n\n\tif (!Ground[Land_Type()].Build) return(false);\n\n\tif (Overlay != OVERLAY_NONE) return(false);\n\n\treturn(true);\n}\n"
  },
  {
    "path": "CODE/CELL.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CELL.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CELL.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 29, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 29, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CELL_H\n#define CELL_H\n\n#include\t\"building.h\"\n#include\t\"unit.h\"\n#include\t\"template.h\"\n\n\n/****************************************************************************\n**\tEach cell on the map is controlled by the following structure.\n*/\nclass CellClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis is the ID number of this cell. By placing the ID number here, it doesn't have\n\t\t**\tbe calculated. Calculating this number requires a divide and would occur about\n\t\t**\t5.72031 bijillion times per second.\n\t\t*/\n\t\tshort ID;\n\n\t\t/*\n\t\t**\tDoes this cell need to be updated on the radar map?  If something changes in the cell\n\t\t**\tthat might change the radar map imagery, then this flag will be set. It gets cleared\n\t\t**\twhen the cell graphic is updated to the radar map.\n\t\t*/\n\t\tunsigned IsPlot:1;\n\n\t\t/*\n\t\t**\tDoes this cell contain the special placement cursor graphic?  This graphic is\n\t\t**\tpresent when selecting a site for building placement.\n\t\t*/\n\t\tunsigned IsCursorHere:1;\n\n\t\t/*\n\t\t**\tA mapped cell has some portion of it visible. Maybe it has a shroud piece\n\t\t**\tover it and maybe not.\n\t\t*/\n\t\tunsigned IsMapped:1;\n\n\t\t/*\n\t\t**\tA visible cell means that it is completely visible with no shroud over\n\t\t**\tit at all.\n\t\t*/\n\t\tunsigned IsVisible:1;\n\n\t\t/*\n\t\t** Every cell can be assigned a waypoint.  A waypoint can only be assigned\n\t\t** to one cell, and vice-versa.  This bit simply indicates whether this\n\t\t** cell is assigned a waypoint or not.\n\t\t*/\n\t\tunsigned IsWaypoint:1;\n\n\t\t/*\n\t\t** Is this cell currently under the radar map cursor?  If so then it\n\t\t**   needs to be updated whenever the map is updated.\n\t\t*/\n\t\tunsigned IsRadarCursor:1;\n\n\t\t/*\n\t\t**\tIf this cell contains a house flag, then this will be true. The actual house\n\t\t**\tflag it contains is specified by the Owner field.\n\t\t*/\n\t\tunsigned IsFlagged:1;\n\n\t\t/*\n\t\t**\tThis is a working flag used to help keep track of what cells should be\n\t\t**\tshrouded. By using this flag it allows a single pass through the map\n\t\t**\tcells for determining shadow regrowth logic.\n\t\t*/\n\t\tunsigned IsToShroud:1;\n\n\t\t/*\n\t\t**\tThis records the movement zone for this map. Movement zones share the\n\t\t**\tsame number if they are contiguous (terrain consideration only). There\n\t\t**\tare basically two kinds of zones. The difference being determined by\n\t\t**\twalls that can be crushed by movement. A vehicle that can crush walls\n\t\t**\twill only consider the CrushZone. All other terrestrial travellers will\n\t\t**\tuse the normal Zone.\n\t\t*/\n\t\tunsigned char Zones[MZONE_COUNT];\n\n\t\t/*\n\t\t** This field controls whether an area is being jammed by a gap\n\t\t** generator.\n\t\t*/\n\t\tunsigned short Jammed;\n\n\t\t/*\n\t\t**\tThis is the trigger ID for any trigger that might be attached to\n\t\t**\tthis cell.\n\t\t*/\n\t\tCCPtr<TriggerClass> Trigger;\n\n\t\t/*\n\t\t**\tThis contains the icon number and set to use for the base\n\t\t**\tof the terrain. All rendering on an icon occurs AFTER the icon\n\t\t**\tspecified by this element is rendered. It is the lowest of the low.\n\t\t*/\n\t\tTemplateType TType;\n\t\tunsigned char TIcon;\n\n\t\t/*\n\t\t**\tThe second layer of 'terrain' icons is represented by a simple\n\t\t**\ttype number and a value byte. This is sufficient for handling\n\t\t**\tconcrete and walls.\n\t\t*/\n\t\tOverlayType Overlay;\n\t\tunsigned char OverlayData;\n\n\t\t/*\n\t\t**\tThis is used to specify any special 'stain' overlay icon. This\n\t\t**\ttypically includes infantry bodies or other temporary marks.\n\t\t*/\n\t\tSmudgeType Smudge;\n\t\tunsigned char SmudgeData;\n\n\t\t/*\n\t\t**\tSmudges and walls need to record ownership values. For walls, this\n\t\t**\tallows adjacent building placement logic to work. For smudges, it\n\t\t**\tallows building over smudges that are no longer attached to buildings\n\t\t**\tin addition to fixing the adjacent placement logic.\n\t\t*/\n\t\tHousesType Owner;\n\n\t\t/*\n\t\t** This flag tells you what type of infantry currently occupy the\n\t\t** cell or are moving into it.\n\t\t*/\n\t\tHousesType InfType;\n\n\t\t/*\n\t\t**\tThese point to the object(s) that are located in this cell or overlap\n\t\t**\tthis cell.\n\t\t*/\n\tprivate:\n\t\tObjectClass * OccupierPtr;\n\n\tpublic:\n#ifdef SORTDRAW\n\t\tObjectClass * Overlapper[10];\n#else\n\t\tObjectClass * Overlapper[6];\n#endif\n\n\t\t/*\n\t\t**\tThis array of bit flags is used to indicate which sub positions\n\t\t**\twithin the cell are either occupied or are soon going to be\n\t\t**\toccupied. For vehicles, the cells that the vehicle is passing over\n\t\t**\twill be flagged with the vehicle bit. For infantry, the the sub\n\t\t**\tposition the infantry is stopped at or headed toward will be marked.\n\t\t**\tThe sub positions it passes over will NOT be marked.\n\t\t*/\n\t\tunion {\n\t\t\tstruct {\n\t\t\t\tunsigned Center:1;\n\t\t\t\tunsigned NW:1;\n\t\t\t\tunsigned NE:1;\n\t\t\t\tunsigned SW:1;\n\t\t\t\tunsigned SE:1;\n\t\t\t\tunsigned Vehicle:1;\t\t// Reserved for vehicle occupation.\n\t\t\t\tunsigned Monolith:1;\t\t// Some immovable blockage is in cell.\n\t\t\t\tunsigned Building:1;\t\t// A building of some time (usually blocks movement).\n\t\t\t} Occupy;\n\t\t\tunsigned char Composite;\n\t\t} Flag;\n\n\t\t//----------------------------------------------------------------\n\t\tCellClass(void);\n\t\tCellClass(NoInitClass const & x) : Trigger(x) {}\n\t\t~CellClass(void) {OccupierPtr=0;}\n\n\t\tint operator == (CellClass const & cell) const {return &cell == this;}\n\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tbool Can_Tiberium_Germinate(void) const;\n\t\tbool Can_Tiberium_Grow(void) const;\n\t\tbool Can_Tiberium_Spread(void) const;\n\t\tbool Is_Bridge_Here(void) const;\n\t\tRTTIType What_Am_I(void) const {return(RTTI_CELL);}\n\t\tBuildingClass * Cell_Building(void) const;\n\t\tCELL Cell_Number(void) const {return(ID);}\n\t\tCOORDINATE Cell_Coord(void) const;\n\t\tCOORDINATE Closest_Free_Spot(COORDINATE coord, bool any=false) const;\n\t\tCOORDINATE Free_Spot(void) const {return Closest_Free_Spot(Cell_Coord());}\n\t\tCellClass & Adjacent_Cell(FacingType face) {return (CellClass &)((*((CellClass const *)this)).Adjacent_Cell(face));}\n\t\tCellClass const & Adjacent_Cell(FacingType face) const;\n\t\tInfantryClass * Cell_Infantry(void) const;\n\t\tLandType Land_Type(void) const {return(Land);}\n\t\tObjectClass * Cell_Find_Object(RTTIType rtti) const;\n\t\tObjectClass * Cell_Object(int x=0, int y=0) const;\n\t\tObjectClass * Cell_Occupier(void) const {return(OccupierPtr);}\n\t\tObjectClass * Fetch_Occupier(void) const;\n\t\tTARGET As_Target(void) const {return ::As_Target(Cell_Number());}\n\t\tTechnoClass * Cell_Techno(int x=0, int y=0) const;\n\t\tTerrainClass * Cell_Terrain(void) const;\n\t\tUnitClass * Cell_Unit(void) const;\n\t\tVesselClass * Cell_Vessel(void) const;\n\t\tbool Goodie_Check(FootClass * object);\n\t\tbool Is_Clear_To_Build(SpeedType loco = SPEED_TRACK) const;\n\t\tbool Is_Clear_To_Move(SpeedType loco, bool ignoreinfantry, bool ignorevehicles, int zone=-1, MZoneType check=MZONE_NORMAL) const;\n\t\tbool Is_Spot_Free(int spot_index) const {return (! (Flag.Composite & (1 << spot_index)) ); }\n\t\tint Cell_Color(bool override=false) const;\n\t\tint Clear_Icon(void) const;\n\t\tstatic int Spot_Index(COORDINATE coord);\n\n\t\t/*\n\t\t**\tObject placement and removal flag operations.\n\t\t*/\n\t\tvoid Occupy_Down(ObjectClass * object);\n\t\tvoid Occupy_Up(ObjectClass * object);\n\t\tvoid Overlap_Down(ObjectClass * object);\n\t\tvoid Overlap_Up(ObjectClass * object);\n\t\tbool Flag_Place(HousesType house);\n\t\tbool Flag_Remove(void);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tbool Should_Save(void) const;\n\t\tbool Save(Pipe & file) const;\n\t\tbool Load(Straw & file);\n\t\tvoid Code_Pointers(void);\n\t\tvoid Decode_Pointers(void);\n\n\t\t/*\n\t\t**\tDisplay and rendering controls.\n\t\t*/\n\t\tvoid Draw_It(int x, int y, bool objects=false) const;\n\t\tvoid Redraw_Objects(bool forced=false);\n\t\tvoid Shimmer(void);\n\n\t\t/*\n\t\t**\tMaintenance calculation support.\n\t\t*/\n\t\tbool Grow_Tiberium(void);\n\t\tbool Spread_Tiberium(bool forced=false);\n\t\tlong Tiberium_Adjust(bool pregame=false);\n\t\tvoid Wall_Update(void);\n\t\tvoid Concrete_Calc(void);\n\t\tvoid Recalc_Attributes(void);\n\t\tint  Reduce_Tiberium(int levels);\n\t\tint  Reduce_Wall(int damage);\n\t\tvoid Incoming(COORDINATE threat=0, bool forced=false, bool nokidding=false);\n\t\tvoid Adjust_Threat(HousesType house, int threat_value);\n\n\t\tint operator != (CellClass const &) const {return 0;}\n\n\tprivate:\n\t\tCellClass (CellClass const &) ;\n\n\t\tLandType Land;\t\t// The land type of this cell.\n};\n\n#endif\n\n"
  },
  {
    "path": "CODE/CHECKBOX.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CHECKBOX.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CHECKBOX.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/26/95                                                     *\n *                                                                                             *\n *                  Last Update : July 6, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CheckBoxClass::Action -- Handles a button action on a checkbox object.                    *\n *   CheckBoxClass::Draw_Me -- Draws the checkbox imagery.                                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"checkbox.h\"\n\n\n/***********************************************************************************************\n * CheckBoxClass::Draw_Me -- Draws the checkbox imagery.                                       *\n *                                                                                             *\n *    This routine will draw the checkbox either filled or empty as necessary.                 *\n *                                                                                             *\n * INPUT:   forced   -- Should the check box be drawn even if it doesn't think it needs to?    *\n *                                                                                             *\n * OUTPUT:  Was the check box rendered?                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CheckBoxClass::Draw_Me(int forced)\n{\n\tif (ToggleClass::Draw_Me(forced)) {\n\n\t\tHide_Mouse();\n\t\tDraw_Box(X, Y, Width, Height, BOXSTYLE_DOWN, false);\n\t\tLogicPage->Fill_Rect(X+1, Y+1, X+Width-2, Y+Height-2, DKGREY);\n\t\tif (IsOn) {\n\t\t\tLogicPage->Fill_Rect(X+1, Y+1, X+Width-2, Y+Height-2, LTGREEN);\n\t\t}\n\t\tShow_Mouse();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CheckBoxClass::Action -- Handles a button action on a checkbox object.                      *\n *                                                                                             *\n *    This routine will detect if the mouse has been clicked on the checkbox object. If so,    *\n *    the check box state will be toggled.                                                     *\n *                                                                                             *\n * INPUT:   flags -- The event flags that resulted in this routine being called.               *\n *                                                                                             *\n *          key   -- The key that resulted in this routine being called.                       *\n *                                                                                             *\n * OUTPUT:  bool; Should normal processing occur?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CheckBoxClass::Action(unsigned flags, KeyNumType & key)\n{\n\tif (flags & LEFTRELEASE) {\n\t\tif (IsOn) {\n\t\t\tTurn_Off();\n\t\t} else {\n\t\t\tTurn_On();\n\t\t}\n\t}\n\treturn(ToggleClass::Action(flags, key));\n}\n"
  },
  {
    "path": "CODE/CHECKBOX.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CHECKBOX.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CHECKBOX.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/26/95                                                     *\n *                                                                                             *\n *                  Last Update : May 26, 1995 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CHECKBOX_H\n#define CHECKBOX_H\n\n#include\t\"toggle.h\"\n\nclass CheckBoxClass : public ToggleClass\n{\n\tpublic:\n\t\tCheckBoxClass(unsigned id, int x, int y) :\n\t\t\tToggleClass(id, x, y, 7, 7)\n\t\t{};\n\n\t\tvirtual int Draw_Me(int forced=false);\n\t\tvirtual int Action(unsigned flags, KeyNumType & key);\n\n\tprotected:\n};\n\n#endif\n"
  },
  {
    "path": "CODE/CHEKLIST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CHEKLIST.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CHEKLIST.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/05/96                                                     *\n *                                                                                             *\n *                  Last Update : July 6, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CheckListClass::Action -- action function for this class                                  *\n *   CheckListClass::Add_Item -- Adds specifies text to check list box.                        *\n *   CheckListClass::CheckListClass -- constructor                                             *\n *   CheckListClass::Check_Item -- [un]checks an items                                         *\n *   CheckListClass::Draw_Entry -- draws a list box entry                                      *\n *   CheckListClass::Get_Item -- Fetches a pointer to the text associated with the index.      *\n *   CheckListClass::Remove_Item -- Remove the item that matches the text pointer specified.   *\n *   CheckListClass::Set_Selected_Index -- Set the selected index to match the text pointer spe*\n *   CheckListClass::~CheckListClass -- Destructor for check list object.                      *\n *   CheckListClass::~CheckListClass -- destructor                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/***************************************************************************\n * CheckListClass::CheckListClass -- constructor                           *\n *                                                                         *\n * INPUT:                                                                  *\n *      id         control ID for this list box                            *\n *      x         x-coord                                                  *\n *      y         y-coord                                                  *\n *      w         width                                                    *\n *      h         height                                                   *\n *      flags      mouse event flags                                       *\n *      up         ptr to Up-arrow shape                                   *\n *      down      ptr to Down-arrow shape                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/16/1995 BR : Created.                                              *\n *=========================================================================*/\nCheckListClass::CheckListClass(int id, int x, int y, int w, int h, TextPrintType flags,\n\tvoid const * up, void const * down) :\n\tListClass (id, x, y, w, h, flags, up, down),\n\tIsReadOnly(false)\n{\n}\n\n\n/***********************************************************************************************\n * CheckListClass::~CheckListClass -- Destructor for check list object.                        *\n *                                                                                             *\n *    This destructor will delete all entries attached to it.                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCheckListClass::~CheckListClass(void)\n{\n\twhile (CheckListClass::Count()) {\n\t\tCheckObject * obj = (CheckObject *)ListClass::Get_Item(0);\n\n\t\tListClass::Remove_Item(0);\n\t\tdelete obj;\n\t}\n}\n\n\n/***********************************************************************************************\n * CheckListClass::Add_Item -- Adds specifies text to check list box.                          *\n *                                                                                             *\n *    This routine will add the specified text string to the check list.                       *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text string to add to the list box.                        *\n *                                                                                             *\n * OUTPUT:  Returns the index number where the text object was added.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CheckListClass::Add_Item(char const * text)\n{\n\tCheckObject * obj = new CheckObject(text, false);\n\treturn(ListClass::Add_Item((char const *)obj));\n}\n\n\nchar const * CheckListClass::Current_Item(void) const\n{\n\tCheckObject * obj = (CheckObject *)ListClass::Current_Item();\n\tif (obj) {\n\t\treturn(obj->Text);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * CheckListClass::Get_Item -- Fetches a pointer to the text associated with the index.        *\n *                                                                                             *\n *    This routine will find the text associated with the entry specified and return a pointer *\n *    to that text.                                                                            *\n *                                                                                             *\n * INPUT:   index -- The entry (index) to fetch a pointer to.                                  *\n *                                                                                             *\n * OUTPUT:  Returns with the text pointer associated with the index specified.                 *\n *                                                                                             *\n * WARNINGS:   If the index is out of range, then NULL is returned.                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * CheckListClass::Get_Item(int index) const\n{\n\tCheckObject * obj = (CheckObject *)ListClass::Get_Item(index);\n\tif (obj) {\n\t\treturn(obj->Text);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * CheckListClass::Remove_Item -- Remove the item that matches the text pointer specified.     *\n *                                                                                             *\n *    This routine will find the entry that matches the text pointer specified and then        *\n *    delete that entry.                                                                       *\n *                                                                                             *\n * INPUT:   text  -- The text pointer to use to find the exact match in the list.              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CheckListClass::Remove_Item(char const * text)\n{\n\tfor (int index = 0; index < Count(); index++) {\n\t\tCheckObject * obj = (CheckObject *)ListClass::Get_Item(index);\n\t\tif (obj && stricmp(obj->Text, text) == 0) {\n\t\t\tListClass::Remove_Item(index);\n\t\t\tdelete obj;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * CheckListClass::Set_Selected_Index -- Set the selected index to match the text pointer spec *\n *                                                                                             *\n *    This routine will find the entry that exactly matches the text pointer specified. If     *\n *    found, then that entry will be set as the currently selected index.                      *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text string to find the match for.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If an exact match to the specified text string could not be found, then the     *\n *             currently selected index is not changed.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CheckListClass::Set_Selected_Index(char const * text)\n{\n\tfor (int index = 0; index < Count(); index++) {\n\t\tCheckObject * obj = (CheckObject *)ListClass::Get_Item(index);\n\t\tif (obj && stricmp(obj->Text, text) == 0) {\n\t\t\tSet_Selected_Index(index);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * CheckListClass::Check_Item -- [un]checks an items                       *\n *                                                                         *\n * INPUT:                                                                  *\n *      index         index of item to check or uncheck                    *\n *      checked      0 = uncheck, non-zero = check                         *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/16/1995 BR : Created.                                              *\n *   02/14/1996 JLB : Revamped.                                            *\n *=========================================================================*/\nvoid CheckListClass::Check_Item(int index, bool checked)\n{\n\tCheckObject * obj = (CheckObject *)ListClass::Get_Item(index);\n\tif (obj && obj->IsChecked != checked) {\n\t\tobj->IsChecked = checked;\n\t\tFlag_To_Redraw();\n\t}\n}\n\n\n/***************************************************************************\n * CheckListClass::Is_Checked -- returns checked state of an item          *\n *                                                                         *\n * INPUT:                                                                  *\n *      index         index of item to query                               *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = item is unchecked, 1 = item is checked                         *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/16/1995 BR : Created.                                              *\n *   02/14/1996 JLB : Revamped.                                            *\n *=========================================================================*/\nbool CheckListClass::Is_Checked(int index) const\n{\n\tCheckObject * obj = (CheckObject *)ListClass::Get_Item(index);\n\tif (obj) {\n\t\treturn(obj->IsChecked);\n\t}\n\treturn(false);\n}\n\n\n/***************************************************************************\n * CheckListClass::Action -- action function for this class                *\n *                                                                         *\n * INPUT:                                                                  *\n *      flags      the reason we're being called                           *\n *      key      the KN_number that was pressed                            *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      true = event was processed, false = event not processed            *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/16/1995 BR : Created.                                              *\n *=========================================================================*/\nint CheckListClass::Action(unsigned flags, KeyNumType &key)\n{\n\tint rc;\n\n\t/*\n\t** If this is a read-only list, it's a display-only device\n\t*/\n\tif (IsReadOnly) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tInvoke parents Action first, so it can set the SelectedIndex if needed.\n\t*/\n\trc =  ListClass::Action(flags, key);\n\n\t/*\n\t**\tNow, if this event was a left-press, toggle the checked state of the\n\t**\tcurrent item.\n\t*/\n\tif (flags & LEFTPRESS) {\n\t\tCheck_Item(SelectedIndex, !Is_Checked(SelectedIndex));\n\t}\n\n\treturn(rc);\n}\n\n\n/***************************************************************************\n * CheckListClass::Draw_Entry -- draws a list box entry                    *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\t\tindex into List of item to draw                      \t\t*\n *\t\tx,y\t\t\tx,y coords to draw at                                  \t*\n *\t\twidth\t\t\tmaximum width allowed for text                       \t\t*\n *\t\tselected\t\ttrue = this item is selected                         \t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/14/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid CheckListClass::Draw_Entry(int index, int x, int y, int width, int selected)\n{\n\tif (index >= Count()) return;\n\n\tCheckObject * obj = (CheckObject *)ListClass::Get_Item(index);\n\n\tif (obj) {\n\t\tchar buffer[100] = \"\";\n\n\t\tif (obj->IsChecked) {\n\t\t\tbuffer[0] = CHECK_CHAR;\n\t\t} else {\n\t\t\tbuffer[0] = UNCHECK_CHAR;\n\t\t}\n\t\tbuffer[1] = ' ';\n\t\tsprintf(&buffer[2], obj->Text);\n\n\t\tTextPrintType flags = TextFlags;\n\t\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t\tif (selected) {\n\t\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\t\tLogicPage->Fill_Rect (x, y, x + width - 1, y + LineHeight - 1, scheme->Shadow);\n\t\t} else {\n\t\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t\t}\n\t\t}\n\n\t\tConquer_Clip_Text_Print(buffer, x, y, scheme, TBLACK, flags, width, Tabs);\n\t}\n}\n\n"
  },
  {
    "path": "CODE/CHEKLIST.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CHEKLIST.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : CHEKLIST.H                               *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : February 16, 1995                        *\n *                                                                         *\n *                  Last Update : February 16, 1995   [BR]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *\tThis class behaves just like the standard list box, except that if the\t*\n * first character of a list entry is a space, clicking on it toggles the\t*\n * space with a check-mark ('\\3').  This makes each entry in the list box\t*\n * \"toggle-able\".\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CHEKLIST_H\n#define CHEKLIST_H\n\n#include \"list.h\"\n\nclass CheckObject\n{\n\tpublic:\n\t\tCheckObject(char const * text = 0, bool checked=false) :\n\t\t\tText(text),\n\t\t\tIsChecked(checked)\n\t\t{};\n\n\t\tchar const * Text;\n\t\tbool IsChecked;\n};\n\n\nclass CheckListClass : public ListClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tConstructor/Destructor\n\t\t*/\n\t\tCheckListClass(int id, int x, int y, int w, int h, TextPrintType flags,\n\t\t\tvoid const * up, void const * down);\n\t\t~CheckListClass(void);\n\n\t\tvirtual int Add_Item(int text) {return ListClass::Add_Item(text);}\n\t\tvirtual int Add_Item(char const * text);\n\t\tvirtual char const * Current_Item(void) const;\n\t\tvirtual char const * Get_Item(int index) const;\n\t\tvirtual void Remove_Item(char const * text);\n\t\tvirtual void Remove_Item(int text) {ListClass::Remove_Item(text);}\n\t\tvirtual void Set_Selected_Index(char const * text);\n\t\tvirtual void Set_Selected_Index(int index) {ListClass::Set_Selected_Index(index);};\n\n\t\t/*\n\t\t**\tCheckmark utility functions\n\t\t*/\n\t\tvoid Check_Item(int index, bool checked);\t// sets checked state of item\n\t\tbool Is_Checked(int index) const;\t\t\t\t// gets checked state of item\n\n\t\tvoid Set_Read_Only(int rdonly) {IsReadOnly = rdonly;}\n\n\t\t/*\n\t\t**\tThis defines the ASCII value of the checkmark character & non-checkmark\n\t\t**\tcharacter.\n\t\t*/\n\t\ttypedef enum CheckListClassEnum {\n\t\t\tCHECK_CHAR = '\\3',\n\t\t\tUNCHECK_CHAR = ' '\n\t\t} CheckListClassEnum;\n\n\tprotected:\n\t\tvirtual int Action(unsigned flags, KeyNumType &key);\n\t\tvirtual void Draw_Entry(int index, int x, int y, int width, int selected);\n\n\tprivate:\n\t\tbool IsReadOnly;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/CLASS.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\t\t\t\n"
  },
  {
    "path": "CODE/CO-WC32.LNT",
    "content": "//    Compiler Options for Watcom C, C++ 32 bit\n\n-cwc\n\n//    This file contains options to allow PC-lint to process source\n//    files for your compiler.  It is used as follows:\n//\n//    lint  co-wc32.lnt  source-file(s)\n//\n-d_M_IX86=200   // assume Intel 80286 architecture -- modify to suit\n-d__declspec()= // ignore this construct\n\n  // additional reserve words needed\n+rw(_loadds,_export)\n+rw(__interrupt,__near,__far,__huge,__fortran,__pascal,__cdecl)\n+rw(__export,__loadds,__saveregs,__asm,__fastcall,__stdcall)\n+rw(_export)\n\n+fcd            // makes cdecl significant -- used for proto generation\n+fcu            // chars are by default unsigned\n+fsu            // so are strings\n-d__386__       // pre-defined macro for 386 version, not set by -cwc\n-d__FLAT__      // not set by -cwc\n-si4            // sizeof(int)         is 4\n-spN4           // sizeof(near pointer) is 4\n-spF6           // sizeof( far pointer) is 6\n-sld10          // sizeof(long double) is 10.\n-function(exit,_exit)   // _exit() is like exit()\n-emacro(734,putc)   // don't complain about items being too large.\n-emacro(506,putc)   // don't complain about constant Boolean\n-emacro(???,va_arg)     // the va_arg() macro can yield 415, 416, 661, 662\n\t\t\t// 796 and 797 (out-of-bounds errors).\n\n   // While processing compiler (library) header files ...\n-elib(46)       // an unsigned short bit field is used as __FILLER__\n-elib(522)      // function return value ignored\n-elib(537)      // repeated include file (ios.h)\n-elib(641)      // converting enum to int\n-elib(652)      // suppress message about #define of earlier declared symbols\n-elib(655)      // ORing enum's\n-elib(726)      // extraneous comma in enumeration\n-elib(760)      // suppress message about multiple identical macro defs\n-elib(762)      // suppress message about multiple identical declarations and\n-elib(806)      // small bit field is signed\n-elib(1053)     // prototypes cannot be distinguished\n-elib(1511)     // member (rdbuf) hides nonvirtual member\n-elib(1704)     // private copy constructor\n-elib(1712)     // default constructor missing\n-elib(1717)     // empty prototypes\n-elib(1720)     // strange argument to assignment operator\n-elib(1721)     // unusual operator =() declaration\n-elib(1722)     // assignment operator does not return ref to class\n-elib(1724)     // strange argument to copy constructor\n\n-esym(1702,operator<<,operator>>)\n\n//  The following functions exhibit variable return modes.\n//  That is, they may equally-usefully be called for a value\n//  as called just for their effects.  Accordingly we inhibit\n//  Warning 534 for these functions.\n//  Feel free to add to or subtract from this list.\n\n-esym(534,close,creat,fclose,fflush,fprintf,fputc)\n-esym(534,fputs,fscanf,fseek,fwrite,lseek,memcpy,memmove,memset)\n-esym(534,printf,puts,scanf,sprintf,sscanf,strcat,strcpy)\n-esym(534,strncat,strncpy,unlink,write)\n\n"
  },
  {
    "path": "CODE/COLRLIST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/COLRLIST.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : COLRLIST.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : April 19, 1995 [BRR]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ColorListClass::Add_Item -- Adds an item to the list                                      *\n *   ColorListClass::ColorListClass -- Class constructor                                       *\n *   ColorListClass::Draw_Entry -- Draws one text line                                         *\n *   ColorListClass::Remove_Item -- Removes an item from the list                              *\n *   ColorListClass::Set_Selected_Style -- tells how to draw selected item                     *\n *   ColorListClass::~ColorListClass -- Class destructor                                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***************************************************************************\n * ColorListClass::ColorListClass -- class constructor                     *\n *                                                                         *\n * INPUT:                                                                  *\n *      id               button ID                                         *\n *      x,y            upper-left corner, in pixels                        *\n *      w,h            width, height, in pixels                            *\n *      list            ptr to array of char strings to list               *\n *    flags          flags for mouse, style of listbox                     *\n *      up,down         pointers to shapes for up/down buttons             *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:          01/05/1995 MML : Created.                             *\n *=========================================================================*/\nColorListClass::ColorListClass (int id, int x, int y, int w, int h,\n\tTextPrintType flags, void const * up, void const * down) :\n\tListClass (id, x, y, w, h, flags, up, down),\n\tStyle(SELECT_HIGHLIGHT),\n\tSelectColor(NULL)\n{\n}\n\n\n/***************************************************************************\n * ColorListClass::~ColorListClass -- Class destructor                     *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1995 BRR : Created.                                             *\n *=========================================================================*/\nColorListClass::~ColorListClass(void)\n{\n\tColors.Clear();\n\tSelectColor = 0;\n}\n\n\n/***************************************************************************\n * ColorListClass::Add_Item -- Adds an item to the list                    *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\ttext\t\ttext to add to list                                      \t*\n *\t\tcolor\t\tcolor for item                                          \t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tposition of item in the list                                       \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1995 BRR : Created.                                             *\n *=========================================================================*/\nint ColorListClass::Add_Item(char const * text, RemapControlType * color)\n{\n\tColors.Add(color);\n\treturn(ListClass::Add_Item(text));\n}\n\n\n/***************************************************************************\n * ColorListClass::Add_Item -- Adds an item to the list                    *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\ttext\t\ttext to add to list                                      \t*\n *\t\tcolor\t\tcolor for item                                          \t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tposition of item in the list                                       \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1995 BRR : Created.                                             *\n *=========================================================================*/\nint ColorListClass::Add_Item(int text, RemapControlType * color)\n{\n\tColors.Add(color);\n\treturn(ListClass::Add_Item(text));\n}\n\n\n/***************************************************************************\n * ColorListClass::Remove_Item -- Removes an item from the list            *\n *                                                                         *\n * INPUT:                                                                  *\n *      text      ptr to item to remove                                    *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid ColorListClass::Remove_Item(char const * text)\n{\n\tint index = List.ID(text);\n\tif (index != -1) {\n\t\tColors.Delete(index);\n\t\tListClass::Remove_Item(text);\n\t}\n}\n\n\n/***************************************************************************\n * ColorListClass::Set_Selected_Style -- tells how to draw selected item   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tstyle\t\tstyle to draw                                           \t\t*\n *\t\tcolor\t\tcolor to draw the special style in; -1 = use item's color\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.                                                              \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid ColorListClass::Set_Selected_Style(SelectStyleType style, RemapControlType * color)\n{\n\tStyle = style;\n\tSelectColor = color;\n}\n\n\n/***************************************************************************\n * ColorListClass::Draw_Entry -- Draws one text line                       *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\t\tindex into List of item to draw                      \t\t*\n *\t\tx,y\t\t\tx,y coords to draw at                                  \t*\n *\t\twidth\t\t\tmaximum width allowed for text                       \t\t*\n *\t\tselected\t\ttrue = this item is selected                         \t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.                                                              \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid ColorListClass::Draw_Entry(int index, int x, int y, int width, int selected)\n{\n\tRemapControlType * color;\n\n\t/*\n\t** Draw a non-selected item in its color\n\t*/\n\tif (!selected) {\n\t\tConquer_Clip_Text_Print(List[index], x, y, Colors[index], TBLACK, TextFlags, width, Tabs);\n\t\treturn;\n\t}\n\n\t/*\n\t** For selected items, choose the right color & style:\n\t*/\n\tif (SelectColor == NULL) {\n\t\tcolor = Colors[index];\n\t} else {\n\t\tcolor = SelectColor;\n\t}\n\n\tswitch (Style) {\n\t\t/*\n\t\t**\tNONE: Just print the string in its native color\n\t\t*/\n\t\tcase SELECT_NORMAL:\n\t\t\tConquer_Clip_Text_Print(List[index], x, y, Colors[index], TBLACK,\n\t\t\t\tTextFlags, width, Tabs);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tHIGHLIGHT: Draw the string in the highlight color (SelectColor must\n\t\t**\tbe set)\n\t\t*/\n\t\tcase SELECT_HIGHLIGHT:\n\t\t\tif (TextFlags & TPF_6PT_GRAD) {\n\t\t\t\tConquer_Clip_Text_Print(List[index], x, y, color, TBLACK, TextFlags | TPF_BRIGHT_COLOR, width, Tabs);\n\t\t\t} else {\n\t\t\t\tConquer_Clip_Text_Print(List[index], x, y, color, TBLACK, TextFlags, width, Tabs);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tBOX: Draw a box around the item in the current select color\n\t\t*/\n\t\tcase SELECT_BOX:\n\t\t\tLogicPage->Draw_Rect (x, y, x + width - 2, y + LineHeight - 2, color->Color);\n\t\t\tConquer_Clip_Text_Print(List[index], x, y, Colors[index], TBLACK, TextFlags, width, Tabs);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tBAR: draw a color bar under the text\n\t\t*/\n\t\tcase SELECT_BAR:\n\t\t\tif (TextFlags & TPF_6PT_GRAD) {\n\t\t\t\tLogicPage->Fill_Rect(x, y, x + width - 1, y + LineHeight - 1, color->Color);\n\t\t\t\tConquer_Clip_Text_Print(List[index], x, y, Colors[index], TBLACK, TextFlags | TPF_BRIGHT_COLOR, width, Tabs);\n\t\t\t} else {\n\t\t\t\tLogicPage->Fill_Rect(x, y, x + width - 2, y + LineHeight - 2, color->Color);\n\t\t\t\tConquer_Clip_Text_Print(List[index], x, y, Colors[index], TBLACK, TextFlags, width, Tabs);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tINVERT: Draw text as the background color on foreground color\n\t\t*/\n\t\tcase SELECT_INVERT:\n\t\t\tLogicPage->Fill_Rect (x, y, x + width - 1, y + LineHeight - 1, Colors[index]->Color);\n\t\t\tbreak;\n\t}\n}\n"
  },
  {
    "path": "CODE/COLRLIST.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/COLRLIST.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : COLRLIST.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef COLORLIST_H\n#define COLORLIST_H\n\n#include \"list.h\"\n\n\n/***************************************************************************\n** This class adds the ability for every list item to have a different color.\n*/\nclass ColorListClass : public ListClass\n{\n\tpublic:\n\t\t/*********************************************************************\n\t\t** These enums are the ways a selected item can be drawn\n\t\t*/\n\t\t//lint -esym(578,SELECT_NONE)\n\t\ttypedef enum SelectEnum {\n\t\t\tSELECT_NORMAL,\t\t\t\t// selected items aren't drawn differently\n\t\t\tSELECT_HIGHLIGHT,\t\t\t// item is highlighted\n\t\t\tSELECT_BOX,\t\t\t\t\t// draw a box around the item\n\t\t\tSELECT_BAR,\t\t\t\t\t// draw a bar behind the item\n\t\t\tSELECT_INVERT\t\t\t\t// draw the string inverted\n\t\t} SelectStyleType;\n\n\t\tColorListClass(int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down);\n\t\tvirtual ~ColorListClass(void);\n\n\t\tvirtual int  Add_Item(char const * text, RemapControlType * color = NULL);\n\t\tvirtual int  Add_Item(int text, RemapControlType * color = NULL);\n\t\tvirtual void Remove_Item(char const * text);\n\n\t\tvirtual void Set_Selected_Style(SelectStyleType style, RemapControlType * color = NULL);\n\n\t\t/*\n\t\t**\tThis is the list of colors for each item.\n\t\t*/\n\t\tDynamicVectorClass<RemapControlType *> Colors;\n\n\tprotected:\n\t\tvirtual void Draw_Entry(int index, int x, int y, int width, int selected);\n\n\t\t/*\n\t\t**\tThis tells how to draw the selected item.\n\t\t*/\n\t\tSelectStyleType Style;\n\t\tRemapControlType * SelectColor;\n\n};\n\n#endif\n"
  },
  {
    "path": "CODE/COMBAT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/COMBAT.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : COMBAT.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 19, 1994                                           *\n *                                                                                             *\n *                  Last Update : July 26, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Combat_Anim -- Determines explosion animation to play.                                    *\n *   Explosion_Damage -- Inflict an explosion damage affect.                                   *\n *   Modify_Damage -- Adjusts damage to reflect the nature of the target.                      *\n *   Wide_Area_Damage -- Apply wide area damage to the map.                                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * Modify_Damage -- Adjusts damage to reflect the nature of the target.                        *\n *                                                                                             *\n *    This routine is the core of combat tactics. It implements the                            *\n *    affect various armor types have against various weapon types. By                         *\n *    careful exploitation of this table, tactical advantage can be                            *\n *    obtained.                                                                                *\n *                                                                                             *\n * INPUT:   damage   -- The damage points to process.                                          *\n *                                                                                             *\n *          warhead  -- The source of the damage points.                                       *\n *                                                                                             *\n *          armor    -- The type of armor defending against the damage.                        *\n *                                                                                             *\n *          distance -- The distance (in leptons) from the source of the damage.               *\n *                                                                                             *\n * OUTPUT:  Returns with the adjusted damage points to inflict upon the                        *\n *          target.                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/16/1994 JLB : Created.                                                                 *\n *   04/17/1994 JLB : Always does a minimum of damage.                                         *\n *   01/01/1995 JLB : Takes into account distance from damage source.                          *\n *   04/11/1996 JLB : Changed damage fall-off formula for less damage fall-off.                *\n *=============================================================================================*/\nint Modify_Damage(int damage, WarheadType warhead, ArmorType armor, int distance)\n{\n\tif (!damage) return(damage);\n\n\t/*\n\t**\tIf there is no raw damage value to start with, then\n\t**\tthere can be no modified damage either.\n\t*/\n\tif (Special.IsInert || !damage || warhead == WARHEAD_NONE) return(0);\n\n\t/*\n\t**\tNegative damage (i.e., heal) is always applied full strength, but only if the heal\n\t**\teffect is close enough.\n\t*/\n\tif (damage < 0) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tif (distance < 0x008) {\n\t\t\tif(warhead != WARHEAD_MECHANICAL && armor == ARMOR_NONE) return(damage);\n\t\t\tif(warhead == WARHEAD_MECHANICAL && armor != ARMOR_NONE) return(damage);\n\t\t}\n#else\n\t\tif (distance < 0x008 && armor == ARMOR_NONE) return(damage);\n#endif\n\t\treturn(0);\n\t}\n\n\tWarheadTypeClass const * whead = WarheadTypeClass::As_Pointer(warhead);\n//\tWarheadTypeClass const * whead = &Warheads[warhead];\n\n\tdamage = damage * whead->Modifier[armor];\n\n\t/*\n\t**\tReduce damage according to the distance from the impact point.\n\t*/\n\tif (damage) {\n\t\tif (!whead->SpreadFactor) {\n\t\t\tdistance /= PIXEL_LEPTON_W/4;\n\t\t} else {\n\t\t\tdistance /= whead->SpreadFactor * (PIXEL_LEPTON_W/2);\n\t\t}\n\t\tdistance = Bound(distance, 0, 16);\n\t\tif (distance) {\n\t\t\tdamage = damage / distance;\n\t\t}\n\n\t\t/*\n\t\t**\tAllow damage to drop to zero only if the distance would have\n\t\t**\treduced damage to less than 1/4 full damage. Otherwise, ensure\n\t\t**\tthat at least one damage point is done.\n\t\t*/\n\t\tif (distance < 4) {\n\t\t\tdamage = max(damage, Rule.MinDamage);\n\t\t}\n\t}\n\n\tdamage = min(damage, Rule.MaxDamage);\n\treturn(damage);\n}\n\n\n/***********************************************************************************************\n * Explosion_Damage -- Inflict an explosion damage affect.                                     *\n *                                                                                             *\n *    Processes the collateral damage affects typically caused by an                           *\n *    explosion.                                                                               *\n *                                                                                             *\n * INPUT:   coord    -- The coordinate of ground zero.                                         *\n *                                                                                             *\n *          strength -- Raw damage points at ground zero.                                      *\n *                                                                                             *\n *          source   -- Source of the explosion (who is responsible).                          *\n *                                                                                             *\n *          warhead  -- The kind of explosion to process.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine can consume some time and will affect the AI                       *\n *             of nearby enemy units (possibly).                                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/16/1991 JLB : Created.                                                                 *\n *   11/30/1991 JLB : Uses coordinate system.                                                  *\n *   12/27/1991 JLB : Radius of explosion damage effect.                                       *\n *   04/13/1994 JLB : Streamlined.                                                             *\n *   04/16/1994 JLB : Warhead damage type modifier.                                            *\n *   04/17/1994 JLB : Cleaned up.                                                              *\n *   06/20/1994 JLB : Uses object pointers to distribute damage.                               *\n *   06/20/1994 JLB : Source is a pointer.                                                     *\n *   06/18/1996 JLB : Strength could be negative for healing effects.                          *\n *=============================================================================================*/\nvoid Explosion_Damage(COORDINATE coord, int strength, TechnoClass * source, WarheadType warhead)\n{\n\tCELL\t\t\t\tcell;\t\t\t// Cell number under explosion.\n\tObjectClass *\tobject;\t\t\t// Working object pointer.\n\tObjectClass *\tobjects[32];\t// Maximum number of objects that can be damaged.\n\tint\t\t\t\tdistance;\t// Distance to unit.\n\tint\t\t\t\trange;\t\t// Damage effect radius.\n\tint\t\t\t\tcount;\t\t// Number of vehicle IDs in list.\n\n\tif (!strength || Special.IsInert || warhead == WARHEAD_NONE) return;\n\n\tWarheadTypeClass const * whead = WarheadTypeClass::As_Pointer(warhead);\n//\tWarheadTypeClass const * whead = &Warheads[warhead];\n//\trange = ICON_LEPTON_W*2;\n\trange = ICON_LEPTON_W + (ICON_LEPTON_W >> 1);\n\tcell = Coord_Cell(coord);\n\tif ((unsigned)cell >= MAP_CELL_TOTAL) return;\n\n\tCellClass * cellptr = &Map[cell];\n\tObjectClass * impacto = cellptr->Cell_Occupier();\n\n\t/*\n\t**\tFill the list of unit IDs that will have damage\n\t**\tassessed upon them. The units can be lifted from\n\t**\tthe cell data directly.\n\t*/\n\tcount = 0;\n\tfor (FacingType i = FACING_NONE; i < FACING_COUNT; i++) {\n\t\t/*\n\t\t**\tFetch a pointer to the cell to examine. This is either\n\t\t**\tan adjacent cell or the center cell. Damage never spills\n\t\t**\tfurther than one cell away.\n\t\t*/\n\t\tif (i != FACING_NONE) {\n\t\t\tcellptr = &Map[cell].Adjacent_Cell(i);\n\t\t}\n\n\t\t/*\n\t\t**\tAdd all objects in this cell to the list of objects to possibly apply\n\t\t** damage to. The list stops building when the object pointer list becomes\n\t\t** full.  Do not include overlapping objects; selection state can affect\n\t\t** the overlappers, and this causes multiplayer games to go out of sync.\n\t\t*/\n\t\tobject = cellptr->Cell_Occupier();\n\t\twhile (object) {\n\t\t\tif (!object->IsToDamage && object != source) {\n\t\t\t\tobject->IsToDamage = true;\n\t\t\t\tobjects[count++] = object;\n\t\t\t\tif (count >= ARRAY_SIZE(objects)) break;\n\t\t\t}\n\t\t\tobject = object->Next;\n\t\t}\n \t\tif (count >= ARRAY_SIZE(objects)) break;\n\t}\n\n\t/*\n\t**\tSweep through the units to be damaged and damage them. When damaging\n\t**\tbuildings, consider a hit on any cell the building occupies as if it\n\t**\twere a direct hit on the building's center.\n\t*/\n\tfor (int index = 0; index < count; index++) {\n\t\tobject = objects[index];\n\n\t\tobject->IsToDamage = false;\n\t\tif (object->IsActive) {\n\t\t\tif (object->What_Am_I() == RTTI_BUILDING && impacto == object) {\n\t\t\t\tdistance = 0;\n\t\t\t} else {\n\t\t\t\tdistance = Distance(coord, object->Center_Coord());\n\t\t\t}\n\t\t\tif (object->IsDown && !object->IsInLimbo && distance < range) {\n\t\t\t\tint damage = strength;\n\t\t\t\tobject->Take_Damage(damage, distance, warhead, source);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is a wall present at this location, it may be destroyed. Check to\n\t**\tmake sure that the warhead is of the kind that can destroy walls.\n\t*/\n\tcellptr = &Map[cell];\n\tif (cellptr->Overlay != OVERLAY_NONE) {\n\t\tOverlayTypeClass const * optr = &OverlayTypeClass::As_Reference(cellptr->Overlay);\n\n\t\tif (optr->IsTiberium && whead->IsTiberiumDestroyer) {\n\t\t\tcellptr->Reduce_Tiberium(strength / 10);\n\t\t}\n\t\tif (optr->IsWall) {\n\t\t\tif (whead->IsWallDestroyer || (whead->IsWoodDestroyer && optr->IsWooden)) {\n\t\t\t\tMap[cell].Reduce_Wall(strength);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is a bridge at this location, then it may be destroyed by the\n\t**\tcombat damage.\n\t*/\n\tif (cellptr->TType == TEMPLATE_BRIDGE1 || cellptr->TType == TEMPLATE_BRIDGE2 ||\n\t\t cellptr->TType == TEMPLATE_BRIDGE1H || cellptr->TType == TEMPLATE_BRIDGE2H ||\n\t\t cellptr->TType == TEMPLATE_BRIDGE_1A || cellptr->TType == TEMPLATE_BRIDGE_1B ||\n\t\t cellptr->TType == TEMPLATE_BRIDGE_2A || cellptr->TType == TEMPLATE_BRIDGE_2B ||\n\t\t cellptr->TType == TEMPLATE_BRIDGE_3A || cellptr->TType == TEMPLATE_BRIDGE_3B ) {\n\n\t\tif (((warhead == WARHEAD_AP || warhead == WARHEAD_HE) && Random_Pick(1, Rule.BridgeStrength) < strength)) {\n\t\t\tMap.Destroy_Bridge_At(cell);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Combat_Anim -- Determines explosion animation to play.                                      *\n *                                                                                             *\n *    This routine is called when a projectile impacts. This routine will determine what       *\n *    animation should be played.                                                              *\n *                                                                                             *\n * INPUT:   damage   -- The amount of damage this warhead possess (warhead size).              *\n *                                                                                             *\n *          warhead  -- The type of warhead.                                                   *\n *                                                                                             *\n *          land     -- The land type that this explosion is over. Sometimes, this makes       *\n *                      a difference (especially over water).                                  *\n *                                                                                             *\n * OUTPUT:  Returns with the animation to play. If no animation is to be played, then          *\n *          ANIM_NONE is returned.                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nAnimType Combat_Anim(int damage, WarheadType warhead, LandType land)\n{\n\t/*\n\t**\tFor cases of no damage or invalid warhead, don't have any\n\t**\tanimation effect at all.\n\t*/\n\tif (damage == 0 || warhead == WARHEAD_NONE) {\n\t\treturn(ANIM_NONE);\n\t}\n\n\tstatic AnimType _aplist[] = {\n\t\tANIM_VEH_HIT3,\t\t\t\t\t// Small fragment throwing explosion -- burn/exp mix.\n\t\tANIM_VEH_HIT2,\t\t\t\t\t//\tSmall fragment throwing explosion -- pop & sparkles.\n\t\tANIM_FRAG1,\t\t\t\t\t\t// Medium fragment throwing explosion -- short decay.\n\t\tANIM_FBALL1,\t\t\t\t\t// Large fireball explosion (bulges rightward).\n\t};\n\n\tstatic AnimType _helist[] = {\n\t\tANIM_VEH_HIT1,\t\t\t\t\t//\tSmall fireball explosion (bulges rightward).\n\t\tANIM_VEH_HIT2,\t\t\t\t\t//\tSmall fragment throwing explosion -- pop & sparkles.\n\t\tANIM_ART_EXP1,\t\t\t\t\t// Large fragment throwing explosion -- many sparkles.\n\t\tANIM_FBALL1,\t\t\t\t\t// Large fireball explosion (bulges rightward).\n\t};\n\n\tstatic AnimType _firelist[] = {\n\t\tANIM_NAPALM1,\t\t\t\t\t// Small napalm burn.\n\t\tANIM_NAPALM2,\t\t\t\t\t// Medium napalm burn.\n\t\tANIM_NAPALM3,\t\t\t\t\t// Large napalm burn.\n\t};\n\n\tstatic AnimType _waterlist[] = {\n\t\tANIM_WATER_EXP3,\n\t\tANIM_WATER_EXP2,\n\t\tANIM_WATER_EXP1,\n\t};\n\n\tWarheadTypeClass const * wptr = WarheadTypeClass::As_Pointer(warhead);\n//\tWarheadTypeClass const * wptr = &Warheads[warhead];\n\tswitch (wptr->ExplosionSet) {\n\t\tcase 6:\n\t\t\treturn(ANIM_ATOM_BLAST);\n\n\t\tcase 2:\n\t\t\tif (damage > 15) {\n\t\t\t\treturn(ANIM_PIFFPIFF);\n\t\t\t}\n\t\t\treturn(ANIM_PIFF);\n\n\t\tcase 4:\n\t\t\tif (land == LAND_NONE) return(ANIM_FLAK);\n//\tFixed math error\n\t\t\tif (land == LAND_WATER) return(_waterlist[(ARRAY_SIZE(_waterlist)-1) * fixed(min(damage, 90), 90)]);\n\t\t\treturn(_aplist[(ARRAY_SIZE(_aplist)-1) * fixed(min(damage, 90), 90)]);\n\n\t\tcase 5:\n\t\t\tif (land == LAND_NONE) return(ANIM_FLAK);\n\t\t\tif (land == LAND_WATER) return(_waterlist[(ARRAY_SIZE(_waterlist)-1) * fixed(min(damage, 130), 130)]);\n\t\t\treturn(_helist[(ARRAY_SIZE(_helist)-1) * fixed(min(damage, 130), 130)]);\n\n\t\tcase 3:\n\t\t\tif (land == LAND_NONE) return(ANIM_FLAK);\n\t\t\tif (land == LAND_WATER) return(_waterlist[(ARRAY_SIZE(_waterlist)-1) * fixed(min(damage, 150), 150)]);\n\t\t\treturn(_firelist[(ARRAY_SIZE(_firelist)-1) * fixed(min(damage, 150), 150)]);\n\n\t\tcase 1:\n\t\t\treturn(ANIM_PIFF);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(ANIM_NONE);\n}\n\n\n/***********************************************************************************************\n * Wide_Area_Damage -- Apply wide area damage to the map.                                      *\n *                                                                                             *\n *    This routine will apply damage to a very wide area on the map. The damage will be        *\n *    spread out from the coordinate specified by the radius specified. The amount of damage   *\n *    will attenuate according to the distance from center.                                    *\n *                                                                                             *\n * INPUT:   coord    -- The coordinate that the explosion damage will center about.            *\n *                                                                                             *\n *          radius   -- The radius of the explosion.                                           *\n *                                                                                             *\n *          damage   -- The amount of damage to apply at the center location.                  *\n *                                                                                             *\n *          source   -- Pointer to the purpetrator of the damage (if any).                     *\n *                                                                                             *\n *          warhead  -- The type of warhead that is causing the damage.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Wide_Area_Damage(COORDINATE coord, LEPTON radius, int rawdamage, TechnoClass * source, WarheadType warhead)\n{\n\tint cell_radius = (radius + CELL_LEPTON_W-1) / CELL_LEPTON_W;\n\tCELL cell = Coord_Cell(coord);\n\n\tfor (int x = -cell_radius; x <= cell_radius; x++) {\n\t\tfor (int y = -cell_radius; y <= cell_radius; y++) {\n\t\t\tint xpos = Cell_X(cell) + x;\n\t\t\tint ypos = Cell_Y(cell) + y;\n\n\t\t\t/*\n\t\t\t**\tIf the potential damage cell is outside of the map bounds,\n\t\t\t**\tthen don't process it. This unusual check method ensures that\n\t\t\t**\tdamage won't wrap from one side of the map to the other.\n\t\t\t*/\n\t\t\tif ((unsigned)xpos > MAP_CELL_W) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ((unsigned)ypos > MAP_CELL_H) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tCELL tcell = XY_Cell(xpos, ypos);\n\t\t\tif (!Map.In_Radar(tcell)) continue;\n\n\t\t\tint dist_from_center = Distance(XY_Coord(x+cell_radius, y+cell_radius), XY_Coord(cell_radius, cell_radius));\n\t\t\tint damage = rawdamage * Inverse(fixed(cell_radius, dist_from_center));\n\t\t\tExplosion_Damage(Cell_Coord(tcell), damage, source, warhead);\n\t\t\tif (warhead == WARHEAD_FIRE && damage > 100) {\n\t\t\t\tnew SmudgeClass(Random_Pick(SMUDGE_SCORCH1, SMUDGE_SCORCH6), Cell_Coord(tcell));\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "CODE/COMBUF.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/COMBUF.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : COMBUF.CPP                             \t*\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : October 23, 1995 [BRR]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   CommBufferClass::CommBufferClass -- class constructor           \t\t*\n *   CommBufferClass::~CommBufferClass -- class destructor           \t\t*\n *   CommBufferClass::Init -- initializes this queue                       *\n *   CommBufferClass::Init_Send_Queue -- Clears the send queue             *\n *   CommBufferClass::Queue_Send -- queues a message for sending           *\n *   CommBufferClass::UnQueue_Send -- removes next entry from send queue\t*\n *   CommBufferClass::Get_Send -- gets ptr to queue entry                  *\n *   CommBufferClass::Queue_Receive -- queues a received message\t\t\t\t*\n *   CommBufferClass::UnQueue_Receive -- removes next entry from send queue*\n *   CommBufferClass::Get_Receive -- gets ptr to queue entry               *\n *   CommBufferClass::Add_Delay -- adds a new delay value for response time*\n *   CommBufferClass::Avg_Response_Time -- returns average response time  \t*\n *   CommBufferClass::Max_Response_Time -- returns max response time  \t\t*\n *   CommBufferClass::Reset_Response_Time -- resets computations\t\t\t\t*\n *   Mono_Debug_Print -- Debug output routine                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n#include <stdio.h>\n#include <mem.h>\n#include \"combuf.h\"\n#include \"connect.h\"\t// for command names for debug output\n#include \"wwlib32.h\"\t// to enable mono output\n\n\n/***************************************************************************\n * CommBufferClass::CommBufferClass -- class constructor             \t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t# queue entries for sending\t\t\t\t\t\t\t\t\t\t*\n *\t\tnumreceive\t# queue entries for receiving\t\t\t\t\t\t\t\t\t\t*\n *\t\tmaxlen\t\tmaximum desired packet length, in bytes\t\t\t\t\t\t*\n *\t\textralen\t\tmax size of app-specific extra bytes (optional)\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nCommBufferClass::CommBufferClass(int numsend, int numreceive, int maxlen,\n\tint extralen)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tInit variables\n\t//------------------------------------------------------------------------\n\tMaxSend = numsend;\n\tMaxReceive = numreceive;\n\tMaxPacketSize = maxlen;\n\tMaxExtraSize = extralen;\n\n\t//------------------------------------------------------------------------\n\t//\tAllocate the queue entries\n\t//------------------------------------------------------------------------\n\tSendQueue = new SendQueueType[numsend];\n\tReceiveQueue = new ReceiveQueueType[numreceive];\n\n\tSendIndex = new int[numsend];\n\tReceiveIndex = new int[numreceive];\n\n\t//------------------------------------------------------------------------\n\t//\tAllocate queue entry buffers\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tSendQueue[i].Buffer = new char[maxlen];\n\t\tif (MaxExtraSize > 0) {\n\t\t\tSendQueue[i].ExtraBuffer = new char[MaxExtraSize];\n\t\t}\n\t\telse {\n\t\t\tSendQueue[i].ExtraBuffer = NULL;\n\t\t}\n\t}\n\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tReceiveQueue[i].Buffer = new char[maxlen];\n\t\tif (MaxExtraSize > 0) {\n\t\t\tReceiveQueue[i].ExtraBuffer = new char[MaxExtraSize];\n\t\t}\n\t\telse {\n\t\t\tReceiveQueue[i].ExtraBuffer = NULL;\n\t\t}\n\t}\n\n\tInit();\n\n}\t/* end of CommBufferClass */\n\n\n/***************************************************************************\n * CommBufferClass::~CommBufferClass -- class destructor             \t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nCommBufferClass::~CommBufferClass()\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tFree queue entry buffers\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tdelete [] SendQueue[i].Buffer;\n\t\tif (SendQueue[i].ExtraBuffer) {\n\t\t\tdelete [] SendQueue[i].ExtraBuffer;\n\t\t}\n\t}\n\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tdelete [] ReceiveQueue[i].Buffer;\n\t\tif (ReceiveQueue[i].ExtraBuffer) {\n\t\t\tdelete [] ReceiveQueue[i].ExtraBuffer;\n\t\t}\n\t}\n\n\tdelete [] SendQueue;\n\tdelete [] ReceiveQueue;\n\n\tdelete [] SendIndex;\n\tdelete [] ReceiveIndex;\n\n}\t/* end of ~CommBufferClass */\n\n\n/***************************************************************************\n * CommBufferClass::Init -- initializes this queue                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/20/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid CommBufferClass::Init(void)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tInit data members\n\t//------------------------------------------------------------------------\n\tSendTotal = 0L;\n\tReceiveTotal = 0L;\n\n\tDelaySum = 0L;\n\tNumDelay = 0L;\n\tMeanDelay = 0L;\n\tMaxDelay = 0L;\n\n\tSendCount = 0;\n\n\tReceiveCount = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInit the queue entries\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tSendQueue[i].IsActive = 0;\n\t\tSendQueue[i].IsACK = 0;\n\t\tSendQueue[i].FirstTime = 0L;\n\t\tSendQueue[i].LastTime = 0L;\n\t\tSendQueue[i].SendCount = 0L;\n\t\tSendQueue[i].BufLen = 0;\n\t\tSendQueue[i].ExtraLen = 0;\n\n\t\tSendIndex[i] = 0;\n\t}\n\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tReceiveQueue[i].IsActive = 0;\n\t\tReceiveQueue[i].IsRead = 0;\n\t\tReceiveQueue[i].IsACK = 0;\n\t\tReceiveQueue[i].BufLen = 0;\n\t\tReceiveQueue[i].ExtraLen = 0;\n\n\t\tReceiveIndex[i] = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tInit debug values\n\t//------------------------------------------------------------------------\n\tDebugOffset = 0;\n\tDebugSize = 0;\n\tDebugNames = NULL;\n\tDebugNameCount = 0;\n\n}\t/* end of Init */\n\n\n/***************************************************************************\n * CommBufferClass::Init_Send_Queue -- Clears the send queue               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/23/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid CommBufferClass::Init_Send_Queue(void)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tInit data members\n\t//------------------------------------------------------------------------\n\tSendCount = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInit the queue entries\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tSendQueue[i].IsActive = 0;\n\t\tSendQueue[i].IsACK = 0;\n\t\tSendQueue[i].FirstTime = 0L;\n\t\tSendQueue[i].LastTime = 0L;\n\t\tSendQueue[i].SendCount = 0L;\n\t\tSendQueue[i].BufLen = 0;\n\t\tSendQueue[i].ExtraLen = 0;\n\n\t\tSendIndex[i] = 0;\n\t}\n\n}\t/* end of Init_Send_Queue */\n\n\n/***************************************************************************\n * CommBufferClass::Queue_Send -- queues a message for sending             *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer containing the message\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of 'buf'\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textrabuf\t\tbuffer containing extra data (optional)\t\t\t\t\t\t*\n *\t\textralen\t\tlength of extra data (optional)\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = no room in the queue\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint CommBufferClass::Queue_Send(void *buf, int buflen, void *extrabuf,\n\tint extralen)\n{\n\tint i;\n\tint index;\n\n\t//------------------------------------------------------------------------\n\t//\tError if no room in the queue\n\t//------------------------------------------------------------------------\n\tif (SendCount==MaxSend || buflen > MaxPacketSize)\n\t\treturn(0);\n\n\t//------------------------------------------------------------------------\n\t//\tFind an empty slot\n\t//------------------------------------------------------------------------\n\tindex = -1;\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tif (SendQueue[i].IsActive==0) {\n\t\t\tindex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (index == -1)\n\t\treturn (0);\n\n\t//------------------------------------------------------------------------\n\t//\tSet entry flags\n\t//------------------------------------------------------------------------\n\tSendQueue[index].IsActive = 1;\t\t\t// entry is now active\n\tSendQueue[index].IsACK = 0;\t\t\t\t// entry hasn't been ACK'd\n\tSendQueue[index].FirstTime = 0L;\t\t\t// filled in by Manager when sent\n\tSendQueue[index].LastTime = 0L;\t\t\t// filled in by Manager when sent\n\tSendQueue[index].SendCount = 0L;\t\t\t// filled in by Manager when sent\n\tSendQueue[index].BufLen = buflen;\t\t// save buffer size\n\n\t//------------------------------------------------------------------------\n\t//\tCopy the packet data\n\t//------------------------------------------------------------------------\n\tmemcpy(SendQueue[index].Buffer,buf,buflen);\n\n\t//------------------------------------------------------------------------\n\t//\tFill in the extra data, if there is any\n\t//------------------------------------------------------------------------\n\tif (extrabuf!=NULL && extralen > 0 && extralen <= MaxExtraSize) {\n\t\tmemcpy(SendQueue[index].ExtraBuffer,extrabuf,extralen);\n\t\tSendQueue[index].ExtraLen = extralen;\n\t}\n\telse {\n\t\tSendQueue[index].ExtraLen = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSave this entry's index\n\t//------------------------------------------------------------------------\n\tSendIndex[SendCount] = index;\n\n\t//------------------------------------------------------------------------\n\t//\tIncrement counters & entry ptr\n\t//------------------------------------------------------------------------\n\tSendCount++;\n\tSendTotal++;\n\n\treturn(1);\n\n}\t/* end of Queue_Send */\n\n\n/***************************************************************************\n * CommBufferClass::UnQueue_Send -- removes next entry from send queue\t\t*\n *                                                                         *\n * Frees the given entry; the index given by the caller is the \"active\"\t\t*\n * index value (ie the \"nth\" active entry), not the actual index in the\t\t*\n * array.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to store entry's data in; if NULL, it's discarded\t*\n *\t\tbuflen\t\tfilled in with length of entry retrieved\t\t\t\t\t\t*\n *\t\tindex\t\t\t\"index\" of entry to un-queue\t\t\t\t\t\t\t\t\t\t*\n *\t\textrabuf\t\tbuffer for extra data (optional)\t\t\t\t\t\t\t\t\t*\n *\t\textralen\t\tptr to length of extra data (optional)\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = no entry to retrieve\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint CommBufferClass::UnQueue_Send(void *buf, int *buflen, int index,\n\tvoid *extrabuf, int *extralen)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tError if no entry to retrieve\n\t//------------------------------------------------------------------------\n\tif (SendCount==0 || SendQueue[SendIndex[index]].IsActive==0) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCopy the data from the entry\n\t//------------------------------------------------------------------------\n\tif (buf!=NULL) {\n\t\tmemcpy(buf,SendQueue[SendIndex[index]].Buffer,\n\t\t\tSendQueue[SendIndex[index]].BufLen);\n\t\t(*buflen) = SendQueue[SendIndex[index]].BufLen;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCopy the extra data\n\t//------------------------------------------------------------------------\n\tif (extrabuf!=NULL && extralen!=NULL) {\n\t\tmemcpy(extrabuf,SendQueue[SendIndex[index]].ExtraBuffer,\n\t\t\tSendQueue[SendIndex[index]].ExtraLen);\n\t\t(*extralen) = SendQueue[SendIndex[index]].ExtraLen;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSet entry flags\n\t//------------------------------------------------------------------------\n\tSendQueue[SendIndex[index]].IsActive = 0;\n\tSendQueue[SendIndex[index]].IsACK = 0;\n\tSendQueue[SendIndex[index]].FirstTime = 0L;\n\tSendQueue[SendIndex[index]].LastTime = 0L;\n\tSendQueue[SendIndex[index]].SendCount = 0L;\n\tSendQueue[SendIndex[index]].BufLen = 0;\n\tSendQueue[SendIndex[index]].ExtraLen = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tMove Indices back one\n\t//------------------------------------------------------------------------\n\tfor (i = index; i < SendCount - 1; i++) {\n\t\tSendIndex[i] = SendIndex[i + 1];\n\t}\n\tSendIndex[SendCount - 1] = 0;\n\tSendCount--;\n\n\treturn(1);\n\n}\t/* end of UnQueue_Send */\n\n\n/***************************************************************************\n * CommBufferClass::Get_Send -- gets ptr to queue entry                    *\n *                                                                         *\n * This routine gets a pointer to the indicated queue entry.  The index\t\t*\n * value is relative to the next-accessible queue entry; 0 = get the\t\t\t*\n * next available queue entry, 1 = get the one behind that, etc.\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\tindex of entry to get (0 = 1st available)\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to entry\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/21/1994 BR : Created.                                              *\n *=========================================================================*/\nSendQueueType * CommBufferClass::Get_Send(int index)\n{\n\tif (SendQueue[SendIndex[index]].IsActive==0) {\n\t\treturn(NULL);\n\t}\n\telse {\n\t\treturn(&SendQueue[SendIndex[index]]);\n\t}\n\n}\t/* end of Get_Send */\n\n\n/***************************************************************************\n * CommBufferClass::Queue_Receive -- queues a received message\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer containing the message\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of 'buf'\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textrabuf\t\tbuffer containing extra data (optional)\t\t\t\t\t\t*\n *\t\textralen\t\tlength of extra data (optional)\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = no room in the queue\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint CommBufferClass::Queue_Receive(void *buf, int buflen, void *extrabuf,\n\tint extralen)\n{\n\tint i;\n\tint index;\n\n\t//------------------------------------------------------------------------\n\t//\tError if no room in the queue\n\t//------------------------------------------------------------------------\n\tif (ReceiveCount==MaxReceive || buflen > MaxPacketSize) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tFind an empty slot\n\t//------------------------------------------------------------------------\n\tindex = -1;\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tif (ReceiveQueue[i].IsActive==0) {\n\t\t\tindex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (index == -1)\n\t\treturn (0);\n\n\t//------------------------------------------------------------------------\n\t//\tSet entry flags\n\t//------------------------------------------------------------------------\n\tReceiveQueue[index].IsActive = 1;\n\tReceiveQueue[index].IsRead = 0;\n\tReceiveQueue[index].IsACK = 0;\n\tReceiveQueue[index].BufLen = buflen;\n\n\t//------------------------------------------------------------------------\n\t//\tCopy the packet data\n\t//------------------------------------------------------------------------\n\tmemcpy(ReceiveQueue[index].Buffer,buf,buflen);\n\n\t//------------------------------------------------------------------------\n\t//\tFill in the extra data, if there is any\n\t//------------------------------------------------------------------------\n\tif (extrabuf!=NULL && extralen > 0 && extralen <= MaxExtraSize) {\n\t\tmemcpy(ReceiveQueue[index].ExtraBuffer,extrabuf,extralen);\n\t\tReceiveQueue[index].ExtraLen = extralen;\n\t}\n\telse {\n\t\tReceiveQueue[index].ExtraLen = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSave this entry's index\n\t//------------------------------------------------------------------------\n\tReceiveIndex[ReceiveCount] = index;\n\n\t//------------------------------------------------------------------------\n\t//\tIncrement counters & entry ptr\n\t//------------------------------------------------------------------------\n\tReceiveCount++;\n\tReceiveTotal++;\n\n\treturn(1);\n\n}\t/* end of Queue_Receive */\n\n\n/***************************************************************************\n * CommBufferClass::UnQueue_Receive -- removes next entry from send queue\t*\n *                                                                         *\n * Frees the given entry; the index given by the caller is the \"active\"\t\t*\n * index value (ie the \"nth\" active entry), not the actual index in the\t\t*\n * array.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to store entry's data in; if NULL, it's discarded\t*\n *\t\tbuflen\t\tfilled in with length of entry retrieved\t\t\t\t\t\t*\n *\t\tindex\t\t\tindex of entry to un-queue\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textrabuf\t\tbuffer for extra data (optional)\t\t\t\t\t\t\t\t\t*\n *\t\textralen\t\tptr to length of extra data (optional)\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = no entry to retrieve\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint CommBufferClass::UnQueue_Receive(void *buf, int *buflen, int index,\n\tvoid *extrabuf, int *extralen)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tError if no entry to retrieve\n\t//------------------------------------------------------------------------\n\tif (ReceiveCount==0 || ReceiveQueue[ReceiveIndex[index]].IsActive==0) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCopy the data from the entry\n\t//------------------------------------------------------------------------\n\tif (buf!=NULL) {\n\t\tmemcpy(buf,ReceiveQueue[ReceiveIndex[index]].Buffer,\n\t\t\tReceiveQueue[ReceiveIndex[index]].BufLen);\n\t\t(*buflen) = ReceiveQueue[ReceiveIndex[index]].BufLen;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCopy the extra data\n\t//------------------------------------------------------------------------\n\tif (extrabuf!=NULL && extralen!=NULL) {\n\t\tmemcpy(extrabuf,ReceiveQueue[ReceiveIndex[index]].ExtraBuffer,\n\t\t\tReceiveQueue[ReceiveIndex[index]].ExtraLen);\n\t\t(*extralen) = ReceiveQueue[ReceiveIndex[index]].ExtraLen;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSet entry flags\n\t//------------------------------------------------------------------------\n\tReceiveQueue[ReceiveIndex[index]].IsActive = 0;\n\tReceiveQueue[ReceiveIndex[index]].IsRead = 0;\n\tReceiveQueue[ReceiveIndex[index]].IsACK = 0;\n\tReceiveQueue[ReceiveIndex[index]].BufLen = 0;\n\tReceiveQueue[ReceiveIndex[index]].ExtraLen = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tMove Indices back one\n\t//------------------------------------------------------------------------\n\tfor (i = index; i < ReceiveCount - 1; i++) {\n\t\tReceiveIndex[i] = ReceiveIndex[i + 1];\n\t}\n\tReceiveIndex[ReceiveCount - 1] = 0;\n\tReceiveCount--;\n\n\treturn(1);\n\n}\t/* end of UnQueue_Receive */\n\n\n/***************************************************************************\n * CommBufferClass::Get_Receive -- gets ptr to queue entry                 *\n *                                                                         *\n * This routine gets a pointer to the indicated queue entry.  The index\t\t*\n * value is relative to the next-accessible queue entry; 0 = get the\t\t\t*\n * next available queue entry, 1 = get the one behind that, etc.\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\tindex of entry to get (0 = 1st available)\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to entry\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/21/1994 BR : Created.                                              *\n *=========================================================================*/\nReceiveQueueType * CommBufferClass::Get_Receive(int index)\n{\n\tif (ReceiveQueue[ReceiveIndex[index]].IsActive==0) {\n\t\treturn(NULL);\n\t}\n\telse {\n\t\treturn(&ReceiveQueue[ReceiveIndex[index]]);\n\t}\n\n}\t/* end of Get_Receive */\n\n\n/***************************************************************************\n * CommBufferClass::Add_Delay -- adds a new delay value for response time  *\n *                                                                         *\n * This routine updates the average response time for this queue.  The\t\t*\n * computation is based on the average of the last 'n' delay values given,\t*\n * It computes a running total of the last n delay values, then divides \t*\n * that by n to compute the average.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * When the number of values given exceeds the max, the mean is subtracted\t*\n * off the total, then the new value is added in.  Thus, any single delay\t*\n * value will have an effect on the total that approaches 0 over time, and\t*\n * the new delay value contributes to 1/n of the mean.\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tdelay\t\t\tvalue to add into the response time computation\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid CommBufferClass::Add_Delay(unsigned long delay)\n{\n\tint roundoff = 0;\n\n\tif (NumDelay==256) {\n\t\tDelaySum -= MeanDelay;\n\t\tDelaySum += delay;\n\t\tif ( (DelaySum & 0x00ff) > 127)\n\t\t\troundoff = 1;\n\t\tMeanDelay = (DelaySum >> 8) + roundoff;\n\t}\n\telse {\n\t\tNumDelay++;\n\t\tDelaySum += delay;\n\t\tMeanDelay = DelaySum / NumDelay;\n\t}\n\n\tif (delay > MaxDelay) {\n\t\tMaxDelay = delay;\n\t}\n\n}\t/* end of Add_Delay */\n\n\n/***************************************************************************\n * CommBufferClass::Avg_Response_Time -- returns average response time    \t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tlatest computed average response time\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nunsigned long CommBufferClass::Avg_Response_Time(void)\n{\n\treturn(MeanDelay);\n\n}\t/* end of Avg_Response_Time */\n\n\n/***************************************************************************\n * CommBufferClass::Max_Response_Time -- returns max response time    \t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tlatest computed average response time\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nunsigned long CommBufferClass::Max_Response_Time(void)\n{\n\treturn(MaxDelay);\n\n}\t/* end of Max_Response_Time */\n\n\n/***************************************************************************\n * CommBufferClass::Reset_Response_Time -- resets computations\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid CommBufferClass::Reset_Response_Time(void)\n{\n\tDelaySum = 0L;\n\tNumDelay = 0L;\n\tMeanDelay = 0L;\n\tMaxDelay = 0L;\n\n}\t/* end of Reset_Response_Time */\n\n\n/***************************************************************************\n * CommBufferClass::Configure_Debug -- sets up special debug values        *\n *                                                                         *\n * Mono_Debug_Print2() can look into a packet to pull out a particular\t\t*\n * ID, and can print both that ID and a string corresponding to\t\t\t\t*\n * that ID.  This routine configures these values so it can find\t\t\t\t*\n * and decode the ID.  This ID is used in addition to the normal\t\t\t\t*\n * CommHeaderType values.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\ttype_offset\t\tID's byte offset into packet\t\t\t\t\t\t\t\t\t*\n *\t\ttype_size\t\tsize of ID, in bytes; 0 if none\t\t\t\t\t\t\t\t*\n *\t\tnames\t\t\t\tptr to array of names; use ID as an index into this\t*\n *\t\tmaxnames\t\t\tmax # in the names array; 0 if none.\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tNames shouldn't be longer than 12 characters.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/31/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid CommBufferClass::Configure_Debug(int type_offset, int type_size,\n\tchar **names, int namestart, int namecount)\n{\n\tDebugOffset = type_offset;\n\tDebugSize = type_size;\n\tDebugNames = names;\n\tDebugNameStart = namestart;\n\tDebugNameCount = namecount;\n\n}\t/* end of Configure_Debug */\n\n\n/***************************************************************************\n * Mono_Debug_Print -- Debug output routine                                *\n *                                                                         *\n * This routine leaves 5 lines at the top for the caller's use.\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\trefresh\t\t1 = clear screen & completely refresh\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/02/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid CommBufferClass::Mono_Debug_Print(int refresh)\n{\n#ifdef WWLIB32_H\n\tint i;\t\t\t\t\t\t\t\t\t\t\t\t// loop counter\n\tstatic int send_col[] = {1,14,28};\t\t\t// coords of send queue columns\n\tstatic int receive_col[] = {40,54,68};\t\t// coords of recv queue columns\n\tint row,col;\t\t\t\t\t\t\t\t\t\t// current row,col for printing\n\tint num;\t\t\t\t\t\t\t\t\t\t\t\t// max # items to print\n\n\tstruct CommHdr {\t\t\t\t\t\t\t\t\t// this mirrors the CommHeaderType\n\t\tunsigned short MagicNumber;\n\t\tunsigned char Code;\n\t\tunsigned long PacketID;\n\t} *hdr;\n\n\t//------------------------------------------------------------------------\n\t//\tIf few enough entries, call the verbose debug version\n\t//------------------------------------------------------------------------\n\tif (MaxSend <= 16) {\n\t\tMono_Debug_Print2(refresh);\n\t\treturn;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tRefresh the screen\n\t//------------------------------------------------------------------------\n\tif (refresh) {\n\t\tMono_Clear_Screen ();\n\t\tMono_Printf(\"Ŀ\\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"Ĵ\\n\");\n\t\tMono_Printf(\"              Send Queue                           Receive Queue            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\" ID  Ct ACK   ID  Ct ACK    ID  Ct ACK ID  Rd ACK    ID  Rd ACK   ID  Rd ACK\\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"\");\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tPrint Send Queue items\n\t//------------------------------------------------------------------------\n\tif (MaxSend <= 48) {\n\t\tnum = MaxSend;\n\t}\n\telse {\n\t\tnum = 48;\n\t}\n\tcol = 0;\n\trow = 0;\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tMono_Set_Cursor (send_col[col],row + 8);\n\t\tif (SendQueue[i].IsActive) {\n\t\t\thdr = (CommHdr *)SendQueue[i].Buffer;\n\t\t\thdr->MagicNumber = hdr->MagicNumber;\n\t\t\thdr->Code = hdr->Code;\n\t\t\tMono_Printf (\"%4d %2d  %d\",hdr->PacketID, SendQueue[i].SendCount,\n\t\t\t\tSendQueue[i].IsACK);\n\t\t}\n\t\telse {\n\t\t\tMono_Printf (\"____ __  _ \");\n\t\t}\n\n\t\trow++;\n\t\tif (row > 15) {\n\t\t\trow = 0;\n\t\t\tcol++;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tPrint Receive Queue items\n\t//------------------------------------------------------------------------\n\tif (MaxReceive <= 48) {\n\t\tnum = MaxSend;\n\t}\n\telse {\n\t\tnum = 48;\n\t}\n\tcol = 0;\n\trow = 0;\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tMono_Set_Cursor (receive_col[col],row + 8);\n\t\tif (ReceiveQueue[i].IsActive) {\n\t\t\thdr = (CommHdr *)ReceiveQueue[i].Buffer;\n\t\t\tMono_Printf (\"%4d  %d  %d\",hdr->PacketID, ReceiveQueue[i].IsRead,\n\t\t\t\tReceiveQueue[i].IsACK);\n\t\t}\n\t\telse {\n\t\t\tMono_Printf (\"____  _  _ \");\n\t\t}\n\n\t\trow++;\n\t\tif (row > 15) {\n\t\t\trow = 0;\n\t\t\tcol++;\n\t\t}\n\t}\n\n#else\n\trefresh = refresh;\n#endif\n}\t/* end of Mono_Debug_Print */\n\n\n/***************************************************************************\n * CommBufferClass::Mono_Debug_Print2 -- Debug output; alternate format    *\n *                                                                         *\n * This routine prints more information than the other version; it's\t\t\t*\n * called only if the number of queue entries is small enough to support\t*\n * this format.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\trefresh\t\t1 = clear screen & completely refresh\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/31/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid CommBufferClass::Mono_Debug_Print2(int refresh)\n{\n#ifdef WWLIB32_H\n\tint i;\t\t\t\t\t\t\t\t\t\t\t\t// loop counter\n\tchar txt[80];\n\tint val;\n\n\tstruct CommHdr {\t\t\t\t\t\t\t\t\t// this mirrors the CommHeaderType\n\t\tunsigned short MagicNumber;\n\t\tunsigned char Code;\n\t\tunsigned long PacketID;\n\t} *hdr;\n\n\t//------------------------------------------------------------------------\n\t//\tRefresh the screen\n\t//------------------------------------------------------------------------\n\tif (refresh) {\n\t\tMono_Clear_Screen ();\n\t\tMono_Printf(\"Ŀ\\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"Ĵ\\n\");\n\t\tMono_Printf(\"              Send Queue                           Receive Queue            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\" ID  Ct Type   Data  Name         ACK  ID  Rd Type   Data  Name         ACK \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"\");\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tPrint Send Queue items\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tMono_Set_Cursor (1,8 + i);\n\n\t\t//.....................................................................\n\t\t//\tPrint an active entry\n\t\t//.....................................................................\n\t\tif (SendQueue[i].IsActive) {\n\n\t\t\t//..................................................................\n\t\t\t//\tGet header info\n\t\t\t//..................................................................\n\t\t\thdr = (CommHdr *)SendQueue[i].Buffer;\n\t\t\thdr->MagicNumber = hdr->MagicNumber;\n\t\t\thdr->Code = hdr->Code;\n\t\t\tsprintf(txt,\"%4d %2d %-5s  \",\n\t\t\t\thdr->PacketID,\n\t\t\t\tSendQueue[i].SendCount,\n\t\t\t\tConnectionClass::Command_Name(hdr->Code));\n\n\t\t\t//..................................................................\n\t\t\t//\tDecode app's ID & its name\n\t\t\t//..................................................................\n\t\t\tif (DebugSize && (DebugOffset + DebugSize) <= SendQueue[i].BufLen) {\n\t\t\t\tif (DebugSize==1) {\n\t\t\t\t\tval = *(SendQueue[i].Buffer + DebugOffset);\n\n\t\t\t\t}\n\t\t\t\telse if (DebugSize==2) {\n\t\t\t\t\tval = *((short *)(SendQueue[i].Buffer + DebugOffset));\n\n\t\t\t\t}\n\t\t\t\telse if (DebugSize==4) {\n\t\t\t\t\tval = *((int *)(SendQueue[i].Buffer + DebugOffset));\n\t\t\t\t}\n\t\t\t\tsprintf(txt + strlen(txt),\"%4d  \",val);\n\n\t\t\t\tif (DebugNameCount > 0 && val >= 0 && val < DebugNameCount) {\n\t\t\t\t\tsprintf(txt + strlen(txt),\"%-12s  %x\",\n\t\t\t\t\t\tDebugNames[val - DebugNameStart], SendQueue[i].IsACK);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsprintf(txt + strlen(txt),\"              %x\",\n\t\t\t\t\t\tSendQueue[i].IsACK);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tsprintf(txt + strlen(txt),\"                    %x\",\n\t\t\t\t\tSendQueue[i].IsACK);\n\t\t\t}\n\n\t\t\tMono_Printf(\"%s\",txt);\n\t\t}\n\t\telse {\n\n\t\t\t//..................................................................\n\t\t\t//\tEntry isn't active; print blanks\n\t\t\t//..................................................................\n\t\t\tMono_Printf(\"____ __                            _\");\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tPrint Receive Queue items\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tMono_Set_Cursor (40,8 + i);\n\n\t\t//.....................................................................\n\t\t//\tPrint an active entry\n\t\t//.....................................................................\n\t\tif (ReceiveQueue[i].IsActive) {\n\n\t\t\t//..................................................................\n\t\t\t//\tGet header info\n\t\t\t//..................................................................\n\t\t\thdr = (CommHdr *)ReceiveQueue[i].Buffer;\n\t\t\thdr->MagicNumber = hdr->MagicNumber;\n\t\t\thdr->Code = hdr->Code;\n\t\t\tsprintf(txt,\"%4d %2d %-5s  \",\n\t\t\t\thdr->PacketID,\n\t\t\t\tReceiveQueue[i].IsRead,\n\t\t\t\tConnectionClass::Command_Name(hdr->Code));\n\n\t\t\t//..................................................................\n\t\t\t//\tDecode app's ID & its name\n\t\t\t//..................................................................\n\t\t\tif (DebugSize && (DebugOffset + DebugSize) <= ReceiveQueue[i].BufLen) {\n\t\t\t\tif (DebugSize==1) {\n\t\t\t\t\tval = *(ReceiveQueue[i].Buffer + DebugOffset);\n\n\t\t\t\t}\n\t\t\t\telse if (DebugSize==2) {\n\t\t\t\t\tval = *((short *)(ReceiveQueue[i].Buffer + DebugOffset));\n\n\t\t\t\t}\n\t\t\t\telse if (DebugSize==4) {\n\t\t\t\t\tval = *((int *)(ReceiveQueue[i].Buffer + DebugOffset));\n\t\t\t\t}\n\t\t\t\tsprintf(txt + strlen(txt),\"%4d  \",val);\n\n\t\t\t\tif (DebugNameCount > 0 && val >= 0 && val < DebugNameCount) {\n\t\t\t\t\tsprintf(txt + strlen(txt),\"%-12s  %x\",\n\t\t\t\t\t\tDebugNames[val - DebugNameStart], ReceiveQueue[i].IsACK);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsprintf(txt + strlen(txt),\"              %x\",\n\t\t\t\t\t\tReceiveQueue[i].IsACK);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tsprintf(txt + strlen(txt),\"                    %x\",\n\t\t\t\t\tReceiveQueue[i].IsACK);\n\t\t\t}\n\n\t\t\tMono_Printf(\"%s\",txt);\n\t\t}\n\t\telse {\n\n\t\t\t//..................................................................\n\t\t\t//\tEntry isn't active; print blanks\n\t\t\t//..................................................................\n\t\t\tMono_Printf(\"____ __                            _\");\n\t\t}\n\t}\n\n#else\n\trefresh = refresh;\n#endif\n}\t/* end of Mono_Debug_Print2 */\n\n\n/************************** end of combuf.cpp ******************************/\n\n\n"
  },
  {
    "path": "CODE/COMBUF.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/COMBUF.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : COMBUF.H                               \t*\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 1, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This class's job is to store outgoing messages & incoming messages, \t\t*\n * and serves as a storage area for various flags for ACK & Retry logic.\t*\n *                                                                         *\n * This class stores buffers in a non-sequenced order; it allows freeing\t*\n * any entry, so the buffers can be kept clear, even if packets come in\t\t*\n * out of order.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The class also contains routines to maintain a cumulative response time\t*\n * for this queue.  It's up to the caller to call Add_Delay() whenever\t\t*\n * it detects that an outgoing message has been ACK'd; this class adds\t\t*\n * that delay into a computed average delay over the last few message \t\t*\n * delays.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef COMBUF_H\n#define COMBUF_H\n\n\n/*\n********************************** Defines **********************************\n*/\n/*---------------------------------------------------------------------------\nThis is one output queue entry\n---------------------------------------------------------------------------*/\ntypedef struct {\n\tunsigned int IsActive\t: 1;\t// 1 = this entry is ready to be processed\n\tunsigned int IsACK\t\t: 1;\t// 1 = ACK received for this packet\n\tunsigned long FirstTime;\t\t// time this packet was first sent\n\tunsigned long LastTime;\t\t\t// time this packet was last sent\n\tunsigned long SendCount;\t\t// # of times this packet has been sent\n\tint BufLen;\t\t\t\t\t\t\t// size of the packet stored in this entry\n\tchar *Buffer;\t\t\t\t\t\t// the data packet\n\tint ExtraLen;\t\t\t\t\t\t// size of extra data\n\tchar *ExtraBuffer;\t\t\t\t// extra data buffer\n} SendQueueType;\n\n/*---------------------------------------------------------------------------\nThis is one input queue entry\n---------------------------------------------------------------------------*/\ntypedef struct {\n\tunsigned int IsActive\t: 1;\t// 1 = this entry is ready to be processed\n\tunsigned int IsRead\t\t: 1;\t// 1 = caller has read this entry\n\tunsigned int IsACK\t\t: 1;\t// 1 = ACK sent for this packet\n\tint BufLen;\t\t\t\t\t\t\t// size of the packet stored in this entry\n\tchar *Buffer;\t\t\t\t\t\t// the data packet\n\tint ExtraLen;\t\t\t\t\t\t// size of extra data\n\tchar *ExtraBuffer;\t\t\t\t// extra data buffer\n} ReceiveQueueType;\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass CommBufferClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*\n\t\t....................... Constructor/Destructor ........................\n\t\t*/\n\t\tCommBufferClass(int numsend, int numrecieve, int maxlen, \n\t\t\tint extralen = 0);\n\t\tvirtual ~CommBufferClass();\n\t\tvoid Init(void);\n\t\tvoid Init_Send_Queue(void);\n\n\t\t/*\n\t\t......................... Send Queue routines .........................\n\t\t*/\n\t\tint Queue_Send(void *buf, int buflen, void *extrabuf = NULL,\n\t\t\tint extralen = 0);\n\t\tint UnQueue_Send(void *buf, int *buflen, int index, \n\t\t\tvoid *extrabuf = NULL, int *extralen = NULL);\n\t\tint Num_Send(void) {return (SendCount);}\t\t// # entries in queue\n\t\tint Max_Send(void) { return (MaxSend);}\t\t// max # send queue entries\n\t\tSendQueueType * Get_Send(int index);\t\t\t// random access to queue\n\t\tunsigned long Send_Total(void) {return (SendTotal);}\n\n\t\t/*\n\t\t....................... Receive Queue routines ........................\n\t\t*/\n\t\tint Queue_Receive(void *buf, int buflen, void *extrabuf = NULL,\n\t\t\tint extralen = 0);\n\t\tint UnQueue_Receive(void *buf, int *buflen, int index, \n\t\t\tvoid *extrabuf = NULL, int *extralen = NULL);\n\t\tint Num_Receive(void) {return (ReceiveCount);}\t// # entries in queue\n\t\tint Max_Receive(void) { return (MaxReceive); }\t// max # recv queue entries\n\t\tReceiveQueueType * Get_Receive(int index);\t// random access to queue\n\t\tunsigned long Receive_Total(void) {return (ReceiveTotal);}\n\n\t\t/*\n\t\t....................... Response time routines ........................\n\t\t*/\n\t\tvoid Add_Delay(unsigned long delay);\t// accumulates response time\n\t\tunsigned long Avg_Response_Time(void);\t// gets mean response time\n\t\tunsigned long Max_Response_Time(void);\t// gets max response time\n\t\tvoid Reset_Response_Time(void);\t\t\t// resets computations\n\n\t\t/*\n\t\t........................ Debug output routines ........................\n\t\t*/\n\t\tvoid Configure_Debug(int type_offset, int type_size, char **names, \n\t\t\tint namestart, int namecount);\n\t\tvoid Mono_Debug_Print(int refresh = 0);\n\t\tvoid Mono_Debug_Print2(int refresh = 0);\n\n\t/*\n\t--------------------------- Private Interface ----------------------------\n\t*/\n\tprivate:\n\t\t/*\n\t\t.......................... Limiting variables .........................\n\t\t*/\n\t\tint MaxSend;\t\t\t\t\t\t\t// max # send queue entries\n\t\tint MaxReceive;\t\t\t\t\t\t// max # receive queue entries\n\t\tint MaxPacketSize;\t\t\t\t\t// max size of a packet, in bytes\n\t\tint MaxExtraSize;\t\t\t\t\t\t// max size of extra bytes\n\n\t\t/*\n\t\t....................... Response time variables .......................\n\t\t*/\n\t\tunsigned long DelaySum;\t\t\t\t// sum of last 4 delay times\n\t\tunsigned long NumDelay;\t\t\t\t// current # delay times summed\n\t\tunsigned long MeanDelay;\t\t\t// current average delay time\n\t\tunsigned long MaxDelay;\t\t\t\t// max delay ever for this queue\n\n\t\t/*\n\t\t........................ Send Queue variables .........................\n\t\t*/\n\t\tSendQueueType * SendQueue;\t\t\t// incoming packets\n\t\tint SendCount; \t\t\t\t\t\t// # packets in the queue\n\t\tunsigned long SendTotal;\t\t\t// total # added to send queue\n\t\tint *SendIndex;\t\t\t\t\t\t// array of Send entry indices\n\n\t\t/*\n\t\t....................... Receive Queue variables .......................\n\t\t*/\n\t\tReceiveQueueType * ReceiveQueue;\t\t// outgoing packets\n\t\tint ReceiveCount;\t\t\t\t\t\t\t// # packets in the queue\n\t\tunsigned long ReceiveTotal;\t\t\t// total # added to receive queue\n\t\tint *ReceiveIndex;\t\t\t\t\t\t// array of Receive entry indices\n\n\t\t/*\n\t\t......................... Debugging Variables .........................\n\t\t*/\n\t\tint DebugOffset;\t\t\t\t\t\t\t// offset into app's packet for ID\n\t\tint DebugSize;\t\t\t\t\t\t\t\t// size of app's ID\n\t\tchar **DebugNames;\t\t\t\t\t\t// ptr to array of app-specific names\n\t\tint DebugNameStart;\t\t\t\t\t\t// number of 1st ID\n\t\tint DebugNameCount;\t\t\t\t\t\t// # of names in array\n};\n\n#endif\n\n/**************************** end of combuf.h ******************************/\n\n"
  },
  {
    "path": "CODE/COMINIT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n//\n// If you link with this it will automatically call the COM initialization stuff \n//\n\n#include \"cominit.h\"\n//#include <stdlib.h>\n//#include <stdio.h>\n//#include <windows.h>\n#include <objbase.h>\n//#include \"externs.h\"\n//#include \"text.rh\"\n\n//#include \"WolDebug.h\"\n\nComInit::ComInit()\n{\n  //HRESULT hRes = CoInitialize(NULL);\n//\tif (SUCCEEDED(hRes)==FALSE)\n//\t\texit(0);\n\tHRESULT hRes = OleInitialize(NULL);\n}\n\nComInit::~ComInit()\n{\n//  CoUninitialize();\n//\tdebugprint( \"pre OleUninitialize\\n\" );\n\tOleUninitialize();\n//\tdebugprint( \"post OleUninitialize\\n\" );\n}\n\n// Creating this instance will setup all COM stuff & do cleanup on program exit\nComInit  Global_COM_Initializer;\n\n"
  },
  {
    "path": "CODE/COMINIT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef COMINIT_HEADER\n#define COMINIT_HEADER\n\n//\n// Link with this to automatically initialize COM at startup\n//  - See cominit.cpp for more info\n//\n\nclass ComInit\n{\n public:\n         ComInit();\n        ~ComInit();\n};\n\n#endif\n"
  },
  {
    "path": "CODE/COMPAT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/COMPAT.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : COMPAT.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/02/95                                                     *\n *                                                                                             *\n *                  Last Update : March 2, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef COMPAT_H\n#define COMPAT_H\n\n\n#define\tBuffType\t\tBufferClass\n//#define movmem(a,b,c) memmove(b,a,c)\n#define ShapeBufferSize\t_ShapeBufferSize\n\n/*=========================================================================*/\n/* Define some equates for the different graphic routines we will install\t*/\n/*\t\tlater.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define HIDBUFF\t  ((void *)(0xA0000))\n#define Size_Of_Region(a, b) ((a)*(b))\n\n/*=========================================================================*/\n/* Define some Graphic Routines which will only be fixed by these defines\t*/\n/*=========================================================================*/\n#define Set_Font_Palette(a) \t\tSet_Font_Palette_Range(a, 0, 15)\n\n/*\n**\tThese are the Open_File, Read_File, and Seek_File constants.\n*/\n#define READ\t\t\t\t\t\t1\t// Read access.\n#define WRITE\t\t\t\t\t\t2\t// Write access.\n\n#ifndef SEEK_SET\n#define SEEK_SET\t\t\t\t\t0\t// Seek from start of file.\n#define SEEK_CUR\t\t\t\t\t1\t// Seek relative from current location.\n#define SEEK_END\t\t\t\t\t2\t// Seek from end of file.\n#endif\n\n#define ERROR_WINDOW \t\t\t1\n#define ErrorWindow \t\t\t1\n\n\n//extern unsigned char *Palette;\nextern unsigned char MDisabled;\t\t\t// Is mouse disabled?\nextern WORD Hard_Error_Occured;\n\n/*\n**\tThis is the menu control structures.\n*/\ntypedef enum MenuIndexType {\n\tMENUX,\n\tMENUY,\n\tITEMWIDTH,\n\tITEMSHIGH,\n\tMSELECTED,\n\tNORMCOL,\n\tHILITE,\n\tMENUPADDING=0x1000\n} MenuIndexType;\n\n\n#ifdef NEVER\n#define BITSPERBYTE 8\n#define MAXSHORT    0x7FFF\n#define HIBITS      0x8000\n#define MAXLONG     0x7FFFFFFFL\n#define HIBITL      0x80000000\n\n#define MAXINT      MAXLONG\n#define HIBITI      HIBITL\n\n#define DMAXEXP     308\n#define FMAXEXP     38\n#define DMINEXP     -307\n#define FMINEXP     -37\n\n#define MAXDOUBLE   1.797693E+308\n#define MAXFLOAT    3.37E+38F\n#define MINDOUBLE   2.225074E-308\n#define MINFLOAT    8.43E-37F\n\n#define DSIGNIF     53\n#define FSIGNIF     24\n\n#define DMAXPOWTWO  0x3FF\n#define FMAXPOWTWO  0x7F\n#define DEXPLEN     11\n#define FEXPLEN     8\n#define EXPBASE     2\n#define IEEE        1\n#define LENBASE     1\n#define HIDDENBIT   1\n#define LN_MAXDOUBLE    7.0978E+2\n#define LN_MINDOUBLE    -7.0840E+2\n#endif\n\n/* These defines handle the various names given to the same color. */\n#define\tDKGREEN\tGREEN\n#define\tDKBLUE\tBLUE\n#define\tGRAY\t\tGREY\n#define\tDKGREY\tGREY\n#define\tDKGRAY\tGREY\n#define\tLTGRAY\tLTGREY\n\n\nclass IconsetClass;\n#ifndef WIN32\ntypedef struct {\n\tshort\tWidth;\t\t\t// Width of icons (pixels).\n\tshort\tHeight;\t\t\t// Height of icons (pixels).\n\tshort\tCount;\t\t\t// Number of (logical) icons in this set.\n\tshort\tAllocated;\t\t// Was this iconset allocated?\n\tshort MapWidth;\t\t// Width of map (in icons).\n\tshort MapHeight;\t\t// Height of map (in icons).\n\tlong\tSize;\t\t\t\t// Size of entire iconset memory block.\n\tlong\tIcons;\t\t\t// Offset from buffer start to icon data.\n//\tunsigned char * Icons;\t// Offset from buffer start to icon data.\n\tlong\tPalettes;\t\t// Offset from buffer start to palette data.\n\tlong\tRemaps;\t\t\t// Offset from buffer start to remap index data.\n\tlong\tTransFlag;\t\t// Offset for transparency flag table.\n\tlong\tColorMap;\t\t// Offset for color control value table.\n\tlong\tMap;\t\t\t\t// Icon map offset (if present).\n//\tunsigned char * Map;\t\t\t\t// Icon map offset (if present).\n} IControl_Type;\n#endif\n\ninline int Get_IconSet_MapWidth(void const * data)\n{\n\tif (data) {\n\t\treturn(((IControl_Type *)data)->MapWidth);\n\t}\n\treturn(0);\n}\n\ninline int Get_IconSet_MapHeight(void const * data)\n{\n\tif (data) {\n\t\treturn(((IControl_Type *)data)->MapHeight);\n\t}\n\treturn(0);\n}\n\ninline unsigned char const * Get_IconSet_ControlMap(void const * data)\n{\n\tif (data) {\n\t\treturn((unsigned char const *)((char *)data + ((IControl_Type *)data)->ColorMap));\n\t}\n\treturn(0);\n}\n\nclass IconsetClass : protected IControl_Type\n{\n\tpublic:\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tint Map_Width(void) const {return(MapWidth);};\n\t\tint Map_Height(void) const {return(MapHeight);};\n\t\tunsigned char * Control_Map(void) {return((unsigned char *)this + ColorMap);};\n\t\tunsigned char const * Control_Map(void) const {return((unsigned char const *)this + ColorMap);};\n\t\tint Icon_Count(void) const {return(Count);};\n\t\tint Pixel_Width(void) const {return(Width);};\n\t\tint Pixel_Height(void) const {return(Height);};\n\t\tint Total_Size(void) const {return(Size);};\n\t\tunsigned char const * Palette_Data(void) const {return((unsigned char const *)this + Palettes);};\n\t\tunsigned char * Palette_Data(void) {return((unsigned char *)this + Palettes);};\n\t\tunsigned char const * Icon_Data(void) const {return((unsigned char const *)this + Icons);};\n\t\tunsigned char * Icon_Data(void) {return((unsigned char *)this + Icons);};\n\t\tunsigned char const * Map_Data(void) const {return((unsigned char const *)this + Map);};\n\t\tunsigned char * Map_Data(void) {return((unsigned char *)this + Map);};\n\t\tunsigned char const * Remap_Data(void) const {return((unsigned char const *)this + Remaps);};\n\t\tunsigned char * Remap_Data(void) {return((unsigned char *)this + Remaps);};\n\t\tunsigned char const * Trans_Data(void) const {return((unsigned char const *)this + TransFlag);};\n\t\tunsigned char * Trans_Data(void) {return((unsigned char *)this + TransFlag);};\n\n\t/*\n\t**\tDisallow these operations with an IconsetClass object.\n\t*/\n\tprivate:\n\t\tIconsetClass & operator = (IconsetClass const &);\n\t\tIconsetClass(void);\n\t\tstatic void * operator new(size_t);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/COMQUEUE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\comqueue.cpv   4.1   11 Apr 1996 18:28:16   JOE_BOSTIC  $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : COMQUEUE.CPP                             *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : May 31, 1995 [BRR]                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   CommQueueClass::Add_Delay -- adds a new delay value for response time *\n *   CommQueueClass::Avg_Response_Time -- returns average response time    *\n *   CommQueueClass::CommQueueClass -- class constructor                   *\n *   CommQueueClass::Configure_Debug -- sets up special debug values       * \n *   CommQueueClass::Get_Receive -- gets ptr to queue entry                *\n *   CommQueueClass::Get_Send -- gets ptr to queue entry                   *\n *   CommQueueClass::Init -- initializes this queue                        *\n *   CommQueueClass::Max_Response_Time -- returns max response time        *\n *   CommQueueClass::Mono_Debug_Print -- Debug output routine              * \n *   CommQueueClass::Mono_Debug_Print2 -- Debug output; alternate format   * \n *   CommQueueClass::Next_Receive -- gets ptr to next entry in send queue  *\n *   CommQueueClass::Next_Send -- gets ptr to next entry in send queue     *\n *   CommQueueClass::Queue_Receive -- queues a received message            *\n *   CommQueueClass::Queue_Send -- queues a message for sending            *\n *   CommQueueClass::Reset_Response_Time -- resets computations            *\n *   CommQueueClass::UnQueue_Receive -- removes next entry from send queue *\n *   CommQueueClass::UnQueue_Send -- removes next entry from send queue    *\n *   CommQueueClass::~CommQueueClass -- class destructor                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/***************************************************************************\n * CommQueueClass::CommQueueClass -- class constructor             \t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t# queue entries for sending\t\t\t\t\t\t\t\t\t\t*\n *\t\tnumreceive\t# queue entries for receiving\t\t\t\t\t\t\t\t\t\t*\n *\t\tmaxlen\t\tmaximum desired packet length, in bytes\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nCommQueueClass::CommQueueClass(int numsend, int numreceive, int maxlen)\n{\n\tint i;\n\n\t/*\n\t**\tInit variables \n\t*/\n\tMaxSend = numsend;\n\tMaxReceive = numreceive;\n\tMaxPacketSize = maxlen;\n\n\t/*\n\t**\tAllocate the queue entries \n\t*/\n\tSendQueue = new SendQueueType[numsend];\n\tReceiveQueue = new ReceiveQueueType[numreceive];\n\n\t/*\n\t**\tAllocate queue entry buffers \n\t*/\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tSendQueue[i].Buffer = new char[maxlen];\n\t}\n\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tReceiveQueue[i].Buffer = new char[maxlen];\n\t}\n\n\tInit();\n}\n\n\n/***************************************************************************\n * CommQueueClass::~CommQueueClass -- class destructor             \t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nCommQueueClass::~CommQueueClass()\n{\n\tint i;\n\n\t/*\n\t**\tFree queue entry buffers \n\t*/\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tdelete [] SendQueue[i].Buffer;\n\t}\n\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tdelete [] ReceiveQueue[i].Buffer;\n\t}\n\n\tdelete [] SendQueue;\n\tdelete [] ReceiveQueue;\n}\n\n\n/***************************************************************************\n * CommQueueClass::Init -- initializes this queue                          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/20/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid CommQueueClass::Init(void)\n{\n\tint i;\n\n\t/*\n\t**\tInit data members\n\t*/\n\tSendTotal = 0L;\n\tReceiveTotal = 0L;\n\n\tDelaySum = 0L;\n\tNumDelay = 0L;\n\tMeanDelay = 0L;\n\tMaxDelay = 0L;\n\n\tSendCount = 0;\n\tSendNext = 0;\n\tSendEmpty = 0;\n\n\tReceiveCount = 0;\n\tReceiveNext = 0;\n\tReceiveEmpty = 0;\n\n\t/*\n\t**\tInit the queue entries\n\t*/\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tSendQueue[i].IsActive = 0;\n\t\tSendQueue[i].IsACK = 0;\n\t\tSendQueue[i].FirstTime = 0L;\n\t\tSendQueue[i].LastTime = 0L;\n\t\tSendQueue[i].SendCount = 0L;\n\t\tReceiveQueue[i].BufLen = 0;\n\t}\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tReceiveQueue[i].IsActive = 0;\n\t\tReceiveQueue[i].IsRead = 0;\n\t\tReceiveQueue[i].IsACK = 0;\n\t\tReceiveQueue[i].BufLen = 0;\n\t}\n\t\n\t/*\n\t**\tInit debug values\n\t*/\n\tDebugOffset = 0;\n\tDebugSize = 0;\n\tDebugNames = NULL;\n\tDebugMaxNames = 0;\n}\n\n\n/***************************************************************************\n * CommQueueClass::Queue_Send -- queues a message for sending              *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer containing the message\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of 'buf'\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = no room in the queue\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint CommQueueClass::Queue_Send(void *buf, int buflen)\n{\n\t/*\n\t**\tError if no room in the queue\n\t*/\n\tif (SendCount==MaxSend || SendQueue[SendEmpty].IsActive!=0) {\n\t\treturn(0); \n\t}\n\n\t/*\n\t**\tSet entry flags \n\t*/\n\tSendQueue[SendEmpty].IsActive = 1;\t\t\t// entry is now active\n\tSendQueue[SendEmpty].IsACK = 0;\t\t\t\t// entry hasn't been ACK'd\n\tSendQueue[SendEmpty].FirstTime = 0L;\t\t// filled in by Manager when sent\n\tSendQueue[SendEmpty].LastTime = 0L;\t\t\t// filled in by Manager when sent\n\tSendQueue[SendEmpty].SendCount = 0L;\t\t// filled in by Manager when sent\n\tSendQueue[SendEmpty].BufLen = buflen;\t\t// save buffer size\n\n\t/*\n\t**\tCopy the packet data \n\t*/\n\tmemcpy(SendQueue[SendEmpty].Buffer,buf,buflen);\n\n\t/*\n\t**\tIncrement counters & entry ptr \n\t*/\n\tSendCount++;\n\tSendEmpty++;\n\tif (SendEmpty==MaxSend) {\n\t\tSendEmpty = 0;\n\t}\n\n\tSendTotal++;\n\n\treturn(1);\n}\n\n\n/***************************************************************************\n * CommQueueClass::UnQueue_Send -- removes next entry from send queue\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to store entry's data in; if NULL, it's discarded\t*\n *\t\tbuflen\t\tfilled in with length of entry retrieved\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = no entry to retreive\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint CommQueueClass::UnQueue_Send(void *buf, int *buflen)\n{\n\t/*\n\t**\tError if no entry to retrieve \n\t*/\n\tif (SendCount==0 || SendQueue[SendNext].IsActive==0) {\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tCopy the data from the entry \n\t*/\n\tif (buf!=NULL) {\n\t\tmemcpy(buf,SendQueue[SendNext].Buffer,SendQueue[SendNext].BufLen);\n\t\t(*buflen) = SendQueue[SendNext].BufLen;\n\t}\n\n\t/*\n\t**\tSet entry flags \n\t*/\n\tSendQueue[SendNext].IsActive = 0;\n\tSendQueue[SendNext].IsACK = 0;\n\tSendQueue[SendNext].FirstTime = 0L;\n\tSendQueue[SendNext].LastTime = 0L;\n\tSendQueue[SendNext].SendCount = 0L;\n\tSendQueue[SendNext].BufLen = 0;\n\tSendCount--;\n\tSendNext++;\n\tif (SendNext==MaxSend) {\n\t\tSendNext = 0;\n\t}\n\n\treturn(1);\n}\n\n\n/***************************************************************************\n * CommQueueClass::Next_Send -- gets ptr to next entry in send queue       *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to entry, NULL if there is none.\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nSendQueueType * CommQueueClass::Next_Send(void)\n{\n\tif (SendCount==0) {\n\t\treturn(NULL);\n\t} else {\n\t\treturn(&SendQueue[SendNext]);\n\t}\n}\n\n\n/***************************************************************************\n * CommQueueClass::Get_Send -- gets ptr to queue entry                     *\n *                                                                         *\n * This routine gets a pointer to the indicated queue entry.  The index\t\t*\n * value is relative to the next-accessable queue entry; 0 = get the\t\t\t*\n * next available queue entry, 1 = get the one behind that, etc.\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\tindex of entry to get (0 = 1st available)\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to entry\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/21/1994 BR : Created.                                              *\n *=========================================================================*/\nSendQueueType * CommQueueClass::Get_Send(int index)\n{\n\tint i;\n\n\ti = SendNext + index;\n\tif (i >= MaxSend) {\n\t\ti -= MaxSend;\n\t}\n\n\tif (SendQueue[i].IsActive==0) {\n\t\treturn(NULL);\n\t} else {\n\t\treturn(&SendQueue[i]);\n\t}\n}\n\n\n/***************************************************************************\n * CommQueueClass::Queue_Receive -- queues a received message\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer containing the message\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of 'buf'\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = no room in the queue\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint CommQueueClass::Queue_Receive(void *buf, int buflen)\n{\n\t/*\n\t**\tError if no room in the queue\n\t*/\n\tif (ReceiveCount==MaxReceive || ReceiveQueue[ReceiveEmpty].IsActive!=0) {\n\t\treturn(0); \n\t}\n\n\t/*\n\t**\tSet entry flags\n\t*/\n\tReceiveQueue[ReceiveEmpty].IsActive = 1;\n\tReceiveQueue[ReceiveEmpty].IsRead = 0;\n\tReceiveQueue[ReceiveEmpty].IsACK = 0;\n\tReceiveQueue[ReceiveEmpty].BufLen = buflen;\n\n\t/*\n\t**\tCopy the packet data\n\t*/\n\tmemcpy(ReceiveQueue[ReceiveEmpty].Buffer,buf,buflen);\n\n\t/*\n\t**\tIncrement counters & entry ptr \n\t*/\n\tReceiveCount++;\n\tReceiveEmpty++;\n\tif (ReceiveEmpty==MaxReceive) {\n\t\tReceiveEmpty = 0;\n\t}\n\n\tReceiveTotal++;\n\n\treturn(1);\n}\n\n\n/***************************************************************************\n * CommQueueClass::UnQueue_Receive -- removes next entry from send queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to store entry's data in; if NULL, it's discarded\t*\n *\t\tbuflen\t\tfilled in with length of entry retrieved\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = no entry to retreive\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint CommQueueClass::UnQueue_Receive(void *buf, int *buflen)\n{\n\t/*\n\t**\tError if no entry to retrieve \n\t*/\n\tif (ReceiveCount==0 || ReceiveQueue[ReceiveNext].IsActive==0) {\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tCopy the data from the entry\n\t*/\n\tif (buf!=NULL) {\n\t\tmemcpy(buf,ReceiveQueue[ReceiveNext].Buffer,\n\t\t\tReceiveQueue[ReceiveNext].BufLen);\n\t\t(*buflen) = ReceiveQueue[ReceiveNext].BufLen;\n\t}\n\n\t/*\n\t**\tSet entry flags\n\t*/\n\tReceiveQueue[ReceiveNext].IsActive = 0;\n\tReceiveQueue[ReceiveNext].IsRead = 0;\n\tReceiveQueue[ReceiveNext].IsACK = 0;\n\tReceiveQueue[ReceiveNext].BufLen = 0;\n\tReceiveCount--;\n\tReceiveNext++;\n\tif (ReceiveNext==MaxReceive) {\n\t\tReceiveNext = 0;\n\t}\n\n\treturn(1);\n}\n\n\n/***************************************************************************\n * CommQueueClass::Next_Receive -- gets ptr to next entry in send queue    *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to entry, NULL if there is none.\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nReceiveQueueType * CommQueueClass::Next_Receive(void)\n{\n\tif (ReceiveCount==0) {\n\t\treturn(NULL);\n\t} else {\n\t\treturn(&ReceiveQueue[ReceiveNext]);\n\t}\n}\n\n\n/***************************************************************************\n * CommQueueClass::Get_Receive -- gets ptr to queue entry                  *\n *                                                                         *\n * This routine gets a pointer to the indicated queue entry.  The index\t\t*\n * value is relative to the next-accessable queue entry; 0 = get the\t\t\t*\n * next available queue entry, 1 = get the one behind that, etc.\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\tindex of entry to get (0 = 1st available)\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to entry\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/21/1994 BR : Created.                                              *\n *=========================================================================*/\nReceiveQueueType * CommQueueClass::Get_Receive(int index)\n{\n\tint i;\n\n\ti = ReceiveNext + index;\n\tif (i >= MaxReceive) {\n\t\ti -= MaxReceive;\n\t}\n\n\tif (ReceiveQueue[i].IsActive==0) {\n\t\treturn(NULL);\n\t} else {\n\t\treturn(&ReceiveQueue[i]);\n\t}\n}\n\n\n/***************************************************************************\n * CommQueueClass::Add_Delay -- adds a new delay value for response time   *\n *                                                                         *\n * This routine updates the average response time for this queue.  The\t\t*\n * computation is based on the average of the last 'n' delay values given,\t*\n * It computes a running total of the last n delay values, then divides \t*\n * that by n to compute the average.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * When the number of values given exceeds the max, the mean is subtracted\t*\n * off the total, then the new value is added in.  Thus, any single delay\t*\n * value will have an effect on the total that approaches 0 over time, and\t*\n * the new delay value contributes to 1/n of the mean.\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tdelay\t\t\tvalue to add into the response time computation\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid CommQueueClass::Add_Delay(unsigned long delay)\n{\n\tint roundoff = 0;\n\n\tif (NumDelay==256) {\n\t\tDelaySum -= MeanDelay;\n\t\tDelaySum += delay;\n\t\tif ( (DelaySum & 0x00ff) > 127) {\n\t\t\troundoff = 1;\n\t\t}\n\t\tMeanDelay = (DelaySum >> 8) + roundoff;\n\t} else {\n\t\tNumDelay++;\n\t\tDelaySum += delay;\n\t\tMeanDelay = DelaySum / NumDelay;\n\t}\n\n\tif (delay > MaxDelay) {\n\t\tMaxDelay = delay;\n\t}\n}\n\n\n/***************************************************************************\n * CommQueueClass::Avg_Response_Time -- returns average response time    \t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tlatest computed average response time\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nunsigned long CommQueueClass::Avg_Response_Time(void)\n{\n\treturn(MeanDelay);\n}\n\n\n/***************************************************************************\n * CommQueueClass::Max_Response_Time -- returns max response time    \t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tlatest computed average response time\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nunsigned long CommQueueClass::Max_Response_Time(void)\n{\n\treturn(MaxDelay);\n}\n\n\n/***************************************************************************\n * CommQueueClass::Reset_Response_Time -- resets computations\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid CommQueueClass::Reset_Response_Time(void)\n{\n\tDelaySum = 0L;\n\tNumDelay = 0L;\n\tMeanDelay = 0L;\n\tMaxDelay = 0L;\n}\n\n\n/*************************************************************************** \n * CommQueueClass::Configure_Debug -- sets up special debug values         * \n *                                                                         * \n * Mono_Debug_Print2() can look into a packet to pull out a particular\t\t*\n * ID, and can print both that ID and a string corresponding to\t\t\t\t*\n * that ID.  This routine configures these values so it can find\t\t\t\t*\n * and decode the ID.  This ID is used in addition to the normal\t\t\t\t*\n * CommHeaderType values.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * INPUT:                                                                  * \n *\t\toffset\t\tID's byte offset into packet\t\t\t\t\t\t\t\t\t\t*\n *\t\tsize\t\t\tsize of ID, in bytes; 0 if none\t\t\t\t\t\t\t\t\t*\n *\t\tnames\t\t\tptr to array of names; use ID as an index into this\t\t*\n *\t\tmaxnames\t\tmax # in the names array; 0 if none.\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tNames shouldn't be longer than 12 characters.\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   05/31/1995 BRR : Created.                                             * \n *=========================================================================*/\nvoid CommQueueClass::Configure_Debug(int offset, int size, char **names, \n\tint maxnames)\n{\n\tDebugOffset = offset;\n\tDebugSize = size;\n\tDebugNames = names;\n\tDebugMaxNames = maxnames;\n}\n\n\n/*************************************************************************** \n * Mono_Debug_Print -- Debug output routine                                * \n *                                                                         * \n * This routine leaves 5 lines at the top for the caller's use.\t\t\t\t*\n *                                                                         * \n * INPUT:                                                                  * \n *\t\trefresh\t\t1 = clear screen & completely refresh\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   05/02/1995 BRR : Created.                                             * \n *=========================================================================*/\nvoid CommQueueClass::Mono_Debug_Print(int refresh)\n{\n#ifdef WWLIB32_H\n\tint i;\t\t\t\t\t\t\t\t\t\t\t\t// loop counter\n\tstatic int send_col[] = {1,14,28};\t\t\t// coords of send queue columns\n\tstatic int receive_col[] = {40,54,68};\t\t// coords of recv queue columns\n\tint row,col;\t\t\t\t\t\t\t\t\t\t// current row,col for printing\n\tint num;\t\t\t\t\t\t\t\t\t\t\t\t// max # items to print\n\n\tstruct CommHdr {\t\t\t\t\t\t\t\t\t// this mirrors the CommHeaderType\n\t\tunsigned short MagicNumber;\n\t\tunsigned char Code;\n\t\tunsigned long PacketID;\n\t} *hdr;\n\n\t/*\n\t**\tIf few enough entries, call the verbose debug version\n\t*/\n\tif (MaxSend <= 16) {\n\t\tMono_Debug_Print2(refresh);\n\t\treturn;\n\t}\n\n\t/*\n\t**\tRefresh the screen\n\t*/\n\tif (refresh) {\n\t\tMono_Clear_Screen ();\n\t\tMono_Printf(\"Ŀ\\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"Ĵ\\n\");\n\t\tMono_Printf(\"              Send Queue                           Receive Queue            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\" ID  Ct ACK   ID  Ct ACK    ID  Ct ACK ID  Rd ACK    ID  Rd ACK   ID  Rd ACK\\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"\");\n\t}\n\n\t/*\n\t**\tPrint Send Queue items\n\t*/\n\tif (MaxSend <= 48) {\n\t\tnum = MaxSend;\n\t} else {\n\t\tnum = 48;\n\t}\n\tcol = 0;\n\trow = 0;\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tMono_Set_Cursor (send_col[col],row + 8);\n\t\tif (SendQueue[i].IsActive) {\n\t\t\thdr = (CommHdr *)SendQueue[i].Buffer;\n\t\t\thdr->MagicNumber = hdr->MagicNumber;\n\t\t\thdr->Code = hdr->Code;\n\t\t\tMono_Printf (\"%4d %2d  %d\",hdr->PacketID, SendQueue[i].SendCount,\n\t\t\t\tSendQueue[i].IsACK);\n\t\t} else {\n\t\t\tMono_Printf (\"____ __  _ \");\n\t\t}\n\n\t\trow++;\n\t\tif (row > 15) {\n\t\t\trow = 0;\n\t\t\tcol++;\n\t\t}\n\t}\n\n\t/*\n\t**\tPrint Receive Queue items\n\t*/\n\tif (MaxReceive <= 48) {\n\t\tnum = MaxSend;\n\t} else {\n\t\tnum = 48;\n\t}\n\tcol = 0;\n\trow = 0;\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tMono_Set_Cursor (receive_col[col],row + 8);\n\t\tif (ReceiveQueue[i].IsActive) {\n\t\t\thdr = (CommHdr *)ReceiveQueue[i].Buffer;\n\t\t\tMono_Printf (\"%4d  %d  %d\",hdr->PacketID, ReceiveQueue[i].IsRead,\n\t\t\t\tReceiveQueue[i].IsACK);\n\t\t} else {\n\t\t\tMono_Printf (\"____  _  _ \");\n\t\t}\n\n\t\trow++;\n\t\tif (row > 15) {\n\t\t\trow = 0;\n\t\t\tcol++;\n\t\t}\n\t}\n\n#else\n\trefresh = refresh;\n#endif\t\n}\n\n\n/*************************************************************************** \n * CommQueueClass::Mono_Debug_Print2 -- Debug output; alternate format     * \n *                                                                         * \n * This routine prints more information than the other version; it's\t\t\t*\n * called only if the number of queue entries is small enough to support\t*\n * this format.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * INPUT:                                                                  * \n *\t\trefresh\t\t1 = clear screen & completely refresh\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   05/31/1995 BRR : Created.                                             * \n *=========================================================================*/\nvoid CommQueueClass::Mono_Debug_Print2(int refresh)\n{\n#ifdef WWLIB32_H\n\tint i;\t\t\t\t\t\t\t\t\t\t\t\t// loop counter\n\tchar txt[80];\n\tint val;\n\n\tstruct CommHdr {\t\t\t\t\t\t\t\t\t// this mirrors the CommHeaderType\n\t\tunsigned short MagicNumber;\n\t\tunsigned char Code;\n\t\tunsigned long PacketID;\n\t} *hdr;\n\n\t/*\n\t**\tRefresh the screen\n\t*/\n\tif (refresh) {\n\t\tMono_Clear_Screen ();\n\t\tMono_Printf(\"Ŀ\\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"Ĵ\\n\");\n\t\tMono_Printf(\"              Send Queue                           Receive Queue            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\" ID  Ct Type   Data  Name         ACK  ID  Rd Type   Data  Name         ACK \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"\");\n\t}\n\n\t/*\n\t**\tPrint Send Queue items\n\t*/\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tMono_Set_Cursor (1,8 + i);\n\t\t\n\t\t/*\n\t\t**\tPrint an active entry\n\t\t*/\n\t\tif (SendQueue[i].IsActive) {\n\t\t\t\n\t\t\t/*\n\t\t\t**\tGet header info\n\t\t\t*/\n\t\t\thdr = (CommHdr *)SendQueue[i].Buffer;\n\t\t\thdr->MagicNumber = hdr->MagicNumber;\n\t\t\thdr->Code = hdr->Code;\n\t\t\tsprintf(txt,\"%4d %2d %-5s  \",\n\t\t\t\thdr->PacketID,\n\t\t\t\tSendQueue[i].SendCount,\n\t\t\t\tConnectionClass::Command_Name(hdr->Code));\n\n\t\t\t/*\n\t\t\t**\tDecode app's ID & its name\n\t\t\t*/\n\t\t\tif (DebugSize && (DebugOffset + DebugSize) <= SendQueue[i].BufLen) {\n\t\t\t\tif (DebugSize==1) {\n\t\t\t\t\tval = *(SendQueue[i].Buffer + DebugOffset);\n\t\t\t\t} else {\n\t\t\t\t\tif (DebugSize==2) {\n\t\t\t\t\t\tval = *((short *)(SendQueue[i].Buffer + DebugOffset));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (DebugSize==4) {\n\t\t\t\t\t\t\tval = *((int *)(SendQueue[i].Buffer + DebugOffset));\n\t\t\t\t\t\t}\n\t\t\t\t\t} \n\t\t\t\t}\n\t\t\t\tsprintf(txt + strlen(txt),\"%4d  \",val);\n\n\t\t\t\tif (DebugMaxNames && val > 0 && val < DebugMaxNames) {\n\t\t\t\t\tsprintf(txt + strlen(txt),\"%-12s  %x\",\n\t\t\t\t\t\tDebugNames[val],\n\t\t\t\t\t\tSendQueue[i].IsACK);\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(txt + strlen(txt),\"              %x\",SendQueue[i].IsACK);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tEntry isn't active; print blanks\n\t\t\t*/\n\t\t\tMono_Printf(\"____ __                            _\");\n\t\t}\n\t}\n\n\t/*\n\t**\tPrint Receive Queue items\n\t*/\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tMono_Set_Cursor (40,8 + i);\n\t\t\n\t\t/*\n\t\t**\tPrint an active entry\n\t\t*/\n\t\tif (ReceiveQueue[i].IsActive) {\n\t\t\t\n\t\t\t/*\n\t\t\t**\tGet header info\n\t\t\t*/\n\t\t\thdr = (CommHdr *)ReceiveQueue[i].Buffer;\n\t\t\thdr->MagicNumber = hdr->MagicNumber;\n\t\t\thdr->Code = hdr->Code;\n\t\t\tsprintf(txt,\"%4d %2d %-5s  \",\n\t\t\t\thdr->PacketID,\n\t\t\t\tReceiveQueue[i].IsRead,\n\t\t\t\tConnectionClass::Command_Name(hdr->Code));\n\t\t\t\n\t\t\t/*\n\t\t\t**\tDecode app's ID & its name\n\t\t\t*/\n\t\t\tif (DebugSize && (DebugOffset + DebugSize) <= SendQueue[i].BufLen) {\n\t\t\t\tif (DebugSize==1) {\n\t\t\t\t\tval = *(ReceiveQueue[i].Buffer + DebugOffset);\n\t\t\t\t} else {\n\t\t\t\t\tif (DebugSize==2) {\n\t\t\t\t\t\tval = *((short *)(ReceiveQueue[i].Buffer + DebugOffset));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (DebugSize==4) {\n\t\t\t\t\t\t\tval = *((int *)(ReceiveQueue[i].Buffer + DebugOffset));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} \n\t\t\t\tsprintf(txt + strlen(txt),\"%4d  \",val);\n\n\t\t\t\tif (DebugMaxNames && val > 0 && val < DebugMaxNames) {\n\t\t\t\t\tsprintf(txt + strlen(txt),\"%-12s  %x\", DebugNames[val], ReceiveQueue[i].IsACK);\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(txt + strlen(txt),\"              %x\",ReceiveQueue[i].IsACK);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tEntry isn't active; print blanks\n\t\t\t*/\n\t\t\tMono_Printf(\"____ __                            _\");\n\t\t}\n\t}\n\n#else\n\trefresh = refresh;\n#endif\t\n}\n\n\n"
  },
  {
    "path": "CODE/COMQUEUE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\comqueue.h_v   4.1   11 Apr 1996 18:26:02   JOE_BOSTIC  $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : COMQUEUE.H                               *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 1, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This class's job is to queue up outgoing messages & incoming messages, \t*\n * and serves as a storage area for various flags for ACK & Retry logic.\t*\n * It allows the application to keep track of how many messages have \t\t*\n * passed through this queue, in & out, so packets can use this as a \t\t*\n * unique ID.  (If packets have a unique ID, the application can use this \t*\n * to detect re-sends.)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The queues act as FIFO buffers (First-In, First-Out).  The first entry\t*\n * placed in a queue is the first one read from it, and so on.  The\t\t\t*\n * controlling application must ensure it places the entries on the queue\t*\n * in the order it wants to access them.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The queue is implemented as an array of Queue Entries.  Index 0 is the\t*\n * first element placed on the queue, and is the first retrieved.  Index\t*\n * 1 is the next, and so on.  When Index 0 is retrieved, the next-available*\n * entry becomes Index 1.  The array is circular; when the end is reached,\t*\n * the indices wrap around to the beginning.\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The class also contains routines to maintain a cumulative response time\t*\n * for this queue.  It's up to the caller to call Add_Delay() whenever\t\t*\n * it detects that an outgoing message has been ACK'd; this class adds\t\t*\n * that delay into a computed average delay over the last few message \t\t*\n * delays.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef COMQUEUE_H\n#define COMQUEUE_H\n\n\n\n/*---------------------------------------------------------------------------\nThis is one output queue entry\n---------------------------------------------------------------------------*/\ntypedef struct {\n\tunsigned int IsActive\t: 1;\t// 1 = this entry is ready to be processed\n\tunsigned int IsACK\t\t: 1;\t// 1 = ACK received for this packet\n\tunsigned long FirstTime;\t\t// time this packet was first sent\n\tunsigned long LastTime;\t\t\t// time this packet was last sent\n\tunsigned long SendCount;\t\t// # of times this packet has been sent\n\tint BufLen;\t\t\t\t\t\t\t// size of the packet stored in this entry\n\tchar *Buffer;\t\t\t\t\t\t// the data packet\n} SendQueueType;\n\n/*---------------------------------------------------------------------------\nThis is one input queue entry\n---------------------------------------------------------------------------*/\ntypedef struct {\n\tunsigned int IsActive\t: 1;\t// 1 = this entry is ready to be processed\n\tunsigned int IsRead\t\t: 1;\t// 1 = caller has read this entry\n\tunsigned int IsACK\t\t: 1;\t// 1 = ACK sent for this packet\n\tint BufLen;\t\t\t\t\t\t\t// size of the packet stored in this entry\n\tchar *Buffer;\t\t\t\t\t\t// the data packet\n} ReceiveQueueType;\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass CommQueueClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*\n\t\t....................... Constructor/Destructor ........................\n\t\t*/\n\t\tCommQueueClass(int numsend, int numrecieve, int maxlen);\n\t\tvirtual ~CommQueueClass();\n\t\tvoid Init(void);\n\n\t\t/*\n\t\t......................... Send Queue routines .........................\n\t\t*/\n\t\tint Queue_Send(void *buf, int buflen);\t\t\t// add to Send queue\n\t\tint UnQueue_Send(void *buf, int *buflen);\t\t// remove from Send queue\n\t\tSendQueueType * Next_Send(void);\t\t\t\t\t// ptr to next avail entry\n\t\tint Num_Send(void) {return (SendCount);}\t\t// # entries in queue\n\t\tint Max_Send(void) { return (MaxSend);}\t\t// max # send queue entries\n\t\tSendQueueType * Get_Send(int index);\t\t\t// random access to queue\n\t\tunsigned long Send_Total(void) {return (SendTotal);}\n\n\t\t/*\n\t\t....................... Receive Queue routines ........................\n\t\t*/\n\t\tint Queue_Receive(void *buf, int buflen);\t\t// add to Receive queue\n\t\tint UnQueue_Receive(void *buf, int *buflen);\t// remove from Receive queue\n\t\tReceiveQueueType * Next_Receive(void);\t\t\t// ptr to next avail entry\n\t\tint Num_Receive(void) {return (ReceiveCount);}\t// # entries in queue\n\t\tint Max_Receive(void) { return (MaxReceive); }\t// max # recv queue entries\n\t\tReceiveQueueType * Get_Receive(int index);\t// random access to queue\n\t\tunsigned long Receive_Total(void) {return (ReceiveTotal);}\n\n\t\t/*\n\t\t....................... Response time routines ........................\n\t\t*/\n\t\tvoid Add_Delay(unsigned long delay);\t// accumulates response time\n\t\tunsigned long Avg_Response_Time(void);\t// gets mean response time\n\t\tunsigned long Max_Response_Time(void);\t// gets max response time\n\t\tvoid Reset_Response_Time(void);\t\t\t// resets computations\n\n\t\t/*\n\t\t........................ Debug output routines ........................\n\t\t*/\n\t\tvoid Configure_Debug(int offset, int size, char **names, int maxnames);\n\t\tvoid Mono_Debug_Print(int refresh = 0);\n\t\tvoid Mono_Debug_Print2(int refresh = 0);\n\n\t/*\n\t--------------------------- Private Interface ----------------------------\n\t*/\n\tprivate:\n\t\t/*\n\t\t.......................... Limiting variables .........................\n\t\t*/\n\t\tint MaxSend;\t\t\t\t\t\t\t// max # send queue entries\n\t\tint MaxReceive;\t\t\t\t\t\t// max # receive queue entries\n\t\tint MaxPacketSize;\t\t\t\t\t// max size of a packet, in bytes\n\n\t\t/*\n\t\t....................... Response time variables .......................\n\t\t*/\n\t\tunsigned long DelaySum;\t\t\t\t// sum of last 4 delay times\n\t\tunsigned long NumDelay;\t\t\t\t// current # delay times summed\n\t\tunsigned long MeanDelay;\t\t\t// current average delay time\n\t\tunsigned long MaxDelay;\t\t\t\t// max delay ever for this queue\n\n\t\t/*\n\t\t........................ Send Queue variables .........................\n\t\t*/\n\t\tSendQueueType * SendQueue;\t\t\t// incoming packets\n\t\tint SendCount; \t\t\t\t\t\t// # packets in the queue\n\t\tint SendNext;\t\t\t\t\t\t\t// next entry read from queue\n\t\tint SendEmpty;\t\t\t\t\t\t\t// next empty spot in queue\n\t\tunsigned long SendTotal;\t\t\t// total # added to send queue\n\n\t\t/*\n\t\t....................... Receive Queue variables .......................\n\t\t*/\n\t\tReceiveQueueType * ReceiveQueue;\t\t// outgoing packets\n\t\tint ReceiveCount;\t\t\t\t\t\t\t// # packets in the queue\n\t\tint ReceiveNext;\t\t\t\t\t\t\t// next entry read from queue\n\t\tint ReceiveEmpty;\t\t\t\t\t\t\t// next empty spot in queue\n\t\tunsigned long ReceiveTotal;\t\t\t// total # added to receive queue\n\n\t\t/*\n\t\t......................... Debugging Variables .........................\n\t\t*/\n\t\tint DebugOffset;\t\t\t\t\t\t\t// offset into app's packet for ID\n\t\tint DebugSize;\t\t\t\t\t\t\t\t// size of app's ID\n\t\tchar **DebugNames;\t\t\t\t\t\t// ptr to array of app-specific names\n\t\tint DebugMaxNames;\t\t\t\t\t\t// max # of names in array\n};\n\n#endif\n\n/*************************** end of comqueue.h *****************************/\n\n"
  },
  {
    "path": "CODE/CONFDLG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\confdlg.cpv   4.67   27 Aug 1996 15:46:52   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CONFDLG.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg                                  *\n *                                  Joe L. Bostic                                              *\n *                                                                                             *\n *                   Start Date : Jan 30, 1995                                                 *\n *                                                                                             *\n *                  Last Update : Jan 30, 1995   [MML]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ConfirmationClass::Process -- Handles all the options graphic interface.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"confdlg.h\"\n\n\nbool ConfirmationClass::Process(int text)\n{\n\treturn(Process(Text_String(text)));\n}\n\n\n/***********************************************************************************************\n * ConfirmationClass::Process -- Handles all the options graphic interface.                    *\n *                                                                                             *\n *    This dialog uses an edit box to confirm a deletion.                                      *\n *                                                                                             *\n * INPUT:   \tchar * string - display in edit box.                                            *\n *                                                                                             *\n * OUTPUT:  \tnone                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:    12/31/1994 MML : Created.                                                       *\n *=============================================================================================*/\nbool ConfirmationClass::Process(char const * string)\n{\n\tenum {\n\t\tNUM_OF_BUTTONS = 2\n\t};\n\n\tchar buffer[80*3];\n\tint result = true;\n\tint width;\n\tint bwidth, bheight;\t\t\t\t// button width and height\n\tint height;\n\tint selection = 0;\n\tbool pressed;\n\tint curbutton;\n\tTextButtonClass * buttons[NUM_OF_BUTTONS];\n\n\t/*\n\t**\tSet up the window.  Window x-coords are in bytes not pixels.\n\t*/\n\tstrcpy(buffer, string);\n\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_6PT_GRAD | TPF_NOSHADOW);\n\tFormat_Window_String(buffer, 200, width, height);\n\twidth += 60;\n\theight += 60;\n\tint x = (320 - width) / 2;\n\tint y = (200 - height) / 2;\n\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tCreate Buttons.  Button coords are in pixels, but are window-relative.\n\t*/\n\tbheight = FontHeight + FontYSpacing + 2;\n\tbwidth = max( (String_Pixel_Width( Text_String( TXT_YES ) ) + 8), 30);\n\n\tTextButtonClass yesbtn(BUTTON_YES, TXT_YES,\n\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n\t\tx + 10, y + height - (bheight + 5), bwidth );\n\n\tTextButtonClass nobtn(BUTTON_NO, TXT_NO,\n\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n\t\tx + width - (bwidth + 10),\n\t\ty + height - (bheight + 5), bwidth );\n\n\tnobtn.Add_Tail(yesbtn);\n\n\tcurbutton = 1;\n\tbuttons[0] = &yesbtn;\n\tbuttons[1] = &nobtn;\n\tbuttons[curbutton]->Turn_On();\n\n\t/*\n\t**\tThis causes left mouse button clicking within the confines of the dialog to\n\t**\tbe ignored if it wasn't recognized by any other button or slider.\n\t*/\n\tGadgetClass dialog(x, y, width, height, GadgetClass::LEFTPRESS);\n\tdialog.Add_Tail(yesbtn);\n\n\t/*\n\t**\tThis causes a right click anywhere or a left click outside the dialog region\n\t**\tto be equivalent to clicking on the return to options dialog.\n\t*/\n\tControlClass background(BUTTON_NO, 0, 0, 320, 200, GadgetClass::LEFTPRESS|GadgetClass::RIGHTPRESS);\n\tbackground.Add_Tail(yesbtn);\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tbool display = true;\n\tbool process = true;\n\tpressed = false;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\tCall_Back();\n\t\t} else {\n\t\t\tif (Main_Loop()) {\n\t\t\t\tprocess = false;\n\t\t\t\tresult = false;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t**\tDraw the background.\n\t\t\t*/\n\t\t\tDialog_Box(x, y, width, height);\n\t\t\tDraw_Caption(TXT_CONFIRMATION, x, y, width);\n\t\t\tFancy_Text_Print(buffer, x+20, y+30, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\t\t\t/*\n\t\t\t**\tDraw the titles.\n\t\t\t*/\n\t\t\tyesbtn.Draw_All();\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tKeyNumType input = yesbtn.Input();\n\n\t\t/*\n\t\t**\tProcess Input.\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase KeyNumType(BUTTON_YES | KN_BUTTON):\n\t\t\t\tselection = BUTTON_YES;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase KeyNumType(BUTTON_NO | KN_BUTTON):\n\t\t\t\tselection = BUTTON_NO;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_LEFT):\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\t\tcurbutton--;\n\t\t\t\tif (curbutton < 0) {\n\t\t\t\t\tcurbutton = NUM_OF_BUTTONS - 1;\n\t\t\t\t}\n\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RIGHT):\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\t\tcurbutton++;\n\t\t\t\tif (curbutton > (NUM_OF_BUTTONS - 1) ) {\n\t\t\t\t\tcurbutton = 0;\n\t\t\t\t}\n\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\t\tselection = curbutton + BUTTON_YES;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (pressed) {\n\t\t\tswitch (selection) {\n\t\t\t\tcase (BUTTON_YES):\n\t\t\t\t\tresult = true;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_NO):\n\t\t\t\t\tresult  = false;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tpressed = false;\n\t\t}\n\t}\n\treturn(result);\n}\n"
  },
  {
    "path": "CODE/CONFDLG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\confdlg.h_v   4.69   27 Aug 1996 15:43:36   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CONFDLG.H                                                    *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\t\t\t\t\t Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : Jan 30, 1995                                                 *\n *                                                                                             *\n *                  Last Update : Jan 30, 1995   [MML]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*/\n\n#ifndef CONFDLG_H\n#define CONFDLG_H\n\n#include \"gadget.h\"\n\nclass ConfirmationClass\n{\n\tprivate:\n\t\tenum ConfirmationClassEnum {\n\t\t\tBUTTON_YES=1,\t\t\t\t\t\t\t\t// Button number for \"Options menu\"\n\t\t\tBUTTON_NO\t\t\t\t\t\t\t\t\t// Button number for \"Options menu\"\n\t\t};\n\n\tpublic:\n\t\tConfirmationClass(void) {  };\n\t\tbool Process(char const * string);\n\t\tbool Process(int text);\n};\n\n#endif\n"
  },
  {
    "path": "CODE/CONNECT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CONNECT.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : CONNECT.CPP                              *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 20, 1994                        *\n *                                                                         *\n *                  Last Update : May 31, 1995 [BRR]\t\t\t\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:    \t\t\t                                                   *\n *   ConnectionClass::ConnectionClass -- class constructor                 *\n *   ConnectionClass::~ConnectionClass -- class destructor                 *\n *   ConnectionClass::Init -- Initializes connection queue to empty\t\t\t*\n *   ConnectionClass::Send_Packet -- adds a packet to the send queue\t\t\t*\n *   ConnectionClass::Receive_Packet -- adds packet to receive queue\t\t\t*\n *   ConnectionClass::Get_Packet -- gets a packet from receive queue\t\t\t*\n *   ConnectionClass::Service -- main polling routine; services packets\t\t*\n *   ConnectionClass::Service_Send_Queue -- services the send queue\t\t\t*\n *   ConnectionClass::Service_Receive_Queue -- services receive queue\t\t*\n *   ConnectionClass::Time -- gets current time\t\t\t\t\t\t\t\t\t\t*\n *   ConnectionClass::Command_Name -- returns name for a packet command\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\n#include\t\"function.h\"\n#include <stdio.h>\n#include <mem.h>\n#include <sys\\timeb.h>\n#include \"connect.h\"\n\n#include \"WolDebug.h\"\n\n/*\n********************************* Globals ***********************************\n*/\nstatic char *ConnectionClass::Commands[PACKET_COUNT] = {\n\t\"ADATA\",\n\t\"NDATA\",\n\t\"ACK\"\n};\n\n\n/***************************************************************************\n * ConnectionClass::ConnectionClass -- class constructor                   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t\tdesired # of entries for the send queue\t\t\t\t\t*\n *\t\tnumreceive\t\tdesired # of entries for the receive queue\t\t\t\t*\n *\t\tmaxlen\t\t\tmax length of an application packet\t\t\t\t\t\t\t*\n *\t\tmagicnum\t\t\tthe packet \"magic number\" for this connection\t\t\t*\n *\t\tretry_delta\t\tthe time to wait between sends\t\t\t\t\t\t\t\t*\n *\t\tmax_retries\t\tthe max # of retries allowed for a packet\t\t\t\t\t*\n *\t\t\t\t\t\t\t(-1 means retry forever, based on this parameter)\t\t*\n *\t\ttimeout\t\t\tthe max amount of time before we give up on a packet\t*\n *\t\t\t\t\t\t\t(-1 means retry forever, based on this parameter)\t\t*\n *\t\textralen\t\t\tmax size of app-specific extra bytes (optional)\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nConnectionClass::ConnectionClass (int numsend, int numreceive,\n\tint maxlen, unsigned short magicnum, unsigned long retry_delta,\n\tunsigned long max_retries, unsigned long timeout, int extralen)\n{\n\t/*------------------------------------------------------------------------\n\tCompute our maximum packet length\n\t------------------------------------------------------------------------*/\n\tMaxPacketLen = maxlen + sizeof(CommHeaderType);\n\n\t/*------------------------------------------------------------------------\n\tAssign the magic number\n\t------------------------------------------------------------------------*/\n\tMagicNum = magicnum;\n\n\t/*------------------------------------------------------------------------\n\tInitialize the retry time.  This is the time that t2 - t1 must be greater\n\tthan before a retry will occur.\n\t------------------------------------------------------------------------*/\n\tRetryDelta = retry_delta;\n\n\t/*------------------------------------------------------------------------\n\tSet the maximum allowable retries.\n\t------------------------------------------------------------------------*/\n\tMaxRetries = max_retries;\n\n\t/*------------------------------------------------------------------------\n\tSet the timeout for this connection.\n\t------------------------------------------------------------------------*/\n\tTimeout = timeout;\n\n\t/*------------------------------------------------------------------------\n\tAllocate the packet staging buffer.  This will be used to\n\t------------------------------------------------------------------------*/\n\tPacketBuf = new char[ MaxPacketLen ];\n\n\t/*------------------------------------------------------------------------\n\tAllocate the packet Queue.  This will store incoming packets (placed there\n\tby Receive_Packet), and outgoing packets (placed there by Send_Packet).\n\tIt can optionally store \"extra\" bytes, which are stored along with each\n\tpacket, but aren't transmitted as part of the packet.  If 'extralen'\n\tis 0, the CommBufferClass ignores this parameter.\n\t------------------------------------------------------------------------*/\n\tQueue = new CommBufferClass (numsend, numreceive, MaxPacketLen, extralen);\n\n}\t/* end of ConnectionClass */\n\n\n/***************************************************************************\n * ConnectionClass::~ConnectionClass -- class destructor                   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nConnectionClass::~ConnectionClass ()\n{\n\t/*------------------------------------------------------------------------\n\tFree memory.\n\t------------------------------------------------------------------------*/\n\tdelete [] PacketBuf;\n\tdelete Queue;\n\n}\t/* end of ~ConnectionClass */\n\n\n/***************************************************************************\n * ConnectionClass::Init -- Initializes connection queue to empty\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid ConnectionClass::Init (void)\n{\n\tNumRecNoAck = 0;\n\tNumRecAck = 0;\n\tNumSendNoAck = 0;\n\tNumSendAck = 0;\n\n\tLastSeqID = 0xffffffff;\n\tLastReadID = 0xffffffff;\n\n\tQueue->Init();\n\n}\t/* end of Init */\n\n\n/***************************************************************************\n * ConnectionClass::Send_Packet -- adds a packet to the send queue\t\t\t*\n *                                                                         *\n * This routine prefixes the given buffer with a CommHeaderType and\t\t\t*\n * queues the resulting packet into the Send Queue.  (It's actually the\t\t*\n * Service() routine that handles the hardware-dependent Send of the data).*\n * The packet's MagicNumber, Code, and PacketID are set here.\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tack_req\t\t1 = ACK is required for this packet; 0 = isn't\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was queue'd OK, 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Send_Packet (void * buf, int buflen, int ack_req)\n{\n\t/*------------------------------------------------------------------------\n\tSet the magic # for the packet\n\t------------------------------------------------------------------------*/\n\t((CommHeaderType *)PacketBuf)->MagicNumber = MagicNum;\n\n\t/*------------------------------------------------------------------------\n\tSet the packet Code: DATA_ACK if it requires an ACK, NOACK if it doesn't\n\tSet the packet ID to the appropriate counter value.\n\t------------------------------------------------------------------------*/\n\tif (ack_req) {\n\t\t((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_ACK;\n\t\t((CommHeaderType *)PacketBuf)->PacketID = NumSendAck;\n\t}\n\telse {\n\t\t((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_NOACK;\n\t\t((CommHeaderType *)PacketBuf)->PacketID = NumSendNoAck;\n\t}\n\n\t/*------------------------------------------------------------------------\n\tNow build the packet\n\t------------------------------------------------------------------------*/\n\tmemcpy(PacketBuf + sizeof(CommHeaderType), buf, buflen);\n\n\t/*------------------------------------------------------------------------\n\tAdd it to the queue; don't add any extra data with it.\n\t------------------------------------------------------------------------*/\n\tif (Queue->Queue_Send(PacketBuf,buflen + sizeof(CommHeaderType), NULL, 0)) {\n\t\tif (ack_req) {\n\t\t\tNumSendAck++;\n\t\t}\n\t\telse {\n\t\t\tNumSendNoAck++;\n\t\t}\n\t\treturn(1);\n\t}\n\telse {\n\t\treturn(0);\n\t}\n\n}\t/* end of Send_Packet */\n\n\n/***************************************************************************\n * ConnectionClass::Receive_Packet -- adds packet to receive queue\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tbuffer to process (already includes CommHeaderType)\t\t\t*\n *\t\tbuflen\tlength of buffer to process\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was processed OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Receive_Packet (void * buf, int buflen)\n{\n\tCommHeaderType *packet;\t\t\t\t\t\t\t\t// ptr to packet header\n\tSendQueueType *send_entry;\t\t\t\t\t\t\t// ptr to send entry header\n\tReceiveQueueType *rec_entry;\t\t\t\t\t\t// ptr to recv entry header\n\tCommHeaderType *entry_data;\t\t\t\t\t\t// ptr to queue entry data\n\tCommHeaderType ackpacket;\t\t\t\t\t\t\t// ACK packet to send\n\tint i;\n\tint save_packet = 1;\t\t\t\t\t\t\t\t\t// 0 = this is a resend\n\tint found;\n\n\t/*------------------------------------------------------------------------\n\tCheck the magic #\n\t------------------------------------------------------------------------*/\n\tpacket = (CommHeaderType *)buf;\n\tif (packet->MagicNumber != MagicNum) {\n\t\treturn(0);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tHandle an incoming ACK\n\t------------------------------------------------------------------------*/\n\tif (packet->Code == PACKET_ACK) {\n\n\t\tfor (i = 0; i < Queue->Num_Send(); i++) {\n\t\t\t/*..................................................................\n\t\t\tGet queue entry ptr\n\t\t\t..................................................................*/\n\t\t\tsend_entry = Queue->Get_Send(i);\n\n\t\t\t/*..................................................................\n\t\t\tIf ptr is valid, get ptr to its data\n\t\t\t..................................................................*/\n\t\t\tif (send_entry != NULL) {\n\t\t\t\tentry_data = (CommHeaderType *)send_entry->Buffer;\n\n\t\t\t\t/*...............................................................\n\t\t\t\tIf ACK is for this entry, mark it\n\t\t\t\t...............................................................*/\n\t\t\t\tif (packet->PacketID==entry_data->PacketID &&\n\t\t\t\t\tentry_data->Code == PACKET_DATA_ACK) {\n\t\t\t\t\tsend_entry->IsACK = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn(1);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tHandle an incoming PACKET_DATA_NOACK packet\n\t------------------------------------------------------------------------*/\n\telse if (packet->Code == PACKET_DATA_NOACK) {\n\t\t/*.....................................................................\n\t\tIf there's only one slot left, don't tie up the queue with this packet\n\t\t.....................................................................*/\n\t\tif (Queue->Max_Receive() - Queue->Num_Receive() <= 1) {\n\t\t\treturn(0);\n\t\t}\n\n\t\t/*.....................................................................\n\t\tError if we can't queue the packet\n\t\t.....................................................................*/\n\t\tif (!Queue->Queue_Receive (buf, buflen, NULL, 0)) {\n\t\t\treturn(0);\n\t\t}\n\n\t\tNumRecNoAck++;\n\n\t\treturn(1);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tHandle an incoming PACKET_DATA_ACK packet\n\t------------------------------------------------------------------------*/\n\telse if (packet->Code == PACKET_DATA_ACK) {\n\t\t/*.....................................................................\n\t\tIf this is a packet requires an ACK, and it's ID is older than our\n\t\t\"oldest\" ID, we know it's a resend; send an ACK, but don't queue it\n\t\t.....................................................................*/\n\t\tif (packet->PacketID <= LastSeqID && LastSeqID != 0xffffffff) {\n\t\t\tsave_packet = 0;\n\t\t}\n\n\t\t/*.....................................................................\n\t\tOtherwise, scan the queue for this entry; if it's found, it's a\n\t\tresend, so don't save it.\n\t\t.....................................................................*/\n\t\telse {\n\t\t\tsave_packet = 1;\n\t\t\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\t\t\t\trec_entry = Queue->Get_Receive(i);\n\n\t\t\t\tif (rec_entry) {\n\n\t\t\t\t\tentry_data = (CommHeaderType *)rec_entry->Buffer;\n\n\t\t\t\t\t/*...........................................................\n\t\t\t\t\tPacket is found; it's a resend\n\t\t\t\t\t...........................................................*/\n\t\t\t\t\tif (entry_data->Code == PACKET_DATA_ACK &&\n\t\t\t\t\t\tentry_data->PacketID == packet->PacketID) {\n\t\t\t\t\t\tsave_packet = 0;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\t/* end of scan for resend */\n\n\t\t/*.....................................................................\n\t\tQueue the packet & update our LastSeqID value.\n\t\t.....................................................................*/\n\t\tif (save_packet) {\n\t\t\t/*..................................................................\n\t\t\tIf there's only one slot left, make sure we only put a packet in it\n\t\t\tif this packet will let us increment our LastSeqID; otherwise, we'll\n\t\t\tget stuck, forever unable to increment LastSeqID.\n\t\t\t..................................................................*/\n\t\t\tif (Queue->Max_Receive() - Queue->Num_Receive() <= 1) {\n\t\t\t\tif (packet->PacketID != (LastSeqID + 1) ) {\n\t\t\t\t\treturn(0);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tIf we can't queue the packet, return; don't send an ACK.\n\t\t\t..................................................................*/\n\t\t\tif (!Queue->Queue_Receive (buf, buflen, NULL, 0)) {\n\t\t\t\treturn(0);\n\t\t\t}\n\n\t\t\tNumRecAck++;\n\n\t\t\t/*..................................................................\n\t\t\tUpdate our LastSeqID value if we can.  Anything less than LastSeqID\n\t\t\twe'll know is a resend.\n\t\t\t..................................................................*/\n\t\t\tif (packet->PacketID == (LastSeqID + 1)) {\n\t\t\t\tLastSeqID = packet->PacketID;\n\t\t\t\t/*...............................................................\n\t\t\t\tNow that we have a new 'LastSeqID', search our Queue to see if\n\t\t\t\tthe next ID is there; if so, keep checking for the next one;\n\t\t\t\tbreak only when the next one isn't found.  This forces\n\t\t\t\tLastSeqID to be the largest possible value.\n\t\t\t\t...............................................................*/\n\t\t\t\tdo {\n\t\t\t\t\tfound = 0;\n\t\t\t\t\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\n\t\t\t\t\t\trec_entry = Queue->Get_Receive(i);\n\n\t\t\t\t\t\tif (rec_entry) {\n\t\t\t\t\t\t\tentry_data = (CommHeaderType *)rec_entry->Buffer;\n\n\t\t\t\t\t\t\t/*......................................................\n\t\t\t\t\t\t\tEntry is found\n\t\t\t\t\t\t\t......................................................*/\n\t\t\t\t\t\t\tif (entry_data->Code == PACKET_DATA_ACK &&\n\t\t\t\t\t\t\t\tentry_data->PacketID == (LastSeqID + 1)) {\n\n\t\t\t\t\t\t\t\tLastSeqID = entry_data->PacketID;\n\t\t\t\t\t\t\t\tfound = 1;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} while (found);\n\t\t\t}\n\t\t}\t/* end of save packet */\n\n\t\t/*.....................................................................\n\t\tSend an ACK, regardless of whether this was a resend or not.\n\t\t.....................................................................*/\n\t\tackpacket.MagicNumber = Magic_Num();\n\t\tackpacket.Code = PACKET_ACK;\n\t\tackpacket.PacketID = packet->PacketID;\n\t\tSend ((char *)&ackpacket, sizeof(CommHeaderType), NULL, 0);\n\n\t\treturn(1);\n\t}\n\n\treturn(0);\n\n}\t/* end of Receive_Packet */\n\n\n/***************************************************************************\n * ConnectionClass::Get_Packet -- gets a packet from receive queue\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tlocation to store buffer\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\tfilled in with length of 'buf'\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was read, 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Get_Packet (void * buf, int *buflen)\n{\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\tint packetlen;\t\t\t\t\t\t\t\t\t\t// size of received packet\n\tCommHeaderType *entry_data;\n\tint i;\n\n\t/*------------------------------------------------------------------------\n\tEnsure that we read the packets in order.  LastReadID is the ID of the\n\tlast PACKET_DATA_ACK packet we read.\n\t------------------------------------------------------------------------*/\n\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\n\t\trec_entry = Queue->Get_Receive(i);\n\n\t\t/*.....................................................................\n\t\tOnly read this entry if it hasn't been yet\n\t\t.....................................................................*/\n\t\tif (rec_entry && rec_entry->IsRead==0) {\n\n\t\t\tentry_data = (CommHeaderType *)rec_entry->Buffer;\n\n\t\t\t/*..................................................................\n\t\t\tIf this is a DATA_ACK packet, its ID must be one greater than\n\t\t\tthe last one we read.\n\t\t\t..................................................................*/\n\t\t\tif ( (entry_data->Code == PACKET_DATA_ACK) &&\n\t\t\t\t(entry_data->PacketID == (LastReadID + 1))) {\n\n\t\t\t\tLastReadID = entry_data->PacketID;\n\t\t\t\trec_entry->IsRead = 1;\n\n\t\t\t\tpacketlen = rec_entry->BufLen - sizeof(CommHeaderType);\n\t\t\t\tif (packetlen > 0) {\n\t\t\t\t\tmemcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType),\n\t\t\t\t\t\tpacketlen);\n\t\t\t\t}\n\t\t\t\t(*buflen) = packetlen;\n\t\t\t\treturn(1);\n\t\t\t}\n\t\t\t/*..................................................................\n\t\t\tIf this is a DATA_NOACK packet, who cares what the ID is?\n\t\t\t..................................................................*/\n\t\t\telse if (entry_data->Code == PACKET_DATA_NOACK) {\n\t\t\t\trec_entry->IsRead = 1;\n\n\t\t\t\tpacketlen = rec_entry->BufLen - sizeof(CommHeaderType);\n\t\t\t\tif (packetlen > 0) {\n\t\t\t\t\tmemcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType),\n\t\t\t\t\t\tpacketlen);\n\t\t\t\t}\n\t\t\t\t(*buflen) = packetlen;\n\t\t\t\treturn(1);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(0);\n\n}\t/* end of Get_Packet */\n\n\n/***************************************************************************\n * ConnectionClass::Service -- main polling routine; services packets\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error (connection is broken!)\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Service (void)\n{\n\t/*------------------------------------------------------------------------\n\tService the Send Queue:  This [re]sends packets in the Send Queue which\n\thaven't been ACK'd yet, and if their retry timeout has expired, and\n\tupdates the FirstTime, LastTime & SendCount values in the Queue entry.\n\tEntries that have been ACK'd should be removed.\n\n\tService the Receive Queue:  This sends ACKs for packets that haven't\n\tbeen ACK'd yet.  Entries that the app has read, and have been ACK'd,\n\tshould be removed.\n\t------------------------------------------------------------------------*/\n\tif ( Service_Send_Queue() && Service_Receive_Queue() ) {\n\t\treturn(1);\n\t}\n\telse {\n\t\treturn(0);\n\t}\n\n}\t/* end of Service */\n\n\n/***************************************************************************\n * ConnectionClass::Service_Send_Queue -- services the send queue\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Service_Send_Queue (void)\n{\n\tint i;\n\tint num_entries;\n\tSendQueueType *send_entry;\t\t\t\t\t\t// ptr to send queue entry\n\tCommHeaderType *packet_hdr;\t\t\t\t\t// packet header\n\tunsigned long curtime;\t\t\t\t\t\t\t// current time\n\tint bad_conn = 0;\n\n\t/*------------------------------------------------------------------------\n\tRemove any ACK'd packets from the queue\n\t------------------------------------------------------------------------*/\n\tfor (i = 0; i < Queue->Num_Send(); i++) {\n\t\t/*.....................................................................\n\t\tGet this queue entry\n\t\t.....................................................................*/\n\t\tsend_entry = Queue->Get_Send(i);\n\n\t\t/*.....................................................................\n\t\tIf ACK has been received, unqueue it\n\t\t.....................................................................*/\n\t\tif (send_entry->IsACK) {\n\n\t\t\t/*..................................................................\n\t\t\tUpdate this queue's response time\n\t\t\t..................................................................*/\n\t\t\tpacket_hdr = (CommHeaderType *)send_entry->Buffer;\n\t\t\tif (packet_hdr->Code == PACKET_DATA_ACK) {\n\t\t\t\tQueue->Add_Delay(Time() - send_entry->FirstTime);\n\t\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tUnqueue the packet\n\t\t\t..................................................................*/\n\t\t\tQueue->UnQueue_Send(NULL,NULL,i,NULL,NULL);\n\t\t\ti--;\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tLoop through all entries in the Send queue.  [Re]Send any entries that\n\tneed it.\n\t------------------------------------------------------------------------*/\n\tnum_entries = Queue->Num_Send();\n\n\tfor (i = 0; i < num_entries; i++) {\n\t\tsend_entry = Queue->Get_Send(i);\n\n\t\tif (send_entry->IsACK) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*.....................................................................\n\t\tOnly send the message if time has elapsed.  (The message's Time\n\t\tfields are init'd to 0 when a message is queue'd or unqueue'd, so the\n\t\tfirst time through, the delta time will appear large.)\n\t\t.....................................................................*/\n\t\tcurtime = Time();\n\t\tif (curtime - send_entry->LastTime > RetryDelta) {\n\n\t\t\t/*..................................................................\n\t\t\tSend the message\n\t\t\t..................................................................*/\n\t\t\tSend (send_entry->Buffer, send_entry->BufLen, send_entry->ExtraBuffer,\n\t\t\t\tsend_entry->ExtraLen);\n\n\t\t\t/*..................................................................\n\t\t\tFill in Time fields\n\t\t\t..................................................................*/\n\t\t\tsend_entry->LastTime = curtime;\n\t\t\tif (send_entry->SendCount==0) {\n\t\t\t\tsend_entry->FirstTime = curtime;\n\n\t\t\t\t/*...............................................................\n\t\t\t\tIf this is the 1st time we're sending this packet, and it doesn't\n\t\t\t\trequire an ACK, mark it as ACK'd; then, the next time through,\n\t\t\t\tit will just be removed from the queue.\n\t\t\t\t...............................................................*/\n\t\t\t\tpacket_hdr = (CommHeaderType *)send_entry->Buffer;\n\t\t\t\tif (packet_hdr->Code == PACKET_DATA_NOACK) {\n\t\t\t\t\tsend_entry->IsACK = 1;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tUpdate SendCount\n\t\t\t..................................................................*/\n\t\t\tsend_entry->SendCount++;\n\n\t\t\t/*..................................................................\n\t\t\tPerform error detection, based on either MaxRetries or Timeout\n\t\t\t..................................................................*/\n\t\t\tif (MaxRetries != -1 && send_entry->SendCount > MaxRetries) {\n\t\t\t\tbad_conn = 1;\n\t\t\t}\n\n\t\t\tif (Timeout != -1 &&\n\t\t\t\t(send_entry->LastTime - send_entry->FirstTime) > Timeout) {\n\t\t\t\tbad_conn = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tIf the connection is going bad, return an error\n\t------------------------------------------------------------------------*/\n\tif (bad_conn) {\n\t\treturn(0);\n\t}\n\telse {\n\t\treturn(1);\n\t}\n\n}\t/* end of Service_Send_Queue */\n\n\n/***************************************************************************\n * ConnectionClass::Service_Receive_Queue -- services receive queue\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Service_Receive_Queue (void)\n{\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\tCommHeaderType *packet_hdr;\t\t\t\t\t// packet header\n\tint i;\n\n\t/*------------------------------------------------------------------------\n\tRemove all dead packets.\n\tPACKET_DATA_NOACK: if it's been read, throw it away.\n\tPACKET_DATA_ACK: if it's been read, and its ID is older than LastSeqID,\n\tthrow it away.\n\t------------------------------------------------------------------------*/\n\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\t\trec_entry = Queue->Get_Receive(i);\n\n\t\tif (rec_entry->IsRead) {\n\t\t\tpacket_hdr = (CommHeaderType *)(rec_entry->Buffer);\n\n\t\t\tif (packet_hdr->Code == PACKET_DATA_NOACK) {\n\t\t\t\tQueue->UnQueue_Receive(NULL,NULL,i,NULL,NULL);\n\t\t\t\ti--;\n\n\t\t\t}\n\t\t\telse if (packet_hdr->PacketID < LastSeqID) {\n\t\t\t\tQueue->UnQueue_Receive(NULL,NULL,i,NULL,NULL);\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(1);\n\n}\t/* end of Service_Receive_Queue */\n\n\n/***************************************************************************\n * ConnectionClass::Time -- gets current time\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nunsigned long ConnectionClass::Time (void)\n{\n\tstatic struct timeb mytime;\t\t\t// DOS time\n\tunsigned long msec;\n\n#ifdef WWLIB32_H\n\n\t/*------------------------------------------------------------------------\n\tIf the Westwood timer system has been activated, use TickCount's value\n\t------------------------------------------------------------------------*/\n\tif (TimerSystemOn) {\n\t\treturn(TickCount);\t\t\t\t// Westwood Library time\n\t}\n\t/*------------------------------------------------------------------------\n\tOtherwise, use the DOS timer\n\t------------------------------------------------------------------------*/\n\telse {\n\t\tftime(&mytime);\n\t\tmsec = (unsigned long)mytime.time * 1000L + (unsigned long)mytime.millitm;\n\t\treturn((msec / 100) * 6);\n\t}\n\n#else\n\n\t/*------------------------------------------------------------------------\n\tIf the Westwood library isn't being used, use the DOS timer.\n\t------------------------------------------------------------------------*/\n\tftime(&mytime);\n\tmsec = (unsigned long)mytime.time * 1000L + (unsigned long)mytime.millitm;\n\treturn((msec / 100) * 6);\n\n#endif\n\n}\t/* end of Time */\n\n\n/***************************************************************************\n * ConnectionClass::Command_Name -- returns name for given packet command  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tcommand\t\tpacket Command value to get name for\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to command name, NULL if invalid\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/31/1995 BRR : Created.                                             *\n *=========================================================================*/\nchar *ConnectionClass::Command_Name(int command)\n{\n\tif (command >= 0 && command < PACKET_COUNT) {\n\t\treturn(Commands[command]);\n\t}\n\telse {\n\t\treturn(NULL);\n\t}\n\n}\t/* end of Command_Name */\n\n/************************** end of connect.cpp *****************************/\n\n\n"
  },
  {
    "path": "CODE/CONNECT.CPP.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\connect.cpv   4.76   03 Oct 1996 09:20:28   JOE_BOSTIC  $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : CONNECT.CPP                              *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 20, 1994                        *\n *                                                                         *\n *                  Last Update : May 31, 1995 [BRR]\t\t\t\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:    \t\t\t                                                   *\n *   ConnectionClass::ConnectionClass -- class constructor                 *\n *   ConnectionClass::~ConnectionClass -- class destructor                 *\n *   ConnectionClass::Init -- Initializes connection queue to empty\t\t\t*\n *   ConnectionClass::Send_Packet -- adds a packet to the send queue\t\t\t*\n *   ConnectionClass::Receive_Packet -- adds packet to receive queue\t\t\t*\n *   ConnectionClass::Get_Packet -- gets a packet from receive queue\t\t\t*\n *   ConnectionClass::Service -- main polling routine; services packets\t\t*\n *   ConnectionClass::Service_Send_Queue -- services the send queue\t\t\t*\n *   ConnectionClass::Service_Receive_Queue -- services receive queue\t\t*\n *   ConnectionClass::Time -- gets current time\t\t\t\t\t\t\t\t\t\t*\n *   ConnectionClass::Command_Name -- returns name for a packet command\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n#include <stdio.h>\n#include <mem.h>\n#include <sys\\timeb.h>\n#include \"connect.h\"\n\n/*\n********************************* Globals ***********************************\n*/\nstatic char *ConnectionClass::Commands[PACKET_COUNT] = {\n\t\"ADATA\",\n\t\"NDATA\",\n\t\"ACK\"\n};\n\n\n/***************************************************************************\n * ConnectionClass::ConnectionClass -- class constructor                   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t\tdesired # of entries for the send queue\t\t\t\t\t*\n *\t\tnumreceive\t\tdesired # of entries for the receive queue\t\t\t\t*\n *\t\tmaxlen\t\t\tmax length of an application packet\t\t\t\t\t\t\t*\n *\t\tmagicnum\t\t\tthe packet \"magic number\" for this connection\t\t\t*\n *\t\tretry_delta\t\tthe time to wait between sends\t\t\t\t\t\t\t\t*\n *\t\tmax_retries\t\tthe max # of retries allowed for a packet\t\t\t\t\t*\n *\t\t\t\t\t\t\t(-1 means retry forever, based on this parameter)\t\t*\n *\t\ttimeout\t\t\tthe max amount of time before we give up on a packet\t*\n *\t\t\t\t\t\t\t(-1 means retry forever, based on this parameter)\t\t*\n *\t\textralen\t\t\tmax size of app-specific extra bytes (optional)\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nConnectionClass::ConnectionClass (int numsend, int numreceive,\n\tint maxlen, unsigned short magicnum, unsigned long retry_delta,\n\tunsigned long max_retries, unsigned long timeout, int extralen)\n{\n\t/*------------------------------------------------------------------------\n\tCompute our maximum packet length\n\t------------------------------------------------------------------------*/\n\tMaxPacketLen = maxlen + sizeof(CommHeaderType);\n\n\t/*------------------------------------------------------------------------\n\tAssign the magic number\n\t------------------------------------------------------------------------*/\n\tMagicNum = magicnum;\n\n\t/*------------------------------------------------------------------------\n\tInitialize the retry time.  This is the time that t2 - t1 must be greater\n\tthan before a retry will occur.\n\t------------------------------------------------------------------------*/\n\tRetryDelta = retry_delta;\n\n\t/*------------------------------------------------------------------------\n\tSet the maximum allowable retries.\n\t------------------------------------------------------------------------*/\n\tMaxRetries = max_retries;\n\n\t/*------------------------------------------------------------------------\n\tSet the timeout for this connection.\n\t------------------------------------------------------------------------*/\n\tTimeout = timeout;\n\n\t/*------------------------------------------------------------------------\n\tAllocate the packet staging buffer.  This will be used to\n\t------------------------------------------------------------------------*/\n\tPacketBuf = new char[ MaxPacketLen ];\n\n\t/*------------------------------------------------------------------------\n\tAllocate the packet Queue.  This will store incoming packets (placed there\n\tby Receive_Packet), and outgoing packets (placed there by Send_Packet).\n\tIt can optionally store \"extra\" bytes, which are stored along with each\n\tpacket, but aren't transmitted as part of the packet.  If 'extralen'\n\tis 0, the CommBufferClass ignores this parameter.\n\t------------------------------------------------------------------------*/\n\tQueue = new CommBufferClass (numsend, numreceive, MaxPacketLen, extralen);\n\n}\t/* end of ConnectionClass */\n\n\n/***************************************************************************\n * ConnectionClass::~ConnectionClass -- class destructor                   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nConnectionClass::~ConnectionClass ()\n{\n\t/*------------------------------------------------------------------------\n\tFree memory.\n\t------------------------------------------------------------------------*/\n\tdelete [] PacketBuf;\n\tdelete Queue;\n\n}\t/* end of ~ConnectionClass */\n\n\n/***************************************************************************\n * ConnectionClass::Init -- Initializes connection queue to empty\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid ConnectionClass::Init (void)\n{\n\tNumRecNoAck = 0;\n\tNumRecAck = 0;\n\tNumSendNoAck = 0;\n\tNumSendAck = 0;\n\n\tLastSeqID = 0xffffffff;\n\tLastReadID = 0xffffffff;\n\n\tQueue->Init();\n\n}\t/* end of Init */\n\n\n/***************************************************************************\n * ConnectionClass::Send_Packet -- adds a packet to the send queue\t\t\t*\n *                                                                         *\n * This routine prefixes the given buffer with a CommHeaderType and\t\t\t*\n * queues the resulting packet into the Send Queue.  (It's actually the\t\t*\n * Service() routine that handles the hardware-dependent Send of the data).*\n * The packet's MagicNumber, Code, and PacketID are set here.\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tack_req\t\t1 = ACK is required for this packet; 0 = isn't\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was queue'd OK, 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Send_Packet (void * buf, int buflen, int ack_req)\n{\n\t/*------------------------------------------------------------------------\n\tSet the magic # for the packet\n\t------------------------------------------------------------------------*/\n\t((CommHeaderType *)PacketBuf)->MagicNumber = MagicNum;\n\n\t/*------------------------------------------------------------------------\n\tSet the packet Code: DATA_ACK if it requires an ACK, NOACK if it doesn't\n\tSet the packet ID to the appropriate counter value.\n\t------------------------------------------------------------------------*/\n\tif (ack_req) {\n\t\t((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_ACK;\n\t\t((CommHeaderType *)PacketBuf)->PacketID = NumSendAck;\n\t}\n\telse {\n\t\t((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_NOACK;\n\t\t((CommHeaderType *)PacketBuf)->PacketID = NumSendNoAck;\n\t}\n\n\t/*------------------------------------------------------------------------\n\tNow build the packet\n\t------------------------------------------------------------------------*/\n\tmemcpy(PacketBuf + sizeof(CommHeaderType), buf, buflen);\n\n\t/*------------------------------------------------------------------------\n\tAdd it to the queue; don't add any extra data with it.\n\t------------------------------------------------------------------------*/\n\tif (Queue->Queue_Send(PacketBuf,buflen + sizeof(CommHeaderType), NULL, 0)) {\n\t\tif (ack_req) {\n\t\t\tNumSendAck++;\n\t\t}\n\t\telse {\n\t\t\tNumSendNoAck++;\n\t\t}\n\t\treturn(1);\n\t}\n\telse {\n\t\treturn(0);\n\t}\n\n}\t/* end of Send_Packet */\n\n\n/***************************************************************************\n * ConnectionClass::Receive_Packet -- adds packet to receive queue\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tbuffer to process (already includes CommHeaderType)\t\t\t*\n *\t\tbuflen\tlength of buffer to process\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was processed OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Receive_Packet (void * buf, int buflen)\n{\n\tCommHeaderType *packet;\t\t\t\t\t\t\t\t// ptr to packet header\n\tSendQueueType *send_entry;\t\t\t\t\t\t\t// ptr to send entry header\n\tReceiveQueueType *rec_entry;\t\t\t\t\t\t// ptr to recv entry header\n\tCommHeaderType *entry_data;\t\t\t\t\t\t// ptr to queue entry data\n\tCommHeaderType ackpacket;\t\t\t\t\t\t\t// ACK packet to send\n\tint i;\n\tint save_packet = 1;\t\t\t\t\t\t\t\t\t// 0 = this is a resend\n\tint found;\n\n\t/*------------------------------------------------------------------------\n\tCheck the magic #\n\t------------------------------------------------------------------------*/\n\tpacket = (CommHeaderType *)buf;\n\tif (packet->MagicNumber != MagicNum) {\n\t\treturn(0);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tHandle an incoming ACK\n\t------------------------------------------------------------------------*/\n\tif (packet->Code == PACKET_ACK) {\n\n\t\tfor (i = 0; i < Queue->Num_Send(); i++) {\n\t\t\t/*..................................................................\n\t\t\tGet queue entry ptr\n\t\t\t..................................................................*/\n\t\t\tsend_entry = Queue->Get_Send(i);\n\n\t\t\t/*..................................................................\n\t\t\tIf ptr is valid, get ptr to its data\n\t\t\t..................................................................*/\n\t\t\tif (send_entry != NULL) {\n\t\t\t\tentry_data = (CommHeaderType *)send_entry->Buffer;\n\n\t\t\t\t/*...............................................................\n\t\t\t\tIf ACK is for this entry, mark it\n\t\t\t\t...............................................................*/\n\t\t\t\tif (packet->PacketID==entry_data->PacketID &&\n\t\t\t\t\tentry_data->Code == PACKET_DATA_ACK) {\n\t\t\t\t\tsend_entry->IsACK = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn(1);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tHandle an incoming PACKET_DATA_NOACK packet\n\t------------------------------------------------------------------------*/\n\telse if (packet->Code == PACKET_DATA_NOACK) {\n\t\t/*.....................................................................\n\t\tIf there's only one slot left, don't tie up the queue with this packet\n\t\t.....................................................................*/\n\t\tif (Queue->Max_Receive() - Queue->Num_Receive() <= 1) {\n\t\t\treturn(0);\n\t\t}\n\n\t\t/*.....................................................................\n\t\tError if we can't queue the packet\n\t\t.....................................................................*/\n\t\tif (!Queue->Queue_Receive (buf, buflen, NULL, 0)) {\n\t\t\treturn(0);\n\t\t}\n\n\t\tNumRecNoAck++;\n\n\t\treturn(1);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tHandle an incoming PACKET_DATA_ACK packet\n\t------------------------------------------------------------------------*/\n\telse if (packet->Code == PACKET_DATA_ACK) {\n\t\t/*.....................................................................\n\t\tIf this is a packet requires an ACK, and it's ID is older than our\n\t\t\"oldest\" ID, we know it's a resend; send an ACK, but don't queue it\n\t\t.....................................................................*/\n\t\tif (packet->PacketID <= LastSeqID && LastSeqID != 0xffffffff) {\n\t\t\tsave_packet = 0;\n\t\t}\n\n\t\t/*.....................................................................\n\t\tOtherwise, scan the queue for this entry; if it's found, it's a\n\t\tresend, so don't save it.\n\t\t.....................................................................*/\n\t\telse {\n\t\t\tsave_packet = 1;\n\t\t\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\t\t\t\trec_entry = Queue->Get_Receive(i);\n\n\t\t\t\tif (rec_entry) {\n\n\t\t\t\t\tentry_data = (CommHeaderType *)rec_entry->Buffer;\n\n\t\t\t\t\t/*...........................................................\n\t\t\t\t\tPacket is found; it's a resend\n\t\t\t\t\t...........................................................*/\n\t\t\t\t\tif (entry_data->Code == PACKET_DATA_ACK &&\n\t\t\t\t\t\tentry_data->PacketID == packet->PacketID) {\n\t\t\t\t\t\tsave_packet = 0;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\t/* end of scan for resend */\n\n\t\t/*.....................................................................\n\t\tQueue the packet & update our LastSeqID value.\n\t\t.....................................................................*/\n\t\tif (save_packet) {\n\t\t\t/*..................................................................\n\t\t\tIf there's only one slot left, make sure we only put a packet in it\n\t\t\tif this packet will let us increment our LastSeqID; otherwise, we'll\n\t\t\tget stuck, forever unable to increment LastSeqID.\n\t\t\t..................................................................*/\n\t\t\tif (Queue->Max_Receive() - Queue->Num_Receive() <= 1) {\n\t\t\t\tif (packet->PacketID != (LastSeqID + 1) ) {\n\t\t\t\t\treturn(0);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tIf we can't queue the packet, return; don't send an ACK.\n\t\t\t..................................................................*/\n\t\t\tif (!Queue->Queue_Receive (buf, buflen, NULL, 0)) {\n\t\t\t\treturn(0);\n\t\t\t}\n\n\t\t\tNumRecAck++;\n\n\t\t\t/*..................................................................\n\t\t\tUpdate our LastSeqID value if we can.  Anything less than LastSeqID\n\t\t\twe'll know is a resend.\n\t\t\t..................................................................*/\n\t\t\tif (packet->PacketID == (LastSeqID + 1)) {\n\t\t\t\tLastSeqID = packet->PacketID;\n\t\t\t\t/*...............................................................\n\t\t\t\tNow that we have a new 'LastSeqID', search our Queue to see if\n\t\t\t\tthe next ID is there; if so, keep checking for the next one;\n\t\t\t\tbreak only when the next one isn't found.  This forces\n\t\t\t\tLastSeqID to be the largest possible value.\n\t\t\t\t...............................................................*/\n\t\t\t\tdo {\n\t\t\t\t\tfound = 0;\n\t\t\t\t\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\n\t\t\t\t\t\trec_entry = Queue->Get_Receive(i);\n\n\t\t\t\t\t\tif (rec_entry) {\n\t\t\t\t\t\t\tentry_data = (CommHeaderType *)rec_entry->Buffer;\n\n\t\t\t\t\t\t\t/*......................................................\n\t\t\t\t\t\t\tEntry is found\n\t\t\t\t\t\t\t......................................................*/\n\t\t\t\t\t\t\tif (entry_data->Code == PACKET_DATA_ACK &&\n\t\t\t\t\t\t\t\tentry_data->PacketID == (LastSeqID + 1)) {\n\n\t\t\t\t\t\t\t\tLastSeqID = entry_data->PacketID;\n\t\t\t\t\t\t\t\tfound = 1;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} while (found);\n\t\t\t}\n\t\t}\t/* end of save packet */\n\n\t\t/*.....................................................................\n\t\tSend an ACK, regardless of whether this was a resend or not.\n\t\t.....................................................................*/\n\t\tackpacket.MagicNumber = Magic_Num();\n\t\tackpacket.Code = PACKET_ACK;\n\t\tackpacket.PacketID = packet->PacketID;\n\t\tSend ((char *)&ackpacket, sizeof(CommHeaderType), NULL, 0);\n\n\t\treturn(1);\n\t}\n\n\treturn(0);\n\n}\t/* end of Receive_Packet */\n\n\n/***************************************************************************\n * ConnectionClass::Get_Packet -- gets a packet from receive queue\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tlocation to store buffer\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\tfilled in with length of 'buf'\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was read, 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Get_Packet (void * buf, int *buflen)\n{\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\tint packetlen;\t\t\t\t\t\t\t\t\t\t// size of received packet\n\tCommHeaderType *entry_data;\n\tint i;\n\n\t/*------------------------------------------------------------------------\n\tEnsure that we read the packets in order.  LastReadID is the ID of the\n\tlast PACKET_DATA_ACK packet we read.\n\t------------------------------------------------------------------------*/\n\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\n\t\trec_entry = Queue->Get_Receive(i);\n\n\t\t/*.....................................................................\n\t\tOnly read this entry if it hasn't been yet\n\t\t.....................................................................*/\n\t\tif (rec_entry && rec_entry->IsRead==0) {\n\n\t\t\tentry_data = (CommHeaderType *)rec_entry->Buffer;\n\n\t\t\t/*..................................................................\n\t\t\tIf this is a DATA_ACK packet, its ID must be one greater than\n\t\t\tthe last one we read.\n\t\t\t..................................................................*/\n\t\t\tif ( (entry_data->Code == PACKET_DATA_ACK) &&\n\t\t\t\t(entry_data->PacketID == (LastReadID + 1))) {\n\n\t\t\t\tLastReadID = entry_data->PacketID;\n\t\t\t\trec_entry->IsRead = 1;\n\n\t\t\t\tpacketlen = rec_entry->BufLen - sizeof(CommHeaderType);\n\t\t\t\tif (packetlen > 0) {\n\t\t\t\t\tmemcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType),\n\t\t\t\t\t\tpacketlen);\n\t\t\t\t}\n\t\t\t\t(*buflen) = packetlen;\n\t\t\t\treturn(1);\n\t\t\t}\n\t\t\t/*..................................................................\n\t\t\tIf this is a DATA_NOACK packet, who cares what the ID is?\n\t\t\t..................................................................*/\n\t\t\telse if (entry_data->Code == PACKET_DATA_NOACK) {\n\t\t\t\trec_entry->IsRead = 1;\n\n\t\t\t\tpacketlen = rec_entry->BufLen - sizeof(CommHeaderType);\n\t\t\t\tif (packetlen > 0) {\n\t\t\t\t\tmemcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType),\n\t\t\t\t\t\tpacketlen);\n\t\t\t\t}\n\t\t\t\t(*buflen) = packetlen;\n\t\t\t\treturn(1);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(0);\n\n}\t/* end of Get_Packet */\n\n\n/***************************************************************************\n * ConnectionClass::Service -- main polling routine; services packets\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error (connection is broken!)\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Service (void)\n{\n\t/*------------------------------------------------------------------------\n\tService the Send Queue:  This [re]sends packets in the Send Queue which\n\thaven't been ACK'd yet, and if their retry timeout has expired, and\n\tupdates the FirstTime, LastTime & SendCount values in the Queue entry.\n\tEntries that have been ACK'd should be removed.\n\n\tService the Receive Queue:  This sends ACKs for packets that haven't\n\tbeen ACK'd yet.  Entries that the app has read, and have been ACK'd,\n\tshould be removed.\n\t------------------------------------------------------------------------*/\n\tif ( Service_Send_Queue() && Service_Receive_Queue() ) {\n\t\treturn(1);\n\t}\n\telse {\n\t\treturn(0);\n\t}\n\n}\t/* end of Service */\n\n\n/***************************************************************************\n * ConnectionClass::Service_Send_Queue -- services the send queue\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Service_Send_Queue (void)\n{\n\tint i;\n\tint num_entries;\n\tSendQueueType *send_entry;\t\t\t\t\t\t// ptr to send queue entry\n\tCommHeaderType *packet_hdr;\t\t\t\t\t// packet header\n\tunsigned long curtime;\t\t\t\t\t\t\t// current time\n\tint bad_conn = 0;\n\n\t/*------------------------------------------------------------------------\n\tRemove any ACK'd packets from the queue\n\t------------------------------------------------------------------------*/\n\tfor (i = 0; i < Queue->Num_Send(); i++) {\n\t\t/*.....................................................................\n\t\tGet this queue entry\n\t\t.....................................................................*/\n\t\tsend_entry = Queue->Get_Send(i);\n\n\t\t/*.....................................................................\n\t\tIf ACK has been received, unqueue it\n\t\t.....................................................................*/\n\t\tif (send_entry->IsACK) {\n\n\t\t\t/*..................................................................\n\t\t\tUpdate this queue's response time\n\t\t\t..................................................................*/\n\t\t\tpacket_hdr = (CommHeaderType *)send_entry->Buffer;\n\t\t\tif (packet_hdr->Code == PACKET_DATA_ACK) {\n\t\t\t\tQueue->Add_Delay(Time() - send_entry->FirstTime);\n\t\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tUnqueue the packet\n\t\t\t..................................................................*/\n\t\t\tQueue->UnQueue_Send(NULL,NULL,i,NULL,NULL);\n\t\t\ti--;\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tLoop through all entries in the Send queue.  [Re]Send any entries that\n\tneed it.\n\t------------------------------------------------------------------------*/\n\tnum_entries = Queue->Num_Send();\n\n\tfor (i = 0; i < num_entries; i++) {\n\t\tsend_entry = Queue->Get_Send(i);\n\n\t\tif (send_entry->IsACK) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*.....................................................................\n\t\tOnly send the message if time has elapsed.  (The message's Time\n\t\tfields are init'd to 0 when a message is queue'd or unqueue'd, so the\n\t\tfirst time through, the delta time will appear large.)\n\t\t.....................................................................*/\n\t\tcurtime = Time();\n\t\tif (curtime - send_entry->LastTime > RetryDelta) {\n\n\t\t\t/*..................................................................\n\t\t\tSend the message\n\t\t\t..................................................................*/\n\t\t\tSend (send_entry->Buffer, send_entry->BufLen, send_entry->ExtraBuffer,\n\t\t\t\tsend_entry->ExtraLen);\n\n\t\t\t/*..................................................................\n\t\t\tFill in Time fields\n\t\t\t..................................................................*/\n\t\t\tsend_entry->LastTime = curtime;\n\t\t\tif (send_entry->SendCount==0) {\n\t\t\t\tsend_entry->FirstTime = curtime;\n\n\t\t\t\t/*...............................................................\n\t\t\t\tIf this is the 1st time we're sending this packet, and it doesn't\n\t\t\t\trequire an ACK, mark it as ACK'd; then, the next time through,\n\t\t\t\tit will just be removed from the queue.\n\t\t\t\t...............................................................*/\n\t\t\t\tpacket_hdr = (CommHeaderType *)send_entry->Buffer;\n\t\t\t\tif (packet_hdr->Code == PACKET_DATA_NOACK) {\n\t\t\t\t\tsend_entry->IsACK = 1;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tUpdate SendCount\n\t\t\t..................................................................*/\n\t\t\tsend_entry->SendCount++;\n\n\t\t\t/*..................................................................\n\t\t\tPerform error detection, based on either MaxRetries or Timeout\n\t\t\t..................................................................*/\n\t\t\tif (MaxRetries != -1 && send_entry->SendCount > MaxRetries) {\n\t\t\t\tbad_conn = 1;\n\t\t\t}\n\n\t\t\tif (Timeout != -1 &&\n\t\t\t\t(send_entry->LastTime - send_entry->FirstTime) > Timeout) {\n\t\t\t\tbad_conn = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tIf the connection is going bad, return an error\n\t------------------------------------------------------------------------*/\n\tif (bad_conn) {\n\t\treturn(0);\n\t}\n\telse {\n\t\treturn(1);\n\t}\n\n}\t/* end of Service_Send_Queue */\n\n\n/***************************************************************************\n * ConnectionClass::Service_Receive_Queue -- services receive queue\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Service_Receive_Queue (void)\n{\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\tCommHeaderType *packet_hdr;\t\t\t\t\t// packet header\n\tint i;\n\n\t/*------------------------------------------------------------------------\n\tRemove all dead packets.\n\tPACKET_DATA_NOACK: if it's been read, throw it away.\n\tPACKET_DATA_ACK: if it's been read, and its ID is older than LastSeqID,\n\tthrow it away.\n\t------------------------------------------------------------------------*/\n\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\t\trec_entry = Queue->Get_Receive(i);\n\n\t\tif (rec_entry->IsRead) {\n\t\t\tpacket_hdr = (CommHeaderType *)(rec_entry->Buffer);\n\n\t\t\tif (packet_hdr->Code == PACKET_DATA_NOACK) {\n\t\t\t\tQueue->UnQueue_Receive(NULL,NULL,i,NULL,NULL);\n\t\t\t\ti--;\n\n\t\t\t}\n\t\t\telse if (packet_hdr->PacketID < LastSeqID) {\n\t\t\t\tQueue->UnQueue_Receive(NULL,NULL,i,NULL,NULL);\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(1);\n\n}\t/* end of Service_Receive_Queue */\n\n\n/***************************************************************************\n * ConnectionClass::Time -- gets current time\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nunsigned long ConnectionClass::Time (void)\n{\n\tstatic struct timeb mytime;\t\t\t// DOS time\n\tunsigned long msec;\n\n#ifdef WWLIB32_H\n\n\t/*------------------------------------------------------------------------\n\tIf the Westwood timer system has been activated, use TickCount's value\n\t------------------------------------------------------------------------*/\n\tif (TimerSystemOn) {\n\t\treturn(TickCount);\t\t\t\t// Westwood Library time\n\t}\n\t/*------------------------------------------------------------------------\n\tOtherwise, use the DOS timer\n\t------------------------------------------------------------------------*/\n\telse {\n\t\tftime(&mytime);\n\t\tmsec = (unsigned long)mytime.time * 1000L + (unsigned long)mytime.millitm;\n\t\treturn((msec / 100) * 6);\n\t}\n\n#else\n\n\t/*------------------------------------------------------------------------\n\tIf the Westwood library isn't being used, use the DOS timer.\n\t------------------------------------------------------------------------*/\n\tftime(&mytime);\n\tmsec = (unsigned long)mytime.time * 1000L + (unsigned long)mytime.millitm;\n\treturn((msec / 100) * 6);\n\n#endif\n\n}\t/* end of Time */\n\n\n/***************************************************************************\n * ConnectionClass::Command_Name -- returns name for given packet command  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tcommand\t\tpacket Command value to get name for\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to command name, NULL if invalid\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/31/1995 BRR : Created.                                             *\n *=========================================================================*/\nchar *ConnectionClass::Command_Name(int command)\n{\n\tif (command >= 0 && command < PACKET_COUNT) {\n\t\treturn(Commands[command]);\n\t}\n\telse {\n\t\treturn(NULL);\n\t}\n\n}\t/* end of Command_Name */\n\n/************************** end of connect.cpp *****************************/\n"
  },
  {
    "path": "CODE/CONNECT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CONNECT.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : CONNECT.H                                *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 1, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * DESCRIPTION:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This class represents a single \"connection\" with another system.  It's\t*\n * a pure virtual base class that acts as a framework for other classes.\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This class contains a CommBufferClass member, which stores received\t\t*\n * & transmitted packets.  The ConnectionClass has virtual functions to\t\t*\n * handle adding packets to the queue, reading them from the queue,\t\t\t*\n * a Send routine for actually sending data, and a Receive_Packet function *\n * which is used to tell the connection that a new packet has come in.\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * The virtual Service routines handle all ACK & Retry logic for\t\t\t\t*\n * communicating between this system & another.  Thus, any class derived\t*\n * from this class may overload the basic ACK/Retry logic.\t\t\t\t\t\t*\n *                                                                         *\n * THE PACKET HEADER:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * The Connection Classes prefix every packet sent with a header that's\t\t*\n * local to this class.  The header contains a \"Magic Number\" which should\t*\n * be unique for each product, and Packet \"Code\", which will tell the\t\t*\n * receiving end if this is DATA, or an ACK packet, and a packet ID, which\t*\n * is a unique numerical ID for this packet (useful for detecting resends).*\n * The header is stored with each packet in the send & receive Queues; \t\t*\n * it's removed before it's passed back to the application, via\t\t\t\t*\n * Get_Packet()\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * THE CONNECTION MANAGER:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * It is assumed that there will be a \"Connection Manager\" class which \t\t*\n * will handle parsing incoming packets; it will then tell the connection\t*\n * that new packets have come in, and the connection will process them in\t*\n * whatever way it needs to for its protocol (check for resends, handle\t\t*\n * ACK packets, etc).  The job of the connection manager is to parse\t\t\t*\n * incoming packets & distribute them to the connections that need to\t\t*\n * store them (for multi-connection protocols).\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * NOTES ON ACK/RETRY:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This class provides a \"non-sequenced\" ACK/Retry approach to packet\t\t*\n * transmission.  It sends out as many packets as are in the queue, whose\t*\n * resend delta times have expired; and it ACK's any packets its received\t*\n * who haven't been ACK'd yet.  Thus, order of delivery is NOT guaranteed;\t*\n * but, the performance is better than a \"sequenced\" approach.  Also, the\t*\n * Packet ID scheme (see below) ensures that the application will read\t\t*\n * the packets in the proper order.  Thus, this class guarantees delivery\t*\n * and order of deliver.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Each packet has a unique numerical ID; the ID is set to a count of the\t*\n * number of packets sent.  Different count values are provided, for both \t*\n * DATA_ACK & DATA_NOACK packets.  This ensures that the counter can be \t*\n * used to detect resends of DATA_ACK packets; the counters for DATA_NOACK *\n * packets aren't currently used.  Other counters keep track of the \t\t\t*\n * last-sequentially-received packet ID (for DATA_ACK packets), so we\t\t*\n * can check for resends & missed packets, and the last-sequentially-read\t*\n * packet ID, so we can ensure the app reads the packets in order.\t\t\t*\n *                                                                         *\n * If the protocol being used already guarantees delivery of packets,\t\t*\n * no ACK is required for the packets.  In this case, the connection\t\t\t*\n * class for this protocol can overload the Service routine to avoid\t\t\t*\n * sending ACK packets, or the Connection Manager can just mark the\t\t\t*\n * packet as ACK'd when it adds it to the Receive Queue for the connection.*\n *                                                                         *\n *\tDerived classes must provide:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Init: Initialization of any hardware-specific values.\t\t\t\t\t\t*\n * - Send: a hardware-dependent send routine.\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef CONNECTION_H\n#define CONNECTION_H\n\n/*\n********************************* Includes **********************************\n*/\n#include \"combuf.h\"\n\n/*\n********************************** Defines **********************************\n*/\n#define CONN_DEBUG\t0\n/*---------------------------------------------------------------------------\nThis structure is the header prefixed to any packet sent by the application.\nMagicNumber:\tThis is a number unique to the application; it's up to the\n\t\t\t\t\tReceive_Packet routine to check this value, to be sure we're\n\t\t\t\t\tnot getting data from some other product.  This value should\n\t\t\t\t\tbe unique for each application.\nCode:\t\t\t\tThis will be one of the below-defined codes.\nPacketID:\t\tThis is a unique numerical ID for this packet.  The Connection\n\t\t\t\t\tsets this ID on all packets sent out.\n---------------------------------------------------------------------------*/\ntypedef struct {\n\tunsigned short MagicNumber;\n\tunsigned char Code;\n\tunsigned long PacketID;\n} CommHeaderType;\n\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass ConnectionClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*.....................................................................\n\t\tThese are the possible values for the Code field of the CommHeaderType:\n\t\t.....................................................................*/\n\t\tenum ConnectionEnum {\n\t\t\tPACKET_DATA_ACK,\t\t\t// this is a data packet requiring an ACK\n\t\t\tPACKET_DATA_NOACK,\t\t// this is a data packet not requiring an ACK\n\t\t\tPACKET_ACK,\t\t\t\t\t// this is an ACK for a packet\n\t\t\tPACKET_COUNT\t\t\t\t// for computational purposes\n\t\t};\n\n\t\t/*.....................................................................\n\t\tConstructor/destructor.\n\t\t.....................................................................*/\n\t\tConnectionClass (int numsend, int numrecieve, int maxlen,\n\t\t\tunsigned short magicnum, unsigned long retry_delta,\n\t\t\tunsigned long max_retries, unsigned long timeout, int extralen = 0);\n\t\tvirtual ~ConnectionClass ();\n\n\t\t/*.....................................................................\n\t\tInitialization.\n\t\t.....................................................................*/\n\t\tvirtual void Init (void);\n\n\t\t/*.....................................................................\n\t\tSend/Receive routines.\n\t\t.....................................................................*/\n\t\tvirtual int Send_Packet (void * buf, int buflen, int ack_req);\n\t\tvirtual int Receive_Packet (void * buf, int buflen);\n\t\tvirtual int Get_Packet (void * buf, int * buflen);\n\n\t\t/*.....................................................................\n\t\tThe main polling routine for the connection.  Should be called as often\n\t\tas possible.\n\t\t.....................................................................*/\n\t\tvirtual int Service (void);\n\n\t\t/*.....................................................................\n\t\tThis routine is used by the retry logic; returns the current time in\n\t\t60ths of a second.\n\t\t.....................................................................*/\n\t\tstatic unsigned long Time (void);\n\n\t\t/*.....................................................................\n\t\tUtility routines.\n\t\t.....................................................................*/\n\t\tunsigned short Magic_Num (void) { return (MagicNum); }\n\t\tunsigned long Retry_Delta (void) { return (RetryDelta); }\n\t\tvoid Set_Retry_Delta (unsigned long delta) { RetryDelta = delta;}\n\t\tunsigned long Max_Retries (void) { return (MaxRetries); }\n\t\tvoid Set_Max_Retries (unsigned long retries) { MaxRetries = retries;}\n\t\tunsigned long Time_Out (void) { return (Timeout); }\n\t\tvoid Set_TimeOut (unsigned long t) { Timeout = t;}\n\t\tunsigned long Max_Packet_Len (void) { return (MaxPacketLen); }\n\t\tstatic char * Command_Name(int command);\n\n\t\t/*.....................................................................\n\t\tThe packet \"queue\"; this non-sequenced version isn't really much of\n\t\ta queue, but more of a repository.\n\t\t.....................................................................*/\n\t\tCommBufferClass *Queue;\n\n\t/*\n\t-------------------------- Protected Interface ---------------------------\n\t*/\n\tprotected:\n\t\t/*.....................................................................\n\t\tRoutines to service the Send & Receive queues.\n\t\t.....................................................................*/\n\t\tvirtual int Service_Send_Queue(void);\n\t\tvirtual int Service_Receive_Queue(void);\n\n\t\t/*.....................................................................\n\t\tThis routine actually performs a hardware-dependent data send.  It's\n\t\tpure virtual, so it must be defined by a derived class.  The routine\n\t\tis protected; it's only called by the ACK/Retry logic, not the\n\t\tapplication.\n\t\t.....................................................................*/\n\t\tvirtual int Send(char *buf, int buflen, void *extrabuf,\n\t\t\tint extralen) = 0;\n\n\t\t/*.....................................................................\n\t\tThis is the maximum packet length, including our own internal header.\n\t\t.....................................................................*/\n\t\tint MaxPacketLen;\n\n\t\t/*.....................................................................\n\t\tPacket staging area; this is where the CommHeaderType gets tacked onto\n\t\tthe application's packet before it's sent.\n\t\t.....................................................................*/\n\t\tchar *PacketBuf;\n\n\t\t/*.....................................................................\n\t\tThis is the magic number assigned to this connection.  It is the first\n\t\tfew bytes of any transmission.\n\t\t.....................................................................*/\n\t\tunsigned short MagicNum;\n\n\t\t/*.....................................................................\n\t\tThis value determines the time delay before a packet is re-sent.\n\t\t.....................................................................*/\n\t\tunsigned long RetryDelta;\n\n\t\t/*.....................................................................\n\t\tThis is the maximum number of retries allowed for a packet; if this\n\t\tvalue is exceeded, the connection is probably broken.\n\t\t.....................................................................*/\n\t\tunsigned long MaxRetries;\n\n\t\t/*.....................................................................\n\t\tThis is the total timeout for this connection; if this time is exceeded\n\t\ton a packet, the connection is probably broken.\n\t\t.....................................................................*/\n\t\tunsigned long Timeout;\n\n\t\t/*.....................................................................\n\t\tRunning totals of # of packets we send & receive which require an ACK,\n\t\tand those that don't.\n\t\t.....................................................................*/\n\t\tunsigned long NumRecNoAck;\n\t\tunsigned long NumRecAck;\n\t\tunsigned long NumSendNoAck;\n\t\tunsigned long NumSendAck;\n\n\t\t/*.....................................................................\n\t\tThis is the ID of the last consecutively-received packet; anything older\n\t\tthan this, we know is a resend.  Anything newer than this MUST be lying\n\t\taround in the Queue for us to detect it as a resend.\n\t\t.....................................................................*/\n\t\tunsigned long LastSeqID;\n\n\t\t/*.....................................................................\n\t\tThis is the ID of the PACKET_DATA_ACK packet we read last; it ensures\n\t\tthat the application reads that type of packet in order.\n\t\t.....................................................................*/\n\t\tunsigned long LastReadID;\n\n\t\t/*.....................................................................\n\t\tNames of all packet commands\n\t\t.....................................................................*/\n\t\tstatic char * Commands[PACKET_COUNT];\n};\n\n#endif\n\n/**************************** end of connect.h *****************************/\n"
  },
  {
    "path": "CODE/CONNMGR.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CONNMGR.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : CONNMGR.H                                *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 3, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This is the Connection Manager base class.  This is an abstract base\t\t*\n * class that's just a shell for more functional derived classes.\t\t\t\t*\n * The main job of the Connection Manager classes is to parse a \"pool\" of\t*\n * incoming packets, which may be from different computers, and distribute\t*\n * those packets to Connection Classes via their Receive_Packet function.\t*\n *                                                                         *\n * This class should be the only access to the network/modem for the\t\t\t*\n * application, so if the app needs any functions to access the \t\t\t\t*\n * connections or the queue's, the derived versions of this class should\t*\n * provide them.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * It's up to the derived class to define:\t\t\t\t\t\t\t\t\t\t\t*\n * - Service:\t\tpolling routine; should Service each connection\t\t\t\t*\n * - Init:\t\t\tinitialization; should perform hardware-dependent\t\t\t*\n *\t\t\t\t\t\tinitialization, then Init each connection; this function\t*\n *   \t\t\t\t\tisn't defined in this class, since the parameters will \t*\n *\t\t\t\t\t\tbe highly protocol-dependent)\t\t\t\t\t\t\t\t\t\t*\n * - Send_Message:sends a packet across the connection (this function \t\t*\n * \t\t\t\t\tisn't defined in this class, since the parameters will \t*\n *\t\t\t\t\t\tbe highly protocol-dependent)\t\t\t\t\t\t\t\t\t\t*\n * - Get_Message:\tgets a message from the connection (this function \t\t\t*\n * \t\t\t\t\tisn't defined in this class, since the parameters will \t*\n *\t\t\t\t\t\tbe highly protocol-dependent)\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * If the derived class supports multiple connections, it should provide\t*\n * functions for creating the connections, associating them with a name\t\t*\n * or ID or both, destroying them, and sending data through all or any\t\t*\n * connection.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CONNMGR_H\n#define CONNMGR_H\n\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass ConnManClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*.....................................................................\n\t\tVarious useful enums:\n\t\t.....................................................................*/\n\t\tenum IPXConnTag {\n\t\t\tCONNECTION_NONE = -1\t\t\t// value of an invalid connection ID\n\t\t};\n\n\t\t/*.....................................................................\n\t\tConstructor/Destructor.  These currently do nothing.\n\t\t.....................................................................*/\n\t\tConnManClass (void) {};\n\t\tvirtual ~ConnManClass () {};\n\n\t\t/*.....................................................................\n\t\tThe Service routine:\n\t\t- Parses incoming packets, and adds them to the Receive Queue for the\n\t\t  Connection Class(s) for this protocol\n\t\t- Invokes each connection's Service routine; returns an error if the\n\t\t  connection's Service routine indicates an error.\n\t\t.....................................................................*/\n\t\tvirtual int Service (void) = 0;\n\n\t\t/*.....................................................................\n\t\tSending & receiving data\n\t\t.....................................................................*/\n\t\tvirtual int Send_Private_Message (void *buf, int buflen,\n\t\t\tint ack_req = 1, int conn_id = CONNECTION_NONE) = 0;\n\t\tvirtual int Get_Private_Message (void *buf, int *buflen,\n\t\t\tint *conn_id) = 0;\n\n\t\t/*.....................................................................\n\t\tConnection management\n\t\t.....................................................................*/\n\t\tvirtual int Num_Connections(void) = 0;\n\t\tvirtual int Connection_ID(int index) = 0;\n\t\tvirtual int Connection_Index(int id) = 0;\n\n\t\t/*.....................................................................\n\t\tQueue utility routines\n\t\t.....................................................................*/\n\t\tvirtual int Global_Num_Send(void) = 0;\n\t\tvirtual int Global_Num_Receive(void) = 0;\n\t\tvirtual int Private_Num_Send(int id = CONNECTION_NONE) = 0;\n\t\tvirtual int Private_Num_Receive(int id = CONNECTION_NONE) = 0;\n\n\t\t/*.....................................................................\n\t\tTiming management\n\t\t.....................................................................*/\n\t\tvirtual void Reset_Response_Time(void) = 0;\n\t\tvirtual unsigned long Response_Time(void) = 0;\n\t\tvirtual void Set_Timing (unsigned long retrydelta,\n\t\t\tunsigned long maxretries, unsigned long timeout) = 0;\n\n\t\t/*.....................................................................\n\t\tDebugging\n\t\t.....................................................................*/\n\t\tvirtual void Configure_Debug(int index, int type_offset, int type_size,\n\t\t\tchar **names, int namestart, int namecount) = 0;\n#ifdef CHEAT_KEYS\n\t\tvirtual void Mono_Debug_Print(int index, int refresh) = 0;\n#endif\n\n\t/*\n\t--------------------------- Private Interface ----------------------------\n\t*/\n\tprivate:\n\t\t/*.....................................................................\n\t\tThis abstract class contains no data members; but a derived class\n\t\twill contain:\n\t\t- An instance of one or more derived Connection Classes\n\t\t- A buffer to store incoming packets\n\t\t.....................................................................*/\n};\n\n#endif\n"
  },
  {
    "path": "CODE/CONQUER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CONQUER.CPP 6     3/13/97 2:05p Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CONQUER.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 3, 1991                                                *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CC_Draw_Shape -- Custom draw shape handler.                                               *\n *   Call_Back -- Main game maintenance callback routine.                                      *\n *   Color_Cycle -- Handle the general palette color cycling.                                  *\n *   Crate_From_Name -- Given a crate name convert it to a crate type.                         *\n *   Disk_Space_Available -- returns bytes of free disk space                                  *\n *   Do_Record_Playback -- handles saving/loading map pos & current object                     *\n *   Fading_Table_Name -- Builds a theater specific fading table name.                         *\n *   Fetch_Techno_Type -- Convert type and ID into TechnoTypeClass pointer.                    *\n *   Force_CD_Available -- Ensures that specified CD is available.                             *\n *   Get_Radar_Icon -- Builds and alloc a radar icon from a shape file                         *\n *   Handle_Team -- Processes team selection command.                                          *\n *   Handle_View -- Either records or restores the tactical view.                              *\n *   KN_To_Facing -- Converts a keyboard input number into a facing value.                     *\n *   Keyboard_Process -- Processes the tactical map input codes.                               *\n *   Language_Name -- Build filename for current language.                                     *\n *   List_Copy -- Makes a copy of a cell offset list.                                          *\n *   Main_Game -- Main game startup routine.                                                   *\n *   Main_Loop -- This is the main game loop (as a single loop).                               *\n *   Map_Edit_Loop -- a mini-main loop for map edit mode only                                  *\n *   Message_Input -- allows inter-player message input processing                             *\n *   MixFileHandler -- Handles VQ file access.                                                 *\n *   Name_From_Source -- retrieves the name for the given SourceType                           *\n *   Owner_From_Name -- Convert an owner name into a bitfield.                                 *\n *   Play_Movie -- Plays a VQ movie.                                                           *\n *   Shake_The_Screen -- Dispatcher that shakes the screen.                                    *\n *   Shape_Dimensions -- Determine the minimum rectangle for the shape.                        *\n *   Source_From_Name -- Converts ASCII name into SourceType.                                  *\n *   Sync_Delay -- Forces the game into a 15 FPS rate.                                         *\n *   Theater_From_Name -- Converts ASCII name into a theater number.                           *\n *   Unselect_All -- Causes all selected objects to become unselected.                         *\n *   VQ_Call_Back -- Maintenance callback used for VQ movies.                                  *\n *   Game_Registry_Key -- Returns pointer to string containing the registry subkey for the game.\n *   Is_Counterstrike_Installed -- Function to determine the availability of the CS expansion.\n *   Is_Aftermath_Installed -- Function to determine the availability of the AM expansion.\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifdef TESTCODE\nclass A {\n\tpublic:\n\t\tenum {VAR=1};\n};\n\ntemplate<class T>\nclass B {\n\tpublic:\n\t\tenum {VAR2=T::VAR};  // this is the line in question.\n};\n\nB<A> test;\n#endif\n\n\n\n#include\t\"function.h\"\n#ifdef WIN32\n#ifdef WINSOCK_IPX\n#include\t\"WSProto.h\"\n#else\t//WINSOCK_IPX\n#include\t\"tcpip.h\"\n#endif\t//WINSOCK_IPX\n#else\n#include\t\"fakesock.h\"\nTcpipManagerClass\tWinsock;\n#endif\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<string.h>\n#include\t<direct.h>\n#include\t<fcntl.h>\n#include\t<io.h>\n#include\t<dos.h>\n#include\t<share.h>\n#include\t\"ccdde.h\"\n#include\t\"vortex.h\"\n\n#ifdef WOLAPI_INTEGRATION\n//#include \"WolDebug.h\"\n#include \"WolStrng.h\"\n#include \"WolapiOb.h\"\nextern WolapiObject* pWolapi;\n#define PAGE_RESPOND_KEY\tKN_RETURN\t//KN_COMMA\n#endif\n\n#ifdef MPEGMOVIE\n#ifdef MCIMPEG\n#include \"mcimovie.h\"\n#endif\n#include \"movie.h\"\nMPG_RESPONSE far __stdcall MpegCallback(MPG_CMD cmd, LPVOID data, LPVOID user);\n#endif\n\n#define SHAPE_TRANS\t\t0x40\n\nvoid * Get_Shape_Header_Data(void * ptr);\nextern bool Spawn_WChat(bool can_launch);\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nvoid Enable_Secret_Units(void);\n#endif\n\nextern bool Is_Mission_Aftermath (char *file_name);\nextern bool Is_Mission_Counterstrike (char *file_name);\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\nextern void Do_Draw(void);\n#endif\n\n#ifdef CHEAT_KEYS\nbool\tbNoMovies = false;\n#endif\n\n/****************************************\n**\tFunction prototypes for this module **\n*****************************************/\nbool Main_Loop(void);\nvoid Keyboard_Process(KeyNumType & input);\nstatic void Message_Input(KeyNumType &input);\nstatic void Color_Cycle(void);\nbool Map_Edit_Loop(void);\n\nextern \"C\" {\n\tbool UseOldShapeDraw = false;\n}\n\n#ifdef CHEAT_KEYS\nvoid Dump_Heap_Pointers( void );\nvoid Error_In_Heap_Pointers( char * string );\n#endif\nstatic void Do_Record_Playback(void);\n\nvoid Toggle_Formation(void);\n\nextern \"C\" {\n\textern char * __nheapbeg;\n}\n\n//\n// Special module globals for recording and playback\n//\nchar TeamEvent = 0;\t\t\t// 0 = no event, 1,2,3 = team event type\nchar TeamNumber = 0;\t\t\t// which team was selected? (1-9)\nchar FormationEvent = 0;\t// 0 = no event, 1 = formation was toggled\n\n\n\t/* -----------------10/14/96 7:29PM------------------\n\n\t --------------------------------------------------*/\n\n#if(TEN)\nvoid TEN_Call_Back(void);\n#endif\t// TEN\n\n#if(MPATH)\nvoid MPATH_Call_Back(void);\n#endif\t// MPATH\n\n/***********************************************************************************************\n * Main_Game -- Main game startup routine.                                                     *\n *                                                                                             *\n *    This is the first official routine of the game. It handles game initialization and       *\n *    the main game loop control.                                                              *\n *                                                                                             *\n *    Initialization:                                                                          *\n *    - Init_Game handles one-time-only inits                                                  *\n *    - Select_Game is responsible for initializations required for each new game played       *\n *      (these may be different depending on whether a multiplayer game is selected, and       *\n *      other parameters)                                                                      *\n *    - This routine performs any un-inits required, both for each game played, and one-time   *\n *                                                                                             *\n * INPUT:   argc  -- Number of command line arguments (including program name itself).         *\n *                                                                                             *\n *          argv  -- Array of command line argument pointers.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Main_Game(int argc, char * argv[])\n{\n\tstatic bool fade = true;\n\n\t/*\n\t**\tPerform one-time-only initializations\n\t*/\n\tif (!Init_Game(argc, argv)) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tGame processing loop:\n\t**\t1) Select which game to play, or whether to exit (don't fade the palette\n\t**\t\ton the first game selection, but fade it in on subsequent calls)\n\t**\t2) Invoke either the main-loop routine, or the editor-loop routine,\n\t**\t\tuntil they indicate that the user wants to exit the scenario.\n\t*/\n\twhile (Select_Game(fade)) {\n\t\tfade = false;\n\t\tScenarioInit = 0;\t\t// Kludge.\n\n\t\tfade = true;\n\n\t\t/*\n\t\t** Initialise the color lookup tables for the chronal vortex\n\t\t*/\n\t\tChronalVortex.Stop();\n\t\tChronalVortex.Setup_Remap_Tables(Scen.Theater);\n\n\t\t/*\n\t\t**\tMake the game screen visible, clear the keyboard buffer of spurious\n\t\t**\tvalues, and then show the mouse.  This PRESUMES that Select_Game() has\n\t\t**\ttold the map to draw itself.\n\t\t*/\n\t\tGamePalette.Set(FADE_PALETTE_MEDIUM);\n\t\tKeyboard->Clear();\n\t\t/*\n\t\t** Only show the mouse if we're not playing back a recording.\n\t\t*/\n\t\tif (Session.Play) {\n\t\t\tHide_Mouse();\n\t\t\tTeamEvent = 0;\n\t\t\tTeamNumber = 0;\n\t\t\tFormationEvent = 0;\n\t\t} else {\n\t\t\tShow_Mouse();\n\t\t}\n\n#ifdef WIN32\n\t\tif (Session.Type == GAME_INTERNET) {\n\t\t\tRegister_Game_Start_Time();\n\t\t\tGameStatisticsPacketSent = false;\n\t\t\tPacketLater = NULL;\n\t\t\tConnectionLost = false;\n\t\t} else {\n#ifndef WOLAPI_INTEGRATION\n\t\t\tDDEServer.Disable();\n#endif\t//\t!WOLAPI_INTEGRATION\n\t\t}\n#endif\t//WIN32\n\n#ifdef SCENARIO_EDITOR\n\t\t/*\n\t\t**\tScenario-editor version of main-loop processing\n\t\t*/\n\t\tfor (;;) {\n\t\t\t/*\n\t\t\t**\tNon-scenario-editor-mode: call the game's main loop\n\t\t\t*/\n\t\t\tif (!Debug_Map) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tTimeQuake = PendingTimeQuake;\n\t\t\t\tPendingTimeQuake = false;\n#else\n\t\t\t\tTimeQuake = false;\n#endif\n\t\t\t\tif (Main_Loop()) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (SpecialDialog != SDLG_NONE) {\n\t\t\t\t\tswitch (SpecialDialog) {\n\t\t\t\t\t\tcase SDLG_SPECIAL:\n\t\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\t\tSpecial_Dialog();\n\t\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase SDLG_OPTIONS:\n\t\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\t\tOptions.Process();\n\t\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase SDLG_SURRENDER:\n\t\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\t\tif (Surrender_Dialog(TXT_SURRENDER)) {\n\t\t\t\t\t\t\t\tPlayerPtr->Flag_To_Lose();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tScenario-editor-mode: call the editor's main loop\n\t\t\t\t*/\n\t\t\t\tif (Map_Edit_Loop()) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#else\n\t\t/*\n\t\t**\tNon-editor version of main-loop processing\n\t\t*/\n\t\tfor (;;) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tTimeQuake = PendingTimeQuake;\n\t\t\tPendingTimeQuake = false;\n#else\n\t\t\tTimeQuake = false;\n#endif\n\t\t\t/*\n\t\t\t**\tCall the game's main loop\n\t\t\t*/\n\t\t\tif (Main_Loop()) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the SpecialDialog flag is set, invoke the given special dialog.\n\t\t\t**\tThis must be done outside the main loop, since the dialog will call\n\t\t\t**\tMain_Loop(), allowing the game to run in the background.\n\t\t\t*/\n\t\t\tif (SpecialDialog != SDLG_NONE) {\n\t\t\t\tswitch (SpecialDialog) {\n\t\t\t\t\tcase SDLG_SPECIAL:\n\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\tSpecial_Dialog();\n\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase SDLG_OPTIONS:\n\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\tOptions.Process();\n\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase SDLG_SURRENDER:\n\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\tif (Surrender_Dialog(TXT_SURRENDER)) {\n\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::DESTRUCT));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\tbreak;\n\n/*ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t\t\t\tcase SDLG_PROPOSE_DRAW:\n\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\tif (Surrender_Dialog(TXT_WOL_PROPOSE_DRAW)) {\n\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PROPOSE_DRAW));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase SDLG_ACCEPT_DRAW:\n\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\tif (Surrender_Dialog(TXT_WOL_ACCEPT_DRAW)) {\n\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::ACCEPT_DRAW));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\tbreak;\n#endif\n*/\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#endif\n\n\n#ifdef WIN32\n\t\t/*\n\t\t** Send the game stats to WChat if we haven't already done so\n\t\t*/\n\t\tif (!GameStatisticsPacketSent && PacketLater) {\n\t\t\tSend_Statistics_Packet();\t\t//\tAfter game sending if PacketLater set.\n\t\t}\n#endif\t//WIN32\n\n\t\t/*\n\t\t**\tScenario is done; fade palette to black\n\t\t*/\n\t\tBlackPalette.Set(FADE_PALETTE_SLOW);\n\t\tVisiblePage.Clear();\n\n\t\t/*\n\t\t**\tUn-initialize whatever needs it, for each game played.\n\t\t**\n\t\t**\tShut down either the modem or network; they'll get re-initialized if\n\t\t**\tthe user selections those options again in Select_Game().  This\n\t\t**\t\"re-boots\" the modem & network code, which I currently feel is safer\n\t\t**\tthan just letting it hang around.\n\t\t** (Skip this step if we're in playback mode; the modem or net won't have\n\t\t** been initialized in that case.)\n\t\t*/\n\t\tif (Session.Record || Session.Play) {\n\t\t\tSession.RecordFile.Close();\n\t\t}\n\n\t\tif (Session.Type == GAME_NULL_MODEM || Session.Type == GAME_MODEM) {\n\t\t\tif (!Session.Play) {\n\t\t\t\tModem_Signoff();\n\t\t\t}\n\t\t} else {\n\t\t\tif (Session.Type == GAME_IPX) {\n\t\t\t\tif (!Session.Play) {\n\t\t\t\t\tShutdown_Network();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n#if(TEN)\n\n\t\tif (Session.Type == GAME_TEN) {\n\t\t\tShutdown_TEN();\n\t\t\t//Prog_End();\n\t\t\tEmergency_Exit(0);\n\t\t}\n#endif\t// TEN\n\n#if(MPATH)\n\t\tif (Session.Type == GAME_MPATH) {\n\t\t\tShutdown_MPATH();\n\t\t\t//Prog_End();\n\t\t\tEmergency_Exit(0);\n\t\t}\n#endif\t// MPATH\n\n\t\t/*\n\t\t**\tIf we're playing back, the mouse will be hidden; show it.\n\t\t** Also, set all variables back to normal, to return to the main menu.\n\t\t*/\n\t\tif (Session.Play) {\n\t\t\tShow_Mouse();\n\t\t\tSession.Type = GAME_NORMAL;\n\t\t\tSession.Play = 0;\n\t\t}\n#ifndef WOLAPI_INTEGRATION\n#ifdef WIN32\n\t\tif (Special.IsFromWChat) {\n\t\t\tShutdown_Network();\t\t      // Clear up the pseudo IPX stuff\n#ifndef WINSOCK_IPX\n\t\t\tWinsock.Close();\n#endif\t//WINSOCK_IPX\n\t\t\tSpecial.IsFromWChat = false;\n\t\t\tSpawnedFromWChat = false;\n\t\t\tDDEServer.Delete_MPlayer_Game_Info();\t//Make sure we dont use the same start packet twice\n\t\t\tSession.Type = GAME_NORMAL;\t\t\t//Have to do this or we will got straight to the multiplayer menu\n\t\t\tSpawn_WChat(false);\t\t//Will switch back to Wchat. It must be there because its been poking us\n\t\t}\n#endif\t//WIN32\n#endif\t//\t!WOLAPI_INTEGRATION\n\t}\n\n\t/*\n\t**\tFree the scenario description buffers\n\t*/\n\tSession.Free_Scenario_Descriptions();\n}\n\n\n/***********************************************************************************************\n * Keyboard_Process -- Processes the tactical map input codes.                                 *\n *                                                                                             *\n *    This routine is used to process the input codes while the player                         *\n *    has the tactical map displayed. It handles all the keys that                             *\n *    are appropriate to that mode.                                                            *\n *                                                                                             *\n * INPUT:   input -- Input code as returned from Input_Num().                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/21/1992 JLB : Created.                                                                 *\n *   07/04/1995 JLB : Handles team and map control hotkeys.                                    *\n *=============================================================================================*/\nvoid Keyboard_Process(KeyNumType & input)\n{\n\tObjectClass * obj;\n\tint index;\n\n\t/*\n\t**\tDon't do anything if there is not keyboard event.\n\t*/\n\tif (input == KN_NONE) {\n\t\treturn;\n\t}\n\t/*\n\t**\tFor network & modem, process user input for inter-player messages.\n\t*/\n\tMessage_Input(input);\n\n#ifdef WIN32\n\t/*\n\t**\tThe VK_BIT must be stripped from the \"plain\" value of the key so that a comparison to\n\t**\tKN_1, for example, will yield TRUE if in fact the \"1\" key was pressed.\n\t*/\n\n\tKeyNumType plain = KeyNumType(input & ~(WWKEY_SHIFT_BIT|WWKEY_ALT_BIT|WWKEY_CTRL_BIT|WWKEY_VK_BIT));\n\tKeyNumType key = KeyNumType(input & ~WWKEY_VK_BIT);\n\n\n#else\n\tKeyNumType plain = KeyNumType(input & ~(KN_SHIFT_BIT|KN_ALT_BIT|KN_CTRL_BIT));\n\tKeyNumType key = plain;\n#endif\n\n#ifdef CHEAT_KEYS\n\n\tif (Debug_Flag) {\n\t\tHousesType h;\n\n\t\tswitch (int(input)) {\n\t\t\tcase int(int(KN_M) | int(KN_SHIFT_BIT)):\n\t\t\tcase int(int(KN_M) | int(KN_ALT_BIT)):\n\t\t\tcase int(int(KN_M) | int(KN_CTRL_BIT)):\n\t\t\t\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\t\t\t\tHouses.Ptr(h)->Refund_Money(10000);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n#endif\n\n#ifdef VIRGIN_CHEAT_KEYS\n\tif (Debug_Playtest && input == (KN_W|KN_ALT_BIT)) {\n\t\tPlayerPtr->Blockage = false;\n\t\tPlayerPtr->Flag_To_Win();\n\t}\n#endif\n\n#ifdef CHEAT_KEYS\n#ifdef WIN32\n\tif (Debug_Playtest && input == (KA_W|KN_ALT_BIT)) {\n#else\n\tif (Debug_Playtest && input == (KN_W|KN_ALT_BIT)) {\n#endif\n\t\tPlayerPtr->Blockage = false;\n\t\tPlayerPtr->Flag_To_Win();\n\t}\n\n\tif ((Debug_Flag || Debug_Playtest) && plain == KN_F4) {\n\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\tDebug_Unshroud = (Debug_Unshroud == false);\n\t\t\tMap.Flag_To_Redraw(true);\n\t\t}\n\t}\n\n\tif (Debug_Flag && input == KN_SLASH) {\n\t\tif (Session.Type != GAME_NORMAL) {\n\t\t\tSpecialDialog = SDLG_SPECIAL;\n\t\t\tinput = KN_NONE;\n\t\t} else {\n\t\t\tSpecial_Dialog();\n\t\t}\n\t}\n#endif\n\n\t/*\n\t**\tProcess prerecorded team selection. This will be an additive select\n\t**\tif the SHIFT key is held down. It will create the team if the\n\t**\tCTRL or ALT key is held down.\n\t*/\n\tint action = 0;\n#ifdef WIN32\n\tif (input & WWKEY_SHIFT_BIT) action = 1;\n\tif (input & WWKEY_ALT_BIT) action = 3;\n\tif (input & WWKEY_CTRL_BIT) action = 2;\n#else\n\tif (input & KN_SHIFT_BIT) action = 1;\n\tif (input & KN_ALT_BIT) action = 3;\n\tif (input & KN_CTRL_BIT) action = 2;\n#endif\n\n\t/*\n\t**\tIf the \"N\" key is pressed, then select the next object.\n\t*/\n\tif (key != 0 && key == Options.KeyNext) {\n\t\tif (action) {\n\t\t\tobj = Map.Prev_Object(CurrentObject.Count() ? CurrentObject[0] : NULL);\n\t\t} else {\n\t\t\tobj = Map.Next_Object(CurrentObject.Count() ? CurrentObject[0] : NULL);\n\t\t}\n\t\tif (obj != NULL) {\n\t\t\tUnselect_All();\n\t\t \tobj->Select();\n\t\t\tMap.Center_Map();\n\t\t\tMap.Flag_To_Redraw(true);\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\tif (key != 0 && key == Options.KeyPrevious) {\n\t\tif (action) {\n\t\t\tobj = Map.Next_Object(CurrentObject.Count() ? CurrentObject[0] : NULL);\n\t\t} else {\n\t\t\tobj = Map.Prev_Object(CurrentObject.Count() ? CurrentObject[0] : NULL);\n\t\t}\n\t\tif (obj != NULL) {\n\t\t\tUnselect_All();\n\t\t \tobj->Select();\n\t\t\tMap.Center_Map();\n\t\t\tMap.Flag_To_Redraw(true);\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\n\n\t/*\n\t**\tAll selected units will go into idle mode.\n\t*/\n\tif (key != 0 && key == Options.KeyStop) {\n\t\tif (CurrentObject.Count()) {\n\t\t\tfor (index = 0; index < CurrentObject.Count(); index++) {\n\t\t\t\tObjectClass const * tech = CurrentObject[index];\n\n\t\t\t\tif (tech != NULL && (tech->Can_Player_Move() || (tech->Can_Player_Fire() && tech->What_Am_I() != RTTI_BUILDING))) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::IDLE, TargetClass(tech)));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tAll selected units will attempt to go into guard area mode.\n\t*/\n\tif (key != 0 && key == Options.KeyGuard) {\n\t\tif (CurrentObject.Count()) {\n\t\t\tfor (index = 0; index < CurrentObject.Count(); index++) {\n\t\t\t\tObjectClass const * tech = CurrentObject[index];\n\n\t\t\t\tif (tech != NULL && tech->Can_Player_Move() && tech->Can_Player_Fire()) {\n\t\t\t\t\tOutList.Add(EventClass(TargetClass(tech), MISSION_GUARD_AREA));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tAll selected units will attempt to scatter.\n\t*/\n\tif (key != 0 && key == Options.KeyScatter) {\n\t\tif (CurrentObject.Count()) {\n\t\t\tfor (index = 0; index < CurrentObject.Count(); index++) {\n\t\t\t\tObjectClass const * tech = CurrentObject[index];\n\n\t\t\t\tif (tech != NULL && tech->Can_Player_Move()) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::SCATTER, TargetClass(tech)));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tCenter the map around the currently selected objects. If no\n\t**\tobjects are selected, then fall into the home case.\n\t*/\n\tif (key != 0 && (key == Options.KeyHome1 || key == Options.KeyHome2)) {\n\t\tif (CurrentObject.Count()) {\n\t\t\tMap.Center_Map();\n#ifdef WIN32\n\t\t\tMap.Flag_To_Redraw(true);\n#endif\n\t\t\tinput = KN_NONE;\n\t\t} else {\n\t\t\tinput = Options.KeyBase;\n\t\t}\n\t}\n\n\t/*\n\t**\tCenter the map about the construction yard or construction vehicle\n\t**\tif one is present.\n\t*/\n\tif (key != 0 && key == Options.KeyBase) {\n\t\tUnselect_All();\n\t\tif (PlayerPtr->CurBuildings) {\n\t\t\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\t\t\tBuildingClass * building = Buildings.Ptr(index);\n\n\t\t\t\tif (building != NULL && !building->IsInLimbo && building->House == PlayerPtr && *building == STRUCT_CONST) {\n\t\t\t\t\tUnselect_All();\n\t\t\t\t\tbuilding->Select();\n\t\t\t\t\tif (building->IsLeader) break;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (CurrentObject.Count() == 0 && PlayerPtr->CurUnits) {\n\t\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass * unit = Units.Ptr(index);\n\n\t\t\t\tif (unit != NULL && !unit->IsInLimbo && unit->House == PlayerPtr && *unit == UNIT_MCV) {\n\t\t\t\t\tUnselect_All();\n\t\t\t\t\tunit->Select();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (CurrentObject.Count()) {\n\t\t\tMap.Center_Map();\n\t\t} else {\n\t\t\tif (PlayerPtr->Center != 0) {\n\t\t\t\tMap.Center_Map(PlayerPtr->Center);\n\t\t\t}\n\t\t}\n\t\tMap.Flag_To_Redraw(true);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t** Toggle the status of formation for the current team\n\t*/\n\tif (key != 0 && key == Options.KeyFormation) {\n\t\tToggle_Formation();\n\t\tinput = KN_NONE;\n\t}\n\n#ifdef TOFIX\n\t/*\n\t** For multiplayer, 'R' pops up the surrender dialog.\n\t*/\n\tif (input != 0 && input == Options.KeyResign) {\n\t\tif (!PlayerLoses && /*Session.Type != GAME_NORMAL &&*/ !PlayerPtr->IsDefeated) {\n\t\t\tSpecialDialog = SDLG_SURRENDER;\n\t\t\tinput = KN_NONE;\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n#endif\n\n\t/*\n\t**\tHandle making and breaking alliances.\n\t*/\n\tif (key != 0 && key == Options.KeyAlliance) {\n\t\tif (Session.Type != GAME_NORMAL || Debug_Flag) {\n\t\t\tif (CurrentObject.Count() && !PlayerPtr->IsDefeated) {\n\t\t\t\tif (CurrentObject[0]->Owner() != PlayerPtr->Class->House) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::ALLY, CurrentObject[0]->Owner()));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tSelect all the units on the current display. This is equivalent to\n\t**\tdrag selecting the whole view.\n\t*/\n\tif (key != 0 && key == Options.KeySelectView) {\n\t\tMap.Select_These(0x00000000, XY_Coord(Map.TacLeptonWidth, Map.TacLeptonHeight));\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tToggles the repair state similarly to pressing the repair button.\n\t*/\n\tif (key != 0 && key == Options.KeyRepair) {\n\t\tMap.Repair_Mode_Control(-1);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tToggles the sell state similarly to pressing the sell button.\n\t*/\n\tif (key != 0 && key == Options.KeySell) {\n\t\tMap.Sell_Mode_Control(-1);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tToggles the map zoom mode similarly to pressing the map button.\n\t*/\n\tif (key != 0 && key == Options.KeyMap) {\n\t\tMap.Zoom_Mode_Control();\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tScrolls the sidebar up one slot.\n\t*/\n\tif (key != 0 && key == Options.KeySidebarUp) {\n\t\tMap.SidebarClass::Scroll(true, -1);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tScrolls the sidebar down one slot.\n\t*/\n\tif (key != 0 && key == Options.KeySidebarDown) {\n\t\tMap.SidebarClass::Scroll(false, -1);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tBrings up the options dialog box.\n\t*/\n\tif (key != 0 && (key == Options.KeyOption1 || key == Options.KeyOption2)) {\n\t\tMap.Help_Text(TXT_NONE);\t\t\t// Turns off help text.\n\t\tQueue_Options();\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tScrolls the tactical map in the direction specified.\n\t*/\n\tint distance = CELL_LEPTON_W;\n\tif (key != 0 && key == Options.KeyScrollLeft) {\n\t\tMap.Scroll_Map(DIR_W, distance, true);\n\t\tinput = KN_NONE;\n\t}\n\tif (key != 0 && key == Options.KeyScrollRight) {\n\t\tMap.Scroll_Map(DIR_E, distance, true);\n\t\tinput = KN_NONE;\n\t}\n\tif (key != 0 && key == Options.KeyScrollUp) {\n\t\tMap.Scroll_Map(DIR_N, distance, true);\n\t\tinput = KN_NONE;\n\t}\n\tif (key != 0 && key == Options.KeyScrollDown) {\n\t\tMap.Scroll_Map(DIR_S, distance, true);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tTeams are handled by the 10 special team keys. The manual comparison\n\t**\tto the KN numbers is because the Windows keyboard driver can vary\n\t**\tthe base code number for the key depending on the shift or alt key\n\t**\tstate!\n\t*/\n\tif (input != 0 && (plain == Options.KeyTeam1 || plain == KN_1)) {\n\t\tHandle_Team(0, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam2 || plain == KN_2)) {\n\t\tHandle_Team(1, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam3 || plain == KN_3)) {\n\t\tHandle_Team(2, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam4 || plain == KN_4)) {\n\t\tHandle_Team(3, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam5 || plain == KN_5)) {\n\t\tHandle_Team(4, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam6 || plain == KN_6)) {\n\t\tHandle_Team(5, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam7 || plain == KN_7)) {\n\t\tHandle_Team(6, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam8 || plain == KN_8)) {\n\t\tHandle_Team(7, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam9 || plain == KN_9)) {\n\t\tHandle_Team(8, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam10 || plain == KN_0)) {\n\t\tHandle_Team(9, action);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tHandle the bookmark hotkeys.\n\t*/\n\tif (input != 0 && plain == Options.KeyBookmark1 && !Debug_Map) {\n\t\tHandle_View(0, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && plain == Options.KeyBookmark2 && !Debug_Map) {\n\t\tHandle_View(1, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && plain == Options.KeyBookmark3 && !Debug_Map) {\n\t\tHandle_View(2, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && plain == Options.KeyBookmark4 && !Debug_Map) {\n\t\tHandle_View(3, action);\n\t\tinput = KN_NONE;\n\t}\n\n#ifdef CHEAT_KEYS\n\tif (input != 0 && Debug_Flag && input && (input & KN_RLSE_BIT) == 0) {\n\t\tDebug_Key(input);\n\t}\n#endif\n}\n\n\nvoid Toggle_Formation(void) {\n\tint team = -1;\n\tlong minx = 0x7FFFFFFFL, miny = 0x7FFFFFFFL;\n\tlong maxx = 0, maxy = 0;\n\tint index;\n\tbool setform = 0;\n\n\t//\n\t// Recording support\n\t//\n\tif (Session.Record) {\n\t\tFormationEvent = 1;\n\t}\n\n\t/*\n\t** Find the first selected object that is a member of a team, and\n\t** register his group as the team we're using.  Once we find the team\n\t** number, update the 'setform' flag to know whether we should be setting\n\t** the formation's offsets, or clearing them.  If they currently have\n\t** illegal offsets (as in 0x80000000), then we're setting.\n\t*/\n\tfor (index = 0; index < Units.Count(); index++) {\n\t\tUnitClass * obj = Units.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->IsSelected) {\n\t\t\tteam = obj->Group;\n\t\t\tif (team != -1) {\n\t\t\t\tsetform = obj->XFormOffset == (int)0x80000000;\n\t\t\t\tTeamSpeed[team] = SPEED_WHEEL;\n\t\t\t\tTeamMaxSpeed[team] = MPH_LIGHT_SPEED;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tif (team == -1) {\n\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->IsSelected) {\n\t\t\t\tteam = obj->Group;\n\t\t\t\tif (team != -1) {\n\t\t\t\t\tsetform = obj->XFormOffset == (int)0x80000000;\n\t\t\t\t\tTeamSpeed[team] = SPEED_WHEEL;\n\t\t\t\t\tTeamMaxSpeed[team] = MPH_LIGHT_SPEED;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (team == -1) {\n\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->IsSelected) {\n\t\t\t\tteam = obj->Group;\n\t\t\t\tif (team != -1) {\n\t\t\t\t\tsetform = obj->XFormOffset == 0x80000000UL;\n\t\t\t\t\tTeamSpeed[team] = SPEED_WHEEL;\n\t\t\t\t\tTeamMaxSpeed[team] = MPH_LIGHT_SPEED;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (team == -1) return;\n\t/*\n\t** Now that we have a team, let's go set (or clear) the formation offsets.\n\t*/\n\tfor (index = 0; index < Units.Count(); index++) {\n\t\tUnitClass * obj = Units.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team) {\n\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\tif (setform) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\tif (obj->Class->MaxSpeed < TeamMaxSpeed[team]) {\n\t\t\t\t\tTeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t\tTeamSpeed[team] = obj->Class->Speed;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tobj->XFormOffset = obj->YFormOffset = (int)0x80000000;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team) {\n\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\tif (setform) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\tif (obj->Class->MaxSpeed < TeamMaxSpeed[team]) {\n\t\t\t\t\tTeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tobj->XFormOffset = obj->YFormOffset = (int)0x80000000;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team) {\n\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\tif (setform) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\tif (obj->Class->MaxSpeed < TeamMaxSpeed[team]) {\n\t\t\t\t\tTeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tobj->XFormOffset = obj->YFormOffset = 0x80000000UL;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** All the units have been counted to find the bounding rectangle and\n\t** center of the formation, or to clear their offsets.  Now, if we're to\n\t** set them into formation, proceed to do so.  Otherwise, bail.\n\t*/\n\tif (setform) {\n\t\tint centerx = (int)((maxx - minx)/2)+minx;\n\t\tint centery = (int)((maxy - miny)/2)+miny;\n\n\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\tobj->YFormOffset = yc - centery;\n\t\t\t}\n\t\t}\n\n\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team ) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\tobj->YFormOffset = yc - centery;\n\t\t\t}\n\t\t}\n\n\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team ) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\tobj->YFormOffset = yc - centery;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Message_Input -- allows inter-player message input processing                               *\n *                                                                                             *\n * INPUT:                                                                                      *\n *\t\tinput\t\tkey value\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\n#pragma off (unreferenced)\nstatic void Message_Input(KeyNumType &input)\n{\n\tint rc;\n\tchar txt[MAX_MESSAGE_LENGTH+32];\n\tint id;\n\tSerialPacketType * serial_packet;\n\tint i;\n\tKeyNumType copy_input;\n\t//char *msg;\n\n\t/*\n\t**\tCheck keyboard input for a request to send a message.\n\t**\tThe 'to' argument for Add_Edit is prefixed to the message buffer; the\n\t**\tmessage buffer is big enough for the 'to' field plus MAX_MESSAGE_LENGTH.\n\t**\tTo send the message, calling Get_Edit_Buf retrieves the buffer minus the\n\t**\t'to' portion.  At the other end, the buffer allocated to display the\n\t**\tmessage must be MAX_MESSAGE_LENGTH plus the size of \"From: xxx (house)\".\n\t*/\n#ifdef WOLAPI_INTEGRATION\n\tif (Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH && \n\t\t( ( input >= KN_F1 && input < (KN_F1 + Session.MaxPlayers) ) || input == PAGE_RESPOND_KEY ) && \n\t\t!Session.Messages.Is_Edit()) {\n#else\n\tif (Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH && input >= KN_F1 && input < (KN_F1 + Session.MaxPlayers) && !Session.Messages.Is_Edit()) {\n#endif\n\t\tmemset (txt, 0, 40);\n\n\t\t/*\n\t\t**\tFor a serial game, send a message on F1 or F4; set 'txt' to the\n\t\t**\t\"Message:\" string & add an editable message to the list.\n\t\t*/\n\t\tif (Session.Type==GAME_NULL_MODEM || Session.Type==GAME_MODEM) {\n\t\t\tif (input==KN_F1 || input==(KN_F1 + Session.MaxPlayers - 1)) {\n\n\t\t\t\tstrcpy(txt, Text_String(TXT_MESSAGE));\t// \"Message:\"\n\n\t\t\t\tSession.Messages.Add_Edit (Session.ColorIdx,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\tMap.Flag_To_Redraw(false);\n\t\t\t}\n\t\t} else if ((Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) && !Session.Messages.Is_Edit()) {\n\t\t/*\n\t\t**\tFor a network game:\n\t\t**\tF1-F7 = \"To <name> (house):\" (only allowed if we're not in ObiWan mode)\n\t\t**\tF8 = \"To All:\"\n\t\t*/\n\t\t\tif (input==(KN_F1 + Session.MaxPlayers - 1)) {\n\n\t\t\t\tSession.MessageAddress = IPXAddressClass();\t\t// set to broadcast\n\t\t\t\tstrcpy(txt, Text_String(TXT_TO_ALL));\t// \"To All:\"\n\n\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\tMap.Flag_To_Redraw(false);\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\t} else if ((input - KN_F1) < Ipx.Num_Connections() && !Session.ObiWan && input != PAGE_RESPOND_KEY ) {\n#else\n\t\t\t} else if ((input - KN_F1) < Ipx.Num_Connections() && !Session.ObiWan) {\n#endif\n\t\t\t\tid = Ipx.Connection_ID(input - KN_F1);\n\t\t\t\tSession.MessageAddress = (*(Ipx.Connection_Address (id)));\n\t\t\t\tsprintf(txt, Text_String(TXT_TO), Ipx.Connection_Name(id));\n\n\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\tMap.Flag_To_Redraw(false);\n\t\t\t}\n#ifdef WOLAPI_INTEGRATION\n\t\t\telse if( Session.Type == GAME_INTERNET && pWolapi && !pWolapi->bConnectionDown && input == PAGE_RESPOND_KEY )\n\t\t\t{\n\t\t\t\tif( *pWolapi->szExternalPager )\n\t\t\t\t{\n\t\t\t\t\t//\tRespond to a page from external ww online user that paged me.\n\t\t\t\t\t//\tSet MessageAddress to all zeroes, as a flag to ourselves later on.\n\t\t\t\t\tNetNumType blip;\n\t\t\t\t\tNetNodeType blop;\n\t\t\t\t\tmemset( blip, 0, 4 );\n\t\t\t\t\tmemset( blop, 0, 6 );\n\t\t\t\t\tSession.MessageAddress = IPXAddressClass( blip, blop );\n\n\t\t\t\t\t//\tTell pWolapi not to reset szExternalPager for the time being.\n\t\t\t\t\tpWolapi->bFreezeExternalPager = true;\n\n\t\t\t\t\tsprintf( txt, Text_String( TXT_TO ), pWolapi->szExternalPager );\n\n\t\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx,\n\t\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\t\tMap.Flag_To_Redraw(false);\n\n\t\t\t\t\tKeyboard->Clear();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tSession.Messages.Add_Message( NULL, 0, TXT_WOL_NOTPAGED, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );\n\t\t\t\t\tSound_Effect( VOC_SYS_ERROR );\n\t\t\t\t}\n\t\t\t}\n#endif\n\t\t}\n#if(TEN)\n\t\t/*\n\t\t**\tFor a TEN game:\n\t\t**\tF1-F7 = \"To <name> (house):\" (only allowed if we're not in ObiWan mode)\n\t\t**\tF8 = \"To All:\"\n\t\t*/\n\t\telse if (Session.Type == GAME_TEN && !Session.Messages.Is_Edit()) {\n\t\t\tif (input==(KN_F1 + Session.MaxPlayers - 1)) {\n\n\t\t\t\tSession.TenMessageAddress = -1;\t\t// set to broadcast\n\t\t\t\tstrcpy(txt,Text_String(TXT_TO_ALL));\t// \"To All:\"\n\n\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\tMap.Flag_To_Redraw(false);\n\n\t\t\t}  else if ((input - KN_F1) < Ten->Num_Connections() && !Session.ObiWan) {\n\n\t\t\t\tid = Ten->Connection_ID(input - KN_F1);\n\t\t\t\tSession.TenMessageAddress = Ten->Connection_Address(id);\n\t\t\t\tsprintf(txt,Text_String(TXT_TO),Ten->Connection_Name(id));\n\n\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\tMap.Flag_To_Redraw(false);\n\t\t\t}\n\t\t}\n#endif\t// TEN\n#if(MPATH)\n\t\t/*\n\t\t**\tFor a MPATH game:\n\t\t**\tF1-F7 = \"To <name> (house):\" (only allowed if we're not in ObiWan mode)\n\t\t**\tF8 = \"To All:\"\n\t\t*/\n\t\telse if (Session.Type == GAME_MPATH && !Session.Messages.Is_Edit()) {\n\t\t\tif (input==(KN_F1 + Session.MaxPlayers - 1)) {\n\n\t\t\t\tSession.MPathMessageAddress = 0;\t\t\t// set to broadcast\n\t\t\t\tstrcpy(txt,Text_String(TXT_TO_ALL));\t// \"To All:\"\n\n\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\tMap.Flag_To_Redraw(false);\n\n\t\t\t}  else if ((input - KN_F1) < MPath->Num_Connections() && !Session.ObiWan) {\n\n\t\t\t\tid = MPath->Connection_ID(input - KN_F1);\n\t\t\t\tSession.MPathMessageAddress = MPath->Connection_Address(id);\n\t\t\t\tsprintf(txt,Text_String(TXT_TO),MPath->Connection_Name(id));\n\n\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\tMap.Flag_To_Redraw(false);\n\t\t\t}\n\t\t}\n#endif\t// MPATH\n\t}\n\n\t/*\n\t**\tProcess message-system input; send the message out if RETURN is hit.\n\t*/\n\tcopy_input = input;\n\trc = Session.Messages.Input(input);\n\n\t/*\n\t**\tIf a single character has been added to an edit buffer, update the display.\n\t*/\n\tif (rc == 1 && Session.Type != GAME_NORMAL) {\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n\t/*\n\t**\tIf backspace was hit, redraw the map.  If the edit message was removed,\n\t** the map must be force-drawn, since it won't be able to compute the\n\t** cells to redraw; otherwise, let the map compute the cells to redraw,\n\t** by not force-drawing it, but just setting the IsToRedraw bit.\n\t*/\n\tif (rc==2 && Session.Type != GAME_NORMAL) {\n\t\tif (copy_input==KN_ESC) {\n\t\t\tMap.Flag_To_Redraw(true);\n#ifdef WOLAPI_INTEGRATION\n\t\t\tif( pWolapi )\n\t\t\t\t//\tJust in case user was responding to a page from outside the game, and we had frozen the \"szExternalPager\".\n\t\t\t\tpWolapi->bFreezeExternalPager = false;\n#endif\n\t\t} else {\n\t\t\tMap.Flag_To_Redraw(false);\n\t\t}\n\t\tMap.DisplayClass::IsToRedraw = true;\n\t}\n\n\t/*\n\t**\tSend a message\n\t*/\n\tif ((rc==3 || rc==4) && Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH) {\n\t\t/*\n\t\t**\tSerial game: fill in a SerialPacketType & send it.\n\t\t**\t(Note: The size of the SerialPacketType.Command must be the same as\n\t\t**\tthe EventClass.Type!)\n\t\t*/\n\t\tif (Session.Type==GAME_NULL_MODEM || Session.Type==GAME_MODEM) {\n\t\t\tserial_packet = (SerialPacketType *)NullModem.BuildBuf;\n\n\t\t\tserial_packet->Command = SERIAL_MESSAGE;\n\t\t\tstrcpy (serial_packet->Name, Session.Players[0]->Name);\n\t\t\tserial_packet->ID = Session.ColorIdx;\n\n\t\t\tif (rc==3) {\n\t\t\t\tstrcpy (serial_packet->Message.Message, Session.Messages.Get_Edit_Buf());\n\t\t\t} else {\n\t\t\t\tstrcpy (serial_packet->Message.Message, Session.Messages.Get_Overflow_Buf());\n\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Send the message, and store this message in our LastMessage\n\t\t\t** buffer; the computer may send us a version of it later.\n\t\t\t*/\n\t\t\tNullModem.Send_Message(NullModem.BuildBuf,\n\t\t\t\tsizeof(SerialPacketType), 1);\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tchar *ptr = &serial_packet->Message.Message[0];\n\tif (!strncmp(ptr,\"SECRET UNITS ON \",15) && NewUnitsEnabled) {\n\t\tEnable_Secret_Units();\n\t}\n#endif\n\t\t\tstrcpy(Session.LastMessage, serial_packet->Message.Message);\n\t\t} else if (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) {\n#ifdef WOLAPI_INTEGRATION\n\t\t\tNetNumType blip;\n\t\t\tNetNodeType blop;\n\t\t\tSession.MessageAddress.Get_Address( blip, blop );\n\t\t\tif(\tblip[0] + blip[1] + blip[2] + blip[3] + blop[0] + blop[1] + blop[2] + blop[3] + blop[4] + blop[5] == 0 )\n\t\t\t{\n\t\t\t\t//\tThis message is a response to the last person that paged me.\n\t\t\t\tif( pWolapi && !pWolapi->bConnectionDown )\t\t//\t(As connection may have gone down.)\n\t\t\t\t{\n\t\t\t\t\tpWolapi->Page( pWolapi->szExternalPager, Session.Messages.Get_Edit_Buf(), false );\n\t\t\t\t\tpWolapi->bFreezeExternalPager = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n#endif\n\t\t\t{\n\n\t\t\t/*\n\t\t\t**\tNetwork game: fill in a GlobalPacketType & send it.\n\t\t\t*/\n\t\t\t\tSession.GPacket.Command = NET_MESSAGE;\n\t\t\t\tstrcpy (Session.GPacket.Name, Session.Players[0]->Name);\n\t\t\t\tSession.GPacket.Message.Color = Session.ColorIdx;\n\t\t\t\tSession.GPacket.Message.NameCRC = Compute_Name_CRC(Session.GameName);\n\n\t\t\t\tif (rc==3) {\n\t\t\t\t\tstrcpy (Session.GPacket.Message.Buf, Session.Messages.Get_Edit_Buf());\n\t\t\t\t} else {\n\t\t\t\t\tstrcpy (Session.GPacket.Message.Buf,\n\t\t\t\t\t\tSession.Messages.Get_Overflow_Buf());\n\t\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf 'F4' was hit, MessageAddress will be a broadcast address; send\n\t\t\t\t**\tthe message to every player we have a connection with.\n\t\t\t\t*/\n\t\t\t\tif (Session.MessageAddress.Is_Broadcast()) {\n\t#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tchar *ptr = &Session.GPacket.Message.Buf[0];\n\t\tif (!strncmp(ptr,\"SECRET UNITS ON \",15) && NewUnitsEnabled) {\n\t\t\t*ptr = 'X';\t\t// force it to an odd hack so we know it was broadcast.\n\t\t\tEnable_Secret_Units();\n\t\t}\n\t#endif\n\t\t\t\t\tfor (i = 0; i < Ipx.Num_Connections(); i++) {\n\t\t\t\t\t\tIpx.Send_Global_Message(&Session.GPacket,\n\t\t\t\t\t\t\tsizeof(GlobalPacketType), 1,\n\t\t\t\t\t\t\tIpx.Connection_Address(Ipx.Connection_ID(i)));\n\t\t\t\t\t\tIpx.Service();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tOtherwise, MessageAddress contains the exact address to send to.\n\t\t\t\t\t**\tSend to that address only.\n\t\t\t\t\t*/\n\t\t\t\t\tIpx.Send_Global_Message(&Session.GPacket,\n\t\t\t\t\t\tsizeof(GlobalPacketType), 1,\n\t\t\t\t\t\t&Session.MessageAddress);\n\t\t\t\t\tIpx.Service();\n\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tStore this message in our LastMessage buffer; the computer may send\n\t\t\t\t**\tus a version of it later.\n\t\t\t\t*/\n\t\t\t\tstrcpy(Session.LastMessage, Session.GPacket.Message.Buf);\n\t\t\t}\n\t\t}\n\n#if(TEN)\n\t\t/*\n\t\t**\tTEN game: fill in a GlobalPacketType & send it.\n\t\t*/\n\t\telse if (Session.Type == GAME_TEN) {\n\t\t\tSession.GPacket.Command = NET_MESSAGE;\n\t\t\tstrcpy (Session.GPacket.Name, Session.Players[0]->Name);\n\t\t\tSession.GPacket.Message.Color = Session.ColorIdx;\n\t\t\tSession.GPacket.Message.NameCRC = Compute_Name_CRC(Session.GameName);\n\n\t\t\tif (rc==3) {\n\t\t\t\tstrcpy (Session.GPacket.Message.Buf, Session.Messages.Get_Edit_Buf());\n\t\t\t} else {\n\t\t\t\tstrcpy (Session.GPacket.Message.Buf,\n\t\t\t\t\tSession.Messages.Get_Overflow_Buf());\n\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t}\n\n\t\t\tTen->Send_Global_Message(&Session.GPacket, sizeof(GlobalPacketType),\n\t\t\t\t1, Session.TenMessageAddress);\n\t\t}\n#endif\t// TEN\n\n#if(MPATH)\n\t\t/*\n\t\t**\tMPATH game: fill in a GlobalPacketType & send it.\n\t\t*/\n\t\telse if (Session.Type == GAME_MPATH) {\n\t\t\tSession.GPacket.Command = NET_MESSAGE;\n\t\t\tstrcpy (Session.GPacket.Name, Session.Players[0]->Name);\n\t\t\tSession.GPacket.Message.Color = Session.ColorIdx;\n\t\t\tSession.GPacket.Message.NameCRC = Compute_Name_CRC(Session.GameName);\n\n\t\t\tif (rc==3) {\n\t\t\t\tstrcpy (Session.GPacket.Message.Buf, Session.Messages.Get_Edit_Buf());\n\t\t\t} else {\n\t\t\t\tstrcpy (Session.GPacket.Message.Buf,\n\t\t\t\t\tSession.Messages.Get_Overflow_Buf());\n\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t}\n\n\t\t\tMPath->Send_Global_Message(&Session.GPacket, sizeof(GlobalPacketType),\n\t\t\t\t1, Session.MPathMessageAddress);\n\t\t}\n#endif\t// MPATH\n\n\t\t/*\n\t\t**\tTell the map to completely update itself, since a message is now missing.\n\t\t*/\n\t\tMap.Flag_To_Redraw(true);\n\t}\n}\n#pragma on (unreferenced)\n\n\n/***********************************************************************************************\n * Color_Cycle -- Handle the general palette color cycling.                                    *\n *                                                                                             *\n *    This is a maintenance routine that handles the color cycling. It should be called as     *\n *    often as necessary to achieve smooth color cycling effects -- at least 8 times a second. *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   06/10/1994 JLB : Uses new cycle color values.                                             *\n *   12/21/1994 JLB : Handles text fade color.                                                 *\n *   07/16/1996 JLB : Faster pulsing of white color.                                           *\n *=============================================================================================*/\nvoid Color_Cycle(void)\n{\n\tstatic CDTimerClass<SystemTimerClass> _timer;\n\tstatic CDTimerClass<SystemTimerClass> _ftimer;\n\tstatic bool _up = false;\n\tstatic int val = 255;\n\tbool changed = false;\n\n\tif (Options.IsPaletteScroll) {\n\t\t/*\n\t\t**\tProcess the fading white color. It is used for the radar box and other glowing\n\t\t**\tgame interface elements.\n\t\t*/\n\t\tif (!_ftimer) {\n\t\t\t_ftimer = TIMER_SECOND/6;\n\n\t\t\t#define\tSTEP_RATE\t20\n\t\t\tif (_up) {\n\t\t\t\tval += STEP_RATE;\n\t\t\t\tif (val > 150) {\n\t\t\t\t\tval = 150;\n\t\t\t\t\t_up = false;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tval -= STEP_RATE;\n\t\t\t\tif (val < 0x20) {\n\t\t\t\t\tval = 0x20;\n\t\t\t\t\t_up = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSet the pulse color as the proportional value between white and the\n\t\t\t**\tminimum value for pulsing.\n\t\t\t*/\n\t\t\tInGamePalette[CC_PULSE_COLOR] = GamePalette[WHITE];\n\t\t\tInGamePalette[CC_PULSE_COLOR].Adjust(val, BlackColor);\n\n\t\t\t/*\n\t\t\t**\tPulse the glowing embers between medium and dark red.\n\t\t\t*/\n\t\t\tInGamePalette[CC_EMBER_COLOR] = RGBClass(255, 80, 80);\n\t\t\tInGamePalette[CC_EMBER_COLOR].Adjust(val, BlackColor);\n\n\t\t\tchanged = true;\n\t\t}\n\n\t\t/*\n\t\t**\tProcess the color cycling effects -- water.\n\t\t*/\n\t\tif (!_timer) {\n\t\t\t_timer = TIMER_SECOND/4;\n\n\t\t\tRGBClass first = InGamePalette[CYCLE_COLOR_START+CYCLE_COLOR_COUNT-1];\n\t\t\tfor (int index = CYCLE_COLOR_START+CYCLE_COLOR_COUNT-1; index >= CYCLE_COLOR_START; index--) {\n\t\t\t\tInGamePalette[index] = InGamePalette[index-1];\n\t\t\t}\n\t\t\tInGamePalette[CYCLE_COLOR_START] = first;\n\n\t\t\tchanged = true;\n\t\t}\n\n\t\t/*\n\t\t**\tIf any of the processing functions changed the palette, then this palette must be\n\t\t**\tpassed to the system.\n\t\t*/\n\t\tif (changed) {\n\t\t\tBStart(BENCH_PALETTE);\n\t\t\tInGamePalette.Set();\n//\t\t\tSet_Palette(InGamePalette);\n\t\t\tBEnd(BENCH_PALETTE);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Call_Back -- Main game maintenance callback routine.                                        *\n *                                                                                             *\n *    This routine handles all the \"real time\" processing that needs to                        *\n *    occur. This includes palette fading and sound updating. It needs                         *\n *    to be called as often as possible.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Call_Back(void)\n{\n\t/*\n\t**\tMusic and speech maintenance\n\t*/\n\tif (SampleType) {\n\t\tSound_Callback();\n\t\tTheme.AI();\n\t\tSpeak_AI();\n\t}\n\n\t/*\n\t**\tNetwork maintenance.\n\t*/\n\tif (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) {\n\t\tIPX_Call_Back();\n\t}\n\n\t/*\n\t**\tSerial game maintenance.\n\t*/\n\tif (Session.Type == GAME_NULL_MODEM || ((Session.Type == GAME_MODEM) && Session.ModemService)) {\n\t\tNullModem.Service();\n\t}\n\n#ifdef WOLAPI_INTEGRATION\n\t//\tWolapi maintenance.\n\tif( pWolapi )\n\t{\n\t\tif( pWolapi->bInGame )\n\t\t{\n\t\t\tif( !pWolapi->bConnectionDown && ::timeGetTime() > pWolapi->dwTimeNextWolapiPump )\n\t\t\t{\n\t\t\t\tpWolapi->pChat->PumpMessages();\n\t\t\t\tpWolapi->pNetUtil->PumpMessages();\n\t\t\t\tpWolapi->dwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT + 700;\t\t//\tSlower pump during games.\n\t\t\t\tif( pWolapi->bConnectionDown )\n\t\t\t\t{\n\t\t\t\t\t//\tConnection to server lost.\n\t\t\t\t\tSession.Messages.Add_Message( NULL, 0, TXT_WOL_WOLAPIGONE, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );\n\t\t\t\t\tSound_Effect( WOLSOUND_LOGOUT );\n//\tajw (Wolapi object is now left around, so we can try to send game results.)\n//\t\t\t\t\t//\tKill wolapi.\n//\t\t\t\t\tpWolapi->UnsetupCOMStuff();\n//\t\t\t\t\tdelete pWolapi;\n//\t\t\t\t\tpWolapi = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//\tWhen showing a modal dialog during chat, this pumping is turned on. It's turned off immediately following.\n\t\t\tif( pWolapi->bPump_In_Call_Back && ( ::timeGetTime() > pWolapi->dwTimeNextWolapiPump ) )\n\t\t\t{\n\t\t\t\tpWolapi->pChat->PumpMessages();\n\t\t\t\tpWolapi->pNetUtil->PumpMessages();\n\t\t\t\tpWolapi->dwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT;\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n#if(TEN)\n\tif (Session.Type == GAME_TEN) {\n\t\tTEN_Call_Back();\n\t}\n#endif\t// TEN\n\n#if(MPATH)\n\tif (Session.Type == GAME_MPATH) {\n\t\tMPATH_Call_Back();\n\t}\n#endif\t// MPATH\n}\n\n\nvoid IPX_Call_Back(void)\n{\n\tIpx.Service();\n\n\t/*\n\t** Read packets only if the game is \"closed\", so we don't steal global\n\t** messages from the connection dialogs.\n\t*/\n\tif (!Session.NetOpen) {\n\t\tif (Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen, &Session.GAddress, &Session.GProductID)) {\n\n\t\t\tif (Session.GProductID == IPXGlobalConnClass::COMMAND_AND_CONQUER0) {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this is another player signing off, remove the connection &\n\t\t\t\t**\tmark that player's house as non-human, so the computer will take\n\t\t\t\t**\tit over.\n\t\t\t\t*/\n\t\t\t\tif (Session.GPacket.Command == NET_SIGN_OFF) {\n\t\t\t\t\tfor (int i = 0; i < Ipx.Num_Connections(); i++) {\n\n\t\t\t\t\t\tint id = Ipx.Connection_ID(i);\n\n\t\t\t\t\t\tif (Session.GAddress == (*Ipx.Connection_Address(id))) {\n\t\t\t\t\t\t\tDestroy_Connection(id, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tProcess a message from another user.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Session.GPacket.Command == NET_MESSAGE) {\n\t\t\t\t\t\tbool msg_ok = false;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** If NetProtect is set, make sure this message came from within\n\t\t\t\t\t\t** this game.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (!Session.NetProtect) {\n\t\t\t\t\t\t\tmsg_ok = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (Session.GPacket.Message.NameCRC ==\n\t\t\t\t\t\t\t\tCompute_Name_CRC(Session.GameName)) {\n\t\t\t\t\t\t\t\tmsg_ok = true;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tmsg_ok = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (msg_ok) {\n\t\t\t\t\t\t\tif (!Session.Messages.Concat_Message(Session.GPacket.Name,\n\t\t\t\t\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\t\t\t\t\tSession.GPacket.Message.Buf, Rule.MessageDelay * TICKS_PER_MINUTE)) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (NewUnitsEnabled && !strncmp(Session.GPacket.Message.Buf,\"XECRET UNITS ON \",15)) {\n\t\tSession.GPacket.Message.Buf[0]='S';\n\t\tEnable_Secret_Units();\n\t}\n#endif\n\t\t\t\t\t\t\t\tSession.Messages.Add_Message (Session.GPacket.Name,\n\t\t\t\t\t\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\t\t\t\t\t\tSession.GPacket.Message.Buf,\n\t\t\t\t\t\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\t\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL |\n\t\t\t\t\t\t\t\t\tTPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\n\t\t\t\t\t\t\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tTell the map to do a partial update (just to force the messages\n\t\t\t\t\t\t\t**\tto redraw).\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tMap.Flag_To_Redraw(true);\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tSave this message in our last-message buffer\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tstrcpy(Session.LastMessage, Session.GPacket.Message.Buf);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tProcess_Global_Packet(&Session.GPacket, &Session.GAddress);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n}\n\n\n#if(TEN)\nvoid TEN_Call_Back(void)\n{\n\tint id;\n\n\tTen->Service();\n\n\tif (Ten->Get_Global_Message (&Session.GPacket, &Session.GPacketlen,\n\t\t&Session.TenAddress)) {\n\n\t\t//\n\t\t//\tIf this is another player signing off, remove the connection &\n\t\t//\tmark that player's house as non-human, so the computer will take\n\t\t//\tit over.\n\t\t//\n\t\tif (Session.GPacket.Command == NET_SIGN_OFF) {\n\t\t\tfor (int i = 0; i < Ten->Num_Connections(); i++) {\n\n\t\t\t\tid = Ten->Connection_ID(i);\n\n\t\t\t\tif (Session.TenAddress == Ten->Connection_Address(id)) {\n\t\t\t\t\tDestroy_TEN_Connection(id, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t//\tProcess a message from another user.\n\t\t//\n\t\telse if (Session.GPacket.Command == NET_MESSAGE) {\n\t\t\tif (!Session.Messages.Concat_Message(Session.GPacket.Name,\n\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\tSession.GPacket.Message.Buf, Rule.MessageDelay * TICKS_PER_MINUTE)) {\n\n\t\t\t\tSession.Messages.Add_Message (Session.GPacket.Name,\n\t\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\t\tSession.GPacket.Message.Buf,\n\t\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL |\n\t\t\t\t\tTPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\n\t\t\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\n\t\t\t\t/*\n\t\t\t\t**\tTell the map to do a partial update (just to force the messages\n\t\t\t\t**\tto redraw).\n\t\t\t\t*/\n\t\t\t\tMap.Flag_To_Redraw(true);\n\n\t\t\t\t/*\n\t\t\t\t**\tSave this message in our last-message buffer\n\t\t\t\t*/\n\t\t\t\tstrcpy(Session.LastMessage, Session.GPacket.Message.Buf);\n\t\t\t}\n\t\t}\n\t}\n}\n#endif\t// TEN\n\n\n#if(MPATH)\nvoid MPATH_Call_Back(void)\n{\n\tint id;\n\n\tMPath->Service();\n\n\tif (MPath->Get_Global_Message (&Session.GPacket, &Session.GPacketlen,\n\t\t&Session.MPathAddress)) {\n\n\t\t//\n\t\t//\tIf this is another player signing off, remove the connection &\n\t\t//\tmark that player's house as non-human, so the computer will take\n\t\t//\tit over.\n\t\t//\n\t\tif (Session.GPacket.Command == NET_SIGN_OFF) {\n\t\t\tfor (int i = 0; i < MPath->Num_Connections(); i++) {\n\n\t\t\t\tid = MPath->Connection_ID(i);\n\n\t\t\t\tif (Session.MPathAddress == MPath->Connection_Address(id)) {\n\t\t\t\t\tDestroy_MPATH_Connection(id, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t//\tProcess a message from another user.\n\t\t//\n\t\telse if (Session.GPacket.Command == NET_MESSAGE) {\n\t\t\tif (!Session.Messages.Concat_Message(Session.GPacket.Name,\n\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\tSession.GPacket.Message.Buf, Rule.MessageDelay * TICKS_PER_MINUTE)) {\n\n\t\t\t\tSession.Messages.Add_Message (Session.GPacket.Name,\n\t\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\t\tSession.GPacket.Message.Buf,\n\t\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL |\n\t\t\t\t\tTPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\n\t\t\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\n\t\t\t\t/*\n\t\t\t\t**\tTell the map to do a partial update (just to force the messages\n\t\t\t\t**\tto redraw).\n\t\t\t\t*/\n\t\t\t\tMap.Flag_To_Redraw(true);\n\n\t\t\t\t/*\n\t\t\t\t**\tSave this message in our last-message buffer\n\t\t\t\t*/\n\t\t\t\tstrcpy(Session.LastMessage, Session.GPacket.Message.Buf);\n\t\t\t}\n\t\t}\n\t}\n}\n#endif\t// MPATH\n\n\n/***********************************************************************************************\n * Language_Name -- Build filename for current language.                                       *\n *                                                                                             *\n *    This routine attaches a language specific suffix to the base                             *\n *    filename provided. Typical use of this is when loading language                          *\n *    specific files at game initialization time.                                              *\n *                                                                                             *\n * INPUT:   basename -- Base name to append language specific                                  *\n *                      extension to.                                                          *\n *                                                                                             *\n * OUTPUT:  Returns with pointer to completed filename.                                        *\n *                                                                                             *\n * WARNINGS:   The return pointer value is valid only until the next time                      *\n *             this routine is called.                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * Language_Name(char const * basename)\n{\n\tstatic char _fullname[_MAX_FNAME+_MAX_EXT];\n\n\tif (!basename) return(NULL);\n\n\tsprintf(_fullname, \"%s.ENG\", basename);\n\treturn(_fullname);\n}\n\n\n/***********************************************************************************************\n * Source_From_Name -- Converts ASCII name into SourceType.                                    *\n *                                                                                             *\n *    This routine is used to convert an ASCII name representing a                             *\n *    SourceType into the actual SourceType value. Typically, this is                          *\n *    used when processing the scenario INI file.                                              *\n *                                                                                             *\n * INPUT:   name  -- The ASCII source name to process.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the SourceType represented by the name                                *\n *          specified.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nSourceType Source_From_Name(char const * name)\n{\n\tif (name) {\n\t\tfor (SourceType source = SOURCE_FIRST; source < SOURCE_COUNT; source++) {\n\t\t\tif (stricmp(SourceName[source], name) == 0) {\n\t\t\t\treturn(source);\n\t\t\t}\n\t\t}\n\t}\n\treturn(SOURCE_NONE);\n}\n\n\n/***********************************************************************************************\n * Name_From_Source -- retrieves the name for the given SourceType         \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tsource\t\tSourceType to get the name for\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\tname of SourceType\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   11/15/1994 BR : Created.                                              \t\t\t\t\t\t  *\n *=============================================================================================*/\nchar const * Name_From_Source(SourceType source)\n{\n\tif ((unsigned)source < SOURCE_COUNT) {\n\t\treturn(SourceName[source]);\n\t}\n\treturn(\"None\");\n}\n\n\n/***********************************************************************************************\n * Theater_From_Name -- Converts ASCII name into a theater number.                             *\n *                                                                                             *\n *    This routine converts an ASCII representation of a theater and converts it into a        *\n *    matching theater number. If no match was found, then THEATER_NONE is returned.           *\n *                                                                                             *\n * INPUT:   name  -- Pointer to ASCII name to convert.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the name converted into a theater number.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTheaterType Theater_From_Name(char const * name)\n{\n\tTheaterType\tindex;\n\n\tif (name) {\n\t\tfor (index = THEATER_FIRST; index < THEATER_COUNT; index++) {\n\t\t\tif (stricmp(name, Theaters[index].Name) == 0) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t}\n\t}\n\treturn(THEATER_NONE);\n}\n\n\n/***********************************************************************************************\n * KN_To_Facing -- Converts a keyboard input number into a facing value.                       *\n *                                                                                             *\n *    This routine determine which compass direction is represented by the keyboard value      *\n *    provided. It is used for map scrolling and other directional control operations from     *\n *    the keyboard.                                                                            *\n *                                                                                             *\n * INPUT:   input -- The KN number to convert.                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the facing type that the keyboard number represents. If it could      *\n *          not be translated, then FACING_NONE is returned.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nFacingType KN_To_Facing(int input)\n{\n\tinput &= ~(KN_ALT_BIT|KN_SHIFT_BIT|KN_CTRL_BIT);\n\tswitch (input) {\n\t\tcase KN_LEFT:\n\t\t\treturn(FACING_W);\n\n\t\tcase KN_RIGHT:\n\t\t\treturn(FACING_E);\n\n\t\tcase KN_UP:\n\t\t\treturn(FACING_N);\n\n\t\tcase KN_DOWN:\n\t\t\treturn(FACING_S);\n\n\t\tcase KN_UPLEFT:\n\t\t\treturn(FACING_NW);\n\n\t\tcase KN_UPRIGHT:\n\t\t\treturn(FACING_NE);\n\n\t\tcase KN_DOWNLEFT:\n\t\t\treturn(FACING_SW);\n\n\t\tcase KN_DOWNRIGHT:\n\t\t\treturn(FACING_SE);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(FACING_NONE);\n}\n\n\n/***********************************************************************************************\n * Sync_Delay -- Forces the game into a 15 FPS rate.                                           *\n *                                                                                             *\n *    This routine will wait until the timer for the current frame has expired before          *\n *    returning. It is called at the end of every game loop in order to force the game loop    *\n *    to run at a fixed rate.                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine will delay an amount of time according to the game speed setting.  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/04/1995 JLB : Created.                                                                 *\n *   03/06/1995 JLB : Fixed.                                                                   *\n *=============================================================================================*/\nstatic void Sync_Delay(void)\n{\n\t/*\n\t**\tAccumulate the number of 'spare' ticks that are frittered away here.\n\t*/\n\tSpareTicks += FrameTimer;\n\n\t/*\n\t**\tDelay until the frame timer expires. This forces the game loop to be regulated to a\n\t**\tspeed controlled by the game options slider.\n\t*/\n\twhile (FrameTimer) {\n\t\tColor_Cycle();\n\t\tCall_Back();\n\n\t\tif (SpecialDialog == SDLG_NONE) {\n#ifdef WIN32\n\t\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#endif\t//WIN32\n\t\t\tKeyNumType input = KN_NONE;\n\t\t\tint x, y;\n\t\t\tMap.Input(input, x, y);\n\t\t\tif (input) {\n\t\t\t\tKeyboard_Process(input);\n\t\t\t}\n\t\t\tMap.Render();\n\t\t}\n\t}\n\tColor_Cycle();\n\tCall_Back();\n}\n\n\n/***********************************************************************************************\n * Main_Loop -- This is the main game loop (as a single loop).                                 *\n *                                                                                             *\n *    This function will perform one game loop.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Should the game end?                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef WIN32\nextern void Check_For_Focus_Loss(void);\nvoid Reallocate_Big_Shape_Buffer(void);\n#endif\t//WIN32\n\n\nbool Main_Loop()\n{\n\tKeyNumType\tinput;\t\t\t\t\t// Player input.\n\tint x;\n\tint y;\n\tint framedelay;\n\nMono_Set_Cursor(0,0);\n\n\tif (!GameActive) return(!GameActive);\n\n#ifdef WIN32\n\t/*\n\t** Call the focus loss handler\n\t*/\n\tCheck_For_Focus_Loss();\n\n\t/*\n\t** Allocate extra memory for uncompressed shapes as needed\n\t*/\n\tReallocate_Big_Shape_Buffer();\n#endif\n\n\t/*\n\t** Sync-bug trapping code\n\t*/\n\tif (Frame >= Session.TrapFrame) {\n\t\tSession.Trap_Object();\n\t}\n\n\t//\n\t// Initialize our AI processing timer\n\t//\n\tSession.ProcessTimer = TickCount;\n\n#if 1\n\tif (Session.TrapCheckHeap) {\n\t\tDebug_Trap_Check_Heap = true;\n\t}\n#endif\n\n#ifdef CHEAT_KEYS\n\n\t/*\n\t**\tUpdate the running status debug display.\n\t*/\n\tSelf_Regulate();\n#endif\n\n\tBStart(BENCH_GAME_FRAME);\n\n\t/*\n\t**\tIf there is no theme playing, but it looks like one is required, then start one\n\t**\tplaying. This is usually the symptom of there being no transition score.\n\t*/\n\tif (SampleType && Theme.What_Is_Playing() == THEME_NONE) {\n\t\tTheme.Queue_Song(THEME_PICK_ANOTHER);\n\t}\n\n\t/*\n\t**\tSetup the timer so that the Main_Loop function processes at the correct rate.\n\t*/\n\tif (Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH &&\n\t\tSession.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\n\t\t//\n\t\t// In playback mode, run as fast as possible.\n\t\t//\n\t\tif (Session.Play) {\n\t\t\tFrameTimer = 0;\n\t\t} else {\n#ifdef FIXIT_VERSION_3\n\t\t\tif( !Session.DesiredFrameRate )\n\t\t\t\tSession.DesiredFrameRate = 60;\t\t//\tA division by zero was happening (very rare).\n#endif\n\t\t\tframedelay = TIMER_SECOND / Session.DesiredFrameRate;\n\t\t\tFrameTimer = framedelay;\n\t\t}\n\t} else {\n\t\tif (Options.GameSpeed != 0) {\n\t\t\tFrameTimer = Options.GameSpeed +\n\t\t\t\t(PlayerPtr->Difficulty == DIFF_EASY ? 1 : 0) -\n\t\t\t\t(PlayerPtr->Difficulty == DIFF_HARD ? 1 : 0);\n\t\t} else {\n\t\t\tFrameTimer = Options.GameSpeed + (PlayerPtr->Difficulty == DIFF_EASY ? 1 : 0);\n\t\t}\n\t}\n\n\t/*\n\t**\tUpdate the display, unless we're inside a dialog.\n\t*/\n\tif (!Session.Play) {\n#ifdef WIN32\n\t\tif (SpecialDialog == SDLG_NONE && GameInFocus) {\n\t\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#else\n\t\tif (SpecialDialog == SDLG_NONE) {\n#endif\n\t\t\tMap.Input(input, x, y);\n\t\t\tif (input) {\n\t\t\t\tKeyboard_Process(input);\n\t\t\t}\n\t\t\tMap.Render();\n\t\t}\n\t}\n\n\t/*\n\t** Save map's position & selected objects, if we're recording the game.\n\t*/\n\tif (Session.Record || Session.Play) {\n\t\tDo_Record_Playback();\n\t}\n\n#ifndef SORTDRAW\n\t/*\n\t** Sort the map's ground layer by y-coordinate value.  This is done\n\t** outside the IsToRedraw check, for the purposes of game sync'ing\n\t** between machines; this way, all machines will sort the Map's\n\t** layer in the same way, and any processing done that's based on\n\t** the order of this layer will remain in sync.\n\t*/\n\tDisplayClass::Layer[LAYER_GROUND].Sort();\n#endif\n\n\t/*\n\t**\tAI logic operations are performed here.\n\t*/\n\tLogic.AI();\n\tTimeQuake = false;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (!PendingTimeQuake) {\n\t\tTimeQuakeCenter = 0;\n\t}\n#endif\n\n\t/*\n\t**\tManage the inter-player message list.  If Manage() returns true, it means\n\t**\ta message has expired & been removed, and the entire map must be updated.\n\t*/\n\tif (Session.Messages.Manage()) {\n#ifdef WIN32\n\t\tHiddenPage.Clear();\n#else\t//WIN32\n\t\tHidPage.Clear();\n#endif\t//WIN32\n\t\tMap.Flag_To_Redraw(true);\n\t}\n\n\t//\n\t// Measure how long it took to process the AI\n\t//\n\tSession.ProcessTicks += (TickCount - Session.ProcessTimer);\n\tSession.ProcessFrames++;\n\n\t/*\n\t**\tProcess all commands that are ready to be processed.\n\t*/\n\tQueue_AI();\n\n\t/*\n\t**\tKeep track of elapsed time in the game.\n\t*/\n\tScore.ElapsedTime += TIMER_SECOND / TICKS_PER_SECOND;\n\n\tCall_Back();\n\n\t/*\n\t**\tCheck for player wins or loses according to global event flag.\n\t*/\n\tif (PlayerWins) {\n\n#ifdef WIN32\n\n\t\t/*\n\t\t** Send the game statistics to WChat.\n\t\t*/\n\t\tif (Session.Type == GAME_INTERNET && !GameStatisticsPacketSent) {\n\t\t\tRegister_Game_End_Time();\n\t\t\tSend_Statistics_Packet();\t\t//\tPlayer just won.\n\t\t}\n\n\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#endif\t//WIN32\n\t\tPlayerLoses = false;\n\t\tPlayerWins = false;\n\t\tPlayerRestarts = false;\n\t\tMap.Help_Text(TXT_NONE);\n\t\tDo_Win();\n\t\treturn(!GameActive);\n\t}\n\tif (PlayerLoses) {\n#ifdef WIN32\n\t\t/*\n\t\t** Send the game statistics to WChat.\n\t\t*/\n\t\tif (Session.Type == GAME_INTERNET && !GameStatisticsPacketSent) {\n\t\t\tRegister_Game_End_Time();\n\t\t\tSend_Statistics_Packet();\t\t//\tPlayer just lost.\n\t\t}\n\n\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#endif\t//WIN32\n\t\tPlayerWins = false;\n\t\tPlayerLoses = false;\n\t\tPlayerRestarts = false;\n\t\tMap.Help_Text(TXT_NONE);\n\t\tDo_Lose();\n\t\treturn(!GameActive);\n\t}\n\tif (PlayerRestarts) {\n#ifdef WIN32\n\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#endif\t//WIN32\n\t\tPlayerWins = false;\n\t\tPlayerLoses = false;\n\t\tPlayerRestarts = false;\n\t\tMap.Help_Text(TXT_NONE);\n\t\tDo_Restart();\n\t\treturn(!GameActive);\n\t}\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\tif( Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH && Session.Players.Count() == 2 &&\n\t\tScen.bLocalProposesDraw && Scen.bOtherProposesDraw )\n\t{\n\t\t//\tEnd game in a draw.\n\t\tif (Session.Type == GAME_INTERNET && !GameStatisticsPacketSent) {\n\t\t\tRegister_Game_End_Time();\n\t\t\tSend_Statistics_Packet();\n\t\t}\n\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n\t\tMap.Help_Text(TXT_NONE);\n\t\tDo_Draw();\n\t\treturn(!GameActive);\n\t}\n#endif\n\n\t/*\n\t**\tThe frame logic has been completed. Increment the frame\n\t**\tcounter.\n\t*/\n\tFrame++;\n\n\t/*\n\t** Is there a memory trasher altering the map??\n\t*/\n\tif (Debug_Check_Map) {\n\t\tif (!Map.Validate()) {\n\t\t\tif (WWMessageBox().Process (TEXT_MAP_ERROR, TEXT_STOP, TEXT_CONTINUE)==0) {\n\t\t\t\tGameActive = 0;\n\t\t\t}\n\t\t\tMap.Validate();\t\t// give debugger a chance to catch it\n\t\t}\n\t}\n\n\n\n#ifdef WIN32\n\tif (Debug_MotionCapture) {\n\t\tstatic void ** _array = 0;\n\t\tstatic int _sequence = 0;\n\t\tstatic int _seqsize = Rule.MovieTime * TICKS_PER_MINUTE;\n\n\t\tif (_array == NULL) {\n\t\t\t_array = new void * [_seqsize];\n\t\t\tmemset(_array, '\\0', _seqsize * sizeof(void*));\n\t\t}\n\n\t\tif (_array == NULL) {\n\t\t\tDebug_MotionCapture = false;\n\t\t}\n\n\t\tstatic GraphicBufferClass temp_page(\tSeenBuff.Get_Width(),\n\t\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Height(),\n\t\t\t\t\t\t\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Width() * SeenBuff.Get_Height());\n\n\t\tint size = SeenBuff.Get_Width() * SeenBuff.Get_Height();\n\n\t\tif (_sequence < _seqsize) {\n\t\t\tif (_array[_sequence] == NULL) {\n\t\t\t\t_array[_sequence] = new char[size];\n\t\t\t}\n\n\t\t\tif (_array[_sequence] != NULL) {\n\t\t\t\tSeenBuff.Blit(temp_page);\n\t\t\t\tmemmove(_array[_sequence], temp_page.Get_Buffer(), size);\n\t\t\t}\n\t\t\t_sequence++;\n\n\t\t} else {\n\t\t\tDebug_MotionCapture = false;\n\n\t\t\tCDFileClass file;\n\t\t\tfile.Cache(200000);\n\t\t\tchar filename[30];\n\n\t\t\tfor (int index = 0; index < _sequence; index++) {\n\t\t\t\tmemmove(temp_page.Get_Buffer(), _array[index], size);\n\t\t\t\tsprintf(filename, \"cap%04d.pcx\", index);\n\t\t\t\tfile.Set_Name(filename);\n\n\t\t\t\tWrite_PCX_File(file, temp_page, & GamePalette);\n\t\t\t}\n\n\t\t\t_sequence = 0;\n\t\t}\n\t}\n#endif\n\n\tBEnd(BENCH_GAME_FRAME);\n\n\tSync_Delay();\n\treturn(!GameActive);\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***************************************************************************\n * Map_Edit_Loop -- a mini-main loop for map edit mode only                *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/19/1994 BR : Created.                                              *\n *=========================================================================*/\nbool Map_Edit_Loop(void)\n{\n\t/*\n\t**\tRedraw the map.\n\t*/\n\tMap.Render();\n\n\t/*\n\t**\tGet user input (keys, mouse clicks).\n\t*/\n\tKeyNumType input;\n\n#ifdef WIN32\n\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#endif\t//WIN32\n\n\tint x;\n\tint y;\n\tMap.Input(input, x, y);\n\n\t/*\n\t**\tProcess keypress.\n\t*/\n\tif (input) {\n\t\tKeyboard_Process(input);\n\t}\n\n\tCall_Back();\t\t\t\t\t\t\t\t// maintains Theme.AI() for music\n\tColor_Cycle();\n\n\treturn(!GameActive);\n}\n\n\n/***************************************************************************\n * Go_Editor -- Enables/disables the map editor\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tflag\t\ttrue = go into editor mode; false = go into game mode\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/19/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid Go_Editor(bool flag)\n{\n\t/*\n\t**\tGo into Scenario Editor mode\n\t*/\n\tif (flag) {\n\t\tDebug_Map = true;\n\t\tDebug_Unshroud = true;\n\n\t\t/*\n\t\t** Un-select any selected objects\n\t\t*/\n\t\tUnselect_All();\n\n\t\t/*\n\t\t** Turn off the sidebar if it's on\n\t\t*/\n\t\tMap.Activate(0);\n\n\t\t/*\n\t\t** Reset the map's Button list for the new mode\n\t\t*/\n\t\tMap.Init_IO();\n\n\t\t/*\n\t\t** Force a complete redraw of the screen\n\t\t*/\n#ifdef WIN32\n\t\tHiddenPage.Clear();\n#else\n\t\tHidPage.Clear();\n#endif\n\t\tMap.Flag_To_Redraw(true);\n\t\tMap.Render();\n\n\t} else {\n\n\t\t/*\n\t\t**\tGo into normal game mode\n\t\t*/\n\t\tDebug_Map = false;\n\t\tDebug_Unshroud = false;\n\n\t\t/*\n\t\t** Un-select any selected objects\n\t\t*/\n\t\tUnselect_All();\n\n\t\t/*\n\t\t** Reset the map's Button list for the new mode\n\t\t*/\n\t\tMap.Init_IO();\n\n\t\t/*\n\t\t** Force a complete redraw of the screen\n\t\t*/\n\t\tHidPage.Clear();\n\t\tMap.Flag_To_Redraw(true);\n\t\tMap.Render();\n\t}\n}\n\n#endif\n\n\n/***********************************************************************************************\n * MixFileHandler -- Handles VQ file access.                                                   *\n *                                                                                             *\n *    This routine is called from the VQ player when it needs to access the source file. By    *\n *    using this routine it is possible to virtualize the file system.                         *\n *                                                                                             *\n * INPUT:   vqa   -- Pointer to the VQA handle for this animation.                             *\n *                                                                                             *\n *          action-- The requested action to perform.                                          *\n *                                                                                             *\n *          buffer-- Optional buffer pointer as needed by the type of action.                  *\n *                                                                                             *\n *          nbytes-- The number of bytes (if needed) for this operation.                       *\n *                                                                                             *\n * OUTPUT:  Returns a value consistent with the action requested.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong MixFileHandler(VQAHandle * vqa, long action, void * buffer, long nbytes)\n{\n\tCCFileClass * file;\n\tlong        error;\n\n\tfile = (CCFileClass *)vqa->VQAio;\n\n\t/*\n\t**\tPerform the action specified by the stream command.\n\t*/\n\tswitch (action) {\n\n\t\t/*\n\t\t** VQACMD_READ means read NBytes from the stream and place it in the\n\t\t** memory pointed to by Buffer.\n\t\t**\n\t\t** Any error code returned will be remapped by VQA library into\n\t\t** VQAERR_READ.\n\t\t*/\n\t\tcase VQACMD_READ:\n\t\t\terror = (file->Read(buffer, (unsigned short)nbytes) != (unsigned short)nbytes);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tVQACMD_WRITE is analogous to VQACMD_READ.\n\t\t**\n\t\t** Writing is not allowed to the VQA file, VQA library will remap the\n\t\t** error into VQAERR_WRITE.\n\t\t*/\n\t\tcase VQACMD_WRITE:\n\t\t\terror = 1;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tVQACMD_SEEK asks that you perform a seek relative to the current\n\t\t** position. NBytes is a signed number, indicating seek direction\n\t\t** (positive for forward, negative for backward). Buffer has no meaning\n\t\t** here.\n\t\t**\n\t\t** Any error code returned will be remapped by VQA library into\n\t\t** VQAERR_SEEK.\n\t\t*/\n\t\tcase VQACMD_SEEK:\n\t\t\terror = (file->Seek(nbytes, SEEK_CUR) == -1);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tVQACMD_OPEN asks that you open your stream for access.\n\t\t*/\n\t\tcase VQACMD_OPEN:\n\t\t\tfile = new CCFileClass((char *)buffer);\n\n\t\t\tif (file != NULL && file->Is_Available()) {\n\t\t\t\terror = file->Open((char *)buffer, READ);\n\n\t\t\t\tif (error != -1) {\n\t\t\t\t\tvqa->VQAio = (unsigned long)file;\n\t\t\t\t\terror = 0;\n\t\t\t\t} else {\n\t\t\t\t\tdelete file;\n\t\t\t\t\tfile = 0;\n\t\t\t\t\terror = 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\terror = 1;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase VQACMD_CLOSE:\n\t\t\tfile->Close();\n\t\t\tdelete file;\n\t\t\tfile = 0;\n\t\t\tvqa->VQAio = 0;\n\t\t\terror = 0;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tVQACMD_INIT means to prepare your stream for reading. This is used for\n\t\t** certain streams that can't be read immediately upon opening, and need\n\t\t** further preparation. This operation is allowed to fail; the error code\n\t\t** will be returned directly to the client.\n\t\t*/\n\t\tcase VQACMD_INIT:\n\n\t\t/*\n\t\t**\tIFFCMD_CLEANUP means to terminate the transaction with the associated\n\t\t** stream. This is used for streams that can't simply be closed. This\n\t\t** operation is not allowed to fail; any error returned will be ignored.\n\t\t*/\n\t\tcase VQACMD_CLEANUP:\n\t\t\terror = 0;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\terror = 0;\n\t\t\tbreak;\n\t}\n\n\treturn(error);\n}\n\n\nvoid Rebuild_Interpolated_Palette(unsigned char * interpal)\n{\n\tfor (int y=0; y<255; y++) {\n\t\tfor (int x=y+1; x<256; x++) {\n\t\t\t*(interpal + (y*256+x)) = *(interpal + (x*256+y));\n\t\t}\n\t}\n}\n\n\nunsigned char \t* InterpolatedPalettes[100];\nBOOL\t\t\t\tPalettesRead;\nunsigned\t\t\tPaletteCounter;\n\n\n/***********************************************************************************************\n * Load_Interpolated_Palettes -- Loads in any precalculated palettes for hires VQs             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Name of palette file                                                              *\n *                                                                                             *\n * OUTPUT:   Number of palettes loaded                                                         *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/7/96 9:49AM ST : Created                                                               *\n *=============================================================================================*/\nint Load_Interpolated_Palettes(char const * filename, BOOL add)\n{\n\tint\tnum_palettes=0;\n\tint\ti;\n\tint \tstart_palette;\n\n\tPalettesRead = FALSE;\n\tCCFileClass\tfile(filename);\n\n\tif (!add) {\n\t\tfor (i=0; i < ARRAY_SIZE(InterpolatedPalettes); i++) {\n\t\t\tInterpolatedPalettes[i]=NULL;\n\t\t}\n\t\tstart_palette=0;\n\t} else {\n\t\tfor (start_palette = 0; start_palette < ARRAY_SIZE(InterpolatedPalettes); start_palette++) {\n\t\t\tif (!InterpolatedPalettes[start_palette]) break;\n\t\t}\n\t}\n\n\t/*\n\t**\tHack another interpolated palette if the requested one is\n\t**\tnot present.\n\t*/\n\tif (!file.Is_Available()) {\n\t\tfile.Set_Name(\"AAGUN.VQP\");\n\t}\n\n\tif (file.Is_Available()) {\n\n\t\tfile.Open(READ);\n\t\tfile.Read(&num_palettes , 4);\n\n\t\tfor (i=0; i < num_palettes; i++) {\n\t\t\tInterpolatedPalettes[i+start_palette] = (unsigned char *)malloc (65536);\n\t\t\tmemset (InterpolatedPalettes[i+start_palette], 0, 65536);\n\t\t\tfor (int y = 0; y < 256; y++) {\n\t\t\t\tfile.Read (InterpolatedPalettes[i+start_palette] + y*256 , y+1);\n\t\t\t}\n\n\t\t\tRebuild_Interpolated_Palette(InterpolatedPalettes[i+start_palette]);\n\t\t}\n\n\t\tPalettesRead = TRUE;\n\t\tfile.Close();\n\t}\n\tPaletteCounter = 0;\n\treturn (num_palettes);\n}\n\n\nvoid Free_Interpolated_Palettes(void)\n{\n\tfor (int i = 0; i < ARRAY_SIZE(InterpolatedPalettes) ;i++) {\n\t\tif (InterpolatedPalettes[i]) {\n\t\t\tfree(InterpolatedPalettes[i]);\n\t\t\tInterpolatedPalettes[i]=NULL;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Play_Movie -- Plays a VQ movie.                                                             *\n *                                                                                             *\n *    Use this routine to play a VQ movie. It will dispatch the specified movie to the         *\n *    VQ player. The routine will not return until the movie has finished playing.             *\n *                                                                                             *\n * INPUT:   name  -- The name of the movie file (sans \".VQA\").                                 *\n *                                                                                             *\n *          theme -- The identifier for an optional theme that should be played in the         *\n *                   background while this VQ plays.                                           *\n *                                                                                             *\n *          clrscrn -- 'true' if to clear the screen when the movie is over                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef WIN32\nextern void Suspend_Audio_Thread(void);\nextern void Resume_Audio_Thread(void);\n\n#ifdef MOVIE640\nextern GraphicBufferClass VQ640;\n#endif\n#endif\nvoid Play_Movie(char const * name, ThemeType theme, bool clrscrn)\n\t{\n\t#ifdef MPEGMOVIE\n\t//theme = theme;\n\t//clrscrn = clrscrn;\n\tif( Using_DVD() )\n\t{\n\t\tif (PlayMpegMovie(name))\n\t\t\treturn;\n\t}\n\t#endif\n\n\t#ifdef CHEAT_KEYS\n\t//\tMono_Printf(\"Movie: %s\\n\", name);\n\t#endif\t//CHEAT_KEYS\n\t/*\n\t** Don't play movies in editor mode\n\t*/\n\tif (Debug_Map) {\n\t\treturn;\n\t}\n\t#ifdef CHEAT_KEYS\n\t//\tMono_Printf(\"A\\n\");\n\t#endif\t//CHEAT_KEYS\n\t/*\n\t** Don't play movies in multiplayer mode\n\t*/\n\tif (Session.Type != GAME_NORMAL) {\n\t\treturn;\n\t}\n\t#ifdef CHEAT_KEYS\n\t//Mono_Printf(\"b\\n\");\n\t#endif\t//CHEAT_KEYS\n\n\tif (name) {\n\t\tchar fullname[_MAX_FNAME+_MAX_EXT];\n\t\t_makepath(fullname, NULL, NULL, name, \".VQA\");\n\t\t#ifdef WIN32\n\t\tchar palname [_MAX_FNAME+_MAX_EXT];\n\t\t_makepath(palname , NULL, NULL, name, \".VQP\");\n\t\t#endif\t//WIN32\n\t\t#ifdef CHEAT_KEYS\n\t\t//\t\t\tMono_Set_Cursor(0, 0);Mono_Printf(\"[%s]\", fullname);\n\t\t#endif\n\n\t\tif (!CCFileClass(fullname).Is_Available()){\n\t\t\t#ifdef CHEAT_KEYS\n\t\t\t//\t\t Mono_Printf(\"fullname: %s\\n\", fullname);\n\t\t\t#endif\t//CHEAT_KEYS\n\t\t return;\n\t\t}\n\t\t/*\n\t\t**\tReset the anim control structure.\n\t\t*/\n\t\tAnim_Init();\n\n\t\t/*\n\t\t**\tPrepare to play a movie. First hide the mouse and stop any score that is playing.\n\t\t**\tWhile the score (if any) is fading to silence, fade the palette to black as well.\n\t\t**\tWhen the palette has finished fading, wait until the score has finished fading\n\t\t**\tbefore launching the movie.\n\t\t*/\n\t\tHide_Mouse();\n\t\tTheme.Queue_Song(theme);\n\t\tif (PreserveVQAScreen == 0 && !clrscrn) {\n\t\t\tBlackPalette.Set(FADE_PALETTE_MEDIUM);\n\t\t\tVisiblePage.Clear();\n\t\t\tBlackPalette.Adjust(0x08, WhitePalette);\n\t\t\tBlackPalette.Set();\n\t\t\tBlackPalette.Adjust(0xFF);\n\t\t\tBlackPalette.Set();\n\t\t}\n\t\tPreserveVQAScreen = 0;\n\t\tKeyboard->Clear();\n\n\t\tVQAHandle * vqa = NULL;\n\n\n\t\t#ifdef WIN32\n\t\t#ifdef MOVIE640\n\t\tif(IsVQ640) {\n\t\t\tAnimControl.ImageWidth = 640;\n\t\t\tAnimControl.ImageHeight = 400;\n\t\t\tAnimControl.ImageBuf = (unsigned char *)VQ640.Get_Offset();\n\t\t} else {\n\t\t\tAnimControl.ImageWidth = 320;\n\t\t\tAnimControl.ImageHeight = 200;\n\t\t\tAnimControl.ImageBuf = (unsigned char *)SysMemPage.Get_Offset();\n\t\t}\n\t\t#endif\n\t\t#endif\n\n\t\tif (!Debug_Quiet && Get_Digi_Handle() != -1) {\n\t\t\tAnimControl.OptionFlags |= VQAOPTF_AUDIO;\n\t\t} else {\n\t\t\tAnimControl.OptionFlags &= ~VQAOPTF_AUDIO;\n\t\t}\n\n\t\tif ((vqa = VQA_Alloc()) != NULL) {\n\t\t\tVQA_Init(vqa, MixFileHandler);\n\n\t\t\tif (VQA_Open(vqa, fullname, &AnimControl) == 0) {\n\t\t\t\tBrokeout = false;\n\t\t\t\t#ifdef WIN32\n\t\t\t\t//Suspend_Audio_Thread();\n\t\t\t\t#ifdef MOVIE640\n\t\t\t\tif(!IsVQ640) {\n\t\t\t\t\tLoad_Interpolated_Palettes(palname);\n\t\t\t\t}\n\t\t\t\t#else\n\t\t\t\tLoad_Interpolated_Palettes(palname);\n\t\t\t\t#endif\n\t\t\t\t//Set_Palette(BlackPalette);\n\t\t\t\tSysMemPage.Clear();\n\t\t\t\tInMovie = true;\n\t\t\t\t#endif\t//WIN32\n\t\t\t\tVQA_Play(vqa, VQAMODE_RUN);\n\t\t\t\tVQA_Close(vqa);\n\t\t\t\t#ifdef WIN32\n\t\t\t\t//Resume_Audio_Thread();\n\t\t\t\tInMovie = FALSE;\n\t\t\t\t#ifdef MOVIE640\n\t\t\t\tif(!IsVQ640) {\n\t\t\t\t\tFree_Interpolated_Palettes();\n\t\t\t\t}\n\t\t\t\t#else\n\t\t\t\tFree_Interpolated_Palettes();\n\t\t\t\t#endif\n\t\t\t\tIsVQ640 = false;\n\t\t\t\tSet_Primary_Buffer_Format();\n\t\t\t\t#endif\t//WIN32\n\n\t\t\t\t/*\n\t\t\t\t**\tAny movie that ends prematurely must have the screen\n\t\t\t\t**\tcleared to avoid any unexpected palette glitches.\n\t\t\t\t*/\n\t\t\t\tif (Brokeout) {\n\t\t\t\t\tclrscrn = true;\n\t\t\t\t\tVisiblePage.Clear();\n\t\t\t\t\tBrokeout = false;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t#ifndef NDEBUG\n\t\t\t\tbool error = true;\n\t\t\t\tassert(error);\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\tVQA_Free(vqa);\n\t\t} else {\n\t\t\tassert(vqa != NULL);\n\t\t}\n\t\t#ifdef CHEAT_KEYS\n\t\t//Mono_Printf(\"d\");\n\t\t#endif\t//CHEAT_KEYS\n\t\t/*\n\t\t**\tPresume that the screen is left in a garbage state as well as the palette\n\t\t**\tbeing in an unknown condition. Recover from this by clearing the screen and\n\t\t**\tforcing the palette to black.\n\t\t*/\n\t\tif (clrscrn) {\n\t\t\tVisiblePage.Clear();\n\t\t\tBlackPalette.Adjust(0x08, WhitePalette);\n\t\t\tBlackPalette.Set();\n\t\t\tBlackPalette.Adjust(0xFF);\n\t\t\tBlackPalette.Set();\n\t\t}\n\t\tShow_Mouse();\n\t}\n}\n\n\nvoid Play_Movie(VQType name, ThemeType theme, bool clrscrn)\n{\n\tif (name != VQ_NONE) {\n\t\tif (name == VQ_REDINTRO) {\n\t\t\tIsVQ640 = true;\n\t\t}\n\t\tPlay_Movie(VQName[name], theme, clrscrn);\n\t\tIsVQ640 = false;\n\t}\n}\n\n\n// Denzil 5/18/98 - Mpeg movie playback\n#ifdef MPEGMOVIE\nextern LPDIRECTDRAWPALETTE PalettePtr;\n\nbool PlayMpegMovie(const char* name)\n\t{\n\tchar path[MAX_PATH];\n\tCCFileClass file;\n\tconst char* filename;\n\n#ifdef CHEAT_KEYS\n\tif( bNoMovies )\n\t\treturn true;\n#endif\n\n\tsprintf(path, \"movies\\\\%.8s.%.3s\", name, \"mpg\");\n\tfilename = file.Set_Name(path);\n\t\n\tif (!file.Is_Available())\n\t\t{\n\t\t#if(1)\n\t\tVisiblePage.Clear();\n\t\tGamePalette.Set();\n\t\tShow_Mouse();\n\t\tsprintf(path, \"Couldn't find %s\\n\", filename);\n\t\tWWMessageBox().Process(path);\n\t\t#endif\n\t\treturn false;\n\t\t}\n\n\t// Stop theme music\n\tif (Misc_Focus_Loss_Function)\n\t\tMisc_Focus_Loss_Function();\n\n\t// Release primary surface\n\tVisiblePage.Un_Init();\n\n\t#ifdef MCIMPEG\n\tif (MciMovie && MpgSettings && (MpgSettings->GetDeviceName() != NULL))\n\t\t{\n\t\tDirectDrawObject->SetCooperativeLevel(MainWindow, DDSCL_NORMAL);\n\n\t\tif (!MciMovie->Open(filename, MpgSettings->GetDeviceName()))\n\t\t\t{\n\t\t\tWWMessageBox().Process(\"Couldn't open movie.\\n\");\n\t\t\t}\n\t\telse if (!MciMovie->Play(MainWindow))\n\t\t\t{\n\t\t\tWWMessageBox().Process(\"Couldn't play movie.\\n\");\n\t\t\t}\n\n\t\tDirectDrawObject->SetCooperativeLevel(MainWindow, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);\n\t\t}\n\telse\n\t#endif\n\t\t{\n\t\tDDSURFACEDESC ddsd;\n\t\tIDirectDrawSurface* primary = NULL;\n\t\tbool modeChange = false;\n\t\tRECT rect;\n\t\n\t\tif (FAILED(DirectDrawObject->SetDisplayMode(ScreenWidth, ScreenHeight, 16)))\n\t\t\t{\n\t\t\tWWMessageBox().Process(\"Couldn't change display mode.\\n\");\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t// Create primary surface reference\n\t\t\tmemset(&ddsd, 0, sizeof(ddsd));\n\t\t\tddsd.dwSize = sizeof(ddsd);\n\t\t\tddsd.dwFlags = DDSD_CAPS;\n\t\t\tddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;\n\n\t\t\tif (FAILED(DirectDrawObject->CreateSurface(&ddsd, &primary, NULL)))\n\t\t\t\t{\n\t\t\t\tWWMessageBox().Process(\"Couldn't create primary movie surface.\\n\");\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\trect.top = rect.left = 0;\n\t\t\t\trect.bottom = ScreenHeight;\n\t\t\t\trect.right = ScreenWidth;\n\t\t\n\t\t\t\tMpgSetCallback(MpegCallback, NULL);\n\t\t\t\tMpgPlay(filename, DirectDrawObject, primary, &rect);\n\n\t\t\t\tif (primary)\n\t\t\t\t\tprimary->Release();\n\n\t\t\t\t}\n\n\t\t\tDirectDrawObject->SetDisplayMode(ScreenWidth, ScreenHeight, 8);\n\t\t\t}\n\t\t}\n\n\t// Restore surfaces\n\tVisiblePage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)(GBC_VISIBLE|GBC_VIDEOMEM));\n\tPaletteSurface->SetPalette(PalettePtr);\n\tAllSurfaces.Set_Surface_Focus(true);\n\tAllSurfaces.Restore_Surfaces();\n\treturn true;\n\t}\n\n\nMPG_RESPONSE far __stdcall MpegCallback(MPG_CMD cmd, LPVOID data, LPVOID user)\n\t{\n\tstatic IDirectDrawPalette* _palette = NULL;\n\n\tuser = user;\n\n\tswitch (cmd)\n\t\t{\n\t\tcase MPGCMD_ERROR:\n\t\t\tWWMessageBox().Process((char const *)data);\n\t\tbreak;\n\n\t\tcase MPGCMD_INIT:\n\t\t\tVisiblePage.Clear();\n\t\tbreak;\n\n\t\tcase MPGCMD_CLEANUP:\n\t\t\tVisiblePage.Clear();\n\n\t\t\tif (_palette != NULL)\n\t\t\t\t{\n\t\t\t\tPaletteSurface->SetPalette(_palette);\n\t\t\t\t_palette->Release();\n\t\t\t\t_palette = NULL;\n\t\t\t\t}\n\t\tbreak;\n\t\t\n\t\tcase MPGCMD_PALETTE:\n\t\t\tif (FAILED(PaletteSurface->GetPalette(&_palette)))\n\t\t\t\t{\n\t\t\t\tWWMessageBox().Process(\"Couldn't get primary palette.\\n\");\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif (FAILED(PaletteSurface->SetPalette((IDirectDrawPalette*)data)))\n\t\t\t\t\t{\n\t\t\t\t\tWWMessageBox().Process(\"Couldn't set movie palette.\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\tbreak;\n\t\t\n\t\tcase MPGCMD_UPDATE:\n\t\t\tif ((BreakoutAllowed || Debug_Flag) && Keyboard->Check())\n\t\t\t\t{\n\t\t\t\tif (Keyboard->Get() == KN_ESC)\n\t\t\t\t\t{\n\t\t\t\t\tKeyboard->Clear();\n\t\t\t\t\treturn MPGRES_QUIT;\n\t\t\t\t\t}\n\n\t\t\t\tKeyboard->Clear();\n\t\t\t\t}\n\n\t\t\tif (!GameInFocus)\n\t\t\t\t{\n\t\t\t\tMpgPause();\n\n\t\t\t\twhile (!GameInFocus)\n\t\t\t\t\t{\n\t\t\t\t\tCheck_For_Focus_Loss();\n\t\t\t\t\t}\n\n\t\t\t\tMpgResume();\n\t\t\t\treturn MPGRES_LOSTFOCUS;\n\t\t\t\t}\n\t\tbreak;\n\n\t\tdefault:\n\t\tbreak;\n\t\t}\n\n\treturn MPGRES_CONTINUE;\n\t}\n#endif\n\n/***********************************************************************************************\n * Unselect_All -- Causes all selected objects to become unselected.                           *\n *                                                                                             *\n *    This routine will unselect all objects that are currently selected.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Unselect_All(void)\n{\n\twhile (CurrentObject.Count()) {\n\t\tCurrentObject[0]->Unselect();\n\t}\n}\n\n\n/***********************************************************************************************\n * Fading_Table_Name -- Builds a theater specific fading table name.                           *\n *                                                                                             *\n *    This routine builds a standard fading table name. This name is dependant on the theater  *\n *    being played, since each theater has its own palette.                                    *\n *                                                                                             *\n * INPUT:   base  -- The base name of this fading table. The base name can be no longer than   *\n *                   seven characters.                                                         *\n *                                                                                             *\n *          theater  -- The theater that this fading table is specific to.                     *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the constructed fading table filename. This pointer is   *\n *          valid until this function is called again.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * Fading_Table_Name(char const * base, TheaterType theater)\n{\n\tstatic char _buffer[_MAX_FNAME+_MAX_EXT];\n\tchar root[_MAX_FNAME];\n\n\tsprintf(root, \"%1.1s%s\", Theaters[theater].Root, base);\n\t_makepath(_buffer, NULL, NULL, root, \".MRF\");\n\treturn(_buffer);\n}\n\n\n/***********************************************************************************************\n * Get_Radar_Icon -- Builds and alloc a radar icon from a shape file                           *\n *                                                                                             *\n * INPUT:      void const * shapefile - pointer to a key framed shapefile                      *\n *             int shapenum          - shape to extract from shapefile                         *\n *                                                                                             *\n * OUTPUT:     void const *           - 3/3 icon set of shape from file                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/12/1995 PWG : Created.                                                                 *\n *   05/10/1995 JLB : Handles a null shapefile pointer.                                        *\n *=============================================================================================*/\nvoid const * Get_Radar_Icon(void const * shapefile, int shapenum, int frames, int zoomfactor)\n{\n\tstatic int _offx[]={\t0, 0,  -1,  1, 0, -1, 1, -1, 1};\n\tstatic int _offy[]={\t0, 0,  -1,  1, 0, -1, 1, -1, 1};\n\tint lp,framelp;\n\tchar pixel;\n\n\tchar * retval = NULL;\n\tchar * buffer = NULL;\n\n\t/*\n\t**\tIf there is no shape file, then there can be no radar icon imagery.\n\t*/\n\tif (!shapefile) return(NULL);\n\n#if (0)\n\tCCPalette.Set();\n\tSet_Logic_Page(SeenBuff);\n\tCC_Draw_Shape(shapefile, shapenum, 64, 64, WINDOW_MAIN, SHAPE_WIN_REL);\n#endif\n\n\t/*\n\t** Get the pixel width and height of the frame we built.  This will\n\t** be used to extract icons and build pixels.\n\t*/\n\tint pixel_width  = Get_Build_Frame_Width( shapefile );\n\tint pixel_height = Get_Build_Frame_Height( shapefile );\n\n\t/*\n\t** Find the width and height in icons, adjust these by half an\n\t** icon because the artists may be sloppy and miss the edge of an\n\t** icon one way or the other.\n\t*/\n\tint icon_width\t = (pixel_width + 12) / 24;\n\tint icon_height = (pixel_height + 12) / 24;\n\n\t/*\n\t** If we have been told to build as many frames as possible, then\n\t** find out how many frames there are to build.\n\t*/\n\tif (frames == -1) frames = Get_Build_Frame_Count( shapefile );\n\n\t/*\n\t** Allocate a position to store our icons.  If the alloc fails then\n\t** we don't add these icons to the set.\n\t**/\n\tbuffer = new char[(icon_width * icon_height * 9 * frames)+2];\n\tif (!buffer) return(NULL);\n\n\t/*\n\t** Save off the return value so that we can return it to the calling\n\t** function.\n\t*/\n\tretval\t = (char *)buffer;\n\t*buffer++ = (char)icon_width;\n\t*buffer++ = (char)icon_height;\n\tint val = 24/zoomfactor;\n\n\tfor (framelp = 0; framelp < frames; framelp ++) {\n\t\t/*\n\t\t** Build the current frame.  If the frame can not be built then we\n\t\t** just need to skip past this set of icons and try to build the\n\t\t** next frame.\n\t\t*/\n#ifdef WIN32\n\t\tvoid * ptr;\n\t\tif ((ptr = (void *)(Build_Frame(shapefile, shapenum + framelp, SysMemPage.Get_Buffer()))) != NULL) {\n\t\t\tptr = Get_Shape_Header_Data(ptr);\n#else\t//WIN#@\n\t\tif (Build_Frame(shapefile, shapenum + framelp, HidPage.Get_Buffer()) <= (unsigned long)HidPage.Get_Size() ) {\n#endif\t//WIN32\n\n\t\t\t/*\n\t\t\t** Loop through the icon width and the icon height building icons\n\t\t\t** into the buffer pointer.  When the getx or gety falls outside of\n\t\t\t** the width and height of the shape, just insert transparent pixels.\n\t\t\t*/\n\t\t\tfor (int icony = 0; icony < icon_height; icony ++) {\n\t\t\t\tfor (int iconx = 0; iconx < icon_width; iconx ++) {\n#ifdef WIN32\n\n\t\t\t\t\tfor (int y = 0; y < zoomfactor; y++) {\n\t\t\t\t\t\tfor (int x = 0; x < zoomfactor; x++) {\n\t\t\t\t\t\t\tint getx = (iconx * 24) + (x * val) + (zoomfactor / 2);\n\t\t\t\t\t\t\tint gety = (icony * 24) + (y * val) + (zoomfactor / 2);\n\t\t\t\t\t\t\tif ((getx < pixel_width) && (gety < pixel_height)) {\n\t\t\t\t\t\t\t\tfor (lp = 0; lp < 9; lp ++) {\n\t\t\t\t\t\t\t\t\tpixel\t= *(char *)((char *)ptr + ((gety - _offy[lp]) * pixel_width) + getx-_offx[lp]);\n\n#else\t//WIN32\n\t\t\t\t\tfor (int y = 0; y < 3; y++) {\n\t\t\t\t\t\tfor (int x = 0; x < 3; x++) {\n\t\t\t\t\t\t\tint getx = (iconx * 24) + (x << 3) + 4;\n\t\t\t\t\t\t\tint gety = (icony * 24) + (y << 3) + 4;\n\t\t\t\t\t\t\tif ((getx < pixel_width) && (gety < pixel_height)) {\n\t\t\t\t\t\t\t\tfor (lp = 0; lp < 9; lp ++) {\n\t\t\t\t\t\t\t\t\tpixel\t= *(char *)((char *)HidPage.Get_Buffer(), ((gety - _offy[lp]) * pixel_width) + getx-_offx[lp]);\n#endif\t//WIN32\n\t\t\t\t\t\t\t\t\tif (pixel == LTGREEN) pixel = 0;\n\t\t\t\t\t\t\t\t\tif (pixel) {\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t*buffer++ = pixel;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t*buffer++ = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tbuffer += icon_width * icon_height * 9;\n\t\t}\n\t}\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * CC_Draw_Shape -- Custom draw shape handler.                                                 *\n *                                                                                             *\n *    All draw shape calls will route through this function. It handles all draws for          *\n *    C&C. Such draws always occur to the logical page and assume certain things about         *\n *    the parameters passed.                                                                   *\n *                                                                                             *\n * INPUT:   shapefile   -- Pointer to the shape data file. This data file contains all the     *\n *                         embedded shapes.                                                    *\n *                                                                                             *\n *          shapenum    -- The shape number within the shapefile that will be drawn.           *\n *                                                                                             *\n *          x,y         -- The pixel coordinates to draw the shape.                            *\n *                                                                                             *\n *          window      -- The clipping window to use.                                         *\n *                                                                                             *\n *          flags       -- The custom draw shape flags. This controls how the parameters       *\n *                         are used (if any).                                                  *\n *                                                                                             *\n *          fadingdata  -- If SHAPE_FADING is desired, then this points to the fading          *\n *                         data table.                                                         *\n *                                                                                             *\n *          ghostdata   -- If SHAPE_GHOST is desired, then this points to the ghost remap      *\n *                         table.                                                              *\n *                                                                                             *\n *          rotation    -- Rotation to apply to the shape (DIR_N = no rotation at all).        *\n *                                                                                             *\n *          scale       -- 24.8 fixed point scale factor.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CC_Draw_Shape(void const * shapefile, int shapenum, int x, int y, WindowNumberType window, ShapeFlags_Type flags, void const * fadingdata, void const * ghostdata, DirType rotation, long scale)\n{\n\tint predoffset;\n#ifdef WIN32\n\tunsigned\tlong\tshape_pointer;\n#endif\t//WIN32\n\n\n\t/*\n\t** Special kludge for E3 to prevent crashes\n\t*/\n\tif ((flags & SHAPE_GHOST) && (!ghostdata)) {\n\t\tghostdata = DisplayClass::SpecialGhost;\n\t}\n\tif ((flags & SHAPE_FADING) && (!fadingdata)) {\n\t\tfadingdata = DisplayClass::FadingShade;\n\t}\n\n\tstatic unsigned char * _xbuffer = 0;\n\n\tif (!_xbuffer) {\n\t\t_xbuffer = new unsigned char[SHAPE_BUFFER_SIZE];\n\t}\n\n\tif (shapefile != NULL && shapenum != -1) {\n\n\t\tint width = Get_Build_Frame_Width(shapefile);\n\t\tint height = Get_Build_Frame_Height(shapefile);\n\n#ifdef NEVER\n\t\t/*\n\t\t**\tPerform a quick clip check against the destination rectangle.\n\t\t*/\n\t\tif (flags & SHAPE_CENTER) {\n\t\t\tif (x-width/2 >= WindowList[window][WINDOWWIDTH]) return;\n\t\t\tif (y-width/2 >= WindowList[window][WINDOWHEIGHT]) return;\n\t\t\tif (x+width/2 < 0) return;\n\t\t\tif (y+height/2 < 0) return;\n\n\t\t} else {\n\t\t\tif (x >= WindowList[window][WINDOWWIDTH]) return;\n\t\t\tif (y >= WindowList[window][WINDOWHEIGHT]) return;\n\t\t\tif (x+width < 0) return;\n\t\t\tif (y+height < 0) return;\n\t\t}\n#endif\n\n\n#ifdef WIN32\n\t\t/*\n\t\t** In WIn95, build shape returns a pointer to the shape not its size\n\t\t*/\n\t\tshape_pointer = Build_Frame(shapefile, shapenum, _ShapeBuffer);\n\t\tif (shape_pointer) {\n\t\t\tGraphicViewPortClass draw_window(LogicPage->Get_Graphic_Buffer(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWX] + LogicPage->Get_XPos(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWY] + LogicPage->Get_YPos(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWWIDTH],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWHEIGHT]);\n\t\t\tunsigned char * buffer = (unsigned char *) shape_pointer;\t//Get_Shape_Header_Data((void*)shape_pointer);\n\n#else\t//WIN32\n\t\tif ( Build_Frame(shapefile, shapenum, _ShapeBuffer ) <= (unsigned long)_ShapeBufferSize) {\n\t\t\tGraphicViewPortClass draw_window(LogicPage,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWX],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWY],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWWIDTH],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWHEIGHT]);\n\t\t\tunsigned char * buffer = (unsigned char *)_ShapeBuffer;\n#endif\t//WIN32\n\n\t\t\tUseOldShapeDraw = false;\n\t\t\t/*\n\t\t\t**\tRotation and scale handler.\n\t\t\t*/\n\t\t\tif (rotation != DIR_N || scale != 0x0100) {\n\n\t\t\t\t/*\n\t\t\t\t** Get the raw shape data without the new header and flag to use the old shape drawing\n\t\t\t\t*/\n\t\t\t\tUseOldShapeDraw = true;\n#ifdef WIN32\n\t\t\t\tbuffer = (unsigned char *) Get_Shape_Header_Data((void*)shape_pointer);\n#endif\n\n\t\t\t\tif (Debug_Rotate) {\n\n\t\t\t\t\tGraphicBufferClass src(width, height, buffer);\n\t\t\t\t\twidth *= 2;\n\t\t\t\t\theight *= 2;\n\t\t\t\t\tmemset(_xbuffer, '\\0', SHAPE_BUFFER_SIZE);\n\t\t\t\t\tGraphicBufferClass dst(width, height, _xbuffer);\n\t\t\t\t\tRotate_Bitmap(&src, &dst, rotation);\n\t\t\t\t\tbuffer = _xbuffer;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tBitmapClass bm(width, height, buffer);\n\t\t\t\t\twidth *= 2;\n\t\t\t\t\theight *= 2;\n\t\t\t\t\tmemset(_xbuffer, '\\0', SHAPE_BUFFER_SIZE);\n\t\t\t\t\tGraphicBufferClass gb(width, height, _xbuffer);\n\t\t\t\t\tTPoint2D pt(width/2, height/2);\n\n\t\t\t\t\tgb.Scale_Rotate(bm, pt, scale, (256-(rotation-64)));\n\t\t\t\t\tbuffer = _xbuffer;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSpecial shadow drawing code (used for aircraft and bullets).\n\t\t\t*/\n\t\t\tif ((flags & (SHAPE_FADING|SHAPE_PREDATOR)) == (SHAPE_FADING|SHAPE_PREDATOR)) {\n\t\t\t\tflags = flags & ~(SHAPE_FADING|SHAPE_PREDATOR);\n\t\t\t\tflags = flags | SHAPE_GHOST;\n\t\t\t\tghostdata = DisplayClass::SpecialGhost;\n\t\t\t}\n\n\t\t\tpredoffset = Frame;\n\n\t\t\tif (x > ( WindowList[window][WINDOWWIDTH] << 2)) {\n\t\t\t\tpredoffset = -predoffset;\n\t\t\t}\n\n\t\t\tif (draw_window.Lock()) {\n\t\t\t\tif ((flags & (SHAPE_GHOST|SHAPE_FADING)) == (SHAPE_GHOST|SHAPE_FADING)) {\n\t\t\t\t\tBuffer_Frame_To_Page(x, y, width, height, buffer, draw_window, flags | SHAPE_TRANS, ghostdata, fadingdata, 1, predoffset);\n\t\t\t\t} else {\n\t\t\t\t\tif (flags & SHAPE_FADING) {\n\t\t\t\t\t\tBuffer_Frame_To_Page(x, y, width, height, buffer, draw_window, flags | SHAPE_TRANS, fadingdata, 1, predoffset);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (flags & SHAPE_PREDATOR) {\n\t\t\t\t\t\t\tBuffer_Frame_To_Page(x, y, width, height, buffer, draw_window, flags | SHAPE_TRANS, predoffset);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tBuffer_Frame_To_Page(x, y, width, height, buffer, draw_window, flags | SHAPE_TRANS, ghostdata, predoffset);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdraw_window.Unlock();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Shape_Dimensions -- Determine the minimum rectangle for the shape.                          *\n *                                                                                             *\n *    This routine will calculate (using brute forced) the minimum rectangle that will         *\n *    enclose the pixels of the shape. This rectangle will be relative to the upper left       *\n *    corner of the maximum shape size. By using this minimum rectangle, it is possible to     *\n *    greatly optimize the map 'dirty rectangle' logic.                                        *\n *                                                                                             *\n * INPUT:   shapedata   -- Pointer to the shape data block.                                    *\n *                                                                                             *\n *          shapenum    -- The shape number to examine. Each shape would have a different      *\n *                         dimension rectangle.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the rectangle that encloses the shape.                                *\n *                                                                                             *\n * WARNINGS:   This routine uses brute force and is slow. It is presumed that the results      *\n *             will be cached for subsiquent reuse.                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/22/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRect const Shape_Dimensions(void const * shapedata, int shapenum)\n{\n\tRect rect;\n\n\tif (shapedata == NULL || shapenum < 0 || shapenum > Get_Build_Frame_Count(shapedata)) {\n\t\treturn(rect);\n\t}\n\n\tchar * shape;\n#ifdef WIN32\n\tvoid * sh = (void *)Build_Frame(shapedata, shapenum, _ShapeBuffer);\n\tif (sh == NULL) return(rect);\n//\tshape = (char *)sh;\n\tshape = (char *)Get_Shape_Header_Data(sh);\n#else\n\tBuild_Frame(shapedata, shapenum, _ShapeBuffer);\n\tshape = (char *)_ShapeBuffer;\n#endif\n\n\tint width = Get_Build_Frame_Width(shapedata);\n\tint height = Get_Build_Frame_Height(shapedata);\n\n\trect.X = 0;\n\trect.Y = 0;\n\tint xlimit = width-1;\n\tint ylimit = height-1;\n\n\t/*\n\t**\tFind top edge of the shape.\n\t*/\n\tfor (int y = 0; y <= ylimit; y++) {\n\t\tfor (int x = 0; x <= xlimit; x++) {\n\t\t\tif (shape[y*width + x] != 0) {\n\t\t\t\trect.Y = y;\n\t\t\t\trect.X = x;\n\t\t\t\ty = ylimit+1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tFind bottom edge of the shape.\n\t*/\n\tfor (y = ylimit; y >= rect.Y; y--) {\n\t\tfor (int x = xlimit; x >= 0; x--) {\n\t\t\tif (shape[y*width + x] != 0) {\n\t\t\t\trect.Height = (y-rect.Y)+1;\n\t\t\t\txlimit = x;\n\t\t\t\ty = rect.Y-1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tFind left edge of the shape.\n\t*/\n\tfor (int x = 0; x < rect.X; x++) {\n\t\tfor (y = rect.Y; y < rect.Y+rect.Height; y++) {\n\t\t\tif (shape[y*width + x] != 0) {\n\t\t\t\trect.X = x;\n\t\t\t\tx = rect.X;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tFind the right edge of the shape.\n\t*/\n\tfor (x = width-1; x >= xlimit; x--) {\n\t\tfor (y = rect.Y; y < rect.Y+rect.Height; y++) {\n\t\t\tif (shape[y*width + x] != 0) {\n\t\t\t\trect.Width = (x-rect.X)+1;\n\t\t\t\tx = xlimit-1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tNormalize the rectangle around the center of the shape.\n\t*/\n\trect.X -= width / 2;\n\trect.Y -= height / 2;\n\n\t/*\n\t**\tReturn with the minimum rectangle that encloses the shape.\n\t*/\n\treturn(rect);\n}\n\n\n/***********************************************************************************************\n * Fetch_Techno_Type -- Convert type and ID into TechnoTypeClass pointer.                      *\n *                                                                                             *\n *    This routine will convert the supplied RTTI type number and the ID value into a valid    *\n *    TechnoTypeClass pointer. If there is an error in conversion, then NULL is returned.      *\n *                                                                                             *\n * INPUT:   type  -- RTTI type of the techno class object.                                     *\n *                                                                                             *\n *          id    -- Integer representation of the techno sub type number.                     *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the techno type class object specified or NULL if the    *\n *          conversion could not occur.                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTechnoTypeClass const * Fetch_Techno_Type(RTTIType type, int id)\n{\n\tswitch (type) {\n\t\tcase RTTI_UNITTYPE:\n\t\tcase RTTI_UNIT:\n\t\t\treturn(&UnitTypeClass::As_Reference(UnitType(id)));\n\n\t\tcase RTTI_VESSELTYPE:\n\t\tcase RTTI_VESSEL:\n\t\t\treturn(&VesselTypeClass::As_Reference(VesselType(id)));\n\n\t\tcase RTTI_BUILDINGTYPE:\n\t\tcase RTTI_BUILDING:\n\t\t\treturn(&BuildingTypeClass::As_Reference(StructType(id)));\n\n\t\tcase RTTI_INFANTRYTYPE:\n\t\tcase RTTI_INFANTRY:\n\t\t\treturn(&InfantryTypeClass::As_Reference(InfantryType(id)));\n\n\t\tcase RTTI_AIRCRAFTTYPE:\n\t\tcase RTTI_AIRCRAFT:\n\t\t\treturn(&AircraftTypeClass::As_Reference(AircraftType(id)));\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * VQ_Call_Back -- Maintenance callback used for VQ movies.                                    *\n *                                                                                             *\n *    This routine is called every frame of the VQ movie as it is being played. If this        *\n *    routine returns non-zero, then the movie will stop.                                      *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the image buffer for the current frame.                     *\n *                                                                                             *\n *          frame    -- The frame number about to be displayed.                                *\n *                                                                                             *\n * OUTPUT:  Should the movie be stopped?                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef WIN32\nvoid VQA_PauseAudio(void);\nvoid Check_VQ_Palette_Set(void);\n\nextern GraphicBufferClass VQ640;\nextern bool IsVQ640;\nlong VQ_Call_Back(unsigned char *, long )\n{\n\tint key = 0;\n\tif (Keyboard->Check()) {\n\t\tkey = Keyboard->Get();\n\t\tKeyboard->Clear();\n\t}\n\tCheck_VQ_Palette_Set();\n#ifdef MOVIE640\n\tif(IsVQ640) {\n\t\tVQ640.Blit(SeenBuff);\n\t} else {\n\t\tInterpolate_2X_Scale(&SysMemPage, &SeenBuff, NULL);\n\t}\n#else\n\tInterpolate_2X_Scale(&SysMemPage, &SeenBuff, NULL);\n#endif\n\t//Call_Back();\n\n\tif ((BreakoutAllowed || Debug_Flag) && key == KN_ESC) {\n\t\tKeyboard->Clear();\n\t\tBrokeout = true;\n\t\treturn(true);\n\t}\n\n\tif (!GameInFocus) {\n\t\tVQA_PauseAudio();\n\t\twhile (!GameInFocus) {\n\t\t\tCheck_For_Focus_Loss();\n\t\t}\n\t}\n\treturn(false);\n}\n\n#else\t//WIN32\n\nlong VQ_Call_Back(unsigned char *, long )\n{\n\tCall_Back();\n\tif ((BreakoutAllowed || Debug_Flag) && Keyboard->Check()) {\n\t\tif (Keyboard->Get() == KN_ESC) {\n\t\t\tKeyboard->Clear();\n\t\t\tBrokeout = true;\n\t\t\treturn(true);\n\t\t}\n\t\tKeyboard->Clear();\n\t}\n\treturn(false);\n}\n#endif\t//WIN32\n\n\n/***********************************************************************************************\n * Handle_Team -- Processes team selection command.                                            *\n *                                                                                             *\n *    This routine will handle creation and selection of pseudo teams that the player can      *\n *    create or control. A team in this sense is an arbitrary grouping of units such that      *\n *    rapid selection control is allowed.                                                      *\n *                                                                                             *\n * INPUT:   team  -- The logical team number to process.                                       *\n *                                                                                             *\n *          action-- The action to perform on this team:                                       *\n *                   0 - Toggle the select state for all members of this team.                 *\n *                   1 - Select the members of this team.                                      *\n *                   2 - Make all selected objects members of this team.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Handle_Team(int team, int action)\n{\n\tint index;\n\n\t//\n\t// Recording support\n\t//\n\tif (Session.Record) {\n\t\tTeamNumber = (char)team;\n\t\tTeamEvent = (char)action + 1;\n\t}\n\n\tAllowVoice = true;\n\tswitch (action) {\n\n\t\t/*\n\t\t**\tToggle the team selection. If the team is selected, then merely unselect it. If the\n\t\t**\tteam is not selected, then unselect all others before selecting this team.\n\t\t*/\n\t\tcase 3:\n\t\tcase 0:\n\n\t\t\t/*\n\t\t\t**\tIf a non team member is currently selected, then deselect all objects\n\t\t\t**\tbefore selecting this team.\n\t\t\t*/\n\t\t\tif (CurrentObject.Count()) {\n\t\t\t\tif (CurrentObject[0]->Is_Foot() && ((FootClass *)CurrentObject[0])->Group != team) {\n\t\t\t\t\tUnselect_All();\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->IsSelected) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->IsSelected) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->IsSelected) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\t\t\tAircraftClass * obj = Aircraft.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->IsSelected) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCenter the map around the team if the ALT key was pressed too.\n\t\t\t*/\n\t\t\tif (action == 3) {\n\t\t\t\tMap.Center_Map();\n#ifdef WIN32\n\t\t\t\tMap.Flag_To_Redraw(true);\n#endif\t//WIn32\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tAdditive selection of team.\n\t\t*/\n\t\tcase 1:\n\t\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->IsSelected) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->IsSelected) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->IsSelected) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\t\t\tAircraftClass * obj = Aircraft.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->IsSelected) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tCreate the team.\n\t\t*/\n\t\tcase 2: {\n\t\t\tlong minx = 0x7FFFFFFFL, miny = 0x7FFFFFFFL;\n\t\t\tlong maxx = 0, maxy = 0;\n\t\t\tTeamSpeed[team] = SPEED_WHEEL;\n\t\t\tTeamMaxSpeed[team] = MPH_LIGHT_SPEED;\n\t\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl) {\n\t\t\t\t \tif (obj->Group == team) obj->Group = 0xFF;\n\t\t\t\t\tif (obj->IsSelected) {\n\t\t\t\t\t\tobj->Group = team;\n\t\t\t\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\t\t\tif (obj->Class->MaxSpeed < TeamMaxSpeed[team]) {\n\t\t\t\t\t\t\tTeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t\t\t\tTeamSpeed[team] = obj->Class->Speed;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl) {\n\t\t\t\t \tif (obj->Group == team) obj->Group = -1;\n\t\t\t\t\tif (obj->IsSelected) {\n\t\t\t\t\t\tobj->Group = team;\n\t\t\t\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\t\t\tif (obj->Class->MaxSpeed < TeamMaxSpeed[team]) {\n\t\t\t\t\t\t\tTeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t\t\t\tTeamSpeed[team] = obj->Class->Speed;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl) {\n\t\t\t\t \tif (obj->Group == team) obj->Group = 0xFF;\n\t\t\t\t\tif (obj->IsSelected) {\n\t\t\t\t\t\tobj->Group = team;\n\t\t\t\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\t\t\tif (obj->Class->MaxSpeed < TeamMaxSpeed[team]) {\n\t\t\t\t\t\t\tTeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\t\t\tAircraftClass * obj = Aircraft.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl) {\n\t\t\t\t \tif (obj->Group == team) obj->Group = 0xFF;\n\t\t\t\t\tif (obj->IsSelected) {\n\t\t\t\t\t\tobj->Group = team;\n\t\t\t\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl &&\n\t\t\t\t \t(obj->Group == team) && (obj->IsSelected) ) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** When a team is first created, they're created without a\n\t\t\t\t\t** formation offset, so they will not be created in\n\t\t\t\t\t** formation.  Later, if they're assigned a formation, the\n\t\t\t\t\t** XFormOffset & YFormOffset numbers will change to valid\n\t\t\t\t\t** offsets, and they'll be formationed.\n\t\t\t\t\t*/\n#if(1)\n\t\t\t\t\tobj->XFormOffset = obj->YFormOffset = (int)0x80000000;\n#else\n#if(1)\n// Old always-north formation stuff\n\t\t\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\t\t\tobj->YFormOffset = yc - centery;\n#else\n// New method: save direction and distance rather than x & y offset\n\t\t\t\t\t\tobj->XFormOffset = ::Direction(As_Coord(center), obj->Center_Coord());\n\t\t\t\t\t\tobj->YFormOffset = ::Distance (As_Coord(center), obj->Center_Coord());\n#endif\n#endif\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl) {\n\t\t\t\t \tif (obj->Group == team) obj->Group = 0xFF;\n\t\t\t\t\tif (obj->IsSelected) obj->Group = team;\n\t\t\t\t\tif (obj->Group == team  && obj->IsSelected) {\n#if(1)\n\t\t\t\t\t\tobj->XFormOffset = obj->YFormOffset = (int)0x80000000;\n#else\n#if(1)\n// Old always-north formation stuff\n\t\t\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\t\t\tobj->YFormOffset = yc - centery;\n#else\n// New method: save direction and distance rather than x & y offset\n\t\t\t\t\t\tobj->XFormOffset = ::Direction(As_Coord(center), obj->Center_Coord());\n\t\t\t\t\t\tobj->YFormOffset = ::Distance (As_Coord(center), obj->Center_Coord());\n#endif\n#endif\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tAllowVoice = true;\n}\n\n\n/***********************************************************************************************\n * Handle_View -- Either records or restores the tactical view.                                *\n *                                                                                             *\n *    This routine is used to record or restore the current map tactical view.                 *\n *                                                                                             *\n * INPUT:   view  -- The view number to work with.                                             *\n *                                                                                             *\n *          action-- The action to perform with this view number.                              *\n *                   0  =  Restore the view to this previously remembered location.            *\n *                   1  =  Record the current view location.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Handle_View(int view, int action)\n{\n\tif ((unsigned)view < ARRAY_SIZE(Scen.Views)) {\n\t\tif (action == 0) {\n\n\t\t\tMap.Set_Tactical_Position(Coord_Whole(Cell_Coord(Scen.Views[view] - (MAP_CELL_W * 4 * RESFACTOR) - (5*RESFACTOR))));\n\n#ifdef WIN32\n\t\t\t/*\n\t\t\t** Win95 scrolling logic cant handle just jumps in screen position so redraw the lot.\n\t\t\t*/\n\t\t\tMap.Flag_To_Redraw (true);\n#endif\t//WIN32\n\t\t} else {\n\t\t\tScen.Views[view] = Coord_Cell(Map.TacticalCoord) + (MAP_CELL_W*4*RESFACTOR) + (5*RESFACTOR);\n\t\t}\n\t}\n}\n\n\n#ifndef ROR_NOT_READY\n#define ROR_NOT_READY 21\n#endif\n\nstatic char * _CD_Volume_Label[] = {\n\t\"CD1\",\n\t\"CD2\",\n\t\"CD3\",\n\t\"CD4\",\n\t// Denzil 4/15/98\n\t#ifdef DVD\n\t\"CD1\",\t\t//\tajw - Pushes RADVD to position 5, to match enum in Force_CD_Available(). 4 will never be returned here.\n\t\"RADVD\",\n\t#endif\n};\nstatic int _Num_Volumes = ARRAY_SIZE(_CD_Volume_Label);\n\n\n#ifdef WIN32\n/***********************************************************************************************\n * Get_CD_Index -- returns the volume type of the CD in the given drive                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    drive number                                                                      *\n *           timeout                                                                           *\n *                                                                                             *\n * OUTPUT:   0 = gdi                                                                           *\n *           1 = nod                                                                           *\n *           2 = covert or CS                                                                       *\n *           3 = Aftermath\n *           5 = DVD\n *          -1 = non C&C                                                                       *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/21/96 5:27PM ST : Created                                                              *\n *    01/20/97 V.Grippi added CS support\t\t\t\t\t\t\t\t\t\t\t       *\n *=============================================================================================*/\nint Get_CD_Index (int cd_drive, int timeout)\n\t{\n\tchar\t\tvolume_name[128];\n\tchar\t\tbuffer[128];\n\tunsigned\tfilename_length;\n\tunsigned\tmisc_dword;\n\tint\t\tcount = 0;\n\n\tCountDownTimerClass timer;\n\n\ttimer.Set(timeout);\n\n\t/*\n\t** Get the volume label. If we get a 'not ready' error then retry for the timeout\n\t** period.\n\t*/\n\tfor (;;)\n\t\t{\n\t\tsprintf(buffer, \"%c:\\\\\", 'A' + cd_drive);\n\n\t\tif (GetVolumeInformation ((char const *)buffer, &volume_name[0] ,\n\t\t\t\t(unsigned long)sizeof(volume_name), (unsigned long *)NULL ,\n\t\t\t\t(unsigned long *)&filename_length, (unsigned long *)&misc_dword,\n\t\t\t\t(char *)NULL, (unsigned long)0))\n\t\t\t{\n\t\t\t/*\n\t\t\t** Try opening 'movies.mix' to verify that the CD is really there and is what\n\t\t\t** it says it is.\n\t\t\t*/\n\t\t\tsprintf(buffer, \"%c:\\\\main.mix\", 'A' + cd_drive);\n\n\t\t\tHANDLE handle = CreateFile(buffer, GENERIC_READ, FILE_SHARE_READ,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n\n\t\t\tif (handle != INVALID_HANDLE_VALUE)\n\t\t\t\t{\n\t\t\t\tCloseHandle(handle);\n\n\t\t\t\t/*\n\t\t\t\t** Match the volume label to the list of known C&C volume labels.\n\t\t\t\t*/\n\t\t\t\tfor (int i = 0 ; i < _Num_Volumes; i++)\n\t\t\t\t\t{\n\t\t\t\t\tif (!stricmp(_CD_Volume_Label[i], volume_name))\n\t\t\t\t\t\treturn(i);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif (!count)\n\t\t\t\t\tcount++;\n\t\t\t\telse\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/*\n\t\t\t** Failed to get the volume label on a known CD drive.\n\t\t\t** If this is a CD changer it may require time to swap the disks so dont return\n\t\t\t** immediately if the error is ROR_NOT_READY\n\t\t\t*/\n\t\t\tif (!timer.Time())\n\t\t\t\treturn -1;\n\t\t\t\t\n\t\t\tint val = GetLastError();\n\t\t\t\n\t\t\tif (val != ROR_NOT_READY)\n\t\t\t\treturn -1;\n\t\t\t}\t\n\t\t}\n\t}\n#else\nint Get_CD_Index(int cd_drive, int)\n\t{\n\tchar buffer[128];\n\n\t/*\n\t** We need to do this twice because of the possibilities of a directory\n\t** being cached.  If this is so, it will only be discovered when we\n\t** actually attempt to read a file from the drive.\n\t*/\n\tif(cd_drive) for (int count = 0; count < 2; count ++)\n\t\t{\n\t\tstruct find_t ft;\n\t\tint file;\n\t\tint open_failed;\n\n\t\t/*\n\t\t** Create a path for the cd drive and attempt to read the volume label from\n\t\t** it.\n\t\t*/\n\t\tsprintf(buffer, \"%c:\\\\\", 'A' + cd_drive);\n\n\t\t/*\n\t\t** If we are able to read the volume label, this is good but not enough.\n\t\t** Further verification must be done.\n\t\t*/\n\t\tif (!_dos_findfirst(buffer, _A_VOLID, &ft))\n\t\t\t{\n\t\t\t/*\n\t\t\t** Since some versions of disk cacheing software will cache the CD's\n\t\t\t** directory tracks, we may think the CD is in the drive when it is\n\t\t\t** actually not.  To resolve this we must attempt to open a file on\n\t\t\t** the cd.  Opening a file will always update the directory tracks\n\t\t\t** (suposedly).\n\t\t\t*/\n\t\t\tsprintf(buffer, \"%c:\\\\main.mix\", 'A' + cd_drive);\n\t\t\topen_failed = _dos_open(buffer, O_RDONLY|SH_DENYNO, &file);\n\n\t\t\tif (!open_failed)\n\t\t\t\t{\n\t\t\t\t_dos_close(file);\n\n\t\t\t\t/*\n\t\t\t\t** Hey some times the stupid dos driver appends a period to the\n\t\t\t\t** name if it is eight characters long.  If the last char is a\n\t\t\t\t** period then erase it.\n\t\t\t\t*/\n\t\t\t\tif (ft.name[strlen(ft.name)-1] == '.')\n\t\t\t\t\t{\n\t\t\t\t\tft.name[strlen(ft.name)-1] = 0;\n\t\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Match the volume label to the list of known C&C volume labels.\n\t\t\t\t*/\n\t\t\t\tfor (int i = 0 ; i < _Num_Volumes; i++)\n\t\t\t\t\t{\n\t\t\t\t\tif (!stricmp(_CD_Volume_Label[i], ft.name))\n\t\t\t\t\t\treturn (i);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\treturn -1;\n\t}\n#endif\n\n\n/***********************************************************************************************\n * Force_CD_Available -- Ensures that specified CD is available.                               *\n *                                                                                             *\n *    Call this routine when you need to ensure that the specified CD is actually in the       *\n *    CD-ROM drive.                                                                            *\n *                                                                                             *\n * INPUT:   cd    -- The CD that must be available. This will either be \"0\" for the GDI CD, or *\n *                   \"1\" for the Nod CD. If either CD will qualify, then pass in \"-1\".         *\n *                0  = CD1\n *                1  = CD2\n *                2  = Counterstrike\n *                3  = Aftermath\n *                4  = Counterstrike or Aftermath\n *                5  = DVD\n *                -1 = Any CD\n *                -2 = Local Harddisk\n *                                                                                             *\n * OUTPUT:  Is the CD inserted and available? If false is returned, then this indicates that   *\n *          the player pressed <CANCEL>.                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1995 JLB : Created.                                                                 *\n *   05/22/1996  ST : Handles multiple CD drives / CD changers                                 *\n *   01/20/1997 V.Grippi added expansion cd message\n *=============================================================================================*/\n\ntypedef enum {\n\tCD_LOCAL = -2,\n\tCD_ANY = -1,\n\tCD_SOVIET = 0,\n\tCD_ALLIED,\n\tCD_COUNTERSTRIKE,\n\tCD_AFTERMATH,\n\tCD_CS_OR_AM,\n\tCD_DVD\n} CD_VOLUME;\n\n#ifdef FIXIT_VERSION_3\n\n#ifndef DVD\n#error DVD must be defined!\n#endif\n\nbool Force_CD_Available( int cd_desired )\t\t\t\t//\tajw\n{\n\tstatic int _last = -1;\n\tstatic void *font;\n#ifdef FRENCH\n\tstatic char * _cd_name[] = {\n\t\t\"ALERTE ROUGE CD1\",\n\t\t\"ALERTE ROUGE CD2\",\n\t\t\"CD Missions Taiga\",\n\t\t\"CD Missions M.A.D.\",\n\t\t\"ALERTE ROUGE DVD\",\n};\n#endif\n#ifdef GERMAN\n\tstatic char * _cd_name[] = {\n\t\t\"ALARMSTUFE ROT CD1\",\n\t\t\"ALARMSTUFE ROT CD2\",\n\t\t\"CD Gegenangriff einlegen\",\n\t\t\"CD TRANS einlegen\",\n\t\t\"ALARMSTUFE ROT DVD\",\n\t};\n#endif\n#ifdef ENGLISH\n\tstatic char * _cd_name[] = {\n\t\t\"RED ALERT DISK 1\",\n\t\t\"RED ALERT DISK 2\",\n\t\t\"CounterStrike CD\",\n\t\t\"Aftermath CD\",\n\t\t\"RED ALERT DVD\",\n\t};\n#endif\n\n\tint new_cd_drive = 0;\n\tint cd_current;\n\tint current_drive;\n\n\tThemeType theme_playing = THEME_NONE;\n\n\t/*\n\t** If the required CD is set to -2 then it means that the file is present\n\t** on the local hard drive and we shouldn't have to worry about it.\n\t*/\n\tif (cd_desired == CD_LOCAL) return(true);\n\n\t/*\n\t** Find out if the CD in the current drive is the one we are looking for\n \t*/\n\tcurrent_drive = CCFileClass::Get_CD_Drive();\n\tcd_current = Get_CD_Index(current_drive, 1*60);\n\n//\tdebugprint(\"Get_CD_Index just returned %d\\n\", cd_current);\n//\tdebugprint(\"We are checking for %d\\n\", cd_desired);\n//\tdebugprint(\"current_drive = %d\\n\", current_drive);\n\n\tif( Using_DVD() )\n\t{\n\t\t//\tAll requested cd indexes get rerouted to the DVD.\n\t\tcd_desired = CD_DVD;\n//\t\tif( RequiredCD != -1 )\n//\t\t\tRequiredCD = CD_DVD;\t\t//\tJust seems like a good idea. Not sure if necessary.\tajw\n\t}\n\n\tif (cd_current >= 0 )\n\t{\n\t\tif( cd_desired == CD_CS_OR_AM )\n\t\t{\n\t\t\t// If the current cd is CS or AM then change request to whatever\n\t\t\t// is present.\n\t\t\tif( cd_current == CD_COUNTERSTRIKE || cd_current == CD_AFTERMATH )\n\t\t\t\tcd_desired = cd_current;\n\t\t}\n\t\t// If the current CD is requested or any CD will work\n\t\tif( cd_desired == cd_current || cd_desired == CD_ANY )\n\t\t{\n\t\t\t/*\n\t\t\t** The required CD is still in the CD drive we used last time\n\t\t\t*/\n\t\t\tnew_cd_drive = current_drive;\n\t\t}\n\t}\n\n\t/*\n\t** Flag that we will have to restart the theme\n\t*/\n\ttheme_playing = Theme.What_Is_Playing();\n\tTheme.Stop();\n\n\t// Check the last drive\n\tif (!new_cd_drive)\n\t{\n\t\t/*\n\t\t** Check the last CD drive we used if it's different from the current one\n\t\t*/\n\t\tint last_drive = CCFileClass::Get_Last_CD_Drive();\n\n\t\t/*\n\t\t** Make sure the last drive is valid and it isn't the current drive\n\t\t*/\n\t\tif (last_drive && last_drive != CCFileClass::Get_CD_Drive())\t\t//\tElse we have already checked this cd.\n\t\t{\n\t\t\t/*\n\t\t\t** Find out if there is a C&C cd in the last drive and if so is it the one we are looking for\n\t\t\t** Give it a nice big timeout so the CD changer has time to swap the discs\n\t\t\t*/\n\t\t\tcd_current = Get_CD_Index(last_drive, 10*60);\n\n\t\t\tif (cd_current >= 0 )\n\t\t\t{\n\t\t\t\tif( cd_desired == CD_CS_OR_AM )\n\t\t\t\t{\n\t\t\t\t\t// If the cd is CS or AM then change request to whatever\n\t\t\t\t\t// is present.\n\t\t\t\t\tif( cd_current == CD_COUNTERSTRIKE || cd_current == CD_AFTERMATH )\n\t\t\t\t\t\tcd_desired = cd_current;\n\t\t\t\t}\n\t\t\t\t// If the cd is present or any cd will work\n\t\t\t\tif( cd_desired == cd_current || cd_desired == CD_ANY )\n\t\t\t\t{\n\t\t\t\t\t/*\n\t\t\t\t\t** The required CD is in the CD drive we used last time\n\t\t\t\t\t*/\n\t\t\t\t\tnew_cd_drive = last_drive;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Lordy.  No sign of that blimming CD anywhere. Search all the CD drives\n\t** then if we still can't find it prompt the user to insert it.\n\t*/\n\tif (!new_cd_drive)\n\t{\n\t\t/*\n\t\t** Small timeout for the first pass through the drives\n\t\t*/\n\t\tint drive_search_timeout = 2*60;\n\n\t\tfor (;;)\n\t\t{\n\t\t\tchar buffer[128];\n\t\t\t/*\n\t\t\t** Search all present CD drives for the required disc.\n\t\t\t*/\n\t\t\tfor (int i = 0 ; i < CDList.Get_Number_Of_Drives(); i++)\n\t\t\t{\n\t\t\t\tint cd_drive = CDList.Get_Next_CD_Drive();\n\t\t\t\tcd_current = Get_CD_Index(cd_drive, drive_search_timeout);\n\n\t\t\t\tif (cd_current >= 0)\n\t\t\t\t{\n\t\t\t\t\t/*\n\t\t\t\t\t** We found a C&C cd - lets see if it was the one we were looking for\n\t\t\t\t\t*/\n\t\t\t\t\t// Require CS or AM\n\t\t\t\t\tif( cd_desired == CD_CS_OR_AM )\n\t\t\t\t\t{\n\t\t\t\t\t\t// If the cd is CS or AM then change request to whatever\n\t\t\t\t\t\t// is present.\n\t\t\t\t\t\tif( cd_current == CD_COUNTERSTRIKE || cd_current == CD_AFTERMATH )\n\t\t\t\t\t\t\tcd_desired = cd_current;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif( cd_desired == cd_current || cd_desired == CD_ANY )\n\t\t\t\t\t{\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Woohoo! The disk was in a different cd drive. Refresh the search path list\n\t\t\t\t \t\t* and return.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tnew_cd_drive = cd_drive;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** A new disc has become available so break\n\t\t\t*/\n\t\t\tif (new_cd_drive) break;\n\n\t\t\t/*\n\t\t\t** Increase the timeout for subsequent drive searches.\n\t\t\t*/\n\t\t\tdrive_search_timeout = 5*60;\n\n\t\t\t/*\n\t\t\t**\tPrompt to insert the CD into the drive.\n\t\t\t*/\n\t\t\t//V.Grippi\n\t\t\tif( cd_desired == CD_CS_OR_AM )\n\t\t\t\tcd_desired = CD_AFTERMATH;\n\t\t\t\n\t\t\tif( cd_desired == CD_DVD )\n\t\t\t{\n\t\t\t\t#ifdef FRENCH\n\t\t\t   \tsprintf(buffer, \"Insrez le %s\",  _cd_name[4]);\n\t\t\t\t#else\n\t\t\t\t#ifdef GERMAN\n\t\t\t\tsprintf(buffer, \"Bitte %s\",  _cd_name[4]);\n\t\t\t\t#else\n\t\t\t\tsprintf(buffer, \"Please insert the %s\",  _cd_name[4]);\n\t\t\t\t#endif\n\t\t\t\t#endif\n\t\t\t}\n\t\t\telse if( cd_desired == CD_COUNTERSTRIKE || cd_desired == CD_AFTERMATH )\n\t\t\t{\n\t\t\t\t#ifdef FRENCH\n\t\t\t   \tsprintf(buffer, \"Insrez le %s\",  _cd_name[cd_desired]);\n\t\t\t\t#else\n\t\t\t\t#ifdef GERMAN\n\t\t\t\tsprintf(buffer, \"Bitte %s\",  _cd_name[cd_desired]);\n\t\t\t\t#else\n\t\t\t\tsprintf(buffer, \"Please insert the %s\",  _cd_name[cd_desired]);\n\t\t\t\t#endif\n\t\t\t\t#endif\n\t\t\t}\n\t\t\telse if( cd_desired == CD_ANY )\n\t\t\t{\n\t\t\t\tsprintf(buffer, Text_String(TXT_CD_DIALOG_1), cd_desired+1, _cd_name[cd_desired]);\n\t\t\t}\n\t\t\telse\t\t//\t0 or 1\n\t\t\t{\n\t\t\t\tsprintf(buffer, Text_String(TXT_CD_DIALOG_2), cd_desired+1, _cd_name[cd_desired]);\n\t\t\t}\n\n\t\t\tGraphicViewPortClass * oldpage = Set_Logic_Page(SeenBuff);\n\t\t\ttheme_playing = Theme.What_Is_Playing();\n\t\t\tTheme.Stop();\n\t\t\tint hidden = Get_Mouse_State();\n\t\t\tfont = (void *)FontPtr;\n\n\t\t\t/*\n\t\t\t**\tOnly set the palette if necessary.\n\t\t\t*/\n\t\t\tif (PaletteClass::CurrentPalette[1].Red_Component() +\n\t\t\t\t\tPaletteClass::CurrentPalette[1].Blue_Component() +\n\t\t\t\t\tPaletteClass::CurrentPalette[1].Green_Component() == 0)\n\t\t\t{\n\t\t\t\tGamePalette.Set();\n\t\t\t}\n\n\t\t\tKeyboard->Clear();\n\n\t\t\twhile (Get_Mouse_State()) Show_Mouse();\n\n\t\t\tif (WWMessageBox().Process(buffer, TXT_OK, TXT_CANCEL, TXT_NONE, TRUE) == 1)\n\t\t\t{\n\t\t\t\tSet_Logic_Page(oldpage);\n#ifdef FIXIT_VERSION_3\n\t\t\t\twhile (hidden--) Hide_Mouse();\n#else\n\t\t\t\tHide_Mouse();\n#endif\n\t\t\t\treturn(false);\n\t\t\t}\n\n\t\t\twhile (hidden--) Hide_Mouse();\n\t\t\tSet_Font(font);\n\t\t\tSet_Logic_Page(oldpage);\n\t\t}\n\t}\n\n\tCurrentCD = cd_current;\n\n\tCCFileClass::Set_CD_Drive(new_cd_drive);\n\tCCFileClass::Refresh_Search_Drives();\n\n\t/*\n\t**\tIf it broke out of the query for CD-ROM loop, then this means that the\n\t**\tCD-ROM has been inserted.\n\t*/\n\tif (cd_desired == 4) cd_desired--;\n\n\t//\tajw - Added condition of cd_desired != 5 to the following if.\n\t//\tReason: This was triggering before Init_Secondary_Mixfiles(), which was screwing up the mixfile system somehow.\n\t//\n\t//\tSince the DVD is the only disk that can possibly be required when Using_DVD(), I never have to reload the mix\n\t//\tfiles here, because no other disk could ever have been asked for. And if not Using_DVD(), cd_desired will never\n\t//\tbe equal to 5. So this is safe.\n\tif (cd_desired > -1 && _last != cd_desired && cd_desired != 5)\n\t{\n\t\t_last = cd_desired;\n\n\t\tTheme.Stop();\n\n//\t\tif (ConquerMix) delete ConquerMix;\n\t\tif (MoviesMix) delete MoviesMix;\n\t\tif (GeneralMix) delete GeneralMix;\n\t\tif (ScoreMix) delete ScoreMix;\n\t\tif (MainMix) delete MainMix;\n\n\t\tMainMix = new MFCD(\"MAIN.MIX\", &FastKey);\n\t\tassert(MainMix != NULL);\n//\t\tConquerMix = new MFCD(\"CONQUER.MIX\", &FastKey);\n\t\tif (CCFileClass(\"MOVIES1.MIX\").Is_Available())\n\t\t\tMoviesMix = new MFCD(\"MOVIES1.MIX\", &FastKey);\n\t\telse\n\t\t\tMoviesMix = new MFCD(\"MOVIES2.MIX\", &FastKey);\n\t\tassert(MoviesMix != NULL);\n\t\tGeneralMix = new MFCD(\"GENERAL.MIX\", &FastKey);\n\t\tScoreMix = new MFCD(\"SCORES.MIX\", &FastKey);\n\t\tThemeClass::Scan();\n\t}\n\n\treturn(true);\n}\n\n#else\t\t//\tFIXIT_VERSION_3 not defined\n\nbool Force_CD_Available(int cd)\n{\n\tstatic int _last = -1;\n//\tstatic char _palette[768];\n//\tstatic char _hold[256];\n\tstatic void *font;\n#ifdef FRENCH\n\tstatic char * _cd_name[] = {\n\t\t\"ALERTE ROUGE CD1\",\n\t\t\"ALERTE ROUGE CD2\",\n\t\t\"CD Missions Taiga\",\n\t\t\"CD Missions M.A.D.\",\n\n\t\t// Denzil 4/15/98\n\t\t#ifdef DVD\n\t\t\"ALERTE ROUGE DVD\",\n\t\t#endif\n};\n\n#endif\n#ifdef GERMAN\n\tstatic char * _cd_name[] = {\n\t\t\"ALARMSTUFE ROT CD1 einlegen\",\n\t\t\"ALARMSTUFE ROT CD2 einlegen\",\n\t\t\"CD Gegenangriff einlegen\",\n\t\t\"CD TRANS einlegen\",\n\n\t\t// Denzil 4/15/98\n\t\t#ifdef DVD\n\t\t\"ALARMSTUFE ROT DVD einlegen\",\n\t\t#endif\n\t};\n#endif\n#ifdef ENGLISH\n\tstatic char * _cd_name[] = {\n\t\t\"RED ALERT DISK 1\",\n\t\t\"RED ALERT DISK 2\",\n\t\t\"CounterStrike CD\",\n\t\t\"Aftermath CD\",\n\n\t\t// Denzil 4/15/98\n\t\t#ifdef DVD\n\t\t\"RED ALERT DVD\",\n\t\t#endif\n\t};\n#endif\n\n\tint new_cd_drive = 0;\n\tint cd_index;\n\tchar buffer[128];\n\tint cd_drive;\n\tint current_drive;\n\tint drive_search_timeout;\n\n\tThemeType theme_playing = THEME_NONE;\n\n//#ifdef FIXIT_ANTS\n//\tif(Scen.ScenarioName[2] == 'A')\n//\t   cd = 2;\n//#endif\n\t/*\n\t** If the required CD is set to -2 then it means that the file is present\n\t** on the local hard drive and we shouldn't have to worry about it.\n\t*/\n\tif (cd == CD_LOCAL) return(true);\n\n\t/*\n\t** Find out if the CD in the current drive is the one we are looking for\n \t*/\n\tcurrent_drive = CCFileClass::Get_CD_Drive();\n\tcd_index = Get_CD_Index(current_drive, 1*60);\n\n\t#ifdef CHEAT_KEYS\n\t//\tMono_Printf(\"Get_CD_Index just returned %d\\n\", cd_index);\n\t//\tMono_Printf(\"We are checking for %d\\n\", cd);\n\t//\tMono_Printf(\"current_drive = %d\\n\", current_drive);\n\t#endif\t//CHEAT_KEYS\n\n\t#ifdef DVD // Denzil\n\t// CD1 and CD2 are ignored, force the DVD\n\tif (cd_index == 0 || cd_index == 1)\n\t\tcd_index = -1;\n\t#endif\n\t\n\tif (cd_index >= 0 )\n\t\t{\n\t\t#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t// Require CS or AM\n\t\tif (cd == CD_CS_OR_AM)\n\t\t\t{\n\t\t\t// If the current cd is CS or AM then change request to whatever\n\t\t\t// is present.\n\t\t\tif (cd_index == 2 || cd_index == 3)\n\t\t\t\t{\n\t\t\t\tcd = cd_index;\n\t\t\t\t}\n\t\t\t}\n\t\t#endif\n\n\t\t#ifdef DVD // Denzil\n\t\t// If the current drive is the DVD then requests for CD1 and CD2 are okay\n\t\tif (cd_index == 4)\n\t\t\t{\n\t\t\t// CD1, CD2 & DVD requests\n\t\t\tif (cd == 0 || cd == 1 || cd == 5)\n\t\t\t\t{\n\t\t\t\tcd_index = cd;\n\t\t\t\t}\n\t\t\t}\n\t\t#endif\n\t\t\n\t\t// If the current CD is requested or any CD will work\n\t\tif (cd == cd_index || cd == -1 )\n\t\t\t{\n\t\t\t/*\n\t\t\t** The required CD is still in the CD drive we used last time\n\t\t\t*/\n\t\t\tnew_cd_drive = current_drive;\n\t\t\t}\n\t\t}\n\n\t/*\n\t** Flag that we will have to restart the theme\n\t*/\n\ttheme_playing = Theme.What_Is_Playing();\n\tTheme.Stop();\n\n\t// Check the last drive\n\tif (!new_cd_drive)\n\t\t{\n\t\t/*\n\t\t** Check the last CD drive we used if it's different from the current one\n\t\t*/\n\t\tint last_drive = CCFileClass::Get_Last_CD_Drive();\n\n\t\t/*\n\t\t** Make sure the last drive is valid and it isn't the current drive\n\t\t*/\n\t\tif (last_drive && last_drive != CCFileClass::Get_CD_Drive())\n\t\t\t{\n\t\t\t/*\n\t\t\t** Find out if there is a C&C cd in the last drive and if so is it the one we are looking for\n\t\t\t** Give it a nice big timeout so the CD changer has time to swap the discs\n\t\t\t*/\n\t\t\tcd_index = Get_CD_Index(last_drive, 10*60);\n\n\t\t\t#ifdef DVD // Denzil\n\t\t\t// Ignore CD1 and CD2 disks, force DVD\n\t\t\tif (cd_index == 0 || cd_index == 1)\n\t\t\t\tcd_index = -1;\n\t\t\t#endif\n\t\t\t\n\t\t\tif (cd_index >= 0 )\n\t\t\t\t{\n\t\t\t\t#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t// Require CS or AM\n\t\t\t\tif (cd == 4)\n\t\t\t\t\t{\n\t\t\t\t\t// If CS or AM was the last drive then use it\n\t\t\t\t\tif (cd_index == 2 || cd_index == 3)\n\t\t\t\t\t\t{\n\t\t\t\t\t\tcd = cd_index;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\t#ifdef DVD // Denzil\n\t\t\t\t// If DVD is in drive\n\t\t\t\tif (cd_index == 4)\n\t\t\t\t\t{\n\t\t\t\t\t// CD1, CD2 and DVD requests are all on the DVD \n\t\t\t\t\tif ((cd == 0) || (cd == 1) || (cd == 5))\n\t\t\t\t\t\t{\n\t\t\t\t\t\tcd_index = cd;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\t// If the cd is present or any cd will work\n\t\t\t\tif (cd == cd_index || cd == -1 )\n\t\t\t\t\t{\n\t\t\t\t\t/*\n\t\t\t\t\t** The required CD is in the CD drive we used last time\n\t\t\t\t\t*/\n\t\t\t\t\tnew_cd_drive = last_drive;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/*\n\t** Lordy.  No sign of that blimming CD anywhere. Search all the CD drives\n\t** then if we still can't find it prompt the user to insert it.\n\t*/\n\tif (!new_cd_drive)\n\t\t{\n\t\t/*\n\t\t** Small timeout for the first pass through the drives\n\t\t*/\n\t\tdrive_search_timeout = 2*60;\n\n\t\tfor (;;)\n\t\t\t{\n\t\t\t/*\n\t\t\t** Search all present CD drives for the required disc.\n\t\t\t*/\n\t\t\tfor (int i = 0 ; i < CDList.Get_Number_Of_Drives(); i++)\n\t\t\t\t{\n\t\t\t\tcd_drive = CDList.Get_Next_CD_Drive();\n\t\t\t\tcd_index = Get_CD_Index(cd_drive, drive_search_timeout);\n\n\t\t\t\t#ifdef DVD // Denzil\n\t\t\t\t// Ignore CD1 and CD2, force the DVD\n\t\t\t\tif (cd_index == 0 || cd_index == 1)\n\t\t\t\t\tcd_index = -1;\n\t\t\t\t#endif\n\t\t\t\t\n\t\t\t\tif (cd_index >= 0)\n\t\t\t\t\t{\n\t\t\t\t\t/*\n\t\t\t\t\t** We found a C&C cd - lets see if it was the one we were looking for\n\t\t\t\t\t*/\n\t\t\t\t\t#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t// Require CS or AM\n\t\t\t\t\tif (cd == 4)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t// If the disk is CS or AM then request it\n\t\t\t\t\t\tif (cd_index == 2 || cd_index == 3)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcd = cd_index;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t#endif\n\n\t\t\t\t\t#ifdef DVD // Denzil\n\t\t\t\t\tif (cd_index == 4)\n\t\t\t\t\t\t{\n\t\t\t\t\t\tif ((cd == 0) || (cd == 1) || (cd == 5))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcd_index = cd;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t#endif\n\t\t\t\t\t\n\t\t\t\t\tif (cd == cd_index || cd == -1 || cd == -2 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Woohoo! The disk was in a different cd drive. Refresh the search path list\n\t\t\t\t \t\t* and return.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tnew_cd_drive = cd_drive;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t/*\n\t\t\t** A new disc has become available so break\n\t\t\t*/\n\t\t\tif (new_cd_drive) break;\n\n\t\t\t/*\n\t\t\t** Increase the timeout for subsequent drive searches.\n\t\t\t*/\n\t\t\tdrive_search_timeout = 5*60;\n\n\t\t\t/*\n\t\t\t**\tPrompt to insert the CD into the drive.\n\t\t\t*/\n\t\t\t//V.Grippi\n\t\t\t#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif(cd == 4) cd--;\n\t\t\t\n\t\t\t// CS or AM\n\t\t\tif(cd == 2 || cd == 3)\n\t\t\t\t{\n\t\t\t#else\n\t\t\tif(cd == 2)\n\t\t   \t\t{\n\t\t\t#endif\n\n\t\t\t\t#ifdef FRENCH\n\t\t\t   \tsprintf(buffer, \"Insrez le %s\",  _cd_name[cd]);\n\t\t\t\t#else\n\t\t\t\t#ifdef GERMAN\n\t\t\t\tsprintf(buffer, \"Bitte %s\",  _cd_name[cd]);\n\t\t\t\t#else\n\t\t\t\tsprintf(buffer, \"Please insert the %s\",  _cd_name[cd]);\n\t\t\t\t#endif\n\t\t\t\t#endif\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t#ifdef DVD\n\t\t\t\t#ifdef FRENCH\n\t\t\t   \tsprintf(buffer, \"Insrez le %s\", _cd_name[4]);\n\t\t\t\t#else\n\t\t\t\t#ifdef GERMAN \n\t\t\t\tsprintf(buffer, \"Bitte %s\", _cd_name[4]);\n\t\t\t\t#else\n\t\t\t\tsprintf(buffer, \"Please insert the %s\", _cd_name[4]);\n\t\t\t\t#endif\n\t\t\t\t#endif\n\t\t\t\t#else\n\t\t\t\tif (cd == -1 )\n\t\t\t\t\t{\n\t\t\t\t\tsprintf(buffer, Text_String(TXT_CD_DIALOG_1), cd+1, _cd_name[cd]);\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tsprintf(buffer, Text_String(TXT_CD_DIALOG_2), cd+1, _cd_name[cd]);\n\t\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t\t}\n\n\t\t\t#ifdef WIN32\n\t\t\tGraphicViewPortClass * oldpage = Set_Logic_Page(SeenBuff);\n\t\t\t#else\n\t\t\tGraphicBufferClass * oldpage = Set_Logic_Page(SeenBuff);\n\t\t\t#endif\n\t\t\ttheme_playing = Theme.What_Is_Playing();\n\t\t\tTheme.Stop();\n\t\t\tint hidden = Get_Mouse_State();\n\t\t\tfont = (void *)FontPtr;\n\n\t\t\t/*\n\t\t\t**\tOnly set the palette if necessary.\n\t\t\t*/\n\t\t\tif (PaletteClass::CurrentPalette[1].Red_Component() +\n\t\t\t\t\tPaletteClass::CurrentPalette[1].Blue_Component() +\n\t\t\t\t\tPaletteClass::CurrentPalette[1].Green_Component() == 0)\n\t\t\t\t{\n\t\t\t\tGamePalette.Set();\n\t\t\t\t}\n\n\t\t\tKeyboard->Clear();\n\n\t\t\twhile (Get_Mouse_State()) Show_Mouse();\n\n\t\t\tif (WWMessageBox().Process(buffer, TXT_OK, TXT_CANCEL, TXT_NONE, TRUE) == 1)\n\t\t\t\t{\n\t\t\t\tSet_Logic_Page(oldpage);\n\t\t\t\tHide_Mouse();\n\t\t\t\treturn(false);\n\t\t\t\t}\n\n\t\t\twhile (hidden--) Hide_Mouse();\n\t\t\tSet_Font(font);\n\t\t\tSet_Logic_Page(oldpage);\n\t\t\t}\n\t\t}\n\n\tCurrentCD = cd_index;\n\n\tCCFileClass::Set_CD_Drive(new_cd_drive);\n\tCCFileClass::Refresh_Search_Drives();\n\n\t/*\n\t**\tIf it broke out of the query for CD-ROM loop, then this means that the\n\t**\tCD-ROM has been inserted.\n\t*/\n\t#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (cd == 4) cd--;\n\t#endif\n//\tif (cd > -3 && _last != cd) {\n\tif (cd > -1 && _last != cd)\n\t\t{\n\t\t_last = cd;\n\n\t\tTheme.Stop();\n\n//\t\tif (ConquerMix) delete ConquerMix;\n\t\tif (MoviesMix) delete MoviesMix;\n\t\tif (GeneralMix) delete GeneralMix;\n\t\tif (ScoreMix) delete ScoreMix;\n\t\tif (MainMix) delete MainMix;\n\n\t\tMainMix = new MFCD(\"MAIN.MIX\", &FastKey);\n\t\t\n\t\tassert(MainMix != NULL);\n//\t\tConquerMix = new MFCD(\"CONQUER.MIX\", &FastKey);\n\n\t\tif (CCFileClass(\"MOVIES1.MIX\").Is_Available())\n\t\t\t{\n\t\t\tMoviesMix = new MFCD(\"MOVIES1.MIX\", &FastKey);\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tMoviesMix = new MFCD(\"MOVIES2.MIX\", &FastKey);\n\t\t\t}\n\t\tassert(MoviesMix != NULL);\n\t\tGeneralMix = new MFCD(\"GENERAL.MIX\", &FastKey);\n\t\tScoreMix = new MFCD(\"SCORES.MIX\", &FastKey);\n\t\tThemeClass::Scan();\n\t\t}\n\n\tif (theme_playing != THEME_NONE)\n\t\t{\n\t\tTheme.Queue_Song(theme_playing);\n\t\t}\n\n\treturn(true);\n\t}\n\n\n#endif\t//\tFIXIT_VERSION_3\n\n/***************************************************************************\n * DISK_SPACE_AVAILABLE -- returns bytes of free disk space                *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     returns amount of free disk space                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/11/1995 PWG : Created.                                             *\n *=========================================================================*/\nunsigned long Disk_Space_Available(void)\n{\n\tstruct diskfree_t diskdata;\n\tunsigned drive;\n\n\t_dos_getdrive(&drive);\n\t_dos_getdiskfree(drive, &diskdata);\n\n\treturn(diskdata.avail_clusters * diskdata.sectors_per_cluster * diskdata.bytes_per_sector);\n}\n\n\n/***********************************************************************************************\n * Do_Record_Playback -- handles saving/loading map pos & current object                       *\n *                                                                                             *\n * INPUT:                                                                                      *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/15/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nstatic void Do_Record_Playback(void)\n{\n\tint count;\n\tTARGET tgt;\n\tint i;\n\tCOORDINATE coord;\n\tObjectClass * obj;\n\tunsigned long sum;\n\tunsigned long sum2;\n\tunsigned long ltgt;\n\n\t/*\n\t**\tRecord a game\n\t*/\n\tif (Session.Record) {\n\n\t\t/*\n\t\t**\tSave the map's location\n\t\t*/\n\t\tSession.RecordFile.Write(&Map.DesiredTacticalCoord,\n\t\t\tsizeof (Map.DesiredTacticalCoord));\n\n\t\t/*\n\t\t**\tSave the current object list count\n\t\t*/\n\t\tcount = CurrentObject.Count();\n\t\tSession.RecordFile.Write(&count, sizeof(count));\n\n\t\t/*\n\t\t**\tSave a CRC of the selected-object list.\n\t\t*/\n\t\tsum = 0;\n\t\tfor (i = 0; i < count; i++) {\n\t\t\tltgt = (unsigned long)(CurrentObject[i]->As_Target());\n\t\t\tsum += ltgt;\n\t\t}\n\t\tSession.RecordFile.Write (&sum, sizeof(sum));\n\n\t\t/*\n\t\t**\tSave all selected objects.\n\t\t*/\n\t\tfor (i = 0; i < count; i++) {\n\t\t\ttgt = CurrentObject[i]->As_Target();\n\t\t\tSession.RecordFile.Write (&tgt, sizeof(tgt));\n\t\t}\n\n\t\t//\n\t\t// Save team-selection and formation events\n\t\t//\n\t\tSession.RecordFile.Write (&TeamEvent, sizeof(TeamEvent));\n\t\tSession.RecordFile.Write (&TeamNumber, sizeof(TeamNumber));\n\t\tSession.RecordFile.Write (&FormationEvent, sizeof(FormationEvent));\n\t\tSession.RecordFile.Write (TeamMaxSpeed, sizeof(TeamMaxSpeed));\n\t\tSession.RecordFile.Write (TeamSpeed, sizeof(TeamSpeed));\n\t\tSession.RecordFile.Write (&FormMove, sizeof(FormMove));\n\t\tSession.RecordFile.Write (&FormSpeed, sizeof(FormSpeed));\n\t\tSession.RecordFile.Write (&FormMaxSpeed, sizeof(FormMaxSpeed));\n\t\tTeamEvent = 0;\n\t\tTeamNumber = 0;\n\t\tFormationEvent = 0;\n\t}\n\n\t/*\n\t**\tPlay back a game (\"attract\" mode)\n\t*/\n\tif (Session.Play) {\n\n\t\t/*\n\t\t**\tRead & set the map's location.\n\t\t*/\n\t\tif (Session.RecordFile.Read(&coord, sizeof(coord))==sizeof(coord)) {\n\t\t\tif (coord != Map.DesiredTacticalCoord) {\n\t\t\t\tMap.Set_Tactical_Position(coord);\n\t\t\t}\n\t\t}\n\n\t\tif (Session.RecordFile.Read(&count, sizeof(count))==sizeof(count)) {\n\t\t\t/*\n\t\t\t**\tCompute a CRC of the current object-selection list.\n\t\t\t*/\n\t\t\tsum = 0;\n\t\t\tfor (i = 0; i < CurrentObject.Count(); i++) {\n\t\t\t\tltgt = (unsigned long)(CurrentObject[i]->As_Target());\n\t\t\t\tsum += ltgt;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tLoad the CRC of the objects on disk; if it doesn't match, select\n\t\t\t**\tall objects as they're loaded.\n\t\t\t*/\n\t\t\tSession.RecordFile.Read (&sum2, sizeof(sum2));\n\t\t\tif (sum2 != sum) {\n\t\t\t\tUnselect_All();\n\t\t\t}\n\n\t\t\tAllowVoice = true;\n\n\t\t\tfor (i = 0; i < count; i++) {\n\t\t\t\tif (Session.RecordFile.Read (&tgt, sizeof(tgt))==sizeof(tgt)) {\n\t\t\t\t\tobj = As_Object(tgt);\n\t\t\t\t\tif (obj && (sum2 != sum)) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tAllowVoice = true;\n\n\t\t}\n\n\t\t//\n\t\t// Save team-selection and formation events\n\t\t//\n\t\tSession.RecordFile.Read (&TeamEvent, sizeof(TeamEvent));\n\t\tSession.RecordFile.Read (&TeamNumber, sizeof(TeamNumber));\n\t\tSession.RecordFile.Read (&FormationEvent, sizeof(FormationEvent));\n\t\tif (TeamEvent) {\n\t\t\tHandle_Team(TeamNumber, TeamEvent - 1);\n\t\t}\n\t\tif (FormationEvent) {\n\t\t\tToggle_Formation();\n\t\t}\n\nSession.RecordFile.Read (TeamMaxSpeed, sizeof(TeamMaxSpeed));\nSession.RecordFile.Read (TeamSpeed, sizeof(TeamSpeed));\nSession.RecordFile.Read (&FormMove, sizeof(FormMove));\nSession.RecordFile.Read (&FormSpeed, sizeof(FormSpeed));\nSession.RecordFile.Read (&FormMaxSpeed, sizeof(FormMaxSpeed));\n\t\t/*\n\t\t**\tThe map isn't drawn in playback mode, so draw it here.\n\t\t*/\n\t\tMap.Render();\n\t}\n}\n\n\n/***********************************************************************************************\n * Hires_Load -- Allocates memory for, and loads, a resolution dependant file.                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Name of file to load                                                              *\n *                                                                                             *\n * OUTPUT:   Ptr to loaded file                                                                *\n *                                                                                             *\n * WARNINGS: Caller is responsible for releasing the memory allocated                          *\n *                                                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/13/96 3:20PM ST : Created                                                              *\n *=============================================================================================*/\nvoid * Hires_Load(char * name)\n{\n\tchar \tfilename[30];\n\tint \tlength;\n\tvoid * return_ptr;\n\n#ifdef WIN32\n\tsprintf(filename, \"H%s\", name);\n#else\n   strcpy(filename, name);\n#endif\n\tCCFileClass file (filename);\n\n\tif (file.Is_Available()) {\n\n\t\tlength = file.Size();\n\t\treturn_ptr = new char[length];\n\t\tfile.Read(return_ptr, length);\n\t\treturn (return_ptr);\n\n\t} else {\n\t\treturn (NULL);\n\t}\n}\n\n\n/***********************************************************************************************\n * Crate_From_Name -- Given a crate name convert it to a crate type.                           *\n *                                                                                             *\n *    Use this routine to convert an ASCII crate name into a crate type. If no match could     *\n *    be found, then CRATE_MONEY is assumed.                                                   *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the crate name text to convert into a crate type.              *\n *                                                                                             *\n * OUTPUT:  Returns with the crate name converted into a crate type.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCrateType Crate_From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (CrateType crate = CRATE_FIRST; crate < CRATE_COUNT; crate++) {\n\t\t\tif (stricmp(name, CrateNames[crate]) == 0) return(crate);\n\t\t}\n\t}\n\treturn(CRATE_MONEY);\n}\n\n\n/***********************************************************************************************\n * Owner_From_Name -- Convert an owner name into a bitfield.                                   *\n *                                                                                             *\n *    This will take an owner specification and convert it into a bitfield that represents     *\n *    it. Sometimes this will be just a single house bit, but other times it could be          *\n *    all the allies or soviet house bits combined.                                            *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text to convert into a house bitfield.                     *\n *                                                                                             *\n * OUTPUT:  Returns with the houses specified. The value is in the form of a bit field with    *\n *          one bit per house type.                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Owner_From_Name(char const * text)\n{\n\tint ownable = 0;\n\tif (stricmp(text, \"soviet\") == 0) {\n\t\townable |= HOUSEF_SOVIET;\n\t} else {\n\t\tif (stricmp(text, \"allies\") == 0 || stricmp(text, \"allied\") == 0) {\n\t\t\townable |= HOUSEF_ALLIES;\n\t\t} else {\n\t\t\tHousesType h = HouseTypeClass::From_Name(text);\n\t\t\tif (h != HOUSE_NONE && (h < HOUSE_MULTI1 || h > HOUSE_MULTI8)) {\n\t\t\t\townable |= (1 << h);\n\t\t\t}\n\t\t}\n\t}\n\treturn(ownable);\n}\n\n\n/***********************************************************************************************\n * Shake_The_Screen -- Dispatcher that shakes the screen.                                      *\n *                                                                                             *\n *    This routine will shake the game screen the number of shakes requested.                  *\n *                                                                                             *\n * INPUT:   shakes   -- The number of shakes to shake the screen.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/04/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid Shake_The_Screen(int shakes)\n{\n#ifdef WIN32\n\tshakes += shakes;\n\n\tHide_Mouse();\n\tSeenPage.Blit(HidPage);\n\tint oldyoff = 0;\n\tint newyoff = 0;\n\twhile(shakes--) {\n\t\tint x = TickCount;\n//\t\tCountDownTimer = 1;\n\t\tdo {\n\t\t\tnewyoff = Sim_Random_Pick(0,2) - 1;\n\t\t} while (newyoff == oldyoff);\n\t\tswitch (newyoff) {\n\t\t\tcase -1:\n\t\t\t\tHidPage.Blit(SeenPage, 0,2, 0,0, 640,398);\n\t\t\t\tbreak;\n\t\t\tcase 0:\n\t\t\t\tHidPage.Blit(SeenPage);\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tHidPage.Blit(SeenPage, 0,0, 0,2, 640,398);\n\t\t\t\tbreak;\n\t\t} while (x == TickCount);\n//\t\t} while (CountDownTimer != 0) ;\n\t}\n\tHidPage.Blit(SeenPage);\n\tShow_Mouse();\n#else\n\tShake_Screen(shakes);\n#endif\n}\n\n\n/***********************************************************************************************\n * List_Copy -- Makes a copy of a cell offset list.                                            *\n *                                                                                             *\n *    This routine will make a copy of a cell offset list. It will only copy the significant   *\n *    elements of the list limited by the maximum length specified.                            *\n *                                                                                             *\n * INPUT:   source   -- Pointer to a cell offset list.                                         *\n *                                                                                             *\n *          len      -- The maximum number of cell offset elements to store in to the          *\n *                      destination list pointer.                                              *\n *                                                                                             *\n *          dest     -- Pointer to the destination list to store the copy into.                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Ensure that the destination list is large enough to hold the list copy.         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid List_Copy(short const * source, int len, short * dest)\n{\n\tif (dest == NULL || dest == NULL) {\n\t\treturn;\n\t}\n\n\twhile (len > 0) {\n\t\t*dest = *source;\n\t\tif (*dest == REFRESH_EOL) break;\n\t\tdest++;\n\t\tsource++;\n\t\tlen--;\n\t}\n}\n\n\n\n#if 0\n//\n// Boy, this function sure is crummy\n//\nvoid Crummy(int crumb1, int crumb2)\n{\n\tif (Debug_Check_Map && Debug_Heap_Dump) {\n\t\tMono_Printf(\"Hi, I'm Crummy.  And so are these: %d, %d\\n\",crumb1,crumb2);\n\t}\n}\n#endif\n\n\n\n/***********************************************************************************************\n * Game_Registry_Key -- Returns pointer to string containing the registry subkey for the game.\n *                      This is located under HKEY_LOCAL_MACHINE.\n * HISTORY:\n *    11/19/98 ajw : Created\n *=============================================================================================*/\nconst char* Game_Registry_Key()\n{\n#ifdef ENGLISH\n\tstatic char szKey[] = \"SOFTWARE\\\\Westwood\\\\Red Alert Windows 95 Edition\";\n#else\n#ifdef GERMAN\n\tstatic char szKey[] = \"SOFTWARE\\\\Westwood\\\\Alarmstufe Rot Windows 95 Edition\";\n#else\n\tstatic char szKey[] = \"SOFTWARE\\\\Westwood\\\\Alerte Rouge version Windows 95\";\n#endif\n#endif\n\treturn szKey;\n}\n\n\n/***********************************************************************************************\n * Is_Counterstrike_Installed -- Function to determine the availability of the CS expansion    *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   true if Counterstrike is present                                                  *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    4/1/97 11:39PM ST : Created                                                              *\n *=============================================================================================*/\nbool Is_Counterstrike_Installed (void)\n{\n\t//\tajw 9/29/98\n\tstatic bool\tbAlreadyChecked = false;\n\tstatic bool bInstalled = false;\n\n\tif( !bAlreadyChecked )\n\t{\n\t\tHKEY hKey;\n\t\tif( RegOpenKeyEx( HKEY_LOCAL_MACHINE, Game_Registry_Key(), 0, KEY_READ, &hKey ) != ERROR_SUCCESS )\n\t\t\treturn false;\n\t\tDWORD dwValue;\n\t\tDWORD dwBufSize = sizeof( DWORD );\n\t\tif( RegQueryValueEx( hKey, \"CStrikeInstalled\", 0, NULL, (LPBYTE)&dwValue, &dwBufSize ) != ERROR_SUCCESS )\n\t\t\tbInstalled = false;\n\t\telse\n\t\t\tbInstalled = (bool)dwValue;\t\t\t//\t(Presumably true, if it's there...)\n\n\t\tRegCloseKey( hKey );\n\t\tbAlreadyChecked = true;\n\t}\n\treturn bInstalled;\n\n//\tRawFileClass file(\"EXPAND.MIX\");\n//\treturn(file.Is_Available());\n}\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n/***********************************************************************************************\n *=============================================================================================*/\nbool Is_Aftermath_Installed (void)\n{\n\t//\tajw 9/29/98\n\tstatic bool\tbAlreadyChecked = false;\n\tstatic bool bInstalled = false;\n\n\tif( !bAlreadyChecked )\n\t{\n\t\tHKEY hKey;\n\t\tif( RegOpenKeyEx( HKEY_LOCAL_MACHINE, Game_Registry_Key(), 0, KEY_READ, &hKey ) != ERROR_SUCCESS )\n\t\t\treturn false;\n\t\tDWORD dwValue;\n\t\tDWORD dwBufSize = sizeof( DWORD );\n\t\tif( RegQueryValueEx( hKey, \"AftermathInstalled\", 0, NULL, (LPBYTE)&dwValue, &dwBufSize ) != ERROR_SUCCESS )\n\t\t\tbInstalled = false;\n\t\telse\n\t\t\tbInstalled = (bool)dwValue;\t\t\t//\t(Presumably true, if it's there...)\n\n\t\tRegCloseKey( hKey );\n\t\tbAlreadyChecked = true;\n\t}\n\treturn bInstalled;\n\n//\tRawFileClass file(\"EXPAND2.MIX\");\n//\treturn(file.Is_Available());\n}\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nvoid Enable_Secret_Units(void)\n{\n#if 0\n\tSecretUnitsEnabled=true;\n\tUnitTypeClass::As_Reference(UNIT_PHASE).Level=10;\n\tVesselTypeClass::As_Reference(VESSEL_CARRIER).Level=10;\n\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\tBuildings.Ptr(index)->Update_Buildables();\n\t}\n#endif\n}\n#endif\n\n#ifdef FIXIT_VERSION_3\nbool Force_Scenario_Available( const char* szName )\n{\n\t//\tCalls Force_CD_Available based on type of scenario. szName is assumed to be an official scenario here.\n\tif( Is_Mission_Counterstrike( (char*)szName ) )\n\t{\n//\t\tdebugprint( \"Force_Scenario_Available requiring disk 4...\\n\" );\n\t\treturn Force_CD_Available( 4 );\n\t}\n\telse if( Is_Mission_Aftermath( (char*)szName ) )\n\t{\n//\t\tdebugprint( \"Force_Scenario_Available requiring disk 3...\\n\" );\n\t\treturn Force_CD_Available( 3 );\n\t}\n\treturn true;\n}\n#endif\n"
  },
  {
    "path": "CODE/CONQUER.CPP.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\conquer.cpv   4.83   24 Oct 1996 12:55:42   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CONQUER.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 3, 1991                                                *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CC_Draw_Shape -- Custom draw shape handler.                                               *\n *   Call_Back -- Main game maintenance callback routine.                                      *\n *   Color_Cycle -- Handle the general palette color cycling.                                  *\n *   Crate_From_Name -- Given a crate name convert it to a crate type.                         *\n *   Disk_Space_Available -- returns bytes of free disk space              \t\t\t\t\t\t  *\n *   Do_Record_Playback -- handles saving/loading map pos & current object                     *\n *   Fading_Table_Name -- Builds a theater specific fading table name.                         *\n *   Fetch_Techno_Type -- Convert type and ID into TechnoTypeClass pointer.                    *\n *   Force_CD_Available -- Ensures that specified CD is available.                             *\n *   Get_Radar_Icon -- Builds and alloc a radar icon from a shape file                         *\n *   Handle_Team -- Processes team selection command.                                          *\n *   Handle_View -- Either records or restores the tactical view.                              *\n *   KN_To_Facing -- Converts a keyboard input number into a facing value.                     *\n *   Keyboard_Process -- Processes the tactical map input codes.                               *\n *   Language_Name -- Build filename for current language.                                     *\n *   List_Copy -- Makes a copy of a cell offset list.                                          *\n *   Main_Game -- Main game startup routine.                                                   *\n *   Main_Loop -- This is the main game loop (as a single loop).                               *\n *   Map_Edit_Loop -- a mini-main loop for map edit mode only                                  *\n *   Message_Input -- allows inter-player message input processing                             *\n *   MixFileHandler -- Handles VQ file access.                                                 *\n *   Name_From_Source -- retrieves the name for the given SourceType                           *\n *   Owner_From_Name -- Convert an owner name into a bitfield.                                 *\n *   Play_Movie -- Plays a VQ movie.                                                           *\n *   Shake_The_Screen -- Dispatcher that shakes the screen.                                    *\n *   Shape_Dimensions -- Determine the minimum rectangle for the shape.                        *\n *   Source_From_Name -- Converts ASCII name into SourceType.                                  *\n *   Sync_Delay -- Forces the game into a 15 FPS rate.                                         *\n *   Theater_From_Name -- Converts ASCII name into a theater number.                           *\n *   Unselect_All -- Causes all selected objects to become unselected.                         *\n *   VQ_Call_Back -- Maintenance callback used for VQ movies.                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifdef TESTCODE\nclass A {\n\tpublic:\n\t\tenum {VAR=1};\n};\n\ntemplate<class T>\nclass B {\n\tpublic:\n\t\tenum {VAR2=T::VAR};  // this is the line in question.\n};\n\nB<A> test;\n#endif\n\n\n\n#include\t\"function.h\"\n#ifdef WIN32\n#include\t\"tcpip.h\"\n#else\n#include\t\"fakesock.h\"\nTcpipManagerClass\tWinsock;\n#endif\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<string.h>\n#include\t<direct.h>\n#include\t<fcntl.h>\n#include\t<io.h>\n#include\t<dos.h>\n#include\t<share.h>\n#include\t\"ccdde.h\"\n#include\t\"vortex.h\"\n\n#define SHAPE_TRANS\t\t0x40\n\nvoid * Get_Shape_Header_Data(void * ptr);\nextern bool Spawn_WChat(void);\n\n/****************************************\n**\tFunction prototypes for this module **\n*****************************************/\nbool Main_Loop(void);\nvoid Keyboard_Process(KeyNumType & input);\nstatic void Message_Input(KeyNumType &input);\nstatic void Color_Cycle(void);\nbool Map_Edit_Loop(void);\n\nextern \"C\" {\n\tbool UseOldShapeDraw = false;\n}\n\n#ifdef CHEAT_KEYS\nvoid Dump_Heap_Pointers( void );\nvoid Error_In_Heap_Pointers( char * string );\n#endif\nstatic void Do_Record_Playback(void);\n\nvoid Toggle_Formation(void);\n\nextern \"C\" {\n\textern char * __nheapbeg;\n}\n\n//\n// Special module globals for recording and playback\n//\nchar TeamEvent = 0;\t\t\t// 0 = no event, 1,2,3 = team event type\nchar TeamNumber = 0;\t\t\t// which team was selected? (1-9)\nchar FormationEvent = 0;\t// 0 = no event, 1 = formation was toggled\n\n\n\t/* -----------------10/14/96 7:29PM------------------\n\n\t --------------------------------------------------*/\n\n/***********************************************************************************************\n * Main_Game -- Main game startup routine.                                                     *\n *                                                                                             *\n *    This is the first official routine of the game. It handles game initialization and       *\n *    the main game loop control.                                                              *\n *                                                                                             *\n *    Initialization:                                                                          *\n *    - Init_Game handles one-time-only inits                                                  *\n *    - Select_Game is responsible for initializations required for each new game played       *\n *      (these may be different depending on whether a multiplayer game is selected, and       *\n *      other parameters)                                                                      *\n *    - This routine performs any un-inits required, both for each game played, and one-time   *\n *                                                                                             *\n * INPUT:   argc  -- Number of command line arguments (including program name itself).         *\n *                                                                                             *\n *          argv  -- Array of command line argument pointers.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Main_Game(int argc, char * argv[])\n{\n\tstatic bool fade = true;\n\n\t/*\n\t**\tPerform one-time-only initializations\n\t*/\n\tif (!Init_Game(argc, argv)) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tGame processing loop:\n\t**\t1) Select which game to play, or whether to exit (don't fade the palette\n\t**\t\ton the first game selection, but fade it in on subsequent calls)\n\t**\t2) Invoke either the main-loop routine, or the editor-loop routine,\n\t**\t\tuntil they indicate that the user wants to exit the scenario.\n\t*/\n\twhile (Select_Game(fade)) {\n\t\tfade = false;\n\t\tScenarioInit = 0;\t\t// Kludge.\n\n\t\tfade = true;\n\n\t\t/*\n\t\t** Initialise the color lookup tables for the chronal vortex\n\t\t*/\n\t\tChronalVortex.Stop();\n\t\tChronalVortex.Setup_Remap_Tables(Scen.Theater);\n\n\t\t/*\n\t\t**\tMake the game screen visible, clear the keyboard buffer of spurious\n\t\t**\tvalues, and then show the mouse.  This PRESUMES that Select_Game() has\n\t\t**\ttold the map to draw itself.\n\t\t*/\n\t\tGamePalette.Set(FADE_PALETTE_MEDIUM);\n\t\tKeyboard->Clear();\n\n\t\t/*\n\t\t** Only show the mouse if we're not playing back a recording.\n\t\t*/\n\t\tif (Session.Play) {\n\t\t\tHide_Mouse();\n\t\t\tTeamEvent = 0;\n\t\t\tTeamNumber = 0;\n\t\t\tFormationEvent = 0;\n\t\t} else {\n\t\t\tShow_Mouse();\n\t\t}\n\n#ifdef WIN32\n\t\tif (Session.Type == GAME_INTERNET) {\n\t\t\tRegister_Game_Start_Time();\n\t\t\tGameStatisticsPacketSent = false;\n\t\t\tPacketLater = NULL;\n\t\t\tConnectionLost = false;\n\t\t} else {\n\t\t\tDDEServer.Disable();\n\t\t}\n#endif\t//WIN32\n\n#ifdef SCENARIO_EDITOR\n\t\t/*\n\t\t**\tScenario-editor version of main-loop processing\n\t\t*/\n\t\tfor (;;) {\n\t\t\t/*\n\t\t\t**\tNon-scenario-editor-mode: call the game's main loop\n\t\t\t*/\n\t\t\tif (!Debug_Map) {\n\t\t\t\tTimeQuake = false;\n\t\t\t\tif (Main_Loop()) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (SpecialDialog != SDLG_NONE) {\n\t\t\t\t\tswitch (SpecialDialog) {\n\t\t\t\t\t\tcase SDLG_SPECIAL:\n\t\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\t\tSpecial_Dialog();\n\t\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase SDLG_OPTIONS:\n\t\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\t\tOptions.Process();\n\t\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase SDLG_SURRENDER:\n\t\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\t\tif (Surrender_Dialog(TXT_SURRENDER)) {\n\t\t\t\t\t\t\t\tPlayerPtr->Flag_To_Lose();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tScenario-editor-mode: call the editor's main loop\n\t\t\t\t*/\n\t\t\t\tif (Map_Edit_Loop()) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#else\n\t\t/*\n\t\t**\tNon-editor version of main-loop processing\n\t\t*/\n\t\tfor (;;) {\n\t\t\tTimeQuake = false;\n\t\t\t/*\n\t\t\t**call the game's main loop\n\t\t\t*/\n\t\t\t//VG_MONO\n\t\t\tMono_Print(\"About to call Main Loop in Main Game/n/n\");\n\n\t\t\tif (Main_Loop()) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the SpecialDialog flag is set, invoke the given special dialog.\n\t\t\t**\tThis must be done outside the main loop, since the dialog will call\n\t\t\t**\tMain_Loop(), allowing the game to run in the background.\n\t\t\t*/\n\t\t\tif (SpecialDialog != SDLG_NONE) {\n\t\t\t\tswitch (SpecialDialog) {\n\t\t\t\t\tcase SDLG_SPECIAL:\n\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\tSpecial_Dialog();\n\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase SDLG_OPTIONS:\n\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\tOptions.Process();\n\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase SDLG_SURRENDER:\n\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\tif (Surrender_Dialog(TXT_SURRENDER)) {\n\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::DESTRUCT));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#endif\n\n\n#ifdef WIN32\n\t\t/*\n\t\t** Send the game stats to WChat if we havnt already done so\n\t\t*/\n\t\tif (!GameStatisticsPacketSent && PacketLater) {\n\t\t\tSend_Statistics_Packet();\n\t\t}\n#endif\t//WIN32\n\n\t\t/*\n\t\t**\tScenario is done; fade palette to black\n\t\t*/\n\t\tBlackPalette.Set(FADE_PALETTE_SLOW);\n\t\tVisiblePage.Clear();\n\n\t\t/*\n\t\t**\tUn-initialize whatever needs it, for each game played.\n\t\t**\n\t\t**\tShut down either the modem or network; they'll get re-initialized if\n\t\t**\tthe user selections those options again in Select_Game().  This\n\t\t**\t\"re-boots\" the modem & network code, which I currently feel is safer\n\t\t**\tthan just letting it hang around.\n\t\t** (Skip this step if we're in playback mode; the modem or net won't have\n\t\t** been initialized in that case.)\n\t\t*/\n\t\tif (Session.Record || Session.Play) {\n\t\t\tSession.RecordFile.Close();\n\t\t}\n\n\t\tif (Session.Type == GAME_NULL_MODEM || Session.Type == GAME_MODEM) {\n\t\t\tif (!Session.Play) {\n\t\t\t\tModem_Signoff();\n\t\t\t}\n\t\t} else {\n\t\t\tif (Session.Type == GAME_IPX) {\n\t\t\t\tif (!Session.Play) {\n\t\t\t\t\tShutdown_Network();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf we're playing back, the mouse will be hidden; show it.\n\t\t** Also, set all variables back to normal, to return to the main menu.\n\t\t*/\n\t\tif (Session.Play) {\n\t\t\tShow_Mouse();\n\t\t\tSession.Type = GAME_NORMAL;\n\t\t\tSession.Play = 0;\n\t\t}\n#ifdef WIN32\n\t\tif (Special.IsFromWChat) {\n\t\t\tShutdown_Network();\t\t      // Clear up the pseudo IPX stuff\n\t\t\tWinsock.Close();\n\t\t\tSpecial.IsFromWChat = false;\n\t\t\tSpawnedFromWChat = false;\n\t\t\tDDEServer.Delete_MPlayer_Game_Info();\t//Make sure we dont use the same start packet twice\n\t\t\tSession.Type = GAME_NORMAL;\t\t\t//Have to do this or we will got straight to the multiplayer menu\n\t\t\tSpawn_WChat();\t\t//Will switch back to Wchat. It must be there because its been poking us\n\t\t}\n#endif\t//WIN32\n\t}\n\n\t/*\n\t**\tFree the scenario description buffers\n\t*/\n\tSession.Free_Scenario_Descriptions();\n}\n\n\n/***********************************************************************************************\n * Keyboard_Process -- Processes the tactical map input codes.                                 *\n *                                                                                             *\n *    This routine is used to process the input codes while the player                         *\n *    has the tactical map displayed. It handles all the keys that                             *\n *    are appropriate to that mode.                                                            *\n *                                                                                             *\n * INPUT:   input -- Input code as returned from Input_Num().                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/21/1992 JLB : Created.                                                                 *\n *   07/04/1995 JLB : Handles team and map control hotkeys.                                    *\n *=============================================================================================*/\nvoid Keyboard_Process(KeyNumType & input)\n{\n\tObjectClass * obj;\n\tint index;\n\n\t/*\n\t**\tDon't do anything if there is not keyboard event.\n\t*/\n\tif (input == KN_NONE) {\n\t\treturn;\n\t}\n\t/*\n\t**\tFor network & modem, process user input for inter-player messages.\n\t*/\n\tMessage_Input(input);\n\n#ifdef WIN32\n\t/*\n\t**\tThe VK_BIT must be stripped from the \"plain\" value of the key so that a comparison to\n\t**\tKN_1, for example, will yield TRUE if in fact the \"1\" key was pressed.\n\t*/\n\n\tKeyNumType plain = KeyNumType(input & ~(WWKEY_SHIFT_BIT|WWKEY_ALT_BIT|WWKEY_CTRL_BIT|WWKEY_VK_BIT));\n\tKeyNumType key = KeyNumType(input & ~WWKEY_VK_BIT);\n\n\n#else\n\tKeyNumType plain = KeyNumType(input & ~(KN_SHIFT_BIT|KN_ALT_BIT|KN_CTRL_BIT));\n\tKeyNumType key = plain;\n#endif\n\n#ifdef CHEAT_KEYS\n\n\tif (Debug_Flag) {\n\t\tHousesType h;\n\n\t\tswitch (int(input)) {\n\t\t\tcase int(int(KN_M) | int(KN_SHIFT_BIT)):\n\t\t\tcase int(int(KN_M) | int(KN_ALT_BIT)):\n\t\t\tcase int(int(KN_M) | int(KN_CTRL_BIT)):\n\t\t\t\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\t\t\t\tHouses.Ptr(h)->Refund_Money(10000);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n#endif\n\n#ifdef VIRGIN_CHEAT_KEYS\n\tif (Debug_Playtest && input == (KN_W|KN_ALT_BIT)) {\n\t\tPlayerPtr->Blockage = false;\n\t\tPlayerPtr->Flag_To_Win();\n\t}\n#endif\n\n#ifdef CHEAT_KEYS\n#ifdef WIN32\n\tif (Debug_Playtest && input == (KA_W|KN_ALT_BIT)) {\n#else\n\tif (Debug_Playtest && input == (KN_W|KN_ALT_BIT)) {\n#endif\n\t\tPlayerPtr->Blockage = false;\n\t\tPlayerPtr->Flag_To_Win();\n\t}\n\n\tif ((Debug_Flag || Debug_Playtest) && plain == KN_F4) {\n\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\tDebug_Unshroud = (Debug_Unshroud == false);\n\t\t\tMap.Flag_To_Redraw(true);\n\t\t}\n\t}\n\n\tif (Debug_Flag && input == KN_SLASH) {\n\t\tif (Session.Type != GAME_NORMAL) {\n\t\t\tSpecialDialog = SDLG_SPECIAL;\n\t\t\tinput = KN_NONE;\n\t\t} else {\n\t\t\tSpecial_Dialog();\n\t\t}\n\t}\n#endif\n\n\t/*\n\t**\tProcess prerecorded team selection. This will be an additive select\n\t**\tif the SHIFT key is held down. It will create the team if the\n\t**\tCTRL or ALT key is held down.\n\t*/\n\tint action = 0;\n#ifdef WIN32\n\tif (input & WWKEY_SHIFT_BIT) action = 1;\n\tif (input & WWKEY_ALT_BIT) action = 3;\n\tif (input & WWKEY_CTRL_BIT) action = 2;\n#else\n\tif (input & KN_SHIFT_BIT) action = 1;\n\tif (input & KN_ALT_BIT) action = 3;\n\tif (input & KN_CTRL_BIT) action = 2;\n#endif\n\n\t/*\n\t**\tIf the \"N\" key is pressed, then select the next object.\n\t*/\n\tif (key != 0 && key == Options.KeyNext) {\n\t\tif (action) {\n\t\t\tobj = Map.Prev_Object(CurrentObject.Count() ? CurrentObject[0] : NULL);\n\t\t} else {\n\t\t\tobj = Map.Next_Object(CurrentObject.Count() ? CurrentObject[0] : NULL);\n\t\t}\n\t\tif (obj != NULL) {\n\t\t\tUnselect_All();\n\t\t \tobj->Select();\n\t\t\tMap.Center_Map();\n\t\t\tMap.Flag_To_Redraw(true);\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\tif (key != 0 && key == Options.KeyPrevious) {\n\t\tif (action) {\n\t\t\tobj = Map.Next_Object(CurrentObject.Count() ? CurrentObject[0] : NULL);\n\t\t} else {\n\t\t\tobj = Map.Prev_Object(CurrentObject.Count() ? CurrentObject[0] : NULL);\n\t\t}\n\t\tif (obj != NULL) {\n\t\t\tUnselect_All();\n\t\t \tobj->Select();\n\t\t\tMap.Center_Map();\n\t\t\tMap.Flag_To_Redraw(true);\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\n\n\t/*\n\t**\tAll selected units will go into idle mode.\n\t*/\n\tif (key != 0 && key == Options.KeyStop) {\n\t\tif (CurrentObject.Count()) {\n\t\t\tfor (index = 0; index < CurrentObject.Count(); index++) {\n\t\t\t\tObjectClass const * tech = CurrentObject[index];\n\n\t\t\t\tif (tech != NULL && (tech->Can_Player_Move() || (tech->Can_Player_Fire() && tech->What_Am_I() != RTTI_BUILDING))) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::IDLE, TargetClass(tech)));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tAll selected units will attempt to go into guard area mode.\n\t*/\n\tif (key != 0 && key == Options.KeyGuard) {\n\t\tif (CurrentObject.Count()) {\n\t\t\tfor (index = 0; index < CurrentObject.Count(); index++) {\n\t\t\t\tObjectClass const * tech = CurrentObject[index];\n\n\t\t\t\tif (tech != NULL && tech->Can_Player_Move() && tech->Can_Player_Fire()) {\n\t\t\t\t\tOutList.Add(EventClass(TargetClass(tech), MISSION_GUARD_AREA));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tAll selected units will attempt to scatter.\n\t*/\n\tif (key != 0 && key == Options.KeyScatter) {\n\t\tif (CurrentObject.Count()) {\n\t\t\tfor (index = 0; index < CurrentObject.Count(); index++) {\n\t\t\t\tObjectClass const * tech = CurrentObject[index];\n\n\t\t\t\tif (tech != NULL && tech->Can_Player_Move()) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::SCATTER, TargetClass(tech)));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tCenter the map around the currently selected objects. If no\n\t**\tobjects are selected, then fall into the home case.\n\t*/\n\tif (key != 0 && (key == Options.KeyHome1 || key == Options.KeyHome2)) {\n\t\tif (CurrentObject.Count()) {\n\t\t\tMap.Center_Map();\n#ifdef WIN32\n\t\t\tMap.Flag_To_Redraw(true);\n#endif\n\t\t\tinput = KN_NONE;\n\t\t} else {\n\t\t\tinput = Options.KeyBase;\n\t\t}\n\t}\n\n\t/*\n\t**\tCenter the map about the construction yard or construction vehicle\n\t**\tif one is present.\n\t*/\n\tif (key != 0 && key == Options.KeyBase) {\n\t\tUnselect_All();\n\t\tif (PlayerPtr->CurBuildings) {\n\t\t\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\t\t\tBuildingClass * building = Buildings.Ptr(index);\n\n\t\t\t\tif (building != NULL && !building->IsInLimbo && building->House == PlayerPtr && *building == STRUCT_CONST) {\n\t\t\t\t\tUnselect_All();\n\t\t\t\t\tbuilding->Select();\n\t\t\t\t\tif (building->IsLeader) break;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (CurrentObject.Count() == 0 && PlayerPtr->CurUnits) {\n\t\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass * unit = Units.Ptr(index);\n\n\t\t\t\tif (unit != NULL && !unit->IsInLimbo && unit->House == PlayerPtr && *unit == UNIT_MCV) {\n\t\t\t\t\tUnselect_All();\n\t\t\t\t\tunit->Select();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (CurrentObject.Count()) {\n\t\t\tMap.Center_Map();\n\t\t} else {\n\t\t\tif (PlayerPtr->Center != 0) {\n\t\t\t\tMap.Center_Map(PlayerPtr->Center);\n\t\t\t}\n\t\t}\n\t\tMap.Flag_To_Redraw(true);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t** Toggle the status of formation for the current team\n\t*/\n\tif (key != 0 && key == Options.KeyFormation) {\n\t\tToggle_Formation();\n\t\tinput = KN_NONE;\n\t}\n\n#ifdef TOFIX\n\t/*\n\t** For multiplayer, 'R' pops up the surrender dialog.\n\t*/\n\tif (input != 0 && input == Options.KeyResign) {\n\t\tif (!PlayerLoses && /*Session.Type != GAME_NORMAL &&*/ !PlayerPtr->IsDefeated) {\n\t\t\tSpecialDialog = SDLG_SURRENDER;\n\t\t\tinput = KN_NONE;\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n#endif\n\n\t/*\n\t**\tHandle making and breaking alliances.\n\t*/\n\tif (key != 0 && key == Options.KeyAlliance) {\n\t\tif (Session.Type != GAME_NORMAL || Debug_Flag) {\n\t\t\tif (CurrentObject.Count() && !PlayerPtr->IsDefeated) {\n\t\t\t\tif (CurrentObject[0]->Owner() != PlayerPtr->Class->House) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::ALLY, CurrentObject[0]->Owner()));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tSelect all the units on the current display. This is equivalent to\n\t**\tdrag selecting the whole view.\n\t*/\n\tif (key != 0 && key == Options.KeySelectView) {\n\t\tMap.Select_These(0x00000000, XY_Coord(Map.TacLeptonWidth, Map.TacLeptonHeight));\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tToggles the repair state similarly to pressing the repair button.\n\t*/\n\tif (key != 0 && key == Options.KeyRepair) {\n\t\tMap.Repair_Mode_Control(-1);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tToggles the sell state similarly to pressing the sell button.\n\t*/\n\tif (key != 0 && key == Options.KeySell) {\n\t\tMap.Sell_Mode_Control(-1);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tToggles the map zoom mode similarly to pressing the map button.\n\t*/\n\tif (key != 0 && key == Options.KeyMap) {\n\t\tMap.Zoom_Mode_Control();\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tScrolls the sidebar up one slot.\n\t*/\n\tif (key != 0 && key == Options.KeySidebarUp) {\n\t\tMap.SidebarClass::Scroll(true, -1);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tScrolls the sidebar down one slot.\n\t*/\n\tif (key != 0 && key == Options.KeySidebarDown) {\n\t\tMap.SidebarClass::Scroll(false, -1);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tBrings up the options dialog box.\n\t*/\n\tif (key != 0 && (key == Options.KeyOption1 || key == Options.KeyOption2)) {\n\t\tMap.Help_Text(TXT_NONE);\t\t\t// Turns off help text.\n\t\tQueue_Options();\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tScrolls the tactical map in the direction specified.\n\t*/\n\tint distance = CELL_LEPTON_W;\n\tif (key != 0 && key == Options.KeyScrollLeft) {\n\t\tMap.Scroll_Map(DIR_W, distance, true);\n\t\tinput = KN_NONE;\n\t}\n\tif (key != 0 && key == Options.KeyScrollRight) {\n\t\tMap.Scroll_Map(DIR_E, distance, true);\n\t\tinput = KN_NONE;\n\t}\n\tif (key != 0 && key == Options.KeyScrollUp) {\n\t\tMap.Scroll_Map(DIR_N, distance, true);\n\t\tinput = KN_NONE;\n\t}\n\tif (key != 0 && key == Options.KeyScrollDown) {\n\t\tMap.Scroll_Map(DIR_S, distance, true);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tTeams are handled by the 10 special team keys. The manual comparison\n\t**\tto the KN numbers is because the Windows keyboard driver can vary\n\t**\tthe base code number for the key depending on the shift or alt key\n\t**\tstate!\n\t*/\n\tif (input != 0 && (plain == Options.KeyTeam1 || plain == KN_1)) {\n\t\tHandle_Team(0, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam2 || plain == KN_2)) {\n\t\tHandle_Team(1, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam3 || plain == KN_3)) {\n\t\tHandle_Team(2, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam4 || plain == KN_4)) {\n\t\tHandle_Team(3, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam5 || plain == KN_5)) {\n\t\tHandle_Team(4, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam6 || plain == KN_6)) {\n\t\tHandle_Team(5, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam7 || plain == KN_7)) {\n\t\tHandle_Team(6, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam8 || plain == KN_8)) {\n\t\tHandle_Team(7, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam9 || plain == KN_9)) {\n\t\tHandle_Team(8, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam10 || plain == KN_0)) {\n\t\tHandle_Team(9, action);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tHandle the bookmark hotkeys.\n\t*/\n\tif (input != 0 && plain == Options.KeyBookmark1 && !Debug_Map) {\n\t\tHandle_View(0, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && plain == Options.KeyBookmark2 && !Debug_Map) {\n\t\tHandle_View(1, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && plain == Options.KeyBookmark3 && !Debug_Map) {\n\t\tHandle_View(2, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && plain == Options.KeyBookmark4 && !Debug_Map) {\n\t\tHandle_View(3, action);\n\t\tinput = KN_NONE;\n\t}\n\n#ifdef CHEAT_KEYS\n\tif (input != 0 && Debug_Flag && input && (input & KN_RLSE_BIT) == 0) {\n\t\tDebug_Key(input);\n\t}\n#endif\n}\n\n\nvoid Toggle_Formation(void) {\n\tint team = -1;\n\tlong minx = 0x7FFFFFFFL, miny = 0x7FFFFFFFL;\n\tlong maxx = 0, maxy = 0;\n\tint index;\n\tbool setform = 0;\n\n\t//\n\t// Recording support\n\t//\n\tif (Session.Record) {\n\t\tFormationEvent = 1;\n\t}\n\n\t/*\n\t** Find the first selected object that is a member of a team, and\n\t** register his group as the team we're using.  Once we find the team\n\t** number, update the 'setform' flag to know whether we should be setting\n\t** the formation's offsets, or clearing them.  If they currently have\n\t** illegal offsets (as in 0x80000000), then we're setting.\n\t*/\n\tfor (index = 0; index < Units.Count(); index++) {\n\t\tUnitClass * obj = Units.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->IsSelected) {\n\t\t\tteam = obj->Group;\n\t\t\tif (team != -1) {\n\t\t\t\tsetform = obj->XFormOffset == (int)0x80000000;\n\t\t\t\tTeamSpeed[team] = SPEED_WHEEL;\n\t\t\t\tTeamMaxSpeed[team] = MPH_LIGHT_SPEED;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tif (team == -1) {\n\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->IsSelected) {\n\t\t\t\tteam = obj->Group;\n\t\t\t\tif (team != -1) {\n\t\t\t\t\tsetform = obj->XFormOffset == (int)0x80000000;\n\t\t\t\t\tTeamSpeed[team] = SPEED_WHEEL;\n\t\t\t\t\tTeamMaxSpeed[team] = MPH_LIGHT_SPEED;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (team == -1) {\n\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->IsSelected) {\n\t\t\t\tteam = obj->Group;\n\t\t\t\tif (team != -1) {\n\t\t\t\t\tsetform = obj->XFormOffset == 0x80000000UL;\n\t\t\t\t\tTeamSpeed[team] = SPEED_WHEEL;\n\t\t\t\t\tTeamMaxSpeed[team] = MPH_LIGHT_SPEED;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (team == -1) return;\n\t/*\n\t** Now that we have a team, let's go set (or clear) the formation offsets.\n\t*/\n\tfor (index = 0; index < Units.Count(); index++) {\n\t\tUnitClass * obj = Units.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team) {\n\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\tif (setform) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\tif (obj->Class->MaxSpeed < TeamMaxSpeed[team]) {\n\t\t\t\t\tTeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t\tTeamSpeed[team] = obj->Class->Speed;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tobj->XFormOffset = obj->YFormOffset = (int)0x80000000;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team) {\n\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\tif (setform) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\tif (obj->Class->MaxSpeed < TeamMaxSpeed[team]) {\n\t\t\t\t\tTeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tobj->XFormOffset = obj->YFormOffset = (int)0x80000000;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team) {\n\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\tif (setform) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\tif (obj->Class->MaxSpeed < TeamMaxSpeed[team]) {\n\t\t\t\t\tTeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tobj->XFormOffset = obj->YFormOffset = 0x80000000UL;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** All the units have been counted to find the bounding rectangle and\n\t** center of the formation, or to clear their offsets.  Now, if we're to\n\t** set them into formation, proceed to do so.  Otherwise, bail.\n\t*/\n\tif (setform) {\n\t\tint centerx = (int)((maxx - minx)/2)+minx;\n\t\tint centery = (int)((maxy - miny)/2)+miny;\n\n\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\tobj->YFormOffset = yc - centery;\n\t\t\t}\n\t\t}\n\n\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team ) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\tobj->YFormOffset = yc - centery;\n\t\t\t}\n\t\t}\n\n\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team ) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\tobj->YFormOffset = yc - centery;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Message_Input -- allows inter-player message input processing                               *\n *                                                                                             *\n * INPUT:                                                                                      *\n *\t\tinput\t\tkey value\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\n#pragma off (unreferenced)\nstatic void Message_Input(KeyNumType &input)\n{\n\tint rc;\n\tchar txt[MAX_MESSAGE_LENGTH+32];\n\tint id;\n\tSerialPacketType * serial_packet;\n\tint i;\n\tKeyNumType copy_input;\n\t//char *msg;\n\n\t/*\n\t**\tCheck keyboard input for a request to send a message.\n\t**\tThe 'to' argument for Add_Edit is prefixed to the message buffer; the\n\t**\tmessage buffer is big enough for the 'to' field plus MAX_MESSAGE_LENGTH.\n\t**\tTo send the message, calling Get_Edit_Buf retrieves the buffer minus the\n\t**\t'to' portion.  At the other end, the buffer allocated to display the\n\t**\tmessage must be MAX_MESSAGE_LENGTH plus the size of \"From: xxx (house)\".\n\t*/\n\tif (Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH && input >= KN_F1 && input < (KN_F1 + Session.MaxPlayers) && !Session.Messages.Is_Edit()) {\n\t\tmemset (txt, 0, 40);\n\n\t\t/*\n\t\t**\tFor a serial game, send a message on F1 or F4; set 'txt' to the\n\t\t**\t\"Message:\" string & add an editable message to the list.\n\t\t*/\n\t\tif (Session.Type==GAME_NULL_MODEM || Session.Type==GAME_MODEM) {\n\t\t\tif (input==KN_F1 || input==(KN_F1 + Session.MaxPlayers - 1)) {\n\n\t\t\t\tstrcpy(txt, Text_String(TXT_MESSAGE));\t// \"Message:\"\n\n\t\t\t\tSession.Messages.Add_Edit (Session.ColorIdx,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\tMap.Flag_To_Redraw(false);\n\t\t\t}\n\t\t} else if ((Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) && !Session.Messages.Is_Edit()) {\n\t\t/*\n\t\t**\tFor a network game:\n\t\t**\tF1-F7 = \"To <name> (house):\" (only allowed if we're not in ObiWan mode)\n\t\t**\tF8 = \"To All:\"\n\t\t*/\n\t\t\tif (input==(KN_F1 + Session.MaxPlayers - 1)) {\n\n\t\t\t\tSession.MessageAddress = IPXAddressClass();\t\t// set to broadcast\n\t\t\t\tstrcpy(txt, Text_String(TXT_TO_ALL));\t// \"To All:\"\n\n\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\tMap.Flag_To_Redraw(false);\n\t\t\t} else if ((input - KN_F1) < Ipx.Num_Connections() && !Session.ObiWan) {\n\n\t\t\t\tid = Ipx.Connection_ID(input - KN_F1);\n\t\t\t\tSession.MessageAddress = (*(Ipx.Connection_Address (id)));\n\t\t\t\tsprintf(txt, Text_String(TXT_TO), Ipx.Connection_Name(id));\n\n\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\tMap.Flag_To_Redraw(false);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tProcess message-system input; send the message out if RETURN is hit.\n\t*/\n\tcopy_input = input;\n\trc = Session.Messages.Input(input);\n\n\t/*\n\t**\tIf a single character has been added to an edit buffer, update the display.\n\t*/\n\tif (rc == 1 && Session.Type != GAME_NORMAL) {\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n\t/*\n\t**\tIf backspace was hit, redraw the map.  If the edit message was removed,\n\t** the map must be force-drawn, since it won't be able to compute the\n\t** cells to redraw; otherwise, let the map compute the cells to redraw,\n\t** by not force-drawing it, but just setting the IsToRedraw bit.\n\t*/\n\tif (rc==2 && Session.Type != GAME_NORMAL) {\n\t\tif (copy_input==KN_ESC) {\n\t\t\tMap.Flag_To_Redraw(true);\n\t\t} else {\n\t\t\tMap.Flag_To_Redraw(false);\n\t\t}\n\t\tMap.DisplayClass::IsToRedraw = true;\n\t}\n\n\t/*\n\t**\tSend a message\n\t*/\n\tif ((rc==3 || rc==4) && Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH) {\n\t\t/*\n\t\t**\tSerial game: fill in a SerialPacketType & send it.\n\t\t**\t(Note: The size of the SerialPacketType.Command must be the same as\n\t\t**\tthe EventClass.Type!)\n\t\t*/\n\t\tif (Session.Type==GAME_NULL_MODEM || Session.Type==GAME_MODEM) {\n\t\t\tserial_packet = (SerialPacketType *)NullModem.BuildBuf;\n\n\t\t\tserial_packet->Command = SERIAL_MESSAGE;\n\t\t\tstrcpy (serial_packet->Name, Session.Players[0]->Name);\n\t\t\tserial_packet->ID = Session.ColorIdx;\n\n\t\t\tif (rc==3) {\n\t\t\t\tstrcpy (serial_packet->Message.Message, Session.Messages.Get_Edit_Buf());\n\t\t\t} else {\n\t\t\t\tstrcpy (serial_packet->Message.Message, Session.Messages.Get_Overflow_Buf());\n\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Send the message, and store this message in our LastMessage\n\t\t\t** buffer; the computer may send us a version of it later.\n\t\t\t*/\n\t\t\tNullModem.Send_Message(NullModem.BuildBuf,\n\t\t\t\tsizeof(SerialPacketType), 1);\n\n\t\t\tstrcpy(Session.LastMessage, serial_packet->Message.Message);\n\t\t} else if (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) {\n\t\t/*\n\t\t**\tNetwork game: fill in a GlobalPacketType & send it.\n\t\t*/\n\t\t\tSession.GPacket.Command = NET_MESSAGE;\n\t\t\tstrcpy (Session.GPacket.Name, Session.Players[0]->Name);\n\t\t\tSession.GPacket.Message.Color = Session.ColorIdx;\n\t\t\tSession.GPacket.Message.NameCRC = Compute_Name_CRC(Session.GameName);\n\n\t\t\tif (rc==3) {\n\t\t\t\tstrcpy (Session.GPacket.Message.Buf, Session.Messages.Get_Edit_Buf());\n\t\t\t} else {\n\t\t\t\tstrcpy (Session.GPacket.Message.Buf,\n\t\t\t\t\tSession.Messages.Get_Overflow_Buf());\n\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf 'F4' was hit, MessageAddress will be a broadcast address; send\n\t\t\t**\tthe message to every player we have a connection with.\n\t\t\t*/\n\t\t\tif (Session.MessageAddress.Is_Broadcast()) {\n\t\t\t\tfor (i = 0; i < Ipx.Num_Connections(); i++) {\n\t\t\t\t\tIpx.Send_Global_Message(&Session.GPacket,\n\t\t\t\t\t\tsizeof(GlobalPacketType), 1,\n\t\t\t\t\t\tIpx.Connection_Address(Ipx.Connection_ID(i)));\n\t\t\t\t\tIpx.Service();\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tOtherwise, MessageAddress contains the exact address to send to.\n\t\t\t\t**\tSend to that address only.\n\t\t\t\t*/\n\t\t\t\tIpx.Send_Global_Message(&Session.GPacket,\n\t\t\t\t\tsizeof(GlobalPacketType), 1,\n\t\t\t\t\t&Session.MessageAddress);\n\t\t\t\tIpx.Service();\n\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tStore this message in our LastMessage buffer; the computer may send\n\t\t\t**\tus a version of it later.\n\t\t\t*/\n\t\t\tstrcpy(Session.LastMessage, Session.GPacket.Message.Buf);\n\t\t}\n\n\t\t/*\n\t\t**\tTell the map to completely update itself, since a message is now missing.\n\t\t*/\n\t\tMap.Flag_To_Redraw(true);\n\t}\n}\n#pragma on (unreferenced)\n\n\n/***********************************************************************************************\n * Color_Cycle -- Handle the general palette color cycling.                                    *\n *                                                                                             *\n *    This is a maintenance routine that handles the color cycling. It should be called as     *\n *    often as necessary to achieve smooth color cycling effects -- at least 8 times a second. *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   06/10/1994 JLB : Uses new cycle color values.                                             *\n *   12/21/1994 JLB : Handles text fade color.                                                 *\n *   07/16/1996 JLB : Faster pulsing of white color.                                           *\n *=============================================================================================*/\nvoid Color_Cycle(void)\n{\n\tstatic CDTimerClass<SystemTimerClass> _timer;\n\tstatic CDTimerClass<SystemTimerClass> _ftimer;\n\tstatic bool _up = false;\n\tstatic int val = 255;\n\tbool changed = false;\n\n\tif (Options.IsPaletteScroll) {\n\t\t/*\n\t\t**\tProcess the fading white color. It is used for the radar box and other glowing\n\t\t**\tgame interface elements.\n\t\t*/\n\t\tif (!_ftimer) {\n\t\t\t_ftimer = TIMER_SECOND/6;\n\n\t\t\t#define\tSTEP_RATE\t20\n\t\t\tif (_up) {\n\t\t\t\tval += STEP_RATE;\n\t\t\t\tif (val > 150) {\n\t\t\t\t\tval = 150;\n\t\t\t\t\t_up = false;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tval -= STEP_RATE;\n\t\t\t\tif (val < 0x20) {\n\t\t\t\t\tval = 0x20;\n\t\t\t\t\t_up = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSet the pulse color as the proportional value between white and the\n\t\t\t**\tminimum value for pulsing.\n\t\t\t*/\n\t\t\tInGamePalette[CC_PULSE_COLOR] = GamePalette[WHITE];\n\t\t\tInGamePalette[CC_PULSE_COLOR].Adjust(val, BlackColor);\n\n\t\t\t/*\n\t\t\t**\tPulse the glowing embers between medium and dark red.\n\t\t\t*/\n\t\t\tInGamePalette[CC_EMBER_COLOR] = RGBClass(255, 80, 80);\n\t\t\tInGamePalette[CC_EMBER_COLOR].Adjust(val, BlackColor);\n\n\t\t\tchanged = true;\n\t\t}\n\n\t\t/*\n\t\t**\tProcess the color cycling effects -- water.\n\t\t*/\n\t\tif (!_timer) {\n\t\t\t_timer = TIMER_SECOND/4;\n\n\t\t\tRGBClass first = InGamePalette[CYCLE_COLOR_START+CYCLE_COLOR_COUNT-1];\n\t\t\tfor (int index = CYCLE_COLOR_START+CYCLE_COLOR_COUNT-1; index >= CYCLE_COLOR_START; index--) {\n\t\t\t\tInGamePalette[index] = InGamePalette[index-1];\n\t\t\t}\n\t\t\tInGamePalette[CYCLE_COLOR_START] = first;\n\n\t\t\tchanged = true;\n\t\t}\n\n\t\t/*\n\t\t**\tIf any of the processing functions changed the palette, then this palette must be\n\t\t**\tpassed to the system.\n\t\t*/\n\t\tif (changed) {\n\t\t\tBStart(BENCH_PALETTE);\n\t\t\tInGamePalette.Set();\n//\t\t\tSet_Palette(InGamePalette);\n\t\t\tBEnd(BENCH_PALETTE);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Call_Back -- Main game maintenance callback routine.                                        *\n *                                                                                             *\n *    This routine handles all the \"real time\" processing that needs to                        *\n *    occur. This includes palette fading and sound updating. It needs                         *\n *    to be called as often as possible.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Call_Back(void)\n{\n\t/*\n\t**\tMusic and speech maintenance\n\t*/\n\tif (SampleType) {\n\t\tSound_Callback();\n\t\tTheme.AI();\n\t\tSpeak_AI();\n\t}\n\n\t/*\n\t**\tNetwork maintenance.\n\t*/\n\tif (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) {\n\t\tIPX_Call_Back();\n\t}\n\n\t/*\n\t**\tSerial game maintenance.\n\t*/\n\tif (Session.Type == GAME_NULL_MODEM || ((Session.Type == GAME_MODEM) && Session.ModemService)) {\n\t\tNullModem.Service();\n\t}\n}\n\n\nvoid IPX_Call_Back(void)\n{\n\tIpx.Service();\n\n\t/*\n\t** Read packets only if the game is \"closed\", so we don't steal global\n\t** messages from the connection dialogs.\n\t*/\n\tif (!Session.NetOpen) {\n\t\tif (Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen, &Session.GAddress, &Session.GProductID)) {\n\n\t\t\tif (Session.GProductID == IPXGlobalConnClass::COMMAND_AND_CONQUER0) {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this is another player signing off, remove the connection &\n\t\t\t\t**\tmark that player's house as non-human, so the computer will take\n\t\t\t\t**\tit over.\n\t\t\t\t*/\n\t\t\t\tif (Session.GPacket.Command == NET_SIGN_OFF) {\n\t\t\t\t\tfor (int i = 0; i < Ipx.Num_Connections(); i++) {\n\n\t\t\t\t\t\tint id = Ipx.Connection_ID(i);\n\n\t\t\t\t\t\tif (Session.GAddress == (*Ipx.Connection_Address(id))) {\n\n\t\t\t\t\t\t\tDestroy_Connection(id, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tProcess a message from another user.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Session.GPacket.Command == NET_MESSAGE) {\n\t\t\t\t\t\tbool msg_ok = false;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** If NetProtect is set, make sure this message came from within\n\t\t\t\t\t\t** this game.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (!Session.NetProtect) {\n\t\t\t\t\t\t\tmsg_ok = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (Session.GPacket.Message.NameCRC ==\n\t\t\t\t\t\t\t\tCompute_Name_CRC(Session.GameName)) {\n\t\t\t\t\t\t\t\tmsg_ok = true;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tmsg_ok = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (msg_ok) {\n\t\t\t\t\t\t\tif (!Session.Messages.Concat_Message(Session.GPacket.Name,\n\t\t\t\t\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\t\t\t\t\tSession.GPacket.Message.Buf, Rule.MessageDelay * TICKS_PER_MINUTE)) {\n\n\t\t\t\t\t\t\t\tSession.Messages.Add_Message (Session.GPacket.Name,\n\t\t\t\t\t\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\t\t\t\t\t\tSession.GPacket.Message.Buf,\n\t\t\t\t\t\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\t\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL |\n\t\t\t\t\t\t\t\t\tTPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\n\t\t\t\t\t\t\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tTell the map to do a partial update (just to force the messages\n\t\t\t\t\t\t\t**\tto redraw).\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tMap.Flag_To_Redraw(true);\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tSave this message in our last-message buffer\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tstrcpy(Session.LastMessage, Session.GPacket.Message.Buf);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tProcess_Global_Packet(&Session.GPacket, &Session.GAddress);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n}\n\n\n/***********************************************************************************************\n * Language_Name -- Build filename for current language.                                       *\n *                                                                                             *\n *    This routine attaches a language specific suffix to the base                             *\n *    filename provided. Typical use of this is when loading language                          *\n *    specific files at game initialization time.                                              *\n *                                                                                             *\n * INPUT:   basename -- Base name to append language specific                                  *\n *                      extension to.                                                          *\n *                                                                                             *\n * OUTPUT:  Returns with pointer to completed filename.                                        *\n *                                                                                             *\n * WARNINGS:   The return pointer value is valid only until the next time                      *\n *             this routine is called.                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * Language_Name(char const * basename)\n{\n\tstatic char _fullname[_MAX_FNAME+_MAX_EXT];\n\n\tif (!basename) return(NULL);\n\n\tsprintf(_fullname, \"%s.ENG\", basename);\n\treturn(_fullname);\n}\n\n\n/***********************************************************************************************\n * Source_From_Name -- Converts ASCII name into SourceType.                                    *\n *                                                                                             *\n *    This routine is used to convert an ASCII name representing a                             *\n *    SourceType into the actual SourceType value. Typically, this is                          *\n *    used when processing the scenario INI file.                                              *\n *                                                                                             *\n * INPUT:   name  -- The ASCII source name to process.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the SourceType represented by the name                                *\n *          specified.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nSourceType Source_From_Name(char const * name)\n{\n\tif (name) {\n\t\tfor (SourceType source = SOURCE_FIRST; source < SOURCE_COUNT; source++) {\n\t\t\tif (stricmp(SourceName[source], name) == 0) {\n\t\t\t\treturn(source);\n\t\t\t}\n\t\t}\n\t}\n\treturn(SOURCE_NONE);\n}\n\n\n/***********************************************************************************************\n * Name_From_Source -- retrieves the name for the given SourceType         \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tsource\t\tSourceType to get the name for\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\tname of SourceType\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   11/15/1994 BR : Created.                                              \t\t\t\t\t\t  *\n *=============================================================================================*/\nchar const * Name_From_Source(SourceType source)\n{\n\tif ((unsigned)source < SOURCE_COUNT) {\n\t\treturn(SourceName[source]);\n\t}\n\treturn(\"None\");\n}\n\n\n/***********************************************************************************************\n * Theater_From_Name -- Converts ASCII name into a theater number.                             *\n *                                                                                             *\n *    This routine converts an ASCII representation of a theater and converts it into a        *\n *    matching theater number. If no match was found, then THEATER_NONE is returned.           *\n *                                                                                             *\n * INPUT:   name  -- Pointer to ASCII name to convert.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the name converted into a theater number.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTheaterType Theater_From_Name(char const * name)\n{\n\tTheaterType\tindex;\n\n\tif (name) {\n\t\tfor (index = THEATER_FIRST; index < THEATER_COUNT; index++) {\n\t\t\tif (stricmp(name, Theaters[index].Name) == 0) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t}\n\t}\n\treturn(THEATER_NONE);\n}\n\n\n/***********************************************************************************************\n * KN_To_Facing -- Converts a keyboard input number into a facing value.                       *\n *                                                                                             *\n *    This routine determine which compass direction is represented by the keyboard value      *\n *    provided. It is used for map scrolling and other directional control operations from     *\n *    the keyboard.                                                                            *\n *                                                                                             *\n * INPUT:   input -- The KN number to convert.                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the facing type that the keyboard number represents. If it could      *\n *          not be translated, then FACING_NONE is returned.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nFacingType KN_To_Facing(int input)\n{\n\tinput &= ~(KN_ALT_BIT|KN_SHIFT_BIT|KN_CTRL_BIT);\n\tswitch (input) {\n\t\tcase KN_LEFT:\n\t\t\treturn(FACING_W);\n\n\t\tcase KN_RIGHT:\n\t\t\treturn(FACING_E);\n\n\t\tcase KN_UP:\n\t\t\treturn(FACING_N);\n\n\t\tcase KN_DOWN:\n\t\t\treturn(FACING_S);\n\n\t\tcase KN_UPLEFT:\n\t\t\treturn(FACING_NW);\n\n\t\tcase KN_UPRIGHT:\n\t\t\treturn(FACING_NE);\n\n\t\tcase KN_DOWNLEFT:\n\t\t\treturn(FACING_SW);\n\n\t\tcase KN_DOWNRIGHT:\n\t\t\treturn(FACING_SE);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(FACING_NONE);\n}\n\n\n/***********************************************************************************************\n * Sync_Delay -- Forces the game into a 15 FPS rate.                                           *\n *                                                                                             *\n *    This routine will wait until the timer for the current frame has expired before          *\n *    returning. It is called at the end of every game loop in order to force the game loop    *\n *    to run at a fixed rate.                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine will delay an amount of time according to the game speed setting.  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/04/1995 JLB : Created.                                                                 *\n *   03/06/1995 JLB : Fixed.                                                                   *\n *=============================================================================================*/\nstatic void Sync_Delay(void)\n{\n\t/*\n\t**\tAccumulate the number of 'spare' ticks that are frittered away here.\n\t*/\n\tSpareTicks += FrameTimer;\n\n\t/*\n\t**\tDelay until the frame timer expires. This forces the game loop to be regulated to a\n\t**\tspeed controlled by the game options slider.\n\t*/\n\twhile (FrameTimer) {\n\t\tColor_Cycle();\n\t\tCall_Back();\n\n\t\tif (SpecialDialog == SDLG_NONE) {\n#ifdef WIN32\n\t\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#endif\t//WIN32\n\t\t\tKeyNumType input = KN_NONE;\n\t\t\tint x, y;\n\t\t\tMap.Input(input, x, y);\n\t\t\tif (input) {\n\t\t\t\tKeyboard_Process(input);\n\t\t\t}\n\t\t\tMap.Render();\n\t\t}\n\t}\n\tColor_Cycle();\n\tCall_Back();\n}\n\n\n/***********************************************************************************************\n * Main_Loop -- This is the main game loop (as a single loop).                                 *\n *                                                                                             *\n *    This function will perform one game loop.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Should the game end?                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef WIN32\nextern void Check_For_Focus_Loss(void);\nvoid Reallocate_Big_Shape_Buffer(void);\n#endif\t//WIN32\n\n\nbool Main_Loop()\n{\n\tKeyNumType\tinput;\t\t\t\t\t// Player input.\n\tint x;\n\tint y;\n\tint framedelay;\n\n\tif (!GameActive) return(!GameActive);\n\n#ifdef WIN32\n\t/*\n\t** Call the focus loss handler\n\t*/\n\tCheck_For_Focus_Loss();\n\n\t/*\n\t** Allocate extra memory for uncompressed shapes as needed\n\t*/\n\tReallocate_Big_Shape_Buffer();\n#endif\n\n\t/*\n\t** Sync-bug trapping code\n\t*/\n\tif (Frame >= Session.TrapFrame) {\n\t\tSession.Trap_Object();\n\t}\n\n\t//\n\t// Initialize our AI processing timer\n\t//\n\tSession.ProcessTimer = TickCount;\n\n#if 1\n\tif (Session.TrapCheckHeap) {\n\t\tDebug_Trap_Check_Heap = true;\n\t}\n#endif\n\n#ifdef CHEAT_KEYS\n\n\t/*\n\t**\tUpdate the running status debug display.\n\t*/\n\tSelf_Regulate();\n#endif\n\n\tBStart(BENCH_GAME_FRAME);\n\n\t/*\n\t**\tIf there is no theme playing, but it looks like one is required, then start one\n\t**\tplaying. This is usually the symptom of there being no transition score.\n\t*/\n\tif (SampleType && Theme.What_Is_Playing() == THEME_NONE) {\n\t\tTheme.Queue_Song(THEME_PICK_ANOTHER);\n\t}\n\n\t/*\n\t**\tSetup the timer so that the Main_Loop function processes at the correct rate.\n\t*/\n\tif (Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH &&\n\t\tSession.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\n\t\t//\n\t\t// In playback mode, run as fast as possible.\n\t\t//\n\t\tif (Session.Play) {\n\t\t\tFrameTimer = 0;\n\t\t} else {\n\t\t\tframedelay = TIMER_SECOND / Session.DesiredFrameRate;\n\t\t\tFrameTimer = framedelay;\n\t\t}\n\t} else {\n\t\tif (Options.GameSpeed != 0) {\n\t\t\tFrameTimer = Options.GameSpeed +\n\t\t\t\t(PlayerPtr->Difficulty == DIFF_EASY ? 1 : 0) -\n\t\t\t\t(PlayerPtr->Difficulty == DIFF_HARD ? 1 : 0);\n\t\t} else {\n\t\t\tFrameTimer = Options.GameSpeed + (PlayerPtr->Difficulty == DIFF_EASY ? 1 : 0);\n\t\t}\n\t}\n\n\t/*\n\t**\tUpdate the display, unless we're inside a dialog.\n\t*/\n\tif (!Session.Play) {\n#ifdef WIN32\n\t\tif (SpecialDialog == SDLG_NONE && GameInFocus) {\n\t\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#else\n\t\tif (SpecialDialog == SDLG_NONE) {\n#endif\n\t\t\tMap.Input(input, x, y);\n\t\t\tif (input) {\n\t\t\t\tKeyboard_Process(input);\n\t\t\t}\n\t\t\tMap.Render();\n\t\t}\n\t}\n\n\t/*\n\t** Save map's position & selected objects, if we're recording the game.\n\t*/\n\tif (Session.Record || Session.Play) {\n\t\tDo_Record_Playback();\n\t}\n\n#ifndef SORTDRAW\n\t/*\n\t** Sort the map's ground layer by y-coordinate value.  This is done\n\t** outside the IsToRedraw check, for the purposes of game sync'ing\n\t** between machines; this way, all machines will sort the Map's\n\t** layer in the same way, and any processing done that's based on\n\t** the order of this layer will remain in sync.\n\t*/\n\tDisplayClass::Layer[LAYER_GROUND].Sort();\n#endif\n\n\t/*\n\t**\tAI logic operations are performed here.\n\t*/\n\tLogic.AI();\n\tTimeQuake = false;\n\n\t/*\n\t**\tManage the inter-player message list.  If Manage() returns true, it means\n\t**\ta message has expired & been removed, and the entire map must be updated.\n\t*/\n\tif (Session.Messages.Manage()) {\n#ifdef WIN32\n\t\tHiddenPage.Clear();\n#else\t//WIN32\n\t\tHidPage.Clear();\n#endif\t//WIN32\n\t\tMap.Flag_To_Redraw(true);\n\t}\n\n\t//\n\t// Measure how long it took to process the AI\n\t//\n\tSession.ProcessTicks += (TickCount - Session.ProcessTimer);\n\tSession.ProcessFrames++;\n\n\t/*\n\t**\tProcess all commands that are ready to be processed.\n\t*/\n\tQueue_AI();\n\n\t/*\n\t**\tKeep track of elapsed time in the game.\n\t*/\n\tScore.ElapsedTime += TIMER_SECOND / TICKS_PER_SECOND;\n\n\tCall_Back();\n\n\t/*\n\t**\tCheck for player wins or loses according to global event flag.\n\t*/\n\tif (PlayerWins) {\n\n#ifdef WIN32\n\n\t\t/*\n\t\t** Send the game statistics to WChat.\n\t\t*/\n\t\tif (Session.Type == GAME_INTERNET && !GameStatisticsPacketSent) {\n\t\t\tRegister_Game_End_Time();\n\t\t\tSend_Statistics_Packet();\n\t\t}\n\n\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#endif\t//WIN32\n\t\tPlayerLoses = false;\n\t\tPlayerWins = false;\n\t\tPlayerRestarts = false;\n\t\tMap.Help_Text(TXT_NONE);\n\t\tDo_Win();\n\t\treturn(!GameActive);\n\t}\n\tif (PlayerLoses) {\n#ifdef WIN32\n\t\t/*\n\t\t** Send the game statistics to WChat.\n\t\t*/\n\t\tif (Session.Type == GAME_INTERNET && !GameStatisticsPacketSent) {\n\t\t\tRegister_Game_End_Time();\n\t\t\tSend_Statistics_Packet();\n\t\t}\n\n\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#endif\t//WIN32\n\t\tPlayerWins = false;\n\t\tPlayerLoses = false;\n\t\tPlayerRestarts = false;\n\t\tMap.Help_Text(TXT_NONE);\n\t\tDo_Lose();\n\t\treturn(!GameActive);\n\t}\n\tif (PlayerRestarts) {\n#ifdef WIN32\n\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#endif\t//WIN32\n\t\tPlayerWins = false;\n\t\tPlayerLoses = false;\n\t\tPlayerRestarts = false;\n\t\tMap.Help_Text(TXT_NONE);\n\t\tDo_Restart();\n\t\treturn(!GameActive);\n\t}\n\n\t/*\n\t**\tThe frame logic has been completed. Increment the frame\n\t**\tcounter.\n\t*/\n\tFrame++;\n\n\t/*\n\t** Is there a memory trasher altering the map??\n\t*/\n\tif (Debug_Check_Map) {\n\t\tif (!Map.Validate()) {\n\t\t\tif (WWMessageBox().Process (TEXT_MAP_ERROR, TEXT_STOP, TEXT_CONTINUE)==0) {\n\t\t\t\tGameActive = 0;\n\t\t\t}\n\t\t\tMap.Validate();\t\t// give debugger a chance to catch it\n\t\t}\n\t}\n\n\n#ifdef WIN32\n\tif (Debug_MotionCapture) {\n\t\tstatic void ** _array = 0;\n\t\tstatic int _sequence = 0;\n\t\tstatic int _seqsize = Rule.MovieTime * TICKS_PER_MINUTE;\n\n\t\tif (_array == NULL) {\n\t\t\t_array = new void * [_seqsize];\n\t\t\tmemset(_array, '\\0', _seqsize * sizeof(void*));\n\t\t}\n\n\t\tif (_array == NULL) {\n\t\t\tDebug_MotionCapture = false;\n\t\t}\n\n\t\tstatic GraphicBufferClass temp_page(\tSeenBuff.Get_Width(),\n\t\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Height(),\n\t\t\t\t\t\t\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Width() * SeenBuff.Get_Height());\n\n\t\tint size = SeenBuff.Get_Width() * SeenBuff.Get_Height();\n\n\t\tif (_sequence < _seqsize) {\n\t\t\tif (_array[_sequence] == NULL) {\n\t\t\t\t_array[_sequence] = new char[size];\n\t\t\t}\n\n\t\t\tif (_array[_sequence] != NULL) {\n\t\t\t\tSeenBuff.Blit(temp_page);\n\t\t\t\tmemmove(_array[_sequence], temp_page.Get_Buffer(), size);\n\t\t\t}\n\t\t\t_sequence++;\n\n\t\t} else {\n\t\t\tDebug_MotionCapture = false;\n\n\t\t\tCDFileClass file;\n\t\t\tfile.Cache(200000);\n\t\t\tchar filename[30];\n\n\t\t\tfor (int index = 0; index < _sequence; index++) {\n\t\t\t\tmemmove(temp_page.Get_Buffer(), _array[index], size);\n\t\t\t\tsprintf(filename, \"cap%04d.pcx\", index);\n\t\t\t\tfile.Set_Name(filename);\n\n\t\t\t\tWrite_PCX_File(file, temp_page, & GamePalette);\n\t\t\t}\n\n\t\t\t_sequence = 0;\n\t\t}\n\t}\n#endif\n\n\tBEnd(BENCH_GAME_FRAME);\n\n\tSync_Delay();\n\treturn(!GameActive);\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***************************************************************************\n * Map_Edit_Loop -- a mini-main loop for map edit mode only                *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/19/1994 BR : Created.                                              *\n *=========================================================================*/\nbool Map_Edit_Loop(void)\n{\n\t/*\n\t**\tRedraw the map.\n\t*/\n\tMap.Render();\n\n\t/*\n\t**\tGet user input (keys, mouse clicks).\n\t*/\n\tKeyNumType input;\n\n#ifdef WIN32\n\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#endif\t//WIN32\n\n\tint x;\n\tint y;\n\tMap.Input(input, x, y);\n\n\t/*\n\t**\tProcess keypress.\n\t*/\n\tif (input) {\n\t\tKeyboard_Process(input);\n\t}\n\n\tCall_Back();\t\t\t\t\t\t\t\t// maintains Theme.AI() for music\n\tColor_Cycle();\n\n\treturn(!GameActive);\n}\n\n\n/***************************************************************************\n * Go_Editor -- Enables/disables the map editor\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tflag\t\ttrue = go into editor mode; false = go into game mode\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/19/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid Go_Editor(bool flag)\n{\n\t/*\n\t**\tGo into Scenario Editor mode\n\t*/\n\tif (flag) {\n\t\tDebug_Map = true;\n\t\tDebug_Unshroud = true;\n\n\t\t/*\n\t\t** Un-select any selected objects\n\t\t*/\n\t\tUnselect_All();\n\n\t\t/*\n\t\t** Turn off the sidebar if it's on\n\t\t*/\n\t\tMap.Activate(0);\n\n\t\t/*\n\t\t** Reset the map's Button list for the new mode\n\t\t*/\n\t\tMap.Init_IO();\n\n\t\t/*\n\t\t** Force a complete redraw of the screen\n\t\t*/\n#ifdef WIN32\n\t\tHiddenPage.Clear();\n#else\n\t\tHidPage.Clear();\n#endif\n\t\tMap.Flag_To_Redraw(true);\n\t\tMap.Render();\n\n\t} else {\n\n\t\t/*\n\t\t**\tGo into normal game mode\n\t\t*/\n\t\tDebug_Map = false;\n\t\tDebug_Unshroud = false;\n\n\t\t/*\n\t\t** Un-select any selected objects\n\t\t*/\n\t\tUnselect_All();\n\n\t\t/*\n\t\t** Reset the map's Button list for the new mode\n\t\t*/\n\t\tMap.Init_IO();\n\n\t\t/*\n\t\t** Force a complete redraw of the screen\n\t\t*/\n\t\tHidPage.Clear();\n\t\tMap.Flag_To_Redraw(true);\n\t\tMap.Render();\n\t}\n}\n\n#endif\n\n\n/***********************************************************************************************\n * MixFileHandler -- Handles VQ file access.                                                   *\n *                                                                                             *\n *    This routine is called from the VQ player when it needs to access the source file. By    *\n *    using this routine it is possible to virtualize the file system.                         *\n *                                                                                             *\n * INPUT:   vqa   -- Pointer to the VQA handle for this animation.                             *\n *                                                                                             *\n *          action-- The requested action to perform.                                          *\n *                                                                                             *\n *          buffer-- Optional buffer pointer as needed by the type of action.                  *\n *                                                                                             *\n *          nbytes-- The number of bytes (if needed) for this operation.                       *\n *                                                                                             *\n * OUTPUT:  Returns a value consistent with the action requested.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong MixFileHandler(VQAHandle * vqa, long action, void * buffer, long nbytes)\n{\n\tCCFileClass * file;\n\tlong        error;\n\n\tfile = (CCFileClass *)vqa->VQAio;\n\n\t/*\n\t**\tPerform the action specified by the stream command.\n\t*/\n\tswitch (action) {\n\n\t\t/*\n\t\t** VQACMD_READ means read NBytes from the stream and place it in the\n\t\t** memory pointed to by Buffer.\n\t\t**\n\t\t** Any error code returned will be remapped by VQA library into\n\t\t** VQAERR_READ.\n\t\t*/\n\t\tcase VQACMD_READ:\n\t\t\terror = (file->Read(buffer, (unsigned short)nbytes) != (unsigned short)nbytes);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tVQACMD_WRITE is analogous to VQACMD_READ.\n\t\t**\n\t\t** Writing is not allowed to the VQA file, VQA library will remap the\n\t\t** error into VQAERR_WRITE.\n\t\t*/\n\t\tcase VQACMD_WRITE:\n\t\t\terror = 1;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tVQACMD_SEEK asks that you perform a seek relative to the current\n\t\t** position. NBytes is a signed number, indicating seek direction\n\t\t** (positive for forward, negative for backward). Buffer has no meaning\n\t\t** here.\n\t\t**\n\t\t** Any error code returned will be remapped by VQA library into\n\t\t** VQAERR_SEEK.\n\t\t*/\n\t\tcase VQACMD_SEEK:\n\t\t\terror = (file->Seek(nbytes, SEEK_CUR) == -1);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tVQACMD_OPEN asks that you open your stream for access.\n\t\t*/\n\t\tcase VQACMD_OPEN:\n\t\t\tfile = new CCFileClass((char *)buffer);\n\n\t\t\tif (file != NULL && file->Is_Available()) {\n\t\t\t\terror = file->Open((char *)buffer, READ);\n\n\t\t\t\tif (error != -1) {\n\t\t\t\t\tvqa->VQAio = (unsigned long)file;\n\t\t\t\t\terror = 0;\n\t\t\t\t} else {\n\t\t\t\t\tdelete file;\n\t\t\t\t\tfile = 0;\n\t\t\t\t\terror = 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\terror = 1;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase VQACMD_CLOSE:\n\t\t\tfile->Close();\n\t\t\tdelete file;\n\t\t\tfile = 0;\n\t\t\tvqa->VQAio = 0;\n\t\t\terror = 0;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tVQACMD_INIT means to prepare your stream for reading. This is used for\n\t\t** certain streams that can't be read immediately upon opening, and need\n\t\t** further preparation. This operation is allowed to fail; the error code\n\t\t** will be returned directly to the client.\n\t\t*/\n\t\tcase VQACMD_INIT:\n\n\t\t/*\n\t\t**\tIFFCMD_CLEANUP means to terminate the transaction with the associated\n\t\t** stream. This is used for streams that can't simply be closed. This\n\t\t** operation is not allowed to fail; any error returned will be ignored.\n\t\t*/\n\t\tcase VQACMD_CLEANUP:\n\t\t\terror = 0;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\terror = 0;\n\t\t\tbreak;\n\t}\n\n\treturn(error);\n}\n\n\nvoid Rebuild_Interpolated_Palette(unsigned char * interpal)\n{\n\tfor (int y=0; y<255; y++) {\n\t\tfor (int x=y+1; x<256; x++) {\n\t\t\t*(interpal + (y*256+x)) = *(interpal + (x*256+y));\n\t\t}\n\t}\n}\n\n\nunsigned char \t* InterpolatedPalettes[50];\nBOOL\t\t\t\tPalettesRead;\nunsigned\t\t\tPaletteCounter;\n\n\n/***********************************************************************************************\n * Load_Interpolated_Palettes -- Loads in any precalculated palettes for hires VQs             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Name of palette file                                                              *\n *                                                                                             *\n * OUTPUT:   Number of palettes loaded                                                         *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/7/96 9:49AM ST : Created                                                               *\n *=============================================================================================*/\nint Load_Interpolated_Palettes(char const * filename, BOOL add)\n{\n\tint\tnum_palettes=0;\n\tint\ti;\n\tint \tstart_palette;\n\n\tPalettesRead = FALSE;\n\tCCFileClass\tfile(filename);\n\n\tif (!add) {\n\t\tfor (i=0; i < 50; i++) {\n\t\t\tInterpolatedPalettes[i]=NULL;\n\t\t}\n\t\tstart_palette=0;\n\t} else {\n\t\tfor (start_palette = 0; start_palette < 50; start_palette++) {\n\t\t\tif (!InterpolatedPalettes[start_palette]) break;\n\t\t}\n\t}\n\n\t/*\n\t**\tHack another interpolated palette if the requested one is\n\t**\tnot present.\n\t*/\n\tif (!file.Is_Available()) {\n\t\tfile.Set_Name(\"AAGUN.VQP\");\n\t}\n\n\tif (file.Is_Available()) {\n\n\t\tfile.Open(READ);\n\t\tfile.Read(&num_palettes , 4);\n\n\t\tfor (i=0; i < num_palettes; i++) {\n\t\t\tInterpolatedPalettes[i+start_palette] = (unsigned char *)malloc (65536);\n\t\t\tmemset (InterpolatedPalettes[i+start_palette], 0, 65536);\n\t\t\tfor (int y = 0; y < 256; y++) {\n\t\t\t\tfile.Read (InterpolatedPalettes[i+start_palette] + y*256 , y+1);\n\t\t\t}\n\n\t\t\tRebuild_Interpolated_Palette(InterpolatedPalettes[i+start_palette]);\n\t\t}\n\n\t\tPalettesRead = TRUE;\n\t\tfile.Close();\n\t}\n\tPaletteCounter = 0;\n\treturn (num_palettes);\n}\n\n\nvoid Free_Interpolated_Palettes(void)\n{\n\tfor (int i = 0; i < 50 ;i++) {\n\t\tif (InterpolatedPalettes[i]) {\n\t\t\tfree(InterpolatedPalettes[i]);\n\t\t\tInterpolatedPalettes[i]=NULL;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Play_Movie -- Plays a VQ movie.                                                             *\n *                                                                                             *\n *    Use this routine to play a VQ movie. It will dispatch the specified movie to the         *\n *    VQ player. The routine will not return until the movie has finished playing.             *\n *                                                                                             *\n * INPUT:   name  -- The name of the movie file (sans \".VQA\").                                 *\n *                                                                                             *\n *          theme -- The identifier for an optional theme that should be played in the         *\n *                   background while this VQ plays.                                           *\n *                                                                                             *\n *          clrscrn -- 'true' if to clear the screen when the movie is over                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef WIN32\nextern void Suspend_Audio_Thread(void);\nextern void Resume_Audio_Thread(void);\n\n#ifdef MOVIE640\nextern GraphicBufferClass VQ640;\n#endif\n#endif\nvoid Play_Movie(char const * name, ThemeType theme, bool clrscrn)\n{\n\t/*\n\t** Don't play movies in editor mode\n\t*/\n\tif (Debug_Map) {\n\t\treturn;\n\t}\n\n\t/*\n\t** Don't play movies in multiplayer mode\n\t*/\n\tif (Session.Type != GAME_NORMAL) {\n\t\treturn;\n\t}\n\n\tif (name) {\n\t\tchar fullname[_MAX_FNAME+_MAX_EXT];\n\t\t_makepath(fullname, NULL, NULL, name, \".VQA\");\n#ifdef WIN32\n\t\tchar palname [_MAX_FNAME+_MAX_EXT];\n\t\t_makepath(palname , NULL, NULL, name, \".VQP\");\n#endif\t//WIN32\n\t\t#ifdef CHEAT_KEYS\n\t\t\tMono_Set_Cursor(0, 0);Mono_Printf(\"[%s]\", fullname);\n\t\t#endif\n\n\t\tif (!CCFileClass(fullname).Is_Available()) return;\n\n\t\t/*\n\t\t**\tReset the anim control structure.\n\t\t*/\n\t\tAnim_Init();\n\n\t\t/*\n\t\t**\tPrepare to play a movie. First hide the mouse and stop any score that is playing.\n\t\t**\tWhile the score (if any) is fading to silence, fade the palette to black as well.\n\t\t**\tWhen the palette has finished fading, wait until the score has finished fading\n\t\t**\tbefore launching the movie.\n\t\t*/\n\t\tHide_Mouse();\n\t\tTheme.Queue_Song(theme);\n\t\tif (PreserveVQAScreen == 0 && !clrscrn) {\n\t\t\tBlackPalette.Set(FADE_PALETTE_MEDIUM);\n\t\t\tVisiblePage.Clear();\n\t\t\tBlackPalette.Adjust(0x08, WhitePalette);\n\t\t\tBlackPalette.Set();\n\t\t\tBlackPalette.Adjust(0xFF);\n\t\t\tBlackPalette.Set();\n\t\t}\n\t\tPreserveVQAScreen = 0;\n\t\tKeyboard->Clear();\n\n\t\tVQAHandle * vqa = NULL;\n\n\n#ifdef WIN32\n#ifdef MOVIE640\n\t\tif(IsVQ640) {\n\t\t\tAnimControl.ImageWidth = 640;\n\t\t\tAnimControl.ImageHeight = 400;\n\t\t\tAnimControl.ImageBuf = (unsigned char *)VQ640.Get_Offset();\n\t\t} else {\n\t\t\tAnimControl.ImageWidth = 320;\n\t\t\tAnimControl.ImageHeight = 200;\n\t\t\tAnimControl.ImageBuf = (unsigned char *)SysMemPage.Get_Offset();\n\t\t}\n#endif\n#endif\n\n\t\tif (!Debug_Quiet && Get_Digi_Handle() != -1) {\n\t\t\tAnimControl.OptionFlags |= VQAOPTF_AUDIO;\n\t\t} else {\n\t\t\tAnimControl.OptionFlags &= ~VQAOPTF_AUDIO;\n\t\t}\n\n\t\tif ((vqa = VQA_Alloc()) != NULL) {\n\t\t\tVQA_Init(vqa, MixFileHandler);\n\n\t\t\tif (VQA_Open(vqa, fullname, &AnimControl) == 0) {\n\t\t\t\tBrokeout = false;\n#ifdef WIN32\n\t\t\t\t//Suspend_Audio_Thread();\n#ifdef MOVIE640\n\t\t\t\tif(!IsVQ640) {\n\t\t\t\t\tLoad_Interpolated_Palettes(palname);\n\t\t\t\t}\n#else\n\t\t\t\tLoad_Interpolated_Palettes(palname);\n#endif\n\t\t\t\t//Set_Palette(BlackPalette);\n\t\t\t\tSysMemPage.Clear();\n\t\t\t\tInMovie = true;\n#endif\t//WIN32\n\t\t\t\tVQA_Play(vqa, VQAMODE_RUN);\n\t\t\t\tVQA_Close(vqa);\n#ifdef WIN32\n\t\t\t\t//Resume_Audio_Thread();\n\t\t\t\tInMovie = FALSE;\n#ifdef MOVIE640\n\t\t\t\tif(!IsVQ640) {\n\t\t\t\t\tFree_Interpolated_Palettes();\n\t\t\t\t}\n#else\n\t\t\t\tFree_Interpolated_Palettes();\n#endif\n\t\t\t\tIsVQ640 = false;\n\t\t\t\tSet_Primary_Buffer_Format();\n#endif\t//WIN32\n\n\t\t\t\t/*\n\t\t\t\t**\tAny movie that ends prematurely must have the screen\n\t\t\t\t**\tcleared to avoid any unexpected palette glitches.\n\t\t\t\t*/\n\t\t\t\tif (Brokeout) {\n\t\t\t\t\tclrscrn = true;\n\t\t\t\t\tVisiblePage.Clear();\n\t\t\t\t\tBrokeout = false;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t#ifndef NDEBUG\n\t\t\t\t\tbool error = true;\n\t\t\t\t\tassert(error);\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\tVQA_Free(vqa);\n\t\t} else {\n\t\t\tassert(vqa != NULL);\n\t\t}\n\n\t\t/*\n\t\t**\tPresume that the screen is left in a garbage state as well as the palette\n\t\t**\tbeing in an unknown condition. Recover from this by clearing the screen and\n\t\t**\tforcing the palette to black.\n\t\t*/\n\t\tif (clrscrn) {\n\t\t\tVisiblePage.Clear();\n\t\t\tBlackPalette.Adjust(0x08, WhitePalette);\n\t\t\tBlackPalette.Set();\n\t\t\tBlackPalette.Adjust(0xFF);\n\t\t\tBlackPalette.Set();\n\t\t}\n\t\tShow_Mouse();\n\t}\n}\n\n\nvoid Play_Movie(VQType name, ThemeType theme, bool clrscrn)\n{\n\tif (name != VQ_NONE) {\n\t\tif (name == VQ_REDINTRO) {\n\t\t\tIsVQ640 = true;\n\t\t}\n\t\tPlay_Movie(VQName[name], theme, clrscrn);\n\t\tIsVQ640 = false;\n\t}\n}\n\n\n/***********************************************************************************************\n * Unselect_All -- Causes all selected objects to become unselected.                           *\n *                                                                                             *\n *    This routine will unselect all objects that are currently selected.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Unselect_All(void)\n{\n\twhile (CurrentObject.Count()) {\n\t\tCurrentObject[0]->Unselect();\n\t}\n}\n\n\n/***********************************************************************************************\n * Fading_Table_Name -- Builds a theater specific fading table name.                           *\n *                                                                                             *\n *    This routine builds a standard fading table name. This name is dependant on the theater  *\n *    being played, since each theater has its own palette.                                    *\n *                                                                                             *\n * INPUT:   base  -- The base name of this fading table. The base name can be no longer than   *\n *                   seven characters.                                                         *\n *                                                                                             *\n *          theater  -- The theater that this fading table is specific to.                     *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the constructed fading table filename. This pointer is   *\n *          valid until this function is called again.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * Fading_Table_Name(char const * base, TheaterType theater)\n{\n\tstatic char _buffer[_MAX_FNAME+_MAX_EXT];\n\tchar root[_MAX_FNAME];\n\n\tsprintf(root, \"%1.1s%s\", Theaters[theater].Root, base);\n\t_makepath(_buffer, NULL, NULL, root, \".MRF\");\n\treturn(_buffer);\n}\n\n\n/***********************************************************************************************\n * Get_Radar_Icon -- Builds and alloc a radar icon from a shape file                           *\n *                                                                                             *\n * INPUT:      void const * shapefile - pointer to a key framed shapefile                      *\n *             int shapenum          - shape to extract from shapefile                         *\n *                                                                                             *\n * OUTPUT:     void const *           - 3/3 icon set of shape from file                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/12/1995 PWG : Created.                                                                 *\n *   05/10/1995 JLB : Handles a null shapefile pointer.                                        *\n *=============================================================================================*/\nvoid const * Get_Radar_Icon(void const * shapefile, int shapenum, int frames, int zoomfactor)\n{\n\tstatic int _offx[]={\t0, 0,  -1,  1, 0, -1, 1, -1, 1};\n\tstatic int _offy[]={\t0, 0,  -1,  1, 0, -1, 1, -1, 1};\n\tint lp,framelp;\n\tchar pixel;\n\n\tchar * retval = NULL;\n\tchar * buffer = NULL;\n\n\t/*\n\t**\tIf there is no shape file, then there can be no radar icon imagery.\n\t*/\n\tif (!shapefile) return(NULL);\n\n#if (0)\n\tCCPalette.Set();\n\tSet_Logic_Page(SeenBuff);\n\tCC_Draw_Shape(shapefile, shapenum, 64, 64, WINDOW_MAIN, SHAPE_WIN_REL);\n#endif\n\n\t/*\n\t** Get the pixel width and height of the frame we built.  This will\n\t** be used to extract icons and build pixels.\n\t*/\n\tint pixel_width  = Get_Build_Frame_Width( shapefile );\n\tint pixel_height = Get_Build_Frame_Height( shapefile );\n\n\t/*\n\t** Find the width and height in icons, adjust these by half an\n\t** icon because the artists may be sloppy and miss the edge of an\n\t** icon one way or the other.\n\t*/\n\tint icon_width\t = (pixel_width + 12) / 24;\n\tint icon_height = (pixel_height + 12) / 24;\n\n\t/*\n\t** If we have been told to build as many frames as possible, then\n\t** find out how many frames there are to build.\n\t*/\n\tif (frames == -1) frames = Get_Build_Frame_Count( shapefile );\n\n\t/*\n\t** Allocate a position to store our icons.  If the alloc fails then\n\t** we don't add these icons to the set.\n\t**/\n\tbuffer = new char[(icon_width * icon_height * 9 * frames)+2];\n\tif (!buffer) return(NULL);\n\n\t/*\n\t** Save off the return value so that we can return it to the calling\n\t** function.\n\t*/\n\tretval\t = (char *)buffer;\n\t*buffer++ = (char)icon_width;\n\t*buffer++ = (char)icon_height;\n\tint val = 24/zoomfactor;\n\n\tfor (framelp = 0; framelp < frames; framelp ++) {\n\t\t/*\n\t\t** Build the current frame.  If the frame can not be built then we\n\t\t** just need to skip past this set of icons and try to build the\n\t\t** next frame.\n\t\t*/\n#ifdef WIN32\n\t\tvoid * ptr;\n\t\tif ((ptr = (void *)(Build_Frame(shapefile, shapenum + framelp, SysMemPage.Get_Buffer()))) != NULL) {\n\t\t\tptr = Get_Shape_Header_Data(ptr);\n#else\t//WIN#@\n\t\tif (Build_Frame(shapefile, shapenum + framelp, HidPage.Get_Buffer()) <= (unsigned long)HidPage.Get_Size() ) {\n#endif\t//WIN32\n\n\t\t\t/*\n\t\t\t** Loop through the icon width and the icon height building icons\n\t\t\t** into the buffer pointer.  When the getx or gety falls outside of\n\t\t\t** the width and height of the shape, just insert transparent pixels.\n\t\t\t*/\n\t\t\tfor (int icony = 0; icony < icon_height; icony ++) {\n\t\t\t\tfor (int iconx = 0; iconx < icon_width; iconx ++) {\n#ifdef WIN32\n\n\t\t\t\t\tfor (int y = 0; y < zoomfactor; y++) {\n\t\t\t\t\t\tfor (int x = 0; x < zoomfactor; x++) {\n\t\t\t\t\t\t\tint getx = (iconx * 24) + (x * val) + (zoomfactor / 2);\n\t\t\t\t\t\t\tint gety = (icony * 24) + (y * val) + (zoomfactor / 2);\n\t\t\t\t\t\t\tif ((getx < pixel_width) && (gety < pixel_height)) {\n\t\t\t\t\t\t\t\tfor (lp = 0; lp < 9; lp ++) {\n\t\t\t\t\t\t\t\t\tpixel\t= *(char *)((char *)ptr + ((gety - _offy[lp]) * pixel_width) + getx-_offx[lp]);\n\n#else\t//WIN32\n\t\t\t\t\tfor (int y = 0; y < 3; y++) {\n\t\t\t\t\t\tfor (int x = 0; x < 3; x++) {\n\t\t\t\t\t\t\tint getx = (iconx * 24) + (x << 3) + 4;\n\t\t\t\t\t\t\tint gety = (icony * 24) + (y << 3) + 4;\n\t\t\t\t\t\t\tif ((getx < pixel_width) && (gety < pixel_height)) {\n\t\t\t\t\t\t\t\tfor (lp = 0; lp < 9; lp ++) {\n\t\t\t\t\t\t\t\t\tpixel\t= *(char *)((char *)HidPage.Get_Buffer(), ((gety - _offy[lp]) * pixel_width) + getx-_offx[lp]);\n#endif\t//WIN32\n\t\t\t\t\t\t\t\t\tif (pixel == LTGREEN) pixel = 0;\n\t\t\t\t\t\t\t\t\tif (pixel) {\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t*buffer++ = pixel;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t*buffer++ = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tbuffer += icon_width * icon_height * 9;\n\t\t}\n\t}\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * CC_Draw_Shape -- Custom draw shape handler.                                                 *\n *                                                                                             *\n *    All draw shape calls will route through this function. It handles all draws for          *\n *    C&C. Such draws always occur to the logical page and assume certain things about         *\n *    the parameters passed.                                                                   *\n *                                                                                             *\n * INPUT:   shapefile   -- Pointer to the shape data file. This data file contains all the     *\n *                         embedded shapes.                                                    *\n *                                                                                             *\n *          shapenum    -- The shape number within the shapefile that will be drawn.           *\n *                                                                                             *\n *          x,y         -- The pixel coordinates to draw the shape.                            *\n *                                                                                             *\n *          window      -- The clipping window to use.                                         *\n *                                                                                             *\n *          flags       -- The custom draw shape flags. This controls how the parameters       *\n *                         are used (if any).                                                  *\n *                                                                                             *\n *          fadingdata  -- If SHAPE_FADING is desired, then this points to the fading          *\n *                         data table.                                                         *\n *                                                                                             *\n *          ghostdata   -- If SHAPE_GHOST is desired, then this points to the ghost remap      *\n *                         table.                                                              *\n *                                                                                             *\n *          rotation    -- Rotation to apply to the shape (DIR_N = no rotation at all).        *\n *                                                                                             *\n *          scale       -- 24.8 fixed point scale factor.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CC_Draw_Shape(void const * shapefile, int shapenum, int x, int y, WindowNumberType window, ShapeFlags_Type flags, void const * fadingdata, void const * ghostdata, DirType rotation, long scale)\n{\n\tint predoffset;\n#ifdef WIN32\n\tunsigned\tlong\tshape_pointer;\n#endif\t//WIN32\n\n\n\t/*\n\t** Special kludge for E3 to prevent crashes\n\t*/\n\tif ((flags & SHAPE_GHOST) && (!ghostdata)) {\n\t\tghostdata = DisplayClass::SpecialGhost;\n\t}\n\tif ((flags & SHAPE_FADING) && (!fadingdata)) {\n\t\tfadingdata = DisplayClass::FadingShade;\n\t}\n\n\tstatic unsigned char * _xbuffer = 0;\n\n\tif (!_xbuffer) {\n\t\t_xbuffer = new unsigned char[SHAPE_BUFFER_SIZE];\n\t}\n\n\tif (shapefile != NULL && shapenum != -1) {\n\n\t\tint width = Get_Build_Frame_Width(shapefile);\n\t\tint height = Get_Build_Frame_Height(shapefile);\n\n#ifdef NEVER\n\t\t/*\n\t\t**\tPerform a quick clip check against the destination rectangle.\n\t\t*/\n\t\tif (flags & SHAPE_CENTER) {\n\t\t\tif (x-width/2 >= WindowList[window][WINDOWWIDTH]) return;\n\t\t\tif (y-width/2 >= WindowList[window][WINDOWHEIGHT]) return;\n\t\t\tif (x+width/2 < 0) return;\n\t\t\tif (y+height/2 < 0) return;\n\n\t\t} else {\n\t\t\tif (x >= WindowList[window][WINDOWWIDTH]) return;\n\t\t\tif (y >= WindowList[window][WINDOWHEIGHT]) return;\n\t\t\tif (x+width < 0) return;\n\t\t\tif (y+height < 0) return;\n\t\t}\n#endif\n\n\n#ifdef WIN32\n\t\t/*\n\t\t** In WIn95, build shape returns a pointer to the shape not its size\n\t\t*/\n\t\tshape_pointer = Build_Frame(shapefile, shapenum, _ShapeBuffer);\n\t\tif (shape_pointer) {\n\t\t\tGraphicViewPortClass draw_window(LogicPage->Get_Graphic_Buffer(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWX] + LogicPage->Get_XPos(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWY] + LogicPage->Get_YPos(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWWIDTH],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWHEIGHT]);\n\t\t\tunsigned char * buffer = (unsigned char *) shape_pointer;\t//Get_Shape_Header_Data((void*)shape_pointer);\n\n#else\t//WIN32\n\t\tif ( Build_Frame(shapefile, shapenum, _ShapeBuffer ) <= (unsigned long)_ShapeBufferSize) {\n\t\t\tGraphicViewPortClass draw_window(LogicPage,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWX],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWY],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWWIDTH],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWHEIGHT]);\n\t\t\tunsigned char * buffer = (unsigned char *)_ShapeBuffer;\n#endif\t//WIN32\n\n\t\t\tUseOldShapeDraw = false;\n\t\t\t/*\n\t\t\t**\tRotation and scale handler.\n\t\t\t*/\n\t\t\tif (rotation != DIR_N || scale != 0x0100) {\n\n\t\t\t\t/*\n\t\t\t\t** Get the raw shape data without the new header and flag to use the old shape drawing\n\t\t\t\t*/\n\t\t\t\tUseOldShapeDraw = true;\n#ifdef WIN32\n\t\t\t\tbuffer = (unsigned char *) Get_Shape_Header_Data((void*)shape_pointer);\n#endif\n\n\t\t\t\tif (Debug_Rotate) {\n\n\t\t\t\t\tGraphicBufferClass src(width, height, buffer);\n\t\t\t\t\twidth *= 2;\n\t\t\t\t\theight *= 2;\n\t\t\t\t\tmemset(_xbuffer, '\\0', SHAPE_BUFFER_SIZE);\n\t\t\t\t\tGraphicBufferClass dst(width, height, _xbuffer);\n\t\t\t\t\tRotate_Bitmap(&src, &dst, rotation);\n\t\t\t\t\tbuffer = _xbuffer;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tBitmapClass bm(width, height, buffer);\n\t\t\t\t\twidth *= 2;\n\t\t\t\t\theight *= 2;\n\t\t\t\t\tmemset(_xbuffer, '\\0', SHAPE_BUFFER_SIZE);\n\t\t\t\t\tGraphicBufferClass gb(width, height, _xbuffer);\n\t\t\t\t\tTPoint2D pt(width/2, height/2);\n\n\t\t\t\t\tgb.Scale_Rotate(bm, pt, scale, (256-(rotation-64)));\n\t\t\t\t\tbuffer = _xbuffer;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSpecial shadow drawing code (used for aircraft and bullets).\n\t\t\t*/\n\t\t\tif ((flags & (SHAPE_FADING|SHAPE_PREDATOR)) == (SHAPE_FADING|SHAPE_PREDATOR)) {\n\t\t\t\tflags = flags & ~(SHAPE_FADING|SHAPE_PREDATOR);\n\t\t\t\tflags = flags | SHAPE_GHOST;\n\t\t\t\tghostdata = DisplayClass::SpecialGhost;\n\t\t\t}\n\n\t\t\tpredoffset = Frame;\n\n\t\t\tif (x > ( WindowList[window][WINDOWWIDTH] << 2)) {\n\t\t\t\tpredoffset = -predoffset;\n\t\t\t}\n\n\t\t\tif (draw_window.Lock()) {\n\t\t\t\tif ((flags & (SHAPE_GHOST|SHAPE_FADING)) == (SHAPE_GHOST|SHAPE_FADING)) {\n\t\t\t\t\tBuffer_Frame_To_Page(x, y, width, height, buffer, draw_window, flags | SHAPE_TRANS, ghostdata, fadingdata, 1, predoffset);\n\t\t\t\t} else {\n\t\t\t\t\tif (flags & SHAPE_FADING) {\n\t\t\t\t\t\tBuffer_Frame_To_Page(x, y, width, height, buffer, draw_window, flags | SHAPE_TRANS, fadingdata, 1, predoffset);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (flags & SHAPE_PREDATOR) {\n\t\t\t\t\t\t\tBuffer_Frame_To_Page(x, y, width, height, buffer, draw_window, flags | SHAPE_TRANS, predoffset);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tBuffer_Frame_To_Page(x, y, width, height, buffer, draw_window, flags | SHAPE_TRANS, ghostdata, predoffset);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdraw_window.Unlock();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Shape_Dimensions -- Determine the minimum rectangle for the shape.                          *\n *                                                                                             *\n *    This routine will calculate (using brute forced) the minimum rectangle that will         *\n *    enclose the pixels of the shape. This rectangle will be relative to the upper left       *\n *    corner of the maximum shape size. By using this minimum rectangle, it is possible to     *\n *    greatly optimize the map 'dirty rectangle' logic.                                        *\n *                                                                                             *\n * INPUT:   shapedata   -- Pointer to the shape data block.                                    *\n *                                                                                             *\n *          shapenum    -- The shape number to examine. Each shape would have a different      *\n *                         dimension rectangle.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the rectangle that encloses the shape.                                *\n *                                                                                             *\n * WARNINGS:   This routine uses brute force and is slow. It is presumed that the results      *\n *             will be cached for subsiquent reuse.                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/22/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRect const Shape_Dimensions(void const * shapedata, int shapenum)\n{\n\tRect rect;\n\n\tif (shapedata == NULL || shapenum < 0 || shapenum > Get_Build_Frame_Count(shapedata)) {\n\t\treturn(rect);\n\t}\n\n\tchar * shape;\n#ifdef WIN32\n\tvoid * sh = (void *)Build_Frame(shapedata, shapenum, _ShapeBuffer);\n\tif (sh == NULL) return(rect);\n//\tshape = (char *)sh;\n\tshape = (char *)Get_Shape_Header_Data(sh);\n#else\n\tBuild_Frame(shapedata, shapenum, _ShapeBuffer);\n\tshape = (char *)_ShapeBuffer;\n#endif\n\n\tint width = Get_Build_Frame_Width(shapedata);\n\tint height = Get_Build_Frame_Height(shapedata);\n\n\trect.X = 0;\n\trect.Y = 0;\n\tint xlimit = width-1;\n\tint ylimit = height-1;\n\n\t/*\n\t**\tFind top edge of the shape.\n\t*/\n\tfor (int y = 0; y <= ylimit; y++) {\n\t\tfor (int x = 0; x <= xlimit; x++) {\n\t\t\tif (shape[y*width + x] != 0) {\n\t\t\t\trect.Y = y;\n\t\t\t\trect.X = x;\n\t\t\t\ty = ylimit+1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tFind bottom edge of the shape.\n\t*/\n\tfor (y = ylimit; y >= rect.Y; y--) {\n\t\tfor (int x = xlimit; x >= 0; x--) {\n\t\t\tif (shape[y*width + x] != 0) {\n\t\t\t\trect.Height = (y-rect.Y)+1;\n\t\t\t\txlimit = x;\n\t\t\t\ty = rect.Y-1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tFind left edge of the shape.\n\t*/\n\tfor (int x = 0; x < rect.X; x++) {\n\t\tfor (y = rect.Y; y < rect.Y+rect.Height; y++) {\n\t\t\tif (shape[y*width + x] != 0) {\n\t\t\t\trect.X = x;\n\t\t\t\tx = rect.X;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tFind the right edge of the shape.\n\t*/\n\tfor (x = width-1; x >= xlimit; x--) {\n\t\tfor (y = rect.Y; y < rect.Y+rect.Height; y++) {\n\t\t\tif (shape[y*width + x] != 0) {\n\t\t\t\trect.Width = (x-rect.X)+1;\n\t\t\t\tx = xlimit-1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tNormalize the rectangle around the center of the shape.\n\t*/\n\trect.X -= width / 2;\n\trect.Y -= height / 2;\n\n\t/*\n\t**\tReturn with the minimum rectangle that encloses the shape.\n\t*/\n\treturn(rect);\n}\n\n\n/***********************************************************************************************\n * Fetch_Techno_Type -- Convert type and ID into TechnoTypeClass pointer.                      *\n *                                                                                             *\n *    This routine will convert the supplied RTTI type number and the ID value into a valid    *\n *    TechnoTypeClass pointer. If there is an error in conversion, then NULL is returned.      *\n *                                                                                             *\n * INPUT:   type  -- RTTI type of the techno class object.                                     *\n *                                                                                             *\n *          id    -- Integer representation of the techno sub type number.                     *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the techno type class object specified or NULL if the    *\n *          conversion could not occur.                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTechnoTypeClass const * Fetch_Techno_Type(RTTIType type, int id)\n{\n\tswitch (type) {\n\t\tcase RTTI_UNITTYPE:\n\t\tcase RTTI_UNIT:\n\t\t\treturn(&UnitTypeClass::As_Reference(UnitType(id)));\n\n\t\tcase RTTI_VESSELTYPE:\n\t\tcase RTTI_VESSEL:\n\t\t\treturn(&VesselTypeClass::As_Reference(VesselType(id)));\n\n\t\tcase RTTI_BUILDINGTYPE:\n\t\tcase RTTI_BUILDING:\n\t\t\treturn(&BuildingTypeClass::As_Reference(StructType(id)));\n\n\t\tcase RTTI_INFANTRYTYPE:\n\t\tcase RTTI_INFANTRY:\n\t\t\treturn(&InfantryTypeClass::As_Reference(InfantryType(id)));\n\n\t\tcase RTTI_AIRCRAFTTYPE:\n\t\tcase RTTI_AIRCRAFT:\n\t\t\treturn(&AircraftTypeClass::As_Reference(AircraftType(id)));\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * VQ_Call_Back -- Maintenance callback used for VQ movies.                                    *\n *                                                                                             *\n *    This routine is called every frame of the VQ movie as it is being played. If this        *\n *    routine returns non-zero, then the movie will stop.                                      *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the image buffer for the current frame.                     *\n *                                                                                             *\n *          frame    -- The frame number about to be displayed.                                *\n *                                                                                             *\n * OUTPUT:  Should the movie be stopped?                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef WIN32\nvoid VQA_PauseAudio(void);\nvoid Check_VQ_Palette_Set(void);\n\nextern GraphicBufferClass VQ640;\nextern bool IsVQ640;\nlong VQ_Call_Back(unsigned char *, long )\n{\n\tint key = 0;\n\tif (Keyboard->Check()) {\n\t\tkey = Keyboard->Get();\n\t\tKeyboard->Clear();\n\t}\n\tCheck_VQ_Palette_Set();\n#ifdef MOVIE640\n\tif(IsVQ640) {\n\t\tVQ640.Blit(SeenBuff);\n\t} else {\n\t\tInterpolate_2X_Scale(&SysMemPage, &SeenBuff, NULL);\n\t}\n#else\n\tInterpolate_2X_Scale(&SysMemPage, &SeenBuff, NULL);\n#endif\n\t//Call_Back();\n\n\tif ((BreakoutAllowed || Debug_Flag) && key == KN_ESC) {\n\t\tKeyboard->Clear();\n\t\tBrokeout = true;\n\t\treturn(true);\n\t}\n\n\tif (!GameInFocus) {\n\t\tVQA_PauseAudio();\n\t\twhile (!GameInFocus) {\n\t\t\tCheck_For_Focus_Loss();\n\t\t}\n\t}\n\treturn(false);\n}\n\n#else\t//WIN32\n\nlong VQ_Call_Back(unsigned char *, long )\n{\n\tCall_Back();\n\tif ((BreakoutAllowed || Debug_Flag) && Keyboard->Check()) {\n\t\tif (Keyboard->Get() == KN_ESC) {\n\t\t\tKeyboard->Clear();\n\t\t\tBrokeout = true;\n\t\t\treturn(true);\n\t\t}\n\t\tKeyboard->Clear();\n\t}\n\treturn(false);\n}\n#endif\t//WIN32\n\n\n/***********************************************************************************************\n * Handle_Team -- Processes team selection command.                                            *\n *                                                                                             *\n *    This routine will handle creation and selection of pseudo teams that the player can      *\n *    create or control. A team in this sense is an arbitrary grouping of units such that      *\n *    rapid selection control is allowed.                                                      *\n *                                                                                             *\n * INPUT:   team  -- The logical team number to process.                                       *\n *                                                                                             *\n *          action-- The action to perform on this team:                                       *\n *                   0 - Toggle the select state for all members of this team.                 *\n *                   1 - Select the members of this team.                                      *\n *                   2 - Make all selected objects members of this team.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Handle_Team(int team, int action)\n{\n\tint index;\n\n\t//\n\t// Recording support\n\t//\n\tif (Session.Record) {\n\t\tTeamNumber = (char)team;\n\t\tTeamEvent = (char)action + 1;\n\t}\n\n\tAllowVoice = true;\n\tswitch (action) {\n\n\t\t/*\n\t\t**\tToggle the team selection. If the team is selected, then merely unselect it. If the\n\t\t**\tteam is not selected, then unselect all others before selecting this team.\n\t\t*/\n\t\tcase 3:\n\t\tcase 0:\n\n\t\t\t/*\n\t\t\t**\tIf a non team member is currently selected, then deselect all objects\n\t\t\t**\tbefore selecting this team.\n\t\t\t*/\n\t\t\tif (CurrentObject.Count()) {\n\t\t\t\tif (CurrentObject[0]->Is_Foot() && ((FootClass *)CurrentObject[0])->Group != team) {\n\t\t\t\t\tUnselect_All();\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->IsSelected) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->IsSelected) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->IsSelected) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\t\t\tAircraftClass * obj = Aircraft.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->IsSelected) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCenter the map around the team if the ALT key was pressed too.\n\t\t\t*/\n\t\t\tif (action == 3) {\n\t\t\t\tMap.Center_Map();\n#ifdef WIN32\n\t\t\t\tMap.Flag_To_Redraw(true);\n#endif\t//WIn32\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tAdditive selection of team.\n\t\t*/\n\t\tcase 1:\n\t\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->IsSelected) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->IsSelected) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->IsSelected) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\t\t\tAircraftClass * obj = Aircraft.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->IsSelected) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tCreate the team.\n\t\t*/\n\t\tcase 2: {\n\t\t\tlong minx = 0x7FFFFFFFL, miny = 0x7FFFFFFFL;\n\t\t\tlong maxx = 0, maxy = 0;\n\t\t\tTeamSpeed[team] = SPEED_WHEEL;\n\t\t\tTeamMaxSpeed[team] = MPH_LIGHT_SPEED;\n\t\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl) {\n\t\t\t\t \tif (obj->Group == team) obj->Group = 0xFF;\n\t\t\t\t\tif (obj->IsSelected) {\n\t\t\t\t\t\tobj->Group = team;\n\t\t\t\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\t\t\tif (obj->Class->MaxSpeed < TeamMaxSpeed[team]) {\n\t\t\t\t\t\t\tTeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t\t\t\tTeamSpeed[team] = obj->Class->Speed;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl) {\n\t\t\t\t \tif (obj->Group == team) obj->Group = -1;\n\t\t\t\t\tif (obj->IsSelected) {\n\t\t\t\t\t\tobj->Group = team;\n\t\t\t\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\t\t\tif (obj->Class->MaxSpeed < TeamMaxSpeed[team]) {\n\t\t\t\t\t\t\tTeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t\t\t\tTeamSpeed[team] = obj->Class->Speed;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl) {\n\t\t\t\t \tif (obj->Group == team) obj->Group = 0xFF;\n\t\t\t\t\tif (obj->IsSelected) {\n\t\t\t\t\t\tobj->Group = team;\n\t\t\t\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\t\t\tif (obj->Class->MaxSpeed < TeamMaxSpeed[team]) {\n\t\t\t\t\t\t\tTeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\t\t\tAircraftClass * obj = Aircraft.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl) {\n\t\t\t\t \tif (obj->Group == team) obj->Group = 0xFF;\n\t\t\t\t\tif (obj->IsSelected) {\n\t\t\t\t\t\tobj->Group = team;\n\t\t\t\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl &&\n\t\t\t\t \t(obj->Group == team) && (obj->IsSelected) ) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** When a team is first created, they're created without a\n\t\t\t\t\t** formation offset, so they will not be created in\n\t\t\t\t\t** formation.  Later, if they're assigned a formation, the\n\t\t\t\t\t** XFormOffset & YFormOffset numbers will change to valid\n\t\t\t\t\t** offsets, and they'll be formationed.\n\t\t\t\t\t*/\n#if(1)\n\t\t\t\t\tobj->XFormOffset = obj->YFormOffset = (int)0x80000000;\n#else\n#if(1)\n// Old always-north formation stuff\n\t\t\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\t\t\tobj->YFormOffset = yc - centery;\n#else\n// New method: save direction and distance rather than x & y offset\n\t\t\t\t\t\tobj->XFormOffset = ::Direction(As_Coord(center), obj->Center_Coord());\n\t\t\t\t\t\tobj->YFormOffset = ::Distance (As_Coord(center), obj->Center_Coord());\n#endif\n#endif\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl) {\n\t\t\t\t \tif (obj->Group == team) obj->Group = 0xFF;\n\t\t\t\t\tif (obj->IsSelected) obj->Group = team;\n\t\t\t\t\tif (obj->Group == team  && obj->IsSelected) {\n#if(1)\n\t\t\t\t\t\tobj->XFormOffset = obj->YFormOffset = (int)0x80000000;\n#else\n#if(1)\n// Old always-north formation stuff\n\t\t\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\t\t\tobj->YFormOffset = yc - centery;\n#else\n// New method: save direction and distance rather than x & y offset\n\t\t\t\t\t\tobj->XFormOffset = ::Direction(As_Coord(center), obj->Center_Coord());\n\t\t\t\t\t\tobj->YFormOffset = ::Distance (As_Coord(center), obj->Center_Coord());\n#endif\n#endif\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tAllowVoice = true;\n}\n\n\n/***********************************************************************************************\n * Handle_View -- Either records or restores the tactical view.                                *\n *                                                                                             *\n *    This routine is used to record or restore the current map tactical view.                 *\n *                                                                                             *\n * INPUT:   view  -- The view number to work with.                                             *\n *                                                                                             *\n *          action-- The action to perform with this view number.                              *\n *                   0  =  Restore the view to this previously remembered location.            *\n *                   1  =  Record the current view location.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Handle_View(int view, int action)\n{\n\tif ((unsigned)view < sizeof(Scen.Views)/sizeof(Scen.Views[0])) {\n\t\tif (action == 0) {\n\t\t\tMap.Set_Tactical_Position(Coord_Whole(Cell_Coord(Scen.Views[view])));\n#ifdef WIN32\n\t\t\t/*\n\t\t\t** Win95 scrolling logic cant handle just jumps in screen position so redraw the lot.\n\t\t\t*/\n\t\t\tMap.Flag_To_Redraw (true);\n#endif\t//WIN32\n\t\t} else {\n\t\t\tScen.Views[view] = Coord_Cell(Map.TacticalCoord);\n\t\t}\n\t}\n}\n\n\n#ifndef ROR_NOT_READY\n#define ROR_NOT_READY 21\n#endif\n\nstatic char * _CD_Volume_Label[] = {\n\t\"CD1\",\n\t\"CD2\",\n};\nstatic int _Num_Volumes = ARRAY_SIZE(_CD_Volume_Label);\n\n\n#ifdef WIN32\n/***********************************************************************************************\n * Get_CD_Index -- returns the volume type of the CD in the given drive                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    drive number                                                                      *\n *           timeout                                                                           *\n *                                                                                             *\n * OUTPUT:   0 = gdi                                                                           *\n *           1 = nod                                                                           *\n *           2 = covert                                                                        *\n *          -1 = non C&C                                                                       *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/21/96 5:27PM ST : Created                                                              *\n *=============================================================================================*/\nint Get_CD_Index (int cd_drive, int timeout)\n{\n\tchar\t\tvolume_name[128];\n\tchar\t\tbuffer[128];\n\tunsigned\tfilename_length;\n\tunsigned\tmisc_dword;\n\tint\t\tcount = 0;\n\n\tCountDownTimerClass timer;\n\n\n\n\ttimer.Set(timeout);\n\n\n\t/*\n\t** Get the volume label. If we get a 'not ready' error then retry for the timeout\n\t** period.\n\t*/\n\tfor (;;) {\n\t\tsprintf(buffer, \"%c:\\\\\", 'A' + cd_drive);\n\t\tif (GetVolumeInformation ((char const *)buffer,\n\t\t\t\t\t\t\t\t\t\t\t&volume_name[0] ,\n\t\t\t\t\t\t\t\t\t\t\t(unsigned long)sizeof(volume_name),\n\t\t\t\t\t\t\t\t\t\t\t(unsigned long *)NULL ,\n\t\t\t\t\t\t\t\t\t\t\t(unsigned long *)&filename_length,\n\t\t\t\t\t\t\t\t\t\t\t(unsigned long *)&misc_dword ,\n\t\t\t\t\t\t\t\t\t\t\t(char *)NULL ,\n\t\t\t\t\t\t\t\t\t\t\t(unsigned long)0)) {\n\n\t\t\t/*\n\t\t\t** Try opening 'movies.mix' to verify that the CD is really there and is what\n\t\t\t** it says it is.\n\t\t\t*/\n\t\t\tsprintf(buffer, \"%c:\\\\main.mix\", 'A' + cd_drive);\n\n\t\t\tHANDLE handle = CreateFile(buffer, GENERIC_READ, FILE_SHARE_READ,\n\t\t\t\t\t\t\t\t\t\t\t\t\tNULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n\n\t\t\tif (handle != INVALID_HANDLE_VALUE) {\n\t\t\t\tCloseHandle(handle);\n\n\t\t\t\t/*\n\t\t\t\t** Match the volume label to the list of known C&C volume labels.\n\t\t\t\t*/\n\t\t\t\tfor (int i=0 ; i<_Num_Volumes ; i++) {\n\t\t\t\t\tif (!stricmp(_CD_Volume_Label[i], volume_name)) return (i);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!count)\n\t\t\t\t\tcount++;\n\t\t\t\telse return -1;\n\t\t\t}\n\t\t} else {\n\t\t\t/*\n\t\t\t** Failed to get the volume label on a known CD drive.\n\t\t\t** If this is a CD changer it may require time to swap the disks so dont return\n\t\t\t** immediately if the error is ROR_NOT_READY\n\t\t\t*/\n\t\t\tif (!timer.Time()) return -1;\n\t\t\tint val = GetLastError();\n\t\t\tif (val != ROR_NOT_READY) return -1;\n\t\t}\n\t}\n}\n#else\nint Get_CD_Index (int cd_drive, int )\n{\n\tchar\t\tbuffer[128];\n\n\t/*\n\t** We need to do this twice because of the possibilities of a directory\n\t** being cached.  If this is so, it will only be discovered when we\n\t** actually attempt to read a file from the drive.\n\t*/\n\tif(cd_drive) for (int count = 0; count < 2; count ++) {\n\t\tstruct find_t ft;\n\t\tint file;\n\t\tint open_failed;\n\n\t\t/*\n\t\t** Create a path for the cd drive and attempt to read the volume label from\n\t\t** it.\n\t\t*/\n\t\tsprintf(buffer, \"%c:\\\\\", 'A' + cd_drive);\n\n\t\t/*\n\t\t** If we are able to read the volume label, this is good but not enough.\n\t\t** Further verification must be done.\n\t\t*/\n\t\tif (!_dos_findfirst(buffer, _A_VOLID, &ft)) {\n\n\t\t\t/*\n\t\t\t** Since some versions of disk cacheing software will cache the CD's\n\t\t\t** directory tracks, we may think the CD is in the drive when it is\n\t\t\t** actually not.  To resolve this we must attempt to open a file on\n\t\t\t** the cd.  Opening a file will always update the directory tracks\n\t\t\t** (suposedly).\n\t\t\t*/\n\t\t\tsprintf(buffer, \"%c:\\\\main.mix\", 'A' + cd_drive);\n\t\t\topen_failed = _dos_open(buffer, O_RDONLY|SH_DENYNO, &file);\n\t\t\tif (!open_failed) {\n\t\t\t\t_dos_close(file);\n\n\t\t\t\t/*\n\t\t\t\t** Hey some times the stupid dos driver appends a period to the\n\t\t\t\t** name if it is eight characters long.  If the last char is a\n\t\t\t\t** period then erase it.\n\t\t\t\t*/\n\t\t\t\tif (ft.name[strlen(ft.name)-1] == '.') {\n\t\t\t\t\tft.name[strlen(ft.name)-1] = 0;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Match the volume label to the list of known C&C volume labels.\n\t\t\t\t*/\n\t\t\t\tfor (int i=0 ; i < _Num_Volumes ; i++) {\n\t\t\t\t\tif (!stricmp(_CD_Volume_Label[i], ft.name)) return (i);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn -1;\n}\n#endif\n\n\n/***********************************************************************************************\n * Force_CD_Available -- Ensures that specified CD is available.                               *\n *                                                                                             *\n *    Call this routine when you need to ensure that the specified CD is actually in the       *\n *    CD-ROM drive.                                                                            *\n *                                                                                             *\n * INPUT:   cd    -- The CD that must be available. This will either be \"0\" for the GDI CD, or *\n *                   \"1\" for the Nod CD. If either CD will qualify, then pass in \"-1\".         *\n *                                                                                             *\n * OUTPUT:  Is the CD inserted and available? If false is returned, then this indicates that   *\n *          the player pressed <CANCEL>.                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1995 JLB : Created.                                                                 *\n *   05/22/1996  ST : Handles multiple CD drives / CD changers                                 *\n *=============================================================================================*/\nbool Force_CD_Available(int cd)\n{\n#ifndef DEMO\n\tstatic int _last = -1;\n#endif\n//\tstatic char _palette[768];\n//\tstatic char _hold[256];\n\tstatic void *font;\n\tstatic char * _cd_name[] = {\n\t\t\"RED ALERT DISK 1\",\n\t\t\"RED ALERT DISK 2\",\n\t};\n\n\tint new_cd_drive = 0;\n\tint cd_index;\n\tchar buffer[128];\n\tint cd_drive;\n\tint current_drive;\n\tint drive_search_timeout;\n\n\tThemeType theme_playing = THEME_NONE;\n\n\t/*\n\t** If the required CD is set to -2 then it means that the file is present\n\t** on the local hard drive and we shouldn't have to worry about it.\n\t*/\n\tif (cd == -2) return(true);\n\n\t/*\n\t** Find out if the CD in the current drive is the one we are looking for\n\t*/\n\tcurrent_drive = CCFileClass::Get_CD_Drive();\n\tcd_index = Get_CD_Index(current_drive, 1*60);\n\tif (cd_index >= 0) {\n\t\tif (cd == cd_index || cd == -1) {\n\t\t\t/*\n\t\t\t** The required CD is still in the CD drive we used last time\n\t\t\t*/\n\t\t\tnew_cd_drive = current_drive;\n\t\t}\n\t}\n\n\t/*\n\t** Flag that we will have to restart the theme\n\t*/\n\ttheme_playing = Theme.What_Is_Playing();\n\tTheme.Stop();\n\n\n\tif (!new_cd_drive) {\n\t\t/*\n\t\t** Check the last CD drive we used if its different from the current one\n\t\t*/\n\t\tint last_drive = CCFileClass::Get_Last_CD_Drive();\n\n\t\t/*\n\t\t** Make sure the last drive is valid and it isnt the current drive\n\t\t*/\n\t\tif (last_drive && last_drive != CCFileClass::Get_CD_Drive()) {\n\t\t\t/*\n\t\t\t** Find out if there is a C&C cd in the last drive and if so is it the one we are looking for\n\t\t\t** Give it a nice big timeout so the CD changer has time to swap the discs\n\t\t\t*/\n\t\t\tcd_index = Get_CD_Index(last_drive, 10*60);\n\t\t\tif (cd_index >= 0) {\n\t\t\t\tif (cd == cd_index || cd == -1) {\n\t\t\t\t\t/*\n\t\t\t\t\t** The required CD is in the CD drive we used last time\n\t\t\t\t\t*/\n\t\t\t\t\tnew_cd_drive = last_drive;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Lordy. No sign of that blimming CD anywhere. Search all the CD drives\n\t** then if we still cant find it prompt the user to insert it.\n\t*/\n\tif (!new_cd_drive) {\n\n\t\t/*\n\t\t** Small timeout for the first pass through the drives\n\t\t*/\n\t\tdrive_search_timeout = 2*60;\n\n\t\tfor (;;) {\n\t\t\t/*\n\t\t\t** Search all present CD drives for the required disc.\n\t\t\t*/\n\t\t\tfor (int i=0 ; i<CDList.Get_Number_Of_Drives() ; i++) {\n\t\t\t\tcd_drive = CDList.Get_Next_CD_Drive();\n\t\t\t\tcd_index = Get_CD_Index(cd_drive, drive_search_timeout);\n\t\t\t\tif (cd_index>=0) {\n\t\t\t\t\t/*\n\t\t\t\t\t** We found a C&C cd - lets see if it was the one we were looking for\n\t\t\t\t\t*/\n\t\t\t\t\tif (cd == cd_index || cd == -1 || cd == -2) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Woohoo! The disk was in a different cd drive. Refresh the search path list\n\t\t\t\t \t\t* and return.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tnew_cd_drive = cd_drive;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** A new disc has become available so break\n\t\t\t*/\n\t\t\tif (new_cd_drive) break;\n\n\t\t\t/*\n\t\t\t** Increase the timeout for subsequent drive searches.\n\t\t\t*/\n\t\t\tdrive_search_timeout = 5*60;\n\n\t\t\t/*\n\t\t\t**\tPrompt to insert the CD into the drive.\n\t\t\t*/\n\t\t\tif (cd == -1) {\n\t\t\t\tsprintf(buffer, Text_String(TXT_CD_DIALOG_1), cd+1, _cd_name[cd]);\n\t\t\t} else {\n\t\t\t\tsprintf(buffer, Text_String(TXT_CD_DIALOG_2), cd+1, _cd_name[cd]);\n\t\t\t}\n#ifdef WIN32\n\t\t\tGraphicViewPortClass * oldpage = Set_Logic_Page(SeenBuff);\n#else\n\t\t\tGraphicBufferClass * oldpage = Set_Logic_Page(SeenBuff);\n#endif\n\t\t\ttheme_playing = Theme.What_Is_Playing();\n\t\t\tTheme.Stop();\n\t\t\tint hidden = Get_Mouse_State();\n\t\t\tfont = (void *)FontPtr;\n\n\t\t\t/*\n\t\t\t**\tOnly set the palette if necessary.\n\t\t\t*/\n\t\t\tif (PaletteClass::CurrentPalette[1].Red_Component() +\n\t\t\t\tPaletteClass::CurrentPalette[1].Blue_Component() +\n\t\t\t\tPaletteClass::CurrentPalette[1].Green_Component() == 0) {\n\n\t\t\t\tGamePalette.Set();\n\t\t\t}\n\n\t\t\tKeyboard->Clear();\n\n\t\t\twhile (Get_Mouse_State()) Show_Mouse();\n\n\t\t\tif (WWMessageBox().Process(buffer, TXT_OK, TXT_CANCEL, TXT_NONE, TRUE) == 1) {\n\t\t\t\tSet_Logic_Page(oldpage);\n\t\t\t\tHide_Mouse();\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t\twhile (hidden--) Hide_Mouse();\n\t\t\tSet_Font(font);\n\t\t\tSet_Logic_Page(oldpage);\n\t\t}\n\t}\n\n\tCurrentCD = cd_index;\n\n#ifndef DEMO\n\n\tCCFileClass::Set_CD_Drive(new_cd_drive);\n\tCCFileClass::Refresh_Search_Drives();\n\n\t/*\n\t**\tIf it broke out of the query for CD-ROM loop, then this means that the\n\t**\tCD-ROM has been inserted.\n\t*/\n//\tif (cd > -3 && _last != cd) {\n\tif (cd > -1 && _last != cd) {\n\t\t_last = cd;\n\n\t\tTheme.Stop();\n\n//\t\tif (ConquerMix) delete ConquerMix;\n\t\tif (MoviesMix) delete MoviesMix;\n\t\tif (GeneralMix) delete GeneralMix;\n\t\tif (ScoreMix) delete ScoreMix;\n\t\tif (MainMix) delete MainMix;\n\n\t\tMainMix = new MFCD(\"MAIN.MIX\", &FastKey);\n\t\tassert(MainMix != NULL);\n//\t\tConquerMix = new MFCD(\"CONQUER.MIX\", &FastKey);\n\t\tif (CCFileClass(\"MOVIES1.MIX\").Is_Available()) {\n\t\t\tMoviesMix = new MFCD(\"MOVIES1.MIX\", &FastKey);\n\t\t} else {\n\t\t\tMoviesMix = new MFCD(\"MOVIES2.MIX\", &FastKey);\n\t\t}\n\t\tassert(MoviesMix != NULL);\n\t\tGeneralMix = new MFCD(\"GENERAL.MIX\", &FastKey);\n\t\tScoreMix = new MFCD(\"SCORES.MIX\", &FastKey);\n\t\tThemeClass::Scan();\n\t}\n#endif\n\n\tif (theme_playing != THEME_NONE) {\n\t\tTheme.Queue_Song(theme_playing);\n\t}\n\n\treturn(true);\n}\n\n\n/***************************************************************************\n * DISK_SPACE_AVAILABLE -- returns bytes of free disk space                *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     returns amount of free disk space                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/11/1995 PWG : Created.                                             *\n *=========================================================================*/\nunsigned long Disk_Space_Available(void)\n{\n\tstruct diskfree_t diskdata;\n\tunsigned drive;\n\n\t_dos_getdrive(&drive);\n\t_dos_getdiskfree(drive, &diskdata);\n\n\treturn(diskdata.avail_clusters * diskdata.sectors_per_cluster * diskdata.bytes_per_sector);\n}\n\n\n/***********************************************************************************************\n * Do_Record_Playback -- handles saving/loading map pos & current object                       *\n *                                                                                             *\n * INPUT:                                                                                      *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/15/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nstatic void Do_Record_Playback(void)\n{\n\tint count;\n\tTARGET tgt;\n\tint i;\n\tCOORDINATE coord;\n\tObjectClass * obj;\n\tunsigned long sum;\n\tunsigned long sum2;\n\tunsigned long ltgt;\n\n\t/*\n\t**\tRecord a game\n\t*/\n\tif (Session.Record) {\n\n\t\t/*\n\t\t**\tSave the map's location\n\t\t*/\n\t\tSession.RecordFile.Write(&Map.DesiredTacticalCoord,\n\t\t\tsizeof (Map.DesiredTacticalCoord));\n\n\t\t/*\n\t\t**\tSave the current object list count\n\t\t*/\n\t\tcount = CurrentObject.Count();\n\t\tSession.RecordFile.Write(&count, sizeof(count));\n\n\t\t/*\n\t\t**\tSave a CRC of the selected-object list.\n\t\t*/\n\t\tsum = 0;\n\t\tfor (i = 0; i < count; i++) {\n\t\t\tltgt = (unsigned long)(CurrentObject[i]->As_Target());\n\t\t\tsum += ltgt;\n\t\t}\n\t\tSession.RecordFile.Write (&sum, sizeof(sum));\n\n\t\t/*\n\t\t**\tSave all selected objects.\n\t\t*/\n\t\tfor (i = 0; i < count; i++) {\n\t\t\ttgt = CurrentObject[i]->As_Target();\n\t\t\tSession.RecordFile.Write (&tgt, sizeof(tgt));\n\t\t}\n\n\t\t//\n\t\t// Save team-selection and formation events\n\t\t//\n\t\tSession.RecordFile.Write (&TeamEvent, sizeof(TeamEvent));\n\t\tSession.RecordFile.Write (&TeamNumber, sizeof(TeamNumber));\n\t\tSession.RecordFile.Write (&FormationEvent, sizeof(FormationEvent));\nSession.RecordFile.Write (TeamMaxSpeed, sizeof(TeamMaxSpeed));\nSession.RecordFile.Write (TeamSpeed, sizeof(TeamSpeed));\nSession.RecordFile.Write (&FormMove, sizeof(FormMove));\nSession.RecordFile.Write (&FormSpeed, sizeof(FormSpeed));\nSession.RecordFile.Write (&FormMaxSpeed, sizeof(FormMaxSpeed));\n\t\tTeamEvent = 0;\n\t\tTeamNumber = 0;\n\t\tFormationEvent = 0;\n\t}\n\n\t/*\n\t**\tPlay back a game (\"attract\" mode)\n\t*/\n\tif (Session.Play) {\n\n\t\t/*\n\t\t**\tRead & set the map's location.\n\t\t*/\n\t\tif (Session.RecordFile.Read(&coord, sizeof(coord))==sizeof(coord)) {\n\t\t\tif (coord != Map.DesiredTacticalCoord) {\n\t\t\t\tMap.Set_Tactical_Position(coord);\n\t\t\t}\n\t\t}\n\n\t\tif (Session.RecordFile.Read(&count, sizeof(count))==sizeof(count)) {\n\t\t\t/*\n\t\t\t**\tCompute a CRC of the current object-selection list.\n\t\t\t*/\n\t\t\tsum = 0;\n\t\t\tfor (i = 0; i < CurrentObject.Count(); i++) {\n\t\t\t\tltgt = (unsigned long)(CurrentObject[i]->As_Target());\n\t\t\t\tsum += ltgt;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tLoad the CRC of the objects on disk; if it doesn't match, select\n\t\t\t**\tall objects as they're loaded.\n\t\t\t*/\n\t\t\tSession.RecordFile.Read (&sum2, sizeof(sum2));\n\t\t\tif (sum2 != sum) {\n\t\t\t\tUnselect_All();\n\t\t\t}\n\n\t\t\tAllowVoice = true;\n\n\t\t\tfor (i = 0; i < count; i++) {\n\t\t\t\tif (Session.RecordFile.Read (&tgt, sizeof(tgt))==sizeof(tgt)) {\n\t\t\t\t\tobj = As_Object(tgt);\n\t\t\t\t\tif (obj && (sum2 != sum)) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tAllowVoice = true;\n\n\t\t}\n\n\t\t//\n\t\t// Save team-selection and formation events\n\t\t//\n\t\tSession.RecordFile.Read (&TeamEvent, sizeof(TeamEvent));\n\t\tSession.RecordFile.Read (&TeamNumber, sizeof(TeamNumber));\n\t\tSession.RecordFile.Read (&FormationEvent, sizeof(FormationEvent));\n\t\tif (TeamEvent) {\n\t\t\tHandle_Team(TeamNumber, TeamEvent - 1);\n\t\t}\n\t\tif (FormationEvent) {\n\t\t\tToggle_Formation();\n\t\t}\n\nSession.RecordFile.Read (TeamMaxSpeed, sizeof(TeamMaxSpeed));\nSession.RecordFile.Read (TeamSpeed, sizeof(TeamSpeed));\nSession.RecordFile.Read (&FormMove, sizeof(FormMove));\nSession.RecordFile.Read (&FormSpeed, sizeof(FormSpeed));\nSession.RecordFile.Read (&FormMaxSpeed, sizeof(FormMaxSpeed));\n\t\t/*\n\t\t**\tThe map isn't drawn in playback mode, so draw it here.\n\t\t*/\n\t\tMap.Render();\n\t}\n}\n\n\n/***********************************************************************************************\n * Hires_Load -- Allocates memory for, and loads, a resolution dependant file.                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Name of file to load                                                              *\n *                                                                                             *\n * OUTPUT:   Ptr to loaded file                                                                *\n *                                                                                             *\n * WARNINGS: Caller is responsible for releasing the memory allocated                          *\n *                                                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/13/96 3:20PM ST : Created                                                              *\n *=============================================================================================*/\nvoid * Hires_Load(char * name)\n{\n\tchar \tfilename[30];\n\tint \tlength;\n\tvoid * return_ptr;\n\n#ifdef WIN32\n\tsprintf(filename, \"H%s\", name);\n#else\n   strcpy(filename, name);\n#endif\n\tCCFileClass file (filename);\n\n\tif (file.Is_Available()) {\n\n\t\tlength = file.Size();\n\t\treturn_ptr = new char[length];\n\t\tfile.Read(return_ptr, length);\n\t\treturn (return_ptr);\n\n\t} else {\n\t\treturn (NULL);\n\t}\n}\n\n\n/***********************************************************************************************\n * Crate_From_Name -- Given a crate name convert it to a crate type.                           *\n *                                                                                             *\n *    Use this routine to convert an ASCII crate name into a crate type. If no match could     *\n *    be found, then CRATE_MONEY is assumed.                                                   *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the crate name text to convert into a crate type.              *\n *                                                                                             *\n * OUTPUT:  Returns with the crate name converted into a crate type.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCrateType Crate_From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (CrateType crate = CRATE_FIRST; crate < CRATE_COUNT; crate++) {\n\t\t\tif (stricmp(name, CrateNames[crate]) == 0) return(crate);\n\t\t}\n\t}\n\treturn(CRATE_MONEY);\n}\n\n\n/***********************************************************************************************\n * Owner_From_Name -- Convert an owner name into a bitfield.                                   *\n *                                                                                             *\n *    This will take an owner specification and convert it into a bitfield that represents     *\n *    it. Sometimes this will be just a single house bit, but other times it could be          *\n *    all the allies or soviet house bits combined.                                            *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text to convert into a house bitfield.                     *\n *                                                                                             *\n * OUTPUT:  Returns with the houses specified. The value is in the form of a bit field with    *\n *          one bit per house type.                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Owner_From_Name(char const * text)\n{\n\tint ownable = 0;\n\tif (stricmp(text, \"soviet\") == 0) {\n\t\townable |= HOUSEF_SOVIET;\n\t} else {\n\t\tif (stricmp(text, \"allies\") == 0 || stricmp(text, \"allied\") == 0) {\n\t\t\townable |= HOUSEF_ALLIES;\n\t\t} else {\n\t\t\tHousesType h = HouseTypeClass::From_Name(text);\n\t\t\tif (h != HOUSE_NONE && (h < HOUSE_MULTI1 || h > HOUSE_MULTI8)) {\n\t\t\t\townable |= (1 << h);\n\t\t\t}\n\t\t}\n\t}\n\treturn(ownable);\n}\n\n\n/***********************************************************************************************\n * Shake_The_Screen -- Dispatcher that shakes the screen.                                      *\n *                                                                                             *\n *    This routine will shake the game screen the number of shakes requested.                  *\n *                                                                                             *\n * INPUT:   shakes   -- The number of shakes to shake the screen.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/04/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid Shake_The_Screen(int shakes)\n{\n#ifdef WIN32\n\tshakes += shakes;\n\n\tHide_Mouse();\n\tSeenPage.Blit(HidPage);\n\tint oldyoff = 0;\n\tint newyoff = 0;\n\twhile(shakes--) {\n\t\tint x = TickCount;\n//\t\tCountDownTimer = 1;\n\t\tdo {\n\t\t\tnewyoff = Sim_Random_Pick(0,2) - 1;\n\t\t} while (newyoff == oldyoff);\n\t\tswitch (newyoff) {\n\t\t\tcase -1:\n\t\t\t\tHidPage.Blit(SeenPage, 0,2, 0,0, 640,398);\n\t\t\t\tbreak;\n\t\t\tcase 0:\n\t\t\t\tHidPage.Blit(SeenPage);\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tHidPage.Blit(SeenPage, 0,0, 0,2, 640,398);\n\t\t\t\tbreak;\n\t\t} while (x == TickCount);\n//\t\t} while (CountDownTimer != 0) ;\n\t}\n\tHidPage.Blit(SeenPage);\n\tShow_Mouse();\n#else\n\tShake_Screen(shakes);\n#endif\n}\n\n\n/***********************************************************************************************\n * List_Copy -- Makes a copy of a cell offset list.                                            *\n *                                                                                             *\n *    This routine will make a copy of a cell offset list. It will only copy the significant   *\n *    elements of the list limited by the maximum length specified.                            *\n *                                                                                             *\n * INPUT:   source   -- Pointer to a cell offset list.                                         *\n *                                                                                             *\n *          len      -- The maximum number of cell offset elements to store in to the          *\n *                      destination list pointer.                                              *\n *                                                                                             *\n *          dest     -- Pointer to the destination list to store the copy into.                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Ensure that the destination list is large enough to hold the list copy.         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid List_Copy(short const * source, int len, short * dest)\n{\n\tif (dest == NULL || dest == NULL) {\n\t\treturn;\n\t}\n\n\twhile (len > 0) {\n\t\t*dest = *source;\n\t\tif (*dest == REFRESH_EOL) break;\n\t\tdest++;\n\t\tsource++;\n\t\tlen--;\n\t}\n}\n\n\n\n#if 0\n//\n// Boy, this function sure is crummy\n//\nvoid Crummy(int crumb1, int crumb2)\n{\n\tif (Debug_Check_Map && Debug_Heap_Dump) {\n\t\tMono_Printf(\"Hi, I'm Crummy.  And so are these: %d, %d\\n\",crumb1,crumb2);\n\t}\n}\n#endif\n"
  },
  {
    "path": "CODE/CONQUER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#define TXT_NONE                 \t0  \t//                \n#define TXT_CREDIT_FORMAT        \t1  \t// %3d.%02d\n#define TXT_TIME_FORMAT_HOURS    \t2  \t// Temps:%02d:%02d:%02d\n#define TXT_TIME_FORMAT_NO_HOURS \t3  \t// Temps:%02d:%02d\n#define TXT_BUTTON_SELL          \t4  \t// Vente\n#define TXT_SELL                 \t5  \t// Vente structure\n#define TXT_BUTTON_REPAIR        \t6  \t// Rparation\n#define TXT_YOU                  \t7  \t// Vous :\n#define TXT_ENEMY                \t8  \t// Ennemi :\n#define TXT_BUILD_DEST           \t9  \t// Btiments dtruits par\n#define TXT_UNIT_DEST            \t10 \t// Units dtruites par\n#define TXT_TIB_HARV             \t11 \t// Minerai rcolt par\n#define TXT_SCORE_1              \t12 \t// Score: %d\n#define TXT_YES                  \t13 \t// Oui\n#define TXT_NO                   \t14 \t// Non\n#define TXT_SCENARIO_WON         \t15 \t// Mission Accomplie\n#define TXT_SCENARIO_LOST        \t16 \t// Mission Echoue\n#define TXT_START_NEW_GAME       \t17 \t// Nouvelle partie\n#define TXT_INTRO                \t18 \t// Intro/Preview\n#define TXT_CANCEL               \t19 \t// Annuler\n#define TXT_ROCK                 \t20 \t// Rocher\n#define TXT_CIVILIAN             \t21 \t// Civil\n#define TXT_JP                   \t22 \t// Equipe de confinement\n#define TXT_OK                   \t23 \t// OK\n#define TXT_TREE                 \t24 \t// Arbre\n#define TXT_LEFT                 \t25 \t// \u0011\n#define TXT_RIGHT                \t26 \t// \u0010\n#define TXT_UP                   \t27 \t// \u001e\n#define TXT_DOWN                 \t28 \t// \u001f\n#define TXT_CLEAR                \t29 \t// Effacer\n#define TXT_WATER                \t30 \t// Eau\n#define TXT_ROAD                 \t31 \t// Route\n#define TXT_SLOPE                \t32 \t// Pente\n#define TXT_PATCH                \t33 \t// Patch\n#define TXT_RIVER                \t34 \t// Rivire\n#define TXT_LOAD_MISSION         \t35 \t// Charger Mission\n#define TXT_SAVE_MISSION         \t36 \t// Sauvegarder Mission\n#define TXT_DELETE_MISSION       \t37 \t// Effacer Mission\n#define TXT_LOAD_BUTTON          \t38 \t// Charger\n#define TXT_SAVE_BUTTON          \t39 \t// Sauvegarder\n#define TXT_DELETE_BUTTON        \t40 \t// Effacer\n#define TXT_GAME_CONTROLS        \t41 \t// Contrles\n#define TXT_SOUND_CONTROLS       \t42 \t// Son\n#define TXT_RESUME_MISSION       \t43 \t// Reprendre Mission\n#define TXT_VISUAL_CONTROLS      \t44 \t// Affichage\n#define TXT_QUIT_MISSION         \t45 \t// Abandonner Mission\n#define TXT_EXIT_GAME            \t46 \t// Quitter le jeu\n#define TXT_OPTIONS              \t47 \t// Options\n#define TXT_SQUISH               \t48 \t// Dbris humains\n#define TXT_CRATER               \t49 \t// Cratre\n#define TXT_SCORCH               \t50 \t// Marque de brlure\n#define TXT_BRIGHTNESS           \t51 \t// Luminosit :\n#define TXT_MUSIC                \t52 \t// Musique\n#define TXT_VOLUME               \t53 \t// Effets sonores\n#define TXT_TINT                 \t54 \t// Teintes :\n#define TXT_CONTRAST             \t55 \t// Contraste :\n#define TXT_SPEED                \t56 \t// Vitesse du jeu :\n#define TXT_SCROLLRATE           \t57 \t// Vitesse dfilement :\n#define TXT_COLOR                \t58 \t// Couleur :\n#define TXT_RETURN_TO_GAME       \t59 \t// Revenir au jeu\n#define TXT_ENEMY_SOLDIER        \t60 \t// Soldat ennemi\n#define TXT_ENEMY_VEHICLE        \t61 \t// Vhicule ennemi\n#define TXT_ENEMY_STRUCTURE      \t62 \t// Structure ennemie\n#define TXT_LTANK                \t63 \t// Tank lger\n#define TXT_MTANK                \t64 \t// Tank lourd\n#define TXT_MTANK2               \t65 \t// Tank moyen\n#define TXT_HTANK                \t66 \t// Tank Mammouth\n#define TXT_SAM                  \t67 \t// Missiles SAM\n#define TXT_JEEP                 \t68 \t// Ranger\n#define TXT_TRANS                \t69 \t// Hlicoptre Chinook\n#define TXT_HARVESTER            \t70 \t// Collecteur minerai\n#define TXT_ARTY                 \t71 \t// Artillerie\n#define TXT_E1                   \t72 \t// Mitrailleurs\n#define TXT_E2                   \t73 \t// Grenadiers\n#define TXT_E3                   \t74 \t// Bazookas\n#define TXT_E4                   \t75 \t// Lance-flammes\n#define TXT_HELI                 \t76 \t// Hlicoptre d'assaut\n#define TXT_ORCA                 \t77 \t// Hind\n#define TXT_APC                  \t78 \t// VBT\n#define TXT_GUARD_TOWER          \t79 \t// Tour de garde\n#define TXT_COMMAND              \t80 \t// Dme radar\n#define TXT_HELIPAD              \t81 \t// Hliport\n#define TXT_AIRSTRIP             \t82 \t// Piste d'atterrissage\n#define TXT_STORAGE              \t83 \t// Silo minerai\n#define TXT_CONST_YARD           \t84 \t// Chantier de construction\n#define TXT_REFINERY             \t85 \t// Raffinerie de minerai\n#define TXT_CIV1                 \t86 \t// Eglise\n#define TXT_CIV2                 \t87 \t// Chez Hans et Gretel\n#define TXT_CIV3                 \t88 \t// Manoir d'Hewitt\n#define TXT_CIV4                 \t89 \t// Maison de Ricktor\n#define TXT_CIV5                 \t90 \t// Maison de Gretchin\n#define TXT_CIV6                 \t91 \t// La grange\n#define TXT_CIV7                 \t92 \t// Pub Damon\n#define TXT_CIV8                 \t93 \t// Maison de Fran\n#define TXT_CIV9                 \t94 \t// Usine d'instruments\n#define TXT_CIV10                \t95 \t// Fabricant de jouets\n#define TXT_CIV11                \t96 \t// Maison de Ludwig\n#define TXT_CIV12                \t97 \t// Meules de foin\n#define TXT_CIV13                \t98 \t// Meule de foin\n#define TXT_CIV14                \t99 \t// Champ de bl\n#define TXT_CIV15                \t100\t// Champ en friche\n#define TXT_CIV16                \t101\t// Champ de mas\n#define TXT_CIV17                \t102\t// Champ de cleri\n#define TXT_CIV18                \t103\t// Champ de pommes de terre\n#define TXT_CIV20                \t104\t// Maison de Sala\n#define TXT_CIV21                \t105\t// Maison d'Abdul\n#define TXT_CIV22                \t106\t// Le Pub Barjo de Pablo\n#define TXT_CIV23                \t107\t// Puits du village\n#define TXT_CIV24                \t108\t// Marchand de chameaux\n#define TXT_CIV25                \t109\t// Eglise\n#define TXT_CIV26                \t110\t// Maison d'Ali\n#define TXT_CIV27                \t111\t// Ted le Marchand\n#define TXT_CIV28                \t112\t// Maison de Menelik\n#define TXT_CIV29                \t113\t// Maison du pasteur John\n#define TXT_CIV30                \t114\t// Puits du village\n#define TXT_CIV31                \t115\t// Hutte du gurisseur\n#define TXT_CIV32                \t116\t// Hutte de Rikitikitembo\n#define TXT_CIV33                \t117\t// Hutte de Roarke\n#define TXT_CIV34                \t118\t// Hutte de Moubasa'\n#define TXT_CIV35                \t119\t// Hutte d'Aksoum\n#define TXT_CIV36                \t120\t// Hutte de Mambo\n#define TXT_CIV37                \t121\t// Le studio\n#define TXT_CIVMISS              \t122\t// Centre technologique\n#define TXT_TURRET               \t123\t// Tourelle\n#define TXT_GUNBOAT              \t124\t// Aviso-torpilleur\n#define TXT_MCV                  \t125\t// Vhicule de construction\n#define TXT_POWER                \t126\t// Centrale lectrique\n#define TXT_ADVANCED_POWER       \t127\t// Centrale lectrique avance\n#define TXT_HOSPITAL             \t128\t// Hpital\n#define TXT_BARRACKS             \t129\t// Caserne\n#define TXT_PUMP                 \t130\t// Pompe\n#define TXT_TANKER               \t131\t// Ptrolier\n#define TXT_SANDBAG_WALL         \t132\t// Sacs de sable\n#define TXT_CYCLONE_WALL         \t133\t// Clture grillage\n#define TXT_BRICK_WALL           \t134\t// Mur de bton\n#define TXT_BARBWIRE_WALL        \t135\t// Clture barbele\n#define TXT_WOOD_WALL            \t136\t// Barrire de bois\n#define TXT_WEAPON_FACTORY       \t137\t// Usine d'armement\n#define TXT_AGUARD_TOWER         \t138\t// Tour de garde avance\n#define TXT_BIO_LAB              \t139\t// Laboratoire biologique\n#define TXT_FIX_IT               \t140\t// Centre de service\n#define TXT_TAB_SIDEBAR          \t141\t// Contrles\n#define TXT_TAB_BUTTON_CONTROLS  \t142\t// Options\n#define TXT_TAB_BUTTON_DATABASE  \t143\t// Base de donnes\n#define TXT_SHADOW               \t144\t// Terrain inconnu\n#define TXT_OPTIONS_MENU         \t145\t// Menu des options\n#define TXT_STOP                 \t146\t// Stop\n#define TXT_PLAY                 \t147\t// Lect\n#define TXT_SHUFFLE              \t148\t// Alat.\n#define TXT_REPEAT               \t149\t// Rpter\n#define TXT_MUSIC_VOLUME         \t150\t// Musique :\n#define TXT_SOUND_VOLUME         \t151\t// Effets sonores :\n#define TXT_ON                   \t152\t// Oui\n#define TXT_OFF                  \t153\t// Non\n#define TXT_MULTIPLAYER_GAME     \t154\t// Jeu Multijoueurs\n#define TXT_NO_FILES             \t155\t// Pas de fichiers disponibles\n#define TXT_DELETE_SINGLE_FILE   \t156\t// Voulez-vous effacer ce\n#define TXT_DELETE_MULTIPLE_FILES\t157\t// Voulez-vous effacer %d\n#define TXT_RESET_MENU           \t158\t// Dfaut\n#define TXT_CONFIRM_EXIT         \t159\t// Voulez-vous abandonner la\n#define TXT_MISSION_DESCRIPTION  \t160\t// Description de la mission\n#define TXT_C1                   \t161\t// Joe\n#define TXT_C2                   \t162\t// Barry\n#define TXT_C3                   \t163\t// Shelly\n#define TXT_C4                   \t164\t// Maria\n#define TXT_C5                   \t165\t// Karen\n#define TXT_C6                   \t166\t// Steve\n#define TXT_C7                   \t167\t// Phil\n#define TXT_C8                   \t168\t// Dwight\n#define TXT_C9                   \t169\t// Erik\n#define TXT_EINSTEIN             \t170\t// Prof. Einstein\n#define TXT_BIB                  \t171\t// Cour\n#define TXT_FASTER               \t172\t// Rapide\n#define TXT_SLOWER               \t173\t// Lent\n#define TXT_AIR_STRIKE           \t174\t// Attaque arienne\n#define TXT_STEEL_CRATE          \t175\t// Caisse d'acier\n#define TXT_WOOD_CRATE           \t176\t// Caisse de bois\n#define TXT_WATER_CRATE          \t177\t// Caisse flottante\n#define TXT_FLAG_SPOT            \t178\t// Emplacement du drapeau\n#define TXT_UNABLE_READ_SCENARIO \t179\t// Lecture scnario impossible\n#define TXT_ERROR_LOADING_GAME   \t180\t// Erreur de chargement !\n#define TXT_OBSOLETE_SAVEGAME    \t181\t// Sauvegarde obsolte\n#define TXT_MUSTENTER_DESCRIPTION\t182\t// Vous devez entrer une\n#define TXT_ERROR_SAVING_GAME    \t183\t// Erreur de sauvegarde !\n#define TXT_DELETE_FILE_QUERY    \t184\t// Effacer ce fichier ?\n#define TXT_EMPTY_SLOT           \t185\t// [EMPLACEMENT VIDE]\n#define TXT_SELECT_MPLAYER_GAME  \t186\t// Choix du jeu Multijoueurs\n#define TXT_MODEM_SERIAL         \t187\t// Modem/Srie\n#define TXT_NETWORK              \t188\t// Rseau\n#define TXT_INIT_NET_ERROR       \t189\t// Initialisation rseau\n#define TXT_JOIN_NETWORK_GAME    \t190\t// Rejoindre jeu en rseau\n#define TXT_NEW                  \t191\t// Nouveau\n#define TXT_JOIN                 \t192\t// Joindre\n#define TXT_SEND_MESSAGE         \t193\t// Envoi Message\n#define TXT_YOUR_NAME            \t194\t// Votre nom :\n#define TXT_SIDE_COLON           \t195\t// Camp :\n#define TXT_COLOR_COLON          \t196\t// Couleur :\n#define TXT_GAMES                \t197\t// Parties\n#define TXT_PLAYERS              \t198\t// Joueurs\n#define TXT_SCENARIO_COLON       \t199\t// Scnario :\n#define TXT_NOT_FOUND            \t200\t// >> NON TROUVE <<\n#define TXT_START_CREDITS_COLON  \t201\t// Crdits :\n#define TXT_BASES_COLON          \t202\t// Bases :\n#define TXT_TIBERIUM_COLON       \t203\t// Minerai :\n#define TXT_CRATES_COLON         \t204\t// Caisses :\n#define TXT_AI_PLAYERS_COLON     \t205\t// Joueurs IA :\n#define TXT_REQUEST_DENIED       \t206\t// Demande refuse.\n#define TXT_UNABLE_PLAY_WAAUGH   \t207\t// Impossible de jouer,\n#define TXT_NOTHING_TO_JOIN      \t208\t// Aucune partie disponible !\n#define TXT_NAME_ERROR           \t209\t// Vous devez entrer un nom !\n#define TXT_DUPENAMES_NOTALLOWED \t210\t// Les noms identiques ne sont\n#define TXT_YOURGAME_OUTDATED    \t211\t// La version de votre jeu est\n#define TXT_DESTGAME_OUTDATED    \t212\t// Version du jeu de\n#define TXT_THATGUYS_GAME        \t213\t// Partie de %s\n#define TXT_THATGUYS_GAME_BRACKET\t214\t// [Partie de %s]\n#define TXT_NETGAME_SETUP        \t215\t// Configuration du jeu en\n#define TXT_REJECT               \t216\t// Rejeter\n#define TXT_CANT_REJECT_SELF     \t217\t// Vous ne pouvez pas vous\n#define TXT_SELECT_PLAYER_REJECT \t218\t// Vous devez slectionner un\n#define TXT_BASES                \t219\t// Bases\n#define TXT_CRATES               \t220\t// Caisses\n#define TXT_AI_PLAYERS           \t221\t// Joueur IA\n#define TXT_SCENARIOS            \t222\t// Scnarios\n#define TXT_CREDITS_COLON        \t223\t// Crdits :\n#define TXT_ONLY_ONE             \t224\t// Un seul joueur ?\n#define TXT_OOPS                 \t225\t// Oops !\n#define TXT_TO                   \t226\t// Pour %s :\n#define TXT_TO_ALL               \t227\t// Pour tous\n#define TXT_MESSAGE              \t228\t// Message :\n#define TXT_CONNECTION_LOST      \t229\t// Perte de connexion avec %s\n#define TXT_LEFT_GAME            \t230\t// %s a quitt le jeu.\n#define TXT_PLAYER_DEFEATED      \t231\t// %s a t vaincu !\n#define TXT_WAITING_CONNECT      \t232\t// Attente de connexion...\n#define TXT_NULL_CONNERR_CHECK_CABLES\t233\t// Erreur de connexion !\n#define TXT_MODEM_CONNERR_REDIALING\t234\t// Erreur de connexion !\n#define TXT_MODEM_CONNERR_WAITING\t235\t// Erreur de connexion !\n#define TXT_SELECT_SERIAL_GAME   \t236\t// Choix du jeu en srie\n#define TXT_DIAL_MODEM           \t237\t// Appel\n#define TXT_ANSWER_MODEM         \t238\t// Attente appel\n#define TXT_NULL_MODEM           \t239\t// Null Modem\n#define TXT_SETTINGS             \t240\t// Paramtres\n#define TXT_PORT_COLON           \t241\t// Port :\n#define TXT_IRQ_COLON            \t242\t// IRQ :\n#define TXT_BAUD_COLON           \t243\t// Bauds :\n#define TXT_INIT_STRING          \t244\t// Chane d'initialisation\n#define TXT_CWAIT_STRING         \t245\t// Chane d'attente d'appel\n#define TXT_TONE_BUTTON          \t246\t// Tonalit\n#define TXT_PULSE_BUTTON         \t247\t// Impulsions\n#define TXT_HOST_SERIAL_GAME     \t248\t// Hte du jeu en srie\n#define TXT_OPPONENT_COLON       \t249\t// Adversaire :\n#define TXT_USER_SIGNED_OFF      \t250\t// Utilisateur reparti !\n#define TXT_JOIN_SERIAL_GAME     \t251\t// Rejoindre jeu en srie\n#define TXT_PHONE_LIST           \t252\t// Rpertoire\n#define TXT_ADD                  \t253\t// Ajouter\n#define TXT_EDIT                 \t254\t// Editer\n#define TXT_DIAL                 \t255\t// Appel\n#define TXT_DEFAULT              \t256\t// Dfaut\n#define TXT_DEFAULT_SETTINGS     \t257\t// Dfaut\n#define TXT_CUSTOM_SETTINGS      \t258\t// Autres paramtres\n#define TXT_PHONE_LISTING        \t259\t// Rpertoire\n#define TXT_NAME_COLON           \t260\t// Nom :\n#define TXT_NUMBER_COLON         \t261\t// Numro :\n#define TXT_UNABLE_FIND_MODEM    \t262\t// Modem non dtect. Vrifiez\n#define TXT_NO_CARRIER           \t263\t// Pas de porteuse.\n#define TXT_LINE_BUSY            \t264\t// Ligne occupe.\n#define TXT_NUMBER_INVALID       \t265\t// Numro incorrect.\n#define TXT_SYSTEM_NOT_RESPONDING\t266\t// L'autre systme ne rpond\n#define TXT_OUT_OF_SYNC          \t267\t// Mauvaise synchronisation !\n#define TXT_PACKET_TOO_LATE      \t268\t// Paquet reu trop tard !\n#define TXT_PLAYER_LEFT_GAME     \t269\t// L'autre joueur a quitt le\n#define TXT_FROM                 \t270\t// De %s:%s\n#define TXT_SCORE_TIME           \t271\t// TEMPS :\n#define TXT_SCORE_LEAD           \t272\t// COMMANDEMENT :\n#define TXT_SCORE_EFFI           \t273\t// EFFICACITE :\n#define TXT_SCORE_TOTA           \t274\t// SCORE TOTAL :\n#define TXT_SCORE_CASU           \t275\t// PERTES :\n#define TXT_SCORE_NEUT           \t276\t// NEUTRE :\n#define TXT_SCORE_BUIL           \t277\t// BATIMENTS PERDUS\n#define TXT_SCORE_BUIL1          \t278\t// BATIMENTS\n#define TXT_SCORE_BUIL2          \t279\t// PERDUS :\n#define TXT_SCORE_TOP            \t280\t// MEILLEURS SCORES\n#define TXT_SCORE_ENDCRED        \t281\t// CREDITS DE FIN :\n#define TXT_SCORE_TIMEFORMAT1    \t282\t// %dh %dm\n#define TXT_SCORE_TIMEFORMAT2    \t283\t// %dm\n#define TXT_DIALING              \t284\t// Appel...\n#define TXT_DIALING_CANCELED     \t285\t// Appel annul\n#define TXT_WAITING_FOR_CALL     \t286\t// Attente d'appel...\n#define TXT_ANSWERING_CANCELED   \t287\t// Attente d'appel annule\n#define TXT_E6                   \t288\t// Ingnieurs\n#define TXT_E8                   \t289\t// Espion\n#define TXT_MODEM_OR_LOOPBACK    \t290\t// Pas de cble Null Modem\n#define TXT_MAP                  \t291\t// Carte\n#define TXT_BLOSSOM_TREE         \t292\t// Arbre en fleurs\n#define TXT_RESTATE_MISSION      \t293\t// Briefing\n#define TXT_COMPUTER             \t294\t// Joueur IA\n#define TXT_COUNT                \t295\t// Nombre :\n#define TXT_LEVEL                \t296\t// Niveau :\n#define TXT_OPPONENT             \t297\t// Adversaire\n#define TXT_KILLS_COLON          \t298\t// Vict.:\n#define TXT_VIDEO                \t299\t// Vido\n#define TXT_C10                  \t300\t// Scientifique\n#define TXT_CAPTURE_THE_FLAG     \t301\t// Capture drapeau\n#define TXT_OBJECTIVE            \t302\t// Objectifs de mission\n#define TXT_MISSION              \t303\t// Mission\n#define TXT_NO_SAVES             \t304\t// Pas de sauvegardes\n#define TXT_CIVILIAN_BUILDING    \t305\t// Btiment civil\n#define TXT_TECHNICIAN           \t306\t// Technicien\n#define TXT_NO_SAVELOAD          \t307\t// Sauvegarde interdite en\n#define TXT_DELPHI               \t308\t// Agent Spcial 1\n#define TXT_TO_REPLAY            \t309\t// Voulez-vous recommencer\n#define TXT_RECONN_TO            \t310\t// Reconnexion vers %s.\n#define TXT_PLEASE_WAIT          \t311\t// Attendez %02d secondes.\n#define TXT_SURRENDER            \t312\t// Voulez-vous vous rendre ?\n#define TXT_SEL_TRANS            \t313\t// CHOIX DE LA TRANSMISSION\n#define TXT_GAMENAME_MUSTBE_UNIQUE\t314\t// Les sauvegardes ne peuvent\n#define TXT_GAME_IS_CLOSED       \t315\t// Partie ferme.\n#define TXT_NAME_MUSTBE_UNIQUE   \t316\t// Les noms doivent tre tous\n#define TXT_RECONNECTING_TO      \t317\t// Reconnexion vers %s\n#define TXT_WAITING_FOR_CONNECTIONS\t318\t// Attente de connexions...\n#define TXT_TIME_ALLOWED         \t319\t// Temps autoris : %02d\n#define TXT_PRESS_ESC            \t320\t// Appuyez sur Echap pour\n#define TXT_JUST_YOU_AND_ME      \t321\t// De l'ordinateur : Il ne\n#define TXT_CAPTURE_THE_FLAG_COLON\t322\t// Capture du drapeau :\n#define TXT_CHAN                 \t323\t// Agent Spcial 2\n#define TXT_HAS_ALLIED           \t324\t// %s s'est alli(e) avec %s\n#define TXT_AT_WAR               \t325\t// %s dclare la guerre  %s\n#define TXT_SEL_TARGET           \t326\t// Choisissez un cible\n#define TXT_RESIGN               \t327\t// Abandonner\n#define TXT_TIBERIUM_FAST        \t328\t// Le minerai pousse trs\n#define TXT_ANSWERING            \t329\t// Rponse en cours...\n#define TXT_INITIALIZING_MODEM   \t330\t// Initialisation Modem...\n#define TXT_SCENARIOS_DO_NOT_MATCH\t331\t// Les scnarios ne\n#define TXT_POWER_OUTPUT         \t332\t// Production d'nergie\n#define TXT_POWER_OUTPUT_LOW     \t333\t// Production d'nergie\n#define TXT_CONTINUE             \t334\t// Continuer\n#define TXT_QUEUE_FULL           \t335\t// Saturation des donnes \n#define TXT_SPECIAL_WARNING      \t336\t// %s a modifi les options de\n#define TXT_CD_DIALOG_1          \t337\t// Placez un CD d'Alerte Rouge\n#define TXT_CD_DIALOG_2          \t338\t// Placez le CD %d (%s) dans\n#define TXT_CD_ERROR1            \t339\t// Alerte Rouge n'a pas\n#define TXT_NO_SOUND_CARD        \t340\t// Pas de carte sonore\n#define TXT_UNKNOWN              \t341\t// INCONNU\n#define TXT_OLD_GAME             \t342\t// (ancien)\n#define TXT_NO_SPACE             \t343\t// Espace disque insuffisant\n#define TXT_MUST_HAVE_SPACE      \t344\t// Vous devez disposer de %d\n#define TXT_RUN_SETUP            \t345\t// Lancez d'abord le programme\n#define TXT_WAITING_FOR_OPPONENT \t346\t// Attente adversaire\n#define TXT_SELECT_SETTINGS      \t347\t// Choisissez l'option\n#define TXT_PRISON               \t348\t// Prison\n#define TXT_GAME_WAS_SAVED       \t349\t// Mission sauvegarde\n#define TXT_SPACE_CANT_SAVE      \t350\t// Espace disque insuffisant\n#define TXT_INVALID_PORT_ADDRESS \t351\t// Port/Adresse invalide. COM\n#define TXT_INVALID_SETTINGS     \t352\t// paramtres Port et/ou IRQ\n#define TXT_IRQ_ALREADY_IN_USE   \t353\t// IRQ dj utilis\n#define TXT_ABORT                \t354\t// Oui\n#define TXT_RESTART              \t355\t// Recommencer\n#define TXT_RESTARTING           \t356\t// Mission relance. Attendez\n#define TXT_LOADING              \t357\t// Chargement de la mission.\n#define TXT_ERROR_IN_INITSTRING  \t358\t// Erreur chane\n#define TXT_SHADOW_COLON         \t359\t// Ombre\n#define TXT_AVMINE               \t360\t// Mine Anti-Vhicule\n#define TXT_APMINE               \t361\t// Mine Anti-Personnel\n#define TXT_NEW_MISSIONS         \t362\t// Nouvelles missions\n#define TXT_THIEF                \t363\t// Voleur\n#define TXT_MRJ                  \t364\t// Brouilleur de radar\n#define TXT_GAP_GENERATOR        \t365\t// Gnrateur d'ombre\n#define TXT_PILLBOX              \t366\t// Bunker\n#define TXT_CAMOPILLBOX          \t367\t// Bunker camoufl\n#define TXT_CHRONOSPHERE         \t368\t// Chronosphre\n#define TXT_ENGLAND              \t369\t// Roy. Uni\n#define TXT_GERMANY              \t370\t// Allemagne\n#define TXT_SPAIN                \t371\t// Espagne\n#define TXT_USSR                 \t372\t// URSS\n#define TXT_UKRAINE              \t373\t// Ukraine\n#define TXT_GREECE               \t374\t// Grce\n#define TXT_FRANCE               \t375\t// France\n#define TXT_TURKEY               \t376\t// Turquie\n#define TXT_SHORE                \t377\t// Rivage\n#define TXT_PLACE_OBJECT         \t378\t// Choisir objet\n#define TXT_SS                   \t379\t// Sous-marin\n#define TXT_DD                   \t380\t// Contre-torpilleur\n#define TXT_CA                   \t381\t// Croiseur\n#define TXT_TRANSPORT            \t382\t// Transport\n#define TXT_PT                   \t383\t// Aviso-torpilleur\n#define TXT_LOBBY                \t384\t// Hall\n#define TXT_CHANNEL_GAMES        \t385\t// Parties\n#define TXT_SAVING_GAME          \t386\t// Sauvegarder partie...\n#define TXT_GAME_FULL            \t387\t// La partie est au complet.\n#define TXT_MUST_SELECT_GAME     \t388\t// Vous devez slectionner une\n#define TXT_S_PLAYING_S          \t389\t// %s joue contre %s\n#define TXT_ONLY_HOST_CAN_MODIFY \t390\t// Seul l'hte peut modifier\n#define TXT_GAME_CANCELLED       \t391\t// La partie a t annule.\n#define TXT_S_FORMED_NEW_GAME    \t392\t// %s a initi une nouvelle\n#define TXT_GAME_NOW_IN_PROGRESS \t393\t// La partie de %s est\n#define TXT_TESLA                \t394\t// Bobine de Tesla\n#define TXT_MGG                  \t395\t// Gnrateur d'ombre mobile\n#define TXT_FLAME_TURRET         \t396\t// Tour lance-flammes\n#define TXT_AAGUN                \t397\t// Canon Anti-Avion\n#define TXT_KENNEL               \t398\t// Niche\n#define TXT_SOVIET_TECH          \t399\t// Centre Technique\n#define TXT_BADGER               \t400\t// Bombardier\n#define TXT_MIG                  \t401\t// Mig\n#define TXT_YAK                  \t402\t// Yak\n#define TXT_FENCE                \t403\t// Barbels\n#define TXT_MEDIC                \t404\t// Mdecin\n#define TXT_SABOTEUR             \t405\t// Saboteur\n#define TXT_GENERAL              \t406\t// Gnral\n#define TXT_E7                   \t407\t// Tanya\n#define TXT_PARA_BOMB            \t408\t// Parabombes\n#define TXT_PARA_INFANTRY        \t409\t// Parachutistes\n#define TXT_PARA_SABOTEUR        \t410\t// Saboteur parachutiste\n#define TXT_SHIP_YARD            \t411\t// Chantier naval\n#define TXT_SUB_PEN              \t412\t// Port sous-marin\n#define TXT_SCENARIO_OPTIONS     \t413\t// Options Scnario\n#define TXT_SPY_MISSION          \t414\t// Avion espion\n#define TXT_U2                   \t415\t// Avion espion\n#define TXT_GUARD_DOG            \t416\t// Chien d'attaque\n#define TXT_SPY_INFO             \t417\t// Info Espion\n#define TXT_BUILDNGS             \t418\t// Btiments\n#define TXT_UNITS                \t419\t// Units\n#define TXT_INFANTRY             \t420\t// Infanterie\n#define TXT_AIRCRAFT             \t421\t// Avion\n#define TXT_TRUCK                \t422\t// Camion d'approvisionnement\n#define TXT_INVUL                \t423\t// Module d'invulnrabilit\n#define TXT_IRON_CURTAIN         \t424\t// Rideau de Fer\n#define TXT_ADVANCED_TECH        \t425\t// Centre technique avanc\n#define TXT_V2_LAUNCHER          \t426\t// Lance-roquettes V2\n#define TXT_FORWARD_COM          \t427\t// Poste de commandement\n#define TXT_DEMOLITIONER         \t428\t// Bombardeur\n#define TXT_MINE_LAYER           \t429\t// Poseur de mines\n#define TXT_FAKE_CONST           \t430\t// Chantier de construction\n#define TXT_FAKE_WEAP            \t431\t// Usine d'armement leurre\n#define TXT_FAKE_YARD            \t432\t// Chantier naval leurre\n#define TXT_FAKE_PEN             \t433\t// Port sous-marin leurre\n#define TXT_FAKE_RADAR           \t434\t// Dme radar leurre\n#define TXT_THEME_BIGF           \t435\t// Bigfoot\n#define TXT_THEME_CRUS           \t436\t// La rvolte\n#define TXT_THEME_FAC1           \t437\t// A l'attaque 1\n#define TXT_THEME_FAC2           \t438\t// A l'attaque 2\n#define TXT_THEME_HELL           \t439\t// Marche de l'enfer\n#define TXT_THEME_RUN1           \t440\t// Sauve-qui-peut\n#define TXT_THEME_SMSH           \t441\t// La dbcle\n#define TXT_THEME_TREN           \t442\t// Tranches\n#define TXT_THEME_WORK           \t443\t// Les professionnels\n#define TXT_THEME_AWAIT          \t444\t// Attente\n#define TXT_THEME_DENSE_R        \t445\t// Dense\n#define TXT_THEME_MAP            \t446\t// Slection carte\n#define TXT_THEME_FOGGER1A       \t447\t// Fogger\n#define TXT_THEME_MUD1A          \t448\t// Boue\n#define TXT_THEME_RADIO2         \t449\t// Radio 2\n#define TXT_THEME_ROLLOUT        \t450\t// Laminage\n#define TXT_THEME_SNAKE          \t451\t// Serpent\n#define TXT_THEME_TERMINAT       \t452\t// Extermination\n#define TXT_THEME_TWIN           \t453\t// Jumeau\n#define TXT_THEME_VECTOR1A       \t454\t// Vecteur\n#define TXT_TEAM_MEMBERS         \t455\t// Equipiers\n#define TXT_BRIDGE               \t456\t// Pont\n#define TXT_BARREL               \t457\t// Baril\n#define TXT_GOODGUY              \t458\t// Amical\n#define TXT_BADGUY               \t459\t// Ennemi\n#define TXT_GOLD                 \t460\t// Or\n#define TXT_GEMS                 \t461\t// Gemmes\n#define TXT_TEASER               \t462\t// Film titre\n#define TXT_MOVIES               \t463\t// Films\n#define TXT_INTERIOR             \t464\t// Intrieur\n#define TXT_SONAR_PULSE          \t465\t// Signal sonar\n#define TXT_MSLO                 \t466\t// Silo de missiles\n#define TXT_GPS_SATELLITE        \t467\t// Satellite GPS\n#define TXT_NUCLEAR_BOMB         \t468\t// Bombe atomique\n#define TXT_EASY                 \t469\t// Facile\n#define TXT_HARD                 \t470\t// Difficile\n#define TXT_NORMAL               \t471\t// Normal\n#define TXT_DIFFICULTY           \t472\t// Slectionnez un niveau de\n#define TXT_ALLIES               \t473\t// Allis\n#define TXT_SOVIET               \t474\t// Soviets\n#define TXT_THEME_INTRO          \t475\t// Thme Intro\n#define TXT_SHADOW_REGROWS       \t476\t// Progr. ombre\n#define TXT_ORE_SPREADS          \t477\t// Progr. minerai\n#define TXT_THEME_SCORE          \t478\t// Musiques\n#define TXT_INTERNET             \t479\t// Internet\n#define TXT_ICE                  \t480\t// Glace\n#define TXT_CRATE                \t481\t// Caisses\n#define TXT_SKIRMISH             \t482\t// Escarmouche\n#define TXT_CHOOSE               \t483\t// Choisissez votre camp.\n#define TXT_MINERALS             \t484\t// Minraux prcieux\n#define TXT_IGNORE               \t485\t// Ignorer\n#define TXT_ERROR_NO_RESP        \t486\t// Erreur - le modem ne rpond\n#define TXT_ERROR_NO_RESCODE     \t487\t// Erreur - Le modem n'a pas\n#define TXT_ERROR_NO_INIT        \t488\t// Erreur - Le modem n'a pas\n#define TXT_ERROR_NO_VERB        \t489\t// Erreur - Le modem n'a pas\n#define TXT_ERROR_NO_ECHO        \t490\t// Erreur - Le modem n'a pas\n#define TXT_ERROR_NO_DISABLE     \t491\t// Erreur - Impossible de\n#define TXT_ERROR_TOO_MANY       \t492\t// Erreur - Trop d'erreurs\n#define TXT_ERROR_ERROR          \t493\t// Erreur - Le modem a\n#define TXT_ERROR_TIMEOUT        \t494\t// Erreur - Temps d'attente de\n#define TXT_ACCOMPLISHED         \t495\t// Accompli\n#define TXT_CLICK_CONTINUE       \t496\t// Cliquez pour continuer\n#define TXT_RECEIVING_SCENARIO   \t497\t// Rception du scnario de\n#define TXT_SENDING_SCENARIO     \t498\t// Envoi du scnario aux\n#define TXT_NO_FLOW_CONTROL_RESPONSE\t499\t// Erreur - Le modem n'a pas\n#define TXT_NO_COMPRESSION_RESPONSE\t500\t// Erreur - Le modem n'a pas\n#define TXT_NO_ERROR_CORRECTION_RESPONSE\t501\t// Erreur - Le modem n'a pas\n#define TXT_EXPLAIN_REGISTRATION \t502\t// Pour jouer  Alerte Rouge\n#define TXT_ERROR_UNABLE_TO_RUN_WCHAT\t503\t// Erreur - Impossible\n#define TXT_REGISTER             \t504\t// Enregistrer\n#define TXT_ORE_MINE             \t505\t// Gisement Minerai\n#define TXT_NO_REGISTERED_MODEM  \t506\t// Aucun modem configur\n#define TXT_CHRONOSHIFT          \t507\t// Dplacement chronoporte\n#define TXT_UNABLE_TO_OPEN_PORT  \t508\t// Adresse invalide ou en\n#define TXT_NO_DIAL_TONE         \t509\t// Pas de tonalit.\n#define TXT_NO_EXPANSION_SCENARIO\t510\t// Erreur - L'autre joueur n'a\n#define TXT_STAND_BY             \t511\t// Patientez SVP...\n#define TXT_THEME_CREDITS        \t512\t// Musique du gnrique de fin\n#define TXT_POWER_AAGUN          \t513\t// Puissance faible: Canon(s)\n#define TXT_POWER_TESLA          \t514\t// Puissance faible: Bobine(s)\n#define TXT_LOW_POWER            \t515\t// Puissance Faible\n#define TXT_COMMANDER            \t516\t// Commandant:\n#define TXT_BATTLES_WON          \t517\t// Parties gagnes:\n#define TXT_MISMATCH             \t518\t// Fichier de donnes du jeu\n#define TXT_SCENARIO_ERROR       \t519\t// Votre version de jeu\n#define TXT_CONNECTING           \t520\t// Connecting\n#define TXT_MODEM_INITIALISATION \t521\t// Initialisation du Modem\n#define TXT_DATA_COMPRESSION     \t522\t// Compression des Donnes\n#define TXT_ERROR_CORRECTION     \t523\t// Correction d'Erreur\n#define TXT_HARDWARE_FLOW_CONTROL\t524\t// Contrle Matriel du Flux\n#define TXT_ADVANCED             \t525\t// Avanc\n#define TXT_THEME_2ND_HAND       \t526\t// Seconde main\n#define TXT_THEME_ARAZOID        \t527\t// Arazode\n#define TXT_THEME_BACKSTAB       \t528\t// Retour  l'envoyeur\n#define TXT_THEME_CHAOS2         \t529\t// Chaos2\n#define TXT_THEME_SHUT_IT        \t530\t// Fermez-la !\n#define TXT_THEME_TWINMIX1       \t531\t// Visite de courtoisie\n#define TXT_THEME_UNDER3         \t532\t// A couvert\n#define TXT_THEME_VR2            \t533\t// VR2\n#define TXT_ASK_EMERGENCY_SAVE_NOT_RESPONDING\t534\t// L'autre systme ne rpond\n#define TXT_ASK_EMERGENCY_SAVE_HUNG_UP\t535\t// L'autre systme a\n#define TXT_NO_REG_APP           \t536\t// Alerte Rouge n'a pu\n#define TXT_NO_CS_SCENARIOS      \t537\t// Un joueur de la partie n'a\n#define TXT_MISSILESUB           \t538\t// Sous-marin MS\n#define TXT_SHOCKTROOPER         \t539\t// Electrocuteur\n#define TXT_MECHANIC             \t540\t// Mcanicien\n#define TXT_CHRONOTANK           \t541\t// Chrono Tank\n#define TXT_TESLATANK            \t542\t// Tank Tesla\n#define TXT_MAD                  \t543\t// Tank M.A.D.\n#define TXT_DEMOTRUCK            \t544\t// Camion de dmolition\n#define TXT_PHASETRANSPORT       \t545\t// Transport Camlon\n#define TXT_THEME_BOG            \t546\t// Marcages\n#define TXT_THEME_FLOAT_V2       \t547\t// Volutes\n#define TXT_THEME_GLOOM          \t548\t// Tnbres\n#define TXT_THEME_GRNDWIRE       \t549\t// Terrain min\n#define TXT_THEME_RPT            \t550\t// Mcaniciens 2\n#define TXT_THEME_SEARCH         \t551\t// Battue\n#define TXT_THEME_TRACTION       \t552\t// Traction\n#define TXT_THEME_WASTELND       \t553\t// Chaos\n#define TXT_CARRIER              \t554\t// Hliport Mobile\n"
  },
  {
    "path": "CODE/CONQUER.LNT",
    "content": "//  Watcom C, C++ (32 bit), -si4 -sp4,\n//  Standard lint options\n\n//    Compiler Options for Watcom C, C++ 32 bit\n\n-cwc\n\n//    This file contains options to allow PC-lint to process source\n//    files for your compiler.  It is used as follows:\n//\n//    lint  co-wc32.lnt  source-file(s)\n//\n-d_M_IX86=200   // assume Intel 80286 architecture -- modify to suit\n-d__declspec()= // ignore this construct\n\n  // additional reserve words needed\n+rw(_loadds,_export)\n+rw(__interrupt,__near,__far,__huge,__fortran,__pascal,__cdecl)\n+rw(__export,__loadds,__saveregs,__asm,__fastcall,__stdcall)\n+rw(_export)\n\n+fcd            // makes cdecl significant -- used for proto generation\n+fcu            // chars are by default unsigned\n+fsu            // so are strings\n-d__386__       // pre-defined macro for 386 version, not set by -cwc\n-d__FLAT__      // not set by -cwc\n-si4            // sizeof(int)         is 4\n-spN4           // sizeof(near pointer) is 4\n-spF6           // sizeof( far pointer) is 6\n-sld10          // sizeof(long double) is 10.\n-function(exit,_exit)   // _exit() is like exit()\n-emacro(734,putc)   // don't complain about items being too large.\n-emacro(506,putc)   // don't complain about constant Boolean\n-emacro(???,va_arg)     // the va_arg() macro can yield 415, 416, 661, 662\n\t\t\t// 796 and 797 (out-of-bounds errors).\n\n   // While processing compiler (library) header files ...\n-elib(46)       // an unsigned short bit field is used as __FILLER__\n-elib(522)      // function return value ignored\n-elib(537)      // repeated include file (ios.h)\n-elib(641)      // converting enum to int\n-elib(652)      // suppress message about #define of earlier declared symbols\n-elib(655)      // ORing enum's\n-elib(726)      // extraneous comma in enumeration\n-elib(760)      // suppress message about multiple identical macro defs\n-elib(762)      // suppress message about multiple identical declarations and\n-elib(806)      // small bit field is signed\n-elib(1053)     // prototypes cannot be distinguished\n-elib(1511)     // member (rdbuf) hides nonvirtual member\n-elib(1704)     // private copy constructor\n-elib(1712)     // default constructor missing\n-elib(1717)     // empty prototypes\n-elib(1720)     // strange argument to assignment operator\n-elib(1721)     // unusual operator =() declaration\n-elib(1722)     // assignment operator does not return ref to class\n-elib(1724)     // strange argument to copy constructor\n\n-esym(1702,operator<<,operator>>)\n\n//  The following functions exhibit variable return modes.\n//  That is, they may equally-usefully be called for a value\n//  as called just for their effects.  Accordingly we inhibit\n//  Warning 534 for these functions.\n//  Feel free to add to or subtract from this list.\n\n-esym(534,close,creat,fclose,fflush,fprintf,fputc)\n-esym(534,fputs,fscanf,fseek,fwrite,lseek,memcpy,memmove,memset)\n-esym(534,printf,puts,scanf,sprintf,sscanf,strcat,strcpy)\n-esym(534,strncat,strncpy,unlink,write)\n\n//------------------------------------------------------------------\n\n-width(0,0)\t\t\t\t// don't break up message lines\n\n// 32 bit integer and pointer size is four bytes.\n-si4 -sp4\n\n// Include directories\n-ic:\\projects\\c&czero\\code\\watcom\\h;..\\vq\\include;..\\gcl510\\h\n"
  },
  {
    "path": "CODE/CONST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CONST.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CONST.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 20, 1993                                           *\n *                                                                                             *\n *                  Last Update : September 20, 1993   [JLB]                                   *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/***************************************************************************\n**\tThese are the access passwords used to activate cheat mode, editor mode,\n**\tand special game options.\n*/\nlong const PlayCodes[] = {\n\t0xE0792D6D,\t\t\t\t\t// Dwight Okahara\n\t0x90046ECF,\t\t\t\t\t// Paul S. Mudra\n\t0xC3EE9A26,\t\t\t\t\t// Frank Klepaki\n\t0xED382178,\t\t\t\t\t// Ed Del Castillo\n\t0L\n};\n\nlong const CheatCodes[] = {\n\t0xA0E2AB53,\t\t\t\t\t// Joseph Hewitt\n\t0x00532693,\t\t\t\t\t// Mike Lightner\n\t0x7DDFF824,\t\t\t\t\t// Joe Bostic\n\t0x2CB5CF01,\t\t\t\t\t// Phil Gorrow\n\t0xB5B63531,\t\t\t\t\t// Bill Randolph\n\t0xDFABC23A,\t\t\t\t\t// Adam Isgreen\n\t0x52B19A22,\t\t\t\t\t// Erik Yeo\n\t0xBE79088C,\t\t\t\t\t// David Dettmer\n\t0xB216AE7E,\t\t\t\t\t// Barry Green\n\t0x0E07B213,\t\t\t\t\t// Steve Tall\n\t0L\n};\n\n\nlong const EditorCodes[] = {\n\t0xA2C09326,\t\t\t\t\t// Erik Yeo\n\t0x1F944BB3,\t\t\t\t\t// Mike Lightner\n\t0xDE07154D,\t\t\t\t\t// Adam Isgreen\n\t0x0E07B213,\t\t\t\t\t// Steve Tall\n\t0x16B170B1,\t\t\t\t\t// Joe Bostic\n\t0L\n};\n\n\n/***********************************************************************************************\n**\tUnit order names. These names correspond to the player selectable orders\n**\ta unit can have. The system initiated orders have no use for the ASCII name\n**\tassociated, but they are listed here for completeness sake.\n*/\nchar const * Missions[MISSION_COUNT] = {\n\t\"Sleep\",\n\t\"Attack\",\n\t\"Move\",\n\t\"QMove\",\n\t\"Retreat\",\n\t\"Guard\",\n\t\"Sticky\",\n\t\"Enter\",\n\t\"Capture\",\n\t\"Harvest\",\n\t\"Area Guard\",\n\t\"Return\",\n\t\"Stop\",\n\t\"Ambush\",\n\t\"Hunt\",\n\t\"Unload\",\n\t\"Sabotage\",\n\t\"Construction\",\n\t\"Selling\",\n\t\"Repair\",\n\t\"Rescue\",\n\t\"Missile\",\n\t\"Harmless\"\n};\n\n\n/***************************************************************************\n**\tSpecial weapon names.\n*/\n#ifdef SCENARIO_EDITOR\nchar const * const SpecialWeaponName[SPC_COUNT] = {\n\t\"Sonar Pulse\",\n\t\"Nuclear Missile\",\n\t\"Chronosphere\",\n\t\"Parachute Bomb\",\n\t\"Paratroopers\",\n\t\"Recon Plane\",\n\t\"Iron Curtain\",\n\t\"GPS Satellite\"\n};\n#endif\nint const SpecialWeaponHelp[SPC_COUNT] = {\n\tTXT_SONAR_PULSE,\n\tTXT_NUCLEAR_BOMB,\n\tTXT_CHRONOSHIFT,\n\tTXT_PARA_BOMB,\n\tTXT_PARA_INFANTRY,\n\tTXT_SPY_MISSION,\n\tTXT_INVUL,\n\tTXT_GPS_SATELLITE\n};\nchar const * const SpecialWeaponFile[SPC_COUNT] = {\n\t\"SONR\",\n\t\"ATOM\",\n\t\"WARP\",\n\t\"PBMB\",\n\t\"PINF\",\n\t\"CAM\",\n\t\"INFX\",\n\t\"GPSS\"\n};\n\n\n/***************************************************************************\n**\tType of quarry to search out and attack. These values are used for team\n**\tattack missions.\n*/\nchar const * const QuarryName[QUARRY_COUNT] = {\n\t\"N/A\",\n\t\"Anything\",\n\t\"Buildings - any\",\n\t\"Harvesters\",\n\t\"Infantry\",\n\t\"Vehicles - any\",\n\t\"Ships - any\",\n\t\"Factories\",\n\t\"Base Defenses\",\n\t\"Base Threats\",\n\t\"Power Facilities\",\n\t\"Fake Buildings\"\n};\n\n\n/***************************************************************************\n**\tThese are the text names for the formation types.\n*/\nchar const * const FormationName[FORMATION_COUNT] = {\n\t\"None\",\n\n\t\"Tight\",\n\t\"Loose\",\n\t\"Wedge North\",\n\t\"Wedge East\",\n\t\"Wedge South\",\n\t\"Wedge West\",\n\t\"Line N/S\",\n\t\"Line E/W\"\n};\n\n\n/***************************************************************************\n**\tThese are the ASCII names for the reinforcement sources.\n*/\nchar const * const SourceName[SOURCE_COUNT] =\n{\n\t\"North\",\n\t\"East\",\n\t\"South\",\n\t\"West\",\n\t\"Air\"\n};\n\n\n/***************************************************************************\n**\tThese are the text names for the various armor types a unit may possess.\n*/\nchar const * const ArmorName[ARMOR_COUNT] = {\n\t\"none\",\n\t\"wood\",\n\t\"light\",\n\t\"heavy\",\n\t\"concrete\"\n};\n\n\n// HACK ALERT! This unused text string is here to stop Watcom from crashing. There is some\n// magic text heap length that causes a crash before the code executes. This dummy string\n// changes the text heap length enough to stop the crash. Who knows why, but it works.\nchar * __test__ = \"alskdfjlasdfjkajsdfkja;sldjfklasj9awutreqjfnfdkvnldzlknvadsjgflkasdjfkajsdfas\";\n\n\n/***************************************************************************\n**\tThe list of VQ filenames.\n*/\nchar const * const VQName[VQ_COUNT] = {\n\t\"AAGUN\",\n\t\"MIG\",\n\t\"SFROZEN\",\n\t\"AIRFIELD\",\n\t\"BATTLE\",\n\t\"BMAP\",\n\t\"BOMBRUN\",\n\t\"DPTHCHRG\",\n\t\"GRVESTNE\",\n\t\"MONTPASS\",\n\t\"MTNKFACT\",\n\t\"CRONTEST\",\n\t\"OILDRUM\",\n\t\"ALLYEND\",\n\t\"RADRRAID\",\n\t\"SHIPYARD\",\n\t\"SHORBOMB\",\n\t\"SITDUCK\",\n\t\"SLNTSRVC\",\n\t\"SNOWBASE\",\n\t\"EXECUTE\",\n\t\"REDINTRO\",\t\t\t// low res.\n\t\"NUKESTOK\",\n\t\"V2ROCKET\",\n\t\"SEARCH\",\n\t\"BINOC\",\n\t\"ELEVATOR\",\n\t\"FROZEN\",\n\t\"MCV\",\n\t\"SHIPSINK\",\n\t\"SOVMCV\",\n\t\"TRINITY\",\n\t\"ALLYMORF\",\n\t\"APCESCPE\",\n\t\"BRDGTILT\",\n\t\"CRONFAIL\",\n\t\"STRAFE\",\n\t\"DESTROYR\",\n\t\"DOUBLE\",\n\t\"FLARE\",\n\t\"SNSTRAFE\",\n\t\"LANDING\",\n\t\"ONTHPRWL\",\n\t\"OVERRUN\",\n\t\"SNOWBOMB\",\n\t\"SOVCEMET\",\n\t\"TAKE_OFF\",\n\t\"TESLA\",\n\t\"SOVIET8\",\n\t\"SPOTTER\",\n\t\"ALLY1\",\n\t\"ALLY2\",\n\t\"ALLY4\",\n\t\"SOVFINAL\",\n\t\"ASSESS\",\n\t\"SOVIET10\",\n\t\"DUD\",\n\t\"MCV_LAND\",\n\t\"MCVBRDGE\",\n\t\"PERISCOP\",\n\t\"SHORBOM1\",\n\t\"SHORBOM2\",\n\t\"SOVBATL\",\n\t\"SOVTSTAR\",\n\t\"AFTRMATH\",\n\t\"SOVIET11\",\n\t\"MASASSLT\",\n\t\"ENGLISH\",\t\t// High res.\n\t\"SOVIET1\",\n\t\"SOVIET2\",\n\t\"SOVIET3\",\n\t\"SOVIET4\",\n\t\"SOVIET5\",\n\t\"SOVIET6\",\n\t\"SOVIET7\",\n\t\"PROLOG\",\n\t\"AVERTED\",\n\t\"COUNTDWN\",\n\t\"MOVINGIN\",\n\t\"ALLY10\",\n\t\"ALLY12\",\n\t\"ALLY5\",\n\t\"ALLY6\",\n\t\"ALLY8\",\n\t\"TANYA1\",\n\t\"TANYA2\",\n\t\"ALLY10B\",\n\t\"ALLY11\",\n\t\"ALLY14\",\n\t\"ALLY9\",\n\t\"SPY\",\n\t\"TOOFAR\",\n\t\"SOVIET12\",\n\t\"SOVIET13\",\n\t\"SOVIET9\",\n\t\"BEACHEAD\",\n\t\"SOVIET14\",\n\t\"SIZZLE\",\n\t\"SIZZLE2\",\n\t\"ANTEND\",\n\t\"ANTINTRO\"\n};\n\n\n/***************************************************************************\n**\tRelative coordinate offsets from the center of a cell for each\n**\tof the legal positions that an object in a cell may stop at. Only infantry\n**\tare allowed to stop at other than the center of the cell.\n*/\nCOORDINATE const StoppingCoordAbs[5] = {\n\t0x00800080L,\t// center\n\t0x00400040L,\t// upper left\n\t0x004000C0L,\t// upper right\n\t0x00C00040L,\t// lower left\n\t0x00C000C0L\t\t// lower right\n};\n\n\n/***************************************************************************\n**\tConverts pixel values (cell relative) into the appropriate lepton (sub cell)\n**\tvalue. This is used to convert pixel (screen) coordinates into the underlying\n**\tcoordinate system.\n*/\nunsigned char const Pixel2Lepton[24] = {\n\t0x00,0x0B,0x15,0x20,0x2B,0x35,0x40,0x4B,\n\t0x55,0x60,0x6B,0x75,0x80,0x8B,0x95,0xA0,\n\t0xAB,0xB5,0xC0,0xCB,0xD5,0xE0,0xEB,0xF5\n};\n\n\n/***************************************************************************\n**\tThis array is used to index a facing in order to retrieve a cell\n**\toffset that, when added to another cell, will achieve the adjacent cell\n**\tin the indexed direction.\n*/\nCELL const AdjacentCell[FACING_COUNT] = {\n\t-(MAP_CELL_W),\t\t\t\t// North\n\t-(MAP_CELL_W-1),\t\t\t// North East\n\t1,\t\t\t\t\t\t\t\t// East\n\tMAP_CELL_W+1,\t\t\t\t// South East\n\tMAP_CELL_W,\t\t\t\t\t// South\n\tMAP_CELL_W-1,\t\t\t\t// South West\n\t-1,\t\t\t\t\t\t\t// West\n\t-(MAP_CELL_W+1)\t\t\t// North West\n};\n\nCOORDINATE const AdjacentCoord[FACING_COUNT] = {\n\t0xFF000000L,\n\t0xFF000100L,\n\t0x00000100L,\n\t0x01000100L,\n\t0x01000000L,\n\t0x0100FF00L,\n\t0x0000FF00L,\n\t0xFF00FF00L\n};\n\n\n/***************************************************************************\n**\tThis specifies the odds of receiving the various random crate power\n**\tups. The odds are expressed as \"shares\" of 100 percent.\n*/\nint CrateShares[CRATE_COUNT] = {\n\t50,\t\t//\tCRATE_MONEY\n\t20,\t\t//\tCRATE_UNIT\n\t3,\t\t\t//\tCRATE_PARA_BOMB\n\t1,\t\t\t//\tCRATE_HEAL_BASE\n\t3,\t\t\t//\tCRATE_CLOAK\n\t5,\t\t\t//\tCRATE_EXPLOSION\n\t5,\t\t\t//\tCRATE_NAPALM\n\t20,\t\t//\tCRATE_SQUAD\n\t1,\t\t\t//\tCRATE_DARKNESS\n\t1,\t\t\t//\tCRATE_REVEAL\n\t3,\t\t\t//\tCRATE_SONAR\n\t10,\t\t//\tCRATE_ARMOR\n\t10,\t\t//\tCRATE_SPEED\n\t10,\t\t//\tCRATE_FIREPOWER\n\t1,\t\t\t//\tCRATE_ICBM\n\t1,\t\t\t//\tCRATE_TIMEQUAKE\n\t3,\t\t\t//\tCRATE_INVULN\n\t5\t\t\t// CRATE_VORTEX\n};\n\nAnimType CrateAnims[CRATE_COUNT] = {\n\tANIM_NONE,\t//\tCRATE_MONEY\n\tANIM_NONE,\t//\tCRATE_UNIT\n\tANIM_NONE,\t//\tCRATE_PARA_BOMB\n\tANIM_NONE,\t//\tCRATE_HEAL_BASE\n\tANIM_NONE,\t//\tCRATE_CLOAK\n\tANIM_NONE,\t//\tCRATE_EXPLOSION\n\tANIM_NONE,\t//\tCRATE_NAPALM\n\tANIM_NONE,\t//\tCRATE_SQUAD\n\tANIM_NONE,\t//\tCRATE_DARKNESS\n\tANIM_NONE,\t//\tCRATE_REVEAL\n\tANIM_NONE,\t//\tCRATE_SONAR\n\tANIM_NONE,\t//\tCRATE_ARMOR\n\tANIM_NONE,\t//\tCRATE_SPEED\n\tANIM_NONE,\t//\tCRATE_FIREPOWER\n\tANIM_NONE,\t//\tCRATE_ICBM\n\tANIM_NONE,\t//\tCRATE_TIMEQUAKE\n\tANIM_NONE,\t//\tCRATE_INVULN\n\tANIM_NONE   // CRATE_VORTEX\n};\n\nint CrateData[CRATE_COUNT] = {\n\t0,\t\t//\tCRATE_MONEY\n\t0,\t\t//\tCRATE_UNIT\n\t0,\t\t//\tCRATE_PARA_BOMB\n\t0,\t\t//\tCRATE_HEAL_BASE\n\t0,\t\t//\tCRATE_CLOAK\n\t0,\t\t//\tCRATE_EXPLOSION\n\t0,\t\t//\tCRATE_NAPALM\n\t0,\t\t//\tCRATE_SQUAD\n\t0,\t\t//\tCRATE_DARKNESS\n\t0,\t\t//\tCRATE_REVEAL\n\t0,\t\t//\tCRATE_SONAR\n\t0,\t\t//\tCRATE_ARMOR\n\t0,\t\t//\tCRATE_SPEED\n\t0,\t\t//\tCRATE_FIREPOWER\n\t0,\t\t//\tCRATE_ICBM\n\t0,\t\t//\tCRATE_TIMEQUAKE\n\t0,\t\t//\tCRATE_INVULN\n\t0\t\t//\tCRATE_VORTEX\n};\n\nchar const * const CrateNames[CRATE_COUNT] = {\n\t\"Money\",\n\t\"Unit\",\n\t\"ParaBomb\",\n\t\"HealBase\",\n\t\"Cloak\",\n\t\"Explosion\",\n\t\"Napalm\",\n\t\"Squad\",\n\t\"Darkness\",\n\t\"Reveal\",\n\t\"Sonar\",\n\t\"Armor\",\n\t\"Speed\",\n\t\"Firepower\",\n\t\"ICBM\",\n\t\"TimeQuake\",\n\t\"Invulnerability\",\n\t\"ChronalVortex\"\n};\n\n\n/***************************************************************************\n** This converts 0..255 facing values into either 8, 16, or 32 facing values.\n**\tNote: a simple shift won't suffice because 0..255 facing values should\n**\tbe converted to the CLOSEST appropriate facing, NOT rounded down to the\n**\tnearest facing.\n*/\nunsigned char const Facing8[256] = {\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,\n\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,\n\t2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,\n\t3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,\n\t4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n\t5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n\t6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n\t7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n};\n\n\nunsigned char const Facing16[256] = {\n\t0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,\n\t2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,\n\t4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,\n\t6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,\n\t8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,\n\t10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,\n\t12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,\n\t14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,0,0,0,0,0,0,0,0\n};\n\n\nsigned char const Rotation16[256] = {\n\t0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,\n\t0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,\n\t0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,\n\t0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,\n\t0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,\n\t0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,\n\t0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,\n\t0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1\n};\n\n\n/*\n**\tThis table incorporates a compensating factor for the distortion caused\n**\tby 3D-Studio when it tries to render 45% angles.\n*/\nunsigned char const Facing32[256] = {\n\t0,0,0,0,0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,\n\t3,4,4,4,4,4,4,5,5,5,5,5,5,5,6,6,6,6,6,6,6,7,7,7,7,7,7,7,8,8,8,8,\n\t8,8,8,9,9,9,9,9,9,9,10,10,10,10,10,10,10,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,\n\t13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,\n\t16,16,16,16,16,17,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,19,\n\t19,20,20,20,20,20,20,21,21,21,21,21,21,21,22,22,22,22,22,22,22,23,23,23,23,23,23,23,24,24,24,24,\n\t24,24,24,25,25,25,25,25,25,25,26,26,26,26,26,26,26,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,\n\t29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,30,31,31,31,31,31,31,31,31,31,0,0,0,0,0,0\n};\n\n\n#ifdef OBSOLETE\nunsigned char const Facing32[256] = {\n\t0,0,0,0,\n\t1,1,1,1,1,1,1,1,\n\t2,2,2,2,2,2,2,2,\n\t3,3,3,3,3,3,3,3,\n\t4,4,4,4,4,4,4,4,\n\t5,5,5,5,5,5,5,5,\n\t6,6,6,6,6,6,6,6,\n\t7,7,7,7,7,7,7,7,\n\t8,8,8,8,8,8,8,8,\n\t9,9,9,9,9,9,9,9,\n\t10,10,10,10,10,10,10,10,\n\t11,11,11,11,11,11,11,11,\n\t12,12,12,12,12,12,12,12,\n\t13,13,13,13,13,13,13,13,\n\t14,14,14,14,14,14,14,14,\n\t15,15,15,15,15,15,15,15,\n\t16,16,16,16,16,16,16,16,\n\t17,17,17,17,17,17,17,17,\n\t18,18,18,18,18,18,18,18,\n\t19,19,19,19,19,19,19,19,\n\t20,20,20,20,20,20,20,20,\n\t21,21,21,21,21,21,21,21,\n\t22,22,22,22,22,22,22,22,\n\t23,23,23,23,23,23,23,23,\n\t24,24,24,24,24,24,24,24,\n\t25,25,25,25,25,25,25,25,\n\t26,26,26,26,26,26,26,26,\n\t27,27,27,27,27,27,27,27,\n\t28,28,28,28,28,28,28,28,\n\t29,29,29,29,29,29,29,29,\n\t30,30,30,30,30,30,30,30,\n\t31,31,31,31,31,31,31,31,\n\t0,0,0,0\n};\n#endif\n\n\n/***************************************************************************\n**\tThese are the movement costs (in ticks at fastest speed) to enter each\n**\tof the given terrain cells.\n*/\n\nint const GroundColor[LAND_COUNT] = {\n\t141,\t\t\t// \"Clear\" terrain.\n\t141,\t\t\t// Road terrain.\n\t172,\t\t\t// Water.\n\t21,\t\t\t// Impassable rock.\n\t21,\t\t\t// Wall (blocks movement).\n\t158,\t\t\t// Tiberium field.\n\t141,\t\t\t//\tBeach terrain.\n\t141,\t\t\t// Rocky terrain.\n\t174\t\t\t// Rocky riverbed.\n};\n\nint const SnowColor[LAND_COUNT] = {\n\t141,\t\t\t// \"Clear\" terrain.\n\t141,\t\t\t// Road terrain.\n\t172,\t\t\t// Water.\n\t21,\t\t\t// Impassable rock.\n\t21,\t\t\t// Wall (blocks movement).\n\t158,\t\t\t// Tiberium field.\n\t141,\t\t\t//\tBeach terrain.\n\t141,\t\t\t// Rocky terrain.\n\t174\t\t\t// Rocky riverbed.\n};\n\n#ifdef NEVER\nint const GroundColor[LAND_COUNT] = {\n\t46,\t\t\t// \"Clear\" terrain.\n\t44,\t\t\t// Road terrain.\n\tBLUE,\t\t\t// Water.\n\tDKGREY,\t\t// Impassable rock.\n\tDKGREY,\t\t// Wall (blocks movement).\n\t158,\t\t\t// Tiberium field.\n\t64,\t\t\t//\tBeach terrain.\n\tDKGREY,\t\t// Rocky terrain.\n\tDKGREY\t\t// Rocky riverbed.\n};\n\nint const SnowColor[LAND_COUNT] = {\n\tWHITE, \t\t// \"Clear\" terrain.\n\tLTGRAY,\t\t// Road terrain.\n\tBLUE,\t\t\t// Water.\n\tDKGREY,\t\t// Impassable rock.\n\tDKGREY,\t\t// Wall (blocks movement).\n\t158,\t\t\t// Tiberium field.\n\tLTGRAY,\t\t//\tBeach terrain.\n\tDKGREY,\t\t// Rocky terrain.\n\tDKGREY\t\t// Rocky riverbed.\n};\n#endif\n\nGroundType Ground[LAND_COUNT];\n\n\n/***************************************************************************\n**\tThese are the names of the theaters.\n*/\nTheaterDataType const Theaters[THEATER_COUNT] = {\n\t{\"TEMPERATE\",\"TEMPERAT\",\"TEM\"},\n\t{\"SNOW\",\"SNOW\",\"SNO\"},\n\t{\"INTERIOR\",\"INTERIOR\",\"INT\"},\n};\n\n\nunsigned char const RemapCiv2[256] = {\n\t0,1,2,3,4,5,6,209,8,9,10,11,12,13,12,15,\t\t\t\t\t\t\t\t\t// 0..15\n\t16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,\t\t\t\t\t\t// 16..31\n\t32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,\t\t\t\t\t\t// 32..47\n\t48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,\t\t\t\t\t\t// 48..63\n\t64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,\t\t\t\t\t\t// 64..79\n\t80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,\t\t\t\t\t\t// 80..95\n\t96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,\t\t// 96..111\n\t112,113,114,115,116,117,187,188,120,121,122,123,124,125,126,127,\t// 112..127\n\t128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,\t// 128..143\n\t144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,209,\t// 144..159\n\t160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,\t// 160..175\n\t176,177,178,179,180,181,182,183,184,185,186,167, 13,189,190,191,\t// 176..191\n\t192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,\t// 192..207\n\t208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,\t// 208..223\n\t224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,\t// 224..239\n\t240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\t// 240..255\n};\n\nunsigned char const RemapCiv4[256] = {\n\t0,1,2,3,4,5,6,187,8,9,10,11,12,13,14,15,\t\t\t\t\t\t\t\t\t// 0..15\n\t16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,\t\t\t\t\t\t// 16..31\n\t32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,\t\t\t\t\t\t// 32..47\n\t48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,\t\t\t\t\t\t// 48..63\n\t64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,\t\t\t\t\t\t// 64..79\n\t80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,\t\t\t\t\t\t// 80..95\n\t96,97,98,99,100,101,102,103,104,105,106,107,108,118,110,119,\t\t// 96..111\n\t112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,\t// 112..127\n\t128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,\t// 128..143\n\t144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,\t// 144..159\n\t160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,\t// 160..175\n\t176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,\t// 176..191\n\t192,193,194,195,196,197,198,199,200,201,202,203,204,205,188,207,\t// 192..207\n\t208,209,182,211,212,213,214,215,216,217,218,219,220,221,222,223,\t// 208..223\n\t224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,\t// 224..239\n\t240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\t// 240..255\n};\n\nunsigned char const RemapCiv5[256] = {\n\t0,1,2,3,4,5,6,109,8,9,10,11,131,13,14,15,\t\t\t\t\t\t\t\t\t// 0..15\n\t16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,\t\t\t\t\t\t// 16..31\n\t32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,\t\t\t\t\t\t// 32..47\n\t48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,\t\t\t\t\t\t// 48..63\n\t64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,\t\t\t\t\t\t// 64..79\n\t80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,\t\t\t\t\t\t// 80..95\n\t96,97,98,99,100,101,102,103,104,105,106,107,108,177,110,178,\t\t// 96..111\n\t112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,\t// 112..127\n\t128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,\t// 128..143\n\t144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,\t// 144..159\n\t160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,\t// 160..175\n\t176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,\t// 176..191\n\t192,193,194,195,196,197,198,199,111,201,202,203,204,205,111,207,\t// 192..207\n\t208,209,182,211,212,213,214,215,216,217,218,219,220,221,222,223,\t// 208..223\n\t224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,\t// 224..239\n\t240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\t// 240..255\n};\n\nunsigned char const RemapCiv6[256] = {\n\t0,1,2,3,4,5,6,120,8,9,10,11,12,13,238,15,\t\t\t\t\t\t\t\t\t// 0..15\n\t16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,\t\t\t\t\t\t// 16..31\n\t32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,\t\t\t\t\t\t// 32..47\n\t48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,\t\t\t\t\t\t// 48..63\n\t64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,\t\t\t\t\t\t// 64..79\n\t80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,\t\t\t\t\t\t// 80..95\n\t96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,\t\t// 96..111\n\t112,113,114,115,116,117,236,206,120,121,122,123,124,125,126,127,\t// 112..127\n\t128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,\t// 128..143\n\t144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,111,\t// 144..159\n\t160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,\t// 160..175\n\t176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,\t// 176..191\n\t192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,\t// 192..207\n\t208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,\t// 208..223\n\t224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,\t// 224..239\n\t240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\t// 240..255\n};\n\nunsigned char const RemapCiv7[256] = {\n\t0,1,2,3,4,5,6,7,8,9,10,11,12,13,131,15,\t\t\t\t\t\t\t\t\t// 0..15\n\t16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,\t\t\t\t\t\t// 16..31\n\t32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,\t\t\t\t\t\t// 32..47\n\t48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,\t\t\t\t\t\t// 48..63\n\t64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,\t\t\t\t\t\t// 64..79\n\t80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,\t\t\t\t\t\t// 80..95\n\t96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,\t\t// 96..111\n\t112,113,114,115,116,117,157,212,120,121,122,123,124,125,126,127,\t// 112..127\n\t128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,\t// 128..143\n\t144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,7,\t\t// 144..159\n\t160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,\t// 160..175\n\t176,177,178,179,180,181,182,183,184,185,186,118,119,189,190,191,\t// 176..191\n\t192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,\t// 192..207\n\t208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,\t// 208..223\n\t224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,\t// 224..239\n\t240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\t// 240..255\n};\n\nunsigned char const RemapCiv8[256] = {\n\t0,1,2,3,4,5,6,182,8,9,10,11,12,13,131,15,\t\t\t\t\t\t\t\t\t// 0..15\n\t16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,\t\t\t\t\t\t// 16..31\n\t32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,\t\t\t\t\t\t// 32..47\n\t48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,\t\t\t\t\t\t// 48..63\n\t64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,\t\t\t\t\t\t// 64..79\n\t80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,\t\t\t\t\t\t// 80..95\n\t96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,\t\t// 96..111\n\t112,113,114,115,116,117,215,7,120,121,122,123,124,125,126,127,\t\t// 112..127\n\t128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,\t// 128..143\n\t144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,182,\t// 144..159\n\t160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,\t// 160..175\n\t176,177,178,179,180,181,182,183,184,185,186,198,199,189,190,191,\t// 176..191\n\t192,193,194,195,196,197,198,199,111,201,202,203,204,205,206,207,\t// 192..207\n\t208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,\t// 208..223\n\t224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,\t// 224..239\n\t240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\t// 240..255\n};\n\nunsigned char const RemapCiv9[256] = {\n\t0,1,2,3,4,5,6,7,8,9,10,11,12,13,7,15,\t\t\t\t\t\t\t\t\t\t// 0..15\n\t16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,\t\t\t\t\t\t// 16..31\n\t32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,\t\t\t\t\t\t// 32..47\n\t48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,\t\t\t\t\t\t// 48..63\n\t64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,\t\t\t\t\t\t// 64..79\n\t80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,\t\t\t\t\t\t// 80..95\n\t96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,\t\t// 96..111\n\t112,113,114,115,116,117,163,165,120,121,122,123,124,125,126,127,\t// 112..127\n\t128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,\t// 128..143\n\t144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,200,\t// 144..159\n\t160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,\t// 160..175\n\t176,177,178,179,180,181,182,183,184,185,186,111,13,189,190,191,\t// 176..191\n\t192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,\t// 192..207\n\t208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,\t// 208..223\n\t224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,\t// 224..239\n\t240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\t// 240..255\n};\n\nunsigned char const RemapCiv10[256] = {\n\t0,1,2,3,4,5,6,137,8,9,10,11,12,13,15,15,\t\t\t\t\t\t\t\t\t// 0..15\n\t16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,\t\t\t\t\t\t// 16..31\n\t32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,\t\t\t\t\t\t// 32..47\n\t48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,\t\t\t\t\t\t// 48..63\n\t64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,\t\t\t\t\t\t// 64..79\n\t80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,\t\t\t\t\t\t// 80..95\n\t96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,\t\t// 96..111\n\t112,113,114,115,116,117,129,131,120,121,122,123,124,125,126,127,\t// 112..127\n\t128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,\t// 128..143\n\t144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,137,\t// 144..159\n\t160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,\t// 160..175\n\t176,177,178,179,180,181,182,183,184,185,186,163,165,189,190,191,\t// 176..191\n\t192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,\t// 192..207\n\t208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,\t// 208..223\n\t224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,\t// 224..239\n\t240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\t// 240..255\n};\n\nunsigned char const RemapEmber[256] = {\n#define\tCEC\tCC_EMBER_COLOR\n\t  0,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,BLACK,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC\n};\n\n\n//char const Keys[] =\n//\t\"[PublicKey]\\n\"\n//\t\"1=AgkCbXo9sKMHOBk=\\n\"\n//#ifdef CHEAT_KEYS\n//\t\"[PrivateKey]\\n\"\n//\t\"1=AggxFU55vc7LYQ==\\n\"\n//#endif\n//\t\"\\n\";\n\nchar const Keys[] =\n\"[PublicKey]\\n\"\n\"1=AihRvNoIbTn85FZRYNZRcT+i6KpU+maCsEqr3Q5q+LDB5tH7Tz2qQ38V\\n\"\n#ifdef CHEAT_KEYS\n\"[PrivateKey]\\n\"\n\"1=AigKVje8mROcR8QixnxUEF5b29Curkq01DNDWCdOG99XBqH79OaCiTCB\\n\"\n#endif\n\"\\n\";\n"
  },
  {
    "path": "CODE/CONTROL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CONTROL.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CONTROL.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : December 5, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ControlClass::Action -- Normal action for control gadget objects.                         *\n *   ControlClass::ControlClass -- Constructor for control class objects.                      *\n *   ControlClass::ControlClass -- Copy constructor for control gadget.                        *\n *   ControlClass::Draw_Me -- Draw logic for the control class object.                         *\n *   ControlClass::Get_ID -- Gets the ID number for this gadget.                               *\n *   ControlClass::Make_Peer -- Assigns a peer gadget to this gadget.                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * ControlClass::ControlClass -- Constructor for control class objects.                        *\n *                                                                                             *\n *    This is the normal constructor for control class objects. At this level, it only needs   *\n *    to record the ID number assigned to this button.                                         *\n *                                                                                             *\n * INPUT:   id    -- The ID number for this gadget. If the ID number specified is 0, then      *\n *                   this tells the system that no special ID code should be returned.         *\n *                                                                                             *\n *          x,y   -- Pixel coordinate of upper left corner of gadget's region.                 *\n *                                                                                             *\n *          w,h   -- Pixel dimensions of the gadget's region.                                  *\n *                                                                                             *\n *          flags -- The input event flags that this gadget recognizes.                        *\n *                                                                                             *\n *          sticky-- This this a \"sticky\" gadget? A sticky gadget is one that takes over the   *\n *                   gadget list while the mouse button is held down, if the mouse button was  *\n *                   initially clicked over its region. This is the behavior of \"normal\"       *\n *                   buttons in Windows.                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nControlClass::ControlClass(unsigned id, int x, int y, int w, int h, unsigned flags, int sticky) :\n\tGadgetClass(x, y, w, h, flags, sticky),\n\tID(id),\n\tPeer(0)\n{\n}\n\n\n/***********************************************************************************************\n * ControlClass::ControlClass -- Copy constructor for control gadget.                          *\n *                                                                                             *\n *    This copy constructor for a control gadget is used create a duplicate gadget that        *\n *    is functionally similar.                                                                 *\n *                                                                                             *\n * INPUT:   control  -- Reference to the gadget that is to be copied.                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/05/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nControlClass::ControlClass(ControlClass const & control) :\n\tGadgetClass(control),\n\tID(control.ID),\n\tPeer(control.Peer)\n{\n}\n\n/***********************************************************************************************\n * ControlClass::Action -- Normal action for control gadget objects.                           *\n *                                                                                             *\n *    This function gets called when the input event that this control gadget is looking for   *\n *    occurs. In such a case, the return key code value is changed to the gadget's ID number   *\n *    with the special button bit flag attached.                                               *\n *                                                                                             *\n * INPUT:   flags -- The event that triggered this function call. If this value is NULL, then  *\n *                   this is a forced (probably due to the sticky flag) call and the key code  *\n *                   is not altered.                                                           *\n *                                                                                             *\n *          key   -- Reference to the key code that will be returned by the controlling        *\n *                   Input() function.                                                         *\n *                                                                                             *\n * OUTPUT:  bool; Should further list processing be aborted?                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ControlClass::Action(unsigned flags, KeyNumType & key)\n{\n\n\t/*\n\t**\tOnly if the flags indicate that a recognized action has occurred, do the\n\t**\tnormal processing of this gadget and set return value to the gadget ID.\n\t*/\n\tif (flags) {\n\t\tif (ID) {\n\t\t\tkey = (KeyNumType)(ID | KN_BUTTON);\n\t\t} else {\n\t\t\tkey = KN_NONE;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is a peer link established, inform that gadget of this\n\t**\taction call.\n\t*/\n\tif (Peer) {\n\t\tPeer->Peer_To_Peer(flags, key, *this);\n\t}\n\n\treturn(GadgetClass::Action(flags, key));\n}\n\n\n/***********************************************************************************************\n * ControlClass::Make_Peer -- Assigns a peer gadget to this gadget.                            *\n *                                                                                             *\n *    This function will assign another gadget to this one. That other gadget will receive     *\n *    notification of any Action() call to this gadget. Presumably, this is how one gadget     *\n *    can automatically adapt to changes in another. Say for example, a slider bar can affect  *\n *    the list box it is attached to.                                                          *\n *                                                                                             *\n * INPUT:   gadget   -- The gadget to inform when any Action() function is called.             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ControlClass::Make_Peer(GadgetClass & gadget)\n{\n\tPeer = &gadget;\n}\n\n\n/***********************************************************************************************\n * ControlClass::Get_ID -- Gets the ID number for this gadget.                                 *\n *                                                                                             *\n *    This function will query and return with the ID number for this gadget. It is primarily  *\n *    used by the Extract_Gadget() function.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the ID number for this gadget. If zero is returned, this means that   *\n *          no ID was assigned to this gadget. This is a special case since a zero value will  *\n *          never be returned as a pseudo-key as is done with non-zero values.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned ControlClass::Get_ID(void) const\n{\n\treturn(ID);\n}\n\n\n/***********************************************************************************************\n * ControlClass::Draw_Me -- Draw logic for the control class object.                           *\n *                                                                                             *\n *    This is called when the control object might need to be redrawn or when redrawing is     *\n *    necessary. Since at this level of the class hierarchy, no actual drawing occurs, this    *\n *    routine doesn't perform any rendering. It does, however, inform any peer attached        *\n *    object that a Draw_Me function has been called. Presumably, the attached peer gadget     *\n *    might very well need to be redrawn as a result of some action by this gadget. Since this *\n *    gadget might, more than likely, be of the \"sticky\" variety, a normal call to Draw_Me     *\n *    for the other gadget will not occur. It must rely on the call by this routine in order   *\n *    to update correctly. A typical example of this would be a slider that is attached to     *\n *    a list box. As the slider is being drug around, the attached list box must be redrawn.   *\n *                                                                                             *\n * INPUT:   forced   -- Should the redraw be forced regardless of the redraw flag?             *\n *                                                                                             *\n * OUTPUT:  bool; Was the gadget redrawn?                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ControlClass::Draw_Me(int forced)\n{\n\tif (Peer) {\n\t\tPeer->Draw_Me();\n\t}\n\treturn(GadgetClass::Draw_Me(forced));\n}\n"
  },
  {
    "path": "CODE/CONTROL.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CONTROL.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CONTROL.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CONTROL_H\n#define CONTROL_H\n\n#include\t\"gadget.h\"\n\n/***************************************************************************\n * ControlClass -- Region tracking class\t\t\t\t\t\t\t\t\t         *\n *                                                                         *\n * INPUT:      int x -- x position of gadget\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint y -- y position of gadget\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint w -- width of gadget\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint h -- height of gadget\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tUWORD flags -- see enumeration choices\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     0 = new scenario created, -1 = not\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tThis class is Abstract (cannot make an instance of it)      *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/03/1995 MML : Created.                                             *\n *=========================================================================*/\nclass ControlClass : public GadgetClass\n{\n\tpublic:\n\t\tControlClass(NoInitClass const & x) : GadgetClass(x) {};\n\t\tControlClass(unsigned id, int x, int y, int w, int h, unsigned flags=LEFTPRESS|RIGHTPRESS, int sticky=false);\n\t\tControlClass(ControlClass const & control);\n\n\t\tvirtual void Make_Peer(GadgetClass & gadget);\n\n\t\t/*\n\t\t**\tRender support function.\n\t\t*/\n\t\tvirtual int Draw_Me(int forced=false);\n\n\t\t/*\n\t\t**\tThis is the ID number for this control gadget. This number is used to generate\n\t\t**\ta special pseudo-key when the gadget detects valid input.\n\t\t*/\n\t\tunsigned ID;\n\n\tprotected:\n\t\tvirtual unsigned Get_ID(void) const;\n\t\tvirtual int Action(unsigned flags, KeyNumType & key);\n\n\t\t/*\n\t\t**\tThis points to the peer button to inform when something happens to this\n\t\t**\tgadget.\n\t\t*/\n\t\tGadgetClass * Peer;\n};\n\n#endif\n\n"
  },
  {
    "path": "CODE/COORD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/COORD.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : COORD.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : July 22, 1996 [JLB]                                          *\n *                                                                                             *\n * Support code to handle the coordinate system is located in this module.                     *\n * Routines here will be called QUITE frequently during play and must be                       *\n * as efficient as possible.                                                                   *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Cardinal_To_Fixed -- Converts cardinal numbers into a fixed point number.                 *\n *   Coord_Cell -- Convert a coordinate into a cell number.                                    *\n *   Coord_Move -- Moves a coordinate an arbitrary direction for an arbitrary distance         *\n *   Coord_Scatter -- Determines a random coordinate from an anchor point.                     *\n *   Coord_Spillage_List -- Calculate a spillage list for the dirty rectangle specified.       *\n *   Coord_Spillage_List -- Determines the offset list for cell spillage/occupation.           *\n *   Distance -- Determines the cell distance between two cells.                               *\n *   Distance -- Determines the lepton distance between two coordinates.                       *\n *   Distance -- Fetch distance between two target values.                                     *\n *   Fixed_To_Cardinal -- Converts a fixed point number into a cardinal number.                *\n *   Normal_Move_Point -- Moves point with tilt compensation.                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * Coord_Cell -- Convert a coordinate into a cell number.                                      *\n *                                                                                             *\n *    This routine will convert the specified coordinate value into a cell number. This is     *\n *    useful to determine the map index number into the cell array that corresponds to a       *\n *    particular coordinate.                                                                   *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to convert into a cell number.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the cell number that corresponds to the coordinate specified.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL Coord_Cell(COORDINATE coord)\n{\n\tCELL_COMPOSITE cell;\n\tcell.Cell = 0;\n\tcell.Sub.X = ((COORD_COMPOSITE &)coord).Sub.X.Sub.Cell;\n\tcell.Sub.Y = ((COORD_COMPOSITE &)coord).Sub.Y.Sub.Cell;\n\treturn(cell.Cell);\n//\treturn(XY_Cell(((COORD_COMPOSITE)coord).Sub.X, ((COORD_COMPOSITE)composite).Sub.Y));\n}\n\n\n/***********************************************************************************************\n * Distance -- Fetch distance between two target values.                                       *\n *                                                                                             *\n *    This routine will determine the lepton distance between the two specified target         *\n *    values.                                                                                  *\n *                                                                                             *\n * INPUT:   target1  -- First target value.                                                    *\n *                                                                                             *\n *          target2  -- Second target value.                                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the lepton distance between the two target values.                    *\n *                                                                                             *\n * WARNINGS:   Be sure that the targets are legal before calling this routine. Otherwise, the  *\n *             return value is meaningless.                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Distance(TARGET target1, TARGET target2)\n{\n\treturn(Distance(As_Coord(target1), As_Coord(target2)));\n}\n\n\n/***********************************************************************************************\n * Distance -- Determines the lepton distance between two coordinates.                         *\n *                                                                                             *\n *    This routine is used to determine the distance between two coordinates. It uses the      *\n *    Dragon Strike method of distance determination and thus it is very fast.                 *\n *                                                                                             *\n * INPUT:   coord1   -- First coordinate.                                                      *\n *                                                                                             *\n *          coord2   -- Second coordinate.                                                     *\n *                                                                                             *\n * OUTPUT:  Returns the lepton distance between the two coordinates.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Distance(COORDINATE coord1, COORDINATE coord2)\n{\n\tint\tdiff1, diff2;\n\n\tdiff1 = Coord_Y(coord1) - Coord_Y(coord2);\n\tif (diff1 < 0) diff1 = -diff1;\n\tdiff2 = Coord_X(coord1) - Coord_X(coord2);\n\tif (diff2 < 0) diff2 = -diff2;\n\tif (diff1 > diff2) {\n\t\treturn(diff1 + ((unsigned)diff2 / 2));\n\t}\n\treturn(diff2 + ((unsigned)diff1 / 2));\n}\n\n\n/***********************************************************************************************\n * Coord_Spillage_List -- Determines the offset list for cell spillage/occupation.             *\n *                                                                                             *\n *    This routine will take an arbitrary position and object size and return with a list of   *\n *    cell offsets from the current cell for all cells that are overlapped by the object. The  *\n *    first cell offset is always zero, so to just get the adjacent spill cell list, add one   *\n *    to the return pointer.                                                                   *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to examine.                                                *\n *                                                                                             *\n *          maxsize -- The maximum width/height of the object (pixels).                        *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a spillage list.                                         *\n *                                                                                             *\n * WARNINGS:   The algorithm is limited to working with a maxsize of 48 or less. Larger values *\n *             will generate an incomplete overlap list.                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/06/1993 JLB : Created.                                                                 *\n *   03/25/1994 JLB : Added width optimization.                                                *\n *   04/29/1994 JLB : Converted to C.                                                          *\n *   06/03/1994 JLB : Converted to general purpose spillage functionality.                     *\n *   01/07/1995 JLB : Manually calculates spillage list for large objects.                     *\n *=============================================================================================*/\nshort const * Coord_Spillage_List(COORDINATE coord, int maxsize)\n{\n\tstatic short const _MoveSpillage[(int)FACING_COUNT+1][5] = {\n\t\t{0, -MAP_CELL_W, REFRESH_EOL, 0, 0},\t\t\t\t\t\t// N\n\t\t{0, -MAP_CELL_W, 1, -(MAP_CELL_W-1), REFRESH_EOL},\t\t// NE\n\t\t{0, 1, REFRESH_EOL, 0, 0},\t\t\t\t\t\t\t\t\t\t// E\n\t\t{0, 1, MAP_CELL_W, MAP_CELL_W+1, REFRESH_EOL},\t\t\t// SE\n\t\t{0, MAP_CELL_W, REFRESH_EOL, 0, 0},\t\t\t\t\t\t\t// S\n\t\t{0, -1, MAP_CELL_W, MAP_CELL_W-1, REFRESH_EOL},\t\t\t// SW\n\t\t{0, -1, REFRESH_EOL, 0, 0},\t\t\t\t\t\t\t\t\t// W\n\t\t{0, -1, -MAP_CELL_W, -(MAP_CELL_W+1), REFRESH_EOL},\t// NW\n\t\t{0, REFRESH_EOL, 0, 0, 0}\t\t\t\t\t\t\t\t\t\t// non-moving.\n\t};\n\tstatic short _manual[10];\n//;\t00 = on axis\n//;\t01 = below axis\n//;\t10 = above axis\n//;\t11 = undefined\n\tstatic signed char const _SpillTable[16]\t= {8,6,2,-1,0,7,1,-1,4,5,3,-1,-1,-1,-1,-1};\n\tint\tindex=0;\n\tint\tx,y;\n\n\t/*\n\t**\tFor mondo-enourmo-gigundo objects, use a prebuilt mammoth table\n\t**\tthat covers a 5x5 square region.\n\t*/\n\tif (maxsize > ICON_PIXEL_W * 2) {\n\t\tstatic short const _gigundo[] = {\n\t\t\t-((2*MAP_CELL_W)-2),-((2*MAP_CELL_W)-1),-((2*MAP_CELL_W)),-((2*MAP_CELL_W)+1),-((2*MAP_CELL_W)+2),\n\t\t\t-((1*MAP_CELL_W)-2),-((1*MAP_CELL_W)-1),-((1*MAP_CELL_W)),-((1*MAP_CELL_W)+1),-((1*MAP_CELL_W)+2),\n\t\t\t-((0*MAP_CELL_W)-2),-((0*MAP_CELL_W)-1),-((0*MAP_CELL_W)),-((0*MAP_CELL_W)+1),-((0*MAP_CELL_W)+2),\n\t\t\t((1*MAP_CELL_W)-2),((1*MAP_CELL_W)-1),((1*MAP_CELL_W)),((1*MAP_CELL_W)+1),((1*MAP_CELL_W)+2),\n\t\t\t+((2*MAP_CELL_W)-2),+((2*MAP_CELL_W)-1),+((2*MAP_CELL_W)),+((2*MAP_CELL_W)+1),+((2*MAP_CELL_W)+2),\n\t\t\tREFRESH_EOL\n\t\t};\n\t\treturn(&_gigundo[0]);\n\t}\n\n\t/*\n\t**\tFor very large objects, build the overlap list by hand. This is time consuming, but\n\t**\tnot nearly as time consuming as drawing even a single cell unnecessarily.\n\t*/\n\tif (maxsize > ICON_PIXEL_W) {\n\t\tmaxsize = min(maxsize, (ICON_PIXEL_W*2))/2;\n\n\t\tx = (ICON_PIXEL_W * Coord_XLepton(coord)) / ICON_LEPTON_W;\n\t\ty = (ICON_PIXEL_H * Coord_YLepton(coord)) / ICON_LEPTON_H;\n\t\tint left = x-maxsize;\n\t\tint right = x+maxsize;\n\t\tint top = y-maxsize;\n\t\tint bottom = y+maxsize;\n\n\t\t_manual[index++] = 0;\n\t\tif (left < 0) _manual[index++] = -1;\n\t\tif (right >= ICON_PIXEL_W) _manual[index++] = 1;\n\t\tif (top < 0) _manual[index++] = -MAP_CELL_W;\n\t\tif (bottom >= ICON_PIXEL_H) _manual[index++] = MAP_CELL_W;\n\t\tif (left < 0 && top < 0) _manual[index++] = -(MAP_CELL_W+1);\n\t\tif (right >= ICON_PIXEL_W && bottom >= ICON_PIXEL_H) _manual[index++] = MAP_CELL_W+1;\n\t\tif (left < 0 && bottom >= ICON_PIXEL_H) _manual[index++] = MAP_CELL_W-1;\n\t\tif (right >= ICON_PIXEL_H && top < 0) _manual[index++] = -(MAP_CELL_W-1);\n\t\t_manual[index] = REFRESH_EOL;\n\t\treturn(&_manual[0]);\n\t}\n\n\t/*\n\t**\tDetermine the number of leptons \"leeway\" allowed this unit.\n\t*/\n\tint posval = Pixel2Lepton[(ICON_PIXEL_W-maxsize)/2];\n\n\tx = Coord_XLepton(coord) - 0x0080;\n\ty = Coord_YLepton(coord) - 0x0080;\n\tif (y > posval) index |= 0x08;\t\t\t// Spilling South.\n\tif (y < -posval) index |= 0x04;\t\t\t// Spilling North.\n\tif (x > posval) index |= 0x02;\t\t\t// Spilling East.\n\tif (x < -posval) index |= 0x01;\t\t\t// Spilling West.\n\n\treturn(&_MoveSpillage[_SpillTable[index]][0]);\n}\n\n\n/***********************************************************************************************\n * Coord_Spillage_List -- Calculate a spillage list for the dirty rectangle specified.         *\n *                                                                                             *\n *    Given a center coordinate and a dirty rectangle, calcuate a cell offset list for         *\n *    determining such things as overlap and redraw logic. Optionally, the center cell         *\n *    location will not be part of the list.                                                   *\n *                                                                                             *\n * INPUT:   coord -- The center coordinate that the dirty rectangle is based off of.           *\n *                                                                                             *\n *          rect  -- Reference to the dirty rectangle.                                         *\n *                                                                                             *\n *          nocenter -- If true, then the center cell offset will not be part of the spillage  *\n *                      list returned. This is handy when the center cell is known to be       *\n *                      processed by some other method and it can be safely and efficiently    *\n *                      ignored by the list generated.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the spillage list that corresponds to the data           *\n *          specified. This is a pointer to a static buffer and as such it will only be valid  *\n *          until the next time that this routine is called.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/22/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * Coord_Spillage_List(COORDINATE coord, Rect const & rect, bool nocenter)\n{\n\tif (!rect.Is_Valid()) {\n\t\tstatic short const _list[] = {REFRESH_EOL};\n\t\treturn(_list);\n\t}\n\n\tCELL coordcell = Coord_Cell(coord);\n\tLEPTON x = Coord_X(coord);\n\tLEPTON y = Coord_Y(coord);\n\n\t/*\n\t**\tAdd the rectangle values to the coordinate in order to normalize the start and end\n\t**\tcorners of the rectangle. The values are now absolute to the real game world rather\n\t**\tthan relative to the coordinate.\n\t*/\n\tLEPTON_COMPOSITE startx;\n\tLEPTON_COMPOSITE starty;\n\tLEPTON_COMPOSITE endx;\n\tLEPTON_COMPOSITE endy;\n\tstartx.Raw = (int)x + (short)Pixel_To_Lepton(rect.X);\n\tstarty.Raw = (int)y + (short)Pixel_To_Lepton(rect.Y);\n\tendx.Raw = startx.Raw + Pixel_To_Lepton(rect.Width-1);\n\tendy.Raw = starty.Raw + Pixel_To_Lepton(rect.Height-1);\n\n\t/*\n\t**\tDetermine the upper left and lower right cell indexes. This is a simple conversion from\n\t**\ttheir lepton counterpart. These cells values are used to form the bounding box for the\n\t**\tmap offset list.\n\t*/\n\tint cellx = startx.Sub.Cell;\n\tint cellx2 = endx.Sub.Cell;\n\tint celly = starty.Sub.Cell;\n\tint celly2 = endy.Sub.Cell;\n\n\t/*\n\t**\tGenerate the spillage list by counting off the rows and colums of the cells\n\t**\tthat are affected. This is easy since the upper left and lower right corner cells\n\t**\tare known.\n\t*/\n\tint count = 0;\n\tstatic short _spillagelist[128];\n\tshort * ptr = _spillagelist;\n\tfor (int yy = celly; yy <= celly2; yy++) {\n\t\tfor (int xx = cellx; xx <= cellx2; xx++) {\n\t\t\tshort offset = (XY_Cell(xx, yy) - coordcell);\n\t\t\tif (!nocenter || offset != 0) {\n\t\t\t\t*ptr++ = offset;\n\t\t\t\tcount++;\n\t\t\t\tif (count+2 >= ARRAY_SIZE(_spillagelist)) break;\n\t\t\t}\n\t\t}\n\t\tif (count+2 >= ARRAY_SIZE(_spillagelist)) break;\n\t}\n\n\t/*\n\t**\tCap the list with the end of list marker and then return a pointer\n\t**\tto the completed list.\n\t*/\n\t*ptr = REFRESH_EOL;\n\treturn(_spillagelist);\n}\n\n\n/***********************************************************************************************\n * Coord_Move -- Moves a coordinate an arbitrary direction for an arbitrary distance           *\n *                                                                                             *\n *    This function will move a coordinate in a using SIN and COS arithmetic.                  *\n *                                                                                             *\n * INPUT:   start    -- The starting coordinate.                                               *\n *                                                                                             *\n *          dir      -- The direction to move the coordinate.                                  *\n *                                                                                             *\n *          distance -- The distance to move the coordinate position (in leptons).             *\n *                                                                                             *\n * OUTPUT:  Returns the new coordinate position.                                               *\n *                                                                                             *\n * WARNINGS:   This routine uses multiplies -- use with caution.                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE Coord_Move(COORDINATE start, register DirType dir, unsigned short distance)\n{\n#ifdef NEVER\n\tshort x = Coord_X(start);\n\tshort y = Coord_Y(start);\n\n\tMove_Point(x, y, dir, distance);\n\treturn(XY_Coord(x,y));\n#endif\n\n\tMove_Point(*(short *)&start, *(((short *)&start)+1), dir, distance);\n\treturn(start);\n}\n\n\n/***********************************************************************************************\n * Coord_Scatter -- Determines a random coordinate from an anchor point.                       *\n *                                                                                             *\n *    This routine will perform a scatter algorithm on the specified                           *\n *    anchor point in order to return with another coordinate that is                          *\n *    randomly nearby the original. Typical use of this would be for                           *\n *    missile targeting.                                                                       *\n *                                                                                             *\n * INPUT:   coord    -- This is the anchor coordinate.                                         *\n *                                                                                             *\n *          distance -- This is the distance in pixels that the scatter                        *\n *                      should fall within.                                                    *\n *                                                                                             *\n *          lock     -- bool; Convert the new coordinate into a center                         *\n *                      cell based coordinate?                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a new coordinate that is nearby the original.                         *\n *                                                                                             *\n * WARNINGS:   Maximum pixel scatter distance is 255.                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/01/1992 JLB : Created.                                                                 *\n *   05/13/1992 JLB : Only uses Random().                                                      *\n *=============================================================================================*/\nCOORDINATE Coord_Scatter(COORDINATE coord, unsigned distance, bool lock)\n{\n\tCOORDINATE\tnewcoord;\n\n\tnewcoord = Coord_Move(coord, Random_Pick(DIR_N, DIR_MAX), distance);\n\n\tif (newcoord & HIGH_COORD_MASK) newcoord = coord;\n\n\tif (lock) {\n\t\tnewcoord = Coord_Snap(newcoord);\n\t}\n\n\treturn(newcoord);\n}\n\nextern int calcx(signed short, short distance);\n#pragma aux calcx parm [ax] [bx] \\\n\tmodify [eax dx] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"imul bx\"\t\t\t\t\t\t\\\n\t\"shl\tax,1\"\t\t\t\t\t\t\\\n\t\"rcl\tdx,1\"\t\t\t\t\t\t\\\n\t\"mov\tal,ah\"\t\t\t\t\t\\\n\t\"mov\tah,dl\"\t\t\t\t\t\\\n\t\"cwd\"\t\t\t\t\t\t\t\t\\\n//\t\"and\teax,0FFFFh\";\n\nextern int calcy(signed short, short distance);\n#pragma aux calcy parm [ax] [bx] \\\n\tmodify [eax dx] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"imul bx\"\t\t\t\t\t\t\\\n\t\"shl\tax,1\"\t\t\t\t\t\t\\\n\t\"rcl\tdx,1\"\t\t\t\t\t\t\\\n\t\"mov\tal,ah\"\t\t\t\t\t\\\n\t\"mov\tah,dl\"\t\t\t\t\t\\\n\t\"cwd\"\t\t\t\t\t\t\t\t\\\n\t\"neg\teax\";\n//\t\"and\teax,0FFFFh\"\t\t\t\t\\\n\nvoid Move_Point(short &x, short &y, register DirType dir, unsigned short distance)\n{\n\tstatic char const CosTable[256] = {\n\t\t0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x15,\n\t\t0x18,0x1b,0x1e,0x21,0x24,0x27,0x2a,0x2d,\n\t\t0x30,0x33,0x36,0x39,0x3b,0x3e,0x41,0x43,\n\t\t0x46,0x49,0x4b,0x4e,0x50,0x52,0x55,0x57,\n\t\t0x59,0x5b,0x5e,0x60,0x62,0x64,0x65,0x67,\n\t\t0x69,0x6b,0x6c,0x6e,0x6f,0x71,0x72,0x74,\n\t\t0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7b,\n\t\t0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7e,0x7e,\n\n\t\t0x7f,0x7e,0x7e,0x7e,0x7e,0x7e,0x7d,0x7d,\n\t\t0x7c,0x7b,0x7b,0x7a,0x79,0x78,0x77,0x76,\n\t\t0x75,0x74,0x72,0x71,0x70,0x6e,0x6c,0x6b,\n\t\t0x69,0x67,0x66,0x64,0x62,0x60,0x5e,0x5b,\n\t\t0x59,0x57,0x55,0x52,0x50,0x4e,0x4b,0x49,\n\t\t0x46,0x43,0x41,0x3e,0x3b,0x39,0x36,0x33,\n\t\t0x30,0x2d,0x2a,0x27,0x24,0x21,0x1e,0x1b,\n\t\t0x18,0x15,0x12,0x0f,0x0c,0x09,0x06,0x03,\n\n\t\t0x00,0xfd,0xfa,0xf7,0xf4,0xf1,0xee,0xeb,\n\t\t0xe8,0xe5,0xe2,0xdf,0xdc,0xd9,0xd6,0xd3,\n\t\t0xd0,0xcd,0xca,0xc7,0xc5,0xc2,0xbf,0xbd,\n\t\t0xba,0xb7,0xb5,0xb2,0xb0,0xae,0xab,0xa9,\n\t\t0xa7,0xa5,0xa2,0xa0,0x9e,0x9c,0x9a,0x99,\n\t\t0x97,0x95,0x94,0x92,0x91,0x8f,0x8e,0x8c,\n\t\t0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x85,\n\t\t0x84,0x83,0x83,0x82,0x82,0x82,0x82,0x82,\n\n\t\t0x82,0x82,0x82,0x82,0x82,0x82,0x83,0x83,\n\t\t0x84,0x85,0x85,0x86,0x87,0x88,0x89,0x8a,\n\t\t0x8b,0x8c,0x8e,0x8f,0x90,0x92,0x94,0x95,\n\t\t0x97,0x99,0x9a,0x9c,0x9e,0xa0,0xa2,0xa5,\n\t\t0xa7,0xa9,0xab,0xae,0xb0,0xb2,0xb5,0xb7,\n\t\t0xba,0xbd,0xbf,0xc2,0xc5,0xc7,0xca,0xcd,\n\t\t0xd0,0xd3,0xd6,0xd9,0xdc,0xdf,0xe2,0xe5,\n\t\t0xe8,0xeb,0xee,0xf1,0xf4,0xf7,0xfa,0xfd,\n\t};\n\n\tstatic char const SinTable[256] = {\n\t\t0x7f,0x7e,0x7e,0x7e,0x7e,0x7e,0x7d,0x7d,\n\t\t0x7c,0x7b,0x7b,0x7a,0x79,0x78,0x77,0x76,\n\t\t0x75,0x74,0x72,0x71,0x70,0x6e,0x6c,0x6b,\n\t\t0x69,0x67,0x66,0x64,0x62,0x60,0x5e,0x5b,\n\t\t0x59,0x57,0x55,0x52,0x50,0x4e,0x4b,0x49,\n\t\t0x46,0x43,0x41,0x3e,0x3b,0x39,0x36,0x33,\n\t\t0x30,0x2d,0x2a,0x27,0x24,0x21,0x1e,0x1b,\n\t\t0x18,0x15,0x12,0x0f,0x0c,0x09,0x06,0x03,\n\n\t\t0x00,0xfd,0xfa,0xf7,0xf4,0xf1,0xee,0xeb,\n\t\t0xe8,0xe5,0xe2,0xdf,0xdc,0xd9,0xd6,0xd3,\n\t\t0xd0,0xcd,0xca,0xc7,0xc5,0xc2,0xbf,0xbd,\n\t\t0xba,0xb7,0xb5,0xb2,0xb0,0xae,0xab,0xa9,\n\t\t0xa7,0xa5,0xa2,0xa0,0x9e,0x9c,0x9a,0x99,\n\t\t0x97,0x95,0x94,0x92,0x91,0x8f,0x8e,0x8c,\n\t\t0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x85,\n\t\t0x84,0x83,0x83,0x82,0x82,0x82,0x82,0x82,\n\n\t\t0x82,0x82,0x82,0x82,0x82,0x82,0x83,0x83,\n\t\t0x84,0x85,0x85,0x86,0x87,0x88,0x89,0x8a,\n\t\t0x8b,0x8c,0x8e,0x8f,0x90,0x92,0x94,0x95,\n\t\t0x97,0x99,0x9a,0x9c,0x9e,0xa0,0xa2,0xa5,\n\t\t0xa7,0xa9,0xab,0xae,0xb0,0xb2,0xb5,0xb7,\n\t\t0xba,0xbd,0xbf,0xc2,0xc5,0xc7,0xca,0xcd,\n\t\t0xd0,0xd3,0xd6,0xd9,0xdc,0xdf,0xe2,0xe5,\n\t\t0xe8,0xeb,0xee,0xf1,0xf4,0xf7,0xfa,0xfd,\n\n\t\t0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x15,\n\t\t0x18,0x1b,0x1e,0x21,0x24,0x27,0x2a,0x2d,\n\t\t0x30,0x33,0x36,0x39,0x3b,0x3e,0x41,0x43,\n\t\t0x46,0x49,0x4b,0x4e,0x50,0x52,0x55,0x57,\n\t\t0x59,0x5b,0x5e,0x60,0x62,0x64,0x65,0x67,\n\t\t0x69,0x6b,0x6c,0x6e,0x6f,0x71,0x72,0x74,\n\t\t0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7b,\n\t\t0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7e,0x7e,\n\t};\n\tdistance = distance;\t\t// Keep LINT quiet.\n\n#ifdef OBSOLETE\n\t/*\n\t**\tCalculate and add in the X component of the move.\n\t*/\n\t_AX = CosTable[dir];\n\tasm imul word ptr distance\n\tasm shl ax,1\n\tasm rcl dx,1\n\tasm mov al,ah\n\tasm mov ah,dl\n\t_DX = _AX;\n\tx += _DX;\n#else\n\tx += calcx(CosTable[dir], distance);\n#endif\n//\tasm add [word ptr start],ax\n\n#ifdef OBSOLETE\n\t/*\n\t**\tCalculate and add in the Y component of the move.\n\t*/\n\t_AX = SinTable[dir];\n\tasm imul word ptr distance\n\tasm shl ax,1\n\tasm rcl dx,1\n\tasm mov al,ah\n\tasm mov ah,dl\n\tasm neg ax\t\t\t\t// Subtraction needed because of inverted sine table.\n\t_DX = _AX;\n\ty += _DX;\n#else\n\ty += calcy(SinTable[dir], distance);\n#endif\n//\tasm add [word ptr start+2],ax\n\n}\n\n\n/***********************************************************************************************\n * Normal_Move_Point -- Moves point with tilt compensation.                                    *\n *                                                                                             *\n *    This routine will move the point in the direction and distance specified but it will     *\n *    take into account the tilt of the playing field. Typical use of this routine is to       *\n *    determine positioning as it relates to the playfield. Turrets are a good example of      *\n *    this.                                                                                    *\n *                                                                                             *\n * INPUT:   x,y   -- References to the coordinates to adjust.                                  *\n *                                                                                             *\n *          dir   -- The direction of the desired movement.                                    *\n *                                                                                             *\n *          distance -- The distance (in coordinate units) to move the point.                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\n// Loss of precision in initializations (8 bits to 7 bits) warning. Hmmm.. can this be fixed?\n//lint -e569\nvoid Normal_Move_Point(short &x, short &y, register DirType dir, unsigned short distance)\n{\n\tstatic signed char const CosTable[256] = {\n\t\t0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x15,\n\t\t0x18,0x1b,0x1e,0x21,0x24,0x27,0x2a,0x2d,\n\t\t0x30,0x33,0x36,0x39,0x3b,0x3e,0x41,0x43,\n\t\t0x46,0x49,0x4b,0x4e,0x50,0x52,0x55,0x57,\n\t\t0x59,0x5b,0x5e,0x60,0x62,0x64,0x65,0x67,\n\t\t0x69,0x6b,0x6c,0x6e,0x6f,0x71,0x72,0x74,\n\t\t0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7b,\n\t\t0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7e,0x7e,\n\n\t\t0x7f,0x7e,0x7e,0x7e,0x7e,0x7e,0x7d,0x7d,\n\t\t0x7c,0x7b,0x7b,0x7a,0x79,0x78,0x77,0x76,\n\t\t0x75,0x74,0x72,0x71,0x70,0x6e,0x6c,0x6b,\n\t\t0x69,0x67,0x66,0x64,0x62,0x60,0x5e,0x5b,\n\t\t0x59,0x57,0x55,0x52,0x50,0x4e,0x4b,0x49,\n\t\t0x46,0x43,0x41,0x3e,0x3b,0x39,0x36,0x33,\n\t\t0x30,0x2d,0x2a,0x27,0x24,0x21,0x1e,0x1b,\n\t\t0x18,0x15,0x12,0x0f,0x0c,0x09,0x06,0x03,\n\n\t\t0x00,0xfd,0xfa,0xf7,0xf4,0xf1,0xee,0xeb,\n\t\t0xe8,0xe5,0xe2,0xdf,0xdc,0xd9,0xd6,0xd3,\n\t\t0xd0,0xcd,0xca,0xc7,0xc5,0xc2,0xbf,0xbd,\n\t\t0xba,0xb7,0xb5,0xb2,0xb0,0xae,0xab,0xa9,\n\t\t0xa7,0xa5,0xa2,0xa0,0x9e,0x9c,0x9a,0x99,\n\t\t0x97,0x95,0x94,0x92,0x91,0x8f,0x8e,0x8c,\n\t\t0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x85,\n\t\t0x84,0x83,0x83,0x82,0x82,0x82,0x82,0x82,\n\n\t\t0x82,0x82,0x82,0x82,0x82,0x82,0x83,0x83,\n\t\t0x84,0x85,0x85,0x86,0x87,0x88,0x89,0x8a,\n\t\t0x8b,0x8c,0x8e,0x8f,0x90,0x92,0x94,0x95,\n\t\t0x97,0x99,0x9a,0x9c,0x9e,0xa0,0xa2,0xa5,\n\t\t0xa7,0xa9,0xab,0xae,0xb0,0xb2,0xb5,0xb7,\n\t\t0xba,0xbd,0xbf,0xc2,0xc5,0xc7,0xca,0xcd,\n\t\t0xd0,0xd3,0xd6,0xd9,0xdc,0xdf,0xe2,0xe5,\n\t\t0xe8,0xeb,0xee,0xf1,0xf4,0xf7,0xfa,0xfd,\n\t};\n\n\tstatic signed char const SinTable[256] = {\n\t\t0x7f,0x7e,0x7e,0x7e,0x7e,0x7e,0x7d,0x7d,\n\t\t0x7c,0x7b,0x7b,0x7a,0x79,0x78,0x77,0x76,\n\t\t0x75,0x74,0x72,0x71,0x70,0x6e,0x6c,0x6b,\n\t\t0x69,0x67,0x66,0x64,0x62,0x60,0x5e,0x5b,\n\t\t0x59,0x57,0x55,0x52,0x50,0x4e,0x4b,0x49,\n\t\t0x46,0x43,0x41,0x3e,0x3b,0x39,0x36,0x33,\n\t\t0x30,0x2d,0x2a,0x27,0x24,0x21,0x1e,0x1b,\n\t\t0x18,0x15,0x12,0x0f,0x0c,0x09,0x06,0x03,\n\n\t\t0x00,0xfd,0xfa,0xf7,0xf4,0xf1,0xee,0xeb,\n\t\t0xe8,0xe5,0xe2,0xdf,0xdc,0xd9,0xd6,0xd3,\n\t\t0xd0,0xcd,0xca,0xc7,0xc5,0xc2,0xbf,0xbd,\n\t\t0xba,0xb7,0xb5,0xb2,0xb0,0xae,0xab,0xa9,\n\t\t0xa7,0xa5,0xa2,0xa0,0x9e,0x9c,0x9a,0x99,\n\t\t0x97,0x95,0x94,0x92,0x91,0x8f,0x8e,0x8c,\n\t\t0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x85,\n\t\t0x84,0x83,0x83,0x82,0x82,0x82,0x82,0x82,\n\n\t\t0x82,0x82,0x82,0x82,0x82,0x82,0x83,0x83,\n\t\t0x84,0x85,0x85,0x86,0x87,0x88,0x89,0x8a,\n\t\t0x8b,0x8c,0x8e,0x8f,0x90,0x92,0x94,0x95,\n\t\t0x97,0x99,0x9a,0x9c,0x9e,0xa0,0xa2,0xa5,\n\t\t0xa7,0xa9,0xab,0xae,0xb0,0xb2,0xb5,0xb7,\n\t\t0xba,0xbd,0xbf,0xc2,0xc5,0xc7,0xca,0xcd,\n\t\t0xd0,0xd3,0xd6,0xd9,0xdc,0xdf,0xe2,0xe5,\n\t\t0xe8,0xeb,0xee,0xf1,0xf4,0xf7,0xfa,0xfd,\n\n\t\t0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x15,\n\t\t0x18,0x1b,0x1e,0x21,0x24,0x27,0x2a,0x2d,\n\t\t0x30,0x33,0x36,0x39,0x3b,0x3e,0x41,0x43,\n\t\t0x46,0x49,0x4b,0x4e,0x50,0x52,0x55,0x57,\n\t\t0x59,0x5b,0x5e,0x60,0x62,0x64,0x65,0x67,\n\t\t0x69,0x6b,0x6c,0x6e,0x6f,0x71,0x72,0x74,\n\t\t0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7b,\n\t\t0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7e,0x7e,\n\t};\n\tdistance = distance;\t\t// Keep LINT quiet.\n\n\tx += calcx(CosTable[dir], distance);\n\n\ty += calcy(SinTable[dir] / 2, distance);\n}\n"
  },
  {
    "path": "CODE/COORDA.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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  I N C  **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : COORDA.ASM                               *\n;*                                                                         *\n;*                   Programmer : Barry W. Green                           *\n;*                                                                         *\n;*                   Start Date : February 17, 1995                        *\n;*                                                                         *\n;*                  Last Update : February 17, 1995  [BWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Cardinal_To_Fixed -- Converts cardinal numbers into a fixed point number.                 *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\tCardinal_To_Fixed\t:NEAR\nGLOBAL\tFixed_To_Cardinal\t:NEAR\n\n\tCODESEG\n\n;***********************************************************************************************\n;* Cardinal_To_Fixed -- Converts cardinal numbers into a fixed point number.                   *\n;*                                                                                             *\n;*    This utility function will convert cardinal numbers into a fixed point fraction. The     *\n;*    use of fixed point numbers occurs throughout the product -- since it is a convenient     *\n;*    tool. The fixed point number is based on the formula:                                    *\n;*                                                                                             *\n;*       result = cardinal / base                                                              *\n;*                                                                                             *\n;*    The accuracy of the fixed point number is limited to 1/256 as the lowest and up to       *\n;*    256 as the largest.                                                                      *\n;*                                                                                             *\n;* INPUT:   base     -- The key number to base the fraction about.                             *\n;*                                                                                             *\n;*          cardinal -- The other number (hey -- what do you call it?)                         *\n;*                                                                                             *\n;* OUTPUT:  Returns with the fixed point number of the \"cardinal\" parameter as it relates      *\n;*          to the \"base\" parameter.                                                           *\n;*                                                                                             *\n;* WARNINGS:   none                                                                            *\n;*                                                                                             *\n;* HISTORY:                                                                                    *\n;*   02/17/1995 BWG : Created.                                                                 *\n;*=============================================================================================*/\n;unsigned int Cardinal_To_Fixed(unsigned base, unsigned cardinal);\n\n\tPROC\tCardinal_To_Fixed C near\n\tUSES\tebx, edx\n\n\tARG\tbase:DWORD\n\tARG\tcardinal:DWORD\n\n\tmov\teax,0FFFFh\t\t; establish default return value\n\n\tmov\tebx,[base]\n\tor\tebx,ebx\n\tjz\tnear ??retneg1\t\t; if base==0, return 65535\n\n\tmov\teax,[cardinal]\t\t; otherwise, return (cardinal*256)/base\n\tshl\teax,8\n\txor\tedx,edx\n\tdiv\tebx\n\t\n??retneg1:\n\tret\n\n\tENDP\tCardinal_To_Fixed\n\n\n;***********************************************************************************************\n;* Fixed_To_Cardinal -- Converts a fixed point number into a cardinal number.                  *\n;*                                                                                             *\n;*    Use this routine to convert a fixed point number into a cardinal number.                 *\n;*                                                                                             *\n;* INPUT:   base     -- The base number that the original fixed point number was created from. *\n;*                                                                                             *\n;*          fixed    -- The fixed point number to convert.                                     *\n;*                                                                                             *\n;* OUTPUT:  Returns with the reconverted number.                                               *\n;*                                                                                             *\n;* WARNINGS:   none                                                                            *\n;*                                                                                             *\n;* HISTORY:                                                                                    *\n;*   02/17/1995 BWG : Created.                                                                 *\n;*=============================================================================================*/\n;unsigned int Fixed_To_Cardinal(unsigned base, unsigned fixed);\n\tPROC\tFixed_To_Cardinal C near\n\tUSES\tedx\n\n\tARG\tbase:DWORD\n\tARG\tfixed:DWORD\n\n\tmov\teax,[base]\n\tmul\t[fixed]\n\tadd\teax,080h\t\t; eax = (base * fixed) + 0x80\n\n\ttest\teax,0FF000000h\t\t; if high byte set, return FFFF\n\tjnz\t??rneg1\n\tshr\teax,8\t\t\t; else, return eax/256\n\tret\n??rneg1\t:\n\tmov\teax,0FFFFh\t\t; establish default return value\n\tret\n\n\tENDP\tFixed_To_Cardinal\n\n\tEND\n"
  },
  {
    "path": "CODE/CPUID.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header:   F:\\projects\\c&c0\\vcs\\code\\cpuid.asv   5.0   11 Nov 1996 09:40:28   JOE_BOSTIC  $\n;***************************************************************************\n;**   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  I N C  **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : MMX.ASM                                  *\n;*                                                                         *\n;*                   Programmer : Steve Tall                               *\n;*                                                                         *\n;*                   Start Date : May 19th, 1996                           *\n;*                                                                         *\n;*                  Last Update : May 19th 1996 [ST]                       *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\n\t\t.586\n\t\t.model\tflat\n\n;\n; Variables externs\n;\nGLOBAL\tC CPUType:byte\n;externdef\tC CPUType:byte\nGLOBAL\tC VendorID:byte\n;externdef\tC VendorID:byte\n\n;\n; Function externs\n;\nGLOBAL\tC Detect_MMX_Availability:near\n;externdef\tC Detect_MMX_Availability:near\n\n\n\t\t.code\n\n\n;*********************************************************************************************\n;* Detect_MMX_Availability -- Detect the presence of MMX technology.                         *\n;*                                                                                           *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      True if MMX technology is available.                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*                                                                                           *\n;* Note: Based in part on CPUID32.ASM by Intel                                               *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   05/19/96 ST : Created.                                                                  *\n;*===========================================================================================*\n\nDetect_MMX_Availability proc C\n\n\t\tlocal\tidflag:byte\n\t\tlocal\tcputype:byte\n\n;assume processor is at least 386\n;\n;check whether AC bit in eflags can be toggled.\n;If not then processor is 386\n\n\t\tmov\t[idflag],0\n\n\t\tpushfd\t\t\t;get Eflags in EAX\n\t\tpop\teax\n\t\tmov\tecx,eax\t\t;save eflags\n\t\txor\teax,40000h\t;toggle AC bit in eflags\n\t\tpush\teax\t\t;new eflags on stack\n\t\tpopfd\t\t\t;move new value into eflags\n\t\tpushfd\t\t\t;get new eflags back into eax\n\t\tpop\teax\n\t\txor\teax,ecx\t\t;if AC bit not toggled then CPU=386\n\t\tmov\t[cputype],3\n\t\tjz\t@@end_get_cpu\t;cpu is 386\n\n\t\tpush\tecx\n\t\tpopfd\t\t\t;restore AC bit in eflags\n\n\n;processor is at least 486\n;\n;Check for ability to set/clear ID flag in EFLAGS\n;ID flag indicates ability of processor to execute the CPUID instruction.\n;486 not guaranteed to have CPUID inst?\n;\n\t\tmov\t[cputype],4\n\t\tmov\teax,ecx\t\t;original EFLAGS\n\t\txor\teax,200000h\t;toggle ID bit\n\t\tpush\teax\n\t\tpopfd\n\t\tpushfd\n\t\tpop\teax\n\t\txor\teax,ecx\t\t;check if still toggled\n\t\tjz\t@@end_get_cpu\n\n\n;       Execute CPUID instruction to determine vendor, family,\n;       model and stepping.\n;\n\n\t\tmov\t[idflag],1\t;flag ID is available\n\n\t\txor\teax,eax\n\t\tcpuid\n\n\t\tmov\tdword ptr [VendorID],ebx\n\t\tmov\tdword ptr [VendorID+4],edx\n\t\tmov\tdword ptr [VendorID+8],ecx\n\t\tmov\tdword ptr [VendorID+12],\" \"\n\n\t\tcmp\teax,1\t\t;check if 1 is valid\n\t\tjl\t@@end_get_cpu\t;inp for cpuid inst.\n\n\t\txor\teax,eax\n\t\tinc\teax\n\n\t\tcpuid\t\t;get stepping, model and family\n\n\t\tand     ax,0f00H\n\t\tshr     ax,08H\n\n\t\tmov\t[cputype],al\n\n@@end_get_cpu:\tmov\tal,[cputype]\n\t\tmov\t[CPUType],al\n\n\n;\n; We have the CPU type in al now.\n; If we arent on at least a pentium then we can assume there is no MMX\n;\n\t\tcmp\tal,5\n\t\tjl\t@@no_mmx\n\n\t\tmov\teax,1\n\t\tcpuid\n\t\ttest\tedx,00800000h\n\t\tjz\t@@no_mmx\n\n;\n; MMX detected - return true\n;\n\t\tmov\teax,1\n\t\tret\n\n\n@@no_mmx:\txor\teax,eax\n\t\tret\n\n\nDetect_MMX_Availability endp\n\n\n\t\t.data\n\nCPUType\t\tdb\t0\nVendorID\tdb\t\"Not available\",0,0,0,0,0,0\n\n\nend\n\n"
  },
  {
    "path": "CODE/CRATE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CRATE.CPP 3     3/04/97 3:12p Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CRATE.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 08/26/96                                                     *\n *                                                                                             *\n *                  Last Update : October 14, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CrateClass::Create_Crate -- Create a crate in the cell specified.                         *\n *   CrateClass::Get_Crate -- Pick up a crate from the cell specified.                         *\n *   CrateClass::Put_Crate -- Generates crate overlay at cell specified.                       *\n *   CrateClass::Remove_It -- Removes the crate from wherever it is.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * CrateClass::Remove_It -- Removes the crate from wherever it is.                             *\n *                                                                                             *\n *    This routine will remove the crate from whereever it happens to be.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the crate found and removed?                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CrateClass::Remove_It(void)\n{\n\tif (Is_Valid()) {\n\t\tGet_Crate(Cell);\n\t\tMake_Invalid();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CrateClass::Create_Crate -- Create a crate in the cell specified.                           *\n *                                                                                             *\n *    This will create a crate in the cell specified. If the crate could not be crated there   *\n *    then 'false' will be returned.                                                           *\n *                                                                                             *\n * INPUT:   cell  -- The desired cell to place the crate in.                                   *\n *                                                                                             *\n * OUTPUT:  bool; Was the crate created and placed in the cell?                                *\n *                                                                                             *\n * WARNINGS:   It is quite possible for the crate not to have been placed. Only the most clear *\n *             locations are valid for crate placement.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CrateClass::Create_Crate(CELL cell)\n{\n\t/*\n\t**\tRemove any existing crate that this crate class is tracking.\n\t*/\n\tRemove_It();\n\n\t/*\n\t**\tTry to place a new crate at the cell specified.\n\t*/\n\tif (Put_Crate(cell)) {\n\t\tCell = cell;\n\t\tTimer = Random_Pick(Rule.CrateTime * (TICKS_PER_MINUTE/2), Rule.CrateTime * (TICKS_PER_MINUTE*2));\n\t\tTimer.Start();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CrateClass::Put_Crate -- Generates crate overlay at cell specified.                         *\n *                                                                                             *\n *    This helpter routine will examine the cell and place the appropriate crate type into     *\n *    the cell specified. If the overlay could not be generated, then 'false' is returned.     *\n *                                                                                             *\n * INPUT:   cell  -- The cell to generate the crate overlay in.                                *\n *                                                                                             *\n * OUTPUT:  bool; Was the crate overlay generated?                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *   10/14/1996 JLB : Takes reference to cell so that tracking can occur.                      *\n *=============================================================================================*/\nbool CrateClass::Put_Crate(CELL & cell)\n{\n\tint old = ScenarioInit;\n\tScenarioInit = 0;\n\n\tif (Map.In_Radar(cell)) {\n\t\tCellClass * cellptr = &Map[cell];\n\n\t\twhile (cellptr->Overlay != OVERLAY_NONE && !cellptr->Is_Clear_To_Build(SPEED_FLOAT) && !cellptr->Is_Clear_To_Build(SPEED_FOOT)) {\n\t\t\tcell = Map.Pick_Random_Location();\n\n\t\t\tif (Percent_Chance(100 * Rule.WaterCrateChance)) {\n\t\t\t\tcell = Map.Nearby_Location(cell, SPEED_FLOAT);\n\t\t\t} else {\n\t\t\t\tcell = Map.Nearby_Location(cell, SPEED_TRACK);\n\t\t\t}\n\t\t\tcellptr = &Map[cell];\n\t\t}\n\n\t\tif (cellptr->Is_Clear_To_Build(SPEED_FLOAT)) {\n\t\t\tnew OverlayClass(OVERLAY_WATER_CRATE, cell);\n\t\t} else {\n\t\t\tnew OverlayClass(OVERLAY_WOOD_CRATE, cell);\n\t\t}\n\t\tScenarioInit = old;\n\t\treturn(true);\n\t}\n\n\tScenarioInit = old;\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CrateClass::Get_Crate -- Pick up a crate from the cell specified.                           *\n *                                                                                             *\n *    This will remove the crate from the cell specified.                                      *\n *                                                                                             *\n * INPUT:   cell  -- The cell to examine and remove any crate overlays present.                *\n *                                                                                             *\n * OUTPUT:  bool; Was a crate overlay found and removed?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CrateClass::Get_Crate(CELL cell)\n{\n\tif (Map.In_Radar(cell)) {\n\t\tCellClass * cellptr = &Map[cell];\n\n\t\tif (cellptr->Overlay == OVERLAY_WOOD_CRATE ||\n\t\t\tcellptr->Overlay == OVERLAY_STEEL_CRATE ||\n\t\t\tcellptr->Overlay == OVERLAY_WATER_CRATE) {\n\n\t\t\tcellptr->Overlay = OVERLAY_NONE;\n\t\t\tcellptr->OverlayData = 0;\n\t\t\tcellptr->Redraw_Objects();\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "CODE/CRATE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CRATE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CRATE.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 08/26/96                                                     *\n *                                                                                             *\n *                  Last Update : August 26, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CRATE_H\n#define CRATE_H\n\n#include\t\"ftimer.h\"\n#include\t\"jshell.h\"\n\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ comittee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\nclass CrateClass {\n\tpublic:\n\t\tCrateClass(void) : Timer(NoInitClass()), Cell(-1) {}\n\t\tvoid Init(void) {Make_Invalid();}\n\t\tbool Create_Crate(CELL cell);\n\t\tbool Is_Here(CELL cell) const {return(Is_Valid() && cell == Cell);}\n\t\tbool Remove_It(void);\n\t\tbool Is_Expired(void) const {return(Is_Valid() && Timer == 0);}\n\t\tbool Is_Valid(void) const {return(Cell != -1);}\n\n\tprivate:\n\t\tstatic bool Put_Crate(CELL & cell);\n\t\tstatic bool Get_Crate(CELL cell);\n\n\t\tvoid Make_Invalid(void) {Cell = -1;Timer.Stop();}\n\n\t\tCDTimerClass<FrameTimerClass> Timer;\n\t\tCELL Cell;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/CRC.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CRC.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CRC.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/02/96                                                     *\n *                                                                                             *\n *                  Last Update : March 2, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CRCEngine::operator() -- Submits one byte of data to the CRC engine.                      *\n *   CRCEngine::operator() -- Submits an arbitrary data block to the CRC engine.               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"crc.h\"\n\n\n/***********************************************************************************************\n * CRCEngine::operator() -- Submits one byte of data to the CRC engine.                        *\n *                                                                                             *\n *    This routine will take the specified byte of data and submit it to the CRC engine        *\n *    for processing. This routine is designed to be as fast as possible since the typical     *\n *    use of this routine is to feed one of presumably many byte sized chunks of data to the   *\n *    CRC engine.                                                                              *\n *                                                                                             *\n * INPUT:   datum -- One byte of data to submit to the CRC engine.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If possible, use the buffer/size operator to submit data rather than repeated   *\n *             calls to this routine.                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CRCEngine::operator() (char datum)\n{\n\tStagingBuffer.Buffer[Index++] = datum;\n\n\tif (Index == sizeof(long))  {\n\t\tCRC = Value();\n\t\tStagingBuffer.Composite = 0;\n\t\tIndex = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * CRCEngine::operator() -- Submits an arbitrary data block to the CRC engine.                 *\n *                                                                                             *\n *    This routine will submit the specified block to the CRC engine. The block can be of      *\n *    arbitrary length.                                                                        *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that contains the data. The buffer will not      *\n *                      be modified.                                                           *\n *                                                                                             *\n *          length   -- The length of the buffer (in bytes).                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the current CRC value accumulated so far.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CRCEngine::operator() (void const * buffer, int length)\n{\n\tif (buffer != NULL && length > 0)  {\n\t\tchar const * dataptr = (char const *)buffer;\n\t\tint bytes_left = length;\n\n\t\t/*\n\t\t**\tIf there are any leader bytes (needed to fill the staging buffer)\n\t\t**\tthen process those by first using them to fill up the staging\n\t\t**\tbuffer. The bulk of the data block will be processed by the high\n\t\t**\tspeed longword processing loop.\n\t\t*/\n\t\twhile (bytes_left && Buffer_Needs_Data()) {\n\t\t\toperator()(*dataptr);\n\t\t\tdataptr++;\n\t\t\tbytes_left--;\n\t\t}\n\n\t\t/*\n\t\t**\tPerform the fast 'bulk' processing by reading long word sized\n\t\t**\tdata blocks.\n\t\t*/\n\t\tlong const * longptr = (long const *)dataptr;\n\t\tint longcount = bytes_left / sizeof(long);\t\t// Whole 'long' elements remaining.\n\t\twhile (longcount--) {\n\t\t\tCRC = _lrotl(CRC, 1) + *longptr++;\n\t\t\tbytes_left -= sizeof(long);\n\t\t}\n\n\t\t/*\n\t\t**\tIf there are remainder bytes, then process these by adding them\n\t\t**\tto the staging buffer.\n\t\t*/\n\t\tdataptr = (char const *)longptr;\n\t\twhile (bytes_left) {\n\t\t\toperator()(*dataptr);\n\t\t\tdataptr++;\n\t\t\tbytes_left--;\n\t\t}\n\t}\n\n\t/*\n\t**\tReturn the current CRC value.\n\t*/\n\treturn(Value());\n}\n"
  },
  {
    "path": "CODE/CRC.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CRC.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CRC.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/02/96                                                     *\n *                                                                                             *\n *                  Last Update : March 2, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef CRC_H\n#define CRC_H\n\n#include\t<stdlib.h>\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ comittee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n/*\n**\tThis is a CRC engine class. It will process submitted data and generate a CRC from it.\n**\tWell, actually, the value returned is not a true CRC. However, it shares the same strength\n**\tcharacteristic and is faster to generate than the traditional CRC. This object is treated like\n**\ta method class. If it is called as a function (using the function operator), it will return\n**\tthe CRC value. There are other function operators to submit data for processing.\n*/\nclass CRCEngine {\n\tpublic:\n\n\t\t// Constructor for CRC engine (it can have an override initial CRC value).\n\t\tCRCEngine(long initial=0) : CRC(initial), Index(0) {\n\t\t\tStagingBuffer.Composite = 0;\n\t\t};\n\n\t\t// Fetches CRC value.\n\t\tlong operator() (void) const {return(Value());};\n\n\t\t// Submits one byte sized datum to the CRC accumulator.\n\t\tvoid operator() (char datum);\n\n\t\t// Submits an arbitrary buffer to the CRC accumulator.\n\t\tlong operator() (void const * buffer, int length);\n\n\t\t// Implicit conversion operator so this object appears like a 'long integer'.\n\t\toperator long(void) const {return(Value());};\n\n\tprotected:\n\n\t\tbool Buffer_Needs_Data(void) const {\n\t\t\treturn(Index != 0);\n\t\t};\n\n\t\tlong Value(void) const {\n\t\t\tif (Buffer_Needs_Data()) {\n\t\t\t\treturn(_lrotl(CRC, 1) + StagingBuffer.Composite);\n\t\t\t}\n\t\t\treturn(CRC);\n\t\t};\n\n\t\t/*\n\t\t**\tCurrent accumulator of the CRC value. This value doesn't take into\n\t\t**\tconsideration any pending data in the staging buffer.\n\t\t*/\n\t\tlong CRC;\n\n\t\t/*\n\t\t**\tThis is the sub index into the staging buffer used to keep track of\n\t\t**\tpartial data blocks as they are submitted to the CRC engine.\n\t\t*/\n\t\tint Index;\n\n\t\t/*\n\t\t**\tThis is the buffer that holds the incoming partial data. When the buffer\n\t\t**\tis filled, the value is transformed into the CRC and the buffer is flushed\n\t\t**\tin preparation for additional data.\n\t\t*/\n\t\tunion {\n\t\t\tlong Composite;\n\t\t\tchar Buffer[sizeof(long)];\n\t\t} StagingBuffer;\n};\n\n#endif\n\n"
  },
  {
    "path": "CODE/CRCPIPE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CRCPIPE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CRCPIPE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CRCPipe::Result -- Fetches the current CRC of the data.                                   *\n *   CRCPipe::Put -- Retrieves the data bytes specified and calculates CRC on it.              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"crcpipe.h\"\n\n\n/***********************************************************************************************\n * CRCPipe::Put -- Retrieves the data bytes specified and calculates CRC on it.                *\n *                                                                                             *\n *    This routine will fetch the number of bytes requested from the straw. The data is        *\n *    not modified by this straw segment, but it is examined by the CRC engine in order to     *\n *    keep an accurate CRC of the data that passes through this routine.                       *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer that will hold the data requested.               *\n *                                                                                             *\n *          length   -- The number of bytes requested.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes stored into the buffer. If this number is  *\n *          less than the number requested, then this indicates that the data stream has been  *\n *          exhausted.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CRCPipe::Put(void const * source, int slen)\n{\n\tCRC(source, slen);\n\treturn(Pipe::Put(source, slen));\n}\n\n\n/***********************************************************************************************\n * CRCPipe::Result -- Fetches the current CRC of the data.                                     *\n *                                                                                             *\n *    This routine will return the CRC of the data that has passed through the pipe up to      *\n *    this time.                                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the CRC value.                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CRCPipe::Result(void) const\n{\n\treturn(CRC());\n}\n\n"
  },
  {
    "path": "CODE/CRCPIPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CRCPIPE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CRCPIPE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef CRCPIPE_H\n#define CRCPIPE_H\n\n#include\t\"pipe.h\"\n#include\t\"crc.h\"\n\n/*\n**\tThis class doesn't modify the data being piped through, but it does examine it and build\n**\ta CRC value from the data.\n*/\nclass CRCPipe : public Pipe\n{\n\tpublic:\n\t\tCRCPipe(void) {}\n\t\tvirtual int Put(void const * source, int slen);\n\n\t\t// Fetch the CRC value.\n\t\tlong Result(void) const;\n\n\tprotected:\n\t\tCRCEngine CRC;\n\n\tprivate:\n\t\tCRCPipe(CRCPipe & rvalue);\n\t\tCRCPipe & operator = (CRCPipe const & pipe);\n};\n\n#endif\n"
  },
  {
    "path": "CODE/CRCSTRAW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CRCSTRAW.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CRCSTRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CRCStraw::Get -- Fetch the data requested and calculate CRC on it.                        *\n *   CRCStraw::Result -- Returns with the CRC of all data passed through the straw.            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"crcstraw.h\"\n\n\n/***********************************************************************************************\n * CRCStraw::Get -- Fetch the data requested and calculate CRC on it.                          *\n *                                                                                             *\n *    This routine will fetch the number of bytes requested. The data will not be modified     *\n *    by this straw segment, but the CRC engine will examine the data so as to keep an         *\n *    accurate CRC value.                                                                      *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer to hold the data requested.                      *\n *                                                                                             *\n *          length   -- The number of bytes requested.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes stored in the buffer. If this number is    *\n *          less than that requested, then this indicates that the data stream has been        *\n *          exhausted.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CRCStraw::Get(void * source, int slen)\n{\n\tif (source == NULL || slen < 1) {\n\t\treturn(0);\n\t}\n\n\tint counter = Straw::Get(source, slen);\n\tCRC(source, counter);\n\treturn(counter);\n}\n\n\n/***********************************************************************************************\n * CRCStraw::Result -- Returns with the CRC of all data passed through the straw.              *\n *                                                                                             *\n *    This routine will return the CRC value of the data that has passed through this straw    *\n *    segment.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the CRC value of the data this straw segment has seen.                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CRCStraw::Result(void) const\n{\n\treturn(CRC());\n}\n"
  },
  {
    "path": "CODE/CRCSTRAW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CRCSTRAW.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CRCSTRAW.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef CRCSTRAW_H\n#define CRCSTRAW_H\n\n#include \"straw.h\"\n#include \"crc.h\"\n\n/*\n**\tThis class will build a CRC value from the data stream that is drawn through this class.\n**\tThe data is not modified, but it is examined as it passes through.\n*/\nclass CRCStraw : public Straw\n{\n\tpublic:\n\t\tCRCStraw(void) {}\n\t\tvirtual int Get(void * source, int slen);\n\n\t\t// Calculate and return the CRC value.\n\t\tlong Result(void) const;\n\n\tprotected:\n\t\tCRCEngine CRC;\n\n\tprivate:\n\t\tCRCStraw(CRCStraw & rvalue);\n\t\tCRCStraw & operator = (CRCStraw const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/CREDITS.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CREDITS.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CREDITS.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 17, 1994                                               *\n *                                                                                             *\n *                  Last Update : March 13, 1995 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CreditClass::AI -- Handles updating the credit display.                                   *\n *   CreditClass::CreditClass -- Default constructor for the credit class object.              *\n *   CreditClass::Graphic_Logic -- Handles the credit redraw logic.                            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * CreditClass::CreditClass -- Default constructor for the credit class object.                *\n *                                                                                             *\n *    This is the constructor for the credit class object. It merely sets the credit display   *\n *    state to null.                                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCreditClass::CreditClass(void) :\n\tCredits(0),\n\tCurrent(0),\n\tIsToRedraw(false),\n\tIsUp(false),\n\tIsAudible(false),\n\tCountdown(0)\n{\n}\n\n\n/***********************************************************************************************\n * CreditClass::Graphic_Logic -- Handles the credit redraw logic.                              *\n *                                                                                             *\n *    This routine should be called whenever the main game screen is to be updated. It will    *\n *    check to see if the credit display should be redrawn. If so, it will redraw it.          *\n *                                                                                             *\n * INPUT:   forced   -- Should the credit display be redrawn regardless of whether the redraw  *\n *                      flag is set? This is typically the case when the screen needs to be    *\n *                      redrawn from scratch.                                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\n//#define\tXX (320-120)\n//#define\tWW\t50\nvoid CreditClass::Graphic_Logic(bool forced)\n{\n\tif (forced || IsToRedraw) {\n\t\tBStart(BENCH_TABS);\n\n\t\tint xx = SeenBuff.Get_Width() - (120 * RESFACTOR);\n\n\t\t/*\n\t\t** Adjust the credits display to be above the sidebar for 640x400\n\t\t*/\n#ifdef WIN32\n\t\txx += 80 * RESFACTOR;\n#endif\n\n\t\t/*\n\t\t**\tPlay a sound effect when the money display changes, but only if a sound\n\t\t**\teffect was requested.\n\t\t*/\n\t\tif (IsAudible) {\n\t\t\tif (IsUp) {\n\t\t\t\tSound_Effect(VOC_MONEY_UP, fixed(1, 2));\n\t\t\t} else  {\n\t\t\t\tSound_Effect(VOC_MONEY_DOWN, fixed(1, 2));\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tDisplay the new current value.\n\t\t*/\n\t\tTabClass::Draw_Credits_Tab();\n#ifdef WIN32\n\t\tFancy_Text_Print(\"%ld\", xx, 0, &MetalScheme, TBLACK, TPF_METAL12 | TPF_CENTER | TPF_USE_GRAD_PAL, Current);\n#else\n\t\tFancy_Text_Print(\"%ld\", xx, 0, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_NOSHADOW|TPF_6PT_GRAD|TPF_CENTER|TPF_BRIGHT_COLOR, Current);\n#endif\t//WIN32\n\n\t\tif (Scen.MissionTimer.Is_Active()) {\n\t\t\tlong secs = Scen.MissionTimer / TICKS_PER_SECOND;\n\t\t\tlong mins = secs / 60;\n\t\t\tlong hours = mins / 60;\n\t\t\tsecs %= 60;\n\t\t\tmins %= 60;\n\n\t\t\t/*\n\t\t\t**\tSpeak mission timer reminders.\n\t\t\t*/\n\t\t\tVoxType vox = VOX_NONE;\n\t\t\tif (Scen.MissionTimer == (1 * TICKS_PER_MINUTE)) vox = VOX_TIME_1;\n\t\t\tif (Scen.MissionTimer == (2 * TICKS_PER_MINUTE)) vox = VOX_TIME_2;\n\t\t\tif (Scen.MissionTimer == (3 * TICKS_PER_MINUTE)) vox = VOX_TIME_3;\n\t\t\tif (Scen.MissionTimer == (4 * TICKS_PER_MINUTE)) vox = VOX_TIME_4;\n\t\t\tif (Scen.MissionTimer == (5 * TICKS_PER_MINUTE)) vox = VOX_TIME_5;\n\t\t\tif (Scen.MissionTimer == (10 * TICKS_PER_MINUTE)) vox = VOX_TIME_10;\n\t\t\tif (Scen.MissionTimer == (20 * TICKS_PER_MINUTE)) vox = VOX_TIME_20;\n\t\t\tif (Scen.MissionTimer == (30 * TICKS_PER_MINUTE)) vox = VOX_TIME_30;\n\t\t\tif (Scen.MissionTimer == (40 * TICKS_PER_MINUTE)) vox = VOX_TIME_40;\n\t\t\tif (vox != VOX_NONE) {\n\t\t\t\tSpeak(vox);\n\t\t\t\tMap.FlasherTimer = 7;\n\t\t\t}\n\n#ifdef WIN32\n\t\t\tif (hours) {\n\t\t\t\tFancy_Text_Print(TXT_TIME_FORMAT_HOURS, 200 * RESFACTOR, 0, &MetalScheme, TBLACK, TPF_METAL12|TPF_CENTER|TPF_USE_GRAD_PAL, hours, mins, secs);\n\t\t\t} else {\n\t\t\t\tFancy_Text_Print(TXT_TIME_FORMAT_NO_HOURS, 200 * RESFACTOR, 0, &MetalScheme, TBLACK, TPF_METAL12|TPF_CENTER|TPF_USE_GRAD_PAL, mins, secs);\n\t\t\t}\n#else\n\t\t\tif (hours) {\n\t\t\t\tFancy_Text_Print(\"%02d:%02d:%02d\", 120 * RESFACTOR, 0, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_NOSHADOW|TPF_6PT_GRAD|TPF_CENTER|TPF_BRIGHT_COLOR, hours, mins, secs);\n\t\t\t} else {\n\t\t\t\tFancy_Text_Print(\"%02d:%02d\", 120 * RESFACTOR, 0, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_NOSHADOW|TPF_6PT_GRAD|TPF_CENTER|TPF_BRIGHT_COLOR, mins, secs);\n\t\t\t}\n#endif\t//WIN32\n\t\t}\n\n\t\tIsToRedraw = false;\n\t\tIsAudible = false;\n\t\tBEnd(BENCH_TABS);\n\t}\n}\n\n\n/***********************************************************************************************\n * CreditClass::AI -- Handles updating the credit display.                                     *\n *                                                                                             *\n *    This routine handles the logic that controls the rate of credit change in the credit     *\n *    display. It doesn't actually redraw the credit display, but will flag it to be redrawn   *\n *    if it detects that a change is to occur.                                                 *\n *                                                                                             *\n * INPUT:   forced   -- Should the credit display immediately reflect the current credit       *\n *                      total for the player? This is usually desired when initially loading   *\n *                      a scenario or saved game.                                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CreditClass::AI(bool forced)\n{\n\tstatic int _last = 0;\n\n\tif (!forced && Frame == _last) return;\n\t_last = Frame;\n\n\tCredits = PlayerPtr->Available_Money();\n\n\t/*\n\t**\tMake sure that the credit counter doesn't drop below zero.\n\t*/\n\tCredits = max(Credits, 0L);\n\n\tif (Scen.MissionTimer.Is_Active() || Scen.MissionTimer) {\n\t\tIsToRedraw = true;\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n\tif (Current == Credits) return;\n\n\tif (forced) {\n\t\tIsAudible = false;\n\t\tCurrent = Credits;\n\t} else {\n\n\t\tif (Countdown) Countdown--;\n\t\tif (Countdown) return;\n\n\t\t/*\n\t\t**\tDetermine the amount to change the display toward the\n\t\t**\tdesired value.\n\t\t*/\n\t\tint adder = Credits - Current;\n\n\t\tif (adder > 0) {\n\t\t\tCountdown = 1;\n\t\t} else {\n\t\t\tCountdown = 3;\n\t\t}\n\n\t\tadder = ABS(adder);\n\t\tadder >>= 3;\n//\t\tadder >>= 4;\n//\t\tadder >>= 5;\n\t\tadder = Bound(adder, 1, 71+72);\n\t\tif (Current > Credits) adder = -adder;\n\t\tCurrent += adder;\n\t\tif (Current-adder != Current) {\n\t\t\tIsAudible = true;\n\t\t\tIsUp = (adder > 0);\n\t\t}\n\t}\n\tIsToRedraw = true;\n\tMap.Flag_To_Redraw(false);\n}\n"
  },
  {
    "path": "CODE/CREDITS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CREDITS.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               *** \n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CREDIT.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 19, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 19, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CREDITS_H\n#define CREDITS_H\n\n/****************************************************************************\n**\tThe animating credit counter display is controlled by this class.\n*/\nclass CreditClass {\n\tpublic:\n\t\tlong Credits;\t\t// Value of credits trying to update display to.\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tCreditClass(void);\n\t\tCreditClass(NoInitClass const & ) {};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tvoid Update(bool forced=false, bool redraw=false);\n\n\t\tvoid Graphic_Logic(bool forced=false);\n\t\tvoid AI(bool forced=false);\n\n\t\tlong\tCurrent;\t\t// Credit value currently displayed.\n\n\t\tunsigned IsToRedraw:1;\n\t\tunsigned IsUp:1;\n\t\tunsigned IsAudible:1;\n\n\tprivate:\n\t\tint\tCountdown;\t// Delay between ticks.\n};\n\n#endif\n\n"
  },
  {
    "path": "CODE/CREW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CREW.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CREW.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 23, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n"
  },
  {
    "path": "CODE/CREW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CREW.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CREW.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 23, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CREW_H\n#define CREW_H\n\n\n/****************************************************************************\n**\tThis class handles the basic crew logic. This includes hero tracking,\n**\tcrew bail-out, and attached object logic.\n*/\nclass CrewClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis keeps track of the number of \"kills\" the unit as accumulated.\n\t\t**\tWhen it reaches a certain point, the unit improves.\n\t\t*/\n\t\tunsigned short Kills;\n\n\t\t/*\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tCrewClass(void) : Kills(0) {};\n\t\tCrewClass(NoInitClass const &) {};\n\t\t~CrewClass(void) {};\n\n\t\tint Made_A_Kill(void) {\n\t\t\tKills++;\n\t\t\treturn(Kills);\n\t\t};\n\n\tprivate:\n};\n\n#endif\n"
  },
  {
    "path": "CODE/CSTRAW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CSTRAW.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CSTRAW.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/10/96                                                     *\n *                                                                                             *\n *                  Last Update : November 10, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CacheStraw::Get -- Fetch data from the data source.                                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"cstraw.h\"\n#include\t<string.h>\n\n\n/***********************************************************************************************\n * CacheStraw::Get -- Fetch data from the data source.                                         *\n *                                                                                             *\n *    This will supply the data quantity requested. It performs a regulating influence on the  *\n *    data requests passed through it. The data is requested from the next straw in the        *\n *    chain such that the data stream is requested in chunks. This serves to lessen the        *\n *    impact of multiple small data requests.                                                  *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer to hold the data.                                *\n *                                                                                             *\n *          slen     -- The number of data bytes requested.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the number of data bytes stored into the buffer specified. If this    *\n *          number is less than that requested, it indicates that the data source has been     *\n *          exhausted.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CacheStraw::Get(void * source, int slen)\n{\n\tint total = 0;\n\n\tif (Is_Valid() && source != NULL && slen > 0) {\n\n\t\t/*\n\t\t**\tKeep processing the data request until there is no more data to supply or the request\n\t\t**\thas been fulfilled.\n\t\t*/\n\t\twhile (slen > 0) {\n\n\t\t\t/*\n\t\t\t**\tFirst try to fetch the data from data previously loaded into the buffer.\n\t\t\t*/\n\t\t\tif (Length > 0) {\n\t\t\t\tint tocopy = (Length < slen) ? Length : slen;\n\t\t\t\tmemmove(source, ((char *)BufferPtr.Get_Buffer()) + Index, tocopy);\n\t\t\t\tslen -= tocopy;\n\t\t\t\tIndex += tocopy;\n\t\t\t\ttotal += tocopy;\n\t\t\t\tLength -= tocopy;\n\t\t\t\tsource = (char*)source + tocopy;\n\t\t\t}\n\t\t\tif (slen == 0) break;\n\n\t\t\t/*\n\t\t\t**\tSince there is more to be fulfilled yet the holding buffer is empty,\n\t\t\t**\trefill the buffer with a fresh block of data from the source.\n\t\t\t*/\n\t\t\tLength = Straw::Get(BufferPtr, BufferPtr.Get_Size());\n\t\t\tIndex = 0;\n\t\t\tif (Length == 0) break;\n\t\t}\n\t}\n\treturn(total);\n}\n"
  },
  {
    "path": "CODE/CSTRAW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/CSTRAW.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CSTRAW.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/10/96                                                     *\n *                                                                                             *\n *                  Last Update : November 10, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef CSTRAW_H\n#define CSTRAW_H\n\n#include\t\"straw.h\"\n#include\t\"buff.h\"\n\n/*\n**\tThis class handles transfer of data by perform regulated requests for data from the next\n**\tclass in the chain. It performs no translation on the data. By using this segment in a\n**\tstraw chain, data throughput can be regulated. This can yield great performance increases\n**\twhen dealing with a file source.\n*/\nclass CacheStraw : public Straw\n{\n\tpublic:\n\t\tCacheStraw(Buffer const & buffer) : BufferPtr(buffer), Index(0), Length(0) {}\n\t\tCacheStraw(int length=4096) : BufferPtr(length), Index(0), Length(0) {}\n\t\tvirtual int Get(void * source, int slen);\n\n\tprivate:\n\t\tBuffer BufferPtr;\n\t\tint Index;\n\t\tint Length;\n\n\t\tbool Is_Valid(void) {return(BufferPtr.Is_Valid());}\n\t\tCacheStraw(CacheStraw & rvalue);\n\t\tCacheStraw & operator = (CacheStraw const & pipe);\n};\n\n\n\n#endif\n\n"
  },
  {
    "path": "CODE/CWSTUB.C",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <process.h>\n#include <errno.h>\n#include <string.h>\n\nchar *dos4g_path()\n{\n\tstatic char *paths_to_check[] = {\n\t\t\"DOS4GPATH\",\n\t\t\"PATH\"\n\t};\n\tstatic char fullpath[80];\n\tchar *dos4gpath;\n\tint i;\n\t\n\t/* If DOS4GPATH points to an executable file name, don't bother\n\t   searching any paths for DOS4GW.EXE.\n\t*/\n\tif (dos4gpath = getenv(\"DOS4GPATH\")) {\n\t \tstrlwr(strcpy(fullpath, dos4gpath));\n\t\tif (strstr(fullpath, \".exe\")) {\n\t\t\treturn(fullpath);\n\t\t}\n\t}\n\tfor( i = 0; i < sizeof(paths_to_check) / sizeof(paths_to_check[0]); i++ ) {\n\t\t_searchenv(\"dos4gw.exe\", paths_to_check[i], fullpath);\n\t\tif (fullpath[0]) {\n\t\t\treturn( &fullpath );\n\t\t}\n\t}\n\treturn(\"dos4gw.exe\");\n}\n\nmain( int argc, char *argv[] )\n{\n\tchar\t*av[4];\n\tauto char\tcmdline[128];\n\t\n\tav[0] = dos4g_path();\t\t/* Locate the DOS/4GW loader */\n\tav[1] = argv[0];\t\t\t/* name of executable to run */\n\tav[2] = getcmd(cmdline);\t/* command line */\n\tav[3] = NULL;\t\t\t\t/* end of list */\n#ifdef VMM\n\tputenv(\"DOS4GVM=MINMEM#2000 MAXMEM#16000 SWAPMIN#4096 SWAPINC#1024 VIRTUALSIZE#10000 SWAPFILE#CONQUER.SWP DELETESWAP @CONQUER.VMC\");\n#endif\n#ifdef QUIET\n\tputenv(\"DOS4G=QUIET\");\t/* disables DOS/4GW Copyright banner */\n#endif\n\texecvp(av[0], av);\n\tperror(av[0]);\n\texit(1);\t\t\t\t\t/* indicate error */\n}\n"
  },
  {
    "path": "CODE/DDE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Dynamic Data Encapsulation               *\n *                                                                         *\n *                    File Name : DDE.CPP\t\t                             *\n *                                                                         *\n *                   Programmer : Steve Wetherill                          *\n *                                                                         *\n *                   Start Date : June 1, 1996                             *\n *                                                                         *\n *                  Last Update : June 8, 1996 [SW]                        *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Instance_Class::InstanceClass -- class constructor                    *\n *   Instance_Class::InstanceClass -- class destructor                     *\n *   Instance_Class::Enable_Callback -- enables local processing of pokes  *\n *   Instance_Class::Register_Servers -- registers a local DDE DNS service *\n *   Instance_Class::Cleanup_App -- currently does nothing                 *\n *   Instance_Class::Test_Server_Running -- does a trial connect to remote *\n *\t  Instance_Class::Open_Poke_Connection -- pokes some data to server\t  *\n *   Instance_Class::Close_Poke_Connectionp -- closes connection to remote *\n *   Instance_Class::Poke_Server -- sends a chunk of data to remote        *\n *   Instance_Class::dde_callback -- processes DDE transactions            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifdef WIN32\n#include\t<windows.h>\n#include\t\"dde.h\"\n\n/***************************************************************************\n * These are static members of Instance_Class\n *=========================================================================*/\n\nstatic DWORD\tInstance_Class::id_inst;\t\t\t// instance identifier set by DdeInitialize\nstatic BOOL\t\tInstance_Class::process_pokes;\t// controls response to pokes\nstatic char \tInstance_Class::ascii_name[32];\t// name of server\n\nstatic BOOL CALLBACK\t(*Instance_Class::callback) (\n\t\t\tLPBYTE pointer,\t\t// pointer to received data\n\t\t\tlong\tlength\t\t\t// length of received data or advisory flag\n\t\t\t) = NULL;\n\n/***************************************************************************\n * Instance_Class::InstanceClass -- class constructor              \t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tname1\t\tnull terminated ASCII client name\t\t\t\t\t\t\t\t\t*\n *\t\tname1\t\tnull terminated ASCII server name\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tdde_error = TRUE if error occurs when initializing DDE\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n\nInstance_Class::Instance_Class( LPSTR name1, LPSTR name2 )\n{\n\n\tdde_error = FALSE;\t\t// no errors\n\tprocess_pokes = FALSE;\t// disable pokes in callback\n\n\tid_inst = 0;\t\t\t\t// set to 0 for first time through\n\tconv_handle = 0;   \t\t// conversation handle reset\n\n\tlstrcpy( ascii_name, name1 );\t// keep a record of ASCII name\n\n\tif\t( DdeInitialize(\n\t\t(LPDWORD) &id_inst,\t\t\t// instance identifier\n\t\tdde_callback,\n\t\tAPPCLASS_STANDARD | \t\t\t// filter server messages\n\t\tCBF_FAIL_SELFCONNECTIONS,\t// prevent from connecting with self\n\t\t0) != DMLERR_NO_ERROR) {   // reserved\n\t\t\tdde_error = TRUE;\t\t\t// flag an error\n\t}\n\n\tlocal_name = DdeCreateStringHandle(\n\t\tid_inst,         \t\t// instance identifier\n    \tname1,     \t\t\t\t// string to register\n    \tCP_WINANSI);    \t\t// Windows ANSI code page\n\n\tremote_name = DdeCreateStringHandle(\n\t\tid_inst,         \t\t// instance identifier\n    \tname2,     \t\t\t\t// string to register\n    \tCP_WINANSI);    \t\t// Windows ANSI code page\n\n\tpoke_topic = DdeCreateStringHandle(\n\t\tid_inst,         \t\t// instance identifier\n\t\t\"POKE TOPIC\", \t\t\t// System topic\n\t\tCP_WINANSI);    \t\t// Windows ANSI code page\n\n\tpoke_item = DdeCreateStringHandle(\n\t\tid_inst,         \t\t// instance identifier\n\t\t\"POKE ITEM\", \t\t\t// System topic\n\t\tCP_WINANSI);    \t\t// Windows ANSI code page\n\n\tsystem_topic = DdeCreateStringHandle(\n\t\tid_inst,         \t\t// instance identifier\n\t\tSZDDESYS_TOPIC, \t\t// System topic\n\t\tCP_WINANSI);    \t\t// Windows ANSI code page\n\n}\n\n/***************************************************************************\n * Instance_Class::~Instance_Class -- class destructor\t              \t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *    none.                                                                *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n\nInstance_Class::~Instance_Class()\n{\n\tDdeUninitialize( id_inst );\n}\n\n/***************************************************************************\n * Instance_Class::Enable_Callback -- enables user callback\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *    TRUE = enable poke processing\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *    FALSE = disable poke processing\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\techos the input\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tuser callback must be explicitly enabled. Disbabled by default.\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n\nBOOL\tInstance_Class::Enable_Callback( BOOL flag )\t\t// enable or disable callback\n{\n\treturn (process_pokes = flag);\n\n}\n\n/***************************************************************************\n * Instance_Class::Register_Server -- registers a local DDE DNS service    *\n *                                                                         *\n * INPUT:                                                                  *\n *    BOOL CALLBACK ( *callback_fnc) ( LPBYTE, DWORD) = user poke callbacl *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE == success\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tFALSE == failed\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n\nBOOL\tInstance_Class::Register_Server( BOOL CALLBACK ( *callback_fnc) (LPBYTE, long) )\n{\n\n\tif (DdeNameService( id_inst, local_name,\t0L, DNS_REGISTER ) != 0L) {\n\t\tcallback = callback_fnc;\n\t\treturn ( TRUE );\n\t} else {\n\t\treturn ( FALSE );\n\t}\n}\n\n/***************************************************************************\n * Instance_Class::Test_Server_Running -- does a trial connect to remote   *\n *                                                                         *\n * INPUT:                                                                  *\n *    name = HSZ string handle of server name.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE == successfully connected to remote\t\t\t\t\t\t\t\t\t\t*\n *\t\tFALSE == failed to connect\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\t- Can be called for local or remote server but of course will \t\t\t*\n *      fail if a called for local and local server is not \"up\".\t\t\t\t*\n *\t\t- Disconects before exiting.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n\nBOOL\tInstance_Class::Test_Server_Running( HSZ name )\n{\n\n\tif( Open_Poke_Connection( name ) == TRUE) {\n\t\tClose_Poke_Connection();\n\t\treturn( TRUE );\n\t} else {\n\t\treturn( FALSE );\n\t}\n}\n\n/***************************************************************************\n *\tInstance_Class::Open_Poke_Connection -- open a connection to server\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *    name = HSZ server name.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE == successfully opened connection\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tFALSE == failed to connect\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tCan be called for local or remote server but of course will \t\t\t*\n *    fail if a called for local and local server is not \"up\".\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n\nBOOL\tInstance_Class::Open_Poke_Connection( HSZ name )\n{\n\tconv_handle = DdeConnect(\n\t\tid_inst,           \t// instance identifier\n\t\tname,         \t\t\t// service name string handle\n\t\tpoke_topic,        \t// topic string handle\n\t\t(PCONVCONTEXT) NULL);// use default context\n\n\tif (conv_handle == NULL) {\n\t\treturn FALSE;\n\t} else {\n\t\treturn TRUE;\n\t}\n}\n\n/***************************************************************************\n *\tInstance_Class::Close_Poke_Connection -- closes poke connection\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *    none.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE == successfully closed connection\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tFALSE == failed to close connection for some reason\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n\nBOOL\tInstance_Class::Close_Poke_Connection( void )\n{\n\tif( conv_handle ) {\n\t\tHCONV\ttemp_handle = conv_handle;\n\t\tconv_handle = NULL;\n\t\treturn( DdeDisconnect( temp_handle ));\n\t} else {\n\t\treturn( TRUE );\n\t}\n}\n\n/***************************************************************************\n *\tInstance_Class::Poke_Server -- pokes some data to server\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *    poke_data\tpoints to data to send to remote\t\t\t\t\t\t\t\t\t*\n *    poke_length\tlength of buffer to send\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE == successfully poked the data\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tFALSE == failed to connect\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\thas a 3 second timeout (change POKE_TIMEOUT, in milliseconds)\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n\n#define\tPOKE_TIMEOUT\t60*1000\t      // 60 sec timeout\n\nBOOL\tInstance_Class::Poke_Server( LPBYTE poke_data, DWORD poke_length )\n{\n\n\tif( DdeClientTransaction(\n\n\t\tpoke_data,\t\t\t\t\t// address of data to pass to server\n\t  \tpoke_length,\t\t\t\t// length of data\n\t\tconv_handle,\t\t\t\t// handle of conversation\n\t\tpoke_topic,\t\t\t\t\t// handle of item name string\n\t\tCF_TEXT,\t\t\t\t\t\t// no special clipboard data format\n\t\tXTYP_POKE,\t\t\t\t\t// transaction type\n\t\tPOKE_TIMEOUT,\t\t\t\t\t\t\t// time-out duration (millisecs)\n\t\t(LPDWORD) NULL\t\t \t\t// address of transaction result (don't check)\n\t   ) == 0) {\n\n\t\treturn( FALSE);\n\t} else {\n\t\treturn( TRUE );\n\t}\n}\n\n/***************************************************************************\n *\tInstance_Class::dde_callback -- callback dde event handler\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tdde_event\ttransaction type\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tuFmt\t\t\tclipboard data format\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\thconv\t\t\thandle of the conversation\t\t\t\t\t\t\t\t\t\t\t*\n *\t\thsz1\t\t\thandle of a string\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\thsz2\t\t\thandle of a string\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\thdata\t\t\thandle of a global memory object\t\t\t\t\t\t\t\t\t*\n *\t\tdwData1\t\ttransaction-specific data\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tdwData2 \t\ttransaction-specific data\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tcontext specific HDDEDATA object\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t  \tNOTE: declared as HDDEDATA CALLBACK which means PASCAL parameters\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n\nHDDEDATA CALLBACK Instance_Class::dde_callback(\n\n\tUINT  dde_event,\t// transaction type\n\tUINT  uFmt,\t\t\t// clipboard data format\n\tHCONV  ,\t\t\t\t// handle of the conversation\n\tHSZ  hsz1,\t\t\t// handle of a string\n\tHSZ  hsz2,\t\t\t// handle of a string\n\tHDDEDATA  hdata,\t// handle of a global memory object\n\tDWORD  \t\t\t,\t// transaction-specific data\n\tDWORD  \t\t\t \t// transaction-specific data\n\t)\n{\n\n\n\tif (!Instance_Class::callback){\n\t\treturn (HDDEDATA) NULL;\n\t}\n\n\tswitch ( dde_event ) {\n\n\t\tcase XTYP_REGISTER:\n      case XTYP_UNREGISTER:\n\n\t\t\treturn (HDDEDATA) NULL;\n\n\t\tcase XTYP_ADVDATA:\n\t\t\treturn (HDDEDATA) DDE_FACK;\n\n\t\tcase XTYP_XACT_COMPLETE:\n\n\t\t\treturn (HDDEDATA) NULL;\n\n\t\tcase XTYP_DISCONNECT:\n\n\t\t\tInstance_Class::callback( NULL, DDE_ADVISE_DISCONNECT);\n\t\t\treturn (HDDEDATA) NULL;\n\n\t\tcase\tXTYP_CONNECT: {\n\n\t\t\tchar\tbuffer[32];\n\n\t\t\tDdeQueryString (Instance_Class::id_inst, hsz2, buffer, sizeof (buffer), 0) ;\n\n\t\t\tif (0 != strcmp (buffer, Instance_Class::ascii_name)) {\n\t\t\t\treturn (HDDEDATA) NULL;\n\t\t\t}\n\n\t\t\tDdeQueryString (Instance_Class::id_inst, hsz1, buffer, sizeof (buffer), 0) ;\n\n\t\t\tif (0 != strcmp (buffer, \"POKE TOPIC\")) {\n\t\t\t\treturn (HDDEDATA) NULL;\n\t\t\t}\n\n\t\t\tInstance_Class::callback( NULL, DDE_ADVISE_CONNECT);\n\t\t\treturn (HDDEDATA) TRUE;\n\t\t}\n\n\t\tcase\tXTYP_POKE:\n\n\t\t\tif\t(Instance_Class::process_pokes == FALSE ) {\n\t\t\t\treturn (HDDEDATA) DDE_FNOTPROCESSED;\t// processing disabled\n\t\t\t} else {\n\n\t\t\t\tchar\tbuffer[32];\n\n\t\t\t\tDdeQueryString (Instance_Class::id_inst, hsz1, buffer, sizeof (buffer), 0) ;\n\n\t\t\t\tif (0 != strcmp (buffer, \"POKE TOPIC\")) {\n\t\t\t\t\treturn (HDDEDATA) DDE_FNOTPROCESSED;\n\t\t\t\t} else if (uFmt == CF_TEXT) {\t\t\t\t\t// make sure it's CF_TEXT\n\n\t\t\t\t\tBOOL processed;\n\t\t\t\t\tBYTE FAR *pdata;\n\t\t\t\t\tDWORD dw_length;\n\n\t\t\t\t\tif ( (pdata = DdeAccessData( hdata, &dw_length)) == NULL ) {\n\t\t\t\t\t\treturn (HDDEDATA) DDE_FNOTPROCESSED;\n\t\t\t\t\t}\n\n\t\t\t\t\tprocessed = Instance_Class::callback((LPBYTE) pdata, dw_length);\n\n\t\t\t\t\tDdeUnaccessData( hdata );\n\n\t\t\t\t\tif (processed == TRUE) {\n\t\t\t\t\t\treturn (HDDEDATA) DDE_FACK;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn (HDDEDATA) NULL;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\tdefault:\n      \treturn (HDDEDATA) NULL;\n    }\n}\n\n#endif\t//WIN32\n"
  },
  {
    "path": "CODE/DDE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Dynamic Data Encapsulation\t\t\t\t\t*\n *                                                                         *\n *                    File Name : DDE.H\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : Steve Wetherill\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Start Date : June 1, 1996\t\t                        *\n *                                                                         *\n *                  Last Update : June 8, 1996   [SW]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This is the DDE (Instance_Class) which provides a simple CLIENT/SERVER\t*\n * DDE model for data transactions between Windows applications.\t\t\t\t*\n * This is a fairly naieve implementation allowing only one client/server\t*\n * per Instance_Class object. \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Typical uses for this class are:\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * i. Robust verification of whether an application is running\t\t\t\t\t*\n * ii. Data transfer between applications\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n/*\n***************************** Class defines *****************************\n*/\n\n#ifndef \t__DDE_H\n#define\t__DDE_H\n\n#define\tDDE_ADVISE_CONNECT\t\t-1\t\t// advisory \"client has connected\"\n#define\tDDE_ADVISE_DISCONNECT\t-2\t\t// advisory \"client has disconnected\"\n\n/*\n***************************** Class Declaration *****************************\n*/\n\nclass\tInstance_Class {\n\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\n\t\t/*.....................................................................\n\t\tConstructor:\n\t\t- takes null terminated ASCII strings names for client and server\n\t\t.....................................................................*/\n\n\t\tInstance_Class(\t\t// constructor\n\t\t\tLPSTR,\t\t\t\t// null terminated local sever name string\n\t\t\tLPSTR\t\t\t\t\t// null terminated remote server name string\n\t\t\t);\n\n\t\t/*.....................................................................\n\t\tDestructor:\n\t\t.....................................................................*/\n\t\t~Instance_Class(void);\t// the destructor\n\n\t\t/*.....................................................................\n\t\tSend data routine:\n\t\t- sends an unsolicited packet of data to the remote server\n\t\t.....................................................................*/\n\t\tBOOL\tPoke_Server( LPBYTE, DWORD);\n\n\t\t/*.....................................................................\n\t\tSend data routine:\n\t\t- sets up DNS for the server and registers a user callback to handle\n\t\t  incoming data\n\t\t.....................................................................*/\n\t\tBOOL\tRegister_Server( BOOL CALLBACK (*)(LPBYTE, long));\n\n\t\t/*.....................................................................\n\t\tDoes a trial connect to the remote server.\n\t\t- used to determine whether server is alive or not (and thus running)\n\t\t.....................................................................*/\n\t\tBOOL\tTest_Server_Running( HSZ );\n\n\t\t/*.....................................................................\n\t\tEnables user callback (disabled by default)\n\t\t.....................................................................*/\n\t\tBOOL\tEnable_Callback( BOOL );\t\t// enable or disable callback\n\n\t\t/*.....................................................................\n\t\tOpen a connection for sending data to remote server\n\t\t.....................................................................*/\n\t\tBOOL\tOpen_Poke_Connection( HSZ );\n\n\t\t/*.....................................................................\n\t\tClose connection with remote server\n\t\t.....................................................................*/\n\t\tBOOL\tClose_Poke_Connection( void );\n\n\t\t//\n\t\t// static members\n\t\t//\n\n\t\t/*.....................................................................\n\t\tUser callback - called upon receipt of incoming data (static member!)\n\t\t.....................................................................*/\n\t\tstatic BOOL CALLBACK\t(*callback) (\n\n\t\t\tLPBYTE pointer,\t\t// pointer to received data\n\t\t\tlong length\t\t\t\t// if >0 length of received data\n\t\t\t\t\t\t\t\t\t\t// if <0\n\t\t\t\t\t\t\t\t\t\t//\t-1 == client connect detected\n\t\t\t\t\t\t\t\t\t\t// -2 == client disconnect detected\n\t\t\t);\n\n\t\t/*.....................................................................\n\t\tDDE callback, called when DDEML has an event for us\n\t\t.....................................................................*/\n\t\tstatic HDDEDATA CALLBACK dde_callback(\n\n\t\t\tUINT  uType,\t\t// transaction type\n\t\t\tUINT  uFmt,\t\t\t// clipboard data format\n\t\t\tHCONV  hconv,\t\t// handle of the conversation\n\t\t\tHSZ  hsz1,\t\t\t// handle of a string\n\t\t\tHSZ  hsz2,\t\t\t// handle of a string\n\t\t\tHDDEDATA  hdata,\t// handle of a global memory object\n\t\t\tDWORD  dwData1,\t// transaction-specific data\n\t\t\tDWORD  dwData2 \t// transaction-specific data\n\t\t\t);\n\t\tHANDLE\tinstance;\t// this application's instance\n\t\tHWND\t\thwnd;\t\t\t// valid window handle\n\n\t\t/*.....................................................................\n\t\tmember variables\n\t\t.....................................................................*/\n\n\t\tstatic DWORD id_inst;\t\t\t// instance identifier set by DdeInitialize\n\t\tstatic BOOL\tprocess_pokes;\t\t// controls response to pokes\n\t\tstatic char ascii_name[32];\t// name of server\n\n\t\t//\n\t\t// non-static member variables\n\t\t//\n\n\t\tHSZ remote_name; \t\t// string handle for remote server name\n\t\tHSZ local_name; \t\t// string handle for local server name\n\t\tHSZ system_topic;\t\t// string handle for the \"system\" topic\n\t\tHSZ poke_topic;\t\t// string handle for poking data to server topic\n\t\tHSZ poke_item;\t\t\t// string handle for poking data to server item\n\n\t\tHCONV conv_handle;   // conversation handle\n\t\tBOOL\tdde_error;\t\t// error flag\n\n};\n\n#endif\n\n\u001a"
  },
  {
    "path": "CODE/DEBUG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/DEBUG.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DEBUG.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : July 18, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Self_Regulate -- Regulates the logic timer to result in smooth animation.                 *\n *   Debug_Key -- Debug mode keyboard processing.                                              *\n *   Bench_Time -- Convert benchmark timer into descriptive string.                            *\n *   Benchmarks -- Display the performance tracking benchmarks.                                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include \"vortex.h\"\n#include\t<stdarg.h>\n\n\n#ifdef CHEAT_KEYS\n\n\nstatic CDTimerClass<SystemTimerClass> DebugTimer;\n\nint VortexFrame = -1;\n\n/***********************************************************************************************\n * Debug_Key -- Debug mode keyboard processing.                                                *\n *                                                                                             *\n *    If debugging is enabled, then this routine will be called for every keystroke that the   *\n *    game doesn't recognize. These extra keys usually perform some debugging function.        *\n *                                                                                             *\n * INPUT:   input -- The key code that was pressed.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Debug_Key(unsigned input)\n{\n\tstatic int map_x = -1;\n\tstatic int map_y = -1;\n\tstatic int map_width = -1;\n\tstatic int map_height = -1;\n\n\tif (!input || input & KN_BUTTON) return;\n\n\t/*\n\t**\tProcessing of normal keystrokes.\n\t*/\n\tif (Debug_Flag) {\n\n\t\tswitch (input) {\n\n\t\t\tcase KN_BACKSPACE:\n\n\t\t\t\tif (ChronalVortex.Is_Active()) {\n\t\t\t\t\tChronalVortex.Disappear();\n\t\t\t\t} else {\n\t\t\t\t\tint xxxx = Get_Mouse_X() + Map.TacPixelX;\n\t\t\t\t\tint yyyy = Get_Mouse_Y() + Map.TacPixelY;\n\t\t\t\t\tCELL cell = Map.DisplayClass::Click_Cell_Calc(xxxx,yyyy);\n\t\t\t\t\tChronalVortex.Appear ( Cell_Coord (cell) );\n\t\t\t\t}\n\t\t\t\tbreak;\n\n#ifdef WIN32\n\t\t\tcase KN_J:\n\t\t\t\tDebug_MotionCapture = true;\n\t\t\t\tbreak;\n\n#ifdef OBSOLETE\n\t\t\tcase KN_K:\n\t\t\t\t/*\n\t\t\t\t** time to create a screen shot using the PCX code (if it works)\n\t\t\t\t*/\n\t\t\t\tif (!Debug_MotionCapture) {\n\t\t\t\t\tGraphicBufferClass temp_page(\tSeenBuff.Get_Width(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Height(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Width() * SeenBuff.Get_Height());\n\t\t\t\t\tCDFileClass file;\n\t\t\t\t\tchar filename[30];\n\n\t\t\t\t\tSeenBuff.Blit(temp_page);\n\t\t\t\t\tfor (int lp = 0; lp < 99; lp ++) {\n\t\t\t\t\t\tsprintf(filename, \"scrsht%02d.pcx\", lp);\n\t\t\t\t\t\tfile.Set_Name(filename);\n\t\t\t\t\t\tif (!file.Is_Available()) break;\n\t\t\t\t\t}\n\n\t\t\t\t\tfile.Cache(200000);\n\t\t\t\t\tWrite_PCX_File(file, temp_page, & GamePalette);\n\t\t\t\t\tSound_Effect(VOC_BEEP);\n\t\t\t\t}\n\t\t\t\tbreak;\n#endif\n#endif\n\n\t\t\tcase KN_P:\n\t\t\t\t{\n\t\t\t\t\tfor (SpecialWeaponType spc = SPC_FIRST; spc < SPC_COUNT; spc++) {\n\t\t\t\t\t\tPlayerPtr->SuperWeapon[spc].Enable(true, true);\n\t\t\t\t\t\tPlayerPtr->SuperWeapon[spc].Forced_Charge(true);\n\t\t\t\t\t\tMap.Add(RTTI_SPECIAL, spc);\n\t\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase KN_I:\n\t\t\t\t{\n\t\t\t\t\tMap.Flash_Power();\n\t\t\t\t\tMap.Flash_Money();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase KN_O:\n\t\t\t\t{\n\t\t\t\t\tAircraftClass * air = new AircraftClass(AIRCRAFT_HIND, PlayerPtr->Class->House);\n\t\t\t\t\tif (air) {\n\t\t\t\t\t\tair->Height = 0;\n\t\t\t\t\t\tair->Unlimbo(Map.Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y()), DIR_N);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase KN_B:\n\t\t\t\t{\n\t\t\t\t\tAircraftClass * air = new AircraftClass(AIRCRAFT_LONGBOW, PlayerPtr->Class->House);\n\t\t\t\t\tif (air) {\n\t\t\t\t\t\tair->Height = 0;\n\t\t\t\t\t\tair->Unlimbo(Map.Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y()), DIR_N);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase KN_GRAVE:\n\t\t\t\t{\n\t\t\t\t\tWarheadType warhead = Random_Pick(WARHEAD_HE, WARHEAD_FIRE);\n\t\t\t\t\tCOORDINATE coord = Map.Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y());\n\t\t\t\t\tint damage = 1000;\n\t\t\t\t\tnew AnimClass(Combat_Anim(damage, warhead, Map[coord].Land_Type()), coord);\n\t\t\t\t\tExplosion_Damage(coord, damage, NULL, warhead);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase KN_C:\n\t\t\t\tDebug_Cheat = (Debug_Cheat == false);\n\t\t\t\tPlayerPtr->IsRecalcNeeded = true;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis placement might affect any prerequisite requirements for construction\n\t\t\t\t**\tlists. Update the buildable options accordingly.\n\t\t\t\t*/\n\t\t\t\tif (!ScenarioInit) {\n\t\t\t\t\tMap.Recalc();\n\t\t\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\t\tBuildings.Ptr(index)->Update_Buildables();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (int)KN_Z|(int)KN_ALT_BIT:\n\t\t\t\tif (map_x == -1) {\n\t\t\t\t\tmap_x = Map.MapCellX;\n\t\t\t\t\tmap_y = Map.MapCellY;\n\t\t\t\t\tmap_width = Map.MapCellWidth;\n\t\t\t\t\tmap_height = Map.MapCellHeight;\n\t\t\t\t\tMap.MapCellX = 1;\n\t\t\t\t\tMap.MapCellY = 1;\n\t\t\t\t\tMap.MapCellWidth = MAP_CELL_W-2;\n\t\t\t\t\tMap.MapCellHeight = MAP_CELL_H-2;\n\t\t\t\t} else {\n\t\t\t\t\tMap.MapCellX = map_x;\n\t\t\t\t\tMap.MapCellY = map_y;\n\t\t\t\t\tMap.MapCellWidth = map_width;\n\t\t\t\t\tMap.MapCellHeight = map_height;\n\t\t\t\t\tmap_x = -1;\n\t\t\t\t\tmap_y = -1;\n\t\t\t\t\tmap_width = -1;\n\t\t\t\t\tmap_height = -1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase KN_M:\n\t\t\t\tif (Debug_Flag) {\n\t\t\t\t\tif (MonoClass::Is_Enabled()) {\n\t\t\t\t\t\tMonoClass::Disable();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMonoClass::Enable();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (int)KN_W|(int)KN_ALT_BIT:\n\t\t\t\tPlayerPtr->Flag_To_Win();\n\t\t\t\tbreak;\n\n\t\t\tcase (int)KN_L|(int)KN_ALT_BIT:\n\t\t\t\tPlayerPtr->Flag_To_Lose();\n\t\t\t\tbreak;\n\n\t\t\tcase KN_DELETE:\n\t\t\t\tif (CurrentObject.Count()) {\n\t\t\t\t\tMap.Recalc();\n\t\t\t\t\t//CurrentObject[0]->Detach_All();\n\t\t\t\t\tif (CurrentObject[0]->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\t((BuildingClass *)CurrentObject[0])->Sell_Back(1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tObjectClass * object = CurrentObject[0];\n\t\t\t\t\t\tobject->Unselect();\n\t\t\t\t\t\tobject->Limbo();\n\t\t\t\t\t\tdelete object;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (int)KN_DELETE|(int)KN_SHIFT_BIT:\n\t\t\t\tif (CurrentObject.Count()) {\n\t\t\t\t\tMap.Recalc();\n\t\t\t\t\tint damage = 50;\n\t\t\t\t\tCurrentObject[0]->Take_Damage(damage, 0, WARHEAD_SA);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase KN_INSERT:\n\t\t\t\tif (CurrentObject.Count()) {\n\t\t\t\t\tMap.PendingObject = &CurrentObject[0]->Class_Of();\n\t\t\t\t\tif (Map.PendingObject) {\n\t\t\t\t\t\tMap.PendingHouse = CurrentObject[0]->Owner();\n\t\t\t\t\t\tMap.PendingObjectPtr = Map.PendingObject->Create_One_Of(HouseClass::As_Pointer(Map.PendingHouse));\n\t\t\t\t\t\tif (Map.PendingObjectPtr) {\n\t\t\t\t\t\t\tMap.Set_Cursor_Pos();\n\t\t\t\t\t\t\tMap.Set_Cursor_Shape(Map.PendingObject->Occupy_List());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase KN_LBRACKET:\n\t\t\tcase KN_F11:\n\t\t\t\tif (MonoPage == DMONO_FIRST) {\n\t\t\t\t\tMonoPage = DMonoType(DMONO_COUNT-1);\n\t\t\t\t} else {\n\t\t\t\t\tMonoPage = DMonoType(MonoPage - 1);\n\t\t\t\t}\n\t\t\t\tDebugTimer = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase KN_RBRACKET:\n\t\t\tcase KN_F12:\n\t\t\t\tMonoPage = DMonoType(MonoPage + 1);\n\t\t\t\tif (MonoPage == DMONO_COUNT) {\n\t\t\t\t\tMonoPage = DMONO_FIRST;\n\t\t\t\t}\n\t\t\t\tDebugTimer = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase KN_V:\n\t\t\tcase KN_F3:\n\t\t\t\tDebug_Icon = (Debug_Icon == false);\n\t\t\t\tMap.Flag_To_Redraw(true);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tReveal entire map to player.\n\t\t\t*/\n//\t\t\tcase KN_F4:\n//\t\t\t\tif (Session.Type == GAME_NORMAL) {\n//\t\t\t\t\tDebug_Unshroud = (Debug_Unshroud == false);\n//\t\t\t\t\tMap.Flag_To_Redraw(true);\n//\t\t\t\t}\n//\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tShows sight and fire range in the form of circles emanating from the currently\n\t\t\t**\tselected unit. The white circle is for sight range, the red circle is for\n\t\t\t**\tfire range.\n\t\t\t*/\n\t\t\tcase KN_F7:\n\t\t\t\tif (CurrentObject.Count() && CurrentObject[0]->Is_Techno()) {\n\t\t\t\t\tTechnoTypeClass const & ttype = (TechnoTypeClass const &)CurrentObject[0]->Class_Of();\n\t\t\t\t\tint sight = ((int)ttype.SightRange)<<8;\n\t\t\t\t\tint weapon = 0;\n\t\t\t\t\tif (ttype.PrimaryWeapon != NULL) weapon = ttype.PrimaryWeapon->Range;\n\t\t\t\t\tSet_Logic_Page(SeenBuff);\n\t\t\t\t\tCOORDINATE center = CurrentObject[0]->Center_Coord();\n\t\t\t\t\tCOORDINATE center2 = CurrentObject[0]->Fire_Coord(0);\n\n\t\t\t\t\tfor (int r = 0; r < 255; r += 10) {\n\t\t\t\t\t\tint\tx,y,x1,y1;\n\t\t\t\t\t\tDirType r1 = (DirType)r;\n\t\t\t\t\t\tDirType r2 = (DirType)((r+10) & 0xFF);\n\n\t\t\t\t\t\tif (Map.Coord_To_Pixel(Coord_Move(center, r1, sight), x, y)) {\n\t\t\t\t\t\t\tMap.Coord_To_Pixel(Coord_Move(center, r2, sight), x1, y1);\n\t\t\t\t\t\t\tLogicPage->Draw_Line(x, y+8, x1, y1+8, WHITE);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Map.Coord_To_Pixel(Coord_Move(center2, r1, weapon), x, y)) {\n\t\t\t\t\t\t\tMap.Coord_To_Pixel(Coord_Move(center2, r2, weapon), x1, y1);\n\t\t\t\t\t\t\tLogicPage->Draw_Line(x, y+8, x1, y1+8, RED);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ((int)KN_F4 | (int)KN_CTRL_BIT):\n\t\t\t\tDebug_Unshroud = (Debug_Unshroud == false);\n\t\t\t\tMap.Flag_To_Redraw(true);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Bench_Time -- Convert benchmark timer into descriptive string.                              *\n *                                                                                             *\n *    This routine will take the values of the benchmark timer specified and build a string    *\n *    that displays the average time each event consumed as well as the ranking of how much    *\n *    time that event took (total) during the tracking duration (one second?).                 *\n *                                                                                             *\n * INPUT:   btype -- The benchmark to convert to a descriptive string.                         *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the descriptive string of the benchmark specified.       *\n *                                                                                             *\n * WARNINGS:   The value returned is a pointer to a static buffer. As such, it is only valid   *\n *             until the next time that this routine is called.                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic char const * Bench_Time(BenchType btype)\n{\n\tstatic char buffer[32];\n\n\tint rootcount = Benches[BENCH_GAME_FRAME].Count();\n\tif (rootcount == 0) rootcount = 1;\n\tint roottime = Benches[BENCH_GAME_FRAME].Value();\n\tint count = Benches[btype].Count();\n\tint time = Benches[btype].Value();\n\tif (count > 0 && count * time > roottime * rootcount) time = roottime / count;\n\tint percent = 0;\n\tif (roottime != 0 && rootcount != 0) {\n\t\tpercent = ((count * time) * 99) / (roottime * rootcount);\n\t}\n\tif (percent > 99) percent = 99;\n\tsprintf(buffer, \"%-2d%% %7d\", percent, time);\n\treturn(buffer);\n}\n\n\n/***********************************************************************************************\n * Benchmarks -- Display the performance tracking benchmarks.                                  *\n *                                                                                             *\n *    This will display the benchmarks for the various processes that are being tracked. The   *\n *    display will indicate the fraction that each process is consuming out of the entire      *\n *    process time as well as the time consumed by each individual event. The total fraction   *\n *    is useful for determing what should be optimized. The individual time is useful for      *\n *    guaging the effectiveness of optimization changes.                                       *\n *                                                                                             *\n * INPUT:   mono  -- Pointer to the monochrome screen that the display will use.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Benchmarks(MonoClass * mono)\n{\n\tstatic bool _first = true;\n\tif (_first) {\n\t\t_first = false;\n\t\tmono->Clear();\n\t\tmono->Set_Cursor(0, 0);\n\t\tmono->Print(Text_String(TXT_DEBUG_PERFORMANCE));\n\t\tif (Benches == NULL) {\n\t\t\tmono->Set_Cursor(20, 15);\n\t\t\tmono->Printf(TXT_NO_PENTIUM);\n\t\t}\n\t}\n\n\tif (Benches != NULL) {\n\t\tmono->Set_Cursor(1, 2);mono->Printf(\"%s\", Bench_Time(BENCH_FINDPATH));\n\t\tmono->Set_Cursor(1, 4);mono->Printf(\"%s\", Bench_Time(BENCH_GREATEST_THREAT));\n\t\tmono->Set_Cursor(1, 6);mono->Printf(\"%s\", Bench_Time(BENCH_AI));\n\t\tmono->Set_Cursor(1, 8);mono->Printf(\"%s\", Bench_Time(BENCH_PCP));\n\t\tmono->Set_Cursor(1, 10);mono->Printf(\"%s\", Bench_Time(BENCH_EVAL_OBJECT));\n\t\tmono->Set_Cursor(1, 12);mono->Printf(\"%s\", Bench_Time(BENCH_EVAL_CELL));\n\t\tmono->Set_Cursor(1, 14);mono->Printf(\"%s\", Bench_Time(BENCH_EVAL_WALL));\n\t\tmono->Set_Cursor(1, 16);mono->Printf(\"%s\", Bench_Time(BENCH_MISSION));\n\n\t\tmono->Set_Cursor(14, 2);mono->Printf(\"%s\", Bench_Time(BENCH_CELL));\n\t\tmono->Set_Cursor(14, 4);mono->Printf(\"%s\", Bench_Time(BENCH_OBJECTS));\n\t\tmono->Set_Cursor(14, 6);mono->Printf(\"%s\", Bench_Time(BENCH_ANIMS));\n\n\t\tmono->Set_Cursor(27, 2);mono->Printf(\"%s\", Bench_Time(BENCH_PALETTE));\n\n\t\tmono->Set_Cursor(40, 2);mono->Printf(\"%s\", Bench_Time(BENCH_GSCREEN_RENDER));\n\t\tmono->Set_Cursor(40, 4);mono->Printf(\"%s\", Bench_Time(BENCH_SIDEBAR));\n\t\tmono->Set_Cursor(40, 6);mono->Printf(\"%s\", Bench_Time(BENCH_RADAR));\n\t\tmono->Set_Cursor(40, 8);mono->Printf(\"%s\", Bench_Time(BENCH_TACTICAL));\n\t\tmono->Set_Cursor(40, 10);mono->Printf(\"%s\", Bench_Time(BENCH_POWER));\n\t\tmono->Set_Cursor(40, 12);mono->Printf(\"%s\", Bench_Time(BENCH_SHROUD));\n\t\tmono->Set_Cursor(40, 14);mono->Printf(\"%s\", Bench_Time(BENCH_TABS));\n\t\tmono->Set_Cursor(40, 16);mono->Printf(\"%s\", Bench_Time(BENCH_BLIT_DISPLAY));\n\n\t\tmono->Set_Cursor(66, 2);mono->Printf(\"%7d\", Benches[BENCH_RULES].Value());\n\t\tmono->Set_Cursor(66, 4);mono->Printf(\"%7d\", Benches[BENCH_SCENARIO].Value());\n\n\t\tfor (BenchType index = BENCH_FIRST; index < BENCH_COUNT; index++) {\n\t\t\tif (index != BENCH_RULES && index != BENCH_SCENARIO) Benches[index].Reset();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Self_Regulate -- Regulates the logic timer to result in smooth animation                    *\n *                                                                                             *\n *    The self regulation process checks the number of frames displayed                        *\n *    per second and from this determines the amount of time to devote                         *\n *    to internal logic processing. By adjusting the time allotted to                          *\n *    internal processing, smooth animation can be maintained.                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   In order for this routine to work properly it MUST be                           *\n *             called every display loop.                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/31/1991 JLB : Created.                                                                 *\n *   07/05/1994 JLB : Handles new monochrome system.                                           *\n *=============================================================================================*/\n#define\tUPDATE_INTERVAL\tTIMER_SECOND\nvoid Self_Regulate(void)\n{\n\tstatic ObjectClass * _lastobject = 0;\n\tstatic bool _first=true;\n\n\tif (DebugTimer == 0) {\n\t\tDebugTimer = UPDATE_INTERVAL;\n\n\t\tif (MonoClass::Is_Enabled()) {\n\t\t\tif (_first) {\n\t\t\t\t_first = false;\n\t\t\t\tfor (DMonoType index = DMONO_FIRST; index < DMONO_COUNT; index++) {\n\t\t\t\t\tMonoArray[index].Clear();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAlways update the stress tracking mono display even if it\n\t\t\t**\tcurrently isn't visible.\n\t\t\t*/\n\t\t\tLogic.Debug_Dump(&MonoArray[DMONO_STRESS]);\n\n\t\t\tMonoClass * mono = &MonoArray[MonoPage];\n\t\t\tmono->Set_Default_Attribute(MonoClass::NORMAL);\n\t\t\tmono->View();\n\n\t\t\tswitch (MonoPage) {\n\t\t\t\tcase DMONO_EVENTS:\n\t\t\t\t\tBenchmarks(mono);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase DMONO_OBJECT:\n\t\t\t\t\tmono->Clear();\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDisplay the status of the currently selected object.\n\t\t\t\t\t*/\n\t\t\t\t\tif (CurrentObject.Count()) {\n\t\t\t\t\t\t_lastobject = CurrentObject[0];\n\t\t\t\t\t}\n\t\t\t\t\tif (_lastobject && !_lastobject->IsActive) {\n\t\t\t\t\t\t_lastobject = 0;\n\t\t\t\t\t}\n\t\t\t\t\tif (_lastobject) {\n\t\t\t\t\t\t_lastobject->Debug_Dump(mono);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase DMONO_STRESS:\n#ifdef OBSOLETE\n\t\t\t\t\tmono->Set_Cursor(0, 20);\n\t\t\t\t\tmono->Printf(\n\t\t\t\t\t\t\"Heap size:%10ld \\r\"\n\t\t\t\t\t\t\"Largest:  %10ld \\r\"\n\t\t\t\t\t\t\"Ttl Free: %10ld \\r\"\n\t\t\t\t\t\t\"Frag:     %10ld \\r\",\n\t\t\t\t\t\tHeap_Size(MEM_NORMAL),\n\t\t\t\t\t\tRam_Free(MEM_NORMAL),\n\t\t\t\t\t\tTotal_Ram_Free(MEM_NORMAL),\n\t\t\t\t\t\tTotal_Ram_Free(MEM_NORMAL)-Ram_Free(MEM_NORMAL)\n\t\t\t\t\t);\n#endif\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase DMONO_HOUSE:\n\t\t\t\t\tmono->Clear();\n\n\t\t\t\t\tif (CurrentObject.Count()) {\n\t\t\t\t\t\t_lastobject = CurrentObject[0];\n\t\t\t\t\t}\n\t\t\t\t\tif (_lastobject && !_lastobject->IsActive) {\n\t\t\t\t\t\t_lastobject = 0;\n\t\t\t\t\t}\n\t\t\t\t\tif (_lastobject && _lastobject->Is_Techno()) {\n\t\t\t\t\t\t((TechnoClass *)_lastobject)->House->Debug_Dump(mono);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tmono->Set_Cursor(0, 0);\n\t\t}\n\t}\n}\n#endif\n"
  },
  {
    "path": "CODE/DEBUG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#define TXT_CLEAR_MAP            \t0x3e8 \t// Clear the map\n#define TXT_INHERIT_MAP          \t0x3e9 \t// Inherit previous map\n#define TXT_SPECIAL_OPTIONS      \t0x3ea \t// Select Special Options\n#define TXT_VISIBLE_TARGET       \t0x3eb \t// Targeting flash visible to\n#define TXT_TREE_TARGET          \t0x3ec \t// Allow targeting of trees.\n#define TXT_MCV_DEPLOY           \t0x3ed \t// Allow undeploy of\n#define TXT_SMART_DEFENCE        \t0x3ee \t// Employ smarter self defense\n#define TXT_SLOW_BUILD           \t0x3ef \t// Moderate production speed.\n#define TXT_THREE_POINT          \t0x3f0 \t// Use three point turn logic.\n#define TXT_TIBERIUM_GROWTH      \t0x3f1 \t// Ore will grow.\n#define TXT_TIBERIUM_SPREAD      \t0x3f2 \t// Ore will spread.\n#define TXT_ROAD_PIECES          \t0x3f3 \t// Disable building \"bib\"\n#define TXT_SCATTER              \t0x3f4 \t// Allow running from\n#define TXT_SHOW_NAMES           \t0x3f5 \t// Show true object names.\n#define TXT_DEFENDER_ADVANTAGE   \t0x3f6 \t// Defender has the advantage.\n#define TXT_SEPARATE_HELIPAD     \t0x3f7 \t// Allow separate helipad\n#define TXT_PASSWORD_CAPTION     \t0x3f8 \t// Password Request\n#define TXT_PASSWORD_MESSAGE     \t0x3f9 \t// Enter Red Alert access code\n#define TXT_PASSWORD_ERROR       \t0x3fa \t// Access code error detected.\n#define TXT_TRY_AGAIN            \t0x3fb \t// Try Again\n#define TXT_MINE_AWARE           \t0x3fc \t// Friendly units avoid\n#define TXT_TRIGGER_EDITOR       \t0x3fd \t// Trigger Editor\n#define TXT_TRIGGER_JUST_EVENT   \t0x3fe \t// Just This Event\n#define TXT_TRIGGER_AND          \t0x3ff \t// ... and ...\n#define TXT_TRIGGER_OR           \t0x400 \t// ... or ...\n#define TXT_TRIGGER_LINKED       \t0x401 \t// ... linked ...\n#define TXT_TRIGGER_JUST_ACTION  \t0x402 \t// Just This Action\n#define TXT_TEAM_EDIT            \t0x403 \t// Team Editor\n#define TXT_SELLABLE             \t0x404 \t// Sellable\n#define TXT_REBUILD              \t0x405 \t// Rebuild\n#define TXT_SPEED_BUILD          \t0x406 \t// Building constructin time\n#define TXT_SCENARIO_ERRORx      \t0x407 \t// Scenario authentication\n#define TXT_DEBUG_STRESS         \t0x408 \t// Frames:F/R:CPU:F/R:\n#define TXT_DEBUG_VEHICLE        \t0x409 \t// Full\n#define TXT_DEBUG_INFANTRY       \t0x40a \t// Full\n#define TXT_DEBUG_SHIP           \t0x40b \t// Full\n#define TXT_DEBUG_BUILDING       \t0x40c \t// Full\n#define TXT_DEBUG_PERFORMANCE    \t0x40d \t//  Game Objects  Drawing  \n#define TXT_DEBUG_AIRCRAFT       \t0x40e \t// Full\n#define TXT_DEBUG_HOUSE          \t0x40f \t// Full Name:Act\n#define TXT_NO_PENTIUM           \t0x410 \t// ****************************\n#define TXT_SIZE_MAP             \t0x411 \t// Size Map\n#define TXT_TRUCK_CRATE          \t0x412 \t// Trucks drop crate when\n"
  },
  {
    "path": "CODE/DEFINES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/DEFINES.H 4     3/07/97 9:55a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DEFINES.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : September 10, 1993   [JLB]                                   *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef DEFINES_H\n#define DEFINES_H\n\n/**********************************************************************\n**\tLanguage control: define the desired language for this build.\n*/\n//#define ENGLISH 1\n//#define FRENCH 1\n//#define GERMAN 1\n//#define SPAIN 1\t(never used)\n//\t- Language define is now passed in from the makefile. -\n\n/**********************************************************************\n**\tControls the nature of the game and its abilities. Only define\n**\tone of these values.\n**\n**\tInternal version -- complete with scenario editor.\n**\tPlaytest version -- no editor but does have minimal cheat keys.\n**\tRelease version -- no editor or cheat keys -- all debugging info removed.\n*/\n//#define\tINTERNAL_VERSION\n//#define\tPLAYTEST_VERSION\n#define\tRELEASE_VERSION\n\n/**********************************************************************\n** ColinM\n** Set this to enable dongle protection\n*/\n//#define DONGLE\n\n\n// Enable 640x400 VQ movie capability in WIN32 mode\n#define MOVIE640\n\n\n//#if (GERMAN | FRENCH)\n//#define\tBOGUSCD\n//#endif\n\n#define\tFIXIT_SCORE_CRASH\t\t\t// Fixes score screen crash\n#define\tFIXIT_MULTI_SAVE\t\t\t// Fixes multiplayer save/load\n#define\tFIXIT_NO_COMP_ALLY\t\t// Prevent ally with computer\n#define\tFIXIT_DESTNET\t\t\t\t// Fixes -destnet parameter in Win95\n#define\tFIXIT_RANDOM_GAME\t\t\t// Fixes random seed at start of multiplayer games\n#define\tFIXIT_FORCE_CD\t\t\t\t// Forces correct CD load after scenario #1\n#define\tFIXIT_IP_CRASH\t\t\t\t// Fixes crash if internet game aborts too quickly\n#define\tFIXIT_IP_STATS\t\t\t\t// Fixes so vessels show up in internet stat info\n#define\tFIXIT_NAME_OVERRIDE     // Allows changing of unit names\n#define\tFIXIT_RADAR_JAMMED\t\t// Fixes unjamming by merely starting to build a radar facility\n#define\tFIXIT_CAPTURE_BIB\t\t\t// Fixes so that if fake is captured, you still can't build off of it.\n#define\tFIXIT_BASE_ANNOUNCE\t\t// Fixes so player controlled buildings count as base when attacked.\n#define\tFIXIT_APTIVA_MODEM\t\t// Fixes crash with Aptiva modem.\n#define\tFIXIT_FLAG_CHECK\t\t\t// Disable placing building over a flag.\n\n#define\tFIXIT_ANTS              // Adds Ant Units\n\n#define\tFIXIT_CSII\t\t\t\t\t// Adds Aftermath CounterStrike II units\n//\tajw 9/28/98 - Note about FIXIT_CSII. Changes seem to have been made for Aftermath (\"Counterstrike II\") that: a) were\n//\tbug fixes that should never be rolled back, b) change the nature of the game, at least in multi-player. This meant\n//\tthat the \"Red Alert\" executable ( == Counterstrike executable ) could no longer be built. Apparently, at the time,\n//\tthis was justified, as it was believed that no further patches to the RA executable would ever be necessary.\n//\tGiven that Denzil's DVD changes and my WOLAPI integration are essentially a patch, we've got a problem.\n//\tWe've decided to level the field and make sure every who gets or patches to the new version of Red Alert, CS, AM, (and\n//\ttheir DVD equivalent(s)) will have the same executable. So we're assuming that all of the FIXIT_CSII changes are \n//\tpermanent (as, in fact, all prior FIXIT_'s are - makes me wonder why the old non-compiling code has to hang around\n//\tforever), and fixing the code so that the assumption \"this is an Aftermath game\" is no longer hard-coded, but can \n//\tchange at runtime. (Which is what should have been done when Aftermath was created.)\n//\t<This goes for the following three defines as well.>\n#define\tFIXIT_CARRIER\t\t\t\t// Adds Aftermath aircraft carrier\n#define\tFIXIT_PHASETRANSPORT\t\t// Adds Aftermath cloaking APC\n//\tajw - Discovered that engineer changing fields were specifically left out of aftrmath.ini, thus this has no effect.\n//\tEngineer changes (and other game rule changes) are in mplayer.ini, which was loaded before aftermath-only mplayer games.\n#define\tFIXIT_ENGINEER\t\t\t\t// Adds Engineer rules.ini overrides\n\n//#define\tFIXIT_FAST_LOAD\t\t\t// Enables faster INI loading\n\n// These fixes will cause the game to go out of sync.\n//#define\tFIXIT_ENGINEER_CAPTURE\t// If building not allied, will still capture if engineer not allied with building.\n//#define\tFIXIT_HELI_LANDING\t// Fixes so new helicopters land at free helipad\n//#define\tFIXIT_MINE_PASSABLE\t// Fixes units not driving onto mines\n\n/* Turn on these changes for the 1.08 patch */\n#define FIXIT_PATCH_108\n\n#ifdef FIXIT_PATCH_108\n#define STEVES_LOAD_OVERRIDE // Allows loading of CONQUER.ENG instead of from mix file.\n#define FIXIT_DIFFICULTY\t\t// Fixes no difficulty level for CStrike missions\n#define FIXIT_VERSION\t// Fixes version playability for 1.04, 1.07 & 1.08\n#define FIXIT_MODEM_LOAD_CRASH // Fixes crash after loading a modem game when names are the same\n#define FIXIT_PHONELIST_CRASH // Fixes crash when clicking on an empty phonelist\n#endif\n\n//\tDenotes changes made for version 3 - reunification of all existing versions and undoing of Aftermath divergence. - ajw\n#define FIXIT_VERSION_3\n#define DVD\n\n// Define DVD to turn on RADVD additions/changes - Denzil\n#ifdef DVD\n//#define INTERNET_OFF\n#define MPEGMOVIE\n//#define MCIMPEG\n#endif\n\n// Test to see if partial object drawing is any faster.\n#define\tPARTIAL\n//#define\tSORTDRAW\n\n/**********************************************************************\n**\tIf the scenario editor to to be active in this build then uncomment\n**\tthe following #define line.\n*/\n#ifdef INTERNAL_VERSION\n#define SCENARIO_EDITOR\n#endif\n\n\n/**********************************************************************\n**\tThis define enables the full set of cheat keys and special\n**\tcommand line options.\n*/\n#if defined(INTERNAL_VERSION) || defined(PLAYTEST_VERSION)\n#define CHEAT_KEYS\n#endif\n\n\n/**********************************************************************\n**\tIf this is defined, the special Virgin limited cheat keys\n**\tare enabled. This allows the \"cheat\" parameter and then only\n**\tallows the ALT-W to win the mission.\n*/\n#ifdef PLAYTEST_VERSION\n#define VIRGIN_CHEAT_KEYS\n#endif\n\n\n/**********************************************************************\n**\tIf this is defined, then the network code will be enabled.\n*/\n#define NETWORK\n#define TIMING_FIX\t1\n\n\n/**********************************************************************\n** Define this to 1 to enable MPath-specific code.  Do not define\n** TEN at the same time.\n*/\n#define MPATH\t0\n\n\n/**********************************************************************\n** Define this to 1 to enable TEN-specific code.  Do not define\n** MPATH at the same time.\n*/\n#define TEN\t\t0\n\n\n/**********************************************************************\n**\tIf this is defined, the DoList is \"mirrored\", for memory trasher\n** detection.\n*/\n#ifdef CHEAT_KEYS\n//#define MIRROR_QUEUE\n#endif\n\n\n/**********************************************************************\n**\tThis define tells the Version Number class to use the date/time-based\n** version numbering system.  If this define is not set, the actual\n** major/minor version numbers will be used.\n*/\n//#define DEV_VERSION\n//#define DEV_VER_NAME\n\n\n/**********************************************************************\n** This define enables a special additional foreign-version-number\n** after the other version number, for display purposes only.\n*/\n#if !defined(ENGLISH)\n#define\tFOREIGN_VERSION\n#define\tFOREIGN_VERSION_NUMBER\t7\n#endif\n\n\n/**********************************************************************\n** This is the multiplier factor to convert low resution coordinates\n**\tinto their actual resolution counterparts.\n*/\n#ifdef WIN32\n#define RESFACTOR\t2\n#else\n//#undef SCENARIO_EDITOR\n#define RESFACTOR 1\n#endif\n\n\n#define SIDEBAR_WID\t80\n\n\n/**********************************************************************\n**\tOptional parameter control for special options.\n*/\n\n/*\n**\tEnable the set of limited cheat key options.\n*/\n#ifdef VIRGIN_CHEAT_KEYS\n#define\tPARM_PLAYTEST\t\t0xF7DDC227\t\t// \"PLAYTEST\"\n#endif\n\n/*\n**\tEnable the full set of cheat key options.\n*/\n#ifdef CHEAT_KEYS\n#ifndef PARM_PLAYTEST\n#define\tPARM_PLAYTEST\t\t0xF7DDC227\t\t// \"PLAYTEST\"\n#endif\n#endif\n\n\n#define\tPARM_INSTALL\t\t0xD95C68A2\t\t//\t\"FROMINSTALL\"\n\n\n//\n// Allow normal game play in the MPath version\n//\n#if(MPATH)\n#define\tPARM_ALLOW_SOLO\t0xc901c9db\t// AllowSoloPlayOptions\n#endif\n\n//\n// Allow normal game play in the TEN version\n//\n#if(TEN)\n#define\tPARM_ALLOW_SOLO\t0xc901c9db\t// AllowSoloPlayOptions\n#endif\n\n/**********************************************************************\n**\tDefines for verifying free disk space\n*/\n#define\tINIT_FREE_DISK_SPACE\t\t8388608\n#define\tSAVE_GAME_DISK_SPACE\t\t (INIT_FREE_DISK_SPACE - (1024*4096))\n//#define\tSAVE_GAME_DISK_SPACE\t\t 100000\n\n\n/**********************************************************************\n**\tThis is the complete list of VQs allowed to be played in the game.\n*/\ntypedef enum VQType {\n\tVQ_NONE=-1,\n\tVQ_AAGUN,\n\tVQ_MIG,\n\tVQ_SFROZEN,\n\tVQ_AIRFIELD,\n\tVQ_BATTLE,\n\tVQ_BMAP,\n\tVQ_BOMBRUN,\n\tVQ_DPTHCHRG,\n\tVQ_GRVESTNE,\n\tVQ_MONTPASS,\n\tVQ_MTNKFACT,\n\tVQ_CRONTEST,\n\tVQ_OILDRUM,\n\tVQ_ALLYEND,\n\tVQ_RADRRAID,\n\tVQ_SHIPYARD,\n\tVQ_SHORBOMB,\n\tVQ_SITDUCK,\n\tVQ_SLNTSRVC,\n\tVQ_SNOWBASE,\n\tVQ_EXECUTE,\n\tVQ_TITLE,\t\t\t\t// Low res.\n\tVQ_NUKESTOK,\n\tVQ_V2ROCKET,\n\tVQ_SEARCH,\n\tVQ_BINOC,\n\tVQ_ELEVATOR,\n\tVQ_FROZEN,\n\tVQ_MCV,\n\tVQ_SHIPSINK,\n\tVQ_SOVMCV,\n\tVQ_TRINITY,\n\tVQ_ALLYMORF,\n\tVQ_APCESCPE,\n\tVQ_BRDGTILT,\n\tVQ_CRONFAIL,\n\tVQ_STRAFE,\n\tVQ_DESTROYR,\n\tVQ_DOUBLE,\n\tVQ_FLARE,\n\tVQ_SNSTRAFE,\n\tVQ_LANDING,\n\tVQ_ONTHPRWL,\n\tVQ_OVERRUN,\n\tVQ_SNOWBOMB,\n\tVQ_SOVCEMET,\n\tVQ_TAKE_OFF,\n\tVQ_TESLA,\n\tVQ_SOVIET8,\n\tVQ_SPOTTER,\n\tVQ_SCENE1,\n\tVQ_SCENE2,\n\tVQ_SCENE4,\n\tVQ_SOVFINAL,\n\tVQ_ASSESS,\n\tVQ_SOVIET10,\n\tVQ_DUD,\n\tVQ_MCV_LAND,\n\tVQ_MCVBRDGE,\n\tVQ_PERISCOP,\n\tVQ_SHORBOM1,\n\tVQ_SHORBOM2,\n\tVQ_SOVBATL,\n\tVQ_SOVTSTAR,\n\tVQ_AFTRMATH,\n\tVQ_SOVIET11,\n\tVQ_MASASSLT,\n\tVQ_REDINTRO,\t\t// High res\n\tVQ_SOVIET1,\n\tVQ_SOVIET2,\n\tVQ_SOVIET3,\n\tVQ_SOVIET4,\n\tVQ_SOVIET5,\n\tVQ_SOVIET6,\n\tVQ_SOVIET7,\n\tVQ_INTRO_MOVIE,\n\tVQ_AVERTED,\n\tVQ_COUNTDWN,\n\tVQ_MOVINGIN,\n\tVQ_ALLIED10,\n\tVQ_ALLIED12,\n\tVQ_ALLIED5,\n\tVQ_ALLIED6,\n\tVQ_ALLIED8,\n\tVQ_TANYA1,\n\tVQ_TANYA2,\n\tVQ_ALLY10B,\n\tVQ_ALLY11,\n\tVQ_ALLY14,\n\tVQ_ALLY9,\n\tVQ_SPY,\n\tVQ_TOOFAR,\n\tVQ_SOVIET12,\n\tVQ_SOVIET13,\n\tVQ_SOVIET9,\n\tVQ_BEACHEAD,\n\tVQ_SOVIET14,\n\tVQ_SIZZLE,\n\tVQ_SIZZLE2,\n\tVQ_ANTEND,\n\tVQ_ANTINTRO,\n\n\tVQ_COUNT,\n\tVQ_FIRST=0\n} VQType;\n\n\n/**********************************************************************\n**\tThese enumerations are used to implement RTTI. The target system\n**\tuses these and thus there can be no more RTTI types than can fit\n**\tin the exponent of a target value.\n*/\ntypedef enum RTTIType {\n\tRTTI_NONE=0,\n\tRTTI_AIRCRAFT,\n\tRTTI_AIRCRAFTTYPE,\n\tRTTI_ANIM,\n\tRTTI_ANIMTYPE,\n\tRTTI_BUILDING,\n\tRTTI_BUILDINGTYPE,\n\tRTTI_BULLET,\n\tRTTI_BULLETTYPE,\n\tRTTI_CELL,\n\tRTTI_FACTORY,\n\tRTTI_HOUSE,\n\tRTTI_HOUSETYPE,\n\tRTTI_INFANTRY,\n\tRTTI_INFANTRYTYPE,\n\tRTTI_OVERLAY,\n\tRTTI_OVERLAYTYPE,\n\tRTTI_SMUDGE,\n\tRTTI_SMUDGETYPE,\n\tRTTI_SPECIAL,\n\tRTTI_TEAM,\n\tRTTI_TEAMTYPE,\n\tRTTI_TEMPLATE,\n\tRTTI_TEMPLATETYPE,\n\tRTTI_TERRAIN,\n\tRTTI_TERRAINTYPE,\n\tRTTI_TRIGGER,\n\tRTTI_TRIGGERTYPE,\n\tRTTI_UNIT,\n\tRTTI_UNITTYPE,\n\tRTTI_VESSEL,\n\tRTTI_VESSELTYPE,\n\n\tRTTI_COUNT\n} RTTIType;\n\n\n/**********************************************************************\n**\tThese are the difficulty settings of the game.\n*/\ntypedef enum DiffType {\n\tDIFF_EASY,\n\tDIFF_NORMAL,\n\tDIFF_HARD,\n\n\tDIFF_COUNT,\n\tDIFF_FIRST=0\n} DiffType;\n\n\n/**********************************************************************\n**\tThis is the size of the speech buffer. This value should be as large\n**\tas the largest speech sample, plus a few bytes for overhead\n**\t(16 bytes is sufficient).\n*/\n#define SPEECH_BUFFER_SIZE\t\t50000L\n\n\n/**********************************************************************\n**\tThe theater mixfiles are cached into a buffer of this size. Ensure\n**\tthat the size specified is at least as large as the largest\n**\ttheater mixfile data block.\n*/\n#define THEATER_BUFFER_SIZE\t1100000L\n\n\n/**********************************************************************\n**\tThis is the size of the shape buffer. This buffer is used as a staging\n**\tbuffer for the shape drawing technology. It MUST be as big as the\n**\tlargest shape (uncompressed) that will be drawn. If this value is\n**\tchanged, be sure to update the makefile and rebuild all of the shape\n**\tdata files.\n*/\n#define SHAPE_BUFFER_SIZE\t\t65000L\n\n\n/**********************************************************************\n**\tFilenames of the data files it can create at run time.\n*/\n#define FAME_FILE_NAME\t\t\t\"HALLFAME.DAT\"\n#define NET_SAVE_FILE_NAME\t\t\"SAVEGAME.NET\"\n#define CONFIG_FILE_NAME\t\t\"REDALERT.INI\"\n\n\n/**********************************************************************\n**\tMap controls. The map is composed of square elements called 'cells'.\n**\tAll larger elements are build upon these.\n*/\n\n#define\tHIGH_COORD_MASK\t\t\t0x80008000L\n\n// Size of the map in cells.\n#define\tMAP_CELL_W\t\t\t\t128\n#define\tMAP_CELL_H\t\t\t\t128\n#define\tMAP_CELL_TOTAL\t\t\t(MAP_CELL_W*MAP_CELL_H)\n\n#define\tREFRESH_EOL\t\t\t\t32767\t\t// This number ends a refresh/occupy offset list.\n#define\tREFRESH_SIDEBAR\t\t32766\t\t// This number flags that sidebar needs refreshing.\n\n\n/****************************************************************************\n**\tThese are custom C&C specific types. The CELL is used for map coordinate\n**\twith cell resolution. The COORDINATE type is used for map coordinates that\n**\thave a lepton resolution. CELL is more efficient when indexing into the map\n**\tand when size is critical. COORDINATE is more efficient when dealing with\n**\taccuracy and object movement.\n*/\ntypedef unsigned short\tLEPTON;\ntypedef union {\n\tLEPTON Raw;\n\tstruct {\n#ifdef BIG_ENDIAN\n\t\tunsigned char Cell;\n\t\tunsigned char Lepton;\n#else\n\t\tunsigned char Lepton;\n\t\tunsigned char Cell;\n#endif\n\t} Sub;\n} LEPTON_COMPOSITE;\n\ntypedef unsigned long\tCOORDINATE;\ntypedef union {\n\tCOORDINATE Coord;\n\tstruct {\n#ifdef BIG_ENDIAN\n\t\tLEPTON_COMPOSITE Y;\n\t\tLEPTON_COMPOSITE X;\n#else\n\t\tLEPTON_COMPOSITE X;\n\t\tLEPTON_COMPOSITE Y;\n#endif\n\t} Sub;\n}\tCOORD_COMPOSITE;\n\ntypedef signed short\t\tCELL;\n#define\tSLUFF_BITS\t(sizeof(CELL)*CHAR_BIT)-(14)\ntypedef union {\n\tCELL Cell;\n\tstruct {\n#ifdef BIG_ENDIAN\n#if SLUFF_BITS\n\t\t/*\n\t\t**\tUnused upper bits will cause problems on a big-endian machine unless they\n\t\t**\tare deliberately accounted for.\n\t\t*/\n\t\tunsigned sluff:SLUF_BITS;\n#endif\n\t\tunsigned Y:7;\n\t\tunsigned X:7;\n#else\n\t\tunsigned X:7;\n\t\tunsigned Y:7;\n#endif\n\t} Sub;\n} CELL_COMPOSITE;\n\ntypedef int\t\tWAYPOINT;\n\n\n/**********************************************************************\n**\tThis is the target composit information. Notice that with an RTTI_NONE\n**\tand an index value of 0, the target value returned is identical with\n**\tTARGET_NONE. This is by design and is necessary.\n*/\ntypedef long\tTARGET;\n\n#define\tTARGET_MANTISSA\t\t\t24\t\t\t\t// Bits of value precision.\n#define\tTARGET_EXPONENT\t\t\t8\ntypedef union {\n\tTARGET Target;\n\tstruct {\n#ifdef BIG_ENDIAN\n\t\tunsigned Exponent:TARGET_EXPONENT;\n\t\tunsigned Mantissa:TARGET_MANTISSA;\n#else\n\t\tunsigned Mantissa:TARGET_MANTISSA;\n\t\tunsigned Exponent:TARGET_EXPONENT;\n#endif\n\t} Sub;\n} TARGET_COMPOSITE;\n\n\ninline TARGET Build_Target(RTTIType kind, int value)\n{\n\tTARGET_COMPOSITE target;\n\n\ttarget.Target = 0;\n\ttarget.Sub.Exponent = kind;\n\ttarget.Sub.Mantissa = value;\n\treturn(target.Target);\n}\n\n\n#define\tTARGET_NONE \t((TARGET)0)\n\n\n/*\n**\tThe map is broken down into regions of this specified dimensions.\n*/\n#define\tREGION_WIDTH\t\t4\n#define\tREGION_HEIGHT\t\t4\n#define\tMAP_REGION_WIDTH\t(((MAP_CELL_W + (REGION_WIDTH -1)) / REGION_WIDTH)+2)\n#define\tMAP_REGION_HEIGHT\t(((MAP_CELL_H + (REGION_WIDTH -1)) / REGION_HEIGHT)+2)\n#define  MAP_TOTAL_REGIONS\t(MAP_REGION_WIDTH * MAP_REGION_HEIGHT)\n\n\n/**********************************************************************\n**\tThis enumerates the various known fear states for infantry units.\n**\tAt these stages, certain events or recovery actions are performed.\n*/\ntypedef enum FearType {\n\tFEAR_NONE=0,\t\t\t// No fear at all (default state).\n\tFEAR_ANXIOUS=10,\t\t// Something makes them scared.\n\tFEAR_SCARED=100,\t\t// Scared enough to take cover.\n\tFEAR_PANIC=200,\t\t// Run away! Run away!\n\tFEAR_MAXIMUM=255\t\t// Scared to death.\n} FearType;\n\n\n/**********************************************************************\n**\tWhen a moving object moves, the Per_Cell_Process function is called\n**\tat various times during the move. Certain operations must be\n**\tperformed at different stages of the move. This enum specifies the\n**\tdifferent conditions under which the Per_Cell_Process function is\n**\tcalled.\n*/\ntypedef enum PCPType {\n\tPCP_ROTATION,\t\t\t// When sitting in place and performing rotations.\n\tPCP_DURING,\t\t\t\t// While moving between two cells.\n\tPCP_END,\t\t\t\t\t// When the 'center' of a cell is reached during movement.\n} PCPType;\n\n\n/**********************************************************************\n**\tA base is broken up into several zones. This type enumerates the\n**\tvarious zones.\n*/\ntypedef enum ZoneType {\n\tZONE_CORE,\t\t\t// Center of base.\n\tZONE_NORTH,\t\t\t// North section.\n\tZONE_EAST,\t\t\t// East section.\n\tZONE_SOUTH,\t\t\t// South section.\n\tZONE_WEST,\t\t\t// West section.\n\n\tZONE_COUNT,\n\tZONE_FIRST=0,\n\tZONE_NONE=-1\n} ZoneType;\n\n\n/**********************************************************************\n**\tThe map is prescanned to mark of movement zones according to certain\n**\tmovement characteristics. This enum specifies those characteristics\n**\tand movement zones kept track of.\n*/\ntypedef enum MZoneType {\n\tMZONE_NORMAL,\t\t\t\t// Normal terrestrial objects (can't crush walls).\n\tMZONE_CRUSHER,\t\t\t\t// Can crush crushable wall types.\n\tMZONE_DESTROYER,\t\t\t// Can destroy walls.\n\tMZONE_WATER,\t\t\t\t//\tWater based objects.\n\n\tMZONE_COUNT,\n\tMZONE_FIRST=0\n} MZoneType;\n\n#define\tMZONEF_NORMAL\t\t(1<<MZONE_NORMAL)\n#define\tMZONEF_CRUSHER\t\t(1<<MZONE_CRUSHER)\n#define\tMZONEF_DESTROYER\t(1<<MZONE_DESTROYER)\n#define\tMZONEF_WATER\t\t(1<<MZONE_WATER)\n#define\tMZONEF_ALL\t\t\t(MZONEF_NORMAL|MZONEF_CRUSHER|MZONEF_DESTROYER|MZONEF_WATER)\n\n\n/**********************************************************************\n**\tThis records the current state of the computer controlled base. The\n**\tAI will respond according to this state in order to control\n**\tproduction and unit orders.\n*/\ntypedef enum StateType {\n\tSTATE_BUILDUP,\t\t\t// Base is building up (defensive buildup stage).\n\tSTATE_BROKE,\t\t\t// Low on money, need cash or income source.\n\tSTATE_THREATENED,\t\t// Enemy units are designated to move close by.\n\tSTATE_ATTACKED,\t\t// Base is under direct attack.\n\tSTATE_ENDGAME\t\t\t//\tResistance is futile.\n} StateType;\n\n\n/**********************************************************************\n**\tUrgency rating used to determine what action to perform. The greater\n**\tthe urgency the more likely the corresponding action will be chosen.\n**\tThese values are assigned to each potential desired action the house\n**\tis to perform.\n*/\ntypedef enum UrgencyType {\n\tURGENCY_NONE,\t\t\t\t// No action on this matter is needed or desired.\n\tURGENCY_LOW,\t\t\t\t// Minimal attention requested.\n\tURGENCY_MEDIUM,\t\t\t//\tNormal attention requested.\n\tURGENCY_HIGH,\t\t\t\t// High attention requested.\n\tURGENCY_CRITICAL,\t\t\t// This matter must be addressed immediately.\n\n\tURGENCY_COUNT,\n\tURGENCY_FIRST=URGENCY_CRITICAL\n} UrgencyType;\n\n\n/**********************************************************************\n**\tThese are the various actions a house may perform. These actions refer\n**\tto global events that encompass selling and production. Low level house\n**\tspecific actions of choosing targets is handled elsewhere.\n*/\ntypedef enum StrategyType {\n\tSTRATEGY_BUILD_POWER,\t\t\t// Power is low, build more.\n\tSTRATEGY_BUILD_DEFENSE,\t\t\t// Defense needs boosting.\n\tSTRATEGY_BUILD_INCOME,\t\t\t// Income is low or in jeopardy, raise it.\n\tSTRATEGY_FIRE_SALE,\t\t\t\t// Situation hopeless, sell and attack.\n\tSTRATEGY_BUILD_ENGINEER,\t\t// An engineer is needed.\n\tSTRATEGY_BUILD_OFFENSE,\t\t\t// Offensive weapons are needed.\n\tSTRATEGY_RAISE_MONEY,\t\t\t// Money is low, emergency raise cash.\n\tSTRATEGY_RAISE_POWER,\t\t\t// Money is low, raise power by selling.\n\tSTRATEGY_LOWER_POWER,\t\t\t// Too much power, sell power plants.\n\tSTRATEGY_ATTACK,\t\t\t\t\t// General charge the enemy attack logic.\n\n\tSTRATEGY_COUNT,\n\tSTRATEGY_FIRST=STRATEGY_BUILD_POWER\n} StrategyType;\n\n\n/**********************************************************************\n**\tThese are the various return conditions that production may\n**\tproduce.\n*/\ntypedef enum ProdFailType {\n\tPROD_OK,\t\t\t\t\t\t// Production request successful.\n\tPROD_LIMIT,\t\t\t\t\t// Failed with production capacity limit reached.\n\tPROD_ILLEGAL,\t\t\t\t// Failed because of illegal request.\n\tPROD_CANT\t\t\t\t\t// Failed because unable to comply (busy or occupied).\n} ProdFailType;\n\n\n/**********************************************************************\n**\tWhen performing a landing operation, the aircraft must pass through\n**\tnavigation checkpoints. These enumerations specify the check points.\n*/\ntypedef enum CheckPointType {\n\tCHECK_STACK,\t\t\t\t// Holding area far away from airfield.\n\tCHECK_DOWNWIND,\t\t\t// Downwind leg of approach.\n\tCHECK_CROSSWIND\t\t\t// Crosswind leg of approach.\n} CheckPointType;\n\n\n/**********************************************************************\n**\tThese enumerate the various crate powerups that are available.\n*/\ntypedef enum CrateType {\n\tCRATE_MONEY,\n\tCRATE_UNIT,\n\tCRATE_PARA_BOMB,\n\tCRATE_HEAL_BASE,\n\tCRATE_CLOAK,\n\tCRATE_EXPLOSION,\n\tCRATE_NAPALM,\n\tCRATE_SQUAD,\n\tCRATE_DARKNESS,\n\tCRATE_REVEAL,\n\tCRATE_SONAR,\n\tCRATE_ARMOR,\n\tCRATE_SPEED,\n\tCRATE_FIREPOWER,\n\tCRATE_ICBM,\n\tCRATE_TIMEQUAKE,\n\tCRATE_INVULN,\n\tCRATE_VORTEX,\n\n\tCRATE_COUNT,\n\tCRATE_FIRST=0\n} CrateType;\n\n\n/**********************************************************************\n**\tThese are the special weapons that can be used in the game. The common thread\n**\twith these weapons is that they are controlled through the sidebar\n**\tmechanism.\n*/\ntypedef enum SpecialWeaponType {\n\tSPC_NONE=-1,\n\tSPC_SONAR_PULSE,\t\t\t// Momentarily reveals submarines.\n\tSPC_NUCLEAR_BOMB,\t\t\t//\tTactical nuclear weapon.\n\tSPC_CHRONOSPHERE,\t\t\t// Paradox device, for teleportation\n\tSPC_PARA_BOMB,\t\t\t\t// Parachute bomb delivery.\n\tSPC_PARA_INFANTRY,\t\t// Parachute reinforcement delivery.\n\tSPC_SPY_MISSION,\t\t\t// Spy plane to take photo recon mission.\n\tSPC_IRON_CURTAIN,\t\t\t// Bestow invulnerability on a unit/building\n\tSPC_GPS,\t\t\t\t\t\t// give allies free unjammable radar.\n\n\tSPC_COUNT,\n\tSPC_FIRST=0,\n\tSPC_ANY=1\n} SpecialWeaponType;\n#define\tSPC_CHRONO2\t(SPC_COUNT)\n\n\n/**********************************************************************\n**\tThe computer AI is categorized by the following enumerations. If\n**\tthe player is controlling a house, then the IQ rating is zero. When\n**\tthe IQ rating is at maximum, then the computer has complete control\n**\tof the house.\n*/\n//typedef enum IQType {\n//\tIQ_DEAD=0x0000,\t\t\t// Player controlled (computer does nothing).\n//\tIQ_IDIOT=0x0040,\n//\tIQ_IMBECILE=0x0080,\n//\tIQ_MORON=0x00C0,\n//\tIQ_MENSA=0x0100\t\t\t// Complete computer control -- look out!\n//} IQType;\n\n\n/**********************************************************************\n**\tThese are the response values when checking to see if an object\n**\tcan enter or exist at a specified location. By examining this\n**\treturn value, appropriate action may be chosen.\n**\tNOTE: If this changes, update the static array in Find_Path module.\n*/\ntypedef enum MoveType {\n\tMOVE_OK, \t\t\t\t// No blockage.\n\tMOVE_CLOAK,\t\t\t\t// A cloaked blocking enemy object.\n\tMOVE_MOVING_BLOCK,\t// Blocked, but only temporarily.\n\tMOVE_DESTROYABLE,\t\t// Enemy unit or building is blocking.\n\tMOVE_TEMP,  \t\t\t// Blocked by friendly unit.\n\tMOVE_NO,\t\t\t\t\t// Strictly prohibited terrain.\n\n\tMOVE_COUNT\n} MoveType;\n\n\n/**********************************************************************\n**\tThese are the themes that the game can play. They must be in exact\n**\tsame order as specified in the CONQUER.TXT file as well as the filename\n**\tlist located in the ThemeClass.\n*/\ntypedef enum ThemeType {\n\tTHEME_QUIET=-3,\n\tTHEME_PICK_ANOTHER=-2,\n\tTHEME_NONE=-1,\n\tTHEME_BIGF,\n\tTHEME_CRUS,\n\tTHEME_FAC1,\n\tTHEME_FAC2,\n\tTHEME_HELL,\n\tTHEME_RUN1,\n\tTHEME_SMSH,\n\tTHEME_TREN,\n\tTHEME_WORK,\n\tTHEME_AWAIT,\n\tTHEME_DENSE_R,\n\tTHEME_FOGGER1A,\n\tTHEME_MUD1A,\n\tTHEME_RADIO2,\n\tTHEME_ROLLOUT,\n\tTHEME_SNAKE,\n\tTHEME_TERMINAT,\n\tTHEME_TWIN,\n\tTHEME_VECTOR1A,\n\n\tTHEME_MAP,\n\tTHEME_SCORE,\n\tTHEME_INTRO,\n\tTHEME_CREDITS,\n\n\tTHEME_2ND_HAND,\n\tTHEME_ARAZOID,\n\tTHEME_BACKSTAB,\n\tTHEME_CHAOS2,\n\tTHEME_SHUT_IT,\n\tTHEME_TWINMIX1,\n\tTHEME_UNDER3,\n\tTHEME_VR2,\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tTHEME_BOG,\n\tTHEME_FLOAT_V2,\n\tTHEME_GLOOM,\n\tTHEME_GRNDWIRE,\n\tTHEME_RPT,\n\tTHEME_SEARCH,\n\tTHEME_TRACTION,\n\tTHEME_WASTELND,\n#endif\n\n\tTHEME_COUNT,\n\tTHEME_LAST=(int)THEME_COUNT-1,\n\tTHEME_FIRST=0\n} ThemeType;\n\ninline ThemeType operator++(ThemeType &, int);\n\n\n/**********************************************************************\n**\tThis is the various threat scan methods that can be used when looking\n**\tfor targets.\n*/\ntypedef enum ThreatType {\n\tTHREAT_NORMAL=0x0000,\t\t// Any distance threat scan?\n\tTHREAT_RANGE=0x0001,\t\t\t// Limit scan to weapon range?\n\tTHREAT_AREA=0x0002,\t\t\t// Limit scan to general area (twice weapon range)?\n\tTHREAT_AIR=0x0004,\t\t\t// Scan for air units?\n\tTHREAT_INFANTRY=0x0008,\t\t// Scan for infantry units?\n\tTHREAT_VEHICLES=0x0010,\t\t// Scan for vehicles?\n\tTHREAT_BUILDINGS=0x0020,\t// Scan for buildings?\n\tTHREAT_TIBERIUM=0x0040,\t\t// Limit scan to Tiberium processing objects?\n\tTHREAT_BOATS=0x0080,\t\t\t// Scan for gunboats?\n\tTHREAT_CIVILIANS=0x0100,\t// Consider civilians to be primary target?\n\tTHREAT_CAPTURE=0x0200,\t\t// Consider capturable buildings only?\n\tTHREAT_FAKES=0x0400,\t\t\t// Consider fake buildings a greater target?\n\tTHREAT_POWER=0x0800,\t\t\t// Consider power generating facilities a greater target?\n\tTHREAT_FACTORIES=0x1000,\t// Consider factories a greater target?\n\tTHREAT_BASE_DEFENSE=0x2000\t// Consider base defense buildings a greater target?\n} ThreatType;\ninline ThreatType operator |(ThreatType, ThreatType);\ninline ThreatType operator &(ThreatType, ThreatType);\ninline ThreatType operator ~(ThreatType);\n\n#define THREAT_GROUND\t(THREAT_VEHICLES|THREAT_BUILDINGS|THREAT_INFANTRY)\n\n\n/**********************************************************************\n**\tThese return values are used when determine if firing is legal.\n**\tBy examining this value it can be determined what should be done\n**\tto fix the reason why firing wasn't allowed.\n*/\ntypedef enum FireErrorType {\n\tFIRE_OK,\t\t\t\t// Weapon is allowed to fire.\n\tFIRE_AMMO,\t\t\t// No ammo available to fire?\n\tFIRE_FACING,\t\t// Not correctly facing target?\n\tFIRE_REARM,\t\t\t// It is busy rearming?\n\tFIRE_ROTATING,\t\t// Is it in process of rotating?\n\tFIRE_ILLEGAL,\t\t// Is it targeting something illegal?\n\tFIRE_CANT,\t\t\t// Is this unit one that cannot fire anything?\n\tFIRE_MOVING,\t\t// Is it moving and not allowed to fire while moving?\n\tFIRE_RANGE,\t\t\t// Is the target out of range?\n\tFIRE_CLOAKED,\t\t// Is the shooter currently cloaked?\n\tFIRE_BUSY\t\t\t// Is shooter currently doing something else?\n} FireErrorType;\n\n\n/**********************************************************************\n**\tIf an object can cloak, then it will be in one of these states.\n**\tFor objects that cannot cloak, they will always be in the\n**\tUNCLOAKED state. This state controls how the object transitions between\n**\tcloaked and uncloaked conditions.\n*/\ntypedef enum CloakType {\n\tUNCLOAKED,\t\t\t// Completely visible (normal state).\n\tCLOAKING,\t\t\t// In process of cloaking.\n\tCLOAKED,\t\t\t\t// Completely cloaked (invisible).\n\tUNCLOAKING\t\t\t// In process of uncloaking.\n} CloakType;\n\n\n/**********************************************************************\n**\tFor units that are cloaking, these value specify the visual character\n**\tof the object.\n*/\ntypedef enum VisualType {\n\tVISUAL_NORMAL,\t\t\t\t// Completely visible -- normal.\n\tVISUAL_INDISTINCT,\t\t// The edges shimmer and become indistinct.\n\tVISUAL_DARKEN,\t\t\t\t// Color and texture is muted along with shimmering.\n\tVISUAL_SHADOWY,\t\t\t// Body is translucent in addition to shimmering.\n\tVISUAL_RIPPLE,\t\t\t\t// Just a ripple (true predator effect).\n\tVISUAL_HIDDEN\t\t\t\t// Nothing at all is visible.\n} VisualType;\n\n\n/**********************************************************************\n**\tThese missions enumerate the various state machines that can apply to\n**\ta game object. Only one of these state machines is active at any one\n**\ttime.\n*/\ntypedef enum MissionType {\n\tMISSION_NONE=-1,\n\n\tMISSION_SLEEP,\t\t\t\t// Do nothing whatsoever.\n\tMISSION_ATTACK,\t\t\t// Attack nearest enemy.\n\tMISSION_MOVE,\t\t\t\t// Guard location or unit.\n\tMISSION_QMOVE,\t\t\t\t// A queue list movement mission.\n\tMISSION_RETREAT,\t\t\t// Return home for R & R.\n\tMISSION_GUARD,\t\t\t\t// Stay still.\n\tMISSION_STICKY,\t\t\t// Stay still -- never recruit.\n\tMISSION_ENTER,\t\t\t\t// Move into object cooperatively.\n\tMISSION_CAPTURE,\t\t\t//\tMove into in order to capture.\n\tMISSION_HARVEST,\t\t\t// Hunt for and collect nearby Tiberium.\n\tMISSION_GUARD_AREA,\t\t// Active guard of area.\n\tMISSION_RETURN,\t\t\t// Head back to refinery.\n\tMISSION_STOP,\t\t\t\t// Sit still.\n\tMISSION_AMBUSH,\t\t\t// Wait until discovered.\n\tMISSION_HUNT,\t\t\t\t// Active search and destroy.\n\tMISSION_UNLOAD,\t\t\t// Search for and deliver cargo.\n\tMISSION_SABOTAGE,\t\t\t//\tMove into in order to destroy.\n\tMISSION_CONSTRUCTION,\t// Building buildup operation.\n\tMISSION_DECONSTRUCTION,\t// Building builddown operation.\n\tMISSION_REPAIR,\t\t\t// Repair process mission.\n\tMISSION_RESCUE,\n\tMISSION_MISSILE,\n\tMISSION_HARMLESS,\t\t\t// Sit around and don't appear like a threat.\n\n\tMISSION_COUNT,\n\tMISSION_FIRST=0\n} MissionType;\n\n\n/**********************************************************************\n**\tThese are the enumerated animation sequences that a building may\n**\tbe processing. These serve to control the way that a building\n**\tappears.\n*/\ntypedef enum BStateType {\n\tBSTATE_NONE=-1,\n\tBSTATE_CONSTRUCTION,\t\t// Construction animation.\n\tBSTATE_IDLE,\t\t\t\t// Idle animation.\n\tBSTATE_ACTIVE,\t\t\t\t// Animation when building is \"doing its thing\".\n\tBSTATE_FULL,\t\t\t\t// Special alternate active state.\n\tBSTATE_AUX1,\t\t\t\t// Auxiliary animation.\n\tBSTATE_AUX2,\t\t\t\t// Auxiliary animation.\n\n\tBSTATE_COUNT\n} BStateType;\n\n\n/**********************************************************************\n**\tWhenever a unit is selected and a click occurs over another object\n**\tor terrain element, there is some action to initiate. This specifies\n**\tthe different types of actions possible. This also controls how the\n**\tmouse cursor looks when \"hovering\" over the spot that clicking would\n**\toccur at.\n*/\ntypedef enum ActionType {\n\tACTION_NONE,\t\t\t// Either undefined action or \"do nothing\".\n\tACTION_MOVE,\t\t\t// Can move there or at least try to.\n\tACTION_NOMOVE,\t\t\t// Special case for movable object, but illegal mouse position.\n\tACTION_ENTER,\t\t\t// Special case for infantry->APC or vehicle->Repair facility.\n\tACTION_SELF,\t\t\t// Self select special case.\n\tACTION_ATTACK,\t\t\t// Can attack or fire upon it in some fashion.\n\tACTION_HARVEST,\t\t// Special harvest mode.\n\tACTION_SELECT,\t\t\t// Would change selection to specified object.\n\tACTION_TOGGLE_SELECT,// Toggles select state of the object.\n\tACTION_CAPTURE,\t\t// The unit will try to capture the object.\n\tACTION_REPAIR,\t\t\t// The target object should be repaired.\n\tACTION_SELL,\t\t\t// The target building should be sold back.\n\tACTION_SELL_UNIT,\t\t// The target unit should be sold back.\n\tACTION_NO_SELL,  \t\t// No sell or no repair.\n\tACTION_NO_REPAIR,\t\t// No sell or no repair.\n\tACTION_SABOTAGE,\t\t// The unit will try to sabotage/destroy the object.\n\tACTION_PARA_BOMB,\t\t// Parachute bomb strike.\n\tACTION_PARA_INFANTRY,// Parachute infantry strike.\n\tACTION_PARA_SABOTEUR,// Parachute saboteur strike.\n\tACTION_NUKE_BOMB,\t\t// That target object should be blasted.\n\tACTION_AIR_STRIKE,\t// That target object should be blasted.\n\tACTION_CHRONOSPHERE,\t// That target object should be teleported.\n\tACTION_CHRONO2,\t\t// Teleport it to the given coordinates now.\n\tACTION_IRON_CURTAIN,\t// That target object should be invulnerable.\n\tACTION_SPY_MISSION,\t// Photo recon mission.\n\tACTION_GUARD_AREA,\t// Guard the area/object clicked on.\n\tACTION_HEAL,\t\t\t// Heal the infantryman clicked on.\n\tACTION_DAMAGE,\t\t\t// Enter and damage building.\n\tACTION_GREPAIR,\t\t// Enter and complete repair building.\n\tACTION_NO_DEPLOY,\n\tACTION_NO_ENTER,\n\tACTION_NO_GREPAIR,\n\n\tACTION_COUNT\n} ActionType;\n\n\n/**********************************************************************\n**\tWhen a unit gets damaged, the result of the damage is returned as\n**\tthis type. It can range from no damage taken to complete destruction.\n*/\ntypedef enum ResultType {\n\tRESULT_NONE,\t\t\t\t// No damage was taken by the target.\n\tRESULT_LIGHT,\t\t\t\t// Some damage was taken, but no state change occurred.\n\tRESULT_HALF,\t\t\t\t// Damaged to below half strength (only returned on transition).\n\tRESULT_MAJOR,\t\t\t\t// Damaged down to 1 hit point.\n\tRESULT_DESTROYED\t\t\t// Damaged to complete destruction.\n} ResultType;\n\n\n#ifdef OBSOLETE\n/**********************************************************************\n**\tThese are the special concrete control defines. They enumerate the\n**\tsequence order of the concrete icons in the concrete art file.\n*/\n// DEBUG === convert this to be zero based so that a nulled cell is the\n//\t\t\t \t default cell.\nenum ConcreteEnum {\n\tC_NONE=-1,\n\tC_LEFT=0,\n\tC_RIGHT=1,\n\tC_RIGHT_UPDOWN=2,\n\tC_LEFT_UPDOWN=3,\n\tC_UP_RIGHT=4,\n\tC_UP_LEFT=5,\n\tC_DOWN_RIGHT=6,\n\tC_DOWN_LEFT=7,\n\tC_RIGHT_DOWN=8,\n\tC_LEFT_DOWN=9,\n\tC_RIGHT_UP=10,\n\tC_LEFT_UP=11,\n\tC_UPDOWN_RIGHT=12,\n\tC_UPDOWN_LEFT=13\n};\n#endif\n\n\n/**********************************************************************\n**\tUnits that move can move at different speeds. These enumerate the\n**\tdifferent speeds that a unit can move.\n*/\ntypedef enum MPHType{\n\tMPH_IMMOBILE=0,\n\tMPH_VERY_SLOW=5,\t\t\t\t//\t2\n\tMPH_KINDA_SLOW=6,\t\t\t\t//\t3\n\tMPH_SLOW=8,\t\t\t\t\t\t//\t4\n\tMPH_SLOW_ISH=10,\t\t\t\t// 5\n\tMPH_MEDIUM_SLOW=12,\t\t\t// 6\n\tMPH_MEDIUM=18,\t\t\t\t\t// 9\n\tMPH_MEDIUM_FAST=30,\t\t\t// 12\n\tMPH_MEDIUM_FASTER=35,\t\t// 14\n\tMPH_FAST=40,\t\t\t\t\t// 16\n\tMPH_ROCKET=60,\t\t\t\t\t// 24\n\tMPH_VERY_FAST=100,\t\t\t// 40\n\tMPH_LIGHT_SPEED=255\t\t\t// 100\n} MPHType;\n\n\n/**********************************************************************\n**\tThe houses that can be played are listed here. Each has their own\n**\tpersonality and strengths.\n*/\ntypedef enum HousesType {\n\tHOUSE_NONE=-1,\n\tHOUSE_SPAIN,\t\t\t\t//\tGold (unremapped)\n\tHOUSE_GREECE,\t\t\t\t// LtBlue\n\tHOUSE_USSR,\t\t\t\t\t// Red\n\tHOUSE_ENGLAND,\t\t\t\t// Green\n\tHOUSE_UKRAINE,\t\t\t\t// Orange\n\tHOUSE_GERMANY,\t\t\t\t// Grey\n\tHOUSE_FRANCE,\t\t\t\t// Blue\n\tHOUSE_TURKEY,\t\t\t\t// Brown\n\tHOUSE_GOOD,\t\t\t\t\t// Global Defense Initiative\n\tHOUSE_BAD,\t\t\t\t\t// Brotherhood of Nod\n\tHOUSE_NEUTRAL,\t\t\t\t// Civilians\n\tHOUSE_JP,\t\t\t\t\t// Disaster Containment Team\n\tHOUSE_MULTI1,\t\t\t\t// Multi-Player house #1\n\tHOUSE_MULTI2,\t\t\t\t// Multi-Player house #2\n\tHOUSE_MULTI3,\t\t\t\t// Multi-Player house #3\n\tHOUSE_MULTI4,\t\t\t\t// Multi-Player house #4\n\tHOUSE_MULTI5,\t\t\t\t// Multi-Player house #5\n\tHOUSE_MULTI6,\t\t\t\t// Multi-Player house #6\n\tHOUSE_MULTI7,\t\t\t\t// Multi-Player house #7\n\tHOUSE_MULTI8,\t\t\t\t// Multi-Player house #8\n\tHOUSE_COUNT,\n\tHOUSE_FIRST=0\n} HousesType;\n\ninline HousesType operator++(HousesType &, int);\n\n#define\tHOUSEF_ALLIES\t(HOUSEF_ENGLAND|HOUSEF_SPAIN|HOUSEF_GREECE|HOUSEF_GERMANY|HOUSEF_FRANCE|HOUSEF_TURKEY|HOUSEF_GOOD)\n#define\tHOUSEF_SOVIET\t(HOUSEF_USSR|HOUSEF_UKRAINE|HOUSEF_BAD)\n#define\tHOUSEF_OTHERS\t(HOUSEF_NEUTRAL|HOUSEF_JP|HOUSEF_MULTI1|HOUSEF_MULTI2|HOUSEF_MULTI3|HOUSEF_MULTI4|HOUSEF_MULTI5|HOUSEF_MULTI6|HOUSEF_MULTI7|HOUSEF_MULTI8)\n#define\tHOUSEF_NONE\t\t0\n\n#define\tHOUSEF_ENGLAND\t(1L<<HOUSE_ENGLAND)\n#define\tHOUSEF_SPAIN\t(1L<<HOUSE_SPAIN)\n#define\tHOUSEF_GREECE\t(1L<<HOUSE_GREECE)\n#define\tHOUSEF_USSR\t\t(1L<<HOUSE_USSR)\n#define\tHOUSEF_UKRAINE\t(1L<<HOUSE_UKRAINE)\n#define\tHOUSEF_GERMANY\t(1L<<HOUSE_GERMANY)\n#define\tHOUSEF_FRANCE\t(1L<<HOUSE_FRANCE)\n#define\tHOUSEF_TURKEY\t(1L<<HOUSE_TURKEY)\n#define\tHOUSEF_GOOD\t\t(1L<<HOUSE_GOOD)\n#define\tHOUSEF_BAD\t\t(1L<<HOUSE_BAD)\n#define\tHOUSEF_NEUTRAL\t(1L<<HOUSE_NEUTRAL)\n#define\tHOUSEF_JP\t\t(1L<<HOUSE_JP)\n#define\tHOUSEF_MULTI1\t(1L<<HOUSE_MULTI1)\n#define\tHOUSEF_MULTI2\t(1L<<HOUSE_MULTI2)\n#define\tHOUSEF_MULTI3\t(1L<<HOUSE_MULTI3)\n#define\tHOUSEF_MULTI4\t(1L<<HOUSE_MULTI4)\n#define\tHOUSEF_MULTI5\t(1L<<HOUSE_MULTI5)\n#define\tHOUSEF_MULTI6\t(1L<<HOUSE_MULTI6)\n#define\tHOUSEF_MULTI7\t(1L<<HOUSE_MULTI7)\n#define\tHOUSEF_MULTI8\t(1L<<HOUSE_MULTI8)\n\ntypedef enum PlayerColorType {\n\tPCOLOR_NONE = -1,\n\tPCOLOR_GOLD,\n\tPCOLOR_LTBLUE,\n\tPCOLOR_RED,\n\tPCOLOR_GREEN,\n\tPCOLOR_ORANGE,\n\tPCOLOR_GREY,\n\tPCOLOR_BLUE,\t\t//This is actually the red scheme used in the dialogs\n\tPCOLOR_BROWN,\n\tPCOLOR_TYPE,\n\tPCOLOR_REALLY_BLUE,\n\tPCOLOR_DIALOG_BLUE,\n\n\tPCOLOR_COUNT,\n\tPCOLOR_FIRST=0,\n\tPCOLOR_LAST=(int)PCOLOR_COUNT-1\n} PlayerColorType;\n\n\n/**********************************************************************\n**\tThis enumerates the remap logic to be applied to an object type when\n**\tit appears in the construction sidebar.\n*/\ntypedef enum RemapType {\n\tREMAP_NONE,\n\tREMAP_NORMAL,\n\tREMAP_ALTERNATE\n} RemapType;\n\n\n/**********************************************************************\n** These are the types of games that can be played.  GDI & NOD are the\n** usual human-vs-computer games; 2-Player games are network or modem,\n** with 2 players; multi-player games are network with > 2 players.\n*/\ntypedef enum ScenarioPlayerEnum\n{\n\tSCEN_PLAYER_NONE = -1,\n\tSCEN_PLAYER_SPAIN,\n\tSCEN_PLAYER_GREECE,\n\tSCEN_PLAYER_USSR,\n\tSCEN_PLAYER_JP,\n\tSCEN_PLAYER_2PLAYER,\n\tSCEN_PLAYER_MPLAYER,\n\tSCEN_PLAYER_COUNT,\n\tSCEN_PLAYER_FIRST = 0\n} ScenarioPlayerType;\n\ninline ScenarioPlayerType operator++(ScenarioPlayerType &, int);\n\n\n/**********************************************************************\n** These are the directional parameters for a scenario.\n*/\ntypedef enum ScenarioDirEnum\n{\n\tSCEN_DIR_NONE = -1,\n\tSCEN_DIR_EAST,\n\tSCEN_DIR_WEST,\n\tSCEN_DIR_COUNT,\n\tSCEN_DIR_FIRST = 0\n} ScenarioDirType;\n\ninline ScenarioDirType operator++(ScenarioDirType &, int);\n\n\n/**********************************************************************\n** These are the random variations of a scenario.\n*/\ntypedef enum ScenarioVarEnum\n{\n\tSCEN_VAR_NONE = -1,\n\tSCEN_VAR_A,\n\tSCEN_VAR_B,\n\tSCEN_VAR_C,\n\tSCEN_VAR_D,\n\tSCEN_VAR_COUNT,\t\t// comes before the Lose value!\n\tSCEN_VAR_LOSE,\n\tSCEN_VAR_FIRST = 0\n} ScenarioVarType;\n\ninline ScenarioVarType operator++(ScenarioVarType &, int);\n\n\n/**********************************************************************\n**\tThe objects to be drawn on the map are grouped into layers. These\n**\tenumerated values specify those layers. The ground layer is sorted\n**\tfrom back to front.\n*/\ntypedef enum LayerType {\n\tLAYER_NONE=-1,\n\tLAYER_SURFACE,\t\t// Flat on the ground (no sorting or apparent vertical height).\n\tLAYER_GROUND,\t\t// Touching the ground type object (units & buildings).\n\tLAYER_AIR,\t\t\t// Flying above the ground (explosions & flames).\n\tLAYER_TOP,\t\t\t// Topmost layer (aircraft & bullets).\n\n\tLAYER_COUNT,\n\tLAYER_FIRST=0\n} LayerType;\n\ninline LayerType operator++(LayerType &, int);\n\n\n/**********************************************************************\n**\tThis enumerates the various bullet types. These types specify bullet's\n**\tvisual and explosive characteristics.\n*/\ntypedef enum BulletType {\n\tBULLET_NONE=-1,\n\n\tBULLET_INVISIBLE,\n\tBULLET_CANNON,\n\tBULLET_ACK,\n\tBULLET_TORPEDO,\n\tBULLET_FROG,\n\tBULLET_HEAT_SEEKER,\n\tBULLET_LASER_GUIDED,\n\tBULLET_LOBBED,\n\tBULLET_BOMBLET,\n\tBULLET_BALLISTIC,\n\tBULLET_PARACHUTE,\n\tBULLET_FIREBALL,\n\tBULLET_DOG,\n\tBULLET_CATAPULT,\n\tBULLET_AAMISSILE,\n\tBULLET_GPS_SATELLITE,\n\tBULLET_NUKE_UP,\n\tBULLET_NUKE_DOWN,\n\n\tBULLET_COUNT,\n\tBULLET_FIRST=0\n} BulletType;\n\ninline BulletType operator++(BulletType &, int);\n\n\n/**********************************************************************\n**\tAll game buildings (structures) are enumerated here. This includes\n**\tcivilian structures as well.\n*/\ntypedef enum StructType {\n\tSTRUCT_NONE=-1,\n\tSTRUCT_ADVANCED_TECH,\n\tSTRUCT_IRON_CURTAIN,\n\tSTRUCT_WEAP,\n\tSTRUCT_CHRONOSPHERE,\n\tSTRUCT_PILLBOX,\n\tSTRUCT_CAMOPILLBOX,\n\tSTRUCT_RADAR,\n\tSTRUCT_GAP,\n\tSTRUCT_TURRET,\n\tSTRUCT_AAGUN,\n\tSTRUCT_FLAME_TURRET,\n\tSTRUCT_CONST,\n\tSTRUCT_REFINERY,\n\tSTRUCT_STORAGE,\n\tSTRUCT_HELIPAD,\n\tSTRUCT_SAM,\n\tSTRUCT_AIRSTRIP,\n\tSTRUCT_POWER,\n\tSTRUCT_ADVANCED_POWER,\n\tSTRUCT_SOVIET_TECH,\n\tSTRUCT_HOSPITAL,\n\tSTRUCT_BARRACKS,\n\tSTRUCT_TENT,\n\tSTRUCT_KENNEL,\n\tSTRUCT_REPAIR,\n\tSTRUCT_BIO_LAB,\n\tSTRUCT_MISSION,\n\tSTRUCT_SHIP_YARD,\n\tSTRUCT_SUB_PEN,\n\tSTRUCT_MSLO,\n\tSTRUCT_FORWARD_COM,\n\tSTRUCT_TESLA,\n\n\t/*\n\t**\tAll buildings that are never used as a prerequisite\n\t**\tfor construction, follow this point. Typically, this is\n\t**\tlimited to civilian structures. Also, the following\n\t**\tbuildings are NEVER used in the availability bit field\n\t**\trecord that each house maintains. i.e., STRUCTF_????\n\t**\tbit checking will never occur with the following\n\t**\tbuilding types.\n\t*/\n\tSTRUCT_FAKEWEAP,\n\tSTRUCT_FAKECONST,\n\tSTRUCT_FAKE_YARD,\n\tSTRUCT_FAKE_PEN,\n\tSTRUCT_FAKE_RADAR,\n\n\tSTRUCT_SANDBAG_WALL,\n\tSTRUCT_CYCLONE_WALL,\n\tSTRUCT_BRICK_WALL,\n\tSTRUCT_BARBWIRE_WALL,\n\tSTRUCT_WOOD_WALL,\n\tSTRUCT_FENCE,\n\n\tSTRUCT_AVMINE,\n\tSTRUCT_APMINE,\n\tSTRUCT_V01,\n\tSTRUCT_V02,\n\tSTRUCT_V03,\n\tSTRUCT_V04,\n\tSTRUCT_V05,\n\tSTRUCT_V06,\n\tSTRUCT_V07,\n\tSTRUCT_V08,\n\tSTRUCT_V09,\n\tSTRUCT_V10,\n\tSTRUCT_V11,\n\tSTRUCT_V12,\n\tSTRUCT_V13,\n\tSTRUCT_V14,\n\tSTRUCT_V15,\n\tSTRUCT_V16,\n\tSTRUCT_V17,\n\tSTRUCT_V18,\n\tSTRUCT_PUMP,\n\tSTRUCT_V20,\n\tSTRUCT_V21,\n\tSTRUCT_V22,\n\tSTRUCT_V23,\n\tSTRUCT_V24,\n\tSTRUCT_V25,\n\tSTRUCT_V26,\n\tSTRUCT_V27,\n\tSTRUCT_V28,\n\tSTRUCT_V29,\n\tSTRUCT_V30,\n\tSTRUCT_V31,\n\tSTRUCT_V32,\n\tSTRUCT_V33,\n\tSTRUCT_V34,\n\tSTRUCT_V35,\n\tSTRUCT_V36,\n\tSTRUCT_V37,\n\tSTRUCT_BARREL,\n\tSTRUCT_BARREL3,\n\n#ifdef FIXIT_ANTS\n\tSTRUCT_QUEEN,\n\tSTRUCT_LARVA1,\n\tSTRUCT_LARVA2,\n#endif\n\n\tSTRUCT_COUNT,\n\tSTRUCT_FIRST=0\n} StructType;\n\ninline StructType operator++(StructType &, int);\n\n#define\tSTRUCTF_NONE\t\t\t\t0L\n#define\tSTRUCTF_ADVANCED_TECH\t(1L << STRUCT_ADVANCED_TECH)\n#define\tSTRUCTF_IRON_CURTAIN\t\t(1L << STRUCT_IRON_CURTAIN)\n#define\tSTRUCTF_WEAP\t\t\t\t(1L << STRUCT_WEAP)\n#define\tSTRUCTF_CHRONOSPHERE\t\t(1L << STRUCT_CHRONOSPHERE)\n#define\tSTRUCTF_PILLBOX\t\t\t(1L << STRUCT_PILLBOX)\n#define\tSTRUCTF_CAMOPILLBOX\t\t(1L << STRUCT_CAMOPILLBOX)\n#define\tSTRUCTF_RADAR\t\t\t\t(1L << STRUCT_RADAR)\n#define\tSTRUCTF_GAP\t\t\t\t\t(1L << STRUCT_GAP)\n#define\tSTRUCTF_TURRET\t\t\t\t(1L << STRUCT_TURRET)\n#define\tSTRUCTF_AAGUN\t\t\t\t(1L << STRUCT_AAGUN)\n#define\tSTRUCTF_FLAME_TURRET\t\t(1L << STRUCT_FLAME_TURRET)\n#define\tSTRUCTF_CONST\t\t\t\t(1L << STRUCT_CONST)\n#define\tSTRUCTF_REFINERY\t\t\t(1L << STRUCT_REFINERY)\n#define\tSTRUCTF_STORAGE\t\t\t(1L << STRUCT_STORAGE)\n#define\tSTRUCTF_HELIPAD\t\t\t(1L << STRUCT_HELIPAD)\n#define\tSTRUCTF_SAM\t\t\t\t\t(1L << STRUCT_SAM)\n#define\tSTRUCTF_AIRSTRIP\t\t\t(1L << STRUCT_AIRSTRIP)\n#define\tSTRUCTF_POWER\t\t\t\t(1L << STRUCT_POWER)\n#define\tSTRUCTF_ADVANCED_POWER\t(1L << STRUCT_ADVANCED_POWER)\n#define\tSTRUCTF_SOVIET_TECH\t\t(1L << STRUCT_SOVIET_TECH)\n#define\tSTRUCTF_HOSPITAL\t\t\t(1L << STRUCT_HOSPITAL)\n#define\tSTRUCTF_BARRACKS\t\t\t(1L << STRUCT_BARRACKS)\n#define\tSTRUCTF_TENT\t\t\t\t(1L << STRUCT_TENT)\n#define\tSTRUCTF_KENNEL\t\t\t\t(1L << STRUCT_KENNEL)\n#define\tSTRUCTF_REPAIR\t\t\t\t(1L << STRUCT_REPAIR)\n#define\tSTRUCTF_BIO_LAB\t\t\t(1L << STRUCT_BIO_LAB)\n#define\tSTRUCTF_MISSION\t\t\t(1L << STRUCT_MISSION)\n#define\tSTRUCTF_SHIP_YARD\t\t\t(1L << STRUCT_SHIP_YARD)\n#define\tSTRUCTF_SUB_PEN\t\t\t(1L << STRUCT_SUB_PEN)\n#define\tSTRUCTF_MSLO\t\t\t\t(1L << STRUCT_MSLO)\n#define\tSTRUCTF_FAKECONST\t\t\t(1L << STRUCT_FAKECONST)\n#define\tSTRUCTF_FAKEWEAP\t\t\t(1L << STRUCT_FAKEWEAP)\n\n\n/**********************************************************************\n**\tThe overlays are enumerated here. An overlay functions similarly to\n**\ta transparent icon. It is placed over the terrain but usually falls\n**\t\"under\" buildings, trees, and units.\n*/\ntypedef enum OverlayType {\n\tOVERLAY_NONE=-1,\n\tOVERLAY_SANDBAG_WALL,\t// Piled sandbags.\n\tOVERLAY_CYCLONE_WALL,\t// Chain-link fence.\n\tOVERLAY_BRICK_WALL,\t\t// Solid concrete wall.\n\tOVERLAY_BARBWIRE_WALL,\t// Barbed-wire wall.\n\tOVERLAY_WOOD_WALL,\t\t// Wooden fence.\n\tOVERLAY_GOLD1,\n\tOVERLAY_GOLD2,\n\tOVERLAY_GOLD3,\n\tOVERLAY_GOLD4,\n\tOVERLAY_GEMS1,\n\tOVERLAY_GEMS2,\n\tOVERLAY_GEMS3,\n\tOVERLAY_GEMS4,\n\tOVERLAY_V12,\t\t\t\t// Haystacks\n\tOVERLAY_V13,\t\t\t\t// Haystack\n\tOVERLAY_V14,\t\t\t\t// Wheat field\n\tOVERLAY_V15,\t\t\t\t// Fallow field\n\tOVERLAY_V16,\t\t\t\t//\tCorn field\n\tOVERLAY_V17,\t\t\t\t// Celery field\n\tOVERLAY_V18,\t\t\t\t// Potato field\n\tOVERLAY_FLAG_SPOT,\t\t// Flag start location.\n\tOVERLAY_WOOD_CRATE,\t\t// Wooden goodie crate.\n\tOVERLAY_STEEL_CRATE,\t\t//\tSteel goodie crate.\n\tOVERLAY_FENCE,\t\t\t\t// New fangled fence.\n\tOVERLAY_WATER_CRATE,\t\t//\tWater goodie crate.\n\n\tOVERLAY_COUNT,\n\tOVERLAY_FIRST=0\n} OverlayType;\n\ninline OverlayType operator++(OverlayType &, int);\n\n\n/**********************************************************************\n**\tThis specifies the infantry in the game. The \"E\" designation is\n**\tsimilar to the army classification of enlisted soldiers.\n*/\ntypedef enum InfantryType{\n\tINFANTRY_NONE=-1,\n\tINFANTRY_E1,\t\t\t\t// Mini-gun armed.\n\tINFANTRY_E2,\t\t\t\t// Grenade thrower.\n\tINFANTRY_E3,\t\t\t\t// Rocket launcher.\n\tINFANTRY_E4,\t\t\t\t// Flame thrower equipped.\n\tINFANTRY_RENOVATOR,\t\t// Engineer.\n\tINFANTRY_TANYA,\t\t\t// Saboteur.\n\tINFANTRY_SPY,\t\t\t\t// Spy.\n\tINFANTRY_THIEF,\t\t\t// Thief.\n\tINFANTRY_MEDIC,\t\t\t// Field Medic.\n\tINFANTRY_GENERAL,\t\t\t// Field Marshal.\n\tINFANTRY_DOG,\t\t\t\t// Soviet attack dog\n\n\tINFANTRY_C1,\t\t\t\t// Civilian\n\tINFANTRY_C2,\t\t\t\t// Civilian\n\tINFANTRY_C3,\t\t\t\t// Civilian\n\tINFANTRY_C4,\t\t\t\t// Civilian\n\tINFANTRY_C5,\t\t\t\t// Civilian\n\tINFANTRY_C6,\t\t\t\t// Civilian\n\tINFANTRY_C7,\t\t\t\t// Civilian\n\tINFANTRY_C8,\t\t\t\t// Civilian\n\tINFANTRY_C9,\t\t\t\t// Civilian\n\tINFANTRY_C10,\t\t\t\t// Nikumba\n\tINFANTRY_EINSTEIN,\t\t// Einstein\n\tINFANTRY_DELPHI,\t\t\t// Agent \"Delphi\"\n\tINFANTRY_CHAN,\t\t\t\t// Dr. Chan\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// CounterStrike II only!\n\tINFANTRY_SHOCK,\t\t\t// Shock Trooper\n\tINFANTRY_MECHANIC,\n#endif\n\n\tINFANTRY_COUNT,\n\tINFANTRY_FIRST=0\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n,\n\tINFANTRY_RA_COUNT = INFANTRY_SHOCK\n#endif\n} InfantryType;\n\n#define INFANTRYF_DOG\t(1L << INFANTRY_DOG)\n\ninline InfantryType operator++(InfantryType &, int);\n\n\n/**********************************************************************\n**\tThe game units are enumerated here. These include not only traditional\n**\tvehicles, but also hovercraft and gunboats.\n*/\ntypedef enum UnitType{\n\tUNIT_NONE=-1,\n\tUNIT_HTANK,\t\t\t\t\t// Mammoth tank.\n\tUNIT_MTANK,\t\t\t\t\t// Heavy tank.\n\tUNIT_MTANK2,\t\t\t\t// Medium tank.\n\tUNIT_LTANK,\t\t\t\t\t// Light tank ('Bradly').\n\tUNIT_APC,\t\t\t\t\t// APC.\n\tUNIT_MINELAYER,\t\t\t// Mine-laying vehicle.\n\tUNIT_JEEP,\t\t\t\t\t// 4x4 jeep replacement.\n\tUNIT_HARVESTER,\t\t\t// Resource gathering vehicle.\n\tUNIT_ARTY,\t\t\t\t\t// Artillery unit.\n\tUNIT_MRJ,\t\t\t\t\t// Mobile Radar Jammer.\n\tUNIT_MGG,\t\t\t\t\t// Mobile Gap Generator\n\tUNIT_MCV,\t\t\t\t\t// Mobile construction vehicle.\n\tUNIT_V2_LAUNCHER,\t\t\t// V2 rocket launcher.\n\tUNIT_TRUCK,\t\t\t\t\t// Convoy truck\n\n#ifdef FIXIT_ANTS\n\tUNIT_ANT1,\t\t\t\t\t// Warrior ant.\n\tUNIT_ANT2,\t\t\t\t\t// Warrior ant.\n\tUNIT_ANT3,\t\t\t\t\t// Warrior ant.\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// CS II ONLY!\n\tUNIT_CHRONOTANK,\t\t\t// Chrono-shifting tank\n\tUNIT_TESLATANK,\t\t\t// Tesla-equipped tank\n\tUNIT_MAD,\t\t\t\t\t// Timequake tank\n\tUNIT_DEMOTRUCK,\t\t\t// Jihad truck\n#ifdef FIXIT_PHASETRANSPORT\t//\tchecked - ajw 9/28/98\n\tUNIT_PHASE,\t\t\t\t\t// cloaking APC for special missions\n#endif\n#endif\n\n\tUNIT_COUNT,\n\tUNIT_FIRST=0\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n,\n\tUNIT_RA_COUNT = UNIT_CHRONOTANK\n#endif\n} UnitType;\n\ninline UnitType operator++(UnitType &, int);\n\n#define\tUNITF_HTANK\t\t\t(1L<<UNIT_HTANK)\n#define\tUNITF_MTANK\t\t\t(1L<<UNIT_MTANK)\n#define\tUNITF_MTANK2\t\t(1L<<UNIT_MTANK2)\n#define\tUNITF_LTANK\t\t\t(1L<<UNIT_LTANK)\n#define\tUNITF_STANK\t\t\t(1L<<UNIT_STANK)\n#define\tUNITF_APC\t\t\t(1L<<UNIT_APC)\n#define\tUNITF_MLRS\t\t\t(1L<<UNIT_MLRS)\n#define\tUNITF_JEEP\t\t\t(1L<<UNIT_JEEP)\n#define\tUNITF_HARVESTER\t(1L<<UNIT_HARVESTER)\n#define\tUNITF_ARTY\t\t\t(1L<<UNIT_ARTY)\n#define\tUNITF_MCV\t\t\t(1L<<UNIT_MCV)\n\n\n/**********************************************************************\n**\tThe naval vessels are enumerated below.\n*/\ntypedef enum VesselType{\n\tVESSEL_NONE=-1,\n\n\tVESSEL_SS,\t\t\t\t\t\t// Submarine\n\tVESSEL_DD,\t\t\t\t\t\t// Medium weapon patrol craft\n\tVESSEL_CA,\t\t\t\t\t\t// Heavy weapon patrol craft\n\tVESSEL_TRANSPORT,\t\t\t\t// Unit transporter\n\tVESSEL_PT,\t\t\t\t\t\t// Light weapon patrol craft\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// CS II ONLY\n\tVESSEL_MISSILESUB,\t\t\t// Missile-equipped submarine\n#endif\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tVESSEL_CARRIER,\n#endif\n\n\tVESSEL_COUNT,\n\tVESSEL_FIRST=0\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n,\n\tVESSEL_RA_COUNT = VESSEL_MISSILESUB\n#endif\n} VesselType;\n\ninline VesselType operator++(VesselType &, int);\n\n#define\tVESSELF_SS\t\t\t(1L<<VESSEL_SS)\n#define\tVESSELF_DD\t\t\t(1L<<VESSEL_DD)\n#define\tVESSELF_CA\t\t\t(1L<<VESSEL_CA)\n#define\tVESSELF_TRANSPORT\t(1L<<VESSEL_TRANSPORT)\n#define\tVESSELF_PT\t\t\t(1L<<VESSEL_PT)\n\n\n/**********************************************************************\n**\tThe various aircraft types are enumerated here. These include helicopters\n**\tas well as traditional aircraft.\n*/\ntypedef enum AircraftType {\n\tAIRCRAFT_TRANSPORT,\t\t\t// Transport helicopter.\n\tAIRCRAFT_BADGER,\t\t\t\t// Badger bomber.\n\tAIRCRAFT_U2,\t\t\t\t\t// Photo recon plane.\n\tAIRCRAFT_MIG,\t\t\t\t\t// Mig attack plane.\n\tAIRCRAFT_YAK,\t\t\t\t\t// Yak attack plane.\n\tAIRCRAFT_LONGBOW,\t\t\t\t// Apache gunship.\n\tAIRCRAFT_HIND,\t\t\t\t\t// Soviet attach helicopter.\n\n\tAIRCRAFT_COUNT,\n\tAIRCRAFT_NONE=-1,\n\tAIRCRAFT_FIRST=0\n} AircraftType;\n\n#define\tAIRCRAFTF_TRANSPORT\t(1L << AIRCRAFT_TRANSPORT)\n#define\tAIRCRAFTF_BADGER\t\t(1L << AIRCRAFT_BADGER)\n#define\tAIRCRAFTF_U2\t\t\t(1L << AIRCRAFT_U2)\n#define\tAIRCRAFTF_MIG\t\t\t(1L << AIRCRAFT_MIG)\n#define\tAIRCRAFTF_YAK\t\t\t(1L << AIRCRAFT_YAK)\n#define\tAIRCRAFTF_LONGBOW\t\t(1L << AIRCRAFT_LONGBOW)\n#define\tAIRCRAFTF_HIND\t\t\t(1L << AIRCRAFT_HIND)\n\ninline AircraftType operator++(AircraftType &, int);\n\n\n/**********************************************************************\n**\tThe game templates are enumerated here. These are the underlying\n**\tterrain art. This includes everything from water to cliffs. If the\n**\tterrain is broken up into icons, is not transparent, and is drawn\n**\tas the bottom most layer, then it is a template.\n*/\ntypedef enum TemplateType {\n\tTEMPLATE_CLEAR1,\n\tTEMPLATE_WATER,\t\t\t// This must be the first non-clear template.\n\tTEMPLATE_WATER2,\n\tTEMPLATE_SHORE01,\n\tTEMPLATE_SHORE02,\n\tTEMPLATE_SHORE03,\n\tTEMPLATE_SHORE04,\n\tTEMPLATE_SHORE05,\n\tTEMPLATE_SHORE06,\n\tTEMPLATE_SHORE07,\n\tTEMPLATE_SHORE08,\n\tTEMPLATE_SHORE09,\n\tTEMPLATE_SHORE10,\n\tTEMPLATE_SHORE11,\n\tTEMPLATE_SHORE12,\n\tTEMPLATE_SHORE13,\n\tTEMPLATE_SHORE14,\n\tTEMPLATE_SHORE15,\n\tTEMPLATE_SHORE16,\n\tTEMPLATE_SHORE17,\n\tTEMPLATE_SHORE18,\n\tTEMPLATE_SHORE19,\n\tTEMPLATE_SHORE20,\n\tTEMPLATE_SHORE21,\n\tTEMPLATE_SHORE22,\n\tTEMPLATE_SHORE23,\n\tTEMPLATE_SHORE24,\n\tTEMPLATE_SHORE25,\n\tTEMPLATE_SHORE26,\n\tTEMPLATE_SHORE27,\n\tTEMPLATE_SHORE28,\n\tTEMPLATE_SHORE29,\n\tTEMPLATE_SHORE30,\n\tTEMPLATE_SHORE31,\n\tTEMPLATE_SHORE32,\n\tTEMPLATE_SHORE33,\n\tTEMPLATE_SHORE34,\n\tTEMPLATE_SHORE35,\n\tTEMPLATE_SHORE36,\n\tTEMPLATE_SHORE37,\n\tTEMPLATE_SHORE38,\n\tTEMPLATE_SHORE39,\n\tTEMPLATE_SHORE40,\n\tTEMPLATE_SHORE41,\n\tTEMPLATE_SHORE42,\n\tTEMPLATE_SHORE43,\n\tTEMPLATE_SHORE44,\n\tTEMPLATE_SHORE45,\n\tTEMPLATE_SHORE46,\n\tTEMPLATE_SHORE47,\n\tTEMPLATE_SHORE48,\n\tTEMPLATE_SHORE49,\n\tTEMPLATE_SHORE50,\n\tTEMPLATE_SHORE51,\n\tTEMPLATE_SHORE52,\n\tTEMPLATE_SHORE53,\n\tTEMPLATE_SHORE54,\n\tTEMPLATE_SHORE55,\n\tTEMPLATE_SHORE56,\n\tTEMPLATE_SHORECLIFF01,\n\tTEMPLATE_SHORECLIFF02,\n\tTEMPLATE_SHORECLIFF03,\n\tTEMPLATE_SHORECLIFF04,\n\tTEMPLATE_SHORECLIFF05,\n\tTEMPLATE_SHORECLIFF06,\n\tTEMPLATE_SHORECLIFF07,\n\tTEMPLATE_SHORECLIFF08,\n\tTEMPLATE_SHORECLIFF09,\n\tTEMPLATE_SHORECLIFF10,\n\tTEMPLATE_SHORECLIFF11,\n\tTEMPLATE_SHORECLIFF12,\n\tTEMPLATE_SHORECLIFF13,\n\tTEMPLATE_SHORECLIFF14,\n\tTEMPLATE_SHORECLIFF15,\n\tTEMPLATE_SHORECLIFF16,\n\tTEMPLATE_SHORECLIFF17,\n\tTEMPLATE_SHORECLIFF18,\n\tTEMPLATE_SHORECLIFF19,\n\tTEMPLATE_SHORECLIFF20,\n\tTEMPLATE_SHORECLIFF21,\n\tTEMPLATE_SHORECLIFF22,\n\tTEMPLATE_SHORECLIFF23,\n\tTEMPLATE_SHORECLIFF24,\n\tTEMPLATE_SHORECLIFF25,\n\tTEMPLATE_SHORECLIFF26,\n\tTEMPLATE_SHORECLIFF27,\n\tTEMPLATE_SHORECLIFF28,\n\tTEMPLATE_SHORECLIFF29,\n\tTEMPLATE_SHORECLIFF30,\n\tTEMPLATE_SHORECLIFF31,\n\tTEMPLATE_SHORECLIFF32,\n\tTEMPLATE_SHORECLIFF33,\n\tTEMPLATE_SHORECLIFF34,\n\tTEMPLATE_SHORECLIFF35,\n\tTEMPLATE_SHORECLIFF36,\n\tTEMPLATE_SHORECLIFF37,\n\tTEMPLATE_SHORECLIFF38,\n\tTEMPLATE_BOULDER1,\n\tTEMPLATE_BOULDER2,\n\tTEMPLATE_BOULDER3,\n\tTEMPLATE_BOULDER4,\n\tTEMPLATE_BOULDER5,\n\tTEMPLATE_BOULDER6,\n\tTEMPLATE_PATCH01,\n\tTEMPLATE_PATCH02,\n\tTEMPLATE_PATCH03,\n\tTEMPLATE_PATCH04,\n\tTEMPLATE_PATCH07,\n\tTEMPLATE_PATCH08,\n\tTEMPLATE_PATCH13,\n\tTEMPLATE_PATCH14,\n\tTEMPLATE_PATCH15,\n\tTEMPLATE_RIVER01,\n\tTEMPLATE_RIVER02,\n\tTEMPLATE_RIVER03,\n\tTEMPLATE_RIVER04,\n\tTEMPLATE_RIVER05,\n\tTEMPLATE_RIVER06,\n\tTEMPLATE_RIVER07,\n\tTEMPLATE_RIVER08,\n\tTEMPLATE_RIVER09,\n\tTEMPLATE_RIVER10,\n\tTEMPLATE_RIVER11,\n\tTEMPLATE_RIVER12,\n\tTEMPLATE_RIVER13,\n\tTEMPLATE_FALLS1,\n\tTEMPLATE_FALLS1A,\n\tTEMPLATE_FALLS2,\n\tTEMPLATE_FALLS2A,\n\tTEMPLATE_FORD1,\n\tTEMPLATE_FORD2,\n\tTEMPLATE_BRIDGE1,\n\tTEMPLATE_BRIDGE1D,\n\tTEMPLATE_BRIDGE2,\n\tTEMPLATE_BRIDGE2D,\n\tTEMPLATE_SLOPE01,\n\tTEMPLATE_SLOPE02,\n\tTEMPLATE_SLOPE03,\n\tTEMPLATE_SLOPE04,\n\tTEMPLATE_SLOPE05,\n\tTEMPLATE_SLOPE06,\n\tTEMPLATE_SLOPE07,\n\tTEMPLATE_SLOPE08,\n\tTEMPLATE_SLOPE09,\n\tTEMPLATE_SLOPE10,\n\tTEMPLATE_SLOPE11,\n\tTEMPLATE_SLOPE12,\n\tTEMPLATE_SLOPE13,\n\tTEMPLATE_SLOPE14,\n\tTEMPLATE_SLOPE15,\n\tTEMPLATE_SLOPE16,\n\tTEMPLATE_SLOPE17,\n\tTEMPLATE_SLOPE18,\n\tTEMPLATE_SLOPE19,\n\tTEMPLATE_SLOPE20,\n\tTEMPLATE_SLOPE21,\n\tTEMPLATE_SLOPE22,\n\tTEMPLATE_SLOPE23,\n\tTEMPLATE_SLOPE24,\n\tTEMPLATE_SLOPE25,\n\tTEMPLATE_SLOPE26,\n\tTEMPLATE_SLOPE27,\n\tTEMPLATE_SLOPE28,\n\tTEMPLATE_SLOPE29,\n\tTEMPLATE_SLOPE30,\n\tTEMPLATE_SLOPE31,\n\tTEMPLATE_SLOPE32,\n\tTEMPLATE_SLOPE33,\n\tTEMPLATE_SLOPE34,\n\tTEMPLATE_SLOPE35,\n\tTEMPLATE_SLOPE36,\n\tTEMPLATE_SLOPE37,\n\tTEMPLATE_SLOPE38,\n\tTEMPLATE_ROAD01,\n\tTEMPLATE_ROAD02,\n\tTEMPLATE_ROAD03,\n\tTEMPLATE_ROAD04,\n\tTEMPLATE_ROAD05,\n\tTEMPLATE_ROAD06,\n\tTEMPLATE_ROAD07,\n\tTEMPLATE_ROAD08,\n\tTEMPLATE_ROAD09,\n\tTEMPLATE_ROAD10,\n\tTEMPLATE_ROAD11,\n\tTEMPLATE_ROAD12,\n\tTEMPLATE_ROAD13,\n\tTEMPLATE_ROAD14,\n\tTEMPLATE_ROAD15,\n\tTEMPLATE_ROAD16,\n\tTEMPLATE_ROAD17,\n\tTEMPLATE_ROAD18,\n\tTEMPLATE_ROAD19,\n\tTEMPLATE_ROAD20,\n\tTEMPLATE_ROAD21,\n\tTEMPLATE_ROAD22,\n\tTEMPLATE_ROAD23,\n\tTEMPLATE_ROAD24,\n\tTEMPLATE_ROAD25,\n\tTEMPLATE_ROAD26,\n\tTEMPLATE_ROAD27,\n\tTEMPLATE_ROAD28,\n\tTEMPLATE_ROAD29,\n\tTEMPLATE_ROAD30,\n\tTEMPLATE_ROAD31,\n\tTEMPLATE_ROAD32,\n\tTEMPLATE_ROAD33,\n\tTEMPLATE_ROAD34,\n\tTEMPLATE_ROAD35,\n\tTEMPLATE_ROAD36,\n\tTEMPLATE_ROAD37,\n\tTEMPLATE_ROAD38,\n\tTEMPLATE_ROAD39,\n\tTEMPLATE_ROAD40,\n\tTEMPLATE_ROAD41,\n\tTEMPLATE_ROAD42,\n\tTEMPLATE_ROAD43,\n\tTEMPLATE_ROUGH01,\n\tTEMPLATE_ROUGH02,\n\tTEMPLATE_ROUGH03,\n\tTEMPLATE_ROUGH04,\n\tTEMPLATE_ROUGH05,\n\tTEMPLATE_ROUGH06,\n\tTEMPLATE_ROUGH07,\n\tTEMPLATE_ROUGH08,\n\tTEMPLATE_ROUGH09,\n\tTEMPLATE_ROUGH10,\n\tTEMPLATE_ROUGH11,\n\tTEMPLATE_ROAD44,\n\tTEMPLATE_ROAD45,\n\tTEMPLATE_RIVER14,\n\tTEMPLATE_RIVER15,\n\tTEMPLATE_RIVERCLIFF01,\n\tTEMPLATE_RIVERCLIFF02,\n\tTEMPLATE_RIVERCLIFF03,\n\tTEMPLATE_RIVERCLIFF04,\n\tTEMPLATE_BRIDGE_1A,\n\tTEMPLATE_BRIDGE_1B,\n\tTEMPLATE_BRIDGE_1C,\n\tTEMPLATE_BRIDGE_2A,\n\tTEMPLATE_BRIDGE_2B,\n\tTEMPLATE_BRIDGE_2C,\n\tTEMPLATE_BRIDGE_3A,\n\tTEMPLATE_BRIDGE_3B,\n\tTEMPLATE_BRIDGE_3C,\n\tTEMPLATE_BRIDGE_3D,\n\tTEMPLATE_BRIDGE_3E,\n\tTEMPLATE_BRIDGE_3F,\n\tTEMPLATE_F01,\n\tTEMPLATE_F02,\n\tTEMPLATE_F03,\n\tTEMPLATE_F04,\n\tTEMPLATE_F05,\n\tTEMPLATE_F06,\n\n\t// Custom interior pieces.\n\tTEMPLATE_ARRO0001,\n\tTEMPLATE_ARRO0002,\n\tTEMPLATE_ARRO0003,\n\tTEMPLATE_ARRO0004,\n\tTEMPLATE_ARRO0005,\n\tTEMPLATE_ARRO0006,\n\tTEMPLATE_ARRO0007,\n\tTEMPLATE_ARRO0008,\n\tTEMPLATE_ARRO0009,\n\tTEMPLATE_ARRO0010,\n\tTEMPLATE_ARRO0011,\n\tTEMPLATE_ARRO0012,\n\tTEMPLATE_ARRO0013,\n\tTEMPLATE_ARRO0014,\n\tTEMPLATE_ARRO0015,\n\tTEMPLATE_FLOR0001,\n\tTEMPLATE_FLOR0002,\n\tTEMPLATE_FLOR0003,\n\tTEMPLATE_FLOR0004,\n\tTEMPLATE_FLOR0005,\n\tTEMPLATE_FLOR0006,\n\tTEMPLATE_FLOR0007,\n\tTEMPLATE_GFLR0001,\n\tTEMPLATE_GFLR0002,\n\tTEMPLATE_GFLR0003,\n\tTEMPLATE_GFLR0004,\n\tTEMPLATE_GFLR0005,\n\tTEMPLATE_GSTR0001,\n\tTEMPLATE_GSTR0002,\n\tTEMPLATE_GSTR0003,\n\tTEMPLATE_GSTR0004,\n\tTEMPLATE_GSTR0005,\n\tTEMPLATE_GSTR0006,\n\tTEMPLATE_GSTR0007,\n\tTEMPLATE_GSTR0008,\n\tTEMPLATE_GSTR0009,\n\tTEMPLATE_GSTR0010,\n\tTEMPLATE_GSTR0011,\n\tTEMPLATE_LWAL0001,\n\tTEMPLATE_LWAL0002,\n\tTEMPLATE_LWAL0003,\n\tTEMPLATE_LWAL0004,\n\tTEMPLATE_LWAL0005,\n\tTEMPLATE_LWAL0006,\n\tTEMPLATE_LWAL0007,\n\tTEMPLATE_LWAL0008,\n\tTEMPLATE_LWAL0009,\n\tTEMPLATE_LWAL0010,\n\tTEMPLATE_LWAL0011,\n\tTEMPLATE_LWAL0012,\n\tTEMPLATE_LWAL0013,\n\tTEMPLATE_LWAL0014,\n\tTEMPLATE_LWAL0015,\n\tTEMPLATE_LWAL0016,\n\tTEMPLATE_LWAL0017,\n\tTEMPLATE_LWAL0018,\n\tTEMPLATE_LWAL0019,\n\tTEMPLATE_LWAL0020,\n\tTEMPLATE_LWAL0021,\n\tTEMPLATE_LWAL0022,\n\tTEMPLATE_LWAL0023,\n\tTEMPLATE_LWAL0024,\n\tTEMPLATE_LWAL0025,\n\tTEMPLATE_LWAL0026,\n\tTEMPLATE_LWAL0027,\n\tTEMPLATE_STRP0001,\n\tTEMPLATE_STRP0002,\n\tTEMPLATE_STRP0003,\n\tTEMPLATE_STRP0004,\n\tTEMPLATE_STRP0005,\n\tTEMPLATE_STRP0006,\n\tTEMPLATE_STRP0007,\n\tTEMPLATE_STRP0008,\n\tTEMPLATE_STRP0009,\n\tTEMPLATE_STRP0010,\n\tTEMPLATE_STRP0011,\n\tTEMPLATE_WALL0001,\n\tTEMPLATE_WALL0002,\n\tTEMPLATE_WALL0003,\n\tTEMPLATE_WALL0004,\n\tTEMPLATE_WALL0005,\n\tTEMPLATE_WALL0006,\n\tTEMPLATE_WALL0007,\n\tTEMPLATE_WALL0008,\n\tTEMPLATE_WALL0009,\n\tTEMPLATE_WALL0010,\n\tTEMPLATE_WALL0011,\n\tTEMPLATE_WALL0012,\n\tTEMPLATE_WALL0013,\n\tTEMPLATE_WALL0014,\n\tTEMPLATE_WALL0015,\n\tTEMPLATE_WALL0016,\n\tTEMPLATE_WALL0017,\n\tTEMPLATE_WALL0018,\n\tTEMPLATE_WALL0019,\n\tTEMPLATE_WALL0020,\n\tTEMPLATE_WALL0021,\n\tTEMPLATE_WALL0022,\n\tTEMPLATE_WALL0023,\n\tTEMPLATE_WALL0024,\n\tTEMPLATE_WALL0025,\n\tTEMPLATE_WALL0026,\n\tTEMPLATE_WALL0027,\n\tTEMPLATE_WALL0028,\n\tTEMPLATE_WALL0029,\n\tTEMPLATE_WALL0030,\n\tTEMPLATE_WALL0031,\n\tTEMPLATE_WALL0032,\n\tTEMPLATE_WALL0033,\n\tTEMPLATE_WALL0034,\n\tTEMPLATE_WALL0035,\n\tTEMPLATE_WALL0036,\n\tTEMPLATE_WALL0037,\n\tTEMPLATE_WALL0038,\n\tTEMPLATE_WALL0039,\n\tTEMPLATE_WALL0040,\n\tTEMPLATE_WALL0041,\n\tTEMPLATE_WALL0042,\n\tTEMPLATE_WALL0043,\n\tTEMPLATE_WALL0044,\n\tTEMPLATE_WALL0045,\n\tTEMPLATE_WALL0046,\n\tTEMPLATE_WALL0047,\n\tTEMPLATE_WALL0048,\n\tTEMPLATE_WALL0049,\n\tTEMPLATE_BRIDGE1H,\n\tTEMPLATE_BRIDGE2H,\n\tTEMPLATE_BRIDGE_1AX,\n\tTEMPLATE_BRIDGE_2AX,\n\tTEMPLATE_BRIDGE1X,\n\tTEMPLATE_BRIDGE2X,\n\n\tTEMPLATE_XTRA0001,\n\tTEMPLATE_XTRA0002,\n\tTEMPLATE_XTRA0003,\n\tTEMPLATE_XTRA0004,\n\tTEMPLATE_XTRA0005,\n\tTEMPLATE_XTRA0006,\n\tTEMPLATE_XTRA0007,\n\tTEMPLATE_XTRA0008,\n\tTEMPLATE_XTRA0009,\n\tTEMPLATE_XTRA0010,\n\tTEMPLATE_XTRA0011,\n\tTEMPLATE_XTRA0012,\n\tTEMPLATE_XTRA0013,\n\tTEMPLATE_XTRA0014,\n\tTEMPLATE_XTRA0015,\n\tTEMPLATE_XTRA0016,\n\n#ifdef FIXIT_ANTS\n\tTEMPLATE_HILL01,\n#endif\n\n\n\tTEMPLATE_COUNT,\n\tTEMPLATE_NONE=65535,\n\tTEMPLATE_FIRST=0\n} TemplateType;\n\ninline TemplateType operator++(TemplateType &, int);\n\n\n/**********************************************************************\n**\tThe three dimensional terrain objects are enumerated here. These\n**\tobjects function similar to buildings in that they can be driven\n**\tbehind and can take damage on an individual basis.\n*/\ntypedef enum TerrainType {\n\tTERRAIN_NONE=-1,\n\tTERRAIN_TREE1,\n\tTERRAIN_TREE2,\n\tTERRAIN_TREE3,\n\tTERRAIN_TREE5,\n\tTERRAIN_TREE6,\n\tTERRAIN_TREE7,\n\tTERRAIN_TREE8,\n\tTERRAIN_TREE10,\n\tTERRAIN_TREE11,\n\tTERRAIN_TREE12,\n\tTERRAIN_TREE13,\n\tTERRAIN_TREE14,\n\tTERRAIN_TREE15,\n\tTERRAIN_TREE16,\n\tTERRAIN_TREE17,\n\tTERRAIN_CLUMP1,\n\tTERRAIN_CLUMP2,\n\tTERRAIN_CLUMP3,\n\tTERRAIN_CLUMP4,\n\tTERRAIN_CLUMP5,\n\n\tTERRAIN_ICE01,\n\tTERRAIN_ICE02,\n\tTERRAIN_ICE03,\n\tTERRAIN_ICE04,\n\tTERRAIN_ICE05,\n\n\tTERRAIN_BOXES01,\n\tTERRAIN_BOXES02,\n\tTERRAIN_BOXES03,\n\tTERRAIN_BOXES04,\n\tTERRAIN_BOXES05,\n\tTERRAIN_BOXES06,\n\tTERRAIN_BOXES07,\n\tTERRAIN_BOXES08,\n\tTERRAIN_BOXES09,\n\n\tTERRAIN_MINE,\n\n\tTERRAIN_COUNT,\n\tTERRAIN_FIRST=0\n} TerrainType;\n\ninline TerrainType operator++(TerrainType &, int);\n\n\n/**********************************************************************\n**\tSmudges are enumerated here. Smudges are transparent icons that are\n**\tdrawn over the underlying terrain in order to give the effect of\n**\talterations to the terrain. Craters are a good example of this.\n*/\ntypedef enum SmudgeType {\n\tSMUDGE_NONE=-1,\n\tSMUDGE_CRATER1,\n\tSMUDGE_CRATER2,\n\tSMUDGE_CRATER3,\n\tSMUDGE_CRATER4,\n\tSMUDGE_CRATER5,\n\tSMUDGE_CRATER6,\n\tSMUDGE_SCORCH1,\n\tSMUDGE_SCORCH2,\n\tSMUDGE_SCORCH3,\n\tSMUDGE_SCORCH4,\n\tSMUDGE_SCORCH5,\n\tSMUDGE_SCORCH6,\n\tSMUDGE_BIB1,\n\tSMUDGE_BIB2,\n\tSMUDGE_BIB3,\n\n\tSMUDGE_COUNT,\n\tSMUDGE_FIRST=0\n} SmudgeType;\n\ninline SmudgeType operator++(SmudgeType &, int);\n\n\n/**********************************************************************\n**\tAnimations are enumerated here. Animations are the high speed and\n**\tshort lived effects that occur with explosions and fire.\n*/\ntypedef enum AnimType {\n\tANIM_NONE=-1,\n\tANIM_FBALL1,\t\t\t\t\t// Large fireball explosion (bulges rightward).\n\tANIM_FBALL_FADE,\t\t\t\t// Fading fireball puff.\n\tANIM_FRAG1,\t\t\t\t\t\t// Medium fragment throwing explosion -- short decay.\n\tANIM_VEH_HIT1,\t\t\t\t\t//\tSmall fireball explosion (bulges rightward).\n\tANIM_VEH_HIT2,\t\t\t\t\t//\tSmall fragment throwing explosion -- pop & sparkles.\n\tANIM_VEH_HIT3,\t\t\t\t\t// Small fragment throwing explosion -- burn/exp mix.\n\tANIM_ART_EXP1,\t\t\t\t\t// Large fragment throwing explosion -- many sparkles.\n\tANIM_NAPALM1,\t\t\t\t\t// Small napalm burn.\n\tANIM_NAPALM2,\t\t\t\t\t// Medium napalm burn.\n\tANIM_NAPALM3,\t\t\t\t\t// Large napalm burn.\n\tANIM_SMOKE_PUFF,\t\t\t\t// Small rocket smoke trail puff.\n\tANIM_PIFF,\t\t\t\t\t\t// Machine gun impact piffs.\n\tANIM_PIFFPIFF,\t\t\t\t\t// Chaingun impact piffs.\n\tANIM_FIRE_SMALL,\t\t\t\t// Small flame animation.\n\tANIM_FIRE_MED,\t\t\t\t\t// Medium flame animation.\n\tANIM_FIRE_MED2,\t\t\t\t// Medium flame animation (oranger).\n\tANIM_FIRE_TINY,\t\t\t\t// Very tiny flames.\n\tANIM_MUZZLE_FLASH,\t\t\t// Big cannon flash (with translucency).\n\tANIM_SMOKE_M,\t\t\t\t\t// Smoke rising from ground.\n\tANIM_BURN_SMALL,\t\t\t\t// Small combustible fire effect (with trail off).\n\tANIM_BURN_MED,\t\t\t\t\t// Medium combustible fire effect (with trail off).\n\tANIM_BURN_BIG,\t\t\t\t\t// Large combustible fire effect (with trail off).\n\tANIM_ON_FIRE_SMALL,\t\t\t// Burning effect for buildings.\n\tANIM_ON_FIRE_MED,\t\t\t\t// Burning effect for buildings.\n\tANIM_ON_FIRE_BIG,\t\t\t\t// Burning effect for buildings.\n\tANIM_SAM_N,\n\tANIM_SAM_NE,\n\tANIM_SAM_E,\n\tANIM_SAM_SE,\n\tANIM_SAM_S,\n\tANIM_SAM_SW,\n\tANIM_SAM_W,\n\tANIM_SAM_NW,\n\tANIM_GUN_N,\n\tANIM_GUN_NE,\n\tANIM_GUN_E,\n\tANIM_GUN_SE,\n\tANIM_GUN_S,\n\tANIM_GUN_SW,\n\tANIM_GUN_W,\n\tANIM_GUN_NW,\n\tANIM_LZ_SMOKE,\n\tANIM_CRATE_DEVIATOR,\t\t\t// Red finned missile.\n\tANIM_CRATE_DOLLAR,\t\t\t// Dollar sign.\n\tANIM_CRATE_EARTH,\t\t\t\t// Cracked Earth.\n\tANIM_CRATE_EMPULSE,\t\t\t// Plasma ball.\n\tANIM_CRATE_INVUN,\t\t\t\t// Orange sphere with green rings.\n\tANIM_CRATE_MINE,\t\t\t\t// Spiked mine.\n\tANIM_CRATE_RAPID,\t\t\t\t// Red skull.\n\tANIM_CRATE_STEALTH,\t\t\t// Cloaking sphere.\n\tANIM_CRATE_MISSILE,\t\t\t// Green finned missile.\n\tANIM_MOVE_FLASH,\n\tANIM_OILFIELD_BURN,\n\tANIM_ELECT_DIE,\t\t\t\t// Electrocution infantryman death from Tesla coil\n\tANIM_PARACHUTE,\t\t\t\t// Parachute (designed to be attached to object).\n\tANIM_DOG_ELECT_DIE,\t\t\t// Electrocution dog death from Tesla coil\n\tANIM_CORPSE1,\n\tANIM_CORPSE2,\n\tANIM_CORPSE3,\n\tANIM_SPUTDOOR,\n\tANIM_ATOM_BLAST,\n\tANIM_CHRONO_BOX,\n\tANIM_GPS_BOX,\n\tANIM_INVUL_BOX,\n\tANIM_PARA_BOX,\n\tANIM_SONAR_BOX,\n\tANIM_TWINKLE1,\n\tANIM_TWINKLE2,\n\tANIM_TWINKLE3,\n\tANIM_FLAK,\n\tANIM_WATER_EXP1,\n\tANIM_WATER_EXP2,\n\tANIM_WATER_EXP3,\n\tANIM_CRATE_ARMOR,\n\tANIM_CRATE_SPEED,\n\tANIM_CRATE_FPOWER,\n\tANIM_CRATE_TQUAKE,\n\tANIM_PARA_BOMB,\n\tANIM_MINE_EXP1,\n\n#ifdef FIXIT_ANTS\n\tANIM_ANT_DEATH,\n#endif\n\n\n\tANIM_COUNT,\n\tANIM_FIRST=0\n} AnimType;\n\n\ninline AnimType operator++(AnimType &, int);\n\n\n/****************************************************************************\n**\tInfantry can be performing various activities. These can range from simple\n**\tidle animations to physical hand to hand combat.\n*/\ntypedef enum DoType {\n\tDO_NOTHING=-1,\t\t\t\t// Not performing any choreographed sequence.\n\tDO_STAND_READY=0,\n\tDO_STAND_GUARD,\n\tDO_PRONE,\n\tDO_WALK,\n\tDO_FIRE_WEAPON,\n\tDO_LIE_DOWN,\n\tDO_CRAWL,\n\tDO_GET_UP,\n\tDO_FIRE_PRONE,\n\tDO_IDLE1,\n\tDO_IDLE2,\n\tDO_GUN_DEATH,\n\tDO_EXPLOSION_DEATH,\n\tDO_EXPLOSION2_DEATH,\n\tDO_GRENADE_DEATH,\n\tDO_FIRE_DEATH,\n\tDO_GESTURE1,\n\tDO_SALUTE1,\n\tDO_GESTURE2,\n\tDO_SALUTE2,\n\tDO_DOG_MAUL,\n\n\tDO_COUNT,\n\tDO_FIRST=0\n} DoType;\n\ninline DoType operator++(DoType &, int);\n\n/*\n**\tThis structure is associated with each maneuver type. It tells whether the\n**\tmaneuver can be interrupted and the frame rate.\n*/\ntypedef struct {\n\tunsigned Interrupt:1;\t// Can it be interrupted?\n\tunsigned IsMobile:1;\t\t// Can it move while doing this?\n\tunsigned RandomStart:1;\t// Should animation be \"randomized\"?\n\tunsigned char Rate;\t\t// Frame rate.\n} DoStruct;\n\ntypedef struct {\n\tint\t\t\t\tFrame;\t// Starting frame of the animation.\n\tunsigned char\tCount;\t// Number of frames of animation.\n\tunsigned char\tJump;\t\t// Frames to jump between facings.\n} DoInfoStruct;\n\n\n/****************************************************************************\n**\tThese are the various radio message that can be transmitted between\n**\tunits and buildings. Some of these require a response from the receiver\n**\tand some don't.\n*/\ntypedef enum RadioMessageType {\n\tRADIO_STATIC,\t\t\t\t// \"hisssss\" -- non-message\n\tRADIO_ROGER,\t\t\t\t// \"Roger.\"\n\tRADIO_HELLO,\t\t\t\t// \"Come in. I wish to talk.\"\n\tRADIO_OVER_OUT,\t\t\t// \"Something came up, bye.\"\n\tRADIO_PICK_UP,\t\t\t\t// \"Please pick me up.\"\n\tRADIO_ATTACH,\t\t\t\t// \"Attach to transport.\"\n\tRADIO_DELIVERY,\t\t\t// \"I've got a delivery for you.\"\n\tRADIO_HOLD_STILL,\t\t\t// \"I'm performing load/unload maneuver. Be careful.\"\n\tRADIO_UNLOADED,\t\t\t// \"I'm clear.\"\n\tRADIO_UNLOAD,\t\t\t\t// \"You are clear to unload. Please start driving off now.\"\n\tRADIO_NEGATIVE,\t\t\t// \"Am unable to comply.\"\n\tRADIO_BUILDING,\t\t\t// \"I'm starting construction now... act busy.\"\n\tRADIO_COMPLETE,\t\t\t// \"I've finished construction. You are free.\"\n\tRADIO_REDRAW,\t\t\t\t// \"Oops, sorry. I might have bumped you a little.\"\n\tRADIO_DOCKING,\t\t\t\t// \"I'm trying to load up now.\"\n\tRADIO_CAN_LOAD,\t\t\t// \"May I become a passenger?\"\n\tRADIO_ARE_REFINERY,\t\t// \"Are you a refinery ready to take shipment?\"\n\tRADIO_TRYING_TO_LOAD,\t// \"Are you trying to become a passenger?\"\n\tRADIO_MOVE_HERE,\t\t\t// \"Move to location X.\"\n\tRADIO_NEED_TO_MOVE,\t\t// \"Do you need to move somewhere?\"\n\tRADIO_YEA_NOW_WHAT,\t\t// \"All right already. Now what?\"\n\tRADIO_IM_IN,\t\t\t\t// \"I'm a passenger now.\"\n\tRADIO_BACKUP_NOW,\t\t\t// \"Begin backup into refinery now.\"\n\tRADIO_RUN_AWAY,\t\t\t// \"Run away! Run away!\"\n\tRADIO_TETHER,\t\t\t\t// \"Establish tether contact.\"\n\tRADIO_UNTETHER,\t\t\t// \"Break tether contact.\"\n\tRADIO_REPAIR,\t\t\t\t// \"Repair one step.\"\n\tRADIO_PREPARED,\t\t\t// \"Are you prepared to fight?\"\n\tRADIO_ATTACK_THIS,\t\t// \"Attack this target please.\"\n\tRADIO_RELOAD,\t\t\t\t// \"Reload one step please.\"\n\tRADIO_CANT,\t\t\t\t\t// \"Circumstances prevent success.\"\n\tRADIO_ALL_DONE,\t\t\t// \"I have completed the task.\"\n\tRADIO_NEED_REPAIR,\t\t// \"Are you in need of service depot work?\"\n\tRADIO_ON_DEPOT,\t\t\t// \"Are you sitting on a service depot?\"\n\n\tRADIO_COUNT\n} RadioMessageType;\n\n\n/****************************************************************************\n**\tVarious trigger events and actions require additional data. This enumeration is\n**\tused to indicate what kind of additional data is required. This is also used\n**\tfor team mission types that might need additional data.\n*/\ntypedef enum NeedType {\n\tNEED_NONE,\t\t\t\t\t// No additional data is required.\n\tNEED_THEME,\t\t\t\t\t// Need a musical theme.\n\tNEED_MOVIE,\t\t\t\t\t// Need a movie to play.\n\tNEED_SOUND,\t\t\t\t\t// Sound effect.\n\tNEED_SPEECH,\t\t\t\t// Speech from EVA.\n\tNEED_INFANTRY,\t\t\t\t// Infantry type class.\n\tNEED_UNIT,\t\t\t\t\t// Unit type class.\n\tNEED_AIRCRAFT,\t\t\t\t// Aircraft type class.\n\tNEED_STRUCTURE,\t\t\t// Structure type class.\n\tNEED_WAYPOINT,\t\t\t\t// Waypoint letter.\n\tNEED_NUMBER,\t\t\t\t// General number.\n\tNEED_TRIGGER,\t\t\t\t//\tTrigger object reference.\n\tNEED_TEAM,\t\t\t\t\t// Team type class.\n\tNEED_HOUSE,\t\t\t\t\t// House type number.\n\tNEED_TIME,\t\t\t\t\t// Time delay value required.\n\tNEED_QUARRY,\t\t\t\t// Quarry type is needed.\n\tNEED_FORMATION,\t\t\t// A formation type is needed.\n\tNEED_BOOL,\t\t\t\t\t// Boolean value is needed.\n\tNEED_SPECIAL,\t\t\t\t// Special weapon ability.\n\tNEED_MISSION,\t\t\t\t// General unit mission type.\n\tNEED_HEX_NUMBER\t\t\t// General number.\n} NeedType;\n\n\n/****************************************************************************\n**\tThere are various target types that teams and special weapons can be\n**\tassigned to attack. These are general target categories since the actual\n**\tdisposition of potential targets cannot be precisely predicted -- thus these\n**\tserve as guidelines for the computer AI.\n*/\ntypedef enum QuarryType {\n\tQUARRY_NONE,\n\n\tQUARRY_ANYTHING,\t\t\t\t\t// Attack any enemy (same as \"hunt\").\n\tQUARRY_BUILDINGS,\t\t\t\t\t// Attack buildings (in general).\n\tQUARRY_HARVESTERS,\t\t\t\t// Attack harvesters or refineries.\n\tQUARRY_INFANTRY,\t\t\t\t\t// Attack infantry.\n\tQUARRY_VEHICLES,\t\t\t\t\t// Attack combat vehicles.\n\tQUARRY_VESSELS,\t\t\t\t\t// Attach ships.\n\tQUARRY_FACTORIES,\t\t\t\t\t// Attack factories (all types).\n\tQUARRY_DEFENSE,\t\t\t\t\t// Attack base defense buildings.\n\tQUARRY_THREAT,\t\t\t\t\t\t// Attack enemies near friendly base.\n\tQUARRY_POWER,\t\t\t\t\t\t// Attack power facilities.\n\tQUARRY_FAKES,\t\t\t\t\t\t// Prefer to attack fake buildings.\n\n\tQUARRY_COUNT,\n\tQUARRY_FIRST=0\n} QuarryType;\n\n\n/****************************************************************************\n**\tTeams can be assigned formations. This specifies the various formations that\n**\ta team can be composed into.\n*/\ntypedef enum FormationType {\n\tFORMATION_NONE,\n\n\tFORMATION_TIGHT,\t\t\t\t// Tight grouping (vulnerable units in center).\n\tFORMATION_LOOSE,\t\t\t\t// Loose grouping (one cell separation between units).\n\tFORMATION_WEDGE_N,\t\t\t// Wedge shape.\n\tFORMATION_WEDGE_E,\t\t\t// Wedge shape.\n\tFORMATION_WEDGE_S,\t\t\t// Wedge shape.\n\tFORMATION_WEDGE_W,\t\t\t// Wedge shape.\n\tFORMATION_LINE_NS,\t\t\t// Column formation.\n\tFORMATION_LINE_EW,\t\t\t// Line formation.\n\n\tFORMATION_COUNT,\n\tFORMATION_FIRST=0\n} FormationType;\n\n\n/****************************************************************************\n**\tSelected units have a special selected unit box around them. These are the\n**\tdefines for the two types of selected unit boxes. One is for infantry and\n**\tthe other is for regular units.\n*/\ntypedef enum SelectEnum {\n\tSELECT_NONE=-1,\n\tSELECT_INFANTRY,\t\t\t\t\t// Small infantry selection box.\n\tSELECT_UNIT,\t\t\t\t\t\t// Big unit selection box.\n\tSELECT_BUILDING=SELECT_UNIT,\t// Custom box for buildings.\n\tSELECT_TERRAIN=SELECT_UNIT,\t// Custom box for terrain objects.\n\tSELECT_WRENCH,\t\t\t\t\t\t// A building is repairing overlay graphic.\n\n\tSELECT_COUNT\n} SelectEnum;\n\n\n/****************************************************************************\n**\tThe pip shapes and text shapes are enumerated according to the following\n**\ttype. These special shapes are drawn over special objects or in other places\n**\twhere shape technology is needed.\n*/\ntypedef enum PipEnum\n{\n\tPIP_EMPTY,\t\t\t// Empty pip spot.\n\tPIP_FULL,\t\t\t// Full pip spot.\n\tPIP_PRIMARY,\t\t// \"Primary\" building marker.\n\tPIP_READY,\t\t\t// \"Ready\" construction information tag.\n\tPIP_HOLDING,\t\t// \"Hold\"ing construction information tag.\n\tPIP_ENGINEER,\t\t// Full pip with engineer coloring.\n\tPIP_CIVILIAN,\t\t// Full pip with civilian coloring.\n\tPIP_COMMANDO,\t\t// Full pip with commando coloring.\n\tPIP_NUMBERS,\t\t// digit 0\n\tPIP_NUMBER1,\t\t// digit 1\n\tPIP_NUMBER2,\t\t// digit 2\n\tPIP_NUMBER3,\t\t// digit 3\n\tPIP_NUMBER4,\t\t// digit 4\n\tPIP_NUMBER5,\t\t// digit 5\n\tPIP_NUMBER6,\t\t// digit 6\n\tPIP_NUMBER7,\t\t// digit 7\n\tPIP_NUMBER8,\t\t// digit 8\n\tPIP_NUMBER9,\t\t// digit 9\n\tPIP_DECOY,\t\t\t// word \"Decoy\" for fake buildings\n\tPIP_LETTERF,\t\t// letter 'F' for signifying in-formation\n\tPIP_MEDIC,\t\t\t// Little medic red cross.\n\tPIP_PRI\t\t\t\t// Abbreviated \"Primary\" for kennel\n} PipEnum;\n\n\n/****************************************************************************\n**\tThe mouse cursor can be in different states. These states are listed\n**\tbelow. Some of these represent animating mouse cursors. The mouse\n**\tis controlled by passing one of these values to the appropriate\n**\tMouseClass member function.\n*/\ntypedef enum MouseType\n{\n\tMOUSE_NORMAL,\n\tMOUSE_N,\n\tMOUSE_NE,\n\tMOUSE_E,\n\tMOUSE_SE,\n\tMOUSE_S,\n\tMOUSE_SW,\n\tMOUSE_W,\n\tMOUSE_NW,\n\tMOUSE_NO_N,\n\tMOUSE_NO_NE,\n\tMOUSE_NO_E,\n\tMOUSE_NO_SE,\n\tMOUSE_NO_S,\n\tMOUSE_NO_SW,\n\tMOUSE_NO_W,\n\tMOUSE_NO_NW,\n\tMOUSE_NO_MOVE,\n\tMOUSE_CAN_MOVE,\n\tMOUSE_ENTER,\n\tMOUSE_DEPLOY,\n\tMOUSE_CAN_SELECT,\n\tMOUSE_CAN_ATTACK,\n\tMOUSE_SELL_BACK,\n\tMOUSE_SELL_UNIT,\n\tMOUSE_REPAIR,\n\tMOUSE_NO_REPAIR,\n\tMOUSE_NO_SELL_BACK,\n\tMOUSE_RADAR_CURSOR,\n\tMOUSE_NUCLEAR_BOMB,\n\tMOUSE_AIR_STRIKE,\n\tMOUSE_DEMOLITIONS,\n\tMOUSE_AREA_GUARD,\n\tMOUSE_HEAL,\n\tMOUSE_DAMAGE,\t\t\t\t\t// Engineer entering building to damage it.\n\tMOUSE_GREPAIR,\t\t\t\t\t// Engineer entering friendly building to heal it.\n\tMOUSE_STAY_ATTACK,\n\tMOUSE_NO_DEPLOY,\n\tMOUSE_NO_ENTER,\n\tMOUSE_NO_GREPAIR,\n\tMOUSE_CHRONO_SELECT,\n\tMOUSE_CHRONO_DEST,\n\n\tMOUSE_COUNT\n} MouseType;\n\n\n/**********************************************************************\n**\tThis structure is used to control the box relief style drawn by\n**\tthe Draw_Box() function.\n*/\ntypedef struct {\n\tint\tFiller;\t\t// Center box fill color.\n\tint\tShadow;\t\t// Shadow color (darker).\n\tint\tHighlight;\t// Highlight color (lighter).\n\tint\tCorner;\t\t// Corner color (transition).\n} BoxStyleType;\n\ntypedef enum BoxStyleEnum {\n\tBOXSTYLE_DOWN,\t\t\t\t\t// Typical depressed edge border.\n\tBOXSTYLE_RAISED,\t\t\t\t// Typical raised edge border.\n\tBOXSTYLE_DIS_DOWN,\t\t\t// Disabled but depressed.\n\tBOXSTYLE_DIS_RAISED,\t\t\t// Disabled but raised.\n\tBOXSTYLE_BOX,\t\t\t\t\t// list box.\n\tBOXSTYLE_BORDER,\t\t\t\t// main dialog box.\n\n\tBOXSTYLE_COUNT\n} BoxStyleEnum;\n\n\n/**********************************************************************\n**\tDamage, as inflicted by projectiles, has different characteristics.\n**\tThese are the different \"warhead\" types that can be assigned to the\n**\tvarious projectiles in the game.\n*/\ntypedef enum WarheadType{\n\tWARHEAD_NONE=-1,\n\n\tWARHEAD_SA,\t\t\t\t\t// Small arms -- good against infantry.\n\tWARHEAD_HE,\t\t\t\t\t//\tHigh explosive -- good against buildings & infantry.\n\tWARHEAD_AP,\t\t\t\t\t// Armor piercing -- good against armor.\n\tWARHEAD_FIRE,\t\t\t\t// Incendiary -- Good against flammables.\n\tWARHEAD_HOLLOW_POINT,\t// Sniper bullet type.\n\tWARHEAD_TESLA,\t\t\t\t// Electrocution warhead for infantrymen\n\tWARHEAD_DOG,\t\t\t\t// Slavering attack beast mauling infantryman\n\tWARHEAD_NUKE,\t\t\t\t// Nuclear missile\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tWARHEAD_MECHANICAL,\t\t// repair weapon for vehicles\n#endif\n\tWARHEAD_COUNT,\n\tWARHEAD_FIRST=0\n} WarheadType;\n\n\n/**********************************************************************\n**\tThis enumerates the various weapon types. The weapon is characterized\n**\tby the projectile it launches, the damage it does, and the rate of\n**\tfire.\n*/\ntypedef enum WeaponType {\n\tWEAPON_NONE=-1,\n\n\tWEAPON_COLT45,\n\tWEAPON_ACK_ACK,\n\tWEAPON_VULCAN,\n\tWEAPON_MAVERICK,\n\tWEAPON_CAMERA,\n\tWEAPON_FIREBALL,\n\tWEAPON_RIFLE,\n\tWEAPON_CHAIN_GUN,\n\tWEAPON_PISTOL,\n\tWEAPON_M16,\n\tWEAPON_DRAGON,\n\tWEAPON_HELLFIRE,\n\tWEAPON_GRENADE,\n\tWEAPON_75MM,\n\tWEAPON_90MM,\n\tWEAPON_105MM,\n\tWEAPON_120MM,\n\tWEAPON_TURRET_GUN,\n\tWEAPON_MAMMOTH_TUSK,\n\tWEAPON_155MM,\n\tWEAPON_M60MG,\n\tWEAPON_NAPALM,\n\tWEAPON_TESLA_ZAP,\n\tWEAPON_NIKE,\n\tWEAPON_8INCH,\n\tWEAPON_STINGER,\n\tWEAPON_TORPEDO,\n\tWEAPON_2INCH,\n\tWEAPON_DEPTH_CHARGE,\n\tWEAPON_PARA_BOMB,\n\tWEAPON_DOGJAW,\n\tWEAPON_HEAL,\n\tWEAPON_SCUD,\n\tWEAPON_FLAMER,\n\tWEAPON_REDEYE,\n\n#ifdef FIXIT_ANTS\n\tWEAPON_MANDIBLE,\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tWEAPON_PORTATESLA,\n\tWEAPON_GOODWRENCH,\n\tWEAPON_SUBSCUD,\n\tWEAPON_TTANKZAP,\n\tWEAPON_APTUSK,\n\tWEAPON_DEMOCHARGE,\n#endif\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tWEAPON_CARRIER,\n#endif\n\n\n\tWEAPON_COUNT,\n\tWEAPON_FIRST=0\n} WeaponType;\n\n\n/**********************************************************************\n**\tThe various armor types are best suited to defend against a limited\n**\tkind of warheads. The game strategy revolves around proper\n**\tcombination of armor and weaponry. Each vehicle or building has armor\n**\trated according to one of the following types.\n*/\ntypedef enum ArmorType {\n\tARMOR_NONE,\t\t\t// Vulnerable to SA and HE.\n\tARMOR_WOOD,\t\t\t// Vulnerable to HE and Fire.\n\tARMOR_ALUMINUM,\t// Vulnerable to AP and SA.\n\tARMOR_STEEL,\t\t// Vulnerable to AP.\n\tARMOR_CONCRETE,\t// Vulnerable to HE and AP.\n\n\tARMOR_COUNT,\n\tARMOR_FIRST=0\n} ArmorType;\n\n\n/**********************************************************************\n**\tThese are the identifiers for the various monochrome debug screens.\n*/\ntypedef enum DMonoType {\n\tDMONO_OBJECT,\n\tDMONO_HOUSE,\n\tDMONO_STRESS,\n\tDMONO_EVENTS,\n\n\tDMONO_COUNT,\n\tDMONO_FIRST=0\n} DMonoType;\n\n/*\n**\tPerformance benchmark tracking identifiers.\n*/\ntypedef enum BenchType {\n\tBENCH_GAME_FRAME,\t\t\t// Whole game frame (used for normalizing).\n\tBENCH_FINDPATH,\t\t\t// Find path calls.\n\tBENCH_GREATEST_THREAT,\t// Greatest threat calculation.\n\tBENCH_AI,\t\t\t\t\t// Object AI calls.\n\tBENCH_CELL,\t\t\t\t\t// Cell draw it function.\n\tBENCH_SIDEBAR,\t\t\t\t// Sidebar (just cameo section) drawing.\n\tBENCH_RADAR,\t\t\t\t// Radar map drawing.\n\tBENCH_TACTICAL,\t\t\t// Whole tactical map.\n\tBENCH_PCP,\t\t\t\t\t// Per cell process.\n\tBENCH_EVAL_OBJECT,\t\t// Evaluate object as potential target.\n\tBENCH_EVAL_CELL,\t\t\t// Evaluate entire cell for potential targets.\n\tBENCH_EVAL_WALL,\t\t\t// Evaluate wall in cell as potential target.\n\n\tBENCH_POWER,\t\t\t\t// Power bar drawing.\n\tBENCH_TABS,\t\t\t\t\t// Tab section (top) drawing.\n\tBENCH_SHROUD,\t\t\t\t// Shroud layer drawing.\n\tBENCH_ANIMS,\t\t\t\t// Animations drawing.\n\tBENCH_OBJECTS,\t\t\t\t// All game object drawing.\n\tBENCH_PALETTE,\t\t\t\t// Color cycling palette adjustments.\n\tBENCH_GSCREEN_RENDER,\t// Rendering of the whole map layered system (with blits).\n\tBENCH_BLIT_DISPLAY,\t\t// DirectX or shadow blit of hidpage to seenpage.\n\tBENCH_MISSION,\t\t\t\t// Mission list processing.\n\n\tBENCH_RULES,\t\t\t\t// Processing of the rules.ini file.\n\tBENCH_SCENARIO,\t\t\t// Processing of the scenario.ini file.\n\n\tBENCH_COUNT,\n\tBENCH_FIRST=0\n} BenchType;\n\n\n#ifdef CHEAT_KEYS\n#define\tBStart(a)\tif (Benches != NULL) Benches[a].Begin()\n#define\tBEnd(a)\t\tif (Benches != NULL) Benches[a].End()\n#else\n#define\tBStart(a)\n#define\tBEnd(a)\n#endif\n\n\n/**********************************************************************\n**\tWorking MCGA colors that give a pleasing effect for beveled edges and\n**\tother purposes.\n*/\n#define\tMAGIC_COL_COUNT\t13\t\t// Translucent color count.\n#define\tSHADOW_COL_COUNT\t4\t\t// Terrain shroud translucent color count.\n#define\tUSHADOW_COL_COUNT\t1\t\t// Unit shadow special ghost colors.\n\n\n/**********************************************************************\n**\tColor cycling range that is used for water effects.\n*/\n#define\tCYCLE_COLOR_START\t\t(6*16)\n#define\tCYCLE_COLOR_COUNT\t\t7\n\n\n/**********************************************************************\n**\tMagic color fading pulsing effect limits -- color gun value.\n*/\n#define\tCC_PULSE_COLOR\t\t\t255\n#define\tCC_EMBER_COLOR\t\t\t(CYCLE_COLOR_START+CYCLE_COLOR_COUNT)\n\n\n/**********************************************************************\n**\tThese are the control flags for Fancy_Text_Print function.\n*/\ntypedef enum TextPrintType {\n\tTPF_LASTPOINT\t\t=0x0000,\t\t// Use previous font point value.\n\tTPF_6POINT\t\t\t=0x0001,\t\t// Use 6 point font.\n\tTPF_8POINT\t\t\t=0x0002,\t\t// Use 8 point font.\n\tTPF_3POINT\t\t\t=0x0003,\t\t// Use 3 point font.\n\tTPF_LED\t\t\t\t=0x0004,\t\t// Use LED font.\n\tTPF_VCR\t\t\t\t=0x0005,\t\t// Use VCR font.\n\tTPF_6PT_GRAD\t\t=0x0006,\t\t// Use 6 point gradient font.\n\tTPF_MAP\t\t\t\t=0x0007,\t\t// Font used for popup help text.\n\tTPF_METAL12\t\t\t=0x0008,    // Use 12 point tab font\n\tTPF_EFNT\t\t\t\t=0x0009,\t\t// Use scenario editor font.\n\tTPF_TYPE\t\t\t\t=0x000A,\t\t// Use teletype font\n\tTPF_SCORE\t\t\t=0x000B,\t\t// Use score screen font.\n\tTPF_LASTSHADOW\t\t=0x0000,\t\t// Use previous font palette.\n\tTPF_NOSHADOW\t\t=0x0010,\t\t// Don't have any shadow.\n\tTPF_DROPSHADOW\t\t=0x0020,\t\t//\tUse a simple drop shadow.\n\tTPF_FULLSHADOW\t\t=0x0040,\t\t// Use a full outline shadow.\n\tTPF_LIGHTSHADOW\t=0x0080,\t\t// Use engraved drop 'shadow' color.\n\tTPF_CENTER\t\t\t=0x0100,\t\t// Center about the X axis.\n\tTPF_RIGHT\t\t\t=0x0200,\t\t// Right justify text.\n\tTPF_MEDIUM_COLOR\t=0x1000,\t\t// Use medium color for all text gradient\n\tTPF_BRIGHT_COLOR\t=0x2000,\t\t// Use bright color for all text gradient\n\tTPF_USE_GRAD_PAL\t=0x4000\t\t// Use a gradient palette based on fore color\n} TextPrintType;\n\ninline TextPrintType operator |(TextPrintType, TextPrintType);\ninline TextPrintType operator &(TextPrintType, TextPrintType);\ninline TextPrintType operator ~(TextPrintType);\n\n// Standard button text print flags.\n#define TPF_BUTTON\t(TPF_CENTER|TPF_6PT_GRAD|TPF_NOSHADOW)\n#define TPF_EBUTTON\t(TPF_CENTER|TPF_EFNT|TPF_NOSHADOW)\n#define TPF_TEXT\t\t(TPF_6PT_GRAD|TPF_NOSHADOW)\n\n\n/**********************************************************************\n**\tThese control the maximum number of objects in the game. Make sure that these\n**\tmaximums never exceed the maximum value for the \"ID\" element in the\n**\tobject class.\n*/\n#define\tBUILDING_MAX\t\t\t500\t\t// Lasts for hours.\n#define\tHOUSE_MAX\t\t\t\t(HOUSE_COUNT+1)\t// Lasts entire scenario.\n#define\tINFANTRY_MAX\t\t\t500\t\t// Lasts for minutes.\n#define\tUNIT_MAX\t\t\t\t\t500\t\t// Lasts for minutes.\n#define\tVESSEL_MAX\t\t\t\t100\t\t// Lasts for minutes.\n#define\tTEAMTYPE_MAX\t\t\t60\t\t\t// Lasts forever.\n\n// Save filename description.\n#define\tDESCRIP_MAX\t\t\t\t44\t\t\t// 40 chars + CR + LF + CTRL-Z + NULL\n\n#define\tCONQUER_PATH_MAX\t\t12\t\t\t// Number of cells to look ahead for movement.\n\n#define\tEACH_INFANTRY_MAX\t\t(INFANTRY_MAX/5)\t\t// Default maximum any one player can have.\n#define\tEACH_UNIT_MAX\t\t\t(UNIT_MAX/5)\t\t\t// Default maximum any one player can have.\n#define\tEACH_BUILDING_MAX\t\t(BUILDING_MAX/5)\t\t// Default maximum any one player can build.\n#define\tEACH_VESSEL_MAX\t\t(VESSEL_MAX/5)\t\t\t// Default maximum any one player can build.\n\n\n/**********************************************************************\n**\tTerrain can be of these different classes. At any point in the game\n**\ta particular piece of ground must fall under one of these classifications.\n**\tThis is true, even if it is undergoing a temporary transition.\n*/\ntypedef enum LandType {\n\tLAND_CLEAR,\t\t// \"Clear\" terrain.\n\tLAND_ROAD,\t\t// Road terrain.\n\tLAND_WATER,\t\t// Water.\n\tLAND_ROCK,\t\t// Impassable rock.\n\tLAND_WALL,\t\t// Wall (blocks movement).\n\tLAND_TIBERIUM,\t// Tiberium field.\n\tLAND_BEACH,\t\t//\tBeach terrain.\n\tLAND_ROUGH,\t\t// Rocky terrain.\n\tLAND_RIVER,\t\t// Rocky riverbed.\n\n\tLAND_COUNT,\n\tLAND_NONE=-1,\n\tLAND_FIRST=0\n} LandType;\n\n\n/**********************************************************************\n**\tThe theaters of operation are as follows.\n*/\ntypedef enum TheaterType {\n\tTHEATER_NONE=-1,\n\tTHEATER_TEMPERATE,\n\tTHEATER_SNOW,\n\tTHEATER_INTERIOR,\n\n\tTHEATER_COUNT,\n\tTHEATER_FIRST=0\n} TheaterType;\n\ninline TheaterType operator++(TheaterType &, int);\n\n#define\tTHEATERF_TEMPERATE\t\t(1<<THEATER_TEMPERATE)\n#define\tTHEATERF_SNOW\t\t\t\t(1<<THEATER_SNOW)\n#define\tTHEATERF_INTERIOR\t\t\t(1<<THEATER_INTERIOR)\n\ntypedef struct {\n\tchar\t\tName[16];\n\tchar\t\tRoot[10];\n\tchar\t\tSuffix[4];\n} TheaterDataType;\n\n\n/**********************************************************************\n**\tEach building has a predetermined size. These are the size numbers.\n**\tThe trailing number is this define is the width and height (respectively)\n**\tof the building in cells.\n*/\ntypedef enum BSizeType {\n\tBSIZE_NONE=-1,\n\tBSIZE_11=0,\n\tBSIZE_21,\n\tBSIZE_12,\n\tBSIZE_22,\n\tBSIZE_23,\n\tBSIZE_32,\n\tBSIZE_33,\n\tBSIZE_42,\n\tBSIZE_55,\n\n\tBSIZE_COUNT\n} BSizeType;\n\ninline BSizeType operator++(BSizeType &, int);\n\n\n/**********************************************************************\n** When objects are manipulated on the map that are marked as being\n**\tremoved (up), placed down (down), or just to be redrawn (change);\n** or when an object's rendering (not logical) size changes, due to\n** its being selected or having an animation attached (overlap up/down).\n*/\ntypedef enum MarkType {\n\tMARK_UP,\t\t\t\t\t//\tRemoved from the map.\n\tMARK_DOWN,\t\t\t\t//\tPlaced on the map.\n\tMARK_CHANGE,\t\t\t//\tAltered in place on the map.\n\tMARK_CHANGE_REDRAW,\t//\tRedraw because of animation change.\n\tMARK_OVERLAP_DOWN,\t// Mark overlap cells on the map\n\tMARK_OVERLAP_UP\t\t// Clear overlap cells on the map\n} MarkType;\n\n\n/****************************************************************************\n**\tWindow number definition list. Each window should be referred to by\n**\tthe value given in this list.\n*/\n// Allow window number enums to be passed to library functions.\ntypedef enum WindowNumberType {\n\tWINDOW_MAIN,\t\t\t\t// Full screen window.\n\tWINDOW_ERROR,\t\t\t\t// Library error window.\n\tWINDOW_TACTICAL,\t\t\t// Tactical map window.\n\tWINDOW_MENU,\t\t\t\t// Main selection menu.\n\tWINDOW_SIDEBAR,\t\t\t// Sidebar (buildable list) window.\n\tWINDOW_EDITOR,\t\t\t\t// Scenario editor window.\n\tWINDOW_PARTIAL,\t\t\t// Partial object draw sub-window.\n} WindowNumberType;\n\n\n/****************************************************************************\n**\tFor every cell there are 8 adjacent cells. Use these direction numbers\n**\twhen referring to adjacent cells. This comes into play when moving\n**\tbetween cells and in the Desired_Facing() algorithm.\n*/\ntypedef enum FacingType {\n\tFACING_NONE=-1,\n\tFACING_N,\t\t\t// North\n\tFACING_NE,\t\t\t// North-East\n\tFACING_E,\t\t\t// East\n\tFACING_SE,\t\t\t// South-East\n\tFACING_S,\t\t\t// South\n\tFACING_SW,\t\t\t// South-West\n\tFACING_W,\t\t\t// West\n\tFACING_NW,\t\t\t// North-West\n\n\tFACING_COUNT,\t\t\t// Total of 8 directions (0..7).\n\tFACING_FIRST=0\n} FacingType;\n\ninline FacingType operator++(FacingType &, int);\ninline FacingType operator + (FacingType f1, FacingType f2)\n{\n\treturn (FacingType)(((int)f1 + (int)f2) & 0x07);\n}\ninline FacingType operator + (FacingType f1, int f2)\n{\n\treturn (FacingType)(((int)f1 + (int)f2) & 0x07);\n}\n\ninline FacingType operator - (FacingType f1, FacingType f2)\n{\n\treturn (FacingType)(((int)f1 - (int)f2) & 0x07);\n}\ninline FacingType operator - (FacingType f1, int f2)\n{\n\treturn (FacingType)(((int)f1 - (int)f2) & 0x07);\n}\n\ninline FacingType operator += (FacingType & f1, FacingType f2)\n{\n\tf1 = (FacingType)(((int)f1 + (int)f2) & 0x07);\n\treturn(f1);\n}\ninline FacingType operator += (FacingType & f1, int f2)\n{\n\tf1 = (FacingType)(((int)f1 + (int)f2) & 0x07);\n\treturn(f1);\n}\n\ninline int operator * (FacingType f1, FacingType f2)\n{\n\treturn((int)f1 * (int)f2);\n}\n\n\n#ifdef NEVER\ntypedef enum DirType {\n\tDIR_MIN=0,\n\tDIR_N=0,\n\tDIR_NE=1<<5,\n\tDIR_E=2<<5,\n\tDIR_SE=3<<5,\n\tDIR_S=4<<5,\n\tDIR_SW=5<<5,\n\tDIR_SW_X1=(5<<5)-8,\t\t// Direction of harvester while unloading.\n\tDIR_SW_X2=(5<<5)-16,\t\t// Direction of harvester while unloading.\n\tDIR_W=6<<5,\n\tDIR_NW=7<<5,\n\tDIR_MAX=255\n} DirType;\ninline DirType operator + (DirType f1, DirType f2)\n{\n\treturn (DirType)(((int)f1 + (int)f2) & 0x00FF);\n}\ninline DirType operator + (DirType f1, int f2)\n{\n\treturn (DirType)(((int)f1 + (int)f2) & 0x00FF);\n}\n#endif\n#define DIR_SW_X1\tDirType((5<<5)-8)\n#define DIR_SW_X2\tDirType((5<<5)-16)\n\n\n/****************************************************************************\n**\tTimer constants. These are used when setting the countdown timer.\n**\tNote that this is based upon a timer that ticks every 60th of a second.\n*/\n#define\tTIMER_SECOND\t\t\t60\n#define\tTIMER_MINUTE\t\t\t(TIMER_SECOND*60)\n\n#define\tFADE_PALETTE_FAST\t\t(TIMER_SECOND/8)\n#define\tFADE_PALETTE_MEDIUM\t(TIMER_SECOND/4)\n#define\tFADE_PALETTE_SLOW\t\t(TIMER_SECOND/2)\n\n#define\tTICKS_PER_SECOND\t\t15\n#define\tTICKS_PER_MINUTE\t\t(TICKS_PER_SECOND * 60)\n#define\tTICKS_PER_HOUR\t\t\t(TICKS_PER_MINUTE * 60)\n\n#define\tGRAYFADETIME\t\t\t(1 * TICKS_PER_SECOND)\n\n\n/****************************************************************************\n** Each vehicle is give a speed rating. This is a combination of not only\n**\tits physical speed, but the means by which it travels (wheels, tracks,\n**\twings, etc). This is used to determine the movement table.\n*/\ntypedef enum SpeedType {\n\tSPEED_NONE=-1,\n\n\tSPEED_FOOT,\t\t\t\t\t// Bipedal.\n\tSPEED_TRACK,\t\t\t\t// Tracked locomotion.\n\tSPEED_WHEEL,\t\t\t\t// Balloon tires.\n\tSPEED_WINGED,\t\t\t\t// Lifter's, 'thopters, and rockets.\n\tSPEED_FLOAT,\t\t\t\t// Ships.\n\n\tSPEED_COUNT,\n\tSPEED_FIRST=SPEED_FOOT\n} SpeedType;\n\n\n/**********************************************************************\n**\tThese are the sound effect digitized sample file names.\n*/\ntypedef enum VocType{\n\tVOC_NONE=-1,\n\n\tVOC_GIRL_OKAY,\t\t\t// \"okay\"\n\tVOC_GIRL_YEAH,\t\t\t// \"yeah?\"\n\tVOC_GUY_OKAY,\t\t\t//\t\"okay\"\n\tVOC_GUY_YEAH,\t\t\t// \"yeah?\"\n\n\tVOC_MINELAY1,\t\t\t// mine layer sound\n\tVOC_ACKNOWL,\t\t\t//\t\"acknowledged\"\n\tVOC_AFFIRM,\t\t\t\t//\t\"affirmative\"\n\tVOC_AWAIT,\t\t\t\t//\t\"awaiting orders\"\n\tVOC_ENG_AFFIRM,\t\t// Engineer: \"affirmative\"\n\tVOC_ENG_ENG,\t\t\t// Engineer: \"engineering\"\n\tVOC_NO_PROB,\t\t\t//\t\"not a problem\"\n\tVOC_READY,\t\t\t\t//\t\"ready and waiting\"\n\tVOC_REPORT,\t\t\t\t//\t\"reporting\"\n\tVOC_RIGHT_AWAY,\t\t//\t\"right away sir\"\n\tVOC_ROGER,\t\t\t\t//\t\"roger\"\n\tVOC_UGOTIT,\t\t\t\t//\t\"you got it\"\n\tVOC_VEHIC,\t\t\t\t//\t\"vehicle reporting\"\n\tVOC_YESSIR,\t\t\t\t//\t\"yes sir\"\n\n\tVOC_SCREAM1,\t\t\t//\tshort infantry scream\n\tVOC_SCREAM3,\t\t\t//\tshort infantry scream\n\tVOC_SCREAM4,\t\t\t//\tshort infantry scream\n\tVOC_SCREAM5,\t\t\t//\tshort infantry scream\n\tVOC_SCREAM6,\t\t\t//\tshort infantry scream\n\tVOC_SCREAM7,\t\t\t//\tshort infantry scream\n\tVOC_SCREAM10,\t\t\t//\tshort infantry scream\n\tVOC_SCREAM11,\t\t\t//\tshort infantry scream\n\tVOC_YELL1,\t\t\t\t//\tlong infantry scream\n\n\tVOC_CHRONO,\t\t\t\t//\tChronosphere sound.\n\tVOC_CANNON1,\t\t\t// Cannon sound (medium).\n\tVOC_CANNON2,\t\t\t// Cannon sound (short).\n\tVOC_IRON1,\n\tVOC_ENG_MOVEOUT,\t\t// Engineer: \"movin' out\"\n\tVOC_SONAR,\t\t\t\t// sonar pulse\n\tVOC_SANDBAG,\t\t\t// sand bag crunch\n\tVOC_MINEBLOW,\n\tVOC_CHUTE1,\t\t\t\t// wind swoosh sound\n\tVOC_DOG_BARK,\t\t\t// dog bark\n\tVOC_DOG_WHINE,\t\t\t// dog whine\n\tVOC_DOG_GROWL2,\t\t// strong dog growl\n\tVOC_FIRE_LAUNCH,\t\t// fireball launch sound\n\tVOC_FIRE_EXPLODE,\t\t// fireball explode sound\n\tVOC_GRENADE_TOSS,\t\t// grenade toss\n\tVOC_GUN_5,\t\t\t\t// 5 round gun burst (slow).\n\tVOC_GUN_7,\t\t\t\t// 7 round gun burst (fast).\n\tVOC_ENG_YES,\t\t\t// Engineer: \"yes sir\"\n\tVOC_GUN_RIFLE,\t\t\t// Rifle shot.\n\tVOC_HEAL,\t\t\t\t// Healing effect.\n\tVOC_DOOR,\t\t\t\t// Hyrdrolic door.\n\tVOC_INVULNERABLE,\t\t// Invulnerability effect.\n\tVOC_KABOOM1,\t\t\t// Long explosion (muffled).\n\tVOC_KABOOM12,\t\t\t// Very long explosion (muffled).\n\tVOC_KABOOM15,\t\t\t// Very long explosion (muffled).\n\tVOC_SPLASH,\t\t\t\t// Water splash\n\tVOC_KABOOM22,\t\t\t// Long explosion (sharp).\n\tVOC_AACANON3,\t\t\t// AA-Cannon\n\tVOC_TANYA_DIE,\t\t\t// Tanya: scream\n\tVOC_GUN_5F,\t\t\t\t// 5 round gun burst (fast).\n\tVOC_MISSILE_1,\t\t\t// Missile with high tech effect.\n\tVOC_MISSILE_2,\t\t\t// Long missile launch.\n\tVOC_MISSILE_3,\t\t\t// Short missile launch.\n\tVOC_x6,\n\tVOC_GUN_5R,\t\t\t\t// 5 round gun burst (rattles).\n\tVOC_BEEP,\t\t\t\t// Generic beep sound.\n\tVOC_CLICK,\t\t\t\t//\tGeneric click sound.\n\tVOC_SILENCER,\t\t\t// Silencer.\n\tVOC_CANNON6,\t\t\t// Long muffled cannon shot.\n\tVOC_CANNON7,\t\t\t// Sharp mechanical cannon fire.\n\tVOC_TORPEDO,\t\t\t// Torpedo launch.\n\tVOC_CANNON8,\t\t\t// Sharp cannon fire.\n\tVOC_TESLA_POWER_UP,\t// Hum charge up.\n\tVOC_TESLA_ZAP,\t\t\t// Tesla zap effect.\n\tVOC_SQUISH,\t\t\t\t// Squish effect.\n\tVOC_SCOLD,\t\t\t\t// Scold bleep.\n\tVOC_RADAR_ON,\t\t\t// Powering up electronics.\n\tVOC_RADAR_OFF,\t\t\t// B movie power down effect.\n\tVOC_PLACE_BUILDING_DOWN,\t// Building slam down sound.\n\tVOC_KABOOM30,\t\t\t// Short explosion (HE).\n\tVOC_KABOOM25,\t\t\t// Short growling explosion.\n\tVOC_x7,\n\tVOC_DOG_HURT,\t\t\t//\tDog whine.\n\tVOC_DOG_YES,\t\t\t// Dog 'yes sir'.\n\tVOC_CRUMBLE,\t\t\t// Building crumble.\n\tVOC_MONEY_UP,\t\t\t// Rising money tick.\n\tVOC_MONEY_DOWN,\t\t// Falling money tick.\n\tVOC_CONSTRUCTION,\t\t// Building construction sound.\n\tVOC_GAME_CLOSED,\t\t// Long bleep.\n\tVOC_INCOMING_MESSAGE,\t// Soft happy warble.\n\tVOC_SYS_ERROR,\t\t\t// Sharp soft warble.\n\tVOC_OPTIONS_CHANGED,\t// Mid range soft warble.\n\tVOC_GAME_FORMING,\t\t// Long warble.\n\tVOC_PLAYER_LEFT,\t\t// Chirp sequence.\n\tVOC_PLAYER_JOINED,\t// Reverse chirp sequence.\n\tVOC_DEPTH_CHARGE,\t\t// Distant explosion sound.\n\tVOC_CASHTURN,\t\t\t// Airbrake.\n\n\tVOC_TANYA_CHEW,\t\t// Tanya: \"Chew on this\"\n\tVOC_TANYA_ROCK,\t\t// Tanya: \"Let's rock\"\n\tVOC_TANYA_LAUGH,\t\t// Tanya: \"ha ha ha\"\n\tVOC_TANYA_SHAKE,\t\t// Tanya: \"Shake it baby\"\n\tVOC_TANYA_CHING,\t\t// Tanya: \"Cha Ching\"\n\tVOC_TANYA_GOT,\t\t\t// Tanya: \"That's all you got\"\n\tVOC_TANYA_KISS,\t\t// Tanya: \"Kiss it bye bye\"\n\tVOC_TANYA_THERE,\t\t// Tanya: \"I'm there\"\n\tVOC_TANYA_GIVE,\t\t// Tanya: \"Give it to me\"\n\tVOC_TANYA_YEA,\t\t\t// Tanya: \"Yea?\"\n\tVOC_TANYA_YES,\t\t\t// Tanya: \"Yes sir?\"\n\tVOC_TANYA_WHATS,\t\t// Tanya: \"What's up.\"\n\tVOC_WALLKILL2,\t\t\t// Crushing wall sound.\n\tVOC_x8,\n\tVOC_TRIPLE_SHOT,\t\t// Three quick shots in succession.\n\tVOC_SUBSHOW,\t\t\t// Submarine surfacing.\n\tVOC_E_AH,\t\t\t\t// Einstein \"ah\"\n\tVOC_E_OK,\t\t\t\t// Einstein \"ok\"\n\tVOC_E_YES,\t\t\t\t// Einstein \"yes\"\n\tVOC_TRIP_MINE,\t\t\t// mine explosion sound\n\n\tVOC_SPY_COMMANDER,\t// Spy: \"commander?\"\n\tVOC_SPY_YESSIR,\t\t// Spy: \"yes sir\"\n\tVOC_SPY_INDEED,\t\t// Spy: \"indeed\"\n\tVOC_SPY_ONWAY,\t\t\t// Spy: \"on my way\"\n\tVOC_SPY_KING,\t\t\t// Spy: \"for king and country\"\n\tVOC_MED_REPORTING,\t// Medic: \"reporting\"\n\tVOC_MED_YESSIR,\t\t// Medic: \"yes sir\"\n\tVOC_MED_AFFIRM,\t\t// Medic: \"affirmative\"\n\tVOC_MED_MOVEOUT,\t\t// Medic: \"movin' out\"\n\tVOC_BEEP_SELECT,\t\t// map selection beep\n\n\tVOC_THIEF_YEA,\t\t\t// Thief: \"yea?\"\n\n#ifdef FIXIT_ANTS\n\tVOC_ANTDIE,\n\tVOC_ANTBITE,\n#else\n\tVOC_x9,\n\tVOC_x10,\n#endif\n\n\tVOC_THIEF_MOVEOUT,\t// Thief: \"movin' out\"\n\tVOC_THIEF_OKAY,\t\t// Thief: \"ok\"\n\tVOC_x11,\n\tVOC_THIEF_WHAT,\t\t// Thief: \"what\"\n\tVOC_THIEF_AFFIRM,\t\t// Thief: \"affirmative\"\n\n\tVOC_STAVCMDR,\n\tVOC_STAVCRSE,\n\tVOC_STAVYES,\n\tVOC_STAVMOV,\n\tVOC_BUZZY1,\n\tVOC_RAMBO1,\n\tVOC_RAMBO2,\n\tVOC_RAMBO3,\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tVOC_MECHYES1,\n\tVOC_MECHHOWDY1,\n\tVOC_MECHRISE1,\n\tVOC_MECHHUH1,\n\tVOC_MECHHEAR1,\n\tVOC_MECHLAFF1,\n\tVOC_MECHBOSS1,\n\tVOC_MECHYEEHAW1,\n\tVOC_MECHHOTDIG1,\n\tVOC_MECHWRENCH1,\n\tVOC_STBURN1,\n\tVOC_STCHRGE1,\n\tVOC_STCRISP1,\n\tVOC_STDANCE1,\n\tVOC_STJUICE1,\n\tVOC_STJUMP1,\n\tVOC_STLIGHT1,\n\tVOC_STPOWER1,\n\tVOC_STSHOCK1,\n\tVOC_STYES1,\n\n\tVOC_CHRONOTANK1,\n\tVOC_MECH_FIXIT1,\n\tVOC_MAD_CHARGE,\n\tVOC_MAD_EXPLODE,\n\tVOC_SHOCK_TROOP1,\n\n#endif\n\tVOC_COUNT,\n\tVOC_FIRST=0\n} VocType;\n\n/*\n**\tEVA voices are specified by these identifiers.\n*/\ntypedef enum VoxType{\n\tVOX_NONE=-1,\n\tVOX_ACCOMPLISHED,\t\t\t\t\t//\tmission accomplished\n\tVOX_FAIL,\t\t\t\t\t\t\t//\tyour mission has failed\n\tVOX_NO_FACTORY,\t\t\t\t\t//\tunable to comply, building in progress\n\tVOX_CONSTRUCTION,\t\t\t\t\t//\tconstruction complete\n\tVOX_UNIT_READY,\t\t\t\t\t// unit ready\n\tVOX_NEW_CONSTRUCT,\t\t\t\t//\tnew construction options\n\tVOX_DEPLOY,\t\t\t\t\t\t\t//\tcannot deploy here\n\tVOX_STRUCTURE_DESTROYED,\t\t// structure destroyed\n\tVOX_INSUFFICIENT_POWER,\t\t\t// insufficient power\n\tVOX_NO_CASH,\t\t\t\t\t\t//\tinsufficient funds\n\tVOX_CONTROL_EXIT,\t\t\t\t\t//\tbattle control terminated\n\tVOX_REINFORCEMENTS,\t\t\t\t//\treinforcements have arrived\n\tVOX_CANCELED,\t\t\t\t\t\t//\tcanceled\n\tVOX_BUILDING,\t\t\t\t\t\t//\tbuilding\n\tVOX_LOW_POWER,\t\t\t\t\t\t//\tlow power\n\tVOX_NEED_MO_MONEY,\t\t\t\t//\tneed more funds\n\tVOX_BASE_UNDER_ATTACK,\t\t\t//\tour base is under attack\n\tVOX_UNABLE_TO_BUILD,\t\t\t\t//\tunable to build more\n\tVOX_PRIMARY_SELECTED,\t\t\t//\tprimary building selected\n#ifdef ENGLISH\n\tVOX_MADTANK_DEPLOYED,\t\t\t// M.A.D. Tank Deployed\n#else\n\tVOX_none3,\n#endif\n\tVOX_none4,\n\tVOX_UNIT_LOST,\t\t\t\t\t\t//\tunit lost\n\tVOX_SELECT_TARGET,\t\t\t\t// select target\n\tVOX_PREPARE,\t\t\t\t\t\t//\tenemy approaching\n\tVOX_NEED_MO_CAPACITY,\t\t\t//\tsilos needed\n\tVOX_SUSPENDED,\t\t\t\t\t\t//\ton hold\n\tVOX_REPAIRING,\t\t\t\t\t\t//\trepairing\n\tVOX_none5,\n\tVOX_none6,\n\tVOX_AIRCRAFT_LOST,\n\tVOX_none7,\n\tVOX_ALLIED_FORCES_APPROACHING,\n\tVOX_ALLIED_APPROACHING,\n\tVOX_none8,\n\tVOX_none9,\n\tVOX_BUILDING_INFILTRATED,\n\tVOX_CHRONO_CHARGING,\n\tVOX_CHRONO_READY,\n\tVOX_CHRONO_TEST,\n\tVOX_HQ_UNDER_ATTACK,\n\tVOX_CENTER_DEACTIVATED,\n\tVOX_CONVOY_APPROACHING,\n\tVOX_CONVOY_UNIT_LOST,\n\tVOX_EXPLOSIVE_PLACED,\n\tVOX_MONEY_STOLEN,\n\tVOX_SHIP_LOST,\n\tVOX_SATALITE_LAUNCHED,\n\tVOX_SONAR_AVAILABLE,\n\tVOX_none10,\n\tVOX_SOVIET_FORCES_APPROACHING,\n\tVOX_SOVIET_REINFORCEMENTS,\n\tVOX_TRAINING,\n\tVOX_ABOMB_READY,\n\tVOX_ABOMB_LAUNCH,\n\tVOX_ALLIES_N,\n\tVOX_ALLIES_S,\n\tVOX_ALLIES_E,\n\tVOX_ALLIES_W,\n\tVOX_OBJECTIVE1,\n\tVOX_OBJECTIVE2,\n\tVOX_OBJECTIVE3,\n\tVOX_IRON_CHARGING,\n\tVOX_IRON_READY,\n\tVOX_RESCUED,\n\tVOX_OBJECTIVE_NOT,\n\tVOX_SIGNAL_N,\n\tVOX_SIGNAL_S,\n\tVOX_SIGNAL_E,\n\tVOX_SIGNAL_W,\n\tVOX_SPY_PLANE,\n\tVOX_FREED,\n\tVOX_UPGRADE_ARMOR,\n\tVOX_UPGRADE_FIREPOWER,\n\tVOX_UPGRADE_SPEED,\n\tVOX_MISSION_TIMER,\n\tVOX_UNIT_FULL,\n\tVOX_UNIT_REPAIRED,\n\tVOX_TIME_40,\n\tVOX_TIME_30,\n\tVOX_TIME_20,\n\tVOX_TIME_10,\n\tVOX_TIME_5,\n\tVOX_TIME_4,\n\tVOX_TIME_3,\n\tVOX_TIME_2,\n\tVOX_TIME_1,\n\tVOX_TIME_STOP,\n\tVOX_UNIT_SOLD,\n\tVOX_TIMER_STARTED,\n\tVOX_TARGET_RESCUED,\n\tVOX_TARGET_FREED,\n\tVOX_TANYA_RESCUED,\n\tVOX_STRUCTURE_SOLD,\n\tVOX_SOVIET_FORCES_FALLEN,\n\tVOX_SOVIET_SELECTED,\n\tVOX_SOVIET_EMPIRE_FALLEN,\n\tVOX_OPERATION_TERMINATED,\n\tVOX_OBJECTIVE_REACHED,\n\tVOX_OBJECTIVE_NOT_REACHED,\n\tVOX_OBJECTIVE_MET,\n\tVOX_MERCENARY_RESCUED,\n\tVOX_MERCENARY_FREED,\n\tVOX_KOSOYGEN_FREED,\n\tVOX_FLARE_DETECTED,\n\tVOX_COMMANDO_RESCUED,\n\tVOX_COMMANDO_FREED,\n\tVOX_BUILDING_IN_PROGRESS,\n\tVOX_ATOM_PREPPING,\n\tVOX_ALLIED_SELECTED,\n\tVOX_ABOMB_PREPPING,\n\tVOX_ATOM_LAUNCHED,\n\tVOX_ALLIED_FORCES_FALLEN,\n\tVOX_ABOMB_AVAILABLE,\n\tVOX_ALLIED_REINFORCEMENTS,\n\tVOX_SAVE1,\n\tVOX_LOAD1,\n\n\tVOX_COUNT,\n\tVOX_FIRST=0\n} VoxType;\n\n\n/****************************************************************************\n**\tGame reinforcements are each controlled by the following structure. The\n**\tdata originates in the scenario INI file but is then carried throughout\n**\tany saved games.\n*/\ntypedef enum SourceType {\n\tSOURCE_NONE=-1,\t\t\t\t// No defined source (error condition).\n\tSOURCE_NORTH,\t\t\t\t\t// From north edge.\n\tSOURCE_EAST,\t\t\t\t\t// From east edge.\n\tSOURCE_SOUTH,\t\t\t\t\t// From south edge.\n\tSOURCE_WEST,\t\t\t\t\t// From west edge.\n\tSOURCE_AIR,\t\t\t\t\t\t// Dropped by air (someplace).\n\n\tSOURCE_COUNT,\n\tSOURCE_FIRST=0\n} SourceType;\n\n\n/****************************************************************************\n**\tThis entry defines a complete color scheme, with the player's remap table,\n** the font remap table, and a color scheme for dialog boxes and buttons.\n*/\ntypedef struct RemapControlType\n{\n\tunsigned char BrightColor;\t\t\t// Highlight (bright) color index.\n\tunsigned char Color;\t\t\t\t\t// Normal color index.\n\tunsigned char RemapTable[256];\t// Actual remap table.\n\tunsigned char FontRemap[16];\t\t// Remap table for gradient font.\n\tunsigned char Shadow;\t\t\t\t// Color of shadowed edge of a raised button.\n\tunsigned char Background;\t\t\t// Background fill color for buttons.\n\tunsigned char Corners;\t\t\t\t// Transition color between shadow and highlight.\n\tunsigned char Highlight;\t\t\t// Bright edge of raised button.\n\tunsigned char Box;\t\t\t\t\t// Color for dialog box border.\n\tunsigned char Bright;\t\t\t\t// Color used for highlighted text.\n\tunsigned char Underline;\t\t\t// Color for underlining dialog box titles.\n\tunsigned char Bar;\t\t\t\t\t// Selected entry list box background color.\n} RemapControlType;\n\n\n/****************************************************************************\n**\tEach type of terrain has certain characteristics. These are indicated\n**\tby the structure below. For every element of terrain there is a\n**\tcorresponding GroundType structure.\n*/\ntypedef struct {\n\tfixed\tCost[SPEED_COUNT];\t// Terrain effect cost (normal).\n\tbool\t\t\t\tBuild;\t\t\t\t\t// Can build on this terrain?\n} GroundType;\n\n\n/**************************************************************************\n**\tFind_Path returns with a pointer to this structure.\n*/\ntypedef struct {\n\tCELL\t\t\t\tStart;\t\t\t\t// Starting cell number.\n\tint\t\t\t\tCost;\t\t\t\t\t// Accumulated terrain cost.\n\tint\t\t\t\tLength;\t\t\t\t// Command string length.\n\tFacingType\t\t*Command;\t\t\t// Pointer to command string.\n\tunsigned long\t*Overlap;\t\t\t// Pointer to overlap list\n\tCELL\t\t\t\tLastOverlap;\t\t// stores position of last overlap\n\tCELL\t\t\t\tLastFixup;\t\t\t// stores position of last overlap\n} PathType;\n\n\n/**********************************************************************\n** These are special indices into the Waypoint array; slots 0-25 are\n** reserved for letter-designated Waypoints, the others are special.\n*/\ntypedef enum WaypointEnum\n{\n\tWAYPT_HOME = 98,\t\t\t\t// Home-cell for this scenario\n\tWAYPT_REINF,\t\t\t\t\t// cell where reinforcements arrive\n\tWAYPT_SPECIAL,\t\t\t\t\t// Used by special airdrop reinforcements.\n\tWAYPT_COUNT\n} WaypointType;\n\n\n/****************************************************************************\n**\tThis is the max number of events supported on one frame.\n*/\n#define\tMAX_EVENTS\t\t\t64\n\ntypedef enum {\n\tKF_NUMBER   = 0x08,\n\tKF_LCW      = 0x10,\n\tKF_DELTA    = 0x20,\n\tKF_KEYDELTA = 0x40,\n\tKF_KEYFRAME = 0x80,\n\tKF_MASK     = 0xF0\n} KeyFrameType;\n\n\n/*\n** New Config structure for .CFG files\n*/\ntypedef struct {\n   unsigned   DigitCard;      \t// SoundCardType.\n   unsigned   Port;      \t\t \t// SoundCardType.\n   unsigned   IRQ;\t\t       \t// SoundCardType.\n   unsigned   DMA;     \t\t \t\t// SoundCardType.\n   unsigned   BitsPerSample;     // bits per sound sample\n   unsigned   Channels;          // stereo/mono sound card\n   unsigned   Speed;\t\t         // stereo/mono sound card\n\tbool       Reverse;\t\t\t\t// Reverse left/right speakers\n\tchar       Language[4];\n} NewConfigType;\n\n\n/****************************************************************************\n**\tThese are the types of dialogs that can pop up outside of the main loop,\n** an call the game in the background.\n*/\ntypedef enum {\n\tSDLG_NONE,\n\tSDLG_OPTIONS,\n\tSDLG_SURRENDER,\n\tSDLG_SPECIAL\n} SpecialDialogType;\n\ntypedef enum {\n\tCC_MOUSE_COLOR=16\n} CCPaletteType;\n\n\n/****************************************************************************\n**\tThese specify the shape numbers in the OPTIONS.SHP file. These shapes\n**\tare used to dress up the dialog boxes. Many of these shapes come in pairs.\n**\tFor dialog box shapes, they are left image / right image paired. For buttons,\n**\tthey are up / down paired.\n*/\ntypedef enum OptionControlType {\n\tOPTION_NONE=-1,\t\t\t// No fancy shmancy shape.\n\tOPTION_DIALOG=0,\t\t\t// Small dialog boxes.\n\tOPTION_CONTROLS=2,\t\t// Large dialog boxes, game controls.\n\tOPTION_DELETE=4,\t\t\t// Delete,Load,Save game.\n\tOPTION_SERIAL=6,\t\t\t// Serial dialog.\n\tOPTION_PHONE=8,\t\t\t// Phone dialog.\n\tOPTION_VISUAL=10,\t\t\t// Visual dialog.\n\tOPTION_NETWORK=12,\t\t// Network dialog.\n\tOPTION_JOIN_NETWORK=14,\t// Join network dialog.\n\tOPTION_SOUND=16,\t\t\t// Sound controls.\n\n\tOPTION_COUNT\n} OptionControlType;\n\n\n#define size_of(typ,id) sizeof(((typ*)0)->id)\n\n\n#define MAX_LOG_LEVEL\t\t10\n\n// Maximum number of multi players possible.\n#define\tMAX_PLAYERS\t\t\t\t\t\t8\t\t// max # of players we can have\n\n\n\n#endif\n"
  },
  {
    "path": "CODE/DESCDLG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/DESCDLG.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DESCDLG.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg                                  *\n *                                  Joe L. Bostic                                              *\n *                                                                                             *\n *                   Start Date : Jan 26, 1995                                                 *\n *                                                                                             *\n *                  Last Update : Jan 26, 1995   [MML]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   DescriptionClass::Process -- Handles all the options graphic interface.                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"descdlg.h\"\n\n\n/***********************************************************************************************\n * DescriptionClass::Process -- Handles all the options graphic interface.                     *\n *                                                                                             *\n *    This dialog uses an edit box to \"fill-out\" a description.                                *\n *                                                                                             *\n * INPUT:      char *string - return answer here.                                              *\n * OUTPUT:     none                                                                            *\n * WARNINGS:   none                                                                            *\n * HISTORY:    12/31/1994 MML : Created.                                                       *\n *=============================================================================================*/\nvoid DescriptionClass::Process(char * string)\n{\n\t/*\n\t**\tSet up the window.  Window x-coords are in bytes not pixels.\n\t*/\n\tSet_Window(WINDOW_EDITOR, OPTION_X, OPTION_Y, OPTION_WIDTH, OPTION_HEIGHT);\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tCreate Buttons.  Button coords are in pixels, but are window-relative.\n\t*/\n\tTextButtonClass optionsbtn(BUTTON_OPTIONS, TXT_OK, TPF_BUTTON, 0, BUTTON_Y);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, 0, BUTTON_Y);\n\n\tcancelbtn.X  = OPTION_X + ((OPTION_WIDTH - optionsbtn.Width)/3)*2;\n\toptionsbtn.X = OPTION_X + ((OPTION_WIDTH - optionsbtn.Width)/3);\n\toptionsbtn.Add_Tail(cancelbtn);\n\n\tEditClass edit(\n\t\tBUTTON_EDIT,\n\t\tstring,\n\t\t31,\n\t\tTPF_6PT_GRAD,\n\t\t0,\n\t\tEDIT_Y,\n\t\tEDIT_W);\n\n\tedit.Set_Focus();\n\tedit.X = OPTION_X + (OPTION_WIDTH - edit.Width)/2,\n\toptionsbtn.Add_Tail(edit);\n\n\t/*\n\t**\tThis causes left mouse button clicking within the confines of the dialog to\n\t**\tbe ignored if it wasn't recognized by any other button or slider.\n\t*/\n\tGadgetClass dialog(OPTION_X, OPTION_Y, OPTION_WIDTH, OPTION_HEIGHT, GadgetClass::LEFTPRESS);\n\toptionsbtn.Add_Tail(dialog);\n\n\t/*\n\t**\tThis causes a right click anywhere or a left click outside the dialog region\n\t**\tto be equivalent to clicking on the return to options dialog.\n\t*/\n\tControlClass background(BUTTON_OPTIONS, 0, 0, 320, 200, GadgetClass::LEFTPRESS|GadgetClass::RIGHTPRESS);\n\toptionsbtn.Add_Tail(background);\n\n\t/*\n\t**\tMain Processing Loop\n\t*/\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if needed\n\t\t*/\n\t\tif (display) {\n\n\t\t\tWindow_Hide_Mouse(WINDOW_EDITOR);\n\n\t\t\t/*\n\t\t\t**\tDraw the background\n\t\t\t*/\n\t\t\tWindow_Box (WINDOW_EDITOR, BOXSTYLE_BORDER); // has border, raised up\n\t\t\tDraw_Caption(TXT_MISSION_DESCRIPTION, OPTION_X, OPTION_Y, OPTION_WIDTH);\n\n\t\t\t/*\n\t\t\t**\tDraw the titles\n\t\t\t*/\n\t\t\toptionsbtn.Draw_All();\n\t\t\tWindow_Show_Mouse();\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input\n\t\t*/\n\t\tKeyNumType input = optionsbtn.Input();\n\n\t\t/*\n\t\t**\tProcess Input\n\t\t*/\n\t\tswitch (input) {\n\n\t\t\tcase KN_RETURN:\n\t\t\tcase KeyNumType(BUTTON_OPTIONS|KN_BUTTON):\n\t\t\t\tstrtrim(string);\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase KN_ESC:\n\t\t\tcase KeyNumType(BUTTON_CANCEL|KN_BUTTON):\n\t\t\t\tstring[0]= NULL;\n\t\t\t\tstrtrim(string);\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase KeyNumType(BUTTON_EDIT|KN_BUTTON):\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "CODE/DESCDLG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/DESCDLG.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               *** \n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DESCDLG.H                                                    *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\t\t\t\t\t Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : Jan 26, 1995                                                 *\n *                                                                                             *\n *                  Last Update : Jan 26, 1995   [MML]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*/\n\n#ifndef DESCDLG_H\n#define DESCDLG_H\n\n#include \"gadget.h\"\n\nclass DescriptionClass \n{\n\tprivate:\n\n\t\tenum DescriptionClassEnum {\n\t\t\tOPTION_WIDTH=216,\t\t\t\t\t\t\t// Width of dialog box.\n\t\t\tOPTION_HEIGHT=122,\t\t\t\t\t\t// Height of dialog box.\n\t\t\tOPTION_X=(((320 - OPTION_WIDTH) / 2) & ~7),\n\t\t\tOPTION_Y=((200 - OPTION_HEIGHT) / 2),\n\t\t\tTEXT_X=OPTION_X+32,\t\t\t \t\t\t// Title's x pos\n\t\t\tTEXT_Y=OPTION_Y+32,  \t\t\t\t\t// Add 11 for each following line\n\t\t\tBUTTON_OPTIONS=1,\t\t\t\t\t\t\t// Button number for \"Ok\"\n\t\t\tBUTTON_CANCEL,\t\t\t\t\t\t\t\n\t\t\tBUTTON_EDIT,\n\t\t\tBUTTON_X=OPTION_X+63,\t \t\t\t\t// Options button x pos\n\t\t\tBUTTON_Y=OPTION_Y+102, \t\t\t\t\t// Options button y pos\n\t\t\tEDIT_Y  =OPTION_Y+50, \t\t\t\t\t\n\t\t\tEDIT_W  =180   //204,\n\t\t};\n\n\tpublic:\n\t\tDescriptionClass(void) {};\n\t\tvoid Process(char *string);\n};\n\n#endif\n\n\n"
  },
  {
    "path": "CODE/DIAL8.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/DIAL8.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DIAL8.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/05/96                                                     *\n *                                                                                             *\n *                  Last Update : July 5, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Dial8Class::Action -- action routine for Dial8Class                                       *\n *   Dial8Class::Dial8Class -- constructor for the facing dial                                 *\n *   Dial8Class::Draw_Me -- render routine for Dial8Class                                      *\n *   Dial8Class::Get_Direction -- retrieves direction (0-255) of dial                          *\n *   Dial8Class::Set_Direction -- sets current direction (0-255) of dial                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/***************************************************************************\n * Dial8Class::Dial8Class -- constructor for the facing dial               *\n *                                                                         *\n * INPUT:                                                                  *\n *      id            button ID                                            *\n *      x,y,w,h      dimensions in window-relative pixels                  *\n *      dir         numerical initial facing value (0-255); this is the    *\n *                  value returned by WWLIB Desired_Facing8()              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/16/1994 BR : Created.                                              *\n *=========================================================================*/\nDial8Class::Dial8Class(int id, int x, int y, int w, int h, DirType dir) :\n\tControlClass(id, x, y, w, h, LEFTPRESS | LEFTHELD | LEFTRELEASE, true)\n{\n\t/*\n\t**\tCenter coordinates.\n\t*/\n\tFaceX = X + (Width / 2);\n\tFaceY = Y + (Height / 2);\n\n\t/*\n\t**\tInit directions.\n\t*/\n\tDirection = dir;\t\t\t\t\t\t\t// 0 - 255\n\tFacing = Dir_Facing(Direction);\t\t// 0 - 7\n\tOldFacing = Facing;\t\t\t\t\t\t// 0 - 7\n\n\t/*\n\t**\tCompute the drawing dimensions:  a 45-degree angle intersects a unity-\n\t**\tradius circle at (.707,.707). Make the decorations 8/10 of the radius,\n\t**\tand the line extend to 6/10 of the radius. Use Width/2 for x-radius,\n\t**\tHeight/2 for y-radius.\n\t*/\n\tFacePoint[0][0] = FaceX;\n\tFacePoint[0][1] = FaceY - (h * 8 / 2) / 10;\n\n\tFacePoint[1][0] = FaceX + (w * 7 * 8 / 2) / 100;\n\tFacePoint[1][1] = FaceY - (h * 7 * 8 / 2) / 100;\n\n\tFacePoint[2][0] = FaceX + (w * 8 / 2) / 10;\n\tFacePoint[2][1] = FaceY;\n\n\tFacePoint[3][0] = FaceX + (w * 7 * 8 / 2) / 100;\n\tFacePoint[3][1] = FaceY + (h * 7 * 8 / 2) / 100;\n\n\tFacePoint[4][0] = FaceX;\n\tFacePoint[4][1] = FaceY + (h * 8 / 2) / 10;\n\n\tFacePoint[5][0] = FaceX - (w * 7 * 8 / 2) / 100;\n\tFacePoint[5][1] = FaceY + (h * 7 * 8 / 2) / 100;\n\n\tFacePoint[6][0] = FaceX - (w * 8 / 2) / 10;\n\tFacePoint[6][1] = FaceY;\n\n\tFacePoint[7][0] = FaceX - (w * 7 * 8 / 2) / 100;\n\tFacePoint[7][1] = FaceY - (h * 7 * 8 / 2) / 100;\n\n\tFaceLine[0][0] = FaceX;\n\tFaceLine[0][1] = FaceY - (h * 6 / 2) / 10;\n\n\tFaceLine[1][0] = FaceX + (w * 7 * 6 / 2) / 100;\n\tFaceLine[1][1] = FaceY - (h * 7 * 6 / 2) / 100;\n\n\tFaceLine[2][0] = FaceX + (w * 6 / 2) / 10;\n\tFaceLine[2][1] = FaceY;\n\n\tFaceLine[3][0] = FaceX + (w * 7 * 6 / 2) / 100;\n\tFaceLine[3][1] = FaceY + (h * 7 * 6 / 2) / 100;\n\n\tFaceLine[4][0] = FaceX;\n\tFaceLine[4][1] = FaceY + (h * 6 / 2) / 10;\n\n\tFaceLine[5][0] = FaceX - (w * 7 * 6 / 2) / 100;\n\tFaceLine[5][1] = FaceY + (h * 7 * 6 / 2) / 100;\n\n\tFaceLine[6][0] = FaceX - (w * 6 / 2) / 10;\n\tFaceLine[6][1] = FaceY;\n\n\tFaceLine[7][0] = FaceX - (w * 7 * 6 / 2) / 100;\n\tFaceLine[7][1] = FaceY - (h * 7 * 6 / 2) / 100;\n}\n\n\n/***************************************************************************\n * Dial8Class::Action -- activation function for Dial8Class                *\n *                                                                         *\n * INPUT:                                                                  *\n *      flags      the reason we're being called                           *\n *      key      the KN_number that was pressed                            *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      true = event was processed, false = event not processed            *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/06/1995 BR : Created.                                              *\n *=========================================================================*/\nint Dial8Class::Action(unsigned flags, KeyNumType &key)\n{\n\tstatic int is_sel = 0;\n\n\t/*\n\t**\tWe might end up clearing the event bits. Make sure that the sticky\n\t**\tprocess is properly updated anyway.\n\t*/\n\tSticky_Process(flags);\n\n\tif (flags & LEFTPRESS) {\n\t\tis_sel = 1;\n\t}\n\n\t/*\n\t**\tIf left mouse is clicked or held, and the dial has changed its direction,\n\t**\tinvoke the parent Action routine:\n\t**\tGadgetClass::Action handles Sticky processing, & sets IsToRepaint if any\n\t**\t  flag bits are set.\n\t**\tControlClass::Action handles Peer_To_Peer notification, and substitutes\n\t**\t  'key' with the button ID if any flags are set, or 0 if no flags are set\n\t*/\n\tif (flags & LEFTPRESS || ((flags & LEFTHELD) && is_sel)) {\n\t\t/*\n\t\t**\tGet new dial position (0-255)\n\t\t*/\n\t\tDirection = (DirType)Desired_Facing8(FaceX, FaceY, Get_Mouse_X(), Get_Mouse_Y());\n\n\t\t/*\n\t\t**\tConvert to Facing value (0-7).\n\t\t*/\n\t\tFacing = Dir_Facing(Direction);\n\n\t\t/*\n\t\t**\tIf it's moved, redraw.\n\t\t*/\n\t\tif (Facing!=OldFacing) {\n\t\t\tOldFacing = Facing;\n\t\t\tControlClass::Action(flags, key);\n\t\t\treturn(true);\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tDial hasn't moved; kill the event & return\n\t\t\t*/\n\t\t\tkey = KN_NONE;\n\t\t\tControlClass::Action(0, key);\n\t\t\treturn(true);\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tOtherwise, no events have occurred; kill the event if it's a LEFTRELEASE,\n\t\t**\tand return\n\t\t*/\n\t\tif (flags & LEFTRELEASE) {\n\t\t\tkey = KN_NONE;\n\t\t\tis_sel = 0;\n\t\t}\n\t\treturn(ControlClass::Action(0, key));\n\t}\n}\n\n\n/***************************************************************************\n * Dial8Class::Draw_Me -- custom render routine for Dial8Class             *\n *                                                                         *\n * INPUT:                                                                  *\n *      forced      true = draw regardless of the current redraw flag state*\n *                                                                         *\n * OUTPUT:                                                                 *\n *      true = gadget was redrawn, false = wasn't                          *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/06/1995 BR : Created.                                              *\n *=========================================================================*/\nint Dial8Class::Draw_Me(int forced)\n{\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t**\tRedraw if parent indicates a redraw is needed\n\t*/\n\tif (ControlClass::Draw_Me(forced)) {\n\t\t/*\n\t\t**\tHide the mouse.\n\t\t*/\n\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tHide_Mouse();\n\t\t}\n\n\t\t/*\n\t\t**\tDraw background & decorations.\n\t\t*/\n\t\tDraw_Box(X, Y, Width, Height, BOXSTYLE_DOWN, true);\n\t\tfor (int i=0; i<8; i++) {\n\t\t\tDraw_Box(FacePoint[i][0] - 1, FacePoint[i][1] -1, 3, 3, BOXSTYLE_RAISED, false);\n\t\t}\n\n\t\t/*\n\t\t**\tDraw the hand & its shadow.\n\t\t*/\n\t\tLogicPage->Draw_Line(FaceX+1, FaceY+1, FaceLine[Facing][0]+1, FaceLine[Facing][1]+1, scheme->Shadow);\n\t\tLogicPage->Draw_Line(FaceX, FaceY, FaceLine[Facing][0], FaceLine[Facing][1], scheme->Highlight);\n\n\t\t/*\n\t\t**\tRestore the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tShow_Mouse();\n\t\t}\n\n\t\treturn(true);\n\t}\n\n\treturn(false);\n}\n\n\n/***************************************************************************\n * Dial8Class::Get_Direction -- retrieves direction (0-255) of dial        *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      DirType dial is pointing to                                        *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/17/1994 BR : Created.                                              *\n *=========================================================================*/\nDirType Dial8Class::Get_Direction(void) const\n{\n\treturn(Direction);\n}\n\n\n/***************************************************************************\n * Dial8Class::Set_Direction -- sets current direction (0-255) of dial     *\n *                                                                         *\n * INPUT:                                                                  *\n *      DirType to set dial to                                             *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/17/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid Dial8Class::Set_Direction(DirType dir)\n{\n\tDirection = dir;\n\tFacing = Dir_Facing(Direction);\n\tOldFacing = Facing;\n\tFlag_To_Redraw();\n}\n"
  },
  {
    "path": "CODE/DIAL8.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/DIAL8.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DIAL8.H                                                      *\n *                                                                                             *\n *                   Programmer : Bill Randolph\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *                   Start Date : 02/06/95                                                     *\n *                                                                                             *\n *                  Last Update : February 6, 1995 [BR]\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef DIAL8_H\n#define DIAL8_H\n\nclass Dial8Class : public ControlClass\n{\n\tpublic:\n\t\t/*\n\t\t** Constructor/Destructor\n\t\t*/\n\t\tDial8Class(int id, int x, int y, int w, int h, DirType dir);\n\n\t\t/*\n\t\t** Get/Set the direction the dial is currently pointing\n\t\t*/\n\t\tDirType Get_Direction(void) const;\n\t\tvoid Set_Direction(DirType dir);\n\n\t\t/*\n\t\t** Overloaded draw routine\n\t\t*/\n\t\tvirtual int Draw_Me(int forced = false);\n\n\tprotected:\n\t\t/*\n\t\t** Overloaded event processing routine\n\t\t*/\n\t\tvirtual int Action(unsigned flags, KeyNumType &key);\n\n\tprivate:\n\t\tint FaceX;\t\t\t\t\t\t// x-coord of center of face\n\t\tint FaceY;\t\t\t\t\t\t// y-coord of center of face\n\t\tint FacePoint[8][2];\t\t\t// coords of the little dial decorations\n\t\tint FaceLine[8][2];\t\t\t// coords for drawing the dial hand\n\t\tDirType Direction;\t\t\t// 0-255 numerical direction of dial\n\t\tFacingType Facing;\t\t\t// numerical facing direction of dial (0 - 7)\n\t\tFacingType OldFacing;\t\t// previous Facing value\n\n};\n\n#endif\n\n"
  },
  {
    "path": "CODE/DIALOG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/DIALOG.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DIALOG.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : July 31, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Clip_Text_Print -- Prints text with clipping and <TAB> support.                           *\n *   Dialog_Box -- draws a dialog background box                                               *\n *   Display_Place_Building -- Displays the \"place building\" dialog box.                       *\n *   Display_Select_Target -- Displays the \"choose target\" prompt.                             *\n *   Display_Status -- Display the player scenario status box.                                 *\n *   Draw_Box -- Displays a highlighted box.                                                   *\n *   Draw_Caption -- Draws a caption on a dialog box.                                          *\n *   Fancy_Text_Print -- Prints text with a drop shadow.                                       *\n *   Plain_Text_Print -- Prints text without using a color scheme                              *\n *   Redraw_Needed -- Determine if sidebar needs to be redrawn.                                *\n *   Render_Bar_Graph -- Renders a specified bargraph.                                         *\n *   Simple_Text_Print -- Prints text with a drop shadow.                                      *\n *   Window_Box -- Draws a fancy box over the specified window.                                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n#include   \"defines.h\"   //VG 10/17/96\n\nunsigned char * Font_Palette(int color);\n\n\n/***********************************************************************************************\n * Dialog_Box -- draws a dialog background box                                                 *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      x,y,w,h      the usual                                                                 *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/26/1995 BR : Created.                                                                  *\n *   07/31/1996 JLB : Uses shapes to draw the box.                                             *\n *=============================================================================================*/\nvoid Dialog_Box(int x, int y, int w, int h)\n{\n// Try to expand the box a little taller and a little wider to make room for\n// the dialog box graphics in the DOS version.\n#ifndef WIN32\n\tx = max(0, x-4);\n\ty = max(0, y-4);\n\tw = min(w+8, 320-x);\n\th = min(h+8, 200-y);\n#endif\n\n\tWindowList[WINDOW_PARTIAL][WINDOWX] = x;\n\tWindowList[WINDOW_PARTIAL][WINDOWY] = y;\n\tWindowList[WINDOW_PARTIAL][WINDOWWIDTH] = w;\n\tWindowList[WINDOW_PARTIAL][WINDOWHEIGHT] = h;\n\n\t/*\n\t**\tAlways draw to the hidpage and then blit forward.\n\t*/\n#ifdef WIN32\n\tGraphicViewPortClass * oldpage = Set_Logic_Page(HidPage);\n#else\n\tGraphicBufferClass * oldpage = Set_Logic_Page(HidPage);\n#endif\n\n\t/*\n\t**\tDraw the background block.\n\t*/\n\tint cx = w/2;\n\tint cy = h/2;\n\tvoid const * shapedata = MFCD::Retrieve(\"DD-BKGND.SHP\");\n#ifdef WIN32\n\tCC_Draw_Shape(shapedata, 0, cx-312, cy-192, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 1, cx,     cy-192, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 2, cx-312, cy,     WINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 3, cx,     cy,     WINDOW_PARTIAL, SHAPE_WIN_REL);\n#else\n\tCC_Draw_Shape(shapedata, 0, cx-156, cy-96, WINDOW_PARTIAL, SHAPE_WIN_REL);\n#endif\n\t/*\n\t**\tDraw the side strips.\n\t*/\n\tshapedata = MFCD::Retrieve(\"DD-EDGE.SHP\");\n\tfor (int yy = 0; yy < h; yy += 6) {\n\t\tCC_Draw_Shape(shapedata, 0, 7*RESFACTOR,         yy, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\t\tCC_Draw_Shape(shapedata, 1, w-((7+8)*RESFACTOR), yy, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\t}\n\n\t/*\n\t**\tDraw the border bars.\n\t*/\n\tshapedata = MFCD::Retrieve(\"DD-LEFT.SHP\");\n\tCC_Draw_Shape(shapedata, 0, 0, cy-100*RESFACTOR, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 0, 0, cy, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\n\tshapedata = MFCD::Retrieve(\"DD-RIGHT.SHP\");\n\tint rightx = w - (7*RESFACTOR);\n#ifndef WIN32\n\trightx--;\n#endif\n\tCC_Draw_Shape(shapedata, 0, rightx, cy-100*RESFACTOR, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 0, rightx, cy,\t\t\t\t\tWINDOW_PARTIAL, SHAPE_WIN_REL);\n\n\tshapedata = MFCD::Retrieve(\"DD-BOTM.SHP\");\n\tCC_Draw_Shape(shapedata, 0, cx-160*RESFACTOR, h-8*RESFACTOR, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 0, cx, h-8*RESFACTOR, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\n\tshapedata = MFCD::Retrieve(\"DD-TOP.SHP\");\n\tCC_Draw_Shape(shapedata, 0, cx-160*RESFACTOR, 0, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 0, cx, 0, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\n\t/*\n\t**\tDraw the corner caps.\n\t*/\n\tshapedata = MFCD::Retrieve(\"DD-CRNR.SHP\");\n\tCC_Draw_Shape(shapedata, 0, 0,                  0, \t\t\t\t\tWINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 1, w-(12*RESFACTOR-1), 0, \t\t\t\t\tWINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 2, 0,                  h-(12*RESFACTOR), WINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 3, w-(12*RESFACTOR-1), h-(12*RESFACTOR), WINDOW_PARTIAL, SHAPE_WIN_REL);\n\n#ifdef WIN32\n\tWWMouse->Draw_Mouse(&HidPage);\n\tHidPage.Blit(SeenBuff, x, y, x, y, w, h, false);\n\tWWMouse->Erase_Mouse(&HidPage, FALSE);\n#else\n//\tShadow_Blit(0, 0, 320, 200, HidPage, SeenPage, Map.ShadowPage->Get_Buffer());\n\tHide_Mouse();\n\tHidPage.Blit(SeenBuff);\n\tShow_Mouse();\n//\tShadow_Blit(0, 0, 320, 200, HidPage, SeenPage, ((GraphicBufferClass*)Map.Shadow_Address())->Get_Buffer());\n#endif\n\tSet_Logic_Page(oldpage);\n}\n\n\n/***********************************************************************************************\n * Draw_Box -- Displays a highlighted box.                                                     *\n *                                                                                             *\n *    This will draw a highlighted box to the logicpage. It can                                *\n *    optionally fill the box with a color as well. This is a low level                        *\n *    function and thus, it doesn't do any graphic mode color adjustments.                     *\n *                                                                                             *\n * INPUT:   x,y   -- Upper left corner of the box to be drawn (pixels).                        *\n *                                                                                             *\n *          w,h   -- Width and height of box (in pixels).                                      *\n *                                                                                             *\n *          up    -- Is the box rendered in the \"up\" stated?                                   *\n *                                                                                             *\n *          filled-- Is the box to be filled.                                                  *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1991 JLB : Created.                                                                 *\n *   05/30/1992 JLB : Embedded color codes.                                                    *\n *   07/31/1992 JLB : Depressed option added.                                                  *\n *=============================================================================================*/\nvoid Draw_Box(int x, int y, int w, int h, BoxStyleEnum up, bool filled)\n{\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t// Filler, Shadow, Hilite, Corner colors\n\n\tBoxStyleType const ButtonColors[BOXSTYLE_COUNT] = {\n\t\t{ scheme->Background, scheme->Highlight, scheme->Shadow,  scheme->Corners},\t// Down\n\t\t{ scheme->Background, scheme->Shadow, scheme->Highlight,  scheme->Corners},\t// Raised\n\t\t{ DKGREY, WHITE,  BLACK,  DKGREY},\t\t\t\t// Disabled down\n\t\t{ DKGREY, BLACK,  LTGREY, DKGREY},\t\t\t\t// Disabled up\n\t\t{ BLACK,  scheme->Box, scheme->Box,  BLACK},\t// List box\n\t\t{ BLACK,  scheme->Box, scheme->Box,  BLACK},\t// Dialog box\n\t};\n\n\tw--;\n\th--;\n\tBoxStyleType const &style = ButtonColors[up];\n\n\tif (filled) {\n\t\tLogicPage->Fill_Rect( x, y, x+w, y+h, style.Filler);\n\t}\n\n\tswitch (up) {\n\t\tcase (BOXSTYLE_BOX):\n\t\t\tLogicPage->Draw_Rect(x, y, x+w, y+h, style.Highlight);\n\t\t\tbreak;\n\n\t\tcase (BOXSTYLE_BORDER):\n\t\t\tLogicPage->Draw_Rect(x+1, y+1, x+w-1, y+h-1, style.Highlight);\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tLogicPage->Draw_Line(x, y+h, x+w, y+h, style.Shadow);\n\t\t\tLogicPage->Draw_Line(x+w, y, x+w, y+h, style.Shadow);\n\n\t\t\tLogicPage->Draw_Line(x, y, x+w, y, style.Highlight);\n\t\t\tLogicPage->Draw_Line(x, y, x, y+h, style.Highlight);\n\n\t\t\tLogicPage->Put_Pixel(x, y+h, style.Corner);\n\t\t\tLogicPage->Put_Pixel(x+w, y, style.Corner);\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * Format_Window_String -- Separates a String into Lines.                                      *\n *   This function will take a long string and break it up into lines                          *\n *   which are not longer then the window width. Any character < ' ' is                        *\n *   considered a new line marker and will be replaced by a NULL.                              *\n *                                                                                             *\n * INPUT:      char *String - string to be formated.                                           *\n *             int maxlinelen - Max length of any line in pixels.                              *\n *                                                                                             *\n * OUTPUT:     int - number of lines string is.                                                *\n *                                                                                             *\n * WARNINGS:    The string passed in will be modified - NULLs will be put                      *\n *                into each position that will be a new line.                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/27/1992  SB : Created.                                                                 *\n *   05/18/1995 JLB : Greatly revised for new font system.                                     *\n *\t  09/04/1996 BWG : Added '@' is treated as a carriage return for width calculations.\t\t  *\n *=============================================================================================*/\nint Format_Window_String(char * string, int maxlinelen, int & width, int & height)\n{\n\tint\tlinelen;\n\tint\tlines = 0;\n\twidth\t= 0;\n\theight = 0;\n\n\t// In no string was passed in, then there are no lines.\n\tif (!string) return(0);\n\n\t// While there are more letters left divide the line up.\n\twhile (*string) {\n\t\tlinelen = 0;\n\t\theight += FontHeight + FontYSpacing;\n\t\tlines++;\n\n\t\t/*\n\t\t**\tLook for special line break character and force a line break when it is\n\t\t**\tdiscovered.\n\t\t*/\n\t\tif (*string == '@') {\n\t\t\t*string = '\\r';\n\t\t}\n\n\t\t// While the current line is less then the max length...\n\t\twhile (linelen < maxlinelen && *string != '\\r' && *string != '\\0' && *string != '@') {\n\t\t\tlinelen += Char_Pixel_Width(*string++);\n\t\t}\n\n\t\t// if the line is to long...\n\t\tif (linelen >= maxlinelen) {\n\n\t\t\t/*\n\t\t\t**\tBack up to an appropriate location to break.\n\t\t\t*/\n\t\t\twhile (*string != ' ' && *string != '\\r' && *string != '\\0' && *string != '@') {\n\t\t\t\tlinelen -= Char_Pixel_Width(*string--);\n\t\t\t}\n\n\t\t}\n\n\t\t/*\n\t\t**\tRecord the largest width of the worst case string.\n\t\t*/\n\t\tif (linelen > width) {\n\t\t\twidth = linelen;\n\t\t}\n\n\t\t/*\n\t\t**\tForce a break at the end of the line.\n\t\t*/\n\t\tif (*string) {\n\t\t \t*string++ = '\\r';\n\t\t}\n\t}\n\treturn(lines);\n}\n\n\n/***********************************************************************************************\n * Window_Box -- Draws a fancy box over the specified window.                                  *\n *                                                                                             *\n *    This routine will draw a fancy (shaded) box over the specified                           *\n *    window. This is the effect used to give the polished look to                             *\n *    screen rectangles without having to use art.                                             *\n *                                                                                             *\n * INPUT:   window   -- Specified window to fill and border.                                   *\n *                                                                                             *\n *          style    -- The style to render the window.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The rendering is done to the LogicPage.                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/03/1992 JLB : Created.                                                                 *\n *   07/31/1992 JLB : Cool raised border effect.                                               *\n *   06/08/1994 JLB : Takes appropriate enumeration parameters.                                *\n *=============================================================================================*/\nvoid Window_Box(WindowNumberType window, BoxStyleEnum style)\n{\n\tint x = WindowList[window][WINDOWX];\n\tint y = WindowList[window][WINDOWY];\n\tint w = WindowList[window][WINDOWWIDTH];\n\tint h = WindowList[window][WINDOWHEIGHT];\n\n\t/*\n\t**\tIf it is to be rendered to the seenpage, then\n\t**\thide the mouse.\n\t*/\n\tif (LogicPage == (&SeenBuff)) Conditional_Hide_Mouse(x ,y, x+w, y+h);\n\n\tDraw_Box(x, y, w, h, style, true);\n\n\t/*\n\t**\tRestore the mouse if it has been hidden and return.\n\t*/\n\tif (LogicPage == &SeenBuff) Conditional_Show_Mouse();\n}\n\n\n/***********************************************************************************************\n * Simple_Text_Print -- Prints text with a drop shadow.                                        *\n *                                                                                             *\n *    This routine functions like Text_Print, but will render a drop                           *\n *    shadow (in black).                                                                       *\n *                                                                                             *\n *    The C&C gradient font colors are as follows:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t0\t\ttransparent (background)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t1\t\tforeground color for mono-color fonts only\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t2\t\tshadow under characters (\"drop shadow\")\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t3\t\tshadow all around characters (\"full shadow\")\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t4-10\tunused\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t11\t\ttop row\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t12\t\tnext row\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t13\t\tnext row\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t14\t\tnext row\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t15\t\tbottom row\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:   text  -- Pointer to text to render.                                                *\n *                                                                                             *\n *          x,y   -- Pixel coordinate for to print text.                                       *\n *                                                                                             *\n *          fore  -- Foreground color.                                                         *\n *                                                                                             *\n *          back  -- Background color.                                                         *\n *                                                                                             *\n *          flag  -- Text print control flags.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1991 JLB : Created.                                                                 *\n *   10/26/94   JLB : Handles font X spacing in a more friendly manner.                        *\n *=============================================================================================*/\nvoid Simple_Text_Print(char const * text, unsigned x, unsigned y, RemapControlType * fore, unsigned back, TextPrintType flag)\n{\n\tstatic int\t\tyspace=0;\t\t\t// Y spacing adjustment for font.\n\tstatic int\t\txspace=0;\t\t\t// Spacing adjustment for font.\n\tvoid const *\tfont=0;\t\t// Font to use.\n\tint\t\t\t\tshadow;\t\t\t\t// Requested shadow value.\n\tunsigned char\tfontpalette[16];\t// Working font palette array.\n\tint forecolor;\n\n\tif (fore == NULL) {\n\t\tfore = &ColorRemaps[PCOLOR_RED];\n\t}\n\n\t/*\n\t** Init the font palette to the given background color\n\t*/\n\tmemset(&fontpalette[0], back, 16);\n\n\tforecolor = fore->Color;\n\n\t/*\n\t**\tA gradient font always requires special fixups for the palette\n\t*/\n\tint point = (flag & (TextPrintType)0x000F);\n\tif (point == TPF_VCR || point == TPF_6PT_GRAD || point == TPF_METAL12 || point == TPF_EFNT || point == TPF_TYPE) {\n\n\t\t/*\n\t\t** If a gradient palette is specified, copy the remap table directly, otherwise\n\t\t**\tuse the foreground color as the entire font remap color.\n\t\t*/\n\t\tif (flag & TPF_USE_GRAD_PAL) {\n\t\t\tmemcpy(fontpalette, fore->FontRemap, 16);\n\t\t\tforecolor = fore->Color;\n\t\t\tif (point == TPF_TYPE) {\n\t\t\t\tforecolor = fontpalette[1];\n\t\t\t}\n\t\t} else {\n\t\t\tmemset(&fontpalette[4], fore->Color, 12);\n\t\t\tforecolor = fore->Color;\n\t\t}\n\n\t\t/*\n\t\t** Medium color: set all font colors to a medium value.  This flag\n\t\t** overrides any gradient effects.\n\t\t*/\n\t\tif (flag & TPF_MEDIUM_COLOR) {\n\t\t\tforecolor = fore->Color;\n\t\t\tmemset(&fontpalette[4], fore->Color, 12);\n\t\t}\n\n\t\t/*\n\t\t** Bright color: set all font colors to a bright value.  This flag\n\t\t** overrides any gradient effects.\n\t\t*/\n\t\tif (flag & TPF_BRIGHT_COLOR) {\n\t\t\tforecolor = fore->Bright;\n\t\t\tmemset(&fontpalette[4], fore->BrightColor, 12);\n\t\t}\n\t}\n\n\t/*\n\t**\tChange the current font if it differs from the font desired.\n\t*/\n#ifdef WIN32\n\txspace = 1;\n#else\n\txspace = 0;\n#endif\n\tyspace = 0;\n\n\tswitch (point) {\n\t\tcase TPF_SCORE:\n\t\t\tfont = ScoreFontPtr;\n\t\t\tbreak;\n\n\t\tcase TPF_METAL12:\n\t\t\tfont = Metal12FontPtr;\n\t\t\t//xspace += 1;\n\t\t\tbreak;\n\n\t\tcase TPF_MAP:\n\t\t\tfont = MapFontPtr;\n\t\t\txspace -= 1;\n\t\t\tbreak;\n\n\t\tcase TPF_VCR:\n\t\t\tfont = VCRFontPtr;\n\t\t\tbreak;\n\n\t\tcase TPF_6PT_GRAD:\n\t\t\tfont = GradFont6Ptr;\n\t\t\txspace -= 1;\n\t\t\tbreak;\n\n\t\tcase TPF_3POINT:\n\t\t\txspace += 1;\n\t\t\tfont = Font3Ptr;\n\t\t\tflag = flag & ~(TPF_DROPSHADOW|TPF_FULLSHADOW|TPF_NOSHADOW);\n\t\t\tbreak;\n\n\t\tcase TPF_6POINT:\n\t\t\tfont = Font6Ptr;\n\t\t\txspace -= 1;\n\t\t\tbreak;\n\n\t\tcase TPF_EFNT:\n\t\t\tfont = EditorFont;\n#ifdef WIN32\n\t\t\tyspace += 1;\n\t\t\txspace -= 1;\n#endif\n\t\t\txspace -= 1;\n\t\t\tbreak;\n\n\t\tcase TPF_8POINT:\n\t\t\tfont = Font8Ptr;\n#ifdef WIN32\n\t\t\txspace -= 2;\n\t\t\tyspace -= 4;\n#else\n\t\t\txspace -= 1;\n\t\t\tyspace -= 2;\n#endif\n\t\t\tbreak;\n\n\t\tcase TPF_LED:\n#ifdef WIN32\n\t\t\txspace -= 4;\n#else\n\t\t\txspace -= 2;\n#endif\n\t\t\tfont = FontLEDPtr;\n\t\t\tbreak;\n\n\t\tcase TPF_TYPE:\n\t\t\tfont = TypeFontPtr;\n\t\t\txspace -= 1;\n\n#ifdef WOLAPI_INTEGRATION\n\t\t   xspace -= 2;\n\t\t   yspace += 2;\n#else\t//\tI am implicitly assuming that TPF_TYPE was no longer being used, before I came along, despite the following. ajw\n#ifdef GERMAN\n\t\t   yspace += 4;   //VG 10/17/96\n#endif\n#endif\n\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tfont = FontPtr;\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tChange the current font palette according to the dropshadow flags.\n\t*/\n\tshadow = (flag & (TPF_NOSHADOW|TPF_DROPSHADOW|TPF_FULLSHADOW|TPF_LIGHTSHADOW));\n\tswitch (shadow) {\n\n\t\t/*\n\t\t**\tThe text is rendered plain.\n\t\t*/\n\t\tcase TPF_NOSHADOW:\n\t\t\tfontpalette[2] = back;\n\t\t\tfontpalette[3] = back;\n\t\t\txspace -= 1;\n#ifdef WIN32\n\t\t\tyspace -= 2;\n#else\n\t\t\tyspace -= 1;\n#endif\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThe text is rendered with a simple\n\t\t**\tdrop shadow.\n\t\t*/\n\t\tcase TPF_DROPSHADOW:\n\t\t\tfontpalette[2] = BLACK;\n\t\t\tfontpalette[3] = back;\n\t\t\txspace -= 1;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tSpecial engraved text look for the options\n\t\t**\tdialog system.\n\t\t*/\n\t\tcase TPF_LIGHTSHADOW:\n\t\t\tfontpalette[2] = ((14 * 16) + 7)+1;\n\t\t\tfontpalette[3] = back;\n\t\t\txspace -= 1;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tEach letter is surrounded by black. This is used\n\t\t**\twhen the text will be over a non-plain background.\n\t\t*/\n\t\tcase TPF_FULLSHADOW:\n\t\t\tfontpalette[2] = BLACK;\n\t\t\tfontpalette[3] = BLACK;\n\t\t\txspace -= 1;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tif (point != TPF_TYPE) {\n\t\tfontpalette[0] = back;\n\t\tfontpalette[1] = fore->Color;\n\t}\n\n\t/*\n\t**\tSet the font and spacing according to the values they should be.\n\t*/\n\tFontXSpacing = xspace;\n\tFontYSpacing = yspace;\n\tSet_Font(font);\n\tSet_Font_Palette(fontpalette);\n\n\t/*\n\t**\tDisplay the (centered) message if there is one.\n\t*/\n\tif (text && *text) {\n\t\tswitch (flag & (TPF_CENTER|TPF_RIGHT)) {\n\t\t\tcase TPF_CENTER:\n\t\t\t\tx -= String_Pixel_Width(text)>>1;\n\t\t\t\tbreak;\n\n\t\t\tcase TPF_RIGHT:\n\t\t\t\tx -= String_Pixel_Width(text);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif ((unsigned)x < LogicPage->Get_Width() && (unsigned)y < LogicPage->Get_Height()) {\n\t\t\tLogicPage->Print(text, x, y, forecolor, back);\n//\t\t\tLogicPage->Print(text, x, y, fore->Color, back);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Fancy_Text_Print -- Prints text with a drop shadow.                                         *\n *                                                                                             *\n *    This routine functions like Text_Print, but will render a drop                           *\n *    shadow (in black).                                                                       *\n *                                                                                             *\n * INPUT:   text  -- Text number to print.                                                     *\n *                                                                                             *\n *          x,y   -- Pixel coordinate for to print text.                                       *\n *                                                                                             *\n *          fore  -- Foreground color.                                                         *\n *                                                                                             *\n *          back  -- Background color.                                                         *\n *                                                                                             *\n *          flag  -- Text print control flags.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine is much slower than normal text print and                          *\n *             if rendered to the SEENPAGE, the intermediate rendering                         *\n *             steps could be visible.                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/29/1994 JLB : Created                                                                  *\n *=============================================================================================*/\nvoid Fancy_Text_Print(int text, unsigned x, unsigned y, RemapControlType * fore, unsigned back, TextPrintType flag, ...)\n{\n\tchar\t\tbuffer[512];\t\t// Working staging buffer.\n\tva_list\targ;\t\t\t\t\t// Argument list var.\n\n\t/*\n\t**\tIf the text number is valid, then process it.\n\t*/\n\tif (text != TXT_NONE) {\n\t\tva_start(arg, flag);\n\n\t\t/*\n\t\t**\tThe text string must be locked since the vsprintf function doesn't know\n\t\t**\thow to handle EMS pointers.\n\t\t*/\n\t\tchar const * tptr = Text_String(text);\n\t\tvsprintf(buffer, tptr, arg);\n\t\tva_end(arg);\n\n\t\tSimple_Text_Print(buffer, x, y, fore, back, flag);\n\t} else {\n\n\t\t/*\n\t\t**\tJust the flags are to be changed, since the text number is TXT_NONE.\n\t\t*/\n\t\tSimple_Text_Print((char const *)0, x, y, fore, back, flag);\n\t}\n}\n\n\n/***********************************************************************************************\n * Fancy_Text_Print -- Prints text with a drop shadow.                                         *\n *                                                                                             *\n *    This routine functions like Text_Print, but will render a drop                           *\n *    shadow (in black).                                                                       *\n *                                                                                             *\n * INPUT:   text  -- Pointer to text to render.                                                *\n *                                                                                             *\n *          x,y   -- Pixel coordinate for to print text.                                       *\n *                                                                                             *\n *          fore  -- Foreground color.                                                         *\n *                                                                                             *\n *          back  -- Background color.                                                         *\n *                                                                                             *\n *          flag  -- Text print control flags.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine is much slower than normal text print and                          *\n *             if rendered to the SEENPAGE, the intermediate rendering                         *\n *             steps could be visible.                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1991 JLB : Created.                                                                 *\n *   10/26/94   JLB : Handles font X spacing in a more friendly manner.                        *\n *   11/29/1994 JLB : Separated actual draw action.                                            *\n *=============================================================================================*/\nvoid Fancy_Text_Print(char const * text, unsigned x, unsigned y, RemapControlType * fore, unsigned back, TextPrintType flag, ...)\n{\n\tchar\t\tbuffer[512];\t\t// Working staging buffer.\n\tva_list\targ;\t\t\t\t\t// Argument list var.\n\n\t/*\n\t**\tIf there is a valid text string pointer then build the final string into the\n\t**\tworking buffer before sending it to the simple string printing routine.\n\t*/\n\tif (text) {\n\n\t\t/*\n\t\t**\tSince vsprintf doesn't know about EMS pointers, be sure to surround this\n\t\t**\tcall with locking code.\n\t\t*/\n\t\tva_start(arg, flag);\n\t\tvsprintf(buffer, text, arg);\n\t\tva_end(arg);\n\n\t\tSimple_Text_Print(buffer, x, y, fore, back, flag);\n\t} else {\n\n\t\t/*\n\t\t**\tJust the flags are desired to be changed, so call the simple print routine with\n\t\t**\ta NULL text pointer.\n\t\t*/\n\t\tSimple_Text_Print((char const *)0, x, y, fore, back, flag);\n\t}\n}\n\n\n/***********************************************************************************************\n * Clip_Text_Print -- Prints text with clipping and <TAB> support.                             *\n *                                                                                             *\n *    Use this routine to print text that that should be clipped at an arbitrary right margin  *\n *    as well as possibly recognizing <TAB> characters. Typical users of this routine would    *\n *    be list boxes.                                                                           *\n *                                                                                             *\n * INPUT:   text  -- Reference to the text to print.                                           *\n *                                                                                             *\n *          x,y   -- Pixel coordinate of the upper left corner of the text position.           *\n *                                                                                             *\n *          fore  -- The foreground color to use.                                              *\n *                                                                                             *\n *          back  -- The background color to use.                                              *\n *                                                                                             *\n *          flag  -- The text print flags to use.                                              *\n *                                                                                             *\n *          width -- The maximum pixel width to draw the text. Extra characters beyond this    *\n *                   point will not be printed.                                                *\n *                                                                                             *\n *          tabs  -- Optional pointer to a series of pixel tabstop positions.                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Conquer_Clip_Text_Print(char const * text, unsigned x, unsigned y, RemapControlType * fore, unsigned back, TextPrintType flag, int width, int const * tabs)\n{\n\tchar buffer[512];\n\n\tif (text) {\n\t\tstrcpy(buffer, text);\n\n\t\t/*\n\t\t**\tSet the font and spacing characteristics according to the flag\n\t\t**\tvalue passed in.\n\t\t*/\n\t\tSimple_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, flag);\n\n\t\tchar * source = &buffer[0];\n\t\tunsigned offset = 0;\n\t\tint processing = true;\n\t\twhile (processing && offset < width) {\n\t\t\tchar * ptr = strchr(source, '\\t');\n\n\t\t\t/*\n\t\t\t**\tZap the tab character. It will be processed later.\n\t\t\t*/\n\t\t\tif (ptr) {\n\t\t\t\t*ptr = '\\0';\n\t\t\t}\n\n\t\t\tif (*source) {\n\n\t\t\t\t/*\n\t\t\t\t**\tScan forward until the end of the string is reached or the\n\t\t\t\t**\tmaximum width, whichever comes first.\n\t\t\t\t*/\n\t\t\t\tint w = 0;\n\t\t\t\tchar * bptr = source;\n\t\t\t\tdo {\n\t\t\t\t\tw += Char_Pixel_Width(*bptr++);\n\t\t\t\t} while (*bptr && offset+w < width);\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the maximum width has been exceeded, then remove the last\n\t\t\t\t**\tcharacter and signal that further processing is not necessary.\n\t\t\t\t*/\n\t\t\t\tif (offset+w >= width) {\n\t\t\t\t\tbptr--;\n\t\t\t\t\tw -= Char_Pixel_Width(*bptr);\n\t\t\t\t\t*bptr = '\\0';\n\t\t\t\t\tprocessing = 0;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tPrint this text block and advance the offset accordingly.\n\t\t\t\t*/\n\t\t\t\tSimple_Text_Print(source, x+offset, y, fore, back, flag);\n\t\t\t\toffset += w;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf a <TAB> was the terminator for this text block, then advance\n\t\t\t**\tto the next tabstop.\n\t\t\t*/\n\t\t\tif (ptr) {\n\t\t\t\tif (tabs) {\n\t\t\t\t\twhile (offset > *tabs) {\n\t\t\t\t\t\ttabs++;\n\t\t\t\t\t}\n\t\t\t\t\toffset = *tabs;\n\t\t\t\t} else {\n\t\t\t\t\toffset = ((offset+1 / 50) + 1) * 50;\n\t\t\t\t}\n\t\t\t\tsource = ptr+1;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/***************************************************************************\n * Plain_Text_Print -- Prints text without using a color scheme            *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\ttext\t\ttext to print\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tx,y\t\tcoords to print at\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tfore\t\tdesired foreground color\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tback\t\tdesired background color\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tflag\t\ttext print control flags\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tDo not use the gradient control flag with this routine!  For \t\t\t*\n *\t\ta gradient appearance, use Fancy_Text_Print.\t\t\t\t\t\t\t\t\t*\n *\t\tDespite this routine's name, it is actually faster to call\t\t\t\t*\n *\t\tFancy_Text_Print than this routine.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/05/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Plain_Text_Print(int text, unsigned x, unsigned y, unsigned fore, unsigned back, TextPrintType flag, ...)\n{\n\tRemapControlType scheme;\n\n\tmemset(&scheme, 0, sizeof(RemapControlType));\n\tmemset(&(scheme.FontRemap[4]), fore, 12);\n\n\tscheme.BrightColor = fore;\n\tscheme.Color = fore;\n\tscheme.Shadow = fore;\n\tscheme.Background = fore;\n\tscheme.Corners = fore;\n\tscheme.Highlight = fore;\n\tscheme.Box = fore;\n\tscheme.Bright = fore;\n\tscheme.Underline = fore;\n\tscheme.Bar = fore;\n\n\tFancy_Text_Print(text, x, y, &scheme, back, flag);\n}\n\n\n/***************************************************************************\n * Plain_Text_Print -- Prints text without using a color scheme            *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\ttext\t\ttext to print\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tx,y\t\tcoords to print at\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tfore\t\tdesired foreground color\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tback\t\tdesired background color\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tflag\t\ttext print control flags\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tDo not use the gradient control flag with this routine!  For \t\t\t*\n *\t\ta gradient appearance, use Fancy_Text_Print.\t\t\t\t\t\t\t\t\t*\n *\t\tDespite this routine's name, it is actually faster to call\t\t\t\t*\n *\t\tFancy_Text_Print than this routine.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/05/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Plain_Text_Print(char const * text, unsigned x, unsigned y, unsigned fore, unsigned back, TextPrintType flag, ...)\n{\n\tRemapControlType scheme;\n\n\tmemset(&scheme, 0, sizeof(RemapControlType));\n\tmemset(&(scheme.FontRemap[4]), fore, 12);\n\n\tscheme.BrightColor = fore;\n\tscheme.Color = fore;\n\tscheme.Shadow = fore;\n\tscheme.Background = fore;\n\tscheme.Corners = fore;\n\tscheme.Highlight = fore;\n\tscheme.Box = fore;\n\tscheme.Bright = fore;\n\tscheme.Underline = fore;\n\tscheme.Bar = fore;\n\n\tFancy_Text_Print(text, x, y, &scheme, back, flag);\n}\n\n\n\nunsigned char * Font_Palette(int color)\n{\n\tstatic unsigned char _fpalette[16];\n\n\tmemset(_fpalette, '\\0', sizeof(_fpalette));\n\tmemset(&_fpalette[11], color, 5);\n\treturn(_fpalette);\n}\n\n\n\n/***********************************************************************************************\n * Draw_Caption -- Draws a caption on a dialog box.                                            *\n *                                                                                             *\n *    This routine draws the caption text and any fancy filigree that the dialog may require.  *\n *                                                                                             *\n * INPUT:   text  -- The text of the caption. This is the text number.                         *\n *                                                                                             *\n *          x,y   -- The dialog box X and Y pixel coordinate of the upper left corner.         *\n *                                                                                             *\n *          w     -- The width of the dialog box (in pixels).                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Draw_Caption(int text, int x, int y, int w)\n{\n\tDraw_Caption(Text_String(text), x, y, w);\n}\n\n\nvoid Draw_Caption(char const * text, int x, int y, int w)\n{\n\t/*\n\t**\tDraw the caption.\n\t*/\n\tif (text != NULL && *text != '\\0') {\n\t\tif (Debug_Map) {\n\t\t\tFancy_Text_Print(text, w/2 + x, (2 * RESFACTOR) + y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER|TPF_EFNT|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\t\t} else {\n\t\t\tFancy_Text_Print(text, w/2 + x, (8 * RESFACTOR) + y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER|TPF_TEXT);\n\t\t\tint length = String_Pixel_Width(text);\n\t\t\tLogicPage->Draw_Line((x+(w/2))-(length/2), y+FontHeight+FontYSpacing + (8 * RESFACTOR), (x+(w/2))+(length/2),\n\t\t\t\ty+FontHeight+FontYSpacing + (8 * RESFACTOR), GadgetClass::Get_Color_Scheme()->Box);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "CODE/DIBAPI.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef DIBAPI_H\n#define DIBAPI_H\n/*\n *  dibapi.h\n *\n *  Copyright (c) 1991 Microsoft Corporation. All rights reserved\n *\n *  Header file for Device-Independent Bitmap (DIB) API.  Provides\n *  function prototypes and constants for the following functions:\n *\n *  BitmapToDIB()        - Creates a DIB from a bitmap\n *  ChangeBitmapFormat() - Changes a bitmap to a specified DIB format\n *  ChangeDIBFormat()    - Changes a DIB's BPP and/or compression format\n *  CopyScreenToBitmap() - Copies entire screen to a standard Bitmap\n *  CopyScreenToDIB()    - Copies entire screen to a DIB\n *  CopyWindowToBitmap() - Copies a window to a standard Bitmap\n *  CopyWindowToDIB()    - Copies a window to a DIB\n *  CreateDIBPalette()   - Creates a palette from a DIB\n *  CreateDIB()          - Creates a new DIB\n *  DestroyDIB()         - Deletes DIB when finished using it\n *  DIBError()           - Displays message box with error message\n *  DIBHeight()          - Gets the DIB height\n *  DIBNumColors()       - Calculates number of colors in the DIB's color table\n *  DIBToBitmap()        - Creates a bitmap from a DIB\n *  DIBWidth()           - Gets the DIB width\n *  FindDIBBits()        - Sets pointer to the DIB bits\n *  GetSystemPalette()   - Gets the current palette\n *  LoadDIB()            - Loads a DIB from a file\n *  PaintBitmap()        - Displays standard bitmap in the specified DC\n *  PaintDIB()           - Displays DIB in the specified DC\n *  PalEntriesOnDevice() - Gets the number of palette entries\n *  PaletteSize()        - Calculates the buffer size required by a palette\n *  PrintDIB()           - Prints the specified DIB\n *  PrintScreen()        - Prints the entire screen\n *  PrintWindow()        - Prints all or part of a window\n *  SaveDIB()            - Saves the specified dib in a file\n *\n * See the file DIBAPI.TXT for more information about these functions.\n *\n *  ajw added\n *  LoadDIB_FromMemory() - Loads a DIB from BMP file data located at a location in memory.\n *\n */\n\n\n/* Handle to a DIB */\n#define HDIB HANDLE\n\n\n/* Print Area selection */\n#define PW_WINDOW        1\n#define PW_CLIENT        2\n\n\n/* Print Options selection */\n#define PW_BESTFIT       1\n#define PW_STRETCHTOPAGE 2\n#define PW_SCALE         3\n\n/* DIB Macros*/\n\n// WIDTHBYTES performs DWORD-aligning of DIB scanlines.  The \"bits\"\n// parameter is the bit count for the scanline (biWidth * biBitCount),\n// and this macro returns the number of DWORD-aligned bytes needed \n// to hold those bits.\n\n#define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4)\n\n/* Error constants */\nenum {\n      ERR_MIN = 0,                     // All error #s >= this value\n      ERR_NOT_DIB = 0,                 // Tried to load a file, NOT a DIB!\n      ERR_MEMORY,                      // Not enough memory!\n      ERR_READ,                        // Error reading file!\n      ERR_LOCK,                        // Error on a GlobalLock()!\n      ERR_OPEN,                        // Error opening a file!\n      ERR_CREATEPAL,                   // Error creating palette.\n      ERR_GETDC,                       // Couldn't get a DC.\n      ERR_CREATEDDB,                   // Error create a DDB.\n      ERR_STRETCHBLT,                  // StretchBlt() returned failure.\n      ERR_STRETCHDIBITS,               // StretchDIBits() returned failure.\n      ERR_SETDIBITSTODEVICE,           // SetDIBitsToDevice() failed.\n      ERR_STARTDOC,                    // Error calling StartDoc().\n      ERR_NOGDIMODULE,                 // Couldn't find GDI module in memory.\n      ERR_SETABORTPROC,                // Error calling SetAbortProc().\n      ERR_STARTPAGE,                   // Error calling StartPage().\n      ERR_NEWFRAME,                    // Error calling NEWFRAME escape.\n      ERR_ENDPAGE,                     // Error calling EndPage().\n      ERR_ENDDOC,                      // Error calling EndDoc().\n      ERR_SETDIBITS,                   // Error calling SetDIBits().\n      ERR_FILENOTFOUND,                // Error opening file in GetDib()\n      ERR_INVALIDHANDLE,               // Invalid Handle\n      ERR_DIBFUNCTION,                 // Error on call to DIB function\n      ERR_MAX                          // All error #s < this value\n     };\n\n\n\n/* Function prototypes */\n\nHDIB      FAR  BitmapToDIB (HBITMAP hBitmap, HPALETTE hPal);\nHDIB      FAR  ChangeBitmapFormat (HBITMAP  hBitmap,\n                                   WORD     wBitCount,\n                                   DWORD    dwCompression,\n                                   HPALETTE hPal);\nHDIB      FAR  ChangeDIBFormat (HDIB hDIB, WORD wBitCount,\n                                DWORD dwCompression);\nHBITMAP   FAR  CopyScreenToBitmap (LPRECT);\nHDIB      FAR  CopyScreenToDIB (LPRECT);\nHBITMAP   FAR  CopyWindowToBitmap (HWND, WORD);\nHDIB      FAR  CopyWindowToDIB (HWND, WORD);\nHPALETTE  FAR  CreateDIBPalette (HDIB hDIB);\nHDIB      FAR  CreateDIB(DWORD, DWORD, WORD);\nWORD      FAR  DestroyDIB (HDIB);\nvoid      FAR  DIBError (int ErrNo);\nDWORD     FAR  DIBHeight (LPCSTR lpDIB);\nWORD      FAR  DIBNumColors (LPCSTR lpDIB);\nHBITMAP   FAR  DIBToBitmap (HDIB hDIB, HPALETTE hPal);\nDWORD     FAR  DIBWidth (LPCSTR lpDIB);\nLPSTR     FAR  FindDIBBits (LPCSTR lpDIB);\nHPALETTE  FAR  GetSystemPalette (void);\nHDIB      FAR  LoadDIB (LPSTR);\nBOOL      FAR  PaintBitmap (HDC, LPRECT, HBITMAP, LPRECT, HPALETTE);\nBOOL      FAR  PaintDIB (HDC, LPRECT, HDIB, LPRECT, HPALETTE);\nint       FAR  PalEntriesOnDevice (HDC hDC);\nWORD      FAR  PaletteSize (LPCSTR lpDIB);\nWORD      FAR  PrintDIB (HDIB, WORD, WORD, WORD, LPSTR);\nWORD      FAR  PrintScreen (LPRECT, WORD, WORD, WORD, LPSTR);\nWORD      FAR  PrintWindow (HWND, WORD, WORD, WORD, WORD, LPSTR);\nWORD      FAR  SaveDIB (HDIB, LPSTR);\n\n//\tajw added\nHDIB\tLoadDIB_FromMemory( const unsigned char* pData, DWORD dwBitsSize );\n\n#endif\n"
  },
  {
    "path": "CODE/DIBFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n//*******************************************************************\n//\n//  file.c\n//\n//  Source file for Device-Independent Bitmap (DIB) API.  Provides\n//  the following functions:\n//\n//  SaveDIB()           - Saves the specified dib in a file\n//  LoadDIB()           - Loads a DIB from a file\n//  DestroyDIB()        - Deletes DIB when finished using it\n//\n// Development Team: Mark Bader\n//                   Patrick Schreiber\n//                   Garrett McAuliffe\n//                   Eric Flo\n//                   Tony Claflin\n//\n// Written by Microsoft Product Support Services, Developer Support.\n// COPYRIGHT:\n//\n//   (C) Copyright Microsoft Corp. 1993.  All rights reserved.\n//\n//   You have a royalty-free right to use, modify, reproduce and\n//   distribute the Sample Files (and/or any modified version) in\n//   any way you find useful, provided that you agree that\n//   Microsoft has no warranty obligations or liability for any\n//   Sample Application Files which are modified.\n//\n//*******************************************************************\n\n#include <windows.h>\n#include <string.h>\n#include <stdio.h>\n#include <math.h>\n#include <io.h>\n#include <direct.h>\n#include <stdlib.h>\n#include \"dibutil.h\"\n#include \"dibapi.h\"\n\n//#include \"WolDebug.h\"\n\n/*\n * Dib Header Marker - used in writing DIBs to files\n */\n#define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B')\n\n/*********************************************************************\n *\n * Local Function Prototypes\n *\n *********************************************************************/\n\n\nHANDLE ReadDIBFile(int);\nBOOL MyRead(int, LPSTR, DWORD);\nBOOL SaveDIBFile(void);\nBOOL WriteDIB(LPSTR, HANDLE);\nDWORD PASCAL MyWrite(int, VOID FAR *, DWORD);\n\n/*************************************************************************\n *\n * LoadDIB()\n *\n * Loads the specified DIB from a file, allocates memory for it,\n * and reads the disk file into the memory.\n *\n *\n * Parameters:\n *\n * LPSTR lpFileName - specifies the file to load a DIB from\n *\n * Returns: A handle to a DIB, or NULL if unsuccessful.\n *\n * NOTE: The DIB API were not written to handle OS/2 DIBs; This\n * function will reject any file that is not a Windows DIB.\n *\n * History:   Date      Author       Reason\n *            9/15/91   Mark Bader   Based on DIBVIEW\n *\n *************************************************************************/\n\n\nHDIB FAR LoadDIB(LPSTR lpFileName)\n{\n   HDIB hDIB;\n   int hFile;\n   OFSTRUCT ofs;\n\n   /*\n    * Set the cursor to a hourglass, in case the loading operation\n    * takes more than a sec, the user will know what's going on.\n    */\n\n   SetCursor(LoadCursor(NULL, IDC_WAIT));\n   if ((hFile = OpenFile(lpFileName, &ofs, OF_READ)) != -1)\n   {\n      hDIB = ReadDIBFile(hFile);\n      _lclose(hFile);\n      SetCursor(LoadCursor(NULL, IDC_ARROW));\n      return hDIB;\n   }\n   else\n   {\n//      DIBError(ERR_FILENOTFOUND);\n      SetCursor(LoadCursor(NULL, IDC_ARROW));\n      return NULL;\n   }\n}\n\n\n/*************************************************************************\n *\n * SaveDIB()\n *\n * Saves the specified DIB into the specified file name on disk.  No\n * error checking is done, so if the file already exists, it will be\n * written over.\n *\n * Parameters:\n *\n * HDIB hDib - Handle to the dib to save\n *\n * LPSTR lpFileName - pointer to full pathname to save DIB under\n *\n * Return value: 0 if successful, or one of:\n *        ERR_INVALIDHANDLE\n *        ERR_OPEN\n *        ERR_LOCK\n *\n * History:\n *\n * NOTE: The DIB API were not written to handle OS/2 DIBs, so this\n * function will not save a file if it is not a Windows DIB.\n *\n * History:   Date      Author       Reason\n *            9/15/91   Mark Bader   Taken from DIBVIEW (which was taken\n *                                      from SHOWDIB)\n *            1/30/92   Mark Bader   Fixed problem of writing too many \n *                                      bytes to the file\n *            6/24/92   Mark Bader   Added check for OS/2 DIB\n *\n *************************************************************************/\n\n\nWORD FAR SaveDIB(HDIB hDib, LPSTR lpFileName)\n{\n   BITMAPFILEHEADER bmfHdr; // Header for Bitmap file\n   LPBITMAPINFOHEADER lpBI;   // Pointer to DIB info structure\n   int fh;     // file handle for opened file\n   OFSTRUCT of;     // OpenFile structure\n   DWORD dwDIBSize;\n   DWORD dwError;   // Error return from MyWrite\n\n   if (!hDib)\n      return ERR_INVALIDHANDLE;\n   fh = OpenFile(lpFileName, &of, OF_CREATE | OF_READWRITE);\n   if (fh == -1)\n      return ERR_OPEN;\n\n   /*\n    * Get a pointer to the DIB memory, the first of which contains\n    * a BITMAPINFO structure\n    */\n   lpBI = (LPBITMAPINFOHEADER)GlobalLock(hDib);\n   if (!lpBI)\n      return ERR_LOCK;\n\n   // Check to see if we're dealing with an OS/2 DIB.  If so, don't\n   // save it because our functions aren't written to deal with these\n   // DIBs.\n\n   if (lpBI->biSize != sizeof(BITMAPINFOHEADER))\n   {\n     GlobalUnlock(hDib);\n     return ERR_NOT_DIB;\n   }\n\n   /*\n    * Fill in the fields of the file header\n    */\n\n   /* Fill in file type (first 2 bytes must be \"BM\" for a bitmap) */\n   bmfHdr.bfType = DIB_HEADER_MARKER;  // \"BM\"\n\n   // Calculating the size of the DIB is a bit tricky (if we want to\n   // do it right).  The easiest way to do this is to call GlobalSize()\n   // on our global handle, but since the size of our global memory may have\n   // been padded a few bytes, we may end up writing out a few too\n   // many bytes to the file (which may cause problems with some apps,\n   // like HC 3.0).\n   //\n   // So, instead let's calculate the size manually.\n   //\n   // To do this, find size of header plus size of color table.  Since the\n   // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains\n   // the size of the structure, let's use this.\n\n   dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPSTR)lpBI);  // Partial Calculation\n\n   // Now calculate the size of the image\n\n   if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) {\n\n      // It's an RLE bitmap, we can't calculate size, so trust the\n      // biSizeImage field\n\n      dwDIBSize += lpBI->biSizeImage;\n      }\n   else {\n      DWORD dwBmBitsSize;  // Size of Bitmap Bits only\n\n      // It's not RLE, so size is Width (DWORD aligned) * Height\n\n      dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;\n\n      dwDIBSize += dwBmBitsSize;\n      \n      // Now, since we have calculated the correct size, why don't we\n      // fill in the biSizeImage field (this will fix any .BMP files which \n      // have this field incorrect).\n\n      lpBI->biSizeImage = dwBmBitsSize;\n      }\n\n\n   // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)\n                   \n   bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);\n   bmfHdr.bfReserved1 = 0;\n   bmfHdr.bfReserved2 = 0;\n\n   /*\n    * Now, calculate the offset the actual bitmap bits will be in\n    * the file -- It's the Bitmap file header plus the DIB header,\n    * plus the size of the color table.\n    */\n   bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize +\n                      PaletteSize((LPSTR)lpBI);\n\n   /* Write the file header */\n   _lwrite(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));\n\n   /*\n    * Write the DIB header and the bits -- use local version of\n    * MyWrite, so we can write more than 32767 bytes of data\n    */\n   dwError = MyWrite(fh, (LPSTR)lpBI, dwDIBSize);\n   GlobalUnlock(hDib);\n   _lclose(fh);\n\n   if (dwError == 0)\n     return ERR_OPEN; // oops, something happened in the write\n   else\n     return 0; // Success code\n}\n\n\n/*************************************************************************\n *\n * DestroyDIB ()\n *\n * Purpose:  Frees memory associated with a DIB\n *\n * Returns:  Nothing\n *\n * History:   Date      Author       Reason\n *            9/15/91   Mark Bader   Created\n *\n *************************************************************************/\n\n\nWORD FAR DestroyDIB(HDIB hDib)\n{\n   GlobalFree(hDib);\n   return 0;\n}\n\n\n//************************************************************************\n//\n// Auxiliary Functions which the above procedures use\n//\n//************************************************************************\n\n\n/*************************************************************************\n *\n * Function:  ReadDIBFile (int)\n *\n *  Purpose:  Reads in the specified DIB file into a global chunk of\n *            memory.\n *\n *  Returns:  A handle to a dib (hDIB) if successful.\n *            NULL if an error occurs.\n *\n * Comments:  BITMAPFILEHEADER is stripped off of the DIB.  Everything\n *            from the end of the BITMAPFILEHEADER structure on is\n *            returned in the global memory handle.\n *\n *\n * NOTE: The DIB API were not written to handle OS/2 DIBs, so this\n * function will reject any file that is not a Windows DIB.\n *\n * History:   Date      Author       Reason\n *            9/15/91   Mark Bader   Based on DIBVIEW\n *            6/25/92   Mark Bader   Added check for OS/2 DIB\n *            7/21/92   Mark Bader   Added code to deal with bfOffBits\n *                                     field in BITMAPFILEHEADER      \n *            9/11/92   Mark Bader   Fixed Realloc Code to free original mem\n *\n *************************************************************************/\n\nHANDLE ReadDIBFile(int hFile)\n{\n   BITMAPFILEHEADER bmfHeader;\n   DWORD dwBitsSize;\n   UINT nNumColors;   // Number of colors in table\n   HANDLE hDIB;        \n   HANDLE hDIBtmp;    // Used for GlobalRealloc() //MPB\n   LPBITMAPINFOHEADER lpbi;\n   DWORD offBits;\n\n   /*\n    * get length of DIB in bytes for use when reading\n    */\n\n   dwBitsSize = filelength(hFile);\n\n   // Allocate memory for header & color table.\tWe'll enlarge this\n   // memory as needed.\n\n   hDIB = GlobalAlloc(GMEM_MOVEABLE,\n       (DWORD)(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)));\n   \n   if (!hDIB) return NULL;\n\n   lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);\n   if (!lpbi) \n   {\n     GlobalFree(hDIB);\n     return NULL;\n   }\n\n   // read the BITMAPFILEHEADER from our file\n\n   if (sizeof (BITMAPFILEHEADER) != _lread (hFile, (LPSTR)&bmfHeader, sizeof (BITMAPFILEHEADER)))\n     goto ErrExit;\n\n   if (bmfHeader.bfType != 0x4d42)\t/* 'BM' */\n     goto ErrExit;\n\n   // read the BITMAPINFOHEADER\n\n   if (sizeof(BITMAPINFOHEADER) != _lread (hFile, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)))\n     goto ErrExit;\n\n   // Check to see that it's a Windows DIB -- an OS/2 DIB would cause\n   // strange problems with the rest of the DIB API since the fields\n   // in the header are different and the color table entries are\n   // smaller.\n   //\n   // If it's not a Windows DIB (e.g. if biSize is wrong), return NULL.\n\n   if (lpbi->biSize == sizeof(BITMAPCOREHEADER))\n     goto ErrExit;\n\n   // Now determine the size of the color table and read it.  Since the\n   // bitmap bits are offset in the file by bfOffBits, we need to do some\n   // special processing here to make sure the bits directly follow\n   // the color table (because that's the format we are susposed to pass\n   // back)\n   nNumColors = (UINT)lpbi->biClrUsed;\n   if (!nNumColors)\n    {\n      // no color table for 24-bit, default size otherwise\n      if (lpbi->biBitCount != 24)\n        nNumColors = 1 << lpbi->biBitCount; /* standard size table */\n    }\n\n   // fill in some default values if they are zero\n   if (lpbi->biClrUsed == 0)\n     lpbi->biClrUsed = nNumColors;\n\n   if (lpbi->biSizeImage == 0)\n   {\n     lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3)\n\t\t\t * lpbi->biHeight;\n   }\n\n   // get a proper-sized buffer for header, color table and bits\n   GlobalUnlock(hDIB);\n   hDIBtmp = GlobalReAlloc(hDIB, lpbi->biSize +\n                        nNumColors * sizeof(RGBQUAD) +\n                        lpbi->biSizeImage, 0);\n\n   if (!hDIBtmp) // can't resize buffer for loading\n     goto ErrExitNoUnlock; //MPB\n   else\n     hDIB = hDIBtmp;\n\n   lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);\n\n   // read the color table\n   _lread (hFile, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD));\n\n   // offset to the bits from start of DIB header\n   offBits = lpbi->biSize + nNumColors * sizeof(RGBQUAD);\n\n   // If the bfOffBits field is non-zero, then the bits might *not* be\n   // directly following the color table in the file.  Use the value in\n   // bfOffBits to seek the bits.\n\n   if (bmfHeader.bfOffBits != 0L)\n      _llseek(hFile, bmfHeader.bfOffBits, SEEK_SET);\n   \n   if (MyRead(hFile, (LPSTR)lpbi + offBits, lpbi->biSizeImage))\n     goto OKExit;\n\n\nErrExit:\n    GlobalUnlock(hDIB);    \nErrExitNoUnlock:    \n    GlobalFree(hDIB);\n    return NULL;\n\nOKExit:\n    GlobalUnlock(hDIB);\n    return hDIB;\n}\n\n/*************************************************************************\n\n  Function:  MyRead (int, LPSTR, DWORD)\n\n   Purpose:  Routine to read files greater than 64K in size.\n\n   Returns:  TRUE if successful.\n             FALSE if an error occurs.\n\n  \n  History:   Date      Author       Reason\n             9/15/91   Mark Bader   Based on DIBVIEW\n \n*************************************************************************/\n\n\nBOOL MyRead(int hFile, LPSTR lpBuffer, DWORD dwSize)\n{\n   char huge *lpInBuf = (char huge *)lpBuffer;\n   int nBytes;\n\n   /*\n    * Read in the data in 32767 byte chunks (or a smaller amount if it's\n    * the last chunk of data read)\n    */\n\n   while (dwSize)\n   {\n      nBytes = (int)(dwSize > (DWORD)32767 ? 32767 : LOWORD (dwSize));\n      if (_lread(hFile, (LPSTR)lpInBuf, nBytes) != (WORD)nBytes)\n         return FALSE;\n      dwSize -= nBytes;\n      lpInBuf += nBytes;\n   }\n   return TRUE;\n}\n\n\n/****************************************************************************\n\n FUNCTION   : MyWrite(int fh, VOID FAR *pv, DWORD ul)\n\n PURPOSE    : Writes data in steps of 32k till all the data is written.\n              Normal _lwrite uses a WORD as 3rd parameter, so it is\n              limited to 32767 bytes, but this procedure is not.\n\n RETURNS    : 0 - If write did not proceed correctly.\n              number of bytes written otherwise.\n \n  History:   Date      Author       Reason\n             9/15/91   Mark Bader   Based on DIBVIEW\n\n ****************************************************************************/\n\n\nDWORD PASCAL MyWrite(int iFileHandle, VOID FAR *lpBuffer, DWORD dwBytes)\n{\n   DWORD dwBytesTmp = dwBytes;       // Save # of bytes for return value\n   BYTE huge *hpBuffer = (BYTE huge *)lpBuffer;   // make a huge pointer to the data\n\n   /*\n    * Write out the data in 32767 byte chunks.\n    */\n\n   while (dwBytes > 32767)\n   {\n      if (_lwrite(iFileHandle, (LPSTR)hpBuffer, (WORD)32767) != 32767)\n         return 0;\n      dwBytes -= 32767;\n      hpBuffer += 32767;\n   }\n\n   /* Write out the last chunk (which is < 32767 bytes) */\n   if (_lwrite(iFileHandle, (LPSTR)hpBuffer, (WORD)dwBytes) != (WORD)dwBytes)\n      return 0;\n   return dwBytesTmp;\n}\n\n//\tajw added\n//\tAdded to allow \"loading\" from a location in memory.\n//\tA modification of ReadDIBFile(), above.\n//***********************************************************************************************\nHDIB LoadDIB_FromMemory( const unsigned char* pData, DWORD dwBitsSize )\n{\n\tBITMAPFILEHEADER bmfHeader;\n\tUINT nNumColors;   // Number of colors in table\n\tHANDLE hDIB;        \n\tHANDLE hDIBtmp;    // Used for GlobalRealloc() //MPB\n\tLPBITMAPINFOHEADER lpbi;\n\tDWORD offBits;\n\n\tconst unsigned char* const pDataStart = pData;\n\tconst unsigned char* pDataEnd = pData + dwBitsSize;\t\t//\tOne char past end of \"file\".\n\n\t// Allocate memory for header & color table.\tWe'll enlarge this\n\t// memory as needed.\n\n//\tdebugprint( \"LoadDIB_FromMemory, GlobalAlloc\\n\" );\n\thDIB = GlobalAlloc(GMEM_MOVEABLE, (DWORD)(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)));\n//\tdebugprint( \"hDIB from GlobalALloc is %i\\n\", hDIB );\n\n\tif (!hDIB)\n\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: failed alloc\\n\" );\n\t\treturn NULL;\n\t}\n\n//\tdebugprint( \"LoadDIB_FromMemory, lpbi Lock\\n\" );\n\tlpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);\n//\tdebugprint( \"lpbi is %i\\n\", lpbi );\n\tif (!lpbi) \n\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: failed lock\\n\" );\n\t\tGlobalFree(hDIB);\n\t\treturn NULL;\n\t}\n\n\t// read the BITMAPFILEHEADER from our file\n//\tif (sizeof (BITMAPFILEHEADER) != _lread (hFile, (LPSTR)&bmfHeader, sizeof (BITMAPFILEHEADER)))\n//\t\tgoto ErrExit;\n\tif( pData + sizeof( BITMAPFILEHEADER ) >= pDataEnd )\n\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: bad size\\n\" );\n\t\tgoto ErrExit;\n\t}\n//\tdebugprint( \"LoadDIB_FromMemory, memcpy BITMAPFILEHEADER %i bytes\\n\", sizeof( BITMAPFILEHEADER ) );\n\tmemcpy( &bmfHeader, pData, sizeof( BITMAPFILEHEADER ) );\n\tpData += sizeof( BITMAPFILEHEADER );\n\n\tif (bmfHeader.bfType != 0x4d42)\t/* 'BM' */\n\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: no BM\\n\" );\n\t\tgoto ErrExit;\n\t}\n\n\t// read the BITMAPINFOHEADER\n//\tif (sizeof(BITMAPINFOHEADER) != _lread (hFile, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)))\n//\t\tgoto ErrExit;\n\tif( pData + sizeof( BITMAPINFOHEADER ) >= pDataEnd )\n\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: bad size 2\\n\" );\n\t\tgoto ErrExit;\n\t}\n//\tdebugprint( \"LoadDIB_FromMemory, memcpy BITMAPINFOHEADER %i bytes\\n\", sizeof( BITMAPINFOHEADER ) );\n\tmemcpy( lpbi, pData, sizeof( BITMAPINFOHEADER ) );\n\tpData += sizeof( BITMAPINFOHEADER );\n\n\t// Check to see that it's a Windows DIB -- an OS/2 DIB would cause\n\t// strange problems with the rest of the DIB API since the fields\n\t// in the header are different and the color table entries are\n\t// smaller.\n\t//\n\t// If it's not a Windows DIB (e.g. if biSize is wrong), return NULL.\n\n\tif (lpbi->biSize == sizeof(BITMAPCOREHEADER))\n\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: lpbi->biSize bad\\n\" );\n\t\tgoto ErrExit;\n\t}\n\n\tif( lpbi->biCompression != BI_RGB )\n\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: Image is compressed\\n\" );\n\t\tgoto ErrExit;\n\t}\n\n\t// Now determine the size of the color table and read it.  Since the\n\t// bitmap bits are offset in the file by bfOffBits, we need to do some\n\t// special processing here to make sure the bits directly follow\n\t// the color table (because that's the format we are susposed to pass\n\t// back)\n\tnNumColors = (UINT)lpbi->biClrUsed;\n\tif (!nNumColors)\n\t{\n\t\t// no color table for 24-bit, default size otherwise\n\t\tif (lpbi->biBitCount != 24)\n\t\t\tnNumColors = 1 << lpbi->biBitCount; /* standard size table */\n\t}\n\n\t// fill in some default values if they are zero\n\tif (lpbi->biClrUsed == 0)\n\t\tlpbi->biClrUsed = nNumColors;\n\n//\tdebugprint( \"biSizeImage is %i. I would say it was %i, because the bpp is %i.\\n\", lpbi->biSizeImage, ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3) * lpbi->biHeight, lpbi->biBitCount );\n\tif (lpbi->biSizeImage == 0)\n\t{\n\t\tlpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3) * lpbi->biHeight;\n\t}\n\n\t// get a proper-sized buffer for header, color table and bits\n\tGlobalUnlock(hDIB);\n//\tdebugprint( \"LoadDIB_FromMemory, GlobalReAlloc: lpbi->biSize=%i, nNumColors=%i, lpbi->biSizeImage=%i\\n\", lpbi->biSize, nNumColors,lpbi->biSizeImage );\n\thDIBtmp = GlobalReAlloc(hDIB, lpbi->biSize + nNumColors * sizeof(RGBQUAD) + lpbi->biSizeImage, 0);\n\n\tif (!hDIBtmp) // can't resize buffer for loading\n\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: realloc failed\\n\" );\n\t\tgoto ErrExitNoUnlock; //MPB\n\t}\n\telse\n\t\thDIB = hDIBtmp;\n\n\tlpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);\n\n\t// read the color table\n//\t_lread (hFile, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD));\n//\tdebugprint( \"LoadDIB_FromMemory, memcpy color table %i colors, so %i bytes\\n\", nNumColors, nNumColors * sizeof(RGBQUAD) );\n\tmemcpy( (LPSTR)(lpbi) + lpbi->biSize, pData, nNumColors * sizeof(RGBQUAD) );\n\tpData += nNumColors * sizeof(RGBQUAD);\n\n\t// offset to the bits from start of DIB header\n\toffBits = lpbi->biSize + nNumColors * sizeof(RGBQUAD);\n\n\t// If the bfOffBits field is non-zero, then the bits might *not* be\n\t// directly following the color table in the file.  Use the value in\n\t// bfOffBits to seek the bits.\n\n\tif (bmfHeader.bfOffBits != 0L)\n//\t\t_llseek(hFile, bmfHeader.bfOffBits, SEEK_SET);\n\t\tpData = pDataStart + bmfHeader.bfOffBits;\n\n//\tdebugprint( \"bmfHeader.bfOffBits is %i\\n\", bmfHeader.bfOffBits );\n\n//\tif (MyRead(hFile, (LPSTR)lpbi + offBits, lpbi->biSizeImage))\n//\t\tgoto OKExit;\n//\tdebugprint( \"Checking that pData(%i) + biSizeImage(%i), which is %i, is equal to pDataEnd(%i)\\n\", \n//\t\t\t\t\tpData, lpbi->biSizeImage, pData + lpbi->biSizeImage, pDataEnd );\n//\tif( pData + lpbi->biSizeImage != pDataEnd )\t\t\tcondition relaxed\n//\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: bad size 3\\n\" );\n//\t\tgoto ErrExit;\n//\t}\n\n//\tdebugprint( \"LoadDIB_FromMemory, memcpy the bits, %i bytes. Image is w %i, h.%i\\n\", \n//\t\t\t\t\t\t\t\tlpbi->biSizeImage, lpbi->biWidth, lpbi->biHeight );\n//\tdebugprint( \"Writing to lpbi (%i) + offBits (%i)\\n\", lpbi, offBits );\n\n\tmemcpy( (LPSTR)lpbi + offBits, pData, lpbi->biSizeImage );\n//\tpData += lpbi->biSizeImage;\n//\tif( pData != pDataEnd )\t\t//\tShould end up one byte past end of data. - condition relaxed\n//\t\tdebugprint( \"LoadDIB_FromMemory: ERROR! Ended up at %i instead of %i\\n\", pData, pDataEnd );\n\tgoto OKExit;\n\nErrExit:\n\tGlobalUnlock(hDIB);\nErrExitNoUnlock:    \n\tGlobalFree(hDIB);\n//\tdebugprint( \"LoadDIB_FromMemory Error!\\n\" );\n\treturn NULL;\n\nOKExit:\n\tGlobalUnlock(hDIB);\n\treturn hDIB;\n}\n"
  },
  {
    "path": "CODE/DIBUTIL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n//**********************************************************************\n//\n//  dibutil.c\n//\n//  Source file for Device-Independent Bitmap (DIB) API.  Provides\n//  the following functions:\n//\n//  CreateDIB()         - Creates new DIB\n//  FindDIBBits()       - Sets pointer to the DIB bits\n//  DIBWidth()          - Gets the width of the DIB\n//  DIBHeight()         - Gets the height of the DIB\n//  PaletteSize()       - Calculates the buffer size required by a palette\n//  DIBNumColors()      - Calculates number of colors in the DIB's color table\n//  CreateDIBPalette()  - Creates a palette from a DIB\n//  DIBToBitmap()       - Creates a bitmap from a DIB\n//  BitmapToDIB()       - Creates a DIB from a bitmap\n//  PalEntriesOnDevice()- Gets the number of palette entries of a device\n//  GetSystemPalette()  - Returns a handle to the current system palette\n//  AllocRoomForDIB()   - Allocates memory for a DIB\n//  ChangeDIBFormat()   - Changes a DIB's BPP and/or compression format\n//  ChangeBitmapFormat()- Changes a bitmap to a DIB with specified BPP and\n//                        compression format\n//\n// Development Team: Mark Bader\n//                   Patrick Schreiber\n//                   Garrett McAuliffe\n//                   Eric Flo\n//                   Tony Claflin\n//\n// Written by Microsoft Product Support Services, Developer Support.\n// COPYRIGHT:\n//\n//   (C) Copyright Microsoft Corp. 1993.  All rights reserved.\n//\n//   You have a royalty-free right to use, modify, reproduce and\n//   distribute the Sample Files (and/or any modified version) in\n//   any way you find useful, provided that you agree that\n//   Microsoft has no warranty obligations or liability for any\n//   Sample Application Files which are modified.\n//\n//**********************************************************************\n\n/* header files */\n#include <windows.h>\n#include <assert.h>\n#include \"dibapi.h\"\n#include \"dibutil.h\"\n#include <stdio.h>\n\n\n/*************************************************************************\n *\n * CreateDIB()\n *\n * Parameters:\n *\n * DWORD dwWidth    - Width for new bitmap, in pixels\n * DWORD dwHeight   - Height for new bitmap \n * WORD  wBitCount  - Bit Count for new DIB (1, 4, 8, or 24)\n *\n * Return Value:\n *\n * HDIB             - Handle to new DIB\n *\n * Description:\n *\n * This function allocates memory for and initializes a new DIB by\n * filling in the BITMAPINFOHEADER, allocating memory for the color\n * table, and allocating memory for the bitmap bits.  As with all\n * HDIBs, the header, colortable and bits are all in one contiguous\n * memory block.  This function is similar to the CreateBitmap() \n * Windows API.\n *\n * The colortable and bitmap bits are left uninitialized (zeroed) in the\n * returned HDIB.\n *\n *\n * History:   Date      Author              Reason\n *            3/20/92   Mark Bader          Created\n *\n ************************************************************************/\n\nHDIB FAR CreateDIB(DWORD dwWidth, DWORD dwHeight, WORD wBitCount)\n{\n   BITMAPINFOHEADER bi;         // bitmap header\n   LPBITMAPINFOHEADER lpbi;     // pointer to BITMAPINFOHEADER\n   DWORD dwLen;                 // size of memory block\n   HDIB hDIB;\n   DWORD dwBytesPerLine;        // Number of bytes per scanline\n\n\n   // Make sure bits per pixel is valid\n   if (wBitCount <= 1)\n      wBitCount = 1;\n   else if (wBitCount <= 4)\n      wBitCount = 4;\n   else if (wBitCount <= 8)\n      wBitCount = 8;\n   else if (wBitCount <= 24)\n      wBitCount = 24;\n   else\n      wBitCount = 4;  // set default value to 4 if parameter is bogus\n\n   // initialize BITMAPINFOHEADER\n   bi.biSize = sizeof(BITMAPINFOHEADER);\n   bi.biWidth = dwWidth;         // fill in width from parameter\n   bi.biHeight = dwHeight;       // fill in height from parameter\n   bi.biPlanes = 1;              // must be 1\n   bi.biBitCount = wBitCount;    // from parameter\n   bi.biCompression = BI_RGB;    \n   bi.biSizeImage = 0;           // 0's here mean \"default\"\n   bi.biXPelsPerMeter = 0;\n   bi.biYPelsPerMeter = 0;\n   bi.biClrUsed = 0;\n   bi.biClrImportant = 0;\n\n   // calculate size of memory block required to store the DIB.  This\n   // block should be big enough to hold the BITMAPINFOHEADER, the color\n   // table, and the bits\n\n   dwBytesPerLine = WIDTHBYTES(wBitCount * dwWidth);\n   dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + (dwBytesPerLine * dwHeight);\n\n   // alloc memory block to store our bitmap\n   hDIB = GlobalAlloc(GHND, dwLen);\n\n   // major bummer if we couldn't get memory block\n   if (!hDIB)\n   {\n      return NULL;\n   }\n\n   // lock memory and get pointer to it\n   lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);\n\n   // use our bitmap info structure to fill in first part of\n   // our DIB with the BITMAPINFOHEADER\n   *lpbi = bi;\n\n   // Since we don't know what the colortable and bits should contain,\n   // just leave these blank.  Unlock the DIB and return the HDIB.\n\n   GlobalUnlock(hDIB);\n\n   /* return handle to the DIB */\n   return hDIB;\n}\n\n\n\n/*************************************************************************\n *\n * FindDIBBits()\n *\n * Parameter:\n *\n * LPSTR lpDIB      - pointer to packed-DIB memory block\n *\n * Return Value:\n *\n * LPSTR            - pointer to the DIB bits\n *\n * Description:\n *\n * This function calculates the address of the DIB's bits and returns a\n * pointer to the DIB bits.\n *\n * History:   Date      Author              Reason\n *            6/01/91   Garrett McAuliffe   Created\n *            9/15/91   Patrick Schreiber   Added header and comments\n *\n ************************************************************************/\n\n\nLPSTR FAR FindDIBBits(LPCSTR lpDIB)\n{\n   return (LPSTR)(lpDIB + *(LPDWORD)lpDIB + PaletteSize(lpDIB));\n}\n\n\n/*************************************************************************\n *\n * DIBWidth()\n *\n * Parameter:\n *\n * LPSTR lpDIB      - pointer to packed-DIB memory block\n *\n * Return Value:\n *\n * DWORD            - width of the DIB\n *\n * Description:\n *\n * This function gets the width of the DIB from the BITMAPINFOHEADER\n * width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER\n * width field if it is an OS/2-style DIB.\n *\n * History:   Date      Author               Reason\n *            6/01/91   Garrett McAuliffe    Created\n *            9/15/91   Patrick Schreiber    Added header and comments\n *\n ************************************************************************/\n\n\nDWORD FAR DIBWidth(LPCSTR lpDIB)\n{\n   LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB\n   LPBITMAPCOREHEADER lpbmc;  // pointer to an OS/2-style DIB\n\n   /* point to the header (whether Win 3.0 and OS/2) */\n\n   lpbmi = (LPBITMAPINFOHEADER)lpDIB;\n   lpbmc = (LPBITMAPCOREHEADER)lpDIB;\n\n   /* return the DIB width if it is a Win 3.0 DIB */\n   if (lpbmi->biSize == sizeof(BITMAPINFOHEADER))\n      return lpbmi->biWidth;\n   else  /* it is an OS/2 DIB, so return its width */\n      return (DWORD)lpbmc->bcWidth;\n}\n\n\n/*************************************************************************\n *\n * DIBHeight()\n *\n * Parameter:\n *\n * LPSTR lpDIB      - pointer to packed-DIB memory block\n *\n * Return Value:\n *\n * DWORD            - height of the DIB\n *\n * Description:\n *\n * This function gets the height of the DIB from the BITMAPINFOHEADER\n * height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER\n * height field if it is an OS/2-style DIB.\n *\n * History:   Date      Author               Reason\n *            6/01/91   Garrett McAuliffe    Created\n *            9/15/91   Patrick Schreiber    Added header and comments\n *\n ************************************************************************/\n\n\nDWORD FAR DIBHeight(LPCSTR lpDIB)\n{\n   LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB\n   LPBITMAPCOREHEADER lpbmc;  // pointer to an OS/2-style DIB\n\n   /* point to the header (whether OS/2 or Win 3.0 */\n\n   lpbmi = (LPBITMAPINFOHEADER)lpDIB;\n   lpbmc = (LPBITMAPCOREHEADER)lpDIB;\n\n   /* return the DIB height if it is a Win 3.0 DIB */\n   if (lpbmi->biSize == sizeof(BITMAPINFOHEADER))\n      return lpbmi->biHeight;\n   else  /* it is an OS/2 DIB, so return its height */\n      return (DWORD)lpbmc->bcHeight;\n}\n\n\n/*************************************************************************\n *\n * PaletteSize()\n *\n * Parameter:\n *\n * LPSTR lpDIB      - pointer to packed-DIB memory block\n *\n * Return Value:\n *\n * WORD             - size of the color palette of the DIB\n *\n * Description:\n *\n * This function gets the size required to store the DIB's palette by\n * multiplying the number of colors by the size of an RGBQUAD (for a\n * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an OS/2-\n * style DIB).\n *\n * History:   Date      Author             Reason\n *            6/01/91   Garrett McAuliffe  Created\n *            9/15/91   Patrick Schreiber  Added header and comments\n *\n ************************************************************************/\n\n\nWORD FAR PaletteSize(LPCSTR lpDIB)\n{\n   /* calculate the size required by the palette */\n   if (IS_WIN30_DIB (lpDIB))\n      return (WORD FAR)(DIBNumColors(lpDIB) * sizeof(RGBQUAD));\n   else\n      return (WORD FAR)(DIBNumColors(lpDIB) * sizeof(RGBTRIPLE));\n}\n\n\n/*************************************************************************\n *\n * DIBNumColors()\n *\n * Parameter:\n *\n * LPSTR lpDIB      - pointer to packed-DIB memory block\n *\n * Return Value:\n *\n * WORD             - number of colors in the color table\n *\n * Description:\n *\n * This function calculates the number of colors in the DIB's color table\n * by finding the bits per pixel for the DIB (whether Win3.0 or OS/2-style\n * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256,\n * if 24, no colors in color table.\n *\n * History:   Date      Author               Reason\n *            6/01/91   Garrett McAuliffe    Created\n *            9/15/91   Patrick Schreiber    Added header and comments\n *\n ************************************************************************/\n\n\nWORD FAR DIBNumColors(LPCSTR lpDIB)\n{\n   WORD wBitCount;  // DIB bit count\n\n   /*  If this is a Windows-style DIB, the number of colors in the\n    *  color table can be less than the number of bits per pixel\n    *  allows for (i.e. lpbi->biClrUsed can be set to some value).\n    *  If this is the case, return the appropriate value.\n    */\n\n   if (IS_WIN30_DIB(lpDIB))\n   {\n      DWORD dwClrUsed;\n\n      dwClrUsed = ((LPBITMAPINFOHEADER)lpDIB)->biClrUsed;\n      if (dwClrUsed)\n     return (WORD)dwClrUsed;\n   }\n\n   /*  Calculate the number of colors in the color table based on\n    *  the number of bits per pixel for the DIB.\n    */\n   if (IS_WIN30_DIB(lpDIB))\n      wBitCount = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount;\n   else\n      wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount;\n\n   /* return number of colors based on bits per pixel */\n   switch (wBitCount)\n      {\n   case 1:\n      return 2;\n\n   case 4:\n      return 16;\n\n   case 8:\n      return 256;\n\n   default:\n      return 0;\n      }\n}\n\n\n/*************************************************************************\n *\n * CreateDIBPalette()\n *\n * Parameter:\n *\n * HDIB hDIB        - specifies the DIB\n *\n * Return Value:\n *\n * HPALETTE         - specifies the palette\n *\n * Description:\n *\n * This function creates a palette from a DIB by allocating memory for the\n * logical palette, reading and storing the colors from the DIB's color table\n * into the logical palette, creating a palette from this logical palette,\n * and then returning the palette's handle. This allows the DIB to be\n * displayed using the best possible colors (important for DIBs with 256 or\n * more colors).\n *\n * History:   Date      Author               Reason\n *            6/01/91   Garrett McAuliffe    Created\n *            9/15/91   Patrick Schreiber    Added header and comments\n *\n ************************************************************************/\n\n\nHPALETTE FAR CreateDIBPalette(HDIB hDIB)\n{\n   LPLOGPALETTE lpPal;      // pointer to a logical palette\n   HANDLE hLogPal;          // handle to a logical palette\n   HPALETTE hPal = NULL;    // handle to a palette\n   int i, wNumColors;       // loop index, number of colors in color table\n   LPSTR lpbi;              // pointer to packed-DIB\n   LPBITMAPINFO lpbmi;      // pointer to BITMAPINFO structure (Win3.0)\n   LPBITMAPCOREINFO lpbmc;  // pointer to BITMAPCOREINFO structure (OS/2)\n   BOOL bWinStyleDIB;       // flag which signifies whether this is a Win3.0 DIB\n\n   /* if handle to DIB is invalid, return NULL */\n\n   if (!hDIB)\n      return NULL;\n\n   /* lock DIB memory block and get a pointer to it */\n   lpbi = (LPSTR)GlobalLock(hDIB);\n\n   /* get pointer to BITMAPINFO (Win 3.0) */\n   lpbmi = (LPBITMAPINFO)lpbi;\n\n   /* get pointer to BITMAPCOREINFO (OS/2 1.x) */\n   lpbmc = (LPBITMAPCOREINFO)lpbi;\n\n   /* get the number of colors in the DIB */\n   wNumColors = DIBNumColors(lpbi);\n\n   /* is this a Win 3.0 DIB? */\n   bWinStyleDIB = IS_WIN30_DIB(lpbi);\n   if (wNumColors)\n   {\n      /* allocate memory block for logical palette */\n      hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) *\n                wNumColors);\n\n      /* if not enough memory, clean up and return NULL */\n      if (!hLogPal)\n      {\n     GlobalUnlock(hDIB);\n     return NULL;\n      }\n\n      /* lock memory block and get pointer to it */\n      lpPal = (LPLOGPALETTE)GlobalLock(hLogPal);\n\n      /* set version and number of palette entries */\n      lpPal->palVersion = PALVERSION;\n      lpPal->palNumEntries = (WORD)wNumColors;\n\n      /*  store RGB triples (if Win 3.0 DIB) or RGB quads (if OS/2 DIB)\n       *  into palette\n       */\n      for (i = 0; i < wNumColors; i++)\n      {\n     if (bWinStyleDIB)\n     {\n        lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;\n        lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;\n        lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;\n        lpPal->palPalEntry[i].peFlags = 0;\n     }\n     else\n     {\n        lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;\n        lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;\n        lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;\n        lpPal->palPalEntry[i].peFlags = 0;\n     }\n      }\n\n      /* create the palette and get handle to it */\n      hPal = CreatePalette(lpPal);\n\n      /* if error getting handle to palette, clean up and return NULL */\n      if (!hPal)\n      {\n     GlobalUnlock(hLogPal);\n     GlobalFree(hLogPal);\n     return NULL;\n      }\n   }\n\n   /* clean up */\n   GlobalUnlock(hLogPal);\n   GlobalFree(hLogPal);\n   GlobalUnlock(hDIB);\n\n   /* return handle to DIB's palette */\n   return hPal;\n}\n\n\n/*************************************************************************\n *\n * DIBToBitmap()\n *\n * Parameters:\n *\n * HDIB hDIB        - specifies the DIB to convert\n *\n * HPALETTE hPal    - specifies the palette to use with the bitmap\n *\n * Return Value:\n *\n * HBITMAP          - identifies the device-dependent bitmap\n *\n * Description:\n *\n * This function creates a bitmap from a DIB using the specified palette.\n * If no palette is specified, default is used.\n *\n * NOTE:\n *\n * The bitmap returned from this funciton is always a bitmap compatible\n * with the screen (e.g. same bits/pixel and color planes) rather than\n * a bitmap with the same attributes as the DIB.  This behavior is by\n * design, and occurs because this function calls CreateDIBitmap to\n * do its work, and CreateDIBitmap always creates a bitmap compatible\n * with the hDC parameter passed in (because it in turn calls\n * CreateCompatibleBitmap).\n *\n * So for instance, if your DIB is a monochrome DIB and you call this\n * function, you will not get back a monochrome HBITMAP -- you will\n * get an HBITMAP compatible with the screen DC, but with only 2\n * colors used in the bitmap.\n *\n * If your application requires a monochrome HBITMAP returned for a\n * monochrome DIB, use the function SetDIBits().\n *\n * Also, the DIBpassed in to the function is not destroyed on exit. This\n * must be done later, once it is no longer needed.\n *\n * History:   Date      Author               Reason\n *            6/01/91   Garrett McAuliffe    Created\n *            9/15/91   Patrick Schreiber    Added header and comments\n *            3/27/92   Mark Bader           Added comments about resulting\n *                                           bitmap format\n *\n ************************************************************************/\n\n\nHBITMAP FAR DIBToBitmap(HDIB hDIB, HPALETTE hPal)\n{\n   LPSTR lpDIBHdr, lpDIBBits;  // pointer to DIB header, pointer to DIB bits\n   HBITMAP hBitmap;            // handle to device-dependent bitmap\n   HDC hDC;                    // handle to DC\n   HPALETTE hOldPal = NULL;    // handle to a palette\n\n   /* if invalid handle, return NULL */\n\n   if (!hDIB)\n      return NULL;\n\n   /* lock memory block and get a pointer to it */\n   lpDIBHdr = (LPSTR)GlobalLock(hDIB);\n\n   /* get a pointer to the DIB bits */\n   lpDIBBits = FindDIBBits(lpDIBHdr);\n\n   /* get a DC */\n   hDC = GetDC(NULL);\n   if (!hDC)\n   {\n      /* clean up and return NULL */\n      GlobalUnlock(hDIB);\n      return NULL;\n   }\n\n   /* select and realize palette */\n   if (hPal)\n      hOldPal = SelectPalette(hDC, hPal, FALSE);\n   RealizePalette(hDC);\n\n   /* create bitmap from DIB info. and bits */\n   hBitmap = CreateDIBitmap(hDC, (LPBITMAPINFOHEADER)lpDIBHdr, CBM_INIT,\n                lpDIBBits, (LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS);\n\n   /* restore previous palette */\n   if (hOldPal)\n      SelectPalette(hDC, hOldPal, FALSE);\n\n   /* clean up */\n   ReleaseDC(NULL, hDC);\n   GlobalUnlock(hDIB);\n\n   /* return handle to the bitmap */\n   return hBitmap;\n}\n\n\n/*************************************************************************\n *\n * BitmapToDIB()\n *\n * Parameters:\n *\n * HBITMAP hBitmap  - specifies the bitmap to convert\n *\n * HPALETTE hPal    - specifies the palette to use with the bitmap\n *\n * Return Value:\n *\n * HDIB             - identifies the device-dependent bitmap\n *\n * Description:\n *\n * This function creates a DIB from a bitmap using the specified palette.\n *\n * History:   Date      Author               Reason\n *            6/01/91   Garrett McAuliffe    Created\n *            9/15/91   Patrick Schreiber    Added header and comments\n *            12/10/91  Patrick Schreiber    Added bits per pixel validation\n *                                           and check GetObject return value\n *\n ************************************************************************/\n\n\nHDIB FAR BitmapToDIB(HBITMAP hBitmap, HPALETTE hPal)\n{\n   BITMAP bm;                   // bitmap structure\n   BITMAPINFOHEADER bi;         // bitmap header\n   BITMAPINFOHEADER FAR *lpbi;  // pointer to BITMAPINFOHEADER\n   DWORD dwLen;                 // size of memory block\n   HANDLE hDIB, h;              // handle to DIB, temp handle\n   HDC hDC;                     // handle to DC\n   WORD biBits;                 // bits per pixel\n\n   /* check if bitmap handle is valid */\n\n   if (!hBitmap)\n      return NULL;\n\n   /* fill in BITMAP structure, return NULL if it didn't work */\n   if (!GetObject(hBitmap, sizeof(bm), (LPSTR)&bm))\n      return NULL;\n\n   /* if no palette is specified, use default palette */\n   if (hPal == NULL)\n      hPal = GetStockObject(DEFAULT_PALETTE);\n\n   /* calculate bits per pixel */\n   biBits = (WORD)( bm.bmPlanes * bm.bmBitsPixel );\n\n   /* make sure bits per pixel is valid */\n   if (biBits <= 1)\n      biBits = 1;\n   else if (biBits <= 4)\n      biBits = 4;\n   else if (biBits <= 8)\n      biBits = 8;\n   else /* if greater than 8-bit, force to 24-bit */\n      biBits = 24;\n\n   /* initialize BITMAPINFOHEADER */\n   bi.biSize = sizeof(BITMAPINFOHEADER);\n   bi.biWidth = bm.bmWidth;\n   bi.biHeight = bm.bmHeight;\n   bi.biPlanes = 1;\n   bi.biBitCount = biBits;\n   bi.biCompression = BI_RGB;\n   bi.biSizeImage = 0;\n   bi.biXPelsPerMeter = 0;\n   bi.biYPelsPerMeter = 0;\n   bi.biClrUsed = 0;\n   bi.biClrImportant = 0;\n\n   /* calculate size of memory block required to store BITMAPINFO */\n   dwLen = bi.biSize + PaletteSize((LPSTR)&bi);\n\n   /* get a DC */\n   hDC = GetDC(NULL);\n\n   /* select and realize our palette */\n   hPal = SelectPalette(hDC, hPal, FALSE);\n   RealizePalette(hDC);\n\n   /* alloc memory block to store our bitmap */\n   hDIB = GlobalAlloc(GHND, dwLen);\n\n   /* if we couldn't get memory block */\n   if (!hDIB)\n   {\n      /* clean up and return NULL */\n      SelectPalette(hDC, hPal, TRUE);\n      RealizePalette(hDC);\n      ReleaseDC(NULL, hDC);\n      return NULL;\n   }\n\n   /* lock memory and get pointer to it */\n   lpbi = (BITMAPINFOHEADER FAR *)GlobalLock(hDIB);\n\n   /* use our bitmap info. to fill BITMAPINFOHEADER */\n   *lpbi = bi;\n\n   /*  call GetDIBits with a NULL lpBits param, so it will calculate the\n    *  biSizeImage field for us\n    */\n   GetDIBits(hDC, hBitmap, 0, (WORD)bi.biHeight, NULL, (LPBITMAPINFO)lpbi,\n         DIB_RGB_COLORS);\n\n   /* get the info. returned by GetDIBits and unlock memory block */\n   bi = *lpbi;\n   GlobalUnlock(hDIB);\n\n   /* if the driver did not fill in the biSizeImage field, make one up */\n   if (bi.biSizeImage == 0)\n      bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight;\n\n   /* realloc the buffer big enough to hold all the bits */\n   dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + bi.biSizeImage;\n   h = GlobalReAlloc(hDIB, dwLen, 0);\n   if (h)\n      hDIB = h;\n   else\n   {\n      /* clean up and return NULL */\n      GlobalFree(hDIB);\n      hDIB = NULL;\n      SelectPalette(hDC, hPal, TRUE);\n      RealizePalette(hDC);\n      ReleaseDC(NULL, hDC);\n      return NULL;\n   }\n\n   /* lock memory block and get pointer to it */\n   lpbi = (BITMAPINFOHEADER FAR *)GlobalLock(hDIB);\n\n   /*  call GetDIBits with a NON-NULL lpBits param, and actualy get the\n    *  bits this time\n    */\n   if (GetDIBits(hDC, hBitmap, 0, (WORD)bi.biHeight, (LPSTR)lpbi + (WORD)lpbi\n         ->biSize + PaletteSize((LPSTR)lpbi), (LPBITMAPINFO)lpbi,\n         DIB_RGB_COLORS) == 0)\n   {\n      /* clean up and return NULL */\n      GlobalUnlock(hDIB);\n      hDIB = NULL;\n      SelectPalette(hDC, hPal, TRUE);\n      RealizePalette(hDC);\n      ReleaseDC(NULL, hDC);\n      return NULL;\n   }\n   bi = *lpbi;\n\n   /* clean up */\n   GlobalUnlock(hDIB);\n   SelectPalette(hDC, hPal, TRUE);\n   RealizePalette(hDC);\n   ReleaseDC(NULL, hDC);\n\n   /* return handle to the DIB */\n   return hDIB;\n}\n\n\n/*************************************************************************\n *\n * PalEntriesOnDevice()\n *\n * Parameter:\n *\n * HDC hDC          - device context\n *\n * Return Value:\n *\n * int              - number of palette entries on device\n *\n * Description:\n *\n * This function gets the number of palette entries on the specified device\n *\n * History:   Date      Author               Reason\n *            6/01/91   Garrett McAuliffe    Created\n *            9/15/91   Patrick Schreiber    Added header and comments\n *\n ************************************************************************/\n\n\nint FAR PalEntriesOnDevice(HDC hDC)\n{\n   int nColors;  // number of colors\n\n   /*  Find out the number of palette entries on this\n    *  device.\n    */\n\n   nColors = GetDeviceCaps(hDC, SIZEPALETTE);\n\n   /*  For non-palette devices, we'll use the # of system\n    *  colors for our palette size.\n    */\n   if (!nColors)\n      nColors = GetDeviceCaps(hDC, NUMCOLORS);\n   assert(nColors);\n   return nColors;\n}\n\n\n/*************************************************************************\n *\n * GetSystemPalette()\n *\n * Parameters:\n *\n * None\n *\n * Return Value:\n *\n * HPALETTE         - handle to a copy of the current system palette\n *\n * Description:\n *\n * This function returns a handle to a palette which represents the system\n * palette.  The system RGB values are copied into our logical palette using\n * the GetSystemPaletteEntries function.  \n *\n * History:   \n *            \n *    Date      Author               Reason        \n *    6/01/91   Garrett McAuliffe    Created        \n *    9/15/91   Patrick Schreiber    Added header and comments\n *    12/20/91  Mark Bader           Added GetSystemPaletteEntries call\n *\n ************************************************************************/\n\n\nHPALETTE FAR GetSystemPalette(void)\n{\n   HDC hDC;                // handle to a DC\n   static HPALETTE hPal = NULL;   // handle to a palette\n   HANDLE hLogPal;         // handle to a logical palette\n   LPLOGPALETTE lpLogPal;  // pointer to a logical palette\n   int nColors;            // number of colors\n\n   /* Find out how many palette entries we want. */\n\n   hDC = GetDC(NULL);\n   if (!hDC)\n      return NULL;\n   nColors = PalEntriesOnDevice(hDC);   // Number of palette entries\n\n   /* Allocate room for the palette and lock it. */\n   hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + nColors * sizeof(\n             PALETTEENTRY));\n\n   /* if we didn't get a logical palette, return NULL */\n   if (!hLogPal)\n      return NULL;\n\n   /* get a pointer to the logical palette */\n   lpLogPal = (LPLOGPALETTE)GlobalLock(hLogPal);\n\n   /* set some important fields */\n   lpLogPal->palVersion = (WORD)PALVERSION;\n   lpLogPal->palNumEntries = (WORD)nColors;\n\n   /* Copy the current system palette into our logical palette */\n\n   GetSystemPaletteEntries(hDC, 0, nColors, \n                           (LPPALETTEENTRY)(lpLogPal->palPalEntry));\n\n   /*  Go ahead and create the palette.  Once it's created,\n    *  we no longer need the LOGPALETTE, so free it.\n    */\n\n   hPal = CreatePalette(lpLogPal);\n\n   /* clean up */\n   GlobalUnlock(hLogPal);\n   GlobalFree(hLogPal);\n   ReleaseDC(NULL, hDC);\n\n   return hPal;\n}\n\n\n/*************************************************************************\n *\n * AllocRoomForDIB()\n *\n * Parameters:\n *\n * BITMAPINFOHEADER - bitmap info header stucture\n *\n * HBITMAP          - handle to the bitmap\n *\n * Return Value:\n *\n * HDIB             - handle to memory block\n *\n * Description:\n *\n *  This routine takes a BITMAPINOHEADER, and returns a handle to global\n *  memory which can contain a DIB with that header.  It also initializes\n *  the header portion of the global memory.  GetDIBits() is used to determine\n *  the amount of room for the DIB's bits.  The total amount of memory\n *  needed = sizeof(BITMAPINFOHEADER) + size of color table + size of bits.\n *\n * History:   Date      Author               Reason\n *            6/01/91   Garrett McAuliffe    Created\n *            12/11/91  Patrick Schreiber    Added header and some comments\n *\n ************************************************************************/\n\nHANDLE AllocRoomForDIB(BITMAPINFOHEADER bi, HBITMAP hBitmap)\n{\n   DWORD              dwLen;\n   HANDLE             hDIB;\n   HDC                hDC;\n   LPBITMAPINFOHEADER lpbi;\n   HANDLE             hTemp;\n\n   /* Figure out the size needed to hold the BITMAPINFO structure\n    * (which includes the BITMAPINFOHEADER and the color table).\n    */\n\n   dwLen = bi.biSize + PaletteSize((LPSTR) &bi);\n   hDIB  = GlobalAlloc(GHND,dwLen);\n\n   /* Check that DIB handle is valid */\n   if (!hDIB)\n      return NULL;\n\n   /* Set up the BITMAPINFOHEADER in the newly allocated global memory,\n    * then call GetDIBits() with lpBits = NULL to have it fill in the\n    * biSizeImage field for us.\n    */\n   lpbi  = (LPBITMAPINFOHEADER)GlobalLock(hDIB);\n   *lpbi = bi;\n\n   hDC   = GetDC(NULL);\n   GetDIBits(hDC, hBitmap, 0, (WORD) bi.biHeight,\n          NULL, (LPBITMAPINFO) lpbi, DIB_RGB_COLORS);\n   ReleaseDC(NULL, hDC);\n\n   /* If the driver did not fill in the biSizeImage field,\n    * fill it in -- NOTE: this is a bug in the driver!\n    */\n   if (lpbi->biSizeImage == 0)\n      lpbi->biSizeImage = WIDTHBYTES((DWORD)lpbi->biWidth * lpbi->biBitCount) *\n              lpbi->biHeight;\n\n   /* Get the size of the memory block we need */\n   dwLen = lpbi->biSize + PaletteSize((LPSTR) &bi) + lpbi->biSizeImage;\n\n   /* Unlock the memory block */\n   GlobalUnlock(hDIB);\n\n   /* ReAlloc the buffer big enough to hold all the bits */\n   hTemp = GlobalReAlloc(hDIB,dwLen,0);\n   if (hTemp)\n      return hTemp;\n   else\n      {\n      /* Else free memory block and return failure */\n      GlobalFree(hDIB);\n      return NULL;\n      }\n}\n\n\n/*************************************************************************\n *\n * ChangeDIBFormat()\n *\n * Parameter:\n *\n * HDIB             - handle to packed-DIB in memory\n *\n * WORD             - desired bits per pixel\n *\n * DWORD            - desired compression format\n *\n * Return Value:\n *\n * HDIB             - handle to the new DIB if successful, else NULL\n *\n * Description:\n *\n * This function will convert the bits per pixel and/or the compression\n * format of the specified DIB. Note: If the conversion was unsuccessful,\n * we return NULL. The original DIB is left alone. Don't use code like the\n * following:\n *\n *    hMyDIB = ChangeDIBFormat(hMyDIB, 8, BI_RLE4);\n *\n * The conversion will fail, but hMyDIB will now be NULL and the original\n * DIB will now hang around in memory. We could have returned the old\n * DIB, but we wanted to allow the programmer to check whether this\n * conversion succeeded or failed.\n *\n * History:   \n *            \n *   Date      Author             Reason         \n *   6/01/91   Garrett McAuliffe  Created         \n *   12/10/91  Patrick Schreiber  Modified from converting RGB to RLE8        \n *                                  to converting RGB/RLE to RGB/RLE.         \n *                                  Added wBitCount and dwCompression         \n *                                  parameters. Also added header and         \n *                                  comments.         \n *\n ************************************************************************/\n\nHDIB FAR ChangeDIBFormat(HDIB hDIB, WORD wBitCount, DWORD dwCompression)\n{\n   HDC                hDC;             // Handle to DC\n   HBITMAP            hBitmap;         // Handle to bitmap\n   BITMAP             Bitmap;          // BITMAP data structure\n   BITMAPINFOHEADER   bi;              // Bitmap info header\n   LPBITMAPINFOHEADER lpbi;            // Pointer to bitmap info\n   HDIB               hNewDIB = NULL;  // Handle to new DIB\n   HPALETTE           hPal, hOldPal;   // Handle to palette, prev pal\n   WORD               DIBBPP, NewBPP;  // DIB bits per pixel, new bpp\n   DWORD              DIBComp, NewComp;// DIB compression, new compression\n\n   /* Check for a valid DIB handle */\n   if (!hDIB)\n      return NULL;\n\n   /* Get the old DIB's bits per pixel and compression format */\n   lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);\n   DIBBPP = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;\n   DIBComp = ((LPBITMAPINFOHEADER)lpbi)->biCompression;\n   GlobalUnlock(hDIB);\n\n   /* Validate wBitCount and dwCompression\n    * They must match correctly (i.e., BI_RLE4 and 4 BPP or\n    * BI_RLE8 and 8BPP, etc.) or we return failure */\n   if (wBitCount == 0)\n      {\n      NewBPP = DIBBPP;\n      if ((dwCompression == BI_RLE4 && NewBPP == 4) ||\n      (dwCompression == BI_RLE8 && NewBPP == 8) ||\n      (dwCompression == BI_RGB))\n     NewComp = dwCompression;\n      else\n     return NULL;\n      }\n   else if (wBitCount == 1 && dwCompression == BI_RGB)\n      {\n      NewBPP = wBitCount;\n      NewComp = BI_RGB;\n      }\n   else if (wBitCount == 4)\n      {\n      NewBPP = wBitCount;\n      if (dwCompression == BI_RGB || dwCompression == BI_RLE4)\n     NewComp = dwCompression;\n      else\n     return NULL;\n      }\n   else if (wBitCount == 8)\n      {\n      NewBPP = wBitCount;\n      if (dwCompression == BI_RGB || dwCompression == BI_RLE8)\n     NewComp = dwCompression;\n      else\n     return NULL;\n      }\n   else if (wBitCount == 24 && dwCompression == BI_RGB)\n      {\n      NewBPP = wBitCount;\n      NewComp = BI_RGB;\n      }\n   else\n      return NULL;\n\n   /* Save the old DIB's palette */\n   hPal = CreateDIBPalette(hDIB);\n   if (!hPal)\n      return NULL;\n\n   /* Convert old DIB to a bitmap */\n   hBitmap = DIBToBitmap(hDIB, hPal);\n   if (!hBitmap)\n      {\n      DeleteObject(hPal);\n      return NULL;\n      }\n\n   /* Get info about the bitmap */\n   GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);\n\n   /* Fill in the BITMAPINFOHEADER appropriately */\n   bi.biSize               = sizeof(BITMAPINFOHEADER);\n   bi.biWidth              = Bitmap.bmWidth;\n   bi.biHeight             = Bitmap.bmHeight;\n   bi.biPlanes             = 1;\n   bi.biBitCount           = NewBPP;\n   bi.biCompression        = NewComp;\n   bi.biSizeImage          = 0;\n   bi.biXPelsPerMeter      = 0;\n   bi.biYPelsPerMeter      = 0;\n   bi.biClrUsed            = 0;\n   bi.biClrImportant       = 0;\n\n   /* Go allocate room for the new DIB */\n   hNewDIB = AllocRoomForDIB(bi, hBitmap);\n   if (!hNewDIB)\n      return NULL;\n\n   /* Get a pointer to the new DIB */\n   lpbi = (LPBITMAPINFOHEADER)GlobalLock(hNewDIB);\n\n   /* Get a DC and select/realize our palette in it */\n   hDC  = GetDC(NULL);\n   hOldPal = SelectPalette(hDC, hPal, FALSE);\n   RealizePalette(hDC);\n\n   /* Call GetDIBits and get the new DIB bits */\n   if (!GetDIBits(hDC, hBitmap, 0, (WORD) lpbi->biHeight,\n       (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi),\n       (LPBITMAPINFO)lpbi, DIB_RGB_COLORS))\n      {\n      GlobalUnlock(hNewDIB);\n      GlobalFree(hNewDIB);\n      hNewDIB = NULL;\n      }\n\n   /* Clean up and return */\n   SelectPalette(hDC, hOldPal, TRUE);\n   RealizePalette(hDC);\n   ReleaseDC(NULL, hDC);\n\n   if (hNewDIB)\n      /* Unlock the new DIB's memory block */\n      GlobalUnlock(hNewDIB);\n\n   DeleteObject(hBitmap);\n   DeleteObject(hPal);\n\n   return hNewDIB;\n}\n\n\n/*************************************************************************\n *\n * ChangeBitmapFormat()\n *\n * Parameter:\n *\n * HBITMAP          - handle to a bitmap\n *\n * WORD             - desired bits per pixel\n *\n * DWORD            - desired compression format\n *\n * HPALETTE         - handle to palette\n *\n * Return Value:\n *\n * HDIB             - handle to the new DIB if successful, else NULL\n *\n * Description:\n *\n * This function will convert a bitmap to the specified bits per pixel\n * and compression format. The bitmap and it's palette will remain\n * after calling this function.\n *\n * History:   \n *            \n *   Date      Author             Reason         \n *   6/01/91   Garrett McAuliffe  Created         \n *   12/10/91  Patrick Schreiber  Modified from converting RGB to RLE8         \n *                                 to converting RGB/RLE to RGB/RLE.         \n *                                 Added wBitCount and dwCompression         \n *                                 parameters. Also added header and         \n *                                 comments.         \n *   12/11/91  Patrick Schreiber  Destroy old DIB if conversion was         \n *                                 successful.         \n *   12/16/91  Patrick Schreiber  Modified from converting DIB to new         \n *                                 DIB to bitmap to new DIB. Added palette\n *                                 parameter.\n *\n ************************************************************************/\n\nHDIB FAR ChangeBitmapFormat(HBITMAP  hBitmap,\n            WORD     wBitCount,\n            DWORD    dwCompression,\n            HPALETTE hPal)\n{\n   HDC                hDC;          // Screen DC\n   HDIB               hNewDIB=NULL; // Handle to new DIB\n   BITMAP             Bitmap;       // BITMAP data structure\n   BITMAPINFOHEADER   bi;           // Bitmap info. header\n   LPBITMAPINFOHEADER lpbi;         // Pointer to bitmap header\n   HPALETTE           hOldPal=NULL; // Handle to palette\n   WORD               NewBPP;       // New bits per pixel\n   DWORD              NewComp;      // New compression format\n\n   /* Check for a valid bitmap handle */\n   if (!hBitmap)\n      return NULL;\n\n   /* Validate wBitCount and dwCompression\n    * They must match correctly (i.e., BI_RLE4 and 4 BPP or\n    * BI_RLE8 and 8BPP, etc.) or we return failure\n    */\n   if (wBitCount == 0)\n      {\n      NewComp = dwCompression;\n      if (NewComp == BI_RLE4)\n     NewBPP = 4;\n      else if (NewComp == BI_RLE8)\n     NewBPP = 8;\n      else /* Not enough info */\n     return NULL;\n      }\n   else if (wBitCount == 1 && dwCompression == BI_RGB)\n      {\n      NewBPP = wBitCount;\n      NewComp = BI_RGB;\n      }\n   else if (wBitCount == 4)\n      {\n      NewBPP = wBitCount;\n      if (dwCompression == BI_RGB || dwCompression == BI_RLE4)\n         NewComp = dwCompression;\n      else\n         return NULL;\n      }\n   else if (wBitCount == 8)\n      {\n      NewBPP = wBitCount;\n      if (dwCompression == BI_RGB || dwCompression == BI_RLE8)\n         NewComp = dwCompression;\n      else\n         return NULL;\n      }\n   else if (wBitCount == 24 && dwCompression == BI_RGB)\n      {\n      NewBPP = wBitCount;\n      NewComp = BI_RGB;\n      }\n   else\n      return NULL;\n\n   /* Get info about the bitmap */\n   GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);\n\n   /* Fill in the BITMAPINFOHEADER appropriately */\n   bi.biSize               = sizeof(BITMAPINFOHEADER);\n   bi.biWidth              = Bitmap.bmWidth;\n   bi.biHeight             = Bitmap.bmHeight;\n   bi.biPlanes             = 1;\n   bi.biBitCount           = NewBPP;\n   bi.biCompression        = NewComp;\n   bi.biSizeImage          = 0;\n   bi.biXPelsPerMeter      = 0;\n   bi.biYPelsPerMeter      = 0;\n   bi.biClrUsed            = 0;\n   bi.biClrImportant       = 0;\n\n   /* Go allocate room for the new DIB */\n   hNewDIB = AllocRoomForDIB(bi, hBitmap);\n   if (!hNewDIB)\n      return NULL;\n\n   /* Get a pointer to the new DIB */\n   lpbi = (LPBITMAPINFOHEADER)GlobalLock(hNewDIB);\n\n   /* If we have a palette, get a DC and select/realize it */\n   if (hPal)\n   {\n      hDC  = GetDC(NULL);\n      hOldPal = SelectPalette(hDC, hPal, FALSE);\n      RealizePalette(hDC);\n   }\n\n   /* Call GetDIBits and get the new DIB bits */\n   if (!GetDIBits(hDC, hBitmap, 0, (WORD) lpbi->biHeight,\n       (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi),\n       (LPBITMAPINFO)lpbi, DIB_RGB_COLORS))\n      {\n      GlobalUnlock(hNewDIB);\n      GlobalFree(hNewDIB);\n      hNewDIB = NULL;\n      }\n\n   /* Clean up and return */\n   if (hOldPal)\n   {\n      SelectPalette(hDC, hOldPal, TRUE);\n      RealizePalette(hDC);\n      ReleaseDC(NULL, hDC);\n   }\n\n   if (hNewDIB)\n      {\n      /* Unlock the new DIB's memory block */\n      GlobalUnlock(hNewDIB);\n      }\n\n   return hNewDIB;\n}\n"
  },
  {
    "path": "CODE/DIBUTIL.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*\n *  dibutil.h\n *\n *  Copyright (c) 1991 Microsoft Corporation. All rights reserved.\n *\n *  Header file for Device-Independent Bitmap (DIB) API.  Provides\n *  function prototypes and constants for the following functions:\n *\n *  AllocRoomForDIB()   - Allocates memory for a DIB\n *\n */\n\n\n/* DIB constants */\n#define PALVERSION   0x300\n\n/* DIB macros */\n#define IS_WIN30_DIB(lpbi)  ((*(LPDWORD)(lpbi)) == sizeof(BITMAPINFOHEADER))\n#define RECTWIDTH(lpRect)     ((lpRect)->right - (lpRect)->left)\n#define RECTHEIGHT(lpRect)    ((lpRect)->bottom - (lpRect)->top)\n\n/* function prototypes */\nHANDLE          AllocRoomForDIB(BITMAPINFOHEADER bi, HBITMAP hBitmap);\n"
  },
  {
    "path": "CODE/DISPLAY.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/DISPLAY.CPP 3     3/09/97 8:04p Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DISPLAY.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : October 20, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   DisplayClass::Compute_Start_Pos -- Computes player's start pos from unit coords.          *\n *   DisplayClass::AI -- Handles the maintenance tasks for the map display.                    *\n *   DisplayClass::All_To_Look -- Direct all objects to look around for the player.            *\n *   DisplayClass::Calculated_Cell -- Fetch a map cell based on specified method.              *\n *   DisplayClass::Cell_Object -- Determines what has been clicked on.                         *\n *   DisplayClass::Cell_Shadow   -- Determine what shadow icon to use for the cell.            *\n *   DisplayClass::Center_Map -- Centers the map about the currently selected objects          *\n *   DisplayClass::Click_Cell_Calc -- Determines cell from screen X & Y.                       *\n *   DisplayClass::Closest_Free_Spot -- Finds the closest cell sub spot that is free.          *\n *   DisplayClass::Coord_To_Pixel -- Determines X and Y pixel coordinates.                     *\n *   DisplayClass::Cursor_Mark -- Set or resets the cursor display flag bits.                  *\n *   DisplayClass::DisplayClass -- Default constructor for display class.                      *\n *   DisplayClass::Draw_It -- Draws the tactical map.                                          *\n *   DisplayClass::Encroach_Shadow -- Causes the shadow to creep back by one cell.             *\n *   DisplayClass::Flag_Cell -- Flag the specified cell to be redrawn.                         *\n *   DisplayClass::Flag_To_Redraw -- Flags the display so that it will be redrawn as soon as poss*\n *   DisplayClass::Get_Occupy_Dimensions -- computes width & height of the given occupy list   *\n *   DisplayClass::Good_Reinforcement_Cell -- Checks cell for renforcement legality.           *\n *   DisplayClass::In_View -- Determines if cell is visible on screen.                         *\n *   DisplayClass::Init_Clear -- Clears the display to a known state.                          *\n *   DisplayClass::Init_IO -- Creates the map's button list                                    *\n *   DisplayClass::Init_Theater -- Theater-specific initialization                             *\n *   DisplayClass::Is_Spot_Free -- Determines if cell sub spot is free of occupation.          *\n *   DisplayClass::Map_Cell -- Mark specified cell as having been mapped.                      *\n *   DisplayClass::Mouse_Left_Held -- Handles the left button held down.                       *\n *   DisplayClass::Mouse_Left_Press -- Handles the left mouse button press.                    *\n *   DisplayClass::Mouse_Left_Release -- Handles the left mouse button release.                *\n *   DisplayClass::Mouse_Left_Up -- Handles the left mouse \"cruising\" over the map.            *\n *   DisplayClass::Mouse_Right_Press -- Handles the right mouse button press.                  *\n *   DisplayClass::Next_Object -- Searches for next object on display.                         *\n *   DisplayClass::One_Time -- Performs any special one time initializations.                  *\n *   DisplayClass::Passes_Proximity_Check -- Determines if building placement is near friendly sq*\n *   DisplayClass::Pixel_To_Coord -- converts screen coord to COORDINATE                       *\n *   DisplayClass::Prev_Object -- Searches for the previous object on the map.                 *\n *   DisplayClass::Read_INI -- Reads map control data from INI file.                           *\n *   DisplayClass::Redraw_Icons -- Draws all terrain icons necessary.                          *\n *   DisplayClass::Redraw_Shadow -- Draw the shadow overlay.                                   *\n *   DisplayClass::Refresh_Band -- Causes all cells under the rubber band to be redrawn.       *\n *   DisplayClass::Refresh_Cells -- Redraws all cells in list.                                 *\n *   DisplayClass::Remove -- Removes a game object from the rendering system.                  *\n *   DisplayClass::Repair_Mode_Control -- Controls the repair mode.                            *\n *   DisplayClass::Scroll_Map -- Scroll the tactical map in desired direction.                 *\n *   DisplayClass::Select_These -- All selectable objects in region are selected.              *\n *   DisplayClass::Sell_Mode_Control -- Controls the sell mode.                                *\n *   DisplayClass::Set_Cursor_Pos -- Controls the display and animation of the tac cursor.     *\n *   DisplayClass::Set_Cursor_Shape -- Changes the shape of the terrain square cursor.         *\n *   DisplayClass::Set_Tactical_Position -- Sets the tactical view position.                   *\n *   DisplayClass::Set_View_Dimensions -- Sets the tactical display screen coordinates.        *\n *   DisplayClass::Shroud_Cell -- Returns the specified cell into the shrouded condition.      *\n *   DisplayClass::Submit -- Adds a game object to the map rendering system.                   *\n *   DisplayClass::TacticalClass::Action -- Processes input for the tactical map.              *\n *   DisplayClass::Text_Overlap_List -- Creates cell overlap list for specified text string.   *\n *   DisplayClass::Write_INI -- Write the map data to the INI file specified.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"vortex.h\"\n\n/*\n**\tThese layer control elements are used to group the displayable objects\n**\tso that proper overlap can be obtained.\n*/\nLayerClass DisplayClass::Layer[LAYER_COUNT];\n\n/*\n** Fading tables\n*/\nunsigned char DisplayClass::FadingBrighten[256];\nunsigned char DisplayClass::FadingShade[256];\nunsigned char DisplayClass::FadingWayDark[256];\nunsigned char DisplayClass::FadingLight[256];\nunsigned char DisplayClass::FadingGreen[256];\nunsigned char DisplayClass::FadingYellow[256];\nunsigned char DisplayClass::FadingRed[256];\nunsigned char DisplayClass::TranslucentTable[(MAGIC_COL_COUNT+1)*256];\nunsigned char DisplayClass::WhiteTranslucentTable[(1+1)*256];\nunsigned char DisplayClass::MouseTranslucentTable[(4+1)*256];\nvoid const * DisplayClass::TransIconset;\nunsigned char DisplayClass::UnitShadow[(USHADOW_COL_COUNT+1)*256];\nunsigned char DisplayClass::UnitShadowAir[(USHADOW_COL_COUNT+1)*256];\nunsigned char DisplayClass::SpecialGhost[2*256];\n\nvoid const * DisplayClass::ShadowShapes;\nunsigned char DisplayClass::ShadowTrans[(SHADOW_COL_COUNT+1)*256];\n\n/*\n** Bit array of cell redraw flags\n*/\nBooleanVectorClass DisplayClass::CellRedraw;\n\n/*\n** The main button that intercepts user input to the map\n*/\nDisplayClass::TacticalClass DisplayClass::TacButton;\n\n\nstatic int const TEX_X = 0;\nstatic int const TEX_Y = 6;\nstatic int const TEX_W = 14;\n\n\n/***********************************************************************************************\n * DisplayClass::DisplayClass -- Default constructor for display class.                        *\n *                                                                                             *\n *    This constructor for the display class just initializes some of the display settings.    *\n *    Most settings are initialized with the correct values at the time that the Init function *\n *    is called. There are some cases where default values are wise and this routine fills     *\n *    those particular ones in.                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nDisplayClass::DisplayClass(void) :\n\tTacticalCoord(0),\n\tTacLeptonWidth(0),\n\tTacLeptonHeight(0),\n\tZoneCell(0),\n\tZoneOffset(0),\n\tCursorSize(0),\n\tProximityCheck(false),\n\tPendingObjectPtr(0),\n\tPendingObject(0),\n\tPendingHouse(HOUSE_NONE),\n\tTacPixelX(0),\n\tTacPixelY(0),\n\tDesiredTacticalCoord(0),\n\tIsToRedraw(true),\n\tIsRepairMode(false),\n\tIsSellMode(false),\n\tIsTargettingMode(SPC_NONE),\n\tIsRubberBand(false),\n\tIsTentative(false),\n\tIsShadowPresent(false),\n\tBandX(0),\n\tBandY(0),\n\tNewX(0),\n\tNewY(0)\n{\n\tShadowShapes = 0;\n\tTransIconset = 0;\n\n\tSet_View_Dimensions(0, 8, 320/CELL_PIXEL_W, 200/CELL_PIXEL_H);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::One_Time -- Performs any special one time initializations.                    *\n *                                                                                             *\n *    This routine is called from the game initialization process. It is to perform any one    *\n *    time initializations necessary for the map display system. It allocates the staging      *\n *    buffer needed for the radar map.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine must be called ONCE and only once.                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   05/31/1994 JLB : Handles layer system now.                                                *\n *   06/02/1994 JLB : Takes care of misc display tables and data allocation.                   *\n *=============================================================================================*/\nvoid DisplayClass::One_Time(void)\n{\n\tMapClass::One_Time();\n\n\t/*\n\t** Init the CellRedraw bit array.  Do not do this in the constructor, since the\n\t** BooleanVector may not have been constructed yet.\n\t*/\n\tCellRedraw.Resize(MAP_CELL_TOTAL);\n\n\tfor (LayerType layer = LAYER_FIRST; layer < LAYER_COUNT; layer++) {\n\t\tLayer[layer].One_Time();\n\t}\n\n\t/*\n\t**\tLoad the generic transparent icon set.\n\t*/\n\tTransIconset = MFCD::Retrieve(\"TRANS.ICN\");\n\n\t#ifndef NDEBUG\n\t\tRawFileClass file(\"SHADOW.SHP\");\n\t\tif (file.Is_Available()) {\n\t\t\tShadowShapes = Load_Alloc_Data(file);\n\t\t} else {\n\t\t\tShadowShapes = MFCD::Retrieve(\"SHADOW.SHP\");\n\t\t}\n\t#else\n\t\tShadowShapes = MFCD::Retrieve(\"SHADOW.SHP\");\n\t#endif\n\n\tSet_View_Dimensions(0, 8 * RESFACTOR);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Init_Clear -- clears the display to a known state                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Init_Clear(void)\n{\n\tMapClass::Init_Clear();\n\n\t/*\n\t** Clear any object being placed\n\t*/\n\tPendingObjectPtr = 0;\n\tPendingObject = 0;\n\tPendingHouse = HOUSE_NONE;\n\tCursorSize = 0;\n\tIsTargettingMode = SPC_NONE;\n\tIsRepairMode = false;\n\tIsRubberBand = false;\n\tIsTentative = false;\n\tIsSellMode = false;\n\n\t/*\n\t** Empty all the display's layers\n\t*/\n\tfor (LayerType layer = LAYER_FIRST; layer < LAYER_COUNT; layer++) {\n\t\tLayer[layer].Init();\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Init_IO -- clears & re-builds the map's button list                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Init_IO(void)\n{\n\tMapClass::Init_IO();\n\t/*\n\t** Re-attach our buttons to the main map button list, only in non-edit mode.\n\t*/\n\tif (!Debug_Map) {\n\t\tTacButton.Zap();\n\t\tAdd_A_Button(TacButton);\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Init_Theater -- Performs theater-specific initialization (mixfiles, etc)      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      theater         new theater                                                            *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 BRR : Created.                                                                 *\n *   05/07/1996 JLB : Added translucent tables.                                                *\n *=============================================================================================*/\nvoid DisplayClass::Init_Theater(TheaterType theater)\n{\n\tchar\t\t\tfullname[16];\n\tstatic TLucentType const MouseCols[4] = {\n\t\t{BLACK, BLACK, 110, 0},\n\t\t{WHITE, WHITE, 110, 0},\n\t\t{LTGREY, LTGREY, 110, 0},\n\t\t{DKGREY, DKGREY, 110, 0}\n\t};\n\tstatic TLucentType const MagicCols[MAGIC_COL_COUNT] = {\n\t\t{32,32,110,0},\n\t\t{33,33,110,0},\n\t\t{34,34,110,0},\n\t\t{35,35,110,0},\n\t\t{36,36,110,0},\n\t\t{37,37,110,0},\n\t\t{38,38,110,0},\n\t\t{39,39,110,0},\n\t\t{BLACK, BLACK, 200, 0},\n\t\t{WHITE, BLACK, 40, 0},\n\t\t{LTGREY, BLACK, 80, 0},\n\t\t{DKGREY, BLACK, 140, 0},\n\t\t{LTGREEN,\tBLACK,130,0}\n\t};\n\tstatic TLucentType const WhiteCols[1] = {\n\t\t{1, WHITE, 80, 0}\n\t};\n\tstatic TLucentType const ShadowCols[SHADOW_COL_COUNT] = {\n\t\t{WHITE+1,\tBLACK,130,0},\n\t\t{WHITE,\t\tBLACK,170,0},\n\t\t{LTGRAY,\t\tBLACK,250,0},\n\t\t{DKGRAY,\t\tBLACK,250,0}\n\t};\n\tstatic TLucentType const UShadowCols[USHADOW_COL_COUNT] = {\n\t\t{LTGREEN,\tBLACK,130,0}\n\t};\n\tstatic TLucentType const UShadowColsAir[USHADOW_COL_COUNT] = {\n\t\t{LTGREEN,\tWHITE,0,0}\n\t};\n\tstatic TLucentType const UShadowColsSnow[USHADOW_COL_COUNT] = {\n\t\t{LTGREEN,\tBLACK,75,0}\n\t};\n\n\t/*\n\t**\tInvoke parent's init routine.\n\t*/\n\tMapClass::Init_Theater(theater);\n\n\t/*\n\t** Save the new theater value\n\t*/\n\tScen.Theater = theater;\n\n\t/*\n\t** Unload old mixfiles, and cache the new ones\n\t*/\n\tsprintf(fullname, \"%s.MIX\", Theaters[theater].Root);\n\n#ifndef WIN32\nLastTheater = THEATER_NONE;\n#endif\n\n\tif (Scen.Theater != LastTheater) {\n\t\tif (TheaterData != NULL) {\n\t\t\tdelete TheaterData;\n\t\t}\n\t\tTheaterData = new MFCD(fullname, &FastKey);\n\t\tassert(TheaterData != NULL);\n\n\t\tbool theaterload = TheaterData->Cache(TheaterBuffer);\n\t\tassert(theaterload);\n//\t\tLastTheater = Scen.Theater;\n\t}\n\n\t/*\n\t**\tLoad the custom palette associated with this theater.\n\t**\tThe fading palettes will have to be generated as well.\n\t*/\n\tsprintf(fullname, \"%s.PAL\", Theaters[theater].Root);\n\tPaletteClass const * ptr = (PaletteClass *)MFCD::Retrieve(fullname);\n\tGamePalette = * ptr;\n\n\tOriginalPalette = GamePalette;\n\n\tBuild_Fading_Table(GamePalette, FadingGreen, GREEN, 110);\n\n\tBuild_Fading_Table(GamePalette, FadingYellow, YELLOW, 140);\n\n\tBuild_Fading_Table(GamePalette, FadingRed, RED, 140);\n\n\tBuild_Translucent_Table(GamePalette, &MouseCols[0], 4, MouseTranslucentTable);\n\n\tBuild_Translucent_Table(GamePalette, &MagicCols[0], MAGIC_COL_COUNT, TranslucentTable);\n\n\tBuild_Translucent_Table(GamePalette, &WhiteCols[0], 1, WhiteTranslucentTable);\n\n\tBuild_Translucent_Table(GamePalette, &ShadowCols[0], SHADOW_COL_COUNT, ShadowTrans);\n\n\tConquer_Build_Translucent_Table(GamePalette, &UShadowColsAir[0], USHADOW_COL_COUNT, UnitShadowAir);\n\tmemcpy(&UnitShadowAir[256], ColorRemaps[PCOLOR_GOLD].RemapTable, sizeof(ColorRemaps[PCOLOR_GOLD].RemapTable));\n\tif (theater == THEATER_SNOW) {\n\t\tConquer_Build_Translucent_Table(GamePalette, &UShadowColsSnow[0], USHADOW_COL_COUNT, UnitShadow);\n\t} else {\n\t\tConquer_Build_Translucent_Table(GamePalette, &UShadowCols[0], USHADOW_COL_COUNT, UnitShadow);\n\t}\n\n\tif (theater == THEATER_SNOW) {\n\t\tConquer_Build_Fading_Table(GamePalette, FadingShade, BLACK, 75);\n\t} else {\n\t\tConquer_Build_Fading_Table(GamePalette, FadingShade, BLACK, 130);\n\t}\n\n\tConquer_Build_Fading_Table(GamePalette, FadingLight, WHITE, 85);\n\n\t/*\n\t**\tCreate the shadow color used by aircraft.\n\t*/\n\tConquer_Build_Fading_Table(GamePalette, &SpecialGhost[256], BLACK, 100);\n\tfor (int index = 0; index < 256; index++) {\n\t\tSpecialGhost[index] = 0;\n\t}\n\n\tMake_Fading_Table(GamePalette, FadingBrighten, WHITE, 25);\n\n\tMake_Fading_Table(GamePalette, FadingWayDark, DKGRAY, 192);\n\n\t/*\n\t**\tAdjust the palette according to the visual control option settings.\n\t*/\n\tOptions.Fixup_Palette();\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Text_Overlap_List -- Creates cell overlap list for specified text string.     *\n *                                                                                             *\n *    This routine is used to create an overlap list that specifies all the cells that are     *\n *    covered by the specified text string. This overlap list is used to handle map  refresh   *\n *    logic.                                                                                   *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text that would appear on the map and must have an         *\n *                   overlap list generated.                                                   *\n *                                                                                             *\n *          x,y   -- The coordinates that the text would appear (upper left corner).           *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to an overlap list that covers all cells \"under\" the text   *\n *          if were displayed at the coordinates specified. The list is actually a series of   *\n *          offsets from the display's upper left corner cell number.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/06/1994 JLB : Created.                                                                 *\n *   12/07/1994 JLB : Sidebar fixup.                                                           *\n *   08/13/1995 JLB : Optimized for variable sized help text.                                  *\n *=============================================================================================*/\nshort const * DisplayClass::Text_Overlap_List(char const * text, int x, int y) const\n{\n\tstatic short _list[60];\n\tint count = ARRAY_SIZE(_list);\n\n\tif (text != NULL) {\n\t\tshort * ptr = &_list[0];\n\t\tint len = String_Pixel_Width(text)+CELL_PIXEL_W;\n\t\tint right = TacPixelX + Lepton_To_Pixel(TacLeptonWidth);\n\n\t\t/*\n\t\t**\tIf the help text would spill into the sidebar, then flag this fact, but\n\t\t**\tshorten the apparent length so that the icon list calculation will\n\t\t**\tfunction correctly.\n\t\t*/\n\t\tif (x+len >= TacPixelX+Lepton_To_Pixel(TacLeptonWidth)) {\n\t\t\tlen = right-x;\n\t\t\t*ptr++ = REFRESH_SIDEBAR;\n\t\t\tcount--;\n\t\t}\n\n\t\t/*\n\t\t**\tBuild the list of overlap cell offset values according to the text\n\t\t**\tcoordinate and the length.\n\t\t*/\n\t\tif (x <= right) {\n\t\t\tCELL ul = Click_Cell_Calc(x, y-1);\n\t\t\tCELL lr = Click_Cell_Calc(x+len-1, Bound(y+24, TacPixelY, TacPixelY+Lepton_To_Pixel(TacLeptonHeight) - 1));\n\n\t\t\tif (ul == -1) ul = Click_Cell_Calc(x, y);\n\n\t\t\tif (ul != -1 && lr != -1) {\n\t\t\t\tfor (int yy = Cell_Y(ul); yy <= Cell_Y(lr); yy++) {\n\t\t\t\t\tfor (int xx = Cell_X(ul); xx <= Cell_X(lr); xx++) {\n\t\t\t\t\t\t*ptr++ = XY_Cell(xx, yy) - Coord_Cell(TacticalCoord);\n\t\t\t\t\t\tcount--;\n\t\t\t\t\t\tif (count < 2) break;\n\t\t\t\t\t}\n\t\t\t\t\tif (count < 2) break;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t*ptr = REFRESH_EOL;\n\t}\n\treturn(_list);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Set_View_Dimensions -- Sets the tactical display screen coordinates.          *\n *                                                                                             *\n *    Use this routine to set the tactical map screen coordinates and dimensions. This routine *\n *    is typically used when the screen size or position changes as a result of the sidebar    *\n *    changing position or appearance.                                                         *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y pixel position on the screen for the tactical map upper left  *\n *                   corner.                                                                   *\n *                                                                                             *\n *          width -- The width of the tactical display (in icons). If this parameter is        *\n *                   omitted, then the width will be as wide as the screen will allow.         *\n *                                                                                             *\n *          height-- The height of the tactical display (in icons). If this parameter is       *\n *                   omitted, then the width will be as wide as the screen will allow.         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/06/1994 JLB : Created.                                                                 *\n *   06/27/1995 JLB : Adjusts tactical map position if necessary.                              *\n *=============================================================================================*/\nvoid DisplayClass::Set_View_Dimensions(int x, int y, int width, int height)\n{\n\tif (width == -1) {\n\t\tTacLeptonWidth = Pixel_To_Lepton(SeenBuff.Get_Width()-x);\n\t} else {\n\t\tTacLeptonWidth = width * CELL_LEPTON_W;\n\t}\n\n\tif (height == -1) {\n\t\theight = (SeenBuff.Get_Height()-y) / CELL_PIXEL_H;\n\t}\n\tTacLeptonHeight = height * CELL_LEPTON_H;\n\n\t/*\n\t**\tAdjust the tactical cell if it is now in an invalid position\n\t**\tbecause of the changed dimensions.\n\t*/\n\tint xx = Coord_X(TacticalCoord) - (MapCellX * CELL_LEPTON_W);\n\tint yy = Coord_Y(TacticalCoord) - (MapCellY * CELL_LEPTON_H);\n\n\tConfine_Rect(&xx, &yy, TacLeptonWidth, TacLeptonHeight, MapCellWidth * CELL_LEPTON_W, MapCellHeight * CELL_LEPTON_H);\n\n\tSet_Tactical_Position(XY_Coord(xx + (MapCellX * CELL_LEPTON_W), yy + (MapCellY * CELL_LEPTON_H)));\n\n\tTacPixelX = x;\n\tTacPixelY = y;\n\tWindowList[WINDOW_TACTICAL][WINDOWX] = x;\n\tWindowList[WINDOW_TACTICAL][WINDOWY] = y;\n\tWindowList[WINDOW_TACTICAL][WINDOWWIDTH] = Lepton_To_Pixel(TacLeptonWidth);\n\tWindowList[WINDOW_TACTICAL][WINDOWHEIGHT] = Lepton_To_Pixel(TacLeptonHeight);\n\tif (Window == WINDOW_TACTICAL) {\n\t\tChange_Window(0);\n\t\tChange_Window(Window);\n\t}\n\tIsToRedraw = true;\n\tFlag_To_Redraw(false);\n\n\tTacButton.X = TacPixelX;\n\tTacButton.Y = TacPixelY;\n\tTacButton.Width = Lepton_To_Pixel(TacLeptonWidth);\n\tTacButton.Height = Lepton_To_Pixel(TacLeptonHeight);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Set_Cursor_Shape -- Changes the shape of the terrain square cursor.           *\n *                                                                                             *\n *    This routine is used to set up the terrain cursor according to the size of the object    *\n *    that is to be placed down. The terrain cursor looks like an arbitrary collection of      *\n *    hatched square overlays. Typical use is when placing buildings.                          *\n *                                                                                             *\n * INPUT:   list  -- A pointer to the list that contains offsets to the cells that are to      *\n *                   be marked.                                                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1994 JLB : Created.                                                                 *\n *   06/26/1995 JLB : Puts placement cursor into static buffer.                                *\n *=============================================================================================*/\nvoid DisplayClass::Set_Cursor_Shape(short const * list)\n{\n\tif (CursorSize) {\n\t\tCursor_Mark(ZoneCell+ZoneOffset, false);\n\t}\n\tZoneOffset = 0;\n\n\tif (list) {\n\t\tint\tw,h;\n\t\tstatic short _list[50];\n\n\t\tmemcpy(_list, list, sizeof(_list));\n\t\tCursorSize = _list;\n\t\tGet_Occupy_Dimensions (w, h, CursorSize);\n\t\tZoneOffset = -(((h/2)*MAP_CELL_W)+(w/2));\n\t\tCursor_Mark(ZoneCell+ZoneOffset, true);\n\t} else {\n\t\tCursorSize = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Passes_Proximity_Check -- Determines if building placement is near friendly sq*\n *                                                                                             *\n *    This routine is used by the building placement cursor logic to determine whether the     *\n *    at the current cursor position if the building would be adjacent to another friendly     *\n *    building. In cases where this is not true, then the building cannot be placed at all.    *\n *    This determination is returned by the function.                                          *\n *                                                                                             *\n * INPUT:   object   -- The building object that the current placement system is examining.    *\n *                                                                                             *\n *          house    -- The house to base the proximity check upon. Typically this is the      *\n *                      player's house, but in multiplay, the computer needs to check for      *\n *                      proximity as well.                                                     *\n *                                                                                             *\n *          list     -- Pointer to the building's offset list.                                 *\n *                                                                                             *\n *          trycell  -- The cell to base the offset list on.                                   *\n *                                                                                             *\n * OUTPUT:  bool; Can the pending building object be placed at the present cursor location     *\n *                checking only for proximity to friendly buildings?  If this isn't for a      *\n *                building type object, then this routine always returns true.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/06/1994 JLB : Created.                                                                 *\n *   06/07/1994 JLB : Handles concrete check.                                                  *\n *   10/11/1994 BWG : Added IsProximate check for ore refineries                               *\n *=============================================================================================*/\nbool DisplayClass::Passes_Proximity_Check(ObjectTypeClass const * object, HousesType house, short const * list, CELL trycell) const\n{\n\tshort const * ptr;\n\tint retval = -1;\n\tbool noradar = false;\n\tbool nomapped = false;\n\tbool shipyard = false;\n\n\tif (house == PlayerPtr->Class->House) {\n\t\tPassedProximity = false;\n\t}\n\n\t/*\n\t** In editor mode, the proximity check always passes.\n\t*/\n\tif (Debug_Map) {\n\t\treturn(true);\n\t}\n\n\tif (list == NULL || trycell == 0) {\n\t\treturn(true);\n\t}\n\n\tif (object == NULL || object->What_Am_I() != RTTI_BUILDINGTYPE) {\n\t\treturn(true);\n\t}\n\n\tBuildingTypeClass const * building = (BuildingTypeClass const *)object;\n\n\t/*\n\t**\tScan through all cells that the building foundation would cover. If any adjacent\n\t**\tcells to these are of friendly persuasion, then consider the proximity check to\n\t**\thave been a success.\n\t*/\n\tptr = list;\n//\tptr = CursorSize;\n\tCELL cell = trycell;\n//\tCELL cell = ZoneCell;\n\tif (building->Adjacent == 1) {\n\t\twhile (*ptr != REFRESH_EOL && (retval == -1) ) {\n\t\t\tcell = trycell + *ptr++;\n//\t\t\tcell = ZoneCell + ZoneOffset + *ptr++;\n\n\t\t\tif (!In_Radar(cell)) {\n\t\t\t\tretval = false;\n\t\t\t\tnoradar = true;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tfor (FacingType facing = FACING_FIRST; facing < FACING_COUNT; facing++) {\n\t\t\t\tCELL\tnewcell = Adjacent_Cell(cell, facing);\n\n\t\t\t\tif (!In_Radar(newcell)) continue;\n\n\t\t\t\tif (!(*this)[newcell].IsMapped) {\n\t\t\t\t\tnomapped = true;\n\t\t\t\t}\n\t\t\t\tTechnoClass * base = (*this)[newcell].Cell_Techno();\n\n\t\t\t\t/*\n\t\t\t\t**\tThe special cell ownership flag allows building adjacent\n\t\t\t\t**\tto friendly walls and bibs even though there is no official\n\t\t\t\t**\tbuilding located there.\n\t\t\t\t*/\n\t\t\t\t//BG: Modified so only walls can be placed next to walls - buildings can't.\n\t\t\t\t//JLB: Except for bibs, in which case buildings can be placed next to these.\n\t\t\t\tif (building->IsWall ||\n\t\t\t\t\t((*this)[newcell].Smudge != SMUDGE_NONE && SmudgeTypeClass::As_Reference((*this)[newcell].Smudge).IsBib)) {\n\n\t\t\t\t\tif ((*this)[newcell].Owner == house) {\n\t\t\t\t\t\tretval = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// we've found a building...\n\t\t\t\tif (base != NULL && base->What_Am_I() == RTTI_BUILDING && base->House->Class->House == house && ((BuildingClass *)base)->Class->IsBase) {\n\t\t\t\t\tretval = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/* BG: modifications to allow buildings one cell away from other buildings.\n\t\t\t\t** This is done by scanning each cell that fails the check (hence getting\n\t\t\t\t** to this point) and looking at the n/s/e/w adjacent cells to see if they\n\t\t\t\t** have buildings in them.  If they do, and they match us, then succeed.\n\t\t\t\t*/\n\t\t\t\tif (retval != -1) break;\n\n\t\t\t\tfor (FacingType newface = FACING_N; newface < FACING_COUNT; newface++) {\n\t\t\t\t\tCELL\tnewercell = Adjacent_Cell(newcell, newface);\n\n\t\t\t\t\tif (building->IsWall ||\n\t\t\t\t\t\t\t\t\t((*this)[newercell].Smudge != SMUDGE_NONE && SmudgeTypeClass::As_Reference((*this)[newercell].Smudge).IsBib)) {\n\n\t\t\t\t\t\tif ((*this)[newercell].Owner == house) {\n\t\t\t\t\t\t\tretval = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tTechnoClass * newbase = (*this)[newercell].Cell_Techno();\n\n\t\t\t\t\t// we've found a building...\n\t\t\t\t\tif (newbase != NULL && newbase->What_Am_I() == RTTI_BUILDING && newbase->House->Class->House == house && ((BuildingClass const *)newbase)->Class->IsBase) {\n\t\t\t\t\t\tretval = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (retval != -1) break;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (retval == -1) retval = false;\n\n\tif (house == PlayerPtr->Class->House) {\n\t\tPassedProximity = (retval != false);\n\t}\n\n\t/*\n\t**\tIf this object has special dispensation to be placed further than one cell from\n\t**\tother regular buildings, then check for this case now. Only bother to check if\n\t**\tit hasn't already been given permission to be placed down.\n\t*/\n\tif (!retval && !noradar && object->What_Am_I() == RTTI_BUILDINGTYPE) {\n\n\t\t// For land mines, let's make it check proximity within 10 squares\n\t\tif (building->Adjacent > 1) {\n\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\tBuildingClass * obj = Buildings.Ptr(index);\n\t\t\t\tif (obj != NULL && !obj->IsInLimbo && obj->House->Class->House == house && obj->Class->IsBase) {\n\t\t\t\t\tint centdist = ::Distance(obj->Center_Coord(), Cell_Coord(cell));\n\t\t\t\t\tcentdist /= CELL_LEPTON_W;\n\t\t\t\t\tcentdist -= (obj->Class->Width() + obj->Class->Height()) / 2;\n\t\t\t\t\tif (centdist <= building->Adjacent) {\n\t\t\t\t\t\tretval = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn((bool)retval);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Set_Cursor_Pos -- Controls the display and animation of the tac cursor.       *\n *                                                                                             *\n *    This routine controls the location, display, and animation of the                        *\n *    tactical map cursor.                                                                     *\n *                                                                                             *\n * INPUT:   pos   -- Position to move the cursor do. If -1 is passed then                      *\n *                   the cursor will just be hidden. If the position                           *\n *                   passed is the same as the last position passed in,                        *\n *                   then animation could occur (based on timers).                             *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1991 JLB : Created.                                                                 *\n *   06/02/1994 JLB : Converted to member function.                                            *\n *   06/08/1994 JLB : If position is -1, then follow mouse.                                    *\n *   02/28/1995 JLB : Forces placement cursor to fit on map.                                   *\n *=============================================================================================*/\nCELL DisplayClass::Set_Cursor_Pos(CELL pos)\n{\n\tCELL\tprevpos;\t\t\t// Last position of cursor (for jump-back reasons).\n\n\t/*\n\t**\tFollow the mouse position if no cell number is provided.\n\t*/\n\tif (pos == -1) {\n\t\tpos = Click_Cell_Calc(Get_Mouse_X(), Get_Mouse_Y());\n\t}\n\n\tif (CursorSize == NULL) {\n\t\tprevpos = ZoneCell;\n\t\tZoneCell = pos;\n\t\treturn(prevpos);\n\t}\n\n\t/*\n\t**\tAdjusts the position so that the placement cursor is never part way off the\n\t**\ttactical map.\n\t*/\n\tint w,h;\n\tGet_Occupy_Dimensions(w, h, CursorSize);\n\n\tint x = Cell_X(pos + ZoneOffset);\n\tint y = Cell_Y(pos + ZoneOffset);\n\n\tif (x < Coord_XCell(TacticalCoord)) x = Coord_XCell(TacticalCoord);\n\tif (y < Coord_YCell(TacticalCoord)) y = Coord_YCell(TacticalCoord);\n\tif (x+w >= Coord_XCell(TacticalCoord) + Lepton_To_Cell(TacLeptonWidth)) x = Coord_XCell(TacticalCoord)+Lepton_To_Cell(TacLeptonWidth)-w;\n\tif (y+h >= Coord_YCell(TacticalCoord) + Lepton_To_Cell(TacLeptonHeight)) y = Coord_YCell(TacticalCoord)+Lepton_To_Cell(TacLeptonHeight)-h;\n\tpos = XY_Cell(x, y) - ZoneOffset;\n\n\t/*\n\t** This checks to see if NO animation or drawing is to occur and, if so,\n\t**\texits.\n\t*/\n\tif (pos == ZoneCell) return(pos);\n\n\tprevpos = ZoneCell;\n\n\t/*\n\t**\tIf the cursor is visible, then handle the graphic update.\n\t**\tOtherwise, just update the global position of the cursor.\n\t*/\n\tif (CursorSize != NULL) {\n\n\t\t/*\n\t\t** Erase the old cursor (if it exists) AND the cursor is moving.\n\t\t*/\n\t\tif (pos != ZoneCell && ZoneCell != -1) {\n\t\t\tCursor_Mark(ZoneCell+ZoneOffset, false);\n\t\t}\n\n\t\t/*\n\t\t** Render the cursor (could just be animation).\n\t\t*/\n\t\tif (pos != -1) {\n\t\t\tCursor_Mark(pos+ZoneOffset, true);\n\t\t}\n\t}\n\tZoneCell = pos;\n\tProximityCheck = Passes_Proximity_Check(PendingObject, PendingHouse, CursorSize, ZoneCell+ZoneOffset);\n\n\treturn(prevpos);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Get_Occupy_Dimensions -- computes width & height of the given occupy list     *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      w      ptr to fill in with height                                                      *\n *      h      ptr to fill in with width                                                       *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/31/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Get_Occupy_Dimensions(int & w, int & h, short const * list) const\n{\n\tint min_x = MAP_CELL_W;\n\tint max_x = -MAP_CELL_W;\n\tint min_y = MAP_CELL_H;\n\tint max_y = -MAP_CELL_H;\n\tint x,y;\n\n\tw = 0;\n\th = 0;\n\n\tif (!list) {\n\t\t/*\n\t\t** Loop through all cell offsets, accumulating max & min x- & y-coords\n\t\t*/\n\t\twhile (*list != REFRESH_EOL) {\n\t\t\t/*\n\t\t\t** Compute x & y coords of the current cell offset.  We can't use Cell_X()\n\t\t\t** & Cell_Y(), because they use shifts to compute the values, and if the\n\t\t\t** offset is negative we'll get a bogus coordinate!\n\t\t\t*/\n\t\t\tx = (*list) % MAP_CELL_W;\n\t\t\ty = (*list) / MAP_CELL_H;\n\n\t\t\tmax_x = max(max_x, x);\n\t\t\tmin_x = min(min_x, x);\n\t\t\tmax_y = max(max_y, y);\n\t\t\tmin_y = min(min_y, y);\n\n\t\t\tlist++;\n\t\t}\n\n\t\tw = max(1, max_x - min_x + 1);\n\t\th = min(1, max_y - min_y + 1);\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Cursor_Mark -- Set or resets the cursor display flag bits.                    *\n *                                                                                             *\n *    This routine will clear or set the cursor display bits on the map.                       *\n *    If the bit is set, then the cursor will be rendered on that map                          *\n *    icon.                                                                                    *\n *                                                                                             *\n * INPUT:   pos   -- Position of the upper left corner of the cursor.                          *\n *                                                                                             *\n *          on    -- Should the bit be turned on?                                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure that every call to set the bits is matched by a                         *\n *             corresponding call to clear the bits.                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/04/1991 JLB : Created.                                                                 *\n *   06/02/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nvoid DisplayClass::Cursor_Mark(CELL pos, bool on)\n{\n\tCELL const * ptr;\n\tCellClass * cellptr;\n\n\tif (pos == -1) return;\n\n\t/*\n\t**\tFor every cell in the CursorSize list, invoke its Redraw_Objects and\n\t**\ttoggle its IsCursorHere flag\n\t*/\n\tptr = CursorSize;\n\twhile (*ptr != REFRESH_EOL) {\n\t\tCELL cell = pos + *ptr++;\n\t\tif (In_Radar(cell)) {\n\t\t\tcellptr = &(*this)[cell];\n\t\t\tcellptr->Redraw_Objects();\n\t\t\tif (on) {\n\t\t\t\tcellptr->IsCursorHere = true;\n\t\t\t} else {\n\t\t\t\tcellptr->IsCursorHere = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tFor every cell in the PendingObjectPtr's Overlap_List, invoke its\n\t**\tRedraw_Objects routine.\n\t*/\n\tif (PendingObjectPtr) {\n\t\tptr = PendingObjectPtr->Overlap_List();\n\t\twhile (*ptr != REFRESH_EOL) {\n\t\t\tCELL cell = pos + *ptr++;\n\t\t\tif (In_Radar(cell)) {\n\t\t\t\tcellptr = &(*this)[cell];\n\t\t\t\tcellptr->Redraw_Objects();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::AI -- Handles the maintenance tasks for the map display.                      *\n *                                                                                             *\n *    This routine is called once per game display frame (15 times per second). It handles     *\n *    the mouse shape tracking and map scrolling as necessary.                                 *\n *                                                                                             *\n * INPUT:   input -- The next key just fetched from the input queue.                           *\n *                                                                                             *\n *          x,y   -- Mouse coordinates.                                                        *\n *                                                                                             *\n * OUTPUT:  Modifies the input code if necessary. When the input code is consumed, it gets     *\n *          set to 0.                                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/01/1994 JLB : Created.                                                                 *\n *   06/02/1994 JLB : Filters mouse click input.                                               *\n *   06/07/1994 JLB : Fixed so template click will behave right.                               *\n *   10/14/1994 JLB : Changing cursor shape over target.                                       *\n *   12/31/1994 JLB : Takes mouse coordinates as parameters.                                   *\n *   06/27/1995 JLB : Breaks out of rubber band mode if mouse leaves map.                      *\n *=============================================================================================*/\nvoid DisplayClass::AI(KeyNumType & input, int x, int y)\n{\n\tif (\n\t\tIsRubberBand &&\n\t\t(Get_Mouse_X() < TacPixelX ||\n\t\tGet_Mouse_Y() < TacPixelY ||\n\t\tGet_Mouse_X() >= (TacPixelX + Lepton_To_Pixel(TacLeptonWidth)) ||\n\t\tGet_Mouse_Y() >= (TacPixelY + Lepton_To_Pixel(TacLeptonHeight)))) {\n\t\t\tMouse_Left_Release(-1, Get_Mouse_X(), Get_Mouse_Y(), NULL, ACTION_NONE);\n\t}\n\n\tMapClass::AI(input, x, y);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Submit -- Adds a game object to the map rendering system.                     *\n *                                                                                             *\n *    This routine is used to add an arbitrary (but tangible) game object to the map. It will  *\n *    be rendered (made visible) once it is submitted to this function. This function builds   *\n *    the list of game objects that get rendered each frame as necessary. It is possible to    *\n *    submit the game object to different rendering layers. All objects in a layer get drawn   *\n *    at the same time. Using this layer method it becomes possible to have objects \"below\"    *\n *    other objects.                                                                           *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object to add.                                          *\n *                                                                                             *\n *          layer    -- The layer to add the object to.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   05/31/1994 JLB : Improved layer system.                                                   *\n *   05/31/1994 JLB : Sorts object position if this is for the ground layer.                   *\n *=============================================================================================*/\nvoid DisplayClass::Submit(ObjectClass const * object, LayerType layer)\n{\n\tif (object) {\n\t\tLayer[layer].Submit(object, (layer == LAYER_GROUND));\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Remove -- Removes a game object from the rendering system.                    *\n *                                                                                             *\n *    Every object that is to disappear from the map must be removed from the rendering        *\n *    system.                                                                                  *\n *                                                                                             *\n * INPUT:   object   -- The object to remove.                                                  *\n *                                                                                             *\n *          layer    -- The layer to remove it from.                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   05/31/1994 JLB : Improved layer system.                                                   *\n *=============================================================================================*/\nvoid DisplayClass::Remove(ObjectClass const * object, LayerType layer)\n{\n\tassert(object != 0);\n\tassert(object->IsActive);\n\n\tif (object) {\n\t\tLayer[layer].Delete((ObjectClass *)object);\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Click_Cell_Calc -- Determines cell from screen X & Y.                         *\n *                                                                                             *\n *    This routine is used to determine the cell that is located at the                        *\n *    screen pixel coordinates given. Typical use is when the player                           *\n *    clicks with the mouse on the tactical map.                                               *\n *                                                                                             *\n * INPUT:   x,y   -- Screen pixel coordinates.                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with cell that is under the coordinates specified.                         *\n *          If the coordinate specified is outside of the tactical                             *\n *          map, then -1 is returned.                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL DisplayClass::Click_Cell_Calc(int x, int y) const\n{\n\tx -= TacPixelX;\n\tx = Pixel_To_Lepton(x);\n\ty -= TacPixelY;\n\ty = Pixel_To_Lepton(y);\n\n\tif ((unsigned)x < TacLeptonWidth && (unsigned)y < TacLeptonHeight) {\n\t\tCOORDINATE tcoord = XY_Coord(Pixel_To_Lepton(Lepton_To_Pixel(Coord_X(TacticalCoord))), Pixel_To_Lepton(Lepton_To_Pixel(Coord_Y(TacticalCoord))));\n\t\treturn(Coord_Cell(Coord_Add(tcoord, XY_Coord(x, y))));\n\t}\n\treturn(-1);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Scroll_Map -- Scroll the tactical map in desired direction.                   *\n *                                                                                             *\n *    This routine is used to scroll the tactical map view in the desired                      *\n *    direction. It can also be used to determine if scrolling would be                        *\n *    legal without actually performing any scrolling action.                                  *\n *                                                                                             *\n * INPUT:   facing   -- The direction to scroll the tactical map.                              *\n *                                                                                             *\n *          distance -- The distance in leptons to scroll the map.                             *\n *                                                                                             *\n *          really   -- Should the map actually be scrolled?  If false,                        *\n *                      then only the legality of a scroll is checked.                         *\n *                                                                                             *\n * OUTPUT:  bool; Would scrolling in the desired direction be possible?                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *   05/20/1994 JLB : Converted to member function.                                            *\n *   08/09/1995 JLB : Added distance parameter.                                                *\n *   08/10/1995 JLB : Any direction scrolling.                                                 *\n *=============================================================================================*/\nbool DisplayClass::Scroll_Map(DirType facing, int & distance, bool really)\n{\n\t/*\n\t**\tIf the distance is invalid then no further checking is required. Bail\n\t**\twith a no-can-do flag.\n\t*/\n\tif (distance == 0) return(false);\n\tFacingType crude = Dir_Facing(facing);\n\n\tif (Coord_X(TacticalCoord) == Cell_To_Lepton(MapCellX) && crude != FACING_W) {\n\t\tif (crude == FACING_SW) facing = DIR_S;\n\t\tif (crude == FACING_NW) facing = DIR_N;\n\t}\n\tif (Coord_Y(TacticalCoord) == Cell_To_Lepton(MapCellY) && crude != FACING_N) {\n\t\tif (crude == FACING_NW) facing = DIR_W;\n\t\tif (crude == FACING_NE) facing = DIR_E;\n\t}\n\tif (Coord_X(TacticalCoord) + TacLeptonWidth == Cell_To_Lepton(MapCellX+MapCellWidth) && crude != FACING_E) {\n\t\tif (crude == FACING_NE) facing = DIR_N;\n\t\tif (crude == FACING_SE) facing = DIR_S;\n\t}\n\tif (Coord_Y(TacticalCoord) + TacLeptonHeight == Cell_To_Lepton(MapCellY+MapCellHeight) && crude != FACING_S) {\n\t\tif (crude == FACING_SE) facing = DIR_E;\n\t\tif (crude == FACING_SW) facing = DIR_W;\n\t}\n\n\t/*\n\t**\tDetermine the coordinate that it wants to scroll to.\n\t*/\n\tCOORDINATE coord = Coord_Move(TacticalCoord, facing, distance);\n\n\t/*\n\t**\tClip the new coordinate to the edges of the game world.\n\t*/\n\tint xx = (int)(short)Coord_X(coord) - (short)Cell_To_Lepton(MapCellX);\n\tint yy = (int)(short)Coord_Y(coord) - (short)Cell_To_Lepton(MapCellY);\n\tbool shifted = Confine_Rect(&xx, &yy, TacLeptonWidth, TacLeptonHeight, Cell_To_Lepton(MapCellWidth), Cell_To_Lepton(MapCellHeight));\n\tif (xx < 0) {\n\t\txx = 0;\n\t\tshifted = true;\n\t}\n\tif (yy < 0) {\n\t\tyy = 0;\n\t\tshifted = true;\n\t}\n\tcoord = XY_Coord(xx + Cell_To_Lepton(MapCellX), yy + Cell_To_Lepton(MapCellY));\n\n\t/*\n\t**\tIf the desired scroll was bound by the edge of the map, then adjust the distance to more accurately\n\t**\treflect the actual distance moved.\n\t*/\n\tif (shifted) {\n\t\tdistance = Distance(TacticalCoord, coord);\n\t}\n\n\t/*\n\t**\tIf the new coordinate is the same as the old, then no scrolling would occur.\n\t*/\n\tif (!distance || coord == TacticalCoord) return(false);\n\n\t/*\n\t**\tSince the new coordinate is different than the old one, possibly adjust the real\n\t**\ttactical map accordingly.\n\t*/\n\tif (really) {\n\t\tSet_Tactical_Position(coord);\n\t\tIsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\n\t\t/*\n\t\t**\tScrolled map REQUIRES all top layer units to be redrawn.\n\t\t*/\n\t\tfor (int index = 0; index < Layer[LAYER_TOP].Count(); index++) {\n\t\t\tLayer[LAYER_TOP][index]->Mark(MARK_CHANGE);\n\t\t}\n\t\tfor (index = 0; index < Layer[LAYER_AIR].Count(); index++) {\n\t\t\tLayer[LAYER_AIR][index]->Mark(MARK_CHANGE);\n\t\t}\n\n\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Refresh_Cells -- Redraws all cells in list.                                   *\n *                                                                                             *\n *    This routine is used to flag all cells in the specified list for                         *\n *    redrawing.                                                                               *\n *                                                                                             *\n * INPUT:   cell  -- The origin cell that the list is offset from.                             *\n *                                                                                             *\n *          list  -- Pointer to a list of offsets from the origin cell.                        *\n *                   Each cell so specified is flagged for redraw.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine is rather slow (by definition).                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/14/1994 JLB : Created.                                                                 *\n *   08/01/1994 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid DisplayClass::Refresh_Cells(CELL cell, short const * list)\n{\n\tshort tlist[36];\n\n\tif (*list == REFRESH_SIDEBAR) {\n\t\tlist++;\n\t}\n\n\tList_Copy(list, ARRAY_SIZE(tlist), tlist);\n\tshort * tt = tlist;\n\twhile (*tt != REFRESH_EOL) {\n\t\tCELL newcell = cell + *tt++;\n\t\tif (In_Radar(newcell)) {\n\t\t\t(*this)[newcell].Redraw_Objects();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Cell_Shadow   -- Determine what shadow icon to use for the cell.              *\n *                                                                                             *\n *    This routine will examine the specified cell and adjacent cells to                       *\n *    determine what shadow icon to use.                                                       *\n *                                                                                             *\n * INPUT:   cell     -- The cell to examine.                                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the shadow icon to use. -2= all black.                                *\n *                                                -1= map cell.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/01/1994 JLB : Created.                                                                 *\n *   04/04/1994 JLB : Revamped for new shadow icon method.                                     *\n *   04/30/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nint DisplayClass::Cell_Shadow(CELL cell) const\n{\n\tstatic char const _shadow[256]={\n\t\t-1,33, 2, 2,34,37, 2, 2,\n\t\t 4,26, 6, 6, 4,26, 6, 6,\n\t\t35,45,17,17,38,41,17,17,\n\t\t 4,26, 6, 6, 4,26, 6, 6,\n\t\t 8,21,10,10,27,31,10,10,\n\t\t12,23,14,14,12,23,14,14,\n\t\t 8,21,10,10,27,31,10,10,\n\t\t12,23,14,14,12,23,14,14,\n\n\t\t32,36,25,25,44,40,25,25,\n\t\t19,30,20,20,19,30,20,20,\n\t\t39,43,29,29,42,46,29,29,\n\t\t19,30,20,20,19,30,20,20,\n\t\t 8,21,10,10,27,31,10,10,\n\t\t12,23,14,14,12,23,14,14,\n\t\t 8,21,10,10,27,31,10,10,\n\t\t12,23,14,14,12,23,14,14,\n\n\t\t 1, 1, 3, 3,16,16, 3, 3,\n\t\t 5, 5, 7, 7, 5, 5, 7, 7,\n\t\t24,24,18,18,28,28,18,18,\n\t\t 5, 5, 7, 7, 5, 5, 7, 7,\n\t\t 9, 9,11,11,22,22,11,11,\n\t\t13,13,-2,-2,13,13,-2,-2,\n\t\t 9, 9,11,11,22,22,11,11,\n\t\t13,13,-2,-2,13,13,-2,-2,\n\n\t\t 1, 1, 3, 3,16,16, 3, 3,\n\t\t 5, 5, 7, 7, 5, 5, 7, 7,\n\t\t24,24,18,18,28,28,18,18,\n\t\t 5, 5, 7, 7, 5, 5, 7, 7,\n\t\t 9, 9,11,11,22,22,11,11,\n\t\t13,13,-2,-2,13,13,-2,-2,\n\t\t 9, 9,11,11,22,22,11,11,\n\t\t13,13,-2,-2,13,13,-2,-2\n\t};\n\n\tint index = 0, value = -1;\n\n\t/*\n\t**\tDon't map cells that are at the top or bottom edge. This solves\n\t**\tproblem of accessing cells off the top or bottom of the map and into\n\t**\twho-knows-what memory.\n\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif ((unsigned)(Cell_Y(cell)-1) >= MAP_CELL_H-2) return(-1);\n#else\n\tif ((unsigned)(Cell_Y(cell)-1) > MAP_CELL_H-2) return(-1);\n#endif\n\t//if ((unsigned)(Cell_Y(cell)-1) > MAP_CELL_H-2) return(-2);\n\n\tCellClass const * cellptr = &(*this)[cell];\n\n\t/*\n\t**\tPresume solid black if that is what is here already.\n\t*/\n\tif (!cellptr->IsVisible && !cellptr->IsMapped) value = -2;\n\n\tif (cellptr->IsMapped /*&& !cellptr->IsVisible*/) {\n\t\t/*\n\t\t** Build an index into the lookup table using all 8 surrounding cells.\n\t\t** We're mapping a revealed cell and we only care about the existence\n\t\t** of black cells.  Bit numbering starts at the upper-right corner and\n\t\t** goes around the cell clockwise, so 0x80 = directly north.\n\t\t*/\n\t\tcellptr-= MAP_CELL_W + 1;\n\t\tif (!cellptr->IsMapped) index |= 0x40;\n\t\tcellptr++;\n\t\tif (!cellptr->IsMapped) index |= 0x80;\n\t\tcellptr++;\n\t\tif (!cellptr->IsMapped) index |= 0x01;\n\t\tcellptr += MAP_CELL_W - 2;\n\t\tif (!cellptr->IsMapped) index |= 0x20;\n\t\tcellptr += 2;\n\t\tif (!cellptr->IsMapped) index |= 0x02;\n\t\tcellptr += MAP_CELL_W - 2;\n\t\tif (!cellptr->IsMapped) index |= 0x10;\n\t\tcellptr++;\n\t\tif (!cellptr->IsMapped) index |= 0x08;\n\t\tcellptr++;\n\t\tif (!cellptr->IsMapped) index |= 0x04;\n\n\t\tvalue = _shadow[index];\n\t}\n\treturn(value);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Map_Cell -- Mark specified cell as having been mapped.                        *\n *                                                                                             *\n *    This routine maps the specified cell. The cell must not already                          *\n *    have been mapped and the mapping player must be the human.                               *\n *    This routine will update any adjacent cell map icon as appropriate.                      *\n *                                                                                             *\n * INPUT:   cell  -- The cell to be mapped.                                                    *\n *                                                                                             *\n *          house -- The player that is doing the mapping.                                     *\n *                                                                                             *\n * OUTPUT:  bool; Was action taken to map this cell?                                           *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1992 JLB : Created.                                                                 *\n *   04/30/1994 JLB : Converted to member function.                                            *\n *   05/24/1994 JLB : Takes pointer to HouseClass.                                             *\n *   02/20/1996 JLB : Allied units reveal the map for the player.                              *\n *=============================================================================================*/\nbool DisplayClass::Map_Cell(CELL cell, HouseClass * house)\n{\n\t/*\n\t** First check for the condition where we're spying on a house's radar\n\t** facility, to see if his mapping is applicable to us.\n\t*/\n\tif (house && house != PlayerPtr) {\n\t\tif (house->RadarSpied & (1<<(PlayerPtr->Class->House))) house = PlayerPtr;\n\t\tif (Session.Type == GAME_NORMAL && house->Is_Ally(PlayerPtr)) house = PlayerPtr;\n\t}\n\n\tif (house != PlayerPtr || !In_Radar(cell)) return(false);\n\n\tCellClass * cellptr = &(*this)[cell];\n\n\t/*\n\t**\tDon't bother remapping this cell if it is already mapped.\n\t*/\n\tif (cellptr->IsMapped) {\n\t\tif (!cellptr->IsVisible) {\n\t\t\tcellptr->Redraw_Objects();\n\t\t}\n\t\treturn(false);\n\t}\n\n\t/*\n\t** Mark the cell as being mapped. This must be done first because\n\t**\tif the IsVisible flag must be set, then it might affect the\n\t**\tadjacent cell processing.\n\t*/\n\tcellptr->IsMapped = true;\n\tcellptr->Redraw_Objects();\n\tif (Cell_Shadow(cell) == -1) {\n\t\tcellptr->IsVisible = true;\n\t}\n\n\t/*\n\t**\tCheck out all adjacent cells to see if they need\n\t**\tto be mapped as well. This is necessary because of the\n\t**\t\"unique\" method of showing shadowed cells. Many combinations\n\t**\tare not allowed, and to fix this, just map the cells until\n\t**\tall is ok.\n\t*/\n\tfor (FacingType dir = FACING_FIRST; dir < FACING_COUNT; dir++) {\n\t\tint\tshadow;\n\t\tCELL\tc;\n\n\t\tc = Adjacent_Cell(cell, dir);\n\t\tCellClass * cptr = &(*this)[c];\n\t\tcptr->Redraw_Objects();\n\n\t\tif (c != cell && !cptr->IsVisible) {\n\t\t\tshadow = Cell_Shadow(c);\n\n\t\t\tif (shadow == -1) {\n\t\t\t\tif (!cptr->IsMapped) {\n\t\t\t\t\tMap_Cell(c, house);\n\t\t\t\t} else {\n\t\t\t\t\tcptr->IsVisible = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (shadow != -2 && !cptr->IsMapped) {\n\t\t\t\t\tMap_Cell(c, house);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tTechnoClass * tech = (*this)[cell].Cell_Techno();\n\tif (tech) {\n\t\ttech->Revealed(house);\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Coord_To_Pixel -- Determines X and Y pixel coordinates.                       *\n *                                                                                             *\n *    This is the routine that figures out the location on the screen for                      *\n *    a specified coordinate. It is one of the fundamental routines                            *\n *    necessary for rendering the game objects. It performs some quick                         *\n *    tests to see if the coordinate is in a visible region and returns                        *\n *    this check as a boolean value.                                                           *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to check.                                                  *\n *                                                                                             *\n *          x,y   -- Reference to the pixel coordinates that this                              *\n *                   coordinate would be when rendered.                                        *\n *                                                                                             *\n * OUTPUT:  bool; Is this coordinate in a visible portion of the map?                          *\n *                                                                                             *\n * WARNINGS:   If the coordinate is not in a visible portion of the                            *\n *             map, then this X and Y parameters are not set.                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/14/1994 JLB : Created.                                                                 *\n *   12/15/1994 JLB : Converted to member function.                                            *\n *   01/07/1995 JLB : Uses inline functions to extract coord components.                       *\n *   08/09/1995 JLB : Uses new coordinate system.                                              *\n *=============================================================================================*/\n#define\tEDGE_ZONE\t(CELL_LEPTON_W*2)\nbool DisplayClass::Coord_To_Pixel(COORDINATE coord, int &x, int &y) const\n{\n\tif (coord) {\n\t\tint xtac = Pixel_To_Lepton(Lepton_To_Pixel(Coord_X(TacticalCoord)));\n\t\tint xoff = Pixel_To_Lepton(Lepton_To_Pixel(Coord_X(coord)));\n\n\t\txoff = (xoff+EDGE_ZONE) - xtac;\n\t\tif ((unsigned)xoff <= TacLeptonWidth + EDGE_ZONE*2) {\n\t\t\tint ytac = Pixel_To_Lepton(Lepton_To_Pixel(Coord_Y(TacticalCoord)));\n\t\t\tint yoff = Pixel_To_Lepton(Lepton_To_Pixel(Coord_Y(coord)));\n\n\t\t\tyoff = (yoff+EDGE_ZONE) - ytac;\n\t\t\tif ((unsigned)yoff <= TacLeptonHeight + EDGE_ZONE*2) {\n\t\t\t\tx = Lepton_To_Pixel(xoff)-CELL_PIXEL_W*2;\n\t\t\t\ty = Lepton_To_Pixel(yoff)-CELL_PIXEL_H*2;\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Push_Onto_TacMap -- Moves x & y coords to being on tactical map               *\n *                                                                                             *\n * This routine expects a line to be drawn between SOURCE & DEST, so it pushes the coords to   *\n * be within the region bounded by TacMapX,Y - + TacMapW,H.                                    *\n *                                                                                             *\n * INPUT:   source, dest -- References to the coordinates to check.                            *\n *                                                                                             *\n *                                                                                             *\n * OUTPUT:  bool; Are these coordinates in a visible portion of the map?                       *\n *                Returns true if the pushed source & dest are visible, but if neither are     *\n *                within the map, then it returns false.                                       *\n *                                                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/27/1995 BWG : Created.                                                                 *\n *=============================================================================================*/\nbool DisplayClass::Push_Onto_TacMap(COORDINATE & source, COORDINATE & dest)\n{\n\tif (!source || !dest) return(false);\n\n\tint x1 = Coord_X(source);\n\tint y1 = Coord_Y(source);\n\tint x2 = Coord_X(dest);\n\tint y2 = Coord_Y(dest);\n\tint left = Coord_X(TacticalCoord);\n\tint right = Coord_X(TacticalCoord) + TacLeptonWidth;\n\tint top = Coord_Y(TacticalCoord);\n\tint bottom = Coord_Y(TacticalCoord) + TacLeptonHeight;\n\n\tif (x1 < left && x2 < left) return(false);\n\tif (x1 > right && x2 > right) return(false);\n\tif (y1 < top && y2 < top) return(false);\n\tif (y1 > bottom && y2 > bottom) return(false);\n\n\tx1 = Bound(x1, left, right);\n\tx2 = Bound(x2, left, right);\n\ty1 = Bound(y1, top, bottom);\n\ty2 = Bound(y2, top, bottom);\n\n\tsource = XY_Coord(x1, y1);\n\tdest = XY_Coord(x2, y2);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Cell_Object -- Determines what has been clicked on.                           *\n *                                                                                             *\n *    This routine is used to determine what the player has clicked on.                        *\n *    It is passed the cell that the click was on and it then examines                         *\n *    the cell and returns with a pointer to the object that is there.                         *\n *                                                                                             *\n * INPUT:   cell  -- The cell that has been clicked upon.                                      *\n *                                                                                             *\n *          x,y   -- Optional offsets from the upper left corner of the cell to be used in     *\n *                   determining exactly which object in the cell is desired.                  *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the object that is \"clickable\" in                        *\n *          the specified cell.                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/14/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * DisplayClass::Cell_Object(CELL cell, int x, int y) const\n{\n\treturn(*this)[cell].Cell_Object(x, y);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Draw_It -- Draws the tactical map.                                            *\n *                                                                                             *\n *    This will draw the tactical map at the recorded position.   This                         *\n *    routine is used whenever the tactical map moves or needs to be                           *\n *    completely redrawn. It will handle making the necessary adjustments                      *\n *    to accomodate a moving cursor.                                                           *\n *                                                                                             *\n * INPUT:      forced   -- bool; force redraw of the entire display?                           *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/15/1991 JLB : Created. (benchmark = 292)                                               *\n *   04/15/1991 JLB : Added _cell2meta[] reference array (206)                                 *\n *   04/15/1991 JLB : Added actual map reference for terrain (207)                             *\n *   04/16/1991 JLB : _cell2meta converted to int (194)                                        *\n *   04/16/1991 JLB : References actual CellIcon[] array (204)                                 *\n *   04/16/1991 JLB : Cell size increased to 16 x 16 (167)                                     *\n *   04/17/1991 JLB : Cell based tactical map rendering (165)                                  *\n *   04/22/1991 JLB : Uses Draw_Stamp() for icon rendering (426)                               *\n *   04/22/1991 JLB : Draw_Stamp uses LogicPage now (276)                                      *\n *   04/23/1991 JLB : Map active location cursor (334)                                         *\n *   05/02/1991 JLB : Added smoothing and 3 icons sets (431)                                   *\n *   05/22/1991 JLB : Broken into Draw_Map() and Refresh_Map().                                *\n *   09/14/1991 JLB : Uses Refresh_Cell when new cells scroll onto display.                    *\n *   05/12/1992 JLB : Destination page support.                                                *\n *   02/14/1994 JLB : Revamped.                                                                *\n *   05/01/1994 JLB : Converted to member function.                                            *\n *   12/15/1994 JLB : Updated to work with display hierarchy.                                  *\n *   12/24/1994 JLB : Examines redraw bit intelligently.                                       *\n *   12/24/1994 JLB : Combined with old Refresh_Map() function.                                *\n *   01/10/1995 JLB : Rubber band drawing.                                                     *\n *=============================================================================================*/\n void DisplayClass::Draw_It(bool forced)\n{\n\tint\tx,y;\t\t\t// Working cell index values.\n\n\tMapClass::Draw_It(forced);\n\n\tif (IsToRedraw || forced) {\n\t\tBStart(BENCH_TACTICAL);\n\t\tIsToRedraw = false;\n\n\t\t/*\n\t\t**\tIn rubber band mode, mark all cells under the \"rubber band\" to be\n\t\t**\tredrawn.\n\t\t*/\n\t\tRefresh_Band();\n\n\t\t/*\n\t\t** Mark all cells under the vortex to be redrawn\n\t\t*/\n\t\tChronalVortex.Set_Redraw();\n\n\n\t\t/*\n\t\t** If the multiplayer message system is displaying one or more messages,\n\t\t** flag all cells covered by the messages to redraw.  This will prevent\n\t\t** messages from smearing the map if it scrolls.\n\t\t*/\n\t\tint num = Session.Messages.Num_Messages();\n\t\tif (num > 0) {\n\t\t\tfor (CELL cell = Coord_Cell(TacticalCoord); cell < Coord_Cell(TacticalCoord) + Lepton_To_Cell(TacLeptonWidth)+1; cell++) {\n\t\t\t\t(*this)[cell].Redraw_Objects();\n\t\t\t}\n\t\t\tfor (cell = Coord_Cell(TacticalCoord) + MAP_CELL_W;\n\t\t\t\tcell < Coord_Cell(TacticalCoord) + MAP_CELL_W + Lepton_To_Cell(TacLeptonWidth)+1; cell++) {\n\t\t\t\t(*this)[cell].Redraw_Objects();\n\t\t\t}\n\t\t\tif (num > 1) {\n\t\t\t\tfor (cell = Coord_Cell(TacticalCoord) + MAP_CELL_W*2;\n\t\t\t\t\tcell < Coord_Cell(TacticalCoord) + MAP_CELL_W*2 + Lepton_To_Cell(TacLeptonWidth)+1; cell++) {\n\t\t\t\t\t(*this)[cell].Redraw_Objects();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (num > 2) {\n\t\t\t\tfor (cell = Coord_Cell(TacticalCoord) + MAP_CELL_W*3;\n\t\t\t\t\tcell < Coord_Cell(TacticalCoord) + MAP_CELL_W*3 + Lepton_To_Cell(TacLeptonWidth)+1; cell++) {\n\t\t\t\t\t(*this)[cell].Redraw_Objects();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (num > 3) {\n\t\t\t\tfor (cell = Coord_Cell(TacticalCoord) + MAP_CELL_W*4;\n\t\t\t\t\tcell < Coord_Cell(TacticalCoord) + MAP_CELL_W*4 + Lepton_To_Cell(TacLeptonWidth)+1; cell++) {\n\t\t\t\t\t(*this)[cell].Redraw_Objects();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tCheck for a movement of the tactical map. If there has been some\n\t\t**\tmovement, then part (or all) of the icons must be redrawn.\n\t\t*/\n\t\tif (Lepton_To_Pixel(Coord_X(DesiredTacticalCoord)) != Lepton_To_Pixel(Coord_X(TacticalCoord)) ||\n\t\t\tLepton_To_Pixel(Coord_Y(DesiredTacticalCoord)) != Lepton_To_Pixel(Coord_Y(TacticalCoord))) {\n\n\t\t\tint xmod = Lepton_To_Pixel(Coord_X(DesiredTacticalCoord));\n\t\t\tint ymod = Lepton_To_Pixel(Coord_Y(DesiredTacticalCoord));\n\n\t\t\tint oldx = Lepton_To_Pixel(Coord_X(TacticalCoord))-xmod;\t\t// Old relative offset.\n\t\t\tint oldy = Lepton_To_Pixel(Coord_Y(TacticalCoord))-ymod;\n\n\t\t\tint oldw = Lepton_To_Pixel(TacLeptonWidth)-ABS(oldx);\t\t\t// Replicable width.\n\t\t\tint oldh = Lepton_To_Pixel(TacLeptonHeight)-ABS(oldy);\t\t// Replicable height.\n\n\t\t\tif (oldw < 1) forced = true;\n\t\t\tif (oldh < 1) forced = true;\n\n\n#ifdef WIN32\t\t//For WIN32 only redraw the edges of the map that move into view\n\n\t\t\t/*\n\t\t\t** Work out which map edges need to be redrawn\n\t\t\t*/\n\t\t\tBOOL redraw_right = (oldx < 0) ? true : false;\t\t//Right hand edge\n\t\t\tBOOL redraw_left  = (oldx > 0) ? true : false;\t\t//Left hand edge\n\t\t\tBOOL redraw_bottom= (oldy < 0) ? true : false;\t\t//Bottom edge\n\t\t\tBOOL redraw_top\t= (oldy > 0) ? true : false;\t\t//Top edge\n\n\t\t\t/*\n\t\t\t**\tBlit any replicable block to avoid having to drawstamp.\n\t\t\t*/\n\t\t\tif (!forced && (oldw != Lepton_To_Pixel(TacLeptonWidth) || oldh != Lepton_To_Pixel(TacLeptonHeight))) {\n\t\t\t\tSet_Cursor_Pos(-1);\n\n\t\t\t\t/*\n\t\t\t\t** If hid page is in video memory then blit from the seen page to avoid blitting\n\t\t\t\t**  an overlapped region.\n\t\t\t\t*/\n\t\t\t\tif (HidPage.Get_IsDirectDraw()) {\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\t\t\tSeenBuff.Blit(HidPage,\n\t\t\t\t\t\t\t\t\t((oldx < 0) ? -oldx : 0) +TacPixelX,\n\t\t\t\t\t\t\t\t\t((oldy < 0) ? -oldy : 0) +TacPixelY,\n\t\t\t\t\t\t\t\t\t((oldx < 0) ? 0 : oldx) +TacPixelX,\n\t\t\t\t\t\t\t\t\t((oldy < 0) ? 0 : oldy) +TacPixelY,\n\t\t\t\t\t\t\t\t\toldw,\n\t\t\t\t\t\t\t\t\toldh);\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t} else {\n\t\t\t\t\tHidPage.Blit(HidPage,\n\t\t\t\t\t\t\t\t\t((oldx < 0) ? -oldx : 0) +TacPixelX,\n\t\t\t\t\t\t\t\t\t((oldy < 0) ? -oldy : 0) +TacPixelY,\n\t\t\t\t\t\t\t\t\t((oldx < 0) ? 0 : oldx) +TacPixelX,\n\t\t\t\t\t\t\t\t\t((oldy < 0) ? 0 : oldy) +TacPixelY,\n\t\t\t\t\t\t\t\t\toldw,\n\t\t\t\t\t\t\t\t\toldh);\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tforced = true;\n\t\t\t}\n\n\t\t\tif (oldx < 0) oldx = 0;\n\t\t\tif (oldy < 0) oldy = 0;\n\n\t\t\t/*\n\t\t\t** Record new map position for future reference.\n\t\t\t*/\n\t\t\tScenarioInit++;\n\t\t\tSet_Tactical_Position(DesiredTacticalCoord);\n\t\t\tScenarioInit--;\n\n\t\t\tif (!forced) {\n\n\t\t\t\t/*\n\t\t\t\t**\n\t\t\t\t**\tSet the 'redraw stamp' bit for any cells that could not be copied.\n\t\t\t\t**\n\t\t\t\t*/\n\t\t\t\tint startx = -Lepton_To_Pixel(Coord_XLepton(TacticalCoord));\n\t\t\t\tint starty = -Lepton_To_Pixel(Coord_YLepton(TacticalCoord));\n\t\t\t\toldw -= 24;\n\t\t\t\toldh -= 24;\n\n\t\t\t\tif (abs(oldx) < 0x25 && abs(oldy) < 0x25) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** The width of the area we redraw depends on the scroll speed\n\t\t\t\t\t*/\n\t\t\t\t\tint extra_x = (abs(oldx)>=16) ? 2 : 1;\n\t\t\t\t\tint extra_y = (abs(oldy)>=16) ? 2 : 1;\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Flag the cells across the top of the visible area if required\n\t\t\t\t\t*/\n\t\t\t\t\tif (redraw_top) {\n\t\t\t\t\t\tfor (y = starty; y <= starty+CELL_PIXEL_H*extra_y; y += CELL_PIXEL_H) {\n\t\t\t\t\t\t\tfor (x = startx; x <= Lepton_To_Pixel(TacLeptonWidth)+((CELL_PIXEL_W*2)); x += CELL_PIXEL_W) {\n\t\t\t\t\t\t\t\tCELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,\n\t\t\t\t\t\t\t\t\t\t\tBound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);\n\n\t\t\t\t\t\t\t\tif (c > 0) (*this)[c].Redraw_Objects(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Flag the cells across the bottom of the visible area if required\n\t\t\t\t\t*/\n\t\t\t\t\tif (redraw_bottom) {\n\t\t\t\t\t\tfor (y = Lepton_To_Pixel(TacLeptonHeight)-CELL_PIXEL_H*(1+extra_y); y <= Lepton_To_Pixel(TacLeptonHeight)+CELL_PIXEL_H*3; y += CELL_PIXEL_H) {\n\t\t\t\t\t\t\tfor (x = startx; x <= Lepton_To_Pixel(TacLeptonWidth)+((CELL_PIXEL_W*2)); x += CELL_PIXEL_W) {\n\t\t\t\t\t\t\t\tCELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,\n\t\t\t\t\t\t\t\t\t\t\tBound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);\n\n\t\t\t\t\t\t\t\tif (c > 0) (*this)[c].Redraw_Objects(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Flag the cells down the left of the visible area if required\n\t\t\t\t\t*/\n\t\t\t\t\tif (redraw_left) {\n\t\t\t\t\t\tfor (x = startx; x <= startx + CELL_PIXEL_W*extra_x; x += CELL_PIXEL_W) {\n\t\t\t\t\t\t\tfor (y = starty; y <= Lepton_To_Pixel(TacLeptonHeight)+((CELL_PIXEL_H*2)); y += CELL_PIXEL_H) {\n\t\t\t\t\t\t\t\tCELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,\n\t\t\t\t\t\t\t\t\t\t\tBound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);\n\n\t\t\t\t\t\t\t\tif (c > 0) (*this)[c].Redraw_Objects(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Flag the cells down the right of the visible area if required\n\t\t\t\t\t*/\n\t\t\t\t\tif (redraw_right) {\n\t\t\t\t\t\tfor (x = Lepton_To_Pixel(TacLeptonWidth)-CELL_PIXEL_W*(extra_x+1); x <= Lepton_To_Pixel(TacLeptonWidth)+CELL_PIXEL_W*3; x += CELL_PIXEL_W) {\n\t\t\t\t\t\t\tfor (y = starty; y <= Lepton_To_Pixel(TacLeptonHeight)+((CELL_PIXEL_H*2)); y += CELL_PIXEL_H) {\n\t\t\t\t\t\t\t\tCELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,\n\t\t\t\t\t\t\t\t\t\t\tBound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);\n\n\t\t\t\t\t\t\t\tif (c > 0) (*this)[c].Redraw_Objects(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSet the 'redraw stamp' bit for any cells that could not be copied.\n\t\t\t\t\t*/\n\t\t\t\t\tint startx = -Lepton_To_Pixel(Coord_XLepton(TacticalCoord));\n\t\t\t\t\tint starty = -Lepton_To_Pixel(Coord_YLepton(TacticalCoord));\n\t\t\t\t\toldw -= 24;\n\t\t\t\t\toldh -= 24;\n\t\t\t\t\tfor (y = starty; y <= Lepton_To_Pixel(TacLeptonHeight)+((CELL_PIXEL_H*2)); y += CELL_PIXEL_H) {\n\t\t\t\t\t\tfor (x = startx; x <= Lepton_To_Pixel(TacLeptonWidth)+((CELL_PIXEL_W*2)); x += CELL_PIXEL_W) {\n\t\t\t\t\t\t\tif (x <= oldx || x >= oldx+oldw || y <= oldy || y >= oldy+oldh) {\n\t\t\t\t\t\t\t\tCELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,\n\t\t\t\t\t\t\t\t\t\t\tBound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);\n\n\t\t\t\t\t\t\t\tif (c > 0) {\n\t\t\t\t\t\t\t\t\t(*this)[c].Redraw_Objects(true);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tSet the tactical coordinate just in case the desired tactical has changed but\n\t\t\t**\tnot enough to result in any visible map change. This is likely to occur with very\n\t\t\t**\tslow scroll rates.\n\t\t\t*/\n\t\t\tScenarioInit++;\n\t\t\tif (DesiredTacticalCoord != TacticalCoord) {\n\t\t\t\tSet_Tactical_Position(DesiredTacticalCoord);\n\t\t\t}\n\t\t\tScenarioInit--;\n\t\t}\n\n\n#else\t//WIN32\n\t\t\t/*\n\t\t\t**\tBlit any replicable block to avoid having to drawstamp.\n\t\t\t*/\n\t\t\tif (!forced && (oldw != Lepton_To_Pixel(TacLeptonWidth) || oldh != Lepton_To_Pixel(TacLeptonHeight))) {\n\t\t\t\tSet_Cursor_Pos(-1);\n\n\t\t\t\tHidPage.Blit(HidPage,\n\t\t\t\t\t\t\t\t((oldx < 0) ? -oldx : 0) +TacPixelX,\n\t\t\t\t\t\t\t\t((oldy < 0) ? -oldy : 0) +TacPixelY,\n\t\t\t\t\t\t\t\t((oldx < 0) ? 0 : oldx) +TacPixelX,\n\t\t\t\t\t\t\t\t((oldy < 0) ? 0 : oldy) +TacPixelY,\n\t\t\t\t\t\t\t\toldw,\n\t\t\t\t\t\t\t\toldh);\n\t\t\t} else {\n\t\t\t\tforced = true;\n\t\t\t}\n\n\t\t\tif (oldx < 0) oldx = 0;\n\t\t\tif (oldy < 0) oldy = 0;\n\n\t\t\t/*\n\t\t\t** Record new map position for future reference.\n\t\t\t*/\n\t\t\tScenarioInit++;\n\t\t\tSet_Tactical_Position(DesiredTacticalCoord);\n\t\t\tScenarioInit--;\n\n\t\t\tif (!forced) {\n\n\t\t\t\t/*\n\t\t\t\t**\tSet the 'redraw stamp' bit for any cells that could not be copied.\n\t\t\t\t*/\n\t\t\t\tint startx = -Lepton_To_Pixel(Coord_XLepton(TacticalCoord));\n\t\t\t\tint starty = -Lepton_To_Pixel(Coord_YLepton(TacticalCoord));\n\t\t\t\toldw -= 24;\n\t\t\t\toldh -= 24;\n\t\t\t\tfor (y = starty; y <= Lepton_To_Pixel(TacLeptonHeight)+((CELL_PIXEL_H*2)); y += CELL_PIXEL_H) {\n\t\t\t\t\tfor (x = startx; x <= Lepton_To_Pixel(TacLeptonWidth)+((CELL_PIXEL_W*2)); x += CELL_PIXEL_W) {\n\t\t\t\t\t\tif (x <= oldx || x >= oldx+oldw || y <= oldy || y >= oldy+oldh) {\n\t\t\t\t\t\t\tCELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,\n\t\t\t\t\t\t\t\t\t\tBound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);\n\n\t\t\t\t\t\t\tif (c > 0) {\n\t\t\t\t\t\t\t\t(*this)[c].Redraw_Objects(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tSet the tactical coordinate just in case the desired tactical has changed but\n\t\t\t**\tnot enough to result in any visible map change. This is likely to occur with very\n\t\t\t**\tslow scroll rates.\n\t\t\t*/\n\t\t\tScenarioInit++;\n\t\t\tif (DesiredTacticalCoord != TacticalCoord) {\n\t\t\t\tSet_Tactical_Position(DesiredTacticalCoord);\n\t\t\t}\n\t\t\tScenarioInit--;\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tIf the entire tactical map is forced to be redrawn, then set all the redraw flags\n\t\t**\tand let the normal processing take care of the rest.\n\t\t*/\n\t\tif (forced) {\n\t\t\tCellRedraw.Set();\n\t\t}\n\n\t\t/*\n\t\t**\tThe first order of business is to redraw all the underlying icons that are\n\t\t**\tflagged to be redrawn.\n\t\t*/\n\t\tif (HidPage.Lock()) {\n\t\t\tRedraw_Icons();\n\n\t\t\t/*\n\t\t\t**\tDraw the infantry bodies in this special layer.\n\t\t\t*/\n//\t\t\tfor (int index = 0; index < Anims.Count(); index++) {\n//\t\t\t\tAnimClass * anim = Anims.Ptr(index);\n//\t\t\t\tif (*anim >= ANIM_CORPSE1 && *anim <= ANIM_CORPSE3) {\n//\t\t\t\t\tanim->Render(forced);\n//\t\t\t\t}\n//\t\t\t}\n\n#ifdef SORTDRAW\n\t\t\tRedraw_OIcons();\n#endif\n\n\t\t\tHidPage.Unlock();\n\t\t}\n\n#ifndef WIN32\n\t\t/*\n\t\t**\tOnce the icons are drawn, duplicate the bottom line of the screen into the phantom\n\t\t**\tarea one line below the screen. This causes the predator effect to work on any\n\t\t**\tshape drawn at the bottom of the screen.\n\t\t*/\n\t\tHidPage.Blit(HidPage, 0, HidPage.Get_Height()-1, 0, HidPage.Get_Height(), HidPage.Get_Width(), 1, false);\n#endif\n\n\t\tif (HidPage.Lock()) {\n\n\t\t\t/*\n\t\t\t** Draw the vortex effect over the terrain\n\t\t\t*/\n\t\t\tChronalVortex.Render();\n\n\t\t\t/*\n\t\t\t**\tRedraw the game objects layer by layer. The layer drawing occurs on the ground layer\n\t\t\t**\tfirst and then followed by all the layers in increasing altitude.\n\t\t\t*/\n\t\t\tBStart(BENCH_OBJECTS);\n\t\t\tfor (LayerType layer = LAYER_FIRST; layer < LAYER_COUNT; layer++) {\n\t\t\t\tfor (int index = 0; index < Layer[layer].Count(); index++) {\n\t\t\t\t\tObjectClass * ptr = Layer[layer][index];\n\n#ifdef SORTDRAW\n\t\t\t\t\t/*\n\t\t\t\t\t**\tTechno objects are drawn as part of the cell redraw process since techno\n\t\t\t\t\t**\tobjects in the ground layer are handled by the Occupier and Overlapper\n\t\t\t\t\t**\tpointer lists.\n\t\t\t\t\t*/\n\t\t\t\t\tif (!Debug_Map && ptr->Is_Techno() && layer == LAYER_GROUND && ((TechnoClass*)ptr)->Visual_Character() == VISUAL_NORMAL) continue;\n#endif\n\n//\t\t\t\t\tif (ptr->What_Am_I() == RTTI_ANIM && *((AnimClass*)ptr) >= ANIM_CORPSE1 && *((AnimClass*)ptr) <= ANIM_CORPSE3) {\n//\t\t\t\t\t\tcontinue;\n//\t\t\t\t\t}\n\t\t\t\t\tassert(ptr->IsActive);\n\t\t\t\t\tptr->Render(forced);\n\t\t\t\t}\n\t\t\t}\n\t\t\tBEnd(BENCH_OBJECTS);\n\n\t//ChronalVortex.Render();\n\t\t\t/*\n\t\t\t**\tFinally, redraw the shadow overlay as necessary.\n\t\t\t*/\n\t\t\tBStart(BENCH_SHROUD);\n\t\t\tRedraw_Shadow();\n\t\t\tBEnd(BENCH_SHROUD);\n\t\t}\n\t\tHidPage.Unlock();\n\n#ifdef SORTDRAW\n\t\tfor (int index = 0; index < Layer[LAYER_GROUND].Count(); index++) {\n\t\t\tLayer[LAYER_GROUND][index]->IsToDisplay = false;\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tDraw the rubber band over the top of it all.\n\t\t*/\n\t\tif (IsRubberBand) {\n\t\t\tLogicPage->Draw_Rect(BandX+TacPixelX, BandY+TacPixelY, NewX+TacPixelX, NewY+TacPixelY, WHITE);\n\t\t}\n\n\t\t/*\n\t\t**\tClear the redraw flags so that normal redraw flag setting can resume.\n\t\t*/\n\t\tCellRedraw.Reset();\n\n#ifdef SCENARIO_EDITOR\n\t\t/*\n\t\t**\tIf we're placing an object (PendingObject is non-NULL), and that object\n\t\t**\tis NOT an icon, smudge, or overlay, draw it here.\n\t\t**\tTerrain, Buildings & Aircraft aren't drawn at the cell's center coord;\n\t\t**\tthey're drawn at the upper left coord, so I have to AND the coord value\n\t\t**\twith 0xFF00FF00 to strip off the lepton coordinates, but leave the\n\t\t**\tcell coordinates.\n\t\t*/\n\t\tif (Debug_Map && PendingObjectPtr) {\n\t\t\tPendingObjectPtr->Coord = PendingObjectPtr->Class_Of().Coord_Fixup(Cell_Coord(ZoneCell + ZoneOffset));\n\t\t\tPendingObjectPtr->Render(true);\n\t\t}\n#endif\n\t\tBEnd(BENCH_TACTICAL);\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Redraw_Icons -- Draws all terrain icons necessary.                            *\n *                                                                                             *\n *    This routine will redraw all of the terrain icons that are flagged                       *\n *    to be redrawn.                                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1994 JLB : Created.                                                                 *\n *   05/01/1994 JLB : Converted to member function.                                            *\n *   06/20/1994 JLB : Uses cell drawing support function.                                      *\n *   12/06/1994 JLB : Scans tactical view in separate row/column loops                         *\n *   12/24/1994 JLB : Uses the cell bit flag array to determine what to redraw.                *\n *=============================================================================================*/\nvoid DisplayClass::Redraw_Icons(void)\n{\n\tIsShadowPresent = false;\n\tfor (int y = -Coord_YLepton(TacticalCoord); y <= TacLeptonHeight; y += CELL_LEPTON_H) {\n\t\tfor (int x = -Coord_XLepton(TacticalCoord); x <= TacLeptonWidth; x += CELL_LEPTON_W) {\n\t\t\tCOORDINATE coord = Coord_Add(TacticalCoord, XY_Coord(x, y));\n\t\t\tCELL cell = Coord_Cell(coord);\n\t\t\tcoord = Coord_Whole(Cell_Coord(cell));\n\n\t\t\t/*\n\t\t\t**\tOnly cells flagged to be redraw are examined.\n\t\t\t*/\n\t\t\tif (In_View(cell) && Is_Cell_Flagged(cell)) {\n\t\t\t\tint xpixel;\n\t\t\t\tint ypixel;\n\n\t\t\t\tif (Coord_To_Pixel(coord, xpixel, ypixel)) {\n\t\t\t\t\tCellClass * cellptr = &(*this)[coord];\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf there is a portion of the underlying icon that could be visible,\n\t\t\t\t\t**\tthen draw it.  Also draw the cell if the shroud is off.\n\t\t\t\t\t*/\n\t\t\t\t\tif (cellptr->IsMapped || Debug_Unshroud) {\n\t\t\t\t\t\tcellptr->Draw_It(xpixel, ypixel);\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf any cell is not fully mapped, then flag it so that the shadow drawing\n\t\t\t\t\t**\tprocess will occur.  Only draw the shadow if Debug_Unshroud is false.\n\t\t\t\t\t*/\n\t\t\t\t\tif (!cellptr->IsVisible && !Debug_Unshroud) {\n\t\t\t\t\t\tIsShadowPresent = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n#ifdef SORTDRAW\nvoid DisplayClass::Redraw_OIcons(void)\n{\n\tfor (int y = -Coord_YLepton(TacticalCoord); y <= TacLeptonHeight; y += CELL_LEPTON_H) {\n\t\tfor (int x = -Coord_XLepton(TacticalCoord); x <= TacLeptonWidth; x += CELL_LEPTON_W) {\n\t\t\tCOORDINATE coord = Coord_Add(TacticalCoord, XY_Coord(x, y));\n\t\t\tCELL cell = Coord_Cell(coord);\n\t\t\tcoord = Coord_Whole(Cell_Coord(cell));\n\n\t\t\t/*\n\t\t\t**\tOnly cells flagged to be redraw are examined.\n\t\t\t*/\n\t\t\tif (In_View(cell) && Is_Cell_Flagged(cell)) {\n\t\t\t\tint xpixel;\n\t\t\t\tint ypixel;\n\n\t\t\t\tif (Coord_To_Pixel(coord, xpixel, ypixel)) {\n\t\t\t\t\tCellClass * cellptr = &(*this)[coord];\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf there is a portion of the underlying icon that could be visible,\n\t\t\t\t\t**\tthen draw it.  Also draw the cell if the shroud is off.\n\t\t\t\t\t*/\n\t\t\t\t\tif (cellptr->IsMapped || Debug_Unshroud) {\n\t\t\t\t\t\tcellptr->Draw_It(xpixel, ypixel, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * DisplayClass::Redraw_Shadow -- Draw the shadow overlay.                                     *\n *                                                                                             *\n *    This routine is called after all other tactical map rendering takes place. It draws      *\n *    the shadow map over the tactical map.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/01/1995 JLB : Created.                                                                 *\n *   08/06/1995 JLB : Clips the fill rect if necessary.                                        *\n *=============================================================================================*/\nvoid DisplayClass::Redraw_Shadow(void)\n{\n\tif (IsShadowPresent) {\n\t\tfor (int y = -Coord_YLepton(TacticalCoord); y <= TacLeptonHeight; y += CELL_LEPTON_H) {\n\t\t\tfor (int x = -Coord_XLepton(TacticalCoord); x <= TacLeptonWidth; x += CELL_LEPTON_W) {\n\t\t\t\tCOORDINATE coord = Coord_Add(TacticalCoord, XY_Coord(x, y));\n\t\t\t\tCELL cell = Coord_Cell(coord);\n\t\t\t\tcoord = Coord_Whole(Cell_Coord(cell));\n\n\t\t\t\t/*\n\t\t\t\t**\tOnly cells flagged to be redrawn are examined.\n\t\t\t\t*/\n\t\t\t\tif (In_View(cell) && Is_Cell_Flagged(cell)) {\n\t\t\t\t\tint xpixel;\n\t\t\t\t\tint ypixel;\n\n\t\t\t\t\tif (Coord_To_Pixel(coord, xpixel, ypixel)) {\n\t\t\t\t\t\tCellClass * cellptr = &(*this)[coord];\n\t\t\t\t\t\tif (cellptr->IsVisible) continue;\n\t\t\t\t\t\tint shadow = -2;\n\t\t\t\t\t\tif (cellptr->IsMapped) {\n\t\t\t\t\t\t\tshadow = Cell_Shadow(cell);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (shadow >= 0) {\n\t\t\t\t\t\t\tCC_Draw_Shape(ShadowShapes, shadow, xpixel, ypixel, WINDOW_TACTICAL, SHAPE_GHOST, NULL, ShadowTrans);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (shadow != -1) {\n\t\t\t\t\t\t\t\tint ww = CELL_PIXEL_W;\n\t\t\t\t\t\t\t\tint hh = CELL_PIXEL_H;\n\n\t\t\t\t\t\t\t\tif (Clip_Rect(&xpixel, &ypixel, &ww, &hh, Lepton_To_Pixel(TacLeptonWidth), Lepton_To_Pixel(TacLeptonHeight)) >= 0) {\n\t\t\t\t\t\t\t\t\tLogicPage->Fill_Rect(TacPixelX+xpixel, TacPixelY+ypixel, TacPixelX+xpixel+ww-1, TacPixelY+ypixel+hh-1, BLACK);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Next_Object -- Searches for next object on display.                           *\n *                                                                                             *\n *    This utility routine is used to find the \"next\" object from the object specified. This   *\n *    is typically used when <TAB> is pressed and the current object shifts.                   *\n *                                                                                             *\n * INPUT:   object   -- The current object to base the \"next\" calculation off of.              *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the next object. If there is no objects available,       *\n *          then NULL is returned.                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * DisplayClass::Next_Object(ObjectClass * object) const\n{\n\tObjectClass * firstobj = NULL;\n\tbool foundmatch = false;\n\n\tif (object == NULL) {\n\t\tfoundmatch = true;\n\t}\n\tfor (unsigned uindex = 0; uindex < Layer[LAYER_GROUND].Count(); uindex++) {\n\t\tObjectClass * obj = Layer[LAYER_GROUND][uindex];\n\n\t\t/*\n\t\t**\tVerify that the object can be selected by and is owned by the player.\n\t\t*/\n\t\tif (obj != NULL && obj->Is_Players_Army()) {\n\t\t\tif (firstobj == NULL) firstobj = obj;\n\t\t\tif (foundmatch) return(obj);\n\t\t\tif (object == obj) foundmatch = true;\n\t\t}\n\t}\n\treturn(firstobj);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Prev_Object -- Searches for the previous object on the map.                   *\n *                                                                                             *\n *    This routine will search for the previous object. Previous is defined as the one listed  *\n *    before the specified object in the ground layer. If there is no specified object, then   *\n *    the last object in the ground layer is returned.                                         *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that \"previous\" is to be defined from.           *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the object previous to the specified one.                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * DisplayClass::Prev_Object(ObjectClass * object)  const\n{\n\tObjectClass * firstobj = NULL;\n\tbool foundmatch = false;\n\n\tif (object == NULL) {\n\t\tfoundmatch = true;\n\t}\n\tfor (int uindex = Layer[LAYER_GROUND].Count()-1; uindex >= 0; uindex--) {\n\t\tObjectClass * obj = Layer[LAYER_GROUND][uindex];\n\n\t\t/*\n\t\t**\tVerify that the object can be selected by and is owned by the player.\n\t\t*/\n\t\tif (obj != NULL && obj->Is_Players_Army()) {\n\t\t\tif (firstobj == NULL) firstobj = obj;\n\t\t\tif (foundmatch) return(obj);\n\t\t\tif (object == obj) foundmatch = true;\n\t\t}\n\t}\n\n\treturn(firstobj);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Pixel_To_Coord -- converts screen coord to COORDINATE                         *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      x,y      pixel coordinates to convert                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      COORDINATE of pixel                                                                    *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/09/1994 BR : Created.                                                                  *\n *   12/06/1994 JLB : Uses map dimension variables in display class.                           *\n *   12/10/1994 JLB : Uses union to speed building coordinate value.                           *\n *=============================================================================================*/\nCOORDINATE DisplayClass::Pixel_To_Coord(int x, int y) const\n{\n\t/*\n\t**\tNormalize the pixel coordinates to be relative to the upper left corner\n\t**\tof the tactical map. The coordinates are expressed in leptons.\n\t*/\n\tx -= TacPixelX;\n\tx = Pixel_To_Lepton(x);\n\ty -= TacPixelY;\n\ty = Pixel_To_Lepton(y);\n\n\t/*\n\t**\tIf pixel coordinate is over the tactical map, then translate it into a coordinate\n\t**\tvalue. If not, then just return with NULL.\n\t*/\n\tif ((unsigned)x < TacLeptonWidth && (unsigned)y < TacLeptonHeight) {\n\t\treturn(Coord_Add(TacticalCoord, XY_Coord(x, y)));\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Calculated_Cell -- Fetch a map cell based on specified method.                *\n *                                                                                             *\n *    Find a cell meeting the specified requirements. This function is                         *\n *    used for scenario reinforcements.                                                        *\n *                                                                                             *\n * INPUT:   dir   -- Method of picking a map cell.                                             *\n *                                                                                             *\n *          waypoint -- Closest waypoint to use for finding appropriate map edge.              *\n *                                                                                             *\n *          cell  -- Cell to find closest edge to if waypoint not specified.                   *\n *                                                                                             *\n *          loco  -- The locomotion of the reinforcements that are trying to enter.            *\n *                                                                                             *\n *          zonecheck   -- Is zone checking required?                                          *\n *                                                                                             *\n *          mzone    -- The movement zone type to check against (only if zone checking).       *\n *                                                                                             *\n * OUTPUT:  Returns with the calculated cell. If 0, then this indicates                        *\n *          that no legal cell was found.                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *   04/11/1994 JLB : Revamped.                                                                *\n *   05/18/1994 JLB : Converted to member function.                                            *\n *   12/18/1995 JLB : Handles edge preference scan.                                            *\n *   06/24/1996 JLB : Removed Dune II legacy code.                                             *\n *   06/25/1996 JLB : Rewrote and greatly simplified.                                          *\n *   10/05/1996 JLB : Checks for zone and crushable status.                                    *\n *=============================================================================================*/\nCELL DisplayClass::Calculated_Cell(SourceType dir, WAYPOINT waypoint, CELL cell, SpeedType loco, bool zonecheck, MZoneType mzone) const\n{\n\tbool vert = false;\n\tbool horz = false;\n\tint x = 0;\n\tint y = 0;\n\tCELL punt = 0;\t\t\t// If all else fails, return this cell location.\n\tint zone = -1;\t\t\t// Tentative zone for legality checking.\n\n\t/*\n\t**\tWaypoint edge detection for ground based reinforcements that have a waypoint origin are\n\t**\tdetermined by finding the closest map edge to the waypoint. Reinforcement location\n\t**\tscanning starts from that position.\n\t*/\n\tCELL trycell = -1;\n\tif (waypoint != -1) {\n\t\ttrycell = Scen.Waypoint[waypoint];\n\t}\n\tif (trycell == -1) {\n\t\ttrycell = cell;\n\t}\n\n\t/*\n\t**\tIf zone checking is requested, then find the correct zone to use.\n\t*/\n\tif (zonecheck && trycell != -1) {\n\t\tzone = (*this)[trycell].Zones[mzone];\n\t}\n\n\t/*\n\t**\tIf the cell or waypoint specified as been detected as legal, then set up the map edge\n\t**\tscanning values accordingly.\n\t*/\n\tif (trycell != -1) {\n\t\tx = Cell_X(trycell) - MapCellX;\n\t\tx = min(x, (-Cell_X(trycell) + (MapCellX+MapCellWidth)));\n\n\t\ty = Cell_Y(trycell) - MapCellY;\n\t\ty = min(y, (-Cell_Y(trycell) + (MapCellY+MapCellHeight)));\n\n\t\tif (x < y) {\n\t\t\tvert = true;\n\t\t\thorz = false;\n\t\t\tif ((Cell_X(trycell)-MapCellX) < MapCellWidth/2) {\n\t\t\t\tx = -1;\n\t\t\t} else {\n\t\t\t\tx = MapCellWidth;\n\t\t\t}\n\t\t\ty = Cell_Y(trycell) - MapCellY;\n\n\t\t} else {\n\n\t\t\tvert = false;\n\t\t\thorz = true;\n\t\t\tif ((Cell_Y(trycell)-MapCellY) < MapCellHeight/2) {\n\t\t\t\ty = -1;\n\t\t\t} else {\n\t\t\t\ty = MapCellHeight;\n\t\t\t}\n\t\t\tx = Cell_X(trycell) - MapCellX;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf no map edge can be inferred from the waypoint, then go with the\n\t**\tmap edge specified by the edge parameter.\n\t*/\n\tif (!vert && !horz) {\n\t\tswitch (dir) {\n\t\t\tdefault:\n\t\t\tcase SOURCE_NORTH:\n\t\t\t\thorz = true;\n\t\t\t\ty = -1;\n\t\t\t\tx = Random_Pick(0, MapCellWidth-1);\n\t\t\t\tbreak;\n\n\t\t\tcase SOURCE_SOUTH:\n\t\t\t\thorz = true;\n\t\t\t\ty = MapCellHeight;\n\t\t\t\tx = Random_Pick(0, MapCellWidth-1);\n\t\t\t\tbreak;\n\n\t\t\tcase SOURCE_EAST:\n\t\t\t\tvert = true;\n\t\t\t\tx = MapCellWidth;\n\t\t\t\ty = Random_Pick(0, MapCellHeight-1);\n\t\t\t\tbreak;\n\n\t\t\tcase SOURCE_WEST:\n\t\t\t\tvert = true;\n\t\t\t\tx = -1;\n\t\t\t\ty = Random_Pick(0, MapCellHeight-1);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tDetermine the default reinforcement cell if all else fails.\n\t*/\n\tpunt = XY_Cell(x + MapCellX, y + MapCellY);\n\n\t/*\n\t**\tScan through the vertical and horizontal edges of the map looking for\n\t**\ta relatively clear cell for object placement. The cell scanned is\n\t**\tfrom the edge position specified by the X and Y variables.\n\t*/\n\tif (vert) {\n\t\tint modifier = (x > MapCellX) ? -1 : 1;\n\n\t\tfor (int index = 0; index < MapCellHeight; index++) {\n\t\t\tCELL trycell = XY_Cell(x + MapCellX, ((y + index) % MapCellHeight) + MapCellY);\n\n\t\t\tif (Good_Reinforcement_Cell(trycell, trycell+modifier, loco, zone, mzone)) {\n\t\t\t\treturn(trycell);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (horz) {\n\t\tint modifier = (y > MapCellY) ? -MAP_CELL_W : MAP_CELL_W;\n\n\t\tfor (int index = 0; index < MapCellWidth; index++) {\n\t\t\tCELL trycell = XY_Cell(((x + index) % MapCellWidth) + MapCellX, y + MapCellY);\n\n\t\t\tif (Good_Reinforcement_Cell(trycell, trycell+modifier, loco, zone, mzone)) {\n\t\t\t\treturn(trycell);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there was no success in finding a suitable reinforcement edge cell, then return\n\t**\twith the default 'punt' cell location.\n\t*/\n\treturn(punt);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Good_Reinforcement_Cell -- Checks cell for renforcement legality.             *\n *                                                                                             *\n *    This routine will check the secified cell (given the specified conditions) and determine *\n *    if that is a good cell for reinforcement purposes. It checks for passability of the cell *\n *    as well as zone and whether blocking walls can be crushed.                               *\n *                                                                                             *\n * INPUT:   outcell  -- The cell that is just outside the edge of the map.                     *\n *                                                                                             *\n *          incell   -- The cell that is just inside the edge of the map.                      *\n *                                                                                             *\n *          loco     -- The locomotion type of the reinforcement.                              *\n *                                                                                             *\n *          zone     -- The zone that the eventual movement destination lies. A reinforcement  *\n *                      edge must fall within the same zone.                                   *\n *                                                                                             *\n *          mzone    -- The zone check type to check against (if zone checking required)       *\n *                                                                                             *\n * OUTPUT:  bool; Is the specified cell good for reinforcement purposes?                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool DisplayClass::Good_Reinforcement_Cell(CELL outcell, CELL incell, SpeedType loco, int zone, MZoneType mzone) const\n{\n\t/*\n\t**\tIf the map edge location is not clear for object placement, then this is not\n\t**\ta good cell for reinforcement purposes.\n\t*/\n\tif (!(*this)[outcell].Is_Clear_To_Move(loco, false, false)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf it looks like the on-map cell cannot be driven on to, then return with\n\t**\tthe failure code.\n\t*/\n\tif (!(*this)[incell].Is_Clear_To_Move(loco, false, false, zone, mzone)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the reinforcement cell is already occupied, then return a failure code.\n\t*/\n\tif ((*this)[outcell].Cell_Techno() != NULL) {\n\t\treturn(false);\n\t}\n\tif ((*this)[incell].Cell_Techno() != NULL) return(false);\n\n\t/*\n\t**\tAll tests have passed, return with success code.\n\t*/\n//Mono_Printf(\"<%04X>\\n\", incell);Keyboard->Get();\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Select_These -- All selectable objects in region are selected.                *\n *                                                                                             *\n *    Use this routine to simultaneously select all objects within the coordinate region       *\n *    specified. This routine is used by the multi-select rubber band handler.                 *\n *                                                                                             *\n * INPUT:   coord1   -- Coordinate of one corner of the selection region.                      *\n *                                                                                             *\n *          coord2   -- The opposite corner of the selection region.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *   04/25/1995 JLB : Limited to non-building type.                                            *\n *   03/06/1996 JLB : Allows selection of aircraft with bounding box.                          *\n *=============================================================================================*/\nvoid DisplayClass::Select_These(COORDINATE coord1, COORDINATE coord2)\n{\n\tCOORDINATE tcoord = TacticalCoord;\t//Cell_Coord(TacticalCell) & 0xFF00FF00L;\n\n\tcoord1 = Coord_Add(tcoord, coord1);\n\tcoord2 = Coord_Add(tcoord, coord2);\n\tint x1 = Coord_X(coord1);\n\tint x2 = Coord_X(coord2);\n\tint y1 = Coord_Y(coord1);\n\tint y2 = Coord_Y(coord2);\n\n\t/*\n\t**\tEnsure that coordinate number one represents the upper left corner\n\t**\tand coordinate number two represents the lower right corner.\n\t*/\n\tif (x1 > x2) {\n\t\tint temp = x1;\n\t\tx1 = x2;\n\t\tx2 = temp;\n\t}\n\tif (y1 > y2) {\n\t\tint temp = y1;\n\t\ty1 = y2;\n\t\ty2 = temp;\n\t}\n\n\t/*\n\t**\tSweep through all ground layer objects and select the ones within the\n\t**\tbounding box.\n\t*/\n\tUnselect_All();\n\tAllowVoice = true;\n\tfor (int index = 0; index < Layer[LAYER_GROUND].Count(); index++) {\n\t\tObjectClass * obj = Layer[LAYER_GROUND][index];\n\t\tCOORDINATE ocoord = obj->Center_Coord();\n\t\tint x = Coord_X(ocoord);\n\t\tint y = Coord_Y(ocoord);\n\n\t\t/*\n\t\t**\tOnly try to select objects that are owned by the player, are allowed to be\n\t\t**\tselected, and are within the bounding box.\n\t\t*/\n\t\tHouseClass * hptr = HouseClass::As_Pointer(obj->Owner());\n\t\tif (\t(hptr != NULL && hptr->IsPlayerControl) &&\n\t\t\t\tobj->Class_Of().IsSelectable &&\n\t\t\t\tobj->What_Am_I() != RTTI_BUILDING &&\n\t\t\t\tx >= x1 && x <= x2 && y >= y1 && y <= y2) {\n\t\t\tif (obj->Select()) {\n\t\t\t\tAllowVoice = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tSelect any aircraft with the bounding box.\n\t*/\n\tfor (int air_index = 0; air_index < Aircraft.Count(); air_index++) {\n\t\tAircraftClass * aircraft = Aircraft.Ptr(air_index);\n\t\tCOORDINATE ocoord = aircraft->Center_Coord();\n\t\tint x = Coord_X(ocoord);\n\t\tint y = Coord_Y(ocoord);\n\n\t\t/*\n\t\t**\tOnly try to select objects that are owned by the player, are allowed to be\n\t\t**\tselected, and are within the bounding box.\n\t\t*/\n\t\tif (\taircraft->House->IsPlayerControl &&\n\t\t\t\taircraft->Class->IsSelectable &&\n\t\t\t\t!aircraft->IsSelected &&\n\t\t\t\tx >= x1 && x <= x2 && y >= y1 && y <= y2) {\n\n\t\t\tif (aircraft->Select()) {\n\t\t\t\tAllowVoice = false;\n\t\t\t}\n\t\t}\n\t}\n\n\tAllowVoice = true;\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Refresh_Band -- Causes all cells under the rubber band to be redrawn.         *\n *                                                                                             *\n *    Use this routine to flag all cells that are covered in some fashion by the multi-unit    *\n *    select \"rubber band\" to be redrawn. This is necessary whenever the rubber band changes   *\n *    size or is being removed.                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Refresh_Band(void)\n{\n\tif (IsRubberBand) {\n\n\t\t/*\n\t\t**\tIn rubber band mode, mark all cells under the \"rubber band\" to be\n\t\t**\tredrawn.\n\t\t*/\n\t\tint x1 = BandX+TacPixelX;\n\t\tint y1 = BandY+TacPixelY;\n\t\tint x2 = NewX+TacPixelX;\n\t\tint y2 = NewY+TacPixelY;\n\n\t\tif (x1 > x2) {\n\t\t\tint temp = x1;\n\t\t\tx1 = x2;\n\t\t\tx2 = temp;\n\t\t}\n\t\tif (y1 > y2) {\n\t\t\tint temp = y1;\n\t\t\ty1 = y2;\n\t\t\ty2 = temp;\n\t\t}\n\n\t\tCELL cell;\n\t\tfor (int y = y1; y <= y2+CELL_PIXEL_H; y += CELL_PIXEL_H) {\n\t\t\tcell = Click_Cell_Calc(x1, Bound(y, 0, TacPixelY+Lepton_To_Pixel(TacLeptonHeight)));\n\t\t\tif (cell != -1) (*this)[cell].Redraw_Objects();\n\n\t\t\tcell = Click_Cell_Calc(x2, Bound(y, 0, TacPixelY+Lepton_To_Pixel(TacLeptonHeight)));\n\t\t\tif (cell != -1) (*this)[cell].Redraw_Objects();\n\t\t}\n\n\t\tfor (int x = x1; x <= x2+CELL_PIXEL_W; x += CELL_PIXEL_W) {\n\t\t\tcell = Click_Cell_Calc(Bound(x, 0, TacPixelX+Lepton_To_Pixel(TacLeptonWidth)), y1);\n\t\t\tif (cell != -1) (*this)[cell].Redraw_Objects();\n\n\t\t\tcell = Click_Cell_Calc(Bound(x, 0, TacPixelX+Lepton_To_Pixel(TacLeptonWidth)), y2);\n\t\t\tif (cell != -1) (*this)[cell].Redraw_Objects();\n\t\t}\n\n\t\t/*\n\t\t**\tStretching the rubber band requires all objects to be redrawn.\n\t\t*/\n\t\tfor (int index = 0; index < Layer[LAYER_TOP].Count(); index++) {\n\t\t\tLayer[LAYER_TOP][index]->Mark(MARK_CHANGE);\n\t\t}\n\t\tfor (index = 0; index < Layer[LAYER_AIR].Count(); index++) {\n\t\t\tLayer[LAYER_AIR][index]->Mark(MARK_CHANGE);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::TacticalClass::Action -- Processes input for the tactical map.                *\n *                                                                                             *\n *    This routine handles the input directed at the tactical map. Since input, in this        *\n *    regard, includes even the presence of the mouse over the tactical map, this routine      *\n *    is called nearly every game frame. It handles adjusting the mouse shape as well as       *\n *    giving orders to units.                                                                  *\n *                                                                                             *\n * INPUT:   flags -- The gadget event flags that triggered the call to this function.          *\n *                                                                                             *\n *          key   -- A reference to the keyboard event (if any).                               *\n *                                                                                             *\n * OUTPUT:  bool; Should processing be aborted on any succeeding buttons in the chain?         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/17/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint DisplayClass::TacticalClass::Action(unsigned flags, KeyNumType & key)\n{\n\tint\t\tx,y;\t\t\t\t\t// Sub cell pixel coordinates.\n\tbool\t\tshadow;\n\tObjectClass * object = 0;\n\tActionType action = ACTION_NONE;\t\t// Action possible with currently selected object.\n\n\t/*\n\t**\tSet some working variables that depend on the mouse position. For the press\n\t**\tor release event, special mouse queuing storage variables are used. Other\n\t**\tevents must use the current mouse position globals.\n\t*/\n\tif (flags & (LEFTPRESS|LEFTRELEASE|RIGHTPRESS|RIGHTRELEASE)) {\n\t\tx = Keyboard->MouseQX;\n\t\ty = Keyboard->MouseQY;\n\t} else {\n\t\tx = Get_Mouse_X();\n\t\ty = Get_Mouse_Y();\n\t}\n\tbool edge = (y == 0 || x == 0 || x == SeenBuff.Get_Width()-1 || y == SeenBuff.Get_Height()-1);\n\tCOORDINATE coord = Map.Pixel_To_Coord(x, y);\n\tCELL cell = Coord_Cell(coord);\n\tif (coord) {\n\n\t\tshadow = (!Map[cell].IsMapped && !Debug_Unshroud);\n\t\tx -= Map.TacPixelX;\n\t\ty -= Map.TacPixelY;\n\n\t\t/*\n\t\t** Cause any displayed cursor to move along with the mouse cursor.\n\t\t*/\n\t\tif (cell != Map.ZoneCell) {\n\t\t\tMap.Set_Cursor_Pos(cell);\n\t\t}\n\n\t\t/*\n\t\t**\tDetermine the object that the mouse is currently over.\n\t\t*/\n\t\tif (!shadow) {\n\t\t\tobject = Map.Close_Object(coord);\n\n\t\t\t/*\n\t\t\t**\tSpecial case check to ignore cloaked object if not owned by the player.\n\t\t\t*/\n\t\t\tif (object != NULL && object->Is_Techno() && !((TechnoClass *)object)->IsOwnedByPlayer && (((TechnoClass *)object)->Cloak == CLOAKED || ((TechnoClass *)object)->Techno_Type_Class()->IsInvisible)) {\n\t\t\t\tobject = NULL;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is a currently selected object, then the action to perform if\n\t\t**\tthe left mouse button were clicked must be determined.\n\t\t*/\n\t\tif (CurrentObject.Count()) {\n\t\t\tif (object != NULL) {\n\t\t\t\taction = CurrentObject[0]->What_Action(object);\n\t\t\t} else {\n\t\t\t\taction = CurrentObject[0]->What_Action(cell);\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif (object && object->Class_Of().IsSelectable) {\n\t\t\t\taction = ACTION_SELECT;\n\t\t\t}\n\n\t\t\tif (Map.IsRepairMode) {\n\t\t\t\tif (object && object->Owner() == PlayerPtr->Class->House && object->Can_Repair()) {\n\t\t\t\t\taction = ACTION_REPAIR;\n\t\t\t\t} else {\n\t\t\t\t\taction = ACTION_NO_REPAIR;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (Map.IsSellMode) {\n\t\t\t\tif (object && object->Owner() == PlayerPtr->Class->House && object->Can_Demolish()) {\n\t\t\t\t\tif (object->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\taction = ACTION_SELL;\n\t\t\t\t\t} else {\n\t\t\t\t\t\taction = ACTION_SELL_UNIT;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCheck to see if the cursor is over an owned wall.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Map[cell].Overlay != OVERLAY_NONE &&\n\t\t\t\t\t\tOverlayTypeClass::As_Reference(Map[cell].Overlay).IsWall &&\n\t\t\t\t\t\tMap[cell].Owner == PlayerPtr->Class->House) {\n\t\t\t\t\t\t\taction = ACTION_SELL;\n\t\t\t\t\t} else {\n\t\t\t\t\t\taction = ACTION_NO_SELL;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (Map.IsTargettingMode == SPC_NUCLEAR_BOMB) {\n\t\t\t\taction = ACTION_NUKE_BOMB;\n\t\t\t}\n\n\t\t\tif (Map.IsTargettingMode == SPC_PARA_BOMB) {\n\t\t\t\taction = ACTION_PARA_BOMB;\n\t\t\t}\n\n\t\t\tif (Map.IsTargettingMode == SPC_PARA_INFANTRY) {\n\t\t\t\taction = ACTION_PARA_INFANTRY;\n\t\t\t}\n\n\t\t\tif (Map.IsTargettingMode == SPC_SPY_MISSION) {\n\t\t\t\taction = ACTION_SPY_MISSION;\n\t\t\t}\n\n\t\t\tif (Map.IsTargettingMode == SPC_IRON_CURTAIN) {\n\t\t\t\taction = ACTION_IRON_CURTAIN;\n\t\t\t}\n\n\t\t\tif (Map.IsTargettingMode == SPC_CHRONOSPHERE) {\n\t\t\t\taction = ACTION_CHRONOSPHERE;\n\t\t\t}\n\n\t\t\tif (Map.IsTargettingMode == SPC_CHRONO2) {\n\t\t\t\taction = ACTION_CHRONO2;\n\t\t\t\tif (shadow) action = ACTION_NOMOVE;\n\t\t\t\tObjectClass const * tobject = As_Object(PlayerPtr->UnitToTeleport);\n\n\t\t\t\t/*\n\t\t\t\t**\tDetermine if the object can be teleported to the destination cell.\n\t\t\t\t*/\n\t\t\t\tif (tobject != NULL && tobject->Is_Techno()) {\n\t\t\t\t\tTechnoClass const * uobject = (TechnoClass const *)tobject;\n\t\t\t\t\tif (!uobject->Can_Teleport_Here(cell)) {\n//\t\t\t\t\tif (((UnitClass *)As_Object(PlayerPtr->UnitToTeleport))->Can_Enter_Cell(cell, FACING_NONE) != MOVE_OK) {\n\t\t\t\t\t\taction = ACTION_NOMOVE;\n\t\t\t\t\t}\n\n\t\t\t\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\telse {\t// If the object is no longer valid, cancel targetting mode.\n\t\t\t\t\taction = ACTION_NOMOVE;\n\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t}\n#endif\n\t\t\t}\n\n\t\t\tif (Map.PendingObject) {\n\t\t\t\taction = ACTION_NONE;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tMove any cursor displayed.\n\t\t*/\n\t\tif (cell != Map.ZoneCell) {\n\t\t\tMap.Set_Cursor_Pos(cell);\n\t\t}\n\n\t\t/*\n\t\t**\tA right mouse button press cancels the current action or selection.\n\t\t*/\n\t\tif (flags & RIGHTPRESS) {\n\t\t\tMap.Mouse_Right_Press();\n\t\t}\n\n\t\t/*\n\t\t**\tMake sure that if the mouse button has been released and the map doesn't know about it,\n\t\t**\tthen it must be informed. Do this by faking a mouse release event.\n\t\t*/\n\t\tif ((flags & LEFTUP) && Map.IsRubberBand) {\n\t\t\tflags |= LEFTRELEASE;\n\t\t}\n\n\t\t/*\n\t\t**\tWhen the mouse buttons aren't pressed, only the mouse cursor shape is processed.\n\t\t**\tThe shape changes depending on what object the mouse is currently over and what\n\t\t**\tobject is currently selected.\n\t\t*/\n\t\tif (!edge) {\n\t\t\tif (flags & LEFTUP) {\n\t\t\t\tMap.Mouse_Left_Up(cell, shadow, object, action);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tNormal actions occur when the mouse button is released. The press event is\n\t\t**\tintercepted and possible rubber-band mode is flagged.\n\t\t*/\n\t\tif (flags & LEFTRELEASE) {\n\t\t\tMap.Mouse_Left_Release(cell, x, y, object, action);\n\t\t}\n\n\t\t/*\n\t\t**\tWhen the mouse is first pressed on the map, then record the mouse\n\t\t**\tposition so that a proper check before going into rubber band\n\t\t**\tmode can be made. Rubber band mode starts when the mouse is\n\t\t**\theld down and moved a certain minimum distance.\n\t\t*/\n\t\tif (!edge && (flags & LEFTPRESS)) {\n\t\t\tMap.Mouse_Left_Up(cell, shadow, object, action);\n\t\t\tMap.Mouse_Left_Press(x, y);\n\t\t}\n\n\t\t/*\n\t\t**\tWhile the mouse is being held down, determine if rubber band mode should\n\t\t**\tstart. If rubber band mode is already active, then update the size\n\t\t**\tand flag the map to redraw it.\n\t\t*/\n\t\tif (flags & LEFTHELD) {\n\t\t\tMap.Mouse_Left_Held(x, y);\n\t\t}\n\t}\n\n\treturn(GadgetClass::Action(0, key));\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Mouse_Right_Press -- Handles the right mouse button press.                    *\n *                                                                                             *\n *    This routine is called when the right mouse button is pressed. This action is supposed   *\n *    to cancel whatever mode or process is active. If there is nothing to cancel, then it     *\n *    will default to unselecting any units that might be currently selected.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Mouse_Right_Press(void)\n{\n\tif (PendingObjectPtr && PendingObjectPtr->Is_Techno()) {\n\t\t//PendingObjectPtr->Transmit_Message(RADIO_OVER_OUT);\n\t\tPendingObjectPtr = 0;\n\t\tPendingObject = 0;\n\t\tPendingHouse = HOUSE_NONE;\n\t\tSet_Cursor_Shape(0);\n\t} else {\n\t\tif (IsRepairMode) {\n\t\t\tIsRepairMode = false;\n\t\t} else {\n\t\t\tif (IsSellMode) {\n\t\t\t\tIsSellMode = false;\n\t\t\t} else {\n\t\t\t\tif (IsTargettingMode != SPC_NONE) {\n\t\t\t\t\tIsTargettingMode = SPC_NONE;\n\t\t\t\t} else {\n\t\t\t\t\tUnselect_All();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// If it breaks... call 228.\n\tSet_Default_Mouse(MOUSE_NORMAL, Map.IsSmall);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Mouse_Left_Up -- Handles the left mouse \"cruising\" over the map.              *\n *                                                                                             *\n *    This routine is called continuously while the mouse is over the tactical map but there   *\n *    are no mouse buttons pressed. Typically, this adjusts the mouse shape and the pop-up     *\n *    help text.                                                                               *\n *                                                                                             *\n * INPUT:   shadow   -- Is the mouse hovering over shadowed terrain?                           *\n *                                                                                             *\n *          object   -- Pointer to the object that the mouse is currently over (may be NULL).  *\n *                                                                                             *\n *          action   -- This is the action that the currently selected object (if any) will    *\n *                      perform if the left mouse button were clicked at this location.        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/24/1995 JLB : Created.                                                                 *\n *   07/05/1995 JLB : Removed pop up help text for shadow and terrain after #3.                *\n *=============================================================================================*/\nvoid DisplayClass::Mouse_Left_Up(CELL cell, bool shadow, ObjectClass * object, ActionType action, bool wsmall)\n{\n\tIsTentative = false;\n\n\tTARGET target = TARGET_NONE;\n\tif (object != NULL) {\n\t\ttarget = object->As_Target();\n\t} else {\n\t\tif (cell != -1) {\n\t\t\ttarget = As_Target(cell);\n\t\t}\n\t}\n\n\t/*\n\t**\tDon't allow selection of an object that is located in shadowed terrain.\n\t**\tIn fact, just show the normal move cursor in order to keep the shadowed\n\t**\tterrain a mystery.\n\t*/\n\tif (shadow) {\n\t\tswitch (action) {\n\t\t\tcase ACTION_NO_DEPLOY:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_DEPLOY, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NO_ENTER:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_ENTER, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NO_GREPAIR:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_GREPAIR, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_DAMAGE:\n\t\t\t\tSet_Default_Mouse(MOUSE_NORMAL, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_GREPAIR:\n\t\t\t\tSet_Default_Mouse(MOUSE_NORMAL, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_GUARD_AREA:\n\t\t\t\tSet_Default_Mouse(MOUSE_AREA_GUARD, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NONE:\n\t\t\t\tSet_Default_Mouse(MOUSE_NORMAL, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NO_SELL:\n\t\t\tcase ACTION_SELL:\n\t\t\tcase ACTION_SELL_UNIT:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_SELL_BACK, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NO_REPAIR:\n\t\t\tcase ACTION_REPAIR:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_REPAIR, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NUKE_BOMB:\n\t\t\t\tSet_Default_Mouse(MOUSE_NUCLEAR_BOMB, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_AIR_STRIKE:\n\t\t\tcase ACTION_PARA_BOMB:\n\t\t\tcase ACTION_PARA_INFANTRY:\n\t\t\tcase ACTION_SPY_MISSION:\n\t\t\tcase ACTION_IRON_CURTAIN:\n\t\t\t\tSet_Default_Mouse(MOUSE_AIR_STRIKE, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_CHRONOSPHERE:\n\t\t\t\tSet_Default_Mouse(MOUSE_CHRONO_SELECT, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_CHRONO2:\n\t\t\t\tSet_Default_Mouse(MOUSE_CHRONO_DEST, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_HEAL:\n\t\t\t\tSet_Default_Mouse(MOUSE_HEAL, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NOMOVE:\n\t\t\t\tif (CurrentObject.Count() && CurrentObject[0]->What_Am_I() == RTTI_AIRCRAFT) {\n\t\t\t\t\tSet_Default_Mouse(MOUSE_NO_MOVE, wsmall);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// Fall into next case for non aircraft object types.\n\n\t\t\tdefault:\n\t\t\t\tSet_Default_Mouse(MOUSE_CAN_MOVE, wsmall);\n\t\t\t\tbreak;\n\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tChange the mouse shape according to the default action that will occur\n\t\t**\tif the mouse button were clicked at this location.\n\t\t*/\n\t\tswitch (action) {\n\t\t\tcase ACTION_NO_DEPLOY:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_DEPLOY, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NO_ENTER:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_ENTER, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NO_GREPAIR:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_GREPAIR, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_DAMAGE:\n\t\t\t\tSet_Default_Mouse(MOUSE_DAMAGE, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_GREPAIR:\n\t\t\t\tSet_Default_Mouse(MOUSE_GREPAIR, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_TOGGLE_SELECT:\n\t\t\tcase ACTION_SELECT:\n\t\t\t\tSet_Default_Mouse(MOUSE_CAN_SELECT, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_MOVE:\n\t\t\t\tSet_Default_Mouse(MOUSE_CAN_MOVE, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_GUARD_AREA:\n\t\t\t\tSet_Default_Mouse(MOUSE_AREA_GUARD, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_ATTACK:\n\t\t\t\tif (Target_Legal(target) && CurrentObject.Count() == 1 && CurrentObject[0]->Is_Techno() && ((TechnoClass *)CurrentObject[0])->In_Range(target, 0)) {\n\t\t\t\t\tSet_Default_Mouse(MOUSE_STAY_ATTACK, wsmall);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// fall into next case.\n\n\t\t\tcase ACTION_HARVEST:\n\t\t\t\tSet_Default_Mouse(MOUSE_CAN_ATTACK, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_SABOTAGE:\n\t\t\t\tSet_Default_Mouse(MOUSE_DEMOLITIONS, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_ENTER:\n\t\t\tcase ACTION_CAPTURE:\n\t\t\t\tSet_Default_Mouse(MOUSE_ENTER, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NOMOVE:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_MOVE, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NO_SELL:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_SELL_BACK, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NO_REPAIR:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_REPAIR, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_SELF:\n\t\t\t\tSet_Default_Mouse(MOUSE_DEPLOY, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_REPAIR:\n\t\t\t\tSet_Default_Mouse(MOUSE_REPAIR, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_SELL_UNIT:\n\t\t\t\tSet_Default_Mouse(MOUSE_SELL_UNIT, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_SELL:\n\t\t\t\tSet_Default_Mouse(MOUSE_SELL_BACK, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NUKE_BOMB:\n\t\t\t\tSet_Default_Mouse(MOUSE_NUCLEAR_BOMB, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_AIR_STRIKE:\n\t\t\tcase ACTION_PARA_BOMB:\n\t\t\tcase ACTION_PARA_INFANTRY:\n\t\t\tcase ACTION_SPY_MISSION:\n\t\t\tcase ACTION_IRON_CURTAIN:\n\t\t\t\tSet_Default_Mouse(MOUSE_AIR_STRIKE, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_CHRONOSPHERE:\n\t\t\t\tSet_Default_Mouse(MOUSE_CHRONO_SELECT, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_CHRONO2:\n\t\t\t\tSet_Default_Mouse(MOUSE_CHRONO_DEST, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_HEAL:\n\t\t\t\tSet_Default_Mouse(MOUSE_HEAL, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tSet_Default_Mouse(MOUSE_NORMAL, wsmall);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tNever display help text if the mouse is held over the radar map.\n\t*/\n\tif (wsmall) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tGive a generic help message when over shadow terrain.\n\t*/\n\tif (shadow) {\n//\t\tif (Scen.Scenario < 4) {\n\t\t\tHelp_Text(TXT_SHADOW);\n//\t\t} else {\n//\t\t\tHelp_Text(TXT_NONE);\n//\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tIf the mouse is held over objects on the map, then help text may\n\t\t**\tpop up that tells what the object is. This call informs the help\n\t\t**\tsystem of the text name for the object under the mouse.\n\t\t*/\n\t\tif (object != NULL) {\n\t\t\tint text;\n\t\t\tint color = LTGREY;\n\n\t\t\t/*\n\t\t\t**\tFetch the appropriate background color for help text.\n\t\t\t*/\n\t\t\tif (PlayerPtr->Is_Ally(object)) {\n\t\t\t\tcolor = GREEN;\n\t\t\t} else {\n\t\t\t\tif (object->Owner() == HOUSE_NONE || object->Owner() == HOUSE_NEUTRAL) {\n\t\t\t\t\tcolor = LTGREY;\n\t\t\t\t} else {\n\t\t\t\t\tcolor = PINK;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tFetch the name of the object. If it is an enemy object, then\n\t\t\t**\tthe exact identity is glossed over with a generic text.\n\t\t\t*/\n\t\t\ttext = object->Full_Name();\n\t\t\tif (object->Is_Techno() && !((TechnoTypeClass const &)object->Class_Of()).IsNominal) {\n\n\t\t\t\tif (!((TechnoClass *)object)->House->Is_Ally(PlayerPtr)) {\n//\t\t\t\tif (!PlayerPtr->Is_Ally(object)) {\n\t\t\t\t\tswitch (object->What_Am_I()) {\n\t\t\t\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t\t\t\ttext = TXT_ENEMY_SOLDIER;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase RTTI_UNIT:\n\t\t\t\t\t\t\ttext = TXT_ENEMY_VEHICLE;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase RTTI_BUILDING:\n\t\t\t\t\t\t\ttext = TXT_ENEMY_STRUCTURE;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (/*Scen.Scenario > 3 ||*/ object->What_Am_I() != RTTI_TERRAIN) {\n\t\t\t\tHelp_Text(text, -1, -1, color);\n\t\t\t} else {\n\t\t\t\tHelp_Text(TXT_NONE);\n\t\t\t}\n\t\t} else {\n\t\t\tif ((*this)[cell].Land_Type() == LAND_TIBERIUM) {\n\t\t\t\tHelp_Text(TXT_MINERALS);\n\t\t\t} else {\n\t\t\t\tHelp_Text(TXT_NONE);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Mouse_Left_Release -- Handles the left mouse button release.                  *\n *                                                                                             *\n *    This routine is called when the left mouse button is released over the tactical map.     *\n *    The release event is the workhorse of the game. Most actions occur at the moment of      *\n *    mouse release.                                                                           *\n *                                                                                             *\n * INPUT:   cell     -- The cell that the mouse is over.                                       *\n *                                                                                             *\n *          x,y      -- The mouse pixel coordinate.                                            *\n *                                                                                             *\n *          object   -- Pointer to the object that the mouse is over.                          *\n *                                                                                             *\n *          action   -- The action that the currently selected object (if any) will            *\n *                      perform.                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/24/1995 JLB : Created.                                                                 *\n *   03/27/1995 JLB : Handles sell and repair actions.                                         *\n *=============================================================================================*/\nvoid DisplayClass::Mouse_Left_Release(CELL cell, int x, int y, ObjectClass * object, ActionType action, bool wsmall)\n{\n\tif (PendingObjectPtr) {\n\t\t/*\n\t\t**\tTry to place the pending object onto the map.\n\t\t*/\n\t\tif (ProximityCheck) {\n\t\t\tOutList.Add(EventClass(EventClass::PLACE, PendingObjectPtr->What_Am_I(), cell + ZoneOffset));\n\t\t} else {\n\t\t\tSpeak(VOX_DEPLOY);\n\t\t}\n\n\t} else {\n\n\t\tif (IsRubberBand) {\n\t\t\tRefresh_Band();\n\t\t\tSelect_These(XYP_Coord(BandX, BandY), XYP_Coord(x, y));\n\n\t\t\tSet_Default_Mouse(MOUSE_NORMAL, wsmall);\n\t\t\tIsRubberBand = false;\n\t\t\tIsTentative = false;\n\t\t\tMap.DisplayClass::IsToRedraw = true;\n\t\t\tMap.Flag_To_Redraw(false);\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tToggle the select state of the object.\n\t\t\t*/\n\t\t\tif (action == ACTION_TOGGLE_SELECT) {\n\t\t\t\tif (!object || !CurrentObject.Count() || CurrentObject[0]->Owner() != PlayerPtr->Class->House) {\n\t\t\t\t\taction = ACTION_SELECT;\n\t\t\t\t} else {\n\t\t\t\t\tif (object->IsSelected) {\n\t\t\t\t\t\tobject->Unselect();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tobject->Select();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSelection of other object action.\n\t\t\t*/\n\t\t\tif (action == ACTION_SELECT || (action == ACTION_NONE && object && object->Class_Of().IsSelectable && !object->IsSelected)) {\n\t\t\t\tUnselect_All();\n\t\t\t\tobject->Select();\n\t\t\t\tSet_Default_Mouse(MOUSE_NORMAL, wsmall);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf an action was detected as possible, then pass this action event\n\t\t\t**\tto all selected objects.\n\t\t\t*/\n\t\t\tif (action != ACTION_NONE && action != ACTION_SELECT) {\n\n\t\t\t\t/*\n\t\t\t\t**\tPass the action to all the selected objects. But first, redetermine\n\t\t\t\t**\twhat action that object should perform. This, seemingly redundant\n\t\t\t\t**\tprocess, is necessary since multiple objects could be selected and each\n\t\t\t\t**\tmight perform a different action when the click occurs.\n\t\t\t\t*/\n\t\t\t\tbool doflash = true;\n\t\t\t\tAllowVoice = true;\n\t\t\t\tFormMove = false;\n\t\t\t\tFormSpeed = SPEED_WHEEL;\n\t\t\t\tFormMaxSpeed = MPH_LIGHT_SPEED;\n\n\t\t\t\tif ( (action == ACTION_MOVE || action == ACTION_NOMOVE) && CurrentObject.Count()) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Scan all units.  If any are selected that shouldn't be, or aren't\n\t\t\t\t\t** selected but should be, then this is not a formation move.\n\t\t\t\t\t*/\n\t\t\t\t\tint group = 254;\t// init to invalid group #\n\n\t\t\t\t\tif (CurrentObject[0]->Is_Foot()) {\n\t\t\t\t\t\tgroup = ((FootClass *)CurrentObject[0])->Group;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tPresume this is a formation move unless something is detected\n\t\t\t\t\t**\tthat will prevent it.\n\t\t\t\t\t*/\n\t\t\t\t\tFormMove = true;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tFirst scan through all the selected units to make sure that they\n\t\t\t\t\t**\tare all of the same team and have been assigned a particular formation\n\t\t\t\t\t*/\n\t\t\t\t\tfor (int index = 0; index < CurrentObject.Count(); index++) {\n\t\t\t\t\t\tObjectClass const * tobject = CurrentObject[index];\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tOnly moveable (i.e., FootClass) objects can ever be in a formation\n\t\t\t\t\t\t**\tso if a selected object isn't of a FootClass type then it can't be\n\t\t\t\t\t\t**\ta formation move.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (tobject->Is_Foot() == false) {\n\t\t\t\t\t\t\tFormMove = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf the object is not part of the same team as the rest of the\n\t\t\t\t\t\t**\tselected group, or it just plain has never been assigned a\n\t\t\t\t\t\t**\tformation offset, then it can't be a formation move.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tFootClass const * foot = (FootClass *)tobject;\n\t\t\t\t\t\tif (foot->Group != group || foot->XFormOffset == 0x80000000) {\n\t\t\t\t\t\t\tFormMove = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDetermine the formation speed on the presumption that this\n\t\t\t\t\t\t**\twill turn out to be a formation move.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tFormMaxSpeed = foot->Techno_Type_Class()->MaxSpeed;\n\t\t\t\t\t\tFormSpeed = foot->Techno_Type_Class()->Speed;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tLoop through all objects (that can theoretically be part of a team) and\n\t\t\t\t\t**\tif there are any that are part of the currently selected team, but\n\t\t\t\t\t**\tare not currently selected themselves, then this will force this move\n\t\t\t\t\t**\tto NOT be a formation move.\n\t\t\t\t\t*/\n\t\t\t\t\tif (FormMove) {\n\t\t\t\t\t\tfor (index = 0; index < ::Logic.Count(); index++) {\n\t\t\t\t\t\t\tObjectClass const * obj = ::Logic[index];\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf the object is selected, then it has already been scanned\n\t\t\t\t\t\t\t**\tby the previous loop.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (obj->IsSelected) continue;\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tOnly consider footclass objects.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (!obj->Is_Foot()) continue;\n\n\t\t\t\t\t\t\tFootClass const * foot = (FootClass *)obj;\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tOnly consider objects that are owned by the player.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (!foot->IsOwnedByPlayer) continue;\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf another member of this team has been discovered and\n\t\t\t\t\t\t\t**\tit isn't selected, then the formation move cannot take\n\t\t\t\t\t\t\t**\tplace.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (foot->Group == group) {\n\t\t\t\t\t\t\t\tFormMove = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (int index = 0; index < CurrentObject.Count(); index++) {\n\t\t\t\t\tObjectClass * tobject = CurrentObject[index];\n\n\t\t\t\t\tif (object != NULL) {\n\t\t\t\t\t\ttobject->Active_Click_With(tobject->What_Action(object), object);\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Trap for formation moves: if this unit is part of a\n\t\t\t\t\t\t** formation (being part of a team qualifies) and they're\n\t\t\t\t\t\t** told to move, adjust the target destination so they stay\n\t\t\t\t\t\t** in formation when they arrive.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tCELL newmove = cell;\n\t\t\t\t\t\tint whatami = tobject->What_Am_I();\n\t\t\t\t\t\tif (action == ACTION_MOVE && tobject->Is_Foot()) {\n\t\t\t\t\t\t\tint oldisform;\n\t\t\t\t\t\t\tFootClass * foot = (FootClass *)tobject;\n\t\t\t\t\t\t\toldisform = foot->IsFormationMove;\n\t\t\t\t\t\t\tfoot->IsFormationMove = FormMove;\n\t\t\t\t\t\t\tif (FormMove && foot->Group != 255 ) {\n\t\t\t\t\t\t\t\tnewmove = foot->Adjust_Dest(cell);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfoot->IsFormationMove = oldisform;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttobject->Active_Click_With(tobject->What_Action(cell), newmove);\n\t\t\t\t\t}\n\t\t\t\t\tAllowVoice = false;\n\t\t\t\t}\n\t\t\t\tAllowVoice = true;\n\t\t\t\tFormMove = false;\n\n\t\t\t\tif (action == ACTION_REPAIR && object->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::REPAIR, TargetClass(object)));\n\t\t\t\t}\n\t\t\t\tif (action == ACTION_SELL_UNIT && object) {\n\t\t\t\t\tswitch (object->What_Am_I()) {\n\t\t\t\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\t\t\tcase RTTI_UNIT:\n\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::SELL, TargetClass(object)));\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t\tif (action == ACTION_SELL) {\n\t\t\t\t\tif (object) {\n\t\t\t\t\t\tOutList.Add(EventClass(EventClass::SELL, TargetClass(object)));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tOutList.Add(EventClass(EventClass::SELLCELL, cell));\n//\t\t\t\t\t\tOutList.Add(EventClass(EventClass::SELL, ::As_Target(cell)));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (action == ACTION_NUKE_BOMB) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_NUCLEAR_BOMB, cell));\n\t\t\t\t}\n\n\t\t\t\tif (action == ACTION_PARA_BOMB) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_PARA_BOMB, cell));\n\t\t\t\t}\n\t\t\t\tif (action == ACTION_PARA_INFANTRY) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_PARA_INFANTRY, cell));\n\t\t\t\t}\n\t\t\t\tif (action == ACTION_SPY_MISSION) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_SPY_MISSION, cell));\n\t\t\t\t}\n\t\t\t\tif (action == ACTION_IRON_CURTAIN) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_IRON_CURTAIN, cell));\n\t\t\t\t}\n\t\t\t\tif (action == ACTION_CHRONOSPHERE) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_CHRONOSPHERE, cell));\n\t\t\t\t}\n\t\t\t\tif (action == ACTION_CHRONO2) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_CHRONO2, cell));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tIsTentative = false;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Mouse_Left_Press -- Handles the left mouse button press.                      *\n *                                                                                             *\n *    Handle the left mouse button press while over the tactical map. If it isn't is           *\n *    repair or sell mode, then a tentative transition to rubber band mode is flagged. If the  *\n *    mouse moves a sufficient distance from this recorded position, then rubber band mode     *\n *    is officially started.                                                                   *\n *                                                                                             *\n * INPUT:   x,y   -- The mouse coordinates at the time of the press.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Mouse_Left_Press(int x, int y)\n{\n\tif (!IsRepairMode && !IsSellMode && IsTargettingMode == SPC_NONE && !PendingObject) {\n\t\tIsTentative = true;\n\t\tBandX = x;\n\t\tBandY = y;\n\t\tNewX = x;\n\t\tNewY = y;\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Mouse_Left_Held -- Handles the left button held down.                         *\n *                                                                                             *\n *    This routine is called continuously while the left mouse button is held down over        *\n *    the tactical map. This handles the rubber band mode detection and dragging.              *\n *                                                                                             *\n * INPUT:   x,y   -- The mouse coordinate.                                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Mouse_Left_Held(int x, int y)\n{\n\tif (IsRubberBand) {\n\t\tif (x != NewX || y != NewY) {\n\t\t\tx = Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1);\n\t\t\ty = Bound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1);\n\t\t\tRefresh_Band();\n\t\t\tNewX = x;\n\t\t\tNewY = y;\n\t\t\tIsToRedraw = true;\n\t\t\tFlag_To_Redraw(false);\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tIf the mouse is still held down while a tentative extended select is possible, then\n\t\t**\tcheck to see if the mouse has moved a sufficient distance in order to activate\n\t\t**\textended select mode.\n\t\t*/\n\t\tif (IsTentative) {\n\n\t\t\t/*\n\t\t\t**\tThe mouse must have moved a minimum distance before rubber band mode can be\n\t\t\t**\tinitiated.\n\t\t\t*/\n\t\t\tif (ABS(x - BandX) > 4 || ABS(y - BandY) > 4) {\n\t\t\t\tIsRubberBand = true;\n\t\t\t\tx = Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1);\n\t\t\t\ty = Bound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1);\n\t\t\t\tNewX = x;\n\t\t\t\tNewY = y;\n\t\t\t\tIsToRedraw = true;\n\t\t\t\tFlag_To_Redraw(false);\n\n\t\t\t\t/*\n\t\t\t\t**\tStretching the rubber band requires all objects to be redrawn.\n\t\t\t\t*/\n\t\t\t\tfor (int index = 0; index < Layer[LAYER_TOP].Count(); index++) {\n\t\t\t\t\tLayer[LAYER_TOP][index]->Mark(MARK_CHANGE);\n\t\t\t\t}\n\t\t\t\tfor (index = 0; index < Layer[LAYER_AIR].Count(); index++) {\n\t\t\t\t\tLayer[LAYER_AIR][index]->Mark(MARK_CHANGE);\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Set_Tactical_Position -- Sets the tactical view position.                     *\n *                                                                                             *\n *    This routine is used to set the tactical view position. The requested position is        *\n *    clipped to the map dimensions as necessary.                                              *\n *                                                                                             *\n * INPUT:   coord -- The coordinate desired for the upper left corner.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Set_Tactical_Position(COORDINATE coord)\n{\n\t/*\n\t**\tBound the desired location to fit the legal map edges.\n\t*/\n\tint xx = (int)Coord_X(coord) - (int)Cell_To_Lepton(MapCellX);\n\tint yy = (int)Coord_Y(coord) - (int)Cell_To_Lepton(MapCellY);\n\n\tConfine_Rect(&xx, &yy, TacLeptonWidth, TacLeptonHeight, Cell_To_Lepton(MapCellWidth), Cell_To_Lepton(MapCellHeight));\n\tcoord = XY_Coord(xx + Cell_To_Lepton(MapCellX), yy + Cell_To_Lepton(MapCellY));\n\n\tif (ScenarioInit) {\n\t\tTacticalCoord = coord;\n\t}\n\tDesiredTacticalCoord = coord;\n\n\tIsToRedraw = true;\n\tFlag_To_Redraw(false);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Compute_Start_Pos -- Computes player's start pos from unit coords.            *\n *                                                                                             *\n * Use this function in multiplayer games, to compute the scenario starting Tactical Pos.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/28/1995 JLB : Commented.                                                               *\n *   06/26/1995 JLB : Fixed building loop.                                                     *\n *   10/20/1996 JLB : Doesn't wrap.                                                            *\n *=============================================================================================*/\nvoid DisplayClass::Compute_Start_Pos(void)\n{\n\t/*\n\t**\tFind the summation cell-x & cell-y for all the player's units, infantry,\n\t**\tand buildings.  Buildings are weighted so that they count 16 times more\n\t**\tthan units or infantry.\n\t*/\n\tlong x = 0;\n\tlong y = 0;\n\tlong num = 0;\n\tfor (int i = 0; i < Infantry.Count(); i++) {\n\t\tInfantryClass * infp = Infantry.Ptr(i);\n\t\tif (!infp->IsInLimbo && infp->IsOwnedByPlayer) {\n\t\t\tx += (long)Coord_XCell(infp->Coord);\n\t\t\ty += (long)Coord_YCell(infp->Coord);\n\t\t\tnum++;\n\t\t}\n\t}\n\n\tfor (i = 0; i < Units.Count(); i++) {\n\t\tUnitClass * unitp = Units.Ptr(i);\n\t\tif (!unitp->IsInLimbo && unitp->IsOwnedByPlayer) {\n\t\t\tx += (long)Coord_XCell(unitp->Coord);\n\t\t\ty += (long)Coord_YCell(unitp->Coord);\n\t\t\tnum++;\n\t\t}\n\t}\n\n\tfor (i = 0; i < Buildings.Count(); i++) {\n\t\tBuildingClass * bldgp = Buildings.Ptr(i);\n\t\tif (!bldgp->IsInLimbo && bldgp->IsOwnedByPlayer) {\n\t\t\tx += (((long)Coord_XCell(bldgp->Coord)) * 16);\n\t\t\ty += (((long)Coord_YCell(bldgp->Coord)) * 16);\n\t\t\tnum += 16;\n\t\t}\n\t}\n\n\tfor (i = 0; i < Vessels.Count(); i++) {\n\t\tVesselClass * bldgp = Vessels.Ptr(i);\n\t\tif (!bldgp->IsInLimbo && bldgp->IsOwnedByPlayer) {\n\t\t\tx += (((long)Coord_XCell(bldgp->Coord)));\n\t\t\ty += (((long)Coord_YCell(bldgp->Coord)));\n\t\t\tnum++;\n\t\t}\n\t}\n\n\t/*\n\t**\tDivide each coord by 'num' to compute the average value\n\t*/\n\tif (num > 0) {\n\t\tx /= num;\n\t} else {\n\t\tx = 0;\n\t}\n\n\tif (num > 0) {\n\t\ty /= num;\n\t} else {\n\t\ty = 0;\n\t}\n\n\t/*\n\t**\tTactical position is based on the cell of the upper left corner. Make adjustments\n\t**\tand bound the calculated location to the map dimensions.\n\t*/\n//\tx -= 5 * RESFACTOR;\n//\ty -= 4 * RESFACTOR;\n\tif (x < MapCellX + 5*RESFACTOR) x = MapCellX + 5*RESFACTOR;\n\tif (y < MapCellY + 4*RESFACTOR) y = MapCellY + 4*RESFACTOR;\n\tif (x > MapCellX+MapCellWidth - 5*RESFACTOR) x = MapCellX+MapCellWidth - 5*RESFACTOR;\n\tif (y > MapCellY+MapCellHeight - 4*RESFACTOR) y = MapCellY+MapCellHeight - 4*RESFACTOR;\n\n\tScen.Waypoint[WAYPT_HOME] = Scen.Views[0] = Scen.Views[1] = Scen.Views[2] = Scen.Views[3] = XY_Cell(x, y);\n\n\tMap.Set_Tactical_Position(Coord_Whole(Cell_Coord((Scen.Views[0] - (MAP_CELL_W * 4 * RESFACTOR)) - (5*RESFACTOR))));\n//\tSet_Tactical_Position(Cell_Coord(XY_Cell(x, y)));\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Sell_Mode_Control -- Controls the sell mode.                                  *\n *                                                                                             *\n *    This routine will control the sell mode for the player.                                  *\n *                                                                                             *\n * INPUT:   control  -- The mode to set the sell state to.                                     *\n *                      0  = Turn sell mode off.                                               *\n *                      1  = Turn sell mode on.                                                *\n *                      -1 = Toggle sell mode.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Sell_Mode_Control(int control)\n{\n\tbool mode = IsSellMode;\n\tswitch (control) {\n\t\tcase 0:\n\t\t\tmode = false;\n\t\t\tbreak;\n\n\t\tcase -1:\n\t\t\tmode = (IsSellMode == false);\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tmode = true;\n\t\t\tbreak;\n\t}\n\n\tif (mode != IsSellMode && !PendingObject) {\n\t\tIsRepairMode = false;\n\t\tif (mode && PlayerPtr->BScan) {\n\t\t\tIsSellMode = true;\n\t\t\tUnselect_All();\n\t\t} else {\n\t\t\tIsSellMode = false;\n\t\t\tRevert_Mouse_Shape();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Repair_Mode_Control -- Controls the repair mode.                              *\n *                                                                                             *\n *    This routine is used to control the repair mode for the player.                          *\n *                                                                                             *\n * INPUT:   control  -- The mode to set the repair to.                                         *\n *                      0 = Turn repair off.                                                   *\n *                      1 = Turn repair on.                                                    *\n *                      -1= Toggle repair state.                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Repair_Mode_Control(int control)\n{\n\tbool mode = IsRepairMode;\n\tswitch (control) {\n\t\tcase 0:\n\t\t\tmode = false;\n\t\t\tbreak;\n\n\t\tcase -1:\n\t\t\tmode = (IsRepairMode == false);\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tmode = true;\n\t\t\tbreak;\n\t}\n\n\tif (mode != IsRepairMode && !PendingObject) {\n\t\tIsSellMode = false;\n\t\tif (mode && PlayerPtr->BScan) {\n\t\t\tIsRepairMode = true;\n\t\t\tUnselect_All();\n\t\t} else {\n\t\t\tIsRepairMode = false;\n\t\t\tRevert_Mouse_Shape();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::In_View -- Determines if cell is visible on screen.                           *\n *                                                                                             *\n *    Use this routine to determine if the specified cell is visible on                        *\n *    the display. This is a useful fact, since many display operations                        *\n *    can be skipped if the cell is not visible.                                               *\n *                                                                                             *\n * INPUT:   cell  -- The cell number to check.                                                 *\n *                                                                                             *\n * OUTPUT:  bool; Is this cell visible on the display?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/30/1994 JLB : Created.                                                                 *\n *   04/30/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nbool DisplayClass::In_View(register CELL cell) const\n{\n\tif (cell & 0xC000) return(false);\n\n\tCOORDINATE coord = Coord_Whole(Cell_Coord(cell));\n\tCOORDINATE tcoord = Coord_Whole(TacticalCoord);\n\n\tif ((unsigned)(Coord_X(coord) - Coord_X(tcoord)) > TacLeptonWidth+CELL_LEPTON_W-1) return(false);\n\tif ((unsigned)(Coord_Y(coord) - Coord_Y(tcoord)) > TacLeptonHeight+CELL_LEPTON_H-1) return(false);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Closest_Free_Spot -- Finds the closest cell sub spot that is free.            *\n *                                                                                             *\n *    Use this routine to find the sub cell spot closest to the coordinate specified that is   *\n *    free from occupation. Typical use of this is for infantry destination calculation.       *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to use as the starting point when finding the closest      *\n *                   free spot.                                                                *\n *                                                                                             *\n *          any   -- Ignore occupation and just return the closest sub cell spot?              *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate of the closest free (possibly) sub cell location.      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE DisplayClass::Closest_Free_Spot(COORDINATE coord, bool any) const\n{\n\tif (coord & HIGH_COORD_MASK) {\n\t\treturn(0x00800080);\n\t}\n\treturn Map[coord].Closest_Free_Spot(coord, any);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Is_Spot_Free -- Determines if cell sub spot is free of occupation.            *\n *                                                                                             *\n *    Use this routine to determine if the coordinate (rounded to the nearest sub cell         *\n *    position) is free for placement. Typical use of this would be for infantry placement.    *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to examine for \"freeness\". The coordinate is rounded to    *\n *          the nearest free sub cell spot.                                                    *\n *                                                                                             *\n * OUTPUT:  Is the sub spot indicated by the coordinate free from previous occupation?         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool DisplayClass::Is_Spot_Free(COORDINATE coord) const\n{\n\tif (coord & HIGH_COORD_MASK) {\n\t\treturn(0x00800080);\n\t}\n\treturn Map[coord].Is_Spot_Free(CellClass::Spot_Index(coord));\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Center_Map -- Centers the map about the currently selected objects            *\n *                                                                                             *\n *    This routine will average the position of all the selected objects and then center       *\n *    the map about those objects.                                                             *\n *                                                                                             *\n * INPUT:   center   -- The is an optional center about override coordinate. If specified,     *\n *                      then the map will be centered about that coordinate. Otherwise it      *\n *                      will center about the average location of all selected objects.        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The map position changes by this routine.                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/22/1995 JLB : Created.                                                                 *\n *   09/16/1996 JLB : Takes coordinate to center about (as override).                          *\n *=============================================================================================*/\nvoid DisplayClass::Center_Map(COORDINATE center)\n{\n \tint x = 0;\n//\tunsigned x = 0;\n \tint y = 0;\n//\tunsigned y = 0;\n\tbool centerit = false;\n\n\tif (CurrentObject.Count()) {\n\n\t\tfor (int index = 0; index < CurrentObject.Count(); index++) {\n\t\t\tCOORDINATE coord = CurrentObject[index]->Center_Coord();\n\n\t\t\tx += Coord_X(coord);\n\t\t\ty += Coord_Y(coord);\n\t\t}\n\n\t\tx /= CurrentObject.Count();\n\t\ty /= CurrentObject.Count();\n\t\tcenterit = true;\n\t}\n\n\tif (center != 0L) {\n\t\tx = Coord_X(center);\n\t\ty = Coord_Y(center);\n\t\tcenterit = true;\n\t}\n\n\tif (centerit) {\n\t\tx = x - (int)TacLeptonWidth/2;\n\t\tif (x < Cell_To_Lepton(MapCellX)) x = Cell_To_Lepton(MapCellX);\n\n\t\ty = y - (int)TacLeptonHeight/2;\n\t\tif (y < Cell_To_Lepton(MapCellY)) y = Cell_To_Lepton(MapCellY);\n\n\t\tSet_Tactical_Position(XY_Coord(x, y));\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Encroach_Shadow -- Causes the shadow to creep back by one cell.               *\n *                                                                                             *\n *    This routine will cause the shadow to creep back by one cell. Multiple calls to this     *\n *    routine will result in the shadow becoming more and more invasive until only the sight   *\n *    range of player controlled units will keep the shadow pushed back.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Encroach_Shadow(void)\n{\n\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tif (!In_Radar(cell)) continue;\n\n\t\tCellClass * cellptr = &(*this)[cell];\n\t\tif (cellptr->IsVisible || !cellptr->IsMapped) continue;\n\n\t\tcellptr->IsToShroud = true;\n\t}\n\n\t/*\n\t**\tMark all shadow edge cells to be fully shrouded. All adjacent mapped\n\t**\tcell should become partially shrouded.\n\t*/\n\tfor (cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tif (!In_Radar(cell)) continue;\n\n\t\tif ((*this)[cell].IsToShroud) {\n\t\t\t(*this)[cell].IsToShroud = false;\n\t\t\tShroud_Cell(cell);\n\t\t}\n\t}\n\n\tAll_To_Look();\n\n\tFlag_To_Redraw(true);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Shroud_Cell -- Returns the specified cell into the shrouded condition.        *\n *                                                                                             *\n *    This routine is called to add the shroud back to the cell specified. Typical of this     *\n *    would be when the shroud is to regenerate.                                               *\n *                                                                                             *\n * INPUT:   cell  -- The cell that the shroud is to be regenerated upon.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Adjacent cells might be affected by this routine. The affect is determined      *\n *             according to the legality of the partial shadow artwork. In the illegal cases   *\n *             the adjacent cell might become shrouded as well.                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 JLB : Created.                                                                 *\n *   06/17/1996 JLB : Modified to handle the new shadow pieces.                                *\n *=============================================================================================*/\nvoid DisplayClass::Shroud_Cell(CELL cell/*KO, bool shadeit*/)\n{\n\tif (PlayerPtr->IsGPSActive) {\n\t\tif ( (*this)[cell].Jammed & (1 << PlayerPtr->Class->House)  ) {\n\t\t\treturn;\n\t\t}\n\t}\n\tif (!In_Radar(cell)) return;\n\n\tCellClass * cellptr = &(*this)[cell];\n\tif (cellptr->IsMapped) {\n\n\t\tcellptr->IsMapped = false;\n\t\tcellptr->IsVisible = false;\n\t\tcellptr->Redraw_Objects();\n\n\t\t/*\n\t\t**\tCheck adjacent cells. There might be some weird combination of\n\t\t**\tshrouded cells such that more cells must be shrouded in order for\n\t\t**\tthis to work.\n\t\t*/\n\t\tfor (FacingType dir = FACING_FIRST; dir < FACING_COUNT; dir++) {\n\t\t\tCELL c = Adjacent_Cell(cell, dir);\n\t\t\tCellClass * cptr = &(*this)[c];\n\n\t\t\t/*\n\t\t\t**\tIf this adjacent cell must be completely shrouded as a result\n\t\t\t**\tof the map change, yet it isn't already shrouded, then recursively\n\t\t\t**\tshroud that cell.\n\t\t\t*/\n\t\t\tif (c != cell) {\n\t\t\t\tcptr->IsVisible = false;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAlways redraw the cell because, more than likely, the shroud\n\t\t\t**\tedge will change shape because of the map change.\n\t\t\t*/\n\t\t\tcptr->Redraw_Objects();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Read_INI -- Reads map control data from INI file.                             *\n *                                                                                             *\n *    This routine is used to read the map control data from the INI                           *\n *    file.                                                                                    *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the loaded INI file data.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The TriggerClass INI data must have been read before calling this function.     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Read_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tRead the map dimensions.\n\t*/\n\tchar const * const name = \"Map\";\n\tint x = ini.Get_Int(name, \"X\", 1);\n\tint y = ini.Get_Int(name, \"Y\", 1);\n\tint w = ini.Get_Int(name, \"Width\", MAP_CELL_W-2);\n\tint h = ini.Get_Int(name, \"Height\", MAP_CELL_H-2);\n\n#ifndef FIXIT_VERSION_3\t\t//\tMap size no longer restricted.\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw\n\tif(Session.Type >= GAME_MODEM && Session.Type <= GAME_INTERNET && PlayingAgainstVersion < VERSION_AFTERMATH_CS) {\n\t\t/*\n\t\t**\tHACK ALERT:\n\t\t**\tForce the map to be limited to the size that 96x96 would be. If the\n\t\t**\tsize is greater (due to hacking?) then shrink it down to legal size.\n\t\t** BG Note: only do this for multiplayer games against non-AfterMath.\n\t\t*/\n\t\tif (w * h > 96 * 96) {\n\t\t\th -= (((w*h) - (96*96)) / w) + 1;\n\t\t}\n\t}\n#else\n\t/*\n\t**\tHACK ALERT:\n\t**\tForce the map to be limited to the size that 96x96 would be. If the\n\t**\tsize is greater (due to hacking?) then shrink it down to legal size.\n\t*/\n\tif (w * h > 96 * 96) {\n\t\th -= (((w*h) - (96*96)) / w) + 1;\n\t}\n#endif\n\n#endif\t//\t!FIXIT_VERSION_3\n\n\tSet_Map_Dimensions( x, y, w, h );\n\n\t/*\n\t**\tThe theater is determined at this point. There is specific data that\n\t**\tis custom to this data. Load the custom data (as it related to terrain)\n\t**\tat this point.\n\t*/\n\tScen.Theater = ini.Get_TheaterType(name, \"Theater\", THEATER_TEMPERATE);\n\n\t/*\n\t** Remove any old theater specific uncompressed shapes\n\t*/\n#ifdef WIN32\n\tif (Scen.Theater != LastTheater) {\n\t\tReset_Theater_Shapes();\n\t}\n#endif\t//WIN32\n\n\t/*\n\t**\tNow that the theater is known, init the entire map hierarchy\n\t*/\n\tInit(Scen.Theater);\n\n\t/*\n\t**\tSpecial initializations occur when the theater is known.\n\t*/\n\tTerrainTypeClass::Init(Scen.Theater);\n\tTemplateTypeClass::Init(Scen.Theater);\n\tOverlayTypeClass::Init(Scen.Theater);\n\tUnitTypeClass::Init(Scen.Theater);\n\tInfantryTypeClass::Init(Scen.Theater);\n\tBuildingTypeClass::Init(Scen.Theater);\n\tBulletTypeClass::Init(Scen.Theater);\n\tAnimTypeClass::Init(Scen.Theater);\n\tAircraftTypeClass::Init(Scen.Theater);\n\tVesselTypeClass::Init(Scen.Theater);\n\tSmudgeTypeClass::Init(Scen.Theater);\n\n\t/*\n\t**\tRead the Waypoint entries.\n\t*/\n\tfor (int i = 0; i < WAYPT_COUNT; i++) {\n\t\tchar buf[20];\n\t\tsprintf(buf, \"%d\", i);\n\t\tScen.Waypoint[i] = ini.Get_Int(\"Waypoints\", buf, -1);\n\n\t\tif (Scen.Waypoint[i] != -1) {\n\t\t\t(*this)[Scen.Waypoint[i]].IsWaypoint = 1;\n\t\t}\n\t}\n\n\t/*\n\t**\tSet the starting position (do this after Init(), which clears the cells'\n\t**\tIsWaypoint flags).\n\t*/\n\tif (Scen.Waypoint[WAYPT_HOME] == -1) {\n\t\tScen.Waypoint[WAYPT_HOME] = XY_Cell(MapCellX + 5*RESFACTOR, MapCellY + 4*RESFACTOR);\n\t}\n\n\tScen.Views[0] = Scen.Views[1] = Scen.Views[2] = Scen.Views[3] = Scen.Waypoint[WAYPT_HOME];\n\tSet_Tactical_Position(Cell_Coord((Scen.Waypoint[WAYPT_HOME] - (MAP_CELL_W * 4 * RESFACTOR)) - (5*RESFACTOR)));\n\n\t/*\n\t**\tLoop through all CellTrigger entries.\n\t*/\n\tint len = ini.Entry_Count(\"CellTriggers\");\n\tfor (int index = 0; index < len; index++) {\n\n\t\t/*\n\t\t**\tGet a cell trigger and cell assignment.\n\t\t*/\n\t\tchar const * cellentry = ini.Get_Entry(\"CellTriggers\", index);\n\t\tTriggerTypeClass * tp = ini.Get_TriggerType(\"CellTriggers\", cellentry);\n\t\tCELL cell = atoi(cellentry);\n\n\t\tif (tp != NULL && !(*this)[cell].Trigger.Is_Valid()) {\n\t\t\tTriggerClass * tt = Find_Or_Make(tp);\n\t\t\tif (tt) {\n\t\t\t\ttt->AttachCount++;\n\t\t\t\ttt->Cell = cell;\n\t\t\t\t(*this)[cell].Trigger = tt;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tRead the map template data.\n\t*/\n\tstatic char const * const MAPPACK = \"MapPack\";\n\tlen = ini.Get_UUBlock(MAPPACK, _staging_buffer, sizeof(_staging_buffer));\n\tBufferStraw bstraw(_staging_buffer, len);\n\tMap.Read_Binary(bstraw);\n\n\tLastTheater = Scen.Theater;\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Write_INI -- Write the map data to the INI file specified.                    *\n *                                                                                             *\n *    This routine will output all the data of this map to the INI database specified.         *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI handler to store the map data to.                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Any existing map data in the INI database will be replaced by this function.    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Write_INI(CCINIClass & ini)\n{\n\tchar entry[20];\n\n\t/*\n\t**\tSave the map parameters.\n\t*/\n\tstatic char const * const NAME = \"Map\";\n\tini.Clear(NAME);\n\tini.Put_TheaterType(NAME, \"Theater\", Scen.Theater);\n\tini.Put_Int(NAME, \"X\", MapCellX);\n\tini.Put_Int(NAME, \"Y\", MapCellY);\n\tini.Put_Int(NAME, \"Width\", MapCellWidth);\n\tini.Put_Int(NAME, \"Height\", MapCellHeight);\n\n\t/*\n\t**\tSave the Waypoint entries.\n\t*/\n\tstatic char const * const WAYNAME = \"Waypoints\";\n\tini.Clear(WAYNAME);\n\tfor (int i = 0; i < WAYPT_COUNT; i++) {\n\t\tif (Scen.Waypoint[i] != -1) {\n\t\t\tsprintf(entry, \"%d\", i);\n\t\t\tini.Put_Int(WAYNAME, entry, Scen.Waypoint[i]);\n\t\t}\n\t}\n\n\t/*\n\t**\tSave the cell's triggers.\n\t*/\n\tstatic char const * const CELLTRIG = \"CellTriggers\";\n\tini.Clear(CELLTRIG);\n\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tif ((*this)[cell].Trigger.Is_Valid()) {\n\t\t\tTriggerClass * tp = (*this)[cell].Trigger;\n\t\t\tif (tp != NULL) {\n\n\t\t\t\t/*\n\t\t\t\t**\tGenerate entry name.\n\t\t\t\t*/\n\t\t\t\tsprintf(entry, \"%d\", cell);\n\n\t\t\t\t/*\n\t\t\t\t**\tSave entry.\n\t\t\t\t*/\n\t\t\t\tini.Put_TriggerType(CELLTRIG, entry, tp->Class);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tWrite the map template data out to the ini file.\n\t*/\n\tstatic char const * const MAPPACK = \"MapPack\";\n\tBufferPipe bpipe(_staging_buffer, sizeof(_staging_buffer));\n\tint len = Map.Write_Binary(bpipe);\n\tini.Clear(MAPPACK);\n\tif (len) {\n\t\tini.Put_UUBlock(MAPPACK, _staging_buffer, len);\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::All_To_Look -- Direct all objects to look around for the player.              *\n *                                                                                             *\n *    This routine will scan through all objects and tell them to look if they are supposed    *\n *    to be able to reveal the map for the player. This routine may be necessary in cases      *\n *    of gap generator reshroud logic.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::All_To_Look(bool units_only)\n{\n\tfor (int index = 0; index < Layer[LAYER_GROUND].Count(); index++) {\n\t\tObjectClass * object = Layer[LAYER_GROUND][index];\n\t\tif (object != NULL && object->Is_Techno()) {\n\t\t\tTechnoClass * tech = ((TechnoClass *)object);\n\n\t\t\tif (tech->What_Am_I() == RTTI_BUILDING && units_only) continue;\n\n\t\t\tif (tech->House->IsPlayerControl) {\n\t\t\t\tif (tech->IsDiscoveredByPlayer) {\n\t\t\t\t\tobject->Look();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (tech->What_Am_I() == RTTI_BUILDING && Rule.IsAllyReveal && tech->House->Is_Ally(PlayerPtr)) {\n\t\t\t\t\ttech->Look();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nvoid DisplayClass::Constrained_Look(COORDINATE center, LEPTON distance)\n{\n\tfor (int index = 0; index < Layer[LAYER_GROUND].Count(); index++) {\n\t\tObjectClass * object = Layer[LAYER_GROUND][index];\n\t\tif (object != NULL && object->Is_Techno()) {\n\t\t\tTechnoClass * tech = ((TechnoClass *)object);\n\n//\t\t\tif (tech->What_Am_I() == RTTI_BUILDING && units_only) continue;\n\n\t\t\tif (tech->House->IsPlayerControl) {\n\t\t\t\tif (tech->IsDiscoveredByPlayer && Distance(tech->Center_Coord(), center) <= (tech->Techno_Type_Class()->SightRange * CELL_LEPTON_W) + distance) {\n\t\t\t\t\tobject->Look();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (tech->What_Am_I() == RTTI_BUILDING && Rule.IsAllyReveal && tech->House->Is_Ally(PlayerPtr) &&\n\t\t\t\t\tDistance(tech->Center_Coord(), center) <= (tech->Techno_Type_Class()->SightRange * CELL_LEPTON_W) + distance) {\n\n\t\t\t\t\ttech->Look();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Flag_Cell -- Flag the specified cell to be redrawn.                           *\n *                                                                                             *\n *    This will flag the cell to be redrawn.                                                   *\n *                                                                                             *\n * INPUT:   cell  -- The cell to be flagged.                                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Flag_Cell(CELL cell)\n{\n\tFlag_To_Redraw(false);\n\tIsToRedraw = true;\n\tCellRedraw[cell] = true;\n}\n"
  },
  {
    "path": "CODE/DISPLAY.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/DISPLAY.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DISPLAY.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 1, 1994                                                  *\n *                                                                                             *\n *                  Last Update : May 1, 1994   [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef DISPLAY_H\n#define DISPLAY_H\n\n#include\t\"map.h\"\n#include\t\"layer.h\"\n\n\n#define\tICON_PIXEL_W\t \t\t24\n#define\tICON_PIXEL_H\t\t\t24\n#define\tICON_LEPTON_W\t\t\t256\n#define\tICON_LEPTON_H\t\t\t256\n#define\tCELL_PIXEL_W\t \t\tICON_PIXEL_W\n#define\tCELL_PIXEL_H\t\t\tICON_PIXEL_H\n#define\tCELL_LEPTON_W\t\t\tICON_LEPTON_W\n#define\tCELL_LEPTON_H\t\t\tICON_LEPTON_H\n\n//\t-----------------------------------------------------------\n#define\tPIXEL_LEPTON_W\t\t\t(ICON_LEPTON_W/ICON_PIXEL_W)\n#define\tPIXEL_LEPTON_H\t\t\t(ICON_LEPTON_H/ICON_PIXEL_H)\n\n#define\tSIDE_BAR_TAC_WIDTH\t10\n#define  SIDE_BAR_TAC_HEIGHT\t8\n\nextern COORDINATE Coord_Add(COORDINATE coord1, COORDINATE coord2);\n\nclass DisplayClass: public MapClass\n{\n\tpublic:\n\n\t\t/*\n\t\t** The tactical map display position is indicated by the cell of the\n\t\t**\tupper left hand corner. These should not be altered directly. Use\n\t\t**\tthe Set_Tactical_Position function instead.\n\t\t*/\n\t\tCOORDINATE TacticalCoord;\n\n\t\t/*\n\t\t**\tThe dimensions (in cells) of the visible window onto the game map. This tactical\n\t\t**\tmap is how the player interacts and views the game world.\n\t\t*/\n\t\tLEPTON TacLeptonWidth;\n\t\tLEPTON TacLeptonHeight;\n\n\t\t/*\n\t\t**\tThese layer control elements are used to group the displayable objects\n\t\t**\tso that proper overlap can be obtained.\n\t\t*/\n\t\tstatic LayerClass Layer[LAYER_COUNT];\n\n\t\t/*\n\t\t**\tThis records the position and shape of a placement cursor to display\n\t\t**\tover the map. This cursor is used when placing buildings and also used\n\t\t**\textensively by the scenario editor.\n\t\t*/\n\t\tCELL ZoneCell;\n\t\tshort ZoneOffset;\n\t\tshort const *CursorSize;\n\t\tbool ProximityCheck;\t\t// Is proximity check ok?\n\n\t\t/*\n\t\t** This holds the building type that is about to be placed upon the map.\n\t\t**\tIt is only valid during the building placement state. The PendingLegal\n\t\t**\tflag is updated as the cursor moves and it reflects the legality of\n\t\t**\tplacing the building at the desired location.\n\t\t*/\n\t\tObjectClass * PendingObjectPtr;\n\t\tObjectTypeClass const * PendingObject;\n\t\tHousesType PendingHouse;\n\n\t\tstatic unsigned char FadingBrighten[256];\n\t\tstatic unsigned char FadingShade[256];\n\t\tstatic unsigned char FadingWayDark[256];\n\t\tstatic unsigned char FadingLight[256];\n\t\tstatic unsigned char FadingGreen[256];\n\t\tstatic unsigned char FadingYellow[256];\n\t\tstatic unsigned char FadingRed[256];\n\t\tstatic unsigned char TranslucentTable[(MAGIC_COL_COUNT+1)*256];\n\t\tstatic unsigned char WhiteTranslucentTable[(1+1)*256];\n\t\tstatic unsigned char MouseTranslucentTable[(4+1)*256];\n\t\tstatic void const *TransIconset;\n\t\tstatic unsigned char UnitShadow[(USHADOW_COL_COUNT+1)*256];\n\t\tstatic unsigned char UnitShadowAir[(USHADOW_COL_COUNT+1)*256];\n\t\tstatic unsigned char SpecialGhost[2*256];\n\n\t\t//-------------------------------------------------------------------------\n\t\tDisplayClass(void);\n\t\tDisplayClass(NoInitClass const & x) : MapClass(x) {};\n\n\t\tvirtual void Read_INI(CCINIClass & ini);\n\t\tvoid Write_INI(CCINIClass & ini);\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t\t// One-time inits\n\t\tvirtual void Init_Clear(void);\t\t\t\t\t\t// Clears all to known state\n\t\tvirtual void Init_IO(void);\t\t\t\t\t\t\t// Inits button list\n\t\tvirtual void Init_Theater(TheaterType theater);\t// Theater-specific inits\n\n\t\t/*\n\t\t**\tGeneral display/map/interface support functionality.\n\t\t*/\n\t\tvirtual void AI(KeyNumType &input, int x, int y);\n\t\tvirtual void Draw_It(bool complete=false);\n\n\t\t/*\n\t\t**\tAdded functionality.\n\t\t*/\n\t\tvoid All_To_Look(bool units_only=false);\n\t\tvoid Constrained_Look(COORDINATE coord, LEPTON distance);\n\t\tvoid Shroud_Cell(CELL cell/*KO, bool shadeit = false*/);\n\t\tvoid Encroach_Shadow(void);\n\t\tvoid Center_Map(COORDINATE center=0L);\n\t\tvirtual bool Map_Cell(CELL cell, HouseClass *house);\n\t\tvirtual CELL Click_Cell_Calc(int x, int y) const;\n\t\tvirtual void Help_Text(int , int =-1, int =-1, int =YELLOW, bool =false) {};\n\t\tvirtual MouseType Get_Mouse_Shape(void) const = 0;\n\t\tvirtual bool Scroll_Map(DirType facing, int & distance, bool really);\n\t\tvirtual void Refresh_Cells(CELL cell, short const *list);\n\t\tvirtual void Set_View_Dimensions(int x, int y, int width=-1, int height=-1);\n\n\t\t/*\n\t\t**\tPending object placement control.\n\t\t*/\n\t\tvirtual void Put_Place_Back(TechnoClass * ) {}; // Affects 'pending' system.\n\t\tvoid Cursor_Mark(CELL pos, bool on);\n\t\tvoid Set_Cursor_Shape(short const * list);\n\t\tCELL Set_Cursor_Pos(CELL pos = -1);\n\t\tvoid Get_Occupy_Dimensions(int & w, int & h, short const *list) const;\n\n\t\t/*\n\t\t**\tTactical map only functionality.\n\t\t*/\n\t\tvirtual void Set_Tactical_Position(COORDINATE coord);\n\t\tvoid Refresh_Band(void);\n\t\tvoid Select_These(COORDINATE coord1, COORDINATE coord2);\n\t\tCOORDINATE Pixel_To_Coord(int x, int y) const;\n\t\tbool Coord_To_Pixel(COORDINATE coord, int & x, int & y) const;\n\t\tbool Push_Onto_TacMap(COORDINATE &source, COORDINATE &dest);\n\t\tvoid Remove(ObjectClass const * object, LayerType layer);\n\t\tvoid Submit(ObjectClass const * object, LayerType layer);\n\t\tCELL Calculated_Cell(SourceType dir, WAYPOINT waypoint=-1, CELL cell=-1, SpeedType loco=SPEED_FOOT, bool zonecheck=true, MZoneType mzone=MZONE_NORMAL) const;\n\t\tbool In_View(register CELL cell) const;\n\t\tbool Passes_Proximity_Check(ObjectTypeClass const * object, HousesType house, short const * list, CELL trycell) const;\n\t\tObjectClass * Cell_Object(CELL cell, int x=0, int y=0) const;\n\t\tObjectClass * Next_Object(ObjectClass * object) const;\n\t\tObjectClass * Prev_Object(ObjectClass * object) const;\n\t\tint Cell_Shadow(CELL cell) const;\n\t\tshort const * Text_Overlap_List(char const * text, int x, int y) const;\n\t\tbool Is_Spot_Free(COORDINATE coord) const;\n\t\tCOORDINATE Closest_Free_Spot(COORDINATE coord, bool any=false) const;\n\t\tvoid Sell_Mode_Control(int control);\n\t\tvoid Repair_Mode_Control(int control);\n\n\t\tvirtual void Flag_Cell(CELL cell);\n\t\tbool Is_Cell_Flagged(CELL cell) const {return CellRedraw.Is_True(cell);};\n\n\t\t/*\n\t\t** Computes starting position based on player's units' Coords.\n\t\t*/\n\t\tvoid Compute_Start_Pos(void);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n\n\tprotected:\n\t\tvirtual void Mouse_Right_Press(void);\n\t\tvirtual void Mouse_Left_Press(int x, int y);\n\t\tvirtual void Mouse_Left_Up(CELL cell, bool shadow, ObjectClass * object, ActionType action, bool wsmall = false);\n\t\tvirtual void Mouse_Left_Held(int x, int y);\n\t\tvirtual void Mouse_Left_Release(CELL cell, int x, int y, ObjectClass * object, ActionType action, bool wsmall = false);\n\n\tpublic:\n\t\t/*\n\t\t**\tThis is the pixel offset for the upper left corner of the tactical map.\n\t\t*/\n\t\tint TacPixelX;\n\t\tint TacPixelY;\n\n\t\t/*\n\t\t**\tThis is the coordinate that the tactical map should be in at next available opportunity.\n\t\t*/\n\t\tCOORDINATE DesiredTacticalCoord;\n\n\t\t/*\n\t\t**\tIf something in the tactical map is to be redrawn, this flag is set to true.\n\t\t*/\n\t\tunsigned IsToRedraw:1;\n\n\t\t/*\n\t\t**\tIf the player is currently wielding a wrench (to select buildings for repair),\n\t\t**\tthen this flag is true. In such a state, normal movement and combat orders\n\t\t**\tare preempted.\n\t\t*/\n\t\tunsigned IsRepairMode:1;\n\n\t\t/*\n\t\t**\tIf the player is currently in \"sell back\" mode, then this flag will be\n\t\t**\ttrue. While in this mode, anything clicked on will be sold back to the\n\t\t**\t\"factory\".\n\t\t*/\n\t\tunsigned IsSellMode:1;\n\n\t\t/*\n\t\t**\tIf the player is currently in ion cannon targeting mode, then this\n\t\t** flag will be true.  While in this mode, anything clicked on will be\n\t\t** be destroyed by the ION cannon.\n\t\t*/\n\t\tSpecialWeaponType IsTargettingMode;\n\n\tprotected:\n\n\t\t/*\n\t\t**\tIf it is currently in rubber band mode (multi unit selection), then this\n\t\t**\tflag will be true. While in such a mode, normal input is preempted while\n\t\t**\tthe extended selection is in progress.\n\t\t*/\n\t\tunsigned IsRubberBand:1;\n\n\t\t/*\n\t\t**\tThe moment the mouse is held down, this flag gets set. If the mouse is dragged\n\t\t**\ta sufficient distance while held down, then true rubber band mode selection\n\t\t**\tcan begin. Using a minimum distance prevents accidental rubber band selection\n\t\t**\tmode from being initiated.\n\t\t*/\n\t\tunsigned IsTentative:1;\n\n\t\t/*\n\t\t**\tThis gadget class is used for capturing input to the tactical map. All mouse input\n\t\t**\twill be routed through this gadget.\n\t\t*/\n\t\tclass TacticalClass : public GadgetClass {\n\t\t\tpublic:\n\t\t\t\tTacticalClass(void) : GadgetClass(0,0,0,0,LEFTPRESS|LEFTRELEASE|LEFTHELD|LEFTUP|RIGHTPRESS,true) {};\n\n\t\t\tprotected:\n\t\t\t\tvirtual int Action(unsigned flags, KeyNumType & key);\n\t\t};\n\t\tfriend class TacticalClass;\n\n\t\t/*\n\t\t**\tThis is the \"button\" that tracks all input to the tactical map.\n\t\t** It must be available to derived classes, for Save/Load purposes.\n\t\t*/\n\t\tstatic TacticalClass TacButton;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is a utility flag that is set during the icon draw process only if there\n\t\t**\twas at least one shadow icon detected that should be redrawn. When the shadow\n\t\t**\tdrawing logic is to take place, but this flag is false, then the shadow drawing\n\t\t**\twill be skipped since it would perform no function.\n\t\t*/\n\t\tunsigned IsShadowPresent:1;\n\n\t\t/*\n\t\t**\tRubber band mode consists of stretching a box from the anchor point (specified\n\t\t**\there) to the current cursor position.\n\t\t*/\n\t\tint BandX,BandY;\n\t\tint NewX,NewY;\n\n\t\tstatic void const *ShadowShapes;\n\t\tstatic unsigned char ShadowTrans[(SHADOW_COL_COUNT+1)*256];\n\n\t\tvoid Redraw_Icons(void);\n\t\tvoid Redraw_OIcons(void);\n\t\tvoid Redraw_Shadow(void);\n\n\t\t/*\n\t\t**\tThis bit array is used to flag cells to be redrawn. If the icon needs to\n\t\t**\tbe redrawn for a cell, then the corresponding flag will be true.\n\t\t*/\n\t\tstatic BooleanVectorClass CellRedraw;\n\n\t\tbool Good_Reinforcement_Cell(CELL outcell, CELL incell, SpeedType loco, int zone, MZoneType mzone) const;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/DOOR.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/DOOR.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DOOR.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/11/95                                                     *\n *                                                                                             *\n *                  Last Update : June 14, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   DoorClass::AI -- Handles the door processing logic.                                       *\n *   DoorClass::Close_Door -- Try to close the unit's door.                                    *\n *   DoorClass::DoorClass -- Constructor for the DoorClass object.                             *\n *   DoorClass::Door_Stage -- Fetches the current door animation frame.                        *\n *   DoorClass::Open_Door -- Opens the door for this unit.                                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * DoorClass::DoorClass -- Constructor for the DoorClass object.                               *\n *                                                                                             *\n *    This constructor sets the door to an initial closed state.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/14/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nDoorClass::DoorClass(void)\n{\n\tState = IS_CLOSED;\n\tIsToRedraw = false;\n\tStages = 0;\n}\n\n\n/***********************************************************************************************\n * DoorClass::AI -- Handles the door processing logic.                                         *\n *                                                                                             *\n *    This routine should be called every game frame. It handles the door closing and opening  *\n *    logic.                                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DoorClass::AI(void)\n{\n\tif (Control.Graphic_Logic()) {\n\t\tif (Control.Fetch_Stage() >= Stages) {\n\t\t\tControl.Set_Rate(0);\n\t\t\tswitch (State) {\n\t\t\t\tcase IS_OPENING:\n\t\t\t\t\tState = IS_OPEN;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase IS_CLOSING:\n\t\t\t\t\tState = IS_CLOSED;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tIsToRedraw = true;\n\t}\n}\n\n\n/***********************************************************************************************\n * DoorClass::Open_Door -- Opens the door for this unit.                                       *\n *                                                                                             *\n *    This routine will perform the door open operation for this unit. It will control vehicle *\n *    rotation if necessary.                                                                   *\n *                                                                                             *\n * INPUT:   rate     -- The animation rate (delay) to use for the door animation logic.        *\n *                                                                                             *\n *          stages   -- The number of animations stages that this door must pass through.      *\n *                                                                                             *\n * OUTPUT:  Was action initiated to open the door?                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool DoorClass::Open_Door(int rate, int stages)\n{\n\tswitch (State) {\n\t\tcase IS_CLOSED:\n\t\tcase IS_CLOSING:\n\t\t\tState = IS_OPENING;\n\t\t\tStages = stages-1;\n\t\t\tControl.Set_Stage(0);\n\t\t\tControl.Set_Rate(rate);\n\t\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * DoorClass::Close_Door -- Try to close the unit's door.                                      *\n *                                                                                             *\n *    This routine will attempt to close the unit's door. If the door is already closed or     *\n *    in the process of closing, then no action is performed.                                  *\n *                                                                                             *\n * INPUT:   rate     -- The animation rate (delay) to use for the door animation logic.        *\n *                                                                                             *\n *          stages   -- The number of animations stages that this door must pass through.      *\n *                                                                                             *\n * OUTPUT:  Action was initiated to close the door?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool DoorClass::Close_Door(int rate, int stages)\n{\n\tswitch (State) {\n\t\tcase IS_OPEN:\n\t\tcase IS_OPENING:\n\t\t\tState = IS_CLOSING;\n\t\t\tStages = stages-1;\n\t\t\tControl.Set_Stage(0);\n\t\t\tControl.Set_Rate(rate);\n\t\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * DoorClass::Door_Stage -- Fetches the current door animation frame.                          *\n *                                                                                             *\n *    Use this routine to fetch the current door animation frame number. Frame zero is the     *\n *    closed frame and frame 'N' is the open frame. If the door is in the process of opening   *\n *    or closing, the appropriate frame number is used. 'N' is defined as the number of        *\n *    stages in the animation minus 1 (e.g., a four frame animation will return a door stage   *\n *    number between 0 and 3, inclusive).                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the door animation frame number.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/14/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint DoorClass::Door_Stage(void) const\n{\n\tswitch (State) {\n\t\tcase IS_CLOSING:\n\t\t\treturn((Stages-1) - Control.Fetch_Stage());\n\n\t\tcase IS_CLOSED:\n\t\t\treturn(0);\n\n\t\tcase IS_OPENING:\n\t\t\treturn(Control.Fetch_Stage());\n\n\t\tcase IS_OPEN:\n\t\t\treturn(Stages-1);\n\t}\n\treturn(0);\n}\n"
  },
  {
    "path": "CODE/DOOR.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/DOOR.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DOOR.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/11/95                                                     *\n *                                                                                             *\n *                  Last Update : June 11, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef DOOR_H\n#define DOOR_H\n\nclass DoorClass\n{\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is the animation control handler.\n\t\t*/\n\t\tStageClass Control;\n\n\t\t/*\n\t\t**\tThis is the recorded number of stages of the current\n\t\t**\tdoor animation process.\n\t\t*/\n\t\tunsigned char Stages;\n\n\t\t/*\n\t\t**\tThis is the door state.\n\t\t*/\n\t\tenum {\n\t\t\tIS_CLOSED,\t\t// Door is closed.\n\t\t\tIS_OPENING,\t\t// Door is in the process of opening.\n\t\t\tIS_OPEN,\t\t\t// Door is fully open.\n\t\t\tIS_CLOSING\t\t//\tDoor is in the process of closing.\n\t\t} State;\n\n\t\t/*\n\t\t**\tIf the animation for this door indicates that the object it is\n\t\t**\tattached to should be redrawn, then this flag will be true.\n\t\t*/\n\t\tunsigned IsToRedraw:1;\n\n\tpublic:\n\t\tDoorClass(void);\n\t\tDoorClass(NoInitClass const & x) : Control(x) {};\n\n\t\tbool Time_To_Redraw(void) {return(IsToRedraw);};\n\t\tvoid Clear_Redraw_Flag(void) {IsToRedraw = false;};\n\t\tvoid AI(void);\n\t\tint Door_Stage(void) const;\n\t\tbool Is_Door_Opening(void) const {return(State == IS_OPENING);};\n\t\tbool Is_Door_Closing(void) const {return(State == IS_CLOSING);};\n\t\tbool Open_Door(int rate, int stages);\n\t\tbool Close_Door(int rate, int stages);\n\t\tbool Is_Door_Open(void) const {return(State == IS_OPEN);};\n\t\tbool Is_Door_Closed(void) const {return(State == IS_CLOSED);};\n\t\tbool Is_Ready_To_Open(void) const;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/DPMI.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\dpmi.cpv   4.41   04 Jul 1996 16:12:42   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DPMI.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 2, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 2, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifdef __FLAT__\n#pragma inline\n#endif\n\n//#include\t\"function.h\"\n#include \"dpmi.h\"\n\n#ifndef __FLAT__\n\nvoid DOSSegmentClass::Swap(DOSSegmentClass &src, int soffset, DOSSegmentClass &dest, int doffset, int size)\n{\n\tif (!size) return;\n\n\tunsigned short ssel = src.Selector;\n\tunsigned short dsel = dest.Selector;\n\n\tasm {\n\t\tpush\tes\n\t\tpush\tds\n\n\t\tmov\tsi,soffset\n\t\tmov\tdi,doffset\n\t\tmov\tcx,size\n\t\tmov\tax,ssel\n\t\tmov\tdx,dsel\n\t\tmov\tds,ax\n\t\tmov\tes,dx\n\t}\nagain:\n\tasm {\n\t\tmov\tal,ds:[si]\n\t\tmov\tah,es:[di]\n\t\tmov\tds:[si],ah\n\t\tmov\tes:[di],al\n\t\tinc\tdi\n\t\tinc\tsi\n\t\tdec\tcx\n\t\tjnz\tagain\n\n\t\tpop\tds\n\t\tpop\tes\n\t}\n}\n#endif\n\n\nvoid DOSSegmentClass::Swap(DOSSegmentClass &src, int soffset, DOSSegmentClass &dest, int doffset, int size)\n{\n\textern void dss_swap(char *src, char *dest, int size);\n\n\t#pragma aux dss_swap = \t\t\\\n\t\"again: mov\tal,[esi]\"\t\\\n\t\t\"mov\tah,[edi]\"\t\t\\\n\t\t\"mov\t[esi],ah\"\t\t\\\n\t\t\"stosb\"\t\t\t\t\t\\\n\t\t\"inc\tesi\"\t\t\t\t\\\n\t\t\"loop\tagain\"\t\t\t\\\n\t\tparm\t[esi] [edi] [ecx]\t\\\n\t\tmodify [ax];\n\n\tif (!size) return;\n\tdss_swap((char *)(src.Selector + soffset), (char *)(dest.Selector + doffset), size);\n}\n\n#ifdef OBSOLETE\nvoid DOSSegmentClass::Copy(DOSSegmentClass &src, int soffset, DOSSegmentClass &dest, int doffset, int size)\n{\n\textern void dss_copy(char *src, char *dest, int size);\n\t#pragma aux dss_copy = \t\t\\\n\t\t\"mov\t\tebx,ecx\"\t\t\t\\\n\t\t\"shr\t\tecx,2\"\t\t\t\\\n\t\t\"jecxz\tcopskip1\"\t\t\\\n\t\t\"rep \t\tmovsd\"\t\t\t\\\n\"copskip1: mov ecx,ebx\"\t\t\t\\\n\t\t\"and\t\tecx,3\"\t\t\t\\\n\t\t\"jecxz\tcopskip2\"\t\t\\\n\t\t\"rep\t\tmovsb\"\t\t\t\\\n\"copskip2:\"\t\t\t\t\t\t\t\\\n\t\tparm\t[esi edi ecx]\t\t\\\n\t\tmodify [ebx];\n\n\tif (!size) return;\n\tdss_copy((char *)(src.Selector + soffset), (char *)(dest.Selector + doffset), size);\n}\n#endif\n\n#ifdef OBSOLETE\nvoid DOSSegmentClass::Copy_To(void *source, int dest, int size)\n{\n\textern void dss_copy_to(void *src, (void *)dest, int size);\n\n\t#pragma aux dss_copy_to =\t\\\n\t\t\"mov\t\tebx,ecx\"\t\t\t\\\n\t\t\"shr\t\tecx,2\"\t\t\t\\\n\t\t\"jecxz\tcop2skip1\"\t\t\\\n\t\t\"rep\t\tmovsd\"\t\t\t\\\n\"cop2skip1: mov ecx,ebx\"\t\t\\\n\t\t\"and\t\tecx,3\"\t\t\t\\\n\t\t\"jecxz\tcop2skip2\"\t\t\\\n\t\t\"rep\t\tmovsb\"\t\t\t\\\n\"cop2skip2:\"\t\t\t\t\t\t\\\n\t\tparm\t[esi edi ecx]\t\t\\\n\t\tmodify [ebx];\n\n\tif (!size) return;\n\tdss_copy_to(src, (void *)(Selector + dest), size);\n\n}\n#endif\n\n#ifdef OBSOLETE\nvoid DOSSegmentClass::Copy_From(void *dest, int source, int size)\n{\n\textern void dss_copy_from(void *dest, (void *)source, int size);\n\n\t#pragma aux dss_copy_from =\t\\\n\t\t\"mov\t\tebx,ecx\"\t\t\t\\\n\t\t\"shr\t\tecx,2\"\t\t\t\\\n\t\t\"jecxz\tcopfskip1\"\t\t\\\n\t\t\"rep\t\tmovsd\"\t\t\t\\\n\"copfskip1: mov ecx,ebx\"\t\t\\\n\t\t\"and\t\tecx,3\"\t\t\t\\\n\t\t\"jecxz\tcopfskip2\"\t\t\\\n\t\t\"rep\t\tmovsb\"\t\t\t\\\n\"copfskip2:\"\t\t\t\t\t\t\\\n\t\tparm\t[edi esi ecx]\t\t\\\n\t\tmodify [ebx];\n\n\tif (!size) return;\n\tdss_copy_from(dest, (void *)(Selector + source), size);\n}\n#endif\n"
  },
  {
    "path": "CODE/DPMI.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\dpmi.h_v   4.43   05 Jul 1996 17:58:40   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DPMI.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 2, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 2, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef DPMI_Hx\n#define DPMI_Hx\n#include\t<dos.h>\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<mem.h>\n\n\nextern void output(short port, short data);\n\n\nclass DOSSegmentClass {\n\t\t/*\n\t\t**\tThis is the selector/segment value. In real mode it is the segment, in protected\n\t\t**\tmode it is the selector (also 16 bits). This value is moved into DS or ES when\n\t\t**\taccessing memory.\n\t\t** Note: in Watcom flat addressing, Selector == Segment<<4 (ex: 0A0000h)\n\t\t*/\n\t\tunsigned int Selector;\n\n\t\t/*\n\t\t**\tThese are C equivalents for pushing and popping the DS segment register. By using\n\t\t**\tthese, it is possible to create very small code that uses a segment and\n\t\t**\toffset without damaging the DS register. These are especially useful in protected\n\t\t**\tmode, but they are legal in real mode as well.\n\t\t*/\n\t\tvoid Push_DS(void) {/*__emit__(0x1E);*/};\n\t\tvoid Pop_DS(void) {/*__emit__(0x1F);*/};\n\n\tpublic:\n\t\tDOSSegmentClass(void);\n\t\t~DOSSegmentClass(void);\n\t\tDOSSegmentClass(unsigned short segment, long size=(1024L*64L));\n\n\t\tunsigned int Get_Selector(void);\n\n\t\t/*\n\t\t**\tThis routine is used to assign where the descriptor actually points to in\n\t\t**\tlow DOS memory. In real mode, this is a simple segment assignment and the size\n\t\t**\tis always 64K regardless of what is specified. In protected mode, the segment\n\t\t**\tis used to update the selector and the size can be any length.\n\t\t** In Watcom flat mode, it sets Selector == segment<<4\n\t\t*/\n\t\tvoid Assign(unsigned short segment, long size=(1024L*64L));\n\n\t\t/*\n\t\t**\tThese routines will move the data to/from regular memory and the segment/descriptor\n\t\t**\tmemory.\n\t\t*/\n\t\tvoid Copy_To(void *source, int dest, int size);\n\t\tvoid Copy_From(void *dest, int source, int size);\n\t\tvoid Copy_Word_To(short data, int dest);\n\t\tvoid Copy_Byte_To(char data, int dest);\n\t\tvoid Copy_DWord_To(long data, int dest);\n\t\tshort Copy_Word_From(int source);\n\t\tchar Copy_Byte_From(int source);\n\t\tlong Copy_DWord_From(int source);\n\n\t\t/*\n\t\t**\tThese routines move data around between sections of segmented (descriptor) memory.\n\t\t**\tTypically, this is used when accessing DOS memory in protected mode or when dealing\n\t\t**\twith hard memory areas such as the screen.\n\t\t*/\n\t\tstatic void Copy(DOSSegmentClass &src, int soffset, DOSSegmentClass &dest, int doffset, int size);\n\t\tstatic void Swap(DOSSegmentClass &src, int soffset, DOSSegmentClass &dest, int doffset, int size);\n};\n\n\ninline DOSSegmentClass::DOSSegmentClass(void)\n{\n\tSelector = 0xB0000;\n}\n\ninline DOSSegmentClass::~DOSSegmentClass(void)\n{\n}\n\ninline void DOSSegmentClass::Copy_Word_To(short data, int dest)\n{\n\t*(short *)(Selector+dest) = data;\n}\n\ninline void DOSSegmentClass::Copy_Byte_To(char data, int dest)\n{\n\t*(char *)(Selector+dest) = data;\n}\n\ninline void DOSSegmentClass::Copy_DWord_To(long data, int dest)\n{\n\t*(long *)(Selector+dest) = data;\n}\n\ninline void DOSSegmentClass::Assign(unsigned short segment, long)\n{\n\tSelector = (long)(segment)<<4L;\n}\n\ninline DOSSegmentClass::DOSSegmentClass(unsigned short segment, long)\n{\n\tAssign(segment);\n}\n\ninline void DOSSegmentClass::Copy_To(void *source, int dest, int size)\n{\n\tmemmove((void*)(Selector+dest), source, (unsigned)size);\n}\n\ninline void DOSSegmentClass::Copy_From(void *dest, int source, int size)\n{\n\tmemmove(dest, (void*)(Selector+source), (unsigned)size);\n}\n\ninline void DOSSegmentClass::Copy(DOSSegmentClass &src, int soffset, DOSSegmentClass &dest, int doffset, int size) {\n\tmemmove((void*)(dest.Selector+doffset), (void*)(src.Selector+soffset), (unsigned)size);\n}\n\ninline short DOSSegmentClass::Copy_Word_From(int source)\n{\n\treturn *(short*)(Selector+source);\n}\n\ninline char DOSSegmentClass::Copy_Byte_From(int source)\n{\n\treturn *(char*)(Selector+source);\n}\n\ninline long DOSSegmentClass::Copy_DWord_From(int source)\n{\n\treturn *(long*)(Selector+source);\n}\n\ninline unsigned int DOSSegmentClass::Get_Selector(void)\n{\n\treturn Selector;\n}\n#endif\n\n\n"
  },
  {
    "path": "CODE/DRIVE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/DRIVE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DRIVE.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 22, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 31, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   DriveClass::AI -- Processes unit movement and rotation.                                   *\n *   DriveClass::Approach_Target -- Handles approaching the target in order to attack it.      *\n *   DriveClass::Assign_Destination -- Set the unit's NavCom.                                  *\n *   DriveClass::Class_Of -- Fetches a reference to the class type for this object.            *\n *   DriveClass::Debug_Dump -- Displays status information to monochrome screen.               *\n *   DriveClass::Do_Turn -- Tries to turn the vehicle to the specified direction.              *\n *   DriveClass::DriveClass -- Constructor for drive class object.                             *\n *   DriveClass::Fixup_Path -- Adds smooth start path to normal movement path.                 *\n *   DriveClass::Force_Track -- Forces the unit to use the indicated track.                    *\n *   DriveClass::Lay_Track -- Handles track laying logic for the unit.                         *\n *   DriveClass::Limbo -- Prepares vehicle and then limbos it.                                 *\n *   DriveClass::Mark_Track -- Marks the midpoint of the track as occupied.                    *\n *   DriveClass::Ok_To_Move -- Checks to see if this object can begin moving.                  *\n *   DriveClass::Per_Cell_Process -- Handles when unit finishes movement into a cell.          *\n *   DriveClass::Response_Attack -- Voice feedback when ordering the unit to attack a target.  *\n *   DriveClass::Response_Move -- Voice feedback when ordering the unit to move.               *\n *   DriveClass::Response_Select -- Voice feedback when selecting the unit.                    *\n *   DriveClass::Scatter -- Causes the unit to travel to a nearby safe cell.                   *\n *   DriveClass::Smooth_Turn -- Handles the low level coord calc for smooth turn logic.        *\n *   DriveClass::Start_Of_Move -- Tries to get a unit to advance toward cell.                  *\n *   DriveClass::Stop_Driver -- Handles removing occupation bits when driving stops.           *\n *   DriveClass::Teleport_To -- Teleport object to specified location.                         *\n *   DriveClass::While_Moving -- Processes unit movement.                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n#ifdef NEVER\nvoid test(void)\n{\n\tenum nums {one, two, three};\n\n   nums x;\n   nums *ptr;\n\n   ptr = &x;\n}\n#endif\n\n\n/***********************************************************************************************\n * DriveClass::Response_Select -- Voice feedback when selecting the unit.                      *\n *                                                                                             *\n *    This is the voice to play when the unit is selected.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/30/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DriveClass::Response_Select(void)\n{\n\tassert(IsActive);\n\n\tstatic VocType _response[] = {\n\t\tVOC_VEHIC,\n\t\tVOC_REPORT,\n\t\tVOC_YESSIR,\n\t\tVOC_YESSIR,\n\t\tVOC_YESSIR,\n\t\tVOC_AWAIT\n\t};\n\tVocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];\n\tif (AllowVoice) {\n\t\tSound_Effect(response, fixed(1), -(ID+1));\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::Response_Move -- Voice feedback when ordering the unit to move.                 *\n *                                                                                             *\n *    This plays the audio feedback when ordering this unit to move to a new destination.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/30/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DriveClass::Response_Move(void)\n{\n\tassert(IsActive);\n\n\tstatic VocType _response[] = {\n\t\tVOC_ACKNOWL,\n\t\tVOC_AFFIRM,\n\t};\n\tVocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];\n\tif (AllowVoice) {\n\t\tSound_Effect(response, fixed(1), -(ID+1));\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::Response_Attack -- Voice feedback when ordering the unit to attack a target.    *\n *                                                                                             *\n *    This plays the audio feedback when ordering this unit to attack.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/30/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DriveClass::Response_Attack(void)\n{\n\tassert(IsActive);\n\n\tstatic VocType _response[] = {\n\t\tVOC_AFFIRM,\n\t\tVOC_ACKNOWL\n\t};\n\tVocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];\n\tif (AllowVoice) {\n\t\tSound_Effect(response, fixed(1), -(ID+1));\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::Scatter -- Causes the unit to travel to a nearby safe cell.                     *\n *                                                                                             *\n *    This routine is called when the unit discovers that it should get out of the \"hot seat\"  *\n *    and move to an adjacent cell. Since the safety of the adjacent cell is not determined    *\n *    before the move begins, it will appear that the unit is just scattering (which it        *\n *    should).                                                                                 *\n *                                                                                             *\n * INPUT:   threat   -- The coordinate of the source of the threat. The unit will try to move  *\n *                      roughly away from the threat.                                          *\n *                                                                                             *\n *          forced   -- The threat is real and a serious effort to scatter should be made.     *\n *                                                                                             *\n *          nokidding-- The scatter should affect the player's infantry even if it otherwise   *\n *                      wouldn't have.                                                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/25/1994 JLB : Created.                                                                 *\n *   09/27/1995 JLB : Revised to never scatter if already moving.                              *\n *   07/09/1996 JLB : Moved to DriveClass so that ships will scatter too.                      *\n *   08/02/1996 JLB : Added the \"nokidding\" parameter.                                         *\n *=============================================================================================*/\nvoid DriveClass::Scatter(COORDINATE threat, bool forced, bool nokidding)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tCertain missions prevent scattering regardless of whether it would be\n\t**\ta good idea or not.\n\t*/\n\tif (MissionControl[Mission].IsParalyzed) return;\n\n\tif ((What_Am_I() != RTTI_UNIT || !((UnitClass *)this)->IsDumping) && (!Target_Legal(NavCom) || (nokidding && !IsRotating))) {\n\t\tif (!Target_Legal(TarCom) || forced || Random_Pick(1, 4) == 1) {\n\t\t\tFacingType\ttoface;\n\t\t\tFacingType\tnewface;\n\t\t\tCELL\t\t\tnewcell;\n\n\t\t\tif (threat != 0) {\n\t\t\t\ttoface = Dir_Facing(Direction8(threat, Coord));\n\t\t\t\ttoface = toface + FacingType(Random_Pick(0, 2)-1);\n\t\t\t} else {\n\t\t\t\ttoface = Dir_Facing(PrimaryFacing.Current());\n\t\t\t\ttoface = toface + FacingType(Random_Pick(0, 2)-1);\n\t\t\t}\n\n\t\t\tfor (FacingType face = FACING_N; face < FACING_COUNT; face++) {\n\t\t\t\tnewface = toface + face;\n\t\t\t\tnewcell = Adjacent_Cell(Coord_Cell(Coord), newface);\n\n\t\t\t\tif (Map.In_Radar(newcell) && Can_Enter_Cell(newcell) == MOVE_OK) {\n\t\t\t\t\tAssign_Destination(::As_Target(newcell));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::Limbo -- Prepares vehicle and then limbos it.                                   *\n *                                                                                             *\n *    This routine removes the occupation bits for the vehicle and also handles cleaning up    *\n *    any vehicle reservation bits. After this, it then proceeds with limboing the unit.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the vehicle limboed?                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool DriveClass::Limbo(void)\n{\n\tif (!IsInLimbo) {\n\t\tStop_Driver();\n\t\tTrackNumber = -1;\n\t}\n\treturn(FootClass::Limbo());\n}\n\n\n/***********************************************************************************************\n * DriveClass::Stop_Driver -- Handles removing occupation bits when driving stops.             *\n *                                                                                             *\n *    This routine will remove the \"reservation\" flag (if present) when the vehicle is         *\n *    required to stop movement.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the vehicle stopped?                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool DriveClass::Stop_Driver(void)\n{\n\tassert(IsActive);\n\n\t/*\n\t** We only need to do something if the vehicle is actually going\n\t** somewhere.\n\t*/\n\tif (Head_To_Coord()) {\n\n\t\t/*\n\t\t** Safe off whether the vehicle is down or not so we know whether\n\t\t** we have to put it back down.\n\t\t*/\n\t\tint temp = IsDown;\n\n\t\t/*\n\t\t** If the vehicle is down, pick it up so it doesn't interfere with\n\t\t** our flags.\n\t\t*/\n\t\tif (temp) {\n\t\t\tMark(MARK_UP);\n\t\t}\n\n\t\t/*\n\t\t** Call the drive class function which will let us release the\n\t\t** reserved track.\n\t\t*/\n\t\tMark_Track(Head_To_Coord(), MARK_UP);\n\n\t\t/*\n\t\t** If it was down it should be down when we are done.\n\t\t*/\n\t\tif (temp) {\n\t\t\tMark(MARK_DOWN);\n\t\t}\n\t}\n\treturn(FootClass::Stop_Driver());\n}\n\n\n/***********************************************************************************************\n * DriveClass::Do_Turn -- Tries to turn the vehicle to the specified direction.                *\n *                                                                                             *\n *    This routine will set the vehicle to rotate to the direction specified. For tracked      *\n *    vehicles, it is just a simple rotation. For wheeled vehicles, it performs a series       *\n *    of short drives (three point turn) to face the desired direction.                        *\n *                                                                                             *\n * INPUT:   dir   -- The direction that this vehicle should face.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DriveClass::Do_Turn(DirType dir)\n{\n\tassert(IsActive);\n\n\tif (dir != PrimaryFacing) {\n\n#ifdef TOFIX\n\t\t/*\n\t\t**\tSpecial rotation track is needed for units that\n\t\t**\tcannot rotate in place.\n\t\t*/\n\t\tif (Special.IsThreePoint && TrackNumber == -1 && Techno_Type_Class()->Speed == SPEED_WHEEL) {\n\t\t\tint\t\t\tfacediff;\t// Signed difference between current and desired facing.\n\t\t\tFacingType\tface;\t\t\t// Current facing (ordinal value).\n\n\t\t\tfacediff = PrimaryFacing.Difference(dir) >> 5;\n\t\t\tfacediff = Bound(facediff, -2, 2);\n\t\t\tif (facediff) {\n\t\t\t\tface = Dir_Facing(PrimaryFacing);\n\n\t\t\t\tIsOnShortTrack = true;\n\t\t\t\tForce_Track(face*FACING_COUNT + (face + facediff), Coord);\n\n\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t\tSet_Speed(0xFF);\t\t// Full speed.\n\t\t\t}\n\t\t} else {\n\t\t\tPrimaryFacing.Set_Desired(dir);\n\t\t}\n#else\n\t\t\tPrimaryFacing.Set_Desired(dir);\n//\t\t\tIsRotating = true;\n#endif\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::Teleport_To -- Teleport object to specified location.                           *\n *                                                                                             *\n *    This will teleport the object to the specified location or as close as possible to it    *\n *    if the destination is blocked.                                                           *\n *                                                                                             *\n * INPUT:   cell  -- The desired destination cell to teleport to.                              *\n *                                                                                             *\n * OUTPUT:  bool; Was the teleport successful?                                                 *\n *                                                                                             *\n * WARNINGS:   All current activity of this object will be terminated by the teleport. It will *\n *             arrive at the destination in static guard mode.                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/21/1996 JLB : Created.                                                                 *\n *   10/31/1996 JLB : Handles flag teleport case.                                              *\n *=============================================================================================*/\nbool DriveClass::Teleport_To(CELL cell)\n{\n\t/*\n\t**\tAll cargo gets destroyed.\n\t*/\n\tif (Rule.IsChronoKill) {\n\t\tKill_Cargo(NULL);\n\t}\n\n\tStop_Driver();\n\tForce_Track(-1, 0);\n\tPrimaryFacing.Set_Current(PrimaryFacing.Desired());\n\tTransmit_Message(RADIO_OVER_OUT);\n\tAssign_Destination(TARGET_NONE);\n\tAssign_Target(TARGET_NONE);\n\tAssign_Mission(MISSION_NONE);\n\tCommence();\n\tMark(MARK_UP);\n\n\t/*\n\t**\tA teleported unit will drop the flag right where it's at.\n\t*/\n\tif (What_Am_I() == RTTI_UNIT && ((UnitClass *)this)->Flagged != HOUSE_NONE) {\n\t\tHouseClass::As_Pointer(((UnitClass *)this)->Flagged)->Flag_Attach(Coord_Cell(Coord));\n\t}\n\n\tif (Can_Enter_Cell(cell) != MOVE_OK) {\n\t\tcell = Map.Nearby_Location(cell, Techno_Type_Class()->Speed);\n\t}\n\tCoord = Cell_Coord(cell);\n\tMark(MARK_DOWN);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DriveClass::Force_Track -- Forces the unit to use the indicated track.                      *\n *                                                                                             *\n *    This override (nuclear bomb) style routine is to be used when a unit needs to start      *\n *    on a movement track but is outside the normal movement system. This occurs when a        *\n *    harvester starts driving off of a refinery.                                              *\n *                                                                                             *\n * INPUT:   track -- The track number to start on.                                             *\n *                                                                                             *\n *          coord -- The coordinate that the unit will end up at when the movement track       *\n *                   is completed.                                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DriveClass::Force_Track(int track, COORDINATE coord)\n{\n\tassert(IsActive);\n\n\tTrackNumber = track;\n\tTrackIndex = 0;\n\tif (coord != 0) {\n\t\tStart_Driver(coord);\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::DriveClass -- Constructor for drive class object.                               *\n *                                                                                             *\n *    This will initialize the drive class to its default state. It is called as a result      *\n *    of creating a unit.                                                                      *\n *                                                                                             *\n * INPUT:   classid  -- The unit's ID class. It is passed on to the foot class constructor.    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/13/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nDriveClass::DriveClass(RTTIType rtti, int id, HousesType house) :\n\tFootClass(rtti, id, house),\n\tIsMoebius(false),\n\tIsHarvesting(false),\n\tIsTurretLockedDown(false),\n\tIsOnShortTrack(false),\n\tSpeedAccum(0),\n\tMoebiusCountDown(0),\n\tMoebiusCell(0),\n\tTrackNumber(-1),\n\tTrackIndex(0)\n{\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * DriveClass::Debug_Dump -- Displays status information to monochrome screen.                 *\n *                                                                                             *\n *    This debug utility function will display the status of the drive class to the mono       *\n *    screen. It is through this information that bugs can be tracked down.                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DriveClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(IsActive);\n\n\tmono->Fill_Attrib(66, 14, 12, 1, IsMoebius ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tFootClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * DriveClass::Smooth_Turn -- Handles the low level coord calc for smooth turn logic.          *\n *                                                                                             *\n *    This routine calculates the new coordinate value needed for the                          *\n *    smooth turn logic. The adjustment and flag values must be                                *\n *    determined prior to entering this routine.                                               *\n *                                                                                             *\n * INPUT:   adj      -- The adjustment coordinate as lifted from the                           *\n *                      correct smooth turn table.                                             *\n *                                                                                             *\n *          dir      -- Pointer to dir for possible modification                               *\n *                      according to the flag bits.                                            *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate the unit should positioned to.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/14/1994 JLB : Created.                                                                 *\n *   07/13/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nCOORDINATE DriveClass::Smooth_Turn(COORDINATE adj, DirType & dir)\n{\n\tassert(IsActive);\n\n\tDirType workdir = dir;\n\tint x,y;\n\tint temp;\n\tTrackControlType flags = TrackControl[TrackNumber].Flag;\n\n\tx = Coord_X(adj);\n\ty = Coord_Y(adj);\n\n\tif (flags & F_T) {\n\t\ttemp\t= x;\n\t\tx\t\t= y;\n\t\ty \t\t= temp;\n\t\tworkdir = (DirType)(DIR_W - workdir);\n\t}\n\n\tif (flags & F_X) {\n\t\tx \t\t = -x;\n\t\tworkdir = (DirType)-workdir;\n\t}\n\n\tif (flags & F_Y) {\n\t\ty = -y;\n\t\tworkdir = (DirType)(DIR_S - workdir);\n\t}\n\n\tdir = workdir;\n\n\treturn(XY_Coord( (LEPTON)(Coord_X(Head_To_Coord()) + x), (LEPTON)(Coord_Y(Head_To_Coord()) + y)));\n}\n\n\n/***********************************************************************************************\n * DriveClass::Assign_Destination -- Set the unit's NavCom.                                    *\n *                                                                                             *\n *    This routine is used to set the unit's navigation computer to the                        *\n *    specified target. Once the navigation computer is set, the unit                          *\n *    will start planning and moving toward the destination.                                   *\n *                                                                                             *\n * INPUT:   target   -- The destination target for the unit to head to.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/07/1992 JLB : Created.                                                                 *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nvoid DriveClass::Assign_Destination(TARGET target)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tAbort early if there is anything wrong with the parameters\n\t**\tor the unit already is assigned the specified destination.\n\t*/\n\tif (target == NavCom) return;\n\n\t/*\n\t**\tFor harvesting type vehicles, it might go into a dock and unload procedure\n\t**\twhen the harvester is full and an empty refinery is selected as a target.\n\t*/\n\tBuildingClass * b = As_Building(target);\n\n\t/*\n\t**\tIf the player clicked on refinery but it is not busy, then assign\n\t**\tit to unload at the refinery.\n\t*/\n\tif (b != NULL && *b == STRUCT_REFINERY && What_Am_I() == RTTI_UNIT && ((UnitTypeClass *)Techno_Type_Class())->IsToHarvest) {\n\t\tif (Contact_With_Whom() != b && !b->In_Radio_Contact()) {\n\t\t\t/*\n\t\t\t**\tEstablish radio contact protocol. If the facility responds correctly,\n\t\t\t**\tthen remain in radio contact and proceed toward the desired destination.\n\t\t\t*/\n\t\t\tif (Transmit_Message(RADIO_HELLO, b) == RADIO_ROGER) {\n\t\t\t\tif (Mission != MISSION_ENTER && Mission != MISSION_HARVEST) {\n\t\t\t\t\tAssign_Mission(MISSION_ENTER);\n\t\t\t\t\ttarget = TARGET_NONE;\n\t\t\t\t} else {\n//\t\t\t\t\ttarget = TARGET_NONE;\n\t\t\t\t}\n\t\t\t} else {\n//\t\t\t\ttarget = TARGET_NONE;\n\t\t\t}\n\t\t} else {\n//\t\t\ttarget = TARGET_NONE;\n\t\t}\n\t}\n\n\t/*\n\t**\tSet the unit's navigation computer.\n\t*/\n\tFootClass::Assign_Destination(target);\n\n\tPath[0] = FACING_NONE;\t\t\t// Force recalculation of path.\n\tif (!IsDriving && Mission != MISSION_UNLOAD) {\n\t\tStart_Of_Move();\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::While_Moving -- Processes unit movement.                                        *\n *                                                                                             *\n *    This routine is used to process movement for the units as they move.                     *\n *    It is called many times for each cell's worth of movement.   This                        *\n *    routine only applies after the next cell HeadTo has been determined.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  true/false; Should this routine be called again?                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/02/1992 JLB : Created.                                                                 *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nbool DriveClass::While_Moving(void)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tPerform quick legality checks.\n\t*/\n\tif (!IsDriving || TrackNumber == -1 || (IsRotating && !Techno_Type_Class()->IsTurretEquipped)) {\n\t\tSpeedAccum = 0;\t\t// Kludge?  No speed should accumulate if movement is on hold.\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf enough movement has accumulated so that the unit can\n\t**\tvisibly move on the map, then process accordingly.\n\t** Slow the unit down if he's carrying a flag.\n\t*/\n\tMPHType maxspeed = MPHType(min(Techno_Type_Class()->MaxSpeed * SpeedBias * House->GroundspeedBias, (int)MPH_LIGHT_SPEED));\n\tif (IsFormationMove) maxspeed = FormationMaxSpeed;\n\n\tint actual;\t\t\t// Working movement addition value.\n\tif (((UnitClass *)this)->Flagged != HOUSE_NONE) {\n\t\tactual = SpeedAccum + ((int)maxspeed/2) * fixed(Speed, 256);\n\t} else {\n\t\tactual = SpeedAccum + maxspeed * fixed(Speed, 256);\n\t}\n\n\tif (actual > PIXEL_LEPTON_W) {\n\t\tTurnTrackType\tconst * track;\t// Track control pointer.\n\t\tTrackType\t\tconst\t* ptr;\t\t// Pointer to coord offset values.\n\t\tint\t\t\t\ttracknum;\t\t// The track number being processed.\n\t\tFacingType\t\tnextface;\t\t// Next facing queued in path.\n\t\tbool\t\t\t\tadj;\t\t\t\t// Is a turn coming up?\n\n\t\ttrack = &TrackControl[TrackNumber];\n\t\tif (IsOnShortTrack) {\n\t\t\ttracknum = track->StartTrack;\n\t\t} else {\n\t\t\ttracknum = track->Track;\n\t\t}\n\t\tptr = RawTracks[tracknum-1].Track;\n\t\tnextface = Path[0];\n\n\t\t/*\n\t\t**\tDetermine if there is a turn coming up. If there is\n\t\t**\ta turn, then track jumping might occur.\n\t\t*/\n\t\tadj = false;\n\t\tif (nextface != FACING_NONE && Dir_Facing(track->Facing) != nextface) {\n\t\t\tadj = true;\n\t\t}\n\n\t\t/*\n\t\t**\tSkip ahead the number of track steps required (limited only\n\t\t**\tby track length). Set the unit to the new position and\n\t\t**\tflag the unit accordingly.\n\t\t*/\n\t\tMark(MARK_UP);\n\t\twhile (actual > PIXEL_LEPTON_W) {\n\t\t\tCOORDINATE\t\toffset;\n\t\t\tDirType\tdir;\n\n\t\t\tactual -= PIXEL_LEPTON_W;\n\n\t\t\toffset = ptr[TrackIndex].Offset;\n\t\t\tif (offset || !TrackIndex) {\n\t\t\t\tdir = ptr[TrackIndex].Facing;\n\t\t\t\tCoord = Smooth_Turn(offset, dir);\n\n\t\t\t\tPrimaryFacing.Set(dir);\n\n\t\t\t\t/*\n\t\t\t\t**\tSee if \"per cell\" processing is necessary.\n\t\t\t\t*/\n\t\t\t\tif (TrackIndex && RawTracks[tracknum-1].Cell == TrackIndex) {\n\t\t\t\t\tMark(MARK_DOWN);\n\t\t\t\t\tPer_Cell_Process(PCP_DURING);\n\t\t\t\t\tif (!IsActive) {\n\t\t\t\t\t\treturn(false);\n\t\t\t\t\t}\n\t\t\t\t\tMark(MARK_UP);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tThe unit could \"jump tracks\". Check to see if the unit should\n\t\t\t\t**\tdo so.\n\t\t\t\t*/\n\t\t\t\tif (/**this != UNIT_GUNBOAT &&*/ nextface != FACING_NONE && adj && RawTracks[tracknum-1].Jump == TrackIndex && TrackIndex) {\n\t\t\t\t\tTurnTrackType const * newtrack;\t\t// Proposed jump-to track.\n\t\t\t\t\tint\ttnum;\n\n\t\t\t\t\ttnum = (int)(Dir_Facing(track->Facing) * FACING_COUNT) + (int)nextface;\n\t\t\t\t\tnewtrack = &TrackControl[tnum];\n\t\t\t\t\tif (newtrack->Track && RawTracks[newtrack->Track-1].Entry) {\n\t\t\t\t\t\tCOORDINATE\tc = Head_To_Coord();\n\t\t\t\t\t\tint oldspeed = Speed;\n\n\t\t\t\t\t\tc = Adjacent_Cell(c, nextface);\n\n\t\t\t\t\t\tswitch (Can_Enter_Cell(Coord_Cell(c), nextface)) {\n\t\t\t\t\t\t\tcase MOVE_OK:\n\t\t\t\t\t\t\t\tIsOnShortTrack = false;\t\t// Shouldn't be necessary, but...\n\t\t\t\t\t\t\t\tTrackNumber = tnum;\n\t\t\t\t\t\t\t\ttrack = newtrack;\n\n\t\t\t\t\t\t\t\ttracknum = track->Track;\n\t\t\t\t\t\t\t\tTrackIndex = RawTracks[tracknum-1].Entry-1;\t// Anticipate increment.\n\t\t\t\t\t\t\t\tptr = RawTracks[tracknum-1].Track;\n\t\t\t\t\t\t\t\tadj = false;\n\n\t\t\t\t\t\t\t\tStop_Driver();\n\t\t\t\t\t\t\t\tIsDriving = true;\n\t\t\t\t\t\t\t\tPer_Cell_Process(PCP_END);\n\t\t\t\t\t\t\t\tIsDriving = false;\n\t\t\t\t\t\t\t\tif (!IsActive) return(false);\n\t\t\t\t\t\t\t\tif (Start_Driver(c)) {\n\t\t\t\t\t\t\t\t\tSet_Speed(oldspeed);\n\t\t\t\t\t\t\t\t\tmemcpy((char*)&Path[0], (char*)&Path[1], CONQUER_PATH_MAX-1);\n\t\t\t\t\t\t\t\t\tPath[CONQUER_PATH_MAX-1] = FACING_NONE;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t\t\t\t\t\t\tTrackNumber = -1;\n\t\t\t\t\t\t\t\t\tactual = 0;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase MOVE_CLOAK:\n\t\t\t\t\t\t\t\tMap[c].Shimmer();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase MOVE_TEMP:\n#ifdef TOFIX\n\t\t\t\t\t\t\t\tif (*this == UNIT_HARVESTER || !House->IsHuman) {\n#else\n\t\t\t\t\t\t\t\tif (!House->IsHuman) {\n#endif\n\t\t\t\t\t\t\t\t\tMap[c].Incoming(0, true, true);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tTrackIndex++;\n\n\t\t\t} else {\n\t\t\t\tactual = 0;\n\t\t\t\tCoord = Head_To_Coord();\n\t\t\t\tStop_Driver();\n\t\t\t\tTrackNumber = -1;\n\t\t\t\tTrackIndex = NULL;\n\n\t\t\t\t/*\n\t\t\t\t**\tPerform \"per cell\" activities.\n\t\t\t\t*/\n\t\t\t\tMark(MARK_DOWN);\n\t\t\t\tPer_Cell_Process(PCP_END);\n\t\t\t\tif (!IsActive) return(false);\n\t\t\t\tMark(MARK_UP);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (IsActive) {\n\t\t\tMark(MARK_DOWN);\n\t\t}\n\t}\n\n\t/*\n\t**\tReplace any remainder back into the unit's movement\n\t**\taccumulator to be processed next pass.\n\t*/\n\tSpeedAccum = actual;\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DriveClass::Per_Cell_Process -- Handles when unit finishes movement into a cell.            *\n *                                                                                             *\n *    This routine is called when a unit has mostly or completely                              *\n *    entered a cell. The unit might be in the middle of a movement track                      *\n *    when this routine is called. It's primary purpose is to perform                          *\n *    sighting and other \"per cell\" activities.                                                *\n *                                                                                             *\n * INPUT:   why   -- Specifies the circumstances under which this routine was called.          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/03/1993 JLB : Created.                                                                 *\n *   03/30/1994 JLB : Revamped for track system.                                               *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *   06/18/1994 JLB : Converted to virtual function.                                           *\n *   06/18/1994 JLB : Distinguishes between center and near-center conditions.                 *\n *=============================================================================================*/\nvoid DriveClass::Per_Cell_Process(PCPType why)\n{\n\tassert(IsActive);\n\n\tif (why == PCP_END) {\n\t\tCELL\tcell = Coord_Cell(Coord);\n\n\t\t/*\n\t\t**\tCheck to see if it has reached its destination. If so, then clear the NavCom\n\t\t**\tregardless of the remaining path list.\n\t\t*/\n\t\tif (As_Cell(NavCom) == cell) {\n\t\t\tIsTurretLockedDown = false;\n\t\t\tNavCom = TARGET_NONE;\n\t\t\tPath[0] = FACING_NONE;\n\t\t}\n\n\t\tLay_Track();\n\t}\n\n\tFootClass::Per_Cell_Process(why);\n}\n\n\n/***********************************************************************************************\n * DriveClass::Start_Of_Move -- Tries to get a unit to advance toward cell.                    *\n *                                                                                             *\n *    This will try to start a unit advancing toward the cell it is                            *\n *    facing. It will check for and handle legality and reserving of the                       *\n *    necessary cell.                                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  true/false; Should this routine be called again because                            *\n *                      initial start operation is temporarily delayed?                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/02/1992 JLB : Created.                                                                 *\n *   10/18/1993 JLB : This should be called repeatedly until HeadTo is not NULL.               *\n *   03/16/1994 JLB : Revamped for track logic.                                                *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *   06/19/1995 JLB : Fixed so that it won't fire on ground unnecessarily.                     *\n *   07/13/1995 JLB : Handles bumping into cloaked objects.                                    *\n *   09/22/1995 JLB : Breaks out of hopeless hunt mode.                                        *\n *   07/10/1996 JLB : Sets scan limit if necessary.                                            *\n *=============================================================================================*/\nbool DriveClass::Start_Of_Move(void)\n{\n\tassert(IsActive);\n\n\tFacingType\t\tfacing;\t\t\t\t// Direction movement will commence.\n\tDirType\t\t\tdir;\t\t\t\t// Desired actual facing toward destination.\n\tint\t\t\t\tfacediff;\t\t\t// Difference between current and desired facing.\n\tint\t\t\t\tspeed;\t\t\t\t// Speed of unit.\n\tCELL\t\t\t\tdestcell;\t\t\t// Cell of destination.\n\tLandType\t\t\tground;\t\t\t\t// Ground unit is entering.\n\tCOORDINATE\t\t\t\tdest;\t\t\t\t\t// Destination coordinate.\n\n\tfacing = Path[0];\n\n\tif (!Target_Legal(NavCom) && facing == FACING_NONE) {\n\t\tIsTurretLockedDown = false;\n\t\tStop_Driver();\n\t\tif (Mission == MISSION_MOVE) {\n\t\t\tEnter_Idle_Mode();\n\t\t}\n\t\treturn(false);\t\t// Why is it calling this routine!?!\n\t}\n\n\t/*\n\t**\tReduce the path length if the target is a unit and the\n\t**\trange to the unit is less than the precalculated path steps.\n\t*/\n\tif (facing != FACING_NONE) {\n\t\tint\tdist;\n\n\t\tif (Is_Target_Vessel(NavCom) || Is_Target_Unit(NavCom) || Is_Target_Infantry(NavCom)) {\n\t\t\tdist = Lepton_To_Cell((LEPTON)Distance(NavCom));\n\n\t\t\tif (dist < ARRAY_SIZE(Path)) {\n\t\t\t\tPath[dist] = FACING_NONE;\n\t\t\t\tfacing = Path[0];\t\t// Maybe needed.\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the path is invalid at this point, then generate one. If\n\t**\tgenerating a new path fails, then abort NavCom.\n\t*/\n\tif (facing == FACING_NONE) {\n\n\t\t/*\n\t\t**\tIf after a path search, there is still no valid path, then set the\n\t\t**\tNavCom to null and let the script take care of assigning a new\n\t\t**\tnavigation target.\n\t\t*/\n\t\tif (PathDelay != 0) {\n\t\t\treturn(false);\n\t\t}\n\n\t\tif (!Basic_Path()) {\n\n\t\t\t/*\n\t\t\t**\tIf the unit is close enough to the target then just stop\n\t\t\t**\tdriving now. This prevents the fidgeting that would occur\n\t\t\t**\tif they mindlessly kept trying to get to the exact location\n\t\t\t**\tdesired. This is quite necessary since it is typical to move\n\t\t\t**\tseveral units with the same mouse click.\n\t\t\t*/\n\t\t\tif (!Is_On_Priority_Mission() && Distance(NavCom) < Rule.CloseEnoughDistance && (Mission == MISSION_MOVE || Mission == MISSION_GUARD_AREA)) {\n\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\tif (!IsActive) return(false);\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t**\tIf a basic path could not be found, but the immediate move destination is\n\t\t\t\t**\tblocked by a friendly temporary blockage, then cause that blockage\n\t\t\t\t**\tto scatter.\n\t\t\t\t*/\n\t\t\t\tCELL cell = Adjacent_Cell(Coord_Cell(Center_Coord()), PrimaryFacing.Current());\n\t\t\t\tif (Map.In_Radar(cell)) {\n\t\t\t\t\tMoveType ok = Can_Enter_Cell(cell);\n\t\t\t\t\tif (ok == MOVE_TEMP) {\n\t\t\t\t\t\tCellClass * cellptr = &Map[cell];\n\t\t\t\t\t\tTechnoClass * blockage = cellptr->Cell_Techno();\n\t\t\t\t\t\tif (blockage && House->Is_Ally(blockage)) {\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf the target can be told to get out of the way, only bother\n\t\t\t\t\t\t\t**\tto do so if we aren't very close to the target and this\n\t\t\t\t\t\t\t**\tobject can just say \"good enough\" and stop here.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Distance(NavCom) < Rule.CloseEnoughDistance && !In_Radio_Contact()) {\n\t\t\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t\t\t\treturn(false);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcellptr->Incoming(0, true, false);\n//\t\t\t\t\t\t\t\tcellptr->Incoming(0, true, true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (TryTryAgain > 0) {\n\t\t\t\t\tTryTryAgain--;\n\t\t\t\t} else {\n\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\tif (!IsActive) return(false);\n\t\t\t\t\tif (IsNewNavCom) Sound_Effect(VOC_SCOLD);\n\t\t\t\t\tIsNewNavCom = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSince the path was blocked, check to make sure that it was completely\n\t\t\t**\tblocked. If so and it has a valid TarCom and it is out of range of the\n\t\t\t**\tTarCom, then give this unit a range limit so that it might not pick\n\t\t\t**\ta \"can't reach\" target again.\n\t\t\t*/\n\t\t\tif (!Target_Legal(NavCom) && Target_Legal(TarCom) && !In_Range(TarCom)) {\n\t\t\t\tIsScanLimited = true;\n\t\t\t\tif (Team.Is_Valid()) Team->Scan_Limit();\n\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tStop the movement, for now, and let the subsequent logic in later game\n\t\t\t**\tframes resume movement as appropriate.\n\t\t\t*/\n\t\t\tStop_Driver();\n\t\t\tTrackNumber = -1;\n\t\t\tIsTurretLockedDown = false;\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t**\tIf a basic path could be found, but the immediate move destination is\n\t\t**\tblocked by a friendly temporary blockage, then cause that blockage\n\t\t**\tto scatter.\n\t\t*/\n\t\tCELL cell = Adjacent_Cell(Coord_Cell(Center_Coord()), Path[0]);\n\t\tif (Map.In_Radar(cell)) {\n\t\t\tMoveType ok = Can_Enter_Cell(cell);\n\t\t\tif (ok == MOVE_TEMP) {\n\t\t\t\tCellClass * cellptr = &Map[cell];\n\t\t\t\tTechnoClass * blockage = cellptr->Cell_Techno();\n\t\t\t\tif (blockage && House->Is_Ally(blockage)) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the target can be told to get out of the way, only bother\n\t\t\t\t\t**\tto do so if we aren't very close to the target and this\n\t\t\t\t\t**\tobject can just say \"good enough\" and stop here.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Distance(NavCom) < Rule.CloseEnoughDistance && !In_Radio_Contact()) {\n\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t\treturn(false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcellptr->Incoming(0, true, false);\n//\t\t\t\t\t\tcellptr->Incoming(0, true, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tTryTryAgain = PATH_RETRY;\n\t\tfacing = Path[0];\n\t}\n\n\t/*\n\t**\tDetermine the coordinate of the next cell to move into.\n\t*/\n\tdest = Adjacent_Cell(Coord, facing);\n\tdir = Facing_Dir(facing);\n\n\t/*\n\t**\tSet the facing correctly if it isn't already correct. This\n\t**\tmeans starting a rotation track if necessary.\n\t*/\n\tfacediff = PrimaryFacing.Difference(dir);\n\tif (facediff) {\n\n\t\t/*\n\t\t**\tRequest a change of facing.\n\t\t*/\n\t\tDo_Turn(dir);\n\t\treturn(true);\n\n\t} else {\n\n\t\t/* NOTE:  Beyond this point, actual track assignment can begin.\n\t\t**\n\t\t**\tIf the cell to move into is impassable (probably for some unexpected\n\t\t**\treason), then abort the path list and set the speed to zero. The\n\t\t** next time this routine is called, a new path will be generated.\n\t\t*/\n\t\tdestcell = Coord_Cell(dest);\n\t\tMark(MARK_UP);\n\t\tMoveType cando = Can_Enter_Cell(destcell, facing);\n\t\tMark(MARK_DOWN);\n\n\t\tif (cando != MOVE_OK) {\n\n\t\t\tif (Mission == MISSION_MOVE /*KO&& House->IsHuman */&& Distance(NavCom) < Rule.CloseEnoughDistance) {\n\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\tif (!IsActive) return(false);//BG\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf a temporary friendly object is blocking the path, then cause it to\n\t\t\t**\tget out of the way.\n\t\t\t*/\n\t\t\tif (cando == MOVE_TEMP) {\n\t\t\t\tMap[destcell].Incoming(0, true, true);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf a cloaked object is blocking, then shimmer the cell.\n\t\t\t*/\n\t\t\tif (cando == MOVE_CLOAK) {\n\t\t\t\tMap[destcell].Shimmer();\n\t\t\t}\n\n\t\t\tStop_Driver();\n\t\t\tif (cando != MOVE_MOVING_BLOCK) {\n\t\t\t \tPath[0] = FACING_NONE;\t\t// Path is blocked!\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If blocked by a moving block then just exit start of move and\n\t\t\t** try again next tick.\n\t\t\t*/\n\t\t\tif (cando == MOVE_DESTROYABLE) {\n\t\t\t\tif (Map[destcell].Cell_Object()) {\n\t\t\t\t\tif (!House->Is_Ally(Map[destcell].Cell_Object())) {\n\t\t\t\t\t\tOverride_Mission(MISSION_ATTACK, Map[destcell].Cell_Object()->As_Target(), TARGET_NONE);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (Map[destcell].Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(Map[destcell].Overlay).IsWall) {\n\t\t\t\t\t\tOverride_Mission(MISSION_ATTACK, ::As_Target(destcell), TARGET_NONE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (IsNewNavCom) Sound_Effect(VOC_SCOLD);\n\t\t\t}\n\t\t\tIsNewNavCom = false;\n\t\t\tTrackNumber = -1;\n\t\t\treturn(true);\n\t\t}\n\n\t\t/*\n\t\t**\tDetermine the speed that the unit can travel to the desired square.\n\t\t*/\n\t\tground = Map[destcell].Land_Type();\n\t\tspeed = Ground[ground].Cost[Techno_Type_Class()->Speed] * 256;\n\n\t\t/* change speed if it's related to a team move */\n\t\tif (IsFormationMove) speed = Ground[ground].Cost[FormationSpeed] * 256;\n\t\tif (!speed) speed = 128;\n\n#ifdef NEVER\n\t\t/*\n\t\t**\tSet the jiggle flag if the terrain would cause the unit\n\t\t**\tto jiggle when travelled over.\n\t\t*/\n\t\tBaseF &= ~BASEF_JIGGLE;\n\t\tif (Ground[ground].Jiggle) {\n\t\t\tBaseF |= BASEF_JIGGLE;\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tA damaged unit has a reduced speed.\n\t\t*/\n\t\tif (Health_Ratio() <= Rule.ConditionYellow /*(Techno_Type_Class()->MaxStrength>>1) > Strength*/) {\n\t\t\tspeed -= (speed/4);\t// Three quarters speed.\n\t\t}\n\t\tif ((speed != Speed)/* || !SpeedAdd*/) {\n\t\t\tSet_Speed(speed);\t\t// Full speed.\n\t\t}\n\n\t\t/*\n\t\t**\tReserve the destination cell so that it won't become\n\t\t**\toccupied AS this unit is moving into it.\n\t\t*/\n\t\tif (cando != MOVE_OK) {\n\t\t \tPath[0] = FACING_NONE;\t\t// Path is blocked!\n\t\t\tTrackNumber = -1;\n\t\t \tdest = NULL;\n\t\t} else {\n\n\t\t\tOverrun_Square(Coord_Cell(dest), true);\n\n\t\t\t/*\n\t\t\t**\tDetermine which track to use (based on recorded path).\n\t\t\t*/\n\t\t\tFacingType nextface = Path[1];\n\t\t\tif (nextface == FACING_NONE) nextface = facing;\n\n\t\t\tIsOnShortTrack = false;\n\t\t\tTrackNumber = facing * FACING_COUNT + (int)nextface;\n\t\t\tif (TrackControl[TrackNumber].Track == 0) {\n\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t\tTrackNumber = -1;\n\t\t\t\treturn(true);\n\t\t\t} else {\n\t\t\t\tif (TrackControl[TrackNumber].Flag & F_D) {\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the middle cell of a two cell track contains a crate,\n\t\t\t\t\t**\tthe check for goodies before movement starts.\n\t\t\t\t\t*/\n\t\t\t\t\tif (!Map[destcell].Goodie_Check(this)) {\n\t\t\t\t\t\tcando = MOVE_NO;\n\t\t\t\t\t\tif (!IsActive) return(false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!IsActive) return(false);\n\t\t\t\t\t\tdest = Adjacent_Cell(dest, nextface);\n\t\t\t\t\t\tdestcell = Coord_Cell(dest);\n\t\t\t\t\t\tcando = Can_Enter_Cell(destcell);\n\t\t\t\t\t}\n\t\t\t\t\tif (!IsActive) return(false);\n\n\t\t\t\t\tif (cando != MOVE_OK) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf a temporary friendly object is blocking the path, then cause it to\n\t\t\t\t\t\t**\tget out of the way.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (cando == MOVE_TEMP) {\n\t\t\t\t\t\t\tMap[destcell].Incoming(0, true, true);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf a cloaked object is blocking, then shimmer the cell.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (cando == MOVE_CLOAK) {\n\t\t\t\t\t\t\tMap[destcell].Shimmer();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tPath[0] = FACING_NONE;\t\t// Path is blocked!\n\t\t\t\t\t\tTrackNumber = -1;\n\t\t\t\t\t\tdest = NULL;\n\t\t\t\t\t\tif (cando == MOVE_DESTROYABLE) {\n\n\t\t\t\t\t\t\tif (Map[destcell].Cell_Object()) {\n\t\t\t\t\t\t\t\tif (!House->Is_Ally(Map[destcell].Cell_Object())) {\n\t\t\t\t\t\t\t\t\tOverride_Mission(MISSION_ATTACK, Map[destcell].Cell_Object()->As_Target(), TARGET_NONE);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (Map[destcell].Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(Map[destcell].Overlay).IsWall) {\n\t\t\t\t\t\t\t\t\tOverride_Mission(MISSION_ATTACK, ::As_Target(destcell), TARGET_NONE);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tIsNewNavCom = false;\n\t\t\t\t\t\t\tTrackIndex = 0;\n\t\t\t\t\t\t\treturn(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmemcpy((char*)&Path[0], (char*)&Path[2], CONQUER_PATH_MAX-2);\n\t\t\t\t\t\tPath[CONQUER_PATH_MAX-2] = FACING_NONE;\n\t\t\t\t\t\tIsPlanningToLook = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tmemcpy((char*)&Path[0], (char*)&Path[1], CONQUER_PATH_MAX-1);\n\t\t\t\t}\n\t\t\t\tPath[CONQUER_PATH_MAX-1] = FACING_NONE;\n\t\t\t}\n\t\t}\n\n\t\tIsNewNavCom = false;\n\t\tTrackIndex = 0;\n\t\tif (!Start_Driver(dest)) {\n\t\t\tTrackNumber = -1;\n\t\t\tPath[0] = FACING_NONE;\n\t\t\tSet_Speed(0);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * DriveClass::AI -- Processes unit movement and rotation.                                     *\n *                                                                                             *\n *    This routine is used to process unit movement and rotation. It                           *\n *    functions autonomously from the script system. Thus, once a unit                         *\n *    is give rotation command or movement path, it will follow this                           *\n *    until specifically instructed to stop. The advantage of this                             *\n *    method is that it allows smooth movement of units, faster game                           *\n *    execution, and reduced script complexity (since actual movement                          *\n *    dynamics need not be controlled directly by the scripts).                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine relies on the process control bits for the                         *\n *             specified unit (for speed reasons). Thus, only setting                          *\n *             movement, rotation, or path list will the unit perform                          *\n *             any physics.                                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/26/1993 JLB : Created.                                                                 *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nvoid DriveClass::AI(void)\n{\n\tassert(IsActive);\n\n\tFootClass::AI();\n\tif (!IsActive || Height > 0) return;\n\n\t/*\n\t** Is this a unit that's been teleported using the chronosphere, and if so,\n\t** has his timer expired such that he needs to teleport back?\n\t*/\n\tif (IsMoebius) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t if (What_Am_I() != RTTI_UNIT || ((UnitClass *)this)->Class->Type != UNIT_CHRONOTANK) {\n#endif\n\t\tif (MoebiusCountDown == 0) {\n\t\t\tIsMoebius = false;\n\t\t\tTeleport_To(MoebiusCell);\n\t\t\tMoebiusCell = 0;\n\t\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t }\n#endif\n\t}\n\n\t/*\n\t**\tIf the unit is following a track, then continue\n\t**\tto do so -- mindlessly.\n\t*/\n\tif (TrackNumber != -1) {\n\n\t\t/*\n\t\t**\tPerform the movement accumulation.\n\t\t*/\n\t\tWhile_Moving();\n\t\tif (!IsActive) return;\n\t\tif (TrackNumber == -1 && (Target_Legal(NavCom) || Path[0] != FACING_NONE) && (What_Am_I() != RTTI_UNIT || !((UnitClass*)this)->IsDumping)) {\n\t\t\tStart_Of_Move();\n\t\t\tif (!IsActive) return;\n\t\t\tWhile_Moving();\n\t\t\tif (!IsActive) return;\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tFor tracked units that are rotating in place, perform the rotation now.\n\t\t*/\n#ifdef TOFIX\n\t\tif ((Class->Speed == SPEED_FLOAT || Class->Speed == SPEED_HOVER || Class->Speed == SPEED_TRACK || (Class->Speed == SPEED_WHEEL && !Special.IsThreePoint)) && PrimaryFacing.Is_Rotating()) {\n\t\t\tif (PrimaryFacing.Rotation_Adjust(Class->ROT)) {\n\t\t\t\tMark(MARK_CHANGE);\n\t\t\t}\n#else\n\t\tif (PrimaryFacing.Is_Rotating()) {\n\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\tif (PrimaryFacing.Rotation_Adjust(Techno_Type_Class()->ROT * House->GroundspeedBias)) {\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t}\n#endif\n\t\t\tif (!IsRotating) {\n\t\t\t\tPer_Cell_Process(PCP_ROTATION);\n\t\t\t\tif (!IsActive) return;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tThe unit has no track to follow, but if there\n\t\t\t**\tis a navigation target or a remaining path,\n\t\t\t**\tthen start on a new track.\n\t\t\t*/\n\t\t\tif ((Mission != MISSION_GUARD || Target_Legal(NavCom)) && Mission != MISSION_UNLOAD) {\n\t\t\t\tif (Target_Legal(NavCom) || Path[0] != FACING_NONE) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDouble check to make sure that the movement destination is\n\t\t\t\t\t**\tin a zone that this unit can travel to. If not, then abort\n\t\t\t\t\t**\tthe navigation target.\n\t\t\t\t\t*/\n\t\t\t\t\tif (IsLocked && Mission != MISSION_ENTER && Target_Legal(NavCom) && !Is_In_Same_Zone(As_Cell(NavCom))) {\n\t\t\t\t\t\tStop_Driver();\n\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tStart_Of_Move();\n\t\t\t\t\t\tif (!IsActive) return;\n\t\t\t\t\t\tWhile_Moving();\n\t\t\t\t\t\tif (!IsActive) return;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tStop_Driver();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::Fixup_Path -- Adds smooth start path to normal movement path.                   *\n *                                                                                             *\n *    This routine modifies the path of the specified unit so that it                          *\n *    will not start out with a rotation. This is necessary for those                          *\n *    vehicles that have difficulty with rotating in place. Typically,                         *\n *    this includes wheeled vehicles.                                                          *\n *                                                                                             *\n * INPUT:   unit  -- Pointer to the unit to adjust.                                            *\n *                                                                                             *\n *          path  -- Pointer to path structure.                                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only units that require a fixup get modified. The                               *\n *             modification only occurs, if there is a legal path to                           *\n *             do so.                                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/03/1994 JLB : Created.                                                                 *\n *   04/06/1994 JLB : Uses path structure.                                                     *\n *   04/10/1994 JLB : Diagonal smooth turn added.                                              *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nvoid DriveClass::Fixup_Path(PathType * path)\n{\n\tassert(IsActive);\n\n\tFacingType stage[6]={FACING_N,FACING_N,FACING_N,FACING_N,FACING_N,FACING_N};\t\t// Prefix path elements.\n\tint\tfacediff;\t\t// The facing difference value (0..4 | 0..-4).\n\tstatic FacingType _path[4][6] = {\n\t\t{(FacingType)2,(FacingType)0,(FacingType)2,(FacingType)0,(FacingType)0,(FacingType)0},\n\t\t{(FacingType)3,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)0,(FacingType)0},\n\t\t{(FacingType)4,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)0,(FacingType)0},\n\t\t{(FacingType)4,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)1,(FacingType)0}\n\t};\n\tstatic FacingType _dpath[4][6] = {\n\t\t{(FacingType)0,(FacingType)0,(FacingType)0,(FacingType)0,(FacingType)0,(FacingType)0},\n\t\t{(FacingType)3,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)0,(FacingType)0},\n\t\t{(FacingType)4,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)1,(FacingType)0},\n\t\t{(FacingType)5,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)1,(FacingType)0}\n\t};\n\n\tint\t\t\tindex;\n\tint\t\t\tcounter;\t\t\t// Path addition\n\tFacingType\t* ptr;\t\t\t\t// Path list pointer.\n\tFacingType\t* ptr2;\t\t\t// Copy of new path list pointer.\n\tFacingType\tnextpath;\t\t// Next path value.\n\tCELL\t\t\tcell;\t\t\t\t// Working cell value.\n\tbool\t\t\tok;\n\n\t/*\n\t**\tVerify that the unit is valid and there is a path problem to resolve.\n\t*/\n\tif (!path || path->Command[0] == FACING_NONE) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tOnly wheeled vehicles need a path fixup -- to avoid 3 point turns.\n\t*/\n#ifdef TOFIX\n\tif (!Special.IsThreePoint || Class->Speed != SPEED_WHEEL) {\n#else\n\tif (What_Am_I() == RTTI_UNIT || What_Am_I() == RTTI_VESSEL) {\n//\tif (What_Am_I() == RTTI_UNIT) {\n#endif\n\t\treturn;\n\t}\n\n\t/*\n\t**\tIf the original path starts in the same direction as the unit, then\n\t**\tthere is no problem to resolve -- abort.\n\t*/\n\tfacediff = PrimaryFacing.Difference((DirType)(path->Command[0]<<5)) >> 5;\n\n\tif (!facediff) return;\n\n\tif (Dir_Facing(PrimaryFacing) & FACING_NE) {\n\t\tptr = &_dpath[(FacingType)ABS((int)facediff)-FACING_NE][1];\t\t\t// Pointer to path adjust list.\n \t\tcounter = (int)_dpath[(FacingType)ABS((int)facediff)-FACING_NE][0];\t\t// Number of path adjusts.\n\t} else {\n\t\tptr = &_path[(FacingType)ABS((int)facediff)-FACING_NE][1];\t\t\t// Pointer to path adjust list.\n \t\tcounter = (int)_path[(FacingType)ABS((int)facediff)-FACING_NE][0];\t\t// Number of path adjusts.\n\t}\n\tptr2 = ptr;\n\n\tok = true;\t\t\t\t\t\t\t\t\t\t// Presume adjustment is all ok.\n\tcell = Coord_Cell(Coord);\t// Starting cell.\n\tnextpath = Dir_Facing(PrimaryFacing);\t// Starting path.\n\tfor (index = 0; index < counter; index++) {\n\n\t\t/*\n\t\t**\tDetermine next path element and add it to the\n\t\t**\tworking path list.\n\t\t*/\n\t\tif (facediff > 0) {\n\t\t\tnextpath = nextpath + *ptr++;\n\t\t} else {\n\t\t\tnextpath = nextpath - *ptr++;\n\t\t}\n\t\tstage[index] = nextpath;\n\t\tcell = Adjacent_Cell(cell, nextpath);\n\t\t//cell = Coord_Cell(Adjacent_Cell(Cell_Coord(cell), nextpath));\n\n\t\t/*\n\t\t**\tIf it can't enter this cell, then abort the path\n\t\t**\tbuilding operation without adjusting the unit's\n\t\t**\tpath.\n\t\t*/\n\t\tif (Can_Enter_Cell(cell, nextpath) != MOVE_OK) {\n\t\t\tok = false;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf veering to the left was not successful, then try veering\n\t**\tto the right. This only makes sense if the vehicle is trying\n\t**\tto turn 180 degrees.\n\t*/\n\tif (!ok && ABS(facediff) == 4) {\n\t\tptr = ptr2;\t\t\t\t\t\t\t\t\t\t\t// Pointer to path adjust list.\n\t\tfacediff = -facediff;\n\t\tok = true;\t\t\t\t\t\t\t\t\t\t\t// Presume adjustment is all ok.\n\t\tcell = Coord_Cell(Coord);\t\t\t\t\t\t// Starting cell.\n\t\tnextpath = Dir_Facing(PrimaryFacing);\t\t// Starting path.\n\t\tfor (index = 0; index < counter; index++) {\n\n\t\t\t/*\n\t\t\t**\tDetermine next path element and add it to the\n\t\t\t**\tworking path list.\n\t\t\t*/\n\t\t\tif (facediff > 0) {\n\t\t\t\tnextpath = nextpath + *ptr++;\n\t\t\t} else {\n\t\t\t\tnextpath = nextpath - *ptr++;\n\t\t\t}\n\t\t\tstage[index] = nextpath;\n\t\t\tcell = Coord_Cell(Adjacent_Cell(Cell_Coord(cell), nextpath));\n\n\t\t\t/*\n\t\t\t**\tIf it can't enter this cell, then abort the path\n\t\t\t**\tbuilding operation without adjusting the unit's\n\t\t\t**\tpath.\n\t\t\t*/\n\t\t\tif (Can_Enter_Cell(cell, nextpath) != MOVE_OK) {\n\t\t\t\tok = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf a legal path addition was created, then install it in place\n\t**\tof the first path value. The initial path entry is to be replaced\n\t**\twith a sequence of path entries that create smooth turning.\n\t*/\n\tif (ok) {\n\t\tif (path->Length <= 1) {\n\t\t\tmemmove((char *)&stage[0], (char*)path->Command, max(counter, 1));\n\t\t\tpath->Length = counter;\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tOptimize the transition path step from the smooth turn\n\t\t\t**\tfirst part as it joins with the rest of the normal\n\t\t\t**\tpath. The normal prefix path steps are NOT to be optimized.\n\t\t\t*/\n\t\t\tif (counter) {\n\t\t\t\tcounter--;\n\t\t\t\tpath->Command[0] = stage[counter];\n\t\t\t\tOptimize_Moves(path, MOVE_OK);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf there is more than one prefix path element, then\n\t\t\t**\tinsert the rest now.\n\t\t\t*/\n\t\t\tif (counter) {\n\t\t\t\tmemmove((char*)&path->Command[0], (char*)&path->Command[counter], 40-counter);\n\t\t\t\tmemmove((char*)&stage[0], (char*)&path->Command[0], counter);\n\t\t\t\tpath->Length += counter;\n\t\t\t}\n\t\t}\n\t\tpath->Command[path->Length] = FACING_NONE;\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::Lay_Track -- Handles track laying logic for the unit.                           *\n *                                                                                             *\n *    This routine handles the track laying for the unit. This entails examining the unit's    *\n *    current location as well as the direction and whether this unit is allowed to lay        *\n *    tracks in the first place.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DriveClass::Lay_Track(void)\n{\n\tassert(IsActive);\n\n#ifdef NEVER\n\tstatic IconCommandType * _trackdirs[8] = {\n\t\tTrackN_S,\n\t\tTrackNE_SW,\n\t\tTrackE_W,\n\t\tTrackNW_SE,\n\t\tTrackN_S,\n\t\tTrackNE_SW,\n\t\tTrackE_W,\n\t\tTrackNW_SE\n\t};\n\n\tif (!(ClassF & CLASSF_TRACKS)) return;\n\n\tIcon_Install(Coord_Cell(Coord), _trackdirs[Facing_To_8(BodyFacing)]);\n#endif\n}\n\n\n/***********************************************************************************************\n * DriveClass::Mark_Track -- Marks the midpoint of the track as occupied.                      *\n *                                                                                             *\n *    This routine will ensure that the midpoint (if any) of the track that the unit is        *\n *    following, will be marked according to the mark type specified.                          *\n *                                                                                             *\n * INPUT:   headto   -- The head to coordinate.                                                *\n *                                                                                             *\n *          type     -- The type of marking to perform.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DriveClass::Mark_Track(COORDINATE headto, MarkType type)\n{\n\tassert(IsActive);\n\n\tint value;\n\n\tif (type == MARK_UP) {\n\t\tvalue = false;\n\t} else {\n\t\tvalue = true;\n\t}\n\n\tif (headto) {\n\t\tif (!IsOnShortTrack && TrackNumber != -1) {\n\n\t\t\t/*\n\t\t\t** If we have not passed the per cell process point we need\n\t\t\t** to deal with it.\n\t\t\t*/\n\t\t\tint tracknum = TrackControl[TrackNumber].Track;\n\t\t\tif (tracknum) {\n\t\t\t\tTrackType const * ptr = RawTracks[tracknum - 1].Track;\n\t\t\t\tint cellidx = RawTracks[tracknum - 1].Cell;\n\t\t\t\tif (cellidx > -1) {\n\t\t\t\t\tDirType dir = ptr[cellidx].Facing;\n\n\t\t\t\t\tif (TrackIndex < cellidx && cellidx != -1) {\n\t\t\t\t\t\tCOORDINATE offset = Smooth_Turn(ptr[cellidx].Offset, dir);\n\t\t\t\t\t\tMap[offset].Flag.Occupy.Vehicle = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tMap[headto].Flag.Occupy.Vehicle = value;\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::Ok_To_Move -- Checks to see if this object can begin moving.                    *\n *                                                                                             *\n *    This routine is used to verify that this object is allowed to move. Some objects can     *\n *    be temporarily occupied and thus cannot move until the situation permits.                *\n *                                                                                             *\n * INPUT:   direction   -- The direction that movement would be desired.                       *\n *                                                                                             *\n * OUTPUT:  Can the unit move in the direction specified?                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool DriveClass::Ok_To_Move(DirType ) const\n{\n\tassert(IsActive);\n\n\treturn true;\n}\n\n\n/***************************************************************************\n**\tSmooth turn track tables. These are coordinate offsets from the center\n**\tof the destination cell. These are the raw tracks that are modified\n**\tby negating the X and Y portions as necessary. Also for reverse travelling\n**\tdirection, the track list can be processed backward.\n**\n**\tTrack 1 = N\n**\tTrack 2 = NE\n**\tTrack 3 = N->NE 45 deg (double path consumption)\n**\tTrack 4 = N->E 90 deg (double path consumption)\n**\tTrack 5 = NE->SE 90 deg (double path consumption)\n** Track 6 = NE->N 45 deg (double path consumption)\n**\tTrack 7 = N->NE (facing change only)\n**\tTrack 8 = NE->E (facing change only)\n**\tTrack 9 = N->E (facing change only)\n**\tTrack 10= NE->SE (facing change only)\n**\tTrack 11= back up into refinery\n**\tTrack 12= drive out of refinery\n*/\n#pragma warn -ias\nDriveClass::TrackType const DriveClass::Track1[24] = {\n\t{0x00F50000L,(DirType)0},\n\t{0x00EA0000L,(DirType)0},\n\t{0x00DF0000L,(DirType)0},\n\t{0x00D40000L,(DirType)0},\n\t{0x00C90000L,(DirType)0},\n\t{0x00BE0000L,(DirType)0},\n\t{0x00B30000L,(DirType)0},\n\t{0x00A80000L,(DirType)0},\n\t{0x009D0000L,(DirType)0},\n\t{0x00920000L,(DirType)0},\n\t{0x00870000L,(DirType)0},\n\t{0x007C0000L,(DirType)0},\t\t// Track jump check here.\n\t{0x00710000L,(DirType)0},\n\t{0x00660000L,(DirType)0},\n\t{0x005B0000L,(DirType)0},\n\t{0x00500000L,(DirType)0},\n\t{0x00450000L,(DirType)0},\n\t{0x003A0000L,(DirType)0},\n\t{0x002F0000L,(DirType)0},\n\t{0x00240000L,(DirType)0},\n\t{0x00190000L,(DirType)0},\n\t{0x000E0000L,(DirType)0},\n\t{0x00030000L,(DirType)0},\n\t{0x00000000L,(DirType)0}\n};\n\nDriveClass::TrackType const DriveClass::Track2[] = {\n\t{0x00F8FF08L,(DirType)32},\n\t{0x00F0FF10L,(DirType)32},\n\t{0x00E8FF18L,(DirType)32},\n\t{0x00E0FF20L,(DirType)32},\n\t{0x00D8FF28L,(DirType)32},\n\t{0x00D0FF30L,(DirType)32},\n\t{0x00C8FF38L,(DirType)32},\n\t{0x00C0FF40L,(DirType)32},\n\t{0x00B8FF48L,(DirType)32},\n\t{0x00B0FF50L,(DirType)32},\n\t{0x00A8FF58L,(DirType)32},\n\t{0x00A0FF60L,(DirType)32},\n\t{0x0098FF68L,(DirType)32},\n\t{0x0090FF70L,(DirType)32},\n\t{0x0088FF78L,(DirType)32},\n\t{0x0080FF80L,(DirType)32},\t\t// Track jump check here.\n\t{0x0078FF88L,(DirType)32},\n\t{0x0070FF90L,(DirType)32},\n\t{0x0068FF98L,(DirType)32},\n\t{0x0060FFA0L,(DirType)32},\n\t{0x0058FFA8L,(DirType)32},\n\t{0x0050FFB0L,(DirType)32},\n\t{0x0048FFB8L,(DirType)32},\n\t{0x0040FFC0L,(DirType)32},\n\t{0x0038FFC8L,(DirType)32},\n\t{0x0030FFD0L,(DirType)32},\n\t{0x0028FFD8L,(DirType)32},\n\t{0x0020FFE0L,(DirType)32},\n\t{0x0018FFE8L,(DirType)32},\n\t{0x0010FFF0L,(DirType)32},\n\t{0x0008FFF8L,(DirType)32},\n\t{0x00000000L,(DirType)32}\n};\n\nDriveClass::TrackType const DriveClass::Track3[] = {\n\t{0x01F5FF00L,(DirType)0},\n\t{0x01EAFF00L,(DirType)0},\n\t{0x01DFFF00L,(DirType)0},\n\t{0x01D4FF00L,(DirType)0},\n\t{0x01C9FF00L,(DirType)0},\n\t{0x01BEFF00L,(DirType)0},\n\t{0x01B3FF00L,(DirType)0},\n\t{0x01A8FF00L,(DirType)0},\n\t{0x019DFF00L,(DirType)0},\n\t{0x0192FF00L,(DirType)0},\n\t{0x0187FF00L,(DirType)0},\n\t{0x0180FF00L,(DirType)0},\n\t{0x0175FF00L,(DirType)0},\t\t// Jump entry point here.\n\t{0x016BFF00L,(DirType)0},\n\t{0x0160FF02L,(DirType)1},\n\t{0x0155FF04L,(DirType)3},\n\t{0x014CFF06L,(DirType)4},\n\t{0x0141FF08L,(DirType)5},\n\t{0x0137FF0BL,(DirType)7},\n\t{0x012EFF0FL,(DirType)8},\n\t{0x0124FF13L,(DirType)9},\n\t{0x011AFF17L,(DirType)11},\n\t{0x0110FF1BL,(DirType)12},\n\t{0x0107FF1FL,(DirType)13},\t\t// Center cell processing here.\n\t{0x00FCFF24L,(DirType)15},\n\t{0x00F3FF28L,(DirType)16},\n\t{0x00ECFF2CL,(DirType)17},\n\t{0x00E0FF32L,(DirType)19},\n\t{0x00D7FF36L,(DirType)20},\n\t{0x00CFFF3DL,(DirType)21},\n\t{0x00C6FF42L,(DirType)23},\n\t{0x00BAFF49L,(DirType)24},\n\t{0x00B0FF4DL,(DirType)25},\n\t{0x00A8FF58L,(DirType)27},\n\t{0x00A0FF60L,(DirType)28},\n\t{0x0098FF68L,(DirType)29},\n\t{0x0090FF70L,(DirType)31},\n\t{0x0088FF78L,(DirType)32},\n\t{0x0080FF80L,(DirType)32},\t\t// Track jump check here.\n\t{0x0078FF88L,(DirType)32},\n\t{0x0070FF90L,(DirType)32},\n\t{0x0068FF98L,(DirType)32},\n\t{0x0060FFA0L,(DirType)32},\n\t{0x0058FFA8L,(DirType)32},\n\t{0x0050FFB0L,(DirType)32},\n\t{0x0048FFB8L,(DirType)32},\n\t{0x0040FFC0L,(DirType)32},\n\t{0x0038FFC8L,(DirType)32},\n\t{0x0030FFD0L,(DirType)32},\n\t{0x0028FFD8L,(DirType)32},\n\t{0x0020FFE0L,(DirType)32},\n\t{0x0018FFE8L,(DirType)32},\n\t{0x0010FFF0L,(DirType)32},\n\t{0x0008FFF8L,(DirType)32},\n\t{0x00000000L,(DirType)32}\n};\n\nDriveClass::TrackType const DriveClass::Track4[] = {\n\t{0x00F5FF00L,(DirType)0},\n\t{0x00EBFF00L,(DirType)0},\n\t{0x00E0FF00L,(DirType)0},\n\t{0x00D5FF00L,(DirType)0},\n\t{0x00CBFF01L,(DirType)0},\n\t{0x00C0FF03L,(DirType)0},\n\t{0x00B5FF05L,(DirType)1},\n\t{0x00ABFF07L,(DirType)1},\n\t{0x00A0FF0AL,(DirType)2},\n\t{0x0095FF0DL,(DirType)3},\n\t{0x008BFF10L,(DirType)4},\n\t{0x0080FF14L,(DirType)5},\t\t// Track entry here.\n\t{0x0075FF18L,(DirType)8},\n\t{0x006DFF1CL,(DirType)12},\n\t{0x0063FF22L,(DirType)16},\n\t{0x005AFF25L,(DirType)20},\n\t{0x0052FF2BL,(DirType)23},\n\t{0x0048FF32L,(DirType)27},\n\t{0x0040FF37L,(DirType)32},\n\t{0x0038FF3DL,(DirType)36},\n\t{0x0030FF46L,(DirType)39},\n\t{0x002BFF4FL,(DirType)43},\n\t{0x0024FF58L,(DirType)47},\n\t{0x0020FF60L,(DirType)51},\n\t{0x001BFF6DL,(DirType)54},\n\t{0x0017FF79L,(DirType)57},\n\t{0x0014FF82L,(DirType)60},\t\t// Track jump here.\n\t{0x0011FF8FL,(DirType)62},\n\t{0x000DFF98L,(DirType)63},\n\t{0x0009FFA2L,(DirType)64},\n\t{0x0006FFACL,(DirType)64},\n\t{0x0004FFB5L,(DirType)66},\n\t{0x0003FFC0L,(DirType)64},\n\t{0x0002FFCBL,(DirType)64},\n\t{0x0001FFD5L,(DirType)64},\n\t{0x0000FFE0L,(DirType)64},\n\t{0x0000FFEBL,(DirType)64},\n\t{0x0000FFF5L,(DirType)64},\n\t{0x00000000L,(DirType)64}\n};\n\nDriveClass::TrackType const DriveClass::Track5[] = {\n\t{0xFFF8FE08L,(DirType)32},\n\t{0xFFF0FE10L,(DirType)32},\n\t{0xFFE8FE18L,(DirType)32},\n\t{0xFFE0FE20L,(DirType)32},\n\t{0xFFD8FE28L,(DirType)32},\n\t{0xFFD0FE30L,(DirType)32},\n\t{0xFFC8FE38L,(DirType)32},\n\t{0xFFC0FE40L,(DirType)32},\n\t{0xFFB8FE48L,(DirType)32},\n\t{0xFFB0FE50L,(DirType)32},\n\t{0xFFA8FE58L,(DirType)32},\n\t{0xFFA0FE60L,(DirType)32},\n\t{0xFF98FE68L,(DirType)32},\n\t{0xFF90FE70L,(DirType)32},\n\t{0xFF88FE78L,(DirType)32},\n\t{0xFF80FE80L,(DirType)32},\t\t// Track entry here.\n\t{0xFF78FE88L,(DirType)32},\n\t{0xFF71FE90L,(DirType)32},\n\t{0xFF6AFE97L,(DirType)32},\n\t{0xFF62FE9FL,(DirType)32},\n\t{0xFF5AFEA8L,(DirType)32},\n\t{0xFF53FEB0L,(DirType)35},\n\t{0xFF4BFEB7L,(DirType)38},\n\t{0xFF44FEBEL,(DirType)41},\n\t{0xFF3EFEC4L,(DirType)44},\n\t{0xFF39FECEL,(DirType)47},\n\t{0xFF34FED8L,(DirType)50},\n\t{0xFF30FEE0L,(DirType)53},\n\t{0xFF2DFEEBL,(DirType)56},\n\t{0xFF2CFEF5L,(DirType)59},\n\t{0xFF2BFF00L,(DirType)62},\n\t{0xFF2CFF0BL,(DirType)66},\n\t{0xFF2DFF15L,(DirType)69},\n\t{0xFF30FF1FL,(DirType)72},\n\t{0xFF34FF28L,(DirType)75},\n\t{0xFF39FF30L,(DirType)78},\n\t{0xFF3EFF3AL,(DirType)81},\n\t{0xFF44FF44L,(DirType)84},\n\t{0xFF4BFF4BL,(DirType)87},\n\t{0xFF53FF50L,(DirType)90},\n\t{0xFF5AFF58L,(DirType)93},\n\t{0xFF62FF60L,(DirType)96},\n\t{0xFF6AFF68L,(DirType)96},\n\t{0xFF71FF70L,(DirType)96},\n\t{0xFF78FF78L,(DirType)96},\n\t{0xFF80FF80L,(DirType)96},\t\t// Track jump check here.\n\t{0xFF88FF88L,(DirType)96},\n\t{0xFF90FF90L,(DirType)96},\n\t{0xFF98FF98L,(DirType)96},\n\t{0xFFA0FFA0L,(DirType)96},\n\t{0xFFA8FFA8L,(DirType)96},\n\t{0xFFB0FFB0L,(DirType)96},\n\t{0xFFB8FFB8L,(DirType)96},\n\t{0xFFC0FFC0L,(DirType)96},\n\t{0xFFC8FFC8L,(DirType)96},\n\t{0xFFD0FFD0L,(DirType)96},\n\t{0xFFD8FFD8L,(DirType)96},\n\t{0xFFE0FFE0L,(DirType)96},\n\t{0xFFE8FFE8L,(DirType)96},\n\t{0xFFF0FFF0L,(DirType)96},\n\t{0xFFF8FFF8L,(DirType)96},\n\t{0x00000000L,(DirType)96}\n};\n\nDriveClass::TrackType const DriveClass::Track6[] = {\n\t{0x0100FE00L,(DirType)32},\n\t{0x00F8FE08L,(DirType)32},\n\t{0x00F0FE10L,(DirType)32},\n\t{0x00E8FE18L,(DirType)32},\n\t{0x00E0FE20L,(DirType)32},\n\t{0x00D8FE28L,(DirType)32},\n\t{0x00D0FE30L,(DirType)32},\n\t{0x00C8FE38L,(DirType)32},\n\t{0x00C0FE40L,(DirType)32},\n\t{0x00B8FE48L,(DirType)32},\n\t{0x00B0FE50L,(DirType)32},\n\t{0x00A8FE58L,(DirType)32},\n\t{0x00A0FE60L,(DirType)32},\n\t{0x0098FE68L,(DirType)32},\n\t{0x0090FE70L,(DirType)32},\n\t{0x0088FE78L,(DirType)32},\n\t{0x0080FE80L,(DirType)32},\t\t// Jump entry point here.\n\t{0x0078FE88L,(DirType)32},\n\t{0x0070FE90L,(DirType)32},\n\t{0x0068FE98L,(DirType)32},\n\t{0x0060FEA0L,(DirType)32},\n\t{0x0058FEA8L,(DirType)32},\n\t{0x0055FEAEL,(DirType)32},\n\t{0x004EFEB8L,(DirType)35},\n\t{0x0048FEC0L,(DirType)37},\n\t{0x0042FEC9L,(DirType)40},\n\t{0x003BFED2L,(DirType)43},\n\t{0x0037FEDAL,(DirType)45},\n\t{0x0032FEE3L,(DirType)48},\n\t{0x002BFEEBL,(DirType)51},\n\t{0x0026FEF5L,(DirType)53},\n\t{0x0022FEFEL,(DirType)56},\n\t{0x001CFF08L,(DirType)59},\n\t{0x0019FF12L,(DirType)61},\n\t{0x0015FF1BL,(DirType)64},\n\t{0x0011FF26L,(DirType)64},\n\t{0x000EFF30L,(DirType)64},\n\t{0x000BFF39L,(DirType)64},\n\t{0x0009FF43L,(DirType)64},\n\t{0x0007FF4EL,(DirType)64},\n\t{0x0005FF57L,(DirType)64},\n\t{0x0003FF62L,(DirType)64},\n\t{0x0001FF6DL,(DirType)64},\n\t{0x0000FF77L,(DirType)64},\n\t{0x0000FF80L,(DirType)64},\t\t// Track jump check here.\n\t{0x0000FF8BL,(DirType)64},\n\t{0x0000FF95L,(DirType)64},\n\t{0x0000FFA0L,(DirType)64},\n\t{0x0000FFABL,(DirType)64},\n\t{0x0000FFB5L,(DirType)64},\n\t{0x0000FFC0L,(DirType)64},\n\t{0x0000FFCBL,(DirType)64},\n\t{0x0000FFD5L,(DirType)64},\n\t{0x0000FFE0L,(DirType)64},\n\t{0x0000FFEBL,(DirType)64},\n\t{0x0000FFF5L,(DirType)64},\n\t{0x00000000L,(DirType)64}\n};\n\nDriveClass::TrackType const DriveClass::Track7[] = {\n\t{0x0006FFFFL,(DirType)0},\n\t{0x000CFFFEL,(DirType)4},\n\t{0x0011FFFCL,(DirType)8},\n\t{0x0018FFFAL,(DirType)12},\n\t{0x001FFFF6L,(DirType)16},\n\t{0x0024FFF3L,(DirType)19},\n\t{0x002BFFF0L,(DirType)22},\n\t{0x0030FFFDL,(DirType)23},\n\t{0x0035FFEBL,(DirType)24},\n\t{0x0038FFE8L,(DirType)25},\n\t{0x003CFFE6L,(DirType)26},\n\t{0x0040FFE3L,(DirType)27},\n\t{0x0043FFE0L,(DirType)28},\n\t{0x0046FFDDL,(DirType)29},\n\t{0x0043FFDFL,(DirType)30},\n\t{0x0040FFE1L,(DirType)30},\n\t{0x003CFFE3L,(DirType)30},\n\t{0x0038FFE5L,(DirType)30},\n\t{0x0035FFE7L,(DirType)31},\n\t{0x0030FFE9L,(DirType)31},\n\t{0x002BFFEBL,(DirType)31},\n\t{0x0024FFEDL,(DirType)31},\n\t{0x001FFFF1L,(DirType)31},\n\t{0x0018FFF4L,(DirType)32},\n\t{0x0011FFF7L,(DirType)32},\n\t{0x000CFFFAL,(DirType)32},\n\t{0x0006FFFDL,(DirType)32},\n\t{0x00000000L,(DirType)32}\n};\n\nDriveClass::TrackType const DriveClass::Track8[] = {\n\t{0x0003FFFCL,(DirType)32},\n\t{0x0006FFF7L,(DirType)36},\n\t{0x000AFFF1L,(DirType)40},\n\t{0x000CFFEBL,(DirType)44},\n\t{0x000DFFE4L,(DirType)46},\n\t{0x000EFFDCL,(DirType)48},\n\t{0x000FFFD5L,(DirType)50},\n\t{0x0010FFD0L,(DirType)52},\n\t{0x0011FFC9L,(DirType)54},\n\t{0x0012FFC2L,(DirType)56},\n\t{0x0011FFC0L,(DirType)58},\n\t{0x0010FFC2L,(DirType)60},\n\t{0x000EFFC9L,(DirType)62},\n\t{0x000CFFCFL,(DirType)64},\n\t{0x000AFFD5L,(DirType)64},\n\t{0x0008FFDAL,(DirType)64},\n\t{0x0006FFE2L,(DirType)64},\n\t{0x0004FFE9L,(DirType)64},\n\t{0x0002FFEFL,(DirType)64},\n\t{0x0001FFF5L,(DirType)64},\n\t{0x0000FFF9L,(DirType)64},\n\t{0x00000000L,(DirType)64}\n};\n\nDriveClass::TrackType const DriveClass::Track9[] = {\n\t{0xFFF50002L,(DirType)0},\n\t{0xFFEB0004L,(DirType)2},\n\t{0xFFE00006L,(DirType)4},\n\t{0xFFD50009L,(DirType)6},\n\t{0xFFCE000CL,(DirType)9},\n\t{0xFFC8000FL,(DirType)11},\n\t{0xFFC00012L,(DirType)13},\n\t{0xFFB80015L,(DirType)16},\n\t{0xFFC00012L,(DirType)18},\n\t{0xFFC8000EL,(DirType)20},\n\t{0xFFCE000AL,(DirType)22},\n\t{0xFFD50004L,(DirType)24},\n\t{0xFFDE0000L,(DirType)26},\n\t{0xFFE9FFF8L,(DirType)28},\n\t{0xFFEEFFF2L,(DirType)30},\n\t{0xFFF5FFEBL,(DirType)32},\n\t{0xFFFDFFE1L,(DirType)34},\n\t{0x0002FFD8L,(DirType)36},\n\t{0x0007FFD2L,(DirType)39},\n\t{0x000BFFCBL,(DirType)41},\n\t{0x0010FFC5L,(DirType)43},\n\t{0x0013FFBEL,(DirType)45},\n\t{0x0015FFB7L,(DirType)48},\n\t{0x0013FFBEL,(DirType)50},\n\t{0x0011FFC5L,(DirType)52},\n\t{0x000BFFCCL,(DirType)54},\n\t{0x0008FFD4L,(DirType)56},\n\t{0x0005FFDFL,(DirType)58},\n\t{0x0003FFEBL,(DirType)62},\n\t{0x0001FFF5L,(DirType)64},\n\t{0x00000000L,(DirType)64}\n};\n\nDriveClass::TrackType const DriveClass::Track10[] = {\n\t{0xFFF6000BL,(DirType)32},\n\t{0xFFF00015L,(DirType)37},\n\t{0xFFEB0020L,(DirType)42},\n\t{0xFFE9002BL,(DirType)47},\n\t{0xFFE50032L,(DirType)52},\n\t{0xFFE30038L,(DirType)57},\n\t{0xFFE00040L,(DirType)60},\n\t{0xFFE20038L,(DirType)62},\n\t{0xFFE40032L,(DirType)64},\n\t{0xFFE5002AL,(DirType)68},\n\t{0xFFE6001EL,(DirType)70},\n\t{0xFFE70015L,(DirType)72},\n\t{0xFFE8000BL,(DirType)74},\n\t{0xFFE90000L,(DirType)76},\n\t{0xFFE8FFF5L,(DirType)78},\n\t{0xFFE7FFEBL,(DirType)80},\n\t{0xFFE6FFE0L,(DirType)82},\n\t{0xFFE5FFD5L,(DirType)84},\n\t{0xFFE4FFCEL,(DirType)86},\n\t{0xFFE2FFC5L,(DirType)88},\n\t{0xFFE0FFC0L,(DirType)90},\n\t{0xFFE3FFC5L,(DirType)92},\n\t{0xFFE5FFCEL,(DirType)94},\n\t{0xFFE9FFD5L,(DirType)95},\n\t{0xFFEBFFE0L,(DirType)96},\n\t{0xFFF0FFEBL,(DirType)96},\n\t{0xFFF6FFF5L,(DirType)96},\n\t{0x00000000L,(DirType)96}\n};\n\nDriveClass::TrackType const DriveClass::Track11[] = {\n\t{0x01000000L,DIR_SW},\n\t{0x00F30008L,DIR_SW},\n\t{0x00E50010L,DIR_SW_X1},\n\t{0x00D60018L,DIR_SW_X1},\n\t{0x00C80020L,DIR_SW_X1},\n\t{0x00B90028L,DIR_SW_X1},\n\t{0x00AB0030L,DIR_SW_X2},\n\t{0x009C0038L,DIR_SW_X2},\n\t{0x008D0040L,DIR_SW_X2},\n\t{0x007F0048L,DIR_SW_X2},\n\t{0x00710050L,DIR_SW_X2},\n\t{0x00640058L,DIR_SW_X2},\n\t{0x00550060L,DIR_SW_X2},\n\n\t{0x00000000L,DIR_SW_X2}\n};\n\nDriveClass::TrackType const DriveClass::Track12[] = {\n\t{0xFF550060L,DIR_SW_X2},\n\t{0xFF640058L,DIR_SW_X2},\n\t{0xFF710050L,DIR_SW_X2},\n\t{0xFF7F0048L,DIR_SW_X2},\n\t{0xFF8D0040L,DIR_SW_X2},\n\t{0xFF9C0038L,DIR_SW_X2},\n\t{0xFFAB0030L,DIR_SW_X2},\n\t{0xFFB90028L,DIR_SW_X1},\n\t{0xFFC80020L,DIR_SW_X1},\n\t{0xFFD60018L,DIR_SW_X1},\n\t{0xFFE50010L,DIR_SW_X1},\n\t{0xFFF30008L,DIR_SW},\n\n\t{0x00000000L,DIR_SW}\n};\n\n#if(1)\n/*\n**\tDrive out of weapon's factory.\n*/\nDriveClass::TrackType const DriveClass::Track13[] = {\n\t{XYP_COORD(0,-35),DIR_S},\n\t{XYP_COORD(0,-34),DIR_S},\n\t{XYP_COORD(0,-33),DIR_S},\n\t{XYP_COORD(0,-32),DIR_S},\n\t{XYP_COORD(0,-31),DIR_S},\n\t{XYP_COORD(0,-30),DIR_S},\n\t{XYP_COORD(0,-29),DIR_S},\n\t{XYP_COORD(0,-28),DIR_S},\n\t{XYP_COORD(0,-27),DIR_S},\n\t{XYP_COORD(0,-26),DIR_S},\n\t{XYP_COORD(0,-25),DIR_S},\n\t{XYP_COORD(0,-24),DIR_S},\n\t{XYP_COORD(0,-23),DIR_S},\n\t{XYP_COORD(0,-22),DIR_S},\n\t{XYP_COORD(0,-21),DIR_S},\n\t{XYP_COORD(0,-20),DIR_S},\n\t{XYP_COORD(0,-19),DIR_S},\n\t{XYP_COORD(0,-18),DIR_S},\n\t{XYP_COORD(0,-17),DIR_S},\n\t{XYP_COORD(0,-16),DIR_S},\n\t{XYP_COORD(0,-15),DIR_S},\n\t{XYP_COORD(0,-14),DIR_S},\n\t{XYP_COORD(0,-13),DIR_S},\n\t{XYP_COORD(0,-12),DIR_S},\n\t{XYP_COORD(0,-11),DIR_S},\n\t{XYP_COORD(0,-10),DIR_S},\n\t{XYP_COORD(0,-9),DIR_S},\n\t{XYP_COORD(0,-8),DIR_S},\n\t{XYP_COORD(0,-7),DIR_S},\n\t{XYP_COORD(0,-6),DIR_S},\n\t{XYP_COORD(0,-5),DIR_S},\n\t{XYP_COORD(0,-4),DIR_S},\n\t{XYP_COORD(0,-3),DIR_S},\n\t{XYP_COORD(0,-2),DIR_S},\n\t{XYP_COORD(0,-1),DIR_S},\n\n\t{0x00000000L,DIR_S}\n};\n#else\n/*\n**\tDrive out of weapon's factory.\n*/\nDriveClass::TrackType const DriveClass::Track13[] = {\n\t{XYP_COORD(10,-21),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(10,-21),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(10,-20),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(10,-20),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(9,-18),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(9,-18),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(9,-17),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(8,-16),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(8,-15),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(7,-14),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(7,-13),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(6,-12),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(6,-11),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(5,-10),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(5,-9),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(4,-8),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(4,-7),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(3,-6),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(3,-5),(DirType)(DIR_SW-9)},\n\t{XYP_COORD(2,-4),(DirType)(DIR_SW-7)},\n\t{XYP_COORD(2,-3),(DirType)(DIR_SW-5)},\n\t{XYP_COORD(1,-2),(DirType)(DIR_SW-3)},\n\t{XYP_COORD(1,-1),(DirType)(DIR_SW-1)},\n\n\t{0x00000000L,DIR_SW}\n};\n#endif\n\n/*\n**\tThere are a limited basic number of tracks that a vehicle can follow. These\n**\tare they. Each track can be interpreted differently but this is controlled\n**\tby the TrackControl structure elaborated elsewhere.\n*/\nDriveClass::RawTrackType const DriveClass::RawTracks[13] = {\n\t{Track1, -1, 0, -1},\n\t{Track2, -1, 0, -1},\n\t{Track3, 37, 12, 22},\n\t{Track4, 26, 11, 19},\n\t{Track5, 45, 15, 31},\n\t{Track6, 44, 16, 27},\n\t{Track7, -1, 0, -1},\n\t{Track8, -1, 0, -1},\n\t{Track9, -1, 0, -1},\n\t{Track10, -1, 0, -1},\n\t{Track11, -1, 0, -1},\n\t{Track12, -1, 0, -1},\n\t{Track13, -1, 0, -1}\n};\n\n\n/***************************************************************************\n**\tSmooth turning control table. Given two directions in a path list, this\n**\ttable determines which track to use and what modifying operations need\n**\tbe performed on the track data.\n*/\nDriveClass::TurnTrackType const DriveClass::TrackControl[67] = {\n\t{1,\t0,\t\tDIR_N,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t0-0\n\t{3,\t7,\t\tDIR_NE,\tF_D},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t0-1 (raw chart)\n\t{4,\t9,\t\tDIR_E,\tF_D},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t0-2 (raw chart)\n\t{0,\t0,\t\tDIR_SE,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t0-3 !\n\t{0,\t0,\t\tDIR_S,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t0-4 !\n\t{0,\t0,\t\tDIR_SW,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t0-5 !\n\t{4,\t9,\t\tDIR_W,\t(DriveClass::TrackControlType)(F_X|F_D)},\t\t\t\t//\t0-6\n\t{3,\t7,\t\tDIR_NW,\t(DriveClass::TrackControlType)(F_X|F_D)},\t\t\t\t//\t0-7\n\t{6,\t8,\t\tDIR_N,\t(DriveClass::TrackControlType)(F_T|F_X|F_Y|F_D)},\t//\t1-0\n\t{2,\t0,\t\tDIR_NE,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t1-1 (raw chart)\n\t{6,\t8,\t\tDIR_E,\tF_D},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t1-2 (raw chart)\n\t{5,\t10,\tDIR_SE,\tF_D},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t1-3 (raw chart)\n\t{0,\t0,\t\tDIR_S,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t1-4 !\n\t{0,\t0,\t\tDIR_SW,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t1-5 !\n\t{0,\t0,\t\tDIR_W,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t1-6 !\n\t{5,\t10,\tDIR_NW,\t(DriveClass::TrackControlType)(F_T|F_X|F_Y|F_D)},\t//\t1-7\n\t{4,\t9,\t\tDIR_N,\t(DriveClass::TrackControlType)(F_T|F_X|F_Y|F_D)},\t//\t2-0\n\t{3,\t7,\t\tDIR_NE,\t(DriveClass::TrackControlType)(F_T|F_X|F_Y|F_D)},\t//\t2-1\n\t{1,\t0,\t\tDIR_E,\t(DriveClass::TrackControlType)(F_T|F_X)},\t\t\t\t//\t2-2\n\t{3,\t7,\t\tDIR_SE,\t(DriveClass::TrackControlType)(F_T|F_X|F_D)},\t\t//\t2-3\n\t{4,\t9,\t\tDIR_S,\t(DriveClass::TrackControlType)(F_T|F_X|F_D)},\t\t//\t2-4\n\t{0,\t0,\t\tDIR_SW,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t2-5 !\n\t{0,\t0,\t\tDIR_W,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t2-6 !\n\t{0,\t0,\t\tDIR_NW,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t2-7 !\n\t{0,\t0,\t\tDIR_N,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t3-0 !\n\t{5,\t10,\tDIR_NE,\t(DriveClass::TrackControlType)(F_Y|F_D)},\t\t\t\t//\t3-1\n\t{6,\t8,\t\tDIR_E,\t(DriveClass::TrackControlType)(F_Y|F_D)},\t\t\t\t//\t3-2\n\t{2,\t0,\t\tDIR_SE,\tF_Y},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t3-3\n\t{6,\t8,\t\tDIR_S,\t(DriveClass::TrackControlType)(F_T|F_X|F_D)},\t\t//\t3-4\n\t{5,\t10,\tDIR_SW,\t(DriveClass::TrackControlType)(F_T|F_X|F_D)},\t\t//\t3-5\n\t{0,\t0,\t\tDIR_W,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t3-6 !\n\t{0,\t0,\t\tDIR_NW,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t3-7 !\n\t{0,\t0,\t\tDIR_N,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t4-0 !\n\t{0,\t0,\t\tDIR_NE,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t4-1 !\n\t{4,\t9,\t\tDIR_E,\t(DriveClass::TrackControlType)(F_Y|F_D)},\t\t\t\t//\t4-2\n\t{3,\t7,\t\tDIR_SE,\t(DriveClass::TrackControlType)(F_Y|F_D)},\t\t\t\t//\t4-3\n\t{1,\t0,\t\tDIR_S,\tF_Y},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t4-4\n\t{3,\t7,\t\tDIR_SW,\t(DriveClass::TrackControlType)(F_X|F_Y|F_D)},\t\t//\t4-5\n\t{4,\t9,\t\tDIR_W,\t(DriveClass::TrackControlType)(F_X|F_Y|F_D)},\t\t//\t4-6\n\t{0,\t0,\t\tDIR_NW,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t4-7 !\n\t{0,\t0,\t\tDIR_N,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t5-0 !\n\t{0,\t0,\t\tDIR_NE,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t5-1 !\n\t{0,\t0,\t\tDIR_E,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t5-2 !\n\t{5,\t10,\tDIR_SE,\t(DriveClass::TrackControlType)(F_T|F_D)},\t\t\t\t//\t5-3\n\t{6,\t8,\t\tDIR_S,\t(DriveClass::TrackControlType)(F_T|F_D)},\t\t\t\t//\t5-4\n\t{2,\t0,\t\tDIR_SW,\tF_T},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t5-5\n\t{6,\t8,\t\tDIR_W,\t(DriveClass::TrackControlType)(F_X|F_Y|F_D)},\t\t//\t5-6\n\t{5,\t10,\tDIR_NW,\t(DriveClass::TrackControlType)(F_X|F_Y|F_D)},\t\t//\t5-7\n\t{4,\t9,\t\tDIR_N,\t(DriveClass::TrackControlType)(F_T|F_Y|F_D)},\t\t//\t6-0\n\t{0,\t0,\t\tDIR_NE,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t6-1 !\n\t{0,\t0,\t\tDIR_E,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t6-2 !\n\t{0,\t0,\t\tDIR_SE,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t6-3 !\n\t{4,\t9,\t\tDIR_S,\t(DriveClass::TrackControlType)(F_T|F_D)},\t\t\t\t//\t6-4\n\t{3,\t7,\t\tDIR_SW,\t(DriveClass::TrackControlType)(F_T|F_D)},\t\t\t\t//\t6-5\n\t{1,\t0,\t\tDIR_W,\tF_T},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t6-6\n\t{3,\t7,\t\tDIR_NW,\t(DriveClass::TrackControlType)(F_T|F_Y|F_D)},\t\t//\t6-7\n\t{6,\t8,\t\tDIR_N,\t(DriveClass::TrackControlType)(F_T|F_Y|F_D)},\t\t//\t7-0\n\t{5,\t10,\tDIR_NE,\t(DriveClass::TrackControlType)(F_T|F_Y|F_D)},\t\t//\t7-1\n\t{0,\t0,\t\tDIR_E,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t7-2 !\n\t{0,\t0,\t\tDIR_SE,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t7-3 !\n\t{0,\t0,\t\tDIR_S,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t7-4 !\n\t{5,\t10,\tDIR_SW,\t(DriveClass::TrackControlType)(F_X|F_D)},\t\t\t\t//\t7-5\n\t{6,\t8,\t\tDIR_W,\t(DriveClass::TrackControlType)(F_X|F_D)},\t\t\t\t//\t7-6\n\t{2,\t0,\t\tDIR_NW,\tF_X},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t7-7\n\n\t{11,\t11,\tDIR_SW,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Backup harvester into refinery.\n\t{12,\t12,\tDIR_SW_X2,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Drive back into refinery.\n\t{13,\t13,\tDIR_SW,\tF_}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Drive out of weapons factory.\n};\n\n\n\n"
  },
  {
    "path": "CODE/DRIVE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/DRIVE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DRIVE.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 14, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 14, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef DRIVE_H\n#define DRIVE_H\n\n#include\t\"foot.h\"\n\n/****************************************************************************\n**\tMovable objects are handled by this class definition. Moveable objects\n**\tcover everything except buildings.\n*/\nclass DriveClass : public FootClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tIf this unit performing harvesting action, then this flag is true. The flag\n\t\t**\tis located here because the other bit flags here give it a free place to\n\t\t**\treside.\n\t\t*/\n\t\tunsigned IsHarvesting:1;\n\n\t\t/*\n\t\t** This flag controls whether the unit has been moebius'd into a\n\t\t** different location, and whether the MoebiusCountDown timer should be\n\t\t** used to take him back where he belongs.\n\t\t*/\n\t\tunsigned IsMoebius:1;\n\n\t\t/*\n\t\t** This controls how long a unit can exist in its alternate location\n\t\t** before being pulled back by the chronosphere into its normal location.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> MoebiusCountDown;\n\n\t\t/*\n\t\t** This is the coord the unit will be taken back to once its moebius\n\t\t** effect wears off.\n\t\t*/\n\t\tCELL MoebiusCell;\n\n\t\t/*\n\t\t**\tSome units must have their turret locked down to face their body direction.\n\t\t**\tWhen this flag is set, this condition is in effect. This flag is a more\n\t\t**\taccurate check than examining the TrackNumber since the turret may be\n\t\t**\trotating into position so that a pending track may start. During this process\n\t\t**\tthe track number does not indicate anything.\n\t\t*/\n\t\tunsigned IsTurretLockedDown:1;\n\n\t\t/*\n\t\t**\tThis vehicle could be processing a \"short track\". A short track is one that\n\t\t**\tdoesn't actually go anywhere. Kind of like turning in place.\n\t\t*/\n\t\tunsigned IsOnShortTrack:1;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tDriveClass(RTTIType rtti, int id, HousesType house);\n\t\tDriveClass(NoInitClass const & x) : FootClass(x), MoebiusCountDown(x) {};\n\t\tvirtual ~DriveClass(void) {};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tbool Teleport_To(CELL cell);\n\t\tvirtual void Response_Select(void);\n\t\tvirtual void Response_Move(void);\n\t\tvirtual void Response_Attack(void);\n\t\tvirtual void Scatter(COORDINATE threat, bool forced=false, bool nokidding=false);\n\t\tvirtual bool Limbo(void);\n\t\tvoid Do_Turn(DirType dir);\n\t\tvirtual void Overrun_Square(CELL , bool =true) {};\n\t\tvirtual void Assign_Destination(TARGET target);\n\t\tvirtual void Per_Cell_Process(PCPType why);\n\t\tvirtual bool Ok_To_Move(DirType ) const;\n\t\tvirtual void AI(void);\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\t\tvoid Force_Track(int track, COORDINATE coord);\n\t\tvirtual bool Stop_Driver(void);\n\n\t\tvoid Mark_Track(COORDINATE headto, MarkType type);\n\n\t\t/**********************************************************************\n\t\t**\tThese enumerations are used as working constants that exist only\n\t\t**\tin the DriveClass namespace.\n\t\t*/\n\t\tenum DriveClassEnum {\n\t\t\tBACKUP_INTO_REFINERY=64,\t\t// Track to backup into refinery.\n\t\t\tOUT_OF_REFINERY,\t\t\t\t\t// Track to leave refinery.\n\t\t\tOUT_OF_WEAPON_FACTORY\t\t\t// Track to leave weapons factory.\n\t\t};\n\n\t\t/****************************************************************************\n\t\t**\tSmooth turning tracks are controlled by this structure and these\n\t\t**\tprocessing bits.\n\t\t*/\n\t\ttypedef enum TrackControlType {\n\t\t\tF_=0x00,\t\t// No translation necessary?\n\t\t\tF_T=0x01,\t// Transpose X and Y components?\n\t\t\tF_X=0x02,\t// Reverse X component sign?\n\t\t\tF_Y=0x04,\t// Reverse Y component sign?\n\t\t\tF_D=0x08\t\t// Two cell consumption?\n\t\t} TrackControlType;\n\n\tprivate:\n\n\t\ttypedef struct {\n\t\t\tchar\t\t\t\t\tTrack;\t\t// Which track to use.\n\t\t\tchar\t\t\t\t\tStartTrack;\t// Track when starting from stand-still.\n\t\t\tDirType\t\t\t\tFacing;\t\t// Facing when track has been completed.\n\t\t\tDriveClass::TrackControlType\tFlag;\t\t\t// List processing flag bits.\n\t\t} TurnTrackType;\n\n\t\ttypedef struct {\n\t\t\tCOORDINATE\t\tOffset;\t\t// Offset to origin coordinate.\n\t\t\tDirType\tFacing;\t\t// Facing (primary track).\n\t\t} TrackType;\n\n\t\ttypedef struct {\n\t\t\tTrackType const * Track;\t// Pointer to track list.\n\t\t\tint\tJump;\t\t// Index where track jumping is allowed.\n\t\t\tint\tEntry;\t// Entry point if jumping to this track.\n\t\t\tint\tCell;\t\t// Per cell process should occur at this index.\n\t\t} RawTrackType;\n\n\t\t/*\n\t\t**\tThese speed values are used to accumulate movement and then\n\t\t**\tconvert them into pixel \"steps\" that are then translated through\n\t\t**\tthe currently running track so that the unit will move.\n\t\t*/\n\t\tint SpeedAccum;\n\n\t\t/*\n\t\t**\tThis the track control logic (used for ground vehicles only). The 'Track'\n\t\t**\tvariable holds the track being followed (0 == not following track). The\n\t\t**\t'TrackIndex' variable holds the current index into the specified track\n\t\t**\t(starts at 0).\n\t\t*/\n\t\tint TrackNumber;\n\t\tint TrackIndex;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tvirtual void Fixup_Path(PathType *path);\n\t\tbool While_Moving(void);\n\t\tbool Start_Of_Move(void);\n\t\tvoid Lay_Track(void);\n\t\tCOORDINATE Smooth_Turn(COORDINATE adj, DirType & dir);\n\n\t\tstatic TurnTrackType const TrackControl[67];\n\t\tstatic RawTrackType const RawTracks[13];\n\t\tstatic TrackType const Track13[];\n\t\tstatic TrackType const Track12[];\n\t\tstatic TrackType const Track11[];\n\t\tstatic TrackType const Track10[];\n\t\tstatic TrackType const Track9[];\n\t\tstatic TrackType const Track8[];\n\t\tstatic TrackType const Track7[];\n\t\tstatic TrackType const Track6[];\n\t\tstatic TrackType const Track5[];\n\t\tstatic TrackType const Track4[];\n\t\tstatic TrackType const Track3[];\n\t\tstatic TrackType const Track2[];\n\t\tstatic TrackType const Track1[24];\n};\n\ninline DriveClass::TrackControlType operator |(DriveClass::TrackControlType, DriveClass::TrackControlType);\ninline DriveClass::TrackControlType operator &(DriveClass::TrackControlType, DriveClass::TrackControlType);\ninline DriveClass::TrackControlType operator ~(DriveClass::TrackControlType);\n\n\n#endif\n"
  },
  {
    "path": "CODE/DROP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/DROP.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DROP.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/24/96                                                     *\n *                                                                                             *\n *                  Last Update : January 24, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"drop.h\"\n\n\nDropListClass::DropListClass(int id, char * text, int max_len, TextPrintType flags, int x, int y, int w, int h, void const * up, void const * down) :\n\tEditClass(id, text, max_len, flags, x, y, w, 9*RESFACTOR, ALPHANUMERIC),\n\tIsDropped(false),\n\tListHeight(h),\n\tDropButton(0, down, x+w, y),\n\tList(0, x, y+Get_Build_Frame_Height(down), w+Get_Build_Frame_Width(down), h, flags, up, down)\n{\n\tFancy_Text_Print(\"\", 0, 0, 0, 0, flags);\n\tEditClass::Height = FontHeight+1;\n\tList.Make_Peer(*this);\n\tDropButton.Make_Peer(*this);\n}\n\n\nvoid DropListClass::Zap(void)\n{\n\tCollapse();\n\tList.Zap();\n\tDropButton.Zap();\n\tEditClass::Zap();\n}\n\nDropListClass & DropListClass::Add(LinkClass & object)\n{\n\tDropButton.Add(object);\n\treturn((DropListClass &)EditClass::Add(object));\n}\n\nDropListClass & DropListClass::Add_Tail(LinkClass & object)\n{\n\tDropButton.Add_Tail(object);\n\treturn((DropListClass &)EditClass::Add_Tail(object));\n}\n\nDropListClass & DropListClass::Add_Head(LinkClass & object)\n{\n\tDropButton.Add_Head(object);\n\treturn((DropListClass &)EditClass::Add_Head(object));\n}\n\nDropListClass * DropListClass::Remove(void)\n{\n\tif (IsDropped) {\n\t\tCollapse();\n\t}\n\tDropButton.Remove();\n\treturn((DropListClass *)EditClass::Remove());\n}\n\nint DropListClass::Add_Item(char const * text)\n{\n\tstrncpy(String, text, MaxLength);\n\tFlag_To_Redraw();\n\treturn(List.Add_Item(text));\n}\n\nchar const * DropListClass::Current_Item(void)\n{\n\treturn(List.Current_Item());\n}\n\nint DropListClass::Current_Index(void)\n{\n\treturn(List.Current_Index());\n}\n\nvoid DropListClass::Set_Selected_Index(int index)\n{\n\tif ((unsigned)index < List.Count()) {\n\t\tList.Set_Selected_Index(index);\n\t\tstrcpy(String, List.Get_Item(Current_Index()));\n\t} else {\n\t\tString[0] = '\\0';\n\t}\n}\n\n\nvoid DropListClass::Clear_Focus(void)\n{\n\tCollapse();\n}\n\nvoid DropListClass::Peer_To_Peer(unsigned flags, KeyNumType & key, ControlClass & whom)\n{\n\tif (&whom == &DropButton) {\n\t\tif (flags & LEFTRELEASE) {\n\t\t\tif (IsDropped) {\n\t\t\t\tCollapse();\n\t\t\t\tkey = (KeyNumType)(ID | KN_BUTTON);\n\t\t\t} else {\n\t\t\t\tExpand();\n\t\t\t}\n\t\t}\n\t}\n\n\tif (&whom == &List) {\n\t\tstrncpy(String, List.Current_Item(), MaxLength);\n\t\tFlag_To_Redraw();\n\t\tkey = (KeyNumType)(ID | KN_BUTTON);\n\t}\n}\n\nvoid DropListClass::Expand(void)\n{\n\tif (!IsDropped) {\n\t\tList.X = X;\n\t\tList.Y = Y+9*RESFACTOR;\n\t\tList.Width = Width;\n\t\tList.Height = ListHeight;\n\t\tList.Add(Head_Of_List());\n\t\tList.Flag_To_Redraw();\n\t\tIsDropped = true;\n\t}\n}\n\nvoid DropListClass::Collapse(void)\n{\n\tif (IsDropped) {\n\t\tList.Remove();\n\t\tIsDropped = false;\n\t}\n}\n\n\nDropListClass & DropListClass::operator = (DropListClass const & list)\n{\n\tif (this == &list) return(*this);\n\tEditClass::operator =(list);\n\tList = list.List;\n\tIsDropped = list.IsDropped;\n\tListHeight = list.ListHeight;\n\tDropButton = list.DropButton;\n\tList.Make_Peer(*this);\n\tDropButton.Make_Peer(*this);\n\treturn(*this);\n}\n\n\nDropListClass::DropListClass(DropListClass const & list) :\n\tEditClass(list),\n\tIsDropped(list.IsDropped),\n\tListHeight(list.ListHeight),\n\tDropButton(list.DropButton),\n\tList(list.List)\n{\n\tList.Make_Peer(*this);\n\tDropButton.Make_Peer(*this);\n}\n\n\nvoid DropListClass::Set_Position(int x, int y)\n{\n\tEditClass::Set_Position(x, y);\n\tList.Set_Position(x, y + Get_Build_Frame_Height(DropButton.Get_Shape_Data()));\n\tDropButton.Set_Position(x + Width, y);\n}\n\n\nvoid DropListClass::Set_Selected_Index(char const * text)\n{\n\tif (text) {\n\t\tfor (int index = 0; index < Count(); index++) {\n\t\t\tif (stricmp(text, List.Get_Item(index)) == 0) {\n\t\t\t\tSet_Selected_Index(index);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n#ifdef WOLAPI_INTEGRATION\nvoid DropListClass::Flag_To_Redraw(void)\n{\n\tif( IsDropped )\n\t\tList.Flag_To_Redraw();\n\tEditClass::Flag_To_Redraw();\n}\n#endif\n"
  },
  {
    "path": "CODE/DROP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/DROP.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DROP.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/05/96                                                     *\n *                                                                                             *\n *                  Last Update : July 5, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef DROP_H\n#define DROP_H\n\n#include\t\"list.h\"\n#include\t\"edit.h\"\n\nclass DropListClass : public EditClass {\n\tpublic:\n\t\tDropListClass(int id, char * text, int max_len, TextPrintType flags, int x, int y, int w, int h, void const * up, void const * down);\n\t\tvirtual ~DropListClass(void) {};\n\n\t\tvirtual DropListClass & Add(LinkClass & object);\n\t\tvirtual DropListClass & Add_Tail(LinkClass & object);\n\t\tvirtual DropListClass & Add_Head(LinkClass & object);\n\t\tvirtual DropListClass * Remove(void);\n\t\tvirtual void Zap(void);\n\n\t\tvirtual int Add_Item(char const * text);\n\t\tvirtual char const * Current_Item(void);\n\t\tvirtual int Current_Index(void);\n\t\tvirtual void Set_Selected_Index(int index);\n\t\tvirtual void Set_Selected_Index(char const * text);\n\t\tvirtual void Peer_To_Peer(unsigned flags, KeyNumType &, ControlClass & whom);\n\t\tvirtual void Clear_Focus(void);\n\t\tvirtual int Count(void) const {return(List.Count());};\n\t\tvirtual char const * Get_Item(int index) const {return(List.Get_Item(index));};\n\n#ifdef WOLAPI_INTEGRATION\n\t\tvirtual void Flag_To_Redraw(void);\n#endif\n\n\t\tvoid Expand(void);\n\t\tvoid Collapse(void);\n\n\t\tvirtual void Set_Position(int x, int y);\n\n\t\tDropListClass & operator = (DropListClass const & list);\n\t\tDropListClass(DropListClass const & list);\n\n\t\t/*\n\t\t**\tIndicates whether the list box has dropped down or not.\n\t\t*/\n\t\tunsigned IsDropped:1;\n\n\t\t/*\n\t\t**\tHeight of list box when it is expanded.\n\t\t*/\n\t\tint ListHeight;\n\n\t\t/*\n\t\t**\tDrop down button.\n\t\t*/\n\t\tShapeButtonClass DropButton;\n\n\t\t/*\n\t\t**\tList object when it is expanded.\n\t\t*/\n\t\tListClass List;\n};\n\n\n\n\ntemplate<class T>\nclass TDropListClass : public EditClass {\n\tpublic:\n\t\tTDropListClass(int id, char * text, int max_len, TextPrintType flags, int x, int y, int w, int h, void const * up, void const * down);\n\t\tTDropListClass(TDropListClass<T> const & list);\n\t\tvirtual ~TDropListClass(void) {};\n\n\t\tT operator [] (int index) const {return(List[index]);};\n\t\tT & operator [] (int index) {return(List[index]);};\n\n\t\tvirtual TDropListClass<T> & Add(LinkClass & object);\n\t\tvirtual TDropListClass<T> & Add_Tail(LinkClass & object);\n\t\tvirtual TDropListClass<T> & Add_Head(LinkClass & object);\n\t\tvirtual TDropListClass<T> * Remove(void);\n\t\tvoid Zap(void);\n\n\t\tvirtual int Add_Item(T text);\n\t\tvirtual T Current_Item(void);\n\t\tvirtual int Current_Index(void);\n\t\tvirtual void Set_Selected_Index(int index);\n\t\tvirtual void Set_Selected_Index(T item);\n\t\tvirtual void Peer_To_Peer(unsigned flags, KeyNumType &, ControlClass & whom);\n\t\tvirtual void Clear_Focus(void);\n\t\tvirtual int Count(void) const {return(List.Count());};\n\t\tvirtual T Get_Item(int index) const {return(List.Get_Item(index));};\n\n\n\t\tvoid Expand(void);\n\t\tvoid Collapse(void);\n\n\t\tvirtual void Set_Position(int x, int y);\n\n\t\tTDropListClass<T> & operator = (TDropListClass<T> const & list);\n\n\t\t/*\n\t\t**\tIndicates whether the list box has dropped down or not.\n\t\t*/\n\t\tunsigned IsDropped:1;\n\n\t\t/*\n\t\t**\tHeight of list box when it is expanded.\n\t\t*/\n\t\tint ListHeight;\n\n\t\t/*\n\t\t**\tDrop down button.\n\t\t*/\n\t\tShapeButtonClass DropButton;\n\n\t\t/*\n\t\t**\tList object when it is expanded.\n\t\t*/\n\t\tTListClass<T> List;\n};\n\n\ntemplate<class T>\nTDropListClass<T>::TDropListClass(int id, char * text, int max_len, TextPrintType flags, int x, int y, int w, int h, void const * up, void const * down) :\n\tEditClass(id, text, max_len, flags, x, y, w, 9, ALPHANUMERIC),\n\tIsDropped(false),\n\tListHeight(h),\n\tDropButton(0, down, x+w, y),\n\tList(0, x, y+Get_Build_Frame_Height(down), w+Get_Build_Frame_Width(down), h, flags, up, down)\n{\n\tList.Make_Peer(*this);\n\tDropButton.Make_Peer(*this);\n}\n\n\ntemplate<class T>\nvoid TDropListClass<T>::Zap(void)\n{\n\tCollapse();\n\tList.Zap();\n\tDropButton.Zap();\n\tEditClass::Zap();\n}\n\n\ntemplate<class T>\nTDropListClass<T> & TDropListClass<T>::Add(LinkClass & object)\n{\n\tDropButton.Add(object);\n\treturn((TDropListClass &)EditClass::Add(object));\n}\n\n\ntemplate<class T>\nTDropListClass<T> & TDropListClass<T>::Add_Tail(LinkClass & object)\n{\n\tDropButton.Add_Tail(object);\n\treturn((TDropListClass &)EditClass::Add_Tail(object));\n}\n\n\ntemplate<class T>\nTDropListClass<T> & TDropListClass<T>::Add_Head(LinkClass & object)\n{\n\tDropButton.Add_Head(object);\n\treturn((TDropListClass &)EditClass::Add_Head(object));\n}\n\n\ntemplate<class T>\nTDropListClass<T> * TDropListClass<T>::Remove(void)\n{\n\tif (IsDropped) {\n\t\tCollapse();\n\t}\n\tDropButton.Remove();\n\treturn((TDropListClass *)EditClass::Remove());\n}\n\n\ntemplate<class T>\nint TDropListClass<T>::Add_Item(T item)\n{\n\tstrncpy(String, item->Description(), MaxLength);\n\tFlag_To_Redraw();\n\treturn(List.Add_Item(item));\n}\n\n\ntemplate<class T>\nT TDropListClass<T>::Current_Item(void)\n{\n\treturn(List.Current_Item());\n}\n\n\ntemplate<class T>\nint TDropListClass<T>::Current_Index(void)\n{\n\treturn(List.Current_Index());\n}\n\n\ntemplate<class T>\nvoid TDropListClass<T>::Set_Selected_Index(int index)\n{\n\tif ((unsigned)index < List.Count()) {\n\t\tList.Set_Selected_Index(index);\n\t\tstrncpy(String, List.Get_Item(Current_Index())->Description(), MaxLength);\n\t} else {\n\t\tString[0] = '\\0';\n\t}\n}\n\n\ntemplate<class T>\nvoid TDropListClass<T>::Clear_Focus(void)\n{\n\tCollapse();\n}\n\n\ntemplate<class T>\nvoid TDropListClass<T>::Peer_To_Peer(unsigned flags, KeyNumType & key, ControlClass & whom)\n{\n\tif (&whom == &DropButton) {\n\t\tif (flags & LEFTRELEASE) {\n\t\t\tif (IsDropped) {\n\t\t\t\tCollapse();\n\t\t\t\tkey = (KeyNumType)(ID | KN_BUTTON);\n\t\t\t} else {\n\t\t\t\tExpand();\n\t\t\t}\n\t\t}\n\t}\n\n\tif (&whom == &List) {\n\t\tstrncpy(String, List.Current_Item()->Description(), MaxLength);\n\t\tFlag_To_Redraw();\n\t\tkey = (KeyNumType)(ID | KN_BUTTON);\n\t}\n}\n\n\ntemplate<class T>\nvoid TDropListClass<T>::Expand(void)\n{\n\tif (!IsDropped) {\n\t\tList.X = X;\n\t\tList.Y = Y+9;\n\t\tList.Width = Width;\n\t\tList.Height = ListHeight;\n\t\tList.Add(Head_Of_List());\n\t\tList.Flag_To_Redraw();\n\t\tIsDropped = true;\n\t}\n}\n\n\ntemplate<class T>\nvoid TDropListClass<T>::Collapse(void)\n{\n\tif (IsDropped) {\n\t\tList.Remove();\n\t\tIsDropped = false;\n\t}\n}\n\n\ntemplate<class T>\nTDropListClass<T> & TDropListClass<T>::operator = (TDropListClass<T> const & list)\n{\n\tif (this == &list) return(*this);\n\tEditClass::operator =(list);\n\tList = list.List;\n\tIsDropped = list.IsDropped;\n\tListHeight = list.ListHeight;\n\tDropButton = list.DropButton;\n\tList.Make_Peer(*this);\n\tDropButton.Make_Peer(*this);\n\treturn(*this);\n}\n\n\ntemplate<class T>\nTDropListClass<T>::TDropListClass(TDropListClass<T> const & list) :\n\tEditClass(list),\n\tIsDropped(list.IsDropped),\n\tListHeight(list.ListHeight),\n\tDropButton(list.DropButton),\n\tList(list.List)\n{\n\tList.Make_Peer(*this);\n\tDropButton.Make_Peer(*this);\n}\n\n\ntemplate<class T>\nvoid TDropListClass<T>::Set_Position(int x, int y)\n{\n\tEditClass::Set_Position(x, y);\n\tList.Set_Position(x, y + Get_Build_Frame_Height(DropButton.Get_Shape_Data()));\n\tDropButton.Set_Position(x + Width, y);\n}\n\n\ntemplate<class T>\nvoid TDropListClass<T>::Set_Selected_Index(T text)\n{\n\tfor (int index = 0; index < Count(); index++) {\n\t\tif (text == List.Get_Item(index)) {\n\t\t\tSet_Selected_Index(index);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n#endif\n"
  },
  {
    "path": "CODE/DTABLE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\nlong DiffTable[] = {\n\t0,\t// Index = 0, Token = 0\n\t1,\t// Index = 0, Token = 1\n\t3,\t// Index = 0, Token = 2\n\t4,\t// Index = 0, Token = 3\n\t7,\t// Index = 0, Token = 4\n\t8,\t// Index = 0, Token = 5\n\t10,\t// Index = 0, Token = 6\n\t11,\t// Index = 0, Token = 7\n\t0,\t// Index = 0, Token = 8\n\t-1,\t// Index = 0, Token = 9\n\t-3,\t// Index = 0, Token = 10\n\t-4,\t// Index = 0, Token = 11\n\t-7,\t// Index = 0, Token = 12\n\t-8,\t// Index = 0, Token = 13\n\t-10,\t// Index = 0, Token = 14\n\t-11,\t// Index = 0, Token = 15\n\t1,\t// Index = 1, Token = 0\n\t3,\t// Index = 1, Token = 1\n\t5,\t// Index = 1, Token = 2\n\t7,\t// Index = 1, Token = 3\n\t9,\t// Index = 1, Token = 4\n\t11,\t// Index = 1, Token = 5\n\t13,\t// Index = 1, Token = 6\n\t15,\t// Index = 1, Token = 7\n\t-1,\t// Index = 1, Token = 8\n\t-3,\t// Index = 1, Token = 9\n\t-5,\t// Index = 1, Token = 10\n\t-7,\t// Index = 1, Token = 11\n\t-9,\t// Index = 1, Token = 12\n\t-11,\t// Index = 1, Token = 13\n\t-13,\t// Index = 1, Token = 14\n\t-15,\t// Index = 1, Token = 15\n\t1,\t// Index = 2, Token = 0\n\t3,\t// Index = 2, Token = 1\n\t5,\t// Index = 2, Token = 2\n\t7,\t// Index = 2, Token = 3\n\t10,\t// Index = 2, Token = 4\n\t12,\t// Index = 2, Token = 5\n\t14,\t// Index = 2, Token = 6\n\t16,\t// Index = 2, Token = 7\n\t-1,\t// Index = 2, Token = 8\n\t-3,\t// Index = 2, Token = 9\n\t-5,\t// Index = 2, Token = 10\n\t-7,\t// Index = 2, Token = 11\n\t-10,\t// Index = 2, Token = 12\n\t-12,\t// Index = 2, Token = 13\n\t-14,\t// Index = 2, Token = 14\n\t-16,\t// Index = 2, Token = 15\n\t1,\t// Index = 3, Token = 0\n\t3,\t// Index = 3, Token = 1\n\t6,\t// Index = 3, Token = 2\n\t8,\t// Index = 3, Token = 3\n\t11,\t// Index = 3, Token = 4\n\t13,\t// Index = 3, Token = 5\n\t16,\t// Index = 3, Token = 6\n\t18,\t// Index = 3, Token = 7\n\t-1,\t// Index = 3, Token = 8\n\t-3,\t// Index = 3, Token = 9\n\t-6,\t// Index = 3, Token = 10\n\t-8,\t// Index = 3, Token = 11\n\t-11,\t// Index = 3, Token = 12\n\t-13,\t// Index = 3, Token = 13\n\t-16,\t// Index = 3, Token = 14\n\t-18,\t// Index = 3, Token = 15\n\t1,\t// Index = 4, Token = 0\n\t3,\t// Index = 4, Token = 1\n\t6,\t// Index = 4, Token = 2\n\t8,\t// Index = 4, Token = 3\n\t12,\t// Index = 4, Token = 4\n\t14,\t// Index = 4, Token = 5\n\t17,\t// Index = 4, Token = 6\n\t19,\t// Index = 4, Token = 7\n\t-1,\t// Index = 4, Token = 8\n\t-3,\t// Index = 4, Token = 9\n\t-6,\t// Index = 4, Token = 10\n\t-8,\t// Index = 4, Token = 11\n\t-12,\t// Index = 4, Token = 12\n\t-14,\t// Index = 4, Token = 13\n\t-17,\t// Index = 4, Token = 14\n\t-19,\t// Index = 4, Token = 15\n\t1,\t// Index = 5, Token = 0\n\t4,\t// Index = 5, Token = 1\n\t7,\t// Index = 5, Token = 2\n\t10,\t// Index = 5, Token = 3\n\t13,\t// Index = 5, Token = 4\n\t16,\t// Index = 5, Token = 5\n\t19,\t// Index = 5, Token = 6\n\t22,\t// Index = 5, Token = 7\n\t-1,\t// Index = 5, Token = 8\n\t-4,\t// Index = 5, Token = 9\n\t-7,\t// Index = 5, Token = 10\n\t-10,\t// Index = 5, Token = 11\n\t-13,\t// Index = 5, Token = 12\n\t-16,\t// Index = 5, Token = 13\n\t-19,\t// Index = 5, Token = 14\n\t-22,\t// Index = 5, Token = 15\n\t1,\t// Index = 6, Token = 0\n\t4,\t// Index = 6, Token = 1\n\t7,\t// Index = 6, Token = 2\n\t10,\t// Index = 6, Token = 3\n\t14,\t// Index = 6, Token = 4\n\t17,\t// Index = 6, Token = 5\n\t20,\t// Index = 6, Token = 6\n\t23,\t// Index = 6, Token = 7\n\t-1,\t// Index = 6, Token = 8\n\t-4,\t// Index = 6, Token = 9\n\t-7,\t// Index = 6, Token = 10\n\t-10,\t// Index = 6, Token = 11\n\t-14,\t// Index = 6, Token = 12\n\t-17,\t// Index = 6, Token = 13\n\t-20,\t// Index = 6, Token = 14\n\t-23,\t// Index = 6, Token = 15\n\t1,\t// Index = 7, Token = 0\n\t4,\t// Index = 7, Token = 1\n\t8,\t// Index = 7, Token = 2\n\t11,\t// Index = 7, Token = 3\n\t15,\t// Index = 7, Token = 4\n\t18,\t// Index = 7, Token = 5\n\t22,\t// Index = 7, Token = 6\n\t25,\t// Index = 7, Token = 7\n\t-1,\t// Index = 7, Token = 8\n\t-4,\t// Index = 7, Token = 9\n\t-8,\t// Index = 7, Token = 10\n\t-11,\t// Index = 7, Token = 11\n\t-15,\t// Index = 7, Token = 12\n\t-18,\t// Index = 7, Token = 13\n\t-22,\t// Index = 7, Token = 14\n\t-25,\t// Index = 7, Token = 15\n\t2,\t// Index = 8, Token = 0\n\t6,\t// Index = 8, Token = 1\n\t10,\t// Index = 8, Token = 2\n\t14,\t// Index = 8, Token = 3\n\t18,\t// Index = 8, Token = 4\n\t22,\t// Index = 8, Token = 5\n\t26,\t// Index = 8, Token = 6\n\t30,\t// Index = 8, Token = 7\n\t-2,\t// Index = 8, Token = 8\n\t-6,\t// Index = 8, Token = 9\n\t-10,\t// Index = 8, Token = 10\n\t-14,\t// Index = 8, Token = 11\n\t-18,\t// Index = 8, Token = 12\n\t-22,\t// Index = 8, Token = 13\n\t-26,\t// Index = 8, Token = 14\n\t-30,\t// Index = 8, Token = 15\n\t2,\t// Index = 9, Token = 0\n\t6,\t// Index = 9, Token = 1\n\t10,\t// Index = 9, Token = 2\n\t14,\t// Index = 9, Token = 3\n\t19,\t// Index = 9, Token = 4\n\t23,\t// Index = 9, Token = 5\n\t27,\t// Index = 9, Token = 6\n\t31,\t// Index = 9, Token = 7\n\t-2,\t// Index = 9, Token = 8\n\t-6,\t// Index = 9, Token = 9\n\t-10,\t// Index = 9, Token = 10\n\t-14,\t// Index = 9, Token = 11\n\t-19,\t// Index = 9, Token = 12\n\t-23,\t// Index = 9, Token = 13\n\t-27,\t// Index = 9, Token = 14\n\t-31,\t// Index = 9, Token = 15\n\t2,\t// Index = 10, Token = 0\n\t6,\t// Index = 10, Token = 1\n\t11,\t// Index = 10, Token = 2\n\t15,\t// Index = 10, Token = 3\n\t21,\t// Index = 10, Token = 4\n\t25,\t// Index = 10, Token = 5\n\t30,\t// Index = 10, Token = 6\n\t34,\t// Index = 10, Token = 7\n\t-2,\t// Index = 10, Token = 8\n\t-6,\t// Index = 10, Token = 9\n\t-11,\t// Index = 10, Token = 10\n\t-15,\t// Index = 10, Token = 11\n\t-21,\t// Index = 10, Token = 12\n\t-25,\t// Index = 10, Token = 13\n\t-30,\t// Index = 10, Token = 14\n\t-34,\t// Index = 10, Token = 15\n\t2,\t// Index = 11, Token = 0\n\t7,\t// Index = 11, Token = 1\n\t12,\t// Index = 11, Token = 2\n\t17,\t// Index = 11, Token = 3\n\t23,\t// Index = 11, Token = 4\n\t28,\t// Index = 11, Token = 5\n\t33,\t// Index = 11, Token = 6\n\t38,\t// Index = 11, Token = 7\n\t-2,\t// Index = 11, Token = 8\n\t-7,\t// Index = 11, Token = 9\n\t-12,\t// Index = 11, Token = 10\n\t-17,\t// Index = 11, Token = 11\n\t-23,\t// Index = 11, Token = 12\n\t-28,\t// Index = 11, Token = 13\n\t-33,\t// Index = 11, Token = 14\n\t-38,\t// Index = 11, Token = 15\n\t2,\t// Index = 12, Token = 0\n\t7,\t// Index = 12, Token = 1\n\t13,\t// Index = 12, Token = 2\n\t18,\t// Index = 12, Token = 3\n\t25,\t// Index = 12, Token = 4\n\t30,\t// Index = 12, Token = 5\n\t36,\t// Index = 12, Token = 6\n\t41,\t// Index = 12, Token = 7\n\t-2,\t// Index = 12, Token = 8\n\t-7,\t// Index = 12, Token = 9\n\t-13,\t// Index = 12, Token = 10\n\t-18,\t// Index = 12, Token = 11\n\t-25,\t// Index = 12, Token = 12\n\t-30,\t// Index = 12, Token = 13\n\t-36,\t// Index = 12, Token = 14\n\t-41,\t// Index = 12, Token = 15\n\t3,\t// Index = 13, Token = 0\n\t9,\t// Index = 13, Token = 1\n\t15,\t// Index = 13, Token = 2\n\t21,\t// Index = 13, Token = 3\n\t28,\t// Index = 13, Token = 4\n\t34,\t// Index = 13, Token = 5\n\t40,\t// Index = 13, Token = 6\n\t46,\t// Index = 13, Token = 7\n\t-3,\t// Index = 13, Token = 8\n\t-9,\t// Index = 13, Token = 9\n\t-15,\t// Index = 13, Token = 10\n\t-21,\t// Index = 13, Token = 11\n\t-28,\t// Index = 13, Token = 12\n\t-34,\t// Index = 13, Token = 13\n\t-40,\t// Index = 13, Token = 14\n\t-46,\t// Index = 13, Token = 15\n\t3,\t// Index = 14, Token = 0\n\t10,\t// Index = 14, Token = 1\n\t17,\t// Index = 14, Token = 2\n\t24,\t// Index = 14, Token = 3\n\t31,\t// Index = 14, Token = 4\n\t38,\t// Index = 14, Token = 5\n\t45,\t// Index = 14, Token = 6\n\t52,\t// Index = 14, Token = 7\n\t-3,\t// Index = 14, Token = 8\n\t-10,\t// Index = 14, Token = 9\n\t-17,\t// Index = 14, Token = 10\n\t-24,\t// Index = 14, Token = 11\n\t-31,\t// Index = 14, Token = 12\n\t-38,\t// Index = 14, Token = 13\n\t-45,\t// Index = 14, Token = 14\n\t-52,\t// Index = 14, Token = 15\n\t3,\t// Index = 15, Token = 0\n\t10,\t// Index = 15, Token = 1\n\t18,\t// Index = 15, Token = 2\n\t25,\t// Index = 15, Token = 3\n\t34,\t// Index = 15, Token = 4\n\t41,\t// Index = 15, Token = 5\n\t49,\t// Index = 15, Token = 6\n\t56,\t// Index = 15, Token = 7\n\t-3,\t// Index = 15, Token = 8\n\t-10,\t// Index = 15, Token = 9\n\t-18,\t// Index = 15, Token = 10\n\t-25,\t// Index = 15, Token = 11\n\t-34,\t// Index = 15, Token = 12\n\t-41,\t// Index = 15, Token = 13\n\t-49,\t// Index = 15, Token = 14\n\t-56,\t// Index = 15, Token = 15\n\t4,\t// Index = 16, Token = 0\n\t12,\t// Index = 16, Token = 1\n\t21,\t// Index = 16, Token = 2\n\t29,\t// Index = 16, Token = 3\n\t38,\t// Index = 16, Token = 4\n\t46,\t// Index = 16, Token = 5\n\t55,\t// Index = 16, Token = 6\n\t63,\t// Index = 16, Token = 7\n\t-4,\t// Index = 16, Token = 8\n\t-12,\t// Index = 16, Token = 9\n\t-21,\t// Index = 16, Token = 10\n\t-29,\t// Index = 16, Token = 11\n\t-38,\t// Index = 16, Token = 12\n\t-46,\t// Index = 16, Token = 13\n\t-55,\t// Index = 16, Token = 14\n\t-63,\t// Index = 16, Token = 15\n\t4,\t// Index = 17, Token = 0\n\t13,\t// Index = 17, Token = 1\n\t22,\t// Index = 17, Token = 2\n\t31,\t// Index = 17, Token = 3\n\t41,\t// Index = 17, Token = 4\n\t50,\t// Index = 17, Token = 5\n\t59,\t// Index = 17, Token = 6\n\t68,\t// Index = 17, Token = 7\n\t-4,\t// Index = 17, Token = 8\n\t-13,\t// Index = 17, Token = 9\n\t-22,\t// Index = 17, Token = 10\n\t-31,\t// Index = 17, Token = 11\n\t-41,\t// Index = 17, Token = 12\n\t-50,\t// Index = 17, Token = 13\n\t-59,\t// Index = 17, Token = 14\n\t-68,\t// Index = 17, Token = 15\n\t5,\t// Index = 18, Token = 0\n\t15,\t// Index = 18, Token = 1\n\t25,\t// Index = 18, Token = 2\n\t35,\t// Index = 18, Token = 3\n\t46,\t// Index = 18, Token = 4\n\t56,\t// Index = 18, Token = 5\n\t66,\t// Index = 18, Token = 6\n\t76,\t// Index = 18, Token = 7\n\t-5,\t// Index = 18, Token = 8\n\t-15,\t// Index = 18, Token = 9\n\t-25,\t// Index = 18, Token = 10\n\t-35,\t// Index = 18, Token = 11\n\t-46,\t// Index = 18, Token = 12\n\t-56,\t// Index = 18, Token = 13\n\t-66,\t// Index = 18, Token = 14\n\t-76,\t// Index = 18, Token = 15\n\t5,\t// Index = 19, Token = 0\n\t16,\t// Index = 19, Token = 1\n\t27,\t// Index = 19, Token = 2\n\t38,\t// Index = 19, Token = 3\n\t50,\t// Index = 19, Token = 4\n\t61,\t// Index = 19, Token = 5\n\t72,\t// Index = 19, Token = 6\n\t83,\t// Index = 19, Token = 7\n\t-5,\t// Index = 19, Token = 8\n\t-16,\t// Index = 19, Token = 9\n\t-27,\t// Index = 19, Token = 10\n\t-38,\t// Index = 19, Token = 11\n\t-50,\t// Index = 19, Token = 12\n\t-61,\t// Index = 19, Token = 13\n\t-72,\t// Index = 19, Token = 14\n\t-83,\t// Index = 19, Token = 15\n\t6,\t// Index = 20, Token = 0\n\t18,\t// Index = 20, Token = 1\n\t31,\t// Index = 20, Token = 2\n\t43,\t// Index = 20, Token = 3\n\t56,\t// Index = 20, Token = 4\n\t68,\t// Index = 20, Token = 5\n\t81,\t// Index = 20, Token = 6\n\t93,\t// Index = 20, Token = 7\n\t-6,\t// Index = 20, Token = 8\n\t-18,\t// Index = 20, Token = 9\n\t-31,\t// Index = 20, Token = 10\n\t-43,\t// Index = 20, Token = 11\n\t-56,\t// Index = 20, Token = 12\n\t-68,\t// Index = 20, Token = 13\n\t-81,\t// Index = 20, Token = 14\n\t-93,\t// Index = 20, Token = 15\n\t6,\t// Index = 21, Token = 0\n\t19,\t// Index = 21, Token = 1\n\t33,\t// Index = 21, Token = 2\n\t46,\t// Index = 21, Token = 3\n\t61,\t// Index = 21, Token = 4\n\t74,\t// Index = 21, Token = 5\n\t88,\t// Index = 21, Token = 6\n\t101,\t// Index = 21, Token = 7\n\t-6,\t// Index = 21, Token = 8\n\t-19,\t// Index = 21, Token = 9\n\t-33,\t// Index = 21, Token = 10\n\t-46,\t// Index = 21, Token = 11\n\t-61,\t// Index = 21, Token = 12\n\t-74,\t// Index = 21, Token = 13\n\t-88,\t// Index = 21, Token = 14\n\t-101,\t// Index = 21, Token = 15\n\t7,\t// Index = 22, Token = 0\n\t22,\t// Index = 22, Token = 1\n\t37,\t// Index = 22, Token = 2\n\t52,\t// Index = 22, Token = 3\n\t67,\t// Index = 22, Token = 4\n\t82,\t// Index = 22, Token = 5\n\t97,\t// Index = 22, Token = 6\n\t112,\t// Index = 22, Token = 7\n\t-7,\t// Index = 22, Token = 8\n\t-22,\t// Index = 22, Token = 9\n\t-37,\t// Index = 22, Token = 10\n\t-52,\t// Index = 22, Token = 11\n\t-67,\t// Index = 22, Token = 12\n\t-82,\t// Index = 22, Token = 13\n\t-97,\t// Index = 22, Token = 14\n\t-112,\t// Index = 22, Token = 15\n\t8,\t// Index = 23, Token = 0\n\t24,\t// Index = 23, Token = 1\n\t41,\t// Index = 23, Token = 2\n\t57,\t// Index = 23, Token = 3\n\t74,\t// Index = 23, Token = 4\n\t90,\t// Index = 23, Token = 5\n\t107,\t// Index = 23, Token = 6\n\t123,\t// Index = 23, Token = 7\n\t-8,\t// Index = 23, Token = 8\n\t-24,\t// Index = 23, Token = 9\n\t-41,\t// Index = 23, Token = 10\n\t-57,\t// Index = 23, Token = 11\n\t-74,\t// Index = 23, Token = 12\n\t-90,\t// Index = 23, Token = 13\n\t-107,\t// Index = 23, Token = 14\n\t-123,\t// Index = 23, Token = 15\n\t9,\t// Index = 24, Token = 0\n\t27,\t// Index = 24, Token = 1\n\t45,\t// Index = 24, Token = 2\n\t63,\t// Index = 24, Token = 3\n\t82,\t// Index = 24, Token = 4\n\t100,\t// Index = 24, Token = 5\n\t118,\t// Index = 24, Token = 6\n\t136,\t// Index = 24, Token = 7\n\t-9,\t// Index = 24, Token = 8\n\t-27,\t// Index = 24, Token = 9\n\t-45,\t// Index = 24, Token = 10\n\t-63,\t// Index = 24, Token = 11\n\t-82,\t// Index = 24, Token = 12\n\t-100,\t// Index = 24, Token = 13\n\t-118,\t// Index = 24, Token = 14\n\t-136,\t// Index = 24, Token = 15\n\t10,\t// Index = 25, Token = 0\n\t30,\t// Index = 25, Token = 1\n\t50,\t// Index = 25, Token = 2\n\t70,\t// Index = 25, Token = 3\n\t90,\t// Index = 25, Token = 4\n\t110,\t// Index = 25, Token = 5\n\t130,\t// Index = 25, Token = 6\n\t150,\t// Index = 25, Token = 7\n\t-10,\t// Index = 25, Token = 8\n\t-30,\t// Index = 25, Token = 9\n\t-50,\t// Index = 25, Token = 10\n\t-70,\t// Index = 25, Token = 11\n\t-90,\t// Index = 25, Token = 12\n\t-110,\t// Index = 25, Token = 13\n\t-130,\t// Index = 25, Token = 14\n\t-150,\t// Index = 25, Token = 15\n\t11,\t// Index = 26, Token = 0\n\t33,\t// Index = 26, Token = 1\n\t55,\t// Index = 26, Token = 2\n\t77,\t// Index = 26, Token = 3\n\t99,\t// Index = 26, Token = 4\n\t121,\t// Index = 26, Token = 5\n\t143,\t// Index = 26, Token = 6\n\t165,\t// Index = 26, Token = 7\n\t-11,\t// Index = 26, Token = 8\n\t-33,\t// Index = 26, Token = 9\n\t-55,\t// Index = 26, Token = 10\n\t-77,\t// Index = 26, Token = 11\n\t-99,\t// Index = 26, Token = 12\n\t-121,\t// Index = 26, Token = 13\n\t-143,\t// Index = 26, Token = 14\n\t-165,\t// Index = 26, Token = 15\n\t12,\t// Index = 27, Token = 0\n\t36,\t// Index = 27, Token = 1\n\t60,\t// Index = 27, Token = 2\n\t84,\t// Index = 27, Token = 3\n\t109,\t// Index = 27, Token = 4\n\t133,\t// Index = 27, Token = 5\n\t157,\t// Index = 27, Token = 6\n\t181,\t// Index = 27, Token = 7\n\t-12,\t// Index = 27, Token = 8\n\t-36,\t// Index = 27, Token = 9\n\t-60,\t// Index = 27, Token = 10\n\t-84,\t// Index = 27, Token = 11\n\t-109,\t// Index = 27, Token = 12\n\t-133,\t// Index = 27, Token = 13\n\t-157,\t// Index = 27, Token = 14\n\t-181,\t// Index = 27, Token = 15\n\t13,\t// Index = 28, Token = 0\n\t39,\t// Index = 28, Token = 1\n\t66,\t// Index = 28, Token = 2\n\t92,\t// Index = 28, Token = 3\n\t120,\t// Index = 28, Token = 4\n\t146,\t// Index = 28, Token = 5\n\t173,\t// Index = 28, Token = 6\n\t199,\t// Index = 28, Token = 7\n\t-13,\t// Index = 28, Token = 8\n\t-39,\t// Index = 28, Token = 9\n\t-66,\t// Index = 28, Token = 10\n\t-92,\t// Index = 28, Token = 11\n\t-120,\t// Index = 28, Token = 12\n\t-146,\t// Index = 28, Token = 13\n\t-173,\t// Index = 28, Token = 14\n\t-199,\t// Index = 28, Token = 15\n\t14,\t// Index = 29, Token = 0\n\t43,\t// Index = 29, Token = 1\n\t73,\t// Index = 29, Token = 2\n\t102,\t// Index = 29, Token = 3\n\t132,\t// Index = 29, Token = 4\n\t161,\t// Index = 29, Token = 5\n\t191,\t// Index = 29, Token = 6\n\t220,\t// Index = 29, Token = 7\n\t-14,\t// Index = 29, Token = 8\n\t-43,\t// Index = 29, Token = 9\n\t-73,\t// Index = 29, Token = 10\n\t-102,\t// Index = 29, Token = 11\n\t-132,\t// Index = 29, Token = 12\n\t-161,\t// Index = 29, Token = 13\n\t-191,\t// Index = 29, Token = 14\n\t-220,\t// Index = 29, Token = 15\n\t16,\t// Index = 30, Token = 0\n\t48,\t// Index = 30, Token = 1\n\t81,\t// Index = 30, Token = 2\n\t113,\t// Index = 30, Token = 3\n\t146,\t// Index = 30, Token = 4\n\t178,\t// Index = 30, Token = 5\n\t211,\t// Index = 30, Token = 6\n\t243,\t// Index = 30, Token = 7\n\t-16,\t// Index = 30, Token = 8\n\t-48,\t// Index = 30, Token = 9\n\t-81,\t// Index = 30, Token = 10\n\t-113,\t// Index = 30, Token = 11\n\t-146,\t// Index = 30, Token = 12\n\t-178,\t// Index = 30, Token = 13\n\t-211,\t// Index = 30, Token = 14\n\t-243,\t// Index = 30, Token = 15\n\t17,\t// Index = 31, Token = 0\n\t52,\t// Index = 31, Token = 1\n\t88,\t// Index = 31, Token = 2\n\t123,\t// Index = 31, Token = 3\n\t160,\t// Index = 31, Token = 4\n\t195,\t// Index = 31, Token = 5\n\t231,\t// Index = 31, Token = 6\n\t266,\t// Index = 31, Token = 7\n\t-17,\t// Index = 31, Token = 8\n\t-52,\t// Index = 31, Token = 9\n\t-88,\t// Index = 31, Token = 10\n\t-123,\t// Index = 31, Token = 11\n\t-160,\t// Index = 31, Token = 12\n\t-195,\t// Index = 31, Token = 13\n\t-231,\t// Index = 31, Token = 14\n\t-266,\t// Index = 31, Token = 15\n\t19,\t// Index = 32, Token = 0\n\t58,\t// Index = 32, Token = 1\n\t97,\t// Index = 32, Token = 2\n\t136,\t// Index = 32, Token = 3\n\t176,\t// Index = 32, Token = 4\n\t215,\t// Index = 32, Token = 5\n\t254,\t// Index = 32, Token = 6\n\t293,\t// Index = 32, Token = 7\n\t-19,\t// Index = 32, Token = 8\n\t-58,\t// Index = 32, Token = 9\n\t-97,\t// Index = 32, Token = 10\n\t-136,\t// Index = 32, Token = 11\n\t-176,\t// Index = 32, Token = 12\n\t-215,\t// Index = 32, Token = 13\n\t-254,\t// Index = 32, Token = 14\n\t-293,\t// Index = 32, Token = 15\n\t21,\t// Index = 33, Token = 0\n\t64,\t// Index = 33, Token = 1\n\t107,\t// Index = 33, Token = 2\n\t150,\t// Index = 33, Token = 3\n\t194,\t// Index = 33, Token = 4\n\t237,\t// Index = 33, Token = 5\n\t280,\t// Index = 33, Token = 6\n\t323,\t// Index = 33, Token = 7\n\t-21,\t// Index = 33, Token = 8\n\t-64,\t// Index = 33, Token = 9\n\t-107,\t// Index = 33, Token = 10\n\t-150,\t// Index = 33, Token = 11\n\t-194,\t// Index = 33, Token = 12\n\t-237,\t// Index = 33, Token = 13\n\t-280,\t// Index = 33, Token = 14\n\t-323,\t// Index = 33, Token = 15\n\t23,\t// Index = 34, Token = 0\n\t70,\t// Index = 34, Token = 1\n\t118,\t// Index = 34, Token = 2\n\t165,\t// Index = 34, Token = 3\n\t213,\t// Index = 34, Token = 4\n\t260,\t// Index = 34, Token = 5\n\t308,\t// Index = 34, Token = 6\n\t355,\t// Index = 34, Token = 7\n\t-23,\t// Index = 34, Token = 8\n\t-70,\t// Index = 34, Token = 9\n\t-118,\t// Index = 34, Token = 10\n\t-165,\t// Index = 34, Token = 11\n\t-213,\t// Index = 34, Token = 12\n\t-260,\t// Index = 34, Token = 13\n\t-308,\t// Index = 34, Token = 14\n\t-355,\t// Index = 34, Token = 15\n\t26,\t// Index = 35, Token = 0\n\t78,\t// Index = 35, Token = 1\n\t130,\t// Index = 35, Token = 2\n\t182,\t// Index = 35, Token = 3\n\t235,\t// Index = 35, Token = 4\n\t287,\t// Index = 35, Token = 5\n\t339,\t// Index = 35, Token = 6\n\t391,\t// Index = 35, Token = 7\n\t-26,\t// Index = 35, Token = 8\n\t-78,\t// Index = 35, Token = 9\n\t-130,\t// Index = 35, Token = 10\n\t-182,\t// Index = 35, Token = 11\n\t-235,\t// Index = 35, Token = 12\n\t-287,\t// Index = 35, Token = 13\n\t-339,\t// Index = 35, Token = 14\n\t-391,\t// Index = 35, Token = 15\n\t28,\t// Index = 36, Token = 0\n\t85,\t// Index = 36, Token = 1\n\t143,\t// Index = 36, Token = 2\n\t200,\t// Index = 36, Token = 3\n\t258,\t// Index = 36, Token = 4\n\t315,\t// Index = 36, Token = 5\n\t373,\t// Index = 36, Token = 6\n\t430,\t// Index = 36, Token = 7\n\t-28,\t// Index = 36, Token = 8\n\t-85,\t// Index = 36, Token = 9\n\t-143,\t// Index = 36, Token = 10\n\t-200,\t// Index = 36, Token = 11\n\t-258,\t// Index = 36, Token = 12\n\t-315,\t// Index = 36, Token = 13\n\t-373,\t// Index = 36, Token = 14\n\t-430,\t// Index = 36, Token = 15\n\t31,\t// Index = 37, Token = 0\n\t94,\t// Index = 37, Token = 1\n\t157,\t// Index = 37, Token = 2\n\t220,\t// Index = 37, Token = 3\n\t284,\t// Index = 37, Token = 4\n\t347,\t// Index = 37, Token = 5\n\t410,\t// Index = 37, Token = 6\n\t473,\t// Index = 37, Token = 7\n\t-31,\t// Index = 37, Token = 8\n\t-94,\t// Index = 37, Token = 9\n\t-157,\t// Index = 37, Token = 10\n\t-220,\t// Index = 37, Token = 11\n\t-284,\t// Index = 37, Token = 12\n\t-347,\t// Index = 37, Token = 13\n\t-410,\t// Index = 37, Token = 14\n\t-473,\t// Index = 37, Token = 15\n\t34,\t// Index = 38, Token = 0\n\t103,\t// Index = 38, Token = 1\n\t173,\t// Index = 38, Token = 2\n\t242,\t// Index = 38, Token = 3\n\t313,\t// Index = 38, Token = 4\n\t382,\t// Index = 38, Token = 5\n\t452,\t// Index = 38, Token = 6\n\t521,\t// Index = 38, Token = 7\n\t-34,\t// Index = 38, Token = 8\n\t-103,\t// Index = 38, Token = 9\n\t-173,\t// Index = 38, Token = 10\n\t-242,\t// Index = 38, Token = 11\n\t-313,\t// Index = 38, Token = 12\n\t-382,\t// Index = 38, Token = 13\n\t-452,\t// Index = 38, Token = 14\n\t-521,\t// Index = 38, Token = 15\n\t38,\t// Index = 39, Token = 0\n\t114,\t// Index = 39, Token = 1\n\t191,\t// Index = 39, Token = 2\n\t267,\t// Index = 39, Token = 3\n\t345,\t// Index = 39, Token = 4\n\t421,\t// Index = 39, Token = 5\n\t498,\t// Index = 39, Token = 6\n\t574,\t// Index = 39, Token = 7\n\t-38,\t// Index = 39, Token = 8\n\t-114,\t// Index = 39, Token = 9\n\t-191,\t// Index = 39, Token = 10\n\t-267,\t// Index = 39, Token = 11\n\t-345,\t// Index = 39, Token = 12\n\t-421,\t// Index = 39, Token = 13\n\t-498,\t// Index = 39, Token = 14\n\t-574,\t// Index = 39, Token = 15\n\t42,\t// Index = 40, Token = 0\n\t126,\t// Index = 40, Token = 1\n\t210,\t// Index = 40, Token = 2\n\t294,\t// Index = 40, Token = 3\n\t379,\t// Index = 40, Token = 4\n\t463,\t// Index = 40, Token = 5\n\t547,\t// Index = 40, Token = 6\n\t631,\t// Index = 40, Token = 7\n\t-42,\t// Index = 40, Token = 8\n\t-126,\t// Index = 40, Token = 9\n\t-210,\t// Index = 40, Token = 10\n\t-294,\t// Index = 40, Token = 11\n\t-379,\t// Index = 40, Token = 12\n\t-463,\t// Index = 40, Token = 13\n\t-547,\t// Index = 40, Token = 14\n\t-631,\t// Index = 40, Token = 15\n\t46,\t// Index = 41, Token = 0\n\t138,\t// Index = 41, Token = 1\n\t231,\t// Index = 41, Token = 2\n\t323,\t// Index = 41, Token = 3\n\t417,\t// Index = 41, Token = 4\n\t509,\t// Index = 41, Token = 5\n\t602,\t// Index = 41, Token = 6\n\t694,\t// Index = 41, Token = 7\n\t-46,\t// Index = 41, Token = 8\n\t-138,\t// Index = 41, Token = 9\n\t-231,\t// Index = 41, Token = 10\n\t-323,\t// Index = 41, Token = 11\n\t-417,\t// Index = 41, Token = 12\n\t-509,\t// Index = 41, Token = 13\n\t-602,\t// Index = 41, Token = 14\n\t-694,\t// Index = 41, Token = 15\n\t51,\t// Index = 42, Token = 0\n\t153,\t// Index = 42, Token = 1\n\t255,\t// Index = 42, Token = 2\n\t357,\t// Index = 42, Token = 3\n\t459,\t// Index = 42, Token = 4\n\t561,\t// Index = 42, Token = 5\n\t663,\t// Index = 42, Token = 6\n\t765,\t// Index = 42, Token = 7\n\t-51,\t// Index = 42, Token = 8\n\t-153,\t// Index = 42, Token = 9\n\t-255,\t// Index = 42, Token = 10\n\t-357,\t// Index = 42, Token = 11\n\t-459,\t// Index = 42, Token = 12\n\t-561,\t// Index = 42, Token = 13\n\t-663,\t// Index = 42, Token = 14\n\t-765,\t// Index = 42, Token = 15\n\t56,\t// Index = 43, Token = 0\n\t168,\t// Index = 43, Token = 1\n\t280,\t// Index = 43, Token = 2\n\t392,\t// Index = 43, Token = 3\n\t505,\t// Index = 43, Token = 4\n\t617,\t// Index = 43, Token = 5\n\t729,\t// Index = 43, Token = 6\n\t841,\t// Index = 43, Token = 7\n\t-56,\t// Index = 43, Token = 8\n\t-168,\t// Index = 43, Token = 9\n\t-280,\t// Index = 43, Token = 10\n\t-392,\t// Index = 43, Token = 11\n\t-505,\t// Index = 43, Token = 12\n\t-617,\t// Index = 43, Token = 13\n\t-729,\t// Index = 43, Token = 14\n\t-841,\t// Index = 43, Token = 15\n\t61,\t// Index = 44, Token = 0\n\t184,\t// Index = 44, Token = 1\n\t308,\t// Index = 44, Token = 2\n\t431,\t// Index = 44, Token = 3\n\t555,\t// Index = 44, Token = 4\n\t678,\t// Index = 44, Token = 5\n\t802,\t// Index = 44, Token = 6\n\t925,\t// Index = 44, Token = 7\n\t-61,\t// Index = 44, Token = 8\n\t-184,\t// Index = 44, Token = 9\n\t-308,\t// Index = 44, Token = 10\n\t-431,\t// Index = 44, Token = 11\n\t-555,\t// Index = 44, Token = 12\n\t-678,\t// Index = 44, Token = 13\n\t-802,\t// Index = 44, Token = 14\n\t-925,\t// Index = 44, Token = 15\n\t68,\t// Index = 45, Token = 0\n\t204,\t// Index = 45, Token = 1\n\t340,\t// Index = 45, Token = 2\n\t476,\t// Index = 45, Token = 3\n\t612,\t// Index = 45, Token = 4\n\t748,\t// Index = 45, Token = 5\n\t884,\t// Index = 45, Token = 6\n\t1020,\t// Index = 45, Token = 7\n\t-68,\t// Index = 45, Token = 8\n\t-204,\t// Index = 45, Token = 9\n\t-340,\t// Index = 45, Token = 10\n\t-476,\t// Index = 45, Token = 11\n\t-612,\t// Index = 45, Token = 12\n\t-748,\t// Index = 45, Token = 13\n\t-884,\t// Index = 45, Token = 14\n\t-1020,\t// Index = 45, Token = 15\n\t74,\t// Index = 46, Token = 0\n\t223,\t// Index = 46, Token = 1\n\t373,\t// Index = 46, Token = 2\n\t522,\t// Index = 46, Token = 3\n\t672,\t// Index = 46, Token = 4\n\t821,\t// Index = 46, Token = 5\n\t971,\t// Index = 46, Token = 6\n\t1120,\t// Index = 46, Token = 7\n\t-74,\t// Index = 46, Token = 8\n\t-223,\t// Index = 46, Token = 9\n\t-373,\t// Index = 46, Token = 10\n\t-522,\t// Index = 46, Token = 11\n\t-672,\t// Index = 46, Token = 12\n\t-821,\t// Index = 46, Token = 13\n\t-971,\t// Index = 46, Token = 14\n\t-1120,\t// Index = 46, Token = 15\n\t82,\t// Index = 47, Token = 0\n\t246,\t// Index = 47, Token = 1\n\t411,\t// Index = 47, Token = 2\n\t575,\t// Index = 47, Token = 3\n\t740,\t// Index = 47, Token = 4\n\t904,\t// Index = 47, Token = 5\n\t1069,\t// Index = 47, Token = 6\n\t1233,\t// Index = 47, Token = 7\n\t-82,\t// Index = 47, Token = 8\n\t-246,\t// Index = 47, Token = 9\n\t-411,\t// Index = 47, Token = 10\n\t-575,\t// Index = 47, Token = 11\n\t-740,\t// Index = 47, Token = 12\n\t-904,\t// Index = 47, Token = 13\n\t-1069,\t// Index = 47, Token = 14\n\t-1233,\t// Index = 47, Token = 15\n\t90,\t// Index = 48, Token = 0\n\t271,\t// Index = 48, Token = 1\n\t452,\t// Index = 48, Token = 2\n\t633,\t// Index = 48, Token = 3\n\t814,\t// Index = 48, Token = 4\n\t995,\t// Index = 48, Token = 5\n\t1176,\t// Index = 48, Token = 6\n\t1357,\t// Index = 48, Token = 7\n\t-90,\t// Index = 48, Token = 8\n\t-271,\t// Index = 48, Token = 9\n\t-452,\t// Index = 48, Token = 10\n\t-633,\t// Index = 48, Token = 11\n\t-814,\t// Index = 48, Token = 12\n\t-995,\t// Index = 48, Token = 13\n\t-1176,\t// Index = 48, Token = 14\n\t-1357,\t// Index = 48, Token = 15\n\t99,\t// Index = 49, Token = 0\n\t298,\t// Index = 49, Token = 1\n\t497,\t// Index = 49, Token = 2\n\t696,\t// Index = 49, Token = 3\n\t895,\t// Index = 49, Token = 4\n\t1094,\t// Index = 49, Token = 5\n\t1293,\t// Index = 49, Token = 6\n\t1492,\t// Index = 49, Token = 7\n\t-99,\t// Index = 49, Token = 8\n\t-298,\t// Index = 49, Token = 9\n\t-497,\t// Index = 49, Token = 10\n\t-696,\t// Index = 49, Token = 11\n\t-895,\t// Index = 49, Token = 12\n\t-1094,\t// Index = 49, Token = 13\n\t-1293,\t// Index = 49, Token = 14\n\t-1492,\t// Index = 49, Token = 15\n\t109,\t// Index = 50, Token = 0\n\t328,\t// Index = 50, Token = 1\n\t547,\t// Index = 50, Token = 2\n\t766,\t// Index = 50, Token = 3\n\t985,\t// Index = 50, Token = 4\n\t1204,\t// Index = 50, Token = 5\n\t1423,\t// Index = 50, Token = 6\n\t1642,\t// Index = 50, Token = 7\n\t-109,\t// Index = 50, Token = 8\n\t-328,\t// Index = 50, Token = 9\n\t-547,\t// Index = 50, Token = 10\n\t-766,\t// Index = 50, Token = 11\n\t-985,\t// Index = 50, Token = 12\n\t-1204,\t// Index = 50, Token = 13\n\t-1423,\t// Index = 50, Token = 14\n\t-1642,\t// Index = 50, Token = 15\n\t120,\t// Index = 51, Token = 0\n\t360,\t// Index = 51, Token = 1\n\t601,\t// Index = 51, Token = 2\n\t841,\t// Index = 51, Token = 3\n\t1083,\t// Index = 51, Token = 4\n\t1323,\t// Index = 51, Token = 5\n\t1564,\t// Index = 51, Token = 6\n\t1804,\t// Index = 51, Token = 7\n\t-120,\t// Index = 51, Token = 8\n\t-360,\t// Index = 51, Token = 9\n\t-601,\t// Index = 51, Token = 10\n\t-841,\t// Index = 51, Token = 11\n\t-1083,\t// Index = 51, Token = 12\n\t-1323,\t// Index = 51, Token = 13\n\t-1564,\t// Index = 51, Token = 14\n\t-1804,\t// Index = 51, Token = 15\n\t132,\t// Index = 52, Token = 0\n\t397,\t// Index = 52, Token = 1\n\t662,\t// Index = 52, Token = 2\n\t927,\t// Index = 52, Token = 3\n\t1192,\t// Index = 52, Token = 4\n\t1457,\t// Index = 52, Token = 5\n\t1722,\t// Index = 52, Token = 6\n\t1987,\t// Index = 52, Token = 7\n\t-132,\t// Index = 52, Token = 8\n\t-397,\t// Index = 52, Token = 9\n\t-662,\t// Index = 52, Token = 10\n\t-927,\t// Index = 52, Token = 11\n\t-1192,\t// Index = 52, Token = 12\n\t-1457,\t// Index = 52, Token = 13\n\t-1722,\t// Index = 52, Token = 14\n\t-1987,\t// Index = 52, Token = 15\n\t145,\t// Index = 53, Token = 0\n\t436,\t// Index = 53, Token = 1\n\t728,\t// Index = 53, Token = 2\n\t1019,\t// Index = 53, Token = 3\n\t1311,\t// Index = 53, Token = 4\n\t1602,\t// Index = 53, Token = 5\n\t1894,\t// Index = 53, Token = 6\n\t2185,\t// Index = 53, Token = 7\n\t-145,\t// Index = 53, Token = 8\n\t-436,\t// Index = 53, Token = 9\n\t-728,\t// Index = 53, Token = 10\n\t-1019,\t// Index = 53, Token = 11\n\t-1311,\t// Index = 53, Token = 12\n\t-1602,\t// Index = 53, Token = 13\n\t-1894,\t// Index = 53, Token = 14\n\t-2185,\t// Index = 53, Token = 15\n\t160,\t// Index = 54, Token = 0\n\t480,\t// Index = 54, Token = 1\n\t801,\t// Index = 54, Token = 2\n\t1121,\t// Index = 54, Token = 3\n\t1442,\t// Index = 54, Token = 4\n\t1762,\t// Index = 54, Token = 5\n\t2083,\t// Index = 54, Token = 6\n\t2403,\t// Index = 54, Token = 7\n\t-160,\t// Index = 54, Token = 8\n\t-480,\t// Index = 54, Token = 9\n\t-801,\t// Index = 54, Token = 10\n\t-1121,\t// Index = 54, Token = 11\n\t-1442,\t// Index = 54, Token = 12\n\t-1762,\t// Index = 54, Token = 13\n\t-2083,\t// Index = 54, Token = 14\n\t-2403,\t// Index = 54, Token = 15\n\t176,\t// Index = 55, Token = 0\n\t528,\t// Index = 55, Token = 1\n\t881,\t// Index = 55, Token = 2\n\t1233,\t// Index = 55, Token = 3\n\t1587,\t// Index = 55, Token = 4\n\t1939,\t// Index = 55, Token = 5\n\t2292,\t// Index = 55, Token = 6\n\t2644,\t// Index = 55, Token = 7\n\t-176,\t// Index = 55, Token = 8\n\t-528,\t// Index = 55, Token = 9\n\t-881,\t// Index = 55, Token = 10\n\t-1233,\t// Index = 55, Token = 11\n\t-1587,\t// Index = 55, Token = 12\n\t-1939,\t// Index = 55, Token = 13\n\t-2292,\t// Index = 55, Token = 14\n\t-2644,\t// Index = 55, Token = 15\n\t194,\t// Index = 56, Token = 0\n\t582,\t// Index = 56, Token = 1\n\t970,\t// Index = 56, Token = 2\n\t1358,\t// Index = 56, Token = 3\n\t1746,\t// Index = 56, Token = 4\n\t2134,\t// Index = 56, Token = 5\n\t2522,\t// Index = 56, Token = 6\n\t2910,\t// Index = 56, Token = 7\n\t-194,\t// Index = 56, Token = 8\n\t-582,\t// Index = 56, Token = 9\n\t-970,\t// Index = 56, Token = 10\n\t-1358,\t// Index = 56, Token = 11\n\t-1746,\t// Index = 56, Token = 12\n\t-2134,\t// Index = 56, Token = 13\n\t-2522,\t// Index = 56, Token = 14\n\t-2910,\t// Index = 56, Token = 15\n\t213,\t// Index = 57, Token = 0\n\t639,\t// Index = 57, Token = 1\n\t1066,\t// Index = 57, Token = 2\n\t1492,\t// Index = 57, Token = 3\n\t1920,\t// Index = 57, Token = 4\n\t2346,\t// Index = 57, Token = 5\n\t2773,\t// Index = 57, Token = 6\n\t3199,\t// Index = 57, Token = 7\n\t-213,\t// Index = 57, Token = 8\n\t-639,\t// Index = 57, Token = 9\n\t-1066,\t// Index = 57, Token = 10\n\t-1492,\t// Index = 57, Token = 11\n\t-1920,\t// Index = 57, Token = 12\n\t-2346,\t// Index = 57, Token = 13\n\t-2773,\t// Index = 57, Token = 14\n\t-3199,\t// Index = 57, Token = 15\n\t234,\t// Index = 58, Token = 0\n\t703,\t// Index = 58, Token = 1\n\t1173,\t// Index = 58, Token = 2\n\t1642,\t// Index = 58, Token = 3\n\t2112,\t// Index = 58, Token = 4\n\t2581,\t// Index = 58, Token = 5\n\t3051,\t// Index = 58, Token = 6\n\t3520,\t// Index = 58, Token = 7\n\t-234,\t// Index = 58, Token = 8\n\t-703,\t// Index = 58, Token = 9\n\t-1173,\t// Index = 58, Token = 10\n\t-1642,\t// Index = 58, Token = 11\n\t-2112,\t// Index = 58, Token = 12\n\t-2581,\t// Index = 58, Token = 13\n\t-3051,\t// Index = 58, Token = 14\n\t-3520,\t// Index = 58, Token = 15\n\t258,\t// Index = 59, Token = 0\n\t774,\t// Index = 59, Token = 1\n\t1291,\t// Index = 59, Token = 2\n\t1807,\t// Index = 59, Token = 3\n\t2324,\t// Index = 59, Token = 4\n\t2840,\t// Index = 59, Token = 5\n\t3357,\t// Index = 59, Token = 6\n\t3873,\t// Index = 59, Token = 7\n\t-258,\t// Index = 59, Token = 8\n\t-774,\t// Index = 59, Token = 9\n\t-1291,\t// Index = 59, Token = 10\n\t-1807,\t// Index = 59, Token = 11\n\t-2324,\t// Index = 59, Token = 12\n\t-2840,\t// Index = 59, Token = 13\n\t-3357,\t// Index = 59, Token = 14\n\t-3873,\t// Index = 59, Token = 15\n\t284,\t// Index = 60, Token = 0\n\t852,\t// Index = 60, Token = 1\n\t1420,\t// Index = 60, Token = 2\n\t1988,\t// Index = 60, Token = 3\n\t2556,\t// Index = 60, Token = 4\n\t3124,\t// Index = 60, Token = 5\n\t3692,\t// Index = 60, Token = 6\n\t4260,\t// Index = 60, Token = 7\n\t-284,\t// Index = 60, Token = 8\n\t-852,\t// Index = 60, Token = 9\n\t-1420,\t// Index = 60, Token = 10\n\t-1988,\t// Index = 60, Token = 11\n\t-2556,\t// Index = 60, Token = 12\n\t-3124,\t// Index = 60, Token = 13\n\t-3692,\t// Index = 60, Token = 14\n\t-4260,\t// Index = 60, Token = 15\n\t312,\t// Index = 61, Token = 0\n\t936,\t// Index = 61, Token = 1\n\t1561,\t// Index = 61, Token = 2\n\t2185,\t// Index = 61, Token = 3\n\t2811,\t// Index = 61, Token = 4\n\t3435,\t// Index = 61, Token = 5\n\t4060,\t// Index = 61, Token = 6\n\t4684,\t// Index = 61, Token = 7\n\t-312,\t// Index = 61, Token = 8\n\t-936,\t// Index = 61, Token = 9\n\t-1561,\t// Index = 61, Token = 10\n\t-2185,\t// Index = 61, Token = 11\n\t-2811,\t// Index = 61, Token = 12\n\t-3435,\t// Index = 61, Token = 13\n\t-4060,\t// Index = 61, Token = 14\n\t-4684,\t// Index = 61, Token = 15\n\t343,\t// Index = 62, Token = 0\n\t1030,\t// Index = 62, Token = 1\n\t1717,\t// Index = 62, Token = 2\n\t2404,\t// Index = 62, Token = 3\n\t3092,\t// Index = 62, Token = 4\n\t3779,\t// Index = 62, Token = 5\n\t4466,\t// Index = 62, Token = 6\n\t5153,\t// Index = 62, Token = 7\n\t-343,\t// Index = 62, Token = 8\n\t-1030,\t// Index = 62, Token = 9\n\t-1717,\t// Index = 62, Token = 10\n\t-2404,\t// Index = 62, Token = 11\n\t-3092,\t// Index = 62, Token = 12\n\t-3779,\t// Index = 62, Token = 13\n\t-4466,\t// Index = 62, Token = 14\n\t-5153,\t// Index = 62, Token = 15\n\t378,\t// Index = 63, Token = 0\n\t1134,\t// Index = 63, Token = 1\n\t1890,\t// Index = 63, Token = 2\n\t2646,\t// Index = 63, Token = 3\n\t3402,\t// Index = 63, Token = 4\n\t4158,\t// Index = 63, Token = 5\n\t4914,\t// Index = 63, Token = 6\n\t5670,\t// Index = 63, Token = 7\n\t-378,\t// Index = 63, Token = 8\n\t-1134,\t// Index = 63, Token = 9\n\t-1890,\t// Index = 63, Token = 10\n\t-2646,\t// Index = 63, Token = 11\n\t-3402,\t// Index = 63, Token = 12\n\t-4158,\t// Index = 63, Token = 13\n\t-4914,\t// Index = 63, Token = 14\n\t-5670,\t// Index = 63, Token = 15\n\t415,\t// Index = 64, Token = 0\n\t1246,\t// Index = 64, Token = 1\n\t2078,\t// Index = 64, Token = 2\n\t2909,\t// Index = 64, Token = 3\n\t3742,\t// Index = 64, Token = 4\n\t4573,\t// Index = 64, Token = 5\n\t5405,\t// Index = 64, Token = 6\n\t6236,\t// Index = 64, Token = 7\n\t-415,\t// Index = 64, Token = 8\n\t-1246,\t// Index = 64, Token = 9\n\t-2078,\t// Index = 64, Token = 10\n\t-2909,\t// Index = 64, Token = 11\n\t-3742,\t// Index = 64, Token = 12\n\t-4573,\t// Index = 64, Token = 13\n\t-5405,\t// Index = 64, Token = 14\n\t-6236,\t// Index = 64, Token = 15\n\t457,\t// Index = 65, Token = 0\n\t1372,\t// Index = 65, Token = 1\n\t2287,\t// Index = 65, Token = 2\n\t3202,\t// Index = 65, Token = 3\n\t4117,\t// Index = 65, Token = 4\n\t5032,\t// Index = 65, Token = 5\n\t5947,\t// Index = 65, Token = 6\n\t6862,\t// Index = 65, Token = 7\n\t-457,\t// Index = 65, Token = 8\n\t-1372,\t// Index = 65, Token = 9\n\t-2287,\t// Index = 65, Token = 10\n\t-3202,\t// Index = 65, Token = 11\n\t-4117,\t// Index = 65, Token = 12\n\t-5032,\t// Index = 65, Token = 13\n\t-5947,\t// Index = 65, Token = 14\n\t-6862,\t// Index = 65, Token = 15\n\t503,\t// Index = 66, Token = 0\n\t1509,\t// Index = 66, Token = 1\n\t2516,\t// Index = 66, Token = 2\n\t3522,\t// Index = 66, Token = 3\n\t4529,\t// Index = 66, Token = 4\n\t5535,\t// Index = 66, Token = 5\n\t6542,\t// Index = 66, Token = 6\n\t7548,\t// Index = 66, Token = 7\n\t-503,\t// Index = 66, Token = 8\n\t-1509,\t// Index = 66, Token = 9\n\t-2516,\t// Index = 66, Token = 10\n\t-3522,\t// Index = 66, Token = 11\n\t-4529,\t// Index = 66, Token = 12\n\t-5535,\t// Index = 66, Token = 13\n\t-6542,\t// Index = 66, Token = 14\n\t-7548,\t// Index = 66, Token = 15\n\t553,\t// Index = 67, Token = 0\n\t1660,\t// Index = 67, Token = 1\n\t2767,\t// Index = 67, Token = 2\n\t3874,\t// Index = 67, Token = 3\n\t4981,\t// Index = 67, Token = 4\n\t6088,\t// Index = 67, Token = 5\n\t7195,\t// Index = 67, Token = 6\n\t8302,\t// Index = 67, Token = 7\n\t-553,\t// Index = 67, Token = 8\n\t-1660,\t// Index = 67, Token = 9\n\t-2767,\t// Index = 67, Token = 10\n\t-3874,\t// Index = 67, Token = 11\n\t-4981,\t// Index = 67, Token = 12\n\t-6088,\t// Index = 67, Token = 13\n\t-7195,\t// Index = 67, Token = 14\n\t-8302,\t// Index = 67, Token = 15\n\t608,\t// Index = 68, Token = 0\n\t1825,\t// Index = 68, Token = 1\n\t3043,\t// Index = 68, Token = 2\n\t4260,\t// Index = 68, Token = 3\n\t5479,\t// Index = 68, Token = 4\n\t6696,\t// Index = 68, Token = 5\n\t7914,\t// Index = 68, Token = 6\n\t9131,\t// Index = 68, Token = 7\n\t-608,\t// Index = 68, Token = 8\n\t-1825,\t// Index = 68, Token = 9\n\t-3043,\t// Index = 68, Token = 10\n\t-4260,\t// Index = 68, Token = 11\n\t-5479,\t// Index = 68, Token = 12\n\t-6696,\t// Index = 68, Token = 13\n\t-7914,\t// Index = 68, Token = 14\n\t-9131,\t// Index = 68, Token = 15\n\t669,\t// Index = 69, Token = 0\n\t2008,\t// Index = 69, Token = 1\n\t3348,\t// Index = 69, Token = 2\n\t4687,\t// Index = 69, Token = 3\n\t6027,\t// Index = 69, Token = 4\n\t7366,\t// Index = 69, Token = 5\n\t8706,\t// Index = 69, Token = 6\n\t10045,\t// Index = 69, Token = 7\n\t-669,\t// Index = 69, Token = 8\n\t-2008,\t// Index = 69, Token = 9\n\t-3348,\t// Index = 69, Token = 10\n\t-4687,\t// Index = 69, Token = 11\n\t-6027,\t// Index = 69, Token = 12\n\t-7366,\t// Index = 69, Token = 13\n\t-8706,\t// Index = 69, Token = 14\n\t-10045,\t// Index = 69, Token = 15\n\t736,\t// Index = 70, Token = 0\n\t2209,\t// Index = 70, Token = 1\n\t3683,\t// Index = 70, Token = 2\n\t5156,\t// Index = 70, Token = 3\n\t6630,\t// Index = 70, Token = 4\n\t8103,\t// Index = 70, Token = 5\n\t9577,\t// Index = 70, Token = 6\n\t11050,\t// Index = 70, Token = 7\n\t-736,\t// Index = 70, Token = 8\n\t-2209,\t// Index = 70, Token = 9\n\t-3683,\t// Index = 70, Token = 10\n\t-5156,\t// Index = 70, Token = 11\n\t-6630,\t// Index = 70, Token = 12\n\t-8103,\t// Index = 70, Token = 13\n\t-9577,\t// Index = 70, Token = 14\n\t-11050,\t// Index = 70, Token = 15\n\t810,\t// Index = 71, Token = 0\n\t2431,\t// Index = 71, Token = 1\n\t4052,\t// Index = 71, Token = 2\n\t5673,\t// Index = 71, Token = 3\n\t7294,\t// Index = 71, Token = 4\n\t8915,\t// Index = 71, Token = 5\n\t10536,\t// Index = 71, Token = 6\n\t12157,\t// Index = 71, Token = 7\n\t-810,\t// Index = 71, Token = 8\n\t-2431,\t// Index = 71, Token = 9\n\t-4052,\t// Index = 71, Token = 10\n\t-5673,\t// Index = 71, Token = 11\n\t-7294,\t// Index = 71, Token = 12\n\t-8915,\t// Index = 71, Token = 13\n\t-10536,\t// Index = 71, Token = 14\n\t-12157,\t// Index = 71, Token = 15\n\t891,\t// Index = 72, Token = 0\n\t2674,\t// Index = 72, Token = 1\n\t4457,\t// Index = 72, Token = 2\n\t6240,\t// Index = 72, Token = 3\n\t8023,\t// Index = 72, Token = 4\n\t9806,\t// Index = 72, Token = 5\n\t11589,\t// Index = 72, Token = 6\n\t13372,\t// Index = 72, Token = 7\n\t-891,\t// Index = 72, Token = 8\n\t-2674,\t// Index = 72, Token = 9\n\t-4457,\t// Index = 72, Token = 10\n\t-6240,\t// Index = 72, Token = 11\n\t-8023,\t// Index = 72, Token = 12\n\t-9806,\t// Index = 72, Token = 13\n\t-11589,\t// Index = 72, Token = 14\n\t-13372,\t// Index = 72, Token = 15\n\t980,\t// Index = 73, Token = 0\n\t2941,\t// Index = 73, Token = 1\n\t4902,\t// Index = 73, Token = 2\n\t6863,\t// Index = 73, Token = 3\n\t8825,\t// Index = 73, Token = 4\n\t10786,\t// Index = 73, Token = 5\n\t12747,\t// Index = 73, Token = 6\n\t14708,\t// Index = 73, Token = 7\n\t-980,\t// Index = 73, Token = 8\n\t-2941,\t// Index = 73, Token = 9\n\t-4902,\t// Index = 73, Token = 10\n\t-6863,\t// Index = 73, Token = 11\n\t-8825,\t// Index = 73, Token = 12\n\t-10786,\t// Index = 73, Token = 13\n\t-12747,\t// Index = 73, Token = 14\n\t-14708,\t// Index = 73, Token = 15\n\t1078,\t// Index = 74, Token = 0\n\t3235,\t// Index = 74, Token = 1\n\t5393,\t// Index = 74, Token = 2\n\t7550,\t// Index = 74, Token = 3\n\t9708,\t// Index = 74, Token = 4\n\t11865,\t// Index = 74, Token = 5\n\t14023,\t// Index = 74, Token = 6\n\t16180,\t// Index = 74, Token = 7\n\t-1078,\t// Index = 74, Token = 8\n\t-3235,\t// Index = 74, Token = 9\n\t-5393,\t// Index = 74, Token = 10\n\t-7550,\t// Index = 74, Token = 11\n\t-9708,\t// Index = 74, Token = 12\n\t-11865,\t// Index = 74, Token = 13\n\t-14023,\t// Index = 74, Token = 14\n\t-16180,\t// Index = 74, Token = 15\n\t1186,\t// Index = 75, Token = 0\n\t3559,\t// Index = 75, Token = 1\n\t5932,\t// Index = 75, Token = 2\n\t8305,\t// Index = 75, Token = 3\n\t10679,\t// Index = 75, Token = 4\n\t13052,\t// Index = 75, Token = 5\n\t15425,\t// Index = 75, Token = 6\n\t17798,\t// Index = 75, Token = 7\n\t-1186,\t// Index = 75, Token = 8\n\t-3559,\t// Index = 75, Token = 9\n\t-5932,\t// Index = 75, Token = 10\n\t-8305,\t// Index = 75, Token = 11\n\t-10679,\t// Index = 75, Token = 12\n\t-13052,\t// Index = 75, Token = 13\n\t-15425,\t// Index = 75, Token = 14\n\t-17798,\t// Index = 75, Token = 15\n\t1305,\t// Index = 76, Token = 0\n\t3915,\t// Index = 76, Token = 1\n\t6526,\t// Index = 76, Token = 2\n\t9136,\t// Index = 76, Token = 3\n\t11747,\t// Index = 76, Token = 4\n\t14357,\t// Index = 76, Token = 5\n\t16968,\t// Index = 76, Token = 6\n\t19578,\t// Index = 76, Token = 7\n\t-1305,\t// Index = 76, Token = 8\n\t-3915,\t// Index = 76, Token = 9\n\t-6526,\t// Index = 76, Token = 10\n\t-9136,\t// Index = 76, Token = 11\n\t-11747,\t// Index = 76, Token = 12\n\t-14357,\t// Index = 76, Token = 13\n\t-16968,\t// Index = 76, Token = 14\n\t-19578,\t// Index = 76, Token = 15\n\t1435,\t// Index = 77, Token = 0\n\t4306,\t// Index = 77, Token = 1\n\t7178,\t// Index = 77, Token = 2\n\t10049,\t// Index = 77, Token = 3\n\t12922,\t// Index = 77, Token = 4\n\t15793,\t// Index = 77, Token = 5\n\t18665,\t// Index = 77, Token = 6\n\t21536,\t// Index = 77, Token = 7\n\t-1435,\t// Index = 77, Token = 8\n\t-4306,\t// Index = 77, Token = 9\n\t-7178,\t// Index = 77, Token = 10\n\t-10049,\t// Index = 77, Token = 11\n\t-12922,\t// Index = 77, Token = 12\n\t-15793,\t// Index = 77, Token = 13\n\t-18665,\t// Index = 77, Token = 14\n\t-21536,\t// Index = 77, Token = 15\n\t1579,\t// Index = 78, Token = 0\n\t4737,\t// Index = 78, Token = 1\n\t7896,\t// Index = 78, Token = 2\n\t11054,\t// Index = 78, Token = 3\n\t14214,\t// Index = 78, Token = 4\n\t17372,\t// Index = 78, Token = 5\n\t20531,\t// Index = 78, Token = 6\n\t23689,\t// Index = 78, Token = 7\n\t-1579,\t// Index = 78, Token = 8\n\t-4737,\t// Index = 78, Token = 9\n\t-7896,\t// Index = 78, Token = 10\n\t-11054,\t// Index = 78, Token = 11\n\t-14214,\t// Index = 78, Token = 12\n\t-17372,\t// Index = 78, Token = 13\n\t-20531,\t// Index = 78, Token = 14\n\t-23689,\t// Index = 78, Token = 15\n\t1737,\t// Index = 79, Token = 0\n\t5211,\t// Index = 79, Token = 1\n\t8686,\t// Index = 79, Token = 2\n\t12160,\t// Index = 79, Token = 3\n\t15636,\t// Index = 79, Token = 4\n\t19110,\t// Index = 79, Token = 5\n\t22585,\t// Index = 79, Token = 6\n\t26059,\t// Index = 79, Token = 7\n\t-1737,\t// Index = 79, Token = 8\n\t-5211,\t// Index = 79, Token = 9\n\t-8686,\t// Index = 79, Token = 10\n\t-12160,\t// Index = 79, Token = 11\n\t-15636,\t// Index = 79, Token = 12\n\t-19110,\t// Index = 79, Token = 13\n\t-22585,\t// Index = 79, Token = 14\n\t-26059,\t// Index = 79, Token = 15\n\t1911,\t// Index = 80, Token = 0\n\t5733,\t// Index = 80, Token = 1\n\t9555,\t// Index = 80, Token = 2\n\t13377,\t// Index = 80, Token = 3\n\t17200,\t// Index = 80, Token = 4\n\t21022,\t// Index = 80, Token = 5\n\t24844,\t// Index = 80, Token = 6\n\t28666,\t// Index = 80, Token = 7\n\t-1911,\t// Index = 80, Token = 8\n\t-5733,\t// Index = 80, Token = 9\n\t-9555,\t// Index = 80, Token = 10\n\t-13377,\t// Index = 80, Token = 11\n\t-17200,\t// Index = 80, Token = 12\n\t-21022,\t// Index = 80, Token = 13\n\t-24844,\t// Index = 80, Token = 14\n\t-28666,\t// Index = 80, Token = 15\n\t2102,\t// Index = 81, Token = 0\n\t6306,\t// Index = 81, Token = 1\n\t10511,\t// Index = 81, Token = 2\n\t14715,\t// Index = 81, Token = 3\n\t18920,\t// Index = 81, Token = 4\n\t23124,\t// Index = 81, Token = 5\n\t27329,\t// Index = 81, Token = 6\n\t31533,\t// Index = 81, Token = 7\n\t-2102,\t// Index = 81, Token = 8\n\t-6306,\t// Index = 81, Token = 9\n\t-10511,\t// Index = 81, Token = 10\n\t-14715,\t// Index = 81, Token = 11\n\t-18920,\t// Index = 81, Token = 12\n\t-23124,\t// Index = 81, Token = 13\n\t-27329,\t// Index = 81, Token = 14\n\t-31533,\t// Index = 81, Token = 15\n\t2312,\t// Index = 82, Token = 0\n\t6937,\t// Index = 82, Token = 1\n\t11562,\t// Index = 82, Token = 2\n\t16187,\t// Index = 82, Token = 3\n\t20812,\t// Index = 82, Token = 4\n\t25437,\t// Index = 82, Token = 5\n\t30062,\t// Index = 82, Token = 6\n\t34687,\t// Index = 82, Token = 7\n\t-2312,\t// Index = 82, Token = 8\n\t-6937,\t// Index = 82, Token = 9\n\t-11562,\t// Index = 82, Token = 10\n\t-16187,\t// Index = 82, Token = 11\n\t-20812,\t// Index = 82, Token = 12\n\t-25437,\t// Index = 82, Token = 13\n\t-30062,\t// Index = 82, Token = 14\n\t-34687,\t// Index = 82, Token = 15\n\t2543,\t// Index = 83, Token = 0\n\t7630,\t// Index = 83, Token = 1\n\t12718,\t// Index = 83, Token = 2\n\t17805,\t// Index = 83, Token = 3\n\t22893,\t// Index = 83, Token = 4\n\t27980,\t// Index = 83, Token = 5\n\t33068,\t// Index = 83, Token = 6\n\t38155,\t// Index = 83, Token = 7\n\t-2543,\t// Index = 83, Token = 8\n\t-7630,\t// Index = 83, Token = 9\n\t-12718,\t// Index = 83, Token = 10\n\t-17805,\t// Index = 83, Token = 11\n\t-22893,\t// Index = 83, Token = 12\n\t-27980,\t// Index = 83, Token = 13\n\t-33068,\t// Index = 83, Token = 14\n\t-38155,\t// Index = 83, Token = 15\n\t2798,\t// Index = 84, Token = 0\n\t8394,\t// Index = 84, Token = 1\n\t13990,\t// Index = 84, Token = 2\n\t19586,\t// Index = 84, Token = 3\n\t25183,\t// Index = 84, Token = 4\n\t30779,\t// Index = 84, Token = 5\n\t36375,\t// Index = 84, Token = 6\n\t41971,\t// Index = 84, Token = 7\n\t-2798,\t// Index = 84, Token = 8\n\t-8394,\t// Index = 84, Token = 9\n\t-13990,\t// Index = 84, Token = 10\n\t-19586,\t// Index = 84, Token = 11\n\t-25183,\t// Index = 84, Token = 12\n\t-30779,\t// Index = 84, Token = 13\n\t-36375,\t// Index = 84, Token = 14\n\t-41971,\t// Index = 84, Token = 15\n\t3077,\t// Index = 85, Token = 0\n\t9232,\t// Index = 85, Token = 1\n\t15388,\t// Index = 85, Token = 2\n\t21543,\t// Index = 85, Token = 3\n\t27700,\t// Index = 85, Token = 4\n\t33855,\t// Index = 85, Token = 5\n\t40011,\t// Index = 85, Token = 6\n\t46166,\t// Index = 85, Token = 7\n\t-3077,\t// Index = 85, Token = 8\n\t-9232,\t// Index = 85, Token = 9\n\t-15388,\t// Index = 85, Token = 10\n\t-21543,\t// Index = 85, Token = 11\n\t-27700,\t// Index = 85, Token = 12\n\t-33855,\t// Index = 85, Token = 13\n\t-40011,\t// Index = 85, Token = 14\n\t-46166,\t// Index = 85, Token = 15\n\t3385,\t// Index = 86, Token = 0\n\t10156,\t// Index = 86, Token = 1\n\t16928,\t// Index = 86, Token = 2\n\t23699,\t// Index = 86, Token = 3\n\t30471,\t// Index = 86, Token = 4\n\t37242,\t// Index = 86, Token = 5\n\t44014,\t// Index = 86, Token = 6\n\t50785,\t// Index = 86, Token = 7\n\t-3385,\t// Index = 86, Token = 8\n\t-10156,\t// Index = 86, Token = 9\n\t-16928,\t// Index = 86, Token = 10\n\t-23699,\t// Index = 86, Token = 11\n\t-30471,\t// Index = 86, Token = 12\n\t-37242,\t// Index = 86, Token = 13\n\t-44014,\t// Index = 86, Token = 14\n\t-50785,\t// Index = 86, Token = 15\n\t3724,\t// Index = 87, Token = 0\n\t11172,\t// Index = 87, Token = 1\n\t18621,\t// Index = 87, Token = 2\n\t26069,\t// Index = 87, Token = 3\n\t33518,\t// Index = 87, Token = 4\n\t40966,\t// Index = 87, Token = 5\n\t48415,\t// Index = 87, Token = 6\n\t55863,\t// Index = 87, Token = 7\n\t-3724,\t// Index = 87, Token = 8\n\t-11172,\t// Index = 87, Token = 9\n\t-18621,\t// Index = 87, Token = 10\n\t-26069,\t// Index = 87, Token = 11\n\t-33518,\t// Index = 87, Token = 12\n\t-40966,\t// Index = 87, Token = 13\n\t-48415,\t// Index = 87, Token = 14\n\t-55863,\t// Index = 87, Token = 15\n\t4095,\t// Index = 88, Token = 0\n\t12286,\t// Index = 88, Token = 1\n\t20478,\t// Index = 88, Token = 2\n\t28669,\t// Index = 88, Token = 3\n\t36862,\t// Index = 88, Token = 4\n\t45053,\t// Index = 88, Token = 5\n\t53245,\t// Index = 88, Token = 6\n\t61436,\t// Index = 88, Token = 7\n\t-4095,\t// Index = 88, Token = 8\n\t-12286,\t// Index = 88, Token = 9\n\t-20478,\t// Index = 88, Token = 10\n\t-28669,\t// Index = 88, Token = 11\n\t-36862,\t// Index = 88, Token = 12\n\t-45053,\t// Index = 88, Token = 13\n\t-53245,\t// Index = 88, Token = 14\n\t-61436\t// Index = 88, Token = 15\n};\n\n"
  },
  {
    "path": "CODE/DYNAVEC.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/DYNAVEC.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n *                                                                         *\n *                 Project Name : Red Alert                                *\n *                                                                         *\n *                    File Name : DYNAVEC.CPP                              *\n *                                                                         *\n *                   Programmer : Bill R Randolph                          *\n *                                                                         *\n *                   Start Date : 09/18/96                                 *\n *                                                                         *\n *                  Last Update : September 18, 1996 [BRR]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   DynamicVectorClass<T>::Add -- Add an element to the vector.           *\n *   DynamicVectorClass<T>::Add_Head -- Adds element to head of the list.  *\n *   DynamicVectorClass<T>::Add_Head -- Adds element to head of the list.  *\n *   DynamicVectorClass<T>::Delete -- Deletes specified index from vector. *\n *   DynamicVectorClass<T>::Delete -- Remove specified object from vector. *\n *   DynamicVectorClass<T>::DynamicVectorClass -- Constructor              *\n *   DynamicVectorClass<T>::ID -- Find matching value in dynamic vector.   *\n *   DynamicVectorClass<T>::Resize -- Changes size of a dynamic vector.    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include \"vector.h\"\n#ifdef WINSOCK_IPX\n#include\t\"WSProto.h\"\n#include\t\"WSPUDP.h\"\n#endif\t//WINSOCK_IPX\n#include\t<mem.h>\n#include\t<stdio.h>\n\n/***********************************************************************************************\n * DynamicVectorClass<T>::DynamicVectorClass -- Constructor for dynamic vector.                *\n *                                                                                             *\n *    This is the normal constructor for the dynamic vector class. It is similar to the normal *\n *    vector class constructor. The vector is initialized to contain the number of elements    *\n *    specified in the \"size\" parameter. The memory is allocated from free store unless the    *\n *    optional array parameter is provided. In this case it will place the vector at the       *\n *    memory location specified.                                                               *\n *                                                                                             *\n * INPUT:   size  -- The maximum number of objects allowed in this vector.                     *\n *                                                                                             *\n *          array -- Optional pointer to the memory area to place the vector at.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nDynamicVectorClass<T>::DynamicVectorClass(unsigned size, T const * array)\n\t: VectorClass<T>(size, array)\n{\n\tGrowthStep = 10;\n\tActiveCount = 0;\n}\n\n\n/***********************************************************************************************\n * DynamicVectorClass<T>::Resize -- Changes the size of a dynamic vector.                      *\n *                                                                                             *\n *    Use this routine to change the size of the vector. The size changed is the maximum       *\n *    number of allocated objects within this vector. If a memory buffer is provided, then     *\n *    the vector will be located there. Otherwise, the memory will be allocated out of free    *\n *    store.                                                                                   *\n *                                                                                             *\n * INPUT:   newsize  -- The desired maximum size of this vector.                               *\n *                                                                                             *\n *          array    -- Optional pointer to a previously allocated memory array.               *\n *                                                                                             *\n * OUTPUT:  bool; Was vector successfully resized according to specifications?                 *\n *                                                                                             *\n * WARNINGS:   Failure to resize the vector could be the result of lack of free store.         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint DynamicVectorClass<T>::Resize(unsigned newsize, T const * array)\n{\n\tif (VectorClass<T>::Resize(newsize, array)) {\n\t\tif (Length() < ActiveCount) ActiveCount = Length();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * DynamicVectorClass<T>::ID -- Find matching value in the dynamic vector.                     *\n *                                                                                             *\n *    Use this routine to find a matching object (by value) in the vector. Unlike the base     *\n *    class ID function of similar name, this one restricts the scan to the current number     *\n *    of valid objects.                                                                        *\n *                                                                                             *\n * INPUT:   object   -- A reference to the object that a match is to be found in the           *\n *                      vector.                                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the index number of the object that is equivalent to the one          *\n *          specified. If no equivalent object could be found then -1 is returned.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint DynamicVectorClass<T>::ID(T const & object)\n{\n\tfor (int index = 0; index < Count(); index++) {\n\t\tif ((*this)[index] == object) return(index);\n\t}\n\treturn(-1);\n}\n\n\n/***********************************************************************************************\n * DynamicVectorClass<T>::Add -- Add an element to the vector.                                 *\n *                                                                                             *\n *    Use this routine to add an element to the vector. The vector will automatically be       *\n *    resized to accomodate the new element IF the vector was allocated previously and the     *\n *    growth rate is not zero.                                                                 *\n *                                                                                             *\n * INPUT:   object   -- Reference to the object that will be added to the vector.              *\n *                                                                                             *\n * OUTPUT:  bool; Was the object added successfully? If so, the object is added to the end     *\n *                of the vector.                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint DynamicVectorClass<T>::Add(T const & object)\n{\n\tif (ActiveCount >= Length()) {\n\t\tif ((IsAllocated || !VectorMax) && GrowthStep > 0) {\n\t\t\tif (!Resize(Length() + GrowthStep)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tFailure to increase the size of the vector is an error condition.\n\t\t\t\t**\tReturn with the error flag.\n\t\t\t\t*/\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIncreasing the size of this vector is not allowed! Bail this\n\t\t\t**\troutine with the error code.\n\t\t\t*/\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tThere is room for the new object now. Add it to the end of the object vector.\n\t*/\n\t(*this)[ActiveCount++] = object;\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DynamicVectorClass<T>::Add_Head -- Adds element to head of the list.                        *\n *                                                                                             *\n *    This routine will add the specified element to the head of the vector. If necessary,     *\n *    the vector will be expanded accordingly.                                                 *\n *                                                                                             *\n * INPUT:   object   -- Reference to the object to add to the head of this vector.             *\n *                                                                                             *\n * OUTPUT:  bool; Was the object added without error?                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint DynamicVectorClass<T>::Add_Head(T const & object)\n{\n\tif (ActiveCount >= Length()) {\n\t\tif ((IsAllocated || !VectorMax) && GrowthStep > 0) {\n\t\t\tif (!Resize(Length() + GrowthStep)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tFailure to increase the size of the vector is an error condition.\n\t\t\t\t**\tReturn with the error flag.\n\t\t\t\t*/\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIncreasing the size of this vector is not allowed! Bail this\n\t\t\t**\troutine with the error code.\n\t\t\t*/\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tThere is room for the new object now. Add it to the end of the object vector.\n\t*/\n\tif (ActiveCount) {\n\t\tmemmove(&(*this)[1], &(*this)[0], ActiveCount * sizeof(T));\n\t}\n\t(*this)[0] = object;\n\tActiveCount++;\n//\t(*this)[ActiveCount++] = object;\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DynamicVectorClass<T>::Delete -- Remove the specified object from the vector.               *\n *                                                                                             *\n *    This routine will delete the object referenced from the vector. All objects in the       *\n *    vector that follow the one deleted will be moved \"down\" to fill the hole.                *\n *                                                                                             *\n * INPUT:   object   -- Reference to the object in this vector that is to be deleted.          *\n *                                                                                             *\n * OUTPUT:  bool; Was the object deleted successfully? This should always be true.             *\n *                                                                                             *\n * WARNINGS:   Do no pass a reference to an object that is NOT part of this vector. The        *\n *             results of this are undefined and probably catastrophic.                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint DynamicVectorClass<T>::Delete(T const & object)\n{\n\treturn(Delete(ID(object)));\n}\n\n\n/***********************************************************************************************\n * DynamicVectorClass<T>::Delete -- Deletes the specified index from the vector.               *\n *                                                                                             *\n *    Use this routine to delete the object at the specified index from the objects in the     *\n *    vector. This routine will move all the remaining objects \"down\" in order to fill the     *\n *    hole.                                                                                    *\n *                                                                                             *\n * INPUT:   index -- The index number of the object in the vector that is to be deleted.       *\n *                                                                                             *\n * OUTPUT:  bool; Was the object index deleted successfully? Failure might mean that the index *\n *                specified was out of bounds.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint DynamicVectorClass<T>::Delete(int index)\n{\n\tif ((unsigned)index < ActiveCount) {\n\t\tActiveCount--;\n\n\t\t/*\n\t\t**\tIf there are any objects past the index that was deleted, copy those\n\t\t**\tobjects down in order to fill the hole. A simple memory copy is\n\t\t**\tnot sufficient since the vector could contain class objects that\n\t\t**\tneed to use the assignment operator for movement.\n\t\t*/\n\t\tfor (int i = index; i < ActiveCount; i++) {\n\t\t\t(*this)[i] = (*this)[i+1];\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n/************************** end of dynavec.cpp *****************************/\n"
  },
  {
    "path": "CODE/EDIT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/EDIT.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : EDIT.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic, Maria del Mar McCready Legg                   *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : June 25, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   EditClass::Action -- Handles input events.                                                *\n *   EditClass::Draw_Background -- Draw the background to the edit gadget.                     *\n *   EditClass::Draw_Me -- Draws the edit box and embedded text.                               *\n *   EditClass::Draw_Text -- Draws the edit gadget text.                                       *\n *   EditClass::EditClass -- Normal constructor for edit class object.                         *\n *   EditClass::Handle_Key -- Handles keyboard input to edit gadget.                           *\n *   EditClass::Set_Text -- Sets the text to the edit gadget.                                  *\n *   EditClass::~EditClass -- Default destructor for the edit gadget.                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * EditClass::EditClass -- Normal constructor for edit class object.                           *\n *                                                                                             *\n *    This is the normal constructor used to create an edit object.                            *\n *                                                                                             *\n * INPUT:   id    -- The ID number for this edit object. This is the ID number that will be    *\n *                   returned by the Input() function when the <RETURN> key is pressed if this *\n *                   gadget has the keyboard input focus.                                      *\n *                                                                                             *\n *          text  -- Reference to the text buffer that the edit gadget will modify as keyboard *\n *                   input is processed. The value that this buffer contains is the default    *\n *                   text displayed.                                                           *\n *                                                                                             *\n *          maxlen-- The maximum size of the text buffer specified. This length INCLUDES the   *\n *                   trailing null character so a simple sizeof() function call can be used.   *\n *                                                                                             *\n *          flags -- These are the text print control flags. It is used to control how the     *\n *                   text looks in the edit box. Use the normal TPF_??? flags.                 *\n *                                                                                             *\n *          x,y   -- The pixel coordinates of the upper left corner of the edit gadget area.   *\n *                                                                                             *\n *          w,h   -- The pixel dimensions of the edit box. If either of these are no provided, *\n *                   or set to -1, then the dimension is determined from the string itself.    *\n *                                                                                             *\n *          sytle -- This style flag parameter control what kind of characters are allowed in  *\n *                   the edit box. The initial string in the text buffer may contain illegal   *\n *                   characters, but they are NOT removed regardless of this parameter.        *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n * WARNINGS:   none                                                                            *\n * HISTORY:                                                                                    *\n *   01/05/1995 MML : Created.                                                                 *\n *   01/21/1995 JLB : Modified.                                                                *\n *=============================================================================================*/\nEditClass::EditClass(int id, char * text, int max_len, TextPrintType flags, int x, int y, int w, int h, EditStyle style) :\n\tControlClass (id, x, y, w, h, LEFTPRESS), String(text)\n{\n\tTextFlags = flags & ~(TPF_CENTER);\n\tEditFlags = style;\n\tSet_Text(text, max_len);\n\tColor = GadgetClass::Get_Color_Scheme();\n\n\tif (w == -1 || h == -1) {\n\t\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TextFlags);\n\n\t\tif (h == -1) {\n\t\t\tHeight = FontHeight+1;\n\t\t}\n\t\tif (w == -1) {\n\t\t\tif (strlen(String) > 0) {\n\t\t\t\tWidth = String_Pixel_Width(String) + 6;\n\t\t\t} else {\n\t\t\t\tWidth = ((Char_Pixel_Width('X')+FontXSpacing) * (MaxLength+1)) + 2;\n\t\t\t}\n    \t}\n\t}\n\n\tIsReadOnly = 0;\n}\n\n\n/***********************************************************************************************\n * EditClass::~EditClass -- Default destructor for the edit gadget.                            *\n *                                                                                             *\n *    This default destructor removes the focus setting if it currently has it.                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEditClass::~EditClass(void)\n{\n\tif (Has_Focus()) {\n\t\tClear_Focus();\n\t}\n}\n\n\n/***********************************************************************************************\n * EditClass::Set_Text -- Sets the text to the edit gadget.                                    *\n *                                                                                             *\n *    Use this routine to change the text that this edit gadget refers to.                     *\n *                                                                                             *\n * INPUT:   text     -- Reference to the character array that this edit gadget will be         *\n *                      modifying.                                                             *\n *          max_len  -- The maximum size of the buffer that will be modified.                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n * WARNINGS:   none                                                                            *\n * HISTORY:                                                                                    *\n *   01/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid EditClass::Set_Text(char * text, int max_len)\n{\n\tString = text;\n\tMaxLength = max_len-1;\n\tLength = strlen(String);\n\tFlag_To_Redraw();\n}\n\n\n/***********************************************************************************************\n * EditClass::Draw_Me -- Draws the edit box and embedded text.                                 *\n *                                                                                             *\n *    This routine will render the edit box. This will show the box outline as well as any     *\n *    text it may contain.                                                                     *\n *                                                                                             *\n * INPUT:   forced   -- Should the edit box be drawn even if it thinks it doesn't have to?     *\n *                                                                                             *\n * OUTPUT:  Was the edit box drawn?                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint EditClass::Draw_Me(int forced)\n{\n\tif (ControlClass::Draw_Me(forced)) {\n\t\t/*\n\t\t**\tHide the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Hide_Mouse(X, Y, X+Width, Y+Height);\n\t\t}\n\n\t\t/*\n\t\t**\tDraw the body & set text color.\n\t\t*/\n\t\tDraw_Background();\n\n\t\t/*\n\t\t**\tDisplay the text.\n\t\t*/\n\t\tDraw_Text(String);\n\n\t\t/*\n\t\t**\tDisplay the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Show_Mouse();\n\t\t}\n\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * EditClass::Action -- Handles input events.                                                  *\n *                                                                                             *\n *    This routine will handle all mouse and keyboard events directed at this edit box         *\n *    gadget. For keyboard events, this will insert the characters into the edit box.          *\n *                                                                                             *\n * INPUT:   flags -- The event flag that triggered this function call.                         *\n *                                                                                             *\n *          key   -- Reference to the keyboard/mouse event that triggered this function call.  *\n *                                                                                             *\n * OUTPUT:  Should the list be processed further?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint EditClass::Action(unsigned flags, KeyNumType & key)\n{\n\t/*\n\t** If this is a read-only edit box, it's a display-only device\n\t*/\n\tif (IsReadOnly) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the left mouse button is pressed over this gadget, then set the focus to\n\t**\tthis gadget. The event flag is cleared so that no button ID number is returned.\n\t*/\n\tif ((flags & LEFTPRESS)) {\n\t\tflags &= ~LEFTPRESS;\n\t\tSet_Focus();\n\t\tFlag_To_Redraw();\t\t// force to draw cursor\n\t}\n\n\t/*\n\t**\tHandle keyboard events here. Normally, the key is added to the string, but if the\n\t**\tRETURN key is pressed, then the button ID number is returned from the Input()\n\t**\tfunction.\n\t*/\n\tif ((flags & KEYBOARD) && Has_Focus()) {\n\n\t\t/*\n\t\t**\tProcess the keyboard character. If indicated, consume this keyboard event\n\t\t**\tso that the edit gadget ID number is not returned.\n\t\t*/\n\t\tif (key == KN_ESC) {\n\n\t\t\tClear_Focus();\n\t\t\tflags = 0;\n\n\t\t} else {\n#ifdef WIN32\n\n\t\t\tKeyASCIIType ascii = (KeyASCIIType)(Keyboard->To_ASCII(key) & 0xff);\n\n\t\t\t/*\n\t\t\t** Allow numeric keypad presses to map to ascii numbers\n\t\t\t*/\n\t\t\tif ((key & WWKEY_VK_BIT) && ascii >='0' && ascii <= '9') {\n\n\t\t\t\tkey = (KeyNumType)(key & ~WWKEY_VK_BIT);\n\t\t\t\tif ( (!(flags & LEFTRELEASE)) && (!(flags & RIGHTRELEASE))) {\n\t\t\t\t\tif (Handle_Key (ascii) ) {\n\t\t\t\t\t\tflags &= ~KEYBOARD;\n\t\t\t\t\t\tkey = KN_NONE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t** Filter out all special keys except return and backspace\n\t\t\t\t*/  \tif ((!(key & WWKEY_VK_BIT) && ascii >= ' ' && ascii <= 255)\n\t\t\t\t\t|| key == KN_RETURN || key == KN_BACKSPACE) {\n\n\n\n\t\t\t\t\tif ((!(flags & LEFTRELEASE)) && (!(flags & RIGHTRELEASE))) {\n\t\t\t\t\t\tif (Handle_Key(Keyboard->To_ASCII(key))) {\n\t\t\t\t\t\t\tflags &= ~KEYBOARD;\n\t\t\t\t\t\t\tkey = KN_NONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tflags &= ~KEYBOARD;\n\t\t\t\t\tkey = KN_NONE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n#else\t//WIN32\n\t\t\tif (Handle_Key(Keyboard->To_ASCII(key))) {\n\t\t\t\tflags &= ~KEYBOARD;\n\t\t\t\tkey = KN_NONE;\n\t\t\t}\n\t\t}\n#endif\t//WIN32\n\t}\n\n\treturn(ControlClass::Action(flags, key));\n}\n\n\n/***********************************************************************************************\n * EditClass::Draw_Background -- Draw the background to the edit gadget.                       *\n *                                                                                             *\n *    This routine will redraw the edit gadget background. The overlaying text is handled by   *\n *    a different routine. The mouse is guaranteed to be hidden when this routine is called.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid EditClass::Draw_Background(void)\n{\n\tDraw_Box (X, Y, Width, Height, BOXSTYLE_BOX, true);\n}\n\n\n/***********************************************************************************************\n * EditClass::Draw_Text -- Draws the edit gadget text.                                         *\n *                                                                                             *\n *    This routine is called when the edit gadget text needs to be drawn. The background has   *\n *    already been drawn by the time this function is called. The mouse is guaranteed to be    *\n *    hidden as well.                                                                          *\n *                                                                                             *\n * INPUT:   text  -- The text to draw in the edit gadget.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid EditClass::Draw_Text(char const * text)\n{\n\tTextPrintType flags;\n\n\tif (Has_Focus()) {\n\t\tflags = TPF_BRIGHT_COLOR;\n\t} else {\n\t\tflags = (TextPrintType)0;\n\t}\n\n\tConquer_Clip_Text_Print(text, X+1, Y+1, Color, TBLACK, TextFlags | flags, Width-2);\n\n\tif (Has_Focus() && strlen(text) < MaxLength &&\n\t\t(String_Pixel_Width(text) + String_Pixel_Width (\"_\") < Width-2) ) {\n\t\tConquer_Clip_Text_Print( \"_\", X+1+String_Pixel_Width(text), Y+1, Color, TBLACK, TextFlags | flags);\n\t}\n}\n\n\n/***********************************************************************************************\n * EditClass::Handle_Key -- Handles keyboard input to edit gadget.                             *\n *                                                                                             *\n *    This is the gruntwork routine that processes keyboard input to the edit gadget. This     *\n *    routine will be called when keyboard input has been detected and this gadget has the     *\n *    current focus.                                                                           *\n *                                                                                             *\n * INPUT:   ascii -- The ASCII key code that was fetched from the keyboard buffer.             *\n *                                                                                             *\n * OUTPUT:  bool; Should this keyboard input NOT cause the gadget ID number to be returned     *\n *                from the controlling Input() routine? Typically, the return value would be   *\n *                true unless the focus is lost due to the <RETURN> key being pressed.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n * HISTORY:                                                                                    *\n *   01/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool EditClass::Handle_Key(KeyASCIIType ascii)\n{\n\tswitch (ascii) {\n\t\t/*\n\t\t**\tHandle the special case of a non-keyboard event. It is possible that this\n\t\t**\tkey code might be passed to this routine if this routine has been overridden\n\t\t**\tand the key event was consumed.\n\t\t*/\n\t\tcase 0:\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tIf the return key is pressed, then remove the focus from this edit\n\t\t**\tgadget but otherwise let the normal gadget processing proceed. This\n\t\t**\tcauses the gadget ID number to be returned from the Input() function\n\t\t**\tso that the controlling program will know that the text can be\n\t\t**\tprocessed.\n\t\t*/\n\t\tcase KA_RETURN:\n\t\t\tClear_Focus();\n\t\t\treturn(false);\n\n\t\t/*\n\t\t**\tWhen the BACKSPACE key is pressed, remove the last character in the edit string.\n\t\t*/\n\t\tcase KA_BACKSPACE:\n\t\t\tif (Length) {\n\t\t\t\tLength--;\n\t\t\t\tString[Length] = '\\0';\n\t\t\t\tFlag_To_Redraw();\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tIf the keyboard event was not a recognized special key, then examine to see\n\t\t**\tif it can legally be added to the edit string and do so if possible.\n\t\t*/\n\t\tdefault:\n\n\t\t\t/*\n\t\t\t**\tDon't add a character if the length is greater than edit width.\n\t\t\t*/\n\t\t\tif ((String_Pixel_Width(String) + Char_Pixel_Width(ascii) ) >= (Width-2)) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDon't add a character if the length is already at maximum.\n\t\t\t*/\n\t\t\tif (Length >= MaxLength) break;\n\n\t\t\t/*\n\t\t\t**\tInvisible characters are never added to the string. This is\n\t\t\t**\tespecially true for spaces at the beginning of the string.\n\t\t\t*/\n\t\t\tif (!isgraph(ascii) && ascii != ' ') break;\n\t\t\tif (ascii == ' ' && Length == 0) break;\n\n\t\t\t/*\n\t\t\t**\tIf this is an upper case only edit gadget, then force the alphabetic\n\t\t\t**\tcharacter to upper case.\n\t\t\t*/\n\t\t\tif ((EditFlags & UPPERCASE) && isalpha(ascii)) {\n\t\t\t\tascii = (KeyASCIIType)toupper(ascii);\n\t\t\t}\n\n\t\t\tif ((!(EditFlags & NUMERIC) || !isdigit(ascii)) &&\n\t\t\t\t(!(EditFlags & ALPHA) || !isalpha(ascii)) &&\n\t\t\t\t(!(EditFlags & MISC) || isalnum(ascii)) &&\n\t\t\t\tascii != ' ') {\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tThe character passed all legality checks, so add it to the edit string\n\t\t\t**\tand flag this gadget to be redrawn. The manual flag to redraw is needed\n\t\t\t**\tbecause the event flag has been cleared. This prevents the gadget's ID\n\t\t\t**\tnumber from being returned just because the gadget has been edited.\n\t\t\t*/\n\t\t\tString[Length++] = ascii;\n\t\t\tString[Length] = '\\0';\n\t\t\tFlag_To_Redraw();\n\t\t\tbreak;\n\t}\n\treturn(true);\n}\n\n\nvoid EditClass::Set_Focus(void)\n{\n\tLength = 0;\n\tif (String) {\n\t\tLength = strlen(String);\n\t}\n\tControlClass::Set_Focus();\n}\n"
  },
  {
    "path": "CODE/EDIT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/EDIT.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : EDIT.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef EDIT_H\n#define EDIT_H\n\nclass EditClass : public ControlClass\n{\n\tpublic:\n\t\ttypedef enum EditStyle {\n\t\t\tALPHA\t\t\t=0x0001,\t\t// Edit accepts alphabetic characters.\n\t\t\tNUMERIC\t\t=0x0002,\t\t// Edit accepts numbers.\n\t\t\tMISC\t\t\t=0x0004,\t\t// Edit accepts misc graphic characters.\n\t\t\tUPPERCASE\t=0x0008,\t\t// Force to upper case.\n\t\t\tALPHANUMERIC=(int)ALPHA|(int)NUMERIC|(int)MISC\n\t\t} EditStyle;\n\n\t\tEditClass (int id, char * text, int max_len, TextPrintType flags, int x, int y, int w=-1, int h=-1, EditStyle style=ALPHANUMERIC);\n\t\tvirtual ~EditClass(void);\n\n\t\tvirtual void Set_Focus(void);\n\t\tvirtual int  Draw_Me(int forced);\n\t\tvirtual void Set_Text(char * text, int max_len);\n\t\tvirtual char * Get_Text(void) {return(String);};\n\t\tvoid Set_Color (RemapControlType * color) { Color = color; }\n\n\t\tvoid Set_Read_Only(int rdonly) {IsReadOnly = rdonly;}\n\n\tprotected:\n\n\t\t/*\n\t\t**\tThese are the text size and style flags to be used when displaying the text\n\t\t**\tof the edit gadget.\n\t\t*/\n\t\tTextPrintType TextFlags;\n\n\t\t/*\n\t\t**\tInput flags that control what characters are allowed in the string.\n\t\t*/\n\t\tEditStyle EditFlags;\n\n\t\t/*\n\t\t**\tPointer to text staging buffer and the maximum length of the string it\n\t\t**\tcan contain.\n\t\t*/\n\t\tchar *String;\n\t\tint MaxLength;\n\n\t\t/*\n\t\t**\tThis is the current length of the string. This length will never exceed the\n\t\t**\tMaxLength allowed.\n\t\t*/\n\t\tint Length;\n\n\t\t/*\n\t\t**\tThis is the desired color of the edit control.\n\t\t*/\n\t\tRemapControlType * Color;\n\n\t\tvirtual int Action (unsigned flags, KeyNumType &key);\n\t\tvirtual void Draw_Background(void);\n\t\tvirtual void Draw_Text(char const * text);\n\t\tvirtual bool Handle_Key(KeyASCIIType ascii);\n\n\tprivate:\n\t\tint IsReadOnly;\n};\n\ninline EditClass::EditStyle operator |(EditClass::EditStyle, EditClass::EditStyle);\ninline EditClass::EditStyle operator &(EditClass::EditStyle, EditClass::EditStyle);\ninline EditClass::EditStyle operator ~(EditClass::EditStyle);\n\n#endif\n"
  },
  {
    "path": "CODE/EGOS.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /counterstrike/EGOS.CPP 2     3/10/97 3:19p Steve_tall $ */\n/*************************************************************************************\n **   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                  **\n *************************************************************************************\n *                                                                                   *\n *                 Project Name : Command & Conquer - Red Alert                      *\n *                                                                                   *\n *                    File Name : EGOS.CPP                                           *\n *                                                                                   *\n *                   Programmer : Steve Tall                                         *\n *                                                                                   *\n *                   Start Date : September 4th, 1996                                *\n *                                                                                   *\n *                  Last Update : September 4th, 1996 [ST]                           *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Overview:                                                                         *\n *                                                                                   *\n *   Scrolling movie style credits.                                                  *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Functions:                                                                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \t\"function.h\"\n\n/*\n** List of Ego Class instances\n**  There will be one instance for each line of text.\n*/\nDynamicVectorClass<EgoClass *> EgoList;\n\n/*\n** Number of slideshow pictures\n*/\n\n#define NUM_SLIDES 17\n\n/*\n** Length of time frame is displayed for\n*/\n#define FRAME_DELAY\t150\n\n/*\n** Number of frames that palete fade occurs over\n*/\n#define FADE_DELAY\t\t37\n\n/*\n** Names of slideshow pictures to play behind the text\n*/\nchar SlideNames[NUM_SLIDES][13]={\n\n\t\"aftr_hi.pcx\",\n\t\"aly1.pcx\",\n\t\"apc_hi.pcx\",\n\t\"aphi0049.pcx\",\n\t\"bnhi0020.pcx\",\n\t\"dchi0040.pcx\",\n\t\"frhi0166.pcx\",\n\t\"lab.pcx\",\n\t\"landsbrg.pcx\",\n\t\"mahi0107.pcx\",\n\t\"mig_hi.pcx\",\n\t\"mtfacthi.pcx\",\n\t\"needle.pcx\",\n\t\"sov2.pcx\",\n\t\"spy.pcx\",\n\t\"stalin.pcx\",\n\t\"tent.pcx\"\n};\n\n/*\n** Names of low res slideshow pictures to play behind the text\n*/\nchar LoresSlideNames[NUM_SLIDES][13]={\n\t\"malo0107.cps\",\n\t\"mig_lo.cps\",\n\t\"mtfactlo.cps\",\n\t\"needl-lo.cps\",\n\t\"sov2-lo.cps\",\n\t\"spy-lo.cps\",\n\t\"staln-lo.cps\",\n\t\"tent-lo.cps\",\n\t\"aftr_lo.cps\",\n\t\"aly1-lo.cps\",\n\t\"apc_lo.cps\",\n\t\"aplo0049.cps\",\n\t\"bnlo0020.cps\",\n\t\"dclo0040.cps\",\n\t\"frlo0166.cps\",\n\t\"lab-lo.cps\",\n\t\"lands-lo.cps\"\n};\n\n/*\n** Array of all the palettes required for the slides\n*/\nchar SlidePals[NUM_SLIDES][256*3];\n\n/*\n** Array of graphic buffers containing the slides\n*/\nGraphicBufferClass *SlideBuffers[NUM_SLIDES];\n\n/*\n** Original copy of slide (pref in video mem) that we use to undraw the text\n*/\nGraphicBufferClass *BackgroundPage;\n\n/*\n**  This palette contains both the font palette entries and the slide\n**  palette.\n*/\nPaletteClass ComboPalette;\n\n/*\n** Ptr to the combo palette.\n*/\nunsigned char *ComboPalPtr;\n\n/*\n** Lookup table. If an entry is non-zero then it should be faded in/out when the slide changes.\n*/\nchar PaletteLUT[256];\n\n/*\n** Height of the strips that are blitted from the slides to the backgound and hid pages.\n** We blit in several strips over several frames so as not to impact on the frame rate.\n*/\n#define CHUNK_HEIGHT RESFACTOR * 50\n\n\n\n#ifndef\tWIN32\nextern void Vsync(void);\n#pragma aux Vsync modify [edx ebx eax] = \\\n\t\"mov\tedx,03DAh\"\t\t\t\t\\\n\t\"mov\tebx,[VertBlank]\"\t\t\\\n\t\"and\tbl,001h\"\t\t\t\t\t\\\n\t\"shl\tbl,3\"\t\t\t\t\t\t\\\n\t\"in_vbi:\"\t\t\t\t\t\t\\\n\t\"in\tal,dx\"\t\t\t\t\t\\\n\t\"and\tal,008h\"\t\t\t\t\t\\\n\t\"xor\tal,bl\"\t\t\t\t\t\\\n\t\"je\tin_vbi\"\t\t\t\t\t\\\n\t\"out_vbi:\"\t\t\t\t\t\t\\\n\t\"in\tal,dx\"\t\t\t\t\t\\\n\t\"and\tal,008h\"\t\t\t\t\t\\\n\t\"xor\tal,bl\"\t\t\t\t\t\\\n\t\"jne\tout_vbi\"\n#endif\t//WIN32\n\n\n\n/***********************************************************************************************\n * EC::EgoClass -- EgoClass constructor                                                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    x position of text                                                                *\n *           y position of text                                                                *\n *           ptr to text string                                                                *\n *           flags to print text with                                                          *\n *                                                                                             *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/9/96 11:53PM ST : Created                                                              *\n *=============================================================================================*/\nEgoClass::EgoClass (int x, int y, char *text, TextPrintType flags)\n{\n\tXPos = x;\n\tYPos = y;\n\tFlags= flags;\n\tText = new char [strlen (text)+1];\n\tstrcpy (Text, text);\n}\n\n\n/***********************************************************************************************\n * EC::~EgoClass -- EgoClass destructor                                                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/9/96 11:54PM ST : Created                                                              *\n *=============================================================================================*/\nEgoClass::~EgoClass(void)\n{\n\tdelete [] Text;\n}\n\n\n/***********************************************************************************************\n * EC::Scroll -- Apply the given distance to the y position of the text.                       *\n *               A positive distance scrolls up.                                               *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    distance in pixels to scroll up                                                   *\n *                                                                                             *\n * OUTPUT:   true if text scrolled beyond the top of the screen                                *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/9/96 11:55PM ST : Created                                                              *\n *=============================================================================================*/\nbool EgoClass::Scroll(int distance)\n{\n\tYPos -= distance;\n\tif (YPos < -20) {\n\t\treturn (true);\n\t}else{\n\t\treturn (false);\n\t}\n}\n\n\n/***********************************************************************************************\n * EC::Render -- Draws the text to the logic page                                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/9/96 11:57PM ST : Created                                                              *\n *=============================================================================================*/\nvoid EgoClass::Render (void)\n{\n\tif (YPos < LogicPage->Get_Height() && YPos > -16) {\n\t\tFancy_Text_Print(Text, XPos, YPos, GadgetClass::Get_Color_Scheme(), TBLACK, Flags);\n\t}\n}\n\n\n\n/***********************************************************************************************\n * EC::Wipe -- Wipes the previously rendered text by blitting a rectangle from the given       *\n *             background screen.                                                              *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to screen containing original background                                      *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/9/96 11:58PM ST : Created                                                              *\n *=============================================================================================*/\nvoid EgoClass::Wipe (GraphicBufferClass *background)\n{\n\tint width = String_Pixel_Width (Text);\n\tint x = XPos;\n\n\tif (Flags & TPF_RIGHT) {\n\t\tx -= width;\n\t}else{\n\t\tif (Flags & TPF_CENTER){\n\t\t\tx -= width/2;\n\t\t}\n\t}\n\n\tbackground->Blit(*LogicPage, x-1, YPos, x-1, YPos, width+2, 7 * RESFACTOR +1, false);\n}\n\n\n\n/***********************************************************************************************\n * Set_Pal -- Low level palette set                                                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to palette                                                                    *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/9/96 11:59PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Set_Pal(char *palette)\n{\n//#ifndef WIN32\n\t//Vsync();\n\t//unsigned char *rgbptr = (unsigned char *) palette;\n\t//outportb(0x03C8, 0);\t\t\t\t\t\t\t\t\t\t\t\t//Start from color 0\n\n\t//for (int index = 0; index < 256; index++) {\n\t//\toutrgb(rgbptr[index*3], rgbptr[index*3+1], rgbptr[index*3+2]);\n\t//}\n//#else\t//WIN32\n\n\tSet_Palette((void*)palette);\n//#endif\n}\n\n\n/***********************************************************************************************\n * Slide_Show -- Handles the blitting and fading of the background pictures.                   *\n *                                                                                             *\n *  The picture frame number is used to trigger blitting and fading events                     *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    picture number                                                                    *\n *           frame                                                                             *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/10/96 0:16AM ST : Created                                                              *\n *=============================================================================================*/\nvoid Slide_Show (int slide, int frame)\n{\n\n\t/*\n\t** Temprary storage to save CCPalette to\n\t*/\n\tchar save_palette[256*3];\n\n\n\tif (frame >= 1 && frame <=4){\n\t\t/*\n\t\t** Blit in a quarter of the new frame to the background page.\n\t\t*/\n\t\tSlideBuffers[slide]->Blit (*BackgroundPage, \t0, (frame-1) * CHUNK_HEIGHT,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t0, (frame-1) * CHUNK_HEIGHT,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Width(), CHUNK_HEIGHT, false);\n\t\treturn;\n\t}\n\n\tif (frame >= 5 && frame <=8 ){\n\t\t/*\n\t\t** Blit in a quarter of the new frame to the hid page.\n\t\t*/\n\t\tBackgroundPage->Blit (HidPage,\t0, (frame-5) * CHUNK_HEIGHT,\n\t\t\t\t\t\t\t\t\t\t\t\t0, (frame-5) * CHUNK_HEIGHT,\n\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Width(), CHUNK_HEIGHT, false);\n\t\treturn;\n\t}\n\n\tif (frame ==9){\n\t\t/*\n\t\t** Create the combo palette from the font entries and the picture entries.\n\t\t*/\n\t\tfor (int index = 0 ; index < 256 ; index++ ){\n\t\t\tif (PaletteLUT[index]) {\n\t\t\t\tComboPalPtr[index*3] = SlidePals[slide][index*3];\n\t\t\t\tComboPalPtr[index*3+1] = SlidePals[slide][index*3+1];\n\t\t\t\tComboPalPtr[index*3+2] = SlidePals[slide][index*3+2];\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\n\n\tif (frame >10 && frame < FADE_DELAY+10){\n\t\t/*\n\t\t** Fade up the picture in the background. The text colors never fade.\n\t\t*/\n\t\tmemcpy (save_palette, CCPalette, sizeof(save_palette));\n\t\t//CCPalette.Partial_Adjust (MIN (6*(frame-5), 255), ComboPalette, PaletteLUT);\n\t\tCCPalette.Partial_Adjust (MIN ((255/FADE_DELAY)*(frame-10), 255), ComboPalette, PaletteLUT);\n\t\tSet_Pal ( (char *) &CCPalette);\n\t\tif (frame != 9+FADE_DELAY){\n\t\t\tmemcpy (CCPalette, save_palette, sizeof(save_palette));\n\t\t}else{\n\t\t\tmemcpy (CCPalette, CurrentPalette, sizeof (CCPalette));\n\t\t}\n\t\treturn;\n\t}\n\n\n\tif (frame >FRAME_DELAY && frame < FRAME_DELAY+FADE_DELAY){\n\t\t/*\n\t\t** Fade down the picture in the background. The text colors never fade.\n\t\t*/\n\t\tmemcpy (save_palette, CCPalette, sizeof(save_palette));\n\t\tCCPalette.Partial_Adjust (MIN ((255/FADE_DELAY)*(frame-FRAME_DELAY), 255), PaletteLUT);\n\t\tif (frame != FRAME_DELAY+FADE_DELAY-1){\n\t\t\tSet_Pal ( (char *) &CCPalette);\n\t\t\tmemcpy (CCPalette, save_palette, sizeof(save_palette));\n\t\t}else{\n\t\t\t/*\n\t\t\t** If this is the last fade down frame then zero the picture palette entries.\n\t\t\t*/\n\t\t\tunsigned char *ccpalptr = (unsigned char*)CCPalette;\n\t\t\tfor (int index = 0 ; index < 256 ; index++){\n\t\t\t\tif (PaletteLUT[index]){\n\t\t\t\t\tccpalptr[index*3] = 0;\n\t\t\t\t\tccpalptr[index*3+1] = 0;\n\t\t\t\t\tccpalptr[index*3+2] = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\tSet_Pal ( (char *) &CCPalette);\n\t\t}\n\n\t}\n\n}\n\n\n\n\n/***********************************************************************************************\n * Show_Who_Was_Responsible -- Main function to print the credits.                             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/10/96 0:20AM ST : Created                                                              *\n *=============================================================================================*/\nvoid Show_Who_Was_Responsible (void)\n{\n\n\tint\ti;\n\tint\tkey;\n\n\t/*\n\t** Deault speed of credits scolling. This is the frame delay between pixel scrolls.\n\t*/\n\tstatic int speed = 3;\n\n\t/*\n\t** In DOS we need to scroll slower so we have a bool that lets us do it every other time\n\t*/\n#ifndef WIN32\n\tbool\tscroll_now = false;\n#endif\t//WIN32\n\n\t/*\n\t** Read in the credits file to be displayed\n\t**\n\t** Lines of text in CREDITS.TXT are treated as follows....\n\t**\n\t**  If the text starts and ends to the left of column 40 then text will be right justified.\n\t**  If the text starts before column 40 and ends after it then it will be centered.\n\t**  If the text starts after column 40 it will be right justified.\n\t*/\n\tCCFileClass creditsfile (\"credits.txt\");\n\tif ( !creditsfile.Is_Available()) return;\n\tchar *credits = new char [creditsfile.Size()+1];\n\tcreditsfile.Read (credits, creditsfile.Size());\n\n\t/*\n\t** Initialise the text printing system.\n\t*/\n\tGadgetClass::Set_Color_Scheme(&ColorRemaps[PCOLOR_GREEN]);\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tTBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\n\t/*\n\t** Miscellaneous stuff for parsing the credits text file.\n\t*/\n\tint \t\t\t\tlength = creditsfile.Size();\n\tint \t\t\t\tline   = 0;\n\tint \t\t\t\tcolumn = 0;\n\tchar\t\t\t\t*cptr = credits;\n\tchar\t\t\t\tch, lastchar, oldchar;\n\tchar\t\t\t\t*strstart, *strparse;\n\tbool\t\t\t\tgotendstr;\n\tint\t\t\t\tstartcolumn, endcolumn, x;\n\tint\t\t\t\ty=SeenBuff.Get_Height()+2;\n\tEgoClass \t\t*ego;\n\tTextPrintType \tflags;\n\n\n\t/*\n\t** Search through the text file and extract the strings, using each string to create\n\t** a new EgoClass\n\t*/\n\tdo {\n\t\t/*\n\t\t** Search for text\n\t\t*/\n\t\tch = *cptr++;\n\t\tlength --;\n\n\t\t/*\n\t\t** Look for a non whitespace character.\n\t\t*/\n\t\tswitch ( ch ){\n\n\t\t\tcase 13:\n\t\t\t\t/*\n\t\t\t\t** Char was carriage return. Go on to the next line starting at column 0.\n\t\t\t\t*/\n\t\t\t\tline++;\n\t\t\t\tcolumn = 0;\n\t\t\t\tbreak;\n\n\n\t\t\tcase 10:\n\t\t\t\t/*\n\t\t\t\t** Ignore line feed. CR does both.\n\t\t\t\t*/\n\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t** Space character. Just advance the cursor and move on.\n\t\t\t\t*/\n\t\t\tcase 32:\n\t\t\t\tcolumn++;\n\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t** Tab char. Advance to the next tab column. Tabs are every 8 columns.\n\t\t\t\t*/\n\t\t\tcase 9:\n\t\t\t\tcolumn += 8;\n\t\t\t\tcolumn &= 0xfffffff8;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\t/*\n\t\t\t\t** Found new string. Work out where it ends so we know how to treat it.\n\t\t\t\t*/\n\t\t\t\tlastchar = ch;\n\t\t\t\tstrstart = cptr-1;\n\t\t\t\tstrparse = cptr-1;\n\t\t\t\tendcolumn = startcolumn = column;\n\t\t\t\tgotendstr = false;\n\n\t\t\t\tdo\t{\n\t\t\t\t\tch = *strparse++;\n\t\t\t\t\tswitch ( ch ){\n\t\t\t\t\t\tcase 9:\n\t\t\t\t\t\tcase 10:\n\t\t\t\t\t\tcase 13:\n\t\t\t\t\t\t\tgotendstr = true;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 32:\n\t\t\t\t\t\t\tif (lastchar == 32) gotendstr = true;\n\t\t\t\t\t\t\tendcolumn++;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tendcolumn++;\n\t\t\t\t\t}\n\t\t\t\t\tif (strparse >= cptr+length) gotendstr = true;\n\n\t\t\t\t\tlastchar = ch;\n\t\t\t\t}while (!gotendstr);\n\n\n\t\t\t\tif (strparse >= cptr+length) break;\n\n\t\t\t\t/*\n\t\t\t\t** Strip off any trailing space.\n\t\t\t\t*/\n\t\t\t\tif (*(strparse-2) == 32){\n\t\t\t\t\tstrparse--;\n\t\t\t\t\tendcolumn -= 2;\n\t\t\t\t}\n\n\n\t\t\t\t/*\n\t\t\t\t** If string straddles the center column then center it.\n\t\t\t\t**\n\t\t\t\t** If string is on the left hand side then right justify it.\n\t\t\t\t**\n\t\t\t\t** If string is on the right hand side then left justify it.\n\t\t\t\t*/\n\t\t\t\tflags = TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_DROPSHADOW;\t//TPF_NOSHADOW;\n\n\t\t\t\tif (startcolumn <40 && endcolumn >40){\n\t\t\t\t\tflags = flags | TPF_CENTER;\n\t\t\t\t\tx = SeenBuff.Get_Width() / 2;\n\t\t\t\t}else{\n\t\t\t\t\tif (startcolumn <40){\n\t\t\t\t\t\tflags = flags | TPF_RIGHT;\n\t\t\t\t\t\tx = endcolumn *SeenBuff.Get_Width() /80;\n\t\t\t\t\t}else{\n\t\t\t\t\t\tx = startcolumn * SeenBuff.Get_Width() / 80;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Temporarily terminate the string.\n\t\t\t\t*/\n\t\t\t\toldchar = *(strparse-1);\n\t\t\t\t*(strparse-1) = 0;\n\n\t\t\t\t/*\n\t\t\t\t** Create the new class and add it to our list.\n\t\t\t\t*/\n\t\t\t\tego = new EgoClass (x, y+ line *8 *RESFACTOR, strstart, flags);\n\n\t\t\t\tEgoList.Add (ego);\n\n\t\t\t\t/*\n\t\t\t\t** Restore the character that was lost when we added the terminator.\n\t\t\t\t*/\n\t\t\t\t*(strparse-1) = oldchar;\n\n\t\t\t\t/*\n\t\t\t\t** Fix up our outer loop parsing variables.\n\t\t\t\t*/\n\t\t\t\tcptr = strparse;\n\t\t\t\tcolumn += strparse - strstart;\n\t\t\t\tlength -= strparse - strstart-1;\n\n\t\t\t\tif (ch == 13) {\n\t\t\t\t\tline++;\n\t\t\t\t\tcolumn = 0;\n\t\t\t\t}else{\n\t\t\t\t\tif (ch == 9){\n\t\t\t\t\t\tcolumn += 7;\n\t\t\t\t\t\tcolumn &= 0xfffffff8;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t} while ( length>0 );\n\n\n\t/*\n\t** Work out which palette entries the font needs so we dont fade those colors.\n\t*/\n\tmemset (PaletteLUT, 1, sizeof (PaletteLUT));\n\tint pcolor = PCOLOR_GREEN;\n\n\tfor (int index = 0; index < 6; index++) {\n\t\tPaletteLUT[ColorRemaps[pcolor].FontRemap[10+index]] =0;\n\t}\n\t//PaletteLUT[ColorRemaps[pcolor].BrightColor] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Color] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Shadow] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Background] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Corners] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Highlight] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Bright] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Underline] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Bar] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Box] = 0;\n\n\n\t/*\n\t** Stop the music.\n\t*/\n\tTheme.Stop();\n\n\t/*\n\t** Fade to black.\n\t*/\n\tBlackPalette.Set(TIMER_SECOND*2, Call_Back);\n\n\t/*\n\t** Load the reference palette for the font.\n\t*/\n\t//Load_Title_Page(true);\n//#ifdef WIN32\n//\tLoad_Picture(\"EGOPAL.CPS\", SysMemPage, SysMemPage, CCPalette, BM_DEFAULT);\n//#else\t//WIN32\n//\tLoad_Picture(\"EGOPAL.CPS\", HidPage, HidPage, CCPalette, BM_DEFAULT);\n//#endif\t//WIN32\n\n\n\tCCFileClass(\"EGOPAL.PAL\").Read(&CCPalette, sizeof(CCPalette));\n\n\t/*\n\t** Copy the font palette entries into the combo palette.\n\t*/\n\tPaletteClass credit_palette;\n\tComboPalPtr = (unsigned char *) &ComboPalette;\n\tunsigned char *creditpal_ptr = (unsigned char *) &credit_palette;\n\tmemcpy (ComboPalette, CCPalette, sizeof (ComboPalette));\n\n\tfor (index = 0 ; index < 256 ; index++ ){\n\t\tif (PaletteLUT[index]) {\n\t\t\tComboPalPtr[index*3] = 0;\n\t\t\tComboPalPtr[index*3+1] = 0;\n\t\t\tComboPalPtr[index*3+2] = 0;\n\t\t}\n\t}\n\n\t/*\n\t** Clear the Seen Page since we will not be blitting to all of it.\n\t*/\n\tSeenBuff.Clear();\n\tHidPage.Clear();\n\n\t/*\n\t** Set the font palette.\n\t*/\n\tmemcpy ( CCPalette, ComboPalette, sizeof (ComboPalette) );\n\tCCPalette.Set();\n\n\t/*\n\t** Loop through and load up all the slideshow pictures\n\t*/\n\tfor (index = 0 ; index < NUM_SLIDES ; index++){\n#ifdef WIN32\n\t\tSlideBuffers[index] = new GraphicBufferClass;\n\t\tSlideBuffers[index]->Init (SeenBuff.Get_Width(), SeenBuff.Get_Height(), NULL , 0 , (GBC_Enum)0);\n\t\tLoad_Title_Screen(&SlideNames[index][0], SlideBuffers[index], (unsigned char*) &SlidePals[index][0]);\n#else\t//WIN32\n\t\tSlideBuffers[index] = new GraphicBufferClass (SeenBuff.Get_Width(), SeenBuff.Get_Height(), (void*)NULL);\n\t\tLoad_Picture(&LoresSlideNames[index][0], *SlideBuffers[index], *SlideBuffers[index], (unsigned char *)&SlidePals[index][0], BM_DEFAULT);\n#endif\t//WIN32\n\t}\n\n\t/*\n\t** Create a new graphic buffer to restore the background from. Initialise it to black so\n\t** we can start scrolling before the first slideshow picture is blitted.\n\t*/\n#ifdef WIN32\n\tBackgroundPage = new GraphicBufferClass;\n\tBackgroundPage->Init (SeenBuff.Get_Width(), SeenBuff.Get_Height(), NULL , 0 , (GBC_Enum)(GBC_VIDEOMEM));\n#else\t//WIN32\n\tBackgroundPage = new GraphicBufferClass (SeenBuff.Get_Width(), SeenBuff.Get_Height(), (void*)NULL );\n#endif\t//WIN32\n\n\tSeenBuff.Blit(*BackgroundPage);\n\n\t/*\n\t** Go away nasty keyboard.\n\t*/\n\tKeyboard->Clear();\n\n\tSet_Logic_Page(HidPage);\n\n\t/*\n\t** Start any old song.\n\t*/\n\tfixed oldvolume = Options.ScoreVolume;\n\tif (oldvolume == 0) {\n\t\tOptions.Set_Score_Volume(fixed(4, 10), false);\n\t}\n\tTheme.Queue_Song(THEME_CREDITS);\n\n\t/*\n\t** Init misc timing variables.\n\t*/\n\tint time  = TickCount;\n\tint frame = 0;\n\tint picture_frame = 0;\n\tint slide_number = 0;\n\n\tHide_Mouse();\n\n\t/*\n\t** Save the priority of this process so we can change it back later\n\t*/\n\t//DWORD process_priority = GetPriorityClass(GetCurrentProcess());\n\n\t/*\n\t** Main scrolling loop.\n\t** Keeps going until all the EgoClass objects are deleted or esc is pressed.\n\t*/\n\twhile ( EgoList.Count() ){\n\n\t\tframe++;\n\n\t\t/*\n\t\t** Once we have been running for a few frames, and Windows has time to do its virtual\n\t\t** memory stuff, increase our priority level.\n\t\t*/\n\t\t//if (frame == 30){\n\t\t//\tSetPriorityClass (GetCurrentProcess() , HIGH_PRIORITY_CLASS);\n\t\t//}\n\n\t\t/*\n\t\t** Update the slideshow frame and switch to the next picture if its time.\n\t\t*/\n\t\tpicture_frame++;\n\n\t\tif (picture_frame > FRAME_DELAY+50){\n\t\t\tif (slide_number <NUM_SLIDES-1){\n\t\t\t\tslide_number++;\n\t\t\t\tpicture_frame = 0;\n\t\t\t}else{\n\t\t\t\tslide_number = 0;\n\t\t\t\tpicture_frame = 0;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Do the slideshow background.\n\t\t*/\n\t\tSlide_Show (slide_number, picture_frame);\n\n\n\t\t/*\n\t\t** Scroll the text. If any text goes off the top then delete that object.\n\t\t*/\n#ifndef WIN32\n\t\tscroll_now = !scroll_now;\n\t\tif (scroll_now){\n#endif\t//WIN32\n\t\t\tfor (i=EgoList.Count()-1 ; i>=0 ; i--){\n\t\t\t\tEgoList[i]->Wipe(BackgroundPage);\n\t\t\t\tif ( EgoList[i]->Scroll(1) ){\n\t\t\t\t\tEgoList.Delete(i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n#ifndef WIN32\n\t\t}\n#endif\t//WIN32\n\t\t/*\n\t\t** Render all the text strings in their new positions.\n\t\t*/\n\t\tif (LogicPage->Lock()){\n\t\t\tfor (i=EgoList.Count()-1 ; i>=0 ; i--){\n\t\t\t\tEgoList[i]->Render();\n\t\t\t}\n\t\t\tLogicPage->Unlock();\n\t\t}\n\n\t\tif (frame > 1000 && !Theme.Still_Playing()){\n\t\t\tTheme.Queue_Song(THEME_CREDITS);\t//NONE);\n\t\t}\n\n\t\t/*\n\t\t** Stop calling Theme.AI after a while so a different song doesnt start playing\n\t\t*/\n\t\tCall_Back();\n//\t\tif (frame <1000 ){\n//\t\t\tTheme.AI();\n//\t\t}else{\n//\t\t\tSound_Callback();\n//\t\t}\n\n\t\t/*\n\t\t** Kill any spare time before blitting the hid page forward.\n\t\t*/\n\t\twhile (TickCount - time < frame *speed && !Keyboard->Check()) {}\n\n\t\t/*\n\t\t** Blit all but the top and bottom of the hid page. This is beacuse the text print doesn't\n\t\t** clip vertically and looks ugly when it suddenly appears and disappears.\n\t\t*/\n#ifndef WIN32\n\t\tWait_Vert_Blank(VertBlank);\n\t\t//Vsync();\n#endif\t//WIN32\n\t\tHidPage.Blit(SeenBuff, 0, 8*RESFACTOR, 0, 8*RESFACTOR, SeenBuff.Get_Width(), SeenBuff.Get_Height() - 16*RESFACTOR, false);\n\n\t\t/*\n\t\t** Try and prevent Win95 from swapping out pictures we havnt used yet.\n\t\t*/\n#ifdef WIN32\n\t\tif (frame && 3 == 3){\n\t\t\tfor (i=slide_number+1 ; i<NUM_SLIDES ; i++){\n\t\t\t\tif ( !SlideBuffers[i]->Get_IsDirectDraw() ){\n\t\t\t\t\tForce_VM_Page_In ((void*)SlideBuffers[i]->Get_Offset(), SeenBuff.Get_Width() * SeenBuff.Get_Height() );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#endif\t//WIN32\n\n\t\t/*\n\t\t** If user hits escape then break.\n\t\t*/\n\t\tkey = KN_NONE;\n\t\tif (Keyboard->Check()){\n\t\t\tkey = Keyboard->Get();\n\t\t\tif (key == KN_ESC){\n\t\t\t\tbreak;\n\t\t\t}\n#if (0)\n\t\t\tif (key == KN_Z){\n\t\t\t\tspeed--;\n\t\t\t\tif (speed <1 ) speed=1;\n\t\t\t\ttime = TickCount;\n\t\t\t\tframe = 0;\n\t\t\t}\n\t\t\tif (key == KN_X){\n\t\t\t\tspeed++;\n\t\t\t\ttime = TickCount;\n\t\t\t\tframe = 0;\n\t\t\t}\n#endif\t//(0)\n\n\t\t}\n\n\t}\n\n\tif (key == KN_ESC){\n\t\tTheme.Fade_Out();\n\t\tBlackPalette.Set(TIMER_SECOND*2, Call_Back);\n\t}else{\n\t\t/*\n\t\t** Wait for the picture to fade down\n\t\t*/\n\t\twhile (picture_frame <= FADE_DELAY+FRAME_DELAY){\n\t\t\tif (picture_frame < FRAME_DELAY && picture_frame > 10+FADE_DELAY){\n\t\t\t\tpicture_frame = FRAME_DELAY;\n\t\t\t}\n\t\t\tframe++;\n\t\t\tpicture_frame++;\n\n\t\t\tSlide_Show (slide_number, picture_frame);\n\n\t\t\tCall_Back();\n//\t\t\tSound_Callback();\t\t//Theme.AI();\n\n\t\t\t/*\n\t\t\t** Kill any spare time\n\t\t\t*/\n\t\t\twhile (TickCount - time < frame *speed && !Keyboard->Check()) {}\n\n\t\t}\n\t}\n\n\t/*\n\t** Tidy up.\n\t*/\n\t//SetPriorityClass (GetCurrentProcess() , process_priority);\n\tSeenBuff.Clear();\n\n\tShow_Mouse();\n\n\tGadgetClass::Set_Color_Scheme(&ColorRemaps[PCOLOR_DIALOG_BLUE]);\n\n\tTheme.Stop();\n\tOptions.Set_Score_Volume(oldvolume, false);\n\n\tfor (index = 0 ; index < NUM_SLIDES ; index++){\n\t\tdelete SlideBuffers[index];\n\t}\n\n\tdelete BackgroundPage;\n\n\tdelete [] credits;\n\n\tEgoList.Clear();\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "CODE/EGOS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/*************************************************************************************\n **   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                  **\n *************************************************************************************\n *                                                                                   *\n *                 Project Name : Command & Conquer - Red Alert                      *\n *                                                                                   *\n *                    File Name : EGOS.H                                             *\n *                                                                                   *\n *                   Programmer : Steve Tall                                         *\n *                                                                                   *\n *                   Start Date : September 4th, 1996                                *\n *                                                                                   *\n *                  Last Update : September 4th, 1996 [ST]                           *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Overview:                                                                         *\n *                                                                                   *\n *   Scrolling movie style credits.                                                  *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Functions:                                                             \t \t\t\t*\n *                                                                         \t\t\t\t*\n *                                                                         \t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nclass EgoClass {\n\n\tpublic:\n\n\t\tEgoClass (int x, int y, char *text, TextPrintType flags);\n\t\t~EgoClass ();\n\n\t\tbool Scroll (int distance);\n\t\tvoid Render (void);\n\t\tvoid Wipe (GraphicBufferClass *background);\n\n\n\t\tchar\t\t\t\t*Text;\n\t\tint\t\t\t\tXPos;\n\t\tint\t\t\t\tYPos;\n\t\tTextPrintType \tFlags;\n};\n\n\n"
  },
  {
    "path": "CODE/ENDING.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/ENDING.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ENDING.H                                                     *\n *                                                                                             *\n *                   Programmer : Barry W. Green                                               *\n *                                                                                             *\n *                   Start Date : July 10, 1995                                                *\n *                                                                                             *\n *                  Last Update : July 10, 1995 [BWG]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\nvoid GDI_Ending(void)\n{\n#ifdef NEVER\n\tif (TempleIoned) {\n\t\tPlay_Movie(\"GDIFINB\");\n\t} else {\n\t\tPlay_Movie(\"GDIFINA\");\n\t}\n\n\tScore.Presentation();\n\n\tif (TempleIoned) {\n\t\tPlay_Movie(\"GDIEND2\");\n\t} else {\n\t\tPlay_Movie(\"GDIEND1\");\n\t}\n\tPlay_Movie(\"CC2TEASE\");\n#endif\n}\n\n\n/***********************************************************************************************\n * Nod_Ending -- play ending movies for Nod players                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   7/10/1995 BWG : Created.                                                                  *\n *=============================================================================================*/\nvoid Nod_Ending(void)\n{\n#ifdef NEVER\n\tstatic char const _tanpal[]={0x0,0x0,0xED,0x0,0x2C,0x0,0xFB,0x0,0xFD,0x0,0x0,0x0,0x0,0x0,0x52,0x0};\n\n\tchar fname[12];\n\tchar * satpic = new char[64000];\n\tint oldfontxspacing = FontXSpacing;\n\tvoid const * oldfont;\n\n\tScore.Presentation();\n\n\toldfont = Set_Font(ScoreFontPtr);\n\n\tvoid * localpal = Load_Alloc_Data(CCFileClass(\"SATSEL.PAL\"));\n\tLoad_Uncompress(CCFileClass(\"SATSEL.CPS\"), HidPage, HidPage);\n\tmemcpy(satpic, HidPage.Get_Buffer(), 64000);\n\n\tvoid * kanefinl = Load_Sample(\"KANEFINL.AUD\");\n\tvoid * loopie6m = Load_Sample(\"LOOPIE6M.AUD\");\n\n\tPlay_Movie(\"NODFINAL\", THEME_NONE, false);\n\n\tHide_Mouse();\n\tWait_Vert_Blank(VertBlank);\n\tSet_Palette(localpal);\n\tmemcpy(SeenBuff.Get_Buffer(), satpic, 64000);\n\tShow_Mouse();\n\n\tKeyboard->Clear();\n\tPlay_Sample(kanefinl, 255, 128);\n\tPlay_Sample(loopie6m, 255, 128);\n\n\tbool mouseshown = false;\n\tbool done = false;\n\tint selection = 1;\n\tbool printedtext = false;\n\twhile (!done) {\n\t\tif (!printedtext && !Is_Sample_Playing(kanefinl)) {\n\t\t\tprintedtext++;\n\t\t\tAlloc_Object(new ScorePrintClass(Text_String(TXT_SEL_TARGET), 0, 180, _tanpal));\n\t\t\tmouseshown = true;\n\t\t\tShow_Mouse();\n\t\t}\n\t\tCall_Back_Delay(1);\n\t\tif (!Keyboard->Check()) {\n\t\t\tif (!Is_Sample_Playing(loopie6m))\tPlay_Sample(loopie6m, 255, 128);\n\t\t} else {\n\t\t\tif (Is_Sample_Playing(kanefinl)) {\n\t\t\t\tClear_KeyBuffer();\n\t\t\t} else {\n\t\t\t\tint key = Keyboard->Get();\n\t\t\t\tif ((key & 0xFF) == KN_LMOUSE && !(key & KN_RLSE_BIT)) {\n\t\t\t\t\tint mousex = MouseQX;\n\t\t\t\t\tint mousey = MouseQY;\n\t\t\t\t\tif (mousey >= 22 && mousey <= 177) {\n\t\t\t\t\t\tdone++;\n\t\t\t\t\t\tif (mousex <  160 && mousey <  100) selection = 2;\n\t\t\t\t\t\tif (mousex <  160 && mousey >= 100) selection = 3;\n\t\t\t\t\t\tif (mousex >= 160 && mousey >= 100) selection = 4;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (mouseshown) Hide_Mouse();\n\tdelete satpic;\n\n/* get rid of all the animating objects */\n\tfor (int i = 0; i < MAXSCOREOBJS; i++) if (ScoreObjs[i]) {\n\t\tdelete ScoreObjs[i];\n\t\tScoreObjs[i] = 0;\n\t}\n\t// erase the \"choose a target\" text\n\tSeenBuff.Fill_Rect(0, 180, 319, 199, 0);\n\n\tHide_Mouse();\n\tKeyboard->Clear();\n\n\tSet_Font(oldfont);\n\tFontXSpacing = oldfontxspacing;\n\tFree_Sample(kanefinl);\n\tFree_Sample(loopie6m);\n\n\tsprintf(fname, \"NODEND%d\", selection);\n\tPreserveVQAScreen = 1;\n\tPlay_Movie(fname);\n\n\tPlay_Movie(\"CC2TEASE\");\n#endif\n}\n"
  },
  {
    "path": "CODE/ENDING.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/ENDING.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ENDING.H                                                     *\n *                                                                                             *\n *                   Programmer : Barry W. Green                                               *\n *                                                                                             *\n *                   Start Date : July 10, 1995                                                *\n *                                                                                             *\n *                  Last Update : July 10, 1995 [BWG]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef ENDING_H\n#define ENDING_H\n\nvoid Nod_Ending(void);\n\n#endif\n"
  },
  {
    "path": "CODE/ENG/CONQUER.BAK",
    "content": "# TXT_NONE\n%3d.%02d\n# TXT_CREDIT_FORMAT\nTime:%02d:%02d:%02d\n# TXT_TIME_FORMAT_HOURS\nTime:%02d:%02d\n# TXT_TIME_FORMAT_NO_HOURS\nSell\n# TXT_BUTTON_SELL\nSell Structure\n# TXT_SELL\nRepair\n# TXT_BUTTON_REPAIR\nYou:\n# TXT_YOU\nEnemy:\n# TXT_ENEMY\nBuildings Destroyed By\n# TXT_BUILD_DEST\nUnits Destroyed By\n# TXT_UNIT_DEST\nOre Harvested By\n# TXT_TIB_HARV\nScore: %d\n# TXT_SCORE_1\nYes\n# TXT_YES\nNo\n# TXT_NO\nMission Accomplished\n# TXT_SCENARIO_WON\nMission Failed\n# TXT_SCENARIO_LOST\nStart New Game\n# TXT_START_NEW_GAME\nIntro & Sneak Peek\n# TXT_INTRO\nCancel\n# TXT_CANCEL\nRock\n# TXT_ROCK\nCivilian\n# TXT_CIVILIAN\nContainment Team\n# TXT_JP\nOK\n# TXT_OK\nTree\n# TXT_TREE\n\\x011\n# TXT_LEFT\n\\x010\n# TXT_RIGHT\n\\x01E\n# TXT_UP\n\\x01F\n# TXT_DOWN\nClear\n# TXT_CLEAR\nWater\n# TXT_WATER\nRoad\n# TXT_ROAD\nSlope\n# TXT_SLOPE\nPatch\n# TXT_PATCH\nRiver\n# TXT_RIVER\nLoad Mission\n# TXT_LOAD_MISSION\nSave Mission\n# TXT_SAVE_MISSION\nDelete Mission\n# TXT_DELETE_MISSION\nLoad\n# TXT_LOAD_BUTTON\nSave\n# TXT_SAVE_BUTTON\nDelete\n# TXT_DELETE_BUTTON\nGame Controls\n# TXT_GAME_CONTROLS\nSound Controls\n# TXT_SOUND_CONTROLS\nResume Mission\n# TXT_RESUME_MISSION\nVisual Controls\n# TXT_VISUAL_CONTROLS\nAbort Mission\n# TXT_QUIT_MISSION\nExit Game\n# TXT_EXIT_GAME\nOptions\n# TXT_OPTIONS\nSquish mark\n# TXT_SQUISH\nCrater\n# TXT_CRATER\nScorch Mark\n# TXT_SCORCH\nBRIGHTNESS:\n# TXT_BRIGHTNESS\nMusic Volume\n# TXT_MUSIC\nSound Volume\n# TXT_VOLUME\nTint:\n# TXT_TINT\nContrast:\n# TXT_CONTRAST\nGame Speed:\n# TXT_SPEED\nScroll Rate:\n# TXT_SCROLLRATE\nColor:\n# TXT_COLOR\nReturn to game\n# TXT_RETURN_TO_GAME\nEnemy Soldier\n# TXT_ENEMY_SOLDIER\nEnemy Vehicle\n# TXT_ENEMY_VEHICLE\nEnemy Structure\n# TXT_ENEMY_STRUCTURE\nLight Tank\n# TXT_LTANK\nHeavy Tank\n# TXT_MTANK\nMedium Tank\n# TXT_MTANK2\nMammoth Tank\n# TXT_HTANK\nSAM Site\n# TXT_SAM\nRanger\n# TXT_JEEP\nChinook Helicopter\n# TXT_TRANS\nOre Truck\n# TXT_HARVESTER\nArtillery\n# TXT_ARTY\nRifle Infantry\n# TXT_E1\nGrenadier\n# TXT_E2\nRocket Soldier\n# TXT_E3\nFlamethrower\n# TXT_E4\nLongbow Helicopter\n# TXT_HELI\nHind\n# TXT_ORCA\nAPC\n# TXT_APC\nGuard Tower\n# TXT_GUARD_TOWER\nRadar Dome\n# TXT_COMMAND\nHelipad\n# TXT_HELIPAD\nAirfield\n# TXT_AIRSTRIP\nOre Silo\n# TXT_STORAGE\nConstruction Yard\n# TXT_CONST_YARD\nOre Refinery\n# TXT_REFINERY\nChurch\n# TXT_CIV1\nHan's and Gretel's\n# TXT_CIV2\nHewitt's Manor\n# TXT_CIV3\nRicktor's House\n# TXT_CIV4\nGretchin's House\n# TXT_CIV5\nThe Barn\n# TXT_CIV6\nDamon's pub\n# TXT_CIV7\nFran's House\n# TXT_CIV8\nMusic Factory\n# TXT_CIV9\nToymaker's\n# TXT_CIV10\nLudwig's House\n# TXT_CIV11\nHaystacks\n# TXT_CIV12\nHaystack\n# TXT_CIV13\nWheat Field\n# TXT_CIV14\nFallow Field\n# TXT_CIV15\nCorn Field\n# TXT_CIV16\nCelery Field\n# TXT_CIV17\nPotato Field\n# TXT_CIV18\nSala's House\n# TXT_CIV20\nAbdul's House\n# TXT_CIV21\nPablo's Wicked Pub\n# TXT_CIV22\nVillage Well\n# TXT_CIV23\nCamel Trader\n# TXT_CIV24\nChurch\n# TXT_CIV25\nAli's House\n# TXT_CIV26\nTrader Ted's\n# TXT_CIV27\nMenelik's House\n# TXT_CIV28\nPrestor John's House\n# TXT_CIV29\nVillage Well\n# TXT_CIV30\nWitch Doctor's Hut\n# TXT_CIV31\nRikitikitembo's Hut\n# TXT_CIV32\nRoarke's Hut\n# TXT_CIV33\nMubasa's Hut\n# TXT_CIV34\nAksum's Hut\n# TXT_CIV35\nMambo's Hut\n# TXT_CIV36\nThe Studio\n# TXT_CIV37\nTechnology Center\n# TXT_CIVMISS\nTurret\n# TXT_TURRET\nGunboat\n# TXT_GUNBOAT\nMobile Construction Vehicle\n# TXT_MCV\nPower Plant\n# TXT_POWER\nAdvanced Power Plant\n# TXT_ADVANCED_POWER\nHospital\n# TXT_HOSPITAL\nBarracks\n# TXT_BARRACKS\nOil Pump\n# TXT_PUMP\nOil Tanker\n# TXT_TANKER\nSandbags\n# TXT_SANDBAG_WALL\nChain Link Fence\n# TXT_CYCLONE_WALL\nConcrete Wall\n# TXT_BRICK_WALL\nBarbwire Fence\n# TXT_BARBWIRE_WALL\nWood Fence\n# TXT_WOOD_WALL\nWar Factory\n# TXT_WEAPON_FACTORY\nAdvanced Guard Tower\n# TXT_AGUARD_TOWER\nBio-Research Laboratory\n# TXT_BIO_LAB\nService Depot\n# TXT_FIX_IT\nSidebar\n# TXT_TAB_SIDEBAR\nOptions\n# TXT_TAB_BUTTON_CONTROLS\nDatabase\n# TXT_TAB_BUTTON_DATABASE\nUnrevealed Terrain\n# TXT_SHADOW\nOptions Menu\n# TXT_OPTIONS_MENU\nStop\n# TXT_STOP\nPlay\n# TXT_PLAY\nShuffle\n# TXT_SHUFFLE\nRepeat\n# TXT_REPEAT\nMusic volume:\n# TXT_MUSIC_VOLUME\nSound volume:\n# TXT_SOUND_VOLUME\nOn\n# TXT_ON\nOff\n# TXT_OFF\nMultiplayer Game\n# TXT_MULTIPLAYER_GAME\nNo files available\n# TXT_NO_FILES\nDo you want to delete this file?\n# TXT_DELETE_SINGLE_FILE\nDo you want to delete %d files?\n# TXT_DELETE_MULTIPLE_FILES\nReset Values\n# TXT_RESET_MENU\nDo you want to abort the mission?\n# TXT_CONFIRM_EXIT\nMission Description\n# TXT_MISSION_DESCRIPTION\nJoe\n# TXT_C1\nBarry\n# TXT_C2\nShelly\n# TXT_C3\nMaria\n# TXT_C4\nKaren\n# TXT_C5\nSteve\n# TXT_C6\nPhil\n# TXT_C7\nDwight\n# TXT_C8\nErik\n# TXT_C9\nProf. Einstein\n# TXT_EINSTEIN\nRoad Bib\n# TXT_BIB\nFaster\n# TXT_FASTER\nSlower\n# TXT_SLOWER\nAir Strike\n# TXT_AIR_STRIKE\nSteel Crate\n# TXT_STEEL_CRATE\nWood Crate\n# TXT_WOOD_CRATE\nWater Crate\n# TXT_WATER_CRATE\nFlag Location\n# TXT_FLAG_SPOT\nUnable to read scenario!\n# TXT_UNABLE_READ_SCENARIO\nError loading game!\n# TXT_ERROR_LOADING_GAME\nObsolete saved game.\n# TXT_OBSOLETE_SAVEGAME\nYou must enter a description!\n# TXT_MUSTENTER_DESCRIPTION\nError saving game!\n# TXT_ERROR_SAVING_GAME\nDelete this file?\n# TXT_DELETE_FILE_QUERY\n[EMPTY SLOT]\n# TXT_EMPTY_SLOT\nSelect Multiplayer Game\n# TXT_SELECT_MPLAYER_GAME\nModem/Serial\n# TXT_MODEM_SERIAL\nNetwork\n# TXT_NETWORK\nUnable to initialize network!\n# TXT_INIT_NET_ERROR\nJoin Network Game\n# TXT_JOIN_NETWORK_GAME\nNew\n# TXT_NEW\nJoin\n# TXT_JOIN\nSend Message\n# TXT_SEND_MESSAGE\nYour Name:\n# TXT_YOUR_NAME\nYour Side:\n# TXT_SIDE_COLON\nYour Color:\n# TXT_COLOR_COLON\nGames\n# TXT_GAMES\nPlayers\n# TXT_PLAYERS\nScenario:\n# TXT_SCENARIO_COLON\n>> NOT FOUND <<\n# TXT_NOT_FOUND\nStarting Credits:\n# TXT_START_CREDITS_COLON\nBases:\n# TXT_BASES_COLON\nOre:\n# TXT_TIBERIUM_COLON\nCrates:\n# TXT_CRATES_COLON\nAI Players:\n# TXT_AI_PLAYERS_COLON\nRequest denied.\n# TXT_REQUEST_DENIED\nUnable to play; scenario not found.\n# TXT_UNABLE_PLAY_WAAUGH\nNothing to join!\n# TXT_NOTHING_TO_JOIN\nYou must enter a name!\n# TXT_NAME_ERROR\nDuplicate names are not allowed.\n# TXT_DUPENAMES_NOTALLOWED\nYour game version is outdated.\n# TXT_YOURGAME_OUTDATED\nDestination game version is outdated.\n# TXT_DESTGAME_OUTDATED\n%s's Game\n# TXT_THATGUYS_GAME\n[%s's Game]\n# TXT_THATGUYS_GAME_BRACKET\nNetwork Game Setup\n# TXT_NETGAME_SETUP\nReject\n# TXT_REJECT\nYou can't reject yourself!\n# TXT_CANT_REJECT_SELF\nYou must select a player to reject.\n# TXT_SELECT_PLAYER_REJECT\nBases\n# TXT_BASES\nCrates\n# TXT_CRATES\nAI Players\n# TXT_AI_PLAYERS\nScenarios\n# TXT_SCENARIOS\nCredits:\n# TXT_CREDITS_COLON\nOnly one player?\n# TXT_ONLY_ONE\nOops!\n# TXT_OOPS\nTo %s:\n# TXT_TO\nTo All:\n# TXT_TO_ALL\nMessage:\n# TXT_MESSAGE\nConnection to %s lost!\n# TXT_CONNECTION_LOST\n%s has left the game.\n# TXT_LEFT_GAME\n%s has been defeated!\n# TXT_PLAYER_DEFEATED\nWaiting to Connect...\n# TXT_WAITING_CONNECT\nConnection error! Check your cables. Attempting to Reconnect...\n# TXT_NULL_CONNERR_CHECK_CABLES\nConnection error! Redialing...\n# TXT_MODEM_CONNERR_REDIALING\nConnection error! Waiting for Call...\n# TXT_MODEM_CONNERR_WAITING\nSelect Serial Game\n# TXT_SELECT_SERIAL_GAME\nDial Modem\n# TXT_DIAL_MODEM\nAnswer Modem\n# TXT_ANSWER_MODEM\nNull Modem\n# TXT_NULL_MODEM\nSettings\n# TXT_SETTINGS\nPort:\n# TXT_PORT_COLON\nIRQ:\n# TXT_IRQ_COLON\nBaud:\n# TXT_BAUD_COLON\nInit String:\n# TXT_INIT_STRING\nCall Waiting String:\n# TXT_CWAIT_STRING\nTone Dialing\n# TXT_TONE_BUTTON\nPulse Dialing\n# TXT_PULSE_BUTTON\nHost Serial Game\n# TXT_HOST_SERIAL_GAME\nOpponent:\n# TXT_OPPONENT_COLON\nUser signed off!\n# TXT_USER_SIGNED_OFF\nJoin Serial Game\n# TXT_JOIN_SERIAL_GAME\nPhone List\n# TXT_PHONE_LIST\nAdd\n# TXT_ADD\nEdit\n# TXT_EDIT\nDial\n# TXT_DIAL\nDefault\n# TXT_DEFAULT\nDefault Settings\n# TXT_DEFAULT_SETTINGS\nCustom Settings\n# TXT_CUSTOM_SETTINGS\nPhone Listing\n# TXT_PHONE_LISTING\nName:\n# TXT_NAME_COLON\nNumber:\n# TXT_NUMBER_COLON\nUnable to find modem. Check power and cables.\n# TXT_UNABLE_FIND_MODEM\nNo carrier.\n# TXT_NO_CARRIER\nLine busy.\n# TXT_LINE_BUSY\nNumber invalid.\n# TXT_NUMBER_INVALID\nOther system not responding!\n# TXT_SYSTEM_NOT_RESPONDING\nGames are out of sync!\n# TXT_OUT_OF_SYNC\nPacket received too late!\n# TXT_PACKET_TOO_LATE\nOther player has left the game.\n# TXT_PLAYER_LEFT_GAME\nFrom %s:%s\n# TXT_FROM\nTIME:\n# TXT_SCORE_TIME\nLEADERSHIP:\n# TXT_SCORE_LEAD\nECONOMY:\n# TXT_SCORE_EFFI\nTOTAL SCORE:\n# TXT_SCORE_TOTA\nCASUALTIES:\n# TXT_SCORE_CASU\nNEUTRAL:\n# TXT_SCORE_NEUT\nBUILDINGS LOST\n# TXT_SCORE_BUIL\nBUILDINGS\n# TXT_SCORE_BUIL1\nLOST:\n# TXT_SCORE_BUIL2\nTOP SCORES\n# TXT_SCORE_TOP\nENDING CREDITS:\n# TXT_SCORE_ENDCRED\n%dh %dm\n# TXT_SCORE_TIMEFORMAT1\n%dm\n# TXT_SCORE_TIMEFORMAT2\nDialing...\n# TXT_DIALING\nDialing Canceled\n# TXT_DIALING_CANCELED\nWaiting for Call...\n# TXT_WAITING_FOR_CALL\nAnswering Canceled\n# TXT_ANSWERING_CANCELED\nEngineer\n# TXT_E6\nSpy\n# TXT_E8\nNot a Null Modem Cable Attached! It is a modem or loopback cable.\n# TXT_MODEM_OR_LOOPBACK\nMap\n# TXT_MAP\nBlossom Tree\n# TXT_BLOSSOM_TREE\nBriefing\n# TXT_RESTATE_MISSION\nComputer\n# TXT_COMPUTER\nUnit Count:\n# TXT_COUNT\nTech Level:\n# TXT_LEVEL\nOpponent\n# TXT_OPPONENT\nKills:\n# TXT_KILLS_COLON\nVideo\n# TXT_VIDEO\nScientist\n# TXT_C10\nCapture The Flag\n# TXT_CAPTURE_THE_FLAG\nMission Objective\n# TXT_OBJECTIVE\nMission\n# TXT_MISSION\nNo saved games available.\n# TXT_NO_SAVES\nCivilian Building\n# TXT_CIVILIAN_BUILDING\nTechnician\n# TXT_TECHNICIAN\nSave game options are not allowed during a multiplayer session.\n# TXT_NO_SAVELOAD\nSpecial 1\n# TXT_DELPHI\nWould you like to replay this mission?\n# TXT_TO_REPLAY\nReconnecting to %s.\n# TXT_RECONN_TO\nPlease wait %02d seconds.\n# TXT_PLEASE_WAIT\nDo you wish to surrender?\n# TXT_SURRENDER\nSELECT TRANSMISSION\n# TXT_SEL_TRANS\nYour game name must be unique.\n# TXT_GAMENAME_MUSTBE_UNIQUE\nGame is closed.\n# TXT_GAME_IS_CLOSED\nYour name must be unique.\n# TXT_NAME_MUSTBE_UNIQUE\nReconnecting to %s\n# TXT_RECONNECTING_TO\nWaiting for connections...\n# TXT_WAITING_FOR_CONNECTIONS\nTime allowed: %02d seconds\n# TXT_TIME_ALLOWED\nPress ESC to cancel.\n# TXT_PRESS_ESC\nFrom Computer: It's just you and me now!\n# TXT_JUST_YOU_AND_ME\nCapture the Flag:\n# TXT_CAPTURE_THE_FLAG_COLON\nSpecial 2\n# TXT_CHAN\n%s has allied with %s\n# TXT_HAS_ALLIED\n%s declares war on %s\n# TXT_AT_WAR\nSelect a target\n# TXT_SEL_TARGET\nResign Game\n# TXT_RESIGN\nOre grows quickly.\n# TXT_TIBERIUM_FAST\nAnswering...\n# TXT_ANSWERING\nInitializing Modem...\n# TXT_INITIALIZING_MODEM\nScenarios don't match.\n# TXT_SCENARIOS_DO_NOT_MATCH\nPower Output\n# TXT_POWER_OUTPUT\nPower Output (low)\n# TXT_POWER_OUTPUT_LOW\nContinue\n# TXT_CONTINUE\nData Queue Overflow\n# TXT_QUEUE_FULL\n%s changed game options!\n# TXT_SPECIAL_WARNING\nPlease insert a Red Alert CD into the CD-ROM drive.\n# TXT_CD_DIALOG_1\nPlease insert CD %d (%s) into the CD-ROM drive.\n# TXT_CD_DIALOG_2\nRed Alert is unable to detect your CD ROM drive.\n# TXT_CD_ERROR1\nNo Sound Card Detected\n# TXT_NO_SOUND_CARD\nUNKNOWN\n# TXT_UNKNOWN\n(old)\n# TXT_OLD_GAME\nInsufficient Disk Space to run Red Alert.\n# TXT_NO_SPACE\nYou must have %d megabytes of free disk space.\n# TXT_MUST_HAVE_SPACE\nRun SETUP program first.\n# TXT_RUN_SETUP\nWaiting for Opponent\n# TXT_WAITING_FOR_OPPONENT\nPlease select 'Settings' to setup default configuration\n# TXT_SELECT_SETTINGS\nPrison\n# TXT_PRISON\nMission Saved\n# TXT_GAME_WAS_SAVED\nInsufficient disk space to save a game.  Please delete a previous save to free up some disk space and try again.\n# TXT_SPACE_CANT_SAVE\nInvalid Port/Address. COM 1-4 OR ADDRESS\n# TXT_INVALID_PORT_ADDRESS\nInvalid Port and/or IRQ settings\n# TXT_INVALID_SETTINGS\nIRQ already in use\n# TXT_IRQ_ALREADY_IN_USE\nAbort\n# TXT_ABORT\nRestart\n# TXT_RESTART\nMission is restarting. Please wait...\n# TXT_RESTARTING\nMission is loading. Please wait...\n# TXT_LOADING\nError in the InitString\n# TXT_ERROR_IN_INITSTRING\nShroud:\n# TXT_SHADOW_COLON\nAnti-Vehicle Mine\n# TXT_AVMINE\nAnti-Personnel Mine\n# TXT_APMINE\nNew Missions\n# TXT_NEW_MISSIONS\nThief\n# TXT_THIEF\nRadar Jammer\n# TXT_MRJ\nGap Generator\n# TXT_GAP_GENERATOR\nPillbox\n# TXT_PILLBOX\nCamo. Pillbox\n# TXT_CAMOPILLBOX\nChronosphere\n# TXT_CHRONOSPHERE\nEngland\n# TXT_ENGLAND\nGermany\n# TXT_GERMANY\nSpain\n# TXT_SPAIN\nRussia\n# TXT_USSR\nUkraine\n# TXT_UKRAINE\nGreece\n# TXT_GREECE\nFrance\n# TXT_FRANCE\nTurkey\n# TXT_TURKEY\nShore\n# TXT_SHORE\nSelect Object\n# TXT_PLACE_OBJECT\nSubmarine\n# TXT_SS\nDestroyer\n# TXT_DD\nCruiser\n# TXT_CA\nTransport\n# TXT_TRANSPORT\nGun Boat\n# TXT_PT\nLobby\n# TXT_LOBBY\nGames\n# TXT_CHANNEL_GAMES\nSave Game...\n# TXT_SAVING_GAME\nGame is full.\n# TXT_GAME_FULL\nYou must select a game!\n# TXT_MUST_SELECT_GAME\n%s playing %s\n# TXT_S_PLAYING_S\nOnly the host can modify this option.\n# TXT_ONLY_HOST_CAN_MODIFY\nGame was cancelled.\n# TXT_GAME_CANCELLED\n%s has formed a new game.\n# TXT_S_FORMED_NEW_GAME\n%s's game is now in progress.\n# TXT_GAME_NOW_IN_PROGRESS\nTesla Coil\n# TXT_TESLA\nMobile Gap Generator\n# TXT_MGG\nFlame Tower\n# TXT_FLAME_TURRET\nAA Gun\n# TXT_AAGUN\nKennel\n# TXT_KENNEL\nSoviet Tech Center\n# TXT_SOVIET_TECH\nBadger Bomber\n# TXT_BADGER\nMig Attack Plane\n# TXT_MIG\nYak Attack Plane\n# TXT_YAK\nBarbed Wire\n# TXT_FENCE\nField Medic\n# TXT_MEDIC\nSaboteur\n# TXT_SABOTEUR\nGeneral\n# TXT_GENERAL\nTanya\n# TXT_E7\nParabombs\n# TXT_PARA_BOMB\nParatroopers\n# TXT_PARA_INFANTRY\nParachute Saboteur\n# TXT_PARA_SABOTEUR\nNaval Yard\n# TXT_SHIP_YARD\nSub Pen\n# TXT_SUB_PEN\nScenario Options\n# TXT_SCENARIO_OPTIONS\nSpy Plane\n# TXT_SPY_MISSION\nSpy Plane\n# TXT_U2\nAttack Dog\n# TXT_GUARD_DOG\nSpy Info\n# TXT_SPY_INFO\nBuildings\n# TXT_BUILDNGS\nUnits\n# TXT_UNITS\nInfantry\n# TXT_INFANTRY\nAircraft\n# TXT_AIRCRAFT\nSupply Truck\n# TXT_TRUCK\nInvulnerability Device\n# TXT_INVUL\nIron Curtain\n# TXT_IRON_CURTAIN\nAllied Tech Center\n# TXT_ADVANCED_TECH\nV2 Rocket\n# TXT_V2_LAUNCHER\nForward Command Post\n# TXT_FORWARD_COM\nDemolitioner\n# TXT_DEMOLITIONER\nMine Layer\n# TXT_MINE_LAYER\nFake Construction Yard\n# TXT_FAKE_CONST\nFake War Factory\n# TXT_FAKE_WEAP\nFake Naval Yard\n# TXT_FAKE_YARD\nFake Sub Pen\n# TXT_FAKE_PEN\nFake Radar Dome\n# TXT_FAKE_RADAR\nBigfoot\n# TXT_THEME_BIGF\nCrush\n# TXT_THEME_CRUS\nFace the Enemy 1\n# TXT_THEME_FAC1\nFace the Enemy 2\n# TXT_THEME_FAC2\nHell March\n# TXT_THEME_HELL\nRun for Your Life\n# TXT_THEME_RUN1\nSmash\n# TXT_THEME_SMSH\nTrenches\n# TXT_THEME_TREN\nWorkmen\n# TXT_THEME_WORK\nAwait\n# TXT_THEME_AWAIT\nDense\n# TXT_THEME_DENSE_R\nMap Selection\n# TXT_THEME_MAP\nFogger\n# TXT_THEME_FOGGER1A\nMud\n# TXT_THEME_MUD1A\nRadio 2\n# TXT_THEME_RADIO2\nRoll Out\n# TXT_THEME_ROLLOUT\nSnake\n# TXT_THEME_SNAKE\nTerminate\n# TXT_THEME_TERMINAT\nTwin\n# TXT_THEME_TWIN\nVector\n# TXT_THEME_VECTOR1A\nTeam Members\n# TXT_TEAM_MEMBERS\nBridge\n# TXT_BRIDGE\nBarrel\n# TXT_BARREL\nFriendly\n# TXT_GOODGUY\nEnemy\n# TXT_BADGUY\nGold\n# TXT_GOLD\nGems\n# TXT_GEMS\nTitle Movie\n# TXT_TEASER\nMovies\n# TXT_MOVIES\nInterior\n# TXT_INTERIOR\nSonar Pulse\n# TXT_SONAR_PULSE\nMissile Silo\n# TXT_MSLO\nGPS Satellite\n# TXT_GPS_SATELLITE\nAtom Bomb\n# TXT_NUCLEAR_BOMB\nEasy\n# TXT_EASY\nHard\n# TXT_HARD\nNormal\n# TXT_NORMAL\nPlease set the difficulty level. It will be used throughout this campaign.\n# TXT_DIFFICULTY\nAllies\n# TXT_ALLIES\nSoviet\n# TXT_SOVIET\nIntro Theme\n# TXT_THEME_INTRO\nShroud Regrows\n# TXT_SHADOW_REGROWS\nOre Regenerates\n# TXT_ORE_SPREADS\nScore Theme\n# TXT_THEME_SCORE\nInternet Game\n# TXT_INTERNET\nIce\n# TXT_ICE\nCrates\n# TXT_CRATE\nSkirmish\n# TXT_SKIRMISH\nChoose your side.\n# TXT_CHOOSE\nValuable Minerals\n# TXT_MINERALS\nIgnore\n# TXT_IGNORE\nError - modem is not responding.\n# TXT_ERROR_NO_RESP\nError - modem did not respond to result code enable command.\n# TXT_ERROR_NO_RESCODE\nError - modem did not respond to initialisation string.\n# TXT_ERROR_NO_INIT\nError - modem did not respond to 'verbose' command.\n# TXT_ERROR_NO_VERB\nError - modem did not respond to 'echo' command.\n# TXT_ERROR_NO_ECHO\nError - unable to disable modem auto answer.\n# TXT_ERROR_NO_DISABLE\nError - Too many errors initialising modem - Aborting.\n# TXT_ERROR_TOO_MANY\nError - Modem returned error status.\n# TXT_ERROR_ERROR\nError - TIme out waiting for connect.\n# TXT_ERROR_TIMEOUT\nAccomplished\n# TXT_ACCOMPLISHED\nClick to Continue\n# TXT_CLICK_CONTINUE\nReceiving scenario from host.\n# TXT_RECEIVING_SCENARIO\nSending scenario to remote players.\n# TXT_SENDING_SCENARIO\nError - Modem failed to respond to flow control command. Your Windows configuration may be incorrect.\n# TXT_NO_FLOW_CONTROL_RESPONSE\nError - Modem failed to respond to compression command. Your Windows configuration may be incorrect.\n# TXT_NO_COMPRESSION_RESPONSE\nError - Modem failed to respond to error correction command. Your Windows configuration may be incorrect.\n# TXT_NO_ERROR_CORRECTION_RESPONSE\nTo play Red Alert via the internet you must be connected to an internet services provider and be registered with Planet Westwood\n# TXT_EXPLAIN_REGISTRATION\nWchat not installed. Please install it from either CD.\n# TXT_ERROR_UNABLE_TO_RUN_WCHAT\nRegister\n# TXT_REGISTER\nOre Mine\n# TXT_ORE_MINE\nNo registered modem\n# TXT_NO_REGISTERED_MODEM\nChronoshift\n# TXT_CHRONOSHIFT\nInvalid Port or Port is in use\n# TXT_UNABLE_TO_OPEN_PORT\nNo dial tone. Ensure your modem is connected to the phone line and try again.\n# TXT_NO_DIAL_TONE\nError - other player does not have this expansion scenario.\n# TXT_NO_EXPANSION_SCENARIO\nPlease Stand By...\n# TXT_STAND_BY\nEnd Credits Theme\n# TXT_THEME_CREDITS\nLow Power: AA-Guns offline\n# TXT_POWER_AAGUN\nLow Power: Tesla Coils offline\n# TXT_POWER_TESLA\nLow Power\n# TXT_LOW_POWER\nCommander:\n# TXT_COMMANDER\nBattles Won:\n# TXT_BATTLES_WON\nGame versions incompatable. To make sure you have the latest version, visit www.westwood.com\n# TXT_MISMATCH\nIncompatable scenario file detected. The scenario may be corrupt.\n# TXT_SCENARIO_ERROR\nConnecting...\n# TXT_CONNECTING\nModem Initialization\n# TXT_MODEM_INITIALISATION\nData Compression\n# TXT_DATA_COMPRESSION\nError Correction\n# TXT_ERROR_CORRECTION\nHardware Flow Control\n# TXT_HARDWARE_FLOW_CONTROL\nAdvanced\n# TXT_ADVANCED\n2nd_Hand\n# TXT_THEME_2ND_HAND\nArazoid\n#TXT_THEME_ARAZOID\nBackStab\n#TXT_THEME_BACKSTAB\nChaos2\n#TXT_THEME_CHAOS2\nShut_It\n#TXT_THEME_SHUT_IT\nTwinMix1\n#TXT_THEME_TWINMIX1\nUnder3\n#TXT_THEME_UNDER3\nVR2\n#TXT_THEME_VR2\nThe other system is not repsonding. Do you wish to attempt an emergency game save? Both players must save for this to work.\n# TXT_ASK_EMERGENCY_SAVE_NOT_RESPONDING\nThe other system hung up. Do you wish to attempt an emergency game save? Both players must save for this to work. # TXT_ASK_EMERGENCY_SAVE\n# TXT_ASK_EMERGENCY_SAVE_HUNG_UP\n\n\n\n\n"
  },
  {
    "path": "CODE/ENG/CONQUER.TXT",
    "content": "# TXT_NONE\n%3d.%02d\n# TXT_CREDIT_FORMAT\nTime:%02d:%02d:%02d\n# TXT_TIME_FORMAT_HOURS\nTime:%02d:%02d\n# TXT_TIME_FORMAT_NO_HOURS\nSell\n# TXT_BUTTON_SELL\nSell Structure\n# TXT_SELL\nRepair\n# TXT_BUTTON_REPAIR\nYou:\n# TXT_YOU\nEnemy:\n# TXT_ENEMY\nBuildings Destroyed By\n# TXT_BUILD_DEST\nUnits Destroyed By\n# TXT_UNIT_DEST\nOre Harvested By\n# TXT_TIB_HARV\nScore: %d\n# TXT_SCORE_1\nYes\n# TXT_YES\nNo\n# TXT_NO\nMission Accomplished\n# TXT_SCENARIO_WON\nMission Failed\n# TXT_SCENARIO_LOST\nStart New Game\n# TXT_START_NEW_GAME\nIntro & Sneak Peek\n# TXT_INTRO\nCancel\n# TXT_CANCEL\nRock\n# TXT_ROCK\nCivilian\n# TXT_CIVILIAN\nContainment Team\n# TXT_JP\nOK\n# TXT_OK\nTree\n# TXT_TREE\n\\x011\n# TXT_LEFT\n\\x010\n# TXT_RIGHT\n\\x01E\n# TXT_UP\n\\x01F\n# TXT_DOWN\nClear\n# TXT_CLEAR\nWater\n# TXT_WATER\nRoad\n# TXT_ROAD\nSlope\n# TXT_SLOPE\nPatch\n# TXT_PATCH\nRiver\n# TXT_RIVER\nLoad Mission\n# TXT_LOAD_MISSION\nSave Mission\n# TXT_SAVE_MISSION\nDelete Mission\n# TXT_DELETE_MISSION\nLoad\n# TXT_LOAD_BUTTON\nSave\n# TXT_SAVE_BUTTON\nDelete\n# TXT_DELETE_BUTTON\nGame Controls\n# TXT_GAME_CONTROLS\nSound Controls\n# TXT_SOUND_CONTROLS\nResume Mission\n# TXT_RESUME_MISSION\nVisual Controls\n# TXT_VISUAL_CONTROLS\nAbort Mission\n# TXT_QUIT_MISSION\nExit Game\n# TXT_EXIT_GAME\nOptions\n# TXT_OPTIONS\nSquish mark\n# TXT_SQUISH\nCrater\n# TXT_CRATER\nScorch Mark\n# TXT_SCORCH\nBRIGHTNESS:\n# TXT_BRIGHTNESS\nMusic Volume\n# TXT_MUSIC\nSound Volume\n# TXT_VOLUME\nTint:\n# TXT_TINT\nContrast:\n# TXT_CONTRAST\nGame Speed:\n# TXT_SPEED\nScroll Rate:\n# TXT_SCROLLRATE\nColor:\n# TXT_COLOR\nReturn to game\n# TXT_RETURN_TO_GAME\nEnemy Soldier\n# TXT_ENEMY_SOLDIER\nEnemy Vehicle\n# TXT_ENEMY_VEHICLE\nEnemy Structure\n# TXT_ENEMY_STRUCTURE\nLight Tank\n# TXT_LTANK\nHeavy Tank\n# TXT_MTANK\nMedium Tank\n# TXT_MTANK2\nMammoth Tank\n# TXT_HTANK\nSAM Site\n# TXT_SAM\nRanger\n# TXT_JEEP\nChinook Helicopter\n# TXT_TRANS\nOre Truck\n# TXT_HARVESTER\nArtillery\n# TXT_ARTY\nRifle Infantry\n# TXT_E1\nGrenadier\n# TXT_E2\nRocket Soldier\n# TXT_E3\nFlamethrower\n# TXT_E4\nLongbow Helicopter\n# TXT_HELI\nHind\n# TXT_ORCA\nAPC\n# TXT_APC\nGuard Tower\n# TXT_GUARD_TOWER\nRadar Dome\n# TXT_COMMAND\nHelipad\n# TXT_HELIPAD\nAirfield\n# TXT_AIRSTRIP\nOre Silo\n# TXT_STORAGE\nConstruction Yard\n# TXT_CONST_YARD\nOre Refinery\n# TXT_REFINERY\nChurch\n# TXT_CIV1\nHan's and Gretel's\n# TXT_CIV2\nHewitt's Manor\n# TXT_CIV3\nRicktor's House\n# TXT_CIV4\nGretchin's House\n# TXT_CIV5\nThe Barn\n# TXT_CIV6\nDamon's pub\n# TXT_CIV7\nFran's House\n# TXT_CIV8\nMusic Factory\n# TXT_CIV9\nToymaker's\n# TXT_CIV10\nLudwig's House\n# TXT_CIV11\nHaystacks\n# TXT_CIV12\nHaystack\n# TXT_CIV13\nWheat Field\n# TXT_CIV14\nFallow Field\n# TXT_CIV15\nCorn Field\n# TXT_CIV16\nCelery Field\n# TXT_CIV17\nPotato Field\n# TXT_CIV18\nSala's House\n# TXT_CIV20\nAbdul's House\n# TXT_CIV21\nPablo's Wicked Pub\n# TXT_CIV22\nVillage Well\n# TXT_CIV23\nCamel Trader\n# TXT_CIV24\nChurch\n# TXT_CIV25\nAli's House\n# TXT_CIV26\nTrader Ted's\n# TXT_CIV27\nMenelik's House\n# TXT_CIV28\nPrestor John's House\n# TXT_CIV29\nVillage Well\n# TXT_CIV30\nWitch Doctor's Hut\n# TXT_CIV31\nRikitikitembo's Hut\n# TXT_CIV32\nRoarke's Hut\n# TXT_CIV33\nMubasa's Hut\n# TXT_CIV34\nAksum's Hut\n# TXT_CIV35\nMambo's Hut\n# TXT_CIV36\nThe Studio\n# TXT_CIV37\nTechnology Center\n# TXT_CIVMISS\nTurret\n# TXT_TURRET\nGunboat\n# TXT_GUNBOAT\nMobile Construction Vehicle\n# TXT_MCV\nPower Plant\n# TXT_POWER\nAdvanced Power Plant\n# TXT_ADVANCED_POWER\nHospital\n# TXT_HOSPITAL\nBarracks\n# TXT_BARRACKS\nOil Pump\n# TXT_PUMP\nOil Tanker\n# TXT_TANKER\nSandbags\n# TXT_SANDBAG_WALL\nChain Link Fence\n# TXT_CYCLONE_WALL\nConcrete Wall\n# TXT_BRICK_WALL\nBarbwire Fence\n# TXT_BARBWIRE_WALL\nWood Fence\n# TXT_WOOD_WALL\nWar Factory\n# TXT_WEAPON_FACTORY\nAdvanced Guard Tower\n# TXT_AGUARD_TOWER\nBio-Research Laboratory\n# TXT_BIO_LAB\nService Depot\n# TXT_FIX_IT\nSidebar\n# TXT_TAB_SIDEBAR\nOptions\n# TXT_TAB_BUTTON_CONTROLS\nDatabase\n# TXT_TAB_BUTTON_DATABASE\nUnrevealed Terrain\n# TXT_SHADOW\nOptions Menu\n# TXT_OPTIONS_MENU\nStop\n# TXT_STOP\nPlay\n# TXT_PLAY\nShuffle\n# TXT_SHUFFLE\nRepeat\n# TXT_REPEAT\nMusic volume:\n# TXT_MUSIC_VOLUME\nSound volume:\n# TXT_SOUND_VOLUME\nOn\n# TXT_ON\nOff\n# TXT_OFF\nMultiplayer Game\n# TXT_MULTIPLAYER_GAME\nNo files available\n# TXT_NO_FILES\nDo you want to delete this file?\n# TXT_DELETE_SINGLE_FILE\nDo you want to delete %d files?\n# TXT_DELETE_MULTIPLE_FILES\nReset Values\n# TXT_RESET_MENU\nDo you want to abort the mission?\n# TXT_CONFIRM_EXIT\nMission Description\n# TXT_MISSION_DESCRIPTION\nJoe\n# TXT_C1\nBarry\n# TXT_C2\nShelly\n# TXT_C3\nMaria\n# TXT_C4\nKaren\n# TXT_C5\nSteve\n# TXT_C6\nPhil\n# TXT_C7\nDwight\n# TXT_C8\nErik\n# TXT_C9\nProf. Einstein\n# TXT_EINSTEIN\nRoad Bib\n# TXT_BIB\nFaster\n# TXT_FASTER\nSlower\n# TXT_SLOWER\nAir Strike\n# TXT_AIR_STRIKE\nSteel Crate\n# TXT_STEEL_CRATE\nWood Crate\n# TXT_WOOD_CRATE\nWater Crate\n# TXT_WATER_CRATE\nFlag Location\n# TXT_FLAG_SPOT\nUnable to read scenario!\n# TXT_UNABLE_READ_SCENARIO\nError loading game!\n# TXT_ERROR_LOADING_GAME\nObsolete saved game.\n# TXT_OBSOLETE_SAVEGAME\nYou must enter a description!\n# TXT_MUSTENTER_DESCRIPTION\nError saving game!\n# TXT_ERROR_SAVING_GAME\nDelete this file?\n# TXT_DELETE_FILE_QUERY\n[EMPTY SLOT]\n# TXT_EMPTY_SLOT\nSelect Multiplayer Game\n# TXT_SELECT_MPLAYER_GAME\nModem/Serial\n# TXT_MODEM_SERIAL\nNetwork\n# TXT_NETWORK\nUnable to initialize network!\n# TXT_INIT_NET_ERROR\nJoin Network Game\n# TXT_JOIN_NETWORK_GAME\nNew\n# TXT_NEW\nJoin\n# TXT_JOIN\nSend Message\n# TXT_SEND_MESSAGE\nYour Name:\n# TXT_YOUR_NAME\nYour Side:\n# TXT_SIDE_COLON\nYour Color:\n# TXT_COLOR_COLON\nGames\n# TXT_GAMES\nPlayers\n# TXT_PLAYERS\nScenario:\n# TXT_SCENARIO_COLON\n>> NOT FOUND <<\n# TXT_NOT_FOUND\nStarting Credits:\n# TXT_START_CREDITS_COLON\nBases:\n# TXT_BASES_COLON\nOre:\n# TXT_TIBERIUM_COLON\nCrates:\n# TXT_CRATES_COLON\nAI Players:\n# TXT_AI_PLAYERS_COLON\nRequest denied.\n# TXT_REQUEST_DENIED\nUnable to play; scenario not found.\n# TXT_UNABLE_PLAY_WAAUGH\nNothing to join!\n# TXT_NOTHING_TO_JOIN\nYou must enter a name!\n# TXT_NAME_ERROR\nDuplicate names are not allowed.\n# TXT_DUPENAMES_NOTALLOWED\nYour game version is outdated.\n# TXT_YOURGAME_OUTDATED\nDestination game version is outdated.\n# TXT_DESTGAME_OUTDATED\n%s's Game\n# TXT_THATGUYS_GAME\n[%s's Game]\n# TXT_THATGUYS_GAME_BRACKET\nNetwork Game Setup\n# TXT_NETGAME_SETUP\nReject\n# TXT_REJECT\nYou can't reject yourself!\n# TXT_CANT_REJECT_SELF\nYou must select a player to reject.\n# TXT_SELECT_PLAYER_REJECT\nBases\n# TXT_BASES\nCrates\n# TXT_CRATES\nAI Players\n# TXT_AI_PLAYERS\nScenarios\n# TXT_SCENARIOS\nCredits:\n# TXT_CREDITS_COLON\nOnly one player?\n# TXT_ONLY_ONE\nOops!\n# TXT_OOPS\nTo %s:\n# TXT_TO\nTo All:\n# TXT_TO_ALL\nMessage:\n# TXT_MESSAGE\nConnection to %s lost!\n# TXT_CONNECTION_LOST\n%s has left the game.\n# TXT_LEFT_GAME\n%s has been defeated!\n# TXT_PLAYER_DEFEATED\nWaiting to Connect...\n# TXT_WAITING_CONNECT\nConnection error! Check your cables. Attempting to Reconnect...\n# TXT_NULL_CONNERR_CHECK_CABLES\nConnection error! Redialing...\n# TXT_MODEM_CONNERR_REDIALING\nConnection error! Waiting for Call...\n# TXT_MODEM_CONNERR_WAITING\nSelect Serial Game\n# TXT_SELECT_SERIAL_GAME\nDial Modem\n# TXT_DIAL_MODEM\nAnswer Modem\n# TXT_ANSWER_MODEM\nNull Modem\n# TXT_NULL_MODEM\nSettings\n# TXT_SETTINGS\nPort:\n# TXT_PORT_COLON\nIRQ:\n# TXT_IRQ_COLON\nBaud:\n# TXT_BAUD_COLON\nInit String:\n# TXT_INIT_STRING\nCall Waiting String:\n# TXT_CWAIT_STRING\nTone Dialing\n# TXT_TONE_BUTTON\nPulse Dialing\n# TXT_PULSE_BUTTON\nHost Serial Game\n# TXT_HOST_SERIAL_GAME\nOpponent:\n# TXT_OPPONENT_COLON\nUser signed off!\n# TXT_USER_SIGNED_OFF\nJoin Serial Game\n# TXT_JOIN_SERIAL_GAME\nPhone List\n# TXT_PHONE_LIST\nAdd\n# TXT_ADD\nEdit\n# TXT_EDIT\nDial\n# TXT_DIAL\nDefault\n# TXT_DEFAULT\nDefault Settings\n# TXT_DEFAULT_SETTINGS\nCustom Settings\n# TXT_CUSTOM_SETTINGS\nPhone Listing\n# TXT_PHONE_LISTING\nName:\n# TXT_NAME_COLON\nNumber:\n# TXT_NUMBER_COLON\nUnable to find modem. Check power and cables.\n# TXT_UNABLE_FIND_MODEM\nNo carrier.\n# TXT_NO_CARRIER\nLine busy.\n# TXT_LINE_BUSY\nNumber invalid.\n# TXT_NUMBER_INVALID\nOther system not responding!\n# TXT_SYSTEM_NOT_RESPONDING\nGames are out of sync!\n# TXT_OUT_OF_SYNC\nPacket received too late!\n# TXT_PACKET_TOO_LATE\nOther player has left the game.\n# TXT_PLAYER_LEFT_GAME\nFrom %s:%s\n# TXT_FROM\nTIME:\n# TXT_SCORE_TIME\nLEADERSHIP:\n# TXT_SCORE_LEAD\nECONOMY:\n# TXT_SCORE_EFFI\nTOTAL SCORE:\n# TXT_SCORE_TOTA\nCASUALTIES:\n# TXT_SCORE_CASU\nNEUTRAL:\n# TXT_SCORE_NEUT\nBUILDINGS LOST\n# TXT_SCORE_BUIL\nBUILDINGS\n# TXT_SCORE_BUIL1\nLOST:\n# TXT_SCORE_BUIL2\nTOP SCORES\n# TXT_SCORE_TOP\nENDING CREDITS:\n# TXT_SCORE_ENDCRED\n%dh %dm\n# TXT_SCORE_TIMEFORMAT1\n%dm\n# TXT_SCORE_TIMEFORMAT2\nDialing...\n# TXT_DIALING\nDialing Canceled\n# TXT_DIALING_CANCELED\nWaiting for Call...\n# TXT_WAITING_FOR_CALL\nAnswering Canceled\n# TXT_ANSWERING_CANCELED\nEngineer\n# TXT_E6\nSpy\n# TXT_E8\nNot a Null Modem Cable Attached! It is a modem or loopback cable.\n# TXT_MODEM_OR_LOOPBACK\nMap\n# TXT_MAP\nBlossom Tree\n# TXT_BLOSSOM_TREE\nBriefing\n# TXT_RESTATE_MISSION\nComputer\n# TXT_COMPUTER\nUnit Count:\n# TXT_COUNT\nTech Level:\n# TXT_LEVEL\nOpponent\n# TXT_OPPONENT\nKills:\n# TXT_KILLS_COLON\nVideo\n# TXT_VIDEO\nScientist\n# TXT_C10\nCapture The Flag\n# TXT_CAPTURE_THE_FLAG\nMission Objective\n# TXT_OBJECTIVE\nMission\n# TXT_MISSION\nNo saved games available.\n# TXT_NO_SAVES\nCivilian Building\n# TXT_CIVILIAN_BUILDING\nTechnician\n# TXT_TECHNICIAN\nSave game options are not allowed during a multiplayer session.\n# TXT_NO_SAVELOAD\nSpecial 1\n# TXT_DELPHI\nWould you like to replay this mission?\n# TXT_TO_REPLAY\nReconnecting to %s.\n# TXT_RECONN_TO\nPlease wait %02d seconds.\n# TXT_PLEASE_WAIT\nDo you wish to surrender?\n# TXT_SURRENDER\nSELECT TRANSMISSION\n# TXT_SEL_TRANS\nYour game name must be unique.\n# TXT_GAMENAME_MUSTBE_UNIQUE\nGame is closed.\n# TXT_GAME_IS_CLOSED\nYour name must be unique.\n# TXT_NAME_MUSTBE_UNIQUE\nReconnecting to %s\n# TXT_RECONNECTING_TO\nWaiting for connections...\n# TXT_WAITING_FOR_CONNECTIONS\nTime allowed: %02d seconds\n# TXT_TIME_ALLOWED\nPress ESC to cancel.\n# TXT_PRESS_ESC\nFrom Computer: It's just you and me now!\n# TXT_JUST_YOU_AND_ME\nCapture the Flag:\n# TXT_CAPTURE_THE_FLAG_COLON\nSpecial 2\n# TXT_CHAN\n%s has allied with %s\n# TXT_HAS_ALLIED\n%s declares war on %s\n# TXT_AT_WAR\nSelect a target\n# TXT_SEL_TARGET\nResign Game\n# TXT_RESIGN\nOre grows quickly.\n# TXT_TIBERIUM_FAST\nAnswering...\n# TXT_ANSWERING\nInitializing Modem...\n# TXT_INITIALIZING_MODEM\nScenarios don't match.\n# TXT_SCENARIOS_DO_NOT_MATCH\nPower Output\n# TXT_POWER_OUTPUT\nPower Output (low)\n# TXT_POWER_OUTPUT_LOW\nContinue\n# TXT_CONTINUE\nData Queue Overflow\n# TXT_QUEUE_FULL\n%s changed game options!\n# TXT_SPECIAL_WARNING\nPlease insert a Red Alert CD into the CD-ROM drive.\n# TXT_CD_DIALOG_1\nPlease insert CD %d (%s) into the CD-ROM drive.\n# TXT_CD_DIALOG_2\nRed Alert is unable to detect your CD ROM drive.\n# TXT_CD_ERROR1\nNo Sound Card Detected\n# TXT_NO_SOUND_CARD\nUNKNOWN\n# TXT_UNKNOWN\n(old)\n# TXT_OLD_GAME\nInsufficient Disk Space to run Red Alert.\n# TXT_NO_SPACE\nYou must have %d megabytes of free disk space.\n# TXT_MUST_HAVE_SPACE\nRun SETUP program first.\n# TXT_RUN_SETUP\nWaiting for Opponent\n# TXT_WAITING_FOR_OPPONENT\nPlease select 'Settings' to setup default configuration\n# TXT_SELECT_SETTINGS\nPrison\n# TXT_PRISON\nMission Saved\n# TXT_GAME_WAS_SAVED\nInsufficient disk space to save a game.  Please delete a previous save to free up some disk space and try again.\n# TXT_SPACE_CANT_SAVE\nInvalid Port/Address. COM 1-4 OR ADDRESS\n# TXT_INVALID_PORT_ADDRESS\nInvalid Port and/or IRQ settings\n# TXT_INVALID_SETTINGS\nIRQ already in use\n# TXT_IRQ_ALREADY_IN_USE\nAbort\n# TXT_ABORT\nRestart\n# TXT_RESTART\nMission is restarting. Please wait...\n# TXT_RESTARTING\nMission is loading. Please wait...\n# TXT_LOADING\nError in the InitString\n# TXT_ERROR_IN_INITSTRING\nShroud:\n# TXT_SHADOW_COLON\nAnti-Vehicle Mine\n# TXT_AVMINE\nAnti-Personnel Mine\n# TXT_APMINE\nNew Missions\n# TXT_NEW_MISSIONS\nThief\n# TXT_THIEF\nRadar Jammer\n# TXT_MRJ\nGap Generator\n# TXT_GAP_GENERATOR\nPillbox\n# TXT_PILLBOX\nCamo. Pillbox\n# TXT_CAMOPILLBOX\nChronosphere\n# TXT_CHRONOSPHERE\nEngland\n# TXT_ENGLAND\nGermany\n# TXT_GERMANY\nSpain\n# TXT_SPAIN\nRussia\n# TXT_USSR\nUkraine\n# TXT_UKRAINE\nGreece\n# TXT_GREECE\nFrance\n# TXT_FRANCE\nTurkey\n# TXT_TURKEY\nShore\n# TXT_SHORE\nSelect Object\n# TXT_PLACE_OBJECT\nSubmarine\n# TXT_SS\nDestroyer\n# TXT_DD\nCruiser\n# TXT_CA\nTransport\n# TXT_TRANSPORT\nGun Boat\n# TXT_PT\nLobby\n# TXT_LOBBY\nGames\n# TXT_CHANNEL_GAMES\nSave Game...\n# TXT_SAVING_GAME\nGame is full.\n# TXT_GAME_FULL\nYou must select a game!\n# TXT_MUST_SELECT_GAME\n%s playing %s\n# TXT_S_PLAYING_S\nOnly the host can modify this option.\n# TXT_ONLY_HOST_CAN_MODIFY\nGame was cancelled.\n# TXT_GAME_CANCELLED\n%s has formed a new game.\n# TXT_S_FORMED_NEW_GAME\n%s's game is now in progress.\n# TXT_GAME_NOW_IN_PROGRESS\nTesla Coil\n# TXT_TESLA\nMobile Gap Generator\n# TXT_MGG\nFlame Tower\n# TXT_FLAME_TURRET\nAA Gun\n# TXT_AAGUN\nKennel\n# TXT_KENNEL\nSoviet Tech Center\n# TXT_SOVIET_TECH\nBadger Bomber\n# TXT_BADGER\nMig Attack Plane\n# TXT_MIG\nYak Attack Plane\n# TXT_YAK\nBarbed Wire\n# TXT_FENCE\nField Medic\n# TXT_MEDIC\nSaboteur\n# TXT_SABOTEUR\nGeneral\n# TXT_GENERAL\nTanya\n# TXT_E7\nParabombs\n# TXT_PARA_BOMB\nParatroopers\n# TXT_PARA_INFANTRY\nParachute Saboteur\n# TXT_PARA_SABOTEUR\nNaval Yard\n# TXT_SHIP_YARD\nSub Pen\n# TXT_SUB_PEN\nScenario Options\n# TXT_SCENARIO_OPTIONS\nSpy Plane\n# TXT_SPY_MISSION\nSpy Plane\n# TXT_U2\nAttack Dog\n# TXT_GUARD_DOG\nSpy Info\n# TXT_SPY_INFO\nBuildings\n# TXT_BUILDNGS\nUnits\n# TXT_UNITS\nInfantry\n# TXT_INFANTRY\nAircraft\n# TXT_AIRCRAFT\nSupply Truck\n# TXT_TRUCK\nInvulnerability Device\n# TXT_INVUL\nIron Curtain\n# TXT_IRON_CURTAIN\nAllied Tech Center\n# TXT_ADVANCED_TECH\nV2 Rocket\n# TXT_V2_LAUNCHER\nForward Command Post\n# TXT_FORWARD_COM\nDemolitioner\n# TXT_DEMOLITIONER\nMine Layer\n# TXT_MINE_LAYER\nFake Construction Yard\n# TXT_FAKE_CONST\nFake War Factory\n# TXT_FAKE_WEAP\nFake Naval Yard\n# TXT_FAKE_YARD\nFake Sub Pen\n# TXT_FAKE_PEN\nFake Radar Dome\n# TXT_FAKE_RADAR\nBigfoot\n# TXT_THEME_BIGF\nCrush\n# TXT_THEME_CRUS\nFace the Enemy 1\n# TXT_THEME_FAC1\nFace the Enemy 2\n# TXT_THEME_FAC2\nHell March\n# TXT_THEME_HELL\nRun for Your Life\n# TXT_THEME_RUN1\nSmash\n# TXT_THEME_SMSH\nTrenches\n# TXT_THEME_TREN\nWorkmen\n# TXT_THEME_WORK\nAwait\n# TXT_THEME_AWAIT\nDense\n# TXT_THEME_DENSE_R\nMap Selection\n# TXT_THEME_MAP\nFogger\n# TXT_THEME_FOGGER1A\nMud\n# TXT_THEME_MUD1A\nRadio 2\n# TXT_THEME_RADIO2\nRoll Out\n# TXT_THEME_ROLLOUT\nSnake\n# TXT_THEME_SNAKE\nTerminate\n# TXT_THEME_TERMINAT\nTwin\n# TXT_THEME_TWIN\nVector\n# TXT_THEME_VECTOR1A\nTeam Members\n# TXT_TEAM_MEMBERS\nBridge\n# TXT_BRIDGE\nBarrel\n# TXT_BARREL\nFriendly\n# TXT_GOODGUY\nEnemy\n# TXT_BADGUY\nGold\n# TXT_GOLD\nGems\n# TXT_GEMS\nTitle Movie\n# TXT_TEASER\nMovies\n# TXT_MOVIES\nInterior\n# TXT_INTERIOR\nSonar Pulse\n# TXT_SONAR_PULSE\nMissile Silo\n# TXT_MSLO\nGPS Satellite\n# TXT_GPS_SATELLITE\nAtom Bomb\n# TXT_NUCLEAR_BOMB\nEasy\n# TXT_EASY\nHard\n# TXT_HARD\nNormal\n# TXT_NORMAL\nPlease set the difficulty level. It will be used throughout this campaign.\n# TXT_DIFFICULTY\nAllies\n# TXT_ALLIES\nSoviet\n# TXT_SOVIET\nIntro Theme\n# TXT_THEME_INTRO\nShroud Regrows\n# TXT_SHADOW_REGROWS\nOre Regenerates\n# TXT_ORE_SPREADS\nScore Theme\n# TXT_THEME_SCORE\nInternet Game\n# TXT_INTERNET\nIce\n# TXT_ICE\nCrates\n# TXT_CRATE\nSkirmish\n# TXT_SKIRMISH\nChoose your side.\n# TXT_CHOOSE\nValuable Minerals\n# TXT_MINERALS\nIgnore\n# TXT_IGNORE\nError - modem is not responding.\n# TXT_ERROR_NO_RESP\nError - modem did not respond to result code enable command.\n# TXT_ERROR_NO_RESCODE\nError - modem did not respond to initialisation string.\n# TXT_ERROR_NO_INIT\nError - modem did not respond to 'verbose' command.\n# TXT_ERROR_NO_VERB\nError - modem did not respond to 'echo' command.\n# TXT_ERROR_NO_ECHO\nError - unable to disable modem auto answer.\n# TXT_ERROR_NO_DISABLE\nError - Too many errors initialising modem - Aborting.\n# TXT_ERROR_TOO_MANY\nError - Modem returned error status.\n# TXT_ERROR_ERROR\nError - TIme out waiting for connect.\n# TXT_ERROR_TIMEOUT\nAccomplished\n# TXT_ACCOMPLISHED\nClick to Continue\n# TXT_CLICK_CONTINUE\nReceiving scenario from host.\n# TXT_RECEIVING_SCENARIO\nSending scenario to remote players.\n# TXT_SENDING_SCENARIO\nError - Modem failed to respond to flow control command. Your Windows configuration may be incorrect.\n# TXT_NO_FLOW_CONTROL_RESPONSE\nError - Modem failed to respond to compression command. Your Windows configuration may be incorrect.\n# TXT_NO_COMPRESSION_RESPONSE\nError - Modem failed to respond to error correction command. Your Windows configuration may be incorrect.\n# TXT_NO_ERROR_CORRECTION_RESPONSE\nTo play Red Alert via the internet you must be connected to an internet services provider and be registered with Planet Westwood\n# TXT_EXPLAIN_REGISTRATION\nWchat not installed. Please install it from either CD.\n# TXT_ERROR_UNABLE_TO_RUN_WCHAT\nRegister\n# TXT_REGISTER\nOre Mine\n# TXT_ORE_MINE\nNo registered modem\n# TXT_NO_REGISTERED_MODEM\nChronoshift\n# TXT_CHRONOSHIFT\nInvalid Port or Port is in use\n# TXT_UNABLE_TO_OPEN_PORT\nNo dial tone. Ensure your modem is connected to the phone line and try again.\n# TXT_NO_DIAL_TONE\nError - other player does not have this expansion scenario.\n# TXT_NO_EXPANSION_SCENARIO\nPlease Stand By...\n# TXT_STAND_BY\nEnd Credits Theme\n# TXT_THEME_CREDITS\nLow Power: AA-Guns offline\n# TXT_POWER_AAGUN\nLow Power: Tesla Coils offline\n# TXT_POWER_TESLA\nLow Power\n# TXT_LOW_POWER\nCommander:\n# TXT_COMMANDER\nBattles Won:\n# TXT_BATTLES_WON\nGame versions incompatible. To make sure you have the latest version, visit www.westwood.com\n# TXT_MISMATCH\nIncompatible scenario file detected. The scenario may be corrupt.\n# TXT_SCENARIO_ERROR\nConnecting...\n# TXT_CONNECTING\nModem Initialization\n# TXT_MODEM_INITIALISATION\nData Compression\n# TXT_DATA_COMPRESSION\nError Correction\n# TXT_ERROR_CORRECTION\nHardware Flow Control\n# TXT_HARDWARE_FLOW_CONTROL\nAdvanced\n# TXT_ADVANCED\n2nd_Hand\n# TXT_THEME_2ND_HAND\nArazoid\n# TXT_THEME_ARAZOID\nBackStab\n# TXT_THEME_BACKSTAB\nChaos2\n# TXT_THEME_CHAOS2\nShut_It\n# TXT_THEME_SHUT_IT\nTwinMix1\n# TXT_THEME_TWINMIX1\nUnder3\n# TXT_THEME_UNDER3\nVR2\n# TXT_THEME_VR2\nThe other system is not responding. Do you wish to attempt an emergency game save? Both players must save for this to work.\n# TXT_ASK_EMERGENCY_SAVE_NOT_RESPONDING\nThe other system hung up. Do you wish to attempt an emergency game save? Both players must save for this to work.\n# TXT_ASK_EMERGENCY_SAVE_HUNG_UP\nRed Alert was unable to run the registration software. You need to install Westwood Chat from the Red Alert CD to register.\n# TXT_NO_REG_APP\nA player in the game does not have this expansion scenario.\n# TXT_NO_CS_SCENARIOS\nMissile Sub\n# TXT_MISSILESUB\nShock Trooper\n# TXT_SHOCKTROOPER\nMechanic\n# TXT_MECHANIC\nChrono Tank\n# TXT_CHRONOTANK\nTesla Tank\n# TXT_TESLATANK\nM.A.D. Tank\n# TXT_MAD\nDemolition Truck\n# TXT_DEMOTRUCK\nPhase Transport\n# TXT_PHASETRANSPORT\nBog\n# TXT_THEME_BOG\nFloating\n# TXT_THEME_FLOAT_V2\nGloom\n# TXT_THEME_GLOOM\nGround Wire\n# TXT_THEME_GRNDWIRE\nMech Man 2\n# TXT_THEME_RPT\nSearch\n# TXT_THEME_SEARCH\nTraction\n# TXT_THEME_TRACTION\nWasteland\n# TXT_THEME_WASTELND\nHelicarrier\n# TXT_CARRIER\n"
  },
  {
    "path": "CODE/ENG/CREDITS.BAK",
    "content": "      \t\t Executive Producer  \t Brett W. Sperry\n                           Producer  \t Ed Del Castillo\n\n\t\t   Original Concept\t Brett W. Sperry\n                          \t\t Joe Bostic\n\n\t\t     Original Story  \t Ron Smith\n                          \t\t Ed Del Castillo\n\n\t      Lead Game Programmers  \t Joe Bostic\n                          \t\t Barry Green\n                          \t\t Steve Tall\n\n             \t   Game Programmers  \t Bill Randolph\n\t\t\t\t\t Phil Gorrow\n\t\t\t\t\t Maria del Mar McCready Legg\n\n\t       Internet Programmers\t Jeff Brown\n                          \t\t David Aldridge\n                          \t\t Matt Thorn\n\n\t     Translation Programmer\t Victor Grippi\n\n     \t\tTechnical Direction  \t Steve Wetherill\n                          \t\t Eric Wang\n\n               \t          Designers  \t Adam Isgreen\n                          \t\t Michael Lightner\n                          \t\t Erik Yeo\n\n            \t       Lead Artists  \t Chris Demers\n                          \t\t Matthew Hansel\n                          \t\t Joseph B. Hewitt IV\n\n                            Artists  \t David T. Potter\n                          \t\t Damon Redmond\n\t\t\t\t\t Paul Wesberry\n                          \t\t Brian White\n\n              \t         Screenplay  \t Ron Smith\n                          \t\t Adam Isgreen\n                          \t\t John Scott Lewinski\n\n   \t      Video Post Production  \t Felix Kupis\n                          \t\t Kevin Becquet\n\n         Movie Compression Director      Tim C. Fritz\n              Compression Assistant      Patrick Connelly\n\n         \t    Audio Direction  \t Paul S. Mudra\n              \t         Soundtrack  \t Frank Klepacki\n           \t      Sound Effects  \t Dwight K. Okahara\n\n            \t       QA Direction  \t Glenn Sperry\n\n\t\t  Quality Assurance  \t James Adkins\n\t\t\t\t\t John Archer\n\t\t\t\t\t Lloyd Bell\n\t\t\t\t\t Chris Bleven\n\t\t\t\t\t D'Andre Cambell\n\t\t\t\t\t Errol Campbell\n\t\t\t\t\t Phillip Castro\n\t\t\t\t\t Steve Corcoran\n\t\t\t\t\t Kenny Dunne\n\t\t\t\t\t Randy Greenback\n\t\t\t\t\t Abe Hernandez\n\t\t\t\t\t Chris Holloway\n                                         Troy Leonard\n                                         Ben Lublin\n\t\t\t\t\t Levi Luke\n\t\t\t\t\t Isaiah Myers\n\t\t\t\t\t Richard Rasmussen\n\t\t\t\t\t Chris Rubyor\n                                         Robert Scheel\n                                         Albert Springfield\n\t\t\t\t\t Mike Smith\n\t\t\t\t\t Tyler Thackery\n\n              \t         Box Design  \t Matthew Hansel\n                          \t\t Thomas Puckett inc.\n\n\t\t      Manual Design  \t Victoria Hart\n\n\n\t\tSpecial thanks to all our friends and supporters\n\t\twithin the Virgin empire. Additional thanks to\n\t\tTracy Chapman for a new beginning and Greg\n\t\tHjelstrom for the amazing chronal vortex.\n\n\n\n\n\t\t\t          The Cast\n\n\tAllied Side\n             \t         Von Esling  \t Arthur Roberts\n                            Stavros  \t Barry Kramer\n\t\t    Albert Einstein\t John Milford\n                              Tanya  \t Lynne Litteer\n           \t       Interrogator  \t Dom Magwili\n              \t          Announcer  \t Gwen Castaldi\n\n\n        \t    Allied Soldiers\n\t\t\t     Finale\t Ricky Russell\n                         \t\t Nick Paulos\n                         \t\t Scott Ryan Talley\n\n\t\t\t Commanders\t Joe Bostic\n                         \t\t Chris Demers\n                         \t\t Barry Green\n                         \t\t Matthew Hansel\n                         \t\t Adam Isgreen\n                         \t\t Frank Klepacki\n                         \t\t Mike Lightner\n                         \t\t Bill Randolph\n                         \t\t Philip E. Shelburne\n                         \t\t Eric Wang\n\n\n\n     \tSoviet Side\n\t\t       Josef Stalin\t Eugene Dynarski\n        \t              Kukov  \t Craig Cavanah\n              \t           Gradenko  \t Alan Terry\n                              Nadia  \t Andrea Robinson\n                               Kane  \t Joe Kucan\n\n\n        \t    Soviet Soldiers  \t John Archer\n\t\t\t\t\t Mike Grayford\n\t\t\t\t\t Frank Klepacki\n\t\t\t\t\t Felix Kupis\n\t\t\t\t\t Chris Rubyor\n                         \t\t Erik Yeo\n\n\n\n     \tIngame Voices\n        \t             E.V.A.  \t Martin Alper\n              \t              Tanya  \t Lanae Freeborn\n\t\t   Infantry & Units\t Mike Grayford\n                         \t\t Adam Isgreen\n\t\t\t\t\t Frank Klepacki\n                         \t\t Troy Leonard\n\t\t\t\t\t Dwight Okahara\n                         \t\t Chris Rubyor\n   \t\t\t\t\t Eric Wang\n                                         Erik Yeo\n\n\n\n\n     \tProduction Crew\n\n\t\t\tDirected By\t Joseph D. Kucan\n\n\t\t     Costume Design  \t Christie Moeller\n\n\t\t     Make-up & Hair  \t Cindy Cline\n\n\t\t     Sound Engineer  \t Paul S. Mudra\n\n\t\t            Casting  \t Marilee Lear, C.S.A.\n\n\t\t\t      Video\t Kevin Becquet\n\n\t\t           Lighting  \t Eric Gooch\n\n          Lead Production Assistant      Paul Bastardo\n\n              Production Assistants  \t Rick Appin\n                                  \t Patience Becquet\n\t\t\t\t\t Pat Connelly\n                                  \t Jeff Fillhaber\n                                  \t Richard Rasmussen\n\n               \t        Sfx Make-up  \t Philip E. Shelburne\n\n        Special Footage Courtesy Of      NBC News Archives Films\n                                  \t Fabulous Footage\n\n\n\n\n                For the latest news, goodies, and updates,\n                visit our web site at www.westwood.com\n\n\n\n\n\n"
  },
  {
    "path": "CODE/ENG/CREDITS.TXT",
    "content": "\t\t\t\tAftermath Credits\n\n\t\tExecutive Producer\tBrett W. Sperry\n     \n\t\t\t  Producer\tLewis S. Peterson\n     \n\t\t\tProgrammer\tBarry Green\n     \n\t       Technical Direction\tSteve Wetherill, Eric Wang\n     \n\t  Solo Play Map Designers: \n\t\t\t\t\tJohn Archer, Patrick Connelly,\n\t\t\t\t\tAdam Isgreen, Michael Lightner,\n\t\t\t\t\tErik Yeo\n     \n\t  Multiplay Map Designers: \n\t\t\t\t\tJohn Archer, Stuart Bailey,\n\t\t\t\t\tNigel Berryman, D'Andre Campbell,\n\t\t\t\t\tValerie Carpentier, Cathi Diet,\n\t\t\t\t\tKeith Ditchburn, Gareth Eke,\n\t\t\t\t\tDarren Esp, Simon Evers, Rod Gray,\n\t\t\t\t\tRandy Greenback, Matthew Howe,\n\t\t\t\t\tLevi Luke, Suzanne Maddison,\n\t\t\t\t\tIain McNeil, Graeme Miller,\n\t\t\t\t\tLee Morse, David Parsons,\n\t\t\t\t\tAlex Scarrow, Robert Scheel,\n\t\t\t\t\tLawrence So, John Sweeney,\n\t\t\t\t\tMatthew Tillett, Phillip Veale \n     \n\t\t\t  Artists\tChris Demers, Matthew Hansel,\n\t\t\t\t\tJoseph B. Hewitt IV \n     \n\t\t  Audio Direction\tPaul S. Mudra\n     \n\t\t       Soundtrack\tFrank Klepacki\n     \n\t\t    Sound Effects\tDwight K. Okahara\n     \n\t\t     QA Direction\tGlenn Sperry\n     \n\t\tQuality Assurance  \n\t\t\t\t\tJim Adkins, Lloyd Bell,\n\t\t\t\t\tChris Blevens, D'Andre Campbell,\n\t\t\t\t\tErrol Campbell, Shane Dietrich,\n\t\t\t\t\tRandy Greenback, Jon Hix, Mark Laity,\n\t\t\t\t\tTroy Leonard, DeMarlo Lewis,\n\t\t\t\t\tLevi Luke, Patrick Offord,\n\t\t\t\t\tRichard Rasmussen, Mike Ruppert,\n\t\t\t\t\tSteve Shockey, Mike Smith,\n\t\t\t\t\tAlbert Springfield\n     \n\t\t    Ingame Voices\tJeff Fillhaber, Michael Smith\n     \n\n\n\n\n\t\t\t     Red Alert Credits\n\n      \t\t Executive Producer  \t Brett W. Sperry\n                           Producer  \t Ed Del Castillo\n\n\t\t   Original Concept\t Brett W. Sperry\n                          \t\t Joe Bostic\n\n\t\t     Original Story  \t Ron Smith\n                          \t\t Ed Del Castillo\n\n\t      Lead Game Programmers  \t Joe Bostic\n                          \t\t Barry Green\n                          \t\t Steve Tall\n\n             \t   Game Programmers  \t Bill Randolph\n\t\t\t\t\t Phil Gorrow\n\t\t\t\t\t Maria del Mar McCready Legg\n\n\t       Internet Programmers\t Jeff Brown\n                          \t\t David Aldridge\n                          \t\t Matt Thorn\n\n\t     Translation Programmer\t Victor Grippi\n\n     \t\tTechnical Direction  \t Steve Wetherill\n                          \t\t Eric Wang\n\n               \t          Designers  \t Adam Isgreen\n                          \t\t Michael Lightner\n                          \t\t Erik Yeo\n\n            \t       Lead Artists  \t Chris Demers\n                          \t\t Matthew Hansel\n                          \t\t Joseph B. Hewitt IV\n\n                            Artists  \t David T. Potter\n                          \t\t Damon Redmond\n\t\t\t\t\t Paul Wesberry\n                          \t\t Brian White\n\n              \t         Screenplay  \t Ron Smith\n                          \t\t Adam Isgreen\n                          \t\t John Scott Lewinski\n\n   \t      Video Post Production  \t Felix Kupis\n                          \t\t Kevin Becquet\n\n         Movie Compression Director      Tim C. Fritz\n              Compression Assistant      Patrick Connelly\n\n         \t    Audio Direction  \t Paul S. Mudra\n              \t         Soundtrack  \t Frank Klepacki\n           \t      Sound Effects  \t Dwight K. Okahara\n\n            \t       QA Direction  \t Glenn Sperry\n\n\t\t  Quality Assurance  \t James Adkins\n\t\t\t\t\t John Archer\n\t\t\t\t\t Lloyd Bell\n\t\t\t\t\t Chris Bleven\n\t\t\t\t\t D'Andre Cambell\n\t\t\t\t\t Errol Campbell\n\t\t\t\t\t Phillip Castro\n\t\t\t\t\t Steve Corcoran\n\t\t\t\t\t Kenny Dunne\n\t\t\t\t\t Randy Greenback\n\t\t\t\t\t Abe Hernandez\n\t\t\t\t\t Chris Holloway\n                                         Troy Leonard\n                                         Ben Lublin\n\t\t\t\t\t Levi Luke\n\t\t\t\t\t Isaiah Myers\n\t\t\t\t\t Richard Rasmussen\n\t\t\t\t\t Chris Rubyor\n                                         Robert Scheel\n                                         Albert Springfield\n\t\t\t\t\t Mike Smith\n\t\t\t\t\t Tyler Thackery\n\n              \t         Box Design  \t Matthew Hansel\n                          \t\t Thomas Puckett Inc.\n\n\t\t      Manual Design  \t Victoria Hart\n\n\n\t\tSpecial thanks to all our friends and supporters\n\t\twithin the Virgin empire. Additional thanks to\n\t\tTracy Chapman for a new beginning and Greg\n\t\tHjelstrom for the amazing chronal vortex.\n\n\n\n\n\t\t\t          The Cast\n\n\tAllied Side\n             \t         Von Esling  \t Arthur Roberts\n                            Stavros  \t Barry Kramer\n\t\t    Albert Einstein\t John Milford\n                              Tanya  \t Lynne Litteer\n           \t       Interrogator  \t Dom Magwili\n              \t          Announcer  \t Gwen Castaldi\n\n\n        \t    Allied Soldiers\n\t\t\t     Finale\t Ricky Russell\n                         \t\t Nick Paulos\n                         \t\t Scott Ryan Talley\n\n\t\t\t Commanders\t Joe Bostic\n                         \t\t Chris Demers\n                         \t\t Barry Green\n                         \t\t Matthew Hansel\n                         \t\t Adam Isgreen\n                         \t\t Frank Klepacki\n                         \t\t Mike Lightner\n                         \t\t Bill Randolph\n                         \t\t Philip E. Shelburne\n                         \t\t Eric Wang\n\n\n\n     \tSoviet Side\n\t\t       Josef Stalin\t Eugene Dynarski\n        \t              Kukov  \t Craig Cavanah\n              \t           Gradenko  \t Alan Terry\n                              Nadia  \t Andrea Robinson\n                               Kane  \t Joe Kucan\n\n\n        \t    Soviet Soldiers  \t John Archer\n\t\t\t\t\t Mike Grayford\n\t\t\t\t\t Frank Klepacki\n\t\t\t\t\t Felix Kupis\n\t\t\t\t\t Chris Rubyor\n                         \t\t Erik Yeo\n\n\n\n     \tIngame Voices\n        \t             E.V.A.  \t Martin Alper\n              \t              Tanya  \t Lanae Freeborn\n\t\t   Infantry & Units\t Mike Grayford\n                         \t\t Adam Isgreen\n\t\t\t\t\t Frank Klepacki\n                         \t\t Troy Leonard\n\t\t\t\t\t Dwight Okahara\n                         \t\t Chris Rubyor\n   \t\t\t\t\t Eric Wang\n                                         Erik Yeo\n\n\n\n\n     \tProduction Crew\n\n\t\t\tDirected By\t Joseph D. Kucan\n\n\t\t     Costume Design  \t Christie Moeller\n\n\t\t     Make-up & Hair  \t Cindy Cline\n\n\t\t     Sound Engineer  \t Paul S. Mudra\n\n\t\t            Casting  \t Marilee Lear, C.S.A.\n\n\t\t\t      Video\t Kevin Becquet\n\n\t\t           Lighting  \t Eric Gooch\n\n          Lead Production Assistant      Paul Bastardo\n\n              Production Assistants  \t Rick Appin\n                                  \t Patience Becquet\n\t\t\t\t\t Pat Connelly\n                                  \t Jeff Fillhaber\n                                  \t Richard Rasmussen\n\n               \t        Sfx Make-up  \t Philip E. Shelburne\n\n        Special Footage Courtesy Of      NBC News Archives Films\n                                  \t Fabulous Footage\n\n\n\n\n\n\n\n\n\n\t\t\tCounterstrike Credits\n\n      \t\t Executive Producer  \t Brett W. Sperry\n                           Producer  \t Ed Del Castillo\n\n\t\t\tProgrammers\t Victor Grippi\n\t\t\t\t\t Joe Bostic\n\t\t\t\t\t Steve Tall\n\t\t\t\t\t Maria del Mar McCready Legg\n\n     \t\tTechnical Direction  \t Steve Wetherill\n                          \t\t Eric Wang\n\n\t    Solo Play Map Designers\t Adam Isgreen\n\t\t\t\t\t Michael Lightner\n\t\t\t\t\t Patrick Connelly\n\n\t    Multiplay Map Designers\t Iain McNeil\n\t\t\t\t\t Alex Scarrow\n\t\t\t\t\t Graeme Miller\n\t\t\t\t\t Nigel Berryman\n\t\t\t\t\t Rod Gray\n\t\t\t\t\t Stuart Bailey\n\t\t\t\t\t Mat Tillett\n\t\t\t\t\t Phil Veale\n\t\t\t\t\t Dave Parsons\n\t\t\t\t\t Darren Esp\n\t\t\t\t\t Cameron Strutt\n\t\t\t\t\t Paul Goodwin\n\t\t\t\t\t John McNeil\n\t\t\t\t\t Lee Morse\n\t\t\t\t\t Adam Isgreen\n\t\t\t\t\t Michael Lightner\n\t\t\t\t\t John Archer\n\t\t\t\t\t Patrick Connelly\n\t\t\t\t\t Lloyd Bell\n\t\t\t\t\t D'Andre Campbell\n\t\t\t\t\t Albert Springfield\n\t\t\t\t\t Levi Luke\n\t\t\t\t\t Robert Scheel\n\n            \t            Artists  \t Chris Demers\n                          \t\t Matthew Hansel\n\t\t\t\t\t Shelly Johnson\n\t\t\t\t\t Frank Mendeola\n\n\t\t\t      Video\t Kevin Becquet\n\t\t\t\t\t Patience Becquet\n\n         \t    Audio Direction  \t Paul S. Mudra\n\n\t\t\t Soundtrack  \t Frank Klepacki\n\n\t\t      Sound Effects  \t Dwight K. Okahara\n\n\t\t       QA Direction\t Glenn Sperry\n\n\t\t  Quality Assurance\t John Archer\n\t\t\t\t\t Mike Smith\n\t\t\t\t\t Lloyd Bell\n                                         Troy Leonard\n\t\t\t\t\t Chris Halloway\n\t\t\t\t\t Randy Greenback\n\t\t\t\t\t D'Andre Cambell\n\t\t\t\t\t Errol Campbell\n                                         Albert Springfield\n\t\t  \t\t\t James Adkins\n\t\t\t\t\t Chris Blevens\n\t\t\t\t\t Levi Luke\n\t\t\t\t\t Steve Shockey\n\t\t\t\t\t Isaiah Myers\n                                         Ben Lublin\n\t\t\t\t\t Richard Rasmussen\n                                         Robert Scheel\n\t\t\t\t\t Tom Andrulis\n\t\t\t\t\t Shane Dietrich\n\t\t\t\t\t Brandon Hansen\n\n\n\n\t\tThanks to Westwood's killer marketing staff for\n\t\tall their support, Intelligent Games for creating\n\t\ta bulk of the multiplayer maps, and Brett and\n\t\t         Louis for being born.\n\n\t\tSpecial thanks to the European Marketing teams\n\t\tfor their support, and to the original Red Alert\n\t\tteam for giving us something to build on.\n\n\n\n\n                For the latest news, goodies, and updates,\n                visit our web site at www.westwood.com\n\n\n\n\n\n\n"
  },
  {
    "path": "CODE/ENG/DEBUG.BAK",
    "content": "Clear the map\n# TXT_CLEAR_MAP\nInherit previous map\n# TXT_INHERIT_MAP\nSelect Special Options\n# TXT_SPECIAL_OPTIONS\nTargeting flash visible to all.\n# TXT_VISIBLE_TARGET\nAllow targeting of trees.\n# TXT_TREE_TARGET\nAllow undeploy of construction yard.\n# TXT_MCV_DEPLOY\nEmploy smarter self defense logic.\n# TXT_SMART_DEFENCE\nModerate production speed.\n# TXT_SLOW_BUILD\nUse three point turn logic.\n# TXT_THREE_POINT\nOre will grow.\n# TXT_TIBERIUM_GROWTH\nOre will spread.\n# TXT_TIBERIUM_SPREAD\nDisable building \"bib\" pieces.\n# TXT_ROAD_PIECES\nAllow running from immediate threats.\n# TXT_SCATTER\nShow true object names.\n# TXT_SHOW_NAMES\nDefender has the advantage.\n# TXT_DEFENDER_ADVANTAGE\nAllow separate helipad purchase\n# TXT_SEPARATE_HELIPAD\nPassword Request\n# TXT_PASSWORD_CAPTION\nEnter Red Alert access code to gain access.\n# TXT_PASSWORD_MESSAGE\nAccess code error detected.\n# TXT_PASSWORD_ERROR\nTry Again\n# TXT_TRY_AGAIN\nFriendly units avoid friendly mines\n# TXT_MINE_AWARE\nTrigger Editor\n# TXT_TRIGGER_EDITOR\nJust This Event\n# TXT_TRIGGER_JUST_EVENT\n... and ...\n# TXT_TRIGGER_AND\n... or ...\n# TXT_TRIGGER_OR\n... linked ...\n# TXT_TRIGGER_LINKED\nJust This Action\n# TXT_TRIGGER_JUST_ACTION\nTeam Editor\n# TXT_TEAM_EDIT\nSellable\n# TXT_SELLABLE\nRebuild\n# TXT_REBUILD\nBuilding constructin time accelerated?\n# TXT_SPEED_BUILD\nScenario authentication code missing or invalid. Re-save scenario to correct it.\n# TXT_SCENARIO_ERROR\nFrames:F/R:CPU:F/R:Cells:Targ:S-Bar:Paths:Sprung Triggers:Ŀ\n                                                                     \nG-Time:Ĵ                                                         \n                                                                     \n                                                             \n                                                                      \n                                                                      \n                                                                      \n                                                                      \n                                                                      \nObject Count:                                                         \n   -Units                                                             \n   -Infantry CPU Workload:Ĵ\n   -Aircraft                                                                \n   -Ships                                                                   \n   -Buildings                                                               \n   -Terrain                                                                 \n   -Bullets                                                                 \n   -Anims                                                                   \n   -Teams                                                                   \n   -Triggers                                                                \n   -TrigTypes                                                               \n   -Factories                                                               \n\n<- F11                        Stress Tracking                            F12 ->\n# TXT_DEBUG_STRESS\nFull Name:Coord:Hgt:Str:Ace:Spd:AmmoArm:Grp:Cloak:Price:Ŀ\n                                                                   \nOwner:Trigger:TarCom:STarCom:PFace:Path:Try:Delay:\n                                                                      \nCargo:Target:Next:NavCom:SNavCom:SFace:PBrk:HeadTo:Archive:Ĵ\n                                                                     \nTmr:St:Rt:StageRadio:Radio Message History:Ĵ\n                                                                        \nMission:Queue:Ĵ                                                 \n                                                                           \nGems:Gold:Ĵ\n                                                                           \nĴ\nIs Down     AnimAttachedPrimary     Player OwnedInitiated   Is Dumping  \nTo Damage   Falling [  ]Loaner      Player AwareDeploying   Teleported  \nTo Display  Useless     Locked      AI aware    Firing                  \nIn Limbo    Ticked Off  Recoil      Lemon       Rotating                \nSelected    Cloakable   Tethered    Invul [    ]Driving                 \nTo Look     Unloading   Formation                                       \nTeam:Mmbrs:Qnt:Center:Target:Formation:͵\n                                              UnderstrngthMoving      \nMission:ĴFullStrengthForcedActive\n                                                  HasBeen     Reforming   \n\n<- F11                        Vehicle                                    F12 ->\n# TXT_DEBUG_VEHICLE\nFull Name:Coord:Hgt:Str:Ace:Spd:AmmoArm:Grp:Cloak:Price:Ŀ\n                                                                   \nOwner:Trigger:TarCom:STarCom:PFace:Path:Try:Delay:\n                                                                      \nCargo:Target:Next:NavCom:SNavCom:SFace:PBrk:HeadTo:Archive:Ĵ\n                                                                     \nTmr:St:Rt:StageRadio:Radio Message History:Ĵ\n                                                                        \nMission:Queue:Ĵ                                                 \n                                                                           \nDoing:Fear:Ĵ\n                                                                           \nĴ\nIs Down     AnimAttachedPrimary     Player OwnedInitiated   Technician  \nTo Damage   Falling [  ]Loaner      Player AwareDeploying   Stoked      \nTo Display  Useless     Locked      AI Aware    Firing      Prone       \nIn Limbo    Ticked Off  Recoil      Lemon       Rotating                \nSelected    Cloakable   Tethered    Invul [    ]Driving                 \nTo Look     Unloading   Formation                                       \nTeam:Mmbrs:Qnt:Center:Target:Formation:͵\n                                              UnderstrngthMoving      \nMission:ĴFullStrengthForcedActive\n                                                  HasBeen     Reforming   \n\n<- F11                        Infantry                                   F12 ->\n# TXT_DEBUG_INFANTRY\nFull Name:Coord:Hgt:Str:Ace:Spd:AmmoArm:Grp:Cloak:Price:Ŀ\n                                                                   \nOwner:Trigger:TarCom:STarCom:PFace:Path:Try:Delay:\n                                                                      \nCargo:Target:Next:NavCom:SNavCom:SFace:PBrk:HeadTo:Archive:Ĵ\n                                                                     \nTmr:St:Rt:StageRadio:Radio Message History:Ĵ\n                                                                        \nMission:Queue:Ĵ                                                 \n                                                                           \nĴ\n                                                                             \nĴ\nIs Down     AnimAttachedPrimary     Player OwnedInitiated   Repairing   \nTo Damage   Falling [  ]Loaner      Player AwareDeploying   ToSelfRepair\nTo Display  Useless     Locked      AI Aware    Firing                  \nIn Limbo    Ticked Off  Recoil      Lemon       Rotating                \nSelected    Cloakable   Tethered    Invul [    ]Driving                 \nTo Look     Unloading   Formation                                       \nTeam:Mmbrs:Qnt:Center:Target:Formation:͵\n                                              UnderstrngthMoving      \nMission:ĴFullStrengthForcedActive\n                                                  HasBeen     Reforming   \n\n<- F11                        Ship                                       F12 ->\n# TXT_DEBUG_SHIP\nFull Name:Coord:Hgt:Str:Ace:Spd:AmmoArm:Grp:Cloak:Price:Ŀ\n                                                                   \nOwner:Trigger:TarCom:STarCom:PFace:Path:Try:Delay:\n                                                                      \nCargo:Target:Next:NavCom:SNavCom:SFace:PBrk:HeadTo:Archive:Ĵ\n                                                                     \nTmr:St:Rt:StageRadio:Radio Message History:Ĵ\n                                                                        \nMission:Queue:Ĵ                                                 \n                                                                           \nBuilding:Ĵ\n                                                                            \nĴ\nIs Down     AnimAttachedPrimary     Player OwnedInitiated   Reparing    \nTo Damage   Falling [  ]Loaner      Player AwareDeploying   To Rebuild  \nTo Display  Useless     Locked      AI Aware    Firing      To Sell     \nIn Limbo    Ticked Off  Recoil      Lemon       Rotating    Charging    \nSelected    Cloakable   Tethered    Invul [    ]Driving     Charged     \nTo Look     Unloading   Formation                           Captured    \nĴJamming     \n                                                                Jammed      \n                                                                            \n                                                                            \n\n<- F11                        Building                                   F12 ->\n# TXT_DEBUG_BUILDING\n Game Objects  Drawing   System      Map Display              Game Init  \nFind-Path:Cell:Palette:Full ProcessRULES.INI:͵\n                                                                        \nTarget Scan:Objects:Sidebar:SCENARIO.INI\n                                                                        \nAI:Anims:Radar:Ĵ\n                                                                        \nPer-Cell-AITactical:Ĵ\n                                                                        \nEval Object:Power Bar:Ĵ\n                                                                        \nEval Cell:Shroud:Ĵ\n                                                                        \nEval Wall:Tabs:Ĵ\n                                                                        \nMission:DirectX BlitĴ\n                                                                        \nĴ\n                                                                        \nĴ\n                                                                        \nĴ\n                                                                        \n\n<- F11                        Performance Benchmarks                     F12 ->\n# TXT_DEBUG_PERFORMANCE\nFull Name:Coord:Hgt:Str:Ace:Spd:AmmoArm:Grp:Cloak:Price:Ŀ\n                                                                   \nOwner:Trigger:TarCom:STarCom:PFace:Path:Try:Delay:\n                                                                      \nCargo:Target:Next:NavCom:SNavCom:SFace:PBrk:HeadTo:Archive:Ĵ\n                                                                     \nTmr:St:Rt:StageRadio:Radio Message History:Ĵ\n                                                                        \nMission:Queue:Ĵ                                                 \n                                                                           \nAttk:Ĵ\n                                                                            \nĴ\nIs Down     AnimAttachedPrimary     Player OwnedInitiated               \nTo Damage   Falling [  ]Loaner      Player AwareDeploying               \nTo Display  Useless     Locked      AI aware    Firing                  \nIn Limbo    Ticked Off  Recoil      Lemon       Rotating                \nSelected    Cloakable   Tethered    Invul [    ]Driving                 \nTo Look     Unloading   Formation                                       \nTeam:Mmbrs:Qnt:Center:Target:Formation:͵\n                                              UnderstrngthMoving      \nMission:ĴFullStrengthForcedActive\n                                                  HasBeen     Reforming   \n\n<- F11                        Aircraft                                   F12 ->\n# TXT_DEBUG_AIRCRAFT\nFull Name:Act Like:Tech:Diff:State:Block:IQ:Repair:Ŀ\n                                                                      \nAScan:Air:Q-AirCredits:Power:R-Spy:Score:Team:Alert:Ĵ\n                                                                     \nBScan:BuildingQ-BldOre:Drain:P-Targ:Trigger:Borrow:Ĵ\n                                                                      \nUScan:Unit:Q-UnitICreds:U-Lost:Allies:Attack:Ĵ\n                                                                      \nIScan:InfantryQ-InfCapacityB-Lost:Radius:Ĵ                AI-Time:\n                                                                      \nVScan:Vessel:Q-ShipNorth:Center Cell:Damage:Ĵ\n                                                                        \nWest:Core:East:Ĵ\n                                                                           \nGlobals:South:Enemy:Ĵ\n                                                                           \nĴ\nIs Active   Defeated    Visionary   Resigned                            \nIs Human    To Die      Low Ore     Gave Up                             \nPlayer Ctrl To Win      Spied       Built Smthng                        \nAutocreate  To Lose     Thieved     Auto Base AI                        \nDiscovered  Civ. Evac   GPS Active                                      \nMax CapacityRecalc Flag Production                                      \n\n<- F11                           House                                   F12 ->\n# TXT_DEBUG_HOUSE\n*******************************\\r** Pentium CPU not detected. **\\r*******************************\n# TXT_NO_PENTIUM\nSize Map\n# TXT_SIZE_MAP\nTrucks drop crate when destroyed?\n# TXT_TRUCK_CRATE\n"
  },
  {
    "path": "CODE/ENG/DEBUG.TXT",
    "content": "Clear the map\n# TXT_CLEAR_MAP\nInherit previous map\n# TXT_INHERIT_MAP\nSelect Special Options\n# TXT_SPECIAL_OPTIONS\nTargeting flash visible to all.\n# TXT_VISIBLE_TARGET\nAllow targeting of trees.\n# TXT_TREE_TARGET\nAllow undeploy of construction yard.\n# TXT_MCV_DEPLOY\nEmploy smarter self defense logic.\n# TXT_SMART_DEFENCE\nModerate production speed.\n# TXT_SLOW_BUILD\nUse three point turn logic.\n# TXT_THREE_POINT\nOre will grow.\n# TXT_TIBERIUM_GROWTH\nOre will spread.\n# TXT_TIBERIUM_SPREAD\nDisable building \"bib\" pieces.\n# TXT_ROAD_PIECES\nAllow running from immediate threats.\n# TXT_SCATTER\nShow true object names.\n# TXT_SHOW_NAMES\nDefender has the advantage.\n# TXT_DEFENDER_ADVANTAGE\nAllow separate helipad purchase\n# TXT_SEPARATE_HELIPAD\nPassword Request\n# TXT_PASSWORD_CAPTION\nEnter Red Alert access code to gain access.\n# TXT_PASSWORD_MESSAGE\nAccess code error detected.\n# TXT_PASSWORD_ERROR\nTry Again\n# TXT_TRY_AGAIN\nFriendly units avoid friendly mines\n# TXT_MINE_AWARE\nTrigger Editor\n# TXT_TRIGGER_EDITOR\nJust This Event\n# TXT_TRIGGER_JUST_EVENT\n... and ...\n# TXT_TRIGGER_AND\n... or ...\n# TXT_TRIGGER_OR\n... linked ...\n# TXT_TRIGGER_LINKED\nJust This Action\n# TXT_TRIGGER_JUST_ACTION\nTeam Editor\n# TXT_TEAM_EDIT\nSellable\n# TXT_SELLABLE\nRebuild\n# TXT_REBUILD\nBuilding constructin time accelerated?\n# TXT_SPEED_BUILD\nScenario authentication code missing or invalid. Re-save scenario to correct it.\n# TXT_SCENARIO_ERRORx\nFrames:F/R:CPU:F/R:Cells:Targ:S-Bar:Paths:Sprung Triggers:Ŀ\n                                                                     \nG-Time:Ĵ                                                         \n                                                                     \n                                                             \n                                                                      \n                                                                      \n                                                                      \n                                                                      \n                                                                      \nObject Count:                                                         \n   -Units                                                             \n   -Infantry CPU Workload:Ĵ\n   -Aircraft                                                                \n   -Ships                                                                   \n   -Buildings                                                               \n   -Terrain                                                                 \n   -Bullets                                                                 \n   -Anims                                                                   \n   -Teams                                                                   \n   -Triggers                                                                \n   -TrigTypes                                                               \n   -Factories                                                               \n\n<- F11                        Stress Tracking                            F12 ->\n# TXT_DEBUG_STRESS\nFull Name:Coord:Hgt:Str:Ace:Spd:AmmoArm:Grp:Cloak:Price:Ŀ\n                                                                   \nOwner:Trigger:TarCom:STarCom:PFace:Path:Try:Delay:\n                                                                      \nCargo:Target:Next:NavCom:SNavCom:SFace:PBrk:HeadTo:Archive:Ĵ\n                                                                     \nTmr:St:Rt:StageRadio:Radio Message History:Ĵ\n                                                                        \nMission:Queue:Ĵ                                                 \n                                                                           \nGems:Gold:Ĵ\n                                                                           \nĴ\nIs Down     AnimAttachedPrimary     Player OwnedInitiated   Is Dumping  \nTo Damage   Falling [  ]Loaner      Player AwareDeploying   Teleported  \nTo Display  Useless     Locked      AI aware    Firing                  \nIn Limbo    Ticked Off  Recoil      Lemon       Rotating                \nSelected    Cloakable   Tethered    Invul [    ]Driving                 \nTo Look     Unloading   Formation                                       \nTeam:Mmbrs:Qnt:Center:Target:Formation:͵\n                                              UnderstrngthMoving      \nMission:ĴFullStrengthForcedActive\n                                                  HasBeen     Reforming   \n\n<- F11                        Vehicle                                    F12 ->\n# TXT_DEBUG_VEHICLE\nFull Name:Coord:Hgt:Str:Ace:Spd:AmmoArm:Grp:Cloak:Price:Ŀ\n                                                                   \nOwner:Trigger:TarCom:STarCom:PFace:Path:Try:Delay:\n                                                                      \nCargo:Target:Next:NavCom:SNavCom:SFace:PBrk:HeadTo:Archive:Ĵ\n                                                                     \nTmr:St:Rt:StageRadio:Radio Message History:Ĵ\n                                                                        \nMission:Queue:Ĵ                                                 \n                                                                           \nDoing:Fear:Ĵ\n                                                                           \nĴ\nIs Down     AnimAttachedPrimary     Player OwnedInitiated   Technician  \nTo Damage   Falling [  ]Loaner      Player AwareDeploying   Stoked      \nTo Display  Useless     Locked      AI Aware    Firing      Prone       \nIn Limbo    Ticked Off  Recoil      Lemon       Rotating                \nSelected    Cloakable   Tethered    Invul [    ]Driving                 \nTo Look     Unloading   Formation                                       \nTeam:Mmbrs:Qnt:Center:Target:Formation:͵\n                                              UnderstrngthMoving      \nMission:ĴFullStrengthForcedActive\n                                                  HasBeen     Reforming   \n\n<- F11                        Infantry                                   F12 ->\n# TXT_DEBUG_INFANTRY\nFull Name:Coord:Hgt:Str:Ace:Spd:AmmoArm:Grp:Cloak:Price:Ŀ\n                                                                   \nOwner:Trigger:TarCom:STarCom:PFace:Path:Try:Delay:\n                                                                      \nCargo:Target:Next:NavCom:SNavCom:SFace:PBrk:HeadTo:Archive:Ĵ\n                                                                     \nTmr:St:Rt:StageRadio:Radio Message History:Ĵ\n                                                                        \nMission:Queue:Ĵ                                                 \n                                                                           \nĴ\n                                                                             \nĴ\nIs Down     AnimAttachedPrimary     Player OwnedInitiated   Repairing   \nTo Damage   Falling [  ]Loaner      Player AwareDeploying   ToSelfRepair\nTo Display  Useless     Locked      AI Aware    Firing                  \nIn Limbo    Ticked Off  Recoil      Lemon       Rotating                \nSelected    Cloakable   Tethered    Invul [    ]Driving                 \nTo Look     Unloading   Formation                                       \nTeam:Mmbrs:Qnt:Center:Target:Formation:͵\n                                              UnderstrngthMoving      \nMission:ĴFullStrengthForcedActive\n                                                  HasBeen     Reforming   \n\n<- F11                        Ship                                       F12 ->\n# TXT_DEBUG_SHIP\nFull Name:Coord:Hgt:Str:Ace:Spd:AmmoArm:Grp:Cloak:Price:Ŀ\n                                                                   \nOwner:Trigger:TarCom:STarCom:PFace:Path:Try:Delay:\n                                                                      \nCargo:Target:Next:NavCom:SNavCom:SFace:PBrk:HeadTo:Archive:Ĵ\n                                                                     \nTmr:St:Rt:StageRadio:Radio Message History:Ĵ\n                                                                        \nMission:Queue:Ĵ                                                 \n                                                                           \nBuilding:Ĵ\n                                                                            \nĴ\nIs Down     AnimAttachedPrimary     Player OwnedInitiated   Reparing    \nTo Damage   Falling [  ]Loaner      Player AwareDeploying   To Rebuild  \nTo Display  Useless     Locked      AI Aware    Firing      To Sell     \nIn Limbo    Ticked Off  Recoil      Lemon       Rotating    Charging    \nSelected    Cloakable   Tethered    Invul [    ]Driving     Charged     \nTo Look     Unloading   Formation                           Captured    \nĴJamming     \n                                                                Jammed      \n                                                                            \n                                                                            \n\n<- F11                        Building                                   F12 ->\n# TXT_DEBUG_BUILDING\n Game Objects  Drawing   System      Map Display              Game Init  \nFind-Path:Cell:Palette:Full ProcessRULES.INI:͵\n                                                                        \nTarget Scan:Objects:Sidebar:SCENARIO.INI\n                                                                        \nAI:Anims:Radar:Ĵ\n                                                                        \nPer-Cell-AITactical:Ĵ\n                                                                        \nEval Object:Power Bar:Ĵ\n                                                                        \nEval Cell:Shroud:Ĵ\n                                                                        \nEval Wall:Tabs:Ĵ\n                                                                        \nMission:DirectX BlitĴ\n                                                                        \nĴ\n                                                                        \nĴ\n                                                                        \nĴ\n                                                                        \n\n<- F11                        Performance Benchmarks                     F12 ->\n# TXT_DEBUG_PERFORMANCE\nFull Name:Coord:Hgt:Str:Ace:Spd:AmmoArm:Grp:Cloak:Price:Ŀ\n                                                                   \nOwner:Trigger:TarCom:STarCom:PFace:Path:Try:Delay:\n                                                                      \nCargo:Target:Next:NavCom:SNavCom:SFace:PBrk:HeadTo:Archive:Ĵ\n                                                                     \nTmr:St:Rt:StageRadio:Radio Message History:Ĵ\n                                                                        \nMission:Queue:Ĵ                                                 \n                                                                           \nAttk:Ĵ\n                                                                            \nĴ\nIs Down     AnimAttachedPrimary     Player OwnedInitiated               \nTo Damage   Falling [  ]Loaner      Player AwareDeploying               \nTo Display  Useless     Locked      AI aware    Firing                  \nIn Limbo    Ticked Off  Recoil      Lemon       Rotating                \nSelected    Cloakable   Tethered    Invul [    ]Driving                 \nTo Look     Unloading   Formation                                       \nTeam:Mmbrs:Qnt:Center:Target:Formation:͵\n                                              UnderstrngthMoving      \nMission:ĴFullStrengthForcedActive\n                                                  HasBeen     Reforming   \n\n<- F11                        Aircraft                                   F12 ->\n# TXT_DEBUG_AIRCRAFT\nFull Name:Act Like:Tech:Diff:State:Block:IQ:Repair:Ŀ\n                                                                      \nAScan:Air:Q-AirCredits:Power:R-Spy:Score:Team:Alert:Ĵ\n                                                                     \nBScan:BuildingQ-BldOre:Drain:P-Targ:Trigger:Borrow:Ĵ\n                                                                      \nUScan:Unit:Q-UnitICreds:U-Lost:Allies:Attack:Ĵ\n                                                                      \nIScan:InfantryQ-InfCapacityB-Lost:Radius:Ĵ                AI-Time:\n                                                                      \nVScan:Vessel:Q-ShipNorth:Center Cell:Damage:Ĵ\n                                                                        \nWest:Core:East:Ĵ\n                                                                           \nGlobals:South:Enemy:Ĵ\n                                                                           \nĴ\nIs Active   Defeated    Visionary   Resigned                            \nIs Human    To Die      Low Ore     Gave Up                             \nPlayer Ctrl To Win      Spied       Built Smthng                        \nAutocreate  To Lose     Thieved     Auto Base AI                        \nDiscovered  Civ. Evac   GPS Active                                      \nMax CapacityRecalc Flag Production                                      \n\n<- F11                           House                                   F12 ->\n# TXT_DEBUG_HOUSE\n*******************************\\r** Pentium CPU not detected. **\\r*******************************\n# TXT_NO_PENTIUM\nSize Map\n# TXT_SIZE_MAP\nTrucks drop crate when destroyed?\n# TXT_TRUCK_CRATE\n"
  },
  {
    "path": "CODE/ENG/ENG/CONQUER.TXT",
    "content": "# TXT_NONE\n%3d.%02d\n# TXT_CREDIT_FORMAT\nTime:%02d:%02d:%02d\n# TXT_TIME_FORMAT_HOURS\nTime:%02d:%02d\n# TXT_TIME_FORMAT_NO_HOURS\nSell\n# TXT_BUTTON_SELL\nSell Structure\n# TXT_SELL\nRepair\n# TXT_BUTTON_REPAIR\nYou:\n# TXT_YOU\nEnemy:\n# TXT_ENEMY\nBuildings Destroyed By\n# TXT_BUILD_DEST\nUnits Destroyed By\n# TXT_UNIT_DEST\nOre Harvested By\n# TXT_TIB_HARV\nScore: %d\n# TXT_SCORE_1\nYes\n# TXT_YES\nNo\n# TXT_NO\nMission Accomplished\n# TXT_SCENARIO_WON\nMission Failed\n# TXT_SCENARIO_LOST\nStart New Game\n# TXT_START_NEW_GAME\nIntro & Sneak Peek\n# TXT_INTRO\nCancel\n# TXT_CANCEL\nRock\n# TXT_ROCK\nCivilian\n# TXT_CIVILIAN\nContainment Team\n# TXT_JP\nOK\n# TXT_OK\nTree\n# TXT_TREE\n\\x011\n# TXT_LEFT\n\\x010\n# TXT_RIGHT\n\\x01E\n# TXT_UP\n\\x01F\n# TXT_DOWN\nClear\n# TXT_CLEAR\nWater\n# TXT_WATER\nRoad\n# TXT_ROAD\nSlope\n# TXT_SLOPE\nPatch\n# TXT_PATCH\nRiver\n# TXT_RIVER\nLoad Mission\n# TXT_LOAD_MISSION\nSave Mission\n# TXT_SAVE_MISSION\nDelete Mission\n# TXT_DELETE_MISSION\nLoad\n# TXT_LOAD_BUTTON\nSave\n# TXT_SAVE_BUTTON\nDelete\n# TXT_DELETE_BUTTON\nGame Controls\n# TXT_GAME_CONTROLS\nSound Controls\n# TXT_SOUND_CONTROLS\nResume Mission\n# TXT_RESUME_MISSION\nVisual Controls\n# TXT_VISUAL_CONTROLS\nAbort Mission\n# TXT_QUIT_MISSION\nExit Game\n# TXT_EXIT_GAME\nOptions\n# TXT_OPTIONS\nSquish mark\n# TXT_SQUISH\nCrater\n# TXT_CRATER\nScorch Mark\n# TXT_SCORCH\nBRIGHTNESS:\n# TXT_BRIGHTNESS\nMusic Volume\n# TXT_MUSIC\nSound Volume\n# TXT_VOLUME\nTint:\n# TXT_TINT\nContrast:\n# TXT_CONTRAST\nGame Speed:\n# TXT_SPEED\nScroll Rate:\n# TXT_SCROLLRATE\nColor:\n# TXT_COLOR\nReturn to game\n# TXT_RETURN_TO_GAME\nEnemy Soldier\n# TXT_ENEMY_SOLDIER\nEnemy Vehicle\n# TXT_ENEMY_VEHICLE\nEnemy Structure\n# TXT_ENEMY_STRUCTURE\nLight Tank\n# TXT_LTANK\nHeavy Tank\n# TXT_MTANK\nMedium Tank\n# TXT_MTANK2\nMammoth Tank\n# TXT_HTANK\nSAM Site\n# TXT_SAM\nRanger\n# TXT_JEEP\nChinook Helicopter\n# TXT_TRANS\nOre Truck\n# TXT_HARVESTER\nArtillery\n# TXT_ARTY\nRifle Infantry\n# TXT_E1\nGrenadier\n# TXT_E2\nRocket Soldier\n# TXT_E3\nFlamethrower\n# TXT_E4\nLongbow Helicopter\n# TXT_HELI\nHind\n# TXT_ORCA\nAPC\n# TXT_APC\nGuard Tower\n# TXT_GUARD_TOWER\nRadar Dome\n# TXT_COMMAND\nHelipad\n# TXT_HELIPAD\nAirfield\n# TXT_AIRSTRIP\nOre Silo\n# TXT_STORAGE\nConstruction Yard\n# TXT_CONST_YARD\nOre Refinery\n# TXT_REFINERY\nChurch\n# TXT_CIV1\nHan's and Gretel's\n# TXT_CIV2\nHewitt's Manor\n# TXT_CIV3\nRicktor's House\n# TXT_CIV4\nGretchin's House\n# TXT_CIV5\nThe Barn\n# TXT_CIV6\nDamon's pub\n# TXT_CIV7\nFran's House\n# TXT_CIV8\nMusic Factory\n# TXT_CIV9\nToymaker's\n# TXT_CIV10\nLudwig's House\n# TXT_CIV11\nHaystacks\n# TXT_CIV12\nHaystack\n# TXT_CIV13\nWheat Field\n# TXT_CIV14\nFallow Field\n# TXT_CIV15\nCorn Field\n# TXT_CIV16\nCelery Field\n# TXT_CIV17\nPotato Field\n# TXT_CIV18\nSala's House\n# TXT_CIV20\nAbdul's House\n# TXT_CIV21\nPablo's Wicked Pub\n# TXT_CIV22\nVillage Well\n# TXT_CIV23\nCamel Trader\n# TXT_CIV24\nChurch\n# TXT_CIV25\nAli's House\n# TXT_CIV26\nTrader Ted's\n# TXT_CIV27\nMenelik's House\n# TXT_CIV28\nPrestor John's House\n# TXT_CIV29\nVillage Well\n# TXT_CIV30\nWitch Doctor's Hut\n# TXT_CIV31\nRikitikitembo's Hut\n# TXT_CIV32\nRoarke's Hut\n# TXT_CIV33\nMubasa's Hut\n# TXT_CIV34\nAksum's Hut\n# TXT_CIV35\nMambo's Hut\n# TXT_CIV36\nThe Studio\n# TXT_CIV37\nTechnology Center\n# TXT_CIVMISS\nTurret\n# TXT_TURRET\nGunboat\n# TXT_GUNBOAT\nMobile Construction Vehicle\n# TXT_MCV\nPower Plant\n# TXT_POWER\nAdvanced Power Plant\n# TXT_ADVANCED_POWER\nHospital\n# TXT_HOSPITAL\nBarracks\n# TXT_BARRACKS\nOil Pump\n# TXT_PUMP\nOil Tanker\n# TXT_TANKER\nSandbags\n# TXT_SANDBAG_WALL\nChain Link Fence\n# TXT_CYCLONE_WALL\nConcrete Wall\n# TXT_BRICK_WALL\nBarbwire Fence\n# TXT_BARBWIRE_WALL\nWood Fence\n# TXT_WOOD_WALL\nWar Factory\n# TXT_WEAPON_FACTORY\nAdvanced Guard Tower\n# TXT_AGUARD_TOWER\nBio-Research Laboratory\n# TXT_BIO_LAB\nService Depot\n# TXT_FIX_IT\nSidebar\n# TXT_TAB_SIDEBAR\nOptions\n# TXT_TAB_BUTTON_CONTROLS\nDatabase\n# TXT_TAB_BUTTON_DATABASE\nUnrevealed Terrain\n# TXT_SHADOW\nOptions Menu\n# TXT_OPTIONS_MENU\nStop\n# TXT_STOP\nPlay\n# TXT_PLAY\nShuffle\n# TXT_SHUFFLE\nRepeat\n# TXT_REPEAT\nMusic volume:\n# TXT_MUSIC_VOLUME\nSound volume:\n# TXT_SOUND_VOLUME\nOn\n# TXT_ON\nOff\n# TXT_OFF\nMultiplayer Game\n# TXT_MULTIPLAYER_GAME\nNo files available\n# TXT_NO_FILES\nDo you want to delete this file?\n# TXT_DELETE_SINGLE_FILE\nDo you want to delete %d files?\n# TXT_DELETE_MULTIPLE_FILES\nReset Values\n# TXT_RESET_MENU\nDo you want to abort the mission?\n# TXT_CONFIRM_EXIT\nMission Description\n# TXT_MISSION_DESCRIPTION\nJoe\n# TXT_C1\nBarry\n# TXT_C2\nShelly\n# TXT_C3\nMaria\n# TXT_C4\nKaren\n# TXT_C5\nSteve\n# TXT_C6\nPhil\n# TXT_C7\nDwight\n# TXT_C8\nErik\n# TXT_C9\nProf. Einstein\n# TXT_EINSTEIN\nRoad Bib\n# TXT_BIB\nFaster\n# TXT_FASTER\nSlower\n# TXT_SLOWER\nAir Strike\n# TXT_AIR_STRIKE\nSteel Crate\n# TXT_STEEL_CRATE\nWood Crate\n# TXT_WOOD_CRATE\nWater Crate\n# TXT_WATER_CRATE\nFlag Location\n# TXT_FLAG_SPOT\nUnable to read scenario!\n# TXT_UNABLE_READ_SCENARIO\nError loading game!\n# TXT_ERROR_LOADING_GAME\nObsolete saved game.\n# TXT_OBSOLETE_SAVEGAME\nYou must enter a description!\n# TXT_MUSTENTER_DESCRIPTION\nError saving game!\n# TXT_ERROR_SAVING_GAME\nDelete this file?\n# TXT_DELETE_FILE_QUERY\n[EMPTY SLOT]\n# TXT_EMPTY_SLOT\nSelect Multiplayer Game\n# TXT_SELECT_MPLAYER_GAME\nModem/Serial\n# TXT_MODEM_SERIAL\nNetwork\n# TXT_NETWORK\nUnable to initialize network!\n# TXT_INIT_NET_ERROR\nJoin Network Game\n# TXT_JOIN_NETWORK_GAME\nNew\n# TXT_NEW\nJoin\n# TXT_JOIN\nSend Message\n# TXT_SEND_MESSAGE\nYour Name:\n# TXT_YOUR_NAME\nYour Side:\n# TXT_SIDE_COLON\nYour Color:\n# TXT_COLOR_COLON\nGames\n# TXT_GAMES\nPlayers\n# TXT_PLAYERS\nScenario:\n# TXT_SCENARIO_COLON\n>> NOT FOUND <<\n# TXT_NOT_FOUND\nStarting Credits:\n# TXT_START_CREDITS_COLON\nBases:\n# TXT_BASES_COLON\nOre:\n# TXT_TIBERIUM_COLON\nCrates:\n# TXT_CRATES_COLON\nAI Players:\n# TXT_AI_PLAYERS_COLON\nRequest denied.\n# TXT_REQUEST_DENIED\nUnable to play; scenario not found.\n# TXT_UNABLE_PLAY_WAAUGH\nNothing to join!\n# TXT_NOTHING_TO_JOIN\nYou must enter a name!\n# TXT_NAME_ERROR\nDuplicate names are not allowed.\n# TXT_DUPENAMES_NOTALLOWED\nYour game version is outdated.\n# TXT_YOURGAME_OUTDATED\nDestination game version is outdated.\n# TXT_DESTGAME_OUTDATED\n%s's Game\n# TXT_THATGUYS_GAME\n[%s's Game]\n# TXT_THATGUYS_GAME_BRACKET\nNetwork Game Setup\n# TXT_NETGAME_SETUP\nReject\n# TXT_REJECT\nYou can't reject yourself!\n# TXT_CANT_REJECT_SELF\nYou must select a player to reject.\n# TXT_SELECT_PLAYER_REJECT\nBases\n# TXT_BASES\nCrates\n# TXT_CRATES\nAI Players\n# TXT_AI_PLAYERS\nScenarios\n# TXT_SCENARIOS\nCredits:\n# TXT_CREDITS_COLON\nOnly one player?\n# TXT_ONLY_ONE\nOops!\n# TXT_OOPS\nTo %s:\n# TXT_TO\nTo All:\n# TXT_TO_ALL\nMessage:\n# TXT_MESSAGE\nConnection to %s lost!\n# TXT_CONNECTION_LOST\n%s has left the game.\n# TXT_LEFT_GAME\n%s has been defeated!\n# TXT_PLAYER_DEFEATED\nWaiting to Connect...\n# TXT_WAITING_CONNECT\nConnection error! Check your cables. Attempting to Reconnect...\n# TXT_NULL_CONNERR_CHECK_CABLES\nConnection error! Redialing...\n# TXT_MODEM_CONNERR_REDIALING\nConnection error! Waiting for Call...\n# TXT_MODEM_CONNERR_WAITING\nSelect Serial Game\n# TXT_SELECT_SERIAL_GAME\nDial Modem\n# TXT_DIAL_MODEM\nAnswer Modem\n# TXT_ANSWER_MODEM\nNull Modem\n# TXT_NULL_MODEM\nSettings\n# TXT_SETTINGS\nPort:\n# TXT_PORT_COLON\nIRQ:\n# TXT_IRQ_COLON\nBaud:\n# TXT_BAUD_COLON\nInit String:\n# TXT_INIT_STRING\nCall Waiting String:\n# TXT_CWAIT_STRING\nTone Dialing\n# TXT_TONE_BUTTON\nPulse Dialing\n# TXT_PULSE_BUTTON\nHost Serial Game\n# TXT_HOST_SERIAL_GAME\nOpponent:\n# TXT_OPPONENT_COLON\nUser signed off!\n# TXT_USER_SIGNED_OFF\nJoin Serial Game\n# TXT_JOIN_SERIAL_GAME\nPhone List\n# TXT_PHONE_LIST\nAdd\n# TXT_ADD\nEdit\n# TXT_EDIT\nDial\n# TXT_DIAL\nDefault\n# TXT_DEFAULT\nDefault Settings\n# TXT_DEFAULT_SETTINGS\nCustom Settings\n# TXT_CUSTOM_SETTINGS\nPhone Listing\n# TXT_PHONE_LISTING\nName:\n# TXT_NAME_COLON\nNumber:\n# TXT_NUMBER_COLON\nUnable to find modem. Check power and cables.\n# TXT_UNABLE_FIND_MODEM\nNo carrier.\n# TXT_NO_CARRIER\nLine busy.\n# TXT_LINE_BUSY\nNumber invalid.\n# TXT_NUMBER_INVALID\nOther system not responding!\n# TXT_SYSTEM_NOT_RESPONDING\nGames are out of sync!\n# TXT_OUT_OF_SYNC\nPacket received too late!\n# TXT_PACKET_TOO_LATE\nOther player has left the game.\n# TXT_PLAYER_LEFT_GAME\nFrom %s:%s\n# TXT_FROM\nTIME:\n# TXT_SCORE_TIME\nLEADERSHIP:\n# TXT_SCORE_LEAD\nECONOMY:\n# TXT_SCORE_EFFI\nTOTAL SCORE:\n# TXT_SCORE_TOTA\nCASUALTIES:\n# TXT_SCORE_CASU\nNEUTRAL:\n# TXT_SCORE_NEUT\nBUILDINGS LOST\n# TXT_SCORE_BUIL\nBUILDINGS\n# TXT_SCORE_BUIL1\nLOST:\n# TXT_SCORE_BUIL2\nTOP SCORES\n# TXT_SCORE_TOP\nENDING CREDITS:\n# TXT_SCORE_ENDCRED\n%dh %dm\n# TXT_SCORE_TIMEFORMAT1\n%dm\n# TXT_SCORE_TIMEFORMAT2\nDialing...\n# TXT_DIALING\nDialing Canceled\n# TXT_DIALING_CANCELED\nWaiting for Call...\n# TXT_WAITING_FOR_CALL\nAnswering Canceled\n# TXT_ANSWERING_CANCELED\nEngineer\n# TXT_E6\nSpy\n# TXT_E8\nNot a Null Modem Cable Attached! It is a modem or loopback cable.\n# TXT_MODEM_OR_LOOPBACK\nMap\n# TXT_MAP\nBlossom Tree\n# TXT_BLOSSOM_TREE\nBriefing\n# TXT_RESTATE_MISSION\nComputer\n# TXT_COMPUTER\nUnit Count:\n# TXT_COUNT\nTech Level:\n# TXT_LEVEL\nOpponent\n# TXT_OPPONENT\nKills:\n# TXT_KILLS_COLON\nVideo\n# TXT_VIDEO\nScientist\n# TXT_C10\nCapture The Flag\n# TXT_CAPTURE_THE_FLAG\nMission Objective\n# TXT_OBJECTIVE\nMission\n# TXT_MISSION\nNo saved games available.\n# TXT_NO_SAVES\nCivilian Building\n# TXT_CIVILIAN_BUILDING\nTechnician\n# TXT_TECHNICIAN\nSave game options are not allowed during a multiplayer session.\n# TXT_NO_SAVELOAD\nSpecial 1\n# TXT_DELPHI\nWould you like to replay this mission?\n# TXT_TO_REPLAY\nReconnecting to %s.\n# TXT_RECONN_TO\nPlease wait %02d seconds.\n# TXT_PLEASE_WAIT\nDo you wish to surrender?\n# TXT_SURRENDER\nSELECT TRANSMISSION\n# TXT_SEL_TRANS\nYour game name must be unique.\n# TXT_GAMENAME_MUSTBE_UNIQUE\nGame is closed.\n# TXT_GAME_IS_CLOSED\nYour name must be unique.\n# TXT_NAME_MUSTBE_UNIQUE\nReconnecting to %s\n# TXT_RECONNECTING_TO\nWaiting for connections...\n# TXT_WAITING_FOR_CONNECTIONS\nTime allowed: %02d seconds\n# TXT_TIME_ALLOWED\nPress ESC to cancel.\n# TXT_PRESS_ESC\nFrom Computer: It's just you and me now!\n# TXT_JUST_YOU_AND_ME\nCapture the Flag:\n# TXT_CAPTURE_THE_FLAG_COLON\nSpecial 2\n# TXT_CHAN\n%s has allied with %s\n# TXT_HAS_ALLIED\n%s declares war on %s\n# TXT_AT_WAR\nSelect a target\n# TXT_SEL_TARGET\nResign Game\n# TXT_RESIGN\nOre grows quickly.\n# TXT_TIBERIUM_FAST\nAnswering...\n# TXT_ANSWERING\nInitializing Modem...\n# TXT_INITIALIZING_MODEM\nScenarios don't match.\n# TXT_SCENARIOS_DO_NOT_MATCH\nPower Output\n# TXT_POWER_OUTPUT\nPower Output (low)\n# TXT_POWER_OUTPUT_LOW\nContinue\n# TXT_CONTINUE\nData Queue Overflow\n# TXT_QUEUE_FULL\n%s changed game options!\n# TXT_SPECIAL_WARNING\nPlease insert a Red Alert CD into the CD-ROM drive.\n# TXT_CD_DIALOG_1\nPlease insert CD %d (%s) into the CD-ROM drive.\n# TXT_CD_DIALOG_2\nRed Alert is unable to detect your CD ROM drive.\n# TXT_CD_ERROR1\nNo Sound Card Detected\n# TXT_NO_SOUND_CARD\nUNKNOWN\n# TXT_UNKNOWN\n(old)\n# TXT_OLD_GAME\nInsufficient Disk Space to run Red Alert.\n# TXT_NO_SPACE\nYou must have %d megabytes of free disk space.\n# TXT_MUST_HAVE_SPACE\nRun SETUP program first.\n# TXT_RUN_SETUP\nWaiting for Opponent\n# TXT_WAITING_FOR_OPPONENT\nPlease select 'Settings' to setup default configuration\n# TXT_SELECT_SETTINGS\nPrison\n# TXT_PRISON\nMission Saved\n# TXT_GAME_WAS_SAVED\nInsufficient disk space to save a game.  Please delete a previous save to free up some disk space and try again.\n# TXT_SPACE_CANT_SAVE\nInvalid Port/Address. COM 1-4 OR ADDRESS\n# TXT_INVALID_PORT_ADDRESS\nInvalid Port and/or IRQ settings\n# TXT_INVALID_SETTINGS\nIRQ already in use\n# TXT_IRQ_ALREADY_IN_USE\nAbort\n# TXT_ABORT\nRestart\n# TXT_RESTART\nMission is restarting. Please wait...\n# TXT_RESTARTING\nMission is loading. Please wait...\n# TXT_LOADING\nError in the InitString\n# TXT_ERROR_IN_INITSTRING\nShroud:\n# TXT_SHADOW_COLON\nAnti-Vehicle Mine\n# TXT_AVMINE\nAnti-Personnel Mine\n# TXT_APMINE\nNew Missions\n# TXT_NEW_MISSIONS\nThief\n# TXT_THIEF\nRadar Jammer\n# TXT_MRJ\nGap Generator\n# TXT_GAP_GENERATOR\nPillbox\n# TXT_PILLBOX\nCamo. Pillbox\n# TXT_CAMOPILLBOX\nChronosphere\n# TXT_CHRONOSPHERE\nEngland\n# TXT_ENGLAND\nGermany\n# TXT_GERMANY\nSpain\n# TXT_SPAIN\nRussia\n# TXT_USSR\nUkraine\n# TXT_UKRAINE\nGreece\n# TXT_GREECE\nFrance\n# TXT_FRANCE\nTurkey\n# TXT_TURKEY\nShore\n# TXT_SHORE\nSelect Object\n# TXT_PLACE_OBJECT\nSubmarine\n# TXT_SS\nDestroyer\n# TXT_DD\nCruiser\n# TXT_CA\nTransport\n# TXT_TRANSPORT\nGun Boat\n# TXT_PT\nLobby\n# TXT_LOBBY\nGames\n# TXT_CHANNEL_GAMES\nSave Game...\n# TXT_SAVING_GAME\nGame is full.\n# TXT_GAME_FULL\nYou must select a game!\n# TXT_MUST_SELECT_GAME\n%s playing %s\n# TXT_S_PLAYING_S\nOnly the host can modify this option.\n# TXT_ONLY_HOST_CAN_MODIFY\nGame was cancelled.\n# TXT_GAME_CANCELLED\n%s has formed a new game.\n# TXT_S_FORMED_NEW_GAME\n%s's game is now in progress.\n# TXT_GAME_NOW_IN_PROGRESS\nTesla Coil\n# TXT_TESLA\nMobile Gap Generator\n# TXT_MGG\nFlame Tower\n# TXT_FLAME_TURRET\nAA Gun\n# TXT_AAGUN\nKennel\n# TXT_KENNEL\nSoviet Tech Center\n# TXT_SOVIET_TECH\nBadger Bomber\n# TXT_BADGER\nMig Attack Plane\n# TXT_MIG\nYak Attack Plane\n# TXT_YAK\nBarbed Wire\n# TXT_FENCE\nField Medic\n# TXT_MEDIC\nSaboteur\n# TXT_SABOTEUR\nGeneral\n# TXT_GENERAL\nTanya\n# TXT_E7\nParabombs\n# TXT_PARA_BOMB\nParatroopers\n# TXT_PARA_INFANTRY\nParachute Saboteur\n# TXT_PARA_SABOTEUR\nNaval Yard\n# TXT_SHIP_YARD\nSub Pen\n# TXT_SUB_PEN\nScenario Options\n# TXT_SCENARIO_OPTIONS\nSpy Plane\n# TXT_SPY_MISSION\nSpy Plane\n# TXT_U2\nAttack Dog\n# TXT_GUARD_DOG\nSpy Info\n# TXT_SPY_INFO\nBuildings\n# TXT_BUILDNGS\nUnits\n# TXT_UNITS\nInfantry\n# TXT_INFANTRY\nAircraft\n# TXT_AIRCRAFT\nSupply Truck\n# TXT_TRUCK\nInvulnerability Device\n# TXT_INVUL\nIron Curtain\n# TXT_IRON_CURTAIN\nAllied Tech Center\n# TXT_ADVANCED_TECH\nV2 Rocket\n# TXT_V2_LAUNCHER\nForward Command Post\n# TXT_FORWARD_COM\nDemolitioner\n# TXT_DEMOLITIONER\nMine Layer\n# TXT_MINE_LAYER\nFake Construction Yard\n# TXT_FAKE_CONST\nFake War Factory\n# TXT_FAKE_WEAP\nFake Naval Yard\n# TXT_FAKE_YARD\nFake Sub Pen\n# TXT_FAKE_PEN\nFake Radar Dome\n# TXT_FAKE_RADAR\nBigfoot\n# TXT_THEME_BIGF\nCrush\n# TXT_THEME_CRUS\nFace the Enemy 1\n# TXT_THEME_FAC1\nFace the Enemy 2\n# TXT_THEME_FAC2\nHell March\n# TXT_THEME_HELL\nRun for Your Life\n# TXT_THEME_RUN1\nSmash\n# TXT_THEME_SMSH\nTrenches\n# TXT_THEME_TREN\nWorkmen\n# TXT_THEME_WORK\nAwait\n# TXT_THEME_AWAIT\nDense\n# TXT_THEME_DENSE_R\nMap Selection\n# TXT_THEME_MAP\nFogger\n# TXT_THEME_FOGGER1A\nMud\n# TXT_THEME_MUD1A\nRadio 2\n# TXT_THEME_RADIO2\nRoll Out\n# TXT_THEME_ROLLOUT\nSnake\n# TXT_THEME_SNAKE\nTerminate\n# TXT_THEME_TERMINAT\nTwin\n# TXT_THEME_TWIN\nVector\n# TXT_THEME_VECTOR1A\nTeam Members\n# TXT_TEAM_MEMBERS\nBridge\n# TXT_BRIDGE\nBarrel\n# TXT_BARREL\nFriendly\n# TXT_GOODGUY\nEnemy\n# TXT_BADGUY\nGold\n# TXT_GOLD\nGems\n# TXT_GEMS\nTitle Movie\n# TXT_TEASER\nMovies\n# TXT_MOVIES\nInterior\n# TXT_INTERIOR\nSonar Pulse\n# TXT_SONAR_PULSE\nMissile Silo\n# TXT_MSLO\nGPS Satellite\n# TXT_GPS_SATELLITE\nAtom Bomb\n# TXT_NUCLEAR_BOMB\nEasy\n# TXT_EASY\nHard\n# TXT_HARD\nNormal\n# TXT_NORMAL\nPlease set the difficulty level. It will be used throughout this campaign.\n# TXT_DIFFICULTY\nAllies\n# TXT_ALLIES\nSoviet\n# TXT_SOVIET\nIntro Theme\n# TXT_THEME_INTRO\nShroud Regrows\n# TXT_SHADOW_REGROWS\nOre Regenerates\n# TXT_ORE_SPREADS\nScore Theme\n# TXT_THEME_SCORE\nInternet Game\n# TXT_INTERNET\nIce\n# TXT_ICE\nCrates\n# TXT_CRATE\nSkirmish\n# TXT_SKIRMISH\nChoose your side.\n# TXT_CHOOSE\nValuable Minerals\n# TXT_MINERALS\nIgnore\n# TXT_IGNORE\nError - modem is not responding.\n# TXT_ERROR_NO_RESP\nError - modem did not respond to result code enable command.\n# TXT_ERROR_NO_RESCODE\nError - modem did not respond to initialisation string.\n# TXT_ERROR_NO_INIT\nError - modem did not respond to 'verbose' command.\n# TXT_ERROR_NO_VERB\nError - modem did not respond to 'echo' command.\n# TXT_ERROR_NO_ECHO\nError - unable to disable modem auto answer.\n# TXT_ERROR_NO_DISABLE\nError - Too many errors initialising modem - Aborting.\n# TXT_ERROR_TOO_MANY\nError - Modem returned error status.\n# TXT_ERROR_ERROR\nError - TIme out waiting for connect.\n# TXT_ERROR_TIMEOUT\nAccomplished\n# TXT_ACCOMPLISHED\nClick to Continue\n# TXT_CLICK_CONTINUE\nReceiving scenario from host.\n# TXT_RECEIVING_SCENARIO\nSending scenario to remote players.\n# TXT_SENDING_SCENARIO\nError - Modem failed to respond to flow control command. Your Windows configuration may be incorrect.\n# TXT_NO_FLOW_CONTROL_RESPONSE\nError - Modem failed to respond to compression command. Your Windows configuration may be incorrect.\n# TXT_NO_COMPRESSION_RESPONSE\nError - Modem failed to respond to error correction command. Your Windows configuration may be incorrect.\n# TXT_NO_ERROR_CORRECTION_RESPONSE\nTo play Red Alert via the internet you must be connected to an internet services provider and be registered with Planet Westwood\n# TXT_EXPLAIN_REGISTRATION\nWchat not installed. Please install it from either CD.\n# TXT_ERROR_UNABLE_TO_RUN_WCHAT\nRegister\n# TXT_REGISTER\nOre Mine\n# TXT_ORE_MINE\nNo registered modem\n# TXT_NO_REGISTERED_MODEM\nChronoshift\n# TXT_CHRONOSHIFT\nInvalid Port or Port is in use\n# TXT_UNABLE_TO_OPEN_PORT\nNo dial tone. Ensure your modem is connected to the phone line and try again.\n# TXT_NO_DIAL_TONE\nError - other player does not have this expansion scenario.\n# TXT_NO_EXPANSION_SCENARIO\nPlease Stand By...\n# TXT_STAND_BY\nEnd Credits Theme\n# TXT_THEME_CREDITS\nLow Power: AA-Guns offline\n# TXT_POWER_AAGUN\nLow Power: Tesla Coils offline\n# TXT_POWER_TESLA\nLow Power\n# TXT_LOW_POWER\nCommander:\n# TXT_COMMANDER\nBattles Won:\n# TXT_BATTLES_WON\nGame versions incompatible. To make sure you have the latest version, visit www.westwood.com\n# TXT_MISMATCH\nIncompatible scenario file detected. The scenario may be corrupt.\n# TXT_SCENARIO_ERROR\nConnecting...\n# TXT_CONNECTING\nModem Initialization\n# TXT_MODEM_INITIALISATION\nData Compression\n# TXT_DATA_COMPRESSION\nError Correction\n# TXT_ERROR_CORRECTION\nHardware Flow Control\n# TXT_HARDWARE_FLOW_CONTROL\nAdvanced\n# TXT_ADVANCED\n2nd_Hand\n# TXT_THEME_2ND_HAND\nArazoid\n# TXT_THEME_ARAZOID\nBackStab\n# TXT_THEME_BACKSTAB\nChaos2\n# TXT_THEME_CHAOS2\nShut_It\n# TXT_THEME_SHUT_IT\nTwinMix1\n# TXT_THEME_TWINMIX1\nUnder3\n# TXT_THEME_UNDER3\nVR2\n# TXT_THEME_VR2\nThe other system is not responding. Do you wish to attempt an emergency game save? Both players must save for this to work.\n# TXT_ASK_EMERGENCY_SAVE_NOT_RESPONDING\nThe other system hung up. Do you wish to attempt an emergency game save? Both players must save for this to work.\n# TXT_ASK_EMERGENCY_SAVE_HUNG_UP\nRed Alert was unable to run the registration software. You need to install Westwood Chat from the Red Alert CD to register.\n# TXT_NO_REG_APP\nA player in the game does not have this expansion scenario.\n# TXT_NO_CS_SCENARIOS\nMissile Sub\n# TXT_MISSILESUB\nShock Trooper\n# TXT_SHOCKTROOPER\nMechanic\n# TXT_MECHANIC\nChrono Tank\n# TXT_CHRONOTANK\nTesla Tank\n# TXT_TESLATANK\nM.A.D. Tank\n# TXT_MAD\nDemolition Truck\n# TXT_DEMOTRUCK\nPhase Transport\n# TXT_PHASETRANSPORT\nBog\n# TXT_THEME_BOG\nFloating\n# TXT_THEME_FLOAT_V2\nGloom\n# TXT_THEME_GLOOM\nGround Wire\n# TXT_THEME_GRNDWIRE\nMech Man 2\n# TXT_THEME_RPT\nSearch\n# TXT_THEME_SEARCH\nTraction\n# TXT_THEME_TRACTION\nWasteland\n# TXT_THEME_WASTELND\nHelicarrier\n# TXT_CARRIER\n"
  },
  {
    "path": "CODE/ENG/ENG/CREDITS.TXT",
    "content": "\t\t\t\tAftermath Credits\n\n\t\tExecutive Producer\tBrett W. Sperry\n     \n\t\t\t  Producer\tLewis S. Peterson\n     \n\t\t\tProgrammer\tBarry Green\n     \n\t       Technical Direction\tSteve Wetherill, Eric Wang\n     \n\t  Solo Play Map Designers: \n\t\t\t\t\tJohn Archer, Patrick Connelly,\n\t\t\t\t\tAdam Isgreen, Michael Lightner,\n\t\t\t\t\tErik Yeo\n     \n\t  Multiplay Map Designers: \n\t\t\t\t\tJohn Archer, Stuart Bailey,\n\t\t\t\t\tNigel Berryman, D'Andre Campbell,\n\t\t\t\t\tValerie Carpentier, Cathi Diet,\n\t\t\t\t\tKeith Ditchburn, Gareth Eke,\n\t\t\t\t\tDarren Esp, Simon Evers, Rod Gray,\n\t\t\t\t\tRandy Greenback, Matthew Howe,\n\t\t\t\t\tLevi Luke, Suzanne Maddison,\n\t\t\t\t\tIain McNeil, Graeme Miller,\n\t\t\t\t\tLee Morse, David Parsons,\n\t\t\t\t\tAlex Scarrow, Robert Scheel,\n\t\t\t\t\tLawrence So, John Sweeney,\n\t\t\t\t\tMatthew Tillett, Phillip Veale \n     \n\t\t\t  Artists\tChris Demers, Matthew Hansel,\n\t\t\t\t\tJoseph B. Hewitt IV \n     \n\t\t  Audio Direction\tPaul S. Mudra\n     \n\t\t       Soundtrack\tFrank Klepacki\n     \n\t\t    Sound Effects\tDwight K. Okahara\n     \n\t\t     QA Direction\tGlenn Sperry\n     \n\t\tQuality Assurance  \n\t\t\t\t\tJim Adkins, Lloyd Bell,\n\t\t\t\t\tChris Blevens, D'Andre Campbell,\n\t\t\t\t\tErrol Campbell, Shane Dietrich,\n\t\t\t\t\tRandy Greenback, Jon Hix, Mark Laity,\n\t\t\t\t\tTroy Leonard, DeMarlo Lewis,\n\t\t\t\t\tLevi Luke, Patrick Offord,\n\t\t\t\t\tRichard Rasmussen, Mike Ruppert,\n\t\t\t\t\tSteve Shockey, Mike Smith,\n\t\t\t\t\tAlbert Springfield\n     \n\t\t    Ingame Voices\tJeff Fillhaber, Michael Smith\n     \n\n\n\n\n\t\t\t     Red Alert Credits\n\n      \t\t Executive Producer  \t Brett W. Sperry\n                           Producer  \t Ed Del Castillo\n\n\t\t   Original Concept\t Brett W. Sperry\n                          \t\t Joe Bostic\n\n\t\t     Original Story  \t Ron Smith\n                          \t\t Ed Del Castillo\n\n\t      Lead Game Programmers  \t Joe Bostic\n                          \t\t Barry Green\n                          \t\t Steve Tall\n\n             \t   Game Programmers  \t Bill Randolph\n\t\t\t\t\t Phil Gorrow\n\t\t\t\t\t Maria del Mar McCready Legg\n\n\t       Internet Programmers\t Jeff Brown\n                          \t\t David Aldridge\n                          \t\t Matt Thorn\n\n\t     Translation Programmer\t Victor Grippi\n\n     \t\tTechnical Direction  \t Steve Wetherill\n                          \t\t Eric Wang\n\n               \t          Designers  \t Adam Isgreen\n                          \t\t Michael Lightner\n                          \t\t Erik Yeo\n\n            \t       Lead Artists  \t Chris Demers\n                          \t\t Matthew Hansel\n                          \t\t Joseph B. Hewitt IV\n\n                            Artists  \t David T. Potter\n                          \t\t Damon Redmond\n\t\t\t\t\t Paul Wesberry\n                          \t\t Brian White\n\n              \t         Screenplay  \t Ron Smith\n                          \t\t Adam Isgreen\n                          \t\t John Scott Lewinski\n\n   \t      Video Post Production  \t Felix Kupis\n                          \t\t Kevin Becquet\n\n         Movie Compression Director      Tim C. Fritz\n              Compression Assistant      Patrick Connelly\n\n         \t    Audio Direction  \t Paul S. Mudra\n              \t         Soundtrack  \t Frank Klepacki\n           \t      Sound Effects  \t Dwight K. Okahara\n\n            \t       QA Direction  \t Glenn Sperry\n\n\t\t  Quality Assurance  \t James Adkins\n\t\t\t\t\t John Archer\n\t\t\t\t\t Lloyd Bell\n\t\t\t\t\t Chris Bleven\n\t\t\t\t\t D'Andre Cambell\n\t\t\t\t\t Errol Campbell\n\t\t\t\t\t Phillip Castro\n\t\t\t\t\t Steve Corcoran\n\t\t\t\t\t Kenny Dunne\n\t\t\t\t\t Randy Greenback\n\t\t\t\t\t Abe Hernandez\n\t\t\t\t\t Chris Holloway\n                                         Troy Leonard\n                                         Ben Lublin\n\t\t\t\t\t Levi Luke\n\t\t\t\t\t Isaiah Myers\n\t\t\t\t\t Richard Rasmussen\n\t\t\t\t\t Chris Rubyor\n                                         Robert Scheel\n                                         Albert Springfield\n\t\t\t\t\t Mike Smith\n\t\t\t\t\t Tyler Thackery\n\n              \t         Box Design  \t Matthew Hansel\n                          \t\t Thomas Puckett Inc.\n\n\t\t      Manual Design  \t Victoria Hart\n\n\n\t\tSpecial thanks to all our friends and supporters\n\t\twithin the Virgin empire. Additional thanks to\n\t\tTracy Chapman for a new beginning and Greg\n\t\tHjelstrom for the amazing chronal vortex.\n\n\n\n\n\t\t\t          The Cast\n\n\tAllied Side\n             \t         Von Esling  \t Arthur Roberts\n                            Stavros  \t Barry Kramer\n\t\t    Albert Einstein\t John Milford\n                              Tanya  \t Lynne Litteer\n           \t       Interrogator  \t Dom Magwili\n              \t          Announcer  \t Gwen Castaldi\n\n\n        \t    Allied Soldiers\n\t\t\t     Finale\t Ricky Russell\n                         \t\t Nick Paulos\n                         \t\t Scott Ryan Talley\n\n\t\t\t Commanders\t Joe Bostic\n                         \t\t Chris Demers\n                         \t\t Barry Green\n                         \t\t Matthew Hansel\n                         \t\t Adam Isgreen\n                         \t\t Frank Klepacki\n                         \t\t Mike Lightner\n                         \t\t Bill Randolph\n                         \t\t Philip E. Shelburne\n                         \t\t Eric Wang\n\n\n\n     \tSoviet Side\n\t\t       Josef Stalin\t Eugene Dynarski\n        \t              Kukov  \t Craig Cavanah\n              \t           Gradenko  \t Alan Terry\n                              Nadia  \t Andrea Robinson\n                               Kane  \t Joe Kucan\n\n\n        \t    Soviet Soldiers  \t John Archer\n\t\t\t\t\t Mike Grayford\n\t\t\t\t\t Frank Klepacki\n\t\t\t\t\t Felix Kupis\n\t\t\t\t\t Chris Rubyor\n                         \t\t Erik Yeo\n\n\n\n     \tIngame Voices\n        \t             E.V.A.  \t Martin Alper\n              \t              Tanya  \t Lanae Freeborn\n\t\t   Infantry & Units\t Mike Grayford\n                         \t\t Adam Isgreen\n\t\t\t\t\t Frank Klepacki\n                         \t\t Troy Leonard\n\t\t\t\t\t Dwight Okahara\n                         \t\t Chris Rubyor\n   \t\t\t\t\t Eric Wang\n                                         Erik Yeo\n\n\n\n\n     \tProduction Crew\n\n\t\t\tDirected By\t Joseph D. Kucan\n\n\t\t     Costume Design  \t Christie Moeller\n\n\t\t     Make-up & Hair  \t Cindy Cline\n\n\t\t     Sound Engineer  \t Paul S. Mudra\n\n\t\t            Casting  \t Marilee Lear, C.S.A.\n\n\t\t\t      Video\t Kevin Becquet\n\n\t\t           Lighting  \t Eric Gooch\n\n          Lead Production Assistant      Paul Bastardo\n\n              Production Assistants  \t Rick Appin\n                                  \t Patience Becquet\n\t\t\t\t\t Pat Connelly\n                                  \t Jeff Fillhaber\n                                  \t Richard Rasmussen\n\n               \t        Sfx Make-up  \t Philip E. Shelburne\n\n        Special Footage Courtesy Of      NBC News Archives Films\n                                  \t Fabulous Footage\n\n\n\n\n\n\n\n\n\n\t\t\tCounterstrike Credits\n\n      \t\t Executive Producer  \t Brett W. Sperry\n                           Producer  \t Ed Del Castillo\n\n\t\t\tProgrammers\t Victor Grippi\n\t\t\t\t\t Joe Bostic\n\t\t\t\t\t Steve Tall\n\t\t\t\t\t Maria del Mar McCready Legg\n\n     \t\tTechnical Direction  \t Steve Wetherill\n                          \t\t Eric Wang\n\n\t    Solo Play Map Designers\t Adam Isgreen\n\t\t\t\t\t Michael Lightner\n\t\t\t\t\t Patrick Connelly\n\n\t    Multiplay Map Designers\t Iain McNeil\n\t\t\t\t\t Alex Scarrow\n\t\t\t\t\t Graeme Miller\n\t\t\t\t\t Nigel Berryman\n\t\t\t\t\t Rod Gray\n\t\t\t\t\t Stuart Bailey\n\t\t\t\t\t Mat Tillett\n\t\t\t\t\t Phil Veale\n\t\t\t\t\t Dave Parsons\n\t\t\t\t\t Darren Esp\n\t\t\t\t\t Cameron Strutt\n\t\t\t\t\t Paul Goodwin\n\t\t\t\t\t John McNeil\n\t\t\t\t\t Lee Morse\n\t\t\t\t\t Adam Isgreen\n\t\t\t\t\t Michael Lightner\n\t\t\t\t\t John Archer\n\t\t\t\t\t Patrick Connelly\n\t\t\t\t\t Lloyd Bell\n\t\t\t\t\t D'Andre Campbell\n\t\t\t\t\t Albert Springfield\n\t\t\t\t\t Levi Luke\n\t\t\t\t\t Robert Scheel\n\n            \t            Artists  \t Chris Demers\n                          \t\t Matthew Hansel\n\t\t\t\t\t Shelly Johnson\n\t\t\t\t\t Frank Mendeola\n\n\t\t\t      Video\t Kevin Becquet\n\t\t\t\t\t Patience Becquet\n\n         \t    Audio Direction  \t Paul S. Mudra\n\n\t\t\t Soundtrack  \t Frank Klepacki\n\n\t\t      Sound Effects  \t Dwight K. Okahara\n\n\t\t       QA Direction\t Glenn Sperry\n\n\t\t  Quality Assurance\t John Archer\n\t\t\t\t\t Mike Smith\n\t\t\t\t\t Lloyd Bell\n                                         Troy Leonard\n\t\t\t\t\t Chris Halloway\n\t\t\t\t\t Randy Greenback\n\t\t\t\t\t D'Andre Cambell\n\t\t\t\t\t Errol Campbell\n                                         Albert Springfield\n\t\t  \t\t\t James Adkins\n\t\t\t\t\t Chris Blevens\n\t\t\t\t\t Levi Luke\n\t\t\t\t\t Steve Shockey\n\t\t\t\t\t Isaiah Myers\n                                         Ben Lublin\n\t\t\t\t\t Richard Rasmussen\n                                         Robert Scheel\n\t\t\t\t\t Tom Andrulis\n\t\t\t\t\t Shane Dietrich\n\t\t\t\t\t Brandon Hansen\n\n\n\n\t\tThanks to Westwood's killer marketing staff for\n\t\tall their support, Intelligent Games for creating\n\t\ta bulk of the multiplayer maps, and Brett and\n\t\t         Louis for being born.\n\n\t\tSpecial thanks to the European Marketing teams\n\t\tfor their support, and to the original Red Alert\n\t\tteam for giving us something to build on.\n\n\n\n\n                For the latest news, goodies, and updates,\n                visit our web site at www.westwood.com\n\n\n\n\n\n\n"
  },
  {
    "path": "CODE/ENG/FRE/CONQUER.TXT",
    "content": "# TXT_NONE                \n%3d.%02d\n# TXT_CREDIT_FORMAT\nTemps:%02d:%02d:%02d\n# TXT_TIME_FORMAT_HOURS\nTemps:%02d:%02d\n# TXT_TIME_FORMAT_NO_HOURS\nVente\n# TXT_BUTTON_SELL\nVente structure\n# TXT_SELL\nRparation\n# TXT_BUTTON_REPAIR\nVous :\n# TXT_YOU\nEnnemi :\n# TXT_ENEMY\nBtiments dtruits par\n# TXT_BUILD_DEST\nUnits dtruites par\n# TXT_UNIT_DEST\nMinerai rcolt par\n# TXT_TIB_HARV\nScore: %d\n# TXT_SCORE_1\nOui\n# TXT_YES\nNon\n# TXT_NO\nMission Accomplie\n# TXT_SCENARIO_WON\nMission Echoue\n# TXT_SCENARIO_LOST\nNouvelle partie\n# TXT_START_NEW_GAME\nIntro/Preview\n# TXT_INTRO\nAnnuler\n# TXT_CANCEL\nRocher\n# TXT_ROCK\nCivil\n# TXT_CIVILIAN\nEquipe de confinement\n# TXT_JP\nOK\n# TXT_OK\nArbre\n# TXT_TREE\n\\x011\n# TXT_LEFT\n\\x010\n# TXT_RIGHT\n\\x01E\n# TXT_UP\n\\x01F\n# TXT_DOWN\nEffacer\n# TXT_CLEAR\nEau\n# TXT_WATER\nRoute\n# TXT_ROAD\nPente\n# TXT_SLOPE\nPatch\n# TXT_PATCH\nRivire\n# TXT_RIVER\nCharger Mission\n# TXT_LOAD_MISSION\nSauvegarder Mission\n# TXT_SAVE_MISSION\nEffacer Mission\n# TXT_DELETE_MISSION\nCharger\n# TXT_LOAD_BUTTON\nSauvegarder\n# TXT_SAVE_BUTTON\nEffacer\n# TXT_DELETE_BUTTON\nContrles\n# TXT_GAME_CONTROLS\nSon\n# TXT_SOUND_CONTROLS\nReprendre Mission\n# TXT_RESUME_MISSION\nAffichage\n# TXT_VISUAL_CONTROLS\nAbandonner Mission\n# TXT_QUIT_MISSION\nQuitter le jeu\n# TXT_EXIT_GAME\nOptions\n# TXT_OPTIONS\nDbris humains\n# TXT_SQUISH\nCratre\n# TXT_CRATER\nMarque de brlure\n# TXT_SCORCH\nLuminosit :\n# TXT_BRIGHTNESS\nMusique\n# TXT_MUSIC\nEffets sonores\n# TXT_VOLUME\nTeintes :\n# TXT_TINT\nContraste :\n# TXT_CONTRAST\nVitesse du jeu :\n# TXT_SPEED\nVitesse dfilement :\n# TXT_SCROLLRATE\nCouleur :\n# TXT_COLOR\nRevenir au jeu\n# TXT_RETURN_TO_GAME\nSoldat ennemi\n# TXT_ENEMY_SOLDIER\nVhicule ennemi\n# TXT_ENEMY_VEHICLE\nStructure ennemie\n# TXT_ENEMY_STRUCTURE\nTank lger\n# TXT_LTANK\nTank lourd\n# TXT_MTANK\nTank moyen\n# TXT_MTANK2\nTank Mammouth\n# TXT_HTANK\nMissiles SAM\n# TXT_SAM\nRanger\n# TXT_JEEP\nHlicoptre Chinook\n# TXT_TRANS\nCollecteur minerai\n# TXT_HARVESTER\nArtillerie\n# TXT_ARTY\nMitrailleurs\n# TXT_E1\nGrenadiers\n# TXT_E2\nBazookas\n# TXT_E3\nLance-flammes\n# TXT_E4\nHlicoptre d'assaut\n# TXT_HELI\nHind\n# TXT_ORCA\nVBT\n# TXT_APC\nTour de garde\n# TXT_GUARD_TOWER\nDme radar \n# TXT_COMMAND\nHliport\n# TXT_HELIPAD\nPiste d'atterrissage\n# TXT_AIRSTRIP\nSilo minerai\n# TXT_STORAGE\nChantier de construction\n# TXT_CONST_YARD\nRaffinerie de minerai\n# TXT_REFINERY\nEglise\n# TXT_CIV1\nChez Hans et Gretel\n# TXT_CIV2\nManoir d'Hewitt\n# TXT_CIV3\nMaison de Ricktor\n# TXT_CIV4\nMaison de Gretchin\n# TXT_CIV5\nLa grange\n# TXT_CIV6\nPub Damon\n# TXT_CIV7\nMaison de Fran\n# TXT_CIV8\nUsine d'instruments\n# TXT_CIV9\nFabricant de jouets\n# TXT_CIV10\nMaison de Ludwig\n# TXT_CIV11\nMeules de foin\n# TXT_CIV12\nMeule de foin\n# TXT_CIV13\nChamp de bl\n# TXT_CIV14\nChamp en friche\n# TXT_CIV15\nChamp de mas\n# TXT_CIV16\nChamp de cleri\n# TXT_CIV17\nChamp de pommes de terre\n# TXT_CIV18\nMaison de Sala\n# TXT_CIV20\nMaison d'Abdul\n# TXT_CIV21\nLe Pub Barjo de Pablo\n# TXT_CIV22\nPuits du village\n# TXT_CIV23\nMarchand de chameaux\n# TXT_CIV24\nEglise\n# TXT_CIV25\nMaison d'Ali\n# TXT_CIV26\nTed le Marchand\n# TXT_CIV27\nMaison de Menelik\n# TXT_CIV28\nMaison du pasteur John\n# TXT_CIV29\nPuits du village\n# TXT_CIV30\nHutte du gurisseur\n# TXT_CIV31\nHutte de Rikitikitembo\n# TXT_CIV32\nHutte de Roarke\n# TXT_CIV33\nHutte de Moubasa'\n# TXT_CIV34\nHutte d'Aksoum\n# TXT_CIV35\nHutte de Mambo\n# TXT_CIV36\nLe studio\n# TXT_CIV37\nCentre technologique\n# TXT_CIVMISS\nTourelle\n# TXT_TURRET\nAviso-torpilleur\n# TXT_GUNBOAT\nVhicule de construction mobile\n# TXT_MCV\nCentrale lectrique\n# TXT_POWER\nCentrale lectrique avance\n# TXT_ADVANCED_POWER\nHpital\n# TXT_HOSPITAL\nCaserne\n# TXT_BARRACKS\nPompe\n# TXT_PUMP\nPtrolier\n# TXT_TANKER\nSacs de sable\n# TXT_SANDBAG_WALL\nClture grillage\n# TXT_CYCLONE_WALL\nMur de bton\n# TXT_BRICK_WALL\nClture barbele\n# TXT_BARBWIRE_WALL\nBarrire de bois\n# TXT_WOOD_WALL\nUsine d'armement\n# TXT_WEAPON_FACTORY\nTour de garde avance\n# TXT_AGUARD_TOWER\nLaboratoire biologique\n# TXT_BIO_LAB\nCentre de service\n# TXT_FIX_IT\nContrles\n# TXT_TAB_SIDEBAR\nOptions\n# TXT_TAB_BUTTON_CONTROLS\nBase de donnes\n# TXT_TAB_BUTTON_DATABASE\nTerrain inconnu\n# TXT_SHADOW\nMenu des options\n# TXT_OPTIONS_MENU\nStop\n# TXT_STOP\nLect\n# TXT_PLAY\nAlat.\n# TXT_SHUFFLE\nRpter\n# TXT_REPEAT\nMusique :\n# TXT_MUSIC_VOLUME\nEffets sonores :\n# TXT_SOUND_VOLUME\nOui\n# TXT_ON\nNon\n# TXT_OFF\nJeu Multijoueurs\n# TXT_MULTIPLAYER_GAME\nPas de fichiers disponibles\n# TXT_NO_FILES\nVoulez-vous effacer ce fichier ?\n# TXT_DELETE_SINGLE_FILE\nVoulez-vous effacer %d fichiers ?\n# TXT_DELETE_MULTIPLE_FILES\nDfaut\n# TXT_RESET_MENU\nVoulez-vous abandonner la mission ?\n# TXT_CONFIRM_EXIT\nDescription de la mission\n# TXT_MISSION_DESCRIPTION\nJoe\n# TXT_C1\nBarry\n# TXT_C2\nShelly\n# TXT_C3\nMaria\n# TXT_C4\nKaren\n# TXT_C5\nSteve\n# TXT_C6\nPhil\n# TXT_C7\nDwight\n# TXT_C8\nErik\n# TXT_C9\nProf. Einstein\n# TXT_EINSTEIN\nCour\n# TXT_BIB\nRapide\n# TXT_FASTER\nLent\n# TXT_SLOWER\nAttaque arienne\n# TXT_AIR_STRIKE\nCaisse d'acier\n# TXT_STEEL_CRATE\nCaisse de bois\n# TXT_WOOD_CRATE\nCaisse flottante\n# TXT_WATER_CRATE\nEmplacement du drapeau\n# TXT_FLAG_SPOT\nLecture scnario impossible !\n# TXT_UNABLE_READ_SCENARIO\nErreur de chargement !\n# TXT_ERROR_LOADING_GAME\nSauvegarde obsolte\n# TXT_OBSOLETE_SAVEGAME\nVous devez entrer une description !\n# TXT_MUSTENTER_DESCRIPTION\nErreur de sauvegarde !\n# TXT_ERROR_SAVING_GAME\nEffacer ce fichier ?\n# TXT_DELETE_FILE_QUERY\n[EMPLACEMENT VIDE]\n# TXT_EMPTY_SLOT\nChoix du jeu Multijoueurs\n# TXT_SELECT_MPLAYER_GAME\nModem/Srie\n# TXT_MODEM_SERIAL\nRseau\n# TXT_NETWORK\nInitialisation rseau impossible !\n# TXT_INIT_NET_ERROR\nRejoindre jeu en rseau\n# TXT_JOIN_NETWORK_GAME\nNouveau\n# TXT_NEW\nJoindre\n# TXT_JOIN\nEnvoi Message\n# TXT_SEND_MESSAGE\nVotre nom :\n# TXT_YOUR_NAME\nCamp :\n# TXT_SIDE_COLON\nCouleur :\n# TXT_COLOR_COLON\nParties\n# TXT_GAMES\nJoueurs\n# TXT_PLAYERS\nScnario :\n# TXT_SCENARIO_COLON\n>> NON TROUVE <<\n# TXT_NOT_FOUND\nCrdits :\n# TXT_START_CREDITS_COLON\nBases :\n# TXT_BASES_COLON\nMinerai :\n# TXT_TIBERIUM_COLON\nCaisses :\n# TXT_CRATES_COLON\nJoueurs IA :\n# TXT_AI_PLAYERS_COLON\nDemande refuse.\n# TXT_REQUEST_DENIED\nImpossible de jouer, scnario non trouv.\n# TXT_UNABLE_PLAY_WAAUGH\nAucune partie disponible !\n# TXT_NOTHING_TO_JOIN\nVous devez entrer un nom !\n# TXT_NAME_ERROR\nLes noms identiques ne sont pas autoriss.\n# TXT_DUPENAMES_NOTALLOWED\nLa version de votre jeu est trop ancienne.\n# TXT_YOURGAME_OUTDATED\nVersion du jeu de destination trop ancienne.\n# TXT_DESTGAME_OUTDATED\nPartie de %s\n# TXT_THATGUYS_GAME\n[Partie de %s]\n# TXT_THATGUYS_GAME_BRACKET\nConfiguration du jeu en rseau\n# TXT_NETGAME_SETUP\nRejeter\n# TXT_REJECT\nVous ne pouvez pas vous rejeter vous-mme ! Vous risquez des conflits d'ego !\n# TXT_CANT_REJECT_SELF\nVous devez slectionner un joueur  rejeter.\n# TXT_SELECT_PLAYER_REJECT\nBases\n# TXT_BASES\nCaisses\n# TXT_CRATES\nJoueur IA\n# TXT_AI_PLAYERS\nScnarios\n# TXT_SCENARIOS\nCrdits :\n# TXT_CREDITS_COLON\nUn seul joueur ?\n# TXT_ONLY_ONE\nOops !\n# TXT_OOPS\nPour %s :\n# TXT_TO\nPour tous\n# TXT_TO_ALL\nMessage :\n# TXT_MESSAGE\nPerte de connexion avec %s !\n# TXT_CONNECTION_LOST\n%s a quitt le jeu.\n# TXT_LEFT_GAME\n%s a t vaincu !\n# TXT_PLAYER_DEFEATED\nAttente de connexion...\n# TXT_WAITING_CONNECT\nErreur de connexion ! Vrifiez vos branchements. Nouvel essai de connexion...\n# TXT_NULL_CONNERR_CHECK_CABLES\nErreur de connexion ! Rappel du numro...\n# TXT_MODEM_CONNERR_REDIALING\nErreur de connexion ! Attente de connexion...\n# TXT_MODEM_CONNERR_WAITING\nChoix du jeu en srie\n# TXT_SELECT_SERIAL_GAME\nAppel\n# TXT_DIAL_MODEM\nAttente appel\n# TXT_ANSWER_MODEM\nNull Modem\n# TXT_NULL_MODEM\nParamtres\n# TXT_SETTINGS\nPort :\n# TXT_PORT_COLON\nIRQ :\n# TXT_IRQ_COLON\nBauds :\n# TXT_BAUD_COLON\nChane d'initialisation\n# TXT_INIT_STRING\nChane d'attente d'appel\n# TXT_CWAIT_STRING\nTonalit\n# TXT_TONE_BUTTON\nImpulsions\n# TXT_PULSE_BUTTON\nHte du jeu en srie\n# TXT_HOST_SERIAL_GAME\nAdversaire :\n# TXT_OPPONENT_COLON\nUtilisateur reparti !\n# TXT_USER_SIGNED_OFF\nRejoindre jeu en srie\n# TXT_JOIN_SERIAL_GAME\nRpertoire\n# TXT_PHONE_LIST\nAjouter\n# TXT_ADD\nEditer\n# TXT_EDIT\nAppel\n# TXT_DIAL\nDfaut\n# TXT_DEFAULT\nDfaut\n# TXT_DEFAULT_SETTINGS\nAutres paramtres\n# TXT_CUSTOM_SETTINGS\nRpertoire\n# TXT_PHONE_LISTING\nNom :\n# TXT_NAME_COLON\nNumro :\n# TXT_NUMBER_COLON\nModem non dtect. Vrifiez vos branchements.\n# TXT_UNABLE_FIND_MODEM\nPas de porteuse.\n# TXT_NO_CARRIER\nLigne occupe.\n# TXT_LINE_BUSY\nNumro incorrect.\n# TXT_NUMBER_INVALID\nL'autre systme ne rpond pas !\n# TXT_SYSTEM_NOT_RESPONDING\nMauvaise synchronisation !\n# TXT_OUT_OF_SYNC\nPaquet reu trop tard !\n# TXT_PACKET_TOO_LATE\nL'autre joueur a quitt le jeu.\n# TXT_PLAYER_LEFT_GAME\nDe %s:%s\n# TXT_FROM\nTEMPS :\n# TXT_SCORE_TIME\nCOMMANDEMENT :\n# TXT_SCORE_LEAD\nEFFICACITE :\n# TXT_SCORE_EFFI\nSCORE TOTAL :\n# TXT_SCORE_TOTA\nPERTES :\n# TXT_SCORE_CASU\nNEUTRE :\n# TXT_SCORE_NEUT\nBATIMENTS PERDUS\n# TXT_SCORE_BUIL\nBATIMENTS\n# TXT_SCORE_BUIL1\nPERDUS :\n# TXT_SCORE_BUIL2\nMEILLEURS SCORES\n# TXT_SCORE_TOP\nCREDITS DE FIN :\n# TXT_SCORE_ENDCRED\n%dh %dm\n# TXT_SCORE_TIMEFORMAT1\n%dm\n# TXT_SCORE_TIMEFORMAT2\nAppel...\n# TXT_DIALING\nAppel annul\n# TXT_DIALING_CANCELED\nAttente d'appel...\n# TXT_WAITING_FOR_CALL\nAttente d'appel annule\n# TXT_ANSWERING_CANCELED\nIngnieurs\n# TXT_E6\nEspion\n# TXT_E8\nPas de cble Null Modem connect ! C'est un cble de modem ou en boucle.\n# TXT_MODEM_OR_LOOPBACK\nCarte\n# TXT_MAP\nArbre en fleurs\n# TXT_BLOSSOM_TREE\nBriefing\n# TXT_RESTATE_MISSION\nJoueur IA\n# TXT_COMPUTER\nNombre :\n# TXT_COUNT\nNiveau :\n# TXT_LEVEL\nAdversaire\n# TXT_OPPONENT\nVict.:\n# TXT_KILLS_COLON\nVido\n# TXT_VIDEO\nScientifique\n# TXT_C10\nCapture drapeau\n# TXT_CAPTURE_THE_FLAG\nObjectifs de mission\n# TXT_OBJECTIVE\nMission\n# TXT_MISSION\nPas de sauvegardes disponibles.\n# TXT_NO_SAVES\nBtiment civil\n# TXT_CIVILIAN_BUILDING\nTechnicien\n# TXT_TECHNICIAN\nSauvegarde interdite en mode Multijoueurs.\n# TXT_NO_SAVELOAD\nAgent Spcial 1\n# TXT_DELPHI\nVoulez-vous recommencer cette mission ?\n# TXT_TO_REPLAY\nReconnexion vers %s.\n# TXT_RECONN_TO\nAttendez %02d secondes.\n# TXT_PLEASE_WAIT\nVoulez-vous vous rendre ?\n# TXT_SURRENDER\nCHOIX DE LA TRANSMISSION\n# TXT_SEL_TRANS\nLes sauvegardes ne peuvent pas avoir le mme nom.\n# TXT_GAMENAME_MUSTBE_UNIQUE\nPartie ferme.\n# TXT_GAME_IS_CLOSED\nLes noms doivent tre tous diffrents.\n# TXT_NAME_MUSTBE_UNIQUE\nReconnexion vers %s\n# TXT_RECONNECTING_TO\nAttente de connexions...\n# TXT_WAITING_FOR_CONNECTIONS\nTemps autoris : %02d secondes\n# TXT_TIME_ALLOWED\nAppuyez sur Echap pour annuler.\n# TXT_PRESS_ESC\nDe l'ordinateur : Il ne reste plus que toi et moi!\n# TXT_JUST_YOU_AND_ME\nCapture du drapeau :\n# TXT_CAPTURE_THE_FLAG_COLON\nAgent Spcial 2\n# TXT_CHAN\n%s s'est alli(e) avec %s\n# TXT_HAS_ALLIED\n%s dclare la guerre  %s\n# TXT_AT_WAR\nChoisissez un cible\n# TXT_SEL_TARGET\nAbandonner\n# TXT_RESIGN\nLe minerai pousse trs vite.\n# TXT_TIBERIUM_FAST\nRponse en cours...\n# TXT_ANSWERING\nInitialisation Modem...\n# TXT_INITIALIZING_MODEM\nLes scnarios ne correspondent pas.\n# TXT_SCENARIOS_DO_NOT_MATCH\nProduction d'nergie\n# TXT_POWER_OUTPUT\nProduction d'nergie (faible)\n# TXT_POWER_OUTPUT_LOW\nContinuer\n# TXT_CONTINUE\nSaturation des donnes  envoyer\n# TXT_QUEUE_FULL\n%s a modifi les options de jeu!\n# TXT_SPECIAL_WARNING\nPlacez un CD d'Alerte Rouge dans le lecteur de CD-ROM.\n# TXT_CD_DIALOG_1\nPlacez le CD %d (%s) dans le lecteur de CD-ROM.\n# TXT_CD_DIALOG_2\nAlerte Rouge n'a pas dtect votre lecteur de CD-ROM.\n# TXT_CD_ERROR1\nPas de carte sonore dtecte\n# TXT_NO_SOUND_CARD\nINCONNU\n# TXT_UNKNOWN\n(ancien)\n# TXT_OLD_GAME\nEspace disque insuffisant pour lancer Alerte Rouge.\n# TXT_NO_SPACE\nVous devez disposer de %d Mo sur votre disque dur.\n# TXT_MUST_HAVE_SPACE\nLancez d'abord le programme SETUP.\n# TXT_RUN_SETUP\nAttente adversaire\n# TXT_WAITING_FOR_OPPONENT\nChoisissez l'option 'Paramtres' pour dfinir la configuration par dfaut\n# TXT_SELECT_SETTINGS\nPrison\n# TXT_PRISON\nMission sauvegarde\n# TXT_GAME_WAS_SAVED\nEspace disque insuffisant pour sauvegarde.  Effacez une ancienne sauvegarde pour librer de la place sur le disque dur et ressayez.\n# TXT_SPACE_CANT_SAVE\nPort/Adresse invalide. COM 1-4 OU ADDRESSE\n# TXT_INVALID_PORT_ADDRESS\nparamtres Port et/ou IRQ invalides\n# TXT_INVALID_SETTINGS\nIRQ dj utilis\n# TXT_IRQ_ALREADY_IN_USE\nOui\n# TXT_ABORT\nRecommencer\n# TXT_RESTART\nMission relance. Attendez SVP...\n# TXT_RESTARTING\nChargement de la mission. Attendez SVP...\n# TXT_LOADING\nErreur chane d'initialisation modem\n# TXT_ERROR_IN_INITSTRING\nOmbre\n# TXT_SHADOW_COLON\nMine Anti-Vhicule \n# TXT_AVMINE\nMine Anti-Personnel \n# TXT_APMINE\nNouvelles missions\n# TXT_NEW_MISSIONS\nVoleur\n# TXT_THIEF\nBrouilleur de radar\n# TXT_MRJ\nGnrateur d'ombre\n# TXT_GAP_GENERATOR\nBunker\n# TXT_PILLBOX\nBunker camoufl\n# TXT_CAMOPILLBOX\nChronosphre\n# TXT_CHRONOSPHERE\nRoy. Uni\n# TXT_ENGLAND\nAllemagne\n# TXT_GERMANY\nEspagne\n# TXT_SPAIN\nURSS\n# TXT_USSR\nUkraine\n# TXT_UKRAINE\nGrce\n# TXT_GREECE\nFrance\n# TXT_FRANCE\nTurquie\n# TXT_TURKEY\nRivage\n# TXT_SHORE\nChoisir objet\n# TXT_PLACE_OBJECT\nSous-marin\n# TXT_SS\nContre-torpilleur\n# TXT_DD\nCroiseur\n# TXT_CA\nTransport\n# TXT_TRANSPORT\nAviso-torpilleur\n# TXT_PT\nHall\n# TXT_LOBBY\nParties\n# TXT_CHANNEL_GAMES\nSauvegarder partie...\n# TXT_SAVING_GAME\nLa partie est au complet.\n# TXT_GAME_FULL\nVous devez slectionner une partie!\n# TXT_MUST_SELECT_GAME\n%s joue contre %s\n# TXT_S_PLAYING_S\nSeul l'hte peut modifier cette option.\n# TXT_ONLY_HOST_CAN_MODIFY\nLa partie a t annule.\n# TXT_GAME_CANCELLED\n%s a initi une nouvelle partie.\n# TXT_S_FORMED_NEW_GAME\nLa partie de %s est maintenant en cours.\n# TXT_GAME_NOW_IN_PROGRESS\nBobine de Tesla\n# TXT_TESLA\nGnrateur d'ombre mobile\n# TXT_MGG\nTour lance-flammes\n# TXT_FLAME_TURRET\nCanon Anti-Avion\n# TXT_AAGUN\nNiche\n# TXT_KENNEL\nCentre Technique\n# TXT_SOVIET_TECH\nBombardier\n# TXT_BADGER\nMig\n# TXT_MIG\nYak\n# TXT_YAK\nBarbels\n# TXT_FENCE\nMdecin\n# TXT_MEDIC\nSaboteur\n# TXT_SABOTEUR\nGnral\n# TXT_GENERAL\nTanya\n# TXT_E7\nParabombes\n# TXT_PARA_BOMB\nParachutistes\n# TXT_PARA_INFANTRY\nSaboteur parachutiste\n# TXT_PARA_SABOTEUR\nChantier naval\n# TXT_SHIP_YARD\nPort sous-marin\n# TXT_SUB_PEN\nOptions Scnario\n# TXT_SCENARIO_OPTIONS\nAvion espion\n# TXT_SPY_MISSION\nAvion espion\n# TXT_U2\nChien d'attaque\n# TXT_GUARD_DOG\nInfo Espion\n# TXT_SPY_INFO\nBtiments\n# TXT_BUILDNGS\nUnits\n# TXT_UNITS\nInfanterie\n# TXT_INFANTRY\nAvion\n# TXT_AIRCRAFT\nCamion d'approvisionnement\n# TXT_TRUCK\nModule d'invulnrabilit\n# TXT_INVUL\nRideau de Fer\n# TXT_IRON_CURTAIN\nCentre technique avanc\n# TXT_ADVANCED_TECH\nLance-roquettes V2\n# TXT_V2_LAUNCHER\nPoste de commandement avanc\n# TXT_FORWARD_COM\nBombardeur\n# TXT_DEMOLITIONER\nPoseur de mines\n# TXT_MINE_LAYER\nChantier de construction leurre\n# TXT_FAKE_CONST\nUsine d'armement leurre\n# TXT_FAKE_WEAP\nChantier naval leurre\n# TXT_FAKE_YARD\nPort sous-marin leurre\n# TXT_FAKE_PEN\nDme radar leurre\n# TXT_FAKE_RADAR\nBigfoot\n# TXT_THEME_BIGF\nLa rvolte\n# TXT_THEME_CRUS\nA l'attaque 1\n# TXT_THEME_FAC1\nA l'attaque 2\n# TXT_THEME_FAC2\nMarche de l'enfer\n# TXT_THEME_HELL\nSauve-qui-peut\n# TXT_THEME_RUN1\nLa dbcle\n# TXT_THEME_SMSH\nTranches\n# TXT_THEME_TREN\nLes professionnels\n# TXT_THEME_WORK\nAttente\n# TXT_THEME_AWAIT\nDense\n# TXT_THEME_DENSE_R\nSlection carte\n# TXT_THEME_MAP\nFogger\n# TXT_THEME_FOGGER1A\nBoue\n# TXT_THEME_MUD1A\nRadio 2\n# TXT_THEME_RADIO2\nLaminage\n# TXT_THEME_ROLLOUT\nSerpent\n# TXT_THEME_SNAKE\nExtermination\n# TXT_THEME_TERMINAT\nJumeau\n# TXT_THEME_TWIN\nVecteur\n# TXT_THEME_VECTOR1A\nEquipiers\n# TXT_TEAM_MEMBERS\nPont\n# TXT_BRIDGE\nBaril\n# TXT_BARREL\nAmical\n# TXT_GOODGUY\nEnnemi\n# TXT_BADGUY\nOr\n# TXT_GOLD\nGemmes\n# TXT_GEMS\nFilm titre\n# TXT_TEASER\nFilms\n# TXT_MOVIES\nIntrieur\n# TXT_INTERIOR\nSignal sonar\n# TXT_SONAR_PULSE\nSilo de missiles\n# TXT_MSLO\nSatellite GPS\n# TXT_GPS_SATELLITE\nBombe atomique\n# TXT_NUCLEAR_BOMB\nFacile\n# TXT_EASY\nDifficile\n# TXT_HARD\nNormal\n# TXT_NORMAL\nSlectionnez un niveau de difficult.\nIl sera valable tout au long de votre campagne.\n# TXT_DIFFICULTY\nAllis\n# TXT_ALLIES\nSoviets\n# TXT_SOVIET\nThme Intro\n# TXT_THEME_INTRO\nProgr. ombre\n# TXT_SHADOW_REGROWS\nProgr. minerai\n# TXT_ORE_SPREADS\nMusiques\n# TXT_THEME_SCORE\nInternet\n# TXT_INTERNET\nGlace\n# TXT_ICE\nCaisses\n# TXT_CRATE\nEscarmouche\n# TXT_SKIRMISH\nChoisissez votre camp.\n# TXT_CHOOSE\nMinraux prcieux\n# TXT_MINERALS\nIgnorer\n# TXT_IGNORE\nErreur - le modem ne rpond pas.\n# TXT_ERROR_NO_RESP\nErreur - Le modem n'a pas rpondu  l'activation du code de rsultat.\n# TXT_ERROR_NO_RESCODE\nErreur - Le modem n'a pas rpondu  la chane d'initialisation.\n# TXT_ERROR_NO_INIT\nErreur - Le modem n'a pas rpondu  l'activation des codes de rsultat dtaills.\n# TXT_ERROR_NO_VERB\nErreur - Le modem n'a pas rpondu  la commande du mode 'cho'.\n# TXT_ERROR_NO_ECHO\nErreur - Impossible de dsactiver rponse auto du modem.\n# TXT_ERROR_NO_DISABLE\nErreur - Trop d'erreurs lors de l'initialisation du modem - Interruption.\n# TXT_ERROR_TOO_MANY\nErreur - Le modem a retourn une erreur de paramtrage.\n# TXT_ERROR_ERROR\nErreur - Temps d'attente de connexion dpass.\n# TXT_ERROR_TIMEOUT\nAccompli\n# TXT_ACCOMPLISHED\nCliquez pour continuer\n# TXT_CLICK_CONTINUE\nRception du scnario de l'hte.\n# TXT_RECEIVING_SCENARIO\nEnvoi du scnario aux joueurs  distance.\n# TXT_SENDING_SCENARIO\nErreur - Le modem n'a pas rpondu  la commande de contrle de flux. Votre configuration de Windows peut tre incorrecte.\n# TXT_NO_FLOW_CONTROL_RESPONSE\nErreur - Le modem n'a pas rpondu  la dsactivation du protocole de compression. Votre configuration de Windows peut tre incorrecte.\n# TXT_NO_COMPRESSION_RESPONSE\nErreur - Le modem n'a pas rpondu  la dsactivation du protocole de correction d'erreurs. Votre configuration de Windows peut tre incorrecte.\n# TXT_NO_ERROR_CORRECTION_RESPONSE\nPour jouer  Alerte Rouge via Internet, vous devez tre connect  un serveur Internet et tre inscrit  Planet Westwood.\n# TXT_EXPLAIN_REGISTRATION\nErreur - Impossible d'excuter WChat.\n# TXT_ERROR_UNABLE_TO_RUN_WCHAT\nEnregistrer\n# TXT_REGISTER\nGisement Minerai\n# TXT_ORE_MINE\nAucun modem configur\n# TXT_NO_REGISTERED_MODEM\nDplacement chronoporte\n# TXT_CHRONOSHIFT\nAdresse invalide ou en cours d'utilisation\n# TXT_UNABLE_TO_OPEN_PORT\nPas de tonalit. Assurez-vous que votre modem est connect  la ligne tlphonique et ressayez.\n# TXT_NO_DIAL_TONE\nErreur - L'autre joueur n'a pas ce scnario d'extension.\n# TXT_NO_EXPANSION_SCENARIO\nPatientez SVP...\n# TXT_STAND_BY\nMusique du gnrique de fin\n# TXT_THEME_CREDITS\nPuissance faible: Canon(s) AA neutralis(s)\n# TXT_POWER_AAGUN\nPuissance faible: Bobine(s) de Tesla neutralise(s)\n# TXT_POWER_TESLA\nPuissance Faible\n# TXT_LOW_POWER\nCommandant:\n# TXT_COMMANDER\nParties gagnes:\n# TXT_BATTLES_WON\nFichier de donnes du jeu dtect incompatible. Un fichier de donnes du jeu est peut-tre corrompu.\n# TXT_MISMATCH\nVotre version de jeu ncessite une mise  jour. Vous pouvez tlcharger la dernire mise  jour sur notre site Web : WWW.WESTWOOD.COM.\n#TXT_SCENARIO_ERROR\nConnecting\n# TXT_CONNECTING\nInitialisation du Modem\n# TXT_MODEM_INITIALISATION\nCompression des Donnes\n# TXT_DATA_COMPRESSION\nCorrection d'Erreur\n# TXT_ERROR_CORRECTION\nContrle Matriel du Flux\n# TXT_HARDWARE_FLOW_CONTROL\nAvanc\n# TXT_ADVANCED\nSeconde main\n# TXT_THEME_2ND_HAND\nArazode\n# TXT_THEME_ARAZOID\nRetour  l'envoyeur\n# TXT_THEME_BACKSTAB\nChaos2\n# TXT_THEME_CHAOS2\nFermez-la !\n# TXT_THEME_SHUT_IT\nVisite de courtoisie\n# TXT_THEME_TWINMIX1\nA couvert \n# TXT_THEME_UNDER3\nVR2\n# TXT_THEME_VR2\nL'autre systme ne rpond pas. Voulez-vous tenter une sauvegarde d'urgence ? Tous les joueurs doivent sauvegarder pour que cela fonctionne.\n# TXT_ASK_EMERGENCY_SAVE_NOT_RESPONDING\nL'autre systme a raccroch. Voulez-vous tenter une sauvegarde d'urgence ? Tous les joueurs doivent sauvegarder pour que cela fonctionne.\n# TXT_ASK_EMERGENCY_SAVE_HUNG_UP\nAlerte Rouge n'a pu excuter le programme d'enregistrement. Vous devez installer Westwood Chat  partir du CD d'Alerte Rouge pour vous enregistrer.\n# TXT_NO_REG_APP\nUn joueur de la partie n'a pas son scnario d'extension.\n# TXT_NO_CS_SCENARIOS\nSous-marin MS\n# TXT_MISSILESUB\nElectrocuteur\n# TXT_SHOCKTROOPER\nMcanicien\n# TXT_MECHANIC\nChrono Tank\n# TXT_CHRONOTANK\nTank Tesla\n# TXT_TESLATANK\nTank M.A.D.\n# TXT_MAD\nCamion de dmolition\n# TXT_DEMOTRUCK\nTransport Camlon\n# TXT_PHASETRANSPORT\nMarcages\n# TXT_THEME_BOG\nVolutes\n# TXT_THEME_FLOAT_V2\nTnbres\n# TXT_THEME_GLOOM\nTerrain min\n# TXT_THEME_GRNDWIRE\nMcaniciens 2\n# TXT_THEME_RPT\nBattue\n# TXT_THEME_SEARCH\nTraction\n# TXT_THEME_TRACTION\nChaos\n# TXT_THEME_WASTELND\nHliport Mobile\n# TXT_CARRIER\n\n"
  },
  {
    "path": "CODE/ENG/FRE/CREDITS.TXT",
    "content": "\t\tProducteur Excutif\tBrett W. Sperry\n\n\t\t\t Producteur\tLewis S. Peterson\n\n\t\t\tProgrammeur\tBarry Green\n\n\t\tDirection Technique\tSteve Wetherill, Eric Wang\n\n\tConcepteurs Cartes Jeu Solo\tJohn Archer, Patrick Connelly,\n\t\t\t\t\tAdam Isgreen, Michael Lightner,\n\t\t\t\t\tErik Yeo\n\n    Concepteurs Cartes Multijoueurs\tJohn Archer, Stuart Bailey,\n\t\t\t\t\tNigel Berryman, D'Andre Campbell,\n\t\t\t\t\tValerie Carpentier, Cathi Diet,\n\t\t\t\t\tKeith Ditchburn, Gareth Eke,\n\t\t\t\t\tDarren Esp, Simon Evers, Rod Gray,\n\t\t\t\t\tRandy Greenback, Matthew Howe,\n\t\t\t\t\tLevi Luke, Suzanne Maddison,\n\t\t\t\t\tIain McNeil, Graeme Miller,\n\t\t\t\t\tLee Morse, David Parsons,\n\t\t\t\t\tAlex Scarrow, Robert Scheel,\n\t\t\t\t\tLawrence So, John Sweeney,\n\t\t\t\t\tMatthew Tillett, Phillip Veale \n\n\t\t\t Graphistes\tChris Demers, Matthew Hansel,\n\t\t\t\t\tJoseph B. Hewitt IV\n\n\t\t    Direction Audio\tPaul S. Mudra\n\n\t\t\t    Musique\tFrank Klepacki\n\n\t\t     Effets Sonores\tDwight K. Okahara\n\n\t\t       Direction AQ\tGlenn Sperry\n\n\t\t  Assurance Qualit\tJim Adkins, Lloyd Bell,\n\t\t\t\t\tChris Blevens, D'Andre Campbell,\n\t\t\t\t\tErrol Campbell, Shane Dietrich,\n\t\t\t\t\tRandy Greenback, Jon Hix,\n\t\t\t\t\tMark Laity, Troy Leonard,\n\t\t\t\t\tDeMarlo Lewis, Levi Luke,\n\t\t\t\t\tPatrick Offord,\tRichard Rasmussen,\n\t\t\t\t\tMike Ruppert, Steve Shockey,\n\t\t\t\t\tMike Smith, Albert Springfield\n\n\t  Nouvelles Voix Franaises\tEmmanuel Curtil, Gilbert Lvy\n\n\n\t\t\t\tAlerte Rouge\n\n              Direction de production   Brett W. Sperry\n                           Producteur   Ed Del Castillo\n\n                     Concept original   Brett W. Sperry\n                                        Joe Bostic\n\n                   Histoire originale   Ron Smith\n                                        Ed Del Castillo\n\n              Programmeurs principaux   Joe Bostic\n                                        Barry Green\n                                        Steve Tall\n\n                         Programmeurs   Bill Randolph\n                                        Phil Gorrow\n                                        Maria del Mar McCready Legg\n\n                Programmeurs Internet   Jeff Brown\n                                        David Aldridge\n                                        Matt Thorn\n\t\t\n               Programmeur traduction   Victor Grippi\n\n                  Direction technique   Steve Wetherill\n                                        Eric Wang\n\n                            Crateurs   Brett W. Sperry\n                                        Adam Isgreen\n                                        Michael Lightner\n                                        Erik Yeo\n\n                  Artistes principaux   Chris Demers\n                                        Matthew Hansel\n                                        Joseph B. Hewitt IV\n\n                             Artistes   Paul Wesberry\n                                        David T. Potter\n                                        Damon Redmond\n                                        Brian White\n\n                             Scnario   Ron Smith\n                                        Adam Isgreen\n                                        John Scott Lewinski\n                      \n                     Post Prod. Vido   Felix Kupis\n                                        Kevin Becquet\n\n                    Compression Vido   Tim C. Fritz\n\n              Asst. Compression Vido   Patrick Connelly\n                                                        \n                     Direction du son   Paul S. Mudra\n                              Musique   Frank Klepacki\n                       Effets sonores   Dwight K. Okahara\n\n                      Direction du CQ   Glenn Sperry\n\n                     Contrle-qualit   Lloyd Bell\n                                        Kenny Dunne\n                                        Mike Smith\n                                        John Archer\n                                        Chris Rubyor\n                                        D'Andre Cambell\n                                        Robert Scheel\n                                        Chris Bleven\n                                        Levi Luke\n                                        Errol Campbell\n                                        Abe Hernandez\n                                        James Adkins\n                                        Richard Rasmussen\n                                        Troy Leonard\n                                        Ben Lublin\n                                        Chris Holloway\n                                        Isaiah Myers\n                                        Phillip Castro\n                                        Albert Springfield\n                                        Randy Greenback\n                                        Tyler Thackery\n\n                 Conception du manuel   Victoria Hart\n\n\n\n       Un grand merci  Danielle Woodyatt, Rosemarie Dalton,\n        et aux quipes Virgin en Europe. Egalement un grand merci \n        Tracy Chapman pour sa chanson \"a new beginning\".\n\n\n\n\n                                   Les  acteurs\n\n\n                                  camp  Allis\n\n                           Von Esling   Arthur Roberts\n                              Stavros   Barry Kramer\n                                Tanya   Lynne Litteer\n                        Interrogateur   Dom Magwili\n                            Annonceur   Gwen Castaldi\n\n\t\t...et John Milford pour Albert Einstein\n\n\n                        Soldats allis   Ricky Russell\n\t\t\t\t\t Nick Paulos\n\t\t\t\t\t Scott Ryan Talley\n\t\t\t\t\t Joe Bostic\n\t\t\t\t\t Chris Demers\n\t\t\t\t\t Barry Green\n\t\t\t\t\t Matthew Hansel\n\t\t\t\t\t Adam Isgreen\n\t\t\t\t\t Frank Klepacki\n\t\t\t\t\t Mike Lightner\n\t\t\t\t\t Bill Randolph\n\t\t\t\t\t Philip E. Shelburne\n\t\t\t\t\t Eric Wang\n\n\n\n                                  camp Soviets\n\n                                 Kukov   Craig Cavanah\n                              Gradenko   Alan Terry\n                                 Nadia   Andrea Robinson\n                                  Kane   Joe Kucan\n\n\t\t...et Eugene Dynarski pour Josef Stalin\n\n\n                   Soldats sovitiques   Felix Kupis\n\t\t\t\t\t Erik Yeo\n                                         John Archer\n                                         Mike Grayford\n                                         Chris Rubyor\n\n\n                                Voix dans le jeu\n\n                                E.V.A.   Martin Alper\n                                 Tanya   Lanae Freeborn\n                            Infanterie   Mike Grayford\n\t\t\t\t\t Adam Isgreen\n                                         Troy Leonard\n\t\t\t\t\t Chris Rubyor\n                                         Dwight Okahara\n                                         Frank Klepacki\n                                         Eric Wang\n                                         \n                               Equipe de production\n\n\n                           Ralisation   Joseph D. Kucan\n\n               Conception des costumes   Christie Moeller\n\n                 Maquillage & Coiffure   Cindy Cline\n\n                      Ingnieur du son   Paul S. Mudra\n\n                               Casting   Marilee Lear, C.S.A.\n\n                                 Vido   Kevin Becquet\n\n                             Eclairage   Eric Gooch\n                               \n                             Production principale\n\n                     Premier Assistant   Paul Bastardo\n\n              Assistants de Production   Pat Connelly\n\t\t\t\t\t Richard Rasmussen\n\t\t\t\t\t Rick Appin\n\t\t\t\t\t Jeff Fillhaber\n\t\t\t\t\t Patience Becquet\n                                                                  \n                        Maquillage Sfx   Philip E. Shelburne\n                                 \n\n                             Squences spciales\n\n                  Avec la permission de NBC News Archives Films\n                               Fabulous Footage\n\n\n\n              \n              Pour obtenir les dernires informations, mises  jour\n              et plein d'autres surprises, visitez notre site Web :\n                               www.westwood.com\n\n\n\n\n\n"
  },
  {
    "path": "CODE/ENG/GER/CONQUER.TXT",
    "content": "# TXT_NONE\n%3d.%02d\n# TXT_CREDIT_FORMAT\nZeit: %02d:%02d:%02d\n# TXT_TIME_FORMAT_HOURS\nZeit: %02d:%02d\n# TXT_TIME_FORMAT_NO_HOURS\nVerkaufen\n# TXT_BUTTON_SELL\nVerkaufen \n# TXT_SELL\nReparieren\n# TXT_BUTTON_REPAIR\nSie:\n# TXT_YOU\nGegner:\n# TXT_ENEMY\nGebude vernichtet durch \n# TXT_BUILD_DEST\nEinheiten zerstrt durch \n# TXT_UNIT_DEST\nErz gesammelt durch \n# TXT_TIB_HARV\nPunkte: %d\n# TXT_SCORE_1\nJa\n# TXT_YES\nNein\n# TXT_NO\nEinsatz erfolgreich \n# TXT_SCENARIO_WON\nEinsatz fehlgeschlagen\n# TXT_SCENARIO_LOST\nNeues Spiel starten \n# TXT_START_NEW_GAME\nVorschau & Intro\n# TXT_INTRO\nZurck\n# TXT_CANCEL\nFelsen\n# TXT_ROCK\nTechnobot\n# TXT_CIVILIAN\nEntseuchungstrupp \n# TXT_JP\nOk\n# TXT_OK\nBaum\n# TXT_TREE\n\\x011\n# TXT_LEFT\n\\x010\n# TXT_RIGHT\n\\x01E\n# TXT_UP\n\\x01F\n# TXT_DOWN\nFrei\n# TXT_CLEAR\nWasser\n# TXT_WATER\nStrasse\n# TXT_ROAD\nHgel\n# TXT_SLOPE\nSchlamm\n# TXT_PATCH\nFluss\n# TXT_RIVER\nEinsatz laden \n# TXT_LOAD_MISSION\nEinsatz sichern \n# TXT_SAVE_MISSION\nEinsatz lschen \n# TXT_DELETE_MISSION\nLaden\n# TXT_LOAD_BUTTON\nSichern\n# TXT_SAVE_BUTTON\nLschen\n# TXT_DELETE_BUTTON\nSpielsteuerung \n# TXT_GAME_CONTROLS\nSoundsteuerung \n# TXT_SOUND_CONTROLS\nZurck\n# TXT_RESUME_MISSION\nOptische Steuerung \n# TXT_VISUAL_CONTROLS\nEinsatz abbrechen \n# TXT_QUIT_MISSION\nSpiel verlassen \n# TXT_EXIT_GAME\nOptionen\n# TXT_OPTIONS\nberreste \n# TXT_SQUISH\nKrater\n# TXT_CRATER\nBrandspuren \n# TXT_SCORCH\nHelligkeit:\n# TXT_BRIGHTNESS\nMusiklautstrke \n# TXT_MUSIC\nGeruschlautstrke \n# TXT_VOLUME\nTnung:\n# TXT_TINT\nKontrast:\n# TXT_CONTRAST\nSpielgeschwindigkeit\n# TXT_SPEED\nScrollgeschwindigkeit:\n# TXT_SCROLLRATE\nFarbe:\n# TXT_COLOR\nZurck zum Spiel \n# TXT_RETURN_TO_GAME\nGegnerischer Cyborg \n# TXT_ENEMY_SOLDIER\nGegnerisches Fahrzeug \n# TXT_ENEMY_VEHICLE\nGegnerisches Gebude \n# TXT_ENEMY_STRUCTURE\nLeichter Panzer \n# TXT_LTANK\nSchwerer Panzer \n# TXT_MTANK\nKampfpanzer \n# TXT_MTANK2\nMammutpanzer \n# TXT_HTANK\nFlak-Stellung \n# TXT_SAM\nRanger 4WD Gelndewagen\n# TXT_JEEP\nHelitrans \n# TXT_TRANS\nErztransporter \n# TXT_HARVESTER\nArtillerie\n# TXT_ARTY\nCyborg \"Schtze\" \n# TXT_E1\nCyborg \"Grenadier\"\n# TXT_E2\nCyborg \"Rak-Zero\"\n# TXT_E3\nCyborg \"Flammenwerfer\"\n# TXT_E4\nKampfhelikopter\n# TXT_HELI\nHind-Hubschrauber\n# TXT_ORCA\nBMT\n# TXT_APC\nWachturm\n# TXT_GUARD_TOWER\nRadar\n# TXT_COMMAND\nHeliport\n# TXT_HELIPAD\nFlugfeld\n# TXT_AIRSTRIP\nErz-Silo\n# TXT_STORAGE\nBauhof\n# TXT_CONST_YARD\nErz-Raffinerie\n# TXT_REFINERY\nKirche\n# TXT_CIV1\nSchmidts Wohnung\n# TXT_CIV2\nAnwesen der Hewitts\n# TXT_CIV3\nHaus von Kerstin \n# TXT_CIV4\nBastis Zuhause\n# TXT_CIV5\nDocs Scheune\n# TXT_CIV6\nDamons Kneipe\n# TXT_CIV7\nDie Farm\n# TXT_CIV8\nMusikfabrik\n# TXT_CIV9\nSpielzeugladen\n# TXT_CIV10\nLudwigs Haus\n# TXT_CIV11\nHeustapel\n# TXT_CIV12\nHeustapel \n# TXT_CIV13\nWeizenfeld\n# TXT_CIV14\nBrachland\n# TXT_CIV15\nMaisfeld\n# TXT_CIV16\nSelleriefelder\n# TXT_CIV17\nKartoffelfeld\n# TXT_CIV18\nSalas Haus\n# TXT_CIV20\nAbduls Haus\n# TXT_CIV21\nPablos Verrufene Pinte\n# TXT_CIV22\nDorfbrunnen\n# TXT_CIV23\nKamelhndler\n# TXT_CIV24\nKirche\n# TXT_CIV25\nAlis Haus\n# TXT_CIV26\nKrmer Ted\n# TXT_CIV27\nMeneliks Heim\n# TXT_CIV28\nPrestor Johns Haus\n# TXT_CIV29\nSchpfbrunnen\n# TXT_CIV30\nHtte des Medizinmanns\n# TXT_CIV31\nRikitikitembos Htte\n# TXT_CIV32\nRoarkes Htte\n# TXT_CIV33\nMubasas Htte\n# TXT_CIV34\nAksums Htte\n# TXT_CIV35\nMambos Htte\n# TXT_CIV36\nDas Studio\n# TXT_CIV37\nTechnologiezentrum\n# TXT_CIVMISS\nGeschtzturm\n# TXT_TURRET\nRak-Kreuzer\n# TXT_GUNBOAT\nMobiles Baufahrzeug \n# TXT_MCV\nKraftwerk\n# TXT_POWER\nGrosskraftwerk\t\n# TXT_ADVANCED_POWER\nKrankenhaus\n# TXT_HOSPITAL\nCyborgfabrik\n# TXT_BARRACKS\nlfrderpumpe \n# TXT_PUMP\nltanker \n# TXT_TANKER\nSandsack-Barriere\n# TXT_SANDBAG_WALL\nMaschendrahtzaun\n# TXT_CYCLONE_WALL\nBetonmauer\n# TXT_BRICK_WALL\nStacheldrahtzaun\n# TXT_BARBWIRE_WALL\nLattenzaun\n# TXT_WOOD_WALL\nWaffenfabrik\n# TXT_WEAPON_FACTORY\nBefestigungsturm\n# TXT_AGUARD_TOWER\nBio-Forschungslabor\n# TXT_BIO_LAB\nWerkstatt\n# TXT_FIX_IT\nSeitenmen\n# TXT_TAB_SIDEBAR\nOptionen\n# TXT_TAB_BUTTON_CONTROLS\nDatenbank\n# TXT_TAB_BUTTON_DATABASE\nUnbekanntes Terrain\n# TXT_SHADOW\nOptionen-Men\n# TXT_OPTIONS_MENU\nSTOP\n# TXT_STOP\nSPIEL\n# TXT_PLAY\nZUFALL\n# TXT_SHUFFLE\nENDLOS\n# TXT_REPEAT\nMusiklautstrke:\n# TXT_MUSIC_VOLUME\nGeruschlautstrke:\n# TXT_SOUND_VOLUME\nAn\n# TXT_ON\nAus \n# TXT_OFF\nMehrspieler-Modus\n# TXT_MULTIPLAYER_GAME\nKeine Dateien verfgbar\n# TXT_NO_FILES\nWollen Sie diese Datei lschen?\n# TXT_DELETE_SINGLE_FILE\nWollen Sie %d Dateien lschen?\n# TXT_DELETE_MULTIPLE_FILES\nStandardwerte\n# TXT_RESET_MENU\nWollen Sie den Einsatz abbrechen?\n# TXT_CONFIRM_EXIT\nEinsatzbeschreibung \n# TXT_MISSION_DESCRIPTION\nJoe\n# TXT_C1\nBarry\n# TXT_C2\nShelly\n# TXT_C3\nMaria\n# TXT_C4\nKaren\n# TXT_C5\nSteve\n# TXT_C6\nPhil\n# TXT_C7\nDwight\n# TXT_C8\nErik\n# TXT_C9\nProf. Einstein\n# TXT_EINSTEIN\nStrasse\n# TXT_BIB\nSchnell\n# TXT_FASTER\nLangsam\n# TXT_SLOWER\nLuftangriff\n# TXT_AIR_STRIKE\nStahlbehlter \n# TXT_STEEL_CRATE\nHolzkiste \n# TXT_WOOD_CRATE\nWasserbehlter \n# TXT_WATER_CRATE\nFlagge \n# TXT_FLAG_SPOT\nKann Szenario nicht lesen!\n# TXT_UNABLE_READ_SCENARIO\nFehler beim Laden des Spieles!\n# TXT_ERROR_LOADING_GAME\nberholter gespeicherter Spielstand.\n# TXT_OBSOLETE_SAVEGAME\nSie mssen eine Beschreibung eingeben!\n# TXT_MUSTENTER_DESCRIPTION\nFehler beim Sichern des Spieles!\n# TXT_ERROR_SAVING_GAME\nDiese Datei lschen?\n# TXT_DELETE_FILE_QUERY\n[NOCH FREI]\n# TXT_EMPTY_SLOT\nMehrspielermodus whlen\n# TXT_SELECT_MPLAYER_GAME\nModem/Seriell\n# TXT_MODEM_SERIAL\nNetzwerk\n# TXT_NETWORK\nKann Netzwerk nicht initialisieren!\n# TXT_INIT_NET_ERROR\nIm Netzwerk mitspielen\n# TXT_JOIN_NETWORK_GAME\nNeu\n# TXT_NEW\nDazu\n# TXT_JOIN\nNachricht senden\n# TXT_SEND_MESSAGE\nIhr  Name:\n# TXT_YOUR_NAME\nSeite:\n# TXT_SIDE_COLON\nFarbe:\n# TXT_COLOR_COLON\nSpielrunden\n# TXT_GAMES\nSpieler\n# TXT_PLAYERS\nSzenario:\n# TXT_SCENARIO_COLON\n>> NICHT GEFUNDEN <<\n# TXT_NOT_FOUND\nGeld beim Spielstart:\n# TXT_START_CREDITS_COLON\nSttzpunkte:\n# TXT_BASES_COLON\nErz:\n# TXT_TIBERIUM_COLON\nKisten:\n# TXT_CRATES_COLON\nKI-Spieler:\n# TXT_AI_PLAYERS_COLON\nAnfrage wurde abgelehnt.\n# TXT_REQUEST_DENIED\nKann nicht starten; Szenario nicht gefunden.\n# TXT_UNABLE_PLAY_WAAUGH\nNiemand da zum Mitspielen!\n# TXT_NOTHING_TO_JOIN\nSie mssen einen Namen eingeben!\n# TXT_NAME_ERROR\nDoppelte Namen sind nicht erlaubt.\n# TXT_DUPENAMES_NOTALLOWED\nIhre Spielversion ist zu alt und berholt.\n# TXT_YOURGAME_OUTDATED\nGegnerische Spielversion ist zu alt und berholt.\n# TXT_DESTGAME_OUTDATED\nDas Spiel von %s\n# TXT_THATGUYS_GAME\n[Das Spiel von %s]\n# TXT_THATGUYS_GAME_BRACKET\nNetzwerk-Spieleinstellungen\n# TXT_NETGAME_SETUP\nAblehnen\n# TXT_REJECT\nHe, Du kannst Dich doch nicht selbst ablehnen! Msstest Du doch langsam wissen... \n# TXT_CANT_REJECT_SELF\nSie mssen schon aussuchen, wen Sie ablehnen wollen...\n# TXT_SELECT_PLAYER_REJECT\nSttzpunkte\n# TXT_BASES\nKisten\n# TXT_CRATES\nKI-Spieler \n# TXT_AI_PLAYERS\nSzenarien\n# TXT_SCENARIOS\nGeld:\n# TXT_CREDITS_COLON\nNur ein einsamer Spieler?\n# TXT_ONLY_ONE\nUuups!\n# TXT_OOPS\nAn %s: \n# TXT_TO\nAn alle: \n# TXT_TO_ALL\nNachricht: \n# TXT_MESSAGE\nVerbindung mit %s abgebrochen!\n# TXT_CONNECTION_LOST\n%s ist aus dem Spiel ausgestiegen.\n# TXT_LEFT_GAME\n%s wurde besiegt!\n# TXT_PLAYER_DEFEATED\nWarte auf Verbindung...\n# TXT_WAITING_CONNECT\nVerbindungsfehler!\\rBitte Kabel berprfen.\\rVersuche neue Verbindung...\n# TXT_NULL_CONNERR_CHECK_CABLES\nVerbindungsabbruch!\\rWhle neu an...\n# TXT_MODEM_CONNERR_REDIALING\nVerbindungsabbruch!\\rWarte auf Anruf...\n# TXT_MODEM_CONNERR_WAITING\nWhle seriellen Modus\n# TXT_SELECT_SERIAL_GAME\nAnrufen\n# TXT_DIAL_MODEM\nAnruf annehmen\n# TXT_ANSWER_MODEM\nNull-Modem\n# TXT_NULL_MODEM\nEinstellungen\n# TXT_SETTINGS\nPort:\n# TXT_PORT_COLON\nIRQ:\n# TXT_IRQ_COLON\nBaud:\n# TXT_BAUD_COLON\nInit.-Sequenz:\n# TXT_INIT_STRING\n\"Call Waiting\"-Sequenz:\n# TXT_CWAIT_STRING\nTonwahl\n# TXT_TONE_BUTTON\nImpulswahl\n# TXT_PULSE_BUTTON\nSerielles Spiel - Host\n# TXT_HOST_SERIAL_GAME\nGegner:\n# TXT_OPPONENT_COLON\nUser hat sich abgemeldet!\n# TXT_USER_SIGNED_OFF\nSerielles Spiel - Mitspieler\n# TXT_JOIN_SERIAL_GAME\nTelefonbuch\n# TXT_PHONE_LIST\nDazu\n# TXT_ADD\nndern\n# TXT_EDIT\nWhlen\n# TXT_DIAL\nStandard\n# TXT_DEFAULT\nStandardeinstellungen\n# TXT_DEFAULT_SETTINGS\nEigene Einstellungen\n# TXT_CUSTOM_SETTINGS\nTelefonbuch-Eintrag\n# TXT_PHONE_LISTING\nName:\n# TXT_NAME_COLON\nNummer:\n# TXT_NUMBER_COLON\nKann Modem nicht finden.\\rBitte Netzanschluss und Kabel berprfen.\n# TXT_UNABLE_FIND_MODEM\nKein Trgersignal.\n# TXT_NO_CARRIER\nBesetzt.\n# TXT_LINE_BUSY\nUngltige Nummer.\n# TXT_NUMBER_INVALID\nDer andere Rechner antwortet nicht!\n# TXT_SYSTEM_NOT_RESPONDING\nDas Spiel luft nicht mehr synchron!\n# TXT_OUT_OF_SYNC\nDatenpaket zu spt angekommen!\n# TXT_PACKET_TOO_LATE\nDer andere Spieler hat das Spiel beendet.\n# TXT_PLAYER_LEFT_GAME\nVon %s: %s\n# TXT_FROM\nZEIT:\n# TXT_SCORE_TIME\nFHRUNG:\n# TXT_SCORE_LEAD\nEFFIZIENZ:\n# TXT_SCORE_EFFI\nGESAMTPUNKTE:\n# TXT_SCORE_TOTA\nVERLUSTE:\n# TXT_SCORE_CASU\nNEUTRAL:\n# TXT_SCORE_NEUT\nGEBUDE VERLOREN\n# TXT_SCORE_BUIL\nGEBUDE\n# TXT_SCORE_BUIL1\nVERLOREN:\n# TXT_SCORE_BUIL2\nDIE BESTEN\n# TXT_SCORE_TOP\nGELD BEI SPIELENDE:\n# TXT_SCORE_ENDCRED\n%ds %dm\n# TXT_SCORE_TIMEFORMAT1\n%dm\n# TXT_SCORE_TIMEFORMAT2\nWhle an...\n# TXT_DIALING\nAnwahl abgebrochen\n# TXT_DIALING_CANCELED\nWarte auf Anruf...\n# TXT_WAITING_FOR_CALL\nAnnehmen abgebrochen\n# TXT_ANSWERING_CANCELED\nInvasor \n# TXT_E6\nSpion\n# TXT_E8\nKein Nullmodem-Kabel angeschlossen! Das ist ein Modem- oder Schleifenkabel.\n# TXT_MODEM_OR_LOOPBACK\nKarte\n# TXT_MAP\nBltenbaum \n# TXT_BLOSSOM_TREE\nEinsatzziel\n# TXT_RESTATE_MISSION\nComputer\n# TXT_COMPUTER\nEinheiten:\n# TXT_COUNT\nTech.-Stufe:\n# TXT_LEVEL\nGegner\n# TXT_OPPONENT\nZerstrt:\n# TXT_KILLS_COLON\nVideo\n# TXT_VIDEO\nForscher\n# TXT_C10\nErobere die Flagge \n# TXT_CAPTURE_THE_FLAG\nEinsatzziel \n# TXT_OBJECTIVE\nEinsatz\n# TXT_MISSION\nKeine gespeicherten Spielstnde! \n# TXT_NO_SAVES\nGebude \n# TXT_CIVILIAN_BUILDING\nTechnobot\n# TXT_TECHNICIAN\nIm Mehrspielermodus ist kein Zugriff auf gespeicherte Spielstnde gestattet.\n# TXT_NO_SAVELOAD\nSpezialagent\n# TXT_DELPHI\nWollen Sie diesen Einsatz neu beginnen? \n# TXT_TO_REPLAY\nNeue Verbindung mit %s.\n# TXT_RECONN_TO\nBitte warten Sie %02d Sekunden.\n# TXT_PLEASE_WAIT\nWollen Sie etwa kapitulieren? \n# TXT_SURRENDER\nNachricht whlen \n# TXT_SEL_TRANS\nDer Spielname darf nur einmal vorkommen. \n# TXT_GAMENAME_MUSTBE_UNIQUE\nDas Spiel ist geschlossen. \n# TXT_GAME_IS_CLOSED\nIhr Name darf nur einmal vorkommen. \n# TXT_NAME_MUSTBE_UNIQUE\nNeue Verbindung mit %s\n# TXT_RECONNECTING_TO\nWarte auf Verbindungen...\n# TXT_WAITING_FOR_CONNECTIONS\nErlaubte Wartezeit: %02d Sekunden\n# TXT_TIME_ALLOWED\nESC drcken, um abzubrechen\n# TXT_PRESS_ESC\nVom Rechner: Jetzt gibt's nur noch uns beide! \n# TXT_JUST_YOU_AND_ME\nErobere die Flagge:\n# TXT_CAPTURE_THE_FLAG_COLON\nSpezialagent\n# TXT_CHAN\n%s hat sich mit %s verbndet\n# TXT_HAS_ALLIED\n%s erklrt %s den Krieg.\n# TXT_AT_WAR\nZiel whlen \n# TXT_SEL_TARGET\nAufgeben \n# TXT_RESIGN\nErz wchst schnell\n# TXT_TIBERIUM_FAST\nAntworte...\n# TXT_ANSWERING\nInitialisiere Modem...\n# TXT_INITIALIZING_MODEM\nSzenarien stimmen nicht berein. \n# TXT_SCENARIOS_DO_NOT_MATCH\nEnergieleistung \n# TXT_POWER_OUTPUT\nEnergieleistung (niedrig)\n# TXT_POWER_OUTPUT_LOW\nWeiter\n# TXT_CONTINUE\nDaten-Warteschlange zu voll \n# TXT_QUEUE_FULL\n%s hat die Spieloptionen gendert!\n# TXT_SPECIAL_WARNING\nBitte legen Sie eine 'Alarmstufe Rot'-CD in das CD-ROM-Laufwerk. \n# TXT_CD_DIALOG_1\nBitte legen Sie die CD %d (%s) in das CD-ROM-Laufwerk. \n# TXT_CD_DIALOG_2\nAlarmstufe Rot kann Ihr CD-ROM-Laufwerk nicht finden.\n# TXT_CD_ERROR1\nKeine Soundkarte entdeckt \n# TXT_NO_SOUND_CARD\nUNBEKANNT\n# TXT_UNKNOWN\n(berholt)\n# TXT_OLD_GAME\nZuwenig Festplattenplatz fr Alarmstufe Rot.\n# TXT_NO_SPACE\nSie brauchen %d Megabytes freien Festplattenplatz.\n# TXT_MUST_HAVE_SPACE\nStarten Sie erst das SETUP-Programm.\n# TXT_RUN_SETUP\nWarte auf Gegner \n# TXT_WAITING_FOR_OPPONENT\nBitte whlen Sie 'Einstellungen', um die Standard-Konfiguration einzustellen. \n# TXT_SELECT_SETTINGS\nGefngnis\n# TXT_PRISON\nEinsatz gespeichert \n# TXT_GAME_WAS_SAVED\nZuwenig Festplattenplatz zum Speichern des Spielstandes. Bitte einen frher gesicherten Spielstand lschen, um Platz freizumachen, und erneut versuchen. \n# TXT_SPACE_CANT_SAVE\nPort/Adresse ungltig. COM 1-4 ODER ADRESSE\n# TXT_INVALID_PORT_ADDRESS\nPort und/oder IRQ-Einstellung ungltig. \n# TXT_INVALID_SETTINGS\nIRQ bereits belegt \n# TXT_IRQ_ALREADY_IN_USE\nAbbruch\n# TXT_ABORT\nNeustart\n# TXT_RESTART\nEinsatz startet neu. Bitte warten...\n# TXT_RESTARTING\nEinsatz wird geladen. Bitte warten...\n# TXT_LOADING\nFehler in der Init-Sequenz \n# TXT_ERROR_IN_INITSTRING\nSchatten:\n# TXT_SHADOW_COLON\nPanzermine \n# TXT_AVMINE\nTretmine \n# TXT_APMINE\nNeue Einstze \n# TXT_NEW_MISSIONS\nD.I.E.B.-Einheit\n# TXT_THIEF\nRadarstrgert \n# TXT_MRJ\nSchattengenerator\n# TXT_GAP_GENERATOR\nBunker\n# TXT_PILLBOX\nTarnbunker \n# TXT_CAMOPILLBOX\nChronosphre\n# TXT_CHRONOSPHERE\nEngland\n# TXT_ENGLAND\nDeutschland\n# TXT_GERMANY\nSpanien\n# TXT_SPAIN\nSowjetunion \n# TXT_USSR\nUkraine\n# TXT_UKRAINE\nGriechenland\n# TXT_GREECE\nFrankreich\n# TXT_FRANCE\nTrkei\n# TXT_TURKEY\nUfer\n# TXT_SHORE\nGegenstand auswhlen \n# TXT_PLACE_OBJECT\nU-Boot\n# TXT_SS\nZerstrer\n# TXT_DD\nSchlachtkreuzer\n# TXT_CA\nTransporter\n# TXT_TRANSPORT\nKanonenboot \n# TXT_PT\nLobby\n# TXT_LOBBY\nSpiele\n# TXT_CHANNEL_GAMES\nSpiel sichern...\n# TXT_SAVING_GAME\nSpiel ist voll.\n# TXT_GAME_FULL\nSie mssen ein Spiel auswhlen! \n# TXT_MUST_SELECT_GAME\n%s spielt %s\n# TXT_S_PLAYING_S\nNur der Spielleiter kann diese Option ndern. \n# TXT_ONLY_HOST_CAN_MODIFY\nSpiel wurde abgebrochen. \n# TXT_GAME_CANCELLED\n%s hat ein neues Spiel erffnet.\n# TXT_S_FORMED_NEW_GAME\nDas Spiel von %s luft jetzt.\n# TXT_GAME_NOW_IN_PROGRESS\nTeslaspule \n# TXT_TESLA\nMobiler Schattengenerator \n# TXT_MGG\nFlammenturm \n# TXT_FLAME_TURRET\nFlak \n# TXT_AAGUN\nZwinger\n# TXT_KENNEL\nTechnologiezentrum \n# TXT_SOVIET_TECH\nLufttransporter\n# TXT_BADGER\nMiG-Jagdbomber \n# TXT_MIG\nYak-Angriffsjger \n# TXT_YAK\nStacheldraht \n# TXT_FENCE\nMechanobot \n# TXT_MEDIC\nSaboteur\n# TXT_SABOTEUR\nGeneral\n# TXT_GENERAL\nTanya\n# TXT_E7\nFallschirmbomben\n# TXT_PARA_BOMB\nFallschirmtruppen\n# TXT_PARA_INFANTRY\nFallschirm-Saboteur \n# TXT_PARA_SABOTEUR\nWerft \n# TXT_SHIP_YARD\nU-Boot-Werft \n# TXT_SUB_PEN\nSzenario-Optionen\n# TXT_SCENARIO_OPTIONS\nSpionageflugzeug \n# TXT_SPY_MISSION\nSpionageflugzeug \n# TXT_U2\nTerminator-Wachhund \n# TXT_GUARD_DOG\nSpionage-Info \n# TXT_SPY_INFO\nGebude\n# TXT_BUILDNGS\nEinheiten\n# TXT_UNITS\nInfantrie-Cyborgs\n# TXT_INFANTRY\nFlugzeuge\n# TXT_AIRCRAFT\nNachschub-Lkw \n# TXT_TRUCK\nUnverwundbarkeitsschirm \n# TXT_INVUL\nEiserner Vorhang \n# TXT_IRON_CURTAIN\nTechnologiezentrum \n# TXT_ADVANCED_TECH\nV2-Raketenwerfer\n# TXT_V2_LAUNCHER\nKommandoposten \n# TXT_FORWARD_COM\nSprengmeister\n# TXT_DEMOLITIONER\nMinenleger \n# TXT_MINE_LAYER\nBauhof-Attrappe \n# TXT_FAKE_CONST\nWaffenfabrik-Attrappe \n# TXT_FAKE_WEAP\nWerft-Attrappe \n# TXT_FAKE_YARD\nU-Boot-Werft-Attrappe \n# TXT_FAKE_PEN\nRadar-Attrappe \n# TXT_FAKE_RADAR\nBigfoot\n# TXT_THEME_BIGF\nCrush\n# TXT_THEME_CRUS\nFace the Enemy 1\n# TXT_THEME_FAC1\nFace the Enemy 2\n# TXT_THEME_FAC2\nHell March\n# TXT_THEME_HELL\nRun for Your Life\n# TXT_THEME_RUN1\nSmash\n# TXT_THEME_SMSH\nTrenches\n# TXT_THEME_TREN\nWorkmen\n# TXT_THEME_WORK\nAwait\n# TXT_THEME_AWAIT\nDense\n# TXT_THEME_DENSE_R\nMap Selection\n# TXT_THEME_MAP\nFogger\n# TXT_THEME_FOGGER1A\nMud\n# TXT_THEME_MUD1A\nRadio 2\n# TXT_THEME_RADIO2\nRoll Out\n# TXT_THEME_ROLLOUT\nSnake\n# TXT_THEME_SNAKE\nTerminate\n# TXT_THEME_TERMINAT\nTwin\n# TXT_THEME_TWIN\nVector\n# TXT_THEME_VECTOR1A\nTeam-Cyborgs \n# TXT_TEAM_MEMBERS\nBrcke\n# TXT_BRIDGE\nFass\n# TXT_BARREL\nVerbndeter\n# TXT_GOODGUY\nGegner\n# TXT_BADGUY\nGold\n# TXT_GOLD\nEdelsteine\n# TXT_GEMS\nTitelfilm \n# TXT_TEASER\nFilme\n# TXT_MOVIES\nInnen\n# TXT_INTERIOR\nSonar\n# TXT_SONAR_PULSE\nRaketensilo\n# TXT_MSLO\nNavigationssatellit\n# TXT_GPS_SATELLITE\nAtombombe\n# TXT_NUCLEAR_BOMB\nLeicht\n# TXT_EASY\nSchwer\n# TXT_HARD\nNormal\n# TXT_NORMAL\nBitte whlen Sie die Schwierigkeitsstufe.\nSie bleibt dann  whrend des gesamten Feldzuges gltig.\n# TXT_DIFFICULTY\nAllianz\n# TXT_ALLIES\nSowjets\n# TXT_SOVIET\nVorspannmusik \n# TXT_THEME_INTRO\nSchatten wchst \n# TXT_SHADOW_REGROWS\nErz breitet sich aus \n# TXT_ORE_SPREADS\nPunkte-Musik \n# TXT_THEME_SCORE\nInternet\n# TXT_INTERNET\nEis\n# TXT_ICE\nKisten\n# TXT_CRATE\nGeplnkel\n# TXT_SKIRMISH\nSeite auswhlen\n# TXT_CHOOSE\nWertvolle Mineralien \n# TXT_MINERALS\nIgnorieren\n# TXT_IGNORE\nFehler - Modem antwortet nicht\n# TXT_ERROR_NO_RESP\nFehler - Modem antwortet nicht auf 'result code enable'-Befehl\n# TXT_ERROR_NO_RESCODE\nFehler - Modem antwortet nicht  auf Initialisierungssequenz.\n# TXT_ERROR_NO_INIT\nFehler - Modem antwortet nicht auf 'verbose'-Befehl\n# TXT_ERROR_NO_VERB\nFehler - Modem antwortet nicht auf 'echo'-Befehl. \n# TXT_ERROR_NO_ECHO\nFehler - Modem antwortet nicht auf Befehl 'disable modem auto answer'.\n# TXT_ERROR_NO_DISABLE\nFehler - Zu viele Fehler beim Initialisieren des Modems. Abbruch. \n# TXT_ERROR_TOO_MANY\nFehler - Modem gibt Fehlermeldung zurck. \n# TXT_ERROR_ERROR\nFehler - Zeit abgelaufen beim Warten auf Verbindung.\n# TXT_ERROR_TIMEOUT\nerfolgreich\n# TXT_ACCOMPLISHED\nKlicken Sie, um weiterzumachen. \n# TXT_CLICK_CONTINUE\nEmpfange Szenario vom Spielleiter.\n# TXT_RECEIVING_SCENARIO\nSende Szenario an Spieler.\n# TXT_SENDING_SCENARIO\nFehler - Modem antwortet nicht auf den Befehl 'flow control'. Ihre Windows-Konfiguration knnte falsch sein. \n# TXT_NO_FLOW_CONTROL_RESPONSE\nFehler - Modem antwortet nicht auf den Befehl 'compression disable'. Ihre Windows-Konfiguration knnte falsch sein. \n# TXT_NO_COMPRESSION_RESPONSE\nFehler - Modem antwortet nicht auf den Befehl 'error correction disable\". Ihre Windows-Konfiguration knnte falsch sein. \n# TXT_NO_ERROR_CORRECTION_RESPONSE\nUm Alarmstufe Rot ber das Internet zu spielen, mssen Sie mit einem Internet-Provider verbunden und beim Planeten Westwood registriert sein. \n# TXT_EXPLAIN_REGISTRATION\nFehler - kann WChat nicht starten.\n# TXT_ERROR_UNABLE_TO_RUN_WCHAT\nRegistrieren\n# TXT_REGISTER\nErzmine \n# TXT_ORE_MINE\nKein eingetragenes Modem \n# TXT_NO_REGISTERED_MODEM\nChronoport\n# TXT_CHRONOSHIFT\nUngltiger oder besetzter Port \n# TXT_UNABLE_TO_OPEN_PORT\nKein Whlton. Vergewissern Sie sich, dass Ihr Modem an die Telefonleitung angeschlossen ist, und versuchen Sie es erneut.\n# TXT_NO_DIAL_TONE\nFehler - der andere Spieler hat dieses Erweiterungsszenario nicht. \n# TXT_NO_EXPANSION_SCENARIO\nBitte warten...\n# TXT_STAND_BY\nThe Credits Theme\n# TXT_THEME_CREDITS\nEnergieniveau kritisch: Flak ausser Betrieb \n# TXT_POWER_AAGUN\nEnergieniveau kritisch: Teslaspulen ausser Betrieb \n# TXT_POWER_TESLA\nEnergieniveau kritisch\n# TXT_LOW_POWER\nKommandeur:\n# TXT_COMMANDER\nSiege:\n# TXT_BATTLES_WON\nIhre Version des Spiels mu mglicherweise upgedated werden. Die neuesten \nInformationen ber Updates erhalten Sie auf unserer Webseite - \nwww.westwood.com\n# TXT_MISMATCH\nNicht-kompatible Datei mit Spieldaten entdeckt. Diese Spieldatei knnte defekt sein.\n# TXT_SCENARIO_ERROR\nWird verbunden\n# TXT_CONNECTING\nModem-Initialisierung\n# TXT_MODEM_INITIALISATION\nDatenkompression\n# TXT_DATA_COMPRESSION\nFehlerkorrektur\n# TXT_ERROR_CORRECTION\nHardware-Datenflukontrolle\n# TXT_HARDWARE_FLOW_CONTROL\nFortgeschritten\n# TXT_ADVANCED\n2nd_Hand\n# TXT_THEME_2ND_HAND\nArazoid\n# TXT_THEME_ARAZOID\nBackStab\n# TXT_THEME_BACKSTAB\nChaos2\n# TXT_THEME_CHAOS2\nShut_It\n# TXT_THEME_SHUT_IT\nTwinMix1\n# TXT_THEME_TWINMIX1\nUnder3\n# TXT_THEME_UNDER3\nVR2\n# TXT_THEME_VR2\nDer andere Rechner reagiert nicht. Mchten Sie eine Notspeicherung versuchen? Damit das funktionieren kann, mssen beide Spieler sichern.\n# TXT_ASK_EMERGENCY_SAVE_NOT_RESPONDING\nDer andere Rechner hat aufgelegt. Mchten Sie eine Notspeicherung versuchen? Damit das funktionieren kann, mssen beide Spieler sichern.\n# TXT_ASK_EMERGENCY_SAVE_HUNG_UP\nAlarmstufe Rot kann die Registrierungssoftware nicht starten. Sie mssen Westwood Chat von der Alarmstufe-Rot-CD aus starten, um sich registrieren zu lassen.\n# TXT_NO_REG_APP\nEin Spieler in dieser Runde hat dieses Erweiterungsszenario nicht.\n# TXT_NO_CS_SCENARIOS\nRaketen-U-Boot\n# TXT_MISSILESUB\nElektrobot\n# TXT_SHOCKTROOPER\nMechaniker\n# TXT_MECHANIC\nChronoPanzer\n# TXT_CHRONOTANK\nTeslaPanzer\n# TXT_TESLATANK\nM.A.D.-Panzer\n# TXT_MAD\nSprengwagen\n# TXT_DEMOTRUCK\nTarntransporter\n# TXT_PHASETRANSPORT\nBog\n# TXT_THEME_BOG\nFloating\n# TXT_THEME_FLOAT_V2\nGloom\n# TXT_THEME_GLOOM\nGround Wire\n# TXT_THEME_GRNDWIRE\nMech Man 2\n# TXT_THEME_RPT\nSearch\n# TXT_THEME_SEARCH\nTraction\n# TXT_THEME_TRACTION\nWasteland\n# TXT_THEME_WASTELND\nHlitransporter\n# TXT_CARRIER\n\n"
  },
  {
    "path": "CODE/ENG/GER/CREDITS.TXT",
    "content": "\n\n\t     Ausfhrender Produzent\tBrett W. Sperry\n\n\t\t\t  Produzent\tLewis S. Peterson\n\n\t\t     Programmierung\tBarry Green\n\n\t\t Technische Leitung\tSteve Wetherill, Eric Wang\n\n      Design der Solospieler-Karten\tJohn Archer, Patrick Connelly,\n\t\t\t\t\tAdam Isgreen, Michael Lightner,\n\t\t\t\t\tErik Yeo\n\n      Design der Mehrspieler-Karten\tJohn Archer, Stuart Bailey,\n\t\t\t\t\tNigel Berryman, D'Andre Campbell,\n\t\t\t\t\tValerie Carpentier, Cathi Diet,\n\t\t\t\t\tKeith Ditchburn, Gareth Eke,\n\t\t\t\t\tDarren Esp, Simon Evers, Rod Gray,\n\t\t\t\t\tRandy Greenback, Matthew Howe,\n\t\t\t\t\tLevi Luke, Suzanne Maddison,\n\t\t\t\t\tIain McNeil, Graeme Miller,\n\t\t\t\t\tLee Morse, David Parsons,\n\t\t\t\t\tAlex Scarrow, Robert Scheel,\n\t\t\t\t\tLawrence So, John Sweeney,\n\t\t\t\t\tMatthew Tillett, Phillip Veale \n\n\t\t\t     Grafik\tChris Demers, Matthew Hansel,\n\t\t\t\t\tJoseph B. Hewitt IV \n\n\t\t      Audio-Leitung\tPaul S. Mudra\n\n\t\t\t      Musik\tFrank Klepacki\n\n\t\t    Geruscheffekte\tDwight K. Okahara\n\n\tLeiter Qualittsberwachung\tGlenn Sperry\n\n\t       Qualittsberwachung\tJim Adkins, Lloyd Bell,\n\t\t\t\t\tChris Blevens, D'Andre Campbell,\n\t\t\t\t\tErrol Campbell, Shane Dietrich,\n\t\t\t\t\tRandy Greenback, Jon Hix,\n\t\t\t\t\tMark Laity, Troy Leonard,\n\t\t\t\t\tDeMarlo Lewis, Levi Luke,\n\t\t\t\t\tPatrick Offord, Richard Rasmussen,\n\t\t\t\t\tMike Ruppert, Steve Shockey,\n\t\t\t\t\tMike Smith, Albert Springfield\n\n\t\t   Deutsche Version\n\n\t\t     Projektleitung\tMarc Buro\t\t\n\n\t\t\t   Sprecher\tJrg Mackensen, Thomas Stein\n\n\t\t\tbersetzung\tRolf D. Busch\n\n\t       Qualittsberwachung\tRolf D. Busch\n\n\n\n\n\t\t\t\tAlarmstufe Rot\n\n\t\tAusfhrender Produzent\tBrett W. Sperry\n                             Produzent\tEd Del Castillo\n\n\t\t      Original Konzept\tBrett W. Sperry\n\t\t\t\t\tJoe Bostic\n\n\t\t\tOriginal Story\tRon Smith\n\t\t\t\t\tEd Del Castillo\n\n\t\t    Hauptprogrammierer\tJoe Bostic\n\t\t\t\t\tBarry Green\n\t\t\t\t\tSteve Tall\n\n             \t \t Programmierer\tPhil Gorrow\n\t\t\t\t\tMaria del Mar McCready Legg\n\t\t\t\t\tJeff Brown\n\t\t\t\t\tBill Randolph\n\t\t\t\t\tMatt Thorn\n\t\t\t\t\tDavid Aldridge\n\t\t\t\t\tSteve Wetherill\n\n\tProgrammierer deutsche Version\tVictor Grippi\n\n     \t\t    Technische Leitung\tSteve Wetherill\n                          \t\tEric Wang\n\n\t\t\t\tDesign\tBrett W. Sperry\n\t\t\t\t\tAdam Isgreen\n\t\t\t\t\tMichael Lightner\n\t\t\t\t\tErik Yeo\n\n\t\t\t Hauptgrafiker\tChris Demers\n\t\t\t\t\tMatthew Hansel\n\t\t\t\t\tJoseph Hewitt\n\n\t\t\t      Grafiker\tPaul Wesberry\n\t\t\t\t\tDavid T. Potter\n\t\t\t\t\tDamon Redmond\n\t\t\t\t\tBrian White\n\n\t\t\t  Film & Video\tEric Gooch\n\t\t\t\t\tKevin Becquet\n\n\t\t Video Post Production\tFelix Kupis\n\t\t\t\t\tKevin Becquet\n\n\t\t\t    Screenplay\tRon Smith\n\t\t\t\t\tAdam Isgreen\n\t\t\t\t\tJohn Scott Lewinski\n\n\t\t\tDirektor Audio\tPaul S. Mudra\n\t\t\t    Soundtrack\tFrank Klepacki\n\t\t\t Sound Effekte\tDwight K. Okahara\n\n\t    Leitung Qualittssicherung\tGlenn Sperry\n\n\t\t    Qualittssicherung\tLloyd Bell\n\t\t\t\t\tKenny Dunne\n\t\t\t\t\tMike Smith\n\t\t\t\t\tJohn Archer\n\t\t\t\t\tChris Rubyor\n\t\t\t\t\tD'Andre Cambell\n\t\t\t\t\tChad Shackelford\n\t\t\t\t\tChris Bleven\n\t\t\t\t\tLevi Luke\n\t\t\t\t\tErrol Campbell\n\t\t\t\t\tAbe Hernandez\n\t\t\t\t\tJames Adkins\n\t\t\t\t\tRichard Rasmussen\n\t\t\t\t\tBen Lublin\n\t\t\t\t\tChris Holloway\n\t\t\t\t\tIsaiah Myers\n\t\t\t\t\tPhillip Castro\n\t\t\t\t\tAlbert Springfield\n\t\t\t\t\tSteve Corcoran\n\t\t\t\t\tJames Hughes\n\t\t\t\t\tRandy Greenback\n\t\t\t\t\tTyler Thackery\n\n\t\t     Verpackungsdesign\tMatthew Hansel\n\t\t\t\t\tThomas Puckett inc.\n\n\t\t\tHandbuchdesign\tVictoria Hart\n\n\n\n                Besonderer Dank an Daniel Woodyatt, Rosemarie Dalton,\n                und alle Virgins in Europa. Vielen Dank auch an\n\t\tTracy Chapman fr einen neuen Anfang.\n\n\n\n\n\t\t\t          Die Schauspieler\n\n\n\tAllierte Seite\n             \t         Von Esling  \t Arthur Roberts\n                            Stavros  \t Barry Kramer\n                              Tanya  \t Lynne Litteer\n\t\t   Verhrspezialist\t Dom Magwili\n\t\t\t  Ansagerin\t Gwen Castaldi\n\n\t\t...und John Milford als Albert Einstein\n\n\n\t\t   Allierte Truppen\tRicky Russell\n\t\t\t\t\tNick Paulos\n\t\t\t\t\tScott Ryan Talley\n\t\t\t\t\tJoe Bostic\n\t\t\t\t\tChris Demers\n\t\t\t\t\tBarry Green\n\t\t\t\t\tMatthew Hansel\n\t\t\t\t\tAdam Isgreen\n\t\t\t\t\tFrank Klepacki\n\t\t\t\t\tMike Lightner\n\t\t\t\t\tBill Randolph\n\t\t\t\t\tPhilip E. Shelburne\n\t\t\t\t\tEric Wang\n\n\n\n\tSovietische Seite\n\t\t\t      Kukov\tCraig Cavanah\n\t\t\t   Gradenko\tAlan Terry\n\t\t\t      Nadia\tAndrea Robinson\n\t\t\t       Kane\tJoe Kucan\n\n\t\t...und Eugene Dynarski als Josef Stalin\n\n\n\t\tSovietische Truppen\tFelix Kupis\n\t\t\t\t\tErik Yeo\n\n\n\tStimmen im Spiel\n\t\t\t     E.V.A.\tMartin Alper\n\t\t\t      Tanya\tLanae Freeborn\n\t\t\t    Truppen\tMike Grayford\n\t\t\t\t\tAdam Isgreen\n\t\t\t\t\tTroy Leonard\n\t\t\t\t\tChris Rubyor\n\n\n\tProduktions Crew\n\n\t\t\t    Casting\tMarilee Lear, C.S.A.\n\n\t\t       Kostmdesign\tChristie Moeller\n\n\t\t Make-up & Frisuren\tCindy Cline\n\n\t\t     Sound Engineer\tPaul S. Mudra\n\n\t\t\tBeleuchtung\tEric Gooch\n\n\t  Hauptproduktionsassistent\tPaul Bastardo\n\n\t     Produktionsassistenten\tPat Connelly\n\t\t\t\t\tRichard Rasmussen\n\t\t\t\t\tRick Appin\n\t\t\t\t\tJeff Fillhaber\n\t\t\t\t\tPatience Becquet\n\n\t\t\t      Video\tKevin Becquet\n\n\t\t\tSfx Make-up\tPhilip E. Shelburne\n\n\n\t    Spezielles Bildmaterial\n\t\t\tCourtesy Of\tNBC News Archives Films\n\t\t\t\t\tFabulous Footage\n\n\n\t\t\t     Regie:\tJoseph D. Kucan\n\n\n\n\n"
  },
  {
    "path": "CODE/ENG/MESSAGE.TXT",
    "content": "# MESSAGE_NONE\nYou must build a Windtrap to provide power to your base.  Without power, your structures will decay.\n# MESSAGE_BUILD_WINDTRAP\nConcrete: Use concrete to make a sturdy foundation for your structures.\n# MESSAGE_STRUCT_CONCRETE\nPalace: This is your Palace.\n# MESSAGE_STRUCT_PALACE\nLight Factory: The Light Factory produces light attack vehicles.\n# MESSAGE_STRUCT_LIGHT\nHeavy Factory: The Heavy Factory produces tracked vehicles.\n# MESSAGE_STRUCT_HEAVY\nHi-Tech Factory: The Hi-Tech Factory produces flying vehicles.\n# MESSAGE_STRUCT_HITECH\nHouse IX: The IX Research Facility advances your House's technology.\n# MESSAGE_STRUCT_IX\nWOR: Wor is used to train your Heavy infantry.\n# MESSAGE_STRUCT_WOR\nConstruction Facility: All structures are built by the construction facility.\n# MESSAGE_STRUCT_CONST\nWindtrap: The windtrap supplies power to your base.  Without power your structures will decay.\n# MESSAGE_STRUCT_WINDTRAP\nBarracks: The Barracks is used to train your Light infantry.\n# MESSAGE_STRUCT_BARRACKS\nStartport: The Starport is used to order and receive shipments from C.H.O.A.M.\n# MESSAGE_STRUCT_STARPORT\nSpice Refinery: The Refinery converts spice into credits.\n# MESSAGE_STRUCT_REFINERY\nRepair Facility: The Repair Facility is used to repair your vehicles.\n# MESSAGE_STRUCT_REPAIR\nWall: The wall is used for passive defense.\n# MESSAGE_STRUCT_WALL\nGun Turret: The cannon turret is used for short range active defense.\n# MESSAGE_STRUCT_TURRET\nRocket Turret: The rocket/cannon turret is used for both short and medium range active defense.\n# MESSAGE_STRUCT_RTURRET\nSpice Silo: The Spice silo is used to store refined spice.\n# MESSAGE_STRUCT_SILO\nOutpost: The Outpost provides radar and aids control of distant vehicles.\n# MESSAGE_STRUCT_OUTPOST\nThere isn't enough open concrete to place this structure.  You may proceed, but without enough concrete the building will need repairs.\n# MESSAGE_NEED_CONCRETE\nSand: This is sand terrain.  Plenty of this stuff on Arrakis, to be sure.\n# MESSAGE_SAND\nSand Dunes: These are an ubiquitous feature of Arrakian landscape.\n# MESSAGE_DUNE\nRock: This is rock terrain.  This valuable terrain is the only place structures can be built.\n# MESSAGE_ROCK\nMountain: Mountains on Arrakis are rare (and an inconvenience).\n# MESSAGE_MOUNT\nSpice Field: This is the Spice, Melange.  It is the most precious substance in the universe.\n# MESSAGE_SPICE\nStructures must be placed on clear rock or concrete and adjacent to another friendly structure.\n# MESSAGE_ADJACENT\nSearch for spice fields to harvest.\n# MESSAGE_SEARCH4SPICE\nWarning: Sandworms (Shai-Hulud) roam Dune devouring anything on the sand.\n# MESSAGE_SANDWORM\n"
  },
  {
    "path": "CODE/EVENT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/EVENT.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : EVENT.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/09/94                                                     *\n *                                                                                             *\n *                  Last Update : November 10, 1995 [BRR]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   EventClass::EventClass -- Construct an id and cell based event.                           *\n *   EventClass::EventClass -- Construct simple target type event.                             *\n *   EventClass::EventClass -- Constructor for mission change events.                          *\n *   EventClass::EventClass -- Constructor for navigation computer events.                     *\n *   EventClass::EventClass -- Constructor for object types affecting cells event.             *\n *   EventClass::EventClass -- Constructor for sidebar build events.                           *\n *   EventClass::EventClass -- Constructs event to transfer special flags.                     *\n *   EventClass::EventClass -- Default constructor for event objects.                          *\n *   EventClass::EventClass -- Event for sequencing animations.                                *\n *   EventClass::EventClass -- Megamission assigned to unit.                                   *\n *   EventClass::Execute -- Execute a queued command.                                          *\n *   EventClass::EventClass -- construct a variable-sized event                                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#ifdef WIN32\n#include \"ccdde.h\"\n#endif\t//WIN32\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n#include \"WolStrng.h\"\n#endif\n\n/***************************************************************************\n** Table of what data is really used in the EventClass struct for different\n** events.  This table must be kept current with the EventType enum.\n*/\nunsigned char EventClass::EventLength[EventClass::LAST_EVENT] = {\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// EMPTY\n\tsize_of(EventClass, Data.General ),\t\t\t\t// ALLY\n\tsize_of(EventClass, Data.MegaMission ),\t\t// MEGAMISSION\n\tsize_of(EventClass, Data.MegaMission_F ),\t\t// MEGAMISSION_F\n\tsize_of(EventClass, Data.Target ),\t\t\t\t// IDLE\n\tsize_of(EventClass, Data.Target ),\t\t\t\t// SCATTER\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// DESTRUCT\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// DEPLOY\n\tsize_of(EventClass, Data.Place ),\t\t\t\t// PLACE\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// OPTIONS\n\tsize_of(EventClass, Data.General ),\t\t\t\t// GAMESPEED\n\tsize_of(EventClass, Data.Specific ),\t\t\t// PRODUCE\n\tsize_of(EventClass, Data.Specific.Type ),\t\t// SUSPEND\n\tsize_of(EventClass, Data.Specific.Type ),\t\t// ABANDON\n\tsize_of(EventClass, Data.Target ),\t\t\t\t// PRIMARY\n\tsize_of(EventClass, Data.Special ),\t\t\t\t// SPECIAL_PLACE\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// EXIT\n\tsize_of(EventClass, Data.Anim ),\t\t\t\t\t// ANIMATION\n\tsize_of(EventClass, Data.Target ),\t\t\t\t// REPAIR\n\tsize_of(EventClass, Data.Target ),\t\t\t\t// SELL\n\tsize_of(EventClass, Data.SellCell),\t\t\t\t// SELLCELL\n\tsize_of(EventClass, Data.Options ),\t\t\t\t// SPECIAL\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// FRAMESYNC\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\tMESSAGE\n\tsize_of(EventClass, Data.FrameInfo.Delay ),\t// RESPONSE_TIME\n\tsize_of(EventClass, Data.FrameInfo ),\t\t\t// FRAMEINFO\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\tSAVEGAME\n\tsize_of(EventClass, Data.NavCom ),\t\t\t\t// ARCHIVE\n\tsize_of(EventClass, Data.Variable.Size),\t\t// ADDPLAYER\n\tsize_of(EventClass, Data.Timing ),\t\t\t\t// TIMING\n\tsize_of(EventClass, Data.ProcessTime ),\t\t// PROCESS_TIME\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t//\tPROPOSE_DRAW\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t//\tRETRACT_DRAW\n#endif\n};\n\nchar * EventClass::EventNames[EventClass::LAST_EVENT] = {\n\t\"EMPTY\",\n\t\"ALLY\",\n\t\"MEGAMISSION\",\n\t\"MEGAMISSION_F\",\n\t\"IDLE\",\n\t\"SCATTER\",\n\t\"DESTRUCT\",\n\t\"DEPLOY\",\n\t\"PLACE\",\n\t\"OPTIONS\",\n\t\"GAMESPEED\",\n\t\"PRODUCE\",\n\t\"SUSPEND\",\n\t\"ABANDON\",\n\t\"PRIMARY\",\n\t\"SPECIAL_PLACE\",\n\t\"EXIT\",\n\t\"ANIMATION\",\n\t\"REPAIR\",\n\t\"SELL\",\n\t\"SELLCELL\",\n\t\"SPECIAL\",\n\t\"FRAMESYNC\",\n\t\"MESSAGE\",\n\t\"RESPONSE_TIME\",\n\t\"FRAMEINFO\",\n\t\"SAVEGAME\",\n\t\"ARCHIVE\",\n\t\"ADDPLAYER\",\n\t\"TIMING\",\n\t\"PROCESS_TIME\",\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\"PROPOSE_DRAW\",\n\t\"RETRACT_DRAW\",\n#endif\n};\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Constructs event to transfer special flags.                       *\n *                                                                                             *\n *    This constructs an event that will transfer the special flags.                           *\n *                                                                                             *\n * INPUT:   data  -- The special flags to be transported to all linked computers.              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(SpecialClass data)\n{\n\tID = PlayerPtr->ID;\n\tType = SPECIAL;\n\tFrame = ::Frame;\n\tData.Options.Data = data;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Construct simple target type event.                               *\n *                                                                                             *\n *    This will construct a generic event that needs only a target parameter. The actual       *\n *    event and target values are specified as parameters.                                     *\n *                                                                                             *\n * INPUT:   type  -- The event type to construct.                                              *\n *                                                                                             *\n *          target-- The target value that this event is to apply to.                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(EventType type, TargetClass target)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tFrame = ::Frame;\n\tData.Target.Whom = target;\n}\n\n\nEventClass::EventClass(EventType type, CELL cell)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tFrame = ::Frame;\n\tData.SellCell.Cell = cell;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Default constructor for event objects.                            *\n *                                                                                             *\n *    This constructs a simple event object that requires no parameters other than the         *\n *    type of event it is.                                                                     *\n *                                                                                             *\n * INPUT:   type  -- The type of event to construct.                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(EventType type)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tFrame = ::Frame;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Constructor for general-purpose-data events.                      *\n *                                                                                             *\n * INPUT:   type  -- The type of event to construct.                                           *\n *            val   -- data value                                                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(EventType type, int val)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tData.General.Value = val;\n\tFrame = ::Frame;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Constructor for navigation computer events.                       *\n *                                                                                             *\n *    Constructor for events that are used to assign the navigation computer.                  *\n *                                                                                             *\n * INPUT:   type     -- The type of event (this constructor can be used by other navigation    *\n *                      type events).                                                          *\n *                                                                                             *\n *          src      -- The object that the event should apply to.                             *\n *                                                                                             *\n *          dest     -- The destination (or target) that the event needs to complete.          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(EventType type, TargetClass src, TargetClass dest)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tFrame = ::Frame;\n\tData.NavCom.Whom = src;\n\tData.NavCom.Where = TargetClass(dest);\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Event for sequencing animations.                                  *\n *                                                                                             *\n *    This constructor is used for animations that must be created through the event system.   *\n *                                                                                             *\n * INPUT:   anim  -- The animation that will be created.                                       *\n *                                                                                             *\n *          coord -- The location where the animation is to be created.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(AnimType anim, HousesType owner, COORDINATE coord)\n{\n\tID = PlayerPtr->ID;\n\tType = ANIMATION;\n\tFrame = ::Frame;\n\tData.Anim.What = anim;\n\tData.Anim.Owner = owner;\n\tData.Anim.Where = coord;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Megamission assigned to unit.                                     *\n *                                                                                             *\n *    This is the event that is used to assign most missions to units. It combines both the    *\n *    mission and the target (navcom and tarcom).                                              *\n *                                                                                             *\n * INPUT:   src      -- The object that this mission is to apply to.                           *\n *                                                                                             *\n *          mission  -- The mission to assign to this object.                                  *\n *                                                                                             *\n *          target   -- The target to assign to this object's TarCom.                          *\n *                                                                                             *\n *          destination -- The destination to assign to this object's NavCom.                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(TargetClass src, MissionType mission, TargetClass target, TargetClass destination)\n{\n\tID = PlayerPtr->ID;\n\tType = MEGAMISSION;\n\tFrame = ::Frame;\n\tData.MegaMission.Whom = src;\n\tData.MegaMission.Mission = mission;\n\tData.MegaMission.Target = target;\n\tData.MegaMission.Destination = destination;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Megamission assigned to unit.                                     *\n *                                                                                             *\n *    This is the event that is used to assign most missions to units. It combines both the    *\n *    mission and the target (navcom and tarcom).  This variation is used for formation moves. *\n *                                                                                             *\n * INPUT:   src      -- The object that this mission is to apply to.                           *\n *                                                                                             *\n *          mission  -- The mission to assign to this object.                                  *\n *                                                                                             *\n *          target   -- The target to assign to this object's TarCom.                          *\n *                                                                                             *\n *          destination -- The destination to assign to this object's NavCom.                  *\n *                                                                                             *\n *          speed    -- The formation override speed for this move.                            *\n *                                                                                             *\n *          maxspeed -- The formation override maximum speed for this move.                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(TargetClass src, MissionType mission, TargetClass target, TargetClass destination, SpeedType speed, MPHType maxspeed)\n{\n\tID = PlayerPtr->ID;\n\tType = MEGAMISSION_F;\n\tFrame = ::Frame;\n\tData.MegaMission_F.Whom = src;\n\tData.MegaMission_F.Mission = mission;\n\tData.MegaMission_F.Target = TargetClass(target);\n\tData.MegaMission_F.Destination = TargetClass(destination);\n\tData.MegaMission_F.Speed = speed;\n\tData.MegaMission_F.MaxSpeed = maxspeed;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Constructor for sidebar build events.                             *\n *                                                                                             *\n *    This constructor is used for events that deal with an object type and an object ID.      *\n *    Typically, this is used exclusively by the sidebar.                                      *\n *                                                                                             *\n * INPUT:   type     -- The event type of this object.                                         *\n *                                                                                             *\n *          object   -- The object type number.                                                *\n *                                                                                             *\n *          id       -- The object sub-type number.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(EventType type, RTTIType object, int id)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tFrame = ::Frame;\n\tData.Specific.Type = object;\n\tData.Specific.ID = id;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Constructor for object types affecting cells event.               *\n *                                                                                             *\n *    This constructor is used for those events that have an object type and associated cell.  *\n *    Typically, this is for building placement after construction has completed.              *\n *                                                                                             *\n * INPUT:   type     -- The event type for this object.                                        *\n *                                                                                             *\n *          object   -- The object type number (actual object is probably inferred from the    *\n *                      sidebar data).                                                         *\n *                                                                                             *\n *          cell     -- The cell location where this event is to occur.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(EventType type, RTTIType object, CELL cell)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tFrame = ::Frame;\n\tData.Place.Type = object;\n\tData.Place.Cell = cell;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Construct an id and cell based event.                             *\n *                                                                                             *\n *    This constructor is used for those events that require an ID number and a cell location. *\n *                                                                                             *\n * INPUT:   type  -- The event type this will be.                                              *\n *                                                                                             *\n *          id    -- The arbitrary id number to assign.                                        *\n *                                                                                             *\n *          cell  -- The location for this event.                                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(EventType type, int id, CELL cell)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tFrame = ::Frame;\n\tData.Special.ID \t= id;\n\tData.Special.Cell = cell;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- construct a variable-sized event                                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *\t\tptr\t\tptr to data associated with this event\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/10/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(EventType type, void * ptr, unsigned long size)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tFrame = ::Frame;\n\tData.Variable.Pointer = ptr;\n\tData.Variable.Size = size;\n}\n\n\n/***********************************************************************************************\n * EventClass::Execute -- Execute a queued command.                                            *\n *                                                                                             *\n *    This routine executes an event. The even must already have been confirmed by any         *\n *    remote machine before calling this routine.                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid EventClass::Execute(void)\n{\n\tTechnoClass * techno;\n\tAnimClass * anim = 0;\n\tHouseClass * house = 0;\n//\tCELL cell = 0;\n\tchar txt[80];\n\tbool formation = false;\n//\tRTTIType rt;\n\n\tif (Debug_Print_Events) {\n\t\tprintf(\"(%d) Executing %s ID:%d Frame:%d \",\n\t\t\t::Frame, EventNames[Type], ID, Frame);\n\t}\n\n\tswitch (Type) {\n\n\t\t/*\n\t\t**\tUpdate the archive target for this building.\n\t\t*/\n\t\tcase ARCHIVE:\n\t\t\ttechno = Data.NavCom.Whom.As_Techno();\n\t\t\tif (techno && techno->IsActive) {\n\t\t\t\ttechno->ArchiveTarget = Data.NavCom.Where;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tMake or break alliance.\n\t\t*/\n\t\tcase ALLY:\n\t\t\thouse = Houses.Raw_Ptr(Data.General.Value);\n\t\t\tif (Houses.Raw_Ptr(ID)->Is_Ally(house)) {\n\t\t\t\tHouses.Raw_Ptr(ID)->Make_Enemy((HousesType)Data.General.Value);\n\t\t\t} else {\n\t\t\t\tHouses.Raw_Ptr(ID)->Make_Ally((HousesType)Data.General.Value);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tSpecial self destruct action requested. This is active in the multiplayer mode.\n\t\t*/\n\t\tcase DESTRUCT:\n\t\t\tHouses.Raw_Ptr(ID)->Flag_To_Die();\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tUpdate the special control flags. This is necessary so that in a multiplay\n\t\t**\tgame, all machines will agree on the rules. If these options change during\n\t\t**\tgame play, then all players are informed that options have changed.\n\t\t*/\n\t\tcase SPECIAL:\n\t\t\t{\n\t\t\t\tSpecial = Data.Options.Data;\n\t\t\t\tHouseClass * house = Houses.Raw_Ptr(ID);\n\n\t\t\t\tsprintf(txt, Text_String(TXT_SPECIAL_WARNING), house->Name);\n\t\t\t\tSession.Messages.Add_Message(NULL, 0, txt,\n\t\t\t\t\thouse->RemapColor,\n\t\t\t\t\tTPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, 1200);\n\t\t\t\tMap.Flag_To_Redraw(false);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tStarts or stops repair on the specified object. This event is triggered by the\n\t\t**\tplayer clicking the repair wrench on a building.\n\t\t*/\n\t\tcase REPAIR:\n\t\t\ttechno = Data.Target.Whom.As_Techno();\n\t\t\tif (techno && techno->IsActive) {\n\t\t\t\ttechno->Repair(-1);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tTells a building/unit to sell. This event is triggered by the player clicking the\n\t\t**\tsell animating cursor over the building or unit.\n\t\t*/\n\t\tcase SELL:\n\t\t\ttechno = Data.Target.Whom.As_Techno();\n\t\t\tif (techno && techno->IsActive && techno->House == Houses.Raw_Ptr(ID)) {\n\t\t\t\tif (techno->What_Am_I() == RTTI_BUILDING || (techno->What_Am_I() == RTTI_UNIT && Map[techno->Center_Coord()].Cell_Building() != 0)) {\n\t\t\t\t\ttechno->Sell_Back(-1);\n\t\t\t\t}\n\t\t\t} else {\n//\t\t\t\tif (Is_Target_Cell(Data.Target.Whom)) {\n//\t\t\t\t\tHouses.Raw_Ptr(ID)->Sell_Wall(As_Cell(Data.Target.Whom));\n//\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tTells the wall at the specified location to sell off.\n\t\t*/\n\t\tcase SELLCELL:\n//\t\t\tcell = Data.SellCell.Cell;\n\t\t\tHouses.Raw_Ptr(ID)->Sell_Wall(Data.SellCell.Cell);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThis even is used to trigger an animation that is generated as a direct\n\t\t**\tresult of player intervention.\n\t\t*/\n\t\tcase ANIMATION:\n\t\t\tanim = new AnimClass(Data.Anim.What, Data.Anim.Where);\n\t\t\tif (anim) {\n\t\t\t\tif (Data.Anim.Owner != HOUSE_NONE && PlayerPtr->Class->House != Data.Anim.Owner) {\n\t\t\t\t\tanim->Make_Invisible();\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThis event will place the specified object at the specified location.\n\t\t**\tThe event is used to place newly constructed buildings down on the map. The\n\t\t**\tobject type is specified. From this object type, the house can determine the\n\t\t**\texact factory and real object pointer to use.\n\t\t*/\n\t\tcase PLACE:\n\t\t\tHouses.Raw_Ptr(ID)->Place_Object(Data.Place.Type, Data.Place.Cell);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThis event starts production of the specified object type. The house can\n\t\t**\tdetermine from the type and ID value, what object to begin production on and\n\t\t**\twhat factory to use.\n\t\t*/\n\t\tcase PRODUCE:\n\t\t\tHouses.Raw_Ptr(ID)->Begin_Production(Data.Specific.Type, Data.Specific.ID);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThis event is generated when the player puts production on hold. From the\n\t\t**\tobject type, the factory can be inferred.\n\t\t*/\n\t\tcase SUSPEND:\n\t\t\tHouses.Raw_Ptr(ID)->Suspend_Production(Data.Specific.Type);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThis event is generated when the player cancels production of the specified\n\t\t**\tobject type. From the object type, the exact factory can be inferred.\n\t\t*/\n\t\tcase ABANDON:\n\t\t\tHouses.Raw_Ptr(ID)->Abandon_Production(Data.Specific.Type);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tToggles the primary factory state of the specified building.\n\t\t*/\n\t\tcase PRIMARY:\n\t\t\t{\n\t\t\t\tBuildingClass * building = Data.Target.Whom.As_Building();\n\t\t\t\tif (building && building->IsActive) {\n\t\t\t\t\tbuilding->Toggle_Primary();\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThis is the general purpose mission control event. Most player\n\t\t**\taction routes through this event. It sets a unit's mission, TarCom,\n\t\t**\tand NavCom to the values specified.\n\t\t*/\n\t\tcase MEGAMISSION_F:\n\t\t\ttechno = Data.MegaMission_F.Whom.As_Techno();\n\t\t\tif (techno && techno->IsActive && techno->Is_Foot()) {\n\t\t\t\t((FootClass *)techno)->IsFormationMove = true;\n\t\t\t\t((FootClass *)techno)->FormationSpeed = Data.MegaMission_F.Speed;\n\t\t\t\t((FootClass *)techno)->FormationMaxSpeed = Data.MegaMission_F.MaxSpeed;\n\t\t\t\tFormMove = true;\n\t\t\t\tFormSpeed = Data.MegaMission_F.Speed;\n\t\t\t\tFormMaxSpeed = Data.MegaMission_F.MaxSpeed;\n\t\t\t\tformation = true;\n\t\t\t}\n\t\t\t// Fall thru to next case...\n\n\t\tcase MEGAMISSION:\n\t\t\tif (Debug_Print_Events) {\n\t\t\t\tprintf(\"Whom:%x Tgt:%x Dest:%x \",\n\t\t\t\t\tData.MegaMission.Whom.As_TARGET(),\n\t\t\t\t\tData.MegaMission.Target.As_TARGET(),\n\t\t\t\t\tData.MegaMission.Destination.As_TARGET());\n\t\t\t}\n\t\t\ttechno = Data.MegaMission.Whom.As_Techno();\n\t\t\tif (techno != NULL && techno->IsActive && techno->Strength > 0 && !techno->IsInLimbo) {\n\n\t\t\t\t/*\n\t\t\t\t**\tFetch a pointer to the object of the mission. If there is an error with\n\t\t\t\t**\tthis object, such as it is dead, then bail.\n\t\t\t\t*/\n\t\t\t\tObjectClass * object = NULL;\n\t\t\t\tif (Data.MegaMission.Target.Is_Valid()) {\n\t\t\t\t\tobject = Data.MegaMission.Target.As_Object();\n\t\t\t\t\tif (object != NULL && (!object->IsActive || object->Strength == 0 || object->IsInLimbo)) {\n\t\t\t\t\t\tbreak;\n//\t\t\t\t\t\tobject = NULL;\n//\t\t\t\t\t\tData.MegaMission.Target.Invalidate();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the destination target is invalid because the object is dead, then\n\t\t\t\t**\tbail from processing this mega mission.\n\t\t\t\t*/\n\t\t\t\tif (Data.MegaMission.Destination.Is_Valid()) {\n\t\t\t\t\tobject = Data.MegaMission.Destination.As_Object();\n\t\t\t\t\tif (object != NULL && (!object->IsActive || object->Strength == 0 || object->IsInLimbo)) {\n\t\t\t\t\t\tbreak;\n//\t\t\t\t\t\tobject = NULL;\n//\t\t\t\t\t\tData.MegaMission.Destination.Invalidate();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tBreak any existing tether or team contact, since it is now invalid.\n\t\t\t\t*/\n\t\t\t\tif (!techno->IsTethered) {\n\t\t\t\t\ttechno->Transmit_Message(RADIO_OVER_OUT);\n\t\t\t\t}\n\t\t\t\tif (techno->Is_Foot()) {\n\t\t\t\t\tif (!formation) ((FootClass *)techno)->IsFormationMove = false;\n\t\t\t\t\tif (((FootClass *)techno)->Team) {\n\t\t\t\t\t\t((FootClass *)techno)->Team->Remove((FootClass *)techno);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (object != NULL) {\n\t\t\t\t\tif (PlayerPtr->Is_Ally(techno)) {\n\t\t\t\t\t\tobject->Clicked_As_Target();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tTest to see if the navigation target should really be queued rather\n\t\t\t\t**\tthan assigned to the object. This would be the case if this is a\n\t\t\t\t**\tspecial queued move mission and there is already a valid navigation\n\t\t\t\t**\ttarget for this unit.\n\t\t\t\t*/\n\t\t\t\tbool q = (Data.MegaMission.Mission == MISSION_QMOVE);\n\n\t\t\t\ttechno->Assign_Mission(Data.MegaMission.Mission);\n\n\t\t\t\tif (techno->Is_Foot()) {\n\t\t\t\t\t((FootClass*)techno)->SuspendedNavCom = TARGET_NONE;\n\t\t\t\t}\n\t\t\t\ttechno->SuspendedTarCom = TARGET_NONE;\n\n\t\t\t\t/*\n\t\t\t\t**\tGuard area mode is handled with care. The specified target is actually\n\t\t\t\t**\tassigned as the location that should be guarded. In addition, the\n\t\t\t\t**\tmovement destination is immediately set to this new location.\n\t\t\t\t*/\n\t\t\t\tif (Data.MegaMission.Mission == MISSION_GUARD_AREA && techno->Is_Foot()) {\n\t\t\t\t\ttechno->Assign_Target(TARGET_NONE);\n\t\t\t\t\ttechno->Assign_Destination(Data.MegaMission.Target.As_TARGET());\n\t\t\t\t\ttechno->ArchiveTarget = Data.MegaMission.Target.As_TARGET();\n\t\t\t\t} else {\n\t\t\t\t\tif (q && techno->Is_Foot()) {\n\t\t\t\t\t\t((FootClass *)techno)->Queue_Navigation_List(Data.MegaMission.Destination.As_TARGET());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (techno->Is_Foot()) {\n\t\t\t\t\t\t\t((FootClass *)techno)->Clear_Navigation_List();\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttechno->Assign_Target(Data.MegaMission.Target.As_TARGET());\n\t\t\t\t\t\ttechno->Assign_Destination(Data.MegaMission.Destination.As_TARGET());\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t//\n\t\t\t\t// Special case for ship repairing: If the assigned mission is to\n\t\t\t\t// move, and 'techno' is a Vessel:\n\t\t\t\t//   If the destination is a shipyard or sub pen, set the IsToSelfRepair flag\n\t\t\t\t//   Otherwise, clear both IsToSelfRepair and IsSelfRepairing\n\t\t\t\t//\n\t\t\t\tRTTIType rt = techno->What_Am_I();\n//\t\t\t\trt = Data.MegaMission.Whom;\n\t\t\t\tif (rt == RTTI_VESSEL && techno != NULL && techno->What_Am_I() == RTTI_VESSEL && Data.MegaMission.Mission == MISSION_MOVE) {\n\t\t\t\t\tVesselClass *ship = (VesselClass *)techno;\n\t\t\t\t\tif (object != NULL) {\n\t\t\t\t\t\tif (object->What_Am_I() == RTTI_BUILDING &&\n//\t\t\t\t\t\tif ((RTTIType)Data.MegaMission.Destination == RTTI_BUILDING &&\n\t\t\t\t\t\t\t(((BuildingClass *)object)->Class->Type == STRUCT_SHIP_YARD ||\n\t\t\t\t\t\t\t((BuildingClass *)object)->Class->Type == STRUCT_SUB_PEN)) {\n\t\t\t\t\t\t\tship->IsToSelfRepair = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tship->IsToSelfRepair = false;\n\t\t\t\t\t\t\tship->IsSelfRepairing = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tship->IsToSelfRepair = false;\n\t\t\t\t\t\tship->IsSelfRepairing = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n#ifdef NEVER\n\t\t\t\tif ((techno->What_Am_I() == RTTI_UNIT || techno->What_Am_I() == RTTI_INFANTRY) &&\n\t\t\t\t\t\tData.MegaMission.Mission == MISSION_GUARD_AREA) {\n\n\t\t\t\t\t((FootClass *)techno)->ArchiveTarget = Data.MegaMission.Destination;\n\t\t\t\t}\n#endif\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tRequest that the unit/infantry/aircraft go into idle mode.\n\t\t*/\n\t\tcase IDLE:\n\t\t\ttechno = Data.Target.Whom.As_Techno();\n\t\t\tif (techno != NULL && techno->IsActive && !techno->IsInLimbo && !techno->IsTethered && techno->What_Am_I() != RTTI_BUILDING) {\n\t\t\t\ttechno->Transmit_Message(RADIO_OVER_OUT);\n\t\t\t\ttechno->Assign_Destination(TARGET_NONE);\n\t\t\t\ttechno->Assign_Target(TARGET_NONE);\n\t\t\t\ttechno->Enter_Idle_Mode();\n\t\t\t\tif (techno->Is_Foot()) {\n\t\t\t\t\t((FootClass *)techno)->Clear_Navigation_List();\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tRequest that the unit/infantry/aircraft scatter from its current location.\n\t\t*/\n\t\tcase SCATTER:\n\t\t\ttechno = Data.Target.Whom.As_Techno();\n\t\t\tif (techno != NULL && techno->Is_Foot() && techno->IsActive && !techno->IsInLimbo && !techno->IsTethered) {\n\t\t\t\t((FootClass *)techno)->IsScattering = true;\n\t\t\t\ttechno->Scatter(0, true, false);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tIf we are placing down the ion cannon blast then lets take\n\t\t** care of it.\n\t\t*/\n\t\tcase SPECIAL_PLACE:\n\t\t\tHouses.Raw_Ptr(ID)->Place_Special_Blast((SpecialWeaponType)Data.Special.ID, Data.Special.Cell);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tExit the game.\n\t\t** Give parting message while palette is fading to black.\n\t\t*/\n\t\tcase EXIT:\n\t\t\tTheme.Queue_Song(THEME_NONE);\n\t\t\tStop_Speaking();\n\t\t\tSpeak(VOX_CONTROL_EXIT);\n\t\t\twhile (Is_Speaking()) {\n\t\t\t\tCall_Back();\n\t\t\t}\n\t\t\tGameActive = false;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tProcess the options menu, unless we're playing back a recording.\n\t\t*/\n\t\tcase OPTIONS:\n\t\t\tif (!Session.Play) {\n\t\t\t\tSpecialDialog = SDLG_OPTIONS;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tProcess the options Game Speed\n\t\t*/\n\t\tcase GAMESPEED:\n\t\t\tOptions.GameSpeed = Data.General.Value;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tAdjust connection timing for multiplayer games\n\t\t*/\n\t\tcase RESPONSE_TIME:\n\t\t\tSession.MaxAhead = Data.FrameInfo.Delay;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tSave a multiplayer game (this event is only generated in multiplayer mode)\n\t\t*/\n\t\tcase SAVEGAME:\n\t\t\t/*\n\t\t\t** Show the user what's going on with a message box (but only if\n\t\t\t** we're not already inside a dialog box routine!)\n\t\t\t*/\n\t\t\tif (SpecialDialog == SDLG_NONE) {\n\t\t\t\tCDTimerClass<SystemTimerClass> timer;\n\t\t\t\t//timer.Start();\n\t\t\t\ttimer = TICKS_PER_SECOND * 4;\n\n\t\t\t\tWWMessageBox().Process(TXT_SAVING_GAME, TXT_NONE);\n\n\t\t\t\tSave_Game (-1, (char *)Text_String(TXT_MULTIPLAYER_GAME));\n\n\t\t\t\twhile (timer > 0) {\n\t\t\t\t\tCall_Back();\n\t\t\t\t}\n\n\t\t\t\tHidPage.Clear();\n\t\t\t\tMap.Flag_To_Redraw(true);\n\t\t\t\tMap.Render();\n\t\t\t}\n\t\t\telse {\n\t\t\t\tSave_Game (-1, (char *)Text_String(TXT_MULTIPLAYER_GAME));\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t** Add a new player to the game:\n\t\t** - Form a network connection to him\n\t\t** - Add his name, ID, House etc to our list of players\n\t\t** - Re-sort the ID array\n\t\t** - Place his units on the map\n\t\t*/\n\t\tcase ADDPLAYER:\n\t\t\tint i;\n\t\t\tprintf(\"ADDPLAYER EVENT!\\n\");\n\t\t\tfor (i=0;i<Data.Variable.Size;i++) {\n\t\t\t\tprintf(\"%d\\n\", ((char *)Data.Variable.Pointer)[i]);\n\t\t\t}\n\t\t\tif (ID != PlayerPtr->ID) {\n\t\t\t\tdelete [] Data.Variable.Pointer;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t//\n\t\t// This event tells all systems to use new timing values.  It's like\n\t\t// RESPONSE_TIME, only it works.  It's only used with the\n\t\t// COMM_MULTI_E_COMP protocol.\n\t\t//\n\t\tcase TIMING:\n#if(TIMING_FIX)\n\t\t\t//\n\t\t\t// If MaxAhead is about to increase, we're vulnerable to a Packet-\n\t\t\t// Received-Too-Late error, if any system generates an event after\n\t\t\t// this TIMING event, but before it executes.  So, record the\n\t\t\t// period of vulnerability's frame start & end values, so we\n\t\t\t// can reschedule these events to execute after it's over.\n\t\t\t//\n\t\t\tif (Data.Timing.MaxAhead > Session.MaxAhead) {\n\t\t\t\tNewMaxAheadFrame1 = Frame;\n\t\t\t\tNewMaxAheadFrame2 = Frame + Data.Timing.MaxAhead;\n\t\t\t}\n#endif\n\t\t\tSession.DesiredFrameRate = Data.Timing.DesiredFrameRate;\n\t\t\tSession.MaxAhead = Data.Timing.MaxAhead;\n\n#ifndef WOLAPI_INTEGRATION\n\t\t\t/*\n\t\t\t** If spawned from WChat then we should be getting poked every minute. If not then\n\t\t\t** deliberately break the max ahead value\n\t\t\t*/\n#ifdef WIN32\n\t\t\tif (Special.IsFromWChat) {\n\t\t\t\tSession.MaxAhead += DDEServer.Time_Since_Heartbeat()/(70*60);\n\t\t\t}\n#endif\t//WIN32\n#endif\t//\t!WOLAPI_INTEGRATION\n\t\t\tif (Debug_Print_Events) {\n\t\t\t\tprintf(\"DesiredFrameRate:%d MaxAhead:%d \",\n\t\t\t\t\tSession.DesiredFrameRate,\n\t\t\t\t\tSession.MaxAhead);\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\t//\n\t\t// This event tells all systems what the other systems' process\n\t\t// timing requirements are; it's used to compute a desired frame rate\n\t\t// for the game.\n\t\t//\n\t\tcase PROCESS_TIME:\n\t\t\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\t\t\tif (ID == Session.Players[i]->Player.ID) {\n\t\t\t\t\tSession.Players[i]->Player.ProcessTime = Data.ProcessTime.AverageTicks;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\tcase PROPOSE_DRAW:\n\t\t\tif( ID == PlayerPtr->ID )\n\t\t\t{\n\t\t\t\tif( Scen.bOtherProposesDraw )\n\t\t\t\t{\n\t\t\t\t\t//\tBoth sides agree to draw. Game will end in a tie.\n\t\t\t\t\tScen.bLocalProposesDraw = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tScen.bLocalProposesDraw = true;\n\t\t\t\tSession.Messages.Add_Message( NULL, 0, TXT_WOL_DRAW_PROPOSED_LOCAL, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif( Scen.bLocalProposesDraw )\n\t\t\t\t{\n\t\t\t\t\t//\tBoth sides agree to draw. Game will end in a tie.\n\t\t\t\t\tScen.bOtherProposesDraw = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tchar szMessage[ 100 ];\n\t\t\t\tfor (i = 0; i < Session.Players.Count(); i++) \n\t\t\t\t{\n\t\t\t\t\tif (ID == Session.Players[i]->Player.ID) \n\t\t\t\t\t{\n\t\t\t\t\t\tsprintf( szMessage, TXT_WOL_DRAW_PROPOSED_OTHER, Session.Players[i]->Name );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tScen.bOtherProposesDraw = true;\n\t\t\t\tSession.Messages.Add_Message( NULL, 0, szMessage, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );\n\t\t\t}\n\t\t\tSound_Effect( VOC_INCOMING_MESSAGE );\n\t\t\tbreak;\n\n\t\tcase RETRACT_DRAW:\n\t\t\tif( ID == PlayerPtr->ID )\n\t\t\t{\n\t\t\t\tScen.bLocalProposesDraw = false;\n\t\t\t\tSession.Messages.Add_Message( NULL, 0, TXT_WOL_DRAW_RETRACTED_LOCAL, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tchar szMessage[ 100 ];\n\t\t\t\tfor (i = 0; i < Session.Players.Count(); i++) \n\t\t\t\t{\n\t\t\t\t\tif (ID == Session.Players[i]->Player.ID) \n\t\t\t\t\t{\n\t\t\t\t\t\tsprintf( szMessage, TXT_WOL_DRAW_RETRACTED_OTHER, Session.Players[i]->Name );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tScen.bOtherProposesDraw = false;\n\t\t\t\tSession.Messages.Add_Message( NULL, 0, szMessage, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );\n\t\t\t}\n\t\t\tSound_Effect( VOC_INCOMING_MESSAGE );\n\t\t\tbreak;\n#endif\n\n\t\t/*\n\t\t**\tDefault: do nothing.\n\t\t*/\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tif (Debug_Print_Events) {\n\t\tprintf(\"\\n\");\n\t}\n\n}\n"
  },
  {
    "path": "CODE/EVENT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/EVENT.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : EVENT.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/09/94                                                     *\n *                                                                                             *\n *                  Last Update : December 9, 1994 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef EVENT_H\n#define EVENT_H\n\n/*\n**\tThis event class is used to contain all external game events (things that the player can\n**\tdo at any time) so that these events can be transported between linked computers. This\n**\tencapsulation is required in order to ensure that each event affects all computers at the\n**\tsame time (same game frame).\n** NOTE: If you add or remove an event type, you must also update the globals\n** EventLength[] and EventNames[].\n*/\nclass EventClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tAll external events are identified by these labels.\n\t\t*/\n\t\ttypedef enum EventType {\n\t\t\tEMPTY,\n\n\t\t\tALLY,\t\t\t\t\t// Make allie of specified house.\n\t\t\tMEGAMISSION,\t\t// Full change of mission with target and destination.\n\t\t\tMEGAMISSION_F,\t\t// Full change of mission with target and destination, and formation overrides.\n\t\t\tIDLE,\t\t\t\t\t// Request to enter idle mode.\n\t\t\tSCATTER,\t\t\t\t// Request to scatter from current location.\n\t\t\tDESTRUCT,\t\t\t// Self destruct request (surrender action).\n\t\t\tDEPLOY,\t\t\t\t// MCV is to deploy at current location.\n\t\t\tPLACE,\t\t\t\t// Place building at location specified.\n\t\t\tOPTIONS,\t\t\t\t// Bring up options screen.\n\t\t\tGAMESPEED,\t\t\t// Set game speed\n\t\t\tPRODUCE,\t\t\t\t// Start or Resume production.\n\t\t\tSUSPEND,\t\t\t\t// Suspend production.\n\t\t\tABANDON,\t\t\t\t// Abandon production.\n\t\t\tPRIMARY,\t\t\t\t// Primary factory selected.\n\t\t\tSPECIAL_PLACE,\t\t// Special target location selected\n\t\t\tEXIT,\t\t\t\t\t// Exit game.\n\t\t\tANIMATION,\t\t\t// Flash ground as movement feedback.\n\t\t\tREPAIR,\t\t\t\t// Repair specified object.\n\t\t\tSELL,\t\t\t\t\t//\tSell specified object.\n\t\t\tSELLCELL,\t\t\t// Sell wall at specified cell.\n\t\t\tSPECIAL,\t\t\t\t// Special options control.\n\n\t\t\t// Private events.\n\t\t\tFRAMESYNC,\t\t\t// Game-connection packet; includes Scenario CRC & sender's frame #\n\t\t\t\t\t\t\t\t\t// Used to initiate game connection phase & to reconnect;\n\t\t\t\t\t\t\t\t\t// When one of these is received, the receiver knows there are\n\t\t\t\t\t\t\t\t\t// no associated commands in this packet.\n\t\t\tMESSAGE,\t\t\t\t// Message to another player (The message is the 40 bytes\n\t\t\t\t\t\t\t\t\t// after the event class).\n\t\t\tRESPONSE_TIME,\t\t// use a new propagation delay value\n\t\t\tFRAMEINFO,\t\t\t// Game-heartbeat packet; includes Game CRC & command count\n\t\t\t\t\t\t\t\t\t// All packets sent for a frame are prefixed with one of these\n\t\t\tSAVEGAME,\t\t\t// allows multiplayer games to save\n\t\t\tARCHIVE,\t\t\t\t// Updates archive target on specified object.\n\t\t\tADDPLAYER,\t\t\t// Add a new player\n\n\t\t\tTIMING,\t\t\t\t// new timing values for all systems to use\n\t\t\tPROCESS_TIME,\t\t// a system's average processing time, in ticks per frame\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t\tPROPOSE_DRAW,\t\t//\tPlayers proposes that 2-player game be called a stalemate.\n\t\t\tRETRACT_DRAW,\t\t//\tPlayer retracts proposed draw offer.\n#endif\n\n\t\t\tLAST_EVENT,\t\t\t// one past the last event\n\t\t} EventType;\n\n\t\tEventType Type;\t\t// Type of queue command object.\n\n\t\t/*\n\t\t** 'Frame' is the frame that the command should execute on.\n\t\t** 27 bits gives over 25 days of playing time without wrapping,\n\t\t** at 30 frames per second, so it should be plenty!\n\t\t*/\n\t\tunsigned Frame : 26;\n\n\t\t/*\n\t\t** House index of the player originating this event\n\t\t*/\n\t\tunsigned ID : 5;\n\n\t\t/*\n\t\t** This bit tells us if we've already executed this event.\n\t\t*/\n\t\tunsigned IsExecuted: 1;\n\n\t\t/*\n\t\t**\tThis union contains the specific data that the event requires.\n\t\t*/\n\t\tunion {\n\t\t\tstruct {\n\t\t\t\tSpecialClass\tData;\t\t// The special option flags.\n\t\t\t} Options;\n\t\t\tstruct {\n\t\t\t\tCELL\t\t\tCell;\t\t\t// The cell to sell wall at.\n\t\t\t} SellCell;\n\t\t\tstruct {\n\t\t\t\txTargetClass\tWhom;\t\t\t// The object to apply the event to.\n\t\t\t} Target;\n\t\t\tstruct {\n\t\t\t\tAnimType\t\tWhat;\t\t\t// The animation to create.\n\t\t\t\tHousesType\tOwner;\t\t// The owner of the animation (when it matters).\n\t\t\t\tCOORDINATE\t\t\tWhere;\t\t// The location to place the animation.\n\t\t\t} Anim;\n\t\t\tstruct {\n\t\t\t\tint \t\t\tValue;\t\t// general-purpose data\n\t\t\t} General;\n\t\t\tstruct {\n\t\t\t\txTargetClass\tWhom;\t\t\t// Whom to apply mission to.\n\t\t\t\tMissionType\tMission;\t\t// What mission to apply.\n\t\t\t\txTargetClass\tTarget;\t\t// Target to assign.\n\t\t\t\txTargetClass\tDestination;// Destination to assign.\n\t\t\t} MegaMission;\n\t\t\tstruct {\n\t\t\t\txTargetClass\tWhom;\t\t\t// Whom to apply mission to.\n\t\t\t\tMissionType\tMission;\t\t// What mission to apply.\n\t\t\t\txTargetClass\tTarget;\t\t// Target to assign.\n\t\t\t\txTargetClass\tDestination;// Destination to assign.\n\t\t\t\tSpeedType\tSpeed;\t\t// Formation override speed.\n\t\t\t\tMPHType\t\tMaxSpeed;\t// Formation override maximum speed.\n\t\t\t} MegaMission_F;\n\t\t\tstruct {\n\t\t\t\txTargetClass\tWhom;\t\t\t// Whom to apply mission to.\n\t\t\t\tMissionType Mission;\t\t// What mission to apply.\n\t\t\t} Mission;\n\t\t\tstruct {\n\t\t\t\txTargetClass\tWhom;\t\t\t// Whom to apply movement change to.\n\t\t\t\txTargetClass\tWhere;\t\t// Where to set NavCom to.\n\t\t\t} NavCom;\n\t\t\tstruct {\n\t\t\t\txTargetClass\tWhom;\t\t\t// Whom to apply attack change to.\n\t\t\t\txTargetClass\tTarget;\t\t// What to set TarCom to.\n\t\t\t} TarCom;\n\t\t\tstruct {\n\t\t\t\tRTTIType\t\tType;\n\t\t\t\tint\t\t\tID;\n\t\t\t} Specific;\n\t\t\tstruct {\n\t\t\t\tRTTIType\t\tType;\n\t\t\t\tCELL\t\t\tCell;\n\t\t\t} Place;\n\t\t\tstruct {\n\t\t\t\tint\t\t\tID;\n\t\t\t\tCELL\t\t\tCell;\n\t\t\t} Special;\n\n\t\t\t/*\n\t\t\t** This structure is used for FRAMEINFO, FRAMESYNC, and RESPONSE_TIME\n\t\t\t** events; exactly one of these will be sent each frame, whether there's\n\t\t\t** data that frame or not.\n\t\t\t** CRC: the game CRC when this packet was generated; used to detect sync errors\n\t\t\t** CommandCount: # of commands the sender has sent; used to detect missed packets\n\t\t\t** Delay: sender's propagation delay value for this frame\n\t\t\t*/\n\t\t\tstruct {\n\t\t\t\tunsigned long CRC;\n\t\t\t\tunsigned short CommandCount;\t// # commands sent so far\n\t\t\t\tunsigned char Delay;\t\t\t\t// propagation delay used this frame\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// (Frame - Delay = sender's current frame #)\n\t\t\t} FrameInfo;\n\t\t\t/*\n\t\t\t** This structure is used for the special variable-length event.  This event\n\t\t\t** can be anything the application wants it to be.  Its purpose is to allow\n\t\t\t** relatively large amounts of data to be associated with the event, without\n\t\t\t** bloating the size of this union (and thus all other event types).\n\t\t\t*/\n\t\t\tstruct {\n\t\t\t\tvoid * Pointer;\n\t\t\t\tunsigned long Size;\n\t\t\t} Variable;\n\n\t\t\t//\n\t\t\t// This structure sets new timing values for all systems in a multiplayer\n\t\t\t// game.  This structure replaces the RESPONSE_TIME event for\n\t\t\t// the COMM_MULTI_E_COMP protocol.\n\t\t\t//\n\t\t\tstruct {\n\t\t\t\tunsigned short DesiredFrameRate;\n\t\t\t\tunsigned short MaxAhead;\n\t\t\t} Timing;\n\n\t\t\t//\n\t\t\t// This structure is transmitted by all systems, and is used to compute\n\t\t\t// the \"desired\" frame rate for the game.\n\t\t\t//\n\t\t\tstruct {\n\t\t\t\tunsigned short AverageTicks;\n\t\t\t} ProcessTime;\n\n\t\t} Data;\n\n\t\t//-------------- Constructors ---------------------\n\t\tEventClass(void) {Type = EMPTY;};\n\t\tEventClass(SpecialClass data);\n\t\tEventClass(EventType type, TargetClass target);\n\t\tEventClass(EventType type);\n\t\tEventClass(EventType type, int val);\n\t\tEventClass(EventType type, CELL cell);\n\t\tEventClass(EventType type, TargetClass src, TargetClass dest);\n\t\tEventClass(TargetClass src, MissionType mission, TargetClass target=TARGET_NONE, TargetClass destination=TARGET_NONE);\n\n\t\tEventClass(TargetClass src, MissionType mission, TargetClass target, TargetClass destination, SpeedType speed, MPHType maxspeed);\n\n\t\tEventClass(EventType type, RTTIType object, int id);\n\t\tEventClass(EventType type, RTTIType object, CELL cell);\n\t\tEventClass(EventType type, int id, CELL cell);\n\t\tEventClass(AnimType anim, HousesType owner, COORDINATE coord);\n\t\tEventClass(void *ptr, unsigned long size);\n\t\tEventClass(EventType type, void *ptr, unsigned long size);\n\n\t\t// Process the event.\n\t\tvoid Execute(void);\n\n\t\tint operator == (EventClass & q) {\n\t\t\treturn memcmp(this, &q, sizeof(q)) == 0;\n\t\t};\n\n\t\tstatic unsigned char EventLength[LAST_EVENT];\n\t\tstatic char * EventNames[LAST_EVENT];\n};\n\n#endif\n"
  },
  {
    "path": "CODE/EXPAND.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/EXPAND.CPP 7     3/17/97 1:05a Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : EXPAND.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/03/95                                                     *\n *                                                                                             *\n *                  Last Update : Mar 01, 1997 [V.Grippi]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   EListClass::Draw_Entry -- Draws entry for expansion scenario.                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n#ifdef FIXIT_VERSION_3\n#include \"WolStrng.h\"\n#endif\n\n//#define CS_DEBUG\n\n#define ARRAYOFFSET 20\n\n\n/***********************************************************************************************\n * Expansion_CS_Present -- Is the Counterstrike expansion available?                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   true if counterstrike installed                                                   *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/5/97 1:59PM ST : Fixed to check for EXPAND.MIX                                         *\n *=============================================================================================*/\nbool Expansion_CS_Present(void)\n{\n\t//\tajw 9/29/98\n\treturn Is_Counterstrike_Installed();\n//\tRawFileClass file(\"EXPAND.MIX\");\n//\treturn(file.Is_Available());\n}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n/***********************************************************************************************\n * Expansion_AM_Present -- Is the Aftermath expansion available?                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   true if AfterMath is installed                                                    *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    7/9/97 1:59PM BG : Fixed to check for EXPAND2.MIX                                        *\n *=============================================================================================*/\nbool Expansion_AM_Present(void)\n{\n\t//\tajw 9/29/98\n\treturn Is_Aftermath_Installed();\n//\tRawFileClass file(\"EXPAND2.MIX\");\n//\treturn(file.Is_Available());\n}\n#endif\n\n\nconst char* ExpandNames[] = {\n\t\"SCG20EA\",\n\t\"SCG21EA\",\n\t\"SCG22EA\",\n\t\"SCG23EA\",\n\t\"SCG24EA\",\n\t\"SCG26EA\",\n\t\"SCG27EA\",\n\t\"SCG28EA\",\n\t\"SCU31EA\",\n\t\"SCU32EA\",\n\t\"SCU33EA\",\n\t\"SCU34EA\",\n\t\"SCU35EA\",\n\t\"SCU36EA\",\n\t\"SCU37EA\",\n\t\"SCU38EA\",\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\"SCG43EA\",\t\t// Harbor Reclamation\n\t\"SCG41EA\",\t\t// In the nick of time\n\t\"SCG40EA\",\t\t// Caught in the act\n\t\"SCG42EA\",\t\t// Production Disruption\n\t\"SCG47EA\",\t\t// Negotiations\n\t\"SCG45EA\",\t\t// Monster Tank Madness\n\t\"SCG44EA\",\t\t// Time Flies\n\t\"SCG48EA\",\t\t// Absolut MADness\n\t\"SCG46EA\",\t\t// Pawn\n\n\t\"SCU43EA\",\t\t// Testing Grounds\n\t\"SCU40EA\",\t\t// Shock Therapy\n\t\"SCU42EA\",\t\t// Let's Make a Steal\n\t\"SCU41EA\",\t\t// Test Drive\n\t\"SCU45EA\",\t\t// Don't Drink The Water\n\t\"SCU44EA\",\t\t// Situation Critical\n\t\"SCU46EA\",\t\t// Brothers in Arms\n\t\"SCU47EA\",\t\t// Deus Ex Machina\n\t\"SCU48EA\",\t\t// Grunyev Revolution\n#endif\n\tNULL\n\t};\n\nconst char* TestNames2[] = {\n\t\"SCG01EA\",\n\t\"SCG02EA\",\n\t\"SCG03EA\",\n\t\"SCG04EA\",\n\t\"SCG05EA\",\n\t\"SCG06EA\",\n\t\"SCG07EA\",\n\t\"SCG08EA\",\n\t\"SCU01EA\",\n\t\"SCU02EA\",\n\t\"SCU03EA\",\n\t\"SCU04EA\",\n\t\"SCU05EA\",\n\t\"SCU06EA\",\n\t\"SCU07EA\",\n\t\"SCU08EA\",\n\t\"SCU09EA\",\n\tNULL\n};\n\n#ifdef GERMAN\nconst char* XlatNames[] = {\n\t\"Zusammenstoss\",\n\t\"Unter Tage\",\n\t\"Kontrollierte Verbrennung\",\n\t\"Griechenland 1 - Stavros\",\n\t\"Griechenland 2 - Evakuierung\",\n\t\"Sibirien 1 - Frische Spuren\",\n\t\"Sibirien 2 - In der Falle\",\n\t\"Sibirien 3 - Wildnis\",\n\t\"Das Feld der Ehre\",\n\t\"Belagerung\",\n\t\"Mausefalle\",\n\t\"Teslas Erbe\",\n\t\"Soldat Volkov\",\n\t\"Die Spitze der Welt\",\n\t\"Paradoxe Gleichung\",\n\t\"Nukleare Eskalation\",\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\"Ein sicherer Hafen\",\t\t\t  //\t\"SCG43EA\",\t\t// Harbor Reclamation\n\t\"Zeitkritische Routine\",\t\t  //\t\"SCG41EA\",\t\t// In the nick of time\n\t\"Auf frischer Tat ertappt\",\t  //\t\"SCG40EA\",\t\t// Caught in the act\n\t\"Drastischer Baustopp\",\t\t\t  //\t\"SCG42EA\",\t\t// Production Disruption\n\t\"Harte Verhandlungen\",\t\t\t  //\t\"SCG47EA\",\t\t// Negotiations\n\t\"Ferngelenktes Kriegsspielzeug\",//\t\"SCG45EA\",\t\t// Monster Tank Madness\n\t\"Licht aus\",\t\t\t\t\t\t  //\t\"SCG44EA\",\t\t// Time Flies\n\t\"Molekulare Kriegsfhrung\",\t  //\t\"SCG48EA\",\t\t// Absolut MADness\n\t\"Bauernopfer\",\t\t\t\t\t\t  //\t\"SCG46EA\",\t\t// Pawn\n\n\t\"Testgelnde\",\t\t\t\t\t\t  //\t\"SCU43EA\",\t\t// Testing Grounds\n\t\"Schocktherapie\",\t\t\t\t\t  //\t\"SCU40EA\",\t\t// Shock Therapy\n\t\"Der Letzte seiner Art\",\t\t  //\t\"SCU42EA\",\t\t// Let's Make a Steal\n\t\"Probefahrt\",\t\t\t\t\t\t  //\t\"SCU41EA\",\t\t// Test Drive\n\t\"Schlaftrunk\",\t\t\t\t\t\t  //\t\"SCU45EA\",\t\t// Don't Drink The Water\n\t\"Der jngste Tag\",\t\t\t\t  //\t\"SCU44EA\",\t\t// Situation Critical\n\t\"Waffenbrder\",\t\t\t\t\t  //\t\"SCU46EA\",\t\t// Brothers in Arms\n\t\"Deus Ex Machina\",\t\t\t\t  //\t\"SCU47EA\",\t\t// Deus Ex Machina\n\t\"Die Replikanten von Grunyev\",  //\t\"SCU48EA\",\t\t// Grunyev Revolution\n\n#endif\n\tNULL\n};\n\n#endif\n\n#ifdef FRENCH\nconst char* XlatNames[] = {\n\t\"Gaz Sarin 1: Ravitaillement Fatal\",\n\t\"Gaz Sarin 2: En Sous-sol\",\n\t\"Gaz Sarin 3: Attaque Chirurgicale\",\n\t\"Grce Occupe 1: Guerre Prive\",\n\t\"Grce Occupe 2: Evacuation\",\n\t\"Conflit Sibrien 1: Traces Fraches\",\n\t\"Conflit Sibrien 2: Pris au Pige\",\n\t\"Conflit Sibrien 3: Terres de Glace\",\n\t\"Mise  l'Epreuve\",\n\t\"Assigs\",\n\t\"La Souricire\",\n\t\"L'Hritage de Tesla\",\n\t\"Tandem de Choc\",\n\t\"Jusqu'au Sommet du Monde\",\n\t\"Effets Secondaires\",\n\t\"Intensification nuclaire\",\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\"Le vieux port\",\t\t\t\t//\t\"SCG43EA\",\t\t// Harbor Reclamation\n\"Juste  temps\",\t\t\t\t//\t\"SCG41EA\",\t\t// In the nick of time\n\"La main dans le sac\",\t\t//\t\"SCG40EA\",\t\t// Caught in the act\n\"Production interrompue\",\t//\t\"SCG42EA\",\t\t// Production Disruption\n\"Ngociations\",\t\t\t\t//\t\"SCG47EA\",\t\t// Negotiations\n\"Tanks en folie!\",\t\t\t//\t\"SCG45EA\",\t\t// Monster Tank Madness\n\"Le temps passe\",\t\t\t\t//\t\"SCG44EA\",\t\t// Time Flies\n\"Dmence absolue\",\t\t\t//\t\"SCG48EA\",\t\t// Absolut MADness\n\"Le pion\",\t\t\t\t\t\t//\t\"SCG46EA\",\t\t// Pawn\n\n\"Terrains d'essais\",\t\t\t//\t\"SCU43EA\",\t\t// Testing Grounds\n\"Thrapie de choc\",\t\t\t//\t\"SCU40EA\",\t\t// Shock Therapy\n\"Au voleur!\",\t\t\t\t\t//\t\"SCU42EA\",\t\t// Let's Make a Steal\n\"Essai de conduite\",\t\t\t//\t\"SCU41EA\",\t\t// Test Drive\n\"Ne buvez pas la tasse\",\t//\t\"SCU45EA\",\t\t// Don't Drink The Water\n\"Situation critique\",\t\t//\t\"SCU44EA\",\t\t// Situation Critical\n\"Frres d'armes\",\t\t\t\t//\t\"SCU46EA\",\t\t// Brothers in Arms\n\"Deus Ex Machina\",\t\t\t//\t\"SCU47EA\",\t\t// Deus Ex Machina\n\"La Rvolution de Grunyev\",//\t\"SCU48EA\",\t\t// Grunyev Revolution\n\n#endif\n\n\tNULL,\n};\n\n#endif\n\n\n\n#ifndef WIN32\t //VG\n\n\t#define\tOPTION_WIDTH\t236\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n#error Can never again build without WIN32 defined.\n\t#define\tOPTION_HEIGHT\t162\n#else\n\t#define\tOPTION_HEIGHT\t162\n#endif\n\t#define\tOPTION_X\t\t\t((320 - OPTION_WIDTH) / 2)\n\t#define\tOPTION_Y\t\t\t(200 - OPTION_HEIGHT) / 2\n\n#else\n\n\t#define\tOPTION_WIDTH\t560\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t#define\tOPTION_HEIGHT\t332\n#else\n\t#define\tOPTION_HEIGHT\t300\n#endif\n\t#define\tOPTION_X\t\t\t((640 - OPTION_WIDTH) / 2)\n\t#define\tOPTION_Y\t\t\t(400 - OPTION_HEIGHT) / 2\n#endif\n\nstruct EObjectClass\n{\n\tHousesType House;\n\tint Scenario;\n\tchar Name[128];\n\tchar FullName[128];\n};\n\n\n/*\n**\tDerived from list class to handle expansion scenario listings. The listings\n**\tare recorded as EObjectClass objects. The data contained specifies the scenario\n**\tnumber, side, and text description.\n*/\nclass EListClass : public ListClass\n{\n\tpublic:\n\t\tEListClass(int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down) :\n\t\t\tListClass(id, x, y, w, h, flags, up, down) {};\n\n\t\tvirtual int Add_Object(EObjectClass * obj) {\n\t\t\treturn(ListClass::Add_Item((char const *)obj));\n\t\t}\n\t\tvirtual EObjectClass * Get_Object(int index) const {\n\t\t\treturn((EObjectClass *)ListClass::Get_Item(index));\n\t\t}\n\t\tvirtual EObjectClass * Current_Object(void) {\n\t\t\treturn((EObjectClass *)ListClass::Current_Item());\n\t\t}\n\n\tprotected:\n\t\tvirtual void Draw_Entry(int index, int x, int y, int width, int selected);\n\n\tprivate:\n\t\tvirtual int Add_Item(char const * text) {return(ListClass::Add_Item(text));};\n\t\tvirtual int Add_Item(int text) {return(ListClass::Add_Item(text));};\n\t\tvirtual char const * Current_Item(void) const {return(ListClass::Current_Item());};\n\t\tvirtual char const * Get_Item(int index) const {return(ListClass::Get_Item(index));};\n};\n\n\n/***********************************************************************************************\n * EListClass::Draw_Entry -- Draws entry for expansion scenario.                               *\n *                                                                                             *\n *    This overrides the normal list class draw action so that the scenario name will be       *\n *    displayed along with the house name.                                                     *\n *                                                                                             *\n * INPUT:   index    -- The index of the entry that should be drawn.                           *\n *                                                                                             *\n *          x,y      -- Coordinate of upper left region to draw the entry into.                *\n *                                                                                             *\n *          width    -- Width of region (pixels) to draw the entry.                            *\n *                                                                                             *\n *          selected -- Is this entry considered selected?                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/17/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid EListClass::Draw_Entry(int index, int x, int y, int width, int selected)\n{\n\tchar buffer[128];\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\tint text = TXT_NONE;\n\tif (Get_Object(index)->House == HOUSE_GOOD) {\n\t\ttext = TXT_ALLIES;\n\t} else {\n\t\ttext = TXT_SOVIET;\n\t}\n\tsprintf(buffer, \"%s: %s\", Text_String(text), Get_Object(index)->Name);\n\n\tTextPrintType flags = TextFlags;\n\n\tif (selected) {\n\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\tLogicPage->Fill_Rect (x, y, x + width - 1, y + LineHeight - 1, 1);\n\t} else {\n\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t}\n\t}\n\n#ifndef WIN32\n        Conquer_Clip_Text_Print(buffer, x, y, scheme, TBLACK, flags & ~(TPF_CENTER), width, Tabs);\n#else\n\tConquer_Clip_Text_Print(buffer, x + 100, y, scheme, TBLACK, flags & ~(TPF_CENTER), width, Tabs);\n#endif\n}\n\n#ifdef FIXIT_VERSION_3\nbool Expansion_Dialog( bool bCounterstrike )\t\t//\tIf not bCounterstrike, then this was called for Aftermath.\n#else\nbool Expansion_Dialog(void)\n#endif\n{\n\tGadgetClass * buttons = NULL;\n\n#ifndef WIN32\n\tTextButtonClass ok(200, TXT_OK, TPF_BUTTON, OPTION_X+40, OPTION_Y+OPTION_HEIGHT-15);\n\tTextButtonClass cancel(201, TXT_CANCEL, TPF_BUTTON, OPTION_X+OPTION_WIDTH-85, OPTION_Y+OPTION_HEIGHT-15);\n#else\n\tTextButtonClass ok(200, TXT_OK, TPF_BUTTON, OPTION_X+40, OPTION_Y + OPTION_HEIGHT - 50 );\n\tTextButtonClass cancel(201, TXT_CANCEL, TPF_BUTTON, OPTION_X+OPTION_WIDTH-85, OPTION_Y + OPTION_HEIGHT - 50 );\n#endif\n\n#ifndef WIN32\n\tEListClass list(202, OPTION_X + 20, OPTION_Y+20, OPTION_WIDTH-40, OPTION_HEIGHT-40, TPF_BUTTON, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n#else\n\tEListClass list(202, OPTION_X+35, OPTION_Y + 30, OPTION_WIDTH-70, OPTION_HEIGHT - 85, TPF_BUTTON, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\n#endif\n\tbuttons = &ok;\n\tcancel.Add(*buttons);\n\tlist.Add(*buttons);\n\n\t/*\n\t**\tAdd in all the expansion scenarios.\n\t*/\n\tCCFileClass file;\n\tchar buffer[128], buffer2[128];\n\tchar * sbuffer = (char*)_ShapeBuffer;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98 - Though disgusted.\n\tfor (int index = 20; index < (36+18); index++) {\n#else\n\tfor (int index = 20; index < 36; index++) {\n#endif\n\n#ifndef CS_DEBUG\n\t\tstrcpy(buffer,ExpandNames[index - 20]);\n\t\tstrcpy(buffer2, ExpandNames[index - 20]);\n#else\n\t\tstrcpy(buffer, TestNames2[index]);\n\t\tstrcpy(buffer2, TestNames2[index]);\n#endif\n\t\tif(buffer[0] == NULL)\n\t\t   break;\n\n     \tstrcat(buffer, \".INI\");\n\t\tstrcat(buffer2, \".INI\");\n\t\tScen.Set_Scenario_Name(buffer);\n\t\tScen.Scenario = index;\n\t\tfile.Set_Name(buffer);\n#ifdef FIXIT_VERSION_3\n\t\tbool bOk;\n\t\tif( index < 36 )\n\t\t\tbOk = bCounterstrike;\n\t\telse\n\t\t\tbOk = !bCounterstrike;\n\n\t\tif( bOk && file.Is_Available() )\n\t\t{\n#else\t//\tFIXIT_VERSION_3\n\t\tif (file.Is_Available()) {\n#endif\t//\tFIXIT_VERSION_3\n\t\t    EObjectClass * obj = new EObjectClass;\n            switch(buffer[2]){\n\n\t\tcase 'G':\n\t\tcase 'g':\n\t\t\tfile.Read(sbuffer, 2000);\n\t\t\tsbuffer[2000] = '\\r';\n\t\t\tsbuffer[2000+1] = '\\n';\n\t\t\tsbuffer[2000+2] = '\\0';\n\t\t\tWWGetPrivateProfileString(\"Basic\", \"Name\", \"x\", buffer, sizeof(buffer), sbuffer);\n#if defined(GERMAN) || defined(FRENCH)\n\t\t\tstrcpy(obj->Name, XlatNames[index - ARRAYOFFSET]);\n#else\n\t\t\tstrcpy(obj->Name, buffer);\n#endif\n//\t\t\tstrcpy(obj->Name, buffer);\n\t\t\tstrcpy(obj->FullName, buffer2);\n\t\t\tobj->House = HOUSE_GOOD;\n\t\t\tobj->Scenario = index;\n\t\t\tlist.Add_Object(obj);\n\t\t\tbreak;\n\n\t\tcase 'U':\n\t\tcase 'u':\n\t\t  \tfile.Read(sbuffer, 2000);\n\t\t    \tsbuffer[2000] = '\\r';\n\t\t        sbuffer[2000+1] = '\\n';\n\t\t\tsbuffer[2000+2] = '\\0';\n\t\t\tWWGetPrivateProfileString(\"Basic\", \"Name\", \"x\", buffer, sizeof(buffer), sbuffer);\n#if defined(GERMAN) || defined(FRENCH)\n\t\t\tstrcpy(obj->Name, XlatNames[index - ARRAYOFFSET]);\n#else\n\t\t\tstrcpy(obj->Name, buffer);\n#endif\n//\t\t     \tstrcpy(obj->Name, buffer);\n\t\t\tstrcpy(obj->FullName, buffer2);\n\t\t\tobj->House = HOUSE_BAD;\n\t\t\tobj->Scenario = index;\n\t\t\tlist.Add_Object(obj);\n\t       \t\tbreak;\n\n\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t    }\n\t}\n\n\tSet_Logic_Page(SeenBuff);\n\tbool recalc = true;\n\tbool display = true;\n\tbool process = true;\n\tbool okval = true;\n\n\n\twhile (process) {\n\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = true;\n\t\t}\n#endif\n\n\t\tCall_Back();\n\n\t\tif (display) {\n\t\t\tdisplay = false;\n\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t**\tLoad the background picture.\n\t\t\t*/\n\t\t\tLoad_Title_Page();\n\t\t\tCCPalette.Set();\n\n\t\t\tDialog_Box(OPTION_X, OPTION_Y, OPTION_WIDTH, OPTION_HEIGHT );\n#ifdef FIXIT_VERSION_3\n\t\t\tif( bCounterstrike )\n\t\t\t\tDraw_Caption( TXT_WOL_CS_MISSIONS, OPTION_X, OPTION_Y, OPTION_WIDTH);\n\t\t\telse\n\t\t\t\tDraw_Caption( TXT_WOL_AM_MISSIONS, OPTION_X, OPTION_Y, OPTION_WIDTH);\n#else\n\t\t\tDraw_Caption(TXT_NEW_MISSIONS, OPTION_X, OPTION_Y, OPTION_WIDTH);\n#endif\n\t\t\tbuttons->Draw_All();\n\t\t\tShow_Mouse();\n\t\t}\n\n\t\tKeyNumType input = buttons->Input();\n\t\tswitch (input) {\n\t\t\tcase 200|KN_BUTTON:\n\t\t\t      \tWhom = list.Current_Object()->House;\n\t\t\t\tScen.Scenario = list.Current_Object()->Scenario;\n\t\t\t\tstrcpy(Scen.ScenarioName, list.Current_Object()->FullName);\n\t\t\t\tprocess = false;\n\t\t\t\tokval = true;\n\t\t\t\tbreak;\n\n\t\t\tcase KN_ESC:\n\t\t\tcase 201|KN_BUTTON:\n\t\t\t\tprocess = false;\n\t\t\t\tokval = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\t\tWhom = list.Current_Object()->House;\n\t\t\t\tScen.Scenario = list.Current_Object()->Scenario;\n\t\t\t\tstrcpy(Scen.ScenarioName, list.Current_Object()->FullName);\n\t\t\t\tprocess = false;\n\t\t\t\tokval = true;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tFree up the allocations for the text lines in the list box.\n\t*/\n \tfor (index = 0; index < list.Count(); index++) {\n \t\tdelete list.Get_Object(index);\n \t}\n\n\treturn(okval);\n\n}\n\n"
  },
  {
    "path": "CODE/EXTERNS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /counterstrike/EXTERNS.H 2     3/10/97 6:23p Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : EXTERNS.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 27, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 27, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef EXTERNS_H\n#define EXTERNS_H\n\n#include\t\"cell.h\"\n\n#ifdef SCENARIO_EDITOR\n#include\t\"mapedit.h\"\n#endif\n#include\t\"techno.h\"\n#include\t\"type.h\"\n#include\t\"building.h\"\n#include\t\"unit.h\"\n#include\t\"credits.h\"\n#include\t\"goptions.h\"\n#include\t\"options.h\"\n#include\t\"infantry.H\"\n\n\nextern char _staging_buffer[32000];\nextern \"C\" {\nvoid _PRO(void);\n}\n\n/*\n**\tConvenient alias for MixFileClass<CDFileClass> object. This allows\n**\teasier entry into the code and less clutter.\n*/\ntypedef MixFileClass<CCFileClass>\tMFCD;\n\nextern bool IsVQ640;\nextern unsigned long GameVersion;\nextern bool Debug_MotionCapture;\nextern bool Debug_Rotate;\nextern bool Debug_Quiet;\nextern bool Debug_Cheat;\nextern bool Debug_Remap;\nextern bool Debug_Flag;\nextern bool Debug_Lose;\nextern bool Debug_Map;\nextern bool Debug_Win;\nextern bool Debug_Icon;\nextern bool Debug_Passable;\nextern bool Debug_Unshroud;\nextern bool Debug_Threat;\nextern bool Debug_Find_Path;\nextern bool Debug_Check_Map;\nextern bool Debug_Playtest;\n\nextern bool Debug_Heap_Dump;\nextern bool Debug_Smart_Print;\nextern bool Debug_Trap_Check_Heap;\nextern bool Debug_Modem_Dump;\nextern bool Debug_Print_Events;\n\nextern void const *LightningShapes;\n\nextern int NewINIFormat;\n\n\n#ifdef FIXIT_ANTS\nextern bool AntsEnabled;\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern bool NewUnitsEnabled;\nextern bool SecretUnitsEnabled;\nextern int MTankDistance;\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\nextern int CarrierLaunchDelay;\n#endif\n#endif\n\n#ifdef FIXIT_NAME_OVERRIDE\nextern char const * NameOverride[25];\nextern int NameIDOverride[25];\n#endif\n\n#ifdef WIN32\nextern bool\t\t\t\t\tGameInFocus;\nextern unsigned char \t*InterpolatedPalettes[100];\nextern BOOL\t\t\t\t\tPalettesRead;\nextern unsigned\t\t\tPaletteCounter;\nextern int \t\t\t\t\tAllDone;\nextern HANDLE \t\t\t\thInstance;\nextern bool \t\t\t\tInMovie;\nextern WinTimerClass\t*\t\tWindowsTimer;\nextern WWMouseClass *\t\tWWMouse;\nextern GraphicBufferClass\tHiddenPage;\n#define\tSeenPage\t\tSeenBuff\nextern GraphicBufferClass\t\tVisiblePage;\nextern GraphicViewPortClass\tSeenBuff;\nextern GraphicBufferClass\t\tSysMemPage;\nextern LPDIRECTSOUND\t\t\t\tSoundObject;\nextern LPDIRECTSOUNDBUFFER\t\tPrimaryBufferPtr;\nextern int\t\t\t\t\t\t\tScreenWidth;\nextern int\t\t\t\t\t\t\tScreenHeight;\nextern GraphicBufferClass\t\tModeXBuff;\n\n#else\n\nextern VideoBufferClass\t\tSeenPage;\nextern GraphicBufferClass\tSeenBuff;\nextern GraphicBufferClass &\tVisiblePage;\n#endif\n\n\n/*\n**\tDynamic global variables (these change or are initialized at run time).\n*/\nextern MissionControlClass\t\tMissionControl[MISSION_COUNT];\nextern char const *\t\t\t\tTutorialText[225];\nextern Buffer *\t\t\t\t\tTheaterBuffer;\nextern GetCDClass\t\t\t\t\tCDList;\nextern CCINIClass\t\t\t\t\tRuleINI;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern CCINIClass\t\t\t\t\tAftermathINI;\n#endif\nextern Benchmark *\t\t\t\tBenches;\nextern int\t\t\t\t\t\t\tMapTriggerID;\nextern int\t\t\t\t\t\t\tLogicTriggerID;\nextern PKey\t\t\t\t\t\t\tFastKey;\nextern PKey\t\t\t\t\t\t\tSlowKey;\nextern RulesClass\t\t\t\t\tRule;\nextern KeyboardClass *\t\t\tKeyboard;\nextern RandomStraw\t\t\t\tCryptRandom;\nextern RandomClass\t\t\t\tNonCriticalRandomNumber;\nextern CarryoverClass *\t\t\tCarryover;\nextern ScenarioClass\t\t\t\tScen;\nextern RemapControlType\t\t\tColorRemaps[PCOLOR_COUNT];\nextern RemapControlType\t\t\tMetalScheme;\nextern RemapControlType\t\t\tGreyScheme;\nextern VersionClass\t\t\t\tVerNum;\nextern bool\t\t\t\t\t\t\tSlowPalette;\nextern bool\t\t\t\t\t\t\tScoresPresent;\nextern bool\t\t\t\t\t\t\tAllowVoice;\nextern NewConfigType\t\t\t\tNewConfig;\nextern VoxType\t\t\t\t\t\tSpeakQueue;\nextern bool\t\t\t\t\t\t\tPlayerWins;\nextern bool\t\t\t\t\t\t\tPlayerLoses;\nextern bool\t\t\t\t\t\t\tPlayerRestarts;\nextern long\t\t\t\t\t\t\tFrame;\nextern VoxType\t\t\t\t\t\tSpeechRecord[2];\nextern void *\t\t\t\t\t\tSpeechBuffer[2];\nextern int\t\t\t\t\t\t\tPreserveVQAScreen;\nextern bool\t\t\t\t\t\t\tBreakoutAllowed;\nextern bool\t\t\t\t\t\t\tBrokeout;\n\nextern GameOptionsClass \t\tOptions;\n\nextern LogicClass \t\t\t\tLogic;\n#ifdef SCENARIO_EDITOR\nextern MapEditClass \t\t\t\tMap;\n#else\nextern MouseClass \t\t\t\tMap;\n#endif\nextern ScoreClass \t\t\t\tScore;\nextern MonoClass \t\t\t\t\tMonoArray[DMONO_COUNT];\nextern MFCD *\t\t\t\t\t\tTheaterData;\nextern MFCD *\t\t\t\t\t\tMoviesMix;\nextern MFCD *\t\t\t\t\t\tGeneralMix;\nextern MFCD *\t\t\t\t\t\tScoreMix;\nextern MFCD *\t\t\t\t\t\tMainMix;\nextern MFCD *\t\t\t\t\t\tConquerMix;\nextern ThemeClass \t\t\t\tTheme;\nextern SpecialClass \t\t\t\tSpecial;\n\n/*\n**\tGame object allocation and tracking classes.\n*/\nextern TFixedIHeapClass<AircraftClass>\t\t\t\t\t\tAircraft;\nextern TFixedIHeapClass<AnimClass>\t\t\t\t\t\t\tAnims;\nextern TFixedIHeapClass<BuildingClass>\t\t\t\t\t\tBuildings;\nextern TFixedIHeapClass<BulletClass>\t\t\t\t\t\tBullets;\nextern TFixedIHeapClass<FactoryClass>\t\t\t\t\t\tFactories;\nextern TFixedIHeapClass<HouseClass>\t\t\t\t\t\t\tHouses;\nextern TFixedIHeapClass<InfantryClass>\t\t\t\t\t\tInfantry;\nextern TFixedIHeapClass<OverlayClass>\t\t\t\t\t\tOverlays;\nextern TFixedIHeapClass<SmudgeClass>\t\t\t\t\t\tSmudges;\nextern TFixedIHeapClass<TeamClass>\t\t\t\t\t\t\tTeams;\nextern TFixedIHeapClass<TeamTypeClass>\t\t\t\t\t\tTeamTypes;\nextern TFixedIHeapClass<TemplateClass>\t\t\t\t\t\tTemplates;\nextern TFixedIHeapClass<TerrainClass>\t\t\t\t\t\tTerrains;\nextern TFixedIHeapClass<TriggerClass>\t\t\t\t\t\tTriggers;\nextern TFixedIHeapClass<UnitClass>\t\t\t\t\t\t\tUnits;\nextern TFixedIHeapClass<VesselClass>\t\t\t\t\t\tVessels;\nextern TFixedIHeapClass<TriggerTypeClass>\t\t\t\t\tTriggerTypes;\n\nextern TFixedIHeapClass<HouseTypeClass>\t\t\t\t\tHouseTypes;\nextern TFixedIHeapClass<BuildingTypeClass>\t\t\t\tBuildingTypes;\nextern TFixedIHeapClass<AircraftTypeClass>\t\t\t\tAircraftTypes;\nextern TFixedIHeapClass<InfantryTypeClass>\t\t\t\tInfantryTypes;\nextern TFixedIHeapClass<BulletTypeClass>\t\t\t\t\tBulletTypes;\nextern TFixedIHeapClass<AnimTypeClass>\t\t\t\t\t\tAnimTypes;\nextern TFixedIHeapClass<UnitTypeClass>\t\t\t\t\t\tUnitTypes;\nextern TFixedIHeapClass<VesselTypeClass>\t\t\t\t\tVesselTypes;\nextern TFixedIHeapClass<TemplateTypeClass>\t\t\t\tTemplateTypes;\nextern TFixedIHeapClass<TerrainTypeClass>\t\t\t\t\tTerrainTypes;\nextern TFixedIHeapClass<OverlayTypeClass>\t\t\t\t\tOverlayTypes;\nextern TFixedIHeapClass<SmudgeTypeClass>\t\t\t\t\tSmudgeTypes;\n\nextern FixedIHeapClass *\t\t\t\t\t\t\t\t\t\tHeapPointers[RTTI_COUNT];\n\nextern TFixedIHeapClass<WeaponTypeClass>\t\t\t\t\tWeapons;\nextern TFixedIHeapClass<WarheadTypeClass>\t\t\t\t\tWarheads;\n\nextern QueueClass<EventClass, MAX_EVENTS>\t\t\t\t\tOutList;\nextern QueueClass<EventClass, (MAX_EVENTS * 64)>\t\tDoList;\n\n#ifdef MIRROR_QUEUE\nextern QueueClass<EventClass, (MAX_EVENTS * 64)>\t\tMirrorList;\n#endif\n\nextern DynamicVectorClass<ObjectClass *>\t\t\t\t\tCurrentObject;\nextern DynamicVectorClass<TriggerClass *>\t\t\t\t\tLogicTriggers;\nextern DynamicVectorClass<TriggerClass *>\t\t\t\t\tMapTriggers;\nextern DynamicVectorClass<TriggerClass *> \t\t\t\tHouseTriggers[HOUSE_COUNT];\n\nextern BaseClass\t\t\t\t\t\t\t\t\t\t\t\t\tBase;\n\n/* These variables are used to keep track of the slowest speed of a team */\nextern MPHType TeamMaxSpeed[10];\nextern SpeedType TeamSpeed[10];\nextern bool FormMove;\nextern SpeedType FormSpeed;\nextern MPHType FormMaxSpeed;\n\nextern bool IsTanyaDead;\nextern bool SaveTanya;\n\nextern bool TimeQuake;\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern bool PendingTimeQuake;\nextern TARGET TimeQuakeCenter;\nextern fixed QuakeUnitDamage;\nextern fixed QuakeBuildingDamage;\nextern int QuakeInfantryDamage;\nextern int QuakeDelay;\nextern fixed ChronoTankDuration;\t\t// chrono override for chrono tanks\n#ifdef FIXIT_ENGINEER\t//\tchecked - ajw 9/28/98\nextern fixed EngineerDamage;\t\t\t// Amount of damage an engineer does\nextern fixed EngineerCaptureLevel;\t// Building damage level before engineer can capture\n#endif\n#endif\n\n/*\n**\tLoaded data file pointers.\n*/\nextern void const *\t\tMetal12FontPtr;\nextern void const *\t\tMapFontPtr;\nextern void const *\t\tVCRFontPtr;\nextern void const *\t\tTypeFontPtr;\nextern void const *\t\tFont3Ptr;\nextern void const *\t\tFont6Ptr;\nextern void const *\t\tEditorFont;\nextern void const *\t\tFont8Ptr;\nextern void const *\t\tFontLEDPtr;\nextern void const *\t\tScoreFontPtr;\nextern void const *\t\tGradFont6Ptr;\nextern char const *\t\tSystemStrings;\nextern char const *\t\tDebugStrings;\n\n/*\n**\tMiscellaneous globals.\n*/\nextern ChronalVortexClass\t\tChronalVortex;\nextern TTimerClass<SystemTimerClass> TickCount;\nextern bool\t\t\t\t\t\t\tPassedProximity;\t// used in display.cpp\nextern HousesType\t\t\t\t\tWhom;\nextern _VQAConfig\t\t\t\t\tAnimControl;\nextern long\t\t\t\t\t\t\tSpareTicks;\nextern long\t\t\t\t\t\t\tPathCount;\nextern long\t\t\t\t\t\t\tCellCount;\nextern long\t\t\t\t\t\t\tTargetScan;\nextern long\t\t\t\t\t\t\tSidebarRedraws;\nextern DMonoType\t\t\t\t\tMonoPage;\nextern bool\t\t\t\t\t\t\tGameActive;\nextern bool\t\t\t\t\t\t\tSpecialFlag;\nextern bool\t\t\t\t\t\t\tScenarioInit;\nextern HouseClass *\t\t\t\tPlayerPtr;\nextern PaletteClass \t\t\t\tCCPalette;\nextern PaletteClass \t\t\t\tBlackPalette;\nextern PaletteClass \t\t\t\tWhitePalette;\nextern PaletteClass \t\t\t\tGamePalette;\n//extern PaletteClass \t\t\t\tInGamePalette;\n#define InGamePalette GamePalette\nextern PaletteClass \t\t\t\tOriginalPalette;\nextern PaletteClass\t\t\t\tScorePalette;\nextern int\t\t\t\t\t\t\tBuildLevel;\nextern unsigned long\t\t\t\tScenarioCRC;\n\n#ifdef FIXIT_VERSION_3\nextern bool\t\t\t\t\t\t\tbAftermathMultiplayer;\t\t//\tIs multiplayer game being played with Aftermath rules?\n#else\nextern unsigned long \t\t\t\tPlayingAgainstVersion;\t\t// Negotiated version number\nextern bool\t\t\t\t\t\t\tVersion107InMix;\t\t\t\t// Is there a v1.07 in the game\n#endif\n\n#ifdef FIXIT_VERSION_3\t\t\t//\tFor endgame auto-sonar pulse.\nextern bool\t\t\t\t\t\t\tbAutoSonarPulse;\n#endif\n\n#ifdef SCENARIO_EDITOR\nextern CELL \t\t\t\t\t\tCurrentCell;\n#endif\n\nextern SessionClass\t\t\t\tSession;\nextern NullModemClass \t\t\tNullModem;\nextern IPXManagerClass \t \t\tIpx;\n\n#if(TEN)\nextern TenConnManClass\t\t\t*Ten;\n#endif\n\n#if(MPATH)\nextern MPlayerManClass\t\t\t*MPath;\n#endif\n\n#if(TIMING_FIX)\nextern int\t\t\t\t\t\t\t\t\t\tNewMaxAheadFrame1;\nextern int\t\t\t\t\t\t\t\t\t\tNewMaxAheadFrame2;\n#endif\n\nextern int\t\t\t\t\t\t\tSeed;\nextern int\t\t\t\t\t\t\tCustomSeed;\nextern GroundType  \t\t\t\tGround[LAND_COUNT];\n\n/*\n**\tConstant externs (data is not modified during game play).\n*/\nextern char const *\t\t\t\t\t\t\tMissions[MISSION_COUNT];\nextern char const\t\t\t\t\t\t\t\tKeys[];\nextern char const * const\t\t\t\t\tVQName[VQ_COUNT];\nextern int\t\t\t\t\t\t\t\t\t\tCrateData[CRATE_COUNT];\nextern char const * const\t\t\t\t\tCrateNames[CRATE_COUNT];\nextern int\t\t\t\t\t\t\t\t\t\tCrateShares[CRATE_COUNT];\nextern AnimType\t\t\t\t\t\t\t\tCrateAnims[CRATE_COUNT];\nextern char const * const\t\t\t\t\tSpecialWeaponName[SPC_COUNT];\nextern int const\t\t\t\t\t\t\t\tSpecialWeaponHelp[SPC_COUNT];\nextern char const * const\t\t\t\t\tSpecialWeaponFile[SPC_COUNT];\nextern char const * const\t\t\t\t\tArmorName[ARMOR_COUNT];\nextern char const * const\t\t\t\t\tQuarryName[QUARRY_COUNT];\nextern char const * const\t\t\t\t\tFormationName[FORMATION_COUNT];\nextern long const\t\t\t\t\t\t\t\tPlayCodes[];\nextern long const\t\t\t\t\t\t\t\tCheatCodes[];\n//extern char const * const\t\t\t\t\tProjectileNames[];\nextern long const\t\t\t\t\t\t\t\tEditorCodes[];\nextern char const * const\t\t\t\t\tSourceName[SOURCE_COUNT];\nextern int const\t\t\t\t\t\t\t\tGroundColor[LAND_COUNT];\nextern int const\t\t\t\t\t\t\t\tSnowColor[LAND_COUNT];\nextern TheaterDataType const \t\t\t\tTheaters[THEATER_COUNT];\nextern unsigned char const \t\t\t\tFacing32[256];\nextern unsigned char const\t\t\t\t\tFacing16[256];\nextern signed char const\t\t\t\t\tRotation16[256];\nextern unsigned char const \t\t\t\tFacing8[256];\nextern unsigned char const\t\t\t\t\tPixel2Lepton[24];\nextern COORDINATE const \t\t\t\t\tStoppingCoordAbs[5];\nextern CELL const \t\t\t\t\t\t\tAdjacentCell[FACING_COUNT];\nextern COORDINATE const \t\t\t\t\tAdjacentCoord[FACING_COUNT];\nextern unsigned char const\t\t\t\t\tRemapCiv2[];\nextern unsigned char const\t\t\t\t\tRemapCiv4[];\nextern unsigned char const\t\t\t\t\tRemapCiv5[];\nextern unsigned char const\t\t\t\t\tRemapCiv6[];\nextern unsigned char const\t\t\t\t\tRemapCiv7[];\nextern unsigned char const\t\t\t\t\tRemapCiv8[];\nextern unsigned char const\t\t\t\t\tRemapCiv9[];\nextern unsigned char const\t\t\t\t\tRemapCiv10[];\nextern unsigned char const\t\t\t\t\tRemapEmber[];\n\nextern int SoundOn;\n\n#ifdef WIN32\nextern GraphicViewPortClass\tHidPage;\n#else\nextern GraphicBufferClass\tHidPage;\n#endif\nextern int \t\t\t\t\t\tMenuList[][8];\nextern CDTimerClass<SystemTimerClass> FrameTimer;\nextern CDTimerClass<SystemTimerClass> CountDownTimer;\n\nextern SpecialDialogType\tSpecialDialog;\n\nextern int RequiredCD;\nextern int CurrentCD;\nextern int MouseInstalled;\n\n\nextern int LogLevel;\nextern unsigned long LogLevelTime[ MAX_LOG_LEVEL ];\nextern unsigned long LogLastTime;\n\nextern class DynamicVectorClass<EventChoiceClass> test2;\nextern class DynamicVectorClass<ActionChoiceClass> test3;\n\nextern bool LogDump_Print;\n\nextern \"C\"{\n\textern bool IsTheaterShape;\n}\n\nextern void Reset_Theater_Shapes(void);\nextern TheaterType LastTheater;\nvoid Coordinate_Remap ( GraphicViewPortClass *inbuffer, int x, int y, int width, int height, unsigned char *remap_table);\nvoid Do_Vortex (int x, int y, int frame);\n\n\n/************************************************************\n** Win32 specific externs\n*/\n#ifdef WIN32\nextern bool ReadyToQuit;\t\t\t\t\t\t\t//Are we about to exit cleanly\nextern bool InDebugger;\t\t\t\t\t\t\t//Are we being run from a debugger\nvoid Memory_Error_Handler(void);\t\t\t\t//Memory error handler function\nvoid WWDebugString (char *string);\n#else\nextern bool IsTheaterShape;\n#endif\t//WIN32\n\n\n/*************************************************************\n** Internet specific externs\n*/\n#ifdef WIN32\n\nextern char PlanetWestwoodHandle[];\t\t\t//Planet WW user name\nextern char PlanetWestwoodPassword[];\t\t//Planet WW password\nextern char PlanetWestwoodIPAddress[];\t\t//IP of server or other player\nextern long PlanetWestwoodPortNumber;\t\t//Port number to send to\nextern bool PlanetWestwoodIsHost;\t\t\t\t//Flag true if player has control of game options\nextern unsigned long PlanetWestwoodGameID;\t//Game ID\nextern HWND\tWChatHWND;\t\t\t\t\t\t\t//Handle to Wchat window.\nextern bool\tGameStatisticsPacketSent;\nextern bool\tConnectionLost;\nextern void *PacketLater;\nextern bool SpawnedFromWChat;\nextern int ShowCommand;\nvoid\tRegister_Game_Start_Time(void);\nvoid\tRegister_Game_End_Time(void);\nvoid\tSend_Statistics_Packet(void);\nvoid \tCheck_From_WChat(char *wchat_name);\nbool \tDo_The_Internet_Menu_Thang (void);\nbool \tServer_Remote_Connect(void);\nbool \tClient_Remote_Connect(void);\nextern\tint UnitBuildPenalty;\n\n\n#endif\t //WIN32\n\n/*\n** From SENDFILE.CPP - externs for scenario file transfers\n*/\nbool Receive_Remote_File ( char *file_name, unsigned int file_length, unsigned int crc, int gametype);\nbool Send_Remote_File ( char *file_name, int gametype );\nbool Get_Scenario_File_From_Host(char *return_name, int gametype);\nbool Find_Local_Scenario (char *description, char *filename, unsigned int length, char *digest, bool official);\n\n#ifdef MPEGMOVIE // Denzil 6/15/98\n#ifdef MCIMPEG\n#include \"mcimovie.h\"\nextern MCIMovie* MciMovie;\n#endif\n\n#include \"mpgset.h\"\nextern MPGSettings* MpgSettings;\n#endif\n\n#endif\n\n"
  },
  {
    "path": "CODE/FACE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FACE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FACE.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/08/96                                                     *\n *                                                                                             *\n *                  Last Update : March 8, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Desired_Facing8 -- Determines facing from one coordinate to another.                      *\n *   Desired_Facing256 -- Determines facing from one coordinate to another.                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/***********************************************************************************************\n * Desired_Facing8 -- Determines facing from one coordinate to another.                        *\n *                                                                                             *\n *    This routine will find the facing (compass direction) from one location to another.      *\n *    Typical use of this is in find path and other 'monster' movement logic.                  *\n *                                                                                             *\n * INPUT:   x1,y1    -- X and Y coordinates for the source location. The coordinate 0,0 is     *\n *                      presumed to be the northwest corner of the map.                        *\n *                                                                                             *\n *          x2,y2    -- X and Y coordinates for the destination (target) location.             *\n *                                                                                             *\n * OUTPUT:  Returns with the facing from the first coordinate to the second coordinate. The    *\n *          value returned will range from 0 being North, increasing clockwise until reaching  *\n *          255 which is just shy of North in a Westerly direction.                            *\n *                                                                                             *\n * WARNINGS:   This routine is only accurate to the 8 primary compass directions. It is much   *\n *             faster than the Desired_Facing256() function so it should be used where speed   *\n *             is more important than accuracy.                                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nDirType Desired_Facing8(int x1, int y1, int x2, int y2)\n{\n\tint index = 0;\t\t\t\t// Facing composite value.\n\n\t/*\n\t**\tFigure the absolute X difference. This determines\n\t**\tif the facing is leftward or not.\n\t*/\n\tint xdiff = x2-x1;\n\tif (xdiff < 0) {\n\t\tindex |= 0x00C0;\n\t\txdiff = -xdiff;\n\t}\n\n\t/*\n\t**\tFigure the absolute Y difference. This determines\n\t**\tif the facing is downward or not. This also clarifies\n\t**\texactly which quadrant the facing lies.\n\t*/\n\tint ydiff = y1-y2;\n\tif (ydiff < 0) {\n\t\tindex ^= 0x0040;\n\t\tydiff = -ydiff;\n\t}\n\n\t/*\n\t**\tDetermine which of the two direction offsets it bigger. The\n\t**\toffset direction that is bigger (X or Y) will indicate which\n\t**\torthogonal direction the facing is closer to.\n\t*/\n\tunsigned bigger;\n\tunsigned smaller;\n\tif (xdiff < ydiff) {\n\t\tsmaller = xdiff;\n\t\tbigger = ydiff;\n\t} else {\n\t\tsmaller = ydiff;\n\t\tbigger = xdiff;\n\t}\n\n\t/*\n\t**\tIf on the diagonal, then incorporate this into the facing\n\t**\tand then bail. The facing is known.\n\t*/\n\tif (((bigger+1)/2) <= smaller) {\n\t\tindex += 0x0020;\n\t\treturn(DirType(index));\n\t}\n\n\t/*\n\t**\tDetermine if the facing is closer to the Y axis or\n\t**\tthe X axis.\n\t*/\n\tint adder = (index & 0x0040);\n\tif (xdiff == bigger) {\n\t\tadder ^= 0x0040;\n\t}\n\tindex += adder;\n\n\treturn(DirType(index));\n}\n\n\n/***********************************************************************************************\n * Desired_Facing256 -- Determines facing from one coordinate to another.                      *\n *                                                                                             *\n *    This routine will figure the facing from the source coordinate toward the destination    *\n *    coordinate. Typically, this routine is used for movement and other 'monster' logic. It   *\n *    is more accurate than the corresponding Desired_Facing8() function, but is slower.       *\n *                                                                                             *\n * INPUT:   srcx, srcy  -- The source coordinate to determine the facing from.                 *\n *                                                                                             *\n *          dstx, dsty  -- The destination (or target) coordinate to determine the facing      *\n *                         toward.                                                             *\n *                                                                                             *\n * OUTPUT:  Returns with the facing from the source coordinate toward the destination          *\n *          coordinate with 0 being North increasing in a clockwise direction. 64 is East,     *\n *          128 is South, etc.                                                                 *\n *                                                                                             *\n * WARNINGS:   The coordinate 0,0 is presumed to be in the Northwest corner of the map.        *\n *             Although this routine is fast, it is not as fast as Desired_Facing8().          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nDirType Desired_Facing256(int srcx, int srcy, int dstx, int dsty)\n{\n\tint composite=0;\t\t// Facing built from intermediate calculations.\n\n\t/*\n\t**\tFetch the absolute X difference. This also gives a clue as\n\t**\tto which hemisphere the direction lies.\n\t*/\n\tint xdiff = dstx - srcx;\n\tif (xdiff < 0) {\n\t\tcomposite |= 0x00C0;\n\t\txdiff = -xdiff;\n\t}\n\n\t/*\n\t**\tFetch the absolute Y difference. This clarifies the exact\n\t**\tquadrant that the direction lies.\n\t*/\n\tint ydiff = srcy - dsty;\n\tif (ydiff < 0) {\n\t\tcomposite ^= 0x0040;\n\t\tydiff = -ydiff;\n\t}\n\n\t/*\n\t**\tBail early if the coordinates are the same. This check also\n\t**\thas the added bonus of ensuring that checking for division\n\t**\tby zero is not needed in the following section.\n\t*/\n\tif (xdiff == 0 && ydiff == 0) return(DirType(0xFF));\n\n\t/*\n\t**\tDetermine which of the two direction offsets it bigger. The\n\t**\toffset direction that is bigger (X or Y) will indicate which\n\t**\torthogonal direction the facing is closer to.\n\t*/\n\tunsigned bigger;\n\tunsigned smaller;\n\tif (xdiff < ydiff) {\n\t\tsmaller = xdiff;\n\t\tbigger = ydiff;\n\t} else {\n\t\tsmaller = ydiff;\n\t\tbigger = xdiff;\n\t}\n\n\t/*\n\t**\tNow that the quadrant is known, we need to determine how far\n\t**\tfrom the orthogonal directions, the facing lies. This value\n\t**\tis calculated as a ratio from 0 (matches orthogonal) to 31\n\t**\t(matches diagonal).\n\t*/\n\t//lint -e414\t\tDivision by zero cannot occur here.\n\tint frac = (smaller * 32U) / bigger;\n\n\t/*\n\t**\tGiven the quadrant and knowing whether the facing is closer\n\t**\tto the X or Y axis, we must make an adjustment toward the\n\t**\tsubsequent quadrant if necessary.\n\t*/\n\tint adder = (composite & 0x0040);\n\tif (xdiff > ydiff) {\n\t\tadder ^= 0x0040;\n\t}\n\tif (adder) {\n\t\tfrac = (adder - frac)-1;\n\t}\n\n\t/*\n\t**\tIntegrate the fraction value into the quadrant.\n\t*/\n\tcomposite += frac;\n\n\t/*\n\t**\tReturn with the final facing value.\n\t*/\n\treturn(DirType(composite & 0x00FF));\n}\n"
  },
  {
    "path": "CODE/FACE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FACE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FACE.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/08/96                                                     *\n *                                                                                             *\n *                  Last Update : March 8, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FACE_H\n#define FACE_H\n\n// Enumerations of the facing values returned from Desired_Facing().\ntypedef enum DirType {\n\tDIR_MIN=0,\n\tDIR_N=0,\n\tDIR_NE=1<<5,\n\tDIR_E=2<<5,\n\tDIR_SE=3<<5,\n\tDIR_S=4<<5,\n\tDIR_SW=5<<5,\n\tDIR_W=6<<5,\n\tDIR_NW=7<<5,\n\tDIR_MAX=255\n} DirType;\n\n// Operators that allow simple math with DirType.\ninline DirType operator + (DirType f1, DirType f2)\n{\n\treturn (DirType)(((int)f1 + (int)f2) & 0x00FF);\n}\ninline DirType operator + (DirType f1, int f2)\n{\n\treturn (DirType)(((int)f1 + (int)f2) & 0x00FF);\n}\ninline DirType operator - (DirType f1, DirType f2)\n{\n\treturn (DirType)(((int)f1 - (int)f2) & 0x00FF);\n}\ninline DirType operator - (DirType f1, int f2)\n{\n\treturn (DirType)(((int)f1 - (int)f2) & 0x00FF);\n}\n\n\n// Function prototypes.\nDirType Desired_Facing8(int x1, int y1, int x2, int y2);\nDirType Desired_Facing256(int srcx, int srcy, int dstx, int dsty);\n\n#endif\n\n\n\n"
  },
  {
    "path": "CODE/FACING.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FACING.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FACING.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/21/95                                                     *\n *                                                                                             *\n *                  Last Update : March 21, 1995 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   FacingClass::FacingClass -- Default constructor for the facing class.                     *\n *   FacingClass::Rotation_Adjust -- Perform a rotation adjustment to current facing.          *\n *   FacingClass::Set_Current -- Sets the current rotation value.                              *\n *   FacingClass::Set_Desired -- Sets the desired facing  value.                               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"facing.h\"\n\n\n/***********************************************************************************************\n * FacingClass::FacingClass -- Default constructor for the facing class.                       *\n *                                                                                             *\n *    This default constructor merely sets the desired and current facing values to be the     *\n *    same (North).                                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nFacingClass::FacingClass(void)\n{\n\tCurrentFacing = DIR_N;\n\tDesiredFacing = DIR_N;\n}\n\n\n/***********************************************************************************************\n * FacingClass::Set_Desired -- Sets the desired facing  value.                                 *\n *                                                                                             *\n *    This routine is used to set the desired facing value without altering the current        *\n *    facing setting. Typical use of this routine is when a vehicle needs to face a           *\n *    direction, but currently isn't facing the correct direction. After this routine is       *\n *    called, it is presumed that subsequent calls to Rotation_Adjust() will result in the     *\n *    eventual alignment of the current facing.                                                *\n *                                                                                             *\n * INPUT:   facing   -- The new facing to assign to the desired value.                         *\n *                                                                                             *\n * OUTPUT:  bool; Did the desired facing value actually change by this routine call?           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FacingClass::Set_Desired(DirType facing)\n{\n\tif (DesiredFacing != facing) {\n\t\tDesiredFacing = facing;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FacingClass::Set_Current -- Sets the current rotation value.                                *\n *                                                                                             *\n *    This routine will set the current rotation value. It is used to override the facing      *\n *    value without adjusting the desired setting.                                             *\n *                                                                                             *\n * INPUT:   facing   -- The new facing to assign to the current facing value.                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the current setting changed by this routine. Failure means that the      *\n *                current setting was already at the value specified.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FacingClass::Set_Current(DirType facing)\n{\n\tif (CurrentFacing != facing) {\n\t\tCurrentFacing = facing;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FacingClass::Rotation_Adjust -- Perform a rotation adjustment to current facing.            *\n *                                                                                             *\n *    This routine is used when the current and desired facings differ but the current         *\n *    facing should be adjusted toward the desired facing. The amount of rotation to adjust    *\n *    is provided as a rotation rate parameter. Typical use of this routine is for turrets     *\n *    and other vehicle related rotating.                                                      *\n *                                                                                             *\n * INPUT:   rate  -- The rotation rate to use when adjusting the current facing toward the     *\n *                   desired facing. A value of 127 means instantaneous rotation.              *\n *                                                                                             *\n * OUTPUT:  bool; Did the rotation result in the current facing transitioning from one         *\n *                1/32 zone to another? If true, then the owning object most likely will       *\n *                need to be redrawn to reflect the change.                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FacingClass::Rotation_Adjust(int rate)\n{\n\t/*\n\t**\tOnly perform the rotation adjustment if the desired facing is not the\n\t**\tsame as the current facing.\n\t*/\n\tif (Is_Rotating()) {\n\t\trate = min(rate, 127);\n\n\t\tDirType oldfacing = CurrentFacing;\n\t\tint diff = Difference();\n\n\t\t/*\n\t\t**\tIf the allowed facing change is greater than the difference between\n\t\t**\tthe current facing and the desired facing, then just snap the\n\t\t**\tfacing to the new value.\n\t\t*/\n\t\tif (ABS(diff) < rate) {\n\t\t\tCurrentFacing = DesiredFacing;\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tAdjust the current facing clockwise or counterclockwise depending\n\t\t\t**\ton the shortest distance to the desired facing from the current\n\t\t\t**\tfacing.\n\t\t\t*/\n\t\t\tif (diff < 0) {\n\t\t\t\tCurrentFacing = (DirType)(CurrentFacing - (DirType)rate);\n\t\t\t} else {\n\t\t\t\tCurrentFacing = (DirType)(CurrentFacing + (DirType)rate);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf this facing adjustment caused the current facing to rotate into a\n\t\t**\tnew 1/32 rotation zone (likely to cause a redraw), then return\n\t\t**\tthis fact with a true value.\n\t\t*/\n\t\treturn(Dir_To_32(CurrentFacing) != Dir_To_32(oldfacing));\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "CODE/FACING.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FACING.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FACING.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/21/95                                                     *\n *                                                                                             *\n *                  Last Update : March 21, 1995 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FACING_H\n#define FACING_H\n\n/*\n**\tThis is a general facing handler class. It is used in those cases where facing needs to be\n**\tkept track of, but there could also be an associated desired facing. The current facing\n**\tis supposed to transition to the desired state over time. Using this class facilitates this\n**\tprocessing as well as isolating the rest of the code from the internals.\n*/\nclass FacingClass\n{\n\tpublic:\n\t\tFacingClass(void);\n\t\tFacingClass(DirType dir) : CurrentFacing(dir), DesiredFacing(dir) {};\n\t\tFacingClass(NoInitClass const & ) {};\n\n\t\toperator DirType (void) const {return(CurrentFacing);};\n\n\t\tDirType Current(void) const {return(CurrentFacing);};\n\t\tDirType Desired(void) const {return(DesiredFacing);};\n\n\t\tint Set_Desired(DirType facing);\n\t\tint Set_Current(DirType facing);\n\n\t\tvoid Set(DirType facing) {\n\t\t\tSet_Current(facing);\n\t\t\tSet_Desired(facing);\n\t\t};\n\n\t\tDirType Get(void) const { return CurrentFacing; }\n\n\t\tint Is_Rotating(void) const {return (DesiredFacing != CurrentFacing);};\n\t\tint Difference(void) const {return (int)(signed char)((int)DesiredFacing - (int)CurrentFacing);}\n\t\tint Difference(DirType facing) const {return (int)(signed char)((int)facing - (int)CurrentFacing);}\n\t\tint Rotation_Adjust(int rate);\n\n\tprivate:\n\t\tDirType CurrentFacing;\n\t\tDirType DesiredFacing;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/FACTORY.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FACTORY.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FACTORY.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/26/94                                                     *\n *                                                                                             *\n *                  Last Update : May 22, 1995 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   FactoryClass::AI -- Process factory production logic.                                     *\n *   FactoryClass::Abandon -- Abandons current construction with money refunded.               *\n *   FactoryClass::Completed -- Clears factory object after a completed production process.    *\n *   FactoryClass::Completion -- Fetches the completion step for this factory.                 *\n *   FactoryClass::Cost_Per_Tick -- Breaks entire production cost into manageable chunks.      *\n *   FactoryClass::FactoryClass -- Default constructor for factory objects.                    *\n *   FactoryClass::Get_Object -- Fetches pointer to object being constructed.                  *\n *   FactoryClass::Get_Special_Item -- gets factory's spc prod item                            *\n *   FactoryClass::Has_Changed -- Checks to see if a production step has occurred?             *\n *   FactoryClass::Has_Completed -- Checks to see if object has completed production.          *\n *   FactoryClass::Set -- Assigns a factory to produce an object.                              *\n *   FactoryClass::Set -- Force factory to \"produce\" special object.                           *\n *   FactoryClass::Start -- Resumes production after suspension or creation.                   *\n *   FactoryClass::Suspend -- Temporarily stop production.                                     *\n *   FactoryClass::operator delete -- Returns a factory to the free factory pool.              *\n *   FactoryClass::operator new -- Allocates a factory object from the free factory pool.      *\n *   FactoryClass::~FactoryClass -- Default destructor for factory objects.                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * FactoryClass::FactoryClass -- Default constructor for factory objects.                      *\n *                                                                                             *\n *    This brings the factory into a null state. It is called when a factory object is         *\n *    created.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nFactoryClass::FactoryClass(void) :\n\tRTTI(RTTI_FACTORY),\n\tID(Factories.ID(this)),\n\tIsSuspended(false),\n\tIsDifferent(false),\n\tBalance(0),\n\tOriginalBalance(0),\n\tObject(0),\n\tSpecialItem(SPC_NONE),\n\tHouse(0)\n{\n\tSet_Rate(0);\n\tSet_Stage(0);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::~FactoryClass -- Default destructor for factory objects.                      *\n *                                                                                             *\n *    This cleans up a factory object in preparation for deletion. If there is currently       *\n *    an object in production, it is abandoned and money is refunded.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nFactoryClass::~FactoryClass(void)\n{\n\tif (GameActive) {\n\t\tAbandon();\n\t}\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Init -- Clears all units for scenario preparation.                            *\n *                                                                                             *\n *    This routine will zero out the factory list and objects. This routine is typically       *\n *    used in preparation for a new scenario load. All factory are guaranteed to be eliminated *\n *    by this routine.                                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FactoryClass::Init(void)\n{\n\tFactories.Free_All();\n}\n\n\n/***********************************************************************************************\n * FactoryClass::operator new -- Allocates a factory object from the free factory pool.        *\n *                                                                                             *\n *    This routine allocates a factory from the free factory pool. If there is no more room    *\n *    to allocate a factory, then NULL is returned.                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with pointer to the newly allocated factory object.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * FactoryClass::operator new(size_t)\n{\n\tvoid * ptr = Factories.Allocate();\n\tif (ptr) {\n\t\t((FactoryClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::operator delete -- Returns a factory to the free factory pool.                *\n *                                                                                             *\n *    This returns the factory object back to the factory allocation pool. The factory is then *\n *    available to be allocated.                                                               *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the factory object to delete.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FactoryClass::operator delete(void * ptr)\n{\n\tif (ptr) {\n\t\t((FactoryClass *)ptr)->IsActive = false;\n\t}\n\tFactories.Free((FactoryClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::AI -- Process factory production logic.                                       *\n *                                                                                             *\n *    This routine should be called once per game tick. It handles the production process.     *\n *    As production proceeds, money is deducted from the owner object's house. When production *\n *    completes, the factory stop processing. A call to Abandon, Delete, or Completed is       *\n *    required after that point.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *   01/04/1995 JLB : Uses exact installment payment method.                                   *\n *=============================================================================================*/\nvoid FactoryClass::AI(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tif (!IsSuspended && (Object != NULL || SpecialItem)) {\n\t\tfor (int index = 0; index < 1; index++) {\n\t\t\tif (!Has_Completed() && Graphic_Logic() ) {\n\t\t\t\tIsDifferent = true;\n\n\t\t\t\tint cost = Cost_Per_Tick();\n\n\t\t\t\tcost = min(cost, Balance);\n\n\t\t\t\t/*\n\t\t\t\t**\tEnough time has expired so that another production step can occur.\n\t\t\t\t**\tIf there is insufficient funds, then go back one production step and\n\t\t\t\t**\tcontinue the countdown. The idea being that by the time the next\n\t\t\t\t**\tproduction step occurs, there may be sufficient funds available.\n\t\t\t\t*/\n\t\t\t\tif (cost > House->Available_Money()) {\n\t\t\t\t\tSet_Stage(Fetch_Stage()-1);\n\t\t\t\t} else {\n\t\t\t\t\tHouse->Spend_Money(cost);\n\t\t\t\t\tBalance -= cost;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the production has completed, then suspend further production.\n\t\t\t\t*/\n\t\t\t\tif (Fetch_Stage() == STEP_COUNT) {\n\t\t\t\t\tIsSuspended = true;\n\t\t\t\t\tSet_Rate(0);\n\t\t\t\t\tHouse->Spend_Money(Balance);\n\t\t\t\t\tBalance = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Has_Changed -- Checks to see if a production step has occurred?               *\n *                                                                                             *\n *    Use this routine to determine if production has advanced at least one step. By using     *\n *    this function, intelligent rendering may be performed.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Has the production process advanced one step since the last time this        *\n *                function was called?                                                         *\n *                                                                                             *\n * WARNINGS:   This function clears the changed status flag as a side effect.                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FactoryClass::Has_Changed(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tbool changed = IsDifferent;\n\tIsDifferent = false;\n\treturn(changed);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Set -- Assigns a factory to produce an object.                                *\n *                                                                                             *\n *    This routine initializes a factory to produce the object specified. The desired object   *\n *    type is created and placed in suspended animation (limbo) until such time as production  *\n *    completes. Production is not actually started by this routine. An explicit call to       *\n *    Start() is required to begin production.                                                 *\n *                                                                                             *\n * INPUT:   object   -- Reference to the object type class that is to be produced.             *\n *                                                                                             *\n *          house    -- Reference to the owner of the object to be produced.                   *\n *                                                                                             *\n * OUTPUT:  bool; Was production successfully prepared for this factory object. Failure means  *\n *                that the object could not be created. This is catastrophic and in such       *\n *                cases, the factory object should be deleted.                                 *\n *                                                                                             *\n * WARNINGS:   Be sure to examine the return value from this function. Failure to initialize   *\n *             the factory means that the factory is useless and should be deleted.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FactoryClass::Set(TechnoTypeClass const & object, HouseClass & house)\n{\n\tassert(Factories.ID(this) == ID);\n\n\t/*\n\t**\tIf there is any production currently in progress, abandon it.\n\t*/\n\tAbandon();\n\n\t/*\n\t**\tSet up the factory for the new production process.\n\t*/\n\tIsDifferent = true;\n\tIsSuspended = true;\n\tSet_Rate(0);\n\tSet_Stage(0);\n\n\t/*\n\t**\tCreate an object of the type requested.\n\t*/\n\tObject = (TechnoClass *)object.Create_One_Of(&house);\n\n\t/*\n\t**\tBuildings that are constructed, will default to rebuilding on so that\n\t**\trepair can commence and base rebuilding can occur.\n\t*/\n\tif (!house.IsHuman && Object != NULL && Object->What_Am_I() == RTTI_BUILDING) {\n\t\t((BuildingClass *)Object)->IsToRebuild = true;\n\t}\n\n\tif (Object) {\n\t\tHouse  = Object->House;\n\t\tBalance = object.Cost_Of() * house.CostBias;\n\t\tObject->PurchasePrice = Balance;\n\t}\n\n\t/*\n\t**\tIf all was set up successfully, then return true.\n\t*/\n\treturn(Object != NULL);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Set -- Fills a factory with an already completed object.                      *\n *                                                                                             *\n *    This routine is called when a produced object is in placement mode but then placement    *\n *    is suspended. The object must then return to the factory as if it were newly completed   *\n *    and awaiting removal.                                                                    *\n *                                                                                             *\n * INPUT:   object   -- The object to return to the factory.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This will abandon any current object being produced at the factory in order     *\n *             to set the new object into it.                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FactoryClass::Set(TechnoClass & object)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tAbandon();\n\tObject = &object;\n\tHouse  = Object->House;\n\tBalance = 0;\n\tSet_Rate(0);\n\tSet_Stage(STEP_COUNT);\n\tIsDifferent = true;\n\tIsSuspended = true;\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Suspend -- Temporarily stop production.                                       *\n *                                                                                             *\n *    This routine will suspend production until a subsequent call to Start() or Abandon().    *\n *    Typical use of this function is when the player puts production on hold or when there    *\n *    is insufficient funds.                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was production actually stopped? A false return value indicates that the     *\n *                factory was empty or production was already stopped (or never started).      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FactoryClass::Suspend(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tif (!IsSuspended) {\n\t\tIsSuspended = true;\n\t\tSet_Rate(0);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Start -- Resumes production after suspension or creation.                     *\n *                                                                                             *\n *    This function will start the production process. It works for newly created factory      *\n *    objects, as well as if production had been suspended previously.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was production started? A false return value means that the factory is       *\n *                empty or there is insufficient credits to begin production.                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FactoryClass::Start(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tif ((Object || SpecialItem) && IsSuspended && !Has_Completed()) {\n\t\tif (House->Available_Money() >= Cost_Per_Tick()) {\n\t\t\tint time;\n\n\t\t\tif (Object) {\n\t\t\t\ttime = Object->Time_To_Build();\n//\t\t\t} else {\n//\t\t\t\ttime = TICKS_PER_MINUTE * 5;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAdjust time according to IQ setting of computer controlled house. The\n\t\t\t**\tbuild time will range from double normal time at the slowest to\n\t\t\t**\tjust normal time at the fastest.\n\t\t\t*/\n\t\t\tif (!House->IsHuman && Rule.Diff[House->Difficulty].IsBuildSlowdown) {\n\t\t\t\ttime = time * Inverse(fixed(House->IQ+Rule.MaxIQ, Rule.MaxIQ*2));\n\t\t\t}\n\n\t\t\tint rate = time / Bound(House->Power_Fraction(), fixed(1, 16), fixed(1));\n//\t\t\tint frac = House->Power_Fraction();\n//\t\t\tfrac = Bound(frac, 0x0010, 0x0100);\n//\t\t\tint rate = (time*256) / frac;\n\n\t\t\trate /= STEP_COUNT;\n\t\t\trate = Bound(rate, 1, 255);\n\n\t\t\tSet_Rate(rate);\n\t\t\tIsSuspended = false;\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Abandon -- Abandons current construction with money refunded.                 *\n *                                                                                             *\n *    This routine is used when construction is to be abandoned and current money spend is     *\n *    to be refunded. This function effectively clears out this factory of all record of the   *\n *    producing object so that it may either be deleted or started anew with the Set()         *\n *    function.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was an object actually abandoned? A false return value indicates that the    *\n *                factory was not producing any object.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FactoryClass::Abandon(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tif (Object) {\n\n\t\tif (Object) {\n\t\t\t/*\n\t\t\t**\tRefund all money expended so far, back to the owner of the object under construction.\n\t\t\t*/\n\t\t\tint money = Object->Class_Of().Cost_Of() * Object->House->CostBias;\n\t\t\tHouse->Refund_Money(money - Balance);\n\t\t\tBalance = 0;\n\n\t\t\t/*\n\t\t\t**\tDelete the object under construction.\n\t\t\t*/\n\t\t\tScenarioInit++;\n\t\t\tdelete Object;\n\t\t\tObject = NULL;\n\t\t\tScenarioInit--;\n\t\t}\n\t\tif (SpecialItem) {\n\t\t\tSpecialItem = SPC_NONE;\n\t\t}\n\n\t\t/*\n\t\t**\tSet the factory back to the idle and empty state.\n\t\t*/\n\t\tSet_Rate(0);\n\t\tSet_Stage(0);\n\t\tIsSuspended = true;\n\t\tIsDifferent = true;\n\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Completion -- Fetches the completion step for this factory.                   *\n *                                                                                             *\n *    Use this routine to determine what animation (or completion step) the factory is         *\n *    currently on.                                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns a completion step number between 0 (uncompleted), to STEP_COUNT (completed)*\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FactoryClass::Completion(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\treturn(Fetch_Stage());\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Has_Completed -- Checks to see if object has completed production.            *\n *                                                                                             *\n *    Use this routine to examine the factory object in order to determine if the associated   *\n *    object has completed production and is awaiting placement.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the associated object to the factory completed and ready for placement?   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FactoryClass::Has_Completed(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tif (Object && Fetch_Stage() == STEP_COUNT) {\n\t\treturn(true);\n\t}\n\tif (SpecialItem && Fetch_Stage() == STEP_COUNT) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Get_Object -- Fetches pointer to object being constructed.                    *\n *                                                                                             *\n *    This routine gets the pointer to the currently constructing object.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the object undergoing construction.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTechnoClass * FactoryClass::Get_Object(void) const\n{\n\tassert(Factories.ID(this) == ID);\n\n\treturn(Object);\n}\n\n\n/***************************************************************************\n * FactoryClass::Get_Special_Item -- gets factory spc prod item            *\n *                                                                         *\n * INPUT:      none                                                        *\n *                                                                         *\n * OUTPUT:     int the item the factory is currently working on            *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/05/1995 PWG : Created.                                             *\n *=========================================================================*/\nint FactoryClass::Get_Special_Item(void) const\n{\n\tassert(Factories.ID(this) == ID);\n\n\treturn(SpecialItem);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Cost_Per_Tick -- Breaks entire production cost into manageable chunks.        *\n *                                                                                             *\n *    Use this routine to determine the cost per game \"tick\" to produce the object.            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the number of credits necessary to advance production one game tick.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FactoryClass::Cost_Per_Tick(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tif (Object) {\n\t\tint steps = STEP_COUNT - Fetch_Stage();\n\t\tif (steps) {\n\t\t\treturn(Balance / steps);\n\t\t}\n\t\treturn(Balance);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Completed -- Clears factory object after a completed production process.      *\n *                                                                                             *\n *    This routine is called after production completes, and the object produced has been      *\n *    placed into the game. It resets the factory for deletion or starting of new production.  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Did any resetting occur? Failure is the result of the factory not having     *\n *                any completed object. An immediate second call to this routine will also     *\n *                yield false.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FactoryClass::Completed(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tif (Object && Fetch_Stage() == STEP_COUNT) {\n\t\tObject = NULL;\n\t\tIsSuspended = true;\n\t\tIsDifferent = true;\n\t\tSet_Stage(0);\n\t\tSet_Rate(0);\n\t\treturn(true);\n\t}\n\n\tif (SpecialItem && Fetch_Stage() == STEP_COUNT) {\n\t\tSpecialItem = SPC_NONE;\n\t\tIsSuspended = true;\n\t\tIsDifferent = true;\n\t\tSet_Stage(0);\n\t\tSet_Rate(0);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n"
  },
  {
    "path": "CODE/FACTORY.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FACTORY.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FACTORY.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/26/94                                                     *\n *                                                                                             *\n *                  Last Update : December 26, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FACTORY_H\n#define FACTORY_H\n\n#include\t\"stage.h\"\n\nclass FactoryClass : private StageClass\n{\n\tpublic:\n\t\tRTTIType RTTI;\n\t\tint ID;\n\n\n\t\tFactoryClass(void);\n\t\tFactoryClass(NoInitClass const & x) : StageClass(x) {};\n\t\t~FactoryClass(void);\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\n\t\tstatic void Init(void);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\t\tvoid Code_Pointers(void);\n\t\tvoid Decode_Pointers(void);\n\n\t\tbool Abandon(void);\n\t\tbool Completed(void);\n\t\tbool Has_Changed(void);\n\t\tbool Has_Completed(void);\n\t\tbool Is_Building(void) const {return(Fetch_Rate() != 0);};\n\t\tbool Set(TechnoTypeClass const & object, HouseClass & house);\n\t\tbool Set(int const & type, HouseClass & house);\n\t\tbool Start(void);\n\t\tbool Suspend(void);\n\t\tint Completion(void);\n\t\tTechnoClass * Get_Object(void) const;\n\t\tint Get_Special_Item(void) const;\n\t\tvoid AI(void);\n\t\tvoid Set(TechnoClass & object);\n\t\tHouseClass * Get_House(void) {return(House);};\n\t\tchar const * Name(void) {return(\"Factory\");}\n\n\t\t/*\n\t\t**\tThis flag is used to maintain the pool of factory class objects. If the object has\n\t\t**\tbeen allocated, then this flag is true. Otherwise, the object is free to be\n\t\t**\tallocated.\n\t\t*/\n\t\tunsigned IsActive:1;\n\n\t\tenum StepCountEnum {\n\t\t\tSTEP_COUNT=54\t\t\t// Number of steps to break production down into.\n\t\t};\n\tprotected:\n\n\t\tint Cost_Per_Tick(void);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tIf production is temporarily suspended, then this flag will be true. A factory\n\t\t**\tis suspended when it is first created, when production has completed, and when\n\t\t**\texplicitly instructed to Suspend() production. Suspended production is not\n\t\t**\tabandoned. It may be resumed with a call to Start().\n\t\t*/\n\t\tunsigned IsSuspended:1;\n\n\t\t/*\n\t\t**\tIf the AI process detected that the production process has advanced far enough\n\t\t**\tthat a change in the building animation would occur, this flag will be true.\n\t\t**\tExamination of this flag (through the Has_Changed function) allows intelligent\n\t\t**\tupdating of any production graphic.\n\t\t*/\n\t\tunsigned IsDifferent:1;\n\n\t\t/*\n\t\t**\tThis records the balance due on the current production item. This value will\n\t\t**\tbe reduced as production proceeds. It will reach zero the moment production has\n\t\t**\tfinished. Using this method ensures that the total production cost will be EXACT\n\t\t**\tregardless of the number of installment payments that are made.\n\t\t*/\n\t\tint Balance;\n\t\tint OriginalBalance;\n\n\t\t/*\n\t\t**\tThis is the object that is being produced. It is held in a state of limbo while\n\t\t**\tundergoing production. Since the object is created at the time production is\n\t\t**\tstarted, it is always available when production completes.\n\t\t*/\n\t\tTechnoClass * Object;\n\n\t\t/*\n\t\t**\tIf the factory is not producing an object and is instead producing\n\t\t** a special item, then special item will be set.\n\t\t*/\n\t\tint SpecialItem;\n\n\t\t/*\n\t\t** The factory has to be doing production for one house or another.\n\t\t** The house pointer will point to whichever house it is being done\n\t\t** for.\n\t\t*/\n\t\tHouseClass  * House;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/FAKESOCK.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/*************************************************************************************\n **   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                  **\n *************************************************************************************\n *                                                                                   *\n *                 Project Name : Command & Conquer - Red Alert                      *\n *                                                                                   *\n *                    File Name : FAKESOCK.H                                         *\n *                                                                                   *\n *                   Programmer : Steve Tall                                         *\n *                                                                                   *\n *                   Start Date : August 6th, 1996                                   *\n *                                                                                   *\n *                  Last Update : August 6th, 1996 [ST]                              *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Overview:                                                                         *\n *                                                                                   *\n *  Stub replacement for the Winsock interface in DOS                                *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Functions:                                                             \t \t\t\t*\n *                                                                         \t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WIN32\n\nclass TcpipManagerClass {\n\n\tpublic:\n\t\tinline BOOL Get_Connected(void) {return (FALSE);}\n\n};\n\nextern TcpipManagerClass\tWinsock;\n#endif\n"
  },
  {
    "path": "CODE/FIELD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Auto Registration App           *\n *                                                                         *\n *                    File Name : FIELD.CPP                                *\n *                                                                         *\n *                   Programmer : Philip W. Gorrow                         *\n *                                                                         *\n *                   Start Date : 04/22/96                                 *\n *                                                                         *\n *                  Last Update : April 22, 1996 [PWG]                     *\n *                                                                         *\n *  Actual member function for the field class.                            *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include <string.h>\n#include \"field.h\"\n\nFieldClass::FieldClass(char *id, char data)\n{\n\tstrncpy(ID, id, sizeof(ID));\n\tDataType = TYPE_CHAR;\n\tSize\t\t= sizeof(data);\n\tData\t\t= new char[Size];\n\tmemcpy(Data, &data, Size);\n\tNext\t\t= NULL;\n}\n\nFieldClass::FieldClass(char *id, unsigned char data)\n{\n\tstrncpy(ID, id, sizeof(ID));\n\tDataType = TYPE_UNSIGNED_CHAR;\n\tSize\t\t= sizeof(data);\n\tData\t\t= new char[Size];\n\tmemcpy(Data, &data, Size);\n\tNext\t\t= NULL;\n}\n\nFieldClass::FieldClass(char *id, short data)\n{\n\tstrncpy(ID, id, sizeof(ID));\n\tDataType = TYPE_SHORT;\n\tSize\t\t= sizeof(data);\n\tData\t\t= new char[Size];\n\tmemcpy(Data, &data, Size);\n\tNext\t\t= NULL;\n}\n\nFieldClass::FieldClass(char *id, unsigned short data)\n{\n\tstrncpy(ID, id, sizeof(ID));\n\tDataType = TYPE_UNSIGNED_SHORT;\n\tSize\t\t= sizeof(data);\n\tData\t\t= new char[Size];\n\tmemcpy(Data, &data, Size);\n\tNext\t\t= NULL;\n}\n\nFieldClass::FieldClass(char *id, long data)\n{\n\tstrncpy(ID, id, sizeof(ID));\n\tDataType = TYPE_LONG;\n\tSize\t\t= sizeof(data);\n\tData\t\t= new char[Size];\n\tmemcpy(Data, &data, Size);\n\tNext\t\t= NULL;\n}\n\nFieldClass::FieldClass(char *id, unsigned long data)\n{\n\tstrncpy(ID, id, sizeof(ID));\n\tDataType = TYPE_UNSIGNED_LONG;\n\tSize\t\t= sizeof(data);\n\tData\t\t= new char[Size];\n\tmemcpy(Data, &data, Size);\n\tNext\t\t= NULL;\n}\n\nFieldClass::FieldClass(char *id, char *data)\n{\n\tstrncpy(ID, id, sizeof(ID));\n\tDataType = TYPE_STRING;\n\tSize\t\t= (unsigned short)(strlen(data)+1);\n\tData\t\t= new char[Size];\n\tmemcpy(Data, data, Size);\n\tNext\t\t= NULL;\n}\n\nFieldClass::FieldClass(char *id, void *data, int length)\n{\n\tstrncpy(ID, id, sizeof(ID));\n\tDataType = TYPE_CHUNK;\n\tSize\t\t= (unsigned short)length;\n\tData\t\t= new char[Size];\n\tmemcpy(Data, data, Size);\n\tNext\t\t= NULL;\n}\n\n\n/**************************************************************************\n * PACKETCLASS::HOST_TO_NET_FIELD -- Converts host field to net format    *\n *                                                                        *\n * INPUT:\t\tFIELD \t* to the data field we need to convert\t\t\t\t  *\n *                                                                        *\n * OUTPUT:     none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/22/1996 PWG : Created.                                            *\n *========================================================================*/\nvoid FieldClass::Host_To_Net(void)\n{\n\t//\n\t// Before we convert the data type, we should convert the actual data\n\t//  sent.\n\t//\n\tswitch (DataType) {\n\t\tcase TYPE_CHAR:\n\t\tcase TYPE_UNSIGNED_CHAR:\n\t\tcase TYPE_STRING:\n\t\tcase TYPE_CHUNK:\n\t\t\tbreak;\n\n\t\tcase TYPE_SHORT:\n\t\tcase TYPE_UNSIGNED_SHORT:\n\t\t\t*((unsigned short *)Data) = htons(*((unsigned short *)Data));\n\t\t\tbreak;\n\n\t\tcase TYPE_LONG:\n\t\tcase TYPE_UNSIGNED_LONG:\n\t\t\t*((unsigned long *)Data) = htonl(*((unsigned long *)Data));\n\t\t\tbreak;\n\n\t\t//\n\t\t// Might be good to insert some type of error message here for unknown\n\t\t//   datatypes -- but will leave that for later.\n\t\t//\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\t//\n\t// Finally convert over the data type and the size of the packet.\n\t//\n\tDataType = htons(DataType);\n\tSize \t \t= htons(Size);\n}\n/**************************************************************************\n * PACKETCLASS::NET_TO_HOST_FIELD -- Converts net field to host format    *\n *                                                                        *\n * INPUT:\t\tFIELD \t* to the data field we need to convert\t\t\t\t  *\n *                                                                        *\n * OUTPUT:     none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/22/1996 PWG : Created.                                            *\n *========================================================================*/\nvoid FieldClass::Net_To_Host(void)\n{\n\t//\n\t// Convert the variables to host order.  This needs to be converted so\n\t// the switch statement does compares on the data that follows.\n\t//\n\tSize \t \t= ntohs(Size);\n\n\tDataType = ntohs(DataType);\n\n\t//\n\t// Before we convert the data type, we should convert the actual data\n\t//  sent.\n\t//\n\tswitch (DataType) {\n\t\tcase TYPE_CHAR:\n\t\tcase TYPE_UNSIGNED_CHAR:\n\t\tcase TYPE_STRING:\n\t\tcase TYPE_CHUNK:\n\t\t\tbreak;\n\n\t\tcase TYPE_SHORT:\n\t\tcase TYPE_UNSIGNED_SHORT:\n\t\t\t*((unsigned short *)Data) = ntohs(*((unsigned short *)Data));\n\t\t\tbreak;\n\n\t\tcase TYPE_LONG:\n\t\tcase TYPE_UNSIGNED_LONG:\n\t\t\t*((unsigned long *)Data) = ntohl(*((unsigned long *)Data));\n\t\t\tbreak;\n\n\t\t//\n\t\t// Might be good to insert some type of error message here for unknown\n\t\t//   datatypes -- but will leave that for later.\n\t\t//\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n"
  },
  {
    "path": "CODE/FIELD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Auto Registration App           *\n *                                                                         *\n *                    File Name : FIELD.H                                  *\n *                                                                         *\n *                   Programmer : Philip W. Gorrow                         *\n *                                                                         *\n *                   Start Date : 04/22/96                                 *\n *                                                                         *\n *                  Last Update : April 22, 1996 [PWG]                     *\n *                                                                         *\n * This module takes care of maintaining the field list used to process    *\n * packets.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef __FIELD_H\n#define __FIELD_H\n\n#include <windows.h>\n#include <winsock.h>\n\n#define FIELD_HEADER_SIZE\t(sizeof(FieldClass) - (sizeof(void *) * 2))\n\n#define TYPE_CHAR\t\t\t\t\t\t1\n#define TYPE_UNSIGNED_CHAR\t\t\t2\n#define TYPE_SHORT\t\t\t\t\t3\n#define TYPE_UNSIGNED_SHORT\t\t4\n#define TYPE_LONG\t\t\t\t\t\t5\n#define TYPE_UNSIGNED_LONG\t\t\t6\n#define TYPE_STRING\t\t\t\t\t7\n#define TYPE_CHUNK\t\t\t\t\t20\n\nclass PacketClass;\n\nclass FieldClass {\n\n\tpublic:\n\t\tfriend class PacketClass;\n\t\t//\n\t\t// Define constructors to be able to create all the different kinds\n\t\t// of fields.\n\t\t//\n\t\tFieldClass(void) {};\n\t\tFieldClass(char *id, char data);\n\t\tFieldClass(char *id, unsigned char data);\n\t\tFieldClass(char *id, short data);\n\t\tFieldClass(char *id, unsigned short data);\n\t\tFieldClass(char *id, long data);\n\t\tFieldClass(char *id, unsigned long data);\n\t\tFieldClass(char *id, char *data);\n\t\tFieldClass(char *id, void *data, int length);\n\n\t\tvoid Host_To_Net(void);\n\t\tvoid Net_To_Host(void);\n\n\tprivate:\n\t\tchar\t\t\t\tID[4];\t\t\t\t// id value of this field\n\t\tunsigned short\tDataType;\t\t\t// id of the data type we are using\n\t\tunsigned short Size;\t\t\t\t\t// size of the data portion of this field\n\t\tvoid  \t\t\t*Data;\t\t\t\t// pointer to the data portion of this field\n\t\tFieldClass\t\t*Next;\t\t\t\t// pointer to the next field in the field list\n};\n\n#endif\n"
  },
  {
    "path": "CODE/FILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n"
  },
  {
    "path": "CODE/FILEPCX.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : iff                                      *\n;*                                                                         *\n;*                    File Name : FILEPCX.H                                *\n;*                                                                         *\n;*                   Programmer : Julio R. Jerez                           *\n;*                                                                         *\n;*                   Start Date : May 2, 1995                              *\n;*                                                                         *\n;*                  Last Update : May 2, 1995   [JRJ]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* GraphicBufferClass* Read_PCX_File (char* name, BYTE* palette,void *buff, long size);\n;* GraphicBufferClass* Read_PCX_File (char* name, BYTE* palette, BufferClass& Buff); \n;* int Write_PCX_File (char* name, GraphicViewPortClass& pic, BYTE* palette );*\n;*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n#include <gbuffer.h>\n#include <string.h>\n#include <buffer.h>\n#include\t<file.h>\n\n#ifndef PCX_H\n#define PCX_H\n\n\ntypedef\tstruct {\n\t\t\t\t\t\t  char\tred ;\n\t\t\t\t\t\t  char\tgreen ;\n\t\t\t\t\t\t  char\tblue ;\n\t\t\t\t\t} RGB ;\n\ntypedef\tstruct\t{\n\t\t\t\t\t\t  char      id ;\n\t\t\t\t\t\t  char\t   version ;\n\t\t\t\t\t\t  char\t   encoding ;\n\t\t\t\t\t\t  char\t   pixelsize ;\n\t\t\t\t\t\t  short \t   x ;\n\t\t\t\t\t\t  short\t\ty ;\n\t\t\t\t\t\t  short     width ;\n\t\t\t\t\t\t  short\t\theight ;\n\t\t\t\t\t\t  short \t   xres ;\n\t\t\t\t\t\t  short\t\tyres ;\n\t\t\t\t\t\t  RGB       ega_palette [ 16 ] ;\n\t\t\t\t\t\t  char\t   nothing ;\n\t\t\t\t\t\t  char      color_planes ;\n\t\t\t\t\t\t  short \t\tbyte_per_line ;\n\t\t\t\t\t\t  short \t \tpalette_type ;\n\t\t\t\t\t\t  char\t   filler [ 58 ] ;\n\t\t\t\t\t\t} PCX_HEADER ;\n\nGraphicBufferClass* Read_PCX_File (char* name, char* palette= NULL,void *buff=NULL, long size=0);\nGraphicBufferClass* Read_PCX_File (char* name, BufferClass& Buff,char* palette= NULL) ;\nint Write_PCX_File (char* name, GraphicViewPortClass& pic, unsigned char* palette );\n\n#endif\n"
  },
  {
    "path": "CODE/FINDPATH.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FINDPATH.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FINDPATH.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : May 25, 1995   [PWG]                                         *\n *                                                                                             *\n * The path algorithm works by following a LOS path to the target. If it                       *\n * collides with an impassable spot, it uses an Edge following routine to                      *\n * get around it. The edge follower moves along the edge in a clockwise or                     *\n * counter clockwise fashion until finding the destination spot. The                           *\n * destination is determined by Find_Path. It is the first passable that                       *\n * can be reached (so it will handle the doughnut case, where there is                         *\n * a passable in the center of an unreachable area).                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Clear_Path_Overlap -- clears the path overlap list                                        *\n *   Find_Path -- Find a path from point a to point b.                                         *\n *   Find_Path_Cell -- Finds a given cell on a specified path                                  *\n *   Follow_Edge -- Follow an edge to get around an impassable spot.                           *\n *   FootClass::Unravel_Loop -- Unravels a loop in the movement path                           *\n *   Get_New_XY -- Get the new x,y based on current position and direction.                    *\n *   Optimize_Moves -- Optimize the move list.                                                 *\n *   Set_Path_Overlap -- Sets the overlap bit for given cell                                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n//#include\t<string.h>\n\n/*\n**\tWhen an edge search is started, it can be performed CLOCKwise or\n**\tCOUNTERCLOCKwise direction.\n*/\n#define\tCLOCK\t\t\t\t(FacingType)1\t// Clockwise.\n#define\tCOUNTERCLOCK\t(FacingType)-1\t// Counterclockwise.\n\n/*\n**\tIf defined, diagonal moves are allowed, else no diagonals.\n*/\n#define\tDIAGONAL\n\n/*\n**\tThis is the marker to signify the end of the path list.\n*/\n#define\tEND\t\t\tFACING_NONE\n\n/*\n**\t\"- 1\" test for bit manipulation.\n*/\n#define TEST\n\n/*\n**\tIf memory is more important than speed, set this define to\n**\ttrue. It will then perform intermediate optimizations to get the most\n**\tmilage out of a limited movement list staging area. If this value\n**\tis true then it figures paths a bit more intelligently.\n*/\n#define\tSAVEMEM\t\ttrue\n\n/*\n**\tModify this macro so that given two cell values, it will return\n**\ta value between 0 and 7, with 0 being North and moving\n**\tclockwise (just like map degrees).\n*/\n#define\tCELL_FACING(a, b)\t\tDir_Facing(::Direction((a), (b)))\n\n\n/*-------------------------------------------------------------------------*/\n/*\n**\tCells values are really indexes into the 'map'. The following value is\n**\tthe X width of the map.\n*/\n#define\tMODULO\tMAP_CELL_W\n\n/*\n**\tMaximum lookahead cells. Twice this value in bytes will be\n**\treserved on the stack. The smaller this number, the faster the processing.\n*/\n#define MAX_MLIST_SIZE\t\t300\n#define THREAT_THRESHOLD\t5\n\n\n#define\tMAX_PATH_EDGE_FOLLOW\t400\n\n#ifdef NEVER\ntypedef enum {\n\tFACING_N,\t\t\t// North\n\tFACING_NE,\t\t\t// North-East\n\tFACING_E,\t\t\t// East\n\tFACING_SE,\t\t\t// South-East\n\tFACING_S,\t\t\t// South\n\tFACING_SW,\t\t\t// South-West\n\tFACING_W,\t\t\t// West\n\tFACING_NW,\t\t\t// North-West\n\n\tFACING_COUNT\t\t\t// Total of 8 directions (0..7).\n} FacingType;\n#endif\n\n\n/*-------------------------------------------------------------------------*/\n//static bool DrawPath;\n\ninline FacingType Opposite(FacingType face)\n{\n\treturn( (FacingType) (face ^ 4));\n}\n\n\ninline static FacingType Next_Direction(FacingType facing, FacingType dir)\n{\n\tfacing = facing + dir;\n\t#ifndef DIAGONAL\n\t\tfacing = (FacingType)(facing & 0x06);\n\t#endif\n\treturn(facing);\n}\n\n/*=========================================================================*/\n/* Define a couple of variables which are private to the module they are   */\n/*      declared in.                                                       */\n/*=========================================================================*/\nstatic unsigned long MainOverlap[MAP_CELL_TOTAL/32];\t\t// overlap list for the main path\nstatic unsigned long LeftOverlap[MAP_CELL_TOTAL/32];\t\t// overlap list for the left path\nstatic unsigned long RightOverlap[MAP_CELL_TOTAL/32];\t// overlap list for the right path\n\n\n//static CELL MoveMask = 0;\nstatic CELL DestLocation;\nstatic CELL StartLocation;\n\n/***************************************************************************\n * Point_Relative_To_Line -- Relation between a point and a line           *\n *                                                                         *\n *      If a point is on a line then the following function holds true:    *\n *      (x - x2)(z1 - z2) = (z - z2)(x1 - x2) given x,z a point on the     *\n *      line (x1,z1),(x2,z2).                                              *\n *      If the right side is > then the left side then the point is on one *\n *      side of the line and if the right side is < the the left side, then*\n *      the point is on the other side of the line.  By subtracting one side*\n *      from the other we can determine on what side (if any) the point is on*\n *      by testing the side of the resulting subtraction.                  *\n *                                                                         *\n * INPUT:                                                                  *\n *      int   x    - x pos of point.                                       *\n *      int   z    - z pos of point.                                       *\n *      int   x1 - x pos of first end of line segment.                     *\n *      int   z1 - z pos of first end of line segment.                     *\n *      int   x1 - x pos of second end of line segment.                    *\n *      int   z1 - z pos of second end of line segment.                    *\n *                                                                         *\n * OUTPUT:                                                                 *\n *   Assuming (x1,z1) is north, (x2,z2) is south:                          *\n *       0 : point is on line.                                             *\n *       > 0 : point is east of line.                                      *\n *       < 0 : point is west of line.                                      *\n *                                                                         *\n * WARNINGS:                                                               *\n *    Remember that int means that assumes 16 bits of precision.           *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/28/1994 SKB : Created.                                             *\n *=========================================================================*/\nint Point_Relative_To_Line(int x, int z, int x1, int z1, int x2, int z2)\n{\n\treturn((((long)x - (long)x2) * ((long)z1 - (long)z2)) - (((long)z - (long)z2) * ((long)x1 - (long)x2)));\n}\n\n\n/***************************************************************************\n * FootClass::Unravel_Loop -- Unravels a loop in the movement path         *\n *                                                                         *\n * While in the midst of the Follow Edge logic, it is possible (due to the *\n * fact that we support diagonal movement) to begin looping around a       *\n * column of some type.  The Unravel loop function will scan backward      *\n * through the list and fixup the path to try to prevent the loop.         *\n *                                                                         *\n * INPUT:      path   -   pointer to the generated path so we can pull the *\n *                         commands out of it.                             *\n *               cell   -   the cell we tried to enter that generated the  *\n *                        double overlap condition.                        *\n *               dir    -   the direction we tried to enter from when we   *\n *                        generated the double overlap condition           *\n *               startx -   the start x position of this path segment      *\n *               starty - the start y position of this path segment        *\n *               destx    - the dest x position for this path segment      *\n *               desty    - the dest y position for this path segment      *\n *                                                                         *\n * OUTPUT:      TRUE    - loop has been successfully unravelled             *\n *               FALSE  - loop can not be unravelled so abort follow edge  *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/25/1995 PWG : Created.                                             *\n *=========================================================================*/\nbool FootClass::Unravel_Loop(PathType * path, CELL &cell, FacingType &dir, int sx, int sy, int dx, int dy, MoveType threshhold)\n{\n\t/*\n\t** Walk back to the actual cell before we advanced our position\n\t*/\n\tFacingType\tcurr_dir\t= dir;\n\tCELL\t\t\tcurr_pos = Adjacent_Cell(cell, Opposite(curr_dir));\n\tint\t\t\tidx\t\t= path->Length;\t\t\t// start at the last position\n\tFacingType\t* list\t\t= &path->Command[idx-1];\t// point to the last command\n\tint\t\t\tcheckx;\n\tint\t\t\tchecky;\n\tint\t\t\tlast_was_line\t= false;\n\n\t/*\n\t** loop backward through the list searching for a point that is\n\t** on the line.  If the point was a diagonal move then adjust\n\t** it.\n\t*/\n\twhile (idx) {\n\t\tcheckx\t\t= Cell_X(curr_pos);\n\t\tchecky\t\t= Cell_Y(curr_pos);\n\n\t\tif (!Point_Relative_To_Line(checkx, checky, sx, sy, dx, dy) || last_was_line) {\n\n\t\t\t/*\n\t\t\t** We have now found a point on the line.  Now we must check to see\n\t\t\t** if we left the line on a diagonal.  If we did then we need to fix\n\t\t\t** it up.\n\t\t\t*/\n\t\t\tif (curr_dir & 1 && curr_pos != path->LastFixup) {\n\t\t\t\tcell \t\t\t\t = curr_pos;\n\t\t\t\tdir  \t\t\t\t = *(list-1);\n\t\t\t\tpath->Length\t = idx;\n\t\t\t\tpath->LastFixup = curr_pos;\n\t\t\t\treturn(true);\n\t\t\t}\n\n\t\t\tlast_was_line = !last_was_line;\n\t\t}\n\n\t\t/*\n\t\t** Since this cell will not be in the list, then pull out its cost\n\t\t*/\n\t\tpath->Cost -= Passable_Cell(curr_pos, *list, -1, threshhold);\n\n\t\t/*\n\t\t** Remove this cells flag from the overlap list for the path\n\t\t*/\n#ifdef TEST\n\t\tpath->Overlap[curr_pos >> 5] &= ~(1 << ((curr_pos & 31)));\n#else\n\t\tpath->Overlap[curr_pos >> 5] &= ~(1 << ((curr_pos & 31) - 1));\n#endif\n\n\t\t/*\n\t\t** Adjust to the next list position and direction.\n\t\t*/\n\t\tcurr_dir = *list--;\n\t\tcurr_pos\t= Adjacent_Cell(curr_pos, Opposite(curr_dir));\n\t\tidx--;\n\t}\n\n\t/*\n\t** If we can't modify the list to eliminate the problem, then we have\n\t** a larger problem in that we have deleted all of the cells in the\n\t** list.\n\t*/\n\treturn(false);\n}\n\n\n/***************************************************************************\n * Register_Cell -- registers a cell on our path and check for backtrack   *\n *                                                                         *\n * This function adds a new cell to our path.  If the cell has already     *\n * been recorded as part of our path, then this function moves back down   *\n * the list truncating it at the point we registered that cell.  This      *\n * function will eliminate all backtracking from the list.                 *\n *                                                                         *\n * INPUT:      long   * list - the list to set the overlap bit for         *\n *               CELL  cell    - the cell to mark on the overlap list      *\n *                                                                         *\n * OUTPUT:     BOOL - TRUE if bit has been set, FALSE if bit already set   *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nbool FootClass::Register_Cell(PathType * path, CELL cell, FacingType dir, int cost, MoveType threshhold)\n{\n\tFacingType  * list;\n\tint \tpos  = cell >> 5;\n#ifdef TEST\n\tint\tbit  = (cell & 31);\n#else\n\tint\tbit  = (cell & 31) - 1;\n#endif\n\n\t/*\n\t** See if this point has already been registered as on the list.  If so\n\t** we need to truncate the list back to this point and register the\n\t** new direction.\n\t*/\n\tif (path->Overlap[pos] & (1 << bit)) {\n\t\t/*\n\t\t** If this is not a case of immediate back tracking then handle\n\t\t** by searching the list to see what we find.  However is this is\n\t\t** an immediate back track, then pop of the last direction\n\t\t** and unflag the cell we are in (not the cell we are moving to).\n\t\t** Note: That we do not check for a zero length cell because we\n\t\t** could not have a duplicate unless there are cells in the list.\n\t\t*/\n\n\t\tif (path->Command[path->Length - 1] == Opposite(dir)) {\n\t\t\tCELL pos = Adjacent_Cell(cell, Opposite(dir));\n#ifdef TEST\n\t\t\tpath->Overlap[pos >> 5] &= ~(1 << ((pos & 31)));\n#else\n\t\t\tpath->Overlap[pos >> 5] &= ~(1 << ((pos & 31) - 1));\n#endif\n\t\t\tpath->Length--;\n\t\t} else {\n\t\t\t/*\n\t\t\t** If this overlap is in the same place as we had our last overlap\n\t\t\t** then we are in a loop condition.  We need to signify that we\n\t\t\t** cannot register this cell.\n\t\t\t*/\n\t\t\tif (path->LastOverlap == cell) {\n\t\t\t\treturn(false);\n\t\t\t} else {\n\t\t\t\tpath->LastOverlap = cell;\n\t\t\t}\n\n\t\t\tCELL pos \t  \t= path->Start;\n\t\t\tint newlen\t\t= 0;\n\t\t\tint idx \t\t   = 0;\n\t\t\tlist\t\t      = path->Command;\n\n\t\t\t/*\n\t\t\t** Note that the cell has to be in this list, so theres no sense\n\t\t\t** in checking whether we found it (famous last words).\n\t\t\t**\n\t\t\t** PWG 8/16/95 - However there is no sense searching the list if\n\t\t\t**               the cell we have overlapped on is the cell we\n\t\t\t**               started in.\n\t\t\t*/\n\n\t\t\tif (pos != cell) {\n\t\t\t\twhile (idx < path->Length) {\n\t\t\t\t\tpos = Adjacent_Cell(pos, *list);\n\t\t\t  \t\tif (pos == cell) {\n\t\t\t\t\t\tidx++;\n\t\t\t\t\t\tlist++;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tidx++;\n\t\t\t\t\tlist++;\n\t\t\t\t}\n\t\t\t\tnewlen = idx;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Now we are pointing at the next command in the list.  From here on\n\t\t\t** out we need to unmark the fact that we have entered these cells and\n\t\t\t** adjust the cost of our path to reflect that we have not entered\n\t\t\t** then.\n\t\t\t*/\n\t\t\twhile (idx < path->Length) {\n\t\t\t\tpos\t\t\t= Adjacent_Cell(pos, *list);\n\t\t\t\tpath->Cost -= Passable_Cell(pos, *list, -1, threshhold);\n#ifdef TEST\n\t\t\t\tpath->Overlap[pos >> 5] &= ~(1 << ((pos & 31)));\n#else\n\t\t\t\tpath->Overlap[pos >> 5] &= ~(1 << ((pos & 31) - 1));\n#endif\n\t\t\t\tidx++;\n\t\t\t\tlist++;\n\t\t\t}\n\t\t\tpath->Length = newlen;\n\t\t}\n\t} else {\n\t\t/*\n\t\t** Now we need to register the new direction, updating the cell structure\n\t\t** and the cost.\n\t\t*/\n\t\tint cpos \t\t\t\t= path->Length++;\n\t\tpath->Command[cpos]\t= dir;\t\t\t// save of the direction we moved\n\t\tpath->Cost \t\t\t  += cost;\t\t\t// figure new cost for cell\n\t\tpath->Overlap[pos]  |= (1 << bit);\t// mark the we have entered point\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Find_Path -- Find a path from point a to point b.                                           *\n *                                                                                             *\n * INPUT:      int source x,y, int destination x,y, char *final moves                          *\n *             array to store moves, int maximum moves we may attempt                          *\n *                                                                                             *\n * OUTPUT:     int number of moves it took (IMPOSSIBLE_MOVES if we could                       *\n *             not reach the destination                                                       *\n *                                                                                             *\n * WARNINGS:   This algorithm assumes that the target is NOT situated                          *\n *             inside an impassable. If this case may arise, the do-while                      *\n *             statement inside the inner while (true) must be changed                         *\n *             to include a check to se if the next_x,y is equal to the                        *\n *             dest_x,y. If it is, then return(IMPOSSIBLE_MOVES).                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1991  CY : Created.                                                                 *\n *=============================================================================================*/\nPathType * FootClass::Find_Path(CELL dest, FacingType * final_moves, int maxlen, MoveType threshhold)\n{\n\tCELL\t\t\t\t\tsource = Coord_Cell(Coord);\t\t// Source expressed as cell\n\tstatic PathType\tpath;\t\t\t\t\t\t\t\t\t\t// Main path control.\n\tCELL\t\t\t\t\tnext;\t\t\t\t\t\t\t\t\t\t// Next cell to enter\n\tCELL\t\t\t\t\tstartcell;\t\t\t\t\t\t\t\t// Cell we started in\n\tFacingType\t\t\tdirection;\t\t\t\t\t\t\t\t// Working direction of look ahead.\n\tFacingType\t\t\tnewdir;\t\t\t\t\t\t\t\t\t// Tentative facing value.\n\n\tbool\t\t\t\t\tleft=false, \t\t\t\t\t\t\t// Was leftward path legal?\n\t\t\t\t\t\t\tright=false;\t\t\t\t\t\t\t// Was rightward path legal?\n\n\tint\t\t\t\t\tlen;\t\t\t\t\t\t\t\t\t\t// Length of detour command list.\n\tint\t\t\t\t\tunit_threat;\t\t\t\t\t\t\t// Calculated unit threat rating\n\tint\t\t\t\t\tcost;\t\t\t\t\t\t\t\t\t\t// Cost to enter the square\n\tFacingType\t\t\tmoves_left[MAX_MLIST_SIZE+2], \t// Counterclockwise move list.\n\t\t\t\t\t\t\tmoves_right[MAX_MLIST_SIZE+2];\t// Clockwise move list.\n\tPathType\t\t\t\tpleft,pright;\t\t\t\t\t\t\t// Path control structures.\n\tPathType *\t\t\twhich;\t\t\t\t\t\t\t\t\t// Which path to actually use.\n\tint\t\t\t\t\tthreat;\n\tint\t\t\t\t\tthreat_stage;\n\n\t/*\n\t** If we have been provided an illegal place to store our final moves\n\t** then forget it.\n\t*/\n\tif (!final_moves) return(NULL);\n\n\tBStart(BENCH_FINDPATH);\n\n\tPathCount++;\n\n\tif (Team && Team->Class->IsRoundAbout) {\n\t\tunit_threat\t\t\t= (Team) ? Team->Risk : Risk();\n\t\tthreat_stage\t\t= 0;\n\t\tthreat\t\t\t\t= 0;\n\t} else {\n\t\tunit_threat = threat = -1;\n\t}\n\n\tStartLocation = source;\n\tDestLocation = dest;\n\n\t/*\n\t** Initialize the path structure so that we can keep track of the\n\t** path.\n\t*/\n\tpath.Start\t\t\t= source;\n\tpath.Cost\t\t\t= 0;\n\tpath.Length \t\t= 0;\n\tpath.Command \t\t= final_moves;\n\tpath.Command[0] \t= END;\n\tpath.Overlap\t\t= MainOverlap;\n\tpath.LastOverlap\t= -1;\n\tpath.LastFixup\t\t= -1;\n\n\tmemset(path.Overlap, 0, sizeof(MainOverlap));\n\n\t/*\n\t** Clear the over lap list and then make sure that our starting position is marked\n\t** on the overlap list.  (Otherwise the harvesters will drive in circles... )\n\t*/\n#ifdef TEST\n\tpath.Overlap[source >> 5] |= (1 << ((source & 31)));\n#else\n\tpath.Overlap[source >> 5] |= (1 << ((source & 31) - 1));\n#endif\n\n\tstartcell \t\t\t= source;\n\n\t/*\n\t**\tAccount for trailing end of list command, so reduce the maximum\n\t**\tallowed legal commands to reflect this.\n\t*/\n\tmaxlen--;\n\n\t/*\n\t**\tAs long as there is room to put commands in the movement command list,\n\t** then put commands in it.  We build the path using the following\n\t** methodology.\n\t**\n\t** 1. Scan through the desired straight line path until we either hit an\n\t**    impassable or have created a valid path.\n\t**\n\t** 2. If we have hit an impassable, walk through the impassable to make\n\t**    sure that there is a passable on the other side.  If there is not\n\t**    and we can not change the impassable, then this list is dead.\n\t**\n\t** 3. Walk around the impassable on both the left and right edges and\n\t**    take the shorter of the two paths.\n\t**\n\t** 4. Taking the new location as our start location start again with\n\t**    step #1.\n\t*/\n\twhile (path.Length < maxlen) {\n\ntop_of_list:\n\t\t/*\n\t\t**\tHave we reached the destination already?  If so abort any further\n\t\t**\tcommand building.\n\t\t*/\n\t\tif (startcell == dest) {\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tFind the absolute correct direction to reach the next straight\n\t\t** line cell and what cell it is.\n\t\t*/\n\t\tdirection\t= CELL_FACING(startcell, dest);\n\t\tnext\t\t\t= Adjacent_Cell(startcell, direction);\n\n\t\t/*\n\t\t**\tIf we can move here, then make this our next move.\n\t\t*/\n\t\tcost = Passable_Cell(next, direction, threat, threshhold);\n\t\tif (cost) {\n\t\t\tRegister_Cell(&path, next, direction, cost, threshhold);\n\t\t} else {\n\t\t\t/*\n\t\t\t**\tIf the impassable location is actually the destination,\n\t\t\t**\tthen stop here and consider this \"good enough\".\n\t\t\t*/\n\t\t\tif (next == dest) break;\n\n\t\t\t/*\n\t\t\t**\tWe could not move to the next cell, so follow through the\n\t\t\t**\timpassable until we find a passable spot that can be reached.\n\t\t\t** Once we find a passable, figure out the shortest path to it.\n\t\t\t** Since we have variable passable conditions this is not as\n\t\t\t** simple as it used to be.  The limiter loop below allows us to\n\t\t\t** step through ten doughnuts before we give up.\n\t\t\t*/\n\t\t\tfor (int limiter = 0; limiter < 5; limiter++) {\n\n\t\t\t\t/*\n\t\t\t\t**\tGet the next passable position by zipping through the\n\t\t\t\t** impassable positions until a passable position is found\n\t\t\t\t**\tor the destination is reached.\n\t\t\t\t*/\n\t\t\t\tfor (;;) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tMove one step closer toward destination.\n\t\t\t\t\t*/\n\t\t\t\t\tnewdir\t= CELL_FACING(next, dest);\n\t\t\t\t\tnext\t\t= Adjacent_Cell(next, newdir);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If the cell is passable then we have been completely\n\t\t\t\t\t** successful.  If the cell is not passable then continue.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Passable_Cell(next, FACING_NONE, threat, threshhold)) {\n//\t\t\t\t\tif ((Passable_Cell(next, FACING_NONE, threat, threshhold)) || (next == dest)) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf we reached destination while in this loop, we\n\t\t\t\t\t**\tknow that either the destination is impassible (if\n\t\t\t\t\t**\twe are ignoring) or that we need to up our threat\n\t\t\t\t\t** tolerance and try again.\n\t\t\t\t\t*/\n\t\t\t\t\tif (next == dest) {\n\t\t\t\t\t\tif (threat != -1) {\n\t\t\t\t\t\t\tswitch (threat_stage++) {\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\tthreat = unit_threat >> 1;\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\tthreat += unit_threat;\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t\tthreat = -1;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tgoto top_of_list;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tgoto end_of_list;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tTry to find a path to the passable position by following\n\t\t\t\t**\tthe edge of the blocking object in both CLOCKwise and\n\t\t\t\t**\tCOUNTERCLOCKwise fashions.\n\t\t\t\t*/\n\t\t\t\tint follow_len = maxlen + (maxlen >> 1);\n\n\t\t\t\tMem_Copy(&path, &pleft, sizeof(PathType));\n\t\t\t\tpleft.Command \t= &moves_left[0];\n\t\t\t\tpleft.Overlap \t= LeftOverlap;\n\t\t\t\tMem_Copy(path.Command, pleft.Command, path.Length);\n\t\t\t\tMem_Copy(path.Overlap, pleft.Overlap, sizeof(LeftOverlap));\n\t\t\t\tleft = Follow_Edge(startcell, next, &pleft, COUNTERCLOCK, direction, threat, threat_stage, sizeof(moves_left)/sizeof(moves_left[0]), threshhold);\n//\t\t\t\tleft = Follow_Edge(startcell, next, &pleft, COUNTERCLOCK, direction, threat, threat_stage, follow_len, threshhold);\n\n\t\t\t\tif (left) {\n\t\t\t\t\tfollow_len = min(maxlen, pleft.Length + (pleft.Length >> 1));\n\t\t\t\t}\n\n\t\t\t\tMem_Copy(&path, &pright, sizeof(PathType));\n\t\t\t\tpright.Command = &moves_right[0];\n\t\t\t\tpright.Overlap = RightOverlap;\n\t\t\t\tMem_Copy(path.Command, pright.Command, path.Length);\n\t\t\t\tMem_Copy(path.Overlap, pright.Overlap, sizeof(RightOverlap));\n\t\t\t\tright = Follow_Edge(startcell, next, &pright, CLOCK, direction, threat, threat_stage, sizeof(moves_right)/sizeof(moves_right[0]), threshhold);\n//\t\t\t\tright = Follow_Edge(startcell, next, &pright, CLOCK, direction, threat, threat_stage, follow_len, threshhold);\n\n\t\t\t\t/*\n\t\t\t\t**\tIf we could find a path, break from this loop. Otherwise this\n\t\t\t\t**\tmeans that we have found a \"hole\" of passable terrain that\n\t\t\t\t**\tcannot be reached by normal means. Scan forward looking for\n\t\t\t\t**\tthe other side of the \"doughnut\".\n\t\t\t\t*/\n\t\t\t\tif (left || right) break;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf no path can be found to the intermediate cell, then\n\t\t\t\t**\tpresume we have found a doughnut of some sort. Scan\n\t\t\t\t**\tforward until the next impassable is found and then\n\t\t\t\t**\tprocess this loop again.\n\t\t\t\t*/\n\t\t\t\tdo {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf we reached destination while in this loop, we\n\t\t\t\t\t**\tknow that either the destination is impassible (if\n\t\t\t\t\t**\twe are ignoring) or that we need to up our threat\n\t\t\t\t\t** tolerance and try again.\n\t\t\t\t\t*/\n\t\t\t\t\tif (next == dest) {\n\t\t\t\t\t\tif (threat != -1) {\n\t\t\t\t\t\t\tswitch (threat_stage++) {\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\tthreat = unit_threat >> 1;\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\tthreat += unit_threat;\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t\tthreat = -1;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tgoto top_of_list;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tgoto end_of_list;\n\t\t\t\t\t}\n\n\t\t\t\t\tnewdir\t= CELL_FACING(next, dest);\n\t\t\t\t\tnext\t\t= Adjacent_Cell(next, newdir);\n\t\t\t\t} while (Passable_Cell(next, newdir, threat, threshhold));\n\t\t\t}\n\n\t\t\tif (!left && !right) break;\n\n\t\t\t/*\n\t\t\t**\tWe found a path around the impassable locations, so figure out\n\t\t\t**\twhich one was the smallest and copy those moves into the\n\t\t\t**\tpath.Command array.\n\t\t\t*/\n\t\t\twhich = &pleft;\n\t\t\tif (right) {\n\t\t\t\twhich = &pright;\n\t\t\t\tif (left) {\n\t\t\t\t\tif (pleft.Length < pright.Length) {\n\t\t\t\t\t\twhich = &pleft;\n\t\t\t\t\t} else {\n\t\t\t\t\t\twhich = &pright;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRecord as much as possible of the shorter of the two\n\t\t\t**\tpaths. The trailing EOL command is not copied because\n\t\t\t**\tthis may not be the end of the find path logic.\n\t\t\t*/\n\t\t\tlen = which->Length;\n\t\t\tlen = min(len, maxlen);\n\t\t\tif (len > 0) {\n\t\t\t\tmemcpy(&path.Overlap[0], &which->Overlap[0], sizeof(LeftOverlap));\n\t\t\t\tmemcpy(&path.Command[0], &which->Command[0], len * sizeof(FacingType));\n\t\t\t\tpath.Length \t\t= len;\n\t\t\t\tpath.Cost   \t\t= which->Cost;\n\t\t\t\tpath.LastOverlap \t= -1;\n\t\t\t\tpath.LastFixup\t \t= -1;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tstartcell = next;\n\t}\n\nend_of_list:\n\t/*\n\t**\tPoke in the stop command.\n\t*/\n\tif (path.Length < maxlen) {\n\t\tpath.Command[path.Length++] = END;\n\t}\n\n\t/*\n\t**\tOptimize the move list but only necessary if\n\t**\tdiagonal moves are allowed.\n\t*/\n\t#ifdef DIAGONAL\n\t\tOptimize_Moves(&path, threshhold);\n\t#endif\n\n\tBEnd(BENCH_FINDPATH);\n\n\treturn(&path);\n}\n\n\n/***********************************************************************************************\n * Follow_Edge -- Follow an edge to get around an impassable spot.                             *\n *                                                                                             *\n * INPUT:   start    -- cell to head from                                                      *\n *                                                                                             *\n *            target   -- Target cell to head to.                                              *\n *                                                                                             *\n *          path     -- Pointer to path list structure.                                        *\n *                                                                                             *\n *          search   -- Direction of search (1=clock, -1=counterclock).                        *\n *                                                                                             *\n *          olddir   -- Facing impassible direction from start.                                *\n *                                                                                             *\n *          callback -- Function pointer for determining if a cell is                          *\n *                      passable or not.                                                       *\n *                                                                                             *\n * OUTPUT:  bool: Could a path be found to the desired cell?                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1991  CY : Created.                                                                 *\n *   06/01/1992  JLB : Optimized & commented.                                                  *\n *=============================================================================================*/\nbool FootClass::Follow_Edge(CELL start, CELL target, PathType * path, FacingType search, FacingType olddir, int threat, int , int max_cells, MoveType threshhold)\n{\n\tFacingType\tnewdir;\t\t\t// Direction of facing before surrounding cell check.\n\tCELL\t\t\toldcell,\t\t// Current cell.\n\t\t\t\t\tnewcell;\t\t// Tentative new cell.\n\tint\t\t\tcost;\t\t\t\t// Working cost value.\n\tint\t\t\tstartx;\n\tint\t\t\tstarty;\n\tint\t\t\tonline=true;\n\tint\t\t\ttargetx;\n\tint\t\t\ttargety;\n\tint\t\t\toldval = 0;\n\tint\t\t\tcellcount=0;\n\tint\t\t\tforceout = false;\n\tFacingType\tfirstdir = (FacingType)-1;\n\tCELL\t\t\tfirstcell = -1;\n\tbool\t\t\tstepped_off_line = false;\n\tstartx \t= Cell_X(start);\n\tstarty\t= Cell_Y(start);\n\ttargetx  = Cell_X(target);\n\ttargety\t= Cell_Y(target);\n\n\tif (!path) return(false);\n\tpath->LastOverlap = -1;\n\tpath->LastFixup\t= -1;\n\n\t#ifndef DIAGONAL\n\t\t/*\n\t\t**\tThe edge following algorithm doesn't \"do\" diagonals. Force initial facing\n\t\t**\tto be an even 90 degree value. Adjust it in the direction it should be\n\t\t**\trotating.\n\t\t*/\n\t\tif (olddir & 0x01) {\n\t\t\tolddir = Next_Direction(olddir, search);\n\t\t}\n\t#endif\n\n\tnewdir\t\t= Next_Direction(olddir, search);\n\toldcell \t\t= start;\n\tnewcell \t\t= Adjacent_Cell(oldcell, newdir);\n\n\t/*\n\t**\tContinue until we find our target, find our original starting spot,\n\t**\tor run out of moves.\n\t*/\n\twhile (path->Length < max_cells) {\n\n\t\t/*\n\t\t**\tLook in all the adjacent cells to determine a passable one that\n\t\t**\tmost closely matches the desired direction (working in the specified\n\t\t**\tdirection).\n\t\t*/\n\t\tnewdir = olddir;\n\t\tfor (;;) {\n\t\t\tbool\tforcefail;\t\t// Is failure forced?\n\n\t\t\tforcefail = false;\n\n\t\t\t#ifdef DIAGONAL\n\t\t\t\t/*\n\t\t\t\t**\tRotate 45/90 degrees in desired direction.\n\t\t\t\t*/\n\t\t\t\tnewdir = Next_Direction(newdir, search);\n\n\t\t\t\t/*\n\t\t\t\t**\tIf facing a diagonal we must check the next 90 degree location\n\t\t\t\t**\tto make sure that we don't walk right by the destination. This\n\t\t\t\t**\twill happen if the destination it is at the corner edge of an\n\t\t\t\t**\timpassable that we are moving around.\n\t\t\t\t*/\n\t\t\t\tif (newdir & FACING_NE) {\n\t\t\t\t\tCELL\tcheckcell;\t\t// Non-diagonal check cell.\n\t\t\t\t\t//int\tx,y;\n\n\t\t\t\t\tcheckcell = Adjacent_Cell(oldcell, Next_Direction(newdir, search));\n\n\t\t\t\t\tif (checkcell == target) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tThis only works if in fact, it is possible to move to the\n\t\t\t\t\t\t**\tcell from the current location.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcost = Passable_Cell(checkcell, Next_Direction(newdir, search), threat, threshhold);\n\t\t\t\t\t\tif (cost) {\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tYES! The destination is at the corner of an impassable, so\n\t\t\t\t\t\t\t**\tset the direction to point directly at it and then the\n\t\t\t\t\t\t\t**\tscanning will terminate later.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tnewdir = Next_Direction(newdir, search);\n\t\t\t\t\t\t\tnewcell = Adjacent_Cell(oldcell, newdir);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tPerform special diagonal check. If the edge follower would cross the\n\t\t\t\t\t**\tdiagonal or fall on the diagonal line from the source, then consider\n\t\t\t\t\t**\tthat cell impassible. Otherwise, the find path algorithm will fail\n\t\t\t\t\t**\twhen there are two impassible locations located on a diagonal\n\t\t\t\t\t**\tthat is lined up between the source and destination location.\n\t\t\t\t\t**\n\t\t\t\t\t** P.S. It might help if you check the right cell rather than using\n\t\t\t\t\t**      the value that just happened to be in checkcell.\n\t\t\t\t\t*/\n\n\t\t\t\t\tcheckcell = Adjacent_Cell(oldcell, newdir);\n\n\t\t\t\t\tint checkx\t\t= Cell_X(checkcell);\n\t\t\t\t\tint checky\t\t= Cell_Y(checkcell);\n\t\t\t\t\tint checkval\t= Point_Relative_To_Line(checkx, checky, startx, starty, targetx, targety);\n\t\t\t\t\tif (checkval && !online) {\n\t\t\t\t\t\tforcefail = ((checkval ^ oldval) < 0);\n\t\t\t\t\t} else {\n\t\t\t \t\t\tforcefail = false;\n\t\t\t\t\t}\n\t\t\t\t\t/*\n\t\t\t\t\t** The only exception to the above is when we are directly backtracking\n\t\t\t\t\t** because we could be trying to escape from a culdesack!\n\t\t\t\t\t*/\n\t\t\t\t\tif (forcefail && path->Length > 0 && (FacingType)(newdir ^ 4) == path->Command[path->Length - 1]) {\n\t\t\t\t\t\tforcefail = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t#else\n\t\t\t\tnewdir = Next_Direction(newdir, search*2);\n\t\t\t#endif\n\n\t\t\t/*\n\t\t\t**\tIf we have just checked the same heading we started with,\n\t\t\t**\twe are surrounded by impassable characters and we exit.\n\t\t\t*/\n\t\t\tif (newdir == olddir) {\n\t\t\t\treturn(false);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tGet the new cell.\n\t\t\t*/\n\t\t\tnewcell = Adjacent_Cell(oldcell, newdir);\n\n\t\t\t/*\n\t\t\t**\tIf we found a passable position, this is where we should move.\n\t\t\t*/\n\t\t\tif (!forcefail && ((cost = Passable_Cell(newcell, newdir, threat, threshhold)) != 0)) {\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tif (newcell == target) {\n\t\t\t\t\tforceout = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\t/*\n\t\t**\tRecord the direction.\n\t\t*/\n\t\tif (!forceout) {\n\t\t\t/*\n\t\t\t** Mark the cell because this is where we need to be.  If register\n\t\t\t** cell fails then the list has been shortened and we need to adjust\n\t\t\t** the new direction.\n\t\t\t*/\n\t\t\tif (!Register_Cell(path, newcell, newdir, cost, threshhold)) {\n\t\t\t\t/*\n\t\t\t\t** The only reason we could not register a cell is that we are in\n\t\t\t\t** a looping situation.  So we need to try and unravel the loop if\n\t\t\t\t** we can.\n\t\t\t\t*/\n\t\t\t\tif (!Unravel_Loop(path, newcell, newdir, startx, starty, targetx, targety, threshhold)) {\n\t\t\t\t\treturn(false);\n\t\t\t\t}\n\t\t\t\t/*\n\t\t\t\t** Since we need to eliminate a diagonal we must pretend the upon\n\t\t\t\t** attaining this square, we were moving turned further in the\n\t\t\t\t** search direction then we really were.\n\t\t\t\t*/\n\t\t\t\tnewdir = Next_Direction(newdir, (FacingType)(search*2));\n\t\t\t}\n\t\t\t/*\n\t\t\t** Find out which side of the line this cell is on.  If it is on\n\t\t\t** a side, then store off that side.\n\t\t\t*/\n\t\t\tint newx\t= Cell_X(newcell);\n\t\t\tint newy\t= Cell_Y(newcell);\n\t\t\tint val\t= Point_Relative_To_Line(newx, newy, startx, starty, targetx, targety);\n\t\t\tif (val) {\n\t\t\t\toldval = val;\n\t\t\t\tonline = false;\n\t\t\t} else {\n\t\t\t\tonline = true;\n\t\t\t}\n\t\t\tcellcount++;\n\t\t\tif (cellcount == MAX_PATH_EDGE_FOLLOW) {\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf we have found the target spot, we are done.\n\t\t*/\n\t\tif (newcell == target) {\n\t\t\tpath->Command[path->Length] = END;\n\t\t\treturn(true);\n\t\t}\n\n\t\t/*\n\t\t**\tIf we make a full circle back to our original spot, get out.\n\t\t*/\n\t\tif (newcell == firstcell && newdir == firstdir) {\n\t\t\treturn(false);\n\t\t}\n\n\t\tif (firstcell == -1) {\n\t\t\tfirstcell = newcell;\n\t\t\tfirstdir  = newdir;\n\t\t}\n\n\t\t/*\n\t\t**\tBecause we moved, our facing is now incorrect. We want to face toward\n\t\t**\tthe impassable edge we are following (well, not actually toward, but\n\t\t**\ta little past so that we can turn corners). We have to turn 45/90 degrees\n\t\t**\tmore than expected in anticipation of the pending 45/90 degree turn at\n\t\t**\tthe start of this loop.\n\t\t*/\n\t\t#ifdef DIAGONAL\n\t\t\tolddir = Next_Direction(newdir, (FacingType)(-(int)search*3));\n\t\t#else\n\t\t\tolddir = Next_Direction(newdir, (FacingType)(-(int)search*4));\n\t\t#endif\n\t\toldcell = newcell;\n\t}\n\n\t/*\n\t**\tThe maximum search path is exhausted... abort with a failure.\n\t*/\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * Optimize_Moves -- Optimize the move list.                                                   *\n *                                                                                             *\n * INPUT:      char *moves to optimize                                                         *\n *                                                                                             *\n * OUTPUT:     none (list is optimized)                                                        *\n *                                                                                             *\n * WARNINGS:   EMPTY moves are used to hold the place of eliminated                            *\n *             commands. Also, NEVER call this routine with a list that                        *\n *             contains illegal commands. The list MUST be terminated                          *\n *             with a EOL command                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1991  CY : Created.                                                                 *\n *   06/01/1992  JLB : Optimized and commented.                                                *\n *=============================================================================================*/\n#define\tEMPTY\t\t(FacingType)-2\nint FootClass::Optimize_Moves(PathType * path, MoveType threshhold)\n//int Optimize_Moves(PathType *path, int (*callback)(CELL, FacingType), int threshold)\n{\n\t/*\n\t**\tFacing command pair adjustment table. Compare the facing difference between\n\t**\tthe two commands. 0 means no optimization is possible. 3 means backtracking\n\t**\tso eliminate both commands. Any other value adjusts the first command facing.\n\t*/\n#ifdef DIAGONAL\n\tstatic FacingType _trans[FACING_COUNT] = {(FacingType)0, (FacingType)0, (FacingType)1, (FacingType)2, (FacingType)3, (FacingType)-2, (FacingType)-1, (FacingType)0};\t// Smoothing.\n#else\n\tstatic FacingType _trans[FACING_COUNT] = {(FacingType)0, (FacingType)0, (FacingType)0, (FacingType)2, (FacingType)3, (FacingType)-2, (FacingType)0, (FacingType)0};\n#endif\n\tFacingType\t* cmd1,\t\t// Floating first command pointer.\n\t\t\t\t\t* cmd2,\t\t// Floating second command pointer.\n\t\t\t\t\tnewcmd;\t\t// Calculated new optimized command.\n\tFacingType\tnewdir;\t\t// Tentative new direction for smoothing.\n\tCELL\t\t\tcell;\t\t\t// Working cell (as it moves along path).\n\n\t/*\n\t**\tAbort if there is any illegal parameter.\n\t*/\n\tif (!path || !path->Command) return(0);\n\n\t/*\n\t**\tOptimization loop -- start scanning with the\n\t**\tfirst pair of commands (if there are at least two\n\t**\tin the command list).\n\t*/\n\tpath->Command[path->Length] = END;\t\t// Force end of list.\n\n\tif (path->Length == 0) return(0);\n\n\tcell = path->Start;\n\tif (path->Length > 1) {\n\t\tcmd2 = path->Command + 1;\n\t\twhile (*cmd2 != END) {\n\n\t\t\t/*\n\t\t\t**\tSet the cmd1 pointer to point to the valid command closest, but\n\t\t\t**\tprevious to cmd2. Be sure not to go previous to the head of the\n\t\t\t**\tcommand list.\n\t\t\t*/\n\t\t\tcmd1 = cmd2-1;\n\t\t\twhile (*cmd1 == EMPTY && cmd1 != path->Command) {\n\t\t\t\tcmd1--;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf there isn't any valid previous command, then bump the\n\t\t\t**\tcmd pointers to the next command pair and continue...\n\t\t\t*/\n\t\t\tif (*cmd1 == EMPTY) {\n\t\t\t\tcmd2++;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tFetch precalculated command change value. 0 means leave\n\t\t\t**\tcommand set alone, 3 means backtrack and eliminate two\n\t\t\t**\tcommands. Any other value is new direction and eliminate\n\t\t\t**\tone command.\n\t\t\t*/\n\t\t\tnewcmd = (FacingType)(*cmd2 - *cmd1);\n\t\t\tif (newcmd < FACING_N) newcmd = (FacingType)(newcmd + FACING_COUNT);\n\t\t\tnewcmd = _trans[newcmd];\n\n\t\t\t/*\n\t\t\t**\tCheck for backtracking. If this occurs, then eliminate the\n\t\t\t**\ttwo commands. This is the easiest optimization.\n\t\t\t*/\n\t\t\tif (newcmd == FACING_SE) {\n\t\t\t\t*cmd1 = EMPTY;\n\t\t\t\t*cmd2++ = EMPTY;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf an optimization code was found the process it. The command is a facing\n\t\t\t**\toffset to more directly travel toward the immediate destination cell.\n\t\t\t*/\n\t\t\tif (newcmd) {\n\n\t\t\t\t/*\n\t\t\t\t**\tOptimizations differ when dealing with diagonals. Especially when dealing\n\t\t\t\t**\twith diagonals of 90 degrees. In such a case, 90 degree optimizations can\n\t\t\t\t**\tonly be optimized if the intervening cell is passable. The distance travelled\n\t\t\t\t**\tis the same, but the path is less circuitous.\n\t\t\t\t*/\n\t\t\t\tif (*cmd1 & FACING_NE) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDiagonal optimizations are always only 45\n\t\t\t\t\t**\tdegree adjustments.\n\t\t\t\t\t*/\n\t\t\t\t\tnewdir = Next_Direction(*cmd1, (newcmd < FACING_N) ? (FacingType)-1 : (FacingType)1);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDiagonal 90 degree changes can be smoothed, although\n\t\t\t\t\t**\tthe path isn't any shorter.\n\t\t\t\t\t*/\n\t\t\t\t\tif (ABS((int)newcmd) == 1) {\n\t\t\t\t\t\tif (Passable_Cell(Adjacent_Cell(cell, newdir), newdir, -1, threshhold)) {\n\t\t\t\t\t\t\t*cmd2 = newdir;\n\t\t\t\t\t\t\t*cmd1 = newdir;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// BOB 16.12.92\n\t\t\t\t\t\tcell = Adjacent_Cell(cell, *cmd1);\n\t\t\t\t\t\tcmd2++;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tnewdir = Next_Direction(*cmd1, newcmd);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAllow shortening turn only on right angle moves that are based on\n\t\t\t\t**\t90 degrees. Always allow 135 degree optimizations.\n\t\t\t\t*/\n\t\t\t\t*cmd2 = newdir;\n\t\t\t\t*cmd1 = EMPTY;\n\n\t\t\t\t/*\n\t\t\t\t**\tBackup what it thinks is the current cell.\n\t\t\t\t*/\n\t\t\t\twhile (*cmd1 == EMPTY && cmd1 != path->Command) {\n\t\t\t\t\tcmd1--;\n\t\t\t\t}\n\t\t\t\tif (*cmd1 != EMPTY) {\n\t\t\t\t\tcell = Adjacent_Cell(cell, Next_Direction(*cmd1, FACING_S));\n\t\t\t\t} else {\n\t\t\t\t\tcell = path->Start;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSince we could not make an optimization, we move our\n\t\t\t**\thead pointer forward.\n\t\t\t*/\n\t\t\tcell = Adjacent_Cell(cell, *cmd1);\n\t\t\tcmd2++;\n\t\t}\n\t}\n\n\t/*\n\t**\tPack the command list to remove any EMPTY command entries.\n\t*/\n\tcmd1 = path->Command;\n\tcmd2 = path->Command;\n\tcell = path->Start;\n\tpath->Cost = 0;\n\tpath->Length = 0;\n\twhile (*cmd2 != END) {\n\t\tif (*cmd2 != EMPTY) {\n\t\t\tcell = Adjacent_Cell(cell, *cmd2);\n\t\t\tpath->Cost+= Passable_Cell(cell, *cmd2, -1, threshhold);\n\t\t\tpath->Length++;\n\t\t\t*cmd1++ = *cmd2;\n\t\t}\n\t\tcmd2++;\n\t}\n\tpath->Length++;\n\t*cmd1 = END;\n\treturn(path->Length);\n}\n\n\nCELL FootClass::Safety_Point(CELL src, CELL dst, int start, int max)\n{\n\tFacingType dir;\n\tCELL\t\t  next;\n\tint \t\t  lp;\n\n\tdir = (FacingType)(CELL_FACING(src, dst) ^ 4) - 1;\n\n\t/*\n\t** Loop through the different acceptable distances.\n\t*/\n\tfor (int dist = start; dist < max; dist ++) {\n\n\t\t/*\n\t\t** Move to the starting location.\n\t\t*/\n\t\tnext = dst;\n\n\t\tfor (lp = 0; lp < dist; lp ++) {\n\t\t\tnext = Adjacent_Cell(next, dir);\n\t\t}\n\n\t\tif (dir & 1) {\n\t\t\t/*\n\t\t\t** If our direction is diagonal than we need to check\n\t\t\t** only one side which is as long as both of the old sides\n\t\t\t** together.\n\t\t\t*/\n\t\t\tfor (lp = 0; lp < dist << 1; lp ++) {\n\t\t\t\tnext = Adjacent_Cell(next, dir + 3);\n\t\t\t\tif (!Can_Enter_Cell(next)) {\n\t\t\t\t\treturn(next);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t/*\n\t\t\t** If our direction is not diagonal than we need to check two\n\t\t\t** sides so that we are checking a corner like location.\n\t\t\t*/\n\t\t\tfor (lp = 0; lp < dist; lp ++) {\n\t\t\t\tnext = Adjacent_Cell(next, dir + 2);\n\t\t\t\tif (!Can_Enter_Cell(next)) {\n\t\t\t\t\treturn(next);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (lp = 0; lp < dist; lp ++) {\n\t\t\t\tnext = Adjacent_Cell(next, dir + 4);\n\t\t\t\tif (!Can_Enter_Cell(next)) {\n\t\t\t\t\treturn(next);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(-1);\n}\n\n\n\n\nint FootClass::Passable_Cell(CELL cell, FacingType face, int threat, MoveType threshhold)\n{\n\tMoveType move = Can_Enter_Cell(cell, face);\n\n\tif (move < MOVE_MOVING_BLOCK && Distance(Cell_Coord(cell)) > 0x0100) threshhold = MOVE_MOVING_BLOCK;\n\n\tif (move > threshhold) return(0);\n\n\tif (Session.Type == GAME_NORMAL) {\n\t\tif (threat != -1) {\n\t\t\tif (::Distance(Cell_Coord(cell), Cell_Coord(DestLocation)) > (THREAT_THRESHOLD * CELL_LEPTON_W)) {\n//\t\t\tif (Map.Cell_Distance(cell, DestLocation) > THREAT_THRESHOLD) {\n\t\t\t\tif (Map.Cell_Threat(cell, Owner()) > threat)\n\t\t\t\t\treturn(0);\n\t\t\t}\n\t\t}\n\t}\n\n\tstatic int _value[MOVE_COUNT] = {\n\t\t1,\t\t\t//\tMOVE_OK\n\t\t1,\t\t\t//\tMOVE_CLOAK\n\t\t3,\t\t\t//\tMOVE_MOVING_BLOCK\n\t\t8,\t\t\t//\tMOVE_DESTROYABLE\n\t\t10,\t\t//\tMOVE_TEMP\n\t\t0\t\t\t//\tMOVE_NO\n\t};\n\treturn(_value[move]);\n}\n\n"
  },
  {
    "path": "CODE/FIXED.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FIXED.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FIXED.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/20/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   fixed::As_ASCII -- Returns a pointer (static) of this number as an ASCII string.          *\n *   fixed::To_ASCII -- Convert a fixed point number into an ASCII string.                     *\n *   fixed::fixed -- Constructor for fixed integral from ASCII initializer.                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"fixed.h\"\n#include\t<string.h>\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<ctype.h>\n\n\n/*\n**\tThese are some handy fixed point constants. Using these constants instead of manually\n**\tconstructing them is not only faster, but more readable.\n*/\nconst fixed fixed::_1_2(1, 2);\t\t// 1/2\nconst fixed fixed::_1_3(1, 3);\t\t// 1/3\nconst fixed fixed::_1_4(1, 4);\t\t// 1/4\nconst fixed fixed::_3_4(3, 4);\t\t// 3/4\nconst fixed fixed::_2_3(2, 3);\t\t// 2/3\n\n\nfixed::fixed(int numerator, int denominator)\n{\n\tif (denominator == 0) {\n\t\tData.Raw = 0;\n\t} else {\n\t\tData.Raw = (unsigned short)((unsigned)(numerator * 256) / (unsigned)denominator);\n\t}\n}\n\n\n/***********************************************************************************************\n * fixed::fixed -- Constructor for fixed integral from ASCII initializer.                      *\n *                                                                                             *\n *    This will parse the ASCII initialization string into a fixed point number.               *\n *    The source string can be a conventional fixed point representation (e.g., \"1.0\", \".25\")  *\n *    or a percent value (e.g. \"100%\", \"25%\", \"150%\"). For percent values, the trailing \"%\"    *\n *    is required.                                                                             *\n *                                                                                             *\n * INPUT:   ascii -- Pointer to the ascii source to translate into a fixed point number.       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   It is possible to specify an ASCII string that has more precision and           *\n *             magnitude than can be represented by the fixed point number. In such a case,    *\n *             the resulting value is undefined.                                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed::fixed(char const * ascii)\n{\n\t/*\n\t**\tIf there is no valid pointer, then default to zero value. This takes care of any\n\t**\tcompiler confusion that would call this routine when the programmer wanted the\n\t**\tinteger parameter constructor to be called.\n\t*/\n\tif (ascii == NULL) {\n\t\tData.Raw = 0;\n\t\treturn;\n\t}\n\n\t/*\n\t**\tThe whole part (if any) always starts with the first legal characters.\n\t*/\n\tchar const * wholepart = ascii;\n\n\t/*\n\t**\tSkip any leading white space.\n\t*/\n\twhile (isspace(*ascii)) {\n\t\tascii++;\n\t}\n\n\t/*\n\t**\tDetermine if the number is expressed as a percentage. Detect this by\n\t**\tseeing if there is a trailing \"%\" character.\n\t*/\n\tchar const * tptr = ascii;\n\twhile (isdigit(*tptr)) {\n\t\ttptr++;\n\t}\n\n\t/*\n\t**\tPercentage value is specified as a whole number but is presumed to be\n\t**\tdivided by 100 to get mathematical fixed point percentage value.\n\t*/\n\tif (*tptr == '\\%') {\n\t\tData.Raw = (unsigned short)((atoi(ascii) * 256) / 100);\n\t} else {\n\n\t\tData.Composite.Whole = Data.Composite.Fraction = 0;\n\t\tif (wholepart && *wholepart != '.') {\n\t\t\tData.Composite.Whole = (unsigned char)atoi(wholepart);\n\t\t}\n\n\t\tchar * fracpart = strchr(ascii, '.');\n\t\tif (fracpart) fracpart++;\n\t\tif (fracpart) {\n\t\t\tint frac = atoi(fracpart);\n\n\t\t\tint len = 0;\n\t\t\tint base = 1;\n\t\t\tchar const * fptr = fracpart;\n\t\t\twhile (isdigit(*fptr)) {\n\t\t\t\tfptr++;\n\t\t\t\tlen++;\n\t\t\t\tbase *= 10;\n\t\t\t}\n\n\t\t\tData.Composite.Fraction = (unsigned char)((256 * frac) / base);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * fixed::To_ASCII -- Convert a fixed point number into an ASCII string.                       *\n *                                                                                             *\n *    Use this routine to convert this fixed point number into an ASCII null terminated        *\n *    string. This is the counterpart to the fixed point constructor that takes an ASCII       *\n *    string.                                                                                  *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer to hold the fixed point ASCII string.            *\n *                                                                                             *\n *          maxlen   -- The length of the buffer.                                              *\n *                                                                                             *\n * OUTPUT:  Returns with the number of characters placed in the buffer. The trailing null is   *\n *          not counted in this total.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint fixed::To_ASCII(char * buffer, int maxlen) const\n{\n\tif (buffer == NULL) return(0);\n\n\t/*\n\t**\tDetermine the whole and fractional parts of the number. The fractional\n\t**\tpart number is the value in 1000ths.\n\t*/\n\tint whole = Data.Composite.Whole;\n\tint frac = ((int)Data.Composite.Fraction * 1000) / 256;\n\tchar tbuffer[32];\n\n\t/*\n\t**\tIf there number consists only of a whole part, then the number is simply\n\t**\tprinted into the buffer. If there is a fractional part, then there\n\t**\twill be a decimal place followed by up to three digits of accuracy for the\n\t**\tfractional component.\n\t*/\n\tif (frac == 0) {\n\t\tsprintf(tbuffer, \"%d\", whole);\n\t} else {\n\t\tsprintf(tbuffer, \"%d.%02d\", whole, frac);\n\n\t\tchar * ptr = &tbuffer[strlen(tbuffer)-1];\n\t\twhile (*ptr == '0') {\n\t\t\t*ptr = '\\0';\n\t\t\tptr--;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf no maximum length to the output buffer was specified, then presume the\n\t**\toutput buffer is just long enough to store the number and the trailing\n\t**\tzero.\n\t*/\n\tif (maxlen == -1) {\n\t\tmaxlen = strlen(tbuffer)+1;\n\t}\n\n\t/*\n\t**\tFill the output buffer with the ASCII number.\n\t*/\n\tstrncpy(buffer, tbuffer, maxlen);\n\n\t/*\n\t**\tReturn with the number of ASCII characters placed into the output buffer.\n\t*/\n\tint len = strlen(tbuffer);\n\tif (len < maxlen-1) return(len);\n\treturn(maxlen-1);\n}\n\n\n/***********************************************************************************************\n * fixed::As_ASCII -- Returns a pointer (static) of this number as an ASCII string.            *\n *                                                                                             *\n *    This number will be converted into an ASCII string (using a static buffer) and the       *\n *    string pointer will be returned.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the ASCII representation of this fixed point number.     *\n *                                                                                             *\n * WARNINGS:   As with all static return pointers, the pointer is valid only until such time   *\n *             as this routine is called again.                                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * fixed::As_ASCII(void) const\n{\n\tstatic char buffer[32];\n\n\tTo_ASCII(buffer, sizeof(buffer));\n\treturn(buffer);\n}\n"
  },
  {
    "path": "CODE/FIXED.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FIXED.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FIXED.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/19/96                                                     *\n *                                                                                             *\n *                  Last Update : June 19, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef FIXED_H\n#define FIXED_H\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n//#pragma warning 604 9\n//#pragma warning 595 9\n\n/*\n**\tThis is a very simple fixed point class that functions like a regular integral type. However\n**\tit is under certain restrictions. The whole part must not exceed 255. The fractional part is\n**\tlimited to an accuracy of 1/256. It cannot represent or properly handle negative values. It\n**\treally isn't all that fast (if an FPU is guaranteed to be present than using \"float\" might be\n**\tmore efficient). It doesn't detect overflow or underflow in mathematical or bit-shift operations.\n**\n**\tTake careful note that the normal mathematical operators return integers and not fixed point\n**\tvalues if either of the components is an integer. This is the normal C auto-upcasting rule\n**\tas it would apply presuming that integers are considered to be of higher precision than\n**\tfixed point numbers. This allows the result of these operators to generate values with greater\n**\tmagnitude than is normally possible if the result were coerced into a fixed point number.\n**\tIf the result should be fixed point, then ensure that both parameters are fixed point.\n**\n**\tNote that although integers are used as the parameters in the mathematical operators, this\n**\tdoes not imply that negative parameters are supported. The use of integers is as a convenience\n**\tto the programmer -- constant integers are presumed signed. If unsigned parameters were\n**\tspecified, then the compiler would have ambiguous conversion situation in the case of constant\n** integers (e.g. 1, 10, 32, etc). This is most important for the constructor when dealing with the\n**\t\"0\" parameter case. In that situation the compiler might interpret the \"0\" as a null pointer rather\n**\tthan an unsigned integer. There should be no adverse consequences of using signed integer parameters\n**\tsince the precision/magnitude of these integers far exceeds the fixed point component counterparts.\n**\n**\tNote that when integer values are returns from the arithmetic operators, the value is rounded\n**\tto the nearest whole integer value. This differs from normal integer math that always rounds down.\n*/\nclass fixed\n{\n\tpublic:\n\t\t// The default constructor must not touch the data members in any way.\n\t\tfixed(void) {}\n\n\t\t// Convenient constructor if numerator and denominator components are known.\n\t\tfixed(int numerator, int denominator);\n\n\t\t// Conversion constructor to get fixed point from integer.\n\t\tfixed(int value) {Data.Composite.Fraction = 0;Data.Composite.Whole = (unsigned char)value;}\n\n\t\t// Constructor if ASCII image of number is known.\n\t\tfixed(char const * ascii);\n\n\t\t// Convert to integer when implicitly required.\n\t\toperator unsigned (void) const {return(((unsigned)Data.Raw+(256/2)) / 256);}\n\n\t\t/*\n\t\t**\tThe standard operators as they apply to in-place operation.\n\t\t*/\n\t\tfixed & operator *= (fixed const & rvalue) {Data.Raw = (unsigned short)(((int)Data.Raw * rvalue.Data.Raw) / 256);return(*this);}\n\t\tfixed & operator *= (int rvalue) {Data.Raw = (unsigned short)(Data.Raw * rvalue);return(*this);}\n\t\tfixed & operator /= (fixed const & rvalue) {if (rvalue.Data.Raw != 0 && rvalue.Data.Raw != 256) Data.Raw = (unsigned short)(((int)Data.Raw * 256) / rvalue);return(*this);}\n\t\tfixed & operator /= (int rvalue) {if (rvalue) Data.Raw = (unsigned short)((unsigned)Data.Raw / rvalue);return(*this);}\n\t\tfixed & operator += (fixed const & rvalue) {Data.Raw += rvalue.Data.Raw;return(*this);}\n\t\tfixed & operator -= (fixed const & rvalue) {Data.Raw -= rvalue.Data.Raw;return(*this);}\n\n\t\t/*\n\t\t**\tThe standard \"My Dear Aunt Sally\" operators. The integer versions of multiply\n\t\t**\tand divide are more efficient than using the fixed point counterparts.\n\t\t*/\n//\t\tconst fixed operator * (fixed const & rvalue) const {return(fixed(*this) *= rvalue);}\n\t\tconst fixed operator * (fixed const & rvalue) const {fixed temp = *this;temp.Data.Raw = (unsigned short)(((int)temp.Data.Raw * (int)rvalue.Data.Raw) / 256);return(temp);}\n\t\tconst int operator * (int rvalue) const {return ((((unsigned)Data.Raw * rvalue) + (256/2)) / 256);}\n//\t\tconst fixed operator / (fixed const & rvalue) const {return(fixed(*this) /= rvalue);}\n\t\tconst fixed operator / (fixed const & rvalue) const {fixed temp = *this;if (rvalue.Data.Raw != 0 && rvalue.Data.Raw != 256) temp.Data.Raw = (unsigned short)(((int)temp.Data.Raw * 256) / rvalue.Data.Raw);return(temp);}\n\t\tconst int operator / (int rvalue) const {if (rvalue) return(((unsigned)Data.Raw+(256/2)) / ((unsigned)rvalue*256));return(*this);}\n//\t\tconst fixed operator + (fixed const & rvalue) const {return(fixed(*this) += rvalue);}\n\t\tconst fixed operator + (fixed const & rvalue) const {fixed temp = *this;temp += rvalue;return(temp);}\n\t\tconst int operator + (int rvalue) const {return((((unsigned)Data.Raw+(256/2))/256) + rvalue);}\n//\t\tconst fixed operator - (fixed const & rvalue) const {return(fixed(*this) -= rvalue);}\n\t\tconst fixed operator - (fixed const & rvalue) const {fixed temp = *this;temp -= rvalue;return(temp);}\n\t\tconst int operator - (int rvalue) const {return((((unsigned)Data.Raw+(256/2))/256) - rvalue);}\n\n\t\t/*\n\t\t**\tThe Shift operators are more efficient than using multiplies or divides by power-of-2 numbers.\n\t\t*/\n\t\tfixed & operator >>= (unsigned rvalue) {Data.Raw >>= rvalue;return(*this);}\n\t\tfixed & operator <<= (unsigned rvalue) {Data.Raw <<= rvalue;return(*this);}\n\t\tconst fixed operator >> (unsigned rvalue) const {fixed temp = *this;temp >>= rvalue;return(temp);}\n\t\tconst fixed operator << (unsigned rvalue) const {fixed temp = *this;temp <<= rvalue;return(temp);}\n\n\t\t/*\n\t\t**\tThe full set of comparison operators.\n\t\t*/\n\t\tbool operator == (fixed const & rvalue) const {return(Data.Raw == rvalue.Data.Raw);}\n\t\tbool operator != (fixed const & rvalue) const {return(Data.Raw != rvalue.Data.Raw);}\n\t\tbool operator < (fixed const & rvalue) const {return(Data.Raw < rvalue.Data.Raw);}\n\t\tbool operator > (fixed const & rvalue) const {return(Data.Raw > rvalue.Data.Raw);}\n\t\tbool operator <= (fixed const & rvalue) const {return(Data.Raw <= rvalue.Data.Raw);}\n\t\tbool operator >= (fixed const & rvalue) const {return(Data.Raw >= rvalue.Data.Raw);}\n\t\tbool operator ! (void) const {return(Data.Raw == 0);}\n\n\t\t/*\n\t\t**\tComparison to integers requires consideration of fractional component.\n\t\t*/\n\t\tbool operator < (int rvalue) const {return(Data.Raw < (rvalue*256));}\n\t\tbool operator > (int rvalue) const {return(Data.Raw > (rvalue*256));}\n\t\tbool operator <= (int rvalue) const {return(Data.Raw <= (rvalue*256));}\n\t\tbool operator >= (int rvalue) const {return(Data.Raw >= (rvalue*256));}\n\t\tbool operator == (int rvalue) const {return(Data.Raw == (rvalue*256));}\n\t\tbool operator != (int rvalue) const {return(Data.Raw != (rvalue*256));}\n\n\t\t/*\n\t\t**\tFriend functions to handle the alternate positioning of fixed and integer parameters.\n\t\t*/\n\t\tfriend const int operator * (int lvalue, fixed const & rvalue) {return(rvalue * lvalue);}\n\t\tfriend const int operator / (int lvalue, fixed const & rvalue) {if (rvalue.Data.Raw == 0 || rvalue.Data.Raw == 256) return (lvalue); return(((unsigned)(lvalue * 256)+(256/2)) / rvalue.Data.Raw);}\n\t\tfriend const int operator + (int lvalue, fixed const & rvalue) {return(rvalue + lvalue);}\n\t\tfriend const int operator - (int lvalue, fixed const & rvalue) {return((((lvalue*256) - rvalue.Data.Raw) + (256/2)) / 256);}\n\t\tfriend bool operator < (unsigned lvalue, fixed const & rvalue) {return((lvalue*256) < rvalue.Data.Raw);}\n\t\tfriend bool operator > (unsigned lvalue, fixed const & rvalue) {return((lvalue*256) > rvalue.Data.Raw);}\n\t\tfriend bool operator <= (unsigned lvalue, fixed const & rvalue) {return((lvalue*256) <= rvalue.Data.Raw);}\n\t\tfriend bool operator >= (unsigned lvalue, fixed const & rvalue) {return((lvalue*256) >= rvalue.Data.Raw);}\n\t\tfriend bool operator == (unsigned lvalue, fixed const & rvalue) {return((lvalue*256) == rvalue.Data.Raw);}\n\t\tfriend bool operator != (unsigned lvalue, fixed const & rvalue) {return((lvalue*256) != rvalue.Data.Raw);}\n\t\tfriend int operator *= (int & lvalue, fixed const & rvalue) {lvalue = lvalue * rvalue;return(lvalue);}\n\t\tfriend int operator /= (int & lvalue, fixed const & rvalue) {lvalue = lvalue / rvalue;return(lvalue);}\n\t\tfriend int operator += (int & lvalue, fixed const & rvalue) {lvalue = lvalue + rvalue;return(lvalue);}\n\t\tfriend int operator -= (int & lvalue, fixed const & rvalue) {lvalue = lvalue - rvalue;return(lvalue);}\n\n\t\t/*\n\t\t**\tHelper functions to handle simple and common operations on fixed point numbers.\n\t\t*/\n\t\tvoid Round_Up(void) {Data.Raw += (unsigned short)(256-1);Data.Composite.Fraction = 0;}\n\t\tvoid Round_Down(void) {Data.Composite.Fraction = 0;}\n\t\tvoid Round(void) {if (Data.Composite.Fraction >= 256/2) Round_Up();Round_Down();}\n\t\tvoid Saturate(unsigned capvalue) {if (Data.Raw > (capvalue*256)) Data.Raw = (unsigned short)(capvalue*256);}\n\t\tvoid Saturate(fixed const & capvalue) {if (*this > capvalue) *this = capvalue;}\n\t\tvoid Sub_Saturate(unsigned capvalue) {if (Data.Raw >= (capvalue*256)) Data.Raw = (unsigned short)((capvalue*256)-1);}\n\t\tvoid Sub_Saturate(fixed const & capvalue) {if (*this >= capvalue) Data.Raw = (unsigned short)(capvalue.Data.Raw-1);}\n\t\tvoid Inverse(void) {*this = fixed(1) / *this;}\n\n\t\t/*\n\t\t**\tFriend helper functions that work in the typical C fashion of passing the object to\n\t\t**\tbe processed as a parameter to the function.\n\t\t*/\n\t\tfriend const fixed Round_Up(fixed const & value) {fixed temp = value; temp.Round_Up();return(temp);}\n\t\tfriend const fixed Round_Down(fixed const & value) {fixed temp = value; temp.Round_Down();return(temp);}\n\t\tfriend const fixed Round(fixed const & value) {fixed temp = value; temp.Round();return(temp);}\n\t\tfriend const fixed Saturate(fixed const & value, unsigned capvalue) {fixed temp = value;temp.Saturate(capvalue);return(temp);}\n\t\tfriend const fixed Saturate(fixed const & value, fixed const & capvalue) {fixed temp = value;temp.Saturate(capvalue);return(temp);}\n\t\tfriend const fixed Sub_Saturate(fixed const & value, unsigned capvalue) {fixed temp = value;temp.Sub_Saturate(capvalue);return(temp);}\n\t\tfriend const fixed Sub_Saturate(fixed const & value, fixed const & capvalue) {fixed temp = value;temp.Sub_Saturate(capvalue);return(temp);}\n\t\tfriend const fixed Inverse(fixed const & value) {fixed temp = value;temp.Inverse();return(temp);}\n\n\t\t/*\n\t\t**\tConversion of the fixed point number into an ASCII string.\n\t\t*/\n\t\tint To_ASCII(char * buffer, int maxlen=-1) const;\n\t\tchar const * As_ASCII(void) const;\n\n\t\t/*\n\t\t**\tHelper constants that provide some convenient fixed point values.\n\t\t*/\n\t\tstatic const fixed _1_2;\n\t\tstatic const fixed _1_3;\n\t\tstatic const fixed _1_4;\n\t\tstatic const fixed _3_4;\n\t\tstatic const fixed _2_3;\n\n\tprivate:\n\t\tunion {\n\t\t\tstruct {\n#ifdef BIG_ENDIAN\n\t\t\t\tunsigned char Whole;\n\t\t\t\tunsigned char Fraction;\n#else\n\t\t\t\tunsigned char Fraction;\n\t\t\t\tunsigned char Whole;\n#endif\n\t\t\t} Composite;\n\t\t\tunsigned short Raw;\n\t\t} Data;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/FLASHER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FLASHER.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FLASHER.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 28, 1994                                                 *\n *                                                                                             *\n *                  Last Update : October 17, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   FlasherClass::Debug_Dump -- Displays current status to the monochrome screen.             *\n *   FlasherClass::Process -- Performs the logic processing for the flashing ability.          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * FlasherClass::Debug_Dump -- Displays current status to the monochrome screen.               *\n *                                                                                             *\n *    This utility function will output the current status of the FlasherClass to the mono     *\n *    screen. It is through this display that bugs may be fixed or detected.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FlasherClass::Debug_Dump(MonoClass * mono) const\n{\n\tmono->Set_Cursor(50, 7);\n\tmono->Printf(\"%2d\", FlashCount);\n}\n#endif\n\n\n/***********************************************************************************************\n * FlasherClass::Process -- Performs the logic processing for the flashing ability.            *\n *                                                                                             *\n *    The ability for an object to flash is controlled by this logic processing routine. It    *\n *    should be called once per game tick per unit.                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Should the associated object be redrawn?                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *   06/20/1994 JLB : Is now independent of object it represents.                              *\n *=============================================================================================*/\nbool FlasherClass::Process(void)\n{\n\tif (FlashCount) {\n\t\tFlashCount--;\n\t\tIsBlushing = false;\n\n\t\tif (FlashCount & 0x01) {\n\t\t\tIsBlushing = true;\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n"
  },
  {
    "path": "CODE/FLASHER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FLASHER.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FLASHER.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 28, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 28, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FLASHER_H\n#define FLASHER_H\n\nclass FlasherClass {\n\tpublic:\n\t\t/*\n\t\t**\tWhen this object is targeted, it will flash a number of times. This is the\n\t\t**\tflash control number. It counts down to zero and then stops. Odd values\n\t\t**\tcause the object to be rendered in a lighter color.\n\t\t*/\n\t\tunsigned FlashCount:7;\n\n\t\t/*\n\t\t**\tWhen an object is targeted, it flashes several times to give visual feedback\n\t\t**\tto the player. Every other game \"frame\", this flag is true until the flashing\n\t\t**\tis determined to be completed.\n\t\t*/\n\t\tunsigned IsBlushing:1;\n\n\t\tFlasherClass(void) {FlashCount = 0; IsBlushing = false;};\n\t\tFlasherClass(NoInitClass const & ) {};\n\t\t~FlasherClass(void) {};\n\n\t\t#ifdef CHEAT_KEYS\n\t\tvoid Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\t\tbool Process(void);\n};\n\n#endif\n"
  },
  {
    "path": "CODE/FLY.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FLY.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FLY.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 24, 1994                                               *\n *                                                                                             *\n *                  Last Update : June 5, 1995 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   FlyClass::Fly_Speed -- Sets the flying object to the speed specified.                     *\n *   FlyClass::Physics -- Performs vector physics (movement).                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * FlyClass::Physics -- Performs vector physics (movement).                                    *\n *                                                                                             *\n *    This routine performs movement (vector) physics. It takes the                            *\n *    specified location and moves it according to the facing and speed                        *\n *    of the vector. It returns the status of the move.                                        *\n *                                                                                             *\n * INPUT:   coord -- Reference to the coordinate that the vector will                          *\n *                   be applied to.                                                            *\n *                                                                                             *\n * OUTPUT:  Returns with the status of the vector physics. This could                          *\n *          range from no effect, to exiting the edge of the world.                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/24/1994 JLB : Created.                                                                 *\n *   06/05/1995 JLB : Simplified to just do movement.                                          *\n *=============================================================================================*/\nImpactType FlyClass::Physics(COORDINATE & coord, DirType facing)\n{\n\tif (SpeedAdd != MPH_IMMOBILE) {\n\t\tint actual = (int)SpeedAdd + SpeedAccum;\n\t\tdiv_t result = div(actual, PIXEL_LEPTON_W);\n\t\tSpeedAccum = result.rem;\n\t\tactual -= result.rem;\n\t\tCOORDINATE old = coord;\n\n\t\t/*\n\t\t**\tIf movement occurred that is at least one\n\t\t**\tpixel, then check update the coordinate and\n\t\t**\tcheck for edge of world collision.\n\t\t*/\n\t\tif (result.quot) {\n\t\t\tCOORDINATE\t\tnewcoord;\t\t// New working coordinate.\n\t\t\tnewcoord = Coord_Move(coord, facing, actual);\n\t\t\t/*\n\t\t\t**\tIf no movement occurred, then presume it hasn't moved at all\n\t\t\t**\tand return immediately with this indication.\n\t\t\t*/\n\t\t\tif (newcoord == coord) {\n\t\t\t\treturn(IMPACT_NONE);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRemember the new position.\n\t\t\t*/\n\t\t\tcoord = newcoord;\n\n\t\t\t/*\n\t\t\t**\tIf the new coordinate is off the edge of the world, then report\n\t\t\t**\tthis.\n\t\t\t*/\n\t\t\tif (newcoord & HIGH_COORD_MASK /*|| !Map.In_Radar(Coord_Cell(newcoord))*/) {\n//\t\t\tif (!Map.In_Radar(Coord_Cell(newcoord))) {\n\t\t\t\tcoord = old;\n\t\t\t\treturn(IMPACT_EDGE);\n\t\t\t}\n\n\t\t\treturn(IMPACT_NORMAL);\n\t\t}\n\t}\n\treturn(IMPACT_NONE);\n}\n\n\n/***********************************************************************************************\n * FlyClass::Fly_Speed -- Sets the flying object to the speed specified.                       *\n *                                                                                             *\n *    This sets the speed of the projectile. It basically functions like a throttle value      *\n *    where 0 equals stop and 255 equals maximum speed (whatever that is for the particular    *\n *    object).                                                                                 *\n *                                                                                             *\n * INPUT:   speed -- Speed setting from 0 to 255.                                              *\n *                                                                                             *\n *          maximum  -- The maximum speed of the object.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *   07/26/1994 JLB : Added maximum speed as guiding value.                                    *\n *=============================================================================================*/\nvoid FlyClass::Fly_Speed(int speed, MPHType maximum)\n{\n\tSpeedAdd = (MPHType)( maximum * fixed(speed, 256));\n//\tSpeedAdd = (MPHType)Fixed_To_Cardinal((int)maximum, speed);\n}\n\n\n"
  },
  {
    "path": "CODE/FLY.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FLY.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FLY.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 24, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 24, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FLY_H\n#define FLY_H\n\ntypedef enum ImpactType {\n\tIMPACT_NONE,\t\t// No movement (of significance) occurred.\n\tIMPACT_NORMAL,\t\t// Some (non eventful) movement occurred.\n\tIMPACT_EDGE\t\t\t// The edge of the world was reached.\n} ImpactType;\n\n\n/****************************************************************************\n**\tFlying objects are handled by this class definition.\n*/\nclass FlyClass {\n\tpublic:\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tFlyClass(void) : SpeedAccum(0), SpeedAdd(MPH_IMMOBILE) {};\n\t\tFlyClass(NoInitClass const &) {};\n\t\t~FlyClass(void) {};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tvoid Fly_Speed(int speed, MPHType maximum);\n\t\tImpactType Physics(COORDINATE &coord, DirType facing);\n\t\tMPHType Get_Speed(void) const {return(SpeedAdd);};\n\n\tprivate:\n\t\t/*\n\t\t**\tObject movement consists of incrementing the accumulator until enough \"distance\"\n\t\t**\thas accumulated so that moving the object becomes reasonable.\n\t\t*/\n\t\tunsigned SpeedAccum;\t\t\t// Lepton accumulator.\n\t\tMPHType SpeedAdd;\t\t\t// Lepton add (per frame).\n};\n\n#endif\n"
  },
  {
    "path": "CODE/FOOT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FOOT.CPP 2     3/06/97 1:46p Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FOOT.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 22, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 5, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   FootClass::AI -- Handle general movement AI.                                              *\n *   FootClass::Active_Click_With -- Initiates attack or move according to target clicked on.  *\n *   FootClass::Active_Click_With -- Performs action as a result of left mouse click.          *\n *   FootClass::Adjust_Dest -- Adjust candidate movement cell to account for formation.        *\n *   FootClass::Approach_Target -- Sets the navigation computer to approach target object.     *\n *   FootClass::Assign_Destination -- Assigns specified destination to NavCom.                 *\n *   FootClass::Basic_Path -- Finds the basic path for a ground object.                        *\n *   FootClass::Body_Facing -- Set the body rotation/facing.                                   *\n *   FootClass::Can_Demolish -- Checks to see if this object can be sold back.                 *\n *   FootClass::Can_Enter_Cell -- Checks to see if the object can enter cell specified.        *\n *   FootClass::Clear_Navigation_List -- Clears out the navigation queue.                      *\n *   FootClass::Death_Announcement -- Announces the death of a unit.                           *\n *   FootClass::Debug_Dump -- Displays the status of the FootClass to the mono monitor.        *\n *   FootClass::Detach -- Detaches a target from tracking systems.                             *\n *   FootClass::Detach_All -- Removes this object from the game system.                        *\n *   FootClass::Enters_Building -- When unit enters a building for some reason.                *\n *   FootClass::FootClass -- Normal constructor for the foot class object.                     *\n *   FootClass::Greatest_Threat -- Fetches the greatest threat to this object.                 *\n *   FootClass::Handle_Navigation_List -- Processes the navigation queue.                      *\n *   FootClass::Is_Allowed_To_Leave_Map -- Checks to see if it can leave the map and the game. *\n *   FootClass::Is_On_Priority_Mission -- Checks to see if this object should be given priority*\n *   FootClass::Is_Recruitable -- Determine if this object is recruitable as a team members.   *\n *   FootClass::Likely_Coord -- Fetches the coordinate the object will be at shortly.          *\n *   FootClass::Mark -- Unit interface to map rendering system.                                *\n *   FootClass::Mission_Attack -- AI for heading towards and firing upon target.               *\n *   FootClass::Mission_Capture -- Handles the capture mission.                                *\n *   FootClass::Mission_Enter -- Enter (cooperatively) mission handler.                        *\n *   FootClass::Mission_Guard_Area -- Causes unit to guard an area about twice weapon range.   *\n *   FootClass::Mission_Hunt -- Handles the default hunt order.                                *\n *   FootClass::Mission_Move -- AI process for moving a vehicle to its destination.            *\n *   FootClass::Mission_Retreat -- Handle reatreat from map mission for mobile objects.        *\n *   FootClass::Offload_Tiberium_Bail -- Fetches the Tiberium to offload per step.             *\n *   FootClass::Override_Mission -- temporarily overrides a units mission                      *\n *   FootClass::Per_Cell_Process -- Perform action based on once-per-cell condition.           *\n *   FootClass::Queue_Navigation_List -- Add a target to the objects navigation list.          *\n *   FootClass::Receive_Message -- Movement related radio messages are handled here.           *\n *   FootClass::Rescue_Mission -- Calls this unit to the rescue.                               *\n *   FootClass::Restore_Mission -- Restores an overridden mission                              *\n *   FootClass::Sell_Back -- Causes this object to be sold back.                               *\n *   FootClass::Set_Speed -- Initiate unit movement physics.                                   *\n *   FootClass::Sort_Y -- Determine the sort coordinate for foot class objects.                *\n *   FootClass::Start_Driver -- This starts the driver heading to the destination desired.     *\n *   FootClass::Stop_Driver -- This routine clears the driving state of the object.            *\n *   FootClass::Stun -- Prepares a ground travelling object for removal.                       *\n *   FootClass::Take_Damage -- Handles taking damage to this object.                           *\n *   FootClass::Unlimbo -- Unlimbos object and performs special fixups.                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * FootClass::FootClass -- Default constructor for foot class objects.                         *\n *                                                                                             *\n *    This is the default constructor for FootClass objects. It sets the foot class values to  *\n *    their default starting settings.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nFootClass::FootClass(RTTIType rtti, int id, HousesType house) :\n\tTechnoClass(rtti, id, house),\n\tIsScanLimited(false),\n\tIsInitiated(false),\n\tIsNewNavCom(false),\n\tIsPlanningToLook(false),\n\tIsDeploying(false),\n\tIsFiring(false),\n\tIsRotating(false),\n\tIsDriving(false),\n\tIsUnloading(false),\n\tIsFormationMove(false),\n\tIsNavQueueLoop(false),\n\tIsScattering(false),\n\tSpeed(0),\n\tSpeedBias(1),\n\tXFormOffset(0x80000000),\n\tYFormOffset(0x80000000),\n\tNavCom(TARGET_NONE),\n\tSuspendedNavCom(TARGET_NONE),\n\tTeam(0),\n\tGroup(255),\n\tMember(0),\n\tPathThreshhold(MOVE_CLOAK),\n\tPathDelay(0),\n\tTryTryAgain(PATH_RETRY),\n\tBaseAttackTimer(0),\n\tFormationSpeed(SPEED_FOOT),\n\tFormationMaxSpeed(MPH_IMMOBILE),\n\tHeadToCoord(0)\n{\n\tPath[0] = FACING_NONE;\n\tfor (int index = 0; index < ARRAY_SIZE(NavQueue); index++) {\n\t\tNavQueue[index] = TARGET_NONE;\n\t}\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * FootClass::Debug_Dump -- Displays the status of the FootClass to the mono monitor.          *\n *                                                                                             *\n *    This routine is used to output the current status of the foot class to the mono          *\n *    monitor. Through this display bugs may be tracked down or eliminated.                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *   07/04/1995 JLB : Handles aircraft special case.                                           *\n *=============================================================================================*/\nvoid FootClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(IsActive);\n\n\tmono->Fill_Attrib(53, 13, 12, 1, IsInitiated ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 18, 12, 1, IsPlanningToLook ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(53, 14, 12, 1, IsDeploying ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(53, 15, 12, 1, IsFiring ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(53, 16, 12, 1, IsRotating ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(53, 17, 12, 1, IsDriving ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(53, 18, 12, 1, IsUnloading ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(27, 18, 12, 1, IsFormationMove ? MonoClass::INVERSE : MonoClass::NORMAL);\n\n\tmono->Set_Cursor(45, 1);mono->Printf(\"%02X\", Speed);\n\tif (NavCom) {\n\t\tmono->Set_Cursor(29, 5);\n\t\tmono->Printf(\"%08X\", NavCom);\n\t}\n\tif (SuspendedNavCom) {\n\t\tmono->Set_Cursor(38, 5);\n\t\tmono->Printf(\"%08X\", SuspendedNavCom);\n\t}\n\n\tif (Team) Team->Debug_Dump(mono);\n\tif (Group != 255) {\n\t\tmono->Set_Cursor(59, 1);mono->Printf(\"%d\", Group);\n\t}\n\n\tstatic char\tconst * _p2c[9] = {\"-\",\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\"};\n\tfor (int index = 0; index < min(12, ARRAY_SIZE(Path)); index++) {\n\t\tmono->Set_Cursor(54+index, 3);\n\t\tmono->Printf(\"%s\", _p2c[((ABS((int)Path[index]+1)) % ARRAY_SIZE(_p2c))]);\n\t}\n\tmono->Set_Cursor(54, 5);mono->Printf(\"%2d\", PathThreshhold);\n\tmono->Set_Cursor(72, 3);mono->Printf(\"%4d\", (long)PathDelay);\n\tmono->Set_Cursor(67, 3);mono->Printf(\"%3d\", TryTryAgain);\n\tif (HeadToCoord) {\n\t\tmono->Set_Cursor(60, 5);mono->Printf(\"%08X\", HeadToCoord);\n\t}\n\n\tTechnoClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * FootClass::Set_Speed -- Initiate unit movement physics.                                     *\n *                                                                                             *\n *    This routine is used to set a unit's velocity control structure.                         *\n *    The game will then process the unit's movement during the momentum                       *\n *    physics calculation.                                                                     *\n *                                                                                             *\n * INPUT:   unit  -- Pointer to the unit to alter.                                             *\n *                                                                                             *\n *          speed -- Throttle setting (0=stop, 255=full throttle).                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/07/1992 JLB : Created.                                                                 *\n *   09/24/1993 JLB : Revised for faster speed.                                                *\n *   04/02/1994 JLB : Revised for new system.                                                  *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *   07/21/1994 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid FootClass::Set_Speed(int speed)\n{\n\tassert(IsActive);\n\n\tspeed &= 0xFF;\n\t((unsigned char &)Speed) = speed;\n}\n\n\n/***********************************************************************************************\n * FootClass::Mark -- Unit interface to map rendering system.                                  *\n *                                                                                             *\n *    This routine is the interface function for units as they relate to                       *\n *    the map rendering system. Whenever a unit's imagery changes, this                        *\n *    function is called.                                                                      *\n *                                                                                             *\n * INPUT:   mark  -- Type of image change (MARK_UP, _DOWN, _CHANGE)                            *\n *             MARK_UP  -- Unit is removed.                                                    *\n *             MARK_CHANGE -- Unit alters image but doesn't move.                              *\n *             MARK_DOWN -- Unit is overlaid onto existing icons.                              *\n *                                                                                             *\n * OUTPUT:  bool; Did the marking operation succeed? Failure could be the result of marking    *\n *                down when it is already down, or visa versa.                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/14/1991 JLB : Created.                                                                 *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *   12/23/1994 JLB : Performs low level check before processing.                              *\n *=============================================================================================*/\nbool FootClass::Mark(MarkType mark)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tif (TechnoClass::Mark(mark)) {\n//\t\tshort list[32];\n\t\tCELL cell = Coord_Cell(Coord);\n\n#ifndef PARTIAL\n\t\tif (In_Which_Layer() != LAYER_GROUND && (mark == MARK_UP || mark == MARK_DOWN)) mark = MARK_CHANGE;\n#endif\n\n\t\t/*\n\t\t**\tInform the map of the refresh, occupation, and overlap\n\t\t**\trequest.\n\t\t*/\n\t\tswitch (mark) {\n\t\t\tcase MARK_UP:\n\t\t\t\tMap.Pick_Up(cell, this);\n\t\t\t\tbreak;\n\n\t\t\tcase MARK_DOWN:\n\t\t\t\tMap.Place_Down(cell, this);\n\t\t\t\tbreak;\n\n\t\t\tcase MARK_CHANGE_REDRAW:\n\t\t\t\tMap.Refresh_Cells(cell, Overlap_List(true));\n\t\t\t\tMap.Refresh_Cells(cell, Occupy_List());\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tMap.Refresh_Cells(cell, Overlap_List());\n\t\t\t\tMap.Refresh_Cells(cell, Occupy_List());\n\t\t\t\tbreak;\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FootClass::Basic_Path -- Finds the basic path for a ground object.                          *\n *                                                                                             *\n *    This is a common routine used by both infantry and other ground travelling units. It     *\n *    will fill in the unit's basic path to the NavCom destination.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was a path found? A failure to find a path means either the target cannot    *\n *                be found or the terrain prohibits the unit's movement.                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FootClass::Basic_Path(void)\n{\n\tassert(IsActive);\n\n\tPathType\t\t* path;\t\t\t// Pointer to path control structure.\n\tCELL\t\t\tcell;\n\tint \t\t\tskip_path = false;\n\n\tPath[0] = FACING_NONE;\n\n\tif (Target_Legal(NavCom)) {\n\t\tcell = As_Cell(NavCom);\n\n\t\t/*\n\t\t**\tWhen the navigation computer is set to a location that is impassible, then\n\t\t**\tfind a nearby cell that can be entered and try to head toward that instead.\n\t\t**\tEXCEPT when that cell is very close -- then just bail.\n\t\t*/\n\t\tint dist = Distance(NavCom);\n\t\tint checkdist = Team.Is_Valid() ? Rule.StrayDistance : Rule.CloseEnoughDistance;\n\t\tif (Can_Enter_Cell(cell) > MOVE_CLOAK && dist > checkdist) {\n\t\t\tCELL cell2 = Map.Nearby_Location(cell, Techno_Type_Class()->Speed, Map[Coord].Zones[Techno_Type_Class()->MZone], Techno_Type_Class()->MZone);\n\t\t\tif (cell2 != 0 && ::Distance(Cell_Coord(cell), Cell_Coord(cell2)) < dist) cell = cell2;\n\t\t}\n\n\t\tif (What_Am_I() == RTTI_INFANTRY) {\n\t\t\tCELL mycell = Coord_Cell(Center_Coord());\n\t\t\tObjectClass * obj = Map[mycell].Cell_Occupier();\n\t\t\twhile (obj) {\n\t\t\t\tif (obj != this && obj->What_Am_I() == RTTI_INFANTRY) {\n\t\t\t\t\tInfantryClass * inf = (InfantryClass *)obj;\n\t\t\t\t\tif (inf->NavCom == NavCom && inf->Path[0] != FACING_NONE) {\n\t\t\t\t\t\tif (Coord_Cell(inf->Head_To_Coord()) == Coord_Cell(inf->Coord)) {\n\t\t\t\t\t\t\tMem_Copy(&inf->Path[1], Path, sizeof(Path)-sizeof(Path[0]));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tMem_Copy(inf->Path, Path, sizeof(Path));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Path[0] != FACING_NONE) {\n\t\t\t\t\t\t\tskip_path = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tobj = obj->Next;\n\t\t\t}\n\t\t}\n\n\t\tif (!skip_path) {\n\t\t\tMark(MARK_UP);\n\t\t\tPath[0] = FACING_NONE;\t\t// Probably not necessary, but...\n\n\t\t\t/*\n\t\t\t**\tTry to find a path to the destination. If a failure occurs, then keep trying\n\t\t\t**\twith greater determination until either a complete failure occurs, or a decent\n\t\t\t**\tpath was found.\n\t\t\t*/\n\t\t\tbool\t\t\tfound1=false;\t\t// Found a best path yet?\n\t\t\tPathType\t   path1;\n\t\t\tFacingType\tworkpath1[200];\t// Staging area for path list.\n//\t\t\tFacingType\tworkpath2[200];\t// Staging area for path list.\n\t\t\tMoveType\t\tmaxtype = MOVE_TEMP;\n\t\t\tif (!House->IsHuman) {\n\t\t\t\tmaxtype = MOVE_TEMP;\n//\t\t\t\tmaxtype = MOVE_DESTROYABLE;\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tFor simple movement missions by the human player, then don't\n\t\t\t\t**\tconsider friendly units as passable if close to the destination.\n\t\t\t\t**\tThis will prevent a human controlled unit from just sitting next\n\t\t\t\t**\tto a destination just because there is another friendly unit\n\t\t\t\t**\toccupying the destination location.\n\t\t\t\t*/\n\t\t\t\tif (Mission == MISSION_MOVE && Distance(NavCom) < Rule.CloseEnoughDistance) {\n\t\t\t\t\tmaxtype = MOVE_DESTROYABLE;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tTry to find a path to the destination. If there is a path\n\t\t\t**\tfailure, then try a more severe path method until the\n\t\t\t**\tmaximum severity is reached.\n\t\t\t*/\n\t\t\tfor (;;) {\n\t\t\t\tpath = Find_Path(cell, &workpath1[0], sizeof(workpath1), PathThreshhold);\n\t\t\t\tif (path && path->Cost) {\n\t\t\t\t\tmemcpy(&path1, path, sizeof(path1));\n\t\t\t\t\tfound1 = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tA valid path was not found. Try the next greater path severity\n\t\t\t\t**\tlevel if the severity can be increased. If not, then consider this\n\t\t\t\t**\ta total failure.\n\t\t\t\t*/\n\t\t\t\tPathThreshhold++;\n\t\t\t\tif (PathThreshhold > maxtype) break;\n\t\t\t}\n\n#ifdef NEVER\n\t\t\t/*\n\t\t\t**\tDetermine if ANY path could be calculated by first examining the most\n\t\t\t**\taggressive case. If this fails, then no path will succeed. Further\n\t\t\t**\tscanning is unnecessary.\n\t\t\t*/\n\t\t\tpath = Find_Path(cell, &workpath1[0], sizeof(workpath1), maxtype);\n\t\t\tif (path && path->Cost) {\n\t\t\t\tmemcpy(&path1, path, sizeof(path1));\n\t\t\t\tfound1 = true;\n\n\t\t\t\t/*\n\t\t\t\t**\tScan for the best path possible. If this succeeds, then do a simple\n\t\t\t\t**\tcomparison with the most aggressive path. If they are very close, then\n\t\t\t\t**\tgo with the best (easiest) path method.\n\t\t\t\t*/\n\t\t\t\tpath = Find_Path(cell, &workpath2[0], sizeof(workpath2), MOVE_CLOAK);\n\t\t\t\tif (path && path->Cost && path->Cost < max((path1.Cost + (path1.Cost/2)), 3)) {\n\t\t\t\t\tmemcpy(&path1, path, sizeof(path1));\n\t\t\t\t\tmemcpy(workpath1, workpath2, sizeof(workpath1));\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThe easiest path method didn't result in a satisfactory path. Scan through\n\t\t\t\t\t**\tthe rest of the path options, looking for the best one.\n\t\t\t\t\t*/\n\t\t\t\t\tfor (MoveType move = (MoveType)(MOVE_CLOAK+1); move < (MoveType)(maxtype-1); move++) {\n//\t\t\t\t\tfor (MoveType move = MOVE_MOVING_BLOCK; move < maxtype-1; move++) {\n\t\t\t\t\t\tpath = Find_Path(cell, &workpath2[0], sizeof(workpath2), move);\n\t\t\t\t\t\tif (path && path->Cost && path->Cost < max((path1.Cost + (path1.Cost/2)), 3)) {\n\t\t\t\t\t\t\tmemcpy(&path1, path, sizeof(path1));\n\t\t\t\t\t\t\tmemcpy(workpath1, workpath2, sizeof(workpath1));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n#endif\n\n\t\t\t/*\n\t\t\t**\tIf a good path was found, then record it in the object's path\n\t\t\t**\tlist.\n\t\t\t*/\n\t\t\tif (found1) {\n\t\t\t\tFixup_Path(&path1);\n\t\t\t\tmemcpy(&Path[0], &workpath1[0], min(path->Length, (int)sizeof(Path)));\n\t\t\t}\n\n\t\t\tMark(MARK_DOWN);\n\t\t}\n\n\t\tPathDelay = Rule.PathDelay * TICKS_PER_MINUTE;\n\t\tif (Path[0] != FACING_NONE) return(true);\n\n\t\t/*\n\t\t**\tIf a basic path couldn't be determined, then abort the navigation process.\n\t\t*/\n\t\tStop_Driver();\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FootClass::Mission_Move -- AI process for moving a vehicle to its destination.              *\n *                                                                                             *\n *    This simple AI script handles moving the vehicle to its desired destination. Since       *\n *    simple movement is handled directly by the engine, this routine merely waits until       *\n *    the unit has reached its destination, and then causes the unit to enter idle mode.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before calling this routine again.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *   10/02/1996 JLB : Player controlled or human owned units don't scan for targets.           *\n *=============================================================================================*/\nint FootClass::Mission_Move(void)\n{\n\tassert(IsActive);\n\n\tif (!Target_Legal(NavCom) && !IsDriving && MissionQueue == MISSION_NONE) {\n\t\tEnter_Idle_Mode();\n\t\treturn(1);\n\t}\n//\tif (!Target_Legal(TarCom) && !House->IsPlayerControl && !House->IsHuman) {\n\tif (!Target_Legal(TarCom) && !House->IsPlayerControl && !House->IsHuman && (!Team.Is_Valid() || !Team->Class->IsSuicide)) {\n\t\tTarget_Something_Nearby(THREAT_RANGE);\n\t}\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * FootClass::Mission_Capture -- Handles the capture mission.                                  *\n *                                                                                             *\n *    Capture missions are nearly the same as normal movement missions. The only difference    *\n *    is that the final destination is handled in a special way so that it is not marked as    *\n *    impassable. This allows the object (usually infantry) the ability to walk onto the       *\n *    object and thus capture it.                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game ticks to delay before calling this routine.        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FootClass::Mission_Capture(void)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tIf there is a valid TarCom but the NavCom isn't set, then set the NavCom accordingly.\n\t*/\n\tif (Is_Target_Building(TarCom) && !Target_Legal(NavCom) && What_Am_I() == RTTI_INFANTRY && ((InfantryClass *)this)->Class->IsBomber) {\n\t\tAssign_Destination(TarCom);\n\t}\n\n\tif (!Target_Legal(NavCom) /*&& !In_Radio_Contact()*/) {\n\t\tEnter_Idle_Mode();\n\t\tif (Map[Center_Coord()].Cell_Building()) {\n\t\t\tScatter(0, true);\n\t\t}\n\t}\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * FootClass::Mission_Attack -- AI for heading towards and firing upon target.                 *\n *                                                                                             *\n *    This AI routine handles heading to within range of the target and then firing upon       *\n *    it until it is destroyed. If the target is destroyed, then the unit will change          *\n *    missions to match its \"idle mode\" of operation (usually guarding).                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before calling this routine again.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FootClass::Mission_Attack(void)\n{\n\tassert(IsActive);\n\tif (Target_Legal(TarCom)) {\n\t\tApproach_Target();\n\t} else {\n\t\tEnter_Idle_Mode();\n\t}\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * FootClass::Mission_Guard -- Handles the AI for guarding in place.                           *\n *                                                                                             *\n *    Units that are performing stationary guard duty use this AI process. They will sit       *\n *    still and target any enemies that get within range.                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before calling this routine again.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FootClass::Mission_Guard(void)\n{\n\tassert(IsActive);\n\n\tif (!Target_Something_Nearby(THREAT_RANGE)) {\n\t\tRandom_Animate();\n\t}\n\n\tint dtime = MissionControl[Mission].Normal_Delay();\n\tif (What_Am_I() == RTTI_VESSEL) {\n\t\tswitch (((VesselClass *)this)->Class->Type) {\n\t\t\tcase VESSEL_DD:\n\t\t\tcase VESSEL_PT:\n\t\t\t\tdtime = MissionControl[Mission].AA_Delay();\n\t\t\t\tbreak;\n\n\t\t\tcase VESSEL_CA:\n\t\t\t\tdtime *= 2;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tif (What_Am_I() == RTTI_INFANTRY) {\n\n\t\t/*\n\t\t**\tIf this is a bomber type infantry and the current target is a building, then go into\n\t\t**\tsabotage mode if not already.\n\t\t*/\n\t\tif (!House->IsHuman && Is_Target_Building(TarCom) && ((InfantryClass *)this)->Class->IsBomber && Mission != MISSION_SABOTAGE) {\n\t\t\tAssign_Mission(MISSION_SABOTAGE);\n\t\t}\n\n\t\tswitch (((InfantryClass *)this)->Class->Type) {\n\t\t\tcase INFANTRY_E1:\n\t\t\tcase INFANTRY_E3:\n\t\t\t\tdtime = MissionControl[Mission].AA_Delay();\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn((Arm != 0) ? (int)Arm : (dtime+Random_Pick(0, 2)));\n}\n\n\n/***********************************************************************************************\n * FootClass::Mission_Hunt -- Handles the default hunt order.                                  *\n *                                                                                             *\n *    This routine is the default hunt order for game objects. It handles searching for a      *\n *    nearby object and heading toward it. The act of targeting will cause it to attack        *\n *    the target it selects.                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the game tick delay before calling this routine again.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FootClass::Mission_Hunt(void)\n{\n\tassert(IsActive);\n\tif (!Target_Something_Nearby(THREAT_NORMAL)) {\n#if(0)\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (What_Am_I() == RTTI_INFANTRY && *(InfantryClass *)this == INFANTRY_GENERAL && House->Class->House==HOUSE_UKRAINE && Scen.Scenario==47) {\n\t\tfor(int index=0; index < Buildings.Count(); index++) {\n\t\t\tif(Buildings.Ptr(index)->IsOwnedByPlayer) {\n\t\t\t\tAssign_Target(Buildings.Ptr(index)->As_Target());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfor(index=0; index < Units.Count(); index++) {\n\t\t\tif(Units.Ptr(index)->IsOwnedByPlayer) {\n\t\t\t\tAssign_Target(Units.Ptr(index)->As_Target());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfor(index=0; index < Infantry.Count(); index++) {\n\t\t\tif(Infantry.Ptr(index)->IsOwnedByPlayer) {\n\t\t\t\tAssign_Target(Infantry.Ptr(index)->As_Target());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfor(index=0; index < Aircraft.Count(); index++) {\n\t\t\tif(Aircraft.Ptr(index)->IsOwnedByPlayer) {\n\t\t\t\tAssign_Target(Aircraft.Ptr(index)->As_Target());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n#endif\n#endif\n\t\tRandom_Animate();\n\t} else {\n\t\tif (What_Am_I() == RTTI_INFANTRY && ( ((InfantryTypeClass const &)Class_Of()).Type == INFANTRY_RENOVATOR || ((InfantryTypeClass const &)Class_Of()).Type == INFANTRY_THIEF) ) {\n\t\t\tAssign_Destination(TarCom);\n\t\t\tAssign_Mission(MISSION_CAPTURE);\n\t\t} else {\n\t\t\tif (What_Am_I() == RTTI_INFANTRY && ((InfantryClass *)this)->Class->IsBomber && Is_Target_Building(TarCom)) {\n\t\t\t\tAssign_Destination(TarCom);\n\t\t\t\tAssign_Mission(MISSION_SABOTAGE);\n\t\t\t} else {\n\t\t\t\tApproach_Target();\n\t\t\t}\n\t\t}\n\t}\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * FootClass::Stop_Driver -- This routine clears the driving state of the object.              *\n *                                                                                             *\n *    This is the counterpart routine to the Start_Driver function. It clears the driving      *\n *    status flags and destination coordinate record.                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was driving stopped?                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *   12/12/1994 JLB : Greatly simplified.                                                      *\n *=============================================================================================*/\nbool FootClass::Stop_Driver(void)\n{\n\tassert(IsActive);\n\n\tif (HeadToCoord) {\n\t\tHeadToCoord = NULL;\n\t\tSet_Speed(0);\n\t\tIsDriving = false;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FootClass::Start_Driver -- This starts the driver heading to the destination desired.       *\n *                                                                                             *\n *    Before a unit can move it must be started by this routine. This routine handles          *\n *    reserving the cell and setting the driving flag.                                         *\n *                                                                                             *\n * INPUT:   headto   -- The coordinate of the immediate drive destination. This is one cell    *\n *                      away from the unit's current location.                                 *\n *                                                                                             *\n * OUTPUT:  bool; Was driving initiated?                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *   12/12/1994 JLB : Uses simple spot index finder.                                           *\n *=============================================================================================*/\nbool FootClass::Start_Driver(COORDINATE &headto)\n{\n\tassert(IsActive);\n\n\tStop_Driver();\n\tif (headto) {\n\t\tHeadToCoord = headto;\n\t\tIsDriving = true;\n\n\t\t/*\n\t\t**\tCheck for crate goodie finder here.\n\t\t*/\n\t\tif (Map[headto].Goodie_Check(this)) {\n\t\t\treturn(true);\n\t\t}\n\t\tif (!IsActive) return(false);\n\n\t\tHeadToCoord = NULL;\n\t\tIsDriving = false;\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FootClass::Sort_Y -- Determine the sort coordinate for foot class objects.                  *\n *                                                                                             *\n *    This routine will determine the sort coordinate for foot class object. This coordinate   *\n *    is usually the coordinate of the object. The exception is if the object is tethered.     *\n *    In this case (presumes offloading to the north), the sorting coordinate is adjusted      *\n *    so that the object will be drawn on top of the transport unit.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate to use for sorting.                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *   11/04/1994 JLB : Sort value is different when unloading from aircraft.                    *\n *=============================================================================================*/\nCOORDINATE FootClass::Sort_Y(void) const\n{\n\tassert(IsActive);\n\n\tif (IsUnloading) {\n\t\treturn(Coord_Add(Coord, 0x01000000L));\n\t}\n\tif (In_Radio_Contact() && IsTethered && Contact_With_Whom()->What_Am_I() == RTTI_UNIT) {\n\t\treturn(Coord_Add(Coord, 0x01000000L));\n\t}\n\treturn(Coord_Add(Coord, 0x00300000L));\n}\n\n\n/***********************************************************************************************\n * FootClass::Stun -- Prepares a ground travelling object for removal.                         *\n *                                                                                             *\n *    This routine clears the units' navigation computer in preparation for removal from the   *\n *    game. This is probably called as a result of unit destruction in combat. Clearing the    *\n *    navigation computer ensures that the normal AI process won't start it moving again while *\n *    the object is undergoing any death animations.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Stun(void)\n{\n\tassert(IsActive);\n\n\tAssign_Destination(TARGET_NONE);\n\tPath[0] = FACING_NONE;\n\tStop_Driver();\n\tTechnoClass::Stun();\n}\n\n\n/***********************************************************************************************\n * FootClass::Approach_Target -- Sets the navigation computer to approach target object.       *\n *                                                                                             *\n *    This routine will set the navigation computer to approach the target indicated by the    *\n *    targeting computer. It is through this function that the unit nears the target so        *\n *    that weapon firing may occur.                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   12/13/1994 JLB : Made part of TechnoClass.                                                *\n *   12/22/1994 JLB : Enhanced search algorithm.                                               *\n *   05/20/1995 JLB : Always approaches if the object is off the map.                          *\n *=============================================================================================*/\nvoid FootClass::Approach_Target(void)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tDetermine that if there is an existing target it is still legal\n\t**\tand within range.\n\t*/\n\tif (Target_Legal(TarCom)) {\n\t\tint primary = What_Weapon_Should_I_Use(TarCom);\n\n\t\t/*\n\t\t**\tIf the target is too far away then head toward it.\n\t\t*/\n\t\tint maxrange = Weapon_Range(primary);\n//\t\tint maxrange = max(Weapon_Range(0), Weapon_Range(1));\n\n\t\tif (!Target_Legal(NavCom) && (!In_Range(TarCom, primary) || !IsLocked)) {\n//\t\tif (!Target_Legal(NavCom) && (Distance(TarCom) > maxrange || !IsLocked)) {\n\n\t\t\t/*\n\t\t\t** If the object that we are attacking is a building adjust the unit's\n\t\t\t** max range so that people can stand far away from the buildings and\n\t\t\t** hit them.\n\t\t\t*/\n\t\t\tBuildingClass * obj = As_Building(TarCom);\n\t\t\tif (obj) {\n\t\t\t\tmaxrange += ((obj->Class->Width() + obj->Class->Height()) * (0x100 / 4));\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Adjust the max range of an infantry unit for where he is standing\n\t\t\t** in the room.\n\t\t\t*/\n\t\t\tmaxrange -= 0x00B7;\n#ifdef OBSOLETE\n\t\t\tif (What_Am_I() == RTTI_INFANTRY) {\n\t\t\t\tmaxrange -= 0x0111;\n\t\t\t} else {\n\t\t\t\tmaxrange -= 0x00B7;\n\t\t\t}\n#endif\n\t\t\tmaxrange = max(maxrange, 0);\n\n\t\t\tCOORDINATE tcoord = ::As_Coord(TarCom);\n\t\t\tCOORDINATE trycoord = 0;\n\t\t\tCELL tcell = Coord_Cell(tcoord);\n\t\t\tCELL trycell = tcell;\n\t\t\tDirType dir = Direction256(tcoord, Center_Coord());\n\t\t\tbool found = false;\n\n\t\t\t/*\n\t\t\t**\tSweep through the cells between the target and the unit, looking for\n\t\t\t**\ta cell that the unit can enter but which is also within weapon range\n\t\t\t**\tof the target. If after a reasonable search, no appropriate cell could\n\t\t\t**\tbe found, then the target will be assigned as the movement destination\n\t\t\t**\tand let \"the chips fall where they may.\"\n\t\t\t*/\n\t\t\tfor (int range = maxrange; range > 0x0080; range -= 0x0100) {\n\t\t\t\tstatic int _angles[] = {0, 8, -8, 16, -16, 24, -24, 32, -32, 48, -48, 64, -64};\n\n\t\t\t\tfor (int index = 0; index < (sizeof(_angles)/sizeof(_angles[0])); index++) {\n\t\t\t\t\ttrycoord = Coord_Move(tcoord, (DirType)(dir + _angles[index]), range);\n\n\t\t\t\t\tif (::Distance(trycoord, tcoord) < range) {\n\t\t\t\t\t\ttrycell = Coord_Cell(trycoord);\n\t\t\t\t\t\tif (Map.In_Radar(trycell) && Map[trycell].Is_Clear_To_Move(Techno_Type_Class()->Speed, false, false, Map[Coord].Zones[Techno_Type_Class()->MZone], Techno_Type_Class()->MZone)) {\n//\t\t\t\t\t\tif (Can_Enter_Cell(trycell) <= MOVE_CLOAK && Map.In_Radar(trycell)) {\n\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (found) break;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf a suitable intermediate location was found, then head toward it.\n\t\t\t**\tOtherwise, head toward the enemy unit directly.\n\t\t\t*/\n\t\t\tif (found) {\n\t\t\t\tAssign_Destination(::As_Target(trycell));\n\t\t\t} else {\n\n\t\t\t\ttrycell = Map.Nearby_Location(trycell, Techno_Type_Class()->Speed, Map[Coord].Zones[Techno_Type_Class()->MZone], Techno_Type_Class()->MZone);\n\t\t\t\tAssign_Destination(::As_Target(trycell));\n//\t\t\t\tAssign_Destination(TarCom);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Mission_Guard_Area -- Causes unit to guard an area about twice weapon range.     *\n *                                                                                             *\n *    This mission routine causes the unit to scan for targets out to twice its weapon range   *\n *    from the home point. If a target was found, then it will be attacked. The unit will      *\n *    chase the target until it gets up to to its weapon range from the home position.         *\n *    In that case, it will return to home position and start scanning for another target.     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with time delay before calling this routine again.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/23/1994 JLB : Created.                                                                 *\n *   07/27/1995 JLB : Greatly simplified.                                                      *\n *=============================================================================================*/\nint FootClass::Mission_Guard_Area(void)\n{\n\tassert(IsActive);\n\n\tif (What_Am_I() == RTTI_UNIT && ((UnitClass *)this)->Class->IsToHarvest) {\n\t\tAssign_Mission(MISSION_HARVEST);\n\t\treturn(1+Random_Pick(1, 10));\n\t}\n\n\t/*\n\t**\tEnsure that the archive target is valid.\n\t*/\n\tif (!Target_Legal(ArchiveTarget)) {\n\t\tArchiveTarget = ::As_Target(Coord);\n\t}\n\n\t/*\n\t**\tIf this is a bomber type infantry and the current target is a building, then go into\n\t**\tsabotage mode if not already.\n\t*/\n\tif (!House->IsHuman && What_Am_I() ==  RTTI_INFANTRY && Is_Target_Building(TarCom) && ((InfantryClass *)this)->Class->IsBomber && Mission != MISSION_SABOTAGE) {\n\t\tAssign_Mission(MISSION_SABOTAGE);\n\t\treturn(1);\n\t}\n\n\t/*\n\t**\tMake sure that the unit has not strayed too far from the home position.\n\t**\tIf it has, then race back to it.\n\t*/\n\tint maxrange = Threat_Range(1)/2;\n\n\tif (!IsFiring && !Target_Legal(NavCom) && Distance(ArchiveTarget) > maxrange) {\n\t\tAssign_Target(TARGET_NONE);\n\t\tAssign_Destination(ArchiveTarget);\n\t}\n\n\tif (!Target_Legal(TarCom)) {\n\t\tCOORDINATE old = Coord;\n\t\tCoord = As_Coord(ArchiveTarget);\n\t\tTarget_Something_Nearby(THREAT_AREA);\n\t\tCoord = old;\n\t\tif (Target_Legal(TarCom)) {\n\t\t\treturn(1);\n\t\t}\n\t\tRandom_Animate();\n\t} else {\n\t\tApproach_Target();\n\t}\n\n\tint dtime = MissionControl[Mission].Normal_Delay();\n\tif (What_Am_I() == RTTI_AIRCRAFT) {\n\t\tdtime *= 2;\n\t}\n\treturn(dtime + Random_Pick(1, 5));\n}\n\n\n/***********************************************************************************************\n * FootClass::Unlimbo -- Unlimbos object and performs special fixups.                          *\n *                                                                                             *\n *    This routine will make sure that the home position for the foot class object gets        *\n *    reset. This is necessary since the home position may change depending on the unit's      *\n *    transition between limbo and non-limbo condition.                                        *\n *                                                                                             *\n * INPUT:   coord    -- The coordinate to unlimbo the unit at.                                 *\n *                                                                                             *\n *          dir      -- The initial direction to give the unit.                                *\n *                                                                                             *\n * OUTPUT:  bool; Was the unit unlimboed successfully?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FootClass::Unlimbo(COORDINATE coord, DirType dir)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tTry to unlimbo the unit.\n\t*/\n\tif (TechnoClass::Unlimbo(coord, dir)) {\n\n\t\t/*\n\t\t**\tMobile units are always revealed to the house that owns them.\n\t\t*/\n\t\tRevealed(House);\n\n\t\t/*\n\t\t**\tStart in a still (non-moving) state.\n\t\t*/\n\t\tPath[0] = FACING_NONE;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FootClass::Take_Damage -- Handles taking damage to this object.                             *\n *                                                                                             *\n *    This routine intercepts the damage assigned to this object and if this object is         *\n *    a member of a team, it informs the team that the damage has occurred. The team may       *\n *    change it's priority or action based on this event.                                      *\n *                                                                                             *\n * INPUT:   damage      -- The damage points inflicted on the unit.                            *\n *                                                                                             *\n *          distance    -- The distance from the point of damage to the unit itself.           *\n *                                                                                             *\n *          warhead     -- The type of damage that is inflicted.                               *\n *                                                                                             *\n *          source      -- The perpetrator of the damage. By knowing who caused the damage,    *\n *                         the team know's who to \"get even with\".                             *\n *                                                                                             *\n * OUTPUT:  Returns with the result type of the damage.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/30/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nResultType FootClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, int forced)\n{\n\tassert(IsActive);\n\n\tResultType result = TechnoClass::Take_Damage(damage, distance, warhead, source, forced);\n\n\tif (result != RESULT_NONE && Team) {\n\n\t\tTeam->Took_Damage(this, result, source);\n\n\t} else {\n\n\t\tif (result != RESULT_DESTROYED && result != RESULT_NONE) {\n\n\t\t\t/*\n\t\t\t**\tDetermine if the target that is currently being attacked has a weapon that can\n\t\t\t**\tdo harm to a ground based unit. This information is needed so that an appropriate\n\t\t\t**\tresponse will occur when damage is taken.\n\t\t\t*/\n//\t\t\tbool tweap = false;\n//\t\t\tif (As_Techno(TarCom)) {\n//\t\t\t\ttweap = (As_Techno(TarCom)->Techno_Type_Class()->PrimaryWeapon != NULL);\n//\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tThis ensures that if a unit is in sticky mode, then it will snap out of\n\t\t\t**\tit when it takes damage.\n\t\t\t*/\n\t\t\tif (source != NULL && MissionControl[Mission].IsNoThreat && !MissionControl[Mission].IsZombie) {\n\t\t\t\tEnter_Idle_Mode();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf this object is not part of a team and it can retaliate for the damage, then have\n\t\t\t**\tit try to do so. This prevents it from just sitting there and taking damage.\n\t\t\t*/\n\t\t\tif (Is_Allowed_To_Retaliate(source)) {\n\n\t\t\t\tint primary = What_Weapon_Should_I_Use(source->As_Target());\n\t\t\t\tif (In_Range(source, primary) || !House->IsHuman) {\n\t\t\t\t\tAssign_Target(source->As_Target());\n\t\t\t\t}\n\n\t\t\t\tif (Mission == MISSION_AMBUSH) {\n\t\t\t\t\tAssign_Mission(MISSION_HUNT);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tSimple retaliation cannot occur because the source of the damage\n\t\t\t\t**\tis too far away. If scatter logic is enabled, then scatter now.\n\t\t\t\t*/\n\t\t\t\tif (!Target_Legal(TarCom) && !Target_Legal(NavCom) && Rule.IsScatter) {\n\t\t\t\t\tScatter(0, true);\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this object isn't doing anything important, then scatter.\n\t\t\t\t*/\n\t\t\t\tif (MissionControl[Mission].IsScatter && !IsTethered && !IsDriving && !Target_Legal(TarCom) && !Target_Legal(NavCom) && What_Am_I() != RTTI_AIRCRAFT && What_Am_I() != RTTI_VESSEL) {\n\t\t\t\t\tif (!House->IsHuman || Rule.IsScatter) {\n\t\t\t\t\t\tScatter(0, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(result);\n}\n\n\n/***********************************************************************************************\n * FootClass::Active_Click_With -- Initiates attack or move according to target clicked on.    *\n *                                                                                             *\n *    At this level, the object is known to have the ability to attack or move to the          *\n *    target specified (in theory). Perform the attack or move as indicated.                   *\n *                                                                                             *\n * INPUT:   target   -- The target clicked upon that will precipitate action.                  *\n *                                                                                             *\n * OUTPUT:  Returns with the type of action performed.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Active_Click_With(ActionType action, ObjectClass * object)\n{\n\tassert(IsActive);\n\tassert(object != NULL);\n\n\tswitch (action) {\n\t\tcase ACTION_GUARD_AREA:\n\t\t\tif (Can_Player_Fire() && Can_Player_Move()) {\n\t\t\t\tif (What_Am_I() == RTTI_INFANTRY &&\n\t\t\t\t\t\t((InfantryClass *)this)->Class->IsBomber &&\n\t\t\t\t\t\tobject->What_Am_I() == RTTI_BUILDING &&\n\t\t\t\t\t\t!House->Is_Ally(object)) {\n\n\t\t\t\t\tPlayer_Assign_Mission(MISSION_SABOTAGE, TARGET_NONE, object->As_Target());\n\t\t\t\t} else {\n\t\t\t\t\tPlayer_Assign_Mission(MISSION_GUARD_AREA, object->As_Target());\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_SELF:\n\t\t\tPlayer_Assign_Mission(MISSION_UNLOAD);\n\t\t\tbreak;\n\n\t\tcase ACTION_ATTACK:\n\t\t\tif (Can_Player_Fire()) {\n\t\t\t\tPlayer_Assign_Mission(MISSION_ATTACK, object->As_Target());\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_ENTER:\n\t\t\tif (Can_Player_Move() && object && object->Is_Techno() /*&& !((RadioClass *)object)->In_Radio_Contact()*/) {\n\t\t\t\tPlayer_Assign_Mission(MISSION_ENTER, TARGET_NONE, object->As_Target());\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_CAPTURE:\n\t\t\tif (Can_Player_Move()) {\n\t\t\t\tPlayer_Assign_Mission(MISSION_CAPTURE, TARGET_NONE, object->As_Target());\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_SABOTAGE:\n\t\t\tif (Can_Player_Move()) {\n\t\t\t\tPlayer_Assign_Mission(MISSION_SABOTAGE, TARGET_NONE, object->As_Target());\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_NOMOVE:\n\t\tcase ACTION_MOVE:\n\t\t\tif (Can_Player_Move()) {\n\n\t\t\t\tTARGET targ = object->As_Target();\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the destination object is not the same zone, then pick a nearby location.\n\t\t\t\t*/\n\t\t\t\tif (object->What_Am_I() != RTTI_AIRCRAFT && Techno_Type_Class()->Speed != SPEED_WINGED && Map[Coord].Zones[Techno_Type_Class()->MZone] != Map[object->Center_Coord()].Zones[Techno_Type_Class()->MZone]) {\n\n#ifdef FIXIT_MINE_PASSABLE\n\t\t\t\t\t// Fixes units not driving onto mines.\n\t\t\t\t\tif (Can_Enter_Cell(Coord_Cell(object->Center_Coord())) > MOVE_OK) {\n\t\t\t\t\t\ttarg = ::As_Target(Map.Nearby_Location(Coord_Cell(object->Center_Coord()), Techno_Type_Class()->Speed, Map[Coord].Zones[Techno_Type_Class()->MZone], Techno_Type_Class()->MZone));\n\t\t\t\t\t}\n#else\n\t\t\t\t\ttarg = ::As_Target(Map.Nearby_Location(Coord_Cell(object->Center_Coord()), Techno_Type_Class()->Speed, Map[Coord].Zones[Techno_Type_Class()->MZone], Techno_Type_Class()->MZone));\n#endif\n\t\t\t\t}\n\n\t\t\t\tPlayer_Assign_Mission(MISSION_MOVE, TARGET_NONE, targ);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Active_Click_With -- Performs action as a result of left mouse click.            *\n *                                                                                             *\n *    This routine performs the action requested when the left mouse button was clicked over   *\n *    a cell. Typically, this is just a move command.                                          *\n *                                                                                             *\n * INPUT:   action   -- The predetermined action that should occur.                            *\n *                                                                                             *\n *          cell     -- The cell number that the action should occur at.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Active_Click_With(ActionType action, CELL cell)\n{\n\tassert(IsActive);\n\n\taction = What_Action(cell);\n\tswitch (action) {\n\t\tcase ACTION_HARVEST:\n\t\t\tPlayer_Assign_Mission(MISSION_HARVEST, TARGET_NONE, ::As_Target(cell));\n\t\t\tbreak;\n\n\t\tcase ACTION_MOVE:\n\t\t\tif (AllowVoice) {\n\t\t\t\tCOORDINATE coord = Map.Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y());\n\t\t\t\tOutList.Add(EventClass(ANIM_MOVE_FLASH, PlayerPtr->Class->House, coord));\n\t\t\t}\n\t\t\t// Fall into next case.\n\n\t\tcase ACTION_NOMOVE:\n\t\t\tif (What_Am_I() != RTTI_AIRCRAFT || Map[cell].IsVisible) {\n\n\t\t\t\t/*\n\t\t\t\t** Find the closest same-zoned cell to where the unit currently is.\n\t\t\t\t** This will allow the unit to come as close to the destination cell\n\t\t\t\t** as is reasonably possible, when clicking on an impassable cell\n\t\t\t\t** (as is likely when clicking in the shroud.)  It looks for the\n\t\t\t\t** nearest cell using an expanding-radius box, and ignores cells\n\t\t\t\t** off the edge of the map.\n\t\t\t\t*/\n\t\t\t\tCellClass const * cellptr = &Map[::As_Cell(::As_Target(Center_Coord()))];\n\t\t\t\tif (What_Am_I() != RTTI_AIRCRAFT) {\n\n\t\t\t\t\tif (Can_Enter_Cell(Coord_Cell(Center_Coord())) == MOVE_OK) {\n\t\t\t\t\t\tcell = Map.Nearby_Location(cell, Techno_Type_Class()->Speed, cellptr->Zones[Techno_Type_Class()->MZone], Techno_Type_Class()->MZone);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcell = Map.Nearby_Location(cell, Techno_Type_Class()->Speed);\n\t\t\t\t\t}\n#ifdef OBSOLETE\n\t\t\t\t\tcell = Map.Nearby_Location(cell, Techno_Type_Class()->Speed, cellptr->Zones[Techno_Type_Class()->MZone], Techno_Type_Class()->MZone);\n#endif\n\t\t\t\t}\n\n\t\t\t\tPlayer_Assign_Mission(MISSION_MOVE, TARGET_NONE, ::As_Target(cell));\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_ATTACK:\n\t\t\tPlayer_Assign_Mission(MISSION_ATTACK, ::As_Target(cell));\n\t\t\tbreak;\n\n\t\t/*\n\t\t** Engineer attempting to capture bridge to repair it\n\t\t*/\n\t\tcase ACTION_CAPTURE:\n\t\t\tif (Can_Player_Move()) {\n\t\t\t\tPlayer_Assign_Mission(MISSION_CAPTURE, TARGET_NONE, ::As_Target(cell));\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_SABOTAGE:\n\t\t\tPlayer_Assign_Mission(MISSION_SABOTAGE, TARGET_NONE, ::As_Target(cell) );\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Per_Cell_Process -- Perform action based on once-per-cell condition.             *\n *                                                                                             *\n *    This routine is called as this object moves from cell to cell. When the center of the    *\n *    cell is reached, check to see if any trigger should be sprung. For moving units, reduce  *\n *    the path to the distance to the target. This forces path recalculation in an effort to   *\n *    avoid units passing each other.                                                          *\n *                                                                                             *\n * INPUT:   why   -- Specifies the circumstances under which this routine was called.          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *   07/08/1995 JLB : Handles generic enter trigger event.                                     *\n *   07/16/1995 JLB : If next to a scanner and cloaked, then shimmer.                          *\n *=============================================================================================*/\nvoid FootClass::Per_Cell_Process(PCPType why)\n{\n\tassert(IsActive);\n\n\tif (why == PCP_END) {\n\n\t\tIsScattering = false;\n\n\t\t/*\n\t\t**\tClear any unloading flag if necessary.\n\t\t*/\n\t\tIsUnloading = false;\n\n\t\t/*\n\t\t**\tIf adjacent to an enemy techno that has the ability to reveal a sub,\n\t\t**\tthen shimmer the cloaked object.\n\t\t*/\n\t\tif (Cloak == CLOAKED) {\n\t\t\tfor (FacingType face = FACING_N; face < FACING_COUNT; face++) {\n\t\t\t\tCELL cell = Adjacent_Cell(Coord_Cell(Coord), face);\n\n\t\t\t\tif (Map.In_Radar(cell)) {\n\t\t\t\t\tTechnoClass const * techno = Map[cell].Cell_Techno();\n\n\t\t\t\t\tif (techno && !techno->House->Is_Ally(this) && techno->Techno_Type_Class()->IsScanner) {\n\t\t\t\t\t\tDo_Shimmer();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tShorten the path if the target is now within weapon range of this\n\t\t**\tunit and this unit is on an attack type mission.\n\t\t*/\n\t\tif (Target_Legal(TarCom) && (What_Am_I() != RTTI_INFANTRY || !((InfantryClass *)this)->Class->IsDog)) {\n\t\t\tint primary = What_Weapon_Should_I_Use(TarCom);\n\t\t\tbool inrange = In_Range(TarCom, primary);\n\t\t\tTechnoClass const * techno = As_Techno(TarCom);\n\t\t\tif (techno != NULL && techno->Is_Foot()) {\n\t\t\t\tinrange = In_Range(((FootClass const *)techno)->Likely_Coord(), primary);\n\t\t\t}\n\n\t\t\tif ((Mission == MISSION_RESCUE || Mission == MISSION_GUARD_AREA || Mission == MISSION_ATTACK || Mission == MISSION_HUNT) && inrange) {\n\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tTrigger event associated with the player entering the cell.\n\t\t*/\n\t\tif (Cloak != CLOAKED) {\n\t\t\tTriggerClass * trigger = Map[Coord].Trigger;\n\t\t\tif (trigger != NULL) {\n\t\t\t\ttrigger->Spring(TEVENT_PLAYER_ENTERED, this, Coord_Cell(Coord));\n\t\t\t\tif (!IsActive) return;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCheck for horizontal trigger crossing.\n\t\t\t*/\n\t\t\tint x = Cell_X(Coord_Cell(Coord));\n\t\t\tint y = Cell_Y(Coord_Cell(Coord));\n\t\t\tfor (int index = 0; index < Map.MapCellWidth; index++) {\n\t\t\t\ttrigger = Map[XY_Cell(index+Map.MapCellX, y)].Trigger;\n\t\t\t\tif (trigger != NULL) {\n\t\t\t\t\tif (trigger->Class->Event1.Event == TEVENT_CROSS_HORIZONTAL || (trigger->Class->EventControl != MULTI_ONLY && trigger->Class->Event2.Event == TEVENT_CROSS_HORIZONTAL)) {\n\t\t\t\t\t\ttrigger->Spring(TEVENT_CROSS_HORIZONTAL, this, Coord_Cell(Coord));\n\t\t\t\t\t\tif (!IsActive) return;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCheck for vertical trigger crossing.\n\t\t\t*/\n\t\t\tfor (index = 0; index < Map.MapCellHeight; index++) {\n\t\t\t\ttrigger = Map[XY_Cell(x, index+Map.MapCellY)].Trigger;\n\t\t\t\tif (trigger != NULL) {\n\t\t\t\t\tif (trigger->Class->Event1.Event == TEVENT_CROSS_VERTICAL || (trigger->Class->EventControl != MULTI_ONLY && trigger->Class->Event2.Event == TEVENT_CROSS_VERTICAL)) {\n\t\t\t\t\t\ttrigger->Spring(TEVENT_CROSS_VERTICAL, this, Coord_Cell(Coord));\n\t\t\t\t\t\tif (!IsActive) return;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCheck for zone entry trigger events.\n\t\t\t*/\n\t\t\tfor (MapTriggerID = 0; MapTriggerID < MapTriggers.Count(); MapTriggerID++) {\n\t\t\t\ttrigger = MapTriggers[MapTriggerID];\n\t\t\t\tif (trigger->Class->Event1.Event == TEVENT_ENTERS_ZONE || (trigger->Class->EventControl != MULTI_ONLY && trigger->Class->Event2.Event == TEVENT_ENTERS_ZONE)) {\n\t\t\t\t\tif (Map[trigger->Cell].Zones[Techno_Type_Class()->MZone] == Map[Coord].Zones[Techno_Type_Class()->MZone]) {\n\t\t\t\t\t\ttrigger->Spring(TEVENT_ENTERS_ZONE, this, Coord_Cell(Coord));\n\t\t\t\t\t\tif (!IsActive) return;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf any of these triggers cause this unit to be destroyed, then\n\t\t\t**\tstop all further processing for this unit.\n\t\t\t*/\n\t\t\tif (!IsActive) return;\n\t\t}\n\n#ifdef OBSOLETE\n\t\t/*\n\t\t** Flag any gap generators to re-draw\n\t\t*/\n\t\tfor (int index = 0; index <Buildings.Count(); index++) {\n\t\t\tBuildingClass * obj = Buildings.Ptr(index);\n\t\t\tif (obj && *obj == STRUCT_GAP && !obj->IsInLimbo && (HouseClass *)obj->House != PlayerPtr) {\n\t\t\t\tint dist = Distance(obj) / CELL_LEPTON_W;\n\t\t\t\tif (dist < (6 + Rule.GapShroudRadius) ) {\n\t//\t\t\tif (dist < (6 + obj->Class->SightRange) ) {\n\t\t\t\t\tobj->IsJamming = false;\t// lie so it'll re-jam now\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#endif\n\n\t}\n\n\tTechnoClass::Per_Cell_Process(why);\n}\n\n\n/***************************************************************************\n * FootClass::Override_Mission -- temporarily overrides a units mission    *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:\t\tMissionType mission - the mission we want to override       *\n *\t\t\t\t\tTARGET\t   tarcom  - the new target we want to override\t\t*\n *\t\t\t\t\tTARGET\t\tnavcom  - the new navigation point to override\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *                                                                         *\n * WARNINGS:   If a mission is already overridden, the current mission is  *\n *\t\t\t\t\tjust re-assigned.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/28/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid FootClass::Override_Mission(MissionType mission, TARGET tarcom, TARGET navcom)\n{\n\tassert(IsActive);\n\n \tSuspendedNavCom = NavCom;\n\tTechnoClass::Override_Mission(mission, tarcom, navcom);\n\n\tAssign_Destination(navcom);\n}\n\n\n/***************************************************************************\n * FootClass::Restore_Mission -- Restores an overridden mission            *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/28/1995 PWG : Created.                                             *\n *=========================================================================*/\nbool FootClass::Restore_Mission(void)\n{\n\tassert(IsActive);\n\n\tif (TechnoClass::Restore_Mission()) {\n\t\tAssign_Destination(SuspendedNavCom);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FootClass::Receive_Message -- Movement related radio messages are handled here.             *\n *                                                                                             *\n *    This routine handles radio message that are related to movement. These are used for      *\n *    complex coordinated maneuvers.                                                           *\n *                                                                                             *\n * INPUT:   from     -- Pointer to the originator of this radio message.                       *\n *                                                                                             *\n *          message  -- The radio message that is being received.                              *\n *                                                                                             *\n *          param    -- The optional parameter (could be a movement destination).              *\n *                                                                                             *\n * OUTPUT:  Returns with the radio response appropriate to the message received. Usually the   *\n *          response is RADIO_ROGER.                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/14/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nRadioMessageType FootClass::Receive_Message(RadioClass * from, RadioMessageType message, long & param)\n{\n\tassert(IsActive);\n\n\tswitch (message) {\n\n\t\t/*\n\t\t**\tAnswers if this object is located on top of a service depot.\n\t\t*/\n\t\tcase RADIO_ON_DEPOT:\n\t\t\tif (Map[Center_Coord()].Cell_Building() != NULL) {\n\t\t\t\tBuildingClass const * building = Map[Center_Coord()].Cell_Building();\n\t\t\t\tif (*building == STRUCT_REPAIR) {\n\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn(RADIO_NEGATIVE);\n\n\t\t/*\n\t\t**\tIntercept the repair request and if this object is moving, then no repair\n\t\t**\tis possible.\n\t\t*/\n\t\tcase RADIO_REPAIR:\n\t\t\tif (Target_Legal(NavCom)) return(RADIO_NEGATIVE);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tSomething bad has happened to the object in contact with. Abort any coordinated\n\t\t**\tactivity with this object. Basically, ... run away! Run away!\n\t\t*/\n\t\tcase RADIO_RUN_AWAY:\n\t\t\tif (In_Radio_Contact()) {\n\t\t\t\tif (NavCom == Contact_With_Whom()->As_Target()) {\n\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (Mission == MISSION_SLEEP) {\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\tCommence();\n\t\t\t}\n\t\t\tif (Mission == MISSION_ENTER) {\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t}\n\t\t\tif (!IsRotating && !Target_Legal(NavCom)) {\n\t\t\t\tScatter(0, true, true);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tChecks to see if this unit needs to move somewhere. If it is already in motion,\n\t\t**\tthen it doesn't need further movement instructions.\n\t\t*/\n\t\tcase RADIO_NEED_TO_MOVE:\n\t\t\tparam = (long)NavCom;\n\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\treturn(RADIO_ROGER);\n\t\t\t}\n\t\t\treturn(RADIO_NEGATIVE);\n\n\t\t/*\n\t\t**\tRadio request to move to location specified. Typically this is used\n\t\t**\tfor complex loading and unloading missions.\n\t\t*/\n\t\tcase RADIO_MOVE_HERE:\n\t\t\tif (NavCom != (TARGET)param) {\n\t\t\t\tif (::As_Target(Coord_Cell(Coord)) == (TARGET)param) {\n\t\t\t\t\treturn(RADIO_YEA_NOW_WHAT);\n\t\t\t\t} else {\n\t\t\t\t\tif (Mission == MISSION_GUARD && MissionQueue == MISSION_NONE) {\n\t\t\t\t\t\tAssign_Mission(MISSION_MOVE);\n\t\t\t\t\t}\n\t\t\t\t\tAssign_Destination((TARGET)param);\n\t\t\t\t\tShorten_Mission_Timer();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t** Requests if this unit is trying to cooperatively load up. Typically, this occurs\n\t\t**\tfor passengers and when vehicles need to be repaired.\n\t\t*/\n\t\tcase RADIO_TRYING_TO_LOAD:\n\t\t\tif (Mission == MISSION_ENTER || MissionQueue == MISSION_ENTER) {\n\t\t\t\tTechnoClass::Receive_Message(from, message, param);\n\t\t\t\treturn(RADIO_ROGER);\n\t\t\t}\n\t\t\tbreak;\n\t}\n\treturn(TechnoClass::Receive_Message(from, message, param));\n}\n\n\n/***********************************************************************************************\n * FootClass::Mission_Enter -- Enter (cooperatively) mission handler.                          *\n *                                                                                             *\n *    This mission handler will cooperatively coordinate the object to maneuver into the       *\n *    object it is in radio contact with. This is used by infantry when they wish to load      *\n *    into an APC as well as by vehicles when they wish to enter a repair facility.            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the number of game ticks before this routine should be called again.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/15/1995 JLB : Created.                                                                 *\n *   09/22/1995 JLB : Modified to handle the \"on hold\" condition.                              *\n *=============================================================================================*/\nint FootClass::Mission_Enter(void)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tFind out who to coordinate with. If in radio contact, then this the transporter is\n\t**\tdefined. If not in radio contact, then try the archive target value to see if that\n\t**\tis suitable.\n\t*/\n\tTechnoClass * contact = Contact_With_Whom();\n\tif (contact == NULL) {\n\t\tcontact = As_Techno(ArchiveTarget);\n\t}\n\n\t/*\n\t**\tIf in contact, then let the transporter handle the movement coordination.\n\t*/\n\tif (contact != NULL) {\n\n\t\t/*\n\t\t**\tIf the transport says to \"bug off\", then abort the enter mission. The transport may\n\t\t**\tlikely say all is 'ok' with the \"RADIO ROGER\", then try again later.\n\t\t*/\n\t\tif (Transmit_Message(RADIO_DOCKING, contact) != RADIO_ROGER && !IsTethered) {\n\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\tEnter_Idle_Mode();\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tSince there is no potential object to enter, then abort this\n\t\t**\tmission with some default standby mission.\n\t\t*/\n\t\tEnter_Idle_Mode();\n\t}\n\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * FootClass::Assign_Destination -- Assigns specified destination to NavCom.                   *\n *                                                                                             *\n *    This routine will assign the specified target to the navigation computer. No legality    *\n *    checks are performed.                                                                    *\n *                                                                                             *\n * INPUT:   target   -- The target value to assign to the navigation computer.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Assign_Destination(TARGET target)\n{\n\tassert(IsActive);\n\n\tNavCom = target;\n\n\t/*\n\t**\tPresume that the easiest path is tried first. As the findpath proceeds, when\n\t**\ta failure occurs, this threshhold will be increased until path failure\n\t**\tcannot be prevent. At this point, all movement should cease.\n\t*/\n\tPathThreshhold = MOVE_CLOAK;\n}\n\n\n/***********************************************************************************************\n * FootClass::Detach_All -- Removes this object from the game system.                          *\n *                                                                                             *\n *    This routine will remove this object from the game system. This routine is called when   *\n *    this object is about to be deleted. All other objects should no longer reference this    *\n *    object in that case.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Detach_All(bool all)\n{\n\tassert(IsActive);\n\n\tif (Team && !ScenarioInit) {\n\t\tTeam->Remove(this);\n\t\tTeam = NULL;\n\t}\n\n\tTechnoClass::Detach_All(all);\n}\n\n\n/***********************************************************************************************\n * FootClass::Rescue_Mission -- Calls this unit to the rescue.                                 *\n *                                                                                             *\n *    This routine is called when the house determines that it should attack the specified     *\n *    target. This routine will determine if it can attack the target specified and if so,     *\n *    the amount of power it can throw at it. This returned power value is used to allow       *\n *    intelligent distribution of retaliation.                                                 *\n *                                                                                             *\n * INPUT:   target   -- The target that this object just might be assigned to attack and thus  *\n *                      how much power it can bring to bear should be returned.                *\n *                                                                                             *\n * OUTPUT:  Returns with the amount of power that this object can bring to bear against the    *\n *          potential target specified.                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FootClass::Rescue_Mission(TARGET tarcom)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tIf the target specified is not legal, then it cannot be attacked. Always return\n\t**\tzero in this case.\n\t*/\n\tif (!Target_Legal(tarcom)) return(0);\n\n\t/*\n\t** If the unit is already assigned to destroy the tarcom then we need\n\t** to return a negative value which tells the computer to lower the\n\t** desired threat rating.\n\t*/\n\tif (TarCom == tarcom) {\n\t\treturn(-Risk());\n\t}\n\n\t/*\n\t** If the unit is currently attacking a target that has a weapon then we\n\t** cannot abandon it as it will destroy us if we return to base.\n\t*/\n\tif (Target_Legal(TarCom)) {\n\t\tTechnoClass * techno = As_Techno(TarCom);\n\t\tif (techno != NULL && techno->Is_Weapon_Equipped()) {\n\t\t\treturn(0);\n\t\t}\n\t}\n\n\t/*\n\t** If the unit is in a harvest mission or is currently attacking\n\t** something, or is not very effective, then it will be of no help\n\t** at all.\n\t*/\n\tif (Team.Is_Valid() || Mission == MISSION_HARVEST || !Risk()) {\n\t\treturn(0);\n\t}\n\n\t/*\n\t** Find the distance to the target modified by the range.  If the\n\t** the distance is 0, then things are ok.\n\t*/\n\tint dist = Distance(tarcom) - Weapon_Range(0);\n\tint threat = Risk() * 1024;\n\tint speed = -1;\n\tif (dist > 0) {\n\n\t\t/*\n\t\t** Next we need to figure out how fast the unit moves because this\n\t\t** decreases the distance penalty.\n\t\t*/\n\t\tspeed = max((unsigned)Techno_Type_Class()->MaxSpeed, (unsigned)1);\n\n\t\tint ratio = (speed > 0) ? Max(dist / speed, 1) : 1;\n\n\t\t/*\n\t\t** Finally modify the threat by the distance the unit is away.\n\t\t*/\n\t\tthreat = max(threat/ratio, 1);\n\t}\n\treturn(threat);\n}\n\n\n/***********************************************************************************************\n * FootClass::Death_Announcement -- Announces the death of a unit.                             *\n *                                                                                             *\n *    This routine is called when a unit (infantry, vehicle, or aircraft) is destroyed.        *\n *                                                                                             *\n * INPUT:   source   -- The perpetrator of this death.                                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Death_Announcement(TechnoClass const * ) const\n{\n\tassert(IsActive);\n\n\tif (IsOwnedByPlayer) {\n\t\tif (What_Am_I() == RTTI_VESSEL) {\n\t\t\tSpeak(VOX_SHIP_LOST);\n\t\t} else {\n\t\t\tSpeak(VOX_UNIT_LOST);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Greatest_Threat -- Fetches the greatest threat to this object.                   *\n *                                                                                             *\n *    This routine will return with the greatest threat (best target) for this object. For     *\n *    movable ground object, they won't automatically return ANY target if this object is      *\n *    cloaked. Otherwise, cloaking is relatively useless.                                      *\n *                                                                                             *\n * INPUT:   method   -- The request method (bit flags) to use when scanning for a target.      *\n *                                                                                             *\n * OUTPUT:  Returns with the best target to attack. If there is no target that qualifies, then *\n *          TARGET_NONE is returned.                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *   07/10/1996 JLB : Handles scan range limitation.                                           *\n *=============================================================================================*/\nTARGET FootClass::Greatest_Threat(ThreatType method) const\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tIf the scan is forced to be limited, then limit the scan now.\n\t*/\n\tif (IsScanLimited) {\n\t\tmethod = method & ~THREAT_AREA;\n\t\tmethod = method | THREAT_RANGE;\n\t}\n\n\t/*\n\t**\tIf this object can cloak, then it won't select a target automatically.\n\t*/\n\tif (House->IsHuman && IsCloakable && Mission == MISSION_GUARD) {\n\t\treturn(TARGET_NONE);\n\t}\n\n\tif (!(method & (THREAT_INFANTRY|THREAT_VEHICLES|THREAT_BUILDINGS|THREAT_TIBERIUM|THREAT_BOATS|THREAT_CIVILIANS|THREAT_POWER|THREAT_FAKES|THREAT_FACTORIES|THREAT_BASE_DEFENSE))) {\n\t\tif (What_Am_I() != RTTI_VESSEL) {\n\t\t\tmethod = method | THREAT_GROUND;\n\t\t} else {\n\t\t\tmethod = method | THREAT_BOATS|THREAT_GROUND;\n\t\t}\n\t}\n\n\t/*\n\t**\tPerform the search for the target.\n\t*/\n\tTARGET target = TechnoClass::Greatest_Threat(method);\n\n\t/*\n\t**\tIf no target could be located and this object is under scan range\n\t**\trestrictions, then this restriction must be lifted now.\n\t*/\n\tif (IsScanLimited && target == TARGET_NONE) {\n\t\tIsScanLimited = false;\n\t}\n\n\t/*\n\t**\tReturn with final target found.\n\t*/\n\treturn(target);\n}\n\n\n/***********************************************************************************************\n * FootClass::Detach -- Detaches a target from tracking systems.                               *\n *                                                                                             *\n *    This routine will detach the specified target from the tracking systems of this object.  *\n *    It will be removed from the navigation computer and any queued mission record.           *\n *                                                                                             *\n * INPUT:   target   -- The target to be removed from this object.                             *\n *                                                                                             *\n *          all      -- Is the unit really about to be eliminated? If this is true then even   *\n *                      friendly contact (i.e., radio) must be eliminated.                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1995 JLB : Created.                                                                 *\n *   07/24/1996 JLB : Removes target from NavQueue list.                                       *\n *=============================================================================================*/\nvoid FootClass::Detach(TARGET target, bool all)\n{\n\tassert(IsActive);\n\n\tTechnoClass::Detach(target, all);\n\n\tif (!SpecialFlag) {\n\t\tif (ArchiveTarget == target) {\n\t\t\tArchiveTarget = TARGET_NONE;\n\t\t}\n\t}\n\n\tif (SuspendedNavCom == target) {\n\t\tSuspendedNavCom = TARGET_NONE;\n\t\tSuspendedMission = MISSION_NONE;\n\t}\n\n\t/*\n\t**\tIf the navigation computer is assigned to the target, then the navigation\n\t**\tcomputer must be cleared.\n\t*/\n\tif (NavCom == target) {\n\t\tNavCom = TARGET_NONE;\n\t\tPath[0] = FACING_NONE;\n\t\tRestore_Mission();\n\t}\n\n\t/*\n\t**\tRemove the target from the NavQueue list as well.\n\t*/\n\tfor (int index = 0; index < ARRAY_SIZE(NavQueue); index++) {\n\t\tif (NavQueue[index] == target) {\n\t\t\tNavQueue[index] = TARGET_NONE;\n\t\t\tif (index < ARRAY_SIZE(NavQueue)-1) {\n\t\t\t\tmemmove(&NavQueue[index], &NavQueue[index+1], ((ARRAY_SIZE(NavQueue)-index)-1) * sizeof(NavQueue[0]));\n\t\t\t\tindex--;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf targeting the specified object and this unit is obviously heading\n\t**\ttoward the target to get within range, then abort the path.\n\t*/\n\tif (TarCom == target && House->IsHuman) {\n\t\tPath[0] = FACING_NONE;\n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Offload_Tiberium_Bail -- Fetches the Tiberium to offload per step.               *\n *                                                                                             *\n *    This routine is called when a packet/package/bail of Tiberium needs to be offloaded      *\n *    from the object. This function is overridden for those objects that can contain          *\n *    Tiberium.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of credits offloaded from the object.                      *\n *                                                                                             *\n * WARNINGS:   This routine must be called multiple times in order to completely offload the   *\n *             Tiberium. When this routine return 0, all Tiberium has been offloaded.          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FootClass::Offload_Tiberium_Bail(void)\n{\n\tassert(IsActive);\n\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * FootClass::Can_Enter_Cell -- Checks to see if the object can enter cell specified.          *\n *                                                                                             *\n *    This routine examines the specified cell to see if the object can enter it. This         *\n *    function is to be overridden for objects that could have the possibility of not being    *\n *    allowed to enter the cell. Typical objects at the FootClass level always return          *\n *    MOVE_OK.                                                                                 *\n *                                                                                             *\n * INPUT:   cell     -- The cell to examine.                                                   *\n *                                                                                             *\n *          facing   -- The direction that this cell might be entered from.                    *\n *                                                                                             *\n * OUTPUT:  Returns with the move check result type. This will be MOVE_OK if there is not      *\n *          blockage. There are various other values that represent other blockage types.      *\n *          The value returned will indicated the most severe reason why entry into the cell   *\n *          is blocked.                                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nMoveType FootClass::Can_Enter_Cell(CELL , FacingType) const\n{\n\tassert(IsActive);\n\n\treturn MOVE_OK;\n}\n\n\n/***********************************************************************************************\n * FootClass::Can_Demolish -- Checks to see if this object can be sold back.                   *\n *                                                                                             *\n *    This routine determines if it is legal to sell the object back. A foot class object can  *\n *    only be sold back if it is sitting on a repair bay.                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the object successfully sold back?                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FootClass::Can_Demolish(void) const\n{\n\tassert(IsActive);\n\n\tswitch (What_Am_I()) {\n\t\tcase RTTI_UNIT:\n\t\tcase RTTI_VESSEL:\n\t\tcase RTTI_AIRCRAFT:\n\t\t\tif (In_Radio_Contact() &&\n\t\t\t\tContact_With_Whom()->What_Am_I() == RTTI_BUILDING &&\n\t\t\t\t*((BuildingClass *)Contact_With_Whom()) == STRUCT_REPAIR &&\n\t\t\t\tDistance(Contact_With_Whom()) < 0x0080) {\n\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(TechnoClass::Can_Demolish());\n}\n\n\n/***********************************************************************************************\n * FootClass::Sell_Back -- Causes this object to be sold back.                                 *\n *                                                                                             *\n *    When an object is sold back, a certain amount of money is refunded to the owner and then *\n *    the object is removed from the game system.                                              *\n *                                                                                             *\n * INPUT:   control  -- The action to perform. The only supported action is \"1\", which means   *\n *                      to sell back.                                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Sell_Back(int control)\n{\n\tassert(IsActive);\n\n\tif (control != 0) {\n\t\tif (House == PlayerPtr) {\n\t\t\tSpeak(VOX_UNIT_SOLD);\n\t\t\tSound_Effect(VOC_CASHTURN);\n\t\t}\n\t\tHouse->Refund_Money(Refund_Amount());\n\t\tStun();\n\t\tLimbo();\n\t\tdelete this;\n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Likely_Coord -- Fetches the coordinate the object will be at shortly.            *\n *                                                                                             *\n *    This routine comes in handy when determining where a travelling object will be at        *\n *    when considering the amount of time it would take for a normal unit to travel one cell.  *\n *    Using this information, an intelligent \"approach target\" logic can be employed.          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate the object is at or soon will be.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE FootClass::Likely_Coord(void) const\n{\n\tassert(IsActive);\n\n\tif (Head_To_Coord()) {\n\t\treturn(Head_To_Coord());\n\t}\n\treturn(Target_Coord());\n}\n\n\n/***********************************************************************************************\n * FootClass::Adjust_Dest -- Adjust candidate movement cell to account for formation.          *\n *                                                                                             *\n *    This routine modify the specified cell if the unit is part of a formation. The           *\n *    adjustment will take into consideration the formation relative offset from the           *\n *    (presumed) center cell specified.                                                        *\n *                                                                                             *\n * INPUT:   cell  -- The cell to presume as the desired center point of the formation.         *\n *                                                                                             *\n * OUTPUT:  Returns with the cell that should be used as the actual destination. If this       *\n *          object is part of a formation, then the cell location will be appropriately        *\n *          adjusted.                                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL FootClass::Adjust_Dest(CELL cell) const\n{\n\tassert(IsActive);\n\n\tif (IsFormationMove) {\n\t\tint xdest = Cell_X(cell);\n\t\tint ydest = Cell_Y(cell);\n\n\t\tint newx = Bound(XFormOffset + xdest, Map.MapCellX, Map.MapCellX + Map.MapCellWidth -1);\n\t\tint newy = Bound(YFormOffset + ydest, Map.MapCellY, Map.MapCellY + Map.MapCellHeight -1);\n\n\t\tcell = XY_Cell(newx, newy);\n\t}\n\treturn(cell);\n}\n\n\n/***********************************************************************************************\n * FootClass::Handle_Navigation_List -- Processes the navigation queue.                        *\n *                                                                                             *\n *    This routine will process the navigation queue. If the queue is present and valid and    *\n *    there is currently no navigation target assigned to this object, then the first entry    *\n *    of the queue will be assigned. The remaining entries will move down. If the queue is     *\n *    to be processed as a circular list, then the first entry is appended to the end.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine might end up assigning a movement destination.                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Handle_Navigation_List(void)\n{\n\t/*\n\t**\tThe navigation queue only needs to be processed if there is\n\t**\tcurrently no navigation target for this object.\n\t*/\n\tif (!Target_Legal(NavCom)) {\n\t\tTARGET target = NavQueue[0];\n\n\t\t/*\n\t\t**\tCheck to see if the navigation queue even exists and\n\t\t**\thas at least one valid entry. If it does, then process it by\n\t\t**\tassigning the object's NavCom to the first entry on the list.\n\t\t*/\n\t\tif (Target_Legal(target)) {\n\t\t\tAssign_Destination(target);\n\t\t\tmemmove(&NavQueue[0], &NavQueue[1], sizeof(NavQueue)-sizeof(NavQueue[0]));\n\t\t\tNavQueue[ARRAY_SIZE(NavQueue)-1] = TARGET_NONE;\n\n\t\t\t/*\n\t\t\t**\tIf the navigation queue is to loop (indefinately), then append the\n\t\t\t**\ttarget value from the first part to the end of the queue.\n\t\t\t*/\n\t\t\tif (IsNavQueueLoop) {\n\t\t\t\tfor (int index = 0; index < ARRAY_SIZE(NavQueue); index++) {\n\t\t\t\t\tif (NavQueue[index] == TARGET_NONE) {\n\t\t\t\t\t\tNavQueue[index] = target;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Queue_Navigation_List -- Add a target to the objects navigation list.            *\n *                                                                                             *\n *    This routine will append the destination target to the object's NavQueue list. After     *\n *    doing so, if the object is not doing anything important, then it will be started on      *\n *    that destination. This is functionally the same as Assign_Destination, but it stores     *\n *    the target to the NavQueue first.                                                        *\n *                                                                                             *\n * INPUT:   target   -- The movement target destination to append the queue.                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The queue is of finite size and any queue requests that would exceed that size  *\n *             are ignored. If there are no queue entries pending and the unit is not          *\n *             otherwise occupied, then the queue target might be carried directly into the    *\n *             NavCom.                                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Queue_Navigation_List(TARGET target)\n{\n\tif (Target_Legal(target)) {\n\t\tint count;\n\t\tfor (count = 0; count < ARRAY_SIZE(NavQueue); count++) {\n\t\t\tif (!Target_Legal(NavQueue[count])) break;\n\t\t}\n\n\t\t/*\n\t\t**\tIf the target is this object itself, then this indicates that the\n\t\t**\tqueue list is to be processed as a loop. Otherwise, just tack the\n\t\t**\tnavigation target to the end of the list.\n\t\t*/\n\t\tif (target == As_Target() && count > 0) {\n\t\t\tIsNavQueueLoop = true;\n\t\t} else {\n\t\t\tif (count == 0) {\n\t\t\t\tIsNavQueueLoop = false;\n\t\t\t}\n\t\t\tif (count < ARRAY_SIZE(NavQueue)) {\n\t\t\t\tNavQueue[count] = target;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf this object isn't doing anything, then start acting on the\n\t\t**\tnavigation queue now.\n\t\t*/\n\t\tif (!Target_Legal(NavCom) && Mission == MISSION_GUARD) {\n\t\t\tEnter_Idle_Mode();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Clear_Navigation_List -- Clears out the navigation queue.                        *\n *                                                                                             *\n *    This routine will clear out any values in the navigation queue. This is the preferred    *\n *    way of aborting a navigation queue for a unit. If the unit is already travelling, it     *\n *    won't be interrupted by this routine.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This will clear the navigation list but not the navigation computer. Thus a     *\n *             unit will still travel to its current immediate destination.                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Clear_Navigation_List(void)\n{\n\tfor (int index = 0; index < ARRAY_SIZE(NavQueue); index++) {\n\t\tNavQueue[index] = TARGET_NONE;\n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Is_Allowed_To_Leave_Map -- Checks to see if it can leave the map and the game.   *\n *                                                                                             *\n *    This routine will determine if this object has permission to leave the map and thus      *\n *    leave the game. Typical objects with this permission are transports used to drop of      *\n *    reinforcements.                                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Does this object have permission to travel off the map edge and leave the    *\n *                game?                                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FootClass::Is_Allowed_To_Leave_Map(void) const\n{\n\t/*\n\t**\tIf the unit hasn't entered the map yet, then don't allow leave the game.\n\t*/\n\tif (!IsLocked) return(false);\n\n\t/*\n\t**\tA unit that isn't marked as a loaner is a gift to the player. Such objects can never\n\t**\tleave the map unless they are part of a team that gives it special permision.\n\t*/\n\tif (!IsALoaner && Mission != MISSION_RETREAT && (!Team.Is_Valid() || !Team->Is_Leaving_Map())) return(false);\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * FootClass::Is_Recruitable -- Determine if this object is recruitable as a team members.     *\n *                                                                                             *\n *    This will examine this object to determine if it is suitable as a team recruit. Some     *\n *    objects are disqualified if they are otherwise premptively occupied.                     *\n *                                                                                             *\n * INPUT:   house -- Pointer to the house that is trying to recruit this object.               *\n *                                                                                             *\n * OUTPUT:  bool; Is this object suitable for recruitment by a team.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FootClass::Is_Recruitable(HouseClass const * house) const\n{\n\t/*\n\t**\tIf not of the correct house presuasion, then recruitment is not allowed.\n\t*/\n\tif (house != NULL && house != House) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the object is not a playing member of the game, then don't consider it available.\n\t*/\n\tif (IsInLimbo) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf it is already part of another team, then it is not available for\n\t**\tgeneral recruitment.\n\t*/\n\tif (Team.Is_Valid()) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf it is currently in a mission the precludes recruitment into a team, then\n\t**\treturn with this information.\n\t*/\n\tif (!Is_Recruitable_Mission(Mission)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIt was not disqualified for general team recruitment, so return that\n\t**\tit is available.\n\t*/\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * FootClass::AI -- Handle general movement AI.                                                *\n *                                                                                             *\n *    This basically just sees if this object is within weapon range of the target and if      *\n *    so, it will stop movement so that firing may commence. This prevents the occasional      *\n *    case of an attacker driving right up to the defender before firing.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::AI(void)\n{\n\tTechnoClass::AI();\n\n// FootClass::Per_Cell_Process does this function already.\n#ifdef OBSOLETE\n\tif (IsActive) {\n\t\tif (!IsScattering && !IsTethered && !IsInLimbo && What_Am_I() != RTTI_AIRCRAFT && Target_Legal(TarCom) && In_Range(TarCom)) {\n\t\t\tAssign_Destination(TARGET_NONE);\n\t\t}\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * FootClass::Is_On_Priority_Mission -- Checks to see if this object should be given priority. *\n *                                                                                             *\n *    Some objects are on an important mission that must succeed. If the object is on such     *\n *    a mission, then it will be more aggressive in its movement action.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is this object on a priority mission?                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FootClass::Is_On_Priority_Mission(void) const\n{\n\tif (Mission == MISSION_ENTER) return(true);\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FootClass::Mission_Retreat -- Handle reatreat from map mission for mobile objects.          *\n *                                                                                             *\n *    This will try to make this mobile object leave the map. It does this by assigning a      *\n *    movement destination that is located off the edge of the map.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine        *\n *          again.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FootClass::Mission_Retreat(void)\n{\n\tassert(IsActive);\n\n\tenum {\n\t\tFIND_EDGE,\n\t\tTRAVELLING\n\t};\n\n\tswitch (Status) {\n\n\t\t/*\n\t\t**\tFind a suitable edge to travel to and then assign destination there.\n\t\t*/\n\t\tcase FIND_EDGE:\n\t\t\tif (Target_Legal(NavCom)) {\n\t\t\t\tStatus = TRAVELLING;\n\t\t\t} else {\n\n\t\t\t\tCELL cell = 0;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this is part of a team, then pick the edge where the team as likely\n\t\t\t\t**\tentered from.\n\t\t\t\t*/\n\t\t\t\tif (Team.Is_Valid() && Team->Class->Origin != -1) {\n\t\t\t\t\tcell = Map.Calculated_Cell(House->Control.Edge, Team->Class->Origin, Coord_Cell(Center_Coord()), Techno_Type_Class()->Speed);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf an edge hasn't been found, then try to find one that is not based on any\n\t\t\t\t**\tteam information.\n\t\t\t\t*/\n\t\t\t\tif (cell == 0) {\n\t\t\t\t\tcell = Map.Calculated_Cell(House->Control.Edge, -1, Coord_Cell(Center_Coord()), Techno_Type_Class()->Speed);\n\t\t\t\t}\n\n\t\t\t\tassert(cell == 0);\t\t// An edge cell must be found!\n\n\t\t\t\tAssign_Destination(::As_Target(cell));\n\t\t\t\tStatus = TRAVELLING;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tWhile travelling, monitor that all is proceeding according to plan.\n\t\t*/\n\t\tcase TRAVELLING:\n\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\tStatus = FIND_EDGE;\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n"
  },
  {
    "path": "CODE/FOOT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FOOT.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FOOT.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 14, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 14, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FOOT_H\n#define FOOT_H\n\n#include\t\"target.h\"\n#include\t\"type.h\"\n#include\t\"techno.h\"\n#include\t\"ftimer.h\"\n\nclass UnitClass;\nclass BuildingClass;\n\n\n/****************************************************************************\n**\tMovable objects are handled by this class definition. Moveable objects\n**\tcover everything except buildings.\n*/\nclass FootClass :\tpublic TechnoClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis flag controls whether a range limiting effect should be in place. If\n\t\t**\ttrue, then target scanning will be limited to the range of the object\n\t\t**\tregardless of what was requested from the target scanning logic. This value\n\t\t**\tis used for ships so that they won't permanently stick on a an attack mission\n\t\t**\tfor a target they can never get within range of. This value will toggle when\n\t\t**\ta path cannot be generated and the target is not within range. It will also\n\t\t**\ttoggle when path limiting is true, but there is not target found within\n\t\t**\tthe limited range.\n\t\t*/\n\t\tunsigned IsScanLimited:1;\n\n\t\t/*\n\t\t**\tIf this unit has officially joined the team's group, then this flag is\n\t\t**\ttrue. A newly assigned unit to a team is not considered part of the\n\t\t**\tteam until it actually reaches the location where the team is. By\n\t\t**\tusing this flag, it allows a team to continue to intelligently attack\n\t\t**\ta target without falling back to regroup the moment a distant member\n\t\t**\tjoins.\n\t\t*/\n\t\tunsigned IsInitiated:1;\n\n\t\t/*\n\t\t**\tWhen the player gives this object a navigation target AND that target\n\t\t**\tdoes not result in any movement of the unit, then a beep should be\n\t\t**\tsounded. This typically occurs when selecting an invalid location for\n\t\t**\tmovement. This flag is cleared if any movement was able to be performed.\n\t\t**\tIt never gets set for computer controlled units.\n\t\t*/\n\t\tunsigned IsNewNavCom:1;\n\n\t\t/*\n\t\t**\tThere are certain cases where a unit should perform a full scan rather than\n\t\t**\tthe more efficient \"ring scan\". This situation occurs when a unit first\n\t\t**\tappears on the map or when it finishes a multiple cell movement track.\n\t\t*/\n\t\tunsigned IsPlanningToLook:1;\n\n\t\t/*\n\t\t**\tCertain units have the ability to metamorphize into a building. When this\n\t\t**\toperation begins, certain processes must occur. During these operations, this\n\t\t**\tflag will be true. This ensures that any necessary special case code gets\n\t\t**\tproperly executed for this unit.\n\t\t*/\n\t\tunsigned IsDeploying:1;\n\n\t\t/*\n\t\t**\tThis flag tells the system that the unit is doing a firing animation. This is\n\t\t**\tcritical to the firing logic.\n\t\t*/\n\t\tunsigned IsFiring:1;\n\n\t\t/*\n\t\t**\tThis unit could be either rotating its body or rotating its turret. During the\n\t\t**\tprocess of rotation, this flag is set. By examining this flag, unnecessary logic\n\t\t**\tcan be avoided.\n\t\t*/\n\t\tunsigned IsRotating:1;\n\n\t\t/*\n\t\t**\tIf this object is current driving to a short range destination, this flag is\n\t\t**\ttrue. A short range destination is either the next cell or the end of the\n\t\t**\tcurrent \"curvy\" track. An object that is driving is not allowed to do anything\n\t\t**\telse until it reaches its destination. The exception is when infantry wish to\n\t\t**\thead to a different destination, they are allowed to start immediately.\n\t\t*/\n\t\tunsigned IsDriving:1;\n\n\t\t/*\n\t\t**\tIf this object is unloading from a hover transport, then this flag will be\n\t\t**\tset to true. This handles the unusual case of an object disembarking from the\n\t\t**\thover lander yet not necessarily tethered but still located in an overlapping\n\t\t**\tposition. This flag will be cleared automatically when the object moves to the\n\t\t**\tcenter of a cell.\n\t\t*/\n\t\tunsigned IsUnloading:1;\n\n\t\t/*\n\t\t** If this object is part of a formation, this bit will be set.  The\n\t\t** formation only occurs when every member of a team is selected, and\n\t\t** only those members of the team are the ones selected.\n\t\t*/\n\t\tunsigned IsFormationMove:1;\n\n\t\t/*\n\t\t**\tIf the navigation movement queue is to be looped rather than consumed, then\n\t\t**\tthis flag will be true. By looping, the unit will travel through the locations\n\t\t**\tin the queue indefinately.\n\t\t*/\n\t\tunsigned IsNavQueueLoop:1;\n\n\t\t/*\n\t\t**\tIf this object is scattering, then this flag will be true. While true, the\n\t\t**\tNavCom should not be arbitrarily changed. This flag will automatcially be\n\t\t**\tcleared when the object moves one cell.\n\t\t*/\n\t\tunsigned IsScattering:1;\n\n\t\t/*\n\t\t**\tThis is the \"throttle setting\" of the unit. It is a fractional value with 0 = stop\n\t\t**\tand 255 = full speed.\n\t\t*/\n\t\tint Speed;\n\n\t\t/*\n\t\t**\tThis is the override speed adjuster. Normally, this is a fixed point\n\t\t**\tvalue of 0x0100, but it can be modified by crate powerups.\n\t\t*/\n\t\tfixed SpeedBias;\n\n\t\t/*\n\t\t** For units in a formation, these values represent the distance from\n\t\t** the target destination where the unit should move to.  For example,\n\t\t** in a horizontal line formation, XFormOffset would be set to some\n\t\t** value, and YFormOffset would be zero.\n\t\t*/\n\t\tint XFormOffset;\n\t\tint YFormOffset;\n\n\t\t/*\n\t\t**\n\t\t**\tThis is the desired destination of the unit. The unit will attempt to head\n\t\t**\ttoward this target (avoiding intervening obstacles).\n\t\t*/\n\t\tTARGET NavCom;\n\t\tTARGET SuspendedNavCom;\n\n\t\t/*\n\t\t**\tA sequence of move destinations can be given to a unit. The sequence is\n\t\t**\tstores as an array of movement targets. The list is terminated with a\n\t\t**\tTARGET_NONE.\n\t\t*/\n\t\tTARGET NavQueue[10];\n\n\t\t/*\n\t\t**\tThis points to the team that \"owns\" this object. This pointer is used to\n\t\t**\tquickly process the team when this object is the source of the change. An\n\t\t**\texample would be if this object were to be destroyed, it would inform the\n\t\t**\tteam of this fact by using this pointer.\n\t\t*/\n\t\tCCPtr<TeamClass> Team;\n\n\t\t/*\n\t\t**\tIf this object is part of a pseudo-team that the player is managing, then\n\t\t**\tthis will be set to the team number (0 - 9). If it is not part of any\n\t\t**\tpseudo-team, then the number will be -1.\n\t\t*/\n\t\tunsigned char Group;\n\n\t\t/*\n\t\t**\tThis points to the next member in the team that this object is part of. This\n\t\t**\tis used to quickly process each team member when the team class is the source\n\t\t**\tof the change. An example would be if the team decided that everyone is going\n\t\t**\tto move to a new location, it would inform each of the objects by chaining\n\t\t**\tthrough this pointer.\n\t\t*/\n\t\tFootClass * Member;\n\n\t\t/*\n\t\t**\tSince all objects derived from this class move according to a path list.\n\t\t**\tThis is the path list. It specifies, as a simple list of facings, the\n\t\t**\tpath that the object should follow in order to reach its destination.\n\t\t**\tThis path list is limited in size, so it might require several generations\n\t\t**\tof path lists before the ultimate destination is reached. The game logic\n\t\t**\thandles regenerating the path list as necessary.\n\t\t*/\n\t\tFacingType Path[CONQUER_PATH_MAX];\n\n\t\t/*\n\t\t**\tThis value keeps track of how serious the unit is in trying to reach the\n\t\t**\tdestination specified. As blockages arise, this threshold will rise\n\t\t**\tunit it reaches the point of complete failure. When that event occurs, the\n\t\t**\tunit will realize that it cannot get to its specified destination and will\n\t\t**\ttry to perform some other action instead.\n\t\t*/\n\t\tMoveType PathThreshhold;\n\n\t\t/*\n\t\t**\tWhen there is a complete findpath failure, this timer is initialized so\n\t\t**\tthat a findpath won't be calculated until this timer expires.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> PathDelay;\n\t\tenum {PATH_RETRY=10};\n\t\tint TryTryAgain;\t\t// Number of retry attempts remaining.\n\n\t\t/*\n\t\t** If the object has recently attacked a base, then this timer will not\n\t\t** have expired yet.  It is used so a building does not keep calling\n\t\t** for help from the same attacker.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> BaseAttackTimer;\n\n\t\t/*\n\t\t** For formation moves, this will be the override speed.\n\t\t*/\n\t\tSpeedType FormationSpeed;\n\n\t\t/*\n\t\t** For formation moves, this will be the override maximum speed.\n\t\t*/\n\t\tMPHType\tFormationMaxSpeed;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tFootClass(NoInitClass const & x) : TechnoClass(x), Team(x), PathDelay(x), BaseAttackTimer(x) {};\n\t\tFootClass(RTTIType rtti, int id, HousesType house);\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tbool Basic_Path(void);\n\n\t\tvirtual RadioMessageType Receive_Message(RadioClass * from, RadioMessageType message, long & param);\n\t\tvirtual bool Can_Demolish(void) const;\n\t\tbool Is_Recruitable(HouseClass const * house=NULL) const;\n\t\tbool Is_On_Priority_Mission(void) const;\n\n\t\t/*\n\t\t**\tCoordinate inquiry functions. These are used for both display and\n\t\t**\tcombat purposes.\n\t\t*/\n\t\tvirtual COORDINATE Sort_Y(void) const;\n\t\tvirtual COORDINATE Likely_Coord(void) const;\n\n\t\t/*\n\t\t**\tDriver control support functions. These are used to control cell\n\t\t**\toccupation flags and driver instructions.\n\t\t*/\n\t\tCOORDINATE Head_To_Coord(void) const {return (HeadToCoord);};\n\t\tvirtual bool Start_Driver(COORDINATE &headto);\n\t\tvirtual bool Stop_Driver(void);\n\t\tvirtual void Assign_Destination(TARGET target);\n\t\tbool Is_Allowed_To_Leave_Map(void) const;\n\n\t\t/*\n\t\t**\tDisplay and rendering support functionality. Supports imagery and how\n\t\t**\tobject interacts with the map and thus indirectly controls rendering.\n\t\t*/\n\t\tvirtual bool Unlimbo(COORDINATE , DirType dir = DIR_N);\n\t\tvirtual bool Mark(MarkType mark=MARK_CHANGE);\n\n\t\t/*\n\t\t**\tUser I/O.\n\t\t*/\n\t\tvirtual void Active_Click_With(ActionType action, ObjectClass * object);\n\t\tvirtual void Active_Click_With(ActionType action, CELL cell);\n\n\t\t/*\n\t\t**\tCombat related.\n\t\t*/\n\t\tvirtual void Stun(void);\n\t\tvirtual ResultType Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source=0, bool forced=false);\n\t\tvirtual void Death_Announcement(TechnoClass const * source=0) const;\n\n\t\t/*\n\t\t**\tAI.\n\t\t*/\n\t\tvirtual void AI(void);\n\t\tvirtual void Sell_Back(int control);\n\t\tvirtual int Offload_Tiberium_Bail(void);\n\t\tvirtual TARGET Greatest_Threat(ThreatType method) const;\n\t\tvirtual void Detach(TARGET target, bool all);\n\t\tvirtual void Detach_All(bool all=true);\n\t\tvirtual int Mission_Retreat(void);\n\t\tvirtual int Mission_Enter(void);\n\t\tvirtual int Mission_Move(void);\n\t\tvirtual int Mission_Capture(void);\n\t\tvirtual int Mission_Attack(void);\n\t\tvirtual int Mission_Guard(void);\n\t\tvirtual int Mission_Hunt(void);\n\t\tvirtual int Mission_Guard_Area(void);\n\n\t\t/*\n\t\t**\tScenario and debug support.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\n\t\t/*\n\t\t**\tMovement and animation.\n\t\t*/\n\t\tvoid Handle_Navigation_List(void);\n\t\tvoid Queue_Navigation_List(TARGET target);\n\t\tvoid Clear_Navigation_List(void);\n\t\tvirtual void Per_Cell_Process(PCPType why);\n\t\tvirtual void Approach_Target(void);\n\t\tvirtual void Fixup_Path(PathType *) {};\n\t\tvirtual void Set_Speed(int speed);\n\t\tvirtual MoveType Can_Enter_Cell(CELL cell, FacingType from=FACING_NONE) const;\n\t\tint Optimize_Moves(PathType *path, MoveType threshhold);\n\t\tvirtual void Override_Mission(MissionType mission, TARGET tarcom, TARGET navcom);\n\t\tvirtual bool Restore_Mission(void);\n\t\tCELL Adjust_Dest(CELL cell) const;\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n\n\t\tCELL Safety_Point(CELL src, CELL dst, int start, int max);\n\t\tint Rescue_Mission(TARGET tarcom);\n\n\tprivate:\n\t\tint Passable_Cell(CELL cell, FacingType face, int threat, MoveType threshhold);\n\t\tPathType * Find_Path(CELL dest, FacingType *final_moves, int maxlen, MoveType threshhold);\n\t\tvoid Debug_Draw_Map(char const * txt, CELL start, CELL dest, bool pause);\n\t\tvoid Debug_Draw_Path(PathType *path);\n\t\tbool Follow_Edge(CELL start, CELL target, PathType *path, FacingType search, FacingType olddir, int threat, int threat_stage, int max_cells, MoveType threshhold);\n\t\tbool Register_Cell(PathType *path, CELL cell, FacingType dir, int cost, MoveType threshhold);\n\t\tbool Unravel_Loop(PathType *path, CELL &cell, FacingType &dir, int sx, int sy, int dx, int dy, MoveType threshhold);\n\n\t\t/*\n\t\t**\tThis is the coordinate that the unit is heading to\n\t\t**\tas an immediate destination. This coordinate is never further\n\t\t**\tthan once cell (or track) from the unit's location. When this coordinate\n\t\t**\tis reached, then the next location in the path list becomes the\n\t\t**\tnext HeadTo coordinate.\n\t\t*/\n\t\tCOORDINATE HeadToCoord;\n};\n\n#endif\n\n\n"
  },
  {
    "path": "CODE/FOREIGN.TXT",
    "content": "For German version:\n\ncall the batch file GERMAN.BAT.  This will copy the appropriate conquer.h and\ncredits.txt files where they need to be, and set the proper network aliases\nfor drives S: and T:.  It also deletes all the object modules, and ends by\nbriefing up DEFINES.H.  You should comment out //#define ENGLISH and //#define\nFRENCH, and un-comment #define GERMAN.  Also, change the release flag to make\nsure that #define RELEASE_VERSION is the only version being made, and make\nsure that //#define DONGLE is commented out.\n\nMake sure that the german maps and such are all up to date, by copying the\nmaps to the directory GERMAPS, and then building the maps by calling\nMAKEGER.BAT EXPAND2.MIX and MAKEGER GENERAL.MIX.  If GENERAL changes, then\nyou also have to rebuild v:\\projects\\c&c0\\cstrike2\\cdger\\cd4\\main.mix.  If\nEXPAND2.MIX changes, you have to copy s:t\\m\\expand2.mix to the patch\ndirectory, f:\\projects\\c&c0\\setup\\aftermth\\patch\\german\\ra200.\n\nAfter building RA95.EXE and GAME.DAT, also copy them up to the patch\ndirectory.\n\nThe .MIX files that changed are MOVIES1, EXPAND2, SOUNDS, and GENERAL.  There\nmay have been others, but that's probably about it.\n\nNote, German version has several different art files, primarily removing\nblood from the infantry/civilians and removing some movies.  Also different\nis PIPS.ANM, with words for HOLD, READY, and PRIMARY.\n\n\n\nFor French version:\n\nFollow all the above steps, but substitute FRENCH.BAT and MAKEFRE.BAT.  The\nfinal destination directory is CDFRE instead of CDGER, of course, and the\npatch directory is FRENCH instead of GERMAN, again of course.\n\nIf MAKEFRE locks up processing sound files, use MAKER instead\nof MAKE.\n\nNote, French version uses most of the same art files.  Different\nis PIPS.ANM, with words for HOLD, READY, and PRIMARY.  Also different are all\nthe hi-res version's sidebar icons.  German has its own icons as well.\n\n"
  },
  {
    "path": "CODE/FTIMER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FTIMER.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FTIMER.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/16/95                                                     *\n *                                                                                             *\n *                  Last Update : July 6, 1996 [JLB]                                           *\n *                                                                                             *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BasicTimerClass<T>::BasicTimerClass -- Constructor for basic timer class.                 *\n *   BasicTimerClass<T>::operator () -- Function operator for timer object.                    *\n *   BasicTimerClass<T>::operator long -- Conversion to long operator.                         *\n *   BasicTimerClass<T>::~BasicTimerClass -- Destructor for basic timer object.                *\n *   TTimerClass<T>::Is_Active -- Checks to see if the timer is counting.                      *\n *   TTimerClass<T>::Start -- Starts (resumes) a stopped timer.                                *\n *   TTimerClass<T>::Stop -- Stops the current timer from incrementing.                        *\n *   TTimerClass<T>::TTimerClass -- Constructor for timer class object.                        *\n *   TTimerClass<T>::operator () -- Function operator for timer object.                        *\n *   TTimerClass<T>::operator long -- Conversion operator for timer object.                    *\n *   CDTimerClass<T>::CDTimerClass -- Constructor for count down timer.                        *\n *   CDTimerClass<T>::Is_Active -- Checks to see if the timer object is active.                *\n *   CDTimerClass<T>::Start -- Starts (resumes) the count down timer.                          *\n *   CDTimerClass<T>::Stop -- Stops (pauses) the count down timer.                             *\n *   CDTimerClass<T>::operator () -- Function operator for the count down timer.               *\n *   CDTimerClass<T>::operator long -- Conversion to long operator function.                   *\n *   CDTimerClass<T>::~CDTimerClass -- Destructor for the count down timer object.             *\n *   TTimerClass<T>::Value -- Returns with the current value of the timer.                     *\n *   CDTimerClass<T>::Value -- Fetches the current value of the countdown timer.               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FTIMER_H\n#define FTIMER_H\n\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\n/**********************************************************************\n**\tThis class is solely used as a parameter to a constructor that does\n**\tabsolutely no initialization to the object being constructed. By using\n**\tthis method, it is possible to load and save data directly from a\n**\tclass that has virtual functions. The construction process automatically\n**\ttakes care of initializing the virtual function table pointer and the\n**\trest of the constructor doesn't initialize any data members. After loading\n**\tinto a class object, simply perform an in-place new operation.\n*/\n#ifndef NOINITCLASS\n#define NOINITCLASS\nstruct NoInitClass {\n\tpublic:\n\t\tvoid operator () (void) const {};\n};\n#endif\n\n\n/*\n**\tThis is a timer class that watches a constant rate timer (specified by the parameter\n**\ttype class) and provides basic timer functionality. It is possible to set the start value\n**\tWITHOUT damaging or otherwise affecting any other timer that may be built upon the same\n**\tspecified timer class object. Treat an object of this type as if it were a \"magic\" integral\n**\tlong that automatically advances at the speed of the timer class object controlling it.\n*/\n// Let lint know that non-virtual destructor is OK for this class.\n//lint -esym(1509,BasicTimerClass)\ntemplate<class T>\nclass BasicTimerClass {\n \tpublic:\n\t\t// Constructor allows assignment as if class was integral 'long' type.\n\t\tBasicTimerClass(unsigned long set=0);\n\t\tBasicTimerClass(NoInitClass const & );\n\n\t\t~BasicTimerClass(void);\n\n\t\t// Fetch current value of timer.\n\t\tunsigned long Value(void) const;\n\n\t\t// Conversion operator to allow consistent treatment with integral types.\n\t\toperator unsigned long(void) const;\n\n\t\t// Function operator to allow timer object definition to be cascaded.\n\t\tunsigned long operator () (void) const;\n\n\tprotected:\n\t\tT Timer;\t\t\t// Timer regulator (ticks at constant rate).\n\t\tunsigned long Started;\t// Time started.\n};\n\n\ntemplate<class T>\ninline BasicTimerClass<T>::BasicTimerClass(NoInitClass const & )\n{\n}\n\n\n/***********************************************************************************************\n * BasicTimerClass<T>::BasicTimerClass -- Constructor for basic timer class.                   *\n *                                                                                             *\n *    This is the constructor for the basic timer class object. It sets the timer counting     *\n *    up from zero at the rate of the controlling timer class object.                          *\n *                                                                                             *\n * INPUT:   set   -- Alternate initial start value for the counter. If not specified, then     *\n *                   the timer is assumed to start at zero and count upwards.                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\n//lint -esym(1403,BasicTimerClass<class FrameTimerClass>::Timer)\n//lint -esym(1403,BasicTimerClass<class SystemTimerClass>::Timer)\ntemplate<class T>\ninline BasicTimerClass<T>::BasicTimerClass(unsigned long set) :\n\tStarted(Timer()-set)\n{\n}\n\n\n/***********************************************************************************************\n * BasicTimerClass<T>::~BasicTimerClass -- Destructor for basic timer object.                  *\n *                                                                                             *\n *    The destructor for the basic timer object doesn't have to do anything.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline BasicTimerClass<T>::~BasicTimerClass(void)\n{\n}\n\n\ntemplate<class T>\ninline unsigned long BasicTimerClass<T>::Value(void) const\n{\n\treturn(Timer()-Started);\n}\n\n\n/***********************************************************************************************\n * BasicTimerClass<T>::operator long -- Conversion to long operator.                           *\n *                                                                                             *\n *    This conversion operator allows the basic timer object to function in much the same      *\n *    manner as the integral \"long\" type. One can assign a long with a timer object and the    *\n *    actual value of the timer is extracted from the object and used.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the timer value expressed as a long.                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline BasicTimerClass<T>::operator unsigned long(void) const\n{\n\treturn(Timer()-Started);\n}\n\n\n/***********************************************************************************************\n * BasicTimerClass<T>::operator () -- Function operator for timer object.                      *\n *                                                                                             *\n *    This function operator allows the timer to also serve as the parameter type class for    *\n *    additional timer objects. This allows one to instantiate a controlling timer class that  *\n *    can control (e.g., turn on or off) all timers that are based upon it.                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the current timer value expressed as a long.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline unsigned long BasicTimerClass<T>::operator () (void) const\n{\n\treturn(Timer()-Started);\n}\n\n\n/*\n**\tThis timer class functions similarly to the basic timer class. In addition to the\n**\tnormal timer operation, this class has the ability to be stopped and started at\n**\twill. If you have no need to start or stop the timer, then use the basic timer\n**\tclass instead.\n*/\ntemplate<class T>\nclass TTimerClass : public BasicTimerClass<T> {\n \tpublic:\n\t\t// Constructor allows assignment as if class was integral 'long' type.\n\t\tTTimerClass(unsigned long set=0);\n\t\tTTimerClass(NoInitClass const & x);\n\n\t\t~TTimerClass(void) {};\n\n\t\t// Fetches current value of timer.\n\t\tunsigned long Value(void) const;\n\n\t\t// Conversion operator to allow consistent treatment with integral types.\n\t\toperator unsigned long(void) const;\n\n\t\t// Function operator to allow timer object definition to be cascaded.\n\t\tunsigned long operator () (void) const;\n\n\t\t// Stops (pauses) the timer.\n\t\tvoid Stop(void);\n\n\t\t// Starts (resumes) the timer.\n\t\tvoid Start(void);\n\n\t\t// Queries whether the timer is currently active.\n\t\tbool Is_Active(void) const;\n\n\tprivate:\n\t\tunsigned long Accumulated;\t\t\t\t//\tTotal accumulated ticks.\n};\n\n\ntemplate<class T>\ninline TTimerClass<T>::TTimerClass(NoInitClass const & x) :\n\tBasicTimerClass<T>(x)\n{\n}\n\n\n/***********************************************************************************************\n * TTimerClass<T>::TTimerClass -- Constructor for timer class object.                          *\n *                                                                                             *\n *    This is the constructor for the advanced timer class object. This object class can start *\n *    or stop the timer under user control.                                                    *\n *                                                                                             *\n * INPUT:   set   -- The initial value to set the timer to. If no value is specified, then     *\n *                   the timer is assumed to start from zero.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline TTimerClass<T>::TTimerClass(unsigned long set) :\n\tBasicTimerClass<T>(set),\n\tAccumulated(0)\n{\n}\n\n\n/***********************************************************************************************\n * TTimerClass<T>::Value -- Returns with the current value of the timer.                       *\n *                                                                                             *\n *    This routine will return with the current value of the timer. It takes into account      *\n *    whether the timer has stopped or not so as to always return the correct value regardless *\n *    of that condition.                                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current value of the timer.                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline unsigned long TTimerClass<T>::Value(void) const\n{\n\tunsigned long value = Accumulated;\n\tif (Started != 0xFFFFFFFFU) {\n\t\tvalue += BasicTimerClass<T>::Value();\n\t}\n\treturn(value);\n}\n\n\n/***********************************************************************************************\n * TTimerClass<T>::operator long -- Conversion operator for timer object.                      *\n *                                                                                             *\n *    This conversion operator allows this timer object to function as an \"rvalue\" of a \"long\" *\n *    type. This is consistent with the integral \"long\" value. It is possible to assign a      *\n *    timer object to a long and have the long initialized with the current value of the       *\n *    timer.                                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current time value expressed as a long.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline TTimerClass<T>::operator unsigned long(void) const\n{\n\tunsigned long value = Accumulated;\n\tif (Started != 0xFFFFFFFFU) {\n\t\tvalue += BasicTimerClass<T>::Value();\n\t}\n\treturn(value);\n}\n\n\n/***********************************************************************************************\n * TTimerClass<T>::operator () -- Function operator for timer object.                          *\n *                                                                                             *\n *    This function operator for the timer class allows this timer class to be used as the     *\n *    template parameter for other timer class objects. With this ability, one can control     *\n *    several timers (e.g., start or stop them) by using a single controlling timer class      *\n *    that other timers are instantiated from.                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current time expressed as a long.                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline unsigned long TTimerClass<T>::operator () (void) const\n{\n\tunsigned long value = Accumulated;\n\tif (Started != 0xFFFFFFFFU) {\n\t\tvalue += BasicTimerClass<T>::Value();\n\t}\n\treturn(value);\n}\n\n\n/***********************************************************************************************\n * TTimerClass<T>::Stop -- Stops the current timer from incrementing.                          *\n *                                                                                             *\n *    This routine will stop (pause) the timer from further increments. To cause the timer     *\n *    to begin anew, call the Start() function.                                                *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid TTimerClass<T>::Stop(void)\n{\n\tif (Started != 0xFFFFFFFFU) {\n\t\tAccumulated += BasicTimerClass<T>::operator unsigned long();\n\t\tStarted = 0xFFFFFFFFU;\n\t}\n}\n\n\n/***********************************************************************************************\n * TTimerClass<T>::Start -- Starts (resumes) a stopped timer.                                  *\n *                                                                                             *\n *    This routine will resume a timer that was previously stopped with the Stop() function.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid TTimerClass<T>::Start(void)\n{\n\tif (Started == 0xFFFFFFFFU) {\n\t\tStarted = Timer();\n\t}\n}\n\n\n/***********************************************************************************************\n * TTimerClass<T>::Is_Active -- Checks to see if the timer is counting.                        *\n *                                                                                             *\n *    Since this timer can be paused, this routine is used to examine the timer to see if it   *\n *    is currently paused or active. If the timer is active, then the return value will be     *\n *    true.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is this timer currently active?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline bool TTimerClass<T>::Is_Active(void) const\n{\n\treturn(Started != 0xFFFFFFFFU);\n}\n\n\n/*\n**\tThis timer counts down from the specified (or constructed) value down towards zero.\n**\tThe countdown rate is controlled by the timer object specified. This timer object can\n**\tbe started or stopped. It can also be tested to see if it has expired or not. An expired\n**\tcount down timer is one that has value of zero. You can treat this class object as if it\n**\twere an integral \"magic\" long that automatically counts down toward zero.\n*/\ntemplate<class T>\nclass CDTimerClass : public BasicTimerClass<T> {\n\tpublic:\n\t\t// Constructor allows assignment as if class was integral 'long' type.\n\t\tCDTimerClass(unsigned long set=0);\n\t\tCDTimerClass(NoInitClass const & x);\n\n\t\t~CDTimerClass(void);\n\n\t\t// Fetches current value of count down timer.\n\t\tunsigned long Value(void) const;\n\n\t\t// Conversion operator to allow consistent treatment with integral types.\n\t\toperator unsigned long(void) const;\n\n\t\t// Function operator to allow timer object definition to be cascaded.\n\t\tunsigned long operator () (void) const;\n\n\t\t// Stops (pauses) the timer.\n\t\tvoid Stop(void);\n\n\t\t// Starts (resumes) the timer.\n\t\tvoid Start(void);\n\n\t\t// Queries whether the timer is currently active.\n\t\tbool Is_Active(void) const;\n\n\tprivate:\n\t\tunsigned long DelayTime;\t\t\t// Ticks remaining before countdown timer expires.\n};\n\n\ntemplate<class T>\ninline CDTimerClass<T>::CDTimerClass(NoInitClass const & x) :\n\tBasicTimerClass<T>(x)\n{\n}\n\n\n/***********************************************************************************************\n * CDTimerClass<T>::CDTimerClass -- Constructor for count down timer.                          *\n *                                                                                             *\n *    This is the constructor for the count down timer object. The optional starting value     *\n *    can be used to initiate the timer. Because of this constructor it is possible to assign  *\n *    a long to a count down timer object in order to begin the countdown process.             *\n *                                                                                             *\n * INPUT:   set   -- The initial starting value for the countdown timer.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline CDTimerClass<T>::CDTimerClass(unsigned long set) :\n\tBasicTimerClass<T>(0),\n\tDelayTime(set)\n{\n}\n\n\n/***********************************************************************************************\n * CDTimerClass<T>::~CDTimerClass -- Destructor for the count down timer object.               *\n *                                                                                             *\n *    The destructor for the count down timer object does nothing.                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline CDTimerClass<T>::~CDTimerClass(void)\n{\n}\n\n\n/***********************************************************************************************\n * CDTimerClass<T>::Value -- Fetches the current value of the countdown timer.                 *\n *                                                                                             *\n *    Use this routine to fetch the current value of the timer. It takes into consideration    *\n *    whether the timer has been stopped or not. It returns the correct value regardless of    *\n *    this condition.                                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the correct value of this count down timer.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline unsigned long CDTimerClass<T>::Value(void) const\n{\n\tunsigned long remain = DelayTime;\n\tif (Started != 0xFFFFFFFFU) {\n\t\tunsigned long value = BasicTimerClass<T>::Value();\n\t\tif (value < remain) {\n\t\t\treturn(remain - value);\n\t\t} else {\n\t\t\treturn(0);\n\t\t}\n\t}\n\treturn(remain);\n}\n\n\n/***********************************************************************************************\n * CDTimerClass<T>::operator long -- Conversion to long operator function.                     *\n *                                                                                             *\n *    This conversion operator allows the count down timer object to be used as if it were     *\n *    a \"magic\" long that automatically counted downward at the controller class tick rate.    *\n *    The count down object can be used in any place that an rvalue long could be used.        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current count down time expressed in the form of a long value.    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline CDTimerClass<T>::operator unsigned long(void) const\n{\n\tunsigned long remain = DelayTime;\n\tif (Started != 0xFFFFFFFFU) {\n\t\tunsigned long value = BasicTimerClass<T>::Value();\n\t\tif (value < remain) {\n\t\t\treturn(remain - value);\n\t\t} else {\n\t\t\treturn(0);\n\t\t}\n\t}\n\treturn(remain);\n}\n\n\n/***********************************************************************************************\n * CDTimerClass<T>::operator () -- Function operator for the count down timer.                 *\n *                                                                                             *\n *    This is the function operator for the count down timer object. By supporting this        *\n *    function operator, this class (or one derived from this class) could be used as the      *\n *    controlling timer to the timer templates.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current count down time expressed in the form of a long.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline unsigned long CDTimerClass<T>::operator () (void) const\n{\n\tunsigned long remain = DelayTime;\n\tif (Started != 0xFFFFFFFFU) {\n\t\tunsigned long value = BasicTimerClass<T>::Value();\n\t\tif (value < remain) {\n\t\t\treturn(remain - value);\n\t\t} else {\n\t\t\treturn(0);\n\t\t}\n\t}\n\treturn(remain);\n}\n\n\n/***********************************************************************************************\n * CDTimerClass<T>::Stop -- Stops (pauses) the count down timer.                               *\n *                                                                                             *\n *    This routine is used to stop (pause) the count down timer object. A timer object paused  *\n *    in this fashion will be resumed by a call to Start() or by assigning a new count down    *\n *    value to the timer.                                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid CDTimerClass<T>::Stop(void)\n{\n\tif (Started != 0xFFFFFFFFU) {\n\t\tDelayTime = *this;\n\t\tStarted = 0xFFFFFFFFU;\n\t}\n}\n\n\n/***********************************************************************************************\n * CDTimerClass<T>::Start -- Starts (resumes) the count down timer.                            *\n *                                                                                             *\n *    This routine is used to start (resume) the count down timer that was previously stopped  *\n *    with the Stop() function. The timer will also resume when a new timer value is assigned. *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid CDTimerClass<T>::Start(void)\n{\n\tif (Started == 0xFFFFFFFFU) {\n\t\tStarted = Timer();\n\t}\n}\n\n\n/***********************************************************************************************\n * CDTimerClass<T>::Is_Active -- Checks to see if the timer object is active.                  *\n *                                                                                             *\n *    Because the timer object counting can be stopped, this routine is used to determine      *\n *    if the timer is currently paused or active.                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the timer currently active?                                               *\n *                                                                                             *\n * WARNINGS:   Note that if the timer has counted down to zero, then it may be active, but     *\n *             the value will, naturally, not change.                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline bool CDTimerClass<T>::Is_Active(void) const\n{\n\treturn(Started != 0xFFFFFFFFU);\n}\n\n#endif\n"
  },
  {
    "path": "CODE/FUNCTION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FUNCTION.H 2     3/13/97 2:05p Steve_tall $*/\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FUNCTION.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 27, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 27, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FUNCTION_H\n#define FUNCTION_H\n\n/*\n**\t!!!DEFINE!!!  \"NDEBUG\" if the assertion code is to be !!!REMOVED!!! from the project.\n*/\n#define\tNDEBUG\n\n#pragma warn -hid\n\n#ifdef NEVER\nMap (screen) class heirarchy.\n\n MapeditClass (most derived class) -- scenario editor\n        \n   MouseClass -- handles mouse animation and display control\n        \n  ScrollClass -- map scroll handler\n        \n    HelpClass -- pop-up help text handler\n        \n     TabClass -- file folder tab screen mode control dispatcher\n        \n SidebarClass -- displays and controls construction list sidebar\n        \n   PowerClass -- display power production/consumption bargraph\n        \n   RadarClass -- displays and controls radar map\n        \n DisplayClass -- general tactical map display handler\n        \n     MapClass -- general tactical map data handler\n        \n GScreenClass (pure virtual base class) -- generic screen control\n\n                          AbstractClass\n                                  \n                                  \n                                  \n                                  \n                            ObjectClass\n                                  \n       Ŀ\n   AnimClass    TemplateClass             FuseClass         TerrainClass\n                                          FlyClass      \n                                   BulletClass            \n       OverlayClass        MissionClass               SmudgeClass\n                                  \n                             RadioClass\n                                  \n                                   CrewClass\n                                   FlasherClass\n                                   StageClass\n                                   CargoClass\n                            TechnoClass\n                                  \n                       Ŀ\n                   FootClass                           BuildingClass\n                       \n         Ŀ\n    DriveClass  InfantryClass          FlyClass\n                               AircraftClass\n       Ŀ\n                  \n            VesselClass\n       \n    UnitClass\n\n\n                            AbstractTypeClass\n                                    \n                              ObjectTypeClass\n                                    \n             Ŀ\n                                                                \n       TechnoTypeClass                                           \n                             BulletTypeClass                     \n                                        TemplateTypeClass         \n    Ŀ    TerrainTypeClass\n                                                   \nUnitTypeClass         BuildingTypeClass        VesselTypeClass\n                                             \n           AircraftTypeClass          InfantryTypeClass\n#endif\n\n\n#include\t\"watcom.h\"\n#include \"lint.h\"\n\n\n#ifdef WIN32\n//#define WIN32_LEAN_AND_MEAN\n#include\t<windows.h>\n#define WWFILE_H\n#define RAWFILE_H\n#define MONOC_H\n\n#define\t_MAX_NAME\t_MAX_FNAME\n\n#endif\n\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ comittee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\n#ifndef BITMAPCLASS\n#define BITMAPCLASS\nclass BitmapClass\n{\n\tpublic:\n\t\tBitmapClass(int w, int h, unsigned char * data) :\n\t\t\tWidth(w), Height(h), Data(data) {};\n\n\t\tint Width;\n\t\tint Height;\n\t\tunsigned char * Data;\n};\n\nclass TPoint2D\n{\n\tpublic:\n\t\tTPoint2D(int xx, int yy) : x(xx), y(yy) {};\n\t\tTPoint2D(void) : x(0), y(0) {};\n\n\t\tint x;\n\t\tint y;\n};\n#endif\n\n\n/**********************************************************************\n**\tThis class is solely used as a parameter to a constructor that does\n**\tabsolutely no initialization to the object being constructed. By using\n**\tthis method, it is possible to load and save data directly from a\n**\tclass that has virtual functions. The construction process automatically\n**\ttakes care of initializing the virtual function table pointer and the\n**\trest of the constructor doesn't initialize any data members. After loading\n**\tinto a class object, simply perform an in-place new operation.\n*/\n#ifndef NOINITCLASS\n#define NOINITCLASS\nstruct NoInitClass {\n\tpublic:\n\t\tvoid operator () (void) const {};\n};\n#endif\n\n\n#define FILE_H\n#define WWMEM_H\n\n#ifndef WIN32\n#define TIMER_H\n#endif\n\n#ifdef WIN32\n#include\t\"key.h\"\n#endif\n\n#include <wwlib32.h>\n#include\t\"mpu.h\"\n#include\t\"bench.h\"\n#include\t\"rect.h\"\n#include\t\"jshell.h\"\n#include\t\"buff.h\"\n#include\t\"face.h\"\n#include\t\"random.h\"\n#include\t\"crc.h\"\n#include \"compat.h\"\n#include\t\"fixed.h\"\n#include\t\"base64.h\"\n#include\t\"pipe.h\"\n#include\t\"xpipe.h\"\n#include\t\"ramfile.h\"\n#include\t\"lcw.h\"\n#include\t\"lzw.h\"\n#include\t\"lcwpipe.h\"\n#include\t\"lzwpipe.h\"\n#include\t\"lzopipe.h\"\n#include\t\"crcpipe.h\"\n#include\t\"shapipe.h\"\n#include\t\"b64pipe.h\"\n#include\t\"straw.h\"\n#include\t\"xstraw.h\"\n#include\t\"b64straw.h\"\n#include\t\"lcwstraw.h\"\n#include\t\"lzwstraw.h\"\n#include\t\"lzostraw.h\"\n#include\t\"crcstraw.h\"\n#include\t\"shastraw.h\"\n#include\t\"rndstraw.h\"\n\n// Should be part of WWLIB.H. This is used in JSHELL.CPP.\ntypedef struct {\n\tunsigned char\tSourceColor;\n\tunsigned char\tDestColor;\n\tunsigned char\tFading;\n\tunsigned char\treserved;\n} TLucentType;\n\n\n#include\t<string.h>\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<stddef.h>\n#include\t<mem.h>\n#include\t<dos.h>\n#include\t<direct.h>\n#include\t<stdarg.h>\n#include\t<ctype.h>\n#include\t<assert.h>\n#include\t<process.h>\n#include\t<new.h>\n\n\n\n#ifdef WIN32\n#define\tint386x(a,b,c,d)\t0\n#define\tint386(a,b,c)\t0\n#endif\n\n\n/*\n**\tVQ player specific includes.\n*/\n#include <vqa32\\vqaplay.h>\n#include <vqa32\\vqafile.h>\n\nextern bool GameActive;\nextern long LParam;\n\n#include\t<assert.h>\n#include\t\"vector.h\"\n#include\t\"heap.h\"\n#include\t\"ccfile.h\"\n#include\t\"monoc.h\"\n#include\t\"conquer.h\"\n#include\t\"debug.h\"\n#include \"special.h\"\n#include\t\"defines.h\"\n#include\t\"ccini.h\"\n#include\t\"ccptr.h\"\n#include\t\"bar.h\"\n\n/*\n**\tGreenleaf specific includes.\n*/\n#include <modem.h>\n#include <fast.h>\n\n\nextern long Frame;\nCELL Coord_Cell(COORDINATE coord);\n\n#include\t\"utracker.h\"\n#include\t\"crate.h\"\n#include\t\"rules.h\"\n#include\t\"ini.h\"\n#include\t\"int.h\"\n#include\t\"pk.h\"\n#include\t\"pkpipe.h\"\n#include\t\"pkstraw.h\"\n#include\t\"sha.h\"\n#include\t\"blowfish.h\"\n#include\t\"blowpipe.h\"\n#include\t\"blwstraw.h\"\n#include\t\"language.h\"\n#include\t\"hsv.h\"\n#include\t\"rgb.h\"\n#include\t\"palette.h\"\n#include \"version.h\"\n#include\t\"facing.h\"\n#include\t\"ftimer.h\"\n#include\t\"theme.h\"\n#include\t\"link.h\"\n#include\t\"gadget.h\"\n#include\t\"control.h\"\n#include\t\"toggle.h\"\n#include\t\"checkbox.h\"\n#include\t\"shapebtn.h\"\n#include\t\"textbtn.h\"\n#include\t\"statbtn.h\"\n#include\t\"slider.h\"\n#include \"list.h\"\n#include\t\"drop.h\"\n#include \"cheklist.h\"\n#include \"colrlist.h\"\n#include\t\"edit.h\"\n#include\t\"gauge.h\"\n#include\t\"msgbox.h\"\n#include\t\"dial8.h\"\n#include\t\"txtlabel.h\"\n#include \"loaddlg.h\"\n#include\t\"super.h\"\n#include\t\"house.h\"\n#include\t\"gscreen.h\"\n#include\t\"map.h\"\n#include\t\"display.h\"\n#include\t\"radar.h\"\n#include\t\"power.h\"\n#include\t\"sidebar.h\"\n#include\t\"tab.h\"\n#include\t\"help.h\"\n#include\t\"mouse.h\"\n#include\t\"help.h\"\n#include\t\"target.h\"\n#include\t\"theme.h\"\n#include\t\"team.h\"\t\t\t\t// Team objects.\n#include\t\"warhead.h\"\n#include\t\"weapon.h\"\n#include\t\"trigtype.h\"\n#include\t\"teamtype.h\"\t\t// Team type objects.\n#include\t\"taction.h\"\n#include\t\"tevent.h\"\n#include\t\"trigger.h\"\t\t\t// Trigger event objects.\n#include\t\"mapedit.h\"\t\t\t// map editor class\n#include\t\"abstract.h\"\n#include \"object.h\"\n#include \"mission.h\"\n#include\t\"door.h\"\n#include\t\"bullet.h\"\t\t\t// Bullet objects.\n#include\t\"terrain.h\"\t\t\t// Terrain objects.\n#include\t\"anim.h\"\t\t\t\t// Animation objects.\n#include\t\"template.h\"\t\t// Icon template objects.\n#include\t\"overlay.h\"\t\t\t// Overlay objects.\n#include\t\"smudge.h\"\t\t\t// Stains on the terrain objects.\n#include\t\"aircraft.h\"\t\t// Aircraft objects.\n#include\t\"unit.h\"\t\t\t\t// Ground unit objects.\n#include \"vessel.h\"\t\t\t// Sea unit objects.\n#include\t\"infantry.h\"\t\t// Infantry objects.\n#include\t\"credits.h\"\t\t\t// Credit counter class.\n#include\t\"score.h\"\t\t\t// Scoring system class.\n#include\t\"factory.h\"\t\t\t// Production manager class.\n#include \"intro.h\"\n#include \"ending.h\"\n#include\t\"logic.h\"\n#include\t\"queue.h\"\n#include\t\"event.h\"\n#include \"base.h\"\t\t\t\t// defines the AI's pre-built base\n#include\t\"carry.h\"\n#include\t\"scenario.h\"\n#include \"msglist.h\"\t\t\t// Multiplayer chat message system\n#include \"session.h\"\t\t\t// Multiplayer session class\n#include \"phone.h\"\t\t\t// Phone list manager\n#include \"ipxmgr.h\"\t\t\t// IPX connection manager\n#include\t\"nullmgr.h\"\t\t\t// Modem connection manager\n#include\t\"readline.h\"\n#include\t\"vortex.h\"\n#include \"egos.h\"\n#ifdef WIN32\n#include\t\"pcx.h\"\n#endif\n\n#if(TEN)\n#include \"tenmgr.h\"\n#endif\n\n#if(MPATH)\n#ifdef WIN32\n#include \"mpmgrw.h\"\n#else\n#include \"mpmgrd.h\"\n#endif\n#endif\n\n// Denzil 5/18/98 - Mpeg movie playback\n#ifdef MPEGMOVIE\nbool InitDDraw(void);\nbool PlayMpegMovie(const char* name);\n#endif\n\n#include\t\"externs.h\"\n\n\nextern int Get_CD_Drive(void);\nextern void Fatal(char const *message, ...);\n\n#ifdef WIN32\n\n/*\n** For WIN32, replace the assert macro so we get an error on the debugger screen\n**  where we can see it.\n**\n*/\n#ifndef __BORLANDC__\n#ifdef assert\n#undef assert\n#endif\t//assert\nvoid Assert_Failure (char *expression, int line, char *file);\n\n#ifdef NDEBUG\n #define assert(__ignore) ((void)0)\n#else\n #define assert(expr)   ((expr)?(void)0:Assert_Failure(#expr,__LINE__,__FILE__))\n#endif\t//NDEBUG\n\n#endif\t//__BORLANDC__\n\n\nextern void Free_Interpolated_Palettes(void);\nextern int Load_Interpolated_Palettes(char const *filename, BOOL add=FALSE);\nextern void Rebuild_Interpolated_Palette(unsigned char *interpal);\nextern void Interpolate_2X_Scale( GraphicBufferClass *source, GraphicViewPortClass *dest ,char const *palette_file_name);\nvoid Increase_Palette_Luminance (unsigned char *palette , int red_percentage , int green_percentage , int blue_percentage ,int cap);\n#endif\n\n/*\n**\tADATA.CPP\n*/\nchar const * Anim_Name(AnimType anim);\n\n/*\n**\tAIRCRAFT.CPP\n*/\nbool Building_Check(void);\n\n/*\n**\tANIM.CPP\n*/\nvoid Shorten_Attached_Anims(ObjectClass * obj);\nAnimType Anim_From_Name(char const * name);\n\n/*\n**\tAUDIO.CPP\n*/\nVocType Voc_From_Name(char const * name);\nchar const * Speech_Name(VoxType speech);\nchar const * Voc_Name(VocType voc);\nint Sound_Effect(VocType voc, fixed volume=1, int variation=1, signed short panvalue=0, HousesType house=HOUSE_NONE);\nvoid Speak(VoxType voice);\nvoid Speak_AI(void);\nvoid Stop_Speaking(void);\nvoid Sound_Effect(VocType voc, COORDINATE coord, int variation=1, HousesType house=HOUSE_NONE);\nbool Is_Speaking(void);\n\n/*\n**\tCDFILE.CPP\n*/\n#ifdef WIN32\nint harderr_handler(unsigned, unsigned, unsigned *);\n#else\nint harderr_handler(unsigned, unsigned, unsigned __far *);\n#endif\n\n/*\n**\tCOMBAT.CPP\n*/\nint Modify_Damage(int damage, WarheadType warhead, ArmorType armor, int distance);\nvoid Explosion_Damage(COORDINATE coord, int strength, TechnoClass * source, WarheadType warhead);\nAnimType Combat_Anim(int damage, WarheadType warhead, LandType land);\nvoid Wide_Area_Damage(COORDINATE coord, LEPTON radius, int damage, TechnoClass * source, WarheadType warhead);\n\n/*\n**\tCONQUER.CPP\n*/\nvoid List_Copy(short const * source, int len, short * dest);\nint Get_CD_Index (int cd_drive, int timeout);\nint Owner_From_Name(char const * text);\nCrateType Crate_From_Name(char const * name);\nRect const Shape_Dimensions(void const * shapedata, int shapenum);\nvoid IPX_Call_Back(void);\nbool Is_Counterstrike_Installed (void);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nbool Is_Aftermath_Installed (void);\n#endif\n\n\n#if(TEN)\nvoid Ten_Call_Back(void);\n#endif\t// TEN\n\n#if(MPATH)\nvoid MPATH_Call_Back(void);\n#endif\t// MPATH\n\nvoid Center_About_Objects(void);\nbool Force_CD_Available(int cd);\nvoid Handle_View(int view, int action=0);\nvoid Handle_Team(int team, int action=0);\nTechnoTypeClass const * Fetch_Techno_Type(RTTIType type, int id);\nchar const * Fading_Table_Name(char const * base, TheaterType theater);\nvoid Unselect_All(void);\nvoid Play_Movie(char const * name, ThemeType theme=THEME_NONE, bool clrscrn=true);\nvoid Play_Movie(VQType name, ThemeType theme=THEME_NONE, bool clrscrn=true);\nbool Main_Loop(void);\nTheaterType Theater_From_Name(char const * name);\nvoid Main_Game(int argc, char * argv[]);\nlong VQ_Call_Back(unsigned char * buffer=NULL, long frame=0);\nvoid Call_Back(void);\nchar const *Language_Name(char const * basename);\nSourceType Source_From_Name(char const * name);\nchar const *Name_From_Source(SourceType source);\nFacingType KN_To_Facing(int input);\nvoid const *Get_Radar_Icon(void const * shapefile, int shapenum, int frames, int zoomfactor);\nvoid CC_Draw_Shape(void const * shapefile, int shapenum, int x, int y, WindowNumberType window, ShapeFlags_Type flags, void const * fadingdata=0, void const * ghostdata=0, DirType rotation=DIR_N, long scale=0x0100);\nvoid Go_Editor(bool flag);\nlong MixFileHandler(VQAHandle * vqa, long action, void * buffer, long nbytes);\nchar *CC_Get_Shape_Filename(void const * shapeptr );\nvoid CC_Add_Shape_To_Global(void const * shapeptr, char * filename, char code );\nvoid Bubba_Print(char * format,...);\nvoid Heap_Dump_Check(char * string );\nvoid Dump_Heap_Pointers(void);\nunsigned long Disk_Space_Available(void);\nvoid * Hires_Load(char * name);\nvoid Shake_The_Screen(int shakes);\n\n/*\n**\tCOORD.CPP\n*/\nshort const * Coord_Spillage_List(COORDINATE coord, Rect const & rect, bool nocenter=true);\nvoid Normal_Move_Point(short &x, short &y, register DirType dir, unsigned short distance);\nvoid Move_Point(short &x, short &y, register DirType dir, unsigned short distance);\nCOORDINATE Coord_Move(COORDINATE start, DirType facing, unsigned short distance);\nCOORDINATE Coord_Scatter(COORDINATE coord, unsigned distance, bool lock=false);\nDirType Direction(CELL cell1, CELL cell2);\nDirType Direction(COORDINATE coord1, COORDINATE coord2);\nDirType Direction256(COORDINATE coord1, COORDINATE coord2);\nDirType Direction8(COORDINATE coord1, COORDINATE coord2);\nint Distance(COORDINATE coord1, COORDINATE coord2);\nint Distance(TARGET target1, TARGET target2);\nshort const * Coord_Spillage_List(COORDINATE coord, int maxsize);\n\n/*\n**\tDEBUG.CPP\n*/\nvoid Log_Event(char const *text, ...);\nvoid Debug_Key(unsigned input);\nvoid Self_Regulate(void);\n\n/*\n**\tDIALOG.CPP\n*/\nvoid Draw_Caption(int text, int x, int y, int w);\nvoid Draw_Caption(char const * text, int x, int y, int w);\nint Format_Window_String(char * string, int maxlinelen, int & width, int & height);\nextern void Dialog_Box(int x, int y, int w, int h);\nvoid Conquer_Clip_Text_Print(char const *, unsigned x, unsigned y, RemapControlType * fore, unsigned back=(unsigned)TBLACK, TextPrintType flag=TPF_8POINT|TPF_DROPSHADOW, int width=-1, int const * tabs=0);\nvoid Draw_Box(int x, int y, int w, int h, BoxStyleEnum up, bool filled);\nint cdecl Dialog_Message(char *errormsg, ...);\nvoid Window_Box(WindowNumberType window, BoxStyleEnum style);\nvoid Fancy_Text_Print(char const *text, unsigned x, unsigned y, RemapControlType * fore, unsigned back, TextPrintType flag, ...);\nvoid Fancy_Text_Print(int text, unsigned x, unsigned y, RemapControlType * fore, unsigned back, TextPrintType flag, ...);\nvoid Simple_Text_Print(char const *text, unsigned x, unsigned y, RemapControlType * fore, unsigned back, TextPrintType flag);\nvoid Plain_Text_Print(int text, unsigned x, unsigned y, unsigned fore, unsigned back, TextPrintType flag, ...);\nvoid Plain_Text_Print(char const *text, unsigned x, unsigned y, unsigned fore, unsigned back, TextPrintType flag, ...);\n\n/*\n**\tDISPLAY.CPP\n*/\n\n/*\n**\tENDING.CPP\n*/\nvoid GDI_Ending(void);\nvoid Nod_Ending(void);\n\n/*\n**\tEXPAND.CPP\n*/\nbool Expansion_Present(void);\nbool Expansion_Dialog(void);\nbool Expansion_CS_Present(void);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nbool Expansion_AM_Present(void);\n#endif\n/*\n**\tFINDPATH.CPP\n*/\nint Optimize_Moves(PathType *path, int (*callback)(CELL, FacingType), int threshhold);\n\n/*\n**\tGOPTIONS.CPP\n*/\n\n/*\n**\tINI.CPP\n*/\nvoid Write_Scenario_INI(char *root);\nbool Read_Scenario_INI(char *root, bool fresh=true);\nint Scan_Place_Object(ObjectClass *obj, CELL cell);\nvoid Assign_Houses(void);\n\n/*\n**\tINIBIN.CPP\n*/\nunsigned long Ini_Binary_Version( void );\nbool Read_Scenario_INB( CCFileClass *file, char *root, bool fresh );\nbool Valid_Scenario_INB( CCFileClass *file );\n\n/*\n**\tINICODE.CPP\n*/\nbool Read_Scenario_INI_Write_INB( char *root, bool fresh );\n\n/*\n**\tINIT.CPP\n*/\nvoid Load_Title_Page(bool visible=false);\nlong Obfuscate(char const * string);\nvoid Anim_Init(void);\nbool Init_Game(int argc, char *argv[]);\nbool Select_Game(bool fade = false);\nbool Parse_Command_Line(int argc, char *argv[]);\nvoid Parse_INI_File(void);\n\n/*\n** INTERPAL.CPP\n*/\n#define SIZE_OF_PALETTE 256\nextern\t\"C\" unsigned char *InterpolationPalette;\nextern\tBOOL\tInterpolationPaletteChanged;\nextern\tvoid \tInterpolate_2X_Scale( GraphicBufferClass *source, GraphicViewPortClass *dest ,char const *palette_file_name);\nvoid Read_Interpolation_Palette (char const *palette_file_name);\nvoid Write_Interpolation_Palette (char const *palette_file_name);\nvoid Increase_Palette_Luminance(unsigned char *InterpolationPalette ,\tint RedPercentage ,int GreenPercentage ,int BluePercentage ,int cap);\nextern \"C\"{\n\textern unsigned char PaletteInterpolationTable[SIZE_OF_PALETTE][SIZE_OF_PALETTE];\n\textern unsigned char *InterpolationPalette;\n\tvoid __cdecl Asm_Create_Palette_Interpolation_Table(void);\n}\n\n/*\n** JSHELL.CPP\n*/\nint Load_Picture(char const *filename, BufferClass& scratchbuf, BufferClass& destbuf, unsigned char *palette, PicturePlaneType format);\nvoid * Conquer_Build_Fading_Table(PaletteClass const & palette, void *dest, int color, int frac);\nvoid * Small_Icon(void const * iconptr, int iconnum);\nvoid Set_Window(int window, int x, int y, int w, int h);\nvoid * Load_Alloc_Data(FileClass &file);\nlong Load_Uncompress(FileClass &file, BuffType &uncomp_buff, BuffType &dest_buff, void *reserved_data);\nlong Translucent_Table_Size(int count);\nvoid *Build_Translucent_Table(PaletteClass const & palette, TLucentType const *control, int count, void *buffer);\nvoid *Conquer_Build_Translucent_Table(PaletteClass const & palette, TLucentType const *control, int count, void *buffer);\nvoid * Make_Fading_Table(PaletteClass const & palette, void * dest, int color, int frac);\n\n/*\n**\tKEYFBUFF.ASM\n*/\nextern \"C\" {\n\tlong __cdecl Buffer_Frame_To_Page(int x, int y, int w, int h, void *Buffer, GraphicViewPortClass &view, int flags, ...);\n}\n\n/*\n**\tKEYFRAME.CPP\n*/\nunsigned long Build_Frame(void const *dataptr, unsigned short framenumber, void *buffptr);\nunsigned short Get_Build_Frame_Count(void const *dataptr);\nunsigned short Get_Build_Frame_X(void const *dataptr);\nunsigned short Get_Build_Frame_Y(void const *dataptr);\nunsigned short Get_Build_Frame_Width(void const *dataptr);\nunsigned short Get_Build_Frame_Height(void const *dataptr);\nbool Get_Build_Frame_Palette(void const *dataptr, void *palette);\n\n/*\n**\tMAP.CPP\n*/\nint Terrain_Cost(CELL cell, FacingType facing);\nint Coord_Spillage_Number(COORDINATE coord, int maxsize);\n\n/*\n**\tMENUS.CPP\n*/\nvoid Setup_Menu(int menu, char const *text[], unsigned long field, int index, int skip);\nint Check_Menu(int menu, char const *text[], char *selection, long field, int index);\nint Do_Menu(char const **strings, bool blue);\nextern int UnknownKey;\nint Main_Menu(unsigned long timeout);\n\n/*\n** MPLAYER.CPP\n*/\nGameType Select_MPlayer_Game (void);\nvoid Clear_Listbox(ListClass *list);\nvoid Clear_Vector(DynamicVectorClass <NodeNameType *> *vector);\nvoid Computer_Message(void);\nint Surrender_Dialog(int text);\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\nint Surrender_Dialog(const char* text);\nbool Determine_If_Using_DVD();\nbool Using_DVD();\n#endif\nint Abort_Dialog(void);\n\n#if(TEN)\nint Read_TEN_Game_Options(void);\n#endif\t// TEN\n\n#if(MPATH)\nint Read_MPATH_Game_Options(void);\n#endif\t// MPATH\n\n#if(TEN)\n/*\n** CCTEN.CPP\n*/\nint Init_TEN(void);\nvoid Shutdown_TEN(void);\nvoid Connect_TEN(void);\nvoid Destroy_TEN_Connection(int id, int error);\nvoid Send_TEN_Win_Packet(void);\nvoid Send_TEN_Alliance(char *whom, int ally);\nvoid Send_TEN_Out_Of_Sync(void);\nvoid Send_TEN_Packet_Too_Late(void);\n#endif\t// TEN\n\n#if(MPATH)\n/*\n** CCMPATH.CPP\n*/\nint Init_MPATH(void);\nvoid Shutdown_MPATH(void);\nvoid Connect_MPATH(void);\nvoid Destroy_MPATH_Connection(int id, int error);\n#endif\t// MPATH\n\n/*\n** NETDLG.CPP\n*/\nbool Init_Network (void);\nvoid Shutdown_Network (void);\nbool Remote_Connect (void);\nvoid Destroy_Connection(int id, int error);\nbool Process_Global_Packet(GlobalPacketType *packet, IPXAddressClass *address);\nunsigned long Compute_Name_CRC(char *name);\nvoid Net_Reconnect_Dialog(int reconn, int fresh, int oldest_index, unsigned long timeval);\n\n/*\n** NULLDLG.CPP\n*/\nint Init_Null_Modem( SerialSettingsType *settings );\nvoid Shutdown_Modem( void );\nvoid Modem_Signoff( void );\nint Test_Null_Modem( void );\nint Reconnect_Modem( void );\nvoid Destroy_Null_Connection(int id, int error);\nGameType Select_Serial_Dialog( void );\nint Com_Scenario_Dialog(bool skirmish=false);\nint Com_Show_Scenario_Dialog(void);\n\nvoid Smart_Printf( char *format, ... );\nvoid Hex_Dump_Data( char *buffer, int length );\nvoid itoh( int i, char *s);\nvoid Log_Start_Time( char *string );\nvoid Log_End_Time( char *string );\nvoid Log_Time( char *string );\nvoid Log_Start_Nest_Time( char *string );\nvoid Log_End_Nest_Time( char *string );\n\n/*\n**\tOBJECT.CPP\n*/\n\n/*\n**\tPROFILE.CPP\n*/\nint WWGetPrivateProfileInt(char const *section, char const *entry, int def, char *profile);\nbool WWWritePrivateProfileInt(char const *section, char const *entry, int value, char *profile);\nbool WWWritePrivateProfileString(char const *section, char const *entry, char const *string, char *profile);\nchar * WWGetPrivateProfileString(char const *section, char const *entry, char const *def, char *retbuffer, int retlen, char const * profile);\nunsigned WWGetPrivateProfileHex (char const *section, char const *entry, char * profile);\n\nchar *Read_Bin_Buffer( void );\nbool Read_Bin_Init( char *buffer, int length );\nint Read_Bin_Length( char *buffer );\nbool Read_Bin_Num( void *num, int length, char *buffer );\nint Read_Bin_Pos( char *buffer );\nint Read_Bin_PosSet( unsigned int pos, char *buffer );\nbool Read_Bin_String( char *string, char *buffer );\n\nchar *Write_Bin_Buffer( void );\nbool Write_Bin_Init( char *buffer, int length );\nint Write_Bin_Length( char *buffer );\nbool Write_Bin_Num( void *num, int length, char *buffer );\nint Write_Bin_Pos( char *buffer );\nint Write_Bin_PosSet( unsigned int pos, char *buffer );\nbool Write_Bin_String( char *string, int length, char *buffer );\n\n/*\n** QUEUE.CPP\n*/\nbool Queue_Target(TargetClass whom, TARGET target);\nbool Queue_Destination(TargetClass whom, TARGET target);\nbool Queue_Mission(TargetClass whom, MissionType mission);\nbool Queue_Mission(TargetClass whom, MissionType mission, TARGET target, TARGET destination);\nbool Queue_Mission(TargetClass whom, MissionType mission, TARGET target, TARGET destination, SpeedType speed, MPHType maxspeed);\nbool Queue_Options(void);\nbool Queue_Exit(void);\nvoid Queue_AI(void);\nvoid Add_CRC(unsigned long *crc, unsigned long val);\n\n/*\n**\tRANDOM.CPP\n*/\n\n/*\n**\tREINF.CPP\n*/\nbool Do_Reinforcements(TeamTypeClass const * team);\nbool Create_Special_Reinforcement(HouseClass * house, TechnoTypeClass const * type, TechnoTypeClass const * another, TeamMissionType mission = TMISSION_NONE, int argument =0);\nint Create_Air_Reinforcement(HouseClass *house, AircraftType air, int number, MissionType mission, TARGET tarcom, TARGET navcom, InfantryType passenger=INFANTRY_NONE);\n\n/*\n**\tROTBMP.CPP\n*/\nint Rotate_Bitmap(GraphicViewPortClass *srcvp,GraphicViewPortClass *destvp,int angle);\n\n/*\n**\tSAVELOAD.CPP\n*/\nbool Load_Misc_Values(Straw & file);\nbool Save_Misc_Values(Pipe & file);\nbool Load_MPlayer_Values(Straw & file);\nbool Save_MPlayer_Values(Pipe & file);\nbool Get_Savefile_Info(int id, char * buf, unsigned * scenp, HousesType * housep);\nbool Load_Game(int id);\nbool Read_Object (void * ptr, int base_size, int class_size, FileClass & file, void * vtable);\nbool Save_Game(int id, char const * descr, bool bargraph=false);\nbool Write_Object (void * ptr, int class_size, FileClass & file);\nvoid Code_All_Pointers(void);\nvoid Decode_All_Pointers(void);\nvoid Dump(void);\n\n/*\n** SCENARIO.CPP\n*/\nvoid Disect_Scenario_Name(char const * name, int & scenario, ScenarioPlayerType & player, ScenarioDirType & dir, ScenarioVarType & var);\nvoid Post_Load_Game(int load_net);\nbool End_Game(void);\nbool Read_Scenario(char *root);\nbool Start_Scenario(char *root, bool briefing=true);\nHousesType Select_House(void);\nvoid Clear_Scenario(void);\nvoid Do_Briefing(char const * text);\nvoid Do_Lose(void);\nvoid Do_Win(void);\nvoid Do_Restart(void);\nvoid Fill_In_Data(void);\nbool Restate_Mission(char const * name, int button1, int button2);\nint BGMessageBox(char const *text, int button1, int button2);\n\n/*\n**\tSCORE.CPP\n*/\nchar const * Map_Selection(void);\nvoid Bit_It_In(int x, int y, int w, int h, GraphicBufferClass *src, GraphicBufferClass *dest, int delay=0, int dagger=0);\nvoid Call_Back_Delay(int time);\nint Alloc_Object(ScoreAnimClass *obj);\n\n/*\n**\tSPECIAL.CPP\n*/\nvoid Special_Dialog(bool simple=false);\nchar const * Fetch_Password(int caption, int message, int btext=TXT_OK);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nint Fetch_Difficulty(bool amath=false);\n#else\nint Fetch_Difficulty(void);\n#endif\n\n/*\n**\tSTARTUP.CPP\n*/\nvoid Print_Error_End_Exit(char *string);\nvoid Emergency_Exit ( int code );\n\n/*\n**\tSUPPORT.ASM\n*/\n\n/*\n** TARGET.CPP\n*/\nTechnoTypeClass const * As_TechnoType(TARGET target);\nCOORDINATE As_Movement_Coord(TARGET target);\nAircraftClass * As_Aircraft(TARGET target);\nAnimClass * As_Animation(TARGET target);\nBuildingClass * As_Building(TARGET target);\nBulletClass * As_Bullet(TARGET target);\nCELL As_Cell(TARGET target);\nCOORDINATE As_Coord(TARGET target);\nInfantryClass * As_Infantry(TARGET target);\nTeamClass * As_Team(TARGET target);\nTeamTypeClass * As_TeamType(TARGET target);\nTechnoClass * As_Techno(TARGET target);\nTriggerClass * As_Trigger(TARGET target);\nTriggerTypeClass * As_TriggerType(TARGET target);\nUnitClass * As_Unit(TARGET target);\nVesselClass * As_Vessel(TARGET target);\ninline bool Target_Legal(TARGET target) {return(target != TARGET_NONE);};\nObjectClass * As_Object(TARGET target);\n\n/*\n**\tTEAMTYPE.CPP\n*/\nNeedType TeamMission_Needs(TeamMissionType tmtype);\n\n/*\n**\tTRACKER.CPP\n*/\nvoid Detach_This_From_All(TARGET target, bool all=true);\n\n/*\n**\tTRIGGER.CPP\n*/\nTriggerClass * Find_Or_Make(TriggerTypeClass * trigtype);\n\n/*\n** ULOGIC.CPP\n*/\nint Terrain_Cost(CELL cell, FacingType facing);\n\n/*\n**\tVERSION.CPP\n*/\nchar const * Version_Name(void);\n\n/*\n**\tWEAPON.CPP\n*/\nWeaponType Weapon_From_Name(char const * name);\nArmorType Armor_From_Name(char const * name);\n\n/*\n** Winstub.cpp\n*/\nvoid Load_Title_Screen(char *name, GraphicViewPortClass *video_page, unsigned char *palette);\n\n/*\n** Egos.CPP\n*/\nvoid Show_Who_Was_Responsible (void);\n\n#include\t\"inline.h\"\n\n/*\n**\tThese declarations ensure that the templates will be expanded for these specified\n**\ttypes. Doing this is required because some of the body functions for this template class\n**\tare located in a .CPP module. Doing so results in faster compilation but requires declarations\n**\tsuch as this for all types that will be required. There are no actual objects of with these\n**\tnames ever created, however there are other objects of this type (with different names) that\n**\tare created.\n*/\nextern CCPtr<AircraftClass> y1;\nextern CCPtr<AnimClass> y2;\nextern CCPtr<BuildingClass> y3;\nextern CCPtr<BulletClass> y4;\nextern CCPtr<FactoryClass> y5;\nextern CCPtr<HouseClass> y6;\nextern CCPtr<InfantryClass> y7;\nextern CCPtr<OverlayClass> y8;\nextern CCPtr<SmudgeClass> y9;\nextern CCPtr<TeamClass> y10;\nextern CCPtr<TeamTypeClass> y11;\nextern CCPtr<TemplateClass> y12;\nextern CCPtr<TerrainClass> y13;\nextern CCPtr<TriggerClass> y14;\nextern CCPtr<TriggerTypeClass> y15;\nextern CCPtr<HouseTypeClass>\t\ty16;\nextern CCPtr<BuildingTypeClass>\ty17;\nextern CCPtr<AircraftTypeClass>\ty18;\nextern CCPtr<InfantryTypeClass>\ty19;\nextern CCPtr<BulletTypeClass>\t\ty20;\nextern CCPtr<AnimTypeClass>\t\ty21;\nextern CCPtr<UnitTypeClass>\t\ty22;\nextern CCPtr<VesselTypeClass>\t\ty23;\nextern CCPtr<TemplateTypeClass>\ty24;\nextern CCPtr<TerrainTypeClass>\ty25;\nextern CCPtr<OverlayTypeClass>\ty26;\nextern CCPtr<SmudgeTypeClass>\t\ty27;\nclass DynamicVectorClass<CCPtr<TeamTypeClass> >;\nextern DynamicVectorClass<CCPtr<TeamTypeClass> > y002;\nclass DynamicVectorClass<CCPtr<TriggerTypeClass> >;\nextern DynamicVectorClass<CCPtr<TriggerTypeClass> > y001;\nclass DynamicVectorClass<TeamMissionClass *>;\nextern DynamicVectorClass<TeamMissionClass *> xxx1;\nclass DynamicVectorClass<EventChoiceClass *>;\nextern DynamicVectorClass<EventChoiceClass *> xxx2;\nclass DynamicVectorClass<ActionChoiceClass *>;\nextern DynamicVectorClass<ActionChoiceClass *> xxx3;\nclass DynamicVectorClass<EgoClass *>;\nextern DynamicVectorClass<EgoClass *> whatever;\n\n#endif\n"
  },
  {
    "path": "CODE/FUNCTION.I",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : FUNCTION.I                               *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : November 10, 1993                        *\n;*                                                                         *\n;*                  Last Update : November 10, 1993   [JLB]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\n"
  },
  {
    "path": "CODE/FUSE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FUSE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FUSE.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 24, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 17, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   FuseClass::Arm_Fuse -- Sets up fuse for detonation check.                                 *\n *   FuseClass::Fuse_Checkup -- Determines if the fuse triggers.                               *\n *   FuseClass::Fuse_Read -- Reads the fuse class data from the save game file.                *\n *   FuseClass::Fuse_Write -- Writes the fuse data to the save game file.                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * FuseClass::FuseClass -- Constructor.                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/27/1995 BRR : Created.  Gosh, what a lotta work.                                       *\n *=============================================================================================*/\nFuseClass::FuseClass(void)\n{\n\tTimer = 0;\n\tArming = 0;\n\tHeadTo = 0;\n\tProximity = 0;\n}\n\n\n/***********************************************************************************************\n * FuseClass::Arm_Fuse -- Sets up fuse for detonation check.                                   *\n *                                                                                             *\n *    This starts a fuse. Fuses are proximity detonation variety but                           *\n *    can be modified to have a minimum time to elapse before detonation                       *\n *    and a maximum time to exist before detonation. Typically, the                            *\n *    timing values are used for missiles that have a minimum arming                           *\n *    distance and a limited amount of fuel.                                                   *\n *                                                                                             *\n * INPUT:   location -- The coordinate where the projectile start. This                        *\n *                      is needed for proper proximity tracking.                               *\n *                                                                                             *\n *          target   -- The actual impact point. Fuses are based on real                       *\n *                      word coordinates.                                                      *\n *                                                                                             *\n *          time     -- The maximum time that the fuse may work before                         *\n *                      explosion is forced.                                                   *\n *                                                                                             *\n *          arming   -- The minimum time that must elapse before the                           *\n *                      fuse may explode.                                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FuseClass::Arm_Fuse(COORDINATE location, COORDINATE target, int timeto, int arming)\n{\n\ttimeto = max(timeto, arming);\n\tTimer = min(timeto, 0xFF);\n\tArming = min(arming, 0xFF);\n\tHeadTo = target;\n\tProximity = Distance(location, target);\n}\n\n\n/***********************************************************************************************\n * FuseClass::Fuse_Checkup -- Determines if the fuse triggers.                                 *\n *                                                                                             *\n *    This will process the fuse and update the internal clocks as well                        *\n *    as check to see if the fuse should trigger (explode) or not.                             *\n *                                                                                             *\n * INPUT:   newlocation -- The new location of the fuse. This is needed                        *\n *                         to determine proximity explosions.                                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the fuse triggered to explode now?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FuseClass::Fuse_Checkup(COORDINATE newlocation)\n{\n\tint\tproximity;\n\n\t/*\n\t**\tAlways decrement the fuse timer.\n\t*/\n\tif (Timer) Timer--;\n\n\t/*\n\t**\tIf the arming countdown has not expired, then do nothing.\n\t*/\n\tif (Arming) {\n\t\tArming--;\n\t} else {\n\n\t\t/*\n\t\t**\tIf the timer has run out, then the warhead explodes.\n\t\t*/\n\t\tif (!Timer) return(true);\n\n\t\tproximity = Distance(newlocation, HeadTo);\n\t\tif (proximity < 0x0010) return(true);\n\t\tif (proximity < ICON_LEPTON_W && proximity > Proximity) {\n\t\t\treturn(true);\n\t\t}\n\t\tProximity = proximity;\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FuseClass::Fuse_Write -- Writes the fuse data to the save game file.                        *\n *                                                                                             *\n *    Use this routine to output the fuse class data to the save game file specified.          *\n *                                                                                             *\n * INPUT:   file  -- The file to output the data to.                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FuseClass::Fuse_Write(FileClass & file)\n{\n\tfile.Write(&Timer, sizeof(Timer));\n\tfile.Write(&Arming, sizeof(Arming));\n\tfile.Write(&HeadTo, sizeof(HeadTo));\n\tfile.Write(&Proximity, sizeof(Proximity));\n}\n\n\n/***********************************************************************************************\n * FuseClass::Fuse_Read -- Reads the fuse class data from the save game file.                  *\n *                                                                                             *\n *    Use this routine to input the fuse class data from the save game file specified.         *\n *                                                                                             *\n * INPUT:   file  -- The file to input the data from.                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FuseClass::Fuse_Read(FileClass & file)\n{\n\tfile.Read(&Timer, sizeof(Timer));\n\tfile.Read(&Arming, sizeof(Arming));\n\tfile.Read(&HeadTo, sizeof(HeadTo));\n\tfile.Read(&Proximity, sizeof(Proximity));\n}\n\n\n"
  },
  {
    "path": "CODE/FUSE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/FUSE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FUSE.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 24, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 24, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FUSE_H\n#define FUSE_H\n\n/****************************************************************************\n**\tThe fuse is used by projectiles to determine whether detonation should\n**\toccur. This is usually determined by tracking the distance to the\n**\tdesignated target reaches zero or when the timer expires.\n*/\nclass FuseClass {\n\tpublic:\n\t\tFuseClass(void);\n\t\tFuseClass(NoInitClass const &) {};\n\t\t~FuseClass(void) {};\n\n\t\tvoid Arm_Fuse(COORDINATE location, COORDINATE target, int time=0xFF, int arming=0);\n\t\tbool Fuse_Checkup(COORDINATE newlocation);\n\t\tvoid Fuse_Write(FileClass & file);\n\t\tvoid Fuse_Read(FileClass & file);\n\t\tCOORDINATE Fuse_Target(void);\n\n\t\t/*\n\t\t**\tFuses can detonate if enough time has elapsed. This value counts\n\t\t**\tdown. When it reaches zero, detonation occurs.\n\t\t*/\n\t\tunsigned char Timer;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tSome fuses need a certain amount of time before detonation can\n\t\t**\toccur. This counts down and when it reaches zero, normal fuse\n\t\t**\tdetonation checking can occur.\n\t\t*/\n\t\tunsigned char Arming;\n\n\t\t/*\n\t\t**\tThis is the designated impact point of the projectile. The fuse\n\t\t**\twill trip when the closest point to this location has been reached.\n\t\t*/\n\t\tCOORDINATE HeadTo;\n\n\t\t/*\n\t\t**\tThis is the running proximity value to the impact point. This value\n\t\t**\twill progressively get smaller. Detonation occurs when it reaches\n\t\t**\tzero or when it starts to grow larger.\n\t\t*/\n\t\tshort Proximity;\n};\n\ninline COORDINATE FuseClass::Fuse_Target(void)\n{\n\treturn(HeadTo);\n}\n\n#endif\n"
  },
  {
    "path": "CODE/GADGET.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/GADGET.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GADGET.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg                                  *\n *                                Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/03/95                                                     *\n *                                                                                             *\n *                  Last Update : August 1, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   GadgetClass::Action -- Base action for gadget.                                            *\n *   GadgetClass::Clear_Focus -- Clears the focus if this gadget has it.                       *\n *   GadgetClass::Delete_List -- Deletes all gadget objects in list.                           *\n *   GadgetClass::Disable -- Disables the gadget from input processing.                        *\n *   GadgetClass::Draw_All -- Forces all gadgets in list to be redrawn.                        *\n *   GadgetClass::Draw_Me -- Gadget redraw action (flag control).                              *\n *   GadgetClass::Enable -- Enables the gadget.                                                *\n *   GadgetClass::Extract_Gadget -- Sweeps through the gadget chain to find gadget specified.  *\n *   GadgetClass::Flag_To_Redraw -- Flags this gadget to be redrawn.                           *\n *   GadgetClass::GadgetClass -- Constructor for gadget object.                                *\n *   GadgetClass::GadgetClass -- Default constructor for a gadget class object.                *\n *   GadgetClass::Get_Next -- Returns a pointer to the next gadget in the chain.               *\n *   GadgetClass::Get_Prev -- Fetches a pointer to the previous gadget.                        *\n *   GadgetClass::Has_Focus -- Checks if this object currently has the keyboard focus.         *\n *   GadgetClass::Remove -- Removes the specified gadget from the list.                        *\n *   GadgetClass::Set_Focus -- Sets focus to this gadget.                                      *\n *   GadgetClass::Sticky_Process -- Handles the sticky flag processing.                        *\n *   GadgetClass::~GadgetClass -- Destructor for gadget object.                                *\n *   GadgetClass::Is_List_To_Redraw -- tells if any gadget in the list needs redrawing         *\n *   GadgetClass::GadgetClass -- Constructor for the gadget object.                            *\n *   GadgetClass::Set_Position -- Set the coordinate position of this gadget.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/*\n**\tThis records the current gadget the the gadget system is \"stuck on\". Such a\n**\tgadget will be processed to the exclusion of all others until the mouse button\n**\tis no longer pressed.\n*/\nGadgetClass * GadgetClass::StuckOn = 0;\n\n/*\n**\tThis is a copy of a pointer to the last list used by the gadget input system.\n**\tIf a change of list is detected, then all gadgets are forced to be redrawn.\n*/\nGadgetClass * GadgetClass::LastList = 0;\n\n\n/*\n**\tThis points to the gadget that is intercepting all keyboard events.\n*/\nGadgetClass * GadgetClass::Focused = 0;\n\n\n/*\n** This points to the current color scheme for drawing all gadgets.\n*/\nstatic RemapControlType _GreyScheme = {15};\nRemapControlType * GadgetClass::ColorScheme = &_GreyScheme;\n\n\n/***********************************************************************************************\n * GadgetClass::GadgetClass -- Constructor for gadget object.                                  *\n *                                                                                             *\n *    This is the normal constructor for gadget objects. A gadget object is only concerned     *\n *    with the region on the screen to considered \"its own\" as well as the flags that tell     *\n *    what mouse action should be recognized when the mouse is over this screen area.          *\n *                                                                                             *\n * INPUT:   x,y   -- Coordinates (in pixels) of the upper left hand corner of the region that  *\n *                   will be \"owned\" by this gadget.                                           *\n *                                                                                             *\n *          w,h   -- Width and height (in pixels) of this gadget's region.                     *\n *                                                                                             *\n *          flags -- The flags (mouse conditions) that will cause this gadget's action         *\n *                   function to be called.                                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/03/1995 MML : Created.                                                                 *\n *=============================================================================================*/\nGadgetClass::GadgetClass(int x, int y, int w, int h, unsigned flags, int sticky) :\n\tX(x), Y(y), Width(w), Height(h), IsToRepaint(false), IsSticky(sticky), IsDisabled(false), Flags(flags)\n{\n\tif (IsSticky) {\n\t\tFlags |= LEFTPRESS|LEFTRELEASE;\n\t}\n}\n\n\n/***********************************************************************************************\n * GadgetClass::GadgetClass -- Constructor for the gadget object.                              *\n *                                                                                             *\n *    This is the copy constructor for the gadget object. It will try to duplicate the         *\n *    righthand gadget.                                                                        *\n *                                                                                             *\n * INPUT:   gadget   -- Reference to the initilization gadget.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nGadgetClass::GadgetClass(GadgetClass const & gadget) :\n\tX(gadget.X),\n\tY(gadget.Y),\n\tWidth(gadget.Width),\n\tHeight(gadget.Height),\n\tIsToRepaint(gadget.IsToRepaint),\n\tIsSticky(gadget.IsSticky),\n\tIsDisabled(gadget.IsDisabled),\n\tFlags(gadget.Flags)\n{\n}\n\n\n/***********************************************************************************************\n * GadgetClass::~GadgetClass -- Destructor for gadget object.                                  *\n *                                                                                             *\n *    This is the destructor for the gadget object. It will clear the focus from this gadget   *\n *    if this gadget currently has the focus.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nGadgetClass::~GadgetClass(void)\n{\n\tif (Has_Focus()) {\n\t\tClear_Focus();\n\t}\n\n\tif (this == StuckOn) {\n\t\tStuckOn = NULL;\n\t}\n\n\tif (this == LastList) {\n\t\tLastList = NULL;\n\t}\n\n\tif (this == Focused) {\n\t\tFocused = NULL;\n\t}\n}\n\n\n/***************************************************************************\n * GADGETCLASS::CLICKEDON -- If a mouse click is detected within gadget's  *\n *      area and the appropriate flag is set, then call Action().          *\n *                                                                         *\n * INPUT:      int key, int mousex, int mousey                             *\n *                                                                         *\n * OUTPUT:     true or false                                               *\n *                                                                         *\n * WARNINGS:   none.                                                       *\n *                                                                         *\n * HISTORY:    01/03/1995 MML : Created.                                   *\n *=========================================================================*/\nint GadgetClass::Clicked_On(KeyNumType & key, unsigned flags, int mousex, int mousey)\n{\n\t/*\n\t**\tSet flags to match only those events that occur AND are being looked for. If\n\t**\tthe result is NULL, then we know that this button should be ignored.\n\t*/\n\tflags &= Flags;\n\n\t/*\n\t**\tIf keyboard input should be processed by this \"gadget\" and keyboard input is\n\t**\tdetected, then always call the action function. It is up to the action function\n\t**\tin this case to either ignore the keyboard input or not.\n\t**\n\t**\tFor mouse actions, check to see if the mouse is in the region of the button\n\t**\tbefore calling the associated action function. This is the typical action for\n\t**\tbuttons.\n\t*/\n\tif (this == StuckOn ||\n\t\t(flags & KEYBOARD) ||\n\t\t(flags && (unsigned)(mousex - X) < Width  && (unsigned)(mousey - Y) < Height)) {\n\n\t\treturn(Action(flags, key));\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Enable -- Enables the gadget.                                                  *\n *                                                                                             *\n *    This function enables the gadget. An enabled gadget will be processed for input          *\n *    purposes.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Enable(void)\n{\n\tIsDisabled = false;\n\tIsToRepaint = true;\n\tClear_Focus();\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Disable -- Disables the gadget from input processing.                          *\n *                                                                                             *\n *    This routine will disable the gadget. A disabled gadget might be rendered, but is        *\n *    ignored for input processing.                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Disable(void)\n{\n\tIsDisabled = true;\n\tIsToRepaint = true;\n\tClear_Focus();\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Remove -- Removes the specified gadget from the list.                          *\n *                                                                                             *\n *    Use this routine if an individual gadget needs to be removed from the list of gadgets.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the specified gadget found and removed? A false indicates that the       *\n *                gadget wasn't in the list.                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nGadgetClass * GadgetClass::Remove(void)\n{\n\tClear_Focus();\n\treturn(GadgetClass *)LinkClass::Remove();\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Get_Next -- Returns a pointer to the next gadget in the chain.                 *\n *                                                                                             *\n *    This returns with the next gadget's pointer. It is identical to the base Get_Next()      *\n *    function, but returns a pointer to a GadgetClass object.                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the next gadget in the list.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nGadgetClass * GadgetClass::Get_Next(void) const\n{\n\treturn(GadgetClass*)LinkClass::Get_Next();\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Get_Prev -- Fetches a pointer to the previous gadget.                          *\n *                                                                                             *\n *    This routine will return the previous gadget in the list. It is identical to the base    *\n *    function Get_Prev, but returns a pointer to a GadgetClass object.                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the previous gadget in the list.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nGadgetClass * GadgetClass::Get_Prev(void) const\n{\n\treturn(GadgetClass*)LinkClass::Get_Prev();\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Delete_List -- Deletes all gadget objects in list.                             *\n *                                                                                             *\n *    This function will delete all gadgets in the list. It is the counterpart to the          *\n *    Create_One_Of functions.                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Any references to these gadget become invalidated by this routine.              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Delete_List(void)\n{\n\tGadgetClass * g = this;\n\n\t/*\n\t**\tMove to head of the list.\n\t*/\n\twhile (g->Get_Prev()) {\n\t\tg = g->Get_Prev();\n\t}\n\n\t/*\n\t**\tFirst delete all the gadgets following the first one. The reason the first one\n\t**\tis kept around is that sometimes deleting one gadget will result in related gadgets\n\t**\tin the same list also being deleted. The first gadget will always contain the\n\t**\tcorrect gadget pointer.\n\t*/\n\twhile (g) {\n\t\tg->Clear_Focus();\n\n\t\tGadgetClass * temp = g;\n\t\tg = g->Get_Next();\n\t\tdelete temp;\n\t}\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Action -- Base action for gadget.                                              *\n *                                                                                             *\n *    This handles the base level action that a gadget performs when a qualifying input event  *\n *    is detected. This sets the redraw flag and returns true (to stop further processing).    *\n *    If no qualifying input event was detected, but this routine was called anyway, then      *\n *    don't perform any action. The call to this routine, in that case, must have been forced  *\n *    for some other reason.                                                                   *\n *                                                                                             *\n * INPUT:   flag  -- The input event bits that qualify for this gadget. A NULL indicates that  *\n *                   no qualifying event occurred.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Should further gadget list processing be aborted?                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint GadgetClass::Action(unsigned flags, KeyNumType &)\n{\n\t/*\n\t**\tIf any of the event flags are active, then this indicates that something probably\n\t**\thas changed the gadget. Flag the gadget to be redrawn. Also, make sure that\n\t**\tany sticky flags are cleared up.\n\t*/\n\tif (flags) {\n\t\tIsToRepaint = true;\n\t\tSticky_Process(flags);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Draw_Me -- Gadget redraw action (flag control).                                *\n *                                                                                             *\n *    At this level, there is no actual rendering taking place with the call to Draw_Me, but   *\n *    the IsToRepaint flag must be cleared. Derived objects will call this routine and if it   *\n *    returns true, they will perform their custom rendering.                                  *\n *                                                                                             *\n * INPUT:   forced   -- Is this redraw forced by outside circumstances?                        *\n *                                                                                             *\n * OUTPUT:  bool; Should the gadget imagery be redrawn?                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/14/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint GadgetClass::Draw_Me(int forced)\n{\n\tif (forced || IsToRepaint) {\n\t\tIsToRepaint = false;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Draw_All -- Forces all gadgets in list to be redrawn.                          *\n *                                                                                             *\n *    Use this function to cause all gadget in the list to be redrawn regardless of the state  *\n *    of the IsToRepaint flag.                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/03/1995 MML : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Draw_All(bool forced)\n{\n\tGadgetClass * gadget = this;\n\n\twhile (gadget != NULL) {\n\t\tgadget->Draw_Me(forced);\n\t\tgadget = gadget->Get_Next();\n\t}\n}\n\n\n/***************************************************************************\n * GADGETCLASS::PROCESSLIST -- Check list for a mouse click within a gadget*\n *                                                                         *\n * INPUT:      none.                                                       *\n *                                                                         *\n * OUTPUT:     key pressed.                                                *\n *                                                                         *\n * WARNINGS:   none.                                                       *\n *                                                                         *\n * HISTORY:    01/03/1995 MML : Created.                                   *\n *=========================================================================*/\nKeyNumType GadgetClass::Input(void)\n{\n\tint mousex, mousey;\n\tKeyNumType key;\n\tunsigned flags;\n\tint forced = false;\n\n\t/*\n\t**\tRecord this list so that a forced redraw only occurs the FIRST time the\n\t**\tgadget list is passed to this routine.\n\t*/\n\tif (LastList != this) {\n\t\tLastList = this;\n\t\tforced = true;\n\t\tStuckOn = NULL;\n\t\tFocused = NULL;\n\t}\n\n\t/*\n\t**\tFetch any pending keyboard input.\n\t*/\n\tkey = Keyboard->Check();\n\tif (key != 0) {\n\t\tkey = Keyboard->Get();\n\t}\n\n#ifdef WIN32\n#ifdef CHEAT_KEYS\n\tif (key == KN_K && !Debug_Map && (Debug_Flag || Debug_Playtest)) {\n\t\t/*\n\t\t** time to create a screen shot using the PCX code (if it works)\n\t\t*/\n\t\tif (!Debug_MotionCapture) {\n\t\t\tGraphicBufferClass temp_page(\tSeenBuff.Get_Width(),\n\t\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Height(),\n\t\t\t\t\t\t\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Width() * SeenBuff.Get_Height());\n\t\t\tCDFileClass file;\n\t\t\tchar filename[30];\n\n//\t\t\tHide_Mouse();\n\t\t\tSeenBuff.Blit(temp_page);\n//\t\t\tShow_Mouse();\n\t\t\tfor (int lp = 0; lp < 99; lp ++) {\n\t\t\t\tsprintf(filename, \"scrsht%02d.pcx\", lp);\n\t\t\t\tfile.Set_Name(filename);\n\t\t\t\tif (!file.Is_Available()) break;\n\t\t\t}\n\n\t\t\tfile.Cache(200000);\n\t\t\tWrite_PCX_File(file, temp_page, & GamePalette);\n\t\t\tSound_Effect(VOC_BEEP);\n\t\t}\n\t}\n#endif\n#endif\n\n\t/*\n\t**\tFor mouse button clicks, the mouse position is actually held in the MouseQ...\n\t**\tglobals rather than their normal Mouse... globals. This is because we need to\n\t**\tknow the position of the mouse at the exact instant when the click occurred\n\t**\trather the the mouse position at the time we get around to this function.\n\t*/\n\tif (((key&0xFF) == KN_LMOUSE) || ((key&0xFF) == KN_RMOUSE)) {\n\t   mousex = Keyboard->MouseQX;\n\t   mousey = Keyboard->MouseQY;\n\t} else {\n\t   mousex = Get_Mouse_X();\n\t   mousey = Get_Mouse_Y();\n\t}\n\n\t/*\n\t**\tSet the mouse button state flags. These will be passed to the individual\n\t**\tbuttons so that they can determine what action to perform (if any).\n\t*/\n\tflags = 0;\n\tif (key) {\n\t\tif (key == KN_LMOUSE) {\n\t\t\tflags |= LEFTPRESS;\n\t\t}\n\t\tif (key == KN_RMOUSE) {\n\t\t\tflags |= RIGHTPRESS;\n\t\t}\n\t\tif (key == (KN_LMOUSE | KN_RLSE_BIT)) {\n\t\t\tflags |= LEFTRELEASE;\n\t\t}\n\t\tif (key == (KN_RMOUSE | KN_RLSE_BIT)) {\n\t\t\tflags |= RIGHTRELEASE;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the mouse wasn't responsible for this key code, then it must be from\n\t**\tthe keyboard. Flag this fact.\n\t*/\n\tif (key && !flags) {\n\t\tflags |= KEYBOARD;\n\t}\n\n\t/*\n\t**\tMouse button up or down action is ignored if there is a keyboard event. This\n\t**\tallows keyboard events to fall through normally even if the mouse is over a\n\t**\tgadget that is flagged for LEFTUP or RIGHTUP.\n\t*/\n\tif (!key) {\n\n\t\t/*\n\t\t**\tCheck for the mouse being held down. We can't use the normal input system\n\t\t**\tfor this, so we must examine the actual current state of the mouse\n\t\t**\tbuttons. As a side note, if we determine that the mouse button isn't being\n\t\t**\theld down, then we automatically know that it must be up -- set the flag\n\t\t**\taccordingly.\n\t\t*/\n\t\tif (Keyboard->Down(KN_LMOUSE)) {\n\t\t\tflags |= LEFTHELD;\n\t\t} else {\n\t\t\tflags |= LEFTUP;\n\t\t}\n\t\tif (Keyboard->Down(KN_RMOUSE)) {\n\t\t\tflags |= RIGHTHELD;\n\t\t} else {\n\t\t\tflags |= RIGHTUP;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf \"sticky\" processing is active, then only process the stuck gadget.\n\t*/\n\tif (StuckOn) {\n\t\tStuckOn->Draw_Me(false);\n\t\tGadgetClass * oldstuck = StuckOn;\n\t\tStuckOn->Clicked_On(key, flags, mousex, mousey);\n\t\tif (StuckOn) {\n\t\t\tStuckOn->Draw_Me(false);\n\t\t} else {\n\t\t\toldstuck->Draw_Me(false);\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tIf there is a gadget that has the keyboard focus, then route all keyboard\n\t\t**\tevents to it.\n\t\t*/\n\t\tif (Focused && (flags & KEYBOARD)) {\n\t\t\tFocused->Draw_Me(false);\n\t\t\tFocused->Clicked_On(key, flags, mousex, mousey);\n\t\t\tif (Focused) {\n\t\t\t\tFocused->Draw_Me(false);\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tSweep through all the buttons in the chain and pass the current button state\n\t\t\t**\tand keyboard input data to them. These routines will detect whether they should\n\t\t\t**\tperform some action and return a flag to this effect. They also have the option\n\t\t\t**\tof changing the key value so that an appropriate return value is use for this\n\t\t\t**\tprocessing routine.\n\t\t\t*/\n\t\t\tGadgetClass * next_button = this;\n\t\t\twhile (next_button != NULL) {\n\n\t\t\t\t/*\n\t\t\t\t**\tMaybe redraw the button if it needs to or is being forced to redraw.\n\t\t\t\t*/\n\t\t\t\tnext_button->Draw_Me(forced);\n\n\t\t\t\tif (!next_button->IsDisabled) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tProcess this button. If the button was recognized and action was\n\t\t\t\t\t**\tperformed, then bail from further processing (speed reasons?).\n\t\t\t\t\t*/\n\t\t\t\t\tif (next_button->Clicked_On(key, flags, mousex, mousey)) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tSome buttons will require repainting when they perform some action.\n\t\t\t\t\t\t**\tDo so at this time.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tnext_button->Draw_Me(false);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tnext_button = next_button->Get_Next();\n\t\t\t}\n\t\t}\n\t}\n\treturn(key);\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Extract_Gadget -- Sweeps through the gadget chain to find gadget specified.    *\n *                                                                                             *\n *    This examines the gadget list looking for on that has the same ID as specified. If that  *\n *    gadget was found, then a pointer to it is returned. Since only ControlClass gadgets      *\n *    or ones derived from it can have an ID value, we know that the returned pointer is at    *\n *    least of the ControlClass type.                                                          *\n *                                                                                             *\n * INPUT:   id -- The ID number to scan for. Zero is not a legal ID number and if passed in,   *\n *                a NULL will always be returned.                                              *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the ControlClass gadget that has the matching ID number. *\n *          If no matching gadget was found, then NULL is returned.                            *\n *                                                                                             *\n * WARNINGS:   If there happens to be more than one gadget with a matching ID, this routine    *\n *             will return a pointer to the first one only.                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nControlClass * GadgetClass::Extract_Gadget(unsigned id)\n{\n\tGadgetClass * g = this;\n\n\tif (id != 0) {\n\t\twhile (g != NULL) {\n\t\t\tif (g->Get_ID() == id) {\n\t\t\t\treturn((ControlClass *)g);\n\t\t\t}\n\t\t\tg = g->Get_Next();\n\t\t}\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Flag_To_Redraw -- Flags this gadget to be redrawn.                             *\n *                                                                                             *\n *    Use this routine to flag the gadget to be redrawn. A gadget so flagged will have its     *\n *    Draw_Me function called at the next available opportunity. Usually, this is the next     *\n *    time the Input() function is called.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Flag_To_Redraw(void)\n{\n\tIsToRepaint = true;\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Sticky_Process -- Handles the sticky flag processing.                          *\n *                                                                                             *\n *    This function examines the event flags and handles any \"sticky\" processing required.     *\n *    Sticky processing is when the button is flagged with the \"IsSticky\" bit and it will      *\n *    be processed to the exclusion of all other gadgets while the mouse button is held        *\n *    down.                                                                                    *\n *                                                                                             *\n * INPUT:   flags -- The event flags that triggered the call to this routine.                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Sticky_Process(unsigned flags)\n{\n\tif (IsSticky && (flags & LEFTPRESS)) {\n\t\tStuckOn = this;\n\t}\n\tif (StuckOn == this && (flags & LEFTRELEASE)) {\n\t\tStuckOn = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Set_Focus -- Sets focus to this gadget.                                        *\n *                                                                                             *\n *    This will set the focus to this gadget regardless of any current focus setting. If there *\n *    is another gadget that has focus, it will have its focus cleared before this gadget will *\n *    get the focus. A focused gadget is one that has all keyboard input routed to it.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Set_Focus(void)\n{\n\tif (Focused) {\n\t\tFocused->Flag_To_Redraw();\n\t\tFocused->Clear_Focus();\n\t}\n\tFlags |= KEYBOARD;\n\tFocused = this;\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Clear_Focus -- Clears the focus if this gadget has it.                         *\n *                                                                                             *\n *    Use this function to clear the focus for the gadget. If the gadget doesn't currently     *\n *    have focus, then this routine will do nothing. For added functionality, overload this    *\n *    virtual function so that gadget specific actions may be take when focus is lost.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Clear_Focus(void)\n{\n\tif (Focused == this) {\n\t\tFlags &= ~KEYBOARD;\n\t\tFocused = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Has_Focus -- Checks if this object currently has the keyboard focus.           *\n *                                                                                             *\n *    If this object has the keyboard focus, then this routine will return true. When the      *\n *    gadget has keyboard focus, all keyboard events get routed to the gadget.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Does this gadget have the keyboard focus?                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool GadgetClass::Has_Focus(void)\n{\n\treturn(this == Focused);\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Is_List_To_Redraw -- tells if any gadget in the list needs redrawing           *\n *                                                                                             *\n * This function is mostly for supporting HidPage drawing.  If it returns true, it means       *\n * the application needs to re-blit the HidPage forward, after calling the list's Input().     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  true = an item needs redrawing, false = no items need redrawing                    *\n *                                                                                             *\n * WARNINGS:   It is assumed 'this' is the head of the list.                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/03/1995 MML : Created.                                                                 *\n *=============================================================================================*/\nint GadgetClass::Is_List_To_Redraw(void)\n{\n\tGadgetClass * gadget = this;\n\n\twhile (gadget != NULL) {\n\t\tif (gadget->IsToRepaint) {\n\t\t\treturn (true);\n\t\t}\n\t\tgadget = gadget->Get_Next();\n\t}\n\treturn (false);\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Set_Position -- Set the coordinate position of this gadget.                    *\n *                                                                                             *\n *    This routine helps with moving a gadget's location. It will set the gadgets upper        *\n *    left corner to the pixel location specified.                                             *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y position to put the gadget's upper left corner to.            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Set_Position(int x, int y)\n{\n\tX = x;\n\tY = y;\n}\n\n"
  },
  {
    "path": "CODE/GADGET.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/GADGET.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GADGET.H                                                     *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg                                  *\n *                                                                                             *\n *                   Start Date : January 3, 1995                                              *\n *                                                                                             *\n *                  Last Update : January 3, 1995   [MML]                                      *\n *                                                                                             *\n *                                                                                             *\n *        LinkClass [This is the linked list manager class. It keeps a record                  *\n *                  of the next and previous gadget in the list. It is possible               *\n *                  delete a gadget out of the middle of the list with this                   *\n *                  class.]                                                                   *\n *                                                                                            *\n *       GadgetClass [The is the basic gadget class. It handles processing of                  *\n *                   input events and dispatching the appropriate functions.                  *\n *                   All gadgets must be derived from this class.]                            *\n *            Ŀ                                                                           *\n *                                                                                           *\n *              ListClass [This list class functions like a list box does in Windows. It      *\n *                         keeps track of a list of text strings. This list can be            *\n *                         scrolled and an item selected. If the list becomes larger than     *\n *                         can be completely displayed, it will automatically create a        *\n *                         slider (at the right edge) to manage the scrolling.]               *\n *                                                                                            *\n *      ControlClass [This class adds the concept of giving an ID number to the                *\n *                   gadget. This ID can then be returned from the Input()                    *\n *                   function as if it were a pseudo-keystroke. Additionally,                 *\n *                   the ability to inform another button that this button has                *\n *                   been actioned is allowed. This ability allows one button                 *\n *                   to watch what happens to another button. Example: a list                 *\n *                   box gadget can tell when an attached slider has been                     *\n *                   touched.]                                                                *\n *    Ŀ                                                                           *\n *                                                                                          *\n *             GaugeClass [This class looks similar to Windows slider, but has               *\n *                        a different controlling logic. There is no thumb and              *\n *                        it serves as a simple variable control setting. This              *\n *                        is analogous to a volume slider.]                                 *\n *                                                                                          *\n *            SliderClass [The slider class is similar to the typical Windows slider. It     *\n *                         has a current setting, a thumb, and a controllable scale. This    *\n *                         is the object created to handle a scrolling list box.]            *\n *                                                                                           *\n *       EditClass                                                                            *\n *                                                                                            *\n *                                                                                            *\n * ToggleClass [The toggle class is used for buttons that have an image and behave just        *\n *             like the buttons in Windows do. That is, they have a separate visual for       *\n *             when they are pressed and raised. They are officially triggered (return        *\n *             their ID number) when the mouse button is released while over the button.      *\n *             This class doesn't perform any rendering itself. It merely provides the        *\n *             logic so that the derived classes will function correctly.]                    *\n *  Ŀ                                                                                   *\n *                                                                                           *\n *     TextButtonClass [The text button functions like a normal Windows style button, but     *\n *                      the imagery is based on text that is displayed on the button. A       *\n *                      typical example would be the \"OK\" or \"Cancel\" buttons.]               *\n *                                                                                            *\n * ShapeButtonClass [The shape buttons is similar to the TextButton but instead of text        *\n *                   being used to give the button its imagery, an actual shape is used        *\n *                   instead. This allows graphic buttons. These are similar to the up/down    *\n *                   arrows seen in a Windows slider.]                                         *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef GADGET_H\n#define GADGET_H\n\n#include \"link.h\"\n\nclass ControlClass;\n\nclass GadgetClass : public LinkClass\n{\n\tpublic:\n\t\ttypedef enum FlagEnum {\n\t\t\tLEFTPRESS    = 0x0001,\t// Left mouse button press.\n\t\t\tLEFTHELD     = 0x0002,\t// Left mouse button is being held down.\n\t\t\tLEFTRELEASE  = 0x0004,\t// Left mouse button released.\n\t\t\tLEFTUP       = 0x0008,\t// Left mouse button is being held up.\n\t\t\tRIGHTPRESS   = 0x0010,\t// Right mouse button press.\n\t\t\tRIGHTHELD    = 0x0020,\t// Right mouse button is being held down.\n\t\t\tRIGHTRELEASE = 0x0040,\t// Right mouse button released.\n\t\t\tRIGHTUP      = 0x0080,\t// Right mouse button is being held up.\n\t\t\tKEYBOARD     = 0x0100\t// Keyboard input processing (maybe).\n\t\t} FlagEnum;\n\n\t\tGadgetClass(int x, int y, int w, int h, unsigned flags, int sticky=false);\n\t\tGadgetClass(NoInitClass const & x) : LinkClass(x) {};\n\t\tGadgetClass(void) {};\n\t\tGadgetClass(GadgetClass const & gadget);\n\t\tvirtual ~GadgetClass(void);\n\n\t\t/*\n\t\t**\tGadget list management functions.\n\t\t*/\n\t\tvirtual KeyNumType Input(void);\n\t\tvirtual void Draw_All(bool forced=true);\n\t\tvirtual void Delete_List(void);\n\t\tvirtual ControlClass * Extract_Gadget(unsigned id);\n\t\tvirtual void Flag_List_To_Redraw(void) {LastList = 0;};\n\t\tvirtual GadgetClass * Remove(void);\n\t\tvirtual GadgetClass * Get_Next(void) const;\n\t\tvirtual GadgetClass * Get_Prev(void) const;\n\n\t\t/*\n\t\t**\tManages individual gadget states and actions.\n\t\t*/\n\t\tvirtual void Disable(void);\n\t\tvirtual void Enable(void);\n\t\tvirtual unsigned Get_ID(void) const {return 0;};\n\t\tvirtual void Flag_To_Redraw(void);\n\t\tvirtual void Peer_To_Peer(unsigned , KeyNumType & , ControlClass & ) {};\n\t\tvirtual void Set_Focus(void);\n\t\tvirtual void Clear_Focus(void);\n\t\tvirtual bool Has_Focus(void);\n\t\tvirtual int  Is_List_To_Redraw(void);\n\t\tvirtual bool Is_To_Redraw(void) {return (IsToRepaint);}\n\t\tvirtual void Set_Position(int x, int y);\n\n\t\t/*\n\t\t**\tGeneral render function.\n\t\t*/\n\t\tvirtual int Draw_Me(int forced=false);\n\n\t\t/*\n\t\t** Sets the current color scheme\n\t\t*/\n\t\tstatic void Set_Color_Scheme(RemapControlType *scheme)\n\t\t\t{ ColorScheme = scheme; }\n\n\t\tstatic RemapControlType * Get_Color_Scheme(void)\n\t\t\t{ return (ColorScheme); }\n\n\t\t/*\n\t\t**\tThis is the coordinates and dimensions of the gadget region. These are in\n\t\t**\tabsolute screen pixel coordinates.\n\t\t*/\n\t\tint X;\n\t\tint Y;\n\t\tint Width;\n\t\tint Height;\n\n\tprotected:\n\n\t\t/*\n\t\t**\tProcesses the event flags so that if this gadget needs to \"stick\" or\n\t\t**\t\"unstick\", it will be properly flagged. Call this function if you are\n\t\t**\tgoing to clear the button press flags before calling the base class\n\t\t**\tAction() function. Otherwise, calling this function manually, is\n\t\t**\tunnecessary since the base class Action() function already does so.\n\t\t*/\n\t\tvirtual void Sticky_Process(unsigned flags);\n\n\t\t/*\n\t\t**\tThis is the action function that will be called whenever the flags and mouse\n\t\t**\tinput indicates. This is the main method by which this button performs a useful\n\t\t**\tfunction.\n\t\t*/\n\t\tvirtual int Action(unsigned flags, KeyNumType & key);\n\n\t\t/*\n\t\t**\tThis is a record of the last list passed to the Input() function. If a list\n\t\t**\tdifferent than the last recorded one is detected, then the draw function is\n\t\t**\tcalled for every gadget in the list. This causes all buttons to be redrawn the\n\t\t**\tfire time Input() is called without forced a manual call to Draw_All().\n\t\t*/\n\t\tstatic GadgetClass * LastList;\n\n\t\t/*\n\t\t**\tThis points to the gadget that has the keyboard focus. All keyboard only\n\t\t**\tevents are fed to this gadget to the exclusion of all others.\n\t\t*/\n\t\tstatic GadgetClass * Focused;\n\n\t\t/*\n\t\t**\tThis button should call the Draw_Me function because some graphic element needs\n\t\t**\tto be redrawn. This flag is set by default if the Action function is called.\n\t\t*/\n\t\tunsigned IsToRepaint:1;\n\n\tpublic:\t\t// HACK HACK HACK.. this is here because the sidebar buttons are static.\n\t\t/*\n\t\t**\tA sticky button is one that is processed to the exclusion of all other buttons\n\t\t**\tIF the mouse was pressed down while over this button and the mouse continues\n\t\t**\tto remain pressed. This is the standard behavior for all normal Windows style\n\t\t**\tbuttons.\n\t\t*/\n\t\tunsigned IsSticky:1;\n\n\t\t//\tajw - Publicized StuckOn 7/30/98 (was protected)\n\t\t/*\n\t\t**\tIf there is a sticky button being processed, then this will point to it. A sticky\n\t\t**\tbutton is one that will ONLY be processed while the mouse button is being\n\t\t**\theld down.\n\t\t*/\n\t\tstatic GadgetClass * StuckOn;\n\n\tprotected:\n\n\t\t/*\n\t\t**\tIf the button is disabled, then it won't be processed by the input function. It will\n\t\t**\thave its Draw_Me function called as necessary. In order to not display the button\n\t\t**\tat all, the appropriate draw function should perform no action -- just return. Or,\n\t\t**\tjust remove the button from the list.\n\t\t*/\n\t\tunsigned IsDisabled:1;\n\n\t\t/*\n\t\t**\tThese are the action flags that are used to determine when the action function\n\t\t**\tshould be called. Example: If this gadget only wants the action button called when\n\t\t**\tthe left mouse button is pressed over the its region, then the flag will be set\n\t\t**\tto LEFTPRESS.\n\t\t*/\n\t\tunsigned Flags;\n\n\t\t/*\n\t\t** This is the current color scheme; it must be initialized by the app.\n\t\t*/\n\t\tstatic RemapControlType *ColorScheme;\n\n\tprivate:\n\t\tvirtual int Clicked_On(KeyNumType & key, unsigned flags, int x, int y);\n};\n\ninline GadgetClass::FlagEnum operator |(GadgetClass::FlagEnum, GadgetClass::FlagEnum);\ninline GadgetClass::FlagEnum operator &(GadgetClass::FlagEnum, GadgetClass::FlagEnum);\ninline GadgetClass::FlagEnum operator ~(GadgetClass::FlagEnum);\n\n\n#endif\n"
  },
  {
    "path": "CODE/GAMEDLG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/GAMEDLG.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GAMEDLG.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg, Joe L. Bostic                   *\n *                                                                                             *\n *                   Start Date : Jan 8, 1995                                                  *\n *                                                                                             *\n *                  Last Update : Jan 18, 1995   [MML]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   OptionsClass::Process -- Handles all the options graphic interface.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"gamedlg.h\"\n#include \"sounddlg.h\"\n#include \"visudlg.h\"\n#define GERMAN_OFFSET_Y   4      //VG\n\n#ifdef WOLAPI_INTEGRATION\n#include \"WolStrng.h\"\n#include \"WolapiOb.h\"\nextern WolapiObject* pWolapi;\nbool WOL_Options_Dialog( WolapiObject* pWO, bool bCalledFromGame );\n#endif\n\n\n/***********************************************************************************************\n * OptionsClass::Process -- Handles all the options graphic interface.                         *\n *                                                                                             *\n *    This routine is the main control for the visual representation of the options            *\n *    screen. It handles the visual overlay and the player input.                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n * OUTPUT:  none                                                                               *\n * WARNINGS:   none                                                                            *\n * HISTORY:                                                                                    *\n *   12/31/1994 MML : Created.                                                                 *\n *=============================================================================================*/\nvoid GameControlsClass::Process(void)\n{\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tint\td_dialog_w = 232 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint\td_dialog_h = 141 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint\td_dialog_x = ((SeenBuff.Get_Width() - d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\tint\td_dialog_y = ((SeenBuff.Get_Height() - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\tint\td_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\tint\td_top_margin = 25 * RESFACTOR;\n\n\tint\td_txt6_h = (6 * RESFACTOR) + 1;\t\t\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint\td_margin1 = (5 * RESFACTOR);\t\t\t\t\t\t\t\t\t\t\t\t// large margin\n\tint\td_margin2 = (2 * RESFACTOR);\t\t\t\t\t\t\t\t\t\t\t\t// small margin\n\n\tint\td_speed_w = d_dialog_w - (34 * RESFACTOR);\n\tint\td_speed_h = 6 * RESFACTOR;\n\tint\td_speed_x = d_dialog_x + (17 * RESFACTOR);\n#ifdef GERMAN\n\tint\td_speed_y = d_dialog_y + d_top_margin + d_margin1 + d_txt6_h - GERMAN_OFFSET_Y;\n#else\n\tint\td_speed_y = d_dialog_y + d_top_margin + d_margin1 + d_txt6_h;\n#endif\n\n\tint\td_scroll_w = d_dialog_w - (34 * RESFACTOR);\n\tint\td_scroll_h = 6 * RESFACTOR;\n\tint\td_scroll_x = d_dialog_x + (17 * RESFACTOR);\n#ifdef GERMAN\n\tint\td_scroll_y = d_speed_y + d_speed_h + d_txt6_h + (d_margin1 * 2) + d_txt6_h - GERMAN_OFFSET_Y;\n#else\n\tint\td_scroll_y = d_speed_y + d_speed_h + d_txt6_h + (d_margin1 * 2) + d_txt6_h;\n#endif\n\n\tint\td_visual_w = d_dialog_w - (40 * RESFACTOR);\n\tint\td_visual_h = 9 * RESFACTOR;\n\tint\td_visual_x = d_dialog_x + (20 * RESFACTOR);\n\tint\td_visual_y = d_scroll_y + d_scroll_h + d_txt6_h + (d_margin1 * 2);\n\n\tint\td_sound_w = d_dialog_w - (40 * RESFACTOR);\n\tint\td_sound_h = (9 * RESFACTOR);\n\tint\td_sound_x = d_dialog_x + (20 * RESFACTOR);\n\tint\td_sound_y = d_visual_y + d_visual_h + d_margin1;\n\n\tint\td_ok_w = 20 * RESFACTOR;\n\tint\td_ok_h = 9 * RESFACTOR;\n\tint\td_ok_x = d_dialog_cx - (d_ok_w / 2);\n\tint\td_ok_y = d_dialog_y + d_dialog_h - d_ok_h - d_margin1 - (4 * RESFACTOR);\n\n#ifdef WOLAPI_INTEGRATION\n\tint d_wol_x = d_sound_x;\n\tint d_wol_y = d_sound_y + d_sound_h + d_margin1;\n\tint d_wol_w = d_sound_w;\n\tint d_wol_h = d_sound_h;\n\n\tbool bShowWolapi = ( pWolapi && !pWolapi->bConnectionDown );\n\tif( bShowWolapi )\n\t{\n\t\t//\tEnlarge dialog and shift ok button down.\n\t\td_dialog_h += d_wol_h + d_margin1;\n\t\td_dialog_y = ((SeenBuff.Get_Height() - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\t\t//d_ok_y += d_wol_h + d_margin1;\n\t\td_ok_y = d_dialog_y + d_dialog_h - d_ok_h - d_margin1 - (4 * RESFACTOR);\n\t}\n#endif\n\n\t/*\n\t**\tButton Enumerations\n\t*/\n#ifdef WOLAPI_INTEGRATION\n\tenum {\n\t\tBUTTON_SPEED = 100,\n\t\tBUTTON_SCROLLRATE,\n\t\tBUTTON_VISUAL,\n\t\tBUTTON_SOUND,\n\t\tBUTTON_WOLAPI,\n\t\tBUTTON_OK,\n\t\tBUTTON_COUNT,\n\t\tBUTTON_FIRST = BUTTON_SPEED,\n\t};\n#else\n\tenum {\n\t\tBUTTON_SPEED = 100,\n\t\tBUTTON_SCROLLRATE,\n\t\tBUTTON_VISUAL,\n\t\tBUTTON_SOUND,\n\t\tBUTTON_OK,\n\t\tBUTTON_COUNT,\n\t\tBUTTON_FIRST = BUTTON_SPEED,\n\t};\n#endif\n\n\t/*\n\t**\tDialog variables\n\t*/\n\tKeyNumType input;\n\n\tint gamespeed = Options.GameSpeed;\n\tint scrollrate = Options.ScrollRate;\n\tint selection;\n\tbool pressed = false;\n\tint curbutton = 0;\n\tTextButtonClass *buttons[BUTTON_COUNT - BUTTON_FIRST];\n\tTextPrintType style;\n\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t**\tButtons\n\t*/\n\tGadgetClass * commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tSliderClass gspeed_btn(BUTTON_SPEED, d_speed_x, d_speed_y, d_speed_w, d_speed_h, true);\n\tSliderClass scrate_btn(BUTTON_SCROLLRATE, d_scroll_x, d_scroll_y, d_scroll_w, d_scroll_h, true);\n\tTextButtonClass visual_btn(BUTTON_VISUAL, TXT_VISUAL_CONTROLS, TPF_BUTTON, d_visual_x, d_visual_y, d_visual_w, d_visual_h);\n\tTextButtonClass sound_btn(BUTTON_SOUND, TXT_SOUND_CONTROLS, TPF_BUTTON, d_sound_x, d_sound_y, d_sound_w, d_sound_h);\n\tTextButtonClass okbtn(BUTTON_OK, TXT_OPTIONS_MENU, TPF_BUTTON, d_ok_x, d_ok_y);\n\tokbtn.X = (SeenBuff.Get_Width()-okbtn.Width)/2;\n\n#ifdef WOLAPI_INTEGRATION\n\tTextButtonClass wol_btn( BUTTON_WOLAPI, TXT_WOL_OPTTITLE, TPF_BUTTON, d_wol_x, d_wol_y, d_wol_w, d_wol_h );\n#endif\n\n\t/*\n\t**\tVarious Inits.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tBuild button list\n\t*/\n\tcommands = &okbtn;\n\tgspeed_btn.Add_Tail(*commands);\n\tscrate_btn.Add_Tail(*commands);\n\tvisual_btn.Add_Tail(*commands);\n\tsound_btn.Add_Tail(*commands);\n#ifdef WOLAPI_INTEGRATION\n\tif( bShowWolapi )\n\t\twol_btn.Add_Tail(*commands);\n#endif\n\t/*\n\t**\tInit button states\n\t**\tFor sliders, the thumb ranges from 0 - (maxval-1), so to convert the\n\t**\tthumb value to a real-world value:\n\t**\t\tval = (MAX - slider.Get_Value()) - 1;\n\t**\tand,\n\t**\t\tslider.Set_Value(-(val + 1 - MAX));\n\t*/\n\tgspeed_btn.Set_Maximum(OptionsClass::MAX_SPEED_SETTING);\t// varies from 0 - 7\n\tgspeed_btn.Set_Thumb_Size(1);\n\tgspeed_btn.Set_Value((OptionsClass::MAX_SPEED_SETTING-1) - gamespeed);\n\n\tscrate_btn.Set_Maximum(OptionsClass::MAX_SCROLL_SETTING);\t// varies from 0 - 7\n\tscrate_btn.Set_Thumb_Size(1);\n\tscrate_btn.Set_Value((OptionsClass::MAX_SCROLL_SETTING-1) - scrollrate);\n\n\t/*\n\t**\tFill array of button ptrs.\n\t*/\n\tbuttons[0] = NULL;\n\tbuttons[1] = NULL;\n\tbuttons[2] = &visual_btn;\n\tbuttons[3] = &sound_btn;\n#ifdef WOLAPI_INTEGRATION\n\tbuttons[4] = &wol_btn;\n\tbuttons[5] = &okbtn;\n#else\n\tbuttons[4] = &okbtn;\n#endif\n\t/*\n\t**\tProcessing loop.\n\t*/\n\tbool process = true;\n\tbool display = true;\n\tbool refresh = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tif (Session.Type == GAME_NORMAL || Session.Type == GAME_SKIRMISH) {\n\t\t\tCall_Back();\n\t\t} else {\n\t\t\tif (Main_Loop()) {\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = true;\n\t\t}\n\t\t#endif\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\n\t\t\tMap.Flag_To_Redraw(true);\n\t\t\tMap.Render();\n\n\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\t\t\tDraw_Caption(TXT_GAME_CONTROLS, d_dialog_x, d_dialog_y, d_dialog_w);\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t\trefresh = true;\n\t\t}\n\n\t\tif (refresh) {\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t**\tLabel the game speed slider\n\t\t\t*/\n\t\t\tstyle = TPF_TEXT;\n\t\t\tif (curbutton == (BUTTON_SPEED - BUTTON_FIRST)) {\n\t\t\t\tstyle = (TextPrintType)(style | TPF_BRIGHT_COLOR);\n\t\t\t}\n\t\t\tFancy_Text_Print(TXT_SPEED, d_speed_x, d_speed_y - d_txt6_h, scheme, TBLACK, style);\n\n\t\t\tFancy_Text_Print(TXT_SLOWER, d_speed_x, d_speed_y + d_speed_h + (1 * RESFACTOR), scheme, TBLACK, TPF_TEXT);\n\t\t\tFancy_Text_Print(TXT_FASTER, d_speed_x + d_speed_w, d_speed_y + d_speed_h + (1 * RESFACTOR), scheme, TBLACK, TPF_TEXT|TPF_RIGHT);\n\n\t\t\t/*\n\t\t\t**\tLabel the scroll rate slider\n\t\t\t*/\n\t\t\tstyle = TPF_TEXT;\n\t\t\tif (curbutton == (BUTTON_SCROLLRATE - BUTTON_FIRST)) {\n\t\t\t\tstyle = (TextPrintType)(style | TPF_BRIGHT_COLOR);\n\t\t\t}\n\t\t\tFancy_Text_Print(TXT_SCROLLRATE, d_scroll_x, d_scroll_y - d_txt6_h, scheme, TBLACK, style);\n\n\t\t\tFancy_Text_Print (TXT_SLOWER, d_scroll_x, d_scroll_y + d_scroll_h + (1 * RESFACTOR), scheme, TBLACK, TPF_TEXT);\n\t\t\tFancy_Text_Print (TXT_FASTER, d_scroll_x + d_scroll_w, d_scroll_y + d_scroll_h + (1 * RESFACTOR), scheme, TBLACK, TPF_TEXT|TPF_RIGHT);\n\n\t\t\tcommands->Draw_All();\n\n\t\t\tShow_Mouse();\n\t\t\trefresh = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\t/*\n\t\t**\tProcess input.\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_SPEED | KN_BUTTON):\n\t\t\t\tcurbutton = (BUTTON_SPEED - BUTTON_FIRST);\n\t\t\t\trefresh = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_SCROLLRATE | KN_BUTTON):\n\t\t\t\tcurbutton = (BUTTON_SCROLLRATE - BUTTON_FIRST);\n\t\t\t\trefresh = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_VISUAL | KN_BUTTON):\n\t\t\t\tselection = BUTTON_VISUAL;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_SOUND | KN_BUTTON):\n\t\t\t\tselection = BUTTON_SOUND;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tselection = BUTTON_OK;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\tcase (BUTTON_WOLAPI | KN_BUTTON):\n\t\t\t\tselection = BUTTON_WOLAPI;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n#endif\n\n\t\t\tcase (KN_ESC):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_LEFT):\n\t\t\t\tif (curbutton == (BUTTON_SPEED - BUTTON_FIRST) ) {\n\t\t\t\t\tgspeed_btn.Bump(1);\n\t\t\t\t} else\n\t\t\t\t\tif (curbutton == (BUTTON_SCROLLRATE - BUTTON_FIRST) ) {\n\t\t\t\t\t\tscrate_btn.Bump(1);\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RIGHT):\n\t\t\t\tif (curbutton == (BUTTON_SPEED - BUTTON_FIRST) ) {\n\t\t\t\t\tgspeed_btn.Bump(0);\n\t\t\t\t} else\n\t\t\t\t\tif (curbutton == (BUTTON_SCROLLRATE - BUTTON_FIRST) ) {\n\t\t\t\t\t\tscrate_btn.Bump(0);\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_UP):\n\t\t\t\tif (buttons[curbutton]) {\n\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t}\n\n\t\t\t\tcurbutton--;\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\tif( !bShowWolapi )\n\t\t\t\t{\n\t\t\t\t\tif( curbutton == BUTTON_WOLAPI - BUTTON_FIRST )\n\t\t\t\t\t\tcurbutton--;\t\t//\tSkip over missing button.\n\t\t\t\t}\n#endif\n\t\t\t\tif (curbutton < 0) {\n\t\t\t\t\tcurbutton = (BUTTON_COUNT - BUTTON_FIRST - 1);\n\t\t\t\t}\n\n\t\t\t\tif (buttons[curbutton]) {\n\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\trefresh = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_DOWN):\n\t\t\t\tif (buttons[curbutton]) {\n\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t}\n\n\t\t\t\tcurbutton++;\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\tif( !bShowWolapi )\n\t\t\t\t{\n\t\t\t\t\tif( curbutton == BUTTON_WOLAPI - BUTTON_FIRST )\n\t\t\t\t\t\tcurbutton++;\t\t//\tSkip over missing button.\n\t\t\t\t}\n#endif\n\t\t\t\tif (curbutton > (BUTTON_COUNT - BUTTON_FIRST - 1) ) {\n\t\t\t\t\tcurbutton = 0;\n\t\t\t\t}\n\n\t\t\t\tif (buttons[curbutton]) {\n\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\trefresh = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\t\tselection = curbutton + BUTTON_FIRST;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tPerform some action. Either to exit the dialog or bring up another.\n\t\t*/\n\t\tif (pressed) {\n\n\t\t\t/*\n\t\t\t**\tRecord the new options slider settings.\n\t\t\t** The GameSpeed data member MUST NOT BE SET HERE!  It will cause multiplayer\n\t\t\t** games to go out of sync.  It's set by virtue of the event being executed.\n\t\t\t*/\n\t\t\tif (gamespeed != ((OptionsClass::MAX_SPEED_SETTING-1) - gspeed_btn.Get_Value()) ) {\n\t\t\t\tgamespeed = (OptionsClass::MAX_SPEED_SETTING-1) - gspeed_btn.Get_Value();\n\t\t\t\tOutList.Add(EventClass(EventClass::GAMESPEED, gamespeed));\n\t\t\t}\n\n\t\t\tif (scrollrate != ((OptionsClass::MAX_SCROLL_SETTING-1) - scrate_btn.Get_Value()) ) {\n\t\t\t\tscrollrate = (OptionsClass::MAX_SCROLL_SETTING-1) - scrate_btn.Get_Value();\n\t\t\t\tOptions.ScrollRate = scrollrate;\n\t\t\t}\n\t\t\tprocess = false;\n\n\t\t\t/*\n\t\t\t** Save the settings in such a way that the GameSpeed is only set during\n\t\t\t** the save process; restore it when we're done, so multiplayer games don't\n\t\t\t** go out of sync.\n\t\t\t*/\n\t\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\t\tOptions.GameSpeed = gamespeed;\n\t\t\t\tOptions.Save_Settings();\t\t\t// save new value\n\t\t\t} else {\n\t\t\t\tint old = Options.GameSpeed;\t\t// save orig value\n\t\t\t\tOptions.GameSpeed = gamespeed;\n\t\t\t\tOptions.Save_Settings();\t\t\t// save new value\n\t\t\t\tOptions.GameSpeed = old;\t\t\t// restore old value\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tPossibly launch into another dialog if so directed.\n\t\t\t*/\n\t\t\tswitch (selection) {\n\t\t\t\tcase (BUTTON_VISUAL):\n\t\t\t\t\tVisualControlsClass().Process();\n\t\t\t\t\tprocess = true;\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\trefresh = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_SOUND):\n\t\t\t\t\tif (!SoundType) {\n\t\t\t\t\t\tWWMessageBox().Process(Text_String(TXT_NO_SOUND_CARD));\n\t\t\t\t\t\tprocess = true;\n\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\trefresh = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSoundControlsClass().Process();\n\t\t\t\t\t\tprocess = true;\n\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\trefresh = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\tcase BUTTON_WOLAPI:\n\t\t\t\t\tif( WOL_Options_Dialog( pWolapi, true ) )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tThe game ended while in this dialog.\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tprocess = true;\n\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\trefresh = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n#endif\n\n\t\t\t\tcase (BUTTON_OK):\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tpressed = false;\n\t\t}\n\t}\n}\n\n\n"
  },
  {
    "path": "CODE/GAMEDLG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/GAMEDLG.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               *** \n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GAMEDLG.H                                                    *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg, Joe L. Bostic                   *\n *                                                                                             *\n *                   Start Date : Jan 8, 1995                                                  *\n *                                                                                             *\n *                  Last Update : Jan 18, 1995   [MML]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef GAMEDLG_H\n#define GAMEDLG_H\n\n#include \"gadget.h\"\n\nclass GameControlsClass \n{\n\tpublic:\n\t\tGameControlsClass(void) {};\n\t\tvoid Process(void);\n};\n\n\n#endif\n\n"
  },
  {
    "path": "CODE/GAUGE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/GAUGE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GAUGE.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic, Maria del Mar McCready Legg                   *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 16, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   GaugeClass::Action -- Handles input events for the gauge.                                 *\n *   GaugeClass::Draw_Me -- Draws the body of the gauge.                                       *\n *   GaugeClass::Pixel_To_Value -- Convert a pixel offset into a gauge value.                  *\n *   GaugeClass::Set_Maximum -- Sets the maximum value for the gauge.                          *\n *   GaugeClass::Set_Value -- Set the value of the gauge.                                      *\n *   GaugeClass::Value_To_Pixel -- Convert gauge value to pixel offset.                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***************************************************************************\n * GaugeClass::GaugeClass -- class constructor                             *\n *                                                                         *\n * INPUT:    id                     -- button ID                           *\n *                                                                         *\n *             x,y                     -- upper-left corner, in pixels     *\n *                                                                         *\n *             w,h                     -- width, height, in pixels         *\n *                                                                         *\n * OUTPUT:   none.                                                         *\n *                                                                         *\n * WARNINGS: none.                                                         *\n *                                                                         *\n * HISTORY:  01/05/1995 MML : Created.                                     *\n *=========================================================================*/\nGaugeClass::GaugeClass(unsigned id, int x, int y, int w, int h)\n\t: ControlClass(id, x, y, w, h, LEFTHELD|LEFTPRESS|LEFTRELEASE, true)\n{\n\tSet_Maximum(255);\n\tSet_Value(0);\n\n\tHasThumb = true;\n\tIsHorizontal = (w > h);\n\tIsColorized = true;\n\n\tClickDiff = 0;\n}\n\n\n/***********************************************************************************************\n * GaugeClass::Set_Maximum -- Sets the maximum value for the gauge.                            *\n *                                                                                             *\n *    This routine will set the maximum value for the gauge. This is the largest value that    *\n *    the current setting may reach. The ability to change this allows the gauge to use and    *\n *    return values that are convenient for the programmer's current needs.                    *\n *                                                                                             *\n * INPUT:   value -- The value to use as the gauge maximum.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the gauge maximum changed? A false indicates that the specified value    *\n *                already matches the current maximum.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint GaugeClass::Set_Maximum(int value)\n{\n\tif (value != MaxValue) {\n\t   MaxValue = value;\n\t\tFlag_To_Redraw();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * GaugeClass::Set_Value -- Set the value of the gauge.                                        *\n *                                                                                             *\n *    This routine will set the current value for the gauge. This value is clipped to the      *\n *    limits of the gauge maximum.                                                             *\n *                                                                                             *\n * INPUT:   value -- The value to set at the new current value.                                *\n *                                                                                             *\n * OUTPUT:  bool; Was the current setting changed? A false indicates that the setting          *\n *                specified is the same as what was already there.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint GaugeClass::Set_Value(int value)\n{\n\tvalue = Bound(value, 0, MaxValue);\n\tif (value != CurValue) {\n\t\tCurValue = value;\n\t\tFlag_To_Redraw();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * GaugeClass::Pixel_To_Value -- Convert a pixel offset into a gauge value.                    *\n *                                                                                             *\n *    Use this routine to convert the specified pixel offset into a gauge value. This is used   *\n *    in translating mouse clicks into a corresponding setting for the gauge.                  *\n *                                                                                             *\n * INPUT:   pixel -- The pixel offset form the start of the gauge.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the setting value in gauge coordinates.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint GaugeClass::Pixel_To_Value(int pixel)\n{\n\tint maximum;\n\n\tif (IsHorizontal) {\n\t\tpixel -= X+1;\n\t\tmaximum = Width;\n\t} else {\n\t\tpixel -= Y+1;\n\t\tmaximum = Height;\n\t}\n\tmaximum -= 2;\n\tpixel = Bound(pixel, 0, maximum);\n\treturn(MaxValue * fixed(pixel, maximum));\n//\treturn(Fixed_To_Cardinal(MaxValue, Cardinal_To_Fixed(maximum, pixel)));\n}\n\n\n/***********************************************************************************************\n * GaugeClass::Value_To_Pixel -- Convert gauge value to pixel offset.                          *\n *                                                                                             *\n *    Use this routine to convert the specified gauge value into a pixel offset from the       *\n *    star of the gauge. This is used for thumb positioning.                                   *\n *                                                                                             *\n * INPUT:   value -- The value to convert to a pixel offset.                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the pixel offset of the specified value from the start of the         *\n *          gauge.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint GaugeClass::Value_To_Pixel(int value)\n{\n\tint maximum;\n\tint start;\n\tif (IsHorizontal) {\n\t\tmaximum = Width;\n\t\tstart = X;\n\t} else {\n\t\tmaximum = Height;\n\t\tstart = Y;\n\t}\n\tmaximum -= 2;\n\treturn(start + maximum * fixed(value, MaxValue));\n//\treturn(start + Fixed_To_Cardinal(maximum, Cardinal_To_Fixed(MaxValue, value)));\n}\n\n\n/***********************************************************************************************\n * GaugeClass::Draw_Me -- Draws the body of the gauge.                                         *\n *                                                                                             *\n *    This routine will draw the body of the gauge if necessary.                               *\n *                                                                                             *\n * INPUT:      forced   -- Should the gauge be redrawn regardless of the current redraw flag?  *\n *                                                                                             *\n * OUTPUT:     bool; Was the gauge redrawn?                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:    01/16/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nint GaugeClass::Draw_Me(int forced)\n{\n\tif (ControlClass::Draw_Me(forced)) {\n\n\t\t/*\n\t\t**\tHide the mouse\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Hide_Mouse(X, Y, X+Width, Y+Height);\n\t\t}\n\n\t\t/*\n\t\t**\tDraw the body & set text color\n\t\t*/\n\t\tDraw_Box (X, Y, Width, Height, BOXSTYLE_DOWN, true);\n\n\t\t/*\n\t\t**\tColourize the inside of the gauge if indicated.\n\t\t*/\n\t\tif (IsColorized) {\n\t\t\tint middle = Value_To_Pixel(CurValue);\n\t\t\tint color = GadgetClass::Get_Color_Scheme()->Bright;\n\t\t\tif (IsHorizontal) {\n\t\t\t\tif (middle >= (X + 1))\n\t\t\t\t\tLogicPage->Fill_Rect(X+1, Y+1, middle, Y+Height-2, color);\n\t\t\t} else {\n\t\t\t\tif (middle >= (Y + 1))\n\t\t\t\t\tLogicPage->Fill_Rect(X+1, Y+1, X+Width-2, middle, color);\n\t\t\t}\n\t\t}\n\n\t\tif (HasThumb) {\n\t\t\tDraw_Thumb();\n\t\t}\n\n\t\t/*\n\t\t**\tDisplay the mouse\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Show_Mouse();\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * GaugeClass::Action -- Handles input events for the gauge.                                   *\n *                                                                                             *\n *    This routine will handle input event processing for the gauge. It will adjust the        *\n *    current setting of the gauge according to the mouse position.                            *\n *                                                                                             *\n * INPUT:   flags -- The input event that is the reason for this function call.                *\n *          key   -- The key code that caused the event.                                       *\n *                                                                                             *\n * OUTPUT:  bool; Was the even recognized, processed, and no further gadget scanning is        *\n *                desired (for this pass).                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint GaugeClass::Action(unsigned flags, KeyNumType &key)\n{\n\t/*\n\t** If there's no thumb on this gauge, it's a display-only device.\n\t*/\n\tif (!HasThumb) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tWe might end up clearing the event bits. Make sure that the sticky\n\t**\tprocess is properly updated anyway.\n\t*/\n\tSticky_Process(flags);\n\n\t/*\n\t**\tIf the thumb is currently being \"dragged around\", then update the slider\n\t**\tposition according to the mouse position. In all other cases, ignore the\n\t**\tbutton being held down.\n\t*/\n\tif ((flags & LEFTPRESS) || ((flags & LEFTHELD) && StuckOn == this)) {\n\n\t\t/*\n\t\t** Compute the difference between where we clicked, and the edge of\n\t\t** the thumb (only if we clicked on the thumb.)\n\t\t*/\n\t\tif (flags & LEFTPRESS) {\n\t\t\tint curpix = Value_To_Pixel(CurValue);\n\t\t\tint clickpix = (IsHorizontal ? Get_Mouse_X() : Get_Mouse_Y());\n\n\t\t\tif ( (clickpix > curpix) && (clickpix - curpix) < Thumb_Pixels()) {\n\t\t\t\tClickDiff = (clickpix - curpix);\n\t\t\t} else {\n\t\t\t\tClickDiff = 0;\n\t\t\t}\n\n\t\t\tint testval = Pixel_To_Value(IsHorizontal ?\n\t\t\t\tGet_Mouse_X() - ClickDiff : Get_Mouse_Y() - ClickDiff);\n\n\t\t\t/*\n\t\t\t** Correct for round-down errors in Pixel_To_Value() and\n\t\t\t** Value_To_Pixel(); make ClickDiff exactly right so that\n\t\t\t** at this point, Get_Mouse_n() - ClickDiff converts to\n\t\t\t** CurValue.\n\t\t\t*/\n\t\t\twhile (testval < CurValue && ClickDiff > 0) {\n\t\t\t\tClickDiff--;\n\t\t\t\ttestval = Pixel_To_Value(IsHorizontal ?\n\t\t\t\tGet_Mouse_X() - ClickDiff : Get_Mouse_Y() - ClickDiff);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf no change occurred in the gauge, just call Control's Action routine,\n\t\t** but turn off the flags so it won't fill in 'key' with the button ID.\n\t\t** Thus, no button ID will be returned by Input.\n\t\t*/\n\t\tif (!Set_Value(Pixel_To_Value(IsHorizontal ?\n\t\t\tGet_Mouse_X() - ClickDiff : Get_Mouse_Y() - ClickDiff))) {\n\n\t\t\tflags &= ~(LEFTHELD|LEFTRELEASE|LEFTPRESS);\n\t\t\tControlClass::Action(0, key);\n\t\t\tkey = KN_NONE;\n\t\t\treturn(true);\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tIgnore the left mouse button being held down if this gauge is not\n\t\t**\tcurrently in \"sticky\" mode. This allows processing of the LEFTPRESS\n\t\t**\tby any derived classes such that this gauge can be more closely\n\t\t**\tcontrolled.\n\t\t*/\n\t\tflags &= ~LEFTHELD;\n\t}\n\treturn(ControlClass::Action(flags, key));\n}\n\n\n/***********************************************************************************************\n * GaugeClass::Draw_Thumb -- Draws the body of the gauge.                                      *\n *                                                                                             *\n *    This routine will draw the body of the gauge if necessary.                               *\n *                                                                                             *\n * INPUT:      none.                                                                           *\n *                                                                                             *\n * OUTPUT:     none.                                                                           *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:    01/16/1995 MML : Created.                                                       *\n *=============================================================================================*/\nvoid GaugeClass::Draw_Thumb(void)\n{\n\tint x = Value_To_Pixel(CurValue);\n\n\tif ((x + 4) > Value_To_Pixel(MaxValue)) {\n\t\tx = Value_To_Pixel(MaxValue) - 2;\n\t}\n\n\tif (x < X) {\n\t\tx = X;\n\t}\n\n\tif (IsHorizontal) {\n\t\tDraw_Box(x, Y, 4, Height, BOXSTYLE_RAISED, true);\n\t} else {\n\t\tDraw_Box(X, x, Width, 4,  BOXSTYLE_RAISED, true);\n\t}\n}\n\n\n/***********************************************************************************************\n * TriColorGaugeClass::TriColorGaugeClass -- Constructor for 3 color (red\\yellow\\green) gauge. *\n *                                                                                             *\n *    This routine will draw the body of the gauge if necessary.                               *\n *                                                                                             *\n * INPUT:      See below.                                                                      *\n *                                                                                             *\n * OUTPUT:     none.                                                                           *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:    01/16/1995 MML : Created.                                                       *\n *=============================================================================================*/\nTriColorGaugeClass::TriColorGaugeClass(unsigned id, int x, int y, int w, int h)\n\t: GaugeClass(id, x, y, w, h)\n{\n\tRedLimit = 0;\t\t\t\t// maximum value for red\n\tYellowLimit = 0;\t\t\t// maximum value for yellow\n}\n\n\n/***********************************************************************************************\n * TriColorGaugeClass::Set_Red_Limit -- Set the value for the red area of gauge.               *\n *                                                                                             *\n * INPUT:      int value.                                                                      *\n *                                                                                             *\n * OUTPUT:     bool true of false.                                                             *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:    01/16/1995 MML : Created.                                                       *\n *=============================================================================================*/\nint TriColorGaugeClass::Set_Red_Limit(int value)\n{\n\tif (value >= 0 && value < MaxValue) {\n\n//\t\tif (value > YellowLimit) {\n//\t\t\tRedLimit = YellowLimit;\n//\t\t\tYellowLimit = value;\n//\t\t} else {\n\t\t\tRedLimit = value;\n//\t\t}\n\t\tFlag_To_Redraw();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TriColorGaugeClass::Set_Yellow_Limit -- Set the value for the yellow area of gauge.         *\n *                                                                                             *\n * INPUT:      int value.                                                                      *\n *                                                                                             *\n * OUTPUT:     bool true of false.                                                             *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:    01/16/1995 MML : Created.                                                       *\n *=============================================================================================*/\nint TriColorGaugeClass::Set_Yellow_Limit(int value)\n{\n\tif (value >= 0 && value < MaxValue) {\n\n//\t\tif (value < RedLimit) {\n//\t\t\tYellowLimit = RedLimit;\n//\t\t\tRedLimit = value;\n//\t\t} else {\n\t\t\tYellowLimit = value;\n//\t\t}\n\t\tFlag_To_Redraw();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TriColorGaugeClass::Draw_Me -- Draw the tri color gauge.                                    *\n *                                                                                             *\n * INPUT:      int forced -- draw or not?                                                      *\n *                                                                                             *\n * OUTPUT:     bool true of false.                                                             *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:    01/16/1995 MML : Created.                                                       *\n *=============================================================================================*/\nint TriColorGaugeClass::Draw_Me(int forced)\n{\n\tif (ControlClass::Draw_Me(forced)) {\n\n\t\t/*\n\t\t**\tHide the mouse\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Hide_Mouse(X, Y, X+Width, Y+Height);\n\t\t}\n\n\t\t/*\n\t\t**\tDraw the body & set text color\n\t\t*/\n\t\tDraw_Box (X, Y, Width, Height, (IsDisabled ? BOXSTYLE_RAISED : BOXSTYLE_DOWN), true);\n\n\t\t/*\n\t\t**\tColourize the inside of the gauge if indicated.\n\t\t*/\n\t\tint red    = Value_To_Pixel(RedLimit);\n\t\tint yellow = Value_To_Pixel(YellowLimit);\n\t\tint middle = Value_To_Pixel(CurValue);\n\n\t\tif (CurValue <= RedLimit) {\n\t\t\tif (IsHorizontal) {\n\t\t\t\tLogicPage->Fill_Rect(X+1, Y+1, middle, Y+Height-2, PINK);\n\t\t\t} else {\n\t\t\t\tLogicPage->Fill_Rect(X+1, Y+1, X+Width-2, middle, PINK);\n\t\t\t}\n\t\t} else if (CurValue > RedLimit && CurValue <= YellowLimit) {\n\t\t\tif (IsHorizontal) {\n\t\t\t\tLogicPage->Fill_Rect(X+1, Y+1, red,    Y+Height-2, PINK);\n\t\t\t\tLogicPage->Fill_Rect(red, Y+1, middle, Y+Height-2, YELLOW);\n\t\t\t} else {\n\t\t\t\tLogicPage->Fill_Rect(X+1, Y+1, X+Width-2, red,    PINK);\n\t\t\t\tLogicPage->Fill_Rect(X+1, red, X+Width-2, middle, YELLOW);\n\t\t\t}\n\t\t} else if (CurValue > YellowLimit && CurValue <= MaxValue) {\n\n\t\t\tif (IsHorizontal) {\n\t\t\t\tLogicPage->Fill_Rect(X+1,    Y+1, red,    Y+Height-2, PINK);\n\t\t\t\tLogicPage->Fill_Rect(red,    Y+1, yellow, Y+Height-2, YELLOW);\n\t\t\t\tLogicPage->Fill_Rect(yellow, Y+1, middle, Y+Height-2, GREEN);\n\t\t\t} else {\n\t\t\t\tLogicPage->Fill_Rect(X+1, Y+1,    X+Width-2, red,    PINK);\n\t\t\t\tLogicPage->Fill_Rect(X+1, red,    X+Width-2, yellow, YELLOW);\n\t\t\t\tLogicPage->Fill_Rect(X+1, yellow, X+Width-2, middle, GREEN);\n\t\t\t}\n\t\t}\n\n\t\tif (HasThumb) {\n\t\t\tDraw_Thumb();\n\t\t}\n\n\t\t/*\n\t\t**\tDisplay the mouse\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Show_Mouse();\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n"
  },
  {
    "path": "CODE/GAUGE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/GAUGE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GAUGE.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic, Maria del Mar McCready Legg                   *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef GAUGE_H\n#define GAUGE_H\n\nclass GaugeClass : public ControlClass\n{\n\tpublic:\n\n\t\tGaugeClass(unsigned id, int x, int y, int w, int h);\n\n\t\tvirtual int Draw_Me(int forced=false);\n\t\tvirtual int Set_Maximum(int value);\n\t\tvirtual int Set_Value(int value);\n\t\tvirtual int Get_Value(void) const {return (CurValue);};\n\t\tvirtual void Use_Thumb(int value) { HasThumb = value ? true : false; };\n\n\t\tvirtual int Thumb_Pixels(void) { return (4);}\n\n\t\t/*\n\t\t**\tIf this gauge has a color to the left of the current setting, then this\n\t\t**\tflag will be true.\n\t\t*/\n\t\tunsigned IsColorized:1;\n\n\tprotected:\n\n\t\t/*\n\t\t**\tIf a thumb is desired, set to true.\n\t\t*/\n\t\tunsigned HasThumb:1;\n\n\t\t/*\n\t\t**\tIs this a horizontal slider?\n\t\t*/\n\t\tunsigned IsHorizontal:1;\n\n\t\tint MaxValue;\t\t\t\t// maximum value (in application units)\n\t\tint CurValue;\t\t\t\t// index of 1st displayed string in box\n\t\t\t\t\t\t\t\t\t\t//  (in application units)\n\n\t\t/*\n\t\t** This value records the difference between where the user clicked\n\t\t** and the edge of the thumb, so that the thumb follows the mouse\n\t\t** with the proper offset.\n\t\t*/\n\t\tint ClickDiff;\n\n\tprotected:\n\t\tvirtual void Draw_Thumb(void);\n\t\tvirtual int  Action(unsigned flags, KeyNumType &key);\n\t\tvirtual int  Pixel_To_Value(int pixel);\n\t\tvirtual int  Value_To_Pixel(int value);\n};\n\n\n\nclass TriColorGaugeClass : public GaugeClass\n{\n\tpublic:\n\t\tTriColorGaugeClass(unsigned id, int x, int y, int w, int h);\n\t\tvirtual int Draw_Me(int forced);\n\t\tvirtual int Set_Red_Limit(int value);\n\t\tvirtual int Set_Yellow_Limit(int value);\n\n\tprotected:\n\t\tint RedLimit;\t\t\t\t// maximum value for red\n\t\tint YellowLimit;\t\t\t// maximum value for yellow\n};\n\n\n\n\n#endif\n"
  },
  {
    "path": "CODE/GETCPU.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/GETCPU.CPP 1     3/03/97 10:24a Joe_bostic $*/\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : GETCPU                                                       *\n *                                                                                             *\n *                    File Name : GETCPU.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 6/26/96                                                      *\n *                                                                                             *\n *                  Last Update : June 26th 1996 [ST]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *   Example of interface to assembly language code to find CPU type                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *   Get_CPU_Type -- interface to ASM detection code                                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n//#define WIN32\n//#include <windows.h>\n#include <stdio.h>\n#include\t<string.h>\n\n\n#define\tbool\tint\n\n/*\n** Prototypes for linkage to assembly module\n*/\nextern \"C\" {\n\tbool __cdecl Detect_MMX_Availability (void);\n\n\textern char CPUType;\n\textern char VendorID;\n}\n\n\n/***********************************************************************************************\n * Get_CPU_Type -- Find out what kind of CPU we are running on                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    int   - reference to cpu type                                                     *\n *           bool  - reference to mmx availability flag                                        *\n *           char* - ptr to buffer to receive chip vendor info                                 *\n *           int   - length of above buffer                                                    *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/26/96 10:15AM ST : Created                                                             *\n *=============================================================================================*/\nvoid Get_CPU_Type(int & cpu_type, bool & mmx, char * vendor_id, int vendor_id_length)\n{\n\t/*\n\t** Call the asm CPU detection code\n\t*/\n\tmmx = Detect_MMX_Availability();\n\n\t/*\n\t** Return the promised results\n\t*/\n\tcpu_type = (int)CPUType;\n\tchar * vendor_ptr = &VendorID;\n\tstrncpy(vendor_id, vendor_ptr, vendor_id_length);\n}\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "CODE/GLOBALS.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /counterstrike/GLOBALS.CPP 2     3/10/97 6:22p Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GLOBALS.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : September 10, 1993   [JLB]                                   *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\nbool IsVQ640 = false;\nunsigned long GameVersion = 0;\nbool Debug_MotionCapture = false;\nbool Debug_Rotate = false;\t\t\t\t// Rotation algorithm control.\nbool Debug_Quiet = false;\nbool Debug_Cheat = false;\nbool Debug_Remap = false;\nbool Debug_Icon = false;\nbool Debug_Flag = false;\nbool Debug_Lose = false;\nbool Debug_Win = false;\nbool Debug_Map = false;\t\t\t\t\t// true = map editor mode\nbool Debug_Passable = false;\t\t\t// true = show passable/impassable terrain\nbool Debug_Unshroud = false;\t\t\t// true = hide the shroud\nbool Debug_Threat = false;\nbool Debug_Find_Path = false;\nbool Debug_Check_Map = false;\t\t\t// true = validate the map each frame\nbool Debug_Playtest = false;\n\nbool Debug_Heap_Dump = false;\t\t\t// true = print the Heap Dump\nbool Debug_Smart_Print = false;\t\t// true = print everything that calls Smart_Printf\nbool Debug_Trap_Check_Heap = false;\t// true = check the Heap\nbool Debug_Modem_Dump = false;\t\t// true = print the Modem Stuff\nbool Debug_Print_Events = false;\t\t// true = print event & packet processing\n\nTFixedIHeapClass<AircraftClass>\t\tAircraft;\nTFixedIHeapClass<AnimClass>\t\t\tAnims;\nTFixedIHeapClass<BuildingClass>\t\tBuildings;\nTFixedIHeapClass<BulletClass>\t\t\tBullets;\nTFixedIHeapClass<FactoryClass>\t\tFactories;\nTFixedIHeapClass<HouseClass>\t\t\tHouses;\nTFixedIHeapClass<InfantryClass>\t\tInfantry;\nTFixedIHeapClass<OverlayClass>\t\tOverlays;\nTFixedIHeapClass<SmudgeClass>\t\t\tSmudges;\nTFixedIHeapClass<TeamClass>\t\t\tTeams;\nTFixedIHeapClass<TeamTypeClass>\t\tTeamTypes;\nTFixedIHeapClass<TemplateClass>\t\tTemplates;\nTFixedIHeapClass<TerrainClass>\t\tTerrains;\nTFixedIHeapClass<TriggerClass>\t\tTriggers;\nTFixedIHeapClass<UnitClass>\t\t\tUnits;\nTFixedIHeapClass<VesselClass>\t\t\tVessels;\nTFixedIHeapClass<TriggerTypeClass>\tTriggerTypes;\n\nTFixedIHeapClass<HouseTypeClass>\t\tHouseTypes;\nTFixedIHeapClass<BuildingTypeClass>\tBuildingTypes;\nTFixedIHeapClass<AircraftTypeClass>\tAircraftTypes;\nTFixedIHeapClass<InfantryTypeClass>\tInfantryTypes;\nTFixedIHeapClass<BulletTypeClass>\tBulletTypes;\nTFixedIHeapClass<AnimTypeClass>\t\tAnimTypes;\nTFixedIHeapClass<UnitTypeClass>\t\tUnitTypes;\nTFixedIHeapClass<VesselTypeClass>\tVesselTypes;\nTFixedIHeapClass<TemplateTypeClass>\tTemplateTypes;\nTFixedIHeapClass<TerrainTypeClass>\tTerrainTypes;\nTFixedIHeapClass<OverlayTypeClass>\tOverlayTypes;\nTFixedIHeapClass<SmudgeTypeClass>\tSmudgeTypes;\n\n\n/*\n**\tThese are the instantiate static heap pointers for the various\n**\tCCPtr class objects that are allowed to exist. If the linker generates\n**\tan error about a missing heap pointer, then this indicates that CCPtr objects\n**\tfor that type are not allowed. For every case of a TFixedIHeap manager of\n**\tgame objects, then a CCPtr can be instantiated for it.\n*/\ntemplate<class T> FixedIHeapClass * CCPtr<AircraftClass>::Heap = &Aircraft;\ntemplate<class T> FixedIHeapClass * CCPtr<AnimClass>::Heap = &Anims;\ntemplate<class T> FixedIHeapClass * CCPtr<BuildingClass>::Heap = &Buildings;\ntemplate<class T> FixedIHeapClass * CCPtr<BulletClass>::Heap = &Bullets;\ntemplate<class T> FixedIHeapClass * CCPtr<FactoryClass>::Heap = &Factories;\ntemplate<class T> FixedIHeapClass * CCPtr<HouseClass>::Heap = &Houses;\ntemplate<class T> FixedIHeapClass * CCPtr<InfantryClass>::Heap = &Infantry;\ntemplate<class T> FixedIHeapClass * CCPtr<OverlayClass>::Heap = &Overlays;\ntemplate<class T> FixedIHeapClass * CCPtr<SmudgeClass>::Heap = &Smudges;\ntemplate<class T> FixedIHeapClass * CCPtr<TeamClass>::Heap = &Teams;\ntemplate<class T> FixedIHeapClass * CCPtr<TeamTypeClass>::Heap = &TeamTypes;\ntemplate<class T> FixedIHeapClass * CCPtr<TemplateClass>::Heap = &Templates;\ntemplate<class T> FixedIHeapClass * CCPtr<TerrainClass>::Heap = &Terrains;\ntemplate<class T> FixedIHeapClass * CCPtr<TriggerClass>::Heap = &Triggers;\ntemplate<class T> FixedIHeapClass * CCPtr<TriggerTypeClass>::Heap = &TriggerTypes;\n\ntemplate<class T> FixedIHeapClass * CCPtr<HouseTypeClass>::Heap = &HouseTypes;\ntemplate<class T> FixedIHeapClass * CCPtr<BuildingTypeClass>::Heap = &BuildingTypes;\ntemplate<class T> FixedIHeapClass * CCPtr<AircraftTypeClass>::Heap = &AircraftTypes;\ntemplate<class T> FixedIHeapClass * CCPtr<InfantryTypeClass>::Heap = &InfantryTypes;\ntemplate<class T> FixedIHeapClass * CCPtr<BulletTypeClass>::Heap = &BulletTypes;\ntemplate<class T> FixedIHeapClass * CCPtr<AnimTypeClass>::Heap = &AnimTypes;\ntemplate<class T> FixedIHeapClass * CCPtr<UnitTypeClass>::Heap = &UnitTypes;\ntemplate<class T> FixedIHeapClass * CCPtr<VesselTypeClass>::Heap = &VesselTypes;\ntemplate<class T> FixedIHeapClass * CCPtr<TemplateTypeClass>::Heap = &TemplateTypes;\ntemplate<class T> FixedIHeapClass * CCPtr<TerrainTypeClass>::Heap = &TerrainTypes;\ntemplate<class T> FixedIHeapClass * CCPtr<OverlayTypeClass>::Heap = &OverlayTypes;\ntemplate<class T> FixedIHeapClass * CCPtr<SmudgeTypeClass>::Heap = &SmudgeTypes;\n\n\n/* These variables are used to keep track of the slowest speed of a team */\nMPHType TeamMaxSpeed[10];\nSpeedType TeamSpeed[10];\nbool FormMove;\nSpeedType FormSpeed;\nMPHType FormMaxSpeed;\n\n\nchar _staging_buffer[32000];\n\n/*\n** Global flag for the life of Tanya.  If this flag is set, she is\n** no longer available.\n*/\nbool IsTanyaDead;\nbool SaveTanya;\n\n#ifdef FIXIT_ANTS\nbool AntsEnabled = false;\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nbool NewUnitsEnabled = false;\nbool SecretUnitsEnabled = false;\nint MTankDistance = 15;\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\nint CarrierLaunchDelay = 60;\n#endif\n#endif\n\nint NewINIFormat = 0;\n\nbool TimeQuake;\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nbool PendingTimeQuake;\nTARGET TimeQuakeCenter;\nfixed QuakeUnitDamage=0x300;\nfixed QuakeBuildingDamage=0x300;\nint QuakeInfantryDamage=25;\nint QuakeDelay;\nfixed ChronoTankDuration=0x300;\t// chrono override for chrono tanks\n#ifdef FIXIT_ENGINEER\t//\tchecked - ajw 9/28/98\nfixed EngineerDamage=0x55;\t\t\t// Amount of damage an engineer does\nfixed EngineerCaptureLevel=0x40;\t// Building damage level before engineer can capture\n#endif\n#endif\n\n#ifdef WIN32\nunsigned short\t\t\tHard_Error_Occured = 0;\nWWMouseClass *\t\t\tWWMouse = NULL;\nGraphicBufferClass\tSysMemPage(DEFAULT_SCREEN_WIDTH, 200, (void*)NULL);\nWinTimerClass *\t\tWindowsTimer=NULL;\nint\t\t\t\t\t\tScreenWidth=640;\nint\t\t\t\t\t\tScreenHeight=400;\nGraphicBufferClass\tModeXBuff;\nbool\t\t\t\t\t\tInMovie = FALSE;\t//Are we currently playing a VQ movie?\nHANDLE\t\t\t\t\thInstance;\nint\t\t\t\t\t\tAllDone;\n\n\n/***************************************************************************\n**\tThis is true if the game is the currently in focus windows app\n**\n*/\nbool GameInFocus = false;\n\n#endif\n\n\n/***************************************************************************\n**\tEncryption keys.\n*/\nPKey FastKey;\n#ifdef CHEAT_KEYS\nPKey SlowKey;\n#endif\n\n#ifdef FIXIT_NAME_OVERRIDE\n/***************************************************************************\n**\tThis is where the name overrides for the units will reside.\n*/\nchar const * NameOverride[25];\nint NameIDOverride[25];\n#endif\n\n/***************************************************************************\n**\tThese are the mission control structures. They hold the information about\n**\thow the missions should behave in the system.\n*/\nMissionControlClass MissionControl[MISSION_COUNT];\n\n\n/***************************************************************************\n**\tThere are various tutorial messages that can appear in the game. These\n**\tare called upon by number and pointed to by this array.\n*/\nchar const * TutorialText[225];\n\n\n/***************************************************************************\n**\tThis holds the rules database. The rules database won't change during the\n**\tprogram's run, but may need to be referenced intermitently.\n*/\nCCINIClass RuleINI;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nCCINIClass AftermathINI;\n#endif\n\n/***************************************************************************\n**\tThis points to the benchmark objects that are allocated only if the\n**\tmachine is running on a Pentium and this is a debug version.\n*/\nBenchmark * Benches;\n\n\n/***************************************************************************\n**\tGeneral rules that control the game.\n*/\nRulesClass Rule;\n\n\n/***************************************************************************\n** All keyboard input is routed through the object pointed to by this\n**\tkeyboard class pointer.\n*/\nKeyboardClass * Keyboard;\n\n\n/***************************************************************************\n**\tRemap control array. This is used to hold the remap\n**\ttables for the various possible player colors, and the color schemes\n** for dialogs.\n*/\nRemapControlType ColorRemaps[PCOLOR_COUNT];\n\n/*\n** Special remap scheme for font that hs to print over metallic tabs\n*/\nRemapControlType MetalScheme;\n\n/*\n** This remap table is for special purposes.  It consists of dark grey shades,\n** and is used for dimming things out.\n*/\nRemapControlType GreyScheme;\n\n\n/***************************************************************************\n**\tThis is the source of the random numbers used in the game. This controls\n**\tthe game logic and thus must be in sync with any networked machines.\n*/\nRandomClass NonCriticalRandomNumber;\nRandomStraw CryptRandom;\n\n\n/***************************************************************************\n**\tThis is a list of all selected objects (for this map). The support functions\n**\tare used to control access to this list. Do not modify it directly.\n*/\nDynamicVectorClass<ObjectClass *> CurrentObject;\n\n\n/***************************************************************************\n**\tThis is the game version.\n*/\nVersionClass VerNum;\n\n\n/***************************************************************************\n**\tThis is the VQ animation controller structure. It is filled in by reading\n**\tthe PLAYER.INI and overridden through program control.\n*/\nVQAConfig AnimControl;\n\nint PreserveVQAScreen;\t\t\t// Used for screen mode transition control.\nbool BreakoutAllowed = true;\t// \"true\" if aborting of movies is allowed.\nbool Brokeout;\t\t\t\t\t\t// Was the movie broken out of?\nbool SlowPalette = false;\t\t// Slow palette flag set?\n\n\n/***************************************************************************\n**\tThese are the movie names to use for mission briefing, winning, and losing\n**\tsequences. They are read from the INI file.\n*/\nScenarioClass Scen;\n\n\n/***************************************************************************\n**\tThis is the pending speech sample to play. This sample will be played\n**\tat the first opportunity.\n*/\nVoxType SpeakQueue = VOX_NONE;\n\n\n/***************************************************************************\n**\tThis records if the score (music) file is present. If not, then much of\n**\tthe streaming score system can be disabled.\n*/\nbool ScoresPresent;\n\n\n/***************************************************************************\n**\tThis flag will control whether there is a response from game units.\n**\tBy carefully controlling this global, multiple responses are suppressed\n**\twhen a large group of infantry is given the movement order.\n*/\nbool AllowVoice = true;\n\n\n/***************************************************************************\n**\tThis is the current frame number. This number is guaranteed to count\n**\tupward at the rate of one per game logic process. The target rate is 15\n**\tper second. This value is saved and restored with the saved game.\n*/\nlong Frame = 0;\n\n\n/***************************************************************************\n**\tThese globals are constantly monitored to determine if the player\n**\thas won or lost. They get set according to the trigger events associated\n**\twith the scenario.\n*/\nbool PlayerWins;\nbool PlayerLoses;\nbool PlayerRestarts;\n\n/*\n** This flag is set if the player neither wins nor loses; it's mostly for\n** multiplayer mode.\n*/\nbool PlayerAborts;\n\n\n/***************************************************************************\n**\tThis is the pointer for the speech staging buffer. This buffer is used\n**\tto hold the currently speaking voice data. Since only one speech sample\n**\tis played at a time, this buffer is only as big as the largest speech\n**\tsample that can be played.\n*/\nvoid * SpeechBuffer[2];\nVoxType SpeechRecord[2];\n\n\n/***************************************************************************\n**\tThe theater specific mixfiles are cached into the buffer pointed to by\n**\tthis global.\n*/\nBuffer * TheaterBuffer;\n\n\n/***************************************************************************\n**\tThis is a running accumulation of the number of ticks that were unused.\n** This accumulates into a useful value that contributes to a\n**\thistogram of game performance.\n*/\nlong SpareTicks;\nlong PathCount;\t\t\t// Number of findpaths called.\nlong CellCount;\t\t\t// Number of cells redrawn.\nlong TargetScan;\t\t\t// Number of target scans.\nlong SidebarRedraws;\t\t// Number of sidebar redraws.\n\n\n/***************************************************************************\n**\tThis is the monochrome debug page array. The various monochrome data\n**\tscreens are located here.\n*/\nMonoClass MonoArray[DMONO_COUNT];\nDMonoType MonoPage = DMONO_STRESS;\t// The current page.\n\n\n/***************************************************************************\n**\tThis holds the theater specific mixfiles.\n*/\nMFCD * TheaterData = 0;\nMFCD * MoviesMix = 0;\nMFCD * GeneralMix = 0;\nMFCD * ScoreMix = 0;\nMFCD * MainMix = 0;\nMFCD * ConquerMix = 0;\n\n\n/***************************************************************************\n**\tThis is the options control class. The options control such things as\n**\tgame speed, visual controls, and other user settings.\n*/\nGameOptionsClass Options;\n\n\n/***************************************************************************\n**\tLogic processing is controlled by this element. It handles both graphic\n**\tand AI logic.\n*/\nLogicClass Logic;\n\n\n/***************************************************************************\n**\tThis handles the background music.\n*/\nThemeClass Theme;\n\n\n/***************************************************************************\n**\tThis is the main control class for the map.\n*/\n#ifdef SCENARIO_EDITOR\nMapEditClass Map;\n#else\nMouseClass Map;\n#endif\n\n\n/**************************************************************************\n**\tThe running game score is handled by this class (and member functions).\n*/\nScoreClass Score;\n\n\n/***************************************************************************\n**\tThe running credit display is controlled by this class (and member\n**\tfunctions.\n*/\nCreditClass CreditDisplay;\n\n\n/**************************************************************************\n** This class records the special command override options that C&C\n**\tsupports.\n*/\nSpecialClass Special;\n\n\nbool PassedProximity;\t// used in display.cpp\n\n\n/***************************************************************************\n**\tThis is the scenario data for the currently loaded scenario.\n** These variables should all be set together.\n*/\nHousesType Whom;\t\t\t\t\t\t\t// Initial command line house choice.\nbool ScenarioInit;\nbool SpecialFlag = false;\n\n\n/***************************************************************************\n** This value tells the sidebar what items it's allowed to add.  The\n** lower the value, the simpler the sidebar will be. This value is the\n**\tdisplayed value for tech level in the multiplay dialogs. It remaps to\n**\tthe in-game rules.ini tech levels.\n*/\nint BuildLevel = 10;\t\t\t\t// Buildable level (1 = simplest)\n\n\n/***************************************************************************\n**\tThe various tutor and dialog messages are located in the data block\n**\treferenced by this pointer.\n*/\nchar const * SystemStrings;\nchar const * DebugStrings;\n\n\n/***************************************************************************\n**\tThe game plays as long as this var is true.\n*/\nbool GameActive;\n\n\n/***************************************************************************\n**\tThis is a scratch variable that is used to when a reference is needed to\n**\ta long, but the value wasn't supplied to a function. This is used\n**\tspecifically for the default reference value. As such, it is not stable.\n*/\nlong LParam;\n\n\n#ifdef SCENARIO_EDITOR\n/***************************************************************************\n** The currently-selected cell for the Scenario Editor\n*/\nCELL CurrentCell = 0;\n#endif\n\n\n/***************************************************************************\n**\tMost of the text in the game will use the six point font. These are the\n**\tpointers to the fonts. If it is NULL, then the font hasn't been loaded\n**\tyet.\n*/\nvoid const * Metal12FontPtr;\t//Font for use on in-game tabs in hires\nvoid const * MapFontPtr;\t\t// Standard very small font.\nvoid const * TypeFontPtr;\t\t// Teletype font for mission briefings.\nvoid const * Font3Ptr;\t\t\t// Standard very small font.\nvoid const * Font6Ptr;\t\t\t// Standard small font.\nvoid const * EditorFont;\t\t// Font used for scenario editor.\nvoid const * Font8Ptr;\t\t\t// 8 point proportional.\nvoid const * FontLEDPtr;\t\t// LED fixed point font.\nvoid const * VCRFontPtr;\t\t// VCR font pointer.\nvoid const * ScoreFontPtr;\t\t// font for score & map selection screens\nvoid const * GradFont6Ptr;\t\t// gradient 6 point font pointer.\n\n\n/***************************************************************************\n**\tThis is the house that the human player is currently playing.\n*/\nHouseClass * PlayerPtr;\n\n\n/***************************************************************************\n**\tSpecial palettes for MCGA mode goes here. These palette buffers are used\n**\tfor pictures that do not use the game palette or are used for fading to\n**\tblack.\n*/\nPaletteClass CCPalette;\nPaletteClass GamePalette;\n//PaletteClass InGamePalette;\nPaletteClass BlackPalette(RGBClass(0, 0, 0));\nPaletteClass WhitePalette(RGBClass(RGBClass::MAX_VALUE, RGBClass::MAX_VALUE, RGBClass::MAX_VALUE));\nPaletteClass OriginalPalette;\nPaletteClass ScorePalette;\n\n\n/***************************************************************************\n**\tThese are the event queues. One is for holding events until they are ready to be\n**\tsent to the remote computer for processing. The other list is for incoming events\n**\tthat need to be executed when the correct frame has been reached.\n*/\nQueueClass<EventClass, MAX_EVENTS> OutList;\nQueueClass<EventClass, (MAX_EVENTS * 64)> DoList;\n\n#ifdef MIRROR_QUEUE\nQueueClass<EventClass, (MAX_EVENTS * 64)> MirrorList;\n#endif\n\n\n/***************************************************************************\n**\tThese are arrays/lists of trigger pointers for each cell & the houses.\n*/\nDynamicVectorClass<TriggerClass *> HouseTriggers[HOUSE_COUNT];\nDynamicVectorClass<TriggerClass *> MapTriggers;\nint MapTriggerID;\nDynamicVectorClass<TriggerClass *> LogicTriggers;\nint LogicTriggerID;\n\n\n/***************************************************************************\n**\tThis is the list of BuildingTypes that define the AI's base.\n*/\nBaseClass Base;\n\n\n/***************************************************************************\n**\tThis is the list of carry over objects. These objects are part of the\n**\tpseudo saved game that might be carried along with the current saved\n**\tgame.\n*/\nCarryoverClass * Carryover;\n\n\n/***************************************************************************\n** This value is computed every time a new scenario is loaded; it's a\n** CRC of the INI and binary map files.\n*/\nunsigned long ScenarioCRC;\n\n\n/***************************************************************************\n** This class manages data specific to multiplayer games.\n*/\nSessionClass Session;\n#if(TIMING_FIX)\n//\n// These values store the min & max frame #'s for when MaxAhead >>increases<<.\n// If MaxAhead increases, and the other systems free-run to the new MaxAhead\n// value, they may miss an event generated after the MaxAhead event was sent,\n// but before it executed, since it will have been scheduled with the older,\n// shorter MaxAhead value.  This will cause a Packet_Received_Too_Late error.\n// The frames from the point where the new MaxAhead takes effect, up to that\n// frame Plus the new MaxAhead, represent a \"period of vulnerability\"; any\n// events received that are scheduled to execute during this period should\n// be re-scheduled for after that period.\n//\nint NewMaxAheadFrame1;\nint NewMaxAheadFrame2;\n#endif\n\n#ifdef FIXIT_VERSION_3\nbool\tbAftermathMultiplayer;\t\t//\tIs multiplayer game being played with Aftermath rules?\n#else\nunsigned long \tPlayingAgainstVersion;\t\t// Negotiated version number\nbool\t\t\t\tVersion107InMix;\t\t\t\t// Is there a v1.07 in the game\n#endif\n\n/***************************************************************************\n**\tThis is the null modem manager class.  Declaring this class doesn't\n** perform any allocations;\n*/\nNullModemClass NullModem (\n   16,\t\t\t\t\t\t\t\t\t\t\t// number of send entries\n\t16,\t\t\t\t\t\t\t\t\t\t\t// number of receive entries\n\t(MAX_SERIAL_PACKET_SIZE / sizeof(EventClass) ) * sizeof(EventClass) + sizeof( CommHeaderType ),\n\t0x1234);\t\t\t\t\t\t\t\t\t\t// Magic number must have each digit unique\n\t\t\t\t\t\t\t\t\t\t\t\t\t// and different from the queue magic number\n\n\n\n/***************************************************************************\n**\tThis is the network IPX manager class.  It handles multiple remote\n** connections.  Declaring this class doesn't perform any allocations;\n** the class itself is 140 bytes.\n*/\n//IPXManagerClass Ipx (\n//\tMAX (sizeof (GlobalPacketType), sizeof(RemoteFileTransferType)),\t\t// size of Global Channel packets\n//\t((546 - sizeof(CommHeaderType)) / sizeof(EventClass) ) * sizeof(EventClass),\n//\t10, \t\t\t\t\t\t\t\t\t\t\t\t\t// # entries in Global Queue\n//\t8, \t\t\t\t\t\t\t\t\t\t\t\t\t// # entries in Private Queues\n//\tVIRGIN_SOCKET, \t\t\t\t\t\t\t\t\t// Socket ID #\n//\tIPXGlobalConnClass::COMMAND_AND_CONQUER0);// Product ID #\n\nIPXManagerClass Ipx (\n\tMAX (sizeof (GlobalPacketType), sizeof(RemoteFileTransferType)),\t\t// size of Global Channel packets\n\t((546 - sizeof(CommHeaderType)) / sizeof(EventClass) ) * sizeof(EventClass),\n\t160, \t\t\t\t\t\t\t\t\t\t\t\t\t// # entries in Global Queue\n\t32, \t\t\t\t\t\t\t\t\t\t\t\t\t// # entries in Private Queues\n\tVIRGIN_SOCKET, \t\t\t\t\t\t\t\t\t// Socket ID #\n\tIPXGlobalConnClass::COMMAND_AND_CONQUER0);// Product ID #\n\n\n#if(TEN)\n/***************************************************************************\n** This is the connection manager for Ten.  Special Ten notes:\n** - TEN connection ID's are equal to the HousesType for that player.\n** - The TEN internal player ID is used to determine the player's color.\n** - Ten's broadcast destination address -1\n*/\nTenConnManClass *Ten = NULL;\n\n#endif\n\n\n#if(MPATH)\n/***************************************************************************\n** This is the connection manager for Ten.  Special Ten notes:\n** - MPATH connection ID's are equal to the HousesType for that player.\n** - The player's color is read from the OPTIONS.INI file\n** - MPath's broadcast destination address is 0\n*/\nMPlayerManClass *MPath = NULL;\n\n#endif\n\n\n/***************************************************************************\n**\tThis is the random-number seed; it's synchronized between systems for\n** multiplayer games.\n*/\nint Seed = 0;\n\n\n/***************************************************************************\n** If this value is non-zero, use it as the random # seed instead; this should\n** help reproduce some bugs.\n*/\nint CustomSeed = 0;\n\nint WindowList[][8] = {\n/* xbyte, ypixel, bytewid, pixelht, cursor color, bkgd color,\tcursor x, cursor y */\n\n\t/* do not change the first 2 entries!! they are necc. to the system */\n\n\t{0,0,40*8*RESFACTOR,200*RESFACTOR,WHITE,BLACK,0,0},\t/* screen window */\n\t{1*8,75,38*8,100,WHITE,BLACK,0,0},\t/* DOS Error window */\n\n\t// Tactical map.\n\t{0, 0, 40*8*RESFACTOR, 200*RESFACTOR, WHITE,LTGREY,0,0},\n\n\t// Initial menu window.\n\t{12*8, 199-42, 16*8, 42, LTGREY, DKGREY, 0, 0},\n\n\t// Sidebar clipping window.\n\t{0,0,0,0,0,0,0,0},\n\n\t// Scenario editor window.\n\t{5*8, 30, 30*8, 140, 0, 0, 0, 0},\n\n\t// Partial object draw sub-window.\n\t{0,0,0,0,WHITE,BLACK,0,0}\n};\n\n\n/* X,Y,Item Width,Items High,Selected,Norm Color,Sel Color,zero \t*/\nint MenuList[][8]={\n\t\t{1, 3, 12, 3, 0, WHITE, PINK, 0},\n};\n\n\n#ifdef WIN32\nGraphicBufferClass\tVisiblePage;\nGraphicBufferClass\tHiddenPage;\nGraphicViewPortClass\tSeenBuff(&VisiblePage, 0, 0, 640, 480);\nGraphicViewPortClass\tHidPage(&HiddenPage, 0, 0, 640, 480);\n#else\nGraphicBufferClass\tHidPage(DEFAULT_SCREEN_WIDTH, 201, (void*)NULL);\nGraphicBufferClass\tSeenBuff(320, 200, (void *)0xA0000L);\nVideoBufferClass\t\tSeenPage;\nGraphicBufferClass & VisiblePage = SeenBuff;\n#endif\n\n\n#ifdef WIN32\n#else\n#endif\n\nint \t\t\t\t\t\tSoundOn;\nCDTimerClass<SystemTimerClass> FrameTimer;\nCDTimerClass<SystemTimerClass> CountDownTimer;\n\nNewConfigType NewConfig;\nTheaterType LastTheater = THEATER_NONE;\t//Lets us know when theater type changes.\n\n\n/***************************************************************************\n**\tThis flag is for popping up dialogs that call the main loop.\n*/\nSpecialDialogType SpecialDialog = SDLG_NONE;\n\n\nint RequiredCD = -1;\nint CurrentCD = -1;\nint MouseInstalled;\n\n//\n// Variables for helping track how much time goes bye in routines\n//\nint LogLevel = 0;\nunsigned long LogLevelTime[ MAX_LOG_LEVEL ] = { 0 };\nunsigned long LogLastTime = 0;\nbool LogDump_Print = false;\t\t// true = print the Log time Stuff\n\n\n/***************************************************************************\n** Tick Count global timer object.\n*/\nTTimerClass<SystemTimerClass> TickCount = 0;\n\n\n/***************************************************************************\n**  Win32 specific globals\n*/\n#ifdef WIN32\n\nbool InDebugger = false;\nbool ReadyToQuit = false;\n\n#else\nbool IsTheaterShape = false;\t// must be defined only if not Win32\n#endif\t//WIN32\n\nGetCDClass\t\tCDList;\nint UnitBuildPenalty = 100;\n\n#ifdef MPEGMOVIE // Denzil 6/15/98\n#ifdef MCIMPEG\n#include \"mcimovie.h\"\nMCIMovie* MciMovie = NULL;\n#endif\n\n#include \"mpgset.h\"\nMPGSettings* MpgSettings = NULL;\n#endif\n\n#ifdef FIXIT_VERSION_3\t\t\t//\tFor endgame auto-sonar pulse.\nbool bAutoSonarPulse = false;\n#endif\n"
  },
  {
    "path": "CODE/GOPTIONS.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /counterstrike/GOPTIONS.CPP 6     3/15/97 7:18p Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OPTIONS.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 8, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 27, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   OptionsClass::Process -- Handles all the options graphic interface.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n#include \"goptions.h\"\n#include \"loaddlg.h\"\n#include \"sounddlg.h\"\n#include \"visudlg.h\"\n#include \"gamedlg.h\"\n#include \"textbtn.h\"\n#include \"descdlg.h\"\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n#include \"WolStrng.h\"\n#endif\n\nbool RedrawOptionsMenu;\n\n/***********************************************************************************************\n * OptionsClass::Process -- Handles all the options graphic interface.                         *\n *                                                                                             *\n *    This routine is the main control for the visual representation of the options            *\n *    screen. It handles the visual overlay and the player input.                              *\n *                                                                                             *\n * INPUT:      none                                                                            *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:      none                                                                         *\n *                                                                                             *\n * HISTORY:     12/31/1994 MML : Created.                                                      *\n *   06/23/1995 JLB : Handles restating the mission objective.                                 *\n *   07/27/1995 JLB : Adjusts menu for multiplay mode.                                         *\n *=============================================================================================*/\nvoid GameOptionsClass::Process(void)\n{\n\tstatic struct {\n\t\tint ID;\t\t\t\t// Button ID to use.\n\t\tint Text;\t\t\t// Text number to use for this button.\n\t\tbool Multiplay;\t// Allowed in multiplayer version?\n\t} _constants[] = {\n\t\t{BUTTON_LOAD,  \tTXT_LOAD_MISSION,    false},\n#ifdef FIXIT_MULTI_SAVE\n\t\t{BUTTON_SAVE,  \tTXT_SAVE_MISSION,    true},\n#else\n\t\t{BUTTON_SAVE,  \tTXT_SAVE_MISSION,    false},\n#endif\n\t\t{BUTTON_DELETE,\tTXT_DELETE_MISSION,  true},\n\t\t{BUTTON_GAME,  \tTXT_GAME_CONTROLS,   true},\n\t\t{BUTTON_QUIT,  \tTXT_QUIT_MISSION,    true},\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t{BUTTON_DRAW,  \tTXT_OK,    true},\n#endif\n\t\t{BUTTON_RESUME,\tTXT_RESUME_MISSION,  true},\n\t\t{BUTTON_RESTATE,\tTXT_RESTATE_MISSION, false},\n\t};\n\n\t/*\n\t**\tVariables.\n\t*/\n\tTextButtonClass * buttons = 0;\n\tint selection;\n\tbool pressed;\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\tint curbutton = 7;\n#else\n\tint curbutton = 6;\n#endif\n\tint y;\n\tTextButtonClass * buttonsel[ARRAY_SIZE(_constants)];\n\tstatic int num_buttons = sizeof(_constants)/sizeof(_constants[0]);\n\n\n\tint num_players = 0;\n\tint i;\n\n\t//\n\t// Compute the number of real players in the game; only allow saves\n\t// if there are more than 1.\n\t//\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\tif (!(HouseClass::As_Pointer(Session.Players[i]->Player.ID)->IsDefeated)) {\n\t\t\tnum_players++;\n\t\t}\n\t}\n\n\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tBuild the button list for all of the buttons for this dialog.\n\t*/\n\tint maxwidth = 0;\n\n\tfor (int index = 0; index < num_buttons ; index++ ) {\n\t\tint text = _constants[index].Text;\n\t\tbuttonsel[index] = NULL;\n\n\t\tif (Session.Type != GAME_NORMAL && !_constants[index].Multiplay) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif ( (Session.Type == GAME_SKIRMISH ||\n\t\t\t\t\tSession.Type == GAME_INTERNET) && text == TXT_SAVE_MISSION) {\n\t\t\tcontinue;\n\t\t}\n\n#ifdef FIXIT_VERSION_3\n\t\tif (Session.Type != GAME_NORMAL && ( num_players < 2 ) &&\n\t\t\t\t\ttext == TXT_SAVE_MISSION) {\n\t\t\tcontinue;\n\t\t}\n#else\n#ifdef FIXIT_MULTI_SAVE\n\t\tif (Session.Type != GAME_NORMAL && (num_players < 2 || PlayingAgainstVersion == VERSION_RED_ALERT_104) &&\n\t\t\t\t\ttext == TXT_SAVE_MISSION) {\n\t\t\tcontinue;\n\t\t}\n#endif\t//FIXIT_MULTI_SAVE\n#endif\n\n\t\tif (Session.Type == GAME_SKIRMISH && text == TXT_DELETE_MISSION) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (Session.Type != GAME_NORMAL && text == TXT_DELETE_MISSION) {\n\t\t\ttext = TXT_RESIGN;\n\t\t}\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\tif (index < 6) {\n#else\n\t\tif (index < 5) {\n#endif\n\t\t\ty = (SeenBuff.Get_Height() - OptionHeight)/2 + ButtonY + ((OButtonHeight+2) * index);\n\t\t} else {\n\t\t\ty = OptionY + ButtonResumeY;\n\t\t}\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\tTextButtonClass* g;\n\t\tif( _constants[index].ID == BUTTON_DRAW )\n\t\t{\n\t\t\tif( Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH && Session.Players.Count() == 2 )\n\t\t\t{\n\t\t\t\tif( Scen.bLocalProposesDraw )\n\t\t\t\t{\n\t\t\t\t\tif( !Scen.bOtherProposesDraw )\n\t\t\t\t\t\tg = new TextButtonClass( BUTTON_DRAW, TXT_WOL_RETRACT_DRAW, TPF_BUTTON, 0, y );\n\t\t\t\t\telse\n\t\t\t\t\t\tcontinue;\t\t//\tGame will end now anyway.\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif( !Scen.bOtherProposesDraw )\n\t\t\t\t\t\tg = new TextButtonClass( BUTTON_DRAW, TXT_WOL_PROPOSE_DRAW, TPF_BUTTON, 0, y );\n\t\t\t\t\telse\n\t\t\t\t\t\tg = new TextButtonClass( BUTTON_DRAW, TXT_WOL_ACCEPT_DRAW, TPF_BUTTON, 0, y );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t\tcontinue;\n\t\t}\n\t\telse\n\t\t\tg = new TextButtonClass(_constants[index].ID, text, TPF_BUTTON, 0, y);\n#else\n\t\tTextButtonClass * g = new TextButtonClass(_constants[index].ID, text, TPF_BUTTON, 0, y);\n#endif\n\n\t\tif (g->Width > maxwidth) {\n\t\t\tmaxwidth = g->Width;\n\t\t}\n\t\tif (buttons == NULL) {\n\t\t\tbuttons = g;\n\t\t} else {\n\t\t\tg->Add_Tail(*buttons);\n\t\t}\n\n\t\tbuttonsel[index] = g;\n\t}\n\n\t/*\n\t** BG: In skirmish mode, there is no 'restate' button, so we have to\n\t**     backtrack through the list to find the last valid button.\n\t*/\n\twhile(!buttonsel[curbutton-1]) curbutton--;\n\n\tbuttonsel[curbutton-1]->Turn_On();\n\n\t/*\n\t**\tForce all button lengths to match the maximum length of the widest button.\n\t*/\n\tGadgetClass * g = buttons;\n\twhile (g != NULL) {\n\t\tg->Width = max(maxwidth, 90 * RESFACTOR);\n\t\tg->X = OptionX+(OptionWidth-g->Width)/2;\n\t\tg = g->Get_Next();\n\t}\n//#ifdef FRENCH\n//\tbuttonsel[BUTTON_RESUME-1]->Width = 110 * RESFACTOR;\n//\tbuttonsel[BUTTON_RESUME-1]->X = OptionX + (17 * RESFACTOR) - 5;\n//#else\n\tbuttonsel[BUTTON_RESUME-1]->Width = 90 * RESFACTOR;\n\tbuttonsel[BUTTON_RESUME-1]->X = OptionX + (17 * RESFACTOR);\n//#endif\n\n\tif (Session.Type == GAME_NORMAL) {\n\t\tbuttonsel[BUTTON_RESTATE-1]->Width = 90 * RESFACTOR;\n\t\tbuttonsel[BUTTON_RESTATE-1]->X = OptionX+OptionWidth-(buttonsel[BUTTON_RESTATE-1]->Width+(17 * RESFACTOR));\n\t}\n\n\t/*\n\t**\tThis causes left mouse button clicking within the confines of the dialog to\n\t**\tbe ignored if it wasn't recognized by any other button or slider.\n\t*/\n\t(new GadgetClass(OptionX, OptionY, OptionWidth, OptionHeight, GadgetClass::LEFTPRESS))->Add_Tail(*buttons);\n\n\t/*\n\t**\tThis cause a right click anywhere or a left click outside the dialog region\n\t**\tto be equivalent to clicking on the return to game button.\n\t*/\n\t(new ControlClass(BUTTON_RESUME, 0, 0, SeenBuff.Get_Width(), SeenBuff.Get_Height(), GadgetClass::LEFTPRESS|GadgetClass::RIGHTPRESS))->Add_Tail(*buttons);\n\n\tKeyboard->Clear();\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER|TPF_TEXT);\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tbool display = true;\n\tbool process = true;\n\tpressed = false;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tif (Session.Type == GAME_NORMAL || Session.Type == GAME_SKIRMISH) {\n\t\t\tCall_Back();\n\t\t} else {\n\t\t\tif (Main_Loop()) {\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored = false;\n\t\t\tdisplay = true;\n\t\t}\n\t\t#endif\n\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display || RedrawOptionsMenu) {\n\n\t\t\t/*\n\t\t\t**\tRedraw the map.\n\t\t\t*/\n\t\t\tHidPage.Clear();\n\t\t\tMap.Flag_To_Redraw(true);\n\t\t\tMap.Render();\n\n\t\t\t/*\n\t\t\t**\tReset up the window.  Window x-coords are in bytes not pixels.\n\t\t\t*/\n\t\t\tSet_Window(WINDOW_EDITOR, OptionX, OptionY, OptionWidth, OptionHeight);\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t**\tDraw the background.\n\t\t\t*/\n\t\t\tDialog_Box(OptionX, OptionY, OptionWidth, OptionHeight);\n\n\t\t\t/*\n\t\t\t**\tDraw the arrows border if requested.\n\t\t\t*/\n \t\t\tDraw_Caption(TXT_OPTIONS, OptionX, OptionY, OptionWidth);\n\n\t\t\t/*\n\t\t\t**\tDisplay the version number at the bottom of the dialog box.\n\t\t\t*/\n#ifndef WIN32\n\t\t\tFancy_Text_Print(\"%s\\rV%s\",\n\t\t\t\t\t(OptionX+OptionWidth)-(17 * RESFACTOR),\n\t\t\t\t\tOptionY+OptionHeight-((Session.Type == GAME_NORMAL) ? (32 * RESFACTOR) : (24 * RESFACTOR)),\n\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\t\tTPF_EFNT|TPF_NOSHADOW|TPF_RIGHT,\n\t\t\t\t\tScen.ScenarioName,\n\t\t\t\t\tVersion_Name());\n\n#else\n\t\t\tFancy_Text_Print(\"%s\\rV%s\",\n\t\t\t\t\t(OptionX+OptionWidth)-(25 * RESFACTOR),\n\t\t\t\t\tOptionY+OptionHeight-((Session.Type == GAME_NORMAL) ? (32 * RESFACTOR) : (24 * RESFACTOR)),\n\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\t\tTPF_EFNT|TPF_NOSHADOW|TPF_RIGHT,\n\t\t\t\t\tScen.ScenarioName,\n\t\t\t\t\tVersion_Name());\n#endif\n\n\t\t\tbuttons->Draw_All();\n\t\t\tTabClass::Hilite_Tab(0);\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t\tRedrawOptionsMenu = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tKeyNumType input = buttons->Input();\n\n\t\t/*\n\t\t**\tProcess Input.\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_RESTATE | KN_BUTTON):\n\t\t\t\tselection = BUTTON_RESTATE;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_LOAD | KN_BUTTON):\n\t\t\t\tselection = BUTTON_LOAD;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_SAVE | KN_BUTTON):\n\t\t\t\tselection = BUTTON_SAVE;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_DELETE | KN_BUTTON):\n\t\t\t\tselection = BUTTON_DELETE;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_QUIT | KN_BUTTON):\n\t\t\t\tselection = BUTTON_QUIT;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_GAME | KN_BUTTON):\n\t\t\t\tselection = BUTTON_GAME;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t\tcase (BUTTON_DRAW | KN_BUTTON):\n\t\t\t\tselection = BUTTON_DRAW;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n#endif\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_RESUME | KN_BUTTON):\n\t\t\t\tselection = BUTTON_RESUME;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_UP):\n\t\t\t\tbuttonsel[curbutton-1]->Turn_Off();\n\t\t\t\tbuttonsel[curbutton-1]->Flag_To_Redraw();\n\t\t\t\tdo {\n\t\t\t\t\tcurbutton--;\n\t\t\t\t\tif (curbutton < 1) curbutton = num_buttons;\n\t\t\t\t} while (!buttonsel[curbutton-1]);\n\n\t\t\t\tbuttonsel[curbutton-1]->Turn_On();\n\t\t\t\tbuttonsel[curbutton-1]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_DOWN):\n\t\t\t\tbuttonsel[curbutton-1]->Turn_Off();\n\t\t\t\tbuttonsel[curbutton-1]->Flag_To_Redraw();\n\t\t\t\tdo {\n\t\t\t\t\tcurbutton++;\n\t\t\t\t\tif ( curbutton > num_buttons ) curbutton = 1;\n\t\t\t\t} while (!buttonsel[curbutton-1]);\n\n\t\t\t\tbuttonsel[curbutton-1]->Turn_On();\n\t\t\t\tbuttonsel[curbutton-1]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\t\tbuttonsel[curbutton-1]->IsPressed = true;\n\t\t\t\tbuttonsel[curbutton-1]->Draw_Me(true);\n\t\t\t\tselection = curbutton;\n\t\t\t\tpressed = true;\n\t\t\t\tKeyboard->Clear();\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (pressed) {\n\n\t\t\tbuttonsel[curbutton-1]->Turn_Off();\n\t\t\tbuttonsel[curbutton-1]->Flag_To_Redraw();\n\t\t\tcurbutton = selection;\n\t\t\tbuttonsel[curbutton-1]->Turn_On();\n\t\t\tbuttonsel[curbutton-1]->Flag_To_Redraw();\n\n\t\t\tswitch (selection) {\n\t\t\t\tcase BUTTON_RESTATE:\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tif (!Restate_Mission(Scen.ScenarioName, TXT_VIDEO, TXT_RESUME_MISSION/*KOTXT_OPTIONS*/)) {\n\t\t\t\t\t\tBreakoutAllowed = true;\n\t\t\t\t\t\tPlay_Movie(Scen.BriefMovie);\n\n\t\t\t\t\t\tBlackPalette.Adjust(0x08, WhitePalette);\n\t\t\t\t\t\tBlackPalette.Set();\n\t\t\t\t\t\tBlackPalette.Adjust(0xFF);\n\t\t\t\t\t\tBlackPalette.Set();\n\t\t\t\t\t\tGamePalette.Set();\n\n\t\t\t\t\t\tMap.Flag_To_Redraw(true);\n\t\t\t\t\t\tTheme.Queue_Song(THEME_PICK_ANOTHER);\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tBlackPalette.Adjust(0x08, WhitePalette);\n\t\t\t\t\t\tBlackPalette.Set();\n\t\t\t\t\t\tBlackPalette.Adjust(0xFF);\n\t\t\t\t\t\tBlackPalette.Set();\n\t\t\t\t\t\tGamePalette.Set();\n\t\t\t\t\t\tMap.Flag_To_Redraw(true);\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_LOAD):\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tif (LoadOptionsClass(LoadOptionsClass::LOAD).Process()) {\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_SAVE):\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\t\t\t\tLoadOptionsClass(LoadOptionsClass::SAVE).Process();\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tOutList.Add(EventClass(EventClass::SAVEGAME));\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_DELETE):\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tif (Session.Type != GAME_NORMAL) {\n\t\t\t\t\t\tif (Surrender_Dialog(TXT_SURRENDER)) {\n\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::DESTRUCT));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tLoadOptionsClass(LoadOptionsClass::WWDELETE).Process();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_QUIT):\n\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\t\t\t\tswitch (WWMessageBox().Process(TXT_CONFIRM_EXIT, TXT_ABORT, TXT_CANCEL, TXT_RESTART)) {\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\tQueue_Exit();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\tPlayerRestarts = true;\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (Surrender_Dialog(TXT_CONFIRM_EXIT)) {\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\tQueue_Exit();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//if (WWMessageBox().Process(TXT_CONFIRM_EXIT, TXT_YES, TXT_NO) == 0) {\n\t\t\t\t\t\t\t//process = false;\n\t\t\t\t\t\t\t//Queue_Exit();\n\t\t\t\t\t\t//} else {\n\t\t\t\t\t\t\t//display = true;\n\t\t\t\t\t\t//}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t\t\tcase BUTTON_DRAW:\n\t\t\t\t\tif( Scen.bLocalProposesDraw )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tRetract draw offer.\n\t\t\t\t\t\tOutList.Add(EventClass(EventClass::RETRACT_DRAW));\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif( !Scen.bOtherProposesDraw )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//\tPropose a draw?\n\t\t\t\t\t\t\tif( Surrender_Dialog( TXT_WOL_PROPOSE_DRAW_CONFIRM ) )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PROPOSE_DRAW));\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//\tAccept a draw?\n\t\t\t\t\t\t\tif( Surrender_Dialog( TXT_WOL_ACCEPT_DRAW_CONFIRM ) )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PROPOSE_DRAW));\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n#endif\n\n\t\t\t\tcase (BUTTON_GAME):\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tGameControlsClass().Process();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_RESUME):\n\t\t\t\t\tSave_Settings();\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tpressed = false;\n\t\t\tbuttonsel[curbutton-1]->IsPressed = false;\n\t\t\tbuttonsel[curbutton-1]->Turn_Off();\n\t\t\tbuttonsel[curbutton-1]->Flag_To_Redraw();\n\t\t}\n\t}\n\n\t/*\n\t**\tClean up and re-enter the game.\n\t*/\n\tbuttons->Delete_List();\n\n\t/*\n\t**\tRedraw the map.\n\t*/\n\tKeyboard->Clear();\n\tHidPage.Clear();\n\tMap.Flag_To_Redraw(true);\n\tMap.Render();\n}\n\n\nvoid GameOptionsClass::Adjust_Variables_For_Resolution(void)\n{\n\tOptionWidth\t\t=\t(216+8) * RESFACTOR;\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\tOptionHeight\t=\t111 * RESFACTOR;\n#else\n\tOptionHeight\t=\t100 * RESFACTOR;\n#endif\n\tOptionX\t\t\t=\t((SeenBuff.Get_Width() - OptionWidth) / 2);\n\tOptionY\t\t\t=\t((SeenBuff.Get_Height() - OptionHeight) / 2);\n\tButtonWidth\t\t=\t130 * RESFACTOR;\n\tOButtonHeight\t=\t9 * RESFACTOR;\n\tCaptionYPos\t\t=\t5 * RESFACTOR;\n\tButtonY\t\t\t=\t21 * RESFACTOR;\n\tBorder1Len\t\t=\t72 * RESFACTOR;\n\tBorder2Len\t\t=\t16 * RESFACTOR;\n\tButtonResumeY\t=\t(OptionHeight - (19 * RESFACTOR));\n}\n"
  },
  {
    "path": "CODE/GOPTIONS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/GOPTIONS.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OPTIONS.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 8, 1994                                                 *\n *                                                                                             *\n *                  Last Update : June 8, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef GOPTIONS_H\n#define GOPTIONS_H\n\n#include \"options.h\"\n#include \"gadget.h\"\n\n\nclass GameOptionsClass : public OptionsClass {\n\t\tenum GameOptionsButtonEnum {\n\t\t\tBUTTON_LOAD=1,\n\t\t\tBUTTON_SAVE,\n\t\t\tBUTTON_DELETE,\n\t\t\tBUTTON_GAME,\n\t\t\tBUTTON_QUIT,\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t\tBUTTON_DRAW,\n#endif\n\t\t\tBUTTON_RESUME,\n\t\t\tBUTTON_RESTATE,\n\n\t\t\tBUTTON_COUNT\n\t\t};\n\n\t\tenum GameOptionsEnum {\n\t\t\tOPTION_WIDTH=(216+8),\n\t\t\tOPTION_HEIGHT=100,\n\t\t\tOPTION_X=((320 - (216+8)) / 2),\n\t\t\tOPTION_Y=((200 - 100) / 2),\n#ifdef FRENCH\n\t\t\tBUTTON_WIDTH=142,\n#else\n\t\t\tBUTTON_WIDTH=130,\n#endif\n\t\t\tNUMBER_OF_BUTTONS=6,\t\t//\tajw Not used.\n\t\t\tCAPTION_Y_POS=5,\n\t\t\tBUTTON_Y=21,\n\t\t\tBORDER1_LEN=72,\n\t\t\tBORDER2_LEN=16,\n\t\t\tBUTTON_RESUME_Y=(100-15)\n\t\t};\n\n\tpublic:\n\t\tGameOptionsClass(void): OptionsClass () { };\n\t\tvoid  Adjust_Variables_For_Resolution(void);\n\t\tvoid Process(void);\n\n\tprivate:\n\t\tint\tOptionWidth;\n\t\tint \tOptionHeight;\n\t\tint \tOptionX;\n\t\tint \tOptionY;\n\t\tint \tButtonWidth;\n\t\tint \tOButtonHeight;\n\t\tint \tCaptionYPos;\n\t\tint \tButtonY;\n\t\tint \tBorder1Len;\n\t\tint \tBorder2Len;\n\t\tint \tButtonResumeY;\n\n};\n\n#endif\n"
  },
  {
    "path": "CODE/GSCREEN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/GSCREEN.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GSCREEN.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : January 19, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   GScreenClass::Add_A_Button -- Add a gadget to the game input system.                      *\n *   GScreenClass::Blit_Display -- Redraw the display from the hidpage to the seenpage.        *\n *   GScreenClass::Flag_To_Redraw -- Flags the display to be redrawn.                          *\n *   GScreenClass::GScreenClass -- Default constructor for GScreenClass.                       *\n *   GScreenClass::Init -- Init's the entire display hierarchy by calling all Init routines.   *\n *   GScreenClass::Init_Clear -- Sets the map to a known state.                                *\n *   GScreenClass::Init_IO -- Initializes the Button list ('Buttons').                         *\n *   GScreenClass::Init_Theater -- Performs theater-specific initializations.                  *\n *   GScreenClass::Input -- Fetches input and processes gadgets.                               *\n *   GScreenClass::One_Time -- Handles one time class setups.                                  *\n *   GScreenClass::Remove_A_Button -- Removes a gadget from the game input system.             *\n *   GScreenClass::Render -- General drawing dispatcher an display update function.            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\nGadgetClass * GScreenClass::Buttons = 0;\n\nGraphicBufferClass * GScreenClass::ShadowPage = 0;\n\n\n/***********************************************************************************************\n * GScreenClass::GScreenClass -- Default constructor for GScreenClass.                         *\n *                                                                                             *\n *    This constructor merely sets the display system, so that it will redraw the first time   *\n *    the render function is called.                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nGScreenClass::GScreenClass(void)\n{\n\tIsToUpdate = true;\n\tIsToRedraw = true;\n}\n\n\n/***********************************************************************************************\n * GScreenClass::One_Time -- Handles one time class setups.                                    *\n *                                                                                             *\n * This routine (and all those that overload it) must perform truly one-time initialization.   *\n * Such init's would normally be done in the constructor, but other aspects of the game may    *\n * not have been initialized at the time the constructors are called (such as the file system, *\n * the display, or other WWLIB subsystems), so many initializations should be deferred to the  *\n * One_Time init's.                                                                            *\n *                                                                                             *\n * Any variables set in this routine should be declared as static, so they won't be modified   *\n * by the load/save process.  Non-static variables will be over-written by a loaded game.      *\n *                                                                                             *\n * This function allocates the shadow buffer that is used for quick screen updates. If         *\n * there were any data files to load, they would be loaded at this time as well.               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine only ONCE at the beginning of the game.                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GScreenClass::One_Time(void)\n{\n\t/*\n\t**\tAllocate the screen shadow page. This page is used to reduce access to the\n\t**\tactual screen memory. It contains a duplicate of what the SEENPAGE is.\n\t*/\n\tButtons = 0;\n\tShadowPage = new GraphicBufferClass(320, 200);\n\tif (ShadowPage) {\n\t\tShadowPage->Clear();\n\t\tHidPage.Clear();\n\t}\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Init -- Init's the entire display hierarchy by calling all Init routines.     *\n *                                                                                             *\n * This routine shouldn't be overloaded.  It's the main map initialization routine, and will   *\n * perform a complete map initialization, from mixfiles to clearing the buffers.  Calling this *\n * routine results in calling every initialization routine in the entire map hierarchy.        *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      theater      theater to initialize to                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/28/1994 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid GScreenClass::Init(TheaterType theater)\n{\n\tInit_Clear();\n\tInit_IO();\n\tInit_Theater(theater);\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Init_Clear -- Sets the map to a known state.                                  *\n *                                                                                             *\n * This routine (and those that overload it) clears any buffers and variables to a known       *\n * state.  It assumes that all buffers are allocated & valid.  The map should be displayable   *\n * after calling this function, and should draw basically an empty display.                    *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/28/1994 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid GScreenClass::Init_Clear(void)\n{\n\t/*\n\t** Clear the ShadowPage & HidPage to force a complete shadow blit.\n\t*/\n\tif (ShadowPage) {\n\t\tShadowPage->Clear();\n\t\tHidPage.Clear();\n\t}\n\n\tIsToRedraw = true;\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Init_Theater -- Performs theater-specific initializations.                    *\n *                                                                                             *\n * This routine (and those that overload it) performs any theater-specific initializations     *\n * needed.  This will include setting the palette, setting up remap tables, etc.  This routine *\n * only needs to be called when the theater has changed.                                       *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/28/1994 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid GScreenClass::Init_Theater(TheaterType )\n{\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Init_IO -- Initializes the Button list ('Buttons').                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/28/1994 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid GScreenClass::Init_IO(void)\n{\n\t/*\n\t** Reset the button list.  This means that any other elements of the map that need\n\t** buttons must attach them after this routine is called!\n\t*/\n\tButtons = 0;\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Flag_To_Redraw -- Flags the display to be redrawn.                            *\n *                                                                                             *\n *    This function is used to flag the display system whether any rendering is needed. The    *\n *    parameter tells the system either to redraw EVERYTHING, or just that something somewhere *\n *    has changed and the individual Draw_It functions must be called. When a sub system       *\n *    determines that it needs to render something local to itself, it would call this routine *\n *    with a false parameter. If the entire screen gets trashed or needs to be rebuilt, then   *\n *    this routine will be called with a true parameter.                                       *\n *                                                                                             *\n * INPUT:   complete -- bool; Should the ENTIRE screen be redrawn?                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This doesn't actually draw the screen, it merely sets flags so that when the    *\n *             Render() function is called, the appropriate drawing steps will be performed.   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GScreenClass::Flag_To_Redraw(bool complete)\n{\n\tIsToUpdate = true;\n\tif (complete) {\n\t\tIsToRedraw = true;\n\t}\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Input -- Fetches input and processes gadgets.                                 *\n *                                                                                             *\n *    This routine will fetch the keyboard/mouse input and dispatch this through the gadget    *\n *    system.                                                                                  *\n *                                                                                             *\n * INPUT:   key      -- Reference to the key code (for future examination).                    *\n *                                                                                             *\n *          x,y      -- Reference to mouse coordinates (for future examination).               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GScreenClass::Input(KeyNumType & key, int & x, int & y)\n{\n\tkey = Keyboard->Check();\n\n\tx = Keyboard->Mouse_X();\n\ty = Keyboard->Mouse_Y();\n\n\tif (Buttons != NULL) {\n\n\t\t/*\n\t\t** If any buttons need redrawing, they will do so in the Input routine, and\n\t\t** they should draw themselves to the HidPage.  So, flag ourselves for a Blit\n\t\t** to show the newly drawn buttons.\n\t\t*/\n\t\tif (Buttons->Is_List_To_Redraw()) {\n\t\t\tFlag_To_Redraw(false);\n\t\t}\n\n#ifdef WIN32\n\t\tGraphicViewPortClass * oldpage= Set_Logic_Page(HidPage);\n#else\n\t\tGraphicBufferClass * oldpage= Set_Logic_Page(HidPage);\n#endif\n\n\t\tkey = Buttons->Input();\n\n\t\tSet_Logic_Page(oldpage);\n\n\t} else {\n\n\t\tif (key != 0) {\n\t\t\tkey = Keyboard->Get();\n\t\t}\n\t}\n\n\tAI(key, x, y);\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Add_A_Button -- Add a gadget to the game input system.                        *\n *                                                                                             *\n *    This will add a gadget to the game input system. The gadget will be processed in         *\n *    subsequent calls to the GScreenClass::Input() function.                                  *\n *                                                                                             *\n * INPUT:   gadget   -- Reference to the gadget that will be added to the input system.        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GScreenClass::Add_A_Button(GadgetClass & gadget)\n{\n\t/*\n\t**\tIf this gadget is already in the list, remove it before adding it in:\n\t**\t- If 1st gadget in list, use Remove_A_Button to remove it, to reset the\n\t**\t  value of 'Buttons' appropriately\n\t**\t- Otherwise, just call the Remove function for that gadget to remove it\n\t**\t  from any list it may be in\n\t*/\n\tif (Buttons == &gadget) {\n\t\tRemove_A_Button(gadget);\n\t} else {\n\t\tgadget.Remove();\n\t}\n\n\t/*\n\t**\tNow add the gadget to our list:\n\t**\t- If there are not buttons, start the list with this one\n\t**\t- Otherwise, add it to the tail of the existing list\n\t*/\n\tif (Buttons) {\n\t\tgadget.Add_Tail(*Buttons);\n\t} else {\n\t\tButtons = &gadget;\n\t}\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Remove_A_Button -- Removes a gadget from the game input system.               *\n *                                                                                             *\n * INPUT:   gadget   -- Reference to the gadget that will be removed from the input system.    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   'gadget' MUST be already a part of 'Buttons', or the new value of 'Buttons'     *\n *               will be invalid!                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GScreenClass::Remove_A_Button(GadgetClass & gadget)\n{\n\tButtons = gadget.Remove();\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Render -- General drawing dispatcher an display update function.              *\n *                                                                                             *\n *    This routine should be called in the main game loop (once every game frame). It will     *\n *    call the Draw_It() function if necessary. All rendering is performed to the LogicPage    *\n *    which is set to the HIDPAGE. After rendering has been performed, the HIDPAGE is          *\n *    copied to the visible page.                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This actually updates the graphic display. As a result it can take quite a      *\n *             while to perform.                                                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GScreenClass::Render(void)\n{\n\t//This is unnessasary surely?\tST - 10/16/96 2:30PM\n\t//if (Buttons && Buttons->Is_List_To_Redraw()) {\n\t//\tIsToRedraw = true;\n\t//}\n\n\n\tif (IsToUpdate || IsToRedraw) {\n\t\tBStart(BENCH_GSCREEN_RENDER);\n\n#ifdef WIN32\n\t\tGraphicViewPortClass * oldpage= Set_Logic_Page(HidPage);\n#else\n\t\tGraphicBufferClass * oldpage= Set_Logic_Page(HidPage);\n\n\t\tif (IsToRedraw) {\n\t\t\tHide_Mouse();\n\t\t\tSeenPage.To_Buffer(0, 0, 320, 200, ShadowPage);\n\t\t\tShow_Mouse();\n\t\t}\n#endif\n\n\t\tDraw_It(IsToRedraw);\n\n\t\tif (Buttons) Buttons->Draw_All(false);\n\n#ifdef SCENARIO_EDITOR\n\t\t/*\n\t\t** Draw the Editor's buttons\n\t\t*/\n\t\tif (Debug_Map) {\n\t\t\tif (Buttons) {\n\t\t\t\tButtons->Draw_All();\n\t\t\t}\n\t\t}\n#endif\n\t\t/*\n\t\t** Draw the multiplayer message system to the Hidpage at this point.\n\t\t** This way, they'll Blit along with the rest of the map.\n\t\t*/\n\t\tif (Session.Messages.Num_Messages() > 0) {\n\t\t\tSession.Messages.Set_Width(\n\t\t\t\tLepton_To_Cell(Map.TacLeptonWidth) * ICON_PIXEL_W);\n\t\t}\n\t\tSession.Messages.Draw();\n\n\t\tBlit_Display();\n\t\tIsToUpdate = false;\n\t\tIsToRedraw = false;\n\n\t\tBEnd(BENCH_GSCREEN_RENDER);\n\t\tSet_Logic_Page(oldpage);\n\t}\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Blit_Display -- Redraw the display from the hidpage to the seenpage.          *\n *                                                                                             *\n *    This routine is used to copy the correct display from the HIDPAGE                        *\n *    to the SEENPAGE.                                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1994 JLB : Created.                                                                 *\n *   05/01/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nextern \"C\" {\n\tvoid ModeX_Blit (GraphicBufferClass * source);\n}\n\nvoid GScreenClass::Blit_Display(void)\n{\n\tBStart(BENCH_BLIT_DISPLAY);\n\t#ifdef WIN32\n\t\tif (SeenBuff.Get_Width()!=320) {\n\t\t\tWWMouse->Draw_Mouse(&HidPage);\n\t\t\tHidPage.Blit(SeenBuff , 0 , 0 , 0 , 0 , HidPage.Get_Width() , HidPage.Get_Height() , (BOOL) FALSE );\n\t\t\tWWMouse->Erase_Mouse(&HidPage, FALSE);\n\t\t} else {\n\t\t\tModeX_Blit(&HiddenPage);\n\t\t}\n\t#else\n\t\tShadow_Blit(0, 0, 320, 200, HidPage, SeenPage, ShadowPage->Get_Buffer());\n\t#endif\n\tBEnd(BENCH_BLIT_DISPLAY);\n}\n\n\n"
  },
  {
    "path": "CODE/GSCREEN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/GSCREEN.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GSCREEN.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : December 15, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef GSCREEN_H\n#define GSCREEN_H\n\n#include\t\"function.h\"\n#include\t\"cell.h\"\n\nclass GScreenClass\n{\n\tpublic:\n\n\t\tGScreenClass(void);\n\t\tGScreenClass(NoInitClass const &) {};\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t\t// One-time initializations\n\t\tvirtual void Init(TheaterType = THEATER_NONE);\t// Inits everything\n\t\tvirtual void Init_Clear(void);\t\t\t\t\t\t// Clears all to known state\n\t\tvirtual void Init_IO(void);\t\t\t\t\t\t\t// Inits button list\n\t\tvirtual void Init_Theater(TheaterType theater);\t// Theater-specific inits\n\n\t\t/*\n\t\t**\tPlayer I/O is routed through here. It is called every game tick.\n\t\t*/\n\t\tvirtual void Input(KeyNumType & key, int & x, int & y);\n\t\tvirtual void AI(KeyNumType &, int, int) {};\n\t\tvirtual void Add_A_Button(GadgetClass & gadget);\n\t\tvirtual void Remove_A_Button(GadgetClass & gadget);\n\n\t\t/*\n\t\t**\tCalled when map needs complete updating.\n\t\t*/\n\t\tvirtual void Flag_To_Redraw(bool complete=false);\n\n\t\t/*\n\t\t**\tRender maintenance routine (call every game tick). Probably no need\n\t\t**\tto override this in derived classes.\n\t\t*/\n\t\tvirtual void Render(void);\n\n\t\t/*\n\t\t**\tIs called when actual drawing is required. This is the function to\n\t\t**\toverride in derived classes.\n\t\t*/\n\t\tvirtual void Draw_It(bool =false) {};\n\n\t\t/*\n\t\t**\tThis moves the hidpage up to the seenpage.\n\t\t*/\n\t\tvirtual void Blit_Display(void);\n\n\t\t/*\n\t\t**\tChanges the mouse shape as indicated.\n\t\t*/\n\t\tvirtual void Set_Default_Mouse(MouseType mouse, bool wsmall) = 0;\n\t\tvirtual bool Override_Mouse_Shape(MouseType mouse, bool wsmall) = 0;\n\t\tvirtual void Revert_Mouse_Shape(void) = 0;\n\t\tvirtual void Mouse_Small(bool wsmall) = 0;\n\n\t\t/*\n\t\t**\tMisc routines.\n\t\t*/\n\t\tvirtual void * Shadow_Address(void) {return(ShadowPage);};\n\n\t\t/*\n\t\t**\tThis points to the buttons that are used for input. All of the derived classes will\n\t\t**\tattached their specific buttons to this list.\n\t\t*/\n\t\tstatic GadgetClass * Buttons;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tIf the entire map is required to redraw, then this flag is true. This flag\n\t\t**\tis set by the Flag_To_Redraw function. Typically, this occurs when the screen\n\t\t**\thas been trashed or is first created.\n\t\t*/\n\t\tunsigned IsToRedraw:1;\n\n\t\t/*\n\t\t**\tIf only a sub-system of the map must be redrawn, then this flag will be set.\n\t\t**\tAn example of something that would set this flag would be an animating icon\n\t\t**\tin the sidebar. In such a case, complete redrawing of the entire display is not\n\t\t**\tnecessary, but the Draw_It function should still be called so that the appropriate\n\t\t**\tclass can perform it's rendering.\n\t\t*/\n\t\tunsigned IsToUpdate:1;\n\n\t\t/*\n\t\t**\tPointer to an exact copy of the visible graphic page. This copy is used to speed\n\t\t**\tdisplay rendering by using an only-update-changed-pixels algorithm.\n\t\t*/\n\t\tstatic GraphicBufferClass * ShadowPage;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/HDATA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/HDATA.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HDATA.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 22, 1994                                                 *\n *                                                                                             *\n *                  Last Update : September 4, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   HouseTypeClass::As_Reference -- Fetches a reference to the house specified.               *\n *   HouseTypeClass::From_Name -- Fetch house pointer from its name.                           *\n *   HouseTypeClass::HouseTypeClass -- Constructor for house type objects.                     *\n *   HouseTypeClass::Init_Heap -- Allocate all heap objects for the house types.               *\n *   HouseTypeClass::One_Time -- One-time initialization                                       *\n *   HouseTypeClass::Read_INI -- Fetch the house control values from ini database.             *\n *   HouseTypeClass::Remap_Table -- Fetches the remap table for this house.                    *\n *   HouseTypeClass::operator delete -- Returns a house type object back to the heap.          *\n *   HouseTypeClass::operator new -- Allocates a house type class object from special heap.    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\nstatic HouseTypeClass const HouseEngland(\n\tHOUSE_ENGLAND,\n\t\"England\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_ENGLAND,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"ENG\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_GREEN,\t\t\t\t// Remap color ID number.\n\t'E'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseGermany(\n\tHOUSE_GERMANY,\n\t\"Germany\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_GERMANY,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"GER\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_GREY,\t\t\t\t// Remap color ID number.\n\t'G'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseFrance(\n\tHOUSE_FRANCE,\n\t\"France\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_FRANCE,\t\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"FRA\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_BLUE,\t\t\t\t// Remap color ID number.\n\t'F'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseUkraine(\n\tHOUSE_UKRAINE,\n\t\"Ukraine\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_UKRAINE,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"UKA\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_ORANGE,\t\t\t\t// Remap color ID number.\n\t'K'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseUSSR(\n\tHOUSE_USSR,\n\t\"USSR\",\t\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_USSR,\t\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"RED\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_RED,\t\t\t\t\t// Remap color ID number.\n\t'U'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseGreece(\n\tHOUSE_GREECE,\n\t\"Greece\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_GREECE,\t\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"GRE\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_LTBLUE,\t\t\t\t// Remap color ID number.\n\t'G'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseTurkey(\n\tHOUSE_TURKEY,\n\t\"Turkey\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_TURKEY,\t\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"TRK\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_BROWN,\t\t\t\t// Remap color ID number.\n\t'T'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseSpain(\n\tHOUSE_SPAIN,\n\t\"Spain\",\t\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_SPAIN,\t\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"SPN\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_GOLD,\t\t\t\t// Remap color ID number.\n\t'S'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseGood(\n\tHOUSE_GOOD,\n\t\"GoodGuy\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_GOODGUY,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"GDI\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_LTBLUE,\t\t\t\t// Remap color ID number.\n\t'G'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseBad(\n\tHOUSE_BAD,\n\t\"BadGuy\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_BADGUY,\t\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"NOD\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_RED,\t\t\t\t\t// Remap color ID number.\n\t'B'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseCivilian(\n\tHOUSE_NEUTRAL,\n\t\"Neutral\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"CIV\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_GOLD,\t\t\t\t// Remap color ID number.\n\t'C'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseJP(\n\tHOUSE_JP,\n\t\"Special\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_JP,\t\t\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"JP\",\t\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_GOLD,\t\t\t\t// Remap color ID number.\n\t'J'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseMulti1(\n\tHOUSE_MULTI1,\n\t\"Multi1\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"MP1\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_GOLD,\t\t\t\t// Remap color ID number.\n\t'M'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseMulti2(\n\tHOUSE_MULTI2,\n\t\"Multi2\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"MP2\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_LTBLUE,\t\t\t\t// Remap color ID number.\n\t'M'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseMulti3(\n\tHOUSE_MULTI3,\n\t\"Multi3\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"MP3\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_RED,\t\t\t\t\t// Remap color ID number.\n\t'M'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseMulti4(\n\tHOUSE_MULTI4,\n\t\"Multi4\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"MP4\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_GREEN,\t\t\t\t// Remap color ID number.\n\t'M'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseMulti5(\n\tHOUSE_MULTI5,\n\t\"Multi5\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"MP5\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_ORANGE,\t\t\t\t// Remap color ID number.\n\t'M'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseMulti6(\n\tHOUSE_MULTI6,\n\t\"Multi6\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"MP6\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_GREY,\t\t\t\t// Remap color ID number.\n\t'M'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseMulti7(\n\tHOUSE_MULTI7,\n\t\"Multi7\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"MP7\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_BLUE,\t\t\t\t// Remap color ID number.\n\t'M'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseMulti8(\n\tHOUSE_MULTI8,\n\t\"Multi8\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"MP8\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_BROWN,\t\t\t\t// Remap color ID number.\n\t'M'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\n#ifdef OBSOLETE\nHouseTypeClass const * const HouseTypeClass::Pointers[HOUSE_COUNT] = {\n\t&HouseSpain,\n\t&HouseGreece,\n\t&HouseUSSR,\n\t&HouseEngland,\n\t&HouseUkraine,\n\t&HouseGermany,\n\t&HouseFrance,\n\t&HouseTurkey,\n\t&HouseGood,\n\t&HouseBad,\n\t&HouseCivilian,\n\t&HouseJP,\n\t&HouseMulti1,\n\t&HouseMulti2,\n\t&HouseMulti3,\n\t&HouseMulti4,\n\t&HouseMulti5,\n\t&HouseMulti6,\n\t&HouseMulti7,\n\t&HouseMulti8,\n};\n#endif\n\n\n/***********************************************************************************************\n * HouseTypeClass::HouseTypeClass -- Constructor for house type objects.                       *\n *                                                                                             *\n *    This is the constructor for house type objects. This object holds the constant data      *\n *    for the house type.                                                                      *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/21/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nHouseTypeClass::HouseTypeClass(\n\t\t\t\tHousesType house,\n\t\t\t\tchar const * ini,\n\t\t\t\tint fullname,\n\t\t\t\tchar const * ext,\n\t\t\t\tint lemon,\n\t\t\t\tPlayerColorType remapcolor,\n\t\t\t\tchar prefix) :\n\tAbstractTypeClass(RTTI_HOUSETYPE, house, fullname, ini),\n//\tRTTI(RTTI_HOUSETYPE),\n//\tID(house),\n\tHouse(house),\n//\tIniName(ini),\n//\tFullName(fullname),\n\tLemon(lemon),\n\tRemapColor(remapcolor),\n\tPrefix(prefix),\n\tFirepowerBias(1),\n\tGroundspeedBias(1),\n\tAirspeedBias(1),\n\tArmorBias(1),\n\tROFBias(1),\n\tCostBias(1),\n\tBuildSpeedBias(1)\n{\n\tstrncpy(Suffix, ext, 3);\n\tSuffix[3] = '\\0';\n}\n\n\n/***********************************************************************************************\n * HouseTypeClass::operator new -- Allocates a house type class object from special heap.      *\n *                                                                                             *\n *    This will allocate a house type object from the special heap that is used to maintain    *\n *    objects of this type.                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to the newly allocated house type object.                        *\n *                                                                                             *\n * WARNINGS:   If there is insufficient room, this routine may return NULL.                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * HouseTypeClass::operator new(size_t)\n{\n\treturn(HouseTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * HouseTypeClass::operator delete -- Returns a house type object back to the heap.            *\n *                                                                                             *\n *    This will return the house type object specified back into the special heap that         *\n *    is used to maintain house type objects.                                                  *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the house type object to delete.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseTypeClass::operator delete(void * ptr)\n{\n\tHouseTypes.Free((HouseTypeClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * HouseTypeClass::Init_Heap -- Allocate all heap objects for the house types.                 *\n *                                                                                             *\n *    This will preallocate all the house types. They must be allocated in a particular order. *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine should be called only once at the beginning of the game.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese house type class objects must be allocated in the exact order that they\n\t**\tare specified in the HousesType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew HouseTypeClass(HouseSpain);\n\tnew HouseTypeClass(HouseGreece);\n\tnew HouseTypeClass(HouseUSSR);\n\tnew HouseTypeClass(HouseEngland);\n\tnew HouseTypeClass(HouseUkraine);\n\tnew HouseTypeClass(HouseGermany);\n\tnew HouseTypeClass(HouseFrance);\n\tnew HouseTypeClass(HouseTurkey);\n\tnew HouseTypeClass(HouseGood);\n\tnew HouseTypeClass(HouseBad);\n\tnew HouseTypeClass(HouseCivilian);\n\tnew HouseTypeClass(HouseJP);\n\tnew HouseTypeClass(HouseMulti1);\n\tnew HouseTypeClass(HouseMulti2);\n\tnew HouseTypeClass(HouseMulti3);\n\tnew HouseTypeClass(HouseMulti4);\n\tnew HouseTypeClass(HouseMulti5);\n\tnew HouseTypeClass(HouseMulti6);\n\tnew HouseTypeClass(HouseMulti7);\n\tnew HouseTypeClass(HouseMulti8);\n}\n\n\n/***********************************************************************************************\n * HouseTypeClass::From_Name -- Fetch house pointer from its name.                             *\n *                                                                                             *\n *    This routine will convert the ASCII house name specified into a                          *\n *    real house number. Typically, this is used when processing a                             *\n *    scenario INI file.                                                                       *\n *                                                                                             *\n * INPUT:   name  -- ASCII name of house to process.                                           *\n *                                                                                             *\n * OUTPUT:  Returns with actual house number represented by the ASCII                          *\n *          name specified.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *   05/21/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nHousesType HouseTypeClass::From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\t\tif (stricmp(As_Reference(house).IniName, name) == 0) {\n//\t\t\tif (stricmp(Pointers[house]->IniName, name) == 0) {\n\t\t\t\treturn(house);\n\t\t\t}\n\t\t}\n\t}\n\treturn(HOUSE_NONE);\n}\n\n\n/***********************************************************************************************\n * HouseTypeClass::One_Time -- One-time initialization                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/21/1994 JLB : Converted to member function.                                            *\n *   06/19/1996 JLB : Converted to regular heap class management.                              *\n *=============================================================================================*/\nvoid HouseTypeClass::One_Time(void)\n{\n}\n\n\n/***********************************************************************************************\n * HouseTypeClass::As_Reference -- Fetches a reference to the house specified.                 *\n *                                                                                             *\n *    Use this routine to fetch a reference to the house number specified.                     *\n *                                                                                             *\n * INPUT:   house -- The house number (HousesType) to look up.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the HouseTypeClass object that matches the house       *\n *          number specified.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nHouseTypeClass & HouseTypeClass::As_Reference(HousesType house)\n{\n\treturn(*HouseTypes.Ptr(house));\n}\n\n\n/***********************************************************************************************\n * HouseTypeClass::Remap_Table -- Fetches the remap table for this house.                      *\n *                                                                                             *\n *    Use this routine to fetch the remap table assigned to this house. The remap table is     *\n *    what gives the house's units/buildings their distinctive color.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the remap table to use for this house.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned char const * HouseTypeClass::Remap_Table(void) const\n{\n\treturn(ColorRemaps[RemapColor].RemapTable);\n}\n\n\n/***********************************************************************************************\n * HouseTypeClass::Read_INI -- Fetch the house control values from ini database.               *\n *                                                                                             *\n *    This routine will fetch the rules controllable values for the house type from the        *\n *    INI database specified.                                                                  *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to fetch the house control values from.     *\n *                                                                                             *\n * OUTPUT:  bool; Was the house section found and processed?                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseTypeClass::Read_INI(CCINIClass & ini)\n{\n\tif (ini.Is_Present(Name())) {\n\t\tFirepowerBias = ini.Get_Fixed(Name(), \"Firepower\", FirepowerBias);\n\t\tGroundspeedBias = ini.Get_Fixed(Name(), \"Groundspeed\", GroundspeedBias);\n\t\tAirspeedBias = ini.Get_Fixed(Name(), \"Airspeed\", AirspeedBias);\n\t\tArmorBias = ini.Get_Fixed(Name(), \"Armor\", ArmorBias);\n\t\tROFBias = ini.Get_Fixed(Name(), \"ROF\", ROFBias);\n\t\tCostBias = ini.Get_Fixed(Name(), \"Cost\", CostBias);\n\t\tBuildSpeedBias = ini.Get_Fixed(Name(), \"BuildTime\", BuildSpeedBias);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "CODE/HEADER.MAC",
    "content": "%home%tof\n\n%home%tof/* $Header:$ */\n/***********************************************************************************************\n **             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                  **\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : %qProject Name$%col96*\n *                                                                                             *\n *                    File Name : %-r%-e%col96*\n *                                                                                             *\n *                   Programmer : %eProgrammer$%col96*\n *                                                                                             *\n *                   Start Date : %date%col96*\n *                                                                                             *\n *                  Last Update : %date%col96*\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n"
  },
  {
    "path": "CODE/HEAP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/HEAP.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HEAP.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/18/95                                                     *\n *                                                                                             *\n *                  Last Update : May 6, 1996 [JLB]                                            *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   FixedHeapClass::Allocate -- Allocate a sub-block from the heap.                           *\n *   FixedHeapClass::Clear -- Clears (and frees) the heap manager memory.                      *\n *   FixedHeapClass::FixedHeapClass -- Normal constructor for heap management class.           *\n *   FixedHeapClass::Free -- Frees a sub-block in the heap.                                    *\n *   FixedHeapClass::Free_All -- Frees all objects in the fixed heap.                          *\n *   FixedHeapClass::ID -- Converts a pointer to a sub-block index number.                     *\n *   FixedHeapClass::Set_Heap -- Assigns a memory block for this heap manager.                 *\n *   FixedHeapClass::~FixedHeapClass -- Destructor for the heap manager class.                 *\n *   FixedIHeapClass::Allocate -- Allocate an object from the heap.                            *\n *   FixedIHeapClass::Clear -- Clears the fixed heap of all entries.                           *\n *   FixedIHeapClass::Free -- Frees an object in the heap.                                     *\n *   FixedIHeapClass::Free_All -- Frees all objects out of the indexed heap.                   *\n *   FixedIHeapClass::Logical_ID -- Fetches the logical ID number.                             *\n *   FixedIHeapClass::Set_Heap -- Set the heap to the buffer provided.                         *\n *   TFixedIHeapClass::Code_Pointers -- codes pointers for every object, to prepare for save   *\n *   TFixedIHeapClass::Decode_Pointers -- Decodes all object pointers, for after loading       *\n *   TFixedIHeapClass::Load -- Loads all active objects                                        *\n *   TFixedIHeapClass::Save -- Saves all active objects                                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n#include\t\"heap.h\"\n#include\t<mem.h>\n#include\t<stdio.h>\n#include\t<stddef.h>\n#include\t<conio.h>\n#include\t<string.h>\n\n\n/***********************************************************************************************\n * FixedHeapClass::FixedHeapClass -- Normal constructor for heap management class.             *\n *                                                                                             *\n *    This is the normal constructor used for the heap manager class. This initializes         *\n *    the class but doesn't yet assign actual heap memory to this manager. That is handled     *\n *    by the Set_Heap() function.                                                              *\n *                                                                                             *\n * INPUT:   size  -- The size of the individual sub-blocks in this heap. This value is         *\n *                   typically the size of some class or structure.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The heap must first be assigned a block of memory to manage before it can       *\n *             be used.                                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nFixedHeapClass::FixedHeapClass(int size) :\n\tIsAllocated(false),\n\tSize(size),\n\tTotalCount(0),\n\tActiveCount(0),\n\tBuffer(0)\n{\n}\n\n\n/***********************************************************************************************\n * FixedHeapClass::~FixedHeapClass -- Destructor for the heap manager class.                   *\n *                                                                                             *\n *    This is the default constructor for the heap manager class. It handles freeing the       *\n *    memory assigned to this heap.                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nFixedHeapClass::~FixedHeapClass(void)\n{\n\tFixedHeapClass::Clear();\n}\n\n\n/***********************************************************************************************\n * FixedHeapClass::Set_Heap -- Assigns a memory block for this heap manager.                   *\n *                                                                                             *\n *    This routine is used to assign a memory heap to this object. A memory heap so assigned   *\n *    will start with all sub-blocks unallocated. After this routine is called, normal         *\n *    allocation and freeing may occur. This routine will allocate necessary memory if the     *\n *    buffer parameter is NULL.                                                                *\n *                                                                                             *\n * INPUT:   count    -- The number of objects that this heap should manage.                    *\n *                                                                                             *\n *          buffer   -- Pointer to pre-allocated buffer that this manager will use. If this    *\n *                      parameter is NULL, then memory will be automatically allocated.        *\n *                                                                                             *\n * OUTPUT:  bool; Was the heap successfully initialized?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FixedHeapClass::Set_Heap(int count, void * buffer)\n{\n\t/*\n\t**\tClear out the old heap data.\n\t*/\n\tClear();\n\n\t/*\n\t**\tIf there is no size to the objects in the heap, then this block memory\n\t**\thandler can NEVER function. Return with a failure condition.\n\t*/\n\tif (!Size) return(false);\n\n\t/*\n\t**\tIf there is no count specified, then this indicates that the heap should\n\t**\tbe disabled.\n\t*/\n\tif (!count) return(true);\n\n\t/*\n\t**\tInitialize the free boolean vector and the buffer for the actual\n\t**\tallocation objects.\n\t*/\n\tif (FreeFlag.Resize(count)) {\n\t\tif (!buffer) {\n\t\t\tbuffer = new char[count * Size];\n\t\t\tif (!buffer) {\n\t\t\t\tFreeFlag.Clear();\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t\tIsAllocated = true;\n\t\t}\n\t\tBuffer = buffer;\n\t\tTotalCount = count;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FixedHeapClass::Allocate -- Allocate a sub-block from the heap.                             *\n *                                                                                             *\n *    Finds the first available sub-block in the heap and returns a pointer to it. The sub-    *\n *    block is marked as allocated by this routine. If there are no more sub-blocks            *\n *    available, then this routine will return NULL.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the newly allocated sub-block.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * FixedHeapClass::Allocate(void)\n{\n\tif (ActiveCount < TotalCount) {\n\t\tint index = FreeFlag.First_False();\n\n\t\tif (index != -1) {\n\t\t\tActiveCount++;\n\t\t\tFreeFlag[index] = true;\n\t\t\treturn((*this)[index]);\n\t\t}\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * FixedHeapClass::Free -- Frees a sub-block in the heap.                                      *\n *                                                                                             *\n *    Use this routine to free a previously allocated sub-block in the heap.                   *\n *                                                                                             *\n * INPUT:   pointer  -- A pointer to the sub-block to free. This is the same pointer that      *\n *                      was returned from the Allocate() function.                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the deallocation successful? Failure could indicate a pointer that       *\n *                doesn't refer to this heap or a null pointer.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FixedHeapClass::Free(void * pointer)\n{\n\tif (pointer && ActiveCount) {\n\t\tint index = ID(pointer);\n\n\t\tif ((unsigned)index < TotalCount) {\n\t\t\tif (FreeFlag[index]) {\n\t\t\t\tActiveCount--;\n\t\t\t\tFreeFlag[index] = false;\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FixedHeapClass::ID -- Converts a pointer to a sub-block index number.                       *\n *                                                                                             *\n *    Use this routine to convert a pointer (returned by Allocate) into the sub-block          *\n *    index number. This index number can be used as a form of identifier for the block.       *\n *                                                                                             *\n * INPUT:   pointer  -- A pointer to the sub-block to convert into an ID number.               *\n *                                                                                             *\n * OUTPUT:  Returns with the index (ID) number for the sub-block specified. This number will   *\n *          range between 0 and the sub-block max -1. If -1 is returned, then the pointer      *\n *          was invalid.                                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FixedHeapClass::ID(void const * pointer) const\n{\n\tif (pointer && Size) {\n\t\treturn((int)(((char *)pointer - (char *)Buffer) / Size));\n\t}\n\treturn(-1);\n}\n\n\n/***********************************************************************************************\n * FixedHeapClass::Clear -- Clears (and frees) the heap manager memory.                        *\n *                                                                                             *\n *    This routine is used to bring the heap manager back into a non-functioning state. All    *\n *    memory allocated by this manager is freed. Any previous pointers to allocated blocks     *\n *    from this heap are now invalid.                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FixedHeapClass::Clear(void)\n{\n\t/*\n\t**\tFree the old buffer (if present).\n\t*/\n\tif (Buffer && IsAllocated) {\n\t\tdelete[] Buffer;\n\t}\n\tBuffer = 0;\n\tIsAllocated = false;\n\tActiveCount = 0;\n\tTotalCount = 0;\n\tFreeFlag.Clear();\n}\n\n\n/***********************************************************************************************\n * FixedHeapClass::Free_All -- Frees all objects in the fixed heap.                            *\n *                                                                                             *\n *    This routine will free all previously allocated objects out of the heap. Use this        *\n *    routine to ensure that the heap is empty.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the heap successfully cleared of all objects?                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FixedHeapClass::Free_All(void)\n{\n\tActiveCount = 0;\n\tFreeFlag.Reset();\n\treturn(true);\n}\n\n\n/////////////////////////////////////////////////////////////////////\n\n\n/***********************************************************************************************\n * FixedIHeapClass::Free_All -- Frees all objects out of the indexed heap.                     *\n *                                                                                             *\n *    Use this routine to free all previously allocated objects in the heap. This routine will *\n *    also clear out the allocated object vector as well.                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the heap successfully cleared of objects?                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FixedIHeapClass::Free_All(void)\n{\n\tActivePointers.Delete_All();\n\treturn(FixedHeapClass::Free_All());\n}\n\n\n/***********************************************************************************************\n * FixedIHeapClass::Clear -- Clears the fixed heap of all entries.                             *\n *                                                                                             *\n *    This routine will clear the entire heap. All memory that was allocation, will be freed   *\n *    by this routine. After calling this routine, the heap must either be resized or          *\n *    a new heap memory block specifically attached, before it can be used again.              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FixedIHeapClass::Clear(void)\n{\n\tFixedHeapClass::Clear();\n\tActivePointers.Clear();\n}\n\n\n/***********************************************************************************************\n * FixedIHeapClass::Set_Heap -- Set the heap to the buffer provided.                           *\n *                                                                                             *\n *    This routine will set the heap to use the buffer specified. Use this routine when a      *\n *    pre-allocated buffer is to be used for the heap. A heap that is assigned in this         *\n *    manner cannot be resized.                                                                *\n *                                                                                             *\n * INPUT:   count -- The number of objects that the buffer pointer can be used to track.       *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer to use when keeping track of the objects.        *\n *                                                                                             *\n * OUTPUT:  Was the heap assigned successfully?                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FixedIHeapClass::Set_Heap(int count, void * buffer)\n{\n\tClear();\n\tif (FixedHeapClass::Set_Heap(count, buffer)) {\n\t\tActivePointers.Resize(count);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FixedIHeapClass::Allocate -- Allocate an object from the heap.                              *\n *                                                                                             *\n *    This routine will allocate an object located in the heap. If no free object space        *\n *    could be found, then NULL is returned.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocated object memory block.                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * FixedIHeapClass::Allocate(void)\n{\n\tvoid * ptr = FixedHeapClass::Allocate();\n\tif (ptr)\t{\n\t\tActivePointers.Add(ptr);\n\t\tmemset (ptr, 0, Size);\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * FixedIHeapClass::Free -- Frees an object in the heap.                                       *\n *                                                                                             *\n *    This routine is used to free an object in the heap. Freeing is accomplished by marking   *\n *    the object's memory as free to be reallocated. The object is also removed from the       *\n *    allocated object pointer vector.                                                         *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to the object that is to be removed from the heap.             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FixedIHeapClass::Free(void * pointer)\n{\n\tif (FixedHeapClass::Free(pointer)) {\n\t\tActivePointers.Delete(pointer);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FixedIHeapClass::Logical_ID -- Fetches the logical ID number.                               *\n *                                                                                             *\n *    Ths logical ID number of a memory block is the index number of the block as if the       *\n *    heap consisted only of valid allocated blocks. This knowledge comes in handy when        *\n *    the real index number must be anticipated before a memory block packing process.         *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to an allocated block in the heap.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the logical index number of this block. The number returned must not  *\n *          be used as a regular index into the heap until such time as the heap has been      *\n *          compacted (by some means or another) without modifying the block order.            *\n *                                                                                             *\n * WARNINGS:   Runs in linear time.                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FixedIHeapClass::Logical_ID(void const * pointer) const\n{\n\tif (pointer != NULL) {\n\t\tfor (int index = 0; index < Count(); index++) {\n\t\t\tif (Active_Ptr(index) == pointer) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t}\n\t}\n\treturn(-1);\n}\n\n\n/***********************************************************************************************\n * TFixedIHeapClass::Save -- Saves all active objects                                          *\n *                                                                                             *\n * INPUT:   file      file to write to                                                         *\n *                                                                                             *\n * OUTPUT:  true = OK, false = error                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/15/1995 BRR : Created.                                                                 *\n *   03/12/1996 JLB : Uses in-place new operator for virtual table control.                    *\n *=============================================================================================*/\ntemplate<class T>\nint TFixedIHeapClass<T>::Save(Pipe & file) const\n{\n\t/*\n\t** Save the number of instances of this class\n\t*/\n\tfile.Put(&ActiveCount, sizeof(ActiveCount));\n\n\t/*\n\t** Save each instance of this class\n\t*/\n\tfor (int i = 0; i < ActiveCount; i++) {\n\n\t\t/*\n\t\t** Save the array index of the object, so it can be loaded back into the\n\t\t** same array location (so TARGET translations will work)\n\t\t*/\n\t\tint idx = ID(Ptr(i));\n\t\tfile.Put(&idx, sizeof(idx));\n\n\t\t/*\n\t\t** Save the object itself\n\t\t*/\n\t\tfile.Put(Ptr(i), sizeof(T));\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * TFixedIHeapClass::Load -- Loads all active objects                                          *\n *                                                                                             *\n * INPUT:   file      file to read from                                                        *\n *                                                                                             *\n * OUTPUT:  true = OK, false = error                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/15/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint TFixedIHeapClass<T>::Load(Straw & file)\n{\n\tint i;\t\t\t// loop counter\n\tint idx;\t\t\t// object index\n\tT * ptr;\t\t\t// object pointer\n\tint a_count;\n\n\t/*\n\t** Read the number of instances of this class\n\t*/\n\tif (file.Get(&a_count, sizeof(a_count)) != sizeof(a_count)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t** Error if more objects than we can hold\n\t*/\n\tif (a_count > TotalCount) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t** Read each class instance\n\t*/\n\tfor (i = 0; i < a_count; i++) {\n\t\t/*\n\t\t** Read the object's array index\n\t\t*/\n\t\tif (file.Get(&idx, sizeof(idx)) != sizeof(idx)) {\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t** Get a pointer to the object, activate that object\n\t\t*/\n\t\tptr = (T *)(*this)[idx];\n\t\tFreeFlag[idx] = true;\n\t\tActiveCount++;\n\t\tActivePointers.Add(ptr);\n\n\t\t/*\n\t\t** Load the object\n\t\t*/\n\t\tfile.Get(ptr, sizeof(T));\n\t\tnew(ptr) T(NoInitClass());\n//\t\tif (!ptr->Load(file)) {\n//\t\t\treturn(false);\n//\t\t}\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * TFixedIHeapClass::Code_Pointers -- codes pointers for every object, to prepare for save     *\n *                                                                                             *\n * INPUT:   file      file to read from                                                        *\n *                                                                                             *\n * OUTPUT:  true = OK, false = error                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/15/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid TFixedIHeapClass<T>::Code_Pointers(void)\n{\n\tint i;\n\n\tfor (i = 0; i < ActiveCount; i++) {\n\t\tPtr(i)->Code_Pointers();\n\t}\n}\n\n\n/***********************************************************************************************\n * TFixedIHeapClass::Decode_Pointers -- Decodes all object pointers, for after loading         *\n *                                                                                             *\n * INPUT:   file      file to read from                                                        *\n *                                                                                             *\n * OUTPUT:  true = OK, false = error                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/15/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid TFixedIHeapClass<T>::Decode_Pointers(void)\n{\n\tint i;\n\n\tfor (i = 0; i < ActiveCount; i++) {\n\t\tPtr(i)->Decode_Pointers();\n\t}\n}\n"
  },
  {
    "path": "CODE/HEAP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/HEAP.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HEAP.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/18/95                                                     *\n *                                                                                             *\n *                  Last Update : February 18, 1995 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef HEAP_H\n#define HEAP_H\n\n#include \"vector.h\"\n\n/**************************************************************************\n**\tThis is a block memory management handler. It is used when memory is to\n**\tbe treated as a series of blocks of fixed size. This is similar to an\n**\tarray of integral types, but unlike such an array, the memory blocks\n**\tare anonymously. This facilitates the use of this class when overloading\n**\tthe new and delete operators for a normal class object.\n*/\nclass FixedHeapClass\n{\n\tpublic:\n\t\tFixedHeapClass(int size);\n\t\tvirtual ~FixedHeapClass(void);\n\n\t\tint Count(void) const {return ActiveCount;};\n\t\tint Length(void) const {return TotalCount;};\n\t\tint Avail(void) const {return TotalCount-ActiveCount;};\n\n\t\tvirtual int ID(void const * pointer) const;\n\t\tvirtual int Set_Heap(int count, void * buffer=0);\n\t\tvirtual void * Allocate(void);\n\t\tvirtual void Clear(void);\n\t\tvirtual int Free(void * pointer);\n\t\tvirtual int Free_All(void);\n\n\t\tvoid * operator[](int index) {return ((char *)Buffer) + (index * Size);};\n\t\tvoid const * operator[](int index) const {return ((char *)Buffer) + (index * Size);};\n\n\tprotected:\n\t\t/*\n\t\t**\tIf the memory block buffer was allocated by this class, then this flag\n\t\t**\twill be true. The block must be deallocated by this class if true.\n\t\t*/\n\t\tunsigned IsAllocated:1;\n\n\t\t/*\n\t\t**\tThis is the size of each sub-block within the buffer.\n\t\t*/\n\t\tint Size;\n\n\t\t/*\n\t\t**\tThis records the absolute number of sub-blocks in the buffer.\n\t\t*/\n\t\tint TotalCount;\n\n\t\t/*\n\t\t**\tThis is the total blocks allocated out of the heap. This number\n\t\t**\twill never exceed Count.\n\t\t*/\n\t\tint ActiveCount;\n\n\t\t/*\n\t\t**\tPointer to the heap's memory buffer.\n\t\t*/\n\t\tvoid * Buffer;\n\n\t\t/*\n\t\t**\tThis is a boolean vector array of allocation flag bits.\n\t\t*/\n\t\tBooleanVectorClass FreeFlag;\n\n\tprivate:\n\t\t// The assignment operator is not supported.\n\t\tFixedHeapClass & operator = (FixedHeapClass const &);\n\n\t\t// The copy constructor is not supported.\n\t\tFixedHeapClass(FixedHeapClass const &);\n};\n\n\n/**************************************************************************\n**\tThis template serves only as an interface to the heap manager class. By\n**\tusing this template, the object pointers are automatically converted\n**\tto the correct type without any code overhead.\n*/\ntemplate<class T>\nclass TFixedHeapClass : public FixedHeapClass\n{\n\tpublic:\n\t\tTFixedHeapClass(void) : FixedHeapClass(sizeof(T)) {};\n\t\tvirtual ~TFixedHeapClass(void) {};\n\n\n\t\tvirtual int ID(T const * pointer) const {return FixedHeapClass::ID(pointer);};\n\t\tvirtual T * Alloc(void) {return (T*)FixedHeapClass::Allocate();};\n\t\tvirtual int Free(T * pointer) {return(FixedHeapClass::Free(pointer));};\n\n\t\tT & operator[](int index) {return *(T *)(((char *)Buffer) + (index * Size));};\n\t\tT const & operator[](int index) const {return *(T*)(((char *)Buffer) + (index * Size));};\n};\n\n\n/**************************************************************************\n**\tThis is a derivative of the fixed heap class. This class adds the\n**\tability to quickly iterate through the active (allocated) objects. Since the\n**\tactive array is a sequence of pointers, the overhead of this class\n**\tis 4 bytes per potential allocated object (be warned).\n*/\nclass FixedIHeapClass : public FixedHeapClass\n{\n\tpublic:\n\t\tFixedIHeapClass(int size) : FixedHeapClass(size) {};\n\t\tvirtual ~FixedIHeapClass(void) {};\n\n\t\tvirtual int Set_Heap(int count, void * buffer=0);\n\t\tvirtual void * Allocate(void);\n\t\tvirtual void Clear(void);\n\t\tvirtual int Free(void * pointer);\n\t\tvirtual int Free_All(void);\n\t\tvirtual int Logical_ID(void const * pointer) const;\n\t\tvirtual int Logical_ID(int id) const {return(Logical_ID((*this)[id]));}\n\n\t\tvirtual void * Active_Ptr(int index) {return ActivePointers[index];};\n\t\tvirtual void const * Active_Ptr(int index) const {return ActivePointers[index];};\n\n\t\t/*\n\t\t**\tThis is an array of pointers to allocated objects. Using this array\n\t\t**\tto control iteration through the objects ensures a minimum of processing.\n\t\t**\tIt also allows access to this array so that custom sorting can be\n\t\t**\tperformed.\n\t\t*/\n\t\tDynamicVectorClass<void *> ActivePointers;\n};\n\n\n/**************************************************************************\n**\tThis template serves only as an interface to the iteratable heap manager\n**\tclass. By using this template, the object pointers are automatically converted\n**\tto the correct type without any code overhead.\n*/\nclass FileClass;\ntemplate<class T>\nclass TFixedIHeapClass : public FixedIHeapClass\n{\n\tpublic:\n\t\tTFixedIHeapClass(void) : FixedIHeapClass(sizeof(T)) {};\n\t\tvirtual ~TFixedIHeapClass(void) {};\n\n\t\tvirtual int ID(T const * pointer) const {return FixedIHeapClass::ID(pointer);};\n\t\tvirtual int Logical_ID(T const * pointer) const {return(FixedIHeapClass::Logical_ID(pointer));}\n\t\tvirtual int Logical_ID(int id) const {return(FixedIHeapClass::Logical_ID(id));}\n\t\tvirtual T * Alloc(void) {return (T*)FixedIHeapClass::Allocate();};\n\t\tvirtual int Free(T * pointer) {return FixedIHeapClass::Free(pointer);};\n\t\tvirtual int Free(void * pointer) {return FixedIHeapClass::Free(pointer);};\n\t\tvirtual int Save(Pipe & file) const;\n\t\tvirtual int Load(Straw & file);\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n\n\t\tvirtual T * Ptr(int index) const {return (T*)FixedIHeapClass::ActivePointers[index];};\n\t\tvirtual T * Raw_Ptr(int index) {return (T*)((*this)[index]);};\n};\n\n\n#endif\n\n\n"
  },
  {
    "path": "CODE/HELP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/HELP.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HELP.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/18/94                                                     *\n *                                                                                             *\n *                  Last Update : September 22, 1995 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   HelpClass::Draw_Help -- Display the help message (if necessary).                          *\n *   HelpClass::HelpClass -- Default constructor for the help processor.                       *\n *   HelpClass::Help_AI -- Handles the help text logic.                                        *\n *   HelpClass::Help_Text -- Assigns text as the current help text.                            *\n *   HelpClass::Init_Clear -- Sets help system to a known state.                               *\n *   HelpClass::Overlap_List -- Returns with offset list for cells under help text.            *\n *   HelpClass::Scroll_Map -- Makes sure scrolling doesn't leave text shards.                  *\n *   HelpClass::Set_Cost -- Initiates the second line of help text showing item cost.          *\n *   HelpClass::Set_Tactical_Position -- Sets the position of the tactical map.                *\n *   HelpClass::Set_Tactical_Position -- Sets the tactical map position.                       *\n *   HelpClass::Set_Tactical_Position -- Sets the tactical map position.                       *\n *   HelpClass::Set_Text -- Determines the overlap list and draw coordinates.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n/*\n**\tThis is the holding buffer for the text overlap list. This buffer must be in the near\n**\tdata segment. It will be filled in by the Set_Text() function.\n*/\nshort const HelpClass::OverlapList[60] = {\n\tREFRESH_EOL\n};\n\nchar const * HelpClass::HelpText;\n\n\n/***********************************************************************************************\n * HelpClass::HelpClass -- Default constructor for the help processor.                         *\n *                                                                                             *\n *    The help processor is initialized by this routine. It merely sets up the help engine     *\n *    to the default state. The default state will not display any help text. Call the         *\n *    Help_Text() function to enable help processing.                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nHelpClass::HelpClass(void) :\n\tHelpX(0),\n\tHelpY(0),\n\tHelpWidth(0),\n\tIsRight(false),\n\tCost(0),\n\tX(0),\n\tY(0),\n\tDrawX(0),\n\tDrawY(0),\n\tWidth(0),\n\tText(TXT_NONE),\n\tColor(LTGREY),\n\tCountDownTimer(0)\n{\n}\n\n\n/***********************************************************************************************\n * HelpClass::Init_Clear -- Sets help system to a known state.                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HelpClass::Init_Clear(void)\n{\n\tTabClass::Init_Clear();\n\n\tSet_Text(TXT_NONE);\n}\n\n\n/***********************************************************************************************\n * HelpClass::Overlap_List -- Returns with offset list for cells under help text.              *\n *                                                                                             *\n *    Use this routine to fetch an offset list for the cells under the text displayed. If      *\n *    there is no text displayed, then the list will consist of just the terminator code.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the offset list for the help text overlap. The offset    *\n *          list is based on the tactical map upper left corner cell.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * HelpClass::Overlap_List(void) const\n{\n\tif (Text == TXT_NONE || CountDownTimer) {\n\t\t((short &)(OverlapList[0])) = REFRESH_EOL;\n\t}\n\treturn(OverlapList);\n}\n\n\n/***********************************************************************************************\n * HelpClass::Help_AI -- Handles the help text logic.                                          *\n *                                                                                             *\n *    This routine handles tracking the mouse position to see if the mouse remains stationary  *\n *    for the required amount of time. If the time requirement has been met, then it flags     *\n *    the help system to display the help text the next time the Draw_Help() function is       *\n *    called.                                                                                  *\n *                                                                                             *\n * INPUT:   key   -- Keyboard input code.                                                      *\n *                                                                                             *\n *          x,y   -- Mouse coordinates.                                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine must be called once and only once per game frame (15 times per     *\n *             second).                                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/18/1994 JLB : Created.                                                                 *\n *   12/31/1994 JLB : Uses mouse coordinates as passed in.                                     *\n *=============================================================================================*/\nvoid HelpClass::AI(KeyNumType &key, int x, int y)\n{\n\tif (!CountDownTimer && !IsRight && (x != X || y != Y)) {\n\t\tHelp_Text(TXT_NONE);\n\t}\n\n\t/*\n\t**\tProcess the countdown timer only if it hasn't already expired and there is\n\t**\ta real help text message to display.\n\t*/\n\tif (CountDownTimer && !HelpText && Text != TXT_NONE) {\n\n\t\t/*\n\t\t**\tIf the mouse has moved, then reset the timer since a moving mouse is not\n\t\t**\tsupposed to bring up the help text.\n\t\t*/\n\t\tif (!IsRight && (X != x || Y != y)) {\n\t\t\tX = x;\n\t\t\tY = y;\n\t\t\tCountDownTimer = HELP_DELAY;\n\t\t\tHelp_Text(TXT_NONE);\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf the delay has expired, then the text must be drawn. Build the help text\n\t\t\t**\toverlay list at this time. Better to do it now, when we KNOW it is needed, then\n\t\t\t**\tto do it earlier when it might not be needed.\n\t\t\t*/\n\t\t\tSet_Text(Text);\n\t\t}\n\t}\n\n\tTabClass::AI(key, x, y);\n}\n\n\n/***********************************************************************************************\n * HelpClass::Help_Text -- Assigns text as the current help text.                              *\n *                                                                                             *\n *    Use this routine to change the help text that will pop up if the cursor isn't moved      *\n *    for the help delay duration. Call this routine as often as desired.                      *\n *                                                                                             *\n * INPUT:   text  -- The text number for the help text to use.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HelpClass::Help_Text(int text, int x, int y, int color, bool quick)\n{\n\tif (text != Text) {\n\n\t\t/*\n\t\t**\tIf there is an existing text message, then flag the map to redraw the underlying\n\t\t**\ticons so that the text message is erased.\n\t\t*/\n\t\tif (Text != TXT_NONE) {\n\t\t\tRefresh_Cells(Coord_Cell(TacticalCoord), &OverlapList[0]);\n\t\t}\n\n\t\t/*\n\t\t**\tRecord the position of the mouse. This recorded position will be used to determine\n\t\t**\tif the mouse has moved. A moving mouse prevents the help text from popping up.\n\t\t*/\n\t\tX = x;\n\t\tif (x == -1) X = Get_Mouse_X();\n\t\tY = y;\n\t\tif (y == -1) Y = Get_Mouse_Y();\n\t\tIsRight = (y != -1) || (x != -1);\n\n\t\tif (quick) {\n\t\t\tCountDownTimer = 1;\n\t\t} else {\n\t\t\tCountDownTimer = HELP_DELAY;\n\t\t}\n\n\t\t/*\n\t\t** All help text prints in the same color for E3\n\t\t*/\n\t\t//Color = color;\n\t\tcolor = color;\n\t\tColor = HELP_TEXT_COLOR;\n\t\tText = text;\n\t\tCost = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * HelpClass::Draw_Help -- Display the help message (if necessary).                            *\n *                                                                                             *\n *    This function will print the help text if it thinks it should. The timer and text        *\n *    message can control whether this occurs. If there is no help text or the countdown timer *\n *    has not expired, then no text will be printed.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HelpClass::Draw_It(bool forced)\n{\n\tTabClass::Draw_It(forced);\n\n\tforced = false;\t\t// TCTCTCTC\n\tif (Text != TXT_NONE && (forced || !CountDownTimer)) {\n\n\t\tif (LogicPage->Lock()) {\n\t\t\tPlain_Text_Print(Text, DrawX, DrawY, Color, BLACK, TPF_MAP|TPF_NOSHADOW);\n\t\t\tLogicPage->Draw_Rect(DrawX-1, DrawY-1, DrawX+Width+1, DrawY+FontHeight, Color);\n\n\t\t\tif (Cost) {\n\t\t\t\tchar buffer[15];\n\t\t\t\tsprintf(buffer, \"$%d\", Cost);\n\t\t\t\tint width = String_Pixel_Width(buffer);\n\n\t\t\t\tPlain_Text_Print(buffer, DrawX, DrawY+FontHeight, Color, BLACK, TPF_MAP|TPF_NOSHADOW);\n\t\t\t\tLogicPage->Draw_Rect(DrawX-1, DrawY+FontHeight, DrawX+width+1, DrawY+FontHeight+FontHeight-1, Color);\n\t\t\t\tLogicPage->Draw_Line(DrawX, DrawY+FontHeight, DrawX+min(width+1, Width)-1, DrawY+FontHeight, BLACK);\n\t\t\t}\n\t\t\tLogicPage->Unlock();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HelpClass::Set_Text -- Determines the overlap list and draw coordinates.                    *\n *                                                                                             *\n *    This routine is used to build the overlap list -- used for icon refreshing. It also      *\n *    determines if the text can fit on the screen and makes adjustments so that it will.      *\n *                                                                                             *\n * INPUT:   text  -- The text number to set the help system to use.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/18/1994 JLB : Created.                                                                 *\n *   12/11/1994 JLB : Won't draw past tactical map edges.                                      *\n *=============================================================================================*/\nvoid HelpClass::Set_Text(int text)\n{\n\tif (text != TXT_NONE) {\n\t\tText = text;\n\t\tPlain_Text_Print(TXT_NONE, 0, 0, 0, 0, TPF_MAP|TPF_NOSHADOW);\n\t\tWidth = String_Pixel_Width(Text_String(Text));\n\t\tif (IsRight) {\n\t\t\tDrawX = X - Width;\n\t\t\tDrawY = Y;\n\t\t} else {\n\t\t\tint right = TacPixelX + Lepton_To_Pixel(TacLeptonWidth) - 3*RESFACTOR;\n\t\t\tint bottom = TacPixelY + Lepton_To_Pixel(TacLeptonHeight) - 1*RESFACTOR;\n\n\t\t\tDrawX = X+X_OFFSET;\n\t\t\tDrawY = Y+Y_OFFSET;\n\t\t\tif (DrawX + Width > right) {\n\t\t\t\tDrawX -= (DrawX+Width) - right;\n\t\t\t}\n\t\t\tif (DrawY + 10*RESFACTOR > bottom) {\n\t\t\t\tDrawY -= (DrawY+10*RESFACTOR) - bottom;\n\t\t\t}\n\t\t\tif (DrawX < TacPixelX+1) DrawX = TacPixelX+1;\n\t\t\tif (DrawY < TacPixelY+1) DrawY = TacPixelY+1;\n\t\t}\n\t\tmemcpy((void*)OverlapList, Text_Overlap_List(Text_String(Text), DrawX-1, DrawY), sizeof(OverlapList));\n\t\t*(short *)&OverlapList[ARRAY_SIZE(OverlapList)-1] = REFRESH_EOL;\n\t}\n}\n\n\n/***********************************************************************************************\n * HelpClass::Scroll_Map -- Makes sure scrolling doesn't leave text shards.                    *\n *                                                                                             *\n *    This routine intercepts the map scrolling request and then makes sure that if, in fact,  *\n *    the map is going to scroll, then reset and erase the help text so that it doesn't        *\n *    mess up the display.                                                                     *\n *                                                                                             *\n * INPUT:   facing   -- The direction to scroll (unused by this routine).                      *\n *                                                                                             *\n *          really   -- If the scroll is actually going to occur, rather than just be examined *\n *                      for legality, then this parameter will be true. If this parameter is   *\n *                      true, then the help text is reset.                                     *\n *                                                                                             *\n * OUTPUT:  Returns if it can, or did, scroll in the requested direction.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HelpClass::Scroll_Map(DirType facing, int & distance, bool really)\n{\n\tif (really) {\n\t\tHelp_Text(TXT_NONE);\n\t}\n\treturn(TabClass::Scroll_Map(facing, distance, really));\n}\n\n\n/***********************************************************************************************\n * HelpClass::Set_Cost -- Initiates the second line of help text showing item cost.            *\n *                                                                                             *\n *    Use this routine after the Help_Text() function to activate the second line. The second  *\n *    line displays a cost. Typically, this is used by the sidebar to display the cost of the  *\n *    specified item.                                                                          *\n *                                                                                             *\n * INPUT:   cost  -- The cost to associate with this help text. If this value is zero, then    *\n *                   no second line is displayed, so don't pass in zero.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/09/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HelpClass::Set_Cost(int cost)\n{\n\tCost = cost;\n}\n\n\n/***********************************************************************************************\n * HelpClass::Set_Tactical_Position -- Sets the position of the tactical map.                  *\n *                                                                                             *\n *    This routine will set the position of the tactical map. At this class level, it merely   *\n *    makes sure that the help text disappears when this happens. The lower level classes      *\n *    actually change the map's position.                                                      *\n *                                                                                             *\n * INPUT:   coord -- The new coordinate to make the upper left corner of the visible display.  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HelpClass::Set_Tactical_Position(COORDINATE coord)\n{\n\tif (TacticalCoord != coord) {\n\t\tHelp_Text(TXT_NONE);\n\t}\n\tTabClass::Set_Tactical_Position(coord);\n}\n"
  },
  {
    "path": "CODE/HELP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/HELP.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HELP.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/18/94                                                     *\n *                                                                                             *\n *                  Last Update : November 18, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef HELP_H\n#define HELP_H\n\n#include\t\"tab.h\"\n\n#define HELP_TEXT_COLOR 80\t//158\t\t//Goldy/orange\n\nclass HelpClass: public TabClass\n{\n\tpublic:\n\t\tHelpClass(void);\n\t\tHelpClass(NoInitClass const & x) : TabClass(x) {};\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvirtual void Init_Clear(void);\t\t\t\t\t\t// Clears all to known state\n\n\t\tvirtual void Draw_It(bool complete=false);\n\t\tvirtual void AI(KeyNumType &input, int x, int y);\n\t\tvirtual bool Scroll_Map(DirType facing, int &distance, bool really);\n\t\tvirtual void Set_Tactical_Position(COORDINATE coord);\n\n\t\tvoid Help_Text(int text, int x=-1, int y=-1, int color=LTGREY, bool quick=false);\n\t\tvoid Set_Cost(int cost);\n\t\tshort const * Overlap_List(void) const;\n\n\tprivate:\n\n\t\tstatic char const *HelpText;\n\t\tint HelpX;\n\t\tint HelpY;\n\t\tint HelpWidth;\n\n\n\t\tvoid Set_Text(int text);\n\n\t\t/*\n\t\t**\tIf the help text is right justified (as with the help text that pops up over the\n\t\t**\tsidebar icons), then this flag is set to true.\n\t\t*/\n\t\tunsigned IsRight:1;\n\n\t\t/*\n\t\t**\tIf the optional second line of text that displays cost is desired, then this\n\t\t**\tvalue will be non-zero. Typically, this is true when the help text is associated\n\t\t**\twith one of the sidebar construction icons.\n\t\t*/\n\t\tint Cost;\n\n\t\t/*\n\t\t**\tThis is the recorded position of the cursor at the time the help text\n\t\t**\tpops up. The help text is rendered as an offset from this pixel position.\n\t\t*/\n\t\tint X;\n\t\tint Y;\n\n\t\t/*\n\t\t**\tThis is the draw X and Y coordinate. This position is relative to the X and\n\t\t**\tY coordinates but adjusted for screen edges as necessary.\n\t\t*/\n\t\tint DrawX;\n\t\tint DrawY;\n\n\t\t/*\n\t\t**\tThe width of the help text (in pixels) is stored here. This is a convenience\n\t\t**\tsince calculating the width takes a bit of time.\n\t\t*/\n\t\tint Width;\n\n\t\t/*\n\t\t**\tThe text number of the help text to display is held here. If no text is to be\n\t\t**\tdisplayed, then this value will be TXT_NONE.\n\t\t*/\n\t\tint Text;\n\n\t\t/*\n\t\t**\tThis is the background color to use for the help text. It can change according\n\t\t**\tto the message displayed.\n\t\t*/\n\t\tint Color;\n\n\t\t/*\n\t\t**\tThis countdown timer controls when the help text will pop up. If the mouse\n\t\t**\tremains stationary while this countdown timer expires, then the help text\n\t\t**\twill pop up.\n\t\t*/\n\t\tCDTimerClass<SystemTimerClass> CountDownTimer;\n\n\t\t/*\n\t\t**\tThis is a calculated cell offset list (from the Map.TacticalCell) that indicates\n\t\t**\twhich cells are under the help text and thus which cells need to be redrawn if\n\t\t**\tthe help text is to be erased.\n\t\t*/\n\t\tstatic short const OverlapList[60];\n\n\t\tenum HelpClassEnum {\n\t\t\tHELP_DELAY=TIMER_SECOND*1,\t\t\t\t// The countdown timer delay before help text pops up.\n\t\t\tY_OFFSET=0,\t\t\t\t\t// The Y pixel offset from cursor for help text print.\n\t\t\tX_OFFSET=12\t\t\t\t\t// The X pixel offset from cursor for help text print.\n\t\t};\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/HOUSE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /counterstrike/HOUSE.CPP 4     3/13/97 7:11p Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HOUSE.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 21, 1994                                                 *\n *                                                                                             *\n *                  Last Update : November 4, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   HouseClass::AI -- Process house logic.                                                    *\n *   HouseClass::AI_Aircraft -- Determines what aircraft to build next.                        *\n *   HouseClass::AI_Attack -- Handles offensive attack logic.                                  *\n *   HouseClass::AI_Base_Defense -- Handles maintaining a strong base defense.                 *\n *   HouseClass::AI_Building -- Determines what building to build.                             *\n *   HouseClass::AI_Fire_Sale -- Check for and perform a fire sale.                            *\n *   HouseClass::AI_Infantry -- Determines the infantry unit to build.                         *\n *   HouseClass::AI_Money_Check -- Handles money production logic.                             *\n *   HouseClass::AI_Power_Check -- Handle the power situation.                                 *\n *   HouseClass::AI_Unit -- Determines what unit to build next.                                *\n *   HouseClass::Abandon_Production -- Abandons production of item type specified.             *\n *   HouseClass::Active_Add -- Add an object to active duty for this house.                    *\n *   HouseClass::Active_Remove -- Remove this object from active duty for this house.          *\n *   HouseClass::Adjust_Capacity -- Adjusts the house Tiberium storage capacity.               *\n *   HouseClass::Adjust_Drain -- Adjust the power drain value of the house.                    *\n *   HouseClass::Adjust_Power -- Adjust the power value of the house.                          *\n *   HouseClass::Adjust_Threat -- Adjust threat for the region specified.                      *\n *   HouseClass::As_Pointer -- Converts a house number into a house object pointer.            *\n *   HouseClass::Assign_Handicap -- Assigns the specified handicap rating to the house.        *\n *   HouseClass::Attacked -- Lets player know if base is under attack.                         *\n *   HouseClass::Available_Money -- Fetches the total credit worth of the house.               *\n *   HouseClass::Begin_Production -- Starts production of the specified object type.           *\n *   HouseClass::Blowup_All -- blows up everything                                             *\n *   HouseClass::Can_Build -- General purpose build legality checker.                          *\n *   HouseClass::Clobber_All -- removes all objects for this house                             *\n *   HouseClass::Computer_Paranoid -- Cause the computer players to becom paranoid.            *\n *   HouseClass::Debug_Dump -- Dumps the house status data to the mono screen.                 *\n *   HouseClass::Detach -- Removes specified object from house tracking systems.               *\n *   HouseClass::Do_All_To_Hunt -- Send all units to hunt.                                     *\n *   HouseClass::Does_Enemy_Building_Exist -- Checks for enemy building of specified type.     *\n *   HouseClass::Expert_AI -- Handles expert AI processing.                                    *\n *   HouseClass::Factory_Count -- Fetches the number of factories for specified type.          *\n *   HouseClass::Factory_Counter -- Fetches a pointer to the factory counter value.            *\n *   HouseClass::Fetch_Factory -- Finds the factory associated with the object type specified. *\n *   HouseClass::Find_Build_Location -- Finds a suitable building location.                    *\n *   HouseClass::Find_Building -- Finds a building of specified type.                          *\n *   HouseClass::Find_Cell_In_Zone -- Finds a legal placement cell within the zone.            *\n *   HouseClass::Find_Juicy_Target -- Finds a suitable field target.                           *\n *   HouseClass::Fire_Sale -- Cause all buildings to be sold.                                  *\n *   HouseClass::Flag_Attach -- Attach flag to specified cell (or thereabouts).                *\n *   HouseClass::Flag_Attach -- Attaches the house flag the specified unit.                    *\n *   HouseClass::Flag_Remove -- Removes the flag from the specified target.                    *\n *   HouseClass::Flag_To_Die -- Flags the house to blow up soon.                               *\n *   HouseClass::Flag_To_Lose -- Flags the house to die soon.                                  *\n *   HouseClass::Flag_To_Win -- Flags the house to win soon.                                   *\n *   HouseClass::Get_Quantity -- Fetches the total number of aircraft of the specified type.   *\n *   HouseClass::Get_Quantity -- Gets the quantity of the building type specified.             *\n *   HouseClass::Harvested -- Adds Tiberium to the harvest storage.                            *\n *   HouseClass::HouseClass -- Constructor for a house object.                                 *\n *   HouseClass::Init -- init's in preparation for new scenario                                *\n *   HouseClass::Init_Data -- Initializes the multiplayer color data.                          *\n *   HouseClass::Is_Allowed_To_Ally -- Determines if this house is allied to make allies.      *\n *   HouseClass::Is_Ally -- Checks to see if the object is an ally.                            *\n *   HouseClass::Is_Ally -- Determines if the specified house is an ally.                      *\n *   HouseClass::Is_Hack_Prevented -- Is production of the specified type and id prohibted?    *\n *   HouseClass::Is_No_YakMig -- Determines if no more yaks or migs should be allowed.         *\n *   HouseClass::MPlayer_Defeated -- multiplayer; house is defeated                            *\n *   HouseClass::Make_Ally -- Make the specified house an ally.                                *\n *   HouseClass::Make_Enemy -- Make an enemy of the house specified.                           *\n *   HouseClass::Manual_Place -- Inform display system of building placement mode.             *\n *   HouseClass::One_Time -- Handles one time initialization of the house array.               *\n *   HouseClass::Place_Object -- Places the object (building) at location specified.           *\n *   HouseClass::Place_Special_Blast -- Place a special blast effect at location specified.    *\n *   HouseClass::Power_Fraction -- Fetches the current power output rating.                    *\n *   HouseClass::Production_Begun -- Records that production has begun.                        *\n *   HouseClass::Read_INI -- Reads house specific data from INI.                               *\n *   HouseClass::Recalc_Attributes -- Recalcs all houses existence bits.                       *\n *   HouseClass::Recalc_Center -- Recalculates the center point of the base.                   *\n *   HouseClass::Refund_Money -- Refunds money to back to the house.                           *\n *   HouseClass::Remap_Table -- Fetches the remap table for this house object.                 *\n *   HouseClass::Sell_Wall -- Tries to sell the wall at the specified location.                *\n *   HouseClass::Set_Factory -- Assign specified factory to house tracking.                    *\n *   HouseClass::Silo_Redraw_Check -- Flags silos to be redrawn if necessary.                  *\n *   HouseClass::Special_Weapon_AI -- Fires special weapon.                                    *\n *   HouseClass::Spend_Money -- Removes money from the house.                                  *\n *   HouseClass::Suggest_New_Building -- Examines the situation and suggests a building.       *\n *   HouseClass::Suggest_New_Object -- Determine what would the next buildable object be.      *\n *   HouseClass::Suggested_New_Team -- Determine what team should be created.                  *\n *   HouseClass::Super_Weapon_Handler -- Handles the super weapon charge and discharge logic.  *\n *   HouseClass::Suspend_Production -- Temporarily puts production on hold.                    *\n *   HouseClass::Tally_Score -- Fills in the score system for this round                       *\n *   HouseClass::Tiberium_Fraction -- Calculates the tiberium fraction of capacity.            *\n *   HouseClass::Tracking_Add -- Informs house of new inventory item.                          *\n *   HouseClass::Tracking_Remove -- Remove object from house tracking system.                  *\n *   HouseClass::Where_To_Go -- Determines where the object should go and wait.                *\n *   HouseClass::Which_Zone -- Determines what zone a coordinate lies in.                      *\n *   HouseClass::Which_Zone -- Determines which base zone the specified cell lies in.          *\n *   HouseClass::Which_Zone -- Determines which base zone the specified object lies in.        *\n *   HouseClass::Write_INI -- Writes the house data to the INI database.                       *\n *   HouseClass::Zone_Cell -- Finds the cell closest to the center of the zone.                *\n *   HouseClass::delete -- Deallocator function for a house object.                            *\n *   HouseClass::new -- Allocator for a house class.                                           *\n *   HouseClass::operator HousesType -- Conversion to HousesType operator.                     *\n *   HouseClass::~HouseClass -- Default destructor for a house object.                         *\n *   HouseStaticClass::HouseStaticClass -- Default constructor for house static class.         *\n *   HouseClass::AI_Raise_Power -- Try to raise power levels by selling off buildings.         *\n *   HouseClass::AI_Raise_Money -- Raise emergency cash by selling buildings.                  *\n *   HouseClass::Random_Cell_In_Zone -- Find a (technically) legal cell in the zone specified. *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"vortex.h\"\n\n//#include \"WolDebug.h\"\n\nTFixedIHeapClass<HouseClass::BuildChoiceClass> HouseClass::BuildChoice;\n\nint TFixedIHeapClass<HouseClass::BuildChoiceClass>::Save(Pipe &) const\n{\n\treturn(true);\n}\n\nint TFixedIHeapClass<HouseClass::BuildChoiceClass>::Load(Straw &)\n{\n\treturn(0);\n}\n\nvoid TFixedIHeapClass<HouseClass::BuildChoiceClass>::Code_Pointers(void)\n{\n}\n\nvoid TFixedIHeapClass<HouseClass::BuildChoiceClass>::Decode_Pointers(void)\n{\n}\n\nextern bool RedrawOptionsMenu;\n\n/***********************************************************************************************\n * HouseClass::operator HousesType -- Conversion to HousesType operator.                       *\n *                                                                                             *\n *    This operator will automatically convert from a houses class object into the HousesType  *\n *    enumerated value.                                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the object's HousesType value.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nHouseClass::operator HousesType(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(Class->House);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Tiberium_Fraction -- Calculates the tiberium fraction of capacity.              *\n *                                                                                             *\n *    This will calculate the current tiberium (gold) load as a ratio of the maximum storage   *\n *    capacity.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the current tiberium storage situation as a ratio of load over capacity.   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/31/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed HouseClass::Tiberium_Fraction(void) const\n{\n\tif (Tiberium == 0) {\n\t\treturn(0);\n\t}\n\treturn(fixed(Tiberium, Capacity));\n}\n\n\n/***********************************************************************************************\n * HouseClass::As_Pointer -- Converts a house number into a house object pointer.              *\n *                                                                                             *\n *    Use this routine to convert a house number into the house pointer that it represents.    *\n *    A simple index into the Houses template array is not sufficient, since the array order   *\n *    is arbitrary. An actual scan through the house object is required in order to find the   *\n *    house object desired.                                                                    *\n *                                                                                             *\n * INPUT:   house -- The house type number to look up.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the house object that the house number represents.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nHouseClass * HouseClass::As_Pointer(HousesType house)\n{\n\tif (house != HOUSE_NONE) {\n\t\tfor (int index = 0; index < Houses.Count(); index++) {\n\t\t\tif (Houses.Ptr(index)->Class->House == house) {\n\t\t\t\treturn(Houses.Ptr(index));\n\t\t\t}\n\t\t}\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * HouseClass::One_Time -- Handles one time initialization of the house array.                 *\n *                                                                                             *\n *    This basically calls the constructor for each of the houses in the game. All other       *\n *    data specific to the house is initialized when the scenario is loaded.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this ONCE at the beginning of the game.                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::One_Time(void)\n{\n\tBuildChoice.Set_Heap(STRUCT_COUNT);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Assign_Handicap -- Assigns the specified handicap rating to the house.          *\n *                                                                                             *\n *    The handicap rating will affect combat, movement, and production for the house. It can   *\n *    either make it more or less difficult for the house (controlled by the handicap value).  *\n *                                                                                             *\n * INPUT:   handicap -- The handicap value to assign to this house. The default value for      *\n *                      a house is DIFF_NORMAL.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the old handicap value.                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *   10/22/1996 JLB : Uses act like value for multiplay only.                                  *\n *=============================================================================================*/\nDiffType HouseClass::Assign_Handicap(DiffType handicap)\n{\n\tDiffType old = Difficulty;\n\tDifficulty = handicap;\n\n\tif (Session.Type != GAME_NORMAL) {\n\t\tHouseTypeClass const * hptr = &HouseTypeClass::As_Reference(ActLike);\n\t\tFirepowerBias = hptr->FirepowerBias * Rule.Diff[handicap].FirepowerBias;\n\t\tGroundspeedBias = hptr->GroundspeedBias * Rule.Diff[handicap].GroundspeedBias * Rule.GameSpeedBias;\n\t\tAirspeedBias = hptr->AirspeedBias * Rule.Diff[handicap].AirspeedBias * Rule.GameSpeedBias;\n\t\tArmorBias = hptr->ArmorBias * Rule.Diff[handicap].ArmorBias;\n\t\tROFBias = hptr->ROFBias * Rule.Diff[handicap].ROFBias;\n\t\tCostBias = hptr->CostBias * Rule.Diff[handicap].CostBias;\n\t\tRepairDelay = Rule.Diff[handicap].RepairDelay;\n\t\tBuildDelay = Rule.Diff[handicap].BuildDelay;\n\t\tBuildSpeedBias = hptr->BuildSpeedBias * Rule.Diff[handicap].BuildSpeedBias * Rule.GameSpeedBias;\n\t} else {\n\t\tFirepowerBias = Rule.Diff[handicap].FirepowerBias;\n\t\tGroundspeedBias = Rule.Diff[handicap].GroundspeedBias * Rule.GameSpeedBias;\n\t\tAirspeedBias = Rule.Diff[handicap].AirspeedBias * Rule.GameSpeedBias;\n\t\tArmorBias = Rule.Diff[handicap].ArmorBias;\n\t\tROFBias = Rule.Diff[handicap].ROFBias;\n\t\tCostBias = Rule.Diff[handicap].CostBias;\n\t\tRepairDelay = Rule.Diff[handicap].RepairDelay;\n\t\tBuildDelay = Rule.Diff[handicap].BuildDelay;\n\t\tBuildSpeedBias = Rule.Diff[handicap].BuildSpeedBias * Rule.GameSpeedBias;\n\t}\n\n\treturn(old);\n}\n\n\n\n#ifdef CHEAT_KEYS\n\nvoid HouseClass::Print_Zone_Stats(int x, int y, ZoneType zone, MonoClass * mono) const\n{\n\tmono->Set_Cursor(x, y);\n\tmono->Printf(\"A:%-5d I:%-5d V:%-5d\", ZoneInfo[zone].AirDefense, ZoneInfo[zone].InfantryDefense, ZoneInfo[zone].ArmorDefense);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Debug_Dump -- Dumps the house status data to the mono screen.                   *\n *                                                                                             *\n *    This utility function will output the current status of the house class to the mono      *\n *    screen. Through this information bugs may be fixed or detected.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Debug_Dump(MonoClass * mono) const\n{\n\tmono->Set_Cursor(0, 0);\n\tmono->Print(Text_String(TXT_DEBUG_HOUSE));\n\n\tmono->Set_Cursor(1, 1);mono->Printf(\"[%d]%14.14s\", Class->House, Name());\n\tmono->Set_Cursor(20, 1);mono->Printf(\"[%d]%13.13s\", ActLike, HouseTypeClass::As_Reference(ActLike).Name());\n\tmono->Set_Cursor(39, 1);mono->Printf(\"%2d\", Control.TechLevel);\n\tmono->Set_Cursor(45, 1);mono->Printf(\"%2d\", Difficulty);\n\tmono->Set_Cursor(52, 1);mono->Printf(\"%2d\", State);\n\tmono->Set_Cursor(58, 1);mono->Printf(\"%2d\", Blockage);\n\tmono->Set_Cursor(65, 1);mono->Printf(\"%2d\", IQ);\n\tmono->Set_Cursor(72, 1);mono->Printf(\"%5d\", (long)RepairTimer);\n\n\tmono->Set_Cursor(1, 3);mono->Printf(\"%08X\", AScan);\n\tmono->Set_Cursor(10, 3);mono->Printf(\"%8.8s\", (BuildAircraft == AIRCRAFT_NONE) ? \" \" : AircraftTypeClass::As_Reference(BuildAircraft).Graphic_Name());\n\tmono->Set_Cursor(21, 3);mono->Printf(\"%3d\", CurAircraft);\n\tmono->Set_Cursor(27, 3);mono->Printf(\"%8d\", Credits);\n\tmono->Set_Cursor(37, 3);mono->Printf(\"%5d\", Power);\n\tmono->Set_Cursor(45, 3);mono->Printf(\"%04X\", RadarSpied);\n\tmono->Set_Cursor(52, 3);mono->Printf(\"%5d\", PointTotal);\n\tmono->Set_Cursor(62, 3);mono->Printf(\"%5d\", (long)TeamTime);\n\tmono->Set_Cursor(71, 3);mono->Printf(\"%5d\", (long)AlertTime);\n\n\tmono->Set_Cursor(1, 5);mono->Printf(\"%08X\", BScan);\n\tmono->Set_Cursor(10, 5);mono->Printf(\"%8.8s\", (BuildStructure == STRUCT_NONE) ? \" \" : BuildingTypeClass::As_Reference(BuildStructure).Graphic_Name());\n\tmono->Set_Cursor(21, 5);mono->Printf(\"%3d\", CurBuildings);\n\tmono->Set_Cursor(27, 5);mono->Printf(\"%8d\", Tiberium);\n\tmono->Set_Cursor(37, 5);mono->Printf(\"%5d\", Drain);\n\tmono->Set_Cursor(44, 5);mono->Printf(\"%16.16s\", QuarryName[PreferredTarget]);\n\tmono->Set_Cursor(62, 5);mono->Printf(\"%5d\", (long)TriggerTime);\n\tmono->Set_Cursor(71, 5);mono->Printf(\"%5d\", (long)BorrowedTime);\n\n\tmono->Set_Cursor(1, 7);mono->Printf(\"%08X\", UScan);\n\tmono->Set_Cursor(10, 7);mono->Printf(\"%8.8s\", (BuildUnit == UNIT_NONE) ? \" \" : UnitTypeClass::As_Reference(BuildUnit).Graphic_Name());\n\tmono->Set_Cursor(21, 7);mono->Printf(\"%3d\", CurUnits);\n\tmono->Set_Cursor(27, 7);mono->Printf(\"%8d\", Control.InitialCredits);\n\tmono->Set_Cursor(38, 7);mono->Printf(\"%5d\", UnitsLost);\n\tmono->Set_Cursor(44, 7);mono->Printf(\"%08X\", Allies);\n\tmono->Set_Cursor(71, 7);mono->Printf(\"%5d\", (long)Attack);\n\n\tmono->Set_Cursor(1, 9);mono->Printf(\"%08X\", IScan);\n\tmono->Set_Cursor(10, 9);mono->Printf(\"%8.8s\", (BuildInfantry == INFANTRY_NONE) ? \" \" : InfantryTypeClass::As_Reference(BuildInfantry).Graphic_Name());\n\tmono->Set_Cursor(21, 9);mono->Printf(\"%3d\", CurInfantry);\n\tmono->Set_Cursor(27, 9);mono->Printf(\"%8d\", Capacity);\n\tmono->Set_Cursor(38, 9);mono->Printf(\"%5d\", BuildingsLost);\n\tmono->Set_Cursor(45, 9);mono->Printf(\"%4d\", Radius / CELL_LEPTON_W);\n\tmono->Set_Cursor(71, 9);mono->Printf(\"%5d\", (long)AITimer);\n\n\tmono->Set_Cursor(1, 11);mono->Printf(\"%08X\", VScan);\n\tmono->Set_Cursor(10, 11);mono->Printf(\"%8.8s\", (BuildVessel == VESSEL_NONE) ? \" \" : VesselTypeClass::As_Reference(BuildVessel).Graphic_Name());\n\tmono->Set_Cursor(21, 11);mono->Printf(\"%3d\", CurVessels);\n\tmono->Set_Cursor(54, 11);mono->Printf(\"%04X\", Coord_Cell(Center));\n\tmono->Set_Cursor(71, 11);mono->Printf(\"%5d\", (long)DamageTime);\n\n\n\tfor (int index = 0; index < ARRAY_SIZE(Scen.GlobalFlags); index++) {\n\t\tmono->Set_Cursor(1+index, 15);\n\t\tif (Scen.GlobalFlags[index] != 0) {\n\t\t\tmono->Print(\"1\");\n\t\t} else {\n\t\t\tmono->Print(\"0\");\n\t\t}\n\t\tif (index >= 24) break;\n\t}\n\tif (Enemy != HOUSE_NONE) {\n\t\tchar const * name = \"\";\n\t\tname = HouseClass::As_Pointer(Enemy)->Name();\n\t\tmono->Set_Cursor(53, 15);mono->Printf(\"[%d]%21.21s\", Enemy, HouseTypeClass::As_Reference(Enemy).Name());\n\t}\n\n\tPrint_Zone_Stats(27, 11, ZONE_NORTH, mono);\n\tPrint_Zone_Stats(27, 13, ZONE_CORE, mono);\n\tPrint_Zone_Stats(27, 15, ZONE_SOUTH, mono);\n\tPrint_Zone_Stats(1, 13, ZONE_WEST, mono);\n\tPrint_Zone_Stats(53, 13, ZONE_EAST, mono);\n\n\tmono->Fill_Attrib(1, 17, 12, 1, IsActive ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 18, 12, 1, IsHuman ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 19, 12, 1, IsPlayerControl ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 20, 12, 1, IsAlerted ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 21, 12, 1, IsDiscovered ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 22, 12, 1, IsMaxedOut ? MonoClass::INVERSE : MonoClass::NORMAL);\n\n\tmono->Fill_Attrib(14, 17, 12, 1, IsDefeated ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(14, 18, 12, 1, IsToDie ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(14, 19, 12, 1, IsToWin ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(14, 20, 12, 1, IsToLose ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(14, 21, 12, 1, IsCivEvacuated ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(14, 22, 12, 1, IsRecalcNeeded ? MonoClass::INVERSE : MonoClass::NORMAL);\n\n\tmono->Fill_Attrib(27, 17, 12, 1, IsVisionary ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(27, 18, 12, 1, IsTiberiumShort ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(27, 19, 12, 1, IsSpied ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(27, 20, 12, 1, IsThieved ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(27, 21, 12, 1, IsGPSActive ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(27, 22, 12, 1, IsStarted ? MonoClass::INVERSE : MonoClass::NORMAL);\n\n\tmono->Fill_Attrib(40, 17, 12, 1, IsResigner ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(40, 18, 12, 1, IsGiverUpper ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(40, 19, 12, 1, IsBuiltSomething ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(40, 20, 12, 1, IsBaseBuilding ? MonoClass::INVERSE : MonoClass::NORMAL);\n}\n#endif\n\n\n/***********************************************************************************************\n * HouseClass::new -- Allocator for a house class.                                             *\n *                                                                                             *\n *    This is the allocator for a house class. Since there can be only                         *\n *    one of each type of house, this is allocator has restricted                              *\n *    functionality. Any attempt to allocate a house structure for a                           *\n *    house that already exists, just returns a pointer to the previously                      *\n *    allocated house.                                                                         *\n *                                                                                             *\n * INPUT:   house -- The house to allocate a class object for.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocated class object.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * HouseClass::operator new(size_t)\n{\n\tvoid * ptr = Houses.Allocate();\n\tif (ptr) {\n\t\t((HouseClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * HouseClass::delete -- Deallocator function for a house object.                              *\n *                                                                                             *\n *    This function marks the house object as \"deallocated\". Such a                            *\n *    house object is available for reallocation later.                                        *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the house object to deallocate.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::operator delete(void * ptr)\n{\n\tif (ptr) {\n\t\t((HouseClass *)ptr)->IsActive = false;\n\t}\n\tHouses.Free((HouseClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * HouseClass::HouseClass -- Constructor for a house object.                                   *\n *                                                                                             *\n *    This function is the constructor and it marks the house object                           *\n *    as being allocated.                                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\n#define \tVOX_NOT_READY\tVOX_NONE\nHouseClass::HouseClass(HousesType house) :\n\tRTTI(RTTI_HOUSE),\n\tID(Houses.ID(this)),\n\tClass(HouseTypes.Ptr(house)),\n\tDifficulty(Scen.CDifficulty),\n\tFirepowerBias(1),\n\tGroundspeedBias(1),\n\tAirspeedBias(1),\n\tArmorBias(1),\n\tROFBias(1),\n\tCostBias(1),\n\tBuildSpeedBias(1),\n\tRepairDelay(0),\n\tBuildDelay(0),\n\tActLike(Class->House),\n\tIsHuman(false),\n\tIsPlayerControl(false),\n\tIsStarted(false),\n\tIsAlerted(false),\n\tIsBaseBuilding(false),\n\tIsDiscovered(false),\n\tIsMaxedOut(false),\n\tIsDefeated(false),\n\tIsToDie(false),\n\tIsToLose(false),\n\tIsToWin(false),\n\tIsCivEvacuated(false),\n\tIsRecalcNeeded(true),\n\tIsVisionary(false),\n\tIsTiberiumShort(false),\n\tIsSpied(false),\n\tIsThieved(false),\n\tIsGPSActive(false),\n\tIsBuiltSomething(false),\n\tIsResigner(false),\n\tIsGiverUpper(false),\n\tIsParanoid(false),\n\tIsToLook(true),\n\tDidRepair(false),\n\tIQ(Control.IQ),\n\tState(STATE_BUILDUP),\n\tJustBuiltStructure(STRUCT_NONE),\n\tJustBuiltInfantry(INFANTRY_NONE),\n\tJustBuiltUnit(UNIT_NONE),\n\tJustBuiltAircraft(AIRCRAFT_NONE),\n\tJustBuiltVessel(VESSEL_NONE),\n\tBlockage(0),\n\tRepairTimer(0),\n\tAlertTime(0),\n\tBorrowedTime(0),\n\tBScan(0),\n\tActiveBScan(0),\n\tOldBScan(0),\n\tUScan(0),\n\tActiveUScan(0),\n\tOldUScan(0),\n\tIScan(0),\n\tActiveIScan(0),\n\tOldIScan(0),\n\tAScan(0),\n\tActiveAScan(0),\n\tOldAScan(0),\n\tVScan(0),\n\tActiveVScan(0),\n\tOldVScan(0),\n\tCreditsSpent(0),\n\tHarvestedCredits(0),\n\tStolenBuildingsCredits(0),\n\tCurUnits(0),\n\tCurBuildings(0),\n\tCurInfantry(0),\n\tCurVessels(0),\n\tCurAircraft(0),\n\tTiberium(0),\n\tCredits(0),\n\tCapacity(0),\n\tAircraftTotals(NULL),\n\tInfantryTotals(NULL),\n\tUnitTotals(NULL),\n\tBuildingTotals(NULL),\n\tVesselTotals(NULL),\n\tDestroyedAircraft(NULL),\n\tDestroyedInfantry(NULL),\n\tDestroyedUnits(NULL),\n\tDestroyedBuildings(NULL),\n\tDestroyedVessels(NULL),\n\tCapturedBuildings(NULL),\n\tTotalCrates(NULL),\n\tAircraftFactories(0),\n\tInfantryFactories(0),\n\tUnitFactories(0),\n\tBuildingFactories(0),\n\tVesselFactories(0),\n\tPower(0),\n\tDrain(0),\n\tAircraftFactory(-1),\n\tInfantryFactory(-1),\n\tUnitFactory(-1),\n\tBuildingFactory(-1),\n\tVesselFactory(-1),\n\tFlagLocation(TARGET_NONE),\n\tFlagHome(0),\n\tUnitsLost(0),\n\tBuildingsLost(0),\n\tWhoLastHurtMe(house),\n\tCenter(0),\n\tRadius(0),\n\tLATime(0),\n\tLAType(RTTI_NONE),\n\tLAZone(ZONE_NONE),\n\tLAEnemy(HOUSE_NONE),\n\tToCapture(TARGET_NONE),\n\tRadarSpied(0),\n\tPointTotal(0),\n\tPreferredTarget(QUARRY_ANYTHING),\n\tAttack(0),\n\tEnemy(HOUSE_NONE),\n\tAITimer(0),\n\tUnitToTeleport(0),\n\tBuildStructure(STRUCT_NONE),\n\tBuildUnit(UNIT_NONE),\n\tBuildInfantry(INFANTRY_NONE),\n\tBuildAircraft(AIRCRAFT_NONE),\n\tBuildVessel(VESSEL_NONE),\n\tNukeDest(0),\n\tAllies(0),\n\tDamageTime(TICKS_PER_MINUTE * Rule.DamageDelay),\n\tTeamTime(TICKS_PER_MINUTE * Rule.TeamDelay),\n\tTriggerTime(0),\n\tSpeakAttackDelay(1),\n\tSpeakPowerDelay(1),\n\tSpeakMoneyDelay(1),\n\tSpeakMaxedDelay(1),\n\tRemapColor(Class->RemapColor)\n{\n\t/*\n\t**\tExplicit in-place construction of the super weapons is\n\t**\trequired here because the default constructor for super\n\t**\tweapons must serve as a no-initialization constructor (save/load reasons).\n\t*/\n\tnew (&SuperWeapon[SPC_NUCLEAR_BOMB]) SuperClass(TICKS_PER_MINUTE * Rule.NukeTime, true, VOX_ABOMB_PREPPING, VOX_ABOMB_READY, VOX_NOT_READY, VOX_INSUFFICIENT_POWER);\n\tnew (&SuperWeapon[SPC_SONAR_PULSE]) SuperClass(TICKS_PER_MINUTE * Rule.SonarTime, false, VOX_NONE, VOX_SONAR_AVAILABLE, VOX_NOT_READY, VOX_NOT_READY);\n\tnew (&SuperWeapon[SPC_CHRONOSPHERE]) SuperClass(TICKS_PER_MINUTE * Rule.ChronoTime, true, VOX_CHRONO_CHARGING, VOX_CHRONO_READY, VOX_NOT_READY, VOX_INSUFFICIENT_POWER);\n\tnew (&SuperWeapon[SPC_PARA_BOMB]) SuperClass(TICKS_PER_MINUTE * Rule.ParaBombTime, false, VOX_NONE, VOX_NONE, VOX_NOT_READY, VOX_NOT_READY);\n\tnew (&SuperWeapon[SPC_PARA_INFANTRY]) SuperClass(TICKS_PER_MINUTE * Rule.ParaInfantryTime, false, VOX_NONE, VOX_NONE, VOX_NOT_READY, VOX_NOT_READY);\n\tnew (&SuperWeapon[SPC_SPY_MISSION]) SuperClass(TICKS_PER_MINUTE * Rule.SpyTime, false, VOX_NONE, VOX_SPY_PLANE, VOX_NOT_READY, VOX_NOT_READY);\n\tnew (&SuperWeapon[SPC_IRON_CURTAIN]) SuperClass(TICKS_PER_MINUTE * Rule.IronCurtainTime, true, VOX_IRON_CHARGING, VOX_IRON_READY, VOX_NOT_READY, VOX_INSUFFICIENT_POWER);\n\tnew (&SuperWeapon[SPC_GPS]) SuperClass(TICKS_PER_MINUTE * Rule.GPSTime, true, VOX_NONE, VOX_NONE, VOX_NOT_READY, VOX_INSUFFICIENT_POWER);\n\n\tmemset(UnitsKilled, '\\0', sizeof(UnitsKilled));\n\tmemset(BuildingsKilled, '\\0', sizeof(BuildingsKilled));\n\tmemset(BQuantity, '\\0', sizeof(BQuantity));\n\tmemset(UQuantity, '\\0', sizeof(UQuantity));\n\tmemset(IQuantity, '\\0', sizeof(IQuantity));\n\tmemset(AQuantity, '\\0', sizeof(AQuantity));\n\tmemset(VQuantity, '\\0', sizeof(VQuantity));\n\tstrcpy(IniName, Text_String(TXT_COMPUTER));\t// Default computer name.\n\tHouseTriggers[house].Clear();\n\tmemset((void *)&Regions[0], 0x00, sizeof(Regions));\n\tMake_Ally(house);\n\tAssign_Handicap(Scen.CDifficulty);\n\n\t/*\n\t**\tSet the time of the first AI attack.\n\t*/\n\tAttack = Rule.AttackDelay * Random_Pick(TICKS_PER_MINUTE/2, TICKS_PER_MINUTE*2);\n\n\tif (Session.Type == GAME_INTERNET) {\n\t\tAircraftTotals = new UnitTrackerClass( (int) AIRCRAFT_COUNT);\n\t\tInfantryTotals = new UnitTrackerClass( (int) INFANTRY_COUNT);\n\t\tUnitTotals = new UnitTrackerClass ( (int) UNIT_COUNT);\n\t\tBuildingTotals = new UnitTrackerClass ( (int) STRUCT_COUNT);\n\t\tVesselTotals = new UnitTrackerClass ( (int) VESSEL_COUNT);\n\n\t\tDestroyedAircraft = new UnitTrackerClass ( (int) AIRCRAFT_COUNT);\n\t\tDestroyedInfantry = new UnitTrackerClass( (int) INFANTRY_COUNT);\n\t\tDestroyedUnits = new UnitTrackerClass ( (int) UNIT_COUNT);\n\t\tDestroyedBuildings = new UnitTrackerClass ( (int) STRUCT_COUNT);\n\t\tDestroyedVessels = new UnitTrackerClass ( (int) VESSEL_COUNT);\n\n\t\tCapturedBuildings = new UnitTrackerClass ( (int) STRUCT_COUNT);\n\t\tTotalCrates = new UnitTrackerClass ( CRATE_COUNT );\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::~HouseClass -- House class destructor                                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/6/96 4:48PM ST : Created                                                               *\n *=============================================================================================*/\nHouseClass::~HouseClass (void)\n{\n\tClass = 0;\n\n\tif (Session.Type == GAME_INTERNET) {\n\t\tdelete AircraftTotals;\n\t\tdelete InfantryTotals;\n\t\tdelete UnitTotals;\n\t\tdelete BuildingTotals;\n\t\tdelete VesselTotals;\n\n\t\tdelete DestroyedAircraft;\n\t\tdelete DestroyedInfantry;\n\t\tdelete DestroyedUnits;\n\t\tdelete DestroyedBuildings;\n\t\tdelete DestroyedVessels;\n\n\t\tdelete CapturedBuildings;\n\t\tdelete TotalCrates;\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseStaticClass::HouseStaticClass -- Default constructor for house static class.           *\n *                                                                                             *\n *    This is the default constructor that initializes all the values to their default         *\n *    settings.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/31/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nHouseStaticClass::HouseStaticClass(void) :\n\tIQ(0),\n\tTechLevel(1),\n\tAllies(0),\n\tMaxUnit(Rule.UnitMax/6),\n\tMaxBuilding(Rule.BuildingMax/6),\n\tMaxInfantry(Rule.InfantryMax/6),\n\tMaxVessel(Rule.VesselMax/6),\n\tMaxAircraft(Rule.UnitMax/6),\n\tInitialCredits(0),\n\tEdge(SOURCE_NORTH)\n{\n}\n\n\n/***********************************************************************************************\n * HouseClass::Can_Build -- General purpose build legality checker.                            *\n *                                                                                             *\n *    This routine is called when it needs to be determined if the specified object type can   *\n *    be built by this house. Production and sidebar maintenance use this routine heavily.     *\n *                                                                                             *\n * INPUT:   type  -- Pointer to the type of object that legality is to be checked for.         *\n *                                                                                             *\n *          house -- This is the house to check for legality against. Note that this might     *\n *                   not be 'this' house since the check could be from a captured factory.     *\n *                   Captured factories build what the original owner of them could build.     *\n *                                                                                             *\n * OUTPUT:  Can the specified object be built?                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *   08/12/1995 JLB : Updated for GDI building sandbag walls in #9.                            *\n *   10/23/1996 JLB : Hack to allow Tanya to both sides in multiplay.                          *\n *   11/04/1996 JLB : Computer uses prerequisite record.                                       *\n *=============================================================================================*/\nbool HouseClass::Can_Build(ObjectTypeClass const * type, HousesType house) const\n{\n\tassert(Houses.ID(this) == ID);\n\tassert(type != NULL);\n\n\t/*\n\t**\tAn object with a prohibited tech level availability will never be allowed, regardless\n\t**\tof who requests it.\n\t*/\n\tif (((TechnoTypeClass const *)type)->Level == -1) return(false);\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t/*\n\t** If this is a CounterStrike II-only unit, and we're playing a multiplayer\n\t** game in 'downshifted' mode against CounterStrike or Red Alert, then\n\t** don't allow building this unit.\n\t*/\n\tif (!NewUnitsEnabled) {\n\t\tswitch(type->What_Am_I()) {\n\t\t\tcase RTTI_INFANTRYTYPE:\n\t\t\t\tif ( ((InfantryTypeClass *)type)->ID >= INFANTRY_RA_COUNT)\n\t\t\t\t\treturn(false);\n\t\t\t\tbreak;\n\t\t\tcase RTTI_UNITTYPE:\n\t\t\t\tif ( ((UnitTypeClass *)type)->ID >= UNIT_RA_COUNT)\n\t\t\t\t\treturn(false);\n\t\t\t\tbreak;\n\t\t\tcase RTTI_VESSELTYPE:\n\t\t\t\tif ( ((VesselTypeClass *)type)->ID >= VESSEL_RA_COUNT)\n\t\t\t\t\treturn(false);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n#endif\n\n\t/*\n\t**\tThe computer can always build everything.\n\t*/\n\tif (!IsHuman && Session.Type == GAME_NORMAL) return(true);\n\n\t/*\n\t**\tSpecial hack to get certain objects to exist for both sides in the game.\n\t*/\n\tint own = type->Get_Ownable();\n\n\t/*\n\t**\tCheck to see if this owner can build the object type specified.\n\t*/\n\tif (((1L << house) & own) == 0) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tPerform some equivalency fixups for the building existence flags.\n\t*/\n\tlong flags = ActiveBScan;\n\n\t/*\n\t**\tThe computer records prerequisite buildings because it can't relay on the\n\t**\tsidebar to keep track of this information.\n\t*/\n\tif (!IsHuman) {\n\t\tflags = OldBScan;\n\t}\n\n\tint pre = ((TechnoTypeClass const *)type)->Prerequisite;\n\n\t/*\n\t**\tAdvanced power also serves as a prerequisite for normal power.\n\t*/\n\tif (flags & STRUCTF_ADVANCED_POWER) flags |= STRUCTF_POWER;\n\n\t/*\n\t**\tEither tech center counts as a prerequisite.\n\t*/\n\tif (Session.Type != GAME_NORMAL) {\n\t\tif ((flags & (STRUCTF_SOVIET_TECH|STRUCTF_ADVANCED_TECH)) != 0) flags |= STRUCTF_SOVIET_TECH|STRUCTF_ADVANCED_TECH;\n\t}\n\n\tint level = Control.TechLevel;\n#ifdef CHEAT_KEYS\n\tif (Debug_Cheat) {\n\t\tlevel = 98;\n\t\tpre = 0;\n\t}\n#endif\n\n\t/*\n\t**\tSee if the prerequisite requirements have been met.\n\t*/\n\treturn((pre & flags) == pre && ((TechnoTypeClass const *)type)->Level <= level);\n}\n\n\n/***************************************************************************\n * HouseClass::Init -- init's in preparation for new scenario              *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/07/1994 BR : Created.                                              *\n *   12/17/1994 JLB : Resets tracker bits.                                 *\n *=========================================================================*/\nvoid HouseClass::Init(void)\n{\n\tHouses.Free_All();\n\n\tfor (HousesType index = HOUSE_FIRST; index < HOUSE_COUNT; index++) {\n\t\tHouseTriggers[index].Clear();\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::AI -- Process house logic.                                                      *\n *                                                                                             *\n *    This handles the AI for the house object. It should be called once per house per game    *\n *    tick. It processes all house global tasks such as low power damage accumulation and      *\n *    house specific trigger events.                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *   07/17/1995 JLB : Limits EVA speaking unless the player can do something.                  *\n *=============================================================================================*/\nvoid HouseClass::AI(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tIf base building has been turned on by a trigger, then force the house to begin\n\t**\tproduction and team creation as well. This is also true if the IQ is high enough to\n\t**\tbeing base building.\n\t*/\n\tif (IsBaseBuilding || IQ >= Rule.IQProduction) {\n\t\tIsBaseBuilding = true;\n\t\tIsStarted = true;\n\t\tIsAlerted = true;\n\t}\n\n\t/*\n\t**\tCheck to see if the house wins.\n\t*/\n\tif (Session.Type == GAME_NORMAL && IsToWin && BorrowedTime == 0 && Blockage <= 0) {\n\t\tIsToWin = false;\n\t\tif (this == PlayerPtr) {\n\t\t\tPlayerWins = true;\n\t\t} else {\n\t\t\tPlayerLoses = true;\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck to see if the house loses.\n\t*/\n\tif (Session.Type == GAME_NORMAL && IsToLose && BorrowedTime == 0) {\n\t\tIsToLose = false;\n\t\tif (this == PlayerPtr) {\n\t\t\tPlayerLoses = true;\n\t\t} else {\n\t\t\tPlayerWins = true;\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck to see if all objects of this house should be blown up.\n\t*/\n\tif (IsToDie && BorrowedTime == 0) {\n\t\tIsToDie = false;\n\t\tBlowup_All();\n\t}\n\n\t/*\n\t**\tDouble check power values to correct illegal conditions. It is possible to\n\t**\tget a power output of negative (one usually) as a result of damage sustained\n\t**\tand the fixed point fractional math involved with power adjustments. If the\n\t**\tpower rating drops below zero, then make it zero.\n\t*/\n\tPower = max(Power, 0);\n\tDrain = max(Drain, 0);\n\n\t/*\n\t**\tIf the base has been alerted to the enemy and should be attacking, then\n\t**\tsee if the attack timer has expired. If it has, then create the attack\n\t**\tteams.\n\t*/\n\tif (IsAlerted && AlertTime == 0) {\n\n\t\t/*\n\t\t**\tAdjusted to reduce maximum number of teams created.\n\t\t*/\n\t\tint maxteams = Random_Pick(2, (int)(((Control.TechLevel-1)/3)+1));\n\t\tfor (int index = 0; index < maxteams; index++) {\n\t\t\tTeamTypeClass const * ttype = Suggested_New_Team(true);\n\t\t\tif (ttype != NULL) {\n\t\t\t\tScenarioInit++;\n\t\t\t\tttype->Create_One_Of();\n\t\t\t\tScenarioInit--;\n\t\t\t}\n\t\t}\n\t\tAlertTime = Rule.AutocreateTime * Random_Pick(TICKS_PER_MINUTE/2, TICKS_PER_MINUTE*2);\n//\t\tint mintime = Rule.AutocreateTime * (TICKS_PER_MINUTE/2);\n//\t\tint maxtime = Rule.AutocreateTime * (TICKS_PER_MINUTE*2);\n//\t\tAlertTime = Random_Pick(mintime, maxtime);\n\t}\n\n\t/*\n\t**\tIf this house's flag waypoint is a valid cell, see if there's\n\t**\tsomeone sitting on it.  If so, make the scatter.  If they refuse,\n\t**\tblow them up.\n\t*/\n\tif (FlagHome != 0 && (Frame % TICKS_PER_SECOND) == 0) {\n\n\t\tTechnoClass * techno = Map[FlagHome].Cell_Techno();\n\t\tif (techno != NULL) {\n\t\t\tbool moving = false;\n\t\t\tif (techno->Is_Foot()) {\n\t\t\t\tif (Target_Legal(((FootClass *)techno)->NavCom)) {\n\t\t\t\t\tmoving = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!moving) {\n\t\t\t\ttechno->Scatter(0, true, true);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the techno doesn't have a valid NavCom, he's not moving,\n\t\t\t**\tso blow him up.\n\t\t\t*/\n\t\t\tif (techno->Is_Foot()) {\n\t\t\t\tif (Target_Legal(((FootClass *)techno)->NavCom)) {\n\t\t\t\t\tmoving = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the techno wasn't an infantry or unit (ie he's a building),\n\t\t\t**\tor he refuses to move, blow him up\n\t\t\t*/\n\t\t\tif (!moving) {\n\t\t\t\tint count = 0;\n\t\t\t\twhile (!(techno->IsInLimbo) && count++ < 5) {\n\t\t\t\t\tint damage = techno->Strength;\n\t\t\t\t\ttechno->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCreate teams for this house if necessary.\n\t** (Use the same timer for some extra capture-the-flag logic.)\n\t*/\n\tif (!IsAlerted && !TeamTime) {\n\n\t\tTeamTypeClass const * ttype = Suggested_New_Team(false);\n\t\tif (ttype) {\n\t\t\tttype->Create_One_Of();\n\t\t}\n\n\t\tTeamTime = Rule.TeamDelay * TICKS_PER_MINUTE;\n\t}\n\n\t/*\n\t**\tIf there is insufficient power, then all buildings that are above\n\t**\thalf strength take a little bit of damage.\n\t*/\n\tif (DamageTime == 0) {\n\n\t\t/*\n\t\t**\tWhen the power is below required, then the buildings will take damage over\n\t\t**\ttime.\n\t\t*/\n\t\tif (Power_Fraction() < 1) {\n\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\tBuildingClass & b = *Buildings.Ptr(index);\n\n\t\t\t\tif (b.House == this && b.Health_Ratio() > Rule.ConditionYellow) {\n\t\t\t\t\t// BG: Only damage buildings that require power, to keep the\n\t\t\t\t\t//     land mines from blowing up under low-power conditions\n\t\t\t\t\tif (b.Class->Drain) {\n\t\t\t\t\t\tint damage = 1;\n\t\t\t\t\t\tb.Take_Damage(damage, 0, WARHEAD_AP, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tDamageTime = TICKS_PER_MINUTE * Rule.DamageDelay;\n\t}\n\n\t/*\n\t**\tIf there are no more buildings to sell, then automatically cancel the\n\t**\tsell mode.\n\t*/\n\tif (PlayerPtr == this && !ActiveBScan && Map.IsSellMode) {\n\t\tMap.Sell_Mode_Control(0);\n\t}\n\n\t/*\n\t**\tVarious base conditions may be announced to the player. Typically, this would be\n\t**\tlow tiberium capacity or low power.\n\t*/\n\tif (PlayerPtr == this) {\n\n\t\tif (SpeakMaxedDelay == 0 && Available_Money() < 100 && UnitFactories+BuildingFactories+InfantryFactories > 0) {\n\t\t\tSpeak(VOX_NEED_MO_MONEY);\n\t\t\tMap.Flash_Money();\n\t\t\tSpeakMaxedDelay = Options.Normalize_Delay(TICKS_PER_MINUTE * Rule.SpeakDelay);\n\t\t}\n\n\t\tif (SpeakMaxedDelay == 0 && IsMaxedOut) {\n\t\t\tIsMaxedOut = false;\n\t\t\tif ((Capacity - Tiberium) < 300 && Capacity > 500 && (ActiveBScan & (STRUCTF_REFINERY | STRUCTF_CONST))) {\n \t\t\t\tSpeak(VOX_NEED_MO_CAPACITY);\n\t\t\t\tSpeakMaxedDelay = Options.Normalize_Delay(TICKS_PER_MINUTE * Rule.SpeakDelay);\n\t\t\t}\n\t\t}\n\t\tif (SpeakPowerDelay == 0 && Power_Fraction() < 1) {\n\t\t\tif (ActiveBScan & STRUCTF_CONST) {\n\t\t\t\tSpeak(VOX_LOW_POWER);\n\t\t\t\tSpeakPowerDelay = Options.Normalize_Delay(TICKS_PER_MINUTE * Rule.SpeakDelay);\n\t\t\t\tMap.Flash_Power();\n\n\t\t\t\tchar const * text = NULL;\n\t\t\t\tif (BQuantity[STRUCT_AAGUN] > 0) {\n\t\t\t\t\ttext = Text_String(TXT_POWER_AAGUN);\n\t\t\t\t}\n\t\t\t\tif (BQuantity[STRUCT_TESLA] > 0) {\n\t\t\t\t\ttext = Text_String(TXT_POWER_TESLA);\n\t\t\t\t}\n\t\t\t\tif (text == NULL) {\n\t\t\t\t\ttext = Text_String(TXT_LOW_POWER);\n\t\t\t\t}\n\t\t\t\tif (text != NULL) {\n\t\t\t\t\tSession.Messages.Add_Message(NULL, 0, text, PCOLOR_GREEN, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is a flag associated with this house, then mark it to be\n\t**\tredrawn.\n\t*/\n\tif (Target_Legal(FlagLocation)) {\n\t\tUnitClass * unit = As_Unit(FlagLocation);\n\t\tif (unit) {\n\t\t\tunit->Mark(MARK_CHANGE);\n\t\t} else {\n\t\t\tCELL cell = As_Cell(FlagLocation);\n\t\t\tMap[cell].Redraw_Objects();\n\t\t}\n\t}\n\n\tbool is_time = false;\n\n\t/*\n\t**\tTriggers are only checked every so often. If the trigger timer has expired,\n\t**\tthen set the trigger processing flag.\n\t*/\n\tif (TriggerTime == 0 || IsBuiltSomething) {\n\t\tis_time = true;\n\t\tTriggerTime = TICKS_PER_MINUTE/10;\n\t\tIsBuiltSomething = false;\n\t}\n\n\t/*\n\t**\tProcess any super weapon logic required.\n\t*/\n\tSuper_Weapon_Handler();\n\n#ifdef FIXIT_VERSION_3\t\t\t//\tFor endgame auto-sonar pulse.\n\tif( Scen.AutoSonarTimer == 0 )\n\t{\n\t\t//\tIf house has nothing but subs left, do an automatic sonar pulse to reveal them.\n\t\tif( VQuantity[ VESSEL_SS ] > 0 )\t\t//\tIncludes count of VESSEL_MISSILESUBs. ajw\n\t\t{\n\t\t\tint iCount = 0;\n\t\t\tfor( int i = 0; i != STRUCT_COUNT-3; ++i )\n\t\t\t{\n\t\t\t\tiCount += BQuantity[ i ];\n\t\t\t}\n\t\t\tif( !iCount )\n\t\t\t{\n\t\t\t\tfor( i = 0; i != UNIT_RA_COUNT-3; ++i )\n\t\t\t\t{\n\t\t\t\t\tiCount += UQuantity[ i ];\n\t\t\t\t}\n\t\t\t\tif( !iCount )\n\t\t\t\t{\n\t\t\t\t\t//\tajw - Found bug - house's civilians are not removed from IQuantity when they die.\n\t\t\t\t\t//\tWorkaround...\n\t\t\t\t\tfor( i = 0; i <= INFANTRY_DOG; ++i )\n\t\t\t\t\t{\n\t\t\t\t\t\tiCount += IQuantity[ i ];\n\t\t\t\t\t}\n\t\t\t\t\tif( !iCount )\n\t\t\t\t\t{\n\t\t\t\t\t\tfor( i = 0; i != AIRCRAFT_COUNT; ++i )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tiCount += AQuantity[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif( !iCount )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor( i = 0; i != VESSEL_RA_COUNT; ++i )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif( i != VESSEL_SS )\n\t\t\t\t\t\t\t\t\tiCount += VQuantity[ i ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif( !iCount )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t//\tDo the ping.\n\t\t\t\t\t\t\t\tfor (int index = 0; index < Vessels.Count(); index++) {\n\t\t\t\t\t\t\t\t\tVesselClass * sub = Vessels.Ptr(index);\n\t\t\t\t\t\t\t\t\tif (*sub == VESSEL_SS || *sub == VESSEL_MISSILESUB) {\n\t\t\t\t\t\t\t\t\t\tsub->PulseCountDown = 15 * TICKS_PER_SECOND;\n\t\t\t\t\t\t\t\t\t\tsub->Do_Uncloak();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbAutoSonarPulse = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n\t/*\n\t** Special win/lose check for multiplayer games; by-passes the\n\t** trigger system.  We must wait for non-zero frame, because init\n\t** may not properly set IScan etc for each house; you have to go\n\t** through each object's AI before it will be properly set.\n\t*/\n\tif (Session.Type != GAME_NORMAL && !IsDefeated &&\n\t\t!ActiveBScan && !ActiveAScan && !UScan && !ActiveIScan && !ActiveVScan && Frame > 0) {\n\t\tMPlayer_Defeated();\n\t}\n\n\t/*\n\t**\tTry to spring all events attached to this house. The triggers will check\n\t**\tfor themselves if they actually need to be sprung or not.\n\t*/\n\tfor (int index = 0; index < HouseTriggers[Class->House].Count(); index++) {\n\t\tif (HouseTriggers[Class->House][index]->Spring() && index > 0) {\n\t\t\tindex--;\n\t\t\tcontinue;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf a radar facility is not present, but the radar is active, then turn the radar off.\n\t**\tThe radar also is turned off when the power gets below 100% capacity.\n\t*/\n\tif (PlayerPtr == this) {\n\t\tbool jammed = Map.Is_Radar_Active();\n\n\t\t/*\n\t\t** Find if there are any radar facilities, and if they're jammed or not\n\t\t*/\n\n\t\tif (IsGPSActive) {\n\t\t\tjammed = false;\n\t\t} else {\n\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\tBuildingClass * building = Buildings.Ptr(index);\n#ifdef FIXIT_RADAR_JAMMED\n\t\t\t\tif (building != NULL && !building->IsInLimbo && building->House == PlayerPtr) {\n#else\n\t\t\t\tif (building && building->House == PlayerPtr) {\n#endif\n\t\t\t\t\tif (*building == STRUCT_RADAR /* || *building == STRUCT_EYE */) {\n\t\t\t\t\t\tif (!building->IsJammed) {\n\t\t\t\t\t\t\tjammed = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (Map.Get_Jammed() != jammed) {\n\t\t\tMap.RadarClass::Flag_To_Redraw(true);\n\t\t}\n\t\tMap.Set_Jammed(jammed);\n// Need to add in here where we activate it when only GPS is active.\n\t\tif (Map.Is_Radar_Active()) {\n\t\t\tif (ActiveBScan & STRUCTF_RADAR) {\n\t\t\t\tif (Power_Fraction() < 1 && !IsGPSActive) {\n\t\t\t\t\tMap.Radar_Activate(0);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!IsGPSActive) {\n\t\t\t\t\tMap.Radar_Activate(0);\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tif (IsGPSActive || (ActiveBScan & STRUCTF_RADAR)) {\n\t\t\t\tif (Power_Fraction() >= 1 || IsGPSActive) {\n\t\t\t\t\tMap.Radar_Activate(1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (Map.Is_Radar_Existing()) {\n\t\t\t\t\tMap.Radar_Activate(4);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tPerform any expert system AI processing.\n\t*/\n\tif (IsBaseBuilding && AITimer == 0) {\n\t\tAITimer = Expert_AI();\n\t}\n\n\tif (!IsBaseBuilding && State == STATE_ENDGAME) {\n\t\tFire_Sale();\n\t\tDo_All_To_Hunt();\n\t}\n\n\tAI_Building();\n\tAI_Unit();\n\tAI_Vessel();\n\tAI_Infantry();\n\tAI_Aircraft();\n\n\n\t/*\n\t**\tIf the production possibilities need to be recalculated, then do so now. This must\n\t**\toccur after the scan bits have been properly updated.\n\t*/\n\tif (PlayerPtr == this && IsRecalcNeeded) {\n\t\tIsRecalcNeeded = false;\n\t\tMap.Recalc();\n\n\t\t/*\n\t\t**\tThis placement might affect any prerequisite requirements for construction\n\t\t**\tlists. Update the buildable options accordingly.\n\t\t*/\n\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass * building = Buildings.Ptr(index);\n\t\t\tif (building && building->Strength > 0 && building->Owner() == Class->House && building->Mission != MISSION_DECONSTRUCTION && building->MissionQueue != MISSION_DECONSTRUCTION) {\n\n\t\t\t\tif (PlayerPtr == building->House) {\n\t\t\t\t\tbuilding->Update_Buildables();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** See if it's time to re-set the can-repair flag\n\t*/\n\tif (DidRepair && RepairTimer == 0) {\n\t\tDidRepair = false;\n\t}\n\n\tif (this == PlayerPtr && IsToLook) {\n\t\tIsToLook = false;\n\t\tMap.All_To_Look();\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Super_Weapon_Handler -- Handles the super weapon charge and discharge logic.    *\n *                                                                                             *\n *    This handles any super weapons assigned to this house. It also performs any necessary    *\n *    maintenance that the super weapons require.                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Super_Weapon_Handler(void)\n{\n\t/*\n\t**\tPerform all super weapon AI processing. This just checks to see if\n\t**\tthe graphic needs changing for the special weapon and updates the\n\t**\tsidebar as necessary.\n\t*/\n\tfor (SpecialWeaponType special = SPC_FIRST; special < SPC_COUNT; special++) {\n\t\tSuperClass * super = &SuperWeapon[special];\n\n\t\tif (super->Is_Present()) {\n\n\t\t\t/*\n\t\t\t**\tPerform any charge-up logic for the super weapon. If the super\n\t\t\t**\tweapon is owned by the player and a graphic change is detected, then\n\t\t\t**\tflag the sidebar to be redrawn so the player will see the change.\n\t\t\t*/\n\t\t\tif (super->AI(this == PlayerPtr)) {\n\t\t\t\tif (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRepeating super weapons that require power will be suspended if there\n\t\t\t**\tis insufficient power available.\n\t\t\t*/\n\t\t\tif (!super->Is_Ready() && super->Is_Powered() && !super->Is_One_Time()) {\n\t\t\t\tsuper->Suspend(Power_Fraction() < 1);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Check to see if they have launched the GPS, but subsequently lost their\n\t** tech center.  If so, remove the GPS, and shroud the map.\n\t*/\n\tif (IsGPSActive && !(ActiveBScan & STRUCTF_ADVANCED_TECH) ) {\n\t\tIsGPSActive = false;\n\t\tif (IsPlayerControl) {\n\t\t\tMap.Shroud_The_Map();\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck to see if the GPS Satellite should be removed from the sidebar\n\t**\tbecause of outside circumstances. The advanced technology facility\n\t**\tbeing destroyed is a good example of this.  Having fired the satellite\n\t** is another good example, because it's a one-shot item.\n\t*/\n\tif (SuperWeapon[SPC_GPS].Is_Present()) {\n\t\tif (!(ActiveBScan & STRUCTF_ADVANCED_TECH) || IsGPSActive || IsDefeated) {\n\t\t\t/*\n\t\t\t**\tRemove the missile capability when there is no advanced tech facility.\n\t\t\t*/\n\t\t\tif (SuperWeapon[SPC_GPS].Remove()) {\n\t\t\t\tif (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t} else {\n\t\t\t/*\n\t\t\t** Auto-fire the GPS satellite if it's charged up.\n\t\t\t*/\n\t\t\tif (SuperWeapon[SPC_GPS].Is_Ready()) {\n\t\t\t\tSuperWeapon[SPC_GPS].Discharged(this == PlayerPtr);\n\t\t\t\tif (SuperWeapon[SPC_GPS].Remove()) {\n\t\t\t\t\tif (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\tBuildingClass * bldg = Buildings.Ptr(index);\n\t\t\t\t\tif (*bldg == STRUCT_ADVANCED_TECH && bldg->House == this) {\n\t\t\t\t\t\tbldg->HasFired = true;\n\t\t\t\t\t\tbldg->Assign_Mission(MISSION_MISSILE);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\t/*\n\t\t**\tIf there is no GPS satellite present, but there is a GPS satellite\n\t\t**\tfacility available, then make the GPS satellite available as well.\n\t\t*/\n\t\tif ((ActiveBScan & STRUCTF_ADVANCED_TECH) != 0 &&\n\t\t\t!IsGPSActive &&\n\t\t\tControl.TechLevel >= Rule.GPSTechLevel &&\n\t\t\t(IsHuman || IQ >= Rule.IQSuperWeapons)) {\n\n\t\t\tbool canfire = false;\n\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\tBuildingClass * bldg = Buildings.Ptr(index);\n\t\t\t\tif (*bldg == STRUCT_ADVANCED_TECH && bldg->House == this && !bldg->IsInLimbo) {\n\t\t\t\t\tif (!bldg->HasFired) {\n\t\t\t\t\t\tcanfire = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (canfire) {\n\t\t\t\tSuperWeapon[SPC_GPS].Enable(false, this == PlayerPtr, Power_Fraction() < 1);\n\n\t\t\t\t/*\n\t\t\t\t**\tFlag the sidebar to be redrawn if necessary.\n\t\t\t\t*/\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_GPS);\n\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck to see if the chronosphere should be removed from the sidebar\n\t**\tbecause of outside circumstances. The chronosphere facility\n\t**\tbeing destroyed is a good example of this.\n\t*/\n\tif (SuperWeapon[SPC_CHRONOSPHERE].Is_Present()) {\n\t\tif ( (!(ActiveBScan & STRUCTF_CHRONOSPHERE) && !SuperWeapon[SPC_CHRONOSPHERE].Is_One_Time()) || IsDefeated) {\n\n\t\t\t/*\n\t\t\t**\tRemove the chronosphere when there is no chronosphere facility.\n\t\t\t**\tNote that this will not remove the one time created chronosphere.\n\t\t\t*/\n\t\t\tif (SuperWeapon[SPC_CHRONOSPHERE].Remove()) {\n\t\t\t\tif (this == PlayerPtr) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\tif (Map.IsTargettingMode == SPC_CHRONOSPHERE || Map.IsTargettingMode == SPC_CHRONO2) {\n\t\t\t\t\t\tif (Map.IsTargettingMode == SPC_CHRONO2) {\n\t\t\t\t\t\t\tTechnoClass * tech = (TechnoClass *)::As_Object(UnitToTeleport);\n\t\t\t\t\t\t\tif (tech && tech->IsActive && tech->What_Am_I() == RTTI_UNIT && *(UnitClass *)tech == UNIT_CHRONOTANK) {\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t Map.IsTargettingMode = SPC_NONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n#else\n\t\t\t\t\tif (Map.IsTargettingMode == SPC_CHRONOSPHERE ||\n\t\t\t\t\t\t Map.IsTargettingMode == SPC_CHRONO2) {\n\t\t\t\t\t\t Map.IsTargettingMode = SPC_NONE;\n\t\t\t\t\t}\n#endif\n\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t}\n\t} else {\n\t\t/*\n\t\t**\tIf there is no chronosphere present, but there is a chronosphere\n\t\t**\tfacility available, then make the chronosphere available as well.\n\t\t*/\n\t\tif ((ActiveBScan & STRUCTF_CHRONOSPHERE) &&\n//\t\t\t(ActLike == HOUSE_GOOD || Session.Type != GAME_NORMAL) &&\n\t\t\tControl.TechLevel >= BuildingTypeClass::As_Reference(STRUCT_CHRONOSPHERE).Level &&\n//\t\t\tControl.TechLevel >= Rule.ChronoTechLevel &&\n\t\t\t(IsHuman || IQ >= Rule.IQSuperWeapons)) {\n\n\t\t\tSuperWeapon[SPC_CHRONOSPHERE].Enable(false, this == PlayerPtr, Power_Fraction() < 1);\n\n\t\t\t/*\n\t\t\t**\tFlag the sidebar to be redrawn if necessary.\n\t\t\t*/\n\t\t\tif (this == PlayerPtr) {\n\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_CHRONOSPHERE);\n\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck to see if the iron curtain should be removed from the sidebar\n\t**\tbecause of outside circumstances. The iron curtain facility\n\t**\tbeing destroyed is a good example of this.\n\t*/\n\tif (SuperWeapon[SPC_IRON_CURTAIN].Is_Present()) {\n\t\tif ( (!(ActiveBScan & STRUCTF_IRON_CURTAIN) && !SuperWeapon[SPC_IRON_CURTAIN].Is_One_Time())  || IsDefeated) {\n\n\t\t\t/*\n\t\t\t**\tRemove the iron curtain when there is no iron curtain facility.\n\t\t\t**\tNote that this will not remove the one time created iron curtain.\n\t\t\t*/\n\t\t\tif (SuperWeapon[SPC_IRON_CURTAIN].Remove()) {\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tif (Map.IsTargettingMode == SPC_IRON_CURTAIN) {\n\t\t\t\t\t\t Map.IsTargettingMode = SPC_NONE;\n\t\t\t\t\t}\n\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t}\n\t} else {\n\t\t/*\n\t\t**\tIf there is no iron curtain present, but there is an iron curtain\n\t\t**\tfacility available, then make the iron curtain available as well.\n\t\t*/\n\t\tif ((ActiveBScan & STRUCTF_IRON_CURTAIN) &&\n\t\t\t(ActLike == HOUSE_USSR || ActLike == HOUSE_UKRAINE || Session.Type != GAME_NORMAL) &&\n\t\t\t(IsHuman || IQ >= Rule.IQSuperWeapons)) {\n\n\t\t\tSuperWeapon[SPC_IRON_CURTAIN].Enable(false, this == PlayerPtr, Power_Fraction() < 1);\n\n\t\t\t/*\n\t\t\t**\tFlag the sidebar to be redrawn if necessary.\n\t\t\t*/\n\t\t\tif (this == PlayerPtr) {\n\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_IRON_CURTAIN);\n\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck to see if the sonar pulse should be removed from the sidebar\n\t**\tbecause of outside circumstances. The spied-upon enemy sub pen\n\t**\tbeing destroyed is a good example of this.\n\t*/\n\tif (SuperWeapon[SPC_SONAR_PULSE].Is_Present()) {\n\t\tint usspy = 1 << (Class->House);\n\t\tbool present = false;\n\t\tbool powered = false;\n\t\tfor (int q = 0; q < Buildings.Count() && !powered; q++) {\n\t\t\tBuildingClass * bldg = Buildings.Ptr(q);\n\t\t\tif ((*bldg == STRUCT_SUB_PEN) && (bldg->House->Class->House != Class->House) && (bldg->SpiedBy & usspy) ) {\n\t\t\t\tpresent = true;\n\t\t\t\tpowered = !(bldg->House->Power_Fraction() < 1);\n\t\t\t}\n\t\t}\n\t\tif ( (!present && !SuperWeapon[SPC_SONAR_PULSE].Is_One_Time())  || IsDefeated) {\n\n\t\t\t/*\n\t\t\t**\tRemove the sonar pulse when there is no spied-upon enemy sub pen.\n\t\t\t**\tNote that this will not remove the one time created sonar pulse.\n\t\t\t*/\n\t\t\tif (SuperWeapon[SPC_SONAR_PULSE].Remove()) {\n\t\t\t\tif (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck to see if the nuclear weapon should be removed from the sidebar\n\t**\tbecause of outside circumstances. The missile silos\n\t**\tbeing destroyed is a good example of this.\n\t*/\n\tif (SuperWeapon[SPC_NUCLEAR_BOMB].Is_Present()) {\n\t\tif ( (!(ActiveBScan & STRUCTF_MSLO) && !SuperWeapon[SPC_NUCLEAR_BOMB].Is_One_Time()) || IsDefeated) {\n\n\t\t\t/*\n\t\t\t**\tRemove the nuke when there is no missile silo.\n\t\t\t**\tNote that this will not remove the one time created nuke.\n\t\t\t*/\n\t\t\tif (SuperWeapon[SPC_NUCLEAR_BOMB].Remove()) {\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tif (Map.IsTargettingMode == SPC_NUCLEAR_BOMB) {\n\t\t\t\t\t\t Map.IsTargettingMode = SPC_NONE;\n\t\t\t\t\t}\n\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t} else {\n\t\t\t/*\n\t\t\t**\tAllow the computer to fire the nuclear weapon when the weapon is\n\t\t\t**\tready and the owner is the computer.\n\t\t\t*/\n\t\t\tif (SuperWeapon[SPC_NUCLEAR_BOMB].Is_Ready() && !IsHuman) {\n\t\t\t\tSpecial_Weapon_AI(SPC_NUCLEAR_BOMB);\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t/*\n\t\t**\tIf there is no nuclear missile present, but there is a missile\n\t\t**\tsilo available, then make the missile available as well.\n\t\t*/\n\t\tif ((ActiveBScan & STRUCTF_MSLO) &&\n\t\t\t((ActLike != HOUSE_USSR && ActLike != HOUSE_UKRAINE) || Session.Type != GAME_NORMAL) &&\n\t\t\t(IsHuman || IQ >= Rule.IQSuperWeapons)) {\n\n\t\t\tSuperWeapon[SPC_NUCLEAR_BOMB].Enable(false, this == PlayerPtr, Power_Fraction() < 1);\n\n\t\t\t/*\n\t\t\t**\tFlag the sidebar to be redrawn if necessary.\n\t\t\t*/\n\t\t\tif (this == PlayerPtr) {\n\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_NUCLEAR_BOMB);\n\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t}\n\t\t}\n\t}\n\n\n\tif (SuperWeapon[SPC_SPY_MISSION].Is_Present()) {\n\t\tif ((ActiveBScan & STRUCTF_AIRSTRIP) == 0) {\n\t\t\tif (SuperWeapon[SPC_SPY_MISSION].Remove()) {\n\t\t\t\tif (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t} else {\n\t\t\tif (this == PlayerPtr && !SuperWeapon[SPC_SPY_MISSION].Is_Ready()) {\n\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t}\n\t\t\tif (SuperWeapon[SPC_SPY_MISSION].Is_Ready() && !IsHuman) {\n\t\t\t\tSpecial_Weapon_AI(SPC_SPY_MISSION);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif ((ActiveBScan & STRUCTF_AIRSTRIP) != 0 && !Scen.IsNoSpyPlane && Control.TechLevel >= Rule.SpyPlaneTechLevel) {\n\t\t\tSuperWeapon[SPC_SPY_MISSION].Enable(false, this == PlayerPtr, false);\n\t\t\tif (this == PlayerPtr) {\n\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_SPY_MISSION);\n\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t}\n\t\t}\n\t}\n\n\tif (SuperWeapon[SPC_PARA_BOMB].Is_Present()) {\n\t\tif ((ActiveBScan & STRUCTF_AIRSTRIP) == 0) {\n\t\t\tif (SuperWeapon[SPC_PARA_BOMB].Remove()) {\n\t\t\t\tif (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t} else {\n\t\t\tif (SuperWeapon[SPC_PARA_BOMB].Is_Ready() && !IsHuman) {\n\t\t\t\tSpecial_Weapon_AI(SPC_PARA_BOMB);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif ((ActiveBScan & STRUCTF_AIRSTRIP) != 0 && Control.TechLevel >= Rule.ParaBombTechLevel && Session.Type == GAME_NORMAL) {\n\t\t\tSuperWeapon[SPC_PARA_BOMB].Enable(false, this == PlayerPtr, false);\n\t\t\tif (this == PlayerPtr) {\n\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_PARA_BOMB);\n\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t}\n\t\t}\n\t}\n\n\tif (SuperWeapon[SPC_PARA_INFANTRY].Is_Present()) {\n\t\tif ((ActiveBScan & STRUCTF_AIRSTRIP) == 0) {\n\t\t\tif (SuperWeapon[SPC_PARA_INFANTRY].Remove()) {\n\t\t\t\tif (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t} else {\n\t\t\tif (SuperWeapon[SPC_PARA_INFANTRY].Is_Ready() && !IsHuman) {\n\t\t\t\tSpecial_Weapon_AI(SPC_PARA_INFANTRY);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif ((ActiveBScan & STRUCTF_AIRSTRIP) != 0 && Control.TechLevel >= Rule.ParaInfantryTechLevel) {\n\t\t\tSuperWeapon[SPC_PARA_INFANTRY].Enable(false, this == PlayerPtr, false);\n\t\t\tif (this == PlayerPtr) {\n\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_PARA_INFANTRY);\n\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Attacked -- Lets player know if base is under attack.                           *\n *                                                                                             *\n *    Call this function whenever a building is attacked (with malice). This function will     *\n *    then announce to the player that his base is under attack. It checks to make sure that   *\n *    this is referring to the player's house rather than the enemy's.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Attacked(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n#ifdef FIXIT_BASE_ANNOUNCE\n\tif (SpeakAttackDelay == 0 && ((Session.Type == GAME_NORMAL && IsPlayerControl) || PlayerPtr->Class->House == Class->House)) {\n#else\n\tif (SpeakAttackDelay == 0 && PlayerPtr->Class->House == Class->House) {\n#endif\n\t\tSpeak(VOX_BASE_UNDER_ATTACK);\n\t\tSpeakAttackDelay = Options.Normalize_Delay(TICKS_PER_MINUTE * Rule.SpeakDelay);\n\n\t\t/*\n\t\t**\tIf there is a trigger event associated with being attacked, process it\n\t\t**\tnow.\n\t\t*/\n\t\tfor (int index = 0; index < HouseTriggers[Class->House].Count(); index++) {\n\t\t\tHouseTriggers[Class->House][index]->Spring(TEVENT_ATTACKED);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Harvested -- Adds Tiberium to the harvest storage.                              *\n *                                                                                             *\n *    Use this routine whenever Tiberium is harvested. The Tiberium is stored equally between  *\n *    all storage capable buildings for the house. Harvested Tiberium adds to the credit       *\n *    value of the house, but only up to the maximum storage capacity that the house can       *\n *    currently maintain.                                                                      *\n *                                                                                             *\n * INPUT:   tiberium -- The number of Tiberium credits to add to the House's total.            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Harvested(unsigned tiberium)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tlong oldtib = Tiberium;\n\n\tTiberium += tiberium;\n\tif (Tiberium > Capacity) {\n\t\tTiberium = Capacity;\n\t\tIsMaxedOut = true;\n\t}\n\tHarvestedCredits += tiberium;\n\tSilo_Redraw_Check(oldtib, Capacity);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Stole -- Accounts for the value of a captured building.\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *    Use this routine whenever a building is captured.  It keeps track of the cost of the     *\n *    building for use in the scoring routine, because you get an 'economy' boost for the      *\n *    value of the stolen building (but you don't get the credit value for it.)                *\n *                                                                                             *\n * INPUT:   worth -- The worth of the building we captured (stole).            \t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/05/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Stole(unsigned worth)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tStolenBuildingsCredits += worth;\n}\n\n\n/***********************************************************************************************\n * HouseClass::Available_Money -- Fetches the total credit worth of the house.                 *\n *                                                                                             *\n *    Use this routine to determine the total credit value of the house. This is the sum of    *\n *    the harvested Tiberium in storage and the initial unspent cash reserves.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the total credit value of the house.                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong HouseClass::Available_Money(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(Tiberium + Credits);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Spend_Money -- Removes money from the house.                                    *\n *                                                                                             *\n *    Use this routine to extract money from the house. Typically, this is a result of         *\n *    production spending. The money is extracted from available cash reserves first. When     *\n *    cash reserves are exhausted, then Tiberium is consumed.                                  *\n *                                                                                             *\n * INPUT:   money -- The amount of money to spend.                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/25/1995 JLB : Created.                                                                 *\n *   06/20/1995 JLB : Spends Tiberium before spending cash.                                    *\n *=============================================================================================*/\nvoid HouseClass::Spend_Money(unsigned money)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tlong oldtib = Tiberium;\n\tif (money > Tiberium) {\n\t\tmoney -= (unsigned)Tiberium;\n\t\tTiberium = 0;\n\t\tCredits -= money;\n\t} else {\n\t\tTiberium -= money;\n\t}\n\tSilo_Redraw_Check(oldtib, Capacity);\n\tCreditsSpent += money;\n}\n\n\n/***********************************************************************************************\n * HouseClass::Refund_Money -- Refunds money to back to the house.                             *\n *                                                                                             *\n *    Use this routine when money needs to be refunded back to the house. This can occur when  *\n *    construction is aborted. At this point, the exact breakdown of Tiberium or initial       *\n *    credits used for the orignal purchase is lost. Presume as much of the money is in the    *\n *    form of Tiberium as storage capacity will allow.                                         *\n *                                                                                             *\n * INPUT:   money -- The number of credits to refund back to the house.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/25/1995 JLB : Created.                                                                 *\n *   06/01/1995 JLB : Refunded money is never lost                                             *\n *=============================================================================================*/\nvoid HouseClass::Refund_Money(unsigned money)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tCredits += money;\n}\n\n\n/***********************************************************************************************\n * HouseClass::Adjust_Capacity -- Adjusts the house Tiberium storage capacity.                 *\n *                                                                                             *\n *    Use this routine to adjust the maximum storage capacity for the house. This storage      *\n *    capacity will limit the number of Tiberium credits that can be stored at any one time.   *\n *                                                                                             *\n * INPUT:   adjust   -- The adjustment to the Tiberium storage capacity.                       *\n *                                                                                             *\n *          inanger  -- Is this a forced adjustment to capacity due to some hostile event?     *\n *                                                                                             *\n * OUTPUT:  Returns with the number of Tiberium credits lost.                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint HouseClass::Adjust_Capacity(int adjust, bool inanger)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tlong oldcap = Capacity;\n\tint retval = 0;\n\n\tCapacity += adjust;\n\tCapacity = max(Capacity, 0L);\n\tif (Tiberium > Capacity) {\n\t\tretval = Tiberium - Capacity;\n\t\tTiberium = Capacity;\n\t\tif (!inanger) {\n\t\t\tRefund_Money(retval);\n\t\t\tretval = 0;\n\t\t} else {\n\t\t\tIsMaxedOut = true;\n\t\t}\n\t}\n\tSilo_Redraw_Check(Tiberium, oldcap);\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Silo_Redraw_Check -- Flags silos to be redrawn if necessary.                    *\n *                                                                                             *\n *    Call this routine when either the capacity or tiberium levels change for a house. This   *\n *    routine will determine if the aggregate tiberium storage level will result in the        *\n *    silos changing their imagery. If this is detected, then all the silos for this house     *\n *    are flagged to be redrawn.                                                               *\n *                                                                                             *\n * INPUT:   oldtib   -- Pre-change tiberium level.                                             *\n *                                                                                             *\n *          oldcap   -- Pre-change tiberium storage capacity.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Silo_Redraw_Check(long oldtib, long oldcap)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tint oldratio = 0;\n\tif (oldcap) oldratio = (oldtib * 5) / oldcap;\n\tint newratio = 0;\n\tif (Capacity) newratio = (Tiberium * 5) / Capacity;\n\n\tif (oldratio != newratio) {\n\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass * b = Buildings.Ptr(index);\n\t\t\tif (b && !b->IsInLimbo && b->House == this && *b == STRUCT_STORAGE) {\n\t\t\t\tb->Mark(MARK_CHANGE);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Is_Ally -- Determines if the specified house is an ally.                        *\n *                                                                                             *\n *    This routine will determine if the house number specified is a ally to this house.       *\n *                                                                                             *\n * INPUT:   house -- The house number to check to see if it is an ally.                        *\n *                                                                                             *\n * OUTPUT:  Is the house an ally?                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Is_Ally(HousesType house) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (house != HOUSE_NONE) {\n\t\treturn(((1<<house) & Allies) != 0);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Is_Ally -- Determines if the specified house is an ally.                        *\n *                                                                                             *\n *    This routine will examine the specified house and determine if it is an ally.            *\n *                                                                                             *\n * INPUT:   house -- Pointer to the house object to check for ally relationship.               *\n *                                                                                             *\n * OUTPUT:  Is the specified house an ally?                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Is_Ally(HouseClass const * house) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (house) {\n\t\treturn(Is_Ally(house->Class->House));\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Is_Ally -- Checks to see if the object is an ally.                              *\n *                                                                                             *\n *    This routine will examine the specified object and return whether it is an ally or not.  *\n *                                                                                             *\n * INPUT:   object   -- The object to examine to see if it is an ally.                         *\n *                                                                                             *\n * OUTPUT:  Is the specified object an ally?                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Is_Ally(ObjectClass const * object) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (object) {\n\t\treturn(Is_Ally(object->Owner()));\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Make_Ally -- Make the specified house an ally.                                  *\n *                                                                                             *\n *    This routine will make the specified house an ally to this house. An allied house will   *\n *    not be considered a threat or potential target.                                          *\n *                                                                                             *\n * INPUT:   house -- The house to make an ally of this house.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *   08/08/1995 JLB : Breaks off combat when ally commences.                                   *\n *   10/17/1995 JLB : Added reveal base when allied.                                           *\n *=============================================================================================*/\nvoid HouseClass::Make_Ally(HousesType house)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (Is_Allowed_To_Ally(house)) {\n\n\t\tAllies |= (1L << house);\n\n\t\t/*\n\t\t**\tDon't consider the newfound ally to be an enemy -- of course.\n\t\t*/\n\t\tif (Enemy == house) {\n\t\t\tEnemy = HOUSE_NONE;\n\t\t}\n\n\t\tif (ScenarioInit) {\n\t\t\tControl.Allies |= (1L << house);\n\t\t}\n\n\t\tif (Session.Type != GAME_NORMAL && !ScenarioInit) {\n\t\t\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\n\t\t\t/*\n\t\t\t**\tAn alliance with another human player will cause the computer\n\t\t\t**\tplayers (if present) to become paranoid.\n\t\t\t*/\n\t\t\tif (hptr != NULL && IsHuman && Rule.IsComputerParanoid) {\n//\t\t\tif (hptr != NULL && hptr->IsHuman) {\n//\t\t\t\tif (!hptr->IsHuman) {\n//\t\t\t\t\thptr->Make_Ally(Class->House);\n//\t\t\t\t}\n\t\t\t\tComputer_Paranoid();\n\t\t\t}\n\n\t\t\tchar buffer[80];\n\n\t\t\t/*\n\t\t\t**\tSweep through all techno objects and perform a cheeseball tarcom clear to ensure\n\t\t\t**\tthat fighting will most likely stop when the cease fire begins.\n\t\t\t*/\n\t\t\tfor (int index = 0; index < Logic.Count(); index++) {\n\t\t\t\tObjectClass * object = Logic[index];\n\n\t\t\t\tif (object != NULL && object->Is_Techno() && !object->IsInLimbo && object->Owner() == Class->House) {\n\t\t\t\t\tTARGET target = ((TechnoClass *)object)->TarCom;\n\t\t\t\t\tif (Target_Legal(target) && As_Techno(target) != NULL) {\n\t\t\t\t\t\tif (Is_Ally(As_Techno(target))) {\n\t\t\t\t\t\t\t((TechnoClass *)object)->Assign_Target(TARGET_NONE);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCause all structures to be revealed to the house that has been\n\t\t\t**\tallied with.\n\t\t\t*/\n\t\t\tif (Rule.IsAllyReveal && house == PlayerPtr->Class->House) {\n\t\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\tBuildingClass const * b = Buildings.Ptr(index);\n\n\t\t\t\t\tif (b && !b->IsInLimbo && (HouseClass *)b->House == this) {\n\t\t\t\t\t\tMap.Sight_From(Coord_Cell(b->Center_Coord()), b->Class->SightRange, PlayerPtr, false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (IsHuman) {\n\t\t\t\tsprintf(buffer, Text_String(TXT_HAS_ALLIED), IniName, HouseClass::As_Pointer(house)->IniName);\n//\t\t\t\tsprintf(buffer, Text_String(TXT_HAS_ALLIED), Session.Players[Class->House - HOUSE_MULTI1]->Name, Session.Players[((HouseClass::As_Pointer(house))->Class->House) - HOUSE_MULTI1]->Name);\n\t\t\t\tSession.Messages.Add_Message(NULL, 0, buffer, RemapColor, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, TICKS_PER_MINUTE * Rule.MessageDelay);\n\t\t\t}\n\n#if(TEN)\n\t\t\t//\n\t\t\t// Notify the TEN server of the new alliance\n\t\t\t//\n\t\t\tif (this == PlayerPtr && hptr != NULL && Session.Type == GAME_TEN) {\n\t\t\t\tSend_TEN_Alliance(hptr->IniName, 1);\n\t\t\t}\n#endif\t// TEN\n\n#if(MPATH)\n\t\t\t//\n\t\t\t// Notify the MPATH server of the new alliance\n\t\t\t//\n\t\t\t//if (this == PlayerPtr && hptr != NULL && Session.Type == GAME_MPATH) {\n\t\t\t\t//Send_MPATH_Alliance(hptr->IniName, 1);\n\t\t\t//}\n#endif\t// MPATH\n\n\t\t\tMap.Flag_To_Redraw(false);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Make_Enemy -- Make an enemy of the house specified.                             *\n *                                                                                             *\n *    This routine will flag the house specified so that it will be an enemy to this house.    *\n *    Enemy houses are legal targets for attack.                                               *\n *                                                                                             *\n * INPUT:   house -- The house to make an enemy of this house.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *   07/27/1995 JLB : Making war is a bilateral action.                                        *\n *=============================================================================================*/\nvoid HouseClass::Make_Enemy(HousesType house)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (house != HOUSE_NONE && Is_Ally(house)) {\n\t\tHouseClass * enemy = HouseClass::As_Pointer(house);\n\t\tAllies &= ~(1L << house);\n\n\t\tif (ScenarioInit) {\n\t\t\tControl.Allies &= !(1L << house);\n\t\t}\n\n\t\t/*\n\t\t**\tBreaking an alliance is a bilateral event.\n\t\t*/\n\t\tif (enemy != NULL && enemy->Is_Ally(this)) {\n\t\t\tenemy->Allies &= ~(1L << Class->House);\n\n\t\t\tif (ScenarioInit) {\n\t\t\t\tControl.Allies &= ~(1L << Class->House);\n\t\t\t}\n\t\t}\n\n\t\tif ((Debug_Flag || Session.Type != GAME_NORMAL) && !ScenarioInit && IsHuman) {\n\t\t\tchar buffer[80];\n\n\t\t\tsprintf(buffer, Text_String(TXT_AT_WAR), IniName, HouseClass::As_Pointer(house)->IniName);\n//\t\t\tsprintf(buffer, Text_String(TXT_AT_WAR), Session.Players[Class->House - HOUSE_MULTI1]->Name, Session.Players[enemy->Class->House - HOUSE_MULTI1]->Name);\n\t\t\tSession.Messages.Add_Message(NULL, 0, buffer, RemapColor, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, TICKS_PER_MINUTE * Rule.MessageDelay);\n\t\t\tMap.Flag_To_Redraw(false);\n\n#if(TEN)\n\t\t\t//\n\t\t\t// Notify the TEN server of the broken alliance\n\t\t\t//\n\t\t\tif (this == PlayerPtr && enemy != NULL && Session.Type == GAME_TEN) {\n\t\t\t\tSend_TEN_Alliance(enemy->IniName, 0);\n\t\t\t}\n#endif\t// TEN\n\n#if(MPATH)\n\t\t\t//\n\t\t\t// Notify the MPATH server of the broken alliance\n\t\t\t//\n\t\t\t//if (this == PlayerPtr && enemy != NULL && Session.Type == GAME_MPATH) {\n\t\t\t\t//Send_MPATH_Alliance(enemy->IniName, 0);\n\t\t\t//}\n#endif\t// MPATH\n\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Remap_Table -- Fetches the remap table for this house object.                   *\n *                                                                                             *\n *    This routine will return with the remap table to use when displaying an object owned     *\n *    by this house. If the object is blushing (flashing), then the lightening remap table is  *\n *    always used. The \"unit\" parameter allows proper remap selection for those houses that    *\n *    have a different remap table for buildings or units.                                     *\n *                                                                                             *\n * INPUT:   blushing -- Is the object blushing (flashing)?                                     *\n *                                                                                             *\n *          remap    -- The remap control value to use.                                        *\n *                      REMAP_NONE     No remap pointer returned at all.                       *\n *                      REMAP_NORMAL   Return the remap pointer for this house.                *\n *                      REMAP_ALTERNATE   (Nod solo play only -- forces red remap).            *\n *                                        Multiplay returns same as REMAP_NORMAL               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the remap table to use when drawing this object.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *   10/25/1995 JLB : Uses remap control value.                                                *\n *=============================================================================================*/\nunsigned char const * HouseClass::Remap_Table(bool blushing, RemapType remap) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (blushing) return(&Map.FadingLight[0]);\n\n\tif (remap == REMAP_NONE) return(0);\n\n\treturn(ColorRemaps[RemapColor].RemapTable);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Suggested_New_Team -- Determine what team should be created.                    *\n *                                                                                             *\n *    This routine examines the house condition and returns with the team that it thinks       *\n *    should be created. The units that are not currently a member of a team are examined      *\n *    to determine the team needed.                                                            *\n *                                                                                             *\n * INPUT:   alertcheck  -- Select from the auto-create team list.                              *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the team type that should be created. If no team should  *\n *          be created, then NULL is returned.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTeamTypeClass const * HouseClass::Suggested_New_Team(bool alertcheck)\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(TeamTypeClass::Suggested_New_Team(this, AScan, UScan, IScan, VScan, alertcheck));\n}\n\n\n/***********************************************************************************************\n * HouseClass::Adjust_Threat -- Adjust threat for the region specified.                        *\n *                                                                                             *\n *    This routine is called when the threat rating for a region needs to change. The region   *\n *    and threat adjustment are provided.                                                      *\n *                                                                                             *\n * INPUT:   region   -- The region that adjustment is to occur on.                             *\n *                                                                                             *\n *          threat   -- The threat adjustment to perform.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Adjust_Threat(int region, int threat)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tstatic int _val[] = {\n\t\t-MAP_REGION_WIDTH - 1,\t-MAP_REGION_WIDTH, -MAP_REGION_WIDTH + 1,\n\t\t-1,\t\t\t\t\t\t\t0,\t\t\t\t\t\t 1,\n\t\tMAP_REGION_WIDTH -1,\t\tMAP_REGION_WIDTH,\t MAP_REGION_WIDTH +1\n\t};\n\tstatic int _thr[] = {\n\t\t2, 1, 2,\n\t\t1, 0, 1,\n\t\t2, 1,\t2\n\t};\n\tint neg;\n\tint * val = &_val[0];\n\tint * thr = &_thr[0];\n\n\tif (threat < 0) {\n\t\tthreat = -threat;\n\t\tneg = true;\n\t} else {\n\t\tneg = false;\n\t}\n\n\tfor (int lp = 0; lp < 9; lp ++) {\n\t\tRegions[region + *val].Adjust_Threat(threat >> *thr, neg);\n\t\tval++;\n\t\tthr++;\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Begin_Production -- Starts production of the specified object type.             *\n *                                                                                             *\n *    This routine is called from the event system. It will start production for the object    *\n *    type specified. This will be reflected in the sidebar as well as the house factory       *\n *    tracking variables.                                                                      *\n *                                                                                             *\n * INPUT:   type  -- The type of object to begin production on.                                *\n *                                                                                             *\n *          id    -- The subtype of object.                                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the reason why, or why not, production was started.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *   10/21/1996 JLB : Handles max object case.                                                 *\n *=============================================================================================*/\nProdFailType HouseClass::Begin_Production(RTTIType type, int id)\n{\n\tassert(Houses.ID(this) == ID);\n\tint result = true;\n\tbool initial_start = false;\n\tFactoryClass * fptr;\n\tTechnoTypeClass const * tech = Fetch_Techno_Type(type, id);\n\n\tfptr = Fetch_Factory(type);\n\n\t/*\n\t**\tIf the house is already busy producing the requested object, then\n\t**\treturn with this failure code, unless we are restarting production.\n\t*/\n\tif (fptr != NULL) {\n\t\tif (fptr->Is_Building()) {\n\t\t\treturn(PROD_CANT);\n\t\t}\n\t} else {\n\t\tfptr = new FactoryClass();\n\t\tif (!fptr) return(PROD_CANT);\n\t\tSet_Factory(type, fptr);\n\t\tresult = fptr->Set(*tech, *this);\n\t\tinitial_start = true;\n\t}\n\n\tif (result) {\n\t\tfptr->Start();\n\n\t\t/*\n\t\t**\tLink this factory to the sidebar so that proper graphic feedback\n\t\t**\tcan take place.\n\t\t*/\n\t\tif (PlayerPtr == this) {\n\t\t\tMap.Factory_Link(fptr->ID, type, id);\n\t\t}\n\t\treturn(PROD_OK);\n\t}\n\n\tdelete fptr;\n\treturn(PROD_CANT);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Suspend_Production -- Temporarily puts production on hold.                      *\n *                                                                                             *\n *    This routine is called from the event system whenever the production of the specified    *\n *    type needs to be suspended. The suspended production will be reflected in the sidebar    *\n *    as well as in the house control structure.                                               *\n *                                                                                             *\n * INPUT:   type  -- The type of object that production is being suspended for.                *\n *                                                                                             *\n * OUTPUT:  Returns why, or why not, production was suspended.                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nProdFailType HouseClass::Suspend_Production(RTTIType type)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tFactoryClass * fptr = Fetch_Factory(type);\n\n\t/*\n\t**\tIf the house is already busy producing the requested object, then\n\t**\treturn with this failure code.\n\t*/\n\tif (fptr == NULL) return(PROD_CANT);\n\n\t/*\n\t**\tActually suspend the production.\n\t*/\n\tfptr->Suspend();\n\n\t/*\n\t**\tTell the sidebar that it needs to be redrawn because of this.\n\t*/\n\tif (PlayerPtr == this) {\n\t\tMap.SidebarClass::IsToRedraw = true;\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n\treturn(PROD_OK);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Abandon_Production -- Abandons production of item type specified.               *\n *                                                                                             *\n *    This routine is called from the event system whenever production must be abandoned for   *\n *    the type specified. This will remove the factory and pending object from the sidebar as  *\n *    well as from the house factory record.                                                   *\n *                                                                                             *\n * INPUT:   type  -- The object type that production is being suspended for.                   *\n *                                                                                             *\n * OUTPUT:  Returns the reason why or why not, production was suspended.                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nProdFailType HouseClass::Abandon_Production(RTTIType type)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tFactoryClass * fptr = Fetch_Factory(type);\n\n\t/*\n\t**\tIf there is no factory to abandon, then return with a failure code.\n\t*/\n\tif (fptr == NULL) return(PROD_CANT);\n\n\t/*\n\t**\tTell the sidebar that it needs to be redrawn because of this.\n\t*/\n\tif (PlayerPtr == this) {\n\t\tMap.Abandon_Production(type, fptr->ID);\n\n\t\tif (type == RTTI_BUILDINGTYPE || type == RTTI_BUILDING) {\n\t\t\tMap.PendingObjectPtr = 0;\n\t\t\tMap.PendingObject = 0;\n\t\t\tMap.PendingHouse = HOUSE_NONE;\n\t\t\tMap.Set_Cursor_Shape(0);\n\t\t}\n\t}\n\n\t/*\n\t**\tAbandon production of the object.\n\t*/\n\tfptr->Abandon();\n\tSet_Factory(type, NULL);\n\tdelete fptr;\n\n\treturn(PROD_OK);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Special_Weapon_AI -- Fires special weapon.                                      *\n *                                                                                             *\n *    This routine will pick a good target to fire the special weapon specified.               *\n *                                                                                             *\n * INPUT:   id -- The special weapon id to fire.                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/24/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Special_Weapon_AI(SpecialWeaponType id)\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t** Loop through all of the building objects on the map\n\t** and see which ones are available.\n \t*/\n\tBuildingClass * bestptr = NULL;\n\tint best = -1;\n\n\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\tBuildingClass * b = Buildings.Ptr(index);\n\n\t\t/*\n\t\t** If the building is valid, not in limbo, not in the process of\n\t\t** being destroyed and not our ally, then we can consider it.\n\t\t*/\n\t\tif (b != NULL && !b->IsInLimbo && b->Strength && !Is_Ally(b)) {\n\t\t\tif (Percent_Chance(90) && (b->Value() > best || best == -1)) {\n\t\t\t\tbest = b->Value();\n\t\t\t\tbestptr = b;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (bestptr) {\n\t\tCELL cell = Coord_Cell(bestptr->Center_Coord());\n\t\tPlace_Special_Blast(id, cell);\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Place_Special_Blast -- Place a special blast effect at location specified.      *\n *                                                                                             *\n *    This routine will create a blast effect at the cell specified. This is the result of     *\n *    the special weapons.                                                                     *\n *                                                                                             *\n * INPUT:   id    -- The special weapon id number.                                             *\n *                                                                                             *\n *          cell  -- The location where the special weapon attack is to occur.                 *\n *                                                                                             *\n * OUTPUT:  Was the special weapon successfully fired at the location specified?               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : commented.                                                               *\n *   07/25/1995 JLB : Added scatter effect for nuclear bomb.                                   *\n *   07/28/1995 JLB : Revamped to use super weapon class controller.                           *\n *=============================================================================================*/\nbool HouseClass::Place_Special_Blast(SpecialWeaponType id, CELL cell)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tBuildingClass * launchsite = 0;\n\tAnimClass * anim = 0;\n\tswitch (id) {\n\t\tcase SPC_SONAR_PULSE:\n\t\t\t// Automatically discharge the sonar pulse and uncloak all subs.\n\t\t\tif (SuperWeapon[SPC_SONAR_PULSE].Is_Ready()) {\n\t\t\t\tSuperWeapon[SPC_SONAR_PULSE].Discharged(this == PlayerPtr);\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t\tMap.Activate_Pulse();\n\t\t\t\t}\n\t\t\t\tSound_Effect(VOC_SONAR);\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t\tfor (int index = 0; index < Vessels.Count(); index++) {\n\t\t\t\t\tVesselClass * sub = Vessels.Ptr(index);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\tif (*sub == VESSEL_SS || *sub == VESSEL_MISSILESUB) {\n#else\n\t\t\t\t\tif (*sub == VESSEL_SS) {\n#endif\n\t\t\t\t\t\tsub->PulseCountDown = 15 * TICKS_PER_SECOND;\n\t\t\t\t\t\tsub->Do_Uncloak();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase SPC_NUCLEAR_BOMB:\n\t\t\tif (SuperWeapon[SPC_NUCLEAR_BOMB].Is_Ready()) {\n\t\t\t\tif (SuperWeapon[SPC_NUCLEAR_BOMB].Is_One_Time()) {\n\t\t\t\t\tBulletClass * bullet = new BulletClass(BULLET_NUKE_DOWN, ::As_Target(cell), 0, 200, WARHEAD_NUKE, MPH_VERY_FAST);\n\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\tint celly = Cell_Y(cell);\n\t\t\t\t\t\tcelly -= 15;\n\t\t\t\t\t\tif (celly < 1) celly = 1;\n\t\t\t\t\t\tCOORDINATE start = Cell_Coord(XY_Cell(Cell_X(cell), celly));\n\t\t\t\t\t\tif (!bullet->Unlimbo(start, DIR_S)) {\n\t\t\t\t\t\t\tdelete bullet;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSuperWeapon[SPC_NUCLEAR_BOMB].Discharged(this == PlayerPtr);\n\t\t\t\t\t\tIsRecalcNeeded = true;\n\t\t\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSearch for a suitable launch site for this missile.\n\t\t\t\t\t*/\n\t\t\t\t\tlaunchsite = Find_Building(STRUCT_MSLO);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf a launch site was found, then proceed with the normal launch\n\t\t\t\t\t**\tsequence.\n\t\t\t\t\t*/\n\t\t\t\t\tif (launchsite) {\n\t\t\t\t\t\tlaunchsite->Assign_Mission(MISSION_MISSILE);\n\t\t\t\t\t\tlaunchsite->Commence();\n\t\t\t\t\t\tNukeDest = cell;\n\t\t\t\t\t}\n\t\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t\t}\n\t\t\t\t\tSuperWeapon[SPC_NUCLEAR_BOMB].Discharged(this == PlayerPtr);\n\t\t\t\t\tIsRecalcNeeded = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase SPC_PARA_INFANTRY:\n\t\t\tif (SuperWeapon[SPC_PARA_INFANTRY].Is_Ready()) {\n\n\t\t\t\tTeamTypeClass * ttype = TeamTypeClass::As_Pointer(\"@PINF\");\n\t\t\t\tif (ttype == NULL) {\n\t\t\t\t\tttype = new TeamTypeClass;\n\t\t\t\t\tif (ttype != NULL) {\n\t\t\t\t\t\tstrcpy(ttype->IniName, \"@PINF\");\n\t\t\t\t\t\tttype->IsTransient = true;\n\t\t\t\t\t\tttype->IsPrebuilt = false;\n\t\t\t\t\t\tttype->IsReinforcable = false;\n\t\t\t\t\t\tttype->Origin = WAYPT_SPECIAL;\n\t\t\t\t\t\tttype->MissionCount = 1;\n\t\t\t\t\t\tttype->MissionList[0].Mission = TMISSION_ATT_WAYPT;\n\t\t\t\t\t\tttype->MissionList[0].Data.Value = WAYPT_SPECIAL;\n\t\t\t\t\t\tttype->ClassCount = 2;\n\t\t\t\t\t\tttype->Members[0].Quantity = AircraftTypeClass::As_Reference(AIRCRAFT_BADGER).Max_Passengers();\n\t\t\t\t\t\tttype->Members[0].Class = &InfantryTypeClass::As_Reference(INFANTRY_E1);\n\t\t\t\t\t\tttype->Members[1].Quantity = 1;\n\t\t\t\t\t\tttype->Members[1].Class = &AircraftTypeClass::As_Reference(AIRCRAFT_BADGER);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (ttype != NULL) {\n\t\t\t\t\tttype->House = Class->House;\n\t\t\t\t\tScen.Waypoint[WAYPT_SPECIAL] = Map.Nearby_Location(cell, SPEED_FOOT);\n\t\t\t\t\tDo_Reinforcements(ttype);\n\t\t\t\t}\n\n//\t\t\t\tCreate_Air_Reinforcement(this, AIRCRAFT_BADGER, 1, MISSION_HUNT, ::As_Target(cell), TARGET_NONE, INFANTRY_E1);\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t}\n\t\t\t\tSuperWeapon[SPC_PARA_INFANTRY].Discharged(this == PlayerPtr);\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase SPC_SPY_MISSION:\n\t\t\tif (SuperWeapon[SPC_SPY_MISSION].Is_Ready()) {\n\t\t\t\tCreate_Air_Reinforcement(this, AIRCRAFT_U2, 1, MISSION_HUNT, ::As_Target(cell), ::As_Target(cell));\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t}\n\t\t\t\tSuperWeapon[SPC_SPY_MISSION].Discharged(this == PlayerPtr);\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase SPC_PARA_BOMB:\n\t\t\tif (SuperWeapon[SPC_PARA_BOMB].Is_Ready()) {\n\t\t\t\tCreate_Air_Reinforcement(this, AIRCRAFT_BADGER, Rule.BadgerBombCount, MISSION_HUNT, ::As_Target(cell), TARGET_NONE);\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t}\n\t\t\t\tSuperWeapon[SPC_PARA_BOMB].Discharged(this == PlayerPtr);\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase SPC_IRON_CURTAIN:\n\t\t\tif (SuperWeapon[SPC_IRON_CURTAIN].Is_Ready()) {\n\t\t\t\tint x = Keyboard->MouseQX - Map.TacPixelX;\n\t\t\t\tint y = Keyboard->MouseQY - Map.TacPixelY;\n\t\t\t\tTechnoClass * tech = Map[cell].Cell_Techno(x, y);\n\t\t\t\tif (tech) {\n\t\t\t\t\tswitch (tech->What_Am_I()) {\n\t\t\t\t\t\tcase RTTI_UNIT:\n\t\t\t\t\t\tcase RTTI_BUILDING:\n\t\t\t\t\t\tcase RTTI_VESSEL:\n\t\t\t\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\t\t\t\ttech->IronCurtainCountDown = Rule.IronCurtainDuration * TICKS_PER_MINUTE;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\t\tif (tech->What_Am_I() == RTTI_UNIT && *(UnitClass *)tech == UNIT_DEMOTRUCK) {\n\t\t\t\t\t\t\t\ttech->IronCurtainCountDown = Rule.IronCurtainDuration * TICKS_PER_SECOND;\n\t\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\t\ttech->Mark(MARK_CHANGE);\n\t\t\t\t\t\t\tSound_Effect(VOC_IRON1, tech->Center_Coord());\n\t\t\t\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tSuperWeapon[SPC_IRON_CURTAIN].Discharged(this == PlayerPtr);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase SPC_CHRONOSPHERE:\n\t\t\tif (SuperWeapon[SPC_CHRONOSPHERE].Is_Ready()) {\n\t\t\t\tint x = Keyboard->MouseQX - Map.TacPixelX;\n\t\t\t\tint y = Keyboard->MouseQY - Map.TacPixelY;\n\t\t\t\tTechnoClass * tech = Map[cell].Cell_Techno(x, y);\n\t\t\t\tif (tech && Is_Ally(tech)) {\n\t\t\t\t\tif (tech->What_Am_I() == RTTI_UNIT ||\n\t\t\t\t\t\ttech->What_Am_I() == RTTI_INFANTRY ||\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\t(tech->What_Am_I() == RTTI_VESSEL && (*((VesselClass *)tech) != VESSEL_TRANSPORT && *((VesselClass *)tech) != VESSEL_CARRIER) )) {\n#else\n\t\t\t\t\t\t(tech->What_Am_I() == RTTI_VESSEL && *((VesselClass *)tech) != VESSEL_TRANSPORT)) {\n#endif\n\n\t\t\t\t\t\tif (tech->What_Am_I() != RTTI_UNIT || !((UnitClass *)tech)->IsDeploying) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tbool porthim = true;\n\tif(tech->What_Am_I() == RTTI_UNIT && ((UnitClass *)tech)->Class->Type == UNIT_CHRONOTANK) {\n\t\tporthim = false;\n\t}\n\tif (porthim) {\n#endif\n\t\t\t\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\t\t\t\tMap.IsTargettingMode = SPC_CHRONO2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tUnitToTeleport = tech->As_Target();\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t}\n#endif\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase SPC_CHRONO2:\n\t\t\t{\n\t\t\t\tTechnoClass * tech = (TechnoClass *)::As_Object(UnitToTeleport);\n\t\t\t\tCELL oldcell = cell;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif (tech != NULL && tech->IsActive && tech->Is_Foot() && tech->What_Am_I() != RTTI_AIRCRAFT) {\n#else\n\t\t\t\tif (tech != NULL && tech->Is_Foot() && tech->What_Am_I() != RTTI_AIRCRAFT) {\n#endif\n\t\t\t\t\t/*\n\t\t\t\t\t** Destroy any infantryman that gets teleported\n\t\t\t\t\t*/\n\t\t\t\t\tif (tech->What_Am_I() == RTTI_INFANTRY) {\n\t\t\t\t\t\tInfantryClass * inf = (InfantryClass *)tech;\n\t\t\t\t\t\tinf->Mark(MARK_UP);\n\t\t\t\t\t\tinf->Coord = Cell_Coord(cell);\n\t\t\t\t\t\tinf->Mark(MARK_DOWN);\n\t\t\t\t\t\tint damage = inf->Strength;\n\t\t\t\t\t\tinf->Take_Damage(damage, 0, WARHEAD_FIRE, 0, true);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t} else if(tech->What_Am_I() == RTTI_UNIT && *(UnitClass *)tech == UNIT_DEMOTRUCK) {\n\t\t\t\t\t\ttech->Assign_Target(tech->As_Target());\n#endif\n\t\t\t\t\t} else {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tWarp the unit to the new location.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tDriveClass * drive = (DriveClass *)tech;\n\t\t\t\t\t\tdrive->MoebiusCell = Coord_Cell(drive->Coord);\n\t\t\t\t\t\toldcell = drive->MoebiusCell;\n\t\t\t\t\t\tdrive->Teleport_To(cell);\n\t\t\t\t\t\tdrive->IsMoebius = true;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif(tech->What_Am_I() == RTTI_UNIT && *(UnitClass *)tech == UNIT_CHRONOTANK) {\n\t\tdrive->IsMoebius = false;\n\t}\n\tdrive->MoebiusCountDown = Rule.ChronoDuration * TICKS_PER_MINUTE;\n\tif (tech->What_Am_I() == RTTI_UNIT && *(UnitClass *)tech == UNIT_CHRONOTANK) {\n\t\tdrive->MoebiusCountDown = ChronoTankDuration * TICKS_PER_MINUTE;\n\t}\n#else\n\t\t\t\t\t\tdrive->MoebiusCountDown = Rule.ChronoDuration * TICKS_PER_MINUTE;\n#endif\n\t\t\t\t\t\tScen.Do_BW_Fade();\n\t\t\t\t\t\tSound_Effect(VOC_CHRONO, drive->Coord);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tUnitToTeleport = TARGET_NONE;\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif(tech && tech->IsActive && (tech->What_Am_I() != RTTI_UNIT || *(UnitClass *)tech != UNIT_CHRONOTANK)) {\n#endif\n\t\t\t\tSuperWeapon[SPC_CHRONOSPHERE].Discharged(this == PlayerPtr);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t}\n#endif\n\t\t\t\tIsRecalcNeeded = true;\n\n\t\t\t\t/*\n\t\t\t\t** Now set a percentage chance that a time quake will occur.\n\t\t\t\t*/\n\t\t\t\tif (!TimeQuake) {\n\t\t\t\t\tTimeQuake = Percent_Chance(Rule.QuakeChance * 100);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Now set a percentage chance that a chronal vortex will appear. It\n\t\t\t\t**\tmight appear where the object teleported to or it might appear\n\t\t\t\t**\twhere it teleported from -- random chance.\n\t\t\t\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// Don't allow a vortex if the teleportation was due to a chrono tank.\n\tif(tech && tech->IsActive && (tech->What_Am_I() != RTTI_UNIT || *(UnitClass *)tech != UNIT_CHRONOTANK))\n#endif\n\t\t\t\tif (!ChronalVortex.Is_Active() && Percent_Chance(Rule.VortexChance * 100)) {\n\t\t\t\t\tint x = Random_Pick(0, Map.MapCellWidth-1);\n\t\t\t\t\tint y = Random_Pick(0, Map.MapCellHeight-1);\n\t\t\t\t\tChronalVortex.Appear(XY_Cell(Map.MapCellX + x, Map.MapCellY + y));\n\n//\t\t\t\t\tif (Percent_Chance(50)) {\n//\t\t\t\t\t\tChronalVortex.Appear(Cell_Coord(oldcell));\n//\t\t\t\t\t} else {\n//\t\t\t\t\t\tChronalVortex.Appear(Cell_Coord(cell));\n//\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Place_Object -- Places the object (building) at location specified.             *\n *                                                                                             *\n *    This routine is called when a building has been produced and now must be placed on       *\n *    the map. When the player clicks on the map, this routine is ultimately called when the   *\n *    event passes through the event queue system.                                             *\n *                                                                                             *\n * INPUT:   type  -- The object type to place. The actual object is lifted from the sidebar.   *\n *                                                                                             *\n *                                                                                             *\n *          cell  -- The location to place the object on the map.                              *\n *                                                                                             *\n * OUTPUT:  Was the placement successful?                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Place_Object(RTTIType type, CELL cell)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tTechnoClass * tech = 0;\n\tFactoryClass * factory = Fetch_Factory(type);\n\n\t/*\n\t**\tOnly if there is a factory active for this type, can it be \"placed\".\n\t**\tIn the case of a missing factory, then this request is completely bogus --\n\t**\tignore it. This might occur if, between two events to exit the same\n\t**\tobject, the mouse was clicked on the sidebar to start building again.\n\t**\tThe second placement event should NOT try to place the object that is\n\t**\tjust starting construction.\n\t*/\n\tif (factory && factory->Has_Completed()) {\n\t\ttech = factory->Get_Object();\n\n\t\tif (cell == -1) {\n\t\t\tTechnoClass * pending = factory->Get_Object();\n\t\t\tif (pending != NULL) {\n\n#ifdef FIXIT_HELI_LANDING\n\t\t\t\t/*\n\t\t\t\t**\tTry to find a place for the object to appear from. For helicopters, it has the\n\t\t\t\t**\toption of finding a nearby helipad if no helipads are free.\n\t\t\t\t*/\n\t\t\t\tTechnoClass * builder = pending->Who_Can_Build_Me(false, false);\n\t\t\t\tif (builder == NULL && pending->What_Am_I() == RTTI_AIRCRAFT && !((AircraftClass *)pending)->Class->IsFixedWing) {\n\t\t\t\t\tbuilder = pending->Who_Can_Build_Me(true, false);\n\n\t\t\t\t}\n#else\n\t\t\t\tbool intheory = false;\n\t\t\t\tif (pending->What_Am_I() == RTTI_AIRCRAFT) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** BG hack - helicopters don't need a specific building to\n\t\t\t\t\t** emerge from, in fact, they'll land next to a building if\n\t\t\t\t\t** need be.\n\t\t\t\t\t*/\n\t\t\t\t\tif( !((AircraftClass *)pending)->Class->IsFixedWing) {\n\t\t\t\t\t\tintheory = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tTechnoClass * builder = pending->Who_Can_Build_Me(intheory, false);\n#endif\n\n\t\t\t\tif (builder != NULL && builder->Exit_Object(pending)) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSince the object has left the factory under its own power, delete\n\t\t\t\t\t**\tthe production manager tied to this slot in the sidebar. Its job\n\t\t\t\t\t**\thas been completed.\n\t\t\t\t\t*/\n\t\t\t\t\tfactory->Completed();\n\t\t\t\t\tAbandon_Production(type);\n\t\t\t\t\tswitch (pending->What_Am_I()) {\n\t\t\t\t\t\tcase RTTI_UNIT:\n\t\t\t\t\t\t\tJustBuiltUnit = ((UnitClass*)pending)->Class->Type;\n\t\t\t\t\t\t\tIsBuiltSomething = true;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase RTTI_VESSEL:\n\t\t\t\t\t\t\tJustBuiltVessel = ((VesselClass*)pending)->Class->Type;\n\t\t\t\t\t\t\tIsBuiltSomething = true;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t\t\t\tJustBuiltInfantry = ((InfantryClass*)pending)->Class->Type;\n\t\t\t\t\t\t\tIsBuiltSomething = true;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase RTTI_BUILDING:\n\t\t\t\t\t\t\tJustBuiltStructure = ((BuildingClass*)pending)->Class->Type;\n\t\t\t\t\t\t\tIsBuiltSomething = true;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\t\t\t\tJustBuiltAircraft = ((AircraftClass*)pending)->Class->Type;\n\t\t\t\t\t\t\tIsBuiltSomething = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThe object could not leave under it's own power. Just wait\n\t\t\t\t\t**\tuntil the player tries to place the object again.\n\t\t\t\t\t*/\n\t\t\t\t\treturn(false);\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tif (tech) {\n\t\t\t\tTechnoClass * builder = tech->Who_Can_Build_Me(false, false);\n\t\t\t\tif (builder) {\n\n\t\t\t\t\tbuilder->Transmit_Message(RADIO_HELLO, tech);\n\t\t\t\t\tif (tech->Unlimbo(Cell_Coord(cell))) {\n\t\t\t\t\t\tfactory->Completed();\n\t\t\t\t\t\tAbandon_Production(type);\n\n\t\t\t\t\t\tif (PlayerPtr == this) {\n\t\t\t\t\t\t\tSound_Effect(VOC_PLACE_BUILDING_DOWN);\n\t\t\t\t\t\t\tMap.Set_Cursor_Shape(0);\n\t\t\t\t\t\t\tMap.PendingObjectPtr = 0;\n\t\t\t\t\t\t\tMap.PendingObject = 0;\n\t\t\t\t\t\t\tMap.PendingHouse = HOUSE_NONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(true);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\t\t\tSpeak(VOX_DEPLOY);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbuilder->Transmit_Message(RADIO_OVER_OUT);\n\t\t\t\t}\n\t\t\t\treturn(false);\n\n\t\t\t} else {\n\n\t\t\t\t// Play a bad sound here?\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Manual_Place -- Inform display system of building placement mode.               *\n *                                                                                             *\n *    This routine will inform the display system that building placement mode has begun.      *\n *    The cursor will be created that matches the layout of the building shape.                *\n *                                                                                             *\n * INPUT:   builder  -- The factory that is building this object.                              *\n *                                                                                             *\n *          object   -- The building that is going to be placed down on the map.               *\n *                                                                                             *\n * OUTPUT:  Was the building placement mode successfully initiated?                            *\n *                                                                                             *\n * WARNINGS:   This merely adjusts the cursor shape. Nothing that affects networked games      *\n *             is affected.                                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/04/1995 JLB : Created.                                                                 *\n *   05/30/1995 JLB : Uses the Bib_And_Offset() function to determine bib size.                *\n *=============================================================================================*/\nbool HouseClass::Manual_Place(BuildingClass * builder,  BuildingClass * object)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (this == PlayerPtr && !Map.PendingObject && builder && object) {\n\t\t/*\n\t\t**\tEnsures that object selection doesn't remain when\n\t\t**\tbuilding placement takes place.\n\t\t*/\n\t\tUnselect_All();\n\n\t\tMap.Repair_Mode_Control(0);\n\t\tMap.Sell_Mode_Control(0);\n\n\t\tMap.PendingObject = object->Class;\n\t\tMap.PendingObjectPtr = object;\n\t\tMap.PendingHouse = Class->House;\n\n\t\tMap.Set_Cursor_Shape(object->Occupy_List(true));\n\t\tMap.Set_Cursor_Pos(Coord_Cell(builder->Coord));\n\t\tbuilder->Mark(MARK_CHANGE);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***************************************************************************\n * HouseClass::Clobber_All -- removes all objects for this house\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      This routine removes the house itself, so the multiplayer code\t\t*\n *\t\t  must not rely on there being \"empty\" houses lying around.\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1995 BRR : Created.                                             *\n *   06/09/1995 JLB : Handles aircraft.                                    *\n *=========================================================================*/\nvoid HouseClass::Clobber_All(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tint i;\n\n\tfor (i = 0; i < ::Aircraft.Count(); i++) {\n\t\tif (::Aircraft.Ptr(i)->House == this) {\n\t\t\tdelete ::Aircraft.Ptr(i);\n\t\t\ti--;\n\t\t}\n\t}\n\tfor (i = 0; i < ::Units.Count(); i++) {\n\t\tif (::Units.Ptr(i)->House == this) {\n\t\t\tdelete ::Units.Ptr(i);\n\t\t\ti--;\n\t\t}\n\t}\n\tfor (i = 0; i < ::Vessels.Count(); i++) {\n\t\tif (::Vessels.Ptr(i)->House == this) {\n\t\t\tdelete ::Vessels.Ptr(i);\n\t\t\ti--;\n\t\t}\n\t}\n\tfor (i = 0; i < Infantry.Count(); i++) {\n\t\tif (Infantry.Ptr(i)->House == this) {\n\t\t\tdelete Infantry.Ptr(i);\n\t\t\ti--;\n\t\t}\n\t}\n\tfor (i = 0; i < Buildings.Count(); i++) {\n\t\tif (Buildings.Ptr(i)->House == this) {\n\t\t\tdelete Buildings.Ptr(i);\n\t\t\ti--;\n\t\t}\n\t}\n\tfor (i = 0; i < TeamTypes.Count(); i++) {\n\t\tif (TeamTypes.Ptr(i)->House == Class->House) {\n\t\t\tdelete TeamTypes.Ptr(i);\n\t\t\ti--;\n\t\t}\n\t}\n\tfor (i = 0; i < Triggers.Count(); i++) {\n\t\tif (Triggers.Ptr(i)->Class->House == Class->House) {\n\t\t\tdelete Triggers.Ptr(i);\n\t\t\ti--;\n\t\t}\n\t}\n\tfor (i = 0; i < TriggerTypes.Count(); i++) {\n\t\tif (TriggerTypes.Ptr(i)->House == Class->House) {\n\t\t\tdelete TriggerTypes.Ptr(i);\n\t\t\ti--;\n\t\t}\n\t}\n\n\tdelete this;\n}\n\n\n/***********************************************************************************************\n * HouseClass::Detach -- Removes specified object from house tracking systems.                 *\n *                                                                                             *\n *    This routine is called when an object is to be removed from the game system. If the      *\n *    specified object is part of the house tracking system, then it will be removed.          *\n *                                                                                             *\n * INPUT:   target   -- The target value of the object that is to be removed from the game.    *\n *                                                                                             *\n *          all      -- Is the target going away for good as opposed to just cloaking/hiding?  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : commented                                                                *\n *=============================================================================================*/\nvoid HouseClass::Detach(TARGET target, bool )\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (ToCapture == target) {\n\t\tToCapture = TARGET_NONE;\n\t}\n\n\tif (Is_Target_Trigger(target)) {\n\t\tHouseTriggers[ID].Delete(As_Trigger(target));\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Does_Enemy_Building_Exist -- Checks for enemy building of specified type.       *\n *                                                                                             *\n *    This routine will examine the enemy houses and if there is a building owned by one       *\n *    of those house, true will be returned.                                                   *\n *                                                                                             *\n * INPUT:   btype -- The building type to check for.                                           *\n *                                                                                             *\n * OUTPUT:  Does a building of the specified type exist for one of the enemy houses?           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Does_Enemy_Building_Exist(StructType btype) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tint bflag = 1L << btype;\n\tfor (HousesType index = HOUSE_FIRST; index < HOUSE_COUNT; index++) {\n\t\tHouseClass * house = HouseClass::As_Pointer(index);\n\n\t\tif (house && !Is_Ally(house) && (house->ActiveBScan & bflag) != 0) {\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Suggest_New_Object -- Determine what would the next buildable object be.        *\n *                                                                                             *\n *    This routine will examine the house status and return with a techno type pointer to      *\n *    the object type that it thinks should be created. The type is restricted to match the    *\n *    type specified. Typical use of this routine is by computer controlled factories.         *\n *                                                                                             *\n * INPUT:   objecttype  -- The type of object to restrict the scan for.                        *\n *                                                                                             *\n *          kennel      -- Is this from a kennel? There are special hacks to ensure that only  *\n *                         dogs can be produced from a kennel.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a techno type for the object type that should be         *\n *          created. If no object should be created, then NULL is returned.                    *\n *                                                                                             *\n * WARNINGS:   This is a time consuming routine. Only call when necessary.                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTechnoTypeClass const * HouseClass::Suggest_New_Object(RTTIType objecttype, bool kennel) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tTechnoTypeClass const * techno = NULL;\n\n\tswitch (objecttype) {\n\t\tcase RTTI_AIRCRAFT:\n\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\tif (BuildAircraft != AIRCRAFT_NONE) {\n\t\t\t\treturn(&AircraftTypeClass::As_Reference(BuildAircraft));\n\t\t\t}\n\t\t\treturn(NULL);\n\n\t\tcase RTTI_VESSEL:\n\t\tcase RTTI_VESSELTYPE:\n\t\t\tif (BuildVessel != VESSEL_NONE) {\n\t\t\t\treturn(&VesselTypeClass::As_Reference(BuildVessel));\n\t\t\t}\n\t\t\treturn(NULL);\n\n\t\t/*\n\t\t**\tUnit construction is based on the rule that up to twice the number required\n\t\t**\tto fill all teams will be created.\n\t\t*/\n\t\tcase RTTI_UNIT:\n\t\tcase RTTI_UNITTYPE:\n\t\t\tif (BuildUnit != UNIT_NONE) {\n\t\t\t\treturn(&UnitTypeClass::As_Reference(BuildUnit));\n\t\t\t}\n\t\t\treturn(NULL);\n\n\t\t/*\n\t\t**\tInfantry construction is based on the rule that up to twice the number required\n\t\t**\tto fill all teams will be created.\n\t\t*/\n\t\tcase RTTI_INFANTRY:\n\t\tcase RTTI_INFANTRYTYPE:\n\t\t\tif (BuildInfantry != INFANTRY_NONE) {\n\t\t\t\tif (kennel && BuildInfantry != INFANTRY_DOG) return(NULL);\n\t\t\t\tif (!kennel && BuildInfantry == INFANTRY_DOG) return(NULL);\n\t\t\t\treturn(&InfantryTypeClass::As_Reference(BuildInfantry));\n\t\t\t}\n\t\t\treturn(NULL);\n\n\t\t/*\n\t\t**\tBuilding construction is based upon the preconstruction list.\n\t\t*/\n\t\tcase RTTI_BUILDING:\n\t\tcase RTTI_BUILDINGTYPE:\n\t\t\tif (BuildStructure != STRUCT_NONE) {\n\t\t\t\treturn(&BuildingTypeClass::As_Reference(BuildStructure));\n\t\t\t}\n\t\t\treturn(NULL);\n\t}\n\treturn(techno);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Flag_Remove -- Removes the flag from the specified target.                      *\n *                                                                                             *\n *    This routine will remove the flag attached to the specified target object or cell.       *\n *    Call this routine before placing the object down. This is called inherently by the       *\n *    the Flag_Attach() functions.                                                             *\n *                                                                                             *\n * INPUT:   target   -- The target that the flag was attached to but will be removed from.     *\n *                                                                                             *\n *          set_home -- if true, clears the flag's waypoint designation                        *\n *                                                                                             *\n * OUTPUT:  Was the flag successfully removed from the specified target?                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Flag_Remove(TARGET target, bool set_home)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tint rc;\n\n\tif (Target_Legal(target)) {\n\n\t\t/*\n\t\t**\tRemove the flag from a unit\n\t\t*/\n\t\tUnitClass * object = As_Unit(target);\n\t\tif (object) {\n\t\t\trc = object->Flag_Remove();\n\t\t\tif (rc && FlagLocation == target) {\n\t\t\t\tFlagLocation = TARGET_NONE;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tRemove the flag from a cell\n\t\t\t*/\n\t\t\tCELL cell = As_Cell(target);\n\t\t\tif (Map.In_Radar(cell)) {\n\t\t\t\trc = Map[cell].Flag_Remove();\n\t\t\t\tif (rc && FlagLocation == target) {\n\t\t\t\t\tFlagLocation = TARGET_NONE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tHandle the flag home cell:\n\t\t**\tIf 'set_home' is set, clear the home value & the cell's overlay\n\t\t*/\n\t\tif (set_home) {\n\t\t\tif (FlagHome != 0) {\n\t\t\t\tMap[FlagHome].Overlay = OVERLAY_NONE;\n\t\t\t\tMap.Flag_Cell(FlagHome);\n\t\t\t\tFlagHome = 0;\n\t\t\t}\n\t\t}\n\n\t\treturn(rc);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Flag_Attach -- Attach flag to specified cell (or thereabouts).                  *\n *                                                                                             *\n *    This routine will attach the house flag to the location specified. If the location       *\n *    cannot contain the flag, then a suitable nearby location will be selected.               *\n *                                                                                             *\n * INPUT:   cell  -- The desired cell location to place the flag.                              *\n *                                                                                             *\n *          set_home -- if true, resets the flag's waypoint designation                        *\n *                                                                                             *\n * OUTPUT:  Was the flag successfully placed?                                                  *\n *                                                                                             *\n * WARNINGS:   The cell picked for the flag might very likely not be the cell requested.       *\n *             Check the FlagLocation value to determine the final cell resting spot.          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *   10/08/1996 JLB : Uses map nearby cell scanning handler.                                   *\n *=============================================================================================*/\nbool HouseClass::Flag_Attach(CELL cell, bool set_home)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tbool rc;\n\tbool clockwise;\n\n\t/*\n\t**\tRandomly decide if we're going to search cells clockwise or counter-\n\t**\tclockwise\n\t*/\n\tclockwise = Percent_Chance(50);\n\n\t/*\n\t**\tOnly continue if this cell is a legal placement cell.\n\t*/\n\tif (Map.In_Radar(cell)) {\n\n\t\t/*\n\t\t**\tIf the flag already exists, then it must be removed from the object\n\t\t**\tit is attached to.\n\t\t*/\n\t\tFlag_Remove(FlagLocation, set_home);\n\n\t\t/*\n\t\t**\tAttach the flag to the cell specified. If it can't be placed, then pick\n\t\t**\ta nearby cell where it can be placed.\n\t\t*/\n\t\tCELL newcell = cell;\n\t\trc = Map[newcell].Flag_Place(Class->House);\n\t\tif (!rc) {\n\t\t\tnewcell = Map.Nearby_Location(cell, SPEED_TRACK);\n\t\t\tif (newcell != 0) {\n\t\t\t\trc = Map[newcell].Flag_Place(Class->House);\n\t\t\t}\n\n#ifdef OBSOLETE\n\t\t\t/*\n\t\t\t**\tLoop for increasing distance from the desired cell.\n\t\t\t**\tFor each distance, randomly pick a starting direction.  Between\n\t\t\t**\tthis and the clockwise/counterclockwise random value, the flag\n\t\t\t**\tshould appear to be placed fairly randomly.\n\t\t\t*/\n\t\t\tfor (int dist = 1; dist < 32; dist++) {\n\t\t\t\tFacingType fcounter;\n\t\t\t\tFacingType rot;\n\n\t\t\t\t/*\n\t\t\t\t**\tClockwise search.\n\t\t\t\t*/\n\t\t\t\tif (clockwise) {\n\t\t\t\t\trot = Random_Pick(FACING_N, FACING_NW);\n\t\t\t\t\tfor (fcounter = FACING_N; fcounter <= FACING_NW; fcounter++) {\n\t\t\t\t\t\tnewcell = Coord_Cell(Coord_Move(Cell_Coord(cell), Facing_Dir(rot), dist*256));\n\t\t\t\t\t\tif (Map.In_Radar(newcell) && Map[newcell].Flag_Place(Class->House)) {\n\t\t\t\t\t\t\tdist = 32;\n\t\t\t\t\t\t\trc = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\trot++;\n\t\t\t\t\t\tif (rot > FACING_NW) rot = FACING_N;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCounter-clockwise search\n\t\t\t\t\t*/\n\t\t\t\t\trot = Random_Pick(FACING_N, FACING_NW);\n\t\t\t\t\tfor (fcounter = FACING_NW; fcounter >= FACING_N; fcounter--) {\n\t\t\t\t\t\tnewcell = Coord_Cell(Coord_Move(Cell_Coord(cell), Facing_Dir(rot), dist*256));\n\t\t\t\t\t\tif (Map.In_Radar(newcell) && Map[newcell].Flag_Place(Class->House)) {\n\t\t\t\t\t\t\tdist = 32;\n\t\t\t\t\t\t\trc = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\trot--;\n\t\t\t\t\t\tif (rot < FACING_N)\n\t\t\t\t\t\t\trot = FACING_NW;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n#endif\n\t\t}\n\n\t\t/*\n\t\t**\tIf we've found a spot for the flag, place the flag at the new cell.\n\t\t**\tif 'set_home' is set, OR this house has no current flag home cell,\n\t\t**\tmark that cell as this house's flag home cell.\n\t\t*/\n\t\tif (rc) {\n\t\t\tFlagLocation = As_Target(newcell);\n\n\t\t\tif (set_home || FlagHome == 0) {\n\t\t\t\tMap[newcell].Overlay = OVERLAY_FLAG_SPOT;\n\t\t\t\tMap[newcell].OverlayData = 0;\n\t\t\t\tMap[newcell].Recalc_Attributes();\n\t\t\t\tFlagHome = newcell;\n\t\t\t}\n\t\t}\n\n\t\treturn(rc);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Flag_Attach -- Attaches the house flag the specified unit.                      *\n *                                                                                             *\n *    This routine will attach the house flag to the specified unit. This routine is called    *\n *    when a unit drives over a cell containing a flag.                                        *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that the house flag is to be attached to.        *\n *                                                                                             *\n *          set_home -- if true, clears the flag's waypoint designation                        *\n *                                                                                             *\n * OUTPUT:  Was the flag attached successfully?                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Flag_Attach(UnitClass * object, bool set_home)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (object && !object->IsInLimbo) {\n\t\tFlag_Remove(FlagLocation, set_home);\n\n\t\t/*\n\t\t**\tAttach the flag to the object.\n\t\t*/\n\t\tobject->Flag_Attach(Class->House);\n\t\tFlagLocation = object->As_Target();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***************************************************************************\n * HouseClass::MPlayer_Defeated -- multiplayer; house is defeated          *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/25/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid HouseClass::MPlayer_Defeated(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tchar txt[80];\n\tint i,j;\n\tunsigned char id;\n\tHouseClass * hptr;\n\tHouseClass * hptr2;\n\tint num_alive;\n\tint num_humans;\n\tint all_allies;\n\n\t/*\n\t**\tSet the defeat flag for this house\n\t*/\n\tIsDefeated = true;\n\n\t/*\n\t**\tIf this is a computer controlled house, then all computer controlled\n\t**\thouses become paranoid.\n\t*/\n\tif (IQ == Rule.MaxIQ && !IsHuman && Rule.IsComputerParanoid) {\n\t\tComputer_Paranoid();\n\t}\n\n\t/*\n\t**\tRemove this house's flag & flag home cell\n\t*/\n\tif (Special.IsCaptureTheFlag) {\n\t\tif (FlagLocation) {\n\t\t\tFlag_Remove(FlagLocation, true);\n\t\t} else {\n\t\t\tif (FlagHome != 0) {\n\t\t\t\tFlag_Remove(FlagHome, true);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf this is me:\n\t**\t- Set MPlayerObiWan, so I can only send messages to all players, and\n\t**\t  not just one (so I can't be obnoxiously omnipotent)\n\t**\t- Reveal the map\n\t**\t- Add my defeat message\n\t*/\n\tif (PlayerPtr == this) {\n\t\tSession.ObiWan = 1;\n\t\tDebug_Unshroud = true;\n\t\tHidPage.Clear();\n\t\tMap.Flag_To_Redraw(true);\n\n\t\t/*\n\t\t**\tPop up a message showing that I was defeated\n\t\t*/\n\t\tsprintf(txt, Text_String(TXT_PLAYER_DEFEATED), IniName);\n\t\tSession.Messages.Add_Message(NULL, 0, txt, Session.ColorIdx,\n\t\t\tTPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\tMap.Flag_To_Redraw(false);\n\n\t} else {\n\n\t\t/*\n\t\t**\tIf it wasn't me, find out who was defeated\n\t\t*/\n\t\tif (IsHuman) {\n\t\t\tsprintf (txt, Text_String(TXT_PLAYER_DEFEATED), IniName);\n\n\t\t\tSession.Messages.Add_Message(NULL, 0, txt, RemapColor,\n\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\t\tMap.Flag_To_Redraw(false);\n\t\t\tRedrawOptionsMenu = true;\n\t\t}\n\t}\n\n\t/*\n\t**\tFind out how many players are left alive.\n\t*/\n\tnum_alive = 0;\n\tnum_humans = 0;\n\tfor (i = 0; i < Session.MaxPlayers; i++) {\n\t\thptr = HouseClass::As_Pointer((HousesType)(HOUSE_MULTI1 + i));\n\t\tif (hptr && !hptr->IsDefeated) {\n\t\t\tif (hptr->IsHuman) {\n\t\t\t\tnum_humans++;\n\t\t\t}\n\t\t\tnum_alive++;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf all the houses left alive are allied with each other, then in reality\n\t**\tthere's only one player left:\n\t*/\n\tall_allies = 1;\n\tfor (i = 0; i < Session.MaxPlayers; i++) {\n\n\t\t/*\n\t\t**\tGet a pointer to this house\n\t\t*/\n\t\thptr = HouseClass::As_Pointer((HousesType)(HOUSE_MULTI1 + i));\n\t\tif (!hptr || hptr->IsDefeated)\n\t\t\tcontinue;\n\n\t\t/*\n\t\t**\tLoop through all houses; if there's one left alive that this house\n\t\t**\tisn't allied with, then all_allies will be false\n\t\t*/\n\t\tfor (j = 0; j < Session.MaxPlayers; j++) {\n\t\t\thptr2 = HouseClass::As_Pointer((HousesType)(HOUSE_MULTI1 + j));\n\t\t\tif (!hptr2) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!hptr2->IsDefeated && !hptr->Is_Ally(hptr2)) {\n\t\t\t\tall_allies = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!all_allies) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf all houses left are allies, set 'num_alive' to 1; game over.\n\t*/\n\tif (all_allies) {\n\t\tnum_alive = 1;\n\t}\n\n\t/*\n\t**\tIf there's only one human player left or no humans left, the game is over:\n\t**\t- Determine whether this player wins or loses, based on the state of the\n\t**\t  player's IsDefeated flag\n\t**\t- Find all players' indices in the Session.Score array\n\t**\t- Tally up scores for this game\n\t*/\n\tif (num_alive == 1 || num_humans == 0) {\n\t\tif (PlayerPtr->IsDefeated) {\n\t\t\tPlayerLoses = true;\n\t\t} else {\n\t\t\tPlayerWins = true;\n\t\t}\n\n\t\t/*\n\t\t** Add up the scores\n\t\t*/\n\t\tTally_Score();\n\n\t\t/*\n\t\t**\tDestroy all the IPX connections, since we have to go through the rest\n\t\t**\tof the Main_Loop() before we detect that the game is over, and we'll\n\t\t**\tend up waiting for frame sync packets from the other machines.\n\t\t*/\n\t\tif (Session.Type==GAME_IPX || Session.Type == GAME_INTERNET) {\n\t\t\ti = 0;\n\t\t\twhile (Ipx.Num_Connections() && (i++ < 1000) ) {\n\t\t\t\tid = Ipx.Connection_ID(0);\n\t\t\t\tIpx.Delete_Connection(id);\n\t\t\t}\n\t\t\tSession.NumPlayers = 0;\n\t\t}\n\n#if(TEN)\n\t\t//\n\t\t// Tell the TEN server who won\n\t\t//\n\t\tif (Session.Type == GAME_TEN) {\n\t\t\tSend_TEN_Win_Packet();\n\t\t}\n#endif\t// TEN\n\n#if(MPATH)\n\t\t//\n\t\t// Tell the MPATH server who won\n\t\t//\n\t\tif (Session.Type == GAME_MPATH) {\n\t\t\tFILE *fp;\n\n\t\t\tfp = fopen(\"winner.txt\",\"wt\");\n\t\t\tif (fp) {\n\t\t\t\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\t\t\t\thptr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\t\t\t\tif (!hptr->IsDefeated) {\n\t\t\t\t\t\tfprintf(fp,\"%s\\n\",hptr->IniName);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfclose(fp);\n\t\t\t}\n\t\t}\n#endif\t// MPATH\n\n\t}\n\n\t/*\n\t**\tBe sure our messages get displayed, even if we're about to exit.\n\t*/\n\tMap.Render();\n}\n\n\n/***************************************************************************\n * HouseClass::Tally_Score -- Fills in the score system for this round     *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid HouseClass::Tally_Score(void)\n{\n\tHousesType house;\n\tHousesType house2;\n\tHouseClass * hptr;\n\tint score_index;\n\tint i,j,k;\n\tint max_index;\n\tint max_count;\n\tint count;\n\n\t/*\n\t** Loop through all houses, tallying up each player's score\n\t*/\n\tfor (house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\thptr = HouseClass::As_Pointer(house);\n\t\t/*\n\t\t** Skip this house if it's not human.\n\t\t*/\n\t\tif (!hptr || !hptr->IsHuman) {\n\t\t\tcontinue;\n\t\t}\n\t\t/*\n\t\t** Now find out where this player is in the score array\n\t\t*/\n\t\tscore_index = -1;\n\t\tfor (i = 0; i < Session.NumScores; i++) {\n\t\t\tif (!stricmp(hptr->IniName, Session.Score[i].Name)) {\n\t\t\t\tscore_index = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf the index is still -1, the name wasn't found; add a new entry.\n\t\t*/\n\t\tif (score_index == -1) {\n\t\t\t/*\n\t\t\t** Just add this player to the end of the array, if there's room\n\t\t\t*/\n\t\t\tif (Session.NumScores < MAX_MULTI_NAMES) {\n\t\t\t\tscore_index = Session.NumScores;\n\t\t\t\tSession.NumScores++;\n\t\t\t}\n\t\t\t/*\n\t\t\t** If there's not room, we have to remove somebody.\n\t\t\t**\tFor each player in the scores array, count the # of '-1' entries\n\t\t\t**\tfrom this game backwards; the one with the most is the one that\n\t\t\t**\thasn't played the longest; replace him with this new guy.\n\t\t\t*/\n\t\t\telse {\n\t\t\t\tmax_index = 0;\n\t\t\t\tmax_count = 0;\n\t\t\t\tfor (j = 0; j < Session.NumScores; j++) {\n\t\t\t\t\tcount = 0;\n\t\t\t\t\tfor (k = Session.NumScores - 1; k >= 0; k--) {\n\t\t\t\t\t\tif (Session.Score[j].Kills[k]==-1) {\n\t\t\t\t\t\t\tcount++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (count > max_count) {\n\t\t\t\t\t\tmax_count = count;\n\t\t\t\t\t\tmax_index = j;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tscore_index = max_index;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tInitialize this new score entry\n\t\t\t*/\n\t\t\tSession.Score[score_index].Wins = 0;\n\t\t\tstrcpy (Session.Score[score_index].Name, hptr->IniName);\n\t\t\tfor (j = 0; j < MAX_MULTI_GAMES; j++)\n\t\t\t\tSession.Score[score_index].Kills[j] = -1;\n\t\t}\n\n\t\t/*\n\t\t**\tInit this player's Kills to 0 (-1 means he didn't play this round;\n\t\t**\t0 means he played but got no kills).\n\t\t*/\n\t\tSession.Score[score_index].Kills[Session.CurGame] = 0;\n\n\t\t/*\n\t\t**\tInit this player's color to his last-used color index\n\t\t*/\n\t\tSession.Score[score_index].Color = hptr->RemapColor;\n\n\t\t/*\n\t\t**\tIf this house was undefeated, it must have been the winner.\n\t\t** (If no human houses are undefeated, the computer won.)\n\t\t*/\n\t\tif (!hptr->IsDefeated) {\n\t\t\tSession.Score[score_index].Wins++;\n\t\t\tSession.Winner = score_index;\n\t\t}\n\n\t\t/*\n\t\t**\tTally up all kills for this player\n\t\t*/\n\t\tfor (house2 = HOUSE_FIRST; house2 < HOUSE_COUNT; house2++) {\n\t\t\tSession.Score[score_index].Kills[Session.CurGame] += hptr->UnitsKilled[house2];\n\t\t\tSession.Score[score_index].Kills[Session.CurGame] += hptr->BuildingsKilled[house2];\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * HouseClass::Blowup_All -- blows up everything                           *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1995 BRR : Created.                                             *\n *   06/09/1995 JLB : Handles aircraft.                                    *\n *   05/07/1996 JLB : Handles ships.                                       *\n *=========================================================================*/\nvoid HouseClass::Blowup_All(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tint i;\n\tint damage;\n\tUnitClass * uptr;\n\tInfantryClass * iptr;\n\tBuildingClass * bptr;\n\tint count;\n\tWarheadType warhead;\n\n\t/*\n\t**\tFind everything owned by this house & blast it with a huge amount of damage\n\t**\tat zero range.  Do units before infantry, so the units' drivers are killed\n\t**\ttoo.  Using Explosion_Damage is like dropping a big bomb right on the\n\t**\tobject; it will also damage anything around it.\n\t*/\n\tfor (i = 0; i < ::Units.Count(); i++) {\n\t\tif (::Units.Ptr(i)->House == this && !::Units.Ptr(i)->IsInLimbo) {\n\t\t\tuptr = ::Units.Ptr(i);\n\n\t\t\t/*\n\t\t\t**\tSome units can't be killed with one shot, so keep damaging them until\n\t\t\t**\tthey're gone.  The unit will destroy itself, and put an infantry in\n\t\t\t**\tits place.  When the unit destroys itself, decrement 'i' since\n\t\t\t**\tits pointer will be removed from the active pointer list.\n\t\t\t*/\n\t\t\tcount = 0;\n\t\t\twhile (::Units.Ptr(i)==uptr && uptr->Strength) {\n\t\t\t\tdamage = uptr->Strength;\n\t\t\t\tuptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);\n\t\t\t\tcount++;\n\t\t\t\tif (count > 5 && uptr->IsActive) {\n\t\t\t\t\tdelete uptr;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\ti--;\n\t\t}\n\t}\n\n\t/*\n\t**\tDestroy all aircraft owned by this house.\n\t*/\n\tfor (i = 0; i < ::Aircraft.Count(); i++) {\n\t\tif (::Aircraft.Ptr(i)->House == this && !::Aircraft.Ptr(i)->IsInLimbo) {\n\t\t\tAircraftClass * aptr = ::Aircraft.Ptr(i);\n\n\t\t\tdamage = aptr->Strength;\n\t\t\taptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);\n\t\t\tif (!aptr->IsActive) {\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tDestroy all vessels owned by this house.\n\t*/\n\tfor (i = 0; i < ::Vessels.Count(); i++) {\n\t\tif (::Vessels.Ptr(i)->House == this && !::Vessels.Ptr(i)->IsInLimbo) {\n\t\t\tVesselClass * vptr = ::Vessels.Ptr(i);\n\n\t\t\tdamage = vptr->Strength;\n\t\t\tvptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);\n\t\t\tif (!vptr->IsActive) {\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tBuildings don't delete themselves when they die; they shake the screen\n\t**\tand begin a countdown, so don't decrement 'i' when it's destroyed.\n\t*/\n\tfor (i = 0; i < Buildings.Count(); i++) {\n\t\tif (Buildings.Ptr(i)->House == this && !Buildings.Ptr(i)->IsInLimbo) {\n\t\t\tbptr = Buildings.Ptr(i);\n\n\t\t\tcount = 0;\n\t\t\twhile (Buildings.Ptr(i)==bptr && bptr->Strength) {\n\t\t\t\tdamage = bptr->Strength;\n\t\t\t\tbptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);\n\t\t\t\tcount++;\n\t\t\t\tif (count > 5) {\n\t\t\t\t\tdelete bptr;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tInfantry don't delete themselves when they die; they go into a death-\n\t**\tanimation sequence, so there's no need to decrement 'i' when they die.\n\t**\tInfantry should die by different types of warheads, so their death\n\t**\tanims aren't all synchronized.\n\t*/\n\tfor (i = 0; i < Infantry.Count(); i++) {\n\t\tif (Infantry.Ptr(i)->House == this && !Infantry.Ptr(i)->IsInLimbo) {\n\t\t\tiptr = Infantry.Ptr(i);\n\n\t\t\tcount = 0;\n\t\t\twhile (Infantry.Ptr(i)==iptr && iptr->Strength) {\n\t\t\t\tdamage = iptr->Strength;\n\t\t\t\twarhead = Random_Pick(WARHEAD_SA, WARHEAD_FIRE);\n\t\t\t\tiptr->Take_Damage(damage, 0, warhead, NULL, true);\n\n\t\t\t\tcount++;\n\t\t\t\tif (count > 5) {\n\t\t\t\t\tdelete iptr;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Flag_To_Die -- Flags the house to blow up soon.                                 *\n *                                                                                             *\n *    When this routine is called, the house will blow up after a period of time. Typically    *\n *    this is called when the flag is captured or the HQ destroyed.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the house flagged to blow up?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Flag_To_Die(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (!IsToWin && !IsToDie && !IsToLose) {\n\t\tIsToDie = true;\n\t\tBorrowedTime = TICKS_PER_MINUTE * Rule.SavourDelay;\n\t}\n\treturn(IsToDie);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Flag_To_Win -- Flags the house to win soon.                                     *\n *                                                                                             *\n *    When this routine is called, the house will be declared the winner after a period of     *\n *    time.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the house flagged to win?                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Flag_To_Win(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (!IsToWin && !IsToDie && !IsToLose) {\n\t\tIsToWin = true;\n\t\tBorrowedTime = TICKS_PER_MINUTE * Rule.SavourDelay;\n\t}\n\treturn(IsToWin);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Flag_To_Lose -- Flags the house to die soon.                                    *\n *                                                                                             *\n *    When this routine is called, it will spell the doom of this house. In a short while      *\n *    all of the object owned by this house will explode. Typical use of this routine is when  *\n *    the flag has been captured or the command vehicle has been destroyed.                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Has the doom been initiated?                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/12/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Flag_To_Lose(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tIsToWin = false;\n\tif (!IsToDie && !IsToLose) {\n\t\tIsToLose = true;\n\t\tBorrowedTime = TICKS_PER_MINUTE * Rule.SavourDelay;\n\t}\n\treturn(IsToLose);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Init_Data -- Initializes the multiplayer color data.                            *\n *                                                                                             *\n *    This routine is called when initializing the color and remap data for this house. The    *\n *    primary user of this routine is the multiplayer version of the game, especially for\t\t  *\n *    saving & loading multiplayer games.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:   color    -- The color of this house.                                               *\n *                                                                                             *\n *          house    -- The house that this should act like.                                   *\n *                                                                                             *\n *          credits  -- The initial credits to assign to this house.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Init_Data(PlayerColorType color, HousesType house, int credits)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tCredits = Control.InitialCredits = credits;\n\tRemapColor = color;\n\tActLike = house;\n}\n\n\n/***********************************************************************************************\n * HouseClass::Power_Fraction -- Fetches the current power output rating.                      *\n *                                                                                             *\n *    Use this routine to fetch the current power output as a fixed point fraction. The        *\n *    value 0x0100 is 100% power.                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with power rating as a fixed pointer number.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed HouseClass::Power_Fraction(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (Power >= Drain || Drain == 0) return(1);\n\n\tif (Power) {\n\t\treturn(fixed(Power, Drain));\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Sell_Wall -- Tries to sell the wall at the specified location.                  *\n *                                                                                             *\n *    This routine will try to sell the wall at the specified location. If there is a wall     *\n *    present and it is owned by this house, then it can be sold.                              *\n *                                                                                             *\n * INPUT:   cell  -- The cell that wall selling is desired.                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1995 JLB : Created.                                                                 *\n *   11/02/1996 JLB : Checks unsellable bit for wall type.                                     *\n *=============================================================================================*/\nvoid HouseClass::Sell_Wall(CELL cell)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif ((unsigned)cell > 0) {\n\t\tOverlayType overlay = Map[cell].Overlay;\n\n\t\tif (overlay != OVERLAY_NONE && Map[cell].Owner == Class->House) {\n\t\t\tOverlayTypeClass const & optr = OverlayTypeClass::As_Reference(overlay);\n\n\t\t\tif (optr.IsWall) {\n\t\t\t\tBuildingTypeClass const * btype = NULL;\n\t\t\t\tswitch (overlay) {\n\t\t\t\t\tcase OVERLAY_SANDBAG_WALL:\n\t\t\t\t\t\tbtype = &BuildingTypeClass::As_Reference(STRUCT_SANDBAG_WALL);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase OVERLAY_CYCLONE_WALL:\n\t\t\t\t\t\tbtype = &BuildingTypeClass::As_Reference(STRUCT_CYCLONE_WALL);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase OVERLAY_BRICK_WALL:\n\t\t\t\t\t\tbtype = &BuildingTypeClass::As_Reference(STRUCT_BRICK_WALL);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase OVERLAY_BARBWIRE_WALL:\n\t\t\t\t\t\tbtype = &BuildingTypeClass::As_Reference(STRUCT_BARBWIRE_WALL);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase OVERLAY_WOOD_WALL:\n\t\t\t\t\t\tbtype = &BuildingTypeClass::As_Reference(STRUCT_WOOD_WALL);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase OVERLAY_FENCE:\n\t\t\t\t\t\tbtype = &BuildingTypeClass::As_Reference(STRUCT_FENCE);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (btype != NULL && !btype->IsUnsellable) {\n\n\t\t\t\t\tif (PlayerPtr == this) {\n\t\t\t\t\t\tSound_Effect(VOC_CASHTURN);\n\t\t\t\t\t}\n\n\t\t\t\t\tRefund_Money(btype->Raw_Cost() * Rule.RefundPercent);\n\t\t\t\t\tMap[cell].Overlay = OVERLAY_NONE;\n\t\t\t\t\tMap[cell].OverlayData = 0;\n\t\t\t\t\tMap[cell].Owner = HOUSE_NONE;\n\t\t\t\t\tMap[cell].Wall_Update();\n\t\t\t\t\tMap[cell].Recalc_Attributes();\n\t\t\t\t\tMap[cell].Redraw_Objects();\n\t\t\t\t\tMap.Radar_Pixel(cell);\n\t\t\t\t\tDetach_This_From_All(::As_Target(cell), true);\n\n\t\t\t\t\tif (optr.IsCrushable) {\n\t\t\t\t\t\tMap.Zone_Reset(MZONEF_NORMAL);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMap.Zone_Reset(MZONEF_CRUSHER|MZONEF_NORMAL);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Suggest_New_Building -- Examines the situation and suggests a building.         *\n *                                                                                             *\n *    This routine is called when a construction yard needs to know what to build next. It     *\n *    will either examine the prebuilt base list or try to figure out what to build next       *\n *    based on the current game situation.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the building type class to build.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuildingTypeClass const * HouseClass::Suggest_New_Building(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (BuildStructure != STRUCT_NONE) {\n\t\treturn(&BuildingTypeClass::As_Reference(BuildStructure));\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Find_Building -- Finds a building of specified type.                            *\n *                                                                                             *\n *    This routine is used to find a building of the specified type. This is particularly      *\n *    useful for when some event requires a specific building instance. The nuclear missile    *\n *    launch is a good example.                                                                *\n *                                                                                             *\n * INPUT:   type  -- The building type to scan for.                                            *\n *                                                                                             *\n *          zone  -- The zone that the building must be located in. If no zone specific search *\n *                   is desired, then pass ZONE_NONE.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the building type requested. If there is no building     *\n *          of the type requested, then NULL is returned.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/27/1995 JLB : Created.                                                                 *\n *   10/02/1995 JLB : Allows for zone specifics.                                               *\n *=============================================================================================*/\nBuildingClass * HouseClass::Find_Building(StructType type, ZoneType zone) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tOnly scan if we KNOW there is at least one building of the type\n\t**\trequested.\n\t*/\n\tif (BQuantity[type] > 0) {\n\n\t\t/*\n\t\t**\tSearch for a suitable launch site for this missile.\n\t\t*/\n\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass * b = Buildings.Ptr(index);\n\t\t\tif (b && !b->IsInLimbo && b->House == this && *b == type) {\n\t\t\t\tif (zone == ZONE_NONE || Which_Zone(b) == zone) {\n\t\t\t\t\treturn(b);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Find_Build_Location -- Finds a suitable building location.                      *\n *                                                                                             *\n *    This routine is used to find a suitable building location for the building specified.    *\n *    The auto base building logic uses this when building the base for the computer.          *\n *                                                                                             *\n * INPUT:   building -- Pointer to the building that needs to be placed down.                  *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate to place the building at. If there are no suitable     *\n *          locations, then NULL is returned.                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE HouseClass::Find_Build_Location(BuildingClass * building) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tint zonerating[ZONE_COUNT];\n\tstruct {\n\t\tint AntiAir;\t\t\t// Average air defense for the base.\n\t\tint AntiArmor;\t\t\t// Average armor defense for the base.\n\t\tint AntiInfantry;\t\t// Average infantry defense for the base.\n\t} zoneinfo = {0,0,0};\n\tint antiair = building->Anti_Air();\n\tint antiarmor = building->Anti_Armor();\n\tint antiinfantry = building->Anti_Infantry();\n\tbool adj = true;\n\n\t/*\n\t**\tNever place combat buildings adjacent to each other. This is partly\n\t**\tbecause combat buildings don't have a bib and jamming will occur as well\n\t**\tas because spacing defensive buildings out will yield a better\n\t**\tdefense.\n\t*/\n\tif (antiair || antiarmor || antiinfantry) {\n\t\tadj = false;\n\t}\n\n\t/*\n\t**\tDetermine the average zone strengths for the base. This value is\n\t**\tused to determine what zones are considered under or over strength.\n\t*/\n\tfor (ZoneType z = ZONE_NORTH; z < ZONE_COUNT; z++) {\n\t\tzoneinfo.AntiAir += ZoneInfo[z].AirDefense;\n\t\tzoneinfo.AntiArmor += ZoneInfo[z].ArmorDefense;\n\t\tzoneinfo.AntiInfantry += ZoneInfo[z].InfantryDefense;\n\t}\n\tzoneinfo.AntiAir /= ZONE_COUNT-ZONE_NORTH;\n\tzoneinfo.AntiArmor /= ZONE_COUNT-ZONE_NORTH;\n\tzoneinfo.AntiInfantry /= ZONE_COUNT-ZONE_NORTH;\n\n\t/*\n\t**\tGive each zone a rating for value. The higher the value the more desirable\n\t**\tto place the specified building in that zone. Factor the average value of\n\t**\tzone defense such that more weight is given to zones that are very under\n\t**\tdefended.\n\t*/\n\tmemset(&zonerating[0], '\\0', sizeof(zonerating));\n\tfor (z = ZONE_FIRST; z < ZONE_COUNT; z++) {\n\t\tint diff;\n\n\t\tdiff = zoneinfo.AntiAir-ZoneInfo[z].AirDefense;\n\t\tif (z == ZONE_CORE) diff /= 2;\n\t\tif (diff > 0) {\n\t\t\tzonerating[z] += min(antiair, diff);\n\t\t}\n\n\t\tdiff = zoneinfo.AntiArmor-ZoneInfo[z].ArmorDefense;\n\t\tif (z == ZONE_CORE) diff /= 2;\n\t\tif (diff > 0) {\n\t\t\tzonerating[z] += min(antiarmor, diff);\n\t\t}\n\n\t\tdiff = zoneinfo.AntiInfantry-ZoneInfo[z].InfantryDefense;\n\t\tif (z == ZONE_CORE) diff /= 2;\n\t\tif (diff > 0) {\n\t\t\tzonerating[z] += min(antiinfantry, diff);\n\t\t}\n\t}\n\n\t/*\n\t**\tNow that each zone has been given a desirability rating, find the zone\n\t**\twith the greatest value and try to place the building in that zone.\n\t*/\n\tZoneType zone = Random_Pick(ZONE_FIRST, ZONE_WEST);\n\tint largest = 0;\n\tfor (z = ZONE_FIRST; z < ZONE_COUNT; z++) {\n\t\tif (zonerating[z] > largest) {\n\t\t\tzone = z;\n\t\t\tlargest = zonerating[z];\n\t\t}\n\t}\n\n\tCELL zcell = Find_Cell_In_Zone(building, zone);\n\tif (zcell) {\n\t\treturn(Cell_Coord(zcell));\n\t}\n\n\t/*\n\t**\tCould not build in preferred zone, so try building in any zone.\n\t*/\n\tstatic ZoneType _zones[] = {ZONE_CORE, ZONE_NORTH, ZONE_SOUTH, ZONE_EAST, ZONE_WEST};\n\tint start = Random_Pick(0, ARRAY_SIZE(_zones)-1);\n\tfor (int zz = 0; zz < ARRAY_SIZE(_zones); zz++) {\n\t\tZoneType tryzone = _zones[(zz + start) % ARRAY_SIZE(_zones)];\n\t\tzcell = Find_Cell_In_Zone(building, tryzone);\n\t\tif (zcell) return(zcell);\n\t}\n\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Recalc_Center -- Recalculates the center point of the base.                     *\n *                                                                                             *\n *    This routine will average the location of the base and record the center point. The      *\n *    recorded center point is used to determine such things as how far the base is spread     *\n *    out and where to protect the most. This routine should be called whenever a building     *\n *    is created or destroyed.                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Recalc_Center(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tFirst presume that there is no base. If there is a base, then these values will be\n\t**\tproperly filled in below.\n\t*/\n\tCenter = 0;\n\tRadius = 0;\n\tfor (ZoneType zone = ZONE_FIRST; zone < ZONE_COUNT; zone++) {\n\t\tZoneInfo[zone].AirDefense = 0;\n\t\tZoneInfo[zone].ArmorDefense = 0;\n\t\tZoneInfo[zone].InfantryDefense = 0;\n\t}\n\n\t/*\n\t**\tOnly process the center base size/position calculation if there are buildings to\n\t**\tconsider. When no buildings for this house are present, then no processing need\n\t**\toccur.\n\t*/\n\tif (CurBuildings > 0) {\n\t\tint x = 0;\n\t\tint y = 0;\n\t\tint count = 0;\n\n\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass const * b = Buildings.Ptr(index);\n\n\t\t\tif (b != NULL && !b->IsInLimbo && (HouseClass *)b->House == this && b->Strength > 0) {\n\n\t\t\t\t/*\n\t\t\t\t**\tGive more \"weight\" to buildings that cost more. The presumption is that cheap\n\t\t\t\t**\tbuildings don't affect the base disposition as much as the more expensive\n\t\t\t\t**\tbuildings do.\n\t\t\t\t*/\n\t\t\t\tint weight = (b->Class->Cost_Of() / 1000)+1;\n\t\t\t\tfor (int i = 0; i < weight; i++) {\n\t\t\t\t\tx += Coord_X(b->Center_Coord());\n\t\t\t\t\ty += Coord_Y(b->Center_Coord());\n\t\t\t\t\tcount++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tThis second check for quantity of buildings is necessary because the first\n\t\t**\tcheck against CurBuildings doesn't take into account if the building is in\n\t\t**\tlimbo, but for base calculation, the limbo state disqualifies a building\n\t\t**\tfrom being processed. Thus, CurBuildings may indicate a base, but count may\n\t\t**\tnot match.\n\t\t*/\n\t\tif (count > 0) {\n\t\t\tx /= count;\n\t\t\ty /= count;\n\n#ifdef NEVER\n\t\t\t/*\n\t\t\t**\tBias the center of the base away from the edges of the map.\n\t\t\t*/\n\t\t\tLEPTON left = Cell_To_Lepton(Map.MapCellX + 10);\n\t\t\tLEPTON top = Cell_To_Lepton(Map.MapCellY + 10);\n\t\t\tLEPTON right = Cell_To_Lepton(Map.MapCellX + Map.MapCellWidth - 10);\n\t\t\tLEPTON bottom = Cell_To_Lepton(Map.MapCellY + Map.MapCellHeight - 10);\n\t\t\tif (x < left) x = left;\n\t\t\tif (x > right) x = right;\n\t\t\tif (y < top) y = top;\n\t\t\tif (y > bottom) y = bottom;\n#endif\n\n\t\t\tCenter = XY_Coord(x, y);\n\t\t}\n\n\t\t/*\n\t\t**\tIf there were any buildings discovered as legal to consider as part of the base,\n\t\t**\tthen figure out the general average radius of the building disposition as it\n\t\t**\trelates to the center of the base.\n\t\t*/\n\t\tif (count > 1) {\n\t\t\tint radius = 0;\n\n\t\t\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\t\t\tBuildingClass const * b = Buildings.Ptr(index);\n\n\t\t\t\tif (b != NULL && !b->IsInLimbo && (HouseClass *)b->House == this && b->Strength > 0) {\n\t\t\t\t\tradius += Distance(Center, b->Center_Coord());\n\t\t\t\t}\n\t\t\t}\n\t\t\tRadius = max(radius / count, 2 * CELL_LEPTON_W);\n\n\t\t\t/*\n\t\t\t**\tDetermine the relative strength of each base defense zone.\n\t\t\t*/\n\t\t\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\t\t\tBuildingClass const * b = Buildings.Ptr(index);\n\n\t\t\t\tif (b != NULL && !b->IsInLimbo && (HouseClass *)b->House == this && b->Strength > 0) {\n\t\t\t\t\tZoneType z = Which_Zone(b);\n\n\t\t\t\t\tif (z != ZONE_NONE) {\n\t\t\t\t\t\tZoneInfo[z].ArmorDefense += b->Anti_Armor();\n\t\t\t\t\t\tZoneInfo[z].AirDefense += b->Anti_Air();\n\t\t\t\t\t\tZoneInfo[z].InfantryDefense += b->Anti_Infantry();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tRadius = 0x0200;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Expert_AI -- Handles expert AI processing.                                      *\n *                                                                                             *\n *    This routine is called when the computer should perform expert AI processing. This       *\n *    method of AI is categorized as an \"Expert System\" process.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the number of game frames to delay before calling this routine again.      *\n *                                                                                             *\n * WARNINGS:   This is relatively time consuming -- call periodically.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint HouseClass::Expert_AI(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tBuildingClass * b = 0;\n\tbool stop = false;\n\tint time = TICKS_PER_SECOND * 10;\n\n\t/*\n\t**\tIf the current enemy no longer has a base or is defeated, then don't consider\n\t**\tthat house a threat anymore. Clear out the enemy record and then try\n\t**\tto find a new enemy.\n\t*/\n\tif (Enemy != HOUSE_NONE) {\n\t\tHouseClass * h = HouseClass::As_Pointer(Enemy);\n\n\t\tif (h == NULL || !h->IsActive || h->IsDefeated || Is_Ally(h) || h->BScan == 0) {\n\t\t\tEnemy = HOUSE_NONE;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is no enemy assigned to this house, then assign one now. The\n\t**\tenemy that is closest is picked. However, don't pick an enemy if the\n\t**\tbase has not been established yet.\n\t*/\n\tif (ActiveBScan && Center && Attack == 0) {\n\t\tint close = 0;\n\t\tHousesType enemy = HOUSE_NONE;\n\t\tint maxunit = 0;\n\t\tint maxinfantry = 0;\n\t\tint maxvessel = 0;\n\t\tint maxaircraft = 0;\n\t\tint maxbuilding = 0;\n\t\tint enemycount = 0;\n\n\t\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\t\tHouseClass * h = HouseClass::As_Pointer(house);\n\t\t\tif (h != NULL && h->IsActive && !h->IsDefeated && !Is_Ally(h)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tPerform a special restriction check to ensure that no enemy is chosen if\n\t\t\t\t**\tthere is even one enemy that has not established a base yet. This will\n\t\t\t\t**\tensure an accurate first pick for enemy since the distance to base\n\t\t\t\t**\tvalue can be determined.\n\t\t\t\t*/\n\t\t\t\tif (!h->IsStarted) {\n\t\t\t\t\tenemy = HOUSE_NONE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tKeep track of the number of buildings and units owned by the\n\t\t\t\t**\tenemy. This is used to bring up the maximum allowed to match.\n\t\t\t\t*/\n\t\t\t\tmaxunit += h->CurUnits;\n\t\t\t\tmaxbuilding += h->CurBuildings;\n\t\t\t\tmaxinfantry += h->CurInfantry;\n\t\t\t\tmaxvessel += h->CurVessels;\n\t\t\t\tmaxaircraft += h->CurAircraft;\n\t\t\t\tenemycount++;\n\n\t\t\t\t/*\n\t\t\t\t**\tDetermine a priority value based on distance to the center of the\n\t\t\t\t**\tcandidate base. The higher the value, the better the candidate house\n\t\t\t\t**\tis to becoming the preferred enemy for this house.\n\t\t\t\t*/\n\t\t\t\tint value = ((MAP_CELL_W*2)-Distance(Center, h->Center));\n\t\t\t\tvalue *= 2;\n\n\t\t\t\t/*\n\t\t\t\t**\tIn addition to distance, record the number of kills directed\n\t\t\t\t**\tagainst this house. The enemy that does more damage might be\n\t\t\t\t**\tconsidered a greater threat.\n\t\t\t\t*/\n\t\t\t\tvalue += h->BuildingsKilled[Class->House]*5;\n\t\t\t\tvalue += h->UnitsKilled[Class->House];\n\n\t\t\t\t/*\n\t\t\t\t**\tFactor in the relative sizes of the bases. An enemy that has a\n\t\t\t\t**\tlarger base will be considered a bigger threat. Conversely, a\n\t\t\t\t**\tsmaller base is considered a lesser threat.\n\t\t\t\t*/\n\t\t\t\tvalue += h->CurUnits - CurUnits;\n\t\t\t\tvalue += h->CurBuildings - CurBuildings;\n\t\t\t\tvalue += (h->CurInfantry - CurInfantry)/4;\n\n\t\t\t\t/*\n\t\t\t\t**\tWhoever last attacked is given a little more priority as\n\t\t\t\t**\ta potential designated enemy.\n\t\t\t\t*/\n\t\t\t\tif (house == LAEnemy) {\n\t\t\t\t\tvalue += 100;\n\t\t\t\t}\n\n#ifdef OBSOLETE\n\t\t\t\t/*\n\t\t\t\t**\tHuman players are a given preference as the target.\n\t\t\t\t*/\n\t\t\t\tif (h->IsHuman) {\n\t\t\t\t\tvalue *= 2;\n\t\t\t\t}\n#endif\n\n\t\t\t\t/*\n\t\t\t\t**\tCompare the calculated value for this candidate house and if it is\n\t\t\t\t**\tgreater than the previously recorded maximum, record this house as\n\t\t\t\t**\tthe prime candidate for enemy.\n\t\t\t\t*/\n\t\t\t\tif (value > close) {\n\t\t\t\t\tenemy = house;\n\t\t\t\t\tclose = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tRecord this closest enemy base as the first enemy to attack.\n\t\t*/\n\t\tEnemy = enemy;\n\n\t\t/*\n\t\t**\tUp the maximum allowed units and buildings to match a rough average\n\t\t**\tof what the enemies are allowed.\n\t\t*/\n\t\tif (enemycount) {\n\t\t\tmaxunit /= enemycount;\n\t\t\tmaxbuilding /= enemycount;\n\t\t\tmaxinfantry /= enemycount;\n\t\t\tmaxvessel /= enemycount;\n\t\t\tmaxaircraft /= enemycount;\n\t\t}\n\n\t\tif (Control.MaxBuilding < maxbuilding + 10) {\n\t\t\tControl.MaxBuilding = maxbuilding + 10;\n\t\t}\n\t\tif (Control.MaxUnit < maxunit + 10) {\n\t\t\tControl.MaxUnit = maxunit + 10;\n\t\t}\n\t\tif (Control.MaxInfantry < maxinfantry + 10) {\n\t\t\tControl.MaxInfantry = maxinfantry + 10;\n\t\t}\n\t\tif (Control.MaxVessel < maxvessel + 10) {\n\t\t\tControl.MaxVessel = maxvessel + 10;\n\t\t}\n\t\tif (Control.MaxAircraft < maxaircraft + 10) {\n\t\t\tControl.MaxAircraft = maxaircraft + 10;\n\t\t}\n\t}\n\n\t/*\n\t**\tHouse state transition check occurs here. Transitions that occur here are ones\n\t**\tthat relate to general base condition rather than specific combat events.\n\t**\tTypically, this is limited to transitions between normal buildup mode and\n\t**\tbroke mode.\n\t*/\n\tif (State == STATE_ENDGAME) {\n\t\tFire_Sale();\n\t\tDo_All_To_Hunt();\n\t} else {\n\t\tif (State == STATE_BUILDUP) {\n\t\t\tif (Available_Money() < 25) {\n\t\t\t\tState = STATE_BROKE;\n\t\t\t}\n\t\t}\n\t\tif (State == STATE_BROKE) {\n\t\t\tif (Available_Money() >= 25) {\n\t\t\t\tState = STATE_BUILDUP;\n\t\t\t}\n\t\t}\n\t\tif (State == STATE_ATTACKED && LATime + TICKS_PER_MINUTE < Frame) {\n\t\t\tState = STATE_BUILDUP;\n\t\t}\n\t\tif (State != STATE_ATTACKED && LATime + TICKS_PER_MINUTE > Frame) {\n\t\t\tState = STATE_ATTACKED;\n\t\t}\n\t}\n\n\t/*\n\t**\tRecords the urgency of all actions possible.\n\t*/\n\tUrgencyType urgency[STRATEGY_COUNT];\n\n\tfor (StrategyType strat = STRATEGY_FIRST; strat < STRATEGY_COUNT; strat++) {\n\t\turgency[strat] = URGENCY_NONE;\n\n\t\tswitch (strat) {\n\t\t\tcase STRATEGY_BUILD_POWER:\n\t\t\t\turgency[strat] = Check_Build_Power();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_BUILD_DEFENSE:\n\t\t\t\turgency[strat] = Check_Build_Defense();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_BUILD_INCOME:\n\t\t\t\turgency[strat] = Check_Build_Income();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_FIRE_SALE:\n\t\t\t\turgency[strat] = Check_Fire_Sale();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_BUILD_ENGINEER:\n\t\t\t\turgency[strat] = Check_Build_Engineer();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_BUILD_OFFENSE:\n\t\t\t\turgency[strat] = Check_Build_Offense();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_RAISE_MONEY:\n\t\t\t\turgency[strat] = Check_Raise_Money();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_RAISE_POWER:\n\t\t\t\turgency[strat] = Check_Raise_Power();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_LOWER_POWER:\n\t\t\t\turgency[strat] = Check_Lower_Power();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_ATTACK:\n\t\t\t\turgency[strat] = Check_Attack();\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\turgency[strat] = URGENCY_NONE;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tPerforms the action required for each of the strategies that share\n\t**\tthe most urgent category. Stop processing if any strategy at the\n\t**\thighest urgency performed any action. This is because higher urgency\n\t**\tactions tend to greatly affect the lower urgency actions.\n\t*/\n\tfor (UrgencyType u = URGENCY_CRITICAL; u >= URGENCY_LOW; u--) {\n\t\tbool acted = false;\n\n\t\tfor (strat = STRATEGY_FIRST; strat < STRATEGY_COUNT; strat++) {\n\t\t\tif (urgency[strat] == u) {\n\t\t\t\tswitch (strat) {\n\t\t\t\t\tcase STRATEGY_BUILD_POWER:\n\t\t\t\t\t\tacted |= AI_Build_Power(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_BUILD_DEFENSE:\n\t\t\t\t\t\tacted |= AI_Build_Defense(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_BUILD_INCOME:\n\t\t\t\t\t\tacted |= AI_Build_Income(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_FIRE_SALE:\n\t\t\t\t\t\tacted |= AI_Fire_Sale(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_BUILD_ENGINEER:\n\t\t\t\t\t\tacted |= AI_Build_Engineer(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_BUILD_OFFENSE:\n\t\t\t\t\t\tacted |= AI_Build_Offense(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_RAISE_MONEY:\n\t\t\t\t\t\tacted |= AI_Raise_Money(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_RAISE_POWER:\n\t\t\t\t\t\tacted |= AI_Raise_Power(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_LOWER_POWER:\n\t\t\t\t\t\tacted |= AI_Lower_Power(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_ATTACK:\n\t\t\t\t\t\tacted |= AI_Attack(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(TICKS_PER_SECOND*5 + Random_Pick(1, TICKS_PER_SECOND/2));\n}\n\n\nUrgencyType HouseClass::Check_Build_Power(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tfixed frac = Power_Fraction();\n\tUrgencyType urgency = URGENCY_NONE;\n\n\tif (frac < 1 && Can_Make_Money()) {\n\t\turgency = URGENCY_LOW;\n\n\t\t/*\n\t\t**\tVery low power condition is considered a higher priority.\n\t\t*/\n\t\tif (frac < fixed::_3_4) urgency = URGENCY_MEDIUM;\n\n\t\t/*\n\t\t**\tWhen under attack and there is a need for power in defense,\n\t\t**\tthen consider power building a higher priority.\n\t\t*/\n\t\tif (State == STATE_THREATENED || State == STATE_ATTACKED) {\n\t\t\tif (BScan | (STRUCTF_CHRONOSPHERE)) {\n\t\t\t\turgency = URGENCY_HIGH;\n\t\t\t}\n\t\t}\n\n\t}\n\treturn(urgency);\n}\n\n\nUrgencyType HouseClass::Check_Build_Defense(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tThis routine determines what urgency level that base defense\n\t**\tshould be given. The more vulnerable the base is, the higher\n\t**\tthe urgency this routine should return.\n\t*/\n\treturn(URGENCY_NONE);\n}\n\n\nUrgencyType HouseClass::Check_Build_Offense(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tThis routine determines what urgency level that offensive\n\t**\tweaponry should be given. Surplus money or a very strong\n\t**\tdefense will cause the offensive urgency to increase.\n\t*/\n\treturn(URGENCY_NONE);\n}\n\n/*\n**\tDetermines what the attack state of the base is. The higher the state,\n**\tthe greater the immediate threat to base defense is.\n*/\nUrgencyType HouseClass::Check_Attack(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (Frame > TICKS_PER_MINUTE && Attack == 0) {\n\t\tif (State == STATE_ATTACKED) {\n\t\t\treturn(URGENCY_LOW);\n\t\t}\n\t\treturn(URGENCY_CRITICAL);\n\t}\n\treturn(URGENCY_NONE);\n}\n\n\nUrgencyType HouseClass::Check_Build_Income(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tThis routine should determine if income processing buildings\n\t**\tshould be constructed and at what urgency. The lower the money,\n\t**\tthe lower the refineries, or recent harvester losses should\n\t**\tcause a greater urgency to be returned.\n\t*/\n\treturn(URGENCY_NONE);\n}\n\n\nUrgencyType HouseClass::Check_Fire_Sale(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tIf there are no more factories at all, then sell everything off because the game\n\t**\tis basically over at this point.\n\t*/\n\tif (State != STATE_ATTACKED && CurBuildings && !(ActiveBScan & (STRUCTF_TENT|STRUCTF_BARRACKS|STRUCTF_CONST|STRUCTF_AIRSTRIP|STRUCTF_WEAP|STRUCTF_HELIPAD))) {\n\t\treturn(URGENCY_CRITICAL);\n\t}\n\treturn(URGENCY_NONE);\n}\n\n\nUrgencyType HouseClass::Check_Build_Engineer(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tThis routine should check to see what urgency that the production of\n\t**\tengineers should be. If a friendly building has been captured or the\n\t**\tenemy has weak defenses, then building an engineer would be a priority.\n\t*/\n\treturn(URGENCY_NONE);\n}\n\n\n/*\n**\tChecks to see if money is critically low and something must be done\n**\tto immediately raise cash.\n*/\nUrgencyType HouseClass::Check_Raise_Money(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tUrgencyType urgency = URGENCY_NONE;\n\tif (Available_Money() < 100) {\n\t\turgency = URGENCY_LOW;\n\t}\n\tif (Available_Money() < 2000 && !Can_Make_Money()) {\n\t\turgency++;\n\t}\n\n\treturn(urgency);\n}\n\n/*\n**\tChecks to see if power is very low and if so, a greater urgency to\n**\tbuild more power is returned.\n*/\nUrgencyType HouseClass::Check_Lower_Power(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (Power > Drain+300) {\n\t\treturn(URGENCY_LOW);\n\t}\n\treturn(URGENCY_NONE);\n}\n\n/*\n**\tThis routine determines if there is a power emergency. Such an\n**\temergency might require selling of structures in order to free\n**\tup power. This might occur if the base is being attacked and there\n**\tare defenses that require power, but are just short of having\n**\tenough.\n*/\nUrgencyType HouseClass::Check_Raise_Power(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tUrgencyType urgency = URGENCY_NONE;\n\n\tif (Power_Fraction() < Rule.PowerEmergencyFraction && Power < Drain - 400) {\n//\tif (Power_Fraction() < Rule.PowerEmergencyFraction && (BQuantity[STRUCT_CONST] == 0 || Available_Money() < 200 || Power < Drain-400)) {\n\t\turgency = URGENCY_MEDIUM;\n\t\tif (State == STATE_ATTACKED) {\n\t\t\turgency++;\n\t\t}\n\t}\n\treturn(urgency);\n}\n\n\nbool HouseClass::AI_Attack(UrgencyType )\n{\n\tassert(Houses.ID(this) == ID);\n\n\tbool shuffle = !((Frame > TICKS_PER_MINUTE && !CurBuildings) || Percent_Chance(33));\n\tbool forced = (CurBuildings == 0);\n\tint index;\n\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\tAircraftClass * a = Aircraft.Ptr(index);\n\n\t\tif (a != NULL && !a->IsInLimbo && a->House == this && a->Strength > 0) {\n\t\t\tif (!shuffle && a->Is_Weapon_Equipped() && (forced || Percent_Chance(75))) {\n\t\t\t\ta->Assign_Mission(MISSION_HUNT);\n\t\t\t}\n\t\t}\n\t}\n\tfor (index = 0; index < Units.Count(); index++) {\n\t\tUnitClass * u = Units.Ptr(index);\n\n\t\tif (u != NULL && !u->IsInLimbo && u->House == this && u->Strength > 0) {\n\t\t\tif (!shuffle && u->Is_Weapon_Equipped() && (forced || Percent_Chance(75))) {\n\t\t\t\tu->Assign_Mission(MISSION_HUNT);\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this unit is guarding the base, then cause it to shuffle\n\t\t\t\t**\tlocation instead.\n\t\t\t\t*/\n\t\t\t\tif (Percent_Chance(20) && u->Mission == MISSION_GUARD_AREA && Which_Zone(u) != ZONE_NONE) {\n\t\t\t\t\tu->ArchiveTarget = ::As_Target(Where_To_Go(u));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\tInfantryClass * i = Infantry.Ptr(index);\n\n\t\tif (i != NULL && !i->IsInLimbo && i->House == this && i->Strength > 0) {\n\t\t\tif (!shuffle && (i->Is_Weapon_Equipped() || *i == INFANTRY_RENOVATOR) && (forced || Percent_Chance(75))) {\n\t\t\t\ti->Assign_Mission(MISSION_HUNT);\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this soldier is guarding the base, then cause it to shuffle\n\t\t\t\t**\tlocation instead.\n\t\t\t\t*/\n\t\t\t\tif (Percent_Chance(20) && i->Mission == MISSION_GUARD_AREA && Which_Zone(i) != ZONE_NONE) {\n\t\t\t\t\ti->ArchiveTarget = ::As_Target(Where_To_Go(i));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tAttack = Rule.AttackInterval * Random_Pick(TICKS_PER_MINUTE/2, TICKS_PER_MINUTE*2);\n\treturn(true);\n}\n\n\n/*\n**\tGiven the specified urgency, build a power structure to meet\n**\tthis need.\n*/\nbool HouseClass::AI_Build_Power(UrgencyType ) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(false);\n}\n\n\n/*\n**\tGiven the specified urgency, build base defensive structures\n**\taccording to need and according to existing base disposition.\n*/\nbool HouseClass::AI_Build_Defense(UrgencyType ) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(false);\n}\n\n/*\n**\tGiven the specified urgency, build offensive units according\n**\tto need and according to the opponents base defenses.\n*/\nbool HouseClass::AI_Build_Offense(UrgencyType ) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(false);\n}\n\n/*\n**\tGiven the specified urgency, build income producing\n**\tstructures according to need.\n*/\nbool HouseClass::AI_Build_Income(UrgencyType ) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(false);\n}\n\n\nbool HouseClass::AI_Fire_Sale(UrgencyType urgency)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (CurBuildings && urgency == URGENCY_CRITICAL) {\n\t\tFire_Sale();\n\t\tDo_All_To_Hunt();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n/*\n**\tGiven the specified urgency, build an engineer.\n*/\nbool HouseClass::AI_Build_Engineer(UrgencyType ) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(false);\n}\n\n/*\n**\tGiven the specified urgency, sell of some power since\n**\tthere appears to be excess.\n*/\nbool HouseClass::AI_Lower_Power(UrgencyType ) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tBuildingClass * b = Find_Building(STRUCT_POWER);\n\tif (b != NULL) {\n\t\tb->Sell_Back(1);\n\t\treturn(true);\n\t}\n\n\tb = Find_Building(STRUCT_ADVANCED_POWER);\n\tif (b != NULL) {\n\t\tb->Sell_Back(1);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::AI_Raise_Power -- Try to raise power levels by selling off buildings.           *\n *                                                                                             *\n *    This routine is called when the computer needs to raise power by selling off buildings.  *\n *    Usually this occurs because of some catastrophe that has lowered power levels to         *\n *    the danger zone.                                                                         *\n *                                                                                             *\n * INPUT:   urgency  -- The urgency that the power needs to be raised. This controls what      *\n *                      buildings will be sold.                                                *\n *                                                                                             *\n * OUTPUT:  bool; Was a building sold to raise power?                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::AI_Raise_Power(UrgencyType urgency) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tSell off structures in this order.\n\t*/\n\tstatic struct {\n\t\tStructType Structure;\n\t\tUrgencyType Urgency;\n\t} _types[] = {\n\t\t{STRUCT_CHRONOSPHERE, URGENCY_LOW},\n\t\t{STRUCT_SHIP_YARD, URGENCY_LOW},\n\t\t{STRUCT_SUB_PEN, URGENCY_LOW},\n\t\t{STRUCT_ADVANCED_TECH, URGENCY_LOW},\n\t\t{STRUCT_FORWARD_COM, URGENCY_LOW},\n\t\t{STRUCT_SOVIET_TECH, URGENCY_LOW},\n\t\t{STRUCT_IRON_CURTAIN, URGENCY_MEDIUM},\n\t\t{STRUCT_RADAR, URGENCY_MEDIUM},\n\t\t{STRUCT_REPAIR, URGENCY_MEDIUM},\n\t\t{STRUCT_TESLA, URGENCY_HIGH}\n\t};\n\n\t/*\n\t**\tFind a structure to sell and then sell it. Bail from further scanning until\n\t**\tthe next time.\n\t*/\n\tfor (int i = 0; i < ARRAY_SIZE(_types); i++) {\n\t\tif (urgency >= _types[i].Urgency) {\n\t\t\tBuildingClass * b = Find_Building(_types[i].Structure);\n\t\t\tif (b != NULL) {\n\t\t\t\tb->Sell_Back(1);\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::AI_Raise_Money -- Raise emergency cash by selling buildings.                    *\n *                                                                                             *\n *    This routine handles the situation where the computer desperately needs cash but cannot  *\n *    wait for normal harvesting to raise it. Buildings must be sold.                          *\n *                                                                                             *\n * INPUT:   urgency  -- The urgency level that cash must be raised. The greater the urgency,   *\n *                      the more important the buildings that can be sold become.              *\n *                                                                                             *\n * OUTPUT:  bool; Was a building sold to raise cash?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::AI_Raise_Money(UrgencyType urgency) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tSell off structures in this order.\n\t*/\n\tstatic struct {\n\t\tStructType\tStructure;\n\t\tUrgencyType\tUrgency;\n\t} _types[] = {\n\t\t{STRUCT_CHRONOSPHERE, URGENCY_LOW},\n\t\t{STRUCT_SHIP_YARD, URGENCY_LOW},\n\t\t{STRUCT_SUB_PEN, URGENCY_LOW},\n\t\t{STRUCT_ADVANCED_TECH, URGENCY_LOW},\n\t\t{STRUCT_FORWARD_COM, URGENCY_LOW},\n\t\t{STRUCT_SOVIET_TECH, URGENCY_LOW},\n\t\t{STRUCT_STORAGE,URGENCY_LOW},\n\t\t{STRUCT_REPAIR,URGENCY_LOW},\n\t\t{STRUCT_TESLA,URGENCY_MEDIUM},\n\t\t{STRUCT_HELIPAD,URGENCY_MEDIUM},\n\t\t{STRUCT_POWER,URGENCY_HIGH},\n\t\t{STRUCT_AIRSTRIP,URGENCY_HIGH},\n//\t\t{STRUCT_WEAP,URGENCY_HIGH},\n//\t\t{STRUCT_BARRACKS,URGENCY_HIGH},\n//\t\t{STRUCT_TENT,URGENCY_HIGH},\n\t\t{STRUCT_CONST,URGENCY_CRITICAL}\n\t};\n\tBuildingClass * b = 0;\n\n\t/*\n\t**\tFind a structure to sell and then sell it. Bail from further scanning until\n\t**\tthe next time.\n\t*/\n\tfor (int i = 0; i < ARRAY_SIZE(_types); i++) {\n\t\tif (urgency >= _types[i].Urgency) {\n\t\t\tb = Find_Building(_types[i].Structure);\n\t\t\tif (b != NULL) {\n\t\t\t\tb->Sell_Back(1);\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n#ifdef NEVER\n\n/***********************************************************************************************\n * HouseClass::AI_Base_Defense -- Handles maintaining a strong base defense.                   *\n *                                                                                             *\n *    This logic is used to maintain a base defense.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine again. *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint HouseClass::AI_Base_Defense(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tCheck to find if any zone of the base is over defended. Such zones should have\n\t**\tsome of their defenses sold off to make better use of the money.\n\t*/\n\n\t/*\n\t**\tMake sure that the core defense is only about 1/2 of the perimeter defense average.\n\t*/\n\tint average = 0;\n\tfor (ZoneType z = ZONE_NORTH; z < ZONE_COUNT; z++) {\n\t\taverage += ZoneInfo[z].AirDefense;\n\t\taverage += ZoneInfo[z].ArmorDefense;\n\t\taverage += ZoneInfo[z].InfantryDefense;\n\t}\n\taverage /= (ZONE_COUNT-ZONE_NORTH);\n\n\t/*\n\t**\tIf the core value is greater than the average, then sell off some of the\n\t**\tinner defensive structures.\n\t*/\n\tint core = ZoneInfo[ZONE_CORE].AirDefense + ZoneInfo[ZONE_CORE].ArmorDefense + ZoneInfo[ZONE_CORE].InfantryDefense;\n\tif (core >= average) {\n\t\tstatic StructType _stype[] = {\n\t\t\tSTRUCT_GTOWER,\n\t\t\tSTRUCT_TURRET,\n\t\t\tSTRUCT_ATOWER,\n\t\t\tSTRUCT_OBELISK,\n\t\t\tSTRUCT_TESLA,\n\t\t\tSTRUCT_SAM\n\t\t};\n\t\tBuildingClass * b;\n\n\t\tfor (int index = 0; index < sizeof(_stype)/sizeof(_stype[0]); index++) {\n\t\t\tb = Find_Building(_stype[index], ZONE_CORE);\n\t\t\tif (b) {\n\t\t\t\tb->Sell_Back(1);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the enemy doesn't have any offensive air capability, then sell off any\n\t**\tSAM sites. Only do this when money is moderately low.\n\t*/\n\tif (Available_Money() < 1000 && (ActiveBScan & STRUCTF_SAM)) {\n\n\t\t/*\n\t\t**\tScan to find if ANY human opponents have aircraft or a helipad. If one\n\t\t** is found then consider that opponent to have a valid air threat potential.\n\t\t**\tDon't sell off SAM sites in that case.\n\t\t*/\n\t\tbool nothreat = true;\n\t\tfor (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\t\tHouseClass * house = HouseClass::As_Pointer(h);\n\n\t\t\tif (house && house->IsActive && house->IsHuman && !Is_Ally(house)) {\n\t\t\t\tif ((house->ActiveAScan & (AIRCRAFTF_ORCA|AIRCRAFTF_TRANSPORT|AIRCRAFTF_HELICOPTER)) || (house->ActiveBScan & STRUCTF_HELIPAD)) {\n\t\t\t\t\tnothreat = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(TICKS_PER_SECOND*5);\n}\n#endif\n\n\n/***********************************************************************************************\n * HouseClass::AI_Building -- Determines what building to build.                               *\n *                                                                                             *\n *    This routine handles the general case of determining what building to build next.        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine again. *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *   11/03/1996 JLB : Tries to match aircraft of enemy                                         *\n *=============================================================================================*/\nint HouseClass::AI_Building(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (BuildStructure != STRUCT_NONE) return(TICKS_PER_SECOND);\n\n\tif (Session.Type == GAME_NORMAL && Base.House == Class->House) {\n\t\tBaseNodeClass * node = Base.Next_Buildable();\n\t\tif (node) {\n\t\t\tBuildStructure = node->Type;\n\t\t}\n\t}\n\n\tif (IsBaseBuilding) {\n\t\t/*\n\t\t**\tDon't suggest anything to build if the base is already big enough.\n\t\t*/\n\t\tint quant = 0;\n\t\tfor (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\t\tHouseClass const * hptr = HouseClass::As_Pointer(h);\n\n\t\t\tif (hptr != NULL && hptr->IsActive && hptr->IsHuman && quant < hptr->CurBuildings) {\n\t\t\t\tquant = hptr->CurBuildings;\n\t\t\t}\n\t\t}\n\t\tquant += Rule.BaseSizeAdd;\n\n// TCTC -- Should multiply largest player base by some rational number.\n//\t\tif (CurBuildings >= quant) return(TICKS_PER_SECOND);\n\n\t\tBuildChoice.Free_All();\n\t\tBuildChoiceClass * choiceptr;\n\t\tStructType stype = STRUCT_NONE;\n\t\tint money = Available_Money();\n\t\tint level = Control.TechLevel;\n\t\tbool hasincome = (BQuantity[STRUCT_REFINERY] > 0 && !IsTiberiumShort && UQuantity[UNIT_HARVESTER] > 0);\n\t\tBuildingTypeClass const * b = NULL;\n\t\tHouseClass const * enemy = NULL;\n\t\tif (Enemy != HOUSE_NONE) {\n\t\t\tenemy = HouseClass::As_Pointer(Enemy);\n\t\t}\n\n\t\tlevel = Control.TechLevel;\n\n\t\t/*\n\t\t**\tTry to build a power plant if there is insufficient power and there is enough\n\t\t**\tmoney available.\n\t\t*/\n\t\tb = &BuildingTypeClass::As_Reference(STRUCT_ADVANCED_POWER);\n\t\tif (Can_Build(b, ActLike) && Power <= Drain+Rule.PowerSurplus && b->Cost_Of() < money) {\n\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\tif (choiceptr != NULL) {\n\t\t\t\t*choiceptr = BuildChoiceClass(BQuantity[STRUCT_REFINERY] == 0 ? URGENCY_LOW : URGENCY_MEDIUM, b->Type);\n\t\t\t}\n\t\t} else {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_POWER);\n\t\t\tif (Can_Build(b, ActLike) && Power <= Drain+Rule.PowerSurplus && b->Cost_Of() < money) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(BQuantity[STRUCT_REFINERY] == 0 ? URGENCY_LOW : URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tBuild a refinery if there isn't one already available.\n\t\t*/\n\t\tunsigned int current = BQuantity[STRUCT_REFINERY];\n\t\tif (!IsTiberiumShort && current < Round_Up(Rule.RefineryRatio*fixed(CurBuildings)) && current < Rule.RefineryLimit) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_REFINERY);\n\t\t\tif (Can_Build(b, ActLike) && (money > b->Cost_Of() || hasincome)) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(BQuantity[STRUCT_REFINERY] == 0 ? URGENCY_HIGH : URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tAlways make sure there is a barracks available, but only if there\n\t\t**\twill be sufficient money to train troopers.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_BARRACKS] + BQuantity[STRUCT_TENT];\n\t\tif (current < Round_Up(Rule.BarracksRatio*fixed(CurBuildings)) && current < Rule.BarracksLimit && (money > 300 || hasincome)) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_BARRACKS);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(current > 0 ? URGENCY_LOW : URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_TENT);\n\t\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t\t*choiceptr = BuildChoiceClass(current > 0 ? URGENCY_LOW : URGENCY_MEDIUM, b->Type);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tTry to build one dog house.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_KENNEL];\n\t\tif (current < 1 && (money > 300 || hasincome)) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_KENNEL);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tTry to build one gap generator.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_GAP];\n\t\tif (current < 1 && Power_Fraction() >= 1 && hasincome) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_GAP);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tA source of combat vehicles is always needed, but only if there will\n\t\t**\tbe sufficient money to build vehicles.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_WEAP];\n\t\tif (current < Round_Up(Rule.WarRatio*fixed(CurBuildings)) && current < Rule.WarLimit && (money > 2000 || hasincome)) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_WEAP);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(current > 0 ? URGENCY_LOW : URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tAlways build up some base defense.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_PILLBOX] + BQuantity[STRUCT_CAMOPILLBOX] + BQuantity[STRUCT_TURRET] + BQuantity[STRUCT_FLAME_TURRET];\n\t\tif (current < Round_Up(Rule.DefenseRatio*fixed(CurBuildings)) && current < Rule.DefenseLimit) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_FLAME_TURRET);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (Percent_Chance(50)) {\n\t\t\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_PILLBOX);\n\t\t\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_TURRET);\n\t\t\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tBuild some air defense.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_SAM] + BQuantity[STRUCT_AAGUN];\n\t\tif (current < Round_Up(Rule.AARatio*fixed(CurBuildings)) && current < Rule.AALimit) {\n\n\t\t\t/*\n\t\t\t**\tBuilding air defense only makes sense if the opponent has aircraft\n\t\t\t**\tof some kind.\n\t\t\t*/\n\t\t\tbool airthreat = false;\n\t\t\tint threat_quantity = 0;\n\t\t\tif (enemy != NULL && enemy->AScan != 0) {\n\t\t\t\tairthreat = true;\n\t\t\t\tthreat_quantity = enemy->CurAircraft;\n\t\t\t}\n\t\t\tif (!airthreat) {\n\t\t\t\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\t\t\t\tHouseClass * h = HouseClass::As_Pointer(house);\n\t\t\t\t\tif (h != NULL && !Is_Ally(house) && h->AScan != 0) {\n\t\t\t\t\t\tairthreat = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (airthreat) {\n\n\t\t\t\tif (BQuantity[STRUCT_RADAR] == 0) {\n\t\t\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_RADAR);\n\t\t\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_HIGH, b->Type);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_SAM);\n\t\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t\t*choiceptr = BuildChoiceClass((current < threat_quantity) ? URGENCY_HIGH : URGENCY_MEDIUM, b->Type);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_AAGUN);\n\t\t\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t\t\t*choiceptr = BuildChoiceClass((current < threat_quantity) ? URGENCY_HIGH : URGENCY_MEDIUM, b->Type);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tAdvanced base defense would be good.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_TESLA];\n\t\tif (current < Round_Up(Rule.TeslaRatio*fixed(CurBuildings)) && current < Rule.TeslaLimit) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_TESLA);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome) && Power_Fraction() >= 1) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tBuild a tech center as soon as possible.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_ADVANCED_TECH] + BQuantity[STRUCT_SOVIET_TECH];\n\t\tif (current < 1) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_ADVANCED_TECH);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome) && Power_Fraction() >= 1) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_SOVIET_TECH);\n\t\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome) && Power_Fraction() >= 1) {\n\t\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tA helipad would be good.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_HELIPAD];\n\t\tif (current < Round_Up(Rule.HelipadRatio*fixed(CurBuildings)) && current < Rule.HelipadLimit) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_HELIPAD);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\tint threat_quantity = 0;\n\t\t\t\t\tif (enemy != NULL) {\n\t\t\t\t\t\tthreat_quantity = enemy->CurAircraft;\n\t\t\t\t\t}\n\n\t\t\t\t\t*choiceptr = BuildChoiceClass((CurAircraft < threat_quantity) ? URGENCY_HIGH : URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tAn airstrip would be good.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_AIRSTRIP];\n\t\tif (current < Round_Up(Rule.AirstripRatio*fixed(CurBuildings)) && current < Rule.AirstripLimit) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_AIRSTRIP);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\tint threat_quantity = 0;\n\t\t\t\t\tif (enemy != NULL) {\n\t\t\t\t\t\tthreat_quantity = enemy->CurAircraft;\n\t\t\t\t\t}\n\n\t\t\t\t\t*choiceptr = BuildChoiceClass((CurAircraft < threat_quantity) ? URGENCY_HIGH : URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n#ifdef OLD\n\t\t/*\n\t\t**\tBuild a repair bay if there isn't one already available.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_REPAIR];\n\t\tif (current == 0) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_REPAIR);\n\t\t\tif (Can_Build(b, ActLike) && b->Cost_Of() < money) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tPick the choice that is the most urgent.\n\t\t*/\n\t\tUrgencyType best = URGENCY_NONE;\n\t\tint bestindex;\n\t\tfor (int index = 0; index < BuildChoice.Count(); index++) {\n\t\t\tif (BuildChoice.Ptr(index)->Urgency > best) {\n\t\t\t\tbestindex = index;\n\t\t\t\tbest = BuildChoice.Ptr(index)->Urgency;\n\t\t\t}\n\t\t}\n\t\tif (best != URGENCY_NONE) {\n\t\t\tBuildStructure = BuildChoice.Ptr(bestindex)->Structure;\n\t\t}\n\t}\n\n\treturn(TICKS_PER_SECOND);\n}\n\n\n/***********************************************************************************************\n * HouseClass::AI_Unit -- Determines what unit to build next.                                  *\n *                                                                                             *\n *    This routine handles the general case of determining what units to build next.           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of games frames to delay before calling this routine again.*\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint HouseClass::AI_Unit(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (BuildUnit != UNIT_NONE) return(TICKS_PER_SECOND);\n\tif (CurUnits >= Control.MaxUnit) return(TICKS_PER_SECOND);\n\n\t/*\n\t**\tA computer controlled house will try to build a replacement\n\t**\tharvester if possible.\n\t*/\n\tif (IQ >= Rule.IQHarvester && !IsTiberiumShort && !IsHuman && BQuantity[STRUCT_REFINERY] > UQuantity[UNIT_HARVESTER] && Difficulty != DIFF_HARD) {\n\t\tif (UnitTypeClass::As_Reference(UNIT_HARVESTER).Level <= Control.TechLevel) {\n\t\t\tBuildUnit = UNIT_HARVESTER;\n\t\t\treturn(TICKS_PER_SECOND);\n\t\t}\n\t}\n\n\tif (Session.Type == GAME_NORMAL) {\n\n\t\tint counter[UNIT_COUNT];\n\t\tmemset(counter, 0x00, sizeof(counter));\n\n\t\t/*\n\t\t**\tBuild a list of the maximum of each type we wish to produce. This will be\n\t\t**\ttwice the number required to fill all teams.\n\t\t*/\n\t\tfor (int index = 0; index < Teams.Count(); index++) {\n\t\t\tTeamClass * tptr = Teams.Ptr(index);\n\t\t\tif (tptr != NULL) {\n\t\t\t\tTeamTypeClass const * team = tptr->Class;\n\t\t\t\tif (((team->IsReinforcable && !tptr->IsFullStrength) || (!tptr->IsForcedActive && !tptr->IsHasBeen && !tptr->JustAltered)) && team->House == Class->House) {\n\t\t\t\t\tfor (int subindex = 0; subindex < team->ClassCount; subindex++) {\n\t\t\t\t\t\tTechnoTypeClass const * memtype = team->Members[subindex].Class;\n\t\t\t\t\t\tif (memtype->What_Am_I() == RTTI_UNITTYPE) {\n\t\t\t\t\t\t\tcounter[((UnitTypeClass const *)memtype)->Type] = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tTeam types that are flagged as prebuilt, will always try to produce enough\n\t\t**\tto fill one team of this type regardless of whether there is a team active\n\t\t**\tof that type.\n\t\t*/\n\t\tfor (index = 0; index < TeamTypes.Count(); index++) {\n\t\t\tTeamTypeClass const * team = TeamTypes.Ptr(index);\n\t\t\tif (team != NULL && team->House == Class->House && team->IsPrebuilt && (!team->IsAutocreate || IsAlerted)) {\n\t\t\t\tfor (int subindex = 0; subindex < team->ClassCount; subindex++) {\n\t\t\t\t\tTechnoTypeClass const * memtype = team->Members[subindex].Class;\n\n\t\t\t\t\tif (memtype->What_Am_I() == RTTI_UNITTYPE) {\n\t\t\t\t\t\tint subtype = ((UnitTypeClass const *)memtype)->Type;\n\t\t\t\t\t\tcounter[subtype] = max(counter[subtype], team->Members[subindex].Quantity);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tReduce the theoretical maximum by the actual number of objects currently\n\t\t**\tin play.\n\t\t*/\n\t\tfor (int uindex = 0; uindex < Units.Count(); uindex++) {\n\t\t\tUnitClass * unit = Units.Ptr(uindex);\n\t\t\tif (unit != NULL && unit->Is_Recruitable(this) && counter[unit->Class->Type] > 0) {\n\t\t\t\tcounter[unit->Class->Type]--;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tPick to build the most needed object but don't consider those objects that\n\t\t**\tcan't be built because of scenario restrictions or insufficient cash.\n\t\t*/\n\t\tint bestval = -1;\n\t\tint bestcount = 0;\n\t\tUnitType bestlist[UNIT_COUNT];\n\t\tfor (UnitType utype = UNIT_FIRST; utype < UNIT_COUNT; utype++) {\n\t\t\tif (counter[utype] > 0 && Can_Build(&UnitTypeClass::As_Reference(utype), Class->House) && UnitTypeClass::As_Reference(utype).Cost_Of() <= Available_Money()) {\n\t\t\t\tif (bestval == -1 || bestval < counter[utype]) {\n\t\t\t\t\tbestval = counter[utype];\n\t\t\t\t\tbestcount = 0;\n\t\t\t\t}\n\t\t\t\tbestlist[bestcount++] = utype;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tThe unit type to build is now known. Fetch a pointer to the techno type class.\n\t\t*/\n\t\tif (bestcount) {\n\t\t\tBuildUnit = bestlist[Random_Pick(0, bestcount-1)];\n\t\t}\n\t}\n\n\tif (IsBaseBuilding) {\n\n\t\tint counter[UNIT_COUNT];\n\t\tint total = 0;\n\t\tfor (UnitType index = UNIT_FIRST; index < UNIT_COUNT; index++) {\n\t\t\tUnitTypeClass const * utype = &UnitTypeClass::As_Reference(index);\n\t\t\tif (Can_Build(utype, ActLike) && utype->Type != UNIT_HARVESTER) {\n\t\t\t\tif (utype->PrimaryWeapon != NULL) {\n\t\t\t\t\tcounter[index] = 20;\n\t\t\t\t} else {\n\t\t\t\t\tcounter[index] = 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcounter[index] = 0;\n\t\t\t}\n\t\t\ttotal += counter[index];\n\t\t}\n\n\t\tif (total > 0) {\n\t\t\tint choice = Random_Pick(0, total-1);\n\t\t\tfor (index = UNIT_FIRST; index < UNIT_COUNT; index++) {\n\t\t\t\tif (choice < counter[index]) {\n\t\t\t\t\tBuildUnit = index;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tchoice -= counter[index];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(TICKS_PER_SECOND);\n}\n\n\nint HouseClass::AI_Vessel(void)\n{\n\tassert(Houses.ID(this) == ID);\n\tif (BuildVessel != VESSEL_NONE) return(TICKS_PER_SECOND);\n\n\tif (CurVessels >= Control.MaxVessel) {\n\t\treturn(TICKS_PER_SECOND);\n\t}\n\n\tif (Session.Type == GAME_NORMAL) {\n\n\t\tint counter[VESSEL_COUNT];\n\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\tmemset(counter, 0x00, sizeof(counter));\n\t\t} else {\n\t\t\tfor (VesselType index = VESSEL_FIRST; index < VESSEL_COUNT; index++) {\n\t\t\t\tif (Can_Build(&VesselTypeClass::As_Reference(index), Class->House) && VesselTypeClass::As_Reference(index).Level <= Control.TechLevel) {\n\t\t\t\t\tcounter[index] = 16;\n\t\t\t\t} else {\n\t\t\t\t\tcounter[index] = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tBuild a list of the maximum of each type we wish to produce. This will be\n\t\t**\ttwice the number required to fill all teams.\n\t\t*/\n\t\tfor (int index = 0; index < Teams.Count(); index++) {\n\t\t\tTeamClass * tptr = Teams.Ptr(index);\n\t\t\tif (tptr) {\n\t\t\t\tTeamTypeClass const * team = tptr->Class;\n\n\t\t\t\tif (((team->IsReinforcable && !tptr->IsFullStrength) || (!tptr->IsForcedActive && !tptr->IsHasBeen && !tptr->JustAltered)) && team->House == Class->House) {\n\t\t\t\t\tfor (int subindex = 0; subindex < team->ClassCount; subindex++) {\n\t\t\t\t\t\tif (team->Members[subindex].Class->What_Am_I() == RTTI_VESSELTYPE) {\n\t\t\t\t\t\t\tcounter[((VesselTypeClass const *)(team->Members[subindex].Class))->Type] = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tTeam types that are flagged as prebuilt, will always try to produce enough\n\t\t**\tto fill one team of this type regardless of whether there is a team active\n\t\t**\tof that type.\n\t\t*/\n\t\tfor (index = 0; index < TeamTypes.Count(); index++) {\n\t\t\tTeamTypeClass const * team = TeamTypes.Ptr(index);\n\t\t\tif (team) {\n\t\t\t\tif (team->House == Class->House && team->IsPrebuilt && (!team->IsAutocreate || IsAlerted)) {\n\t\t\t\t\tfor (int subindex = 0; subindex < team->ClassCount; subindex++) {\n\t\t\t\t\t\tif (team->Members[subindex].Class->What_Am_I() == RTTI_VESSELTYPE) {\n\t\t\t\t\t\t\tint subtype = ((VesselTypeClass const *)(team->Members[subindex].Class))->Type;\n\t\t\t\t\t\t\tcounter[subtype] = max(counter[subtype], team->Members[subindex].Quantity);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tReduce the theoretical maximum by the actual number of objects currently\n\t\t**\tin play.\n\t\t*/\n\t\tfor (int vindex = 0; vindex < Vessels.Count(); vindex++) {\n\t\t\tVesselClass * unit = Vessels.Ptr(vindex);\n\t\t\tif (unit != NULL && unit->Is_Recruitable(this) && counter[unit->Class->Type] > 0) {\n\t\t\t\tcounter[unit->Class->Type]--;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tPick to build the most needed object but don't consider those object that\n\t\t**\tcan't be built because of scenario restrictions or insufficient cash.\n\t\t*/\n\t\tint bestval = -1;\n\t\tint bestcount = 0;\n\t\tVesselType bestlist[VESSEL_COUNT];\n\t\tfor (VesselType utype = VESSEL_FIRST; utype < VESSEL_COUNT; utype++) {\n\t\t\tif (counter[utype] > 0 && Can_Build(&VesselTypeClass::As_Reference(utype), Class->House) && VesselTypeClass::As_Reference(utype).Cost_Of() <= Available_Money()) {\n\t\t\t\tif (bestval == -1 || bestval < counter[utype]) {\n\t\t\t\t\tbestval = counter[utype];\n\t\t\t\t\tbestcount = 0;\n\t\t\t\t}\n\t\t\t\tbestlist[bestcount++] = utype;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tThe unit type to build is now known. Fetch a pointer to the techno type class.\n\t\t*/\n\t\tif (bestcount) {\n\t\t\tBuildVessel = bestlist[Random_Pick(0, bestcount-1)];\n\t\t}\n\t}\n\n\tif (IsBaseBuilding) {\n\t\tBuildVessel = VESSEL_NONE;\n\t}\n\n\treturn(TICKS_PER_SECOND);\n}\n\n\n\n/***********************************************************************************************\n * HouseClass::AI_Infantry -- Determines the infantry unit to build.                           *\n *                                                                                             *\n *    This routine handles the general case of determining what infantry unit to build         *\n *    next.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before being called again.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint HouseClass::AI_Infantry(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (BuildInfantry != INFANTRY_NONE) return(TICKS_PER_SECOND);\n\tif (CurInfantry >= Control.MaxInfantry) return(TICKS_PER_SECOND);\n\n\tif (Session.Type == GAME_NORMAL) {\n\t\tTechnoTypeClass const * techno = 0;\n\t\tint counter[INFANTRY_COUNT];\n\t\tmemset(counter, 0x00, sizeof(counter));\n\n\t\t/*\n\t\t**\tBuild a list of the maximum of each type we wish to produce. This will be\n\t\t**\ttwice the number required to fill all teams.\n\t\t*/\n\t\tfor (int index = 0; index < Teams.Count(); index++) {\n\t\t\tTeamClass * tptr = Teams.Ptr(index);\n\t\t\tif (tptr != NULL) {\n\t\t\t\tTeamTypeClass const * team = tptr->Class;\n\n\t\t\t\tif (((team->IsReinforcable && !tptr->IsFullStrength) || (!tptr->IsForcedActive && !tptr->IsHasBeen && !tptr->JustAltered)) && team->House == Class->House) {\n\t\t\t\t\tfor (int subindex = 0; subindex < team->ClassCount; subindex++) {\n\t\t\t\t\t\tif (team->Members[subindex].Class->What_Am_I() == RTTI_INFANTRYTYPE) {\n\t\t\t\t\t\t\tcounter[((InfantryTypeClass const *)(team->Members[subindex].Class))->Type] += team->Members[subindex].Quantity + (team->IsReinforcable ? 1 : 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tTeam types that are flagged as prebuilt, will always try to produce enough\n\t\t**\tto fill one team of this type regardless of whether there is a team active\n\t\t**\tof that type.\n\t\t*/\n\t\tfor (index = 0; index < TeamTypes.Count(); index++) {\n\t\t\tTeamTypeClass const * team = TeamTypes.Ptr(index);\n\t\t\tif (team != NULL) {\n\t\t\t\tif (team->House == Class->House && team->IsPrebuilt && (!team->IsAutocreate || IsAlerted)) {\n\t\t\t\t\tfor (int subindex = 0; subindex < team->ClassCount; subindex++) {\n\t\t\t\t\t\tif (team->Members[subindex].Class->What_Am_I() == RTTI_INFANTRYTYPE) {\n\t\t\t\t\t\t\tint subtype = ((InfantryTypeClass const *)(team->Members[subindex].Class))->Type;\n//\t\t\t\t\t\t\t\t\tcounter[subtype] = 1;\n\t\t\t\t\t\t\tcounter[subtype] = max(counter[subtype], team->Members[subindex].Quantity);\n\t\t\t\t\t\t\tcounter[subtype] = min(counter[subtype], 5);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tReduce the theoretical maximum by the actual number of objects currently\n\t\t**\tin play.\n\t\t*/\n\t\tfor (int uindex = 0; uindex < Infantry.Count(); uindex++) {\n\t\t\tInfantryClass * infantry = Infantry.Ptr(uindex);\n\t\t\tif (infantry != NULL && infantry->Is_Recruitable(this) && counter[infantry->Class->Type] > 0) {\n\t\t\t\tcounter[infantry->Class->Type]--;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tPick to build the most needed object but don't consider those object that\n\t\t**\tcan't be built because of scenario restrictions or insufficient cash.\n\t\t*/\n\t\tint bestval = -1;\n\t\tint bestcount = 0;\n\t\tInfantryType bestlist[INFANTRY_COUNT];\n\t\tfor (InfantryType utype = INFANTRY_FIRST; utype < INFANTRY_COUNT; utype++) {\n\n\t\t\tif (utype != INFANTRY_DOG || !(IScan & INFANTRYF_DOG)) {\n\t\t\t\tif (counter[utype] > 0 && Can_Build(&InfantryTypeClass::As_Reference(utype), Class->House) && InfantryTypeClass::As_Reference(utype).Cost_Of() <= Available_Money()) {\n\t\t\t\t\tif (bestval == -1 || bestval < counter[utype]) {\n\t\t\t\t\t\tbestval = counter[utype];\n\t\t\t\t\t\tbestcount = 0;\n\t\t\t\t\t}\n\t\t\t\t\tbestlist[bestcount++] = utype;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tThe infantry type to build is now known. Fetch a pointer to the techno type class.\n\t\t*/\n\t\tif (bestcount) {\n\t\t\tint pick = Random_Pick(0, bestcount-1);\n\t\t\tBuildInfantry = bestlist[pick];\n\t\t}\n\n\t}\n\n\tif (IsBaseBuilding) {\n\t\tHouseClass const * enemy = NULL;\n\t\tif (Enemy != HOUSE_NONE) {\n\t\t\tenemy = HouseClass::As_Pointer(Enemy);\n\t\t}\n\n\t\t/*\n\t\t**\tThis structure is used to keep track of the list of infantry types that should be\n\t\t**\tbuilt. The infantry type and the value assigned to it is recorded.\n\t\t*/\n\t\tstruct {\n\t\t\tInfantryType\tType;\t\t// Infantry type.\n\t\t\tint\t\t\t\tValue;\t// Relative value assigned.\n\t\t} typetrack[INFANTRY_COUNT];\n\t\tint count = 0;\n\t\tint total = 0;\n\t\tfor (InfantryType index = INFANTRY_FIRST; index < INFANTRY_COUNT; index++) {\n\t\t\tif (Can_Build(&InfantryTypeClass::As_Reference(index), ActLike) && InfantryTypeClass::As_Reference(index).Level <= Control.TechLevel) {\n\t\t\t\ttypetrack[count].Value = 0;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98 This looks like a potential bug. It is prob. for save game format compatibility.\n\t\t\t\tint clipindex = index;\n\t\t\t\tif (clipindex >= INFANTRY_RA_COUNT) clipindex -= INFANTRY_RA_COUNT;\n\t\t\t\tif ((enemy != NULL && enemy->IQuantity[clipindex] > IQuantity[clipindex]) || Available_Money() > Rule.InfantryReserve || CurInfantry < CurBuildings * Rule.InfantryBaseMult) {\n#else\n\t\t\t\tif ((enemy != NULL && enemy->IQuantity[index] > IQuantity[index]) || Available_Money() > Rule.InfantryReserve || CurInfantry < CurBuildings * Rule.InfantryBaseMult) {\n#endif\n\n\t\t\t\t\tswitch (index) {\n\t\t\t\t\t\tcase INFANTRY_E1:\n\t\t\t\t\t\t\ttypetrack[count].Value = 3;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase INFANTRY_E2:\n\t\t\t\t\t\t\ttypetrack[count].Value = 5;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase INFANTRY_E3:\n\t\t\t\t\t\t\ttypetrack[count].Value = 2;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase INFANTRY_E4:\n\t\t\t\t\t\t\ttypetrack[count].Value = 5;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase INFANTRY_RENOVATOR:\n\t\t\t\t\t\t\tif (CurInfantry > 5) {\n\t\t\t\t\t\t\t\ttypetrack[count].Value = 1 - max(IQuantity[index], 0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase INFANTRY_TANYA:\n\t\t\t\t\t\t\ttypetrack[count].Value = 1 - max(IQuantity[index], 0);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\ttypetrack[count].Value = 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (typetrack[count].Value > 0) {\n\t\t\t\t\ttypetrack[count].Type = index;\n\t\t\t\t\ttotal += typetrack[count].Value;\n\t\t\t\t\tcount++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is at least one choice, then pick it. The object picked\n\t\t**\tis influenced by the weight (value) assigned to it. This is accomplished\n\t\t**\tby picking a number between 0 and the total weight value. The appropriate\n\t\t**\tinfantry object that matches the number picked is then selected to be built.\n\t\t*/\n\t\tif (count > 0) {\n\t\t\tint pick = Random_Pick(0, total-1);\n\t\t\tfor (int index = 0; index < count; index++) {\n\t\t\t\tif (pick < typetrack[index].Value) {\n\t\t\t\t\tBuildInfantry = typetrack[index].Type;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tpick -= typetrack[index].Value;\n\t\t\t}\n\t\t}\n\t}\n\treturn(TICKS_PER_SECOND);\n}\n\n\n/***********************************************************************************************\n * HouseClass::AI_Aircraft -- Determines what aircraft to build next.                          *\n *                                                                                             *\n *    This routine is used to determine the general case of what aircraft to build next.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of frame to delay before calling this routine again.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint HouseClass::AI_Aircraft(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (!IsHuman && IQ >= Rule.IQAircraft) {\n\t\tif (BuildAircraft != AIRCRAFT_NONE) return(TICKS_PER_SECOND);\n\t\tif (CurAircraft >= Control.MaxAircraft) return(TICKS_PER_SECOND);\n\n\t\tif (Can_Build(&AircraftTypeClass::As_Reference(AIRCRAFT_LONGBOW), ActLike) &&\n\t\t\t\t AircraftTypeClass::As_Reference(AIRCRAFT_LONGBOW).Level <= Control.TechLevel &&\n\t\t\t\t BQuantity[STRUCT_HELIPAD] > AQuantity[AIRCRAFT_LONGBOW] + AQuantity[AIRCRAFT_HIND]) {\n\t\t\tBuildAircraft = AIRCRAFT_LONGBOW;\n\t\t\treturn(TICKS_PER_SECOND);\n\t\t}\n\n\t\tif (Can_Build(&AircraftTypeClass::As_Reference(AIRCRAFT_HIND), ActLike) &&\n\t\t\t\t AircraftTypeClass::As_Reference(AIRCRAFT_HIND).Level <= Control.TechLevel &&\n\t\t\t\t BQuantity[STRUCT_HELIPAD] > AQuantity[AIRCRAFT_LONGBOW] + AQuantity[AIRCRAFT_HIND]) {\n\t\t\tBuildAircraft = AIRCRAFT_HIND;\n\t\t\treturn(TICKS_PER_SECOND);\n\t\t}\n\n\t\tif (Can_Build(&AircraftTypeClass::As_Reference(AIRCRAFT_MIG), ActLike) &&\n\t\t\t\t AircraftTypeClass::As_Reference(AIRCRAFT_MIG).Level <= Control.TechLevel &&\n\t\t\t\t BQuantity[STRUCT_AIRSTRIP] > AQuantity[AIRCRAFT_MIG] + AQuantity[AIRCRAFT_YAK]) {\n\t\t\tBuildAircraft = AIRCRAFT_MIG;\n\t\t\treturn(TICKS_PER_SECOND);\n\t\t}\n\n\t\tif (Can_Build(&AircraftTypeClass::As_Reference(AIRCRAFT_YAK), ActLike) &&\n\t\t\t\t AircraftTypeClass::As_Reference(AIRCRAFT_YAK).Level <= Control.TechLevel &&\n\t\t\t\t BQuantity[STRUCT_AIRSTRIP] > AQuantity[AIRCRAFT_MIG] + AQuantity[AIRCRAFT_YAK]) {\n\t\t\tBuildAircraft = AIRCRAFT_YAK;\n\t\t\treturn(TICKS_PER_SECOND);\n\t\t}\n\t}\n\n\treturn(TICKS_PER_SECOND);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Production_Begun -- Records that production has begun.                          *\n *                                                                                             *\n *    This routine is used to inform the Expert System that production of the specified object *\n *    has begun. This allows the AI to proceed with picking another object to begin production *\n *    on.                                                                                      *\n *                                                                                             *\n * INPUT:   product  -- Pointer to the object that production has just begun on.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Production_Begun(TechnoClass const * product)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (product != NULL) {\n\t\tswitch (product->What_Am_I()) {\n\t\t\tcase RTTI_UNIT:\n\t\t\t\tif (*((UnitClass*)product) == BuildUnit) {\n\t\t\t\t\tBuildUnit = UNIT_NONE;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_VESSEL:\n\t\t\t\tif (*((VesselClass*)product) == BuildVessel) {\n\t\t\t\t\tBuildVessel = VESSEL_NONE;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_INFANTRY:\n\t\t\t\tif (*((InfantryClass*)product) == BuildInfantry) {\n\t\t\t\t\tBuildInfantry = INFANTRY_NONE;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_BUILDING:\n\t\t\t\tif (*((BuildingClass*)product) == BuildStructure) {\n\t\t\t\t\tBuildStructure = STRUCT_NONE;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\tif (*((AircraftClass*)product) == BuildAircraft) {\n\t\t\t\t\tBuildAircraft = AIRCRAFT_NONE;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Tracking_Remove -- Remove object from house tracking system.                    *\n *                                                                                             *\n *    This routine informs the Expert System that the specified object is no longer part of    *\n *    this house's inventory. This occurs when the object is destroyed or captured.            *\n *                                                                                             *\n * INPUT:   techno   -- Pointer to the object to remove from the tracking systems of this      *\n *                      house.                                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Tracking_Remove(TechnoClass const * techno)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tint type;\n\n\tswitch (techno->What_Am_I()) {\n\t\tcase RTTI_BUILDING:\n\t\t\tCurBuildings--;\n\t\t\tBQuantity[((BuildingTypeClass const &)techno->Class_Of()).Type]--;\n\t\t\tbreak;\n\n\t\tcase RTTI_AIRCRAFT:\n\t\t\tCurAircraft--;\n\t\t\tAQuantity[((AircraftTypeClass const &)techno->Class_Of()).Type]--;\n\t\t\tbreak;\n\n\t\tcase RTTI_INFANTRY:\n\t\t\tCurInfantry--;\n\t\t\tif (!((InfantryClass *)techno)->IsTechnician) {\n\t\t\t\ttype = ((InfantryTypeClass const &)techno->Class_Of()).Type;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif (type >= INFANTRY_RA_COUNT) type -= INFANTRY_RA_COUNT;\n#endif\n\t\t\t\tIQuantity[type]--;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_UNIT:\n\t\t\tCurUnits--;\n\t\t\ttype = ((UnitTypeClass const &)techno->Class_Of()).Type;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif (type >= UNIT_RA_COUNT) type -= UNIT_RA_COUNT;\n#endif\n\t\t\tUQuantity[type]--;\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\t\tCurVessels--;\n\t\t\ttype = ((VesselTypeClass const &)techno->Class_Of()).Type;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif (type >= VESSEL_RA_COUNT) type -= VESSEL_RA_COUNT;\n#endif\n\t\t\tVQuantity[type]--;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Tracking_Add -- Informs house of new inventory item.                            *\n *                                                                                             *\n *    This function is called when the specified object is now available as part of the house's*\n *    inventory. This occurs when the object is newly produced and also when it is captured    *\n *    by this house.                                                                           *\n *                                                                                             *\n * INPUT:   techno   -- Pointer to the object that is now part of the house inventory.         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Tracking_Add(TechnoClass const * techno)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tStructType building;\n\tAircraftType aircraft;\n\tInfantryType infantry;\n\tUnitType unit;\n\tVesselType vessel;\n\tint quant;\n\n\tswitch (techno->What_Am_I()) {\n\t\tcase RTTI_BUILDING:\n\t\t\tCurBuildings++;\n\t\t\tbuilding = ((BuildingTypeClass const &)techno->Class_Of()).Type;\n\t\t\tBQuantity[building]++;\n\t\t\tBScan |= (1L << building);\n\t\t\tif (Session.Type == GAME_INTERNET) {\n\t\t\t\tBuildingTotals->Increment_Unit_Total(techno->Class_Of().ID);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_AIRCRAFT:\n\t\t\tCurAircraft++;\n\t\t\taircraft = ((AircraftTypeClass const &)techno->Class_Of()).Type;\n\t\t\tAQuantity[aircraft]++;\n\t\t\tAScan |= (1L << aircraft);\n\t\t\tif (Session.Type == GAME_INTERNET) {\n\t\t\t\tAircraftTotals->Increment_Unit_Total(techno->Class_Of().ID);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_INFANTRY:\n\t\t\tCurInfantry++;\n\t\t\tinfantry = ((InfantryTypeClass const &)techno->Class_Of()).Type;\n\t\t\tif (!((InfantryClass *)techno)->IsTechnician) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tquant = infantry;\n\t\t\t\tif (quant >= INFANTRY_RA_COUNT) quant -= INFANTRY_RA_COUNT;\n\t\t\t\tIQuantity[quant]++;\n#else\n\t\t\t\tIQuantity[infantry]++;\n#endif\n\t\t\t\tif (!((InfantryTypeClass const &)techno->Class_Of()).IsCivilian && Session.Type == GAME_INTERNET) {\n\t\t\t\t\tInfantryTotals->Increment_Unit_Total(techno->Class_Of().ID);\n\t\t\t\t}\n\t\t\t\tIScan |= (1L << infantry);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_UNIT:\n\t\t\tCurUnits++;\n\t\t\tunit = ((UnitTypeClass const &)techno->Class_Of()).Type;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tquant = unit;\n\t\t\tif (quant >= UNIT_RA_COUNT) quant -= UNIT_RA_COUNT;\n\t\t\tUQuantity[quant]++;\n#else\n\t\t\tUQuantity[unit]++;\n#endif\n\t\t\tUScan |= (1L << unit);\n\t\t\tif (Session.Type == GAME_INTERNET) {\n\t\t\t\tUnitTotals->Increment_Unit_Total(techno->Class_Of().ID);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\t\tCurVessels++;\n\t\t\tvessel = ((VesselTypeClass const &)techno->Class_Of()).Type;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tquant = vessel;\n\t\t\tif (quant >= VESSEL_RA_COUNT) quant -= VESSEL_RA_COUNT;\n\t\t\tVQuantity[quant]++;\n#else\n\t\t\tVQuantity[vessel]++;\n#endif\n\t\t\tVScan |= (1L << vessel);\n\t\t\tif (Session.Type == GAME_INTERNET) {\n\t\t\t\tVesselTotals->Increment_Unit_Total(techno->Class_Of().ID);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Factory_Counter -- Fetches a pointer to the factory counter value.              *\n *                                                                                             *\n *    Use this routine to fetch a pointer to the variable that holds the number of factories   *\n *    that can produce the specified object type. This is a helper routine used when           *\n *    examining the number of factories as well as adjusting their number.                     *\n *                                                                                             *\n * INPUT:   rtti  -- The RTTI of the object that could be produced.                            *\n *                                                                                             *\n * OUTPUT:  Returns with the number of factories owned by this house that could produce the    *\n *          object of the type specified.                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint * HouseClass::Factory_Counter(RTTIType rtti)\n{\n\tswitch (rtti) {\n\t\tcase RTTI_UNITTYPE:\n\t\tcase RTTI_UNIT:\n\t\t\treturn(&UnitFactories);\n\n\t\tcase RTTI_VESSELTYPE:\n\t\tcase RTTI_VESSEL:\n\t\t\treturn(&VesselFactories);\n\n\t\tcase RTTI_AIRCRAFTTYPE:\n\t\tcase RTTI_AIRCRAFT:\n\t\t\treturn(&AircraftFactories);\n\n\t\tcase RTTI_INFANTRYTYPE:\n\t\tcase RTTI_INFANTRY:\n\t\t\treturn(&InfantryFactories);\n\n\t\tcase RTTI_BUILDINGTYPE:\n\t\tcase RTTI_BUILDING:\n\t\t\treturn(&BuildingFactories);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Active_Remove -- Remove this object from active duty for this house.            *\n *                                                                                             *\n *    This routine will recognize the specified object as having been removed from active      *\n *    duty.                                                                                    *\n *                                                                                             *\n * INPUT:   techno   -- Pointer to the object to remove from active duty.                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Active_Remove(TechnoClass const * techno)\n{\n\tif (techno == NULL) return;\n\n\tif (techno->What_Am_I() == RTTI_BUILDING) {\n\t\tint * fptr = Factory_Counter(((BuildingClass *)techno)->Class->ToBuild);\n\t\tif (fptr != NULL) {\n\t\t\t*fptr = *fptr - 1;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Active_Add -- Add an object to active duty for this house.                      *\n *                                                                                             *\n *    This routine will recognize the specified object as having entered active duty. Any      *\n *    abilities granted to the house by that object are now available.                         *\n *                                                                                             *\n * INPUT:   techno   -- Pointer to the object that is entering active duty.                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Active_Add(TechnoClass const * techno)\n{\n\tif (techno == NULL) return;\n\n\tif (techno->What_Am_I() == RTTI_BUILDING) {\n\t\tint * fptr = Factory_Counter(((BuildingClass *)techno)->Class->ToBuild);\n\t\tif (fptr != NULL) {\n\t\t\t*fptr = *fptr + 1;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Which_Zone -- Determines what zone a coordinate lies in.                        *\n *                                                                                             *\n *    This routine will determine what zone the specified coordinate lies in with respect to   *\n *    this house's base. A location that is too distant from the base, even though it might    *\n *    be a building, is not considered part of the base and returns ZONE_NONE.                 *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to examine.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the base zone that the specified coordinate lies in.                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nZoneType HouseClass::Which_Zone(COORDINATE coord) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (coord == 0) return(ZONE_NONE);\n\n\tint distance = Distance(Center, coord);\n\tif (distance <= Radius) return(ZONE_CORE);\n\tif (distance > Radius*4) return(ZONE_NONE);\n\n\tDirType facing = Direction(Center, coord);\n\tif (facing < DIR_NE || facing > DIR_NW) return(ZONE_NORTH);\n\tif (facing >= DIR_NE && facing < DIR_SE) return(ZONE_EAST);\n\tif (facing >= DIR_SE && facing < DIR_SW) return(ZONE_SOUTH);\n\treturn(ZONE_WEST);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Which_Zone -- Determines which base zone the specified object lies in.          *\n *                                                                                             *\n *    Use this routine to determine what zone the specified object lies in.                    *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that will be checked for zone occupation.        *\n *                                                                                             *\n * OUTPUT:  Returns with the base zone that the object lies in. For objects that are too       *\n *          distant from the center of the base, ZONE_NONE is returned.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nZoneType HouseClass::Which_Zone(ObjectClass const * object) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (!object) return(ZONE_NONE);\n\treturn(Which_Zone(object->Center_Coord()));\n}\n\n\n/***********************************************************************************************\n * HouseClass::Which_Zone -- Determines which base zone the specified cell lies in.            *\n *                                                                                             *\n *    This routine is used to determine what base zone the specified cell is in.               *\n *                                                                                             *\n * INPUT:   cell  -- The cell to examine.                                                      *\n *                                                                                             *\n * OUTPUT:  Returns the base zone that the cell lies in or ZONE_NONE if the cell is too far    *\n *          away.                                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nZoneType HouseClass::Which_Zone(CELL cell) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(Which_Zone(Cell_Coord(cell)));\n}\n\n\n/***********************************************************************************************\n * HouseClass::Recalc_Attributes -- Recalcs all houses existence bits.                         *\n *                                                                                             *\n *    This routine will go through all game objects and reset the existence bits for the       *\n *    owning house. This method ensures that if the object exists, then the corresponding      *\n *    existence bit is also set.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Recalc_Attributes(void)\n{\n\t/*\n\t**\tClear out all tracking values that will be filled in by this\n\t**\troutine. This allows the filling in process to not worry about\n\t**\told existing values.\n\t*/\n\tfor (int index = 0; index < Houses.Count(); index++) {\n\t\tHouseClass * house = Houses.Ptr(index);\n\n\t\tif (house != NULL) {\n\t\t\thouse->BScan = 0;\n\t\t\thouse->ActiveBScan = 0;\n\t\t\thouse->IScan = 0;\n\t\t\thouse->ActiveIScan = 0;\n\t\t\thouse->UScan = 0;\n\t\t\thouse->ActiveUScan = 0;\n\t\t\thouse->AScan = 0;\n\t\t\thouse->ActiveAScan = 0;\n\t\t\thouse->VScan = 0;\n\t\t\thouse->ActiveVScan = 0;\n\t\t}\n\t}\n\n\t/*\n\t**\tA second pass through the sentient objects is required so that the appropriate scan\n\t**\tbits will be set for the owner house.\n\t*/\n\tfor (index = 0; index < Units.Count(); index++) {\n\t\tUnitClass const * unit = Units.Ptr(index);\n\t\tunit->House->UScan |= (1L << unit->Class->Type);\n\t\tif (unit->IsLocked && (Session.Type != GAME_NORMAL || !unit->House->IsHuman || unit->IsDiscoveredByPlayer)) {\n\t\t\tif (!unit->IsInLimbo) {\n\t\t\t\tunit->House->ActiveUScan |= (1L << unit->Class->Type);\n\t\t\t}\n\t\t}\n\t}\n\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\tInfantryClass const * infantry = Infantry.Ptr(index);\n\t\tinfantry->House->IScan |= (1L << infantry->Class->Type);\n\t\tif (infantry->IsLocked && (Session.Type != GAME_NORMAL || !infantry->House->IsHuman || infantry->IsDiscoveredByPlayer)) {\n\t\t\tif (!infantry->IsInLimbo) {\n\t\t\t\tinfantry->House->ActiveIScan |= (1L << infantry->Class->Type);\n\t\t\t\tinfantry->House->OldIScan |= (1L << infantry->Class->Type);\n\t\t\t}\n\t\t}\n\t}\n\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\tAircraftClass const * aircraft = Aircraft.Ptr(index);\n\t\taircraft->House->AScan |= (1L << aircraft->Class->Type);\n\t\tif (aircraft->IsLocked && (Session.Type != GAME_NORMAL || !aircraft->House->IsHuman || aircraft->IsDiscoveredByPlayer)) {\n\t\t\tif (!aircraft->IsInLimbo) {\n\t\t\t\taircraft->House->ActiveAScan |= (1L << aircraft->Class->Type);\n\t\t\t\taircraft->House->OldAScan |= (1L << aircraft->Class->Type);\n\t\t\t}\n\t\t}\n\t}\n\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\tBuildingClass const * building = Buildings.Ptr(index);\n\t\tif (building->Class->Type < 32) {\n\t\t\tbuilding->House->BScan |= (1L << building->Class->Type);\n\t\t\tif (building->IsLocked && (Session.Type != GAME_NORMAL || !building->House->IsHuman || building->IsDiscoveredByPlayer)) {\n\t\t\t\tif (!building->IsInLimbo) {\n\t\t\t\t\tbuilding->House->ActiveBScan |= (1L << building->Class->Type);\n\t\t\t\t\tbuilding->House->OldBScan |= (1L << building->Class->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\tVesselClass const * vessel = Vessels.Ptr(index);\n\t\tvessel->House->VScan |= (1L << vessel->Class->Type);\n\t\tif (vessel->IsLocked && (Session.Type != GAME_NORMAL || !vessel->House->IsHuman || vessel->IsDiscoveredByPlayer)) {\n\t\t\tif (!vessel->IsInLimbo) {\n\t\t\t\tvessel->House->ActiveVScan |= (1L << vessel->Class->Type);\n\t\t\t\tvessel->House->OldVScan |= (1L << vessel->Class->Type);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Zone_Cell -- Finds the cell closest to the center of the zone.                  *\n *                                                                                             *\n *    This routine is used to find the cell that is closest to the center point of the         *\n *    zone specified. Typical use of this routine is for building and unit placement so that   *\n *    they can \"cover\" the specified zone.                                                     *\n *                                                                                             *\n * INPUT:   zone  -- The zone that the center point is to be returned.                         *\n *                                                                                             *\n * OUTPUT:  Returns with the cell that is closest to the center point of the zone specified.   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL HouseClass::Zone_Cell(ZoneType zone) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tswitch (zone) {\n\t\tcase ZONE_CORE:\n\t\t\treturn(Coord_Cell(Center));\n\n\t\tcase ZONE_NORTH:\n\t\t\treturn(Coord_Cell(Coord_Move(Center, DIR_N, Radius*3)));\n\n\t\tcase ZONE_EAST:\n\t\t\treturn(Coord_Cell(Coord_Move(Center, DIR_E, Radius*3)));\n\n\t\tcase ZONE_WEST:\n\t\t\treturn(Coord_Cell(Coord_Move(Center, DIR_W, Radius*3)));\n\n\t\tcase ZONE_SOUTH:\n\t\t\treturn(Coord_Cell(Coord_Move(Center, DIR_S, Radius*3)));\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Where_To_Go -- Determines where the object should go and wait.                  *\n *                                                                                             *\n *    This function is called for every new unit produced or delivered in order to determine   *\n *    where the unit should \"hang out\" to await further orders. The best area for the          *\n *    unit to loiter is returned as a cell location.                                           *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that needs to know where to go.                  *\n *                                                                                             *\n * OUTPUT:  Returns with the cell that the unit should move to.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1995 JLB : Created.                                                                 *\n *   11/04/1996 JLB : Simplified to use helper functions                                       *\n *=============================================================================================*/\nCELL HouseClass::Where_To_Go(FootClass const * object) const\n{\n\tassert(Houses.ID(this) == ID);\n\tassert(object != NULL);\n\n\tZoneType zone;\t\t\t// The zone that the object should go to.\n\tif (object->Anti_Air() + object->Anti_Armor() + object->Anti_Infantry() == 0) {\n\t\tzone = ZONE_CORE;\n\t} else {\n\t\tzone = Random_Pick(ZONE_NORTH, ZONE_WEST);\n\t}\n\n\tCELL cell = Random_Cell_In_Zone(zone);\n\tassert(cell != 0);\n\n\treturn(Map.Nearby_Location(cell, SPEED_TRACK, Map[cell].Zones[MZONE_NORMAL], MZONE_NORMAL));\n}\n\n\n/***********************************************************************************************\n * HouseClass::Find_Juicy_Target -- Finds a suitable field target.                             *\n *                                                                                             *\n *    This routine is used to find targets out in the field and away from base defense.        *\n *    Typical of this would be the attack helicopters and the roving attack bands of           *\n *    hunter killers.                                                                          *\n *                                                                                             *\n * INPUT:   coord -- The coordinate of the attacker. Closer targets are given preference.      *\n *                                                                                             *\n * OUTPUT:  Returns with a suitable target to attack.                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/12/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTARGET HouseClass::Find_Juicy_Target(COORDINATE coord) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tUnitClass * best = 0;\n\tint value = 0;\n\n\tfor (int index = 0; index < Units.Count(); index++) {\n\t\tUnitClass * unit = Units.Ptr(index);\n\n\t\tif (unit && !unit->IsInLimbo && !Is_Ally(unit) && unit->House->Which_Zone(unit) == ZONE_NONE) {\n\t\t\tint val = Distance(coord, unit->Center_Coord());\n\n\t\t\tif (unit->Anti_Air()) val *= 2;\n\n\t\t\tif (*unit == UNIT_HARVESTER) val /= 2;\n\n\t\t\tif (value == 0 || val < value) {\n\t\t\t\tvalue = val;\n\t\t\t\tbest = unit;\n\t\t\t}\n\t\t}\n\t}\n\tif (best) {\n\t\treturn(best->As_Target());\n\t}\n\treturn(TARGET_NONE);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Get_Quantity -- Fetches the total number of aircraft of the specified type.     *\n *                                                                                             *\n *    Call this routine to fetch the total quantity of aircraft of the type specified that is  *\n *    owned by this house.                                                                     *\n *                                                                                             *\n * INPUT:   aircraft -- The aircraft type to check the quantity of.                            *\n *                                                                                             *\n * OUTPUT:  Returns with the total quantity of all aircraft of that type that is owned by this *\n *          house.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint  HouseClass::Get_Quantity(AircraftType aircraft)\n{\n\treturn(AQuantity[aircraft]);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Fetch_Factory -- Finds the factory associated with the object type specified.   *\n *                                                                                             *\n *    This is the counterpart to the Set_Factory function. It will return with a factory       *\n *    pointer that is associated with the object type specified.                               *\n *                                                                                             *\n * INPUT:   rtti  -- The RTTI of the object type to find the factory for.                      *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the factory (if present) that can manufacture the        *\n *          object type specified.                                                             *\n *                                                                                             *\n * WARNINGS:   If this returns a non-NULL pointer, then the factory is probably already busy   *\n *             producing another unit of that category.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nFactoryClass * HouseClass::Fetch_Factory(RTTIType rtti) const\n{\n\tint factory_index = -1;\n\n\tswitch (rtti) {\n\t\tcase RTTI_INFANTRY:\n\t\tcase RTTI_INFANTRYTYPE:\n\t\t\tfactory_index = InfantryFactory;\n\t\t\tbreak;\n\n\t\tcase RTTI_UNIT:\n\t\tcase RTTI_UNITTYPE:\n\t\t\tfactory_index = UnitFactory;\n\t\t\tbreak;\n\n\t\tcase RTTI_BUILDING:\n\t\tcase RTTI_BUILDINGTYPE:\n\t\t\tfactory_index = BuildingFactory;\n\t\t\tbreak;\n\n\t\tcase RTTI_AIRCRAFT:\n\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\tfactory_index = AircraftFactory;\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\tcase RTTI_VESSELTYPE:\n\t\t\tfactory_index = VesselFactory;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tfactory_index = -1;\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tFetch the actual pointer to the factory object. If there is\n\t**\tno object factory that matches the specified rtti type, then\n\t**\tnull is returned.\n\t*/\n\tif (factory_index != -1) {\n\t\treturn(Factories.Raw_Ptr(factory_index));\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Set_Factory -- Assign specified factory to house tracking.                      *\n *                                                                                             *\n *    Call this routine when a factory has been created and it now must be passed on to the    *\n *    house for tracking purposes. The house maintains several factory pointers and this       *\n *    routine will ensure that the factory pointer gets stored correctly.                      *\n *                                                                                             *\n * INPUT:   rtti  -- The RTTI of the object the factory it to manufacture.                     *\n *                                                                                             *\n *          factory  -- The factory object pointer.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Set_Factory(RTTIType rtti, FactoryClass * factory)\n{\n\tint * factory_index = 0;\n\n\tassert(rtti != RTTI_NONE);\n\n\tswitch (rtti) {\n\t\tcase RTTI_UNIT:\n\t\tcase RTTI_UNITTYPE:\n\t\t\tfactory_index = &UnitFactory;\n\t\t\tbreak;\n\n\t\tcase RTTI_INFANTRY:\n\t\tcase RTTI_INFANTRYTYPE:\n\t\t\tfactory_index = &InfantryFactory;\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\tcase RTTI_VESSELTYPE:\n\t\t\tfactory_index = &VesselFactory;\n\t\t\tbreak;\n\n\t\tcase RTTI_BUILDING:\n\t\tcase RTTI_BUILDINGTYPE:\n\t\t\tfactory_index = &BuildingFactory;\n\t\t\tbreak;\n\n\t\tcase RTTI_AIRCRAFT:\n\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\tfactory_index = &AircraftFactory;\n\t\t\tbreak;\n\t}\n\n\tassert(factory_index != NULL);\n\n\t/*\n\t**\tAssign the factory to the appropriate slot. For the case of clearing\n\t**\tthe factory out, then -1 is assigned.\n\t*/\n\tif (factory != NULL) {\n\t\t*factory_index = factory->ID;\n\t} else {\n\t\t*factory_index = -1;\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Factory_Count -- Fetches the number of factories for specified type.            *\n *                                                                                             *\n *    This routine will count the number of factories owned by this house that can build       *\n *    objects of the specified type.                                                           *\n *                                                                                             *\n * INPUT:   rtti  -- The type of object (RTTI) that the factories are to be counted for.       *\n *                                                                                             *\n * OUTPUT:  Returns with the number of factories that can build the object type specified.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint HouseClass::Factory_Count(RTTIType rtti) const\n{\n\tint const * ptr = ((HouseClass *)this)->Factory_Counter(rtti);\n\tif (ptr != NULL) {\n\t\treturn(*ptr);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Get_Quantity -- Gets the quantity of the building type specified.               *\n *                                                                                             *\n *    This will return the total number of buildings of that type owned by this house.         *\n *                                                                                             *\n * INPUT:   building -- The building type to check.                                            *\n *                                                                                             *\n * OUTPUT:  Returns with the number of buildings of that type owned by this house.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint  HouseClass::Get_Quantity(StructType building)\n{\n\treturn(BQuantity[building]);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Read_INI -- Reads house specific data from INI.                                 *\n *                                                                                             *\n *    This routine reads the house specific data for a particular                              *\n *    scenario from the scenario INI file. Typical data includes starting                      *\n *    credits, maximum unit count, etc.                                                        *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to loaded scenario INI file.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/24/1994 JLB : Created.                                                                 *\n *   05/18/1995 JLB : Creates all houses.                                                      *\n *=============================================================================================*/\nvoid HouseClass::Read_INI(CCINIClass & ini)\n{\n\tHouseClass \t* p;\t\t\t\t// Pointer to current player data.\n\tchar const\t* hname;\t\t\t//\tPointer to house name.\n\n\tfor (HousesType index = HOUSE_FIRST; index < HOUSE_COUNT; index++) {\n\t\thname = HouseTypeClass::As_Reference(index).IniName;\n\n\t\tp = new HouseClass(index);\n\t\tp->Control.TechLevel = ini.Get_Int(hname, \"TechLevel\", Scen.Scenario);\n\t\tp->Control.MaxBuilding = ini.Get_Int(hname, \"MaxBuilding\", p->Control.MaxBuilding);\n\t\tp->Control.MaxUnit = ini.Get_Int(hname, \"MaxUnit\", p->Control.MaxUnit);\n\t\tp->Control.MaxInfantry = ini.Get_Int(hname, \"MaxInfantry\", p->Control.MaxInfantry);\n\t\tp->Control.MaxVessel = ini.Get_Int(hname, \"MaxVessel\", p->Control.MaxVessel);\n\t\tif (p->Control.MaxVessel == 0) p->Control.MaxVessel = p->Control.MaxUnit;\n\t\tp->Control.InitialCredits = ini.Get_Int(hname, \"Credits\", 0) * 100;\n\t\tp->Credits = p->Control.InitialCredits;\n\n\t\tint iq = ini.Get_Int(hname, \"IQ\", 0);\n\t\tif (iq > Rule.MaxIQ) iq = 1;\n\t\tp->IQ = p->Control.IQ = iq;\n\n\t\tp->Control.Edge = ini.Get_SourceType(hname, \"Edge\", SOURCE_NORTH);\n\t\tp->IsPlayerControl = ini.Get_Bool(hname, \"PlayerControl\", false);\n\n\t\tint owners = ini.Get_Owners(hname, \"Allies\", (1 << HOUSE_NEUTRAL));\n\t\tp->Make_Ally(index);\n\t\tp->Make_Ally(HOUSE_NEUTRAL);\n\t\tfor (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\t\tif ((owners & (1 << h)) != 0) {\n\t\t\t\tp->Make_Ally(h);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Write_INI -- Writes the house data to the INI database.                         *\n *                                                                                             *\n *    This routine will write out all data necessary to recreate it in anticipation of a       *\n *    new scenario. All houses (that are active) will have their scenario type data written    *\n *    out.                                                                                     *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to write the data to.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Write_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tThe identity house control object. Only if the house value differs from the\n\t**\tidentity, will the data be written out.\n\t*/\n\tHouseStaticClass control;\n\n\tfor (HousesType i = HOUSE_FIRST; i < HOUSE_COUNT; i++) {\n\t\tHouseClass * p = As_Pointer(i);\n\n\t\tif (p != NULL) {\n\t\t\tchar const * name = p->Class->IniName;\n\n\t\t\tini.Clear(name);\n\t\t\tif (i >= HOUSE_MULTI1) continue;\n\n\t\t\tif (p->Control.InitialCredits != control.InitialCredits) {\n\t\t\t\tini.Put_Int(name, \"Credits\", (int)(p->Control.InitialCredits / 100));\n\t\t\t}\n\n\t\t\tif (p->Control.Edge != control.Edge) {\n\t\t\t\tini.Put_SourceType(name, \"Edge\", p->Control.Edge);\n\t\t\t}\n\n\t\t\tif (p->Control.MaxUnit > 0 && p->Control.MaxUnit != control.MaxUnit) {\n\t\t\t\tini.Put_Int(name, \"MaxUnit\", p->Control.MaxUnit);\n\t\t\t}\n\n\t\t\tif (p->Control.MaxInfantry > 0 && p->Control.MaxInfantry != control.MaxInfantry) {\n\t\t\t\tini.Put_Int(name, \"MaxInfantry\", p->Control.MaxInfantry);\n\t\t\t}\n\n\t\t\tif (p->Control.MaxBuilding > 0 && p->Control.MaxBuilding != control.MaxBuilding) {\n\t\t\t\tini.Put_Int(name, \"MaxBuilding\", p->Control.MaxBuilding);\n\t\t\t}\n\n\t\t\tif (p->Control.MaxVessel > 0 && p->Control.MaxVessel != control.MaxVessel) {\n\t\t\t\tini.Put_Int(name, \"MaxVessel\", p->Control.MaxVessel);\n\t\t\t}\n\n\t\t\tif (p->Control.TechLevel != control.TechLevel) {\n\t\t\t\tini.Put_Int(name, \"TechLevel\", p->Control.TechLevel);\n\t\t\t}\n\n\t\t\tif (p->Control.IQ != control.IQ) {\n\t\t\t\tini.Put_Int(name, \"IQ\", p->Control.IQ);\n\t\t\t}\n\n\t\t\tif (p->IsPlayerControl != false && p != PlayerPtr) {\n\t\t\t\tini.Put_Bool(name, \"PlayerControl\", p->IsPlayerControl);\n\t\t\t}\n\n\t\t\tini.Put_Owners(name, \"Allies\", p->Control.Allies & ~((1 << p->Class->House) | (1 << HOUSE_NEUTRAL)));\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Is_No_YakMig -- Determines if no more yaks or migs should be allowed.           *\n *                                                                                             *\n *    This routine will examine the current yak and mig situation verses airfields. If there   *\n *    are equal aircraft to airfields, then this routine will return TRUE.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Are all airfields full and thus no more yaks or migs are allowed?            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Is_No_YakMig(void) const\n{\n\tint quantity = AQuantity[AIRCRAFT_YAK] + AQuantity[AIRCRAFT_MIG];\n\n\t/*\n\t**\tAdjust the quantity down one if there is an aircraft in production. This will\n\t**\tallow production to resume after being held.\n\t*/\n\tFactoryClass const * factory = Fetch_Factory(RTTI_AIRCRAFT);\n\tif (factory != NULL && factory->Get_Object() != NULL) {\n\t\tAircraftClass const * air = (AircraftClass const *)factory->Get_Object();\n\t\tif (*air == AIRCRAFT_MIG || *air == AIRCRAFT_YAK) {\n\t\t\tquantity -= 1;\n\t\t}\n\t}\n\n\tif (quantity >= BQuantity[STRUCT_AIRSTRIP]) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Is_Hack_Prevented -- Is production of the specified type and id prohibted?      *\n *                                                                                             *\n *    This is a special hack check routine to see if the object type and id specified is       *\n *    prevented from being produced. The Yak and the Mig are so prevented if there would be    *\n *    insufficient airfields for them to land upon.                                            *\n *                                                                                             *\n * INPUT:   rtti  -- The RTTI type of the value specified.                                     *\n *                                                                                             *\n *          value -- The type number (according to the RTTI type specified).                   *\n *                                                                                             *\n * OUTPUT:  bool; Is production of this object prohibited?                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Is_Hack_Prevented(RTTIType rtti, int value) const\n{\n\tif (rtti == RTTI_AIRCRAFTTYPE && (value == AIRCRAFT_MIG || value == AIRCRAFT_YAK)) {\n\t\treturn(Is_No_YakMig());\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Fire_Sale -- Cause all buildings to be sold.                                    *\n *                                                                                             *\n *    This routine will sell back all buildings owned by this house.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was a fire sale performed?                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Fire_Sale(void)\n{\n\tif (CurBuildings > 0) {\n\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass * b = Buildings.Ptr(index);\n\n\t\t\tif (b != NULL && !b->IsInLimbo && b->House == this && b->Strength > 0) {\n\t\t\t\tb->Sell_Back(1);\n\t\t\t}\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Do_All_To_Hunt -- Send all units to hunt.                                       *\n *                                                                                             *\n *    This routine will cause all combatants of this house to go into hunt mode. The effect of *\n *    this is to throw everything this house has to muster at the enemies of this house.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/23/1996 JLB : Created.                                                                 *\n *   10/02/1996 JLB : Handles aircraft too.                                                    *\n *=============================================================================================*/\nvoid HouseClass::Do_All_To_Hunt(void) const\n{\n\tint index;\n\n\tfor (index = 0; index < Units.Count(); index++) {\n\t\tUnitClass * unit = Units.Ptr(index);\n\n\t\tif (unit->House == this && unit->IsDown && !unit->IsInLimbo) {\n\t\t\tif (unit->Team) unit->Team->Remove(unit);\n\t\t\tunit->Assign_Mission(MISSION_HUNT);\n\t\t}\n\t}\n\n\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\tInfantryClass * infantry = Infantry.Ptr(index);\n\n\t\tif (infantry->House == this && infantry->IsDown && !infantry->IsInLimbo) {\n\t\t\tif (infantry->Team) infantry->Team->Remove(infantry);\n\t\t\tinfantry->Assign_Mission(MISSION_HUNT);\n\t\t}\n\t}\n\n\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\tVesselClass * vessel = Vessels.Ptr(index);\n\n\t\tif (vessel->House == this && vessel->IsDown && !vessel->IsInLimbo) {\n\t\t\tif (vessel->Team) vessel->Team->Remove(vessel);\n\t\t\tvessel->Assign_Mission(MISSION_HUNT);\n\t\t}\n\t}\n\n\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\tAircraftClass * aircraft = Aircraft.Ptr(index);\n\n\t\tif (aircraft->House == this && aircraft->IsDown && !aircraft->IsInLimbo) {\n\t\t\tif (aircraft->Team) aircraft->Team->Remove(aircraft);\n\t\t\taircraft->Assign_Mission(MISSION_HUNT);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Is_Allowed_To_Ally -- Determines if this house is allied to make allies.        *\n *                                                                                             *\n *    Use this routine to determine if this house is legally allowed to ally with the          *\n *    house specified. There are many reason why an alliance is not allowed. Typically, this   *\n *    is when there would be no more opponents left to fight or if this house has been         *\n *    defeated.                                                                                *\n *                                                                                             *\n * INPUT:   house -- The house that alliance with is desired.                                  *\n *                                                                                             *\n * OUTPUT:  bool; Is alliance with the house specified prohibited?                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Is_Allowed_To_Ally(HousesType house) const\n{\n\t/*\n\t**\tIs not allowed to ally with a house that is patently invalid, such\n\t**\tas one that is illegally defined.\n\t*/\n\tif (house == HOUSE_NONE) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tOne cannot ally twice with the same house.\n\t*/\n\tif (Is_Ally(house)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the scenario is being set up, then alliances are always\n\t**\tallowed. No further checking is required.\n\t*/\n\tif (ScenarioInit) {\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tAlliances (outside of scneario init time) are allowed only if\n\t**\tthis is a multiplayer game. Otherwise, they are prohibited.\n\t*/\n\tif (Session.Type == GAME_NORMAL) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tWhen the house is defeated, it can no longer make alliances.\n\t*/\n\tif (IsDefeated) {\n\t\treturn(false);\n\t}\n\n#ifdef FIXIT_VERSION_3\n\t// Fix to prevent ally with computer.\n\tif ( !HouseClass::As_Pointer(house)->IsHuman) {\n\t\treturn(false);\n\t}\n#else\t//\tFIXIT_VERSION_3\n#ifdef FIXIT_NO_COMP_ALLY\n\t// Fix to prevent ally with computer.\n\tif (PlayingAgainstVersion > VERSION_RED_ALERT_104 && !HouseClass::As_Pointer(house)->IsHuman) {\n\t\treturn(false);\n\t}\n#endif\n#endif\t//\tFIXIT_VERSION_3\n\n\t/*\n\t**\tCount the number of active houses in the game as well as the\n\t**\tnumber of existing allies with this house.\n\t*/\n\tint housecount = 0;\n\tint allycount = 0;\n\tfor (HousesType house2 = HOUSE_MULTI1; house2 < HOUSE_COUNT; house2++) {\n\t\tHouseClass * hptr = HouseClass::As_Pointer(house2);\n\t\tif (hptr != NULL && hptr->IsActive && !hptr->IsDefeated) {\n\t\t\thousecount++;\n\t\t\tif (Is_Ally(hptr)) {\n\t\t\t\tallycount++;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tAlliance is not allowed if there wouldn't be any enemies left to\n\t**\tfight.\n\t*/\n\tif (housecount == allycount+1) {\n\t\treturn(false);\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Computer_Paranoid -- Cause the computer players to becom paranoid.              *\n *                                                                                             *\n *    This routine will cause the computer players to become suspicious of the human           *\n *    players and thus the computer players will band together in order to defeat the          *\n *    human players.                                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Computer_Paranoid(void)\n{\n\n\t/*\n\t**\tLoop through every computer controlled house and make allies with all other computer\n\t**\tcontrolled houses and then make enemies with all other human controlled houses.\n\t*/\n\tfor (HousesType house = HOUSE_MULTI1; house < HOUSE_COUNT; house++) {\n\t\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\t\tif (hptr != NULL && hptr->IsActive && !hptr->IsDefeated && !hptr->IsHuman) {\n\t\t\thptr->IsParanoid = true;\n\n\t\t\t/*\n\t\t\t**\tBreak alliance with every human it is allied with and make friends with\n\t\t\t**\tany other computer players.\n\t\t\t*/\n\t\t\tfor (HousesType house2 = HOUSE_MULTI1; house2 < HOUSE_COUNT; house2++) {\n\t\t\t\tHouseClass * hptr2 = HouseClass::As_Pointer(house2);\n\t\t\t\tif (hptr2 != NULL && hptr2->IsActive && !hptr2->IsDefeated) {\n\t\t\t\t\tif (hptr2->IsHuman) {\n\t\t\t\t\t\thptr->Make_Enemy(house2);\n\t\t\t\t\t} else {\n\t\t\t\t\t\thptr->Make_Ally(house2);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Adjust_Power -- Adjust the power value of the house.                            *\n *                                                                                             *\n *    This routine will update the power output value of the house. It will cause any buildgins*\n *    that need to be redrawn to do so.                                                        *\n *                                                                                             *\n * INPUT:   adjust   -- The amount to adjust the power output value.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/01/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Adjust_Power(int adjust)\n{\n\tPower += adjust;\n\n\tUpdate_Spied_Power_Plants();\n}\n\n\n/***********************************************************************************************\n * HouseClass::Adjust_Drain -- Adjust the power drain value of the house.                      *\n *                                                                                             *\n *    This routine will update the drain value of the house. It will cause any buildings that  *\n *    need to be redraw to do so.                                                              *\n *                                                                                             *\n * INPUT:   adjust   -- The amount to adjust the drain (positive means more drain).            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/01/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Adjust_Drain(int adjust)\n{\n\tDrain += adjust;\n\tUpdate_Spied_Power_Plants();\n}\n\n\n/***********************************************************************************************\n * HouseClass::Update_Spied_Power_Plants -- Redraw power graphs on spied-upon power plants.    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/11/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Update_Spied_Power_Plants(void)\n{\n\tint count = CurrentObject.Count();\n\tif (count) {\n\t\tfor (int index = 0; index < count; index++) {\n\t\t\tObjectClass const * tech = CurrentObject[index];\n\t\t\tif (tech && tech->What_Am_I()==RTTI_BUILDING) {\n\t\t\t\tBuildingClass *bldg = (BuildingClass *)tech;\n\t\t\t\tif (!bldg->IsOwnedByPlayer && *bldg == STRUCT_POWER || *bldg == STRUCT_ADVANCED_POWER) {\n\t\t\t\t\tif ( bldg->SpiedBy & (1<<(PlayerPtr->Class->House)) ) {\n\t\t\t\t\t\tbldg->Mark(MARK_CHANGE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Find_Cell_In_Zone -- Finds a legal placement cell within the zone.              *\n *                                                                                             *\n *    Use this routine to determine where the specified object should go if it were to go      *\n *    some random (but legal) location within the zone specified.                              *\n *                                                                                             *\n * INPUT:   techno   -- The object that is desirous of going into the zone specified.          *\n *                                                                                             *\n *          zone     -- The zone to find a location within.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the cell that the specified object could be placed in the zone. If    *\n *          no valid location could be found, then 0 is returned.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/01/1996 JLB : Created.                                                                 *\n *   11/04/1996 JLB : Not so strict on zone requirement.                                       *\n *=============================================================================================*/\nCELL HouseClass::Find_Cell_In_Zone(TechnoClass const * techno, ZoneType zone) const\n{\n\tif (techno == NULL) return(0);\n\n\tint bestval = -1;\n\tint bestcell = 0;\n\tTechnoTypeClass const * ttype = techno->Techno_Type_Class();\n\n\t/*\n\t**\tPick a random location within the zone specified.\n\t*/\n\tCELL trycell = Random_Cell_In_Zone(zone);\n\n\tshort const * list = NULL;\n\tif (techno->What_Am_I() == RTTI_BUILDING) {\n\t\tlist = techno->Occupy_List(true);\n\t}\n\n\t/*\n\t**\tFind a legal placement position as close as possible to the picked location while still\n\t**\tremaining within the zone.\n\t*/\n\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n//\t\tif (Map.In_Radar(cell)) {\n\t\tif (Map.In_Radar(cell) && Which_Zone(cell) != ZONE_NONE) {\n\t\t\tbool ok = ttype->Legal_Placement(cell);\n\n\t\t\t/*\n\t\t\t**\tAnother (adjacency) check is required for buildings.\n\t\t\t*/\n\t\t\tif (ok && list != NULL && !Map.Passes_Proximity_Check(ttype, techno->House->Class->House, list, cell)) {\n\t\t\t\tok = false;\n\t\t\t}\n\n\t\t\tif (ok) {\n\t\t\t\tint dist = Distance(Cell_Coord(cell), Cell_Coord(trycell));\n\t\t\t\tif (bestval == -1 || dist < bestval) {\n\t\t\t\t\tbestval = dist;\n\t\t\t\t\tbestcell = cell;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tReturn the best location to move to.\n\t*/\n\treturn(bestcell);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Random_Cell_In_Zone -- Find a (technically) legal cell in the zone specified.   *\n *                                                                                             *\n *    This routine will pick a random cell within the zone specified. The pick will be         *\n *    clipped to the map edge when necessary.                                                  *\n *                                                                                             *\n * INPUT:   zone  -- The zone to pick a cell from.                                             *\n *                                                                                             *\n * OUTPUT:  Returns with a picked cell within the zone. If the entire zone lies outside of the *\n *          map, then a cell in the core zone is returned instead.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL HouseClass::Random_Cell_In_Zone(ZoneType zone) const\n{\n\tCOORDINATE coord = 0;\n\tint maxdist = 0;\n\tswitch (zone) {\n\t\tcase ZONE_CORE:\n\t\t\tcoord = Coord_Scatter(Center, Random_Pick(0, Radius), true);\n\t\t\tbreak;\n\n\t\tcase ZONE_NORTH:\n\t\t\tmaxdist = min(Radius*3, (Coord_Y(Center) - Cell_To_Lepton(Map.MapCellY)) - CELL_LEPTON_H);\n\t\t\tif (maxdist < 0) break;\n\t\t\tcoord = Coord_Move(Center, (DirType)(Random_Pick(DIR_N, DIR_E)-((DirType)32)), Random_Pick(min(Radius*2, maxdist), min(Radius*3, maxdist)));\n\t\t\tbreak;\n\n\t\tcase ZONE_EAST:\n\t\t\tmaxdist = min(Radius*3, (Cell_To_Lepton(Map.MapCellX + Map.MapCellWidth) - Coord_X(Center)) - CELL_LEPTON_W);\n\t\t\tif (maxdist < 0) break;\n\t\t\tcoord = Coord_Move(Center, Random_Pick(DIR_NE, DIR_SE), Random_Pick(min(Radius*2, maxdist), min(Radius*3, maxdist)));\n\t\t\tbreak;\n\n\t\tcase ZONE_SOUTH:\n\t\t\tmaxdist = min(Radius*3, (Cell_To_Lepton(Map.MapCellY + Map.MapCellHeight) - Coord_Y(Center)) - CELL_LEPTON_H);\n\t\t\tif (maxdist < 0) break;\n\t\t\tcoord = Coord_Move(Center, Random_Pick(DIR_SE, DIR_SW), Random_Pick(min(Radius*2, maxdist), min(Radius*3, maxdist)));\n\t\t\tbreak;\n\n\t\tcase ZONE_WEST:\n\t\t\tmaxdist = min(Radius*3, (Coord_X(Center) - Cell_To_Lepton(Map.MapCellX)) - CELL_LEPTON_W);\n\t\t\tif (maxdist < 0) break;\n\t\t\tcoord = Coord_Move(Center, Random_Pick(DIR_SW, DIR_NW), Random_Pick(min(Radius*2, maxdist), min(Radius*3, maxdist)));\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tDouble check that the location is valid and if so, convert it into a cell\n\t**\tnumber.\n\t*/\n\tCELL cell;\n\tif (coord == 0 || !Map.In_Radar(Coord_Cell(coord))) {\n\t\tif (zone == ZONE_CORE) {\n\n\t\t\t/*\n\t\t\t**\tFinding a cell within the core failed, so just pick the center\n\t\t\t**\tcell. This cell is guaranteed to be valid.\n\t\t\t*/\n\t\t\tcell = Coord_Cell(Center);\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf the edge fails, then try to find a cell within the core.\n\t\t\t*/\n\t\t\tcell = Random_Cell_In_Zone(ZONE_CORE);\n\t\t}\n\t} else {\n\t\tcell = Coord_Cell(coord);\n\t}\n\n\t/*\n\t**\tIf the randomly picked location is not in the legal map area, then clip it to\n\t**\tthe legal map area.\n\t*/\n\tif (!Map.In_Radar(cell)) {\n\t\tint x = Cell_X(cell);\n\t\tint y = Cell_Y(cell);\n\n\t\tif (x < Map.MapCellX) x = Map.MapCellX;\n\t\tif (y < Map.MapCellY) y = Map.MapCellY;\n\t\tif (x >= Map.MapCellX + Map.MapCellWidth) x = Map.MapCellX + Map.MapCellWidth -1;\n\t\tif (y >= Map.MapCellY + Map.MapCellHeight) y = Map.MapCellY + Map.MapCellHeight -1;\n\t\tcell = XY_Cell(x, y);\n\t}\n\treturn(cell);\n}\n"
  },
  {
    "path": "CODE/HOUSE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/HOUSE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HOUSE.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 21, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 21, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef HOUSE_H\n#define HOUSE_H\n\n#include\t\"type.h\"\n#include\t\"region.h\"\n#include\t\"vector.h\"\n\nclass TriggerClass;\nclass FootClass;\nclass FactoryClass;\n\n#define HOUSE_NAME_MAX\t12\n\n\n/****************************************************************************\n**\tCertain aspects of the house \"country\" are initially set by the scenario\n**\tcontrol file. This information is static for the duration of the current\n**\tscenario, but is dynamic between scenarios. As such, it can't be placed in\n**\tthe static HouseTypeClass structure, but is embedded into the house\n**\tclass instead.\n*/\nclass HouseStaticClass {\n\tpublic:\n\t\tHouseStaticClass(void);\n\t\tHouseStaticClass(NoInitClass const & ) {};\n\n\t\t/*\n\t\t**\tThis value indicates the degree of smartness to assign to this house.\n\t\t**\tA value is zero is presumed for human controlled houses.\n\t\t*/\n\t\tint IQ;\n\n\t\t/*\n\t\t**\tThis is the buildable tech level for this house. This value is used\n\t\t**\tfor when the computer is deciding what objects to build.\n\t\t*/\n\t\tint TechLevel;\n\n\t\t/*\n\t\t**\tThis is the original ally specification to use at scenario\n\t\t**\tstart. Various forces during play may adjust the ally state\n\t\t**\tof this house.\n\t\t*/\n\t\tint Allies;\n\n\t\t/*\n\t\t**\tThis is the maximum number allowed to be built by this house. The\n\t\t**\tvalue depends on the scenario being played.\n\t\t*/\n\t\tunsigned MaxUnit;\n\t\tunsigned MaxBuilding;\n\t\tunsigned MaxInfantry;\n\t\tunsigned MaxVessel;\n\t\tunsigned MaxAircraft;\n\n\t\t/*\n\t\t**\tThis records the initial credits assigned to this house when the scenario\n\t\t**\twas loaded.\n\t\t*/\n\t\tlong InitialCredits;\n\n\t\t/*\n\t\t**\tFor generic (unspecified) reinforcements, they arrive by a common method. This\n\t\t**\tspecifies which method is to be used.\n\t\t*/\n\t\tSourceType Edge;\n};\n\n\n/****************************************************************************\n**\tPlayer control structure. Each player (computer or human) has one of\n**\tthese structures associated. These are located in a global array.\n*/\nclass HouseClass {\n\tpublic:\n\t\tRTTIType RTTI;\n\t\tint ID;\n\n\t\t/*\n\t\t**\tPointer to the HouseTypeClass that this house is \"owned\" by.\n\t\t**\tAll constant data for a house type is stored in that class.\n\t\t*/\n\t\tCCPtr<HouseTypeClass> Class;\n\n\t\t/*\n\t\t**\tThis is the handicap (difficulty level) assigned to this house.\n\t\t*/\n\t\tDiffType Difficulty;\n\n\t\t/*\n\t\t**\tOverride handicap control values.\n\t\t*/\n\t\tfixed FirepowerBias;\n\t\tfixed GroundspeedBias;\n\t\tfixed AirspeedBias;\n\t\tfixed ArmorBias;\n\t\tfixed ROFBias;\n\t\tfixed CostBias;\n\t\tfixed BuildSpeedBias;\n\t\tfixed RepairDelay;\n\t\tfixed BuildDelay;\n\n\t\t/*\n\t\t**\tThe initial house data as loaded from the scenario control file is\n\t\t**\tstored here. Although this data changes for each scenario, it remains\n\t\t**\tstatic for the duration of the current scenario.\n\t\t*/\n\t\tHouseStaticClass Control;\n\n\t\t/*\n\t\t**\tThis is the house type that this house object should act like. This\n\t\t**\tvalue controls production choices and radar cover plate imagery.\n\t\t*/\n\t\tHousesType ActLike;\n\n\t\t/*\n\t\t**\tIs this player active?  Usually that answer is true, but for civilians, it\n\t\t**\tmight possibly be false.\n\t\t*/\n\t\tunsigned IsActive:1;\n\n\t\t/*\n\t\t**\tIf this house is controlled by the player, then this flag will be true. The\n\t\t**\tcomputer controls all other active houses.\n\t\t*/\n\t\tunsigned IsHuman:1;\n\n\t\t/*\n\t\t**\tIf the player can control units of this house even if the player doesn't\n\t\t**\town units of this house, then this flag will be true.\n\t\t*/\n\t\tunsigned IsPlayerControl:1;\n\n\t\t/*\n\t\t**\tThis flag enables production. If the flag is false, production is disabled.\n\t\t**\tBy timing when this flag gets set, the player can be given some breathing room.\n\t\t*/\n\t\tunsigned IsStarted:1;\n\n\t\t/*\n\t\t**\tWhen alerted, the house will create teams of the special \"auto\" type and\n\t\t**\twill generate appropriate units to fill those team types.\n\t\t*/\n\t\tunsigned IsAlerted:1;\n\n\t\t/*\n\t\t**\tIf automatic base building is on, then this flag will be set to true.\n\t\t*/\n\t\tunsigned IsBaseBuilding:1;\n\n\t\t/*\n\t\t**\tIf the house has been discovered, then this flag will be set\n\t\t**\tto true. However, the trigger even associated with discovery\n\t\t**\twill only be executed during the next house AI process.\n\t\t*/\n\t\tunsigned IsDiscovered:1;\n\n\t\t/*\n\t\t**\tIf Tiberium storage is maxed out, then this flag will be set. At some point\n\t\t**\tthe player is told of this fact and then this flag is cleared. This allows the\n\t\t**\tplayer to be told, but only occasionally rather than continuously.\n\t\t*/\n\t\tunsigned IsMaxedOut:1;\n\n\t\t/*\n\t\t** If this house is played by a human in a multiplayer game, this flag\n\t\t** keeps track of whether this house has been defeated or not.\n\t\t*/\n\t\tunsigned IsDefeated:1;\n\n\t\t/*\n\t\t**\tThese flags are used in conjunction with the BorrowedTime timer. When\n\t\t**\tthat timer expires and one of these flags are set, then that event is\n\t\t**\tapplied to the house. This allows a dramatic pause between the event\n\t\t**\ttrigger and the result.\n\t\t*/\n\t\tunsigned IsToDie:1;\n\t\tunsigned IsToWin:1;\n\t\tunsigned IsToLose:1;\n\n\t\t/*\n\t\t**\tThis flag is set when a transport carrying a civilian has been\n\t\t**\tsuccessfully evacuated. It is presumed that a possible trigger\n\t\t**\tevent will be sprung by this event.\n\t\t*/\n\t\tunsigned IsCivEvacuated:1;\n\n\t\t/*\n\t\t**\tIf potentially something changed that might affect the sidebar list of\n\t\t**\tbuildable objects, then this flag indicates that at the first LEGAL opportunity,\n\t\t**\tthe sidebar will be recalculated.\n\t\t*/\n\t\tunsigned IsRecalcNeeded:1;\n\n\t\t/*\n\t\t**\tIf the map has been completely revealed to the player, then this flag\n\t\t**\twill be set to true. By examining this flag, a second \"reveal all map\"\n\t\t**\tcrate won't be given to the player.\n\t\t*/\n\t\tunsigned IsVisionary:1;\n\n\t\t/*\n\t\t**\tThis flag is set to true when the house has determined that\n\t\t**\tthere is insufficient Tiberium to keep the harvesters busy.\n\t\t**\tIn such a case, the further refinery/harvester production\n\t\t**\tshould cease. This is one of the first signs that the endgame\n\t\t**\thas begun.\n\t\t*/\n\t\tunsigned IsTiberiumShort:1;\n\n\t\t/*\n\t\t**\tThese flags are used for the general house trigger events of being\n\t\t**\tspied and thieved. The appropriate flag will be set when the event\n\t\t**\toccurs.\n\t\t*/\n\t\tunsigned IsSpied:1;\n\t\tunsigned IsThieved:1;\n\n\t\t/*\n\t\t** This flag is used to control non-human repairing of buildings.  Each\n\t\t** house gets to repair one building per loop, and this flag controls\n\t\t** whether this house has 'spent' its repair option this time through.\n\t\t*/\n\t\tunsigned DidRepair:1;\n\n\t\t/*\n\t\t** This flag is used to control whether or not this house has the GPS\n\t\t** satellite in orbit.  If the satellite's there, they have unlimited\n\t\t** radar and the map is fully revealed.\n\t\t*/\n\t\tunsigned IsGPSActive:1;\n\n\t\t/*\n\t\t**\tIf the JustBuilt??? variable has changed, then this flag will\n\t\t**\tbe set to true.\n\t\t*/\n\t\tunsigned IsBuiltSomething:1;\n\n\t\t/*\n\t\t** Did this house lose via resignation?\n\t\t*/\n\t\tunsigned IsResigner:1;\n\n\t\t/*\n\t\t** Did this house lose because the player quit?\n\t\t*/\n\t\tunsigned IsGiverUpper:1;\n\n\t\t/*\n\t\t**\tIf this computer controlled house has reason to be mad at humans,\n\t\t**\tthen this flag will be true. Such a condition prevents alliances with\n\t\t**\ta human and encourages the computers players to ally amongst themselves.\n\t\t*/\n\t\tunsigned IsParanoid:1;\n\n\t\t/*\n\t\t**\tA gap generator shrouded cells and all units of this house must perform\n\t\t**\ta look just in case their look radius intersects the shroud area.\n\t\t*/\n\t\tunsigned IsToLook:1;\n\n\t\t/*\n\t\t**\tThis value indicates the degree of smartness to assign to this house.\n\t\t**\tA value of zero indicates that the player controls everything.\n\t\t*/\n\t\tint IQ;\n\n\t\t/*\n\t\t**\tThis records the current state of the base. This state is used to control\n\t\t**\twhat action the base will perform and directly affects production and\n\t\t**\tunit disposition. The state will change according to time and combat\n\t\t**\tevents.\n\t\t*/\n\t\tStateType State;\n\n\t\t/*\n\t\t**\tThese super weapon control objects are used to control the recharge\n\t\t**\tand availability of these special weapons to this house.\n\t\t*/\n\t\tSuperClass SuperWeapon[SPC_COUNT];\n\n\t\t/*\n\t\t**\tThis is a record of the last building that was built. For buildings that\n\t\t**\twere built as a part of scenario creation, it will be the last one\n\t\t**\tdiscovered.\n\t\t*/\n\t\tStructType JustBuiltStructure;\n\t\tInfantryType JustBuiltInfantry;\n\t\tUnitType JustBuiltUnit;\n\t\tAircraftType JustBuiltAircraft;\n\t\tVesselType JustBuiltVessel;\n\n\t\t/*\n\t\t**\tThis records the number of triggers associated with this house that are\n\t\t**\tblocking a win condition. A win will only occur if all the blocking\n\t\t**\ttriggers have been deleted.\n\t\t*/\n\t\tint Blockage;\n\n\t\t/*\n\t\t**\tFor computer controlled houses, there is an artificial delay between\n\t\t**\tperforming repair actions. This timer regulates that delay. If the\n\t\t**\ttimer has not expired, then no repair initiation is allowed.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> RepairTimer;\n\n\t\t/*\n\t\t**\tThis timer controls the computer auto-attack logic. When this timer expires\n\t\t**\tand the house has been alerted, then it will create a set of attack\n\t\t**\tteams.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> AlertTime;\n\n\t\t/*\n\t\t**\tThis timer is used to handle the delay between some catastrophic\n\t\t**\tevent trigger and when it is actually carried out.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> BorrowedTime;\n\n\t\t/*\n\t\t**\tThis is the last working scan bits for buildings. If a building is\n\t\t**\tactive and owned by this house, it will have a bit set in this element\n\t\t**\tthat corresponds to the building type number. Since this value is\n\t\t**\taccumulated over time, the \"New\" element contains the under-construction\n\t\t**\tversion.\n\t\t*/\n\t\tunsigned long BScan;\n\t\tunsigned long ActiveBScan;\n\t\tunsigned long OldBScan;\n\n\t\t/*\n\t\t**\tThis is the last working scan bits for units. For every existing unit\n\t\t**\ttype owned by this house, a corresponding bit is set in this element. As\n\t\t**\tthe scan bits are being constructed, they are built into the \"New\" element\n\t\t**\tand then duplicated into the regular element at the end of every logic cycle.\n\t\t*/\n\t\tunsigned long UScan;\n\t\tunsigned long ActiveUScan;\n\t\tunsigned long OldUScan;\n\n\t\t/*\n\t\t**\tInfantry type existence bits. Similar to unit and building bits.\n\t\t*/\n\t\tunsigned long IScan;\n\t\tunsigned long ActiveIScan;\n\t\tunsigned long OldIScan;\n\n\t\t/*\n\t\t**\tAircraft type existence bits. Similar to unit and building bits.\n\t\t*/\n\t\tunsigned long AScan;\n\t\tunsigned long ActiveAScan;\n\t\tunsigned long OldAScan;\n\n\t\t/*\n\t\t**\tVessel type existence bits. Similar to unit and building bits.\n\t\t*/\n\t\tunsigned long VScan;\n\t\tunsigned long ActiveVScan;\n\t\tunsigned long OldVScan;\n\n\t\t/*\n\t\t**\tRecord of gains and losses for this house during the course of the\n\t\t**\tscenario.\n\t\t*/\n\t\tunsigned CreditsSpent;\n\t\tunsigned HarvestedCredits;\n\t\tint StolenBuildingsCredits;\n\n\t\t/*\n\t\t**\tThis is the running count of the number of units owned by this house. This\n\t\t**\tvalue is used to keep track of ownership limits.\n\t\t*/\n\t\tunsigned CurUnits;\n\t\tunsigned CurBuildings;\n\t\tunsigned CurInfantry;\n\t\tunsigned CurVessels;\n\t\tunsigned CurAircraft;\n\n\t\t/*\n\t\t**\tThis is the running total of the number of credits this house has accumulated.\n\t\t*/\n\t\tlong Tiberium;\n\t\tlong Credits;\n\t\tlong Capacity;\n\n\t\t/*\n\t\t** Stuff to keep track of the total number of units built by this house.\n\t\t*/\n\t\tUnitTrackerClass * AircraftTotals;\n\t\tUnitTrackerClass * InfantryTotals;\n\t\tUnitTrackerClass * UnitTotals;\n\t\tUnitTrackerClass * BuildingTotals;\n\t\tUnitTrackerClass * VesselTotals;\n\n\t\t/*\n\t\t** Total number of units destroyed by this house\n\t\t*/\n\t\tUnitTrackerClass * DestroyedAircraft;\n\t\tUnitTrackerClass * DestroyedInfantry;\n\t\tUnitTrackerClass * DestroyedUnits;\n\t\tUnitTrackerClass * DestroyedBuildings;\n\t\tUnitTrackerClass * DestroyedVessels;\n\n\t\t/*\n\t\t** Total number of enemy buildings captured by this house\n\t\t*/\n\t\tUnitTrackerClass * CapturedBuildings;\n\n\t\t/*\n\t\t** Total number of crates found by this house\n\t\t*/\n\t\tUnitTrackerClass * TotalCrates;\n\n\t\t/*\n\t\t**\tRecords the number of infantry and vehicle factories active. This value is\n\t\t**\tused to regulate the speed of production.\n\t\t*/\n\t\tint AircraftFactories;\n\t\tint InfantryFactories;\n\t\tint UnitFactories;\n\t\tint VesselFactories;\n\t\tint BuildingFactories;\n\n\t\t/*\n\t\t**\tThis is the accumulation of the total power and drain factors. From these\n\t\t**\tvalues a ratio can be derived. This ratio is used to control the rate\n\t\t**\tof building decay.\n\t\t*/\n\t\tint Power;\t\t\t\t\t// Current power output.\n\t\tint Drain;\t\t\t\t\t// Power consumption.\n\n\t\t/*\n\t\t**\tFor human controlled houses, only one type of unit can be produced\n\t\t**\tat any one instant. These factory objects control this production.\n\t\t*/\n\t\tint AircraftFactory;\n\t\tint InfantryFactory;\n\t\tint UnitFactory;\n\t\tint VesselFactory;\n\t\tint BuildingFactory;\n\n\t\t/*\n\t\t**\tThis target value specifies where the flag is located. It might be a cell\n\t\t**\tor it might be an object.\n\t\t*/\n\t\tTARGET FlagLocation;\n\n\t\t/*\n\t\t** This is the flag-home-cell for this house.  This is where we must bring\n\t\t** another house's flag back to, to defeat that house.\n\t\t*/\n\t\tCELL FlagHome;\n\n\t\t/*\n\t\t** For multiplayer games, each house needs to keep track of how many\n\t\t** objects of each other house they've killed.\n\t\t*/\n\t\tunsigned UnitsKilled[HOUSE_COUNT];\n\t\tunsigned UnitsLost;\n\t\tunsigned BuildingsKilled[HOUSE_COUNT];\n\t\tunsigned BuildingsLost;\n\n\t\t/*\n\t\t** This keeps track of the last house to destroy one of my units.\n\t\t** It's used for scoring multiplayer games.\n\t\t*/\n\t\tHousesType WhoLastHurtMe;\n\n\t\t/*\n\t\t**\tThis records information about the location and size of\n\t\t**\tthe base.\n\t\t*/\n\t\tCOORDINATE Center;\t\t\t// Center of the base.\n\t\tint Radius;\t\t\t\t// Average building distance from center (leptons).\n\t\tstruct {\n\t\t\tint AirDefense;\n\t\t\tint ArmorDefense;\n\t\t\tint InfantryDefense;\n\t\t} ZoneInfo[ZONE_COUNT];\n\n\t\t/*\n\t\t**\tThis records information about the last time a building of this\n\t\t**\tside was attacked. This information is used to determine proper\n\t\t**\tresponse.\n\t\t*/\n\t\tint LATime;\t\t\t\t\t\t// Time of attack.\n\t\tRTTIType LAType;\t\t\t\t// Type of attacker.\n\t\tZoneType LAZone;\t\t\t\t// Last zone that was attacked.\n\t\tHousesType LAEnemy;\t\t\t// Owner of attacker.\n\n\t\t/*\n\t\t**\tThis target value is the building that must be captured as soon as possible.\n\t\t**\tTypically, this will be one of the buildings of this house that has been\n\t\t**\tcaptured and needs to be recaptured.\n\t\t*/\n\t\tTARGET ToCapture;\n\n\t\t/*\n\t\t** This value shows who is spying on this house's radar facilities.\n\t\t** This is used for the other side to be able to update their radar\n\t\t** map based on the cells that this house's units reveal.\n\t\t*/\n\t\tint RadarSpied;\n\n\t\t/*\n\t\t** Running score, based on units destroyed and units lost.\n\t\t*/\n\t\tint PointTotal;\n\n\t\t/*\n\t\t**\tThis is the targeting directions for when this house gets a\n\t\t**\tspecial weapon.\n\t\t*/\n\t\tQuarryType PreferredTarget;\n\n\tprivate:\n\t\t/*\n\t\t**\tTracks number of each building type owned by this house. Even if the\n\t\t**\tbuilding is in construction, it will be reflected in this total.\n\t\t*/\n#ifdef FIXIT_ANTS\n\t\tint BQuantity[STRUCT_COUNT-3];\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tint UQuantity[UNIT_RA_COUNT-3];\n#else\n\t\tint UQuantity[UNIT_COUNT-3];\n#endif\n#else\n\t\tint BQuantity[STRUCT_COUNT];\n\t\tint UQuantity[UNIT_COUNT];\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tint IQuantity[INFANTRY_RA_COUNT];\n#else\n\t\tint IQuantity[INFANTRY_COUNT];\n#endif\n\t\tint AQuantity[AIRCRAFT_COUNT];\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tint VQuantity[VESSEL_RA_COUNT];\n#else\n\t\tint VQuantity[VESSEL_COUNT];\n#endif\n\n\t\t/*\n\t\t**\tThis timer keeps track of when an all out attack should be performed.\n\t\t**\tWhen this timer expires, send most of this house's units in an\n\t\t**\tattack.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> Attack;\n\n\tpublic:\n\t\t/*\n\t\t**\tThis records the overriding enemy that the computer will try to\n\t\t**\tdestroy. Typically, this is the last house to attack, but can be\n\t\t**\tinfluenced by nearness.\n\t\t*/\n\t\tHousesType Enemy;\n\n\t\t/*\n\t\t**\tThe house expert system is regulated by this timer. Each computer controlled\n\t\t**\thouse will process the Expert System AI at intermittent intervals. Not only will\n\t\t**\tthis distribute the overhead more evenly, but will add variety to play.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> AITimer;\n\n\t\t/*\n\t\t** For the moebius effect, this is a pointer to the unit that we\n\t\t** selected to teleport.  Only one teleporter should be active per house.\n\t\t*/\n\t\tTARGET UnitToTeleport;\n\n\t\t/*\n\t\t**\tThis elaborates the suggested objects to construct. When the specified object\n\t\t**\tis constructed, then this corresponding value will be reset to nill state. The\n\t\t**\texpert system decides what should be produced, and then records the\n\t\t**\trecommendation in these variables.\n\t\t*/\n\t\tStructType BuildStructure;\n\t\tUnitType BuildUnit;\n\t\tInfantryType BuildInfantry;\n\t\tAircraftType BuildAircraft;\n\t\tVesselType BuildVessel;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\t\tHouseClass(HousesType house);\n\t\tHouseClass(NoInitClass const & x) : Class(x), Control(x), AlertTime(x), BorrowedTime(x), Attack(x), AITimer(x), DamageTime(x), TeamTime(x), TriggerTime(x), SpeakAttackDelay(x), SpeakPowerDelay(x), SpeakMoneyDelay(x), SpeakMaxedDelay(x) {};\n\t\t~HouseClass(void);\n\t\toperator HousesType(void) const;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tCELL Random_Cell_In_Zone(ZoneType zone) const;\n\t\tstatic void Computer_Paranoid(void);\n\t\tbool Is_Allowed_To_Ally(HousesType house) const;\n\t\tvoid Do_All_To_Hunt(void) const;\n\t\tvoid Super_Weapon_Handler(void);\n\t\tint * Factory_Counter(RTTIType rtti);\n\t\tint Factory_Count(RTTIType rtti) const;\n\t\tDiffType Assign_Handicap(DiffType handicap);\n\t\tTARGET Find_Juicy_Target(COORDINATE coord) const;\n\t\tvoid Print_Zone_Stats(int x, int y, ZoneType zone, MonoClass * mono) const;\n\t\tCELL Where_To_Go(FootClass const * object) const;\n\t\tCELL Zone_Cell(ZoneType zone) const;\n\t\tZoneType Which_Zone(COORDINATE coord) const;\n\t\tZoneType Which_Zone(ObjectClass const * object) const;\n\t\tZoneType Which_Zone(CELL cell) const;\n\t\tCELL Find_Cell_In_Zone(TechnoClass const * techno, ZoneType zone) const;\n\t\tProdFailType Begin_Production(RTTIType type, int id);\n\t\tProdFailType Suspend_Production(RTTIType type);\n\t\tProdFailType Abandon_Production(RTTIType type);\n\t\tbool Place_Object(RTTIType type, CELL cell);\n\t\tbool Manual_Place(BuildingClass * builder, BuildingClass * object);\n\t\tvoid Special_Weapon_AI(SpecialWeaponType id);\n\t\tbool Place_Special_Blast(SpecialWeaponType id, CELL cell);\n\t\tbool Flag_Attach(CELL cell, bool set_home = false);\n\t\tbool Flag_Attach(UnitClass * object, bool set_home = false);\n\t\tbool Flag_Remove(TARGET target, bool set_home = false);\n\t\tvoid Init_Data(PlayerColorType color, HousesType house, int credits);\n\t\tCOORDINATE Find_Build_Location(BuildingClass * building) const;\n\t\tBuildingClass * Find_Building(StructType type, ZoneType zone=ZONE_NONE) const;\n\t\tchar const * Name(void) const {return(Class->Name());}\n\n\t\tbool Fire_Sale(void);\n\t\tbool Is_Hack_Prevented(RTTIType rtti, int value) const;\n\t\tbool Is_No_YakMig(void) const;\n\t\tint Expert_AI(void);\n\t\tvoid Production_Begun(TechnoClass const * rtti);\n\t\tvoid Sell_Wall(CELL cell);\n\t\tbool Flag_To_Die(void);\n\t\tbool Flag_To_Win(void);\n\t\tbool Flag_To_Lose(void);\n\t\tvoid Make_Ally(HousesType house);\n\t\tvoid Make_Ally(ObjectClass * object) {if (object) Make_Ally(object->Owner());};\n\t\tvoid Make_Enemy(HousesType house);\n\t\tvoid Make_Enemy(ObjectClass * object) {if (object) Make_Enemy(object->Owner());};\n\t\tbool Is_Ally(HousesType house) const;\n\t\tbool Is_Ally(HouseClass const * house) const;\n\t\tbool Is_Ally(ObjectClass const * object) const;\n\t\t#ifdef CHEAT_KEYS\n\t\tvoid Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\t\tvoid AI(void);\n\t\tbool Can_Build(RTTIType rtti, int type, HousesType house) const;\n\n\t\t// Factory controls.\n\t\tFactoryClass * Fetch_Factory(RTTIType rtti) const;\n\t\tvoid Set_Factory(RTTIType rtti, FactoryClass * factory);\n\n\t\tbool Can_Build(ObjectTypeClass const * type, HousesType house) const;\n\n\t\tint  Get_Quantity(AircraftType aircraft);\n\t\tint  Get_Quantity(StructType building);\n\t\tunsigned char const * Remap_Table(bool blushing=false, RemapType remap=REMAP_NORMAL) const;\n\n\t\tTechnoTypeClass const * Suggest_New_Object(RTTIType objectype, bool kennel=false) const;\n\t\tBuildingTypeClass const * Suggest_New_Building(void) const;\n\t\tvoid Recalc_Center(void);\n\t\tbool Does_Enemy_Building_Exist(StructType) const;\n\t\tvoid Harvested(unsigned tiberium);\n\t\tvoid Stole(unsigned worth);\n\t\tlong Available_Money(void) const;\n\t\tvoid Spend_Money(unsigned money);\n\t\tvoid Refund_Money(unsigned money);\n\t\tvoid Attacked(void);\n\t\tvoid Adjust_Power(int adjust);\n\t\tvoid Adjust_Drain(int adjust);\n\t\tvoid Update_Spied_Power_Plants(void);\n\t\tint Adjust_Capacity(int adjust, bool inanger=false);\n\t\tfixed Power_Fraction(void) const;\n\t\tfixed Tiberium_Fraction(void) const;\n\t\tvoid Begin_Production(void) {IsStarted = true;};\n\t\tTeamTypeClass const * Suggested_New_Team(bool alertcheck = false);\n\t\tvoid Adjust_Threat(int region, int threat);\n\t\tvoid Tracking_Remove(TechnoClass const * techno);\n\t\tvoid Tracking_Add(TechnoClass const * techno);\n\t\tvoid Active_Remove(TechnoClass const * techno);\n\t\tvoid Active_Add(TechnoClass const * techno);\n\n\t\tUrgencyType Check_Attack(void) const;\n\t\tUrgencyType Check_Build_Power(void) const;\n\t\tUrgencyType Check_Build_Defense(void) const;\n\t\tUrgencyType Check_Build_Offense(void) const;\n\t\tUrgencyType Check_Build_Income(void) const;\n\t\tUrgencyType Check_Fire_Sale(void) const;\n\t\tUrgencyType Check_Build_Engineer(void) const;\n\t\tUrgencyType Check_Raise_Money(void) const;\n\t\tUrgencyType Check_Raise_Power(void) const;\n\t\tUrgencyType Check_Lower_Power(void) const;\n\n\t\tbool AI_Attack(UrgencyType urgency);\n\t\tbool AI_Build_Power(UrgencyType urgency) const;\n\t\tbool AI_Build_Defense(UrgencyType urgency) const;\n\t\tbool AI_Build_Offense(UrgencyType urgency) const;\n\t\tbool AI_Build_Income(UrgencyType urgency) const;\n\t\tbool AI_Fire_Sale(UrgencyType urgency);\n\t\tbool AI_Build_Engineer(UrgencyType urgency) const;\n\t\tbool AI_Raise_Money(UrgencyType urgency) const;\n\t\tbool AI_Raise_Power(UrgencyType urgency) const;\n\t\tbool AI_Lower_Power(UrgencyType urgency) const;\n\n\t\tbool Can_Make_Money(void) const {\n\t\t\treturn(Available_Money() > 300 || (BScan & STRUCTF_REFINERY));\n\t\t};\n\n\t\tstatic void Init(void);\n\t\tstatic void One_Time(void);\n\t\tstatic HouseClass * As_Pointer(HousesType house);\n\t\tstatic void Recalc_Attributes(void);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tstatic void Read_INI(CCINIClass & ini);\n\t\tstatic void Write_INI(CCINIClass & ini);\n\t\tstatic void Read_Flag_INI(char *buffer);\n\t\tstatic void Write_Flag_INI(char *buffer);\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\t\tvoid Code_Pointers(void);\n\t\tvoid Decode_Pointers(void);\n\n\t\t/*\n\t\t**\tSpecial house actions.\n\t\t*/\n\t\tvoid Detach(TARGET target, bool all);\n\n\t\t/*\n\t\t**\tThis vector holds the recorded status of the map regions. It is through\n\t\t**\tthis region information that team paths are calculated.\n\t\t*/\n\t\tRegionClass Regions[MAP_TOTAL_REGIONS];\n\n\t\t/*\n\t\t**\tThis count down timer class decrements and then changes\n\t\t** the Atomic Bomb state.\n\t\t*/\n\t\tCELL NukeDest;\n\n\t\t/*\n\t\t** This routine completely removes this house & all its objects from the game.\n\t\t*/\n\t\tvoid Clobber_All(void);\n\n\t\t/*\n\t\t** This routine blows up everything in this house.  Fun!\n\t\t*/\n\t\tvoid Blowup_All(void);\n\n\t\t/*\n\t\t** This routine gets called in multiplayer games when every unit, building,\n\t\t** and infantry for a house is destroyed.\n\t\t*/\n\t\tvoid MPlayer_Defeated(void);\n\n\t\t/*\n\t\t** When the game's over, this routine assigns everyone their score.\n\t\t*/\n\t\tvoid Tally_Score(void);\n\n\t\tfriend class MapEditClass;\n\n\tprivate:\n\t\tvoid Silo_Redraw_Check(long oldtib, long oldcap);\n\t\tint AI_Building(void);\n\t\tint AI_Unit(void);\n\t\tint AI_Vessel(void);\n\t\tint AI_Infantry(void);\n\t\tint AI_Aircraft(void);\n\n\t\t/*\n\t\t**\tThis is a bit field record of all the other houses that are allies with\n\t\t**\tthis house. It is presumed that any house that isn't an ally, is therefore\n\t\t**\tan enemy. A house is always considered allied with itself.\n\t\t*/\n\t\tunsigned Allies;\n\n\t\t/*\n\t\t**\tGeneral low-power related damaged is doled out whenever this timer\n\t\t**\texpires.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> DamageTime;\n\n\t\t/*\n\t\t**\tTeam creation is done whenever this timer expires.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> TeamTime;\n\n\t\t/*\n\t\t**\tThis controls the rate that the trigger time logic is processed.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> TriggerTime;\n\n\t\t/*\n\t\t**\tAt various times, the computer may announce the player's condition. The following\n\t\t**\tvariables are used as countdown timers so that these announcements are paced\n\t\t**\tfar enough apart to reduce annoyance.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> SpeakAttackDelay;\n\t\tCDTimerClass<FrameTimerClass> SpeakPowerDelay;\n\t\tCDTimerClass<FrameTimerClass> SpeakMoneyDelay;\n\t\tCDTimerClass<FrameTimerClass> SpeakMaxedDelay;\n\n\t\t/*\n\t\t**\tThis structure is used to record a build request as determined by\n\t\t**\tthe house AI processing. Higher priority build requests take precidence.\n\t\t*/\n\t\tstruct BuildChoiceClass {\n\t\t\tstatic void * operator new(size_t, void * ptr) {return(ptr);};\n\t\t\tUrgencyType\tUrgency;\t\t\t// The urgency of the build request.\n\t\t\tStructType\tStructure;\t\t// The type of building to produce.\n\n\t\t\tBuildChoiceClass(UrgencyType u, StructType s) : Urgency(u), Structure(s) {};\n\t\t\tBuildChoiceClass(NoInitClass const & ) {};\n\t\t\tint Save(Pipe &) const {return(true);};\n\t\t\tint Load(Straw &) {return(true);};\n\t\t\tvoid Code_Pointers(void) {};\n\t\t\tvoid Decode_Pointers(void) {};\n\t\t};\n\n\t\tstatic TFixedIHeapClass<BuildChoiceClass> BuildChoice;\n\n\n\t/*\n\t** These values are for multiplay only.\n\t*/\n\tpublic:\n\t\t/*\n\t\t** For multiplayer games, each house instance has a remap table; the table\n\t\t** in the HousesTypeClass isn't used.  This variable is set to the remap\n\t\t** table for the color the player wants to play.\n\t\t*/\n\t\tPlayerColorType RemapColor;\n\n\t\t/*\n\t\t** This is the name (\"handle\") the player has chosen for himself.\n\t\t*/\n\t\tchar IniName[HOUSE_NAME_MAX];\n\n#ifdef WOLAPI_INTEGRATION\n\t\t//\tFor Internet games only, unchanging name of player when game began.\n\t\t//\tThis name does not get changed to \"Computer\" if computer takes over for player.\n\t\tchar InitialName[HOUSE_NAME_MAX];\n#endif\n\n\t\tint QuantityB(int index) {return(BQuantity[index]);}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tint QuantityU(int index) {\n\t\t\tif(index >= UNIT_RA_COUNT) index -= UNIT_RA_COUNT;\n\t\t\treturn(UQuantity[index]);\n\t\t}\n\t\tint QuantityI(int index) {\n\t\t\tif(index >= INFANTRY_RA_COUNT) index -= INFANTRY_RA_COUNT;\n\t\t\treturn(IQuantity[index]);\n\t\t}\n\t\tint QuantityA(int index) {return(AQuantity[index]);}\n\t\tint QuantityV(int index) {\n\t\t\tif(index >= VESSEL_RA_COUNT) index -= VESSEL_RA_COUNT;\n\t\t\treturn(VQuantity[index]);\n\t\t}\n#else\n\t\tint QuantityU(int index) {return(UQuantity[index]);}\n\t\tint QuantityI(int index) {return(IQuantity[index]);}\n\t\tint QuantityA(int index) {return(AQuantity[index]);}\n\t\tint QuantityV(int index) {return(VQuantity[index]);}\n#endif\n\n};\n\n#endif\n\n"
  },
  {
    "path": "CODE/HSV.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/HSV.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HSV.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/02/95                                                     *\n *                                                                                             *\n *                  Last Update : February 20, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   HSVClass::Adjust -- Adjust an HSV color toward specified color.                           *\n *   HSVClass::Difference -- Finds the difference between two HSV color objects.               *\n *   HSVClass::Set -- Set the palette for this color object.                                   *\n *   HSVClass::operator RGBClass -- Conversion operator for RGBClass object.                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"watcom.h\"\n#include\t\"hsv.h\"\n#include\t\"rgb.h\"\n\nHSVClass const HSVClass::BlackColor(0, 0, 0);\n\n\n/***********************************************************************************************\n * HSVClass::Adjust -- Adjust an HSV color toward specified color.                             *\n *                                                                                             *\n *    This routine will adjust the HSV color object toward the color of the specified HSV      *\n *    object. Typical users of this would be palette morphing or fading routines.              *\n *                                                                                             *\n * INPUT:   ratio    -- The ratio to move the HSV object toward the color specified. A value   *\n *                      of zero means no movement at all. A value of 255 means move completely *\n *                      toward the specified color (changed completely).                       *\n *                                                                                             *\n *          hsv      -- A reference to the color that the current HSV object is to change      *\n *                      toward.                                                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HSVClass::Adjust(int ratio, HSVClass const & hsv)\n{\n\t/*\n\t**\tRatio conversion is limited to 0 through 100%. This is\n\t**\tthe range of 0 to 255.\n\t*/\n\tratio &= 0x00FF;\n\n\t/*\n\t**\tAdjust the color guns by the ratio specified toward the\n\t**\tdestination color.\n\t*/\n\tint value = hsv.Value_Component() - Value_Component();\n\tValue = Value_Component() + (value * ratio) / 256;\n\n\tint saturation = hsv.Saturation_Component() - Saturation_Component();\n\tSaturation = Saturation_Component() + (saturation * ratio) / 256;\n\n\tint hue = hsv.Hue_Component() - Hue_Component();\n\tHue = Hue_Component() + (hue * ratio) / 256;\n}\n\n\n/***********************************************************************************************\n * HSVClass::Difference -- Finds the difference between two HSV color objects.                 *\n *                                                                                             *\n *    This routine will determine a color difference between two HSV objects. The difference   *\n *    has no particular meaning other that larger numbers meaning greater difference.          *\n *                                                                                             *\n * INPUT:   hsv   -- The other HSV object to compare this HSV object to.                       *\n *                                                                                             *\n * OUTPUT:  Returns with a relative distance (in arbitrary units) between this HSV object and  *\n *          the HSV object supplied.                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint HSVClass::Difference(HSVClass const & hsv) const\n{\n\tint hue = (int)Hue - (int)hsv.Hue;\n\tif (hue < 0) hue = -hue;\n\n\tint saturation = (int)Saturation - (int)hsv.Saturation;\n\tif (saturation < 0) saturation = -saturation;\n\n\tint value = (int)Value - (int)hsv.Value;\n\tif (value < 0) value = -value;\n\n\treturn(hue*hue + saturation*saturation + value*value);\n}\n\n\n/***********************************************************************************************\n * HSVClass::operator RGBClass -- Conversion operator for RGBClass object.                     *\n *                                                                                             *\n *    This conversion operator will convert the HSV object into an RGB object.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a reference (implied) of the RGBClass object that most closely        *\n *          matches this HSVClass object.                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nHSVClass::operator RGBClass (void) const\n{\n\tunsigned int i;\t\t\t\t// Integer part.\n\tunsigned int f;\t\t\t\t// Fractional or remainder part.  f/HSV_BASE gives fraction.\n\tunsigned int tmp;\t\t\t// Temporary variable to help with calculations.\n\tunsigned int values[7];\t// Possible rgb values.  Don't use zero.\n\n\tint hue = Hue_Component();\n\tint saturation = Saturation_Component();\n\tint value = Value_Component();\n\tint red, green, blue;\n\n\n\thue *= 6;\n\tf = hue % 255;\n\n\t// Set up possible red, green and blue values.\n\tvalues[1] =\n\tvalues[2] = value;\n\n\t//\n\t// The following lines of code change\n\t//\tvalues[3] = (v * (255 - ( (s * f) / 255) )) / 255;\n\t//\tvalues[4] = values[5] = (v * (255 - s)) / 255;\n\t// values[6] = (v * (255 - (s * (255 - f)) / 255)) / 255;\n\t// so that the are rounded divides.\n\t//\n\n\ttmp = (saturation * f) / 255;\n\tvalues[3] = (value * (255 - tmp)) / 255;\n\n\tvalues[4] =\n\tvalues[5] = (value * (255 - saturation)) / 255;\n\n\ttmp = 255 - (saturation * (255 - f)) / 255;\n\tvalues[6] = (value * tmp) / 255;\n\n\n\t// This should not be rounded.\n\ti = hue / 255;\n\n\ti += (i > 4) ? -4 : 2;\n\tred = values[i];\n\n\ti += (i > 4) ? -4 : 2;\n\tblue = values[i];\n\n\ti += (i > 4) ? -4 : 2;\n\tgreen = values[i];\n\n\treturn(RGBClass(red, green, blue));\n}\n\n\n/***********************************************************************************************\n * HSVClass::Set -- Set the palette for this color object.                                     *\n *                                                                                             *\n *    The palette will be set for this color object. Use this routine to set an arbitrary      *\n *    color index with the HSVClass object.                                                    *\n *                                                                                             *\n * INPUT:   color -- The color index to change.                                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HSVClass::Set(int color) const\n{\n\tRGBClass rgb = *this;\n\trgb.Set(color);\n}\n"
  },
  {
    "path": "CODE/HSV.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/HSV.H 1     3/03/97 10:24a Joe_bostic $ */\n/*********************************************************************************************** \n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HSV.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/02/95                                                     *\n *                                                                                             *\n *                  Last Update : December 2, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef HSV_H\n#define HSV_H\n\nclass RGBClass;\nclass HSVClass;\n\n/*\n**\tEach color entry is represented by this class. It holds the values for the color\n**\tattributes. The values are recorded in a range from 0 to 255 with 255 being the\n**\tmaximum.\n*/\nclass HSVClass\n{\n\tprivate:\n\t\tstatic HSVClass const BlackColor;\n\n\tpublic:\n\t\tHSVClass(void) : Hue(0), Saturation(0), Value(0) {};\n\t\tHSVClass(unsigned char hue, unsigned char saturation, unsigned char value) :\n\t\t\t\tHue(hue),\n\t\t\t\tSaturation(saturation),\n\t\t\t\tValue(value)\n\t\t\t{};\n\t\toperator RGBClass (void) const;\n\n\t\tenum {\n\t\t\tMAX_VALUE=255\n\t\t};\n\n\t\tvoid Adjust(int ratio, HSVClass const & hsv);\n\t\tint Difference(HSVClass const & hsv) const;\n\t\tint Hue_Component(void) const {return(Hue);};\n\t\tint Saturation_Component(void) const {return(Saturation);};\n\t\tint Value_Component(void) const {return(Value);};\n\t\tvoid Set(int color) const;\n\n\tprivate:\n\t\tunsigned char Hue;\n\t\tunsigned char Saturation;\n\t\tunsigned char Value;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/ICONLIST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifdef WOLAPI_INTEGRATION\n\n//\tIconlist.cpp - created by ajw 07/07/98\n\n//\tIconListClass is ListClass plus the option to include an icon on each line entry,\n//\tthe option to have the class maintain its own copies of strings passed to it\n//\tfor display, and the option to limit the maximum number of these strings that are\n//\tkept (entries are removed from the top when this maximum is reached).\n//\tAlso added: multiple item selection capability. Note that the old selection code\n//\truns as normal, but it simply not used when it comes time to display.\n//\tAlso added: if mem. allocation is being done by this, the ability to break new items\n//\tinto multiple lines of text is enabled.\n//\tAlso added: extra data can be invisibly stored with each item, if memory allocation is\n//\tbeing done by this.\n//\tExtra data included 3 item preceding icons, 1 fixed position icon, an extra string,\n//\tan extra void pointer, and a color remapping value.\n\n#include \"iconlist.h\"\n#include \"dibapi.h\"\n\nint Format_Window_String_New( const char* string, int maxlinelen, int& width, int& height, char* szReturn, int iExtraChars );\nvoid CC_Draw_DIB( const char* pDIB, int xDest, int yDest, int iWidth, WindowNumberType window );\n\n//***********************************************************************************************\nIconListClass::IconListClass( int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down, \n\t\t\t\t\t\t\t\tbool bResponsibleForStringAlloc, int iSelectionType, int iMaxItemsSaved ) :\n\tListClass( id, x, y, w, h, flags, up, down )\n{\n\t//\tIf bResponsibleForStringAlloc, COPIES of strings are stored in the list. Deletion is\n\t//\thandled by this class. Icons are different - the caller is responsible for what's on\n\t//\tthe other end of the pointer.\n\tbDoAlloc = bResponsibleForStringAlloc;\n\t//\tiSelectionType = 0 for no selection shown, 1 for normal ListClass selection, 2 for n multiple selections\n\tif( iSelectionType < 0 || iSelectionType > 2 )\t\tiSelectionType = 1;\n\tiSelectType = iSelectionType;\n\t//\tIf iMaxItemsSaved is 0, there is no limit to the number of text lines. The list can grow forever.\n\t//\tOtherwise items are deleted from the head of the list when the maximum is passed.\n\t//\tiMaxItemsSaved only applies when bResponsibleForStringAlloc.\n\tiMaxItems = iMaxItemsSaved;\n}\n\n//***********************************************************************************************\nIconListClass::~IconListClass( void )\n{\n\t//\tDelete the IconList_ItemExtras structs created to hold extra info on each item.\n\tfor( int i = 0; i < ExtrasList.Count(); i++ )\n\t\tdelete (IconList_ItemExtras*)ExtrasList[ i ];\n\n\tif( bDoAlloc )\n\t{\n\t\t//\tDelete all alloc'ed strings.\n\t\tfor( int i = 0; i < List.Count(); i++ )\n\t\t\tdelete [] (char*)List[i];\n\t}\n}\n\n/***********************************************************************************************\n * IconListClass::Add_Item -- Adds an item to the list box.                                        *\n *                                                                                             *\n *    This will add the specified string to the list box. The string is added to the end       *\n *    of the list.                                                                             *\n *                                                                                             *\n * INPUT:      text  -- Pointer to the string to add to the list box.                          *\n *             pIcon -- Pointer to the shape to add.\n *             IconKind -- Indicates what type of image pIcon points to.\n *             szExtraDataString -- Extra string data that gets copied and stored along with item.\n *             szExtraDataPtr -- Extra data that gets stored along with item.\n *             pColorRemap -- Points to a color remapping used when drawing the item.\n *\n * OUTPUT:     Returns new item index.                                                         *\n * WARNINGS:   none                                                                            *\n * HISTORY:    07/07/1998 ajw : Created.                                                       *\n *=============================================================================================*/\nint IconListClass::Add_Item(char const * text)\n{\n\treturn Add_Item( text, NULL, NULL, ICON_SHAPE );\n}\n\nint IconListClass::Add_Item( const char* text, const char* szHelp, \n\t\t\t\t\t\t\t\tvoid* pIcon0, ICONKIND IconKind0, const char* szExtraDataString /* = NULL */, \n\t\t\t\t\t\t\t\tvoid* pvExtraDataPtr /* = NULL */, RemapControlType* pColorRemap /* = NULL */,\n\t\t\t\t\t\t\t\tvoid* pIcon1 /* = NULL */, ICONKIND IconKind1 /* = ICON_SHAPE */, \n\t\t\t\t\t\t\t\tvoid* pIcon2 /* = NULL */, ICONKIND IconKind2 /* = ICON_SHAPE */,\n\t\t\t\t\t\t\t\tvoid* pFixedIcon /* = NULL */, ICONKIND FixedIconKind /* = ICON_SHAPE */, int iXFixedIcon /* = 0 */, int iYFixedIcon /* = 0 */, int iFixedIconWidth /* = -1 */ )\n{\n\tif( text )\n\t{\n\t\tif( bDoAlloc )\n\t\t{\n\t\t\tint iRetVal;\n\n\t\t\tchar* szText = new char[ strlen( text ) + 51 ];\t\t\t//\t50 extra chars added for line breaks later.\n\t\t\tstrcpy( szText, text );\n\n\t\t\tint iWidthMax, iHeight;\n\t\t\t//\tStupid usage of globals for font stuff... <grumble>\n\t\t\tif( TextFlags == TPF_TYPE )\n\t\t\t{\n\t\t\t\tvoid* pFontBefore = Set_Font( TypeFontPtr );\n\t\t\t\tDWORD FontXSpacingBefore = FontXSpacing;\n\t\t\t\tFontXSpacing = -2;\n\n\t\t\t\tint iWidthToClipAt = IsScrollActive ? Width : Width - UpGadget.Width;\n\t\t\t\t//\tThis call will place '\\r's in the string where line breaks should occur.\n\t\t\t\tFormat_Window_String_New( text, iWidthToClipAt, iWidthMax, iHeight, szText, 50 );\n\n\t\t\t\tSet_Font( pFontBefore );\n\t\t\t\tFontXSpacing = FontXSpacingBefore;\t\t//\tJust in case it matters... Doubt it.\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//\tCurrently never called. Test well if you use IconList with a font other than TPF_TYPE,\n\t\t\t\t//\tas the character spacing globals get set weirdly, I've found.\n\t\t\t\tint iWidthToClipAt = IsScrollActive ? Width : Width - UpGadget.Width;\n\t\t\t\t//\tThis call will place '\\r's in the string where line breaks should occur.\n\t\t\t\tFormat_Window_String_New( text, iWidthToClipAt, iWidthMax, iHeight, szText, 50 );\n\t\t\t}\n\n\t\t\t//\tEach break character causes a line to be added to list.\n\t\t\tchar szBreakchars[] = \"\\r\\n\\v\\f\";\n\t\t\tchar* szToken;\n\t\t\tchar* szNextChar = szText;\n\t\t\tszToken = strtok( szText, szBreakchars );\n\t\t\twhile( szToken )\n\t\t\t{\n\t\t\t\twhile( szNextChar < szToken )\n\t\t\t\t{\n\t\t\t\t\t//\tWe expected szToken to begin at szNextChar. Since it doesn't, extra break\n\t\t\t\t\t//\tcharacters must have been removed by strtok as they were adjacent. We want \n\t\t\t\t\t//\ta line break for every break character, so add lines for each space that\n\t\t\t\t\t//\tszNextChar is off by.\n\t\t\t\t\tszNextChar++;\n\t\t\t\t\tAdd_Item_Detail( \" \", szHelp, pIcon0, IconKind0, szExtraDataString, pvExtraDataPtr, pColorRemap, pIcon1, IconKind1, pIcon2, IconKind2, pFixedIcon, FixedIconKind, iXFixedIcon, iYFixedIcon, iFixedIconWidth );\n\t\t\t\t}\n\t\t\t\tiRetVal = Add_Item_Detail( szToken, szHelp, pIcon0, IconKind0, szExtraDataString, pvExtraDataPtr, pColorRemap, pIcon1, IconKind1, pIcon2, IconKind2, pFixedIcon, FixedIconKind, iXFixedIcon, iYFixedIcon, iFixedIconWidth );\n\n\t\t\t\t//\tExpect next token two chars after the end of this one.\n\t\t\t\tszNextChar = szToken + strlen( szToken ) + 1;\n\n\t\t\t\t//\tGet next token.\n\t\t\t\tszToken = strtok( NULL, szBreakchars );\n\t\t\t}\n\t\t\tdelete [] szText;\n\t\t\treturn iRetVal;\t\t\t\t//\tLast value returned by ListClass::Add_Item\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//\tAdd one item to list.\n\t\t\tIconList_ItemExtras* pItemExtra = new IconList_ItemExtras;\n\t\t\tpItemExtra->bMultiSelected = false;\n\t\t\tpItemExtra->pIcon[0] = pIcon0;\n\t\t\tpItemExtra->IconKind[0] = IconKind0;\n\t\t\tpItemExtra->pIcon[1] = pIcon1;\n\t\t\tpItemExtra->IconKind[1] = IconKind1;\n\t\t\tpItemExtra->pIcon[2] = pIcon2;\n\t\t\tpItemExtra->IconKind[2] = IconKind2;\n\t\t\tpItemExtra->FixedIcon.pIcon = pFixedIcon;\n\t\t\tpItemExtra->FixedIcon.IconKind = FixedIconKind;\n\t\t\tpItemExtra->FixedIcon.xOffset = iXFixedIcon;\n\t\t\tpItemExtra->FixedIcon.yOffset = iYFixedIcon;\n\t\t\tpItemExtra->FixedIcon.iWidth = iFixedIconWidth;\n\t\t\tpItemExtra->pvExtraData = pvExtraDataPtr;\n\t\t\tpItemExtra->pColorRemap = pColorRemap;\n\t\t\tif( szHelp )\n\t\t\t{\n\t\t\t\t//\tCopy help into new help string.\n\t\t\t\tpItemExtra->szHelp = new char[ strlen( szHelp ) + 1 ];\n\t\t\t\tstrcpy( pItemExtra->szHelp, szHelp );\n\t\t\t}\n\t\t\tif( szExtraDataString )\n\t\t\t{\n\t\t\t\t//\tCopy special data string into new extradata string.\n\t\t\t\tpItemExtra->szExtraData = new char[ strlen( szExtraDataString ) + 1 ];\n\t\t\t\tstrcpy( pItemExtra->szExtraData, szExtraDataString );\n\t\t\t}\n\t\t\tExtrasList.Add( pItemExtra );\n\n\t\t\treturn ListClass::Add_Item( text );\n\t\t}\n\t}\n\telse\n\t{\n\t\t//\t(no text for new item)\n\t\tif( pIcon0 || pIcon1 || pIcon2 )\n\t\t{\n\t\t\t//\tNote: Cannot add an entry without text unless string allocation is being handled by me.\n\t\t\t//\tOtherwise, because we want the icon to show up, create a blank entry for the ListClass.\n\t\t\tif( bDoAlloc )\n\t\t\t{\n\t\t\t\tIconList_ItemExtras* pItemExtra = new IconList_ItemExtras;\n\t\t\t\tpItemExtra->bMultiSelected = false;\n\t\t\t\tpItemExtra->pIcon[0] = pIcon0;\n\t\t\t\tpItemExtra->IconKind[0] = IconKind0;\n\t\t\t\tpItemExtra->pIcon[1] = pIcon1;\n\t\t\t\tpItemExtra->IconKind[1] = IconKind1;\n\t\t\t\tpItemExtra->pIcon[2] = pIcon2;\n\t\t\t\tpItemExtra->IconKind[2] = IconKind2;\n\t\t\t\tpItemExtra->FixedIcon.pIcon = pFixedIcon;\n\t\t\t\tpItemExtra->FixedIcon.IconKind = FixedIconKind;\n\t\t\t\tpItemExtra->FixedIcon.xOffset = iXFixedIcon;\n\t\t\t\tpItemExtra->FixedIcon.yOffset = iYFixedIcon;\n\t\t\t\tpItemExtra->FixedIcon.iWidth = iFixedIconWidth;\n\t\t\t\tpItemExtra->pvExtraData = pvExtraDataPtr;\n\t\t\t\tpItemExtra->pColorRemap = pColorRemap;\n\t\t\t\tif( szHelp )\n\t\t\t\t{\n\t\t\t\t\t//\tCopy help into new help string.\n\t\t\t\t\tpItemExtra->szHelp = new char[ strlen( szHelp ) + 1 ];\n\t\t\t\t\tstrcpy( pItemExtra->szHelp, szHelp );\n\t\t\t\t}\n\t\t\t\tif( szExtraDataString )\n\t\t\t\t{\n\t\t\t\t\t//\tCopy special data string into new extradata string.\n\t\t\t\t\tpItemExtra->szExtraData = new char[ strlen( szExtraDataString ) + 1 ];\n\t\t\t\t\tstrcpy( pItemExtra->szExtraData, szExtraDataString );\n\t\t\t\t}\n\t\t\t\tExtrasList.Add( pItemExtra );\n\n\t\t\t\tif( iMaxItems && List.Count() == iMaxItems )\n\t\t\t\t{\n\t\t\t\t\t//\tDelete head of list.\n\t\t\t\t\tRemove_Item( 0 );\n\t\t\t\t}\n\t\t\t\t//\tCreate new string, essentially blank.\n\t\t\t\tchar* szText = new char[2];\n\t\t\t\tstrcpy( szText, \" \" );\n\t\t\t\treturn ListClass::Add_Item( szText );\n\t\t\t}\n\t\t\telse\n\t\t\t\t//\tCannot add entry, as text is blank and ListClass::Add_Item will do nothing.\n\t\t\t\t//\tThe Icon we want will not show up.\n\t\t\t\treturn List.Count() - 1;\n\t\t}\n\t\telse\n\t\t\treturn ListClass::Add_Item( text );\n\t}\n}\n\n//***********************************************************************************************\nint IconListClass::Add_Item_Detail( const char* szToken, const char* szHelp,\n\t\t\t\t\t\t\t\t\t\tvoid* pIcon0, ICONKIND IconKind0, const char* szExtraDataString, \n\t\t\t\t\t\t\t\t\t\tvoid* pvExtraData, RemapControlType* pColorRemap,\n\t\t\t\t\t\t\t\t\t\tvoid* pIcon1, ICONKIND IconKind1, \n\t\t\t\t\t\t\t\t\t\tvoid* pIcon2, ICONKIND IconKind2,\n\t\t\t\t\t\t\t\t\t\tvoid* pFixedIcon, ICONKIND FixedIconKind, int iXFixedIcon, int iYFixedIcon, int iFixedIconWidth )\n{\n\t//\tBroken out of above function as it is repeated.\n\n\t//\tAdd one item to list.\n\t//\tToo many entries?\n\tif( iMaxItems && List.Count() == iMaxItems )\n\t{\n\t\t//\tDelete head of list.\n\t\tRemove_Item( 0 );\n\t}\n\t//\tCreate icon entry.\n\tIconList_ItemExtras* pItemExtra = new IconList_ItemExtras;\n\tpItemExtra->bMultiSelected = false;\n\tpItemExtra->pIcon[0] = pIcon0;\t\t\t\t//\tajw - Question: repeat the icon for each entry? make it optional?\n\tpItemExtra->IconKind[0] = IconKind0;\n\tpItemExtra->pIcon[1] = pIcon1;\n\tpItemExtra->IconKind[1] = IconKind1;\n\tpItemExtra->pIcon[2] = pIcon2;\n\tpItemExtra->IconKind[2] = IconKind2;\n\tpItemExtra->FixedIcon.pIcon = pFixedIcon;\n\tpItemExtra->FixedIcon.IconKind = FixedIconKind;\n\tpItemExtra->FixedIcon.xOffset = iXFixedIcon;\n\tpItemExtra->FixedIcon.yOffset = iYFixedIcon;\n\tpItemExtra->FixedIcon.iWidth = iFixedIconWidth;\n\tpItemExtra->pvExtraData = pvExtraData;\n\tpItemExtra->pColorRemap = pColorRemap;\n\tif( szHelp )\n\t{\n\t\t//\tCopy help into new help string.\n\t\tpItemExtra->szHelp = new char[ strlen( szHelp ) + 1 ];\n\t\tstrcpy( pItemExtra->szHelp, szHelp );\n\t}\n\tif( szExtraDataString )\n\t{\n\t\t//\tCopy special data string into new extradata string.\n\t\tpItemExtra->szExtraData = new char[ strlen( szExtraDataString ) + 1 ];\n\t\tstrcpy( pItemExtra->szExtraData, szExtraDataString );\n\t}\n\tExtrasList.Add( pItemExtra );\n\t//\tCreate text entry.\n\t//\tCopy text to new string.\n\tchar* szTextBit = new char[ strlen( szToken ) + 1 ];\n\tstrcpy( szTextBit, szToken );\n\treturn ListClass::Add_Item( szTextBit );\n}\n\n//***********************************************************************************************\nint IconListClass::Add_Item( int text )\n{\n\treturn Add_Item( Text_String(text), NULL, NULL, ICON_SHAPE );\n}\n\n//***********************************************************************************************\nint IconListClass::Add_Item( int text, const char* szHelp,\n\t\t\t\t\t\t\t\tvoid* pIcon0, ICONKIND IconKind0, const char* szExtraDataString /* = NULL */, \n\t\t\t\t\t\t\t\tvoid* pvExtraDataPtr /* = NULL */, RemapControlType* pColorRemap /* = NULL */,\n\t\t\t\t\t\t\t\tvoid* pIcon1 /* = NULL */, ICONKIND IconKind1 /* = ICON_SHAPE */, \n\t\t\t\t\t\t\t\tvoid* pIcon2 /* = NULL */, ICONKIND IconKind2 /* = ICON_SHAPE */,\n\t\t\t\t\t\t\t\tvoid* pFixedIcon /* = NULL */, ICONKIND FixedIconKind /* = ICON_SHAPE */, int iXFixedIcon /* = 0 */, int iYFixedIcon /* = 0 */, int iFixedIconWidth /* = -1 */ )\n{\n\treturn Add_Item( Text_String(text), szHelp, pIcon0, IconKind0, szExtraDataString, pvExtraDataPtr, pColorRemap, \n\t\t\t\t\t\tpIcon1, IconKind1, pIcon2, IconKind2, pFixedIcon, FixedIconKind, iXFixedIcon, iYFixedIcon, iFixedIconWidth );\n}\n\n//***********************************************************************************************\nvoid IconListClass::Remove_Item( char const * text )\n{\n\tif( text )\n\t\tRemove_Item( List.ID(text) );\n}\n\n//***********************************************************************************************\nvoid IconListClass::Remove_Item( int index )\n{\n\tif( (unsigned)index < List.Count() )\n\t{\n\t\tdelete (IconList_ItemExtras*)ExtrasList[ index ];\n\t\tExtrasList.Delete( index );\n\t\tif( bDoAlloc )\n\t\t\t//\tDelete alloc'ed string.\n\t\t\tdelete [] (char*)List[index];\n\t\tListClass::Remove_Item( index );\n\t\t\n\t\t//\tI should probably put this in ListClass:Remove_Item(), as it seems clearly to be\n\t\t//\tmissing, but I want to only affect my own new code, to not introduce possible bugs.\n\t\t//\tShift the selected index if appropriate...\n\t\tif( SelectedIndex >= index )\n\t\t{\n\t\t\tSelectedIndex--;\n\t\t\tif( SelectedIndex < 0 )\n\t\t\t\tSelectedIndex = 0;\n\t\t}\n\t}\n}\n\n/***********************************************************************************************\n * IconListClass::Draw_Entry -- Calls ListClass::Draw_Entry, then adds icon.                   *\n *                                                                                             *\n *    This routine is called by the Draw_Me function when it desired to redraw a particular    *\n *    text line in the list box.                                                               *\n *                                                                                             *\n * INPUT:   index    -- The index of the list entry to draw. This index is based on the        *\n *                      total list and NOT the current visible view page.                      *\n *                                                                                             *\n *          x,y      -- Pixel coordinates for the upper left corner of the text entry.         *\n *                                                                                             *\n *          width    -- The maximum width that the text may draw over. It is expected that     *\n *                      this drawing routine entirely fills this length.                       *\n *                                                                                             *\n *          selected -- bool; Is this a selected (highlighted) listbox entry?                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n * WARNINGS:   none                                                                            *\n * HISTORY:                                                                                    *\n *   07/07/1998  ajw: Created.                                                                 *\n *=============================================================================================*/\n\n#define PREICONGAP\t\t1\n#define ICONTEXTGAP\t\t2\n\nvoid IconListClass::Draw_Entry( int index, int x, int y, int width, int selected )\n{\n\tIconList_ItemExtras* pExtras = (IconList_ItemExtras*)ExtrasList[ index ];\n\n\tint xText = x;\n\t//\tajw If I end up needing to use SHAPEs for icons, figure out shape width here and offset x.\n\tbool bIconsPresent = false;\n\tfor( int iIcon = 0; iIcon != 3; iIcon++ )\n\t\tif( pExtras->pIcon[ iIcon ] && pExtras->IconKind[ iIcon ] == ICON_DIB )\n\t\t{\n\t\t\t//\tPush text over to accommodate icon.\n\t\t\tint iWidthIcon = PREICONGAP + DIBWidth( (char*)pExtras->pIcon[ iIcon ] );\n\t\t\txText += iWidthIcon;\n\t\t\twidth -= iWidthIcon;\n\t\t\tbIconsPresent = true;\n\t\t}\n\tif( bIconsPresent )\n\t{\n\t\txText += ICONTEXTGAP;\n\t\twidth -= ICONTEXTGAP;\n\t}\n\n\tRemapControlType* pRemap = pExtras->pColorRemap;\n\tif( !pRemap )\n\t{\n\t\t//\tTabs hack. If there are icons, and a tab, push back the FIRST tab appropriately.\n\t\t//\t(Ignore others. This is a hack because having more than one tab will now break this.)\n\t\t//\tSee local version of this same hack, below.\n\t\tint TempTabs;\n\t\tconst int* TabsSave;\n\t\tif( Tabs )\n\t\t{\n\t\t\tTempTabs = *Tabs - ( xText - x );\n\t\t\tTabsSave = Tabs;\n\t\t\tTabs = &TempTabs;\n\t\t}\n\t\tswitch( iSelectType )\n\t\t{\n\t\tcase 0:\n\t\t\t//\tDon't draw any items selected (even if they are, really, in ListClass).\n\t\t\tListClass::Draw_Entry( index, xText, y, width, false );\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tListClass::Draw_Entry( index, xText, y, width, selected );\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\t//\tIgnore 'selected' parameter. We use our own records.\n\t\t\tListClass::Draw_Entry( index, xText, y, width, pExtras->bMultiSelected );\n\t\t\tbreak;\n\t\t}\n\t\t//\tRestore Tabs.\n\t\tif( Tabs )\n\t\t\tTabs = TabsSave;\n\t}\n\telse\n\t{\n\t\t//\tUse different color remapping.\n\t\t//\tThis is largely copied straight from ListClass::Draw_Entry()...\n\n\t\tTextPrintType flags = TextFlags;\n\n\t\tbool bShowSelected;\n\n\t\tswitch( iSelectType )\n\t\t{\n\t\tcase 0:\n\t\t\tbShowSelected = false;\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tbShowSelected = selected;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tbShowSelected = pExtras->bMultiSelected;\n\t\t\tbreak;\n\t\t}\n\n\t\tif( bShowSelected )\n\t\t{\n\t\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\t\tLogicPage->Fill_Rect( xText, y, xText + width - 1, y + LineHeight - 1, pRemap->Shadow );\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (!(flags & TPF_USE_GRAD_PAL))\n\t\t\t{\n\t\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t\t}\n\t\t}\n\t\t//\tTabs hack. If there are icons, and a tab, push back the FIRST tab appropriately.\n\t\t//\t(Ignore others. This is a hack because having more than one tab will now break this.)\n\t\tif( Tabs )\n\t\t{\n\t\t\tint tab = *Tabs - ( xText - x );\n\t\t\tConquer_Clip_Text_Print( List[index], xText, y, pRemap, TBLACK, flags, width, &tab );\n\t\t}\n\t\telse\n\t\t\tConquer_Clip_Text_Print( List[index], xText, y, pRemap, TBLACK, flags, width, NULL );\n\t}\n\n\t//\tDraw fixed position icon.\n\tif( pExtras->FixedIcon.pIcon )\n\t{\n\t\tif( pExtras->FixedIcon.IconKind == ICON_SHAPE )\n\t\t\tCC_Draw_Shape( pExtras->FixedIcon.pIcon, 0, x + pExtras->FixedIcon.xOffset, y + pExtras->FixedIcon.yOffset, WINDOW_MAIN, SHAPE_NORMAL );\n\t\t\t//\tPut similar code in here for shapes if used...\n\t\telse\n\t\t\tCC_Draw_DIB( (char*)pExtras->FixedIcon.pIcon, x + pExtras->FixedIcon.xOffset, y + pExtras->FixedIcon.yOffset, pExtras->FixedIcon.iWidth, WINDOW_MAIN );\n\t}\n\n\t//\tDraw variable position left-of-text icons.\n\tfor( iIcon = 0; iIcon != 3; iIcon++ )\n\t{\n\t\tif( pExtras->pIcon[ iIcon ] )\n\t\t{\n\t\t\tx += PREICONGAP;\n\t\t\tif( pExtras->IconKind[ iIcon ] == ICON_SHAPE )\n\t\t\t\tCC_Draw_Shape( pExtras->pIcon[ iIcon ], 0, x, y, WINDOW_MAIN, SHAPE_NORMAL );\n\t\t\t\t//\tPut similar code in here for shapes if used...\n\t\t\telse\n\t\t\t{\n\t\t\t\tCC_Draw_DIB( (char*)pExtras->pIcon[ iIcon ], x, y, 9999, WINDOW_MAIN );\n\t\t\t\tx += DIBWidth( (char*)pExtras->pIcon[ iIcon ] );\n\t\t\t}\n\t\t}\n\t}\n}\n\n//***********************************************************************************************\nint IconListClass::Action(unsigned flags, KeyNumType & key)\n{\n\t//\tOverriding of function is for the sake of MultiSelecting only.\n\tif( iSelectType == 2 )\n\t{\n\t\tif( !( flags & LEFTRELEASE ) )\n\t\t{\n\t\t\tif( !( flags & KEYBOARD ) )\n\t\t\t{\n\t\t\t\tint index = Get_Mouse_Y() - (Y+1);\n\t\t\t\tindex = index / LineHeight;\n\t\t\t\tint iSelected = CurrentTopIndex + index;\n\t\t\t\tiSelected = min( iSelected, List.Count() - 1 );\n\t\t\t\tif( iSelected >= 0 )\n\t\t\t\t\t((IconList_ItemExtras*)ExtrasList[ iSelected ])->bMultiSelected = \n\t\t\t\t\t\t!((IconList_ItemExtras*)ExtrasList[ iSelected ])->bMultiSelected;\n\t\t\t}\n\t\t}\n\t}\n\treturn ListClass::Action( flags, key );\n}\n\n//***********************************************************************************************\n// * IconListClass::Show_Last_Item -- Scrolls listbox down to ensure that last entry is visible.\n//\tajw 07/09/98\nvoid IconListClass::Show_Last_Item()\n{\n\tint iItemLast = List.Count() - 1;\n\tif( iItemLast - LineCount + 1 != CurrentTopIndex )\n\t{\n\t\tFlag_To_Redraw();\n\t\tSet_View_Index( iItemLast - LineCount + 1 );\n\t}\n}\n\n//***********************************************************************************************\nbool IconListClass::bItemIsMultiSelected( int index ) const\n{\n\tif( index < ExtrasList.Count() && index > -1 )\n\t\treturn ( (IconList_ItemExtras*)ExtrasList[ index ] )->bMultiSelected;\n\telse\n\t\treturn false;\n}\n\n//***********************************************************************************************\nvoid IconListClass::MultiSelect( int index, bool bSelect )\n{\n\tif( index < ExtrasList.Count() && index > -1 )\n\t\t( (IconList_ItemExtras*)ExtrasList[ index ] )->bMultiSelected = bSelect;\n}\n\n//***********************************************************************************************\nconst char* IconListClass::Get_Item_ExtraDataString( int index ) const\n{\n\t//\tReturns const pointer to the hidden \"extra data\" string that can be associated with each item.\n\t//\tThis is NULL if no extra data was assigned.\n\tif( index < ExtrasList.Count() && index > -1 )\n\t{\n\t\treturn ( (IconList_ItemExtras*)ExtrasList[ index ] )->szExtraData;\n\t}\n\treturn NULL;\n}\n\n//***********************************************************************************************\nvoid IconListClass::Set_Item_ExtraDataString( int index, const char* szNewString )\n{\n\tif( index < ExtrasList.Count() && index > -1 )\n\t{\n\t\tIconList_ItemExtras* pItemExtra = (IconList_ItemExtras*)ExtrasList[ index ];\n\t\tif( pItemExtra->szExtraData )\n\t\t{\n\t\t\t//\tDelete the existing string.\n\t\t\tdelete [] pItemExtra->szExtraData;\n\t\t}\n\t\tif( szNewString )\n\t\t{\n\t\t\t//\tCopy special data string into new extradata string.\n\t\t\tpItemExtra->szExtraData = new char[ strlen( szNewString ) + 1 ];\n\t\t\tstrcpy( pItemExtra->szExtraData, szNewString );\n\t\t}\n\t\telse\n\t\t\tpItemExtra->szExtraData = NULL;\n\t}\n}\n\t\t\t\t\n//***********************************************************************************************\nvoid* IconListClass::Get_Item_ExtraDataPtr( int index ) const\n{\n\t//\tReturns the hidden \"extra data\" void pointer that can be associated with each item.\n\t//\tThis is NULL if no value was assigned.\n\tif( index < ExtrasList.Count() && index > -1 )\n\t\treturn ( (IconList_ItemExtras*)ExtrasList[ index ] )->pvExtraData;\n\telse\n\t\treturn NULL;\n}\n\n//***********************************************************************************************\nvoid IconListClass::Set_Item_ExtraDataPtr( int index, void* pNewValue )\n{\n\t//\tSets the hidden \"extra data\" void pointer that can be associated with each item.\n\tif( index < ExtrasList.Count() && index > -1 )\n\t\t( (IconList_ItemExtras*)ExtrasList[ index ] )->pvExtraData = pNewValue;\n}\n\n//***********************************************************************************************\nconst IconList_ItemExtras* IconListClass::Get_ItemExtras( int index ) const\n{\n\tif( index < ExtrasList.Count() && index > -1 )\n\t\treturn (IconList_ItemExtras*)ExtrasList[ index ];\n\telse\n\t\treturn NULL;\n}\n\t\t\n//***********************************************************************************************\nconst char* IconListClass::Get_Item_Help( int index ) const\n{\n\t//\tReturns pointer to the string allocated for tooltip help.\n\tif( index < ExtrasList.Count() && index > -1 )\n\t\treturn ( (IconList_ItemExtras*)ExtrasList[ index ] )->szHelp;\n\telse\n\t\treturn NULL;\n}\n\n//***********************************************************************************************\nvoid IconListClass::Clear()\n{\n\t//\tRemoves all items from list.\n\n\t//\tDelete the IconList_ItemExtras structs created to hold extra info on each item.\n\tfor( int i = 0; i < ExtrasList.Count(); i++ )\n\t\tdelete (IconList_ItemExtras*)ExtrasList[ i ];\n\tExtrasList.Clear();\n\n\tif( bDoAlloc )\n\t{\n\t\t//\tDelete all alloc'ed strings.\n\t\tfor( int i = 0; i < List.Count(); i++ )\n\t\t\tdelete [] (char*)List[i];\n\t}\n\n\tList.Clear();\n\tRemove_Scroll_Bar();\n\tCurrentTopIndex = 0;\n}\n\n//***********************************************************************************************\nRemapControlType* IconListClass::Get_Item_Color( int index )\n{\n\tif( index < ExtrasList.Count() && index > -1 )\n\t\treturn ( (IconList_ItemExtras*)ExtrasList[ index ] )->pColorRemap;\n\telse\n\t\treturn NULL;\n}\n\n//***********************************************************************************************\nvoid IconListClass::Set_Item_Color( int index, RemapControlType* pColorRemap )\n{\n\tif( index < ExtrasList.Count() && index > -1 )\n\t\t( (IconList_ItemExtras*)ExtrasList[ index ] )->pColorRemap = pColorRemap;\n}\n\n//***********************************************************************************************\nint IconListClass::Find( const char* szItemToFind )\n{\n\t//\tReturns -1 if szItemToFind is not found as the text BEGINNING one of the list entries, else index of item.\n\t//\tCompare is case-sensitive.\n\tfor( int i = 0; i < List.Count(); i++ )\n\t{\n\t\tif( strncmp( List[ i ], szItemToFind, strlen( szItemToFind ) ) == 0 )\n\t\t\treturn i;\n\t}\n\treturn -1;\n}\n\n//***********************************************************************************************\nint IconListClass::FindColor( RemapControlType* pColorRemap )\n{\n\t//\tReturns -1 if no items of specified color are found, else first index. Assumes colorptr == colorptr is a valid equality test.\n\tfor( int i = 0; i < List.Count(); i++ )\n\t{\n\t\tif( Get_Item_Color( i ) == pColorRemap )\n\t\t\treturn i;\n\t}\n\treturn -1;\n}\n\n//***********************************************************************************************\nbool IconListClass::Set_Item( unsigned int index, const char* szText )\n{\n\t//\tResets the text string allocated for an item.\n\tif( !bDoAlloc || index >= List.Count() )\n\t\treturn false;\n\n\t//\tDelete alloc'ed string.\n\tdelete [] (char*)List[ index ];\n\n\t//\tCopy text to new string.\n\tchar* szTextNew = new char[ strlen( szText ) + 1 ];\n\tstrcpy( szTextNew, szText );\n\n\t//\tReassign List's ptr.\n\tList[ index ] = szTextNew;\n\n\treturn true;\n}\n\n//***********************************************************************************************\nbool IconListClass::Set_Icon( unsigned int index, unsigned int iIconNumber, void* pIcon, ICONKIND IconKind )\n{\n\tif( index >= List.Count() )\n\t\treturn false;\n\n\t//\tSets one of the left-aligned icons.\n\t( (IconList_ItemExtras*)ExtrasList[ index ] )->pIcon[ iIconNumber ] = pIcon;\n\t( (IconList_ItemExtras*)ExtrasList[ index ] )->IconKind[ iIconNumber ] = IconKind;\n\treturn true;\n}\n\n//***********************************************************************************************\nint IconListClass::GetRealWidth()\t\t//\tsigh\n{\n\tif( IsScrollActive )\n\t\treturn Width + ScrollGadget.Width;\n\treturn Width;\n}\n\n//***********************************************************************************************\nvoid IconListClass::Resize( int x, int y, int w, int h )\n{\n\tRemove_Scroll_Bar();\t//\tIf there is one.\n\n\tX = x;\n\tY = y;\n\tWidth = w;\n\tHeight = h;\n\n\tSet_Position( x, y );\n\n\tLineCount = (h-1) / LineHeight;\n\n\n\tif (List.Count() > LineCount) {\n\t\tAdd_Scroll_Bar();\n\t}\n\n\tFlag_To_Redraw();\n}\n\n//***********************************************************************************************\nint IconListClass::IndexUnderMouse()\n{\n\t//\tReturns index of line that mouse is currently over, or -1 for mouse not hitting valid index.\n\t//\tAssumes that x position of mouse is already known to be over the iconlist.\n\tint index = Get_Mouse_Y() - (Y+1);\n\tindex = index / LineHeight + CurrentTopIndex;\n\tif( index > List.Count() - 1 || index < 0 )\n\t\treturn -1;\n\treturn index;\n}\n\n//***********************************************************************************************\nint IconListClass::OffsetToIndex( int iIndex, int y )\n{\n\t//\tFinds the current offset of item iIndex from the current top view index, in pixels, and add it to y.\n\treturn y + ( iIndex - CurrentTopIndex ) * LineHeight;\n}\n\n//***********************************************************************************************\n//***********************************************************************************************\n//\t* Format_Window_String_New\n//\tFunctions like Format_Window_String except it fixes an infinite loop bug that occurred when strings\n//\tlacked suitable break points, eliminates the '@' as an escape character, and operates differently\n//\tin that it leaves the original string along, writing results instead to a second string parameter,\n//\tthat is iExtraChars longer than the original string. This is all a big hack so that I can insert \n//\textra break characters when a break in a long single word has to be made.\n//\tHey - it's better than an infinite loop that forces you to reset your machine, as in the original code...\n\nint Format_Window_String_New( const char* string, int maxlinelen, int& width, int& height, char* szReturn, int iExtraChars )\n{\n\tint\tlinelen;\n\tint\tlines = 0;\n\twidth\t= 0;\n\theight = 0;\n\n\t// In no string was passed in, then there are no lines.\n\tif (!string) return(0);\n\n\t// While there are more letters left divide the line up.\n\twhile (*string) {\n\t\tlinelen = 0;\n\t\theight += FontHeight + FontYSpacing;\n\t\tlines++;\n\n\t\t// While the current line is less then the max length...\n\t\t*szReturn = *string;\n\t\tlinelen += Char_Pixel_Width( *string );\n\t\twhile ( linelen < maxlinelen && *string != '\\r' && *string != '\\0' )\n\t\t{\n\t\t\t*++szReturn = *++string;\n\t\t\tlinelen += Char_Pixel_Width( *string );\n\t\t}\n\n\t\t// if the line is too long...\n\t\tif (linelen >= maxlinelen) \n\t\t{\n\t\t\t/*\n\t\t\t**\tBack up to an appropriate location to break.\n\t\t\t*/\n\t\t\tconst char* stringOverEnd = string;\n\t\t\twhile( linelen > 0 && *string != ' ' && *string != '\\r' && *string != '\\0' )\n\t\t\t{\n\t\t\t\tlinelen -= Char_Pixel_Width(*string--);\n\t\t\t}\n\t\t\tif( linelen <= 0 )\n\t\t\t{\n\t\t\t\t//\tWe could not find a nice break point.\n\t\t\t\t//\tGo back one char from over-the-end point and add in a break there.\n\t\t\t\tstring = stringOverEnd - 1;\n\t\t\t\tif( iExtraChars > 0 )\n\t\t\t\t\tiExtraChars--;\t\t\t//\tOne less to make use of later.\n\t\t\t\telse\n\t\t\t\t\t//\tWe've used up all our extras characters.\n\t\t\t\t\t//\tPut in a break below by wiping out a valid char here.\n\t\t\t\t\tszReturn--;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//\tBack up szReturn to same location.\n\t\t\t\tszReturn -= ( stringOverEnd - string );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tRecord the largest width of the worst case string.\n\t\t*/\n\t\tif (linelen > width) {\n\t\t\twidth = linelen;\n\t\t}\n\n\t\t/*\n\t\t**\tForce a break at the end of the line.\n\t\t*/\n\t\tif (*string) {\n\t\t \t*szReturn++ = '\\r';\n\t\t\tstring++;\n\t\t}\n\t}\n\treturn(lines);\n}\n\n//***********************************************************************************************\nvoid CC_Draw_DIB( const char* pDIB, int xDest, int yDest, int iWidth, WindowNumberType window )\n{\n\t//\tA very basic DIB drawing routine. No clipping. No edge of window overrun checking.\n\t//\tIf iWidth is too large, default width of dib is used.\n\t//\tIf iWidth is negative, dib isn't drawn.\n\tif( pDIB && iWidth >= 0 )\n\t{\n\n\t\tint iWidthDIB = DIBWidth( pDIB );\n\t\tint iHeight = DIBHeight( pDIB );\n\t\tconst char* pBits = FindDIBBits( pDIB );\n\n\t\tint iSrcPitch = ( iWidthDIB + 3 ) & ~3;\n\n\t\tif( iWidth > iWidthDIB )\n\t\t\tiWidth = iWidthDIB;\n\n\t\tGraphicViewPortClass draw_window(\tLogicPage->Get_Graphic_Buffer(),\n\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWX] + LogicPage->Get_XPos(),\n\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWY] + LogicPage->Get_YPos(),\n\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWWIDTH],\n\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWHEIGHT] );\n\t\tif( draw_window.Lock() )\n\t\t{\n\t\t\tint iDestPitch = draw_window.Get_Pitch() + draw_window.Get_Width();\t//\tMeaning of \"Pitch\" in this class seems to mean the eol skip.\n\t\t\tchar* pLineDest = (char*)draw_window.Get_Offset() + xDest + ( yDest + iHeight - 1 ) * iDestPitch;\n\n\t\t\tconst char* pLineSrc = pBits;\n\t\t\tfor( int y = 0; y != iHeight; y++ )\n\t\t\t{\n\t\t\t\tchar* pDest = pLineDest;\n\t\t\t\tconst char* pSrc = pLineSrc;\n\t\t\t\tfor( int x = 0; x != iWidth; x++ )\n\t\t\t\t{\n\t\t\t\t\t*pDest++ = *pSrc++;\n\t\t\t\t}\n\t\t\t\tpLineDest -= iDestPitch;\n\t\t\t\tpLineSrc += iSrcPitch;\n\t\t\t}\n\t\t\tdraw_window.Unlock();\n\t\t}\n\t}\n//\telse\n//\t\tdebugprint( \"CC_Draw_DIB bad case ------------ pDib %i, iWidth %i\\n\", pDIB, iWidth );\n}\n\n\n#endif\n"
  },
  {
    "path": "CODE/ICONLIST.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifdef WOLAPI_INTEGRATION\n\n/***************************************************************************\n * IconListClass -- Exactly like ListClass, but displays an icon as well\n *                  (actually a 'shape' image), left-aligned, covering\n *                  any text that happens to be there...\n *                  Also, I've added the option of making this class\n *                  responsible for the mem alloc. of the strings, and\n *\t\t\t\t\tan automatic limiting of entries to a set maximum.\n *                                                                         *\n * HISTORY:    07/07/1998 ajw : Created, largely in hack mode.             *\n *=========================================================================*/\n\n#ifndef ICONLIST_H\n#define ICONLIST_H\n\n#include \"function.h\"\n#include \"vector.h\"\n\nenum ICONKIND\n{\n\tICON_SHAPE = 0,\t\t//\tpIcon points to a shape.\n\tICON_DIB\t\t\t//\tpIcon points to DIBitmap data.\n};\n\nstruct FIXEDICON\t\t//\tFor putting icons in list entries at a specific fixed offset.\n{\n\tvoid*\t\tpIcon;\n\tICONKIND\tIconKind;\n\tint\t\t\txOffset;\n\tint\t\t\tyOffset;\n\tint\t\t\tiWidth;\n};\n\nstruct IconList_ItemExtras\n{\n\tIconList_ItemExtras() : bMultiSelected( false ), szHelp( NULL ), szExtraData( NULL ), pvExtraData( NULL )\n\t{\n\t\tpIcon[0] = NULL;\n\t\tpIcon[1] = NULL;\n\t\tpIcon[2] = NULL;\n\t}\n\tvirtual ~IconList_ItemExtras()\n\t{\n\t\tdelete [] szHelp;\n\t\tdelete [] szExtraData;\n\t}\n\n\tbool\t\tbMultiSelected;\t\t//\tTrue if selected when bMultiSelect is on.\n\tvoid*\t\tpIcon[3];\t\t\t//\tIcon that appears before an item.\n\tICONKIND\tIconKind[3];\t\t//\tSpecifies what kind of image data pIcon points to.\n\tchar*\t\tszHelp;\t\t\t\t//\tTooltip help string that can be associated with item. Allocated and deleted here.\n\tchar*\t\tszExtraData;\t\t//\tExtra string that can be associated with item. Allocated and deleted here.\n\tvoid*\t\tpvExtraData;\t\t//\tHidden pointer that can be associated with item.\n\tRemapControlType*\tpColorRemap;\t//\tPointer to a color remap, or null for default colored text.\n\tFIXEDICON\tFixedIcon;\n};\n\nclass IconListClass : public ListClass\n{\n\tpublic:\n\t\tIconListClass( int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down, bool bResponsibleForStringAlloc = FALSE, int iSelectionType = 1, int iMaxItemsSaved = 0 );\n//\t\tIconListClass( const IconListClass& list );\n\t\tvirtual ~IconListClass( void );\n\n\t\tvirtual int Add_Item( char const * text );\n\t\tvirtual int Add_Item( const char* text, const char* szHelp,\n\t\t\t\t\t\t\t\tvoid* pIcon0, ICONKIND IconKind0, const char* szExtraDataString = NULL, \n\t\t\t\t\t\t\t\tvoid* pvExtraDataPtr = NULL, RemapControlType* pColorRemap = NULL,\n\t\t\t\t\t\t\t\tvoid* pIcon1 = NULL, ICONKIND IconKind1 = ICON_SHAPE, \n\t\t\t\t\t\t\t\tvoid* pIcon2 = NULL, ICONKIND IconKind2 = ICON_SHAPE,\n\t\t\t\t\t\t\t\tvoid* pFixedIcon = NULL, ICONKIND FixedIconKind = ICON_SHAPE, int iXFixedIcon = 0, int iYFixedIcon = 0, int iFixedIconWidth = -1 );\n\n\t\tvirtual int Add_Item( int text );\n\t\tvirtual int Add_Item( int text, const char* szHelp,\n\t\t\t\t\t\t\t\tvoid* pIcon0, ICONKIND IconKind0, const char* szExtraDataString = NULL, \n\t\t\t\t\t\t\t\tvoid* pvExtraDataPtr = NULL, RemapControlType* pColorRemap = NULL,\n\t\t\t\t\t\t\t\tvoid* pIcon1 = NULL, ICONKIND IconKind1 = ICON_SHAPE, \n\t\t\t\t\t\t\t\tvoid* pIcon2 = NULL, ICONKIND IconKind2 = ICON_SHAPE,\n\t\t\t\t\t\t\t\tvoid* pFixedIcon = NULL, ICONKIND FixedIconKind = ICON_SHAPE, int iXFixedIcon = 0, int iYFixedIcon = 0, int iFixedIconWidth = -1 );\n\n//\t\tvirtual int Add_Scroll_Bar(void);\n//\t\tvirtual void Bump(int up);\n//\t\tvirtual int Count(void) const {return List.Count();};\n//\t\tvirtual int Current_Index(void) const;\n//\t\tvirtual char const * Current_Item(void) const;\n//\t\tvirtual int Draw_Me(int forced);\n//\t\tvirtual char const * Get_Item(int index) const;\n//\t\tvirtual int Step_Selected_Index(int forward);\n//\t\tvirtual void Flag_To_Redraw(void);\n\n//\t\tvirtual void Peer_To_Peer(unsigned flags, KeyNumType & key, ControlClass & whom);\n\t\tvirtual void Remove_Item( char const * text );\n\t\tvirtual void Remove_Item( int );\n//\t\tvirtual int  Remove_Scroll_Bar(void);\n//\t\tvirtual void Set_Selected_Index(int index);\n//\t\tvirtual void Set_Selected_Index(char const * text);\n//\t\tvirtual void Set_Tabs(int const * tabs);\n//\t\tvirtual int  Set_View_Index(int index);\n//\t\tvirtual void Step(int up);\n//\t\tvirtual void Set_Position(int x, int y);\n\n\t\t/*\n\t\t** These overloaded list routines handle adding/removing the scroll bar\n\t\t** automatically when the list box is added or removed.\n\t\t*/\n//\t\tvirtual LinkClass & Add(LinkClass & object);\n//\t\tvirtual LinkClass & Add_Tail(LinkClass & object);\n//\t\tvirtual LinkClass & Add_Head(LinkClass & object);\n//\t\tvirtual GadgetClass * Remove(void);\n\n\t\tvirtual void\t\tShow_Last_Item();\n\t\tvirtual bool\t\tbItemIsMultiSelected( int index ) const;\n\t\tvirtual void\t\tMultiSelect( int index, bool bSelect );\n\t\tvirtual const char*\tGet_Item_ExtraDataString( int index ) const;\n\t\tvirtual void\t\tSet_Item_ExtraDataString( int index, const char* szNewString );\n\t\tvirtual void*\t\tGet_Item_ExtraDataPtr( int index ) const;\n\t\tvirtual void\t\tSet_Item_ExtraDataPtr( int index, void* pNewValue );\n\t\tconst char*\t\t\tGet_Item_Help( int index ) const;\n\t\tvirtual RemapControlType*\tGet_Item_Color( int index );\n\t\tvirtual void\t\t\t\tSet_Item_Color( int index, RemapControlType* pColorRemap );\n\t\tvirtual const IconList_ItemExtras*\tGet_ItemExtras( int index ) const;\n\t\tvirtual void\t\tClear();\n\t\tvirtual int\t\t\tGet_View_Index()\t{\treturn CurrentTopIndex;\t\t}\n\t\tbool bScrollBeingDragged()\n\t\t{\n\t\t\t//\tReturns true if the scroll bar of the list is being dragged by the user.\n\t\t\treturn ( GadgetClass::StuckOn == &ScrollGadget );\n\t\t}\n\n\t\tvirtual int\t\t\tFind( const char* szItemToFind );\n\t\tvirtual int\t\t\tFindColor( RemapControlType* pColorRemap );\n\n\t\tvirtual bool\t\tSet_Item( unsigned int index, const char* szText );\n\t\tvirtual bool\t\tSet_Icon( unsigned int index, unsigned int iIconNumber, void* pIcon, ICONKIND IconKind );\n\n\t\tvirtual int\t\t\tGetRealWidth();\n\t\tvirtual void\t\tResize( int x, int y, int w, int h );\n\t\tvirtual int\t\t\tIndexUnderMouse();\n\t\tvirtual int\t\t\tOffsetToIndex( int iIndex, int y );\n\n\t\tvirtual int\t\t\tSetSelectType( int iSelectTypeNew )\n\t\t{\n\t\t\t//\tProvided to enable horrible hacks, mainly involved with dealing with ListClass's inability\n\t\t\t//\tto have no item selected...\n\t\t\tint iSelectTypeOld = iSelectType;\n\t\t\tiSelectType = iSelectTypeNew;\n\t\t\treturn iSelectTypeOld;\n\t\t}\n\n\tprotected:\n\t\tvirtual int  Action(unsigned flags, KeyNumType &key);\n\t\tvirtual void Draw_Entry( int index, int x, int y, int width, int selected );\n\n\t\tvirtual int  Add_Item_Detail( const char* szToken, const char* szHelp,\n\t\t\t\t\t\t\t\t\t\tvoid* pIcon0, ICONKIND IconKind0, const char* szExtraDataString, \n\t\t\t\t\t\t\t\t\t\tvoid* pvExtraData, RemapControlType* pColorRemap,\n\t\t\t\t\t\t\t\t\t\tvoid* pIcon1, ICONKIND IconKind1, void* pIcon2, ICONKIND IconKind2,\n\t\t\t\t\t\t\t\t\t\tvoid* pFixedIcon, ICONKIND FixedIconKind, int iXFixedIcon, int iYFixedIcon, int iFixedIconWidth );\n\n\t\t//\tThe list of Icons.\n\t\t//DynamicVectorClass<void*> IconList;\n\t\t//DynamicVectorClass< IconList_ItemExtras* > ExtrasList;\t\tajw: creates hellacious linking problems\n\t\tDynamicVectorClass< void* > ExtrasList;\n\n\t\tbool bDoAlloc;\t\t//\tTrue if I am responsible for mem. allocation/deletion of strings.\n//\t\tbool bMultiSelect;\t//\tTrue if we are using the multiple item selection feature.\n\t\tint iSelectType;\t//\t0 for no selection shown, 1 for normal ListClass selection, 2 for n multiple selections\n\t\tint\tiMaxItems;\t\t//\tNumber of items to limit list to, if bDoAlloc is true.\n};\n\n#endif\n\n#endif\n"
  },
  {
    "path": "CODE/IDATA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/IDATA.CPP 3     3/16/97 10:16p Joe_b $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : IDATA.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 15, 1994                                              *\n *                                                                                             *\n *                  Last Update : July 19, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   InfantryTypeClass::As_Reference -- Fetches a reference to the infantry type specified.    *\n *   InfantryTypeClass::Create_And_Place -- Creates and places infantry object onto the map.   *\n *   InfantryTypeClass::Create_One_Of -- Creates an infantry object.                           *\n *   InfantryTypeClass::Display -- Displays a generic infantry object.                         *\n *   InfantryTypeClass::From_Name -- Converts an ASCII name into an infantry type number.      *\n *   InfantryTypeClass::Full_Name -- Fetches the full name text number.                        *\n *   InfantryTypeClass::Get_Cameo_Data -- Fetches the small cameo shape for sidebar strip.     *\n *   InfantryTypeClass::InfantryTypeClass -- Constructor for infantry type class objects.      *\n *   InfantryTypeClass::Init_Heap -- Initialize the infantry type class heap.                  *\n *   InfantryTypeClass::Occupy_List -- Returns with default infantry occupation list.          *\n *   InfantryTypeClass::One_Time -- Performs any one time processing for infantry system.      *\n *   InfantryTypeClass::Prep_For_Add -- Prepares the scenario editor for adding of infantry obj*\n *   InfantryTypeClass::Read_INI -- Fetches infantry override values from the INI database.    *\n *   InfantryTypeClass::operator delete -- Frees an infantry type class object.                *\n *   InfantryTypeClass::operator new -- Allocate an infanty type class object.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"type.h\"\n\nstatic DoInfoStruct DogDoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{0,\t1,\t1},\t\t\t\t\t// DO_PRONE\t\t\t// NA\n\t{8,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{104,\t14,14},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{0,\t0,\t0},\t\t\t\t\t// DO_LIE_DOWN\t\t// NA\n\t{56,\t6,\t6},\t\t\t\t\t// DO_CRAWL\n\t{0,\t0,\t0},\t\t\t\t\t// DO_GET_UP\n\t{104,\t14,14},\t\t\t\t\t// DO_FIRE_PRONE\n\t{216,\t18,0},\t\t\t\t\t// DO_IDLE1\n\t{216,\t18,0},\t\t\t\t\t// DO_IDLE2\n\t{235,\t7,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{242,\t9,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{242,\t9,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{242,\t9, 0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{251,\t14,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE2\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE2\n\t{106,\t12,14},\t\t\t\t\t//\tDO_DOG_MAUL\n};\n\nstatic DoInfoStruct E1DoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{192,\t1,\t8},\t\t\t\t\t// DO_PRONE\n\t{16,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{64,\t8,\t8},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{128,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{144,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{176,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{192,\t6,\t8},\t\t\t\t\t// DO_FIRE_PRONE\n\t{256,\t16,0},\t\t\t\t\t// DO_IDLE1\n\t{272,\t16,0},\t\t\t\t\t// DO_IDLE2\n\t{382-94,\t8,\t0},\t\t\t\t// DO_GUN_DEATH\n\t{398-94,\t8,\t0},\t\t\t\t// DO_EXPLOSION_DEATH\n\t{398-94,\t8,\t0},\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{406-94,\t12,0},\t\t\t\t// DO_GRENADE_DEATH\n\t{418-94,\t18,0},\t\t\t\t// DO_FIRE_DEATH\n\t{436-94,\t3,\t3},\t\t\t\t// DO_GESTURE1\n\t{460-94,\t3,\t3},\t\t\t\t// DO_SALUTE1\n\t{484-94,\t3,\t3},\t\t\t\t// DO_GESTURE2\n\t{508-94,\t3,\t3},\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct E2DoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{288,\t1,\t12},\t\t\t\t\t// DO_PRONE\n\t{16,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{64,\t20,20},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{224,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{240,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{272,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{288,\t8,\t12},\t\t\t\t\t// DO_FIRE_PRONE\n\t{384,\t16,0},\t\t\t\t\t// DO_IDLE1\n\t{400,\t16,0},\t\t\t\t\t// DO_IDLE2\n\t{510-94,\t8,\t0},\t\t\t\t// DO_GUN_DEATH\n\t{526-94,\t8,\t0},\t\t\t\t// DO_EXPLOSION_DEATH\n\t{526-94,\t8,\t0},\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{534-94,\t12,0},\t\t\t\t// DO_GRENADE_DEATH\n\t{546-94,\t18,0},\t\t\t\t// DO_FIRE_DEATH\n\t{564-94,\t3,\t3},\t\t\t\t// DO_GESTURE1\n\t{588-94,\t3,\t3},\t\t\t\t// DO_SALUTE1\n\t{612-94,\t3,\t3},\t\t\t\t// DO_GESTURE2\n\t{636-94,\t3,\t3},\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct E3DoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{192,\t1,10},\t\t\t\t\t// DO_PRONE\n\t{16,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{64,\t8,\t8},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{128,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{144,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{176,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{192,\t10,10},\t\t\t\t\t// DO_FIRE_PRONE\n\t{272,\t16,0},\t\t\t\t\t// DO_IDLE1\n\t{288,\t16,0},\t\t\t\t\t// DO_IDLE2\n\t{398-94,\t8,\t0},\t\t\t\t// DO_GUN_DEATH\n\t{414-94,\t8,\t0},\t\t\t\t// DO_EXPLOSION_DEATH\n\t{414-94,\t8,\t0},\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{422-94,\t12,0},\t\t\t\t// DO_GRENADE_DEATH\n\t{434-94,\t18,0},\t\t\t\t// DO_FIRE_DEATH\n\t{452-94,\t3,\t3},\t\t\t\t// DO_GESTURE1\n\t{476-94,\t3,\t3},\t\t\t\t// DO_SALUTE1\n\t{500-94,\t3,\t3},\t\t\t\t// DO_GESTURE2\n\t{524-94,\t3,\t3},\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct E4DoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{256,\t1,16},\t\t\t\t\t// DO_PRONE\n\t{16,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{64,\t16,16},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{192,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{208,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{240,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{256,\t16,16},\t\t\t\t\t// DO_FIRE_PRONE\n\t{384,\t16,0},\t\t\t\t\t// DO_IDLE1\n\t{400,\t16,0},\t\t\t\t\t// DO_IDLE2\n\t{510-94,\t8,\t0},\t\t\t\t// DO_GUN_DEATH\n\t{526-94,\t8,\t0},\t\t\t\t// DO_EXPLOSION_DEATH\n\t{526-94,\t8,\t0},\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{534-94,\t12,0},\t\t\t\t// DO_GRENADE_DEATH\n\t{546-94,\t18,0},\t\t\t\t// DO_FIRE_DEATH\n\t{564-94,\t3,\t3},\t\t\t\t// DO_GESTURE1\n\t{588-94,\t3,\t3},\t\t\t\t// DO_SALUTE1\n\t{612-94,\t3,\t3},\t\t\t\t// DO_GESTURE2\n\t{636-94,\t3,\t3},\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct E6DoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{82,\t1,\t4},\t\t\t\t\t// DO_PRONE\n\t{16,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{0,\t0,\t0},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{67,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{82,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{114,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{0,\t0,\t0},\t\t\t\t\t// DO_FIRE_PRONE\n\t{130,\t16,0},\t\t\t\t\t// DO_IDLE1\n\t{130,\t16,0},\t\t\t\t\t// DO_IDLE2\n\t{146,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{154,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{162,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{162,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{182,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{200,\t3,\t3},\t\t\t\t\t// DO_GESTURE1\n\t{224,\t3,\t3},\t\t\t\t\t// DO_SALUTE1\n\t{200,\t3,\t3},\t\t\t\t\t// DO_GESTURE2\n\t{224,\t3,\t3},\t\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct E7DoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{128,\t1,\t4},\t\t\t\t\t// DO_PRONE\n\t{8,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{56,\t7,\t7},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{113,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{128,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{161,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{176,\t7,\t7},\t\t\t\t\t// DO_FIRE_PRONE\n\t{232,\t17,0},\t\t\t\t\t// DO_IDLE1\n\t{249,\t13,0},\t\t\t\t\t// DO_IDLE2\n\t{262,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{270,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{278,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{286,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{298,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE2\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\n//Spy\nstatic DoInfoStruct SpyDoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{144,\t1,\t4},\t\t\t\t\t// DO_PRONE\n\t{16,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{64,\t8,\t8},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{128,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{144,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{176,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{192,\t8,\t8},\t\t\t\t\t// DO_FIRE_PRONE\n\t{256,\t14,0},\t\t\t\t\t// DO_IDLE1\n\t{270,\t18,0},\t\t\t\t\t// DO_IDLE2\n\t{288,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{296,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{304,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{312,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{324,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE2\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct E9DoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{72,\t1,\t4},\t\t\t\t\t// DO_PRONE\n\t{8,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{0,\t0,\t0},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{56,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{72,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{108,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{0,\t0,\t0},\t\t\t\t\t// DO_FIRE_PRONE\n\t{120,\t19,0},\t\t\t\t\t// DO_IDLE1\n\t{120,\t19,0},\t\t\t\t\t// DO_IDLE2\n\t{139,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{147,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{155,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{163,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{175,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE2\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct MedicDoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{130,\t1,\t4},\t\t\t\t\t// DO_PRONE\n\t{8,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{56,\t28,0},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{114,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{130,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{162,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{56,\t28,0},\t\t\t\t\t// DO_FIRE_PRONE\n\t{178,\t15,0},\t\t\t\t\t// DO_IDLE1\n\t{178,\t15,0},\t\t\t\t\t// DO_IDLE2\n\t{193,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{210,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{202,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{217,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{229,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE2\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct GeneralDoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{104,\t1,\t4},\t\t\t\t\t// DO_PRONE\n\t{8,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{56,\t4,\t4},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{88,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{104,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{136,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{152,\t4,\t4},\t\t\t\t\t// DO_FIRE_PRONE\n\t{184,\t26,0},\t\t\t\t\t// DO_IDLE1\n\t{184,\t26,0},\t\t\t\t\t// DO_IDLE2\n\t{210,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{226,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{218,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{234,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{246,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE2\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct CivilianDoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{0,\t1,\t1},\t\t\t\t\t// DO_PRONE\t\t\t\t// N/A\n\t{56, \t6,\t6},\t\t\t\t\t// DO_WALK\n\t{205-85,\t4, 4},\t\t\t\t// DO_FIRE_WEAPON\n\t{0, \t1,\t1},\t\t\t\t\t// DO_LIE_DOWN\t\t\t// N/A\n\t{8, \t6,\t6},\t\t\t\t\t// DO_CRAWL\n\t{0, \t1,\t1},\t\t\t\t\t// DO_GET_UP\t\t\t// N/A\n\t{205-85,\t4,\t4},\t\t\t\t// DO_FIRE_PRONE\n\t{189-85,\t10,0},\t\t\t\t// DO_IDLE1\n\t{199-85,\t6,\t0},\t\t\t\t// DO_IDLE2\n\t{152,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{160,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{160,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{168,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{180,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{0, \t1,\t0},\t\t\t\t\t// DO_GESTURE1\t\t\t// N/A\n\t{0, \t1,\t0},\t\t\t\t\t// DO_SALUTE1\t\t\t// N/A\n\t{0, \t1,\t0},\t\t\t\t\t// DO_GESTURE2\t\t\t// N/A\n\t{0, \t1,\t0},\t\t\t\t\t// DO_SALUTE2\t\t\t// N/A\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct EinsteinDoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{0,\t1,\t1},\t\t\t\t\t// DO_PRONE\t\t\t\t// N/A\n\t{56, \t6,\t6},\t\t\t\t\t// DO_WALK\n\t{205-92,\t4, 4},\t\t\t\t// DO_FIRE_WEAPON\n\t{0, \t1,\t1},\t\t\t\t\t// DO_LIE_DOWN\t\t\t// N/A\n\t{8, \t6,\t6},\t\t\t\t\t// DO_CRAWL\n\t{0, \t1,\t1},\t\t\t\t\t// DO_GET_UP\t\t\t// N/A\n\t{0,\t0,\t0},\t\t\t\t\t// DO_FIRE_PRONE\n\t{104,\t16,0},\t\t\t\t\t// DO_IDLE1\n\t{104,\t16,0},\t\t\t\t\t// DO_IDLE2\n\t{212-92,\t8,\t0},\t\t\t\t// DO_GUN_DEATH\n\t{220-92,\t8,\t0},\t\t\t\t// DO_EXPLOSION_DEATH\n\t{228-92,\t12,0},\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{228-92,\t12,0},\t\t\t\t// DO_GRENADE_DEATH\n\t{240-92,\t17,0},\t\t\t\t// DO_FIRE_DEATH\n\t{0, \t1,\t0},\t\t\t\t\t// DO_GESTURE1\t\t\t// N/A\n\t{0, \t1,\t0},\t\t\t\t\t// DO_SALUTE1\t\t\t// N/A\n\t{0, \t1,\t0},\t\t\t\t\t// DO_GESTURE2\t\t\t// N/A\n\t{0, \t1,\t0},\t\t\t\t\t// DO_SALUTE2\t\t\t// N/A\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\n// Attack dogs\nstatic InfantryTypeClass const Dog(\n\tINFANTRY_DOG,\t\t\t\t// Infantry type number.\n\tTXT_GUARD_DOG,\t\t\t\t// Translate name number for infantry type.\n\t\"DOG\",\t\t\t\t\t\t// INI name for infantry.\n\t0x0015,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_FULL,\t\t\t\t\t// Transport pip shape/color to use.\n\tDogDoControls,\n\t1,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t1,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Minigunners\nstatic InfantryTypeClass const E1(\n\tINFANTRY_E1,\t\t\t\t// Infantry type number.\n\tTXT_E1,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"E1\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_FULL,\t\t\t\t\t// Transport pip shape/color to use.\n\tE1DoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Grenadiers\nstatic InfantryTypeClass const E2(\n\tINFANTRY_E2,\t\t\t\t// Infantry type number.\n\tTXT_E2,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"E2\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_FULL,\t\t\t\t\t// Transport pip shape/color to use.\n\tE2DoControls,\n\t14,\t\t\t\t\t\t\t// Frame of projectile launch.\n\t6,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Bazooka\nstatic InfantryTypeClass const E3(\n\tINFANTRY_E3,\t\t\t\t// Infantry type number.\n\tTXT_E3,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"E3\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_FULL,\t\t\t\t\t// Transport pip shape/color to use.\n\tE3DoControls,\n\t3,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t3,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Flamethrower\nstatic InfantryTypeClass const E4(\n\tINFANTRY_E4,\t\t\t\t// Infantry type number.\n\tTXT_E4,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"E4\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_FULL,\t\t\t\t\t// Transport pip shape/color to use.\n\tE4DoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Renovator\nstatic InfantryTypeClass const E6(\n\tINFANTRY_RENOVATOR,\t\t\t\t// Infantry type number.\n\tTXT_E6,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"E6\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tE6DoControls,\n\t3,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t3,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Spy\nstatic InfantryTypeClass const E8(\n\tINFANTRY_SPY,\t\t\t\t// Infantry type number.\n\tTXT_E8,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"SPY\",\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tSpyDoControls,\n\t3,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t3,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Thief\nstatic InfantryTypeClass const E9(\n\tINFANTRY_THIEF,\t\t\t\t// Infantry type number.\n\tTXT_THIEF,\t\t\t\t\t// Translate name number for infantry type.\n\t\"THF\",\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tE9DoControls,\n\t3,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t3,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Tanya\nstatic InfantryTypeClass const E7(\n\tINFANTRY_TANYA,\t\t\t// Infantry type number.\n\tTXT_E7,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"E7\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_COMMANDO,\t\t\t\t// Transport pip shape/color to use.\n\tE7DoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const Medic(\n\tINFANTRY_MEDIC,\t\t\t// Infantry type number.\n\tTXT_MEDIC,\t\t\t\t\t// Translate name number for infantry type.\n\t\"MEDI\",\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tMedicDoControls,\n\t25,\t\t\t\t\t\t\t// Frame of projectile launch.\n\t25,\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const General(\n\tINFANTRY_GENERAL,\t\t\t// Infantry type number.\n\tTXT_GENERAL,\t\t\t\t// Translate name number for infantry type.\n\t\"GNRL\",\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tGeneralDoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Civilians\nstatic InfantryTypeClass const C1(\n\tINFANTRY_C1,\t\t\t\t// Infantry type number.\n\tTXT_C1,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C1\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const C2(\n\tINFANTRY_C2,\t\t\t\t// Infantry type number.\n\tTXT_C2,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C2\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\ttrue,\t\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\tRemapCiv2\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const C3(\n\tINFANTRY_C3,\t\t\t\t// Infantry type number.\n\tTXT_C3,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C3\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\ttrue,\t\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const C4(\n\tINFANTRY_C4,\t\t\t\t// Infantry type number.\n\tTXT_C4,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C4\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\ttrue,\t\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\ttrue,\t\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\tRemapCiv4\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const C5(\n\tINFANTRY_C5,\t\t\t\t// Infantry type number.\n\tTXT_C5,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C5\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\ttrue,\t\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\tRemapCiv5\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const C6(\n\tINFANTRY_C6,\t\t\t\t// Infantry type number.\n\tTXT_C6,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C6\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\ttrue,\t\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\tRemapCiv6\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const C7(\n\tINFANTRY_C7,\t\t\t\t// Infantry type number.\n\tTXT_C7,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C7\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\ttrue,\t\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\tRemapCiv7\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const C8(\n\tINFANTRY_C8,\t\t\t\t// Infantry type number.\n\tTXT_C8,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C8\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\ttrue,\t\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\tRemapCiv8\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const C9(\n\tINFANTRY_C9,\t\t\t\t// Infantry type number.\n\tTXT_C9,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C9\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\ttrue,\t\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\tRemapCiv9\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Nikoomba\nstatic InfantryTypeClass const C10(\n\tINFANTRY_C10,\t\t\t\t// Infantry type number.\n\tTXT_C10,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C10\",\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\ttrue,\t\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\tRemapCiv10\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const Einstein(\n\tINFANTRY_EINSTEIN,\t\t// Infantry type number.\n\tTXT_EINSTEIN,\t\t\t\t// Translate name number for infantry type.\n\t\"EINSTEIN\",\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tEinsteinDoControls,\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const Delphi(\n\tINFANTRY_DELPHI,\t\t\t// Infantry type number.\n\tTXT_DELPHI,\t\t\t\t\t// Translate name number for infantry type.\n\t\"DELPHI\",\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const DrChan(\n\tINFANTRY_CHAN,\t\t\t\t// Infantry type number.\n\tTXT_CHAN,\t\t\t\t\t// Translate name number for infantry type.\n\t\"CHAN\",\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tEinsteinDoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\n// Shock Trooper\nstatic InfantryTypeClass const ShockTrooper(\n\tINFANTRY_SHOCK,\t\t\t// Infantry type number.\n\tTXT_SHOCKTROOPER,\t\t\t// Translate name number for infantry type.\n\t\"SHOK\",\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_FULL,\t\t\t\t\t// Transport pip shape/color to use.\n\tE4DoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n\nstatic InfantryTypeClass const Mechanic(\n\tINFANTRY_MECHANIC,\t\t// Infantry type number.\n\tTXT_MECHANIC,\t\t\t\t\t// Translate name number for infantry type.\n\t\"MECH\",\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tMedicDoControls,\n\t25,\t\t\t\t\t\t\t// Frame of projectile launch.\n\t25,\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n#endif\n\n/***********************************************************************************************\n * InfantryTypeClass::InfantryTypeClass -- Constructor for infantry type class objects.        *\n *                                                                                             *\n *    This routine will construct the infantry type objects. It is use to create the static    *\n *    infantry types that are used to give each of the infantry objects their characteristics. *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *   02/16/1996 JLB : Greatly simplified.                                                      *\n *=============================================================================================*/\nInfantryTypeClass::InfantryTypeClass (\n\t\t\t\t\t\tInfantryType type,\n\t\t\t\t\t\tint name,\n\t\t\t\t\t\tchar const * ininame,\n\t\t\t\t\t\tint verticaloffset,\n\t\t\t\t\t\tint primaryoffset,\n\t\t\t\t\t\tbool is_female,\n\t\t\t\t\t\tbool is_crawling,\n\t\t\t\t\t\tbool is_civilian,\n\t\t\t\t\t\tbool is_remap_override,\n\t\t\t\t\t\tbool is_nominal,\n\t\t\t\t\t\tbool is_theater,\n\t\t\t\t\t\tPipEnum pip,\n\t\t\t\t\t\tDoInfoStruct const * control,\n\t\t\t\t\t\tint firelaunch,\n\t\t\t\t\t\tint pronelaunch,\n\t\t\t\t\t\tunsigned char const * override_remap)\n\t: TechnoTypeClass(RTTI_INFANTRYTYPE,\n\t\t\t\t\t\t\tint(type),\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tininame,\n\t\t\t\t\t\t\tREMAP_NORMAL,\n\t\t\t\t\t\t\tverticaloffset,\n\t\t\t\t\t\t\tprimaryoffset,\n\t\t\t\t\t\t\t0x0000,\n\t\t\t\t\t\t\t0x0000,\n\t\t\t\t\t\t\t0x0000,\n\t\t\t\t\t\t\tis_nominal,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tis_theater,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t8,\n\t\t\t\t\t\t\tSPEED_FOOT),\n\tIsFemale(is_female),\n\tIsCrawling(is_crawling),\n\tIsCapture(false),\n\tIsFraidyCat(false),\n\tIsCivilian(is_civilian),\n\tIsBomber(false),\n\tIsDog(false),\n\tIsRemapOverride(is_remap_override),\n\tType(type),\n\tPip(pip),\n\tDoControls(control),\n\tFireLaunch(firelaunch),\n\tProneLaunch(pronelaunch),\n\tOverrideRemap(override_remap)\n{\n\t/*\n\t**\tForced infantry overrides from the default.\n\t*/\n\tIsCrushable = true;\n\tIsScanner = true;\n\tIsRepairable = false;\n\tIsCrew = false;\n\tSpeed = SPEED_FOOT;\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::operator new -- Allocate an infanty type class object.                   *\n *                                                                                             *\n *    This will allocate an infantry type class object from the special memory pool of that    *\n *    purpose.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the infantry type class object allocated. If there was   *\n *          insufficient memory to fulfill the request, then NULL is returned.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * InfantryTypeClass::operator new(size_t)\n{\n\treturn(InfantryTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::operator delete -- Frees an infantry type class object.                  *\n *                                                                                             *\n *    This will return a previously allocated infantry type class object back to the memory    *\n *    pool from whence it came.                                                                *\n *                                                                                             *\n * INPUT:   pointer  -- The pointer to the infantry type class object to free.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryTypeClass::operator delete(void * pointer)\n{\n\tInfantryTypes.Free((InfantryTypeClass *)pointer);\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::Init_Heap -- Initialize the infantry type class heap.                    *\n *                                                                                             *\n *    This will pre-allocate all known infantry types.                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine once and before the rules.ini file is processed.              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese infantry type class objects must be allocated in the exact order that they\n\t**\tare specified in the InfantryType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew InfantryTypeClass(E1);\n\tnew InfantryTypeClass(E2);\n\tnew InfantryTypeClass(E3);\n\tnew InfantryTypeClass(E4);\n\tnew InfantryTypeClass(E6);\n\tnew InfantryTypeClass(E7);\n\tnew InfantryTypeClass(E8);\n\tnew InfantryTypeClass(E9);\n\tnew InfantryTypeClass(Medic);\n\tnew InfantryTypeClass(General);\n\tnew InfantryTypeClass(Dog);\n\tnew InfantryTypeClass(C1);\n\tnew InfantryTypeClass(C2);\n\tnew InfantryTypeClass(C3);\n\tnew InfantryTypeClass(C4);\n\tnew InfantryTypeClass(C5);\n\tnew InfantryTypeClass(C6);\n\tnew InfantryTypeClass(C7);\n\tnew InfantryTypeClass(C8);\n\tnew InfantryTypeClass(C9);\n\tnew InfantryTypeClass(C10);\n\tnew InfantryTypeClass(Einstein);\n\tnew InfantryTypeClass(Delphi);\n\tnew InfantryTypeClass(DrChan);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tnew InfantryTypeClass(ShockTrooper);\n\tnew InfantryTypeClass(Mechanic);\n#endif\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::Create_One_Of -- Creates an infantry object.                             *\n *                                                                                             *\n *    This creates an infantry object, but does not attempt to place it on the map. It is      *\n *    typically used by the scenario editor when an object is needed, but the location has     *\n *    not yet been specified for where it should appear on the map.                            *\n *                                                                                             *\n * INPUT:   house -- The owner of the infantry object.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the created infantry object. If an object could not be   *\n *          created, then NULL is returned.                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * InfantryTypeClass::Create_One_Of(HouseClass * house) const\n{\n\treturn(new InfantryClass(Type, house->Class->House));\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::Create_And_Place -- Creates and places infantry object onto the map.     *\n *                                                                                             *\n *    This routine is used by the scenario editor to create and place an infantry object onto  *\n *    the map at the location specified.                                                       *\n *                                                                                             *\n * INPUT:   cell     -- The cell location to place the infantry object at.                     *\n *                                                                                             *\n *          house    -- The owner of the infantry object.                                      *\n *                                                                                             *\n * OUTPUT:  bool; Was the infantry object successfully created and placed at the location      *\n *                specified?                                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryTypeClass::Create_And_Place(CELL cell, HousesType house) const\n{\n\tInfantryClass * i = new InfantryClass(Type, house);\n\tif (i != NULL) {\n\t\tCOORDINATE coord = Map[cell].Closest_Free_Spot(Cell_Coord(cell));\n\t\tif (coord) {\n\t\t\treturn(i->Unlimbo(coord, DIR_E));\n\t\t} else {\n\t\t\tdelete i;\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::Occupy_List -- Returns with default infantry occupation list.            *\n *                                                                                             *\n *    This routine will return with a cell offset occupation list for a generic infantry       *\n *    object. This is typically just a single cell since infantry are never bigger than one    *\n *    cell and this routine presumes the infantry is located in the center of the cell.        *\n *                                                                                             *\n * INPUT:   placement   -- Is this for placement legality checking only? The normal condition  *\n *                         is for marking occupation flags.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with a cell offset list for the infantry object as if it were located      *\n *          in the center of a cell.                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * InfantryTypeClass::Occupy_List(bool) const\n{\n\tstatic short const _list[] = {0, REFRESH_EOL};\n\n\treturn(&_list[0]);\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***********************************************************************************************\n * InfantryTypeClass::Display -- Displays a generic infantry object.                           *\n *                                                                                             *\n *    This routine is used by the scenario editor to display a generic representation of the   *\n *    infantry object for the scenario editor. It simply draws a single (nice profile) view    *\n *    of the infantry type.                                                                    *\n *                                                                                             *\n * INPUT:   x,y      -- The display coordinates to render the infantry object at.              *\n *                                                                                             *\n *          window   -- The window that the display coordinates are relative to.               *\n *                                                                                             *\n *          house    -- The house colors to use when rendering this infantry object.           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryTypeClass::Display(int x, int y, WindowNumberType window, HousesType house) const\n{\n\tif (house != HOUSE_NONE) {\n\n\t\tint shape = 0;\n\t\tvoid const * ptr = Get_Cameo_Data();\n\t\tif (ptr == NULL) {\n\t\t\tptr = Get_Image_Data();\n\t\t\tshape = 2;\n\t\t}\n\n\t\tCC_Draw_Shape(ptr, shape, x, y, window, SHAPE_NORMAL|SHAPE_CENTER|SHAPE_WIN_REL);\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::Prep_For_Add -- Prepares the scenario editor for adding of infantry object.*\n *                                                                                             *\n *    This routine will prepare the scenario editor so that the infantry objects appear on     *\n *    the object list.                                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryTypeClass::Prep_For_Add(void)\n{\n\tfor (InfantryType index = INFANTRY_FIRST; index < INFANTRY_COUNT; index++) {\n\t\tMap.Add_To_List(&As_Reference(index));\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * InfantryTypeClass::From_Name -- Converts an ASCII name into an infantry type number.        *\n *                                                                                             *\n *    This routine is used to convert the infantry ASCII name as specified into an infantry    *\n *    type number. This is called from the INI reader routine in the process if creating the   *\n *    infantry objects needed for the scenario.                                                *\n *                                                                                             *\n * INPUT:   name  -- The ASCII name to convert into an infantry type number.                   *\n *                                                                                             *\n * OUTPUT:  Returns with the infantry type number that corresponds to the infantry ASCII name  *\n *          specified. If no match could be found, then INFANTRY_NONE is returned.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nInfantryType InfantryTypeClass::From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (InfantryType classid = INFANTRY_FIRST; classid < INFANTRY_COUNT; classid++) {\n\t\t\tif (stricmp(As_Reference(classid).IniName, name) == 0) {\n\t\t\t\treturn(classid);\n\t\t\t}\n\t\t}\n\t}\n\treturn(INFANTRY_NONE);\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::One_Time -- Performs any one time processing for infantry system.        *\n *                                                                                             *\n *    This routine will perform one time processing for the infantry type system. This is      *\n *    generally restricted to loading of the infantry shape data.                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryTypeClass::One_Time(void)\n{\n\tfor (InfantryType index = INFANTRY_FIRST; index < INFANTRY_COUNT; index++) {\n\t\tchar fullname[_MAX_FNAME+_MAX_EXT];\n\t\tInfantryTypeClass\tconst * uclass;\n\t\tCCFileClass\tfile;\n\n\t\tuclass = &As_Reference(index);\n\n\t\t/*\n\t\t**\tGeneric shape for all houses load method.\n\t\t*/\n\t\t_makepath(fullname, NULL, NULL, uclass->Graphic_Name(), \".SHP\");\n\n\t\t#ifndef NDEBUG\n\t\t\tRawFileClass sfile(fullname);\n\t\t\tif (sfile.Is_Available()) {\n\t\t\t\t((void const *&)uclass->ImageData) = Load_Alloc_Data(sfile);\n\t\t\t} else {\n\t\t\t\t((void const *&)uclass->ImageData) = MFCD::Retrieve(fullname);\n\t\t\t}\n\t\t#else\n\t\t\t((void const *&)uclass->ImageData) = MFCD::Retrieve(fullname);\n\t\t#endif\n\n\t\t/*\n\t\t**\tThe small build image icon sized shapes are always generic.\n\t\t*/\n\t\tchar buffer[_MAX_FNAME];\n\t\tsprintf(buffer, \"%.4sICON\", uclass->Graphic_Name());\n\t\t_makepath(fullname, NULL, NULL, buffer, \".SHP\");\n\n\t\t#ifndef NDEBUG\n\t\t\tRawFileClass ifile(fullname);\n\t\t\tif (ifile.Is_Available()) {\n\t\t\t\t((void const *&)uclass->CameoData) = Load_Alloc_Data(ifile);\n\t\t\t} else {\n\t\t\t\t((void const *&)uclass->CameoData) = MFCD::Retrieve(fullname);\n\t\t\t}\n\t\t#else\n\t\t\t((void const *&)uclass->CameoData) = MFCD::Retrieve(fullname);\n\t\t#endif\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::Full_Name -- Fetches the full name text number.                          *\n *                                                                                             *\n *    This routine will fetch the full name text number for this infantry type. It examines    *\n *    the special custom name flag to determine whether the custom name or the generic name    *\n *    is to be used.                                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with text number for the name to give this infantry type object.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint InfantryTypeClass::Full_Name(void) const\n{\n\tif (Debug_Map || !IsNominal || Rule.IsNamed || Type == INFANTRY_C10 || Type == INFANTRY_DELPHI || Type == INFANTRY_EINSTEIN) {\n\t\treturn(TechnoTypeClass::Full_Name());\n\t}\n\treturn(TXT_CIVILIAN);\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::As_Reference -- Fetches a reference to the infantry type specified.      *\n *                                                                                             *\n *    Use this routine to convert an infantry type number into a reference to the infantry     *\n *    type class object it represents.                                                         *\n *                                                                                             *\n * INPUT:   type  -- The infantry type number to convert into a infantry type class object.    *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the infantry type class object specified.              *\n *                                                                                             *\n * WARNINGS:   Be sure that the type parameter is legal, otherwise the results are undefined.  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nInfantryTypeClass & InfantryTypeClass::As_Reference(InfantryType type)\n{\n\treturn(*InfantryTypes.Ptr(type));\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::Read_INI -- Fetches infantry override values from the INI database.      *\n *                                                                                             *\n *    This routine will retrieve the override values for this infantry type class object from  *\n *    the INI database specified.                                                              *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to retrieve the data from.                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the infantry section for this type found and data retrieved from it?     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryTypeClass::Read_INI(CCINIClass & ini)\n{\n\tif (TechnoTypeClass::Read_INI(ini)) {\n\t\tIsFraidyCat = ini.Get_Bool(Name(), \"Fraidycat\", IsFraidyCat);\n\t\tIsCapture = ini.Get_Bool(Name(), \"Infiltrate\", IsCapture);\n\t\tIsBomber = ini.Get_Bool(Name(), \"C4\", IsBomber);\n\t\tIsDog = ini.Get_Bool(Name(), \"IsCanine\", IsDog);\n\t\tif (IsBomber) IsCapture = true;\n\t\tif (IsDog) IsLeader = false;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\nvoid InfantryTypeClass::Dimensions(int & width, int & height) const\n{\n#ifdef WIN32\n\twidth = 14;\n\theight = 20;\n#else\n\twidth = 12;\n\theight = 16;\n#endif\n}\n"
  },
  {
    "path": "CODE/INFANTRY.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/INFANTRY.CPP 2     3/03/97 10:35p Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INFANTRY.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 15, 1994                                              *\n *                                                                                             *\n *                  Last Update : October 28, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   InfantryClass::AI -- Handles the infantry non-graphic related AI processing.              *\n *   InfantryClass::Active_Click_With -- Handles action when clicking with infantry soldier.   *\n *   InfantryClass::Assign_Destination -- Gives the infantry a movement destination.           *\n *   InfantryClass::Assign_Target -- Gives the infantry a combat target.                       *\n *   InfantryClass::Can_Enter_Cell -- Determines if the infantry can enter the cell specified. *\n *   InfantryClass::Can_Fire -- Can the infantry fire its weapon?                              *\n *   InfantryClass::Class_Of -- Returns the class reference for this object.                   *\n *   InfantryClass::Clear_Occupy_Bit -- Clears occupy bit and given cell                       *\n *   InfantryClass::Debug_Dump -- Displays debug information about infantry unit.              *\n *   InfantryClass::Detach -- Removes the specified target from targeting computer.            *\n *   InfantryClass::Do_Action -- Launches the infantry into an animation sequence.             *\n *   InfantryClass::Doing_AI -- Handles the animation AI processing.                           *\n *   InfantryClass::Draw_It -- Draws a unit object.                                            *\n *   InfantryClass::Edge_Of_World_AI -- Detects when infantry has left the map.                *\n *   InfantryClass::Enter_Idle_Mode -- The infantry unit enters idle mode by this routine.     *\n *   InfantryClass::Fear_AI -- Process any fear related affects on this infantry.              *\n *   InfantryClass::Fire_At -- Fires projectile from infantry unit.                            *\n *   InfantryClass::Firing_AI -- Handles firing and combat AI for the infantry.                *\n *   InfantryClass::Full_Name -- Fetches the full name of the infantry unit.                   *\n *   InfantryClass::Get_Image_Data -- Fetches the image data for this infantry unit.           *\n *   InfantryClass::Greatest_Threat -- Determines greatest threat (target) for infantry unit.  *\n *   InfantryClass::InfantryClass -- The constructor for infantry objects.                     *\n *   InfantryClass::Init -- Initialize the infantry object system.                             *\n *   InfantryClass::Is_Ready_To_Random_Anima -- Checks to see if it is ready to perform an idle*\n *   InfantryClass::Limbo -- Performs cleanup operations needed when limboing.                 *\n *   InfantryClass::Mission_Attack -- Intercept attack mission for special handling.           *\n *   InfantryClass::Movement_AI -- This routine handles all infantry movement logic.           *\n *   InfantryClass::Overlap_List -- The list of cells that the infantry overlaps, but doesn't o*\n *   InfantryClass::Paradrop -- Handles paradropping infantry.                                 *\n *   InfantryClass::Per_Cell_Process -- Handles special operations that occur once per cell.   *\n *   InfantryClass::Random_Animate -- Randomly animate the infantry (maybe)                    *\n *   InfantryClass::Read_INI -- Reads units from scenario INI file.                            *\n *   InfantryClass::Response_Attack -- Plays infantry audio response to attack order.          *\n *   InfantryClass::Response_Move -- Plays infantry response to movement order.                *\n *   InfantryClass::Response_Select -- Plays infantry audio response due to being selected.    *\n *   InfantryClass::Scatter -- Causes the infantry to scatter to nearby cell.                  *\n *   InfantryClass::Set_Occupy_Bit -- Sets the occupy bit cell and bit pos\t                    *\n *   InfantryClass::Set_Primary_Facing -- Change infantry primary facing -- always and instantl*\n *   InfantryClass::Shape_Number -- Fetch the shape number for this infantry.                  *\n *   InfantryClass::Start_Driver -- Handles giving immediate destination and move orders.      *\n *   InfantryClass::Stop_Driver -- Stops the infantry from moving any further.                 *\n *   InfantryClass::Take_Damage -- Applies damage to the infantry unit.                        *\n *   InfantryClass::Unlimbo -- Unlimbo infantry unit in legal sub-location.                    *\n *   InfantryClass::What_Action -- Determines what action to perform for the cell specified.   *\n *   InfantryClass::What_Action -- Infantry units might be able to capture -- check.           *\n *   InfantryClass::Write_INI -- Store the infantry to the INI database.                       *\n *   InfantryClass::operator delete -- Returns the infantry object back to the free pool       *\n *   InfantryClass::operator new -- Allocates an infantry object from the free pool.           *\n *   InfantryClass::~InfantryClass -- Default destructor for infantry units.                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\nint const InfantryClass::HumanShape[32] = {0,0,7,7,7,7,6,6,6,6,5,5,5,5,5,4,4,4,3,3,3,3,2,2,2,2,1,1,1,1,1,0};\n\n\n/***************************************************************************\n** This is the array of constant data associated with infantry maneuvers. It\n**\tspecifies the frame rate as well as if the animation can be aborted.\n*/\n// interruptible, mobile, randomstart, rate\nDoStruct const InfantryClass::MasterDoControls[DO_COUNT] = {\n\t{true,\tfalse,\tfalse,\t0},\t// DO_STAND_READY\n\t{true,\tfalse,\tfalse,\t0},\t// DO_STAND_GUARD\n\t{true,\tfalse,\tfalse,\t0},\t// DO_PRONE\n\t{true,\ttrue,\t\ttrue,\t\t2},\t// DO_WALK\n\t{true,\tfalse,\tfalse,\t1},\t// DO_FIRE_WEAPON\n\t{false,\ttrue,\t\tfalse,\t2},\t// DO_LIE_DOWN\n\t{true,\ttrue,\t\ttrue,\t\t2},\t// DO_CRAWL\n\t{false,\tfalse,\tfalse,\t3},\t// DO_GET_UP\n\t{true,\tfalse,\tfalse,\t1},\t// DO_FIRE_PRONE\n\t{true,\tfalse,\tfalse,\t2},\t// DO_IDLE1\n\t{true,\tfalse,\tfalse,\t2},\t// DO_IDLE2\n\t{false,\tfalse,\tfalse,\t2},\t// DO_GUN_DEATH\n\t{false,\tfalse,\tfalse,\t2},\t// DO_EXPLOSION_DEATH\n\t{false,\tfalse,\tfalse,\t2},\t// DO_EXPLOSION2_DEATH\n\t{false,\tfalse,\tfalse,\t2},\t// DO_GRENADE_DEATH\n\t{false,\tfalse,\tfalse,\t2},\t// DO_FIRE_DEATH\n\t{false,\tfalse,\tfalse,\t2},\t// DO_GESTURE1\n\t{false,\tfalse,\tfalse,\t2},\t// DO_SALUTE1\n\t{false,\tfalse,\tfalse,\t2},\t// DO_GESTURE2\n\t{false,\tfalse,\tfalse,\t2},\t// DO_SALUTE2\n\t{false,\tfalse,\tfalse,\t2},\t// DO_DOG_MAUL\n};\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * InfantryClass::Debug_Dump -- Displays debug information about infantry unit.                *\n *                                                                                             *\n *    This routine is used by the debug version to display pertinent information about the     *\n *    infantry unit.                                                                           *\n *                                                                                             *\n * INPUT:   mono  -- The monochrome screen to display the debug information to.                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tmono->Set_Cursor(0, 0);\n\n\tmono->Print(Text_String(TXT_DEBUG_INFANTRY));\n\tmono->Set_Cursor(1, 11);mono->Printf(\"%3d\", Doing);\n\tmono->Set_Cursor(8, 11);mono->Printf(\"%3d\", Fear);\n\n\tmono->Fill_Attrib(66, 13, 12, 1, IsTechnician ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 14, 12, 1, IsStoked ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 15, 12, 1, IsProne ? MonoClass::INVERSE : MonoClass::NORMAL);\n\n\tFootClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * InfantryClass::InfantryClass -- The constructor for infantry objects.                       *\n *                                                                                             *\n *    This is the constructor used when creating an infantry unit. All values are required     *\n *    except for facing and position. If these are absent, then the infantry is created in     *\n *    a state of limbo -- not placed upon the map.                                             *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nInfantryClass::InfantryClass(InfantryType classid, HousesType house) :\n\tFootClass(RTTI_INFANTRY, Infantry.ID(this), house),\n\tClass(InfantryTypes.Ptr((int)classid)),\n\tDoing(DO_NOTHING),\n\tComment(0),\n\tIsTechnician(false),\n\tIsStoked(false),\n\tIsProne(false),\n\tIsZoneCheat(false),\n\tWasSelected(false),\n\tFear(FEAR_NONE)\n{\n\tHouse->Tracking_Add(this);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tIsCloakable = Class->IsCloakable;\n#endif\n\t/*\n\t**\tFor two shooters, clear out the second shot flag -- it will be set the first time\n\t**\tthe object fires. For non two shooters, set the flag since it will never be cleared\n\t**\tand the second shot flag tells the system that normal rearm times apply -- this is\n\t**\twhat is desired for non two shooters.\n\t*/\n\tif (Class->Is_Two_Shooter()) {\n\t\tIsSecondShot = false;\n\t} else {\n\t\tIsSecondShot = true;\n\t}\n\tStrength = Class->MaxStrength;\n\n\t/*\n\t**\tCivilians carry much less ammo than soldiers do.\n\t*/\n\tAmmo = Class->MaxAmmo;\n}\n\n\n/***********************************************************************************************\n * InfantryClass::~InfantryClass -- Default destructor for infantry units.                     *\n *                                                                                             *\n *    This is the default destructor for infantry type units. It will put the infantry into    *\n *    a limbo state if it isn't already in that state and the game is still active.            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nInfantryClass::~InfantryClass(void)\n{\n\tif (GameActive && Class.Is_Valid()) {\n\n\t\t/*\n\t\t**\tRemove this member from any team it may be associated with. This must occur at the\n\t\t**\ttop most level of the inheritance hierarchy because it may call virtual functions.\n\t\t*/\n\t\tif (Team.Is_Valid()) {\n\t\t\tTeam->Remove(this);\n\t\t\tTeam = NULL;\n\t\t}\n\n\t\tHouse->Tracking_Remove(this);\n\t\tLimbo();\n\t}\n\tID = -1;\n}\n\n\n/***********************************************************************************************\n * InfantryClass::operator new -- Allocates an infantry object from the free pool.             *\n *                                                                                             *\n *    This will allocate an infantry object from the infantry object free pool. If there is    *\n *    no available slot, then NULL is returned.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocated infantry object or NULL if none could be   *\n *          allocated.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * InfantryClass::operator new(size_t)\n{\n\tvoid * ptr = Infantry.Allocate();\n\tif (ptr != NULL) {\n\t\t((InfantryClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::operator delete -- Returns the infantry object back to the free pool         *\n *                                                                                             *\n *    This routine is used return an infantry object back to the system.                       *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the infantry object to delete.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::operator delete(void * ptr)\n{\n\tif (ptr != NULL) {\n\t\t((InfantryClass *)ptr)->IsActive = false;\n\t}\n\tInfantry.Free((InfantryClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Take_Damage -- Applies damage to the infantry unit.                          *\n *                                                                                             *\n *    This routine applies the damage specified to the infantry object. It is possible that    *\n *    this routine will DESTROY the infantry unit in the process.                              *\n *                                                                                             *\n * INPUT:   damage   -- The damage points to inflict.                                          *\n *                                                                                             *\n *          distance -- The distance from the damage center point to the object's center point.*\n *                                                                                             *\n *          warhead  -- The warhead type that is inflicting the damage.                        *\n *                                                                                             *\n *          source   -- Who is responsible for inflicting the damage.                          *\n *                                                                                             *\n * OUTPUT:  bool; Was the infantry unit destroyed by this damage?                              *\n *                                                                                             *\n * WARNINGS:   Since the infantry unit could be destroyed by this routine, be sure to check    *\n *             for this in the code that follows the call to Take_Damage().                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *   11/22/1994 JLB : Shares base damage handler for techno objects.                           *\n *   03/31/1995 JLB : Revenge factor.                                                          *\n *=============================================================================================*/\nResultType InfantryClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, int forced)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tResultType res = RESULT_NONE;\n\n\t/*\n\t**\tProne infantry take only half damage, but never below one damage point.\n\t*/\n\tif (IsProne && damage > 0) {\n\t\tdamage = damage * Rule.ProneDamageBias;\n\t}\n\n\t/*\n\t** If we're taking damage from a dog, we have to decide if we're the\n\t** target of the dog.  Dogs don't spill collateral damage onto anyone\n\t** else, so if we're the target of a valid dog, take full damage, but if\n\t** we're not the target, or the dog doesn't exist, then take no damage.\n\t*/\n\tif (source != NULL && source->What_Am_I() == RTTI_INFANTRY && ((InfantryClass *)source)->Class->IsDog) {\n\t\tif (source->TarCom == As_Target()) {\n\t\t\tdamage = Strength;\n\t\t} else {\n\t\t\tdamage = 0;\n\t\t}\n\t}\n\tres = FootClass::Take_Damage(damage, distance, warhead, source, forced);\n\n\t/*\n\t** hack for dog: if you're hit by a dog, and you're the target, your\n\t** damage gets upped to max.\n\t*/\n\n\tif (res == RESULT_NONE) return(res);\n\n\tif (res == RESULT_DESTROYED) {\n\t\tif (*this == INFANTRY_TANYA) {\n\t\t\tIsTanyaDead = true;\n\t\t}\n\t\tDeath_Announcement(source);\n\t\tStop_Driver();\n\t\tStun();\n\t\tMission = MISSION_NONE;\n\t\tAssign_Mission(MISSION_GUARD);\n\t\tCommence();\n\n\t\tVocType sound;\n\t\tVocType altsound;\n\t\tsound = Sim_Random_Pick(VOC_SCREAM1, VOC_SCREAM11);\n\t\taltsound = VOC_YELL1;\n\t\tif (*this == INFANTRY_TANYA) {\n\t\t\tsound = altsound = VOC_TANYA_DIE;\n\t\t}\n\t\tif (Class->IsDog) {\n\t\t\tsound = altsound = VOC_DOG_HURT;\n\t\t}\n\n\t\t/*\n\t\t**\tThe type of warhead determines the animation the infantry\n\t\t**\twill perform when killed.\n\t\t*/\n\t\tbool delthis = false;\n\t\tTARGET us = As_Target();\n\t\tswitch (WarheadTypeClass::As_Pointer(warhead)->InfantryDeath) {\n\t\t\tdefault:\n\t\t\tcase 0:\n\t\t\t\tdelthis = true;\n\t\t\t\tbreak;\n\n\t\t\tcase 1:\n\t\t\t\tSound_Effect(sound, Coord);\n\t\t\t\tDo_Action(DO_GUN_DEATH, true);\n\t\t\t\tbreak;\n\n\t\t\tcase 2:\n\t\t\t\tSound_Effect(sound, Coord);\n\t\t\t\tDo_Action(DO_EXPLOSION_DEATH, true);\n\t\t\t\tbreak;\n\n\t\t\tcase 3:\n\t\t\t\tSound_Effect(sound, Coord);\n\t\t\t\tDo_Action(DO_GRENADE_DEATH, true);\n\t\t\t\tbreak;\n\n\t\t\tcase 4:\n\t\t\t\tSound_Effect(altsound, Coord);\n\t\t\t\tDo_Action(DO_FIRE_DEATH, true);\n\t\t\t\tbreak;\n\n\t\t\tcase 5:\n\t\t\t\tSound_Effect(sound, Coord);\n\t\t\t\tAnimType anim = ANIM_ELECT_DIE;\n\t\t\t\tif (Class->IsDog) anim = ANIM_DOG_ELECT_DIE;\n\t\t\t\tnew AnimClass(anim, Coord);\n\t\t\t\tdelthis = true;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (delthis) {\n\t\t\tdelete this;\n\t\t}\n\t\treturn(res);\n\t}\n\n\t/*\n\t**\tWhen infantry gets hit, it gets scared.\n\t*/\n\tif (res != RESULT_DESTROYED) {\n\t\tCOORDINATE source_coord = (source) ? source->Coord : NULL;\n\n\t\t/*\n\t\t**\tIf an engineer is damaged and it is just sitting there, then tell it\n\t\t**\tto go do something since it will definitely die if it doesn't.\n\t\t*/\n\t\tif (!House->IsHuman && *this == INFANTRY_RENOVATOR && (Mission == MISSION_GUARD || Mission == MISSION_GUARD_AREA)) {\n\t\t\tAssign_Mission(MISSION_HUNT);\n\t\t}\n\n\t\tif (source != NULL) {\n\t\t\tScatter(source_coord);\n\t\t}\n\n\t\tif (source != NULL && Fear < FEAR_SCARED) {\n\t\t\tif (Class->IsFraidyCat) {\n\t\t\t\tFear = FEAR_PANIC;\n\t\t\t} else {\n\t\t\t\tFear = FEAR_SCARED;\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIncrease the fear of the infantry by a bit. The fear increases more\n\t\t\t**\tquickly if the infantry is damaged.\n\t\t\t*/\n\t\t\tint morefear = FEAR_ANXIOUS;\n\t\t\tif (Health_Ratio() > Rule.ConditionRed) morefear /= 2;\n\t\t\tif (Health_Ratio() > Rule.ConditionYellow) morefear /= 2;\n\t\t\tFear = FearType(min((int)Fear + morefear, FEAR_MAXIMUM));\n\t\t}\n\t}\n\treturn(res);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Shape_Number -- Fetch the shape number for this infantry.                    *\n *                                                                                             *\n *    This will determine the shape number to use for this infantry soldier. The shape number  *\n *    is relative to the shape file associated with this infantry unit.                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the shape number for this infantry object to be used when drawing.    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint InfantryClass::Shape_Number(void) const\n{\n\t/*\n\t**\tFetch the shape pointer to use for the infantry. This is controlled by what\n\t**\tchoreograph sequence the infantry is performing, it's facing, and whether it\n\t**\tis prone.\n\t*/\n\tDoType doit = Doing;\n\tif (doit == DO_NOTHING) doit = DO_STAND_READY;\n\n\t/*\n\t**\tThe infantry shape is always modulo the number of animation frames\n\t**\tof the action stage that the infantry is doing.\n\t*/\n\tint shapenum = Fetch_Stage() % max(Class->DoControls[doit].Count, 1);\n\n\t/*\n\t**\tIf facing makes a difference, then the shape number will be incremented\n\t**\tby the facing accordingly.\n\t*/\n\tif (Class->DoControls[doit].Jump) {\n\t\tshapenum += HumanShape[Dir_To_32(PrimaryFacing.Current())] * Class->DoControls[doit].Jump;\n\t}\n\n\t/*\n\t**\tFinally, the shape number is biased according to the starting frame number for\n\t**\tthat action in the infantry shape file.\n\t*/\n\tshapenum += Class->DoControls[doit].Frame;\n\n\t/*\n\t**\tReturn with the final infantry shape number.\n\t*/\n\treturn(shapenum);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Draw_It -- Draws a unit object.                                              *\n *                                                                                             *\n *    This routine is the one that actually draws a unit object. It displays the unit          *\n *    according to its current state flags and centered at the location specified.             *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y coordinate of where to draw the unit.                         *\n *                                                                                             *\n *          window   -- The clipping window to use.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1994 JLB : Created.                                                                 *\n *   06/27/1994 JLB : Takes a window parameter.                                                *\n *   08/15/1994 JLB : Converted to infantry support.                                           *\n *   08/14/1996 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid InfantryClass::Draw_It(int x, int y, WindowNumberType window) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tVerify the legality of the unit class by seeing if there is shape imagery for it. If\n\t**\tthere is no shape image, then it certainly can't be drawn -- bail.\n\t*/\n\tvoid const * shapefile = Get_Image_Data();\n\n\tif (shapefile == NULL) return;\n\n\ty += 4;\n\tx -= 2;\n\n\t/*\n\t**\tActually draw the root body of the unit.\n\t*/\n\tTechno_Draw_Object(shapefile, Shape_Number(), x, y, window);\n\n\tFootClass::Draw_It(x, y, window);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Per_Cell_Process -- Handles special operations that occur once per cell.     *\n *                                                                                             *\n *    This routine will handle any special operations that need to be performed once each      *\n *    cell travelled. This includes radioing a transport that it is now clear and the          *\n *    transport is free to leave.                                                              *\n *                                                                                             *\n * INPUT:   why   -- Specifies the circumstances under which this routine was called.          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *   03/01/1995 JLB : Capture building options.                                                *\n *   05/31/1995 JLB : Capture is always successful now.                                        *\n *=============================================================================================*/\nvoid InfantryClass::Per_Cell_Process(PCPType why)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tBStart(BENCH_PCP);\n\tCellClass * cellptr = &Map[Coord];\n\n\tif (why == PCP_END) {\n\n\t\t/*\n\t\t**\tIf the infantry unit is entering a cell that contains the building it is trying to\n\t\t**\tcapture, then capture it.\n\t\t*/\n\t\tif (Mission == MISSION_CAPTURE) {\n\t\t\tTechnoClass * tech = cellptr->Cell_Building();\n\n\t\t\tif (tech == NULL) tech = cellptr->Cell_Techno();\n\t\t\tif (tech != NULL && (tech->As_Target() == NavCom || tech->As_Target() == TarCom)) {\n\t\t\t\tif (*this == INFANTRY_RENOVATOR) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tAn engineer will either mega-repair a friendly or allied\n\t\t\t\t\t**\tbuilding or it will damage/capture an enemy building. Whether\n\t\t\t\t\t**\tit damages or captures depends on how badly damaged the\n\t\t\t\t\t**\tenemy building is.\n\t\t\t\t\t*/\n#ifdef FIXIT_ENGINEER_CAPTURE\n\t\t\t\t\tif (House->Is_Ally(tech)) {\n#else\n\t\t\t\t\tif (tech->House->Is_Ally(House)) {\n#endif\n\t\t\t\t\t\ttech->Renovate();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbool iscapturable = false;\n\t\t\t\t\t\tif (tech->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\t\tiscapturable = ((BuildingClass *)tech)->Class->IsCaptureable;\n\t\t\t\t\t\t}\n#ifdef FIXIT_ENGINEER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\tif (tech->Health_Ratio() <= EngineerCaptureLevel && iscapturable) {\n#else\n\t\t\t\t\t\tif (tech->Health_Ratio() <= Rule.ConditionRed && iscapturable) {\n#endif\n\t\t\t\t\t\t\tif (tech->Trigger.Is_Valid()) {\n\t\t\t\t\t\t\t\ttech->Trigger->Spring(TEVENT_PLAYER_ENTERED, this);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttech->House->IsThieved = true;\n\t\t\t\t\t\t\ttech->Captured(House);\n\t\t\t\t\t\t} else {\n#ifdef FIXIT_ENGINEER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\t\tint damage = min( (tech->Techno_Type_Class()->MaxStrength) * EngineerDamage, tech->Strength-1);\n#else\n\t\t\t\t\t\t\tint damage = min( (tech->Techno_Type_Class()->MaxStrength) / 3, tech->Strength-1);\n#endif\n\t\t\t\t\t\t\ttech->Take_Damage(damage, 0, WARHEAD_HE, this, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tBEnd(BENCH_PCP);\n\t\t\t\t\t\tdelete this;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tif (*this != INFANTRY_SPY && tech->Trigger.Is_Valid()) {\n\t\t\t\t\t\ttech->Trigger->Spring(TEVENT_PLAYER_ENTERED, this);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (*this == INFANTRY_SPY) {\n\t\t\t\t\t\tint housespy = (1 << (House->Class->House));\n//\t\t\t\t\t\ttech->House->IsSpied = true;\n\n\t\t\t\t\t\tif (tech->Trigger.Is_Valid()) {\n\t\t\t\t\t\t\ttech->Trigger->Spring(TEVENT_SPIED, this);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (IsOwnedByPlayer) Speak(VOX_BUILDING_INFILTRATED);\n\n\t\t\t\t\t\ttech->Mark(MARK_OVERLAP_UP);\n\t\t\t\t\t\ttech->SpiedBy |= housespy;\n\t\t\t\t\t\ttech->Mark(MARK_OVERLAP_DOWN);\n\t\t\t\t\t\tif (tech->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\t\tStructType build = *(BuildingClass *)tech;\n\t\t\t\t\t\t\tif (build == STRUCT_RADAR /* || build == STRUCT_EYE */ ) {\n\t\t\t\t\t\t\t\ttech->House->RadarSpied |= housespy;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// If they're spying on a sub pen, give 'em a sonar pulse\n\t\t\t\t\t\t\tif (build == STRUCT_SUB_PEN) {\n\t\t\t\t\t\t\t\tHouse->SuperWeapon[SPC_SONAR_PULSE].Enable(false, true, false);\n\t\t\t\t\t\t\t\tif (IsOwnedByPlayer) {\n\t\t\t\t\t\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_SONAR_PULSE);\n\t\t\t\t\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tif (*this == INFANTRY_THIEF) {\t// Thief just raided a storage facility\n\t\t\t\t\t\t\ttech->House->IsThieved = true;\n\n\t\t\t\t\t\t\tif (tech->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\t\t\tBuildingClass * bldg = (BuildingClass *)tech;\n\t\t\t\t\t\t\t\tif (bldg->Class->Capacity) {\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t** If we just raided a storage facility (refinery or silo)\n\t\t\t\t\t\t\t\t\t** then give the thief up to half the capacity of the\n\t\t\t\t\t\t\t\t\t** storage facility.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tif (IsOwnedByPlayer || bldg->IsOwnedByPlayer) Speak(VOX_MONEY_STOLEN);\n#ifdef OBSOLETE\n\t\t\t\t\t\t\t\t\tlong capacity = bldg->Class->Capacity * 256;\n\t\t\t\t\t\t\t\t\tcapacity /= (bldg->House->Tiberium+1);\n\t\t\t\t\t\t\t\t\tint bldgcap = bldg->Class->Capacity;\n\n\t\t\t\t\t\t\t\t\tlong cash = (bldgcap * 256) / (capacity+1);\n\t\t\t\t\t\t\t\t\tif (cash > (bldgcap / 2)) cash = bldgcap / 2;\n#else\n\t\t\t\t\t\t\t\t\tlong cash = bldg->House->Available_Money() / 2;\n#endif\n\t\t\t\t\t\t\t\t\tbldg->House->Spend_Money(cash);\n\t\t\t\t\t\t\t\t\tHouse->Refund_Money(cash);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tBEnd(BENCH_PCP);\n\t\t\t\tdelete this;\n\t\t\t\treturn;\n\n\t\t\t} else {\n\n\t#ifdef OBSOLETE\n\t\t\t\t// are we trying to repair a bridge?\n\t\t\t\tif (Is_Target_Cell(TarCom) ) {\n\t\t\t\t\tCELL cell = Coord_Cell(Coord);\n\t\t\t\t\tif (cell == ::As_Cell(NavCom)) {\n\t\t\t\t\t\tTemplateType tt = cellptr->TType;\n\t\t\t\t\t\tint icon = cellptr->TIcon;\n\t\t\t\t\t\tint w = TemplateTypeClass::As_Reference(cellptr->TType).Width;\n\t\t\t\t\t\tint h = TemplateTypeClass::As_Reference(cellptr->TType).Height;\n\n\t\t\t\t\t\tcell -= icon % w;\n\t\t\t\t\t\tcell -= MAP_CELL_W * (icon / w);\n\t\t\t\t\t\tif (tt == TEMPLATE_BRIDGE1D || tt == TEMPLATE_BRIDGE2D) {\n\t\t\t\t\t\t\tnew TemplateClass(TemplateType(cellptr->TType-1), cell);\n\t\t\t\t\t\t\tMap.Zone_Reset(MZONEF_ALL);\n\t\t\t\t\t\t\tdelete this;\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// Trying to repair multi-segment bridge.  Look for the\n\t\t\t\t\t\t\t// start tile, then fix it, and determine the direction to\n\t\t\t\t\t\t\t// go in and repair it all that way.\n\t\t\t\t\t\t\tTemplateType newtt = TEMPLATE_BRIDGE_1A;\n\t\t\t\t\t\t\tint xmov = -1;\t// coords to move to for next template\n\t\t\t\t\t\t\tint ymov = 2;\n\t\t\t\t\t\t\tbool valid = false;\n\t\t\t\t\t\t\tswitch (tt) {\n\t\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_1B:\n\t\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_1C:\n\t\t\t\t\t\t\t\t\tvalid = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_2B:\n\t\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_2C:\n\t\t\t\t\t\t\t\t\tnewtt = TEMPLATE_BRIDGE_2A;\n\t\t\t\t\t\t\t\t\txmov = 2;\n\t\t\t\t\t\t\t\t\tymov = -1;\n\t\t\t\t\t\t\t\t\tvalid = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3C:\n\t\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3D:\n\t\t\t\t\t\t\t\t\tnewtt = TEMPLATE_BRIDGE_3A;\n\t\t\t\t\t\t\t\t\tvalid = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3E:\n\t\t\t\t\t\t\t\t\tnewtt = TEMPLATE_BRIDGE_3A;\n\t\t\t\t\t\t\t\t\txmov = 2;\n\t\t\t\t\t\t\t\t\tymov = -1;\n\t\t\t\t\t\t\t\t\tvalid = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Did we find a valid repairable bridge piece?\n\t\t\t\t\t\t\tif (valid) {\n\t\t\t\t\t\t\t\tbool doing = true;\n\t\t\t\t\t\t\t\twhile (doing) {\n\t\t\t\t\t\t\t\t\tnew TemplateClass(TemplateType(newtt), cell);\n\t\t\t\t\t\t\t\t\tcell += (MAP_CELL_W * ymov) + xmov;\n\t\t\t\t\t\t\t\t\tif (xmov < 0) {\n\t\t\t\t\t\t\t\t\t\txmov = -1;\n\t\t\t\t\t\t\t\t\t\tymov = 1;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\txmov = 1;\n\t\t\t\t\t\t\t\t\t\tymov = -1;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tcellptr = &Map[cell];\n\t\t\t\t\t\t\t\t\ttt = cellptr->TType;\n\t\t\t\t\t\t\t\t\tif ((tt >= TEMPLATE_BRIDGE_3B && tt <= TEMPLATE_BRIDGE_3F) ||\n\t\t\t\t\t\t\t\t\t\t  tt == TEMPLATE_BRIDGE_1B || tt == TEMPLATE_BRIDGE_1C ||\n\t\t\t\t\t\t\t\t\t\t  tt == TEMPLATE_BRIDGE_2B || tt == TEMPLATE_BRIDGE_2C ) {\n\n\t\t\t\t\t\t\t\t\t\tif (tt >= TEMPLATE_BRIDGE_3B) {\n\t\t\t\t\t\t\t\t\t\t\tnewtt = TEMPLATE_BRIDGE_3A;\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tif (tt < TEMPLATE_BRIDGE_2A) {\n\t\t\t\t\t\t\t\t\t\t\t\tnewtt = TEMPLATE_BRIDGE_1A;\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tnewtt = TEMPLATE_BRIDGE_2A;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\ticon = cellptr->TIcon;\n\t\t\t\t\t\t\t\t\t\tw = TemplateTypeClass::As_Reference(cellptr->TType).Width;\n\t\t\t\t\t\t\t\t\t\th = TemplateTypeClass::As_Reference(cellptr->TType).Height;\n\n\t\t\t\t\t\t\t\t\t\tcell -= icon % w;\n\t\t\t\t\t\t\t\t\t\tcell -= MAP_CELL_W * (icon / w);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tdoing = false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tMap.Zone_Reset(MZONEF_ALL);\n\t\t\t\t\t\t\t\tdelete this;\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t#endif\n\t\t\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t\tif (Map[Coord].Cell_Building()) {\n\t\t\t\t\t\t\tScatter(0, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t#ifdef OBSOLETE\n\t\t\t\t}\n\t#endif\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tInfantry entering a transport vehicle will break radio contact\n\t\t**\tat attach itself to the transporter.\n\t\t*/\n\t\tTechnoClass * techno = Contact_With_Whom();\n\t\tif (Mission == MISSION_ENTER && techno != NULL && Coord_Cell(Coord) == Coord_Cell(techno->Coord) && techno == As_Techno(NavCom)) {\n\t\t\tif (Transmit_Message(RADIO_IM_IN) == RADIO_ATTACH) {\n\t\t\t\tLimbo();\n\t\t\t\ttechno->Attach(this);\n\t\t\t}\n\t\t\tBEnd(BENCH_PCP);\n\t\t\treturn;\n\t\t}\n\n\t\t/*\n\t\t**\tIf the infantry unit is entering a cell that contains the building it is trying to\n\t\t**\tsabotage, then sabotage it.\n\t\t*/\n\t\tif (Mission == MISSION_SABOTAGE) {\n\t\t\tBuildingClass * building = cellptr->Cell_Building();\n\t\t\tif (building != NULL && building->As_Target() == NavCom) {\n\t\t\t\tif (!building->IronCurtainCountDown && building->Mission != MISSION_DECONSTRUCTION) {\n\t\t\t\t\tbuilding->IsGoingToBlow = true;\n\t\t\t\t\tbuilding->Clicked_As_Target((Rule.C4Delay * TICKS_PER_MINUTE) / 2);\n\t\t\t\t\tbuilding->CountDown = Rule.C4Delay * TICKS_PER_MINUTE;\n\t\t\t\t\tbuilding->WhomToRepay = As_Target();\n\t\t\t\t}\n\t\t\t\tNavCom = TARGET_NONE;\n\t\t\t\tDo_Uncloak();\n\t\t\t\tArm = Rearm_Delay(true);\n\t\t\t\tScatter(building->Center_Coord(), true, true);\t// RUN AWAY!\n\t\t\t\tBEnd(BENCH_PCP);\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tif (::As_Target(Coord_Cell(Center_Coord())) == NavCom) {\n\t\t\t\t\tExplosion_Damage(Coord, Rule.BridgeStrength, this, WARHEAD_HE);\n\n\t\t\t\t\tStop_Driver();\n\t\t\t\t\tScatter(Adjacent_Cell(Coord, PrimaryFacing), true, true);\n\t\t\t\t\tAssign_Mission(MISSION_MOVE);\n\n\t\t\t\t\tCELL cell = Coord_Cell(Center_Coord());\n\t\t\t\t\tCellClass * cellptr = &Map[cell];\n\t\t\t\t\tif (!Target_Legal(NavCom) || Map[As_Cell(NavCom)].Land_Type() == LAND_WATER) {\n\t\t\t\t\t\tMark(MARK_DOWN);\t\t// Needed only so that Tanya will get destroyed by the explosion.\n\t\t\t\t\t}\n\t\t\t\t\tExplosion_Damage(Coord, Rule.BridgeStrength, NULL, WARHEAD_HE);\n\t\t\t\t\tExplosion_Damage(Coord, Rule.BridgeStrength, NULL, WARHEAD_HE);\n\t\t\t\t\tif (!IsActive) {\n\t\t\t\t\t\tBEnd(BENCH_PCP);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tMark(MARK_DOWN);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf this unit is on a teather, then cut it at this time so that\n\t\t**\tthe \"parent\" unit is free to proceed. Note that the parent\n\t\t**\tunit might actually be a building.\n\t\t*/\n\t\tif (IsTethered) {\n\t\t\tTransmit_Message(RADIO_UNLOADED);\n\t\t\tif (House->ActLike == HOUSE_USSR || House->ActLike == HOUSE_UKRAINE) {\n\t\t\t\tDo_Action(DO_GESTURE1);\n\t\t\t} else  {\n\t\t\t\tDo_Action(DO_GESTURE2);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSpecial voice play.\n\t\t\t*/\n\t\t\tif (*this ==  INFANTRY_TANYA) {\n\t\t\t\tSound_Effect(VOC_TANYA_LAUGH, Coord);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the cell is now full of infantry, tell them all to scatter\n\t\t\t**\tin order to make room for more.\n\t\t\t*/\n\t\t\tif ((cellptr->Flag.Composite & 0x01F) == 0x01F) {\n\t\t\t\tcellptr->Incoming(0, true, true);\n//\t\t\t\tcellptr->Incoming(0, true);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tWhen the infantry reaches the center of the cell, it may begin a new mission.\n\t\t*/\n\t\tif (MissionQueue == MISSION_NONE && !Target_Legal(NavCom) && !Target_Legal(TarCom) && !In_Radio_Contact()) {\n\t\t\tEnter_Idle_Mode();\n\t\t}\n\t\tCommence();\n\n\t\t/*\n\t\t** If entering a cell with a land mine in it, blow up the mine.\n\t\t*/\n\t\tBuildingClass * bldng = cellptr->Cell_Building();\n\t\tif (bldng != NULL && *bldng == STRUCT_APMINE) {\n\t\t\t/*\n\t\t\t** Show the animation and get rid of the land mine\n\t\t\t*/\n\t\t\tCOORDINATE blcoord = bldng->Center_Coord();\n\t\t\tnew AnimClass(Combat_Anim(Rule.APMineDamage, WARHEAD_HE, cellptr->Land_Type()), blcoord);\n\t\t\tdelete bldng;\n\t\t\tint damage;\n\t\t\tfor (int index = 0; index < Infantry.Count(); index++) {\n\t\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\t\tif (obj != NULL && !obj->IsInLimbo) {\n\t\t\t\t\tint dist = ::Distance(obj->Coord, blcoord);\n\t\t\t\t\tif (dist <= 0xC0) {\n\t\t\t\t\t\tdamage = Rule.APMineDamage;\n\t\t\t\t\t\tobj->Take_Damage(damage, 0, WARHEAD_HE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!IsActive) {\n\t\t\t\tBEnd(BENCH_PCP);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tLook(true);\n\n#if 1\n/*\n**\tIf after all is said and done, the unit finishes its move on an impassable cell, then\n**\tit must presume that it is in the case of a unit driving onto a bridge that blows up\n**\tbefore the unit completes it's move. In such a case the unit should have been destroyed\n**\tanyway, so blow it up now.\n*/\nLandType land = Map[Coord].Land_Type();\nif (!IsDriving && !Class->IsBomber && (land == LAND_ROCK || land == LAND_WATER || land == LAND_RIVER)) {\n\tint damage = Strength;\n\tTake_Damage(damage, 0, WARHEAD_AP, NULL, true);\n\treturn;\n}\n#endif\n\n\t}\n\n\tif (IsActive) {\n\t\tFootClass::Per_Cell_Process(why);\n\t}\n\tBEnd(BENCH_PCP);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Detach -- Removes the specified target from targeting computer.              *\n *                                                                                             *\n *    This is a support routine that removes the target specified from any targeting or        *\n *    navigation computers. When a target is destroyed or removed from the game system,        *\n *    the target must be removed from any tracking systems of the other units. This routine    *\n *    handles removal for infantry units.                                                      *\n *                                                                                             *\n * INPUT:   target   -- The target to remove from the infantry unit's tracking systems.        *\n *                                                                                             *\n *          all      -- Is the target going away for good as opposed to just cloaking/hiding?  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Detach(TARGET target, bool all)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (TarCom == target) {\n\t\tMark(MARK_OVERLAP_UP);\n\t\tIsFiring = false;\n\t\tMark(MARK_OVERLAP_DOWN);\n\t}\n\tFootClass::Detach(target, all);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Init -- Initialize the infantry object system.                               *\n *                                                                                             *\n *    This routine will force the infantry object system into its empty initial state. It      *\n *    is called when the scenario needs to be cleared in preparation for a scenario load.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Init(void)\n{\n\tInfantry.Free_All();\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Assign_Destination -- Gives the infantry a movement destination.             *\n *                                                                                             *\n *    This routine updates the infantry's navigation computer so that the infantry will        *\n *    travel to the destination target specified.                                              *\n *                                                                                             *\n * INPUT:   target   -- The target to have the infantry unit move to.                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Assign_Destination(TARGET target)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tSpecial flag so that infantry will start heading in the right direction immediately.\n\t*/\n\tif (IsDriving && !IsFormationMove && Target_Legal(target) && Map[Center_Coord()].Is_Clear_To_Move(Class->Speed, true, false)) {\n\t\tStop_Driver();\n\t}\n\n\t/*\n\t**\tWhen telling an infantry soldier to move to a location twice, then this\n\t**\tmeans that movement is more important than safety. Get up and run!\n\t*/\n\tif (House->IsHuman && Target_Legal(target) && NavCom == target && IsProne && !Class->IsFraidyCat && !Class->IsDog) {\n\t\tDo_Action(DO_GET_UP);\n\t}\n\n\t/*\n\t** If telling a dog to attack a human, start the dog running\n\t*/\n\tTechnoClass * tech = As_Techno(target);\n\n\t/*\n\t**\tHandle entry logic here.\n\t*/\n\tif (Mission == MISSION_ENTER || MissionQueue == MISSION_ENTER) {\n\n\t\t/*\n\t\t**\tIf not already in radio contact (presumed with the transport), then\n\t\t**\teither try to establish contact if allowed, or just move close and\n\t\t**\twait until radio contact can be established.\n\t\t*/\n\t\tif (!In_Radio_Contact()) {\n\t\t\tTechnoClass * techno = As_Techno(target);\n\t\t\tif (techno != NULL) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDetermine if the transport is already in radio contact. If so, then just move\n\t\t\t\t**\ttoward the transport and try to establish contact at a later time.\n\t\t\t\t*/\n\t\t\t\tif (techno->In_Radio_Contact()) {\n// TCTCTC -- call for an update from the transport to get a good rendezvous position.\n\n\t\t\t\t\tArchiveTarget = target;\n\t\t\t\t} else {\n\t\t\t\t\tif (Transmit_Message(RADIO_HELLO, techno) == RADIO_ROGER) {\n\t\t\t\t\t\tif (Transmit_Message(RADIO_DOCKING) != RADIO_ROGER) {\n\t\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t//BG: keep retransmitted navcom from radio-move-here.\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tPath[0] = FACING_NONE;\n\t\t}\n\t} else {\n\t\tPath[0] = FACING_NONE;\n\t}\n\tFootClass::Assign_Destination(target);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Assign_Target -- Gives the infantry a combat target.                         *\n *                                                                                             *\n *    This routine will update the infantry's targeting computer so that it will try to        *\n *    attack the target specified. This might result in it moving to be within range and thus  *\n *    also cause adjustment of the navigation computer.                                        *\n *                                                                                             *\n * INPUT:   target   -- The target that this infantry should attack.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *   06/30/1995 JLB : Tries to capture target if possible.                                     *\n *=============================================================================================*/\nvoid InfantryClass::Assign_Target(TARGET target)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tPath[0] = FACING_NONE;\n\tif (Class->IsDog) {\n\t\tif (::As_Object(target) && ::As_Object(target)->What_Am_I() != RTTI_INFANTRY) {\n\t\t\ttarget = TARGET_NONE;\n\t\t}\n\t}\n\tFootClass::Assign_Target(target);\n\n\t/*\n\t**\tIf this is an infantry that can only capture, then also assign its destination to the\n\t**\ttarget specified.\n\t*/\n\tif (!Target_Legal(NavCom) && Class->IsCapture && !Is_Weapon_Equipped()) {\n\t\tBuildingClass const * building = As_Building(target);\n\t\tif (building != NULL && building->Class->IsCaptureable) {\n\t\t\tAssign_Destination(target);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::AI -- Handles the infantry non-graphic related AI processing.                *\n *                                                                                             *\n *    This routine is used to handle the non-graphic AI processing the infantry requires.      *\n *    Call this routine ONCE per game frame.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *   08/14/1996 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid InfantryClass::AI(void)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tFootClass::AI();\n\n\tif (!IsActive) {\n\t\treturn;\n\t}\n\n\tif (IsUnloading) Mark(MARK_CHANGE_REDRAW);\n\n\t/*\n\t**\tInfantry that are not on the ground should always be redrawn. Such is\n\t**\tthe case when they are parachuting to the ground.\n\t*/\n\tif (In_Which_Layer() != LAYER_GROUND) {\n\t\tMark(MARK_CHANGE);\n\t}\n\n\t/*\n\t**\tSpecial hack to make sure that if this infantry is in firing animation, but the\n\t**\tstage class isn't set, then abort the firing flag.\n\t*/\n\tif (IsFiring && Fetch_Rate() == 0) {\n\t\tMark(MARK_OVERLAP_UP);\n\t\tIsFiring = false;\n\t\tDo_Action(DO_STAND_READY);\n\t\tMark(MARK_OVERLAP_DOWN);\n\t}\n\n\t/*\n\t**\tDelete this unit if it finds itself off the edge of the map and it is in\n\t**\tguard or other static mission mode.\n\t*/\n\tif (Edge_Of_World_AI()) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tAct on new orders if the unit is at a good position to do so.\n\t*/\n\tif (!IsFiring && !IsFalling && !IsDriving && (Doing == DO_NOTHING || MasterDoControls[Doing].Interrupt)) {\n\t\tif (Mission == MISSION_NONE && MissionQueue == MISSION_NONE) Enter_Idle_Mode();\n\t\tCommence();\n\t}\n\n\t/*\n\t**\tSpecial hack to make sure the dog never attacks a cell.\n\t*/\n\tif (Class->IsDog && Target_Legal(TarCom) && Is_Target_Cell(TarCom)) {\n\t\tAssign_Target(TARGET_NONE);\n\t}\n\n\t/*\n\t**\tHandle any infantry fear logic or related actions.\n\t*/\n\tFear_AI();\n\n\t/*\n\t**\tSpecial victory dance action.\n\t*/\n\tif (!Target_Legal(NavCom) && !IsProne && IsStoked && Comment == 0) {\n\t\tIsStoked = false;\n\t\tDo_Action(Percent_Chance(50) ? DO_GESTURE1 : DO_GESTURE2);\n\t}\n\n\t/*\n\t**\tDetermine if this infantry unit should fire off an\n\t**\tattack or not.\n\t*/\n\tFiring_AI();\n\n\t/*\n\t**\tHandle the completion of the animation sequence.\n\t*/\n\tDoing_AI();\n\n\t/*\n\t**\tPerform movement operations at this time.\n\t*/\n\tMovement_AI();\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Can_Enter_Cell -- Determines if the infantry can enter the cell specified.   *\n *                                                                                             *\n *    This routine is used to examine the cell specified and determine if the infantry is      *\n *    allowed to enter it. It is used by the path finding algorithm.                           *\n *                                                                                             *\n * INPUT:   cell  -- The cell to examine.                                                      *\n *                                                                                             *\n * OUTPUT:  Returns the type of blockage in the cell.                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nMoveType InfantryClass::Can_Enter_Cell(CELL cell, FacingType ) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t** If we are moving into an illegal cell, then we can't do that.\n\t*/\n\tif ((unsigned)cell >= MAP_CELL_TOTAL) return(MOVE_NO);\n\n\t/*\n\t**\tIf moving off the edge of the map, then consider that an illegal move.\n\t*/\n\tif (!ScenarioInit && !Map.In_Radar(cell) && !Is_Allowed_To_Leave_Map()) {\n\t\treturn(MOVE_NO);\n\t}\n\n\tCellClass * cellptr = &Map[cell];\n\n\t/*\n\t**\tWalls are considered impassable for infantry UNLESS the wall has a hole\n\t**\tin it.\n\t*/\n\tif (cellptr->Overlay != OVERLAY_NONE) {\n\t\tOverlayTypeClass const & otype = OverlayTypeClass::As_Reference(cellptr->Overlay);\n\n\t\tif (otype.IsCrate && !((Session.Type == GAME_NORMAL) ? House->IsPlayerControl : House->IsHuman) && Session.Type == GAME_NORMAL) {\n\t\t\treturn(MOVE_NO);\n\t\t}\n\n\t\tif (otype.IsWall) {\n\t\t\tif ((cellptr->OverlayData / 16) != otype.DamageLevels) {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the wall can be destroyed, then return this fact instead of\n\t\t\t\t**\ta complete failure to enter.\n\t\t\t\t*/\n\t\t\t\tif (Is_Weapon_Equipped() && Class->PrimaryWeapon->Is_Wall_Destroyer()) {\n\t\t\t\t\treturn(MOVE_DESTROYABLE);\n\t\t\t\t}\n\t\t\t\treturn(MOVE_NO);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Loop through all of the objects in the square setting a bit\n\t** for how they affect movement.\n\t*/\n\tMoveType retval = MOVE_OK;\n\tObjectClass * obj = cellptr->Cell_Occupier();\n\twhile (obj != NULL) {\n\n\t\tif (obj != this) {\n\n\t\t\t/*\n\t\t\t**\tAlways allow movement if the cell is the object to be captured or sabotaged.\n\t\t\t*/\n\t\t\tif (((Mission == MISSION_ENTER && In_Radio_Contact()) || Mission == MISSION_CAPTURE || Mission == MISSION_SABOTAGE) &&\n\t\t\t\t(obj->As_Target() == NavCom || obj->As_Target() == TarCom)) {\n\n\t\t\t\treturn(MOVE_OK);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tGuard area should not allow the guarding unit to enter the cell with the\n\t\t\t**\tguarded unit.\n\t\t\t*/\n\t\t\tif (Mission == MISSION_GUARD_AREA && ArchiveTarget == obj->As_Target() && Is_Target_Unit(ArchiveTarget)) {\n\t\t\t\treturn(MOVE_NO);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If object is a land mine, allow movement\n\t\t\t*/\n\t\t\tif (obj->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\tif ((*(BuildingClass *)obj) == STRUCT_AVMINE) {\n\t\t\t\t\tobj = obj->Next;\n\t\t\t\t\tcontinue;\n\t\t\t\t} else {\n\t\t\t\t\tif (!Rule.IsMineAware || !((BuildingClass *)obj)->House->Is_Ally(House)) {\n\t\t\t\t\t\tif ((*(BuildingClass *)obj) == STRUCT_APMINE) {\n\t\t\t\t\t\t\tobj = obj->Next;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSpecial case check so that a landed aircraft that is in radio contact, will not block\n\t\t\t**\ta capture attempt. It is presumed that this case happens when a helicopter is landed\n\t\t\t**\tat a helipad.\n\t\t\t*/\n//\t\t\tif ((Mission != MISSION_CAPTURE && Mission != MISSION_SABOTAGE) || obj->What_Am_I() != RTTI_AIRCRAFT || !((AircraftClass *)obj)->In_Radio_Contact()) {\n\n\t\t\t\t/*\n\t\t\t\t**\tSpecial check to always allow entry into the building that this infantry\n\t\t\t\t**\tis trying to capture.\n\t\t\t\t*/\n//\t\t\t\tif (obj->What_Am_I() == RTTI_BUILDING || obj->What_Am_I() == RTTI_AIRCRAFT || obj->What_Am_I() == RTTI_UNIT) {\n//\t\t\t\t\tif ((Mission == MISSION_CAPTURE || Mission == MISSION_SABOTAGE) && (obj->As_Target() == NavCom || obj->As_Target() == TarCom)) {\n//\t\t\t\t\t\treturn(MOVE_OK);\n//\t\t\t\t\t}\n//\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tSpecial check to always allow entry into the building that this infantry\n\t\t\t\t**\tis trying to capture.\n\t\t\t\t*/\n\t\t\t\tif (Mission == MISSION_ENTER && obj->As_Target() == NavCom && IsTethered) {\n\t\t\t\t\treturn(MOVE_OK);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAllied objects block movement using different rules than for enemy\n\t\t\t\t**\tobjects.\n\t\t\t\t*/\n\t\t\t\tif (House->Is_Ally(obj) || ScenarioInit) {\n\t\t\t\t\tswitch (obj->What_Am_I()) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tA unit blocks as either a moving blockage or a stationary temp blockage.\n\t\t\t\t\t\t**\tThis depends on whether the unit is currently moving or not.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RTTI_UNIT:\n\t\t\t\t\t\t\tif (((UnitClass *)obj)->IsDriving || Target_Legal(((UnitClass *)obj)->NavCom)) {\n\t\t\t\t\t\t\t\tif (retval < MOVE_MOVING_BLOCK) retval = MOVE_MOVING_BLOCK;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (retval < MOVE_TEMP) retval = MOVE_TEMP;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tAircraft and buildings always block movement. If for some reason there is an\n\t\t\t\t\t\t**\tallied terrain object, that blocks movement as well.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RTTI_TERRAIN:\n\t\t\t\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\t\t\tcase RTTI_BUILDING:\n\t\t\t\t\t\t\treturn(MOVE_NO);\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCloaked enemy objects are not considered if this is a Find_Path()\n\t\t\t\t\t**\tcall.\n\t\t\t\t\t*/\n\t\t\t\t\tif (!obj->Is_Techno() || ((TechnoClass *)obj)->Cloak != CLOAKED) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tAny non-allied blockage is considered impassible if the infantry\n\t\t\t\t\t\t**\tis not equipped with a weapon.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (Combat_Damage() <= 0) return(MOVE_NO);\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tSome kinds of terrain are considered destroyable if the infantry is equipped\n\t\t\t\t\t\t**\twith the weapon that can destroy it. Otherwise, the terrain is considered\n\t\t\t\t\t\t**\timpassable.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tswitch (obj->What_Am_I()) {\n\t\t\t\t\t\t\tcase RTTI_TERRAIN:\n#ifdef OBSOLETE\n\t\t\t\t\t\t\t\tif (((TerrainClass *)obj)->Class->Armor == ARMOR_WOOD &&\n\t\t\t\t\t\t\t\t\t\tClass->PrimaryWeapon->WarheadPtr->IsWoodDestroyer) {\n\n\t\t\t\t\t\t\t\t\tif (retval < MOVE_DESTROYABLE) retval = MOVE_DESTROYABLE;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\treturn(MOVE_NO);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n#else\n\t\t\t\t\t\t\t\treturn(MOVE_NO);\n#endif\n\t\t\t\t\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t\t\t\t\tif ( *(InfantryClass *)obj == INFANTRY_SPY && !Class->IsDog) {\n\t\t\t\t\t\t\t\t\tretval = MOVE_TEMP;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// otherwise, fall thru.\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tif (retval < MOVE_DESTROYABLE) retval = MOVE_DESTROYABLE;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (retval < MOVE_CLOAK) retval = MOVE_CLOAK;\n\t\t\t\t\t}\n\t\t\t\t}\n//\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tMove to next object in chain.\n\t\t*/\n\t\tobj = obj->Next;\n\t}\n\n\t/*\n\t**\tIf foot soldiers cannot travel on the cell -- consider it impassable.\n\t*/\n\tif (retval == MOVE_OK && !IsTethered && Ground[cellptr->Land_Type()].Cost[SPEED_FOOT] == 0) {\n\n#ifdef OBSOLETE\n\t\t/*\n\t\t** Special case - if it's an engineer, and the cell under consideration\n\t\t** is his NavCom, and his mission is mission_capture, then he's most\n\t\t** likely moving to his final destination to repair a bridge, so we\n\t\t** should let him.\n\t\t*/\n\t\tif (*this == INFANTRY_RENOVATOR && Is_Target_Cell(TarCom) && (cell == ::As_Cell(NavCom)) && (cellptr->TType == TEMPLATE_BRIDGE1D || cellptr->TType == TEMPLATE_BRIDGE2D || (cellptr->TType >= TEMPLATE_BRIDGE_1C && cellptr->TType <= TEMPLATE_BRIDGE_3E) ) ) {\n\t\t\treturn(MOVE_OK);\n\t\t}\n#endif\n\t\treturn(MOVE_NO);\n\t}\n\n\t/*\n\t** if a unit has the cell reserved then we just can't go in there.\n\t*/\n\tif (retval == MOVE_OK && cellptr->Flag.Occupy.Vehicle) {\n\t\treturn(MOVE_NO);\n\t}\n\n\t/*\n\t** if a block of infantry has the cell reserved then there are two\n\t** possibilities...\n\t*/\n\tif (cellptr->InfType != HOUSE_NONE) {\n\t\tif (House->Is_Ally(cellptr->InfType)) {\n\t\t\tif ((cellptr->Flag.Composite & 0x1F) == 0x1f) {\n\t\t\t\tif (retval < MOVE_MOVING_BLOCK) retval = MOVE_MOVING_BLOCK;\n\t\t\t}\n\t\t} else {\n\t\t\tif (Combat_Damage() > 0) {\n\t\t\t\tif (retval < MOVE_DESTROYABLE) {\n\t\t\t\t\tretval = MOVE_DESTROYABLE;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn(MOVE_NO);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf it is still ok to move the infantry, then perform the last check\n\t**\tto see if the cell is already full of infantry.\n\t*/\n\tif (retval == MOVE_OK && (cellptr->Flag.Composite & 0x1F) == 0x1F) {\n\t\treturn(MOVE_NO);\n\t}\n\n\t/*\n\t**\tReturn with the most severe reason why this cell would be impassable.\n\t*/\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Overlap_List -- The list of cells that the infantry overlaps, but doesn't occ*\n *                                                                                             *\n *    This is a rendering support routine that will return a pointer to a list of cell offsets *\n *    that specify the cells the infantry unit is currently overlapping (graphic wise) but     *\n *    is not considered to occupy. This list is used to update the map display.                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to an offset list for cells that the unit overlaps but doesn't   *\n *          occupy.                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef PARTIAL\nshort const * InfantryClass::Overlap_List(bool redraw) const\n#else\nshort const * InfantryClass::Overlap_List(bool ) const\n#endif\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsDog) {\n\t\treturn(Coord_Spillage_List(Coord, 24 + (Doing == DO_DOG_MAUL ? 40 : 0) + (Doing >= DO_GUN_DEATH && Doing <= DO_FIRE_DEATH ? 40 : 0) ));\n\t} else {\n\n\t\t/*\n\t\t**\tThe default infantry rectangle will be as large as the largest shape the infantry\n\t\t**\tcan be.\n\t\t*/\n\n#ifdef PARTIAL\n\t\tRect rect(-16, -24, 32, 36);\n\n\t\t/*\n\t\t**\tIf this is for a visual change redraw, then the overlap list will be based\n\t\t**\ton the actual dimensions of the shape data. If the dimensions have already\n\t\t**\tbeen calculated then use them, otherwise, use the default large rectangle\n\t\t**\tpreviously created.\n\t\t*/\n\t\tif (Height == 0 && !IsSelected && redraw && Class->DimensionData != NULL) {\n\t\t\tint shapenum = Shape_Number();\n\t\t\tif (!Class->DimensionData[shapenum].Is_Valid()) {\n\t\t\t\tClass->DimensionData[shapenum] = Shape_Dimensions(Get_Image_Data(), shapenum);\n\t\t\t}\n\t\t\trect = Class->DimensionData[shapenum];\n\t\t\trect.Y += 4;\n\t\t\trect.X -= 2;\n\t\t}\n\t\treturn(Coord_Spillage_List(Coord, rect, true));\n#else\n\n\t\tstatic Rect rect(-16, -24, 32, 36);\n\t\treturn(Coord_Spillage_List(Coord, rect, true));\n#endif\n\n//\t\treturn(Coord_Spillage_List(Coord, 24 /*+ ((Doing > DO_WALK || IsSelected)?12:0)*/ ));\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Can_Fire -- Can the infantry fire its weapon?                                *\n *                                                                                             *\n *    Determines if the infantry unit can fire on the target. If it can't fire, then the       *\n *    reason why is returned.                                                                  *\n *                                                                                             *\n * INPUT:   target   -- The target to determine if the infantry can fire upon.                 *\n *                                                                                             *\n * OUTPUT:  Returns the fire error type that indicates if the infantry can fire and if it      *\n *          can't, why not.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *   06/27/1995 JLB : Flame thrower can fire while prone now.                                  *\n *=============================================================================================*/\nFireErrorType InfantryClass::Can_Fire(TARGET target, int which) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tDon't allow firing if the infantry is still firing on previous target.\n\t*/\n//\tif (IsFiring) return(FIRE_REARM);\n\n\t/*\n\t** If a medic is shooting at a healed target, let's declare the target\n\t** illegal so he won't be constantly healing healed infantrymen.\n\t*/\n\tif (Combat_Damage() < 0) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tTechnoClass * targ = As_Techno(target);\n#else\n\t\tInfantryClass * targ = As_Infantry(target);\n#endif\n\t\tif (targ == NULL || targ->Health_Ratio() >= Rule.ConditionGreen) {\n\t\t\treturn(FIRE_ILLEGAL);\n\t\t}\n\t}\n\n\t/*\n\t**\tIf this unit cannot fire while moving, then bail.\n\t*/\n\tif (IsDriving || (Target_Legal(NavCom) && Doing != DO_NOTHING && !MasterDoControls[Doing].Interrupt)) {\n\t\treturn(FIRE_MOVING);\n\t}\n\n\treturn(FootClass::Can_Fire(target, which));\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Enter_Idle_Mode -- The infantry unit enters idle mode by this routine.       *\n *                                                                                             *\n *    Use this routine when the infantry unit as accomplished its task and needs to find       *\n *    something to do. The default behavior is to enter some idle state such as guarding.      *\n *                                                                                             *\n * INPUT:   initial  -- Is this called when the unit just leaves a factory or is initially     *\n *                      or is initially placed on the map?                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Enter_Idle_Mode(bool )\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tMissionType order = MISSION_GUARD;\n\n\tif (Target_Legal(TarCom)) {\n\t\torder = MISSION_ATTACK;\n\t\tif (Mission == MISSION_SABOTAGE) {\n\t\t\torder = MISSION_SABOTAGE;\n\t\t}\n\t\tif (Mission == MISSION_CAPTURE) {\n\t\t\torder = MISSION_CAPTURE;\n\t\t}\n\t} else {\n\n\t\tHandle_Navigation_List();\n\n\t\tif (Target_Legal(NavCom)) {\n\t\t\torder = MISSION_MOVE;\n\t\t\tif (Mission == MISSION_CAPTURE) {\n\t\t\t\torder = MISSION_CAPTURE;\n\t\t\t}\n\t\t\tif (Mission == MISSION_SABOTAGE) {\n\t\t\t\torder = MISSION_SABOTAGE;\n\t\t\t}\n\t\t} else {\n\n\t\t\tif (Mission == MISSION_GUARD || Mission == MISSION_GUARD_AREA || MissionControl[Mission].IsZombie || MissionControl[Mission].IsParalyzed) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (Class->IsDog) {\n\t\t\t\tif (House->IsHuman || Team.Is_Valid()) {\n\t\t\t\t\torder = MISSION_GUARD;\n\t\t\t\t} else {\n\t\t\t\t\torder = MISSION_GUARD_AREA;\n\t\t\t\t\tArchiveTarget = ::As_Target(Coord_Cell(Center_Coord()));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (House->IsHuman || Team.Is_Valid()) {\n\t\t\t\t\torder = MISSION_GUARD;\n\t\t\t\t} else {\n\t\t\t\t\tif (House->IQ < Rule.IQGuardArea) {\n\t\t\t\t\t\torder = MISSION_GUARD;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (Is_Weapon_Equipped()) {\n\t\t\t\t\t\t\torder = MISSION_GUARD_AREA;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\torder = MISSION_GUARD;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tAssign_Mission(order);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Random_Animate -- Randomly animate the infantry (maybe)                      *\n *                                                                                             *\n *    This routine is the random animator initiator for infantry units. This routine should    *\n *    be called regularly. On occasion, it will cause the infantry to go into an idle          *\n *    animation.                                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *   12/13/1994 JLB : Does random facing change.                                               *\n *   07/02/1995 JLB : Nikoomba special effects.                                                *\n *=============================================================================================*/\nbool InfantryClass::Random_Animate(void)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Is_Ready_To_Random_Animate()) {\n\t\tIdleTimer = Random_Pick(Rule.RandomAnimateTime * (TICKS_PER_MINUTE/2), Rule.RandomAnimateTime * (TICKS_PER_MINUTE*2));\n\n\t\t/*\n\t\t**\tScared infantry will always follow the golden rule of civilians;\n\t\t**\t\t\"When in darkness or in doubt, run in circles, scream, and shout!\"\n\t\t*/\n\t\tif (Class->IsFraidyCat && !House->IsHuman && Fear > FEAR_ANXIOUS) {\n\t\t\tScatter(NULL, true);\n\t\t\treturn(true);\n\t\t}\n\n\t\tswitch (Random_Pick(0, 10)) {\n\t\t\tcase 0:\n\t\t\t\tif (Class->IsDog) {\n\t\t\t\t\tDo_Action(DO_IDLE1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 1:\n\t\t\t\tDo_Action(DO_SALUTE1);\n\t\t\t\tbreak;\n\n\t\t\tcase 2:\n\t\t\t\tDo_Action(DO_SALUTE2);\n\t\t\t\tbreak;\n\n\t\t\tcase 3:\n\t\t\t\tDo_Action(DO_GESTURE1);\n\t\t\t\tbreak;\n\n\t\t\tcase 4:\n\t\t\t\tDo_Action(DO_GESTURE2);\n\t\t\t\tbreak;\n\n\t\t\tcase 5:\n\t\t\t\tDo_Action(DO_IDLE1);\n\t\t\t\tbreak;\n\n\t\t\tcase 6:\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t\tPrimaryFacing.Set(Facing_Dir(Random_Pick(FACING_N, FACING_NW)));\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t\tbreak;\n\n\t\t\tcase 7:\n\t\t\t\tDo_Action(DO_IDLE2);\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t\tPrimaryFacing.Set(Facing_Dir(Random_Pick(FACING_N, FACING_NW)));\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t\tif (!IsSelected && IsOwnedByPlayer && *this == INFANTRY_TANYA && Sim_Random_Pick(0, 2) == 0) {\n\t\t\t\t\tSound_Effect(VOC_TANYA_SHAKE, Coord);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tOn occasion, civilian types will wander about.\n\t\t\t*/\n\t\t\tcase 8:\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t\tPrimaryFacing.Set(Facing_Dir(Random_Pick(FACING_N, FACING_NW)));\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t\tif (!House->IsHuman && Class->IsFraidyCat) {\n\t\t\t\t\tScatter(NULL, true);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 9:\n\t\t\tcase 10:\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t\tPrimaryFacing.Set(Facing_Dir(Random_Pick(FACING_N, FACING_NW)));\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Scatter -- Causes the infantry to scatter to nearby cell.                    *\n *                                                                                             *\n *    This routine is used when the infantry should scatter to a nearby cell. Scattering       *\n *    occurs as an occasional consequence of being fired upon. It is one of the features       *\n *    that makes infantry so \"charming\".                                                       *\n *                                                                                             *\n * INPUT:   threat   -- The coordinate source of the threat that is causing the infantry to    *\n *                      scatter. If the threat isn't from a particular direction, then this    *\n *                      parameter will be NULL.                                                *\n *                                                                                             *\n *          forced   -- The threat is real and a serious effort to scatter should be made.     *\n *                                                                                             *\n *          nokidding-- The scatter should affect the player's infantry even if it otherwise   *\n *                      wouldn't have.                                                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *   12/12/1994 JLB : Flame thrower infantry always scatter.                                   *\n *   08/02/1996 JLB : Added the nokidding parameter                                            *\n *=============================================================================================*/\nvoid InfantryClass::Scatter(COORDINATE threat, bool forced, bool nokidding)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tA unit that is in the process of going somewhere will never scatter.\n\t*/\n\tif (IsDriving) forced = false;\n\n\t/*\n\t**\tCertain missions prevent scattering regardless of whether it would be\n\t**\ta good idea or not.\n\t*/\n\tif (!MissionControl[Mission].IsScatter && !forced) return;\n\n\t/*\n\t**\tIf the infantry is currently engaged in legitimate combat, then don't\n\t**\tscatter unless forced to.\n\t*/\n\tif (!Class->IsFraidyCat && Target_Legal(TarCom) && !forced) return;\n\n\t/*\n\t**\tDon't scatter if performing an action that can't be interrupted.\n\t*/\n\tif (Doing != DO_NOTHING && !MasterDoControls[Doing].Interrupt) return;\n\n\t/*\n\t**\tFor human players, don't scatter the infantry, if the special\n\t**\tflag has not been enabled that allows infantry scatter.\n\t*/\n\tif (!Rule.IsScatter && !nokidding && House->IsHuman && !forced && !Team.Is_Valid()) return;\n\n\tif (forced || Class->IsFraidyCat /*|| !(Random_Pick(1, 4) == 1)*/) {\n\t\tFacingType\ttoface;\n\n\t\tif (threat) {\n\t\t\ttoface = Dir_Facing(Direction8(threat, Coord));\n\t\t\ttoface = toface + FacingType(Random_Pick(0, 4)-2);\n\t\t} else {\n\t\t\tCOORDINATE coord = Coord_Fraction(Center_Coord());\n\n\t\t\tif (coord != 0x00800080L) {\n\t\t\t\ttoface = Dir_Facing((DirType)Desired_Facing8(0x0080, 0x0080, Coord_X(coord), Coord_Y(coord)));\n\t\t\t} else {\n\t\t\t\ttoface = Dir_Facing(PrimaryFacing.Current());\n\t\t\t}\n\t\t\ttoface = toface + FacingType(Random_Pick(0, 4)-2);\n\t\t}\n\n\t\tCELL newcell = 0;\n\t\tCELL altcell = 0;\n\t\tfor (FacingType face = FACING_N; face < FACING_COUNT; face++) {\n\t\t\tFacingType newface = toface + face;\n\t\t\tnewcell = Adjacent_Cell(Coord_Cell(Coord), newface);\n\n\t\t\tif (Map.In_Radar(newcell) && Can_Enter_Cell(newcell) == MOVE_OK) {\n\t\t\t\tif (altcell == 0) altcell = newcell;\n\t\t\t\tif (!Map[newcell].Is_Bridge_Here()) break;\n//\t\t\t\tAssign_Mission(MISSION_MOVE);\n//\t\t\t\tAssign_Destination(::As_Target(newcell));\n\t\t\t}\n\t\t}\n\t\tif (face == FACING_COUNT) {\n\t\t\tnewcell = 0;\n\t\t}\n\n\t\tif (newcell == 0) {\n\t\t\tnewcell = altcell;\n\t\t}\n\n\t\tif (newcell != 0) {\n\t\t\tAssign_Mission(MISSION_MOVE);\n\t\t\tAssign_Destination(::As_Target(newcell));\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Do_Action -- Launches the infantry into an animation sequence.               *\n *                                                                                             *\n *    This starts the infantry into a choreographed animation sequence. These sequences can    *\n *    be as simple as standing up or lying down, but can also be complex, such as dying or     *\n *    performing some idle animation.                                                          *\n *                                                                                             *\n * INPUT:   todo     -- The choreographed sequence to start.                                   *\n *                                                                                             *\n *          force    -- Force starting this animation even if the current animation is flagged *\n *                      as uninterruptible. This is necessary for death animations.            *\n *                                                                                             *\n * OUTPUT:  bool; Was the animation started?                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryClass::Do_Action(DoType todo, bool force)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (todo == DO_NOTHING || Class->DoControls[todo].Count == 0) {\n\t\treturn(false);\n\t}\n\n\tif (*this == INFANTRY_SPY && todo >= DO_GESTURE1) {\n\t\ttodo = (DoType)(DO_IDLE1 + Random_Pick(0,1));\n\t}\n\n\tif (todo != Doing && (Doing == DO_NOTHING || force || MasterDoControls[Doing].Interrupt)) {\n\t\tMark(MARK_OVERLAP_UP);\n\t\tDoing = todo;\n\t\tMark(MARK_OVERLAP_DOWN);\n\t\tif (todo == DO_IDLE1 || todo == DO_IDLE2) {\n\t\t\tSet_Rate(Options.Normalize_Delay(MasterDoControls[Doing].Rate));\n\t\t} else {\n\t\t\tSet_Rate(MasterDoControls[Doing].Rate);\n\t\t}\n\t\tSet_Stage(0);\n\n\t\t/*\n\t\t**\tKludge to make sure that if infantry is in the dying animation, it isn't still\n\t\t**\tmoving as well.\n\t\t*/\n\t\tif (Strength == 0) {\n\t\t\tStop_Driver();\n\t\t}\n\n\t\t/*\n\t\t**\tSince the animation sequence might be interrupted. Set any flags\n\t\t**\tnecessary so that if interrupted, the affect on the infantry is\n\t\t**\tstill accomplished.\n\t\t*/\n\t\tswitch (todo) {\n\t\t\tcase DO_LIE_DOWN:\n\t\t\t\tIsProne = true;\n\t\t\t\tbreak;\n\n\t\t\tcase DO_GET_UP:\n\t\t\t\tIsProne = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn(true);\n\t}\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Stop_Driver -- Stops the infantry from moving any further.                   *\n *                                                                                             *\n *    This is used to stop the infantry from animating in movement. This function will stop    *\n *    the infantry moving and revert it to either a prone or standing.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the driving stopped?                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryClass::Stop_Driver(void)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Head_To_Coord()) {\n\n\t\t/*\n\t\t**\tRemove the \"reservation\" bit in the destination location.\n\t\t*/\n\t\tClear_Occupy_Bit(Head_To_Coord());\n\t}\n\n\t/*\n\t**\tSet the occupation bit at the current location.\n\t*/\n\tSet_Occupy_Bit(Coord);\n\n\tif (Class->IsDog) {\n\t\tDo_Action(DO_STAND_READY);\n\t} else {\n\t\tif (IsProne) {\n\t\t\tDo_Action(DO_PRONE);\n\t\t} else {\n\t\t\tDo_Action(DO_STAND_READY);\n\t\t}\n\t}\n\n\tif (Can_Enter_Cell(Coord_Cell(Coord)) == MOVE_OK) {\n\t\tIsZoneCheat = false;\n\t} else {\n\t\tIsZoneCheat = true;\n\t}\n\n\treturn(FootClass::Stop_Driver());\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Start_Driver -- Handles giving immediate destination and move orders.        *\n *                                                                                             *\n *    Use this routine to being the infantry moving toward the destination specified. The      *\n *    destination is first checked to see if there is a free spot available. Then the infantry *\n *    reserves that spot and begins movement toward it.                                        *\n *                                                                                             *\n * INPUT:   headto   -- The coordinate location desired for the infantry to head to.           *\n *                                                                                             *\n * OUTPUT:  bool; Was the infantry successfully started on its journey? Failure may be because *\n *                the specified destination could not contain the infantry unit.               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/21/1994 JLB : Created.                                                                 *\n *   05/14/1995 JLB : Tries to move to closest spot possible.                                  *\n *   05/15/1995 JLB : Uses closest spot if moving onto transport.                              *\n *=============================================================================================*/\nbool InfantryClass::Start_Driver(COORDINATE & headto)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tCOORDINATE old = headto;\n\n\t/*\n\t**\tConvert the head to coordinate to a legal sub-position location.\n\t*/\n\theadto = Map[headto].Closest_Free_Spot(Coord_Move(headto, Direction(headto)+DIR_S, 0x007C));\n\tif (!headto && Can_Enter_Cell(Coord_Cell(old)) == MOVE_OK) {\n\t\theadto = Map[old].Closest_Free_Spot(Coord_Move(old, Direction(headto)+DIR_S, 0x0080), true);\n\t}\n\n\t/*\n\t**\tIf the infantry started moving, then fixup the occupation bits.\n\t*/\n\tif (headto && FootClass::Start_Driver(headto)) {\n\t\tif (!IsActive) return(false);\n\n\t\t/*\n\t\t**\tRemove the occupation bit from the infantry's current location.\n\t\t*/\n  \t\tClear_Occupy_Bit(Coord);\n\n\t\t/*\n\t\t**\tSet the occupation bit for the new headto location.\n\t\t*/\n\t\tSet_Occupy_Bit(headto);\n\t\treturn(true);\n\t}\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Limbo -- Performs cleanup operations needed when limboing.                   *\n *                                                                                             *\n *    This routine will clean up the infantry occupation bits (as necessary) as well as stop   *\n *    the infantry movement process when it gets limboed.                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the infantry unit limboed?                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryClass::Limbo(void)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!IsInLimbo) {\n\t\tStop_Driver();\n\n\t\tClear_Occupy_Bit(Coord);\n\t}\n\treturn(FootClass::Limbo());\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Fire_At -- Fires projectile from infantry unit.                              *\n *                                                                                             *\n *    Use this routine when the infantry unit wishes to fire a projectile. This routine        *\n *    will launch the projectile and perform any other necessary infantry specific operations. *\n *                                                                                             *\n * INPUT:   target   -- The target of the attack.                                              *\n *                                                                                             *\n *          which    -- Which weapon to use for firing. 0=primary, 1=secondary.                *\n *                                                                                             *\n * OUTPUT:  Returns with pointer to the projectile launched. If none could be launched, then   *\n *          NULL is returned. If there is already the maximum bullet objects in play, then     *\n *          this could happen.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nBulletClass * InfantryClass::Fire_At(TARGET target, int which)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tMark(MARK_OVERLAP_UP);\n\tIsFiring = false;\n\tMark(MARK_OVERLAP_DOWN);\n\n\tBulletClass * bullet = FootClass::Fire_At(target, which);\n\tif (bullet != NULL && !IsInLimbo) {\n\n\t\t/*\n\t\t**\tFor fraidycat infantry that run out of ammo, always go into\n\t\t**\ta maximum fear state at that time.\n\t\t*/\n\t\tif (Class->IsFraidyCat && !Ammo) {\n\t\t\tFear = FEAR_MAXIMUM;\n\t\t\tif (Mission == MISSION_ATTACK || Mission == MISSION_HUNT) {\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t}\n\t\t}\n\t}\n\treturn(bullet);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Unlimbo -- Unlimbo infantry unit in legal sub-location.                      *\n *                                                                                             *\n *    This will attempt to unlimbo the infantry unit at the designated coordinate, but will    *\n *    ensure that the coordinate is a legal subposition.                                       *\n *                                                                                             *\n * INPUT:   coord    -- The coordinate to unlimbo the infantry at.                             *\n *                                                                                             *\n *          facing   -- The desired initial facing for the infantry unit.                      *\n *                                                                                             *\n *          strength -- The desired initial strength for the infantry unit.                    *\n *                                                                                             *\n *          mission  -- The desired initial mission for the infantry unit.                     *\n *                                                                                             *\n * OUTPUT:  bool; Was the infantry unlimboed successfully?                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryClass::Unlimbo(COORDINATE coord, DirType facing)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tMake sure that the infantry start in a legal position on the map.\n\t*/\n\tcoord = Map[coord].Closest_Free_Spot(coord, ScenarioInit);\n\tif (coord == NULL) {\n\t\treturn(false);\n\t}\n\n\tif (FootClass::Unlimbo(coord, facing)) {\n\n\t\t/*\n\t\t**\tEnsure that the owning house knows about the\n\t\t**\tnew object.\n\t\t*/\n\t\tHouse->IScan |= (1L << Class->Type);\n\t\tHouse->ActiveIScan |= (1L << Class->Type);\n\n\t\t/*\n\t\t**\tIf there is no sight range, then this object isn't discovered by the player unless\n\t\t**\tit actually appears in a cell mapped by the player.\n\t\t*/\n\t\tif (Class->SightRange == 0) {\n\t\t\tIsDiscoveredByPlayer = false;\n\t\t}\n\n\t\tSet_Occupy_Bit(coord);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Greatest_Threat -- Determines greatest threat (target) for infantry unit.    *\n *                                                                                             *\n *    This routine intercepts the Greatest_Threat request and adds the appropriate target      *\n *    types to search for. For regular infantry, this consists of all the ground types. For    *\n *    rocket launching infantry, this also includes aircraft.                                  *\n *                                                                                             *\n * INPUT:   threat   -- The basic threat control value.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with the best target for this infantry unit to attack. If no suitable      *\n *          target could be found, then TARGET_NONE is returned.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/01/1995 JLB : Created.                                                                 *\n *   09/28/1995 JLB : Engineers try to recapture buildings first.                              *\n *=============================================================================================*/\nTARGET InfantryClass::Greatest_Threat(ThreatType threat) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tEngineers consider only buildings that can be captured as being a threat. All others\n\t**\tare ignored. If there is a building that needs to be recaptured and it is nearby\n\t**\tthen automatically head toward it to recapture it.\n\t*/\n\tif (!House->IsHuman && Class->IsCapture && !Is_Weapon_Equipped()) {\n\t\tif (House->ToCapture != TARGET_NONE && Distance(House->ToCapture) < 0x0F00) {\n\t\t\treturn(House->ToCapture);\n\t\t}\n\t\tthreat = threat | THREAT_CAPTURE;\n\t}\n\n\tif (!Is_Weapon_Equipped()) {\n\t\tif (!Class->IsCapture && *this != INFANTRY_RENOVATOR && *this != INFANTRY_SPY && *this != INFANTRY_THIEF) {\n\t\t\treturn(TARGET_NONE);\n\t\t}\n\t}\n\n\t/*\n\t**\tSpecial hack to make Tanya not auto-fire if controlled by a\n\t**\thuman player.\n\t*/\n\tif (*this == INFANTRY_TANYA && House->IsHuman) {\n\t\treturn(TARGET_NONE);\n\t}\n\n\tif (Class->PrimaryWeapon != NULL) {\n\t\tthreat = threat | Class->PrimaryWeapon->Allowed_Threats();\n\t}\n\tif (Class->SecondaryWeapon != NULL) {\n\t\tthreat = threat | Class->SecondaryWeapon->Allowed_Threats();\n\t}\n\n\t/*\n\t**\tOrganic weapon types don't consider anything but infantry to be a threat. Such\n\t**\tweapon types would be the dog jaw and the medic first aid kit.\n\t*/\n\tif (Is_Weapon_Equipped() && Class->PrimaryWeapon->WarheadPtr->IsOrganic) {\n\t\tthreat = threat & ~(THREAT_BUILDINGS|THREAT_VEHICLES|THREAT_BOATS|THREAT_AIR);\n\t}\n\n\t/*\n\t**\tHuman controlled infantry don't automatically fire upon buildings.\n\t*/\n\tif (Is_Weapon_Equipped() && House->IsHuman) {\n\t\tthreat = threat & ~THREAT_BUILDINGS;\n\t}\n\n\t/*\n\t**\tIf this is a bomber type, then allow buildings to be considered a threat.\n\t*/\n\tif (Class->IsBomber && !House->IsHuman) {\n\t\tthreat = threat | THREAT_BUILDINGS;\n\t}\n\n\t/*\n\t** Special hack: if it's a thief, then the only possible objects to\n\t** consider are tiberium-processing objects (silos & refineries).\n\t*/\n\tif (*this == INFANTRY_THIEF) {\n\t\tthreat = threat | THREAT_CAPTURE | THREAT_TIBERIUM;\n//\t\tthreat = (ThreatType)(THREAT_CAPTURE | THREAT_TIBERIUM);\n\t}\n\treturn(FootClass::Greatest_Threat(threat));\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Response_Select -- Plays infantry audio response due to being selected.      *\n *                                                                                             *\n *    This routine handles playing an audio response as a result of the player selecting the   *\n *    infantry unit. This occurs prior to giving it an order and may not be followed by any    *\n *    order at all.                                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/01/1995 JLB : Created.                                                                 *\n *   05/05/1995 JLB : Rambo response types added.                                              *\n *=============================================================================================*/\nvoid InfantryClass::Response_Select(void)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!AllowVoice) return;\n\n\tif (Class->IsCivilian && *this != INFANTRY_EINSTEIN) {\n\t\tVocType response = VOC_NONE;\n\t\tif (Class->IsFemale) {\n\t\t\tresponse = VOC_GIRL_YEAH;\n\t\t} else {\n\t\t\tresponse = VOC_GUY_YEAH;\n\t\t}\n\t\tSound_Effect(response, fixed(1), ID+1);\n\n\t} else {\n\t\tstatic VocType _eng_response[] = {VOC_ENG_YES,VOC_ENG_ENG};\n\t\tstatic VocType _ein_response[] = {VOC_E_AH};\n\t\tstatic VocType _dog_response[] = {VOC_DOG_YES};\n\t\tstatic VocType _spy_response[] = {VOC_SPY_COMMANDER,VOC_SPY_YESSIR};\n\t\tstatic VocType _medic_response[] = {VOC_MED_REPORTING,VOC_MED_YESSIR};\n\t\tstatic VocType _tanya_response[] = {VOC_TANYA_YEA,VOC_TANYA_YES,VOC_TANYA_WHATS};\n\t\tstatic VocType _thief_response[] = {VOC_THIEF_YEA,VOC_THIEF_WHAT};\n\t\tstatic VocType _default_response[] = {VOC_ACKNOWL,VOC_REPORT,VOC_REPORT,VOC_YESSIR,VOC_YESSIR,VOC_READY,VOC_AWAIT};\n\t\tstatic VocType _stavros[] = {VOC_STAVCMDR,VOC_STAVYES};\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tstatic VocType _mechanic_response[] = {VOC_MECHHOWDY1,VOC_MECHHUH1,VOC_MECHLAFF1};\n\t\tstatic VocType _shock_response[] = {VOC_STYES1,VOC_STJUMP1,VOC_STJUICE1};\n#endif\n\n\t\tint size = 0;\n\t\tVocType * response = NULL;\n\t\tHousesType house = PlayerPtr->ActLike;\n\t\tswitch (Class->Type) {\n\t\t\tcase INFANTRY_GENERAL:\n\t\t\t\tif (house != HOUSE_USSR && house != HOUSE_BAD) {\n\t\t\t\t\tresponse = _stavros;\n\t\t\t\t\tsize = ARRAY_SIZE(_stavros);\n\t\t\t\t} else {\n\t\t\t\t\tresponse = _default_response;\n\t\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\t}\n\t\t\t\thouse = HOUSE_USSR;\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_DOG:\n\t\t\t\tresponse = _dog_response;\n\t\t\t\tsize = ARRAY_SIZE(_dog_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_EINSTEIN:\n\t\t\t\tresponse = _ein_response;\n\t\t\t\tsize = ARRAY_SIZE(_ein_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_SPY:\n\t\t\t\tresponse = _spy_response;\n\t\t\t\tsize = ARRAY_SIZE(_spy_response);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif(house == HOUSE_USSR) {\n\t\t\t\t\tresponse = _default_response;\n\t\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\t}\n#endif\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_MEDIC:\n\t\t\t\tresponse = _medic_response;\n\t\t\t\tsize = ARRAY_SIZE(_medic_response);\n\t\t\t\tbreak;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tcase INFANTRY_MECHANIC:\n\t\t\t\tresponse = _mechanic_response;\n\t\t\t\tsize = ARRAY_SIZE(_mechanic_response);\n\t\t\t\tbreak;\n\t\t\tcase INFANTRY_SHOCK:\n\t\t\t\tresponse = _shock_response;\n\t\t\t\tsize = ARRAY_SIZE(_shock_response);\n\t\t\t\tbreak;\n#endif\n\t\t\tcase INFANTRY_TANYA:\n\t\t\t\tresponse = _tanya_response;\n\t\t\t\tsize = ARRAY_SIZE(_tanya_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_THIEF:\n\t\t\t\tresponse = _thief_response;\n\t\t\t\tsize = ARRAY_SIZE(_thief_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_RENOVATOR:\n\t\t\t\tresponse = _eng_response;\n\t\t\t\tsize = ARRAY_SIZE(_eng_response);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tresponse = _default_response;\n\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\tbreak;\n\t\t}\n\t\tif (response != NULL) {\n\t\t\tSound_Effect(response[Sim_Random_Pick(0, size-1)], fixed(1), ID+1, 0, house);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Response_Move -- Plays infantry response to movement order.                  *\n *                                                                                             *\n *    When the infantry is given the order to move, this routine handles the audio response    *\n *    generated by the infantry unit.                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/01/1995 JLB : Created.                                                                 *\n *   05/05/1995 JLB : Rambo response types added.                                              *\n *=============================================================================================*/\nvoid InfantryClass::Response_Move(void)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!AllowVoice) return;\n\n\tif (Class->IsCivilian && *this != INFANTRY_EINSTEIN) {\n\t\tVocType response;\n\t\tif (Class->IsFemale) {\n\t\t\tresponse = VOC_GIRL_OKAY;\n\t\t} else {\n\t\t\tresponse = VOC_GUY_OKAY;\n\t\t}\n\t\tSound_Effect(response, fixed(1), ID+1);\n\n\t} else {\n\t\tstatic VocType _eng_response[] = {VOC_ENG_AFFIRM,VOC_ENG_AFFIRM};\n\t\tstatic VocType _ein_response[] = {VOC_E_OK,VOC_E_YES};\n\t\tstatic VocType _dog_response[] = {VOC_DOG_BARK};\n\t\tstatic VocType _spy_response[] = {VOC_SPY_ONWAY,VOC_SPY_KING,VOC_SPY_INDEED};\n\t\tstatic VocType _medic_response[] = {VOC_MED_AFFIRM,VOC_MED_MOVEOUT};\n#ifdef ENGLISH\n\t\tstatic VocType _tanya_response[] = {VOC_TANYA_THERE,VOC_TANYA_ROCK};\n#else\n\t\tstatic VocType _tanya_response[] = {VOC_TANYA_THERE,VOC_TANYA_GIVE};\n#endif\n\t\tstatic VocType _thief_response[] = {VOC_THIEF_MOVEOUT,VOC_THIEF_OKAY,VOC_THIEF_AFFIRM};\n\t\tstatic VocType _default_response[] = {VOC_ROGER,VOC_RIGHT_AWAY,VOC_UGOTIT,VOC_AFFIRM,VOC_AFFIRM};\n\t\tstatic VocType _stavros[] = {VOC_STAVMOV,VOC_STAVCRSE};\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tstatic VocType _mechanic[] = {VOC_MECHYES1,VOC_MECHRISE1,VOC_MECHHEAR1,VOC_MECHBOSS1};\n\t\tstatic VocType _shock[] = {VOC_STPOWER1,VOC_STDANCE1,VOC_STCHRGE1};\n#endif\n\n\t\tint size = 0;\n\t\tVocType * response = NULL;\n\t\tHousesType house = PlayerPtr->ActLike;\n\t\tswitch (Class->Type) {\n\t\t\tcase INFANTRY_GENERAL:\n\t\t\t\tif (house != HOUSE_USSR && house != HOUSE_BAD) {\n\t\t\t\t\tresponse = _stavros;\n\t\t\t\t\tsize = ARRAY_SIZE(_stavros);\n\t\t\t\t} else {\n\t\t\t\t\tresponse = _default_response;\n\t\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\t}\n\t\t\t\thouse = HOUSE_USSR;\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_DOG:\n\t\t\t\tresponse = _dog_response;\n\t\t\t\tsize = ARRAY_SIZE(_dog_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_EINSTEIN:\n\t\t\t\tresponse = _ein_response;\n\t\t\t\tsize = ARRAY_SIZE(_ein_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_RENOVATOR:\n\t\t\t\tresponse = _eng_response;\n\t\t\t\tsize = ARRAY_SIZE(_eng_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_SPY:\n\t\t\t\tresponse = _spy_response;\n\t\t\t\tsize = ARRAY_SIZE(_spy_response);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif(house == HOUSE_USSR) {\n\t\t\t\t\tresponse = _default_response;\n\t\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\t}\n#endif\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_MEDIC:\n\t\t\t\tresponse = _medic_response;\n\t\t\t\tsize = ARRAY_SIZE(_medic_response);\n\t\t\t\tbreak;\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tcase INFANTRY_MECHANIC:\n\t\t\t\tresponse = _mechanic;\n\t\t\t\tsize = ARRAY_SIZE(_mechanic);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_SHOCK:\n\t\t\t\tresponse = _shock;\n\t\t\t\tsize = ARRAY_SIZE(_shock);\n\t\t\t\tbreak;\n\n#endif\n\t\t\tcase INFANTRY_TANYA:\n\t\t\t\tresponse = _tanya_response;\n\t\t\t\tsize = ARRAY_SIZE(_tanya_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_THIEF:\n\t\t\t\tresponse = _thief_response;\n\t\t\t\tsize = ARRAY_SIZE(_thief_response);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tresponse = _default_response;\n\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\tbreak;\n\t\t}\n\t\tif (response != NULL) {\n\t\t\tSound_Effect(response[Sim_Random_Pick(0, size-1)], fixed(1), ID+1, 0, house);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Response_Attack -- Plays infantry audio response to attack order.            *\n *                                                                                             *\n *    When the player gives an infantry unit the order to attack, this routine handles         *\n *    the audio response by that unit.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/01/1995 JLB : Created.                                                                 *\n *   05/05/1995 JLB : Rambo response types added.                                              *\n *=============================================================================================*/\nvoid InfantryClass::Response_Attack(void)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!AllowVoice) return;\n\n\tif (Class->IsCivilian && *this != INFANTRY_EINSTEIN) {\n\t\tVocType response;\n\t\tif (Class->IsFemale) {\n\t\t\tresponse = VOC_GIRL_OKAY;\n\t\t} else {\n\t\t\tresponse = VOC_GUY_OKAY;\n\t\t}\n\t\tSound_Effect(response, fixed(1), ID+1);\n\n\t} else {\n\t\tstatic VocType _eng_response[] = {VOC_ENG_AFFIRM,VOC_ENG_AFFIRM};\n\t\tstatic VocType _dog_response[] = {VOC_DOG_GROWL2};\n\t\tstatic VocType _ein_response[] = {VOC_E_OK,VOC_E_YES};\n\t\tstatic VocType _spy_response[] = {VOC_SPY_ONWAY,VOC_SPY_KING,VOC_SPY_INDEED};\n\t\tstatic VocType _medic_response[] = {VOC_MED_AFFIRM,VOC_MED_MOVEOUT};\n#ifdef ENGLISH\n\t\tstatic VocType _tanya_response[] = {VOC_TANYA_CHEW,VOC_TANYA_CHING,VOC_TANYA_LAUGH};\n#else\n\t\tstatic VocType _tanya_response[] = {VOC_TANYA_CHEW,VOC_TANYA_CHING,VOC_TANYA_LAUGH,VOC_TANYA_ROCK};\n#endif\n\t\tstatic VocType _thief_response[] = {VOC_NONE};\n\t\tstatic VocType _default_response[] = {VOC_RIGHT_AWAY,VOC_AFFIRM,VOC_AFFIRM,VOC_UGOTIT,VOC_NO_PROB,VOC_YESSIR,VOC_YESSIR,VOC_YESSIR};\n\t\tstatic VocType _stavros[] = {VOC_STAVCRSE};\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tstatic VocType _mechanic[] = {VOC_MECHYEEHAW1,VOC_MECHHOTDIG1,VOC_MECHWRENCH1};\n\t\tstatic VocType _shock[] = {VOC_STLIGHT1,VOC_STBURN1,VOC_STCRISP1,VOC_STSHOCK1};\n#endif\n\n\t\tint size = 0;\n\t\tVocType * response = NULL;\n\t\tHousesType house = PlayerPtr->ActLike;\n\t\tswitch (Class->Type) {\n\t\t\tcase INFANTRY_GENERAL:\n\t\t\t\tif (house != HOUSE_USSR && house != HOUSE_BAD) {\n\t\t\t\t\tresponse = _stavros;\n\t\t\t\t\tsize = ARRAY_SIZE(_stavros);\n\t\t\t\t} else {\n\t\t\t\t\tresponse = _default_response;\n\t\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\t}\n\t\t\t\thouse = HOUSE_USSR;\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_DOG:\n\t\t\t\tresponse = _dog_response;\n\t\t\t\tsize = ARRAY_SIZE(_dog_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_SPY:\n\t\t\t\tresponse = _spy_response;\n\t\t\t\tsize = ARRAY_SIZE(_spy_response);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif(house == HOUSE_USSR) {\n\t\t\t\t\tresponse = _default_response;\n\t\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\t}\n#endif\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_EINSTEIN:\n\t\t\t\tresponse = _ein_response;\n\t\t\t\tsize = ARRAY_SIZE(_ein_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_RENOVATOR:\n\t\t\t\tresponse = _eng_response;\n\t\t\t\tsize = ARRAY_SIZE(_eng_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_MEDIC:\n\t\t\t\tresponse = _medic_response;\n\t\t\t\tsize = ARRAY_SIZE(_medic_response);\n\t\t\t\tbreak;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tcase INFANTRY_MECHANIC:\n\t\t\t\tresponse = _mechanic;\n\t\t\t\tsize = ARRAY_SIZE(_mechanic);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_SHOCK:\n\t\t\t\tresponse = _shock;\n\t\t\t\tsize = ARRAY_SIZE(_shock);\n\t\t\t\tbreak;\n#endif\n\t\t\tcase INFANTRY_TANYA:\n\t\t\t\tresponse = _tanya_response;\n\t\t\t\tsize = ARRAY_SIZE(_tanya_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_THIEF:\n\t\t\t\tresponse = _thief_response;\n\t\t\t\tsize = ARRAY_SIZE(_thief_response);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tresponse = _default_response;\n\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\tbreak;\n\t\t}\n\t\tif (response != NULL) {\n\t\t\tSound_Effect(response[Sim_Random_Pick(0, size-1)], fixed(1), ID+1, 0, house);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::What_Action -- Infantry units might be able to capture -- check.             *\n *                                                                                             *\n *    This routine checks to see if the infantry unit can capture the specified object rather  *\n *    than merely attacking it. If this is the case, then ACTION_CAPTURE will be returned.     *\n *                                                                                             *\n * INPUT:   object   -- The object that the mouse is currently over.                           *\n *                                                                                             *\n * OUTPUT:  Returns the action that will be performed if the mouse were clicked over the       *\n *          object specified.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/01/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType InfantryClass::What_Action(ObjectClass const * object) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\tassert(object != NULL);\n\n\tActionType action = FootClass::What_Action(object);\n\n\t/*\n\t** If this is an engineer/renovator, we have to make some adjustments.\n\t** If the cursor is over an enemy building, return action-none.  If it's\n\t** over a friendly building, we have to return action-capture so he can\n\t** renovate it.\n\t** However, abort the whole thing if the building is a barrel or mine.\n\t*/\n\tif (*this == INFANTRY_RENOVATOR && object->What_Am_I() == RTTI_BUILDING && House->IsPlayerControl) {\n\t\tBuildingClass const * bldg = (BuildingClass *)object;\n\t\tif (bldg->Class->IsRepairable) {\n\t\t\tif (House->Is_Ally(bldg)) {\n\t\t\t\tif (bldg->Health_Ratio() == 1) {\n\t\t\t\t\treturn(ACTION_NO_GREPAIR);\n\t\t\t\t}\n\t\t\t\treturn(ACTION_GREPAIR);\n\t\t\t} else {\n\n\t\t\t\tif (bldg->Class->IsCaptureable) {\n#ifdef FIXIT_ENGINEER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\tif (bldg->Health_Ratio() <= EngineerCaptureLevel) {\n#else\n\t\t\t\t\tif (bldg->Health_Ratio() <= Rule.ConditionRed) {\n#endif\n\t\t\t\t\t\treturn(ACTION_CAPTURE);\n\t\t\t\t\t}\n\t\t\t\t\treturn(ACTION_DAMAGE);\n\t\t\t\t}\n\n//\t\t\t\tif (bldg->Health_Ratio() <= Rule.ConditionRed && bldg->Class->IsCaptureable) {\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** If this is a medic, and the cursor's over a friendly infantryman,\n\t** execute an action-attack.  In CSII, if this is a mechanic and the\n\t** cursor's over a friendly vehicle, execute an action-attack.\n\t*/\n\tif (Combat_Damage() < 0 && House->IsPlayerControl) {\n\t\tif (House->Is_Ally(object)) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif( (object->What_Am_I() == RTTI_INFANTRY && object != this && *this == INFANTRY_MEDIC) ||\n\t\t\t    (*this == INFANTRY_MECHANIC && (object->What_Am_I() == RTTI_UNIT || object->What_Am_I() == RTTI_AIRCRAFT) ) ) {\n\n\t\t\t\t\tif (object->Health_Ratio() < Rule.ConditionGreen) {\n// If it's a mechanic force-moving into an APC, don't try to heal it.\n\t\t\t\t\t\tif(*this == INFANTRY_MECHANIC && object->What_Am_I() == RTTI_UNIT && *(UnitClass *)object == UNIT_APC && (Keyboard->Down(Options.KeyForceMove1) || Keyboard->Down(Options.KeyForceMove2)) ) {\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn(ACTION_HEAL);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t}\n#else\n\t\t\tif(object->What_Am_I() == RTTI_INFANTRY && object != this) {\n\t\t\t\tif (object->Health_Ratio() < Rule.ConditionGreen) {\n\t\t\t\t\treturn(ACTION_HEAL);\n\t\t\t\t}\n\t\t\t}\n#endif\n\t\t\tif(!object->Is_Techno() || !((TechnoClass *)object)->Techno_Type_Class()->Max_Passengers()) {\n\t\t\t\tif (action == ACTION_GUARD_AREA || action == ACTION_MOVE) {\n\t\t\t\t\treturn(action);\n\t\t\t\t}\n\t\t\t\treturn(ACTION_SELECT);\n\t\t\t}\n\t\t} else {\n\t\t\treturn(ACTION_NOMOVE);\n\t\t}\n\t}\n\n#ifdef OBSOLETE\n\t/*\n\t** See if it's a thief attacking an enemy vehicle, let him CAPTURE it.\n\t*/\n\tif (*this == INFANTRY_THIEF && object->What_Am_I() == RTTI_UNIT) {\n\t\tif (((UnitClass *)object)->House != House) {\n\t\t\treturn(ACTION_CAPTURE);\n\t\t}\n\t}\n#endif\n\n\t/*\n\t** Dogs can only attack infantrymen\n\t*/\n\tif (Class->IsDog && action == ACTION_ATTACK && object->What_Am_I() != RTTI_INFANTRY) {\n\t\taction = ACTION_NONE;\n\t}\n\n\t/*\n\t**\tSee if it's a commando, and if he's attacking a building,\n\t** have him return ACTION_SABOTAGE instead\n\t*/\n\tif (Class->IsBomber && action == ACTION_ATTACK && object->What_Am_I() == RTTI_BUILDING) {\n\t\tBuildingClass const * obj = (BuildingClass *)object;\n\t\t/*\n\t\t** Hack: Tanya should shoot barrels, bomb other structures.\n\t\t*/\n\t\tif (obj->Class->IsRepairable) {\n//\t\tif (*obj != STRUCT_BARREL && *obj != STRUCT_BARREL3) {\n\t\t\treturn(ACTION_SABOTAGE);\n\t\t} else {\n\t\t\treturn(ACTION_ATTACK);\n\t\t}\n\t}\n\n\t/*\n\t** See if this infantry is trying to move onto where a land mine is.\n\t*/\n\tif (action == ACTION_NONE && object->What_Am_I() == RTTI_BUILDING && House->IsPlayerControl) {\n\t\tStructType blah = *((BuildingClass *)object);\n\t\tif (blah == STRUCT_AVMINE || blah == STRUCT_APMINE) return(ACTION_MOVE);\n\t}\n\n\t/*\n\t**\tThere is no self-select action available for infantry types.\n\t*/\n\tif (action == ACTION_SELF) {\n\t\taction = ACTION_NONE;\n\t}\n\n\t/*\n\t**\tCheck to see if it can enter a transporter.\n\t*/\n\tif (\n\t\tHouse->Is_Ally(object) &&\n\t\tHouse->IsPlayerControl && object->Is_Techno()) {\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n if (object->What_Am_I() != RTTI_VESSEL || *(VesselClass *)object != VESSEL_CARRIER) {\n#endif\n\t\tswitch (((InfantryClass *)this)->Transmit_Message(RADIO_CAN_LOAD, (TechnoClass*)object)) {\n\t\t\tcase RADIO_ROGER:\n\t\t\t\taction = ACTION_ENTER;\n\t\t\t\tbreak;\n\n\t\t\tcase RADIO_NEGATIVE:\n\t\t\t\taction = ACTION_NO_ENTER;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n }\n#endif\n\t}\n\n\tif (Class->IsCapture && action == ACTION_ATTACK) {\n\t\tif (!House->Is_Ally(object) && (\n//Disable capturing of helicopters\t\t\t (object->What_Am_I() == RTTI_AIRCRAFT && ((AircraftClass *)object)->Pip_Count() == 0 && *((AircraftClass *)object) == AIRCRAFT_TRANSPORT) ||\n\t\t\t (object->What_Am_I() == RTTI_BUILDING && ((BuildingClass *)object)->Class->IsCaptureable) )\n\t\t\t) {\n\n\t\t\t\tif (*this == INFANTRY_THIEF && (object->What_Am_I() == RTTI_BUILDING && ((BuildingClass *)object)->Class->Capacity == 0)) {\n\t\t\t\t\taction = ACTION_NONE;\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If we're trying to capture a building, make sure we can get\n\t\t\t\t\t** to it.  Find an adjacent cell that's the same zone as us.\n\t\t\t\t\t** The target circumstance is a naval yard that doesn't touch\n\t\t\t\t\t** the shore - a total island.  In that case, we can't capture\n\t\t\t\t\t** it, so we shouldn't show the action-capture cursor.\n\t\t\t\t\t*/\n\t\t\t\t\taction = ACTION_CAPTURE;\n\t\t\t\t\tif (object->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\tCELL cell = ::As_Cell(object->As_Target());\n\t\t\t\t\t\tint targzone = Map[::As_Cell(As_Target())].Zones[Class->MZone];\n\t\t\t\t\t\tshort const *list = ((BuildingClass *)object)->Class->Occupy_List(false);\n\t\t\t\t\t\tbool found = false;\n\t\t\t\t\t\twhile (*list != REFRESH_EOL && !found) {\n\t\t\t\t\t\t\tCELL newcell = cell + *list++;\n\t\t\t\t\t\t\tfor (FacingType i=FACING_N; i < FACING_COUNT; i++) {\n\t\t\t\t\t\t\t\tif (Map[Adjacent_Cell(newcell, i)].Zones[Class->MZone] == targzone) {\n\t\t\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!found) {\n\t\t\t\t\t\t\taction = ACTION_NONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t} else {\n\t\t\tif (!Is_Weapon_Equipped()) {\n\t\t\t\taction = ACTION_NONE;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf it doesn't know what to do with the object, then just\n\t**\tsay it can't move there.\n\t*/\n\tif (action == ACTION_NONE) action = ACTION_NOMOVE;\n\n\treturn(action);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Active_Click_With -- Handles action when clicking with infantry soldier.     *\n *                                                                                             *\n *    This routine is called when the player clicks over an object while this infantry soldier *\n *    is selected. Capture attempts are prohibited if the infantry cannot capture. The         *\n *    command might respond if told to sabotage something.                                     *\n *                                                                                             *\n * INPUT:   action   -- The action that is nominally to be performed.                          *\n *                                                                                             *\n *          object   -- The object over which the mouse was clicked.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Active_Click_With(ActionType action, ObjectClass * object)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\taction = What_Action(object);\n\n\tswitch (action) {\n\t\tcase ACTION_GREPAIR:\n\t\tcase ACTION_DAMAGE:\n\t\tcase ACTION_CAPTURE:\n\t\t\taction = ACTION_CAPTURE;\n\t\t\tbreak;\n\n\t\tcase ACTION_HEAL:\n\t\t\taction = ACTION_ATTACK;\n\t\t\tbreak;\n\n//\t\tcase ACTION_ENTER:\n//\t\t\taction = ACTION_MOVE;\n//\t\t\tbreak;\n\n\t\tcase ACTION_SABOTAGE:\n\t\tcase ACTION_ATTACK:\n\t\tcase ACTION_GUARD_AREA:\n\t\tcase ACTION_MOVE:\n\t\t\taction = action;\n\t\t\tbreak;\n\n\t\tdefault:\n//\t\t\taction = ACTION_NONE;\n\t\t\tbreak;\n\t}\n\n\tFootClass::Active_Click_With(action, object);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Set_Occupy_Bit -- Sets the occupy bit cell and bit pos                       *\n *                                                                                             *\n * INPUT:      CELL      - the cell we are setting the bit in                                  *\n *                                                                                             *\n *               int      - the spot index we are setting the bit for                          *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/08/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Set_Occupy_Bit(CELL cell, int spot_index)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t** Set the occupy position for the spot that we passed in\n\t*/\n\tMap[cell].Flag.Composite |= (1 << spot_index);\n\n\t/*\n\t** Record the type of infantry that now owns the cell\n\t*/\n\tMap[cell].InfType = Owner();\n}\n\n\n/***************************************************************************\n * InfantryClass::Clear_Occupy_Bit -- Clears occupy bit and given cell\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/08/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid InfantryClass::Clear_Occupy_Bit(CELL cell, int spot_index)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t** Clear the occupy bit for the infantry in that cell\n\t*/\n\tMap[cell].Flag.Composite &= ~(1 << spot_index);\n\n\t/*\n\t** If he was the last infantry recorded in the cell then\n\t** remove the infantry ownership flag.\n\t*/\n\tif (!(Map[cell].Flag.Composite & 0x1F)) {\n\t\tMap[cell].InfType = HOUSE_NONE;\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Full_Name -- Fetches the full name of the infantry unit.                     *\n *                                                                                             *\n *    This routine will return with the full name (as a text number) for this infantry         *\n *    unit. Typically, this is the normal name, but in cases of civilian type survivors from   *\n *    a building explosion, it might be a technician instead. In such a case, the special      *\n *    technician name number is returned instead.                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the full name to use for this infantry unit.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/30/1995 JLB : Created.                                                                 *\n *   10/28/1996 JLB : Spy returns \"enemy soldier\" text name.                                   *\n *=============================================================================================*/\nint InfantryClass::Full_Name(void) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (IsTechnician) {\n\t\treturn(TXT_TECHNICIAN);\n\t}\n\n\tif (*this == INFANTRY_SPY && !House->IsPlayerControl) {\n\t\treturn(TXT_E1);\n\t}\n\n\treturn(Class->Full_Name());\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Mission_Attack -- Intercept attack mission for special handling.             *\n *                                                                                             *\n *    This routine intercepts the normal attack mission and if an engineer is detected and the *\n *    target is a building, then the engineer will be automatically assigned the capture       *\n *    mission. In other cases, the normal attack logic will proceed.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine again. *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/07/1995 JLB : Created.                                                                 *\n *   04/15/1996 BWG : Engineers can only attack their own house's buildings now.               *\n *   05/29/1996 JLB : Engineers can now damage/capture enemy buildings.                        *\n *=============================================================================================*/\nint InfantryClass::Mission_Attack(void)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsBomber && As_Building(TarCom)) {\n\t\tAssign_Destination(TarCom);\n\t\tAssign_Mission(MISSION_SABOTAGE);\n\t\treturn(1);\n\t}\n\n\tif (Class->IsCapture && As_Building(TarCom) != NULL) {\n\t\tAssign_Destination(TarCom);\n\t\tAssign_Mission(MISSION_CAPTURE);\n\t\treturn(1);\n\t}\n\n\treturn(FootClass::Mission_Attack());\n}\n\n\n/***********************************************************************************************\n * InfantryClass::What_Action -- Determines what action to perform for the cell specified.     *\n *                                                                                             *\n *    This routine will determine what action to perform if the mouse was clicked on the cell  *\n *    specified. This is just a courier function since the lower level classes actually        *\n *    perform the work. The need for this routine at this level is due to the existence of     *\n *    a similarly named function at this level as well.  C++ namespace rules require this      *\n *    function courier to be in place or an error will result.                                 *\n *                                                                                             *\n * INPUT:   cell  -- The cell that the mouse might be clicked upon.                            *\n *                                                                                             *\n * OUTPUT:  Returns with the action that would be given to this infantry unit if the mouse     *\n *          were clicked at the cell specified.                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType InfantryClass::What_Action(CELL cell) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tActionType action = FootClass::What_Action(cell);\n\n\t/*\n\t** Dogs can only attack infantrymen\n\t*/\n\tif (Class->IsDog && action == ACTION_ATTACK) {\n\t\taction = ACTION_NONE;\n\t}\n\n\t/*\n\t** If this is a medic, and the cursor's over a friendly infantryman,\n\t** execute an action-attack.\n\t*/\n\tif (Combat_Damage() < 0 && House->IsPlayerControl) {\n\t\tif (action == ACTION_ATTACK) {\n\t\t\taction = ACTION_NOMOVE;\n\t\t}\n\t}\n\n\t/*\n\t**\tDemolitioners may destroy a bridge\n\t*/\n\tif (Class->IsBomber && action == ACTION_MOVE && !Special.IsCaptureTheFlag) {\n\t\tswitch (Map[cell].TType) {\n\t\t\tcase TEMPLATE_BRIDGE1:\n\t\t\tcase TEMPLATE_BRIDGE2:\n\t\t\tcase TEMPLATE_BRIDGE1H:\n\t\t\tcase TEMPLATE_BRIDGE2H:\n\t\t\tcase TEMPLATE_BRIDGE_1A:\n\t\t\tcase TEMPLATE_BRIDGE_1B:\n\t\t\tcase TEMPLATE_BRIDGE_2A:\n\t\t\tcase TEMPLATE_BRIDGE_2B:\n//\t\t\tcase TEMPLATE_BRIDGE_3A:\n//\t\t\tcase TEMPLATE_BRIDGE_3B:\n\t\t\t\treturn(ACTION_SABOTAGE);\n\t\t}\n\t}\n\n#ifdef OBSOLETE\n\t/*\n\t** Engineers may repair a destroyed bridge.\n\t*/\n\tif (*this == INFANTRY_RENOVATOR && action == ACTION_NOMOVE) {\n\t\t/*\n\t\t** If they're pointing on the wrong side of the bridge, ignore it\n\t\t** 'cause we can't get there.\n\t\t*/\n\t\tTemplateType tt = Map[cell].TType;\n\t\tif (tt == TEMPLATE_BRIDGE1D || tt == TEMPLATE_BRIDGE2D ||\n\t\t\ttt == TEMPLATE_BRIDGE_1C || tt == TEMPLATE_BRIDGE_2C ||\n\t\t\t(tt >= TEMPLATE_BRIDGE_3C && tt <= TEMPLATE_BRIDGE_3E) ) {\n\t\t\t/*\n\t\t\t** We know they're pointing at a destroyed bridge cell.  If the cell\n\t\t\t** they're pointing at is surrounded by impassables, return this\n\t\t\t** cell as impassable.  But, if any cell surrounding this cell is\n\t\t\t** passable, return that this is a capturable cell.\n\t\t\t*/\n\t\t\tif (Map[cell].Land_Type() == LAND_ROCK) {\n\t\t\t\tif (tt == TEMPLATE_BRIDGE_3C) return(ACTION_CAPTURE);\n\n\t\t\t\tif (tt == TEMPLATE_BRIDGE_3C) return(ACTION_CAPTURE);\n\t\t\t\tint y = Cell_Y(cell);\n\t\t\t\tif (y) {\n\t\t\t\t\tLandType above = Map[(CELL)(cell-(MAP_CELL_W-1))].Land_Type();\n\t\t\t\t\tif (above == LAND_CLEAR || above == LAND_ROAD) {\n\t\t\t\t\t\tif (Map[(CELL)(cell-(MAP_CELL_W-1))].Zone == Map[As_Cell(As_Target())].Zone) {\n\t\t\t\t\t\t\treturn(ACTION_CAPTURE);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(ACTION_NOMOVE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (y < MAP_CELL_H) {\n\t\t\t\t\tLandType below = Map[(CELL)(cell + MAP_CELL_W-1)].Land_Type();\n\t\t\t\t\tif (below == LAND_CLEAR || below == LAND_ROAD) {\n\t\t\t\t\t\tif (Map[(CELL)(cell+MAP_CELL_W-1)].Zone == Map[As_Cell(As_Target())].Zone) {\n\t\t\t\t\t\t\treturn(ACTION_CAPTURE);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(ACTION_NOMOVE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn(ACTION_NOMOVE);\n\t\t}\n\t}\n#endif\n\treturn(action);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Class_Of -- Returns the class reference for this object.                     *\n *                                                                                             *\n *    This routine will return a reference to the infantry type class object that describes    *\n *    this infantry's characteristics.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the InfantryTypeClass object associated with this      *\n *          infantry object.                                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectTypeClass const & InfantryClass::Class_Of(void) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(*Class);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Read_INI -- Reads units from scenario INI file.                              *\n *                                                                                             *\n *    This routine is used to read all the starting units from the                             *\n *    scenario control INI file. The units are created and placed on the                       *\n *    map by this routine.                                                                     *\n *                                                                                             *\n *    INI entry format:                                                                        *\n *      Housename, Typename, Strength, Cellnum, CellSublocation, Missionname,                  *\n *         Facingnum, Triggername                                                              *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the loaded scenario INI file.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Read_INI(CCINIClass & ini)\n{\n\tInfantryClass\t* infantry;\t\t\t// Working infantry pointer.\n\tHousesType\t\tinhouse;\t\t\t// Infantry house.\n\tInfantryType\tclassid;\t\t\t// Infantry class.\n\tchar\t\t\t\tbuf[128];\n\tchar\t\t\t\t* validation;\n\tDirType \t\t\tdir;\n\tTriggerTypeClass\t* tp;\n\n\tint len = ini.Entry_Count(INI_Name());\n\tfor (int index = 0; index < len; index++) {\n\t\tchar const * entry = ini.Get_Entry(INI_Name(), index);\n\n\t\t/*\n\t\t**\tGet an infantry entry\n\t\t*/\n\t\tini.Get_String(INI_Name(), entry, NULL, buf, sizeof(buf));\n\n\t\t/*\n\t\t**\t1st token: house name.\n\t\t*/\n\t\tinhouse = HouseTypeClass::From_Name(strtok(buf, \",\\n\\r\"));\n\t\tif (inhouse != HOUSE_NONE) {\n\n\t\t\t/*\n\t\t\t**\t2nd token: infantry type name.\n\t\t\t*/\n\t\t\tclassid = InfantryTypeClass::From_Name(strtok(NULL, \",\\n\\r\"));\n\n\t\t\tif (classid != INFANTRY_NONE) {\n\n\t\t\t\tinfantry = new InfantryClass(classid, inhouse);\n\t\t\t\tif (infantry != NULL) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\t3rd token: strength.\n\t\t\t\t\t*/\n\t\t\t\t\tint strength = atoi(strtok(NULL, \",\\n\\r\"));\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\t4th token: cell #.\n\t\t\t\t\t*/\n\t\t\t\t\tCELL cell = atoi(strtok(NULL, \",\\n\\r\"));\n\t\t\t\t\tCOORDINATE coord = Cell_Coord(cell);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\t5th token: cell sub-location.\n\t\t\t\t\t*/\n\t\t\t\t\tint sub = atoi(strtok(NULL, \",\"));\n\t\t\t\t\tcoord = Coord_Add(Coord_Whole(coord), StoppingCoordAbs[ sub ]);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tFetch the mission and facing.\n\t\t\t\t\t*/\n\t\t\t\t\tMissionType mission = MissionClass::Mission_From_Name(strtok(NULL, \",\\n\\r\"));\n\t\t\t\t\tvalidation = strtok(NULL, \",\\n\\r\");\n\t\t\t\t\tif (validation) {\n\t\t\t\t\t\tdir = (DirType)atoi(validation);\n\t\t\t\t\t\tvalidation = strtok(NULL, \",\\n\\r\");\n\t\t\t\t\t\tif (validation) {\n\t\t\t\t\t\t\ttp = TriggerTypeClass::From_Name(validation);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttp = NULL;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdir = (DirType)0;\n\t\t\t\t\t\ttp = NULL;\n\t\t\t\t\t}\n\n\t\t\t\t\tinfantry->Trigger = NULL;\n\t\t\t\t\tif (tp != NULL) {\n\t\t\t\t\t\tTriggerClass * tt = Find_Or_Make(tp);\n\t\t\t\t\t\tif (tt != NULL) {\n\t\t\t\t\t\t\ttt->AttachCount++;\n\t\t\t\t\t\t\tinfantry->Trigger = tt;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (infantry->Unlimbo(coord, dir)) {\n\t\t\t\t\t\tinfantry->Strength = infantry->Class_Of().MaxStrength * fixed(strength, 256);\n\t\t\t\t\t\tif (infantry->Strength > infantry->Class->MaxStrength-3) infantry->Strength = infantry->Class->MaxStrength;\n//\t\t\t\t\t\tinfantry->Strength = Fixed_To_Cardinal(infantry->Class_Of().MaxStrength, strength);\n\t\t\t\t\t\tif (Session.Type == GAME_NORMAL || infantry->House->IsHuman) {\n\t\t\t\t\t\t\tinfantry->Assign_Mission(mission);\n\t\t\t\t\t\t\tinfantry->Commence();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinfantry->Enter_Idle_Mode();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf the infantry could not be unlimboed, then this is a big error.\n\t\t\t\t\t\t**\tDelete the infantry.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tdelete infantry;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Write_INI -- Store the infantry to the INI database.                         *\n *                                                                                             *\n *    This will store all the infantry objects to the INI database specified.                  *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to store the infantry data to.              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Write_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tFirst, clear out all existing infantry data from the ini file.\n\t*/\n\tini.Clear(INI_Name());\n\n\t/*\n\t**\tWrite the infantry data out.\n\t*/\n\tfor (int index = 0; index < Infantry.Count(); index++) {\n\t\tInfantryClass * infantry = Infantry.Ptr(index);\n\t\tif (!infantry->IsInLimbo) {\n\t\t\tchar\tuname[10];\n\t\t\tchar\tbuf[128];\n\n\t\t\tsprintf(uname, \"%d\", index);\n\t\t\tsprintf(buf, \"%s,%s,%d,%u,%d,%s,%d,%s\",\n\t\t\t\t\tinfantry->House->Class->IniName,\n\t\t\t\t\tinfantry->Class->IniName,\n\t\t\t\t\tinfantry->Health_Ratio()*256,\n\t\t\t\t\tCoord_Cell(infantry->Coord),\n\t\t\t\t\tCellClass::Spot_Index(infantry->Coord),\n\t\t\t\t\tMissionClass::Mission_Name((infantry->Mission == MISSION_NONE) ?\n\t\t\t\t\t\tinfantry->MissionQueue : infantry->Mission),\n\t\t\t\t\tinfantry->PrimaryFacing.Current(),\n\t\t\t\t\tinfantry->Trigger.Is_Valid() ? infantry->Trigger->Class->IniName : \"None\"\n\t\t\t\t);\n\t\t\tini.Put_String(INI_Name(), uname, buf);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Fear_AI -- Process any fear related affects on this infantry.                *\n *                                                                                             *\n *    Use this routine to handle the fear logic for this infantry. It will slowly increase     *\n *    the bravery of the infantry as well as cause it to stand up or lie down as appropriate.  *\n *    It will even handle the special fraidy cat logic for civilian infantry.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this once per game logic loop per infantry unit.                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Fear_AI(void)\n{\n\t/*\n\t**\tAfter a time, the infantry will gain courage.\n\t*/\n\tif (Fear > 0) {\n\n\t\tFear--;\n\n\t\t/*\n\t\t**\tWhen an armed civilian becomes unafraid, he will then reload\n\t\t**\tanother clip into his pistol.\n\t\t*/\n\t\tif (Fear == 0 && Ammo == 0 && Is_Weapon_Equipped()) {\n\t\t\tAmmo = Class->MaxAmmo;\n\t\t}\n\n\t\t/*\n\t\t**\tStand up if brave and lie down if afraid.\n\t\t*/\n\t\tif (IsProne) {\n\t\t\tif (Fear < FEAR_ANXIOUS) {\n\t\t\t\tDo_Action(DO_GET_UP);\n\t\t\t}\n\t\t} else  {\n\n\t\t\t/*\n\t\t\t**\tDrop to the ground if anxious. Don't drop to the ground while moving\n\t\t\t**\tand the special elite flag is active.\n\t\t\t*/\n\t\t\tif (!Class->IsDog && Height == 0 && Fear >= FEAR_ANXIOUS && ((!Target_Legal(NavCom) && !IsDriving))) {\n\t\t\t\tDo_Action(DO_LIE_DOWN);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tWhen in darkness or in doubt,\n\t**\t\trun in circles, scream, and shout.\n\t*/\n\tif (Class->IsFraidyCat && Fear > FEAR_ANXIOUS && !IsFalling && !IsDriving && !Target_Legal(NavCom)) {\n\t\tScatter(0, true);\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Edge_Of_World_AI -- Detects when infantry has left the map.                  *\n *                                                                                             *\n *    This routine will detect when the infantry has left the edge of the world and will       *\n *    delete it as necessary.                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the infantry unit deleted by this routine?                               *\n *                                                                                             *\n * WARNINGS:   Be sure the check the return value and if true, abort any further processing    *\n *             for this infantry unit.                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryClass::Edge_Of_World_AI(void)\n{\n\t/*\n\t**\tDelete this unit if it finds itself off the edge of the map and it is in\n\t**\tguard or other static mission mode.\n\t*/\n\tif (Team.Is_Valid() && IsLocked) Team->IsLeaveMap = true;\n\n\tif (!Team.Is_Valid() && Mission == MISSION_GUARD && !Map.In_Radar(Coord_Cell(Coord))) {\n\t\tStun();\n\t\tdelete this;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Firing_AI -- Handles firing and combat AI for the infantry.                  *\n *                                                                                             *\n *    This will examine the infantry and determine what firing action is required. It will     *\n *    search for targets, starting firing animations, and launch bullets as necessary.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per infantry per game logic loop.                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Firing_AI(void)\n{\n\tif (Target_Legal(TarCom)) {\n\t\tint primary = What_Weapon_Should_I_Use(TarCom);\n\n\t\tif (!IsFiring) {\n\t\t\tswitch (Can_Fire(TarCom, primary)) {\n\t\t\t\tcase FIRE_ILLEGAL:\n\t\t\t\t\tif (Combat_Damage(primary) < 0) {\n\t\t\t\t\t\tObjectClass * targ= As_Object(TarCom);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\tif (targ) {\n\t\t\t\t\t\t\tif( (targ->What_Am_I() == RTTI_INFANTRY && *this == INFANTRY_MEDIC) ||\n\t\t\t\t\t\t\t\t (*this == INFANTRY_MECHANIC && (targ->What_Am_I() == RTTI_AIRCRAFT || targ->What_Am_I() == RTTI_UNIT )) ) {\n\n\t\t\t\t\t\t\t\t\tif (targ->Health_Ratio() >= Rule.ConditionGreen) {\n\t\t\t\t\t\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\t\t}\n#else\n\t\t\t\t\t\tif (targ && targ->What_Am_I() == RTTI_INFANTRY) {\n\t\t\t\t\t\t\tif (targ->Health_Ratio() >= Rule.ConditionGreen) {\n\t\t\t\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase FIRE_CLOAKED:\n\t\t\t\t\tDo_Uncloak();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase FIRE_OK:\n\t\t\t\t\t/*\n\t\t\t\t\t**\tStart firing animation.\n\t\t\t\t\t*/\n\t\t\t\t\tif (IsProne) {\n\t\t\t\t\t\tDo_Action(DO_FIRE_PRONE);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tDo_Action(DO_FIRE_WEAPON);\n\t\t\t\t\t}\n\n\t\t\t\t\tMark(MARK_OVERLAP_UP);\n\t\t\t\t\tIsFiring = true;\n\t\t\t\t\tMark(MARK_OVERLAP_DOWN);\n\n\t\t\t\t\tPrimaryFacing.Set(Direction8(Center_Coord(), As_Coord(TarCom)));\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the target is in range, and the NavCom is the same, then just\n\t\t\t\t\t**\tstop and keep firing.\n\t\t\t\t\t*/\n\t\t\t\t\tif (TarCom == NavCom) {\n\t\t\t\t\t\tNavCom = TARGET_NONE;\n\t\t\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf in the middle of firing animation, then only\n\t\t**\tprocess that. Infantry cannot fire and move simultaneously.\n\t\t**\tAt some point in the firing animation process, a projectile\n\t\t**\twill be launched. When the required animation frames have\n\t\t**\tbeen completed, the firing animation stops.\n\t\t*/\n\t\tint firestage = Class->FireLaunch;\n\t\tif (IsProne) firestage = Class->ProneLaunch;\n\n\t\tif (IsFiring && Fetch_Stage() == firestage) {\n\t\t\tFire_At(TarCom, primary);\n\n\t\t\t/*\n\t\t\t**\tRun away from slowly approaching projectiles.\n\t\t\t*/\n\t\t\tif (Class->PrimaryWeapon->MaxSpeed < Rule.Incoming) {\n\t\t\t\tMap[::As_Cell(TarCom)].Incoming(Coord, true);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If it's a dog, get rid of him (he'll be re-created when he hits)\n\t\t\t*/\n\t\t\tif (Class->IsDog) {\n\t\t\t\tWasSelected = IsSelected;\n\t\t\t\tScenarioInit++;\n\t\t\t\tLimbo();\n\t\t\t\tScenarioInit--;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (IsFiring) {\n\t\t\tMark(MARK_OVERLAP_UP);\n\t\t\tIsFiring = false;\n\t\t\tMark(MARK_OVERLAP_DOWN);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Doing_AI -- Handles the animation AI processing.                             *\n *                                                                                             *\n *    Infantry can be in one of many different animation sequences. At the conclusion of each  *\n *    sequence, the infantry will quite likely transition to a new animation state. This       *\n *    routine handles detecting when that trasition should occur and starting the infantry     *\n *    into its new state.                                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per infantry unit per game logic loop.              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Doing_AI(void)\n{\n\tif (Doing == DO_NOTHING || Fetch_Stage() >= Class->DoControls[Doing].Count) {\n\t\tswitch (Doing) {\n\t\t\tdefault:\n\t\t\t\tif (IsDriving) {\n\t\t\t\t\tif (Class->IsDog) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDog crawl animation is actually the run animation.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (Target_Legal(TarCom)) {\n\t\t\t\t\t\t\tDo_Action(DO_CRAWL, true);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tDo_Action(DO_WALK, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (IsProne) {\n\t\t\t\t\t\t\tDo_Action(DO_CRAWL, true);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tDo_Action(DO_WALK, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (Class->IsDog) {\n\t\t\t\t\t\tDo_Action(DO_STAND_READY, true);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (IsProne) {\n\t\t\t\t\t\t\tDo_Action(DO_PRONE, true);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tDo_Action(DO_STAND_READY, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase DO_DOG_MAUL:\n\t\t\t\tDo_Action(DO_STAND_READY, true);\n\t\t\t\tbreak;\n\n\t\t\tcase DO_GUN_DEATH:\n\t\t\tcase DO_EXPLOSION_DEATH:\n\t\t\tcase DO_EXPLOSION2_DEATH:\n\t\t\tcase DO_GRENADE_DEATH:\n\t\t\tcase DO_FIRE_DEATH:\n\t\t\t\tif (Fetch_Stage() >= Class->DoControls[Doing].Count) {\n\t\t\t\t\tif (Doing == DO_GUN_DEATH && !Class->IsDog && Height==0) {\n\t\t\t\t\t\tnew AnimClass(ANIM_CORPSE1, Coord_Add(Center_Coord(), XYP_Coord(-2, 4)));\n\t\t\t\t\t}\n\t\t\t\t\tif (Doing == DO_GRENADE_DEATH && !Class->IsDog && Height==0) {\n\t\t\t\t\t\tnew AnimClass(ANIM_CORPSE1, Coord_Add(Center_Coord(), XYP_Coord(-10, 3)));\n\t\t\t\t\t}\n\t\t\t\t\tif (Doing == DO_EXPLOSION_DEATH && !Class->IsDog && Height==0) {\n\t\t\t\t\t\tnew AnimClass(ANIM_CORPSE3, Coord_Add(Center_Coord(), XYP_Coord(-2, 4)));\n\t\t\t\t\t}\n\t\t\t\t\tif (Doing == DO_EXPLOSION2_DEATH && !Class->IsDog && Height==0) {\n\t\t\t\t\t\tnew AnimClass(ANIM_CORPSE2, Center_Coord());\n\t\t\t\t\t}\n\t\t\t\t\tdelete this;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Movement_AI -- This routine handles all infantry movement logic.             *\n *                                                                                             *\n *    It examines the infantry state and determines what movement action should be initiated   *\n *    or processed. It handles the actual movement of the infantry as well as any path finding *\n *    or infantry startup logic.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per infantry unit per game logic loop.              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Movement_AI(void)\n{\n\t/*\n\t**\tSpecial hack check to ensure that infantry will never get stuck in a movement order if\n\t**\tthere is no place to go.\n\t*/\n\tif (Mission == MISSION_MOVE && !Target_Legal(NavCom)) {\n\t\tEnter_Idle_Mode();\n\t}\n\n\tif (!IsFiring && !IsFalling && Doing != DO_DOG_MAUL) {\n\t\tif (!IsDriving) {\n\n\t\t\t/*\n\t\t\t**\tWhen in guard mode, never allow a valid navcom.\n\t\t\t*/\n\t\t\tif (Mission == MISSION_GUARD && MissionQueue == MISSION_NONE && Target_Legal(NavCom)) {\n\t\t\t\tAssign_Destination(TARGET_NONE);\n//\t\t\t\tif (IsTethered) Scatter(0, true);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDouble check to make sure it doesn't have a movement destination into a zone\n\t\t\t**\tthat it can't travel to. In such a case, abort the movement process by clearing\n\t\t\t**\tthe navigation computer.\n\t\t\t*/\n\t\t\tif ((!IsZoneCheat || Can_Enter_Cell(Coord_Cell(Coord)) != MOVE_NO) && !IsDriving && !IsTethered && Target_Legal(NavCom) && IsLocked && Map[Coord].Zones[Class->MZone] != Map[As_Cell(NavCom)].Zones[Class->MZone]) {\n// hack: if it's tanya, spy, or engineer, let 'em move there anyway.\n\t\t\t\tif (!Class->IsCapture && Mission != MISSION_ENTER) {\n//\t\t\t\tif (*this != INFANTRY_TANYA && *this != INFANTRY_SPY && *this != INFANTRY_RENOVATOR) {\n\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tA head to coordinate is needed. If there is no path\n\t\t\t**\tavailable, then create one.\n\t\t\t*/\n\t\t\tif (Target_Legal(NavCom) && Strength && Mission != MISSION_GUARD) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDetermine if the next cell in the list is available\n\t\t\t\t**\tto be entered. If not, then abort the path and try\n\t\t\t\t**\tagain.\n\t\t\t\t*/\n\t\t\t\tif (Path[0] != FACING_NONE && Can_Enter_Cell(Adjacent_Cell(Coord_Cell(Center_Coord()), Path[0])) != MOVE_OK) {\n\t\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tCheck to see if the target is closer than expected. This occurs\n\t\t\t\t**\twhen heading toward a moving object and that object is heading\n\t\t\t\t**\ttoward the unit. Shorten the precalculated path to be no longer\n\t\t\t\t**\tthan the distance to the target.\n\t\t\t\t*/\n\t\t\t\tint d = Lepton_To_Cell(Distance(NavCom));\n\t\t\t\tif (d < CONQUER_PATH_MAX) {\n\t\t\t\t\tPath[d] = FACING_NONE;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tFind a path to follow if one isn't already calculated.\n\t\t\t\t*/\n\t\t\t\tif (Path[0] == FACING_NONE) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCalculate the path from the current location to the\n\t\t\t\t\t**\tdestination indicated by the navigation computer. If there\n\t\t\t\t\t**\twas a fundamental error with finding a path, then this\n\t\t\t\t\t**\tindicates that basic path & movement logic needs to be\n\t\t\t\t\t**\taborted.\n\t\t\t\t\t*/\n\t\t\t\t\tif (PathDelay != 0) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!Basic_Path()) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tCheck to ensure that if a computer controlled unit is in\n\t\t\t\t\t\t**\thunt mode, but cannot reach the target it would like to,\n\t\t\t\t\t\t**\tabort the target tracking and let the normal hunt logic\n\t\t\t\t\t\t**\tassign a new one.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (!House->IsHuman && Mission == MISSION_HUNT) {\n\t\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf the infantry unit is close enough to the target, then\n\t\t\t\t\t\t\t**\ttell it to stop.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Distance(NavCom) < Rule.CloseEnoughDistance && !IsTethered) {\n\t\t\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t**\tUpdate the try try again counter so that this\n\t\t\t\t\t\t\t\t**\tinfantry unit will try again at a later time.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tif (TryTryAgain) {\n\t\t\t\t\t\t\t\t\tTryTryAgain--;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tif (IsNewNavCom) Sound_Effect(VOC_SCOLD);\n\t\t\t\t\t\t\t\t\tIsNewNavCom = false;\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t**\tAbort the target and destination process since the path\n\t\t\t\t\t\t\t\t\t**\tcould not be found. In such a case, processing should stop\n\t\t\t\t\t\t\t\t\t**\tor else the game will bog down with repeated path failures.\n\t\t\t\t\t\t\t\t\t**\tOnly perform the abort of the target is in a different zone.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tif ((!IsZoneCheat || Can_Enter_Cell(Coord_Cell(Coord)) != MOVE_NO) && IsLocked && Target_Legal(NavCom) && Map[As_Cell(NavCom)].Zones[Class->MZone] != Map[Coord].Zones[Class->MZone]) {\n\t\t\t\t\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (IsLocked && Target_Legal(TarCom) && Map[As_Cell(TarCom)].Zones[Class->MZone] != Map[Coord].Zones[Class->MZone]) {\n\t\t\t\t\t\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tStop_Driver();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tTryTryAgain = PATH_RETRY;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tDetermine the coordinate to head to based on the infantry's\n\t\t\t\t**\tcurrent location and the next location in the path.\n\t\t\t\t*/\n\t\t\t\tCOORDINATE acoord = Adjacent_Cell(Coord, Path[0]);\n\t\t\t\tCELL acell = Coord_Cell(acoord);\n\n\t\t\t\tif (Can_Enter_Cell(acell) != MOVE_OK) {\n\n\t\t\t\t\tif ((Mission == MISSION_MOVE || Mission == MISSION_ENTER) && !IsTethered /*&& House->IsHuman*/ && Distance(NavCom) < Rule.CloseEnoughDistance) {\n\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** If blocked by a moving block then just exit start of move and\n\t\t\t\t\t\t** try again next tick.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (Can_Enter_Cell(acell) == MOVE_DESTROYABLE) {\n\t\t\t\t\t\t\tif (Map[acell].Cell_Object()) {\n\t\t\t\t\t\t\t\tif (!House->Is_Ally(Map[acell].Cell_Object())) {\n\t\t\t\t\t\t\t\t\tOverride_Mission(MISSION_ATTACK, Map[acell].Cell_Object()->As_Target(), TARGET_NONE);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (Map[acell].Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(Map[acell].Overlay).IsWall) {\n\t\t\t\t\t\t\t\t\tOverride_Mission(MISSION_ATTACK, ::As_Target(acell), TARGET_NONE);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t\t\tStop_Driver();\n\t\t\t\t\tif (IsNewNavCom) Sound_Effect(VOC_SCOLD);\n\t\t\t\t\tIsNewNavCom = false;\n\n\t\t\t\t} else {\n\t\t\t\t\tif (Start_Driver(acoord)) {\n\t\t\t\t\t\tif (!IsActive) return;\n\t\t\t\t\t\tPrimaryFacing.Set(Direction8(Center_Coord(), Head_To_Coord()));\n\t\t\t\t\t\tif (IsFormationMove) {\n\t\t\t\t\t\t\tSet_Speed(Ground[Map[Coord].Land_Type()].Cost[FormationSpeed] * 256);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSet_Speed(0xFF);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (Class->IsDog) {\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tDog crawl animation is actually the run animation.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Target_Legal(TarCom)) {\n\t\t\t\t\t\t\t\tDo_Action(DO_CRAWL);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tDo_Action(DO_WALK);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (IsProne) {\n\t\t\t\t\t\t\t\tDo_Action(DO_CRAWL);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tDo_Action(DO_WALK);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tThe infantry knows where it should be headed, so head there. Check\n\t\t\t**\tto see if the infantry is \"close enough\" to the desired location that\n\t\t\t**\tit should just consider itself to have arrived. In this case, force\n\t\t\t**\tthe infantry to the destination location and mark this path step\n\t\t\t**\tas complete.\n\t\t\t*/\n\t\t\tMark(MARK_UP);\n\t\t\tif (Distance(Head_To_Coord()) < 0x0010) {\n\n\t\t\t\tmemcpy(&Path[0], &Path[1], sizeof(Path)-sizeof(Path[0]));\n\t\t\t\tPath[(sizeof(Path)/sizeof(Path[0]))-1] = FACING_NONE;\n\t\t\t\tCoord = Head_To_Coord();\n\t\t\t\tPer_Cell_Process(PCP_END);\n\t\t\t\tif (!IsActive || IsInLimbo) return;\n\n\t\t\t\tStop_Driver();\n\t\t\t\tif (!IsActive || IsInLimbo) return;\n\n\t\t\t\tif (Coord_Cell(Coord) == As_Cell(NavCom)) {\n\t\t\t\t\tNavCom = TARGET_NONE;\n\t\t\t\t\tif (Mission == MISSION_MOVE) {\n\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t}\n\t\t\t\t\t//Stop_Driver();\n\t\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tint\tmovespeed = Speed;\n\n\t\t\t\t/*\n\t\t\t\t**\tWhen prone, the infantry moves at half speed or double\n\t\t\t\t**\tspeed. This depends on whether the infantry actually has\n\t\t\t\t**\tprone animation stages. Civilians don't, and so they\n\t\t\t\t**\trun instead.\n\t\t\t\t*/\n\t\t\t\tif (Class->IsDog && Target_Legal(TarCom)) {\n\t\t\t\t\tmovespeed *= 2;\n\t\t\t\t}\n\n\t\t\t\tif (IsProne && !Class->IsDog) {\n\t\t\t\t\tif ((Class->IsFraidyCat && !Class->IsCrawling) ) {\n\t\t\t\t\t\tmovespeed = Speed*2;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmovespeed = Speed/2;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (IsTethered) {\n\t\t\t\t\tTransmit_Message(RADIO_REDRAW);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAdvance the infantry as far as it should go.\n\t\t\t\t*/\n\t\t\t\tMPHType maxspeed = MPHType(min(Class->MaxSpeed * SpeedBias * House->GroundspeedBias, MPH_LIGHT_SPEED));\n\n\t\t\t\tif (IsFormationMove) maxspeed = FormationMaxSpeed;\n\n\t\t\t\tCoord = Coord_Move(Coord, Direction(Head_To_Coord()), maxspeed * fixed(movespeed, 256));\n\t\t\t}\n\t\t\tMark(MARK_DOWN);\n\t\t}\n\t\tIsNewNavCom = false;\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Get_Image_Data -- Fetches the image data for this infantry unit.             *\n *                                                                                             *\n *    The image data for the infantry differs from normal if this is a spy. A spy always       *\n *    appears like a minigunner to the non-owning players.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the image data to use for this infantry soldier.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid const * InfantryClass::Get_Image_Data(void) const\n{\n\tif (!IsOwnedByPlayer && *this == INFANTRY_SPY) {\n\t\treturn(MFCD::Retrieve(\"E1.SHP\"));\n\t}\n\treturn(TechnoClass::Get_Image_Data());\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Is_Ready_To_Random_Anima -- Checks to see if it is ready to perform an idle  *\n *                                                                                             *\n *    This routine will examine this infantry and determine if it is allowed and ready to      *\n *    perform an idle animation. The conditions under which idle animations can be performed   *\n *    are restrictive. Hence this routine.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is this infantry ready to do an idle animation?                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryClass::Is_Ready_To_Random_Animate(void) const\n{\n\t/*\n\t**\tSee if the base classes (more rudimentary checking) determines that idle animations\n\t**\tcannot occur. If they cannot, then return with the failure code.\n\t*/\n\tif (!FootClass::Is_Ready_To_Random_Animate()) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tWhile the infantry is in the air (such as when paradropping), it won't be allowed\n\t**\tto idle animate.\n\t*/\n\tif (Height > 0) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tWhen the infantry is walking or otherwise engauged in travel, it won't idle animate.\n\t*/\n\tif (IsDriving) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tWhen prone, idle animations cannot occur. This is primarily because there are no prone\n\t**\tidle animations.\n\t*/\n\tif (IsProne) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tWhen firing, the infantry should not perform any idle animations.\n\t*/\n\tif (IsFiring) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tOnly if the infantry is in guard or ready stance is idle animations allowed. This is\n\t**\tbecause the idle animations start and end with these frames.\n\t*/\n\tif (Doing != DO_STAND_GUARD && Doing != DO_STAND_READY) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tSince no reason was found to indicate it is not a good time to idle\n\t**\tanimate, then it must be a good time to do so.\n\t*/\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Paradrop -- Handles paradropping infantry.                                   *\n *                                                                                             *\n *    This routine will paradrop this soldier at the location specified. It will cause the     *\n *    soldier to hunt if controlled by the computer and to guard if controlledy by the         *\n *    human.                                                                                   *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to paradrop the soldier to.                                *\n *                                                                                             *\n * OUTPUT:  bool; Was the paradrop successful?                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryClass::Paradrop(COORDINATE coord)\n{\n\tif (FootClass::Paradrop(coord)) {\n\t\tif (House->IsHuman) {\n\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t} else {\n\t\t\tAssign_Mission(MISSION_HUNT);\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "CODE/INFANTRY.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/INFANTRY.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INFANTRY.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 15, 1994                                              *\n *                                                                                             *\n *                  Last Update : August 15, 1994   [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef INFANTRY_H\n#define INFANTRY_H\n\n\nclass InfantryClass : public FootClass\n{\n\tpublic:\n\t\tCCPtr<InfantryTypeClass> Class;\n\n\t\t/*\n\t\t**\tIf the infantry is undergoing some choreographed animation sequence, then\n\t\t**\tthis holds the particular sequence number. The frame of animation is kept\n\t\t**\ttrack of by the regular frame tracking system. When performing an animation\n\t\t**\tsequence, the infantry cannot perform anything else (even move).\n\t\t*/\n\t\tDoType Doing;\n\n\t\t/*\n\t\t**\tCertain infantry will either perform some comment or say something after an\n\t\t**\tamount of time has expired subsequent to an significant event. This is the\n\t\t**\ttimer the counts down.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> Comment;\n\n\t\t/*\n\t\t**\tIf this civilian is actually a technician, then this flag will be true.\n\t\t**\tIt should only be set for the civilian type infantry. Typically, the\n\t\t**\ttechnician appears after a building is destroyed.\n\t\t*/\n\t\tunsigned IsTechnician:1;\n\n\t\t/*\n\t\t**\tIf the infantry just performed some feat, then it may respond with an action.\n\t\t**\tThis flag will be true if an action is to be performed when the Comment timer\n\t\t**\thas expired.\n\t\t*/\n\t\tunsigned IsStoked:1;\n\n\t\t/*\n\t\t**\tThis flag indicates if the infantry unit is prone. Prone infantry become that way\n\t\t**\twhen they are fired upon. Infantry in the prone position are less vulnerable to\n\t\t**\tcombat.\n\t\t*/\n\t\tunsigned IsProne:1;\n\n\t\t/*\n\t\t**\tIf the infantry is allowed to move one cell from one zone to another, then this\n\t\t**\tflag will be true. It exists only so that when a bridge is destroyed, the bomb\n\t\t**\tplacer is allowed to run from the destroyed bridge cell back onto a real cell.\n\t\t*/\n\t\tunsigned IsZoneCheat:1;\n\n\t\t/*\n\t\t** This flag is set for the dogs, when they launch into bullet mode.\n\t\t** it's to remember if the unit was selected, and if it was, then\n\t\t** when the dog is re-enabled, he'll reselect himself.\n\t\t*/\n\t\tunsigned WasSelected:1;\n\n\t\t/*\n\t\t**\tThe fear rating of this infantry unit. The more afraid the infantry, the more\n\t\t**\tlikely it is to panic and seek cover.\n\t\t*/\n\t\tFearType Fear;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\t\tInfantryClass(InfantryType classid, HousesType house);\n\t\tInfantryClass(NoInitClass const & x) : FootClass(x), Class(x), Comment(x) {};\n\t\tvirtual ~InfantryClass(void);\n\t\toperator InfantryType(void) const {return Class->Type;};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tstatic void Init(void);\n\n\t\tvirtual void Assign_Destination(TARGET);\n\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tvirtual bool Is_Ready_To_Random_Animate(void) const;\n\t\tvoid const * Get_Image_Data(void) const;\n\t\tint Shape_Number(void) const;\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const;\n\t\tvirtual int Full_Name(void) const;\n\n\t\t/*\n\t\t**\tObject entry and exit from the game system.\n\t\t*/\n\t\tvirtual bool Unlimbo(COORDINATE coord, DirType facing);\n\t\tvirtual bool Paradrop(COORDINATE coord);\n\t\tvirtual bool Limbo(void);\n\t\tvirtual void Detach(TARGET target, bool all);\n\n\t\t/*\n\t\t**\tDisplay and rendering support functionality. Supports imagery and how\n\t\t**\tobject interacts with the map and thus indirectly controls rendering.\n\t\t*/\n\t\tvirtual short const * Overlap_List(bool redraw = false) const;\n\t\tvirtual void Draw_It(int x, int y, WindowNumberType window) const;\n\n\t\t/*\n\t\t**\tUser I/O.\n\t\t*/\n\t\tvirtual void Response_Select(void);\n\t\tvirtual void Response_Move(void);\n\t\tvirtual void Response_Attack(void);\n\t\tvirtual void Active_Click_With(ActionType action, ObjectClass * object);\n\t\tvirtual void Active_Click_With(ActionType action, CELL cell) {FootClass::Active_Click_With(action, cell);}\n\n\t\t/*\n\t\t**\tCombat related.\n\t\t*/\n\t\tvirtual ActionType What_Action(ObjectClass const * object) const;\n\t\tvirtual ActionType What_Action(CELL cell) const;\n\t\tvirtual BulletClass * Fire_At(TARGET target, int which);\n\t\tvirtual ResultType Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source=0, bool forced=false);\n\t\tvirtual FireErrorType Can_Fire(TARGET target, int which) const;\n\t\tvirtual void Assign_Target(TARGET);\n\t\tvoid Set_Occupy_Bit(COORDINATE coord) {Set_Occupy_Bit(Coord_Cell(coord), CellClass::Spot_Index(coord));};\n\t\tvoid Set_Occupy_Bit(CELL cell, int spot_index);\n\t\tvoid Clear_Occupy_Bit(COORDINATE coord) {Clear_Occupy_Bit(Coord_Cell(coord), CellClass::Spot_Index(coord));};\n\t\tvoid Clear_Occupy_Bit(CELL cell, int spot_index);\n\n\t\t/*\n\t\t**\tDriver control support functions. These are used to control cell\n\t\t**\toccupation flags and driver instructions.\n\t\t*/\n\t\tvirtual bool Stop_Driver(void);\n\t\tvirtual bool Start_Driver(COORDINATE & coord);\n\n\t\t/*\n\t\t**\tAI.\n\t\t*/\n\t\tvirtual void AI(void);\n\t\tvoid Fear_AI(void);\n\t\tvirtual TARGET Greatest_Threat(ThreatType threat) const;\n\t\tvirtual int Mission_Attack(void);\n\t\tbool Edge_Of_World_AI(void);\n\t\tvoid Firing_AI(void);\n\t\tvoid Doing_AI(void);\n\t\tvoid Movement_AI(void);\n\n\t\t/*\n\t\t**\tScenario and debug support.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tstatic void Read_INI(CCINIClass & ini);\n\t\tstatic void Write_INI(CCINIClass & ini);\n\t\tstatic char *INI_Name(void) {return \"INFANTRY\";};\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\n\t\t/*\n\t\t**\tMovement and animation.\n\t\t*/\n\t\tvirtual bool Do_Action(DoType todo, bool force=false);\n\t\tvirtual bool Random_Animate(void);\n\t\tvirtual MoveType Can_Enter_Cell(CELL , FacingType =FACING_NONE) const;\n\t\tvirtual void Per_Cell_Process(PCPType why);\n\t\tvirtual void Enter_Idle_Mode(bool initial=false);\n\t\tvirtual void Scatter(COORDINATE threat, bool forced=false, bool nokidding=false);\n\n\t\t/*\n\t\t**\tTranslation table to convert facing into infantry shape number. This special\n\t\t**\ttable is needed since several facing stages are reused and flipped about the Y\n\t\t**\taxis.\n\t\t*/\n\t\tstatic int const HumanShape[32];\n\n\tprivate:\n\n\t\tstatic DoStruct const MasterDoControls[DO_COUNT];\n};\n\n#endif\n"
  },
  {
    "path": "CODE/INI.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/INI.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INI.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : November 2, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   INIClass::Clear -- Clears out a section (or all sections) of the INI data.                *\n *   INIClass::Entry_Count -- Fetches the number of entries in a specified section.            *\n *   INIClass::Find_Entry -- Find specified entry within section.                              *\n *   INIClass::Find_Section -- Find the specified section within the INI data.                 *\n *   INIClass::Get_Bool -- Fetch a boolean value for the section and entry specified.          *\n *   INIClass::Get_Entry -- Get the entry identifier name given ordinal number and section name*\n *   INIClass::Get_Fixed -- Fetch a fixed point number from the section & entry.               *\n *   INIClass::Put_Fixed -- Store a fixed point number to the INI database.                    *\n *   INIClass::Get_Hex -- Fetches integer [hex format] from the section and entry specified.   *\n *   INIClass::Get_Int -- Fetch an integer entry from the specified section.                   *\n *   INIClass::Get_PKey -- Fetch a key from the ini database.                                  *\n *   INIClass::Get_String -- Fetch the value of a particular entry in a specified section.     *\n *   INIClass::Get_TextBlock -- Fetch a block of normal text.                                  *\n *   INIClass::Get_UUBlock -- Fetch an encoded block from the section specified.               *\n *   INIClass::INISection::Find_Entry -- Finds a specified entry and returns pointer to it.    *\n *   INIClass::Load -- Load INI data from the file specified.                                  *\n *   INIClass::Load -- Load the INI data from the data stream (straw).                         *\n *   INIClass::Put_Bool -- Store a boolean value into the INI database.                        *\n *   INIClass::Put_Hex -- Store an integer into the INI database, but use a hex format.        *\n *   INIClass::Put_Int -- Stores a signed integer into the INI data base.                      *\n *   INIClass::Put_PKey -- Stores the key to the INI database.                                 *\n *   INIClass::Put_String -- Output a string to the section and entry specified.               *\n *   INIClass::Put_TextBlock -- Stores a block of text into an INI section.                    *\n *   INIClass::Put_UUBlock -- Store a binary encoded data block into the INI database.         *\n *   INIClass::Save -- Save the ini data to the file specified.                                *\n *   INIClass::Save -- Saves the INI data to a pipe stream.                                    *\n *   INIClass::Section_Count -- Counts the number of sections in the INI data.                 *\n *   INIClass::Strip_Comments -- Strips comments of the specified text line.                   *\n *   INIClass::~INIClass -- Destructor for INI handler.                                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t<string.h>\n#include\t<stdlib.h>\n#include\t<stddef.h>\n#include\t<stdio.h>\n#include\t<ctype.h>\n#include\t\"ini.h\"\n#include\t\"readline.h\"\n#include\t\"xpipe.h\"\n#include\t\"b64pipe.h\"\n#include\t\"xstraw.h\"\n#include\t\"b64straw.h\"\n\n\n#ifdef FIXIT_FAST_LOAD\n#include\t\"cstraw.h\"\n#endif\n\n\n\n// Disable the \"temporary object used to initialize a non-constant reference\" warning.\n#pragma warning 665 9\n\n\n/***********************************************************************************************\n * INIClass::~INIClass -- Destructor for INI handler.                                          *\n *                                                                                             *\n *    This is the destructor for the INI class. It handles deleting all of the allocations     *\n *    it might have done.                                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nINIClass::~INIClass(void)\n{\n\tClear();\n}\n\n\n/***********************************************************************************************\n * INIClass::Clear -- Clears out a section (or all sections) of the INI data.                  *\n *                                                                                             *\n *    This routine is used to clear out the section specified. If no section is specified,     *\n *    then the entire INI data is cleared out. Optionally, this routine can be used to clear   *\n *    out just an individual entry in the specified section.                                   *\n *                                                                                             *\n * INPUT:   section  -- Pointer to the section to clear out [pass NULL to clear all].          *\n *                                                                                             *\n *          entry    -- Pointer to optional entry specifier. If this parameter is specified,   *\n *                      then only this specific entry (if found) will be cleared. Otherwise,   *\n *                      the entire section specified will be cleared.                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *   08/21/1996 JLB : Optionally clears section too.                                           *\n *   11/02/1996 JLB : Updates the index list.                                                  *\n *=============================================================================================*/\nbool INIClass::Clear(char const * section, char const * entry)\n{\n\tif (section == NULL) {\n\t\tSectionList.Delete();\n\t\tSectionIndex.Clear();\n\t} else {\n\t\tINISection * secptr = Find_Section(section);\n\t\tif (secptr != NULL) {\n\t\t\tif (entry != NULL) {\n\t\t\t\tINIEntry * entptr = secptr->Find_Entry(entry);\n\t\t\t\tif (entptr != NULL) {\n\t\t\t\t\t/*\n\t\t\t\t\t**\tRemove the entry from the entry index list.\n\t\t\t\t\t*/\n\t\t\t\t\tsecptr->EntryIndex.Remove_Index(entptr->Index_ID());\n\n\t\t\t\t\tdelete entptr;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t**\tRemove this section index from the section index list.\n\t\t\t\t*/\n\t\t\t\tSectionIndex.Remove_Index(secptr->Index_ID());\n\n\t\t\t\tdelete secptr;\n\t\t\t}\n\t\t}\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * INIClass::Load -- Load INI data from the file specified.                                    *\n *                                                                                             *\n *    Use this routine to load the INI class with the data from the specified file.            *\n *                                                                                             *\n * INPUT:   file  -- Reference to the file that will be used to fill up this INI manager.      *\n *                                                                                             *\n * OUTPUT:  bool; Was the file loaded successfully?                                            *\n *                                                                                             *\n * WARNINGS:   This routine allocates memory.                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool INIClass::Load(FileClass & file)\n{\n\treturn(Load(FileStraw(file)));\n}\n\n\n/***********************************************************************************************\n * INIClass::Load -- Load the INI data from the data stream (straw).                           *\n *                                                                                             *\n *    This will fetch data from the straw and build an INI database from it.                   *\n *                                                                                             *\n * INPUT:   straw -- The straw that the data will be provided from.                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the database loaded ok?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef FIXIT_FAST_LOAD\nbool INIClass::Load(Straw & ffile)\n#else\nbool INIClass::Load(Straw & file)\n#endif\n{\n\tbool end_of_file = false;\n\tchar buffer[MAX_LINE_LENGTH];\n\n#ifdef FIXIT_FAST_LOAD\n\tCacheStraw file;\n\tfile.Get_From(ffile);\n#endif\n\n\t/*\n\t**\tPrescan until the first section is found.\n\t*/\n\twhile (!end_of_file) {\n\t\tRead_Line(file, buffer, sizeof(buffer), end_of_file);\n\t\tif (end_of_file) return(false);\n\t\tif (buffer[0] == '[' && strchr(buffer, ']') != NULL) break;\n\t}\n\n\t/*\n\t**\tProcess a section. The buffer is prefilled with the section name line.\n\t*/\n\twhile (!end_of_file) {\n\n\t\tbuffer[0] = ' ';\n\t\tchar * ptr = strchr(buffer, ']');\n\t\tif (ptr) *ptr = '\\0';\n\t\tstrtrim(buffer);\n\t\tINISection * secptr = new INISection(strdup(buffer));\n\t\tif (secptr == NULL) {\n\t\t\tClear();\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t**\tRead in the entries of this section.\n\t\t*/\n\t\twhile (!end_of_file) {\n\n\t\t\t/*\n\t\t\t**\tIf this line is the start of another section, then bail out\n\t\t\t**\tof the entry loop and let the outer section loop take\n\t\t\t**\tcare of it.\n\t\t\t*/\n\t\t\tint len = Read_Line(file, buffer, sizeof(buffer), end_of_file);\n\t\t\tif (buffer[0] == '[' && strchr(buffer, ']') != NULL) break;\n\n\t\t\t/*\n\t\t\t**\tDetermine if this line is a comment or blank line. Throw it out if it is.\n\t\t\t*/\n\t\t\tStrip_Comments(buffer);\n\t\t\tif (len == 0 || buffer[0] == ';' || buffer[0] == '=') continue;\n\n\t\t\t/*\n\t\t\t**\tThe line isn't an obvious comment. Make sure that there is the \"=\" character\n\t\t\t**\tat an appropriate spot.\n\t\t\t*/\n\t\t\tchar * divider = strchr(buffer, '=');\n\t\t\tif (!divider) continue;\n\n\t\t\t/*\n\t\t\t**\tSplit the line into entry and value sections. Be sure to catch the\n\t\t\t**\t\"=foobar\" and \"foobar=\" cases. These lines are ignored.\n\t\t\t*/\n\t\t\t*divider++ = '\\0';\n\t\t\tstrtrim(buffer);\n\t\t\tif (!strlen(buffer)) continue;\n\n\t\t\tstrtrim(divider);\n\t\t\tif (!strlen(divider)) continue;\n\n\t\t\tINIEntry * entryptr = new INIEntry(strdup(buffer), strdup(divider));\n\t\t\tif (entryptr == NULL) {\n\t\t\t\tdelete secptr;\n\t\t\t\tClear();\n\t\t\t\treturn(false);\n\t\t\t}\n\n\t\t\tsecptr->EntryIndex.Add_Index(entryptr->Index_ID(), entryptr);\n\t\t\tsecptr->EntryList.Add_Tail(entryptr);\n\t\t}\n\n\t\t/*\n\t\t**\tAll the entries for this section have been parsed. If this section is blank, then\n\t\t**\tdon't bother storing it.\n\t\t*/\n\t\tif (secptr->EntryList.Is_Empty()) {\n\t\t\tdelete secptr;\n\t\t} else {\n\t\t\tSectionIndex.Add_Index(secptr->Index_ID(), secptr);\n\t\t\tSectionList.Add_Tail(secptr);\n\t\t}\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * INIClass::Save -- Save the ini data to the file specified.                                  *\n *                                                                                             *\n *    Use this routine to save the ini data to the file specified. All existing data in the    *\n *    file, if it was present, is replaced.                                                    *\n *                                                                                             *\n * INPUT:   file  -- Reference to the file to write the INI data to.                           *\n *                                                                                             *\n * OUTPUT:  bool; Was the data written to the file?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint INIClass::Save(FileClass & file) const\n{\n\treturn(Save(FilePipe(file)));\n}\n\n\n/***********************************************************************************************\n * INIClass::Save -- Saves the INI data to a pipe stream.                                      *\n *                                                                                             *\n *    This routine will output the data of the INI file to a pipe stream.                      *\n *                                                                                             *\n * INPUT:   pipe  -- Reference to the pipe stream to pump the INI image to.                    *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes output to the pipe.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint INIClass::Save(Pipe & pipe) const\n{\n\tint total = 0;\n\n\tINISection * secptr = SectionList.First();\n\twhile (secptr && secptr->Is_Valid()) {\n\n\t\t/*\n\t\t**\tOutput the section identifier.\n\t\t*/\n\t\ttotal += pipe.Put(\"[\", 1);\n\t\ttotal += pipe.Put(secptr->Section, strlen(secptr->Section));\n\t\ttotal += pipe.Put(\"]\", 1);\n\t\ttotal += pipe.Put(\"\\r\\n\", strlen(\"\\r\\n\"));\n\n\t\t/*\n\t\t**\tOutput all the entries and values in this section.\n\t\t*/\n\t\tINIEntry * entryptr = secptr->EntryList.First();\n\t\twhile (entryptr && entryptr->Is_Valid()) {\n\t\t\ttotal += pipe.Put(entryptr->Entry, strlen(entryptr->Entry));\n\t\t\ttotal += pipe.Put(\"=\", 1);\n\t\t\ttotal += pipe.Put(entryptr->Value, strlen(entryptr->Value));\n\t\t\ttotal += pipe.Put(\"\\r\\n\", strlen(\"\\r\\n\"));\n\n\t\t\tentryptr = entryptr->Next();\n\t\t}\n\n\t\t/*\n\t\t**\tAfter the last entry in this section, output an extra\n\t\t**\tblank line for readability purposes.\n\t\t*/\n\t\ttotal += pipe.Put(\"\\r\\n\", strlen(\"\\r\\n\"));\n\n\t\tsecptr = secptr->Next();\n\t}\n\ttotal += pipe.End();\n\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * INIClass::Find_Section -- Find the specified section within the INI data.                   *\n *                                                                                             *\n *    This routine will scan through the INI data looking for the section specified. If the    *\n *    section could be found, then a pointer to the section control data is returned.          *\n *                                                                                             *\n * INPUT:   section  -- The name of the section to search for. Don't enclose the name in       *\n *                      brackets. Case is NOT sensitive in the search.                         *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the INI section control structure if the section was     *\n *          found. Otherwise, NULL is returned.                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *   11/02/1996 JLB : Uses index manager.                                                      *\n *=============================================================================================*/\nINIClass::INISection * INIClass::Find_Section(char const * section) const\n{\n\tif (section != NULL) {\n\n\t\tlong crc = CRCEngine()(section, strlen(section));\n\n\t\tif (SectionIndex.Is_Present(crc)) {\n\t\t\treturn(SectionIndex.Fetch_Index(crc));\n\t\t}\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * INIClass::Section_Count -- Counts the number of sections in the INI data.                   *\n *                                                                                             *\n *    This routine will scan through all the sections in the INI data and return a count       *\n *    of the number it found.                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of sections recorded in the INI data.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *   11/02/1996 JLB : Uses index manager.                                                      *\n *=============================================================================================*/\nint INIClass::Section_Count(void) const\n{\n\treturn(SectionIndex.Count());\n}\n\n\n/***********************************************************************************************\n * INIClass::Entry_Count -- Fetches the number of entries in a specified section.              *\n *                                                                                             *\n *    This routine will examine the section specified and return with the number of entries    *\n *    associated with it.                                                                      *\n *                                                                                             *\n * INPUT:   section  -- Pointer to the section that will be examined.                          *\n *                                                                                             *\n * OUTPUT:  Returns with the number entries in the specified section.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *   11/02/1996 JLB : Uses index manager.                                                      *\n *=============================================================================================*/\nint INIClass::Entry_Count(char const * section) const\n{\n\tINISection * secptr = Find_Section(section);\n\tif (secptr != NULL) {\n\t\treturn(secptr->EntryIndex.Count());\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * INIClass::Find_Entry -- Find specified entry within section.                                *\n *                                                                                             *\n *    This support routine will find the specified entry in the specified section. If found,   *\n *    a pointer to the entry control structure will be returned.                               *\n *                                                                                             *\n * INPUT:   section  -- Pointer to the section name to search under.                           *\n *                                                                                             *\n *          entry    -- Pointer to the entry name to search for.                               *\n *                                                                                             *\n * OUTPUT:  If the entry was found, then a pointer to the entry control structure will be      *\n *          returned. Otherwise, NULL will be returned.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nINIClass::INIEntry * INIClass::Find_Entry(char const * section, char const * entry) const\n{\n\tINISection * secptr = Find_Section(section);\n\tif (secptr != NULL) {\n\t\treturn(secptr->Find_Entry(entry));\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_Entry -- Get the entry identifier name given ordinal number and section name. *\n *                                                                                             *\n *    This will return the identifier name for the entry under the section specified. The      *\n *    ordinal number specified is used to determine which entry to retrieve. The entry         *\n *    identifier is the text that appears to the left of the \"=\" character.                    *\n *                                                                                             *\n * INPUT:   section  -- The section to use.                                                    *\n *                                                                                             *\n *          index    -- The ordinal number to use when fetching an entry name.                 *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the entry name.                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * INIClass::Get_Entry(char const * section, int index) const\n{\n\tINISection * secptr = Find_Section(section);\n\n\tif (secptr != NULL && index < secptr->EntryIndex.Count()) {\n\t\tINIEntry * entryptr = secptr->EntryList.First();\n\n\t\twhile (entryptr != NULL && entryptr->Is_Valid()) {\n\t\t\tif (index == 0) return(entryptr->Entry);\n\t\t\tindex--;\n\t\t\tentryptr = entryptr->Next();\n\t\t}\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * INIClass::Put_UUBlock -- Store a binary encoded data block into the INI database.           *\n *                                                                                             *\n *    Use this routine to store an arbitrary length binary block of data into the INI database.*\n *    This routine will covert the data into displayable form and then break it into lines     *\n *    that are stored in sequence to the section. A section used to store data in this         *\n *    fashion can not be used for any other entries.                                           *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to place the data into.                         *\n *                                                                                             *\n *          block    -- Pointer to the block of binary data to store.                          *\n *                                                                                             *\n *          len      -- The length of the binary data.                                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the data stored to the database?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool INIClass::Put_UUBlock(char const * section, void const * block, int len)\n{\n\tif (section == NULL || block == NULL || len < 1) return(false);\n\n\tClear(section);\n\n\tBufferStraw straw(block, len);\n\tBase64Straw bstraw(Base64Straw::ENCODE);\n\tbstraw.Get_From(straw);\n\n\tint counter = 1;\n\n\tfor (;;) {\n\t\tchar buffer[71];\n\t\tchar sbuffer[32];\n\n\t\tint length = bstraw.Get(buffer, sizeof(buffer)-1);\n\t\tbuffer[length] = '\\0';\n\t\tif (length == 0) break;\n\n\t\tsprintf(sbuffer, \"%d\", counter);\n\t\tPut_String(section, sbuffer, buffer);\n\t\tcounter++;\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_UUBlock -- Fetch an encoded block from the section specified.                 *\n *                                                                                             *\n *    This routine will take all the entries in the specified section and decompose them into  *\n *    a binary block of data that will be stored into the buffer specified. By using this      *\n *    routine [and the Put_UUBLock counterpart], arbitrary blocks of binary data may be        *\n *    stored in the INI file. A section processed by this routine can contain no other         *\n *    entries than those put there by a previous call to Put_UUBlock.                          *\n *                                                                                             *\n * INPUT:   section  -- The section name to process.                                           *\n *                                                                                             *\n *          block    -- Pointer to the buffer that will hold the retrieved data.               *\n *                                                                                             *\n *          len      -- The length of the buffer. The retrieved data will not fill past this   *\n *                      limit.                                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes decoded into the buffer specified.                *\n *                                                                                             *\n * WARNINGS:   If the number of bytes retrieved exactly matches the length of the buffer       *\n *             specified, then you might have a condition of buffer \"overflow\".                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint INIClass::Get_UUBlock(char const * section, void * block, int len) const\n{\n\tif (section == NULL) return(0);\n\n\tBase64Pipe b64pipe(Base64Pipe::DECODE);\n\tBufferPipe bpipe(block, len);\n\n\tb64pipe.Put_To(&bpipe);\n\n\tint total = 0;\n\tint counter = Entry_Count(section);\n\tfor (int index = 0; index < counter; index++) {\n\t\tchar buffer[128];\n\n\t\tint length = Get_String(section, Get_Entry(section, index), \"=\", buffer, sizeof(buffer));\n\t\tint outcount = b64pipe.Put(buffer, length);\n\t\ttotal += outcount;\n\t}\n\ttotal += b64pipe.End();\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * INIClass::Put_TextBlock -- Stores a block of text into an INI section.                      *\n *                                                                                             *\n *    This routine will take an arbitrarily long block of text and store it into the INI       *\n *    database. The text is broken up into lines and each line is then stored as a numbered    *\n *    entry in the specified section. A section used to store text in this way can not be used *\n *    to hold any other entries. The text is presumed to contain space characters scattered    *\n *    throughout it and that one space between words and sentences is natural.                 *\n *                                                                                             *\n * INPUT:   section  -- The section to place the text block into.                              *\n *                                                                                             *\n *          text     -- Pointer to a null terminated text string that holds the block of       *\n *                      text. The length can be arbitrary.                                     *\n *                                                                                             *\n * OUTPUT:  bool; Was the text block placed into the database?                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool INIClass::Put_TextBlock(char const * section, char const * text)\n{\n\tif (section == NULL) return(false);\n\n\tClear(section);\n\n\tint index = 1;\n\twhile (text != NULL && *text != NULL) {\n\n\t\tchar buffer[128];\n\n\t\tstrncpy(buffer, text, 75);\n\t\tbuffer[75] = '\\0';\n\n\t\tchar b[32];\n\t\tsprintf(b, \"%d\", index);\n\n\t\t/*\n\t\t**\tScan backward looking for a good break position.\n\t\t*/\n\t\tint count = strlen(buffer);\n\t\tif (count > 0) {\n\t\t\tif (count >= 75) {\n\t\t\t\twhile (count) {\n\t\t\t\t\tchar c = buffer[count];\n\n\t\t\t\t\tif (isspace(c)) break;\n\t\t\t\t\tcount--;\n\t\t\t\t}\n\n\t\t\t\tif (count == 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tbuffer[count] = '\\0';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstrtrim(buffer);\n\t\t\tPut_String(section, b, buffer);\n\t\t\tindex++;\n\t\t\ttext = ((char  *)text) + count;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_TextBlock -- Fetch a block of normal text.                                    *\n *                                                                                             *\n *    This will take all entries in the specified section and format them into a block of      *\n *    normalized text. That is, text with single spaces between each concatenated line. All    *\n *    entries in the specified section are processed by this routine. Use Put_TextBlock to     *\n *    build the entries in the section.                                                        *\n *                                                                                             *\n * INPUT:   section  -- The section name to process.                                           *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer that will hold the complete text.                *\n *                                                                                             *\n *          len      -- The length of the buffer specified. The text will, at most, fill this  *\n *                      buffer with the last character being forced to null.                   *\n *                                                                                             *\n * OUTPUT:  Returns with the number of characters placed into the buffer. The trailing null    *\n *          is not counted.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint INIClass::Get_TextBlock(char const * section, char * buffer, int len) const\n{\n\tif (len <= 0) return(0);\n\n\tbuffer[0] = '\\0';\n\tif (len <= 1) return(0);\n\n\tint elen = Entry_Count(section);\n\tint total = 0;\n\tfor (int index = 0; index < elen; index++) {\n\n\t\t/*\n\t\t**\tAdd spacers between lines of fetched text.\n\t\t*/\n\t\tif (index > 0) {\n\t\t\t*buffer++ = ' ';\n\t\t\tlen--;\n\t\t\ttotal++;\n\t\t}\n\n\t\tGet_String(section, Get_Entry(section, index), \"\", buffer, len);\n\n\t\tint partial = strlen(buffer);\n\t\ttotal += partial;\n\t\tbuffer += partial;\n\t\tlen -= partial;\n\t\tif (len <= 1) break;\n\t}\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * INIClass::Put_Int -- Stores a signed integer into the INI data base.                        *\n *                                                                                             *\n *    Use this routine to store an integer value into the section and entry specified.         *\n *                                                                                             *\n * INPUT:   section  -- The identifier for the section that the entry will be placed in.       *\n *                                                                                             *\n *          entry    -- The entry identifier used for the integer number.                      *\n *                                                                                             *\n *          number   -- The integer number to store in the database.                           *\n *                                                                                             *\n *          format   -- The format to store the integer. The format is generally only a        *\n *                      cosmetic affect. The Get_Int operation will interpret the value the    *\n *                      same regardless of what format was used to store the integer.          *\n *                                                                                             *\n *                      0  : plain decimal digit                                               *\n *                      1  : hexadecimal digit (trailing \"h\")                                  *\n *                      2  : hexadecimal digit (leading \"$\")                                   *\n *                                                                                             *\n * OUTPUT:  bool; Was the number stored?                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *   07/10/1996 JLB : Handles multiple integer formats.                                        *\n *=============================================================================================*/\nbool INIClass::Put_Int(char const * section, char const * entry, int number, int format)\n{\n\tchar buffer[MAX_LINE_LENGTH];\n\n\tswitch (format) {\n\t\tdefault:\n\t\tcase 0:\n\t\t\tsprintf(buffer, \"%d\", number);\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tsprintf(buffer, \"%Xh\", number);\n\t\t\tbreak;\n\n\t\tcase 2:\n\t\t\tsprintf(buffer, \"$%X\", number);\n\t\t\tbreak;\n\t}\n\treturn(Put_String(section, entry, buffer));\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_Int -- Fetch an integer entry from the specified section.                     *\n *                                                                                             *\n *    This routine will fetch an integer value from the entry and section specified. If no     *\n *    entry could be found, then the default value will be returned instead.                   *\n *                                                                                             *\n * INPUT:   section  -- The section name to search under.                                      *\n *                                                                                             *\n *          entry    -- The entry name to search for.                                          *\n *                                                                                             *\n *          defvalue -- The default value to use if the specified entry could not be found.    *\n *                                                                                             *\n * OUTPUT:  Returns with the integer value specified in the INI database or else returns the   *\n *          default value.                                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *   07/10/1996 JLB : Handles multiple integer formats.                                        *\n *=============================================================================================*/\nint INIClass::Get_Int(char const * section, char const * entry, int defvalue) const\n{\n\t/*\n\t**\tVerify that the parameters are nominally correct.\n\t*/\n\tif (section == NULL || entry == NULL) return(defvalue);\n\n\tINIEntry * entryptr = Find_Entry(section, entry);\n\tif (entryptr && entryptr->Value != NULL) {\n\n\t\tif (*entryptr->Value == '$') {\n\t\t\tsscanf(entryptr->Value, \"$%x\", &defvalue);\n\t\t} else {\n\t\t\tif (tolower(entryptr->Value[strlen(entryptr->Value)-1]) == 'h') {\n\t\t\t\tsscanf(entryptr->Value, \"%xh\", &defvalue);\n\t\t\t} else {\n\t\t\t\tdefvalue = atoi(entryptr->Value);\n\t\t\t}\n\t\t}\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * INIClass::Put_Hex -- Store an integer into the INI database, but use a hex format.          *\n *                                                                                             *\n *    This routine is similar to the Put_Int routine, but the number is stored as a hexadecimal*\n *    number.                                                                                  *\n *                                                                                             *\n * INPUT:   section  -- The identifier for the section that the entry will be placed in.       *\n *                                                                                             *\n *          entry    -- The entry identifier to tag to the integer number specified.           *\n *                                                                                             *\n *          number   -- The number to assign the the specified entry and placed in the         *\n *                      specified section.                                                     *\n *                                                                                             *\n * OUTPUT:  bool; Was the number placed into the INI database?                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool INIClass::Put_Hex(char const * section, char const * entry, int number)\n{\n\tchar buffer[MAX_LINE_LENGTH];\n\n\tsprintf(buffer, \"%X\", number);\n\treturn(Put_String(section, entry, buffer));\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_Hex -- Fetches integer [hex format] from the section and entry specified.     *\n *                                                                                             *\n *    This routine will search under the section specified, looking for a matching entry. The  *\n *    value is interpreted as a hexadecimal number and then returned. If no entry could be     *\n *    found, then the default value is returned instead.                                       *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to search under.                                *\n *                                                                                             *\n *          entry    -- The entry identifier to search for.                                    *\n *                                                                                             *\n *          defvalue -- The default value to use if the entry could not be located.            *\n *                                                                                             *\n * OUTPUT:  Returns with the integer value from the specified section and entry. If no entry   *\n *          could be found, then the default value will be returned instead.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint INIClass::Get_Hex(char const * section, char const * entry, int defvalue) const\n{\n\t/*\n\t**\tVerify that the parameters are nominally correct.\n\t*/\n\tif (section == NULL || entry == NULL) return(defvalue);\n\n\tINIEntry * entryptr = Find_Entry(section, entry);\n\tif (entryptr && entryptr->Value != NULL) {\n\t\tsscanf(entryptr->Value, \"%x\", &defvalue);\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * INIClass::Put_String -- Output a string to the section and entry specified.                 *\n *                                                                                             *\n *    This routine will put an arbitrary string to the section and entry specified. Any        *\n *    previous matching entry will be replaced.                                                *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to place the string under.                      *\n *                                                                                             *\n *          entry    -- The entry identifier to identify this string [placed under the section]*\n *                                                                                             *\n *          string   -- Pointer to the string to assign to this entry.                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the entry assigned without error?                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *   11/02/1996 JLB : Uses index handler.                                                      *\n *=============================================================================================*/\nbool INIClass::Put_String(char const * section, char const * entry, char const * string)\n{\n\tif (section == NULL || entry == NULL) return(false);\n\n\tINISection * secptr = Find_Section(section);\n\n\tif (secptr == NULL) {\n\t\tsecptr = new INISection(strdup(section));\n\t\tif (secptr == NULL) return(false);\n\t\tSectionList.Add_Tail(secptr);\n\t\tSectionIndex.Add_Index(secptr->Index_ID(), secptr);\n\t}\n\n\t/*\n\t**\tRemove the old entry if found.\n\t*/\n\tINIEntry * entryptr = secptr->Find_Entry(entry);\n\tif (entryptr != NULL) {\n\t\tsecptr->EntryIndex.Remove_Index(entryptr->Index_ID());\n\t\tdelete entryptr;\n\t}\n\n\t/*\n\t**\tCreate and add the new entry.\n\t*/\n\tif (string != NULL && strlen(string) > 0) {\n\t\tentryptr = new INIEntry(strdup(entry), strdup(string));\n\n\t\tif (entryptr == NULL) {\n\t\t\treturn(false);\n\t\t}\n\t\tsecptr->EntryList.Add_Tail(entryptr);\n\t\tsecptr->EntryIndex.Add_Index(entryptr->Index_ID(), entryptr);\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_String -- Fetch the value of a particular entry in a specified section.       *\n *                                                                                             *\n *    This will retrieve the entire text to the right of the \"=\" character. The text is        *\n *    found by finding a matching entry in the section specified. If no matching entry could   *\n *    be found, then the default value will be stored in the output string buffer.             *\n *                                                                                             *\n * INPUT:   section  -- Pointer to the section name to search under.                           *\n *                                                                                             *\n *          entry    -- The entry identifier to search for.                                    *\n *                                                                                             *\n *          defvalue -- If no entry could be found, then this text will be returned.           *\n *                                                                                             *\n *          buffer   -- Output buffer to store the retrieved string into.                      *\n *                                                                                             *\n *          size     -- The size of the output buffer. The maximum string length that could    *\n *                      be retrieved will be one less than this length. This is due to the     *\n *                      forced trailing zero added to the end of the string.                   *\n *                                                                                             *\n * OUTPUT:  Returns with the length of the string retrieved.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint INIClass::Get_String(char const * section, char const * entry, char const * defvalue, char * buffer, int size) const\n{\n\t/*\n\t**\tVerify that the parameters are nominally legal.\n\t*/\n\tif (buffer != NULL && size > 0) {\n\t\tbuffer[0] = '\\0';\n\t}\n\tif (buffer == NULL || !size || section == NULL || entry == NULL) return(0);\n\n\t/*\n\t**\tFetch the entry string if it is present. If not, then the normal default\n\t**\tvalue will be used as the entry value.\n\t*/\n\tINIEntry * entryptr = Find_Entry(section, entry);\n\tif (entryptr) {\n\t\tif (entryptr->Value) {\n\t\t\tdefvalue = entryptr->Value;\n\t\t}\n\t}\n\n\t/*\n\t**\tFill in the buffer with the entry value and return with the length of the string.\n\t*/\n\tif (defvalue == NULL) {\n\t\tbuffer[0] = '\\0';\n\t\treturn(0);\n\t} else {\n\t\tstrncpy(buffer, defvalue, size);\n\t\tbuffer[size-1] = '\\0';\n\t\tstrtrim(buffer);\n\t\treturn(strlen(buffer));\n\t}\n}\n\n\n/***********************************************************************************************\n * INIClass::Put_Bool -- Store a boolean value into the INI database.                          *\n *                                                                                             *\n *    Use this routine to place a boolean value into the INI database. The boolean value will  *\n *    be stored as \"yes\" or \"no\".                                                              *\n *                                                                                             *\n * INPUT:   section  -- The section to place the entry and boolean value into.                 *\n *                                                                                             *\n *          entry    -- The entry identifier to tag to the boolean value.                      *\n *                                                                                             *\n *          value    -- The boolean value to place into the database.                          *\n *                                                                                             *\n * OUTPUT:  bool; Was the boolean value placed into the database?                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool INIClass::Put_Bool(char const * section, char const * entry, bool value)\n{\n\tif (value) {\n\t\treturn(Put_String(section, entry, \"yes\"));\n\t} else {\n\t\treturn(Put_String(section, entry, \"no\"));\n\t}\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_Bool -- Fetch a boolean value for the section and entry specified.            *\n *                                                                                             *\n *    This routine will search under the section specified, looking for a matching entry. If   *\n *    one is found, the value is interpreted as a boolean value and then returned. In the case *\n *    of no matching entry, the default value will be returned instead. The boolean value      *\n *    is interpreted using the standard boolean conventions. e.g., \"Yes\", \"Y\", \"1\", \"True\",    *\n *    \"T\" are all consider to be a TRUE boolean value.                                         *\n *                                                                                             *\n * INPUT:   section  -- The section to search under.                                           *\n *                                                                                             *\n *          entry    -- The entry to search for.                                               *\n *                                                                                             *\n *          defvalue -- The default value to use if no matching entry could be located.        *\n *                                                                                             *\n * OUTPUT:  Returns with the boolean value of the specified section and entry. If no match     *\n *          then the default boolean value is returned.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool INIClass::Get_Bool(char const * section, char const * entry, bool defvalue) const\n{\n\t/*\n\t**\tVerify that the parameters are nominally correct.\n\t*/\n\tif (section == NULL || entry == NULL) return(defvalue);\n\n\tINIEntry * entryptr = Find_Entry(section, entry);\n\tif (entryptr && entryptr->Value != NULL) {\n\t\tswitch (toupper(*entryptr->Value)) {\n\t\t\tcase 'Y':\n\t\t\tcase 'T':\n\t\t\tcase '1':\n\t\t\t\treturn(true);\n\n\t\t\tcase 'N':\n\t\t\tcase 'F':\n\t\t\tcase '0':\n\t\t\t\treturn(false);\n\t\t}\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * INIClass::INISection::Find_Entry -- Finds a specified entry and returns pointer to it.      *\n *                                                                                             *\n *    This routine scans the supplied entry for the section specified. This is used for        *\n *    internal database maintenance.                                                           *\n *                                                                                             *\n * INPUT:   entry -- The entry to scan for.                                                    *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the entry control structure if the entry was found.      *\n *          Otherwise it returns NULL.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *   11/02/1996 JLB : Uses index handler.                                                      *\n *=============================================================================================*/\nINIClass::INIEntry * INIClass::INISection::Find_Entry(char const * entry) const\n{\n\tif (entry != NULL) {\n\t\tint crc = CRCEngine()(entry, strlen(entry));\n\t\tif (EntryIndex.Is_Present(crc)) {\n\t\t\treturn(EntryIndex.Fetch_Index(crc));\n\t\t}\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * INIClass::Put_PKey -- Stores the key to the INI database.                                   *\n *                                                                                             *\n *    The key stored to the database will have both the exponent and modulus portions saved.   *\n *    Since the fast key only requires the modulus, it is only necessary to save the slow      *\n *    key to the database. However, storing the slow key stores the information necessary to   *\n *    generate the fast and slow keys. Because public key encryption requires one key to be    *\n *    completely secure, only store the fast key in situations where the INI database will     *\n *    be made public.                                                                          *\n *                                                                                             *\n * INPUT:   key   -- The key to store the INI database.                                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the key stored to the database?                                          *\n *                                                                                             *\n * WARNINGS:   Store the fast key for public INI database availability. Store the slow key if  *\n *             the INI database is secure.                                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool INIClass::Put_PKey(PKey const & key)\n{\n\tchar buffer[512];\n\n\tint len = key.Encode_Modulus(buffer);\n\tPut_UUBlock(\"PublicKey\", buffer, len);\n\n\tlen = key.Encode_Exponent(buffer);\n\tPut_UUBlock(\"PrivateKey\", buffer, len);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_PKey -- Fetch a key from the ini database.                                    *\n *                                                                                             *\n *    This routine will fetch the key from the INI database. The key fetched is controlled by  *\n *    the parameter. There are two choices of key -- the fast or slow key.                     *\n *                                                                                             *\n * INPUT:   fast  -- Should the fast key be retrieved? The fast key has the advantage of       *\n *                   requiring only the modulus value.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the key retrieved.                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nPKey INIClass::Get_PKey(bool fast) const\n{\n\tPKey key;\n\tchar buffer[512];\n\n\t/*\n\t**\tWhen retrieving the fast key, the exponent is a known constant. Don't parse the\n\t**\texponent from the database.\n\t*/\n\tif (fast) {\n\t\tBigInt exp = PKey::Fast_Exponent();\n\t\texp.DEREncode((unsigned char *)buffer);\n\t\tkey.Decode_Exponent(buffer);\n\t} else {\n\t\tGet_UUBlock(\"PrivateKey\", buffer, sizeof(buffer));\n\t\tkey.Decode_Exponent(buffer);\n\t}\n\n\tGet_UUBlock(\"PublicKey\", buffer, sizeof(buffer));\n\tkey.Decode_Modulus(buffer);\n\n\treturn(key);\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_Fixed -- Fetch a fixed point number from the section & entry.                 *\n *                                                                                             *\n *    This routine will examine the section and entry specified and interpret the value        *\n *    as if it were a fixed point number. The format of the fixed point number can be          *\n *    percentage (e.g. 100%) or a floating point number (e.g., 1.7).                           *\n *                                                                                             *\n * INPUT:   section  -- Pointer to the section identifier to look under.                       *\n *                                                                                             *\n *          entry    -- Pointer to the entry identifier to examine.                            *\n *                                                                                             *\n *          defvalue -- If the section and entry could not be found, then this value will      *\n *                      be returned.                                                           *\n *                                                                                             *\n * OUTPUT:  Returns with the fixed point number that occurs at the section and entry           *\n *          specified. If it could not be found, then the default value is returned.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed INIClass::Get_Fixed(char const * section, char const * entry, fixed defvalue) const\n{\n\tchar buffer[128];\n\tfixed retval = defvalue;\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\tretval = fixed(buffer);\n\t}\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * INIClass::Put_Fixed -- Store a fixed point number to the INI database.                      *\n *                                                                                             *\n *    Use this routine to output a fixed point number to the database. The entry will be       *\n *    placed in the section and entry specified. If there was any existing entry, it will      *\n *    be replaced.                                                                             *\n *                                                                                             *\n * INPUT:   section  -- Pointer to the section identifier.                                     *\n *                                                                                             *\n *          entry    -- Pointer to the entry identifier to use for this value.                 *\n *                                                                                             *\n *          value    -- The value to store in the database.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the data stored?                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool INIClass::Put_Fixed(char const * section, char const * entry, fixed value)\n{\n\treturn(Put_String(section, entry, value.As_ASCII()));\n}\n\n\n/***********************************************************************************************\n * INIClass::Strip_Comments -- Strips comments of the specified text line.                     *\n *                                                                                             *\n *    This routine will scan the string (text line) supplied and if any comment portions are   *\n *    found, they will be trimmed off. Leading and trailing blanks are also removed.           *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the null terminate string to be processed.                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid INIClass::Strip_Comments(char * buffer)\n{\n\tif (buffer != NULL) {\n\t\tchar * comment = strchr(buffer, ';');\n\t\tif (comment) {\n\t\t\t*comment = '\\0';\n\t\t\tstrtrim(buffer);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "CODE/INI.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/INI.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INI.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/15/96                                                     *\n *                                                                                             *\n *                  Last Update : May 15, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef INI_H\n#define INI_H\n\n#include\t<stdlib.h>\n#include\t\"listnode.h\"\n#include\t\"pipe.h\"\n#include\t\"wwfile.h\"\n#include\t\"pk.h\"\n#include\t\"fixed.h\"\n#include\t\"crc.h\"\n#include\t\"search.h\"\n\n/*\n**\tThis is an INI database handler class. It handles a database with a disk format identical\n**\tto the INI files commonly used by Windows.\n*/\nclass INIClass {\n\tpublic:\n\t\tINIClass(void) {}\n\t\t~INIClass(void);\n\n\t\t/*\n\t\t**\tFetch and store INI data.\n\t\t*/\n\t\tbool Load(FileClass & file);\n\t\tbool Load(Straw & file);\n\t\tint Save(FileClass & file) const;\n\t\tint Save(Pipe & file) const;\n\n\t\t/*\n\t\t**\tErase all data within this INI file manager.\n\t\t*/\n\t\tbool Clear(char const * section = 0, char const * entry = 0);\n\n\t\tint Line_Count(char const * section) const;\n\t\tbool Is_Loaded(void) const {return(!SectionList.Is_Empty());}\n\t\tint Size(void) const;\n\t\tbool Is_Present(char const * section, char const * entry = 0) const {if (entry == 0) return(Find_Section(section) != 0);return(Find_Entry(section, entry) != 0);}\n\n\t\t/*\n\t\t**\tFetch the number of sections in the INI file or verify if a specific\n\t\t**\tsection is present.\n\t\t*/\n\t\tint Section_Count(void) const;\n\t\tbool Section_Present(char const * section) const {return(Find_Section(section) != NULL);}\n\n\t\t/*\n\t\t**\tFetch the number of entries in a section or get a particular entry in a section.\n\t\t*/\n\t\tint Entry_Count(char const * section) const;\n\t\tchar const * Get_Entry(char const * section, int index) const;\n\n\t\t/*\n\t\t**\tGet the various data types from the section and entry specified.\n\t\t*/\n\t\tint Get_String(char const * section, char const * entry, char const * defvalue, char * buffer, int size) const;\n\t\tint Get_Int(char const * section, char const * entry, int defvalue=0) const;\n\t\tint Get_Hex(char const * section, char const * entry, int defvalue=0) const;\n\t\tbool Get_Bool(char const * section, char const * entry, bool defvalue=false) const;\n\t\tint Get_TextBlock(char const * section, char * buffer, int len) const;\n\t\tint Get_UUBlock(char const * section, void * buffer, int len) const;\n\t\tPKey Get_PKey(bool fast) const;\n\t\tfixed Get_Fixed(char const * section, char const * entry, fixed defvalue) const;\n\n\t\t/*\n\t\t**\tPut a data type to the section and entry specified.\n\t\t*/\n\t\tbool Put_Fixed(char const * section, char const * entry, fixed value);\n\t\tbool Put_String(char const * section, char const * entry, char const * string);\n\t\tbool Put_Hex(char const * section, char const * entry, int number);\n\t\tbool Put_Int(char const * section, char const * entry, int number, int format=0);\n\t\tbool Put_Bool(char const * section, char const * entry, bool value);\n\t\tbool Put_TextBlock(char const * section, char const * text);\n\t\tbool Put_UUBlock(char const * section, void const * block, int len);\n\t\tbool Put_PKey(PKey const & key);\n\n\tprotected:\n\t\tenum {MAX_LINE_LENGTH=128};\n\n\t\t/*\n\t\t**\tThe value entries for the INI file are stored as objects of this type.\n\t\t**\tThe entry identifier and value string are combined into this object.\n\t\t*/\n\t\tstruct INIEntry : Node<INIEntry> {\n\t\t\tINIEntry(char * entry = 0, char * value = 0) : Entry(entry), Value(value) {}\n\t\t\t~INIEntry(void) {free(Entry);Entry = 0;free(Value);Value = 0;}\n\t\t\tint Index_ID(void) const {return(CRCEngine()(Entry, strlen(Entry)));};\n\n\t\t\tchar * Entry;\n\t\t\tchar * Value;\n\t\t};\n\n\t\t/*\n\t\t**\tEach section (bracketed) is represented by an object of this type. All entries\n\t\t**\tsubordinate to this section are attached.\n\t\t*/\n\t\tstruct INISection : Node<INISection> {\n\t\t\tINISection(char * section) : Section(section) {}\n\t\t\t~INISection(void) {free(Section);Section = 0;EntryList.Delete();}\n\t\t\tINIEntry * Find_Entry(char const * entry) const;\n\t\t\tint Index_ID(void) const {return(CRCEngine()(Section, strlen(Section)));};\n\n\t\t\tchar * Section;\n\t\t\tList<INIEntry> EntryList;\n\t\t\tIndexClass<INIEntry *>EntryIndex;\n\t\t};\n\n\t\t/*\n\t\t**\tUtility routines to help find the appropriate section and entry objects.\n\t\t*/\n\t\tINISection * Find_Section(char const * section) const;\n\t\tINIEntry * Find_Entry(char const * section, char const * entry) const;\n\t\tstatic void Strip_Comments(char * buffer);\n\n\t\t/*\n\t\t**\tThis is the list of all sections within this INI file.\n\t\t*/\n\t\tList<INISection> SectionList;\n\n\t\tIndexClass<INISection *> SectionIndex;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/INIBIN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\inibin.cpv   4.40   04 Jul 1996 16:14:52   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***             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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INIBIN.CPP                                                   *\n *                                                                                             *\n *                   Programmer : David R. Dettmer                                             *\n *                                                                                             *\n *                   Start Date : October 20, 1995                                             *\n *                                                                                             *\n *                  Last Update : November 7, 1995   [DRD]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n"
  },
  {
    "path": "CODE/INICODE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\inicode.cpv   4.38   03 Jul 1996 05:14:04   JOE_BOSTIC  $ */\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : INICODE.CPP                              *\n *                                                                         *\n *                   Programmer : David R Dettmer                          *\n *                                                                         *\n *                   Start Date : November 7, 1995                         *\n *                                                                         *\n *                  Last Update : February 20, 1996 [JLB]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n#ifdef TOFIX\n\nvoid Get_Scenario_Digest(char * digest, char * buffer)\n{\n\tchar buf[128];\t// Working string staging buffer.\n\tchar stage[sizeof(BigInt)*2];\n\n\tchar * stage_ptr = &stage[0];\n\tint len = strlen(buffer) + 2;\n\tchar * tbuffer = buffer + len;\n\n\tWWGetPrivateProfileString(\"DIGEST\", NULL, NULL, tbuffer, sizeof(_staging_buffer)-len, buffer);\n\tstage[0] = '\\0';\n\twhile (*tbuffer != '\\0') {\n\n\t\tWWGetPrivateProfileString(\"DIGEST\", tbuffer, NULL, buf, sizeof(buf)-1, buffer);\n\t\tstrcat(stage, buf);\n\t\ttbuffer += strlen(tbuffer)+1;\n\t}\n\n\tlen = strlen(stage);\n\tchar * dbuffer = &stage[0];\n\ttbuffer = &stage[0];\n\tfor (int index = 0; index < len/2; index++) {\n\t\tint c;\n\t\tif (isdigit(*tbuffer)) {\n\t\t\tc = (*tbuffer) - '0';\n\t\t} else {\n\t\t\tc = 10 + (toupper(*tbuffer) - 'A');\n\t\t}\n\t\ttbuffer++;\n\t\tc <<= 4;\n\t\tif (isdigit(*tbuffer)) {\n\t\t\tc |= (*tbuffer) - '0';\n\t\t} else {\n\t\t\tc |= 10 + (toupper(*tbuffer) - 'A');\n\t\t}\n\t\ttbuffer++;\n\t\t*dbuffer++ = c;\n\t}\n\n\t/*\n\t**\tDecode and decrypt the number.\n\t*/\n\tBigInt hash = 0;\n\thash.DERDecode((unsigned char*)stage);\n\n\tBigInt d;\n\td = d.Decode_ASCII(KEY_D);\n\tBigInt n;\n\tn = n.Decode_ASCII(KEY_N);\n\n\thash = hash.exp_b_mod_c(d, n);\n\n\tmemcpy(digest, &hash, 20);\n\n\tbuffer = strstr(buffer, \"[DIGEST]\");\n\tif (buffer) {\n\t\t*buffer = '\\0';\n\t}\n}\n\n\nbool Read_Scenario_INI_Write_INB( char *root, bool fresh)\n{\n\tchar *buffer;\t\t\t\t// Scenario.ini staging buffer pointer.\n\tchar *binbuf;\t\t\t\t// Scenario.inb staging buffer pointer.\n\tchar fname[_MAX_FNAME+_MAX_EXT];\t\t\t// full INI filename\n\tchar buf[256];\t\t\t\t// Working string staging buffer.\n\tchar scenarioname[40];\n\tint len;\n\tunsigned char val;\n\n\t/*\n\t**\tFetch working pointer to the INI staging buffer. Make sure that the buffer\n\t**\tis cleared out before proceeding.  (Don't use the HidPage for this, since\n\t**\tthe HidPage may be needed for various uncompressions during the INI\n\t**\tparsing.)\n\t*/\n\tbuffer = (char *)_staging_buffer;\n\tmemset(buffer, '\\0', sizeof(_staging_buffer));\n\n\t/*\n\t**\tCreate scenario filename and read the file.\n\t** The previous routine verifies that the file is available.\n\t*/\n\n\tsprintf(fname,\"%s.INI\",root);\n\tCCFileClass file(fname);\n\n\tfile.Read(buffer, sizeof(_staging_buffer)-1);\n\n\t/*\n\t**\tFetch and slice off any message digest attached.\n\t*/\n\tchar digest[20];\n\tGet_Scenario_Digest(digest, buffer);\n\n\tchar real_digest[20];\n\tSHAEngine digest_engine;\n\tdigest_engine.Hash(buffer, strlen(buffer));\n\tdigest_engine.Result(real_digest);\n\n\tif (memcmp(digest, real_digest, sizeof(real_digest)) != 0) {\n\t\tWWMessageBox().Process(TXT_SCENARIO_ERROR, TXT_OK);\n\t}\n\n\t/*\n\t** Init the Scenario CRC value\n\t*/\n\tScenarioCRC = 0;\n\tlen = strlen(buffer);\n\tfor (int i = 0; i < len; i++) {\n\t\tval = (unsigned char)buffer[i];\n\t\tAdd_CRC(&ScenarioCRC, (unsigned long)val);\n\t}\n\n\tsprintf(fname,\"%s.INB\",root);\n\tfile.Set_Name(fname);\n\tfile.Cache(16384);\n\tfile.Open(WRITE);\n\n\tunsigned long crc = Ini_Binary_Version();\n\n\tfile.Write( (char *)&crc, sizeof(crc) );\n\n\tbinbuf = (char *)Alloc( sizeof(_staging_buffer), MEM_NORMAL );\n\n\tif (binbuf) {\n\t\tWrite_Bin_Init( binbuf, sizeof(_staging_buffer) );\n\t} else {\n\t\tPrint_Error_End_Exit( \"Unable to alloc space for writing INB\" );\n\t}\n\n\t/*\n\t**\tFetch the appropriate movie names from the INI file.\n\t*/\n\tWWGetPrivateProfileString(\"Basic\", \"Name\", \"\", scenarioname, sizeof(scenarioname), buffer);\n\tWWGetPrivateProfileString(\"Basic\", \"Intro\", \"x\", Scen.IntroMovie, sizeof(Scen.IntroMovie), buffer);\n\tWWGetPrivateProfileString(\"Basic\", \"Brief\", \"x\", Scen.BriefMovie, sizeof(Scen.BriefMovie), buffer);\n\tWWGetPrivateProfileString(\"Basic\", \"Win\", \"x\", Scen.WinMovie, sizeof(Scen.WinMovie), buffer);\n\tWWGetPrivateProfileString(\"Basic\", \"Lose\", \"x\", Scen.LoseMovie, sizeof(Scen.LoseMovie), buffer);\n\tWWGetPrivateProfileString(\"Basic\", \"Action\", \"x\", Scen.ActionMovie, sizeof(Scen.ActionMovie), buffer);\n\tScen.IsToCarryOver = WWGetPrivateProfileInt(\"Basic\", \"ToCarryOver\", 0, buffer);\n\tScen.IsToInherit = WWGetPrivateProfileInt(\"Basic\", \"ToInherit\", 0, buffer);\n\n\tWrite_Bin_String( scenarioname, strlen(scenarioname), binbuf );\n\tWrite_Bin_String( Scen.IntroMovie, strlen(Scen.IntroMovie), binbuf );\n\tWrite_Bin_String( Scen.BriefMovie, strlen(Scen.BriefMovie), binbuf );\n\tWrite_Bin_String( Scen.WinMovie, strlen(Scen.WinMovie), binbuf );\n\tWrite_Bin_String( Scen.LoseMovie, strlen(Scen.LoseMovie), binbuf );\n\tWrite_Bin_String( Scen.ActionMovie, strlen(Scen.ActionMovie), binbuf );\n\n\t/*\n\t**\tFetch the transition theme for this scenario.\n\t*/\n\tScen.TransitTheme = THEME_NONE;\n\tWWGetPrivateProfileString(\"Basic\", \"Theme\", \"No Theme\", buf, sizeof(buf), buffer);\n\tScen.TransitTheme = Theme.From_Name(buf);\n\n\tWWGetPrivateProfileString( \"Basic\", \"Player\", \"Greece\", buf, 127, buffer);\n\tScen.PlayerHouse = HouseTypeClass::From_Name(buf);\n\tif (Scen.PlayerHouse >= HOUSE_MULTI1) {\n\t\tScen.PlayerHouse = HOUSE_GREECE;\n\t}\n// TCTC To Fix?\n//\tScen.CarryOverPercent = WWGetPrivateProfileInt( \"Basic\", \"CarryOverMoney\", 100, buffer);\n\tScen.CarryOverCap = WWGetPrivateProfileInt( \"Basic\", \"CarryOverCap\", -1, buffer);\n\tScen.Percent = WWGetPrivateProfileInt( \"Basic\", \"Percent\", 0, buffer);\n\n\tWrite_Bin_Num( &Scen.TransitTheme, sizeof(Scen.TransitTheme), binbuf );\n\tWrite_Bin_Num( &Scen.PlayerHouse, sizeof(Scen.PlayerHouse), binbuf );\n\tWrite_Bin_Num( &Scen.CarryOverPercent, 1, binbuf );\n\tWrite_Bin_Num( &Scen.CarryOverCap, 2, binbuf );\n\tWrite_Bin_Num( &Scen.Percent, 1, binbuf );\n\n\t/*\n\t**\tRead in the specific information for each of the house types.  This creates\n\t**\tthe houses of different types.\n\t*/\n\tHouseClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in the team-type data. The team types must be created before any\n\t**\ttriggers can be created.\n\t*/\n\tTeamTypeClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tAssign PlayerPtr by reading the player's house from the INI;\n\t**\tMust be done before any TechnoClass objects are created.\n\t*/\n\tif (Session.Type == GAME_NORMAL) {\n\t\tScen.CarryOverPercent = Cardinal_To_Fixed(100, Scen.CarryOverPercent);\n\n\t\tPlayerPtr = HouseClass::As_Pointer( Scen.PlayerHouse );\n\t\tassert(PlayerPtr != NULL);\n\t\tPlayerPtr->IsHuman = true;\n\n\t\tint carryover;\n\t\tif (Scen.CarryOverCap != -1) {\n\t\t\tcarryover = MIN(Fixed_To_Cardinal(Scen.CarryOverMoney, Scen.CarryOverPercent), (Scen.CarryOverCap * 100) );\n\t\t} else {\n\t\t\tcarryover = Fixed_To_Cardinal(Scen.CarryOverMoney, Scen.CarryOverPercent);\n\t\t}\n\t\tPlayerPtr->Credits += carryover;\n\t\tPlayerPtr->Control.InitialCredits += carryover;\n\t} else {\n\n\t\tAssign_Houses();\n\t}\n\n\t/*\n\t**\tRead in the trigger data. The triggers must be created before any other\n\t**\tobjects can be initialized.\n\t*/\n\tTriggerClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in the map control values. This includes dimensions\n\t**\tas well as theater information.\n\t*/\n\tMap.Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tAttempt to read the map's binary image file; if fails, read the\n\t**\ttemplate data from the INI, for backward compatibility\n\t*/\n\tif (fresh) {\n\t\tif (!Map.Read_Binary(root, &ScenarioCRC)) {\n\t\t\treturn( false );\n\t\t}\n\t}\n\tCall_Back();\n\n\t/*\n\t**\tRead in and place the 3D terrain objects.\n\t*/\n\tTerrainClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in and place the units (all sides).\n\t*/\n\tUnitClass::Read_INI(buffer);\n\tCall_Back();\n\n\tVesselClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in and place the infantry units (all sides).\n\t*/\n\tInfantryClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in and place all the buildings on the map.\n\t*/\n\tBuildingClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in the AI's base information.\n\t*/\n\tBase.Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in any normal overlay objects.\n\t*/\n\tOverlayClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in any smudge overlays.\n\t*/\n\tSmudgeClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in any briefing text.\n\t*/\n\tchar * stage = &Scen.BriefingText[0];\n\t*stage = '\\0';\n\tint index = 1;\n\n\t/*\n\t**\tBuild the full text of the mission objective.\n\t*/\n\tfor (;;) {\n\t\tchar buff[16];\n\n\t\tsprintf(buff, \"%d\", index++);\n\t\t*stage = '\\0';\n\t\tWWGetPrivateProfileString(\"Briefing\", buff, \"\", stage, 255, buffer);\n\t\tif (strlen(stage) == 0) break;\n\t\tstrcat(stage, \" \");\n\t\tstage += strlen(stage);\n\t}\n\n\tlen = Write_Bin_Length( binbuf );\n\tif (len != -1) {\n\t\tfile.Write( binbuf, len );\n\t}\n\n\tFree( binbuf );\n\tfile.Close();\n\n\treturn(true);\n}\n\n#endif\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "CODE/INIT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/INIT.CPP 8     3/14/97 5:15p Joe_b $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INIT.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : January 20, 1992                                             *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Anim_Init -- Initialize the VQ animation control structure.                               *\n *   Bootstrap -- Perform the initial bootstrap procedure.                                     *\n *   Calculate_CRC -- Calculates a one-way hash from a data block.                             *\n *   Init_Authorization -- Verifies that the player is authorized to play the game.            *\n *   Init_Bootstrap_Mixfiles -- Registers and caches any mixfiles needed for bootstrapping.    *\n *   Init_Bulk_Data -- Initialize the time-consuming mixfile caching.                          *\n *   Init_CDROM_Access -- Initialize the CD-ROM access handler.                                *\n *   Init_Color_Remaps -- Initialize the text remap tables.                                    *\n *   Init_Expansion_Files -- Fetch any override expansion mixfiles.                            *\n *   Init_Fonts -- Initialize all the game font pointers.                                      *\n *   Init_Game -- Main game initialization routine.                                            *\n *   Init_Heaps -- Initialize the game heaps and buffers.                                      *\n *   Init_Keys -- Initialize the cryptographic keys.                                           *\n *   Init_Mouse -- Initialize the mouse system.                                                *\n *   Init_One_Time_Systems -- Initialize internal pointers to the bulk data.                   *\n *   Init_Random -- Initializes the random-number generator                                    *\n *   Init_Secondary_Mixfiles -- Register and cache secondary mixfiles.                         *\n *   Load_Recording_Values -- Loads recording values from recording file                       *\n *   Load_Title_Page -- Load the background art for the title page.                            *\n *   Obfuscate -- Sufficiently transform parameter to thwart casual hackers.                   *\n *   Parse_Command_Line -- Parses the command line parameters.                                 *\n *   Parse_INI_File -- Parses CONQUER.INI for special options                                  *\n *   Play_Intro -- plays the introduction & logo movies                                        *\n *   Save_Recording_Values -- Saves recording values to a recording file                       *\n *   Select_Game -- The game's main menu                                                       *\n *   Load_Prolog_Page -- Loads the special pre-prolog \"please wait\" page.                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"loaddlg.h\"\n#ifdef WIN32\n#ifdef WINSOCK_IPX\n#include\t\"WSProto.h\"\n#include\t\"WSPUDP.h\"\n#include\t\"WSPIPX.h\"\n#include\t\"internet.h\"\n#else\t//WINSOCK_IPX\n#include\t\"tcpip.h\"\n#endif\t//WINSOCK_IPX\n\n#endif\n#include\t<conio.h>\n#include\t<dos.h>\n#ifndef WIN32\n#include\t<sys\\timeb.h>\n#endif\n#include  \"ccdde.h\"\n\n#include <time.h>\n\n#ifdef DONGLE\n#include \"cbn_.h\"\n#endif\n\n#ifdef MPEGMOVIE // Denzil 6/25/98\n#include \"mpgset.h\"\n#endif\n\nRemapControlType SidebarScheme;\n\n#include \"WolDebug.h\"\n\n#ifdef CHEAT_KEYS\nextern bool bNoMovies;\n#endif\n\n/****************************************\n**\tFunction prototypes for this module **\n*****************************************/\nstatic void Play_Intro(bool sequenced=false);\nstatic void Init_Color_Remaps(void);\nstatic void Init_Heaps(void);\nstatic void Init_Expansion_Files(void);\nstatic void Init_One_Time_Systems(void);\nstatic void Init_Fonts(void);\nstatic void Init_CDROM_Access(void);\nstatic void Init_Bootstrap_Mixfiles(void);\nstatic void Init_Secondary_Mixfiles(void);\nstatic void Init_Mouse(void);\nstatic void Bootstrap(void);\n//static void Init_Authorization(void);\nstatic void Init_Bulk_Data(void);\nstatic void Init_Keys(void);\n\nextern int UnitBuildPenalty;\n\nextern \"C\" {\nextern long RandNumb;\n}\n#ifndef WIN32\nstatic int UsePageFaultHandler = 1;\t\t\t\t// 1 = install PFH\n#endif\t//WIN32\n\n//extern int SimRandIndex;\nvoid Init_Random(void);\n\n#define ATTRACT_MODE_TIMEOUT\t3600\t\t// timeout for attract mode\n\nbool Load_Recording_Values(CCFileClass & file);\nbool Save_Recording_Values(CCFileClass & file);\n\n#ifdef WOLAPI_INTEGRATION\nextern int WOL_Main();\n#include \"WolapiOb.h\"\nextern WolapiObject* pWolapi;\n#endif\n\n#ifdef FIXIT_VERSION_3\nbool Expansion_Dialog( bool bCounterstrike );\n#endif\n\nextern bool Is_Mission_Counterstrike (char *file_name);\n\n/***********************************************************************************************\n * Load_Prolog_Page -- Loads the special pre-prolog \"please wait\" page.                        *\n *                                                                                             *\n *    This loads and displays the prolog page that is displayed before the prolog movie        *\n *    is played. This page is necessary because there is much loading that occurs before       *\n *    the prolog movie is played and looking at a picture is better than looking at a blank    *\n *    screen.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Load_Prolog_Page(void)\n{\n\tHide_Mouse();\n#ifdef WIN32\n\tLoad_Title_Screen(\"PROLOG.PCX\", &HidPage, CCPalette);\n\tHidPage.Blit(SeenPage);\n#else\n\tLoad_Picture(\"PROLOG.CPS\", HidPage, HidPage, CCPalette, BM_DEFAULT);\n\tHidPage.Blit(SeenPage);\n#endif\n\tCCPalette.Set();\n\tShow_Mouse();\n}\n\n\n/***********************************************************************************************\n * Init_Game -- Main game initialization routine.                                              *\n *                                                                                             *\n *    Perform all one-time game initializations here. This includes all                        *\n *    allocations and table setups. The intro and other one-time startup                       *\n *    tasks are also performed here.                                                           *\n *                                                                                             *\n * INPUT:   argc,argv   -- Command line arguments.                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this ONCE!                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\n#include\t\"sha.h\"\n//#include    <locale.h>\nbool Init_Game(int , char * [])\n{\n\t/*\n\t**\tAllocate the benchmark tracking objects only if the machine and\n\t**\tcompile flags indicate.\n\t*/\n\t#ifdef CHEAT_KEYS\n\tif (Processor() >= 2) {\n\t\tBenches = new Benchmark [BENCH_COUNT];\n\t}\n\t#endif\n\n\t/*\n\t**\tInitialize the encryption keys.\n\t*/\n\tInit_Keys();\n\n\t/*\n\t**\tBootstrap as much as possible before error-prone initializations are\n\t**\tperformed. This bootstrap process will enable the error message\n\t**\thandler to function.\n\t*/\n\tBootstrap();\n\n\t/*\n\t**\tCheck for an initialize a working mouse pointer. Display error and bail if\n\t**\tno mouse driver is installed.\n\t*/\n\tInit_Mouse();\n\n\t/*\n\t**\tInitialize access to the CD-ROM and ensure that the CD is inserted. This can, and\n\t**\tmost likely will, result in a visible prompt.\n\t*/\n\tInit_CDROM_Access();\n\n\tif (Special.IsFromInstall) {\n\t\tLoad_Prolog_Page();\n\t}\n\n\t/*\n\t**\tRegister and cache any secondary mixfiles.\n\t*/\n\tInit_Secondary_Mixfiles();\n\n\t/*\n\t**\tThis is a special hack to initialize the heaps that must be in place before the\n\t**\trules file is processed. These heaps should properly be allocated as a consequence\n\t**\tof processing the rules.ini file, but that is a bit beyond the capabilities of\n\t**\tthe rule parser routine (currently).\n\t*/\n\tHouseTypes.Set_Heap(HOUSE_COUNT);\n\tBuildingTypes.Set_Heap(STRUCT_COUNT);\n\tAircraftTypes.Set_Heap(AIRCRAFT_COUNT);\n\tInfantryTypes.Set_Heap(INFANTRY_COUNT);\n\tBulletTypes.Set_Heap(BULLET_COUNT);\n\tAnimTypes.Set_Heap(ANIM_COUNT);\n\tUnitTypes.Set_Heap(UNIT_COUNT);\n\tVesselTypes.Set_Heap(VESSEL_COUNT);\n\tTemplateTypes.Set_Heap(TEMPLATE_COUNT);\n\tTerrainTypes.Set_Heap(TERRAIN_COUNT);\n\tOverlayTypes.Set_Heap(OVERLAY_COUNT);\n\tSmudgeTypes.Set_Heap(SMUDGE_COUNT);\n\n\tHouseTypeClass::Init_Heap();\n\tBuildingTypeClass::Init_Heap();\n\tAircraftTypeClass::Init_Heap();\n\tInfantryTypeClass::Init_Heap();\n\tBulletTypeClass::Init_Heap();\n\tAnimTypeClass::Init_Heap();\n\tUnitTypeClass::Init_Heap();\n\tVesselTypeClass::Init_Heap();\n\tTemplateTypeClass::Init_Heap();\n\tTerrainTypeClass::Init_Heap();\n\tOverlayTypeClass::Init_Heap();\n\tSmudgeTypeClass::Init_Heap();\n\n\t/*\n\t**\tFind and process any rules for this game.\n\t*/\n\tif (RuleINI.Load(CCFileClass(\"RULES.INI\"), false)) {\n\t\tRule.Process(RuleINI);\n\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t//  Aftermath runtime change 9/29/98\n\t//\tThis is safe to do, as only rules for aftermath units are included in this ini.\n\tif (Is_Aftermath_Installed() == true) {\n\t\tif (AftermathINI.Load(CCFileClass(\"AFTRMATH.INI\"), false)) {\n\t\t\tRule.Process(AftermathINI);\n\t\t}\n\t}\n#endif\n\n\tSession.MaxPlayers = Rule.MaxPlayers;\n\n\t/*\n\t**\tInitialize the game object heaps as well as other rules-dependant buffer allocations.\n\t*/\n\tInit_Heaps();\n\n\t/*\n\t**\tInitialize the animation system.\n\t*/\n\tAnim_Init();\n\n#ifndef FIXIT_VERSION_3\t\t\t//\tWChat eliminated.\n#ifdef WIN32\n\tif (SpawnedFromWChat){\n\t\tSpecial.IsFromWChat = true;\n\t}\n#endif\n#endif\n\n\t#ifdef MPEGMOVIE // Denzil 6/15/98\n\tif( Using_DVD() )\n\t{\n\t\t#ifdef MCIMPEG\n\t\tMciMovie = new MCIMovie(MainWindow);\n\t\t#endif\n\t\tMpgSettings = new MPGSettings(NULL); //RawFileClass(CONFIG_FILE_NAME));\n\t}\n\t#endif\n\n\t/*\n\t**\tPlay the startup animation.\n\t*/\n\tif (!Special.IsFromInstall && !Special.IsFromWChat) {\n\t\tVisiblePage.Clear();\n//\t\tMono_Printf(\"Playing Intro\\n\");\n\t\tPlay_Intro();\n\t\tmemset(CurrentPalette, 0x01, 768);\n\t\tWhitePalette.Set();\n\t} else {\n\t\tmemset(CurrentPalette, 0x01, 768);\n\t}\n\n\t/*\n\t**\tInitialize the text remap tables.\n\t*/\n\tInit_Color_Remaps();\n\n\t/*\n\t**\tGet authorization to access the game.\n\t*/\n//\tInit_Authorization();\n//\tShow_Mouse();\n\n\t/*\n\t**\tSet the logic page to the seenpage.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tIf not automatically launching into the intro, then display the title\n\t**\tpage while the bulk data is cached.\n\t*/\n\tif (!Special.IsFromInstall) {\n\t\tLoad_Title_Page(true);\n\n\t\tHide_Mouse();\n\t\tFancy_Text_Print(TXT_STAND_BY, 160*RESFACTOR, 120*RESFACTOR, &ColorRemaps[PCOLOR_DIALOG_BLUE], TBLACK, TPF_CENTER|TPF_TEXT|TPF_DROPSHADOW);\n\t\tShow_Mouse();\n\n\t\tCCPalette.Set(FADE_PALETTE_SLOW);\n\t\tCall_Back();\n\t}\n\n\t/*\n\t**\tInitialize the bulk data. This takes the longest time and must be performed once\n\t**\tbefore the regular game starts.\n\t*/\n\tInit_Bulk_Data();\n\n\t/*\n\t**\tInitialize the multiplayer score values\n\t*/\n\tSession.GamesPlayed = 0;\n\tSession.NumScores = 0;\n\tSession.CurGame = 0;\n\tfor (int i = 0; i < MAX_MULTI_NAMES; i++) {\n\t\tSession.Score[i].Name[0] = '\\0';\n\t\tSession.Score[i].Wins = 0;\n\t\tfor (int j = 0; j < MAX_MULTI_GAMES; j++) {\n\t\t\tSession.Score[i].Kills[j] = -1;\t// -1 = this player didn't play this round\n\t\t}\n\t}\n\n\t/*\n\t** Copy the title screen's palette into the GamePalette & OriginalPalette,\n\t** because the options Load routine uses these palettes to set the brightness, etc.\n\t*/\n\tGamePalette = CCPalette;\n//\tInGamePalette = CCPalette;\n\tOriginalPalette = CCPalette;\n\n\t/*\n\t**\tRead game options, so the GameSpeed is initialized when multiplayer\n\t** dialogs are invoked.  (GameSpeed must be synchronized between systems.)\n\t*/\n\tOptions.Load_Settings();\n\n\treturn(true);\n}\n\n#ifdef WINSOCK_IPX\t\t\t//\tSteve Tall missed this one - ajw\nextern bool Get_Broadcast_Addresses (void);\n#endif\n\n/***********************************************************************************************\n * Select_Game -- The game's main menu                                                         *\n *                                                                                             *\n * INPUT:                                                                                      *\n *\t\tfade\t\tif true, will fade the palette in gradually\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/05/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nbool Select_Game(bool fade)\n{\n\t//\tEnums in Select_Game() must match order of buttons in Main_Menu().\n#ifdef FIXIT_VERSION_3\n\tenum {\n\t\tSEL_TIMEOUT = -1,\t\t\t\t// main menu timeout--go into attract mode\n\t\tSEL_NEW_SCENARIO_CS,\t\t\t\t// Expansion scenario to play.\n\t\tSEL_NEW_SCENARIO_AM,\t\t\t\t// Expansion scenario to play.\n\t\tSEL_START_NEW_GAME,\t\t\t// start a new game\n\t\tSEL_LOAD_MISSION,\t\t\t\t// load a saved game\n\t\tSEL_MULTIPLAYER_GAME,\t\t// play modem/null-modem/network game\n\t\tSEL_INTRO,\t\t\t\t\t\t// couch-potato mode\n\t\tSEL_EXIT,\t\t\t\t\t\t// exit to DOS\n\t\tSEL_FAME,\t\t\t\t\t\t// view the hall o' fame\n\t\tSEL_NONE,\t\t\t\t\t\t// placeholder default value\n\t};\n#else\t//\tFIXIT_VERSION_3\n\tenum {\n\t\tSEL_TIMEOUT = -1,\t\t\t\t// main menu timeout--go into attract mode\n\t\tSEL_NEW_SCENARIO,\t\t\t\t// Expansion scenario to play.\n\t\tSEL_START_NEW_GAME,\t\t\t// start a new game\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - Internet play\n\t\tSEL_INTERNET,\n#endif\t//WIN32\n//#if defined(MPEGMOVIE) // Denzil 6/25/98\n//\t\tSEL_MOVIESETTINGS,\n//#endif\n\t\tSEL_LOAD_MISSION,\t\t\t\t// load a saved game\n\t\tSEL_MULTIPLAYER_GAME,\t\t// play modem/null-modem/network game\n\t\tSEL_INTRO,\t\t\t\t\t\t// couch-potato mode\n\t\tSEL_EXIT,\t\t\t\t\t\t// exit to DOS\n\t\tSEL_FAME,\t\t\t\t\t\t// view the hall o' fame\n\t\tSEL_NONE,\t\t\t\t\t\t// placeholder default value\n\t};\n#endif\t//\tFIXIT_VERSION_3\n\n\tbool gameloaded=false;\t\t\t// Has the game been loaded from the menu?\n\tint selection;\t\t\t\t\t\t// the default selection\n\tbool process = true;\t\t\t\t// false = break out of while loop\n\tbool display = true;\n\n#ifdef DONGLE\n\t/* These where added by ColinM for the dongle checking */\n\tshort iRet = 0;\n\tunsigned short iPortNr = 1;  /* automatic port scan enabled */\n\tunsigned char cSCodeSER[] = \"\\x41\\x42\";\n\tunsigned long ulIdRet = 0;\n\tunsigned char cBoxName[]= \"\\x00\\x00\";\n#endif\n\t\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tint cdcheck = 0;\n\tbool cs = Is_Counterstrike_Installed();\n#endif\n\n//\t#ifndef DVD // Denzil - We want the menu screen\t\t\tajw No we don't\n//\tif (Special.IsFromInstall) {\n//\t\tdisplay = false;\n//\t}\n//\t#endif\n\n\tShow_Mouse();\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tNewUnitsEnabled = SecretUnitsEnabled = 0;\t// Assume new units disabled, unless specifically .INI enabled or multiplayer negotiations enable it.\n#endif\n\n#ifndef WOLAPI_INTEGRATION\n#ifdef WIN32\n\t/*\n\t** Enable the DDE Server so we can get internet start game packets from WChat\n\t*/\n\tDDEServer.Enable();\n#endif\t//WIN32\n#endif\t//\t!WOLAPI_INTEGRATION\n\n\t/*\n\t**\t[Re]set any globals that need it, in preparation for a new scenario\n\t*/\n\tGameActive = true;\n\tDoList.Init();\n\t#ifdef MIRROR_QUEUE\n\tMirrorList.Init();\n\t#endif\n\tOutList.Init();\n\tFrame = 0;\n\tScen.MissionTimer = 0;\n\tScen.MissionTimer.Stop();\n\tScen.CDifficulty = DIFF_NORMAL;\n\tScen.Difficulty = DIFF_NORMAL;\n\tPlayerWins = false;\n\tPlayerLoses = false;\n\tSession.ObiWan = false;\n\tDebug_Unshroud = false;\n\tMap.Set_Cursor_Shape(0);\n\tMap.PendingObjectPtr = 0;\n\tMap.PendingObject = 0;\n\tMap.PendingHouse = HOUSE_NONE;\n\n\tSession.ProcessTicks = 0;\n\tSession.ProcessFrames = 0;\n\tSession.DesiredFrameRate = 30;\n#if(TIMING_FIX)\n\tNewMaxAheadFrame1 = 0;\n\tNewMaxAheadFrame2 = 0;\n#endif\n\n/* ColinM added to check for dongle */\n#ifdef DONGLE\n\tiRet = CbN_BoxReady( iPortNr , cBoxName);\n\tif (cBoxName[0] != 0xc5 && cBoxName[0] != 0xc9) \n\t{\n\tWWMessageBox().Process(\"Please ensure dongle is attached. Run the dongle batch file too.\", TXT_OK);\n\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t}\n\n\tiRet = CbN_ReadSER( iPortNr, cSCodeSER, &ulIdRet);\n\tif (ulIdRet != 0xa0095)\n\t{\n\tWWMessageBox().Process(\"Please ensure dongle is attached. Run the dongle batch file too.\", TXT_OK);\n\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t}\n#endif\n\n\t/*\n\t**\tInit multiplayer game scores.  Let Wins accumulate; just init the current\n\t** Kills for this game.  Kills of -1 means this player didn't play this round.\n\t*/\n\tfor (int i = 0 ; i < MAX_MULTI_GAMES; i++) {\n\t\tSession.Score[i].Kills[Session.CurGame] = -1;\n\t}\n\n\t/*\n\t**\tSet default mouse shape\n\t*/\n\tMap.Set_Default_Mouse(MOUSE_NORMAL, false);\n\n\t/*\n\t**\tIf the last game we played was a multiplayer game, jump right to that\n\t**\tmenu by pre-setting 'selection'.\n\t*/\n\tif (Session.Type == GAME_NORMAL) {\n\t\tselection = SEL_NONE;\n\t} else {\n\t\tselection = SEL_MULTIPLAYER_GAME;\n\t}\n\n\t/*\n\t**\tMain menu processing; only do this if we're not in editor mode.\n\t*/\n\tif (!Debug_Map) {\n\n\t\t/*\n\t\t**\tMenu selection processing loop\n\t\t*/\n\t\tTheme.Queue_Song(THEME_CRUS);\n\n\t\t/*\n\t\t** If we're playing back a recording, load all pertinent values & skip\n\t\t** the menu loop.  Hide the now-useless mouse pointer.\n\t\t*/\n\t\tif (Session.Play && Session.RecordFile.Is_Available()) {\n\t\t\tif (Session.RecordFile.Open(READ)) {\n\t\t\t\tLoad_Recording_Values(Session.RecordFile);\n\t\t\t\tprocess = false;\n\t\t\t\tTheme.Fade_Out();\n\t\t\t} else\n\t\t\t\tSession.Play = false;\n\t\t}\n\n#ifndef FIXIT_VERSION_3\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - Internet play\n\t\t/*\n\t\t** Handle case where we were spawned from Wchat\n\t\t*/\n\t\tif (SpawnedFromWChat) {\n\t\t\tSpecial.IsFromInstall = false;\t//Dont play intro if we were spawned from wchat\n\t\t\tselection = SEL_INTERNET;\n\t\t\tTheme.Queue_Song(THEME_QUIET);\n\t\t\tSession.Type = GAME_INTERNET;\n\t\t\tdisplay = false;\n\t\t\tSet_Logic_Page(SeenBuff);\n\t\t}\n#endif\t//WIN32\n#endif\n\n\t\twhile (process) {\n\n\t\t\t/*\n\t\t\t**\tRedraw the title page if needed\n\t\t\t*/\n\t\t\tif (display) {\n\t\t\t\tHide_Mouse();\n\n\t\t\t\t/*\n\t\t\t\t**\tDisplay the title page; fade it in if this is the first time\n\t\t\t\t**\tthrough the loop, and the 'fade' flag is true\n\t\t\t\t*/\n\t\t\t\tLoad_Title_Page();\n\t\t\t\tGamePalette = CCPalette;\n\n\t\t\t\tHidPage.Blit(SeenPage);\n//\t\t\t\tif (fade) {\n//\t\t\t\t\tWhitePalette.Set();\n//\t\t\t\t\tCCPalette.Set(FADE_PALETTE_SLOW, Call_Back);\n//\t\t\t\t\tfade = false;\n//\t\t\t\t} else {\n\t\t\t\t\tCCPalette.Set();\n//\t\t\t\t}\n\n\t\t\t\tSet_Logic_Page(SeenBuff);\n\t\t\t\tdisplay = false;\n\t\t\t\tShow_Mouse();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDisplay menu and fetch selection from player.\n\t\t\t*/\n\t\t\tif (Special.IsFromInstall) selection = SEL_START_NEW_GAME;\n\n#ifndef WOLAPI_INTEGRATION\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - Internet play\n\t\t\t/*\n\t\t\t** Handle case where we were spawned from Wchat and our start game\n\t\t\t**  packet has already arrived\n\t\t\t*/\n\t\t\tif (Special.IsFromWChat && DDEServer.Get_MPlayer_Game_Info()) {\n\t\t\t\tCheck_From_WChat(NULL);\n\t\t\t\tselection = SEL_MULTIPLAYER_GAME;\n\t\t\t\tTheme.Queue_Song(THEME_QUIET);\n\t\t\t\tSession.Type = GAME_INTERNET;\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t** We werent spawned but we could still receive a DDE packet from wchat\n\t\t\t\t*/\n\t\t\t\tif (DDEServer.Get_MPlayer_Game_Info()) {\n\t\t\t\t\tCheck_From_WChat(NULL);\n\t\t\t\t\t/*\n\t\t\t\t\t** Make sure top and bottom of screen are clear in 640x480 mode\n\t\t\t\t\t*/\n\t\t\t\t\tif (ScreenHeight == 480) {\n\t\t\t\t\t\tVisiblePage.Fill_Rect (0, 0, 639, 40, 0);\n\t\t\t\t\t\tVisiblePage.Fill_Rect (0, 440, 639, 479, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n#endif\t//WIN32\n#endif\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\tif( pWolapi )\n\t\t\t\tselection =\tSEL_MULTIPLAYER_GAME;\t\t//\tWe are returning from a game.\n#endif\n\n\t\t\tif (selection == SEL_NONE) {\n#ifdef FIXIT_ANTS\n\t\t\t\tAntsEnabled = false;\n#endif\n\t\t\t\tselection = Main_Menu(ATTRACT_MODE_TIMEOUT);\n\t\t\t}\n\t\t\tCall_Back();\n\n\t\t\tswitch (selection) {\n\n\t\t\t\t/*\n\t\t\t\t**\tPick an expansion scenario.\n\t\t\t\t*/\n#ifdef FIXIT_VERSION_3\n\t\t\t\tcase SEL_NEW_SCENARIO_CS:\n\t\t\t\tcase SEL_NEW_SCENARIO_AM:\n#else\t//\tFIXIT_VERSION_3\n\t\t\t\tcase SEL_NEW_SCENARIO:\n#endif\t//\tFIXIT_VERSION_3\n\t\t\t\t\tScen.CarryOverMoney = 0;\n\t\t\t\t\tIsTanyaDead = false;\n\t\t\t\t\tSaveTanya = false;\n\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\tif( selection == SEL_NEW_SCENARIO_CS )\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!Force_CD_Available(2)) {\n\t\t\t\t\t\t   selection = SEL_NONE;\n\t\t\t\t\t\t   break;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(!Expansion_Dialog( true )){\n\t\t\t\t\t\t   selection = SEL_NONE;\n\t\t\t\t\t\t   break;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!Force_CD_Available(3)) {\n\t\t\t\t\t\t   selection = SEL_NONE;\n\t\t\t\t\t\t   break;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(!Expansion_Dialog( false )){\n\t\t\t\t\t\t   selection = SEL_NONE;\n\t\t\t\t\t\t   break;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n#else\t//\tFIXIT_VERSION_3\n\t#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\tif (cs) {\n\t\t\t\t\t\tcdcheck = 2;\n\t\t\t\t\t}\n\t\t\t\t\tif (Is_Aftermath_Installed()) {\n\t\t\t\t\t\tif (!cdcheck) {\n\t\t\t\t\t\t\tcdcheck = 3;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcdcheck = 4;\t// special case: means check for 3 or 4\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif(!Force_CD_Available(cdcheck)) {\n\t\t\t\t\t   return(false);\n\t\t\t\t\t}\n\t#else\n\t\t\t\t\tif(!Force_CD_Available(2)) {\n\t\t\t\t\t   return(false);\n\t\t\t\t\t}\n\t#endif\n\t\t\t\t\tif(!Expansion_Dialog()){\n\t\t\t\t\t   selection = SEL_NONE;\n\t\t\t\t\t   break;\n\t\t\t\t\t}\n#endif\t//\tFIXIT_VERSION_3\n\n#ifdef FIXIT_DIFFICULTY\n\t#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\tswitch (Fetch_Difficulty(cdcheck >= 3)) {\n\t#else\n\t\t\t\t\tswitch (Fetch_Difficulty()) {\n\t#endif\n\t\t \t\t\t\tcase 0:\n\t\t\t\t\t\t\tScen.CDifficulty = DIFF_HARD;\n\t\t\t\t\t\t\tScen.Difficulty = DIFF_EASY;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tScen.CDifficulty = DIFF_HARD;\n\t\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tScen.CDifficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tScen.CDifficulty = DIFF_EASY;\n\t\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\tScen.CDifficulty = DIFF_EASY;\n\t\t\t\t\t\t\tScen.Difficulty = DIFF_HARD;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n#endif\n\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\tTheme.Queue_Song(THEME_FIRST);\n\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tSEL_START_NEW_GAME: Play the game\n\t\t\t\t*/\n\t\t\t\tcase SEL_START_NEW_GAME:\n\t\t\t\t\tif (Special.IsFromInstall) {\n\t\t\t\t\t\tScen.CDifficulty = DIFF_NORMAL;\n\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tswitch (Fetch_Difficulty()) {\n\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\tScen.CDifficulty = DIFF_HARD;\n\t\t\t\t\t\t\t\tScen.Difficulty = DIFF_EASY;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\tScen.CDifficulty = DIFF_HARD;\n\t\t\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\tScen.CDifficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\tScen.CDifficulty = DIFF_EASY;\n\t\t\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\t\tScen.CDifficulty = DIFF_EASY;\n\t\t\t\t\t\t\t\tScen.Difficulty = DIFF_HARD;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tScen.CarryOverMoney = 0;\n\t\t\t\t\tBuildLevel = 10;\n\t\t\t\t\tIsTanyaDead = false;\n\t\t\t\t\tSaveTanya = false;\n\t\t\t\t\tWhom = HOUSE_GOOD;\n\n\t\t\t\t\tif (!Special.IsFromInstall) {\n#ifdef FIXIT_ANTS\n\t\t\t\t\t\tif (AntsEnabled)  {\n\t\t\t\t\t\t\tScen.Set_Scenario_Name(\"SCA01EA.INI\");\n\t\t\t\t\t\t} else {\n#endif\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\tswitch (WWMessageBox().Process(TXT_CHOOSE, TXT_ALLIES, TXT_CANCEL, TXT_SOVIET)) {\n\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t\tScen.Set_Scenario_Name(\"SCU01EA.INI\");\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t\tcontinue;\n#else\n\t\t\t\t\t\t\tswitch (WWMessageBox().Process(TXT_CHOOSE, TXT_ALLIES, TXT_SOVIET)) {\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\tScen.Set_Scenario_Name(\"SCU01EA.INI\");\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tdefault:\n#endif\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\tScen.Set_Scenario_Name(\"SCG01EA.INI\");\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t}\n#ifdef FIXIT_ANTS\n\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\tLoad_Title_Page();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tTheme.Fade_Out();\n#ifdef DVD // Denzil\t\t\tajw Presumably a bug fix.\n\t\t\t\t\t\tChoose_Side();\n\t\t\t\t\t\tHide_Mouse();\n#else\n\t\t\t\t\t\tHide_Mouse();\n\t\t\t\t\t\tChoose_Side();\n#endif\n\t\t\t\t\t\tif (CurrentCD == 0) {\n\t\t\t\t\t\t\tScen.Set_Scenario_Name(\"SCG01EA.INI\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tScen.Set_Scenario_Name(\"SCU01EA.INI\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n#ifndef FIXIT_VERSION_3\t\t\t//\tRemoved button from main menu.\n\t\t\t\t#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - Internet play\n\t\t\t\t/*\n\t\t\t\t** Internet game is requested\n\t\t\t\t*/\n\t\t\t\tcase SEL_INTERNET:\n\t\t\t\t\t/*\n\t\t\t\t\t** Only call up the internet menu code if we dont already have connect info from WChat\n\t\t\t\t\t*/\n\t\t\t\t\tif (!DDEServer.Get_MPlayer_Game_Info()) {\n\t\t\t\t\t\tif (Do_The_Internet_Menu_Thang() && DDEServer.Get_MPlayer_Game_Info()) {\n\t\t\t\t\t\t\tCheck_From_WChat(NULL);\n\t\t\t\t\t\t\tselection = SEL_MULTIPLAYER_GAME;\n\t\t\t\t\t\t\tdisplay = false;\n\t\t\t\t\t\t\tSession.Type = GAME_INTERNET;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCheck_From_WChat(NULL);\n\t\t\t\t\t\tdisplay = false;\n\t\t\t\t\t\tSession.Type = GAME_INTERNET;\n\t\t\t\t\t\tselection = SEL_MULTIPLAYER_GAME;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t#endif\t//WIN32\n#endif\n\n//\t\t\t\t#if defined(MPEGMOVIE) // Denzil 6/25/98\n//\t\t\t\tcase SEL_MOVIESETTINGS:\n//\t\t\t\t\tMpgSettings->Dialog();\n//\t\t\t\t\tdisplay = true;\n//\t\t\t\t\tselection = SEL_NONE;\n//\t\t\t\tbreak;\n//\t\t\t\t#endif\n\n\t\t\t\t/*\n\t\t\t\t**\tLoad a saved game.\n\t\t\t\t*/\n\t\t\t\tcase SEL_LOAD_MISSION:\n\t\t\t\t\tif (LoadOptionsClass(LoadOptionsClass::LOAD).Process()) {\n\t\t\t\t\t\tTheme.Queue_Song(THEME_FIRST);\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tgameloaded = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tSEL_MULTIPLAYER_GAME: set 'Session.Type' to NULL-modem, modem, or\n\t\t\t\t**\tnetwork play.\n\t\t\t\t*/\n\t\t\t\tcase SEL_MULTIPLAYER_GAME:\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\t\tif( !pWolapi )\n\t\t\t\t\t{\n#endif\n\t\t\t\t\tswitch (Session.Type) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf 'Session.Type' isn't already set up for a multiplayer game,\n\t\t\t\t\t\t**\twe must prompt the user for which type of multiplayer game\n\t\t\t\t\t\t**\tthey want.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase GAME_NORMAL:\n\t\t\t\t\t\t\tSession.Type = Select_MPlayer_Game();\n\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// 'Cancel'\n\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase GAME_SKIRMISH:\n\t\t\t\t\t\t\tif ( !Com_Scenario_Dialog(true) ) {\n\t\t\t\t\t\t\t\tSession.Type = Select_MPlayer_Game();\n\t\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// user hit Cancel\n\t\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t//\tEver hits? Session.Type set to GAME_SKIRMISH without user selecting in Select_MPlayer_Game()?\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\t//\tIf mission is Counterstrike, CS CD will be required. But aftermath units require AM CD.\n\t\t\t\t\t\t\t\tbAftermathMultiplayer = Is_Aftermath_Installed() && !Is_Mission_Counterstrike( Scen.ScenarioName );\n\t\t\t\t\t\t\t\t//\tajw I'll bet this was needed before also...\n\t\t\t\t\t\t\t\tSession.ScenarioIsOfficial = Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official();\n#endif\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase GAME_NULL_MODEM:\n\t\t\t\t\t\tcase GAME_MODEM:\n\t\t\t\t\t\t\tif ( Session.Type != GAME_SKIRMISH && NullModem.Num_Connections() ) {\n\t\t\t\t\t\t\t\tNullModem.Init_Send_Queue();\n\n\t\t\t\t\t\t\t\tif ((Session.Type == GAME_NULL_MODEM &&\n\t\t\t\t\t\t\t\t\tSession.ModemType == MODEM_NULL_HOST) ||\n\t\t\t\t\t\t\t\t\t(Session.Type == GAME_MODEM &&\n\t\t\t\t\t\t\t\t\tSession.ModemType == MODEM_DIALER) ) {\n\n\t\t\t\t\t\t\t\t\tif ( !Com_Scenario_Dialog() ) {\n\t\t\t\t\t\t\t\t\t\tSession.Type = Select_Serial_Dialog();\n\t\t\t\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// user hit Cancel\n\t\t\t\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tif ( !Com_Show_Scenario_Dialog() ) {\n\t\t\t\t\t\t\t\t\t\tSession.Type = Select_Serial_Dialog();\n\t\t\t\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// user hit Cancel\n\t\t\t\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tSession.Type = Select_MPlayer_Game();\n\t\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// 'Cancel'\n\t\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n#ifndef WOLAPI_INTEGRATION\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - Internet play\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Handle being spawned from WChat. Internet play based on IPX code.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase GAME_INTERNET:\t\t\t\t\t\t//\tajw\t\tNo longer hit.\n\t\t\t\t\t\t\tif (Special.IsFromWChat) {\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** Give myself focus.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tSetForegroundWindow ( MainWindow );\n\t\t\t\t\t\t\t\tShowWindow ( MainWindow, ShowCommand );\n\n#ifdef WINSOCK_IPX\n\n\t\t\t\t\t\t\t\tif (PacketTransport ) delete PacketTransport;\n\t\t\t\t\t\t\t\tPacketTransport = new UDPInterfaceClass;\n\t\t\t\t\t\t\t\tassert ( PacketTransport != NULL);\n\n\t\t\t\t\t\t\t\tif (PacketTransport->Init()) {\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to read multiplayer settings.\\n\");\n\t\t\t\t\t\t\t\t\tSession.Read_MultiPlayer_Settings ();\n\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to call Start_Server or Start_Client.\\n\");\n\t\t\t\t\t\t\t\t\tPacketTransport->Start_Listening();\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t** Flush out any pending packets from a previous game.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tPacketTransport->Discard_In_Buffers();\n\t\t\t\t\t\t\t\t\tPacketTransport->Discard_Out_Buffers();\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tdelete PacketTransport;\n\t\t\t\t\t\t\t\t\tPacketTransport = NULL;\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Winsock failed to initialise.\\n\");\n\t\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\t\tselection = SEL_EXIT;\n\t\t\t\t\t\t\t\t\tSpecial.IsFromWChat = false;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to call Init_Network.\\n\");\n\t\t\t\t\t\t\t\tInit_Network();\n\n\n#else\t//WINSOCK_IPX\n\n\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to initialise Winsock.\\n\");\n\t\t\t\t\t\t\t\tif (Winsock.Init()) {\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to read multiplayer settings.\\n\");\n\t\t\t\t\t\t\t\t\tSession.Read_MultiPlayer_Settings ();\n\t\t\t\t\t\t\t\t\tServer = PlanetWestwoodIsHost;\n\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to set addresses.\\n\");\n\t\t\t\t\t\t\t\t\tWinsock.Set_Host_Address(PlanetWestwoodIPAddress);\n\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to call Start_Server or Start_Client.\\n\");\n\t\t\t\t\t\t\t\t\tif (Server) {\n\t\t\t\t\t\t\t\t\t\tWinsock.Start_Server();\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tWinsock.Start_Client();\n\t\t\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t** Flush out any pending packets from a previous game.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to flush packet queue.\\n\");\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Allocating scrap memory.\\n\");\n\t\t\t\t\t\t\t\t\tchar *temp_buffer = new char[1024];\n\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Creating timer class instance.\\n\");\n\t\t\t\t\t\t\t\t\tCountDownTimerClass ptimer;\n\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Entering read loop.\\n\");\n\t\t\t\t\t\t\t\t\twhile (Winsock.Read(temp_buffer, 1024)) {\n\n\t\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Discarding a packet.\\n\");\n\t\t\t\t\t\t\t\t\t\tptimer.Set (30, true);\n\t\t\t\t\t\t\t\t\t\twhile (ptimer.Time()) {};\n\t\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Ready to check for more packets.\\n\");\n\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to delete scrap memory.\\n\");\n\t\t\t\t\t\t\t\t\tdelete temp_buffer;\n\n\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Winsock failed to initialise.\\n\");\n\t\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\t\tselection = SEL_EXIT;\n\t\t\t\t\t\t\t\t\tSpecial.IsFromWChat = false;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n#endif\t//WINSOCK_IPX\n\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to call Init_Network.\\n\");\n\t\t\t\t\t\t\t\tInit_Network();\n\n\t\t\t\t\t\t\t\tif (DDEServer.Get_MPlayer_Game_Info()) {\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to call Read_Game_Options.\\n\");\n\t\t\t\t\t\t\t\t\tRead_Game_Options( NULL );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tRead_Game_Options( \"C&CSPAWN.INI\" );\n\t\t\t\t\t\t\t\t}\n#ifdef WINSOCK_IPX\n\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to set addresses.\\n\");\n\t\t\t\t\t\t\t\tPacketTransport->Set_Broadcast_Address (PlanetWestwoodIPAddress);\n#endif\t//WINSOCK_IPX\n\t\t\t\t\t\t\t\tif (PlanetWestwoodIsHost) {\n\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to call Server_Remote_Connect.\\n\");\n\t\t\t\t\t\t\t\t\tif (Server_Remote_Connect()) {\n\t\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Server_Remote_Connect returned success.\\n\");\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t** We failed to connect to the other player\n\t\t\t\t\t\t\t\t\t\t*/\n#ifdef WINSOCK_IPX\n\t\t\t\t\t\t\t\t\t\tdelete PacketTransport;\n\t\t\t\t\t\t\t\t\t\tPacketTransport = NULL;\n#else\t//WINSOCK_IPX\n\t\t\t\t\t\t\t\t\t\tWinsock.Close();\n#endif\t//WINSOCK_IPX\n\t\t\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t\t\tDDEServer.Delete_MPlayer_Game_Info();\t// Make sure we dont go round in an infinite loop\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to call Client_Remote_Connect.\\n\");\n\t\t\t\t\t\t\t\t\tif (Client_Remote_Connect()) {\n\t\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Client_Remote_Connect returned success.\\n\");\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t** We failed to connect to the other player\n\t\t\t\t\t\t\t\t\t\t*/\n#ifdef WINSOCK_IPX\n\t\t\t\t\t\t\t\t\t\tdelete PacketTransport;\n\t\t\t\t\t\t\t\t\t\tPacketTransport = NULL;\n#else\t//WINSOCK_IPX\n\t\t\t\t\t\t\t\t\t\tWinsock.Close();\n#endif\t//WINSOCK_IPX\n\t\t\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t\t\tDDEServer.Delete_MPlayer_Game_Info();  // Make sure we dont go round in an infinite loop\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tSession.Type = Select_MPlayer_Game();\n\t\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// 'Cancel'\n\t\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n#endif\t//WIN32\n#endif\t//\t!WOLAPI_INTEGRATION\n\n\t\t\t\t\t}\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\t\t}\t//\tif( !pWolapi )\n\n\t\t\t\t\tif( pWolapi )\n\t\t\t\t\t\tSession.Type = GAME_INTERNET;\n#endif\n//debugprint( \"Session.Type = %i\\n\", Session.Type );\n\t\t\t\t\tswitch (Session.Type) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tModem, Null-Modem or internet\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase GAME_MODEM:\n\t\t\t\t\t\tcase GAME_NULL_MODEM:\n#ifndef WOLAPI_INTEGRATION\n\t\t\t\t\t\tcase GAME_INTERNET:\n#endif\n\t\t\t\t\t\tcase GAME_SKIRMISH:\n\t\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\t\tprocess = false;\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\tOptions.ScoreVolume = Options.MultiScoreVolume;\n#else\n\t\t\t\t\t\t\tOptions.ScoreVolume = 0;\n#endif\n\t\t\t\t\t\t\tbreak;\n\n#ifdef WOLAPI_INTEGRATION\t\t//\timplies also WINSOCK_IPX\n\t\t\t\t\t\tcase GAME_INTERNET:\n\t\t\t\t\t\t\tif( PacketTransport )\n\t\t\t\t\t\t\t\tdelete PacketTransport;\n\t\t\t\t\t\t\tPacketTransport = new UDPInterfaceClass;\n\t\t\t\t\t\t\tassert( PacketTransport != NULL );\n\t\t\t\t\t\t\tif( PacketTransport->Init() )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tswitch( WOL_Main() )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\t//\tStart game.\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\t\tOptions.ScoreVolume = Options.MultiScoreVolume;\n#else\n\t\t\t\t\t\t\t\t\tOptions.ScoreVolume = 0;\n#endif\n\t\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\t//\tUser cancelled.\n\t\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\t\tselection = SEL_MULTIPLAYER_GAME;\t//SEL_NONE;\n\t\t\t\t\t\t\t\t\tdelete PacketTransport;\n\t\t\t\t\t\t\t\t\tPacketTransport = NULL;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase -1:\n\t\t\t\t\t\t\t\t\t//\tPatch was downloaded. Exit app.\n\t\t\t\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\t\t\t\tBlackPalette.Set( FADE_PALETTE_SLOW );\n\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\tselection = SEL_MULTIPLAYER_GAME;\t//SEL_NONE;\n\t\t\t\t\t\t\t\tdelete PacketTransport;\n\t\t\t\t\t\t\t\tPacketTransport = NULL;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n#endif\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tNetwork (IPX): start a new network game.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase GAME_IPX:\n\t\t\t\t\t\t\tWWDebugString (\"RA95 - Game type is IPX.\\n\");\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Init network system & remote-connect\n\t\t\t\t\t\t\t*/\n#ifdef WINSOCK_IPX\n\t\t\t\t\t\t\tif (PacketTransport ) delete PacketTransport;\n//\t\t\t\t\t\t\tif (WWMessageBox().Process(\"Select a protocol to use for network play.\", \"UDP\", \"IPX\")) {\n\t\t\t\t\t\t\t\tPacketTransport = new IPXInterfaceClass;\n\t\t\t\t\t\t\t\tassert ( PacketTransport != NULL);\n//\t\t\t\t\t\t\t}else{\n//\t\t\t\t\t\t\t\tPacketTransport = new UDPInterfaceClass;\t//IPXInterfaceClass;\n//\t\t\t\t\t\t\t\tassert ( PacketTransport != NULL);\n//\t\t\t\t\t\t\t\tif (!Get_Broadcast_Addresses()) {\n//\t\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n//\t\t\t\t\t\t\t\t\tdisplay = true;\n//\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n//\t\t\t\t\t\t\t\t\tdelete PacketTransport;\n//\t\t\t\t\t\t\t\t\tPacketTransport = NULL;\n//\t\t\t\t\t\t\t\t\tbreak;\n//\t\t\t\t\t\t\t\t}\n//\t\t\t\t\t\t\t}\n\n#endif\t//WINSOCK_IPX\n\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to call Init_Network.\\n\");\n\t\t\t\t\t\t\tif (Session.Type == GAME_IPX && Init_Network() && Remote_Connect()) {\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\tOptions.ScoreVolume = Options.MultiScoreVolume;\n#else\n\t\t\t\t\t\t\t\tOptions.ScoreVolume = 0;\n#endif\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\t\t} else {\t\t\t\t\t\t// user hit cancel, or init failed\n\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\tselection = SEL_NONE;\n#ifdef WINSOCK_IPX\n\t\t\t\t\t\t\t\tdelete PacketTransport;\n\t\t\t\t\t\t\t\tPacketTransport = NULL;\n#endif\t//WINSOCK_IPX\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n#if(TEN)\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tTEN: jump straight into the game\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase GAME_TEN:\n\t\t\t\t\t\t\tif (Init_TEN()) {\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\tOptions.ScoreVolume = Options.MultiScoreVolume;\n#else\n\t\t\t\t\t\t\t\tOptions.ScoreVolume = 0;\n#endif\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tWWMessageBox().Process(\"Unable to initialize TEN!\");\n\t\t\t\t\t\t\t\t//Prog_End();\n\t\t\t\t\t\t\t\tEmergency_Exit(1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n#endif\t// TEN\n\n#if(MPATH)\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tMPATH: jump straight into the game\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase GAME_MPATH:\n\t\t\t\t\t\t\tif (Init_MPATH()) {\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\tOptions.ScoreVolume = Options.MultiScoreVolume;\n#else\n\t\t\t\t\t\t\t\tOptions.ScoreVolume = 0;\n#endif\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tWWMessageBox().Process(\"Unable to initialize MPATH!\");\n\t\t\t\t\t\t\t\t//Prog_End();\n\t\t\t\t\t\t\t\tEmergency_Exit(1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n#endif\t// MPATH\n\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tPlay a VQ\n\t\t\t\t*/\n\t\t\t\tcase SEL_INTRO:\n\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\tif (Debug_Flag) {\n\t\t\t\t\t\tPlay_Intro(Debug_Flag);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tHide_Mouse();\n\t\t\t\t\t\tVisiblePage.Clear();\n\t\t\t\t\t\tShow_Mouse();\n\t\t\t\t\t\tPlay_Movie(VQ_INTRO_MOVIE, THEME_NONE, true);\t\t// no transition picture to briefing\n\t\t\t\t\t\tKeyboard->Clear();\n\t\t\t\t\t\tPlay_Movie(VQ_SIZZLE, THEME_NONE, true);\n\t\t\t\t\t\tPlay_Movie(VQ_SIZZLE2, THEME_NONE, true);\n//\t\t\t\t\t\tPlay_Movie(VQ_INTRO_MOVIE, THEME_NONE, false);\t\t// has transitino picture to briefing\n\t\t\t\t\t}\n\t\t\t\t\tTheme.Queue_Song(THEME_CRUS);\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tfade = true;\n\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tExit to DOS.\n\t\t\t\t*/\n\t\t\t\tcase SEL_EXIT:\n\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\tBlackPalette.Set(FADE_PALETTE_SLOW);\n\t\t\t\t\treturn(false);\n\n\t\t\t\t/*\n\t\t\t\t**\tDisplay the hall of fame.\n\t\t\t\t*/\n\t\t\t\tcase SEL_FAME:\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase SEL_TIMEOUT:\n\t\t\t\t\tif (Session.Attract && Session.RecordFile.Is_Available()) {\n\t\t\t\t\t\tSession.Play = true;\n\t\t\t\t\t\tif (Session.RecordFile.Open(READ)) {\n\t\t\t\t\t\t\tLoad_Recording_Values(Session.RecordFile);\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSession.Play = false;\n\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t** For Debug_Map (editor) mode to load scenario\n\t\t*/\n\t\tScen.Set_Scenario_Name(\"SCG01EA.INI\");\n\t}\n\n\t/*\n\t**\tDon't carry stray keystrokes into game.\n\t*/\n\tKeyboard->Clear();\n\n\t/*\n\t** Initialize the random number generator(s)\n\t*/\n\tInit_Random();\n\n\t/*\n\t** Save initialization values if we're recording this game.\n\t*/\n\tif (Session.Record) {\n\t\tif (Session.RecordFile.Open(WRITE)) {\n\t\t\tSave_Recording_Values(Session.RecordFile);\n\t\t} else {\n\t\t\tSession.Record = false;\n\t\t}\n\t}\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tswitch(Session.Type) {\n\t\tcase GAME_MODEM:\n\t\tcase GAME_NULL_MODEM:\n\t\tcase GAME_IPX:\n#ifdef FIXIT_VERSION_3\n\t\t\tif( !bAftermathMultiplayer ) {\n#else\n\t\t\tif (PlayingAgainstVersion < VERSION_AFTERMATH_CS) {\n#endif\n\t\t\t\tNewUnitsEnabled = SecretUnitsEnabled = false;\n\t\t\t} else {\n\t\t\t\tNewUnitsEnabled = true;\n\t\t\t}\n//\t\t\tdebugprint( \"Non Internet game: NewUnitsEnabled = %i\\n\", NewUnitsEnabled );\n\t\t\tbreak;\n\t\tcase GAME_INTERNET:\n\t\t\tif( !pWolapi )\n\t\t\t{\n//\t\t\t\tdebugprint( \"pWolapi is null on internet game!\" );\n\t\t\t\tFatal( \"pWolapi is null on internet game!\" );\n\t\t\t}\n\t\t\t//if( pWolapi->bEnableNewAftermathUnits )\n\t\t\tif( bAftermathMultiplayer )\n\t\t\t\tNewUnitsEnabled = true;\n\t\t\telse\n\t\t\t\tNewUnitsEnabled = SecretUnitsEnabled = false;\n//\t\t\tdebugprint( \"Internet game: NewUnitsEnabled = %i\\n\", NewUnitsEnabled );\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n#endif\n\t/*\n\t**\tLoad the scenario.  Specify variation 'A' for the editor; for the game,\n\t**\tdon't specify a variation, to make 'Set_Scenario_Name()' pick a random one.\n\t**\tSkip this if we've already loaded a save-game.\n\t*/\n\tif (!gameloaded && !Session.LoadGame) {\n//\t\tif (Debug_Map) {\n//\t\t\tSet_Scenario_Name(Scen.ScenarioName, Scen.Scenario, Scen.ScenPlayer, Scen.ScenDir, SCEN_VAR_A);\n//\t\t}  else {\n//\t\t\tSet_Scenario_Name(Scen.ScenarioName, Scen.Scenario, Scen.ScenPlayer, Scen.ScenDir);\n//\t\t}\n\n\t\t/*\n\t\t** Start_Scenario() changes the palette; so, fade out & clear the screen\n\t\t** before calling it.\n\t\t*/\n\t\tHide_Mouse();\n\n\t\tif (selection != SEL_START_NEW_GAME) {\n\t\t\tBlackPalette.Set(FADE_PALETTE_MEDIUM, Call_Back);\n#ifdef WIN32\n\t\t\tHiddenPage.Clear();\n\t\t\tVisiblePage.Clear();\n#else\n\t\t\tHidPage.Clear();\n\t\t\tSeenPage.Clear();\n#endif\t//WIN32\n\t\t}\n\t\tShow_Mouse();\n//Mono_Printf(\"About to call Start Scenario with %s\\n\", Scen.ScenarioName);\n\t\tif (!Start_Scenario(Scen.ScenarioName)) {\n\t\t\treturn(false);\n\t\t}\n\t\tif (Special.IsFromInstall) Show_Mouse();\n\t\tSpecial.IsFromInstall = false;\n\t}\n\n\t/*\n\t**\tFor multiplayer games, initialize the inter-player message system.\n\t**\tDo this after loading the scenario, so the map's upper-left corner is\n\t**\tproperly set.\n\t*/\n\tSession.Messages.Init(\n\t\tMap.TacPixelX, Map.TacPixelY, \t// x,y for messages\n\t\t6, \t\t\t\t\t\t\t\t\t\t// max # msgs\n\t\tMAX_MESSAGE_LENGTH-14,\t\t\t\t// max msg length\n\t\t7 * RESFACTOR,\t\t\t\t\t\t\t// font height in pixels\n\t\t-1, -1, \t\t\t\t\t\t\t\t\t// x,y for edit line (appears above msgs)\n\t\t0,//BG\t\t1,\t\t\t\t\t\t\t// enable edit overflow\n\t\t20,          \t\t\t\t\t\t\t// min,\n\t\tMAX_MESSAGE_LENGTH - 14,\t\t\t//    max for trimming overflow\n#ifdef WIN32\n\t\tLepton_To_Pixel(Map.TacLeptonWidth));\t// Width in pixels of buffer\n#else\n\t\t(320-SIDEBAR_WID));\t// Width in pixels of buffer\n#endif\n\n\tif (Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH &&\n\t\t!Session.Play) {\n\t\tif (Session.Type == GAME_TEN) {\n#if(TEN)\n\t\t\tSession.Create_TEN_Connections();\n#endif\t// TEN\n\t\t} else if (Session.Type == GAME_MPATH) {\n#if(MPATH)\n\t\t\tSession.Create_MPATH_Connections();\n#endif\n\t\t} else {\n\t\t\tSession.Create_Connections();\n\t\t}\n\t}\n\n\n\t/*\n\t** If this isnt an internet game that set the unit build rate to its default value\n\t*/\n\tif (Session.Type != GAME_INTERNET){\n\t\tUnitBuildPenalty = 100;\n\t}\n\n\t/*\n\t**\tHide the SeenPage; force the map to render one frame.  The caller can\n\t**\tthen fade the palette in.\n\t**\t(If we loaded a game, this step will fade out the title screen.  If we\n\t**\tstarted a scenario, Start_Scenario() will have played a couple of VQ\n\t**\tmovies, which will have cleared the screen to black already.)\n\t*/\n\tCall_Back();\n\tHide_Mouse();\n\tBlackPalette.Set(FADE_PALETTE_MEDIUM, Call_Back);\n//\tFade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);\n#ifdef WIN32\n\tHiddenPage.Clear();\n\tVisiblePage.Clear();\n#else\n\tHidPage.Clear();\n\tSeenPage.Clear();\n#endif\t//WIN32\n\tShow_Mouse();\n\tSet_Logic_Page(SeenBuff);\n#ifdef WIN32\n\t/*\n\t** Sidebar is always active in hi-res.\n\t*/\n\tif (!Debug_Map) {\n\t\tMap.SidebarClass::Activate(1);\n\t}\n#endif\t//WIN32\n\tMap.Flag_To_Redraw();\n\tCall_Back();\n\tMap.Render();\n\n#ifdef WOLAPI_INTEGRATION\n\n\t\t\t\t\t\t//ajw debugging only\n//\t\t\t\t\t\tdebugprint( \"Debugging Session...\\n\" );\n//\t\t\t\t\t\tdebugprint( \"Session.Players count is %i.\\n\", Session.Players.Count() );\n\t\t\t\t\t\tfor (i = 0; i < Session.Players.Count(); i++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tNetNumType net;\n\t\t\t\t\t\t\tNetNodeType node;\n\t\t\t\t\t\t\tSession.Players[i]->Address.Get_Address( net, node );\n//\t\t\t\t\t\t\tdebugprint( \"Player %i, %s, color %i, ip %i.%i.%i.%i.%i.%i\\n\", i, Session.Players[i]->Name, \n//\t\t\t\t\t\t\t\tSession.Players[i]->Player.Color, node[0], node[1], node[2], node[3], node[4], node[5] );\n\t\t\t\t\t\t}\n//\t\t\t\t\t\tdebugprint( \"PlanetWestwoodPortNumber is %i\\n\", PlanetWestwoodPortNumber );\n\n#endif\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Play_Intro -- plays the introduction & logo movies                                          *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/06/1995 BRR : Created.                                                                 *\n *   05/08/1996 JLB : Modified for Red Alert and direction control.                            *\n *=============================================================================================*/\nstatic void Play_Intro(bool sequenced)\n{\n\tstatic VQType _counter = VQ_FIRST;\n\n\tKeyboard->Clear();\n\tif (sequenced) {\n\t\tif (_counter <= VQ_FIRST) _counter = VQ_COUNT;\n\t\tif (_counter == VQ_COUNT) _counter--;\n\t\tif (_counter == VQ_REDINTRO) _counter--;\n\t\tif (_counter == VQ_TITLE) _counter--;\n\t\tHide_Mouse();\n\t\tVisiblePage.Clear();\n\t\tShow_Mouse();\n\t\tPlay_Movie(VQType(_counter--), THEME_NONE);\n\t\t\n//\t\tShow_Mouse();\n\t} else {\n\t\tHide_Mouse();\n\t\tVisiblePage.Clear();\n\t\tShow_Mouse();\n#ifdef WIN32\n\t\tPlay_Movie(VQ_REDINTRO, THEME_NONE, false);\n#else\n\t\tPlay_Movie(VQ_TITLE, THEME_NONE, false);\n#endif\n\t}\n}\n\n\n/***********************************************************************************************\n * Anim_Init -- Initialize the VQ animation control structure.                                 *\n *                                                                                             *\n *    VQ animations are controlled by a structure passed to the VQ player. This routine        *\n *    initializes the structure to values required by C&C.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only need to call this routine once at the beginning of the game.               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/20/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef WIN32\n#ifdef MOVIE640\nGraphicBufferClass VQ640(640, 400, (void *)NULL);\n#endif\n#endif\nvoid Anim_Init(void)\n{\n\n#ifdef WIN32\n\n\t/* Configure player with INI file */\n\tVQA_DefaultConfig(&AnimControl);\n\tAnimControl.DrawFlags = VQACFGF_TOPLEFT;\n\tAnimControl.DrawFlags |= VQACFGF_BUFFER;\n//AnimControl.DrawFlags |= VQACFGF_NODRAW;\n//BG - M. Grayford says turn this off\tAnimControl.DrawFlags |= VQACFGF_NOSKIP;\n\n\tAnimControl.DrawFlags |= VQACFGF_NOSKIP;\n\tAnimControl.FrameRate = -1;\n\tAnimControl.DrawRate = -1;\n\tAnimControl.DrawerCallback = VQ_Call_Back;\n\tAnimControl.ImageWidth = 320;\n\tAnimControl.ImageHeight = 200;\n\tAnimControl.ImageBuf = (unsigned char *)SysMemPage.Get_Offset();\n#ifdef MOVIE640\n\tif(IsVQ640) {\n\t\tAnimControl.ImageWidth = 640;\n\t\tAnimControl.ImageHeight = 400;\n\t\tAnimControl.ImageBuf = (unsigned char *)VQ640.Get_Offset();\n\t}\n#endif\n\tAnimControl.Vmode = 0;\n\tAnimControl.OptionFlags |= VQAOPTF_CAPTIONS|VQAOPTF_EVA;\n\tif (SlowPalette) {\n\t\tAnimControl.OptionFlags |= VQAOPTF_SLOWPAL;\n\t}\n\tAnimControl.SoundObject = SoundObject;\n\tAnimControl.PrimaryBufferPtr = PrimaryBufferPtr;\n\tif (MonoClass::Is_Enabled()) {\n\t\tAnimControl.OptionFlags |= VQAOPTF_MONO;\n\t}\n\n#else\t//WIN32\n\t/* Configure player with INI file */\n\tVQA_DefaultConfig(&AnimControl);\n//\tvoid const * font = Load_Font(FONT8);\n//\tAnimControl.EVAFont = (char *)font;\n//\tAnimControl.CapFont = (char *)font;\n\tAnimControl.DrawerCallback = VQ_Call_Back;\n\tAnimControl.ImageWidth = 320;\n\tAnimControl.ImageHeight = 200;\n\tAnimControl.Vmode = MCGA_MODE;\n\tAnimControl.VBIBit = VertBlank;\n\tAnimControl.DrawFlags |= VQACFGF_TOPLEFT;\n\tAnimControl.OptionFlags |= VQAOPTF_HMIINIT|VQAOPTF_CAPTIONS|VQAOPTF_EVA;\n//\tAnimControl.AudioBuf = (unsigned char *)HidPage.Get_Buffer();\n//\tAnimControl.AudioBufSize = 32768U;\n\tAnimControl.DigiCard = NewConfig.DigitCard;\n\tAnimControl.HMIBufSize = 8192;\n\tAnimControl.DigiHandle = Get_Digi_Handle();\n\tAnimControl.Volume = 0x00FF;\n\tAnimControl.AudioRate = 22050;\n//\tif (NewConfig.Speed) AnimControl.AudioRate = 11025;\n\n\tif (!Debug_Quiet && Get_Digi_Handle() != -1) {\n\t\tAnimControl.OptionFlags |= VQAOPTF_AUDIO;\n\t}\n\n\tif (MonoClass::Is_Enabled()) {\n\t\tAnimControl.OptionFlags |= VQAOPTF_MONO;\n\t}\n\n#endif\t//WIN32\n}\n\n\n/***********************************************************************************************\n * Parse_Command_Line -- Parses the command line parameters.                                   *\n *                                                                                             *\n *    This routine should be called before the graphic mode is initialized. It examines the    *\n *    command line parameters and sets the appropriate globals. If there is an error, then     *\n *    it outputs a command summary and then returns false.                                     *\n *                                                                                             *\n * INPUT:   argc  -- The number of command line arguments.                                     *\n *                                                                                             *\n *          argv  -- Pointer to character string array that holds the individual arguments.    *\n *                                                                                             *\n * OUTPUT:  bool; Was the command line parsed successfully?                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool Parse_Command_Line(int argc, char * argv[])\n{\n\t/*\n\t**\tParse the command line and set globals to reflect the parameters\n\t**\tpassed in.\n\t*/\n\tWhom = HOUSE_GOOD;\n\tSpecial.Init();\n\n\tDebug_Map = false;\n\tDebug_Unshroud = false;\n\n\tfor (int index = 1; index < argc; index++) {\n\t\tchar * string;\t\t// Pointer to argument.\n\t\tlong code = 0;\n\n\t\tstring = strupr(argv[index]);\n\n\t\t/*\n\t\t**\tPrint usage text only if requested.\n\t\t*/\n\t\tif (stricmp(\"/?\", string) == 0 || stricmp(\"-?\", string) == 0 || stricmp(\"-h\", string) == 0 || stricmp(\"/h\", string) == 0) {\n\t\t\t/*\n\t\t\t**\tUnrecognized command line parameter... Display usage\n\t\t\t**\tand then exit.\n\t\t\t*/\n\t\t\tputs(TEXT_OPTIONS);\n\t\t\treturn(false);\n\t\t}\n\n\n\t\tbool processed = true;\n\t\tlong ob = Obfuscate(string);\n\n\t\t/*\n\t\t**\tCheck to see if the parameter is a cheat enabling one.\n\t\t*/\n\t\tlong const * optr = &CheatCodes[0];\n\t\twhile (*optr) {\n\t\t\tif (*optr++ == ob) {\n\t\t\t\tDebug_Playtest = true;\n\t\t\t\tDebug_Flag = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tCheck to see if the parameter is a cheat enabling one.\n\t\t*/\n\t\toptr = &PlayCodes[0];\n\t\twhile (*optr) {\n\t\t\tif (*optr++ == ob) {\n\t\t\t\tDebug_Playtest = true;\n\t\t\t\tDebug_Flag = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tCheck to see if the parameter is a scenario editor\n\t\t**\tenabling one.\n\t\t*/\n\t\toptr = &EditorCodes[0];\n\t\twhile (*optr) {\n\t\t\tif (*optr++ == ob) {\n\t\t\t\tDebug_Map = true;\n\t\t\t\tDebug_Unshroud = true;\n\t\t\t\tDebug_Flag = true;\n\t\t\t\tDebug_Playtest = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tswitch (ob) {\n\n#ifdef VIRGIN_CHEAT_KEYS\n\t\t\tcase PARM_PLAYTEST:\n\t\t\t\tDebug_Playtest = true;\n\t\t\t\tbreak;\n#endif\n\n\t\t\t/*\n\t\t\t** Special flag - is C&C being run from the install program?\n\t\t\t*/\n\t\t\tcase PARM_INSTALL:\n\t\t\t\tSpecial.IsFromInstall = true;\n// If uncommented, will disable the <ESC> key during the first movie run.\n//\t\t\t\tBreakoutAllowed = false;\n\t\t\t\tbreak;\n\n#if(TEN)\n\t\t\tcase PARM_ALLOW_SOLO:\n\t\t\t\tSession.AllowSolo = 1;\n\t\t\t\tbreak;\n#endif\n\n#if(MPATH)\n\t\t\tcase PARM_ALLOW_SOLO:\n\t\t\t\tSession.AllowSolo = 1;\n\t\t\t\tbreak;\n#endif\n\n\t\t\tdefault:\n\t\t\t\tprocessed = false;\n\t\t\t\tbreak;\n\t\t}\n\t\tif (processed) continue;\n\n\n#ifdef CHEAT_KEYS\n\t\t/*\n\t\t**\tScenario Editor Mode\n\t\t*/\n\t\tif (stricmp(string, \"-CHECKMAP\") == 0) {\n\t\t\tDebug_Check_Map = true;\n\t\t\tcontinue;\n\t\t}\n\n#endif\n\n\t\t/*\n\t\t**\tFile search path override.\n\t\t*/\n\t\tif (strstr(string, \"-CD\")) {\n\t\t\tCCFileClass::Set_Search_Drives(&string[3]);\n\t\t\tcontinue;\n\t\t}\n\n#if (0)\n\t\t/*\n\t\t** Build speed modifier\n\t\t*/\n\t\tif (strstr (string, \"-UNITRATE:\")){\n\t\t\tint unit_rate;\n\t\t\tsscanf (string, \"-UNITRATE:%d\", &unit_rate);\n\t\t\tUnitBuildPenalty = unit_rate;\n\t\t}\n#endif\t//(0)\n\n\t\t/*\n\t\t**\tSpecify destination connection for network play\n\t\t*/\n\t\tif (strstr(string, \"-DESTNET\")) {\n\t\t\tNetNumType net;\n\t\t\tNetNodeType node;\n\n\t\t\t/*\n\t\t\t** Scan the command-line string, pulling off each address piece\n\t\t\t*/\n\t\t\tint i = 0;\n\t\t\tchar * p = strtok(string + 8, \".\");\n\t\t\twhile (p) {\n\t\t\t\tint x;\n\n\t\t\t\tsscanf(p, \"%x\", &x);\t\t\t// convert from hex string to int\n\t\t\t\tif (i < 4) {\n\t\t\t\t\tnet[i] = (char)x;\t\t\t// fill NetNum\n\t\t\t\t} else {\n\t\t\t\t\tnode[i-4] = (char)x;\t\t// fill NetNode\n\t\t\t\t}\n\t\t\t\ti++;\n\t\t\t\tp = strtok(NULL, \".\");\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If all the address components were successfully read, fill in the\n\t\t\t** BridgeNet with a broadcast address to the network across the bridge.\n\t\t\t*/\n\t\t\tif (i >= 4) {\n\t\t\t\tSession.IsBridge = 1;\n\t\t\t\tmemset(node, 0xff, 6);\n\t\t\t\tSession.BridgeNet = IPXAddressClass(net, node);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tSpecify socket ID, as an offset from 0x4000.\n\t\t*/\n\t\tif (strstr(string, \"-SOCKET\")) {\n\t\t\tunsigned short socket;\n\n\t\t\tsocket = (unsigned short)(atoi(string + strlen(\"SOCKET\")));\n\t\t\tsocket += 0x4000;\n\t\t\tif (socket >= 0x4000 && socket < 0x8000) {\n\t\t\t\tIpx.Set_Socket (socket);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tSet the Net Stealth option\n\t\t*/\n\t\tif (strstr(string, \"-STEALTH\")) {\n\t\t\tSession.NetStealth = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tSet the Net Protection option\n\t\t*/\n\t\tif (strstr(string, \"-MESSAGES\")) {\n\t\t\tSession.NetProtect = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tAllow \"attract\" mode\n\t\t*/\n\t\tif (strstr(string, \"-ATTRACT\")) {\n\t\t\tSession.Attract = true;\n\t\t\tcontinue;\n\t\t}\n\n\n#ifdef WIN32\n\t\t/*\n\t\t** Set screen to 640x480 instead of 640x400\n\t\t*/\n\t\tif (strstr(string, \"-480\")) {\n\t\t\tScreenHeight = 480;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t** Check for spawn from WChat\n\t\t*/\n#ifndef FIXIT_VERSION_3\t\t\t//\tWChat eliminated.\n\t\tif (strstr(string,\"-WCHAT\")){\n\t\t\tSpawnedFromWChat = true;\n\t\t}\n#endif\n\n#endif\n\n#ifdef CHEAT_KEYS\n\t\t/*\n\t\t**\tSpecify the random number seed (for debugging)\n\t\t*/\n\t\tif (strstr(string, \"-SEED\")) {\n\t\t\tCustomSeed = (unsigned short)(atoi(string + strlen(\"SEED\")));\n\t\t\tcontinue;\n\t\t}\n\n#ifndef WIN32\n\t\t/*\n\t\t**\tDon't install Page Fault Handler (MUST use this for debugger)\n\t\t*/\n\t\tif (stricmp(string, \"-NOPFS\") == 0) {\n\t\t\tUsePageFaultHandler = 0;\n\t\t\tcontinue;\n\t\t}\n#endif\n\n#endif\n\n\n#if(TEN)\n\t\t/*\n\t\t**\tEnable TEN\n\t\t*/\n\t\tif (strstr(string, \"TEN\")) {\n\n#ifdef CHEAT_KEYS\n\t\t\tDebug_Flag = true;\n\t\t\tMonoClass::Enable();\n#endif\n\n\t\t\tSession.Type = GAME_TEN;\n\t\t\tSpecial.IsFromInstall = false;\n\t\t\t//\n\t\t\t// Create the Ten network manager.  This allows us to keep\n\t\t\t// the packet queues clean even while we're initializing the game,\n\t\t\t// so the queues don't fill up in case we're slow, or the user\n\t\t\t// didn't insert a CD.\n\t\t\t//\n\t\t\tTen = new TenConnManClass();\n\t\t\tTen->Init();\n\t\t\tstrcpy(Session.OptionsFile, \"OPTIONS.INI\");\n\t\t\tTen->Flush_All();\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tSet the game options filename\n\t\t*/\n\t\tif (strstr(string, \"OPTIONS:\")) {\n\t\t\tstrcpy(Session.OptionsFile, string + 8);\n\t\t\tcontinue;\n\t\t}\n#endif\t// TEN\n\n#if(MPATH)\n\t\t/*\n\t\t**\tEnable MPATH\n\t\t*/\n\t\tif (strstr(string, \"MPATH\")) {\n\n#ifdef CHEAT_KEYS\n\t\t\tDebug_Flag = true;\n\t\t\tMonoClass::Enable();\n#endif\n\n\t\t\tSession.Type = GAME_MPATH;\n\t\t\tSpecial.IsFromInstall = false;\n\t\t\t//\n\t\t\t// Create the MPath network manager.  This allows us to keep\n\t\t\t// the packet queues clean even while we're initializing the game,\n\t\t\t// so the queues don't fill up in case we're slow, or the user\n\t\t\t// didn't insert a CD.\n\t\t\t//\n\t\t\tMPath = new MPlayerManClass();\n\t\t\tMPath->Init();\n\t\t\tstrcpy(Session.OptionsFile, \"OPTIONS.INI\");\n\t\t\tMPath->Flush_All();\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tSet the game options filename\n\t\t*/\n\t\tif (strstr(string, \"OPTIONS:\")) {\n\t\t\tstrcpy(Session.OptionsFile, string + 8);\n\t\t\tcontinue;\n\t\t}\n#endif\t// MPATH\n\n\n#ifdef NEVER\n\t\t/*\n\t\t**\tHandle the prog init differently in this case.\n\t\t*/\n\t\tif (strstr(string, \"-V\")) {\n\t\t\tcontinue;\n\t\t}\n#endif\n\n\t\t/*\n\t\t** look for passed-in video mode to default to\n\t\t*/\n#ifndef\tWIN32\n\t\tif (strnicmp(string, \"-V\", strlen(\"-V\")) == 0) {\n\t\t\tSet_Video_Mode(MCGA_MODE);\t// do this to get around first_time variable...\n\t\t\tSet_Original_Video_Mode(atoi(string+2));\n\t\t\tcontinue;\n\t\t}\n#endif\n\n#ifdef CHEAT_KEYS\n\t\tif (strstr(string,\"-NOMOVIES\")){\n\t\t\tbNoMovies = true;\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tSpecial command line control parsing.\n\t\t*/\n\t\tif (strnicmp(string, \"-X\", strlen(\"-O\")) == 0) {\n\t\t\tstring += strlen(\"-X\");\n\t\t\twhile (*string) {\n\t\t\t\tchar code = *string++;\n\t\t\t\tswitch (toupper(code)) {\n\n#ifdef  CHEAT_KEYS\n\t\t\t\t\t/*\n\t\t\t\t\t**\tMonochrome debug screen enable.\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'M':\n\t\t\t\t\t\tMonoClass::Enable();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tInert weapons -- no units take damage.\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'I':\n\t\t\t\t\t\tSpecial.IsInert = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tHussled recharge timer.\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'H':\n\t\t\t\t\t\tSpecial.IsSpeedBuild = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\t\"Record\" a multi-player game\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'X':\n\t\t\t\t\t\tSession.Record = 1;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\t\"Play Back\" a multi-player game\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'Y':\n\t\t\t\t\t\tSession.Play = 1;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tPrint lots of debug stuff about events & packets\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'P':\n\t\t\t\t\t\tDebug_Print_Events = true;\n\t\t\t\t\t\tbreak;\n#endif\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tQuiet mode override control.\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'Q':\n\t\t\t\t\t\tDebug_Quiet = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tputs(TEXT_INVALID);\n\t\t\t\t\t\treturn(false);\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tcontinue;\n\t\t}\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Obfuscate -- Sufficiently transform parameter to thwart casual hackers.                     *\n *                                                                                             *\n *    This routine borrows from CRC and PGP technology to sufficiently alter the parameter     *\n *    in order to make it difficult to reverse engineer the key phrase. This is designed to    *\n *    be used for hidden game options that will be released at a later time over Westwood's    *\n *    Web page or through magazine hint articles.                                              *\n *                                                                                             *\n *    This algorithm is cryptographically categorized as a \"one way hash\".                     *\n *                                                                                             *\n *    Since this is a one way transformation, it becomes much more difficult to reverse        *\n *    engineer the pass phrase even if the resultant pass code is known. This has an added     *\n *    benefit of making this algorithm immune to traditional cryptographic attacks.            *\n *                                                                                             *\n *    The largest strength of this transformation algorithm lies in the restriction on the     *\n *    source vector being legal ASCII uppercase characters. This restriction alone makes even  *\n *    a simple CRC transformation practically impossible to reverse engineer. This algorithm   *\n *    uses far more than a simple CRC transformation to achieve added strength from advanced   *\n *    attack methods.                                                                          *\n *                                                                                             *\n * INPUT:   string   -- Pointer to the key phrase that will be transformed into a code.        *\n *                                                                                             *\n * OUTPUT:  Returns with the code that the key phrase is translated into.                      *\n *                                                                                             *\n * WARNINGS:   A zero length pass phrase results in a 0x00000000 result code.                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Obfuscate(char const * string)\n{\n\tchar buffer[128];\n\n\tif (!string) return(0);\n\tmemset(buffer, '\\xA5', sizeof(buffer));\n\n\t/*\n\t**\tCopy key phrase into a working buffer. This hides any transformation done\n\t**\tto the string.\n\t*/\n\tstrncpy(buffer, string, sizeof(buffer));\n\tbuffer[sizeof(buffer)-1] = '\\0';\n\tint length = strlen(buffer);\n\n\t/*\n\t**\tOnly upper case letters are significant.\n\t*/\n\tstrupr(buffer);\n\n\t/*\n\t**\tEnsure that only visible ASCII characters compose the key phrase. This\n\t**\tdiscourages the direct forced illegal character input method of attack.\n\t*/\n\tfor (int index = 0; index < length; index++) {\n\t\tif (!isgraph(buffer[index])) {\n\t\t\tbuffer[index] = 'A' + (index%26);\n\t\t}\n\t}\n\n\t/*\n\t**\tIncrease the strength of even short pass phrases by extending the\n\t**\tlength to be at least a minimum number of characters. This helps prevent\n\t**\ta weak pass phrase from compromising the obfuscation process. This\n\t**\tprocess also forces the key phrase to be an even multiple of four.\n\t**\tThis is necessary to support the cypher process that occurs later.\n\t*/\n\tif (length < 16 || (length & 0x03)) {\n\t\tint maxlen = 16;\n\t\tif (((length+3) & 0x00FC) > maxlen) {\n\t\t\tmaxlen = ((length+3) & 0x00FC);\n\t\t}\n\t\tfor (index = length; index < maxlen; index++) {\n\t\t\tbuffer[index] = 'A' + ((('?' ^ buffer[index-length]) + index) % 26);\n\t\t}\n\t\tlength = index;\n\t\tbuffer[length] = '\\0';\n\t}\n\n\t/*\n\t**\tTransform the buffer into a number. This transformation is character\n\t**\torder dependant.\n\t*/\n\tlong code = Calculate_CRC(buffer, length);\n\n\t/*\n\t**\tRecord a copy of this initial transformation to be used in a later\n\t**\tself referential transformation.\n\t*/\n\tlong copy = code;\n\n\t/*\n\t**\tReverse the character string and combine with the previous transformation.\n\t**\tThis doubles the workload of trying to reverse engineer the CRC calculation.\n\t*/\n\tstrrev(buffer);\n\tcode ^= Calculate_CRC(buffer, length);\n\n\t/*\n\t**\tPerform a self referential transformation. This makes a reverse engineering\n\t**\tby using a cause and effect attack more difficult.\n\t*/\n\tcode = code ^ copy;\n\n\t/*\n\t**\tUnroll and combine the code value into the pass phrase and then perform\n\t**\tanother self referential transformation. Although this is a trivial cypher\n\t**\tprocess, it gives the sophisticated hacker false hope since the strong\n\t**\tcypher process occurs later.\n\t*/\n\tstrrev(buffer);\t\t// Restore original string order.\n\tfor (index = 0; index < length; index++) {\n\t\tcode ^= (unsigned char)buffer[index];\n\t\tunsigned char temp = (unsigned char)code;\n\t\tbuffer[index] ^= temp;\n\t\tcode >>= 8;\n\t\tcode |= (((long)temp)<<24);\n\t}\n\n\t/*\n\t**\tIntroduce loss into the vector. This strengthens the key against traditional\n\t**\tcryptographic attack engines. Since this also weakens the key against\n\t**\tunconventional attacks, the loss is limited to less than 10%.\n\t*/\n\tfor (index = 0; index < length; index++) {\n\t\tstatic unsigned char _lossbits[] = {0x00,0x08,0x00,0x20,0x00,0x04,0x10,0x00};\n\t\tstatic unsigned char _addbits[] = {0x10,0x00,0x00,0x80,0x40,0x00,0x00,0x04};\n\n\t\tbuffer[index] |= _addbits[index % (sizeof(_addbits)/sizeof(_addbits[0]))];\n\t\tbuffer[index] &= ~_lossbits[index % (sizeof(_lossbits)/sizeof(_lossbits[0]))];\n\t}\n\n\t/*\n\t**\tPerform a general cypher transformation on the vector\n\t**\tand use the vector itself as the cypher key. This is a variation on the\n\t**\tcypher process used in PGP. It is a very strong cypher process with no known\n\t**\tweaknesses. However, in this case, the cypher key is the vector itself and this\n\t**\topens up a weakness against attacks that have access to this transformation\n\t**\talgorithm. The sheer workload of reversing this transformation should be enough\n\t**\tto discourage even the most determined hackers.\n\t*/\n\tfor (index = 0; index < length; index += 4) {\n\t\tshort key1 = buffer[index];\n\t\tshort key2 = buffer[index+1];\n\t\tshort key3 = buffer[index+2];\n\t\tshort key4 = buffer[index+3];\n\t\tshort val1 = key1;\n\t\tshort val2 = key2;\n\t\tshort val3 = key3;\n\t\tshort val4 = key4;\n\n\t\tval1 *= key1;\n\t\tval2 += key2;\n\t\tval3 += key3;\n\t\tval4 *= key4;\n\n\t\tshort s3 = val3;\n\t\tval3 ^= val1;\n\t\tval3 *= key1;\n\t\tshort s2 = val2;\n\t\tval2 ^= val4;\n\t\tval2 += val3;\n\t\tval2 *= key3;\n\t\tval3 += val2;\n\n\t\tval1 ^= val2;\n\t\tval4 ^= val3;\n\n\t\tval2 ^= s3;\n\t\tval3 ^= s2;\n\n\t\tbuffer[index] = val1;\n\t\tbuffer[index+1] = val2;\n\t\tbuffer[index+2] = val3;\n\t\tbuffer[index+3] = val4;\n\t}\n\n\t/*\n\t**\tConvert this final vector into a cypher key code to be\n\t**\treturned by this routine.\n\t*/\n\tcode = Calculate_CRC(buffer, length);\n\n\t/*\n\t**\tReturn the final code value.\n\t*/\n\treturn(code);\n}\n\n\n/***********************************************************************************************\n * Calculate_CRC -- Calculates a one-way hash from a data block.                               *\n *                                                                                             *\n *    This routine is used to create a hash value from a data block. The algorithm is similar  *\n *    to a CRC, but is faster.                                                                 *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to a buffer of data to be 'hashed'.                            *\n *                                                                                             *\n *          len      -- The length of the buffer to compute the hash upon.                     *\n *                                                                                             *\n * OUTPUT:  Returns with a 32bit hash value calculated from the specified buffer.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nextern \"C\"  {\nlong Calculate_CRC(void * buffer, long len)\n{\n\treturn(CRCEngine()(buffer, len));\n}\n}\n\n\n/***************************************************************************\n * Init_Random -- Initializes the random-number generator                  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid Init_Random(void)\n{\n\t#ifdef WIN32\n\n\t\t/*\n\t\t**\tGather some \"random\" bits from the system timer. Actually, only the\n\t\t**\tlow order millisecond bits are secure. The other bits could be\n\t\t**\teasily guessed from the system clock (most clocks are fairly accurate\n\t\t**\tand thus predictable).\n\t\t*/\n\t\tSYSTEMTIME t;\n\t\tGetSystemTime(&t);\n\t\tCryptRandom.Seed_Byte(t.wMilliseconds);\n\t\tCryptRandom.Seed_Bit(t.wSecond);\n\t\tCryptRandom.Seed_Bit(t.wSecond>>1);\n\t\tCryptRandom.Seed_Bit(t.wSecond>>2);\n\t\tCryptRandom.Seed_Bit(t.wSecond>>3);\n\t\tCryptRandom.Seed_Bit(t.wSecond>>4);\n\t\tCryptRandom.Seed_Bit(t.wMinute);\n\t\tCryptRandom.Seed_Bit(t.wMinute>>1);\n\t\tCryptRandom.Seed_Bit(t.wMinute>>2);\n\t\tCryptRandom.Seed_Bit(t.wMinute>>3);\n\t\tCryptRandom.Seed_Bit(t.wMinute>>4);\n\t\tCryptRandom.Seed_Bit(t.wHour);\n\t\tCryptRandom.Seed_Bit(t.wDay);\n\t\tCryptRandom.Seed_Bit(t.wDayOfWeek);\n\t\tCryptRandom.Seed_Bit(t.wMonth);\n\t\tCryptRandom.Seed_Bit(t.wYear);\n\t#else\n\n\t\t/*\n\t\t**\tGather some \"random\" bits from the DOS mode timer.\n\t\t*/\n\t\tstruct timeb t;\n\t\tftime(&t);\n\t\tCryptRandom.Seed_Byte(t.millitm);\n\t\tCryptRandom.Seed_Byte(t.time);\n\t#endif\n\n#ifdef FIXIT_MULTI_SAVE\n\t//\n\t// If we've loaded a multiplayer save game, return now; the random #\n\t// class is loaded along with ScenarioClass.\n\t//\n\tif (Session.LoadGame) {\n\t\treturn;\n\t}\n\n\t//\n\t// If we're playing a recording, the Seed is loaded in\n\t// Load_Recording_Values().  Just init the random # and return.\n\t//\n\tif (Session.Play) {\n\t\tRandNumb = Seed;\n\t\tScen.RandomNumber = Seed;\n\t\treturn;\n\t}\n#else\n\t/*\n\t** Do nothing if we've loaded a multiplayer game, or we're playing back\n\t** a recording; the random number generator is initialized by loading\n\t** the game.\n\t*/\n\tif (Session.LoadGame || Session.Play) {\n\t\tRandNumb = Seed;\n\t\tScen.RandomNumber = Seed;\n\t\treturn;\n\t}\n#endif\t// FIXIT_MULTI_SAVE\n\n\t/*\n\t**\tInitialize the random number Seed.  For multiplayer, this will have been done\n\t** in the connection dialogs.  For single-player games, AND if we're not playing\n\t** back a recording, init the Seed to a random value.\n\t*/\n\tif (Session.Type == GAME_NORMAL || Session.Type == GAME_SKIRMISH &&\n\t\t!Session.Play) {\n\n\t\t/*\n\t\t** Set the optional user-specified seed\n\t\t*/\n\t\tif (CustomSeed != 0) {\n\t\t\tSeed = CustomSeed;\n\t\t} else {\n\t\t\tsrand(time(NULL));\n\t\t\tSeed = rand();\n\t\t}\n\t}\n\n\t/*\n\t**\tInitialize the random-number generators\n\t*/\n\tScen.RandomNumber = Seed;\n\tRandNumb = Seed;\n}\n\n\n/***********************************************************************************************\n * Load_Title_Page -- Load the background art for the title page.                              *\n *                                                                                             *\n *    This routine will load the background art in a machine independent format. There is      *\n *    different art required for the hi-res and lo-res versions of the game.                   *\n *                                                                                             *\n * INPUT:   visible  -- Should the title page art be copied to the visible page by this        *\n *                      routine?                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure the mouse is hidden if the image is to be copied to the visible page.   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Load_Title_Page(bool visible)\n{\n#ifdef WIN32\n\tLoad_Title_Screen(\"TITLE.PCX\", &HidPage, CCPalette);\n\tif (visible) {\n\t\tHidPage.Blit(SeenPage);\n\t}\n#else\n\tLoad_Picture(\"TITLE.CPS\", HidPage, HidPage, CCPalette, BM_DEFAULT);\n\tif (visible) {\n\t\tHidPage.Blit(SeenPage);\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * Init_Color_Remaps -- Initialize the text remap tables.                                      *\n *                                                                                             *\n *    There are various color scheme remap tables that are dependant upon the color remap      *\n *    information embedded within the palette control file. This routine will fetch that       *\n *    data and build the text remap tables as indicated.                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Color_Remaps(void)\n{\n\t/*\n\t**\tSetup the remap tables.  PALETTE.CPS contains a special set of pixels in\n\t** the upper-left corner.  Each row of 16 pixels is one range of colors.  The\n\t** first row represents unity (the default color units are drawn in); rows\n\t** after that are the remap colors.\n\t*/\n\n#ifdef WIN32\n\n\tSysMemPage.Clear();\n\tLoad_Picture(\"PALETTE.CPS\", SysMemPage, SysMemPage, NULL, BM_DEFAULT);\n\tSysMemPage.Blit(HidPage);\n#else\n\tLoad_Picture(\"PALETTE.CPS\", HidPage, HidPage, NULL, BM_DEFAULT);\n#endif\n\tfor (PlayerColorType pcolor = PCOLOR_FIRST; pcolor < PCOLOR_COUNT; pcolor++) {\n\n\t\tunsigned char * ptr = ColorRemaps[pcolor].RemapTable;\n\n\t\tfor (int color = 0; color < 256; color++) {\n\t\t\tptr[color] = color;\n\t\t}\n\n\t\tfor (int index = 0; index < 16; index++) {\n\t\t\tptr[HidPage.Get_Pixel(index, 0)] = HidPage.Get_Pixel(index, pcolor);\n\t\t}\n\t\tfor (index = 0; index < 6; index++) {\n\t\t\tColorRemaps[pcolor].FontRemap[10+index] = HidPage.Get_Pixel(2+index, pcolor);\n\t\t}\n\t\tColorRemaps[pcolor].BrightColor = WHITE;\n//\t\tColorRemaps[pcolor].BrightColor = HidPage.Get_Pixel(1, pcolor);\n\t\tColorRemaps[pcolor].Color = HidPage.Get_Pixel(4, pcolor);\n\n\t\tColorRemaps[pcolor].Shadow = HidPage.Get_Pixel(10, pcolor);\n\t\tColorRemaps[pcolor].Background = HidPage.Get_Pixel(9, pcolor);\n\t\tColorRemaps[pcolor].Corners = HidPage.Get_Pixel(7, pcolor);\n\t\tColorRemaps[pcolor].Highlight = HidPage.Get_Pixel(4, pcolor);\n\t\tColorRemaps[pcolor].Bright = HidPage.Get_Pixel(0, pcolor);\n\t\tColorRemaps[pcolor].Underline = HidPage.Get_Pixel(0, pcolor);\n\t\tColorRemaps[pcolor].Bar = HidPage.Get_Pixel(6, pcolor);\n\n\t\t/*\n\t\t**\tThis must grab from column 4 because the multiplayer color dialog palette counts\n\t\t**\ton this to be true.\n\t\t*/\n\t\tColorRemaps[pcolor].Box = HidPage.Get_Pixel(4, pcolor);\n\t}\n\n\t/*\n\t** Now do the special dim grey scheme\n\t*/\n\tfor (int color = 0; color < 256; color++) {\n\t\tGreyScheme.RemapTable[color] = color;\n\t}\n\tfor (int index = 0; index < 6; index++) {\n\t\tGreyScheme.FontRemap[10+index] = HidPage.Get_Pixel(9+index, PCOLOR_GREY) & 0x00FF;\n\t}\n\tGreyScheme.BrightColor = HidPage.Get_Pixel(3, PCOLOR_GREY) & 0x00FF;\n\tGreyScheme.Color = HidPage.Get_Pixel(7, PCOLOR_GREY) & 0x00FF;\n\n\tGreyScheme.Shadow = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(15, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Background = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(14, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Corners = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(13, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Highlight = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(9, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Bright = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(5, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Underline = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(5, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Bar = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(11, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Box = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(11, PCOLOR_GREY) & 0x00FF];\n\n\t/*\n\t** Set up the metallic remap table for the font that prints over the tabs\n\t*/\n\tmemset ((void*)&MetalScheme, 4, sizeof(MetalScheme));\n\tfor (int color_counter = 0; color_counter < 16; color_counter++) {\n\t\tMetalScheme.FontRemap[color_counter] = color_counter;\n\t}\n\tMetalScheme.FontRemap[1] = 128;\n\tMetalScheme.FontRemap[2] = 12;\n\tMetalScheme.FontRemap[3] = 13;\n\tMetalScheme.FontRemap[4] = 14;\n\tMetalScheme.Color = 128;\n\tMetalScheme.Background = 0;\n\tMetalScheme.Underline = 128;\n\n\t/*\n\t** Set up the font remap table for the mission briefing font\n\t*/\n\tfor (int colr = 0; colr < 16; colr++) {\n\t\tColorRemaps[PCOLOR_TYPE].FontRemap[colr] = HidPage.Get_Pixel(colr, PCOLOR_TYPE);\n\t}\n\n\tColorRemaps[PCOLOR_TYPE].Shadow = 11;\n\tColorRemaps[PCOLOR_TYPE].Background = 10;\n\tColorRemaps[PCOLOR_TYPE].Corners = 10;\n\tColorRemaps[PCOLOR_TYPE].Highlight = 9;\n\tColorRemaps[PCOLOR_TYPE].Bright = 15;\n\tColorRemaps[PCOLOR_TYPE].Underline = 11;\n\tColorRemaps[PCOLOR_TYPE].Bar = 11;\n\tColorRemaps[PCOLOR_TYPE].Box = 10;\n\tColorRemaps[PCOLOR_TYPE].BrightColor = 15;\n\tColorRemaps[PCOLOR_TYPE].Color = 9;\n\n\tGadgetClass::Set_Color_Scheme(&ColorRemaps[PCOLOR_DIALOG_BLUE]);\n//\tGadgetClass::Set_Color_Scheme(&ColorRemaps[PCOLOR_BLUE]);\n}\n\n\n/***********************************************************************************************\n * Init_Heaps -- Initialize the game heaps and buffers.                                        *\n *                                                                                             *\n *    This routine will allocate the game heaps and buffers. The rules file has already been   *\n *    processed by the time that this routine is called.                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Heaps(void)\n{\n\t/*\n\t**\tInitialize the game object heaps.\n\t*/\n\tVessels.Set_Heap(Rule.VesselMax);\n\tUnits.Set_Heap(Rule.UnitMax);\n\tFactories.Set_Heap(Rule.FactoryMax);\n\tTerrains.Set_Heap(Rule.TerrainMax);\n\tTemplates.Set_Heap(Rule.TemplateMax);\n\tSmudges.Set_Heap(Rule.SmudgeMax);\n\tOverlays.Set_Heap(Rule.OverlayMax);\n\tInfantry.Set_Heap(Rule.InfantryMax);\n\tBullets.Set_Heap(Rule.BulletMax);\n\tBuildings.Set_Heap(Rule.BuildingMax);\n\tAnims.Set_Heap(Rule.AnimMax);\n\tAircraft.Set_Heap(Rule.AircraftMax);\n\tTriggers.Set_Heap(Rule.TriggerMax);\n\tTeamTypes.Set_Heap(Rule.TeamTypeMax);\n\tTeams.Set_Heap(Rule.TeamMax);\n\tHouses.Set_Heap(HOUSE_MAX);\n\tTriggerTypes.Set_Heap(Rule.TrigTypeMax);\n//\tWeapons.Set_Heap(Rule.WeaponMax);\n\n\t/*\n\t**\tSpeech holding tank buffer. Since speech does not mix, it can be placed\n\t**\tinto a custom holding tank only as large as the largest speech file to\n\t**\tbe played.\n\t*/\n\tfor (int index = 0; index < ARRAY_SIZE(SpeechBuffer); index++) {\n\t\tSpeechBuffer[index] = new char [SPEECH_BUFFER_SIZE];\n\t\tSpeechRecord[index] = VOX_NONE;\n\t\tassert(SpeechBuffer[index] != NULL);\n\t}\n\n\t/*\n\t**\tAllocate the theater buffer block.\n\t*/\n\tTheaterBuffer = new Buffer(THEATER_BUFFER_SIZE);\n\tassert(TheaterBuffer != NULL);\n}\n\n\n/***********************************************************************************************\n * Init_Expansion_Files -- Fetch any override expansion mixfiles.                              *\n *                                                                                             *\n *    This routine will search for and register/cache any override mixfiles found.             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Expansion_Files(void)\n{\n\n\t/*\n\t**\tBefore all else, cache any additional mixfiles.\n\t*/\n\tstruct find_t ff;\t\t// for _dos_findfirst\n\tif (!_dos_findfirst(\"SC*.MIX\", _A_NORMAL, &ff)) {\n\t\tchar * ptr;\n\t\tdo {\n\t\t\tptr = strdup(ff.name);\n\t\t\tnew MFCD(ptr, &FastKey);\n\t\t\tMFCD::Cache(ptr);\n\t\t} while (!_dos_findnext(&ff));\n\t}\n\tif (!_dos_findfirst(\"SS*.MIX\", _A_NORMAL, &ff)) {\n\t\tchar * ptr;\n\t\tdo {\n\t\t\tptr = strdup(ff.name);\n\t\t\tnew MFCD(ptr, &FastKey);\n\t\t} while (!_dos_findnext(&ff));\n\t}\n}\n\n\n/***********************************************************************************************\n * Init_One_Time_Systems -- Initialize internal pointers to the bulk data.                     *\n *                                                                                             *\n *    This performs the one-time processing required after the bulk data has been cached but   *\n *    before the game actually starts. Typically, this routine extracts pointers to all the    *\n *    embedded data sub-files within the main game data mixfile. This routine must be called   *\n *    AFTER the bulk data has been cached.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine AFTER the bulk data has been cached.                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_One_Time_Systems(void)\n{\n\tCall_Back();\n\tMap.One_Time();\n\tLogic.One_Time();\n\tOptions.One_Time();\n\tSession.One_Time();\n\n\tObjectTypeClass::One_Time();\n\tBuildingTypeClass::One_Time();\n\tBulletTypeClass::One_Time();\n\tHouseTypeClass::One_Time();\n\tTemplateTypeClass::One_Time();\n\tOverlayTypeClass::One_Time();\n\tSmudgeTypeClass::One_Time();\n\tTerrainTypeClass::One_Time();\n\tUnitTypeClass::One_Time();\n\tVesselTypeClass::One_Time();\n\tInfantryTypeClass::One_Time();\n\tAnimTypeClass::One_Time();\n\tAircraftTypeClass::One_Time();\n\tHouseClass::One_Time();\n}\n\n\n/***********************************************************************************************\n * Init_Fonts -- Initialize all the game font pointers.                                        *\n *                                                                                             *\n *    This routine is used to fetch pointers to the game fonts. The mixfile containing these   *\n *    fonts must have been previously cached. This routine is a necessary prerequisite to      *\n *    displaying any dialogs or printing any text.                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Fonts(void)\n{\n\tMetal12FontPtr = MFCD::Retrieve(\"12METFNT.FNT\");\n\tMapFontPtr = MFCD::Retrieve(\"HELP.FNT\");\n\tFont6Ptr = MFCD::Retrieve(\"6POINT.FNT\");\n\tGradFont6Ptr = MFCD::Retrieve(\"GRAD6FNT.FNT\");\n\tEditorFont = MFCD::Retrieve(\"EDITFNT.FNT\");\n\tFont8Ptr = MFCD::Retrieve(\"8POINT.FNT\");\n\tFontPtr = (char *)Font8Ptr;\n\tSet_Font(FontPtr);\n\tFont3Ptr = MFCD::Retrieve(\"3POINT.FNT\");\n\tScoreFontPtr = MFCD::Retrieve(\"SCOREFNT.FNT\");\n\tFontLEDPtr = MFCD::Retrieve(\"LED.FNT\");\n\tVCRFontPtr = MFCD::Retrieve(\"VCR.FNT\");\n\tTypeFontPtr = MFCD::Retrieve(\"8POINT.FNT\");    //(\"TYPE.FNT\"); //VG 10/17/96\n}\n\n\n/***********************************************************************************************\n * Init_CDROM_Access -- Initialize the CD-ROM access handler.                                  *\n *                                                                                             *\n *    This routine is called to setup the CD-ROM access or emulation handler. It will ensure   *\n *    that the appropriate CD-ROM is present (dependant on the RequiredCD global).             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The fonts, palettes, and other bootstrap systems must have been initialized     *\n *             prior to calling this routine since this routine will quite likely display      *\n *             a dialog box requesting the appropriate CD be inserted.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_CDROM_Access(void)\n{\n\tVisiblePage.Clear();\n\tHidPage.Clear();\n\n#ifdef FIXIT_VERSION_3\n\t//\tDetermine if we're going to be running from a DVD.\n\t//\tThe entire session will either require a DVD, or the regular CDs. Never both.\n\t//\tCall Using_DVD() to determine which case it is.\n\t//\tHere we set the value that Using_DVD() returns.\n\tDetermine_If_Using_DVD();\n\t//\tForce_CD_Available() is modified when Using_DVD() is true so that all requests become requests for the DVD.\n#endif\n\n\t/*\n\t**\tAlways try to look at the CD-ROM for data files.\n\t*/\n\tif (!CCFileClass::Is_There_Search_Drives()) {\n\n\t\t/*\n\t\t**\tThis call is needed because of a side effect of this function. It will examine the\n\t\t**\tCD-ROMs attached to this computer and set the appropriate status values. Without this\n\t\t**\tcall, the \"?:\\\\\" could not be filled in correctly.\n\t\t*/\n\t\tForce_CD_Available(-1);\n\n\t\t/*\n\t\t** If there are no search drives specified then we must be playing\n\t\t** off cd, so read files from there.\n\t\t*/\n\t\tint error;\n\n\t\tdo {\n\t\t\terror = CCFileClass::Set_Search_Drives(\"?:\\\\\");\n\t\t\tswitch (error) {\n\t\t\t\tcase 1:\n\t\t\t\t\tVisiblePage.Clear();\n\t\t\t\t\tGamePalette.Set();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t\tWWMessageBox().Process(TXT_CD_ERROR1, TXT_OK);\n\t\t\t\t\t//Prog_End();\n\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\n\t\t\t\tcase 2:\n\t\t\t\t\tVisiblePage.Clear();\n\t\t\t\t\tGamePalette.Set();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t\tif (WWMessageBox().Process(TXT_CD_DIALOG_1, TXT_OK, TXT_CANCEL) == 1) {\n\t\t\t\t\t\t//Prog_End();\n\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t}\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tVisiblePage.Clear();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t\tif (!Force_CD_Available(RequiredCD)) {\n\t\t\t\t\t\t//Prog_End();\n\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t}\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} while (error);\n\n\t\tRequiredCD = -1;\n\t} else {\n\n\t\t/*\n\t\t** If there are search drives specified then all files are to be\n\t\t** considered local.\n\t\t*/\n\t\tRequiredCD = -2;\n\t}\n}\n\n\n/***********************************************************************************************\n * Init_Bootstrap_Mixfiles -- Registers and caches any mixfiles needed for bootstrapping.      *\n *                                                                                             *\n *    This routine will register the initial mixfiles that are required to display error       *\n *    messages and get input from the player.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure to call this routine before any dialogs would be displayed to the       *\n *             player.                                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Bootstrap_Mixfiles(void)\n{\n\tint temp = RequiredCD;\n\tRequiredCD = -2;\n\n#ifdef WOLAPI_INTEGRATION\n\tCCFileClass fileWolapiMix( \"WOLAPI.MIX\" );\n\tif( fileWolapiMix.Is_Available() )\n\t{\n\t\tnew MFCD( \"WOLAPI.MIX\", &FastKey );\n\t\tMFCD::Cache( \"WOLAPI.MIX\" );\n\t}\n#endif\n\n#ifdef FIXIT_CSII\t//\tOk. ajw\n\tCCFileClass file2(\"EXPAND2.MIX\");\n\tif (file2.Is_Available()) {\n\t\tnew MFCD(\"EXPAND2.MIX\", &FastKey);\n\t\tbool ok = MFCD::Cache(\"EXPAND2.MIX\");\n\t\tassert(ok);\n\t}\n#endif\n\n#ifdef FIXIT_CSII\t//\tOk. ajw\n\tbool ok1;\n #ifdef WIN32\n\tnew MFCD(\"HIRES1.MIX\", &FastKey);\n\tok1 = MFCD::Cache(\"HIRES1.MIX\");\n\tassert(ok1);\n #else\n\tnew MFCD(\"LORES1.MIX\", &FastKey);\n\tok1 = MFCD::Cache(\"LORES1.MIX\");\n\tassert(ok1);\n #endif\n#endif\n\n#ifdef FIXIT_ANTS\t//\tOk. ajw\n\tCCFileClass file(\"EXPAND.MIX\");\n\tif (file.Is_Available()) {\n\t\tnew MFCD(\"EXPAND.MIX\", &FastKey);\n\t\tbool ok = MFCD::Cache(\"EXPAND.MIX\");\n\t\tassert(ok);\n\t}\n#endif\n\n\tnew MFCD(\"REDALERT.MIX\", &FastKey);\n\n\t/*\n\t**\tBootstrap enough of the system so that the error dialog box can successfully\n\t**\tbe displayed.\n\t*/\n\tnew MFCD(\"LOCAL.MIX\", &FastKey);\t\t\t// Cached.\n\tbool ok = MFCD::Cache(\"LOCAL.MIX\");\n\tassert(ok);\n\n#ifdef WIN32\n\tnew MFCD(\"HIRES.MIX\", &FastKey);\n\tok = MFCD::Cache(\"HIRES.MIX\");\n\tassert(ok);\n\n\tnew MFCD(\"NCHIRES.MIX\", &FastKey);\t\t//Non-cached hires stuff incl VQ palettes\n#else\n\tnew MFCD(\"LORES.MIX\", &FastKey);\n\tok = MFCD::Cache(\"LORES.MIX\");\n\tassert(ok);\n#endif\t//WIN32\n\n\tRequiredCD = temp;\n}\n\n\n/***********************************************************************************************\n * Init_Secondary_Mixfiles -- Register and cache secondary mixfiles.                           *\n *                                                                                             *\n *    This routine is used to register the mixfiles that are needed for main menu processing.  *\n *    Call this routine before the main menu is display and processed.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\n//#define DENZIL_MIXEXTRACT\n#ifdef DENZIL_MIXEXTRACT\nvoid Extract(char* filename, char* outfile);\n#endif\n \nstatic void Init_Secondary_Mixfiles(void)\n{\n\tMainMix = new MFCD(\"MAIN.MIX\", &FastKey);\n\tassert(MainMix != NULL);\n\n\t//Denzil extract mixfile\n\t#ifdef DENZIL_MIXEXTRACT\n\t#if(0)\n\tExtract(\"CONQUER.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\conquer.mix\");\n\tExtract(\"EDHI.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\edhi.mix\");\n\tExtract(\"EDLO.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\edlo.mix\");\n\tExtract(\"GENERAL.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\general.mix\");\n\tExtract(\"INTERIOR.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\interior.mix\");\n\tExtract(\"MOVIES1.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\movies1.mix\");\n\tExtract(\"SCORES.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\scores.mix\");\n\tExtract(\"SNOW.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\snow.mix\");\n\tExtract(\"SOUNDS.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\sounds.mix\");\n\tExtract(\"RUSSIAN.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\russian.mix\");\n\tExtract(\"ALLIES.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\allies.mix\");\n\tExtract(\"TEMPERAT.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\temperat.mix\");\n\t#else\n\tExtract(\"CONQUER.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\conquer.mix\");\n\tExtract(\"EDHI.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\edhi.mix\");\n\tExtract(\"EDLO.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\edlo.mix\");\n\tExtract(\"GENERAL.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\general.mix\");\n\tExtract(\"INTERIOR.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\interior.mix\");\n\tExtract(\"MOVIES2.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\movies2.mix\");\n\tExtract(\"SCORES.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\scores.mix\");\n\tExtract(\"SNOW.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\snow.mix\");\n\tExtract(\"SOUNDS.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\sounds.mix\");\n\tExtract(\"RUSSIAN.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\russian.mix\");\n\tExtract(\"ALLIES.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\allies.mix\");\n\tExtract(\"TEMPERAT.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\temperat.mix\");\n\t#endif\n\t#endif\n\t\n\t/*\n\t**\tInform the file system of the various MIX files.\n\t*/\n\tConquerMix = new MFCD(\"CONQUER.MIX\", &FastKey);\t\t\t// Cached.\n//\tnew MFCD(\"TRANSIT.MIX\", &FastKey);\n\n\tif (GeneralMix == NULL) GeneralMix = new MFCD(\"GENERAL.MIX\", &FastKey);\t\t\t// Never cached.\n\n\tif (CCFileClass(\"MOVIES1.MIX\").Is_Available()) {\n\t\tMoviesMix = new MFCD(\"MOVIES1.MIX\", &FastKey);\t\t\t// Never cached.\n\t} else {\n\t\tMoviesMix = new MFCD(\"MOVIES2.MIX\", &FastKey);\t\t\t// Never cached.\n\t}\n\tassert(MoviesMix != NULL);\n\n\t/*\n\t**\tRegister the score mixfile.\n\t*/\n\tScoresPresent = true;\n\tScoreMix = new MFCD(\"SCORES.MIX\", &FastKey);\n\tThemeClass::Scan();\n\n\t/*\n\t**\tThese are sound card specific, but the install program would have\n\t**\tcopied the correct versions to the hard drive.\n\t*/\n\tnew MFCD(\"SPEECH.MIX\", &FastKey);\t\t\t// Never cached.\n\tnew MFCD(\"SOUNDS.MIX\", &FastKey);\t\t\t// Cached.\n\tnew MFCD(\"RUSSIAN.MIX\", &FastKey);\t\t\t// Cached.\n\tnew MFCD(\"ALLIES.MIX\", &FastKey);\t\t\t// Cached.\n}\n\n\n/***********************************************************************************************\n * Bootstrap -- Perform the initial bootstrap procedure.                                       *\n *                                                                                             *\n *    This routine will load and initialize the game engine such that a dialog box could be    *\n *    displayed. Because this is very critical, call this routine before any other game        *\n *    initialization code.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Bootstrap(void)\n{\n\tBlackPalette.Set();\n\n\t/*\n\t**\tBe sure to short circuit the CD-ROM check if there is a CD-ROM override\n\t**\tpath.\n\t*/\n\tif (CCFileClass::Is_There_Search_Drives()) {\n\t\tRequiredCD = -2;\n\t}\n\n\t/*\n\t** Process the message loop until we are in focus. We need to be in focus to read pixels from\n\t** the screen.\n\t*/\n\t#ifdef WIN32\n\tdo {\n\t\tKeyboard->Check();\n\t} while (!GameInFocus);\n\tAllSurfaces.SurfacesRestored = false;\n\t#endif\n\n\t/*\n\t**\tPerform any special debug-only processing. This includes preparing the\n\t**\tmonochrome screen.\n\t*/\n\tMono_Clear_Screen();\n\n\t/*\n\t**\tRegister and make resident all local mixfiles with particular emphasis\n\t**\ton the mixfiles that are necessary to display and error messages and\n\t**\tprocess further initialization.\n\t*/\n\tInit_Bootstrap_Mixfiles();\n\n\t/*\n\t**\tInitialize the resident font pointers.\n\t*/\n\tInit_Fonts();\n\n#ifndef WIN32\n\t/*\n\t**\tInstall the hard error handler.\n\t*/\n\t_harderr(harderr_handler);\t\t// BG: Install hard error handler\n\n\t/*\n\t** Install a Page Fault handler\n\t*/\n\tif (UsePageFaultHandler) {\n\t\tInstall_Page_Fault_Handle();\n\t}\n#endif\n\n\t/*\n\t**\tSetup the keyboard processor in preparation for the game.\n\t*/\n\t#ifdef WIN32\n\t\tKeyboard->Clear();\n\t#else\n\t\tKeyboard_Attributes_Off(BREAKON | SCROLLLOCKON | TRACKEXT | PAUSEON | CTRLSON | CTRLCON | FILTERONLY | TASKSWITCHABLE);\n\t\tKeyboard_Attributes_On(PASSBREAKS);\n\t\tKeyboard->Clear();\n\t#endif\n\n\t/*\n\t**\tThis is the shape staging buffer. It must always be available, so it is\n\t**\tallocated here and never freed. The library sets the globals ShapeBuffer\n\t**\tand ShapeBufferSize to these values, so it can be accessed for other\n\t**\tpurposes.\n\t*/\n\tSet_Shape_Buffer(new unsigned char[SHAPE_BUFFER_SIZE], SHAPE_BUFFER_SIZE);\n\n\t/*\n\t**\tFetch the language text from the hard drive first. If it cannot be\n\t**\tfound on the hard drive, then look for it in the mixfile.\n\t*/\n#ifdef STEVES_LOAD_OVERRIDE\n\tRawFileClass strings (\"CONQUER.ENG\");\n\tif (strings.Is_Available()){\n\t\tSystemStrings = new char [strings.Size()];\n\t\tstrings.Read((void*)SystemStrings, strings.Size());\n\t}else{\n\t\tSystemStrings = (char const *)MFCD::Retrieve(Language_Name(\"CONQUER\"));\n\t}\n#else\n\tSystemStrings = (char const *)MFCD::Retrieve(Language_Name(\"CONQUER\"));\n#endif\n\tDebugStrings = (char const *)MFCD::Retrieve(\"DEBUG.ENG\");\n\n\t/*\n\t**\tDefault palette initialization.\n\t*/\n\tmemmove((unsigned char *)&GamePalette[0], (void *)MFCD::Retrieve(\"TEMPERAT.PAL\"), 768L);\n\tWhitePalette[0] = BlackPalette[0];\n//\tGamePalette.Set();\n\n\t/*\n\t**\tInitialize expansion files (if present). Expansion files must be located\n\t**\tin the current directory.\n\t*/\n\tInit_Expansion_Files();\n\n\tSidebarScheme.Background \t= BLACK;\n\tSidebarScheme.Corners    \t= LTGREY;\n\tSidebarScheme.Shadow\t\t \t= DKGREY;\n\tSidebarScheme.Highlight  \t= WHITE;\n\tSidebarScheme.Color\t\t \t= LTGREY;\n\tSidebarScheme.Bright\t\t \t= WHITE;\n\tSidebarScheme.BrightColor\t= WHITE;\n\tSidebarScheme.Box\t\t \t \t= LTGREY;\n\tGadgetClass::Set_Color_Scheme(&SidebarScheme);\n}\n\n\n/***********************************************************************************************\n * Init_Mouse -- Initialize the mouse system.                                                  *\n *                                                                                             *\n *    This routine will ensure that a valid mouse driver is present and a working mouse        *\n *    pointer can be displayed. The mouse is hidden when this routine exits.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Mouse(void)\n{\n\t/*\n\t** Since there is no mouse shape currently available we need\n\t** to set one of our own.\n\t*/\n#ifdef WIN32\n\tShowCursor(false);\n#endif\n\tif (MouseInstalled) {\n\t\tvoid const * temp_mouse_shapes = MFCD::Retrieve(\"MOUSE.SHP\");\n\t\tif (temp_mouse_shapes) {\n\t\t\tSet_Mouse_Cursor(0, 0, Extract_Shape(temp_mouse_shapes, 0));\n\t\t\twhile (Get_Mouse_State() > 1) Show_Mouse();\n\t\t}\n\t} else {\n\t\tchar buffer[255];\n\t\tGamePalette.Set();\n\t\tGamePalette.Set();\n\t\tsprintf(buffer, TEXT_NO_MOUSE);\n\t\tVisiblePage.Clear();\n\t\tWWMessageBox().Process(buffer, TXT_OK);\n\t\t//Prog_End();\n\t\tEmergency_Exit(1);\n\t}\n\n\tMap.Set_Default_Mouse(MOUSE_NORMAL, false);\n\tShow_Mouse();\n\twhile (Get_Mouse_State() > 1) Show_Mouse();\n\tCall_Back();\n\tHide_Mouse();\n}\n\n\n#ifdef OBSOLETE\n/***********************************************************************************************\n * Init_Authorization -- Verifies that the player is authorized to play the game.              *\n *                                                                                             *\n *    This is a development routine that restricts access to the game by way of passwords.     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Authorization(void)\n{\n\tif (Special.IsFromInstall) return;\n\n\tLoad_Title_Page();\n#ifdef WIN32\n\tWait_Vert_Blank();\n#else\t//WIN32\n\tInit_Delay();\n\tWait_Vert_Blank(VertBlank);\n#endif\t//WIN32\n\n\tCCPalette.Set();\n//\t\tSet_Palette(Palette);\n\tHidPage.Blit(SeenPage);\n\tShow_Mouse();\n\n\t/*\n\t**\tFetch the type of game to be played. This will be either\n\t**\tC&C:Red Alert or C&C:Plus.\n\t*/\n//tryagain:\n\n\tbool ok = Debug_Flag;\n\tint counter = 3;\n\n\tif (Debug_Flag) ok = true;\n\n\t/*\n\t**\tC&C:Red Alert requires a password for legal entry. Try (three times) to get a correct\n\t**\tpassword. If not found, then try again.\n\t*/\n\tbool skipper = false;\n#ifdef NEVER\n\twhile (!ok && counter) {\n\t\tSmartPtr<char const> str = Fetch_Password(TXT_PASSWORD_CAPTION, TXT_PASSWORD_MESSAGE, TXT_OK);\n\t\tSmartPtr<long const> lptr = &CheatCodes[0];\n\t\twhile (*lptr) {\n\t\t\tif (Obfuscate(str) == *lptr++) {\n\t\t\t\tok = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tlptr = &EditorCodes[0];\n\t\twhile (*lptr) {\n\t\t\tif (Obfuscate(str) == *lptr++) {\n\t\t\t\tok = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tlptr = &PlayCodes[0];\n\t\twhile (*lptr) {\n\t\t\tif (Obfuscate(str) == *lptr++) {\n\t\t\t\tok = true;\n\t\t\t\tskipper = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (ok) break;\n\n\t\tHide_Mouse();\n\t\tLoad_Title_Page();\n\t\tHidPage.Blit(SeenPage);\n\t\tShow_Mouse();\n\t\tDelay(TIMER_SECOND*(4-counter)*1);\n\t\tif (WWMessageBox().Process(TXT_PASSWORD_ERROR, TXT_TRY_AGAIN, TXT_CANCEL)) {\n\t\t\tgoto tryagain;\n\t\t}\n\n\t\tcounter--;\n\t\tif (counter == 0) goto tryagain;\n\t}\n#endif\n\n\tif (!skipper) {\n\t\tCCPalette.Set();\n\t}\n\n\tHide_Mouse();\n\tLoad_Title_Page();\n\tHidPage.Blit(SeenPage);\n\tShow_Mouse();\n\tCall_Back();\n}\n#endif\n\n\n/***********************************************************************************************\n * Init_Bulk_Data -- Initialize the time-consuming mixfile caching.                            *\n *                                                                                             *\n *    This routine is called to handle the time consuming process of game initialization.      *\n *    The title page will be displayed when this routine is called.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine will take a very long time.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Bulk_Data(void)\n{\n\t/*\n\t**\tCache the main game data. This operation can take a very long time.\n\t*/\n\tMFCD::Cache(\"CONQUER.MIX\");\n\tif (SampleType != 0 && !Debug_Quiet) {\n\t\tMFCD::Cache(\"SOUNDS.MIX\");\n\t\tMFCD::Cache(\"RUSSIAN.MIX\");\n\t\tMFCD::Cache(\"ALLIES.MIX\");\n\t}\n\tCall_Back();\n\n\t/*\n\t**\tFetch the tutorial message data.\n\t*/\n\tINIClass ini;\n\tini.Load(CCFileClass(\"TUTORIAL.INI\"));\n\tfor (int index = 0; index < ARRAY_SIZE(TutorialText); index++) {\n\t\tTutorialText[index] = NULL;\n\n\t\tchar buffer[128];\n\t\tchar num[10];\n\t\tsprintf(num, \"%d\", index);\n\t\tif (ini.Get_String(\"Tutorial\", num, \"\", buffer, sizeof(buffer))) {\n\t\t\tTutorialText[index] = strdup(buffer);\n\t\t}\n\t}\n\n\t/*\n\t**\tPerform one-time game system initializations.\n\t*/\n\tInit_One_Time_Systems();\n}\n\n\n/***********************************************************************************************\n * Init_Keys -- Initialize the cryptographic keys.                                             *\n *                                                                                             *\n *    This routine will initialize the fast cryptographic key. It will also initialize the     *\n *    slow one if this is a scenario editor version of the game.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Keys(void)\n{\n\tRAMFileClass file((void*)Keys, strlen(Keys));\n\tINIClass ini;\n\tini.Load(file);\n\n\tFastKey = ini.Get_PKey(true);\n#ifdef SCENARIO_EDITOR\n\tSlowKey = ini.Get_PKey(false);\n#endif\n}\n\n\n/***************************************************************************\n * Save_Recording_Values -- Saves multiplayer-specific values              *\n *                                                                         *\n * This routine saves multiplayer values that need to be restored for a\t\t*\n * save game.  In addition to saving the random # seed for this scenario, \t*\n * it saves the contents of the actual random number generator; this \t\t*\n * ensures that the random # sequencer will pick up where it left off when\t*\n * the game was saved.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This routine also saves the header for a Recording file, so it must \t\t*\n * save some data not needed specifically by a save-game file (ie Seed).\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\tfile to save to\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = success, false = failure\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/28/1995 BRR : Created.                                             *\n *=========================================================================*/\nbool Save_Recording_Values(CCFileClass & file)\n{\n\tSession.Save(file);\n\tfile.Write(&BuildLevel, sizeof(BuildLevel));\n\tfile.Write(&Debug_Unshroud, sizeof(Debug_Unshroud));\n\tfile.Write(&Seed, sizeof(Seed));\n\tfile.Write(&Scen.Scenario, sizeof(Scen.Scenario));\n\tfile.Write(Scen.ScenarioName, sizeof(Scen.ScenarioName));\n\tfile.Write(&Whom, sizeof(Whom));\n\tfile.Write(&Special, sizeof(SpecialClass));\n\tfile.Write(&Options, sizeof(GameOptionsClass));\n\n\treturn (true);\n}\n\n\n/***************************************************************************\n * Load_Recording_Values -- Loads multiplayer-specific values              *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\t\tfile to load from\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = success, false = failure\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/28/1995 BRR : Created.                                             *\n *=========================================================================*/\nbool Load_Recording_Values(CCFileClass & file)\n{\n\tSession.Load(file);\n\tfile.Read(&BuildLevel, sizeof(BuildLevel));\n\tfile.Read(&Debug_Unshroud, sizeof(Debug_Unshroud));\n\tfile.Read(&Seed, sizeof(Seed));\n\tfile.Read(&Scen.Scenario, sizeof(Scen.Scenario));\n\tfile.Read(Scen.ScenarioName, sizeof(Scen.ScenarioName));\n\tfile.Read(&Whom, sizeof(Whom));\n\tfile.Read(&Special, sizeof(SpecialClass));\n\tfile.Read(&Options, sizeof(GameOptionsClass));\n\treturn (true);\n}\n\nextern \"C\" {\nvoid __PRO(void) {\n//\tprintf(\"_pro\\n\");\n}\n}\n\n#ifdef DENZIL_MIXEXTRACT\nvoid Extract(char* filename, char* outname)\n\t{\n\tCCFileClass inFile(filename);\n\tCCFileClass outFile(outname);\n\n\tinFile.Open();\n\toutFile.Open(WRITE);\n\t\n\tvoid* buffer = malloc(32768);\n\n\tif (buffer)\n\t\t{\n\t\tunsigned long size = inFile.Size();\n\t\tunsigned long bytes;\n\n\t\twhile (size > 0)\n\t\t\t{\n\t\t\tbytes = inFile.Read(buffer, 32768);\n\t\t\toutFile.Write(buffer, bytes);\n\t\t\tsize -= bytes;\n\t\t\t}\n\t\t\n\t\tfree(buffer);\n\t\t}\n\t}\n#endif\n\n\n#ifdef FIXIT_VERSION_3\n\nbool bUsingDVD = false;\n\nconst char* Game_Registry_Key();\n\n//***********************************************************************************************\nbool Is_DVD_Installed()\n{\n\tbool bInstalled;\n\tHKEY hKey;\n\tif( RegOpenKeyEx( HKEY_LOCAL_MACHINE, Game_Registry_Key(), 0, KEY_READ, &hKey ) != ERROR_SUCCESS )\n\t\treturn false;\n\tDWORD dwValue;\n\tDWORD dwBufSize = sizeof( DWORD );\n\tif( RegQueryValueEx( hKey, \"DVD\", 0, NULL, (LPBYTE)&dwValue, &dwBufSize ) != ERROR_SUCCESS )\n\t\tbInstalled = false;\n\telse\n\t\tbInstalled = (bool)dwValue;\t\t\t//\t(Presumably true, if it's there...)\n\n\tRegCloseKey( hKey );\n\n\treturn bInstalled;\n}\n\n//***********************************************************************************************\nbool Determine_If_Using_DVD()\n{\n\t//\tDetermines if the user has a DVD currently available. If they do, we'll use it throughout the\n\t//\tsession. Else we won't check for it again and will always ask for CDs.\n\tif( Is_DVD_Installed() )\n\t{\n\t\tif( Force_CD_Available( 5 ) )\n\t\t{\n\t\t\tbUsingDVD = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//\tUser hit cancel. Allow things to progress normally. They will be prompted for\n\t\t\t//\ta Red Alert disk as usual.\n\t\t\tbUsingDVD = false;\n\t\t}\n\t}\n\telse\n\t\tbUsingDVD = false;\n\t\n\treturn bUsingDVD;\n}\n\n//***********************************************************************************************\nbool Using_DVD()\n{\n\treturn bUsingDVD;\n}\n\n#endif\n"
  },
  {
    "path": "CODE/INIT.CPP.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\init.cpv   4.82   24 Oct 1996 12:53:00   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INIT.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : January 20, 1992                                             *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Anim_Init -- Initialize the VQ animation control structure.                               *\n *   Bootstrap -- Perform the initial bootstrap procedure.                                     *\n *   Calculate_CRC -- Calculates a one-way hash from a data block.                             *\n *   Init_Authorization -- Verifies that the player is authorized to play the game.            *\n *   Init_Bootstrap_Mixfiles -- Registers and caches any mixfiles needed for bootstrapping.    *\n *   Init_Bulk_Data -- Initialize the time-consuming mixfile caching.                          *\n *   Init_CDROM_Access -- Initialize the CD-ROM access handler.                                *\n *   Init_Color_Remaps -- Initialize the text remap tables.                                    *\n *   Init_Expansion_Files -- Fetch any override expansion mixfiles.                            *\n *   Init_Fonts -- Initialize all the game font pointers.                                      *\n *   Init_Game -- Main game initialization routine.                                            *\n *   Init_Heaps -- Initialize the game heaps and buffers.                                      *\n *   Init_Keys -- Initialize the cryptographic keys.                                           *\n *   Init_Mouse -- Initialize the mouse system.                                                *\n *   Init_One_Time_Systems -- Initialize internal pointers to the bulk data.                   *\n *   Init_Random -- Initializes the random-number generator                                    *\n *   Init_Secondary_Mixfiles -- Register and cache secondary mixfiles.                         *\n *   Load_Recording_Values -- Loads recording values from recording file                       *\n *   Load_Title_Page -- Load the background art for the title page.                            *\n *   Obfuscate -- Sufficiently transform parameter to thwart casual hackers.                   *\n *   Parse_Command_Line -- Parses the command line parameters.                                 *\n *   Parse_INI_File -- Parses CONQUER.INI for special options                                  *\n *   Play_Intro -- plays the introduction & logo movies                                        *\n *   Save_Recording_Values -- Saves recording values to a recording file                       *\n *   Select_Game -- The game's main menu                                                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"loaddlg.h\"\n#ifdef WIN32\n#include\t\"tcpip.h\"\n#endif\n#include\t<conio.h>\n#include\t<dos.h>\n#ifndef WIN32\n#include\t<sys\\timeb.h>\n#endif\n#include  \"ccdde.h\"\n\n#include <time.h>\n\nRemapControlType SidebarScheme;\n\n\n/****************************************\n**\tFunction prototypes for this module **\n*****************************************/\nstatic void Play_Intro(bool sequenced=false);\nstatic void Init_Color_Remaps(void);\nstatic void Init_Heaps(void);\nstatic void Init_Expansion_Files(void);\nstatic void Init_One_Time_Systems(void);\nstatic void Init_Fonts(void);\nstatic void Init_CDROM_Access(void);\nstatic void Init_Bootstrap_Mixfiles(void);\nstatic void Init_Secondary_Mixfiles(void);\nstatic void Init_Mouse(void);\nstatic void Bootstrap(void);\n//static void Init_Authorization(void);\nstatic void Init_Bulk_Data(void);\nstatic void Init_Keys(void);\n\nextern \"C\" {\nextern long RandNumb;\n}\n#ifndef WIN32\nstatic int UsePageFaultHandler = 1;\t\t\t\t// 1 = install PFH\n#endif\t//WIN32\n\n//extern int SimRandIndex;\nvoid Init_Random(void);\n\n#define ATTRACT_MODE_TIMEOUT\t3600\t\t// timeout for attract mode\n\nbool Load_Recording_Values(CCFileClass & file);\nbool Save_Recording_Values(CCFileClass & file);\n\n\n/***********************************************************************************************\n * Init_Game -- Main game initialization routine.                                              *\n *                                                                                             *\n *    Perform all one-time game initializations here. This includes all                        *\n *    allocations and table setups. The intro and other one-time startup                       *\n *    tasks are also performed here.                                                           *\n *                                                                                             *\n * INPUT:   argc,argv   -- Command line arguments.                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this ONCE!     \u001b\u001b\n                                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\n#include\t\"sha.h\"\n//#include    <locale.h>\nbool Init_Game(int , char * [])\n{\n\n\t//must set international locale up front\n\t//V.Grippi 10/22/96\n\t//#ifdef WIN32\n        //#ifdef German\n        // \tsetlocale(LC_ALL,  \"German\");\n\t//#endif\n\t//#endif\n\n\t/*\n\t**\tAllocate the benchmark tracking objects only if the machine and\n\t**\tcompile flags indicate.\n\t*/\n\t#ifdef CHEAT_KEYS\n\tif (Processor() >= 2) {\n\t\tBenches = new Benchmark [BENCH_COUNT];\n\t}\n\t#endif\n\n\t/*\n\t**\tInitialize the encryption keys.\n\t*/\n\tInit_Keys();\n\n\t/*\n\t**\tBootstrap as much as possible before error-prone initializations are\n\t**\tperformed. This bootstrap process will enable the error message\n\t**\thandler to function.\n\t*/\n        //VG_MONO\n        Mono_Print(\"about to BOOTSTRAP ourselves!!!!\\n\");\n\tBootstrap();\n                \n\t/*\n\t**\tCheck for an initialize a working mouse pointer. Display error and bail if\n\t**\tno mouse driver is installed.\n\t*/\n\tInit_Mouse();\n\n\t/*\n\t**\tInitialize access to the CD-ROM and ensure that the CD is inserted. This can, and\n\t**\tmost likely will, result in a visible prompt.\n\t*/\n\tInit_CDROM_Access();\n\n\t/*\n\t**\tRegister and cache any secondary mixfiles.\n\t*/\n        //VG_MONO\n        Mono_Print(\"about to call init secondary mixfiles\\n\");\n\tInit_Secondary_Mixfiles();\n\n\t/*\n\t**\tThis is a special hack to initialize the heaps that must be in place before the\n\t**\trules file is processed. These heaps should properly be allocated as a consequence\n\t**\tof processing the rules.ini file, but that is a bit beyond the capabilities of\n\t**\tthe rule parser routine (currently).\n\t*/\n\tHouseTypes.Set_Heap(HOUSE_COUNT);\n\tBuildingTypes.Set_Heap(STRUCT_COUNT);\n\tAircraftTypes.Set_Heap(AIRCRAFT_COUNT);\n\tInfantryTypes.Set_Heap(INFANTRY_COUNT);\n\tBulletTypes.Set_Heap(BULLET_COUNT);\n\tAnimTypes.Set_Heap(ANIM_COUNT);\n\tUnitTypes.Set_Heap(UNIT_COUNT);\n\tVesselTypes.Set_Heap(VESSEL_COUNT);\n\tTemplateTypes.Set_Heap(TEMPLATE_COUNT);\n\tTerrainTypes.Set_Heap(TERRAIN_COUNT);\n\tOverlayTypes.Set_Heap(OVERLAY_COUNT);\n\tSmudgeTypes.Set_Heap(SMUDGE_COUNT);\n\n\tHouseTypeClass::Init_Heap();\n\tBuildingTypeClass::Init_Heap();\n\tAircraftTypeClass::Init_Heap();\n\tInfantryTypeClass::Init_Heap();\n\tBulletTypeClass::Init_Heap();\n\tAnimTypeClass::Init_Heap();\n\tUnitTypeClass::Init_Heap();\n\tVesselTypeClass::Init_Heap();\n\tTemplateTypeClass::Init_Heap();\n\tTerrainTypeClass::Init_Heap();\n\tOverlayTypeClass::Init_Heap();\n\tSmudgeTypeClass::Init_Heap();\n\n\t/*\n\t**\tFind and process any rules for this game.\n\t*/\n\tif (RuleINI.Load(CCFileClass(\"RULES.INI\"), false)) {\n\t\tRule.Process(RuleINI);\n\t}\n\n\tSession.MaxPlayers = Rule.MaxPlayers;\n\n\t/*\n\t**\tInitialize the game object heaps as well as other rules-dependant buffer allocations.\n\t*/\n\tInit_Heaps();\n\n\t/*\n\t**\tInitialize the animation system.\n\t*/\n\tAnim_Init();\n\n\tif (SpawnedFromWChat){\n\t\tSpecial.IsFromWChat = true;\n\t}\n\n\t/*\n\t**\tPlay the startup animation.\n\t*/\n\tif (!Special.IsFromInstall && !Special.IsFromWChat) {\n\t\tVisiblePage.Clear();\n\t\tPlay_Intro();\n\t\tmemset(CurrentPalette, 0x01, 768);\n\t\tWhitePalette.Set();\n\t} else {\n\t\tmemset(CurrentPalette, 0x01, 768);\n\t}\n\n\t/*\n\t**\tInitialize the text remap tables.\n\t*/\n\tInit_Color_Remaps();\n\n\t/*\n\t**\tGet authorization to access the game.\n\t*/\n//\tInit_Authorization();\n//\tShow_Mouse();\n\n\t/*\n\t**\tIf not automatically launching into the intro, then display the title\n\t**\tpage while the bulk data is cached.\n\t*/\n\tif (!Special.IsFromInstall) {\n//\t\tHide_Mouse();\n\t\tLoad_Title_Page(true);\n\t\tCCPalette.Set(FADE_PALETTE_SLOW);\n//\t\tHidPage.Blit(SeenPage);\n//\t\tShow_Mouse();\n\t\tCall_Back();\n\t}\n\n\t/*\n\t**\tInitialize the bulk data. This takes the longest time and must be performed once\n\t**\tbefore the regular game starts.\n\t*/\n\tInit_Bulk_Data();\n\n\t/*\n\t**\tInitialize the multiplayer score values\n\t*/\n\tSession.GamesPlayed = 0;\n\tSession.NumScores = 0;\n\tSession.CurGame = 0;\n\tfor (int i = 0; i < MAX_MULTI_NAMES; i++) {\n\t\tSession.Score[i].Name[0] = '\\0';\n\t\tSession.Score[i].Wins = 0;\n\t\tfor (int j = 0; j < MAX_MULTI_GAMES; j++) {\n\t\t\tSession.Score[i].Kills[j] = -1;\t// -1 = this player didn't play this round\n\t\t}\n\t}\n\n\t/*\n\t** Copy the title screen's palette into the GamePalette & OriginalPalette,\n\t** because the options Load routine uses these palettes to set the brightness, etc.\n\t*/\n\tGamePalette = CCPalette;\n//\tInGamePalette = CCPalette;\n\tOriginalPalette = CCPalette;\n\n\t/*\n\t**\tRead game options, so the GameSpeed is initialized when multiplayer\n\t** dialogs are invoked.  (GameSpeed must be synchronized between systems.)\n\t*/\n\tOptions.Load_Settings();\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Select_Game -- The game's main menu                                                         *\n *                                                                                             *\n * INPUT:                                                                                      *\n *\t\tfade\t\tif true, will fade the palette in gradually\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/05/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nbool Select_Game(bool fade)\n{\n\tenum {\n\t\tSEL_TIMEOUT = -1,\t\t\t\t// main menu timeout--go into attract mode\n\t\tSEL_NEW_SCENARIO,\t\t\t\t// Expansion scenario to play.\n\t\tSEL_START_NEW_GAME,\t\t\t// start a new game\n#ifdef WIN32\n\t\tSEL_INTERNET,\n#endif\t//WIN32\n\t\tSEL_LOAD_MISSION,\t\t\t\t// load a saved game\n\t\tSEL_MULTIPLAYER_GAME,\t\t// play modem/null-modem/network game\n\t\tSEL_INTRO,\t\t\t\t\t\t// couch-potato mode\n\t\tSEL_EXIT,\t\t\t\t\t\t// exit to DOS\n\t\tSEL_FAME,\t\t\t\t\t\t// view the hall o' fame\n\t\tSEL_NONE,\t\t\t\t\t\t// placeholder default value\n\t};\n\tbool gameloaded=false;\t\t\t// Has the game been loaded from the menu?\n\tint selection;\t\t\t\t\t\t// the default selection\n\tbool process = true;\t\t\t\t// false = break out of while loop\n\tbool display = true;\n\n\tif (Special.IsFromInstall) {\n\t\tdisplay = false;\n\t}\n\n\tShow_Mouse();\n\n#ifdef WIN32\n\t/*\n\t** Enable the DDE Server so we can get internet start game packets from WChat\n\t*/\n\tDDEServer.Enable();\n#endif\t//WIN32\n\n\t/*\n\t**\t[Re]set any globals that need it, in preparation for a new scenario\n\t*/\n\tGameActive = true;\n\tDoList.Init();\n\t#ifdef MIRROR_QUEUE\n\tMirrorList.Init();\n\t#endif\n\tOutList.Init();\n\tFrame = 0;\n\tScen.MissionTimer = 0;\n\tScen.MissionTimer.Stop();\n\tPlayerWins = false;\n\tPlayerLoses = false;\n\tSession.ObiWan = false;\n\tDebug_Unshroud = false;\n\tMap.Set_Cursor_Shape(0);\n\tMap.PendingObjectPtr = 0;\n\tMap.PendingObject = 0;\n\tMap.PendingHouse = HOUSE_NONE;\n\n\tSession.ProcessTicks = 0;\n\tSession.ProcessFrames = 0;\n\tSession.DesiredFrameRate = 30;\n\n\t/*\n\t**\tInit multiplayer game scores.  Let Wins accumulate; just init the current\n\t** Kills for this game.  Kills of -1 means this player didn't play this round.\n\t*/\n\tfor (int i = 0 ; i < MAX_MULTI_GAMES; i++) {\n\t\tSession.Score[i].Kills[Session.CurGame] = -1;\n\t}\n\n\t/*\n\t**\tSet default mouse shape\n\t*/\n\tMap.Set_Default_Mouse(MOUSE_NORMAL, false);\n\n\t/*\n\t**\tIf the last game we played was a multiplayer game, jump right to that\n\t**\tmenu by pre-setting 'selection'.\n\t*/\n\tif (Session.Type == GAME_NORMAL) {\n\t\tselection = SEL_NONE;\n\t} else {\n\t\tselection = SEL_MULTIPLAYER_GAME;\n\t}\n\n\t/*\n\t**\tMain menu processing; only do this if we're not in editor mode.\n\t*/\n\tif (!Debug_Map) {\n\n\t\t/*\n\t\t**\tMenu selection processing loop\n\t\t*/\n\t\tTheme.Queue_Song(THEME_CRUS);\n\n\t\t/*\n\t\t** If we're playing back a recording, load all pertinent values & skip\n\t\t** the menu loop.  Hide the now-useless mouse pointer.\n\t\t*/\n\t\tif (Session.Play && Session.RecordFile.Is_Available()) {\n\t\t\tif (Session.RecordFile.Open(READ)) {\n\t\t\t\tLoad_Recording_Values(Session.RecordFile);\n\t\t\t\tprocess = false;\n\t\t\t\tTheme.Fade_Out();\n\t\t\t} else\n\t\t\t\tSession.Play = false;\n\t\t}\n\n#ifdef WIN32\n\t\t/*\n\t\t** Handle case where we were spawned from Wchat\n\t\t*/\n\t\tif (SpawnedFromWChat) {\n\t\t\tSpecial.IsFromInstall = false;\t//Dont play intro if we were spawned from wchat\n\t\t\tselection = SEL_INTERNET;\n\t\t\tTheme.Queue_Song(THEME_QUIET);\n\t\t\tSession.Type = GAME_INTERNET;\n\t\t\tdisplay = false;\n\t\t\tSet_Logic_Page(SeenBuff);\n\t\t}\n#endif\t//WIN32\n\n\t\twhile (process) {\n\n\t\t\t/*\n\t\t\t**\tRedraw the title page if needed\n\t\t\t*/\n\t\t\tif (display) {\n\t\t\t\tHide_Mouse();\n\n\t\t\t\t/*\n\t\t\t\t**\tDisplay the title page; fade it in if this is the first time\n\t\t\t\t**\tthrough the loop, and the 'fade' flag is true\n\t\t\t\t*/\n\t\t\t\tLoad_Title_Page();\n\t\t\t\tGamePalette = CCPalette;\n\n\t\t\t\tHidPage.Blit(SeenPage);\n//\t\t\t\tif (fade) {\n//\t\t\t\t\tWhitePalette.Set();\n//\t\t\t\t\tCCPalette.Set(FADE_PALETTE_SLOW, Call_Back);\n//\t\t\t\t\tfade = false;\n//\t\t\t\t} else {\n\t\t\t\t\tCCPalette.Set();\n//\t\t\t\t}\n\n\t\t\t\tSet_Logic_Page(SeenBuff);\n\t\t\t\tdisplay = false;\n\t\t\t\tShow_Mouse();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDisplay menu and fetch selection from player.\n\t\t\t*/\n\t\t\tif (Special.IsFromInstall) selection = SEL_START_NEW_GAME;\n\n#ifdef WIN32\n\t\t\t/*\n\t\t\t** Handle case where we were spawned from Wchat and our start game\n\t\t\t**  packet has already arrived\n\t\t\t*/\n\t\t\tif (Special.IsFromWChat && DDEServer.Get_MPlayer_Game_Info()) {\n\t\t\t\tCheck_From_WChat(NULL);\n\t\t\t\tselection = SEL_MULTIPLAYER_GAME;\n\t\t\t\tTheme.Queue_Song(THEME_QUIET);\n\t\t\t\tSession.Type = GAME_INTERNET;\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t** We werent spawned but we could still receive a DDE packet from wchat\n\t\t\t\t*/\n\t\t\t\tif (DDEServer.Get_MPlayer_Game_Info()) {\n\t\t\t\t\tCheck_From_WChat(NULL);\n\t\t\t\t\t/*\n\t\t\t\t\t** Make sure top and bottom of screen are clear in 640x480 mode\n\t\t\t\t\t*/\n\t\t\t\t\tif (ScreenHeight == 480) {\n\t\t\t\t\t\tVisiblePage.Fill_Rect (0, 0, 639, 40, 0);\n\t\t\t\t\t\tVisiblePage.Fill_Rect (0, 440, 639, 479, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n#endif\t//WIN32\n\n\t\t\tif (selection == SEL_NONE) {\n\t\t\t\tselection = Main_Menu(ATTRACT_MODE_TIMEOUT);\n\t\t\t}\n\t\t\tCall_Back();\n\n\t\t\tswitch (selection) {\n\n\t\t\t\t/*\n\t\t\t\t**\tPick an expansion scenario.\n\t\t\t\t*/\n\t\t\t\tcase SEL_NEW_SCENARIO:\n\t\t\t\t\tScen.CarryOverMoney = 0;\n\t\t\t\t\tIsTanyaDead = false;\n\t\t\t\t\tSaveTanya = false;\n\t\t\t\t\tExpansion_Dialog();\n\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\tTheme.Queue_Song(THEME_FIRST);\n\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tSEL_START_NEW_GAME: Play the game\n\t\t\t\t*/\n\t\t\t\tcase SEL_START_NEW_GAME:\n\t\t\t\t\tif (Special.IsFromInstall) {\n\t\t\t\t\t\tScen.CDifficulty = DIFF_NORMAL;\n\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tswitch (Fetch_Difficulty()) {\n\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\tScen.CDifficulty = DIFF_HARD;\n\t\t\t\t\t\t\t\tScen.Difficulty = DIFF_EASY;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\tScen.CDifficulty = DIFF_HARD;\n\t\t\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\tScen.CDifficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\tScen.CDifficulty = DIFF_EASY;\n\t\t\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\t\tScen.CDifficulty = DIFF_EASY;\n\t\t\t\t\t\t\t\tScen.Difficulty = DIFF_HARD;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tScen.CarryOverMoney = 0;\n\t\t\t\t\tBuildLevel = 1;\n\t\t\t\t\tIsTanyaDead = false;\n\t\t\t\t\tSaveTanya = false;\n\t\t\t\t\tWhom = HOUSE_GOOD;\n\n\t\t\t\t\tif (!Special.IsFromInstall) {\n\t\t\t\t\t\tswitch (WWMessageBox().Process(TXT_CHOOSE, TXT_ALLIES, TXT_SOVIET)) {\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\tScen.Set_Scenario_Name(\"SCG01EA.INI\");\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\tScen.Set_Scenario_Name(\"SCU01EA.INI\");\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\tLoad_Title_Page();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\tHide_Mouse();\n\t\t\t\t\t\tChoose_Side();\n\t\t\t\t\t\tif (CurrentCD == 0) {\n\t\t\t\t\t\t\tScen.Set_Scenario_Name(\"SCG01EA.INI\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tScen.Set_Scenario_Name(\"SCU01EA.INI\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n#ifdef WIN32\n\t\t\t\t/*\n\t\t\t\t** Internet game is requested\n\t\t\t\t*/\n\t\t\t\tcase SEL_INTERNET:\n\t\t\t\t\t/*\n\t\t\t\t\t** Only call up the internet menu code if we dont already have connect info from WChat\n\t\t\t\t\t*/\n\t\t\t\t\tif (!DDEServer.Get_MPlayer_Game_Info()) {\n\t\t\t\t\t\tif (Do_The_Internet_Menu_Thang() && DDEServer.Get_MPlayer_Game_Info()) {\n\t\t\t\t\t\t\tCheck_From_WChat(NULL);\n\t\t\t\t\t\t\tselection = SEL_MULTIPLAYER_GAME;\n\t\t\t\t\t\t\tdisplay = false;\n\t\t\t\t\t\t\tSession.Type = GAME_INTERNET;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCheck_From_WChat(NULL);\n\t\t\t\t\t\tdisplay = false;\n\t\t\t\t\t\tSession.Type = GAME_INTERNET;\n\t\t\t\t\t\tselection = SEL_MULTIPLAYER_GAME;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n#endif\t//WIN32\n\n\t\t\t\t/*\n\t\t\t\t**\tLoad a saved game.\n\t\t\t\t*/\n\t\t\t\tcase SEL_LOAD_MISSION:\n\t\t\t\t\tif (LoadOptionsClass(LoadOptionsClass::LOAD).Process()) {\n\t\t\t\t\t\tTheme.Queue_Song(THEME_FIRST);\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tgameloaded = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tSEL_MULTIPLAYER_GAME: set 'Session.Type' to NULL-modem, modem, or\n\t\t\t\t**\tnetwork play.\n\t\t\t\t*/\n\t\t\t\tcase SEL_MULTIPLAYER_GAME:\n\t\t\t\t\tswitch (Session.Type) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf 'Session.Type' isn't already set up for a multiplayer game,\n\t\t\t\t\t\t**\twe must prompt the user for which type of multiplayer game\n\t\t\t\t\t\t**\tthey want.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase GAME_NORMAL:\n\t\t\t\t\t\t\tSession.Type = Select_MPlayer_Game();\n\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// 'Cancel'\n\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase GAME_SKIRMISH:\n\t\t\t\t\t\t\tif ( !Com_Scenario_Dialog(true) ) {\n\t\t\t\t\t\t\t\tSession.Type = Select_MPlayer_Game();\n\t\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// user hit Cancel\n\t\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase GAME_NULL_MODEM:\n\t\t\t\t\t\tcase GAME_MODEM:\n\t\t\t\t\t\t\tif ( Session.Type != GAME_SKIRMISH && NullModem.Num_Connections() ) {\n\t\t\t\t\t\t\t\tNullModem.Init_Send_Queue();\n\n\t\t\t\t\t\t\t\tif ((Session.Type == GAME_NULL_MODEM &&\n\t\t\t\t\t\t\t\t\tSession.ModemType == MODEM_NULL_HOST) ||\n\t\t\t\t\t\t\t\t\t(Session.Type == GAME_MODEM &&\n\t\t\t\t\t\t\t\t\tSession.ModemType == MODEM_DIALER) ) {\n\n\t\t\t\t\t\t\t\t\tif ( !Com_Scenario_Dialog() ) {\n\t\t\t\t\t\t\t\t\t\tSession.Type = Select_Serial_Dialog();\n\t\t\t\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// user hit Cancel\n\t\t\t\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tif ( !Com_Show_Scenario_Dialog() ) {\n\t\t\t\t\t\t\t\t\t\tSession.Type = Select_Serial_Dialog();\n\t\t\t\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// user hit Cancel\n\t\t\t\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tSession.Type = Select_MPlayer_Game();\n\t\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// 'Cancel'\n\t\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n#ifdef WIN32\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Handle being spawned from WChat. Internet play based on IPX code.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase GAME_INTERNET:\n\t\t\t\t\t\t\tif (Special.IsFromWChat) {\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** Give myself focus.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tSetForegroundWindow ( MainWindow );\n\t\t\t\t\t\t\t\tShowWindow ( MainWindow, ShowCommand );\n\n\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - About to initialise Winsock.\\n\");\n\t\t\t\t\t\t\t\tif (Winsock.Init()) {\n\t\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - About to read multiplayer settings.\\n\");\n\t\t\t\t\t\t\t\t\tSession.Read_MultiPlayer_Settings ();\n\t\t\t\t\t\t\t\t\tServer = PlanetWestwoodIsHost;\n\n\t\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - About to set addresses.\\n\");\n\t\t\t\t\t\t\t\t\tWinsock.Set_Host_Address(PlanetWestwoodIPAddress);\n\n\t\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - About to call Start_Server or Start_Client.\\n\");\n\t\t\t\t\t\t\t\t\tif (Server) {\n\t\t\t\t\t\t\t\t\t\tWinsock.Start_Server();\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tWinsock.Start_Client();\n\t\t\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t** Flush out any pending packets from a previous game.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - About to flush packet queue.\\n\");\n\t\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - Allocating scrap memory.\\n\");\n\t\t\t\t\t\t\t\t\tchar *temp_buffer = new char[1024];\n\n\t\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - Creating timer class instance.\\n\");\n\t\t\t\t\t\t\t\t\tCountDownTimerClass ptimer;\n\n\t\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - Entering read loop.\\n\");\n\t\t\t\t\t\t\t\t\twhile (Winsock.Read(temp_buffer, 1024)) {\n\n\t\t\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - Discarding a packet.\\n\");\n\t\t\t\t\t\t\t\t\t\tptimer.Set (30, true);\n\t\t\t\t\t\t\t\t\t\twhile (ptimer.Time()) {};\n\t\t\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - Ready to check for more packets.\\n\");\n\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - About to delete scrap memory.\\n\");\n\t\t\t\t\t\t\t\t\tdelete temp_buffer;\n\n\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - Winsock failed to initialise.\\n\");\n\t\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\t\tselection = SEL_EXIT;\n\t\t\t\t\t\t\t\t\tSpecial.IsFromWChat = false;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - About to call Init_Network.\\n\");\n\t\t\t\t\t\t\t\tInit_Network();\n\n\t\t\t\t\t\t\t\tif (DDEServer.Get_MPlayer_Game_Info()) {\n\t\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - About to call Read_Game_Options.\\n\");\n\t\t\t\t\t\t\t\t\tRead_Game_Options( NULL );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tRead_Game_Options( \"C&CSPAWN.INI\" );\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (Server) {\n\n\t\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - About to call Server_Remote_Connect.\\n\");\n\t\t\t\t\t\t\t\t\tif (Server_Remote_Connect()) {\n\t\t\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - Server_Remote_Connect returned success.\\n\");\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t** We failed to connect to the other player\n\t\t\t\t\t\t\t\t\t\t *\n\t\t\t\t\t\t\t\t\t\t *   SEND FAILURE PACKET TO WCHAT HERE !!!!!\n\t\t\t\t\t\t\t\t\t\t *\n\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\tWinsock.Close();\n\t\t\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t\t\tDDEServer.Delete_MPlayer_Game_Info();\t// Make sure we dont go round in an infinite loop\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - About to call Client_Remote_Connect.\\n\");\n\t\t\t\t\t\t\t\t\tif (Client_Remote_Connect()) {\n\t\t\t\t\t\t\t\t\t\tOutputDebugString (\"RA95 - Client_Remote_Connect returned success.\\n\");\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t** We failed to connect to the other player\n\t\t\t\t\t\t\t\t\t\t *\n\t\t\t\t\t\t\t\t\t\t *   SEND FAILURE PACKET TO WCHAT HERE !!!!!\n\t\t\t\t\t\t\t\t\t\t *\n\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\tWinsock.Close();\n\t\t\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t\t\tDDEServer.Delete_MPlayer_Game_Info();  // Make sure we dont go round in an infinite loop\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tSession.Type = Select_MPlayer_Game();\n\t\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// 'Cancel'\n\t\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n#endif\t//WIN32\n\n\t\t\t\t\t}\n\n\t\t\t\t\tswitch (Session.Type) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tModem, Null-Modem or internet\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase GAME_MODEM:\n\t\t\t\t\t\tcase GAME_NULL_MODEM:\n\t\t\t\t\t\tcase GAME_INTERNET:\n\t\t\t\t\t\tcase GAME_SKIRMISH:\n\t\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\tOptions.ScoreVolume = 0;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tNetwork (IPX): start a new network game.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase GAME_IPX:\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Init network system & remote-connect\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Session.Type == GAME_IPX && Init_Network() && Remote_Connect()) {\n\t\t\t\t\t\t\t\tOptions.ScoreVolume = 0;\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\t\t} else {\t\t\t\t\t\t// user hit cancel, or init failed\n\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tPlay a VQ\n\t\t\t\t*/\n\t\t\t\tcase SEL_INTRO:\n\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\tif (Debug_Flag) {\n\t\t\t\t\t\tPlay_Intro(Debug_Flag);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tHide_Mouse();\n\t\t\t\t\t\tVisiblePage.Clear();\n\t\t\t\t\t\tShow_Mouse();\n\t\t\t\t\t\tPlay_Movie(VQ_INTRO_MOVIE, THEME_NONE, true);\t\t// no transition picture to briefing\n//\t\t\t\t\t\tPlay_Movie(VQ_INTRO_MOVIE, THEME_NONE, false);\t\t// has transitino picture to briefing\n\t\t\t\t\t}\n\t\t\t\t\tTheme.Queue_Song(THEME_CRUS);\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tfade = true;\n\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tExit to DOS.\n\t\t\t\t*/\n\t\t\t\tcase SEL_EXIT:\n\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\tBlackPalette.Set(FADE_PALETTE_SLOW);\n\t\t\t\t\treturn(false);\n\n\t\t\t\t/*\n\t\t\t\t**\tDisplay the hall of fame.\n\t\t\t\t*/\n\t\t\t\tcase SEL_FAME:\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase SEL_TIMEOUT:\n\t\t\t\t\tif (Session.Attract && Session.RecordFile.Is_Available()) {\n\t\t\t\t\t\tSession.Play = true;\n\t\t\t\t\t\tif (Session.RecordFile.Open(READ)) {\n\t\t\t\t\t\t\tLoad_Recording_Values(Session.RecordFile);\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSession.Play = false;\n\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t** For Debug_Map (editor) mode to load scenario\n\t\t*/\n\t\tScen.Set_Scenario_Name(\"SCG01EA.INI\");\n\t}\n\n\t/*\n\t**\tDon't carry stray keystrokes into game.\n\t*/\n\tKeyboard->Clear();\n\n\t/*\n\t** Initialize the random number generator(s)\n\t*/\n        //VG_MONO\n        Mono_Print(\"about to call Init_Random, COOL!!\\n\");\n\tInit_Random();\n\n\t/*\n\t** Save initialization values if we're recording this game.\n\t*/\n\tif (Session.Record) {\n\t\tif (Session.RecordFile.Open(WRITE)) {\n\t\t\tSave_Recording_Values(Session.RecordFile);\n\t\t} else {\n\t\t\tSession.Record = false;\n\t\t}\n\t}\n\n\t/*\n\t**\tLoad the scenario.  Specify variation 'A' for the editor; for the game,\n\t**\tdon't specify a variation, to make 'Set_Scenario_Name()' pick a random one.\n\t**\tSkip this if we've already loaded a save-game.\n\t*/\n\tif (!gameloaded && !Session.LoadGame) {\n//\t\tif (Debug_Map) {\n//\t\t\tSet_Scenario_Name(Scen.ScenarioName, Scen.Scenario, Scen.ScenPlayer, Scen.ScenDir, SCEN_VAR_A);\n//\t\t}  else {\n//\t\t\tSet_Scenario_Name(Scen.ScenarioName, Scen.Scenario, Scen.ScenPlayer, Scen.ScenDir);\n//\t\t}\n\n\t\t/*\n\t\t** Start_Scenario() changes the palette; so, fade out & clear the screen\n\t\t** before calling it.\n\t\t*/\n\t\tHide_Mouse();\n\n\t\tif (selection != SEL_START_NEW_GAME) {\n\t\t\tBlackPalette.Set(FADE_PALETTE_MEDIUM, Call_Back);\n#ifdef WIN32\n                        //VG_MONO\n                        Mono_Print(\"about tocall hiddenpage clear\\n\");\n\t\t\tHiddenPage.Clear();\n\t\t\tVisiblePage.Clear();\n#else\n\t\t\tHidPage.Clear();\n\t\t\tSeenPage.Clear();\n#endif\t//WIN32\n\t\t}\n\t\tShow_Mouse();\n                //VG_MONO\n                Mono_Print(\"about to call start_scenario\\n\");\n\n\t\tif (!Start_Scenario(Scen.ScenarioName)) {\n\t\t\treturn(false);\n\t\t}\n\t\tif (Special.IsFromInstall) Show_Mouse();\n\t\tSpecial.IsFromInstall = false;\n\t}\n\n\t/*\n\t**\tFor multiplayer games, initialize the inter-player message system.\n\t**\tDo this after loading the scenario, so the map's upper-left corner is\n\t**\tproperly set.\n\t*/\n\tSession.Messages.Init(\n\t\tMap.TacPixelX, Map.TacPixelY, \t// x,y for messages\n\t\t6, \t\t\t\t\t\t\t\t\t\t// max # msgs\n\t\tMAX_MESSAGE_LENGTH-14,\t\t\t\t// max msg length\n\t\t7 * RESFACTOR,\t\t\t\t\t\t\t// font height in pixels\n\t\t-1, -1, \t\t\t\t\t\t\t\t\t// x,y for edit line (appears above msgs)\n0,//BG\t\t1,\t\t\t\t\t\t\t\t\t\t\t// enable edit overflow\n\t\t20,          \t\t\t\t\t\t\t// min,\n\t\tMAX_MESSAGE_LENGTH - 14,\t\t\t//    max for trimming overflow\n#ifdef WIN32\n\t\tLepton_To_Pixel(Map.TacLeptonWidth));\t// Width in pixels of buffer\n#else\n\t\t(320-SIDEBAR_WID));\t// Width in pixels of buffer\n#endif\n\n\tif (Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH && !Session.Play) {\n\t\tSession.Create_Connections();\n\t}\n\n\t/*\n\t**\tHide the SeenPage; force the map to render one frame.  The caller can\n\t**\tthen fade the palette in.\n\t**\t(If we loaded a game, this step will fade out the title screen.  If we\n\t**\tstarted a scenario, Start_Scenario() will have played a couple of VQ\n\t**\tmovies, which will have cleared the screen to black already.)\n\t*/\n        //VG_MONO\n        Mono_Print(\"about to call Call_Back \\n\");\n\tCall_Back();\n\tHide_Mouse();\n\tBlackPalette.Set(FADE_PALETTE_MEDIUM, Call_Back);\n//\tFade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);\n#ifdef WIN32\n\tHiddenPage.Clear();\n\tVisiblePage.Clear();\n#else\n\tHidPage.Clear();\n\tSeenPage.Clear();\n#endif\t//WIN32\n\tShow_Mouse();\n\tSet_Logic_Page(SeenBuff);\n#ifdef WIN32\n\t/*\n\t** Sidebar is always active in hi-res.\n\t*/\n        //VG_MONO\n        Mono_Print(\"about to call map sidebar class::activate\\n\");\n\tif (!Debug_Map) {\n\t\tMap.SidebarClass::Activate(1);\n\t}\n#endif\t//WIN32\n\tMap.Flag_To_Redraw();\n\tCall_Back();\n        //VG_MONO\n        Mono_Print(\"about to call Map.Render \\n\");\n\tMap.Render();\n        Mono_Print(\"just returned from Map.Render \\n\");\n\t\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Pla\ny_Intro -- plays the introduction & logo movies                                          *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/06/1995 BRR : Created.                                                                 *\n *   05/08/1996 JLB : Modified for Red Alert and direction control.                            *\n *=============================================================================================*/\nstatic void Play_Intro(bool sequenced)\n{\n\tstatic VQType _counter = VQ_FIRST;\n\n\tKeyboard->Clear();\n\tif (sequenced) {\n\t\tif (_counter <= VQ_FIRST) _counter = VQ_COUNT;\n\t\tif (_counter == VQ_COUNT) _counter--;\n\t\tif (_counter == VQ_REDINTRO) _counter--;\n\t\tif (_counter == VQ_TITLE) _counter--;\n\t\tHide_Mouse();\n\t\tVisiblePage.Clear();\n\t\tShow_Mouse();\n\t\tPlay_Movie(VQType(_counter--), THEME_NONE);\n//\t\tShow_Mouse();\n\t} else {\n\t\tHide_Mouse();\n\t\tVisiblePage.Clear();\n\t\tShow_Mouse();\n#ifdef WIN32\n\t\tPlay_Movie(VQ_REDINTRO, THEME_NONE, false);\n#else\n\t\tPlay_Movie(VQ_TITLE, THEME_NONE, false);\n#endif\n\t}\n}\n\n\n/***********************************************************************************************\n * Anim_Init -- Initialize the VQ animation control structure.                                 *\n *                                                                                             *\n *    VQ animations are controlled by a structure passed to the VQ player. This routine        *\n *    initializes the structure to values required by C&C.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only need to call this routine once at the beginning of the game.               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/20/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef WIN32\n#ifdef MOVIE640\nGraphicBufferClass VQ640(640, 400, (void *)NULL);\n#endif\n#endif\nvoid Anim_Init(void)\n{\n\n#ifdef WIN32\n\n\t/* Configure player with INI file */\n\tVQA_DefaultConfig(&AnimControl);\n\tAnimControl.DrawFlags = VQACFGF_TOPLEFT;\n\tAnimControl.DrawFlags |= VQACFGF_BUFFER;\n//AnimControl.DrawFlags |= VQACFGF_NODRAW;\n//BG - M. Grayford says turn this off\tAnimControl.DrawFlags |= VQACFGF_NOSKIP;\n\n\tAnimControl.DrawFlags |= VQACFGF_NOSKIP;\n\tAnimControl.FrameRate = -1;\n\tAnimControl.DrawRate = -1;\n\tAnimControl.DrawerCallback = VQ_Call_Back;\n\tAnimControl.ImageWidth = 320;\n\tAnimControl.ImageHeight = 200;\n\tAnimControl.ImageBuf = (unsigned char *)SysMemPage.Get_Offset();\n#ifdef MOVIE640\n\tif(IsVQ640) {\n\t\tAnimControl.ImageWidth = 640;\n\t\tAnimControl.ImageHeight = 400;\n\t\tAnimControl.ImageBuf = (unsigned char *)VQ640.Get_Offset();\n\t}\n#endif\n\tAnimControl.Vmode = 0;\n\tAnimControl.OptionFlags |= VQAOPTF_CAPTIONS|VQAOPTF_EVA;\n\tif (SlowPalette) {\n\t\tAnimControl.OptionFlags |= VQAOPTF_SLOWPAL;\n\t}\n\tAnimControl.SoundObject = SoundObject;\n\tAnimControl.PrimaryBufferPtr = PrimaryBufferPtr;\n\tif (MonoClass::Is_Enabled()) {\n\t\tAnimControl.OptionFlags |= VQAOPTF_MONO;\n\t}\n\n#else\t//WIN32\n\t/* Configure player with INI file */\n\tVQA_DefaultConfig(&AnimControl);\n//\tvoid const * font = Load_Font(FONT8);\n//\tAnimControl.EVAFont = (char *)font;\n//\tAnimControl.CapFont = (char *)font;\n\tAnimControl.DrawerCallback = VQ_Call_Back;\n\tAnimControl.ImageWidth = 320;\n\tAnimControl.ImageHeight = 200;\n\tAnimControl.Vmode = MCGA_MODE;\n\tAnimControl.VBIBit = VertBlank;\n\tAnimControl.DrawFlags |= VQACFGF_TOPLEFT;\n\tAnimControl.OptionFlags |= VQAOPTF_HMIINIT|VQAOPTF_CAPTIONS|VQAOPTF_EVA;\n//\tAnimControl.AudioBuf = (unsigned char *)HidPage.Get_Buffer();\n//\tAnimControl.AudioBufSize = 32768U;\n\tAnimControl.DigiCard = NewConfig.DigitCard;\n\tAnimControl.HMIBufSize = 8192;\n\tAnimControl.DigiHandle = Get_Digi_Handle();\n\tAnimControl.Volume = 0x00FF;\n\tAnimControl.AudioRate = 22050;\n//\tif (NewConfig.Speed) AnimControl.AudioRate = 11025;\n\n\tif (!Debug_Quiet && Get_Digi_Handle() != -1) {\n\t\tAnimControl.OptionFlags |= VQAOPTF_AUDIO;\n\t}\n\n\tif (MonoClass::Is_Enabled()) {\n\t\tAnimControl.OptionFlags |= VQAOPTF_MONO;\n\t}\n\n#endif\t//WIN32\n}\n\n\n/***********************************************************************************************\n * Parse_Command_Line -- Parses the command line parameters.                                   *\n *                                                                                             *\n *    This routine should be called before the graphic mode is initialized. It examines the    *\n *    command line parameters and sets the appropriate globals. If there is an error, then     *\n *    it outputs a command summary and then returns false.                                     *\n *                                                                                             *\n * INPUT:   argc  -- The number of command line arguments.                                     *\n *                                                                                             *\n *          argv  -- Pointer to character string array that holds the individual arguments.    *\n *                                                                                             *\n * OUTPUT:  bool; Was the command line parsed successfully?                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool Parse_Command_Line(int argc, char * argv[])\n{\n\t/*\n\t**\tParse the command line and set globals to reflect the parameters\n\t**\tpassed in.\n\t*/\n\tWhom = HOUSE_GOOD;\n\tSpecial.Init();\n\n\tDebug_Map = false;\n\tDebug_Unshroud = false;\n\n\tfor (int index = 1; index < argc; index++) {\n\t\tchar * string;\t\t// Pointer to argument.\n\t\tlong code = 0;\n\n\t\tstring = strupr(argv[index]);\n\n\t\t/*\n\t\t**\tPrint usage text only if requested.\n\t\t*/\n\t\tif (stricmp(\"/?\", string) == 0 || stricmp(\"-?\", string) == 0 || stricmp(\"-h\", string) == 0 || stricmp(\"/h\", string) == 0) {\n\t\t\t/*\n\t\t\t**\tUnrecognized command line parameter... Display usage\n\t\t\t**\tand then exit.\n\t\t\t*/\n\t\t\tputs(TEXT_OPTIONS);\n\t\t\treturn(false);\n\t\t}\n\n\n\t\tbool processed = true;\n\t\tlong ob = Obfuscate(string);\n\n\t\t/*\n\t\t**\tCheck to see if the parameter is a cheat enabling one.\n\t\t*/\n\t\tlong const * optr = &CheatCodes[0];\n\t\twhile (*optr) {\n\t\t\tif (*optr++ == ob) {\n\t\t\t\tDebug_Playtest = true;\n\t\t\t\tDebug_Flag = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tCheck to see if the parameter is a cheat enabling one.\n\t\t*/\n\t\toptr = &PlayCodes[0];\n\t\twhile (*optr) {\n\t\t\tif (*optr++ == ob) {\n\t\t\t\tDebug_Playtest = true;\n\t\t\t\tDebug_Flag = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tCheck to see if the parameter is a scenario editor\n\t\t**\tenabling one.\n\t\t*/\n\t\toptr = &EditorCodes[0];\n\t\twhile (*optr) {\n\t\t\tif (*optr++ == ob) {\n\t\t\t\tDebug_Map = true;\n\t\t\t\tDebug_Unshroud = true;\n\t\t\t\tDebug_Flag = true;\n\t\t\t\tDebug_Playtest = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tswitch (ob) {\n\n#ifdef VIRGIN_CHEAT_KEYS\n\t\t\tcase PARM_PLAYTEST:\n\t\t\t\tDebug_Playtest = true;\n\t\t\t\tbreak;\n#endif\n\n\t\t\t/*\n\t\t\t** Special flag - is C&C being run from the install program?\n\t\t\t*/\n\t\t\tcase PARM_INSTALL:\n\t\t\t\tSpecial.IsFromInstall = true;\n\t\t\t\tBreakoutAllowed = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tprocessed = false;\n\t\t\t\tbreak;\n\t\t}\n\t\tif (processed) continue;\n\n\n#ifdef CHEAT_KEYS\n\t\t/*\n\t\t**\tScenario Editor Mode\n\t\t*/\n\t\tif (stricmp(string, \"-CHECKMAP\") == 0) {\n\t\t\tDebug_Check_Map = true;\n\t\t\tcontinue;\n\t\t}\n\n#endif\n\n\t\t/*\n\t\t**\tFile search path override.\n\t\t*/\n\t\tif (strstr(string, \"-CD\")) {\n\t\t\tCCFileClass::Set_Search_Drives(&string[3]);\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tSpecify destination connection for network play\n\t\t*/\n\t\tif (strstr(string, \"-DESTNET\")) {\n\t\t\tNetNumType net;\n\t\t\tNetNodeType node;\n\n\t\t\t/*\n\t\t\t** Scan the command-line string, pulling off each address piece\n\t\t\t*/\n\t\t\tint i = 0;\n\t\t\tchar * p = strtok(string + 8, \".\");\n\t\t\twhile (p) {\n\t\t\t\tint x;\n\n\t\t\t\tsscanf(p, \"%x\", &x);\t\t\t// convert from hex string to int\n\t\t\t\tif (i < 4) {\n\t\t\t\t\tnet[i] = (char)x;\t\t\t// fill NetNum\n\t\t\t\t} else {\n\t\t\t\t\tnode[i-4] = (char)x;\t\t// fill NetNode\n\t\t\t\t}\n\t\t\t\ti++;\n\t\t\t\tp = strtok(NULL, \".\");\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If all the address components were successfully read, fill in the\n\t\t\t** BridgeNet with a broadcast address to the network across the bridge.\n\t\t\t*/\n\t\t\tif (i >= 4) {\n\t\t\t\tSession.IsBridge = 1;\n\t\t\t\tmemset(node, 0xff, 6);\n\t\t\t\tSession.BridgeNet = IPXAddressClass(net, node);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tSpecify socket ID, as an offset from 0x4000.\n\t\t*/\n\t\tif (strstr(string, \"-SOCKET\")) {\n\t\t\tunsigned short socket;\n\n\t\t\tsocket = (unsigned short)(atoi(string + strlen(\"SOCKET\")));\n\t\t\tsocket += 0x4000;\n\t\t\tif (socket >= 0x4000 && socket < 0x8000) {\n\t\t\t\tIpx.Set_Socket (socket);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tSet the Net Stealth option\n\t\t*/\n\t\tif (strstr(string, \"-STEALTH\")) {\n\t\t\tSession.NetStealth = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tSet the Net Protection option\n\t\t*/\n\t\tif (strstr(string, \"-MESSAGES\")) {\n\t\t\tSession.NetProtect = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tAllow \"attract\" mode\n\t\t*/\n\t\tif (strstr(string, \"-ATTRACT\")) {\n\t\t\tSession.Attract = true;\n\t\t\tcontinue;\n\t\t}\n\n\n#ifdef WIN32\n\t\t/*\n\t\t** Set screen to 640x480 instead of 640x400\n\t\t*/\n\t\tif (strstr(string, \"-480\")) {\n\t\t\tScreenHeight = 480;\n\t\t\tcontinue;\n\t\t}\n#endif\n\n#ifdef CHEAT_KEYS\n\t\t/*\n\t\t**\tSpecify the random number seed (for debugging)\n\t\t*/\n\t\tif (strstr(string, \"-SEED\")) {\n\t\t\tCustomSeed = (unsigned short)(atoi(string + strlen(\"SEED\")));\n\t\t\tcontinue;\n\t\t}\n\n#ifndef WIN32\n\t\t/*\n\t\t**\tDon't install Page Fault Handler (MUST use this for debugger)\n\t\t*/\n\t\tif (stricmp(string, \"-NOPFS\") == 0) {\n\t\t\tUsePageFaultHandler = 0;\n\t\t\tcontinue;\n\t\t}\n#endif\n\n#endif\n\n#ifdef NEVER\n\t\t/*\n\t\t**\tHandle the prog init differently in this case.\n\t\t*/\n\t\tif (strstr(string, \"-V\")) {\n\t\t\tcontinue;\n\t\t}\n#endif\n\n\t\t/*\n\t\t** look for passed-in video mode to default to\n\t\t*/\n#ifndef\tWIN32\n\t\tif (strnicmp(string, \"-V\", strlen(\"-V\")) == 0) {\n\t\t\tSet_Video_Mode(MCGA_MODE);\t// do this to get around first_time variable...\n\t\t\tSet_Original_Video_Mode(atoi(string+2));\n\t\t\tcontinue;\n\t\t}\n#endif\n\t\t/*\n\t\t**\tSpecial command line control parsing.\n\t\t*/\n\t\tif (strnicmp(string, \"-X\", strlen(\"-O\")) == 0) {\n\t\t\tstring += strlen(\"-X\");\n\t\t\twhile (*string) {\n\t\t\t\tchar code = *string++;\n\t\t\t\tswitch (toupper(code)) {\n\n#ifdef  CHEAT_KEYS\n\t\t\t\t\t/*\n\t\t\t\t\t**\tMonochrome debug screen enable.\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'M':\n\t\t\t\t\t\tMonoClass::Enable();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tInert weapons -- no units take damage.\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'I':\n\t\t\t\t\t\tSpecial.IsInert = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tHussled recharge timer.\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'H':\n\t\t\t\t\t\tSpecial.IsSpeedBuild = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\t\"Record\" a multi-player game\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'X':\n\t\t\t\t\t\tSession.Record = 1;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\t\"Play Back\" a multi-player game\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'Y':\n\t\t\t\t\t\tSession.Play = 1;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tPrint lots of debug stuff about events & packets\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'P':\n\t\t\t\t\t\tDebug_Print_Events = true;\n\t\t\t\t\t\tbreak;\n#endif\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tQuiet mode override control.\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'Q':\n\t\t\t\t\t\tDebug_Quiet = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tputs(TEXT_INVALID);\n\t\t\t\t\t\treturn(false);\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tcontinue;\n\t\t}\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Obfuscate -- Sufficiently transform parameter to thwart casual hackers.                     *\n *                                                                                             *\n *    This routine borrows from CRC and PGP technology to sufficiently alter the parameter     *\n *    in order to make it difficult to reverse engineer the key phrase. This is designed to    *\n *    be used for hidden game options that will be released at a later time over Westwood's    *\n *    Web page or through magazine hint articles.                                              *\n *                                                                                             *\n *    This algorithm is cryptographically categorized as a \"one way hash\".                     *\n *                                                                                             *\n *    Since this is a one way transformation, it becomes much more difficult to reverse        *\n *    engineer the pass phrase even if the resultant pass code is known. This has an added     *\n *    benefit of making this algorithm immune to traditional cryptographic attacks.            *\n *                                                                                             *\n *    The largest strength of this transformation algorithm lies in the restriction on the     *\n *    source vector being legal ASCII uppercase characters. This restriction alone makes even  *\n *    a simple CRC transformation practically impossible to reverse engineer. This algorithm   *\n *    uses far more than a simple CRC transformation to achieve added strength from advanced   *\n *    attack methods.                                                                          *\n *                                                                                             *\n * INPUT:   string   -- Pointer to the key phrase that will be transformed into a code.        *\n *                                                                                             *\n * OUTPUT:  Returns with the code that the key phrase is translated into.                      *\n *                                                                                             *\n * WARNINGS:   A zero length pass phrase results in a 0x00000000 result code.                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Obfuscate(char const * string)\n{\n\tchar buffer[128];\n\n\tif (!string) return(0);\n\tmemset(buffer, '\\xA5', sizeof(buffer));\n\n\t/*\n\t**\tCopy key phrase into a working buffer. This hides any transformation done\n\t**\tto the string.\n\t*/\n\tstrncpy(buffer, string, sizeof(buffer));\n\tbuffer[sizeof(buffer)-1] = '\\0';\n\tint length = strlen(buffer);\n\n\t/*\n\t**\tOnly upper case letters are significant.\n\t*/\n\tstrupr(buffer);\n\n\t/*\n\t**\tEnsure that only visible ASCII characters compose the key phrase. This\n\t**\tdiscourages the direct forced illegal character input method of attack.\n\t*/\n\tfor (int index = 0; index < length; index++) {\n\t\tif (!isgraph(buffer[index])) {\n\t\t\tbuffer[index] = 'A' + (index%26);\n\t\t}\n\t}\n\n\t/*\n\t**\tIncrease the strength of even short pass phrases by extending the\n\t**\tlength to be at least a minimum number of characters. This helps prevent\n\t**\ta weak pass phrase from compromising the obfuscation process. This\n\t**\tprocess also forces the key phrase to be an even multiple of four.\n\t**\tThis is necessary to support the cypher process that occurs later.\n\t*/\n\tif (length < 16 || (length & 0x03)) {\n\t\tint maxlen = 16;\n\t\tif (((length+3) & 0x00FC) > maxlen) {\n\t\t\tmaxlen = ((length+3) & 0x00FC);\n\t\t}\n\t\tfor (index = length; index < maxlen; index++) {\n\t\t\tbuffer[index] = 'A' + ((('?' ^ buffer[index-length]) + index) % 26);\n\t\t}\n\t\tlength = index;\n\t\tbuffer[length] = '\\0';\n\t}\n\n\t/*\n\t**\tTransform the buffer into a number. This transformation is character\n\t**\torder dependant.\n\t*/\n\tlong code = Calculate_CRC(buffer, length);\n\n\t/*\n\t**\tRecord a copy of this initial transformation to be used in a later\n\t**\tself referential transformation.\n\t*/\n\tlong copy = code;\n\n\t/*\n\t**\tReverse the character string and combine with the previous transformation.\n\t**\tThis doubles the workload of trying to reverse engineer the CRC calculation.\n\t*/\n\tstrrev(buffer);\n\tcode ^= Calculate_CRC(buffer, length);\n\n\t/*\n\t**\tPerform a self referential transformation. This makes a reverse engineering\n\t**\tby using a cause and effect attack more difficult.\n\t*/\n\tcode = code ^ copy;\n\n\t/*\n\t**\tUnroll and combine the code value into the pass phrase and then perform\n\t**\tanother self referential transformation. Although this is a trivial cypher\n\t**\tprocess, it gives the sophisticated hacker false hope since the strong\n\t**\tcypher process occurs later.\n\t*/\n\tstrrev(buffer);\t\t// Restore original string order.\n\tfor (index = 0; index < length; index++) {\n\t\tcode ^= (unsigned char)buffer[index];\n\t\tunsigned char temp = (unsigned char)code;\n\t\tbuffer[index] ^= temp;\n\t\tcode >>= 8;\n\t\tcode |= (((long)temp)<<24);\n\t}\n\n\t/*\n\t**\tIntroduce loss into the vector. This strengthens the key against traditional\n\t**\tcryptographic attack engines. Since this also weakens the key against\n\t**\tunconventional attacks, the loss is limited to less than 10%.\n\t*/\n\tfor (index = 0; index < length; index++) {\n\t\tstatic unsigned char _lossbits[] = {0x00,0x08,0x00,0x20,0x00,0x04,0x10,0x00};\n\t\tstatic unsigned char _addbits[] = {0x10,0x00,0x00,0x80,0x40,0x00,0x00,0x04};\n\n\t\tbuffer[index] |= _addbits[index % (sizeof(_addbits)/sizeof(_addbits[0]))];\n\t\tbuffer[index] &= ~_lossbits[index % (sizeof(_lossbits)/sizeof(_lossbits[0]))];\n\t}\n\n\t/*\n\t**\tPerform a general cypher transformation on the vector\n\t**\tand use the vector itself as the cypher key. This is a variation on the\n\t**\tcypher process used in PGP. It is a very strong cypher process with no known\n\t**\tweaknesses. However, in this case, the cypher key is the vector itself and this\n\t**\topens up a weakness against attacks that have access to this transformation\n\t**\talgorithm. The sheer workload of reversing this transformation should be enough\n\t**\tto discourage even the most determined hackers.\n\t*/\n\tfor (index = 0; index < length; index += 4) {\n\t\tshort key1 = buffer[index];\n\t\tshort key2 = buffer[index+1];\n\t\tshort key3 = buffer[index+2];\n\t\tshort key4 = buffer[index+3];\n\t\tshort val1 = key1;\n\t\tshort val2 = key2;\n\t\tshort val3 = key3;\n\t\tshort val4 = key4;\n\n\t\tval1 *= key1;\n\t\tval2 += key2;\n\t\tval3 += key3;\n\t\tval4 *= key4;\n\n\t\tshort s3 = val3;\n\t\tval3 ^= val1;\n\t\tval3 *= key1;\n\t\tshort s2 = val2;\n\t\tval2 ^= val4;\n\t\tval2 += val3;\n\t\tval2 *= key3;\n\t\tval3 += val2;\n\n\t\tval1 ^= val2;\n\t\tval4 ^= val3;\n\n\t\tval2 ^= s3;\n\t\tval3 ^= s2;\n\n\t\tbuffer[index] = val1;\n\t\tbuffer[index+1] = val2;\n\t\tbuffer[index+2] = val3;\n\t\tbuffer[index+3] = val4;\n\t}\n\n\t/*\n\t**\tConvert this final vector into a cypher key code to be\n\t**\treturned by this routine.\n\t*/\n\tcode = Calculate_CRC(buffer, length);\n\n\t/*\n\t**\tReturn the final code value.\n\t*/\n\treturn(code);\n}\n\n\n/***********************************************************************************************\n * Calculate_CRC -- Calculates a one-way hash from a data block.                               *\n *                                                                                             *\n *    This routine is used to create a hash value from a data block. The algorithm is similar  *\n *    to a CRC, but is faster.                                                                 *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to a buffer of data to be 'hashed'.                            *\n *                                                                                             *\n *          len      -- The length of the buffer to compute the hash upon.                     *\n *                                                                                             *\n * OUTPUT:  Returns with a 32bit hash value calculated from the specified buffer.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nextern \"C\"  {\nlong Calculate_CRC(void * buffer, long len)\n{\n\treturn(CRCEngine()(buffer, len));\n}\n}\n\n\n/***************************************************************************\n * Init_Random -- Initializes the random-number generator                  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid Init_Random(void)\n{\n\t#ifdef WIN32\n\n\t\t/*\n\t\t**\tGather some \"random\" bits from the system timer. Actually, only the\n\t\t**\tlow order millisecond bits are secure. The other bits could be\n\t\t**\teasily guessed from the system clock (most clocks are fairly accurate\n\t\t**\tand thus predictable).\n\t\t*/\n\t\tSYSTEMTIME t;\n\t\tGetSystemTime(&t);\n\t\tCryptRandom.Seed_Byte(t.wMilliseconds);\n\t\tCryptRandom.Seed_Bit(t.wSecond);\n\t\tCryptRandom.Seed_Bit(t.wSecond>>1);\n\t\tCryptRandom.Seed_Bit(t.wSecond>>2);\n\t\tCryptRandom.Seed_Bit(t.wSecond>>3);\n\t\tCryptRandom.Seed_Bit(t.wSecond>>4);\n\t\tCryptRandom.Seed_Bit(t.wMinute);\n\t\tCryptRandom.Seed_Bit(t.wMinute>>1);\n\t\tCryptRandom.Seed_Bit(t.wMinute>>2);\n\t\tCryptRandom.Seed_Bit(t.wMinute>>3);\n\t\tCryptRandom.Seed_Bit(t.wMinute>>4);\n\t\tCryptRandom.Seed_Bit(t.wHour);\n\t\tCryptRandom.Seed_Bit(t.wDay);\n\t\tCryptRandom.Seed_Bit(t.wDayOfWeek);\n\t\tCryptRandom.Seed_Bit(t.wMonth);\n\t\tCryptRandom.Seed_Bit(t.wYear);\n\t#else\n\n\t\t/*\n\t\t**\tGather some \"random\" bits from the DOS mode timer.\n\t\t*/\n\t\tstruct timeb t;\n\t\tftime(&t);\n\t\tCryptRandom.Seed_Byte(t.millitm);\n\t\tCryptRandom.Seed_Byte(t.time);\n\t#endif\n\n\t/*\n\t** Do nothing if we've loaded a multiplayer game, or we're playing back\n\t** a recording; the random number generator is initialized by loading\n\t** the game.\n\t*/\n\tif (Session.LoadGame || Session.Play) {\n\t\tRandNumb = Seed;\n\t\tScen.RandomNumber = Seed;\n\t\treturn;\n\t}\n\n\t/*\n\t**\tInitialize the random number Seed.  For multiplayer, this will have been done\n\t** in the connection dialogs.  For single-player games, AND if we're not playing\n\t** back a recording, init the Seed to a random value.\n\t*/\n\tif (Session.Type == GAME_NORMAL || Session.Type == GAME_SKIRMISH &&\n\t\t!Session.Play) {\n\n\t\t/*\n\t\t** Set the optional user-specified seed\n\t\t*/\n\t\tif (CustomSeed != 0) {\n\t\t\tSeed = CustomSeed;\n\t\t} else {\n\t\t\tsrand(time(NULL));\n\t\t\tSeed = rand();\n\t\t}\n\t}\n\n\t/*\n\t**\tInitialize the random-number generators\n\t*/\n\tScen.RandomNumber = Seed;\n\tRandNumb = Seed;\n}\n\n\n/***********************************************************************************************\n * Load_Title_Page -- Load the background art for the title page.                              *\n *                                                                                             *\n *    This routine will load the background art in a machine independent format. There is      *\n *    different art required for the hi-res and lo-res versions of the game.                   *\n *                                                                                             *\n * INPUT:   visible  -- Should the title page art be copied to the visible page by this        *\n *                      routine?                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure the mouse is hidden if the image is to be copied to the visible page.   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Load_Title_Page(bool visible)\n{\n#ifdef WIN32\n\tLoad_Title_Screen(\"TITLE.PCX\", &HidPage, CCPalette);\n\tif (visible) {\n\t\tHidPage.Blit(SeenPage);\n\t}\n#else\n\tLoad_Picture(\"TITLE.CPS\", HidPage, HidPage, CCPalette, BM_DEFAULT);\n\tif (visible) {\n\t\tHidPage.Blit(SeenPage);\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * Init_Color_Remaps -- Initialize the text remap tables.                                      *\n *                                                                                             *\n *    There are various color scheme remap tables that are dependant upon the color remap      *\n *    information embedded within the palette control file. This routine will fetch that       *\n *    data and build the text remap tables as indicated.                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Color_Remaps(void)\n{\n\t/*\n\t**\tSetup the remap tables.  PALETTE.CPS contains a special set of pixels in\n\t** the upper-left corner.  Each row of 16 pixels is one range of colors.  The\n\t** first row represents unity (the default color units are drawn in); rows\n\t** after that are the remap colors.\n\t*/\n\n#ifdef WIN32\n\n\tSysMemPage.Clear();\n\tLoad_Picture(\"PALETTE.CPS\", SysMemPage, SysMemPage, NULL, BM_DEFAULT);\n\tSysMemPage.Blit(HidPage);\n#else\n\tLoad_Picture(\"PALETTE.CPS\", HidPage, HidPage, NULL, BM_DEFAULT);\n#endif\n\tfor (PlayerColorType pcolor = PCOLOR_FIRST; pcolor < PCOLOR_COUNT; pcolor++) {\n\n\t\tunsigned char * ptr = ColorRemaps[pcolor].RemapTable;\n\n\t\tfor (int color = 0; color < 256; color++) {\n\t\t\tptr[color] = color;\n\t\t}\n\n\t\tfor (int index = 0; index < 16; index++) {\n\t\t\tptr[HidPage.Get_Pixel(index, 0)] = HidPage.Get_Pixel(index, pcolor);\n\t\t}\n\t\tfor (index = 0; index < 6; index++) {\n\t\t\tColorRemaps[pcolor].FontRemap[10+index] = HidPage.Get_Pixel(2+index, pcolor);\n\t\t}\n\t\tColorRemaps[pcolor].BrightColor = HidPage.Get_Pixel(2, pcolor);\n\t\tColorRemaps[pcolor].Color = HidPage.Get_Pixel(4, pcolor);\n\n\t\tColorRemaps[pcolor].Shadow = HidPage.Get_Pixel(10, pcolor);\n\t\tColorRemaps[pcolor].Background = HidPage.Get_Pixel(9, pcolor);\n\t\tColorRemaps[pcolor].Corners = HidPage.Get_Pixel(8, pcolor);\n\t\tColorRemaps[pcolor].Highlight = HidPage.Get_Pixel(4, pcolor);\n\t\tColorRemaps[pcolor].Bright = HidPage.Get_Pixel(0, pcolor);\n\t\tColorRemaps[pcolor].Underline = HidPage.Get_Pixel(0, pcolor);\n\t\tColorRemaps[pcolor].Bar = HidPage.Get_Pixel(6, pcolor);\n\t\tColorRemaps[pcolor].Box = HidPage.Get_Pixel(4, pcolor);\n\t}\n\n\t/*\n\t** Now do the special dim grey scheme\n\t*/\n\tfor (int color = 0; color < 256; color++) {\n\t\tGreyScheme.RemapTable[color] = color;\n\t}\n\tfor (int index = 0; index < 6; index++) {\n\t\tGreyScheme.FontRemap[10+index] = HidPage.Get_Pixel(9+index, PCOLOR_GREY) & 0x00FF;\n\t}\n\tGreyScheme.BrightColor = HidPage.Get_Pixel(3, PCOLOR_GREY) & 0x00FF;\n\tGreyScheme.Color = HidPage.Get_Pixel(7, PCOLOR_GREY) & 0x00FF;\n\n\tGreyScheme.Shadow = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(15, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Background = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(14, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Corners = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(13, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Highlight = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(9, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Bright = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(5, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Underline = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(5, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Bar = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(11, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Box = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(11, PCOLOR_GREY) & 0x00FF];\n\n\t/*\n\t** Set up the metallic remap table for the font that prints over the tabs\n\t*/\n\tmemset ((void*)&MetalScheme, 4, sizeof(MetalScheme));\n\tfor (int color_counter = 0; color_counter < 16; color_counter++) {\n\t\tMetalScheme.FontRemap[color_counter] = color_counter;\n\t}\n\tMetalScheme.FontRemap[1] = 128;\n\tMetalScheme.FontRemap[2] = 12;\n\tMetalScheme.FontRemap[3] = 13;\n\tMetalScheme.FontRemap[4] = 14;\n\tMetalScheme.Color = 128;\n\tMetalScheme.Background = 0;\n\tMetalScheme.Underline = 128;\n\n\t/*\n\t** Set up the font remap table for the mission briefing font\n\t*/\n\tfor (int colr = 0; colr < 16; colr++) {\n\t\tColorRemaps[PCOLOR_TYPE].FontRemap[colr] = HidPage.Get_Pixel(colr, PCOLOR_TYPE);\n\t}\n\n\tColorRemaps[PCOLOR_TYPE].Shadow = 11;\n\tColorRemaps[PCOLOR_TYPE].Background = 10;\n\tColorRemaps[PCOLOR_TYPE].Corners = 10;\n\tColorRemaps[PCOLOR_TYPE].Highlight = 9;\n\tColorRemaps[PCOLOR_TYPE].Bright = 15;\n\tColorRemaps[PCOLOR_TYPE].Underline = 11;\n\tColorRemaps[PCOLOR_TYPE].Bar = 11;\n\tColorRemaps[PCOLOR_TYPE].Box = 10;\n\tColorRemaps[PCOLOR_TYPE].BrightColor = 15;\n\tColorRemaps[PCOLOR_TYPE].Color = 9;\n\n\tGadgetClass::Set_Color_Scheme(&ColorRemaps[PCOLOR_BLUE]);\n}\n\n\n/***********************************************************************************************\n * Init_Heaps -- Initialize the game heaps and buffers.                                        *\n *                                                                                             *\n *    This routine will allocate the game heaps and buffers. The rules file has already been   *\n *    processed by the time that this routine is called.                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Heaps(void)\n{\n\t/*\n\t**\tInitialize the game object heaps.\n\t*/\n\tVessels.Set_Heap(Rule.VesselMax);\n\tUnits.Set_Heap(Rule.UnitMax);\n\tFactories.Set_Heap(Rule.FactoryMax);\n\tTerrains.Set_Heap(Rule.TerrainMax);\n\tTemplates.Set_Heap(Rule.TemplateMax);\n\tSmudges.Set_Heap(Rule.SmudgeMax);\n\tOverlays.Set_Heap(Rule.OverlayMax);\n\tInfantry.Set_Heap(Rule.InfantryMax);\n\tBullets.Set_Heap(Rule.BulletMax);\n\tBuildings.Set_Heap(Rule.BuildingMax);\n\tAnims.Set_Heap(Rule.AnimMax);\n\tAircraft.Set_Heap(Rule.AircraftMax);\n\tTriggers.Set_Heap(Rule.TriggerMax);\n\tTeamTypes.Set_Heap(Rule.TeamTypeMax);\n\tTeams.Set_Heap(Rule.TeamMax);\n\tHouses.Set_Heap(HOUSE_MAX);\n\tTriggerTypes.Set_Heap(Rule.TrigTypeMax);\n//\tWeapons.Set_Heap(Rule.WeaponMax);\n\n\t/*\n\t**\tSpeech holding tank buffer. Since speech does not mix, it can be placed\n\t**\tinto a custom holding tank only as large as the largest speech file to\n\t**\tbe played.\n\t*/\n\tfor (int index = 0; index < ARRAY_SIZE(SpeechBuffer); index++) {\n\t\tSpeechBuffer[index] = new char [SPEECH_BUFFER_SIZE];\n\t\tSpeechRecord[index] = VOX_NONE;\n\t\tassert(SpeechBuffer[index] != NULL);\n\t}\n\n\t/*\n\t**\tAllocate the theater buffer block.\n\t*/\n\tTheaterBuffer = new Buffer(THEATER_BUFFER_SIZE);\n\tassert(TheaterBuffer != NULL);\n}\n\n\n/***********************************************************************************************\n * Init_Expansion_Files -- Fetch any override expansion mixfiles.                              *\n *                                                                                             *\n *    This routine will search for and register/cache any override mixfiles found.             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Expansion_Files(void)\n{\n\t/*\n\t**\tBefore all else, cache any additional mixfiles.\n\t*/\n\tstruct find_t ff;\t\t// for _dos_findfirst\n\tif (!_dos_findfirst(\"SC*.MIX\", _A_NORMAL, &ff)) {\n\t\tchar * ptr;\n\t\tdo {\n\t\t\tptr = strdup(ff.name);\n\t\t\tnew MFCD(ptr, &FastKey);\n\t\t\tMFCD::Cache(ptr);\n\t\t} while (!_dos_findnext(&ff));\n\t}\n\tif (!_dos_findfirst(\"SS*.MIX\", _A_NORMAL, &ff)) {\n\t\tchar * ptr;\n\t\tdo {\n\t\t\tptr = strdup(ff.name);\n\t\t\tnew MFCD(ptr, &FastKey);\n\t\t} while (!_dos_findnext(&ff));\n\t}\n}\n\n\n/***********************************************************************************************\n * Init_One_Time_Systems -- Initialize internal pointers to the bulk data.                     *\n *                                                                                             *\n *    This performs the one-time processing required after the bulk data has been cached but   *\n *    before the game actually starts. Typically, this routine extracts pointers to all the    *\n *    embedded data sub-files within the main game data mixfile. This routine must be called   *\n *    AFTER the bulk data has been cached.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine AFTER the bulk data has been cached.                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_One_Time_Systems(void)\n{\n\tCall_Back();\n\tMap.One_Time();\n\tLogic.One_Time();\n\tOptions.One_Time();\n\tSession.One_Time();\n\n\tObjectTypeClass::One_Time();\n\tBuildingTypeClass::One_Time();\n\tBulletTypeClass::One_Time();\n\tHouseTypeClass::One_Time();\n\tTemplateTypeClass::One_Time();\n\tOverlayTypeClass::One_Time();\n\tSmudgeTypeClass::One_Time();\n\tTerrainTypeClass::One_Time();\n\tUnitTypeClass::One_Time();\n\tVesselTypeClass::One_Time();\n\tInfantryTypeClass::One_Time();\n\tAnimTypeClass::One_Time();\n\tAircraftTypeClass::One_Time();\n\tHouseClass::One_Time();\n}\n\n\n/***********************************************************************************************\n * Init_Fonts -- Initialize all the game font pointers.                                        *\n *                                                                                             *\n *    This routine is used to fetch pointers to the game fonts. The mixfile containing these   *\n *    fonts must have been previously cached. This routine is a necessary prerequisite to      *\n *    displaying any dialogs or printing any text.                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Fonts(void)\n{\n\tMetal12FontPtr = MFCD::Retrieve(\"12METFNT.FNT\");\n\tMapFontPtr = MFCD::Retrieve(\"HELP.FNT\");\n\tFont6Ptr = MFCD::Retrieve(\"6POINT.FNT\");\n\tGradFont6Ptr = MFCD::Retrieve(\"GRAD6FNT.FNT\");\n\tEditorFont = MFCD::Retrieve(\"EDITFNT.FNT\");\n\tFont8Ptr = MFCD::Retrieve(\"8POINT.FNT\");\n\tFontPtr = (char *)Font8Ptr;\n\tSet_Font(FontPtr);\n\tFont3Ptr = MFCD::Retrieve(\"3POINT.FNT\");\n\tScoreFontPtr = MFCD::Retrieve(\"SCOREFNT.FNT\");\n\tFontLEDPtr = MFCD::Retrieve(\"LED.FNT\");\n\tVCRFontPtr = MFCD::Retrieve(\"VCR.FNT\");\n\tTypeFontPtr = MFCD::Retrieve(\"8POINT.FNT\");    //(\"TYPE.FNT\"); //VG 10/17/96\n}\n\n\n/***********************************************************************************************\n * Init_CDROM_Access -- Initialize the CD-ROM access handler.                                  *\n *                                                                                             *\n *    This routine is called to setup the CD-ROM access or emulation handler. It will ensure   *\n *    that the appropriate CD-ROM is present (dependant on the RequiredCD global).             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The fonts, palettes, and other bootstrap systems must have been initialized     *\n *             prior to calling this routine since this routine will quite likely display      *\n *             a dialog box requesting the appropriate CD be inserted.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_CDROM_Access(void)\n{\n\t/*\n\t**\tAlways try to look at the CD-ROM for data files.\n\t*/\n\tif (!CCFileClass::Is_There_Search_Drives()) {\n\n\t\t/*\n\t\t**\tThis call is needed because of a side effect of this function. It will examine the\n\t\t**\tCD-ROMs attached to this computer and set the appropriate status values. Without this\n\t\t**\tcall, the \"?:\\\\\" could not be filled in correctly.\n\t\t*/\n\t\tForce_CD_Available(-1);\n\n\t\t/*\n\t\t** If there are no search drives specified then we must be playing\n\t\t** off cd, so read files from there.\n\t\t*/\n\t\tint error;\n\n\t\tdo {\n\t\t\terror = CCFileClass::Set_Search_Drives(\"?:\\\\\");\n\t\t\tswitch (error) {\n\t\t\t\tcase 1:\n\t\t\t\t\tVisiblePage.Clear();\n\t\t\t\t\tGamePalette.Set();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t\tWWMessageBox().Process(TXT_CD_ERROR1, TXT_OK);\n\t\t\t\t\tProg_End();\n\t\t\t\t\texit(EXIT_FAILURE);\n\n\t\t\t\tcase 2:\n\t\t\t\t\tVisiblePage.Clear();\n\t\t\t\t\tGamePalette.Set();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t\tif (WWMessageBox().Process(TXT_CD_DIALOG_1, TXT_OK, TXT_CANCEL) == 1) {\n\t\t\t\t\t\tProg_End();\n\t\t\t\t\t\texit(EXIT_FAILURE);\n\t\t\t\t\t}\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tVisiblePage.Clear();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t\tif (!Force_CD_Available(RequiredCD)) {\n\t\t\t\t\t\tProg_End();\n\t\t\t\t\t\texit(EXIT_FAILURE);\n\t\t\t\t\t}\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} while (error);\n\n\t\tRequiredCD = -1;\n\t} else {\n\n\t\t/*\n\t\t** If there are search drives specified then all files are to be\n\t\t** considered local.\n\t\t*/\n\t\tRequiredCD = -2;\n\t}\n}\n\n\n/***********************************************************************************************\n * Init_Bootstrap_Mixfiles -- Registers and caches any mixfiles needed for bootstrapping.      *\n *                                                                                             *\n *    This routine will register the initial mixfiles that are required to display error       *\n *    messages and get input from the player.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure to call this routine before any dialogs would be displayed to the       *\n *             player.                                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Bootstrap_Mixfiles(void)\n{\n\tint temp = RequiredCD;\n\tRequiredCD = -2;\n\n\tnew MFCD(\"REDALERT.MIX\", &FastKey);\n\n\t/*\n\t**\tBootstrap enough of the system so that the error dialog box can successfully\n\t**\tbe displayed.\n\t*/\n\tnew MFCD(\"LOCAL.MIX\", &FastKey);\t\t\t// Cached.\n\tbool ok = MFCD::Cache(\"LOCAL.MIX\");\n\tassert(ok);\n\n#ifdef WIN32\n\tnew MFCD(\"HIRES.MIX\", &FastKey);\n\tok = MFCD::Cache(\"HIRES.MIX\");\n\tassert(ok);\n\n\tnew MFCD(\"NCHIRES.MIX\", &FastKey);\t\t//Non-cached hires stuff incl VQ palettes\n#else\n\tnew MFCD(\"LORES.MIX\", &FastKey);\n\tok = MFCD::Cache(\"LORES.MIX\");\n\tassert(ok);\n#endif\t//WIN32\n\n\tRequiredCD = temp;\n}\n\n\n/***********************************************************************************************\n * Init_Secondary_Mixfiles -- Register and cache secondary mixfiles.                           *\n *                                                                                             *\n *    This routine is used to register the mixfiles that are needed for main menu processing.  *\n *    Call this routine before the main menu is display and processed.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Secondary_Mixfiles(void)\n{\n\tMainMix = new MFCD(\"MAIN.MIX\", &FastKey);\n\tassert(MainMix != NULL);\n\n\t/*\n\t**\tInform the file system of the various MIX files.\n\t*/\n\tConquerMix = new MFCD(\"CONQUER.MIX\", &FastKey);\t\t\t// Cached.\n//\tnew MFCD(\"TRANSIT.MIX\", &FastKey);\n\n\tif (GeneralMix == NULL) GeneralMix = new MFCD(\"GENERAL.MIX\", &FastKey);\t\t\t// Never cached.\n\n\tif (CCFileClass(\"MOVIES1.MIX\").Is_Available()) {\n\t\tMoviesMix = new MFCD(\"MOVIES1.MIX\", &FastKey);\t\t\t// Never cached.\n\t} else {\n\t\tMoviesMix = new MFCD(\"MOVIES2.MIX\", &FastKey);\t\t\t// Never cached.\n\t}\n\tassert(MoviesMix != NULL);\n\n\t/*\n\t**\tRegister the score mixfile.\n\t*/\n\tScoresPresent = true;\n\tScoreMix = new MFCD(\"SCORES.MIX\", &FastKey);\n\tThemeClass::Scan();\n\n\t/*\n\t**\tThese are sound card specific, but the install program would have\n\t**\tcopied the correct versions to the hard drive.\n\t*/\n\tnew MFCD(\"SPEECH.MIX\", &FastKey);\t\t\t// Never cached.\n\tnew MFCD(\"SOUNDS.MIX\", &FastKey);\t\t\t// Cached.\n\tnew MFCD(\"RUSSIAN.MIX\", &FastKey);\t\t\t// Cached.\n\tnew MFCD(\"ALLIES.MIX\", &FastKey);\t\t\t// Cached.\n}\n\n\n/***********************************************************************************************\n * Bootstrap -- Perform the initial bootstrap procedure.                                       *\n *                                                                                             *\n *    This routine will load and initialize the game engine such that a dialog box could be    *\n *    displayed. Because this is very critical, call this routine before any other game        *\n *    initialization code.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Bootstrap(void)\n{\n\tBlackPalette.Set();\n\n\t/*\n\t**\tBe sure to short circuit the CD-ROM check if there is a CD-ROM override\n\t**\tpath.\n\t*/\n\tif (CCFileClass::Is_There_Search_Drives()) {\n\t\tRequiredCD = -2;\n\t}\n\n\t/*\n\t** Process the message loop until we are in focus. We need to be in focus to read pixels from\n\t** the screen.\n\t*/\n\t#ifdef WIN32\n\tdo {\n\t\tKeyboard->Check();\n\t} while (!GameInFocus);\n\tAllSurfaces.SurfacesRestored = false;\n\t#endif\n\n\t/*\n\t**\tPerform any special debug-only processing. This includes preparing the\n\t**\tmonochrome screen.\n\t*/\n\tMono_Clear_Screen();\n\n\t/*\n\t**\tRegister and make resident all local mixfiles with particular emphasis\n\t**\ton the mixfiles that are necessary to display and error messages and\n\t**\tprocess further initialization.\n\t*/\n\tInit_Bootstrap_Mixfiles();\n\n\t/*\n\t**\tInitialize the resident font pointers.\n\t*/\n\tInit_Fonts();\n\n#ifndef WIN32\n\t/*\n\t**\tInstall the hard error handler.\n\t*/\n\t_harderr(harderr_handler);\t\t// BG: Install hard error handler\n\n\t/*\n\t** Install a Page Fault handler\n\t*/\n\tif (UsePageFaultHandler) {\n\t\tInstall_Page_Fault_Handle();\n\t}\n#endif\n\n\t/*\n\t**\tSetup the keyboard processor in preparation for the game.\n\t*/\n\t#ifdef WIN32\n\t\tKeyboard->Clear();\n\t#else\n\t\tKeyboard_Attributes_Off(BREAKON | SCROLLLOCKON | TRACKEXT | PAUSEON | CTRLSON | CTRLCON | FILTERONLY | TASKSWITCHABLE);\n\t\tKeyboard_Attributes_On(PASSBREAKS);\n\t\tKeyboard->Clear();\n\t#endif\n\n\t/*\n\t**\tThis is the shape staging buffer. It must always be available, so it is\n\t**\tallocated here and never freed. The library sets the globals ShapeBuffer\n\t**\tand ShapeBufferSize to these values, so it can be accessed for other\n\t**\tpurposes.\n\t*/\n\tSet_Shape_Buffer(new unsigned char[SHAPE_BUFFER_SIZE], SHAPE_BUFFER_SIZE);\n\n\t/*\n\t**\tFetch the language text from the hard drive first. If it cannot be\n\t**\tfound on the hard drive, then look for it in the mixfile.\n\t*/\n\tSystemStrings = (char const *)MFCD::Retrieve(Language_Name(\"CONQUER\"));\n\tDebugStrings = (char const *)MFCD::Retrieve(\"DEBUG.ENG\");\n\n\t/*\n\t**\tDefault palette initialization.\n\t*/\n\tmemmove((unsigned char *)&GamePalette[0], (void *)MFCD::Retrieve(\"TEMPERAT.PAL\"), 768L);\n\tWhitePalette[0] = BlackPalette[0];\n//\tGamePalette.Set();\n\n\t/*\n\t**\tInitialize expansion files (if present). Expansion files must be located\n\t**\tin the current directory.\n\t*/\n\tInit_Expansion_Files();\n\n\tSidebarScheme.Background \t= BLACK;\n\tSidebarScheme.Corners    \t= LTGREY;\n\tSidebarScheme.Shadow\t\t \t= DKGREY;\n\tSidebarScheme.Highlight  \t= WHITE;\n\tSidebarScheme.Color\t\t \t= LTGREY;\n\tSidebarScheme.Bright\t\t \t= WHITE;\n\tSidebarScheme.BrightColor\t= WHITE;\n\tSidebarScheme.Box\t\t \t \t= LTGREY;\n\tGadgetClass::Set_Color_Scheme(&SidebarScheme);\n}\n\n\n/***********************************************************************************************\n * Init_Mouse -- Initialize the mouse system.                                                  *\n *                                                                                             *\n *    This routine will ensure that a valid mouse driver is present and a working mouse        *\n *    pointer can be displayed. The mouse is hidden when this routine exits.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Mouse(void)\n{\n\t/*\n\t** Since there is no mouse shape currently available we need\n\t** to set one of our own.\n\t*/\n#ifdef WIN32\n\tShowCursor(false);\n#endif\n\tif (MouseInstalled) {\n\t\tvoid const * temp_mouse_shapes = MFCD::Retrieve(\"MOUSE.SHP\");\n\t\tif (temp_mouse_shapes) {\n\t\t\tSet_Mouse_Cursor(0, 0, Extract_Shape(temp_mouse_shapes, 0));\n\t\t\twhile (Get_Mouse_State() > 1) Show_Mouse();\n\t\t}\n\t} else {\n\t\tchar buffer[255];\n\t\tGamePalette.Set();\n\t\tGamePalette.Set();\n\t\tsprintf(buffer, TEXT_NO_MOUSE);\n\t\tVisiblePage.Clear();\n\t\tWWMessageBox().Process(buffer, TXT_OK);\n\t\tProg_End();\n\t\texit(1);\n\t}\n\n\tMap.Set_Default_Mouse(MOUSE_NORMAL, false);\n\tShow_Mouse();\n\twhile (Get_Mouse_State() > 1) Show_Mouse();\n\tCall_Back();\n\tHide_Mouse();\n}\n\n\n#ifdef OBSOLETE\n/***********************************************************************************************\n * Init_Authorization -- Verifies that the player is authorized to play the game.              *\n *                                                                                             *\n *    This is a development routine that restricts access to the game by way of passwords.     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Authorization(void)\n{\n\tif (Special.IsFromInstall) return;\n\n\tLoad_Title_Page();\n#ifdef WIN32\n\tWait_Vert_Blank();\n#else\t//WIN32\n\tInit_Delay();\n\tWait_Vert_Blank(VertBlank);\n#endif\t//WIN32\n\n\tCCPalette.Set();\n//\t\tSet_Palette(Palette);\n\tHidPage.Blit(SeenPage);\n\tShow_Mouse();\n\n\t/*\n\t**\tFetch the type of game to be played. This will be either\n\t**\tC&C:Red Alert or C&C:Plus.\n\t*/\n//tryagain:\n\n\tbool ok = Debug_Flag;\n\tint counter = 3;\n\n\tif (Debug_Flag) ok = true;\n\n\t/*\n\t**\tC&C:Red Alert requires a password for legal entry. Try (three times) to get a correct\n\t**\tpassword. If not found, then try again.\n\t*/\n\tbool skipper = false;\n#ifdef NEVER\n\twhile (!ok && counter) {\n\t\tSmartPtr<char const> str = Fetch_Password(TXT_PASSWORD_CAPTION, TXT_PASSWORD_MESSAGE, TXT_OK);\n\t\tSmartPtr<long const> lptr = &CheatCodes[0];\n\t\twhile (*lptr) {\n\t\t\tif (Obfuscate(str) == *lptr++) {\n\t\t\t\tok = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tlptr = &EditorCodes[0];\n\t\twhile (*lptr) {\n\t\t\tif (Obfuscate(str) == *lptr++) {\n\t\t\t\tok = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tlptr = &PlayCodes[0];\n\t\twhile (*lptr) {\n\t\t\tif (Obfuscate(str) == *lptr++) {\n\t\t\t\tok = true;\n\t\t\t\tskipper = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (ok) break;\n\n\t\tHide_Mouse();\n\t\tLoad_Title_Page();\n\t\tHidPage.Blit(SeenPage);\n\t\tShow_Mouse();\n\t\tDelay(TIMER_SECOND*(4-counter)*1);\n\t\tif (WWMessageBox().Process(TXT_PASSWORD_ERROR, TXT_TRY_AGAIN, TXT_CANCEL)) {\n\t\t\tgoto tryagain;\n\t\t}\n\n\t\tcounter--;\n\t\tif (counter == 0) goto tryagain;\n\t}\n#endif\n\n\tif (!skipper) {\n\t\tCCPalette.Set();\n\t}\n\n\tHide_Mouse();\n\tLoad_Title_Page();\n\tHidPage.Blit(SeenPage);\n\tShow_Mouse();\n\tCall_Back();\n}\n#endif\n\n\n/***********************************************************************************************\n * Init_Bulk_Data -- Initialize the time-consuming mixfile caching.                            *\n *                                                                                             *\n *    This routine is called to handle the time consuming process of game initialization.      *\n *    The title page will be displayed when this routine is called.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine will take a very long time.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Bulk_Data(void)\n{\n\t/*\n\t**\tCache the main game data. This operation can take a very long time.\n\t*/\n\tMFCD::Cache(\"CONQUER.MIX\");\n\tif (SampleType != 0 && !Debug_Quiet) {\n\t\tMFCD::Cache(\"SOUNDS.MIX\");\n\t\tMFCD::Cache(\"RUSSIAN.MIX\");\n\t\tMFCD::Cache(\"ALLIES.MIX\");\n\t}\n\tCall_Back();\n\n\t/*\n\t**\tFetch the tutorial message data.\n\t*/\n\tINIClass ini;\n\tini.Load(CCFileClass(\"TUTORIAL.INI\"));\n\tfor (int index = 0; index < ARRAY_SIZE(TutorialText); index++) {\n\t\tTutorialText[index] = NULL;\n\n\t\tchar buffer[128];\n\t\tchar num[10];\n\t\tsprintf(num, \"%d\", index);\n\t\tif (ini.Get_String(\"Tutorial\", num, \"\", buffer, sizeof(buffer))) {\n\t\t\tTutorialText[index] = strdup(buffer);\n\t\t}\n\t}\n\n\t/*\n\t**\tPerform one-time game system initializations.\n\t*/\n\tInit_One_Time_Systems();\n}\n\n\n/***********************************************************************************************\n * Init_Keys -- Initialize the cryptographic keys.                                             *\n *                                                                                             *\n *    This routine will initialize the fast cryptographic key. It will also initialize the     *\n *    slow one if this is a scenario editor version of the game.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Keys(void)\n{\n\tRAMFileClass file((void*)Keys, strlen(Keys));\n\tINIClass ini;\n\tini.Load(file);\n\n\tFastKey = ini.Get_PKey(true);\n#ifdef SCENARIO_EDITOR\n\tSlowKey = ini.Get_PKey(false);\n#endif\n}\n\n\n/***************************************************************************\n * Save_Recording_Values -- Saves multiplayer-specific values              *\n *                                                                         *\n * This routine saves multiplayer values that need to be restored for a\t\t*\n * save game.  In addition to saving the random # seed for this scenario, \t*\n * it saves the contents of the actual random number generator; this \t\t*\n * ensures that the random # sequencer will pick up where it left off when\t*\n * the game was saved.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This routine also saves the header for a Recording file, so it must \t\t*\n * save some data not needed specifically by a save-game file (ie Seed).\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\tfile to save to\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = success, false = failure\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/28/1995 BRR : Created.                                             *\n *=========================================================================*/\nbool Save_Recording_Values(CCFileClass & file)\n{\n\tSession.Save(file);\n\tfile.Write(&BuildLevel, sizeof(BuildLevel));\n\tfile.Write(&Debug_Unshroud, sizeof(Debug_Unshroud));\n\tfile.Write(&Seed, sizeof(Seed));\n\tfile.Write(&Scen.Scenario, sizeof(Scen.Scenario));\n\tfile.Write(Scen.ScenarioName, sizeof(Scen.ScenarioName));\n\tfile.Write(&Whom, sizeof(Whom));\n\tfile.Write(&Special, sizeof(SpecialClass));\n\tfile.Write(&Options, sizeof(GameOptionsClass));\n\n\treturn (true);\n}\n\n\n/***************************************************************************\n * Load_Recording_Values -- Loads multiplayer-specific values              *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\t\tfile to load from\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = success, false = failure\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/28/1995 BRR : Created.                                             *\n *=========================================================================*/\nbool Load_Recording_Values(CCFileClass & file)\n{\n\tSession.Load(file);\n\tfile.Read(&BuildLevel, sizeof(BuildLevel));\n\tfile.Read(&Debug_Unshroud, sizeof(Debug_Unshroud));\n\tfile.Read(&Seed, sizeof(Seed));\n\tfile.Read(&Scen.Scenario, sizeof(Scen.Scenario));\n\tfile.Read(Scen.ScenarioName, sizeof(Scen.ScenarioName));\n\tfile.Read(&Whom, sizeof(Whom));\n\tfile.Read(&Special, sizeof(SpecialClass));\n\tfile.Read(&Options, sizeof(GameOptionsClass));\n\treturn (true);\n}\n\nextern \"C\" {\nvoid __PRO(void) {\n//\tprintf(\"_pro\\n\");\n}\n}\n"
  },
  {
    "path": "CODE/INLINE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/INLINE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INLINE.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 08/21/96                                                     *\n *                                                                                             *\n *                  Last Update : September 30, 1996 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Adjacent_Cell -- Calculate the adjacent cell in the direction specified.                  *\n *   Adjacent_Cell -- Calculate the adjacent cell in the direction specified.                  *\n *   Cell_Coord -- Convert a cell to a coordinate value.                                       *\n *   Cell_To_Lepton -- Convert a cell distance into a lepton distance.                         *\n *   Cell_X -- Fetch the X cell component from the cell value.                                 *\n *   Cell_Y -- Fetch the Y cell component from the cell value specified.                       *\n *   Coord_Add -- Adds coordinates together.                                                   *\n *   Coord_Fraction -- Discards all but the sub-cell components of the coordinate.             *\n *   Coord_Mid -- Finds the midpoint between two coordinates.                                  *\n *   Coord_Snap -- Coerce coordinate to refer to center of a cell.                             *\n *   Coord_Sub -- Subtracts one coordinate from another.                                       *\n *   Coord_Whole -- Discards the sub-cell components of the coordinate.                        *\n *   Coord_X -- Fetches the X lepton component from a coordinate value.                        *\n *   Coord_XCell -- Fetch the X cell component from a coordinate value.                        *\n *   Coord_XLepton -- Fetch the X sub-cell lepton component from the coordinate.               *\n *   Coord_Y -- Fetch the Y lepton component from the coordinate value.                        *\n *   Coord_YCell -- Fetch the Y cell component from a coordinate.                              *\n *   Coord_YLepton -- Fetches the Y lepton sub-cell component from the coordinate.             *\n *   Dir_Facing -- Convert a DirType into a FacingType value.                                  *\n *   Dir_To_16 -- Convert a facing to a 0..15 value.                                           *\n *   Dir_To_32 -- Convert a DirType into a 0..31 value.                                        *\n *   Dir_To_8 -- Convert a DirType into a value from 0 to 7.                                   *\n *   Direction -- Calculates the DirType from one cell to another.                             *\n *   Direction -- Determines the facing value from one coordinate to another.                  *\n *   Direction256 -- Calculate the facing value from one coordinate to another.                *\n *   Direction8 -- Fetches the direction from one coordinate to another.                       *\n *   Distance -- Finds the distance between two arbitrary points.                              *\n *   Facing_Dir -- Convert a FacingType into a DirType.                                        *\n *   Lepton_To_Cell -- Convert lepton distance to cell distance.                               *\n *   Lepton_To_Pixel -- Convert a lepton value into pixel value.                               *\n *   Percent_Chance -- Calculate a percentage chance event.                                    *\n *   Pixel_To_Lepton -- Convert pixel value into lepton equivalent.                            *\n *   Random_Pick -- Pick a random number in a specified range.                                 *\n *   Sim_Percent_Chance -- Calculates a percentage chance event for local events.              *\n *   Sim_Random_Pick -- Picks a random number that will not affect the game.                   *\n *   Text_String -- Convert a text number into a text pointer.                                 *\n *   XYP_COORD -- Convert pixel components into a coordinate value.                            *\n *   XYP_Coord -- Combine pixel values into a coordinate.                                      *\n *   XY_Cell -- Create a cell from X and Y cell components.                                    *\n *   XY_Coord -- Convert X Y lepton components into a COORD.                                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef INLINE_H\n#define INLINE_H\n\n\n/***********************************************************************************************\n * Lepton_To_Pixel -- Convert a lepton value into pixel value.                                 *\n *                                                                                             *\n *    Use this routine to convert the specified lepton value into it's pixel corresponding     *\n *    value. The pixel value returned will be the closest pixel value to the lepton value. It  *\n *    will round up or down as necessary.                                                      *\n *                                                                                             *\n * INPUT:   lepton   -- The lepton value to convert into a pixel value.                        *\n *                                                                                             *\n * OUTPUT:  Returns with the lepton value rounded to the nearest pixel component.              *\n *                                                                                             *\n * WARNINGS:   Precision is not maintained by this routine. Thus, if a value is converted to   *\n *             pixel and then back to leptons, the value will probably not be the same.        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Lepton_To_Pixel(LEPTON lepton)\n{\n\treturn (((int)(signed short)lepton * ICON_PIXEL_W) + (ICON_LEPTON_W / 2)) / ICON_LEPTON_W;\n}\n\n\n/***********************************************************************************************\n * Pixel_To_Lepton -- Convert pixel value into lepton equivalent.                              *\n *                                                                                             *\n *    This routine will take the specified pixel value and convert it into lepton value.       *\n *                                                                                             *\n * INPUT:   pixel -- The pixel value to convert.                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the lepton equivalent of the pixel value specified.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline LEPTON Pixel_To_Lepton(int pixel)\n{\n\treturn (LEPTON)(((pixel * ICON_LEPTON_W) + (ICON_PIXEL_W / 2)) / ICON_PIXEL_W);\n}\n\n\n/***********************************************************************************************\n * XY_Coord -- Convert X Y lepton components into a COORD.                                     *\n *                                                                                             *\n *    This routine will take the specified X and Y lepton components and combine them into     *\n *    a coordinate value.                                                                      *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y lepton components to combine.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a coordinate value that is created from the X and Y lepton components.*\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE XY_Coord(LEPTON x, LEPTON y)\n{\n\tCOORD_COMPOSITE coord;\n\n\tcoord.Sub.X.Raw = x;\n\tcoord.Sub.Y.Raw = y;\n\treturn(coord.Coord);\n}\n\n\n/***********************************************************************************************\n * XYP_COORD -- Convert pixel components into a coordinate value.                              *\n *                                                                                             *\n *    This routine will take the specified pixel components and convert and combine them into  *\n *    a coordinate value.                                                                      *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y pixel components to coerce into a coordinate value.           *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate value that matches the pixel values specified.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE XYP_COORD(int x, int y)\n{\n\treturn(XY_Coord(Pixel_To_Lepton(x), Pixel_To_Lepton(y)));\n}\n\n\n/***********************************************************************************************\n * Coord_XCell -- Fetch the X cell component from a coordinate value.                          *\n *                                                                                             *\n *    This routine will extract the X cell component from the coordinate value specified and   *\n *    return the value.                                                                        *\n *                                                                                             *\n * INPUT:   coord -- The coordinate value to extract the X component from.                     *\n *                                                                                             *\n * OUTPUT:  Returns with the X cell component of the coordinate value.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline CELL Coord_XCell(COORDINATE coord)\n{\n\treturn(((COORD_COMPOSITE &)coord).Sub.X.Sub.Cell);\n}\n\n\n/***********************************************************************************************\n * Coord_YCell -- Fetch the Y cell component from a coordinate.                                *\n *                                                                                             *\n *    This routine will extract the Y cell component from the coordinate value specified.      *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to extract the Y cell from.                                *\n *                                                                                             *\n * OUTPUT:  Returns with just the Y cell component of the coordinate value.                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline CELL Coord_YCell(COORDINATE coord)\n{\n\treturn(((COORD_COMPOSITE &)coord).Sub.Y.Sub.Cell);\n}\n\n\n/***********************************************************************************************\n * XY_Cell -- Create a cell from X and Y cell components.                                      *\n *                                                                                             *\n *    This routine will construct a cell value by taking the X and Y cell value components     *\n *    and combining them appropriately.                                                        *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y cell components to combine.                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the CELL value created from the specified components.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline CELL XY_Cell(int x, int y)\n{\n\tCELL_COMPOSITE cell;\n\tcell.Cell = 0;\n\tcell.Sub.X = x;\n\tcell.Sub.Y = y;\n\treturn(cell.Cell);\n}\n\n\n/***********************************************************************************************\n * Cell_To_Lepton -- Convert a cell distance into a lepton distance.                           *\n *                                                                                             *\n *    This routine will take the cell distance specified and convert it into a lepton distance.*\n *                                                                                             *\n * INPUT:   cell_distance  -- The distance in cells to convert.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the lepton equivalent of the cell distance specified.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline LEPTON Cell_To_Lepton(int cell_distance)\n{\n\tLEPTON_COMPOSITE lepton;\n\tlepton.Sub.Cell = (unsigned char)cell_distance;\n\tlepton.Sub.Lepton = 0;\n\treturn(lepton.Raw);\n}\n\n\n/***********************************************************************************************\n * Lepton_To_Cell -- Convert lepton distance to cell distance.                                 *\n *                                                                                             *\n *    This routine will convert the specified lepton distance into the closest cell distance   *\n *    possible. This might require rounding up or down as necessary.                           *\n *                                                                                             *\n * INPUT:   lepton_distance   -- The lepton distance to convert.                               *\n *                                                                                             *\n * OUTPUT:  Returns with the cell distance that most closely corresponds to the lepton         *\n *          distance specified.                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Lepton_To_Cell(LEPTON lepton_distance)\n{\n\tif (((LEPTON_COMPOSITE &)lepton_distance).Sub.Lepton >= (CELL_LEPTON_W/2)) {\n\t\treturn(((LEPTON_COMPOSITE &)lepton_distance).Sub.Cell + 1);\n\t}\n\treturn(((LEPTON_COMPOSITE &)lepton_distance).Sub.Cell);\n}\n\n\n/***********************************************************************************************\n * Coord_X -- Fetches the X lepton component from a coordinate value.                          *\n *                                                                                             *\n *    This routine will extract the X lepton component from the coordinate.                    *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to extract the X lepton equivalent from.                   *\n *                                                                                             *\n * OUTPUT:  Returns with the X lepton portion of the coordinate value specified.               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline LEPTON Coord_X(COORDINATE coord)\n{\n\treturn(((COORD_COMPOSITE &)coord).Sub.X.Raw);\n}\n\n\n/***********************************************************************************************\n * Coord_Y -- Fetch the Y lepton component from the coordinate value.                          *\n *                                                                                             *\n *    This routine will extract the Y lepton component from the coordinate value specified.    *\n *                                                                                             *\n * INPUT:   coord -- The coordinate value to dissect.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the Y lepton component from the specified coordinate value.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline LEPTON Coord_Y(COORDINATE coord)\n{\n\treturn(((COORD_COMPOSITE &)coord).Sub.Y.Raw);\n}\n\n\n/***********************************************************************************************\n * Cell_X -- Fetch the X cell component from the cell value.                                   *\n *                                                                                             *\n *    This routine will extract the X cell component from the cell value specified.            *\n *                                                                                             *\n * INPUT:   cell  -- The cell to extract.                                                      *\n *                                                                                             *\n * OUTPUT:  Returns with the X cell component portion of the cell value specified.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Cell_X(CELL cell)\n{\n\treturn(((CELL_COMPOSITE &)cell).Sub.X);\n}\n\n\n/***********************************************************************************************\n * Cell_Y -- Fetch the Y cell component from the cell value specified.                         *\n *                                                                                             *\n *    This routine will extract the Y cell component from the cell value.                      *\n *                                                                                             *\n * INPUT:   cell  -- The cell value to extract from.                                           *\n *                                                                                             *\n * OUTPUT:  Returns with the Y cell component of the cell value specified.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Cell_Y(CELL cell)\n{\n\treturn(((CELL_COMPOSITE &)cell).Sub.Y);\n}\n\n\n/***********************************************************************************************\n * Coord_XLepton -- Fetch the X sub-cell lepton component from the coordinate.                 *\n *                                                                                             *\n *    This routine will extract just the X sub cell lepton component from the coordinate       *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   coord -- The coordinate value to extract from.                                     *\n *                                                                                             *\n * OUTPUT:  Returns with the X lepton component of the coordinate that is part of the cell.    *\n *          Thus, a coordinate that exactly lines up on the left edge of a cell would return   *\n *          zero. One that exactly lines up on the right edge would return CELL_LEPTON_W.      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Coord_XLepton(COORDINATE coord)\n{\n\treturn(((COORD_COMPOSITE &)coord).Sub.X.Sub.Lepton);\n}\n\n\n/***********************************************************************************************\n * Coord_YLepton -- Fetches the Y lepton sub-cell component from the coordinate.               *\n *                                                                                             *\n *    This routine will extract the sub-cell Y lepton portion of the coordinate.               *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to dissect.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with just the Y lepton portion of the coordinate and only for the sub-cell *\n *          it refers to.                                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Coord_YLepton(COORDINATE coord)\n{\n\treturn(((COORD_COMPOSITE &)coord).Sub.Y.Sub.Lepton);\n}\n\n\n/***********************************************************************************************\n * XYP_Coord -- Combine pixel values into a coordinate.                                        *\n *                                                                                             *\n *    This will convert X and Y pixel values into a coordinate. Primarily this is used for     *\n *    converting mouse clicks into coordinate values.                                          *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y pixel coordinates to convert. Origin is upper left corner.    *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate that most closely corresponds to the pixel values      *\n *          specified.                                                                         *\n *                                                                                             *\n * WARNINGS:   The coordinate is relative to the upper left corner (0,0). To conver the        *\n *             coordinate to a game relative one, it must be biased by the display coordinate  *\n *             of the tactical map and the screen position of the tactical display.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE XYP_Coord(int x, int y)\n{\n\tCOORD_COMPOSITE coord;\n\n\tcoord.Sub.X.Raw = Pixel_To_Lepton(x);\n\tcoord.Sub.Y.Raw = Pixel_To_Lepton(y);\n\treturn(coord.Coord);\n}\n\n\n/***********************************************************************************************\n * Cell_Coord -- Convert a cell to a coordinate value.                                         *\n *                                                                                             *\n *    This routine will convert the specified cell into a coordinat value. The coordinate      *\n *    will refer to the center of the cell specified.                                          *\n *                                                                                             *\n * INPUT:   cell  -- The cell to convert into a coordinate.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate that refers to the center of the cell specified.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Cell_Coord(CELL cell)\n{\n\tCOORD_COMPOSITE coord;\n\n\tcoord.Sub.X.Sub.Cell = (unsigned char)(((CELL_COMPOSITE &)cell).Sub.X);\n\tcoord.Sub.X.Sub.Lepton = (unsigned char)(CELL_LEPTON_W / 2);\n\tcoord.Sub.Y.Sub.Cell = (unsigned char)(((CELL_COMPOSITE &)cell).Sub.Y);\n\tcoord.Sub.Y.Sub.Lepton = (unsigned char)(CELL_LEPTON_W / 2);\n\treturn(coord.Coord);\n}\n\n\n/***********************************************************************************************\n * Coord_Snap -- Coerce coordinate to refer to center of a cell.                               *\n *                                                                                             *\n *    This routine will take the specified coordinate and force it to refer to the center of   *\n *    the cell.                                                                                *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to modify.                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the specified coordinate after it has been modified to refer to the   *\n *          center of the cell.                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Coord_Snap(COORDINATE coord)\n{\n\t((COORD_COMPOSITE &)coord).Sub.X.Sub.Lepton = CELL_LEPTON_W/2;\n\t((COORD_COMPOSITE &)coord).Sub.Y.Sub.Lepton = CELL_LEPTON_W/2;\n\treturn(coord);\n}\n\n\n/***********************************************************************************************\n * Coord_Fraction -- Discards all but the sub-cell components of the coordinate.               *\n *                                                                                             *\n *    Use this routine to discard the cell components of the coordinate, leaving only the      *\n *    sub-cell component.                                                                      *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to modify.                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with just the sub-cell components intact from the supplied coordinate.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Coord_Fraction(COORDINATE coord)\n{\n\t((COORD_COMPOSITE &)coord).Sub.X.Sub.Cell = 0;\n\t((COORD_COMPOSITE &)coord).Sub.Y.Sub.Cell = 0;\n\treturn(coord);\n}\n\n\n/***********************************************************************************************\n * Coord_Whole -- Discards the sub-cell components of the coordinate.                          *\n *                                                                                             *\n *    This routine will discard the sub-cell components, leaving only the whole cell portion.  *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to modify.                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with only the whole cell components of the coordinate intact. The          *\n *          resulting coordinate will refer to the upper left corner of the cell.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Coord_Whole(COORDINATE coord)\n{\n\t((COORD_COMPOSITE &)coord).Sub.X.Sub.Lepton = 0;\n\t((COORD_COMPOSITE &)coord).Sub.Y.Sub.Lepton = 0;\n\treturn(coord);\n}\n\n\n/***********************************************************************************************\n * Coord_Add -- Adds coordinates together.                                                     *\n *                                                                                             *\n *    This routine will add one coordinate to another. Actually, it adds the X and Y components*\n *    separately (signed) and then recombines them back into a coordinate.                     *\n *                                                                                             *\n * INPUT:   coord1   -- One coordinate to add.                                                 *\n *                                                                                             *\n *          coord2   -- The other coordinate to add.                                           *\n *                                                                                             *\n * OUTPUT:  Returns with the logical add of the two coordinates.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Coord_Add(COORDINATE coord1, COORDINATE coord2)\n{\n\tCOORD_COMPOSITE coord;\n\n\tcoord.Sub.X.Raw = (LEPTON)((int)(short)((COORD_COMPOSITE &)coord1).Sub.X.Raw + (int)(short)((COORD_COMPOSITE &)coord2).Sub.X.Raw);\n\tcoord.Sub.Y.Raw = (LEPTON)((int)(short)((COORD_COMPOSITE &)coord1).Sub.Y.Raw + (int)(short)((COORD_COMPOSITE &)coord2).Sub.Y.Raw);\n\treturn(coord.Coord);\n}\n\n\n/***********************************************************************************************\n * Coord_Sub -- Subtracts one coordinate from another.                                         *\n *                                                                                             *\n *    This routine will subtract one coordinate from the other. The coordinates are broken     *\n *    up into their X and Y components, the subtraction is performed, and then they are        *\n *    recombined back into a coordinate to be returned.                                        *\n *                                                                                             *\n * INPUT:   coord1   -- The coordinate to be subtracted from.                                  *\n *                                                                                             *\n *          coord2   -- The coordinate to subtract.                                            *\n *                                                                                             *\n * OUTPUT:  Returns with the result of subtracting coord2 from coord1.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Coord_Sub(COORDINATE coord1, COORDINATE coord2)\n{\n\tCOORD_COMPOSITE coord;\n\n\tcoord.Sub.X.Raw = (LEPTON)((int)(short)((COORD_COMPOSITE &)coord1).Sub.X.Raw - (int)(short)((COORD_COMPOSITE &)coord2).Sub.X.Raw);\n\tcoord.Sub.Y.Raw = (LEPTON)((int)(short)((COORD_COMPOSITE &)coord1).Sub.Y.Raw - (int)(short)((COORD_COMPOSITE &)coord2).Sub.Y.Raw);\n\treturn(coord.Coord);\n}\n\n\n/***********************************************************************************************\n * Coord_Mid -- Finds the midpoint between two coordinates.                                    *\n *                                                                                             *\n *    This will find the coordinate that is exactly between the two coordinates specified.     *\n *                                                                                             *\n * INPUT:   coord1   -- The first coordinate.                                                  *\n *                                                                                             *\n *          coord2   -- The second coordinate.                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the midpoint between the two coordinates.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Coord_Mid(COORDINATE coord1, COORDINATE coord2)\n{\n\tCOORD_COMPOSITE coord;\n\n\tcoord.Sub.X.Raw = (LEPTON)(((int)((COORD_COMPOSITE &)coord1).Sub.X.Raw + (int)((COORD_COMPOSITE &)coord2).Sub.X.Raw) / 2);\n\tcoord.Sub.Y.Raw = (LEPTON)(((int)((COORD_COMPOSITE &)coord1).Sub.Y.Raw + (int)((COORD_COMPOSITE &)coord2).Sub.Y.Raw) / 2);\n\treturn(coord.Coord);\n}\n\n\n/***********************************************************************************************\n * Dir_Facing -- Convert a DirType into a FacingType value.                                    *\n *                                                                                             *\n *    Use this routine to convert the specified DirType value into the closest FacingType      *\n *    value that matches it.                                                                   *\n *                                                                                             *\n * INPUT:   facing   -- The DirType to convert.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with a FacingType value that most closely matches the DirType specified.   *\n *                                                                                             *\n * WARNINGS:   Precision of direction is lost by this transformation.                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline FacingType Dir_Facing(DirType facing)\n{\n\treturn (FacingType)(((unsigned char)((int)facing+0x10)&0xFF)>>5);\n}\n\n\n/***********************************************************************************************\n * Facing_Dir -- Convert a FacingType into a DirType.                                          *\n *                                                                                             *\n *    This will conver the specified FacingType value into the DirType that exactly matches    *\n *    it.                                                                                      *\n *                                                                                             *\n * INPUT:   facing   -- The FacingType to convert.                                             *\n *                                                                                             *\n * OUTPUT:  Returns with the DirType that exactly matches the facing.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline DirType Facing_Dir(FacingType facing)\n{\n\treturn (DirType)((int)facing << 5);\n}\n\n\n/***********************************************************************************************\n * Dir_To_16 -- Convert a facing to a 0..15 value.                                             *\n *                                                                                             *\n *    Use this routine to convert a DirType into a 0 through 15 value.                         *\n *                                                                                             *\n * INPUT:   facing   -- The DirType to convert into a 0..15 value.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the facing converted into a value where 0 equals North, 4 equals      *\n *          East, 8 equals South, etc.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Dir_To_16(DirType facing)\n{\n\treturn Facing16[facing];\n}\n\n\n/***********************************************************************************************\n * Dir_To_32 -- Convert a DirType into a 0..31 value.                                          *\n *                                                                                             *\n *    This will convert the DirType specified, into a 0 through 31 value where zero is North,  *\n *    and rotates clockwise. The return value is baised to take into consideration the         *\n *    distortion caused by 3D studio upon the game vehicle objects.                            *\n *                                                                                             *\n * INPUT:   facing   -- The DirType to convert.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the facing converted into a value from zero to 31.                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Dir_To_32(DirType facing)\n{\n\treturn Facing32[facing];\n}\n\n\n/***********************************************************************************************\n * Direction256 -- Calculate the facing value from one coordinate to another.                  *\n *                                                                                             *\n *    This will calculate the facing from the first coordinate to the second.                  *\n *                                                                                             *\n * INPUT:   coord1   -- The first coordinate that facing will be calculated from.              *\n *                                                                                             *\n *          coord2   -- The second coordinate that facing will be calcuated to.                *\n *                                                                                             *\n * OUTPUT:  Returns with the DirType that is the facing from coord1 to coord2.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline DirType Direction256(COORDINATE coord1, COORDINATE coord2)\n{\n\treturn (Desired_Facing256(Coord_X(coord1), Coord_Y(coord1), Coord_X(coord2), Coord_Y(coord2)));\n}\n\n\n/***********************************************************************************************\n * Direction -- Determines the facing value from one coordinate to another.                    *\n *                                                                                             *\n *    This will determine the DirType from the first coordinate to the second.                 *\n *                                                                                             *\n * INPUT:   coord1   -- The first coordinate that facing will be calculated from.              *\n *                                                                                             *\n *          coord2   -- The second coordinate to calculate facing to.                          *\n *                                                                                             *\n * OUTPUT:  Returns with the DirType that represents the facing from coordinate 1 to coordinate*\n *          2.                                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline DirType Direction(COORDINATE coord1, COORDINATE coord2)\n{\n\treturn (Desired_Facing256(Coord_X(coord1), Coord_Y(coord1), Coord_X(coord2), Coord_Y(coord2)));\n}\n\n\n/***********************************************************************************************\n * Direction8 -- Fetches the direction from one coordinate to another.                         *\n *                                                                                             *\n *    This will calculate the facing from the first coordinate to the second. The return value *\n *    is of limited accuracy, but the calculation is fast.                                     *\n *                                                                                             *\n * INPUT:   coord1   -- The coordinate to calculate the facing from.                           *\n *                                                                                             *\n *          coord2   -- The coordinate to figure the facing to.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the DirType to get from coordinate 1 to coordinate 2.                 *\n *                                                                                             *\n * WARNINGS:   The return DirType is only accurate to the 8 primary compass rose directions.   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline DirType Direction8(COORDINATE coord1, COORDINATE coord2)\n{\n\treturn (Desired_Facing8(Coord_X(coord1), Coord_Y(coord1), Coord_X(coord2), Coord_Y(coord2)));\n}\n\n\n/***********************************************************************************************\n * Direction -- Calculates the DirType from one cell to another.                               *\n *                                                                                             *\n *    This routine will calculate the facing to get from one cell to another. Since dealing    *\n *    with cells is much less precise than with coordinates, the return value is only          *\n *    accurate to 8 facings.                                                                   *\n *                                                                                             *\n * INPUT:   cell1 -- The cell to calculate the DirType from.                                   *\n *                                                                                             *\n *          cell2 -- The cell to calculate the DirType to.                                     *\n *                                                                                             *\n * OUTPUT:  Returns with the DirType to get from the first cell to the second.                 *\n *                                                                                             *\n * WARNINGS:   The return value is only accurate to the 8 primary compass rose directions.     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline DirType Direction(CELL cell1, CELL cell2)\n{\n\treturn (Desired_Facing8(Cell_X(cell1), Cell_Y(cell1), Cell_X(cell2), Cell_Y(cell2)));\n}\n\n\n/***********************************************************************************************\n * Adjacent_Cell -- Calculate the adjacent cell in the direction specified.                    *\n *                                                                                             *\n *    This will coerce the coordinate specified so that it will refer to the immediately       *\n *    adjacent cell in the direction specified.                                                *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to calculate the adjacency from.                           *\n *                                                                                             *\n *          dir   -- The direction to travel to calculate the adjacent cell.                   *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate the refers to the adjacent cell in the direciton       *\n *          specified.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Adjacent_Cell(COORDINATE coord, FacingType dir)\n{\n\treturn (Coord_Snap(Coord_Add(AdjacentCoord[(int)dir & 0x07], coord)));\n}\n\n\n/***********************************************************************************************\n * Adjacent_Cell -- Calculate the adjacent cell in the direction specified.                    *\n *                                                                                             *\n *    This will coerce the coordinate specified so that it will refer to the immediately       *\n *    adjacent cell in the direction specified.                                                *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to calculate the adjacency from.                           *\n *                                                                                             *\n *          dir   -- The direction to travel to calculate the adjacent cell.                   *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate the refers to the adjacent cell in the direciton       *\n *          specified.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Adjacent_Cell(COORDINATE coord, DirType dir)\n{\n\treturn Adjacent_Cell(coord, Dir_Facing(dir));\n}\n\n\n/***********************************************************************************************\n * Adjacent_Cell -- Calculate the adjacent cell in the direction specified.                    *\n *                                                                                             *\n *    This routine will take the specified cell and coerce it to refer to the immediately      *\n *    adjacent cell in the direction specified.                                                *\n *                                                                                             *\n * INPUT:   cell  -- The cell to coerce into an adjacent cell.                                 *\n *                                                                                             *\n *          dir   -- The direction to determine the adjacent cell.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the cell value that represents the adjacent cell in the direction     *\n *          specified.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline CELL Adjacent_Cell(CELL cell, FacingType dir)\n{\n\treturn (CELL)(cell + AdjacentCell[dir]);\n}\n\n\n/***********************************************************************************************\n * Adjacent_Cell -- Calculate the adjacent cell in the direction specified.                    *\n *                                                                                             *\n *    This routine will take the specified cell and coerce it to refer to the immediately      *\n *    adjacent cell in the direction specified.                                                *\n *                                                                                             *\n * INPUT:   cell  -- The cell to coerce into an adjacent cell.                                 *\n *                                                                                             *\n *          dir   -- The direction to determine the adjacent cell.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the cell value that represents the adjacent cell in the direction     *\n *          specified.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline CELL Adjacent_Cell(CELL cell, DirType dir)\n{\n\treturn (CELL)(cell + AdjacentCell[Dir_Facing(dir)]);\n}\n\n\n/***********************************************************************************************\n * Dir_To_8 -- Convert a DirType into a value from 0 to 7.                                     *\n *                                                                                             *\n *    This routine will convert a DirType value into a facing number from 0 to 7.              *\n *                                                                                             *\n * INPUT:   facing   -- The DirType to convert.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the DirType converted to a number from 0 to 7 with 0 being North and  *\n *          rotating clockwise.                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline FacingType Dir_To_8(DirType facing)\n{\n\treturn (FacingType)(((unsigned char)((int)facing|0x10))>>5);\n}\n\n\n/***********************************************************************************************\n * Text_String -- Convert a text number into a text pointer.                                   *\n *                                                                                             *\n *    This routine will convert text numbers (as generated elsewhere) into an actual text      *\n *    pointer that can be used for normal purposes.                                            *\n *                                                                                             *\n * INPUT:   string   -- The text number to extract a pointer to.                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the text that represents the text number specified.      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline char const * Text_String(int string)\n{\n#ifdef FIXIT_NAME_OVERRIDE\n\tif (string < 0 && abs(string) < ARRAY_SIZE(NameOverride)) {\n\t\treturn(NameOverride[-(string+1)]);\n\t}\n#endif\n\n\tif (string < 1000) return(Extract_String(SystemStrings, string));\n\treturn(Extract_String(DebugStrings, string-1000));\n}\n\n\n/***********************************************************************************************\n * Random_Pick -- Pick a random number in a specified range.                                   *\n *                                                                                             *\n *    This routine is used to pick a game influencing random number between (inclusive) the    *\n *    range specified.                                                                         *\n *                                                                                             *\n * INPUT:   a  -- Low limit of range to pick from.                                             *\n *                                                                                             *\n *          b  -- High limit of range to pick from.                                            *\n *                                                                                             *\n * OUTPUT:  Returns with a random number picked between (inclusive) the range of values        *\n *          specified.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T> inline T Random_Pick(T a, T b)\n{\n\treturn T(Scen.RandomNumber((int)a, (int)b));\n};\n\n\n/***********************************************************************************************\n * Percent_Chance -- Calculate a percentage chance event.                                      *\n *                                                                                             *\n *    This will calculate a percentage chance and return with 'true' as likely as the          *\n *    chance value would occur (or less) on a random pick from 1 to 100. Thus a                *\n *    Percent_Chance(50) would return 'true' 50 percent of the time. Percent_Chance(25) would  *\n *    return 'true' 25% of the time, etc.                                                      *\n *                                                                                             *\n * INPUT:   percent  -- The percent value to calculate the chance upon.                        *\n *                                                                                             *\n * OUTPUT:  Returns with 'true' in the same percentage as the percentage number supplied.      *\n *                                                                                             *\n * WARNINGS:   This affects the game syncronization random number generator and should be used *\n *             for those events that could affect the game engine.                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline bool Percent_Chance(int percent)\n{\n\treturn (Scen.RandomNumber(0, 99) < percent);\n}\n\n\n/***********************************************************************************************\n * Sim_Random_Pick -- Picks a random number that will not affect the game.                     *\n *                                                                                             *\n *    Use this routine to pick a random number such that it will be used so that it won't      *\n *    actually affect the outcome of the game. It is critical to use this routine for any      *\n *    random need that won't be needed on other machines in a multiplayer game. The result     *\n *    can be freely used as long as it doesn't affect the outcome of the game.                 *\n *                                                                                             *\n * INPUT:   a  -- Low range of the random number to pick.                                      *\n *                                                                                             *\n *          b  -- High range of the random number to pick.                                     *\n *                                                                                             *\n * OUTPUT:  Returns with a random number between (inclusive) the range limit values            *\n *          specified.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nextern RandomClass NonCriticalRandomNumber;\ntemplate<class T> inline T Sim_Random_Pick(T a, T b)\n{\n\treturn T(NonCriticalRandomNumber((int)a, (int)b));\n};\n\n\n/***********************************************************************************************\n * Sim_Percent_Chance -- Calculates a percentage chance event for local events.                *\n *                                                                                             *\n *    This routine is similar to the normal Percent_Chance() routine except that it doesn't    *\n *    alter the main random number gerenator sequence. As such, this routine should be used    *\n *    for those events that should have a random character, but will either not affect the     *\n *    game engine or are only calculated on one machine in a multiplayer game.                 *\n *                                                                                             *\n * INPUT:   percent  -- The percent chance to calculate the possible return of 'true' on.      *\n *                                                                                             *\n * OUTPUT:  Returns 'true' with the same percentage chance as the percent number specified.    *\n *          A percent value of 50 means 50%, 25 means 25%, etc.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline bool Sim_Percent_Chance(int percent)\n{\n\treturn (NonCriticalRandomNumber(0, 99) < percent);\n}\n\n\n/***********************************************************************************************\n * Distance -- Finds the distance between two arbitrary points.                                *\n *                                                                                             *\n *    This finds the (Dragon Strike) distance between two arbitrary points in flat space.      *\n *    It does this by adding 1/2 the smaller absolute axis difference to the other absolute    *\n *    axis distance. The result is rough but quick to calculate.                               *\n *                                                                                             *\n * INPUT:   x1,y1 -- Coordinate location for point 1.                                          *\n *                                                                                             *\n *          x2,y2 -- Coordinate location for point 2.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the rough distance between the two points. The value returned is      *\n *          expressed in the same units as the parameters were specified in.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Distance(int x1, int y1, int x2, int y2)\n{\n\tint diff1 = y1 - y2;\n\tif (diff1 < 0) diff1 = -diff1;\n\tint diff2 = x1 - x2;\n\tif (diff2 < 0) diff2 = -diff2;\n\tif (diff1 > diff2) {\n\t\treturn(diff1 + ((unsigned)diff2 / 2));\n\t}\n\treturn(diff2 + ((unsigned)diff1 / 2));\n}\n\n\n#endif\n\n"
  },
  {
    "path": "CODE/INT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/INT.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INT.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 04/26/96                                                     *\n *                                                                                             *\n *                  Last Update : April 26, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"mp.h\"\n#include \"int.h\"\n\nint bignum::Error = 0;\nbool bignum::Carry = false;\nbool bignum::Borrow = false;\nbignum bignum::Remainder;\n\n"
  },
  {
    "path": "CODE/INT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/INT.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INT.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 04/26/96                                                     *\n *                                                                                             *\n *                  Last Update : April 26, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef INT_H\n#define INT_H\n\n#include <memory.h>\n#include\t<limits.h>\n#include\t<assert.h>\n#include\t\"mp.h\"\n#include\t\"straw.h\"\n\n#pragma warn -inl\n\ntemplate<int PRECISION>\nclass Int {\n\tpublic:\n\n\t\t/*\n\t\t**\tConstructors and initializers.\n\t\t*/\n\t\tInt(void) {XMP_Init(&reg[0], 0, PRECISION);}\n\t\tInt(unsigned long value) {XMP_Init(&reg[0], value, PRECISION);}\n\n\t\tvoid Randomize(Straw & rng, int bitcount) {XMP_Randomize(&reg[0], rng, bitcount, PRECISION);}\n\t\tvoid Randomize(Straw & rng, const Int & minval, const Int & maxval) {XMP_Randomize(&reg[0], rng, minval, maxval, PRECISION); reg[0] |= 1;}\n\n\t\t/*\n\t\t**\tConvenient conversion operators to get at the underlying array of\n\t\t**\tintegers. Big number math is basically manipulation of arbitrary\n\t\t**\tlength arrays.\n\t\t*/\n\t\toperator digit * () {return & reg[0];}\n\t\toperator const digit * () const {return & reg[0];}\n\n\t\t/*\n\t\t**\tArray access operator (references bit position). Bit 0 is the first bit.\n\t\t*/\n\t\tbool operator[](unsigned bit) const {return(XMP_Test_Bit(&reg[0], bit));}\n\n\t\t/*\n\t\t**\tUnary operators.\n\t\t*/\n\t\tInt & operator ++ (void) {XMP_Inc(&reg[0], PRECISION);return(*this);}\n\t\tInt & operator -- (void) {XMP_Dec(&reg[0], PRECISION);return(*this);}\n\t\tint operator ! (void) const {return(XMP_Test_Eq_Int(&reg[0], 0, PRECISION));}\n\t\tInt operator ~ (void) {XMP_Not(&reg[0], PRECISION);return(*this);}\n\t\tInt operator - (void) const {Int a = *this;a.Negate();return (a);}\n\n\t\t/*\n\t\t**\tAttribute query functions.\n\t\t*/\n\t\tint ByteCount(void) const {return(XMP_Count_Bytes(&reg[0], PRECISION));}\n\t\tint BitCount(void) const {return(XMP_Count_Bits(&reg[0], PRECISION));}\n\t\tbool Is_Negative(void) const {return(XMP_Is_Negative(&reg[0], PRECISION));}\n\t\tunsigned MaxBitPrecision() const {return PRECISION*(sizeof(unsigned long)*CHAR_BIT);}\n\t\tbool IsSmallPrime(void) const {return(XMP_Is_Small_Prime(&reg[0], PRECISION));}\n\t\tbool SmallDivisorsTest(void) const {return(XMP_Small_Divisors_Test(&reg[0], PRECISION));}\n\t\tbool FermatTest(unsigned rounds) const {return(XMP_Fermat_Test(&reg[0], rounds, PRECISION));}\n\t\tbool IsPrime(void) const {return(XMP_Is_Prime(&reg[0], PRECISION));}\n\t\tbool RabinMillerTest(Straw & rng, unsigned int rounds) const {return(XMP_Rabin_Miller_Test(rng, &reg[0], rounds, PRECISION));}\n\n\t\t/*\n\t\t**\t'in-place' binary operators.\n\t\t*/\n\t\tInt & operator += (const Int & number) {Carry = XMP_Add(&reg[0], &reg[0], number, 0, PRECISION);return(*this);}\n\t\tInt & operator -= (const Int & number) {Borrow = XMP_Sub(&reg[0], &reg[0], number, 0, PRECISION);return(*this);}\n\t\tInt & operator *= (const Int & multiplier) {Remainder = *this;Error=XMP_Signed_Mult(&reg[0], Remainder, multiplier, PRECISION);return(*this);}\n\t\tInt & operator /= (const Int & t) {*this = (*this) / t;return *this;}\n\t\tInt & operator %= (const Int & t) {*this = (*this) % t;return *this;}\n\t\tInt &  operator <<= (int bits) {XMP_Shift_Left_Bits(&reg[0], bits, PRECISION);return *this;}\n\t\tInt &  operator >>= (int bits) {XMP_Shift_Right_Bits(&reg[0], bits, PRECISION);return *this;}\n\n\t\t/*\n\t\t**\tMathematical binary operators.\n\t\t*/\n\t\tInt operator + (const Int & number) const {Int term;Carry = XMP_Add(term, &reg[0], number, 0, PRECISION);return(term);}\n\t\tInt operator + (unsigned short b) const {Int result;Carry=XMP_Add_Int(result, &reg[0], b, 0, PRECISION);return(result);}\n//\t\tfriend Int<PRECISION> operator + (digit b, const Int<PRECISION> & a) {return(Int<PRECISION>(b) + a);}\n\t\tInt operator - (const Int & number) const {Int term;Borrow = XMP_Sub(term, &reg[0], number, 0, PRECISION);return(term);}\n\t\tInt operator - (unsigned short b) const {Int result;Borrow = XMP_Sub_Int(result, &reg[0], b, 0, PRECISION);return(result);}\n//\t\tfriend Int<PRECISION> operator - (digit b, const Int<PRECISION> & a) {return(Int<PRECISION>(b) - a);}\n\t\tInt operator * (const Int & multiplier) const {Int result;Error=XMP_Signed_Mult(result, &reg[0], multiplier, PRECISION);return result;}\n\t\tInt operator * (unsigned short b) const {Int result;Error=XMP_Unsigned_Mult_Int(result, &reg[0], b, PRECISION);return(result);}\n//\t\tfriend Int<PRECISION> operator * (digit b, const Int<PRECISION> & a) {return(Int<PRECISION>(b) * a);}\n\t\tInt operator / (const Int & divisor) const {Int quotient = *this;XMP_Signed_Div(Remainder, quotient, &reg[0], divisor, PRECISION);return (quotient);}\n\t\tInt operator / (unsigned long b) const {return(*this / Int<PRECISION>(b));}\n\t\tInt operator / (unsigned short divisor) const {Int quotient;Error=XMP_Unsigned_Div_Int(quotient, &reg[0], divisor, PRECISION);return(quotient);}\n//\t\tfriend Int<PRECISION> operator / (digit a, const Int<PRECISION> & b) {return(Int<PRECISION>(a) / b);}\n\t\tInt operator % (const Int & divisor) const {Int remainder;XMP_Signed_Div(remainder, Remainder, &reg[0], divisor, PRECISION);return(remainder);}\n\t\tInt operator % (unsigned long b) const {return(*this % Int<PRECISION>(b));}\n\t\tunsigned short operator % (unsigned short divisor) const {return(XMP_Unsigned_Div_Int(Remainder, &reg[0], divisor, PRECISION));}\n//\t\tfriend Int<PRECISION> operator % (digit a, const Int<PRECISION> & b) {return(Int<PRECISION>(a) % b);}\n\n\t\t/*\n\t\t**\tBitwise binary operators.\n\t\t*/\n\t\tInt operator >> (int bits) const {Int result = *this; XMP_Shift_Right_Bits(result, bits, PRECISION);return result;}\n\t\tInt operator << (int bits) const {Int result = *this; XMP_Shift_Left_Bits(result, bits, PRECISION);return result;}\n\n\t\t/*\n\t\t**\tComparison binary operators.\n\t\t*/\n\t\tint operator == (const Int &b) const {return (memcmp(&reg[0], &b.reg[0], (MAX_BIT_PRECISION/CHAR_BIT))==0);}\n\t\tint operator != (const Int& b) const {return !(*this == b);}\n\t\tint operator > (const Int & number) const {return(XMP_Compare(&reg[0], number, PRECISION) > 0);}\n\t\tint operator >= (const Int & number) const {return(XMP_Compare(&reg[0], number, PRECISION) >= 0);}\n\t\tint operator < (const Int & number) const {return(XMP_Compare(&reg[0], number, PRECISION) < 0);}\n\t\tint operator <= (const Int & number) const {return(XMP_Compare(&reg[0], number, PRECISION) <= 0);}\n\n\t\t/*\n\t\t**\tMisc. mathematical and logical functions.\n\t\t*/\n\t\tvoid Negate(void) {XMP_Neg(&reg[0], PRECISION);}\n\t\tInt Abs(void) {XMP_Abs(&reg[0], PRECISION);return(*this);}\n\t\tInt times_b_mod_c(Int const & multiplier, Int const & modulus) const {\n\t\t\tInt result;\n\t\t\tError=xmp_stage_modulus(modulus, PRECISION);\n\t\t\tError=XMP_Mod_Mult(result, &reg[0], multiplier, PRECISION);\n\t\t\tXMP_Mod_Mult_Clear(PRECISION);\n\t\t\treturn result;\n\t\t}\n\n\t\tInt exp_b_mod_c(const Int & e, const Int & m) const {\n\t\t\tInt result;\n\t\t\tError=xmp_exponent_mod(result, &reg[0], e, m, PRECISION);\n\t\t\treturn result;\n\t\t}\n\n\n\t\tstatic Int Unsigned_Mult(Int const & multiplicand, Int const & multiplier) {Int product;Error=XMP_Unsigned_Mult(&product.reg[0], &multiplicand.reg[0], &multiplier.reg[0], PRECISION);return(product);}\n\t\tstatic void Unsigned_Divide(Int & remainder, Int & quotient, const Int & dividend, const Int & divisor) {Error=XMP_Unsigned_Div(remainder, quotient, dividend, divisor, PRECISION);}\n\t\tstatic void Signed_Divide(Int & remainder, Int & quotient, const Int & dividend, const Int & divisor) {XMP_Signed_Div(remainder, quotient, dividend, divisor, PRECISION);}\n\t\tInt Inverse(const Int & modulus) const {Int result;XMP_Inverse_A_Mod_B(result, &reg[0], modulus, PRECISION);return(result);}\n\n\t\tstatic Int Decode_ASCII(char const * string) {Int result;XMP_Decode_ASCII(string, result, PRECISION);return(result);}\n\n\t\t// Number (sign independand) inserted into buffer.\n\t\tint Encode(unsigned char *output) const {return(XMP_Encode(output, &reg[0], PRECISION));}\n\t\tint Encode(unsigned char * output, unsigned length) const {return(XMP_Encode(output, length, &reg[0], PRECISION));}\n\t\tvoid Signed_Decode(const unsigned char * from, int frombytes) {XMP_Signed_Decode(&reg[0], from, frombytes, PRECISION);}\n\t\tvoid Unsigned_Decode(const unsigned char * from, int frombytes) {XMP_Unsigned_Decode(&reg[0], from, frombytes, PRECISION);}\n\n\t\t// encode Int using Distinguished Encoding Rules, returns size of output\n\t\tint DEREncode(unsigned char * output) const {return(XMP_DER_Encode(&reg[0], output, PRECISION));}\n\t\tvoid DERDecode(const unsigned char *input) {XMP_DER_Decode(&reg[0], input, PRECISION);}\n\n\t\t// Friend helper functions.\n\t\tfriend Int<PRECISION> Generate_Prime(Straw & rng, int pbits, Int<PRECISION> const * = 0);\n\t\tfriend Int<PRECISION> Gcd(const Int<PRECISION> & a, const Int<PRECISION> & b);\n//\t\tfriend bool NextPrime(Int<PRECISION> & p, const Int<PRECISION> & max, bool blumInt=false);\n//\t\tfriend Int<PRECISION> a_exp_b_mod_pq(const Int<PRECISION> & a, const Int<PRECISION> & ep, const Int<PRECISION> & eq, const Int<PRECISION> & p, const Int<PRECISION> & q, const Int<PRECISION> & u);\n\n\t\tstatic int Error;\n\n\t\t// Carry result from last addition.\n\t\tstatic bool Carry;\n\n\t\t// Borrow result from last subtraction.\n\t\tstatic bool Borrow;\n\n\t\t// Remainder value from the various division routines.\n\t\tstatic Int Remainder;\n\n\n\tprivate:\n\t\tdigit reg[PRECISION];\n\n\n\t\tstruct RemainderTable\n\t\t{\n\t\t\tRemainderTable(const Int<PRECISION> & p) : HasZeroEntry(false)\n\t\t\t{\n\t\t\t\tfor (unsigned i = 0; i < ARRAY_SIZE(primeTable); i++) {\n\t\t\t\t\ttable[i] = p % primeTable[i];\n\t\t\t\t}\n\t\t\t}\n\t\t\tbool HasZero() const {return(HasZeroEntry);}\n\t\t\tvoid Increment(unsigned short increment = 1)\n\t\t\t{\n\t\t\t\tHasZeroEntry = false;\n\t\t\t\tfor (unsigned int i = 0; i < ARRAY_SIZE(primeTable); i++) {\n\t\t\t\t\ttable[i] += increment;\n\t\t\t\t\twhile (table[i] >= primeTable[i]) {\n\t\t\t\t\t\ttable[i] -= primeTable[i];\n\t\t\t\t\t}\n\t\t\t\t\tHasZeroEntry = (HasZeroEntry || !table[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tvoid Increment(const RemainderTable & rtQ)\n\t\t\t{\n\t\t\t\tHasZeroEntry = false;\n\t\t\t\tfor (unsigned int i = 0; i < ARRAY_SIZE(primeTable); i++) {\n\t\t\t\t\ttable[i] += rtQ.table[i];\n\t\t\t\t\tif (table[i] >= primeTable[i]) {\n\t\t\t\t\t\ttable[i] -= primeTable[i];\n\t\t\t\t\t}\n\t\t\t\t\tHasZeroEntry = (HasZeroEntry || !table[i]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbool HasZeroEntry;\n\t\t\tunsigned short table[ARRAY_SIZE(primeTable)];\n\t\t};\n\n};\n\n\ntemplate<class T>\nT Gcd(const T & a, const T & n)\n{\n\tT g[3]={n, a, 0UL};\n\n\tunsigned int i = 1;\n\twhile (!!g[i%3]) {\n\t\tg[(i+1)%3] = g[(i-1)%3] % g[i%3];\n\t\ti++;\n\t}\n\treturn g[(i-1)%3];\n}\n\n\n\n#pragma warning 604 9\n#pragma warning 595 9\ntemplate<class T>\nT Generate_Prime(Straw & rng, int pbits, T const *)\n{\n\tT minQ = (T(1UL) << (unsigned short)(pbits-(unsigned short)2));\n\tT maxQ = ((T(1UL) << (unsigned short)(pbits-(unsigned short)1)) - (unsigned short)1);\n\n\tT q;\n\tT p;\n\n\tdo {\n\t\tq.Randomize(rng, minQ, maxQ);\n\t\tp = (q*2) + (unsigned short)1;\n\n\t\tT::RemainderTable rtQ(q);\n\t\tT::RemainderTable rtP(p);\n\n\t\twhile (rtQ.HasZero() || rtP.HasZero() || !q.IsPrime() || !p.IsPrime()) {\n\t\t\tq += 2;\n\t\t\tp += 4;\n\t\t\tif (q > maxQ) break;\n\n\t\t\trtQ.Increment(2);\n\t\t\trtP.Increment(4);\n\t\t}\n\t} while (q > maxQ);\n\n\treturn(p);\n}\n\n\n\n\n\n\ntypedef Int<MAX_UNIT_PRECISION>\tbignum;\ntypedef Int<MAX_UNIT_PRECISION>\tBigInt;\n\n\n\n//BigInt Gcd(const BigInt & a, const BigInt & n);\n//BigInt Generate_Prime(RandomNumberGenerator & rng, int pbits, BigInt const * dummy);\n\n#endif\n\n"
  },
  {
    "path": "CODE/INTERNET.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /counterstrike/INTERNET.CPP 6     3/17/97 1:05a Steve_tall $ */\n/*************************************************************************************\n **   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                  **\n *************************************************************************************\n *                                                                                   *\n *                 Project Name : Command & Conquer - Red Alert                      *\n *                                                                                   *\n *                    File Name : INTERNET.CPP                                       *\n *                                                                                   *\n *                   Programmer : Steve Tall                                         *\n *                                                                                   *\n *                   Start Date : March 11th, 1996                                   *\n *                                                                                   *\n *                  Last Update : August 5th, 1996 [ST]                              *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Overview:                                                                         *\n *                                                                                   *\n *  Miscellaneous junk related to H2H internet connection.                           *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Functions:                                                             \t \t\t\t*\n *  Check_From_WChat -- Interprets start game packet from WChat           \t \t\t\t*\n *  Read_Game_Options -- Read the game setup options from the wchat packet\t \t\t\t*\n *  Is_User_WChat_Registered -- retrieve the users wchat entry from registry \t\t\t*\n *  Spawn_WChat -- spawns or switches focus to wchat                         \t\t\t*\n *  Spawn_Registration_App -- spawns the C&C/Planet westwood registration app\t\t\t*\n *  Do_The_Internet_Menu_Thang -- Handle case where user clicks on 'Internet' button *\n *                                                                         \t\t\t\t*\n *                                                                         \t\t\t\t*\n *                                                                         \t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifdef WIN32\n\n#include \"function.h\"\n#include \"tcpip.h\"\n#include \"ccdde.h\"\n\n\nextern bool SpawnedFromWChat;\n\n#ifndef WOLAPI_INTEGRATION\nint Read_Game_Options(void);\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern bool Is_Mission_126x126 (char *file_name);\nextern bool Is_Mission_Aftermath (char *file_name);\nextern bool Is_Mission_Counterstrike (char *file_name);\n#endif\n\n/***************************************************************************\n** Internet specific globals\n*/\nchar PlanetWestwoodHandle[] = {\"Handle\"};\t\t\t\t//Planet WW user name\nchar PlanetWestwoodPassword[] = {\"Password\"};\t\t\t//Planet WW password\nchar PlanetWestwoodIPAddress[IP_ADDRESS_MAX] = {\"206.154.108.87\"};\t//IP of server or other player\nlong PlanetWestwoodPortNumber = 1234;\t\t\t\t\t//Port number to send to\nbool PlanetWestwoodIsHost = false;\t\t\t\t\t\t//Flag true if player has control of game options\nunsigned long PlanetWestwoodGameID;\t\t\t\t\t\t//Game ID\nunsigned long PlanetWestwoodStartTime;\t\t\t\t\t//Time that game was started\nHWND\tWChatHWND = 0;\t\t\t\t\t\t\t\t\t\t\t//Handle to Wchat window.\nbool\tGameStatisticsPacketSent;\t\t\t\t\t\t\t//Flag that game stats have been sent to wchat\nbool\tConnectionLost;\t\t\t\t\t\t\t\t\t\t//Flag that the connection to the other player was lost\nint\t\tWChatMaxAhead;\nint\t\tWChatSendRate;\nbool\tSpawnedFromWChat;\nint\t\tShowCommand;\n\n#ifdef FRENCH\n#define TXT_HACKHACK  \"Connexion En Cours...\"\n#endif\n#if defined(ENGLISH) || defined(GERMAN)\n#define TXT_HACKHACK  Text_String(TXT_CONNECTING)\n#endif\n\n/***********************************************************************************************\n * Check_From_WChat -- This function reads in C&CSPAWN.INI and interprets it.                  *\n *                     C&CSPAWN.INI is now sent to us by WCHAT via DDE                         *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Name of C&CSPAWN.INI file. If NULL then get file from DDE Server.                 *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/9/96 1:44PM ST : Created                                                               *\n *=============================================================================================*/\n#ifndef WOLAPI_INTEGRATION\nvoid Check_From_WChat(char *wchat_name)\n{\n\n\tchar\tdefault_string[] = {\"Error\"};\n\tchar\tkey_string[256];\n\tchar *ini_file;\n\tRawFileClass wchat_file;\n\n\t/*\n\t** Get a pointer to C&CSPAWN.INI either by reading it from disk or getting it from\n\t** the DDE server.\n\t*/\n\tif (wchat_name){\n\t\tini_file = new char [8192];\n\t}else{\n\t\tini_file = DDEServer.Get_MPlayer_Game_Info();\n\n#ifdef NEVER\n\t\t/*\n\t\t** Save it to disk as well so I can see it\n\t\t*/\n\t\tRawFileClass anotherfile (\"FROMCHAT.TXT\");\n\t\tanotherfile.Write(ini_file, DDEServer.Get_MPlayer_Game_Info_Length());\n#endif\n\n\t}\n\n\tif (wchat_name){\n\t\twchat_file.Set_Name(wchat_name);\n\t}\n\n\tif (!wchat_name || wchat_file.Is_Available()){\n\n\t\t/*\n\t\t** Read the ini file from disk if we founf it there\n\t\t*/\n\t\tif (wchat_name){\n\t\t\twchat_file.Read(ini_file, wchat_file.Size());\n\t\t}\n\n\t\t/*\n\t\t** Get the IP address\n\t\t*/\n\t\tkey_string[0] = 0;\n\n\t\tWWGetPrivateProfileString(\"Internet\",\n\t\t\t\t\t\t\t\t\t\t\"Address\",\n\t\t\t\t\t\t\t\t\t\tdefault_string,\n\t\t\t\t\t\t\t\t\t\tkey_string,\n\t\t\t\t\t\t\t\t\t\tsizeof(key_string),\n\t\t\t\t\t\t\t\t\t\tini_file);\n\n\n\t\tif (!strcmp (key_string, default_string)) {\n\t\t\tif (wchat_name) delete ini_file;\n\t\t\treturn;\n\t\t}\n\t\tstrcpy (PlanetWestwoodIPAddress, key_string);\n\n\n\n\t\t/*\n\t\t** Get the port number\n\t\t*/\n\t\tkey_string[0] = 0;\n\n\t\tWWGetPrivateProfileString(\"Internet\",\n\t\t\t\t\t\t\t\t\t\t\"Port\",\n\t\t\t\t\t\t\t\t\t\tdefault_string,\n\t\t\t\t\t\t\t\t\t\tkey_string,\n\t\t\t\t\t\t\t\t\t\tsizeof(key_string),\n\t\t\t\t\t\t\t\t\t\tini_file);\n\n\n\t\tif (!strcmp (key_string, default_string)) {\n\t\t\tif (wchat_name) delete ini_file;\n\t\t\treturn;\n\t\t}\n\n\t\tPlanetWestwoodPortNumber = atol(key_string);\n\n\n\t\t/*\n\t\t** Get host or client\n\t\t*/\n\t\tkey_string[0] = 0;\n\n\t\tWWGetPrivateProfileString(\"Internet\",\n\t\t\t\t\t\t\t\t\t\t\"Host\",\n\t\t\t\t\t\t\t\t\t\tdefault_string,\n\t\t\t\t\t\t\t\t\t\tkey_string,\n\t\t\t\t\t\t\t\t\t\tsizeof(key_string),\n\t\t\t\t\t\t\t\t\t\tini_file);\n\n\n\t\tif (!strcmp (key_string, default_string)) {\n\t\t\tif (wchat_name) delete ini_file;\n\t\t\treturn;\n\t\t}\n\n\t\tif (strchr (key_string, '1')){\n\t\t\tPlanetWestwoodIsHost = true;\n\t\t}else{\n\t\t\tPlanetWestwoodIsHost = false;\n\t\t}\n\n\n\t\tSpecial.IsFromWChat = true;\n\t}\n\n\tif (wchat_name) delete ini_file;\n\n}\n#endif\t//\t!WOLAPI_INTEGRATION\n\n\n/***************************************************************************\n * Read_Game_Options -- reads multiplayer game options from disk           *\n *                                                                         *\n * This routine is used for multiplayer games which read the game options\t*\n * from disk, rather than through a connection dialog.\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tname of C&CSPAWN.INI file. Null if data should be got from DDE server*                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                          \\                                     *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/11/1996 BRR : Created.                                             *\n *=========================================================================*/\n#ifndef WOLAPI_INTEGRATION\nint Read_Game_Options(char *name)\n{\n\tchar *buffer;\n\n\tchar filename[256] = {\"INVALID.123\"};\n\n\tif (name){\n\t\tstrcpy (filename, name);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tCreate filename and read the file.\n\t------------------------------------------------------------------------*/\n\tCCFileClass file (filename);\n\n\tif (name && !file.Is_Available()) {\n\t\treturn(0);\n\t} else {\n\t\tif (name){\n\t\t\tbuffer = new char [8192];\t\t\t\t\t\t\t// INI staging buffer pointer.\n\t\t\tmemset(buffer, '\\0', 8192);\n\t\t\tfile.Read(buffer, 8192-1);\n\t\t\tfile.Close();\n\t\t}else{\n\t\t\tbuffer = DDEServer.Get_MPlayer_Game_Info();\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tGet the player's name\n\t------------------------------------------------------------------------*/\n\tWWGetPrivateProfileString(\"Options\", \"Handle\", \"Noname\", Session.Handle,\n\t\tsizeof(Session.Handle), buffer);\n\tstrcpy(Session.GameName, Session.Handle);\n\tSession.ColorIdx = (PlayerColorType) WWGetPrivateProfileInt(\"Options\", \"Color\", 0, buffer);\n\tSession.PrefColor = Session.ColorIdx;\n\tint temp = WWGetPrivateProfileInt(\"Options\", \"Side\", 0, buffer);\n\tSession.House = (HousesType) ((int)HOUSE_USSR + temp);\n\n\tSession.Options.Credits = WWGetPrivateProfileInt(\"Options\", \"Credits\", 0, buffer);\n\tSession.Options.Bases = WWGetPrivateProfileInt(\"Options\", \"Bases\", 0, buffer);\n\tSession.Options.Tiberium = WWGetPrivateProfileInt(\"Options\", \"Tiberium\", 0, buffer);\n\tSession.Options.Goodies = WWGetPrivateProfileInt(\"Options\", \"Crates\", 0, buffer);\n\tSpecial.IsShadowGrow = WWGetPrivateProfileInt (\"Options\", \"Shadow\", 0, buffer);\n\tBuildLevel = WWGetPrivateProfileInt(\"Options\", \"BuildLevel\", 0, buffer);\n\tSession.Options.UnitCount = WWGetPrivateProfileInt(\"Options\", \"UnitCount\", 0, buffer);\n\tSeed = WWGetPrivateProfileInt(\"Options\", \"Seed\", 0, buffer);\n\tSpecial.IsCaptureTheFlag = WWGetPrivateProfileInt(\"Options\", \"CapFlag\", 0, buffer);\n\tUnitBuildPenalty = WWGetPrivateProfileInt (\"Options\", \"BuildRate\", 100, buffer);\n\n\tPlanetWestwoodGameID = WWGetPrivateProfileInt(\"Internet\", \"GameID\", 0, buffer);\n\tPlanetWestwoodStartTime = WWGetPrivateProfileInt (\"Internet\", \"StartTime\", 0, buffer);\n\tWChatHWND = (HWND) WWGetPrivateProfileInt(\"Internet\", \"HWND\", (int)FindWindow(\"OWL_Window\", \"Westwood Chat\"), buffer);\n\n\tSession.Options.AIPlayers = WWGetPrivateProfileInt(\"Options\", \"AI\", 0, buffer);\t\t//Number of AI players\n\tif (Session.Options.AIPlayers){\n\t\tSession.Options.Ghosts = 1;\n\t}\n\n\tif (Session.Options.Tiberium) {\n\t\tSpecial.IsTGrowth = 1;\n\t\tSpecial.IsTSpread = 1;\n\t} else {\n\t\tSpecial.IsTGrowth = 0;\n\t\tSpecial.IsTSpread = 0;\n\t}\n\n\t/*\n\t** Read the scenario name from the .INI and try to match it with a scenario file in our list.\n\t*/\n\tWWGetPrivateProfileString(\"Options\", \"Scenario\", \"SCM01EA.INI\",\n\t\t\t\t\t\t\t\t\t\tSession.Options.ScenarioDescription,\n\t\t\t\t\t\t\t\t\t\tsizeof (Session.Options.ScenarioDescription),\n\t\t\t\t\t\t\t\t\t\tbuffer);\n\t//WWDebugString (\"RA95I - Scenario is \");\n\t//WWDebugString (Session.Options.ScenarioDescription);\n\t//WWDebugString (\"\\n\");\n\n\tSession.Options.ScenarioIndex = -1;\n\tfor (int i = 0; i < Session.Scenarios.Count(); i++) {\n\t\tif (!strcmp (Session.Scenarios[i]->Description(), Session.Options.ScenarioDescription) ){\n\t\t\tSession.Options.ScenarioIndex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (PlanetWestwoodIsHost){\n\t\t/*\n\t\t** Special new kludge for counterstrike.\n\t\t**\n\t\t** The only time the file can be unavailable is if its a counterstrike\n\t\t** mission and the CS CD is not in the drive so\n\t\t** make sure the counterstrike CD is in the drive.\n\t\t**\n\t\t** If Counterstrike is installed then force the CD\n\t\t** to be there.\n\t\t**\n\t\t*/\n\t\tif (Session.Options.ScenarioIndex == -1) {\n\t\t\t//WWDebugString (\"RA95I - Session.Options.ScenarioIndex == -1\\n\");\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif( (Expansion_CS_Present() && Is_Mission_Counterstrike(Session.ScenarioFileName)) ||\n\t\t\t    (Expansion_AM_Present() && Is_Mission_Aftermath(Session.ScenarioFileName)) ) {\n#else\n\t\t\tif ( Expansion_CS_Present() ) {\n#endif\n\n\t\t\t\tint current_drive = CCFileClass::Get_CD_Drive();\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tint index=Get_CD_Index(current_drive, 1*60);\n\t\t\t\tbool needcd = false;\n\t\t\t\tif (Is_Mission_Counterstrike(Session.ScenarioFileName)) {\n\t\t\t\t\tif (index != 2 && index != 3) {\n\t\t\t\t\t\tRequiredCD = 2;\n\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (Is_Mission_Aftermath(Session.ScenarioFileName)) {\n\t\t\t\t\tif (index != 3) {\n\t\t\t\t\t\tRequiredCD = 3;\n\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (needcd) {\n#else\n\t\t\t\tif ( Get_CD_Index(current_drive, 1*60) != 2 ){\n\t\t\t\t\tRequiredCD = 2;\n#endif\n\t\t\t\t\t//WWDebugString (\"RA95I - CounterStrike CD not in drive\\n\");\n\n\t\t\t\t\tif (!Force_CD_Available (RequiredCD)){\n\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t}\n\t\t\t\t\t//WWDebugString (\"RA95I - Returned from Force_CD_Available()\\n\");\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Update the internal list of scenarios to include the counterstrike\n\t\t\t\t\t** list.\n\t\t\t\t\t*/\n\t\t\t\t\tSession.Read_Scenario_Descriptions();\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** See if that scenario is available now. Its fatal if it isnt.\n\t\t\t*/\n\t\t\tSession.Options.ScenarioIndex = -1;\n\t\t\tfor (i = 0; i < Session.Scenarios.Count(); i++) {\n\t\t\t\tif (!strcmp (Session.Scenarios[i]->Description(), Session.Options.ScenarioDescription) ){\n\t\t\t\t\tSession.Options.ScenarioIndex = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t//if (Session.Options.ScenarioIndex == -1)\n\t\t\t//\tWWDebugString (\"RA95I - Session.Options.ScenarioIndex is still -1\\n\");\n\n\t\t}\n\t}\n\n\n\tOptions.GameSpeed = 0;\n\n\n\t//MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);\n\n\tSession.MaxAhead = WChatMaxAhead = WWGetPrivateProfileInt(\"Timing\", \"MaxAhead\", 9, buffer);\n\tSession.FrameSendRate = WChatSendRate = WWGetPrivateProfileInt(\"Timing\", \"SendRate\", 3, buffer);\n\n\tif (name) delete buffer;\n\treturn (1);\n\n}\n#endif\t//\t!WOLAPI_INTEGRATION\n\n\n\n\n/***********************************************************************************************\n * Get_Registry_Sub_Key -- search a registry key for a sub-key                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    handle of key to search                                                           *\n *           text to search for                                                                *\n *           true if old key should be closed when new key opened                              *\n *                                                                                             *\n * OUTPUT:   handle to the key we found or 0                                                   *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/12/96 2:11PM ST : Created                                                              *\n *=============================================================================================*/\n\nextern HKEY Get_Registry_Sub_Key (HKEY base_key, char *search_key, BOOL close);\n\n\n\nvoid Just_Path(char *path, char *destpath)\n{\n\tchar *terminator = NULL;\t\t//He'll be back.\n\n\tstrcpy  (destpath, path);\n\tterminator = strrchr (destpath, '\\\\');\n\tif (terminator){\n\t\t*terminator = 0;\n\t}\n}\n\n\n\n\n\n/***********************************************************************************************\n * Is_User_WChat_Registered -- retrieve the users wchat entry from the registry                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:  Nothing                                                                             *\n *                                                                                             *\n * OUTPUT:   TRUE if users wchat entry was found in the registry                               *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/12/96 2:13PM ST : Created                                                              *\n *=============================================================================================*/\nbool Is_User_WChat_Registered(char *buffer, int buffer_len)\n{\n\tHKEY\tkey;\n\tchar\tuser_handle[256];\n\tDWORD\tuser_handle_size = sizeof (user_handle);\n\tchar\tuser_pword[256];\n\tDWORD\tuser_pword_size = sizeof (user_pword);\n\n\n\t/*\n\t** Check HKEY_CLASSES_ROOT first. Old versions of Wchat register there\n\t*/\n\tkey = Get_Registry_Sub_Key (HKEY_CLASSES_ROOT, \"Wchat\", FALSE);\n\n\tif (key){\n\t\tkey = Get_Registry_Sub_Key (key, \"Nick1\", TRUE);\n\t\tif (key){\n\n\t\t\tif (RegQueryValue(key, \"Nick\", user_handle, (long*)&user_handle_size) == ERROR_SUCCESS){\n\n\t\t\t\tif (RegQueryValue(key, \"Pass\", user_pword, (long*)&user_pword_size) == ERROR_SUCCESS){\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If the first char of the users name is non-numberic and there is a password\n\t\t\t\t\t** then return success\n\t\t\t\t\t*/\n\t\t\t\t\tif ((user_handle[0] < '0' || user_handle[0] > '9') && user_pword[0]){\n\t\t\t\t\t\tRegCloseKey( key );\n\t\t\t\t\t\treturn (TRUE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tRegCloseKey ( key );\n\t}\n\n\n\n\t/*\n\t** Check HKEY_LOCAL_MACKINE/Software\n\t*/\n\tuser_handle_size = sizeof (user_handle);\n\n\tkey = Get_Registry_Sub_Key (HKEY_LOCAL_MACHINE, \"SOFTWARE\", FALSE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"Westwood\", TRUE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"InetReg\", TRUE);\n\tif (!key) return (FALSE);\n\n\tif (RegQueryValueEx(key, \"UserName\", NULL, NULL, (unsigned char*)user_handle, &user_handle_size) != ERROR_SUCCESS){\n\t\tRegCloseKey(key);\n\t\treturn (FALSE);\n\t}\n\n\tRegCloseKey(key);\n\tmemcpy (buffer, user_handle, min(buffer_len, user_handle_size));\n\n\t/*\n\t** If the first char of the users name is non-numeric then return success\n\t*/\n\tif (user_handle[0] < '0' || user_handle[0] > '9'){\n\t\treturn (TRUE);\n\t}else{\n\t\treturn (FALSE);\n\t}\n}\n\n\n\n/***********************************************************************************************\n * Spawn_WChat -- spawns or switches focus to wchat                                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    can launch. If set then we are allowed to launch WChat if not already running     *\n *                                                                                             *\n * OUTPUT:   True if wchat was spawned                                                         *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/8/96 12:33PM ST : Created                                                              *\n *=============================================================================================*/\n#ifndef WOLAPI_INTEGRATION\nbool Poke_WChat(void);\nbool Spawn_WChat(bool can_launch)\n{\n\tWWDebugString (\"RA95 - In Spawn_WChat.\\n\");\n\tchar packet[10] = {\"Hello\"};\n\tHWND chat_window = NULL;\n\n\t/*\n\t** See if WChat is already running...\n\t*/\n\tif (WChatHWND && IsWindow (WChatHWND) ){\n\t\tchat_window = WChatHWND;\n\t}else{\n\t\tchat_window = FindWindow ( \"OWL_Window\", \"Westwood Chat\" );\n\t}\n\n\tif (chat_window){\n\t/*\n\t** WChat is already running. Minimize myself then try to give it focus.\n\t*/\n\t\tBlackPalette.Set();\n\t\tVisiblePage.Clear();\n\t\tShowWindow (MainWindow, SW_MINIMIZE);\n\t\t/*\n\t\t** Give windoze a couple of secs to sort itself out.\n\t\t*/\n\t\tCountDownTimerClass wibble_timer;\n\t\twibble_timer.Set ( 60 * 3, true);\n\n\t\twhile (wibble_timer.Time()){\n\t\t\t/*\n\t\t\t** Call our message loop to make sure we get all the messages that are sent to us\n\t\t\t** when we minimise.\n\t\t\t*/\n\t\t\tKeyboard->Check();\n\t\t}\n\n\t\t/*\n\t\t** Send chat a tickle message so it knows to send the game stats to the server.\n\t\t*/\n\t\tif (GameStatisticsPacketSent && !PlanetWestwoodIsHost) {\n\t\t\tSend_Data_To_DDE_Server (packet, strlen(packet), DDEServerClass::DDE_TICKLE);\n\t\t}\n\n\t\t//Send_Data_To_DDE_Server (packet, strlen(packet), DDEServerClass::DDE_TICKLE);\n\t\t/*\n\t\t** Give the focus to WChat\n\t\t*/\n\t\tSetForegroundWindow ( chat_window );\n\t\tShowWindow ( chat_window, SW_RESTORE );\n\t\treturn(true);\n\t}\n\n\n\t/*\n\t** Fail if we aren't allowed to launch wchat and we couldnt find its window.\n\t*/\n\tif (!can_launch) return (false);\n\n\n\t/*\n\t** Find where WChat was installed to\n\t*/\n\tHKEY\tkey;\n\tchar\twchat_loc[256];\n\tDWORD\twchat_loc_size = 256;\n\n\tkey = Get_Registry_Sub_Key (HKEY_LOCAL_MACHINE, \"SOFTWARE\", FALSE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"Westwood\", TRUE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"WChat\", TRUE);\n\tif (!key) return (FALSE);\n\n\t//key = Get_Registry_Sub_Key (key, \"UserName\", TRUE);\n\t//if (!key) return (FALSE);\n\n\t//key = Get_Registry_Sub_Key (key, \"Nick\", TRUE);\n\t//if (!key) return (FALSE);\n\n\tif (RegQueryValueEx(key, \"InstallPath\", NULL, NULL, (unsigned char*)wchat_loc, &wchat_loc_size) != ERROR_SUCCESS){\n\t\tRegCloseKey(key);\n\t\treturn (FALSE);\n\t}\n\n\tRegCloseKey(key);\n\n\tPROCESS_INFORMATION process_info;\n\tSTARTUPINFO start_info;\n\tmemset ((void*)&start_info, 0, sizeof(start_info));\n\tstart_info.cb = sizeof(start_info);\n\tchar justpath [256];\n\tJust_Path(wchat_loc, justpath);\n\n\t/*\n\t** We found WChat in the registry. Minimize myself then try to spawn it.\n\t*/\n\tBlackPalette.Set();\n\tVisiblePage.Clear();\n\tShowWindow (MainWindow, SW_MINIMIZE);\n\t/*\n\t** Give windoze a couple of secs to sort itself out.\n\t*/\n\tCountDownTimerClass wibble_timer;\n\twibble_timer.Set ( 60 * 3, true);\n\n\twhile (wibble_timer.Time()){\n\t\t/*\n\t\t** Call our message loop to make sure we get all the messages that are sent to us\n\t\t** when we minimise.\n\t\t*/\n\t\tKeyboard->Check();\n\t}\n\tbool success = CreateProcess (wchat_loc, NULL, NULL, NULL, false, 0, NULL, justpath, &start_info, &process_info);\n\n\tif (success){\n\t\treturn (true);\n\t}else{\n\t\tShowWindow (MainWindow, SW_RESTORE);\n\t\twhile ( Keyboard->Check() ) {};\n\t\treturn (false);\n\t}\n}\n\n#endif\t//#ifndef WOLAPI_INTEGRATION\n\n/***********************************************************************************************\n * Spawn_Registration_App -- spawns the C&C/Planet westwood registration app                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   True if app was spawned                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/8/96 12:33PM ST : Created                                                              *\n *=============================================================================================*/\n#ifndef WOLAPI_INTEGRATION\nbool Spawn_Registration_App(void)\n{\n\n\t/*\n\t** Find where inetreg was installed to\n\t*/\n\n\tHKEY\tkey;\n\tchar\tinetreg_loc[256];\n\tDWORD\tinetreg_loc_size = 256;\n\n\tkey = Get_Registry_Sub_Key (HKEY_LOCAL_MACHINE, \"SOFTWARE\", FALSE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"Westwood\", TRUE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"InetReg\", TRUE);\n\tif (!key) return (FALSE);\n\n\tif (RegQueryValueEx(key, \"InstallPath\", NULL, NULL, (unsigned char*)inetreg_loc, &inetreg_loc_size) != ERROR_SUCCESS){\n\t\tRegCloseKey(key);\n\t\treturn (FALSE);\n\t}\n\n\tRegCloseKey(key);\n\n\tPROCESS_INFORMATION process_info;\n\tSTARTUPINFO start_info;\n\tchar justpath \t[256];\n\tmemset ((void*)&start_info, 0, sizeof(start_info));\n\tstart_info.cb = sizeof(start_info);\n\tJust_Path(inetreg_loc, justpath);\n\n\tBOOL success = CreateProcess (inetreg_loc, NULL, NULL, NULL, false, 0, NULL, justpath, &start_info, &process_info);\n\tif (success){\n\t\t//WaitForSingleObject (process_info.hProcess, 1000*10000);\n\t\t//SetForegroundWindow ( MainWindow );\n\t\t//ShowWindow ( MainWindow, SW_RESTORE );\n\t}\n\treturn (success);\n\n}\n\n#endif\t//#ifndef WOLAPI_INTEGRATION\n\n\n/***********************************************************************************************\n * Do_The_Internet_Menu_Thang -- Handle case where user clicks on 'Internet' button            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/7/96 8:30PM ST : Created                                                               *\n *=============================================================================================*/\n#ifndef WOLAPI_INTEGRATION\nbool Do_The_Internet_Menu_Thang(void)\n{\n\n\tint factor\t\t\t= (SeenBuff.Get_Width() == 320) ? 1 : 2;\n\tchar packet[10] = {\"Hello\"};\n\n\t/*\n\t** Dialog & button dimensions\n\t*/\n\tint d_dialog_w = 120 *factor;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 80*factor;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320*factor - d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\tint d_dialog_y = ((200*factor - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_margin1=10;\n\tint d_txt6_h=15;\n\n#if (GERMAN | FRENCH)\n\tint d_cancel_w = 50*factor;\n#else\n\tint d_cancel_w = 40*factor;\n#endif\n\tint d_cancel_h = 9*factor;\n\tint d_cancel_x = d_dialog_cx - d_cancel_w / 2;\n\tint d_cancel_y = d_dialog_y + d_dialog_h - 20*factor;\n\n\tint\twidth;\n\tint\theight;\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tTBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\tFormat_Window_String((char*)TXT_HACKHACK, SeenBuff.Get_Height(), width, height);\n\n\n\t/*\n\t** Button Enumerations\n\t*/\n\tenum {\n\t\tBUTTON_CANCEL = 100,\n\t};\n\n\t/*\n\t** Buttons\n\t*/\n\t//TextButtonClass *buttons;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,\n\t\tTPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n//#if (GERMAN | FRENCH)\n//\t\td_cancel_x, d_cancel_y);\n//#else\n\t\td_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n//#endif\n\n\t//buttons = &cancelbtn;\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tTBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\n\tchar users_name[256];\n\tint  buffer_len = sizeof (users_name);\n\tbool process;\n\tbool display;\n\tKeyNumType input;\n\n\n\tif (!Special.IsFromWChat && !SpawnedFromWChat){\n\t\t/*\n\t\t** If the user is registered with Planet Westwood then spawn WChat.\n\t\t*/\n\t\tif (Is_User_WChat_Registered(users_name, buffer_len)){\n\t\t\tGameStatisticsPacketSent = false;\n\t\t\tif (!Spawn_WChat(true)){\n\t\t\t\tSet_Logic_Page(SeenBuff);\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tSet_Palette(CCPalette);\n\t\t\t\tWWMessageBox().Process(TXT_ERROR_UNABLE_TO_RUN_WCHAT, TXT_OK);\n\t\t\t\tLogicPage->Clear();\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t** OK, whatever, just run WChat anyway.\n\t\t\t*/\n\t\t\tif (!Spawn_WChat (true)){\n\n\t\t\t\tSet_Logic_Page(SeenBuff);\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tSet_Palette(CCPalette);\n\n\t\t\t\t//WWMessageBox().Process(TXT_EXPLAIN_REGISTRATION, TXT_CANCEL);\n\t\t\t\tWWMessageBox().Process(TXT_NO_REG_APP, TXT_CANCEL);\n\t\t\t}\n\t\t\tLoad_Title_Page(true);\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\n\t** User is registered and we spawned WChat. Wait for a game start message from WChat.\n\t**\n\t*/\n\n\tprocess = true;\n\tdisplay = true;\n\n\twhile (process){\n\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored){\n\t\t\tAllSurfaces.SurfacesRestored = FALSE;\n\t\t\tdisplay = true;\n\t\t}\n\n\t\tif (display) {\n\t\t\tSet_Logic_Page(SeenBuff);\n\n\t\t\tHide_Mouse();\n\t\t\t/*\n\t\t\t** Redraw backgound & dialog box\n\t\t\t*/\n\t\t\tLoad_Title_Page(true);\n\t\t\tSet_Palette(CCPalette);\n\n\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t/*\n\t\t\t** Dialog & Field labels\n\t\t\t*/\n\t\t\tDraw_Caption (TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);\n\n\t\t\tFancy_Text_Print(TXT_HACKHACK, d_dialog_cx-width/2, d_dialog_y + 25*factor,\n\t\t\t\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);\n\n\t\t\t//cancelbtn.Zap();\n\t\t\t//buttons = &cancelbtn;\n\n\t\t\t/*\n\t\t\t.................... Rebuild the button list ....................\n\t\t\t*/\n\t\t\t//buttons->Draw_All();\n\t\t\tcancelbtn.Draw_Me(true);\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t}\n\n\n\t\t/*\n\t\t** See if the game start packet has arrived from wchat yet.\n\t\t*/\n\t\tif (DDEServer.Get_MPlayer_Game_Info()){\n\t\t\t//MessageBox (NULL, \"About to restore focus to C&C95\", \"C&C95\", MB_OK);\n\t\t\t//SetForegroundWindow ( MainWindow );\n\t\t\t//ShowWindow ( MainWindow, SW_SHOWMAXIMIZED\t);\n\t\t\treturn(true);\n\t\t}\n\n\t\t//input = buttons->Input();\n\t\tinput = cancelbtn.Input();\n\n\t\t/*\n\t\t---------------------------- Process input ----------------------------\n\t\t*/\n\t\tswitch (input) {\n\n\t\t\t/*\n\t\t\t** Cancel. Just return to the main menu\n\t\t\t*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tSend_Data_To_DDE_Server (packet, strlen(packet), DDEServerClass::DDE_CONNECTION_FAILED);\n\t\t\t\tGameStatisticsPacketSent = false;\n\t\t\t\tSpawn_WChat(false);\n\t\t\t\tbreak;\n\t\t}\n\n\t}\n\n\treturn (false);\n}\n\n#endif\t//#ifndef WOLAPI_INTEGRATION\n\n\n\n#endif\t//WIN32\n"
  },
  {
    "path": "CODE/INTERNET.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                     $Archive:: /Sun/Internet.h                                             $*\n *                                                                                             *\n *                      $Author:: Joe_b                                                       $*\n *                                                                                             *\n *                     $Modtime:: 8/05/97 6:45p                                               $*\n *                                                                                             *\n *                    $Revision:: 7                                                           $*\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef INTERNET_H\n#define INTERNET_H\n\n#define IP_ADDRESS_MAX 40\n\n\nvoid\tRegister_Game_Start_Time(void);\nvoid\tRegister_Game_End_Time(void);\nvoid\tSend_Statistics_Packet(void);\nvoid \tCheck_From_WChat(char *wchat_name);\nbool \tDo_The_Internet_Menu_Thang (void);\nbool \tServer_Remote_Connect(void);\nbool \tClient_Remote_Connect(void);\nint \tRead_Game_Options(char *name);\n\nextern char PlanetWestwoodIPAddress[IP_ADDRESS_MAX];\nextern long PlanetWestwoodPortNumber;\nextern bool PlanetWestwoodIsHost;\n\n#endif\n"
  },
  {
    "path": "CODE/INTERPAL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/INTERPAL.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INTERPAL.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : December 7th 1995                                            *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *  This module contains functions to allow use of old 320x200 animations on a 640x400 screen  *\n *                                                                                             *\n * Functions:                                                                                  *\n *  Read_Interpolation_Palette -- reads an interpolation palette table from disk               *\n *  Write_Interpolation_Palette -- writes an interpolation palette to disk                     *\n *  Create_Palette_Interpolation_Table -- build the palette interpolation table                *\n *  Increase_Palette_Luminance -- increase the contrast of a palette                           *\n *  Interpolate_2X_Scale -- Stretch a 320x200 graphic buffer into 640x400                      *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\nBOOL\tInterpolationPaletteChanged = FALSE;\nextern \"C\" {\nextern void __cdecl Asm_Interpolate (unsigned char* src_ptr ,\n\t\t\t\t\t\t \t\t\t\t\t\tunsigned char* dest_ptr ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tlines ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tsrc_width ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tdest_width);\n\nextern void __cdecl Asm_Interpolate_Line_Double (unsigned char* src_ptr ,\n\t\t\t\t\t\t \t\t\t\t\t\tunsigned char* dest_ptr ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tlines ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tsrc_width ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tdest_width);\n\nextern void __cdecl Asm_Interpolate_Line_Interpolate (unsigned char* src_ptr ,\n\t\t\t\t\t\t \t\t\t\t\t\tunsigned char* dest_ptr ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tlines ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tsrc_width ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tdest_width);\n\n}\n\n#define SIZE_OF_PALETTE\t256\nextern \"C\"{\n\tunsigned char PaletteInterpolationTable[SIZE_OF_PALETTE][SIZE_OF_PALETTE];\n\tunsigned char * InterpolationPalette;\n}\n\n\n\n/***********************************************************************************************\n * Read_Interpolation_Palette -- reads an interpolation palette table from disk               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    name of palette file                                                              *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    12/12/95 12:15PM ST : Created                                                            *\n *=============================================================================================*/\n\nvoid Read_Interpolation_Palette (char const * palette_file_name)\n{\n\tCCFileClass palette_file(palette_file_name);\n\n\tif (palette_file.Is_Available()) {\n\t\tpalette_file.Open(READ);\n\t\tpalette_file.Read(&PaletteInterpolationTable[0][0], 256*256);\n\t\tpalette_file.Close();\n\t\tInterpolationPaletteChanged = FALSE;\n\t}\n}\n\n\n/***********************************************************************************************\n * Write_Interpolation_Palette -- writes an interpolation palette table to disk               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    name of palette file                                                              *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    12/12/95 12:15PM ST : Created                                                            *\n *=============================================================================================*/\n\nvoid Write_Interpolation_Palette (char const * palette_file_name)\n{\n\tCCFileClass palette_file(palette_file_name);\n\n\tif (!palette_file.Is_Available()) {\n\t\tpalette_file.Open(WRITE);\n\t\tpalette_file.Write(&PaletteInterpolationTable[0][0], 256*256);\n\t\tpalette_file.Close();\n\t}\n}\n\n\n\n\n\n/***************************************************************************\n * CREATE_PALETTE_INTERPOLATION_TABLE                                      *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/06/1995  MG : Created.                                             *\n *=========================================================================*/\nvoid Create_Palette_Interpolation_Table( void )\n{\n\n//\tAsm_Create_Palette_Interpolation_Table();\n\n\t#if (1)\n\n\tint \t\t\t\ti;\n\tint \t\t\t\tj;\n\tint \t\t\t\tp;\n\tunsigned char\t* first_palette_ptr;\n\tunsigned char\t* second_palette_ptr;\n\tunsigned char\t* match_pal_ptr;\n\tint\t\t\t\tfirst_r;\n\tint\t\t\t\tfirst_g;\n\tint\t\t\t\tfirst_b;\n\tint\t\t\t\tsecond_r;\n\tint\t\t\t\tsecond_g;\n\tint\t\t\t\tsecond_b;\n\tint\t\t\t\tdiff_r;\n\tint\t\t\t\tdiff_g;\n\tint\t\t\t\tdiff_b;\n\tint\t\t\t\tdest_r;\n\tint\t\t\t\tdest_g;\n\tint\t\t\t\tdest_b;\n\tint \t\t\t\tdistance;\n\tint \t\t\t\tclosest_distance;\n\tint \t\t\t\tindex_of_closest_color;\n\n\t//\n\t// Create an interpolation table for the current palette.\n\t//\n\tfirst_palette_ptr = (unsigned char *) InterpolationPalette;\n\tfor ( i = 0; i < SIZE_OF_PALETTE; i ++ ) {\n\n\t\t//\n\t\t// Get the first palette entry's RGB.\n\t\t//\n\t\tfirst_r = *first_palette_ptr;\n\t\tfirst_palette_ptr ++;\n\t\tfirst_g = *first_palette_ptr;\n\t\tfirst_palette_ptr ++;\n\t\tfirst_b = *first_palette_ptr;\n\t\tfirst_palette_ptr ++;\n\n\t\tsecond_palette_ptr = (unsigned char *) InterpolationPalette;\n\t\tfor  ( j = 0; j < SIZE_OF_PALETTE; j ++ ) {\n\t\t\t//\n\t\t\t// Get the second palette entry's RGB.\n\t\t\t//\n\t\t\tsecond_r = *second_palette_ptr;\n\t\t\tsecond_palette_ptr ++;\n\t\t\tsecond_g = *second_palette_ptr;\n\t\t\tsecond_palette_ptr ++;\n\t\t\tsecond_b = *second_palette_ptr;\n\t\t\tsecond_palette_ptr ++;\n\n\t\t\t//\n\t\t\t// Now calculate the RGB halfway between the first and second colors.\n\t\t\t//\n\t\t\tdest_r = ( first_r + second_r ) >> 1;\n\t\t\tdest_g = ( first_g + second_g ) >> 1;\n\t\t\tdest_b = ( first_b + second_b ) >> 1;\n\n\t\t\t//\n\t\t\t// Now find the color in the palette that most closely matches the interpolated color.\n\t\t\t//\n\t\t\tindex_of_closest_color = 0;\n//\t\t\tclosest_distance = (256 * 256) * 3;\n\t\t\tclosest_distance = 500000;\n\t\t\tmatch_pal_ptr = (unsigned char *) InterpolationPalette;\n\t\t\tfor ( p = 0; p < SIZE_OF_PALETTE; p ++ ) {\n\t\t\t\tdiff_r = ( ((int) (*match_pal_ptr)) - dest_r );\n\t\t\t\tmatch_pal_ptr ++;\n\t\t\t\tdiff_g = ( ((int) (*match_pal_ptr)) - dest_g );\n\t\t\t\tmatch_pal_ptr ++;\n\t\t\t\tdiff_b = ( ((int) (*match_pal_ptr)) - dest_b );\n\t\t\t\tmatch_pal_ptr ++;\n\n\t\t\t\tdistance = ( diff_r * diff_r ) + ( diff_g * diff_g ) + ( diff_b * diff_b );\n\t\t\t\tif ( distance < closest_distance ) {\n\t\t\t\t\tclosest_distance = distance;\n\t\t\t\t\tindex_of_closest_color = p;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tPaletteInterpolationTable[ i ][ j ] = (unsigned char) index_of_closest_color;\n\t\t}\n\t}\n\n\t#endif\n\tInterpolationPaletteChanged = FALSE;\n\treturn;\n\n}\n\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Increase_Palette_Luminance -- increase contrast of colours in a palette                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to palette                                                                    *\n *           percentage increase of red                                                        *\n *           percentage increase of green                                                      *\n *           percentage increase of blue                                                       *\n *           cap value for colours                                                             *\n *                                                                                             *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    12/12/95 12:16PM ST : Created                                                            *\n *=============================================================================================*/\n\nvoid Increase_Palette_Luminance (unsigned char * palette , int red_percentage , int green_percentage , int blue_percentage , int cap)\n{\n\n\tunsigned\tint\tred;\n\tunsigned\tint\tgreen;\n\tunsigned\tint\tblue;\n\tfor (int i=0 ; i<SIZE_OF_PALETTE*3 ; i+=3) {\n\n\t\tred \t= (unsigned)*(palette+i);\n\t\tgreen = (unsigned)*(palette+i+1);\n\t\tblue\t= (unsigned)*(palette+i+2);\n\n\t\tred \t+= red*red_percentage/100;\n\t\tgreen\t+= green*green_percentage/100;\n\t\tblue\t+= blue*blue_percentage/100;\n\n\t\tred \t= MIN (cap, red);\n\t\tgreen\t= MIN (cap, green);\n\t\tblue\t= MIN (cap, blue);\n\n\t\t*(palette+i)\t=(unsigned char)red;\n\t\t*(palette+i+1)\t=(unsigned char)green;\n\t\t*(palette+i+2)\t=(unsigned char)blue;\n\n\t}\n\n}\n\n\n\n\n\n\n\n\n\n\n\n\nint\tCopyType\t=0;\n\n#ifdef WIN32\n/***************************************************************************\n * INTERPOLATE_2X_SCALE                                                    *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/06/1995  MG : Created.                                             *\n *=========================================================================*/\nvoid Interpolate_2X_Scale( GraphicBufferClass * source, GraphicViewPortClass * dest , char const * palette_file_name)\n{\n\tunsigned char\t* src_ptr;\n\tunsigned char\t* dest_ptr;\n\tunsigned char\t* last_dest_ptr;\n\tunsigned char\t* end_of_source;\n\tint\tsrc_width;\n\tint\tdest_width;\n//\tint\twidth_counter;\n\tBOOL\tsource_locked = FALSE;\n\tBOOL\tdest_locked = FALSE;\n\n\n\t/*\n\t**If a palette table exists on disk then read it in otherwise create it\n\t*/\n\tif (InterpolationPaletteChanged) {\n\t\tif (palette_file_name) {\n\t\t\tRead_Interpolation_Palette(palette_file_name);\n\t\t}\n\t\tif (InterpolationPaletteChanged) {\n\t\t\tCreate_Palette_Interpolation_Table();\n\t\t}\n\t}\n\n\t/*\n\t** Write the palette table to disk so we don't have to create it again next time\n\t*/\n\tif (palette_file_name) {\n\t\tWrite_Interpolation_Palette(palette_file_name);\n\t}\n\tif ( dest == &SeenBuff ) Hide_Mouse();\n\n\tWait_Blit();\n\n\t/*\n\t** Lock video surfaces if required\n\t*/\n\tif (source->Get_IsDirectDraw()) {\n\t\tif (!source->Lock()) {\n\t\t\tif (dest == &SeenBuff) Show_Mouse();\n\t\t\treturn;\n\t\t}\n\t\tsource_locked = TRUE;\n\t}\n\tif (dest->Get_IsDirectDraw()) {\n\t\tif (!dest->Lock()) {\n\t\t\tif (source_locked) {\n\t\t\t\tsource->Unlock();\n\t\t\t}\n\t\t\tif (dest == &SeenBuff) Show_Mouse();\n\t\t\treturn;\n\t\t}\n\t\tdest_locked = TRUE;\n\t}\n\n\n\t//\n\t// Get pointers to the source and destination buffers.\n\t//\n\tsrc_ptr = (unsigned char *) source->Get_Offset();\n\tdest_ptr = (unsigned char *) dest->Get_Offset();\n\tend_of_source = src_ptr + ( source->Get_Width() * source->Get_Height() );\n\n\t//\n\t// Get width of source and dest buffers.\n\t//\n\tsrc_width = source->Get_Width();\n\tdest_width = 2*(dest->Get_Width() + dest->Get_XAdd() + dest->Get_Pitch());\n\tlast_dest_ptr = dest_ptr;\n\n\t/*\n\t** Call the appropriate assembly language copy routine\n\t*/\n#if (1)\n\tswitch (CopyType) {\n\t\tcase 0:\n\t\t\tAsm_Interpolate ( src_ptr , dest_ptr , source->Get_Height() , src_width , dest_width);\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tAsm_Interpolate_Line_Double( src_ptr , dest_ptr , source->Get_Height() , src_width , dest_width);\n\t\t\tbreak;\n\n\t\tcase 2:\n\t\t\tAsm_Interpolate_Line_Interpolate( src_ptr , dest_ptr , source->Get_Height() , src_width , dest_width);\n\t\t\tbreak;\n\t}\n#endif\n\n#if (0)\n\t//\n\t// Copy over the first pixel (upper left).\n\t//\n\t*dest_ptr = *src_ptr;\n\tsrc_ptr ++;\n\tdest_ptr ++;\n\n\t//\n\t// Scale copy.\n\t//\n\twidth_counter = 0;\n\twhile ( src_ptr < end_of_source ) {\n\n\t\t//\n\t\t// Blend this pixel with the one to the left and place this new color in the dest buffer.\n\t\t//\n\t\t*dest_ptr = PaletteInterpolationTable[ (*src_ptr) ][ (*( src_ptr - 1 )) ];\n\t\tdest_ptr ++;\n\n\t\t//\n\t\t// Now place the source pixel into the dest buffer.\n\t\t//\n\t\t*dest_ptr = *src_ptr;\n\n\t\tsrc_ptr ++;\n\t\tdest_ptr ++;\n\n\t\twidth_counter ++;\n\t\tif ( width_counter == src_width ) {\n\t\t\twidth_counter = 0;\n\t\t\tlast_dest_ptr += dest_width;\n\t\t\tdest_ptr = last_dest_ptr;\n\t\t}\n\t}\n\n#endif\n\tif (source_locked) source->Unlock();\n\tif (dest_locked) dest->Unlock();\n\tif (dest == &SeenBuff) Show_Mouse();\n\n//BG\tlong *longptr = (long *)&PaletteInterpolationTable[0][0];\n//BG\tMono_Printf(\"Clock cycles: %08x\\n\",*longptr);\n}\n#endif\n\n\n\n\n\n"
  },
  {
    "path": "CODE/INTRO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/INTRO.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INTRO.H                                                      *\n *                                                                                             *\n *                   Programmer : Barry W. Green                                               *\n *                                                                                             *\n *                   Start Date : May 8, 1995                                                  *\n *                                                                                             *\n *                  Last Update : May 8, 1995  [BWG]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\nVQAHandle * Open_Movie(char * name);\nVQAHandle * Open_Movie(char * name)\n{\n\tif (!Debug_Quiet && Get_Digi_Handle() != -1) {\n\t\tAnimControl.OptionFlags |= VQAOPTF_AUDIO;\n\t} else {\n\t\tAnimControl.OptionFlags &= ~VQAOPTF_AUDIO;\n\t}\n\n\tVQAHandle * vqa = VQA_Alloc();\n\tif (vqa) {\n\t\tVQA_Init(vqa, MixFileHandler);\n\n\t\tif (VQA_Open(vqa, name, &AnimControl) != 0) {\n\t\t\tVQA_Free(vqa);\n\t\t\tvqa = 0;\n\t\t}\n\t}\n\treturn(vqa);\n}\n\n\n/***********************************************************************************************\n * Choose_Side -- play the introduction movies, select house                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   5/08/1995 BWG : Created.                                                                  *\n *=============================================================================================*/\nvoid Choose_Side(void)\t\t//\tajw - In RA, all this did was play a movie. Denzil is using it in its original sense.\n{\n\n\tWhom = HOUSE_GOOD;\n\n\tif (Special.IsFromInstall) {\n\t\t#ifdef DVD // Denzil\n\t\tif( Using_DVD() )\n\t\t{\n\t\t\tHide_Mouse();\n\t\t\tLoad_Title_Page();\n\t\t\tGamePalette = CCPalette;\n\t\t\tHidPage.Blit(SeenPage);\n\t\t\tCCPalette.Set();\n\t\t\tSet_Logic_Page(SeenBuff);\n\t\t\tShow_Mouse();\n\t\t\t\n\t\t\tswitch (WWMessageBox().Process(TXT_CHOOSE, TXT_ALLIES, TXT_SOVIET))\n\t\t\t\t{\n\t\t\t\tcase 0:\n\t\t\t\t\tCurrentCD = 0;\n\t\t\t\tbreak;\n\n\t\t\t\tcase 1:\n\t\t\t\t\tCurrentCD = 1;\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tHide_Mouse();\n\t\t\tBlackPalette.Set(FADE_PALETTE_SLOW);\n\t\t\tSeenPage.Clear();\n\t\t}\n\t\t#endif\n\t\t\n\t\tPlay_Movie(VQ_INTRO_MOVIE, THEME_NONE, false);\n\t}\n\n//\tScen.ScenPlayer = SCEN_PLAYER_GREECE;\n\n#ifdef OBSOLETE\n\tstatic char const _yellowpal[]={0x0,0x0,0xC9,0x0,0xBA,0x0,0x93,0x0,0x61,0x0,0x0,0x0,0x0,0x0,0xEE,0x0};\n\tstatic char const _redpal[]   ={0x0,0x0,0xA8,0x0,0xD9,0x0,0xDA,0x0,0xE1,0x0,0x0,0x0,0x0,0x0,0xD4,0x0};\n\tstatic char const _graypal[]  ={0x0,0x0,0x17,0x0,0x10,0x0,0x12,0x0,0x14,0x0,0x0,0x0,0x0,0x0,0x1C,0x0};\n\n\tvoid * anim;\n\tVQAHandle * gdibrief=0, * nodbrief=0;\n\tvoid const * staticaud, * oldfont;\n\tvoid const * speechg, * speechn, * speech;\n\tint statichandle, speechhandle, speechplaying = 0;\n\tint oldfontxspacing = FontXSpacing;\n\tint setpalette = 0;\n\n\tint frame = 0, endframe = 255, selection = 0, lettersdone = 0;\n\n\tHide_Mouse();\n/* Change to the six-point font for Text_Print */\n\toldfont = Set_Font(ScoreFontPtr);\n\n\tCall_Back();\n\n\tstaticaud = Load_Alloc_Data(CCFileClass(\"STRUGGLE.AUD\"));\n\tspeechg = Load_Alloc_Data(CCFileClass(\"GDI_SLCT.AUD\"));\n\tspeechn = Load_Alloc_Data(CCFileClass(\"NOD_SLCT.AUD\"));\n\n//\tstaticaud = MixFileClass::Retrieve(\"STRUGGLE.AUD\");\n//\tspeechg = MixFileClass::Retrieve(\"GDI_SLCT.AUD\");\n//\tspeechn = MixFileClass::Retrieve(\"NOD_SLCT.AUD\");\n\n\tanim = Open_Animation(\"CHOOSE.WSA\", NULL, 0L, (WSAOpenType)(WSA_OPEN_FROM_MEM | WSA_OPEN_TO_PAGE), Palette);\n\tCall_Back();\n\n\tnodbrief = Open_Movie(\"NOD1PRE.VQA\");\n\tCall_Back();\n\tgdibrief = Open_Movie(\"GDI1.VQA\");\n\n\tif (Special.IsFromInstall) {\n\t\tSet_Video_Mode(MCGA_MODE);\n\t\tPreserveVQAScreen = 1;\n//\t\tHide_Mouse();\n\t\tPlay_Movie(\"INTRO2\", THEME_NONE, false);\n\t\tShow_Mouse();\n\t}\n\n\tHidPage.Clear();\n\tif (!Special.IsFromInstall) {\n\t\tSeenPage.Clear();\n//\t\tSet_Palette(Palette);\n\t\tPalette.Set();\n\t} else {\n\t\tsetpalette = 1;\n\t}\n\n\tstatichandle = Play_Sample(staticaud, 255, 64);\n\tAlloc_Object(new ScorePrintClass(TXT_GDI_NAME,   0, 180, _yellowpal));\n#ifdef FRENCH\n\tAlloc_Object(new ScorePrintClass(TXT_GDI_NAME2,  0, 187, _yellowpal));\n#endif\n\tAlloc_Object(new ScorePrintClass(TXT_NOD_NAME, 180, 180, _redpal));\n\n#ifdef GERMAN\n\tAlloc_Object(new ScorePrintClass(TXT_SEL_TRANS, 57, 190, _graypal));\n#else\n#ifdef FRENCH\n\tAlloc_Object(new ScorePrintClass(TXT_SEL_TRANS, 103, 194, _graypal));\n#else\n\tAlloc_Object(new ScorePrintClass(TXT_SEL_TRANS, 103, 190, _graypal));\n#endif\n#endif\n\tKeyboard->Clear();\n\n\twhile (endframe != frame || (speechplaying && Is_Sample_Playing(speech)) ) {\n\t\tAnimate_Frame(anim, HidPage, frame++);\n\t\tHide_Mouse();\n\t\tif (setpalette) {\n\t\t\tWait_Vert_Blank(VertBlank);\n\t\t\t//Set_Palette(Palette);\n\t\t\tPalette.Set();\n\t\t\tsetpalette = 0;\n\t\t}\n\t\tHidPage.Blit(SeenPage, 0, 22, 0, 22, 320, 156);\n\t\tShow_Mouse();\n\n\t\tif (!Is_Sample_Playing(staticaud)) statichandle = Play_Sample(staticaud, 255, 64);\n\t\tCall_Back_Delay(3);\t// delay only if haven't clicked\n\n\t\t/* keep the mouse hidden until the letters are thru printing */\n\t\tif (!lettersdone) {\n\t\t\tlettersdone = true;\n\t\t\tfor (int i=0; i < MAXSCOREOBJS; i++) if (ScoreObjs[i]) lettersdone = 0;\n\t\t\tif (lettersdone) {\n\t\t\t\tShow_Mouse();\n\t\t\t}\n\t\t}\n\t\tif (frame >= Get_Animation_Frame_Count(anim)) frame = 0;\n\t\tif (Keyboard->Check() && endframe == 255) {\n\t\t\tif ((Keyboard->Get() & 0xFF) == KN_LMOUSE) {\n\t\t\t\tif ((MouseQY > 48) && (MouseQY < 150)) {\n\t\t\t\t\tif ((MouseQX > 18) && (MouseQX < 148)) {\n\n\t\t\t\t\t// Chose GDI\n\t\t\t\t\t\tWhom = HOUSE_GOOD;\n\t\t\t\t\t\tScenPlayer = SCEN_PLAYER_GDI;\n\t\t\t\t\t\tendframe = 0;\n\t\t\t\t\t\tspeechhandle = Play_Sample(speechg);\n\t\t\t\t\t\tspeechplaying = true;\n\t\t\t\t\t\tspeech = speechg;\n\t\t\t\t\t} else if ((MouseQX > 160) && (MouseQX < 300)) {\n\t\t\t\t\t// Chose Nod\n\t\t\t\t\t\tselection = 1;\n\t\t\t\t\t\tendframe = 14;\n\t\t\t\t\t\tWhom = HOUSE_BAD;\n\t\t\t\t\t\tScenPlayer = SCEN_PLAYER_NOD;\n\t\t\t\t\t\tspeechhandle = Play_Sample(speechn);\n\t\t\t\t\t\tspeechplaying = true;\n\t\t\t\t\t\tspeech = speechn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tHide_Mouse();\n\tClose_Animation(anim);\n\n\t// erase the \"choose side\" text\n\tSeenBuff.Fill_Rect(0, 180, 319, 199, 0);\n\n\tKeyboard->Clear();\n\n\t/* play the scenario 1 briefing movie */\n\tif (Whom == HOUSE_GOOD) {\n\t\tif (nodbrief) {\n\t\t\tVQA_Close(nodbrief);\n\t\t\tVQA_Free(nodbrief);\n\t\t}\n\t\tif (gdibrief) {\n#ifdef CHEAT_KEYS\n#else\n\t\t\tVQA_Play(gdibrief, VQAMODE_RUN);\n#endif\n\t\t\tVQA_Close(gdibrief);\n\t\t\tVQA_Free(gdibrief);\n\t\t}\n\t} else {\n\t\tif (gdibrief) {\n\t\t\tVQA_Close(gdibrief);\n\t\t\tVQA_Free(gdibrief);\n\t\t}\n\t\tif (nodbrief) {\n#ifdef CHEAT_KEYS\n#else\n\t\t\tVQA_Play(nodbrief, VQAMODE_RUN);\n#endif\n\t\t\tVQA_Close(nodbrief);\n\t\t\tVQA_Free(nodbrief);\n\t\t}\n\t}\n\n/* get rid of all the animating objects */\n\tfor (int i = 0; i < MAXSCOREOBJS; i++) if (ScoreObjs[i]) {\n\t\tdelete ScoreObjs[i];\n\t\tScoreObjs[i] = 0;\n\t}\n\n\tif (Whom == HOUSE_GOOD) {\n\t\t/*\n\t\t** Make sure the screen's fully clear after the movie plays\n\t\t*/\n\t\tSeenPage.Clear();\n\n\t\tBlackPalette.Adjust(WhitePalette, 0x08);\n\t\tBlackPalette.Set();\n\t\tBlackPalette.Adjust(0xFF);\n\t\tBlackPalette.Set();\n\n//\t\tmemset(BlackPalette, 0x01, 768);\n//\t\tSet_Palette(BlackPalette);\n//\t\tmemset(BlackPalette, 0x00, 768);\n\t} else {\n\t\tPreserveVQAScreen = 1;\n\t}\n\tFree(staticaud);\n\tFree(speechg);\n\tFree(speechn);\n\n\tSet_Font(oldfont);\n\tFontXSpacing = oldfontxspacing;\n#endif\n}\n"
  },
  {
    "path": "CODE/INTRO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/INTRO.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INTRO.H                                                      *\n *                                                                                             *\n *                   Programmer : Barry W. Green                                               *\n *                                                                                             *\n *                   Start Date : May 8, 1995                                                  *\n *                                                                                             *\n *                  Last Update : May 8, 1995  [BWG]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef INTRO_H\n#define INTRO_H\n\nvoid Choose_Side(void);\n\n#endif\n"
  },
  {
    "path": "CODE/IOMAP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/IOMAP.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : IOMAP.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Bill Randolph                                                *\n *                                                                                             *\n *                   Start Date : January 16, 1995                                             *\n *                                                                                             *\n *                  Last Update : March 12, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * All map-related loading/saving routines should go in this module, so it can be overlayed.   *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CellClass::Code_Pointers -- codes class's pointers for load/save                          *\n *   CellClass::Decode_Pointers -- decodes pointers for load/save                              *\n *   CellClass::Load -- Reads from a save game file.                                           *\n *   CellClass::Save -- Write to a save game file.                                             *\n *   CellClass::Should_Save -- Should the cell be written to disk?                             *\n *   DisplayClass::Code_Pointers -- codes class's pointers for load/save                       *\n *   DisplayClass::Decode_Pointers -- decodes pointers for load/save                           *\n *   MapClass::Code_Pointers -- codes class's pointers for load/save                           *\n *   MapClass::Decode_Pointers -- decodes pointers for load/save                               *\n *   MouseClass::Load -- Loads from a save game file.                                          *\n *   MouseClass::Save -- Saves to a save game file.                                            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/***********************************************************************************************\n * CellClass::Should_Save -- Should the cell be written to disk?                               *\n *                                                                                             *\n *    This function will determine if the cell needs to be written to disk. Any cell that      *\n *    contains special data should be written to disk.                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Should this cell's data be written to disk?                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Should_Save(void) const\n{\n\tstatic CellClass const _identity_cell;\n\n\treturn(memcmp(&_identity_cell, this, sizeof(*this)) != 0);\n}\n\n\n/***********************************************************************************************\n * CellClass::Load -- Loads from a save game file.                                             *\n *                                                                                             *\n * INPUT:   file  -- The file to read the cell's data from.                                    *\n *                                                                                             *\n * OUTPUT:  true = success, false = failure                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Load(Straw & file)\n{\n\tfile.Get(this, sizeof(*this));\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * CellClass::Save -- Write to a save game file.                                               *\n *                                                                                             *\n * INPUT:   file  -- The file to write the cell's data to.                                     *\n *                                                                                             *\n * OUTPUT:  true = success, false = failure                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Save(Pipe & file) const\n{\n\tfile.Put(this, sizeof(*this));\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * CellClass::Code_Pointers -- codes class's pointers for load/save                            *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid CellClass::Code_Pointers(void)\n{\n\tif (Cell_Occupier() != NULL) {\n\t\tOccupierPtr = (ObjectClass *)OccupierPtr->As_Target();\n\t}\n\n\tfor (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\tif (Overlapper[index] != NULL && Overlapper[index]->IsActive) {\n\t\t\tOverlapper[index] = (ObjectClass *)Overlapper[index]->As_Target();\n\t\t} else {\n\t\t\tOverlapper[index] = NULL;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Decode_Pointers -- decodes pointers for load/save                                *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *   03/12/1996 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid CellClass::Decode_Pointers(void)\n{\n\tif (OccupierPtr != NULL) {\n\t\tOccupierPtr = As_Object((TARGET)OccupierPtr);\n\t\tassert(OccupierPtr != NULL);\n\t}\n\n\tfor (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\tif (Overlapper[index] != NULL) {\n\t\t\tOverlapper[index] = As_Object((TARGET)Overlapper[index]);\n\t\t\tassert(Overlapper[index] != NULL);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MouseClass::Load -- Loads from a save game file.                                            *\n *                                                                                             *\n * Loading the map is very complicated.  Here are the steps:                                   *\n * - Read the Theater for this save-game                                                       *\n * - call Init_Theater to perform theater-specific inits                                       *\n * - call Free_Cells to free the cell array, because loading the map object will overwrite     *\n *   the pointer to the cell array                                                             *\n * - read the map object from disk                                                             *\n * - call Alloc_Cells to re-allocate the cell array                                            *\n * - call Init_Cells to set the cells to a known state, because not every cell will be loaded  *\n * - read the cell objects into the cell array                                                 *\n * - After the map & all objects have been loaded & the pointers decoded, Init_IO() >MUST< be  *\n *   called to restore the map's button list to the proper state.                              *\n *                                                                                             *\n * INPUT:   file  -- The file to read the cell's data from.                                    *\n *                                                                                             *\n * OUTPUT:  true = success, false = failure                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *   03/12/1996 JLB : Simplified.                                                              *\n *=============================================================================================*/\nbool MouseClass::Load(Straw & file)\n{\n\t/*\n\t**\tLoad Theater:  Even though this value is located in the DisplayClass,\n\t**\tit must be loaded first so initialization can be done before any other\n\t**\tmap data is loaded.  If initialization isn't done first, data read from\n\t**\tdisk will be over-written when initialization occurs.  This code must\n\t**\tgo in the most-derived Map class.\n\t*/\n\tTheaterType theater;\n\tif (file.Get(&theater, sizeof(theater)) != sizeof(theater)) {\n\t\treturn(false);\n\t}\n\n#ifdef WIN32\nLastTheater = THEATER_NONE;\n#endif\n\n\t/*\n\t** Remove any old theater specific uncompressed shapes\n\t*/\n#ifdef WIN32\n//\tif (theater != LastTheater) {\n\t\tReset_Theater_Shapes();\n//\t}\n#endif\t//WIN32\n\n\t/*\n\t**\tInit display mixfiles\n\t*/\n\tInit_Theater(theater);\n\tTerrainTypeClass::Init(Scen.Theater);\n\tTemplateTypeClass::Init(Scen.Theater);\n\tOverlayTypeClass::Init(Scen.Theater);\n\tUnitTypeClass::Init(Scen.Theater);\n\tInfantryTypeClass::Init(Scen.Theater);\n\tBuildingTypeClass::Init(Scen.Theater);\n\tBulletTypeClass::Init(Scen.Theater);\n\tAnimTypeClass::Init(Scen.Theater);\n\tAircraftTypeClass::Init(Scen.Theater);\n\tVesselTypeClass::Init(Scen.Theater);\n\tSmudgeTypeClass::Init(Scen.Theater);\n\n\t//LastTheater = Scen.Theater;\n\n\t/*\n\t** Free the cell array, because we're about to overwrite its pointers\n\t*/\n\tFree_Cells();\n\n\t/*\n\t** Read the entire map object in.  Only read in sizeof(MouseClass), so if we're\n\t** in editor mode, none of the map editor object is read in.\n\t*/\n\tfile.Get(this, sizeof(*this));\n#ifdef SCENARIO_EDITOR\n\tnew(this) MapEditClass(NoInitClass());\n#else\n\tnew(this) MouseClass(NoInitClass());\n#endif\n\n\t/*\n\t** Reallocate the cell array\n\t*/\n\tAlloc_Cells();\n\n\t/*\n\t** Init all cells to empty\n\t*/\n\tInit_Cells();\n\n\t/*\n\t**\tRead # cells saved\n\t*/\n\tint count;\n\tif (file.Get(&count, sizeof(count)) != sizeof(count)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tRead cells\n\t*/\n\tfor (int index = 0; index < count; index++) {\n\t\tCELL cell = 0;\n\t\tif (file.Get(&cell, sizeof(cell)) != sizeof(cell)) {\n\t\t\treturn(false);\n\t\t}\n\n\t\tif (!(*this)[cell].Load(file)) {\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\tLastTheater = Scen.Theater;\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * MouseClass::Save -- Save to a save game file.                                               *\n *                                                                                             *\n * INPUT:   file  -- The file to write the cell's data to.                                     *\n *                                                                                             *\n * OUTPUT:  true = success, false = failure                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *   02/26/1996 JLB : Cleaned up.                                                              *\n *=============================================================================================*/\nbool MouseClass::Save(Pipe & file) const\n{\n\t/*\n\t**\tSave Theater >first<\n\t*/\n\tTheaterType theater = Scen.Theater;\n\tfile.Put(&theater, sizeof(theater));\n\n\tfile.Put(this, sizeof(*this));\n\n\t/*\n\t**\tCount how many cells will be saved.\n\t*/\n\tint count = 0;\n\tCellClass const * cellptr = &(*this)[(CELL)0];\n\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tif (cellptr->Should_Save()) {\n\t\t\tcount++;\n\t\t}\n\t\tcellptr++;\n\t}\n\n\t/*\n\t**\twrite out count of the cells.\n\t*/\n\tfile.Put(&count, sizeof(count));\n\n\t/*\n\t**\tSave cells that need it\n\t*/\n\tcellptr = &(*this)[(CELL)0];\n\tfor (cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tif (cellptr->Should_Save()) {\n\t\t\tfile.Put(&cell, sizeof(cell));\n\t\t\tcellptr->Save(file);\n\t\t\tcount--;\n\t\t}\n\t\tcellptr++;\n\t}\n\n\tif (count != 0) return(false);\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Code_Pointers -- codes class's pointers for load/save                         *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid DisplayClass::Code_Pointers(void)\n{\n\t/*\n\t**\tCode PendingObjectPtr.\n\t*/\n\tif (PendingObjectPtr) {\n\t\tPendingObjectPtr = (ObjectClass *)PendingObjectPtr->As_Target();\n\t}\n\n\t/*\n\t**\tChain to parent.\n\t*/\n\tMapClass::Code_Pointers();\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Decode_Pointers -- decodes pointers for load/save                             *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid DisplayClass::Decode_Pointers(void)\n{\n\t/*\n\t**\tDecode PendingObjectPtr.  We can't decode PendingObject here, because we'd\n\t**\thave to reference PendingObjectPtr->Class_Of(), and the object that\n\t**\tPendingObjectPtr is pointing to hasn't been decoded yet.  Since we can't\n\t**\tdecode PendingObjectPtr, we can't set the placement cursor shape here\n\t**\teither.  These have to be done as last-minute fixups.\n\t*/\n\tif (PendingObjectPtr) {\n\t\tPendingObjectPtr = As_Object((TARGET)PendingObjectPtr);\n\t\tassert(PendingObjectPtr != NULL);\n\t}\n\n\t/*\n\t**\tChain to parent.\n\t*/\n\tMapClass::Decode_Pointers();\n}\n\n\n/***********************************************************************************************\n * MapClass::Code_Pointers -- codes class's pointers for load/save                             *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid MapClass::Code_Pointers(void)\n{\n\tCellClass * cellptr = &(*this)[(CELL)0];\n\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tcellptr->Code_Pointers();\n\t\tcellptr++;\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Decode_Pointers -- decodes pointers for load/save                                 *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid MapClass::Decode_Pointers(void)\n{\n\tCellClass * cellptr = &(*this)[(CELL)0];\n\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tcellptr->Decode_Pointers();\n\t\tcellptr++;\n\t}\n}\n\n\n"
  },
  {
    "path": "CODE/IOOBJ.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/IOOBJ.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : IOOBJ.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Bill Randolph                                                *\n *                                                                                             *\n *                   Start Date : January 16, 1995                                             *\n *                                                                                             *\n *                  Last Update : May 13, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BulletClass::Code_Pointers -- codes class's pointers for load/save                        *\n *   BulletClass::Decode_Pointers -- decodes pointers for load/save                            *\n *   CargoClass::Code_Pointers -- codes class's pointers for load/save                         *\n *   CargoClass::Decode_Pointers -- decodes pointers for load/save                             *\n *   FactoryClass::Code_Pointers -- codes class's pointers for load/save                       *\n *   FactoryClass::Decode_Pointers -- decodes pointers for load/save                           *\n *   FootClass::Code_Pointers -- codes class's pointers for load/save                          *\n *   FootClass::Decode_Pointers -- decodes pointers for load/save                              *\n *   HouseClass::Code_Pointers -- codes class's pointers for load/save                         *\n *   HouseClass::Decode_Pointers -- decodes pointers for load/save                             *\n *   LayerClass::Code_Pointers -- codes class's pointers for load/save                         *\n *   LayerClass::Decode_Pointers -- decodes pointers for load/save                             *\n *   LayerClass::Load -- Reads from a save game file.                                          *\n *   LayerClass::Save -- Write to a save game file.                                            *\n *   ObjectClass::Code_Pointers -- codes class's pointers for load/save                        *\n *   ObjectClass::Decode_Pointers -- decodes pointers for load/save                            *\n *   RadioClass::Code_Pointers -- codes class's pointers for load/save                         *\n *   RadioClass::Decode_Pointers -- decodes pointers for load/save                             *\n *   ReinforcementClass::Code_Pointers -- codes class's pointers for load/save                 *\n *   ReinforcementClass::Decode_Pointers -- decodes pointers for load/save                     *\n *   ScoreClass::Code_Pointers -- codes class's pointers for load/save                         *\n *   ScoreClass::Decode_Pointers -- decodes pointers for load/save                             *\n *   TeamClass::Code_Pointers -- codes class's pointers for load/save                          *\n *   TeamClass::Decode_Pointers -- decodes pointers for load/save                              *\n *   TeamTypeClass::Code_Pointers -- codes class's pointers for load/save                      *\n *   TeamTypeClass::Decode_Pointers -- decodes pointers for load/save                          *\n *   TechnoClass::Code_Pointers -- codes class's pointers for load/save                        *\n *   TechnoClass::Decode_Pointers -- decodes pointers for load/save                            *\n *   TriggerClass::Code_Pointers -- codes class's pointers for load/save                       *\n *   TriggerClass::Decode_Pointers -- decodes pointers for load/save                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/***********************************************************************************************\n * TeamTypeClass::Code_Pointers -- codes class's pointers for load/save                        *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid TeamTypeClass::Code_Pointers(void)\n{\n\t/*\n\t**\tCode the Class array\n\t*/\n\tfor (int i = 0; i < ClassCount; i++) {\n\t\tMembers[i].Class = (TechnoTypeClass *)Members[i].Class->As_Target();\n\t\tassert(Members[i].Class != NULL);\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamTypeClass::Decode_Pointers -- decodes pointers for load/save                            *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid TeamTypeClass::Decode_Pointers(void)\n{\n\t/*\n\t**\tDecode the Class array\n\t*/\n\tfor (int i = 0; i < ClassCount; i++) {\n\t\tMembers[i].Class =  As_TechnoType((TARGET)Members[i].Class);\n\t\tassert(Members[i].Class != NULL);\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamClass::Code_Pointers -- codes class's pointers for load/save                            *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *   05/13/1996 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid TeamClass::Code_Pointers(void)\n{\n\t/*\n\t**\tCode the 'Member'\n\t*/\n\tif (Member) {\n\t\tMember = (FootClass *)Member->As_Target();\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamClass::Decode_Pointers -- decodes pointers for load/save                                *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *   03/12/1996 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid TeamClass::Decode_Pointers(void)\n{\n\t/*\n\t**\tDecode the 'Member'\n\t*/\n\tif (Member) {\n\t\tMember = (FootClass *)As_Techno((TARGET)Member);\n\t\tassert(Member != NULL);\n\t}\n}\n\n\n/***********************************************************************************************\n * TriggerClass::Code_Pointers -- codes class's pointers for load/save                         *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid TriggerTypeClass::Code_Pointers(void)\n{\n\tAction1.Code_Pointers();\n\tAction2.Code_Pointers();\n}\n\n\n/***********************************************************************************************\n * TriggerClass::Decode_Pointers -- decodes pointers for load/save                             *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid TriggerTypeClass::Decode_Pointers(void)\n{\n\tAction1.Decode_Pointers();\n\tAction2.Decode_Pointers();\n}\n\n\n/***********************************************************************************************\n * BulletClass::Code_Pointers -- codes class's pointers for load/save                          *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid BulletClass::Code_Pointers(void)\n{\n\t/*\n\t**\tCode 'Payback'\n\t*/\n\tif (Payback) {\n\t\tPayback = (TechnoClass *)Payback->As_Target();\n\t}\n\n\t/*\n\t**\tChain to parent\n\t*/\n\tObjectClass::Code_Pointers();\n}\n\n\n/***********************************************************************************************\n * BulletClass::Decode_Pointers -- decodes pointers for load/save                              *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid BulletClass::Decode_Pointers(void)\n{\n\t/*\n\t**\tDecode 'Payback'\n\t*/\n\tif (Payback) {\n\t\tPayback = As_Techno((TARGET)Payback);\n\t\tassert(Payback != NULL);\n\t}\n\n\t/*\n\t**\tChain to parent\n\t*/\n\tObjectClass::Decode_Pointers();\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Code_Pointers -- codes class's pointers for load/save                         *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid FactoryClass::Code_Pointers(void)\n{\n\tif (Object) {\n\t\tObject = (TechnoClass *)Object->As_Target();\n\t}\n\n\t((HouseClass *&)House) = (HouseClass *)House->Class->House;\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Decode_Pointers -- decodes pointers for load/save                             *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid FactoryClass::Decode_Pointers(void)\n{\n\tif (Object) {\n\t\tObject = As_Techno((TARGET)Object);\n\t\tassert(Object != NULL);\n\t}\n\n\t((HouseClass *&)House) = HouseClass::As_Pointer((HousesType)House);\n\tassert(House != NULL);\n}\n\n\n/***********************************************************************************************\n * LayerClass::Load -- Loads from a save game file.                                            *\n *                                                                                             *\n * INPUT:   file  -- The file to read the cell's data from.                                    *\n *                                                                                             *\n * OUTPUT:  true = success, false = failure                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool LayerClass::Load(Straw & file)\n{\n\t/*\n\t**\tRead # elements in the layer\n\t*/\n\tint count;\n\tif (file.Get(&count, sizeof(count)) != sizeof(count)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tClear the array\n\t*/\n\tClear();\n\n\t/*\n\t**\tRead in all array elements\n\t*/\n\tfor (int index = 0; index < count; index++) {\n\t\tObjectClass * ptr;\n\t\tif (file.Get(&ptr, sizeof(ObjectClass *)) != sizeof(ObjectClass *)) {\n\t\t\treturn(false);\n\t\t}\n\t\tAdd(ptr);\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * LayerClass::Save -- Write to a save game file.                                              *\n *                                                                                             *\n * INPUT:   file  -- The file to write the cell's data to.                                     *\n *                                                                                             *\n * OUTPUT:  true = success, false = failure                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool LayerClass::Save(Pipe & file) const\n{\n\t/*\n\t**\tSave # array elements\n\t*/\n\tint count = Count();\n\tfile.Put(&count, sizeof(count));\n\n\t/*\n\t**\tSave all elements\n\t*/\n\tfor (int index = 0; index < count; index++) {\n\t\tObjectClass * ptr = (*this)[index];\n\t\tfile.Put(&ptr, sizeof(ObjectClass *));\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * LayerClass::Code_Pointers -- codes class's pointers for load/save                           *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid LayerClass::Code_Pointers(void)\n{\n\tfor (int index = 0; index < Count(); index++) {\n\t\tObjectClass * obj = (*this)[index];\n\t\tassert(obj != NULL);\n\t\t(*this)[index] = (ObjectClass *)(obj->As_Target());\n\t}\n}\n\n\n/***********************************************************************************************\n * LayerClass::Decode_Pointers -- decodes pointers for load/save                               *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid LayerClass::Decode_Pointers(void)\n{\n\tfor (int index = 0; index < Count(); index++) {\n\t\tTARGET target = (TARGET)(*this)[index];\n\t\t(*this)[index] = (ObjectClass *)As_Object(target);\n\t\tassert((*this)[index] != NULL);\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Code_Pointers -- codes class's pointers for load/save                           *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid HouseClass::Code_Pointers(void)\n{\n}\n\n\n/***********************************************************************************************\n * HouseClass::Decode_Pointers -- decodes pointers for load/save                               *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid HouseClass::Decode_Pointers(void)\n{\n\t/*\n\t** Re-assign the house's remap table (for multiplayer game loads)\n\t** Loading the house from disk will have over-written the house's RemapTable, so\n\t** Init_Data() is called to reset it to a valid pointer.\n\t*/\n\tInit_Data(RemapColor, ActLike, Credits);\n}\n\n\n/***********************************************************************************************\n * ScoreClass::Code_Pointers -- codes class's pointers for load/save                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid ScoreClass::Code_Pointers(void)\n{\n\tRealTime.Stop();\n}\n\n\n/***********************************************************************************************\n * ScoreClass::Decode_Pointers -- decodes pointers for load/save                               *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid ScoreClass::Decode_Pointers(void)\n{\n\tRealTime.Start();\n}\n\n\n/***********************************************************************************************\n * FootClass::Code_Pointers -- codes class's pointers for load/save                            *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid FootClass::Code_Pointers(void)\n{\n\tif (Member != NULL && Member->IsActive) {\n\t\tMember = (FootClass *)Member->As_Target();\n\t} else {\n\t\tMember = TARGET_NONE;\n\t}\n\n\tTechnoClass::Code_Pointers();\n}\n\n\n/***********************************************************************************************\n * FootClass::Decode_Pointers -- decodes pointers for load/save                                *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid FootClass::Decode_Pointers(void)\n{\n\tif ((TARGET)Member != TARGET_NONE) {\n\t\tMember = (FootClass *)As_Techno((TARGET)Member);\n\t\tassert(Member != NULL);\n\t}\n\n\tTechnoClass::Decode_Pointers();\n}\n\n\n/***********************************************************************************************\n * RadioClass::Code_Pointers -- codes class's pointers for load/save                           *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid RadioClass::Code_Pointers(void)\n{\n\t/*\n\t**\tCode 'Radio'\n\t*/\n\tif (Radio) {\n\t\tRadio = (RadioClass *)Radio->As_Target();\n\t}\n\n\tMissionClass::Code_Pointers();\n}\n\n\n/***********************************************************************************************\n * RadioClass::Decode_Pointers -- decodes pointers for load/save                               *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid RadioClass::Decode_Pointers(void)\n{\n\t/*\n\t**\tDecode 'Radio'\n\t*/\n\tif (Radio) {\n\t\tRadio = As_Techno((TARGET)Radio);\n\t\tassert(Radio != NULL);\n\t}\n\n\tMissionClass::Decode_Pointers();\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Code_Pointers -- codes class's pointers for load/save                          *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid TechnoClass::Code_Pointers(void)\n{\n\tCargoClass::Code_Pointers();\n\tRadioClass::Code_Pointers();\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Decode_Pointers -- decodes pointers for load/save                              *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid TechnoClass::Decode_Pointers(void)\n{\n\tCargoClass::Decode_Pointers();\n\tRadioClass::Decode_Pointers();\n}\n\n\n/***********************************************************************************************\n * CargoClass::Code_Pointers -- codes class's pointers for load/save                           *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid CargoClass::Code_Pointers(void)\n{\n\t/*\n\t**\tCode 'CargoHold'\n\t*/\n\tif (CargoHold) {\n\t\tCargoHold = (FootClass *)CargoHold->As_Target();\n\t}\n}\n\n\n/***********************************************************************************************\n * CargoClass::Decode_Pointers -- decodes pointers for load/save                               *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid CargoClass::Decode_Pointers(void)\n{\n\t/*\n\t**\tDecode 'CargoHold'\n\t*/\n\tif (CargoHold) {\n\t\tCargoHold = (FootClass *)As_Techno((TARGET)CargoHold);\n\t\tassert(CargoHold != NULL);\n\t}\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Code_Pointers -- codes class's pointers for load/save                          *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid ObjectClass::Code_Pointers(void)\n{\n\tif (Next) {\n\t\tNext = (ObjectClass *)Next->As_Target();\n\t}\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Decode_Pointers -- decodes pointers for load/save                              *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid ObjectClass::Decode_Pointers(void)\n{\n\tif (Next) {\n\t\tNext = As_Object((TARGET)Next);\n\t\tassert(Next != NULL);\n\t}\n}\n\n"
  },
  {
    "path": "CODE/IPX.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/IPX.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPX.CPP                                  *\n *                                                                         *\n *                   Programmer : Barry Nance\t\t\t\t\t\t\t\t\t\t*\n * \t\t\t\t\t\t\t\t\t\t from Client/Server LAN Programming\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t Westwood-ized by Bill Randolph\t\t\t\t*\n *                                                                         *\n *                   Start Date : December 14, 1994                        *\n *                                                                         *\n *                  Last Update : December 15, 1994   [BR]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Pitfalls:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Never try to use a closed socket; always check the return code from\t*\n *   IPX_Open_Socket().\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Always give IPX an outstanding ECB for listening, before you send.\t\t*\n * - It turns out that IPX is pretty bad about saving registers, so if\t\t*\n *   you have any register variables in your program, they may get\t\t\t*\n *   trashed.  To circumvent this, all functions in this module save &\t\t*\n *   restore the registers before invoking any IPX or NETX function.\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   IPX_SPX_Installed -- checks for installation of IPX/SPX               *\n *   IPX_Open_Socket -- opens an IPX socket for sending or receiving       *\n *   IPX_Close_Socket -- closes an open socket                             *\n *   IPX_Get_Connection_Number -- gets local Connection Number\t\t\t\t\t*\n *   IPX_Get_1st_Connection_Num -- gets 1st Connect Number for given user  *\n *   IPX_Get_Internet_Address -- gets Network Number & Node Address\t\t\t*\n *   IPX_Get_User_ID -- gets user ID from Connection Number                *\n *   IPX_Listen_For_Packet -- commands IPX to listen for a packet          *\n *   IPX_Send_Packet -- commands IPX to send a packet                      *\n *   IPX_Get_Local_Target -- fills in ImmediateAddress field of ECB        *\n *   IPX_Cancel_Event -- cancels an operation in progress                  *\n *   Let_IPX_Breath -- gives IPX some CPU time                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include <stdio.h>\n#include <mem.h>\n#include <i86.h>\n#include \"ipx.h\"\n\n#ifdef WIN32\n#include \"ipx95.h\"\n#endif\t//WIN32\n\n\n// Turn off \"expression is not meaningful\".\n#pragma warning 628 9\n\n\n/***************************************************************************\n * IPX_SPX_Installed -- checks for installation of IPX/SPX                 *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = not installed; 1 = IPX only, 2 = IPX and SPX are installed\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/14/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPX_SPX_Installed(void)\n{\n#ifdef WIN32\n\n#ifdef TIBERIAN_SUN\n\treturn(false);\n#else\n\tif ( Load_IPX_Dll () ){\n\t\treturn ( IPX_Initialise() );\n\t}else{\n\t\treturn(false);\n\t}\n#endif\n\n#else\t//WIN32\n\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tRMIType rmi;\n\n\t//------------------------------------------------------------------------\n\t//\tInit all registers to 0's\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0, sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0, sizeof(rmi));\n\n\t//------------------------------------------------------------------------\n\t//\tFill in registers for the DPMI call, function 0x300\n\t//------------------------------------------------------------------------\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = 0x002f;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//------------------------------------------------------------------------\n\t//\tFill in registers for the real-mode interrupt handler.\n\t//\tTo test for the presence of IPX, set AH to 0x7a, AL to 0, and invoke\n\t//\tinterrupt 0x2f (the \"multiplex\" interrupt).  If IPX is installed,\n\t//\tAL will be 0xff, and ES:DI will contain the IPX/SPX function address.\n\t//------------------------------------------------------------------------\n\trmi.eax = 0x00007a00;\n\n\t//------------------------------------------------------------------------\n\t//\tcall DPMI\n\t//------------------------------------------------------------------------\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\t//------------------------------------------------------------------------\n\t//\tIf IPX isn't there, return 0\n\t//------------------------------------------------------------------------\n\tif ( (rmi.eax & 0x00ff) != 0xff) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tTest for SPX by invoking the IPX_SPX function with BX = 0x10, and AL = 0.\n\t//\tIf SPX is present, AL will be 0xff.\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = IPX_INT;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.ebx = 0x00000010;\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\t//------------------------------------------------------------------------\n\t//\tSPX is installed; return '2'\n\t//------------------------------------------------------------------------\n\tif ( (rmi.eax & 0x00ff) == 0xff) {\n\t\treturn(2);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSPX is not installed; return '1'\n\t//------------------------------------------------------------------------\n\treturn(1);\n#endif\t//WIN32\n\n}\t/* end of IPX_SPX_Installed */\n\n\n/***************************************************************************\n * IPX_Open_Socket -- opens an IPX socket for sending or receiving         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsocket\t\tthe socket number to open\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = OK\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t-1 = IPX not installed\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t0xfe = socket table is full\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t0xff = socket is already open\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tThe application must define its socket number carefully.  Use\t\t\t*\n *\t\tvalues from 0x4000 to 0x8000 for custom socket numbers.  The app\t\t*\n *\t\tmust know its own socket number as well as the socket number of\t\t*\n *\t\ta destination workstation.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\n\nint IPX_Open_Socket(unsigned short socket)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tRMIType rmi;\n\tint rc;\n\n\t//------------------------------------------------------------------------\n\t//\tOpen the socket:\n\t//\tDX = socket number\n\t//\tAL = 0 for short-lived socket, 0xff for long-lived socket\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = IPX_INT;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG (&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF (&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.ebx = IPX_OPEN_SOCKET;\t\t\t// function code\n\trmi.edx = socket;\t\t\t\t\t\t// desired socket #\n\trmi.eax = 0x00ff;\t\t\t\t\t\t// make this a long-lived socket\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\n\n\trc = (rmi.eax & 0xff);\n\n\treturn(rc);\n\n}\t/* end of IPX_Open_Socket */\n#endif\t//WIN32\n\n/***************************************************************************\n * IPX_Close_Socket -- closes an open socket                               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsocket\t\tsocket number to close\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = ok, -1 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\n\nint IPX_Close_Socket(unsigned short socket)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tRMIType rmi;\n\n\t//------------------------------------------------------------------------\n\t//\tClose the socket:\n\t//\tDX = socket number\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = IPX_INT;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.ebx = IPX_CLOSE_SOCKET;\n\trmi.edx = socket;\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\treturn(0);\n\n}\t/* end of IPX_Close_Socket */\n#endif\t\t//WIN32\n\n\n/***************************************************************************\n * IPX_Get_Connection_Number -- gets local Connection Number\t\t\t\t\t*\n *                                                                         *\n * This Novell call will the return the user's local \"Connection Number\".\t*\n * This value will be 0 if the user isn't logged into Novell, so this\t\t*\n * routine can be used to detect if other calls (such as Get_Local_Target)\t*\n * will be OK.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tConnection Number, 0 = none\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nint IPX_Get_Connection_Number(void)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tRMIType rmi;\n\tint num;\n\n\t//------------------------------------------------------------------------\n\t//\tCall Interrupt 0x21, with AH = 0xdc.  This tells Novell to put the local\n\t//\tconnection number into AL.\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = 0x21;\t\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.eax = 0x0000dc00;\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\tnum = rmi.eax & 0x00ff;\n\n\treturn(num);\n\n}\t/* end of IPX_Get_Connection_Number */\n#endif\t//WIN32\n\n\n/***************************************************************************\n * IPX_Get_1st_Connection_Num -- gets 1st Connect Number for given user    *\n *                                                                         *\n * This gets the Connection Number for the given User ID.  Since a user\t\t*\n * may be logged in more than once, this just returns the first connection\t*\n * found and ignores the others.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tusername\t\tname of the user to get the Connection Number for\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tfirst-found Connection Number for that user, 0 if user not logged in\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nint IPX_Get_1st_Connection_Num (char * username)\n{\n\tstruct request_buffer {\n\t\tunsigned short len;\t\t\t\t\t\t\t// username length + 5\n\t\tunsigned char buffer_type;\t\t\t\t\t// ConnectionNum = 0x15\n\t\tunsigned short object_type;\t\t\t\t// set ot 0x0100\n\t\tunsigned char name_len;\t\t\t\t\t\t// length of username\n\t\tchar name [48];\t\t\t\t\t\t\t\t// copy of username\n\t\tunsigned short reserved;\n\t};\n\tstruct reply_buffer {\n\t\tunsigned short  len;\n\t\tunsigned char   number_connections;\t\t// will be 0 - 100\n\t\tunsigned char   connection_num [100];\t// array of connection numbers\n\t\tunsigned short  reserved[2];\n\t};\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tRMIType rmi;\n\tstruct request_buffer * reqbuf;\n\tstruct reply_buffer * replybuf;\n\tunsigned short segment;\t\t\t\t\t\t\t// for DOS allocation\n\tunsigned short selector;\t\t\t\t\t\t// for DOS allocation\n\tint num_conns;\t\t\t\t\t\t\t\t\t\t// # connections returned\n\tint conn_num;\t\t\t\t\t\t\t\t\t\t// connection number\n\tint rc;\n\n\t//------------------------------------------------------------------------\n\t//\tAllocate DOS memory to store the buffers passed to the interrupt\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_ALLOC_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = (sizeof(struct request_buffer) + \t// # paragraphs to allocate\n\t\tsizeof(struct reply_buffer) + 15) >> 4;\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\t//------------------------------------------------------------------------\n\t//\tIf the carry flag is set, DPMI is indicating an error.\n\t//------------------------------------------------------------------------\n\tif (regs.x.cflag) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tGet pointers to allocated memory.\n\t//\t'reqbuf' is just the returned real-mode segment, multiplied by 16.\n\t//\t'replybuf' is an offset from 'reqbuf'.\n\t//------------------------------------------------------------------------\n\tsegment = regs.w.ax;\n\tselector = regs.w.dx;\n\treqbuf = (struct request_buffer *)(segment << 4);\n\treplybuf = (struct reply_buffer *)\n\t\t(((char *)reqbuf) + sizeof (struct request_buffer));\n\n\t//------------------------------------------------------------------------\n\t//\tInit the contents of the request & reply buffers\n\t//------------------------------------------------------------------------\n\treqbuf->len = (unsigned short)(strlen(username) + 5);\n\treqbuf->buffer_type = 0x15;\n\treqbuf->object_type = 0x0100;\n\treqbuf->name_len    = (unsigned char) strlen(username);\n\tstrcpy(reqbuf->name, username);\n\treqbuf->reserved = reqbuf->reserved;\t\t\t\t// prevent compiler warning\n\treplybuf->len = 101;\n\treplybuf->reserved[0] = replybuf->reserved[0];\t// prevent compiler warning\n\treplybuf->reserved[0] = replybuf->reserved[1];\t// prevent compiler warning\n\n\t//------------------------------------------------------------------------\n\t//\tInvoke Int 21 with AH=0xe3, DS:SI=&request_buffer, ES:DI=&reply_buffer\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = 0x21;\t\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.eax = 0x0000e300;\n\trmi.ds = segment;\n\trmi.esi = 0;\n\trmi.es = segment;\n\trmi.edi = sizeof(struct request_buffer);\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\t//------------------------------------------------------------------------\n\t//\tStash the 1st connection number\n\t//------------------------------------------------------------------------\n\trc = (rmi.eax & 0x00ff);\t\t\t\t\t\t\t\t// if AL !=0, error\n\tnum_conns = replybuf->number_connections;\t\t\t// # times user is logged in\n\tconn_num = (int )replybuf->connection_num[0];\t// 1st connection #\n\n\t//------------------------------------------------------------------------\n\t//\tFree DOS memory\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_FREE_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.edx = selector;\t\t\t\t\t\t\t\t\t// ptr to free\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\t//------------------------------------------------------------------------\n\t//\tReturn error if function failed, or user not logged in\n\t//------------------------------------------------------------------------\n\tif (rc != 0 || num_conns==0) {\n\t\treturn(0);\n\t}\n\telse {\n\t\treturn(conn_num);\n\t}\n\n}\t/* end of IPX_Get_1st_Connection_Num */\n\n#endif\t//WIN32\n\n/***************************************************************************\n * IPX_Get_Internet_Address -- gets Network Number & Node Address\t\t\t\t*\n *                                                                         *\n * Once you've obtained a Connection Number from IPX_Get_Connection_Number\t*\n * or IPX_Get_1st_Connection_Num, use this function to translate it into\t*\n * a Network Number and Node Address; then, place those numbers in the\t\t*\n * IPX header for outgoing packets.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tconnection_number\t\tConnection Number to translate\t\t\t\t\t\t*\n *\t\tnetwork_number\t\t\tptr: will hold Network Number\t\t\t\t\t\t\t*\n *\t\tphysical_node\t\t\tptr: will hold Node Address\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = OK, -1 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tIf connection_number is 0 and NETX isn't running, this routine\t\t\t*\n *\t\twill just put garbage into the network_number and physical_node.\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nint IPX_Get_Internet_Address(int connection_number,\n\tunsigned char * network_number, unsigned char * physical_node)\n{\n\tstruct request_buffer {\n\t\tunsigned short  len;\n\t\tunsigned char   buffer_type;\t\t\t\t// Internet = 0x13\n\t\tunsigned char   connection_number;\t\t// Conn. Number to translate\n\t};\n\tstruct reply_buffer {\n\t\tunsigned short  len;\n\t\tunsigned char   network_number [4];\t\t// filled in by IPX\n\t\tunsigned char   physical_node  [6];\t\t// filled in by IPX\n\t\tunsigned short  server_socket;\t\t\t// filled in by IPX, but don't use!\n\t};\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tRMIType rmi;\n\tstruct request_buffer * reqbuf;\n\tstruct reply_buffer * replybuf;\n\tunsigned short segment;\t\t\t\t\t\t\t// for DOS allocation\n\tunsigned short selector;\t\t\t\t\t\t// for DOS allocation\n\n\t//------------------------------------------------------------------------\n\t//\tError if invalid connection is given\n\t//------------------------------------------------------------------------\n\tif (connection_number==0) {\n\t\treturn(-1);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tAllocate DOS memory to store the buffers passed to the interrupt\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_ALLOC_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = (sizeof(struct request_buffer) + \t// # paragraphs to allocate\n\t\tsizeof(struct reply_buffer) + 15) >> 4;\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\t//------------------------------------------------------------------------\n\t//\tIf the carry flag is set, DPMI is indicating an error.\n\t//------------------------------------------------------------------------\n\tif (regs.x.cflag) {\n\t\treturn(-1);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tGet pointers to allocated memory.\n\t//\t'reqbuf' is just the returned real-mode segment, multiplied by 16.\n\t//\t'replybuf' is an offset from 'reqbuf'.\n\t//------------------------------------------------------------------------\n\tsegment = regs.w.ax;\n\tselector = regs.w.dx;\n\treqbuf = (struct request_buffer *)(segment << 4);\n\treplybuf = (struct reply_buffer *)\n\t\t(((char *)reqbuf) + sizeof (struct request_buffer));\n\n\t//------------------------------------------------------------------------\n\t//\tInit the contents of the request & reply buffers\n\t//------------------------------------------------------------------------\n\treqbuf->len = 2;\n\treqbuf->buffer_type = 0x13;\n\treqbuf->connection_number = (unsigned char)connection_number;\n\treplybuf->len = 12;\n\treplybuf->network_number[0] = replybuf->network_number[0];\t// suppress warning\n\treplybuf->physical_node[0] = replybuf->physical_node[0];\t\t// suppress warning\n\treplybuf->server_socket = replybuf->server_socket;\t\t\t\t// suppress warning\n\n\t//------------------------------------------------------------------------\n\t//\tInvoke Int 21 with AH=0xe3, DS:SI=&request_buffer, ES:DI=&reply_buffer\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = 0x21;\t\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.eax = 0x0000e300;\n\trmi.ds = segment;\n\trmi.esi = 0;\n\trmi.es = segment;\n\trmi.edi = sizeof(struct request_buffer);\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\tmemcpy(network_number, replybuf->network_number, 4);\n\tmemcpy(physical_node,  replybuf->physical_node,  6);\n\n\t//------------------------------------------------------------------------\n\t//\tFree DOS memory\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_FREE_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.edx = selector;\t\t\t\t\t\t\t\t\t// ptr to free\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\treturn(0);\n\n}\t/* end of IPX_Get_Internet_Address */\n#endif\t//WIN32\n\n/***************************************************************************\n * IPX_Get_User_ID -- gets user ID from Connection Number                  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tconnection_number\t\tConnection Number to get User ID for\t\t\t\t*\n *\t\tuser_id\t\t\t\t\tptr to buffer to put User ID into; \t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\tsize must be >= 48 chars\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = OK, -1 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nint IPX_Get_User_ID(int connection_number, char * user_id)\n{\n\tstruct request_buffer {\n\t\tunsigned short  len;\n\t\tunsigned char   buffer_type;\t\t\t// 0x16 = UserID buffer type\n\t\tunsigned char   connection_number;\t// Connection Number to get ID for\n\t};\n\tstruct reply_buffer {\n\t\tunsigned short  len;\n\t\tunsigned char   object_id[4];\n\t\tunsigned char   object_type[2];\n\t\tchar            object_name[48];\n\t\tchar            login_time[7];\n\t\tunsigned short  reserved;\n\t};\n\tunion REGS      regs;\n\tstruct SREGS    sregs;\n\tRMIType rmi;\n\tstruct request_buffer * reqbuf;\n\tstruct reply_buffer * replybuf;\n\tunsigned short segment;\t\t\t\t\t\t\t// for DOS allocation\n\tunsigned short selector;\t\t\t\t\t\t// for DOS allocation\n\n\t//------------------------------------------------------------------------\n\t//\tError if invalid connection is given\n\t//------------------------------------------------------------------------\n\tif (connection_number==0) {\n\t\treturn(-1);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tAllocate DOS memory to store the buffers passed to the interrupt\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_ALLOC_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = (sizeof(struct request_buffer) + \t// # paragraphs to allocate\n\t\tsizeof(struct reply_buffer) + 15) >> 4;\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\t//------------------------------------------------------------------------\n\t//\tIf the carry flag is set, DPMI is indicating an error.\n\t//------------------------------------------------------------------------\n\tif (regs.x.cflag) {\n\t\treturn(-1);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tGet pointers to allocated memory.\n\t//\t'reqbuf' is just the returned real-mode segment, multiplied by 16.\n\t//\t'replybuf' is an offset from 'reqbuf'.\n\t//------------------------------------------------------------------------\n\tsegment = regs.w.ax;\n\tselector = regs.w.dx;\n\treqbuf = (struct request_buffer *)(segment << 4);\n\treplybuf = (struct reply_buffer *)\n\t\t(((char *)reqbuf) + sizeof (struct request_buffer));\n\n\t//------------------------------------------------------------------------\n\t//\tInit the contents of the request & reply buffers\n\t//------------------------------------------------------------------------\n\treqbuf->len = 2;\n\treqbuf->buffer_type = 0x16;\n\treqbuf->connection_number = (unsigned char)connection_number;\n\treplybuf->len = sizeof(struct reply_buffer) - 2;\n\treplybuf->object_id[0] = replybuf->object_id[0];\t\t// suppress warnings\n\treplybuf->object_type[0] = replybuf->object_type[0];\t// suppress warnings\n\treplybuf->login_time[0] = replybuf->login_time[0];\t\t// suppress warnings\n\treplybuf->reserved = replybuf->reserved;\t\t\t\t\t// suppress warnings\n\n\t//------------------------------------------------------------------------\n\t//\tInvoke Int 21 with AH=0xe3, DS:SI=&request_buffer, ES:DI=&reply_buffer\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = 0x21;\t\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.eax = 0x0000e300;\n\trmi.ds = segment;\n\trmi.esi = 0;\n\trmi.es = segment;\n\trmi.edi = sizeof(struct request_buffer);\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\t//------------------------------------------------------------------------\n\t//\tFill in the caller's buffer with the user name\n\t//------------------------------------------------------------------------\n\tstrncpy(user_id, replybuf->object_name, 48);\n\n\t//------------------------------------------------------------------------\n\t//\tFree DOS memory\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_FREE_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.edx = selector;\t\t\t\t\t\t\t\t\t// ptr to free\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\treturn(0);\n\n}\t/* end of IPX_Get_User_ID */\n#endif\t//WIN32\n\n/***************************************************************************\n * IPX_Listen_For_Packet -- commands IPX to listen for a packet            *\n *                                                                         *\n * Before calling this function, you must fill in an ECB:\t\t\t\t\t\t*\n *\t\tSocketNumber:\t\t\t\tmust contain the socket you've opened,\t\t\t*\n *\t\t\t\t\t\t\t\t\t\tand are \"listening\" on\t\t\t\t\t\t\t\t*\n *\t\tEvent_Service_Routine:\toptionally points to a callback routine\t\t*\n *\t\tPacketCount:\t\t\t\tset to 2, to tell IPX there are 2 areas to\t*\n *\t\t\t\t\t\t\t\t\t\tstore the incoming data in\t\t\t\t\t\t\t*\n *\t\tPacket[0].Address:\t\tset to the address of an IPXHeaderType\t\t\t*\n *\t\tPacket[0].Length:\t\t\tsizeof(IPXHeaderType)\t\t\t\t\t\t\t\t*\n *\t\tPacket[1].Address:\t\taddress of data buffer, for the packet\t\t\t*\n *\t\tPacket[1].Length:\t\t\tsize of the data buffer\t\t\t\t\t\t\t\t*\n *                                                                         *\n * When the packet is received, ECBType.CompletionCode will be 0 if \t\t\t*\n * successful.  Otherwise, some error occurred.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * You should initialize the ECB to 0's before filling it in.\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tecb_ptr\t\tpointer to a filled-in ECB; MUST be real-mode memory\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = OK, IPX error otherwise\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tThe ECB must be located in real-mode memory, as well as the values\t*\n *\t\tpointed to in the ECB (the IPX Header, the buffer to send, etc.)\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nint IPX_Listen_For_Packet(struct ECB *ecb_ptr)\n{\n\tunion REGS      regs;\n\tstruct SREGS    sregs;\n\tRMIType rmi;\n\n\t//------------------------------------------------------------------------\n\t//\tCall IPX with ES:SI=ecb_ptr\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = IPX_INT;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.ebx = IPX_LISTEN_FOR_PACKET;\n\trmi.es = (short)((long)ecb_ptr >> 4);\n\trmi.esi = (long)((long)ecb_ptr & 0x000f);\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\treturn(rmi.eax & 0x00ff);\n\n}\t/* end of IPX_Listen_For_Packet */\n#endif\t//WIN32\n\n/***************************************************************************\n * IPX_Send_Packet -- commands IPX to send a packet                        *\n *                                                                         *\n * Before calling this function, you must fill in an ECB:\t\t\t\t\t\t*\n *\t\tSocketNumber:\t\t\t\tmust contain the socket you've opened,\t\t\t*\n *\t\t\t\t\t\t\t\t\t\tand are sending on\t\t\t\t\t\t\t\t\t*\n *\t\tEvent_Service_Routine:\toptionally points to a callback routine\t\t*\n *\t\tPacketCount:\t\t\t\tset to 2, to tell IPX there are 2 areas the\t*\n *\t\t\t\t\t\t\t\t\t\toutgoing data is stored in\t\t\t\t\t\t\t*\n *\t\tPacket[0].Address:\t\tset to the address of an IPXHeaderType\t\t\t*\n *\t\tPacket[0].Length:\t\t\tsizeof(IPXHeaderType)\t\t\t\t\t\t\t\t*\n *\t\tPacket[1].Address:\t\taddress of buffer containing data to send\t\t*\n *\t\tPacket[1].Length:\t\t\tsize of the data buffer\t\t\t\t\t\t\t\t*\n *\t\tImmediateAddress:\t\t\tmust be filled in with the node address of\t*\n *\t\t\t\t\t\t\t\t\t\tthe bridge that will route the message;\t\t*\n *\t\t\t\t\t\t\t\t\t\tfill this in by calling IPX_Get_Local_Target\t*\n *                                                                         *\n * Also, you must fill in the IPXHeaderType with certain values:\t\t\t\t*\n *\t\tPacketType:\t\t\t\t\tset to 4 for IPX\t\t\t\t\t\t\t\t\t\t*\n *\t\tDestNetworkNumber:\t\tNetwork Number of the destination system\t\t*\n *\t\tDestNetworkNode:\t\t\tNode Address of the destination system\t\t\t*\n *\t\tDestNetworkSocket:\t\tthe destination system's socket to send to;\t*\n *\t\t\t\t\t\t\t\t\t\tthis doesn't have to be the same as the\t\t*\n *\t\t\t\t\t\t\t\t\t\tsocket opened on the local machine.\t\t\t\t*\n *                                                                         *\n * You should initialize the ECB & IPXHeader to 0's before filling them in.*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tecb_ptr\t\tpointer to a filled-in ECB\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.  This function doesn't return anything; the caller must check\t*\n *    its ECB.CompletionCode for: 0 = OK, IPX Error otherwise.\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tThe ECB must be located in real-mode memory, as well as the values\t*\n *\t\tpointed to in the ECB (the IPX Header, the buffer to send, etc.)\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nvoid IPX_Send_Packet(struct ECB *ecb_ptr)\n{\n\tunion REGS      regs;\n\tstruct SREGS    sregs;\n\tRMIType rmi;\n\n\t//------------------------------------------------------------------------\n\t//\tCall IPX with ES:SI=ecb_ptr\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = IPX_INT;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.ebx = IPX_SEND_PACKET;\n\trmi.es = (short)((long)ecb_ptr >> 4);\n\trmi.esi = (long)((long)ecb_ptr & 0x000f);\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n}\t/* end of IPX_Send_Packet */\n#endif\t//WIN32\n\n/***************************************************************************\n * IPX_Get_Local_Target -- fills in ImmediateAddress field of ECB          *\n *                                                                         *\n * Use this function to fill in the ECB's ImmediateAddress field when\t\t*\n * sending a packet.  The Immediate Address is the node address of the\t\t*\n * bridge that must route the message.  If there is no bridge, it's \t\t\t*\n * filled in with the destination Node Address.  In either case, it\t\t\t*\n * will contain the proper value for sending.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tdest_network\t\t\tdestination Network Number\t\t\t\t\t\t\t\t*\n *\t\tdest_node\t\t\t\tdestination Node Address\t\t\t\t\t\t\t\t*\n *\t\tdest_socket\t\t\t\tdestination Socket Number\t\t\t\t\t\t\t\t*\n *\t\tbridge_address\t\t\tfield to fill in with Immediate Address\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = OK, error otherwise\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tIf the Connection Number is 0 (user not logged in), dest_network\t\t*\n *\t\tand dest_node will be garbage, and this routine will probably crash.\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nint IPX_Get_Local_Target(unsigned char *dest_network, unsigned char *dest_node,\n\tunsigned short dest_socket, unsigned char *bridge_address)\n{\n\tstruct request_buffer {\n\t\tunsigned char   network_number [4];\n\t\tunsigned char   physical_node  [6];\n\t\tunsigned short  socket;\n\t};\n\tstruct reply_buffer {\n\t\tunsigned char   local_target [6];\n\t};\n\tunsigned int rc;\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tRMIType rmi;\n\tstruct request_buffer *reqbuf;\n\tstruct reply_buffer *replybuf;\n\tunsigned short segment;\t\t\t\t\t\t\t// for DOS allocation\n\tunsigned short selector;\t\t\t\t\t\t// for DOS allocation\n\n\t//------------------------------------------------------------------------\n\t//\tAllocate DOS memory to store the buffers passed to the interrupt\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_ALLOC_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = (sizeof(struct request_buffer) + \t// # paragraphs to allocate\n\t\tsizeof(struct reply_buffer) + 15) >> 4;\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\t//------------------------------------------------------------------------\n\t//\tIf the carry flag is set, DPMI is indicating an error.\n\t//------------------------------------------------------------------------\n\tif (regs.x.cflag) {\n\t\treturn(-1);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tGet pointers to allocated memory.\n\t//\t'reqbuf' is just the returned real-mode segment, multiplied by 16.\n\t//\t'replybuf' is an offset from 'reqbuf'.\n\t//------------------------------------------------------------------------\n\tsegment = regs.w.ax;\n\tselector = regs.w.dx;\n\treqbuf = (struct request_buffer *)(segment << 4);\n\treplybuf = (struct reply_buffer *)\n\t\t(((char *)reqbuf) + sizeof (struct request_buffer));\n\n\t//------------------------------------------------------------------------\n\t//\tInit the contents of the request & reply buffers\n\t//------------------------------------------------------------------------\n\tmemcpy(reqbuf->network_number, dest_network, 4);\n\tmemcpy(reqbuf->physical_node, dest_node, 6);\n\treqbuf->socket = dest_socket;\n\n\t//------------------------------------------------------------------------\n\t//\tInvoke IPX with DS:SI=&request_buffer, ES:DI=&reply_buffer\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = IPX_INT;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.ebx = IPX_GET_LOCAL_TARGET;\n\trmi.ds = segment;\n\trmi.esi = 0;\n\trmi.es = segment;\n\trmi.edi = sizeof(struct request_buffer);\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\trc = (rmi.eax & 0x00ff);\n\tmemcpy(bridge_address, replybuf->local_target, 6);\n\n\t//------------------------------------------------------------------------\n\t//\tFree DOS memory\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_FREE_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.edx = selector;\t\t\t\t\t\t\t\t\t// ptr to free\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\treturn(rc);\n\n}\t/* end of IPX_Get_Local_Target */\n#endif\t//WIN32\n\n/***************************************************************************\n * IPX_Cancel_Event -- cancels an operation in progress                    *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tecb_ptr\t\tpointer to ECB event to cancel\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t???\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tThe ECB must be located in real-mode memory, as well as the values\t*\n *\t\tpointed to in the ECB (the IPX Header, the buffer to send, etc.)\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nint IPX_Cancel_Event(struct ECB *ecb_ptr)\n{\n\tunion REGS      regs;\n\tstruct SREGS    sregs;\n\tRMIType rmi;\n\tunsigned int rc;\n\n\t//------------------------------------------------------------------------\n\t//\tFill in registers for the DPMI call\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = IPX_INT;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//------------------------------------------------------------------------\n\t//\tFill in registers for the interrupt call\n\t//------------------------------------------------------------------------\n\trmi.ebx = IPX_CANCEL_EVENT;\n\trmi.es = (short)((long)ecb_ptr >> 4);\n\trmi.esi = (long)((long)ecb_ptr & 0x000f);\n\n\t//------------------------------------------------------------------------\n\t//\tcall DPMI\n\t//------------------------------------------------------------------------\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\trc = (rmi.eax & 0x00ff);\n\n\treturn(rc);\n\n}\t/* end of IPX_Cancel_Event */\n#endif\t//WIN32\n\n/***************************************************************************\n * Let_IPX_Breath -- gives IPX some CPU time                               *\n *                                                                         *\n * Use this function if you're polling the ECB's InUse flag, waiting\t\t\t*\n * for it to go to 0:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *\t\twhile ECBType.InUse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tLet_IPX_Breath();\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nvoid Let_IPX_Breath(void)\n{\n\tunion REGS      regs;\n\tstruct SREGS    sregs;\n\tRMIType rmi;\n\n\t//------------------------------------------------------------------------\n\t//\tFill in registers for the DPMI call\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = IPX_INT;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//------------------------------------------------------------------------\n\t//\tFill in registers for the interrupt call\n\t//------------------------------------------------------------------------\n\trmi.ebx = IPX_RELINQUISH_CONTROL;\n\n\t//------------------------------------------------------------------------\n\t//\tcall DPMI\n\t//------------------------------------------------------------------------\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n}\t/* end of Let_IPX_Breath */\n#endif\t//WIN32\n/**************************** end of ipx.cpp *******************************/\n"
  },
  {
    "path": "CODE/IPX.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/IPX.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPX.H                                    *\n *                                                                         *\n *                   Programmer : Barry Nance\t\t\t\t\t\t\t\t\t\t*\n * \t\t\t\t\t\t\t\t\t\t from Client/Server LAN Programming\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t Westwood-ized by Bill Randolph\t\t\t\t*\n *                                                                         *\n *                   Start Date : December 14, 1994                        *\n *                                                                         *\n *                  Last Update : December 14, 1994   [BR]                 *\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef IPX_H\n#define IPX_H\n\n/*\n******************************** Structures *********************************\n*/\ntypedef unsigned char NetNumType[4];\ntypedef unsigned char NetNodeType[6];\ntypedef char UserID[48];\n\n/*---------------------------------------------------------------------------\nThis is the IPX Packet structure.  It's followed by the data itself, which\ncan be up to 546 bytes long.  Annotation of 'IPX' means IPX will set this\nfield; annotation of 'APP' means the application must set the field.\nNOTE: All header fields are ordered high-byte,low-byte.\n---------------------------------------------------------------------------*/\ntypedef struct IPXHEADER {\n\tunsigned short CheckSum;\t\t\t\t\t// IPX: Not used; always 0xffff\n\tunsigned short Length;\t\t\t\t\t\t// IPX: Total size, incl header & data\n\tunsigned char TransportControl;\t\t\t// IPX: # bridges message crossed\n\tunsigned char PacketType;\t\t\t\t\t// APP: Set to 4 for IPX (5 for SPX)\n\tunsigned char DestNetworkNumber[4];\t\t// APP: destination Network Number\n\tunsigned char DestNetworkNode[6];\t\t// APP: destination Node Address\n\tunsigned short DestNetworkSocket;\t\t// APP: destination Socket Number\n\tunsigned char SourceNetworkNumber[4];\t// IPX: source Network Number\n\tunsigned char SourceNetworkNode[6];\t\t// IPX: source Node Address\n\tunsigned short SourceNetworkSocket;\t\t// IPX: source Socket Number\n} IPXHeaderType;\n\n/*---------------------------------------------------------------------------\nThis is the IPX Event Control Block.  It serves as a communications area\nbetween IPX and the application for a single IPX operation.  You should set\nup a separate ECB for each IPX operation you perform.\n---------------------------------------------------------------------------*/\ntypedef struct ECB {\n\tvoid *Link_Address;\n\tvoid (*Event_Service_Routine)(void);\t// APP: event handler (NULL=none)\n\tunsigned char InUse;\t\t\t\t\t\t\t// IPX: 0 = event complete\n\tunsigned char CompletionCode;\t\t\t\t// IPX: event's return code\n\tunsigned short SocketNumber;\t\t\t\t// APP: socket to send data through\n\tunsigned short ConnectionID;\t\t\t\t// returned by Listen (???)\n\tunsigned short RestOfWorkspace;\n\tunsigned char DriverWorkspace[12];\n\tunsigned char ImmediateAddress[6];\t\t// returned by Get_Local_Target\n\tunsigned short PacketCount;\n\tstruct {\n\t\tvoid *Address;\n\t\tunsigned short Length;\n\t} Packet[2];\n} ECBType;\n\n\n/*---------------------------------------------------------------------------\nThis structure is used for calling DPMI function 0x300, Call-Real-Mode-\nInterrupt.  It passes register values to & from the interrupt handler.\n---------------------------------------------------------------------------*/\ntypedef struct {\n\tlong edi;\n\tlong esi;\n\tlong ebp;\n\tlong Reserved;\n\tlong ebx;\n\tlong edx;\n\tlong ecx;\n\tlong eax;\n\tshort Flags;\n\tshort es;\n\tshort ds;\n\tshort fs;\n\tshort gs;\n\tshort ip;\n\tshort cs;\n\tshort sp;\n\tshort ss;\n} RMIType;\n\n/*\n********************************** Defines **********************************\n*/\n/*---------------------------------------------------------------------------\nThese defines are for the IPX functions.  The function number is specified \nby placing it in BX when IPX is called.  There are two ways to invoke IPX: \nuse interrupt 0x7a, or use a function whose address is obtained by calling \ninterrupt 0x2f with AX=0x7a00; the function address is returned in ES:DI.  \nThis is the preferred method, since other apps are known to use int 0x7a.\n---------------------------------------------------------------------------*/\n#define\tIPX_OPEN_SOCKET\t\t\t\t\t\t0x0000\n#define\tIPX_CLOSE_SOCKET\t\t\t\t\t\t0x0001\n#define\tIPX_GET_LOCAL_TARGET\t\t\t\t\t0x0002\n#define\tIPX_SEND_PACKET\t\t\t\t\t\t0x0003\n#define\tIPX_LISTEN_FOR_PACKET\t\t\t\t0x0004\n#define\tIPX_SCHEDULE_EVENT\t\t\t\t\t0x0005\n#define\tIPX_CANCEL_EVENT\t\t\t\t\t\t0x0006\n#define\tIPX_GET_INTERVAL_MARKER\t\t\t\t0x0008\n#define\tIPX_GET_INTERNETWORK_ADDRESS\t\t0x0009\n#define\tIPX_RELINQUISH_CONTROL\t\t\t\t0x000A\n#define\tIPX_DISCONNECT_FROM_TARGET\t\t\t0x000B\n\n/*---------------------------------------------------------------------------\nThese defines are for various IPX error codes:\n---------------------------------------------------------------------------*/\n#define\tIPXERR_CONNECTION_SEVERED\t\t\t0x00ec\n#define\tIPXERR_CONNECTION_FAILED\t\t\t0x00ed\n#define\tIPXERR_NO_CONNECTION\t\t\t\t\t0x00ee\n#define\tIPXERR_CONNECTION_TABLE_FULL\t\t0x00ef\n#define\tIPXERR_NO_CANCEL_ECB\t\t\t\t\t0x00f9\n#define\tIPXERR_NO_PATH\t\t\t\t\t\t\t0x00fa\n#define\tIPXERR_ECB_INACTIVE\t\t\t\t\t0x00fc\n#define\tIPXERR_INVALID_PACKET_LENGTH\t\t0x00fd\n#define\tIPXERR_SOCKET_TABLE_FULL\t\t\t0x00fe\n#define\tIPXERR_SOCKET_ERROR\t\t\t\t\t0x00ff\n\n/*---------------------------------------------------------------------------\nThese defines are for various interrupt vectors and DPMI functions:\n---------------------------------------------------------------------------*/\n#define\tIPX_INT\t\t\t\t\t\t\t\t\t0x007a\n#define\tDPMI_INT\t\t\t\t\t\t\t\t\t0x0031\n#define\tDPMI_ALLOC_DOS_MEM\t\t\t\t\t0x0100\n#define\tDPMI_FREE_DOS_MEM\t\t\t\t\t\t0x0101\n#define\tDPMI_CALL_REAL_INT\t\t\t\t\t0x0300\n#define\tDPMI_LOCK_MEM\t\t\t\t\t\t\t0x0600\n#define\tDPMI_UNLOCK_MEM\t\t\t\t\t\t0x0601\n\n/*\n******************************** Prototypes *********************************\n*/\n/*---------------------------------------------------------------------------\nNOTE: All routines return 0 for a success code and one of the above IPX\nerror codes if there's an error, EXCEPT:\n- IPX_SPX_Installed (0 = not installed)\n- Get_Connection_Number / Get_1st_Connection_Number (0 = no connection)\n---------------------------------------------------------------------------*/\n/*\n.................................. ipx.cpp ..................................\n*/\nint IPX_SPX_Installed(void);\nint IPX_Open_Socket(unsigned short socket);\nint IPX_Close_Socket(unsigned short socket);\nint IPX_Get_Connection_Number(void);\nint IPX_Get_1st_Connection_Num (char *username);\nint IPX_Get_Internet_Address(int connection_number, \n\tunsigned char *network_number, unsigned char *physical_node);\nint IPX_Get_User_ID(int connection_number, char *user_id);\nint IPX_Listen_For_Packet(struct ECB *ecb_ptr);\nvoid IPX_Send_Packet(struct ECB *ecb_ptr);\nint IPX_Get_Local_Target(unsigned char *dest_network, unsigned char *dest_node,\n\tunsigned short dest_socket, unsigned char *bridge_address);\nint IPX_Cancel_Event(struct ECB *ecb_ptr);\nvoid Let_IPX_Breath(void);\n\n#endif\n\n/***************************** end of ipx.h ********************************/\n\n"
  },
  {
    "path": "CODE/IPX95.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPX95PP                                  *\n *                                                                         *\n *                   Programmer : Steve Tall                               *\n *                                                                         *\n *                   Start Date : January 22nd, 1996                       *\n *                                                                         *\n *                  Last Update : July 10th, 1996   [ST]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Overview:                                                               *\n *                                                                         *\n *  Windows 95 equivelent functions from IPX.CPP                           *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n#ifdef WIN32\n\n#include \"ipx95.h\"\n\n/*\n** Instance handle for the THIPX32 .DLL\n*/\nHINSTANCE\tIpxDllInstance = NULL;\n\n/*\n** Function pointers\n*/\n//extern \"C\" {\n\tIPXInitialiseType\t\t\t\t\tIPX_Initialise = NULL;\n\tIPXGetOutstandingBuffer95Type\tIPX_Get_Outstanding_Buffer95 = NULL;\n\tIPXShutDown95Type             IPX_Shut_Down95 = NULL;\n\tIPXSendPacket95Type           IPX_Send_Packet95 = NULL;\n\tIPXBroadcastPacket95Type      IPX_Broadcast_Packet95 = NULL;\n\tIPXStartListening95Type       IPX_Start_Listening95 = NULL;\n\tIPXOpenSocket95Type           IPX_Open_Socket95 = NULL;\n\tIPXCloseSocket95Type          IPX_Close_Socket95 = NULL;\n\tIPXGetConnectionNumber95Type  IPX_Get_Connection_Number95 = NULL;\n\tIPXGetLocalTarget95           IPX_Get_Local_Target95 = NULL;\n//}\n\nchar const *FunctionNames[] = {\n\t\"_IPX_Initialise\",\n\t\"_IPX_Get_Outstanding_Buffer95\",\n\t\"_IPX_Shut_Down95\",\n\t\"_IPX_Send_Packet95\",\n\t\"_IPX_Broadcast_Packet95\",\n\t\"_IPX_Start_Listening95\",\n\t\"_IPX_Open_Socket95\",\n\t\"_IPX_Close_Socket95\",\n\t\"_IPX_Get_Connection_Number95\",\n\t\"_IPX_Get_Local_Target95\",\n\tNULL\n};\n\nextern void Get_OS_Version (void);\nbool\t\t\t\tWindowsNT = false;\n\n\n/***********************************************************************************************\n * Load_IPX_Dll -- Loads the THIPX32 DLL                                                       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   true if DLL loaded                                                                *\n *                                                                                             *\n * WARNINGS: This call will fail under NT due to a side effect of loading the THIPX32.DLL      *\n *           which causes the 16 bit DLL THIPX16.DLL to load.                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    4/1/97 11:40AM ST : Created                                                              *\n *=============================================================================================*/\nbool Load_IPX_Dll (void)\n{\n\tGet_OS_Version();\n\tif (WindowsNT) return (false);\n\n\tSetErrorMode( SEM_NOOPENFILEERRORBOX );\n\tIpxDllInstance = LoadLibrary ( \"THIPX32.DLL\" );\n\tSetErrorMode ( 0 );\n\n\tif ( IpxDllInstance ){\n\n\t\tconst char\t\t*function_name;\n\t\tunsigned long \t*fptr = (unsigned long *) &IPX_Initialise;\n\t\tint\t\t\t\tcount = 0;\n\n\t\tdo {\n\t\t\tfunction_name = FunctionNames[count];\n\t\t\tif (function_name){\n\t\t\t\t*fptr = (unsigned long) GetProcAddress (IpxDllInstance, function_name);\n\t\t\t\tassert (*fptr != NULL);\n\t\t\t\tfptr++;\n\t\t\t\tcount++;\n\t\t\t}\n\n\t\t} while ( function_name );\n\n\t\treturn (true);\n\n\t}else{\n\t\treturn (false);\n\t}\n}\n\n\n\n/***********************************************************************************************\n * Unload_IPX_Dll -- Frees the THIPX32 library                                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    4/1/97 2:37PM ST : Created                                                               *\n *=============================================================================================*/\nvoid Unload_IPX_Dll (void)\n{\n\tif (IpxDllInstance){\n\t\tFreeLibrary (IpxDllInstance);\n\t\tIpxDllInstance = NULL;\n\t}\n}\n\n\nint IPX_Open_Socket(unsigned short socket)\n{\n\treturn ( IPX_Open_Socket95((int)socket));\n}\n\nint IPX_Close_Socket(unsigned short socket)\n{\n\tIPX_Close_Socket95((int)socket);\n\treturn (0);\n}\n\n\nint IPX_Get_Connection_Number(void)\n{\n\treturn (IPX_Get_Connection_Number95());\n}\n\n\n\nint IPX_Broadcast_Packet(unsigned char * buf, int buflen)\n{\n\treturn(IPX_Broadcast_Packet95(buf, buflen));\n}\n\nextern \"C\"{\n\textern void __cdecl Int3(void);\n}\n\nint IPX_Get_Local_Target(unsigned char * dest_network, unsigned char * dest_node,\n\tunsigned short dest_socket, unsigned char * bridge_address)\n{\n\t//Int3();\n\treturn (IPX_Get_Local_Target95(dest_network, dest_node, dest_socket, bridge_address));\n}\n\n\n#endif\t//WIN32\n"
  },
  {
    "path": "CODE/IPX95.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPX95PP                                  *\n *                                                                         *\n *                   Programmer : Steve Tall                               *\n *                                                                         *\n *                   Start Date : January 22nd, 1996                       *\n *                                                                         *\n *                  Last Update : January 22nd, 1996   [ST]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\n/*\n** Types for function pointers\n*/\ntypedef BOOL __stdcall (*IPXInitialiseType) (void);\ntypedef BOOL __stdcall (*IPXGetOutstandingBuffer95Type) (unsigned char*);\ntypedef void __stdcall (*IPXShutDown95Type) (void);\ntypedef int  __stdcall (*IPXSendPacket95Type) (unsigned char *, unsigned char *, int, unsigned char*, unsigned char*);\ntypedef int  __stdcall (*IPXBroadcastPacket95Type) (unsigned char *, int);\ntypedef BOOL __stdcall (*IPXStartListening95Type) (void);\ntypedef int  __stdcall (*IPXOpenSocket95Type) (int);\ntypedef void __stdcall (*IPXCloseSocket95Type) (int);\ntypedef int  __stdcall (*IPXGetConnectionNumber95Type) (void);\ntypedef int  __stdcall (*IPXGetLocalTarget95) (unsigned char *, unsigned char*, unsigned short, unsigned char*);\n\n\n\n/*\n** Function pointers\n*/\n//extern \"C\"{\n\textern IPXInitialiseType\t\t\t\t\tIPX_Initialise;\n\textern IPXGetOutstandingBuffer95Type  \tIPX_Get_Outstanding_Buffer95;\n\textern IPXShutDown95Type              \tIPX_Shut_Down95;\n\textern IPXSendPacket95Type            \tIPX_Send_Packet95;\n\textern IPXBroadcastPacket95Type       \tIPX_Broadcast_Packet95;\n\textern IPXStartListening95Type        \tIPX_Start_Listening95;\n\textern IPXOpenSocket95Type            \tIPX_Open_Socket95;\n\textern IPXCloseSocket95Type           \tIPX_Close_Socket95;\n\textern IPXGetConnectionNumber95Type   \tIPX_Get_Connection_Number95;\n\textern IPXGetLocalTarget95            \tIPX_Get_Local_Target95;\n//}\n\n/*\n** Functions\n*/\nbool Load_IPX_Dll (void);\nvoid Unload_IPX_Dll (void);\n\n\n#if (0)\nextern \"C\"{\n\textern BOOL __stdcall IPX_Initialise(void);\n\textern BOOL __stdcall IPX_Get_Outstanding_Buffer95(unsigned char *buffer);\n\textern void __stdcall IPX_Shut_Down95(void);\n\textern int  __stdcall IPX_Send_Packet95(unsigned char *, unsigned char *, int, unsigned char*, unsigned char*);\n\textern int  __stdcall IPX_Broadcast_Packet95(unsigned char *, int);\n\textern BOOL __stdcall IPX_Start_Listening95(void);\n\textern int  __stdcall IPX_Open_Socket95(int socket);\n\textern void __stdcall IPX_Close_Socket95(int socket);\n\textern int  __stdcall IPX_Get_Connection_Number95(void);\n\textern int  __stdcall IPX_Get_Local_Target95(unsigned char *, unsigned char*, unsigned short, unsigned char*);\n}\n#endif\t//(0)\n\nextern bool WindowsNT;\n"
  },
  {
    "path": "CODE/IPXADDR.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/IPXADDR.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPXADDR.CPP                              *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : December 19, 1994   [BR]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   IPXAddressClass::IPXAddressClass -- class constructor                 *\n *   IPXAddressClass::IPXAddressClass -- class constructor form 2\t\t\t\t*\n *   IPXAddressClass::IPXAddressClass -- class constructor form 3\t\t\t\t*\n *   IPXAddressClass::Set_Address -- sets the IPX address values        \t*\n *   IPXAddressClass::Set_Address -- sets the IPX values from a header\t\t*\n *   IPXAddressClass::Get_Address -- retrieves the IPX address values      *\n *   IPXAddressClass::Get_Address -- copies address into an IPX header\t\t*\n *   IPXAddressClass::Is_Broadcast -- tells if this is a broadcast address *\n *   IPXAddressClass::operator== -- overloaded comparison operator         *\n *   IPXAddressClass::operator!= -- overloaded comparison operator         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include <stdio.h>\n#include <mem.h>\n#include \"ipxaddr.h\"\n\n#ifdef WINSOCK_IPX\n#include\t\"WSProto.h\"\n#endif\t//WINSOCK_IPX\n\n\n/***************************************************************************\n * IPXAddressClass::IPXAddressClass -- class constructor                   *\n *                                                                         *\n * This default constructor generates a broadcast address.\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tNetwork Number for this address\t\t\t\t\t\t\t\t\t\t*\n *\t\tnode\t\tNode Address for this address\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nIPXAddressClass::IPXAddressClass(void)\n{\n\tNetworkNumber[0] = 0xff;\n\tNetworkNumber[1] = 0xff;\n\tNetworkNumber[2] = 0xff;\n\tNetworkNumber[3] = 0xff;\n\tNodeAddress[0] = 0xff;\n\tNodeAddress[1] = 0xff;\n\tNodeAddress[2] = 0xff;\n\tNodeAddress[3] = 0xff;\n\tNodeAddress[4] = 0xff;\n\tNodeAddress[5] = 0xff;\n\n}\t/* end of IPXAddressClass */\n\n\n/***************************************************************************\n * IPXAddressClass::IPXAddressClass -- class constructor form 2\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tNetwork Number for this address\t\t\t\t\t\t\t\t\t\t*\n *\t\tnode\t\tNode Address for this address\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nIPXAddressClass::IPXAddressClass(NetNumType net, NetNodeType node)\n{\n\tmemcpy(NetworkNumber, net, 4);\n\tmemcpy(NodeAddress, node, 6);\n\n}\t/* end of IPXAddressClass */\n\n\n/***************************************************************************\n * IPXAddressClass::IPXAddressClass -- class constructor form 3\t\t\t\t*\n *                                                                         *\n * This form of the constructor takes an IPX header as an argument.  It\t\t*\n * extracts the address from the Source address fields in the header.\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\theader\tHeader from which to extract the address\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nIPXAddressClass::IPXAddressClass(IPXHeaderType *header)\n{\n\tmemcpy(NetworkNumber,header->SourceNetworkNumber,4);\n\tmemcpy(NodeAddress,header->SourceNetworkNode,6);\n\n}\t/* end of IPXAddressClass */\n\n\n/***************************************************************************\n * IPXAddressClass::Set_Address -- sets the IPX address values        \t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tNetwork Number for this address\t\t\t\t\t\t\t\t\t\t*\n *\t\tnode\t\tNode Address for this address\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXAddressClass::Set_Address(NetNumType net, NetNodeType node)\n{\n\tmemcpy(NetworkNumber,net,4);\n\tmemcpy(NodeAddress,node,6);\n\n}\t/* end of Set_Address */\n\n\n/***************************************************************************\n * IPXAddressClass::Set_Address -- sets the IPX values from a header\t\t\t*\n *                                                                         *\n * This routine extracts the source addresses from the given IPX header.\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tNetwork Number for this address\t\t\t\t\t\t\t\t\t\t*\n *\t\tnode\t\tNode Address for this address\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXAddressClass::Set_Address(IPXHeaderType *header)\n{\n#ifdef WINSOCK_IPX\n\tProtocolEnum protocol = PROTOCOL_IPX;\n\tif ( PacketTransport ) protocol = PacketTransport->Get_Protocol();\n\n\tswitch ( protocol ) {\n\n\t\tcase PROTOCOL_IPX:\n\t\t\tmemcpy(NetworkNumber,header->SourceNetworkNumber,4);\n\t\t\tmemcpy(NodeAddress,header->SourceNetworkNode,6);\n\t\t\tbreak;\n\n\t\tcase PROTOCOL_UDP:\n\t\t\tunsigned char *addr = (unsigned char*) header;\n\t\t\tmemset (NodeAddress, 0, 6);\n\t\t\tmemcpy (NodeAddress, addr, 4);\n\t\t\tmemset (NetworkNumber, 0, 4);\n\t\t\tbreak;\n\t}\n#else\t//WINSOCK_IPX\n\n\tif (header) {\n\t\tmemcpy(NetworkNumber,header->SourceNetworkNumber,4);\n\t\tmemcpy(NodeAddress,header->SourceNetworkNode,6);\n\t} else {\n\t\t/*\n\t\t** Address is meaningless when using winsock\n\t\t*/\n\t\tmemset(NetworkNumber, 1 ,4);\n\t\tmemset(NodeAddress, 1, 6);\n\t}\n\n#endif\t//WINSOCK_IPX\n\n}\t/* end of Set_Address */\n\n\n/***************************************************************************\n * IPXAddressClass::Get_Address -- retrieves the IPX address values        *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tNetwork Number for this address\t\t\t\t\t\t\t\t\t\t*\n *\t\tnode\t\tNode Address for this address\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXAddressClass::Get_Address(NetNumType net, NetNodeType node)\n{\n\tmemcpy(net,NetworkNumber,4);\n\tmemcpy(node,NodeAddress,6);\n\n}\t/* end of Get_Address */\n\n\n/***************************************************************************\n * IPXAddressClass::Get_Address -- copies address into an IPX header\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tNetwork Number for this address\t\t\t\t\t\t\t\t\t\t*\n *\t\tnode\t\tNode Address for this address\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXAddressClass::Get_Address(IPXHeaderType *header)\n{\n\tmemcpy(header->DestNetworkNumber,NetworkNumber,4);\n\tmemcpy(header->DestNetworkNode,NodeAddress,6);\n\n}\t/* end of Get_Address */\n\n\n/***************************************************************************\n * IPXAddressClass::Is_Broadcast -- tells if this is a broadcast address   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXAddressClass::Is_Broadcast(void)\n{\n\tif (\tNetworkNumber[0] == 0xff &&\n\t\t\tNetworkNumber[1] == 0xff &&\n\t\t\tNetworkNumber[2] == 0xff &&\n\t\t\tNetworkNumber[3] == 0xff &&\n\t\t\tNodeAddress[0] == 0xff &&\n\t\t\tNodeAddress[1] == 0xff &&\n\t\t\tNodeAddress[2] == 0xff &&\n\t\t\tNodeAddress[3] == 0xff &&\n\t\t\tNodeAddress[4] == 0xff &&\n\t\t\tNodeAddress[5] == 0xff) {\n\t\treturn(1);\n\t}\n\telse {\n\t\treturn(0);\n\t}\n\n}\t/* end of Is_Broadcast */\n\n\n/***************************************************************************\n * IPXAddressClass::operator== -- overloaded comparison operator           *\n *                                                                         *\n * Since, if NETX isn't running, the network number on a received packet\t*\n * can be bogus (all 0's), only the node address is used for comparison \t*\n * purposes here.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\taddr\t\taddress to compare to\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = not equal, 1 = equal\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXAddressClass::operator == (IPXAddressClass & addr)\n{\n\t//------------------------------------------------------------------------\n\t//\tIf either Network Number is all 0's (which can happen if the system is\n\t//\tnot running NETX), compare only the Node Addresses.\n\t//------------------------------------------------------------------------\n\tif ( (NetworkNumber[0]==0 &&\n\t\t\tNetworkNumber[1]==0 &&\n\t\t\tNetworkNumber[2]==0 &&\n\t\t\tNetworkNumber[3]==0) ||\n\t\t  (addr.NetworkNumber[0]==0 &&\n\t\t\taddr.NetworkNumber[1]==0 &&\n\t\t\taddr.NetworkNumber[2]==0 &&\n\t\t\taddr.NetworkNumber[3]==0) ) {\n\n\t\tif (memcmp(NodeAddress,addr.NodeAddress,6)==0) {\n\t\t\treturn(1);\n\t\t}\n\t\telse {\n\t\t\treturn(0);\n\t\t}\n\n\t}\n\t//------------------------------------------------------------------------\n\t//\tOtherwise, compare both the Network Numbers and Node Addresses\n\t//------------------------------------------------------------------------\n\telse {\n\t\tif (memcmp(NodeAddress,addr.NodeAddress,6)==0 &&\n\t\t\tmemcmp(NetworkNumber,addr.NetworkNumber,4)==0) {\n\t\t\treturn(1);\n\t\t}\n\t\telse {\n\t\t\treturn(0);\n\t\t}\n\t}\n\n}\t/* end of operator== */\n\n\n/***************************************************************************\n * IPXAddressClass::operator!= -- overloaded comparison operator           *\n *                                                                         *\n * Since, if NETX isn't running, the network number on a received packet\t*\n * can be bogus (all 0's), only the node address is used for comparison \t*\n * purposes here.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\taddr\t\taddress to compare to\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = equal, 1 = not equal\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXAddressClass::operator != (IPXAddressClass & addr)\n{\n\t//------------------------------------------------------------------------\n\t//\tIf either Network Number is all 0's (which can happen if the system is\n\t//\tnot running NETX), compare only the Node Addresses.\n\t//------------------------------------------------------------------------\n\tif ( (NetworkNumber[0]==0 &&\n\t\t\tNetworkNumber[1]==0 &&\n\t\t\tNetworkNumber[2]==0 &&\n\t\t\tNetworkNumber[3]==0) ||\n\t\t  (addr.NetworkNumber[0]==0 &&\n\t\t\taddr.NetworkNumber[1]==0 &&\n\t\t\taddr.NetworkNumber[2]==0 &&\n\t\t\taddr.NetworkNumber[3]==0) ) {\n\n\t\tif (memcmp(NodeAddress,addr.NodeAddress,6)==0) {\n\t\t\treturn(0);\n\t\t}\n\t\telse {\n\t\t\treturn(1);\n\t\t}\n\t}\n\t//------------------------------------------------------------------------\n\t//\tOtherwise, compare both the Network Numbers and Node Addresses\n\t//------------------------------------------------------------------------\n\telse {\n\t\tif (memcmp(NodeAddress,addr.NodeAddress,6)==0 &&\n\t\t\tmemcmp(NetworkNumber,addr.NetworkNumber,4)==0) {\n\t\t\treturn(0);\n\t\t}\n\t\telse {\n\t\t\treturn(1);\n\t\t}\n\t}\n\n}\t/* end of operator!= */\n\n\n/***************************************************************************\n * IPXAddressClass::operator > -- overloaded comparison operator           *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\taddr\t\taddress to compare to\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE = greater, FALSE = not\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXAddressClass::operator > (IPXAddressClass & addr)\n{\n\treturn(memcmp(this, &addr, 10) > 0);\n\n}\t/* end of operator> */\n\n\n/***************************************************************************\n * IPXAddressClass::operator < -- overloaded comparison operator           *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\taddr\t\taddress to compare to\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE = less, FALSE = not\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXAddressClass::operator < (IPXAddressClass & addr)\n{\n\treturn(memcmp(this, &addr, 10) < 0);\n\n}\t/* end of operator< */\n\n\n/***************************************************************************\n * IPXAddressClass::operator >= -- overloaded comparison operator          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\taddr\t\taddress to compare to\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE = greater or equal, FALSE = not\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXAddressClass::operator >= (IPXAddressClass & addr)\n{\n\treturn(memcmp(this, &addr, 10) >= 0);\n\n}\t/* end of operator>= */\n\n\n/***************************************************************************\n * IPXAddressClass::operator <= -- overloaded comparison operator          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\taddr\t\taddress to compare to\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE = less or equal, FALSE = not\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXAddressClass::operator <= (IPXAddressClass & addr)\n{\n\treturn(memcmp(this, &addr, 10) <= 0);\n\n}\t/* end of operator<= */\n\n/************************** end of ipxaddr.cpp *****************************/\n"
  },
  {
    "path": "CODE/IPXADDR.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/IPXADDR.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPXADDR.H                                *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : December 19, 1994   [BR]                 *\n *                                                                         *\n * This class is useful for any IPX-related code.  It's just a utility\t\t*\n * to help manage those annoying IPX address fields.  This class lets you\t*\n * compare addresses, copy addresses to & from the IPX header, etc.\t\t\t*\n *                                                                         *\n * The class has no virtual functions, so you can treat this class just\t\t*\n * like a data structure; it can be loaded & saved, and even transmitted\t*\n * across the net.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef IPXADDR_H\n#define IPXADDR_H\n\n#include \"ipx.h\"\t\t\t\t// for NetNumType & NetNodeType\n\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass IPXAddressClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*.....................................................................\n\t\tConstructors:\n\t\t.....................................................................*/\n\t\tIPXAddressClass(void);\n\t\tIPXAddressClass(NetNumType net, NetNodeType node);\n\t\tIPXAddressClass(IPXHeaderType *header);\n\n\t\t/*.....................................................................\n\t\tSet the address from explicit variables, or from the SOURCE values\n\t\tin an IPX packet header.\n\t\t.....................................................................*/\n\t\tvoid Set_Address(NetNumType net, NetNodeType node);\n\t\tvoid Set_Address(IPXHeaderType *header);\n\t\t/*.....................................................................\n\t\tGet the address values explicitly, or copy them into the DESTINATION\n\t\tvalues in an IPX packet header.\n\t\t.....................................................................*/\n\t\tvoid Get_Address (NetNumType net, NetNodeType node);\n\t\tvoid Get_Address(IPXHeaderType *header);\n\n\t\t/*.....................................................................\n\t\tTells if this address is a broadcast address\n\t\t.....................................................................*/\n\t\tint Is_Broadcast(void);\n\n\t\t/*.....................................................................\n\t\tOverloaded operators:\n\t\t.....................................................................*/\n\t\tint operator == (IPXAddressClass & addr);\n\t\tint operator != (IPXAddressClass & addr);\n\t\tint operator > (IPXAddressClass &addr);\n\t\tint operator < (IPXAddressClass &addr);\n\t\tint operator >= (IPXAddressClass &addr);\n\t\tint operator <= (IPXAddressClass &addr);\n\t/*\n\t-------------------------- Protected Interface ---------------------------\n\t*/\n\tprotected:\n\t/*\n\t--------------------------- Private Interface ----------------------------\n\t*/\n\tprivate:\n\t\tNetNumType NetworkNumber;\n\t\tNetNodeType NodeAddress;\n};\n\n#endif\n\n/**************************** end of ipxaddr.h *****************************/\n"
  },
  {
    "path": "CODE/IPXCONN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/IPXCONN.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPXCONN.CPP                              *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 20, 1994                        *\n *                                                                         *\n *                  Last Update : April 9, 1995 [BRR]\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:    \t\t\t                                                   *\n *   IPXConnClass::IPXConnClass -- class constructor           \t\t\t\t*\n *   IPXConnClass::~IPXConnClass -- class destructor           \t\t\t\t*\n *   IPXConnClass::Init -- hardware-specific initialization routine\t\t\t*\n *   IPXConnClass::Configure -- One-time initialization routine\t\t\t\t*\n *   IPXConnClass::Start_Listening -- commands IPX to listen               *\n *   IPXConnClass::Stop_Listening -- commands IPX to stop  listen          *\n *   IPXConnClass::Send -- sends a packet; invoked by SequencedConnection\t*\n *   IPXConnClass::Open_Socket -- opens communications socket    \t\t\t\t*\n *   IPXConnClass::Close_Socket -- closes the socket \t\t\t\t\t\t\t\t*\n *   IPXConnClass::Send_To -- sends the packet to the given address\t\t\t*\n *   IPXConnClass::Broadcast -- broadcasts the given packet\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include \"function.h\"\n#include <stdio.h>\n#include <mem.h>\n#include <string.h>\n#include \"ipxconn.h\"\n\n#ifdef WINSOCK_IPX\n#include \"WSProto.h\"\n\n#else\n\n#include \"ipx95.h\"\n#ifdef WIN32\n#include \"tcpip.h\"\n#else\t//WIN32\n#include \"fakesock.h\"\n#endif\t//WIN32\n#endif\t//WINSOCK_IPX\n\n\n\n/*\n********************************* Globals ***********************************\n*/\nunsigned short \tIPXConnClass::Socket;\nint\t\t\t \t\tIPXConnClass::ConnectionNum;\nECBType *\t\t\tIPXConnClass::ListenECB;\nIPXHeaderType *\tIPXConnClass::ListenHeader;\nchar *\t\t\t\tIPXConnClass::ListenBuf;\nECBType *\t\t\tIPXConnClass::SendECB;\nIPXHeaderType *\tIPXConnClass::SendHeader;\nchar *\t\t\t\tIPXConnClass::SendBuf;\nlong \t\t\t\t\tIPXConnClass::Handler;\nint \t\t\t\t\tIPXConnClass::Configured = 0;\nint \t\t\t\t\tIPXConnClass::SocketOpen = 0;\nint \t\t\t\t\tIPXConnClass::Listening = 0;\nint\t\t\t\t\tIPXConnClass::PacketLen;\n\n\n/***************************************************************************\n * IPXConnClass::IPXConnClass -- class constructor             \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t\tdesired # of entries for the send queue\t\t\t\t\t*\n *\t\tnumreceive\t\tdesired # of entries for the receive queue\t\t\t\t*\n *\t\tmaxlen\t\t\tmax length of an application packet\t\t\t\t\t\t\t*\n *\t\tmagicnum\t\t\tthe packet \"magic number\" for this connection\t\t\t*\n *\t\taddress\t\t\taddress of destination (NULL = no address)\t\t\t\t*\n *\t\tid\t\t\t\t\tconnection's unique numerical ID\t\t\t\t\t\t\t\t*\n *\t\tname\t\t\t\tconnection's name\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textralen\t\t\tmax size of app-specific extra bytes (optional)\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nIPXConnClass::IPXConnClass (int numsend, int numreceive, int maxlen,\n\tunsigned short magicnum, IPXAddressClass *address, int id, char *name,\n\tint extralen) :\n\tConnectionClass (numsend, numreceive, maxlen, magicnum,\n\t\t2,\t\t\t// retry delta\n\t\t-1,\t\t// max retries\n\t\t60,\t\t// timeout\n\t\textralen)\t// (currently, this is only used by the Global Channel)\n{\n\tNetNumType net;\n\tNetNodeType node;\n\n\t/*------------------------------------------------------------------------\n\tSave the values passed in\n\t------------------------------------------------------------------------*/\n\tif (address)\n\t\tAddress = (*address);\n\tID = id;\n\tstrcpy (Name, name);\n\n#ifdef WINSOCK_IPX\n\tAddress.Get_Address(net,node);\n\tmemcpy(ImmediateAddress,node,6);\n\tImmed_Set = 0;\n#else\n\tif ( !Winsock.Get_Connected() ) {\n\t\t/*------------------------------------------------------------------------\n\t\tIf our Address field is an actual address (ie NULL wasn't passed to the\n\t\tconstructor), pre-compute the ImmediateAddress value for the SendECB.\n\t\tThis allows pre-computing of the ImmediateAddress for all connections\n\t\tcreated after Configure() is called.\n\t\t------------------------------------------------------------------------*/\n\t\tif (!Address.Is_Broadcast() && Configured==1) {\n\t\t\tAddress.Get_Address(net,node);\n\n\t\t\t/*.....................................................................\n\t\t\tIf the user is logged in & has a valid Novell Connection Number, get\n\t\t\tthe bridge address the \"official\" way\n\t\t\t.....................................................................*/\n\t\t\tif (ConnectionNum != 0) {\n\t\t\t\tif (IPX_Get_Local_Target (net, node, Socket, ImmediateAddress)!=0) {\n\t\t\t\t\tmemcpy(ImmediateAddress,node,6);\n\t\t\t\t}\n\t\t\t}\n\t\t\t/*.....................................................................\n\t\t\tOtherwise, use the destination node address as the ImmediateAddress,\n\t\t\tand just hope there's no network bridge in the path.\n\t\t\t.....................................................................*/\n\t\t\telse {\n\t\t\t\tmemcpy(ImmediateAddress,node,6);\n\t\t\t}\n\n\t\t\tImmed_Set = 1;\n\t\t}\n\t\telse {\n\t\t\tmemset (ImmediateAddress, 0, 6);\n\t\t\tImmed_Set = 0;\n\t\t}\n\t}\n#endif\t//WINSOCK_IPX\n}\t/* end of IPXConnClass */\n\n\n/***************************************************************************\n * IPXConnClass::Init -- hardware-specific initialization routine\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXConnClass::Init (void)\n{\n\t/*------------------------------------------------------------------------\n\tInvoke the parent's Init routine\n\t------------------------------------------------------------------------*/\n\tConnectionClass::Init();\n\n}\t/* end of Init */\n\n\n/***************************************************************************\n * IPXConnClass::Configure -- One-time initialization routine\t\t\t\t\t*\n *                                                                         *\n * This routine sets up static members that are shared by all IPX\t\t\t\t*\n * connections (ie those variables used by the Send/Listen/Broadcast\t\t\t*\n * routines).\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * INPUT:                                                                  *\n *\t\tsocket\t\t\t\tsocket ID for sending & receiving\t\t\t\t\t\t*\n *\t\tconn_num\t\t\t\tlocal IPX Connection Number (0 = not logged in)\t\t*\n *\t\tlisten_ecb\t\t\tptr to ECBType for listening\t\t\t\t\t\t\t\t*\n *\t\tsend_ecb\t\t\t\tptr to ECBType for sending\t\t\t\t\t\t\t\t\t*\n *\t\tlisten_header\t\tptr to IPXHeaderType for listening\t\t\t\t\t\t*\n *\t\tsend_header\t\t\tptr to IPXHeaderType for sending\t\t\t\t\t\t\t*\n *\t\tlisten_buf\t\t\tptr to buffer for listening\t\t\t\t\t\t\t\t*\n *\t\tsend_buf\t\t\t\tptr to buffer for sending\t\t\t\t\t\t\t\t\t*\n *\t\thandler_rm_ptr\t\tREAL-MODE pointer to event service routine\t\t\t*\n *\t\t\t\t\t\t\t\t(high word = segment, low word = offset)\t\t\t\t*\n *\t\tmaxpacketlen\t\tmax packet size to listen for\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\t- All pointers must be protected-mode pointers, but must point to\t\t*\n *\t\t  DOS real-mode memory (except the Handler segment/offset)\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXConnClass::Configure (unsigned short socket, int conn_num,\n\tECBType *listen_ecb, ECBType *send_ecb, IPXHeaderType *listen_header,\n\tIPXHeaderType *send_header, char *listen_buf, char *send_buf,\n\tlong handler_rm_ptr, int maxpacketlen)\n{\n\t/*------------------------------------------------------------------------\n\tSave the values passed in\n\t------------------------------------------------------------------------*/\n\tSocket = socket;\n\tConnectionNum = conn_num;\n\tListenECB = listen_ecb;\n\tSendECB = send_ecb;\n\tListenHeader = listen_header;\n\tSendHeader = send_header;\n\tListenBuf = listen_buf;\n\tSendBuf = send_buf;\n\tHandler = handler_rm_ptr;\n\tPacketLen = maxpacketlen;\n\n\tConfigured = 1;\n\n}\t/* end of Configure */\n\n\n/***************************************************************************\n * IPXConnClass::Start_Listening -- commands IPX to listen                 *\n *                                                                         *\n * This routine may be used to start listening in polled mode (if the \t\t*\n * ECB's Event_Service_Routine is NULL), or in interrupt mode; it's\t\t\t*\n * up to the caller to fill the ECB in.  If in polled mode, Listening\t\t*\n * must be restarted every time a packet comes in.\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\t- The ListenECB must have been properly filled in by the IPX Manager.*\n *\t\t- Configure must be called before calling this routine.\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/16/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXConnClass::Start_Listening(void)\n{\n#ifdef WIN32\n\n#ifdef WINSOCK_IPX\n\t/*\n\t** Open the socket.\n\t*/\n\tif (!Open_Socket(Socket))\n\t\treturn(false);\n\n\t/*\n\t** start listening on the socket.\n\t*/\n\tif ( PacketTransport->Start_Listening () ) {\n\t\tListening =1;\n\t\treturn (true);\n\t} else {\n\t\tClose_Socket(Socket);\n\t\treturn (false);\n\t}\n\n#else\n\tif (Winsock.Get_Connected ()) return (true);\n\n\t/*------------------------------------------------------------------------\n\tOpen the Socket\n\t------------------------------------------------------------------------*/\n\tif (!Open_Socket(Socket))\n\t\treturn(false);\n\n\tif (IPX_Start_Listening95()) {\n\t\tListening =1;\n\t\treturn (true);\n\t} else {\n\t\tClose_Socket(Socket);\n\t\treturn (false);\n\t}\n#endif\t//WINSOCK_IPX\n\n#else\t//WIN32\n\n\tvoid *hdr_ptr;\n\tunsigned long hdr_val;\n\tvoid *buf_ptr;\n\tunsigned long buf_val;\n\tint rc;\n\n\t/*------------------------------------------------------------------------\n\tDon't do a thing unless we've been configured, and we're not listening.\n\t------------------------------------------------------------------------*/\n\tif (Configured==0 || Listening==1) {\n\t\treturn(0);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tOpen the Socket\n\t------------------------------------------------------------------------*/\n\tif (!Open_Socket(Socket)) {\n\t\treturn(0);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tClear the ECB & header\n\t------------------------------------------------------------------------*/\n\tmemset(ListenECB, 0, sizeof(ECBType));\n\tmemset(ListenHeader, 0, sizeof(IPXHeaderType));\n\n\t/*------------------------------------------------------------------------\n\tConvert protected-mode ptrs to real-mode ptrs\n\t------------------------------------------------------------------------*/\n\thdr_val = (unsigned long)ListenHeader;\n\thdr_ptr = (void *)(((hdr_val & 0xffff0) << 12) | (hdr_val & 0x000f));\n\n\tbuf_val = (unsigned long)ListenBuf;\n\tbuf_ptr = (void *)(((buf_val & 0xffff0) << 12) | (buf_val & 0x000f));\n\n\t/*------------------------------------------------------------------------\n\tFill in the ECB\n\t------------------------------------------------------------------------*/\n\tListenECB->SocketNumber = Socket;\n\tListenECB->PacketCount = 2;\n\tListenECB->Packet[0].Address = hdr_ptr;\n\tListenECB->Packet[0].Length = sizeof(IPXHeaderType);\n\tListenECB->Packet[1].Address = buf_ptr;\n\tListenECB->Packet[1].Length = (unsigned short)PacketLen;\n\n\t((long &)ListenECB->Event_Service_Routine) = Handler;\n\n\t/*------------------------------------------------------------------------\n\tCommand IPX to listen\n\t------------------------------------------------------------------------*/\n\trc = IPX_Listen_For_Packet(ListenECB);\n\tif (rc!=0) {\n\t\tClose_Socket(Socket);\n\t\treturn(0);\n\t}\n\telse {\n\t\tListening = 1;\n\t\treturn(1);\n\t}\n\n#endif\t//WIN32\n\n}\t/* end of Start_Listening */\n\n\n/***************************************************************************\n * IPXConnClass::Stop_Listening -- commands IPX to stop  listen            *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\t- This routine MUST NOT be called if IPX is not listening already!\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/16/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXConnClass::Stop_Listening(void)\n{\n#ifdef WINSOCK_IPX\n\tif ( PacketTransport ) PacketTransport->Stop_Listening();\n\tListening = 0;\n\n\t//\tAll done.\n\treturn(1);\n#else\n\t/*------------------------------------------------------------------------\n\tDon't do anything unless we're already Listening.\n\t------------------------------------------------------------------------*/\n\tif (Listening==0) {\n\t\treturn(0);\n\t}\n\n#ifdef WIN32\n\n\tif (Winsock.Get_Connected()) {\n\t\tListening = 0;\n\t\treturn (true);\n\t} else {\n\t\tIPX_Shut_Down95();\n\t\tClose_Socket(Socket);\n\t}\n\n#else\t//WIN32\n\n\t/*------------------------------------------------------------------------\n\tShut IPX down.\n\t------------------------------------------------------------------------*/\n\tIPX_Cancel_Event(ListenECB);\n\tClose_Socket(Socket);\n\n#endif\t//WIN32\n\n\tListening = 0;\n\n\t/*------------------------------------------------------------------------\n\tAll done.\n\t------------------------------------------------------------------------*/\n\treturn(1);\n#endif\t//WINSOCK_IPX\n\n}\t/* end of Stop_Listening */\n\n\n/***************************************************************************\n * IPXConnClass::Send -- sends a packet; invoked by SequencedConnection\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer to send\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textrabuf\t\t(not used by this class)\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textralen\t\t(not used by this class)\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/16/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXConnClass::Send(char *buf, int buflen, void *, int)\n{\n\t/*------------------------------------------------------------------------\n\tInvoke our own Send_To routine, filling in our Address as the destination.\n\t------------------------------------------------------------------------*/\n\tif (Immed_Set) {\n\t\treturn(Send_To (buf, buflen, &Address, ImmediateAddress));\n\t}\n\telse {\n\t\treturn(Send_To (buf, buflen, &Address, NULL));\n\t}\n\n}\t/* end of Send */\n\n\n/***************************************************************************\n * IPXConnClass::Open_Socket -- opens communications socket    \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsocket\t\tdesired socket ID number\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/16/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXConnClass::Open_Socket(unsigned short socket)\n{\n\tint rc;\n#ifdef WINSOCK_IPX\n\trc = PacketTransport->Open_Socket(socket);\n\n\tSocketOpen = rc;\n\treturn ( rc );\n\n#else\t//WINSOCK_IPX\n\tif (Winsock.Get_Connected()) {\n\t\tSocketOpen = 1;\n\t\treturn (true);\n\t}\n\n\tSocketOpen = 0;\n\n\t/*------------------------------------------------------------------------\n\tTry to open a listen socket.  The socket may have been left open by\n\ta previously-crashed program, so ignore the state of the SocketOpen\n\tflag for this call; use IPX to determine if the socket was already open.\n\t------------------------------------------------------------------------*/\n\trc = IPX_Open_Socket(socket);\n\tif (rc) {\n\n\t\t/*.....................................................................\n\t\tIf already open, close & reopen it\n\t\t.....................................................................*/\n\t\tif (rc==IPXERR_SOCKET_ERROR) {\n#ifdef WIN32\n\t\t\tWWDebugString (\"Error -- Specified socket is already open\");\n#endif\t//WIN32\n\t\t\tIPX_Close_Socket(socket);\n\t\t\trc = IPX_Open_Socket(socket);\n\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tStill can't open: return error\n\t\t\t..................................................................*/\n\t\tif (rc) {\n\t\t\treturn(0);\n\t\t}\n\t}\n\n\tSocketOpen = 1;\n\n\treturn(1);\n#endif\t//WINSOCK_IPX\n\n}\t/* end of Open_Socket */\n\n\n/***************************************************************************\n * IPXConnClass::Close_Socket -- closes the socket \t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsocket\t\tdesired socket ID number\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tCalling this routine when the sockets aren't open may crash!\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/16/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXConnClass::Close_Socket(unsigned short socket)\n{\n#ifdef WINSOCK_IPX\n\tsocket = socket;\n\tPacketTransport->Close_Socket();\n\tSocketOpen = 0;\n#else\t//WINSOCK_IPX\n\tif (Winsock.Get_Connected()) {\n\t\tSocketOpen = 0;\n\t\treturn;\n\t}\n\n\t/*------------------------------------------------------------------------\n\tNever, ever, ever, under any circumstances whatsoever, close a socket\n\tthat isn't open.  You'll regret it forever (or until at least until\n\tyou're through rebooting, which, if you're on a Pentium is the same\n\tthing).\n\t------------------------------------------------------------------------*/\n\tif (SocketOpen==1) {\n\t\tIPX_Close_Socket(socket);\n\t}\n\n\tSocketOpen = 0;\n#endif\t//WINSOCK_IPX\n}\t/* end of Close_Socket */\n\n\n/***************************************************************************\n * IPXConnClass::Send_To -- sends the packet to the given address\t\t\t\t*\n *                                                                         *\n * The \"ImmediateAddress\" field of the SendECB must be filled in with the\t*\n * address of a bridge, or the node address of the destination if there\t\t*\n * is no bridge.  The NETX call to find this address will always crash\t\t*\n * if NETX isn't loaded (ConnectionNum is 0), so this case is trapped &\t\t*\n * prevented.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Also, if the address of this IPX connection is known when the \t\t\t\t*\n * constructor is called, and Configure has been called, Get_Local_Target \t*\n * is called to precompute the ImmediateAddress; this case is detected & \t*\n * if the value is already computed, it's just memcpy'd over.\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\taddress\t\tAddress to send to\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\timmed\t\t\tImmediateAddress value, NULL if none\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/16/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXConnClass::Send_To(char *buf, int buflen, IPXAddressClass *address,\n\tNetNodeType immed)\n{\n#ifdef WINSOCK_IPX\n\n\timmed = immed;\n\tassert ( immed == NULL );\n\tPacketTransport->WriteTo ( (void*)buf, buflen, (void*) address );\n\treturn (true);\n\n#else\t//WINSOCK_IPX\n\tNetNumType net;\n\tNetNodeType node;\n\tint rc;\n\n#ifdef WIN32\n\n\tunsigned char\tsend_address[6];\n\n\tif (Winsock.Get_Connected()) {\n\t\tWinsock.Write((void*)buf, buflen);\n\t\treturn (true);\n\t}\n\n\tif (immed) {\n\t\tmemcpy(send_address, immed, 6);\n#ifdef FIXIT_DESTNET\n\t\t// fixes DESTNET\n\t\taddress->Get_Address(net,node);\n#else\n\t\t// breaks DESTNET\n\t\tmemcpy(node, immed, 6);\n\t\tmemset (net, 0, sizeof(net) );\n#endif\n\t} else {\n\t\taddress->Get_Address(net,node);\n\t\t/*.....................................................................\n\t\tIf the user is logged in & has a valid Novell Connection Number, get the\n\t\tbridge address the \"official\" way\n\t\t.....................................................................*/\n\t\tif (ConnectionNum != 0) {\n\t\t\trc = IPX_Get_Local_Target (net, node, Socket, &send_address[0]);\n\t\t\tif (rc!=0) {\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t} else {\n\t\t\t/*.....................................................................\n\t\t\tOtherwise, use the destination node address as the ImmediateAddress, and\n\t\t\tjust hope there's no network bridge in the path.\n\t\t\t.....................................................................*/\n\t\t\tmemcpy(send_address,node,6);\n\t\t}\n\t}\n\n\treturn (IPX_Send_Packet95(&send_address[0], (unsigned char*)buf, buflen, (unsigned char*)net, (unsigned char*)node));\n\n#else\t//WIN32\n\n\tvoid *hdr_ptr;\n\tvoid *buf_ptr;\n\tunsigned long hdr_val;\n\tunsigned long buf_val;\n\n\t/*------------------------------------------------------------------------\n\tClear the ECB & header\n\t------------------------------------------------------------------------*/\n\tmemset(SendECB, 0, sizeof(ECBType));\n\tmemset(SendHeader, 0, sizeof(IPXHeaderType));\n\n\t/*------------------------------------------------------------------------\n\tCopy the message into the SendBuf\n\t------------------------------------------------------------------------*/\n\tmemcpy (SendBuf,buf,buflen);\n\n\t/*------------------------------------------------------------------------\n\tConvert protected-mode ptrs to real-mode ptrs\n\t------------------------------------------------------------------------*/\n\thdr_val = (unsigned long)SendHeader;\n\thdr_ptr = (void *)(((hdr_val & 0xffff0) << 12) | (hdr_val & 0x000f));\n\tbuf_val = (unsigned long)SendBuf;\n\tbuf_ptr = (void *)(((buf_val & 0xffff0) << 12) | (buf_val & 0x000f));\n\n\t/*------------------------------------------------------------------------\n\tFill in ECB\n\t------------------------------------------------------------------------*/\n\tSendECB->SocketNumber = Socket;\t\t\t\t\t\t// my output socket\n\tSendECB->PacketCount = 2;\t\t\t\t\t\t\t\t// 2 data areas\n\tSendECB->Packet[0].Address = hdr_ptr;\n\tSendECB->Packet[0].Length = sizeof(IPXHeaderType);\n\tSendECB->Packet[1].Address = buf_ptr;\n\tSendECB->Packet[1].Length = (unsigned short)buflen;\n\n\t/*------------------------------------------------------------------------\n\tGet the bridge address\n\t------------------------------------------------------------------------*/\n\tif (immed) {\n\t\tmemcpy(SendECB->ImmediateAddress, immed, 6);\n\t}\n\telse {\n\t\taddress->Get_Address(net,node);\n\n\t\t/*.....................................................................\n\t\tIf the user is logged in & has a valid Novell Connection Number, get\n\t\tthe bridge address the \"official\" way\n\t\t.....................................................................*/\n\t\tif (ConnectionNum != 0) {\n\t\t\trc = IPX_Get_Local_Target (net, node, Socket,\n\t\t\t\tSendECB->ImmediateAddress);\n\t\t\tif (rc!=0) {\n\t\t\t\treturn(0);\n\t\t\t}\n\t\t}\n\t\t/*.....................................................................\n\t\tOtherwise, use the destination node address as the ImmediateAddress,\n\t\tand just hope there's no network bridge in the path.\n\t\t.....................................................................*/\n\t\telse {\n\t\t\tmemcpy(SendECB->ImmediateAddress,node,6);\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tFill in outgoing header\n\t------------------------------------------------------------------------*/\n\tSendHeader->PacketType = 4;\t\t\t\t\t\t\t// 4 = IPX packet\n\taddress->Get_Address(SendHeader);\t\t\t\t\t// fill in header addresses\n\tSendHeader->DestNetworkSocket = Socket;\t\t\t// destination socket id\n\n\t/*------------------------------------------------------------------------\n\tSend the packet\n\t------------------------------------------------------------------------*/\n\tIPX_Send_Packet(SendECB);\n\n\t/*------------------------------------------------------------------------\n\tWait for send to complete\n\t------------------------------------------------------------------------*/\n\twhile (SendECB->InUse)\n\t\tLet_IPX_Breath();\n\n\tif (SendECB->CompletionCode!=0) {\n\t\treturn(0);\n\t}\n\telse {\n\t\treturn(1);\n\t}\n\n#endif\t//WIN32\n#endif\t//WINSOCK_IPX\n\n}\t/* end of Send_To */\n\n\n/***************************************************************************\n * IPXConnClass::Broadcast -- broadcasts the given packet\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsocket\t\tdesired socket ID number\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/16/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXConnClass::Broadcast(char *buf, int buflen)\n{\n#ifdef WINSOCK_IPX\n\tPacketTransport->Broadcast (buf, buflen);\n\treturn (true);\n\n#else\t//WINSOCK_IPX\n\n#ifdef WIN32\n\n\tif (Winsock.Get_Connected()) {\n\t\tWinsock.Write((void*)buf, buflen);\n\t\treturn(true);\n\t} else {\n\t\treturn (IPX_Broadcast_Packet95((unsigned char*)buf, buflen));\n\t}\n\n#else\t//WIN32\n\n\tvoid *hdr_ptr;\n\tvoid *buf_ptr;\n\tunsigned long hdr_val;\n\tunsigned long buf_val;\n\n\t/*------------------------------------------------------------------------\n\tClear the ECB & header\n\t------------------------------------------------------------------------*/\n\tmemset(SendECB, 0, sizeof(ECBType));\n\tmemset(SendHeader, 0, sizeof(IPXHeaderType));\n\n\t/*------------------------------------------------------------------------\n\tCopy the message into the SendBuf\n\t------------------------------------------------------------------------*/\n\tmemcpy (SendBuf,buf,buflen);\n\n\t/*------------------------------------------------------------------------\n\tConvert protected-mode ptrs to real-mode ptrs\n\t------------------------------------------------------------------------*/\n\thdr_val = (unsigned long)SendHeader;\n\thdr_ptr = (void *)(((hdr_val & 0xffff0) << 12) | (hdr_val & 0x000f));\n\tbuf_val = (unsigned long)SendBuf;\n\tbuf_ptr = (void *)(((buf_val & 0xffff0) << 12) | (buf_val & 0x000f));\n\n\t/*------------------------------------------------------------------------\n\tFill in ECB\n\t------------------------------------------------------------------------*/\n\tSendECB->SocketNumber = Socket;\t\t\t\t\t\t// my output socket\n\tSendECB->PacketCount = 2;\t\t\t\t\t\t\t\t// 2 data areas\n\tSendECB->Packet[0].Address = hdr_ptr;\n\tSendECB->Packet[0].Length = sizeof(IPXHeaderType);\n\tSendECB->Packet[1].Address = buf_ptr;\n\tSendECB->Packet[1].Length = (unsigned short)buflen;\n\tSendECB->ImmediateAddress[0] = 0xff;\n\tSendECB->ImmediateAddress[1] = 0xff;\n\tSendECB->ImmediateAddress[2] = 0xff;\n\tSendECB->ImmediateAddress[3] = 0xff;\n\tSendECB->ImmediateAddress[4] = 0xff;\n\tSendECB->ImmediateAddress[5] = 0xff;\n\n\t/*------------------------------------------------------------------------\n\tFill in outgoing header\n\t------------------------------------------------------------------------*/\n\tSendHeader->PacketType = 4;\t\t\t\t\t\t\t// 4 = IPX packet\n\tSendHeader->DestNetworkNumber[0] = 0xff;\t\t\t// 0xff = broadcast\n\tSendHeader->DestNetworkNumber[1] = 0xff;\n\tSendHeader->DestNetworkNumber[2] = 0xff;\n\tSendHeader->DestNetworkNumber[3] = 0xff;\n\tSendHeader->DestNetworkNode[0] = 0xff;\t\t\t\t// 0xff = broadcast\n\tSendHeader->DestNetworkNode[1] = 0xff;\n\tSendHeader->DestNetworkNode[2] = 0xff;\n\tSendHeader->DestNetworkNode[3] = 0xff;\n\tSendHeader->DestNetworkNode[4] = 0xff;\n\tSendHeader->DestNetworkNode[5] = 0xff;\n\tSendHeader->DestNetworkSocket = Socket;\t\t\t// destination socket #\n\n\t/*------------------------------------------------------------------------\n\tSend the packet\n\t------------------------------------------------------------------------*/\n\tIPX_Send_Packet(SendECB);\n\n\t/*------------------------------------------------------------------------\n\tWait for send to complete\n\t------------------------------------------------------------------------*/\n\twhile (SendECB->InUse) {\n\t\tLet_IPX_Breath();\n\t}\n\n\tif (SendECB->CompletionCode!=0) {\n\t\treturn(0);\n\t}\n\telse {\n\t\treturn(1);\n\t}\n\n#endif\t//WIN32\n#endif\t//WINSOCK_IPX\n}\t/* end of Broadcast */\n\n/************************** end of ipxconn.cpp *****************************/\n\n"
  },
  {
    "path": "CODE/IPXCONN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/IPXCONN.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPXCONN.H                                *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 9, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This is the Connection Class for IPX communications.  It inherits\t\t\t*\n * a Queue, PacketBuf, timeout variables from ConnectionClass.  It \t\t\t*\n * inherits its Send_/Receive_/Get_Packet functions, and the sequenced\t\t*\n * ACK/Retry logic in Service_Send_Queue & Service_Receive_Queue from\t\t*\n * SequencedConnClass.  It guarantees order of delivery of packets.\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef IPXCONN_H\n#define IPXCONN_H\n\n\n/*\n********************************* Includes **********************************\n*/\n#include \"connect.h\"\n#include \"ipxaddr.h\"\n\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass IPXConnClass : public ConnectionClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*.....................................................................\n\t\tVarious useful enums:\n\t\t.....................................................................*/\n\t\tenum IPXConnTag {\n\t\t\tCONN_NAME_MAX = 40\t\t\t// max # chars allowed for connection name\n\t\t};\n\n\t\t/*.....................................................................\n\t\tConstructor/destructor.\n\t\t.....................................................................*/\n\t\tIPXConnClass(int numsend, int numrecieve, int maxlen,\n\t\t\tunsigned short magicnum, IPXAddressClass *address, int id, char *name,\n\t\t\tint extralen = 0);\n\t\tvirtual ~IPXConnClass () {};\n\n\t\t/*.....................................................................\n\t\tInitialization.\n\t\t.....................................................................*/\n\t\tvirtual void Init (void);\n\n\t\t/*.....................................................................\n\t\tThe Configure function is for configuring all connections at once.\n\t\tIt's static because it doesn't apply to any specific connection, but\n\t\tall of them.\n\t\t.....................................................................*/\n\t\tstatic void Configure(unsigned short socket,\n\t\t\tint conn_num, ECBType *listen_ecb, ECBType *send_ecb,\n\t\t\tIPXHeaderType *listen_header, IPXHeaderType *send_header,\n\t\t\tchar *listen_buf, char *send_buf, long handler_rm_ptr,\n\t\t\tint maxpacketlen);\n\n\t\t/*.....................................................................\n\t\tThese routines tell IPX to start listening for packets, and to stop\n\t\tlistening for packets.  They're static because they affect all\n\t\tconnections at once (there's no way to turn listening on for only one\n\t\tconnection; it's all or nothing).\n\t\t.....................................................................*/\n\t\tstatic int Start_Listening (void);\n\t\tstatic int Stop_Listening (void);\n\n\t\t/*.....................................................................\n\t\tThe Destination IPX Address for this connection\n\t\t.....................................................................*/\n\t\tIPXAddressClass Address;\n\n\t\t/*.....................................................................\n\t\tThe \"Immediate\" (Bridge) address for this connection, and a flag\n\t\ttelling if the address has been precomputed.\n\t\t.....................................................................*/\n\t\tNetNodeType ImmediateAddress;\n\t\tint Immed_Set;\n\n\t\t/*.....................................................................\n\t\tEach IPX Connection can have a Name & Unique numerical ID\n\t\t.....................................................................*/\n\t\tint ID;\n\t\tchar Name[CONN_NAME_MAX];\n\n\t/*\n\t-------------------------- Protected Interface ---------------------------\n\t*/\n\tprotected:\n\n\t\t/*.....................................................................\n\t\tThis is the overloaded Send routine declared in ConnectionClass, and\n\t\tused in SequencedConnClass.\n\t\t.....................................................................*/\n\t\tvirtual int Send (char *buf, int buflen, void *extrabuf, int extralen);\n\n\t\t/*.....................................................................\n\t\tThese are the routines that access IPX.  Open_Socket & Close_Socket are\n\t\tstatic because they're called by Start_Listening & Stop_Listening.\n\t\tSend_To & Broadcast are static since they're direct interfaces to IPX,\n\t\tand there's only one IPX instance running.\n\t\t.....................................................................*/\n\t\tstatic int Open_Socket(unsigned short socket);\n\t\tstatic void Close_Socket(unsigned short socket);\n\t\tstatic int Send_To(char *buf, int buflen, IPXAddressClass *address,\n\t\t\tNetNodeType immed);\n\t\tstatic int Broadcast(char *buf, int buflen);\n\n\t\t/*.....................................................................\n\t\tThe socket ID for this connection\n\t\t.....................................................................*/\n\t\tstatic unsigned short Socket;\n\n\t\t/*.....................................................................\n\t\tUser's local Connection # (0 = not logged in)\n\t\t.....................................................................*/\n\t\tstatic int ConnectionNum;\n\n\t\t/*.....................................................................\n\t\tThis is a static version of MaxPacketLen, which is the size of the\n\t\tapp's packets, plus our internal CommHeaderType.  It's used in the\n\t\tStart_Listening routine.\n\t\t.....................................................................*/\n\t\tstatic int PacketLen;\n\n\t\t/*.....................................................................\n\t\tVariables for Listening (created by the IPXManagerClass, and passed\n\t\tin via Init).  All IPX connections share these buffers.\n\t\t.....................................................................*/\n\t\tstatic ECBType *ListenECB;\n\t\tstatic IPXHeaderType *ListenHeader;\n\t\tstatic char *ListenBuf;\n\n\t\t/*.....................................................................\n\t\tVariables for Sending (created by the IPXManagerClass, and passed\n\t\tin via Init).  All IPX connections share these buffers.\n\t\t.....................................................................*/\n\t\tstatic ECBType *SendECB;\n\t\tstatic IPXHeaderType *SendHeader;\n\t\tstatic char *SendBuf;\n\n\t\t/*.....................................................................\n\t\tThis is a REAL-MODE pointer to the event-service-routine for IPX.\n\t\tIf it's 0, IPX will operate in polled mode.  Otherwise, the high word\n\t\tmust contain the segment, and the low word must contain the offset.\n\t\tCS will be the high word value when the routine is called.  (Requiring\n\t\tthe segment/offset to be computed by the caller gives the caller\n\t\tcontrol over CS.)\n\t\t.....................................................................*/\n\t\tstatic long Handler;\n\n\t\t/*.....................................................................\n\t\tThis status flag tells us if Configure() has been called or not.\n\t\t.....................................................................*/\n\t\tstatic int Configured;\n\n\t\t/*.....................................................................\n\t\tThis status flag tells us if the socket has been opened or not.\n\t\t.....................................................................*/\n\t\tstatic int SocketOpen;\n\n\t\t/*.....................................................................\n\t\tThis status flag tells us if Start_Listening() has been called or not.\n\t\t.....................................................................*/\n\t\tstatic int Listening;\n};\n\n#endif\n\n/*************************** end of ipxconn.h ******************************/\n"
  },
  {
    "path": "CODE/IPXGCONN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/IPXGCONN.CPP 3     10/13/97 2:20p Steve_t $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPXGCONN.CPP                             *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 20, 1994                        *\n *                                                                         *\n *                  Last Update : July 6, 1995 [BRR]                       *\n *-------------------------------------------------------------------------*\n * Functions:    \t\t\t                                                   *\n *   IPXGlobalConnClass::IPXGlobalConnClass -- class constructor           *\n *   IPXGlobalConnClass::~IPXGlobalConnClass -- class destructor           *\n *   IPXGlobalConnClass::Send_Packet -- adds a packet to the send queue\t\t*\n *   IPXGlobalConnClass::Receive_Packet -- adds packet to the receive queue*\n *   IPXGlobalConnClass::Get_Packet -- gets a packet from the receive queue*\n *   IPXGlobalConnClass::Send -- sends a packet\t\t\t\t\t\t\t\t\t\t*\n *   IPXGlobalConnClass::Service_Receive_Queue -- services receive queue\t*\n *   IPXGlobalConnClass::Set_Bridge -- Sets up connection to cross a bridge*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include \"function.h\"\n#include <stdio.h>\n#include <mem.h>\n#include \"ipxgconn.h\"\n\n\n/***************************************************************************\n * IPXGlobalConnClass::IPXGlobalConnClass -- class constructor             *\n *                                                                         *\n * This routine chains to the parent constructor, but it adjusts the size\t*\n * of the packet by the added bytes in the GlobalHeaderType structure.  \t*\n * This forces the parent classes to allocate the proper sized PacketBuf\t*\n * for outgoing packets, and to set MaxPacketLen to the proper value.\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t\tdesired # of entries for the send queue\t\t\t\t\t*\n *\t\tnumreceive\t\tdesired # of entries for the receive queue\t\t\t\t*\n *\t\tmaxlen\t\t\tmax length of an application packet\t\t\t\t\t\t\t*\n *\t\tproduct_id\t\tunique ID for this product\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nIPXGlobalConnClass::IPXGlobalConnClass (int numsend, int numreceive,\n\tint maxlen, unsigned short product_id) :\n\tIPXConnClass (numsend, numreceive,\n\t\tmaxlen + sizeof(GlobalHeaderType) - sizeof(CommHeaderType),\n\t\tGLOBAL_MAGICNUM, \t\t// magic number for this connection\n\t\tNULL,\t\t\t\t\t\t// IPX Address (none)\n\t\t0, \t\t\t\t\t\t// Connection ID\n\t\t\"\",\t\t\t\t\t\t// Connection Name\n\t\tsizeof (IPXAddressClass))\t// extra storage for the sender's address\n{\n\tint i;\n\n\tProductID = product_id;\n\tIsBridge = 0;\n\n\tfor (i = 0; i < 4; i++) {\n\t\tLastPacketID[i] = 0xffffffff;\n\t}\n\tLastRXIndex = 0;\n\n}\t/* end of IPXGlobalConnClass */\n\n\n/***************************************************************************\n * IPXGlobalConnClass::Send_Packet -- adds a packet to the send queue\t\t*\n *                                                                         *\n * This routine prefixes the given buffer with a GlobalHeaderType and\t\t*\n * queues the resulting packet into the Send Queue.  The packet's \t\t\t*\n * MagicNumber, Code, PacketID, destination Address and ProductID are set \t*\n * here. \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\taddress\t\taddress to send the packet to (NULL = Broadcast)\t\t\t*\n *\t\tack_req\t\t1 = ACK is required for this packet; 0 = isn't\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXGlobalConnClass::Send_Packet (void * buf, int buflen,\n\tIPXAddressClass *address, int ack_req)\n{\n\tIPXAddressClass dest_addr;\n\n\t/*------------------------------------------------------------------------\n\tStore the packet's Magic Number\n\t------------------------------------------------------------------------*/\n\t((GlobalHeaderType *)PacketBuf)->Header.MagicNumber = MagicNum;\n\n\t/*------------------------------------------------------------------------\n\tIf this is a ACK-required packet, sent to a specific system, mark it as\n\tACK-required; otherwise, mark as no-ACK-required.\n\t------------------------------------------------------------------------*/\n\tif (ack_req && address != NULL) {\n\t\t((GlobalHeaderType *)PacketBuf)->Header.Code = PACKET_DATA_ACK;\n\t}\n\telse {\n\t\t((GlobalHeaderType *)PacketBuf)->Header.Code = PACKET_DATA_NOACK;\n\t}\n\n\t/*------------------------------------------------------------------------\n\tFill in the packet ID.  This will have very limited meaning; it only\n\tallows us to determine if an ACK packet we receive later goes with this\n\tpacket; it doesn't let us detect re-sends of other systems' packets.\n\t------------------------------------------------------------------------*/\n\t((GlobalHeaderType *)PacketBuf)->Header.PacketID = Queue->Send_Total();\n\n\t/*------------------------------------------------------------------------\n\tSet the product ID for this packet.\n\t------------------------------------------------------------------------*/\n\t((GlobalHeaderType *)PacketBuf)->ProductID = ProductID;\n\n\t/*------------------------------------------------------------------------\n\tSet this packet's destination address.  If no address is specified, use\n\ta Broadcast address (which IPXAddressClass's default constructor creates).\n\t------------------------------------------------------------------------*/\n\tif (address != NULL) {\n\t\tdest_addr = (*address);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tCopy the application's data\n\t------------------------------------------------------------------------*/\n\tmemcpy(PacketBuf + sizeof(GlobalHeaderType), buf, buflen);\n\n\t/*------------------------------------------------------------------------\n\tQueue it, along with the destination address\n\t------------------------------------------------------------------------*/\n\treturn(Queue->Queue_Send(PacketBuf,buflen + sizeof(GlobalHeaderType),\n\t\t&dest_addr, sizeof (IPXAddressClass)));\n\n}\t/* end of Send_Packet */\n\n\n/***************************************************************************\n * IPXGlobalConnClass::Receive_Packet -- adds packet to the receive queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tbuffer to process (already includes GlobalHeaderType)\t\t\t*\n *\t\tbuflen\tlength of buffer to process\t\t\t\t\t\t\t\t\t\t\t*\n *\t\taddress\tthe address of the sender (the IPX Manager class must\t\t\t*\n *\t\t\t\t\textract this from the IPX Header of the received packet.)\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXGlobalConnClass::Receive_Packet (void * buf, int buflen,\n\tIPXAddressClass *address)\n{\n\tGlobalHeaderType *packet;\t\t\t\t// ptr to this packet\n\tSendQueueType *send_entry;\t\t\t\t// ptr to send entry header\n\tGlobalHeaderType *entry_data;\t\t\t// ptr to queue entry data\n\tGlobalHeaderType ackpacket;\t\t\t// ACK packet to send\n\tint i;\n\tint resend;\n\n\t/*------------------------------------------------------------------------\n\tCheck the magic #\n\t------------------------------------------------------------------------*/\n\tpacket = (GlobalHeaderType *)buf;\n\tif (packet->Header.MagicNumber!=MagicNum) {\n\t\treturn(0);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tProcess the packet based on its Code\n\t------------------------------------------------------------------------*/\n\tswitch (packet->Header.Code) {\n\t\t//.....................................................................\n\t\t// DATA_ACK: Check for a resend by comparing the source address &\n\t\t// ID of this packet with our last 4 received packets.\n\t\t// Send an ACK for the packet, regardless of whether it's a resend\n\t\t// or not.\n\t\t//.....................................................................\n\t\tcase PACKET_DATA_ACK:\n\t\t{\n\t\t\t//..................................................................\n\t\t\t// Check for a resend\n\t\t\t//..................................................................\n\t\t\tresend = 0;\n\t\t\tfor (i = 0; i < 4; i++) {\n\t\t\t\tif (i >= Queue->Receive_Total()) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif ((*address)==LastAddress[i] &&\n\t\t\t\t\tpacket->Header.PacketID==LastPacketID[i]) {\n\t\t\t\t\tresend = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbool send_ack = true;\n\n\t\t\t//..................................................................\n\t\t\t// If it's not a resend, queue it; then, record the sender's address\n\t\t\t// & the packet ID for future resend detection.\n\t\t\t//..................................................................\n\t\t\tif (!resend) {\n\t\t\t\tif (Queue->Queue_Receive (buf, buflen, address, sizeof(IPXAddressClass))) {\n\t\t\t\t\tLastAddress[LastRXIndex] = (*address);\n\t\t\t\t\tLastPacketID[LastRXIndex] = packet->Header.PacketID;\n\t\t\t\t\tLastRXIndex++;\n\t\t\t\t\tif (LastRXIndex >= 4) {\n\t\t\t\t\t\tLastRXIndex = 0;\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\t//..................................................................\n\t\t\t\t\t// Don't send an ack if we didn't have room to store the packet.\n\t\t\t\t\t//..................................................................\n\t\t\t\t\tsend_ack = false;\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\t//..................................................................\n\t\t\t// Send an ACK for this packet\n\t\t\t//..................................................................\n\t\t\tif (send_ack) {\n\t\t\t\tackpacket.Header.MagicNumber = MagicNum;\n\t\t\t\tackpacket.Header.Code = PACKET_ACK;\n\t\t\t\tackpacket.Header.PacketID = packet->Header.PacketID;\n\t\t\t\tackpacket.ProductID = ProductID;\n\t\t\t\tSend ((char *)&ackpacket, sizeof(GlobalHeaderType),\n\t\t\t\t\taddress, sizeof(IPXAddressClass));\n\t\t\t}\n\n\n\t\t\tbreak;\n\t\t}\n\t\t/*.....................................................................\n\t\tDATA_NOACK: Queue this message, along with the sender's address.\n\t\tDon't bother checking for a Re-Send, since the other system will only\n\t\tsend this packet once.\n\t\t.....................................................................*/\n\t\tcase PACKET_DATA_NOACK:\n\t\t\tQueue->Queue_Receive (buf, buflen, address, sizeof(IPXAddressClass));\n\t\t\tbreak;\n\n\t\t/*.....................................................................\n\t\tACK: If this ACK is for any of my packets, mark that packet as\n\t\tacknowledged, then throw this packet away.  Otherwise, ignore the ACK\n\t\t(if we re-sent before we received the other system's first ACK, this\n\t\tACK will be a leftover)\n\t\t.....................................................................*/\n\t\tcase PACKET_ACK:\n\t\t\tfor (i = 0; i < Queue->Num_Send(); i++) {\n\t\t\t\t/*...............................................................\n\t\t\t\tGet queue entry ptr\n\t\t\t\t...............................................................*/\n\t\t\t\tsend_entry = Queue->Get_Send(i);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tIf ptr is valid, get ptr to its data\n\t\t\t\t...............................................................*/\n\t\t\t\tentry_data = (GlobalHeaderType *)(send_entry->Buffer);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tIf ACK is for this entry, mark it\n\t\t\t\t...............................................................*/\n\t\t\t\tif (packet->Header.PacketID==entry_data->Header.PacketID &&\n\t\t\t\t\tentry_data->Header.Code == PACKET_DATA_ACK) {\n\t\t\t\t\tsend_entry->IsACK = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*.....................................................................\n\t\tDefault: ignore the packet\n\t\t.....................................................................*/\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\treturn(1);\n\n}\t/* end of Receive_Packet */\n\n\n/***************************************************************************\n * IPXGlobalConnClass::Get_Packet -- gets a packet from the receive queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tlocation to store buffer\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tfilled in with length of 'buf'\t\t\t\t\t\t\t\t\t*\n *\t\taddress\t\tfilled in with sender's address\t\t\t\t\t\t\t\t\t*\n *\t\tproduct_id\tfilled in with sender's ProductID\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXGlobalConnClass::Get_Packet (void * buf, int *buflen,\n\tIPXAddressClass *address, unsigned short *product_id)\n{\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\tGlobalHeaderType *packet;\n\tint packetlen;\t\t\t\t\t\t\t\t\t\t// size of received packet\n\n\t/*------------------------------------------------------------------------\n\tReturn if nothing to do\n\t------------------------------------------------------------------------*/\n\tif (Queue->Num_Receive() == 0) {\n\t\treturn(0);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tGet ptr to the next available entry\n\t------------------------------------------------------------------------*/\n\trec_entry = Queue->Get_Receive(0);\n\n\t/*------------------------------------------------------------------------\n\tRead it if it's un-read\n\t------------------------------------------------------------------------*/\n\tif (rec_entry!=NULL && rec_entry->IsRead==0) {\n\n\t\t/*.....................................................................\n\t\tMark as read\n\t\t.....................................................................*/\n\t\trec_entry->IsRead = 1;\n\n\t\t/*.....................................................................\n\t\tCopy data packet\n\t\t.....................................................................*/\n\t\tpacket = (GlobalHeaderType *)(rec_entry->Buffer);\n\t\tpacketlen = rec_entry->BufLen - sizeof(GlobalHeaderType);\n\t\tif (packetlen > 0) {\n\t\t\tmemcpy(buf, rec_entry->Buffer + sizeof(GlobalHeaderType), packetlen);\n\t\t}\n\t\t(*buflen) = packetlen;\n\t\t(*product_id) = packet->ProductID;\n\t\t(*address) = (*((IPXAddressClass *)(rec_entry->ExtraBuffer)));\n\n\t\treturn(1);\n\t}\n\n\treturn(0);\n\n}\t/* end of Get_Packet */\n\n\n/***************************************************************************\n * IPXGlobalConnClass::Send -- sends a packet\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * This routine gets invoked by NonSequencedConn, when it's processing\t\t*\n * the Send & Receive Queues.  The buffer provided will already have the\t*\n * GlobalHeaderType header embedded in it.\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textrabuf\t\textra buffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textralen\t\tlength of extra buffer\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXGlobalConnClass::Send(char *buf, int buflen, void *extrabuf, int )\n{\n\tIPXAddressClass *addr;\n\tint rc;\n\n\t/*------------------------------------------------------------------------\n\tExtract the packet's embedded IPX address\n\t------------------------------------------------------------------------*/\n\taddr = (IPXAddressClass *)extrabuf;\n\n\t/*------------------------------------------------------------------------\n\tIf it's a broadcast address, broadcast it\n\t------------------------------------------------------------------------*/\n\tif (addr->Is_Broadcast()) {\n\t\treturn(Broadcast (buf, buflen));\n\t}\n\n\t/*------------------------------------------------------------------------\n\tOtherwise, send it\n\t------------------------------------------------------------------------*/\n\telse {\n\t\tif (IsBridge && !memcmp (addr, BridgeNet, 4)) {\n\t\t\trc = Send_To (buf, buflen, addr, BridgeNode);\n\t\t}\n\t\telse {\n\t\t\trc = Send_To (buf, buflen, addr, NULL);\n\t\t}\n\t\treturn (rc);\n\t}\n\n} \t/* end of Send */\n\n\n/***************************************************************************\n * IPXGlobalConnClass::Service_Receive_Queue -- services the receive queue\t*\n *                                                                         *\n * This routine is necessary because the regular ConnectionClass checks\t\t*\n * for sequential packet ID's before removing them from the receive queue;\t*\n * this class cannot do that.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXGlobalConnClass::Service_Receive_Queue (void)\n{\n\tint i;\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\n\t//------------------------------------------------------------------------\n\t// Remove all dead packets:  If a packet's been read, throw it away.\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\t\trec_entry = Queue->Get_Receive(i);\n\n\t\tif (rec_entry->IsRead) {\n\t\t\tQueue->UnQueue_Receive(NULL,NULL,i,NULL,NULL);\n\t\t\ti--;\n\t\t}\n\t}\n\n\treturn (1);\n\n} \t/* end of Service_Receive_Queue */\n\n\n/***************************************************************************\n * Set_Bridge -- Sets up connection to cross a bridge                      *\n *                                                                         *\n * This routine is designed to prevent the connection from having to\t\t\t*\n * call Get_Local_Target, except the minimum number of times, since that\t*\n * routine is buggy & goes away for long periods sometimes.\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbridge\t\tnetwork number of the destination bridge\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/06/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid IPXGlobalConnClass::Set_Bridge(NetNumType bridge)\n{\n#ifdef WINSOCK_IPX\n\n\tif (Configured) {\n\t\tbridge = bridge;\n\t\tIsBridge = 0;\n\t}\n\n#else\t//WINSOCK_IPX\n\tif (Configured) {\n\t\tmemcpy (BridgeNet, bridge, 4);\n\t\tmemset (BridgeNode, 0xff, 6);\n\n\t\tif (IPX_Get_Local_Target (BridgeNet, BridgeNode, Socket, BridgeNode)==0) {\n\t\t\tIsBridge = 1;\n\t\t}\n\t\telse {\n\t\t\tIsBridge = 0;\n\t\t}\n\t}\n#endif\t//WINSOCK_IPX\n\n} \t/* end of Set_Bridge */\n\n\n/************************** end of ipxgconn.cpp ****************************/\n"
  },
  {
    "path": "CODE/IPXGCONN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/IPXGCONN.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPXGCONN.H                               *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 11, 1995   [BR]                 \t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This class is a special type of IPX Connection.  It can talk to more\t\t*\n * than one system at a time.  It can Broadcast packets to all systems,\t\t*\n * or send a packet to one individual system.  The packets it sends to\t\t*\n * individual systems can be DATA_NOACK or DATA_ACK packets, but the\t\t\t*\n * packets broadcast have to be DATA_NOACK packets.  This class is for\t\t*\n * only the crudest \"Who-are-you\" type of network communications.  Once\t\t*\n * the IPX Address of another system is identified, a \"real\" IPX\t\t\t\t*\n * Connection should be created, & further communications done through it.\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This means that the packet ID field no longer can be used to detect\t\t*\n * resends, since the receive queue may receive a lot more packets than\t\t*\n * we send out.  So, re-sends cannot be detected; the application must be\t*\n * designed so that it can handle multiple copies of the same packet.\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * The class uses a slightly different header from the normal Connections;\t*\n * this header includes the ProductID of the sender, so multiple \t\t\t\t*\n * applications can share the same socket, but by using different product\t*\n * ID's, can distinguish between their own packets & others.\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tBecause of this additional header, and because Receive ACK/Retry logic\t*\n * is different (we can't detect resends), the following routines are\t\t*\n * overloaded:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tSend_Packet:\t\tmust embed the product ID into the packet header\t*\n *\t\tReceive_Packet:\tmust detect resends via the LastAddress & \t\t\t*\n *\t\t\t\t\t\t\t\tLastPacketID arrays. This class doesn't ACK \t\t\t*\n *\t\t\t\t\t\t\t\tpackets until Service_Receive_Queue is called; \t\t*\n *\t\t\t\t\t\t\t\tthe parent classes ACK the packet when it's \t\t\t*\n *\t\t\t\t\t\t\t\treceived.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tGet_Packet:\t\t\textracts the product ID from the header;\t\t\t\t*\n *\t\t\t\t\t\t\t\tdoesn't care about reading packets in order\t\t\t*\n *\t\tSend\t\t\t\t\tis capable of broadcasting the packet, or sending\t*\n *\t\t\t\t\t\t\t\tto a specific address\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tThis class also has the ability to cross a Novell Network Bridge.\t\t\t*\n * You provide the class with the bridge address, and subsequent\t\t\t\t*\n * broadcasts are sent across the bridge as well as to the local network.\t*\n * Address-specific sends contain the destination network's address,\t\t\t*\n * so they cross a bridge automatically; it's just the broadcasts\t\t\t\t*\n * that need to know the bridge address.\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef IPXGLOBALCONN_H\n#define IPXGLOBALCONN_H\n\n\n#include \"ipxconn.h\"\n\n\n/*\n********************************** Defines **********************************\n*/\n//---------------------------------------------------------------------------\n// This is the header for Global Connection messages.  It includes the usual\n// \"standard\" header that the other connections do; but it also includes an\n// IPX address field, so the application can get the address of the sender\n// of this message.  This address field must be provided in by the IPX\n// Connection Manager class, when it calls this class's Receive_Packet\n// function.\n//---------------------------------------------------------------------------\ntypedef struct {\n\tCommHeaderType Header;\n\tunsigned short ProductID;\n} GlobalHeaderType;\n\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass IPXGlobalConnClass : public IPXConnClass\n{\n\t//------------------------------------------------------------------------\n\t// Public Interface\n\t//------------------------------------------------------------------------\n\tpublic:\n\t\t//.....................................................................\n\t\t// Some useful enums:\n\t\t//.....................................................................\n\t\tenum GlobalConnectionEnum {\n\t\t\t//..................................................................\n\t\t\t// This is the magic number for all Global Connections.  Having the\n\t\t\t// same magic number across products lets us ID different products\n\t\t\t// on the net.  If you change the fundamental connection protocol,\n\t\t\t// you must use a different magic number.\n\t\t\t//..................................................................\n\t\t\t//GLOBAL_MAGICNUM = 0x1234,\t// used for C&C 1\n\t\t\tGLOBAL_MAGICNUM = 0x1235,\t\t// used for C&C 0\n\t\t\t//..................................................................\n\t\t\t// These are the values used for the ProductID field in the Global\n\t\t\t// Message structure.  It also should be the Magic Number used for\n\t\t\t// the private connections within that product.\n\t\t\t// This list should be continually updated & kept current.  Never\n\t\t\t// ever ever use an old product ID for your product!\n\t\t\t//..................................................................\n\t\t\tCOMMAND_AND_CONQUER = 0xaa01,\n\t\t\tCOMMAND_AND_CONQUER0 = 0xaa00\n\t\t};\n\n\t\t//.....................................................................\n\t\t// Constructor/destructor.\n\t\t//.....................................................................\n\t\tIPXGlobalConnClass (int numsend, int numrecieve, int maxlen,\n\t\t\tunsigned short product_id);\n\t\tvirtual ~IPXGlobalConnClass () {};\n\n\t\t//.....................................................................\n\t\t// Send/Receive routines.\n\t\t//.....................................................................\n\t\tvirtual int Send_Packet (void * buf, int buflen,\n\t\t\tIPXAddressClass *address, int ack_req);\n\t\tvirtual int Receive_Packet (void * buf, int buflen,\n\t\t\tIPXAddressClass *address);\n\t\tvirtual int Get_Packet (void * buf, int *buflen,\n\t\t\tIPXAddressClass *address, unsigned short *product_id);\n\n\t\t//.....................................................................\n\t\t// This is for telling the connection it can cross a bridge.\n\t\t//.....................................................................\n\t\tvoid Set_Bridge (NetNumType bridge);\n\n\t\t//.....................................................................\n\t\t// The Product ID for this product.\n\t\t//.....................................................................\n\t\tunsigned short ProductID;\n\n\t\t//.....................................................................\n\t\t// This describes the address of a bridge we have to cross.  This class\n\t\t// supports crossing only one bridge.  Storing the bridge's network\n\t\t// number allows us to obtain its local target address only once, then\n\t\t// re-use it.\n\t\t//.....................................................................\n\t\tNetNumType BridgeNet;\n\t\tNetNodeType BridgeNode;\n\t\tint IsBridge;\n\n\t//------------------------------------------------------------------------\n\t// Protected Interface\n\t//------------------------------------------------------------------------\n\tprotected:\n\n\t\t//.....................................................................\n\t\t// This is the overloaded Send routine declared in ConnectionClass, and\n\t\t// used in SequencedConnClass.  This special version sends to the address\n\t\t// stored in the extra buffer within the Queue.\n\t\t//.....................................................................\n\t\tvirtual int Send (char *buf, int buflen, void *extrabuf, int extralen);\n\n\t\t//.....................................................................\n\t\t// This routine is overloaded from SequencedConnClass, because the\n\t\t// Global Connection needs to ACK its packets differently from the\n\t\t// other connections.\n\t\t//.....................................................................\n\t\tvirtual int Service_Receive_Queue (void);\n\n\tprivate:\n\t\t//.....................................................................\n\t\t// Since we can't detect resends by using the PacketID (since we're\n\t\t// receiving packets from a variety of sources, all using different\n\t\t// ID's), we'll have to remember the last 'n' packet addresses & id's\n\t\t// for comparison purposes.\n\t\t// Note that, if network traffic is heavy, it's still possible for an\n\t\t// app to receive the same packet twice!\n\t\t//.....................................................................\n\t\tIPXAddressClass LastAddress[4];\t// array of last 4 addresses\n\t\tunsigned long LastPacketID[4];\t// array of last 4 packet ID's\n\t\tint LastRXIndex;\t\t\t\t\t\t// index of next avail pos\n};\n\n#endif\n\n/*************************** end of ipxgconn.h *****************************/\n"
  },
  {
    "path": "CODE/IPXMGR.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/IPXMGR.CPP 3     10/13/97 2:20p Steve_t $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPXMGR.CPP                               *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 20, 1994                        *\n *                                                                         *\n *                  Last Update : May 4, 1995 [BRR]                        *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                       \t\t\t*\n *   IPXManagerClass::IPXManagerClass -- class constructor                 *\n *   IPXManagerClass::~IPXManagerClass -- class destructor                 *\n *   IPXManagerClass::Init -- initialization routine\t\t\t\t\t\t\t\t*\n *   IPXManagerClass::Is_IPX -- tells if IPX is installed or not\t\t\t\t*\n *   IPXManagerClass::Set_Timing -- sets timing for all connections\t\t\t*\n *   IPXManagerClass::Create_Connection -- creates a new connection        *\n *   IPXManagerClass::Delete_Connection -- deletes a connection            *\n *   IPXManagerClass::Num_Connections -- gets the # of connections\t\t\t*\n *   IPXManagerClass::Connection_ID -- gets the given connection's ID      *\n *   IPXManagerClass::Connection_Name -- gets name for given connection    *\n *   IPXManagerClass::Connection_Address -- retrieves connection's address\t*\n *   IPXManagerClass::Connection_Index -- gets given connection's index    *\n *   IPXManagerClass::Set_Connection_Parms -- sets connection's name & id\t*\n *   IPXManagerClass::Send_Global_Message -- sends a Global Message\t\t\t*\n *   IPXManagerClass::Get_Global_Message -- polls the Global Message queue\t*\n *   IPXManagerClass::Send_Private_Message -- Sends a Private Message\t\t*\n *   IPXManagerClass::Get_Private_Message -- Polls Private Message queue\t*\n *   IPXManagerClass::Service -- main polling routine for IPX Connections\t*\n *   IPXManagerClass::Get_Bad_Connection -- returns bad connection ID      *\n *   IPXManagerClass::Global_Num_Send\t-- gets # entries in send queue\t   *\n *   IPXManagerClass::Global_Num_Receive -- gets # entries in recv queue   *\n *   IPXManagerClass::Private_Num_Send -- gets # entries in send queue\t   *\n *   IPXManagerClass::Private_Num_Receive -- gets # entries in recv queue  *\n *   IPXManagerClass::Set_Bridge -- prepares to cross a bridge             *\n *   IPXManagerClass::Set_Socket -- sets socket ID for all connections\t\t*\n *   IPXManagerClass::Response_Time -- Returns largest Avg Response Time   *\n *   IPXManagerClass::Global_Response_Time -- Returns Avg Response Time    *\n *   IPXManagerClass::Reset_Response_Time -- Reset response time \t\t\t\t*\n *   IPXManagerClass::Oldest_Send -- gets ptr to oldest send buf           *\n *   IPXManagerClass::Mono_Debug_Print -- debug output routine\t\t\t\t\t*\n *   IPXManagerClass::Alloc_RealMode_Mem -- allocates real-mode memory\t\t*\n *   IPXManagerClass::Free_RealMode_Mem -- frees real-mode memory\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include <stdio.h>\n#include <mem.h>\n#include <i86.h>\n#include \"ipxmgr.h\"\n#include \"wwlib32.h\"\t// to enable mono output\n\n#ifdef WINSOCK_IPX\n\n#include \"WSProto.h\"\n#include \"WSPIPX.h\"\n\n#else\t//WINSOCK_IPX\n\n#include \"ipx95.h\"\n#ifdef WIN32\n#include \"tcpip.h\"\n#else\n#include\t\"fakesock.h\"\n#endif\t//WIN32\n\n#endif\t//WINSOCK_IPX\n\n// Turn off \"expression is not meaningful\".\n#pragma warning 628 9\n\n#include \"WolDebug.h\"\n\n/***************************************************************************\n * IPXManagerClass::IPXManagerClass -- class constructor                   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tglb_maxlen\t\tGlobal Channel maximum packet length\t\t\t\t\t\t*\n *\t\tpvt_maxlen\t\tPrivate Channel maximum packet length\t\t\t\t\t\t*\n *\t\tsocket\t\t\tsocket ID to use\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tproduct_id\t\ta unique numerical ID for this product\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tThe socket number is byte-swapped, since IPX requires socket ID's\t\t*\n *\t\tto be stored high/low.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nIPXManagerClass::IPXManagerClass (int glb_maxlen, int pvt_maxlen,\n\tint glb_num_packets, int pvt_num_packets, unsigned short socket,\n\tunsigned short product_id)\n{\n\tint i;\n#ifdef WINSOCK_IPX\n\t/*\n\t** Find out if Packet protocol services are available through Winsock.\n\t*/\n\tif ( PacketTransport ) {\n\t\tdelete  PacketTransport;\n\t\tPacketTransport = NULL;\n\t}\n\tPacketTransport = new WinsockInterfaceClass;\n\tassert ( PacketTransport != NULL );\n\n\tif ( PacketTransport->Init() ){\n\t\tIPXStatus = 1;\n\t}else{\n\t\tIPXStatus = 0;\n\t}\n\tdelete PacketTransport;\n\tPacketTransport = NULL;\n\n#else\t//WINSOCK_IPX\n\n\t//------------------------------------------------------------------------\n\t//\tInitialize data members\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tIPXStatus = 1 if IPX is installed, 0 if not\n\t//........................................................................\n\tif (IPX_SPX_Installed()==0) {\n\t\tIPXStatus = 0;\n\t}\n\telse {\n\t\tIPXStatus = 1;\n\t}\n#endif\t//WINSOCK_IPX\n\n\t//........................................................................\n\t//\tSet listening state flag to off\n\t//........................................................................\n\tListening = 0;\n\n\t//........................................................................\n\t//\tNo memory has been alloc'd yet\n\t//........................................................................\n\tRealMemAllocd = 0;\n\n\t//........................................................................\n\t//\tSet max packet sizes, for allocating real-mode memory\n\t//........................................................................\n\tGlb_MaxPacketLen = glb_maxlen;\n\tGlb_NumPackets = glb_num_packets;\n\tPvt_MaxPacketLen = pvt_maxlen;\n\tPvt_NumPackets = pvt_num_packets;\n\n\t//........................................................................\n\t//\tSave the app's product ID\n\t//........................................................................\n\tProductID = product_id;\n\n\t//........................................................................\n\t//\tSave our socket ID number\n\t//........................................................................\n\tSocket = (unsigned short)( (((unsigned long)socket & 0x00ff) << 8) |\n\t\t(((unsigned long)socket & 0xff00) >> 8));\n\n\t//------------------------------------------------------------------------\n\t//\tGet the user's IPX local connection number\n\t//------------------------------------------------------------------------\n\tConnectionNum = 0;\n#ifndef WINSOCK_IPX\n\tif (IPXStatus) {\n\t\tConnectionNum = IPX_Get_Connection_Number();\n\t}\n#endif\t//WINSOCK_IPX\n\n\t//------------------------------------------------------------------------\n\t//\tInit connection states\n\t//------------------------------------------------------------------------\n\tNumConnections = 0;\n\tCurConnection = 0;\n\tfor (i = 0; i < CONNECT_MAX; i++) {\n\t\tConnection[i] = 0;\n\t}\n\tGlobalChannel = 0;\n\n\tSendOverflows = 0;\n\tReceiveOverflows = 0;\n\tBadConnection = CONNECTION_NONE;\n\n\t//------------------------------------------------------------------------\n\t//\tInit timing parameters\n\t//------------------------------------------------------------------------\n\tRetryDelta = 2;\t\t// 2 ticks between retries\n\tMaxRetries = -1;\t\t// disregard # retries\n\tTimeout = 60;\t\t\t// report bad connection after 1 second\n\n}\t/* end of IPXManagerClass */\n\n\n/***************************************************************************\n * IPXManagerClass::~IPXManagerClass -- class destructor                   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nIPXManagerClass::~IPXManagerClass()\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tStop all IPX events\n\t//------------------------------------------------------------------------\n\tif (Listening) {\n\t\tIPXConnClass::Stop_Listening();\n\t\tListening = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tFree all protected-mode memory\n\t//------------------------------------------------------------------------\n\tif (GlobalChannel) {\n\t\tdelete GlobalChannel;\n\t\tGlobalChannel = 0;\n\t}\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tdelete Connection[i];\n\t\tConnection[i] = 0;\n\t}\n\tNumConnections = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tFree all real-mode memory\n\t//------------------------------------------------------------------------\n\tif (RealMemAllocd) {\n\t\tFree_RealMode_Mem();\n\t\tRealMemAllocd = 0;\n\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n#ifdef WIN32\n#ifndef WINSOCK_IPX\n\tUnload_IPX_Dll();\n#endif\n#endif\n#endif\n}\t/* end of ~IPXManagerClass */\n\n\n/***************************************************************************\n * IPXManagerClass::Init -- initialization routine\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * This routine allocates memory, & initializes variables\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Init()\n{\n\tint i;\n\n\tif (Session.Type != GAME_INTERNET) {\n\n\t\t//------------------------------------------------------------------------\n\t\t//\tError if IPX not installed\n\t\t//------------------------------------------------------------------------\n\t\tif (!IPXStatus) {\n\t\t\treturn(0);\n\t\t}\n\n\t\t//------------------------------------------------------------------------\n\t\t//\tStop Listening\n\t\t//------------------------------------------------------------------------\n\t\tif (Listening) {\n\t\t\tIPXConnClass::Stop_Listening();\n\t\t\tListening = 0;\n\t\t}\n\n\t\t//------------------------------------------------------------------------\n\t\t//\tFree Real-mode memory\n\t\t//------------------------------------------------------------------------\n\t\tif (RealMemAllocd) {\n\t\t\tFree_RealMode_Mem();\n\t\t\tRealMemAllocd = 0;\n\t\t}\n\n\t} else {\n\t\t/*\n\t\t** Pretend IPX is available for Internet games whether it is or not\n\t\t*/\n\t\tIPXStatus = 1;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tFree protected-mode memory\n\t//------------------------------------------------------------------------\n\tif (GlobalChannel) {\n\t\tdelete GlobalChannel;\n\t\tGlobalChannel = 0;\n\t}\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tdelete Connection[i];\n\t\tConnection[i] = 0;\n\t}\n\tNumConnections = 0;\n\n\tif (Session.Type != GAME_INTERNET) {\n\t\t//------------------------------------------------------------------------\n\t\t//\tAllocate real-mode memory\n\t\t//------------------------------------------------------------------------\n\t\tif (!Alloc_RealMode_Mem()) return(0);\n\t\tRealMemAllocd = 1;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tAllocate the Global Channel\n\t//------------------------------------------------------------------------\n\tGlobalChannel = new IPXGlobalConnClass (Glb_NumPackets, Glb_NumPackets,\n\t\tGlb_MaxPacketLen, ProductID);\n\tif (!GlobalChannel) {\n\t\treturn(0);\n\t}\n\tGlobalChannel->Init();\n\tGlobalChannel->Set_Retry_Delta (RetryDelta);\n\tGlobalChannel->Set_Max_Retries (MaxRetries);\n\tGlobalChannel->Set_TimeOut (Timeout);\n\n\t//------------------------------------------------------------------------\n\t//\tConfigure the IPX Connections\n\t//------------------------------------------------------------------------\n\tIPXConnClass::Configure(Socket, ConnectionNum, ListenECB, SendECB,\n\t\tFirstHeaderBuf, SendHeader, FirstDataBuf, SendBuf, Handler, PacketLen);\n\n\t//------------------------------------------------------------------------\n\t//\tStart Listening\n\t//------------------------------------------------------------------------\n\tif (Session.Type != GAME_INTERNET) {\n\t\tif (!IPXConnClass::Start_Listening()) return(0);\n\t}\n\tListening = 1;\n\n\treturn(1);\n\n}\t/* end of Init */\n\n\n/***************************************************************************\n * IPXManagerClass::Is_IPX -- tells if IPX is installed or not\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = IPX is installed; 0 = isn't\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Is_IPX(void)\n{\n\treturn(IPXStatus);\n\n}\t/* end of Is_IPX */\n\n\n/***************************************************************************\n * IPXManagerClass::Set_Timing -- sets timing for all connections\t\t\t\t*\n *                                                                         *\n * This will set the timing parameters for all existing connections, and\t*\n * all connections created from now on.  This allows an application to\t\t*\n * measure the Response_Time while running, and adjust timing accordingly.\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tretrydelta\tvalue to set for retry delta \t\t\t\t\t\t\t\t\t\t*\n *\t\tmaxretries\tvalue to set for max # retries\t\t\t\t\t\t\t\t\t*\n *\t\ttimeout\t\tvalue to set for connection timeout\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/02/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXManagerClass::Set_Timing (unsigned long retrydelta,\n\tunsigned long maxretries, unsigned long timeout)\n{\n\tint i;\n\n\tRetryDelta = retrydelta;\n\tMaxRetries = maxretries;\n\tTimeout = timeout;\n\n\tif (GlobalChannel) {\n\t\tGlobalChannel->Set_Retry_Delta (RetryDelta);\n\t\tGlobalChannel->Set_Max_Retries (MaxRetries);\n\t\tGlobalChannel->Set_TimeOut (Timeout);\n\t}\n\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tConnection[i]->Set_Retry_Delta (RetryDelta);\n\t\tConnection[i]->Set_Max_Retries (MaxRetries);\n\t\tConnection[i]->Set_TimeOut (Timeout);\n\t}\n\n}\t/* end of Set_Timing */\n\n\n/***************************************************************************\n * IPXManagerClass::Create_Connection -- creates a new connection          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\t\t\tapplication-specific numerical ID for this connection\t\t*\n *\t\tnode\t\t\tptr to IPXNodeIDType (name & address)\t\t\t\t\t\t\t*\n *\t\taddress\t\tIPX address for this connection\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tNever create a connection with an 'id' of -1.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Create_Connection(int id, char *name,\n\tIPXAddressClass *address)\n{\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tError if no more room\n\t//------------------------------------------------------------------------\n\tif (NumConnections==CONNECT_MAX) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCreate new connection\n\t//------------------------------------------------------------------------\n\tConnection[NumConnections] = new IPXConnClass(Pvt_NumPackets,\n\t\tPvt_NumPackets, Pvt_MaxPacketLen, ProductID, address, id, name);\n\tif (!Connection[NumConnections]) {\n\t\treturn(0);\n\t}\n\n\tConnection[NumConnections]->Init ();\n\tConnection[NumConnections]->Set_Retry_Delta (RetryDelta);\n\tConnection[NumConnections]->Set_Max_Retries (MaxRetries);\n\tConnection[NumConnections]->Set_TimeOut (Timeout);\n\n\tNumConnections++;\n\n\treturn(1);\n\n}\t/* end of Create_Connection */\n\n\n/***************************************************************************\n * IPXManagerClass::Delete_Connection -- deletes a connection              *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\tID of connection to delete\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Delete_Connection(int id)\n{\n\tint i,j;\n\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tError if no connections to delete\n\t//------------------------------------------------------------------------\n\tif (NumConnections==0) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tLoop through all connections\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < NumConnections; i++) {\n\t\t//.....................................................................\n\t\t//\tIf a match, delete it\n\t\t//.....................................................................\n\t\tif (Connection[i]->ID==id) {\n\t\t\tdelete Connection[i];\n\n\t\t\t//..................................................................\n\t\t\t//\tMove array elements back one index\n\t\t\t//..................................................................\n\t\t\tfor (j = i; j < NumConnections - 1; j++) {\n\t\t\t\tConnection[j] = Connection[j+1];\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tAdjust counters\n\t\t\t//..................................................................\n\t\t\tNumConnections--;\n\t\t\tif (CurConnection >= NumConnections)\n\t\t\t\tCurConnection = 0;\n\t\t\treturn(1);\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNo match; error\n\t//------------------------------------------------------------------------\n\treturn(0);\n\n}\t/* end of Delete_Connection */\n\n\n/***************************************************************************\n * IPXManagerClass::Num_Connections -- gets the # of connections\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# of connections\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Num_Connections(void)\n{\n\treturn(NumConnections);\n\n}\t/* end of Num_Connections */\n\n\n/***************************************************************************\n * IPXManagerClass::Connection_ID -- gets the given connection's ID        *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\t\tindex of connection to retrieve\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tID for that connection, CONNECTION_NONE if invalid index\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Connection_ID(int index)\n{\n\tif (index >= 0 && index < NumConnections) {\n\t\treturn(Connection[index]->ID);\n\t}\n\telse {\n\t\treturn(CONNECTION_NONE);\n\t}\n}\t/* end of Connection_ID */\n\n\n/***************************************************************************\n * IPXManagerClass::Connection_Name -- retrieves name for given connection *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\tID of connection to get name of\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to connection's name, NULL if not found\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nchar *IPXManagerClass::Connection_Name(int id)\n{\n\tint i;\n\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tif (Connection[i]->ID==id) {\n\t\t\treturn(Connection[i]->Name);\n\t\t}\n\t}\n\n\treturn(NULL);\n\n}\t/* end of Connection_Name */\n\n\n/***************************************************************************\n * IPXManagerClass::Connection_Address -- retrieves connection's address\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\tID of connection to get address for\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tpointer to IXPAddressClass, NULL if not found\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nIPXAddressClass * IPXManagerClass::Connection_Address(int id)\n{\n\tint i;\n\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tif (Connection[i]->ID==id) {\n\t\t\treturn(&Connection[i]->Address);\n\t\t}\n\t}\n\n\treturn(NULL);\n\n}\t/* end of Connection_Address */\n\n\n/***************************************************************************\n * IPXManagerClass::Connection_Index -- gets given connection's index      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tID to retrieve index for\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tindex for this connection, CONNECTION_NONE if not found\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Connection_Index(int id)\n{\n\tint i;\n\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tif (Connection[i]->ID==id) {\n\t\t\treturn(i);\n\t\t}\n\t}\n\n\treturn(CONNECTION_NONE);\n\n}\t/* end of Connection_Index */\n\n\n/***************************************************************************\n * IPXManagerClass::Set_Connection_Parms -- sets connection's name & id\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\tconnection index\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tid\t\t\tnew connection ID\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tname\t\tnew connection name\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXManagerClass::Set_Connection_Parms(int index, int id, char *name)\n{\n\tif (index >= NumConnections)\n\t\treturn;\n\n\tConnection[index]->ID = id;\n\tstrcpy(Connection[index]->Name,name);\n\n}\t/* end of Set_Connection_Parms */\n\n\n/***************************************************************************\n * IPXManagerClass::Send_Global_Message -- sends a Global Message\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buf\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tack_req\t\t1 = ACK required; 0 = no ACK required\t\t\t\t\t\t\t*\n *\t\taddress\t\taddress to send to; NULL = broadcast\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Send_Global_Message(void *buf, int buflen,\n\tint ack_req, IPXAddressClass *address)\n{\n\tint rc;\n\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus || !Listening) return(0);\n\n\trc = GlobalChannel->Send_Packet (buf, buflen, address, ack_req);\n\tif (!rc) {\n\t\tSendOverflows++;\n\t}\n\n\treturn(rc);\n\n}\t/* end of Send_Global_Message */\n\n\n/***************************************************************************\n * IPXManagerClass::Get_Global_Message -- polls the Global Message queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\t\tbuffer to store received packet\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\t\tlength of data placed in 'buf'\t\t\t\t\t\t\t\t*\n *\t\taddress\t\t\tIPX address of sender\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tproduct_id\t\tproduct ID of sender\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Get_Global_Message(void *buf, int *buflen,\n\tIPXAddressClass *address, unsigned short *product_id)\n{\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus || !Listening) return(0);\n\n\treturn(GlobalChannel->Get_Packet (buf, buflen, address, product_id));\n\n}\t/* end of Get_Global_Message */\n\n\n/***************************************************************************\n * IPXManagerClass::Send_Private_Message -- Sends a Private Message\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of 'buf'\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tconn_id\t\tconnection ID to send to (CONNECTION_NONE = all)\t\t\t*\n *\t\tack_req\t\t1 = ACK required; 0 = no ACK required\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Send_Private_Message(void *buf, int buflen, int ack_req,\n\tint conn_id)\n{\n\tint i;\t\t\t\t\t\t// loop counter\n\tint connect_idx;\t\t\t// index of channel to send to, if specified\n\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\n\tif (!IPXStatus || !Listening || (NumConnections==0)) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSend the message to all connections\n\t//------------------------------------------------------------------------\n\tif (conn_id==CONNECTION_NONE) {\n\t\t//.....................................................................\n\t\t//\tCheck for room in all connections\n\t\t//.....................................................................\n\t\tfor (i = 0; i < NumConnections; i++) {\n\t\t\tif (Connection[i]->Queue->Num_Send() ==\n\t\t\t\tConnection[i]->Queue->Max_Send()) {\n\t\t\t\tSendOverflows++;\n\t\t\t\treturn(0);\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tSend packet to all connections\n\t\t//.....................................................................\n\t\tfor (i = 0; i < NumConnections; i++) {\n\t\t\tConnection[i]->Send_Packet (buf, buflen, ack_req);\n\t\t}\n\t\treturn(1);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSend the message to the specified connection\n\t//------------------------------------------------------------------------\n\telse {\n\t\tconnect_idx = Connection_Index (conn_id);\n\t\tif (connect_idx == CONNECTION_NONE) {\n\t\t\tSendOverflows++;\n\t\t\treturn(0);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tCheck for room in the connection\n\t\t//.....................................................................\n\t\tif (Connection[connect_idx]->Queue->Num_Send() ==\n\t\t\tConnection[connect_idx]->Queue->Max_Send()) {\n\t\t\tSendOverflows++;\n\t\t\treturn(0);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tSend the packet to that connection\n\t\t//.....................................................................\n\t\tConnection[connect_idx]->Send_Packet (buf, buflen, ack_req);\n\t\treturn(1);\n\t}\n\n}\t/* end of Send_Private_Message */\n\n\n/***************************************************************************\n * IPXManagerClass::Get_Private_Message -- Polls the Private Message queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to store incoming packet\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of data placed in 'buf'\t\t\t\t\t\t\t\t\t*\n *\t\tconn_id\t\tfilled in with connection ID of sender\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Get_Private_Message(void *buf, int *buflen, int *conn_id)\n{\n\tint i;\n\tint rc;\n\tint c_id;\n\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus || !Listening || (NumConnections==0)) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSafety check: ensure CurConnection is in range.\n\t//------------------------------------------------------------------------\n\tif (CurConnection >= NumConnections) {\n\t\tCurConnection = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tScan all connections for a received packet, starting with 'CurConnection'\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < NumConnections; i++) {\n\n\t\t//.....................................................................\n\t\t//\tCheck this connection for a packet\n\t\t//.....................................................................\n\t\trc = Connection[CurConnection]->Get_Packet (buf, buflen);\n\t\tc_id = Connection[CurConnection]->ID;\n\n\t\t//.....................................................................\n\t\t//\tIncrement CurConnection to the next connection index\n\t\t//.....................................................................\n\t\tCurConnection++;\n\t\tif (CurConnection >= NumConnections) {\n\t\t\tCurConnection = 0;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tIf we got a packet, return the connection ID\n\t\t//.....................................................................\n\t\tif (rc) {\n\t\t\t(*conn_id) = c_id;\n\t\t\treturn(1);\n\t\t}\n\t}\n\n\treturn(0);\n\n}\t/* end of Get_Private_Message */\n\n\n/***************************************************************************\n * IPXManagerClass::Service -- main polling routine for IPX Connections\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Service(void)\n{\n\tint rc = 1;\n\tint i;\n\tCommHeaderType *packet;\n\tint packetlen;\n\tIPXAddressClass address;\n\n#ifdef WINSOCK_IPX\n\n\n\tunsigned char temp_receive_buffer[1024];\n\tint\ttemp_receive_buffer_len;\n\tint\ttemp_address_len;\n\n\n\tchar temp_address [128];\n\n\tif ( PacketTransport ) {\n\n\t\tdo {\n\t\t\ttemp_receive_buffer_len = sizeof (temp_receive_buffer);\n\t\t\ttemp_address_len = sizeof (temp_address);\n\t\t\tpacketlen = PacketTransport->Read ( temp_receive_buffer, temp_receive_buffer_len, temp_address, temp_address_len );\n\t\t\tif ( packetlen ) {\n\t\t\t\tCurDataBuf = (char*)temp_receive_buffer;\n\t\t\t\taddress = *((IPXAddressClass*) temp_address);\n\n\t\t\t\tpacket = (CommHeaderType *)CurDataBuf;\n\t\t\t\tif (packet->MagicNumber == GlobalChannel->Magic_Num()) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Put the packet in the Global Queue\n\t\t\t\t\t*/\n\t\t\t\t\tif (!GlobalChannel->Receive_Packet (packet, packetlen, &address))\n\t\t\t\t\t\tReceiveOverflows++;\n\t\t\t\t} else {\n\t\t\t\t\tif (packet->MagicNumber == ProductID) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Find the Private Queue that this packet is for\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tbool found_address = false;\n\t\t\t\t\t\tfor (i = 0; i < NumConnections; i++) {\n\t\t\t\t\t\t\tif (Connection[i]->Address == address) {\n\t\t\t\t\t\t\t\tfound_address = true;\n\t\t\t\t\t\t\t\tif (!Connection[i]->Receive_Packet (packet, packetlen))\n\t\t\t\t\t\t\t\t\tReceiveOverflows++;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif( Session.Type == GAME_INTERNET )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** This packet came from an unknown source. If it looks like one of our players\n\t\t\t\t\t\t\t** packets then it might be from a player whos IP has changed.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (!found_address) {\n\t\t\t\t\t\t\t\tif (packet->Code == ConnectionClass::PACKET_DATA_NOACK){\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t** Magic number and packet code are valid. It's probably a C&C packet.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tEventClass *event = (EventClass*) (((char*) packet) + sizeof (CommHeaderType));\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t** If this is a framesync packet then grab the address and match it to an existing player.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tif (event->Type == EventClass::FRAMESYNC) {\n\t\t\t\t\t\t\t\t\t\tint id = event->ID;\n\n\t\t\t\t\t\t\t\t\t\tassert (id != PlayerPtr->ID);\n\t\t\t\t\t\t\t\t\t\tfor ( int i=1 ; i<Session.Players.Count() ; i++) {\n\t\t\t\t\t\t\t\t\t\t\tif (Session.Players[i]->Player.ID == id) {\n\n\t\t\t\t\t\t\t\t\t\t\t\tint iConnectionIndex = Connection_Index(id);\n\t\t\t\t\t\t\t\t\t\t\t\tif( iConnectionIndex != CONNECTION_NONE ) //\t(else Create_Connections() has not yet been called)\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t\t\t\t** Found a likely candidate. Update his address. It should be OK to drop this\n\t\t\t\t\t\t\t\t\t\t\t\t\t** packet since it's a framesync packet and will will pick up the next one.\n\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\t\t\t\tSession.Players[i]->Address = address;\n\t\t\t\t\t\t\t\t\t\t\t\t\tConnection[iConnectionIndex]->Address = address;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t} while (packetlen);\n\n\t}\n\n\n\n\n#else\t//WINSOCK_IPX\n\n#ifdef WIN32\n\n\tunsigned char temp_receive_buffer[1024];\n\tint\trecv_length;\n\n\tif (Winsock.Get_Connected() || Special.IsFromWChat) {\n\n\t\tif (!Winsock.Get_Connected()) return (0);\n\n\t\t/*\n\t\t** This is an internet connection so get the packets from winsock\n\t\t*/\n\t\twhile ((recv_length = Winsock.Read(temp_receive_buffer, 1024))!=0) {\n\n\t\t\tCurHeaderBuf = NULL;\n\t\t\tCurDataBuf = (char*)&temp_receive_buffer[0];\n\n\t\t\t/*.....................................................................\n\t\t\tCompute the length of the packet (byte-swap the length in the IPX hdr)\n\t\t\t.....................................................................*/\n\t\t\tpacketlen = recv_length;\n\n\t\t\t/*.....................................................................\n\t\t\tExtract the sender's address from the IPX header\n\t\t\t.....................................................................*/\n\t\t\taddress.Set_Address (CurHeaderBuf);\n\n\t\t\t/*.....................................................................\n\t\t\tExamine the Magic Number of the received packet to determine if this\n\t\t\tpacket goes into the Global Queue, or into one of the Private Queues\n\t\t\t.....................................................................*/\n\t\t\tpacket = (CommHeaderType *)CurDataBuf;\n\t\t\tif (packet->MagicNumber == GlobalChannel->Magic_Num()) {\n\t\t\t\t/*..................................................................\n\t\t\t\tPut the packet in the Global Queue\n\t\t\t\t..................................................................*/\n\t\t\t\tif (!GlobalChannel->Receive_Packet (packet, packetlen, &address))\n\t\t\t\t\tReceiveOverflows++;\n\t\t\t} else {\n\t\t\t\tif (packet->MagicNumber == ProductID) {\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tFind the Private Queue that this packet is for\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tfor (i = 0; i < NumConnections; i++) {\n\t\t\t\t\t\tif (Connection[i]->Address == address) {\n\t\t\t\t\t\t\tif (!Connection[i]->Receive_Packet (packet, packetlen))\n\t\t\t\t\t\t\t\tReceiveOverflows++;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t} else {\n\n\t\twhile (IPX_Get_Outstanding_Buffer95(&temp_receive_buffer[0])) {\n\n\t\t\tCurHeaderBuf = (IPXHEADER*)&temp_receive_buffer[0];\n\t\t\tCurDataBuf = (char*)&temp_receive_buffer[sizeof(IPXHeaderType)];\n\n\t\t\t/*.....................................................................\n\t\t\tCompute the length of the packet (byte-swap the length in the IPX hdr)\n\t\t\t.....................................................................*/\n\t\t\tpacketlen = ((CurHeaderBuf->Length & 0xff) << 8) |\n\t\t\t\t(CurHeaderBuf->Length >> 8);\n\t\t\tpacketlen -= sizeof(IPXHeaderType);\n\n\t\t\t/*.....................................................................\n\t\t\tExtract the sender's address from the IPX header\n\t\t\t.....................................................................*/\n\t\t\taddress.Set_Address (CurHeaderBuf);\n\n\t\t\t/*.....................................................................\n\t\t\tExamine the Magic Number of the received packet to determine if this\n\t\t\tpacket goes into the Global Queue, or into one of the Private Queues\n\t\t\t.....................................................................*/\n\t\t\tpacket = (CommHeaderType *)CurDataBuf;\n\t\t\tif (packet->MagicNumber == GlobalChannel->Magic_Num()) {\n\t\t\t\t/*..................................................................\n\t\t\t\tPut the packet in the Global Queue\n\t\t\t\t..................................................................*/\n\t\t\t\tif (!GlobalChannel->Receive_Packet (packet, packetlen, &address))\n\t\t\t\t\tReceiveOverflows++;\n\t\t\t} else {\n\t\t\t\tif (packet->MagicNumber == ProductID) {\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tFind the Private Queue that this packet is for\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tfor (i = 0; i < NumConnections; i++) {\n\t\t\t\t\t\tif (Connection[i]->Address == address) {\n\t\t\t\t\t\t\tif (!Connection[i]->Receive_Packet (packet, packetlen))\n\t\t\t\t\t\t\t\tReceiveOverflows++;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n#else\t//WIN32\n\n\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus || !Listening) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tLoop until there are no more packets to process.\n\t//------------------------------------------------------------------------\n\twhile (1) {\n\n\t\t//.....................................................................\n\t\t//\tCheck the BufferFlags for the \"current\" buffer; if it's empty,\n\t\t//\tbreak; out of the loop.\n\t\t//.....................................................................\n\t\tif (BufferFlags[CurIndex]==0) {\n\t\t\tbreak;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tCompute the length of the packet (byte-swap the length in the IPX hdr)\n\t\t//.....................................................................\n\t\tpacketlen = ((CurHeaderBuf->Length & 0xff) << 8) |\n\t\t\t(CurHeaderBuf->Length >> 8);\n\t\tpacketlen -= sizeof(IPXHeaderType);\n\n\t\t//.....................................................................\n\t\t//\tExtract the sender's address from the IPX header\n\t\t//.....................................................................\n\t\taddress.Set_Address (CurHeaderBuf);\n\n\t\t//.....................................................................\n\t\t//\tExamine the Magic Number of the received packet to determine if this\n\t\t//\tpacket goes into the Global Queue, or into one of the Private Queues\n\t\t//.....................................................................\n\t\tpacket = (CommHeaderType *)CurDataBuf;\n\t\tif (packet->MagicNumber == GlobalChannel->Magic_Num()) {\n\n\t\t\t//..................................................................\n\t\t\t//\tPut the packet in the Global Queue\n\t\t\t//..................................................................\n\t\t\tif (!GlobalChannel->Receive_Packet (packet, packetlen, &address)) {\n\t\t\t\tReceiveOverflows++;\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tFind the Private Queue that this packet is for\n\t\t//.....................................................................\n\t\telse if (packet->MagicNumber == ProductID) {\n\t\t\tfor (i = 0; i < NumConnections; i++) {\n\t\t\t\tif (Connection[i]->Address == address) {\n\t\t\t\t\tif (!Connection[i]->Receive_Packet (packet, packetlen)) {\n\t\t\t\t\t\tReceiveOverflows++;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tSet the current BufferFlags to 0 (since we've cleaned out this buffer)\n\t\t//.....................................................................\n\t\tBufferFlags[CurIndex] = 0;\n\n\t\t//.....................................................................\n\t\t//\tGo to the next packet buffer\n\t\t//.....................................................................\n\t\tCurIndex++;\n\t\tCurHeaderBuf = (IPXHeaderType *)(((char *)CurHeaderBuf) + FullPacketLen);\n\t\tCurDataBuf = ((char *)CurDataBuf) + FullPacketLen;\n\t\tif (CurIndex >= NumBufs) {\n\t\t\tCurHeaderBuf = FirstHeaderBuf;\n\t\t\tCurDataBuf = FirstDataBuf;\n\t\t\tCurIndex = 0;\n\t\t}\n\t}\n\n#endif\t//WIN32\n#endif\t//WINSOCK_IPX\n\n\t//------------------------------------------------------------------------\n\t//\tService all connections.  If a connection reports that it's gone \"bad\",\n\t//\treport an error to the caller.  If it's the Global Channel, un-queue the\n\t//\tsend entry that's holding things up.  This will keep the Global Channel\n\t//\tfrom being clogged by one un-ACK'd outgoing packet.\n\t//------------------------------------------------------------------------\n\tif (GlobalChannel) {\n\t\tif (!GlobalChannel->Service()) {\n\t\t\tGlobalChannel->Queue->UnQueue_Send (NULL, NULL, 0);\n\t\t\trc = 0;\n\t\t}\n\t}\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tif (!Connection[i]->Service()) {\n\t\t\trc = 0;\n\t\t\tBadConnection = Connection[i]->ID;\n\t\t}\n\t}\n\n\tif (rc) {\n\t\tBadConnection = CONNECTION_NONE;\n\t}\n\n\treturn(rc);\n\n}\t/* end of Service */\n\n/***************************************************************************\n * IPXManagerClass::Get_Bad_Connection -- returns bad connection ID        *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tID of bad connection; CONNECTION_NONE if none.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nint IPXManagerClass::Get_Bad_Connection(void)\n{\n\treturn(BadConnection);\n\n}\t/* end of Get_Bad_Connection */\n\n\n/***************************************************************************\n * IPXManagerClass::Global_Num_Send\t-- reports # entries in send queue\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# entries in the Global Send Queue\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Global_Num_Send(void)\n{\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus || !Listening) {\n\t\treturn(0);\n\t}\n\n\treturn(GlobalChannel->Queue->Num_Send());\n\n}\t/* end of Global_Num_Send */\n\n\n/***************************************************************************\n * IPXManagerClass::Global_Num_Receive -- reports # entries in recv queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# entries in the Global Receive Queue\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Global_Num_Receive(void)\n{\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus || !Listening) {\n\t\treturn(0);\n\t}\n\n\treturn(GlobalChannel->Queue->Num_Receive());\n\n}\t/* end of Global_Num_Receive */\n\n\n/***************************************************************************\n * IPXManagerClass::Private_Num_Send -- reports # entries in send queue\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\t# entries in the Private Send Queue\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Private_Num_Send(int id)\n{\n\tint i;\n\tint maxnum;\n\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus || !Listening || (NumConnections==0)) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tIf connection ID specified, return that connection's # of packets\n\t//------------------------------------------------------------------------\n\tif (id != CONNECTION_NONE) {\n\t\ti = Connection_Index(id);\n\t\tif (i != CONNECTION_NONE) {\n\t\t\treturn(Connection[i]->Queue->Num_Send());\n\t\t}\n\t\telse {\n\t\t\treturn(0);\n\t\t}\n\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tOtherwise, return the max # of all connections\n\t//------------------------------------------------------------------------\n\telse {\n\t\tmaxnum = 0;\n\t\tfor (i = 0; i < NumConnections; i++) {\n\t\t\tif (Connection[i]->Queue->Num_Send() > maxnum) {\n\t\t\t\tmaxnum = Connection[i]->Queue->Num_Send();\n\t\t\t}\n\t\t}\n\t\treturn(maxnum);\n\t}\n\n}\t/* end of Private_Num_Send */\n\n\n/***************************************************************************\n * IPXManagerClass::Private_Num_Receive -- reports # entries in recv queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\tID of connection to query\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# entries in the Private Receive Queue\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Private_Num_Receive(int id)\n{\n\tint i;\n\tint maxnum;\n\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus || !Listening || (NumConnections==0))\n\t\treturn(0);\n\n\t//------------------------------------------------------------------------\n\t//\tIf connection ID specified, return that connection's # of packets\n\t//------------------------------------------------------------------------\n\tif (id != CONNECTION_NONE) {\n\t\ti = Connection_Index(id);\n\t\tif (i != CONNECTION_NONE) {\n\t\t\treturn(Connection[i]->Queue->Num_Receive());\n\t\t}\n\t\telse {\n\t\t\treturn(0);\n\t\t}\n\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tOtherwise, return the max # of all connections\n\t//------------------------------------------------------------------------\n\telse {\n\t\tmaxnum = 0;\n\t\tfor (i = 0; i < NumConnections; i++) {\n\t\t\tif (Connection[i]->Queue->Num_Receive() > maxnum) {\n\t\t\t\tmaxnum = Connection[i]->Queue->Num_Receive();\n\t\t\t}\n\t\t}\n\t\treturn(maxnum);\n\t}\n\n}\t/* end of Private_Num_Receive */\n\n\n/***************************************************************************\n * IPXManagerClass::Set_Socket -- sets socket ID for all connections\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsocket\tnew socket ID to use\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tDo not call this function after communications have started; you\t\t*\n *\t\tmust call it before calling Init().\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tThe socket number is byte-swapped, since IPX requires socket ID's\t\t*\n *\t\tto be stored high/low.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXManagerClass::Set_Socket(unsigned short socket)\n{\n\tSocket = (unsigned short)( (((unsigned long)socket & 0x00ff) << 8) |\n\t\t(((unsigned long)socket & 0xff00) >> 8));\n\n}\t/* end of Set_Socket */\n\n\n/***************************************************************************\n * IPXManagerClass::Response_Time -- Returns largest Avg Response Time     *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tlargest avg response time\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nunsigned long IPXManagerClass::Response_Time(void)\n{\n\tunsigned long resp;\n\tunsigned long maxresp = 0;\n\tint i;\n\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tresp = Connection[i]->Queue->Avg_Response_Time();\n\t\tif (resp > maxresp) {\n\t\t\tmaxresp = resp;\n\t\t}\n\t}\n\n\treturn(maxresp);\n\n}\t/* end of Response_Time */\n\n\n/***************************************************************************\n * IPXManagerClass::Global_Response_Time -- Returns Avg Response Time      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tavg global channel response time\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nunsigned long IPXManagerClass::Global_Response_Time(void)\n{\n\tif (GlobalChannel) {\n\t\treturn (GlobalChannel->Queue->Avg_Response_Time());\n\t}\n\telse {\n\t\treturn (0);\n\t}\n\n}\t/* end of Global_Response_Time */\n\n\n/***************************************************************************\n * IPXManagerClass::Reset_Response_Time -- Reset response time\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid IPXManagerClass::Reset_Response_Time(void)\n{\n\tint i;\n\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tConnection[i]->Queue->Reset_Response_Time();\n\t}\n\n\tif (GlobalChannel)\n\t\tGlobalChannel->Queue->Reset_Response_Time();\n\n}\t/* end of Reset_Response_Time */\n\n\n/***************************************************************************\n * IPXManagerClass::Oldest_Send -- gets ptr to oldest send buf             *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tbuf ptr\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid * IPXManagerClass::Oldest_Send(void)\n{\n\tint i,j;\n\tunsigned long time;\n\tunsigned long mintime = 0xffffffff;\n\tSendQueueType *send_entry;\t\t\t\t// ptr to send entry header\n\tCommHeaderType *packet;\n\tvoid *buf = NULL;\n\n\tfor (i = 0; i < NumConnections; i++) {\n\n\t\tsend_entry = NULL;\n\n\t\tfor (j = 0; j < Connection[i]->Queue->Num_Send(); j++) {\n\t\t\tsend_entry = Connection[i]->Queue->Get_Send(j);\n\t\t\tif (send_entry) {\n\t\t\t\tpacket = (CommHeaderType *)send_entry->Buffer;\n\t\t\t\tif (packet->Code == ConnectionClass::PACKET_DATA_ACK &&\n\t\t\t\t\tsend_entry->IsACK == 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsend_entry = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (send_entry!=NULL) {\n\n\t\t\ttime = send_entry->FirstTime;\n\n\t\t\tif (time < mintime) {\n\t\t\t\tmintime = time;\n\t\t\t\tbuf = send_entry->Buffer;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(buf);\n\n}\t/* end of Oldest_Send */\n\n\n/***************************************************************************\n * IPXManagerClass::Set_Bridge -- prepares to cross a bridge               *\n *                                                                         *\n * This routine is designed to prevent the connection from having to\t\t\t*\n * call Get_Local_Target, except the minimum number of times, since that\t*\n * routine is buggy & goes away for long periods sometimes.\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbridge\t\tnetwork number of the destination bridge\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/06/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid IPXManagerClass::Set_Bridge(NetNumType bridge)\n{\n\tif (GlobalChannel) {\n\t\tGlobalChannel->Set_Bridge(bridge);\n\t}\n\n}\t/* end of Set_Bridge */\n\n\n/***************************************************************************\n * IPXManagerClass::Configure_Debug -- sets up special debug values        *\n *                                                                         *\n * Mono_Debug_Print2() can look into a packet to pull out a particular\t\t*\n * ID, and can print both that ID and a string corresponding to\t\t\t\t*\n * that ID.  This routine configures these values so it can find\t\t\t\t*\n * and decode the ID.  This ID is used in addition to the normal\t\t\t\t*\n * CommHeaderType values.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\t\t\tconnection index to configure (-1 = Global Channel)\t*\n *\t\ttype_offset\t\tID's byte offset into packet\t\t\t\t\t\t\t\t\t*\n *\t\ttype_size\t\tsize of ID, in bytes; 0 if none\t\t\t\t\t\t\t\t*\n *\t\tnames\t\t\t\tptr to array of names; use ID as an index into this\t*\n *\t\tnamestart\t\tnumerical value of 1st name in the array\t\t\t\t\t*\n *\t\tnamecount\t\t# in the names array; 0 if none.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tNames shouldn't be longer than 12 characters.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/31/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid IPXManagerClass::Configure_Debug(int index, int type_offset,\n\tint type_size, char **names, int namestart, int namecount)\n{\n\tif (index == -1) {\n\t\tGlobalChannel->Queue->Configure_Debug (type_offset, type_size, names,\n\t\t\tnamestart, namecount);\n\t}\n\telse if (Connection[index]) {\n\t\tConnection[index]->Queue->Configure_Debug (type_offset, type_size, names,\n\t\t\tnamestart, namecount);\n\t}\n\n}\t/* end of Configure_Debug */\n\n\n/***************************************************************************\n * IPXManagerClass::Mono_Debug_Print -- debug output routine\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\t\tindex of connection to display (-1 = Global Channel)\t\t*\n *\t\trefresh\t\t1 = complete screen refresh\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXManagerClass::Mono_Debug_Print(int index, int refresh)\n{\n#ifdef WWLIB32_H\n\tchar txt[80];\n\tint i;\n\n\tif (index == -1)\n\t\tGlobalChannel->Queue->Mono_Debug_Print (refresh);\n\n\telse if (Connection[index])\n\t\tConnection[index]->Queue->Mono_Debug_Print (refresh);\n\n\tif (refresh) {\n\t\tMono_Set_Cursor (20,1);\n\t\tMono_Printf (\"IPX Queue:\");\n\n\t\tMono_Set_Cursor (9,2);\n\t\tMono_Printf (\"Average Response Time:\");\n\n\t\tMono_Set_Cursor (43,1);\n\t\tMono_Printf (\"Send Overflows:\");\n\n\t\tMono_Set_Cursor (40,2);\n\t\tMono_Printf (\"Receive Overflows:\");\n\n\t}\n\n\tMono_Set_Cursor (32,1);\n\tMono_Printf (\"%d\",index);\n\n\tMono_Set_Cursor (32,2);\n\tif (index == -1) {\n\t\tMono_Printf (\"%d  \", GlobalChannel->Queue->Avg_Response_Time());\n\t}\n\telse {\n\t\tMono_Printf (\"%d  \", Connection[index]->Queue->Avg_Response_Time());\n\t}\n\n\tMono_Set_Cursor (59,1);\n\tMono_Printf (\"%d  \", SendOverflows);\n\n\tMono_Set_Cursor (59,2);\n\tMono_Printf (\"%d  \", ReceiveOverflows);\n\n\tfor (i = 0; i < NumBufs; i++) {\n\t\tif (BufferFlags[i]) {\n\t\t\ttxt[i] = 'X';\n\t\t}\n\t\telse {\n\t\t\ttxt[i] = '_';\n\t\t}\n\t}\n\ttxt[i] = 0;\n\tMono_Set_Cursor ((80-NumBufs)/2,3);\n\tMono_Printf (\"%s\",txt);\n\n#else\n\tindex = index;\n\trefresh = refresh;\n#endif\n\n}\t/* end of Mono_Debug_Print */\n\n\n/***************************************************************************\n * IPXManagerClass::Alloc_RealMode_Mem -- allocates real-mode memory\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Alloc_RealMode_Mem(void)\n{\n\n#ifdef WIN32\n\treturn (1);\n#else\n\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tint size;\t\t\t\t\t\t\t\t\t// required size of allocation\n\tunsigned char *realmode;\t\t\t\t// start addresses of real-mode data\n\tint realmodelen;\t\t\t\t\t\t\t// length of real-mode data\n\tunsigned long func_val;\n\tchar *p;\t\t\t\t\t\t\t\t\t\t// for parsing buffer\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tCompute # of buffers we need to allocate, & the max size of each one\n\t//------------------------------------------------------------------------\n\tNumBufs = Glb_NumPackets + (Pvt_NumPackets * CONNECT_MAX);\n\n\tPacketLen = Glb_MaxPacketLen + sizeof (GlobalHeaderType);\n\tif (Pvt_MaxPacketLen + sizeof (CommHeaderType) > PacketLen)\n\t\tPacketLen = Pvt_MaxPacketLen + sizeof (CommHeaderType);\n\n\tFullPacketLen = PacketLen + sizeof(IPXHeaderType);\n\n\t//------------------------------------------------------------------------\n\t//\tCompute the size of everything we'll ever need, allocate it in one big\n\t//\tchunk.  The memory is used as follows:\n\t//\t- Real-mode assembly IPX callback routine, plus its data,\n\t//\t  (which includes the ListenECB)\n\t//\t- Array of IPX Packet buffers (IPXHeader plus data buffer)\n\t//\t- SendECB: ECB for sending\n\t//\t- SendHeader: IPX Header for sending\n\t//\t- SendBuf: Packet buffer for sending\n\t//\t- BufferFlags: 1 byte for each incoming packet buffer; 1=in use, 0=free\n\t//------------------------------------------------------------------------\n\trealmode = (unsigned char *)Get_RM_IPX_Address();\n\trealmodelen = Get_RM_IPX_Size();\n\tsize = realmodelen + \t\t\t\t// assembly routine & its data\n\t\t(FullPacketLen * NumBufs) +\t// array of packet buffers\n\t\tsizeof(ECBType) +\t\t\t\t\t// SendECB\n\t\tFullPacketLen +\t\t\t\t\t// SendHeader & SendBuf\n\t\tNumBufs;\t\t\t\t\t\t\t\t// BufferFlags\n\tif (size > 65535) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tAllocate DOS memory for the ECB, IPXHeader & packet buffers:\n\t//\tAX = 0x100\n\t//\tBX = # paragraphs to allocate\n\t//\t- if Success, AX = real-mode segment, DX = selector\n\t//\t- if Failure, carry flag is set\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_ALLOC_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = ((size + 15) >> 4);\t\t\t\t\t\t// # paragraphs to allocate\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\t//------------------------------------------------------------------------\n\t//\tIf the carry flag is set, DPMI is indicating an error.\n\t//------------------------------------------------------------------------\n\tif (regs.x.cflag) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSave the values of the returned segment & selector\n\t//------------------------------------------------------------------------\n\tSelector = regs.w.dx;\n\tSegment = regs.w.ax;\n\tRealMemSize = size;\n\tRealModeData = (RealModeDataType *)(((long)Segment) << 4);\n\n\t//------------------------------------------------------------------------\n\t//\tLock the memory (since we're servicing interrupts with it)\n\t//\tAX = 0x600\n\t//\tBX:CX = starting linear address of memory to lock\n\t//\tSI:DI = size of region to lock (in bytes)\n\t//\t- If Failure, carry flag is set.\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_LOCK_MEM;\t\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = ((long)RealModeData & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)RealModeData & 0x0000ffff);\n\tregs.x.esi = ((long)RealMemSize & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)RealMemSize & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n\n\t//------------------------------------------------------------------------\n\t//\tIf the carry flag is set, DPMI is indicating an error.\n\t//------------------------------------------------------------------------\n\tif (regs.x.cflag) {\n\t\tmemset (&regs, 0 ,sizeof(regs));\n\t\tsegread (&sregs);\n\t\tregs.x.eax = DPMI_FREE_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\t\tregs.x.edx = Selector;\t\t\t\t\t\t\t\t\t// ptr to free\n\t\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// free the memory\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCopy the Real-mode code into our memory buffer\n\t//------------------------------------------------------------------------\n\tp = (char *)(((long)Segment) << 4);\n\tmemcpy (p,realmode,realmodelen);\n\tp += realmodelen;\n\n\t//------------------------------------------------------------------------\n\t//\tCompute & save the entry point for the real-mode packet handler\n\t//------------------------------------------------------------------------\n\tfunc_val = (unsigned long)RealModeData;\n\tHandler = (((func_val & 0xffff0) << 12) |\n\t\t((func_val & 0x000f) + RealModeData->FuncOffset));\n\n\t//------------------------------------------------------------------------\n\t//\tFill in buffer pointers\n\t//------------------------------------------------------------------------\n\tListenECB = &(RealModeData->ListenECB);\n\n\tFirstHeaderBuf = (IPXHeaderType *)p;\n\tFirstDataBuf = (((char *)FirstHeaderBuf) + sizeof(IPXHeaderType));\n\tCurIndex = 0;\n\tCurHeaderBuf = FirstHeaderBuf;\n\tCurDataBuf = FirstDataBuf;\n\tp += FullPacketLen * NumBufs;\n\n\tSendECB = (ECBType *)p;\n\tp += sizeof (ECBType);\n\n\tSendHeader = (IPXHeaderType *)p;\n\tp += sizeof (IPXHeaderType);\n\n\tSendBuf = (char *)p;\n\tp += PacketLen;\n\n\tBufferFlags = (char *)p;\n\n\t//------------------------------------------------------------------------\n\t//\tFill in the real-mode routine's data (The ECB will be filled in when we\n\t//\tcommand IPX to Listen).\n\t//------------------------------------------------------------------------\n\tRealModeData->NumBufs = (short)NumBufs;\n\tRealModeData->BufferFlags = (char *)\n\t\t((((long)BufferFlags & 0xffff0) << 12) |\n\t\t((long)BufferFlags & 0x0000f));\n\tRealModeData->PacketSize = (short)FullPacketLen;\n\tRealModeData->FirstPacketBuf = (IPXHeaderType *)\n\t\t((((long)FirstHeaderBuf & 0xffff0) << 12) |\n\t\t((long)FirstHeaderBuf & 0x0000f));\n\tRealModeData->CurIndex = 0;\n\tRealModeData->CurPacketBuf = RealModeData->FirstPacketBuf;\n\tRealModeData->Semaphore = 0;\n\tRealModeData->ReEntrantCount = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInit state of all buffers to empty\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < NumBufs; i++) {\n\t\tBufferFlags[i] = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCheck the start & end markers in the real-mode memory area\n\t//------------------------------------------------------------------------\n\tif (RealModeData->Marker1 != 0x1111 ||\n\t\tRealModeData->Marker2 != 0x2222) {\n\t\tFree_RealMode_Mem();\n\t\treturn(0);\n\t}\n\telse {\n\t\treturn(1);\n\t}\n#endif\t//WIN32\n}\t/* end of Alloc_Realmode_Mem */\n\n\n/***************************************************************************\n * IPXManagerClass::Free_RealMode_Mem -- frees real-mode memory\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Free_RealMode_Mem(void)\n{\n\n#ifdef WIN32\n\n\treturn (1);\n\n#else\t//WIN32\n\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tint rc = 1;\n\n\t//------------------------------------------------------------------------\n\t//\tUnlock the memory\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_UNLOCK_MEM;\t\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = ((long)RealModeData & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)RealModeData & 0x0000ffff);\n\tregs.x.esi = ((long)RealMemSize & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)RealMemSize & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n\n\t//------------------------------------------------------------------------\n\t//\tIf the carry flag is set, DPMI is indicating an error.\n\t//------------------------------------------------------------------------\n\tif (regs.x.cflag) {\n\t\trc = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tFree DOS memory\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_FREE_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.edx = Selector;\t\t\t\t\t\t\t\t\t// ptr to free\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// free the memory\n\n\treturn(rc);\n#endif\t//WIN32\n\n}\t/* end of Free_Realmode_Mem */\n\n/*************************** end of ipxmgr.cpp *****************************/\n"
  },
  {
    "path": "CODE/IPXMGR.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/IPXMGR.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPXMGR.H                                 *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 3, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This is the Connection Manager for IPX network communications.  It\t\t*\n * creates, manages, & orchestrates multiple IPX connections, as well as\t*\n * the \"global\" connection (\"Global Channel\"), which can talk to any \t\t*\n * system on the net.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Use the Global Channel to query systems for their names, ID's, &\t\t\t*\n * IPX addresses.  Then, create a Private Connection with each system\t\t*\n * that joins your game, and use the Private Channel to send game packets\t*\n * (the private channel will perform somewhat faster, & gives you better\t*\n * control than the Global Channel; it can detect retries, and the Global\t*\n * Channel can't).\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * HOW THIS CLASS WORKS:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This class has to set up an IPX Event Service Routine in low (DOS)\t\t*\n * memory.  So, it uses DPMI to allocate & lock a chunk of DOS memory;\t\t*\n * this memory is used for all incoming packet buffers, the outgoing\t\t\t*\n * packet buffer, and the actual code for the event handler.  The real-\t\t*\n * mode handler code & this class share a portion of memory that's mapped\t*\n * into a \"RealModeDataType\" structure.  As packets come in, the handler\t*\n * points IPX to the next available packet buffer & restarts listening;\t\t*\n * it sets a flag to tell this class that a packet is present at that\t\t*\n * buffer slot.  This class must read all the packets & determine which\t\t*\n * connection they go with (the Global Channel, or one of the Private\t\t*\n * Channels).  This parsing is done in the Service routine for this class.\t*\n * \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Constructor:\tJust inits some variables, checks to see if IPX is there\t*\n * Destructor:\t\tComplete shutdown; stops IPX listening, frees all memory\t*\n * Init:\t\t\t\tShould only be called once (but can be called more); \t\t*\n * \t\t\t\t\tallocates all memory, creates the Global Channel\t\t\t*\n * \t\t\t\t\tconnection, starts IPX listening.  By not placing this \t*\n * \t\t\t\t\tstep in the constructor, the app can control when \t\t\t*\n * \t\t\t\t\tlistening actually starts; also, you don't get a bunch\t*\n *\t\t\t\t\t\tof allocations just by declaring an IPXManagerClass\t\t*\n *\t\t\t\t\t\tinstance.  You have to call Init() for the allocations\t*\n *\t\t\t\t\t\tto occur.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Connection utilities: Create & manage Private Connections.  Each \t\t\t*\n *\t\t\t\t\t\tconnection has its own IPX address, numerical ID, and\t\t*\n *\t\t\t\t\t\tcharacter name (presumably the name of the other\t\t\t*\n *\t\t\t\t\t\tplayer).\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Send/Get_Global_Message: adds a packet to the Global Connection queue,\t*\n *\t\t\t\t\t\tor reads from the queue.  The caller should check the\t\t*\n *\t\t\t\t\t\tProductID value from returned packets to be sure it's\t\t*\n *\t\t\t\t\t\ttalking to the right product.\t\t\t\t\t\t\t\t\t\t*\n * Send/Get_Private_Message: adds a packet to a Private Connection queue,\t*\n *\t\t\t\t\t\tor reads from the queue\t\t\t\t\t\t\t\t\t\t\t\t*\n * Service:\t\t\tChecks the Real-Mode-Memory packet array to see if any\t*\n *\t\t\t\t\t\tnew packets have come in; if they have, it parses them\t*\n *\t\t\t\t\t\t& distributes them to the right connection queue.  The\t*\n *\t\t\t\t\t\tqueue's Service routine handles ACK'ing or Resending\t\t*\n *\t\t\t\t\t\tpackets.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tHere's a memory map of the Real-Mode memory block.  'N' is the number\t*\n * of packet buffers allocated in low memory:\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t----------------------------------\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|       Shared-memory data       |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|  Real-mode event handler code  |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|  IPX Header & Packet Buffer 0  |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|  IPX Header & Packet Buffer 1  |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|  IPX Header & Packet Buffer 2  |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|             . . .              |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|  IPX Header & Packet Buffer N  |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|    Send Event Control Block    |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|         Send IPX Header        |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|       Send Packet Buffer       |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|        Flags Array [N]         |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t----------------------------------\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef IPXMANAGER_H\n#define IPXMANAGER_H\n\n\n/*\n********************************* Includes **********************************\n*/\n#include \"ipxconn.h\"\n#include \"ipxgconn.h\"\n#include \"ipxaddr.h\"\n#include \"connmgr.h\"\n\n/*\n********************************** Defines **********************************\n*/\n/*---------------------------------------------------------------------------\nThis is Virgin Interactive Entertainment's registered socket ID.\n---------------------------------------------------------------------------*/\n#define\tVIRGIN_SOCKET\t\t0x8813\n\n/*---------------------------------------------------------------------------\nThis is the maximum number of IPX connections supported.  Just change this\nvalue to support more.\n---------------------------------------------------------------------------*/\n#define\tCONNECT_MAX\t\t\t7\n\n/*---------------------------------------------------------------------------\nThese routines report the location & length of the real-mode routine, as\nit's stored in protected-mode memory.\n---------------------------------------------------------------------------*/\nextern \"C\" {\n\tvoid * __cdecl Get_RM_IPX_Address(void);\n\tlong __cdecl Get_RM_IPX_Size(void);\n}\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass IPXManagerClass : public ConnManClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*.....................................................................\n\t\tConstructor/destructor.\n\t\t.....................................................................*/\n\t\tIPXManagerClass (int glb_maxlen, int pvt_maxlen, int glb_num_packets,\n\t\t\tint pvt_num_packets, unsigned short socket, unsigned short product_id);\n\t\tvirtual ~IPXManagerClass ();\t// stop listening\n\n\t\t/*.....................................................................\n\t\tInitialization routines.\n\t\t.....................................................................*/\n\t\tint Init (void);\n\t\tint Is_IPX(void);\n\t\tvirtual void Set_Timing (unsigned long retrydelta, unsigned long maxretries,\n\t\t\tunsigned long timeout);\n\t\tvoid Set_Bridge(NetNumType bridge);\n\n\t\t/*.....................................................................\n\t\tThese routines control creation of the \"Connections\" (data queues) for\n\t\teach remote system.\n\t\t.....................................................................*/\n\t\tint Create_Connection(int id, char *name, IPXAddressClass *address);\n\t\tint Delete_Connection(int id);\n\t\tvirtual int Num_Connections(void);\n\t\tvirtual int Connection_ID(int index);\n\t\tchar *Connection_Name(int id);\n\t\tIPXAddressClass * Connection_Address(int id);\n\t\tvirtual int Connection_Index(int id);\n\t\tvoid Set_Connection_Parms(int index, int id, char *name);\n\n\t\t/*.....................................................................\n\t\tThis is how the application sends & receives messages.\n\t\t.....................................................................*/\n\t\tint Send_Global_Message (void *buf, int buflen, int ack_req = 0,\n\t\t\tIPXAddressClass *address = NULL);\n\t\tint Get_Global_Message (void *buf, int *buflen, IPXAddressClass *address,\n\t\t\tunsigned short *product_id);\n\n\t\tvirtual int Send_Private_Message (void *buf, int buflen,\n\t\t\tint ack_req = 1, int conn_id = CONNECTION_NONE);\n\t\tvirtual int Get_Private_Message (void *buf, int *buflen, int *conn_id);\n\n\t\t/*.....................................................................\n\t\tThe main polling routine; should be called as often as possible.\n\t\t.....................................................................*/\n\t\tvirtual int Service (void);\n\n\t\t/*.....................................................................\n\t\tThis routine reports which connection has an error on it.\n\t\t.....................................................................*/\n\t\tint Get_Bad_Connection(void);\n\n\t\t/*.....................................................................\n\t\tQueue utility routines.  The application can determine how many\n\t\tmessages are in the send/receive queues.\n\t\t.....................................................................*/\n\t\tvirtual int Global_Num_Send(void);\n\t\tvirtual int Global_Num_Receive(void);\n\t\tvirtual int Private_Num_Send(int id = CONNECTION_NONE);\n\t\tvirtual int Private_Num_Receive(int id = CONNECTION_NONE);\n\n\t\t/*.....................................................................\n\t\tThis routine changes the socket ID assigned the IPX Manager when it\n\t\twas constructed.  Do not call this function after calling Init()!\n\t\tThe Socket ID should be known by both ends of the communications before\n\t\tany packets are sent.\n\t\t.....................................................................*/\n\t\tvoid Set_Socket(unsigned short socket);\n\n\t\t/*.....................................................................\n\t\tRoutines to return the largest average queue response time, and to\n\t\treset the response time for all queues.\n\t\t.....................................................................*/\n\t\tvirtual unsigned long Response_Time(void);\n\t\tunsigned long Global_Response_Time(void);\n\t\tvirtual void Reset_Response_Time(void);\n\n\t\t/*.....................................................................\n\t\tThis routine returns a pointer to the oldest non-ACK'd buffer I've sent.\n\t\t.....................................................................*/\n\t\tvoid * Oldest_Send(void);\n\n\t\t/*.....................................................................\n\t\tDebug routines\n\t\t.....................................................................*/\n\t\tvirtual void Configure_Debug(int index, int type_offset, int type_size,\n\t\t\tchar **names, int namestart, int namecount);\n\t\tvirtual void Mono_Debug_Print(int index, int refresh = 0);\n\n\t/*\n\t--------------------------- Private Interface ----------------------------\n\t*/\n\tprivate:\n\t\t/*.....................................................................\n\t\tThese routines allocate & free the DOS Real-mode memory block.\n\t\t.....................................................................*/\n\t\tint Alloc_RealMode_Mem(void);\n\t\tint Free_RealMode_Mem(void);\n\n\t\t/*.....................................................................\n\t\tMisc variables\n\t\t.....................................................................*/\n\t\tunsigned int IPXStatus : 1;\t\t// 0 = no IPX, 1 = IPX found\n\t\tunsigned int Listening : 1;\t\t// 1 = Listening is on\n\t\tunsigned int RealMemAllocd : 1;\t// 1 = Real-mode memory has been alloc'd\n\n\t\t/*.....................................................................\n\t\tPacket Sizes, used for allocating real-mode memory\n\t\t.....................................................................*/\n\t\tint Glb_MaxPacketLen;\t\t\t\t// Global Channel maximum packet size\n\t\tint Glb_NumPackets;\t\t\t\t\t// # Global send/receive packets\n\t\tint Pvt_MaxPacketLen;\t\t\t\t// Private Channel maximum packet size\n\t\tint Pvt_NumPackets;\t\t\t\t\t// # Private send/receive packets\n\n\t\t/*.....................................................................\n\t\tThe ProductID is used in the Global Channel's packet header, and it's\n\t\tused for the Private Channels' Magic Number.\n\t\t.....................................................................*/\n\t\tunsigned short ProductID;\t\t\t// product ID\n\n\t\t/*.....................................................................\n\t\tThe Socket ID, and local Novell Connection Number\n\t\t.....................................................................*/\n\t\tunsigned short Socket;\t\t\t\t// Our socket ID for sending/receiving\n\t\tint ConnectionNum;\t\t\t\t\t// local connection #, 0=not logged in\n\n\t\t/*.....................................................................\n\t\tArray of connection queues\n\t\t.....................................................................*/\n\t\tIPXConnClass * Connection[CONNECT_MAX]; // array of connection object ptrs\n\t\tint NumConnections;\t\t\t\t\t\t// # connection objects in use\n\t\tIPXGlobalConnClass *GlobalChannel;\t// the Global Channel\n\n\t\t/*.....................................................................\n\t\tCurrent queue for polling for received packets\n\t\t.....................................................................*/\n\t\tint CurConnection;\n\n\t\t/*.....................................................................\n\t\tTiming parameters for all connections\n\t\t.....................................................................*/\n\t\tunsigned long RetryDelta;\n\t\tunsigned long MaxRetries;\n\t\tunsigned long Timeout;\n\n\t\t/*---------------------------------------------------------------------\n\t\tReal-mode memory pointers and such\n\t\t---------------------------------------------------------------------*/\n\t\t/*.....................................................................\n\t\tThis is a structure that mirrors data in real-mode memory:\n\t\t.....................................................................*/\n\t\ttypedef struct {\n\t\t\tshort Marker1;\t\t\t\t\t\t\t// the byte ID marker\n\t\t\tECBType ListenECB;\t\t\t\t\t// the Listening ECB\n\t\t\tshort NumBufs;\t\t\t\t\t\t\t// # of buffers we're giving to the handler\n\t\t\tchar *BufferFlags;\t\t\t\t\t// array of buffer-avail flags\n\t\t\tshort PacketSize;\t\t\t\t\t\t// size of packet including IPX header\n\t\t\tIPXHeaderType *FirstPacketBuf;\t// ptr to 1st packet buffer\n\t\t\tshort CurIndex;\t\t\t\t\t\t// handler's current packet index\n\t\t\tIPXHeaderType *CurPacketBuf;\t\t// handler's current packet buf\n\t\t\tshort FuncOffset;\t\t\t\t\t\t// contains offset of code\n\t\t\tchar Semaphore;\t\t\t\t\t\t// prevents re-entrancy\n\t\t\tshort ReEntrantCount;\t\t\t\t// times we've been called re-entrantly\n\t\t\tshort StackPtr;\t\t\t\t\t\t// real-mode stack pointer\n\t\t\tshort StackSeg;\t\t\t\t\t\t// real-mode stack segment\n\t\t\tshort StackPtr_int;\t\t\t\t\t// internal stack pointer\n\t\t\tshort StackSeg_int;\t\t\t\t\t// internal stack segment\n\t\t\tshort StackCheck;\t\t\t\t\t\t// stack check value (0x1234)\n\t\t\tshort Stack[256];\t\t\t\t\t\t// actual stack space\n\t\t\tshort StackSpace;\t\t\t\t\t\t// label for top of stack\n\t\t\tshort Marker2;\t\t\t\t\t\t\t// the byte ID marker\n\t\t} RealModeDataType;\n\n\t\t/*.....................................................................\n\t\tThe number & size of packet buffers in low memory\n\t\t.....................................................................*/\n\t\tint NumBufs;\t\t\t\t\t\t\t\t// # packet buffers allocated\n\t\tint PacketLen;\t\t\t\t\t\t\t\t// size of packet without IPX header\n\t\tint FullPacketLen;\t\t\t\t\t\t// size of packet including IPX header\n\n\t\t/*.....................................................................\n\t\tSelector & Segment of the DOS allocation;\n\t\tSize of the allocation;\n\t\tPtr to the real-mode assembly data area\n\t\t.....................................................................*/\n\t\tunsigned short Selector;\t\t\t\t// selector of DOS allocation pointer\n\t\tunsigned short Segment;\t\t\t\t\t// real-mode segment of DOS allocation\n\t\tint RealMemSize;\t\t\t\t\t\t\t// size of real mode memory allocated\n\t\tRealModeDataType *RealModeData;\t\t// assembly routine & its data\n\n\t\t/*.....................................................................\n\t\tThis is a real-mode pointer to the address of the real-mode assembly\n\t\tentry point.\n\t\t.....................................................................*/\n\t\tlong Handler;\n\n\t\t/*.....................................................................\n\t\tEvent Control Block for listening; contained within the real-mode\n\t\tassembly routine's data area\n\t\t.....................................................................*/\n\t\tECBType *ListenECB;\t\t\t\t\t\t// ECB for listening\n\n\t\t/*.....................................................................\n\t\tptr to the 1st header & data buffers in the packet buffer array\n\t\t.....................................................................*/\n\t\tIPXHeaderType *FirstHeaderBuf;\t\t// array of packet headers & buffers\n\t\tchar *FirstDataBuf;\t\t\t\t\t\t// 1st data buffer area\n\n\t\t/*.....................................................................\n\t\tCurrent packet index & ptrs for parsing packets\n\t\t.....................................................................*/\n\t\tint CurIndex;\t\t\t\t\t\t\t\t// Current packet index, for reading\n\t\tIPXHeaderType *CurHeaderBuf;\t\t\t// Current packet ptr, for reading\n\t\tchar *CurDataBuf;\t\t\t\t\t\t\t// Current actual data ptr\n\n\t\t/*.....................................................................\n\t\tECB, header, & buffer for sending\n\t\t.....................................................................*/\n\t\tECBType *SendECB;\t\t\t\t\t\t\t// ECB for sending\n\t\tIPXHeaderType *SendHeader;\t\t\t\t// Header for sending\n\t\tchar *SendBuf;\t\t\t\t\t\t\t\t// buffer for sending\n\n\t\t/*.....................................................................\n\t\tFlags indicating whether a buffer contains data or not (1 = full)\n\t\tThe IPXManager must clear this flag; the real-mode routine will set it.\n\t\t.....................................................................*/\n\t\tchar *BufferFlags;\t\t\t\t\t\t// array of rx-buffer-avail flags\n\n\t\t/*.....................................................................\n\t\tVarious Statistics\n\t\t.....................................................................*/\n\t\tint SendOverflows;\n\t\tint ReceiveOverflows;\n\t\tint BadConnection;\n};\n\n#endif\n\n/*************************** end of ipxmgr.h *******************************/\n"
  },
  {
    "path": "CODE/IPXPROT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\n;!!!!!!!!!!!!!!!!!!! lock the allocation\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : VQLIB                                    *\n;*                                                                         *\n;*                    File Name : HANDLER.ASM                              *\n;*                                                                         *\n;*                   Programmer : Bill Randolph                            *\n;*                                                                         *\n;*                   Start Date : April 7, 1995                            *\n;*                                                                         *\n;*                  Last Update : April 7, 1995   [BRR]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   IPXHandler -- callback routine for IPX                                *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\n\n;******************************** Includes *********************************\n\n\n;******************************** Defines ***********************************\n\n\n;****************************** Declarations ********************************\nGLOBAL\t C Get_RM_IPX_Address:NEAR\nGLOBAL\t C Get_RM_IPX_Size:NEAR\n\n;********************************* Data ************************************\n\tDATASEG\n\nLABEL \tRealBinStart\tBYTE\ninclude \"obj\\win32\\ipxreal.ibn\"\nLABEL\tRealBinEnd\tBYTE\n\n;********************************* Data ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Get_RM_IPX_Address -- Return address of real mode code for copy.        *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\tnone                                                               *\n;*                                                                         *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;*\tVOID * to the address of the real mode IPX code\t\t\t   *\n;*                                                                         *\n;* PROTO:\t\t\t\t\t\t\t\t   *\n;*\tVOID\t*Get_RM_IPX_Address(VOID);\t\t\t           *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_IPX_Address C Near\n\n\tmov\teax, OFFSET RealBinStart\n\tret\n\n\tENDP\n\n;***************************************************************************\n;* Get_RM_IPX_Size -- return size of real mode IPX code.                   *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t   \t\t\t   *\n;*\tnone                                                               *\n;*                                                                         *\n;* OUTPUT:      \t\t\t\t   \t\t\t   *\n;*\tLONG size of the real mode IPX code                                *\n;*                                                                         *\n;* PROTO:\t\t\t\t\t   \t\t\t   *\n;*\tLONG\tGet_RM_IPX_Size(VOID);\t\t\t\t   \t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_IPX_Size C Near\n\n\tmov\teax, OFFSET RealBinEnd - OFFSET RealBinStart\n\tret\n\n\tENDP\n\n\tEND\n\n;************************** End of handler.asm *****************************\n"
  },
  {
    "path": "CODE/IPXREAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : VQLIB                                    *\n;*                                                                         *\n;*                    File Name : HANDLER.ASM                              *\n;*                                                                         *\n;*                   Programmer : Bill Randolph                            *\n;*                                                                         *\n;*                   Start Date : April 7, 1995                            *\n;*                                                                         *\n;*                  Last Update : April 7, 1995   [BRR]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   IPXHandler -- callback routine for IPX                                *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nMODEL LARGE\nP386N\nLOCALS ??\n\n\n;******************************** Includes *********************************\n\n\n;******************************** Defines ***********************************\n\n\n;****************************** Declarations ********************************\nGLOBAL\tIPXHandler:FAR\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n\n;---------------------------------------------------------------------------\n; The markers let the application verify that it's mapping this memory\n; correctly.\n;---------------------------------------------------------------------------\nMarker1\t\t\tDW 1111h\t; placeholder to find data start\n\n;---------------------------------------------------------------------------\n; This is the IPX Event Control Block:\n;---------------------------------------------------------------------------\nECB_LinkAddress\t\tDD ?\nECB_EventServiceRoutine\tDD ?\t\t; Event Handler ptr\nECB_InUse\t\tDB ?\t\t; 0 = event is complete\nECB_CompletionCode\tDB ?\t\t; 0 = OK, IPX error otherwise\nECB_SocketNumber\tDW ?\t\t; socket to listen/send on\nECB_ConnectionID\tDW ?\nECB_RestOfWorkspace\tDW ?\nECB_DriverWorkSpace\tDB 12 DUP (?)\nECB_ImmediateAddress\tDB 6 DUP (?)\t; bridge address\nECB_PacketCount\t\tDW ?\t\t; # data areas (2)\nECB_HeaderAddress\tDD ?\t\t; ptr to IPX header buffer\nECB_HeaderLength\tDW ?\t\t; length of IPX header buffer\nECB_PacketAddress\tDD ? \t\t; ptr to packet buffer\nECB_PacketLength\tDW ?\t\t; length of packet buffer\n\n;---------------------------------------------------------------------------\n; The rest of the variables are for telling IPX which buffer to store the\n; next incoming packet in.  They must be initialized by the application.\n;---------------------------------------------------------------------------\nNumBufs\t\tDW 0\t\t\t; # buffers provided by app\nBufferFlags\tDD 0\t\t\t; array of in-use flags (1 = in use)\nPacketSize\tDW 0\t\t\t; total size of 1 buf (incl IPX hdr)\nFirstPacketBuf\tDD 0\t\t\t; ptr to 1st packet buffer\nCurIndex\tDW 0\t\t\t; current packet/flag index\nCurPacketBuf\tDD 0\t\t\t; ptr to current packet buf\nFuncOffset\tDW StartLabel\t\t; offset of our routine\n\n;---------------------------------------------------------------------------\n; These values are for preventing re-entrancy; they're currently not used.\n;---------------------------------------------------------------------------\nSemaphore\tDB 0\t\t\t; prevents re-entrancy\nReEntrantCount\tDW 0\t\t\t; times we've been called re-entrantly\n\n;---------------------------------------------------------------------------\n; Local stack space\n;---------------------------------------------------------------------------\nStackPtr\tDW 0\t\t\t; saved copy of stack ptr\nStackSeg\tDW 0\t\t\t; saved copy of stack seg\nStackPtr_int\tDW 0\t\t\t; our internal stack ptr\nStackSeg_int\tDW 0\t\t\t; our internal stack seg\nStackCheck\tDW 1234h\t\t; check for stack overflow\n\t\tDW 256 DUP (0)\t\t; stack storage space\nStackSpace\tDW 0\t\t\t; label for our stack space\n\n;---------------------------------------------------------------------------\n; These bytes mark the end of the real-mode data area\n;---------------------------------------------------------------------------\nMarker2\t\tDW 2222h\t\t; placeholder to find data end\n\n\n;***************************************************************************\n;* IPXHandler -- IPX callback routine\t\t\t\t\t   *\n;*                                                                         *\n;* This routine is assembled as a stand-alone executable, then loaded      *\n;* into low DOS memory by a protected-mode application.                    *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*\tnone.\t\t\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT: \t\t\t                                           *\n;*\tnone.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*\tnone.\t\t\t\t\t\t\t\t   *\n;* \t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   04/07/1995 BRR : Created.                                             *\n;*=========================================================================*\n\tlabel StartLabel\n\tPROC\tIPXHandler C FAR USES\n\n\t;...................................................................\n\t; Turn off interrupts; make sure memory copies go forward\n\t;...................................................................\n\tpushf\n\tcli\n\tcld\n\n\t;...................................................................\n\t; Set up segment registers to point DS to CS\n\t;...................................................................\n\tpush\tds\n\tpush\tax\n\tmov\tax,cs\n\tmov\tds,ax\n\n\t;...................................................................\n\t; Set up our local stack; save SS & SP first.\n\t;...................................................................\n\tmov\t[StackSeg],ss\n\tmov\t[StackPtr],sp\n\tmov\t[StackPtr_int], OFFSET StackSpace\n\tmov\t[StackSeg_int], SEG StackSpace\n\tlss\tsp, [DWORD PTR StackPtr_int]\n\t\n\n\t;...................................................................\n\t; Save all registers\n\t;...................................................................\n\tpushad\n\tpush\tes\n\n\t;...................................................................\n\t; If we've been called re-entrantly, just exit\n\t;...................................................................\n\tcmp\t[Semaphore],0\n\tjz\t??Start_Handler\n\tadd\t[ReEntrantCount],1\n\tjmp\t??Exit_Handler\n\n??Start_Handler:\n\t;...................................................................\n\t; Set our semaphore\n\t;...................................................................\n\tmov\t[Semaphore],1\n\n\t;-------------------------------------------------------------------\n\t; Set 'CurIndex' to the index of the next-available receive buffer,\n\t; and 'CurPacketBuf to the next-available packet buffer\n\t;-------------------------------------------------------------------\n\t;...................................................................\n\t; Get 'CurIndex' & increment it.  Wrap to 0 if we reach 'NumBufs'\n\t; Since I'm treating 'CurPacketBuf' as a long integer (and not as\n\t; a segment:offset), the entire data area can't be larger than 64K.\n\t;...................................................................\n\tmov\tdx,[CurIndex]\t\t; DX = CurIndex\n\tmov\teax,[CurPacketBuf]\t; EAX = current packet buffer addr\n\tinc\tdx\t\t\t; DX = next index\n\tadd\tax,[PacketSize]\t\t; EAX = next buffer ptr\n\tcmp\tdx,[NumBufs]\t\t; see if DX is past # buffers\n\tjb\t??Get_Flag\n\tmov\tdx,0\t\t\t; wrap to 1st index\n\tmov\teax,[FirstPacketBuf]\t; wrap to 1st packet buffer\n\n??Get_Flag:\n\t;...................................................................\n\t; Get the next buffer-in-use flag; if it's 0, load [CurIndex] with \n\t; the value of SI (the next index).  If it's 1, skip the updating of\n\t; the index, flag & buffer ptr.\n\t; DX = new CurIndex\n\t; EAX = new CurPacketBuf\n\t;...................................................................\n\tles\tdi,[BufferFlags]\t; ES:DI = BufferFlags address\n\tmov\tbx,di\t\t\t; BX = DI + new CurIndex\n\tadd\tbx,dx\n\n\tcmp\t[BYTE PTR es:bx],0\t; compare next flag to 0 (avail)\n\tjne\t??Set_ECB\t\t; if not avail, skip setting new values\n\n\t;...................................................................\n\t; The next buffer is available; so, set this buffer's In-Use flag\n\t; to 1, and move on to the next buffer.  Do not set this buffer's\n\t; flag to 1 until we move on to the next buffer, to prevent the\n\t; application from reading the currently-in-use packet buffer.\n\t; DX = new CurIndex\n\t; EAX = new CurPacketBuf\n\t; ES:DI = BufferFlags address\n\t;...................................................................\n\tmov\tbx,di\t\t\t; BX = DI + old CurIndex\n\tadd\tbx,[CurIndex]\n\tmov\t[BYTE PTR es:bx],1\t; set old BufferFlags value to in-use\n\n\tmov\t[CurIndex],dx\t\t; save new index\n\tmov\t[CurPacketBuf],eax\t; save new packet address\n\n\t;-------------------------------------------------------------------\n\t; Set up the Event Control Block to tell IPX to start listening.\n\t; The following entries are filled in by the app, and should be left\n\t; alone:\n\t; - EventServiceRoutine\n\t; - SocketNumber\n\t; The rest should be re-initialized.  Note that EBX is now pointing\n\t; to an unavailable buffer if the next buffer was already in use;\n\t; so it must be reloaded with the correct buffer address from\n\t; [CurPacketBuf].\n\t;-------------------------------------------------------------------\n??Set_ECB:\n\tmov\t[ECB_LinkAddress],0\t\t; default\n\tmov\t[ECB_InUse],0\t\t\t; default\n\tmov\t[ECB_CompletionCode],0\t\t; default\n\tmov\t[ECB_ConnectionID],0\t\t; default\n\tmov\t[ECB_RestOfWorkspace],0\t\t; default\n\tmov\t[ECB_DriverWorkSpace],0\t\t; default\n\tmov\t[ECB_ImmediateAddress],0\t; default\n\tmov\t[ECB_PacketCount],2\t\t; use 2 data areas\n\tmov\tebx,[CurPacketBuf]\t\t; get current buffer address\n\tmov\t[ECB_HeaderAddress],ebx\t\t; set header address\n\tmov\t[ECB_HeaderLength],30\t\t; size of IPX header\n\tadd\tebx,30\t\t\t\t; point to past the header\n\tmov\t[ECB_PacketAddress],ebx\t\t; set packet data address\n\tmov\tax,[PacketSize]\t\t\t; get size of one buffer\n\tsub\tax,30\t\t\t\t; remove size of IPX header\n\tmov\t[ECB_PacketLength],ax\t\t; set size of packet data\n\n\t;-------------------------------------------------------------------\n\t; Clear the IPX header for this packet\n\t;-------------------------------------------------------------------\n\tles\tdi,[ECB_HeaderAddress]\t\t; ES:DI = IPX Listen Header\n\tmov\tcx,30\t\t\t\t; (30 bytes = size of header)\n\tmov\tal,0\n\trep\tstosb\t\t\t\t; clear to 0's\n\n\t;-------------------------------------------------------------------\n\t; Command IPX to start listening again.\n\t;-------------------------------------------------------------------\n\tmov\tbx,4\t\t\t\t; IPX code for Listen\n\tmov\tax,ds\t\t\t\t; ES = segment of ListenECB\n\tmov\tes,ax\n\tmov\tax,OFFSET ECB_LinkAddress\t\n\tmov\tsi,ax\t\t\t\t; ES:SI = address of ECB\n\tint\t07ah\t\t\t\t; call IPX interrupt\n\n\t;...................................................................\n\t; Clear our semaphore\n\t;...................................................................\n\tmov\t[Semaphore],0\n\n??Exit_Handler:\n\t;...................................................................\n\t; Pop values from our local stack\n\t;...................................................................\n\tpop\tes\n\tpopad\n\n\t;...................................................................\n\t; Check our stack-check value; if the stack has overflowed, generate\n\t; a debugger break.\n\t;...................................................................\n\tcmp\t[StackCheck],1234h\n\tje\t??Restore_Stack\n\tint\t3\n\n\t;...................................................................\n\t; Restore the stack to its previous value\n\t;...................................................................\n??Restore_Stack:\n\tlss\tsp, [DWORD PTR StackPtr]\n\n\t;...................................................................\n\t; Pop the rest of the registers\n\t;...................................................................\n\tpop\tax\n\tpop\tds\n\n\tpopf\n\n\tret\n\nENDP\t\tIPXHandler\n\nEND\n\n;************************** End of handler.asm *****************************\n"
  },
  {
    "path": "CODE/ITABLE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\nunsigned short IndexTable[] = {\n\t0,\t// Index = 0, Token = 0\n\t0,\t// Index = 0, Token = 1\n\t0,\t// Index = 0, Token = 2\n\t0,\t// Index = 0, Token = 3\n\t32,\t// Index = 0, Token = 4\n\t64,\t// Index = 0, Token = 5\n\t96,\t// Index = 0, Token = 6\n\t128,\t// Index = 0, Token = 7\n\t0,\t// Index = 0, Token = 8\n\t0,\t// Index = 0, Token = 9\n\t0,\t// Index = 0, Token = 10\n\t0,\t// Index = 0, Token = 11\n\t32,\t// Index = 0, Token = 12\n\t64,\t// Index = 0, Token = 13\n\t96,\t// Index = 0, Token = 14\n\t128,\t// Index = 0, Token = 15\n\t0,\t// Index = 1, Token = 0\n\t0,\t// Index = 1, Token = 1\n\t0,\t// Index = 1, Token = 2\n\t0,\t// Index = 1, Token = 3\n\t48,\t// Index = 1, Token = 4\n\t80,\t// Index = 1, Token = 5\n\t112,\t// Index = 1, Token = 6\n\t144,\t// Index = 1, Token = 7\n\t0,\t// Index = 1, Token = 8\n\t0,\t// Index = 1, Token = 9\n\t0,\t// Index = 1, Token = 10\n\t0,\t// Index = 1, Token = 11\n\t48,\t// Index = 1, Token = 12\n\t80,\t// Index = 1, Token = 13\n\t112,\t// Index = 1, Token = 14\n\t144,\t// Index = 1, Token = 15\n\t16,\t// Index = 2, Token = 0\n\t16,\t// Index = 2, Token = 1\n\t16,\t// Index = 2, Token = 2\n\t16,\t// Index = 2, Token = 3\n\t64,\t// Index = 2, Token = 4\n\t96,\t// Index = 2, Token = 5\n\t128,\t// Index = 2, Token = 6\n\t160,\t// Index = 2, Token = 7\n\t16,\t// Index = 2, Token = 8\n\t16,\t// Index = 2, Token = 9\n\t16,\t// Index = 2, Token = 10\n\t16,\t// Index = 2, Token = 11\n\t64,\t// Index = 2, Token = 12\n\t96,\t// Index = 2, Token = 13\n\t128,\t// Index = 2, Token = 14\n\t160,\t// Index = 2, Token = 15\n\t32,\t// Index = 3, Token = 0\n\t32,\t// Index = 3, Token = 1\n\t32,\t// Index = 3, Token = 2\n\t32,\t// Index = 3, Token = 3\n\t80,\t// Index = 3, Token = 4\n\t112,\t// Index = 3, Token = 5\n\t144,\t// Index = 3, Token = 6\n\t176,\t// Index = 3, Token = 7\n\t32,\t// Index = 3, Token = 8\n\t32,\t// Index = 3, Token = 9\n\t32,\t// Index = 3, Token = 10\n\t32,\t// Index = 3, Token = 11\n\t80,\t// Index = 3, Token = 12\n\t112,\t// Index = 3, Token = 13\n\t144,\t// Index = 3, Token = 14\n\t176,\t// Index = 3, Token = 15\n\t48,\t// Index = 4, Token = 0\n\t48,\t// Index = 4, Token = 1\n\t48,\t// Index = 4, Token = 2\n\t48,\t// Index = 4, Token = 3\n\t96,\t// Index = 4, Token = 4\n\t128,\t// Index = 4, Token = 5\n\t160,\t// Index = 4, Token = 6\n\t192,\t// Index = 4, Token = 7\n\t48,\t// Index = 4, Token = 8\n\t48,\t// Index = 4, Token = 9\n\t48,\t// Index = 4, Token = 10\n\t48,\t// Index = 4, Token = 11\n\t96,\t// Index = 4, Token = 12\n\t128,\t// Index = 4, Token = 13\n\t160,\t// Index = 4, Token = 14\n\t192,\t// Index = 4, Token = 15\n\t64,\t// Index = 5, Token = 0\n\t64,\t// Index = 5, Token = 1\n\t64,\t// Index = 5, Token = 2\n\t64,\t// Index = 5, Token = 3\n\t112,\t// Index = 5, Token = 4\n\t144,\t// Index = 5, Token = 5\n\t176,\t// Index = 5, Token = 6\n\t208,\t// Index = 5, Token = 7\n\t64,\t// Index = 5, Token = 8\n\t64,\t// Index = 5, Token = 9\n\t64,\t// Index = 5, Token = 10\n\t64,\t// Index = 5, Token = 11\n\t112,\t// Index = 5, Token = 12\n\t144,\t// Index = 5, Token = 13\n\t176,\t// Index = 5, Token = 14\n\t208,\t// Index = 5, Token = 15\n\t80,\t// Index = 6, Token = 0\n\t80,\t// Index = 6, Token = 1\n\t80,\t// Index = 6, Token = 2\n\t80,\t// Index = 6, Token = 3\n\t128,\t// Index = 6, Token = 4\n\t160,\t// Index = 6, Token = 5\n\t192,\t// Index = 6, Token = 6\n\t224,\t// Index = 6, Token = 7\n\t80,\t// Index = 6, Token = 8\n\t80,\t// Index = 6, Token = 9\n\t80,\t// Index = 6, Token = 10\n\t80,\t// Index = 6, Token = 11\n\t128,\t// Index = 6, Token = 12\n\t160,\t// Index = 6, Token = 13\n\t192,\t// Index = 6, Token = 14\n\t224,\t// Index = 6, Token = 15\n\t96,\t// Index = 7, Token = 0\n\t96,\t// Index = 7, Token = 1\n\t96,\t// Index = 7, Token = 2\n\t96,\t// Index = 7, Token = 3\n\t144,\t// Index = 7, Token = 4\n\t176,\t// Index = 7, Token = 5\n\t208,\t// Index = 7, Token = 6\n\t240,\t// Index = 7, Token = 7\n\t96,\t// Index = 7, Token = 8\n\t96,\t// Index = 7, Token = 9\n\t96,\t// Index = 7, Token = 10\n\t96,\t// Index = 7, Token = 11\n\t144,\t// Index = 7, Token = 12\n\t176,\t// Index = 7, Token = 13\n\t208,\t// Index = 7, Token = 14\n\t240,\t// Index = 7, Token = 15\n\t112,\t// Index = 8, Token = 0\n\t112,\t// Index = 8, Token = 1\n\t112,\t// Index = 8, Token = 2\n\t112,\t// Index = 8, Token = 3\n\t160,\t// Index = 8, Token = 4\n\t192,\t// Index = 8, Token = 5\n\t224,\t// Index = 8, Token = 6\n\t256,\t// Index = 8, Token = 7\n\t112,\t// Index = 8, Token = 8\n\t112,\t// Index = 8, Token = 9\n\t112,\t// Index = 8, Token = 10\n\t112,\t// Index = 8, Token = 11\n\t160,\t// Index = 8, Token = 12\n\t192,\t// Index = 8, Token = 13\n\t224,\t// Index = 8, Token = 14\n\t256,\t// Index = 8, Token = 15\n\t128,\t// Index = 9, Token = 0\n\t128,\t// Index = 9, Token = 1\n\t128,\t// Index = 9, Token = 2\n\t128,\t// Index = 9, Token = 3\n\t176,\t// Index = 9, Token = 4\n\t208,\t// Index = 9, Token = 5\n\t240,\t// Index = 9, Token = 6\n\t272,\t// Index = 9, Token = 7\n\t128,\t// Index = 9, Token = 8\n\t128,\t// Index = 9, Token = 9\n\t128,\t// Index = 9, Token = 10\n\t128,\t// Index = 9, Token = 11\n\t176,\t// Index = 9, Token = 12\n\t208,\t// Index = 9, Token = 13\n\t240,\t// Index = 9, Token = 14\n\t272,\t// Index = 9, Token = 15\n\t144,\t// Index = 10, Token = 0\n\t144,\t// Index = 10, Token = 1\n\t144,\t// Index = 10, Token = 2\n\t144,\t// Index = 10, Token = 3\n\t192,\t// Index = 10, Token = 4\n\t224,\t// Index = 10, Token = 5\n\t256,\t// Index = 10, Token = 6\n\t288,\t// Index = 10, Token = 7\n\t144,\t// Index = 10, Token = 8\n\t144,\t// Index = 10, Token = 9\n\t144,\t// Index = 10, Token = 10\n\t144,\t// Index = 10, Token = 11\n\t192,\t// Index = 10, Token = 12\n\t224,\t// Index = 10, Token = 13\n\t256,\t// Index = 10, Token = 14\n\t288,\t// Index = 10, Token = 15\n\t160,\t// Index = 11, Token = 0\n\t160,\t// Index = 11, Token = 1\n\t160,\t// Index = 11, Token = 2\n\t160,\t// Index = 11, Token = 3\n\t208,\t// Index = 11, Token = 4\n\t240,\t// Index = 11, Token = 5\n\t272,\t// Index = 11, Token = 6\n\t304,\t// Index = 11, Token = 7\n\t160,\t// Index = 11, Token = 8\n\t160,\t// Index = 11, Token = 9\n\t160,\t// Index = 11, Token = 10\n\t160,\t// Index = 11, Token = 11\n\t208,\t// Index = 11, Token = 12\n\t240,\t// Index = 11, Token = 13\n\t272,\t// Index = 11, Token = 14\n\t304,\t// Index = 11, Token = 15\n\t176,\t// Index = 12, Token = 0\n\t176,\t// Index = 12, Token = 1\n\t176,\t// Index = 12, Token = 2\n\t176,\t// Index = 12, Token = 3\n\t224,\t// Index = 12, Token = 4\n\t256,\t// Index = 12, Token = 5\n\t288,\t// Index = 12, Token = 6\n\t320,\t// Index = 12, Token = 7\n\t176,\t// Index = 12, Token = 8\n\t176,\t// Index = 12, Token = 9\n\t176,\t// Index = 12, Token = 10\n\t176,\t// Index = 12, Token = 11\n\t224,\t// Index = 12, Token = 12\n\t256,\t// Index = 12, Token = 13\n\t288,\t// Index = 12, Token = 14\n\t320,\t// Index = 12, Token = 15\n\t192,\t// Index = 13, Token = 0\n\t192,\t// Index = 13, Token = 1\n\t192,\t// Index = 13, Token = 2\n\t192,\t// Index = 13, Token = 3\n\t240,\t// Index = 13, Token = 4\n\t272,\t// Index = 13, Token = 5\n\t304,\t// Index = 13, Token = 6\n\t336,\t// Index = 13, Token = 7\n\t192,\t// Index = 13, Token = 8\n\t192,\t// Index = 13, Token = 9\n\t192,\t// Index = 13, Token = 10\n\t192,\t// Index = 13, Token = 11\n\t240,\t// Index = 13, Token = 12\n\t272,\t// Index = 13, Token = 13\n\t304,\t// Index = 13, Token = 14\n\t336,\t// Index = 13, Token = 15\n\t208,\t// Index = 14, Token = 0\n\t208,\t// Index = 14, Token = 1\n\t208,\t// Index = 14, Token = 2\n\t208,\t// Index = 14, Token = 3\n\t256,\t// Index = 14, Token = 4\n\t288,\t// Index = 14, Token = 5\n\t320,\t// Index = 14, Token = 6\n\t352,\t// Index = 14, Token = 7\n\t208,\t// Index = 14, Token = 8\n\t208,\t// Index = 14, Token = 9\n\t208,\t// Index = 14, Token = 10\n\t208,\t// Index = 14, Token = 11\n\t256,\t// Index = 14, Token = 12\n\t288,\t// Index = 14, Token = 13\n\t320,\t// Index = 14, Token = 14\n\t352,\t// Index = 14, Token = 15\n\t224,\t// Index = 15, Token = 0\n\t224,\t// Index = 15, Token = 1\n\t224,\t// Index = 15, Token = 2\n\t224,\t// Index = 15, Token = 3\n\t272,\t// Index = 15, Token = 4\n\t304,\t// Index = 15, Token = 5\n\t336,\t// Index = 15, Token = 6\n\t368,\t// Index = 15, Token = 7\n\t224,\t// Index = 15, Token = 8\n\t224,\t// Index = 15, Token = 9\n\t224,\t// Index = 15, Token = 10\n\t224,\t// Index = 15, Token = 11\n\t272,\t// Index = 15, Token = 12\n\t304,\t// Index = 15, Token = 13\n\t336,\t// Index = 15, Token = 14\n\t368,\t// Index = 15, Token = 15\n\t240,\t// Index = 16, Token = 0\n\t240,\t// Index = 16, Token = 1\n\t240,\t// Index = 16, Token = 2\n\t240,\t// Index = 16, Token = 3\n\t288,\t// Index = 16, Token = 4\n\t320,\t// Index = 16, Token = 5\n\t352,\t// Index = 16, Token = 6\n\t384,\t// Index = 16, Token = 7\n\t240,\t// Index = 16, Token = 8\n\t240,\t// Index = 16, Token = 9\n\t240,\t// Index = 16, Token = 10\n\t240,\t// Index = 16, Token = 11\n\t288,\t// Index = 16, Token = 12\n\t320,\t// Index = 16, Token = 13\n\t352,\t// Index = 16, Token = 14\n\t384,\t// Index = 16, Token = 15\n\t256,\t// Index = 17, Token = 0\n\t256,\t// Index = 17, Token = 1\n\t256,\t// Index = 17, Token = 2\n\t256,\t// Index = 17, Token = 3\n\t304,\t// Index = 17, Token = 4\n\t336,\t// Index = 17, Token = 5\n\t368,\t// Index = 17, Token = 6\n\t400,\t// Index = 17, Token = 7\n\t256,\t// Index = 17, Token = 8\n\t256,\t// Index = 17, Token = 9\n\t256,\t// Index = 17, Token = 10\n\t256,\t// Index = 17, Token = 11\n\t304,\t// Index = 17, Token = 12\n\t336,\t// Index = 17, Token = 13\n\t368,\t// Index = 17, Token = 14\n\t400,\t// Index = 17, Token = 15\n\t272,\t// Index = 18, Token = 0\n\t272,\t// Index = 18, Token = 1\n\t272,\t// Index = 18, Token = 2\n\t272,\t// Index = 18, Token = 3\n\t320,\t// Index = 18, Token = 4\n\t352,\t// Index = 18, Token = 5\n\t384,\t// Index = 18, Token = 6\n\t416,\t// Index = 18, Token = 7\n\t272,\t// Index = 18, Token = 8\n\t272,\t// Index = 18, Token = 9\n\t272,\t// Index = 18, Token = 10\n\t272,\t// Index = 18, Token = 11\n\t320,\t// Index = 18, Token = 12\n\t352,\t// Index = 18, Token = 13\n\t384,\t// Index = 18, Token = 14\n\t416,\t// Index = 18, Token = 15\n\t288,\t// Index = 19, Token = 0\n\t288,\t// Index = 19, Token = 1\n\t288,\t// Index = 19, Token = 2\n\t288,\t// Index = 19, Token = 3\n\t336,\t// Index = 19, Token = 4\n\t368,\t// Index = 19, Token = 5\n\t400,\t// Index = 19, Token = 6\n\t432,\t// Index = 19, Token = 7\n\t288,\t// Index = 19, Token = 8\n\t288,\t// Index = 19, Token = 9\n\t288,\t// Index = 19, Token = 10\n\t288,\t// Index = 19, Token = 11\n\t336,\t// Index = 19, Token = 12\n\t368,\t// Index = 19, Token = 13\n\t400,\t// Index = 19, Token = 14\n\t432,\t// Index = 19, Token = 15\n\t304,\t// Index = 20, Token = 0\n\t304,\t// Index = 20, Token = 1\n\t304,\t// Index = 20, Token = 2\n\t304,\t// Index = 20, Token = 3\n\t352,\t// Index = 20, Token = 4\n\t384,\t// Index = 20, Token = 5\n\t416,\t// Index = 20, Token = 6\n\t448,\t// Index = 20, Token = 7\n\t304,\t// Index = 20, Token = 8\n\t304,\t// Index = 20, Token = 9\n\t304,\t// Index = 20, Token = 10\n\t304,\t// Index = 20, Token = 11\n\t352,\t// Index = 20, Token = 12\n\t384,\t// Index = 20, Token = 13\n\t416,\t// Index = 20, Token = 14\n\t448,\t// Index = 20, Token = 15\n\t320,\t// Index = 21, Token = 0\n\t320,\t// Index = 21, Token = 1\n\t320,\t// Index = 21, Token = 2\n\t320,\t// Index = 21, Token = 3\n\t368,\t// Index = 21, Token = 4\n\t400,\t// Index = 21, Token = 5\n\t432,\t// Index = 21, Token = 6\n\t464,\t// Index = 21, Token = 7\n\t320,\t// Index = 21, Token = 8\n\t320,\t// Index = 21, Token = 9\n\t320,\t// Index = 21, Token = 10\n\t320,\t// Index = 21, Token = 11\n\t368,\t// Index = 21, Token = 12\n\t400,\t// Index = 21, Token = 13\n\t432,\t// Index = 21, Token = 14\n\t464,\t// Index = 21, Token = 15\n\t336,\t// Index = 22, Token = 0\n\t336,\t// Index = 22, Token = 1\n\t336,\t// Index = 22, Token = 2\n\t336,\t// Index = 22, Token = 3\n\t384,\t// Index = 22, Token = 4\n\t416,\t// Index = 22, Token = 5\n\t448,\t// Index = 22, Token = 6\n\t480,\t// Index = 22, Token = 7\n\t336,\t// Index = 22, Token = 8\n\t336,\t// Index = 22, Token = 9\n\t336,\t// Index = 22, Token = 10\n\t336,\t// Index = 22, Token = 11\n\t384,\t// Index = 22, Token = 12\n\t416,\t// Index = 22, Token = 13\n\t448,\t// Index = 22, Token = 14\n\t480,\t// Index = 22, Token = 15\n\t352,\t// Index = 23, Token = 0\n\t352,\t// Index = 23, Token = 1\n\t352,\t// Index = 23, Token = 2\n\t352,\t// Index = 23, Token = 3\n\t400,\t// Index = 23, Token = 4\n\t432,\t// Index = 23, Token = 5\n\t464,\t// Index = 23, Token = 6\n\t496,\t// Index = 23, Token = 7\n\t352,\t// Index = 23, Token = 8\n\t352,\t// Index = 23, Token = 9\n\t352,\t// Index = 23, Token = 10\n\t352,\t// Index = 23, Token = 11\n\t400,\t// Index = 23, Token = 12\n\t432,\t// Index = 23, Token = 13\n\t464,\t// Index = 23, Token = 14\n\t496,\t// Index = 23, Token = 15\n\t368,\t// Index = 24, Token = 0\n\t368,\t// Index = 24, Token = 1\n\t368,\t// Index = 24, Token = 2\n\t368,\t// Index = 24, Token = 3\n\t416,\t// Index = 24, Token = 4\n\t448,\t// Index = 24, Token = 5\n\t480,\t// Index = 24, Token = 6\n\t512,\t// Index = 24, Token = 7\n\t368,\t// Index = 24, Token = 8\n\t368,\t// Index = 24, Token = 9\n\t368,\t// Index = 24, Token = 10\n\t368,\t// Index = 24, Token = 11\n\t416,\t// Index = 24, Token = 12\n\t448,\t// Index = 24, Token = 13\n\t480,\t// Index = 24, Token = 14\n\t512,\t// Index = 24, Token = 15\n\t384,\t// Index = 25, Token = 0\n\t384,\t// Index = 25, Token = 1\n\t384,\t// Index = 25, Token = 2\n\t384,\t// Index = 25, Token = 3\n\t432,\t// Index = 25, Token = 4\n\t464,\t// Index = 25, Token = 5\n\t496,\t// Index = 25, Token = 6\n\t528,\t// Index = 25, Token = 7\n\t384,\t// Index = 25, Token = 8\n\t384,\t// Index = 25, Token = 9\n\t384,\t// Index = 25, Token = 10\n\t384,\t// Index = 25, Token = 11\n\t432,\t// Index = 25, Token = 12\n\t464,\t// Index = 25, Token = 13\n\t496,\t// Index = 25, Token = 14\n\t528,\t// Index = 25, Token = 15\n\t400,\t// Index = 26, Token = 0\n\t400,\t// Index = 26, Token = 1\n\t400,\t// Index = 26, Token = 2\n\t400,\t// Index = 26, Token = 3\n\t448,\t// Index = 26, Token = 4\n\t480,\t// Index = 26, Token = 5\n\t512,\t// Index = 26, Token = 6\n\t544,\t// Index = 26, Token = 7\n\t400,\t// Index = 26, Token = 8\n\t400,\t// Index = 26, Token = 9\n\t400,\t// Index = 26, Token = 10\n\t400,\t// Index = 26, Token = 11\n\t448,\t// Index = 26, Token = 12\n\t480,\t// Index = 26, Token = 13\n\t512,\t// Index = 26, Token = 14\n\t544,\t// Index = 26, Token = 15\n\t416,\t// Index = 27, Token = 0\n\t416,\t// Index = 27, Token = 1\n\t416,\t// Index = 27, Token = 2\n\t416,\t// Index = 27, Token = 3\n\t464,\t// Index = 27, Token = 4\n\t496,\t// Index = 27, Token = 5\n\t528,\t// Index = 27, Token = 6\n\t560,\t// Index = 27, Token = 7\n\t416,\t// Index = 27, Token = 8\n\t416,\t// Index = 27, Token = 9\n\t416,\t// Index = 27, Token = 10\n\t416,\t// Index = 27, Token = 11\n\t464,\t// Index = 27, Token = 12\n\t496,\t// Index = 27, Token = 13\n\t528,\t// Index = 27, Token = 14\n\t560,\t// Index = 27, Token = 15\n\t432,\t// Index = 28, Token = 0\n\t432,\t// Index = 28, Token = 1\n\t432,\t// Index = 28, Token = 2\n\t432,\t// Index = 28, Token = 3\n\t480,\t// Index = 28, Token = 4\n\t512,\t// Index = 28, Token = 5\n\t544,\t// Index = 28, Token = 6\n\t576,\t// Index = 28, Token = 7\n\t432,\t// Index = 28, Token = 8\n\t432,\t// Index = 28, Token = 9\n\t432,\t// Index = 28, Token = 10\n\t432,\t// Index = 28, Token = 11\n\t480,\t// Index = 28, Token = 12\n\t512,\t// Index = 28, Token = 13\n\t544,\t// Index = 28, Token = 14\n\t576,\t// Index = 28, Token = 15\n\t448,\t// Index = 29, Token = 0\n\t448,\t// Index = 29, Token = 1\n\t448,\t// Index = 29, Token = 2\n\t448,\t// Index = 29, Token = 3\n\t496,\t// Index = 29, Token = 4\n\t528,\t// Index = 29, Token = 5\n\t560,\t// Index = 29, Token = 6\n\t592,\t// Index = 29, Token = 7\n\t448,\t// Index = 29, Token = 8\n\t448,\t// Index = 29, Token = 9\n\t448,\t// Index = 29, Token = 10\n\t448,\t// Index = 29, Token = 11\n\t496,\t// Index = 29, Token = 12\n\t528,\t// Index = 29, Token = 13\n\t560,\t// Index = 29, Token = 14\n\t592,\t// Index = 29, Token = 15\n\t464,\t// Index = 30, Token = 0\n\t464,\t// Index = 30, Token = 1\n\t464,\t// Index = 30, Token = 2\n\t464,\t// Index = 30, Token = 3\n\t512,\t// Index = 30, Token = 4\n\t544,\t// Index = 30, Token = 5\n\t576,\t// Index = 30, Token = 6\n\t608,\t// Index = 30, Token = 7\n\t464,\t// Index = 30, Token = 8\n\t464,\t// Index = 30, Token = 9\n\t464,\t// Index = 30, Token = 10\n\t464,\t// Index = 30, Token = 11\n\t512,\t// Index = 30, Token = 12\n\t544,\t// Index = 30, Token = 13\n\t576,\t// Index = 30, Token = 14\n\t608,\t// Index = 30, Token = 15\n\t480,\t// Index = 31, Token = 0\n\t480,\t// Index = 31, Token = 1\n\t480,\t// Index = 31, Token = 2\n\t480,\t// Index = 31, Token = 3\n\t528,\t// Index = 31, Token = 4\n\t560,\t// Index = 31, Token = 5\n\t592,\t// Index = 31, Token = 6\n\t624,\t// Index = 31, Token = 7\n\t480,\t// Index = 31, Token = 8\n\t480,\t// Index = 31, Token = 9\n\t480,\t// Index = 31, Token = 10\n\t480,\t// Index = 31, Token = 11\n\t528,\t// Index = 31, Token = 12\n\t560,\t// Index = 31, Token = 13\n\t592,\t// Index = 31, Token = 14\n\t624,\t// Index = 31, Token = 15\n\t496,\t// Index = 32, Token = 0\n\t496,\t// Index = 32, Token = 1\n\t496,\t// Index = 32, Token = 2\n\t496,\t// Index = 32, Token = 3\n\t544,\t// Index = 32, Token = 4\n\t576,\t// Index = 32, Token = 5\n\t608,\t// Index = 32, Token = 6\n\t640,\t// Index = 32, Token = 7\n\t496,\t// Index = 32, Token = 8\n\t496,\t// Index = 32, Token = 9\n\t496,\t// Index = 32, Token = 10\n\t496,\t// Index = 32, Token = 11\n\t544,\t// Index = 32, Token = 12\n\t576,\t// Index = 32, Token = 13\n\t608,\t// Index = 32, Token = 14\n\t640,\t// Index = 32, Token = 15\n\t512,\t// Index = 33, Token = 0\n\t512,\t// Index = 33, Token = 1\n\t512,\t// Index = 33, Token = 2\n\t512,\t// Index = 33, Token = 3\n\t560,\t// Index = 33, Token = 4\n\t592,\t// Index = 33, Token = 5\n\t624,\t// Index = 33, Token = 6\n\t656,\t// Index = 33, Token = 7\n\t512,\t// Index = 33, Token = 8\n\t512,\t// Index = 33, Token = 9\n\t512,\t// Index = 33, Token = 10\n\t512,\t// Index = 33, Token = 11\n\t560,\t// Index = 33, Token = 12\n\t592,\t// Index = 33, Token = 13\n\t624,\t// Index = 33, Token = 14\n\t656,\t// Index = 33, Token = 15\n\t528,\t// Index = 34, Token = 0\n\t528,\t// Index = 34, Token = 1\n\t528,\t// Index = 34, Token = 2\n\t528,\t// Index = 34, Token = 3\n\t576,\t// Index = 34, Token = 4\n\t608,\t// Index = 34, Token = 5\n\t640,\t// Index = 34, Token = 6\n\t672,\t// Index = 34, Token = 7\n\t528,\t// Index = 34, Token = 8\n\t528,\t// Index = 34, Token = 9\n\t528,\t// Index = 34, Token = 10\n\t528,\t// Index = 34, Token = 11\n\t576,\t// Index = 34, Token = 12\n\t608,\t// Index = 34, Token = 13\n\t640,\t// Index = 34, Token = 14\n\t672,\t// Index = 34, Token = 15\n\t544,\t// Index = 35, Token = 0\n\t544,\t// Index = 35, Token = 1\n\t544,\t// Index = 35, Token = 2\n\t544,\t// Index = 35, Token = 3\n\t592,\t// Index = 35, Token = 4\n\t624,\t// Index = 35, Token = 5\n\t656,\t// Index = 35, Token = 6\n\t688,\t// Index = 35, Token = 7\n\t544,\t// Index = 35, Token = 8\n\t544,\t// Index = 35, Token = 9\n\t544,\t// Index = 35, Token = 10\n\t544,\t// Index = 35, Token = 11\n\t592,\t// Index = 35, Token = 12\n\t624,\t// Index = 35, Token = 13\n\t656,\t// Index = 35, Token = 14\n\t688,\t// Index = 35, Token = 15\n\t560,\t// Index = 36, Token = 0\n\t560,\t// Index = 36, Token = 1\n\t560,\t// Index = 36, Token = 2\n\t560,\t// Index = 36, Token = 3\n\t608,\t// Index = 36, Token = 4\n\t640,\t// Index = 36, Token = 5\n\t672,\t// Index = 36, Token = 6\n\t704,\t// Index = 36, Token = 7\n\t560,\t// Index = 36, Token = 8\n\t560,\t// Index = 36, Token = 9\n\t560,\t// Index = 36, Token = 10\n\t560,\t// Index = 36, Token = 11\n\t608,\t// Index = 36, Token = 12\n\t640,\t// Index = 36, Token = 13\n\t672,\t// Index = 36, Token = 14\n\t704,\t// Index = 36, Token = 15\n\t576,\t// Index = 37, Token = 0\n\t576,\t// Index = 37, Token = 1\n\t576,\t// Index = 37, Token = 2\n\t576,\t// Index = 37, Token = 3\n\t624,\t// Index = 37, Token = 4\n\t656,\t// Index = 37, Token = 5\n\t688,\t// Index = 37, Token = 6\n\t720,\t// Index = 37, Token = 7\n\t576,\t// Index = 37, Token = 8\n\t576,\t// Index = 37, Token = 9\n\t576,\t// Index = 37, Token = 10\n\t576,\t// Index = 37, Token = 11\n\t624,\t// Index = 37, Token = 12\n\t656,\t// Index = 37, Token = 13\n\t688,\t// Index = 37, Token = 14\n\t720,\t// Index = 37, Token = 15\n\t592,\t// Index = 38, Token = 0\n\t592,\t// Index = 38, Token = 1\n\t592,\t// Index = 38, Token = 2\n\t592,\t// Index = 38, Token = 3\n\t640,\t// Index = 38, Token = 4\n\t672,\t// Index = 38, Token = 5\n\t704,\t// Index = 38, Token = 6\n\t736,\t// Index = 38, Token = 7\n\t592,\t// Index = 38, Token = 8\n\t592,\t// Index = 38, Token = 9\n\t592,\t// Index = 38, Token = 10\n\t592,\t// Index = 38, Token = 11\n\t640,\t// Index = 38, Token = 12\n\t672,\t// Index = 38, Token = 13\n\t704,\t// Index = 38, Token = 14\n\t736,\t// Index = 38, Token = 15\n\t608,\t// Index = 39, Token = 0\n\t608,\t// Index = 39, Token = 1\n\t608,\t// Index = 39, Token = 2\n\t608,\t// Index = 39, Token = 3\n\t656,\t// Index = 39, Token = 4\n\t688,\t// Index = 39, Token = 5\n\t720,\t// Index = 39, Token = 6\n\t752,\t// Index = 39, Token = 7\n\t608,\t// Index = 39, Token = 8\n\t608,\t// Index = 39, Token = 9\n\t608,\t// Index = 39, Token = 10\n\t608,\t// Index = 39, Token = 11\n\t656,\t// Index = 39, Token = 12\n\t688,\t// Index = 39, Token = 13\n\t720,\t// Index = 39, Token = 14\n\t752,\t// Index = 39, Token = 15\n\t624,\t// Index = 40, Token = 0\n\t624,\t// Index = 40, Token = 1\n\t624,\t// Index = 40, Token = 2\n\t624,\t// Index = 40, Token = 3\n\t672,\t// Index = 40, Token = 4\n\t704,\t// Index = 40, Token = 5\n\t736,\t// Index = 40, Token = 6\n\t768,\t// Index = 40, Token = 7\n\t624,\t// Index = 40, Token = 8\n\t624,\t// Index = 40, Token = 9\n\t624,\t// Index = 40, Token = 10\n\t624,\t// Index = 40, Token = 11\n\t672,\t// Index = 40, Token = 12\n\t704,\t// Index = 40, Token = 13\n\t736,\t// Index = 40, Token = 14\n\t768,\t// Index = 40, Token = 15\n\t640,\t// Index = 41, Token = 0\n\t640,\t// Index = 41, Token = 1\n\t640,\t// Index = 41, Token = 2\n\t640,\t// Index = 41, Token = 3\n\t688,\t// Index = 41, Token = 4\n\t720,\t// Index = 41, Token = 5\n\t752,\t// Index = 41, Token = 6\n\t784,\t// Index = 41, Token = 7\n\t640,\t// Index = 41, Token = 8\n\t640,\t// Index = 41, Token = 9\n\t640,\t// Index = 41, Token = 10\n\t640,\t// Index = 41, Token = 11\n\t688,\t// Index = 41, Token = 12\n\t720,\t// Index = 41, Token = 13\n\t752,\t// Index = 41, Token = 14\n\t784,\t// Index = 41, Token = 15\n\t656,\t// Index = 42, Token = 0\n\t656,\t// Index = 42, Token = 1\n\t656,\t// Index = 42, Token = 2\n\t656,\t// Index = 42, Token = 3\n\t704,\t// Index = 42, Token = 4\n\t736,\t// Index = 42, Token = 5\n\t768,\t// Index = 42, Token = 6\n\t800,\t// Index = 42, Token = 7\n\t656,\t// Index = 42, Token = 8\n\t656,\t// Index = 42, Token = 9\n\t656,\t// Index = 42, Token = 10\n\t656,\t// Index = 42, Token = 11\n\t704,\t// Index = 42, Token = 12\n\t736,\t// Index = 42, Token = 13\n\t768,\t// Index = 42, Token = 14\n\t800,\t// Index = 42, Token = 15\n\t672,\t// Index = 43, Token = 0\n\t672,\t// Index = 43, Token = 1\n\t672,\t// Index = 43, Token = 2\n\t672,\t// Index = 43, Token = 3\n\t720,\t// Index = 43, Token = 4\n\t752,\t// Index = 43, Token = 5\n\t784,\t// Index = 43, Token = 6\n\t816,\t// Index = 43, Token = 7\n\t672,\t// Index = 43, Token = 8\n\t672,\t// Index = 43, Token = 9\n\t672,\t// Index = 43, Token = 10\n\t672,\t// Index = 43, Token = 11\n\t720,\t// Index = 43, Token = 12\n\t752,\t// Index = 43, Token = 13\n\t784,\t// Index = 43, Token = 14\n\t816,\t// Index = 43, Token = 15\n\t688,\t// Index = 44, Token = 0\n\t688,\t// Index = 44, Token = 1\n\t688,\t// Index = 44, Token = 2\n\t688,\t// Index = 44, Token = 3\n\t736,\t// Index = 44, Token = 4\n\t768,\t// Index = 44, Token = 5\n\t800,\t// Index = 44, Token = 6\n\t832,\t// Index = 44, Token = 7\n\t688,\t// Index = 44, Token = 8\n\t688,\t// Index = 44, Token = 9\n\t688,\t// Index = 44, Token = 10\n\t688,\t// Index = 44, Token = 11\n\t736,\t// Index = 44, Token = 12\n\t768,\t// Index = 44, Token = 13\n\t800,\t// Index = 44, Token = 14\n\t832,\t// Index = 44, Token = 15\n\t704,\t// Index = 45, Token = 0\n\t704,\t// Index = 45, Token = 1\n\t704,\t// Index = 45, Token = 2\n\t704,\t// Index = 45, Token = 3\n\t752,\t// Index = 45, Token = 4\n\t784,\t// Index = 45, Token = 5\n\t816,\t// Index = 45, Token = 6\n\t848,\t// Index = 45, Token = 7\n\t704,\t// Index = 45, Token = 8\n\t704,\t// Index = 45, Token = 9\n\t704,\t// Index = 45, Token = 10\n\t704,\t// Index = 45, Token = 11\n\t752,\t// Index = 45, Token = 12\n\t784,\t// Index = 45, Token = 13\n\t816,\t// Index = 45, Token = 14\n\t848,\t// Index = 45, Token = 15\n\t720,\t// Index = 46, Token = 0\n\t720,\t// Index = 46, Token = 1\n\t720,\t// Index = 46, Token = 2\n\t720,\t// Index = 46, Token = 3\n\t768,\t// Index = 46, Token = 4\n\t800,\t// Index = 46, Token = 5\n\t832,\t// Index = 46, Token = 6\n\t864,\t// Index = 46, Token = 7\n\t720,\t// Index = 46, Token = 8\n\t720,\t// Index = 46, Token = 9\n\t720,\t// Index = 46, Token = 10\n\t720,\t// Index = 46, Token = 11\n\t768,\t// Index = 46, Token = 12\n\t800,\t// Index = 46, Token = 13\n\t832,\t// Index = 46, Token = 14\n\t864,\t// Index = 46, Token = 15\n\t736,\t// Index = 47, Token = 0\n\t736,\t// Index = 47, Token = 1\n\t736,\t// Index = 47, Token = 2\n\t736,\t// Index = 47, Token = 3\n\t784,\t// Index = 47, Token = 4\n\t816,\t// Index = 47, Token = 5\n\t848,\t// Index = 47, Token = 6\n\t880,\t// Index = 47, Token = 7\n\t736,\t// Index = 47, Token = 8\n\t736,\t// Index = 47, Token = 9\n\t736,\t// Index = 47, Token = 10\n\t736,\t// Index = 47, Token = 11\n\t784,\t// Index = 47, Token = 12\n\t816,\t// Index = 47, Token = 13\n\t848,\t// Index = 47, Token = 14\n\t880,\t// Index = 47, Token = 15\n\t752,\t// Index = 48, Token = 0\n\t752,\t// Index = 48, Token = 1\n\t752,\t// Index = 48, Token = 2\n\t752,\t// Index = 48, Token = 3\n\t800,\t// Index = 48, Token = 4\n\t832,\t// Index = 48, Token = 5\n\t864,\t// Index = 48, Token = 6\n\t896,\t// Index = 48, Token = 7\n\t752,\t// Index = 48, Token = 8\n\t752,\t// Index = 48, Token = 9\n\t752,\t// Index = 48, Token = 10\n\t752,\t// Index = 48, Token = 11\n\t800,\t// Index = 48, Token = 12\n\t832,\t// Index = 48, Token = 13\n\t864,\t// Index = 48, Token = 14\n\t896,\t// Index = 48, Token = 15\n\t768,\t// Index = 49, Token = 0\n\t768,\t// Index = 49, Token = 1\n\t768,\t// Index = 49, Token = 2\n\t768,\t// Index = 49, Token = 3\n\t816,\t// Index = 49, Token = 4\n\t848,\t// Index = 49, Token = 5\n\t880,\t// Index = 49, Token = 6\n\t912,\t// Index = 49, Token = 7\n\t768,\t// Index = 49, Token = 8\n\t768,\t// Index = 49, Token = 9\n\t768,\t// Index = 49, Token = 10\n\t768,\t// Index = 49, Token = 11\n\t816,\t// Index = 49, Token = 12\n\t848,\t// Index = 49, Token = 13\n\t880,\t// Index = 49, Token = 14\n\t912,\t// Index = 49, Token = 15\n\t784,\t// Index = 50, Token = 0\n\t784,\t// Index = 50, Token = 1\n\t784,\t// Index = 50, Token = 2\n\t784,\t// Index = 50, Token = 3\n\t832,\t// Index = 50, Token = 4\n\t864,\t// Index = 50, Token = 5\n\t896,\t// Index = 50, Token = 6\n\t928,\t// Index = 50, Token = 7\n\t784,\t// Index = 50, Token = 8\n\t784,\t// Index = 50, Token = 9\n\t784,\t// Index = 50, Token = 10\n\t784,\t// Index = 50, Token = 11\n\t832,\t// Index = 50, Token = 12\n\t864,\t// Index = 50, Token = 13\n\t896,\t// Index = 50, Token = 14\n\t928,\t// Index = 50, Token = 15\n\t800,\t// Index = 51, Token = 0\n\t800,\t// Index = 51, Token = 1\n\t800,\t// Index = 51, Token = 2\n\t800,\t// Index = 51, Token = 3\n\t848,\t// Index = 51, Token = 4\n\t880,\t// Index = 51, Token = 5\n\t912,\t// Index = 51, Token = 6\n\t944,\t// Index = 51, Token = 7\n\t800,\t// Index = 51, Token = 8\n\t800,\t// Index = 51, Token = 9\n\t800,\t// Index = 51, Token = 10\n\t800,\t// Index = 51, Token = 11\n\t848,\t// Index = 51, Token = 12\n\t880,\t// Index = 51, Token = 13\n\t912,\t// Index = 51, Token = 14\n\t944,\t// Index = 51, Token = 15\n\t816,\t// Index = 52, Token = 0\n\t816,\t// Index = 52, Token = 1\n\t816,\t// Index = 52, Token = 2\n\t816,\t// Index = 52, Token = 3\n\t864,\t// Index = 52, Token = 4\n\t896,\t// Index = 52, Token = 5\n\t928,\t// Index = 52, Token = 6\n\t960,\t// Index = 52, Token = 7\n\t816,\t// Index = 52, Token = 8\n\t816,\t// Index = 52, Token = 9\n\t816,\t// Index = 52, Token = 10\n\t816,\t// Index = 52, Token = 11\n\t864,\t// Index = 52, Token = 12\n\t896,\t// Index = 52, Token = 13\n\t928,\t// Index = 52, Token = 14\n\t960,\t// Index = 52, Token = 15\n\t832,\t// Index = 53, Token = 0\n\t832,\t// Index = 53, Token = 1\n\t832,\t// Index = 53, Token = 2\n\t832,\t// Index = 53, Token = 3\n\t880,\t// Index = 53, Token = 4\n\t912,\t// Index = 53, Token = 5\n\t944,\t// Index = 53, Token = 6\n\t976,\t// Index = 53, Token = 7\n\t832,\t// Index = 53, Token = 8\n\t832,\t// Index = 53, Token = 9\n\t832,\t// Index = 53, Token = 10\n\t832,\t// Index = 53, Token = 11\n\t880,\t// Index = 53, Token = 12\n\t912,\t// Index = 53, Token = 13\n\t944,\t// Index = 53, Token = 14\n\t976,\t// Index = 53, Token = 15\n\t848,\t// Index = 54, Token = 0\n\t848,\t// Index = 54, Token = 1\n\t848,\t// Index = 54, Token = 2\n\t848,\t// Index = 54, Token = 3\n\t896,\t// Index = 54, Token = 4\n\t928,\t// Index = 54, Token = 5\n\t960,\t// Index = 54, Token = 6\n\t992,\t// Index = 54, Token = 7\n\t848,\t// Index = 54, Token = 8\n\t848,\t// Index = 54, Token = 9\n\t848,\t// Index = 54, Token = 10\n\t848,\t// Index = 54, Token = 11\n\t896,\t// Index = 54, Token = 12\n\t928,\t// Index = 54, Token = 13\n\t960,\t// Index = 54, Token = 14\n\t992,\t// Index = 54, Token = 15\n\t864,\t// Index = 55, Token = 0\n\t864,\t// Index = 55, Token = 1\n\t864,\t// Index = 55, Token = 2\n\t864,\t// Index = 55, Token = 3\n\t912,\t// Index = 55, Token = 4\n\t944,\t// Index = 55, Token = 5\n\t976,\t// Index = 55, Token = 6\n\t1008,\t// Index = 55, Token = 7\n\t864,\t// Index = 55, Token = 8\n\t864,\t// Index = 55, Token = 9\n\t864,\t// Index = 55, Token = 10\n\t864,\t// Index = 55, Token = 11\n\t912,\t// Index = 55, Token = 12\n\t944,\t// Index = 55, Token = 13\n\t976,\t// Index = 55, Token = 14\n\t1008,\t// Index = 55, Token = 15\n\t880,\t// Index = 56, Token = 0\n\t880,\t// Index = 56, Token = 1\n\t880,\t// Index = 56, Token = 2\n\t880,\t// Index = 56, Token = 3\n\t928,\t// Index = 56, Token = 4\n\t960,\t// Index = 56, Token = 5\n\t992,\t// Index = 56, Token = 6\n\t1024,\t// Index = 56, Token = 7\n\t880,\t// Index = 56, Token = 8\n\t880,\t// Index = 56, Token = 9\n\t880,\t// Index = 56, Token = 10\n\t880,\t// Index = 56, Token = 11\n\t928,\t// Index = 56, Token = 12\n\t960,\t// Index = 56, Token = 13\n\t992,\t// Index = 56, Token = 14\n\t1024,\t// Index = 56, Token = 15\n\t896,\t// Index = 57, Token = 0\n\t896,\t// Index = 57, Token = 1\n\t896,\t// Index = 57, Token = 2\n\t896,\t// Index = 57, Token = 3\n\t944,\t// Index = 57, Token = 4\n\t976,\t// Index = 57, Token = 5\n\t1008,\t// Index = 57, Token = 6\n\t1040,\t// Index = 57, Token = 7\n\t896,\t// Index = 57, Token = 8\n\t896,\t// Index = 57, Token = 9\n\t896,\t// Index = 57, Token = 10\n\t896,\t// Index = 57, Token = 11\n\t944,\t// Index = 57, Token = 12\n\t976,\t// Index = 57, Token = 13\n\t1008,\t// Index = 57, Token = 14\n\t1040,\t// Index = 57, Token = 15\n\t912,\t// Index = 58, Token = 0\n\t912,\t// Index = 58, Token = 1\n\t912,\t// Index = 58, Token = 2\n\t912,\t// Index = 58, Token = 3\n\t960,\t// Index = 58, Token = 4\n\t992,\t// Index = 58, Token = 5\n\t1024,\t// Index = 58, Token = 6\n\t1056,\t// Index = 58, Token = 7\n\t912,\t// Index = 58, Token = 8\n\t912,\t// Index = 58, Token = 9\n\t912,\t// Index = 58, Token = 10\n\t912,\t// Index = 58, Token = 11\n\t960,\t// Index = 58, Token = 12\n\t992,\t// Index = 58, Token = 13\n\t1024,\t// Index = 58, Token = 14\n\t1056,\t// Index = 58, Token = 15\n\t928,\t// Index = 59, Token = 0\n\t928,\t// Index = 59, Token = 1\n\t928,\t// Index = 59, Token = 2\n\t928,\t// Index = 59, Token = 3\n\t976,\t// Index = 59, Token = 4\n\t1008,\t// Index = 59, Token = 5\n\t1040,\t// Index = 59, Token = 6\n\t1072,\t// Index = 59, Token = 7\n\t928,\t// Index = 59, Token = 8\n\t928,\t// Index = 59, Token = 9\n\t928,\t// Index = 59, Token = 10\n\t928,\t// Index = 59, Token = 11\n\t976,\t// Index = 59, Token = 12\n\t1008,\t// Index = 59, Token = 13\n\t1040,\t// Index = 59, Token = 14\n\t1072,\t// Index = 59, Token = 15\n\t944,\t// Index = 60, Token = 0\n\t944,\t// Index = 60, Token = 1\n\t944,\t// Index = 60, Token = 2\n\t944,\t// Index = 60, Token = 3\n\t992,\t// Index = 60, Token = 4\n\t1024,\t// Index = 60, Token = 5\n\t1056,\t// Index = 60, Token = 6\n\t1088,\t// Index = 60, Token = 7\n\t944,\t// Index = 60, Token = 8\n\t944,\t// Index = 60, Token = 9\n\t944,\t// Index = 60, Token = 10\n\t944,\t// Index = 60, Token = 11\n\t992,\t// Index = 60, Token = 12\n\t1024,\t// Index = 60, Token = 13\n\t1056,\t// Index = 60, Token = 14\n\t1088,\t// Index = 60, Token = 15\n\t960,\t// Index = 61, Token = 0\n\t960,\t// Index = 61, Token = 1\n\t960,\t// Index = 61, Token = 2\n\t960,\t// Index = 61, Token = 3\n\t1008,\t// Index = 61, Token = 4\n\t1040,\t// Index = 61, Token = 5\n\t1072,\t// Index = 61, Token = 6\n\t1104,\t// Index = 61, Token = 7\n\t960,\t// Index = 61, Token = 8\n\t960,\t// Index = 61, Token = 9\n\t960,\t// Index = 61, Token = 10\n\t960,\t// Index = 61, Token = 11\n\t1008,\t// Index = 61, Token = 12\n\t1040,\t// Index = 61, Token = 13\n\t1072,\t// Index = 61, Token = 14\n\t1104,\t// Index = 61, Token = 15\n\t976,\t// Index = 62, Token = 0\n\t976,\t// Index = 62, Token = 1\n\t976,\t// Index = 62, Token = 2\n\t976,\t// Index = 62, Token = 3\n\t1024,\t// Index = 62, Token = 4\n\t1056,\t// Index = 62, Token = 5\n\t1088,\t// Index = 62, Token = 6\n\t1120,\t// Index = 62, Token = 7\n\t976,\t// Index = 62, Token = 8\n\t976,\t// Index = 62, Token = 9\n\t976,\t// Index = 62, Token = 10\n\t976,\t// Index = 62, Token = 11\n\t1024,\t// Index = 62, Token = 12\n\t1056,\t// Index = 62, Token = 13\n\t1088,\t// Index = 62, Token = 14\n\t1120,\t// Index = 62, Token = 15\n\t992,\t// Index = 63, Token = 0\n\t992,\t// Index = 63, Token = 1\n\t992,\t// Index = 63, Token = 2\n\t992,\t// Index = 63, Token = 3\n\t1040,\t// Index = 63, Token = 4\n\t1072,\t// Index = 63, Token = 5\n\t1104,\t// Index = 63, Token = 6\n\t1136,\t// Index = 63, Token = 7\n\t992,\t// Index = 63, Token = 8\n\t992,\t// Index = 63, Token = 9\n\t992,\t// Index = 63, Token = 10\n\t992,\t// Index = 63, Token = 11\n\t1040,\t// Index = 63, Token = 12\n\t1072,\t// Index = 63, Token = 13\n\t1104,\t// Index = 63, Token = 14\n\t1136,\t// Index = 63, Token = 15\n\t1008,\t// Index = 64, Token = 0\n\t1008,\t// Index = 64, Token = 1\n\t1008,\t// Index = 64, Token = 2\n\t1008,\t// Index = 64, Token = 3\n\t1056,\t// Index = 64, Token = 4\n\t1088,\t// Index = 64, Token = 5\n\t1120,\t// Index = 64, Token = 6\n\t1152,\t// Index = 64, Token = 7\n\t1008,\t// Index = 64, Token = 8\n\t1008,\t// Index = 64, Token = 9\n\t1008,\t// Index = 64, Token = 10\n\t1008,\t// Index = 64, Token = 11\n\t1056,\t// Index = 64, Token = 12\n\t1088,\t// Index = 64, Token = 13\n\t1120,\t// Index = 64, Token = 14\n\t1152,\t// Index = 64, Token = 15\n\t1024,\t// Index = 65, Token = 0\n\t1024,\t// Index = 65, Token = 1\n\t1024,\t// Index = 65, Token = 2\n\t1024,\t// Index = 65, Token = 3\n\t1072,\t// Index = 65, Token = 4\n\t1104,\t// Index = 65, Token = 5\n\t1136,\t// Index = 65, Token = 6\n\t1168,\t// Index = 65, Token = 7\n\t1024,\t// Index = 65, Token = 8\n\t1024,\t// Index = 65, Token = 9\n\t1024,\t// Index = 65, Token = 10\n\t1024,\t// Index = 65, Token = 11\n\t1072,\t// Index = 65, Token = 12\n\t1104,\t// Index = 65, Token = 13\n\t1136,\t// Index = 65, Token = 14\n\t1168,\t// Index = 65, Token = 15\n\t1040,\t// Index = 66, Token = 0\n\t1040,\t// Index = 66, Token = 1\n\t1040,\t// Index = 66, Token = 2\n\t1040,\t// Index = 66, Token = 3\n\t1088,\t// Index = 66, Token = 4\n\t1120,\t// Index = 66, Token = 5\n\t1152,\t// Index = 66, Token = 6\n\t1184,\t// Index = 66, Token = 7\n\t1040,\t// Index = 66, Token = 8\n\t1040,\t// Index = 66, Token = 9\n\t1040,\t// Index = 66, Token = 10\n\t1040,\t// Index = 66, Token = 11\n\t1088,\t// Index = 66, Token = 12\n\t1120,\t// Index = 66, Token = 13\n\t1152,\t// Index = 66, Token = 14\n\t1184,\t// Index = 66, Token = 15\n\t1056,\t// Index = 67, Token = 0\n\t1056,\t// Index = 67, Token = 1\n\t1056,\t// Index = 67, Token = 2\n\t1056,\t// Index = 67, Token = 3\n\t1104,\t// Index = 67, Token = 4\n\t1136,\t// Index = 67, Token = 5\n\t1168,\t// Index = 67, Token = 6\n\t1200,\t// Index = 67, Token = 7\n\t1056,\t// Index = 67, Token = 8\n\t1056,\t// Index = 67, Token = 9\n\t1056,\t// Index = 67, Token = 10\n\t1056,\t// Index = 67, Token = 11\n\t1104,\t// Index = 67, Token = 12\n\t1136,\t// Index = 67, Token = 13\n\t1168,\t// Index = 67, Token = 14\n\t1200,\t// Index = 67, Token = 15\n\t1072,\t// Index = 68, Token = 0\n\t1072,\t// Index = 68, Token = 1\n\t1072,\t// Index = 68, Token = 2\n\t1072,\t// Index = 68, Token = 3\n\t1120,\t// Index = 68, Token = 4\n\t1152,\t// Index = 68, Token = 5\n\t1184,\t// Index = 68, Token = 6\n\t1216,\t// Index = 68, Token = 7\n\t1072,\t// Index = 68, Token = 8\n\t1072,\t// Index = 68, Token = 9\n\t1072,\t// Index = 68, Token = 10\n\t1072,\t// Index = 68, Token = 11\n\t1120,\t// Index = 68, Token = 12\n\t1152,\t// Index = 68, Token = 13\n\t1184,\t// Index = 68, Token = 14\n\t1216,\t// Index = 68, Token = 15\n\t1088,\t// Index = 69, Token = 0\n\t1088,\t// Index = 69, Token = 1\n\t1088,\t// Index = 69, Token = 2\n\t1088,\t// Index = 69, Token = 3\n\t1136,\t// Index = 69, Token = 4\n\t1168,\t// Index = 69, Token = 5\n\t1200,\t// Index = 69, Token = 6\n\t1232,\t// Index = 69, Token = 7\n\t1088,\t// Index = 69, Token = 8\n\t1088,\t// Index = 69, Token = 9\n\t1088,\t// Index = 69, Token = 10\n\t1088,\t// Index = 69, Token = 11\n\t1136,\t// Index = 69, Token = 12\n\t1168,\t// Index = 69, Token = 13\n\t1200,\t// Index = 69, Token = 14\n\t1232,\t// Index = 69, Token = 15\n\t1104,\t// Index = 70, Token = 0\n\t1104,\t// Index = 70, Token = 1\n\t1104,\t// Index = 70, Token = 2\n\t1104,\t// Index = 70, Token = 3\n\t1152,\t// Index = 70, Token = 4\n\t1184,\t// Index = 70, Token = 5\n\t1216,\t// Index = 70, Token = 6\n\t1248,\t// Index = 70, Token = 7\n\t1104,\t// Index = 70, Token = 8\n\t1104,\t// Index = 70, Token = 9\n\t1104,\t// Index = 70, Token = 10\n\t1104,\t// Index = 70, Token = 11\n\t1152,\t// Index = 70, Token = 12\n\t1184,\t// Index = 70, Token = 13\n\t1216,\t// Index = 70, Token = 14\n\t1248,\t// Index = 70, Token = 15\n\t1120,\t// Index = 71, Token = 0\n\t1120,\t// Index = 71, Token = 1\n\t1120,\t// Index = 71, Token = 2\n\t1120,\t// Index = 71, Token = 3\n\t1168,\t// Index = 71, Token = 4\n\t1200,\t// Index = 71, Token = 5\n\t1232,\t// Index = 71, Token = 6\n\t1264,\t// Index = 71, Token = 7\n\t1120,\t// Index = 71, Token = 8\n\t1120,\t// Index = 71, Token = 9\n\t1120,\t// Index = 71, Token = 10\n\t1120,\t// Index = 71, Token = 11\n\t1168,\t// Index = 71, Token = 12\n\t1200,\t// Index = 71, Token = 13\n\t1232,\t// Index = 71, Token = 14\n\t1264,\t// Index = 71, Token = 15\n\t1136,\t// Index = 72, Token = 0\n\t1136,\t// Index = 72, Token = 1\n\t1136,\t// Index = 72, Token = 2\n\t1136,\t// Index = 72, Token = 3\n\t1184,\t// Index = 72, Token = 4\n\t1216,\t// Index = 72, Token = 5\n\t1248,\t// Index = 72, Token = 6\n\t1280,\t// Index = 72, Token = 7\n\t1136,\t// Index = 72, Token = 8\n\t1136,\t// Index = 72, Token = 9\n\t1136,\t// Index = 72, Token = 10\n\t1136,\t// Index = 72, Token = 11\n\t1184,\t// Index = 72, Token = 12\n\t1216,\t// Index = 72, Token = 13\n\t1248,\t// Index = 72, Token = 14\n\t1280,\t// Index = 72, Token = 15\n\t1152,\t// Index = 73, Token = 0\n\t1152,\t// Index = 73, Token = 1\n\t1152,\t// Index = 73, Token = 2\n\t1152,\t// Index = 73, Token = 3\n\t1200,\t// Index = 73, Token = 4\n\t1232,\t// Index = 73, Token = 5\n\t1264,\t// Index = 73, Token = 6\n\t1296,\t// Index = 73, Token = 7\n\t1152,\t// Index = 73, Token = 8\n\t1152,\t// Index = 73, Token = 9\n\t1152,\t// Index = 73, Token = 10\n\t1152,\t// Index = 73, Token = 11\n\t1200,\t// Index = 73, Token = 12\n\t1232,\t// Index = 73, Token = 13\n\t1264,\t// Index = 73, Token = 14\n\t1296,\t// Index = 73, Token = 15\n\t1168,\t// Index = 74, Token = 0\n\t1168,\t// Index = 74, Token = 1\n\t1168,\t// Index = 74, Token = 2\n\t1168,\t// Index = 74, Token = 3\n\t1216,\t// Index = 74, Token = 4\n\t1248,\t// Index = 74, Token = 5\n\t1280,\t// Index = 74, Token = 6\n\t1312,\t// Index = 74, Token = 7\n\t1168,\t// Index = 74, Token = 8\n\t1168,\t// Index = 74, Token = 9\n\t1168,\t// Index = 74, Token = 10\n\t1168,\t// Index = 74, Token = 11\n\t1216,\t// Index = 74, Token = 12\n\t1248,\t// Index = 74, Token = 13\n\t1280,\t// Index = 74, Token = 14\n\t1312,\t// Index = 74, Token = 15\n\t1184,\t// Index = 75, Token = 0\n\t1184,\t// Index = 75, Token = 1\n\t1184,\t// Index = 75, Token = 2\n\t1184,\t// Index = 75, Token = 3\n\t1232,\t// Index = 75, Token = 4\n\t1264,\t// Index = 75, Token = 5\n\t1296,\t// Index = 75, Token = 6\n\t1328,\t// Index = 75, Token = 7\n\t1184,\t// Index = 75, Token = 8\n\t1184,\t// Index = 75, Token = 9\n\t1184,\t// Index = 75, Token = 10\n\t1184,\t// Index = 75, Token = 11\n\t1232,\t// Index = 75, Token = 12\n\t1264,\t// Index = 75, Token = 13\n\t1296,\t// Index = 75, Token = 14\n\t1328,\t// Index = 75, Token = 15\n\t1200,\t// Index = 76, Token = 0\n\t1200,\t// Index = 76, Token = 1\n\t1200,\t// Index = 76, Token = 2\n\t1200,\t// Index = 76, Token = 3\n\t1248,\t// Index = 76, Token = 4\n\t1280,\t// Index = 76, Token = 5\n\t1312,\t// Index = 76, Token = 6\n\t1344,\t// Index = 76, Token = 7\n\t1200,\t// Index = 76, Token = 8\n\t1200,\t// Index = 76, Token = 9\n\t1200,\t// Index = 76, Token = 10\n\t1200,\t// Index = 76, Token = 11\n\t1248,\t// Index = 76, Token = 12\n\t1280,\t// Index = 76, Token = 13\n\t1312,\t// Index = 76, Token = 14\n\t1344,\t// Index = 76, Token = 15\n\t1216,\t// Index = 77, Token = 0\n\t1216,\t// Index = 77, Token = 1\n\t1216,\t// Index = 77, Token = 2\n\t1216,\t// Index = 77, Token = 3\n\t1264,\t// Index = 77, Token = 4\n\t1296,\t// Index = 77, Token = 5\n\t1328,\t// Index = 77, Token = 6\n\t1360,\t// Index = 77, Token = 7\n\t1216,\t// Index = 77, Token = 8\n\t1216,\t// Index = 77, Token = 9\n\t1216,\t// Index = 77, Token = 10\n\t1216,\t// Index = 77, Token = 11\n\t1264,\t// Index = 77, Token = 12\n\t1296,\t// Index = 77, Token = 13\n\t1328,\t// Index = 77, Token = 14\n\t1360,\t// Index = 77, Token = 15\n\t1232,\t// Index = 78, Token = 0\n\t1232,\t// Index = 78, Token = 1\n\t1232,\t// Index = 78, Token = 2\n\t1232,\t// Index = 78, Token = 3\n\t1280,\t// Index = 78, Token = 4\n\t1312,\t// Index = 78, Token = 5\n\t1344,\t// Index = 78, Token = 6\n\t1376,\t// Index = 78, Token = 7\n\t1232,\t// Index = 78, Token = 8\n\t1232,\t// Index = 78, Token = 9\n\t1232,\t// Index = 78, Token = 10\n\t1232,\t// Index = 78, Token = 11\n\t1280,\t// Index = 78, Token = 12\n\t1312,\t// Index = 78, Token = 13\n\t1344,\t// Index = 78, Token = 14\n\t1376,\t// Index = 78, Token = 15\n\t1248,\t// Index = 79, Token = 0\n\t1248,\t// Index = 79, Token = 1\n\t1248,\t// Index = 79, Token = 2\n\t1248,\t// Index = 79, Token = 3\n\t1296,\t// Index = 79, Token = 4\n\t1328,\t// Index = 79, Token = 5\n\t1360,\t// Index = 79, Token = 6\n\t1392,\t// Index = 79, Token = 7\n\t1248,\t// Index = 79, Token = 8\n\t1248,\t// Index = 79, Token = 9\n\t1248,\t// Index = 79, Token = 10\n\t1248,\t// Index = 79, Token = 11\n\t1296,\t// Index = 79, Token = 12\n\t1328,\t// Index = 79, Token = 13\n\t1360,\t// Index = 79, Token = 14\n\t1392,\t// Index = 79, Token = 15\n\t1264,\t// Index = 80, Token = 0\n\t1264,\t// Index = 80, Token = 1\n\t1264,\t// Index = 80, Token = 2\n\t1264,\t// Index = 80, Token = 3\n\t1312,\t// Index = 80, Token = 4\n\t1344,\t// Index = 80, Token = 5\n\t1376,\t// Index = 80, Token = 6\n\t1408,\t// Index = 80, Token = 7\n\t1264,\t// Index = 80, Token = 8\n\t1264,\t// Index = 80, Token = 9\n\t1264,\t// Index = 80, Token = 10\n\t1264,\t// Index = 80, Token = 11\n\t1312,\t// Index = 80, Token = 12\n\t1344,\t// Index = 80, Token = 13\n\t1376,\t// Index = 80, Token = 14\n\t1408,\t// Index = 80, Token = 15\n\t1280,\t// Index = 81, Token = 0\n\t1280,\t// Index = 81, Token = 1\n\t1280,\t// Index = 81, Token = 2\n\t1280,\t// Index = 81, Token = 3\n\t1328,\t// Index = 81, Token = 4\n\t1360,\t// Index = 81, Token = 5\n\t1392,\t// Index = 81, Token = 6\n\t1408,\t// Index = 81, Token = 7\n\t1280,\t// Index = 81, Token = 8\n\t1280,\t// Index = 81, Token = 9\n\t1280,\t// Index = 81, Token = 10\n\t1280,\t// Index = 81, Token = 11\n\t1328,\t// Index = 81, Token = 12\n\t1360,\t// Index = 81, Token = 13\n\t1392,\t// Index = 81, Token = 14\n\t1408,\t// Index = 81, Token = 15\n\t1296,\t// Index = 82, Token = 0\n\t1296,\t// Index = 82, Token = 1\n\t1296,\t// Index = 82, Token = 2\n\t1296,\t// Index = 82, Token = 3\n\t1344,\t// Index = 82, Token = 4\n\t1376,\t// Index = 82, Token = 5\n\t1408,\t// Index = 82, Token = 6\n\t1408,\t// Index = 82, Token = 7\n\t1296,\t// Index = 82, Token = 8\n\t1296,\t// Index = 82, Token = 9\n\t1296,\t// Index = 82, Token = 10\n\t1296,\t// Index = 82, Token = 11\n\t1344,\t// Index = 82, Token = 12\n\t1376,\t// Index = 82, Token = 13\n\t1408,\t// Index = 82, Token = 14\n\t1408,\t// Index = 82, Token = 15\n\t1312,\t// Index = 83, Token = 0\n\t1312,\t// Index = 83, Token = 1\n\t1312,\t// Index = 83, Token = 2\n\t1312,\t// Index = 83, Token = 3\n\t1360,\t// Index = 83, Token = 4\n\t1392,\t// Index = 83, Token = 5\n\t1408,\t// Index = 83, Token = 6\n\t1408,\t// Index = 83, Token = 7\n\t1312,\t// Index = 83, Token = 8\n\t1312,\t// Index = 83, Token = 9\n\t1312,\t// Index = 83, Token = 10\n\t1312,\t// Index = 83, Token = 11\n\t1360,\t// Index = 83, Token = 12\n\t1392,\t// Index = 83, Token = 13\n\t1408,\t// Index = 83, Token = 14\n\t1408,\t// Index = 83, Token = 15\n\t1328,\t// Index = 84, Token = 0\n\t1328,\t// Index = 84, Token = 1\n\t1328,\t// Index = 84, Token = 2\n\t1328,\t// Index = 84, Token = 3\n\t1376,\t// Index = 84, Token = 4\n\t1408,\t// Index = 84, Token = 5\n\t1408,\t// Index = 84, Token = 6\n\t1408,\t// Index = 84, Token = 7\n\t1328,\t// Index = 84, Token = 8\n\t1328,\t// Index = 84, Token = 9\n\t1328,\t// Index = 84, Token = 10\n\t1328,\t// Index = 84, Token = 11\n\t1376,\t// Index = 84, Token = 12\n\t1408,\t// Index = 84, Token = 13\n\t1408,\t// Index = 84, Token = 14\n\t1408,\t// Index = 84, Token = 15\n\t1344,\t// Index = 85, Token = 0\n\t1344,\t// Index = 85, Token = 1\n\t1344,\t// Index = 85, Token = 2\n\t1344,\t// Index = 85, Token = 3\n\t1392,\t// Index = 85, Token = 4\n\t1408,\t// Index = 85, Token = 5\n\t1408,\t// Index = 85, Token = 6\n\t1408,\t// Index = 85, Token = 7\n\t1344,\t// Index = 85, Token = 8\n\t1344,\t// Index = 85, Token = 9\n\t1344,\t// Index = 85, Token = 10\n\t1344,\t// Index = 85, Token = 11\n\t1392,\t// Index = 85, Token = 12\n\t1408,\t// Index = 85, Token = 13\n\t1408,\t// Index = 85, Token = 14\n\t1408,\t// Index = 85, Token = 15\n\t1360,\t// Index = 86, Token = 0\n\t1360,\t// Index = 86, Token = 1\n\t1360,\t// Index = 86, Token = 2\n\t1360,\t// Index = 86, Token = 3\n\t1408,\t// Index = 86, Token = 4\n\t1408,\t// Index = 86, Token = 5\n\t1408,\t// Index = 86, Token = 6\n\t1408,\t// Index = 86, Token = 7\n\t1360,\t// Index = 86, Token = 8\n\t1360,\t// Index = 86, Token = 9\n\t1360,\t// Index = 86, Token = 10\n\t1360,\t// Index = 86, Token = 11\n\t1408,\t// Index = 86, Token = 12\n\t1408,\t// Index = 86, Token = 13\n\t1408,\t// Index = 86, Token = 14\n\t1408,\t// Index = 86, Token = 15\n\t1376,\t// Index = 87, Token = 0\n\t1376,\t// Index = 87, Token = 1\n\t1376,\t// Index = 87, Token = 2\n\t1376,\t// Index = 87, Token = 3\n\t1408,\t// Index = 87, Token = 4\n\t1408,\t// Index = 87, Token = 5\n\t1408,\t// Index = 87, Token = 6\n\t1408,\t// Index = 87, Token = 7\n\t1376,\t// Index = 87, Token = 8\n\t1376,\t// Index = 87, Token = 9\n\t1376,\t// Index = 87, Token = 10\n\t1376,\t// Index = 87, Token = 11\n\t1408,\t// Index = 87, Token = 12\n\t1408,\t// Index = 87, Token = 13\n\t1408,\t// Index = 87, Token = 14\n\t1408,\t// Index = 87, Token = 15\n\t1392,\t// Index = 88, Token = 0\n\t1392,\t// Index = 88, Token = 1\n\t1392,\t// Index = 88, Token = 2\n\t1392,\t// Index = 88, Token = 3\n\t1408,\t// Index = 88, Token = 4\n\t1408,\t// Index = 88, Token = 5\n\t1408,\t// Index = 88, Token = 6\n\t1408,\t// Index = 88, Token = 7\n\t1392,\t// Index = 88, Token = 8\n\t1392,\t// Index = 88, Token = 9\n\t1392,\t// Index = 88, Token = 10\n\t1392,\t// Index = 88, Token = 11\n\t1408,\t// Index = 88, Token = 12\n\t1408,\t// Index = 88, Token = 13\n\t1408,\t// Index = 88, Token = 14\n\t1408\t// Index = 88, Token = 15\n};\n\n"
  },
  {
    "path": "CODE/JOEMAKE.BAT",
    "content": "@echo off\ntimer\n:***************************************************************************\n:*                                                                         *\n:* Network make batch file: compiles using network slaves                  *\n:*                                                                         *\n:* Required mods to user's AUTOEXEC:                                       *\n:* - PATH should include the SLAVES directory, so make can find NETEXEC    *\n:* - WWLIB should point to user's WWLIB32 installation                     *\n:* - WATCOM should point to the local WATCOM root directory                *\n:*                                                                         *\n:* Required changes to this batch file:                                    *\n:* - NETWHO should be set to the user's name                               *\n:* - CCLOCALDIR & CCNETDIR should point to the local & net CC dirs         *\n:*                                                                         *\n:***************************************************************************\n:------------------------- set up environment ------------------------------\nset NETWHO=joeb\nset CCLOCALDIR=c:\\projects\\c&czero\nset CCNETDIR=f:\\projects\\c&c0\\slaves\\%NETWHO%\\c&c0\nset WWLIBNET=f:\\projects\\c&c0\\slaves\\%NETWHO%\\wwlib32\nset WATDIR=c:\\projects\\c&czero\\code\\watcom\nset NETWORK=1\n\n:------------------------- substitute drives -------------------------------\nsubst o: /d >&NUL\nsubst r: /d >&NUL\nsubst q: /d >&NUL\nsubst o: %WATDIR%\nsubst r: %CCLOCALDIR%\nsubst q: %WWLIB%\n\n:----------------------- Set Watcom's environment --------------------------\nset watcom=o:\nset include=o:\\h;o:\\h\\win;q:\\include;..\\vq\\include;.;\nset wwflat=q:\nREM set wwvcs=g:\\library\\wwlib32\\pvcswat\nset DOS16M=@0--8mm\n\n:---------------------- update network source files ------------------------\ncopy /s q:\\include\\*.h           %WWLIBNET%\\include /U\ncopy r:\\vq\\include\\vqm32\\*.h  %CCNETDIR%\\vq\\include\\vqm32 /U /S\ncopy r:\\vq\\include\\vqa32\\*.h  %CCNETDIR%\\vq\\include\\vqa32 /U /S\ncopy r:\\code\\*.cpp r:\\code\\*.h r:\\code\\*.asm r:\\code\\*.i r:\\code\\*.inc r:\\code\\makefile  r:\\code\\*.lnk %CCNETDIR%\\code /U\ncopy r:\\code\\watcom\\*.* %CCNETDIR%\\code\\watcom /U\ncopy r:\\code\\watcom\\binb\\*.* %CCNETDIR%\\code\\watcom\\binb /U\ncopy r:\\code\\watcom\\binw\\*.* %CCNETDIR%\\code\\watcom\\binw /U\ncopy r:\\code\\watcom\\binnt\\*.* %CCNETDIR%\\code\\watcom\\binnt /U\ncopy /s r:\\code\\watcom\\h\\*.* %CCNETDIR%\\code\\watcom\\h /U\nREM copy /s r:\\code\\watcom\\*.* %CCNETDIR%\\code\\watcom /U\nREM copy r:\\code\\*.h              %CCNETDIR%\\code /U\nREM copy r:\\code\\*.asm            %CCNETDIR%\\code /U\nREM copy r:\\code\\*.i              %CCNETDIR%\\code /U\nREM copy r:\\code\\*.inc            %CCNETDIR%\\code /U\nREM copy r:\\code\\makefile         %CCNETDIR%\\code /U\n\n:----------------------------- Fire up wmake -------------------------------\nnetexec /s\nwmake /c %1 %2 %3 %4 %5 %6 %7 %8 %9\nif errorlevel 1 goto makerr\ngoto endit\n\n:makerr\nif exist %CCNETDIR%\\code\\netmake.err type %CCNETDIR%\\code\\netmake.err\n\n:endit\nset NETWORK=\n\n:---------------------------- Get the objects ------------------------------\ncopy %CCNETDIR%\\code\\obj\\*.obj r:\\code\\obj /U\n\n:***************************************************************************\ntimer\n\n"
  },
  {
    "path": "CODE/JSHELL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/JSHELL.CPP 2     3/13/97 2:05p Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : JSHELL.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 2, 1994                                                *\n *                                                                                             *\n *                  Last Update : May 11, 1995 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Build_Translucent_Table -- Creates a translucent control table.                           *\n *   Conquer_Build_Translucent_Table -- Builds fading table for shadow colors only.            *\n *   Fatal -- General purpose fatal error handler.                                             *\n *   Load_Alloc_Data -- Allocates a buffer and loads the file into it.                         *\n *   Load_Uncompress -- Loads and uncompresses data to a buffer.                               *\n *   Set_Window -- Sets the window dimensions to that specified.                               *\n *   Small_Icon -- Create a small icon from a big one.                                         *\n *   Translucent_Table_Size -- Determines the size of a translucent table.                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"wwfile.h\"\n\n\n/***********************************************************************************************\n * Small_Icon -- Create a small icon from a big one.                                           *\n *                                                                                             *\n *    This routine will extract the specified icon from the icon data file and convert that    *\n *    icon into a small (3x3) representation. Typical use of this mini-icon is for the radar   *\n *    map.                                                                                     *\n *                                                                                             *\n * INPUT:   iconptr  -- Pointer to the icon data file.                                         *\n *                                                                                             *\n *          iconnum  -- The embedded icon number to convert into a small image.                *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the small icon imagery. This is exactly 9 bytes long.    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/11/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * Small_Icon(void const * iconptr, int iconnum)\n{\n\tstatic unsigned char _icon[9];\n\tIControl_Type const * iptr = (IControl_Type const *)iconptr;\n\tunsigned char * data;\n\n\tif (iconptr) {\n\t\ticonnum = ((char *)((char *)iptr + iptr->Map))[iconnum];\n\t\tdata = &((unsigned char *)((unsigned char *)iptr + iptr->Icons))[iconnum*(24*24)];\n//\t\tdata = &iptr->Icons[iconnum*(24*24)];\n\n\t\tfor (int index = 0; index < 9; index++) {\n\t\t\tint _offsets[9] = {\n\t\t\t\t4+4*24,\n\t\t\t\t12+4*24,\n\t\t\t\t20+4*24,\n\t\t\t\t4+12*24,\n\t\t\t\t12+12*24,\n\t\t\t\t20+12*24,\n\t\t\t\t4+20*24,\n\t\t\t\t12+20*24,\n\t\t\t\t20+20*24\n\t\t\t};\n\t\t\t_icon[index] = data[_offsets[index]];\n\t\t}\n\t}\n\n\treturn(_icon);\n}\n\n\n/***********************************************************************************************\n * Set_Window -- Sets the window dimensions to that specified.                                 *\n *                                                                                             *\n *    Use this routine to set the windows dimensions to the coordinates and dimensions         *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   x     -- Window X pixel position.                                                  *\n *                                                                                             *\n *          y     -- Window Y pixel position.                                                  *\n *                                                                                             *\n *          w     -- Window width in pixels.                                                   *\n *                                                                                             *\n *          h     -- Window height in pixels.                                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The X and width values are truncated to an even 8 pixel boundary. This is       *\n *             the same as stripping off the lower 3 bits.                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Set_Window(int window, int x, int y, int w, int h)\n{\n\tWindowList[window][WINDOWWIDTH] = w;\n\tWindowList[window][WINDOWHEIGHT] = h;\n\tWindowList[window][WINDOWX] = x;\n\tWindowList[window][WINDOWY] = y;\n}\n\n\n/***********************************************************************************************\n * Fatal -- General purpose fatal error handler.                                               *\n *                                                                                             *\n *    This is a very simple general purpose fatal error handler. It goes directly to text      *\n *    mode, prints the error, and then aborts with a failure code.                             *\n *                                                                                             *\n * INPUT:   message  -- The text message to display.                                           *\n *                                                                                             *\n *          ...      -- Any optional parameters that are used in formatting the message.       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine never returns. The game exits immediately.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Fatal(char const * message, ...)\n{\n\tva_list\tva;\n\n\tva_start(va, message);\n\t//Prog_End();\n\tvfprintf(stderr, message, va);\n\tMono_Printf(message);\n\tEmergency_Exit(EXIT_FAILURE);\n}\n\n\n#ifdef NEVER\nvoid File_Fatal(char const * message)\n{\n\t//Prog_End();\n\tperror(message);\n\tEmergency_Exit(EXIT_FAILURE);\n}\n#endif\n\n\n\n/***********************************************************************************************\n * Load_Uncompress -- Loads and uncompresses data to a buffer.                                 *\n *                                                                                             *\n *    This is the C++ counterpart to the Load_Uncompress function. It will load the file       *\n *    specified into the graphic buffer indicated and uncompress it.                           *\n *                                                                                             *\n * INPUT:   file     -- The file to load and uncompress.                                       *\n *                                                                                             *\n *          uncomp_buff -- The graphic buffer that initial loading will use.                   *\n *                                                                                             *\n *          dest_buff   -- The buffer that will hold the uncompressed data.                    *\n *                                                                                             *\n *          reserved_data  -- This is an optional pointer to a buffer that will hold any       *\n *                            reserved data the compressed file may contain. This is           *\n *                            typically a palette.                                             *\n *                                                                                             *\n * OUTPUT:  Returns with the size of the uncompressed data in the destination buffer.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Load_Uncompress(FileClass &file, BuffType &uncomp_buff, BuffType &dest_buff, void * reserved_data)\n{\n\tunsigned short\tsize;\n\tvoid\t* sptr = uncomp_buff.Get_Buffer();\n\tvoid\t* dptr = dest_buff.Get_Buffer();\n\tint\topened = false;\n\tCompHeaderType\theader;\n\n\t/*\n\t**\tThe file must be opened in order to be read from. If the file\n\t**\tisn't opened, then open it. Record this fact so that it can be\n\t**\trestored to its closed state at the end.\n\t*/\n\tif (!file.Is_Open()) {\n\t\tif (!file.Open()) {\n\t\t\treturn(0);\n\t\t}\n\t\topened = true;\n\t}\n\n\t/*\n\t**\tRead in the size of the file (supposedly).\n\t*/\n\tfile.Read(&size, sizeof(size));\n\n\t/*\n\t**\tRead in the header block. This block contains the compression type\n\t**\tand skip data (among other things).\n\t*/\n\tfile.Read(&header, sizeof(header));\n\tsize -= sizeof(header);\n\n\t/*\n\t**\tIf there are skip bytes then they must be processed. Either read\n\t**\tthem into the buffer provided or skip past them. No check is made\n\t**\tto ensure that the reserved data buffer is big enough (watch out!).\n\t*/\n\tif (header.Skip) {\n\t\tsize -= header.Skip;\n\t\tif (reserved_data) {\n\t\t\tfile.Read(reserved_data, header.Skip);\n\t\t} else {\n\t\t\tfile.Seek(header.Skip, SEEK_CUR);\n\t\t}\n\t\theader.Skip = 0;\n\t}\n\n\t/*\n\t**\tDetermine where is the proper place to load the data. If both buffers\n\t**\tspecified are identical, then the data should be loaded at the end of\n\t**\tthe buffer and decompressed at the beginning.\n\t*/\n\tif (uncomp_buff.Get_Buffer() == dest_buff.Get_Buffer()) {\n\t\tsptr = (char *)sptr + uncomp_buff.Get_Size()-(size+sizeof(header));\n\t}\n\n\t/*\n\t**\tRead in the bulk of the data.\n\t*/\n\tMem_Copy(&header, sptr, sizeof(header));\n\tfile.Read((char *)sptr + sizeof(header), size);\n\n\t/*\n\t**\tDecompress the data.\n\t*/\n\tsize = (unsigned int) Uncompress_Data(sptr, dptr);\n\n\t/*\n\t**\tClose the file if necessary.\n\t*/\n\tif (opened) {\n\t\tfile.Close();\n\t}\n\treturn((long)size);\n}\n\n\nint Load_Picture(char const * filename, BufferClass& scratchbuf, BufferClass& destbuf, unsigned char * palette, PicturePlaneType )\n{\n\treturn(Load_Uncompress(CCFileClass(filename), scratchbuf, destbuf,  palette ) / 8000);\n}\n\n\n/***********************************************************************************************\n * Load_Alloc_Data -- Allocates a buffer and loads the file into it.                           *\n *                                                                                             *\n *    This is the C++ replacement for the Load_Alloc_Data function. It will allocate the       *\n *    memory big enough to hold the file and then read the file into it.                       *\n *                                                                                             *\n * INPUT:   file  -- The file to read.                                                         *\n *                                                                                             *\n *          mem   -- The memory system to use for allocation.                                  *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocated and filled memory block.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * Load_Alloc_Data(FileClass &file)\n{\n\tvoid * ptr = 0;\n\tlong size = file.Size();\n\n\tptr = new char [size];\n\tif (ptr) {\n\t\tfile.Read(ptr, size);\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * Translucent_Table_Size -- Determines the size of a translucent table.                       *\n *                                                                                             *\n *    Use this routine to determine how big the translucent table needs                        *\n *    to be given the specified number of colors. This value is typically                      *\n *    used when allocating the buffer for the translucent table.                               *\n *                                                                                             *\n * INPUT:   count -- The number of colors that are translucent.                                *\n *                                                                                             *\n * OUTPUT:  Returns the size of the translucent table.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Translucent_Table_Size(int count)\n{\n\treturn(256L + (256L * count));\n}\n\n\n/***********************************************************************************************\n * Build_Translucent_Table -- Creates a translucent control table.                             *\n *                                                                                             *\n *    The table created by this routine is used by Draw_Shape (GHOST) to                       *\n *    achieve a translucent affect. The original color of the shape will                       *\n *    show through. This differs from the fading effect, since that                            *\n *    affect only alters the background color toward a single destination                      *\n *    color.                                                                                   *\n *                                                                                             *\n * INPUT:   palette  -- Pointer to the control palette.                                        *\n *                                                                                             *\n *          control  -- Pointer to array of structures that control how                        *\n *                      the translucent table will be built.                                   *\n *                                                                                             *\n *          count    -- The number of entries in the control array.                            *\n *                                                                                             *\n *          buffer   -- Pointer to buffer to place the translucent table.                      *\n *                      If NULL is passed in, then the buffer will be                          *\n *                      allocated.                                                             *\n *                                                                                             *\n * OUTPUT:  Returns with pointer to the translucent table.                                     *\n *                                                                                             *\n * WARNINGS:   This routine is exceedingly slow. Use sparingly.                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * Build_Translucent_Table(PaletteClass const & palette, TLucentType const * control, int count, void * buffer)\n{\n\tunsigned char\tconst *table;\t\t// Remap table pointer.\n\tint\t\t\tindex;\t\t// Working color index.\n\n\tif (count && control && palette) {\n\t\tif (!buffer) {\n\t\t\tbuffer = new char [Translucent_Table_Size(count)];\n\t\t}\n\n\t\tif (buffer) {\n\t\t\tmemset(buffer, -1, 256);\n\t\t\ttable = (unsigned char*)buffer + 256;\n\n\t\t\t/*\n\t\t\t**\tBuild the individual remap tables for each translucent color.\n\t\t\t*/\n\t\t\tfor (index = 0; index < count; index++) {\n\t\t\t\t((unsigned char*)buffer)[control[index].SourceColor] = index;\n\t\t\t\tBuild_Fading_Table(palette, (void*)table, control[index].DestColor, control[index].Fading);\n\t\t\t\ttable = (unsigned char*)table + 256;\n\t\t\t}\n\t\t}\n\t}\n\treturn(buffer);\n}\n\n\n/***********************************************************************************************\n * Conquer_Build_Translucent_Table -- Builds fading table for shadow colors only.              *\n *                                                                                             *\n *    This routine will build a translucent (fading) table to remap colors into the shadow     *\n *    color region of the palette. Shadow colors are not affected by this translucent table.   *\n *    This means that a shape can be overlapped any number of times and the imagery will       *\n *    remain deterministic (and constant).                                                     *\n *                                                                                             *\n * INPUT:   palette  -- Pointer to the palette to base the translucent process on.             *\n *                                                                                             *\n *          control  -- Pointer to special control structure that specifies the                *\n *                      target color, and percentage of fade.                                  *\n *                                                                                             *\n *          count    -- The number of colors to be remapped (entries in the control array).    *\n *                                                                                             *\n *          buffer   -- Pointer to the staging buffer that will hold the translucent table     *\n *                      data. If this parameter is NULL, then an appropriate sized table       *\n *                      will be allocated.                                                     *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the translucent table data.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * Conquer_Build_Translucent_Table(PaletteClass const & palette, TLucentType const * control, int count, void * buffer)\n{\n\tunsigned char\tconst *table;\t\t// Remap table pointer.\n\n\tif (count && control) {\n\t\tif (!buffer) {\n\t\t\tbuffer = new char [Translucent_Table_Size(count)];\n\t\t}\n\n\t\tif (buffer) {\n\t\t\tmemset(buffer, -1, 256);\n\t\t\ttable = (unsigned char*)buffer + 256;\n\n\t\t\t/*\n\t\t\t**\tBuild the individual remap tables for each translucent color.\n\t\t\t*/\n\t\t\tfor (int index = 0; index < count; index++) {\n\t\t\t\t((unsigned char*)buffer)[control[index].SourceColor] = index;\n\t\t\t\tConquer_Build_Fading_Table(palette, (void*)table, control[index].DestColor, control[index].Fading);\n\t\t\t\ttable = (unsigned char*)table + 256;\n\t\t\t}\n\t\t}\n\t}\n\treturn(buffer);\n}\n\n\nvoid * Make_Fading_Table(PaletteClass const & palette, void * dest, int color, int frac)\n{\n\tif (dest) {\n\t\tunsigned char * ptr = (unsigned char *)dest;\n\n\t\t/*\n\t\t**\tFind an appropriate remap color index for every color in the palette.\n\t\t**\tThere are certain exceptions to this, but they are trapped within the\n\t\t**\tloop.\n\t\t*/\n\t\tfor (int index = 0; index < PaletteClass::COLOR_COUNT; index++) {\n\n\t\t\t/*\n\t\t\t**\tFind the color that, ideally, the working color should be remapped\n\t\t\t**\tto in the special remap range.\n\t\t\t*/\n\t\t\tRGBClass trycolor = palette[index];\n\t\t\ttrycolor.Adjust(frac, palette[color]);\t\t\t// Try to match this color.\n\n\t\t\t/*\n\t\t\t**\tSearch through the remap range to find the color that should be remapped\n\t\t\t**\tto. This special range is used for shadows or other effects that are\n\t\t\t**\tnot compounded if additively applied.\n\t\t\t*/\n\t\t\t*ptr++ = palette.Closest_Color(trycolor);\n\t\t}\n\t}\n\treturn(dest);\n}\n\n\nvoid * Conquer_Build_Fading_Table(PaletteClass const & palette, void * dest, int color, int frac)\n{\n\tif (dest) {\n\t\tunsigned char * ptr = (unsigned char *)dest;\n//\t\tHSVClass desthsv = palette[color];\n\n\t\t/*\n\t\t**\tFind an appropriate remap color index for every color in the palette.\n\t\t**\tThere are certain exceptions to this, but they are trapped within the\n\t\t**\tloop.\n\t\t*/\n\t\tfor (int index = 0; index < PaletteClass::COLOR_COUNT; index++) {\n\n\t\t\t/*\n\t\t\t**\tIf this color should not be remapped, then it will be stored as a remap\n\t\t\t**\tto itself. This is effectively no remap.\n\t\t\t*/\n\t\t\tif (index > PaletteClass::COLOR_COUNT-16 || index == 0) {\n\t\t\t\t*ptr++ = index;\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tFind the color that, ideally, the working color should be remapped\n\t\t\t\t**\tto in the special remap range.\n\t\t\t\t*/\n\t\t\t\tRGBClass trycolor = palette[index];\n\t\t\t\ttrycolor.Adjust(frac, palette[color]);\t\t\t// Try to match this color.\n\n\t\t\t\t/*\n\t\t\t\t**\tSearch through the remap range to find the color that should be remapped\n\t\t\t\t**\tto. This special range is used for shadows or other effects that are\n\t\t\t\t**\tnot compounded if additively applied.\n\t\t\t\t*/\n\t\t\t\tint best = -1;\n\t\t\t\tint bvalue = 0;\n\t\t\t\tfor (int id = PaletteClass::COLOR_COUNT-16; id < PaletteClass::COLOR_COUNT-1; id++) {\n\t\t\t\t\tint diff = palette[id].Difference(trycolor);\n\t\t\t\t\tif (best == -1 || diff < bvalue) {\n\t\t\t\t\t\tbest = id;\n\t\t\t\t\t\tbvalue = diff;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t*ptr++ = best;\n\t\t\t}\n\t\t}\n\t}\n\treturn(dest);\n}\n\n\n#ifdef OBSOLETE\n//int Desired_Facing8(int x1, int y1, int x2, int y2)\nDirType xDesired_Facing8(int x1, int y1, int x2, int y2)\n{\n\tint index = 0;\t\t\t\t// Facing composite value.\n\n\t/*\n\t**\tFigure the absolute X difference. This determines\n\t**\tif the facing is leftward or not.\n\t*/\n\tint xdiff = x2-x1;\n\tif (xdiff < 0) {\n\t\tindex |= 0x00C0;\n\t\txdiff = -xdiff;\n\t}\n\n\t/*\n\t**\tFigure the absolute Y difference. This determines\n\t**\tif the facing is downward or not. This also clarifies\n\t**\texactly which quadrant the facing lies.\n\t*/\n\tint ydiff = y1-y2;\n\tif (ydiff < 0) {\n\t\tindex ^= 0x0040;\n\t\tydiff = -ydiff;\n\t}\n\n\t/*\n\t**\tDetermine which of the two direction offsets it bigger. The\n\t**\toffset direction that is bigger (X or Y) will indicate which\n\t**\torthogonal direction the facing is closer to.\n\t*/\n\tunsigned bigger;\n\tunsigned smaller;\n\tif (xdiff < ydiff) {\n\t\tsmaller = xdiff;\n\t\tbigger = ydiff;\n\t} else {\n\t\tsmaller = ydiff;\n\t\tbigger = xdiff;\n\t}\n\n\t/*\n\t**\tIf on the diagonal, then incorporate this into the facing\n\t**\tand then bail. The facing is known.\n\t*/\n\tif (((bigger+1)/2) <= smaller) {\n\t\tindex += 0x0020;\n\t\treturn(DirType(index));\n\t}\n\n\t/*\n\t**\tDetermine if the facing is closer to the Y axis or\n\t**\tthe X axis.\n\t*/\n\tint adder = (index & 0x0040);\n\tif (xdiff == bigger) {\n\t\tadder ^= 0x0040;\n\t}\n\tindex += adder;\n\n\treturn(DirType(index));\n}\n\n\n//int Desired_Facing256(int srcx, int srcy, int dstx, int dsty)\nDirType xDesired_Facing256(int srcx, int srcy, int dstx, int dsty)\n{\n\tint composite=0;\t\t// Facing built from intermediate calculations.\n\n\t/*\n\t**\tFetch the absolute X difference. This also gives a clue as\n\t**\tto which hemisphere the direction lies.\n\t*/\n\tint xdiff = dstx - srcx;\n\tif (xdiff < 0) {\n\t\tcomposite |= 0x00C0;\n\t\txdiff = -xdiff;\n\t}\n\n\t/*\n\t**\tFetch the absolute Y difference. This clarifies the exact\n\t**\tquadrant that the direction lies.\n\t*/\n\tint ydiff = srcy - dsty;\n\tif (ydiff < 0) {\n\t\tcomposite ^= 0x0040;\n\t\tydiff = -ydiff;\n\t}\n\n\t/*\n\t**\tBail early if the coordinates are the same. This check also\n\t**\thas the added bonus of ensuring that checking for division\n\t**\tby zero is not needed in the following section.\n\t*/\n\tif (xdiff == 0 && ydiff == 0) return(DirType(0xFF));\n\n\t/*\n\t**\tDetermine which of the two direction offsets it bigger. The\n\t**\toffset direction that is bigger (X or Y) will indicate which\n\t**\torthogonal direction the facing is closer to.\n\t*/\n\tunsigned bigger;\n\tunsigned smaller;\n\tif (xdiff < ydiff) {\n\t\tsmaller = xdiff;\n\t\tbigger = ydiff;\n\t} else {\n\t\tsmaller = ydiff;\n\t\tbigger = xdiff;\n\t}\n\n\t/*\n\t**\tNow that the quadrant is known, we need to determine how far\n\t**\tfrom the orthogonal directions, the facing lies. This value\n\t**\tis calculated as a ratio from 0 (matches orthogonal) to 31\n\t**\t(matches diagonal).\n\t*/\n\tint frac = (smaller * 32U) / bigger;\n\n\t/*\n\t**\tGiven the quadrant and knowing whether the facing is closer\n\t**\tto the X or Y axis, we must make an adjustment toward the\n\t**\tsubsequent quadrant if necessary.\n\t*/\n\tint adder = (composite & 0x0040);\n\tif (xdiff > ydiff) {\n\t\tadder ^= 0x0040;\n\t}\n\tif (adder) {\n\t\tfrac = (adder - frac)-1;\n\t}\n\n\t/*\n\t**\tIntegrate the fraction value into the quadrant.\n\t*/\n\tcomposite += frac;\n\n\t/*\n\t**\tReturn with the final facing value.\n\t*/\n\treturn(DirType(composite & 0x00FF));\n}\n#endif\n"
  },
  {
    "path": "CODE/JSHELL.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/JSHELL.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : JSHELL.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/13/95                                                     *\n *                                                                                             *\n *                  Last Update : March 13, 1995 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef JSHELL_H\n#define JSHELL_H\n\n\n#include\t<assert.h>\n\n#ifdef WIN32\n//#define getch\tGet_Key_Num\n//#define kbhit\tCheck_Key_Num\n#include\t\"key.h\"\n#else\n#include\t<conio.h>\n#endif\n\n/*\n**\tInterface class to the keyboard. This insulates the game from library vagaries. Most\n**\tnotable being the return values are declared as \"int\" in the library whereas C&C\n**\texpects it to be of KeyNumType.\n*/\n#ifdef WIN32\n//#define KeyNumType\tint\n//#define KeyASCIIType\tint\n\n//lint -esym(1725,KeyboardClass::MouseQX,KeyboardClass::MouseQY)\nstruct KeyboardClass : public WWKeyboardClass\n\n#else\nstruct KeyboardClass\n#endif\n{\n\n\t/*\n\t**\tThis flag is used to indicate whether the WW library has taken over\n\t**\tthe keyboard or not. If not, then the normal console input\n\t**\ttakes precedence.\n\t*/\n\tunsigned IsLibrary;\n\n#ifndef WIN32\n\tint &MouseQX;\n\tint &MouseQY;\n\n\tKeyboardClass() :\n\t\tIsLibrary(true),\n\t\tMouseQX(::MouseQX),\n\t\tMouseQY(::MouseQY)\n\t{}\n\tKeyNumType Get(void) {return (IsLibrary ? (KeyNumType)Get_Key_Num() : (KeyNumType)getch());};\n\tKeyNumType Check(void) {return (IsLibrary ? (KeyNumType)Check_Key_Num() : (KeyNumType)kbhit());};\n\tKeyASCIIType To_ASCII(KeyNumType key) {return((KeyASCIIType)KN_To_KA(key));};\n\tvoid Clear(void) {if (IsLibrary) Clear_KeyBuffer();};\n\tint Down(KeyNumType key) {return(Key_Down(key));};\n#else\n\tKeyboardClass() : IsLibrary(true) {}\n\tKeyNumType Get(void) {return ((KeyNumType)WWKeyboardClass::Get());};\n\tKeyNumType Check(void) {return ((KeyNumType)WWKeyboardClass::Check());};\n\tKeyASCIIType To_ASCII(KeyNumType key) {return((KeyASCIIType)WWKeyboardClass::To_ASCII(key));};\n\tvoid Clear(void) {WWKeyboardClass::Clear();};\n\tint Down(KeyNumType key) {return(WWKeyboardClass::Down(key));};\n#endif\n\n\tint Mouse_X(void) {return(Get_Mouse_X());};\n\tint Mouse_Y(void) {return(Get_Mouse_Y());};\n};\n\n\n/*\n**\tThese templates allow enumeration types to have simple bitwise\n**\tarithmatic performed. The operators must be instatiated for the\n**\tenumerated types desired.\n*/\ntemplate<class T> inline T operator ++(T & a)\n{\n\ta = (T)((int)a + (int)1);\n\treturn(a);\n}\ntemplate<class T> inline T operator ++(T & a, int)\n{\n\tT aa = a;\n\ta = (T)((int)a + (int)1);\n\treturn(aa);\n}\ntemplate<class T> inline T operator --(T & a)\n{\n\ta = (T)((int)a - (int)1);\n\treturn(a);\n}\ntemplate<class T> inline T operator --(T & a, int)\n{\n\tT aa = a;\n\ta = (T)((int)a - (int)1);\n\treturn(aa);\n}\ntemplate<class T> inline T operator |(T t1, T t2)\n{\n\treturn((T)((int)t1 | (int)t2));\n}\ntemplate<class T> inline T operator &(T t1, T t2)\n{\n\treturn((T)((int)t1 & (int)t2));\n}\ntemplate<class T> inline T operator ~(T t1)\n{\n\treturn((T)(~(int)t1));\n}\n\n#ifndef WIN32\ntemplate<class T> inline T min(T value1, T value2)\n{\n\tif (value1 < value2) {\n\t\treturn(value1);\n\t}\n\treturn(value2);\n}\nint min(int, int);\nlong min(long, long);\n\ntemplate<class T> inline T max(T value1, T value2)\n{\n\tif (value1 > value2) {\n\t\treturn(value1);\n\t}\n\treturn(value2);\n}\nint max(int, int);\nlong max(long, long);\n#endif\n\ntemplate<class T> inline void swap(T &value1, T &value2)\n{\n\tT temp = value1;\n\tvalue1 = value2;\n\tvalue2 = temp;\n}\nint swap(int, int);\nlong swap(long, long);\n\ntemplate<class T> inline\nT Bound(T original, T minval, T maxval)\n{\n\tif (original < minval) return(minval);\n\tif (original > maxval) return(maxval);\n\treturn(original);\n};\nint Bound(signed int, signed int, signed int);\nunsigned Bound(unsigned, unsigned, unsigned);\nlong Bound(long, long, long);\n\ntemplate<class T>\nT _rotl(T X, int n)\n{\n\treturn((T)(( ( ( X ) << n ) | ( ( X ) >> ( (sizeof(T)*8) - n ) ) )));\n}\n\n\n/*\n**\tThis macro serves as a general way to determine the number of elements\n**\twithin an array.\n*/\n#define\tARRAY_LENGTH(x)\tint(sizeof(x)/sizeof(x[0]))\n#define\tARRAY_SIZE(x)\t\tint(sizeof(x)/sizeof(x[0]))\n\n\n/*\n**\tThe shape flags are likely to be \"or\"ed together and other such bitwise\n**\tmanipulations. These instatiated operator templates allow this.\n*/\ninline ShapeFlags_Type operator |(ShapeFlags_Type, ShapeFlags_Type);\ninline ShapeFlags_Type operator &(ShapeFlags_Type, ShapeFlags_Type);\ninline ShapeFlags_Type operator ~(ShapeFlags_Type);\n\n\nvoid Set_Bit(void * array, int bit, int value);\n#pragma aux Set_Bit parm [esi] [ecx] [eax] \\\n\tmodify [esi ebx] = \t\t\t\\\n\t\"mov\tebx,ecx\"\t\t\t\t\t\\\n\t\"shr\tebx,5\"\t\t\t\t\t\\\n\t\"and\tecx,01Fh\"\t\t\t\t\\\n\t\"btr\t[esi+ebx*4],ecx\"\t\t\\\n\t\"or\teax,eax\"\t\t\t\t\t\\\n\t\"jz\tok\"\t\t\t\t\t\t\\\n\t\"bts\t[esi+ebx*4],ecx\"\t\t\\\n\t\"ok:\"\n\nint Get_Bit(void const * array, int bit);\n#pragma aux Get_Bit parm [esi] [eax] \\\n\tmodify [esi ebx] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"mov\tebx,eax\"\t\t\t\t\t\\\n\t\"shr\tebx,5\"\t\t\t\t\t\\\n\t\"and\teax,01Fh\"\t\t\t\t\\\n\t\"bt\t[esi+ebx*4],eax\"\t\t\\\n\t\"setc\tal\"\n\nint First_True_Bit(void const * array);\n#pragma aux First_True_Bit parm [esi] \\\n\tmodify [esi ebx] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"mov\teax,-32\"\t\t\t\t\t\\\n\t\"again:\"\t\t\t\t\t\t\t\\\n\t\"add\teax,32\"\t\t\t\t\t\\\n\t\"mov\tebx,[esi]\"\t\t\t\t\\\n\t\"add\tesi,4\"\t\t\t\t\t\\\n\t\"bsf\tebx,ebx\"\t\t\t\t\t\\\n\t\"jz\tagain\"\t\t\t\t\t\\\n\t\"add\teax,ebx\"\n\nint First_False_Bit(void const * array);\n#pragma aux First_False_Bit parm [esi] \\\n\tmodify [esi ebx] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"mov\teax,-32\"\t\t\t\t\t\\\n\t\"again:\"\t\t\t\t\t\t\t\\\n\t\"add\teax,32\"\t\t\t\t\t\\\n\t\"mov\tebx,[esi]\"\t\t\t\t\\\n\t\"not\tebx\"\t\t\t\t\t\t\\\n\t\"add\tesi,4\"\t\t\t\t\t\\\n\t\"bsf\tebx,ebx\"\t\t\t\t\t\\\n\t\"jz\tagain\"\t\t\t\t\t\\\n\t\"add\teax,ebx\"\n\n#ifdef OBSOLETE\nextern int Bound(int original, int min, int max);\n#pragma aux Bound parm [eax] [ebx] [ecx] \\\n\tmodify [eax] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"cmp\tebx,ecx\"\t\t\t\t\t\\\n\t\"jl\tokorder\"\t\t\t\t\t\\\n\t\"xchg\tebx,ecx\"\t\t\t\t\t\\\n\t\"okorder: cmp\teax,ebx\"\t\t\\\n\t\"jg\tokmin\"\t\t\t\t\t\\\n\t\"mov\teax,ebx\"\t\t\t\t\t\\\n\t\"okmin: cmp\teax,ecx\"\t\t\t\\\n\t\"jl\tokmax\"\t\t\t\t\t\\\n\t\"mov\teax,ecx\"\t\t\t\t\t\\\n\t\"okmax:\"\n\nextern unsigned Bound(unsigned original, unsigned min, unsigned max);\n#pragma aux Bound parm [eax] [ebx] [ecx] \\\n\tmodify [eax] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"cmp\tebx,ecx\"\t\t\t\t\t\\\n\t\"jb\tokorder\"\t\t\t\t\t\\\n\t\"xchg\tebx,ecx\"\t\t\t\t\t\\\n\t\"okorder: cmp\teax,ebx\"\t\t\\\n\t\"ja\tokmin\"\t\t\t\t\t\\\n\t\"mov\teax,ebx\"\t\t\t\t\t\\\n\t\"okmin: cmp\teax,ecx\"\t\t\t\\\n\t\"jb\tokmax\"\t\t\t\t\t\\\n\t\"mov\teax,ecx\"\t\t\t\t\t\\\n\t\"okmax:\"\n#endif\n\n\nunsigned Fixed_To_Cardinal(unsigned base, unsigned fixed);\n#pragma aux Fixed_To_Cardinal parm [eax] [edx] \\\n\tmodify [edx] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"mul\tedx\"\t\t\t\t\t\t\\\n\t\"add\teax,080h\"\t\t\t\t\\\n\t\"test\teax,0FF000000h\"\t\t\\\n\t\"jz\tok\"\t\t\t\t\t\t\\\n\t\"mov\teax,000FFFFFFh\"\t\t\\\n\t\"ok:\"\t\t\t\t\t\t\t\t\\\n\t\"shr\teax,8\"\n\n\nunsigned Cardinal_To_Fixed(unsigned base, unsigned cardinal);\n#pragma aux Cardinal_To_Fixed parm [ebx] [eax] \\\n\tmodify [edx] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"or\tebx,ebx\"\t\t\t\t\t\\\n\t\"jz\tfini\"\t\t\t\t\t\t\\\n\t\"shl\teax,8\"\t\t\t\t\t\\\n\t\"xor\tedx,edx\"\t\t\t\t\t\\\n\t\"div\tebx\"\t\t\t\t\t\t\\\n\t\"fini:\"\n\n\n#ifndef OUTPORTB\n#define OUTPORTB\nextern void outportb(int port, unsigned char data);\n#pragma aux outportb parm [edx] [al] =\t\t\\\n\t\t\"out\tdx,al\"\n\nextern void outport(int port, unsigned short data);\n#pragma aux outport parm [edx] [ax] =\t\t\\\n\t\t\"out\tdx,al\"\t\t\\\n\t\t\"inc\tdx\"\t\t\t\\\n\t\t\"mov\tal,ah\"\t\t\\\n\t\t\"out\tdx,al\"\n#endif\n\n\n/*\n**\tTimer objects that fetch the appropriate timer value according to\n**\tthe type of timer they are.\n*/\nextern long Frame;\nclass FrameTimerClass\n{\n\tpublic:\n\t\tlong operator () (void) const {return(Frame);};\n\t\toperator long (void) const {return(Frame);};\n};\n\n\n#ifndef WIN32\nextern bool TimerSystemOn;\nextern \"C\" {\n\tlong Get_System_Tick_Count(void);\n\tlong Get_User_Tick_Count(void);\n}\n//bool Init_Timer_System(unsigned int freq, int partial=false);\nbool Remove_Timer_System(void);\n#else\nextern WinTimerClass\t*\t\tWindowsTimer;\n#endif\n\n#ifndef SYSTEM_TIMER_CLASS\n#define SYSTEM_TIMER_CLASS\nclass SystemTimerClass\n{\n\tpublic:\n\t\t#ifdef WIN32\n\t\t\tlong operator () (void) const {if (!WindowsTimer) return(0);return(WindowsTimer->Get_System_Tick_Count());};\n\t\t\toperator long (void) const {if (!WindowsTimer) return(0);return(WindowsTimer->Get_System_Tick_Count());};\n\t\t#else\n\t\t\tlong operator () (void) const {return(Get_System_Tick_Count());};\n\t\t\toperator long (void) const {return(Get_System_Tick_Count());};\n\t\t#endif\n};\n#endif\n\n\nclass UserTimerClass\n{\n\tpublic:\n\t\t#ifdef WIN32\n\t\t\tlong operator () (void) const {if (!WindowsTimer) return(0);return(WindowsTimer->Get_User_Tick_Count());};\n\t\t\toperator long (void) const {if (!WindowsTimer) return(0);return(WindowsTimer->Get_User_Tick_Count());};\n\t\t#else\n\t\t\tlong operator () (void) const {return(Get_User_Tick_Count());};\n\t\t\toperator long (void) const {return(Get_User_Tick_Count());};\n\t\t#endif\n};\n\n\ntemplate<class T>\nvoid Bubble_Sort(T * array, int count)\n{\n\tif (array != NULL && count > 1) {\n\t\tbool swapflag;\n\n\t\tdo {\n\t\t\tswapflag = false;\n\t\t\tfor (int index = 0; index < count-1; index++) {\n\t\t\t\tif (array[index] > array[index+1]) {\n\t\t\t\t\tT temp = array[index];\n\t\t\t\t\tarray[index] = array[index+1];\n\t\t\t\t\tarray[index+1] = temp;\n\t\t\t\t\tswapflag = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} while (swapflag);\n\t}\n}\n\ntemplate<class T>\nvoid PBubble_Sort(T * array, int count)\n{\n\tif (array != NULL && count > 1) {\n\t\tbool swapflag;\n\n\t\tdo {\n\t\t\tswapflag = false;\n\t\t\tfor (int index = 0; index < count-1; index++) {\n\t\t\t\tif (*array[index] > *array[index+1]) {\n\t\t\t\t\tT temp = array[index];\n\t\t\t\t\tarray[index] = array[index+1];\n\t\t\t\t\tarray[index+1] = temp;\n\t\t\t\t\tswapflag = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} while (swapflag);\n\t}\n}\n\ntemplate<class T>\nvoid PNBubble_Sort(T * array, int count)\n{\n\tif (array != NULL && count > 1) {\n\t\tbool swapflag;\n\n\t\tdo {\n\t\t\tswapflag = false;\n\t\t\tfor (int index = 0; index < count-1; index++) {\n\t\t\t\tif (stricmp(array[index]->Name(), array[index+1]->Name()) > 0) {\n\t\t\t\t\tT temp = array[index];\n\t\t\t\t\tarray[index] = array[index+1];\n\t\t\t\t\tarray[index+1] = temp;\n\t\t\t\t\tswapflag = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} while (swapflag);\n\t}\n}\n\ntemplate<class T>\nclass SmartPtr\n{\n\tpublic:\n\t\tSmartPtr(NoInitClass const &) {}\n\t\tSmartPtr(T * realptr = 0) : Pointer(realptr) {}\n\t\tSmartPtr(SmartPtr const & rvalue) : Pointer(rvalue.Pointer) {}\n\t\t~SmartPtr(void) {Pointer = 0;}\n\n\t\toperator T * (void) const {return(Pointer);}\n\n\t\toperator long (void) const {return((long)Pointer);}\n\n\t\tSmartPtr<T> operator ++ (int) {assert(Pointer != 0);SmartPtr<T> temp = *this;++Pointer;return(temp);}\n\t\tSmartPtr<T> & operator ++ (void) {assert(Pointer != 0);++Pointer;return(*this);}\n\t\tSmartPtr<T> operator -- (int) {assert(Pointer != 0);SmartPtr<T> temp = *this;--Pointer;return(temp);}\n\t\tSmartPtr<T> & operator -- (void) {assert(Pointer != 0);--Pointer;return(*this);}\n\n\t\tSmartPtr & operator = (SmartPtr const & rvalue) {Pointer = rvalue.Pointer;return(*this);}\n\t\tT * operator -> (void) const {assert(Pointer != 0);return(Pointer);}\n\t\tT & operator * (void) const {assert(Pointer != 0);return(*Pointer);}\n\n\tprivate:\n\t\tT * Pointer;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/KEY.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/KEY.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Keyboard Library                                    *\n *                                                                                             *\n *                    File Name : KEYBOARD.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 10/16/95                                                     *\n *                                                                                             *\n *                  Last Update : November 2, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer               *\n *   WWKeyboardClass::Check -- Checks to see if a key is in the buffer                         *\n *   WWKeyboardClass::Clear -- Clears the keyboard buffer.                                     *\n *   WWKeyboardClass::Down -- Checks to see if the specified key is being held down.           *\n *   WWKeyboardClass::Fetch_Element -- Extract the next element in the keyboard buffer.        *\n *   WWKeyboardClass::Fill_Buffer_From_Syste -- Extract and process any queued windows messages*\n *   WWKeyboardClass::Get -- Logic to get a metakey from the buffer                            *\n *   WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels           *\n *   WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars       *\n *   WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels           *\n *   WWKeyboardClass::Is_Buffer_Empty -- Checks to see if the keyboard buffer is empty.        *\n *   WWKeyboardClass::Is_Buffer_Full -- Determines if the keyboard buffer is full.             *\n *   WWKeyboardClass::Is_Mouse_Key -- Checks to see if specified key refers to the mouse.      *\n *   WWKeyboardClass::Message_Handler -- Process a windows message as it relates to the keyboar*\n *   WWKeyboardClass::Peek_Element -- Fetches the next element in the keyboard buffer.         *\n *   WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                         *\n *   WWKeyboardClass::Put_Element -- Put a keyboard data element into the buffer.              *\n *   WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer    *\n *   WWKeyboardClass::To_ASCII -- Convert the key value into an ASCII representation.          *\n *   WWKeyboardClass::Available_Buffer_Room -- Fetch the quantity of free elements in the keybo*\n *   WWKeyboardClass::Put_Mouse_Message -- Stores a mouse type message into the keyboard buffer*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"key.h\"\n\n#include\t\"monoc.h\"\n\n//void Message_Loop(void);\n\n//WWKeyboardClass * _Kbd = NULL;\n\n\n#define\tARRAY_SIZE(x)\t\tint(sizeof(x)/sizeof(x[0]))\n\n\n/***********************************************************************************************\n * WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class                *\n *                                                                                             *\n * INPUT:\t\tnone\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * OUTPUT:     none\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nWWKeyboardClass::WWKeyboardClass(void) :\n\tMouseQX(0),\n\tMouseQY(0),\n\tHead(0),\n\tTail(0)\n{\n//\t_Kbd = this;\n\n\tmemset(KeyState, '\\0', sizeof(KeyState));\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer                 *\n *                                                                                             *\n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     int\t\t- the key value that was pulled from buffer (includes bits)\t\t\t\t  *                                                                                *\n *                                                                                             *\n * WARNINGS:   If the key was a mouse event MouseQX and MouseQY will be updated                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nunsigned short WWKeyboardClass::Buff_Get(void)\n{\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t\t\t// wait for key in buffer\n\n\tunsigned short temp = Fetch_Element();\n\tif (Is_Mouse_Key(temp)) {\n\t\tMouseQX = Fetch_Element();\n\t\tMouseQY = Fetch_Element();\n\t}\n\treturn(temp);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Is_Mouse_Key -- Checks to see if specified key refers to the mouse.        *\n *                                                                                             *\n *    This checks the specified key code to see if it refers to the mouse buttons.             *\n *                                                                                             *\n * INPUT:   key   -- The key to check.                                                         *\n *                                                                                             *\n * OUTPUT:  bool; Is the key a mouse button key?                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Is_Mouse_Key(unsigned short key)\n{\n\tkey &= 0xFF;\n\treturn (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Check -- Checks to see if a key is in the buffer                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *   09/24/1996 JLB : Converted to new style keyboard system.                                  *\n *=============================================================================================*/\nunsigned short WWKeyboardClass::Check(void) const\n{\n\t((WWKeyboardClass *)this)->Fill_Buffer_From_System();\n\tif (Is_Buffer_Empty()) return(false);\n\treturn(Peek_Element());\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Get -- Logic to get a metakey from the buffer                              *\n *                                                                                             *\n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     int\t\t- the meta key taken from the buffer.\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:\tThis routine will not return until a keypress is received\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nunsigned short WWKeyboardClass::Get(void)\n{\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t// wait for key in buffer\n\treturn (Buff_Get());\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                           *\n *                                                                                             *\n * INPUT:\t\tint\t \t- the key to insert into the buffer          \t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     bool\t\t- true if key is sucessfuly inserted.\t\t\t\t\t\t\t              *\n *                                                                                             *\n * WARNINGS:   none\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Put(unsigned short key)\n{\n\tif (!Is_Buffer_Full()) {\n\t\tPut_Element(key);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Put_Key_Message(unsigned short vk_key, bool release)\n{\n\t/*\n\t** Get the status of all of the different keyboard modifiers.  Note, only pay attention\n\t** to numlock and caps lock if we are dealing with a key that is affected by them.  Note\n\t** that we do not want to set the shift, ctrl and alt bits for Mouse keypresses as this\n\t** would be incompatible with the dos version.\n\t*/\n\tif (!Is_Mouse_Key(vk_key)) {\n\t\tif (((GetKeyState(VK_SHIFT) & 0x8000) != 0) ||\n\t\t\t((GetKeyState(VK_CAPITAL) & 0x0008) != 0) ||\n\t\t\t((GetKeyState(VK_NUMLOCK) & 0x0008) != 0)) {\n\n\t\t\tvk_key |= WWKEY_SHIFT_BIT;\n\t\t}\n\t\tif ((GetKeyState(VK_CONTROL) & 0x8000) != 0) {\n\t\t\tvk_key |= WWKEY_CTRL_BIT;\n\t\t}\n\t\tif ((GetKeyState(VK_MENU) & 0x8000) != 0) {\n\t\t\tvk_key |= WWKEY_ALT_BIT;\n\t\t}\n\t}\n\n\tif (release) {\n\t\tvk_key |= WWKEY_RLS_BIT;\n\t}\n\n\t/*\n\t** Finally use the put command to enter the key into the keyboard\n\t** system.\n\t*/\n\treturn(Put(vk_key));\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Put_Mouse_Message -- Stores a mouse type message into the keyboard buffer. *\n *                                                                                             *\n *    This routine will store the mouse type event into the keyboard buffer. It also checks    *\n *    to ensure that there is enough room in the buffer so that partial mouse events won't     *\n *    be recorded.                                                                             *\n *                                                                                             *\n * INPUT:   vk_key   -- The mouse key message itself.                                          *\n *                                                                                             *\n *          x,y      -- The mouse coordinates at the time of the event.                        *\n *                                                                                             *\n *          release  -- Is this a mouse button release?                                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the event stored sucessfully into the keyboard buffer?                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Put_Mouse_Message(unsigned short vk_key, int x, int y, bool release)\n{\n\tif (Available_Buffer_Room() >= 3 && Is_Mouse_Key(vk_key)) {\n\t\tPut_Key_Message(vk_key, release);\n\t\tPut((unsigned short)x);\n\t\tPut((unsigned short)y);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::To_ASCII -- Convert the key value into an ASCII representation.            *\n *                                                                                             *\n *    This routine will convert the key code specified into an ASCII value. This takes into    *\n *    consideration the language and keyboard mapping of the host Windows system.              *\n *                                                                                             *\n * INPUT:   key   -- The key code to convert into ASCII.                                       *\n *                                                                                             *\n * OUTPUT:  Returns with the key converted into ASCII. If the key has no ASCII equivalent,     *\n *          then '\\0' is returned.                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar WWKeyboardClass::To_ASCII(unsigned short key)\n{\n\t/*\n\t**\tReleased keys never translate into an ASCII value.\n\t*/\n\tif (key & WWKEY_RLS_BIT) {\n\t\treturn('\\0');\n\t}\n\n\t/*\n\t**\tSet the KeyState buffer to reflect the shift bits stored in the key value.\n\t*/\n\tif (key & WWKEY_SHIFT_BIT) {\n\t\tKeyState[VK_SHIFT] = 0x80;\n\t}\n\tif (key & WWKEY_CTRL_BIT) {\n\t\tKeyState[VK_CONTROL] = 0x80;\n\t}\n\tif (key & WWKEY_ALT_BIT) {\n\t\tKeyState[VK_MENU] = 0x80;\n\t}\n\n\t/*\n\t**\tAsk windows to translate the key into an ASCII equivalent.\n\t*/\n\tchar buffer[10];\n\tint result = 1;\n\tint scancode = 0;\n\n\tscancode = MapVirtualKey(key & 0xFF, 0);\n\tresult = ToAscii((UINT)(key & 0xFF), (UINT)scancode, (PBYTE)KeyState, (LPWORD)buffer, (UINT)0);\n\n\t/*\n\t**\tRestore the KeyState buffer back to pristine condition.\n\t*/\n\tif (key & WWKEY_SHIFT_BIT) {\n\t\tKeyState[VK_SHIFT] = 0;\n\t}\n\tif (key & WWKEY_CTRL_BIT) {\n\t\tKeyState[VK_CONTROL] = 0;\n\t}\n\tif (key & WWKEY_ALT_BIT) {\n\t\tKeyState[VK_MENU] = 0;\n\t}\n\n\t/*\n\t**\tIf Windows could not perform the translation as expected, then\n\t**\treturn with a null ASCII value.\n\t*/\n\tif (result != 1) {\n\t\treturn('\\0');\n\t}\n\n\treturn(buffer[0]);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Down -- Checks to see if the specified key is being held down.             *\n *                                                                                             *\n *    This routine will examine the key specified to see if it is currently being held down.   *\n *                                                                                             *\n * INPUT:   key   -- The key to check.                                                         *\n *                                                                                             *\n * OUTPUT:  bool; Is the specified key currently being held down?                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nWWKeyboardClass::Down(unsigned short key)\n{\n\treturn(GetAsyncKeyState(key & 0xFF));\n}\n\n\nextern \"C\" {\n\tvoid __cdecl Stop_Execution (void);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Fetch_Element -- Extract the next element in the keyboard buffer.          *\n *                                                                                             *\n *    This routine will extract the next pending element in the keyboard queue. If there is    *\n *    no element available, then NULL is returned.                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the element extracted from the queue. An empty queue is signified     *\n *          by a 0 return value.                                                               *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned short WWKeyboardClass::Fetch_Element(void)\n{\n\tunsigned short val = 0;\n\tif (Head != Tail) {\n\t\tval = Buffer[Head];\n\n\t\tHead = (Head + 1) % ARRAY_SIZE(Buffer);\n\t}\n\treturn(val);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Peek_Element -- Fetches the next element in the keyboard buffer.           *\n *                                                                                             *\n *    This routine will examine and return with the next element in the keyboard buffer but    *\n *    it will not alter or remove that element. Use this routine to see what is pending in     *\n *    the keyboard queue.                                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the next element in the keyboard queue. If the keyboard buffer is     *\n *          empty, then 0 is returned.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned short WWKeyboardClass::Peek_Element(void) const\n{\n\tif (!Is_Buffer_Empty()) {\n\t\treturn(Buffer[Head]);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Put_Element -- Put a keyboard data element into the buffer.                *\n *                                                                                             *\n *    This will put one keyboard data element into the keyboard buffer. Typically, this data   *\n *    is a key code, but it might be mouse coordinates.                                        *\n *                                                                                             *\n * INPUT:   val   -- The data element to add to the keyboard buffer.                           *\n *                                                                                             *\n * OUTPUT:  bool; Was the keyboard element added successfully? A failure would indicate that   *\n *                the keyboard buffer is full.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Put_Element(unsigned short val)\n{\n\tif (!Is_Buffer_Full()) {\n\t\tint temp = (Tail+1) % ARRAY_SIZE(Buffer);\n\t\tBuffer[Tail] = val;\n\t\tTail = temp;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Is_Buffer_Full -- Determines if the keyboard buffer is full.               *\n *                                                                                             *\n *    This routine will examine the keyboard buffer to determine if it is completely           *\n *    full of queued keyboard events.                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the keyboard buffer completely full?                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Is_Buffer_Full(void) const\n{\n\tif ((Tail + 1) % ARRAY_SIZE(Buffer) == Head) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Is_Buffer_Empty -- Checks to see if the keyboard buffer is empty.          *\n *                                                                                             *\n *    This routine will examine the keyboard buffer to see if it contains no events at all.    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the keyboard buffer currently without any pending events queued?          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Is_Buffer_Empty(void) const\n{\n\tif (Head == Tail) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Fill_Buffer_From_Syste -- Extract and process any queued windows messages. *\n *                                                                                             *\n *    This routine will extract and process any windows messages in the windows message        *\n *    queue. It is presumed that the normal message handler will call the keyboard             *\n *    message processing function.                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid WWKeyboardClass::Fill_Buffer_From_System(void)\n{\n\tif (!Is_Buffer_Full()) {\n\t\tMSG\tmsg;\n\t\twhile (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {\n\t\t  \tif (!GetMessage( &msg, NULL, 0, 0 )) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tTranslateMessage(&msg);\n\t\t\tDispatchMessage(&msg);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Clear -- Clears the keyboard buffer.                                       *\n *                                                                                             *\n *    This routine will clear the keyboard buffer of all pending keyboard events.              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid WWKeyboardClass::Clear(void)\n{\n\t/*\n\t**\tExtract any windows pending keyboard message events and then clear out the keyboard\n\t**\tbuffer.\n\t*/\n\tFill_Buffer_From_System();\n\tHead = Tail;\n\n\t/*\n\t**\tPerform a second clear to handle the rare case of the keyboard buffer being full and there\n\t**\tstill remains keyboard related events in the windows message queue.\n\t*/\n\tFill_Buffer_From_System();\n\tHead = Tail;\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Message_Handler -- Process a windows message as it relates to the keyboard *\n *                                                                                             *\n *    This routine will examine the Windows message specified. If the message relates to an    *\n *    event that the keyboard input system needs to process, then it will be processed         *\n *    accordingly.                                                                             *\n *                                                                                             *\n * INPUT:   window   -- Handle to the window receiving the message.                            *\n *                                                                                             *\n *          message  -- The message number of this event.                                      *\n *                                                                                             *\n *          wParam   -- The windows specific word parameter (meaning depends on message).      *\n *                                                                                             *\n *          lParam   -- The windows specific long word parameter (meaning is message dependant)*\n *                                                                                             *\n * OUTPUT:  bool; Was this keyboard message recognized and processed? A 'false' return value   *\n *                means that the message should be processed normally.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Message_Handler(HWND window, UINT message, UINT wParam, LONG lParam)\n{\n\tbool processed = false;\n\n\t/*\n\t**\tExamine the message to see if it is one that should be processed. Only keyboard and\n\t**\tpertinant mouse messages are processed.\n\t*/\n\tswitch (message) {\n\n\t\t/*\n\t\t**\tSystem key has been pressed. This is the normal keyboard event message.\n\t\t*/\n\t\tcase WM_SYSKEYDOWN:\n\t\tcase WM_KEYDOWN:\n\t\t\tif (wParam == VK_SCROLL) {\n\t\t\t\tStop_Execution();\n\t\t\t} else {\n\t\t\t\tPut_Key_Message((unsigned short)wParam);\n\t\t\t}\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThe key has been released. This is the normal key release message.\n\t\t*/\n\t\tcase WM_SYSKEYUP:\n\t\tcase WM_KEYUP:\n\t\t\tPut_Key_Message((unsigned short)wParam, true);\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tPress of the left mouse button.\n\t\t*/\n\t\tcase WM_LBUTTONDOWN:\n\t\t\tPut_Mouse_Message(VK_LBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tRelease of the left mouse button.\n\t\t*/\n\t\tcase WM_LBUTTONUP:\n\t\t\tPut_Mouse_Message(VK_LBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tDouble click of the left mouse button. Fake this into being\n\t\t**\tjust a rapid click of the left button twice.\n\t\t*/\n\t\tcase WM_LBUTTONDBLCLK:\n\t\t\tPut_Mouse_Message(VK_LBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tPut_Mouse_Message(VK_LBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tPut_Mouse_Message(VK_LBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tPut_Mouse_Message(VK_LBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tPress of the middle mouse button.\n\t\t*/\n\t\tcase WM_MBUTTONDOWN:\n\t\t\tPut_Mouse_Message(VK_MBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tRelease of the middle mouse button.\n\t\t*/\n\t\tcase WM_MBUTTONUP:\n\t\t\tPut_Mouse_Message(VK_MBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tMiddle button double click gets translated into two\n\t\t**\tregular middle button clicks.\n\t\t*/\n\t\tcase WM_MBUTTONDBLCLK:\n\t\t\tPut_Mouse_Message(VK_MBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tPut_Mouse_Message(VK_MBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tPut_Mouse_Message(VK_MBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tPut_Mouse_Message(VK_MBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tRight mouse button press.\n\t\t*/\n\t\tcase WM_RBUTTONDOWN:\n\t\t\tPut_Mouse_Message(VK_RBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tRight mouse button release.\n\t\t*/\n\t\tcase WM_RBUTTONUP:\n\t\t\tPut_Mouse_Message(VK_RBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tTranslate a double click of the right button\n\t\t**\tinto being just two regular right button clicks.\n\t\t*/\n\t\tcase WM_RBUTTONDBLCLK:\n\t\t\tPut_Mouse_Message(VK_RBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tPut_Mouse_Message(VK_RBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tPut_Mouse_Message(VK_RBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tPut_Mouse_Message(VK_RBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tIf the message is not pertinant to the keyboard system,\n\t\t**\tthen do nothing.\n\t\t*/\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tIf this message has been processed, then pass it on to the system\n\t**\tdirectly.\n\t*/\n\tif (processed) {\n\t\tDefWindowProc(window, message, wParam, lParam);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Available_Buffer_Room -- Fetch the quantity of free elements in the keyboa *\n *                                                                                             *\n *    This examines the keyboard buffer queue and determine how many elements are available    *\n *    for use before the buffer becomes full. Typical use of this would be when inserting      *\n *    mouse events that require more than one element. Such an event must detect when there    *\n *    would be insufficient room in the buffer and bail accordingly.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of elements that may be stored in to the keyboard buffer   *\n *          before it becomes full and cannot accept any more elements.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint WWKeyboardClass::Available_Buffer_Room(void) const\n{\n\tint avail;\n\tif (Head == Tail) {\n\t\tavail = ARRAY_SIZE(Buffer);\n\t}\n\tif (Head < Tail) {\n\t\tavail = Tail - Head;\n\t}\n\tif (Head > Tail) {\n\t\tavail = (Tail + ARRAY_SIZE(Buffer)) - Head;\n\t}\n\treturn(avail);\n}\n"
  },
  {
    "path": "CODE/KEY.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/KEY.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Keyboard Library                                    *\n *                                                                                             *\n *                    File Name : KEYBOARD.H                                                   *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 10/16/95                                                     *\n *                                                                                             *\n *                  Last Update : October 16, 1995 [PWG]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef KEYBOARD_H\n#define KEYBOARD_H\n\n#ifndef WIN32\n#include\t\"..\\wwflat32\\include\\keyboard.h\"\n#else\n\n#include\t<windows.h>\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ comittee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\ntypedef enum {\n\tWWKEY_SHIFT_BIT\t= 0x100,\n\tWWKEY_CTRL_BIT\t\t= 0x200,\n\tWWKEY_ALT_BIT\t\t= 0x400,\n\tWWKEY_RLS_BIT\t\t= 0x800,\n\tWWKEY_VK_BIT\t\t= 0x1000,\n\tWWKEY_DBL_BIT\t\t= 0x2000,\n\tWWKEY_BTN_BIT\t\t= 0x8000,\n} WWKey_Type;\n\n\nclass WWKeyboardClass\n{\n\tpublic:\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\tWWKeyboardClass();\n\n\t\t/* Define the functions which work with the Keyboard Class\t\t\t\t*/\n\t\tunsigned short Check(void) const;\n\t\tunsigned short Get(void);\n\t\tbool Put(unsigned short key);\n\t\tvoid Clear(void);\n\t\tchar To_ASCII(unsigned short num);\n\t\tbool Down(unsigned short key);\n\n\t\t/* Define the main hook for the message processing loop.\t\t\t\t\t*/\n\t\tbool Message_Handler(HWND hwnd, UINT message, UINT wParam, LONG lParam);\n\n\t\t/* Define the public access variables which are used with the\t\t\t*/\n\t\t/*   Keyboard Class.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\tint MouseQX;\n\t\tint MouseQY;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is a keyboard state array that is used to aid in translating\n\t\t**\tKN_ keys into KA_ keys.\n\t\t*/\n\t\tunsigned char KeyState[256];\n\n\t\t/*\n\t\t**\tThis is the circular keyboard holding buffer. It holds the VK key and\n\t\t**\tthe current shift state at the time the key was added to the queue.\n\t\t*/\n\t\tunsigned short Buffer[256];\t\t// buffer which holds actual keypresses\n\n\t\tunsigned short Buff_Get(void);\n\t\tunsigned short Fetch_Element(void);\n\t\tunsigned short Peek_Element(void) const;\n\t\tbool Put_Element(unsigned short val);\n\t\tbool Is_Buffer_Full(void) const;\n\t\tbool Is_Buffer_Empty(void) const;\n\t\tstatic bool Is_Mouse_Key(unsigned short key);\n\t\tvoid Fill_Buffer_From_System(void);\n\t\tbool Put_Key_Message(unsigned short vk_key, bool release = false);\n\t\tbool Put_Mouse_Message(unsigned short vk_key, int x, int y, bool release = false);\n\t\tint Available_Buffer_Room(void) const;\n\n\t\t/*\n\t\t**\tThese are the tracking pointers to maintain the\n\t\t**\tcircular keyboard list.\n\t\t*/\n\t\tint Head;\n\t\tint Tail;\n};\n\n\n#define\tVK_NONE\t\t\t\t  0x00\n#define\tVK_LBUTTON          0x01\n#define\tVK_RBUTTON          0x02\n#define\tVK_CANCEL           0x03\n#define\tVK_MBUTTON          0x04\n#define\tVK_NONE_05\t\t\t  0x05\n#define\tVK_NONE_06\t\t\t  0x06\n#define\tVK_NONE_07\t\t\t  0x07\n#define\tVK_BACK             0x08\n#define\tVK_TAB              0x09\n#define\tVK_NONE_0A\t\t\t  0x0A\n#define\tVK_NONE_0B\t\t\t  0x0B\n#define\tVK_CLEAR            0x0C\n#define\tVK_RETURN           0x0D\n#define\tVK_NONE_0E\t\t\t  0x0E\n#define\tVK_NONE_0F\t\t\t  0x0F\n#define\tVK_SHIFT            0x10\n#define\tVK_CONTROL          0x11\n#define\tVK_MENU             0x12\n#define\tVK_PAUSE            0x13\n#define\tVK_CAPITAL          0x14\n#define\tVK_NONE_15\t\t\t  0x15\n#define\tVK_NONE_16\t\t\t  0x16\n#define\tVK_NONE_17\t\t\t  0x17\n#define\tVK_NONE_18\t\t\t  0x18\n#define\tVK_NONE_19\t\t\t  0x19\n#define\tVK_NONE_1A\t\t\t  0x1A\n#define\tVK_ESCAPE           0x1B\n#define\tVK_NONE_1C\t\t\t  0x1C\n#define\tVK_NONE_1D\t\t\t  0x1D\n#define\tVK_NONE_1E\t\t\t  0x1E\n#define\tVK_NONE_1F\t\t\t  0x1F\n#define\tVK_SPACE            0x20\n#define\tVK_PRIOR            0x21\n#define\tVK_NEXT             0x22\n#define\tVK_END              0x23\n#define\tVK_HOME             0x24\n#define\tVK_LEFT             0x25\n#define\tVK_UP               0x26\n#define\tVK_RIGHT            0x27\n#define\tVK_DOWN             0x28\n#define\tVK_SELECT           0x29\n#define\tVK_PRINT            0x2A\n#define\tVK_EXECUTE          0x2B\n#define\tVK_SNAPSHOT         0x2C\n#define\tVK_INSERT           0x2D\n#define\tVK_DELETE           0x2E\n#define\tVK_HELP             0x2F\n#define\tVK_0\t\t\t\t\t  0x30\n#define\tVK_1\t\t\t\t\t  0x31\n#define\tVK_2\t\t\t\t\t  0x32\n#define\tVK_3\t\t\t\t\t  0x33\n#define\tVK_4\t\t\t\t\t  0x34\n#define\tVK_5\t\t\t\t\t  0x35\n#define\tVK_6\t\t\t\t\t  0x36\n#define\tVK_7\t\t\t\t\t  0x37\n#define\tVK_8\t\t\t\t\t  0x38\n#define\tVK_9\t\t\t\t\t  0x39\n#define\tVK_NONE_3B\t\t\t  0x3B\n#define\tVK_NONE_3C\t\t\t  0x3C\n#define\tVK_NONE_3D\t\t\t  0x3D\n#define\tVK_NONE_3E\t\t\t  0x3E\n#define\tVK_NONE_3F\t\t\t  0x3F\n#define\tVK_NONE_40\t\t\t  0x40\n#define\tVK_A\t\t\t\t\t  0x41\n#define\tVK_B\t\t\t\t\t  0x42\n#define\tVK_C\t\t\t\t\t  0x43\n#define\tVK_D\t\t\t\t\t  0x44\n#define\tVK_E\t\t\t\t\t  0x45\n#define\tVK_F\t\t\t\t\t  0x46\n#define\tVK_G\t\t\t\t\t  0x47\n#define\tVK_H\t\t\t\t\t  0x48\n#define\tVK_I\t\t\t\t\t  0x49\n#define\tVK_J\t\t\t\t\t  0x4A\n#define\tVK_K\t\t\t\t\t  0x4B\n#define\tVK_L\t\t\t\t\t  0x4C\n#define\tVK_M\t\t\t\t\t  0x4D\n#define\tVK_N\t\t\t\t\t  0x4E\n#define\tVK_O\t\t\t\t\t  0x4F\n#define\tVK_P\t\t\t\t\t  0x50\n#define\tVK_Q\t\t\t\t\t  0x51\n#define\tVK_R\t\t\t\t\t  0x52\n#define\tVK_S\t\t\t\t\t  0x53\n#define\tVK_T\t\t\t\t\t  0x54\n#define\tVK_U\t\t\t\t\t  0x55\n#define\tVK_V\t\t\t\t\t  0x56\n#define\tVK_W\t\t\t\t\t  0x57\n#define\tVK_X\t\t\t\t\t  0x58\n#define\tVK_Y\t\t\t\t\t  0x59\n#define\tVK_Z\t\t\t\t\t  0x5A\n#define\tVK_NONE_5B\t\t\t  0x5B\n#define\tVK_NONE_5C\t\t\t  0x5C\n#define\tVK_NONE_5D\t\t\t  0x5D\n#define\tVK_NONE_5E\t\t\t  0x5E\n#define\tVK_NONE_5F\t\t\t  0x5F\n#define\tVK_NUMPAD0          0x60\n#define\tVK_NUMPAD1          0x61\n#define\tVK_NUMPAD2          0x62\n#define\tVK_NUMPAD3          0x63\n#define\tVK_NUMPAD4          0x64\n#define\tVK_NUMPAD5          0x65\n#define\tVK_NUMPAD6          0x66\n#define\tVK_NUMPAD7          0x67\n#define\tVK_NUMPAD8          0x68\n#define\tVK_NUMPAD9          0x69\n#define\tVK_MULTIPLY         0x6A\n#define\tVK_ADD              0x6B\n#define\tVK_SEPARATOR        0x6C\n#define\tVK_SUBTRACT         0x6D\n#define\tVK_DECIMAL          0x6E\n#define\tVK_DIVIDE           0x6F\n#define\tVK_F1               0x70\n#define\tVK_F2               0x71\n#define\tVK_F3               0x72\n#define\tVK_F4               0x73\n#define\tVK_F5               0x74\n#define\tVK_F6               0x75\n#define\tVK_F7               0x76\n#define\tVK_F8               0x77\n#define\tVK_F9               0x78\n#define\tVK_F10              0x79\n#define\tVK_F11              0x7A\n#define\tVK_F12              0x7B\n#define\tVK_F13              0x7C\n#define\tVK_F14              0x7D\n#define\tVK_F15              0x7E\n#define\tVK_F16              0x7F\n#define\tVK_F17              0x80\n#define\tVK_F18              0x81\n#define\tVK_F19              0x82\n#define\tVK_F20              0x83\n#define\tVK_F21              0x84\n#define\tVK_F22              0x85\n#define\tVK_F23              0x86\n#define\tVK_F24              0x87\n#define\tVK_NONE_88          0x88\n#define\tVK_NONE_89          0x89\n#define\tVK_NONE_8A          0x8A\n#define\tVK_NONE_8B          0x8B\n#define\tVK_NONE_8C          0x8C\n#define\tVK_NONE_8D          0x8D\n#define\tVK_NONE_8E          0x8E\n#define\tVK_NONE_8F          0x8F\n#define\tVK_NUMLOCK          0x90\n#define\tVK_SCROLL           0x91\n#define\tVK_NONE_92\t\t\t  0x92\n#define\tVK_NONE_93\t\t\t  0x93\n#define\tVK_NONE_94\t\t\t  0x94\n#define\tVK_NONE_95\t\t\t  0x95\n#define\tVK_NONE_96\t\t\t  0x96\n#define\tVK_NONE_97\t\t\t  0x97\n#define\tVK_NONE_98\t\t\t  0x98\n#define\tVK_NONE_99\t\t\t  0x99\n#define\tVK_NONE_9A\t\t\t  0x9A\n#define\tVK_NONE_9B\t\t\t  0x9B\n#define\tVK_NONE_9C\t\t\t  0x9C\n#define\tVK_NONE_9D\t\t\t  0x9D\n#define\tVK_NONE_9E\t\t\t  0x9E\n#define\tVK_NONE_9F\t\t\t  0x9F\n#define\tVK_NONE_A0\t\t\t  0xA0\n#define\tVK_NONE_A1\t\t\t  0xA1\n#define\tVK_NONE_A2\t\t\t  0xA2\n#define\tVK_NONE_A3\t\t\t  0xA3\n#define\tVK_NONE_A4\t\t\t  0xA4\n#define\tVK_NONE_A5\t\t\t  0xA5\n#define\tVK_NONE_A6\t\t\t  0xA6\n#define\tVK_NONE_A7\t\t\t  0xA7\n#define\tVK_NONE_A8\t\t\t  0xA8\n#define\tVK_NONE_A9\t\t\t  0xA9\n#define\tVK_NONE_AA\t\t\t  0xAA\n#define\tVK_NONE_AB\t\t\t  0xAB\n#define\tVK_NONE_AC\t\t\t  0xAC\n#define\tVK_NONE_AD\t\t\t  0xAD\n#define\tVK_NONE_AE\t\t\t  0xAE\n#define\tVK_NONE_AF\t\t\t  0xAF\n#define\tVK_NONE_B0\t\t\t  0xB0\n#define\tVK_NONE_B1\t\t\t  0xB1\n#define\tVK_NONE_B2\t\t\t  0xB2\n#define\tVK_NONE_B3\t\t\t  0xB3\n#define\tVK_NONE_B4\t\t\t  0xB4\n#define\tVK_NONE_B5\t\t\t  0xB5\n#define\tVK_NONE_B6\t\t\t  0xB6\n#define\tVK_NONE_B7\t\t\t  0xB7\n#define\tVK_NONE_B8\t\t\t  0xB8\n#define\tVK_NONE_B9\t\t\t  0xB9\n#define\tVK_NONE_BA\t\t\t  0xBA\t//\t;\n#define\tVK_NONE_BB\t\t\t  0xBB\t// =\n#define\tVK_NONE_BC\t\t\t  0xBC\t// ,\n#define\tVK_NONE_BD\t\t\t  0xBD\t// -\n#define\tVK_NONE_BE\t\t\t  0xBE\t// .\n#define\tVK_NONE_BF\t\t\t  0xBF\t// /\n#define\tVK_NONE_C0\t\t\t  0xC0\t// `\n#define\tVK_NONE_C1\t\t\t  0xC1\n#define\tVK_NONE_C2\t\t\t  0xC2\n#define\tVK_NONE_C3\t\t\t  0xC3\n#define\tVK_NONE_C4\t\t\t  0xC4\n#define\tVK_NONE_C5\t\t\t  0xC5\n#define\tVK_NONE_C6\t\t\t  0xC6\n#define\tVK_NONE_C7\t\t\t  0xC7\n#define\tVK_NONE_C8\t\t\t  0xC8\n#define\tVK_NONE_C9\t\t\t  0xC9\n#define\tVK_NONE_CA\t\t\t  0xCA\n#define\tVK_NONE_CB\t\t\t  0xCB\n#define\tVK_NONE_CC\t\t\t  0xCC\n#define\tVK_NONE_CD\t\t\t  0xCD\n#define\tVK_NONE_CE\t\t\t  0xCE\n#define\tVK_NONE_CF\t\t\t  0xCF\n#define\tVK_NONE_D0\t\t\t  0xD0\n#define\tVK_NONE_D1\t\t\t  0xD1\n#define\tVK_NONE_D2\t\t\t  0xD2\n#define\tVK_NONE_D3\t\t\t  0xD3\n#define\tVK_NONE_D4\t\t\t  0xD4\n#define\tVK_NONE_D5\t\t\t  0xD5\n#define\tVK_NONE_D6\t\t\t  0xD6\n#define\tVK_NONE_D7\t\t\t  0xD7\n#define\tVK_NONE_D8\t\t\t  0xD8\n#define\tVK_NONE_D9\t\t\t  0xD9\n#define\tVK_NONE_DA\t\t\t  0xDA\n#define\tVK_NONE_DB\t\t\t  0xDB\t\t// [\n#define\tVK_NONE_DC\t\t\t  0xDC\t\t// '\\'\n#define\tVK_NONE_DD\t\t\t  0xDD\t\t// ]\n#define\tVK_NONE_DE\t\t\t  0xDE\t\t// '\n#define\tVK_NONE_DF\t\t\t  0xDF\n#define\tVK_NONE_E0\t\t\t  0xE0\n#define\tVK_NONE_E1\t\t\t  0xE1\n#define\tVK_NONE_E2\t\t\t  0xE2\n#define\tVK_NONE_E3\t\t\t  0xE3\n#define\tVK_NONE_E4\t\t\t  0xE4\n#define\tVK_NONE_E5\t\t\t  0xE5\n#define\tVK_NONE_E6\t\t\t  0xE6\n#define\tVK_NONE_E7\t\t\t  0xE7\n#define\tVK_NONE_E8\t\t\t  0xE8\n#define\tVK_NONE_E9\t\t\t  0xE9\n#define\tVK_NONE_EA\t\t\t  0xEA\n#define\tVK_NONE_EB\t\t\t  0xEB\n#define\tVK_NONE_EC\t\t\t  0xEC\n#define\tVK_NONE_ED\t\t\t  0xED\n#define\tVK_NONE_EE\t\t\t  0xEE\n#define\tVK_NONE_EF\t\t\t  0xEF\n#define\tVK_NONE_F0\t\t\t  0xF0\n#define\tVK_NONE_F1\t\t\t  0xF1\n#define\tVK_NONE_F2\t\t\t  0xF2\n#define\tVK_NONE_F3\t\t\t  0xF3\n#define\tVK_NONE_F4\t\t\t  0xF4\n#define\tVK_NONE_F5\t\t\t  0xF5\n#define\tVK_NONE_F6\t\t\t  0xF6\n#define\tVK_NONE_F7\t\t\t  0xF7\n#define\tVK_NONE_F8\t\t\t  0xF8\n#define\tVK_NONE_F9\t\t\t  0xF9\n#define\tVK_NONE_FA\t\t\t  0xFA\n#define\tVK_NONE_FB\t\t\t  0xFB\n#define\tVK_NONE_FC\t\t\t  0xFC\n#define\tVK_NONE_FD\t\t\t  0xFD\n#define\tVK_NONE_FE\t\t\t  0xFE\n#define\tVK_NONE_FF\t\t\t  0xFF\n\n#define\tVK_UPLEFT\t\t\t  VK_HOME\n#define\tVK_UPRIGHT\t\t\t  VK_PRIOR\n#define\tVK_DOWNLEFT\t\t\t  VK_END\n#define\tVK_DOWNRIGHT\t\t  VK_NEXT\n#define\tVK_ALT\t\t\t\t  VK_MENU\n\ntypedef enum KeyASCIIType {\n\t//\n\t// Define all the KA types as variations of the VK types.  This is\n\t// so the KA functions will work properly under windows 95.\n\t//\n\tKA_NONE\t\t\t\t= 0,\n\tKA_MORE \t\t\t\t= 1,\n\tKA_SETBKGDCOL \t\t= 2,\n\tKA_SETFORECOL \t\t= 6,\n\tKA_FORMFEED \t\t= 12,\n\tKA_SPCTAB \t\t\t= 20,\n\tKA_SETX \t\t\t\t= 25,\n\tKA_SETY \t\t\t\t= 26,\n\n\tKA_SPACE\t\t\t\t= 32,\t\t\t\t\t/*   */\n\tKA_EXCLAMATION,\t\t\t\t\t\t\t/* ! */\n\tKA_DQUOTE,\t\t\t\t\t\t\t\t\t/* \" */\n\tKA_POUND,\t\t\t\t\t\t\t\t\t/* # */\n\tKA_DOLLAR,\t\t\t\t\t\t\t\t\t/* $ */\n\tKA_PERCENT,\t\t\t\t\t\t\t\t\t/* % */\n\tKA_AMPER,\t\t\t\t\t\t\t\t\t/* & */\n\tKA_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKA_LPAREN,\t\t\t\t\t\t\t\t\t/* ( */\n\tKA_RPAREN,\t\t\t\t\t\t\t\t\t/* ) */\n\tKA_ASTERISK,\t\t\t\t\t\t\t\t/* * */\n\tKA_PLUS,\t\t\t\t\t\t\t\t\t\t/* + */\n\tKA_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKA_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKA_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKA_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKA_0, KA_1, KA_2, KA_3, KA_4, KA_5, KA_6, KA_7, KA_8, KA_9,\n\tKA_COLON,\t\t\t\t\t\t\t\t\t/* : */\n\tKA_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKA_LESS_THAN,\t\t\t\t\t\t\t\t/* < */\n\tKA_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\tKA_GREATER_THAN,\t\t\t\t\t\t\t/* > */\n\tKA_QUESTION,\t\t\t\t\t\t\t\t/* ? */\n\n\tKA_AT,\t\t\t\t\t\t\t\t\t\t/* @ */\n\tKA_A,\t\t\t\t\t\t\t\t\t\t\t/* A */\n\tKA_B,\t\t\t\t\t\t\t\t\t\t\t/* B */\n\tKA_C,\t\t\t\t\t\t\t\t\t\t\t/* C */\n\tKA_D,\t\t\t\t\t\t\t\t\t\t\t/* D */\n\tKA_E,\t\t\t\t\t\t\t\t\t\t\t/* E */\n\tKA_F,\t\t\t\t\t\t\t\t\t\t\t/* F */\n\tKA_G,\t\t\t\t\t\t\t\t\t\t\t/* G */\n\tKA_H,\t\t\t\t\t\t\t\t\t\t\t/* H */\n\tKA_I,\t\t\t\t\t\t\t\t\t\t\t/* I */\n\tKA_J,\t\t\t\t\t\t\t\t\t\t\t/* J */\n\tKA_K,\t\t\t\t\t\t\t\t\t\t\t/* K */\n\tKA_L,\t\t\t\t\t\t\t\t\t\t\t/* L */\n\tKA_M,\t\t\t\t\t\t\t\t\t\t\t/* M */\n\tKA_N,\t\t\t\t\t\t\t\t\t\t\t/* N */\n\tKA_O,\t\t\t\t\t\t\t\t\t\t\t/* O */\n\n\tKA_P,\t\t\t\t\t\t\t\t\t\t\t/* P */\n\tKA_Q,\t\t\t\t\t\t\t\t\t\t\t/* Q */\n\tKA_R,\t\t\t\t\t\t\t\t\t\t\t/* R */\n\tKA_S,\t\t\t\t\t\t\t\t\t\t\t/* S */\n\tKA_T,\t\t\t\t\t\t\t\t\t\t\t/* T */\n\tKA_U,\t\t\t\t\t\t\t\t\t\t\t/* U */\n\tKA_V,\t\t\t\t\t\t\t\t\t\t\t/* V */\n\tKA_W,\t\t\t\t\t\t\t\t\t\t\t/* W */\n\tKA_X,\t\t\t\t\t\t\t\t\t\t\t/* X */\n\tKA_Y,\t\t\t\t\t\t\t\t\t\t\t/* Y */\n\tKA_Z,\t\t\t\t\t\t\t\t\t\t\t/* Z */\n\tKA_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKA_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\tKA_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKA_CARROT,\t\t\t\t\t\t\t\t\t/* ^ */\n\tKA_UNDERLINE,\t\t\t\t\t\t\t\t/* _ */\n\n\tKA_GRAVE,\t\t\t\t\t\t\t\t\t/* ` */\n\tKA_a,\t\t\t\t\t\t\t\t\t\t\t/* a */\n\tKA_b,\t\t\t\t\t\t\t\t\t\t\t/* b */\n\tKA_c,\t\t\t\t\t\t\t\t\t\t\t/* c */\n\tKA_d,\t\t\t\t\t\t\t\t\t\t\t/* d */\n\tKA_e,\t\t\t\t\t\t\t\t\t\t\t/* e */\n\tKA_f,\t\t\t\t\t\t\t\t\t\t\t/* f */\n\tKA_g,\t\t\t\t\t\t\t\t\t\t\t/* g */\n\tKA_h,\t\t\t\t\t\t\t\t\t\t\t/* h */\n\tKA_i,\t\t\t\t\t\t\t\t\t\t\t/* i */\n\tKA_j,\t\t\t\t\t\t\t\t\t\t\t/* j */\n\tKA_k,\t\t\t\t\t\t\t\t\t\t\t/* k */\n\tKA_l,\t\t\t\t\t\t\t\t\t\t\t/* l */\n\tKA_m,\t\t\t\t\t\t\t\t\t\t\t/* m */\n\tKA_n,\t\t\t\t\t\t\t\t\t\t\t/* n */\n\tKA_o,\t\t\t\t\t\t\t\t\t\t\t/* o */\n\n\tKA_p,\t\t\t\t\t\t\t\t\t\t\t/* p */\n\tKA_q,\t\t\t\t\t\t\t\t\t\t\t/* q */\n\tKA_r,\t\t\t\t\t\t\t\t\t\t\t/* r */\n\tKA_s,\t\t\t\t\t\t\t\t\t\t\t/* s */\n\tKA_t,\t\t\t\t\t\t\t\t\t\t\t/* t */\n\tKA_u,\t\t\t\t\t\t\t\t\t\t\t/* u */\n\tKA_v,\t\t\t\t\t\t\t\t\t\t\t/* v */\n\tKA_w,\t\t\t\t\t\t\t\t\t\t\t/* w */\n\tKA_x,\t\t\t\t\t\t\t\t\t\t\t/* x */\n\tKA_y,\t\t\t\t\t\t\t\t\t\t\t/* y */\n\tKA_z,\t\t\t\t\t\t\t\t\t\t\t/* z */\n\tKA_LBRACE,\t\t\t\t\t\t\t\t\t/* { */\n\tKA_BAR,\t\t\t\t\t\t\t\t\t\t/* | */\n\tKA_RBRACE,\t\t\t\t\t\t\t\t\t/* ] */\n\tKA_TILDA,\t\t\t\t\t\t\t\t\t/* ~ */\n\n\tKA_ESC \t\t\t\t= VK_ESCAPE,\n\tKA_EXTEND \t\t\t= VK_ESCAPE,\n\tKA_RETURN \t\t\t= VK_RETURN,\n\tKA_BACKSPACE \t\t= VK_BACK,\n\tKA_TAB \t\t\t\t= VK_TAB ,\n\tKA_DELETE\t\t\t= VK_DELETE,\t\t\t\t\t\t\t\t\t/* <DELETE> */\n\tKA_INSERT\t\t\t= VK_INSERT,\t\t\t\t\t\t\t\t\t/* <INSERT> */\n\tKA_PGDN\t\t\t\t= VK_NEXT,\t\t\t\t\t\t\t\t\t\t/* <PAGE DOWN> */\n\tKA_DOWNRIGHT \t\t= VK_NEXT,\n\tKA_DOWN\t\t\t\t= VK_DOWN,\t\t\t\t\t\t\t\t\t\t/* <DOWN ARROW> */\n\tKA_END\t\t\t\t= VK_END,\t\t\t\t\t\t\t\t\t\t/* <END> */\n\tKA_DOWNLEFT \t\t= VK_END,\n\tKA_RIGHT\t\t\t\t= VK_RIGHT,\t\t\t\t\t\t\t\t\t/* <RIGHT ARROW> */\n\tKA_KEYPAD5\t\t\t= VK_SELECT,\t\t\t\t\t\t\t\t\t/* NUMERIC KEY PAD <5> */\n\tKA_LEFT\t\t\t\t= VK_LEFT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ARROW> */\n\tKA_PGUP\t\t\t\t= VK_PRIOR,\t\t\t\t\t\t\t\t\t\t/* <PAGE UP> */\n\tKA_UPRIGHT \t\t\t= VK_PRIOR,\n\tKA_UP\t\t\t\t\t= VK_UP,\t\t\t\t\t\t\t\t\t\t/* <UP ARROW> */\n\tKA_HOME\t\t\t\t= VK_HOME,\t\t\t\t\t\t\t\t\t\t/* <HOME> */\n\tKA_UPLEFT \t\t\t= VK_HOME,\n\tKA_F12\t\t\t\t= VK_F12,\n\tKA_F11\t\t\t\t= VK_F11,\n\tKA_F10\t\t\t\t= VK_F10,\n\tKA_F9 \t\t\t\t= VK_F9,\n\tKA_F8\t\t\t\t\t= VK_F8,\n\tKA_F7\t\t\t\t\t= VK_F7,\n\tKA_F6\t\t\t\t\t= VK_F6,\n\tKA_F5\t\t\t\t\t= VK_F5,\n\tKA_F4\t\t\t\t\t= VK_F4,\n\tKA_F3\t\t\t\t\t= VK_F3,\n\tKA_F2\t\t\t\t\t= VK_F2,\n\tKA_F1\t\t\t\t\t= VK_F1,\n\tKA_LMOUSE \t \t\t= VK_LBUTTON,\n\tKA_RMOUSE \t \t\t= VK_RBUTTON,\n\n\tKA_SHIFT_BIT \t\t= WWKEY_SHIFT_BIT,\n\tKA_CTRL_BIT  \t\t= WWKEY_CTRL_BIT,\n\tKA_ALT_BIT   \t\t= WWKEY_ALT_BIT,\n\tKA_RLSE_BIT  \t\t= WWKEY_RLS_BIT,\n} KeyASCIIType;\n\n\ntypedef enum KeyNumType {\n\tKN_NONE\t\t\t\t= 0,\n\n\tKN_0 \t\t\t\t\t= VK_0,\n\tKN_1 \t\t\t\t\t= VK_1,\n\tKN_2 \t\t\t\t\t= VK_2,\n\tKN_3 \t\t\t\t\t= VK_3,\n\tKN_4 \t\t\t\t\t= VK_4,\n\tKN_5 \t\t\t\t\t= VK_5,\n\tKN_6 \t\t\t\t\t= VK_6,\n\tKN_7 \t\t\t\t\t= VK_7,\n\tKN_8 \t\t\t\t\t= VK_8,\n\tKN_9 \t\t\t\t\t= VK_9,\n\tKN_A \t\t\t\t\t= VK_A,\n\tKN_B \t\t\t\t\t= VK_B,\n\tKN_BACKSLASH\t\t= VK_NONE_DC,\n\tKN_BACKSPACE\t\t= VK_BACK,\n\tKN_C \t\t\t\t\t= VK_C,\n\tKN_CAPSLOCK\t\t\t= VK_CAPITAL,\n\tKN_CENTER\t\t\t= VK_CLEAR,\n\tKN_COMMA \t\t\t= VK_NONE_BC,\n\tKN_D \t\t\t\t\t= VK_D,\n\tKN_DELETE\t\t\t= VK_DELETE,\n\tKN_DOWN\t\t\t\t= VK_DOWN,\n\tKN_DOWNLEFT\t\t\t= VK_END,\n\tKN_DOWNRIGHT\t\t= VK_NEXT,\n\tKN_E \t\t\t\t\t= VK_E,\n\tKN_END\t\t\t\t= VK_END,\n\tKN_EQUAL \t\t\t= VK_NONE_BB,\n\tKN_ESC\t\t\t\t= VK_ESCAPE,\n\tKN_E_DELETE \t\t= VK_DELETE,\n\tKN_E_DOWN\t\t\t= VK_NUMPAD2,\n\tKN_E_END\t\t\t\t= VK_NUMPAD1,\n\tKN_E_HOME\t\t\t= VK_NUMPAD7,\n\tKN_E_INSERT\t\t\t= VK_INSERT,\n\tKN_E_LEFT\t\t\t= VK_NUMPAD4,\n\tKN_E_PGDN   \t\t= VK_NUMPAD3,\n\tKN_E_PGUP\t\t\t= VK_NUMPAD9,\n\tKN_E_RIGHT\t\t\t= VK_NUMPAD6,\n\tKN_E_UP\t\t\t\t= VK_NUMPAD8,\n\tKN_F \t\t\t\t\t= VK_F,\n\tKN_F1\t\t\t\t\t= VK_F1,\n\tKN_F10\t\t\t\t= VK_F10,\n\tKN_F11\t\t\t\t= VK_F11,\n\tKN_F12\t\t\t\t= VK_F12,\n\tKN_F2\t\t\t\t\t= VK_F2,\n\tKN_F3\t\t\t\t\t= VK_F3,\n\tKN_F4\t\t\t\t\t= VK_F4,\n\tKN_F5\t\t\t\t\t= VK_F5,\n\tKN_F6\t\t\t\t\t= VK_F6,\n\tKN_F7\t\t\t\t\t= VK_F7,\n\tKN_F8\t\t\t\t\t= VK_F8,\n\tKN_F9\t\t\t\t\t= VK_F9,\n\tKN_G \t\t\t\t\t= VK_G,\n\tKN_GRAVE \t\t\t= VK_NONE_C0,\n\tKN_H \t\t\t\t\t= VK_H,\n\tKN_HOME\t\t\t\t= VK_HOME,\n\tKN_I \t\t\t\t\t= VK_I,\n\tKN_INSERT\t\t\t= VK_INSERT,\n\tKN_J \t\t\t\t\t= VK_J,\n\tKN_K \t\t\t\t\t= VK_K,\n\tKN_KEYPAD_ASTERISK= VK_MULTIPLY,\n\tKN_KEYPAD_MINUS\t= VK_SUBTRACT,\n\tKN_KEYPAD_PLUS\t\t= VK_ADD,\n\tKN_KEYPAD_RETURN\t= VK_RETURN,\n\tKN_KEYPAD_SLASH\t= VK_DIVIDE,\n\tKN_L \t\t\t\t\t= VK_L,\n\tKN_LALT\t\t\t\t= VK_MENU,\n\tKN_LBRACKET\t\t\t= VK_NONE_DB,\n\tKN_LCTRL\t\t\t\t= VK_CONTROL,\n\tKN_LEFT\t\t\t\t= VK_LEFT,\n\tKN_LMOUSE\t\t\t= VK_LBUTTON,\n\tKN_LSHIFT\t\t\t= VK_SHIFT,\n\tKN_M \t\t\t\t\t= VK_M,\n\tKN_MINUS \t\t\t= VK_NONE_BD,\n\tKN_N \t\t\t\t\t= VK_N,\n\tKN_NUMLOCK\t\t\t= VK_NUMLOCK,\n\tKN_O \t\t\t\t\t= VK_O,\n\tKN_P \t\t\t\t\t= VK_P,\n\tKN_PAUSE\t\t\t\t= VK_PAUSE,\n\tKN_PERIOD \t\t\t= VK_NONE_BE,\n\tKN_PGDN\t\t\t\t= VK_NEXT,\n\tKN_PGUP\t\t\t\t= VK_PRIOR,\n\tKN_PRNTSCRN\t\t\t= VK_PRINT,\n\tKN_Q \t\t\t\t\t= VK_Q,\n\tKN_R \t\t\t\t\t= VK_R,\n\tKN_RALT\t\t\t\t= VK_MENU,\n\tKN_RBRACKET\t\t\t= VK_NONE_DD,\n\tKN_RCTRL\t\t\t\t= VK_CONTROL,\n\tKN_RETURN \t\t\t= VK_RETURN,\n\tKN_RIGHT\t\t\t\t= VK_RIGHT,\n\tKN_RMOUSE\t\t\t= VK_RBUTTON,\n\tKN_RSHIFT\t\t\t= VK_SHIFT,\n\tKN_S \t\t\t\t\t= VK_S,\n\tKN_SCROLLLOCK\t\t= VK_SCROLL,\n\tKN_SEMICOLON \t\t= VK_NONE_BA,\n\tKN_SLASH \t\t\t= VK_NONE_BF,\n\tKN_SPACE \t\t\t= VK_SPACE,\n\tKN_SQUOTE \t\t\t= VK_NONE_DE,\n\tKN_T \t\t\t\t\t= VK_T,\n\tKN_TAB\t\t\t\t= VK_TAB,\n\tKN_U \t\t\t\t\t= VK_U,\n\tKN_UP\t\t\t\t\t= VK_UP,\n\tKN_UPLEFT\t\t\t= VK_HOME,\n\tKN_UPRIGHT\t\t\t= VK_PRIOR,\n\tKN_V \t\t\t\t\t= VK_V,\n\tKN_W \t\t\t\t\t= VK_W,\n\tKN_X \t\t\t\t\t= VK_X,\n\tKN_Y \t\t\t\t\t= VK_Y,\n\tKN_Z \t\t\t\t\t= VK_Z,\n\n\tKN_SHIFT_BIT \t\t= WWKEY_SHIFT_BIT,\n\tKN_CTRL_BIT  \t\t= WWKEY_CTRL_BIT,\n\tKN_ALT_BIT   \t\t= WWKEY_ALT_BIT,\n\tKN_RLSE_BIT  \t\t= WWKEY_RLS_BIT,\n\tKN_BUTTON    \t\t= WWKEY_BTN_BIT,\n} KeyNumType;\n\n\n//extern WWKeyboardClass *_Kbd;\n#endif\n\n#endif\n"
  },
  {
    "path": "CODE/KEYBOARD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\conquer.cpv   4.74   23 Sep 1996 12:36:00   JOE_BOSTIC  $ */\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Keyboard Library                                    *\n *                                                                                             *\n *                    File Name : KEYBOARD.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 10/16/95                                                     *\n *                                                                                             *\n *                  Last Update : September 24, 1996 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                         *\n *   WWKeyboardClass::Get -- Logic to get a metakey from the buffer                            *\n *   WWKeyboardClass::Check -- Checks to see if a key is in the buffer                         *\n *   WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer    *\n *   WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer               *\n *   WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels           *\n *   WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels           *\n *   WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars       *\n *   Check_Key -- compatability routine for old 32 bit library                                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"keyboard.h\"\n\n#include\t\"monoc.h\"\n\n//void Message_Loop(void);\n\nWWKeyboardClass * _Kbd = NULL;\n\n\n#define\tARRAY_SIZE(x)\t\tint(sizeof(x)/sizeof(x[0]))\n\n\n/***********************************************************************************************\n * WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class                *\n *                                                                                             *\n * INPUT:\t\tnone\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * OUTPUT:     none\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nWWKeyboardClass::WWKeyboardClass(void) :\n\tMouseQX(0),\n\tMouseQY(0),\n\tHead(0),\n\tTail(0)\n//\tMState(0),\n//\tConditional(0),\n//\tCurrentCursor(0)\n{\n\t_Kbd = this;\n\n\tmemset(KeyState, '\\0', sizeof(KeyState));\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer                 *\n *                                                                                             *\n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     int\t\t- the key value that was pulled from buffer (includes bits)\t\t\t\t  *                                                                                *\n *                                                                                             *\n * WARNINGS:   If the key was a mouse event MouseQX and MouseQY will be updated                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nunsigned short WWKeyboardClass::Buff_Get(void)\n{\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t\t\t// wait for key in buffer\n\n\tunsigned short temp = Fetch_Element();\n\tif (Is_Mouse_Key(temp)) {\n\t\tMouseQX = Fetch_Element();\n\t\tMouseQY = Fetch_Element();\n\t}\n\treturn(temp);\n}\n\n\nbool WWKeyboardClass::Is_Mouse_Key(unsigned short key)\n{\n\tkey &= 0xFF;\n\treturn (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Check -- Checks to see if a key is in the buffer                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *   09/24/1996 JLB : Converted to new style keyboard system.                                  *\n *=============================================================================================*/\nunsigned short WWKeyboardClass::Check(void) const\n{\n\t((WWKeyboardClass *)this)->Fill_Buffer_From_System();\n\tif (Is_Buffer_Empty()) return(false);\n\treturn(Peek_Element());\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Get -- Logic to get a metakey from the buffer                              *\n *                                                                                             *\n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     int\t\t- the meta key taken from the buffer.\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:\tThis routine will not return until a keypress is received\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nunsigned short WWKeyboardClass::Get(void)\n{\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t// wait for key in buffer\n\treturn (Buff_Get());\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                           *\n *                                                                                             *\n * INPUT:\t\tint\t \t- the key to insert into the buffer          \t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     bool\t\t- true if key is sucessfuly inserted.\t\t\t\t\t\t\t              *\n *                                                                                             *\n * WARNINGS:   none\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Put(unsigned short key)\n{\n\tif (!Is_Buffer_Full()) {\n\t\tPut_Element(key);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Put_Key_Message(unsigned short vk_key, bool release)\n{\n\t//\n\t// Get the status of all of the different keyboard modifiers.  Note, only pay attention\n\t// to numlock and caps lock if we are dealing with a key that is affected by them.  Note\n\t// that we do not want to set the shift, ctrl and alt bits for Mouse keypresses as this\n\t// would be incompatible with the dos version.\n\t//\n\tif (!Is_Mouse_Key(vk_key)) {\n\t\tif (((GetKeyState(VK_SHIFT) & 0x8000) != 0) ||\n\t\t\t((GetKeyState(VK_CAPITAL) & 0x0008) != 0) ||\n\t\t\t((GetKeyState(VK_NUMLOCK) & 0x0008) != 0)) {\n\n\t\t\tvk_key |= WWKEY_SHIFT_BIT;\n\t\t}\n\t\tif ((GetKeyState(VK_CONTROL) & 0x8000) != 0) {\n\t\t\tvk_key |= WWKEY_CTRL_BIT;\n\t\t}\n\t\tif ((GetKeyState(VK_MENU) & 0x8000) != 0) {\n\t\t\tvk_key |= WWKEY_ALT_BIT;\n\t\t}\n\t}\n\n\tif (release) {\n\t\tvk_key |= WWKEY_RLS_BIT;\n\t}\n\n\t//\n\t// Finally use the put command to enter the key into the keyboard\n\t// system.\n\t//\n\treturn(Put(vk_key));\n\n\n\n}\n\n\nchar WWKeyboardClass::To_ASCII(unsigned short key)\n{\n\t/*\n\t**\tReleased keys never translate into an ASCII value.\n\t*/\n\tif (key & WWKEY_RLS_BIT) {\n\t\treturn('\\0');\n\t}\n\n\t/*\n\t**\tSet the KeyState buffer to reflect the shift bits stored in the key value.\n\t*/\n\tif (key & WWKEY_SHIFT_BIT) {\n\t\tKeyState[VK_SHIFT] = 0x80;\n\t}\n\tif (key & WWKEY_CTRL_BIT) {\n\t\tKeyState[VK_CONTROL] = 0x80;\n\t}\n\tif (key & WWKEY_ALT_BIT) {\n\t\tKeyState[VK_MENU] = 0x80;\n\t}\n\n\t/*\n\t**\tAsk windows to translate the key into an ASCII equivalent.\n\t*/\n\tchar buffer[10];\n\tint result = 1;\n\tint scancode = 0;\n\tchar override = '\\0';\n\n\tswitch (key & 0xFF) {\n//\t\tcase KN_RETURN:\n//\t\t\toverride = KA_RETURN;\n//\t\t\tbreak;\n\n//\t\tcase KN_BACKSPACE:\n//\t\t\toverride = KA_BACKSPACE;\n//\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tscancode = MapVirtualKey(key & 0xFF, 0);\n\t\t\tresult = ToAscii((UINT)(key & 0xFF), (UINT)scancode, (PBYTE)KeyState, (LPWORD)buffer, (UINT)0);\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tRestore the KeyState buffer back to pristine condition.\n\t*/\n\tif (key & WWKEY_SHIFT_BIT) {\n\t\tKeyState[VK_SHIFT] = 0;\n\t}\n\tif (key & WWKEY_CTRL_BIT) {\n\t\tKeyState[VK_CONTROL] = 0;\n\t}\n\tif (key & WWKEY_ALT_BIT) {\n\t\tKeyState[VK_MENU] = 0;\n\t}\n\n\t/*\n\t**\tIf Windows could not perform the translation as expected, then\n\t**\treturn with a null ASCII value.\n\t*/\n\tif (result != 1) {\n\t\treturn('\\0');\n\t}\n\n\tif (override != 0) {\n\t\treturn(override);\n\t}\n\n\treturn(buffer[0]);\n}\n\n\nWWKeyboardClass::Down(unsigned short key)\n{\n\treturn(GetAsyncKeyState(key & 0xFF));\n}\n\n\nextern \"C\" {\n\tvoid __cdecl Stop_Execution (void);\n}\n\n\n\nunsigned short WWKeyboardClass::Fetch_Element(void)\n{\n\tunsigned short val = 0;\n\tif (Head != Tail) {\n\t\tval = Buffer[Head];\n\n\t\tHead = (Head + 1) % ARRAY_SIZE(Buffer);\n\t}\n\treturn(val);\n}\n\n\nunsigned short WWKeyboardClass::Peek_Element(void) const\n{\n\tif (!Is_Buffer_Empty()) {\n\t\treturn(Buffer[Head]);\n\t}\n\treturn(0);\n}\n\n\nbool WWKeyboardClass::Put_Element(unsigned short val)\n{\n\tif (!Is_Buffer_Full()) {\n\t\tint temp = (Tail+1) % ARRAY_SIZE(Buffer);\n\t\tBuffer[Tail] = val;\n\t\tTail = temp;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\nbool WWKeyboardClass::Is_Buffer_Full(void) const\n{\n\tif ((Tail + 1) % ARRAY_SIZE(Buffer) == Head) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\nbool WWKeyboardClass::Is_Buffer_Empty(void) const\n{\n\tif (Head == Tail) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\nvoid WWKeyboardClass::Fill_Buffer_From_System(void)\n{\n\tif (!Is_Buffer_Full()) {\n\t\tMSG\tmsg;\n\t\twhile (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {\n\t\t  \tif (!GetMessage( &msg, NULL, 0, 0 )) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tTranslateMessage(&msg);\n\t\t\tDispatchMessage(&msg);\n\t\t}\n\t}\n}\n\n\nvoid WWKeyboardClass::Clear(void)\n{\n\tHead = Tail;\n}\n\n\nvoid WWKeyboardClass::Message_Handler(HWND , UINT message, UINT wParam, LONG lParam)\n{\n\tswitch (message) {\n\t\tcase WM_SYSKEYDOWN:\n\t\tcase WM_KEYDOWN:\n\t\t\tif ( wParam==VK_SCROLL ){\n\t\t\t\tStop_Execution();\n\t\t\t} else {\n\t\t\t\tPut_Key_Message((unsigned short)wParam);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WM_SYSKEYUP:\n\t\tcase WM_KEYUP:\n\t\t\tPut_Key_Message((unsigned short)wParam, true);\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_LBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONUP:\n\t\t\tPut_Key_Message(VK_LBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_LBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tPut_Key_Message(VK_LBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_MBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONUP:\n\t\t\tPut_Key_Message(VK_MBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_MBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tPut_Key_Message(VK_MBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_RBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONUP:\n\t\t\tPut_Key_Message(VK_RBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_RBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tPut_Key_Message(VK_RBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n//\t\tcase WM_MOUSEMOVE:\n//\t\t\tif (CurrentCursor)\n//\t\t\t\tSetCursor(CurrentCursor);\n//\t\t\tbreak;\n\t}\n}\n"
  },
  {
    "path": "CODE/KEYBOARD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\conquer.cpv   4.74   23 Sep 1996 12:36:00   JOE_BOSTIC  $ */\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Keyboard Library                                    *\n *                                                                                             *\n *                    File Name : KEYBOARD.H                                                   *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 10/16/95                                                     *\n *                                                                                             *\n *                  Last Update : October 16, 1995 [PWG]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef KEYBOARD_H\n#define KEYBOARD_H\n\n#include\t<windows.h>\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ comittee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\ntypedef enum {\n\tWWKEY_SHIFT_BIT\t= 0x100,\n\tWWKEY_CTRL_BIT\t\t= 0x200,\n\tWWKEY_ALT_BIT\t\t= 0x400,\n\tWWKEY_RLS_BIT\t\t= 0x800,\n\tWWKEY_VK_BIT\t\t= 0x1000,\n\tWWKEY_DBL_BIT\t\t= 0x2000,\n\tWWKEY_BTN_BIT\t\t= 0x8000,\n} WWKey_Type;\n\n\nclass WWKeyboardClass\n{\n\tpublic:\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\tWWKeyboardClass();\n\n\t\t/* Define the functions which work with the Keyboard Class\t\t\t\t*/\n\t\tunsigned short Check(void) const;\n\t\tunsigned short Get(void);\n\t\tbool Put(unsigned short key);\n\t\tvoid Clear(void);\n\t\tchar To_ASCII(unsigned short num);\n\t\tbool Down(unsigned short key);\n\n\t\t/* Define the main hook for the message processing loop.\t\t\t\t\t*/\n\t\tvoid Message_Handler(HWND hwnd, UINT message, UINT wParam, LONG lParam);\n\n\t\t/* Define the public access variables which are used with the\t\t\t*/\n\t\t/*   Keyboard Class.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\tint MouseQX;\n\t\tint MouseQY;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is a keyboard state array that is used to aid in translating\n\t\t**\tKN_ keys into KA_ keys.\n\t\t*/\n\t\tunsigned char KeyState[256];\n\n\t\t/*\n\t\t**\tThis is the circular keyboard holding buffer. It holds the VK key and\n\t\t**\tthe current shift state at the time the key was added to the queue.\n\t\t*/\n\t\tunsigned short Buffer[256];\t\t// buffer which holds actual keypresses\n\n\t\tunsigned short Buff_Get(void);\n\t\tunsigned short Fetch_Element(void);\n\t\tunsigned short Peek_Element(void) const;\n\t\tbool Put_Element(unsigned short val);\n\t\tbool Is_Buffer_Full(void) const;\n\t\tbool Is_Buffer_Empty(void) const;\n\t\tstatic bool Is_Mouse_Key(unsigned short key);\n\t\tvoid Fill_Buffer_From_System(void);\n\t\tbool Put_Key_Message(unsigned short vk_key, bool release = false);\n\n\t\t/*\n\t\t**\tThese are the tracking pointers to maintain the\n\t\t**\tcircular keyboard list.\n\t\t*/\n\t\tint Head;\n\t\tint Tail;\n};\n\n\n#define\tVK_NONE\t\t\t\t  0x00\n#define\tVK_LBUTTON          0x01\n#define\tVK_RBUTTON          0x02\n#define\tVK_CANCEL           0x03\n#define\tVK_MBUTTON          0x04\n#define\tVK_NONE_05\t\t\t  0x05\n#define\tVK_NONE_06\t\t\t  0x06\n#define\tVK_NONE_07\t\t\t  0x07\n#define\tVK_BACK             0x08\n#define\tVK_TAB              0x09\n#define\tVK_NONE_0A\t\t\t  0x0A\n#define\tVK_NONE_0B\t\t\t  0x0B\n#define\tVK_CLEAR            0x0C\n#define\tVK_RETURN           0x0D\n#define\tVK_NONE_0E\t\t\t  0x0E\n#define\tVK_NONE_0F\t\t\t  0x0F\n#define\tVK_SHIFT            0x10\n#define\tVK_CONTROL          0x11\n#define\tVK_MENU             0x12\n#define\tVK_PAUSE            0x13\n#define\tVK_CAPITAL          0x14\n#define\tVK_NONE_15\t\t\t  0x15\n#define\tVK_NONE_16\t\t\t  0x16\n#define\tVK_NONE_17\t\t\t  0x17\n#define\tVK_NONE_18\t\t\t  0x18\n#define\tVK_NONE_19\t\t\t  0x19\n#define\tVK_NONE_1A\t\t\t  0x1A\n#define\tVK_ESCAPE           0x1B\n#define\tVK_NONE_1C\t\t\t  0x1C\n#define\tVK_NONE_1D\t\t\t  0x1D\n#define\tVK_NONE_1E\t\t\t  0x1E\n#define\tVK_NONE_1F\t\t\t  0x1F\n#define\tVK_SPACE            0x20\n#define\tVK_PRIOR            0x21\n#define\tVK_NEXT             0x22\n#define\tVK_END              0x23\n#define\tVK_HOME             0x24\n#define\tVK_LEFT             0x25\n#define\tVK_UP               0x26\n#define\tVK_RIGHT            0x27\n#define\tVK_DOWN             0x28\n#define\tVK_SELECT           0x29\n#define\tVK_PRINT            0x2A\n#define\tVK_EXECUTE          0x2B\n#define\tVK_SNAPSHOT         0x2C\n#define\tVK_INSERT           0x2D\n#define\tVK_DELETE           0x2E\n#define\tVK_HELP             0x2F\n#define\tVK_0\t\t\t\t\t  0x30\n#define\tVK_1\t\t\t\t\t  0x31\n#define\tVK_2\t\t\t\t\t  0x32\n#define\tVK_3\t\t\t\t\t  0x33\n#define\tVK_4\t\t\t\t\t  0x34\n#define\tVK_5\t\t\t\t\t  0x35\n#define\tVK_6\t\t\t\t\t  0x36\n#define\tVK_7\t\t\t\t\t  0x37\n#define\tVK_8\t\t\t\t\t  0x38\n#define\tVK_9\t\t\t\t\t  0x39\n#define\tVK_NONE_3B\t\t\t  0x3B\n#define\tVK_NONE_3C\t\t\t  0x3C\n#define\tVK_NONE_3D\t\t\t  0x3D\n#define\tVK_NONE_3E\t\t\t  0x3E\n#define\tVK_NONE_3F\t\t\t  0x3F\n#define\tVK_NONE_40\t\t\t  0x40\n#define\tVK_A\t\t\t\t\t  0x41\n#define\tVK_B\t\t\t\t\t  0x42\n#define\tVK_C\t\t\t\t\t  0x43\n#define\tVK_D\t\t\t\t\t  0x44\n#define\tVK_E\t\t\t\t\t  0x45\n#define\tVK_F\t\t\t\t\t  0x46\n#define\tVK_G\t\t\t\t\t  0x47\n#define\tVK_H\t\t\t\t\t  0x48\n#define\tVK_I\t\t\t\t\t  0x49\n#define\tVK_J\t\t\t\t\t  0x4A\n#define\tVK_K\t\t\t\t\t  0x4B\n#define\tVK_L\t\t\t\t\t  0x4C\n#define\tVK_M\t\t\t\t\t  0x4D\n#define\tVK_N\t\t\t\t\t  0x4E\n#define\tVK_O\t\t\t\t\t  0x4F\n#define\tVK_P\t\t\t\t\t  0x50\n#define\tVK_Q\t\t\t\t\t  0x51\n#define\tVK_R\t\t\t\t\t  0x52\n#define\tVK_S\t\t\t\t\t  0x53\n#define\tVK_T\t\t\t\t\t  0x54\n#define\tVK_U\t\t\t\t\t  0x55\n#define\tVK_V\t\t\t\t\t  0x56\n#define\tVK_W\t\t\t\t\t  0x57\n#define\tVK_X\t\t\t\t\t  0x58\n#define\tVK_Y\t\t\t\t\t  0x59\n#define\tVK_Z\t\t\t\t\t  0x5A\n#define\tVK_NONE_5B\t\t\t  0x5B\n#define\tVK_NONE_5C\t\t\t  0x5C\n#define\tVK_NONE_5D\t\t\t  0x5D\n#define\tVK_NONE_5E\t\t\t  0x5E\n#define\tVK_NONE_5F\t\t\t  0x5F\n#define\tVK_NUMPAD0          0x60\n#define\tVK_NUMPAD1          0x61\n#define\tVK_NUMPAD2          0x62\n#define\tVK_NUMPAD3          0x63\n#define\tVK_NUMPAD4          0x64\n#define\tVK_NUMPAD5          0x65\n#define\tVK_NUMPAD6          0x66\n#define\tVK_NUMPAD7          0x67\n#define\tVK_NUMPAD8          0x68\n#define\tVK_NUMPAD9          0x69\n#define\tVK_MULTIPLY         0x6A\n#define\tVK_ADD              0x6B\n#define\tVK_SEPARATOR        0x6C\n#define\tVK_SUBTRACT         0x6D\n#define\tVK_DECIMAL          0x6E\n#define\tVK_DIVIDE           0x6F\n#define\tVK_F1               0x70\n#define\tVK_F2               0x71\n#define\tVK_F3               0x72\n#define\tVK_F4               0x73\n#define\tVK_F5               0x74\n#define\tVK_F6               0x75\n#define\tVK_F7               0x76\n#define\tVK_F8               0x77\n#define\tVK_F9               0x78\n#define\tVK_F10              0x79\n#define\tVK_F11              0x7A\n#define\tVK_F12              0x7B\n#define\tVK_F13              0x7C\n#define\tVK_F14              0x7D\n#define\tVK_F15              0x7E\n#define\tVK_F16              0x7F\n#define\tVK_F17              0x80\n#define\tVK_F18              0x81\n#define\tVK_F19              0x82\n#define\tVK_F20              0x83\n#define\tVK_F21              0x84\n#define\tVK_F22              0x85\n#define\tVK_F23              0x86\n#define\tVK_F24              0x87\n#define\tVK_NONE_88          0x88\n#define\tVK_NONE_89          0x89\n#define\tVK_NONE_8A          0x8A\n#define\tVK_NONE_8B          0x8B\n#define\tVK_NONE_8C          0x8C\n#define\tVK_NONE_8D          0x8D\n#define\tVK_NONE_8E          0x8E\n#define\tVK_NONE_8F          0x8F\n#define\tVK_NUMLOCK          0x90\n#define\tVK_SCROLL           0x91\n#define\tVK_NONE_92\t\t\t  0x92\n#define\tVK_NONE_93\t\t\t  0x93\n#define\tVK_NONE_94\t\t\t  0x94\n#define\tVK_NONE_95\t\t\t  0x95\n#define\tVK_NONE_96\t\t\t  0x96\n#define\tVK_NONE_97\t\t\t  0x97\n#define\tVK_NONE_98\t\t\t  0x98\n#define\tVK_NONE_99\t\t\t  0x99\n#define\tVK_NONE_9A\t\t\t  0x9A\n#define\tVK_NONE_9B\t\t\t  0x9B\n#define\tVK_NONE_9C\t\t\t  0x9C\n#define\tVK_NONE_9D\t\t\t  0x9D\n#define\tVK_NONE_9E\t\t\t  0x9E\n#define\tVK_NONE_9F\t\t\t  0x9F\n#define\tVK_NONE_A0\t\t\t  0xA0\n#define\tVK_NONE_A1\t\t\t  0xA1\n#define\tVK_NONE_A2\t\t\t  0xA2\n#define\tVK_NONE_A3\t\t\t  0xA3\n#define\tVK_NONE_A4\t\t\t  0xA4\n#define\tVK_NONE_A5\t\t\t  0xA5\n#define\tVK_NONE_A6\t\t\t  0xA6\n#define\tVK_NONE_A7\t\t\t  0xA7\n#define\tVK_NONE_A8\t\t\t  0xA8\n#define\tVK_NONE_A9\t\t\t  0xA9\n#define\tVK_NONE_AA\t\t\t  0xAA\n#define\tVK_NONE_AB\t\t\t  0xAB\n#define\tVK_NONE_AC\t\t\t  0xAC\n#define\tVK_NONE_AD\t\t\t  0xAD\n#define\tVK_NONE_AE\t\t\t  0xAE\n#define\tVK_NONE_AF\t\t\t  0xAF\n#define\tVK_NONE_B0\t\t\t  0xB0\n#define\tVK_NONE_B1\t\t\t  0xB1\n#define\tVK_NONE_B2\t\t\t  0xB2\n#define\tVK_NONE_B3\t\t\t  0xB3\n#define\tVK_NONE_B4\t\t\t  0xB4\n#define\tVK_NONE_B5\t\t\t  0xB5\n#define\tVK_NONE_B6\t\t\t  0xB6\n#define\tVK_NONE_B7\t\t\t  0xB7\n#define\tVK_NONE_B8\t\t\t  0xB8\n#define\tVK_NONE_B9\t\t\t  0xB9\n#define\tVK_NONE_BA\t\t\t  0xBA\t//\t;\n#define\tVK_NONE_BB\t\t\t  0xBB\t// =\n#define\tVK_NONE_BC\t\t\t  0xBC\t// ,\n#define\tVK_NONE_BD\t\t\t  0xBD\t// -\n#define\tVK_NONE_BE\t\t\t  0xBE\t// .\n#define\tVK_NONE_BF\t\t\t  0xBF\t// /\n#define\tVK_NONE_C0\t\t\t  0xC0\t// `\n#define\tVK_NONE_C1\t\t\t  0xC1\n#define\tVK_NONE_C2\t\t\t  0xC2\n#define\tVK_NONE_C3\t\t\t  0xC3\n#define\tVK_NONE_C4\t\t\t  0xC4\n#define\tVK_NONE_C5\t\t\t  0xC5\n#define\tVK_NONE_C6\t\t\t  0xC6\n#define\tVK_NONE_C7\t\t\t  0xC7\n#define\tVK_NONE_C8\t\t\t  0xC8\n#define\tVK_NONE_C9\t\t\t  0xC9\n#define\tVK_NONE_CA\t\t\t  0xCA\n#define\tVK_NONE_CB\t\t\t  0xCB\n#define\tVK_NONE_CC\t\t\t  0xCC\n#define\tVK_NONE_CD\t\t\t  0xCD\n#define\tVK_NONE_CE\t\t\t  0xCE\n#define\tVK_NONE_CF\t\t\t  0xCF\n#define\tVK_NONE_D0\t\t\t  0xD0\n#define\tVK_NONE_D1\t\t\t  0xD1\n#define\tVK_NONE_D2\t\t\t  0xD2\n#define\tVK_NONE_D3\t\t\t  0xD3\n#define\tVK_NONE_D4\t\t\t  0xD4\n#define\tVK_NONE_D5\t\t\t  0xD5\n#define\tVK_NONE_D6\t\t\t  0xD6\n#define\tVK_NONE_D7\t\t\t  0xD7\n#define\tVK_NONE_D8\t\t\t  0xD8\n#define\tVK_NONE_D9\t\t\t  0xD9\n#define\tVK_NONE_DA\t\t\t  0xDA\n#define\tVK_NONE_DB\t\t\t  0xDB\t\t// [\n#define\tVK_NONE_DC\t\t\t  0xDC\t\t// '\\'\n#define\tVK_NONE_DD\t\t\t  0xDD\t\t// ]\n#define\tVK_NONE_DE\t\t\t  0xDE\t\t// '\n#define\tVK_NONE_DF\t\t\t  0xDF\n#define\tVK_NONE_E0\t\t\t  0xE0\n#define\tVK_NONE_E1\t\t\t  0xE1\n#define\tVK_NONE_E2\t\t\t  0xE2\n#define\tVK_NONE_E3\t\t\t  0xE3\n#define\tVK_NONE_E4\t\t\t  0xE4\n#define\tVK_NONE_E5\t\t\t  0xE5\n#define\tVK_NONE_E6\t\t\t  0xE6\n#define\tVK_NONE_E7\t\t\t  0xE7\n#define\tVK_NONE_E8\t\t\t  0xE8\n#define\tVK_NONE_E9\t\t\t  0xE9\n#define\tVK_NONE_EA\t\t\t  0xEA\n#define\tVK_NONE_EB\t\t\t  0xEB\n#define\tVK_NONE_EC\t\t\t  0xEC\n#define\tVK_NONE_ED\t\t\t  0xED\n#define\tVK_NONE_EE\t\t\t  0xEE\n#define\tVK_NONE_EF\t\t\t  0xEF\n#define\tVK_NONE_F0\t\t\t  0xF0\n#define\tVK_NONE_F1\t\t\t  0xF1\n#define\tVK_NONE_F2\t\t\t  0xF2\n#define\tVK_NONE_F3\t\t\t  0xF3\n#define\tVK_NONE_F4\t\t\t  0xF4\n#define\tVK_NONE_F5\t\t\t  0xF5\n#define\tVK_NONE_F6\t\t\t  0xF6\n#define\tVK_NONE_F7\t\t\t  0xF7\n#define\tVK_NONE_F8\t\t\t  0xF8\n#define\tVK_NONE_F9\t\t\t  0xF9\n#define\tVK_NONE_FA\t\t\t  0xFA\n#define\tVK_NONE_FB\t\t\t  0xFB\n#define\tVK_NONE_FC\t\t\t  0xFC\n#define\tVK_NONE_FD\t\t\t  0xFD\n#define\tVK_NONE_FE\t\t\t  0xFE\n#define\tVK_NONE_FF\t\t\t  0xFF\n\n#define\tVK_UPLEFT\t\t\t  VK_HOME\n#define\tVK_UPRIGHT\t\t\t  VK_PRIOR\n#define\tVK_DOWNLEFT\t\t\t  VK_END\n#define\tVK_DOWNRIGHT\t\t  VK_NEXT\n#define\tVK_ALT\t\t\t\t  VK_MENU\n\nenum {\n\t//\n\t// Define all the KA types as variations of the VK types.  This is\n\t// so the KA functions will work properly under windows 95.\n\t//\n\tKA_NONE\t\t\t\t= 0,\n\tKA_MORE \t\t\t\t= 1,\n\tKA_SETBKGDCOL \t\t= 2,\n\tKA_SETFORECOL \t\t= 6,\n\tKA_FORMFEED \t\t= 12,\n\tKA_SPCTAB \t\t\t= 20,\n\tKA_SETX \t\t\t\t= 25,\n\tKA_SETY \t\t\t\t= 26,\n\n\tKA_SPACE\t\t\t\t= 32,\t\t\t\t\t/*   */\n\tKA_EXCLAMATION,\t\t\t\t\t\t\t/* ! */\n\tKA_DQUOTE,\t\t\t\t\t\t\t\t\t/* \" */\n\tKA_POUND,\t\t\t\t\t\t\t\t\t/* # */\n\tKA_DOLLAR,\t\t\t\t\t\t\t\t\t/* $ */\n\tKA_PERCENT,\t\t\t\t\t\t\t\t\t/* % */\n\tKA_AMPER,\t\t\t\t\t\t\t\t\t/* & */\n\tKA_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKA_LPAREN,\t\t\t\t\t\t\t\t\t/* ( */\n\tKA_RPAREN,\t\t\t\t\t\t\t\t\t/* ) */\n\tKA_ASTERISK,\t\t\t\t\t\t\t\t/* * */\n\tKA_PLUS,\t\t\t\t\t\t\t\t\t\t/* + */\n\tKA_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKA_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKA_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKA_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKA_0, KA_1, KA_2, KA_3, KA_4, KA_5, KA_6, KA_7, KA_8, KA_9,\n\tKA_COLON,\t\t\t\t\t\t\t\t\t/* : */\n\tKA_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKA_LESS_THAN,\t\t\t\t\t\t\t\t/* < */\n\tKA_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\tKA_GREATER_THAN,\t\t\t\t\t\t\t/* > */\n\tKA_QUESTION,\t\t\t\t\t\t\t\t/* ? */\n\n\tKA_AT,\t\t\t\t\t\t\t\t\t\t/* @ */\n\tKA_A,\t\t\t\t\t\t\t\t\t\t\t/* A */\n\tKA_B,\t\t\t\t\t\t\t\t\t\t\t/* B */\n\tKA_C,\t\t\t\t\t\t\t\t\t\t\t/* C */\n\tKA_D,\t\t\t\t\t\t\t\t\t\t\t/* D */\n\tKA_E,\t\t\t\t\t\t\t\t\t\t\t/* E */\n\tKA_F,\t\t\t\t\t\t\t\t\t\t\t/* F */\n\tKA_G,\t\t\t\t\t\t\t\t\t\t\t/* G */\n\tKA_H,\t\t\t\t\t\t\t\t\t\t\t/* H */\n\tKA_I,\t\t\t\t\t\t\t\t\t\t\t/* I */\n\tKA_J,\t\t\t\t\t\t\t\t\t\t\t/* J */\n\tKA_K,\t\t\t\t\t\t\t\t\t\t\t/* K */\n\tKA_L,\t\t\t\t\t\t\t\t\t\t\t/* L */\n\tKA_M,\t\t\t\t\t\t\t\t\t\t\t/* M */\n\tKA_N,\t\t\t\t\t\t\t\t\t\t\t/* N */\n\tKA_O,\t\t\t\t\t\t\t\t\t\t\t/* O */\n\n\tKA_P,\t\t\t\t\t\t\t\t\t\t\t/* P */\n\tKA_Q,\t\t\t\t\t\t\t\t\t\t\t/* Q */\n\tKA_R,\t\t\t\t\t\t\t\t\t\t\t/* R */\n\tKA_S,\t\t\t\t\t\t\t\t\t\t\t/* S */\n\tKA_T,\t\t\t\t\t\t\t\t\t\t\t/* T */\n\tKA_U,\t\t\t\t\t\t\t\t\t\t\t/* U */\n\tKA_V,\t\t\t\t\t\t\t\t\t\t\t/* V */\n\tKA_W,\t\t\t\t\t\t\t\t\t\t\t/* W */\n\tKA_X,\t\t\t\t\t\t\t\t\t\t\t/* X */\n\tKA_Y,\t\t\t\t\t\t\t\t\t\t\t/* Y */\n\tKA_Z,\t\t\t\t\t\t\t\t\t\t\t/* Z */\n\tKA_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKA_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\tKA_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKA_CARROT,\t\t\t\t\t\t\t\t\t/* ^ */\n\tKA_UNDERLINE,\t\t\t\t\t\t\t\t/* _ */\n\n\tKA_GRAVE,\t\t\t\t\t\t\t\t\t/* ` */\n\tKA_a,\t\t\t\t\t\t\t\t\t\t\t/* a */\n\tKA_b,\t\t\t\t\t\t\t\t\t\t\t/* b */\n\tKA_c,\t\t\t\t\t\t\t\t\t\t\t/* c */\n\tKA_d,\t\t\t\t\t\t\t\t\t\t\t/* d */\n\tKA_e,\t\t\t\t\t\t\t\t\t\t\t/* e */\n\tKA_f,\t\t\t\t\t\t\t\t\t\t\t/* f */\n\tKA_g,\t\t\t\t\t\t\t\t\t\t\t/* g */\n\tKA_h,\t\t\t\t\t\t\t\t\t\t\t/* h */\n\tKA_i,\t\t\t\t\t\t\t\t\t\t\t/* i */\n\tKA_j,\t\t\t\t\t\t\t\t\t\t\t/* j */\n\tKA_k,\t\t\t\t\t\t\t\t\t\t\t/* k */\n\tKA_l,\t\t\t\t\t\t\t\t\t\t\t/* l */\n\tKA_m,\t\t\t\t\t\t\t\t\t\t\t/* m */\n\tKA_n,\t\t\t\t\t\t\t\t\t\t\t/* n */\n\tKA_o,\t\t\t\t\t\t\t\t\t\t\t/* o */\n\n\tKA_p,\t\t\t\t\t\t\t\t\t\t\t/* p */\n\tKA_q,\t\t\t\t\t\t\t\t\t\t\t/* q */\n\tKA_r,\t\t\t\t\t\t\t\t\t\t\t/* r */\n\tKA_s,\t\t\t\t\t\t\t\t\t\t\t/* s */\n\tKA_t,\t\t\t\t\t\t\t\t\t\t\t/* t */\n\tKA_u,\t\t\t\t\t\t\t\t\t\t\t/* u */\n\tKA_v,\t\t\t\t\t\t\t\t\t\t\t/* v */\n\tKA_w,\t\t\t\t\t\t\t\t\t\t\t/* w */\n\tKA_x,\t\t\t\t\t\t\t\t\t\t\t/* x */\n\tKA_y,\t\t\t\t\t\t\t\t\t\t\t/* y */\n\tKA_z,\t\t\t\t\t\t\t\t\t\t\t/* z */\n\tKA_LBRACE,\t\t\t\t\t\t\t\t\t/* { */\n\tKA_BAR,\t\t\t\t\t\t\t\t\t\t/* | */\n\tKA_RBRACE,\t\t\t\t\t\t\t\t\t/* ] */\n\tKA_TILDA,\t\t\t\t\t\t\t\t\t/* ~ */\n\n\tKA_ESC \t\t\t\t= VK_ESCAPE,\n\tKA_EXTEND \t\t\t= VK_ESCAPE,\n\tKA_RETURN \t\t\t= VK_RETURN,\n\tKA_BACKSPACE \t\t= VK_BACK,\n\tKA_TAB \t\t\t\t= VK_TAB ,\n\tKA_DELETE\t\t\t= VK_DELETE,\t\t\t\t\t\t\t\t\t/* <DELETE> */\n\tKA_INSERT\t\t\t= VK_INSERT,\t\t\t\t\t\t\t\t\t/* <INSERT> */\n\tKA_PGDN\t\t\t\t= VK_NEXT,\t\t\t\t\t\t\t\t\t\t/* <PAGE DOWN> */\n\tKA_DOWNRIGHT \t\t= VK_NEXT,\n\tKA_DOWN\t\t\t\t= VK_DOWN,\t\t\t\t\t\t\t\t\t\t/* <DOWN ARROW> */\n\tKA_END\t\t\t\t= VK_END,\t\t\t\t\t\t\t\t\t\t/* <END> */\n\tKA_DOWNLEFT \t\t= VK_END,\n\tKA_RIGHT\t\t\t\t= VK_RIGHT,\t\t\t\t\t\t\t\t\t/* <RIGHT ARROW> */\n\tKA_KEYPAD5\t\t\t= VK_SELECT,\t\t\t\t\t\t\t\t\t/* NUMERIC KEY PAD <5> */\n\tKA_LEFT\t\t\t\t= VK_LEFT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ARROW> */\n\tKA_PGUP\t\t\t\t= VK_PRIOR,\t\t\t\t\t\t\t\t\t\t/* <PAGE UP> */\n\tKA_UPRIGHT \t\t\t= VK_PRIOR,\n\tKA_UP\t\t\t\t\t= VK_UP,\t\t\t\t\t\t\t\t\t\t/* <UP ARROW> */\n\tKA_HOME\t\t\t\t= VK_HOME,\t\t\t\t\t\t\t\t\t\t/* <HOME> */\n\tKA_UPLEFT \t\t\t= VK_HOME,\n\tKA_F12\t\t\t\t= VK_F12,\n\tKA_F11\t\t\t\t= VK_F11,\n\tKA_F10\t\t\t\t= VK_F10,\n\tKA_F9 \t\t\t\t= VK_F9,\n\tKA_F8\t\t\t\t\t= VK_F8,\n\tKA_F7\t\t\t\t\t= VK_F7,\n\tKA_F6\t\t\t\t\t= VK_F6,\n\tKA_F5\t\t\t\t\t= VK_F5,\n\tKA_F4\t\t\t\t\t= VK_F4,\n\tKA_F3\t\t\t\t\t= VK_F3,\n\tKA_F2\t\t\t\t\t= VK_F2,\n\tKA_F1\t\t\t\t\t= VK_F1,\n\tKA_LMOUSE \t \t\t= VK_LBUTTON,\n\tKA_RMOUSE \t \t\t= VK_RBUTTON,\n\n\tKA_SHIFT_BIT \t\t= WWKEY_SHIFT_BIT,\n\tKA_CTRL_BIT  \t\t= WWKEY_CTRL_BIT,\n\tKA_ALT_BIT   \t\t= WWKEY_ALT_BIT,\n\tKA_RLSE_BIT  \t\t= WWKEY_RLS_BIT,\n};\n\n\ntypedef enum KeyNumType {\n\tKN_NONE\t\t\t\t= 0,\n\n\tKN_0 \t\t\t\t\t= VK_0,\n\tKN_1 \t\t\t\t\t= VK_1,\n\tKN_2 \t\t\t\t\t= VK_2,\n\tKN_3 \t\t\t\t\t= VK_3,\n\tKN_4 \t\t\t\t\t= VK_4,\n\tKN_5 \t\t\t\t\t= VK_5,\n\tKN_6 \t\t\t\t\t= VK_6,\n\tKN_7 \t\t\t\t\t= VK_7,\n\tKN_8 \t\t\t\t\t= VK_8,\n\tKN_9 \t\t\t\t\t= VK_9,\n\tKN_A \t\t\t\t\t= VK_A,\n\tKN_B \t\t\t\t\t= VK_B,\n\tKN_BACKSLASH\t\t= VK_NONE_DC,\n\tKN_BACKSPACE\t\t= VK_BACK,\n\tKN_C \t\t\t\t\t= VK_C,\n\tKN_CAPSLOCK\t\t\t= VK_CAPITAL,\n\tKN_CENTER\t\t\t= VK_CLEAR,\n\tKN_COMMA \t\t\t= VK_NONE_BC,\n\tKN_D \t\t\t\t\t= VK_D,\n\tKN_DELETE\t\t\t= VK_DELETE,\n\tKN_DOWN\t\t\t\t= VK_DOWN,\n\tKN_DOWNLEFT\t\t\t= VK_END,\n\tKN_DOWNRIGHT\t\t= VK_NEXT,\n\tKN_E \t\t\t\t\t= VK_E,\n\tKN_END\t\t\t\t= VK_END,\n\tKN_EQUAL \t\t\t= VK_NONE_BB,\n\tKN_ESC\t\t\t\t= VK_ESCAPE,\n\tKN_E_DELETE \t\t= VK_DELETE,\n\tKN_E_DOWN\t\t\t= VK_NUMPAD2,\n\tKN_E_END\t\t\t\t= VK_NUMPAD1,\n\tKN_E_HOME\t\t\t= VK_NUMPAD7,\n\tKN_E_INSERT\t\t\t= VK_INSERT,\n\tKN_E_LEFT\t\t\t= VK_NUMPAD4,\n\tKN_E_PGDN   \t\t= VK_NUMPAD3,\n\tKN_E_PGUP\t\t\t= VK_NUMPAD9,\n\tKN_E_RIGHT\t\t\t= VK_NUMPAD6,\n\tKN_E_UP\t\t\t\t= VK_NUMPAD8,\n\tKN_F \t\t\t\t\t= VK_F,\n\tKN_F1\t\t\t\t\t= VK_F1,\n\tKN_F10\t\t\t\t= VK_F10,\n\tKN_F11\t\t\t\t= VK_F11,\n\tKN_F12\t\t\t\t= VK_F12,\n\tKN_F2\t\t\t\t\t= VK_F2,\n\tKN_F3\t\t\t\t\t= VK_F3,\n\tKN_F4\t\t\t\t\t= VK_F4,\n\tKN_F5\t\t\t\t\t= VK_F5,\n\tKN_F6\t\t\t\t\t= VK_F6,\n\tKN_F7\t\t\t\t\t= VK_F7,\n\tKN_F8\t\t\t\t\t= VK_F8,\n\tKN_F9\t\t\t\t\t= VK_F9,\n\tKN_G \t\t\t\t\t= VK_G,\n\tKN_GRAVE \t\t\t= VK_NONE_C0,\n\tKN_H \t\t\t\t\t= VK_H,\n\tKN_HOME\t\t\t\t= VK_HOME,\n\tKN_I \t\t\t\t\t= VK_I,\n\tKN_INSERT\t\t\t= VK_INSERT,\n\tKN_J \t\t\t\t\t= VK_J,\n\tKN_K \t\t\t\t\t= VK_K,\n\tKN_KEYPAD_ASTERISK= VK_MULTIPLY,\n\tKN_KEYPAD_MINUS\t= VK_SUBTRACT,\n\tKN_KEYPAD_PLUS\t\t= VK_ADD,\n\tKN_KEYPAD_RETURN\t= VK_RETURN,\n\tKN_KEYPAD_SLASH\t= VK_DIVIDE,\n\tKN_L \t\t\t\t\t= VK_L,\n\tKN_LALT\t\t\t\t= VK_MENU,\n\tKN_LBRACKET\t\t\t= VK_NONE_DB,\n\tKN_LCTRL\t\t\t\t= VK_CONTROL,\n\tKN_LEFT\t\t\t\t= VK_LEFT,\n\tKN_LMOUSE\t\t\t= VK_LBUTTON,\n\tKN_LSHIFT\t\t\t= VK_SHIFT,\n\tKN_M \t\t\t\t\t= VK_M,\n\tKN_MINUS \t\t\t= VK_NONE_BD,\n\tKN_N \t\t\t\t\t= VK_N,\n\tKN_NUMLOCK\t\t\t= VK_NUMLOCK,\n\tKN_O \t\t\t\t\t= VK_O,\n\tKN_P \t\t\t\t\t= VK_P,\n\tKN_PAUSE\t\t\t\t= VK_PAUSE,\n\tKN_PERIOD \t\t\t= VK_NONE_BE,\n\tKN_PGDN\t\t\t\t= VK_NEXT,\n\tKN_PGUP\t\t\t\t= VK_PRIOR,\n\tKN_PRNTSCRN\t\t\t= VK_PRINT,\n\tKN_Q \t\t\t\t\t= VK_Q,\n\tKN_R \t\t\t\t\t= VK_R,\n\tKN_RALT\t\t\t\t= VK_MENU,\n\tKN_RBRACKET\t\t\t= VK_NONE_DD,\n\tKN_RCTRL\t\t\t\t= VK_CONTROL,\n\tKN_RETURN \t\t\t= VK_RETURN,\n\tKN_RIGHT\t\t\t\t= VK_RIGHT,\n\tKN_RMOUSE\t\t\t= VK_RBUTTON,\n\tKN_RSHIFT\t\t\t= VK_SHIFT,\n\tKN_S \t\t\t\t\t= VK_S,\n\tKN_SCROLLLOCK\t\t= VK_SCROLL,\n\tKN_SEMICOLON \t\t= VK_NONE_BA,\n\tKN_SLASH \t\t\t= VK_NONE_BF,\n\tKN_SPACE \t\t\t= VK_SPACE,\n\tKN_SQUOTE \t\t\t= VK_NONE_DE,\n\tKN_T \t\t\t\t\t= VK_T,\n\tKN_TAB\t\t\t\t= VK_TAB,\n\tKN_U \t\t\t\t\t= VK_U,\n\tKN_UP\t\t\t\t\t= VK_UP,\n\tKN_UPLEFT\t\t\t= VK_HOME,\n\tKN_UPRIGHT\t\t\t= VK_PRIOR,\n\tKN_V \t\t\t\t\t= VK_V,\n\tKN_W \t\t\t\t\t= VK_W,\n\tKN_X \t\t\t\t\t= VK_X,\n\tKN_Y \t\t\t\t\t= VK_Y,\n\tKN_Z \t\t\t\t\t= VK_Z,\n\n\tKN_SHIFT_BIT \t\t= WWKEY_SHIFT_BIT,\n\tKN_CTRL_BIT  \t\t= WWKEY_CTRL_BIT,\n\tKN_ALT_BIT   \t\t= WWKEY_ALT_BIT,\n\tKN_RLSE_BIT  \t\t= WWKEY_RLS_BIT,\n\tKN_BUTTON    \t\t= WWKEY_BTN_BIT,\n} KeyNumType;\n\n\nextern WWKeyboardClass *_Kbd;\n\n#endif\n"
  },
  {
    "path": "CODE/KEYFBUFF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : KEYFBUFF.ASM                             *\n;*                                                                         *\n;*                   Programmer : David R. Dettmer                         *\n;*                                                                         *\n;*                   Start Date : March 3, 1995                            *\n;*                                                                         *\n;*                  Last Update :                                          *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Buffer_Frame_To_Page -- Copies a linear buffer to a virtual viewport  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n;********************** Model & Processor Directives ***********************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"gbuffer.inc\"\n\n\n;******************************** Equates **********************************\n\nTRUE\tequ\t1\t\t\t; Boolean 'true' value\nFALSE\tequ\t0\t\t\t; Boolean 'false' value\n\n;*=========================================================================*/\n;* The following are defines used to control what functions are linked\t   *\n;* in for Buffer_Frame_To_Page.\t\t\t\t\t\t   *\n;*=========================================================================*/\n;USE_NORMAL\t\tEQU\tTRUE\n;USE_HORZ_REV \t\tEQU\tTRUE\n;USE_VERT_REV \t\tEQU\tTRUE\n;USE_SCALING \t\tEQU\tTRUE\n\n\nFLAG_NORMAL\t\tEQU\t0\nFLAG_TRANS\t\tEQU\t1\nFLAG_GHOST\t\tEQU\t2\nFLAG_FADING\t\tEQU\t4\nFLAG_PREDATOR\t\tEQU\t8\n\nFLAG_MASK\t\tEQU\t0Fh\n\n\nSHAPE_NORMAL \t\tEQU\t0000h\t\t; Standard shape\n;SHAPE_HORZ_REV \t\tEQU\t0001h\t\t; Flipped horizontally\n;SHAPE_VERT_REV \t\tEQU\t0002h\t\t; Flipped vertically\n;SHAPE_SCALING \t\tEQU\t0004h\t\t; Scaled (WORD scale_x, WORD scale_y)\n;SHAPE_VIEWPORT_REL \tEQU\t0010h\t\t; Coords are window-relative\n;SHAPE_WIN_REL \t\tEQU\t0010h\t\t; Coordinates are window relative instead of absolute.\nSHAPE_CENTER \t\tEQU\t0020h\t\t; Coords are based on shape's center pt\nSHAPE_TRANS\t\tEQU\t0040h\t\t; has transparency\n\nSHAPE_FADING \t\tEQU\t0100h\t\t; Fading effect (VOID * fading_table,\n\t\t\t\t\t\t;   WORD fading_num)\nSHAPE_PREDATOR \t\tEQU\t0200h\t\t; Transparent warping effect\n;SHAPE_COMPACT \t\tEQU\t0400h\t\t; Never use this bit\n;SHAPE_PRIORITY \t\tEQU\t0800h\t\t; Use priority system when drawing\nSHAPE_GHOST\t\tEQU\t1000h\t\t; Shape is drawn ghosted\n;SHAPE_SHADOW\t\tEQU\t2000h\nSHAPE_PARTIAL  \t\tEQU\t4000h\n;SHAPE_COLOR \t\tEQU\t8000h\t\t; Remap the shape's colors\n\t\t\t\t\t\t;   (VOID * color_table)\n\n\n;\n;.......................... Shadow Effect ..................................\n;\nSHADOW_COL\t\tEQU\t00FFh\t; magic number for shadows\n\n;......................... Priority System .................................\n;\nCLEAR_UNUSED_BITS  \tEQU\t0007h\t; and with 0000-0111 to clear\n\t\t\t\t\t;  non-walkable high bit and\n\t\t\t\t\t;  scaling id bits\nNON_WALKABLE_BIT  \tEQU\t0080h\t; and with 1000-0000 to clear all\n\t\t\t\t\t;  but non-walkable bit\n;\n;......................... Predator Effect .................................\n;\n;PRED_MASK\t\tEQU\t0007h\t; mask used for predator pixel puts\nPRED_MASK\t\tEQU\t000Eh\t; mask used for predator pixel puts\n\n\n;---------------------------------------------------------------------------\n;\n; Use a macro to make code a little cleaner.\n; The parameter varname is optional.\n; Syntax to use macro is :\n;  WANT equ expression\n;  USE func [,varname]\n; If the 'varname' is defined, a table declaration is created like:\n;\tGLOBAL\tTableName:DWORD\n; Then, the table entry is created:\n;  If WANT is true, the table entry is created for the given function:\n;\tvarname\tDD\tfunc\n;  If WANT is not TRUE, a Not_Supported entry is put in the table:\n;\tvarname\tDD\tNot_Supported\n; The resulting tables look like:\n;\n;\tGLOBAL\tExampTable:DWORD\n;\tExampTable\tDD\troutine1\n;\t\t\tDD\troutine2\n;\t\t\tDD\troutine3\n;\t\t\t...\n; Thus, each table is an array of function pointers.\n;\n;---------------------------------------------------------------------------\nMACRO USE func, varname\n IF WANT\n  varname \tDD\tfunc\n ELSE\n  varname\tDD\tNot_Supported\n ENDIF\nENDM\n\n; IFNB <varname>\n;\tGLOBAL\tvarname:DWORD\n; ENDIF\n\n;---------------------------------------------------------------------------\n\n\nDATASEG\n\n;---------------------------------------------------------------------------\n; Predator effect variables\n;---------------------------------------------------------------------------\n; make table for negative offset and use the used space for other variables\n\nBFPredNegTable\tDW\t-1, -3, -2, -5, -2, -4, -3, -1\n\t; 8 words below calculated\n\t\tDW\t0, 0, 0, 0, 0, 0, 0, 0\t; index ffffff00\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff10\nBFPredOffset\tDD\t0, 0, 0, 0\t\t; index ffffff20\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff30\n\t; partially faded predator effect value\nBFPartialPred\tDD\t0, 0, 0, 0\t\t; index ffffff40\nBFPartialCount\tDD\t0, 0, 0, 0\t\t; index ffffff50\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff60\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff70\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff80\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff90\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffa0\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffb0\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffc0\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffd0\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffe0\n\t\tDD\t0, 0, 0, 0\t\t; index fffffff0\nBFPredTable\tDW\t1, 3, 2, 5, 2, 3, 4, 1\n;BFPredTable\tDB\t1, 3, 2, 5, 4, 3, 2, 1\n\n\nCODESEG\n\n;---------------------------------------------------------------------------\n; Code Segment Tables:\n; This code uses the USE macro to set up tables of function addresses.\n; The tables have the following format:\n; Tables defined are:\n;\tBufferFrameTable\n;---------------------------------------------------------------------------\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Copy, BufferFrameTable\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Ghost\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Ghost_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Fading\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Fading_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Ghost_Fading\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Ghost_Fading_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Ghost\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Ghost_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Fading\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Fading_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Ghost_Fading\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Ghost_Fading_Trans\n\n;---------------------------------------------------------------------------\n\nglobal _Int3:near\nproc _Int3 near\n\tint\t3\n\tret\nendp\n\n\n;***************************************************************************\n;* VVC::TOPAGE -- Copies a linear buffer to a virtual viewport\t\t   *\n;*                                                                         *\n;* INPUT:\tWORD\tx_pixel\t\t- x pixel on viewport to copy from *\n;*\t\tWORD\ty_pixel \t- y pixel on viewport to copy from *\n;*\t\tWORD\tpixel_width\t- the width of copy region\t   *\n;*\t\tWORD\tpixel_height\t- the height of copy region\t   *\n;*\t\tBYTE *\tsrc\t\t- buffer to copy from\t\t   *\n;*\t\tVVPC *  dest\t\t- virtual viewport to copy to\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    Coordinates and dimensions will be adjusted if they exceed *\n;*\t        the boundaries.  In the event that no adjustment is \t   *\n;*\t        possible this routine will abort.  If the size of the \t   *\n;*\t\tregion to copy exceeds the size passed in for the buffer   *\n;*\t\tthe routine will automatically abort.\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Buffer_Frame_To_Page:NEAR\n\tPROC\tBuffer_Frame_To_Page C near\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\tARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\tARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\tARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\tARG    \tsrc         :DWORD\t\t; this is a member function\n\tARG\tdest        :DWORD\t\t; what are we blitting to\n\n\tARG\tflags       :DWORD\t\t; flags passed\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL\tIsTranslucent\t\t:DWORD\t; ptr to the is_translucent table\n\tLOCAL\tTranslucent\t\t:DWORD\t; ptr to the actual translucent table\n\tLOCAL\tFadingTable\t\t:DWORD\t; extracted fading table pointer\n\tLOCAL\tFadingNum\t\t:DWORD\t; get the number of times to fade\n\n\tLOCAL\tStashECX\t\t:DWORD\t; temp variable for ECX register\n\n\tLOCAL\tjflags\t\t\t:DWORD\t; flags used to goto correct buff frame routine\n\tLOCAL\tBufferFrameRout\t\t:DWORD\t; ptr to the buffer frame routine\n\n\tLOCAL\tjmp_loc\t\t\t:DWORD\t; calculated jump location\n\tLOCAL\tloop_cnt\t\t:DWORD\n\n\tLOCAL \tx1_pixel\t\t:DWORD\n\tLOCAL\ty1_pixel\t\t:DWORD\n\tLOCAL\tscr_x\t\t\t:DWORD\n\tLOCAL\tscr_y\t\t\t:DWORD\n\tLOCAL\tdest_adjust_width\t:DWORD\n\tLOCAL\tscr_adjust_width\t:DWORD\n\n\n\tcmp\t[ src ] , 0\n\tjz\t??real_out\n\n\t;====================================================================\n\t; Pull off optional arguments:\n\t; EDI is used as an offset from the 'flags' parameter, to point\n\t; to the optional argument currently being processed.\n\t;====================================================================\n??do_args:\n\tmov\tedi , 4\t \t\t\t; optional params start past flags\n\tmov\t[ jflags ] , 0\t\t\t; clear jump flags\n\n??check_centering:\n\t;-------------------------------------------------------------------\n\t; See if we need to center the frame\n\t;-------------------------------------------------------------------\n\ttest\t[ flags ] , SHAPE_CENTER\t; does this need to be centered?\n\tje\t??check_trans\t\t\t; if not the skip over this stuff\n\n\tmov\teax , [ pixel_width ]\n\tmov\tebx , [ pixel_height ]\n\tsar\teax , 1\n\tsar\tebx , 1\n\tsub\t[ x_pixel ] , eax\n\tsub\t[ y_pixel ] , ebx\n\n??check_trans:\n\ttest\t[ flags ] , SHAPE_TRANS\n\tjz\t??check_ghost\n\n\tor\t[ jflags ] , FLAG_TRANS\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_GHOST: DWORD is_translucent tbl\n\t;--------------------------------------------------------------------\n??check_ghost:\n\ttest\t[ flags ] , SHAPE_GHOST\t\t; are we ghosting this shape\n\tjz\t??check_fading\n\n\tmov\teax , [ flags + edi ]\n\tor\t[ jflags ] , FLAG_GHOST\n\tmov\t[ IsTranslucent ] , eax\t\t; save ptr to is_trans. tbl\n\tadd\teax , 0100h\t\t\t; add 256 for first table\n\tadd\tedi , 4\t\t\t\t; next argument\n\tmov\t[ Translucent ] , eax\t\t; save ptr to translucent tbl\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_FADING: DWORD fade_table[256], DWORD fade_count\n\t;--------------------------------------------------------------------\n??check_fading:\n\ttest\t[ flags ] , SHAPE_FADING\t; are we fading this shape\n\tjz\t??check_predator\n\n\tmov\teax , [ flags + edi ]\n\tmov\t[ FadingTable ] , eax\t\t; save address of fading tbl\n\tmov\teax , [ flags + edi + 4 ]\t; get fade num\n\tor\t[ jflags ] , FLAG_FADING\n\tand\teax , 03fh\t\t\t; no need for more than 63\n\tadd\tedi , 8\t\t\t\t; next argument\n\tcmp\teax , 0\t\t\t\t; check if it's 0\n\tjnz\t??set_fading\t\t\t; if not, store fade num\n\n\tand\t[ flags ] , NOT SHAPE_FADING\t; otherwise, don't fade\n\n??set_fading:\n\tmov\t[ FadingNum ] , eax\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_PREDATOR: DWORD init_pred_lookup_offset (0-7)\n\t;--------------------------------------------------------------------\n??check_predator:\n\ttest\t[ flags ] , SHAPE_PREDATOR\t; is predator effect on\n\tjz\t??check_partial\n\n\tmov\teax , [ flags + edi ]\t\t; pull the partial value\n\tor\t[ jflags ] , FLAG_PREDATOR\n\tshl\teax , 1\n\tcmp\teax , 0\n\tjge\t??check_range\n\n\tneg\teax\n\tmov\tebx , -1\n\tand\teax , PRED_MASK\t\t\t; keep entries within bounds\n\tmov\tbl , al\n\tmov\teax , ebx\t\t\t; will be ffffff00-ffffff07\n\tjmp\t??pred_cont\n\n??check_range:\n\tand\teax , PRED_MASK\t\t\t; keep entries within bounds\n\n??pred_cont:\n\tadd\tedi , 4\t\t\t\t; next argument\n\tmov\t[ BFPredOffset ] , eax\n\tmov\t[ BFPartialCount ] , 0\t\t; clear the partial count\n\tmov\t[ BFPartialPred ] , 100h\t; init partial to off\n\n??pred_neg_init:\n\tmov  \tesi , [ dest ]\t    ; get ptr to dest\n\tmov\tebx, 7 * 2\n\n??pred_loop:\n\tmovzx\teax , [ WORD PTR BFPredNegTable + ebx ]\n\tadd\teax , [ (GraphicViewPort esi) . GVPWidth ]\t; add width\n\tadd\teax , [ (GraphicViewPort esi) . GVPXAdd ]\t; add x add\n\tmov\t[ WORD PTR BFPredNegTable + 16 + ebx ] , ax\n\tdec\tebx\n\tdec\tebx\n\tjge\t??pred_loop\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_PARTIAL: DWORD partial_pred_value (0-255)\n\t;--------------------------------------------------------------------\n??check_partial:\n\ttest\t[ flags ] , SHAPE_PARTIAL\t\t; is this a partial pred?\n\tjz\t??setupfunc\n\n\tmov\teax , [ flags + edi ]\t\t; pull the partial value\n\tadd\tedi , 4\t\t\t\t; next argument\n\tand\teax , 0ffh\t\t\t; make sure 0-255\n\tmov\t[ BFPartialPred ] , eax\t\t; store it off\n\n??setupfunc:\n\tmov\tebx , [ jflags ]\t\t; load flags value\n\tand\tebx , FLAG_MASK\t\t\t; clip high bits\n\tadd\tebx , ebx\t\t\t; mult by 4 to get DWORD offset\n\tadd\tebx , ebx\n\tmov\tebx , [ BufferFrameTable + ebx ]\t; get table value\n\tmov\t[ BufferFrameRout ] , ebx\t\t; store it in the function pointer\n\n; Clip dest Rectangle against source Window boundaries.\n\n\tmov\t[ scr_x ] , 0\n\tmov\t[ scr_y ] , 0\n\tmov  \tesi , [ dest ]\t    ; get ptr to dest\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\n\tor\tal , dl\n\tjz\t??do_blit\n\n\ttest\tcl , 1000b\n\tjz\t??dest_left_ok\n\n\tmov\teax , [ x_pixel ]\n\tneg\teax\n\tmov\t[ x_pixel ] , 0\n\tmov\t[ scr_x ] , eax\n\n??dest_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dest_bottom_ok\n\n\tmov\teax , [ y_pixel ]\n\tneg\teax\n\tmov\t[ y_pixel ] , 0\n\tmov\t[ scr_y ] , eax\n\n??dest_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??dest_right_ok\n\n\tmov\teax , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n\n??dest_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\n\tmov\teax , [ (GraphicViewPort esi) . GVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n??do_blit:\n\tcld\n\tmov\teax , [ (GraphicViewPort esi) . GVPXAdd ]\n\tadd\teax , [ (GraphicViewPort esi) . GVPWidth ]\n\tmov\tedi , [ (GraphicViewPort esi) . GVPOffset ]\n\n\tmov\tecx , eax\n\tmul\t[ y_pixel ]\n\tadd\tedi , [ x_pixel ]\n\tadd\tedi , eax\n\n\tadd\tecx , [ x_pixel ]\n\tsub\tecx , [ x1_pixel ]\n\tmov\t[ dest_adjust_width ] , ecx\n\n\tmov\tesi , [ src ]\n\tmov\teax , [ pixel_width ]\n\tsub\teax , [ x1_pixel ]\n\tadd\teax , [ x_pixel ]\n\tmov\t[ scr_adjust_width ] , eax\n\n\tmov\teax , [ scr_y ]\n\tmul\t[ pixel_width ]\n\tadd\teax , [ scr_x ]\n\tadd\tesi , eax\n\n\tmov\tedx , [ y1_pixel ]\n\tmov\teax , [ x1_pixel ]\n\n\tsub\tedx , [ y_pixel ]\n\tjle\t??real_out\n\n\tsub\teax , [ x_pixel ]\n\tjle\t??real_out\n\n\tjmp\t[ BufferFrameRout ]\t; buffer frame to viewport routine\n\n??real_out:\n\tret\n\n\n; ********************************************************************\n; Forward bitblit only\n; the inner loop is so efficient that\n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n; ********************************************************************\n\nBF_Copy:\n\n\tcmp\teax , 10\n\tjl\t??forward_loop_bytes\n\n??forward_loop_dword:\n\tmov\tecx , edi\n\tmov\tebx , eax\n\tneg\tecx\n\tand\tecx , 3\n\tsub\tebx , ecx\n\trep\tmovsb\n\tmov\tecx , ebx\n\tshr\tecx , 2\n\trep\tmovsd\n\tmov\tecx , ebx\n\tand\tecx , 3\n\trep\tmovsb\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??forward_loop_dword\n\n\tret\n\n??forward_loop_bytes:\n\tmov\tecx , eax\n\trep\tmovsb\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\t\t\t\t\t; decrement the height\n\tjnz\t??forward_loop_bytes\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Trans:\n\n; calc the code location to skip to 10 bytes per REPT below!!!!\n\tmov\tecx , eax\n\tand\tecx , 01fh\n\tlea\tecx , [ ecx + ecx * 4 ]\t\t; quick multiply by 5\n\tneg\tecx\n\tshr\teax , 5\n\tlea\tecx , [ ??trans_reference + ecx * 2 ] ; next multiply by 2\n\tmov\t[ loop_cnt ] , eax\n\tmov\t[ jmp_loc ] , ecx\n\n??trans_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n; the following code should NOT be changed without changing the calculation\n; above!!!!!!\n\n??trans_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\t\tmov\tbl , [ esi ]\n\t\tinc\tesi\n\t\ttest\tbl , bl\n\t\tjz\ttrans_pixel\n\n\t\tmov\t[ edi ] , bl\n\n\ttrans_pixel:\n\t\tinc\tedi\n\tENDM\n\n??trans_reference:\n\tdec\tecx\n\tjge\t??trans_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??trans_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Ghost:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??ghost_reference - ??ghost_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??ghost_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??ghost_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??ghost_line:\n\n\tREPT\t32\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tstore_pixel\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??ghost_reference:\n\tdec\tecx\n\tjge\t??ghost_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??ghost_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Ghost_Trans:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??ghost_t_reference - ??ghost_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??ghost_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??ghost_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??ghost_t_line:\n\n\tREPT\t32\n\tlocal\ttransp_pixel\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttransp_pixel\n\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tstore_pixel\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttransp_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??ghost_t_reference:\n\tdec\tecx\n\tjge\t??ghost_t_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??ghost_t_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Fading:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??fading_reference - ??fading_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??fading_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??fading_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\tjmp\t[ jmp_loc ]\n\n??fading_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??fading_line:\n\n\tREPT\t32\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??fading_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??fading_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??fading_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Fading_Trans:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??fading_t_reference - ??fading_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??fading_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??fading_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\tjmp\t[ jmp_loc ]\n\n??fading_t_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??fading_t_line:\n\n\tREPT\t32\n\tlocal\ttransp_pixel\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttransp_pixel\n\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\t\tmov\t[ edi ] , al\n\n\ttransp_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??fading_t_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??fading_t_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??fading_t_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Ghost_Fading:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??ghost_f_reference - ??ghost_f_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??ghost_f_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??ghost_f_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??ghost_f_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??ghost_f_line:\n\n\tREPT\t32\n\tlocal\tstore_pixel\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a lucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tdo_fading\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the lation table\n\t\t\t\t\t\t\t; ((_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (_color * 256) of the lation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n; DRD\t\tjmp\tstore_pixel\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??ghost_f_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??ghost_f_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??ghost_f_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Ghost_Fading_Trans:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??ghost_f_t_reference - ??ghost_f_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??ghost_f_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??ghost_f_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??ghost_f_t_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??ghost_f_t_line:\n\n\tREPT\t32\n\tlocal\ttransp_pixel\n\tlocal\tstore_pixel\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttransp_pixel\n\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tdo_fading\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n; DRD\t\tjmp\tstore_pixel\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttransp_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??ghost_f_t_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??ghost_f_t_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??ghost_f_t_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Predator:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_reference - ??predator_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??predator_line:\n\n\tREPT\t32\n\tlocal\tget_pred\n\tlocal\tskip_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tskip_pixel\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n;\t\txor\tbh , bh\n;\t\tmov\teax , [ BFPredValue ]\t; pick up a color offset a pseudo-\n;\t\t\t\t\t\t;  random amount from the current\n;\t\tmov\t[ BFPartialCount ] , ebx\n;\t\tmov\tal , [ edi + eax ]\t;  viewport address\n\n\t\tmov\t[ edi ] , al\n\n\tskip_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??predator_reference:\n\tdec\tecx\n\tjge\t??predator_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Predator_Trans:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_t_reference - ??predator_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??predator_t_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\tlocal\tget_pred\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttrans_pixel\n\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tstore_pixel\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttrans_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??predator_t_reference:\n\tdec\tecx\n\tjge\t??predator_t_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_t_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Predator_Ghost:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_g_reference - ??predator_g_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_g_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_g_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??predator_g_line:\n\n\tREPT\t32\n\tlocal\tget_pred\n\tlocal\tcheck_ghost\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tinc\tesi\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tcheck_ghost\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tcheck_ghost:\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tstore_pixel\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??predator_g_reference:\n\tdec\tecx\n\tjge\t??predator_g_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_g_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Predator_Ghost_Trans:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_g_t_reference - ??predator_g_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_g_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_g_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??predator_g_t_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\tlocal\tget_pred\n\tlocal\tcheck_ghost\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttrans_pixel\n\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tcheck_ghost\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tcheck_ghost:\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tstore_pixel\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttrans_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??predator_g_t_reference:\n\tdec\tecx\n\tjge\t??predator_g_t_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_g_t_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Predator_Fading:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_f_reference - ??predator_f_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_f_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_f_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??predator_f_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??predator_f_line:\n\n\tREPT\t32\n\tlocal\tget_pred\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tinc\tesi\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tdo_fading\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??predator_f_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??predator_f_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_f_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Predator_Fading_Trans:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_f_t_reference - ??predator_f_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_f_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_f_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??predator_f_t_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??predator_f_t_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\tlocal\tget_pred\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttrans_pixel\n\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tdo_fading\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\t\tmov\t[ edi ] , al\n\n\ttrans_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??predator_f_t_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??predator_f_t_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_f_t_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Predator_Ghost_Fading:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_g_f_reference - ??predator_g_f_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_g_f_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_g_f_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??predator_g_f_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??predator_g_f_line:\n\n\tREPT\t32\n\tlocal\tget_pred\n\tlocal\tcheck_ghost\n\tlocal\tstore_pixel\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tinc\tesi\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tcheck_ghost\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tcheck_ghost:\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tdo_fading\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n; DRD\t\tjmp\tstore_pixel\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??predator_g_f_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??predator_g_f_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_g_f_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Predator_Ghost_Fading_Trans:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_g_f_t_reference - ??predator_g_f_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_g_f_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_g_f_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??predator_g_f_t_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??predator_g_f_t_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\tlocal\tget_pred\n\tlocal\tcheck_ghost\n\tlocal\tstore_pixel\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttrans_pixel\n\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tcheck_ghost\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tcheck_ghost:\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tdo_fading\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n; DRD\t\tjmp\tstore_pixel\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttrans_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??predator_g_f_t_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??predator_g_f_t_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_g_f_t_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nNot_Supported:\n\tret\n\n\tENDP\tBuffer_Frame_To_Page\nEND\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : KEYFBUFF.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 16, 1992                            *\n;*                                                                         *\n;*                  Last Update : October 2, 1994   [JLB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   BUFFER_FRAME_TO_LOGICPAGE --                                          *\n;*   Normal_Draw -- Function that writes a normal pixel line               *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\tIDEAL\n\tP386\nIDEAL_MODE\tEQU\t1\n\tINCLUDE \"wwlib.i\"\n\n\t;-------------------------------------------------------------------\n\t; Extern all the library variables that this module requires\n\t;-------------------------------------------------------------------\n\n\tEXTRN\tC MaskPage:WORD\n\tEXTRN\tC BackGroundPage:WORD\n\n\t;-------------------------------------------------------------------\n\t; Define all the equates that this module requires\n\t;-------------------------------------------------------------------\n\nWIN_X\t\tEQU\t0\t\t; offset for the x coordinate\nWIN_Y\t\tEQU\t2\t\t; offset for the y coordinate\nWIN_WIDTH\tEQU\t4\t\t; offset for the window width\nWIN_HEIGHT\tEQU\t6\t\t; offset for the window height\nBYTESPERROW\tEQU\t320\t\t; number of bytes per row\n\nFLAG_NORMAL\t\tEQU\t0\t\t; flag for normal draw\n\nFLAG_GHOST\t\tEQU\t1\t\t; This flag enables the ghost\nFLAG_PRIORITY_TRANS\tEQU\t2\t\t; flag for priority and transparent\nFLAG_TRANS\t\tEQU\t4\t\t; flag for transparent draw\nFLAG_PRIORITY\t\tEQU\t8\t\t; flag for priority draw\n\n\t\t\t\t\t\t; fx on the above flags\n\nFLAG_MASK\t\tEQU\t15\t\t; used to and of uneeded bits\n\nSHAPE_NORMAL\t\tEQU\t0000h\t\t; Standard shape.\n;SHAPE_HORZ_REV\t\tEQU\t0001h\t\t; Flipped horizontally.\n;SHAPE_VERT_REV\t\tEQU\t0002h\t\t; Flipped vertically.\n;SHAPE_SCALING\t\tEQU\t0004h\t\t; Scaled (WORD scale_x, WORD scale_y)\n\nSHAPE_WIN_REL\t\tEQU\t0010h\t\t; Coordinates are window relative instead of absolute.\nSHAPE_CENTER\t\tEQU\t0020h\t\t; Coordinates are based on shape's center point.\nSHAPE_TRANS\t\tEQU\t0040h\t\t; has transparency\n\n\n;SHAPE_FADING\t\tEQU\t0100h\t\t; Fading effect active (VOID * fading_table, WORD fading_num).\n;SHAPE_PREDATOR\t\tEQU\t0200h\t\t; Transparent warping effect.\n;SHAPE_COMPACT\t\tEQU\t0400h\t\t; Never use this bit.\nSHAPE_PRIORITY\t\tEQU\t0800h\t\t; Use priority system when drawing.\n\nSHAPE_GHOST\t\tEQU\t1000h\t\t; Transluscent table process.\n;SHAPE_SHADOW\t\tEQU\t2000h\t\t; ????\n;SHAPE_PARTIAL \t\tEQU\t4000h\t\t; ????\n;SHAPE_COLOR\t\tEQU\t8000h\t\t; Remap the shape's colors (VOID * color_table).\n\n\n; MBL MOD 12.1.92\n\nCLEAR_NON_WALK_BIT_AND_SCALE_BITS\tEQU\t7\t; Makes it one AND per pixel in Priority_Trans display\nCLEAR_NON_WALK_BIT    \tEQU\t7fh\t; and with 0111-1111 to clear non-walkable high bit\nCLEAR_SCALE_BITS  \tEQU\t87h\t; and with 1000-0111 to clear scaling id bits\nNON_WALKABLE_BIT  \tEQU\t80h\t; and with 1000-0000 to clear all but non-walkable bit\n\n; END MBL MOD\n\n\n\tCODESEG\n\n\t;   1 = GHOST (all odd entrys are prefixed with Ghost_)\n\t;   2 = BLAAAH\n\t;   4 = Trans (prfx)\n\t;   8 = Prior (prfx)\n\n\n;---------------------------------------------------------------------------\n; Define the table of different line draw types\n;---------------------------------------------------------------------------\n\nLineTable\tDW\tWSA_Normal_Draw\t\t\t;0\n\t\tDW\tGhost_Normal_Draw\t\t;1\n\t\tDW\t0\t\t\t\t;2\n\t\tDW\t0\t\t\t\t;3\n\n\t\tDW\tTransparent_Draw\t\t;4\n\t\tDW\tGhost_Transparent_Draw\t\t;5\n\t\tDW\t0\t\t\t\t;6\n\t\tDW\t0\t\t\t\t;7\n\n\t\tDW\tPriority_Draw\t\t\t;8\n\t\tDW\tGhost_Priority_Draw\t\t;9\n\t\tDW\t0\t\t\t\t;10\n\t\tDW\t0\t\t\t\t;11\n\n\t\tDW\tPriority_Transparent_Draw\t;12\n\t\tDW\tGhost_Priority_Transparent_Draw\t;13\n\t\tDW\t0\t\t\t\t;14\n\t\tDW\t0\t\t\t\t;15\n\n\n\n;***************************************************************************\n;* BUFFER_FRAME_TO_LOGICPAGE --                                            *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/16/1992 PWG : Created.                                             *\n;*=========================================================================*\n\tPUBLIC\tC Buffer_Frame_To_LogicPage\n\tPROC\tC Buffer_Frame_To_LogicPage FAR USES ax bx ecx dx ds esi es edi\n\n\t;-------------------------------------------------------------------\n\t; Define the arguements that our program takes.\n\t;-------------------------------------------------------------------\n\n\tARG\tx_pixel:WORD\t\t; x pixel position to draw at\n\tARG\ty_pixel:WORD\t\t; y pixel position to draw at\n\tARG\tpixel_w:WORD\t\t; pixel width of draw region\n\tARG\tpixel_h:WORD\t\t; pixel height of draw region\n\tARG\twin:WORD\t\t; window to clip around\n\tARG\tflags:WORD\t\t; flags that this routine will take\n\tARG\tbuffer:DWORD\t\t; pointer to the buffer with data\n\tARG\targs:WORD\n\n\t;-------------------------------------------------------------------\n\t; Define the local variables that our program uses\n\t;-------------------------------------------------------------------\n\n\tLOCAL\tIsTranslucent:DWORD\t; ptr to the is_translucent table\n\tLOCAL\tTranslucent:DWORD\t; ptr to the actual translucent table\n\n\tLOCAL\twin_x1:WORD\t\t; clip window left x pixel position\n\tLOCAL\twin_x2:WORD\t\t; clip window right x pixel position\n\tLOCAL\twin_y1:WORD\t\t; clip window top y pixel position\n\tLOCAL\twin_y2:WORD\t\t; clip window bottom y pixel position\n\tLOCAL\tclipleft:WORD\t\t; number of pixels to clip on left\n\tLOCAL\tclipright:WORD\t\t; number of pixels to clip on right\n\tLOCAL\tnextline:WORD\t\t; offset to the next line\n\tLOCAL\tputmiddle:WORD \t\t; routine to call to put the middle\n\tLOCAL\tmaskpage:WORD\t\t; location of the depth masks\n\tLOCAL   background:WORD\t\t; location of the background data\n\tLOCAL   jflags:WORD\t\t; location of the background data\n\n\tLOCAL\tpriority:BYTE\t\t; the priority level of the back\n\n\tpush\tfs\n\n\txor\tecx,ecx\n\n\t;--------------------------------------------------------------------\n\t; Check to see if we have supplied any GHOST tables.\n\t;--------------------------------------------------------------------\n\tpush\tdi\n\n\tmov\tdi,6\n\tmov\t[jflags],0\n\n??ghost:\n\ttest\t[flags],SHAPE_GHOST\t; are we ghosting this shape\n\tjz\tshort ??no_ghost\t; if not then skip and do more\n\n\tor\t[jflags],FLAG_GHOST\n\n\tles\tax,[DWORD PTR buffer + di]\n\n\t; get the \"are we really translucent?\" table\n\tmov\t[WORD PTR IsTranslucent],ax\n\tmov\t[WORD PTR IsTranslucent + 2],es\n\tadd\tax,0100h\t\t; add to offset for tables\n\n\t; get the \"ok we are translucent!!\" table\n\tmov\t[WORD PTR Translucent],ax\n\tmov\t[WORD PTR Translucent + 2],es\n\n\tadd\tdi,4\n\n??no_ghost:\n\n\tpop\tdi\n\n\t;-------------------------------------------------------------------\n\t; See if we need to center the frame\n\t;-------------------------------------------------------------------\n\ttest\t[flags],SHAPE_CENTER\t; does this need to be centered?\n\tje\tshort ??no_centering\t; if not the skip over this stuff\n\n\tmov\tax,[pixel_w]\n\tmov\tbx,[pixel_h]\n\tsar\tax,1\n\tsar\tbx,1\n\tsub\t[x_pixel],ax\n\tsub\t[y_pixel],bx\n\n??no_centering:\n\tmov\tax,[flags]\n\tand\tax,SHAPE_PRIORITY+SHAPE_TRANS\n\tcmp\tax,SHAPE_PRIORITY+SHAPE_TRANS\n\tjne\tshort ??test_trans\n\n\tor\t[jflags],FLAG_PRIORITY_TRANS\n\tjmp\tshort ??priority\n\n\t;-------------------------------------------------------------------\n\t; Get the trans information if we need to get it\n\t;-------------------------------------------------------------------\n??test_trans:\n\ttest\t[flags],SHAPE_TRANS\t; does this draw use transparencies?\n\tje\tshort ??test_priority\t; if not the skip over this junk\n\n\tor\t[jflags],FLAG_TRANS\n\n??test_priority:\n\t;-------------------------------------------------------------------\n\t; Get the priority information if we need to get it\n\t;-------------------------------------------------------------------\n\ttest\t[flags],SHAPE_PRIORITY\t; does this draw use priorities?\n\tje\tshort ??no_priority\t; if not the skip over this junk\n\n\tor\t[jflags],FLAG_PRIORITY\n\n??priority:\n\tmov\tax,[BackGroundPage]\t; get the background page from ds\n\tmov\t[background],ax\t\t;    and store it on the stack\n\tmov\tax,[MaskPage]\t\t; get the mask page from ds\n\tmov\t[maskpage],ax\t\t;    and store it on the stack\n\tmov\tax,[WORD PTR buffer + 4]; get the priority level from args\n\tmov\t[priority],al\t\t;    and store it in a local\n\n\t;-------------------------------------------------------------------\n\t; Get the draw routine that we are going to draw with\n\t;-------------------------------------------------------------------\n??no_priority:\n;\tmov\tbx,[flags]\t\t; load in the current flags byte\n;\tand\tbx,FLAG_MASK\t\t; prevent lockup on bad value\n\tmov\tbx,[jflags]\t\t; load in the jump table flags\n\tshl\tbx,1\n\tmov\tax,[WORD PTR LineTable + bx]\t; get the offset of the skip table\n\tmov\t[putmiddle],ax\t\t; store off the new offset\n\n\t;-------------------------------------------------------------------\n\t; Get a pointer to the logic page to where we will draw our buffer\n\t;-------------------------------------------------------------------\n\tpush\t[LogicPage]\t\t; push the current logic page\n\tcall\tFAR PTR Get_Page\t; get the physical page address\n\tadd\tsp,2\t\t\t; pull the parameter from the stack\n\tmov\tes,dx\t\t\t; store the address in the dest\n\n\t;--------------------------------------------------------------------\n\t; Point DI to the beginning of the window that we need to look at.\n\t;   that way we can access all of the info through di.\n\t;--------------------------------------------------------------------\n\tmov\tsi,OFFSET WindowList\t; get the offset of the window list\n\tmov\tcl,4\t\t\t; shift 3 times = multiply by 16\n\tmov\tax,[win]\t\t; get the window number we are using\n\tshl\tax,cl\t\t\t; each window is 8 words long\n\tadd\tsi,ax\t\t\t; add that into the offset of window\n\n\t;--------------------------------------------------------------------\n\t; Place all the clipping values on the stack so our function will\n\t; be truly re-entrant and will not need to shadow these values.\n\t;--------------------------------------------------------------------\n\tmov\tcl,3\t\t\t; to convert x to pixel mult by 8\n\tmov\tax,[si + WIN_X]\t\t; get the left clip position\n\tshl\tax,cl\t\t\t; convert to a pixel x position\n\tmov\t[win_x1],ax\t\t; store the left edge of window\n\tmov\t[win_x2],ax\n\n\tmov\tax,[si + WIN_WIDTH]\t; get the width of the window\n\tshl\tax,cl\t\t\t; convert to a pixel width\n\tadd\t[win_x2],ax\t\t; add to get the right window edge\n\n\tmov\tax,[si + WIN_Y]\t\t; get the win y coordinate to clip\n\tmov\t[win_y1],ax\t\t; and save it onto the stack\n\n\tadd\tax,[si + WIN_HEIGHT]\t; calculate the bottom win y coord\n\tmov\t[win_y2],ax\t\t; and save it onto the stack\n\n\ttest\t[flags],SHAPE_WIN_REL\t; is this window relative?\n\tje\tshort ??get_buffer\t; if not the skip over\n\n\tmov\tax,[win_x1]\t\t; get left edge of window\n\tadd\t[x_pixel],ax\t\t; add to x pixel position\n\tmov\tax,[win_y1]\t\t; get top edge of window\n\tadd\t[y_pixel],ax\t\t; add to y pixel position\n\n\t;--------------------------------------------------------------------\n\t; Get a pointer to the source buffer so we can handle the clipping\n\t;--------------------------------------------------------------------\n??get_buffer:\n\tlds\tsi,[buffer]\t\t; get a pointer to the buffer\n\n\t;--------------------------------------------------------------------\n\t; Check the top of our shape and clip any lines that are necessary\n\t;--------------------------------------------------------------------\n\tmov\tax,[y_pixel]\t\t; get the y_pixel draw position\n\tsub\tax,[win_y1]\t\t; subtract out the window y top\n\tjns\tshort ??check_bottom\t\t;   skip if y below window top\n\tadd\tax,[pixel_h]\t\t; add in the height of the region\n\tjg\tshort ??clip_top\t\t; if positive then clip top lines\n\n??jump_exit:\n\tjmp\t??exit\t\t\t; otherwise completely clipped\n\n??clip_top:\n\txchg\t[pixel_h],ax\n\tsub\tax,[pixel_h]\n\tadd\t[y_pixel],ax\n\tmul\t[pixel_w]\t\t; convert to number of bytes to skip\n\tadd\tsi,ax\t\t\t; skip past the necessary bytes\n\n\t;--------------------------------------------------------------------\n\t; Check the bottom of our shape and clip it if necessary\n\t;--------------------------------------------------------------------\n??check_bottom:\n\tmov\tax,[win_y2]\t\t; get the bottom y of the window\n\tsub\tax,[y_pixel]\t\t; subtract of the y to draw at\n\tjs\t??jump_exit\t\t; if its signed then nothing to draw\n\tjz\t??jump_exit\t\t; if its zero then nothing to draw\n\n\tcmp\tax,[pixel_h]\t\t; if more room to draw then height\n\tjae\tshort ??clip_x_left\t\t;   then go check the left clip\n\tmov\t[pixel_h],ax\t\t; clip all but amount that will fit\n\n??clip_x_left:\n\tmov\t[clipleft],0\t\t; clear clip on left of region\n\tmov\tax,[x_pixel]\t\t; get the pixel x of draw region\n\tsub\tax,[win_x1]\t\t; pull out the window coordinate\n\tjns\tshort ??clip_x_right\n\tneg\tax\t\t\t; negate to get amnt to skip in buf\n\tmov\t[clipleft],ax\t\t; store it in the left clip info\n\tadd\t[x_pixel],ax\t\t; move to the edge of the window\n\tsub\t[pixel_w],ax\t\t; pull it out of the pixel width\n\n??clip_x_right:\n\tmov\t[clipright],0\t\t; clear clip on right of region\n\tmov\tax,[win_x2]\t\t; get the window x of clip region\n\tsub\tax,[x_pixel]\t\t; subtract the draw edge of region\n\tjs\t??jump_exit\t\t; if its negative then get out\n\tjz\t??jump_exit\t\t; if its zero then get out\n\n\tcmp\tax,[pixel_w]\t\t; is space available larger than w\n\tjae\tshort ??draw_prep\t\t;   if so then go get drawing\n\n\n\txchg\t[pixel_w],ax\t\t; amt to draw in pixel_w (wid in ax)\n\tsub\tax,[pixel_w]\t\t; pull out the amount to draw\n\tmov\t[clipright],ax\t\t; this is the amount to clip on right\n\n??draw_prep:\n\tpush\tsi\t\t\t; save off source pos in buffer\n\tpush\tds\t\t\t;   both offset and segment\n\tmov\tax,@data\n\tmov\tds,ax\n\tmov\tbx,[y_pixel]\n\tshl\tbx,1\t\t\t; shift left by 1 for word table look\n\tlds\tsi,[YTable]\t; get the address of the ytable\n\tmov\tdi,[ds:si+bx]\t\t; look up the multiplied value\n\tpop\tds\t\t\t; restore source pos in buffer\n\tpop\tsi\t\t\t;   both offset and segment\n\n\tadd\tdi,[x_pixel]\t\t; add in the x pixel position\n\tmov\t[nextline],di\t\t; save it off in the next line\n\n \t;--------------------------------------------------------------------\n\t; Now determine the type of the shape and process it in the proper\n\t;   way.\n\t;--------------------------------------------------------------------\n\tmov\tdx,[pixel_h]\n\n\t; Check to see if the WSA is the screen width and there is no\n\t; clipping. In this case, then a special single call to the\n\t; line processing routine is possible.\n\tmov\tax,[clipleft]\n\tadd\tax,[clipright]\n\tjne\tshort ??top_of_loop\n\tcmp\t[pixel_w],BYTESPERROW\n\tjne\tshort ??top_of_loop\n\n\t;------------------------------------\n\t; The width of the WSA is the screen width, so just process as\n\t; one large WSA line.\n\tmov\tax,BYTESPERROW\n\timul\tdx\n\tmov\tcx,ax\n\tcall\t[putmiddle]\n\tjmp\tshort ??exit\n\n\t;------------------------------------\n\t; Process line by line.\n??top_of_loop:\n\tadd\tsi,[clipleft]\t\t; skip whats necessary on left edge\n\tmov\tcx,[pixel_w]\t\t; get the width we need to draw\n\n\t; Copy the source to the destination as appropriate. This routine can\n\t; trash AX, BX, CX, and DI. It must properly modify SI to point one byte past\n\t; the end of the data.\n\tcall\t[putmiddle]\n\n\tadd\tsi,[clipright]\t\t; skip past the left clip\n\tadd\t[nextline],BYTESPERROW\n\tmov\tdi,[nextline]\n\n\tdec\tdx\n\tjnz\t??top_of_loop\n\n??exit:\n\tpop\tfs\n\tret\n\tENDP\n\n\n;***************************************************************************\n;* NORMAL_DRAW -- Function that writes a normal pixel line                 *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tNOLANGUAGE WSA_Normal_Draw NEAR\n\n IF 1\n \t; This version is marginally faster than the later version.\n \tmov\tax,cx\n\tshr\tcx,2\n\trep movsd\n\tand\tax,011b\n\tmov\tcx,ax\n\tshr\tcx,1\n\trep movsw\n\tadc\tcx,cx\n\trep movsb\n\tret\n\n ELSE\n\n\tshr\tcx,1\t\t\t; convert to words (odd pix in carry)\n\trep\tmovsw\t\t\t; write out the needed words\n\tadc\tcx,0\t\t\t; add the carry into cx\n\trep\tmovsb\t\t\t; write out the odd byte if any\n\tret\n ENDIF\n\n\tENDP\n\n\n;***************************************************************************\n;* TRANSPARENT_DRAW -- Function that writes a transparent pixel line       *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   10/02/1994 JLB : Optimized for 250% speed improvement.                *\n;*=========================================================================*\n\tPROC\tNOLANGUAGE Transparent_Draw NEAR\n\n IF 1\n\t; Preserve DX since it is used as a scratch register.\n\tpush\tdx\n\n??loop:\n\t; Swap DS:SI and ES:DI back in preparation for the REP SCASB\n\t; instruction.\n\txchg\tdi,si\n\tmov\tdx,es\n\tmov\tax,ds\n\tmov\tds,dx\n\tmov\tes,ax\n\n\t; Remember the bytes remaining in order to calculate the position\n\t; of the scan when it stops.\n\tmov\tbx,cx\n\n\t; Scan looking for a non-zero value in the source buffer.\n\txor\tal,al\n\trepe scasb\n\n\t; When the loop ends, if the EQ flag is set then the scanning is\n\t; complete. Jump to the end of the routine in order to fixup the\n\t; pointers.\n\tje\tshort ??fini\n\n\t; Advance the destination pointer by the amount necessary to match\n\t; the source movement. DS:SI points to where data should be written.\n\tadd\tsi,bx\n\tinc\tcx\t\t; SCASB leaves CX one too low, fix it.\n\tdec\tdi\t\t; SCASB leaves DI one byte too far, fix it.\n\tsub\tsi,cx\n\n\t; Scan for the duration of non-zero pixels. This yields a count which\n\t; is used to copy the source data to the destination. Preserve DI.\n\tmov\tdx,di\n\tmov\tbx,cx\n\trepne scasb\n\tmov\tdi,dx\n\n\t; Set BX to equal the number of bytes to copy from source to dest.\n\tinc\tcx\t\t; SCASB leaves CX one too low, fix it.\n\tsub\tbx,cx\n\n\t; Move the data from ES:DI to DS:SI for BX bytes.\n\txchg\tcx,bx\t\t; Make CX=bytes to move, BX=bytes remaining.\n\n\t; Swap DS:SI and ES:DI in preparation for the REP MOV instruction.\n\txchg\tdi,si\n\tmov\tdx,es\n\tmov\tax,ds\n\tmov\tds,dx\n\tmov\tes,ax\n\n\t; Move the data from source to dest. First try to move double\n\t; words. Then copy the remainder bytes (if any). Putting jumps in\n\t; this section doesn't result in any savings -- oh well.\n\tmov\tax,cx\n\tshr\tcx,2\n\trep movsd\n\tand\tax,0011b\n\tmov\tcx,ax\n\tshr\tcx,1\n\trep movsw\n\tadc\tcx,cx\n\trep movsb\n\n\t; Restore CX with the remaining bytes to process.\n\tmov\tcx,bx\n\n\t; If there are more bytes to process, then loop back.\n\tor\tcx,cx\n\tjne\tshort ??loop\n\n??fini:\n\t; Swap ES:DI and DS:SI back to original orientation.\n\tmov\tax,ds\n\tmov\tbx,es\n\tmov\tes,ax\n\tmov\tds,bx\n\txchg\tdi,si\n\n\t; Restore DX and return.\n\tpop\tdx\n\tret\n\n ELSE\n\n??loop_top:\n\tlodsb\n\tor\tal,al\n\tjz\tshort ??skip\n\n\tmov\t[es:di],al\t\t; store the pixel to the screen\n??skip:\n\tinc\tdi\n\tloop\t??loop_top\n\tret\n\n ENDIF\n\n\tENDP\n\n\n;***************************************************************************\n;* PRIORITY_DRAW -- Function that writes a pixels if they are in front of  *\n;*\t\t    the given plate.\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   12/01/1992 MBL : Updated to work with latest mask data encoding.      *\n;*   17/01/1993 MCC : Updated for 386, and optimized\t\t\t   *\n;*=========================================================================*\n\n\tPROC\tNOLANGUAGE Priority_Draw NEAR\n\n\tmov\tfs,[background]\t\t; get the SEG of the background page\n\tmov\tgs,[maskpage]\t\t; get the SEG of the mask info\n\tmov\tah,[priority]\t\t; keep a copy of priority varible for faster cmp\n\n\n??loop_top:\n\tlodsb\t\t\t\t; get the pixel to draw on the screen\n\n\t\t\t\t\t; get the mask byte for our pixel\n\tmov\tbl,[ds:di]\n\t\t\t\t\t; get rid of non-walkable bit and\n\t\t\t\t\t; get rid of scaling id bits\n\tand\tbl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS\n\n\tcmp\tah,bl\t\t\t; are we more toward the front?\n\tjge\tshort ??out_pixel\t; if so then write the pixel\n\n\tmov\tal,[fs:di]\t\t; get the pixel to write\n??out_pixel:\n\tstosb\t\t\t\t; write the pixel and inc the DI\n\tloop\t??loop_top\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* PRIORITY_TRANSPARENT_DRAW -- Function that writes a pixels if they are  *\n;*\t\t    in front of the given plate.  It also deals with\t   *\n;*\t\t    transparent pixels.\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   12/01/1992 MBL : Updated to work with latest mask data encoding.      *\n;*   17/01/1993 MCC : Updated for 386, and optimized\t\t\t   *\n;*=========================================================================*\n\n\tPROC\tNOLANGUAGE Priority_Transparent_Draw NEAR\n\n\tmov\tfs,[background]\t\t; get the SEG of the background page\n\tmov\tgs,[maskpage]\t\t; get the SEG of the mask info\n\tmov\tah,[priority]\t\t; keep a copy of priority varible for faster cmp\n\n??loop_top:\n\tlodsb\t\t\t\t; get the pixel on the screen\n\tor\tal,al\t\t\t; check to see if al is transparent\n\tje\tshort ??write_back\t; if it is go write background\n\n\tmov\tbl,[gs:di]\t\t; get the mask byte for our pixel\n\n\t\t\t\t\t; get rid of non-walkable bit and\n\t\t\t\t\t; get rid of scaling id bits\n\tand\tbl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS\n\n\tcmp\tah,bl\t\t\t; are we more toward the front?\n\tjge\tshort ??out_pixel\t; if so then write the pixel\n\n??write_back:\n\tmov\tal,[fs:di]\t\t; get the pixel to write\n??out_pixel:\n\tstosb\t\t\t\t; write the pixel\n\tloop\t??loop_top\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GHOST_NORMAL_DRAW -- Function that writes a normal pixel line           *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   05/27/1993 MCC : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tNOLANGUAGE Ghost_Normal_Draw NEAR\n\n??loop_top:\n\tlodsb\n\n;---\n\t; Ok, find out if the colour is a Translucent colour\n\tpush\tax\n\tpush \tds\n\n\tlds\tbx,[IsTranslucent]\n\tmov\tah,al\t\t\t; preserve real pixel\n\txlat\t\t\t\t; get new al (transluecent pixel\n\txchg\tah,al\t\t\t; get real pixel back into AL just in case\n\tcmp\tah,255\n\tje\tshort ??normal_pixel\t\t; is it a translucent ?\n\t\t\t\t\t; if we get passed here value in\n\t\t\t\t\t; AH should be 0-15\n\n\t; yes, it is a translucent colour so goto our translucent translation\n\t; table and set up a ptr to the correct table\n\n\tmov\tal,[es:di]\n\t\t\t\t\t; mov pixel at destination to al and we have\n\t\t\t\t\t; the index to the translation table\n\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tlds\tbx,[Translucent]\t; get the ptr to it!\n\tadd\tbh,ah\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\t\t\t\t; XLAT only uses AL so no need to clear AH\n\txlat\t\t\t\t; get new pixel in AL\n\n??normal_pixel:\n\tpop\tds\n\tpop\tbx\n\tmov\tah,bh\n;---\n\n\tmov\t[es:di],al\t\t; store the pixel to the screen\n\n??skip:\n\tinc\tdi\n\tloop\t??loop_top\n\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GHOST_TRANSPARENT_DRAW -- Function that writes a transparent pixel line *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   05/27/1993 MCC : Created.                                             *\n;*=========================================================================*\n\tPROC\tNOLANGUAGE Ghost_Transparent_Draw NEAR\n\n??loop_top:\n\tlodsb\n\tor\tal,al\n\tjz\tshort ??skip\n\n;---\n\t; Ok, find out if the colour is a Translucent colour\n\tpush\tax\n\tpush \tds\n\n\tlds\tbx,[IsTranslucent]\n\tmov\tah,al\t\t\t; preserve real pixel\n\txlat\t\t\t\t; get new al (transluecent pixel\n\txchg\tah,al\t\t\t; get real pixel back into AL just in case\n\tcmp\tah,255\n\tje\tshort ??normal_pixel\t\t; is it a translucent ?\n\t\t\t\t\t; if we get passed here value in\n\t\t\t\t\t; AH should be 0-15\n\n\t; yes, it is a translucent colour so goto our translucent translation\n\t; table and set up a ptr to the correct table\n\n\tmov\tal,[es:di]\n\t\t\t\t\t; mov pixel at destination to al and we have\n\t\t\t\t\t; the index to the translation table\n\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tlds\tbx,[Translucent]\t; get the ptr to it!\n\tadd\tbh,ah\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\t\t\t\t; XLAT only uses AL so no need to clear AH\n\txlat\t\t\t\t; get new pixel in AL\n\n??normal_pixel:\n\tpop\tds\n\tpop\tbx\n\tmov\tah,bh\n;---\n\n\tmov\t[es:di],al\t\t; store the pixel to the screen\n\n??skip:\n\tinc\tdi\n\tloop\t??loop_top\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GHOST_PRIORITY_DRAW -- Function that writes a pixels if they are in fron*\n;*\t\t    the given plate.\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   12/01/1992 MBL : Updated to work with latest mask data encoding.      *\n;*   05/27/1993 MCC : Updated to use the new Ghosting fx\t\t   *\n;*   17/01/1993 MCC : Updated for 386, and optimized\t\t\t   *\n;*=========================================================================*\n\tPROC\tNOLANGUAGE Ghost_Priority_Draw NEAR\n\n\tmov\tfs,[background]\t\t; get the SEG of the background page\n\tmov\tgs,[maskpage]\t\t; get the SEG of the mask info\n\tmov\tah,[priority]\t\t; keep a copy of priority varible for faster cmp\n\n\n??loop_top:\n\tlodsb\t\t\t\t; get the pixel to draw on the screen\n\t\t\t\t\t; get the mask byte for our pixel\n\tmov\tbl,[ds:di]\n\t\t\t\t\t; get rid of non-walkable bit and\n\t\t\t\t\t; get rid of scaling id bits\n\tand\tbl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS\n\tcmp\tah,bl\t\t\t; are we more toward the front?\n\tjge\tshort ??out_pixel\t; if so then write the pixel\n\n\tmov\tal,[fs:di]\t\t; get the pixel to write\n??out_pixel:\n\tstosb\t\t\t\t; write the pixel and inc the DI\n\tloop\t??loop_top\n\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GHOST_PRIORITY_TRANSPARENT_DRAW -- Function that writes a pixels if they*\n;*\t\t    in front of the given plate.  It also deals with\t   *\n;*\t\t    transparent pixels.\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   12/01/1992 MBL : Updated to work with latest mask data encoding.      *\n;*   05/27/1993 MCC : Updated to use the new Ghosting fx\t\t   *\n;*   17/01/1993 MCC : Updated for 386, and optimized\t\t\t   *\n;*=========================================================================*\n\tPROC\tNOLANGUAGE Ghost_Priority_Transparent_Draw NEAR\n\n\tmov\tfs,[background]\t\t; get the SEG of the background page\n\tmov\tgs,[maskpage]\t\t; get the SEG of the mask info\n\tmov\tah,[priority]\t\t; keep a copy of priority varible for faster cmp\n\n??loop_top:\n\tlodsb\t\t\t\t; get the pixel on the screen\n\tor\tal,al\t\t\t; check to see if al is transparent\n\tje\tshort ??write_back\t;   if it is go write background\n\tmov\tbl,[gs:di]\t\t; get the mask byte for our pixel\n\t\t\t\t\t; get rid of non-walkable bit and\n\t\t\t\t\t; get rid of scaling id bits\n\tand\tbl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS\n\tcmp\tah,bl\t\t\t; are we more toward the front?\n\tjge\tshort ??out_pixel\t; if so then write the pixel\n??write_back:\n\tmov\tal,[fs:di]\t\t; get the pixel to write\n??out_pixel:\n\tstosb\t\t\t\t; write the pixel\n\tloop\t??loop_top\n\n\tret\n\n\tENDP\n\n\tEND\n"
  },
  {
    "path": "CODE/KEYFBUFF.ASM.BAK",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : KEYFBUFF.ASM                             *\n;*                                                                         *\n;*                   Programmer : David R. Dettmer                         *\n;*                                                                         *\n;*                   Start Date : March 3, 1995                            *\n;*                                                                         *\n;*                  Last Update :                                          *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Buffer_Frame_To_Page -- Copies a linear buffer to a virtual viewport  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n;********************** Model & Processor Directives ***********************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"gbuffer.inc\"\n\n\n;******************************** Equates **********************************\n\nTRUE\tequ\t1\t\t\t; Boolean 'true' value\nFALSE\tequ\t0\t\t\t; Boolean 'false' value\n\n;*=========================================================================*/\n;* The following are defines used to control what functions are linked\t   *\n;* in for Buffer_Frame_To_Page.\t\t\t\t\t\t   *\n;*=========================================================================*/\n;USE_NORMAL\t\tEQU\tTRUE\n;USE_HORZ_REV \t\tEQU\tTRUE\n;USE_VERT_REV \t\tEQU\tTRUE\n;USE_SCALING \t\tEQU\tTRUE\n\n\nFLAG_NORMAL\t\tEQU\t0\nFLAG_TRANS\t\tEQU\t1\nFLAG_GHOST\t\tEQU\t2\nFLAG_FADING\t\tEQU\t4\nFLAG_PREDATOR\t\tEQU\t8\n\nFLAG_MASK\t\tEQU\t0Fh\n\n\nSHAPE_NORMAL \t\tEQU\t0000h\t\t; Standard shape\n;SHAPE_HORZ_REV \t\tEQU\t0001h\t\t; Flipped horizontally\n;SHAPE_VERT_REV \t\tEQU\t0002h\t\t; Flipped vertically\n;SHAPE_SCALING \t\tEQU\t0004h\t\t; Scaled (WORD scale_x, WORD scale_y)\n;SHAPE_VIEWPORT_REL \tEQU\t0010h\t\t; Coords are window-relative\n;SHAPE_WIN_REL \t\tEQU\t0010h\t\t; Coordinates are window relative instead of absolute.\nSHAPE_CENTER \t\tEQU\t0020h\t\t; Coords are based on shape's center pt\nSHAPE_TRANS\t\tEQU\t0040h\t\t; has transparency\n\nSHAPE_FADING \t\tEQU\t0100h\t\t; Fading effect (VOID * fading_table,\n\t\t\t\t\t\t;   WORD fading_num)\nSHAPE_PREDATOR \t\tEQU\t0200h\t\t; Transparent warping effect\n;SHAPE_COMPACT \t\tEQU\t0400h\t\t; Never use this bit\n;SHAPE_PRIORITY \t\tEQU\t0800h\t\t; Use priority system when drawing\nSHAPE_GHOST\t\tEQU\t1000h\t\t; Shape is drawn ghosted\n;SHAPE_SHADOW\t\tEQU\t2000h\nSHAPE_PARTIAL  \t\tEQU\t4000h\n;SHAPE_COLOR \t\tEQU\t8000h\t\t; Remap the shape's colors\n\t\t\t\t\t\t;   (VOID * color_table)\n\n\n;\n;.......................... Shadow Effect ..................................\n;\nSHADOW_COL\t\tEQU\t00FFh\t; magic number for shadows\n\n;......................... Priority System .................................\n;\nCLEAR_UNUSED_BITS  \tEQU\t0007h\t; and with 0000-0111 to clear\n\t\t\t\t\t;  non-walkable high bit and\n\t\t\t\t\t;  scaling id bits\nNON_WALKABLE_BIT  \tEQU\t0080h\t; and with 1000-0000 to clear all\n\t\t\t\t\t;  but non-walkable bit\n;\n;......................... Predator Effect .................................\n;\n;PRED_MASK\t\tEQU\t0007h\t; mask used for predator pixel puts\nPRED_MASK\t\tEQU\t000Eh\t; mask used for predator pixel puts\n\n\n;---------------------------------------------------------------------------\n;\n; Use a macro to make code a little cleaner.\n; The parameter varname is optional.\n; Syntax to use macro is :\n;  WANT equ expression\n;  USE func [,varname]\n; If the 'varname' is defined, a table declaration is created like:\n;\tGLOBAL\tTableName:DWORD\n; Then, the table entry is created:\n;  If WANT is true, the table entry is created for the given function:\n;\tvarname\tDD\tfunc\n;  If WANT is not TRUE, a Not_Supported entry is put in the table:\n;\tvarname\tDD\tNot_Supported\n; The resulting tables look like:\n;\n;\tGLOBAL\tExampTable:DWORD\n;\tExampTable\tDD\troutine1\n;\t\t\tDD\troutine2\n;\t\t\tDD\troutine3\n;\t\t\t...\n; Thus, each table is an array of function pointers.\n;\n;---------------------------------------------------------------------------\nMACRO USE func, varname\n IF WANT\n  varname \tDD\tfunc\n ELSE\n  varname\tDD\tNot_Supported\n ENDIF\nENDM\n\n; IFNB <varname>\n;\tGLOBAL\tvarname:DWORD\n; ENDIF\n\n;---------------------------------------------------------------------------\n\n\nDATASEG\n\n;---------------------------------------------------------------------------\n; Predator effect variables\n;---------------------------------------------------------------------------\n; make table for negative offset and use the used space for other variables\n\nBFPredNegTable\tDW\t-1, -3, -2, -5, -2, -4, -3, -1\n\t; 8 words below calculated\n\t\tDW\t0, 0, 0, 0, 0, 0, 0, 0\t; index ffffff00\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff10\nBFPredOffset\tDD\t0, 0, 0, 0\t\t; index ffffff20\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff30\n\t; partially faded predator effect value\nBFPartialPred\tDD\t0, 0, 0, 0\t\t; index ffffff40\nBFPartialCount\tDD\t0, 0, 0, 0\t\t; index ffffff50\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff60\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff70\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff80\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff90\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffa0\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffb0\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffc0\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffd0\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffe0\n\t\tDD\t0, 0, 0, 0\t\t; index fffffff0\nBFPredTable\tDW\t1, 3, 2, 5, 2, 3, 4, 1\n;BFPredTable\tDB\t1, 3, 2, 5, 4, 3, 2, 1\n\n\nCODESEG\n\n;---------------------------------------------------------------------------\n; Code Segment Tables:\n; This code uses the USE macro to set up tables of function addresses.\n; The tables have the following format:\n; Tables defined are:\n;\tBufferFrameTable\n;---------------------------------------------------------------------------\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Copy, BufferFrameTable\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Ghost\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Ghost_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Fading\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Fading_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Ghost_Fading\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Ghost_Fading_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Ghost\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Ghost_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Fading\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Fading_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Ghost_Fading\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Ghost_Fading_Trans\n\n;---------------------------------------------------------------------------\n\nglobal _Int3:near\nproc _Int3 near\n\tint\t3\n\tret\nendp\n\n\n;***************************************************************************\n;* VVC::TOPAGE -- Copies a linear buffer to a virtual viewport\t\t   *\n;*                                                                         *\n;* INPUT:\tWORD\tx_pixel\t\t- x pixel on viewport to copy from *\n;*\t\tWORD\ty_pixel \t- y pixel on viewport to copy from *\n;*\t\tWORD\tpixel_width\t- the width of copy region\t   *\n;*\t\tWORD\tpixel_height\t- the height of copy region\t   *\n;*\t\tBYTE *\tsrc\t\t- buffer to copy from\t\t   *\n;*\t\tVVPC *  dest\t\t- virtual viewport to copy to\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    Coordinates and dimensions will be adjusted if they exceed *\n;*\t        the boundaries.  In the event that no adjustment is \t   *\n;*\t        possible this routine will abort.  If the size of the \t   *\n;*\t\tregion to copy exceeds the size passed in for the buffer   *\n;*\t\tthe routine will automatically abort.\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Buffer_Frame_To_Page:NEAR\n\tPROC\tBuffer_Frame_To_Page C near\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\tARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\tARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\tARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\tARG    \tsrc         :DWORD\t\t; this is a member function\n\tARG\tdest        :DWORD\t\t; what are we blitting to\n\n\tARG\tflags       :DWORD\t\t; flags passed\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL\tIsTranslucent\t\t:DWORD\t; ptr to the is_translucent table\n\tLOCAL\tTranslucent\t\t:DWORD\t; ptr to the actual translucent table\n\tLOCAL\tFadingTable\t\t:DWORD\t; extracted fading table pointer\n\tLOCAL\tFadingNum\t\t:DWORD\t; get the number of times to fade\n\n\tLOCAL\tStashECX\t\t:DWORD\t; temp variable for ECX register\n\n\tLOCAL\tjflags\t\t\t:DWORD\t; flags used to goto correct buff frame routine\n\tLOCAL\tBufferFrameRout\t\t:DWORD\t; ptr to the buffer frame routine\n\n\tLOCAL\tjmp_loc\t\t\t:DWORD\t; calculated jump location\n\tLOCAL\tloop_cnt\t\t:DWORD\n\n\tLOCAL \tx1_pixel\t\t:DWORD\n\tLOCAL\ty1_pixel\t\t:DWORD\n\tLOCAL\tscr_x\t\t\t:DWORD\n\tLOCAL\tscr_y\t\t\t:DWORD\n\tLOCAL\tdest_adjust_width\t:DWORD\n\tLOCAL\tscr_adjust_width\t:DWORD\n\n\n\tcmp\t[ src ] , 0\n\tjz\t??real_out\n\n\t;====================================================================\n\t; Pull off optional arguments:\n\t; EDI is used as an offset from the 'flags' parameter, to point\n\t; to the optional argument currently being processed.\n\t;====================================================================\n??do_args:\n\tmov\tedi , 4\t \t\t\t; optional params start past flags\n\tmov\t[ jflags ] , 0\t\t\t; clear jump flags\n\n??check_centering:\n\t;-------------------------------------------------------------------\n\t; See if we need to center the frame\n\t;-------------------------------------------------------------------\n\ttest\t[ flags ] , SHAPE_CENTER\t; does this need to be centered?\n\tje\t??check_trans\t\t\t; if not the skip over this stuff\n\n\tmov\teax , [ pixel_width ]\n\tmov\tebx , [ pixel_height ]\n\tsar\teax , 1\n\tsar\tebx , 1\n\tsub\t[ x_pixel ] , eax\n\tsub\t[ y_pixel ] , ebx\n\n??check_trans:\n\ttest\t[ flags ] , SHAPE_TRANS\n\tjz\t??check_ghost\n\n\tor\t[ jflags ] , FLAG_TRANS\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_GHOST: DWORD is_translucent tbl\n\t;--------------------------------------------------------------------\n??check_ghost:\n\ttest\t[ flags ] , SHAPE_GHOST\t\t; are we ghosting this shape\n\tjz\t??check_fading\n\n\tmov\teax , [ flags + edi ]\n\tor\t[ jflags ] , FLAG_GHOST\n\tmov\t[ IsTranslucent ] , eax\t\t; save ptr to is_trans. tbl\n\tadd\teax , 0100h\t\t\t; add 256 for first table\n\tadd\tedi , 4\t\t\t\t; next argument\n\tmov\t[ Translucent ] , eax\t\t; save ptr to translucent tbl\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_FADING: DWORD fade_table[256], DWORD fade_count\n\t;--------------------------------------------------------------------\n??check_fading:\n\ttest\t[ flags ] , SHAPE_FADING\t; are we fading this shape\n\tjz\t??check_predator\n\n\tmov\teax , [ flags + edi ]\n\tmov\t[ FadingTable ] , eax\t\t; save address of fading tbl\n\tmov\teax , [ flags + edi + 4 ]\t; get fade num\n\tor\t[ jflags ] , FLAG_FADING\n\tand\teax , 03fh\t\t\t; no need for more than 63\n\tadd\tedi , 8\t\t\t\t; next argument\n\tcmp\teax , 0\t\t\t\t; check if it's 0\n\tjnz\t??set_fading\t\t\t; if not, store fade num\n\n\tand\t[ flags ] , NOT SHAPE_FADING\t; otherwise, don't fade\n\n??set_fading:\n\tmov\t[ FadingNum ] , eax\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_PREDATOR: DWORD init_pred_lookup_offset (0-7)\n\t;--------------------------------------------------------------------\n??check_predator:\n\ttest\t[ flags ] , SHAPE_PREDATOR\t; is predator effect on\n\tjz\t??check_partial\n\n\tmov\teax , [ flags + edi ]\t\t; pull the partial value\n\tor\t[ jflags ] , FLAG_PREDATOR\n\tshl\teax , 1\n\tcmp\teax , 0\n\tjge\t??check_range\n\n\tneg\teax\n\tmov\tebx , -1\n\tand\teax , PRED_MASK\t\t\t; keep entries within bounds\n\tmov\tbl , al\n\tmov\teax , ebx\t\t\t; will be ffffff00-ffffff07\n\tjmp\t??pred_cont\n\n??check_range:\n\tand\teax , PRED_MASK\t\t\t; keep entries within bounds\n\n??pred_cont:\n\tadd\tedi , 4\t\t\t\t; next argument\n\tmov\t[ BFPredOffset ] , eax\n\tmov\t[ BFPartialCount ] , 0\t\t; clear the partial count\n\tmov\t[ BFPartialPred ] , 100h\t; init partial to off\n\n??pred_neg_init:\n\tmov  \tesi , [ dest ]\t    ; get ptr to dest\n\tmov\tebx, 7 * 2\n\n??pred_loop:\n\tmovzx\teax , [ WORD PTR BFPredNegTable + ebx ]\n\tadd\teax , [ (GraphicViewPort esi) . GVPWidth ]\t; add width\n\tadd\teax , [ (GraphicViewPort esi) . GVPXAdd ]\t; add x add\n\tmov\t[ WORD PTR BFPredNegTable + 16 + ebx ] , ax\n\tdec\tebx\n\tdec\tebx\n\tjge\t??pred_loop\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_PARTIAL: DWORD partial_pred_value (0-255)\n\t;--------------------------------------------------------------------\n??check_partial:\n\ttest\t[ flags ] , SHAPE_PARTIAL\t\t; is this a partial pred?\n\tjz\t??setupfunc\n\n\tmov\teax , [ flags + edi ]\t\t; pull the partial value\n\tadd\tedi , 4\t\t\t\t; next argument\n\tand\teax , 0ffh\t\t\t; make sure 0-255\n\tmov\t[ BFPartialPred ] , eax\t\t; store it off\n\n??setupfunc:\n\tmov\tebx , [ jflags ]\t\t; load flags value\n\tand\tebx , FLAG_MASK\t\t\t; clip high bits\n\tadd\tebx , ebx\t\t\t; mult by 4 to get DWORD offset\n\tadd\tebx , ebx\n\tmov\tebx , [ BufferFrameTable + ebx ]\t; get table value\n\tmov\t[ BufferFrameRout ] , ebx\t\t; store it in the function pointer\n\n; Clip dest Rectangle against source Window boundaries.\n\n\tmov\t[ scr_x ] , 0\n\tmov\t[ scr_y ] , 0\n\tmov  \tesi , [ dest ]\t    ; get ptr to dest\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\n\tor\tal , dl\n\tjz\t??do_blit\n\n\ttest\tcl , 1000b\n\tjz\t??dest_left_ok\n\n\tmov\teax , [ x_pixel ]\n\tneg\teax\n\tmov\t[ x_pixel ] , 0\n\tmov\t[ scr_x ] , eax\n\n??dest_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dest_bottom_ok\n\n\tmov\teax , [ y_pixel ]\n\tneg\teax\n\tmov\t[ y_pixel ] , 0\n\tmov\t[ scr_y ] , eax\n\n??dest_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??dest_right_ok\n\n\tmov\teax , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n\n??dest_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\n\tmov\teax , [ (GraphicViewPort esi) . GVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n??do_blit:\n\tcld\n\tmov\teax , [ (GraphicViewPort esi) . GVPXAdd ]\n\tadd\teax , [ (GraphicViewPort esi) . GVPWidth ]\n\tmov\tedi , [ (GraphicViewPort esi) . GVPOffset ]\n\n\tmov\tecx , eax\n\tmul\t[ y_pixel ]\n\tadd\tedi , [ x_pixel ]\n\tadd\tedi , eax\n\n\tadd\tecx , [ x_pixel ]\n\tsub\tecx , [ x1_pixel ]\n\tmov\t[ dest_adjust_width ] , ecx\n\n\tmov\tesi , [ src ]\n\tmov\teax , [ pixel_width ]\n\tsub\teax , [ x1_pixel ]\n\tadd\teax , [ x_pixel ]\n\tmov\t[ scr_adjust_width ] , eax\n\n\tmov\teax , [ scr_y ]\n\tmul\t[ pixel_width ]\n\tadd\teax , [ scr_x ]\n\tadd\tesi , eax\n\n\tmov\tedx , [ y1_pixel ]\n\tmov\teax , [ x1_pixel ]\n\n\tsub\tedx , [ y_pixel ]\n\tjle\t??real_out\n\n\tsub\teax , [ x_pixel ]\n\tjle\t??real_out\n\n\tjmp\t[ BufferFrameRout ]\t; buffer frame to viewport routine\n\n??real_out:\n\tret\n\n\n; ********************************************************************\n; Forward bitblit only\n; the inner loop is so efficient that\n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n; ********************************************************************\n\nBF_Copy:\n\n\tcmp\teax , 10\n\tjl\t??forward_loop_bytes\n\n??forward_loop_dword:\n\tmov\tecx , edi\n\tmov\tebx , eax\n\tneg\tecx\n\tand\tecx , 3\n\tsub\tebx , ecx\n\trep\tmovsb\n\tmov\tecx , ebx\n\tshr\tecx , 2\n\trep\tmovsd\n\tmov\tecx , ebx\n\tand\tecx , 3\n\trep\tmovsb\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??forward_loop_dword\n\n\tret\n\n??forward_loop_bytes:\n\tmov\tecx , eax\n\trep\tmovsb\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\t\t\t\t\t; decrement the height\n\tjnz\t??forward_loop_bytes\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Trans:\n\n; calc the code location to skip to 10 bytes per REPT below!!!!\n\tmov\tecx , eax\n\tand\tecx , 01fh\n\tlea\tecx , [ ecx + ecx * 4 ]\t\t; quick multiply by 5\n\tneg\tecx\n\tshr\teax , 5\n\tlea\tecx , [ ??trans_reference + ecx * 2 ] ; next multiply by 2\n\tmov\t[ loop_cnt ] , eax\n\tmov\t[ jmp_loc ] , ecx\n\n??trans_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n; the following code should NOT be changed without changing the calculation\n; above!!!!!!\n\n??trans_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\t\tmov\tbl , [ esi ]\n\t\tinc\tesi\n\t\ttest\tbl , bl\n\t\tjz\ttrans_pixel\n\n\t\tmov\t[ edi ] , bl\n\n\ttrans_pixel:\n\t\tinc\tedi\n\tENDM\n\n??trans_reference:\n\tdec\tecx\n\tjge\t??trans_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??trans_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Ghost:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??ghost_reference - ??ghost_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??ghost_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??ghost_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??ghost_line:\n\n\tREPT\t32\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tstore_pixel\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??ghost_reference:\n\tdec\tecx\n\tjge\t??ghost_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??ghost_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Ghost_Trans:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??ghost_t_reference - ??ghost_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??ghost_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??ghost_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??ghost_t_line:\n\n\tREPT\t32\n\tlocal\ttransp_pixel\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttransp_pixel\n\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tstore_pixel\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttransp_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??ghost_t_reference:\n\tdec\tecx\n\tjge\t??ghost_t_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??ghost_t_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Fading:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??fading_reference - ??fading_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??fading_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??fading_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\tjmp\t[ jmp_loc ]\n\n??fading_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??fading_line:\n\n\tREPT\t32\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??fading_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??fading_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??fading_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Fading_Trans:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??fading_t_reference - ??fading_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??fading_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??fading_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\tjmp\t[ jmp_loc ]\n\n??fading_t_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??fading_t_line:\n\n\tREPT\t32\n\tlocal\ttransp_pixel\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttransp_pixel\n\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\t\tmov\t[ edi ] , al\n\n\ttransp_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??fading_t_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??fading_t_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??fading_t_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Ghost_Fading:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??ghost_f_reference - ??ghost_f_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??ghost_f_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??ghost_f_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??ghost_f_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??ghost_f_line:\n\n\tREPT\t32\n\tlocal\tstore_pixel\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a lucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tdo_fading\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the lation table\n\t\t\t\t\t\t\t; ((_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (_color * 256) of the lation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n; DRD\t\tjmp\tstore_pixel\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??ghost_f_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??ghost_f_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??ghost_f_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Ghost_Fading_Trans:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??ghost_f_t_reference - ??ghost_f_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??ghost_f_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??ghost_f_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??ghost_f_t_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??ghost_f_t_line:\n\n\tREPT\t32\n\tlocal\ttransp_pixel\n\tlocal\tstore_pixel\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttransp_pixel\n\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tdo_fading\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n; DRD\t\tjmp\tstore_pixel\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttransp_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??ghost_f_t_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??ghost_f_t_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??ghost_f_t_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Predator:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_reference - ??predator_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??predator_line:\n\n\tREPT\t32\n\tlocal\tget_pred\n\tlocal\tskip_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tskip_pixel\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n;\t\txor\tbh , bh\n;\t\tmov\teax , [ BFPredValue ]\t; pick up a color offset a pseudo-\n;\t\t\t\t\t\t;  random amount from the current\n;\t\tmov\t[ BFPartialCount ] , ebx\n;\t\tmov\tal , [ edi + eax ]\t;  viewport address\n\n\t\tmov\t[ edi ] , al\n\n\tskip_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??predator_reference:\n\tdec\tecx\n\tjge\t??predator_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Predator_Trans:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_t_reference - ??predator_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??predator_t_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\tlocal\tget_pred\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttrans_pixel\n\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tstore_pixel\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttrans_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??predator_t_reference:\n\tdec\tecx\n\tjge\t??predator_t_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_t_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Predator_Ghost:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_g_reference - ??predator_g_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_g_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_g_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??predator_g_line:\n\n\tREPT\t32\n\tlocal\tget_pred\n\tlocal\tcheck_ghost\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tinc\tesi\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tcheck_ghost\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tcheck_ghost:\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tstore_pixel\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??predator_g_reference:\n\tdec\tecx\n\tjge\t??predator_g_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_g_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Predator_Ghost_Trans:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_g_t_reference - ??predator_g_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_g_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_g_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n??predator_g_t_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\tlocal\tget_pred\n\tlocal\tcheck_ghost\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttrans_pixel\n\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tcheck_ghost\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tcheck_ghost:\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tstore_pixel\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttrans_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??predator_g_t_reference:\n\tdec\tecx\n\tjge\t??predator_g_t_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_g_t_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Predator_Fading:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_f_reference - ??predator_f_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_f_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_f_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??predator_f_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??predator_f_line:\n\n\tREPT\t32\n\tlocal\tget_pred\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tinc\tesi\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tdo_fading\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??predator_f_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??predator_f_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_f_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Predator_Fading_Trans:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_f_t_reference - ??predator_f_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_f_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_f_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??predator_f_t_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??predator_f_t_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\tlocal\tget_pred\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttrans_pixel\n\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tdo_fading\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\t\tmov\t[ edi ] , al\n\n\ttrans_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??predator_f_t_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??predator_f_t_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_f_t_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Predator_Ghost_Fading:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_g_f_reference - ??predator_g_f_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_g_f_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_g_f_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??predator_g_f_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??predator_g_f_line:\n\n\tREPT\t32\n\tlocal\tget_pred\n\tlocal\tcheck_ghost\n\tlocal\tstore_pixel\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tinc\tesi\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tcheck_ghost\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tcheck_ghost:\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tdo_fading\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n; DRD\t\tjmp\tstore_pixel\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\n??predator_g_f_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??predator_g_f_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_g_f_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nBF_Predator_Ghost_Fading_Trans:\n\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ ??predator_g_f_t_reference - ??predator_g_f_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ??predator_g_f_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\n??predator_g_f_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\n??predator_g_f_t_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\n??predator_g_f_t_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\tlocal\tget_pred\n\tlocal\tcheck_ghost\n\tlocal\tstore_pixel\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttrans_pixel\n\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tcheck_ghost\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\t[ BYTE PTR BFPredOffset ] , 2\n\t\tmovzx\teax , [ WORD PTR BFPredTable + eax ]\n\t\tand\t[ BYTE PTR BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , [ BYTE PTR edi + eax ]\t;  viewport address\n\n\tcheck_ghost:\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , [ BYTE PTR ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tdo_fading\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , [ BYTE PTR ebx + eax ]\t; get new pixel in al\n; DRD\t\tjmp\tstore_pixel\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, [BYTE PTR ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttrans_pixel:\n\t\tinc\tedi\n\n\tENDM\n\n??predator_g_f_t_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\t??predator_g_f_t_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\t??predator_g_f_t_loop\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nNot_Supported:\n\tret\n\n\tENDP\tBuffer_Frame_To_Page\nEND\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : KEYFBUFF.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 16, 1992                            *\n;*                                                                         *\n;*                  Last Update : October 2, 1994   [JLB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   BUFFER_FRAME_TO_LOGICPAGE --                                          *\n;*   Normal_Draw -- Function that writes a normal pixel line               *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\tIDEAL\n\tP386\nIDEAL_MODE\tEQU\t1\n\tINCLUDE \"wwlib.i\"\n\n\t;-------------------------------------------------------------------\n\t; Extern all the library variables that this module requires\n\t;-------------------------------------------------------------------\n\n\tEXTRN\tC MaskPage:WORD\n\tEXTRN\tC BackGroundPage:WORD\n\n\t;-------------------------------------------------------------------\n\t; Define all the equates that this module requires\n\t;-------------------------------------------------------------------\n\nWIN_X\t\tEQU\t0\t\t; offset for the x coordinate\nWIN_Y\t\tEQU\t2\t\t; offset for the y coordinate\nWIN_WIDTH\tEQU\t4\t\t; offset for the window width\nWIN_HEIGHT\tEQU\t6\t\t; offset for the window height\nBYTESPERROW\tEQU\t320\t\t; number of bytes per row\n\nFLAG_NORMAL\t\tEQU\t0\t\t; flag for normal draw\n\nFLAG_GHOST\t\tEQU\t1\t\t; This flag enables the ghost\nFLAG_PRIORITY_TRANS\tEQU\t2\t\t; flag for priority and transparent\nFLAG_TRANS\t\tEQU\t4\t\t; flag for transparent draw\nFLAG_PRIORITY\t\tEQU\t8\t\t; flag for priority draw\n\n\t\t\t\t\t\t; fx on the above flags\n\nFLAG_MASK\t\tEQU\t15\t\t; used to and of uneeded bits\n\nSHAPE_NORMAL\t\tEQU\t0000h\t\t; Standard shape.\n;SHAPE_HORZ_REV\t\tEQU\t0001h\t\t; Flipped horizontally.\n;SHAPE_VERT_REV\t\tEQU\t0002h\t\t; Flipped vertically.\n;SHAPE_SCALING\t\tEQU\t0004h\t\t; Scaled (WORD scale_x, WORD scale_y)\n\nSHAPE_WIN_REL\t\tEQU\t0010h\t\t; Coordinates are window relative instead of absolute.\nSHAPE_CENTER\t\tEQU\t0020h\t\t; Coordinates are based on shape's center point.\nSHAPE_TRANS\t\tEQU\t0040h\t\t; has transparency\n\n\n;SHAPE_FADING\t\tEQU\t0100h\t\t; Fading effect active (VOID * fading_table, WORD fading_num).\n;SHAPE_PREDATOR\t\tEQU\t0200h\t\t; Transparent warping effect.\n;SHAPE_COMPACT\t\tEQU\t0400h\t\t; Never use this bit.\nSHAPE_PRIORITY\t\tEQU\t0800h\t\t; Use priority system when drawing.\n\nSHAPE_GHOST\t\tEQU\t1000h\t\t; Transluscent table process.\n;SHAPE_SHADOW\t\tEQU\t2000h\t\t; ????\n;SHAPE_PARTIAL \t\tEQU\t4000h\t\t; ????\n;SHAPE_COLOR\t\tEQU\t8000h\t\t; Remap the shape's colors (VOID * color_table).\n\n\n; MBL MOD 12.1.92\n\nCLEAR_NON_WALK_BIT_AND_SCALE_BITS\tEQU\t7\t; Makes it one AND per pixel in Priority_Trans display\nCLEAR_NON_WALK_BIT    \tEQU\t7fh\t; and with 0111-1111 to clear non-walkable high bit\nCLEAR_SCALE_BITS  \tEQU\t87h\t; and with 1000-0111 to clear scaling id bits\nNON_WALKABLE_BIT  \tEQU\t80h\t; and with 1000-0000 to clear all but non-walkable bit\n\n; END MBL MOD\n\n\n\tCODESEG\n\n\t;   1 = GHOST (all odd entrys are prefixed with Ghost_)\n\t;   2 = BLAAAH\n\t;   4 = Trans (prfx)\n\t;   8 = Prior (prfx)\n\n\n;---------------------------------------------------------------------------\n; Define the table of different line draw types\n;---------------------------------------------------------------------------\n\nLineTable\tDW\tWSA_Normal_Draw\t\t\t;0\n\t\tDW\tGhost_Normal_Draw\t\t;1\n\t\tDW\t0\t\t\t\t;2\n\t\tDW\t0\t\t\t\t;3\n\n\t\tDW\tTransparent_Draw\t\t;4\n\t\tDW\tGhost_Transparent_Draw\t\t;5\n\t\tDW\t0\t\t\t\t;6\n\t\tDW\t0\t\t\t\t;7\n\n\t\tDW\tPriority_Draw\t\t\t;8\n\t\tDW\tGhost_Priority_Draw\t\t;9\n\t\tDW\t0\t\t\t\t;10\n\t\tDW\t0\t\t\t\t;11\n\n\t\tDW\tPriority_Transparent_Draw\t;12\n\t\tDW\tGhost_Priority_Transparent_Draw\t;13\n\t\tDW\t0\t\t\t\t;14\n\t\tDW\t0\t\t\t\t;15\n\n\n\n;***************************************************************************\n;* BUFFER_FRAME_TO_LOGICPAGE --                                            *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/16/1992 PWG : Created.                                             *\n;*=========================================================================*\n\tPUBLIC\tC Buffer_Frame_To_LogicPage\n\tPROC\tC Buffer_Frame_To_LogicPage FAR USES ax bx ecx dx ds esi es edi\n\n\t;-------------------------------------------------------------------\n\t; Define the arguements that our program takes.\n\t;-------------------------------------------------------------------\n\n\tARG\tx_pixel:WORD\t\t; x pixel position to draw at\n\tARG\ty_pixel:WORD\t\t; y pixel position to draw at\n\tARG\tpixel_w:WORD\t\t; pixel width of draw region\n\tARG\tpixel_h:WORD\t\t; pixel height of draw region\n\tARG\twin:WORD\t\t; window to clip around\n\tARG\tflags:WORD\t\t; flags that this routine will take\n\tARG\tbuffer:DWORD\t\t; pointer to the buffer with data\n\tARG\targs:WORD\n\n\t;-------------------------------------------------------------------\n\t; Define the local variables that our program uses\n\t;-------------------------------------------------------------------\n\n\tLOCAL\tIsTranslucent:DWORD\t; ptr to the is_translucent table\n\tLOCAL\tTranslucent:DWORD\t; ptr to the actual translucent table\n\n\tLOCAL\twin_x1:WORD\t\t; clip window left x pixel position\n\tLOCAL\twin_x2:WORD\t\t; clip window right x pixel position\n\tLOCAL\twin_y1:WORD\t\t; clip window top y pixel position\n\tLOCAL\twin_y2:WORD\t\t; clip window bottom y pixel position\n\tLOCAL\tclipleft:WORD\t\t; number of pixels to clip on left\n\tLOCAL\tclipright:WORD\t\t; number of pixels to clip on right\n\tLOCAL\tnextline:WORD\t\t; offset to the next line\n\tLOCAL\tputmiddle:WORD \t\t; routine to call to put the middle\n\tLOCAL\tmaskpage:WORD\t\t; location of the depth masks\n\tLOCAL   background:WORD\t\t; location of the background data\n\tLOCAL   jflags:WORD\t\t; location of the background data\n\n\tLOCAL\tpriority:BYTE\t\t; the priority level of the back\n\n\tpush\tfs\n\n\txor\tecx,ecx\n\n\t;--------------------------------------------------------------------\n\t; Check to see if we have supplied any GHOST tables.\n\t;--------------------------------------------------------------------\n\tpush\tdi\n\n\tmov\tdi,6\n\tmov\t[jflags],0\n\n??ghost:\n\ttest\t[flags],SHAPE_GHOST\t; are we ghosting this shape\n\tjz\tshort ??no_ghost\t; if not then skip and do more\n\n\tor\t[jflags],FLAG_GHOST\n\n\tles\tax,[DWORD PTR buffer + di]\n\n\t; get the \"are we really translucent?\" table\n\tmov\t[WORD PTR IsTranslucent],ax\n\tmov\t[WORD PTR IsTranslucent + 2],es\n\tadd\tax,0100h\t\t; add to offset for tables\n\n\t; get the \"ok we are translucent!!\" table\n\tmov\t[WORD PTR Translucent],ax\n\tmov\t[WORD PTR Translucent + 2],es\n\n\tadd\tdi,4\n\n??no_ghost:\n\n\tpop\tdi\n\n\t;-------------------------------------------------------------------\n\t; See if we need to center the frame\n\t;-------------------------------------------------------------------\n\ttest\t[flags],SHAPE_CENTER\t; does this need to be centered?\n\tje\tshort ??no_centering\t; if not the skip over this stuff\n\n\tmov\tax,[pixel_w]\n\tmov\tbx,[pixel_h]\n\tsar\tax,1\n\tsar\tbx,1\n\tsub\t[x_pixel],ax\n\tsub\t[y_pixel],bx\n\n??no_centering:\n\tmov\tax,[flags]\n\tand\tax,SHAPE_PRIORITY+SHAPE_TRANS\n\tcmp\tax,SHAPE_PRIORITY+SHAPE_TRANS\n\tjne\tshort ??test_trans\n\n\tor\t[jflags],FLAG_PRIORITY_TRANS\n\tjmp\tshort ??priority\n\n\t;-------------------------------------------------------------------\n\t; Get the trans information if we need to get it\n\t;-------------------------------------------------------------------\n??test_trans:\n\ttest\t[flags],SHAPE_TRANS\t; does this draw use transparencies?\n\tje\tshort ??test_priority\t; if not the skip over this junk\n\n\tor\t[jflags],FLAG_TRANS\n\n??test_priority:\n\t;-------------------------------------------------------------------\n\t; Get the priority information if we need to get it\n\t;-------------------------------------------------------------------\n\ttest\t[flags],SHAPE_PRIORITY\t; does this draw use priorities?\n\tje\tshort ??no_priority\t; if not the skip over this junk\n\n\tor\t[jflags],FLAG_PRIORITY\n\n??priority:\n\tmov\tax,[BackGroundPage]\t; get the background page from ds\n\tmov\t[background],ax\t\t;    and store it on the stack\n\tmov\tax,[MaskPage]\t\t; get the mask page from ds\n\tmov\t[maskpage],ax\t\t;    and store it on the stack\n\tmov\tax,[WORD PTR buffer + 4]; get the priority level from args\n\tmov\t[priority],al\t\t;    and store it in a local\n\n\t;-------------------------------------------------------------------\n\t; Get the draw routine that we are going to draw with\n\t;-------------------------------------------------------------------\n??no_priority:\n;\tmov\tbx,[flags]\t\t; load in the current flags byte\n;\tand\tbx,FLAG_MASK\t\t; prevent lockup on bad value\n\tmov\tbx,[jflags]\t\t; load in the jump table flags\n\tshl\tbx,1\n\tmov\tax,[WORD PTR LineTable + bx]\t; get the offset of the skip table\n\tmov\t[putmiddle],ax\t\t; store off the new offset\n\n\t;-------------------------------------------------------------------\n\t; Get a pointer to the logic page to where we will draw our buffer\n\t;-------------------------------------------------------------------\n\tpush\t[LogicPage]\t\t; push the current logic page\n\tcall\tFAR PTR Get_Page\t; get the physical page address\n\tadd\tsp,2\t\t\t; pull the parameter from the stack\n\tmov\tes,dx\t\t\t; store the address in the dest\n\n\t;--------------------------------------------------------------------\n\t; Point DI to the beginning of the window that we need to look at.\n\t;   that way we can access all of the info through di.\n\t;--------------------------------------------------------------------\n\tmov\tsi,OFFSET WindowList\t; get the offset of the window list\n\tmov\tcl,4\t\t\t; shift 3 times = multiply by 16\n\tmov\tax,[win]\t\t; get the window number we are using\n\tshl\tax,cl\t\t\t; each window is 8 words long\n\tadd\tsi,ax\t\t\t; add that into the offset of window\n\n\t;--------------------------------------------------------------------\n\t; Place all the clipping values on the stack so our function will\n\t; be truly re-entrant and will not need to shadow these values.\n\t;--------------------------------------------------------------------\n\tmov\tcl,3\t\t\t; to convert x to pixel mult by 8\n\tmov\tax,[si + WIN_X]\t\t; get the left clip position\n\tshl\tax,cl\t\t\t; convert to a pixel x position\n\tmov\t[win_x1],ax\t\t; store the left edge of window\n\tmov\t[win_x2],ax\n\n\tmov\tax,[si + WIN_WIDTH]\t; get the width of the window\n\tshl\tax,cl\t\t\t; convert to a pixel width\n\tadd\t[win_x2],ax\t\t; add to get the right window edge\n\n\tmov\tax,[si + WIN_Y]\t\t; get the win y coordinate to clip\n\tmov\t[win_y1],ax\t\t; and save it onto the stack\n\n\tadd\tax,[si + WIN_HEIGHT]\t; calculate the bottom win y coord\n\tmov\t[win_y2],ax\t\t; and save it onto the stack\n\n\ttest\t[flags],SHAPE_WIN_REL\t; is this window relative?\n\tje\tshort ??get_buffer\t; if not the skip over\n\n\tmov\tax,[win_x1]\t\t; get left edge of window\n\tadd\t[x_pixel],ax\t\t; add to x pixel position\n\tmov\tax,[win_y1]\t\t; get top edge of window\n\tadd\t[y_pixel],ax\t\t; add to y pixel position\n\n\t;--------------------------------------------------------------------\n\t; Get a pointer to the source buffer so we can handle the clipping\n\t;--------------------------------------------------------------------\n??get_buffer:\n\tlds\tsi,[buffer]\t\t; get a pointer to the buffer\n\n\t;--------------------------------------------------------------------\n\t; Check the top of our shape and clip any lines that are necessary\n\t;--------------------------------------------------------------------\n\tmov\tax,[y_pixel]\t\t; get the y_pixel draw position\n\tsub\tax,[win_y1]\t\t; subtract out the window y top\n\tjns\tshort ??check_bottom\t\t;   skip if y below window top\n\tadd\tax,[pixel_h]\t\t; add in the height of the region\n\tjg\tshort ??clip_top\t\t; if positive then clip top lines\n\n??jump_exit:\n\tjmp\t??exit\t\t\t; otherwise completely clipped\n\n??clip_top:\n\txchg\t[pixel_h],ax\n\tsub\tax,[pixel_h]\n\tadd\t[y_pixel],ax\n\tmul\t[pixel_w]\t\t; convert to number of bytes to skip\n\tadd\tsi,ax\t\t\t; skip past the necessary bytes\n\n\t;--------------------------------------------------------------------\n\t; Check the bottom of our shape and clip it if necessary\n\t;--------------------------------------------------------------------\n??check_bottom:\n\tmov\tax,[win_y2]\t\t; get the bottom y of the window\n\tsub\tax,[y_pixel]\t\t; subtract of the y to draw at\n\tjs\t??jump_exit\t\t; if its signed then nothing to draw\n\tjz\t??jump_exit\t\t; if its zero then nothing to draw\n\n\tcmp\tax,[pixel_h]\t\t; if more room to draw then height\n\tjae\tshort ??clip_x_left\t\t;   then go check the left clip\n\tmov\t[pixel_h],ax\t\t; clip all but amount that will fit\n\n??clip_x_left:\n\tmov\t[clipleft],0\t\t; clear clip on left of region\n\tmov\tax,[x_pixel]\t\t; get the pixel x of draw region\n\tsub\tax,[win_x1]\t\t; pull out the window coordinate\n\tjns\tshort ??clip_x_right\n\tneg\tax\t\t\t; negate to get amnt to skip in buf\n\tmov\t[clipleft],ax\t\t; store it in the left clip info\n\tadd\t[x_pixel],ax\t\t; move to the edge of the window\n\tsub\t[pixel_w],ax\t\t; pull it out of the pixel width\n\n??clip_x_right:\n\tmov\t[clipright],0\t\t; clear clip on right of region\n\tmov\tax,[win_x2]\t\t; get the window x of clip region\n\tsub\tax,[x_pixel]\t\t; subtract the draw edge of region\n\tjs\t??jump_exit\t\t; if its negative then get out\n\tjz\t??jump_exit\t\t; if its zero then get out\n\n\tcmp\tax,[pixel_w]\t\t; is space available larger than w\n\tjae\tshort ??draw_prep\t\t;   if so then go get drawing\n\n\n\txchg\t[pixel_w],ax\t\t; amt to draw in pixel_w (wid in ax)\n\tsub\tax,[pixel_w]\t\t; pull out the amount to draw\n\tmov\t[clipright],ax\t\t; this is the amount to clip on right\n\n??draw_prep:\n\tpush\tsi\t\t\t; save off source pos in buffer\n\tpush\tds\t\t\t;   both offset and segment\n\tmov\tax,@data\n\tmov\tds,ax\n\tmov\tbx,[y_pixel]\n\tshl\tbx,1\t\t\t; shift left by 1 for word table look\n\tlds\tsi,[YTable]\t; get the address of the ytable\n\tmov\tdi,[ds:si+bx]\t\t; look up the multiplied value\n\tpop\tds\t\t\t; restore source pos in buffer\n\tpop\tsi\t\t\t;   both offset and segment\n\n\tadd\tdi,[x_pixel]\t\t; add in the x pixel position\n\tmov\t[nextline],di\t\t; save it off in the next line\n\n \t;--------------------------------------------------------------------\n\t; Now determine the type of the shape and process it in the proper\n\t;   way.\n\t;--------------------------------------------------------------------\n\tmov\tdx,[pixel_h]\n\n\t; Check to see if the WSA is the screen width and there is no\n\t; clipping. In this case, then a special single call to the\n\t; line processing routine is possible.\n\tmov\tax,[clipleft]\n\tadd\tax,[clipright]\n\tjne\tshort ??top_of_loop\n\tcmp\t[pixel_w],BYTESPERROW\n\tjne\tshort ??top_of_loop\n\n\t;------------------------------------\n\t; The width of the WSA is the screen width, so just process as\n\t; one large WSA line.\n\tmov\tax,BYTESPERROW\n\timul\tdx\n\tmov\tcx,ax\n\tcall\t[putmiddle]\n\tjmp\tshort ??exit\n\n\t;------------------------------------\n\t; Process line by line.\n??top_of_loop:\n\tadd\tsi,[clipleft]\t\t; skip whats necessary on left edge\n\tmov\tcx,[pixel_w]\t\t; get the width we need to draw\n\n\t; Copy the source to the destination as appropriate. This routine can\n\t; trash AX, BX, CX, and DI. It must properly modify SI to point one byte past\n\t; the end of the data.\n\tcall\t[putmiddle]\n\n\tadd\tsi,[clipright]\t\t; skip past the left clip\n\tadd\t[nextline],BYTESPERROW\n\tmov\tdi,[nextline]\n\n\tdec\tdx\n\tjnz\t??top_of_loop\n\n??exit:\n\tpop\tfs\n\tret\n\tENDP\n\n\n;***************************************************************************\n;* NORMAL_DRAW -- Function that writes a normal pixel line                 *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tNOLANGUAGE WSA_Normal_Draw NEAR\n\n IF 1\n \t; This version is marginally faster than the later version.\n \tmov\tax,cx\n\tshr\tcx,2\n\trep movsd\n\tand\tax,011b\n\tmov\tcx,ax\n\tshr\tcx,1\n\trep movsw\n\tadc\tcx,cx\n\trep movsb\n\tret\n\n ELSE\n\n\tshr\tcx,1\t\t\t; convert to words (odd pix in carry)\n\trep\tmovsw\t\t\t; write out the needed words\n\tadc\tcx,0\t\t\t; add the carry into cx\n\trep\tmovsb\t\t\t; write out the odd byte if any\n\tret\n ENDIF\n\n\tENDP\n\n\n;***************************************************************************\n;* TRANSPARENT_DRAW -- Function that writes a transparent pixel line       *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   10/02/1994 JLB : Optimized for 250% speed improvement.                *\n;*=========================================================================*\n\tPROC\tNOLANGUAGE Transparent_Draw NEAR\n\n IF 1\n\t; Preserve DX since it is used as a scratch register.\n\tpush\tdx\n\n??loop:\n\t; Swap DS:SI and ES:DI back in preparation for the REP SCASB\n\t; instruction.\n\txchg\tdi,si\n\tmov\tdx,es\n\tmov\tax,ds\n\tmov\tds,dx\n\tmov\tes,ax\n\n\t; Remember the bytes remaining in order to calculate the position\n\t; of the scan when it stops.\n\tmov\tbx,cx\n\n\t; Scan looking for a non-zero value in the source buffer.\n\txor\tal,al\n\trepe scasb\n\n\t; When the loop ends, if the EQ flag is set then the scanning is\n\t; complete. Jump to the end of the routine in order to fixup the\n\t; pointers.\n\tje\tshort ??fini\n\n\t; Advance the destination pointer by the amount necessary to match\n\t; the source movement. DS:SI points to where data should be written.\n\tadd\tsi,bx\n\tinc\tcx\t\t; SCASB leaves CX one too low, fix it.\n\tdec\tdi\t\t; SCASB leaves DI one byte too far, fix it.\n\tsub\tsi,cx\n\n\t; Scan for the duration of non-zero pixels. This yields a count which\n\t; is used to copy the source data to the destination. Preserve DI.\n\tmov\tdx,di\n\tmov\tbx,cx\n\trepne scasb\n\tmov\tdi,dx\n\n\t; Set BX to equal the number of bytes to copy from source to dest.\n\tinc\tcx\t\t; SCASB leaves CX one too low, fix it.\n\tsub\tbx,cx\n\n\t; Move the data from ES:DI to DS:SI for BX bytes.\n\txchg\tcx,bx\t\t; Make CX=bytes to move, BX=bytes remaining.\n\n\t; Swap DS:SI and ES:DI in preparation for the REP MOV instruction.\n\txchg\tdi,si\n\tmov\tdx,es\n\tmov\tax,ds\n\tmov\tds,dx\n\tmov\tes,ax\n\n\t; Move the data from source to dest. First try to move double\n\t; words. Then copy the remainder bytes (if any). Putting jumps in\n\t; this section doesn't result in any savings -- oh well.\n\tmov\tax,cx\n\tshr\tcx,2\n\trep movsd\n\tand\tax,0011b\n\tmov\tcx,ax\n\tshr\tcx,1\n\trep movsw\n\tadc\tcx,cx\n\trep movsb\n\n\t; Restore CX with the remaining bytes to process.\n\tmov\tcx,bx\n\n\t; If there are more bytes to process, then loop back.\n\tor\tcx,cx\n\tjne\tshort ??loop\n\n??fini:\n\t; Swap ES:DI and DS:SI back to original orientation.\n\tmov\tax,ds\n\tmov\tbx,es\n\tmov\tes,ax\n\tmov\tds,bx\n\txchg\tdi,si\n\n\t; Restore DX and return.\n\tpop\tdx\n\tret\n\n ELSE\n\n??loop_top:\n\tlodsb\n\tor\tal,al\n\tjz\tshort ??skip\n\n\tmov\t[es:di],al\t\t; store the pixel to the screen\n??skip:\n\tinc\tdi\n\tloop\t??loop_top\n\tret\n\n ENDIF\n\n\tENDP\n\n\n;***************************************************************************\n;* PRIORITY_DRAW -- Function that writes a pixels if they are in front of  *\n;*\t\t    the given plate.\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   12/01/1992 MBL : Updated to work with latest mask data encoding.      *\n;*   17/01/1993 MCC : Updated for 386, and optimized\t\t\t   *\n;*=========================================================================*\n\n\tPROC\tNOLANGUAGE Priority_Draw NEAR\n\n\tmov\tfs,[background]\t\t; get the SEG of the background page\n\tmov\tgs,[maskpage]\t\t; get the SEG of the mask info\n\tmov\tah,[priority]\t\t; keep a copy of priority varible for faster cmp\n\n\n??loop_top:\n\tlodsb\t\t\t\t; get the pixel to draw on the screen\n\n\t\t\t\t\t; get the mask byte for our pixel\n\tmov\tbl,[ds:di]\n\t\t\t\t\t; get rid of non-walkable bit and\n\t\t\t\t\t; get rid of scaling id bits\n\tand\tbl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS\n\n\tcmp\tah,bl\t\t\t; are we more toward the front?\n\tjge\tshort ??out_pixel\t; if so then write the pixel\n\n\tmov\tal,[fs:di]\t\t; get the pixel to write\n??out_pixel:\n\tstosb\t\t\t\t; write the pixel and inc the DI\n\tloop\t??loop_top\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* PRIORITY_TRANSPARENT_DRAW -- Function that writes a pixels if they are  *\n;*\t\t    in front of the given plate.  It also deals with\t   *\n;*\t\t    transparent pixels.\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   12/01/1992 MBL : Updated to work with latest mask data encoding.      *\n;*   17/01/1993 MCC : Updated for 386, and optimized\t\t\t   *\n;*=========================================================================*\n\n\tPROC\tNOLANGUAGE Priority_Transparent_Draw NEAR\n\n\tmov\tfs,[background]\t\t; get the SEG of the background page\n\tmov\tgs,[maskpage]\t\t; get the SEG of the mask info\n\tmov\tah,[priority]\t\t; keep a copy of priority varible for faster cmp\n\n??loop_top:\n\tlodsb\t\t\t\t; get the pixel on the screen\n\tor\tal,al\t\t\t; check to see if al is transparent\n\tje\tshort ??write_back\t; if it is go write background\n\n\tmov\tbl,[gs:di]\t\t; get the mask byte for our pixel\n\n\t\t\t\t\t; get rid of non-walkable bit and\n\t\t\t\t\t; get rid of scaling id bits\n\tand\tbl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS\n\n\tcmp\tah,bl\t\t\t; are we more toward the front?\n\tjge\tshort ??out_pixel\t; if so then write the pixel\n\n??write_back:\n\tmov\tal,[fs:di]\t\t; get the pixel to write\n??out_pixel:\n\tstosb\t\t\t\t; write the pixel\n\tloop\t??loop_top\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GHOST_NORMAL_DRAW -- Function that writes a normal pixel line           *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   05/27/1993 MCC : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tNOLANGUAGE Ghost_Normal_Draw NEAR\n\n??loop_top:\n\tlodsb\n\n;---\n\t; Ok, find out if the colour is a Translucent colour\n\tpush\tax\n\tpush \tds\n\n\tlds\tbx,[IsTranslucent]\n\tmov\tah,al\t\t\t; preserve real pixel\n\txlat\t\t\t\t; get new al (transluecent pixel\n\txchg\tah,al\t\t\t; get real pixel back into AL just in case\n\tcmp\tah,255\n\tje\tshort ??normal_pixel\t\t; is it a translucent ?\n\t\t\t\t\t; if we get passed here value in\n\t\t\t\t\t; AH should be 0-15\n\n\t; yes, it is a translucent colour so goto our translucent translation\n\t; table and set up a ptr to the correct table\n\n\tmov\tal,[es:di]\n\t\t\t\t\t; mov pixel at destination to al and we have\n\t\t\t\t\t; the index to the translation table\n\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tlds\tbx,[Translucent]\t; get the ptr to it!\n\tadd\tbh,ah\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\t\t\t\t; XLAT only uses AL so no need to clear AH\n\txlat\t\t\t\t; get new pixel in AL\n\n??normal_pixel:\n\tpop\tds\n\tpop\tbx\n\tmov\tah,bh\n;---\n\n\tmov\t[es:di],al\t\t; store the pixel to the screen\n\n??skip:\n\tinc\tdi\n\tloop\t??loop_top\n\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GHOST_TRANSPARENT_DRAW -- Function that writes a transparent pixel line *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   05/27/1993 MCC : Created.                                             *\n;*=========================================================================*\n\tPROC\tNOLANGUAGE Ghost_Transparent_Draw NEAR\n\n??loop_top:\n\tlodsb\n\tor\tal,al\n\tjz\tshort ??skip\n\n;---\n\t; Ok, find out if the colour is a Translucent colour\n\tpush\tax\n\tpush \tds\n\n\tlds\tbx,[IsTranslucent]\n\tmov\tah,al\t\t\t; preserve real pixel\n\txlat\t\t\t\t; get new al (transluecent pixel\n\txchg\tah,al\t\t\t; get real pixel back into AL just in case\n\tcmp\tah,255\n\tje\tshort ??normal_pixel\t\t; is it a translucent ?\n\t\t\t\t\t; if we get passed here value in\n\t\t\t\t\t; AH should be 0-15\n\n\t; yes, it is a translucent colour so goto our translucent translation\n\t; table and set up a ptr to the correct table\n\n\tmov\tal,[es:di]\n\t\t\t\t\t; mov pixel at destination to al and we have\n\t\t\t\t\t; the index to the translation table\n\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tlds\tbx,[Translucent]\t; get the ptr to it!\n\tadd\tbh,ah\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\t\t\t\t; XLAT only uses AL so no need to clear AH\n\txlat\t\t\t\t; get new pixel in AL\n\n??normal_pixel:\n\tpop\tds\n\tpop\tbx\n\tmov\tah,bh\n;---\n\n\tmov\t[es:di],al\t\t; store the pixel to the screen\n\n??skip:\n\tinc\tdi\n\tloop\t??loop_top\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GHOST_PRIORITY_DRAW -- Function that writes a pixels if they are in fron*\n;*\t\t    the given plate.\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   12/01/1992 MBL : Updated to work with latest mask data encoding.      *\n;*   05/27/1993 MCC : Updated to use the new Ghosting fx\t\t   *\n;*   17/01/1993 MCC : Updated for 386, and optimized\t\t\t   *\n;*=========================================================================*\n\tPROC\tNOLANGUAGE Ghost_Priority_Draw NEAR\n\n\tmov\tfs,[background]\t\t; get the SEG of the background page\n\tmov\tgs,[maskpage]\t\t; get the SEG of the mask info\n\tmov\tah,[priority]\t\t; keep a copy of priority varible for faster cmp\n\n\n??loop_top:\n\tlodsb\t\t\t\t; get the pixel to draw on the screen\n\t\t\t\t\t; get the mask byte for our pixel\n\tmov\tbl,[ds:di]\n\t\t\t\t\t; get rid of non-walkable bit and\n\t\t\t\t\t; get rid of scaling id bits\n\tand\tbl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS\n\tcmp\tah,bl\t\t\t; are we more toward the front?\n\tjge\tshort ??out_pixel\t; if so then write the pixel\n\n\tmov\tal,[fs:di]\t\t; get the pixel to write\n??out_pixel:\n\tstosb\t\t\t\t; write the pixel and inc the DI\n\tloop\t??loop_top\n\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GHOST_PRIORITY_TRANSPARENT_DRAW -- Function that writes a pixels if they*\n;*\t\t    in front of the given plate.  It also deals with\t   *\n;*\t\t    transparent pixels.\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   12/01/1992 MBL : Updated to work with latest mask data encoding.      *\n;*   05/27/1993 MCC : Updated to use the new Ghosting fx\t\t   *\n;*   17/01/1993 MCC : Updated for 386, and optimized\t\t\t   *\n;*=========================================================================*\n\tPROC\tNOLANGUAGE Ghost_Priority_Transparent_Draw NEAR\n\n\tmov\tfs,[background]\t\t; get the SEG of the background page\n\tmov\tgs,[maskpage]\t\t; get the SEG of the mask info\n\tmov\tah,[priority]\t\t; keep a copy of priority varible for faster cmp\n\n??loop_top:\n\tlodsb\t\t\t\t; get the pixel on the screen\n\tor\tal,al\t\t\t; check to see if al is transparent\n\tje\tshort ??write_back\t;   if it is go write background\n\tmov\tbl,[gs:di]\t\t; get the mask byte for our pixel\n\t\t\t\t\t; get rid of non-walkable bit and\n\t\t\t\t\t; get rid of scaling id bits\n\tand\tbl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS\n\tcmp\tah,bl\t\t\t; are we more toward the front?\n\tjge\tshort ??out_pixel\t; if so then write the pixel\n??write_back:\n\tmov\tal,[fs:di]\t\t; get the pixel to write\n??out_pixel:\n\tstosb\t\t\t\t; write the pixel\n\tloop\t??loop_top\n\n\tret\n\n\tENDP\n\n\tEND\n"
  },
  {
    "path": "CODE/KEYFRAME.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/KEYFRAME.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : KEYFRAME.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                   Programmer : David Dettmer                                                *\n *                                                                                             *\n *                   Start Date : 06/25/95                                                     *\n *                                                                                             *\n *                  Last Update : June 25, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Get_Build_Frame_Count -- Fetches the number of frames in data block.                      *\n *   Get_Build_Frame_Width -- Fetches the width of the shape image.                            *\n *   Get_Build_Frame_Height -- Fetches the height of the shape image.                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"function.h\"\n\n#define SUBFRAMEOFFS\t\t\t7\t// 3 1/2 frame offsets loaded (2 offsets/frame)\n\n\n#define\tApply_Delta(buffer, delta)\t\tApply_XOR_Delta((char*)(buffer), (char*)(delta))\n\ntypedef struct {\n\tunsigned short frames;\n\tunsigned short x;\n\tunsigned short y;\n\tunsigned short width;\n\tunsigned short height;\n\tunsigned short largest_frame_size;\n\tshort\t\t\t\tflags;\n} KeyFrameHeaderType;\n\n\n\n#ifdef WIN32\n#define\tINITIAL_BIG_SHAPE_BUFFER_SIZE\t20000000\n#define\tUNCOMPRESS_MAGIC_NUMBER\t\t\t56789\n\nunsigned\tBigShapeBufferLength = INITIAL_BIG_SHAPE_BUFFER_SIZE;\nextern \"C\"{\n\tchar\t\t* BigShapeBufferStart = NULL;\n\tBOOL\t\tUseBigShapeBuffer = FALSE;\n}\nchar\t\t* BigShapeBufferPtr = NULL;\nint\t\t\tTotalBigShapes=0;\nBOOL\t\tReallocShapeBufferFlag = FALSE;\n\n\n\nchar\t** KeyFrameSlots [1000];\nint \tTotalSlotsUsed=0;\n\n\n\ntypedef struct tShapeHeaderType{\n\tunsigned draw_flags;\n\tchar\t\t* shape_data;\n} ShapeHeaderType;\n\nstatic int Length;\n\nvoid * Get_Shape_Header_Data(void * ptr)\n{\n\tif (UseBigShapeBuffer) {\n\t\treturn((void *)(((ShapeHeaderType *)ptr)->shape_data+(long)BigShapeBufferStart));\n\t} else {\n\t\treturn (ptr);\n\t}\n}\n\nint Get_Last_Frame_Length(void)\n{\n\treturn(Length);\n}\n\n\n\nvoid Reallocate_Big_Shape_Buffer(void)\n{\n\tif (ReallocShapeBufferFlag) {\n\t\tBigShapeBufferLength += 2000000;\t\t\t\t\t\t\t//Extra 2 Mb of uncompressed shape space\n\t\tBigShapeBufferPtr -= (unsigned)BigShapeBufferStart;\n\t\tBigShapeBufferStart = (char*)Resize_Alloc(BigShapeBufferStart, BigShapeBufferLength);\n\t\tBigShapeBufferPtr += (unsigned)BigShapeBufferStart;\n\t\tReallocShapeBufferFlag = FALSE;\n\t}\n}\n\n\n\n\nvoid Check_Use_Compressed_Shapes (void)\n{\n\tMEMORYSTATUS\tmem_info;\n\n\tmem_info.dwLength=sizeof(mem_info);\n\tGlobalMemoryStatus(&mem_info);\n\n\tUseBigShapeBuffer = (mem_info.dwTotalPhys > 12*1024*1024) ? TRUE : FALSE;\n}\n\n#endif\n\n\nunsigned long Build_Frame(void const * dataptr, unsigned short framenumber, void * buffptr)\n{\n#ifdef FIXIT_SCORE_CRASH\n\tchar * ptr;\n\tunsigned long offcurr, offdiff;\n#else\n\tchar * ptr, * lockptr;\n\tunsigned long offcurr, off16, offdiff;\n#endif\n\tunsigned long offset[SUBFRAMEOFFS];\n\tKeyFrameHeaderType * keyfr;\n\tunsigned short buffsize, currframe, subframe;\n\tunsigned long length = 0;\n\tchar frameflags;\n\n\t//\n\t// valid pointer??\n\t//\n\tif ( !dataptr || !buffptr ) {\n\t\treturn(0);\n\t}\n\n\t//\n\t// look at header then check that frame to build is not greater\n\t// than total frames\n\t//\n\tkeyfr = (KeyFrameHeaderType *) dataptr;\n\n\tif ( framenumber >= keyfr->frames ) {\n\t\treturn(0);\n\t}\n\n\t// calc buff size\n\tbuffsize = keyfr->width * keyfr->height;\n\n\t// get offset into data\n\tptr = (char *)dataptr + (((unsigned long)framenumber << 3) + sizeof(KeyFrameHeaderType));\n\tMem_Copy( ptr, &offset[0], 12L );\n\tframeflags = (char)(offset[0] >> 24);\n\n\tif ( (frameflags & KF_KEYFRAME) ) {\n\n\t\tptr = (char *)Add_Long_To_Pointer( dataptr, (offset[0] & 0x00FFFFFFL) );\n\n\t\tif (keyfr->flags & 1 ) {\n\t\t\tptr = (char *)Add_Long_To_Pointer( ptr, 768L );\n\t\t}\n\n\t\tlength = LCW_Uncompress( ptr, buffptr, buffsize );\n\t} else {\t// key delta or delta\n\n\t\tif ( (frameflags & KF_DELTA) ) {\n\t\t\tcurrframe = (unsigned short)offset[1];\n\n\t\t\tptr = (char *)Add_Long_To_Pointer( dataptr, (((unsigned long)currframe << 3) + sizeof(KeyFrameHeaderType)) );\n\t\t\tMem_Copy( ptr, &offset[0], (long)(SUBFRAMEOFFS * sizeof(unsigned long)) );\n\t\t}\n\n\t\t// key frame\n\t\toffcurr = offset[1] & 0x00FFFFFFL;\n\n\t\t// key delta\n\t\toffdiff = (offset[0] & 0x00FFFFFFL) - offcurr;\n\n\t\tptr = (char *)Add_Long_To_Pointer( dataptr, offcurr );\n\n\t\tif (keyfr->flags & 1 ) {\n\t\t\tptr = (char *)Add_Long_To_Pointer( ptr, 768L );\n\t\t}\n\n#ifndef FIXIT_SCORE_CRASH\n\t\toff16 = (unsigned long)lockptr & 0x00003FFFL;\n#endif\n\n\t\tlength = LCW_Uncompress( ptr, buffptr, buffsize );\n\n\t\tif (length > buffsize) {\n\t\t\treturn(0);\n\t\t}\n\n#ifndef FIXIT_SCORE_CRASH\n\t\tif ( ((offset[2] & 0x00FFFFFFL) - offcurr) >= (0x00010000L - off16) ) {\n\n\t\t\tptr = (char *)Add_Long_To_Pointer( ptr, offdiff );\n\t\t\toff16 = (unsigned long)ptr & 0x00003FFFL;\n\n\t\t\toffcurr += offdiff;\n\t\t\toffdiff = 0;\n\t\t}\n#endif\n\n#ifdef NEVER\n\t\t// check for LCW'd rsd\n\n\t\tif ( ((offset[1] >> 24) & KF_LCW) ) {\n\t\t\tlength = LCW_Uncompress( ptr, buffptr, buffsize );\n\t\t} else {\n\t\t\tlength = buffsize;\n\t\t\tApply_XOR_Delta( buffptr, Add_Long_To_Pointer( ptr, offdiff ) );\n\t\t}\n#else\n\t\tlength = buffsize;\n\t\tApply_Delta(buffptr, Add_Long_To_Pointer(ptr, offdiff));\n#endif\n\n\t\tif ( (frameflags & KF_DELTA) ) {\n\t\t\t// adjust to delta after the keydelta\n\n\t\t\tcurrframe++;\n\t\t\tsubframe = 2;\n\n\t\t\twhile (currframe <= framenumber) {\n\t\t\t\toffdiff = (offset[subframe] & 0x00FFFFFFL) - offcurr;\n\n#ifndef FIXIT_SCORE_CRASH\n\t\t\t\tif ( ((offset[subframe+2] & 0x00FFFFFFL) - offcurr) >= (0x00010000L - off16) ) {\n\n\t\t\t\t\tptr = (char *)Add_Long_To_Pointer( ptr, offdiff );\n\t\t\t\t\toff16 = (unsigned long)lockptr & 0x00003FFFL;\n\n\t\t\t\t\toffcurr += offdiff;\n\t\t\t\t\toffdiff = 0;\n\t\t\t\t}\n#endif\n\n#ifdef NEVER\n\t\t\t\t// check for LCW'd rsd\n\n\t\t\t\tif ( ((offset[1] >> 24) & KF_LCW) ) {\n\t\t\t\t\tlength = LCW_Uncompress( ptr, buffptr, buffsize );\n\t\t\t\t} else {\n\t\t\t\t\tlength = buffsize;\n\t\t\t\t\tApply_XOR_Delta( buffptr, Add_Long_To_Pointer( ptr, offdiff ) );\n\t\t\t\t}\n#else\n\t\t\t\tlength = buffsize;\n\t\t\t\tApply_Delta(buffptr, Add_Long_To_Pointer(ptr, offdiff));\n#endif\n\n\t\t\t\tcurrframe++;\n\t\t\t\tsubframe += 2;\n\n\t\t\t\tif ( subframe >= (SUBFRAMEOFFS - 1) &&\n\t\t\t\t\tcurrframe <= framenumber ) {\n\t\t\t\t\tMem_Copy( Add_Long_To_Pointer( dataptr,\n\t\t\t\t\t\t\t\t\t(((unsigned long)currframe << 3) +\n\t\t\t\t\t\t\t\t\tsizeof(KeyFrameHeaderType)) ),\n\t\t\t\t\t\t&offset[0], (long)(SUBFRAMEOFFS * sizeof(unsigned long)) );\n\t\t\t\t\tsubframe = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(length);\n}\n\n\n/***********************************************************************************************\n * Get_Build_Frame_Count -- Fetches the number of frames in data block.                        *\n *                                                                                             *\n *    Use this routine to determine the number of shapes within the data block.                *\n *                                                                                             *\n * INPUT:   dataptr  -- Pointer to the keyframe shape data block.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the number of shapes in the data block.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Commented.                                                               *\n *=============================================================================================*/\nunsigned short Get_Build_Frame_Count(void const * dataptr)\n{\n\tif (dataptr) {\n\t\treturn(((KeyFrameHeaderType const *)dataptr)->frames);\n\t}\n\treturn(0);\n}\n\n\nunsigned short Get_Build_Frame_X(void const * dataptr)\n{\n\tif (dataptr) {\n\t\treturn(((KeyFrameHeaderType const *)dataptr)->x);\n\t}\n\treturn(0);\n}\n\n\nunsigned short Get_Build_Frame_Y(void const * dataptr)\n{\n\tif (dataptr) {\n\t\treturn(((KeyFrameHeaderType const *)dataptr)->y);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * Get_Build_Frame_Width -- Fetches the width of the shape image.                              *\n *                                                                                             *\n *    Use this routine to fetch the width of the shapes within the keyframe shape data block.  *\n *    All shapes within the block have the same width.                                         *\n *                                                                                             *\n * INPUT:   dataptr  -- Pointer to the keyframe shape data block.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the width of the shapes in the block -- expressed in pixels.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Commented                                                                *\n *=============================================================================================*/\nunsigned short Get_Build_Frame_Width(void const * dataptr)\n{\n\tif (dataptr) {\n\t\treturn(((KeyFrameHeaderType const *)dataptr)->width);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * Get_Build_Frame_Height -- Fetches the height of the shape image.                            *\n *                                                                                             *\n *    Use this routine to fetch the height of the shapes within the keyframe shape data block. *\n *    All shapes within the block have the same height.                                        *\n *                                                                                             *\n * INPUT:   dataptr  -- Pointer to the keyframe shape data block.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the height of the shapes in the block -- expressed in pixels.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Commented                                                                *\n *=============================================================================================*/\nunsigned short Get_Build_Frame_Height(void const * dataptr)\n{\n\tif (dataptr) {\n\t\treturn(((KeyFrameHeaderType const *)dataptr)->height);\n\t}\n\treturn(0);\n}\n\n\nbool Get_Build_Frame_Palette(void const * dataptr, void * palette)\n{\n\tif (dataptr && (((KeyFrameHeaderType const *)dataptr)->flags & 1)) {\n\t\tchar const * ptr = (char const *)Add_Long_To_Pointer( dataptr,\n\t\t\t\t\t\t\t( (( (long)sizeof(unsigned long) << 1) *\n\t\t\t\t\t\t\t\t((KeyFrameHeaderType *) dataptr)->frames ) +\n\t\t\t\t\t\t\t16 + sizeof(KeyFrameHeaderType) ) );\n\n\t\tmemcpy(palette, ptr, 768L);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "CODE/LANGUAGE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#ifdef ENGLISH\n#define\tTEXT_ERROR_TIMER\t\t\"Error - Timer system failed to initialise due to system instability. You need to restart Windows.\"\n#define TEXT_SHORT_TITLE                \"Red Alert\"\n#define TEXT_MEMORY_ERROR               \"Error - out of memory.\"\n#define TEXT_ABORT                              \"Abort\"\n#define TEXT_DDRAW_ERROR                \"Error - Unable to allocate primary video buffer - aborting.\"\n#define TEXT_TITLE                              \"Command & Conquer : Red Alert\"\n#define TEXT_VIDEO_ERROR                \"Error - Unable to set the video mode.\"\n#define TEXT_INSUFFICIENT               \"Insufficient Disk Space to run Red Alert.\\n\"\n#define TEXT_MUST_HAVE                  \"You must have %d megabytes of free disk space.\"\n#define TEXT_CRITICALLY_LOW     \"Warning - you are critically low on free disk space for saving games. Do you want to play Red Alert anyway?\"\n#define TEXT_NO_RAM                             \"Insufficient RAM available.\\n\"\n#define TEXT_USE_START_MENU\t\t\t\t\t\"\\n\\rIf you have Windows 95 running you should start Red Alert\\r\\nDOS version via the Windows 95 Start Menu.\\n\\rPress any key.\\n\\r\"\n#define TEXT_SETUP_FIRST                \"Run SETUP program first.\\n\"\n#define TEXT_NO_MOUSE                   \"Red Alert is unable to detect your mouse driver.\"\n#define TEXT_FILE_ERROR         \"FILE ERROR\"\n#define TEXT_PRESS_KEY                  \"Press any key to retry.\"\n#define TEXT_ESC_KEY                    \"Press <ESC> to exit program.\"\n#define TEXT_TO_EXIT                    \"Press any key to exit program.\"\n#define TEXT_INVALID                    \"Invalid option switch.\\n\"\n#define TEXT_MAP_ERROR                  \"Map Error!\"\n#define TEXT_STOP                               \"Stop\"\n#define TEXT_CONTINUE                   \"Continue\"\n#define TEXT_OPTIONS                    \"Red Alert (c) 1996, Westwood Studios\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"Parameters:\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"  -DESTNET  = Specify Network Number of destination system\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"              (Syntax: DESTNETxx.xx.xx.xx)\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"  -SOCKET   = Network Socket ID (0 - 16383)\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"  -STEALTH  = Hide multiplayer names (\\\"Boss mode\\\")\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"  -MESSAGES = Allow messages from outside this game.\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"\\r\\n\"\n#endif\n\n\n#ifdef GERMAN\n#define TEXT_ERROR_TIMER                \"Fehler - das Timer-System konnte aufgrund einer Instabilitt des Systems nicht initialisiert werden. Bitte starten Sie Windows neu.\"\n#define TEXT_SHORT_TITLE                \"C&C:AR\"\n#define TEXT_MEMORY_ERROR               \"Fehler - Kein Speicher mehr.\"\n#define TEXT_ABORT                      \"Abbrechen\"\n#define TEXT_DDRAW_ERROR                \"Fehler - Kann primren Videopuffer nicht finden - Abbruch.\"\n#define TEXT_TITLE                      \"Command & Conquer : Alarmstufe Rot\"\n#define TEXT_VIDEO_ERROR                \"Fehler - Kann Grafikmodus nicht einstellen.\"\n#define TEXT_INSUFFICIENT               \"Nicht genug Festplattenplatz fr Command & Conquer:AR.\\n\"\n#define TEXT_MUST_HAVE                  \"Sie brauchen %d MByte freien Platz auf der Festplatte.\"\n#define TEXT_CRITICALLY_LOW   \t\t\t \"Nicht genug Festplattenplatz fr Command & Conquer:AR.\\nSie brauchen %d MByte freien Platz auf der Festplatte.\"\n#define TEXT_NO_RAM                     \"Zuwenig Hauptspeicher verfgbar.\\n\"\n#define TEXT_USE_START_MENU\t\t\t\t\t\"\\n\\rWenn auf Ihrem Rechner Windows 95 luft,\\n\\rstarten Sie die DOS-Version von Alarmstufe Rot\\n\\rbitte ber das Start-Men von Windows 95.\\n\\rZum Weitermachen beliebige Taste drcken.\\n\\r\"\n#define TEXT_SETUP_FIRST                \"Bitte erst das SETUP-Programm starten.\\n\"\n#define TEXT_NO_MOUSE                   \"C&C:AR kann Ihren Maustreiber nicht finden...\"\n#define TEXT_FILE_ERROR       \t\t\t \"DATEIFEHLER\"\n#define TEXT_PRESS_KEY                  \"Beliebige Taste drcken fr erneuten Versuch.\"\n#define TEXT_ESC_KEY                    \"<ESC> drcken, um das Programm zu verlassen.\"\n#define TEXT_TO_EXIT                    \"Beliebige Taste drcken, um das Programm zu verlassen.\"\n#define TEXT_INVALID                    \"Ungltiger Parameter.\\n\"\n#define TEXT_MAP_ERROR                  \"Kartenfehler!\"\n#define TEXT_STOP                       \"Halt\"\n#define TEXT_CONTINUE                   \"Weiter\"\n#define TEXT_OPTIONS                    \"C&C: Alarmstufe Rot (c) 1996, Westwood Studios\\r\\n\" \\\n\t\t\t\t \t\t\t\t\t\t\t\t\t \"Parameter:\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t \"  -DESTNET  = Netzwerkkennung des Zielrechners festlegen\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t \"              (Syntax: DESTNETxx.xx.xx.xx)\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t \"  -SOCKET   = Kennung des Netzwerk-Sockets (0 - 16383)\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t \"  -STEALTH  = Namen im Mehrspieler-Modus verstecken (\\\"Boss-Modus\\\")\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t \"  -MESSAGES = Mitteilungen von ausserhalb des Spiels zulassen\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t \"\\r\\n\"\n#endif\n\n\n#ifdef FRENCH\n#define TEXT_ERROR_TIMER                \"Error - L'horloge systme n'a pas pu s'initialiser en raison de l'instabilit du sytme. Vous devez redmarrer Windows.\"\n#define TEXT_SHORT_TITLE                \"Alerte Rouge\"\n#define TEXT_MEMORY_ERROR               \"Erreur - Plus de mmoire.\"\n#define TEXT_ABORT                              \"Interrompre\"\n#define TEXT_DDRAW_ERROR                \" Erreur - Impossible d'allouer le tampon vido principal - Interruption.\"\n#define TEXT_TITLE                              \"Command & Conquer : Alerte Rouge\"\n#define TEXT_VIDEO_ERROR                \" Erreur - Impossible d'tablir le mode vido.\"\n#define TEXT_INSUFFICIENT               \"Espace disque insuffisant pour lancer Command & Conquer.\\n\"\n#define TEXT_MUST_HAVE                  \"Vous devez disposer de %d Mo d'espace disponsible sur le disque dur.\"\n#define TEXT_CRITICALLY_LOW     \"Espace disque insuffisant pour lancer Command & Conquer.\\nVous devez disposer de %d Mo d'espace disponsible sur le disque dur.\"\n#define TEXT_NO_RAM                             \"Mmoire vive (RAM) insuffisante.\\n\"\n#define TEXT_USE_START_MENU\t\t\t\t \"\\n\\rSi vous tes dans Windows 95 vous devez lancer Alerte Rouge\\r\\nDOS  partir du menu Dmarrer de Windows 95.\\n\\rAppuyez sur n'importe quelle touche.\\n\\r\"\n#define TEXT_SETUP_FIRST                \"Lancez d'abord le programme de configuration SETUP.\\n\"\n#define TEXT_NO_MOUSE                   \"Alerte Rouge ne peut pas dtecter votre gestionnaire de souris.\"\n#define TEXT_FILE_ERROR         \"ERREUR DE FICHIER\"\n#define TEXT_PRESS_KEY                  \"Appuyez sur une touche pour recommencer.\"\n#define TEXT_ESC_KEY                    \"Appuyez sur Echap pour quitter le programme.\"\n#define TEXT_TO_EXIT                    \"Appuyez sur une touche pour quitter le programme.\"\n#define TEXT_INVALID                    \"Commande d'option invalide.\\n\"\n#define TEXT_MAP_ERROR                  \"Erreur de carte!\"\n#define TEXT_STOP                               \"Stop\"\n#define TEXT_CONTINUE                   \"Continuer\"\n#define TEXT_OPTIONS                    \"Alerte Rouge (c) 1996, Westwood Studios\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"Paramtres:\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"  -DESTNET  = Spcifier le numro de rseau du systme de destination\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"              (Syntaxe: DESTNETxx.xx.xx.xx)\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"  -SOCKET   = ID Socket rseau (0 \u0005 16383)\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"  -STEALTH  = Cacher les noms en mode multijoueurs (\\\"Mode Boss\\\")\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"  -MESSAGES = Autorise les messages extrieurs  ce jeu.\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"\\r\\n\"\n#endif\n\n"
  },
  {
    "path": "CODE/LAYER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LAYER.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LAYER.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 31, 1994                                                 *\n *                                                                                             *\n *                  Last Update : March 10, 1995 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LayerClass::Sort -- Perform an incremental sort pass on the layer's objects.              *\n *   LayerClass::Sorted_Add -- Adds object in sorted order to layer.                           *\n *   LayerClass::Submit -- Adds an object to a layer list.                                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"layer.h\"\n\n\n/***********************************************************************************************\n * LayerClass::Submit -- Adds an object to a layer list.                                       *\n *                                                                                             *\n *    This routine is used to add an object to the layer list. If the list is full, then the   *\n *    object is not added.                                                                     *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object to add.                                          *\n *                                                                                             *\n * OUTPUT:  bool; Was the object added successfully?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   05/31/1994 JLB : Allows sorted insert.                                                    *\n *   01/02/1995 JLB : Fixed to work with EMSListOf template.                                   *\n *=============================================================================================*/\nbool LayerClass::Submit(ObjectClass const * object, bool sort)\n{\n\t/*\n\t**\tAdd the object to the layer. Either at the end (if \"sort\" is false) or at the\n\t**\tappropriately sorted position.\n\t*/\n\tif (sort) {\n\t\treturn(Sorted_Add(object));\n\t}\n\treturn(Add((ObjectClass *)object));\n}\n\n\n/***********************************************************************************************\n * LayerClass::Sort -- Handles sorting the objects in the layer.                               *\n *                                                                                             *\n *    This routine is used if the layer objects must be sorted and sorting is to occur now.    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Don't call this routine too often since it does take a bit of time to           *\n *             execute. It is a single pass binary sort and thus isn't horribly slow,          *\n *             but it does take some time.                                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *   03/10/1995 JLB : Uses comparison operator.                                                *\n *=============================================================================================*/\nvoid LayerClass::Sort(void)\n{\n\tfor (int index = 0; index < Count()-1; index++) {\n\t\tif (*(*this)[index+1] < *(*this)[index]) {\n\t\t\tObjectClass * temp;\n\n\t\t\ttemp = (*this)[index+1];\n\t\t\t(*this)[index+1] = (*this)[index];\n\t\t\t(*this)[index] = temp;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DynamicVectorClass<T>::Sorted_Add -- Adds object in sorted order to vector.                 *\n *                                                                                             *\n *    Use this routine to add an object to the vector but it will be inserted in sorted        *\n *    order. This depends on the \">\" operator being defined for the vector object.             *\n *                                                                                             *\n * INPUT:   object   -- Reference to the object that will be added to the vector.              *\n *                                                                                             *\n * OUTPUT:  bool; Was the object added to the vector successfully?                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LayerClass::Sorted_Add(ObjectClass const * const object)\n{\n\tif (ActiveCount >= Length()) {\n\t\tif ((IsAllocated || !VectorMax) && GrowthStep > 0) {\n\t\t\tif (!Resize(Length() + GrowthStep)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tFailure to increase the size of the vector is an error condition.\n\t\t\t\t**\tReturn with the error flag.\n\t\t\t\t*/\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIncreasing the size of this vector is not allowed! Bail this\n\t\t\t**\troutine with the error code.\n\t\t\t*/\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tThere is room for the new object now. Add it to the right sorted position.\n\t*/\n\tfor (int index = 0; index < ActiveCount; index++) {\n\t\tif ((*(*this)[index]) > (*object)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tMake room if the insertion spot is not at the end of the vector.\n\t*/\n\tfor (int i = ActiveCount-1; i >= index; i--) {\n\t\t(*this)[i+1] = (*this)[i];\n\t}\n\t(*this)[index] = (ObjectClass *)object;\n\tActiveCount++;\n\treturn(true);\n}\n\n\n"
  },
  {
    "path": "CODE/LAYER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LAYER.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LAYER.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 31, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 31, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef LAYER_H\n#define LAYER_H\n\n#include \"vector.h\"\n\nclass ObjectClass;\n\nclass LayerClass : public DynamicVectorClass<ObjectClass *>\n{\n\tpublic:\n\n\t\t//-----------------------------------------------------------------\n\t\tvoid Sort(void);\n\t\tbool Submit(ObjectClass const * object, bool sort=false);\n\t\tint Sorted_Add(ObjectClass const * const object);\n\n\n\t\tvirtual void Init(void) {Clear();};\n\t\tvirtual void One_Time(void) {};\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n};\n\n#endif\n"
  },
  {
    "path": "CODE/LCW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LCW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **    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        **\n ***************************************************************************\n *                                                                         *\n *               Project Name : WESTWOOD LIBRARY (PSX)                     *\n *                                                                         *\n *                 File Name : LCWUNCMP.CPP                                *\n *                                                                         *\n *                Programmer : Ian M. Leslie                               *\n *                                                                         *\n *                Start Date : May 17, 1995                                *\n *                                                                         *\n *               Last Update : May 17, 1995    [IML]                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n/***************************************************************************\n * LCW_Uncomp -- Decompress an LCW encoded data block.                     *\n *                                                                         *\n * Uncompress data to the following codes in the format b = byte, w = word *\n * n = byte code pulled from compressed data.                              *\n *                                                                         *\n *   Command code, n        |Description                                   *\n * ------------------------------------------------------------------------*\n * n=0xxxyyyy,yyyyyyyy      |short copy back y bytes and run x+3 from dest *\n * n=10xxxxxx,n1,n2,...,nx+1|med length copy the next x+1 bytes from source*\n * n=11xxxxxx,w1            |med copy from dest x+3 bytes from offset w1   *\n * n=11111111,w1,w2         |long copy from dest w1 bytes from offset w2   *\n * n=11111110,w1,b1         |long run of byte b1 for w1 bytes              *\n * n=10000000               |end of data reached                           *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *      void * source ptr                                                  *\n *      void * destination ptr                                             *\n *      unsigned long length of uncompressed data                          *\n *                                                                         *\n *                                                                         *\n * OUTPUT:                                                                 *\n *     unsigned long # of destination bytes written                        *\n *                                                                         *\n * WARNINGS:                                                               *\n *     3rd argument is dummy. It exists to provide cross-platform          *\n *      compatibility. Note therefore that this implementation does not    *\n *      check for corrupt source data by testing the uncompressed length.  *\n *                                                                         *\n * HISTORY:                                                                *\n *    03/20/1995 IML : Created.                                            *\n *=========================================================================*/\nint LCW_Uncomp(void const * source, void * dest, unsigned long )\n{\n\tunsigned char * source_ptr, * dest_ptr, * copy_ptr, op_code, data;\n\tunsigned\t  count, * word_dest_ptr, word_data;\n\n\t/* Copy the source and destination ptrs. */\n\tsource_ptr = (unsigned char*) source;\n\tdest_ptr   = (unsigned char*) dest;\n\n\twhile (1 /*TRUE*/) {\n\n\t\t/* Read in the operation code. */\n\t\top_code = *source_ptr++;\n\n\t\tif (!(op_code & 0x80)) {\n\n\t\t\t/* Do a short copy from destination. */\n\t\t\tcount\t = (op_code >> 4) + 3;\n\t\t\tcopy_ptr = dest_ptr - ((unsigned) *source_ptr++ + (((unsigned) op_code & 0x0f) << 8));\n\n\t\t\twhile (count--) *dest_ptr++ = *copy_ptr++;\n\n\t\t} else {\n\n\t\t\tif (!(op_code & 0x40)) {\n\n\t\t\t\tif (op_code == 0x80) {\n\n\t\t\t\t\t/* Return # of destination bytes written. */\n\t\t\t\t\treturn ((unsigned long) (dest_ptr - (unsigned char*) dest));\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/* Do a medium copy from source. */\n\t\t\t\t\tcount = op_code & 0x3f;\n\n\t\t\t\t\twhile (count--) *dest_ptr++ = *source_ptr++;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tif (op_code == 0xfe) {\n\n\t\t\t\t\t/* Do a long run. */\n\t\t\t\t\tcount = *source_ptr + ((unsigned) *(source_ptr + 1) << 8);\n\t\t\t\t\tword_data = data = *(source_ptr + 2);\n\t\t\t\t\tword_data  = (word_data << 24) + (word_data << 16) + (word_data << 8) + word_data;\n\t\t\t\t\tsource_ptr += 3;\n\n\t\t\t\t\tcopy_ptr = dest_ptr + 4 - ((unsigned) dest_ptr & 0x3);\n\t\t\t\t\tcount -= (copy_ptr - dest_ptr);\n\t\t\t\t\twhile (dest_ptr < copy_ptr) *dest_ptr++ = data;\n\n\t\t\t\t\tword_dest_ptr = (unsigned*) dest_ptr;\n\n\t\t\t\t\tdest_ptr += (count & 0xfffffffc);\n\n\t\t\t\t\twhile (word_dest_ptr < (unsigned*) dest_ptr) {\n\t\t\t\t\t\t*word_dest_ptr\t\t= word_data;\n\t\t\t\t\t\t*(word_dest_ptr + 1) = word_data;\n\t\t\t\t\t\tword_dest_ptr += 2;\n\t\t\t\t\t}\n\n\t\t\t\t\tcopy_ptr = dest_ptr + (count & 0x3);\n\t\t\t\t\twhile (dest_ptr < copy_ptr) *dest_ptr++ = data;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif (op_code == 0xff) {\n\n\t\t\t\t\t\t/* Do a long copy from destination. */\n\t\t\t\t\t\tcount\t = *source_ptr + ((unsigned) *(source_ptr + 1) << 8);\n\t\t\t\t\t\tcopy_ptr = (unsigned char*) dest + *(source_ptr + 2) + ((unsigned) *(source_ptr + 3) << 8);\n\t\t\t\t\t\tsource_ptr += 4;\n\n\t\t\t\t\t\twhile (count--) *dest_ptr++ = *copy_ptr++;\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/* Do a medium copy from destination. */\n\t\t\t\t\t\tcount = (op_code & 0x3f) + 3;\n\t\t\t\t\t\tcopy_ptr = (unsigned char*) dest + *source_ptr + ((unsigned) *(source_ptr + 1) << 8);\n\t\t\t\t\t\tsource_ptr += 2;\n\n\t\t\t\t\t\twhile (count--) *dest_ptr++ = *copy_ptr++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "CODE/LCW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LCW.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LCW.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef LCW_H\n#define LCW_H\n\n\nint LCW_Uncomp(void const * source, void * dest, unsigned long length=0);\n\nextern \"C\" {\nint __cdecl LCW_Comp(void const * source, void * dest, int length);\n}\n\n#endif\n"
  },
  {
    "path": "CODE/LCWCOMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header:   F:\\projects\\c&c0\\vcs\\code\\lcwcomp.asv   5.0   11 Nov 1996 09:40:34   JOE_BOSTIC  $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library routine                          *\n;*                                                                         *\n;*                    File Name : COMPRESS.ASM                             *\n;*                                                                         *\n;*                   Programmer : Louis Castle                             *\n;*                                                                         *\n;*                  Last Update : 20 August, 1990   [CY]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL    C LCW_Comp          :NEAR\n\nCODESEG\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; ULONG LCW_Compress(BYTE *source,BYTE *dest, ULONG length);\n;\n; ----------------------------------------------------------------\n\n\n\n;***********************************************************\n;\n; ULONG LCW_Compress(BYTE *source, BYTE *dest, ULONG length)\n;\n; returns the size of the compressed data in bytes\n;\n;*\nPROC\tLCW_Comp C near\n\tUSES ebx,ecx,edx,edi,esi\n\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tdatasize:DWORD\n\n\tLOCAL inlen:DWORD\n\tLOCAL a1stdest:DWORD\n\tLOCAL a1stsrc:DWORD\n\tLOCAL lenoff:DWORD\n\tLOCAL ndest:DWORD\n\tLOCAL count:DWORD\n\tLOCAL matchoff:DWORD\n\tLOCAL end_of_data:DWORD\n\n\n\tcld\n \tmov\tedi,[dest]\n \tmov\tesi,[source]\n \tmov\tedx,[datasize]\t\t; get length of data to compress\n\n;\tmov\tax,ds\n;\tmov\tes,ax\n\n;\n; compress data to the following codes in the format b = byte, w = word\n; n = byte code pulled from compressed data\n;   Bit field of n\t\tcommand\t\tdescription\n; n=0xxxyyyy,yyyyyyyy\t\tshort run\tback y bytes and run x+3\n; n=10xxxxxx,n1,n2,...,nx+1\tmed length\tcopy the next x+1 bytes\n; n=11xxxxxx,w1\t\t\tmed run\t\trun x+3 bytes from offset w1\n; n=11111111,w1,w2\t\tlong run\trun w1 bytes from offset w2\n; n=10000000\t\t\tend\t\tend of data reached\n;\n\tcld\t\t\t; make sure all string commands are forward\n\tmov\tebx,esi\n\tadd\tebx,edx\n\tmov\t[end_of_data],ebx\n\tmov\t[inlen],1\t; set the in-length flag\n\tmov\t[a1stdest],edi\t; save original dest offset for size calc\n\tmov\t[a1stsrc],esi\t; save offset of first byte of data\n\tmov\t[lenoff],edi\t; save the offset of the legth of this len\n\tsub\teax,eax\n\tmov\tal,081h\t\t; the first byte is always a len\n\tstosb\t\t\t; write out a len of 1\n\tlodsb\t\t\t; get the byte\n\tstosb\t\t\t; save it\n??loop:\n\tmov\t[ndest],edi\t; save offset of compressed data\n\tmov\tedi,[a1stsrc]\t; get the offset to the first byte of data\n\tmov\t[count],1\t; set the count of run to 0\n??searchloop:\n\tsub\teax,eax\n\tmov\tal,[esi]\t; get the current byte of data\n\tcmp\tal,[esi+64]\n\tjne\tshort ??notrunlength\n\n\tmov\tebx,edi\n\n\tmov\tedi,esi\n\tmov\tecx,[end_of_data]\n\tsub\tecx,edi\n   \trepe\tscasb\n\tdec\tedi\n\tmov\tecx,edi\n\tsub\tecx,esi\n\tcmp\tecx,65\n\tjb\tshort ??notlongenough\n\n\tmov\t[DWORD PTR inlen],0\t; clear the in-length flag\n\tmov\tesi,edi\n\tmov\tedi,[ndest]\t; get the offset of our compressed data\n\n\tmov\tah,al\n\tmov\tal,0FEh\n\tstosb\n\txchg\tecx,eax\n\tstosw\n\tmov\tal,ch\n\tstosb\n\n\tmov\t[ndest],edi\t; save offset of compressed data\n\tmov\tedi,ebx\n\tjmp\t??searchloop\n??notlongenough:\n\tmov\tedi,ebx\n??notrunlength:\n\n??oploop:\n\tmov\tecx,esi\t\t; get the address of the last byte +1\n\tsub\tecx,edi\t\t; get the total number of bytes left to comp\n\tjz\tshort ??searchdone\n\n\trepne\tscasb\t\t; look for a match\n\tjne\tshort ??searchdone\t; if we don't find one we're done\n\n\tmov\tebx,[count]\n\tmov\tah,[esi+ebx-1]\n\tcmp\tah,[edi+ebx-2]\n\n\tjne\t??oploop\n\n\tmov\tedx,esi\t\t; save this spot for the next search\n\tmov\tebx,edi\t\t; save this spot for the length calc\n\tdec\tedi\t\t; back up one for compare\n\tmov\tecx,[end_of_data]\t\t; get the end of data\n\tsub\tecx,esi\t\t; sub current source for max len\n\n\trepe\tcmpsb\t\t; see how many bytes match\n\n; start of change MH 9-24-91\n\tjne\tshort ??notend\t; if found mismatch then di - bx = match count\n\n\tinc\tedi\t\t; else cx = 0 and di + 1 - bx = match count\n\n??notend:\n; end of change MH 9-24-91\n\n\tmov\tesi,edx\t\t; restore si\n\tmov\teax,edi\t\t; get the dest\n\tsub\teax,ebx\t\t; sub the start for total bytes that match\n\tmov\tedi,ebx\t\t; restore dest\n\tcmp\teax,[count]\t; see if its better than before\n\tjb\t??searchloop\t; if not keep looking\n\n\tmov\t[count],eax\t; if so keep the count\n\tdec\tebx\t\t; back it up for the actual match offset\n\tmov\t[matchoff],ebx ; save the offset for later\n\tjmp\t??searchloop\t; loop until we searched it all\n\n??searchdone:\n\n\tmov\tecx,[count]\t; get the count of the longest run\n\tmov\tedi,[ndest]\t; get the offset of our compressed data\n\tcmp\tecx,2\t\t; see if its not enough run to matter\n\tjbe\tshort ??lenin\t\t; if its 0,1, or 2 its too small\n\n\tcmp\tecx,10\t\t; if not, see if it would fit in a short\n\tja\tshort ??medrun\t; if not, see if its a medium run\n\n\tmov\teax,esi\t\t; if its short get the current address\n\tsub\teax,[matchoff] ; sub the offset of the match\n\tcmp\teax,0FFFh\t; if its less than 12 bits its a short\n\tja\tshort ??medrun\t; if its not, its a medium\n\n??shortrun:\n\tsub\tebx,ebx\n\tmov\tbl,cl\t\t; get the length (3-10)\n\tsub\tbl,3\t\t; sub 3 for a 3 bit number 0-7\n\tshl\tbl,4\t\t; shift it left 4\n\tadd\tah,bl\t\t; add in the length for the high nibble\n\txchg\tah,al\t\t; reverse the bytes for a word store\n\tjmp\tshort ??srunnxt\t; do the run fixup code\n\n??medrun:\n\tcmp\tecx,64\t\t; see if its a short run\n\tja\tshort ??longrun\t; if not, oh well at least its long\n\n\tsub\tcl,3\t\t; back down 3 to keep it in 6 bits\n\tor\tcl,0C0h\t\t; the highest bits are always on\n\tmov\tal,cl\t\t; put it in al for the stosb\n\tstosb\t\t\t; store it\n\tjmp\tshort ??medrunnxt ; do the run fixup code\n\n??lenin:\n\tcmp\t[DWORD PTR inlen],0\t; is it doing a length?\n\tjnz\tshort ??len\t; if so, skip code\n\n??lenin1:\n\tmov\t[lenoff],edi\t; save the length code offset\n\tmov\tal,80h\t\t; set the length to 0\n\tstosb\t\t\t; save it\n\n??len:\n\tmov\tebx,[lenoff]\t; get the offset of the length code\n\tcmp\t[BYTE PTR ebx],0BFh\t; see if its maxed out\n\tje\t??lenin1\t; if so put out a new len code\n\n??stolen:\n\tinc\t[BYTE PTR ebx] ; inc the count code\n\tlodsb\t\t\t; get the byte\n\tstosb\t\t\t; store it\n\tmov\t[DWORD PTR inlen],1\t; we are now in a length so save it\n\tjmp\tshort ??nxt\t; do the next code\n\n??longrun:\n\tmov\tal,0ffh\t\t; its a long so set a code of FF\n\tstosb\t\t\t; store it\n\n\tmov\teax,[count]\t; send out the count\n\tstosw\t\t\t; store it\n??medrunnxt:\n\tmov\teax,[matchoff] ; get the offset\n\tsub\teax,[a1stsrc]\t; make it relative tot he start of data\n??srunnxt:\n\tstosw\t\t\t; store it\n; this code common to all runs\n\tadd\tesi,[count]\t; add in the length of the run to the source\n\tmov\t[DWORD PTR inlen],0\t; set the in leght flag to false\n\n;=======================================================================\n\n??nxt:\n\tcmp\tesi,[end_of_data]\t\t; see if we did the whole pic\n\tjae\tshort ??out\t\t; if so, cool! were done\n\n\tjmp\t??loop\n\n??out:\n\tmov\tax,080h\t\t; remember to send an end of data code\n\tstosb\t\t\t; store it\n\tmov\teax,edi\t\t; get the last compressed address\n\tsub\teax,[a1stdest]\t; sub the first for the compressed size\n\n\n\tret\n\nENDP\tLCW_Comp\n\n\nEND\n\u001a"
  },
  {
    "path": "CODE/LCWPIPE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LCWPIPE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LCWPIPE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LCWPipe::Flush -- Flushes any partially accumulated block.                                *\n *   LCWPipe::LCWPipe -- Constructor for the LCW processor pipe.                               *\n *   LCWPipe::Put -- Send some data through the LCW processor pipe.                            *\n *   LCWPipe::~LCWPipe -- Deconstructor for the LCW pipe object.                               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"lcwpipe.h\"\n#include\t\"lcw.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * LCWPipe::LCWPipe -- Constructor for the LCW processor pipe.                                 *\n *                                                                                             *\n *    This will initialize the LCWPipe object so that it is prepared for compression or        *\n *    decompression as indicated.                                                              *\n *                                                                                             *\n * INPUT:   decrypt  -- Should decompression be performed?                                     *\n *                                                                                             *\n *          blocksize-- The size of the data blocks to process.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLCWPipe::LCWPipe(CompControl control, int blocksize) :\n\t\tControl(control),\n\t\tCounter(0),\n\t\tBuffer(NULL),\n\t\tBuffer2(NULL),\n\t\tBlockSize(blocksize)\n{\n\tSafetyMargin = BlockSize/128+1;\n\tBuffer = new char[BlockSize+SafetyMargin];\n\tBuffer2 = new char[BlockSize+SafetyMargin];\n\tBlockHeader.CompCount = 0xFFFF;\n}\n\n\n/***********************************************************************************************\n * LCWPipe::~LCWPipe -- Deconstructor for the LCW pipe object.                                 *\n *                                                                                             *\n *    This will free any buffers it may have allocated.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLCWPipe::~LCWPipe(void)\n{\n\tdelete [] Buffer;\n\tBuffer = NULL;\n\n\tdelete [] Buffer2;\n\tBuffer2 = NULL;\n}\n\n\n/***********************************************************************************************\n * LCWPipe::Put -- Send some data through the LCW processor pipe.                              *\n *                                                                                             *\n *    This routine will take the data requested and process it (decompression or compression). *\n *    It does this by accumulating the necessary bytes to make a whole block. Then the block   *\n *    is processed and the entire contents are flushed to the next pipe segment in the chain.  *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the data to be fed to this LCW processor.                   *\n *                                                                                             *\n *          length   -- The number of bytes received.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes output at the far distant final link in    *\n *          the pipe chain.                                                                    *\n *                                                                                             *\n * WARNINGS:   The compression process may be slow as well as consuming two buffers.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LCWPipe::Put(void const * source, int slen)\n{\n\tif (source == NULL || slen < 1) {\n\t\treturn(Pipe::Put(source, slen));\n\t}\n\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tCopy as much as can fit into the buffer from the source data supplied.\n\t*/\n\tif (Control ==  DECOMPRESS) {\n\n\t\twhile (slen > 0) {\n\n\t\t\t/*\n\t\t\t**\tFirst check to see if we are in the block header accumulation phase.\n\t\t\t**\tWhen a whole block header has been accumulated, only then will the regular\n\t\t\t**\tdata processing begin for the block.\n\t\t\t*/\n\t\t\tif (BlockHeader.CompCount == 0xFFFF) {\n\t\t\t\tint len = (slen < (sizeof(BlockHeader)-Counter)) ? slen : (sizeof(BlockHeader)-Counter);\n\t\t\t\tmemmove(&Buffer[Counter], source, len);\n\t\t\t\tsource = ((char *)source) + len;\n\t\t\t\tslen -= len;\n\t\t\t\tCounter += len;\n\n\t\t\t\t/*\n\t\t\t\t**\tA whole block header has been accumulated. Store it for safekeeping.\n\t\t\t\t*/\n\t\t\t\tif (Counter == sizeof(BlockHeader)) {\n\t\t\t\t\tmemmove(&BlockHeader, Buffer, sizeof(BlockHeader));\n\t\t\t\t\tCounter = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tFill the buffer with compressed data until there is enough to make a whole\n\t\t\t**\tdata block.\n\t\t\t*/\n\t\t\tif (slen > 0) {\n\t\t\t\tint len = (slen < (BlockHeader.CompCount-Counter)) ? slen : (BlockHeader.CompCount-Counter);\n\n\t\t\t\tmemmove(&Buffer[Counter], source, len);\n\t\t\t\tslen -= len;\n\t\t\t\tsource = ((char *)source) + len;\n\t\t\t\tCounter += len;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf an entire block has been accumulated, then uncompress it and feed it\n\t\t\t\t**\tthrough the pipe.\n\t\t\t\t*/\n\t\t\t\tif (Counter == BlockHeader.CompCount) {\n\t\t\t\t\tLCW_Uncomp(Buffer, Buffer2);\n\t\t\t\t\ttotal += Pipe::Put(Buffer2, BlockHeader.UncompCount);\n\t\t\t\t\tCounter = 0;\n\t\t\t\t\tBlockHeader.CompCount = 0xFFFF;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tIf the buffer already contains some data, then any new data must be stored\n\t\t**\tinto the staging buffer until a full set has been accumulated.\n\t\t*/\n\t\tif (Counter > 0) {\n\t\t\tint tocopy = (slen < (BlockSize-Counter)) ? slen : (BlockSize-Counter);\n\t\t\tmemmove(&Buffer[Counter], source, tocopy);\n\t\t\tsource = ((char *)source) + tocopy;\n\t\t\tslen -= tocopy;\n\t\t\tCounter += tocopy;\n\n\t\t\tif (Counter == BlockSize) {\n\t\t\t\tint len = LCW_Comp(Buffer, Buffer2, BlockSize);\n\n\t\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\t\tBlockHeader.UncompCount = (unsigned short)BlockSize;\n\t\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t\t\tCounter = 0;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tProcess the source data in whole block chunks until there is insufficient\n\t\t**\tsource data left for a whole data block.\n\t\t*/\n\t\twhile (slen >= BlockSize) {\n\t\t\tint len = LCW_Comp(source, Buffer2, BlockSize);\n\n\t\t\tsource = ((char *)source) + BlockSize;\n\t\t\tslen -= BlockSize;\n\n\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\tBlockHeader.UncompCount = (unsigned short)BlockSize;\n\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is any remaining data, then it is stored into the buffer\n\t\t**\tuntil a full data block has been accumulated.\n\t\t*/\n\t\tif (slen > 0) {\n\t\t\tmemmove(Buffer, source, slen);\n\t\t\tCounter = slen;\n\t\t}\n\t}\n\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * LCWPipe::Flush -- Flushes any partially accumulated block.                                  *\n *                                                                                             *\n *    This routine is called when any buffered data must be flushed out the pipe. For the      *\n *    compression process, this will generate the sub-sized compressed block. For              *\n *    decompression, this routine should not have any data in the buffer. In such a case, it   *\n *    means that the data source was prematurely truncated. In such a case, just dump the      *\n *    accumulated data through the pipe.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of data bytes output to the distant final link in   *\n *          the pipe chain.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LCWPipe::Flush(void)\n{\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tIf there is accumulated data, then it must processed.\n\t*/\n\tif (Counter > 0) {\n\t\tif (Control == DECOMPRESS) {\n\n\t\t\t/*\n\t\t\t**\tIf the accumulated data is insufficient to make a block header, then\n\t\t\t**\tthis means the data has been truncated. Just dump the data through\n\t\t\t**\tas if were already decompressed.\n\t\t\t*/\n\t\t\tif (BlockHeader.CompCount == 0xFFFF) {\n\t\t\t\ttotal += Pipe::Put(Buffer, Counter);\n\t\t\t\tCounter = 0;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tThere appears to be a partial block accumulated in the buffer. It would\n\t\t\t**\tbe disastrous to try to decompress the data since there wouldn't be\n\t\t\t**\tthe special end of data code that LCW decompression needs. In this\n\t\t\t**\tcase, dump the data out as if it were already decompressed.\n\t\t\t*/\n\t\t\tif (Counter > 0) {\n\t\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\t\ttotal += Pipe::Put(Buffer, Counter);\n\t\t\t\tCounter = 0;\n\t\t\t\tBlockHeader.CompCount = 0xFFFF;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tA partial block in the compression process is a normal occurrence. Just\n\t\t\t**\tcompress the partial block and output normally.\n\t\t\t*/\n\t\t\tint len = LCW_Comp(Buffer, Buffer2, Counter);\n\n\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\tBlockHeader.UncompCount = (unsigned short)Counter;\n\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t\tCounter = 0;\n\t\t}\n\t}\n\n\ttotal += Pipe::Flush();\n\treturn(total);\n}\n\n"
  },
  {
    "path": "CODE/LCWPIPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LCWPIPE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LCWPIPE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef LCWPIPE_H\n#define LCWPIPE_H\n\n#include\t\"pipe.h\"\n\n\n/*\n**\tPerforms LCW compression/decompression on the data stream that is piped through this\n**\tclass. The data is compressed in blocks so of small enough size to be compressed\n**\tquickly and large enough size to get decent compression rates.\n*/\nclass LCWPipe : public Pipe\n{\n\tpublic:\n\t\ttypedef enum CompControl {\n\t\t\tCOMPRESS,\n\t\t\tDECOMPRESS\n\t\t} CompControl;\n\n\t\tLCWPipe(CompControl, int blocksize=1024*8);\n\t\tvirtual ~LCWPipe(void);\n\n\t\tvirtual int Flush(void);\n\t\tvirtual int Put(void const * source, int slen);\n\n\tprivate:\n\t\t/*\n\t\t**\tThis tells the pipe if it should be decompressing or compressing the data stream.\n\t\t*/\n\t\tCompControl Control;\n\n\t\t/*\n\t\t**\tThe number of bytes accumulated into the staging buffer.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tPointer to the working buffer that compression/decompression will use.\n\t\t*/\n\t\tchar * Buffer;\n\t\tchar * Buffer2;\n\n\t\t/*\n\t\t**\tThe working block size. Data will be compressed in chunks of this size.\n\t\t*/\n\t\tint BlockSize;\n\n\t\t/*\n\t\t**\tLCW compression requires a safety margin when decompressing over itself. This\n\t\t**\tmargin is only for the worst case situation (very rare).\n\t\t*/\n\t\tint SafetyMargin;\n\n\t\t/*\n\t\t**\tEach block has a header of this format.\n\t\t*/\n\t\tstruct {\n\t\t\tunsigned short CompCount;\t\t// Size of data block (compressed).\n\t\t\tunsigned short UncompCount;\t// Bytes of uncompressed data it represents.\n\t\t} BlockHeader;\n\n\t\tLCWPipe(LCWPipe & rvalue);\n\t\tLCWPipe & operator = (LCWPipe const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/LCWSTRAW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LCWSTRAW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LCWSTRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LCWStraw::Get -- Fetch data through the LCW processor.                                    *\n *   LCWStraw::LCWStraw -- Constructor for LCW straw object.                                   *\n *   LCWStraw::~LCWStraw -- Destructor for the LCW straw.                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"lcwstraw.h\"\n#include\t\"lcw.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * LCWStraw::LCWStraw -- Constructor for LCW straw object.                                     *\n *                                                                                             *\n *    This will initialize the LCW straw object. Whether the object is to compress or          *\n *    decompress and the block size to use is specified. The data is compressed in blocks      *\n *    that are sized to be quick to compress and yet still yield good compression ratios.      *\n *                                                                                             *\n * INPUT:   decrypt  -- Should the data be decompressed?                                       *\n *                                                                                             *\n *          blocksize-- The size of the blocks to process.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   It takes two buffers of the blocksize specified if compression is to be         *\n *             performed.                                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLCWStraw::LCWStraw(CompControl control, int blocksize) :\n\t\tControl(control),\n\t\tCounter(0),\n\t\tBuffer(NULL),\n\t\tBuffer2(NULL),\n\t\tBlockSize(blocksize)\n{\n\tSafetyMargin = BlockSize/128+1;\n\tBuffer = new char[BlockSize+SafetyMargin];\n\tif (control == COMPRESS) {\n\t\tBuffer2 = new char[BlockSize+SafetyMargin];\n\t}\n}\n\n\n/***********************************************************************************************\n * LCWStraw::~LCWStraw -- Destructor for the LCW straw.                                        *\n *                                                                                             *\n *    The destructor will free up the allocated buffers that it allocated in the constructor.  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLCWStraw::~LCWStraw(void)\n{\n\tdelete [] Buffer;\n\tBuffer = NULL;\n\n\tdelete [] Buffer2;\n\tBuffer2 = NULL;\n}\n\n\n/***********************************************************************************************\n * LCWStraw::Get -- Fetch data through the LCW processor.                                      *\n *                                                                                             *\n *    This routine will fetch the data bytes specified. It does this by first accumulating     *\n *    a full block of data and then compressing or decompressing it as indicated. Subsequent   *\n *    requests for data will draw from this buffer of processed data until it is exhausted     *\n *    and another block must be fetched.                                                       *\n *                                                                                             *\n * INPUT:   destbuf  -- Pointer to the buffer to hold the data requested.                      *\n *                                                                                             *\n *          length   -- The number of data bytes requested.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes stored into the buffer. If this number     *\n *          is less than that requested, then this indicates that the data source has been     *\n *          exhausted.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LCWStraw::Get(void * destbuf, int slen)\n{\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tVerify parameters for legality.\n\t*/\n\tif (destbuf == NULL || slen < 1) {\n\t\treturn(0);\n\t}\n\n\twhile (slen > 0) {\n\n\t\t/*\n\t\t**\tCopy as much data is requested and available into the desired\n\t\t**\tdestination buffer.\n\t\t*/\n\t\tif (Counter) {\n\t\t\tint len = (slen < Counter) ? slen : Counter;\n\t\t\tif (Control == DECOMPRESS) {\n\t\t\t\tmemmove(destbuf, &Buffer[BlockHeader.UncompCount-Counter], len);\n\t\t\t} else {\n\t\t\t\tmemmove(destbuf, &Buffer2[(BlockHeader.CompCount+sizeof(BlockHeader))-Counter], len);\n\t\t\t}\n\t\t\tdestbuf = ((char *)destbuf) + len;\n\t\t\tslen -= len;\n\t\t\tCounter -= len;\n\t\t\ttotal += len;\n\t\t}\n\t\tif (slen == 0) break;\n\n\t\tif (Control == DECOMPRESS) {\n\t\t\tint incount = Straw::Get(&BlockHeader, sizeof(BlockHeader));\n\t\t\tif (incount != sizeof(BlockHeader)) break;\n\n\t\t\tvoid * ptr = &Buffer[(BlockSize+SafetyMargin) - BlockHeader.CompCount];\n\t\t\tincount = Straw::Get(ptr, BlockHeader.CompCount);\n\t\t\tif (incount != BlockHeader.CompCount) break;\n\n\t\t\tLCW_Uncomp(ptr, Buffer);\n\t\t\tCounter = BlockHeader.UncompCount;\n\t\t} else {\n\t\t\tBlockHeader.UncompCount = (unsigned short)Straw::Get(Buffer, BlockSize);\n\t\t\tif (BlockHeader.UncompCount == 0) break;\n\t\t\tBlockHeader.CompCount = (unsigned short)LCW_Comp(Buffer, &Buffer2[sizeof(BlockHeader)], BlockHeader.UncompCount);\n\t\t\tmemmove(Buffer2, &BlockHeader, sizeof(BlockHeader));\n\t\t\tCounter = BlockHeader.CompCount+sizeof(BlockHeader);\n\t\t}\n\t}\n\n\treturn(total);\n}\n"
  },
  {
    "path": "CODE/LCWSTRAW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LCWSTRAW.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LCWSTRAW.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef LCWSTRAW_H\n#define LCWSTRAW_H\n\n\n#include\t\"straw.h\"\n\n/*\n**\tThis class handles LCW compression/decompression to the data stream that is drawn through\n**\tthis class. Note that for compression, two internal buffers are required. For decompression\n**\tonly one buffer is required. This changes the memory footprint of this class depending on\n**\tthe process desired.\n*/\nclass LCWStraw : public Straw\n{\n\tpublic:\n\t\ttypedef enum CompControl {\n\t\t\tCOMPRESS,\n\t\t\tDECOMPRESS\n\t\t} CompControl;\n\n\t\tLCWStraw(CompControl control, int blocksize=1024*8);\n\t\tvirtual ~LCWStraw(void);\n\n\t\tvirtual int Get(void * source, int slen);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis tells the pipe if it should be decompressing or compressing the data stream.\n\t\t*/\n\t\tCompControl Control;\n\n\t\t/*\n\t\t**\tThe number of bytes accumulated into the staging buffer.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tPointer to the working buffer that compression/decompression will use.\n\t\t*/\n\t\tchar * Buffer;\n\t\tchar * Buffer2;\n\n\t\t/*\n\t\t**\tThe working block size. Data will be compressed in chunks of this size.\n\t\t*/\n\t\tint BlockSize;\n\n\t\t/*\n\t\t**\tLCW compression requires a safety margin when decompressing over itself. This\n\t\t**\tmargin is only for the worst case situation (very rare).\n\t\t*/\n\t\tint SafetyMargin;\n\n\t\t/*\n\t\t**\tEach block has a header of this format.\n\t\t*/\n\t\tstruct {\n\t\t\tunsigned short CompCount;\t\t// Size of data block (compressed).\n\t\t\tunsigned short UncompCount;\t// Bytes of uncompressed data it represents.\n\t\t} BlockHeader;\n\n\t\tLCWStraw(LCWStraw & rvalue);\n\t\tLCWStraw & operator = (LCWStraw const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/LCWUNCMP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LCWUNCMP.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **    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        **\n ***************************************************************************\n *                                                                         *\n *               Project Name : WESTWOOD LIBRARY (PSX)                     *\n *                                                                         *\n *                 File Name : LCWUNCMP.CPP                                *\n *                                                                         *\n *                Programmer : Ian M. Leslie                               *\n *                                                                         *\n *                Start Date : May 17, 1995                                *\n *                                                                         *\n *               Last Update : May 17, 1995    [IML]                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nextern \"C\" {\n\n/***************************************************************************\n * LCW_UNCOMPRESS -- Decompress an LCW encoded data block.                 *\n *                                                                         *\n * Uncompress data to the following codes in the format b = byte, w = word *\n * n = byte code pulled from compressed data.                              *\n *                                                                         *\n * Command code, n        |Description                                     *\n * ------------------------------------------------------------------------*\n * n=0xxxyyyy,yyyyyyyy    |short copy back y bytes and run x+3   from dest *\n * n=10xxxxxx,n1,n2,...,nx+1|med length copy the next x+1 bytes from source*\n * n=11xxxxxx,w1          |med copy from dest x+3 bytes from offset w1     *\n * n=11111111,w1,w2       |long copy from dest w1 bytes from offset w2     *\n * n=11111110,w1,b1       |long run of byte b1 for w1 bytes                *\n * n=10000000             |end of data reached                             *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *      void * source ptr                                                  *\n *      void * destination ptr                                             *\n *      unsigned long length of uncompressed data                          *\n *                                                                         *\n *                                                                         *\n * OUTPUT:                                                                 *\n *     unsigned long # of destination bytes written                        *\n *                                                                         *\n * WARNINGS:                                                               *\n *     3rd argument is dummy. It exists to provide cross-platform          *\n *      compatibility. Note therefore that this implementation does not    *\n *      check for corrupt source data by testing the uncompressed length.  *\n *                                                                         *\n * HISTORY:                                                                *\n *    03/20/1995 IML : Created.                                            *\n *=========================================================================*/\nunsigned long __cdecl LCW_Uncompress (void * source, void * dest, unsigned long )\n//unsigned long LCW_Uncompress (void * source, void * dest, unsigned long length)\n{\n\tunsigned char * source_ptr, * dest_ptr, * copy_ptr, op_code, data;\n\tunsigned\t  count, * word_dest_ptr, word_data;\n\n\t/* Copy the source and destination ptrs. */\n\tsource_ptr = (unsigned char*) source;\n\tdest_ptr   = (unsigned char*) dest;\n\n\twhile (1 /*TRUE*/) {\n\n\t\t/* Read in the operation code. */\n\t\top_code = *source_ptr++;\n\n\t\tif (!(op_code & 0x80)) {\n\n\t\t\t/* Do a short copy from destination. */\n\t\t\tcount\t = (op_code >> 4) + 3;\n\t\t\tcopy_ptr = dest_ptr - ((unsigned) *source_ptr++ + (((unsigned) op_code & 0x0f) << 8));\n\n\t\t\twhile (count--) *dest_ptr++ = *copy_ptr++;\n\n\t\t} else {\n\n\t\t\tif (!(op_code & 0x40)) {\n\n\t\t\t\tif (op_code == 0x80) {\n\n\t\t\t\t\t/* Return # of destination bytes written. */\n\t\t\t\t\treturn ((unsigned long) (dest_ptr - (unsigned char*) dest));\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/* Do a medium copy from source. */\n\t\t\t\t\tcount = op_code & 0x3f;\n\n\t\t\t\t\twhile (count--) *dest_ptr++ = *source_ptr++;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tif (op_code == 0xfe) {\n\n\t\t\t\t\t/* Do a long run. */\n\t\t\t\t\tcount = *source_ptr + ((unsigned) *(source_ptr + 1) << 8);\n\t\t\t\t\tword_data = data = *(source_ptr + 2);\n\t\t\t\t\tword_data  = (word_data << 24) + (word_data << 16) + (word_data << 8) + word_data;\n\t\t\t\t\tsource_ptr += 3;\n\n\t\t\t\t\tcopy_ptr = dest_ptr + 4 - ((unsigned) dest_ptr & 0x3);\n\t\t\t\t\tcount -= (copy_ptr - dest_ptr);\n\t\t\t\t\twhile (dest_ptr < copy_ptr) *dest_ptr++ = data;\n\n\t\t\t\t\tword_dest_ptr = (unsigned*) dest_ptr;\n\n\t\t\t\t\tdest_ptr += (count & 0xfffffffc);\n\n\t\t\t\t\twhile (word_dest_ptr < (unsigned*) dest_ptr) {\n\t\t\t\t\t\t*word_dest_ptr\t\t= word_data;\n\t\t\t\t\t\t*(word_dest_ptr + 1) = word_data;\n\t\t\t\t\t\tword_dest_ptr += 2;\n\t\t\t\t\t}\n\n\t\t\t\t\tcopy_ptr = dest_ptr + (count & 0x3);\n\t\t\t\t\twhile (dest_ptr < copy_ptr) *dest_ptr++ = data;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif (op_code == 0xff) {\n\n\t\t\t\t\t\t/* Do a long copy from destination. */\n\t\t\t\t\t\tcount\t = *source_ptr + ((unsigned) *(source_ptr + 1) << 8);\n\t\t\t\t\t\tcopy_ptr = (unsigned char*) dest + *(source_ptr + 2) + ((unsigned) *(source_ptr + 3) << 8);\n\t\t\t\t\t\tsource_ptr += 4;\n\n\t\t\t\t\t\twhile (count--) *dest_ptr++ = *copy_ptr++;\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/* Do a medium copy from destination. */\n\t\t\t\t\t\tcount = (op_code & 0x3f) + 3;\n\t\t\t\t\t\tcopy_ptr = (unsigned char*) dest + *source_ptr + ((unsigned) *(source_ptr + 1) << 8);\n\t\t\t\t\t\tsource_ptr += 2;\n\n\t\t\t\t\t\twhile (count--) *dest_ptr++ = *copy_ptr++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "CODE/LED.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\led.h_v   4.42   04 Jul 1996 16:10:40   JOE_BOSTIC  $ */\n\n#ifndef LED_H\n#define LED_H\n\nclass LEDClass\n{\n\tpublic:\n\t\ttypedef enum ControlType {\n\t\t\tLED_NOCHANGE,\t\t\t// Do nothing (just query).\n\t\t\tLED_OFF,\t\t\t\t\t// Turn LED off.\n\t\t\tLED_ON,\t\t\t\t\t// Turn LED on.\n\t\t\tLED_TOGGLE\t\t\t\t// Toggle LED state.\n\t\t} ControlType;\n\n\tprotected:\n\t\tstatic int Shift_Control(ControlType control, char bit);\n\n\tpublic:\n\t\tstatic int Scroll_Lock(ControlType control=LED_TOGGLE) {return Shift_Control(control, 0x01);};\n\t\tstatic int Caps_Lock(ControlType control=LED_TOGGLE) {return Shift_Control(control, 0x02);};\n\t\tstatic int Num_Lock(ControlType control=LED_TOGGLE) {return Shift_Control(control, 0x04);};\n\n\tprivate:\n\t\tstatic void Send_To_Keyboard(unsigned char val);\n};\n\n#endif\n"
  },
  {
    "path": "CODE/LIBRARY.TXT",
    "content": "Guys, in the interests of proceeding with a meaningful discussion I have decided to distill the coding standards group down even more, in fact to this email group. I have collated input from some of you into this message for further discussion \"offline\". We'll meet again (with the group of 7) on Feb 22 to discuss the revised \"coding standards\" document in its entirety rather than going through it piecemeal. I think this will lead to much more expeditious results. We will refer to our standard as the \"Westwood Coding Standard\". This can (and will) differ from K&R and we should not allow ourselves to get hung up on this distinction. We are building a set of rules which is contemporary and practical, it is our coding standard and we can do what we like with it. We will endeavor to limit ourselves to the bounds of reason, however. This group has enough experience to ensure that.\n\nGOAL: We should define a rigid set of parameters for source code layout for the following reasons:\n\nA. clarity -- esp. for someone unfamiliar with the code.\nB. consistency -- structure and scope should be clear by merely\nexamining structure/indenting without forcing the reader to analyze the code. i.e. no structure/indent exceptions.\nC. maintainability -- strive for minimal coding traps or hidden\ngotchas. Since maintenance coding could be done by someone who is unfamiliar with the code, it is very important that \nstructure/indenting rules don't force additional burdens.\nD. ease of use -- structure and brace rules should be easy to\ntype and edit. Programmers are generally reluctant to perform unnecessary typing and recognizing this, is a legitimate concern.\n\nRULES:\n1. Indenting should consistently indicate code structure. In other words, it should be possible to immediately detect the line that controls execution of a code block by merely scanning back until the first line of indent change. This addresses goals A, B, and C.\n\nGOOD EXAMPLE:\nswitch(a) {\ncase X:\nbreak;\ncase Y:\nbreak;\n}\n\nBAD EXAMPLE:\nswitch(a) {\ncase X:\nbreak;\ncase Y:\nbreak;\n}\n\n\n2. Braces placement should tightly coupled to the controlling statement. In other words, the brace should not be distant from the \"if\", \"else\", \"do\", or \"switch\". By far the most difficult to maintain is separating the \"else\" from the preceding \"}\". The greater the distance between the \"}\" and the \"else\", the greater the obscurity of the code's structure and flow.\n\nGOOD EXAMPLE:\nif (a) {\nbla;\n} else {\nbla;\n}\n\nBAD EXAMPLE:\nif (a) {\nbla;\n}\n...\n...\n...\n// This code block is intimately tied to the preceding \"if\", // but the separation obscures this. Worse yet, depending on\n// the size of the comments, the \"else\" may not even be visible // on the screen. This violates goals A and C.\nelse {\nbla;\n}\n\nHowever,\n\nif (a) {\nstatement1;\n} else if (b) {\nstatement 2;\n} else if (c) {\nstatement 3;\n}\n\nis preferable to:\n\nif (a) {\nstatement1;\n} else {\nif (b) {\nstatement 2;\n} else {\nif (c) {\nstatement 3;\n}\n}\n}\n\nEven though this violates A:  It is not clear because if the if statements are complicated they will consistently go off the right edge of the screen, obsucuring your view of them...\n\nThis also seems to be a slight variation of B:  The scope of the if statements could all be the same.  There is no inherent need to change scope, so changing scope promotes extra unneeded lines (you can't see as much code this way).\n\n3. Code lines with the same level of indention should have minimal interdependence. In other words, it should be possible to insert lines in a block of similarly indented code with minimal to no danger of breakage. This addresses goals A, B, C, and D. The second example in rule #2 demonstrates the problem. By looking at the \"if\" it would appear that code could be safely added past the \"}\", however, this would cause an error. The programmer cannot trust the indent level in this example and is thus forced to examine the subsequent code in order to look for this trap.\n\n4. Place the braces on the same line with the control structure that it is attached to. This cuts down on the number of code lines without obscuring the structure. Less code lines means more code is visible on the screen at any one time. This addresses goals A, C, and to some extend D. This also inherently solves rule #2.\n\n5. Always enclose code blocks in braces after an \"if\", \"else\", \"do\", or \"while\" statement. Doing so helps with code maintenance (goal C) and makes the control structures consistently coded (goal B).\n\nGOOD EXAMPLE:\nif (a) {\nbla;\n}\n\nBAD EXAMPLE:\nif (a)\nbla;\n\n...or...\n\nif (a)\nif (b)\nbla;\nelse           // Confusing as to which \"if\" it is attached to.\nbla;\n\n"
  },
  {
    "path": "CODE/LINK.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LINK.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LINK.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 19, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LinkClass::Add -- This object adds itself to the given list                               *\n *   LinkClass::Add_Head -- This gadget makes itself the head of the given list.               *\n *   LinkClass::Add_Tail -- Add myself to the end of the given list.                           *\n *   LinkClass::Get_Next -- Fetches the next object in list.                                   *\n *   LinkClass::Get_Prev -- Fetches previous object in linked list.                            *\n *   LinkClass::Head_Of_List -- Finds the head of the list.                                    *\n *   LinkClass::LinkClass -- Copy constructor for linked list object.                          *\n *   LinkClass::Remove -- Removes the specified object from the list.                          *\n *   LinkClass::Tail_Of_List -- Scans for the object at the end of the list.                   *\n *   LinkClass::Zap -- Forces the link pointers to NULL.                                       *\n *   LinkClass::operator= -- Assignment operator for linked list class object.                 *\n *   LinkClass::~LinkClass -- Default destructor for linked list object.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include \"link.h\"\n\n\n/***********************************************************************************************\n * LinkClass::LinkClass -- Copy constructor for linked list object.                            *\n *                                                                                             *\n *    This copy constructor, unlike the assignment operator, doesn't have to deal with an      *\n *    already initialized and legal link object to the left of the \"=\". It merely puts the     *\n *    destination object into the same list as the source object.                              *\n *                                                                                             *\n * INPUT:   link  -- Reference to the object on the right of the \"=\".                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass::LinkClass(LinkClass const & link) :\n\tNext(0), Prev(0)\n{\n\t/*\n\t**\tAdd this object to the same list that the copy object\n\t**\tresides in.\n\t*/\n\tAdd((LinkClass &)link);\n}\n\n\n/***********************************************************************************************\n * LinkClass::~LinkClass -- Default destructor for linked list object.                         *\n *                                                                                             *\n *    This default destructor will remove the object from any linked list it may be part of.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass::~LinkClass(void)\n{\n\tRemove();\n}\n\n\n/***********************************************************************************************\n * LinkClass::Zap -- Forces the link pointers to NULL.                                         *\n *                                                                                             *\n *    This routine will \"zap\" out the link pointers. This is usually necessary when the link   *\n *    pointers start in an undefined state, but we KNOW that they aren't pointing to anything  *\n *    valid. In such a case it becomes necessary to zap them so that when the object is added  *\n *    to a list, it will be added correctly.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid LinkClass::Zap(void)\n{\n\tNext = 0;\n\tPrev = 0;\n}\n\n\n/***********************************************************************************************\n * LinkClass::operator= -- Assignment operator for linked list class object.                   *\n *                                                                                             *\n *    The assignment operator makes sure that the previous and next pointers remain valid.     *\n *    Because this class only consists of pointers, the assignment operator doesn't actually   *\n *    transfer any data from the source object. It merely makes the destination object part    *\n *    of the same list as the source object. In essence, this is transferring information      *\n *    but not the actual values.                                                               *\n *                                                                                             *\n *    If the destination object is already part of another list, it is removed from that list  *\n *    before being added to the source object's list. This ensures that either list remains    *\n *    in a valid condition.                                                                    *\n *                                                                                             *\n * INPUT:   link  -- The object to the right of the \"=\" operator.                              *\n *                                                                                             *\n * OUTPUT:  Returns a reference to the rightmost object -- per standard assignment rules.      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & LinkClass::operator = (LinkClass const & link)\n{\n\tif (&link == this) return(*this);\n\n\tRemove();\n\tAdd((LinkClass &)link);\n\n\treturn(*this);\n}\n\n\n/***********************************************************************************************\n * LinkClass::Get_Next -- Fetches the next object in list.                                     *\n *                                                                                             *\n *    This routine will return with a pointer to the next object in the list. If there are     *\n *    no more objects, then NULL is returned.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with pointer to next object in list or NULL if at end of list.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass * LinkClass::Get_Next(void) const\n{\n\treturn(Next);\n}\n\n\n/***********************************************************************************************\n * LinkClass::Get_Prev -- Fetches previous object in linked list.                              *\n *                                                                                             *\n *    Use this routine to get a pointer to the previous object in the linked list. If there    *\n *    are no previous objects (such as at the head of the list), then NULL is returned.        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the previous object in the list or NULL if none.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass * LinkClass::Get_Prev(void) const\n{\n\treturn(Prev);\n}\n\n\n/***********************************************************************************************\n * LinkClass::Head_Of_List -- Finds the head of the list.                                      *\n *                                                                                             *\n *    Use this routine to scan for and return a reference to the object at the head of the     *\n *    list.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the object at the head of the list.                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & LinkClass::Head_Of_List(void)\n{\n\tLinkClass * link = this;\n\twhile (link->Prev) {\n\t\tlink = link->Prev;\n\t\tif (link == this) break;\t\t// Safety check\n\t}\n\treturn(*link);\n}\n\n\n/***********************************************************************************************\n * LinkClass::Tail_Of_List -- Scans for the object at the end of the list.                     *\n *                                                                                             *\n *    Use this routine to scan for and return a reference to the object at the end of the      *\n *    list.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the object at the end of the list.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & LinkClass::Tail_Of_List(void)\n{\n\tLinkClass * link = this;\n\twhile (link->Next) {\n\t\tlink = link->Next;\n\t\tif (link == this) break;\t\t// Safety check\n\t}\n\treturn(*link);\n}\n\n\n/***********************************************************************************************\n * LinkClass::Add -- This object adds itself to the given list                                 *\n *                                                                                             *\n *    Use this routine to add a link object to the list, but to be added right after the       *\n *    given link. This allows inserting a link in the middle of the chain. A quite necessary   *\n *    ability if the chain is order dependant (e.g., the gadget system).                       *\n *                                                                                             *\n * INPUT:   list -- gadget object to add this one to                                           *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the head of the list.                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & LinkClass::Add(LinkClass & list)\n{\n\tLinkClass * ptr;\n\n\t/*\n\t**\tSave ptr to next gadget.\n\t*/\n\tptr = list.Next;\n\n\t/*\n\t**\tLink myself in after 'list'.\n\t*/\n\tlist.Next = this;\n\tPrev = &list;\n\n\t/*\n\t**\tLink myself to next gadget, if there is one.\n\t*/\n\tNext = ptr;\n\tif (ptr) {\n\t\tptr->Prev = this;\n\t}\n\n\treturn(Head_Of_List());\n}\n\n\n/***********************************************************************************************\n * LinkClass::Add_Head -- This gadget makes itself the head of the given list.                 *\n *                                                                                             *\n * INPUT:   list -- the list to make myself the head of                                        *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the object at the head of the list. This should be     *\n *          the same object that is passed in.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & LinkClass::Add_Head(LinkClass & list)\n{\n\tLinkClass * ptr;\n\n\t/*\n\t**\tGet head of given list.\n\t*/\n\tptr = &list.Head_Of_List();\n\n\t/*\n\t**\tLink myself in front of it.\n\t*/\n\tptr->Prev = this;\n\tNext = ptr;\n\tPrev = NULL;\n\n\treturn(*this);\n}\n\n\n/***********************************************************************************************\n * LinkClass::Add_Tail -- Add myself to the end of the given list.                             *\n *                                                                                             *\n * INPUT:   list -- list to add myself to                                                      *\n *                                                                                             *\n * OUTPUT:  the head of the list                                                               *\n *                                                                                             *\n * WARNINGS:   The previous and next pointers for the added object MUST have been properly     *\n *             initialized for this routine to work correctly.                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & LinkClass::Add_Tail(LinkClass & list)\n{\n\tLinkClass * ptr;\n\n\t/*\n\t**\tGet head of given list.\n\t*/\n\tptr = &list.Tail_Of_List();\n\n\t/*\n\t**\tLink myself in front of it.\n\t*/\n\tptr->Next = this;\n\tPrev = ptr;\n\tNext = NULL;\n\n\treturn(Head_Of_List());\n}\n\n\n/***********************************************************************************************\n * LinkClass::Remove -- Removes the specified object from the list.                            *\n *                                                                                             *\n *    This routine will remove the specified object from the list of objects. Because of the   *\n *    previous and next pointers, it is possible to remove an object from the list without     *\n *    knowing the head of the list. To do this, just call Remove() with the parameter of       *\n *    \"this\".                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the new head of list.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass * LinkClass::Remove(void)\n{\n\tLinkClass * head = &Head_Of_List();\n\tLinkClass * tail = &Tail_Of_List();\n\n\tif (Prev) {\n\t\tPrev->Next = Next;\n\t}\n\tif (Next) {\n\t\tNext->Prev = Prev;\n\t}\n\tPrev = 0;\n\tNext = 0;\n\n\tif (head==this) {\n\t\tif (tail==this) {\n\t\t\treturn(0);\n\t\t}\n\t\treturn(&tail->Head_Of_List());\n\t}\n\treturn(head);\n}\n\n\n"
  },
  {
    "path": "CODE/LINK.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LINK.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LINK.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef LINK_H\n#define LINK_H\n\n\n/*\n**\tThis implements a simple linked list. It is possible to add, remove, and traverse the\n**\tlist. Since this is a doubly linked list, it is possible to remove an entry from the\n**\tmiddle of an existing list.\n*/\nclass LinkClass\n{\n\tpublic:\n\t\tLinkClass(NoInitClass const &) {};\n\t\tLinkClass(void) : Next(0), Prev(0) {};\n\t\tvirtual ~LinkClass(void);\n\n\t\tvirtual LinkClass * Get_Next(void) const;\n\t\tvirtual LinkClass * Get_Prev(void) const;\n\t\tvirtual LinkClass & Add(LinkClass & object);\n\t\tvirtual LinkClass & Add_Tail(LinkClass & object);\n\t\tvirtual LinkClass & Add_Head(LinkClass & object);\n\t\tvirtual LinkClass & Head_Of_List(void);\n\t\tvirtual LinkClass & Tail_Of_List(void);\n\t\tvirtual void Zap(void);\n\t\tvirtual LinkClass * Remove(void);\n\n\t\tLinkClass & operator=(LinkClass const & link);\t\t// Assignment operator.\n\t\tLinkClass(LinkClass const & link);\t\t\t\t\t\t// Copy constructor.\n\n\tprivate:\n\t\t/*\n\t\t**\tPointers to previous and next link objects in chain.\n\t\t*/\n\t\tLinkClass * Next;\n\t\tLinkClass * Prev;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/LINT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LINT.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LINT.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/28/96                                                     *\n *                                                                                             *\n *                  Last Update : March 28, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n// overloading data member (e.g., IsToRedraw)\n//lint -e1516\n\n// function distinguishing error (actually not an error when conversion operators are used).\n//lint -e1053\n\n\n/*\n**\tThe current version of Lint doesn't know how to deal with conversion operators. It\n**\terroneously generates this error message as a result. Unfortunately, we have to throw\n**\tout the baby with the bathwater on this one.\n*/\n//lint -e58 -e56\n\n/*\n**\tHiding a non virtual member function is generally ok.\n*/\n//lint -e1511\n\n/*\n**\tThe warning about not initializing a member during construction is\n**\tvalid. However, C&C takes advantage of this by using the in place\n**\tnew operator during the load game process. Disable the warning, but\n**\tgrudgingly.\n*/\n//lint -e1401\n\n/*\n**\tDisable warning about non virtual base class destructor for these objects.\n*/\n//lint -esym(1509,GraphicBufferClass,GraphicViewPortClass,BufferClass,VideoViewPortClass,GetCDClass)\n//lint -esym(1509,BasicTimerClass,FlyClass,FuseClass,StageClass,FlasherClass,CargoClass,DoorClass)\n//lint -esym(1509,AbstractTypeClass)\n\n/*\n** The \"unusual cast\" warning is the result of derived casting. This is\n** because there is no \"dynamic_cast<>\" implemented in Watcom (version 10.5).\n*/\n//lint -e740 -e571\n\n/*\n**\t\"function not previously declared inline\" is probably not worth noting.\n*/\n//lint -e1727\n\n/*\n**\tAllow sub-integer loss of precision. This will allow assigning ints to\n**\tchars without warning.\n*/\n//lint -e734\n\n/*\n**\tShifting an integer left is always ok.\n*/\n//lint -e701 -e703\n\n/*\n**\tAllow repeated include files. The body of the include file should be\n**\tcoded to ensure that it is processed only once.\n*/\n//lint -e537\n\n/*\n**\tImplicitly converting an enum to an integer is almost always ok.\n*/\n//lint -e641\n\n/*\n**\tIt is possible to have template functions for \"++\" and \"--\" that\n**\tdon't require one of the parameters to be a class object.\n*/\n//lint -e1042\n\n/*\n**\tRedundant declarations are ok. They are a bit harder to maintain,\n**\tbut they facilitate keeping modules less interdependant (include\n**\tfile wise).\n*/\n//lint -e963 -e762 -e763\n\n/*\n**\tNot having a default constructor is ok.\n*/\n//lint -e1712\n\n/*\n**\tPrivate constructors are ok. In fact, they are necessary if the\n**\tclass object must never be instantiated outside of the class\n**\titself.\n*/\n//lint -e1704\n\n/*\n**\tIgnoring the return value from a function is ok. It is very\n**\tcommon for certain side-effect type functions.\n*/\n//lint -e534\n\n/*\n**\tImplicitly converting from a signed to an unsigned parameter (or\n**\tvisa versa) is ok.\n*/\n//lint -e732 -e502 -e713 -e737 -eau\n\n/*\n**\tAllow functions to overload and hide base functions. This is a\n**\ttechnique of inheritance that handles function parameter changes.\n*/\n//lint -e1411\n\n/*\n**\tIf a switch statement doesn't have a case for every value (enums)\n**\tbut it does have a \"default\" case, then don't warn about it.\n*/\n//lint -e788\n\n/*\n**\tIf bitwize arithmetic is performed on compatible enumeration types,\n**\tthen don't complain. Many enums are used in this fashion.\n*/\n//lint -e655 -e656\n\n/*\n**\tIf a data member is not explicitly initialized in the initializer\n**\tlist, this is ok.\n*/\n//lint -e1542\n\n/*\n**\tCalling \"new\" when not part of an assignment operation can be valid. This\n**\tis true if the \"new\" operator has been overloaded and the class keeps\n**\ttrack of itself.\n*/\n//lint -e522\n\n/*\n**\tA class that is zero bytes long is ok. This is how method classes\n**\tusually work.\n*/\n//lint -e1501\n\n/*\n**\tBoolean passed to function is ok.\n*/\n//lint -e730\n\n/*\n**\tSigned/unsigned mix with relational... ignore for now.\n*/\n//lint -e574\n\n"
  },
  {
    "path": "CODE/LIST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LIST.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LIST.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 23, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ListClass::Add -- This object adds itself to the given list                               *\n *   ListClass::Add_Head -- This gadget makes itself the head of the given list.               *\n *   ListClass::Add_Item -- Adds a text item (as number) to the list box.                      *\n *   ListClass::Add_Item -- Adds an item to the list box.                                      *\n *   ListClass::Add_Scroll_Bar -- Adds a scroll bar to the list box.                           *\n *   ListClass::Add_Tail -- Add myself to the end of the given list.                           *\n *   ListClass::Bump -- Bumps the list box up/down one \"page\".                                 *\n *   ListClass::Current_Index -- Fetches the current selected index.                           *\n *   ListClass::Current_Item -- Fetches pointer to current item string.                        *\n *   ListClass::Draw_Entry -- Draws a list box text line as indicated.                         *\n *   ListClass::Draw_Me -- Draws the listbox.                                                  *\n *   ListClass::Get_Item -- Fetches an arbitrary item string.                                  *\n *   ListClass::Peer_To_Peer -- A peer gadget was touched -- make adjustments.                 *\n *   ListClass::Remove -- Removes the specified object from the list.                          *\n *   ListClass::Remove_Item -- Remove specified text from list box.                            *\n *   ListClass::Remove_Scroll_Bar -- Removes the scroll bar if present                         *\n *   ListClass::Set_Selected_Index -- Set the top of the listbox to index specified.           *\n *   ListClass::Set_Tabs -- Sets the tab stop list to be used for text printing.               *\n *   ListClass::Set_View_Index -- Sets the top line for the current list view.                 *\n *   ListClass::Step -- Moves the list view one line in direction specified.                   *\n *   ListClass::Step_Selected_Index -- Change the listbox top line in direction specified.     *\n *   ListClass::~ListClass -- Destructor for list class objects.                               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***************************************************************************\n * ListClass::ListClass -- class constructor                               *\n *                                                                         *\n * INPUT:            id               button ID                            *\n *                                                                         *\n *                     x,y            upper-left corner, in pixels         *\n *                                                                         *\n *                     w,h            width, height, in pixels             *\n *                                                                         *\n *                     list            ptr to array of char strings to list*\n *                                                                         *\n *                   flags, style   flags for mouse, style of listbox      *\n *                                                                         *\n * OUTPUT:           none.                                                 *\n *                                                                         *\n * WARNINGS:         none.                                                 *\n *                                                                         *\n * HISTORY:          01/05/1995 MML : Created.                             *\n *=========================================================================*/\nListClass::ListClass (int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down) :\n\tControlClass(id, x, y, w, h, LEFTPRESS | LEFTRELEASE | KEYBOARD, false),\n\tUpGadget(0, up, x+w, y),\n\tDownGadget(0, down, x+w, y+h),\n\tScrollGadget(0, x+w, y, 0, h, true)\n{\n\t/*\n\t**\tSet preliminary values for the slider related gadgets. They don't automatically\n\t**\tappear at this time, but there are some values that can be pre-filled in.\n\t*/\n\tUpGadget.X -= UpGadget.Width;\n\tDownGadget.X -= DownGadget.Width;\n\tDownGadget.Y -= DownGadget.Height;\n\tScrollGadget.X -= max(UpGadget.Width, DownGadget.Width);\n\tScrollGadget.Y = Y+UpGadget.Height;\n\tScrollGadget.Height -= UpGadget.Height + DownGadget.Height;\n\tScrollGadget.Width = max(UpGadget.Width, DownGadget.Width);\n\n\t/*\n\t**\tSet the list box to a default state.\n\t*/\n\tTextFlags = flags;\n\tIsScrollActive = false;\n\tTabs = 0;\n\tSelectedIndex = 0;\n\tCurrentTopIndex = 0;\n\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TextFlags);\n\tLineHeight = FontHeight+FontYSpacing-1;\n\tLineCount = (h-1) / LineHeight;\n}\n\n\nListClass::ListClass(ListClass const & list) :\n\tControlClass(list),\n\tTextFlags(list.TextFlags),\n\tTabs(list.Tabs),\n\tList(list.List),\n\tLineHeight(list.LineHeight),\n\tLineCount(list.LineCount),\n\tIsScrollActive(list.IsScrollActive),\n\tUpGadget(list.UpGadget),\n\tDownGadget(list.DownGadget),\n\tScrollGadget(list.ScrollGadget),\n\tSelectedIndex(list.SelectedIndex),\n\tCurrentTopIndex(list.CurrentTopIndex)\n{\n\tUpGadget.Make_Peer(*this);\n\tDownGadget.Make_Peer(*this);\n\tScrollGadget.Make_Peer(*this);\n}\n\n\nvoid ListClass::Set_Position(int x, int y)\n{\n\tUpGadget.X = x + Width - UpGadget.Width;\n\tUpGadget.Y = y;\n\tDownGadget.X = x + Width - DownGadget.Width;\n\tDownGadget.Y = y + Height - DownGadget.Height;\n\tScrollGadget.X = x + Width - max(UpGadget.Width, DownGadget.Width);\n\tScrollGadget.Y = y + UpGadget.Height;\n\tScrollGadget.Height = Height - (UpGadget.Height + DownGadget.Height);\n\tScrollGadget.Width = max(UpGadget.Width, DownGadget.Width);\n}\n\n\n/***********************************************************************************************\n * ListClass::~ListClass -- Destructor for list class objects.                                 *\n *                                                                                             *\n *    This is the destructor for list objects. It handles removing anything it might have      *\n *    allocated. This is typically the scroll bar.                                             *\n *                                                                                             *\n * INPUT:      none                                                                            *\n * OUTPUT:     none                                                                            *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/16/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nListClass::~ListClass(void)\n{\n\tRemove_Scroll_Bar();\n}\n\n\n/***********************************************************************************************\n * ListClass::Add_Item -- Adds an item to the list box.                                        *\n *                                                                                             *\n *    This will add the specified string to the list box. The string is added to the end       *\n *    of the list.                                                                             *\n *                                                                                             *\n * INPUT:      text  -- Pointer to the string to add to the list box.                          *\n * OUTPUT:     none                                                                            *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/15/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nint ListClass::Add_Item(char const * text)\n{\n\tif (text) {\n\t\tList.Add(text);\n\t\tFlag_To_Redraw();\n\n\t\t/*\n\t\t**\tAdd scroll gadget if the list gets too large to display all of the items\n\t\t**\tat the same time.\n\t\t*/\n\t\tif (List.Count() > LineCount) {\n\t\t\tAdd_Scroll_Bar();\n\t\t}\n\n\t\t/*\n\t\t**\tTell the slider that there is one more entry in the list.\n\t\t*/\n\t\tif (IsScrollActive) {\n\t\t\tScrollGadget.Set_Maximum(List.Count());\n\t\t}\n\t}\n\treturn(List.Count() - 1);\n}\n\n\n/***********************************************************************************************\n * ListClass::Add_Item -- Adds a text item (as number) to the list box.                        *\n *                                                                                             *\n *    This will add the text as specified by the text number provided, to the list box.        *\n *    The string is added to the end of the list.                                              *\n *                                                                                             *\n * INPUT:      text  -- The text number for the string to add to the list box.                 *\n * OUTPUT:     none                                                                            *\n * WARNINGS:   Once a string is added to the list box in this fashion, there is no method of   *\n *             retrieving the text number as it relates to any particular index in the list.   *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ListClass::Add_Item(int text)\n{\n\tif (text != TXT_NONE) {\n\t\tAdd_Item(Text_String(text));\n\t}\n\treturn(List.Count() - 1);\n}\n\n\nvoid ListClass::Remove_Item(int index)\n{\n\tif ((unsigned)index < List.Count()) {\n\t\tList.Delete(index);\n\n\t\t/*\n\t\t**\tIf the list is now small enough to display completely within the list box region,\n\t\t**\tthen delete the slider gadget (if they are present).\n\t\t*/\n\t\tif (List.Count() <= LineCount) {\n\t\t\tRemove_Scroll_Bar();\n\t\t}\n\n\t\t/*\n\t\t**\tTell the slider that there is one less entry in the list.\n\t\t*/\n\t\tif (IsScrollActive) {\n\t\t\tScrollGadget.Set_Maximum(List.Count());\n\t\t}\n\n\t\t/*\n\t\t** If we just removed the selected entry, select the previous one\n\t\t*/\n\t\tif (SelectedIndex >= List.Count()) {\n\t\t\tSelectedIndex--;\n\t\t\tif (SelectedIndex < 0) {\n\t\t\t\tSelectedIndex = 0;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** If we just removed the top-displayed entry, step up one item\n\t\t*/\n\t\tif (CurrentTopIndex >= List.Count()) {\n\t\t\tCurrentTopIndex--;\n\t\t\tif (CurrentTopIndex < 0)\n\t\t\t\tCurrentTopIndex = 0;\n\t\t\tif (IsScrollActive)\n\t\t\t\tScrollGadget.Step(1);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * ListClass::Remove_Item -- Remove specified text from list box.                              *\n *                                                                                             *\n *    This routine will remove the specified text string from the list box.                    *\n *                                                                                             *\n * INPUT:      text  -- Pointer to the string to remove.                                       *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   The text pointer passed into this routine MUST be the same text pointer that    *\n *             was used to add the string to the list.                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ListClass::Remove_Item(char const * text)\n{\n\tif (text) {\n\t\tRemove_Item(List.ID(text));\n\t}\n}\n\n\n/***************************************************************************\n * ListClass::Action -- If clicked on, do this!                            *\n *                                                                         *\n * INPUT:            int flags -- combination of mouse flags indicating    *\n *                                  what action to take.                   *\n *                                                                         *\n * OUTPUT:           bool result.                                          *\n *                                                                         *\n * WARNINGS:         none.                                                 *\n *                                                                         *\n * HISTORY:          01/05/1995 MML : Created.                             *\n *=========================================================================*/\nint ListClass::Action(unsigned flags, KeyNumType & key)\n{\n\tif (flags & LEFTRELEASE) {\n\t\tkey = KN_NONE;\n\t\tflags &= (~LEFTRELEASE);\n\t\tControlClass::Action(flags, key);\n\t\treturn(true);\n\t} else {\n\n\t\t/*\n\t\t** Handle keyboard events here.\n\t\t*/\n\t\tif (flags & KEYBOARD) {\n\n\t\t\t/*\n\t\t\t**\tProcess the keyboard character. If indicated, consume this keyboard event\n\t\t\t**\tso that the edit gadget ID number is not returned.\n\t\t\t*/\n\t\t\tif (key == KN_UP) {\n\t\t\t\tStep_Selected_Index(-1);\n\t\t\t\tkey = KN_NONE;\n\t\t\t} else if (key == KN_DOWN) {\n\t\t\t\tStep_Selected_Index(1);\n\t\t\t\tkey = KN_NONE;\n\t\t\t} else {\n\t\t\t\tflags &= ~KEYBOARD;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tint index = Get_Mouse_Y() - (Y+1);\n\t\t\tindex = index / LineHeight;\n\t\t\tSelectedIndex = CurrentTopIndex + index;\n\t\t\tSelectedIndex = min(SelectedIndex, List.Count()-1);\n\t\t\tif (SelectedIndex == -1) SelectedIndex = 0;\n\t\t}\n\t}\n\treturn(ControlClass::Action(flags, key));\n}\n\n\n/***********************************************************************************************\n * ListClass::Draw_Me -- Draws the listbox.                                                    *\n *                                                                                             *\n *    This routine will render the listbox.                                                    *\n *                                                                                             *\n * INPUT:   forced   -- Should the listbox be redrawn even if it already thinks it doesn't     *\n *                      need to be? This is true when something outside of the gadget system   *\n *                      has trashed the screen.                                                *\n *                                                                                             *\n * OUTPUT:  Was the listbox redrawn?                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ListClass::Draw_Me(int forced)\n{\n\tif (GadgetClass::Draw_Me(forced)) {\n\n\t\t/*\n\t\t**\tTurn off the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Hide_Mouse(X, Y, X+Width, Y+Height);\n\t\t}\n\n\t\tDraw_Box (X, Y, Width, Height, BOXSTYLE_BOX, true);\n\n\t\t/*\n\t\t**\tDraw List.\n\t\t*/\n\t\tif (List.Count()) {\n\t\t\tfor (int index = 0; index < LineCount; index++)  {\n\t\t\t\tint line = CurrentTopIndex + index;\n\n\t\t\t\tif (List.Count() > line) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tPrints the text and handles right edge clipping and tabs.\n\t\t\t\t\t*/\n\t\t\t\t\tDraw_Entry(line, X+1, Y+(LineHeight*index)+1, Width-2, (line == SelectedIndex));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tTurn on the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Show_Mouse();\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ListClass::Bump -- Bumps the list box up/down one \"page\".                                   *\n *                                                                                             *\n *    Use this routine to adjust the \"page\" that is being viewed in the list box. The view     *\n *    will move up or down (as specified) one page (screen full) of text strings.              *\n *                                                                                             *\n * INPUT:   up -- Should the adjustment be up?                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ListClass::Bump(int up)\n{\n\tif (IsScrollActive) {\n\t\tif (ScrollGadget.Step(up)) {\n\t\t\tCurrentTopIndex = ScrollGadget.Get_Value();\n\t\t\tFlag_To_Redraw();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * ListClass::Step -- Moves the list view one line in direction specified.                     *\n *                                                                                             *\n *    This routine will move the current view \"page\" one line in the direction specified.      *\n *                                                                                             *\n * INPUT:   up -- Should the view be moved upward?                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ListClass::Step(int up)\n{\n\tif (IsScrollActive) {\n\t\tif (ScrollGadget.Step(up)) {\n\t\t\tCurrentTopIndex = ScrollGadget.Get_Value();\n\t\t\tFlag_To_Redraw();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * ListClass::Get_Item -- Fetches an arbitrary item string.                                    *\n *                                                                                             *\n *    This routine will fetch an item string from the list box. The item fetched can be any    *\n *    one of the ones in the list.                                                             *\n *                                                                                             *\n * INPUT:   index -- The index to examine and return the text pointer from.                    *\n *                                                                                             *\n * OUTPUT:  Returns with the text pointer to the string at the index position specified.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * ListClass::Get_Item(int index) const\n{\n\tif (List.Count() == 0) {\n\t\treturn NULL;\n\t}\n\tindex = min(index, List.Count()-1);\n\treturn(List[index]);\n}\n\n\n/***********************************************************************************************\n * ListClass::Current_Item -- Fetches pointer to current item string.                          *\n *                                                                                             *\n *    This routine will fetch a pointer to the currently selected item's text.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Return with pointer to currently selected text.                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * ListClass::Current_Item(void) const\n{\n\tif (List.Count() <= SelectedIndex) {\n\t\treturn(0);\n\t}\n\treturn(List[SelectedIndex]);\n}\n\n\n/***********************************************************************************************\n * ListClass::Current_Index -- Fetches the current selected index.                             *\n *                                                                                             *\n *    This routine will fetch the index number for the currently selected line.                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the index of the currently selected line. This ranges from zero to    *\n *          the number of items in the list minus one.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ListClass::Current_Index(void) const\n{\n\treturn(SelectedIndex);\n}\n\n\n/***********************************************************************************************\n * ListClass::Peer_To_Peer -- A peer gadget was touched -- make adjustments.                   *\n *                                                                                             *\n *    This routine is called when one of the peer gadgets (the scroll arrows or the slider)    *\n *    was touched in some fashion. This routine will sort out whom and why and then make       *\n *    any necessary adjustments to the list box.                                               *\n *                                                                                             *\n * INPUT:   flags    -- The event flags that affected the peer gadget.                         *\n *                                                                                             *\n *          key      -- The key value at the time of the event.                                *\n *                                                                                             *\n *          whom     -- Which gadget is being touched.                                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ListClass::Peer_To_Peer(unsigned flags, KeyNumType &, ControlClass & whom)\n{\n\tif (flags & LEFTRELEASE) {\n\t\tif (&whom == &UpGadget) {\n\t\t\tStep(true);\n\t\t}\n\t\tif (&whom == &DownGadget) {\n\t\t\tStep(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tThe slider has changed, so reflect the current list position\n\t**\taccording to the slider setting.\n\t*/\n\tif (&whom == &ScrollGadget) {\n\t\tSet_View_Index(ScrollGadget.Get_Value());\n\t}\n}\n\n\n/***********************************************************************************************\n * ListClass::Set_View_Index -- Sets the top line for the current list view.                   *\n *                                                                                             *\n *    This routine is used to set the line that will be at the top of the list view. This is   *\n *    how the view can be scrolled up and down. This does not affect the currently selected    *\n *    item.                                                                                    *\n *                                                                                             *\n * INPUT:   index -- The line (index) to move to the top of the list view.                     *\n *                                                                                             *\n * OUTPUT:  bool; Was the view actually changed?                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ListClass::Set_View_Index(int index)\n{\n\tindex = Bound(index, 0, max(0, List.Count() - LineCount));\n\tif (index != CurrentTopIndex) {\n\t\tCurrentTopIndex = index;\n\t\tFlag_To_Redraw();\n\t\tif (IsScrollActive) {\n\t\t\tScrollGadget.Set_Value(CurrentTopIndex);\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ListClass::Add_Scroll_Bar -- Adds a scroll bar to the list box.                             *\n *                                                                                             *\n *    This routine will add a scroll bar (with matching arrows) to the list box. They are      *\n *    added to the right edge and cause the interior of the list box to become narrower.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the scroll bar added?                                                    *\n *                                                                                             *\n * WARNINGS:   The list box becomes narrower when the scroll bar is added.                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ListClass::Add_Scroll_Bar(void)\n{\n\tif (!IsScrollActive) {\n\t\tIsScrollActive = true;\n\n\t\t/*\n\t\t**\tEverything has been created successfully. Flag the list box to be\n\t\t**\tredrawn because it now must be made narrower to accomodate the new\n\t\t**\tslider gadgets.\n\t\t*/\n\t\tFlag_To_Redraw();\n\t\tWidth -= ScrollGadget.Width;\n\n\t\t/*\n\t\t**\tTell the newly created gadgets that they should inform this list box\n\t\t**\twhenever they get touched. In this way, the list box will automatically\n\t\t**\tbe updated under control of the slider buttons.\n\t\t*/\n\t\tUpGadget.Make_Peer(*this);\n\t\tDownGadget.Make_Peer(*this);\n\t\tScrollGadget.Make_Peer(*this);\n\n\t\t/*\n\t\t**\tAdd these newly created gadgets to the same gadget list that the\n\t\t**\tlist box is part of.\n\t\t*/\n\t\tUpGadget.Add(*this);\n\t\tDownGadget.Add(*this);\n\t\tScrollGadget.Add(*this);\n\n\t\t/*\n\t\t**\tMake sure these added gadgets get redrawn at the next opportunity.\n\t\t*/\n\t\tUpGadget.Flag_To_Redraw();\n\t\tDownGadget.Flag_To_Redraw();\n\t\tScrollGadget.Flag_To_Redraw();\n\n\t\t/*\n\t\t**\tInform the slider of the size of the window and the current view position.\n\t\t*/\n\t\tScrollGadget.Set_Maximum(List.Count());\n\t\tScrollGadget.Set_Thumb_Size(LineCount);\n\t\tScrollGadget.Set_Value(CurrentTopIndex);\n\n\t\t/*\n\t\t**\tReturn with success flag.\n\t\t*/\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ListClass::Remove_Scroll_Bar -- Removes the scroll bar if present                           *\n *                                                                                             *\n *    Use this routine to remove any attached scroll bar to this list box. If the scroll bar   *\n *    is not present, then no action occurs.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the scroll bar removed?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ListClass::Remove_Scroll_Bar(void)\n{\n\tif (IsScrollActive) {\n\t\tIsScrollActive = false;\n\t\tWidth += ScrollGadget.Width;\n\t\tScrollGadget.Remove();\n\t\tUpGadget.Remove();\n\t\tDownGadget.Remove();\n\t\tFlag_To_Redraw();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ListClass::Set_Tabs -- Sets the tab stop list to be used for text printing.                 *\n *                                                                                             *\n *    This sets the tab stop list to be used for text printing. It specifies a series of       *\n *    pixel offsets for each tab stop. The offsets are from the starting pixel position that   *\n *    the text begins at.                                                                      *\n *                                                                                             *\n * INPUT:   tabs  -- Pointer to a list of tab pixel offsets.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only a pointer to the tabs is recorded by the ListClass object. Make sure that  *\n *             the list remains intact for the duration of the existence of this object.       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ListClass::Set_Tabs(int const * tabs)\n{\n\tTabs = tabs;\n}\n\n\n/***********************************************************************************************\n * ListClass::Draw_Entry -- Draws a list box text line as indicated.                           *\n *                                                                                             *\n *    This routine is called by the Draw_Me function when it desired to redraw a particular    *\n *    text line in the list box.                                                               *\n *                                                                                             *\n * INPUT:   index    -- The index of the list entry to draw. This index is based on the        *\n *                      total list and NOT the current visible view page.                      *\n *                                                                                             *\n *          x,y      -- Pixel coordinates for the upper left corner of the text entry.         *\n *                                                                                             *\n *          width    -- The maximum width that the text may draw over. It is expected that     *\n *                      this drawing routine entirely fills this length.                       *\n *                                                                                             *\n *          selected -- bool; Is this a selected (highlighted) listbox entry?                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n * WARNINGS:   none                                                                            *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ListClass::Draw_Entry(int index, int x, int y, int width, int selected)\n{\n\tTextPrintType flags = TextFlags;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\tif (selected) {\n\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\tLogicPage->Fill_Rect (x, y, x + width - 1, y + LineHeight - 1, scheme->Shadow);\n\t} else {\n\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t}\n\t}\n\n\tConquer_Clip_Text_Print(List[index], x, y, scheme, TBLACK, flags, width, Tabs);\n\n}\n\n\n/***********************************************************************************************\n * ListClass::Add -- Adds myself to list immediately after given object                        *\n *                                                                                             *\n * Adds the list box to the chain, immediately after the given object.  The order will be:     *\n * - Listbox                                                                                   *\n * - Up arrow (if active)                                                                      *\n * - Down arrow (if active)                                                                    *\n * - Scroll gadget (if active)                                                                 *\n *                                                                                             *                                                                                       *\n * INPUT:   object   -- Pointer to the object to be added right after this one.                *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the head of the list.                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & ListClass::Add(LinkClass & list)\n{\n\t/*\n\t**\tAdd the scroll bar gadgets if they're active.\n\t*/\n\tif (IsScrollActive) {\n\t\tScrollGadget.Add(list);\n\t\tDownGadget.Add(list);\n\t\tUpGadget.Add(list);\n\t}\n\n\t/*\n\t**\tAdd myself to the list, then return.\n\t*/\n\treturn(ControlClass::Add(list));\n}\n\n\n/***********************************************************************************************\n * ListClass::Add_Head -- Adds myself to head of the given list                                *\n *                                                                                             *\n * INPUT:   list -- list to add myself to                                                      *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the object at the head of the list. This should be     *\n *          the same object that is passed in.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & ListClass::Add_Head(LinkClass & list)\n{\n\t/*\n\t**\tAdd the scroll bar gadgets if they're active.\n\t*/\n\tif (IsScrollActive) {\n\t\tScrollGadget.Add_Head(list);\n\t\tDownGadget.Add_Head(list);\n\t\tUpGadget.Add_Head(list);\n\t}\n\n\t/*\n\t**\tAdd myself to the list, then return.\n\t*/\n\treturn(ControlClass::Add_Head(list));\n}\n\n\n/***********************************************************************************************\n * ListClass::Add_Tail -- Adds myself to tail of given list                                    *\n *                                                                                             *\n * Adds the list box to the tail of the give chain.  The order will be:                        *\n * - Listbox                                                                                   *\n * - Up arrow (if active)                                                                      *\n * - Down arrow (if active)                                                                    *\n * - Scroll gadget (if active)                                                                 *\n *                                                                                             *\n * INPUT:   list -- list to add myself to                                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The previous and next pointers for the added object MUST have been properly     *\n *             initialized for this routine to work correctly.                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & ListClass::Add_Tail(LinkClass & list)\n{\n\t/*\n\t**\tAdd myself to the list.\n\t*/\n\tControlClass::Add_Tail(list);\n\n\t/*\n\t**\tAdd the scroll bar gadgets if they're active.\n\t*/\n\tif (IsScrollActive) {\n\t\tUpGadget.Add_Tail(list);\n\t\tDownGadget.Add_Tail(list);\n\t\tScrollGadget.Add_Tail(list);\n\t}\n\n\treturn(Head_Of_List());\n}\n\n\n/***********************************************************************************************\n * ListClass::Remove -- Removes the specified object from the list.                            *\n *                                                                                             *\n *    This routine will remove the specified object from the list of objects. Because of the   *\n *    previous and next pointers, it is possible to remove an object from the list without     *\n *    knowing the head of the list. To do this, just call Remove() with the parameter of       *\n *    \"this\".                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the new head of list.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nGadgetClass * ListClass::Remove(void)\n{\n\t/*\n\t**\tRemove the scroll bar if it's active\n\t*/\n\tif (IsScrollActive) {\n\t\tScrollGadget.Remove();\n\t\tDownGadget.Remove();\n\t\tUpGadget.Remove();\n\t}\n\n\t/*\n\t**\tRemove myself & return\n\t*/\n\treturn(ControlClass::Remove());\n}\n\n\n/***********************************************************************************************\n * ListClass::Set_Selected_Index -- Set the top of the listbox to index specified.             *\n *                                                                                             *\n *    This routine will set the top line of the listbox to the index value specified.          *\n *                                                                                             *\n * INPUT:   index -- The index to set the top of the listbox to.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The requested index may be adjusted to fit within legal parameters.             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *   01/23/1996 JLB : Forces selected index to always be zero for a null list.                 *\n *=============================================================================================*/\nvoid ListClass::Set_Selected_Index(int index)\n{\n   if ((unsigned)index < List.Count()) {\n\t\tSelectedIndex = index;\n\t\tFlag_To_Redraw();\n\t\tif (SelectedIndex < CurrentTopIndex) {\n\t\t\tSet_View_Index(SelectedIndex);\n\t\t}\n\t\tif (SelectedIndex >= CurrentTopIndex+LineCount) {\n\t\t\tSet_View_Index(SelectedIndex-(LineCount-1));\n\t\t}\n   } else {\n   \tSelectedIndex = 0;\n   }\n}\n\n\n/***********************************************************************************************\n * ListClass::Step_Selected_Index -- Change the listbox top line in direction specified.       *\n *                                                                                             *\n *    This routine will scroll the top line of the listbox in the direction specified.         *\n *                                                                                             *\n * INPUT:   step  -- The direction (and amount) to adjust the listbox. If negative value, then *\n *                   the top line is scrolled upward.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the original top line index number.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ListClass::Step_Selected_Index(int step)\n{\n\tint old = SelectedIndex;\n\n\tSet_Selected_Index(old + step);\n\treturn(old);\n}\n\n\nvoid ListClass::Flag_To_Redraw(void)\n{\n\tif (IsScrollActive) {\n\t\tUpGadget.Flag_To_Redraw();\n\t\tDownGadget.Flag_To_Redraw();\n\t\tScrollGadget.Flag_To_Redraw();\n\t}\n\tControlClass::Flag_To_Redraw();\n}\n\n\nvoid ListClass::Set_Selected_Index(char const * text)\n{\n\tif (text && List.Count() > 0) {\n\t\tfor (int index = 0; index < List.Count(); index++) {\n\t\t\tif (stricmp(List[index], text) == 0) {\n\t\t\t\tSet_Selected_Index(index);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "CODE/LIST.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LIST.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LIST.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef LIST_H\n#define LIST_H\n\n#include \"control.h\"\n#include \"shapebtn.h\"\n#include \"slider.h\"\n\n\n/***************************************************************************\n * ListClass -- Like a Windows ListBox structure\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:      int x -- x position of gadget\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint y -- y position of gadget\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint w -- width of gadget\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint h -- height of gadget\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tUWORD flags -- see enumeration choices\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t*\n * HISTORY:    01/03/1995 MML : Created.                                   *\n *=========================================================================*/\nclass ListClass : public ControlClass\n{\n\tpublic:\n\t\tListClass(int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down);\n\t\tListClass(ListClass const & list);\n\t\tvirtual ~ListClass(void);\n\n\t\tvirtual int Add_Item(char const * text);\n\t\tvirtual int Add_Item(int text);\n\t\tvirtual int Add_Scroll_Bar(void);\n\t\tvirtual void Bump(int up);\n\t\tvirtual int Count(void) const {return List.Count();};\n\t\tvirtual int Current_Index(void) const;\n\t\tvirtual char const * Current_Item(void) const;\n\t\tvirtual int Draw_Me(int forced);\n\t\tvirtual char const * Get_Item(int index) const;\n\t\tvirtual int Step_Selected_Index(int forward);\n\t\tvirtual void Flag_To_Redraw(void);\n\n\t\tvirtual void Peer_To_Peer(unsigned flags, KeyNumType & key, ControlClass & whom);\n\t\tvirtual void Remove_Item(char const * text);\n\t\tvirtual void Remove_Item(int);\n\t\tvirtual int  Remove_Scroll_Bar(void);\n\t\tvirtual void Set_Selected_Index(int index);\n\t\tvirtual void Set_Selected_Index(char const * text);\n\t\tvirtual void Set_Tabs(int const * tabs);\n\t\tvirtual int  Set_View_Index(int index);\n\t\tvirtual void Step(int up);\n\t\tvirtual void Set_Position(int x, int y);\n\n\t\t/*\n\t\t** These overloaded list routines handle adding/removing the scroll bar\n\t\t** automatically when the list box is added or removed.\n\t\t*/\n\t\tvirtual LinkClass & Add(LinkClass & object);\n\t\tvirtual LinkClass & Add_Tail(LinkClass & object);\n\t\tvirtual LinkClass & Add_Head(LinkClass & object);\n\t\tvirtual GadgetClass * Remove(void);\n\n\tprotected:\n\t\tvirtual int  Action(unsigned flags, KeyNumType &key);\n\t\tvirtual void Draw_Entry(int index, int x, int y, int width, int selected);\n\n\t\t/*\n\t\t**\tThis controls what the text looks like. It uses the basic TPF_ flags that\n\t\t**\tare used to control Fancy_Text_Print().\n\t\t*/\n\t\tTextPrintType TextFlags;\n\n\t\t/*\n\t\t**\tThis is a series of tabstop pixel positions to use when processing any\n\t\t**\t<TAB> characters found in a list box string. The tabs are a series of\n\t\t**\tpixel offsets from the starting pixel position of the text.\n\t\t*/\n\t\tint const *Tabs;\n\n\t\t/*\n\t\t**\tThe actual list of text pointers is maintained by this list manager. The pointers\n\t\t**\tare stored in EMS. The text that is pointed to may also be in EMS.\n\t\t*/\n\t\tDynamicVectorClass<char const *> List;\n\n\t\t/*\n\t\t**\tThis is the total pixel height of a standard line of text. This is greatly\n\t\t**\tinfluenced by the TextFlags value.\n\t\t*/\n\t\tint LineHeight;\n\n\t\t/*\n\t\t**\tThis is the number of text lines that can fit within the list box.\n\t\t*/\n\t\tint LineCount;\n\n\t\t/*\n\t\t**\tIf the slider bar has been created, these point to the respective gadgets\n\t\t**\tthat it is composed of.\n\t\t*/\n\t\tunsigned IsScrollActive:1;\n\t\tShapeButtonClass UpGadget;\n\t\tShapeButtonClass DownGadget;\n\t\tSliderClass ScrollGadget;\n\n\t\t/*\n\t\t**\tThis is the currently selected index. It is highlighted.\n\t\t*/\n\t\tint SelectedIndex;\n\n\t\t/*\n\t\t**\tThis specifies the line (index) that is at the top of the list box.\n\t\t*/\n\t\tint CurrentTopIndex;\n};\n\n\ntemplate<class T>\nclass TListClass : public ControlClass\n{\n\tpublic:\n\t\tTListClass(int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down);\n\t\tTListClass(TListClass<T> const & list);\n\t\tvirtual ~TListClass(void);\n\t\tT operator [] (int index) const {return(List[index]);};\n\t\tT & operator [] (int index) {return(List[index]);};\n\n\t\tvirtual int Add_Item(T text);\n\t\tvirtual int Add_Scroll_Bar(void);\n\t\tvirtual void Insert_Item(T item);\n\t\tvirtual void Bump(int up);\n\t\tvirtual int Count(void) const {return List.Count();};\n\t\tvirtual int Current_Index(void) const;\n\t\tvirtual T Current_Item(void) const;\n\t\tvirtual int Draw_Me(int forced);\n\t\tvirtual int Step_Selected_Index(int forward);\n\t\tvirtual void Flag_To_Redraw(void);\n\t\tvirtual T Get_Item(int index) const {return(List[index]);};\n\n\t\tvirtual void Peer_To_Peer(unsigned flags, KeyNumType & key, ControlClass & whom);\n\t\tvirtual void Remove_Item(T);\n\t\tvirtual void Remove_Index(int);\n\t\tvirtual int  Remove_Scroll_Bar(void);\n\t\tvirtual void Set_Selected_Index(int index);\n\t\tvirtual void Set_Selected_Index(T item);\n\t\tvirtual void Set_Tabs(int const * tabs);\n\t\tvirtual int  Set_View_Index(int index);\n\t\tvirtual void Step(int up);\n\t\tvirtual void Set_Position(int x, int y);\n\n\t\t/*\n\t\t** These overloaded list routines handle adding/removing the scroll bar\n\t\t** automatically when the list box is added or removed.\n\t\t*/\n\t\tvirtual LinkClass & Add(LinkClass & object);\n\t\tvirtual LinkClass & Add_Tail(LinkClass & object);\n\t\tvirtual LinkClass & Add_Head(LinkClass & object);\n\t\tvirtual GadgetClass * Remove(void);\n\n\tprotected:\n\t\tvirtual int  Action(unsigned flags, KeyNumType &key);\n\n\t\t/*\n\t\t**\tThis controls what the text looks like. It uses the basic TPF_ flags that\n\t\t**\tare used to control Fancy_Text_Print().\n\t\t*/\n\t\tTextPrintType TextFlags;\n\n\t\t/*\n\t\t**\tThis is a series of tabstop pixel positions to use when processing any\n\t\t**\t<TAB> characters found in a list box string. The tabs are a series of\n\t\t**\tpixel offsets from the starting pixel position of the text.\n\t\t*/\n\t\tint const * Tabs;\n\n\t\t/*\n\t\t**\tThe actual list of text pointers is maintained by this list manager.\n\t\t*/\n\t\tDynamicVectorClass<T> List;\n\n\t\t/*\n\t\t**\tThis is the total pixel height of a standard line of text. This is greatly\n\t\t**\tinfluenced by the TextFlags value.\n\t\t*/\n\t\tint LineHeight;\n\n\t\t/*\n\t\t**\tThis is the number of text lines that can fit within the list box.\n\t\t*/\n\t\tint LineCount;\n\n\t\t/*\n\t\t**\tIf the slider bar has been created, these point to the respective gadgets\n\t\t**\tthat it is composed of.\n\t\t*/\n\t\tunsigned IsScrollActive:1;\n\t\tShapeButtonClass UpGadget;\n\t\tShapeButtonClass DownGadget;\n\t\tSliderClass ScrollGadget;\n\n\t\t/*\n\t\t**\tThis is the currently selected index. It is highlighted.\n\t\t*/\n\t\tint SelectedIndex;\n\n\t\t/*\n\t\t**\tThis specifies the line (index) that is at the top of the list box.\n\t\t*/\n\t\tint CurrentTopIndex;\n};\n\ntemplate<class T>\nTListClass<T>::TListClass(int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down) :\n\tControlClass(id, x, y, w, h, LEFTPRESS | LEFTRELEASE | KEYBOARD, false),\n\tUpGadget(0, up, x+w, y),\n\tDownGadget(0, down, x+w, y+h),\n\tScrollGadget(0, x+w, y, 0, h, true),\n\tTextFlags(flags),\n\tTabs(0),\n\tIsScrollActive(false),\n\tSelectedIndex(0),\n\tCurrentTopIndex(0)\n{\n\t/*\n\t**\tSet preliminary values for the slider related gadgets. They don't automatically\n\t**\tappear at this time, but there are some values that can be pre-filled in.\n\t*/\n\tUpGadget.X -= UpGadget.Width;\n\tDownGadget.X -= DownGadget.Width;\n\tDownGadget.Y -= DownGadget.Height;\n\tScrollGadget.X -= max(UpGadget.Width, DownGadget.Width);\n\tScrollGadget.Y = Y+UpGadget.Height;\n\tScrollGadget.Height -= UpGadget.Height + DownGadget.Height;\n\tScrollGadget.Width = max(UpGadget.Width, DownGadget.Width);\n\n\t/*\n\t**\tSet the list box to a default state.\n\t*/\n\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TextFlags);\n\tLineHeight = FontHeight+FontYSpacing-1;\n\tLineCount = (h-1) / LineHeight;\n}\n\ntemplate<class T>\nTListClass<T>::TListClass(TListClass<T> const & list) :\n\tControlClass(list),\n\tTextFlags(list.TextFlags),\n\tTabs(list.Tabs),\n\tList(list.List),\n\tLineHeight(list.LineHeight),\n\tLineCount(list.LineCount),\n\tIsScrollActive(list.IsScrollActive),\n\tUpGadget(list.UpGadget),\n\tDownGadget(list.DownGadget),\n\tScrollGadget(list.ScrollGadget),\n\tSelectedIndex(list.SelectedIndex),\n\tCurrentTopIndex(list.CurrentTopIndex)\n{\n\tUpGadget.Make_Peer(*this);\n\tDownGadget.Make_Peer(*this);\n\tScrollGadget.Make_Peer(*this);\n}\n\ntemplate<class T>\nvoid TListClass<T>::Set_Position(int x, int y)\n{\n\tUpGadget.X = x + Width - UpGadget.Width;\n\tUpGadget.Y = y;\n\tDownGadget.X = x + Width - DownGadget.Width;\n\tDownGadget.Y = y + Height - DownGadget.Height;\n\tScrollGadget.X = x + Width - max(UpGadget.Width, DownGadget.Width);\n\tScrollGadget.Y = y + UpGadget.Height;\n\tScrollGadget.Height = Height - (UpGadget.Height + DownGadget.Height);\n\tScrollGadget.Width = max(UpGadget.Width, DownGadget.Width);\n}\n\ntemplate<class T>\nTListClass<T>::~TListClass(void)\n{\n\tRemove_Scroll_Bar();\n}\n\ntemplate<class T>\nvoid TListClass<T>::Insert_Item(T item)\n{\n\tif (Current_Index() >= Count()) {\n\t\tList.Add(item);\n\t} else {\n\t\tList.Add(item);\n\n\t\t/*\n\t\t**\tMove all trailing items upward.\n\t\t*/\n\t\tfor (int index = List.Count()-1; index >= Current_Index(); index--) {\n\t\t\tList[index+1] = List[index];\n\t\t}\n\n\t\t/*\n\t\t**\tInsert the new item into the location at the current index.\n\t\t*/\n\t\tList[Current_Index()] = item;\n\t}\n}\n\n\ntemplate<class T>\nint TListClass<T>::Add_Item(T text)\n{\n//\tif (text) {\n\t\tList.Add(text);\n\t\tFlag_To_Redraw();\n\n\t\t/*\n\t\t**\tAdd scroll gadget if the list gets too large to display all of the items\n\t\t**\tat the same time.\n\t\t*/\n\t\tif (List.Count() > LineCount) {\n\t\t\tAdd_Scroll_Bar();\n\t\t}\n\n\t\t/*\n\t\t**\tTell the slider that there is one more entry in the list.\n\t\t*/\n\t\tif (IsScrollActive) {\n\t\t\tScrollGadget.Set_Maximum(List.Count());\n\t\t}\n//\t}\n\treturn(List.Count() - 1);\n}\n\ntemplate<class T>\nvoid TListClass<T>::Remove_Index(int index)\n{\n\tif ((unsigned)index < List.Count()) {\n\t\tList.Delete(index);\n\n\t\t/*\n\t\t**\tIf the list is now small enough to display completely within the list box region,\n\t\t**\tthen delete the slider gadget (if they are present).\n\t\t*/\n\t\tif (List.Count() <= LineCount) {\n\t\t\tRemove_Scroll_Bar();\n\t\t}\n\n\t\t/*\n\t\t**\tTell the slider that there is one less entry in the list.\n\t\t*/\n\t\tif (IsScrollActive) {\n\t\t\tScrollGadget.Set_Maximum(List.Count());\n\t\t}\n\n\t\t/*\n\t\t** If we just removed the selected entry, select the previous one\n\t\t*/\n\t\tif (SelectedIndex >= List.Count()) {\n\t\t\tSelectedIndex--;\n\t\t\tif (SelectedIndex < 0) {\n\t\t\t\tSelectedIndex = 0;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** If we just removed the top-displayed entry, step up one item\n\t\t*/\n\t\tif (CurrentTopIndex >= List.Count()) {\n\t\t\tCurrentTopIndex--;\n\t\t\tif (CurrentTopIndex < 0)\n\t\t\t\tCurrentTopIndex = 0;\n\t\t\tif (IsScrollActive)\n\t\t\t\tScrollGadget.Step(1);\n\t\t}\n\t}\n}\n\ntemplate<class T>\nvoid TListClass<T>::Remove_Item(T text)\n{\n\tRemove_Index(List.ID(text));\n}\n\ntemplate<class T>\nint TListClass<T>::Action(unsigned flags, KeyNumType & key)\n{\n\tif (flags & LEFTRELEASE) {\n\t\tkey = KN_NONE;\n\t\tflags &= (~LEFTRELEASE);\n\t\tControlClass::Action(flags, key);\n\t\treturn(true);\n\t} else {\n\n\t\t/*\n\t\t** Handle keyboard events here.\n\t\t*/\n\t\tif (flags & KEYBOARD) {\n\n\t\t\t/*\n\t\t\t**\tProcess the keyboard character. If indicated, consume this keyboard event\n\t\t\t**\tso that the edit gadget ID number is not returned.\n\t\t\t*/\n\t\t\tif (key == KN_UP) {\n\t\t\t\tStep_Selected_Index(-1);\n\t\t\t\tkey = KN_NONE;\n\t\t\t} else if (key == KN_DOWN) {\n\t\t\t\tStep_Selected_Index(1);\n\t\t\t\tkey = KN_NONE;\n\t\t\t} else {\n\t\t\t\tflags &= ~KEYBOARD;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tint index = Get_Mouse_Y() - (Y+1);\n\t\t\tindex = index / LineHeight;\n\t\t\tSelectedIndex = CurrentTopIndex + index;\n\t\t\tSelectedIndex = min(SelectedIndex, List.Count()-1);\n\t\t}\n\t}\n\treturn(ControlClass::Action(flags, key));\n}\n\ntemplate<class T>\nint TListClass<T>::Draw_Me(int forced)\n{\n\tif (GadgetClass::Draw_Me(forced)) {\n\n\t\t/*\n\t\t**\tTurn off the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Hide_Mouse(X, Y, X+Width, Y+Height);\n\t\t}\n\n\t\tDraw_Box(X, Y, Width, Height, BOXSTYLE_BOX, true);\n\n\t\t/*\n\t\t**\tDraw List.\n\t\t*/\n\t\tif (List.Count()) {\n\t\t\tfor (int index = 0; index < LineCount; index++)  {\n\t\t\t\tint line = CurrentTopIndex + index;\n\n\t\t\t\tif (List.Count() > line) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tPrints the text and handles right edge clipping and tabs.\n\t\t\t\t\t*/\n\t\t\t\t\tList[line]->Draw_It(line, X+1, Y+(LineHeight*index)+1, Width-2, LineHeight, (line == SelectedIndex), TextFlags);\n//\t\t\t\t\tList[index].Draw_It(line, X+1, Y+(LineHeight*index)+1, Width-2, LineHeight, (line == SelectedIndex), TextFlags);\n//\t\t\t\t\tDraw_Entry(line, X+1, Y+(LineHeight*index)+1, Width-2, (line == SelectedIndex));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tTurn on the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Show_Mouse();\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\ntemplate<class T>\nvoid TListClass<T>::Bump(int up)\n{\n\tif (IsScrollActive) {\n\t\tif (ScrollGadget.Step(up)) {\n\t\t\tCurrentTopIndex = ScrollGadget.Get_Value();\n\t\t\tFlag_To_Redraw();\n\t\t}\n\t}\n}\n\ntemplate<class T>\nvoid TListClass<T>::Step(int up)\n{\n\tif (IsScrollActive) {\n\t\tif (ScrollGadget.Step(up)) {\n\t\t\tCurrentTopIndex = ScrollGadget.Get_Value();\n\t\t\tFlag_To_Redraw();\n\t\t}\n\t}\n}\n\n#ifdef NEVER\ntemplate<class T>\nT TListClass<T>::Get_Item(int index) const\n{\n\tindex = min(index, List.Count());\n\treturn(List[index]);\n}\n#endif\n\ntemplate<class T>\nT TListClass<T>::Current_Item(void) const\n{\n\tstatic T _temp;\n\tif (List.Count() <= SelectedIndex) {\n\t\treturn(_temp);\n\t}\n\treturn(List[SelectedIndex]);\n}\n\ntemplate<class T>\nint TListClass<T>::Current_Index(void) const\n{\n\treturn(SelectedIndex);\n}\n\ntemplate<class T>\nvoid TListClass<T>::Peer_To_Peer(unsigned flags, KeyNumType &, ControlClass & whom)\n{\n\tif (flags & LEFTRELEASE) {\n\t\tif (&whom == &UpGadget) {\n\t\t\tStep(true);\n\t\t}\n\t\tif (&whom == &DownGadget) {\n\t\t\tStep(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tThe slider has changed, so reflect the current list position\n\t**\taccording to the slider setting.\n\t*/\n\tif (&whom == &ScrollGadget) {\n\t\tSet_View_Index(ScrollGadget.Get_Value());\n\t}\n}\n\ntemplate<class T>\nint TListClass<T>::Set_View_Index(int index)\n{\n\tindex = Bound(index, 0, List.Count() - LineCount);\n\tif (index != CurrentTopIndex) {\n\t\tCurrentTopIndex = index;\n\t\tFlag_To_Redraw();\n\t\tif (IsScrollActive) {\n\t\t\tScrollGadget.Set_Value(CurrentTopIndex);\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\ntemplate<class T>\nint TListClass<T>::Add_Scroll_Bar(void)\n{\n\tif (!IsScrollActive) {\n\t\tIsScrollActive = true;\n\n\t\t/*\n\t\t**\tEverything has been created successfully. Flag the list box to be\n\t\t**\tredrawn because it now must be made narrower to accomodate the new\n\t\t**\tslider gadgets.\n\t\t*/\n\t\tFlag_To_Redraw();\n\t\tWidth -= ScrollGadget.Width;\n\n\t\t/*\n\t\t**\tTell the newly created gadgets that they should inform this list box\n\t\t**\twhenever they get touched. In this way, the list box will automatically\n\t\t**\tbe updated under control of the slider buttons.\n\t\t*/\n\t\tUpGadget.Make_Peer(*this);\n\t\tDownGadget.Make_Peer(*this);\n\t\tScrollGadget.Make_Peer(*this);\n\n\t\t/*\n\t\t**\tAdd these newly created gadgets to the same gadget list that the\n\t\t**\tlist box is part of.\n\t\t*/\n\t\tUpGadget.Add(*this);\n\t\tDownGadget.Add(*this);\n\t\tScrollGadget.Add(*this);\n\n\t\t/*\n\t\t**\tMake sure these added gadgets get redrawn at the next opportunity.\n\t\t*/\n\t\tUpGadget.Flag_To_Redraw();\n\t\tDownGadget.Flag_To_Redraw();\n\t\tScrollGadget.Flag_To_Redraw();\n\n\t\t/*\n\t\t**\tInform the slider of the size of the window and the current view position.\n\t\t*/\n\t\tScrollGadget.Set_Maximum(List.Count());\n\t\tScrollGadget.Set_Thumb_Size(LineCount);\n\t\tScrollGadget.Set_Value(CurrentTopIndex);\n\n\t\t/*\n\t\t**\tReturn with success flag.\n\t\t*/\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\ntemplate<class T>\nint TListClass<T>::Remove_Scroll_Bar(void)\n{\n\tif (IsScrollActive) {\n\t\tIsScrollActive = false;\n\t\tWidth += ScrollGadget.Width;\n\t\tScrollGadget.Remove();\n\t\tUpGadget.Remove();\n\t\tDownGadget.Remove();\n\t\tFlag_To_Redraw();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\ntemplate<class T>\nvoid TListClass<T>::Set_Tabs(int const * tabs)\n{\n\tTabs = tabs;\n}\n\n#ifdef NEVER\ntemplate<class T>\nvoid TListClass<T>::Draw_Entry(int index, int x, int y, int width, int selected)\n{\n\tif (TextFlags & TPF_6PT_GRAD) {\n\t\tTextPrintType flags = TextFlags;\n\n\t\tif (selected) {\n\t\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\t\tLogicPage->Fill_Rect(x, y, x + width - 1, y + LineHeight - 1, CC_GREEN_SHADOW);\n\t\t} else {\n\t\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t\t}\n\t\t}\n\n\t\tConquer_Clip_Text_Print(List[index], x, y, CC_GREEN, TBLACK, flags, width, Tabs);\n\n\t} else {\n\t\tConquer_Clip_Text_Print(List[index], x, y, (selected ? BLUE : WHITE), TBLACK, TextFlags, width, Tabs);\n\t}\n}\n#endif\n\ntemplate<class T>\nLinkClass & TListClass<T>::Add(LinkClass & list)\n{\n\t/*\n\t**\tAdd the scroll bar gadgets if they're active.\n\t*/\n\tif (IsScrollActive) {\n\t\tScrollGadget.Add(list);\n\t\tDownGadget.Add(list);\n\t\tUpGadget.Add(list);\n\t}\n\n\t/*\n\t**\tAdd myself to the list, then return.\n\t*/\n\treturn(ControlClass::Add(list));\n}\n\ntemplate<class T>\nLinkClass & TListClass<T>::Add_Head(LinkClass & list)\n{\n\t/*\n\t**\tAdd the scroll bar gadgets if they're active.\n\t*/\n\tif (IsScrollActive) {\n\t\tScrollGadget.Add_Head(list);\n\t\tDownGadget.Add_Head(list);\n\t\tUpGadget.Add_Head(list);\n\t}\n\n\t/*\n\t**\tAdd myself to the list, then return.\n\t*/\n\treturn(ControlClass::Add_Head(list));\n}\n\ntemplate<class T>\nLinkClass & TListClass<T>::Add_Tail(LinkClass & list)\n{\n\t/*\n\t**\tAdd myself to the list.\n\t*/\n\tControlClass::Add_Tail(list);\n\n\t/*\n\t**\tAdd the scroll bar gadgets if they're active.\n\t*/\n\tif (IsScrollActive) {\n\t\tUpGadget.Add_Tail(list);\n\t\tDownGadget.Add_Tail(list);\n\t\tScrollGadget.Add_Tail(list);\n\t}\n\n\treturn(Head_Of_List());\n}\n\ntemplate<class T>\nGadgetClass * TListClass<T>::Remove(void)\n{\n\t/*\n\t**\tRemove the scroll bar if it's active\n\t*/\n\tif (IsScrollActive) {\n\t\tScrollGadget.Remove();\n\t\tDownGadget.Remove();\n\t\tUpGadget.Remove();\n\t}\n\n\t/*\n\t**\tRemove myself & return\n\t*/\n\treturn(ControlClass::Remove());\n}\n\ntemplate<class T>\nvoid TListClass<T>::Set_Selected_Index(int index)\n{\n   if ((unsigned)index < List.Count()) {\n\t\tSelectedIndex = index;\n\t\tFlag_To_Redraw();\n\t\tif (SelectedIndex < CurrentTopIndex) {\n\t\t\tSet_View_Index(SelectedIndex);\n\t\t}\n\t\tif (SelectedIndex >= CurrentTopIndex+LineCount) {\n\t\t\tSet_View_Index(SelectedIndex-(LineCount-1));\n\t\t}\n   }\n}\n\ntemplate<class T>\nint TListClass<T>::Step_Selected_Index(int step)\n{\n\tint old = SelectedIndex;\n\n\tSet_Selected_Index(old + step);\n\treturn(old);\n}\n\ntemplate<class T>\nvoid TListClass<T>::Flag_To_Redraw(void)\n{\n\tif (IsScrollActive) {\n\t\tUpGadget.Flag_To_Redraw();\n\t\tDownGadget.Flag_To_Redraw();\n\t\tScrollGadget.Flag_To_Redraw();\n\t}\n\tControlClass::Flag_To_Redraw();\n}\n\ntemplate<class T>\nvoid TListClass<T>::Set_Selected_Index(T text)\n{\n\tfor (int index = 0; index < Count(); index++) {\n\t\tif (text == Get_Item(index)) {\n\t\t\tSet_Selected_Index(index);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n#endif\n"
  },
  {
    "path": "CODE/LISTNODE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LISTNODE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LISTNODE.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/16/96                                                     *\n *                                                                                             *\n *                  Last Update : May 16, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef LISTNODE_H\n#define LISTNODE_H\n\n#include\t<stddef.h>\n#include\t<assert.h>\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ comittee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\n#pragma warn -inl\n\n/*\n**\tThis is a doubly linked list node. Typical use of this node is to derive\n**\tobjects from this node. The interface class for this node can be used for\n**\tadded convenience.\n*/\nclass GenericList;\nclass GenericNode {\n\tpublic:\n\t\tGenericNode(void) : NextNode(0), PrevNode(0) {}\n\t\t~GenericNode(void) {Unlink();}\n\t\tGenericNode(GenericNode & node) {node.Link(this);}\n\t\tGenericNode & operator = (GenericNode & node) {\n\t\t\tif (&node != this) {\n\t\t\t\tnode.Link(this);\n\t\t\t}\n\t\t\treturn(*this);\n\t\t}\n\n\t\tvoid Unlink(void) {\n\t\t\tif (Is_Valid()) {\n\t\t\t\tPrevNode->NextNode = NextNode;\n\t\t\t\tNextNode->PrevNode = PrevNode;\n\t\t\t\tPrevNode = 0;\n\t\t\t\tNextNode = 0;\n\t\t\t}\n\t\t}\n\n\t\tGenericList * Main_List(void) const {\n\t\t\tGenericNode const * node = this;\n\t\t\twhile (node->PrevNode) {\n\t\t\t\tnode = PrevNode;\n\t\t\t}\n\t\t\treturn((GenericList *)this);\n\t\t}\n\t\tvoid Link(GenericNode * node) {\n\t\t\tassert(node != NULL);\n\t\t\tnode->Unlink();\n\t\t\tnode->NextNode = NextNode;\n\t\t\tnode->PrevNode = this;\n\t\t\tif (NextNode) NextNode->PrevNode = node;\n\t\t\tNextNode = node;\n\t\t}\n\n\t\tGenericNode * Next(void) const {return(NextNode);}\n\t\tGenericNode * Prev(void) const {return(PrevNode);}\n\t\tbool Is_Valid(void) const {return(this != NULL && NextNode != NULL && PrevNode != NULL);}\n\n\tprotected:\n\t\tGenericNode * NextNode;\n\t\tGenericNode * PrevNode;\n};\n\n\n/*\n**\tThis is a generic list handler. It manages N generic nodes. Use the interface class\n**\tto the generic list for added convenience.\n*/\nclass GenericList {\n\tpublic:\n\t\tGenericList(void) {\n\t\t\tFirstNode.Link(&LastNode);\n\t\t}\n\n\t\tGenericNode * First(void) const {return(FirstNode.Next());}\n\t\tGenericNode * Last(void) const {return(LastNode.Prev());}\n\t\tbool Is_Empty(void) const {return(!FirstNode.Next()->Is_Valid());}\n\t\tvoid Add_Head(GenericNode * node) {FirstNode.Link(node);}\n\t\tvoid Add_Tail(GenericNode * node) {LastNode.Prev()->Link(node);}\n\t\tvoid Delete(void) {while (FirstNode.Next()->Is_Valid()) delete FirstNode.Next();}\n\n\tprotected:\n\t\tGenericNode FirstNode;\n\t\tGenericNode LastNode;\n\n\tprivate:\n\t\tGenericList(GenericList & list);\n\t\tGenericList & operator = (GenericList const &);\n};\n\n\n\n/*\n**\tThis node class serves only as an \"interface class\" for the normal node\n**\tobject. In order to use this interface class you absolutely must be sure\n**\tthat the node is the root base object of the \"class T\". If it is true that the\n**\taddress of the node is the same as the address of the \"class T\", then this\n**\tinterface class will work. You can usually ensure this by deriving the\n**\tclass T object from this node.\n*/\ntemplate<class T> class List;\ntemplate<class T>\nclass Node : public GenericNode {\n\tpublic:\n\t\tList<T> * Main_List(void) const {return((List<T> *)GenericNode::Main_List());}\n\t\tT * Next(void) const {return((T *)GenericNode::Next());}\n\t\tT * Prev(void) const {return((T *)GenericNode::Prev());}\n\t\tbool Is_Valid(void) const {return(GenericNode::Is_Valid());}\n};\n\n\n/*\n**\tThis is an \"interface class\" for a list of nodes. The rules for the class T object\n**\tare the same as the requirements required of the node class.\n*/\ntemplate<class T>\nclass List : public GenericList {\n\tpublic:\n\t\tT * First(void) const {return((T*)GenericList::First());}\n\t\tT * Last(void) const {return((T*)GenericList::Last());}\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/LOADDLG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LOADDLG.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LOADDLG.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Maria Legg, Joe Bostic, Bill Randolph                        *\n *                                                                                             *\n *                   Start Date : March 19, 1995                                               *\n *                                                                                             *\n *                  Last Update : June 25, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LoadOptionsClass::LoadOptionsClass -- class constructor                                   *\n *   LoadOptionsClass::~LoadOptionsClass -- class destructor                                   *\n *   LoadOptionsClass::Process -- main processing routine                                      *\n *   LoadOptionsClass::Clear_List -- clears the list box & Files arrays                        *\n *   LoadOptionsClass::Fill_List -- fills the list box & GameNum arrays                        *\n *   LoadOptionsClass::Num_From_Ext -- clears the list box & GameNum arrays                    *\n *   LoadOptionsClass::Compare -- for qsort                                                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include <io.h>\t\t\t\t// for unlink\n\n\n/***********************************************************************************************\n * LoadOptionsClass::LoadOptionsClass -- class constructor                                     *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      style      style for this load/save dialog (LOAD/SAVE/DELETE)                          *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nLoadOptionsClass::LoadOptionsClass(LoadStyleType style)\n{\n\tStyle = style;\n\tFiles.Clear();\n}\n\n\n/***********************************************************************************************\n * LoadOptionsClass::~LoadOptionsClass -- class destructor                                     *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nLoadOptionsClass::~LoadOptionsClass()\n{\n\tfor (int i = 0; i < Files.Count(); i++) {\n\t\tdelete Files[i];\n\t}\n\tFiles.Clear();\n}\n\n\n/***********************************************************************************************\n * LoadOptionsClass::Process -- main processing routine                                        *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      false = User cancelled, true = operation completed                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nint LoadOptionsClass::Process(void)\n{\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tint d_dialog_w = 250 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 156 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = (((320 * RESFACTOR) - d_dialog_w) / 2);\t\t\t\t// centered x-coord\n\tint d_dialog_y = (((200 * RESFACTOR) - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// coord of x-center\n\n\tint d_txt8_h = 11 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// ht of 8-pt text\n\tint d_margin = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\tint x_margin = 16 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint d_list_w = d_dialog_w - (x_margin * 2);\n\tint d_list_h = 104 * RESFACTOR;\n\tint d_list_x = d_dialog_x + x_margin;\n\tint d_list_y = d_dialog_y + d_margin + d_txt8_h + d_margin;\n\n\tint d_edit_w = d_dialog_w - (x_margin * 2);\n\tint d_edit_h = 13 * RESFACTOR;\n\tint d_edit_x = d_dialog_x + x_margin;\n\tint d_edit_y = d_list_y + d_list_h - (30 * RESFACTOR) + d_margin + d_txt8_h;\n\n#if (GERMAN | FRENCH)\n\tint d_button_w = 50 * RESFACTOR;\n#else\n\tint d_button_w = 40 * RESFACTOR;\n#endif\n\tint d_button_h = 13 * RESFACTOR;\n\tint d_button_x = d_dialog_cx - d_button_w - d_margin;\n\tint d_button_y = d_dialog_y + d_dialog_h - d_button_h - d_margin;\n\n#if defined(GERMAN) || defined(FRENCH)\n\tint d_cancel_w = 60 * RESFACTOR;//BG:40\n#else\n\tint d_cancel_w = 40 * RESFACTOR;\n#endif\n\tint d_cancel_h = 13 * RESFACTOR;\n\tint d_cancel_x = d_dialog_cx + d_margin;\n\tint d_cancel_y = d_dialog_y + d_dialog_h - d_cancel_h - d_margin;\n\n\t/*\n\t**\tButton enumerations\n\t*/\n\tenum {\n\t\tBUTTON_LOAD = 100,\n\t\tBUTTON_SAVE,\n\t\tBUTTON_DELETE,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_LIST,\n\t\tBUTTON_EDIT,\n\t};\n\n\t/*\n\t**\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*\n\t**\tDialog variables\n\t*/\n\tbool cancel = false;\t\t\t\t\t\t// true = user cancels\n\tint list_ht = d_list_h;\t\t\t\t\t// adjusted list box height\n\n\t/*\n\t**\tOther Variables\n\t*/\n\tint btn_txt;\t\t\t\t\t\t\t\t// text on the 'OK' button\n\tint btn_id;\t\t\t\t\t\t\t\t\t// ID of 'OK' button\n\tint caption;\t\t\t\t\t\t\t\t// dialog caption\n\tint game_idx = 0;\t\t\t\t\t\t\t// index of game to save/load/etc\n\tint game_num = 0;\t\t\t\t\t\t\t// file number of game to load/save/etc\n\tchar game_descr[DESCRIP_MAX] = {0};\t\t\t\t// save-game description\n\tchar fname[_MAX_NAME+_MAX_EXT];\t\t\t\t\t\t\t// for generating filename to delete\n\tint rc;\t\t\t\t\t\t\t\t\t\t// return code\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass * commands = NULL;\t\t// the button list\n\n\tswitch (Style) {\n\t\tcase LOAD:\n\t\t\tbtn_txt = TXT_LOAD_BUTTON;\n\t\t\tbtn_id = BUTTON_LOAD;\n\t\t\tcaption = TXT_LOAD_MISSION;\n\t\t\tbreak;\n\n\t\tcase SAVE:\n\t\t\tbtn_txt = TXT_SAVE_BUTTON;\n\t\t\tbtn_id = BUTTON_SAVE;\n\t\t\tcaption = TXT_SAVE_MISSION;\n\t\t\tlist_ht -= 30;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbtn_txt = TXT_DELETE_BUTTON;\n\t\t\tbtn_id = BUTTON_DELETE;\n\t\t\tcaption = TXT_DELETE_MISSION;\n\t\t\tbreak;\n\t}\n\n\tTextButtonClass button (btn_id, btn_txt, TPF_BUTTON, d_button_x, d_button_y, d_button_w);\n\tTextButtonClass cancelbtn (BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w);\n\n\tListClass listbtn (BUTTON_LIST, d_list_x, d_list_y, d_list_w, list_ht,\n\t\tTPF_6PT_GRAD | TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"BTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"BTN-DN.SHP\"));\n\n\tEditClass editbtn (BUTTON_EDIT, game_descr, sizeof(game_descr)-4, TPF_6PT_GRAD|TPF_NOSHADOW, d_edit_x, d_edit_y, d_edit_w, -1, EditClass::ALPHANUMERIC);\n\n\t/*\n\t**\tInitialize.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\tFill_List(&listbtn);\n\n\t/*\n\t**\tDo nothing if list is empty.\n\t*/\n\tif ((Style == LOAD || Style == WWDELETE) && listbtn.Count()==0) {\n\t\tClear_List(&listbtn);\n\t\tWWMessageBox().Process(TXT_NO_SAVES);\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tCreate the button list.\n\t*/\n\tcommands = &button;\n\tcancelbtn.Add_Tail(*commands);\n\tlistbtn.Add_Tail(*commands);\n\tif (Style == SAVE) {\n\t\teditbtn.Add_Tail(*commands);\n\t\teditbtn.Set_Focus();\n\t}\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tKeyboard->Clear();\n\tbool firsttime = true;\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tif (Session.Type == GAME_NORMAL || Session.Type == GAME_SKIRMISH) {\n\t\t\tCall_Back();\n\t\t} else {\n\t\t\tif (Main_Loop()) {\n\t\t\t\tprocess = false;\n\t\t\t\tcancel = true;\n\t\t\t}\n\t\t}\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = true;\n\t\t}\n\t\t#endif\n\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\n\t\t\t/*\n\t\t\t**\tDisplay the dialog box.\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tif (display) {\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\t\t\t\tDraw_Caption(caption, d_dialog_x, d_dialog_y, d_dialog_w);\n\n\t\t\t\tif (Style == SAVE) {\n\t\t\t\t\tFancy_Text_Print(TXT_MISSION_DESCRIPTION, d_dialog_cx,\n\t\t\t\t\t\td_edit_y - d_txt8_h, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT | TPF_CENTER);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRedraw the buttons.\n\t\t\t*/\n\t\t\tif (display) {\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t**\tThe first time through the processing loop, set the edit\n\t\t**\tgadget to have the focus if this is the save dialog. The\n\t\t**\tfocus must be set here since the gadget list has changed\n\t\t**\tand this change will cause any previous focus setting to be\n\t\t**\tcleared by the input processing routine.\n\t\t*/\n\t\tif (firsttime && Style == SAVE) {\n\t\t\tfirsttime = false;\n\t\t\teditbtn.Set_Focus();\n\t\t\teditbtn.Flag_To_Redraw();\n\t\t}\n\n\t\t/*\n\t\t**\tIf the <RETURN> key was pressed, then default to the appropriate\n\t\t**\taction button according to the style of this dialog box.\n\t\t*/\n\t\tif (input == KN_RETURN || input == (BUTTON_EDIT|KN_BUTTON)) {\n\t\t\tToggleClass * toggle = NULL;\n\t\t\tswitch (Style) {\n\t\t\t\tcase SAVE:\n\t\t\t\t\tinput = (KeyNumType)(BUTTON_SAVE|KN_BUTTON);\n\t\t\t\t\tcancelbtn.Turn_Off();\n//\t\t\t\t\tcancelbtn.IsOn = false;\n\t\t\t\t\ttoggle = (ToggleClass*)commands->Extract_Gadget(BUTTON_SAVE);\n\t\t\t\t\tif (toggle != NULL) {\n\t\t\t\t\t\ttoggle->Turn_On();\n//\t\t\t\t\t\ttoggle->IsOn = true;\n\t\t\t\t\t\ttoggle->IsPressed = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase LOAD:\n\t\t\t\t\tinput = (KeyNumType)(BUTTON_LOAD|KN_BUTTON);\n//\t\t\t\t\tcancelbtn.IsOn = false;\n\t\t\t\t\tcancelbtn.Turn_Off();\n\t\t\t\t\ttoggle = (ToggleClass *)commands->Extract_Gadget(BUTTON_LOAD);\n\t\t\t\t\tif (toggle != NULL) {\n\t\t\t\t\t\ttoggle->IsOn = true;\n\t\t\t\t\t\ttoggle->IsPressed = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase WWDELETE:\n\t\t\t\t\tinput = (KeyNumType)(BUTTON_DELETE|KN_BUTTON);\n//\t\t\t\t\tcancelbtn.IsOn = false;\n\t\t\t\t\tcancelbtn.Turn_Off();\n\t\t\t\t\ttoggle = (ToggleClass *)commands->Extract_Gadget(BUTTON_DELETE);\n\t\t\t\t\tif (toggle != NULL) {\n\t\t\t\t\t\ttoggle->IsOn = true;\n\t\t\t\t\t\ttoggle->IsPressed = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tHide_Mouse();\n\t\t\tcommands->Draw_All(true);\n\t\t\tShow_Mouse();\n\t\t}\n\n\t\t/*\n\t\t**\tProcess input.\n\t\t*/\n\t\tswitch (input) {\n\t\t\t/*\n\t\t\t** Load: if load fails, present a message, and stay in the dialog\n\t\t\t** to allow the user to try another game\n\t\t\t*/\n\t\t\tcase (BUTTON_LOAD | KN_BUTTON):\n\t\t\t\tgame_idx = listbtn.Current_Index();\n\t\t\t\tgame_num = Files[game_idx]->Num;\n\t\t\t\tif (Files[game_idx]->Valid) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Start a timer before we load the game\n\t\t\t\t\t*/\n\t\t\t\t\tCDTimerClass<SystemTimerClass> timer;\n//\t\t\t\t\ttimer.Start();\n\t\t\t\t\ttimer = TICKS_PER_SECOND*4;\n\n\t\t\t\t\tWWMessageBox().Process(TXT_LOADING, TXT_NONE);\n\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\trc = Load_Game(game_num);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Make sure the message says on the screen at least 1 second\n\t\t\t\t\t*/\n\t\t\t\t\twhile (timer > 0) {\n\t\t\t\t\t\tCall_Back();\n\t\t\t\t\t}\n\t\t\t\t\tKeyboard->Clear();\n\n\t\t\t\t\tif (!rc) {\n\t\t\t\t\t\tWWMessageBox().Process(TXT_ERROR_LOADING_GAME);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSpeak(VOX_LOAD1);\n\t\t\t\t\t\twhile (Is_Speaking()) {\n\t\t\t\t\t\t\tCall_Back();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tHide_Mouse();\n\t\t\t\t\t\tSeenPage.Clear();\n\t\t\t\t\t\tGamePalette.Set();\n//\t\t\t\t\t\tSet_Palette(GamePalette);\n\t\t\t\t\t\tShow_Mouse();\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tWWMessageBox().Process(TXT_OBSOLETE_SAVEGAME);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t** Save: Save the game & exit the dialog\n\t\t\t*/\n\t\t\tcase (BUTTON_EDIT | KN_BUTTON):\n\n\t\t\tcase (BUTTON_SAVE | KN_BUTTON):\n\t\t\t\tif (!strlen(game_descr)) {\n\t\t\t\t\tWWMessageBox().Process(TXT_MUSTENTER_DESCRIPTION);\n\t\t\t\t\tfirsttime = true;\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tgame_idx = listbtn.Current_Index();\n\t\t\t\tif (Disk_Space_Available() < SAVE_GAME_DISK_SPACE && game_idx == 0) {\n\t\t\t\t\tWWMessageBox().Process(TXT_SPACE_CANT_SAVE);\n\t\t\t\t\tfirsttime = true;\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tgame_num = Files[game_idx]->Num;\n\t\t\t\tif (!Save_Game(game_num, game_descr)) {\n\t\t\t\t\tWWMessageBox().Process(TXT_ERROR_SAVING_GAME);\n\t\t\t\t} else {\n\t\t\t\t\tSpeak(VOX_SAVE1);\n\t\t\t\t\twhile (Is_Speaking()) {\n\t\t\t\t\t\tCall_Back();\n\t\t\t\t\t}\n\t\t\t\t\tCDTimerClass<SystemTimerClass> timer;\n//\t\t\t\t\ttimer.Start();\n\t\t\t\t\ttimer = TICKS_PER_SECOND*4;\n\n\t\t\t\t\tWWMessageBox().Process(TXT_GAME_WAS_SAVED, TXT_NONE, TXT_NONE);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDelay to let the user read the message\n\t\t\t\t\t*/\n\t\t\t\t\twhile (timer > 0) {\n\t\t\t\t\t\tCall_Back();\n\t\t\t\t\t}\n\t\t\t\t\tKeyboard->Clear();\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t** Delete: delete the file & stay in the dialog, to allow the user\n\t\t\t** to delete multiple files.\n\t\t\t*/\n\t\t\tcase (BUTTON_DELETE | KN_BUTTON):\n\t\t\t\tgame_idx = listbtn.Current_Index();\n\t\t\t\tgame_num = Files[game_idx]->Num;\n\t\t\t\tif (WWMessageBox().Process(TXT_DELETE_FILE_QUERY, TXT_YES, TXT_NO)==0) {\n\t\t\t\t\tsprintf(fname, \"SAVEGAME.%03d\", game_num);\n\t\t\t\t\tunlink(fname);\n\t\t\t\t\tClear_List(&listbtn);\n\t\t\t\t\tFill_List(&listbtn);\n\t\t\t\t\tif (listbtn.Count() == 0) {\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tToggleClass * toggle = (ToggleClass *)commands->Extract_Gadget(BUTTON_DELETE);\n\t\t\t\t\t\tif (toggle != NULL) {\n//\t\t\t\t\t\t\ttoggle->IsOn = false;\n\t\t\t\t\t\t\ttoggle->Turn_Off();\n\t\t\t\t\t\t\ttoggle->IsPressed = false;\n\t\t\t\t\t\t\ttoggle->Flag_To_Redraw();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t** If the user clicks on the list, see if the there is a new current\n\t\t\t** item; if so, and if we're in SAVE mode, copy the list item into\n\t\t\t** the save-game description field.\n\t\t\t*/\n\t\t\tcase (BUTTON_LIST | KN_BUTTON):\n\t\t\t\tif (Style != SAVE) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (listbtn.Count() && listbtn.Current_Index() != game_idx) {\n\t\t\t\t\tgame_idx = listbtn.Current_Index();\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Copy the game's description, UNLESS it's the empty slot; if\n\t\t\t\t\t** it is, set the edit buffer to empty.\n\t\t\t\t\t*/\n\t\t\t\t\tif (game_idx != 0) {\n\t\t\t\t\t\tstrcpy(game_descr, listbtn.Get_Item(game_idx));\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tStrip any leading parenthesis off of the description.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (game_descr[0] == '(') {\n\t\t\t\t\t\t\tchar * ptr = strchr(game_descr, ')');\n\t\t\t\t\t\t\tif (ptr != NULL) {\n\t\t\t\t\t\t\t\tstrcpy(game_descr, ptr+1);\n\t\t\t\t\t\t\t\tstrtrim(game_descr);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tgame_descr[0] = 0;\n\t\t\t\t\t}\n\t\t\t\t\teditbtn.Set_Text(game_descr, 40);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t** ESC/Cancel: break\n\t\t\t*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tcancel = true;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tClear_List(&listbtn);\n\n\tif (cancel) return(false);\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * LoadOptionsClass::Clear_List -- clears the list box & Files arrays                          *\n *                                                                                             *\n * This step is essential, because it frees all the strings allocated for list items.          *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid LoadOptionsClass::Clear_List(ListClass * list)\n{\n\t/*\n\t** For every item in the list, free its buffer & remove it from the list.\n\t*/\n\tint j = list->Count();\n\tfor (int i = 0; i < j; i++) {\n\t\tlist->Remove_Item(list->Get_Item(0));\n\t}\n\n\t/*\n\t** Clear the array of game numbers\n\t*/\n\tfor (i = 0; i < Files.Count(); i++) {\n\t\tdelete Files[i];\n\t}\n\tFiles.Clear();\n}\n\n\n/***********************************************************************************************\n * LoadOptionsClass::Fill_List -- fills the list box & GameNum arrays                          *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *   06/25/1995 JLB : Shows which saved games are \"(old)\".                                     *\n *=============================================================================================*/\nvoid LoadOptionsClass::Fill_List(ListClass * list)\n{\n\tFileEntryClass * fdata;\t// for adding entries to 'Files'\n\tchar descr[DESCRIP_MAX+32];\n\tunsigned scenario;\t\t\t// scenario #\n\tHousesType house;\t\t\t\t// house\n\tstruct find_t ff;\t\t// for _dos_findfirst\n\tint id;\n\n\t/*\n\t** Make sure the list is empty\n\t*/\n\tClear_List(list);\n\n\t/*\n\t** Add the Empty Slot entry\n\t*/\n\tif (Style == SAVE) {\n\t\tfdata = new FileEntryClass;\n\t\tstrcpy(fdata->Descr, Text_String(TXT_EMPTY_SLOT));\n\t\tfdata->DateTime = 0xffffffff;\t// will always be first\n\t\tFiles.Add(fdata);\n\t}\n\n\t/*\n\t** Find all savegame files\n\t*/\n\tint rc = _dos_findfirst(\"SAVEGAME.*\", _A_NORMAL, &ff);\n\n\twhile (!rc) {\n\n\t\tif (stricmp(ff.name, NET_SAVE_FILE_NAME) != 0) {\n\n\t\t\t/*\n\t\t\t** Extract the game ID from the filename\n\t\t\t*/\n\t\t\tid = Num_From_Ext(ff.name);\n\n\t\t\t/*\n\t\t\t** get the game's info; if success, add it to the list\n\t\t\t*/\n\t\t\tbool ok = Get_Savefile_Info(id, descr, &scenario, &house);\n\n\t\t\tfdata = new FileEntryClass;\n\n\t\t\tfdata->Descr[0] = '\\0';\n\t\t\tif (!ok) {\n\t\t\t\tstrcpy(fdata->Descr, Text_String(TXT_OLD_GAME));\n\t\t\t} else {\n\t\t\t\tif (house == HOUSE_USSR || house == HOUSE_UKRAINE) {\n#ifdef WIN32\n\t\t\t\t\tsprintf(fdata->Descr, \"(%s) \", Text_String(TXT_SOVIET));\n#else\n\t\t\t\t\tsprintf(fdata->Descr, \"(%c) \", *Text_String(TXT_SOVIET));\n#endif\n\t\t\t\t} else {\n#ifdef WIN32\n\t\t\t\t\tsprintf(fdata->Descr, \"(%s) \", Text_String(TXT_ALLIES));\n#else\n\t\t\t\t\tsprintf(fdata->Descr, \"(%c) \", *Text_String(TXT_ALLIES));\n#endif\n\t\t\t\t}\n\t\t\t}\n\t\t\tstrncat(fdata->Descr, descr, (sizeof(fdata->Descr)-strlen(fdata->Descr))-1);\n\t\t\tfdata->Valid = ok;\n\t\t\tfdata->Scenario = scenario;\n\t\t\tfdata->House = house;\n\t\t\tfdata->Num = id;\n\t\t\tfdata->DateTime = (((unsigned long)ff.wr_date) << 16) | (unsigned long)ff.wr_time;\n\t\t\tFiles.Add(fdata);\n\t\t}\n\n\t\t/*\n\t\t** Find the next file\n\t\t*/\n\t\trc = _dos_findnext(&ff);\n\t}\n\n\t/*\n\t** If saving a game, determine a unique file ID for the empty slot\n\t*/\n\tif (Style == SAVE) {\n\t\t/*\n\t\t** Find an un-used number to associate with the Empty Slot by looking in\n\t\t** GameNum for each number from 0 to 'N', where 'N' is the # of entries\n\t\t** in the list; if any number isn't found, use that number; otherwise,\n\t\t** use 'N + 1'.\n\t\t*/\n\t\tfor (int i = 0; i < Files.Count(); i++) {\t\t// i = the # we're searching for\n\t\t\tid = -1;\t\t\t\t\t\t\t\t\t\t\t// mark as 'not found'\n\t\t\tfor (int j = 0; j < Files.Count(); j++) {\t// loop through all game ID's\n\t\t\t\tif (Files[j]->Num==i) {\t\t\t\t\t// if found, mark as found\n\t\t\t\t\tid = j;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (id == -1)\tbreak;\t\t\t\t\t\t\t// if ID not found, use this one\n\t\t}\n\n\t\tFiles[0]->Num = i;\t\t\t\t\t\t\t\t// set the empty slot's ID\n\t}\n\n\t/*\n\t** Now sort the list in order of Date/Time (newest first, oldest last)\n\t*/\n\tqsort((void *)(&Files[0]), Files.Count(), sizeof(class FileEntryClass *), LoadOptionsClass::Compare);\n\n\t/*\n\t** Now add every file's name to the list box\n\t*/\n\tfor (int i = 0; i < Files.Count(); i++) {\n\t\tlist->Add_Item(Files[i]->Descr);\n\t}\n}\n\n\n/***********************************************************************************************\n * LoadOptionsClass::Num_From_Ext -- clears the list box & GameNum arrays                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      fname      filename to parse                                                           *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      File number for this name.                                                             *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nint LoadOptionsClass::Num_From_Ext(char * fname)\n{\n\tchar ext[_MAX_EXT];\n\n\t_splitpath(fname, NULL, NULL, NULL, ext);\n\tint num = atoi(ext + 1);\t\t// skip the '.'\n\treturn(num);\n}\n\n\n/***********************************************************************************************\n * LoadOptionsClass::Compare -- for qsort                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      p1,p2      ptrs to elements to compare                                                 *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      0 = same, -1 = (*p1) goes BEFORE (*p2), 1 = (*p1) goes AFTER (*p2)                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nint LoadOptionsClass::Compare(const void * p1, const void * p2)\n{\n\tclass FileEntryClass * fe1, * fe2;\n\n\tfe1 = *((class FileEntryClass **)p1);\n\tfe2 = *((class FileEntryClass **)p2);\n\n\tif (fe1->DateTime > fe2->DateTime) return(-1);\n\tif (fe1->DateTime < fe2->DateTime) return(1);\n\treturn(0);\n}\n\n"
  },
  {
    "path": "CODE/LOADDLG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LOADDLG.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                         \t\t\t\t\t\t  *\n *                 Project Name : Command & Conquer                        \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                    File Name : LOADDLG.H \t                              \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                   Programmer : Maria Legg, Joe Bostic, Bill Randolph     \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                   Start Date : March 19, 1995\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                  Last Update : March 19, 1995\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef LOADDLG_H\n#define LOADDLG_H\n\nclass FileEntryClass {\n\tpublic:\n\t\tchar Descr[80];\t\t\t\t// save-game description\n\t\tunsigned Scenario;\t\t\t// scenario #\n\t\tHousesType House;\t\t\t\t// house\n\t\tint Num;\t\t\t\t\t\t\t// save file number (from the extension)\n\t\tunsigned long DateTime;\t\t// date/time stamp of file\n\t\tbool Valid;\t\t\t\t\t\t// Is the scenario valid?\n};\n\nclass LoadOptionsClass\n{\n\tpublic:\n\t\t/*\n\t\t** This defines the style of the dialog\n\t\t*/\n\t\ttypedef enum OperationModeEnum {\n\t\t\tNONE = 0,\n\t\t\tLOAD,\n\t\t\tSAVE,\n\t\t\tWWDELETE\n\t\t} LoadStyleType;\n\n\t\tLoadOptionsClass (LoadStyleType style = LoadOptionsClass::NONE);\n\t\t~LoadOptionsClass ();\n\t\tint Process (void);\n\n\n\tprotected:\n\t\t/*\n\t\t** Internal routines\n\t\t*/\n\t\tvoid Clear_List (ListClass *list);\t\t// clears the list & game # array\n\t\tvoid Fill_List (ListClass *list);\t\t// fills the list & game # array\n\t\tint Num_From_Ext (char *fname);\t\t\t// translates filename to file #\n\t\tstatic int Compare(const void *p1, const void *p2); // for qsort()\n\n\t\t/*\n\t\t** This is the requested style of the dialog\n\t\t*/\n\t\tLoadStyleType Style;\n\n\t\t/*\n\t\t** This is an array of pointers to FileEntryClass objects.  These objects\n\t\t** are allocated on the fly as files are found, and pointers to them are\n\t\t** added to the vector list.  Thus, all the objects must be free'd before\n\t\t** the vector list is cleared.  This list is used for sorting the files\n\t\t** by date/time.\n\t\t*/\n\t\tDynamicVectorClass<FileEntryClass *> Files;\n};\n\n\n#endif\n\n"
  },
  {
    "path": "CODE/LOGIC.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LOGIC.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LOGIC.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 27, 1993                                           *\n *                                                                                             *\n *                  Last Update : July 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LogicClass::AI -- Handles AI logic processing for game objects.                           *\n *   LogicClass::Debug_Dump -- Displays logic class status to the mono screen.                 *\n *   LogicClass::Detach -- Detatch the specified target from the logic system.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"logic.h\"\n#include \t\"vortex.h\"\n\nstatic unsigned FramesPerSecond=0;\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * LogicClass::Debug_Dump -- Displays logic class status to the mono screen.                   *\n *                                                                                             *\n *    This is a debugging support routine. It displays the current state of the logic class    *\n *    to the monochrome monitor. It assumes that it is being called once per second.           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine only once per second.                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   01/26/1996 JLB : Prints game time value.                                                  *\n *=============================================================================================*/\nvoid LogicClass::Debug_Dump(MonoClass * mono) const\n{\n\t#define RECORDCOUNT\t40\n\t#define RECORDHEIGHT 21\n\tstatic int _framecounter = 0;\n\n\tstatic bool first = true;\n\tif (first) {\n\t\tfirst = false;\n\tmono->Set_Cursor(0, 0);\n\tmono->Print(Text_String(TXT_DEBUG_STRESS));\n\t}\n\n//mono->Set_Cursor(0,0);mono->Printf(\"%d\", AllowVoice);\n\n\n\t_framecounter++;\n\tmono->Set_Cursor(1, 1);mono->Printf(\"%ld\", (long)Scen.Timer);\n\tmono->Set_Cursor(10, 1);mono->Printf(\"%3d\", FramesPerSecond);\n\tmono->Set_Cursor(1, 3);mono->Printf(\"%02d:%02d:%02d\", Scen.Timer / TICKS_PER_HOUR, (Scen.Timer % TICKS_PER_HOUR)/TICKS_PER_MINUTE, (Scen.Timer % TICKS_PER_MINUTE)/TICKS_PER_SECOND);\n\n\tmono->Set_Cursor(1, 11);mono->Printf(\"%3d\", Units.Count());\n\tmono->Set_Cursor(1, 12);mono->Printf(\"%3d\", Infantry.Count());\n\tmono->Set_Cursor(1, 13);mono->Printf(\"%3d\", Aircraft.Count());\n\tmono->Set_Cursor(1, 14);mono->Printf(\"%3d\", Vessels.Count());\n\tmono->Set_Cursor(1, 15);mono->Printf(\"%3d\", Buildings.Count());\n\tmono->Set_Cursor(1, 16);mono->Printf(\"%3d\", Terrains.Count());\n\tmono->Set_Cursor(1, 17);mono->Printf(\"%3d\", Bullets.Count());\n\tmono->Set_Cursor(1, 18);mono->Printf(\"%3d\", Anims.Count());\n\tmono->Set_Cursor(1, 19);mono->Printf(\"%3d\", Teams.Count());\n\tmono->Set_Cursor(1, 20);mono->Printf(\"%3d\", Triggers.Count());\n\tmono->Set_Cursor(1, 21);mono->Printf(\"%3d\", TriggerTypes.Count());\n\tmono->Set_Cursor(1, 22);mono->Printf(\"%3d\", Factories.Count());\n\n\tSpareTicks = min((long)SpareTicks, (long)TIMER_SECOND);\n\n\t/*\n\t**\tCPU utilization record.\n\t*/\n\tmono->Sub_Window(15, 1, 6, 11);\n\tmono->Scroll();\n\tmono->Set_Cursor(0, 10);\n\tmono->Printf(\"%3d%%\", ((TIMER_SECOND-SpareTicks)*100) / TIMER_SECOND);\n\n\t/*\n\t**\tUpdate the frame rate log.\n\t*/\n\tmono->Sub_Window(22, 1, 6, 11);\n\tmono->Scroll();\n\tmono->Set_Cursor(0, 10);\n\tmono->Printf(\"%4d\", FramesPerSecond);\n\n\t/*\n\t**\tUpdate the findpath calc record.\n\t*/\n\tmono->Sub_Window(50, 1, 6, 11);\n\tmono->Scroll();\n\tmono->Set_Cursor(0, 10);\n\tmono->Printf(\"%4d\", PathCount);\n\tPathCount = 0;\n\n\t/*\n\t**\tUpdate the cell redraw record.\n\t*/\n\tmono->Sub_Window(29, 1, 6, 11);\n\tmono->Scroll();\n\tmono->Set_Cursor(0, 10);\n\tmono->Printf(\"%5d\", CellCount);\n\tCellCount = 0;\n\n\t/*\n\t**\tUpdate the target scan record.\n\t*/\n\tmono->Sub_Window(36, 1, 6, 11);\n\tmono->Scroll();\n\tmono->Set_Cursor(0, 10);\n\tmono->Printf(\"%5d\", TargetScan);\n\tTargetScan = 0;\n\n\t/*\n\t**\tSidebar redraw record.\n\t*/\n\tmono->Sub_Window(43, 1, 6, 11);\n\tmono->Scroll();\n\tmono->Set_Cursor(0, 10);\n\tmono->Printf(\"%5d\", SidebarRedraws);\n\tSidebarRedraws = 0;\n\n\t/*\n\t**\tUpdate the CPU utilization chart.\n\t*/\n\tmono->Sub_Window(15, 13, 63, 10);\n\tmono->Pan(1);\n\tmono->Sub_Window(15, 13, 64, 10);\n\tint graph = RECORDHEIGHT * fixed(TIMER_SECOND-SpareTicks, TIMER_SECOND);\n\tfor (int row = 1; row < RECORDHEIGHT; row += 2) {\n\t\tstatic char _barchar[4] = {' ', 220, 0, 219};\n\t\tchar str[2];\n\t\tint index = 0;\n\n\t\tindex |= (graph >= row) ? 0x01 : 0x00;\n\t\tindex |= (graph >= row+1) ? 0x02: 0x00;\n\n\t\tstr[1] = '\\0';\n\t\tstr[0] = _barchar[index];\n\t\tmono->Text_Print(str, 62, 9-(row/2));\n\t}\n\tmono->Sub_Window();\n\n\n\tSpareTicks = 0;\n\tFramesPerSecond = 0;\n}\n#endif\n\n\n/***********************************************************************************************\n * LogicClass::AI -- Handles AI logic processing for game objects.                             *\n *                                                                                             *\n *    This routine is used to perform the AI processing for all game objects. This includes    *\n *    all houses, factories, objects, and teams.                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/29/1994 JLB : Created.                                                                 *\n *   12/17/1994 JLB : Must perform one complete pass rather than bailing early.                *\n *   12/23/1994 JLB : Ensures that no object gets skipped if it was deleted.                   *\n *=============================================================================================*/\nvoid LogicClass::AI(void)\n{\n\tint index;\n\n\tFramesPerSecond++;\n\n\t/*\n\t** Fading to B&W or color due to the chronosphere is handled here.\n\t*/\n\tScen.Do_Fade_AI();\n\n\t/*\n\t**\tHandle any general timer trigger events.\n\t*/\n\tfor (LogicTriggerID = 0; LogicTriggerID < LogicTriggers.Count(); LogicTriggerID++) {\n\t\tTriggerClass * trig = LogicTriggers[LogicTriggerID];\n\n\t\t/*\n\t\t**\tGlobal changed trigger event might be triggered.\n\t\t*/\n\t\tif (Scen.IsGlobalChanged) {\n\t\t\tif (trig->Spring(TEVENT_GLOBAL_SET)) continue;\n\t\t\tif (trig->Spring(TEVENT_GLOBAL_CLEAR)) continue;\n\t\t}\n\n\t\t/*\n\t\t**\tBridge change event.\n\t\t*/\n\t\tif (Scen.IsBridgeChanged) {\n\t\t\tif (trig->Spring(TEVENT_ALL_BRIDGES_DESTROYED)) continue;\n\t\t}\n\n\t\t/*\n\t\t**\tGeneral time expire trigger events can be sprung without warning.\n\t\t*/\n\t\tif (trig->Spring(TEVENT_TIME)) continue;\n\n\t\t/*\n\t\t**\tThe mission timer expiration trigger event might spring if the timer is active\n\t\t**\tbut at a value of zero.\n\t\t*/\n\t\tif (Scen.MissionTimer.Is_Active() && Scen.MissionTimer == 0) {\n\t\t\tif (trig->Spring(TEVENT_MISSION_TIMER_EXPIRED)) continue;\n\t\t}\n\t}\n\n\t/*\n\t**\tClean up any status values that were maintained only for logic trigger\n\t**\tpurposes.\n\t*/\n\tif (Scen.MissionTimer.Is_Active() && Scen.MissionTimer == 0) {\n\t\tScen.MissionTimer.Stop();\n\t\tMap.Flag_To_Redraw(true);\t\t\t// Used only to cause tabs to redraw in new state.\n\t}\n\tScen.IsGlobalChanged = false;\n\tScen.IsBridgeChanged = false;\n\t/*\n\t**\tShadow creeping back over time is handled here.\n\t*/\n\tif (Special.IsShadowGrow && Rule.ShroudRate != 0 && Scen.ShroudTimer == 0) {\n\t\tScen.ShroudTimer = TICKS_PER_MINUTE * Rule.ShroudRate;\n\t\tMap.Encroach_Shadow();\n\t}\n\n\t/*\n\t**\tTeam AI is processed.\n\t*/\n\tfor (index = 0; index < Teams.Count(); index++) {\n\t\tTeams.Ptr(index)->AI();\n\t}\n\n\t/*\n\t** If there's a time quake, handle it here.\n\t*/\n\tif (TimeQuake) {\n\t\tSound_Effect(VOC_KABOOM15);\n\t\tShake_The_Screen(8);\n\t}\n\n\tChronalVortex.AI();\n\t/*\n\t**\tAI for all sentient objects is processed.\n\t*/\n\tfor (index = 0; index < Count(); index++) {\n\t\tObjectClass * obj = (*this)[index];\n\n\t\tBStart(BENCH_AI);\n\t\tobj->AI();\n\t\tBEnd(BENCH_AI);\n\n\t\tif (TimeQuake && obj != NULL && obj->IsActive && !obj->IsInLimbo && obj->Strength) {\n\t\t\tint damage = obj->Class_Of().MaxStrength * Rule.QuakeDamagePercent;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif (TimeQuakeCenter) {\n\t\t\t\tif(::Distance(obj->As_Target(),TimeQuakeCenter)/256 < MTankDistance) {\n\t\t\t\t\tswitch(obj->What_Am_I()) {\n\t\t\t\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t\t\t\tdamage = QuakeInfantryDamage;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase RTTI_BUILDING:\n\t\t\t\t\t\t\tdamage = QuakeBuildingDamage * obj->Class_Of().MaxStrength;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tdamage = QuakeUnitDamage * obj->Class_Of().MaxStrength;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (damage) {\n\t\t\t\t\t\tobj->Clicked_As_Target();\n\t\t\t\t\t\tnew AnimClass(ANIM_MINE_EXP1, obj->Center_Coord());\n\t\t\t\t\t}\n\t\t\t\t\tobj->Take_Damage(damage, 0, WARHEAD_AP, 0, true);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tobj->Take_Damage(damage, 0, WARHEAD_AP, 0, true);\n\t\t\t}\n#else\n\t\t\tobj->Take_Damage(damage, 0, WARHEAD_AP, 0, true);\n#endif\n\t\t}\n\t\t/*\n\t\t**\tIf the object was destroyed in the process of performing its AI, then\n\t\t**\tadjust the index so that no object gets skipped.\n\t\t*/\n\t\tif (obj != (*this)[index]) {\n\t\t\tindex--;\n\t\t}\n\t}\n\tHouseClass::Recalc_Attributes();\n\n\t/*\n\t**\tMap related logic is performed.\n\t*/\n\tMap.Logic();\n\n\t/*\n\t**\tFactory processing is performed.\n\t*/\n\tfor (index = 0; index < Factories.Count(); index++) {\n\t\tFactories.Ptr(index)->AI();\n\t}\n\n\t/*\n\t**\tHouse processing is performed.\n\t*/\n#ifdef FIXIT_VERSION_3\n\tif( Session.Type != GAME_NORMAL )\n\t{\n\t\tfor (HousesType house = HOUSE_MULTI1; house < HOUSE_COUNT; house++) {\n\t\t\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\t\t\tif (hptr && hptr->IsActive) {\n\t\t\t\thptr->AI();\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\t\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\t\t\tif (hptr && hptr->IsActive) {\n\t\t\t\thptr->AI();\n\t\t\t}\n\t\t}\n\t}\n#else\t//\tAI() is called redundantly 12 times in multiplayer games here. ajw\n\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\t\tif (hptr && hptr->IsActive) {\n\t\t\thptr->AI();\n\t\t}\n\t}\n#endif\n\n#ifdef FIXIT_VERSION_3\t\t\t//\tFor endgame auto-sonar pulse.\n\tif( Session.Type != GAME_NORMAL && Scen.AutoSonarTimer == 0 )\n\t{\n\t\tif( bAutoSonarPulse )\n\t\t{\n\t\t\tMap.Activate_Pulse();\n\t\t\tSound_Effect(VOC_SONAR);\n\t\t\tbAutoSonarPulse = false;\n\t\t}\n#define AUTOSONAR_PERIOD\tTICKS_PER_SECOND * 40;\n\t\tScen.AutoSonarTimer = AUTOSONAR_PERIOD;\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * LogicClass::Detach -- Detatch the specified target from the logic system.                   *\n *                                                                                             *\n *    This routine is called when the specified target object is about to be removed from the  *\n *    game system and all references to it must be severed. The only thing that the logic      *\n *    system looks for in this case is to see if the target refers to a trigger and if so,     *\n *    it scans through the trigger list and removes all references to it.                      *\n *                                                                                             *\n * INPUT:   target   -- The target to remove from the sytem.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid LogicClass::Detach(TARGET target, bool )\n{\n\t/*\n\t**\tRemove any triggers from the logic trigger list.\n\t*/\n\tif (Is_Target_Trigger(target)) {\n\t\tfor (int index = 0; index < LogicTriggers.Count(); index++) {\n\t\t\tif (As_Trigger(target) == LogicTriggers[index]) {\n\t\t\t\tLogicTriggers.Delete(index);\n\t\t\t\tindex--;\n\t\t\t}\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "CODE/LOGIC.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LOGIC.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LOGIC.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 29, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 29, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef LOGIC_H\n#define LOGIC_H\n\n#include\t\"layer.h\"\n\n/***********************************************************************************************\n**\tGame logic processing is controlled by this class. The graphic and AI logic is handled\n**\tseparately so that on slower machines, the graphic display is least affected.\n*/\nclass LogicClass : public LayerClass\n{\n\tpublic:\n\t\tvoid AI(void);\n\t\tvoid Detach(TARGET target, bool all=true);\n\t\t#ifdef CHEAT_KEYS\n\t\tvoid Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n};\n#endif\n"
  },
  {
    "path": "CODE/LZO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LZO.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZW.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 08/28/96                                                     *\n *                                                                                             *\n *                  Last Update : August 28, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef _LZO_H\n#define _LZO_H\n\n#include \"lzoconf.h\"\n\nint lzo1x_1_compress ( \tconst lzo_byte *in ,\n\t\t\t\t\t\t\t\tlzo_uint  in_len,\n                         lzo_byte *out,\n\t\t\t\t\t\t\t\tlzo_uint *out_len,\n                         lzo_voidp wrkmem );\n\n\nint lzo1x_decompress\t(  const lzo_byte *in ,\n\t\t\t\t\t\t\t\tlzo_uint  in_len,\n\t\t\t\t\t\t\t\tlzo_byte *out,\n\t\t\t\t\t\t\t\tlzo_uint *out_len,\n                         lzo_voidp );\n\n\n\n\n\n#endif\n"
  },
  {
    "path": "CODE/LZO1X.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* lzo1x.h -- public interface of the LZO1X compression algorithm\n\n   This file is part of the LZO real-time data compression library.\n\n   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer\n\n   The LZO library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Library General Public\n   License as published by the Free Software Foundation; either\n   version 2 of the License, or (at your option) any later version.\n\n   The LZO library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n   Library General Public License for more details.\n\n   You should have received a copy of the GNU Library General Public\n   License along with the LZO library; see the file COPYING.LIB.\n   If not, write to the Free Software Foundation, Inc.,\n   675 Mass Ave, Cambridge, MA 02139, USA.\n\n   Markus F.X.J. Oberhumer\n   markus.oberhumer@jk.uni-linz.ac.at\n */\n\n\n#ifndef __LZO1X_H\n#define __LZO1X_H\n\n#include \"lzoconf.h\"\n\n//#ifdef __cplusplus\n//extern \"C\" {\n//#endif\n\n\n/***********************************************************************\n//\n************************************************************************/\n\n/* Memory required for the wrkmem parameter.\n * When the required size is 0, you can also pass a NULL pointer.\n */\n\n#define LZO1X_MEM_COMPRESS      ((lzo_uint) (16384L * sizeof(lzo_byte *)))\n#define LZO1X_MEM_DECOMPRESS    (0)\n\n\n/* fast decompression */\nLZO_EXTERN(int)\nlzo1x_decompress        ( const lzo_byte *src, lzo_uint  src_len,\n                                lzo_byte *dst, lzo_uint *dst_len,\n                                lzo_voidp wrkmem /* NOT USED */ );\n\n/* safe decompression with overrun testing */\nLZO_EXTERN(int)\nlzo1x_decompress_x      ( const lzo_byte *src, lzo_uint  src_len,\n                                lzo_byte *dst, lzo_uint *dst_len,\n                                lzo_voidp wrkmem /* NOT USED */ );\n\n\n/***********************************************************************\n//\n************************************************************************/\n\nLZO_EXTERN(int)\nlzo1x_1_compress        ( const lzo_byte *src, lzo_uint  src_len,\n                                lzo_byte *dst, lzo_uint *dst_len,\n                                lzo_voidp wrkmem );\n\n\n/***********************************************************************\n// better compression ratio at the cost of more memory and time\n************************************************************************/\n\n#define LZO1X_999_MEM_COMPRESS  ((lzo_uint) (14 * 16384L * sizeof(short)))\n\nLZO_EXTERN(int)\nlzo1x_999_compress      ( const lzo_byte *src, lzo_uint  src_len,\n                                lzo_byte *dst, lzo_uint *dst_len,\n                                lzo_voidp wrkmem );\n\n\n//#ifdef __cplusplus\n//} /* extern \"C\" */\n//#endif\n\n#endif /* already included */\n\n/*\nvi:ts=4\n*/\n"
  },
  {
    "path": "CODE/LZO1X_C.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* lzo1x_c.c -- standalone LZO1X-1 compressor\n\n   This file is part of the LZO real-time data compression library.\n\n   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer\n\n   The LZO library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Library General Public\n   License as published by the Free Software Foundation; either\n   version 2 of the License, or (at your option) any later version.\n\n   The LZO library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n   Library General Public License for more details.\n\n   You should have received a copy of the GNU Library General Public\n   License along with the LZO library; see the file COPYING.LIB.\n   If not, write to the Free Software Foundation, Inc.,\n   675 Mass Ave, Cambridge, MA 02139, USA.\n\n   Markus F.X.J. Oberhumer\n   markus.oberhumer@jk.uni-linz.ac.at\n */\n\n\n#include \"lzo1x.h\"\n#define NDEBUG\n#include <assert.h>\n#include \"lzo_conf.h\"\n\n#if !defined(LZO1X) && !defined(LZO1Y)\n#  define LZO1X\n#endif\n\n\n/***********************************************************************\n//\n************************************************************************/\n\n#define M1_MAX_OFFSET\t0x0400\n#if defined(LZO1X)\n#define M2_MAX_OFFSET\t0x0800\n#elif defined(LZO1Y)\n#define M2_MAX_OFFSET\t0x0400\n#endif\n#define M3_MAX_OFFSET\t0x4000\n#define M4_MAX_OFFSET\t0xbfff\n\n#define MX_MAX_OFFSET\t(M1_MAX_OFFSET + M2_MAX_OFFSET)\n\n#define M1_MARKER\t\t0\n#define M2_MARKER\t\t64\n#define M3_MARKER\t\t32\n#define M4_MARKER\t\t16\n\n\n#define _DV2(p,shift1,shift2) \\\n\t\t(((( (lzo_uint)(p[2]) << shift1) ^ p[1]) << shift2) ^ p[0])\n#define DVAL_NEXT(dv,p) \\\n\t\tdv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_uint)(p[2]) << (2*5)))\n#define _DV(p,shift) \t\t_DV2(p,shift,shift)\n#define DVAL_FIRST(dv,p)\tdv = _DV((p),5)\n#define _DINDEX(dv,p)\t\t((40799u * (dv)) >> 5)\n#define DINDEX(dv,p)\t\t(((_DINDEX(dv,p)) & 0x3fff) << 0)\n#define UPDATE_D(dict,cycle,dv,p)\t\tdict[ DINDEX(dv,p) ] = (p)\n#define UPDATE_I(dict,cycle,index,p)\tdict[index] = (p)\n\n\n/***********************************************************************\n// compress a block of data.\n************************************************************************/\n\nstatic int do_compress(const lzo_byte *in , lzo_uint  in_len,\n\tlzo_byte *out, lzo_uint *out_len,\n\tlzo_voidp wrkmem )\n{\n\tregister const lzo_byte *ip;\n\tlzo_uint dv;\n\tlzo_byte *op;\n\tconst lzo_byte * const in_end = in + in_len;\n\tconst lzo_byte * const ip_end = in + in_len - 9 - 4;\n\tconst lzo_byte *ii;\n\tconst lzo_bytepp const dict = (const lzo_bytepp) wrkmem;\n\n\top = out;\n\tip = in;\n\tii = ip;\n\n\tDVAL_FIRST(dv,ip); UPDATE_D(dict,cycle,dv,ip); ip++;\n\tDVAL_NEXT(dv,ip);  UPDATE_D(dict,cycle,dv,ip); ip++;\n\tDVAL_NEXT(dv,ip);  UPDATE_D(dict,cycle,dv,ip); ip++;\n\tDVAL_NEXT(dv,ip);  UPDATE_D(dict,cycle,dv,ip); ip++;\n\n\twhile (1) {\n\t\tregister const lzo_byte *m_pos;\n\t\tlzo_uint m_len;\n\t\tlzo_ptrdiff_t m_off;\n\t\tlzo_uint lit;\n\n\t\tlzo_uint dindex = DINDEX(dv,ip);\n\t\tm_pos = dict[dindex];\n\t\tUPDATE_I(dict,cycle,dindex,ip);\n\n\n\t\tif (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) {\n\t\t}\n#if defined(LZO_UNALIGNED_OK_2)\n\t\telse\n\t\t\tif (* (unsigned short *) m_pos != * (unsigned short *) ip)\n#else\n\t\telse\n\t\t\tif (m_pos[0] != ip[0] || m_pos[1] != ip[1])\n#endif\n\t\t{\n\t\t} else {\n\t\t\tif (m_pos[2] == ip[2]) {\n\t\t\t\tlit = ip - ii;\n\t\t\t\tm_pos += 3;\n\t\t\t\tif (m_off <= M2_MAX_OFFSET)\n\t\t\t\t\tgoto match;\n\n\t\t\t\t/* better compression, but slower */\n\t\t\t\tif (lit == 3) {\n\t\t\t\t\tassert(op - 2 > out); op[-2] |= LZO_BYTE(3);\n\t\t\t\t\t*op++ = *ii++; *op++ = *ii++; *op++ = *ii++;\n\t\t\t\t\tgoto code_match;\n\t\t\t\t}\n\n\t\t\t\tif (*m_pos == ip[3]) {\n\t\t\t\t\tgoto match;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t/* still need a better way for finding M1 matches */\n\t\t\t}\n\t\t}\n\n\n\t/* a literal */\n\t\t++ip;\n\t\tif (ip >= ip_end) {\n\t\t\tbreak;\n\t\t}\n\t\tDVAL_NEXT(dv,ip);\n\t\tcontinue;\n\n\n\t/* a match */\n\nmatch:\n\n\t\t/* store current literal run */\n\t\tif (lit > 0) {\n\t\t\tregister lzo_uint t = lit;\n\n\t\t\tif (t <= 3) {\n\t\t\t\tassert(op - 2 > out);\n\t\t\t\top[-2] |= LZO_BYTE(t);\n\t\t\t} else {\n\t\t\t\tif (t <= 18) {\n\t\t\t\t\t*op++ = LZO_BYTE(t - 3);\n\t\t\t\t} else {\n\t\t\t\t\tregister lzo_uint tt = t - 18;\n\n\t\t\t\t\t*op++ = 0;\n\t\t\t\t\twhile (tt > 255) {\n\t\t\t\t\t\ttt -= 255;\n\t\t\t\t\t\t*op++ = 0;\n\t\t\t\t\t}\n\t\t\t\t\tassert(tt > 0);\n\t\t\t\t\t*op++ = LZO_BYTE(tt);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdo {\n\t\t\t\t*op++ = *ii++;\n\t\t\t} while (--t > 0);\n\t\t}\n\n\n\t\t/* code the match */\ncode_match:\n\t\tassert(ii == ip);\n\t\tip += 3;\n\t\tif (*m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++ ||\n\t\t    *m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++)\n\t\t{\n\t\t\t--ip;\n\t\t\tm_len = ip - ii;\n\t\t\tassert(m_len >= 3); assert(m_len <= 8);\n\n\t\t\tif (m_off <= M2_MAX_OFFSET) {\n\t\t\t\tm_off -= 1;\n\t\t\t\t*op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2));\n\t\t\t\t*op++ = LZO_BYTE(m_off >> 3);\n\t\t\t} else {\n\t\t\t\tif (m_off <= M3_MAX_OFFSET) {\n\t\t\t\t\tm_off -= 1;\n\t\t\t\t\t*op++ = LZO_BYTE(M3_MARKER | (m_len - 2));\n\t\t\t\t\tgoto m3_m4_offset;\n\t\t\t\t} else {\n\t\t\t\t\tm_off -= 0x4000;\n\t\t\t\t\tassert(m_off > 0); assert(m_off <= 0x7fff);\n\t\t\t\t\t*op++ = LZO_BYTE(M4_MARKER |\n\t\t\t\t\t                 ((m_off & 0x4000) >> 11) | (m_len - 2));\n\t\t\t\t\tgoto m3_m4_offset;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tconst lzo_byte *end;\n\t\t\tend = in_end;\n\t\t\twhile (ip < end && *m_pos == *ip) {\n\t\t\t\tm_pos++;\n\t\t\t\tip++;\n\t\t\t}\n\t\t\tm_len = (ip - ii);\n\t\t\tassert(m_len >= 3);\n\n\t\t\tif (m_off <= M3_MAX_OFFSET) {\n\t\t\t\tm_off -= 1;\n\t\t\t\tif (m_len <= 33) {\n\t\t\t\t\t*op++ = LZO_BYTE(M3_MARKER | (m_len - 2));\n\t\t\t\t} else {\n\t\t\t\t\tm_len -= 33;\n\t\t\t\t\t*op++ = M3_MARKER | 0;\n\t\t\t\t\tgoto m3_m4_len;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tm_off -= 0x4000;\n\t\t\t\tassert(m_off > 0); assert(m_off <= 0x7fff);\n\t\t\t\tif (m_len <= 9) {\n\t\t\t\t\t*op++ = LZO_BYTE(M4_MARKER |\n\t\t\t\t\t                 ((m_off & 0x4000) >> 11) | (m_len - 2));\n\t\t\t\t} else {\n\t\t\t\t\tm_len -= 9;\n\t\t\t\t\t*op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11));\nm3_m4_len:\n\t\t\t\t\twhile (m_len > 255) {\n\t\t\t\t\t\tm_len -= 255;\n\t\t\t\t\t\t*op++ = 0;\n\t\t\t\t\t}\n\t\t\t\t\tassert(m_len > 0);\n\t\t\t\t\t*op++ = LZO_BYTE(m_len);\n\t\t\t\t}\n\t\t\t}\n\nm3_m4_offset:\n\t\t\t*op++ = LZO_BYTE((m_off & 63) << 2);\n\t\t\t*op++ = LZO_BYTE(m_off >> 6);\n\t\t}\n\n\t\tii = ip;\n\t\tif (ip >= ip_end) {\n\t\t\tbreak;\n\t\t}\n\t\tDVAL_FIRST(dv,ip);\n\t}\n\n\t/* store final literal run */\n\tif (in_end - ii > 0) {\n\t\tregister lzo_uint t = in_end - ii;\n\n\t\tif (op == out && t <= 238) {\n\t\t\t*op++ = LZO_BYTE(17 + t);\n\t\t} else {\n\t\t\tif (t <= 3) {\n\t\t\t\top[-2] |= LZO_BYTE(t);\n\t\t\t} else {\n\t\t\t\tif (t <= 18) {\n\t\t\t\t\t*op++ = LZO_BYTE(t - 3);\n\t\t\t\t} else {\n\t\t\t\t\tregister lzo_uint tt = t - 18;\n\n\t\t\t\t\t*op++ = 0;\n\t\t\t\t\twhile (tt > 255) {\n\t\t\t\t\t\ttt -= 255;\n\t\t\t\t\t\t*op++ = 0;\n\t\t\t\t\t}\n\t\t\t\t\tassert(tt > 0);\n\t\t\t\t\t*op++ = LZO_BYTE(tt);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdo {\n\t\t\t*op++ = *ii++;\n\t\t} while (--t > 0);\n\t}\n\n\t*out_len = op - out;\n\treturn LZO_E_OK;\n}\n\n\n/***********************************************************************\n// public entry point\n************************************************************************/\n\nint lzo1x_1_compress     ( const lzo_byte *in , lzo_uint  in_len,\n                                 lzo_byte *out, lzo_uint *out_len,\n                                 lzo_voidp wrkmem )\n{\n\tlzo_byte *op = out;\n\tint r = LZO_E_OK;\n\n\tif (in_len <= 0)\n\t\t*out_len = 0;\n\telse if (in_len <= 9 + 4)\n\t{\n\t\t*op++ = LZO_BYTE(17 + in_len);\n\t\tdo *op++ = *in++; while (--in_len > 0);\n\t\t*out_len = op - out;\n\t}\n\telse\n\t\tr = do_compress(in,in_len,out,out_len,wrkmem);\n\n\tif (r == LZO_E_OK)\n\t{\n\t\top = out + *out_len;\n\t\t*op++ = M4_MARKER | 1;\n\t\t*op++ = 0;\n\t\t*op++ = 0;\n\t\t*out_len += 3;\n\t}\n\n\treturn r;\n}\n\n\n/*\nvi:ts=4\n*/\n"
  },
  {
    "path": "CODE/LZO1X_D.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* lzo1x_d.c -- standalone LZO1X decompressor\n\n   This file is part of the LZO real-time data compression library.\n\n   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer\n\n   The LZO library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Library General Public\n   License as published by the Free Software Foundation; either\n   version 2 of the License, or (at your option) any later version.\n\n   The LZO library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n   Library General Public License for more details.\n\n   You should have received a copy of the GNU Library General Public\n   License along with the LZO library; see the file COPYING.LIB.\n   If not, write to the Free Software Foundation, Inc.,\n   675 Mass Ave, Cambridge, MA 02139, USA.\n\n   Markus F.X.J. Oberhumer\n   markus.oberhumer@jk.uni-linz.ac.at\n */\n\n\n#include \"lzo1x.h\"\n#define NDEBUG\n#include <assert.h>\n\n#if !defined(LZO1X) && !defined(LZO1Y)\n#  define LZO1X\n#endif\n\n#if 1\n#  define TEST_IP\t\t\t\t1\n#else\n#  define TEST_IP\t\t\t\t(ip < ip_end)\n#endif\n\n\n/***********************************************************************\n// decompress a block of data.\n************************************************************************/\n\nint lzo1x_decompress     ( const lzo_byte *in , lzo_uint  in_len,\n                                 lzo_byte *out, lzo_uint *out_len,\n                                 lzo_voidp )\n{\n\tregister lzo_byte *op;\n\tregister const lzo_byte *ip;\n\tregister lzo_uint t;\n\tregister const lzo_byte *m_pos;\n\tconst lzo_byte * const ip_end = in + in_len;\n\n\t*out_len = 0;\n\n\top = out;\n\tip = in;\n\n\tif (*ip > 17)\n\t{\n\t\tt = *ip++ - 17;\n\t\tgoto first_literal_run;\n\t}\n\n\twhile (TEST_IP)\n\t{\n\t\tt = *ip++;\n\t\tif (t >= 16)\n\t\t\tgoto match;\n\t\t/* a literal run */\n\t\tif (t == 0)\n\t\t{\n\t\t\tt = 15;\n\t\t\twhile (*ip == 0)\n\t\t\t\tt += 255, ip++;\n\t\t\tt += *ip++;\n\t\t}\n\t\t/* copy literals */\n\t\t*op++ = *ip++; *op++ = *ip++; *op++ = *ip++;\nfirst_literal_run:\n\t\tdo *op++ = *ip++; while (--t > 0);\n\n\n\t\tt = *ip++;\n\n\t\tif (t >= 16)\n\t\t\tgoto match;\n#if defined(LZO1X)\n\t\tm_pos = op - 1 - 0x800;\n#elif defined(LZO1Y)\n\t\tm_pos = op - 1 - 0x400;\n#endif\n\t\tm_pos -= t >> 2;\n\t\tm_pos -= *ip++ << 2;\n\t\t*op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos++;\n\t\tgoto match_done;\n\n\n\t\t/* handle matches */\n\t\twhile (TEST_IP)\n\t\t{\n\t\t\tif (t < 16)\t\t\t\t\t\t/* a M1 match */\n\t\t\t{\n\t\t\t\tm_pos = op - 1;\n\t\t\t\tm_pos -= t >> 2;\n\t\t\t\tm_pos -= *ip++ << 2;\n\t\t\t\t*op++ = *m_pos++; *op++ = *m_pos++;\n\t\t\t}\n\t\t\telse\n\t\t\t{\nmatch:\n\t\t\t\tif (t >= 64)\t\t\t\t/* a M2 match */\n\t\t\t\t{\n\t\t\t\t\tm_pos = op - 1;\n#if defined(LZO1X)\n\t\t\t\t\tm_pos -= (t >> 2) & 7;\n\t\t\t\t\tm_pos -= *ip++ << 3;\n\t\t\t\t\tt = (t >> 5) - 1;\n#elif defined(LZO1Y)\n\t\t\t\t\tm_pos -= (t >> 2) & 3;\n\t\t\t\t\tm_pos -= *ip++ << 2;\n\t\t\t\t\tt = (t >> 4) - 3;\n#endif\n\t\t\t\t}\n\t\t\t\telse if (t >= 32)\t\t\t/* a M3 match */\n\t\t\t\t{\n\t\t\t\t\tt &= 31;\n\t\t\t\t\tif (t == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tt = 31;\n\t\t\t\t\t\twhile (*ip == 0)\n\t\t\t\t\t\t\tt += 255, ip++;\n\t\t\t\t\t\tt += *ip++;\n\t\t\t\t\t}\n\t\t\t\t\tm_pos = op - 1;\n\t\t\t\t\tm_pos -= *ip++ >> 2;\n\t\t\t\t\tm_pos -= *ip++ << 6;\n\t\t\t\t}\n\t\t\t\telse\t\t\t\t\t\t/* a M4 match */\n\t\t\t\t{\n\t\t\t\t\tm_pos = op;\n\t\t\t\t\tm_pos -= (t & 8) << 11;\n\t\t\t\t\tt &= 7;\n\t\t\t\t\tif (t == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tt = 7;\n\t\t\t\t\t\twhile (*ip == 0)\n\t\t\t\t\t\t\tt += 255, ip++;\n\t\t\t\t\t\tt += *ip++;\n\t\t\t\t\t}\n\t\t\t\t\tm_pos -= *ip++ >> 2;\n\t\t\t\t\tm_pos -= *ip++ << 6;\n\t\t\t\t\tif (m_pos == op)\n\t\t\t\t\t\tgoto eof_found;\n\t\t\t\t\tm_pos -= 0x4000;\n\t\t\t\t}\n\t\t\t\t*op++ = *m_pos++; *op++ = *m_pos++;\n\t\t\t\tdo *op++ = *m_pos++; while (--t > 0);\n\t\t\t}\n\nmatch_done:\n\t\t\tt = ip[-2] & 3;\n\t\t\tif (t == 0)\n\t\t\t\tbreak;\n\t\t\t/* copy literals */\n\t\t\tdo *op++ = *ip++; while (--t > 0);\n\t\t\tt = *ip++;\n\t\t}\n\t}\n\n\t/* ip == ip_end and no EOF code was found */\n\n\t//Unreachable - ST 9/5/96 5:07PM\n\t//*out_len = op - out;\n\t//return (ip == ip_end ? LZO_E_EOF_NOT_FOUND : LZO_E_ERROR);\n\neof_found:\n\tassert(t == 1);\n\t*out_len = op - out;\n\treturn (ip == ip_end ? LZO_E_OK : LZO_E_ERROR);\n}\n\n\n/*\nvi:ts=4\n*/\n"
  },
  {
    "path": "CODE/LZOCONF.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* lzoconf.h -- configuration for the LZO real-time data compression library\n\n   This file is part of the LZO real-time data compression library.\n\n   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer\n\n   The LZO library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Library General Public\n   License as published by the Free Software Foundation; either\n   version 2 of the License, or (at your option) any later version.\n\n   The LZO library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n   Library General Public License for more details.\n\n   You should have received a copy of the GNU Library General Public\n   License along with the LZO library; see the file COPYING.LIB.\n   If not, write to the Free Software Foundation, Inc.,\n   675 Mass Ave, Cambridge, MA 02139, USA.\n\n   Markus F.X.J. Oberhumer\n   markus.oberhumer@jk.uni-linz.ac.at\n */\n\n\n#ifndef __LZOCONF_H\n#define __LZOCONF_H\n\n#define LZO_VERSION             0x0200\n#define LZO_VERSION_STRING      \"0.20\"\n#define LZO_VERSION_DATE        \"11 Aug 1996\"\n\n\n#include <limits.h>             /* CHAR_BIT, UINT_MAX, ULONG_MAX */\n#if !defined(CHAR_BIT) || (CHAR_BIT != 8)\n#  error invalid CHAR_BIT\n#endif\n\n//#ifdef __cplusplus\n//extern \"C\" {\n//#endif\n\n\n/***********************************************************************\n// defines\n************************************************************************/\n\n#if defined(__MSDOS__) || defined(MSDOS)\n#  define __LZO_MSDOS\n#  if (UINT_MAX < 0xffffffffL)\n#    define __LZO_MSDOS16 \n#  endif\n#endif\n\n\n/***********************************************************************\n// integral and pointer types\n************************************************************************/\n\n/* Unsigned type with 32 bits or more */\n#if (UINT_MAX >= 0xffffffffL)\n   typedef unsigned int     lzo_uint;\n   typedef int              lzo_int;\n#  define LZO_UINT_MAX      UINT_MAX\n#elif (ULONG_MAX >= 0xffffffffL)\n   typedef unsigned long    lzo_uint;\n   typedef long             lzo_int;\n#  define LZO_UINT_MAX      ULONG_MAX\n#else\n#  error lzo_uint\n#endif\n\n\n/* Memory model that allows to access memory at offsets of lzo_uint.\n * Huge pointers (16 bit MSDOS) are somewhat slow, but they work\n * fine and I really don't care about 16 bit compiler\n * optimizations nowadays.\n */\n#if (LZO_UINT_MAX <= UINT_MAX)\n#  define __LZO_MMODEL\n#elif defined(__LZO_MSDOS16)\n#  define __LZO_MMODEL      huge\n#  define __LZO_ENTRY       __cdecl\n#else\n#  error __LZO_MMODEL\n#endif\n\n\n/* no typedef here because of const-pointer issues */\n#define lzo_byte            unsigned char __LZO_MMODEL\n#define lzo_voidp           void __LZO_MMODEL *\n#define lzo_bytep           unsigned char __LZO_MMODEL *\n#define lzo_uintp           lzo_uint __LZO_MMODEL *\n#define lzo_intp            lzo_int __LZO_MMODEL *\n#define lzo_voidpp          lzo_voidp __LZO_MMODEL * \n#define lzo_bytepp          lzo_bytep __LZO_MMODEL * \n\n\n/* Unsigned type that can store all bits of a lzo_voidp */\ntypedef unsigned long       lzo_ptr_t;\n\n/* Align a pointer on a boundary that is a multiple of 'size' */\n#define LZO_ALIGN(ptr,size) \\\n    ((lzo_voidp) (((lzo_ptr_t)(ptr) + (size)-1) & ~((lzo_ptr_t)((size)-1))))\n\n\n/***********************************************************************\n// function types\n************************************************************************/\n\n//#ifdef __cplusplus\n//#  define LZO_EXTERN_C          extern \"C\"\n//#else\n#  define LZO_EXTERN_C          extern\n//#endif\n\n\n#if !defined(__LZO_ENTRY)       /* calling convention */\n#  define __LZO_ENTRY\n#endif\n#if !defined(__LZO_EXPORT)      /* DLL export (and maybe size) information */\n#  define __LZO_EXPORT\n#endif\n\n#if !defined(LZO_EXTERN)\n#  define LZO_EXTERN(_rettype)  LZO_EXTERN_C _rettype __LZO_ENTRY __LZO_EXPORT\n#endif\n\n\ntypedef int __LZO_ENTRY\n(__LZO_EXPORT *lzo_compress_t)  ( const lzo_byte *src, lzo_uint  src_len,\n                                        lzo_byte *dst, lzo_uint *dst_len,\n                                        lzo_voidp wrkmem );\n\ntypedef int __LZO_ENTRY\n(__LZO_EXPORT *lzo_decompress_t)( const lzo_byte *src, lzo_uint  src_len,\n                                        lzo_byte *dst, lzo_uint *dst_len,\n                                        lzo_voidp wrkmem );\n\n\n/* a progress indicator callback function */\ntypedef void __LZO_ENTRY\n(__LZO_EXPORT *lzo_progress_callback_t)(lzo_uint,lzo_uint);\n\n\n/***********************************************************************\n// error codes and prototypes\n************************************************************************/\n\n/* Error codes for the compression/decompression functions. Negative\n * values are errors, positive values will be used for special but\n * normal events.\n */\n#define LZO_E_OK                    0\n#define LZO_E_ERROR                 (-1)\n#define LZO_E_NOT_COMPRESSIBLE      (-2)    /* not used right now */\n#define LZO_E_EOF_NOT_FOUND         (-3)\n#define LZO_E_INPUT_OVERRUN         (-4)\n#define LZO_E_OUTPUT_OVERRUN        (-5)\n#define LZO_E_LOOKBEHIND_OVERRUN    (-6)\n#define LZO_E_OUT_OF_MEMORY         (-7)    /* not used right now */\n\n\n/* this should be the first function you call. Check the return code ! */\nLZO_EXTERN(int) lzo_init(void);\n\n/* version functions (useful for shared libraries) */\nLZO_EXTERN(unsigned) lzo_version(void);\nLZO_EXTERN(const char *) lzo_version_string(void);\n\n/* string functions */\nLZO_EXTERN(int)\nlzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len);\nLZO_EXTERN(lzo_voidp)\nlzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len);\nLZO_EXTERN(lzo_voidp)\nlzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len);\nLZO_EXTERN(lzo_voidp)\nlzo_memset(lzo_voidp _s, int _c, lzo_uint _len);\n\n/* checksum functions */\nLZO_EXTERN(lzo_uint)\nlzo_adler32(lzo_uint _adler, const lzo_byte *_buf, lzo_uint _len);\n\n/* misc. */\nLZO_EXTERN(int) lzo_assert(int _expr);\nLZO_EXTERN(int) _lzo_config_check(void);\n\n\n//#ifdef __cplusplus\n//} /* extern \"C\" */\n//#endif\n\n#endif /* already included */\n\n/*\nvi:ts=4\n*/\n"
  },
  {
    "path": "CODE/LZOPIPE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LZOPIPE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZWPIPE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LZWPipe::Flush -- Flushes any partially accumulated block.                                *\n *   LZWPipe::LZWPipe -- Constructor for the LZO processor pipe.                               *\n *   LZWPipe::Put -- Send some data through the LZO processor pipe.                            *\n *   LZWPipe::~LZWPipe -- Deconstructor for the LZO pipe object.                               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"lzopipe.h\"\n#include\t\"lzo.h\"\n#include\t\"buff.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * LZOPipe::LZOPipe -- Constructor for the LZO processor pipe.                                 *\n *                                                                                             *\n *    This will initialize the LZOPipe object so that it is prepared for compression or        *\n *    decompression as indicated.                                                              *\n *                                                                                             *\n * INPUT:   decrypt  -- Should decompression be performed?                                     *\n *                                                                                             *\n *          blocksize-- The size of the data blocks to process.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZOPipe::LZOPipe(CompControl control, int blocksize) :\n\t\tControl(control),\n\t\tCounter(0),\n\t\tBuffer(NULL),\n\t\tBuffer2(NULL),\n\t\tBlockSize(blocksize)\n{\n\tSafetyMargin = BlockSize;\n\tBuffer = new char[BlockSize+SafetyMargin];\n\tBuffer2 = new char[BlockSize+SafetyMargin];\n\tBlockHeader.CompCount = 0xFFFF;\n}\n\n\n/***********************************************************************************************\n * LZOPipe::~LZOPipe -- Deconstructor for the LZO pipe object.                                 *\n *                                                                                             *\n *    This will free any buffers it may have allocated.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZOPipe::~LZOPipe(void)\n{\n\tdelete [] Buffer;\n\tBuffer = NULL;\n\n\tdelete [] Buffer2;\n\tBuffer2 = NULL;\n}\n\n\n/***********************************************************************************************\n * LZOPipe::Put -- Send some data through the LZO processor pipe.                              *\n *                                                                                             *\n *    This routine will take the data requested and process it (decompression or compression). *\n *    It does this by accumulating the necessary bytes to make a whole block. Then the block   *\n *    is processed and the entire contents are flushed to the next pipe segment in the chain.  *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the data to be fed to this LZO processor.                   *\n *                                                                                             *\n *          length   -- The number of bytes received.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes output at the far distant final link in    *\n *          the pipe chain.                                                                    *\n *                                                                                             *\n * WARNINGS:   The compression process may be slow as well as consuming two buffers.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LZOPipe::Put(void const * source, int slen)\n{\n\tif (source == NULL || slen < 1) {\n\t\treturn(Pipe::Put(source, slen));\n\t}\n\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tCopy as much as can fit into the buffer from the source data supplied.\n\t*/\n\tif (Control ==  DECOMPRESS) {\n\n\t\twhile (slen > 0) {\n\n\t\t\t/*\n\t\t\t**\tFirst check to see if we are in the block header accumulation phase.\n\t\t\t**\tWhen a whole block header has been accumulated, only then will the regular\n\t\t\t**\tdata processing begin for the block.\n\t\t\t*/\n\t\t\tif (BlockHeader.CompCount == 0xFFFF) {\n\t\t\t\tint len = (slen < (sizeof(BlockHeader)-Counter)) ? slen : (sizeof(BlockHeader)-Counter);\n\t\t\t\tmemmove(&Buffer[Counter], source, len);\n\t\t\t\tsource = ((char *)source) + len;\n\t\t\t\tslen -= len;\n\t\t\t\tCounter += len;\n\n\t\t\t\t/*\n\t\t\t\t**\tA whole block header has been accumulated. Store it for safekeeping.\n\t\t\t\t*/\n\t\t\t\tif (Counter == sizeof(BlockHeader)) {\n\t\t\t\t\tmemmove(&BlockHeader, Buffer, sizeof(BlockHeader));\n\t\t\t\t\tCounter = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tFill the buffer with compressed data until there is enough to make a whole\n\t\t\t**\tdata block.\n\t\t\t*/\n\t\t\tif (slen > 0) {\n\t\t\t\tint len = (slen < (BlockHeader.CompCount-Counter)) ? slen : (BlockHeader.CompCount-Counter);\n\n\t\t\t\tmemmove(&Buffer[Counter], source, len);\n\t\t\t\tslen -= len;\n\t\t\t\tsource = ((char *)source) + len;\n\t\t\t\tCounter += len;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf an entire block has been accumulated, then uncompress it and feed it\n\t\t\t\t**\tthrough the pipe.\n\t\t\t\t*/\n\t\t\t\tif (Counter == BlockHeader.CompCount) {\n\t\t\t\t\tunsigned int length = sizeof (Buffer2);\n\t\t\t\t\tlzo1x_decompress ((unsigned char*)Buffer, BlockHeader.CompCount, (unsigned char*)Buffer2, &length, NULL);\n\t\t\t\t\ttotal += Pipe::Put(Buffer2, BlockHeader.UncompCount);\n\t\t\t\t\tCounter = 0;\n\t\t\t\t\tBlockHeader.CompCount = 0xFFFF;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tIf the buffer already contains some data, then any new data must be stored\n\t\t**\tinto the staging buffer until a full set has been accumulated.\n\t\t*/\n\t\tif (Counter > 0) {\n\t\t\tint tocopy = (slen < (BlockSize-Counter)) ? slen : (BlockSize-Counter);\n\t\t\tmemmove(&Buffer[Counter], source, tocopy);\n\t\t\tsource = ((char *)source) + tocopy;\n\t\t\tslen -= tocopy;\n\t\t\tCounter += tocopy;\n\n\t\t\tif (Counter == BlockSize) {\n\t\t\t\tunsigned int len = sizeof (Buffer2);\n\t\t\t\tchar *dictionary = new char [64*1024];\n\t\t\t\tlzo1x_1_compress ((unsigned char*)Buffer, BlockSize, (unsigned char*)Buffer2, &len, dictionary);\n\t\t\t\tdelete [] dictionary;\n\t\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\t\tBlockHeader.UncompCount = (unsigned short)BlockSize;\n\t\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t\t\tCounter = 0;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tProcess the source data in whole block chunks until there is insufficient\n\t\t**\tsource data left for a whole data block.\n\t\t*/\n\t\twhile (slen >= BlockSize) {\n\t\t\tunsigned int len = sizeof (Buffer2);\n\t\t\tchar *dictionary = new char [64*1024];\n\t\t\tlzo1x_1_compress ((unsigned char*)source, BlockSize, (unsigned char*)Buffer2, &len, dictionary);\n\t\t\tdelete [] dictionary;\n\t\t\tsource = ((char *)source) + BlockSize;\n\t\t\tslen -= BlockSize;\n\n\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\tBlockHeader.UncompCount = (unsigned short)BlockSize;\n\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is any remaining data, then it is stored into the buffer\n\t\t**\tuntil a full data block has been accumulated.\n\t\t*/\n\t\tif (slen > 0) {\n\t\t\tmemmove(Buffer, source, slen);\n\t\t\tCounter = slen;\n\t\t}\n\t}\n\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * LZOPipe::Flush -- Flushes any partially accumulated block.                                  *\n *                                                                                             *\n *    This routine is called when any buffered data must be flushed out the pipe. For the      *\n *    compression process, this will generate the sub-sized compressed block. For              *\n *    decompression, this routine should not have any data in the buffer. In such a case, it   *\n *    means that the data source was prematurely truncated. In such a case, just dump the      *\n *    accumulated data through the pipe.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of data bytes output to the distant final link in   *\n *          the pipe chain.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LZOPipe::Flush(void)\n{\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tIf there is accumulated data, then it must processed.\n\t*/\n\tif (Counter > 0) {\n\t\tif (Control == DECOMPRESS) {\n\n\t\t\t/*\n\t\t\t**\tIf the accumulated data is insufficient to make a block header, then\n\t\t\t**\tthis means the data has been truncated. Just dump the data through\n\t\t\t**\tas if were already decompressed.\n\t\t\t*/\n\t\t\tif (BlockHeader.CompCount == 0xFFFF) {\n\t\t\t\ttotal += Pipe::Put(Buffer, Counter);\n\t\t\t\tCounter = 0;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tThere appears to be a partial block accumulated in the buffer. It would\n\t\t\t**\tbe disastrous to try to decompress the data since there wouldn't be\n\t\t\t**\tthe special end of data code that LZO decompression needs. In this\n\t\t\t**\tcase, dump the data out as if it were already decompressed.\n\t\t\t*/\n\t\t\tif (Counter > 0) {\n\t\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\t\ttotal += Pipe::Put(Buffer, Counter);\n\t\t\t\tCounter = 0;\n\t\t\t\tBlockHeader.CompCount = 0xFFFF;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tA partial block in the compression process is a normal occurrence. Just\n\t\t\t**\tcompress the partial block and output normally.\n\t\t\t*/\n\t\t\tunsigned int len = sizeof (Buffer2);\n\t\t\tchar *dictionary = new char [64*1024];\n\t\t\tlzo1x_1_compress ((unsigned char*)Buffer, Counter, (unsigned char *)Buffer2, &len, dictionary);\n\t\t\tdelete [] dictionary;\n\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\tBlockHeader.UncompCount = (unsigned short)Counter;\n\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t\tCounter = 0;\n\t\t}\n\t}\n\n\ttotal += Pipe::Flush();\n\treturn(total);\n}\n\n"
  },
  {
    "path": "CODE/LZOPIPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LZOPIPE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZOPIPE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef LZOPIPE_H\n#define LZOPIPE_H\n\n#include\t\"pipe.h\"\n\n\n/*\n**\tPerforms LZO compression/decompression on the data stream that is piped through this\n**\tclass. The data is compressed in blocks so of small enough size to be compressed\n**\tquickly and large enough size to get decent compression rates.\n*/\nclass LZOPipe : public Pipe\n{\n\tpublic:\n\t\ttypedef enum CompControl {\n\t\t\tCOMPRESS,\n\t\t\tDECOMPRESS\n\t\t} CompControl;\n\n\t\tLZOPipe(CompControl, int blocksize=1024*8);\n\t\tvirtual ~LZOPipe(void);\n\n\t\tvirtual int Flush(void);\n\t\tvirtual int Put(void const * source, int slen);\n\n\tprivate:\n\t\t/*\n\t\t**\tThis tells the pipe if it should be decompressing or compressing the data stream.\n\t\t*/\n\t\tCompControl Control;\n\n\t\t/*\n\t\t**\tThe number of bytes accumulated into the staging buffer.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tPointer to the working buffer that compression/decompression will use.\n\t\t*/\n\t\tchar * Buffer;\n\t\tchar * Buffer2;\n\n\t\t/*\n\t\t**\tThe working block size. Data will be compressed in chunks of this size.\n\t\t*/\n\t\tint BlockSize;\n\n\t\t/*\n\t\t**\tProbably dont need this anymore as LZO decompresses into a staging buffer.\n\t\t*/\n\t\tint SafetyMargin;\n\n\t\t/*\n\t\t**\tEach block has a header of this format.\n\t\t*/\n\t\tstruct {\n\t\t\tunsigned short CompCount;\t\t// Size of data block (compressed).\n\t\t\tunsigned short UncompCount;\t// Bytes of uncompressed data it represents.\n\t\t} BlockHeader;\n\n\t\tLZOPipe(LZOPipe & rvalue);\n\t\tLZOPipe & operator = (LZOPipe const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/LZOSTRAW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LZOSTRAW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZOSTRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LZOStraw::Get -- Fetch data through the LZO processor.                                    *\n *   LZOStraw::LZOStraw -- Constructor for LZO straw object.                                   *\n *   LZOStraw::~LZOStraw -- Destructor for the LZO straw.                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"lzostraw.h\"\n#include\t\"lzo.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * LZOStraw::LZOStraw -- Constructor for LZO straw object.                                     *\n *                                                                                             *\n *    This will initialize the LZO straw object. Whether the object is to compress or          *\n *    decompress and the block size to use is specified. The data is compressed in blocks      *\n *    that are sized to be quick to compress and yet still yield good compression ratios.      *\n *                                                                                             *\n * INPUT:   decrypt  -- Should the data be decompressed?                                       *\n *                                                                                             *\n *          blocksize-- The size of the blocks to process.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   It takes two buffers of the blocksize specified if compression is to be         *\n *             performed.                                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZOStraw::LZOStraw(CompControl control, int blocksize) :\n\t\tControl(control),\n\t\tCounter(0),\n\t\tBuffer(NULL),\n\t\tBuffer2(NULL),\n\t\tBlockSize(blocksize)\n{\n\tSafetyMargin = BlockSize;\n\tBuffer = new char[BlockSize+SafetyMargin];\n\tif (control == COMPRESS) {\n\t\tBuffer2 = new char[BlockSize+SafetyMargin];\n\t}\n}\n\n\n/***********************************************************************************************\n * LZOStraw::~LZOStraw -- Destructor for the LZO straw.                                        *\n *                                                                                             *\n *    The destructor will free up the allocated buffers that it allocated in the constructor.  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZOStraw::~LZOStraw(void)\n{\n\tdelete [] Buffer;\n\tBuffer = NULL;\n\n\tdelete [] Buffer2;\n\tBuffer2 = NULL;\n}\n\n\n/***********************************************************************************************\n * LZOStraw::Get -- Fetch data through the LZO processor.                                      *\n *                                                                                             *\n *    This routine will fetch the data bytes specified. It does this by first accumulating     *\n *    a full block of data and then compressing or decompressing it as indicated. Subsequent   *\n *    requests for data will draw from this buffer of processed data until it is exhausted     *\n *    and another block must be fetched.                                                       *\n *                                                                                             *\n * INPUT:   destbuf  -- Pointer to the buffer to hold the data requested.                      *\n *                                                                                             *\n *          length   -- The number of data bytes requested.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes stored into the buffer. If this number     *\n *          is less than that requested, then this indicates that the data source has been     *\n *          exhausted.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LZOStraw::Get(void * destbuf, int slen)\n{\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tVerify parameters for legality.\n\t*/\n\tif (destbuf == NULL || slen < 1) {\n\t\treturn(0);\n\t}\n\n\twhile (slen > 0) {\n\n\t\t/*\n\t\t**\tCopy as much data is requested and available into the desired\n\t\t**\tdestination buffer.\n\t\t*/\n\t\tif (Counter) {\n\t\t\tint len = (slen < Counter) ? slen : Counter;\n\t\t\tif (Control == DECOMPRESS) {\n\t\t\t\tmemmove(destbuf, &Buffer[BlockHeader.UncompCount-Counter], len);\n\t\t\t} else {\n\t\t\t\tmemmove(destbuf, &Buffer2[(BlockHeader.CompCount+sizeof(BlockHeader))-Counter], len);\n\t\t\t}\n\t\t\tdestbuf = ((char *)destbuf) + len;\n\t\t\tslen -= len;\n\t\t\tCounter -= len;\n\t\t\ttotal += len;\n\t\t}\n\t\tif (slen == 0) break;\n\n\t\tif (Control == DECOMPRESS) {\n\t\t\tint incount = Straw::Get(&BlockHeader, sizeof(BlockHeader));\n\t\t\tif (incount != sizeof(BlockHeader)) break;\n\n\t\t\tchar *staging_buffer = new char [BlockHeader.CompCount];\n\t\t\tincount = Straw::Get(staging_buffer, BlockHeader.CompCount);\n\t\t\tif (incount != BlockHeader.CompCount) break;\n\t\t\tunsigned int length = sizeof(Buffer);\n\t\t\tlzo1x_decompress ((unsigned char*)staging_buffer, BlockHeader.CompCount, (unsigned char*)Buffer, &length, NULL);\n\t\t\tdelete [] staging_buffer;\n\t\t\tCounter = BlockHeader.UncompCount;\n\t\t} else {\n\t\t\tBlockHeader.UncompCount = (unsigned short)Straw::Get(Buffer, BlockSize);\n\t\t\tif (BlockHeader.UncompCount == 0) break;\n\t\t\tchar *dictionary = new char [64*1024];\n\t\t\tunsigned int length = sizeof (Buffer2) - sizeof (BlockHeader);\n\t\t\tlzo1x_1_compress ((unsigned char*)Buffer, BlockHeader.UncompCount, (unsigned char*)(&Buffer2[sizeof(BlockHeader)]), &length, dictionary);\n\t\t\tBlockHeader.CompCount = (unsigned short)length;\n\t\t\tdelete [] dictionary;\n\t\t\tmemmove(Buffer2, &BlockHeader, sizeof(BlockHeader));\n\t\t\tCounter = BlockHeader.CompCount+sizeof(BlockHeader);\n\t\t}\n\t}\n\n\treturn(total);\n}\n"
  },
  {
    "path": "CODE/LZOSTRAW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LZoSTRAW.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZOSTRAW.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef LZOSTRAW_H\n#define LZOSTRAW_H\n\n\n#include\t\"straw.h\"\n\n/*\n**\tThis class handles LZO compression/decompression to the data stream that is drawn through\n**\tthis class. Note that for compression, two internal buffers are required. For decompression\n**\tonly one buffer is required. This changes the memory footprint of this class depending on\n**\tthe process desired.\n*/\nclass LZOStraw : public Straw\n{\n\tpublic:\n\t\ttypedef enum CompControl {\n\t\t\tCOMPRESS,\n\t\t\tDECOMPRESS\n\t\t} CompControl;\n\n\t\tLZOStraw(CompControl control, int blocksize=1024*8);\n\t\tvirtual ~LZOStraw(void);\n\n\t\tvirtual int Get(void * source, int slen);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis tells the pipe if it should be decompressing or compressing the data stream.\n\t\t*/\n\t\tCompControl Control;\n\n\t\t/*\n\t\t**\tThe number of bytes accumulated into the staging buffer.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tPointer to the working buffer that compression/decompression will use.\n\t\t*/\n\t\tchar * Buffer;\n\t\tchar * Buffer2;\n\n\t\t/*\n\t\t**\tThe working block size. Data will be compressed in chunks of this size.\n\t\t*/\n\t\tint BlockSize;\n\n\t\t/*\n\t\t**\tProbably dont need this anymore as LZO decompresses into a staging buffer.\n\t\t*/\n\t\tint SafetyMargin;\n\n\t\t/*\n\t\t**\tEach block has a header of this format.\n\t\t*/\n\t\tstruct {\n\t\t\tunsigned short CompCount;\t\t// Size of data block (compressed).\n\t\t\tunsigned short UncompCount;\t// Bytes of uncompressed data it represents.\n\t\t} BlockHeader;\n\n\t\tLZOStraw(LZOStraw & rvalue);\n\t\tLZOStraw & operator = (LZOStraw const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/LZO_CONF.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* lzo_conf.h -- main internal configuration file for the the LZO library\n\n   This file is part of the LZO real-time data compression library.\n\n   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer\n\n   The LZO library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Library General Public\n   License as published by the Free Software Foundation; either\n   version 2 of the License, or (at your option) any later version.\n\n   The LZO library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n   Library General Public License for more details.\n\n   You should have received a copy of the GNU Library General Public\n   License along with the LZO library; see the file COPYING.LIB.\n   If not, write to the Free Software Foundation, Inc.,\n   675 Mass Ave, Cambridge, MA 02139, USA.\n\n   Markus F.X.J. Oberhumer\n   markus.oberhumer@jk.uni-linz.ac.at\n */\n\n\n/* WARNING: this file should *not* be used by applications. It is\n   part of the implementation of the library and is subject\n   to change.\n */\n\n\n#ifndef __LZO_CONF_H\n#define __LZO_CONF_H\n\n#ifndef __LZOCONF_H\n#  include <lzoconf.h>\n#endif\n\n\n/***********************************************************************\n// compiler specific defines\n************************************************************************/\n\n/* need Borland C 4.0 or above because of huge-pointer bugs */\n#if defined(__LZO_MSDOS16) && defined(__TURBOC__)\n#  if (__TURBOC__ < 0x452)\n#    error You need a newer compiler version\n#  endif\n#endif\n\n#if defined(__LZO_MSDOS) || defined(__i386__) || defined(__386__)\n#  if !defined(__LZO_i386)\n#    define __LZO_i386\n#  endif\n#endif\n\n\n/***********************************************************************\n//\n************************************************************************/\n\n#include <stddef.h>\t\t\t/* ptrdiff_t, size_t */\n#include <string.h>\t\t\t/* memcpy, memmove, memcmp, memset */\n\n#if 0 && !defined(assert)\n#  error <assert.h> not included\n#endif\n\n#if defined(__BOUNDS_CHECKING_ON)\n#  include <unchecked.h>\n#else\n#  define BOUNDS_CHECKING_OFF_DURING(stmt)\t\tstmt\n#  define BOUNDS_CHECKING_OFF_IN_EXPR(expr)\t\t(expr)\n#endif\n\n/* ptrdiff_t */\n#if (UINT_MAX >= 0xffffffffL)\n   typedef ptrdiff_t        lzo_ptrdiff_t;\n#else\n   typedef long             lzo_ptrdiff_t;\n#endif\n\n\n#ifdef __cplusplus\n#  define LZO_UNUSED(parm)\n#else\n#  define LZO_UNUSED(parm)\tparm\n#endif\n\n\n#if !defined(__inline__) && !defined(__GNUC__)\n#  if defined(__cplusplus)\n#    define __inline__\t\tinline\n#  else\n#    define __inline__\t\t/* nothing */\n#  endif\n#endif\n\n\n/***********************************************************************\n// compiler and architecture specific stuff\n************************************************************************/\n\n/* Some defines that indicate if memory can be accessed at unaligned\n * addresses. You should also test that this is actually faster if\n * it is allowed by your system.\n */\n\n#if 1 && defined(__LZO_i386)\n#  if !defined(LZO_UNALIGNED_OK_2)\n#    define LZO_UNALIGNED_OK_2\n#  endif\n#  if !defined(LZO_UNALIGNED_OK_4)\n#    define LZO_UNALIGNED_OK_4\n#  endif\n#endif\n\n\n#if defined(LZO_UNALIGNED_OK_2) || defined(LZO_UNALIGNED_OK_4)\n#  if !defined(LZO_UNALIGNED_OK)\n#    define LZO_UNALIGNED_OK\n#  endif\n#endif\n\n\n/* Definitions for byte order, according to significance of bytes, from low\n * addresses to high addresses. The value is what you get by putting '4'\n * in the most significant byte, '3' in the second most significant byte,\n * '2' in the second least significant byte, and '1' in the least\n * significant byte.\n */\n\n#define\tLZO_LITTLE_ENDIAN\t\t1234\n#define\tLZO_BIG_ENDIAN\t\t\t4321\n#define\tLZO_PDP_ENDIAN\t\t\t3412\n\n/* The byte order is only needed if we use LZO_UNALIGNED_OK */\n#if !defined(LZO_BYTE_ORDER)\n#  if defined(__LZO_i386)\n#    define LZO_BYTE_ORDER\t\tLZO_LITTLE_ENDIAN\n#  elif defined(__mc68000__)\n#    define LZO_BYTE_ORDER\t\tLZO_BIG_ENDIAN\n#  elif defined(__BYTE_ORDER)\n#    define LZO_BYTE_ORDER\t\t__BYTE_ORDER\n#  endif\n#endif\n\n#if defined(LZO_UNALIGNED_OK)\n#  if !defined(LZO_BYTE_ORDER)\n#    error LZO_BYTE_ORDER is not defined\n#  elif (LZO_BYTE_ORDER != LZO_LITTLE_ENDIAN) && \\\n        (LZO_BYTE_ORDER != LZO_BIG_ENDIAN)\n#    error invalid LZO_BYTE_ORDER\n#  endif\n#endif\n\n\n/***********************************************************************\n// optimization\n************************************************************************/\n\n/* gcc 2.6.3 and gcc 2.7.2 have a bug */\n#define LZO_OPTIMIZE_GNUC_i386_IS_BUGGY\n\n/* Help the optimizer with register allocation.\n * Don't activate this macro for a fair comparision with other algorithms.\n */\n#if 1 && defined(NDEBUG) && !defined(__BOUNDS_CHECKING_ON)\n#  if defined(__GNUC__) && defined(__i386__)\n#    if !defined(LZO_OPTIMIZE_GNUC_i386_IS_BUGGY)\n#      define LZO_OPTIMIZE_GNUC_i386\n#    endif\n#  endif\n#endif\n\n\n/***********************************************************************\n//\n************************************************************************/\n\n#define LZO_BYTE(x)\t\t\t((unsigned char) (x))\n\n#define LZO_MAX(a,b)\t\t((a) >= (b) ? (a) : (b))\n#define LZO_MIN(a,b)\t\t((a) <= (b) ? (a) : (b))\n\n#define lzo_sizeof(x)\t\t((lzo_uint) (sizeof(x)))\n\n#define LZO_HIGH(x)\t\t\t((lzo_uint) (sizeof(x)/sizeof(*(x))))\n\n/* this always fits into 16 bits */\n#define LZO_SIZE(bits)\t\t(1u << (bits))\n#define LZO_MASK(bits)\t\t(LZO_SIZE(bits) - 1)\n\n#define LZO_LSIZE(bits)\t\t(1ul << (bits))\n#define LZO_LMASK(bits)\t\t(LZO_LSIZE(bits) - 1)\n\n#define LZO_USIZE(bits)\t\t((lzo_uint) 1 << (bits))\n#define LZO_UMASK(bits)\t\t(LZO_USIZE(bits) - 1)\n\n\n/***********************************************************************\n// ANSI C preprocessor macros\n************************************************************************/\n\n#define _LZO_STRINGIZE(x)\t\t\t#x\n#define _LZO_MEXPAND(x)\t\t\t\t_LZO_STRINGIZE(x)\n\n/* concatenate */\n#define _LZO_CONCAT2(a,b)\t\t\ta ## b\n#define _LZO_CONCAT3(a,b,c)\t\t\ta ## b ## c\n#define _LZO_CONCAT4(a,b,c,d)\t\ta ## b ## c ## d\n#define _LZO_CONCAT5(a,b,c,d,e)\t\ta ## b ## c ## d ## e\n\n/* expand and concatenate (by using one level of indirection) */\n#define _LZO_ECONCAT2(a,b)\t\t\t_LZO_CONCAT2(a,b)\n#define _LZO_ECONCAT3(a,b,c)\t\t_LZO_CONCAT3(a,b,c)\n#define _LZO_ECONCAT4(a,b,c,d)\t\t_LZO_CONCAT4(a,b,c,d)\n#define _LZO_ECONCAT5(a,b,c,d,e)\t_LZO_CONCAT5(a,b,c,d,e)\n\n\n/***********************************************************************\n//\n************************************************************************/\n\n/* Generate compressed data in a deterministic way.\n * This is fully portable, and compression can be faster as well.\n * A reason NOT to be deterministic is when the block size is\n * very small (e.g. 8kB) or the dictionary is big, because\n * then the initialization of the dictionary becomes a relevant \n * magnitude for compression speed.\n */\n#define LZO_DETERMINISTIC\n\n\n/***********************************************************************\n//\n************************************************************************/\n\n#if 0 \n/* This line causes problems on some architectures */\n#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \\\n\t(BOUNDS_CHECKING_OFF_IN_EXPR( \\\n\t\t(m_off = ip - m_pos) > max_offset ))\n\n#else\n/* This is the safe (but slower) version */\n#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \\\n\t\t(m_pos == NULL || (m_off = ip - m_pos) > max_offset)\n#endif\n\n\n/* m_pos may point anywhere...\n * This marco is probably a good candidate for architecture specific problems.\n * Try casting the pointers to lzo_ptr_t before comparing them.\n */\n#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \\\n\t(BOUNDS_CHECKING_OFF_IN_EXPR( \\\n\t\t(m_pos < in || (m_off = ip - m_pos) <= 0 || m_off > max_offset) ))\n\n\n\n#endif /* already included */\n\n/*\nvi:ts=4\n*/\n\n"
  },
  {
    "path": "CODE/LZW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LZW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZW.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 08/28/96                                                     *\n *                                                                                             *\n *                  Last Update : August 28, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Find_Child_Node -- Find a matching dictionary entry.                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include\t\"xstraw.h\"\n#include\t\"xpipe.h\"\n#include\t\"buff.h\"\n#include\t\"lzw.h\"\n\n\nLZWEngine::LZWEngine(void)\n{\n\tReset();\n}\n\n\nvoid LZWEngine::Reset(void)\n{\n\tfor (int i = 0; i < TABLE_SIZE; i++) {\n\t\tdict[i].Make_Unused();\n\t}\n}\n\nint LZWEngine::Compress(Buffer const & input, Buffer const & output)\n{\n\tBufferStraw instraw(input);\n\tBufferPipe outpipe(output);\n\n\tint outcount = 0;\n\tCodeType string_code = END_OF_STREAM;\n\tCodeType next_code = FIRST_CODE;\n\n\tstring_code = 0;\n\tif (instraw.Get(&string_code, sizeof(char)) == 0) {\n\t\tstring_code = END_OF_STREAM;\n\t}\n\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tFetch a character from the source data stream. If exhausted,\n\t\t**\tthen break out of the process loop so that the final code\n\t\t**\tcan be written out.\n\t\t*/\n\t\tunsigned char character;\n\t\tif (instraw.Get(&character, sizeof(character)) == 0) break;\n\n\t\t/*\n\t\t**\tSee if there is a match for the current code and current\n\t\t**\tcharacter. A match indicates that there is already a\n\t\t**\tdictionary entry that fully represents the character\n\t\t**\tsequence.\n\t\t*/\n\t\tint index = Find_Child_Node(string_code, character);\n\n\t\t/*\n\t\t**\tIf a code match was found, then set the current code\n\t\t**\tvalue to this code value that represents the concatenation\n\t\t**\tof the previous code value and the current character.\n\t\t*/\n\t\tif (index != -1 && dict[index].CodeValue != -1) {\n\t\t\tstring_code = dict[index].CodeValue;\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tSince no exact match was found, then create a new code\n\t\t\t**\tentry that represents the current code and character\n\t\t\t**\tvalue concatenated. This presumes there is room in the\n\t\t\t**\tcode table.\n\t\t\t*/\n\t\t\tif (index != -1 && next_code <= MAX_CODE) {\n\t\t\t\tdict[index] = CodeClass(next_code, string_code, character);\n\t\t\t\tnext_code++;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tOutput the code to the compression stream and reset the\n\t\t\t**\tcurrent code value to match the current character. This\n\t\t\t**\thas the effect of clearing out the current character\n\t\t\t**\tsequence scan in preparation for building a new one. It\n\t\t\t**\talso ensures that the character will be written out.\n\t\t\t*/\n\t\t\toutcount += outpipe.Put(&string_code, sizeof(string_code));\n\t\t\tstring_code = character;\n\t\t}\n\t}\n\n\toutcount += outpipe.Put(&string_code, sizeof(string_code));\n\tif (string_code != END_OF_STREAM) {\n\t\tstring_code = END_OF_STREAM;\n\t\toutcount += outpipe.Put(&string_code, sizeof(string_code));\n\t}\n\n\treturn(outcount);\n}\n\n\nint LZWEngine::Uncompress(Buffer const & input, Buffer const & output)\n{\n\tint outcount = 0;\n\tBufferStraw instraw(input);\n\tBufferPipe outpipe(output);\n\n\tCodeType old_code;\n\tif (instraw.Get(&old_code, sizeof(old_code)) == 0) {\n\t\treturn(outcount);\n\t}\n\n\tunsigned char character = (unsigned char)old_code;\n\toutcount += outpipe.Put(&character, sizeof(character));\n\n\tunsigned int count;\n\tCodeType new_code;\n\tCodeType next_code = FIRST_CODE;\n\tfor (;;) {\n\t\tif (instraw.Get(&new_code, sizeof(new_code)) == 0) break;\n\n\t\tif (new_code == END_OF_STREAM) break;\n\n\t\t/*\n\t\t** This code checks for the CHARACTER+STRING+CHARACTER+STRING+CHARACTER\n\t\t** case which generates an undefined code.  It handles it by decoding\n\t\t** the last code, and adding a single character to the end of the decode string.\n\t\t*/\n\t\tif (new_code >= next_code) {\n\t\t\tdecode_stack[0] = character;\n\t\t\tcount = 1;\n\t\t\tcount += Decode_String(&decode_stack[1], old_code);\n\t\t} else {\n\t\t\tcount = Decode_String(decode_stack, new_code);\n\t\t}\n\n\t\tcharacter = decode_stack[count-1];\n\t\twhile (count > 0) {\n\t\t\t--count;\n\t\t\toutcount += outpipe.Put(&decode_stack[count], sizeof(decode_stack[0]));\n\t\t}\n\n\t\t/*\n\t\t**\tAdd the new code sequence to the dictionary (presuming there is still\n\t\t**\troom).\n\t\t*/\n\t\tif (next_code <= MAX_CODE) {\n\t\t\tdict[next_code] = CodeClass(next_code, old_code, character);\n\t\t\tnext_code++;\n\t\t}\n\t\told_code = new_code;\n\t}\n\n\treturn(outcount);\n}\n\n\nint LZWEngine::Make_LZW_Hash(CodeType code, char character)\n{\n\treturn((((int)(unsigned char)character) << ( BITS - 8 ) ) ^ (int)code);\n}\n\n\nint LZWEngine::Find_Child_Node(CodeType parent_code, char child_character)\n{\n\t/*\n\t**\tFetch the first try index for the code and character.\n\t*/\n\tint hash_index = Make_LZW_Hash(parent_code, child_character);\n\n\t/*\n\t**\tBase the hash-miss-try-again-displacement value on the current\n\t**\tindex. [Shouldn't the value be some large prime number???].\n\t*/\n\tint offset = 1;\n\tif (hash_index != 0) {\n\t\toffset = TABLE_SIZE - hash_index;\n\t}\n\n\t/*\n\t**\tKeep offsetting through the dictionary until an exact match is\n\t**\tfound for the code and character specified.\n\t*/\n\tint initial = hash_index;\n\twhile (!dict[hash_index].Is_Matching(parent_code, child_character)) {\n\n\t\t/*\n\t\t**\tStop searching if an unused index is found since this means that\n\t\t**\ta match doesn't exist in the table at all.\n\t\t*/\n\t\tif (dict[hash_index].Is_Unused()) break;\n\n\t\t/*\n\t\t**\tBump the hash index to another value such that sequential bumps\n\t\t**\twill not result in the same index value until all of the table\n\t\t**\thas been scanned.\n\t\t*/\n\t\thash_index -= offset;\n\t\tif (hash_index < 0) {\n\t\t\thash_index += TABLE_SIZE;\n\t\t}\n\n\t\t/*\n\t\t**\tIf the entire table has been scanned and no match or unused\n\t\t**\tentry was found, then return a special value indicating this\n\t\t**\tcondition.\n\t\t*/\n\t\tif (initial == hash_index) {\n\t\t\thash_index = -1;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn(hash_index);\n}\n\n\nint LZWEngine::Decode_String(char * ptr, CodeType code)\n{\n\tint count = 0;\n\twhile (code > 255) {\n\t\t*ptr++ = dict[code].CharValue;\n\t\tcount++;\n\t\tcode = dict[code].ParentCode;\n\t}\n\t*ptr = (char)code;\n\tcount++;\n\treturn(count);\n}\n\n\nint LZW_Uncompress(Buffer const & inbuff, Buffer const & outbuff)\n{\n\tLZWEngine lzw;\n\treturn(lzw.Uncompress(inbuff, outbuff));\n}\n\n\nint LZW_Compress(Buffer const & inbuff, Buffer const & outbuff)\n{\n\tLZWEngine lzw;\n\treturn(lzw.Compress(inbuff, outbuff));\n}\n\n\n\n\n\n#ifdef NEVER\n\n\n/*\n * Constants used throughout the program.  BITS defines how many bits\n * will be in a code.  TABLE_SIZE defines the size of the dictionary\n * table.\n */\n#define BITS                       12\n#define MAX_CODE                   ( ( 1 << BITS ) - 1 )\n#define TABLE_SIZE                 5021\n#define END_OF_STREAM              256\n#define FIRST_CODE                 257\n#define UNUSED                     -1\n\ntypedef unsigned short CodeType;\n\n/*\n * This data structure defines the dictionary.  Each entry in the dictionary\n * has a code value.  This is the code emitted by the compressor.  Each\n * code is actually made up of two pieces:  a parent_code, and a\n * character.  Code values of less than 256 are actually plain\n * text codes.\n */\nstruct CodeClass\n{\n\tCodeType CodeValue;\n\tCodeType ParentCode;\n\tchar CharValue;\n\n\tCodeClass(void) {}\n\tCodeClass(CodeType code, CodeType parent, char c) : CodeValue(code), ParentCode(parent), CharValue(c) {}\n\n\tvoid Make_Unused(void) {CodeValue = UNUSED;}\n\tbool Is_Unused(void) const {return(CodeValue == UNUSED);}\n\tbool Is_Matching(CodeType code, char c) const {return(ParentCode == code && CharValue == c);}\n};\nCodeClass dict[TABLE_SIZE];\n\nchar decode_stack[TABLE_SIZE];\n\ninline int Make_LZW_Hash(CodeType code, char character)\n{\n\treturn((((int)(unsigned char)character) << ( BITS - 8 ) ) ^ (int)code);\n}\n\n\n/***********************************************************************************************\n * Find_Child_Node -- Find a matching dictionary entry.                                        *\n *                                                                                             *\n *    This hashing routine is responsible for finding the table location                       *\n *    for a string/character combination.  The table index is created                          *\n *    by using an exclusive OR combination of the prefix and character.                        *\n *    This code also has to check for collisions, and handles them by                          *\n *    jumping around in the table.                                                             *\n *                                                                                             *\n * INPUT:   parent_code -- The code of the parent string sequence.                             *\n *                                                                                             *\n *          character   -- The current character.                                              *\n *                                                                                             *\n * OUTPUT:  Returns with the index for the matching dictionary entry. If no matching index     *\n *          could be found, then it returns with the index to an unused dictionary entry. If   *\n *          there are also no unused entries in the dictionary, then -1 is returned.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/28/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic int Find_Child_Node(CodeType parent_code, char child_character)\n{\n\t/*\n\t**\tFetch the first try index for the code and character.\n\t*/\n\tint hash_index = Make_LZW_Hash(parent_code, child_character);\n\n\t/*\n\t**\tBase the hash-miss-try-again-displacement value on the current\n\t**\tindex. [Shouldn't the value be some large prime number???].\n\t*/\n\tint offset = 1;\n\tif (hash_index != 0) {\n\t\toffset = TABLE_SIZE - hash_index;\n\t}\n\n\t/*\n\t**\tKeep offsetting through the dictionary until an exact match is\n\t**\tfound for the code and character specified.\n\t*/\n\tint initial = hash_index;\n\twhile (!dict[hash_index].Is_Matching(parent_code, child_character)) {\n\n\t\t/*\n\t\t**\tStop searching if an unused index is found since this means that\n\t\t**\ta match doesn't exist in the table at all.\n\t\t*/\n\t\tif (dict[hash_index].Is_Unused()) break;\n\n\t\t/*\n\t\t**\tBump the hash index to another value such that sequential bumps\n\t\t**\twill not result in the same index value until all of the table\n\t\t**\thas been scanned.\n\t\t*/\n\t\thash_index -= offset;\n\t\tif (hash_index < 0) {\n\t\t\thash_index += TABLE_SIZE;\n\t\t}\n\n\t\t/*\n\t\t**\tIf the entire table has been scanned and no match or unused\n\t\t**\tentry was found, then return a special value indicating this\n\t\t**\tcondition.\n\t\t*/\n\t\tif (initial == hash_index) {\n\t\t\thash_index = -1;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn(hash_index);\n}\n\n\n/*\n * This routine decodes a string from the dictionary, and stores it\n * in the decode_stack data structure.  It returns a count to the\n * calling program of how many characters were placed in the stack.\n */\nstatic int Decode_String(char * ptr, CodeType code)\n{\n\tint count = 0;\n\twhile (code > 255) {\n\t\t*ptr++ = dict[code].CharValue;\n\t\tcount++;\n\t\tcode = dict[code].ParentCode;\n\t}\n\t*ptr = (char)code;\n\tcount++;\n\treturn(count);\n}\n\n\n/*\n * The compressor is short and simple.  It reads in new symbols one\n * at a time from the input file.  It then  checks to see if the\n * combination of the current symbol and the current code are already\n * defined in the dictionary.  If they are not, they are added to the\n * dictionary, and we start over with a new one symbol code.  If they\n * are, the code for the combination of the code and character becomes\n * our new code.\n */\n\nint LZW_Compress(Buffer & inbuff, Buffer & outbuff)\n{\n\tBufferStraw input(inbuff);\n\tBufferPipe output(outbuff);\n\n\tfor (int i = 0; i < TABLE_SIZE; i++) {\n\t\tdict[i].Make_Unused();\n//\t\tdict[i].code_value = UNUSED;\n\t}\n\n\tint outcount = 0;\n\tCodeType string_code = END_OF_STREAM;\n\tCodeType next_code = FIRST_CODE;\n\tfor (;;) {\n\t\tchar character;\n\n\t\tif (input.Get(&character, sizeof(character)) == 0) break;\n\n\t\tint index = Find_Child_Node(string_code, character);\n\n\t\tif (index == -1) {\n\t\t\tstring_code = character;\n\t\t\toutcount += output.Put(&string_code, sizeof(string_code));\n\t\t} else {\n\n\t\t\tif (dict[index].CodeValue != -1) {\n\t\t\t\tstring_code = dict[ index ].CodeValue;\n\t\t\t} else {\n\t\t\t\tif (next_code <= MAX_CODE) {\n\t\t\t\t\tdict[index] = CodeClass(next_code++, string_code, character);\n\t\t\t\t}\n\t\t\t\toutcount += output.Put(&string_code, sizeof(string_code));\n\t\t\t\tstring_code = character;\n\t\t\t}\n\t\t}\n\t}\n\n\toutcount += output.Put(&string_code, sizeof(string_code));\n\tstring_code = END_OF_STREAM;\n\toutcount += output.Put(&string_code, sizeof(string_code));\n\n\treturn(outcount);\n}\n\n\n/*\n * The file expander operates much like the encoder.  It has to\n * read in codes, the convert the codes to a string of characters.\n * The only catch in the whole operation occurs when the encoder\n * encounters a CHAR+STRING+CHAR+STRING+CHAR sequence.  When this\n * occurs, the encoder outputs a code that is not presently defined\n * in the table.  This is handled as an exception.\n */\nint LZW_Uncompress(Buffer & inbuff, Buffer & outbuff)\n{\n\tint outcount = 0;\n\tBufferStraw input(inbuff);\n\tBufferPipe output(outbuff);\n\n\tCodeType old_code;\n\tif (input.Get(&old_code, sizeof(old_code)) == 0) {\n\t\treturn(outcount);\n\t}\n\n\tchar character = (char)old_code;\n\toutcount += output.Put(&character, sizeof(character));\n\n\tunsigned int count;\n\tCodeType new_code;\n\tCodeType next_code = FIRST_CODE;\n\tfor (;;) {\n\t\tif (input.Get(&new_code, sizeof(new_code)) == 0) break;\n\n\t\t/*\n\t\t** This code checks for the CHARACTER+STRING+CHARACTER+STRING+CHARACTER\n\t\t** case which generates an undefined code.  It handles it by decoding\n\t\t** the last code, and adding a single character to the end of the decode string.\n\t\t*/\n\t\tif (new_code >= next_code) {\n\t\t\tdecode_stack[0] = character;\n\t\t\tcount = 1;\n\t\t\tcount += Decode_String(&decode_stack[1], old_code);\n\t\t} else {\n\t\t\tcount = Decode_String(decode_stack, new_code);\n\t\t}\n\n\t\tcharacter = decode_stack[count-1];\n\t\twhile (count > 0) {\n\t\t\t--count;\n\t\t\toutcount += output.Put(&decode_stack[count], sizeof(decode_stack[0]));\n\t\t}\n\n\t\t/*\n\t\t**\tAdd the new code sequence to the dictionary (presuming there is still\n\t\t**\troom).\n\t\t*/\n\t\tif (next_code <= MAX_CODE) {\n\t\t\tdict[next_code] = CodeClass(next_code, old_code, character);\n\t\t\tnext_code++;\n\t\t}\n\t\told_code = new_code;\n\t}\n\n\treturn(outcount);\n}\n\n#endif\n"
  },
  {
    "path": "CODE/LZW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LZW.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZW.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 08/28/96                                                     *\n *                                                                                             *\n *                  Last Update : August 28, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef _LZW_H\n#define _LZW_H\n\n#include\t\"buff.h\"\n\nclass LZWEngine\n{\n\tpublic:\n\t\tLZWEngine(void);\n\n\t\tint Compress(Buffer const & input, Buffer const & output);\n\t\tint Uncompress(Buffer const & input, Buffer const & output);\n\n\t\tvoid Reset(void);\n\n\tprivate:\n\t\ttypedef short CodeType;\n\t\tstruct CodeClass {\n\t\t\tCodeType CodeValue;\n\t\t\tCodeType ParentCode;\n\t\t\tchar CharValue;\n\n\t\t\tCodeClass(void) {}\n\t\t\tCodeClass(CodeType code, CodeType parent, char c) : CodeValue(code), ParentCode(parent), CharValue(c) {}\n\n\t\t\tenum {UNUSED=-1};\n\t\t\tvoid Make_Unused(void) {CodeValue = UNUSED;}\n\t\t\tbool Is_Unused(void) const {return(CodeValue == UNUSED);}\n\t\t\tbool Is_Matching(CodeType code, char c) const {return(ParentCode == code && CharValue == c);}\n\t\t};\n\n\t\tenum {\n\t\t\tBITS=12,\n\t\t\tMAX_CODE=((1 << BITS ) - 1),\n\t\t\tFIRST_CODE=257,\n\t\t\tEND_OF_STREAM=256,\n\t\t\tTABLE_SIZE=5021\n\t\t};\n\t\tCodeClass dict[TABLE_SIZE];\n\n\t\tchar decode_stack[TABLE_SIZE];\n\n\t\tint Find_Child_Node(CodeType parent_code, char child_character);\n\t\tint Decode_String(char * ptr, CodeType code);\n\t\tstatic int Make_LZW_Hash(CodeType code, char character);\n};\n\n\nint LZW_Compress(Buffer const & inbuff, Buffer const & outbuff);\nint LZW_Uncompress(Buffer const & inbuff, Buffer const & outbuff);\n\n#endif\n"
  },
  {
    "path": "CODE/LZWOTRAW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LZWOTRAW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZWSTRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LZWStraw::Get -- Fetch data through the LZW processor.                                    *\n *   LZWStraw::LZWStraw -- Constructor for LZW straw object.                                   *\n *   LZWStraw::~LZWStraw -- Destructor for the LZW straw.                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"lzostraw.h\"\n#include\t\"lzo.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * LZWStraw::LZWStraw -- Constructor for LZW straw object.                                     *\n *                                                                                             *\n *    This will initialize the LZW straw object. Whether the object is to compress or          *\n *    decompress and the block size to use is specified. The data is compressed in blocks      *\n *    that are sized to be quick to compress and yet still yield good compression ratios.      *\n *                                                                                             *\n * INPUT:   decrypt  -- Should the data be decompressed?                                       *\n *                                                                                             *\n *          blocksize-- The size of the blocks to process.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   It takes two buffers of the blocksize specified if compression is to be         *\n *             performed.                                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZWStraw::LZWStraw(CompControl control, int blocksize) :\n\t\tControl(control),\n\t\tCounter(0),\n\t\tBuffer(NULL),\n\t\tBuffer2(NULL),\n\t\tBlockSize(blocksize)\n{\n\tSafetyMargin = BlockSize;\n//\tSafetyMargin = BlockSize/128+1;\n\tBuffer = new char[BlockSize+SafetyMargin];\n\tif (control == COMPRESS) {\n\t\tBuffer2 = new char[BlockSize+SafetyMargin];\n\t}\n}\n\n\n/***********************************************************************************************\n * LZWStraw::~LZWStraw -- Destructor for the LZW straw.                                        *\n *                                                                                             *\n *    The destructor will free up the allocated buffers that it allocated in the constructor.  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZWStraw::~LZWStraw(void)\n{\n\tdelete [] Buffer;\n\tBuffer = NULL;\n\n\tdelete [] Buffer2;\n\tBuffer2 = NULL;\n}\n\n\n/***********************************************************************************************\n * LZWStraw::Get -- Fetch data through the LZW processor.                                      *\n *                                                                                             *\n *    This routine will fetch the data bytes specified. It does this by first accumulating     *\n *    a full block of data and then compressing or decompressing it as indicated. Subsequent   *\n *    requests for data will draw from this buffer of processed data until it is exhausted     *\n *    and another block must be fetched.                                                       *\n *                                                                                             *\n * INPUT:   destbuf  -- Pointer to the buffer to hold the data requested.                      *\n *                                                                                             *\n *          length   -- The number of data bytes requested.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes stored into the buffer. If this number     *\n *          is less than that requested, then this indicates that the data source has been     *\n *          exhausted.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LZWStraw::Get(void * destbuf, int slen)\n{\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tVerify parameters for legality.\n\t*/\n\tif (destbuf == NULL || slen < 1) {\n\t\treturn(0);\n\t}\n\n\twhile (slen > 0) {\n\n\t\t/*\n\t\t**\tCopy as much data is requested and available into the desired\n\t\t**\tdestination buffer.\n\t\t*/\n\t\tif (Counter) {\n\t\t\tint len = (slen < Counter) ? slen : Counter;\n\t\t\tif (Control == DECOMPRESS) {\n\t\t\t\tmemmove(destbuf, &Buffer[BlockHeader.UncompCount-Counter], len);\n\t\t\t} else {\n\t\t\t\tmemmove(destbuf, &Buffer2[(BlockHeader.CompCount+sizeof(BlockHeader))-Counter], len);\n\t\t\t}\n\t\t\tdestbuf = ((char *)destbuf) + len;\n\t\t\tslen -= len;\n\t\t\tCounter -= len;\n\t\t\ttotal += len;\n\t\t}\n\t\tif (slen == 0) break;\n\n\t\tif (Control == DECOMPRESS) {\n\t\t\tint incount = Straw::Get(&BlockHeader, sizeof(BlockHeader));\n\t\t\tif (incount != sizeof(BlockHeader)) break;\n\n\t\t\tchar *stageing_buffer = new char [BlockHeader.CompCount];\n\t\t\tincount = Straw::Get(staging_buffer, BlockHeader.CompCount);\n\t\t\tif (incount != BlockHeader.CompCount) break;\n\n\t\t\tlz01x_decompress (ptr, BlockHeader.CompCount, Buffer, sizeof(Buffer), NULL);\n\t\t\tCounter = BlockHeader.UncompCount;\n\t\t} else {\n\t\t\tBlockHeader.UncompCount = (unsigned short)Straw::Get(Buffer, BlockSize);\n\t\t\tif (BlockHeader.UncompCount == 0) break;\n\t\t\tint len = sizeof (Buffer2) - sizeof (BlockHeader);\n\t\t\tchar *dictionary = new char [64*1024];\n\t\t\tlzo1x_1_compress (Buffer, BlockHeader.UncompCount, &Buffer2[sizeof(BlockHeader)], &BlockHeader.CompCount, dictionary);\n\t\t\tdelete [] dictionary;\n\t\t\tmemmove(Buffer2, &BlockHeader, sizeof(BlockHeader));\n\t\t\tCounter = BlockHeader.CompCount+sizeof(BlockHeader);\n\t\t}\n\t}\n\n\treturn(total);\n}\n"
  },
  {
    "path": "CODE/LZWPIPE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LZWPIPE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZWPIPE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LZWPipe::Flush -- Flushes any partially accumulated block.                                *\n *   LZWPipe::LZWPipe -- Constructor for the LZW processor pipe.                               *\n *   LZWPipe::Put -- Send some data through the LZW processor pipe.                            *\n *   LZWPipe::~LZWPipe -- Deconstructor for the LZW pipe object.                               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"lzwpipe.h\"\n#include\t\"lzw.h\"\n#include\t\"buff.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * LZWPipe::LZWPipe -- Constructor for the LZW processor pipe.                                 *\n *                                                                                             *\n *    This will initialize the LZWPipe object so that it is prepared for compression or        *\n *    decompression as indicated.                                                              *\n *                                                                                             *\n * INPUT:   decrypt  -- Should decompression be performed?                                     *\n *                                                                                             *\n *          blocksize-- The size of the data blocks to process.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZWPipe::LZWPipe(CompControl control, int blocksize) :\n\t\tControl(control),\n\t\tCounter(0),\n\t\tBuffer(NULL),\n\t\tBuffer2(NULL),\n\t\tBlockSize(blocksize)\n{\n\tSafetyMargin = BlockSize;\n//\tSafetyMargin = BlockSize/128+1;\n\tBuffer = new char[BlockSize+SafetyMargin];\n\tBuffer2 = new char[BlockSize+SafetyMargin];\n\tBlockHeader.CompCount = 0xFFFF;\n}\n\n\n/***********************************************************************************************\n * LZWPipe::~LZWPipe -- Deconstructor for the LZW pipe object.                                 *\n *                                                                                             *\n *    This will free any buffers it may have allocated.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZWPipe::~LZWPipe(void)\n{\n\tdelete [] Buffer;\n\tBuffer = NULL;\n\n\tdelete [] Buffer2;\n\tBuffer2 = NULL;\n}\n\n\n/***********************************************************************************************\n * LZWPipe::Put -- Send some data through the LZW processor pipe.                              *\n *                                                                                             *\n *    This routine will take the data requested and process it (decompression or compression). *\n *    It does this by accumulating the necessary bytes to make a whole block. Then the block   *\n *    is processed and the entire contents are flushed to the next pipe segment in the chain.  *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the data to be fed to this LZW processor.                   *\n *                                                                                             *\n *          length   -- The number of bytes received.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes output at the far distant final link in    *\n *          the pipe chain.                                                                    *\n *                                                                                             *\n * WARNINGS:   The compression process may be slow as well as consuming two buffers.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LZWPipe::Put(void const * source, int slen)\n{\n\tif (source == NULL || slen < 1) {\n\t\treturn(Pipe::Put(source, slen));\n\t}\n\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tCopy as much as can fit into the buffer from the source data supplied.\n\t*/\n\tif (Control ==  DECOMPRESS) {\n\n\t\twhile (slen > 0) {\n\n\t\t\t/*\n\t\t\t**\tFirst check to see if we are in the block header accumulation phase.\n\t\t\t**\tWhen a whole block header has been accumulated, only then will the regular\n\t\t\t**\tdata processing begin for the block.\n\t\t\t*/\n\t\t\tif (BlockHeader.CompCount == 0xFFFF) {\n\t\t\t\tint len = (slen < (sizeof(BlockHeader)-Counter)) ? slen : (sizeof(BlockHeader)-Counter);\n\t\t\t\tmemmove(&Buffer[Counter], source, len);\n\t\t\t\tsource = ((char *)source) + len;\n\t\t\t\tslen -= len;\n\t\t\t\tCounter += len;\n\n\t\t\t\t/*\n\t\t\t\t**\tA whole block header has been accumulated. Store it for safekeeping.\n\t\t\t\t*/\n\t\t\t\tif (Counter == sizeof(BlockHeader)) {\n\t\t\t\t\tmemmove(&BlockHeader, Buffer, sizeof(BlockHeader));\n\t\t\t\t\tCounter = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tFill the buffer with compressed data until there is enough to make a whole\n\t\t\t**\tdata block.\n\t\t\t*/\n\t\t\tif (slen > 0) {\n\t\t\t\tint len = (slen < (BlockHeader.CompCount-Counter)) ? slen : (BlockHeader.CompCount-Counter);\n\n\t\t\t\tmemmove(&Buffer[Counter], source, len);\n\t\t\t\tslen -= len;\n\t\t\t\tsource = ((char *)source) + len;\n\t\t\t\tCounter += len;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf an entire block has been accumulated, then uncompress it and feed it\n\t\t\t\t**\tthrough the pipe.\n\t\t\t\t*/\n\t\t\t\tif (Counter == BlockHeader.CompCount) {\n\t\t\t\t\tLZW_Uncompress(Buffer, Buffer2);\n\t\t\t\t\ttotal += Pipe::Put(Buffer2, BlockHeader.UncompCount);\n\t\t\t\t\tCounter = 0;\n\t\t\t\t\tBlockHeader.CompCount = 0xFFFF;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tIf the buffer already contains some data, then any new data must be stored\n\t\t**\tinto the staging buffer until a full set has been accumulated.\n\t\t*/\n\t\tif (Counter > 0) {\n\t\t\tint tocopy = (slen < (BlockSize-Counter)) ? slen : (BlockSize-Counter);\n\t\t\tmemmove(&Buffer[Counter], source, tocopy);\n\t\t\tsource = ((char *)source) + tocopy;\n\t\t\tslen -= tocopy;\n\t\t\tCounter += tocopy;\n\n\t\t\tif (Counter == BlockSize) {\n\t\t\t\tint len = LZW_Compress(::Buffer(Buffer, BlockSize), Buffer2);\n\n\t\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\t\tBlockHeader.UncompCount = (unsigned short)BlockSize;\n\t\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t\t\tCounter = 0;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tProcess the source data in whole block chunks until there is insufficient\n\t\t**\tsource data left for a whole data block.\n\t\t*/\n\t\twhile (slen >= BlockSize) {\n\t\t\tint len = LZW_Compress(::Buffer((void*)source, BlockSize), Buffer2);\n\n\t\t\tsource = ((char *)source) + BlockSize;\n\t\t\tslen -= BlockSize;\n\n\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\tBlockHeader.UncompCount = (unsigned short)BlockSize;\n\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is any remaining data, then it is stored into the buffer\n\t\t**\tuntil a full data block has been accumulated.\n\t\t*/\n\t\tif (slen > 0) {\n\t\t\tmemmove(Buffer, source, slen);\n\t\t\tCounter = slen;\n\t\t}\n\t}\n\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * LZWPipe::Flush -- Flushes any partially accumulated block.                                  *\n *                                                                                             *\n *    This routine is called when any buffered data must be flushed out the pipe. For the      *\n *    compression process, this will generate the sub-sized compressed block. For              *\n *    decompression, this routine should not have any data in the buffer. In such a case, it   *\n *    means that the data source was prematurely truncated. In such a case, just dump the      *\n *    accumulated data through the pipe.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of data bytes output to the distant final link in   *\n *          the pipe chain.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LZWPipe::Flush(void)\n{\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tIf there is accumulated data, then it must processed.\n\t*/\n\tif (Counter > 0) {\n\t\tif (Control == DECOMPRESS) {\n\n\t\t\t/*\n\t\t\t**\tIf the accumulated data is insufficient to make a block header, then\n\t\t\t**\tthis means the data has been truncated. Just dump the data through\n\t\t\t**\tas if were already decompressed.\n\t\t\t*/\n\t\t\tif (BlockHeader.CompCount == 0xFFFF) {\n\t\t\t\ttotal += Pipe::Put(Buffer, Counter);\n\t\t\t\tCounter = 0;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tThere appears to be a partial block accumulated in the buffer. It would\n\t\t\t**\tbe disastrous to try to decompress the data since there wouldn't be\n\t\t\t**\tthe special end of data code that LZW decompression needs. In this\n\t\t\t**\tcase, dump the data out as if it were already decompressed.\n\t\t\t*/\n\t\t\tif (Counter > 0) {\n\t\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\t\ttotal += Pipe::Put(Buffer, Counter);\n\t\t\t\tCounter = 0;\n\t\t\t\tBlockHeader.CompCount = 0xFFFF;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tA partial block in the compression process is a normal occurrence. Just\n\t\t\t**\tcompress the partial block and output normally.\n\t\t\t*/\n\t\t\tint len = LZW_Compress(::Buffer(Buffer, Counter), Buffer2);\n\n\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\tBlockHeader.UncompCount = (unsigned short)Counter;\n\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t\tCounter = 0;\n\t\t}\n\t}\n\n\ttotal += Pipe::Flush();\n\treturn(total);\n}\n\n"
  },
  {
    "path": "CODE/LZWPIPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LZWPIPE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZWPIPE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef LZWPIPE_H\n#define LZWPIPE_H\n\n#include\t\"pipe.h\"\n\n\n/*\n**\tPerforms LZW compression/decompression on the data stream that is piped through this\n**\tclass. The data is compressed in blocks so of small enough size to be compressed\n**\tquickly and large enough size to get decent compression rates.\n*/\nclass LZWPipe : public Pipe\n{\n\tpublic:\n\t\ttypedef enum CompControl {\n\t\t\tCOMPRESS,\n\t\t\tDECOMPRESS\n\t\t} CompControl;\n\n\t\tLZWPipe(CompControl, int blocksize=1024*8);\n\t\tvirtual ~LZWPipe(void);\n\n\t\tvirtual int Flush(void);\n\t\tvirtual int Put(void const * source, int slen);\n\n\tprivate:\n\t\t/*\n\t\t**\tThis tells the pipe if it should be decompressing or compressing the data stream.\n\t\t*/\n\t\tCompControl Control;\n\n\t\t/*\n\t\t**\tThe number of bytes accumulated into the staging buffer.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tPointer to the working buffer that compression/decompression will use.\n\t\t*/\n\t\tchar * Buffer;\n\t\tchar * Buffer2;\n\n\t\t/*\n\t\t**\tThe working block size. Data will be compressed in chunks of this size.\n\t\t*/\n\t\tint BlockSize;\n\n\t\t/*\n\t\t**\tLZW compression requires a safety margin when decompressing over itself. This\n\t\t**\tmargin is only for the worst case situation (very rare).\n\t\t*/\n\t\tint SafetyMargin;\n\n\t\t/*\n\t\t**\tEach block has a header of this format.\n\t\t*/\n\t\tstruct {\n\t\t\tunsigned short CompCount;\t\t// Size of data block (compressed).\n\t\t\tunsigned short UncompCount;\t// Bytes of uncompressed data it represents.\n\t\t} BlockHeader;\n\n\t\tLZWPipe(LZWPipe & rvalue);\n\t\tLZWPipe & operator = (LZWPipe const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/LZWSTRAW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LZWSTRAW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZWSTRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LZWStraw::Get -- Fetch data through the LZW processor.                                    *\n *   LZWStraw::LZWStraw -- Constructor for LZW straw object.                                   *\n *   LZWStraw::~LZWStraw -- Destructor for the LZW straw.                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"lzwstraw.h\"\n#include\t\"lzw.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * LZWStraw::LZWStraw -- Constructor for LZW straw object.                                     *\n *                                                                                             *\n *    This will initialize the LZW straw object. Whether the object is to compress or          *\n *    decompress and the block size to use is specified. The data is compressed in blocks      *\n *    that are sized to be quick to compress and yet still yield good compression ratios.      *\n *                                                                                             *\n * INPUT:   decrypt  -- Should the data be decompressed?                                       *\n *                                                                                             *\n *          blocksize-- The size of the blocks to process.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   It takes two buffers of the blocksize specified if compression is to be         *\n *             performed.                                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZWStraw::LZWStraw(CompControl control, int blocksize) :\n\t\tControl(control),\n\t\tCounter(0),\n\t\tBuffer(NULL),\n\t\tBuffer2(NULL),\n\t\tBlockSize(blocksize)\n{\n\tSafetyMargin = BlockSize;\n//\tSafetyMargin = BlockSize/128+1;\n\tBuffer = new char[BlockSize+SafetyMargin];\n\tif (control == COMPRESS) {\n\t\tBuffer2 = new char[BlockSize+SafetyMargin];\n\t}\n}\n\n\n/***********************************************************************************************\n * LZWStraw::~LZWStraw -- Destructor for the LZW straw.                                        *\n *                                                                                             *\n *    The destructor will free up the allocated buffers that it allocated in the constructor.  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZWStraw::~LZWStraw(void)\n{\n\tdelete [] Buffer;\n\tBuffer = NULL;\n\n\tdelete [] Buffer2;\n\tBuffer2 = NULL;\n}\n\n\n/***********************************************************************************************\n * LZWStraw::Get -- Fetch data through the LZW processor.                                      *\n *                                                                                             *\n *    This routine will fetch the data bytes specified. It does this by first accumulating     *\n *    a full block of data and then compressing or decompressing it as indicated. Subsequent   *\n *    requests for data will draw from this buffer of processed data until it is exhausted     *\n *    and another block must be fetched.                                                       *\n *                                                                                             *\n * INPUT:   destbuf  -- Pointer to the buffer to hold the data requested.                      *\n *                                                                                             *\n *          length   -- The number of data bytes requested.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes stored into the buffer. If this number     *\n *          is less than that requested, then this indicates that the data source has been     *\n *          exhausted.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LZWStraw::Get(void * destbuf, int slen)\n{\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tVerify parameters for legality.\n\t*/\n\tif (destbuf == NULL || slen < 1) {\n\t\treturn(0);\n\t}\n\n\twhile (slen > 0) {\n\n\t\t/*\n\t\t**\tCopy as much data is requested and available into the desired\n\t\t**\tdestination buffer.\n\t\t*/\n\t\tif (Counter) {\n\t\t\tint len = (slen < Counter) ? slen : Counter;\n\t\t\tif (Control == DECOMPRESS) {\n\t\t\t\tmemmove(destbuf, &Buffer[BlockHeader.UncompCount-Counter], len);\n\t\t\t} else {\n\t\t\t\tmemmove(destbuf, &Buffer2[(BlockHeader.CompCount+sizeof(BlockHeader))-Counter], len);\n\t\t\t}\n\t\t\tdestbuf = ((char *)destbuf) + len;\n\t\t\tslen -= len;\n\t\t\tCounter -= len;\n\t\t\ttotal += len;\n\t\t}\n\t\tif (slen == 0) break;\n\n\t\tif (Control == DECOMPRESS) {\n\t\t\tint incount = Straw::Get(&BlockHeader, sizeof(BlockHeader));\n\t\t\tif (incount != sizeof(BlockHeader)) break;\n\n\t\t\tvoid * ptr = &Buffer[(BlockSize+SafetyMargin) - BlockHeader.CompCount];\n\t\t\tincount = Straw::Get(ptr, BlockHeader.CompCount);\n\t\t\tif (incount != BlockHeader.CompCount) break;\n\n\t\t\tLZW_Uncompress(ptr, Buffer);\n\t\t\tCounter = BlockHeader.UncompCount;\n\t\t} else {\n\t\t\tBlockHeader.UncompCount = (unsigned short)Straw::Get(Buffer, BlockSize);\n\t\t\tif (BlockHeader.UncompCount == 0) break;\n\t\t\tBlockHeader.CompCount = (unsigned short)LZW_Compress(::Buffer(Buffer, BlockHeader.UncompCount), &Buffer2[sizeof(BlockHeader)]);\n\t\t\tmemmove(Buffer2, &BlockHeader, sizeof(BlockHeader));\n\t\t\tCounter = BlockHeader.CompCount+sizeof(BlockHeader);\n\t\t}\n\t}\n\n\treturn(total);\n}\n"
  },
  {
    "path": "CODE/LZWSTRAW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/LZWSTRAW.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZWSTRAW.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef LZWSTRAW_H\n#define LZWSTRAW_H\n\n\n#include\t\"straw.h\"\n\n/*\n**\tThis class handles LZW compression/decompression to the data stream that is drawn through\n**\tthis class. Note that for compression, two internal buffers are required. For decompression\n**\tonly one buffer is required. This changes the memory footprint of this class depending on\n**\tthe process desired.\n*/\nclass LZWStraw : public Straw\n{\n\tpublic:\n\t\ttypedef enum CompControl {\n\t\t\tCOMPRESS,\n\t\t\tDECOMPRESS\n\t\t} CompControl;\n\n\t\tLZWStraw(CompControl control, int blocksize=1024*8);\n\t\tvirtual ~LZWStraw(void);\n\n\t\tvirtual int Get(void * source, int slen);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis tells the pipe if it should be decompressing or compressing the data stream.\n\t\t*/\n\t\tCompControl Control;\n\n\t\t/*\n\t\t**\tThe number of bytes accumulated into the staging buffer.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tPointer to the working buffer that compression/decompression will use.\n\t\t*/\n\t\tchar * Buffer;\n\t\tchar * Buffer2;\n\n\t\t/*\n\t\t**\tThe working block size. Data will be compressed in chunks of this size.\n\t\t*/\n\t\tint BlockSize;\n\n\t\t/*\n\t\t**\tLZW compression requires a safety margin when decompressing over itself. This\n\t\t**\tmargin is only for the worst case situation (very rare).\n\t\t*/\n\t\tint SafetyMargin;\n\n\t\t/*\n\t\t**\tEach block has a header of this format.\n\t\t*/\n\t\tstruct {\n\t\t\tunsigned short CompCount;\t\t// Size of data block (compressed).\n\t\t\tunsigned short UncompCount;\t// Bytes of uncompressed data it represents.\n\t\t} BlockHeader;\n\n\t\tLZWStraw(LZWStraw & rvalue);\n\t\tLZWStraw & operator = (LZWStraw const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#* $Header$\n#***********************************************************************************************\n#***              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               ***\n#***********************************************************************************************\n#*                                                                                             *\n#*                 Project Name : Command & Conquer                                            *\n#*                                                                                             *\n#*                    File Name : MAKEFILE                                                     *\n#*                                                                                             *\n#*                   Programmer : Joe L. Bostic                                                *\n#*                                                                                             *\n#*                   Start Date : 03/02/95                                                     *\n#*                                                                                             *\n#*                  Last Update : March 2, 1995 [JLB]                                          *\n#*                                                                                             *\n#*---------------------------------------------------------------------------------------------*\n#* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n.SILENT\n.OPTIMIZE\n.ERASE\n\n#---------------------------------------------------------------------------\n# Working values depending on what target executable will be created.\n#---------------------------------------------------------------------------\n\n!ifdef GERMAN\nLANGUAGE=GERMAN\n!else\n!ifdef FRENCH\nLANGUAGE=FRENCH\n!else\nLANGUAGE=ENGLISH\n!endif\n!endif\n\n!ifdef WIN32\nWWFLAT=..\\win32lib\nWWOBJ=obj\\win32\\$(LANGUAGE)\nLINKFILE=win95.lnk\nCC=..\\watcom\\binnt\\wpp386\nLIB=..\\watcom\\binnt\\wlib\n!else\nWWFLAT=..\\wwflat32\nWWOBJ=obj\\dos\nLINKFILE=conquer.lnk\nCC=..\\watcom\\binnt\\wpp386\nLIB=..\\watcom\\binnt\\wlib\n!endif\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#  These paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:  .\n.c:    .\n.cpp:  .\n.h:    .\n.obj:  $(WWOBJ)\n.lib:  $(WWFLAT)\\lib\n.exe:  ..\\run\n\n\n#===========================================================================\n# Compiler and assembler flags.\n#===========================================================================\n!ifdef WIN32\nCC_CFG = /d0                            # No debugging information\t( else use /d1 )\nCC_CFG += /DWIN32=1\nCC_CFG += /D_WIN32\nCC_CFG += /DWOLAPI_INTEGRATION\nCC_CFG += /DWINSOCK_IPX\nCC_CFG += /D$(LANGUAGE)=1\nCC_CFG += /i=..\\dxsdk\\inc\nCC_CFG += /i=..\\watcom\\h\\nt                # NT include directory.\nCC_CFG += /i=..\\watcom\\H                   # Normal Watcom include directory.\nCC_CFG += /i=$(WWFLAT)\\INCLUDE          # Normal library include directory.\nCC_CFG += /i=..\\winvq\\include           # Includes player (VQ) directory.\nCC_CFG += /bt=NT\nCC_CFG += /otxan\nCC_CFG += /5r                           # Pentium optimized register calling conventions.\n!else\nCC_CFG = /d1                            # Partial debug (line numbers only)\nCC_CFG += /i=..\\watcom\\H                   # Normal Watcom include directory.\nCC_CFG += /i=$(WWFLAT)\\INCLUDE          # Normal library include directory.\nCC_CFG += /i=..\\vq\\include              # Includes player (VQ) directory.\nCC_CFG += /DDOS4G                       # Must be defined for Greenleaf\nCC_CFG += /5s                           # Pentium optimized stack calling conventions.\nCC_CFG += /DGF_WATCOM_S                 # Must be defined for Greenleaf with /3s\nCC_CFG += /bt=DOS\n!endif\n\nCC_CFG += /i=..\\gcl510\\H                # Includes Greenleaf headers.\nCC_CFG += /of+                          # Generate traceable stack frames.\nCC_CFG += /zp1                          # Pack structures on byte boundary.\nCC_CFG += /s                            # Remove stack check calls.\nCC_CFG += /j                            # char is now signed.\nCC_CFG += /fh=$(WWOBJ)\\conquer.pch      # Use precompiled headers.\nCC_CFG += /fhq\nCC_CFG += /we                           # Treat all warnings as errors.\nCC_CFG += /w8                           # Most warnings enabled.\nCC_CFG += /ri                           # char and shorts are returned as int.\nCC_CFG += /zq                           # Operate quietly.\n\nASM_CFG = /i$(WWFLAT)\\INCLUDE           # Include directory.\nASM_CFG += /zd                          # Debugging information line numbers.\nASM_CFG += /t                           # Quiet operation.\nASM_CFG += /m                           # Allow multiple passes.\nASM_CFG += /w+                          # Enable maximum warnings.\nASM_CFG += /jJUMPS                      # Enable jump optimizations.\nASM_CFG += /ml                          # Case sensitivity on code.\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj: .AUTODEPEND\n\techo Compiling $<\n\t*$(CC) $(CC_CFG) -fo$(WWOBJ)\\$^. $<\n\n.cpp.obj: .AUTODEPEND\n\techo Compiling $<\n\t*$(CC) $(CC_CFG) -fo$(WWOBJ)\\$^. $<\n\n.asm.obj:\n\techo Assembling $<\n\tutils\\tasm $(ASM_CFG) $<, $(WWOBJ)\\$^.\n\n#---------------------------------------------------------------------------\n# Object modules.\n#---------------------------------------------------------------------------\nOBJECTS = &\n\tAADATA.OBJ &\n\tABSTRACT.OBJ &\n\tADATA.OBJ &\n\tAIRCRAFT.OBJ &\n\tANIM.OBJ &\n\tAUDIO.OBJ &\n\tBAR.OBJ &\n\tBASE.OBJ &\n\tBBDATA.OBJ &\n\tBDATA.OBJ &\n\tBUILDING.OBJ &\n\tBULLET.OBJ &\n\tCARGO.OBJ &\n\tCARRY.OBJ &\n\tCCFILE.OBJ &\n\tCCINI.OBJ &\n\tCCPTR.OBJ &\n\tCDATA.OBJ &\n\tCELL.OBJ &\n\tCHECKBOX.OBJ &\n\tCHEKLIST.OBJ &\n\tCOLRLIST.OBJ &\n\tCOMBAT.OBJ &\n\tCOMBUF.OBJ &\n\tCONNECT.OBJ &\n\tCONQUER.OBJ &\n\tCONST.OBJ &\n\tCONTROL.OBJ &\n\tCOORD.OBJ &\n\tCRATE.OBJ &\n\tCREDITS.OBJ &\n\tCREW.OBJ &\n\tDEBUG.OBJ &\n\tDIAL8.OBJ &\n\tDIALOG.OBJ &\n\tDISPLAY.OBJ &\n\tDOOR.OBJ &\n\tDRIVE.OBJ &\n\tDROP.OBJ &\n\tDYNAVEC.OBJ &\n\tEDIT.OBJ &\n\tEGOS.OBJ &\n\tENDING.OBJ &\n\tEVENT.OBJ &\n\tEXPAND.OBJ &\n\tFACE.OBJ &\n\tFACING.OBJ &\n\tFACTORY.OBJ &\n\tFINDPATH.OBJ &\n\tFLASHER.OBJ &\n\tFLY.OBJ &\n\tFOOT.OBJ &\n\tFUSE.OBJ &\n\tGADGET.OBJ &\n\tGAMEDLG.OBJ &\n\tGAUGE.OBJ &\n\tGLOBALS.OBJ &\n\tGOPTIONS.OBJ &\n\tGSCREEN.OBJ &\n\tHDATA.OBJ &\n\tHEAP.OBJ &\n\tHELP.OBJ &\n\tHOUSE.OBJ &\n\tIDATA.OBJ &\n\tINFANTRY.OBJ &\n\tINI.OBJ &\n\tINIT.OBJ &\n\tINTRO.OBJ &\n\tIOMAP.OBJ &\n\tIOOBJ.OBJ &\n\tIPX.OBJ &\n\tIPXADDR.OBJ &\n\tIPXCONN.OBJ &\n\tIPXGCONN.OBJ &\n\tIPXMGR.OBJ &\n\tIPXPROT.OBJ &\n\tJSHELL.OBJ &\n\tLAYER.OBJ &\n\tLINK.OBJ &\n\tLIST.OBJ &\n\tLOADDLG.OBJ &\n\tLOGIC.OBJ &\n\tMAP.OBJ &\n\tMAPEDDLG.OBJ &\n\tMAPEDIT.OBJ &\n\tMAPEDPLC.OBJ &\n\tMAPEDTM.OBJ &\n\tMAPSEL.OBJ &\n\tMENUS.OBJ &\n\tMISSION.OBJ &\n\tMOUSE.OBJ &\n\tMPLAYER.OBJ &\n\tMSGBOX.OBJ &\n\tMSGLIST.OBJ &\n\tNETDLG.OBJ &\n\tNULLCONN.OBJ &\n\tNULLDLG.OBJ &\n\tNULLMGR.OBJ &\n\tOBJECT.OBJ &\n\tODATA.OBJ &\n\tOPTIONS.OBJ &\n\tOVERLAY.OBJ &\n\tPOWER.OBJ &\n\tPROFILE.OBJ &\n\tQUEUE.OBJ &\n\tRADAR.OBJ &\n\tRADIO.OBJ &\n\tREINF.OBJ &\n\tRULES.OBJ &\n\tSAVELOAD.OBJ &\n\tSCENARIO.OBJ &\n\tSCORE.OBJ &\n\tSCROLL.OBJ &\n\tSDATA.OBJ &\n\tSESSION.OBJ &\n\tSHAPEBTN.OBJ &\n\tSIDEBAR.OBJ &\n\tSLIDER.OBJ &\n\tSMUDGE.OBJ &\n\tSOUNDDLG.OBJ &\n\tSPECIAL.OBJ &\n\tSTARTUP.OBJ &\n\tSTATBTN.OBJ &\n\tSUPER.OBJ &\n\tTAB.OBJ &\n\tTACTION.OBJ &\n\tTARGET.OBJ &\n\tTDATA.OBJ &\n\tTEAM.OBJ &\n\tTEAMTYPE.OBJ &\n\tTECHNO.OBJ &\n\tTEMPLATE.OBJ &\n\tTERRAIN.OBJ &\n\tTEVENT.OBJ &\n\tTEXTBTN.OBJ &\n\tTHEME.OBJ &\n\tTOGGLE.OBJ &\n\tTRACKER.OBJ &\n\tTRIGGER.OBJ &\n\tTRIGTYPE.OBJ &\n\tTXTLABEL.OBJ &\n\tUDATA.OBJ &\n\tUNIT.OBJ &\n\tUTRACKER.OBJ &\n\tVDATA.OBJ &\n\tVECTOR.OBJ &\n\tVERSION.OBJ &\n\tVESSEL.OBJ &\n\tVISUDLG.OBJ &\n\tVORTEX.OBJ &\n\tWARHEAD.OBJ &\n\tWEAPON.OBJ &\n\tMCIMOVIE.OBJ &\n\tMCI.OBJ &\n\tMPGSET.OBJ &\n\tICONLIST.OBJ &\n\tWOL_MAIN.OBJ &\n\tWOL_CHAT.OBJ &\n\tRAWOLAPI.OBJ &\n\tWOLAPIOB.OBJ &\n\tW95TRACE.OBJ &\n\tCOMINIT.OBJ &\n\tWOL_LOGN.OBJ &\n\tWOLEDIT.OBJ &\n\tPASSEDIT.OBJ &\n\tSEDITDLG.OBJ &\n\tDIBFILE.OBJ &\n\tDIBUTIL.OBJ &\n\tWOL_GSUP.OBJ &\n\tUDPADDR.OBJ &\n\tWSPROTO.OBJ &\n\tWSPUDP.OBJ &\n\tWSPIPX.OBJ &\n\t_WSPROTO.OBJ &\n\tTOOLTIP.OBJ &\n\tWOL_OPT.OBJ &\n\tWOL_CGAM.OBJ &\n\tBIGCHECK.OBJ &\n\tWOL_DNLD.OBJ &\n\tWOLSTRNG.OBJ\n\n\n# Files that are candidates for library submission,\n# since they depend on the westwood library to a great\n# degree\nLIBFILES = &\n\tROTBMP.OBJ &\n\tSPRITE.OBJ &\n\n# Self contained technology modules\nTECHFILES = &\n\tLZO1X_C.OBJ &\n\tLZO1X_D.OBJ &\n\tLZOPIPE.OBJ &\n\tLZOSTRAW.OBJ &\n\tLZW.OBJ &\n\tLZWPIPE.OBJ &\n\tLZWSTRAW.OBJ &\n\tBUFF.OBJ &\n\tBENCH.OBJ &\n\tRECT.OBJ &\n\tMPU.OBJ &\n\tREADLINE.OBJ &\n\tPKPIPE.OBJ &\n\tPKSTRAW.OBJ &\n\tXSTRAW.OBJ &\n\tXPIPE.OBJ &\n\tRNDSTRAW.OBJ &\n\tPK.OBJ &\n\tBLWSTRAW.OBJ &\n\tSTRAW.OBJ &\n\tB64STRAW.OBJ &\n\tLCWSTRAW.OBJ &\n\tCRCSTRAW.OBJ &\n\tSHASTRAW.OBJ &\n\tRAMFILE.OBJ &\n\tINI.OBJ &\n\tLCWPIPE.OBJ &\n\tLCWCOMP.OBJ &\n\tLCW.OBJ &\n\tCRCPIPE.OBJ &\n\tSHAPIPE.OBJ &\n\tPIPE.OBJ &\n\tBLOWPIPE.OBJ &\n\tB64PIPE.OBJ &\n\tBASE64.OBJ &\n\tFIXED.OBJ &\n\tMIXFILE.OBJ &\n\tCDFILE.OBJ &\n\tBFIOFILE.OBJ &\n\tRAWFILE.OBJ &\n\tMP.OBJ &\n\tINT.OBJ &\n\tMONOC.OBJ &\n\tRANDOM.OBJ &\n\tRGB.OBJ &\n\tHSV.OBJ &\n\tPALETTE.OBJ &\n\tBLOWFISH.OBJ &\n\tSHA.OBJ &\n\tCRC.OBJ &\n\tSENDFILE.OBJ\n\n!ifdef WIN32\nOBJECTS += 2KEYFBUF.OBJ &\n\tCPUID.OBJ &\n\tGETCPU.OBJ &\n\tINTERPAL.OBJ &\n\tWINASM.OBJ &\n\tWINSTUB.OBJ &\n\t2TXTPRNT.OBJ &\n\tWRITEPCX.OBJ &\n\tIPX95.OBJ &\n\t2KEYFRAM.OBJ &\n\tTCPIP.OBJ &\n\tINTERNET.OBJ &\n\tDDE.OBJ &\n\tCCDDE.OBJ &\n\tSTATS.OBJ &\n\tPACKET.OBJ &\n\tKEY.OBJ &\n\tFIELD.OBJ\n\n!else\nOBJECTS += KEYFBUFF.OBJ &\n\tTXTPRNT.OBJ &\n\tKEYFRAME.OBJ\n!endif\n\n!ifdef WIN32\nPROJ_LIBS = &\n\twin32lib.lib\n\n!else\nPROJ_LIBS = &\n\twwflat32.lib\n!endif\n\nVQ_LIBS = &\n\tvqa32wp.lib &\n\tvqm32wp.lib\n\nGCL_LIBS = &\n\tgclfr3s.lib\n\nMEMCHECK_LIBS = &\n\tMCA3S.LIB\n\n############################################################################\n# Pre-compilation process. Move old files to backup directory.\n.BEFORE\n\t-if exist *.bak move *.bak bak\n\t-if exist $(WWOBJ)\\*.pch del $(WWOBJ)\\*.pch\n\n# After make has completed.\n.AFTER\n\n# If there is an abnormal termination in make process (e.g., error in compile).\n.ERROR\n\n\n#############################################################################\n# Default target\n!ifdef WIN32\nall: ra95.exe\n!else\nall: game.dat\n!endif\n\n\n#############################################################################\n# Builds the JSHELL.LIB file.\n$(WWOBJ)\\jshell.lib: $(LIBFILES) $(WWOBJ)\\jshell.lnk\n\t$(LIB) -c $^@ @$(WWOBJ)\\jshell.lnk\n\n$(WWOBJ)\\jshell.lnk: makefile\n\t%create $^@\n\tfor %index in ($(LIBFILES))  do %append $^@ -+ $(WWOBJ)\\%index\n\n#############################################################################\n# Builds the TECH.LIB file.\n$(WWOBJ)\\tech.lib: $(TECHFILES) $(WWOBJ)\\tech.lnk\n\t$(LIB) -c $^@ @$(WWOBJ)\\tech.lnk\n\n$(WWOBJ)\\tech.lnk: makefile\n\t%create $^@\n\tfor %index in ($(TECHFILES))  do %append $^@ -+ $(WWOBJ)\\%index\n\n#############################################################################\n# Builds the stub replacement program.\nCWSTUB.OBJ: CWSTUB.C\n\t*wcc /i=..\\watcom\\h /dQUIET /dVMM /ms /zQ -fo$(WWOBJ)\\$^. $<\n\nCWSTUB.EXE: CWSTUB.OBJ\n\t*watcom\\binw\\wlink system dos file $(WWOBJ)\\cwstub.obj name cwstub.exe option quiet library \\wat\\lib386\\dos\\clibs.lib, \\wat\\lib386\\math87s.lib, \\wat\\lib386\\dos\\emu87.lib\n\n\n#############################################################################\n# Build the EXE\ngame.dat: $(WWOBJ)\\tech.lib $(WWOBJ)\\jshell.lib $(OBJECTS) $(LINKFILE) $(TECHFILE)\n\t-Echo \"dos.exe\" linking phase.\n        ..\\watcom\\binw\\wlink name ..\\run\\dos.exe @$(LINKFILE)\n\t-Echo Binding phase.\n        -..\\watcom\\binw\\wstrip -n -q ..\\run\\dos.exe ..\\run\\temp.tmp\n\t-..\\watcom\\4gwbind ..\\watcom\\4gwpro.exe ..\\run\\temp.tmp ..\\run\\game.dat -vmon\n# -copy ..\\run\\game.dat C:\\westwood\\redalert\n# -copy ..\\run\\game.dat C:\\westwood\\ra\n# -copy ..\\run\\dos.exe C:\\westwood\\redalert\n#\t-copy ..\\run\\game.dat ..\\cd\\install\n\t-Echo \"game.dat\" executable completed.\n\nra95.exe: $(WWOBJ)\\tech.lib $(WWOBJ)\\jshell.lib $(OBJECTS) $(LINKFILE) mpgdll.lib\n\tEcho \"ra95.exe\" linking phase. [$(LANGUAGE)]\n#         nwlink name ..\\run\\$@ @$(LINKFILE)\n# ajw - Steve Tall replaced wlink with nwlink. Watcom fix allows more debug symbols in exe, so allows debugging in WD.\n#        ..\\watcom\\binw\\wlink name ..\\run\\$@ @$(LINKFILE)\n        linker\\nwlink name ..\\run\\$@ @$(LINKFILE)\n#        ..\\watcom\\binnt\\WRC cc_icon ..\\run\\$@\n#        copy ..\\run\\ra95.exe C:\\westwood\\redalert\n#        copy ..\\run\\ra95.exe C:\\westwood\\ra\n\tEcho \"ra95.exe\" executable completed. [$(LANGUAGE)]\n\n\n#############################################################################\n# This creates the linker command file for the DOS version.\nconquer.lnk : makefile\n\t%create $^@\n\t%append $^@ system dos4g\n\t%append $^@ option stack=128k\n\t%append $^@ option redefsok\n\t%append $^@ option quiet\n\t%append $^@ option map\n\t%append $^@ option eliminate\n\t%append $^@ option caseexact\n\t%append $^@ debug all\n\t%append $^@ library $(WWOBJ)\\jshell.lib\n\t%append $^@ library $(WWOBJ)\\tech.lib\n\tfor %index in ($(OBJECTS))  do %append $^@ file $(WWOBJ)\\%index\n\tfor %index in ($(PROJ_LIBS)) do %append $^@ library $(WWFLAT)\\lib\\%index\n\tfor %index in ($(VQ_LIBS)) do %append $^@ library ..\\vq\\lib\\%index\n\tfor %index in ($(GCL_LIBS)) do %append $^@ library ..\\gcl510\\w10\\%index\n#\t%append $^@ debug watcom all\n\n\n#############################################################################\n# This creates the linker command file for the Windows 95 version.\nwin95.lnk : makefile\n\t%create $^@\n\t%append $^@ system win95\n\t%append $^@ option redefsok\n\t%append $^@ option quiet\n\t%append $^@ option map\n        %append $^@ option eliminate\n\t%append $^@ option caseexact\n\t%append $^@ option stack=128k\n#\t%append $^@ debug watcom all\n#\t%append $^@ debug all\n\tfor %index in ($(OBJECTS))  do %append $^@ file $(WWOBJ)\\%index\n\t%append $^@ library $(WWOBJ)\\jshell.lib\n\t%append $^@ library $(WWOBJ)\\tech.lib\n\t%append $^@ library $(WWFLAT)\\lib\\win32lib.lib\n\t%append $^@ library ..\\winvq\\lib\\vqa32wp.lib\n\t%append $^@ library ..\\winvq\\lib\\vqm32wp.lib\n     \t%append $^@ library ipx\\wwipx32.lib\n\t%append $^@ library ..\\dxsdk\\lib\\dxguid.lib\n\t%append $^@ library ..\\dxsdk\\lib\\ddraw.lib\n\t%append $^@ library ..\\dxsdk\\lib\\dsound.lib\n\t%append $^@ library $(WWFLAT)\\lib\\keyboard.lib\n\t%append $^@ library mpgdll.lib\n\t%append $^@ library ..\\dxmedia\\lib\\amstrmid.lib\n\t%append $^@ library ..\\dxmedia\\lib\\strmbasd.lib\n#\t%append $^@ library ..\\watcom\\lib386\\nt\\uuid.lib\n\t%append $^@ library uuid.lib\n\n#############################################################\n# Update source and art to network.\nupdate: pre .SYMBOLIC\n\t-copy i:\\cd1\\*.* f:\\projects\\c&c0\\cd\\win95\\cd1 /s /u\n\t-copy i:\\cd2\\*.* f:\\projects\\c&c0\\cd\\win95\\cd2 /s /u\n#\t-copy i:\\cd1\\*.* f:\\projects\\c&c0\\cd\\dos\\cd1 /s /u\n#\t-copy i:\\cd2\\*.* f:\\projects\\c&c0\\cd\\dos\\cd2 /s /u\n\t-copy ..\\art\\ingame\\*.* f:\\projects\\c&c0\\art\\ingame /u /v /s\n\t-copy ..\\audio\\sfx\\*.* f:\\projects\\c&c0\\audio\\ingame\\sfx /u /v /s\n\t-copy *.* f:\\projects\\c&c0\\code /v /s /u\n\t-copy ..\\wwflat32\\*.* f:\\projects\\c&c0\\wwflat32 /v /s /u\n\t-copy ..\\win32lib\\*.* f:\\projects\\c&c0\\win32lib /v /s /u\n\t-copy ..\\vq\\*.* f:\\projects\\c&c0\\vq /v /s /u\n\t-copy ..\\winvq\\*.* f:\\projects\\c&c0\\winvq /v /s /u\n\npre: .SYMBOLIC\n\t-copy f:\\projects\\c&c0\\editor\\english\\*.exe i:\\cd1\\install /u\n\t-copy f:\\projects\\c&c0\\editor\\english\\*.exe i:\\cd2\\install /u\n\t-copy f:\\projects\\c&c0\\editor\\english\\edit.dat i:\\cd1\\install /u\n\t-copy f:\\projects\\c&c0\\editor\\english\\edit.dat i:\\cd2\\install /u\n\t-copy ..\\run\\rules.ini ..\\maps /u\n\t-copy ..\\run\\rules.ini f:\\projects\\c&c0\\maps /u\n\t-watcom\\binw\\wstrip -n -q ..\\run\\ra95.exe ..\\run\\ra95.exe\n\t-copy ..\\run\\ra95.exe i:\\cd1\\install /u\n\t-copy ..\\run\\ra95.exe i:\\cd2\\install /u\n\t-copy ..\\run\\game.dat i:\\cd1\\install /u\n\t-copy ..\\run\\game.dat i:\\cd2\\install /u\n\tpacklist SETUP.LST\n\t-copy setup.pkg i:\\cd1\\setup95 /u\n \t-copy setup.pkg i:\\cd2\\setup95 /u\n\t-mkdir f:\\projects\\c&c0\\playtest\\%_DATE\n\t-copy ..\\run\\ra95.exe f:\\projects\\c&c0\\playtest\\%_DATE /u /v\n\t-copy ..\\run\\game.dat f:\\projects\\c&c0\\playtest\\%_DATE /u /v\n\t-copy *.map f:\\projects\\c&c0\\playtest\\%_DATE /u /v\n\t-copy *.cpp *.h f:\\projects\\c&c0\\playtest\\%_DATE /u /v\n\n\n#############################################################################\n# Explicit rules to build the master zip files (used by Codewrite merge).\nBILL_R.ZIP: pkzip.dat .SYMBOLIC\n\t-del f:\\projects\\c&c0\\bill_r.zip\n\t-pkzip -p -u -x@pkzip.dat f:\\projects\\c&c0\\bill_r.zip *.* eng\\conquer.txt\n\nMARIA_L.ZIP: pkzip.dat .SYMBOLIC\n\t-del f:\\projects\\c&c0\\maria_l.zip\n\t-pkzip -p -u -x@pkzip.dat f:\\projects\\c&c0\\maria_l.zip *.* eng\\conquer.txt\n\nBARRY_G.ZIP: pkzip.dat .SYMBOLIC\n\t-del f:\\projects\\c&c0\\barry_g.zip\n\t-pkzip -p -u -x@pkzip.dat f:\\projects\\c&c0\\barry_g.zip *.* eng\\conquer.txt\n\nPHIL_G.ZIP: pkzip.dat .SYMBOLIC\n\t-del f:\\projects\\c&c0\\phil_g.zip\n\t-pkzip -p -u -x@pkzip.dat f:\\projects\\c&c0\\phil_g.zip *.* eng\\conquer.txt\n\nDAVID_D.ZIP: pkzip.dat .SYMBOLIC\n\t-del f:\\projects\\c&c0\\david_d.zip\n\t-pkzip -p -u -x@pkzip.dat f:\\projects\\c&c0\\david_d.zip *.* eng\\conquer.txt\n\nBILL_P.ZIP: pkzip.dat .SYMBOLIC\n\t-del f:\\projects\\c&c0\\bill_p.zip\n\t-pkzip -p -u -x@pkzip.dat f:\\projects\\c&c0\\bill_p.zip *.* eng\\conquer.txt\n\nSTEVE_T.ZIP: pkzip.dat .SYMBOLIC\n\t-del f:\\projects\\c&c0\\steve_t.zip\n\t-pkzip -p -u -x@pkzip.dat f:\\projects\\c&c0\\steve_t.zip *.* eng\\conquer.txt\n\nVICTOR_G.ZIP: pkzip.dat .SYMBOLIC\n\t-del f:\\projects\\c&c0\\victor_g.zip\n\t-pkzip -p -u -x@pkzip.dat f:\\projects\\c&c0\\victor_g.zip *.* eng\\conquer.txt\n\n# Special \"mega-zip\" process.\nJOE_B.ZIP: pkzip.dat .SYMBOLIC\n\t-pkzip -rp -u -xcps\\*.* -x@pkzip.dat f:\\projects\\c&c0\\joe_b.zip\n\n\n#############################################################################\n# Rebuilds the master zip control file. This is used by the zip process.\nPKZIP.DAT: makefile .SYMBOLIC\n\t%create $^@\n\t%append $^@ *.000\n\t%append $^@ *.@@@\n\t%append $^@ *.bak\n\t%append $^@ *.bat\n\t%append $^@ *.cfg\n\t%append $^@ *.csm\n\t%append $^@ *.dat\n\t%append $^@ *.def\n\t%append $^@ *.doc\n\t%append $^@ *.dsw\n\t%append $^@ *.err\n\t%append $^@ *.ewp\n\t%append $^@ *.ext\n\t%append $^@ *.i\n\t%append $^@ *.ide\n\t%append $^@ *.lnk\n\t%append $^@ *.log\n\t%append $^@ *.lst\n\t%append $^@ *.mac\n\t%append $^@ *.map\n\t%append $^@ *.mbt\n\t%append $^@ *.mk\n\t%append $^@ *.mk1\n\t%append $^@ *.mrt\n\t%append $^@ *.obj\n\t%append $^@ *.obr\n\t%append $^@ *.out\n\t%append $^@ *.pch\n\t%append $^@ *.pfs\n\t%append $^@ *.pgp\n\t%append $^@ *.pif\n\t%append $^@ *.pjt\n\t%append $^@ *.prf\n\t%append $^@ *.pro\n\t%append $^@ *.ptg\n\t%append $^@ *.rc\n\t%append $^@ *.rep\n\t%append $^@ *.rpt\n\t%append $^@ *.rst\n\t%append $^@ *.sym\n\t%append $^@ *.tag\n\t%append $^@ *.td\n\t%append $^@ *.td\n\t%append $^@ *.tgt\n\t%append $^@ *.tmp\n\t%append $^@ *.tr\n\t%append $^@ *.tr\n\t%append $^@ *.txt\n\t%append $^@ *.vec\n\t%append $^@ *.wpj\n\t%append $^@ *.zip\n\t%append $^@ *.~*\n\t%append $^@ an_prefs\n\t%append $^@ state.rst\n\n\n#--------------------------------------------------------------------------\n# The IPX assembly object files are created in a special way:\n# IPXREAL is the real-mode code that gets stuffed into memory by protected-\n# mode code.  It's assembled, then converted into a big header file by\n# the 'EBN' utility.\n# IPXPROT is the protected-mode code that includes IPXREAL.IBN, and\n# provides routines to let C++ read the code's address & size.\n#--------------------------------------------------------------------------\n$(WWOBJ)\\ipxreal.ibn: $(WWOBJ)\\ipxreal.obj\n\t%create $^*.rsp\n\t%append $^*.rsp $(WWOBJ)\\$^&.obj\n\t%append $^*.rsp $(WWOBJ)\\$^&.exe\n\t%append $^*.rsp $(WWOBJ)\\$^&.map\n\tutils\\tlink @$^*.rsp\n\tutils\\tdstrip $(WWOBJ)\\ipxreal.exe\n\tutils\\ebn $(WWOBJ)\\ipxreal.exe\n\n$(WWOBJ)\\ipxreal.obj:\tipxreal.asm\n\tutils\\tasm /zn /la /ml /m2 ipxreal.asm, $(WWOBJ)\\ipxreal.obj\n\nipxprot.obj: $(WWOBJ)\\ipxreal.ibn ipxprot.asm\n\tutils\\tasm $(ASM_CFG) ipxprot.asm, $(WWOBJ)\\ipxprot.obj\n#\tcopy $(WWOBJ)\\ipxprot.obj d:obj /U\n\n\nipx.obj: ipx.cpp function.h\n\techo Compiling $[.\n\t*$(CC) $(CC_CFG) -zz -fo$(WWOBJ)\\$^. $[*.cpp\n\nipxmgr.obj: ipxmgr.cpp function.h\n\techo Compiling $[.\n\t*$(CC) $(CC_CFG) -zz -fo$(WWOBJ)\\$^. $[*.cpp\n\nipxconn.obj: ipxconn.cpp function.h\n\techo Compiling $[.\n\t*$(CC) $(CC_CFG) -zz -fo$(WWOBJ)\\$^. $[*.cpp\n\nipx95.obj: ipx95.cpp function.h\n\techo Compiling $[.\n\t*$(CC) $(CC_CFG) -zz -fo$(WWOBJ)\\$^. $[*.cpp\n\nwinstub.obj: winstub.cpp ipx95.h tcpip.h function.h\n\techo Compiling $[.\n\t*$(CC) $(CC_CFG) -zz -fo$(WWOBJ)\\$^. $[*.cpp\n\n\n\n#**************************** End of makefile ******************************\n"
  },
  {
    "path": "CODE/MAKE_ALL.BAT",
    "content": "SET WATCOM=C:\\rawolapi\\SOURCE\\WATCOM\nWMAKE WIN32=1 /a\nWMAKE WIN32=1 GERMAN=1 /a\nWMAKE WIN32=1 FRENCH=1 /a"
  },
  {
    "path": "CODE/MAP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MAP.CPP 3     3/14/97 5:15p Joe_b $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MAP.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : October 5, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   MapClass::Base_Region -- Finds the owner and base zone for specified cell.                *\n *   MapClass::Cell_Region -- Determines the region from a specified cell number.              *\n *   MapClass::Cell_Threat -- Gets a houses threat value for a cell                            *\n *   MapClass::Close_Object -- Finds a clickable close object to the specified coordinate.     *\n *   MapClass::Destroy_Bridge_At -- Destroyes the bridge at location specified.                *\n *   MapClass::Detach -- Remove specified object from map references.                          *\n *   MapClass::In_Radar -- Is specified cell in the radar map?                                 *\n *   MapClass::Init -- clears all cells                                                        *\n *   MapClass::Intact_Bridge_Count -- Determine the number of intact bridges.                  *\n *   MapClass::Logic -- Handles map related logic functions.                                   *\n *   MapClass::Nearby_Location -- Finds a generally clear location near a specified cell.      *\n *   MapClass::One_Time -- Performs special one time initializations for the map.              *\n *   MapClass::Overlap_Down -- computes & marks object's overlap cells                         *\n *   MapClass::Overlap_Up -- Computes & clears object's overlap cells                          *\n *   MapClass::Overpass -- Performs any final cleanup to a freshly constructed map.            *\n *   MapClass::Pick_Up -- Removes specified object from the map.                               *\n *   MapClass::Place_Down -- Places the specified object onto the map.                         *\n *   MapClass::Place_Random_Crate -- Places a crate at random location on map.                 *\n *   MapClass::Read_Binary -- Reads the binary data from the straw specified.                  *\n *   MapClass::Remove_Crate -- Remove a crate from the specified cell.                         *\n *   MapClass::Set_Map_Dimensions -- Initialize the map.                                       *\n *   MapClass::Sight_From -- Mark as visible the cells within a specified radius.              *\n *   MapClass::Validate -- validates every cell on the map                                     *\n *   MapClass::Write_Binary -- Pipes the map template data to the destination specified.       *\n *   MapClass::Zone_Reset -- Resets all zone numbers to match the map.                         *\n *   MapClass::Zone_Span -- Flood fills the specified zone from the cell origin.               *\n *   MapClass::Pick_Random_Location -- Picks a random location on the map.                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n#define\tMCW\tMAP_CELL_W\nint const MapClass::RadiusOffset[] = {\n\t/* 0  */\t0,\n\t/* 1  */\t(-MCW*1)-1,(-MCW*1)+0,(-MCW*1)+1,-1,1,(MCW*1)-1,(MCW*1)+0,(MCW*1)+1,\n\t/* 2  */\t(-MCW*2)-1,(-MCW*2)+0,(-MCW*2)+1,(-MCW*1)-2,(-MCW*1)+2,-2,2,(MCW*1)-2,(MCW*1)+2,(MCW*2)-1,(MCW*2)+0,(MCW*2)+1,\n\t/* 3  */\t(-MCW*3)-1,(-MCW*3)+0,(-MCW*3)+1,(-MCW*2)-2,(-MCW*2)+2,(-MCW*1)-3,(-MCW*1)+3,-3,3,(MCW*1)-3,(MCW*1)+3,(MCW*2)-2,(MCW*2)+2,(MCW*3)-1,(MCW*3)+0,(MCW*3)+1,\n\t/* 4  */\t(-MCW*4)-1,(-MCW*4)+0,(-MCW*4)+1,(-MCW*3)-3,(-MCW*3)-2,(-MCW*3)+2,(-MCW*3)+3,(-MCW*2)-3,(-MCW*2)+3,(-MCW*1)-4,(-MCW*1)+4,-4,4,(MCW*1)-4,(MCW*1)+4,(MCW*2)-3,(MCW*2)+3,(MCW*3)-3,(MCW*3)-2,(MCW*3)+2,(MCW*3)+3,(MCW*4)-1,(MCW*4)+0,(MCW*4)+1,\n\t/* 5  */\t(-MCW*5)-1,(-MCW*5)+0,(-MCW*5)+1,(-MCW*4)-3,(-MCW*4)-2,(-MCW*4)+2,(-MCW*4)+3,(-MCW*3)-4,(-MCW*3)+4,(-MCW*2)-4,(-MCW*2)+4,(-MCW*1)-5,(-MCW*1)+5,-5,5,(MCW*1)-5,(MCW*1)+5,(MCW*2)-4,(MCW*2)+4,(MCW*3)-4,(MCW*3)+4,(MCW*4)-3,(MCW*4)-2,(MCW*4)+2,(MCW*4)+3,(MCW*5)-1,(MCW*5)+0,(MCW*5)+1,\n\t/* 6  */\t(-MCW*6)-1,(-MCW*6)+0,(-MCW*6)+1,(-MCW*5)-3,(-MCW*5)-2,(-MCW*5)+2,(-MCW*5)+3,(-MCW*4)-4,(-MCW*4)+4,(-MCW*3)-5,(-MCW*3)+5,(-MCW*2)-5,(-MCW*2)+5,(-MCW*1)-6,(-MCW*1)+6,-6,6,(MCW*1)-6,(MCW*1)+6,(MCW*2)-5,(MCW*2)+5,(MCW*3)-5,(MCW*3)+5,(MCW*4)-4,(MCW*4)+4,(MCW*5)-3,(MCW*5)-2,(MCW*5)+2,(MCW*5)+3,(MCW*6)-1,(MCW*6)+0,(MCW*6)+1,\n\t/* 7  */\t(-MCW*7)-1,(-MCW*7)+0,(-MCW*7)+1,(-MCW*6)-3,(-MCW*6)-2,(-MCW*6)+2,(-MCW*6)+3,(-MCW*5)-5,(-MCW*5)-4,(-MCW*5)+4,(-MCW*5)+5,(-MCW*4)-5,(-MCW*4)+5,(-MCW*3)-6,(-MCW*3)+6,(-MCW*2)-6,(-MCW*2)+6,(-MCW*1)-7,(-MCW*1)+7,-7,7,(MCW*1)-7,(MCW*1)+7,(MCW*2)-6,(MCW*2)+6,(MCW*3)-6,(MCW*3)+6,(MCW*4)-5,(MCW*4)+5,(MCW*5)-5,(MCW*5)-4,(MCW*5)+4,(MCW*5)+5,(MCW*6)-3,(MCW*6)-2,(MCW*6)+2,(MCW*6)+3,(MCW*7)-1,(MCW*7)+0,(MCW*7)+1,\n\t/* 8  */\t(-MCW*8)-1,(-MCW*8)+0,(-MCW*8)+1,(-MCW*7)-3,(-MCW*7)-2,(-MCW*7)+2,(-MCW*7)+3,(-MCW*6)-5,(-MCW*6)-4,(-MCW*6)+4,(-MCW*6)+5,(-MCW*5)-6,(-MCW*5)+6,(-MCW*4)-6,(-MCW*4)+6,(-MCW*3)-7,(-MCW*3)+7,(-MCW*2)-7,(-MCW*2)+7,(-MCW*1)-8,(-MCW*1)+8,-8,8,(MCW*1)-8,(MCW*1)+8,(MCW*2)-7,(MCW*2)+7,(MCW*3)-7,(MCW*3)+7,(MCW*4)-6,(MCW*4)+6,(MCW*5)-6,(MCW*5)+6,(MCW*6)-5,(MCW*6)-4,(MCW*6)+4,(MCW*6)+5,(MCW*7)-3,(MCW*7)-2,(MCW*7)+2,(MCW*7)+3,(MCW*8)-1,(MCW*8)+0,(MCW*8)+1,\n\t/* 9  */\t(-MCW*9)-1,(-MCW*9)+0,(-MCW*9)+1,(-MCW*8)-3,(-MCW*8)-2,(-MCW*8)+2,(-MCW*8)+3,(-MCW*7)-5,(-MCW*7)-4,(-MCW*7)+4,(-MCW*7)+5,(-MCW*6)-6,(-MCW*6)+6,(-MCW*5)-7,(-MCW*5)+7,(-MCW*4)-7,(-MCW*4)+7,(-MCW*3)-8,(-MCW*3)+8,(-MCW*2)-8,(-MCW*2)+8,(-MCW*1)-9,(-MCW*1)+9,-9,9,(MCW*1)-9,(MCW*1)+9,(MCW*2)-8,(MCW*2)+8,(MCW*3)-8,(MCW*3)+8,(MCW*4)-7,(MCW*4)+7,(MCW*5)-7,(MCW*5)+7,(MCW*6)-6,(MCW*6)+6,(MCW*7)-5,(MCW*7)-4,(MCW*7)+4,(MCW*7)+5,(MCW*8)-3,(MCW*8)-2,(MCW*8)+2,(MCW*8)+3,(MCW*9)-1,(MCW*9)+0,(MCW*9)+1,\n\t/* 10 */\t(-MCW*10)-1,(-MCW*10)+0,(-MCW*10)+1,(-MCW*9)-3,(-MCW*9)-2,(-MCW*9)+2,(-MCW*9)+3,(-MCW*8)-5,(-MCW*8)-4,(-MCW*8)+4,(-MCW*8)+5,(-MCW*7)-7,(-MCW*7)-6,(-MCW*7)+6,(-MCW*7)+7,(-MCW*6)-7,(-MCW*6)+7,(-MCW*5)-8,(-MCW*5)+8,(-MCW*4)-8,(-MCW*4)+8,(-MCW*3)-9,(-MCW*3)+9,(-MCW*2)-9,(-MCW*2)+9,(-MCW*1)-10,(-MCW*1)+10,-10,10,(MCW*1)-10,(MCW*1)+10,(MCW*2)-9,(MCW*2)+9,(MCW*3)-9,(MCW*3)+9,(MCW*4)-8,(MCW*4)+8,(MCW*5)-8,(MCW*5)+8,(MCW*6)-7,(MCW*6)+7,(MCW*7)-7,(MCW*7)-6,(MCW*7)+6,(MCW*7)+7,(MCW*8)-5,(MCW*8)-4,\n\t\t\t(MCW*8)+4,(MCW*8)+5,(MCW*9)-3,(MCW*9)-2,(MCW*9)+2,(MCW*9)+3,(MCW*10)-1,(MCW*10)+0,(MCW*10)+1,\n};\n\nint const MapClass::RadiusCount[11] = {1,9,21,37,61,89,121,161,205,253,309};\n\n\nCellClass * BlubCell;\n\n/***********************************************************************************************\n * MapClass::One_Time -- Performs special one time initializations for the map.                *\n *                                                                                             *\n *    This routine is used by the game initialization function in order to perform any one     *\n *    time initializations required for the map. This includes allocation of the map and       *\n *    setting up its default dimensions.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine MUST be called once and only once.                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   12/01/1994 BR : Added CellTriggers initialization                                         *\n *=============================================================================================*/\nvoid MapClass::One_Time(void)\n{\n\tGScreenClass::One_Time();\n\n\tXSize = MAP_CELL_W;\n\tYSize = MAP_CELL_H;\n\tSize = XSize * YSize;\n\n\t/*\n\t**\tAllocate the cell array.\n\t*/\n\tAlloc_Cells();\n}\n\n\n/***********************************************************************************************\n * MapClass::Init_Clear -- clears the map & buffers to a known state                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Init_Clear(void)\n{\n\tGScreenClass::Init_Clear();\n\tInit_Cells();\n\tTiberiumScan = 0;\n\tTiberiumGrowthCount = 0;\n\tTiberiumGrowthExcess = 0;\n\tTiberiumSpreadCount = 0;\n\tTiberiumSpreadExcess = 0;\n\tfor (int index = 0; index < ARRAY_SIZE(Crates); index++) {\n\t\tCrates[index].Init();\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Alloc_Cells -- allocates the cell array                                           *\n *                                                                                             *\n * This routine should be called at One_Time, and after loading the Map object from a save     *\n * game, but prior to loading the cell objects.                                                *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Alloc_Cells(void)\n{\n\t/*\n\t**\tAssume that whatever the contents of the VectorClass are is garbage\n\t**\t(it may have been loaded from a save-game file), so zero it out first.\n\t*/\n\tnew (&Array) VectorClass<CellClass>;\n\tArray.Resize(Size);\n}\n\n\n/***********************************************************************************************\n * MapClass::Free_Cells -- frees the cell array                                                *\n *                                                                                             *\n * This routine is used by the Load_Game routine to free the map's cell array before loading   *\n * the map object from disk; the array is then re-allocated & cleared before the cell objects  *\n * are loaded.                                                                                 *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Free_Cells(void)\n{\n\tArray.Clear();\n}\n\n\n/***********************************************************************************************\n * MapClass::Init_Cells -- Initializes the cell array to a fresh state.                        *\n *                                                                                             *\n * This routine is used by Init_Clear to set the cells to a known state; it's also used by     *\n * the Load_Game routine to init all cells before loading a set of cells from disk, so it      *\n * needs to be called separately from the other Init_xxx() routines.                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Init_Cells(void)\n{\n\tTotalValue = 0;\n\tfor (int index = 0; index < MAP_CELL_TOTAL; index++) {\n\t\tnew (&Array[index]) CellClass;\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Set_Map_Dimensions -- Set map dimensions.                                         *\n *                                                                                             *\n *    This routine is used to set the legal limits and position of the                         *\n *    map as it relates to the overall map array. Typically, this is                           *\n *    called by the scenario loading code.                                                     *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y coordinate of the \"upper left\" corner                         *\n *                   of the map.                                                               *\n *                                                                                             *\n *          w,h   -- The width and height of the legal map.                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/14/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Set_Map_Dimensions(int x, int y, int w, int h)\n{\n\tMapCellX = x;\n\tMapCellY = y;\n\tMapCellWidth = w;\n\tMapCellHeight = h;\n}\n\n\n/***********************************************************************************************\n * MapClass::Sight_From -- Mark as visible the cells within a specified radius.                *\n *                                                                                             *\n *    This routine is used to reveal the cells around a specific location.                     *\n *    Typically, as a unit moves or is deployed, this routine will be                          *\n *    called. Since it deals with MANY cells, it needs to be extremely                         *\n *    fast.                                                                                    *\n *                                                                                             *\n * INPUT:   cell     -- The coordinate that the sighting originates from.                      *\n *                                                                                             *\n *          sightrange-- The distance in cells that sighting extends.                          *\n *                                                                                             *\n *          incremental-- Is this an incremental sighting. In other                            *\n *                      words, has this function been called before where                      *\n *                      the center coordinate is no more than one cell                         *\n *                      distant from the last time?                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/19/1992 JLB : Created.                                                                 *\n *   03/08/1994 JLB : Updated to use sight table and incremental flag.                         *\n *   05/18/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nvoid MapClass::Sight_From(CELL cell, int sightrange, HouseClass * house, bool incremental)\n{\n\tint xx;\t\t\t\t// Center cell X coordinate (bounds checking).\n\tint const * ptr;\t// Offset pointer.\n\tint count;\t\t\t// Counter for number of offsets to process.\n\n\t/*\n\t**\tUnits that are off-map cannot sight.\n\t*/\n\tif (!In_Radar(cell)) return;\n\tif (!sightrange || sightrange > 10) return;\n\n\t/*\n\t**\tDetermine logical cell coordinate for center scan point.\n\t*/\n\txx = Cell_X(cell);\n\n\t/*\n\t**\tIncremental scans only scan the outer rings. Full scans\n\t**\tscan all internal cells as well.\n\t*/\n\tcount = RadiusCount[sightrange];\n\tptr = &RadiusOffset[0];\n\tif (incremental) {\n\t\tif (sightrange > 2) {\n\t\t\tptr += RadiusCount[sightrange-3];\n\t\t\tcount -= RadiusCount[sightrange-3];\n\t\t}\n\t}\n\n\t/*\n\t**\tProcess all offsets required for the desired scan.\n\t*/\n\twhile (count--) {\n\t\tCELL\tnewcell;\t\t\t// New cell with offset.\n\t\tint\txdiff;\t\t\t// New cell's X coordinate distance from center.\n\n\t\tnewcell = cell + *ptr++;\n\n\t\t/*\n\t\t**\tDetermine if the map edge has been wrapped. If so,\n\t\t**\tthen don't process the cell.\n\t\t*/\n\t\tif ((unsigned)newcell >= MAP_CELL_TOTAL) continue;\n\t\txdiff = Cell_X(newcell) - xx;\n\t\txdiff = ABS(xdiff);\n\t\tif (xdiff > sightrange) continue;\n\t\tif (Distance(Cell_Coord(newcell), Cell_Coord(cell)) > (sightrange * CELL_LEPTON_W)) continue;\n\n\t\t/*\n\t\t**\tMap the cell. For incremental scans, then update\n\t\t**\tadjacent cells as well. For full scans, just update\n\t\t**\tthe cell itself.\n\t\t*/\n\t\tif (!(*this)[newcell].IsMapped) {\n\t\t\tMap.Map_Cell(newcell, house);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Shroud_From -- cloak a radius of cells\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *    This routine is used to shroud the cells around a specific location.                     *\n *    Typically, as a gap generator refreshes (when Encroach_Shadow() is called) this routine's*\n *    called. Since it deals with MANY cells, it needs to be extremely                         *\n *    fast.                                                                                    *\n *                                                                                             *\n * INPUT:   cell     -- The coordinate that the shrouding originates from.                     *\n *                                                                                             *\n *          sightrange-- The distance in cells that sighting extends.                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/10/1995 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Shroud_From(CELL cell, int sightrange)\n{\n\tint xx;\t\t\t\t// Center cell X coordinate (bounds checking).\n\tint const * ptr;\t// Offset pointer.\n\tint count;\t\t\t// Counter for number of offsets to process.\n\n\t/*\n\t**\tUnits that are off-map cannot sight.\n\t*/\n\tif (!In_Radar(cell)) return;\n\tif (!sightrange || sightrange > Rule.GapShroudRadius) return;\n\n\t/*\n\t**\tDetermine logical cell coordinate for center scan point.\n\t*/\n\txx = Cell_X(cell);\n\n\t/*\n\t**\tIncremental scans only scan the outer rings. Full scans\n\t**\tscan all internal cells as well.\n\t*/\n\tcount = RadiusCount[sightrange];\n\tptr = &RadiusOffset[0];\n\n\t/*\n\t**\tProcess all offsets required for the desired scan.\n\t*/\n\twhile (count--) {\n\t\tCELL\tnewcell;\t\t\t// New cell with offset.\n\t\tint\txdiff;\t\t\t// New cell's X coordinate distance from center.\n\n\t\tnewcell = cell + *ptr++;\n\n\t\t/*\n\t\t**\tDetermine if the map edge has been wrapped. If so,\n\t\t**\tthen don't process the cell.\n\t\t*/\n\t\tif ((unsigned)newcell >= MAP_CELL_TOTAL) continue;\n\t\txdiff = Cell_X(newcell) - xx;\n\t\txdiff = ABS(xdiff);\n\t\tif (xdiff > sightrange) continue;\n\t\tif (Distance(Cell_Coord(newcell), Cell_Coord(cell)) > (sightrange * CELL_LEPTON_W)) continue;\n\n\t\t/*\n\t\t**\tShroud the cell.\n\t\t*/\n\t\tMap.Shroud_Cell(newcell);\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Jam_From -- Mark as jammed the cells within a specified radius.                   *\n *                                                                                             *\n *    This routine is used to jam the cells around a specific location.                        *\n *    Typically, as a gap generator structure is created, this routine will be                 *\n *    called. Since it deals with MANY cells, it needs to be extremely                         *\n *    fast.                                                                                    *\n *                                                                                             *\n * INPUT:   cell     -- The coordinate that the jamming originates from.                       *\n *                                                                                             *\n *          jamrange -- The distance in cells that jamming extends.                            *\n *                                                                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/09/1995 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Jam_From(CELL cell, int jamrange, HouseClass * house)\n{\n\tint xx;\t\t\t\t// Center cell X coordinate (bounds checking).\n\tint const * ptr;\t// Offset pointer.\n\tint count;\t\t\t// Counter for number of offsets to process.\n\n\t/*\n\t**\tUnits that are off-map cannot jam.\n\t*/\n\tif (!jamrange || jamrange > Rule.GapShroudRadius) return;\n\n\t/*\n\t**\tDetermine logical cell coordinate for center scan point.\n\t*/\n\txx = Cell_X(cell);\n\n\t/*\n\t**\tIncremental scans only scan the outer rings. Full scans\n\t**\tscan all internal cells as well.\n\t*/\n\tcount = RadiusCount[jamrange];\n\tptr = &RadiusOffset[0];\n\n\t/*\n\t**\tProcess all offsets required for the desired scan.\n\t*/\n\twhile (count--) {\n\t\tCELL\tnewcell;\t\t\t// New cell with offset.\n\t\tint\txdiff;\t\t\t// New cell's X coordinate distance from center.\n\n\t\tnewcell = cell + *ptr++;\n\n\t\t/*\n\t\t**\tDetermine if the map edge has been wrapped. If so,\n\t\t**\tthen don't process the cell.\n\t\t*/\n\t\tif ((unsigned)newcell >= MAP_CELL_TOTAL) continue;\n\t\txdiff = Cell_X(newcell) - xx;\n\t\txdiff = ABS(xdiff);\n\t\tif (xdiff > jamrange) continue;\n\t\tif (Distance(Cell_Coord(newcell), Cell_Coord(cell)) > (jamrange * CELL_LEPTON_W)) continue;\n\n\t\t/*\n\t\t**\tJam the cell. For incremental scans, then update\n\t\t**\tadjacent cells as well. For full scans, just update\n\t\t**\tthe cell itself.\n\t\t*/\n\t\tMap.Jam_Cell(newcell, house/*KO, false*/);\n\t}\n\n//\tPlayerPtr->IsToLook = true;\n\tif (!house->IsPlayerControl) {\n\t\tMap.Constrained_Look(Cell_Coord(cell), Rule.GapShroudRadius * CELL_LEPTON_W);\n\t}\n\n#ifdef OBSOLETE\n\t/*\n\t**\tThe objects on the map need to perform a manual look operation if they happen\n\t**\tto have their sight range overlap the gap radius.\n\t*/\n\tif (!house->IsPlayerControl) {\n//\tif (house != PlayerPtr) {\n\n\t\tfor (int index = 0; index < Map.Layer[LAYER_GROUND].Count(); index++) {\n\t\t\tObjectClass * object = Map.Layer[LAYER_GROUND][index];\n\t\t\tif (object && object->Is_Techno()) {\n\t\t\t\tTechnoClass * tech = ((TechnoClass *)object);\n\n\t\t\t\tif (tech->IsDiscoveredByPlayer &&\n\t\t\t\t\t(tech->Distance(As_Target(cell)) / CELL_LEPTON_W) <= tech->Techno_Type_Class()->SightRange + Rule.GapShroudRadius &&\n\t\t\t\t\t(tech->House->IsPlayerControl ||\n\t\t\t\t\t(tech->What_Am_I() == RTTI_BUILDING && Rule.IsAllyReveal && tech->House->Is_Ally(PlayerPtr)))) {\n\n\t\t\t\t\tobject->Look();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n#ifdef OBSOLETE\n\t\t/*\n\t\t** Here all the player's vehicles will perform a look if they're within\n\t\t** the shadow.\n\t\t*/\n\t\tfor (int index = 0; index < Units.Count(); index++) {\n\t\t\tUnitClass * unit = Units.Ptr(index);\n\t\t\tif (unit && !unit->IsInLimbo && unit->House == PlayerPtr) {\n\t\t\t\tint dist = (unit->Distance(As_Target(cell))) / CELL_LEPTON_W;\n\t\t\t\tif (dist <= unit->Class->SightRange + Rule.GapShroudRadius /*gap generator sightrange*/) {\n\t\t\t\t\tunit->Look();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\tInfantryClass * unit = Infantry.Ptr(index);\n\t\t\tif (unit && !unit->IsInLimbo && unit->House == PlayerPtr) {\n\t\t\t\tint dist = (unit->Distance(As_Target(cell))) / CELL_LEPTON_W;\n\t\t\t\tif (dist <= unit->Class->SightRange + Rule.GapShroudRadius /*gap generator sightrange*/) {\n\t\t\t\t\tunit->Look();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass * unit = Vessels.Ptr(index);\n\t\t\tif (unit && !unit->IsInLimbo && unit->House == PlayerPtr) {\n\t\t\t\tint dist = (unit->Distance(As_Target(cell))) / CELL_LEPTON_W;\n\t\t\t\tif (dist <= unit->Class->SightRange + Rule.GapShroudRadius /*gap generator sightrange*/) {\n\t\t\t\t\tunit->Look();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n}\n\n\n/***********************************************************************************************\n * MapClass::UnJam_From -- Remove jamming on the cells within a specified radius.              *\n *                                                                                             *\n *    This routine is used to jam the cells around a specific location.                        *\n *    Typically, as a gap generator structure is created, this routine will be                 *\n *    called. Since it deals with MANY cells, it needs to be extremely                         *\n *    fast.                                                                                    *\n *                                                                                             *\n * INPUT:   cell     -- The coordinate that the jamming originates from.                       *\n *                                                                                             *\n *          jamrange -- The distance in cells that jamming extends.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/09/1995 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::UnJam_From(CELL cell, int jamrange, HouseClass * house)\n{\n\tint xx;\t\t\t\t// Center cell X coordinate (bounds checking).\n\tint const * ptr;\t// Offset pointer.\n\tint count;\t\t\t// Counter for number of offsets to process.\n\n\t/*\n\t**\tUnits that are off-map cannot jam.\n\t*/\n\tif (!jamrange || jamrange > Rule.GapShroudRadius) return;\n\n\t/*\n\t**\tDetermine logical cell coordinate for center scan point.\n\t*/\n\txx = Cell_X(cell);\n\n\t/*\n\t**\tIncremental scans only scan the outer rings. Full scans\n\t**\tscan all internal cells as well.\n\t*/\n\tcount = RadiusCount[jamrange];\n\tptr = &RadiusOffset[0];\n\n\t/*\n\t**\tProcess all offsets required for the desired scan.\n\t*/\n\twhile (count--) {\n\t\tCELL\tnewcell;\t\t\t// New cell with offset.\n\t\tint\txdiff;\t\t\t// New cell's X coordinate distance from center.\n\n\t\tnewcell = cell + *ptr++;\n\n\t\t/*\n\t\t**\tDetermine if the map edge has been wrapped. If so,\n\t\t**\tthen don't process the cell.\n\t\t*/\n\t\tif ((unsigned)newcell >= MAP_CELL_TOTAL) continue;\n\t\txdiff = Cell_X(newcell) - xx;\n\t\txdiff = ABS(xdiff);\n\t\tif (xdiff > jamrange) continue;\n\t\tif (Distance(Cell_Coord(newcell), Cell_Coord(cell)) > (jamrange * CELL_LEPTON_W)) continue;\n\n\t\t/*\n\t\t**\tJam the cell. For incremental scans, then update\n\t\t**\tadjacent cells as well. For full scans, just update\n\t\t**\tthe cell itself.\n\t\t*/\n\t\tMap.UnJam_Cell(newcell, house);\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::In_Radar -- Is specified cell in the radar map?                                   *\n *                                                                                             *\n *    This determines if the specified cell can be within the navigable                        *\n *    bounds of the map. Technically, this means, any cell that can be                         *\n *    scanned by radar. If a cell returns false from this function, then                       *\n *    the player could never move to or pass over this cell.                                   *\n *                                                                                             *\n * INPUT:   cell  -- The cell to examine.                                                      *\n *                                                                                             *\n * OUTPUT:  bool; Is this cell possible to be displayed on radar?                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *   04/30/1994 JLB : Converted to member function.                                            *\n *   05/01/1994 JLB : Speeded up.                                                              *\n *=============================================================================================*/\nbool MapClass::In_Radar(CELL cell) const\n{\n\t/*\n\t**\tIf the cell value is WAY out of range, then it obviously can't be part of the game\n\t**\tplayfield.\n\t*/\n\tif ((unsigned)cell > MAP_CELL_TOTAL) return(false);\n\n\t/*\n\t**\tIf the cell is off the left or right edge of the playfield, then return the \"not in\n\t**\tradar\" flag.\n\t*/\n\tif ((unsigned)(Cell_X(cell) - MapCellX) >= (unsigned)MapCellWidth) return(false);\n\n\t/*\n\t**\tIf the cell is off the top or bottom edge of the playfield, then return the \"not in\n\t**\tradar\" flag.\n\t*/\n\tif ((unsigned)(Cell_Y(cell) - MapCellY) >= (unsigned)MapCellHeight) return(false);\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * MapClass::Place_Down -- Places the specified object onto the map.                           *\n *                                                                                             *\n *    This routine is used to place an object onto the map. It updates the \"occupier\" of the   *\n *    cells that this object covers. The cells are determined from the Occupy_List function    *\n *    provided by the object. Only one cell can have an occupier and this routine is the only  *\n *    place that sets this condition.                                                          *\n *                                                                                             *\n * INPUT:   cell     -- The cell to base object occupation around.                             *\n *                                                                                             *\n *          object   -- The object to place onto the map.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Place_Down(CELL cell, ObjectClass * object)\n{\n\tif (!object) return;\n\n\tif (object->Class_Of().IsFootprint && object->In_Which_Layer() == LAYER_GROUND)  {\n\t\tshort xlist[32];\n\t\tList_Copy(object->Occupy_List(), ARRAY_SIZE(xlist), xlist);\n\t\tshort const * list = xlist;\n\t\twhile (*list != REFRESH_EOL) {\n\t\t\tCELL newcell = cell + *list++;\n\t\t\tif ((unsigned)newcell < MAP_CELL_TOTAL) {\n\t\t\t\t(*this)[newcell].Occupy_Down(object);\n\t\t\t\t(*this)[newcell].Recalc_Attributes();\n\t\t\t\t(*this)[newcell].Redraw_Objects();\n\t\t\t}\n\t\t}\n\n\t\tList_Copy(object->Overlap_List(), ARRAY_SIZE(xlist), xlist);\n\t\tlist = xlist;\n\t\twhile (*list != REFRESH_EOL) {\n\t\t\tCELL newcell = cell + *list++;\n\t\t\tif ((unsigned)newcell < MAP_CELL_TOTAL) {\n\t\t\t\t(*this)[newcell].Overlap_Down(object);\n\t\t\t\t(*this)[newcell].Redraw_Objects();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Pick_Up -- Removes specified object from the map.                                 *\n *                                                                                             *\n *    The object specified is removed from the map by this routine. This will remove the       *\n *    occupation flag for all the cells that the object covers. The cells that are covered     *\n *    are determined from the Occupy_List function.                                            *\n *                                                                                             *\n * INPUT:   cell     -- The cell that the object is centered about.                            *\n *                                                                                             *\n *          object   -- Pointer to the object that will be removed.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Pick_Up(CELL cell, ObjectClass * object)\n{\n\tif (!object) return;\n\n\tif (object->Class_Of().IsFootprint && object->In_Which_Layer() == LAYER_GROUND)  {\n\t\tshort xlist[32];\n\t\tList_Copy(object->Occupy_List(), ARRAY_SIZE(xlist), xlist);\n\t\tshort const * list = xlist;\n\t\twhile (*list != REFRESH_EOL) {\n\t\t\tCELL newcell = cell + *list++;\n\t\t\tif ((unsigned)newcell < MAP_CELL_TOTAL) {\n\t\t\t\t(*this)[newcell].Occupy_Up(object);\n\t\t\t\t(*this)[newcell].Recalc_Attributes();\n\t\t\t\t(*this)[newcell].Redraw_Objects();\n\t\t\t}\n\t\t}\n\n\t\tList_Copy(object->Overlap_List(), ARRAY_SIZE(xlist), xlist);\n\t\tlist = xlist;\n\t\twhile (*list != REFRESH_EOL) {\n\t\t\tCELL newcell = cell + *list++;\n\t\t\tif ((unsigned)newcell < MAP_CELL_TOTAL) {\n\t\t\t\t(*this)[newcell].Overlap_Up(object);\n\t\t\t\t(*this)[newcell].Redraw_Objects();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Overlap_Down -- computes & marks object's overlap cells                           *\n *                                                                                             *\n * This routine is just like Place_Down, but it doesn't mark the cell's Occupier.              *\n * This routine is used to implement MARK_OVERLAP_DOWN, which is useful for changing           *\n * an object's render size, but not its logical size (ie when it's selected or an              *\n * animation is attached to it).                                                               *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      cell -- The cell to base object overlap around.                                        *\n *    object   -- The object to place onto the map.                                            *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/12/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Overlap_Down(CELL cell, ObjectClass * object)\n{\n\tif (!object) return;\n\n\tif (object->Class_Of().IsFootprint && object->In_Which_Layer() == LAYER_GROUND)  {\n\t\tshort xlist[32];\n\t\tList_Copy(object->Overlap_List(), ARRAY_SIZE(xlist), xlist);\n\t\tshort const * list = xlist;\n\t\twhile (*list != REFRESH_EOL) {\n\t\t\tCELL newcell = cell + *list++;\n\t\t\tif ((unsigned)newcell < MAP_CELL_TOTAL) {\n\t\t\t\t(*this)[newcell].Overlap_Down(object);\n\t\t\t\t(*this)[newcell].Redraw_Objects();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Overlap_Up -- Computes & clears object's overlap cells                            *\n *                                                                                             *\n * This routine is just like Pick_Up, but it doesn't mark the cell's Occupier.                 *\n * This routine is used to implement MARK_OVERLAP_UP, which is useful for changing             *\n * an object's render size, but not its logical size (ie when it's selected or an              *\n * animation is attached to it).                                                               *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      cell -- The cell to base object overlap around.                                        *\n *    object   -- The object to place onto the map.                                            *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/12/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Overlap_Up(CELL cell, ObjectClass * object)\n{\n\tif (!object) return;\n\n\tif (object->Class_Of().IsFootprint && object->In_Which_Layer() == LAYER_GROUND)  {\n\t\tshort xlist[32];\n\t\tList_Copy(object->Overlap_List(), ARRAY_SIZE(xlist), xlist);\n\t\tshort const * list = xlist;\n\t\twhile (*list != REFRESH_EOL) {\n\t\t\tCELL newcell = cell + *list++;\n\t\t\tif ((unsigned)newcell < MAP_CELL_TOTAL) {\n\t\t\t\t(*this)[newcell].Overlap_Up(object);\n\t\t\t\t(*this)[newcell].Redraw_Objects();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Overpass -- Performs any final cleanup to a freshly constructed map.              *\n *                                                                                             *\n *    This routine will clean up anything necessary with the presumption that the map has      *\n *    been freshly created. Such things to clean up include various tiberium concentrations.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the total credit value of the tiberium on the map.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *   02/13/1995 JLB : Returns total tiberium worth.                                            *\n *   02/15/1995 JLB : Optimal scan.                                                            *\n *=============================================================================================*/\nlong MapClass::Overpass(void)\n{\n\tlong value = 0;\n\n\t/*\n\t**\tSmooth out Tiberium. Cells that are not surrounded by other tiberium\n\t**\twill be reduced in density.\n\t*/\n\tfor (int y = 0; y < MapCellHeight; y++) {\n\t\tfor (int x = 0; x < MapCellWidth; x++) {\n\t\t\tCELL cell = (MapCellY+y) * MAP_CELL_W + (MapCellX+x);\n\t\t\tvalue += (*this)[cell].Tiberium_Adjust(true);\n\t\t\t(*this)[cell].Recalc_Attributes();\n\t\t}\n\t}\n\treturn(value);\n}\n\n\n/***********************************************************************************************\n * MapClass::Write_Binary -- Pipes the map template data to the destination specified.         *\n *                                                                                             *\n *    This stores the template data from the map to the output pipe specified. The template    *\n *    data consists of the template type number and template icon number for every cell on     *\n *    the map. The output is organized in such a way so as to get maximum compression.         *\n *                                                                                             *\n * INPUT:   pipe  -- Reference to the output pipe that will receive the map template data.     *\n *                                                                                             *\n * OUTPUT:  Returns with the total number of bytes output to the pipe.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint MapClass::Write_Binary(Pipe & pipe)\n{\n\tint total = 0;\n\n\tLCWPipe comp(LCWPipe::COMPRESS);\n\tcomp.Put_To(&pipe);\n\n\tCellClass * cellptr = &Array[0];\n\tfor (int i = 0; i < MAP_CELL_TOTAL; i++) {\n\t\ttotal += comp.Put(&cellptr->TType, sizeof(cellptr->TType));\n\t\tcellptr++;\n\t}\n\n\tcellptr = &Array[0];\n\tfor (i = 0; i < MAP_CELL_TOTAL; i++) {\n\t\ttotal += comp.Put(&cellptr->TIcon, sizeof(cellptr->TIcon));\n\t\tcellptr++;\n\t}\n\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * MapClass::Read_Binary -- Reads the binary data from the straw specified.                    *\n *                                                                                             *\n *    This routine will retrieve the map template data from the straw specified.               *\n *                                                                                             *\n * INPUT:   straw -- Reference to the straw that will supply the map template data.            *\n *                                                                                             *\n * OUTPUT:  bool; Was the template data retrieved?                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool MapClass::Read_Binary(Straw & straw)\n{\n\tLCWStraw decomp(LCWStraw::DECOMPRESS);\n\tdecomp.Get_From(&straw);\n\n\tCELL cell;\n\tCellClass * cellptr;\n\tswitch (NewINIFormat) {\n\t\tdefault:\n\t\t\tcellptr = &Array[0];\n\t\t\tfor (cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\tdecomp.Get(&cellptr->TType, sizeof(cellptr->TType));\n\t\t\t\tcellptr++;\n\t\t\t}\n\t\t\tcellptr = &Array[0];\n\t\t\tfor (cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\tdecomp.Get(&cellptr->TIcon, sizeof(cellptr->TIcon));\n\t\t\t\tcellptr->Recalc_Attributes();\n\t\t\t\tcellptr++;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 0:\n\t\tcase 1:\n\t\tcase 2:\n\t\t\tcellptr = &Array[0];\n\t\t\tfor (cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\tdecomp.Get(&cellptr->TType, sizeof(cellptr->TType));\n\t\t\t\tdecomp.Get(&cellptr->TIcon, sizeof(cellptr->TIcon));\n\t\t\t\tcellptr->Recalc_Attributes();\n\t\t\t\tcellptr++;\n\t\t\t}\n\t\t\tbreak;\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * MapClass::Logic -- Handles map related logic functions.                                     *\n *                                                                                             *\n *    Manages tiberium growth and spread.                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/11/1995 JLB : Created.                                                                 *\n *   07/09/1995 JLB : Handles two directional scan.                                            *\n *   08/01/1995 JLB : Gives stronger weight to blossom trees.                                  *\n *=============================================================================================*/\nvoid MapClass::Logic(void)\n{\n\t/*\n\t**\tCrate regeneration is handled here.\n\t*/\n\tif (Session.Type != GAME_NORMAL && Session.Options.Goodies) {\n\n\t\t/*\n\t\t**\tFind any crate that has expired and then regenerate it at a new\n\t\t**\tspot.\n\t\t*/\n\t\tfor (int index = 0; index < ARRAY_SIZE(Crates); index++) {\n\t\t\tif (Crates[index].Is_Expired()) {\n\t\t\t\tCrates[index].Remove_It();\n\t\t\t\tPlace_Random_Crate();\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tBail early if there is no allowed growth or spread of Tiberium.\n\t*/\n\tif (!Rule.IsTGrowth && !Rule.IsTSpread) return;\n\n\t/*\n\t**\tScan another block of the map in order to accumulate the potential\n\t**\tTiberium cells that can grow or spread.\n\t*/\n\tint subcount = MAP_CELL_TOTAL / (Rule.GrowthRate * TICKS_PER_MINUTE);\n\tsubcount = max(subcount, 1);\n\tfor (int index = TiberiumScan; index < MAP_CELL_TOTAL; index++) {\n\t\tCELL cell = index;\n\t\tif (In_Radar(cell)) {\n\t\t\tCellClass * ptr = &(*this)[cell];\n\n\t\t\t/*\n\t\t\t**\tTiberium cells can grow.\n\t\t\t*/\n\t\t\tif (ptr->Can_Tiberium_Grow()) {\n\n\t\t\t\t/*\n\t\t\t\t**\tEither replace an existing recorded cell value or add the new cell value to\n\t\t\t\t**\tthe list.\n\t\t\t\t*/\n\t\t\t\tif (Random_Pick(0, TiberiumGrowthExcess) <= TiberiumGrowthCount) {\n\t\t\t\t\tif (TiberiumGrowthCount < sizeof(TiberiumGrowth)/sizeof(TiberiumGrowth[0])) {\n\t\t\t\t\t\tTiberiumGrowth[TiberiumGrowthCount++] = cell;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tTiberiumGrowth[Random_Pick(0, TiberiumGrowthCount-1)] = cell;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tTiberiumGrowthExcess++;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tHeavy Tiberium growth can spread.\n\t\t\t*/\n\t\t\tif (ptr->Can_Tiberium_Spread()) {\n\t\t\t\t/*\n\t\t\t\t**\tEither replace an existing recorded cell value or add the new cell value to\n\t\t\t\t**\tthe list.\n\t\t\t\t*/\n\t\t\t\tif (Random_Pick(0, TiberiumSpreadExcess) <= TiberiumSpreadCount) {\n\t\t\t\t\tif (TiberiumSpreadCount < ARRAY_SIZE(TiberiumSpread)) {\n\t\t\t\t\t\tTiberiumSpread[TiberiumSpreadCount++] = cell;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tTiberiumSpread[Random_Pick(0, TiberiumSpreadCount-1)] = cell;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tTiberiumSpreadExcess++;\n\t\t\t}\n\t\t}\n\n\t\tsubcount--;\n\t\tif (subcount == 0) break;\n\t}\n\tTiberiumScan = index;\n\n\t/*\n\t**\tWhen the entire map has been processed, proceed with tiberium (ore) growth\n\t**\tand spread action.\n\t*/\n\tif (TiberiumScan >= MAP_CELL_TOTAL) {\n\t\tTiberiumScan = 0;\n\n\t\t/*\n\t\t**\tGrowth logic.\n\t\t*/\n\t\tif (TiberiumGrowthCount) {\n\t\t\tfor (int i = 0; i < TiberiumGrowthCount; i++) {\n\t\t\t\tCELL cell = TiberiumGrowth[i];\n\t\t\t\tCellClass * newcell = &(*this)[cell];\n\t\t\t\tnewcell->Grow_Tiberium();\n\t\t\t}\n\t\t}\n\t\tTiberiumGrowthCount = 0;\n\t\tTiberiumGrowthExcess = 0;\n\n\t\t/*\n\t\t**\tSpread logic.\n\t\t*/\n\t\tif (TiberiumSpreadCount) {\n\t\t\tfor (int i = 0; i < TiberiumSpreadCount; i++) {\n\t\t\t\tMap[TiberiumSpread[i]].Spread_Tiberium();\n\t\t\t}\n\t\t}\n\t\tTiberiumSpreadCount = 0;\n\t\tTiberiumSpreadExcess = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Cell_Region -- Determines the region from a specified cell number.                *\n *                                                                                             *\n *    Use this routine to determine what region a particular cell lies in.                     *\n *                                                                                             *\n * INPUT:   cell  -- The cell number to examine.                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the region that the specified cell occupies.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint MapClass::Cell_Region(CELL cell)\n{\n\treturn((Cell_X(cell) / REGION_WIDTH) + 1) +\t(((Cell_Y(cell) / REGION_HEIGHT) + 1) * MAP_REGION_WIDTH);\n}\n\n\n/***************************************************************************\n * MapClass::Cell_Threat -- Gets a houses threat value for a cell          *\n *                                                                         *\n * INPUT:   CELL        cell    - the cell number to check                 *\n *            HouseType house   - the house to check                       *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/25/1995 PWG : Created.                                             *\n *=========================================================================*/\nint MapClass::Cell_Threat(CELL cell, HousesType house)\n{\n\tint threat = HouseClass::As_Pointer(house)->Regions[Map.Cell_Region(Map[cell].Cell_Number())].Threat_Value();\n\tif (!threat && Map[cell].IsVisible) {\n\t\tthreat = 1;\n\t}\n\treturn(threat);\n}\n\n\n/***********************************************************************************************\n * MapClass::Place_Random_Crate -- Places a crate at random location on map.                   *\n *                                                                                             *\n *    This routine will place a crate at a random location on the map. This routine will only  *\n *    make a limited number of attempts to place and if unsuccessful, it will not place any.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was a crate successfully placed?                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool MapClass::Place_Random_Crate(void)\n{\n\t/*\n\t**\tFind a crate index that is free for assignment. If there are\n\t**\tno free slots, then return with failure to place crate.\n\t*/\n\tint crateindex = 0;\n\tfor (crateindex = 0; crateindex < ARRAY_SIZE(Crates); crateindex++) {\n\t\tif (!Crates[crateindex].Is_Valid()) break;\n\t}\n\tif (crateindex == ARRAY_SIZE(Crates)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tGive a good effort to scan for and place a crate down on the map.\n\t*/\n\tfor (int index = 0; index < 1000; index++) {\n\t\tCELL cell = Map.Pick_Random_Location();\n\n\t\tif (Crates[crateindex].Create_Crate(cell)) {\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MapClass::Remove_Crate -- Remove a crate from the specified cell.                           *\n *                                                                                             *\n *    This will examine the cell and remove any crates there.                                  *\n *                                                                                             *\n * INPUT:   cell  -- The cell to examine for crates and remove from.                           *\n *                                                                                             *\n * OUTPUT:  bool; Was a crate found at the location specified and was it removed?              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool MapClass::Remove_Crate(CELL cell)\n{\n\tif (Session.Type != GAME_NORMAL) {\n\t\tfor (int index = 0; index < ARRAY_SIZE(Crates); index++) {\n\t\t\tif (Crates[index].Is_Here(cell)) {\n\t\t\t\treturn(Crates[index].Remove_It());\n\t\t\t}\n\t\t}\n\t}\n\n//\tif (Session.Type == GAME_NORMAL) {\n\t\tCellClass * cellptr = &(*this)[cell];\n\t\tif (cellptr->Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(cellptr->Overlay).IsCrate) {\n\t\t\tcellptr->Overlay = OVERLAY_NONE;\n\t\t\tcellptr->OverlayData = 0;\n\t\t\treturn(true);\n\t\t}\n//\t} else {\n//\t\tfor (int index = 0; index < ARRAY_SIZE(Crates); index++) {\n//\t\t\tif (Crates[index].Is_Here(cell)) {\n//\t\t\t\treturn(Crates[index].Remove_It());\n//\t\t\t}\n//\t\t}\n//\t}\n\treturn(false);\n}\n\n\n/***************************************************************************\n * MapClass::Validate -- validates every cell on the map                   *\n *                                                                         *\n * This is a debugging routine, designed to detect memory trashers that    *\n * alter the map.  This routine is slow, but thorough.                     *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      true = map is OK, false = an error was found                       *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/08/1995 BRR : Created.                                             *\n *=========================================================================*/\nint MapClass::Validate(void)\n{\n\tCELL cell;\n\tTemplateType ttype;\n\tunsigned char ticon;\n\tTemplateTypeClass const *tclass;\n\tunsigned char map[13*8];\n\tOverlayType overlay;\n\tSmudgeType smudge;\n\tObjectClass * obj;\n\tLandType land;\n\tint i;\n\nBlubCell = &Array[797];\n\nif (BlubCell->Overlapper[1]) {\n\tobj = BlubCell->Overlapper[1];\n\tif (obj) {\n\t\tif (obj->IsInLimbo)\n\t\tobj = obj;\n\t}\n}\n\n\t/*\n\t**\tCheck every cell on the map, even those that aren't displayed,\n\t**\tin the hopes of detecting a memory trasher.\n\t*/\n\tfor (cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t/*\n\t\t**\tValidate Template & Icon data\n\t\t*/\n\t\tttype = (*this)[cell].TType;\n\t\tticon = (*this)[cell].TIcon;\n\t\tif (ttype >= TEMPLATE_COUNT && ttype != TEMPLATE_NONE)\n\t\t\treturn(false);\n\n\t\t/*\n\t\t**\tTo validate the icon value, we have to get a copy of the template's\n\t\t**\t\"icon map\"; this map will have 0xff's in spots where there is no\n\t\t**\ticon.  If the icon value is out of range or points to an invalid spot,\n\t\t**\treturn an error.\n\t\t*/\n\t\tif (ttype != TEMPLATE_NONE) {\n\t\t\ttclass = &TemplateTypeClass::As_Reference(ttype);\n\t\t\tticon = (*this)[cell].TIcon;\n\t\t\tMem_Copy(Get_Icon_Set_Map(tclass->Get_Image_Data()), map, tclass->Width * tclass->Height);\n\t\t\tif (ticon < 0 || ticon >= (tclass->Width * tclass->Height) || map[ticon]==0xff) {\n\t\t\t\treturn (false);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tValidate Overlay\n\t\t*/\n\t\toverlay = (*this)[cell].Overlay;\n\t\tif (overlay < OVERLAY_NONE || overlay >= OVERLAY_COUNT) {\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t**\tValidate Smudge\n\t\t*/\n\t\tsmudge = (*this)[cell].Smudge;\n\t\tif (smudge < SMUDGE_NONE || smudge >= SMUDGE_COUNT) {\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t**\tValidate LandType\n\t\t*/\n\t\tland = (*this)[cell].Land_Type();\n\t\tif (land < LAND_CLEAR || land >= LAND_COUNT) {\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t**\tValidate Occupier\n\t\t*/\n\t\tobj = (*this)[cell].Cell_Occupier();\n\t\tif (obj) {\n\t\t\tif (\n\t\t\t\t((unsigned int)obj & 0xff000000) ||\n\t\t\t\t((unsigned int)obj->Next & 0xff000000) ||\n//\t\t\t\t((unsigned int)obj->Trigger & 0xff000000) ||\n\t\t\t\tobj->IsInLimbo ||\n\t\t\t\t((unsigned int)Coord_Cell(obj->Coord) >= MAP_CELL_TOTAL)) {\n\n\t\t\t\treturn (false);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tValidate Overlappers\n\t\t*/\n\t\tfor (i = 0; i < ARRAY_SIZE((*this)[cell].CellClass::Overlapper); i++) {\n\t\t\tobj = (*this)[cell].Overlapper[i];\n\t\t\tif (obj) {\n\t\t\t\tif (\n\t\t\t\t\t((unsigned int)obj & 0xff000000) ||\n\t\t\t\t\t((unsigned int)obj->Next & 0xff000000) ||\n//\t\t\t\t\t((unsigned int)obj->Trigger & 0xff000000) ||\n\t\t\t\t\tobj->IsInLimbo ||\n\t\t\t\t\t((unsigned int)Coord_Cell(obj->Coord) >= MAP_CELL_TOTAL)) {\n\n\t\t\t\t\treturn (false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn (true);\n}\n\n\n/***********************************************************************************************\n * MapClass::Close_Object -- Finds a clickable close object to the specified coordinate.       *\n *                                                                                             *\n *    This routine is used by the mouse input processing code to find a clickable object       *\n *    close to coordinate specified. This is for targeting as well as selection determination. *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to scan for close object from.                             *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to an object that is nearby the specified coordinate.       *\n *                                                                                             *\n * WARNINGS:   There could be a cloaked object at the location, but it won't be considered     *\n *             if it is not owned by the player.                                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * MapClass::Close_Object(COORDINATE coord) const\n{\n\tObjectClass * object = 0;\n\tint distance = 0;\n\tCELL cell = Coord_Cell(coord);\n\n\t/*\n\t**\tScan through current and adjacent cells, looking for the\n\t**\tclosest object (within reason) to the specified coordinate.\n\t*/\n\tstatic int _offsets[] = {0, -1, 1, -MAP_CELL_W, MAP_CELL_W, MAP_CELL_W-1, MAP_CELL_W+1, -(MAP_CELL_W-1), -(MAP_CELL_W+1)};\n\tfor (int index = 0; index < (sizeof(_offsets) / sizeof(_offsets[0])); index++) {\n\n\t\t/*\n\t\t**\tExamine the cell for close object. Make sure that the cell actually is a\n\t\t**\tlegal one.\n\t\t*/\n\t\tCELL newcell = cell + _offsets[index];\n\t\tif (In_Radar(newcell)) {\n\n\t\t\t/*\n\t\t\t**\tSearch through all objects that occupy this cell and then\n\t\t\t**\tfind the closest object. Check against any previously found object\n\t\t\t**\tto ensure that it is actually closer.\n\t\t\t*/\n\t\t\tObjectClass * o = Array[newcell].Cell_Occupier();\n\t\t\twhile (o != NULL) {\n\n\t\t\t\t/*\n\t\t\t\t**\tSpecial case check to ignore cloaked object if not owned by the player.\n\t\t\t\t*/\n\t\t\t\tif (!o->Is_Techno() || ((TechnoClass *)o)->IsOwnedByPlayer || ((TechnoClass *)o)->Cloak != CLOAKED) {\n\t\t\t\t\tint d=-1;\n\t\t\t\t\tif (o->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\td = Distance(coord, Cell_Coord(newcell));\n\t\t\t\t\t\tif (d > 0x00B5) d = -1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\td = Distance(coord, o->Center_Coord());\n\t\t\t\t\t}\n\t\t\t\t\tif (d >= 0 && (!object || d < distance)) {\n\t\t\t\t\t\tdistance = d;\n\t\t\t\t\t\tobject = o;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\to = o->Next;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tOnly return the object if it is within 1/4 cell distance from the specified\n\t**\tcoordinate.\n\t*/\n\tif (object && distance > 0xB5) {\n\t\tobject = 0;\n\t}\n\treturn(object);\n}\n\n\n/***********************************************************************************************\n * MapClass::Zone_Reset -- Resets all zone numbers to match the map.                           *\n *                                                                                             *\n *    This routine will rescan the map and fill in the zone values for each of the cells.      *\n *    All cells that are contiguous are given the same zone number.                            *\n *                                                                                             *\n * INPUT:   method   -- The method to recalculate the zones upon. If 1 then recalc non         *\n *                      crushable zone. If 2 then recalc crushable zone. If 3, then            *\n *                      recalc both zones.                                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This is a time consuming routine. Call it as infrequently as possible. It must  *\n *             be called whenever something that would affect contiguousness occurs. Example:  *\n *             when a bridge is built or destroyed.                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool MapClass::Zone_Reset(int method)\n{\n\t/*\n\t**\tZero out all zones to a null state.\n\t*/\n\tfor (int index = 0; index < MAP_CELL_TOTAL; index++) {\n\t\tif (method & MZONEF_NORMAL) {\n\t\t\tArray[index].Zones[MZONE_NORMAL] = 0;\n\t\t}\n\t\tif (method & MZONEF_CRUSHER) {\n\t\t\tArray[index].Zones[MZONE_CRUSHER] = 0;\n\t\t}\n\t\tif (method & MZONEF_DESTROYER) {\n\t\t\tArray[index].Zones[MZONE_DESTROYER] = 0;\n\t\t}\n\t\tif (method & MZONEF_WATER) {\n\t\t\tArray[index].Zones[MZONE_WATER] = 0;\n\t\t}\n\t}\n\n\t/*\n\t**\tNormal zone recalculation.\n\t*/\n\tif (method & MZONEF_NORMAL) {\n\t\tint zone = 1;\t\t\t// Starting zone number.\n\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\tif (Zone_Span(cell, zone, MZONE_NORMAL)) {\n\t\t\t\tzone++;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCrushable wall recalculation.\n\t*/\n\tif (method & MZONEF_CRUSHER) {\n\t\tint zone = 1;\t\t\t// Starting zone number.\n\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\tif (Zone_Span(cell, zone, MZONE_CRUSHER)) {\n\t\t\t\tzone++;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tWall destroyer zone recalculation.\n\t*/\n\tif (method & MZONEF_DESTROYER) {\n\t\tint zone = 1;\t\t\t// Starting zone number.\n\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\tif (Zone_Span(cell, zone, MZONE_DESTROYER)) {\n\t\t\t\tzone++;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tWater based zone recalcuation.\n\t*/\n\tif (method & MZONEF_WATER) {\n\t\tint zone = 1;\t\t\t// Starting zone number.\n\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\tif (Zone_Span(cell, zone, MZONE_WATER)) {\n\t\t\t\tzone++;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MapClass::Zone_Span -- Flood fills the specified zone from the cell origin.                 *\n *                                                                                             *\n *    This routine is used to fill a zone value into the map. The map is \"flood filled\" from   *\n *    the cell specified. All adjacent (8 connected) and generally passable terrain cells are  *\n *    given the zone number specified. This routine checks for legality before filling         *\n *    occurs. The routine is safe to call even if the legality of the cell is unknown at the   *\n *    time of the call.                                                                        *\n *                                                                                             *\n * INPUT:   cell  -- The cell to begin filling from.                                           *\n *                                                                                             *\n *          zone  -- The zone number to assign to all adjacent cells.                          *\n *                                                                                             *\n *          check -- The zone type to check against.                                           *\n *                                                                                             *\n * OUTPUT:  Returns with the number of cells marked by this routine.                           *\n *                                                                                             *\n * WARNINGS:   This routine is slow and recursive. Only use when necessary.                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/25/1995 JLB : Created.                                                                 *\n *   10/05/1996 JLB : Examines crushable walls.                                                *\n *=============================================================================================*/\nint MapClass::Zone_Span(CELL cell, int zone, MZoneType check)\n{\n\tint filled = 0;\n\tint xbegin = Cell_X(cell);\n\tint xend = xbegin;\n\tint y = Cell_Y(cell);\n\n\t/*\n\t**\tPerform some preliminary legality checks. If the cell specified\n\t**\tis illegal, then no further processing is necessary.\n\t*/\n\tif (y < MapCellY || y >= MapCellY+MapCellHeight || xbegin < MapCellX || xbegin >= MapCellX+MapCellWidth) {\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tFind the full extent of the current span by first scanning leftward\n\t**\tuntil a boundary is reached.\n\t*/\n\tfor (; xbegin >= MapCellX; xbegin--) {\n\t\tCellClass * cellptr = &(*this)[XY_Cell(xbegin, y)];\n\t\tif (cellptr->Zones[check] != 0 || (!cellptr->Is_Clear_To_Move(check == MZONE_WATER ? SPEED_FLOAT : SPEED_TRACK, true, true, -1, check))) {\n\n\t\t\t/*\n\t\t\t**\tSpecial short circuit code to bail from this entire routine if\n\t\t\t**\tit was called for a cell that is not a legal candidate for\n\t\t\t**\tzone marking. This eliminates redundant processing and allows this\n\t\t\t**\troutine to be called for illegal cells without causing an error.\n\t\t\t*/\n\t\t\tif (xbegin == Cell_X(cell)) return(0);\n\n\t\t\t/*\n\t\t\t**\tOtherwise break out of the left scan since a boundary was discovered.\n\t\t\t*/\n\t\t\txbegin++;\n\t\t\tbreak;\n\t\t}\n\t}\n\txbegin = max(xbegin, MapCellX);\n\n\t/*\n\t**\tScan rightward until a boundary is reached. This will then define the\n\t**\textent of the current span.\n\t*/\n\tfor (; xend < MapCellX+MapCellWidth; xend++) {\n\t\tCellClass * cellptr = &(*this)[XY_Cell(xend, y)];\n\t\tif (cellptr->Zones[check] != 0 || (!cellptr->Is_Clear_To_Move(check == MZONE_WATER ? SPEED_FLOAT : SPEED_TRACK, true, true, -1, check))) {\n\t\t\txend--;\n\t\t\tbreak;\n\t\t}\n\t}\n\txend = min(xend, MapCellX+MapCellWidth-1);\n\n\t/*\n\t**\tAt this point we know the bounds of the current span. Fill in the zone values\n\t**\tfor the entire span.\n\t*/\n\tfor (int x = xbegin; x <= xend; x++) {\n\t\t(*this)[XY_Cell(x, y)].Zones[check] = zone;\n\t\tfilled++;\n\t}\n\n\t/*\n\t**\tNow scan the upper and lower shadow rows. If any of these rows contain\n\t**\tcandidate cells, then recursively call the span process for them. Take\n\t**\tnote that the adjacent span scanning starts one cell wider on each\n\t**\tend of the scan. This is necessary because diagonals are considered\n\t**\tadjacent.\n\t*/\n\tfor (x = xbegin-1; x <= xend; x++) {\n\t\tfilled += Zone_Span(XY_Cell(x, y-1), zone, check);\n\t\tfilled += Zone_Span(XY_Cell(x, y+1), zone, check);\n\t}\n\treturn(filled);\n}\n\n\n/***********************************************************************************************\n * MapClass::Nearby_Location -- Finds a generally clear location near a specified cell.        *\n *                                                                                             *\n *    This routine is used to find a location that probably will be ok to move to that is      *\n *    located as close as possible to the specified cell. The computer uses this when it has   *\n *    determined the ideal location for an object, but then needs to give a valid movement     *\n *    destination to a unit.                                                                   *\n *                                                                                             *\n * INPUT:   cell  -- The cell that scanning should radiate out from.                           *\n *                                                                                             *\n *          zone  -- The zone that must be matched to find a legal location (value of -1 means *\n *                   any zone will do).                                                        *\n *                                                                                             *\n *                                                                                             *\n *          check -- The type of zone to check against. Only valid if a zone value is given.   *\n *                                                                                             *\n * OUTPUT:  Returns with the cell that is generally clear (legal to move to) that is close     *\n *          to the specified cell.                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/05/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL MapClass::Nearby_Location(CELL cell, SpeedType speed, int zone, MZoneType check) const\n{\n\tCELL topten[10];\n\tint count = 0;\n\tint xx = Cell_X(cell);\n\tint yy = Cell_Y(cell);\n\n\t/*\n\t**\tDetermine the limits of the scanning in the four directions so that\n\t**\tit won't scan past the edge of the world.\n\t*/\n\tint left = xx - MapCellX;\n\tint right = (MapCellWidth - left) - 1;\n\tint top = yy - MapCellY;\n\tint bottom = (MapCellHeight - top) - 1;\n\n\t/*\n\t**\tRadiate outward from the specified location, looking for the closest\n\t**\tlocation that is generally clear.\n\t*/\n\tfor (int radius = 0; radius < MAP_CELL_W/2; radius++) {\n\t\tCELL newcell;\n\t\tCellClass const * cellptr;\n\n\t\t/*\n\t\t**\tScan the top and bottom rows of the \"box\".\n\t\t*/\n\t\tfor (int x = -radius; x <= radius; x++) {\n\t\t\tif (x >= -left && radius <= top) {\n\t\t\t\tnewcell = XY_Cell(xx+x, yy-radius);\n\t\t\t\tcellptr = &Map[newcell];\n\t\t\t\tif (Map.In_Radar(newcell) && cellptr->Is_Clear_To_Move(speed, false, false, zone, check)) {\n\t\t\t\t\ttopten[count++] = newcell;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (count == ARRAY_SIZE(topten)) break;\n\n\t\t\tif (x <= right && radius <= bottom) {\n\t\t\t\tnewcell = XY_Cell(xx+x, yy+radius);\n\t\t\t\tcellptr = &Map[newcell];\n\t\t\t\tif (Map.In_Radar(newcell) && cellptr->Is_Clear_To_Move(speed, false, false, zone, check)) {\n\t\t\t\t\ttopten[count++] = newcell;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (count == ARRAY_SIZE(topten)) break;\n\t\t}\n\n\t\tif (count == ARRAY_SIZE(topten)) break;\n\n\t\t/*\n\t\t**\tScan the left and right columns of the \"box\".\n\t\t*/\n\t\tfor (int y = -(radius-1); y <= radius-1; y++) {\n\t\t\tif (y >= -top && radius <= left) {\n\t\t\t\tnewcell = XY_Cell(xx-radius, yy+y);\n\t\t\t\tcellptr = &Map[newcell];\n\t\t\t\tif (Map.In_Radar(newcell) && cellptr->Is_Clear_To_Move(speed, false, false, zone, check)) {\n\t\t\t\t\ttopten[count++] = newcell;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (count == ARRAY_SIZE(topten)) break;\n\n\t\t\tif (y <= bottom && radius <= right) {\n\t\t\t\tnewcell = XY_Cell(xx+radius, yy+y);\n\t\t\t\tcellptr = &Map[newcell];\n\t\t\t\tif (Map.In_Radar(newcell) && cellptr->Is_Clear_To_Move(speed, false, false, zone, check)) {\n\t\t\t\t\ttopten[count++] = newcell;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (count == ARRAY_SIZE(topten)) break;\n\t\t}\n\n\t\tif (count > 0) break;\n\t}\n\n\tif (count > 0) {\n\t\treturn(topten[Frame % count]);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * MapClass::Base_Region -- Finds the owner and base zone for specified cell.                  *\n *                                                                                             *\n *    This routine is used to determine what base the specified cell is close to and what      *\n *    zone of that base the cell lies in. This routine is particularly useful in letting the   *\n *    computer know when the player targets a destination near a computer's base.              *\n *                                                                                             *\n * INPUT:   cell     -- The cell that is to be checked.                                        *\n *                                                                                             *\n *          house    -- Reference to the house type number. This value will be set if a base   *\n *                      was found nearby the specified cell.                                   *\n *                                                                                             *\n *          zone     -- The zone that the cell is located in IF the cell is near a base.       *\n *                                                                                             *\n *                                                                                             *\n * OUTPUT:  Was a base near the specified cell found? If not, then the 'house' and 'zone'      *\n *          reference values are left in an undefined state and the return value will be       *\n *          false.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/05/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool MapClass::Base_Region(CELL cell, HousesType & house, ZoneType & zone) const\n{\n\tif ((unsigned)cell < MAP_CELL_TOTAL && In_Radar(cell)) {\n\t\tfor (house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\t\tHouseClass * h = HouseClass::As_Pointer(house);\n\n\t\t\tif (h && h->IsActive && !h->IsDefeated && h->Center) {\n\t\t\t\tzone = h->Which_Zone(cell);\n\t\t\t\tif (zone != ZONE_NONE) {\n\t\t\t\t\treturn(true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MapClass::Destroy_Bridge_At -- Destroyes the bridge at location specified.                  *\n *                                                                                             *\n *    This routine will destroy the bridge at the location specified.                          *\n *                                                                                             *\n * INPUT:   cell  -- A cell that can uniquely identify the bridge.                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the bridge destroyed?                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool MapClass::Destroy_Bridge_At(CELL cell)\n{\n\tif (In_Radar(cell) && !Special.IsCaptureTheFlag) {\n\t\tCellClass * cellptr = &(*this)[cell];\n\t\tTemplateType ttype = cellptr->TType;\n\n\t\tif (ttype == TEMPLATE_BRIDGE1 || ttype == TEMPLATE_BRIDGE2) {\n\t\t\tint icon = cellptr->TIcon;\n\t\t\tint w = TemplateTypeClass::As_Reference(ttype).Width;\n\t\t\tint h = TemplateTypeClass::As_Reference(ttype).Height;\n\n\t\t\tcell -= icon % w;\n\t\t\tcell -= MAP_CELL_W * (icon / w);\n\n\t\t\tif (ttype == TEMPLATE_BRIDGE1) {\n\t\t\t\tnew TemplateClass(TEMPLATE_BRIDGE1H, cell);\n\t\t\t} else {\n\t\t\t\tnew TemplateClass(TEMPLATE_BRIDGE2H, cell);\n\t\t\t}\n\n\t\t\tnew AnimClass(ANIM_NAPALM3, Cell_Coord(cell + w/2 + (h/2)*MAP_CELL_W));\n\t\t}\n\n\t\tif (ttype == TEMPLATE_BRIDGE1H || ttype == TEMPLATE_BRIDGE2H) {\n\t\t\tint icon = cellptr->TIcon;\n\t\t\tint bridge_w = TemplateTypeClass::As_Reference(ttype).Width;\n\t\t\tint bridge_h = TemplateTypeClass::As_Reference(ttype).Height;\n\n\t\t\tcell -= icon % bridge_w;\n\t\t\tcell -= MAP_CELL_W * (icon / bridge_w);\n\n\t\t\tif (ttype == TEMPLATE_BRIDGE1H) {\n\t\t\t\tnew TemplateClass(TEMPLATE_BRIDGE1D, cell);\n\t\t\t} else {\n\t\t\t\tnew TemplateClass(TEMPLATE_BRIDGE2D, cell);\n\t\t\t}\n\n\t\t\tScen.BridgeCount--;\n\t\t\tScen.IsBridgeChanged = true;\n\t\t\tnew AnimClass(ANIM_NAPALM3, Cell_Coord(cell + bridge_w/2 + (bridge_h/2)*MAP_CELL_W));\n\t\t\tMap.Zone_Reset(MZONEF_ALL);\n\n\t\t\t/*\n\t\t\t** Now, loop through all the bridge cells and find anyone standing\n\t\t\t** on a destroyed part (which is now river), and nuke them.\n\t\t\t*/\n\t\t\tfor (int y = 0; y < bridge_h; y++) {\n\t\t\t\tfor (int x = 0; x < bridge_w; x++) {\n\t\t\t\t\tCellClass * bridge_cell = &(*this)[cell];\n\t\t\t\t\tif (bridge_cell->TType == ttype) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tAny unit that is firing on the bridge at this location, will stop\n\t\t\t\t\t\t**\tfiring because the bridge has been destroyed.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tDetach_This_From_All(As_Target(cell), true);\n\n\t\t\t\t\t\tObjectClass * obj = bridge_cell->Cell_Occupier();\n\t\t\t\t\t\twhile (obj != NULL) {\n\t\t\t\t\t\t\tObjectClass * next = obj->Next;\n\t\t\t\t\t\t\tif (obj->Is_Techno()) {\n\t\t\t\t\t\t\t\tint damage = obj->Strength;\n\t\t\t\t\t\t\t\tobj->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tobj = next;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcell++;\n\t\t\t\t}\n\t\t\t\tcell += MAP_CELL_W - bridge_w;\n\t\t\t}\n\t\t\tShake_The_Screen(3);\n\n\t\t\treturn(true);\n\t\t} else {\n\t\t\t/*\n\t\t\t** All this code is for the multi-part bridges.\n\t\t\t*/\n\t\t\tif (ttype >= TEMPLATE_BRIDGE_1A && ttype <= TEMPLATE_BRIDGE_3E) {\n\t\t\t\tint icon = cellptr->TIcon;\n\t\t\t\tint w = TemplateTypeClass::As_Reference(ttype).Width;\n\t\t\t\tint h = TemplateTypeClass::As_Reference(ttype).Height;\n\n\t\t\t\tcell -= icon % w;\n\t\t\t\tcell -= MAP_CELL_W * (icon / w);\n\t\t\t\tswitch (ttype) {\n\t\t\t\t\tcase TEMPLATE_BRIDGE_1A:\n\t\t\t\t\tcase TEMPLATE_BRIDGE_1B:\n\t\t\t\t\tcase TEMPLATE_BRIDGE_2A:\n\t\t\t\t\tcase TEMPLATE_BRIDGE_2B:\n\t\t\t\t\tcase TEMPLATE_BRIDGE_3A:\n\t\t\t\t\tcase TEMPLATE_BRIDGE_3B:\n\t\t\t\t\t\tttype++;\n\t\t\t\t\t\tnew TemplateClass(TemplateType(ttype), cell);\n\t\t\t\t\t\tbreak;\n\t\t \t\t}\n\n\t\t\t\t/*\n\t\t\t\t** If we were a middle piece that just got blown up, update the\n\t\t\t\t** adjoining pieces to make sure they're shaped properly.\n\t\t\t\t*/\n\t\t\t\tif (ttype == TEMPLATE_BRIDGE_3C) {\n\t\t\t\t\t// check the template below us, at x-1, y+1\n\t\t\t\t\tCELL cell2 = cell + (MAP_CELL_W - 1);\n\t\t\t\t\tCellClass * celptr = &(*this)[cell2];\n\t\t\t\t\tif (celptr->TType == TEMPLATE_BRIDGE_3C) {\n\t\t\t\t\t\t// It was also destroyed.  Update us and it.\n\t\t\t\t\t\tnew TemplateClass(TemplateType(TEMPLATE_BRIDGE_3D), cell);\n\t\t\t\t\t\tnew TemplateClass(TemplateType(TEMPLATE_BRIDGE_3E), cell2);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Now check the template above us, at x+1, y-1.\n\t\t\t\t\tcell2 = cell - (MAP_CELL_W - 1);\n\t\t\t\t\tcelptr = &(*this)[cell2];\n\t\t\t\t\tif (celptr->TType == TEMPLATE_BRIDGE_3C) {\n\t\t\t\t\t\tif (cellptr->TType == TEMPLATE_BRIDGE_3D) {\n\t\t\t\t\t\t\t// if we're already one-sided, turn us to all water\n\t\t\t\t\t\t\tnew TemplateClass(TemplateType(TEMPLATE_BRIDGE_3F), cell);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnew TemplateClass(TemplateType(TEMPLATE_BRIDGE_3E), cell);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnew TemplateClass(TemplateType(TEMPLATE_BRIDGE_3D), cell2);\n\t\t\t\t\t}\n\t\t\t\t\tMap.Zone_Reset(MZONEF_ALL);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** If we're an end bridge piece, update the adjoining piece to\n\t\t\t\t** be the proper shape.\n\t\t\t\t*/\n\t\t\t\tif (cellptr->TType == TEMPLATE_BRIDGE_1C) {\n\t\t\t\t\tScen.BridgeCount--;\n\t\t\t\t\tScen.IsBridgeChanged = true;\n\n\t\t\t\t\t// Point to the template below us, x-1, y+2\n\t\t\t\t\tCELL cell2 = cell + (MAP_CELL_W * 2) - 1;\n\t\t\t\t\tswitch ((*this)[cell2].TType) {\n\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3A:\n\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3B:\n\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3C:\n\t\t\t\t\t\t\tnew TemplateClass(TemplateType(TEMPLATE_BRIDGE_3E), cell2);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3D:\n\t\t\t\t\t\t\tnew TemplateClass(TemplateType(TEMPLATE_BRIDGE_3F), cell2);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (cellptr->TType == TEMPLATE_BRIDGE_2C) {\n\t\t\t\t\t\t// Point to the template above us, x+2, y-1\n\t\t\t\t\t\tCELL cell2 = cell - (MAP_CELL_W - 2);\n\t\t\t\t\t\tswitch ((*this)[cell2].TType) {\n\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3A:\n\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3B:\n\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3C:\n\t\t\t\t\t\t\t\tnew TemplateClass(TemplateType(TEMPLATE_BRIDGE_3D), cell2);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3E:\n\t\t\t\t\t\t\t\tnew TemplateClass(TemplateType(TEMPLATE_BRIDGE_3F), cell2);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (cellptr->TType == TEMPLATE_BRIDGE_1C ||\n\t\t\t\t\tcellptr->TType == TEMPLATE_BRIDGE_2C ||\n\t\t\t\t  (cellptr->TType >= TEMPLATE_BRIDGE_3C && cellptr->TType <= TEMPLATE_BRIDGE_3E)) {\n\t\t\t\t\tint x, y, tdata = 0;\n\t\t\t\t\tfor (y = 0; y < h; y++) {\n\t\t\t\t\t\tfor (x = 0; x < w; x++) {\n\t\t\t\t\t\t\tCellClass * ptr = &(*this)[(CELL)(cell + x)];\n\t\t\t\t\t\t\tif (ptr->TType == cellptr->TType || ptr->Land_Type() == LAND_RIVER || ptr->Land_Type() == LAND_WATER) {\n\t\t\t\t\t\t\t\tDetach_This_From_All(As_Target((CELL)(cell+tdata)), true);\n\n\t\t\t\t\t\t\t\tObjectClass * obj = ptr->Cell_Occupier();\n\t\t\t\t\t\t\t\twhile (obj != NULL) {\n\t\t\t\t\t\t\t\t\tObjectClass * next = obj->Next;\n\t\t\t\t\t\t\t\t\tif (obj->Is_Techno()) {\n\t\t\t\t\t\t\t\t\t\tint damage = obj->Strength;\n\t\t\t\t\t\t\t\t\t\tobj->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tobj = next;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttdata++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcell += MAP_CELL_W;\n\t\t\t\t\t}\n\t\t\t\t\tShake_The_Screen(3);\n\t\t\t\t\tMap.Zone_Reset(MZONEF_ALL);\n\t\t\t\t\treturn(true);\n\t\t\t\t}\n\t\t\t\tShake_The_Screen(3);\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MapClass::Detach -- Remove specified object from map references.                            *\n *                                                                                             *\n *    This routine will take the object (represented by a target value) and remove all         *\n *    references to it from the map. Typically, this is used to remove trigger reference.      *\n *                                                                                             *\n * INPUT:   target   -- The target object to remove from the map.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Detach(TARGET target, bool)\n{\n\t/*\n\t**\tRemove this trigger from the map zone/line tracking list.\n\t*/\n\tif (Is_Target_Trigger(target)) {\n\t\tfor (int index = 0; index < MapTriggers.Count(); index++) {\n\t\t\tif (MapTriggers[index] == As_Trigger(target)) {\n\t\t\t\tMapTriggers.Delete(index);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tLoop through all cells; remove any reference to this trigger\n\t\t*/\n\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\tif ((*this)[cell].Trigger == As_Trigger(target)) {\n\t\t\t\t(*this)[cell].Trigger = NULL;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Intact_Bridge_Count -- Determine the number of intact bridges.                    *\n *                                                                                             *\n *    This will examine the entire map and return the number of bridges that are intact. An    *\n *    intact bridge is one that units can travel over.                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of intact bridges on the map.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint MapClass::Intact_Bridge_Count(void) const\n{\n\t/*\n\t**\tCount all non-destroyed bridges on the map.\n\t*/\n\tint count = 0;\n\tCellClass const * cellptr = &(*this)[(CELL)0];\n\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tswitch (cellptr->TType) {\n\t\t\tcase TEMPLATE_BRIDGE1:\n\t\t\tcase TEMPLATE_BRIDGE1H:\n\t\t\tcase TEMPLATE_BRIDGE2:\n\t\t\tcase TEMPLATE_BRIDGE2H:\n\t\t\tcase TEMPLATE_BRIDGE_1A:\n\t\t\tcase TEMPLATE_BRIDGE_1B:\n\t\t\t\tif (cellptr->TIcon == 6) {\n\t\t\t\t\tcount++;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tcellptr++;\n\t}\n\n\treturn(count);\n}\n\n\n/***********************************************************************************************\n * MapClass::Pick_Random_Location -- Picks a random location on the map.                       *\n *                                                                                             *\n *    This routine will pick a random location on the map. It performs no legality checking    *\n *    other than forcing the cell to be on the map proper.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a cell that is within the map.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/25/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL MapClass::Pick_Random_Location(void) const\n{\n\tint x = Map.MapCellX + Random_Pick(0, Map.MapCellWidth-1);\n\tint y = Map.MapCellY + Random_Pick(0, Map.MapCellHeight-1);\n\n\treturn(XY_Cell(x, y));\n}\n\n/***********************************************************************************************\n * MapClass::Shroud_The_Map -- cover the whole map in darkness (usually from blackout crate)\t  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a cell that is within the map.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/19/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Shroud_The_Map(void)\n{\n\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tCellClass * cellptr = &Map[cell];\n\t\tif (cellptr->IsMapped || cellptr->IsVisible) {\n\t\t\tcellptr->Redraw_Objects();\n\t\t\t/*\n\t\t\t** BG: remove \"ring of darkness\" around edge of map.\n\t\t\t*/\n\t\t\tint x = Cell_X(cell);\n\t\t\tint y = Cell_Y(cell);\n\t\t\tif (x >= Map.MapCellX && x < (Map.MapCellX + Map.MapCellWidth) &&\n\t\t\t\ty >= Map.MapCellY && y < (Map.MapCellY + Map.MapCellHeight)) {\n\t\t\t\tcellptr->IsMapped = false;\n\t\t\t\tcellptr->IsVisible = false;\n\t\t\t}\n\t\t}\n\t}\n\tfor (int obj_index = 0; obj_index < DisplayClass::Layer[LAYER_GROUND].Count(); obj_index++) {\n\t\tObjectClass * layer_object = DisplayClass::Layer[LAYER_GROUND][obj_index];\n\t\tif (layer_object && layer_object->Is_Techno() && ((TechnoClass *)layer_object)->House == PlayerPtr) {\n\t\t\tlayer_object->Look();\n\t\t}\n\t}\n\tFlag_To_Redraw(true);\n}\n"
  },
  {
    "path": "CODE/MAP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MAP.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MAP.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 29, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 29, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MAP_H\n#define MAP_H\n\n#include\t\"gscreen.h\"\n#include\t\"crate.h\"\n\nclass MapClass: public GScreenClass\n{\n\tpublic:\n\n\t\tMapClass(void) {};\n\t\tMapClass(NoInitClass const & x) : GScreenClass(x), Array(x) {};\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t// Theater-specific inits\n\t\tvirtual void Init_Clear(void);\t\t\t\t\t\t// Clears all to known state\n\t\tvirtual void Alloc_Cells(void);\t\t\t\t\t\t// Allocates buffers\n\t\tvirtual void Free_Cells(void);\t\t\t\t\t\t\t// Frees buffers\n\t\tvirtual void Init_Cells(void);\t\t\t\t\t\t\t// Frees buffers\n\n\t\t/*--------------------------------------------------------\n\t\t** Main functions that deal with groupings of cells within the map or deals with the cell\n\t\t** as it relates to the map - not what the cell contains.\n\t\t*/\n\t\tCELL Pick_Random_Location(void) const;\n\t\tint Intact_Bridge_Count(void) const;\n\t\tbool Base_Region(CELL cell, HousesType & house, ZoneType & zone) const;\n\t\tCELL Nearby_Location(CELL cell, SpeedType speed, int zone=-1, MZoneType check=MZONE_NORMAL) const;\n\t\tObjectClass * Close_Object(COORDINATE coord) const;\n\t\tvirtual void Detach(ObjectClass * ) {};\n\t\tint Cell_Region(CELL cell);\n\t\tint Cell_Threat(CELL cell, HousesType house);\n\t\tbool In_Radar(CELL cell) const;\n\t\tvoid Sight_From(CELL cell, int sightrange, HouseClass *house, bool incremental=false);\n\t\tvoid Jam_From(CELL cell, int jamrange, HouseClass *house);\n\t\tvoid Shroud_From(CELL cell, int sightrange);\n\t\tvoid UnJam_From(CELL cell, int jamrange, HouseClass *house);\n\t\tvoid Place_Down(CELL cell, ObjectClass * object);\n\t\tvoid Pick_Up(CELL cell, ObjectClass * object);\n\t\tvoid Overlap_Down(CELL cell, ObjectClass * object);\n\t\tvoid Overlap_Up(CELL cell, ObjectClass * object);\n\t\tbool Read_Binary(Straw & straw);\n\t\tint Write_Binary(Pipe & pipe);\n\t\tbool Place_Random_Crate(void);\n\t\tbool Remove_Crate(CELL cell);\n\t\tbool Zone_Reset(int method);\n\t\tbool Zone_Cell(CELL cell, int zone);\n\t\tint Zone_Span(CELL cell, int zone, MZoneType check);\n\t\tbool Destroy_Bridge_At(CELL cell);\n\t\tvoid Detach(TARGET target, bool all=true);\n\t\tvoid Shroud_The_Map(void);\n\n\t\tlong Overpass(void);\n\n\t\tvirtual void Logic(void);\n\t\tvirtual void Set_Map_Dimensions(int x, int y, int w, int h);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n\n\t\t/*\n\t\t** Debug routine\n\t\t*/\n\t\tint Validate(void);\n\n\t\t/*\n\t\t**\tThis is the dimensions and position of the sub section of the global map.\n\t\t**\tIt is this region that appears on the radar map and constrains normal\n\t\t**\tmovement.\n\t\t*/\n\t\tint MapCellX;\n\t\tint MapCellY;\n\t\tint MapCellWidth;\n\t\tint MapCellHeight;\n\n\t\t/*\n\t\t**\tThis is the total value of all harvestable Tiberium on the map.\n\t\t*/\n\t\tlong TotalValue;\n\n\t\tCellClass & operator [] (COORDINATE coord) {return(Array[Coord_Cell(coord)]);};\n\t\tCellClass & operator [] (CELL cell) {return(Array[cell]);};\n\t\tCellClass const & operator [] (COORDINATE coord) const {return(Array[Coord_Cell(coord)]);};\n\t\tCellClass const & operator [] (CELL cell) const {return(Array[cell]);};\n\t\tint ID(CellClass const * ptr) {return(Array.ID(ptr));};\n\t\tint ID(CellClass const & ptr) {return(Array.ID(ptr));};\n\n\tprotected:\n\n\t\t/*\n\t\t**\tThis is the array of cell objects.\n\t\t*/\n\t\tVectorClass<CellClass> Array;\n\n\t\t/*\n\t\t**\tThese are the size dimensions of the underlying array of cell objects.\n\t\t**\tThis is the dimensions of the \"map\" that the tactical view is\n\t\t**\trestricted to.\n\t\t*/\n\t\tint\tXSize;\n\t\tint\tYSize;\n\t\tint\tSize;\n\n\t\tstatic int const RadiusCount[11];\n\t\tstatic int const RadiusOffset[];\n\n\t\t/*\n\t\t**\tThis specifies the information for the various crates in the game.\n\t\t*/\n\t\tCrateClass Crates[256];\n\n\tprivate:\n\t\tfriend class CellClass;\n\n\t\t/*\n\t\t**\tTiberium growth potential cells are recorded here.\n\t\t*/\n\t\tCELL TiberiumGrowth[MAP_CELL_W/2];\n\t\tint TiberiumGrowthCount;\n\t\tint TiberiumGrowthExcess;\n\n\t\t/*\n\t\t**\tList of cells that are full enough strength that they could spread\n\t\t**\tTiberium to adjacent cells.\n\t\t*/\n\t\tCELL TiberiumSpread[MAP_CELL_W/2];\n\t\tint TiberiumSpreadCount;\n\t\tint TiberiumSpreadExcess;\n\n\t\t/*\n\t\t**\tThis is the current cell number in the incremental map scan process.\n\t\t*/\n\t\tCELL TiberiumScan;\n\n\t\tenum MapEnum {SCAN_AMOUNT=MAP_CELL_TOTAL};\n};\n\n#endif\n"
  },
  {
    "path": "CODE/MAPEDDLG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MAPEDDLG.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : MAPEDDLG.CPP                             *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : November 18, 1994                        *\n *                                                                         *\n *                  Last Update : September 4, 1996 [JLB]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Map Editor dialogs & main menu options                                  *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   MapEditClass::Handle_Triggers -- processes the trigger dialogs        *\n *   MapEditClass::Load_Scenario -- loads a scenario INI file              *\n *   MapEditClass::New_Scenario -- creates a new scenario                  *\n *   MapEditClass::Pick_Scenario -- dialog for choosing scenario           *\n *   MapEditClass::Save_Scenario -- saves current scenario to an INI file  *\n *   MapEditClass::Scenario_Dialog -- scenario global parameters dialog    *\n *   MapEditClass::Select_Trigger -- lets user select a trigger            *\n *   MapEditClass::Size_Map -- lets user set size & location of map        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n#ifdef SCENARIO_EDITOR\n\n\n/***************************************************************************\n * MapEditClass::New_Scenario -- creates a new scenario                    *\n *                                                                         *\n * - Prompts user for scenario data (house, scenario #); sets globals      *\n *     PlayerPtr (for house) & Scenario (for scenario #)                   *\n *   - Prompts user for map size                                           *\n * - Initializes the scenario by calling Clear_Scenario(), which calls     *\n *     everybody's Init() routine                                          *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = new scenario created, -1 = not                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/21/1994 BR : Created.                                              *\n *=========================================================================*/\nint MapEditClass::New_Scenario(void)\n{\n\tint scen_num;\n\tScenarioPlayerType player;\n\tScenarioDirType dir;\n\tScenarioVarType var;\n\tDisect_Scenario_Name(Scen.ScenarioName, scen_num, player, dir, var);\n\n\tint rc;\n\tHousesType house;\n\n\t/*\n\t**\tForce the house save value to match the player house.\n\t*/\n\tif (PlayerPtr) {\n\t\tswitch (PlayerPtr->Class->House) {\n\t\t\tcase HOUSE_SPAIN:\n\t\t\t\tplayer = SCEN_PLAYER_SPAIN;\n\t\t\t\tbreak;\n\n\t\t\tcase HOUSE_GREECE:\n\t\t\t\tplayer = SCEN_PLAYER_GREECE;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\tcase HOUSE_USSR:\n\t\t\t\tplayer = SCEN_PLAYER_USSR;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tPrompt for scenario info\n\t*/\n\trc = Pick_Scenario(\"New Scenario\", scen_num, player, dir, var);\n\tif (rc != 0) {\n\t\treturn(-1);\n\t}\n\n\tScenarioInit++;\n\n\t/*\n\t**\tBlow away everything\n\t*/\n\tClear_Scenario();\n\n\t/*\n\t**\tSet parameters\n\t*/\n//\tScen.Scenario = scen_num;\n//\tScen.ScenPlayer = player;\n//\tScen.ScenDir = dir;\n//\tScen.ScenVar = var;\n\tScen.Set_Scenario_Name(scen_num, player, dir, var);\n\n\t/*\n\t**\tCreate houses\n\t*/\n\tfor (house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\tnew HouseClass(house);\n\t}\n\n\tswitch (player) {\n\t\tcase SCEN_PLAYER_MPLAYER:\n\t\t\tPlayerPtr = HouseClass::As_Pointer(HOUSE_MULTI1);\n\t\t\tPlayerPtr->IsHuman = true;\n\t\t\tLastHouse = HOUSE_MULTI1;\n\t\t\tbreak;\n\n\t\tcase SCEN_PLAYER_USSR:\n\t\t\tPlayerPtr = HouseClass::As_Pointer(HOUSE_USSR);\n\t\t\tPlayerPtr->IsHuman = true;\n\t\t\tBase.House = HOUSE_SPAIN;\n\t\t\tLastHouse = HOUSE_GOOD;\n\t\t\tbreak;\n\n\t\tcase SCEN_PLAYER_SPAIN:\n\t\t\tPlayerPtr = HouseClass::As_Pointer(HOUSE_SPAIN);\n\t\t\tPlayerPtr->IsHuman = true;\n\t\t\tBase.House = HOUSE_USSR;\n\t\t\tLastHouse = HOUSE_GOOD;\n\t\t\tbreak;\n\n\t\tcase SCEN_PLAYER_GREECE:\n\t\t\tPlayerPtr = HouseClass::As_Pointer(HOUSE_GREECE);\n\t\t\tPlayerPtr->IsHuman = true;\n\t\t\tBase.House = HOUSE_USSR;\n\t\t\tLastHouse = HOUSE_GOOD;\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tInit the entire map\n\t*/\n//\tInit_Clear();\n\tFill_In_Data();\n\n\t/*\n\t**\tPrompt for map size\n\t*/\n\tSize_Map(-1, -1, 30, 30);\n\n\t/*\n\t**\tSet the Home & Reinforcement Cells to the center of the map\n\t*/\n\tScen.Waypoint[WAYPT_REINF] = XY_Cell(MapCellX + MapCellWidth / 2, MapCellY + MapCellHeight / 2);\n\tScen.Waypoint[WAYPT_HOME] = XY_Cell(MapCellX + MapCellWidth / 2, MapCellY + MapCellHeight / 2);\n\t(*this)[TacticalCoord].IsWaypoint = 1;\n\tFlag_Cell(Coord_Cell(TacticalCoord));\n\n\tSet_Tactical_Position(Cell_Coord(Scen.Waypoint[WAYPT_HOME] - (MAP_CELL_W * 4 * RESFACTOR) - (5 * RESFACTOR)));\n\tScenarioInit--;\n\n\treturn(0);\n}\n\n\n/***************************************************************************\n * MapEditClass::Load_Scenario -- loads a scenario INI file                *\n *                                                                         *\n * - Prompts user for scenario data (house, scenario #); sets globals      *\n *     PlayerPtr (for house) & Scenario (for scenario #)                   *\n * - Loads the INI file for that scenario                                  *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0.                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/21/1994 BR : Created.                                              *\n *=========================================================================*/\nint MapEditClass::Load_Scenario(void)\n{\n\tint scen_num;\n\tScenarioPlayerType player;\n\tScenarioDirType dir;\n\tScenarioVarType var;\n\tDisect_Scenario_Name(Scen.ScenarioName, scen_num, player, dir, var);\n\n\tint rc;\n\tNodeNameType * who;\t\t\t\t\t\t// node to add to Players\n\n\t/*\n\t**\tPrompt for scenario info\n\t*/\n\trc = Pick_Scenario(\"Load Scenario\", scen_num, player, dir, var);\n\tif (rc != 0) {\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tSet parameters\n\t*/\n//\tScen.Scenario = scen_num;\n//\tScen.ScenPlayer = player;\n//\tScen.ScenDir = dir;\n//\tScen.ScenVar = var;\n\tScen.Set_Scenario_Name(scen_num, player, dir, var);\n\n\t/*\n\t**\tRead_Scenario_Ini() must be able to set PlayerPtr to the right house:\n\t**\t- Reading the INI will create the house objects\n\t**\t- PlayerPtr must be set before any Techno objects are created\n\t**\t- For GDI or NOD scenarios, PlayerPtr is set by reading the INI;\n\t**\t  but for multiplayer, it's set via the Players vector; so, here we have\n\t**\t  to set various multiplayer variables to fool the Assign_Houses() routine\n\t**\t  into working properly.\n\t*/\n\tif (player == SCEN_PLAYER_MPLAYER) {\n\t\tClear_Vector(&Session.Players);\n\n\t\twho = new NodeNameType;\n\t\tstrcpy(who->Name, Session.Handle);\n\t\twho->Player.House = Session.House;\n\t\twho->Player.Color = Session.ColorIdx;\n\t\tSession.Players.Add (who);\n\n\t\tSession.NumPlayers = 1;\n\t\tLastHouse = HOUSE_MULTI1;\n\t} else {\n#ifdef NEVER\n\tif (ScenPlayer==SCEN_PLAYER_JP) {\n\t\tPlayerPtr = HouseClass::As_Pointer(HOUSE_MULTI4);\n\t\tPlayerPtr->IsHuman = true;\n\t\tBase.House = HOUSE_MULTI4;\n\t} else {\n#endif\n\t\tLastHouse = HOUSE_GOOD;\n\t}\n\n\t/*\n\t**\tBlow away everything\n\t*/\n\tClear_Scenario();\n\n\t/*\n\t**\tRead the INI\n\t*/\n\tif (Read_Scenario_INI(Scen.ScenarioName) == 0) {\n\t\tif(Scen.Scenario < 20 && Scen.ScenarioName[2] == 'G'){\n\t            WWMessageBox().Process(\"Please insert Red Alert CD1\");\n\t\t}else if(Scen.Scenario < 20 && Scen.ScenarioName[2] == 'U')\n            \t    WWMessageBox().Process(\"Please insert Red Alert CD2\");\n\t\telse\n\t\t    WWMessageBox().Process(\"Unable to read scenario!\");\n\t\tHidPage.Clear();\n\t\tFlag_To_Redraw(true);\n\t\tRender();\n\t} else {\n\t\tFill_In_Data();\n\t\tGamePalette.Set();\n//\t\tSet_Palette(GamePalette);\n\t}\n\n\treturn(0);\n}\n\n\n/***************************************************************************\n * MapEditClass::Save_Scenario -- saves current scenario to an INI file    *\n *                                                                         *\n * - Prompts user for scenario data (house, scenario #); sets globals      *\n *     PlayerPtr (for house) & Scenario (for scenario #)                   *\n * - Saves the INI file for this scenario                                  *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, -1 = error/cancel                                          *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/21/1994 BR : Created.                                              *\n *=========================================================================*/\nint MapEditClass::Save_Scenario(void)\n{\n\tint scen_num;\n\tScenarioPlayerType player;\n\tScenarioDirType dir;\n\tScenarioVarType var;\n\n\tDisect_Scenario_Name(Scen.ScenarioName, scen_num, player, dir, var);\n\n\tint rc;\n//\tFILE * fp;\n//\tchar fname[13];\n\n\t/*\n\t**\tPrompt for scenario info\n\t*/\n\trc = Pick_Scenario(\"Save Scenario\", scen_num, player, dir, var);\n\tif (rc != 0) {\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tWarning if scenario already exists\n\t*/\n//\tScen.Set_Scenario_Name(scen_num, player, dir, var);\n//\tfp = fopen(fname, \"rb\");\n//\tif (fp) {\n//\t\tfclose(fp);\n//\t\trc = WWMessageBox().Process(\"File exists. Replace?\", TXT_YES, TXT_NO);\n//\t\tHidPage.Clear();\n//\t\tFlag_To_Redraw(true);\n//\t\tRender();\n//\t\tif (rc==1) {\n//\t\t\treturn(-1);\n//\t\t}\n//\t}\n\n\t/*\n\t**\tSet parameters\n\t*/\n//\tScen.Scenario = scen_num;\n//\tScen.ScenPlayer = player;\n//\tScen.ScenDir = dir;\n//\tScen.ScenVar = var;\n\tScen.Set_Scenario_Name(scen_num, player, dir, var);\n\n\t/*\n\t**\tPlayer may have changed from GDI to NOD, so change playerptr accordingly\n\t*/\n\tswitch (player) {\n\t\tcase SCEN_PLAYER_USSR:\n\t\t\tPlayerPtr = HouseClass::As_Pointer(HOUSE_USSR);\n\t\t\tPlayerPtr->IsHuman = true;\n//\t\t\tBase.House = HOUSE_SPAIN;\n\t\t\tLastHouse = HOUSE_GOOD;\n\t\t\tbreak;\n\n\t\tcase SCEN_PLAYER_SPAIN:\n\t\t\tPlayerPtr = HouseClass::As_Pointer(HOUSE_SPAIN);\n\t\t\tPlayerPtr->IsHuman = true;\n//\t\t\tBase.House = HOUSE_USSR;\n\t\t\tLastHouse = HOUSE_GOOD;\n\t\t\tbreak;\n\n\t\tcase SCEN_PLAYER_GREECE:\n\t\t\tPlayerPtr = HouseClass::As_Pointer(HOUSE_GREECE);\n\t\t\tPlayerPtr->IsHuman = true;\n//\t\t\tBase.House = HOUSE_USSR;\n\t\t\tLastHouse = HOUSE_GOOD;\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tWrite the INI\n\t*/\n\tWrite_Scenario_INI(Scen.ScenarioName);\n\n\treturn(0);\n}\n\n\n/***************************************************************************\n * MapEditClass::Pick_Scenario -- dialog for choosing scenario             *\n *                                                                         *\n * Prompts user for:                                                       *\n *   - House (GDI, NOD)                                                    *\n *   - Scenario #                                                          *\n *                                                                         *\n *           Ŀ                          *\n *                       Caption                                         *\n *                                                                       *\n *                    Scenario ___                                       *\n *                     Version ___                                       *\n *                                                                       *\n *                    [East]  [West]                                     *\n *                                                                       *\n *                    [    GDI     ]                                     *\n *                    [    NOD     ]                                     *\n *                    [Multi-Player]                                     *\n *                                                                       *\n *                    [OK]  [Cancel]                                     *\n *                                                                       *\n *                                     *\n *                                                                         *\n * INPUT:                                                                  *\n *      caption      string to use as a title                              *\n *      scen_nump   output: ptr to scenario #                              *\n *      playerp      output: ptr to player type                            *\n *      dirp         output: ptr to direction                              *\n *      varp         output: ptr to variation                              *\n *      multi         1 = allow to change single/multiplayer; 0 = not      *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, -1 = cancel                                                *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/21/1994 BR : Created.                                              *\n *   09/04/1996 JLB : Simplified                                           *\n *=========================================================================*/\nint MapEditClass::Pick_Scenario(char const * caption, int & scen_nump, ScenarioPlayerType & playerp, ScenarioDirType & dirp, ScenarioVarType & varp)\n{\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tenum {\n\t\tD_DIALOG_W = 200,\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\t\tD_DIALOG_H = 164,\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\t\tD_DIALOG_X = ((320 - D_DIALOG_W) / 2),\t\t\t\t// centered x-coord\n\t\tD_DIALOG_Y = ((200 - D_DIALOG_H) / 2),\t\t\t\t// centered y-coord\n\t\tD_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),\t\t// coord of x-center\n\n\t\tD_TXT8_H = 11,\t\t\t\t\t\t\t\t\t\t\t\t// ht of 8-pt text\n\t\tD_MARGIN = 7,\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\t\tD_SCEN_W = 45,\t\t\t\t\t\t\t\t\t\t\t\t// Scenario # width\n\t\tD_SCEN_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// Scenario # height\n\t\tD_SCEN_X = D_DIALOG_CX + 5,\t\t\t\t\t\t\t// Scenario # x\n\t\tD_SCEN_Y = D_DIALOG_Y + D_MARGIN + D_TXT8_H + D_MARGIN,\t// Scenario # y\n\n\t\tD_VARA_W = 13,\t\t\t\t\t\t\t\t\t\t\t\t// Version A width\n\t\tD_VARA_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// Version A height\n\t\tD_VARA_X = D_DIALOG_CX - (D_VARA_W * 5) / 2,\t\t// Version A x\n\t\tD_VARA_Y = D_SCEN_Y + D_SCEN_H + D_MARGIN,\t\t// Version A y\n\n\t\tD_VARB_W = 13,\t\t\t\t\t\t\t\t\t\t\t\t// Version B width\n\t\tD_VARB_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// Version B height\n\t\tD_VARB_X = D_VARA_X + D_VARA_W,\t\t\t\t\t\t// Version B x\n\t\tD_VARB_Y = D_SCEN_Y + D_SCEN_H + D_MARGIN,\t\t// Version B y\n\n\t\tD_VARC_W = 13,\t\t\t\t\t\t\t\t\t\t\t\t// Version C width\n\t\tD_VARC_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// Version C height\n\t\tD_VARC_X = D_VARB_X + D_VARB_W,\t\t\t\t\t\t// Version C x\n\t\tD_VARC_Y = D_SCEN_Y + D_SCEN_H + D_MARGIN,\t\t// Version C y\n\n\t\tD_VARD_W = 13,\t\t\t\t\t\t\t\t\t\t\t\t// Version D width\n\t\tD_VARD_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// Version D height\n\t\tD_VARD_X = D_VARC_X + D_VARC_W,\t\t\t\t\t\t// Version D x\n\t\tD_VARD_Y = D_SCEN_Y + D_SCEN_H + D_MARGIN,\t\t// Version D y\n\n\t\tD_VARLOSE_W = 13,\t\t\t\t\t\t\t\t\t\t\t// Version Lose width\n\t\tD_VARLOSE_H = 9,\t\t\t\t\t\t\t\t\t\t\t// Version Lose height\n\t\tD_VARLOSE_X = D_VARD_X + D_VARD_W,\t\t\t\t\t// Version Lose x\n\t\tD_VARLOSE_Y = D_SCEN_Y + D_SCEN_H + D_MARGIN,\t// Version Lose y\n\n\t\tD_EAST_W = 50,\t\t\t\t\t\t\t\t\t\t\t\t// EAST width\n\t\tD_EAST_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// EAST height\n\t\tD_EAST_X = D_DIALOG_CX - D_EAST_W - 5,\t\t\t\t// EAST x\n\t\tD_EAST_Y = D_VARLOSE_Y + D_VARLOSE_H + D_MARGIN,// EAST y\n\n\t\tD_WEST_W = 50,\t\t\t\t\t\t\t\t\t\t\t\t// WEST width\n\t\tD_WEST_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// WEST height\n\t\tD_WEST_X = D_DIALOG_CX + 5,\t\t\t\t\t\t\t// WEST x\n\t\tD_WEST_Y = D_VARLOSE_Y + D_VARLOSE_H + D_MARGIN,// EAST y\n\n\t\tD_GDI_W = 90,\t\t\t\t\t\t\t\t\t\t\t\t// GDI width\n\t\tD_GDI_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// GDI height\n\t\tD_GDI_X = D_DIALOG_CX - (D_GDI_W / 2),\t\t\t\t// GDI x\n\t\tD_GDI_Y = D_EAST_Y + D_EAST_H + D_MARGIN,\t\t\t// GDI y\n\n\t\tD_NOD_W = 90,\t\t\t\t\t\t\t\t\t\t\t\t// NOD width\n\t\tD_NOD_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// NOD height\n\t\tD_NOD_X = D_DIALOG_CX - (D_NOD_W / 2),\t\t\t\t// NOD x\n\t\tD_NOD_Y = D_GDI_Y + D_GDI_H,\t\t\t\t\t\t\t// NOD y\n\n\t\tD_NEU_W = 90,\t\t\t\t\t\t\t\t\t\t\t\t// Neutral width\n\t\tD_NEU_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// Neutral height\n\t\tD_NEU_X = D_DIALOG_CX - (D_NOD_W / 2),\t\t\t\t// Neutral x\n\t\tD_NEU_Y = D_NOD_Y + D_NOD_H,\t\t\t\t\t\t\t// Neutral y\n\n\t\tD_MPLAYER_W = 90,\t\t\t\t\t\t\t\t\t\t\t// Multi-Player width\n\t\tD_MPLAYER_H = 9,\t\t\t\t\t\t\t\t\t\t\t// Multi-Player height\n\t\tD_MPLAYER_X = D_DIALOG_CX - (D_MPLAYER_W / 2),\t// Multi-Player x\n\t\tD_MPLAYER_Y = D_NEU_Y + D_NEU_H,\t\t\t\t\t\t// Multi-Player y\n\n\t\tD_OK_W = 45,\t\t\t\t\t\t\t\t\t\t\t\t// OK width\n\t\tD_OK_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t\t// OK height\n\t\tD_OK_X = D_DIALOG_CX - D_OK_W - 5,\t\t\t\t\t// OK x\n\t\tD_OK_Y = D_DIALOG_Y + D_DIALOG_H - D_OK_H - (D_MARGIN+15),\t// OK y\n\n\t\tD_CANCEL_W = 45,\t\t\t\t\t\t\t\t\t\t\t// Cancel width\n\t\tD_CANCEL_H = 9,\t\t\t\t\t\t\t\t\t\t\t// Cancel height\n\t\tD_CANCEL_X = D_DIALOG_CX + 5,\t\t\t\t\t\t\t// Cancel x\n\t\tD_CANCEL_Y = D_DIALOG_Y + D_DIALOG_H - D_CANCEL_H - (D_MARGIN+15), // Cancel y\n\n\t};\n\n\t/*\n\t**\tButton enumerations\n\t*/\n\tenum {\n\t\tBUTTON_GDI=100,\n\t\tBUTTON_NOD,\n\t\tBUTTON_NEUTRAL,\n\t\tBUTTON_MPLAYER,\n\t\tBUTTON_EAST,\n\t\tBUTTON_WEST,\n\t\tBUTTON_OK,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_SCENARIO,\n\t\tBUTTON_VAR_A,\n\t\tBUTTON_VAR_B,\n\t\tBUTTON_VAR_C,\n\t\tBUTTON_VAR_D,\n\t};\n\n\t/*\n\t**\tDialog variables\n\t*/\n\tbool cancel = false;\t\t\t\t\t\t\t// true = user cancels\n\n\t/*\n\t**\tOther Variables\n\t*/\n\tchar scen_buf[10]={0};\t\t\t\t\t\t// buffer for editing scenario #\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass * commands = NULL;\t\t// the button list\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tEditClass editbtn (BUTTON_SCENARIO, scen_buf, 5, TPF_EFNT|TPF_NOSHADOW, D_SCEN_X, D_SCEN_Y, D_SCEN_W, D_SCEN_H, EditClass::ALPHANUMERIC);\n#else\n\tEditClass editbtn (BUTTON_SCENARIO, scen_buf, 5, TPF_EFNT|TPF_NOSHADOW, D_SCEN_X, D_SCEN_Y, D_SCEN_W, D_SCEN_H, EditClass::NUMERIC);\n#endif\n\n\tTextButtonClass varabtn(BUTTON_VAR_A, \"A\", TPF_EBUTTON, D_VARA_X, D_VARA_Y, D_VARA_W, D_VARA_H);\n\tTextButtonClass varbbtn(BUTTON_VAR_B, \"B\", TPF_EBUTTON, D_VARB_X, D_VARB_Y, D_VARB_W, D_VARB_H);\n\tTextButtonClass varcbtn(BUTTON_VAR_C, \"C\", TPF_EBUTTON, D_VARC_X, D_VARC_Y, D_VARC_W, D_VARC_H);\n\tTextButtonClass vardbtn(BUTTON_VAR_D, \"D\", TPF_EBUTTON, D_VARD_X, D_VARD_Y, D_VARD_W, D_VARD_H);\n\tTextButtonClass gdibtn(BUTTON_GDI, \"North (Spain)\", TPF_EBUTTON, D_GDI_X, D_GDI_Y, D_GDI_W, D_GDI_H);\n\tTextButtonClass nodbtn(BUTTON_NOD, \"South (Greece)\", TPF_EBUTTON, D_NOD_X, D_NOD_Y, D_NOD_W, D_NOD_H);\n\tTextButtonClass neubtn(BUTTON_NEUTRAL, HouseTypeClass::As_Reference(HOUSE_USSR).IniName, TPF_EBUTTON, D_NEU_X, D_NEU_Y, D_NEU_W, D_NEU_H);\n\tTextButtonClass playermbtn(BUTTON_MPLAYER, \"Multiplayer\", TPF_EBUTTON, D_MPLAYER_X, D_MPLAYER_Y, D_MPLAYER_W, D_MPLAYER_H);\n\tTextButtonClass eastbtn(BUTTON_EAST, \"East\", TPF_EBUTTON, D_EAST_X, D_EAST_Y, D_EAST_W, D_EAST_H);\n\tTextButtonClass westbtn(BUTTON_WEST, \"West\", TPF_EBUTTON, D_WEST_X, D_WEST_Y, D_WEST_W, D_WEST_H);\n\tTextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_EBUTTON, D_OK_X, D_OK_Y, D_OK_W, D_OK_H);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_EBUTTON, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W, D_CANCEL_H);\n\n\t/*\n\t**\tInitialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (scen_nump < 100) {\n\t\tsprintf(scen_buf, \"%d\", scen_nump);\t\t// init edit buffer\n\t} else {\n\t\tchar first = scen_nump / 36;\n\t\tchar second = scen_nump % 36;\n\t\tscen_buf[0] = first + 'A';\n//Mono_Printf(\"picking map, scen# = %d, first = %c, second = %d (numeric)\\n\",scen_nump, scen_buf[0],second);Keyboard->Get();Keyboard->Get();\n\t\tif (second < 10) {\n\t\t\tscen_buf[1] = second + '0';\n\t\t} else {\n\t\t\tscen_buf[1] = (second-10) + 'A';\n\t\t}\n\t\tscen_buf[2] = 0;\n\t}\n#else\n\tsprintf(scen_buf, \"%d\", scen_nump);\t\t// init edit buffer\n#endif\n\teditbtn.Set_Text(scen_buf, 5);\n\n\tvarabtn.Turn_Off();\n\tvarbbtn.Turn_Off();\n\tvarcbtn.Turn_Off();\n\tvardbtn.Turn_Off();\n\tswitch (varp) {\n\t\tcase SCEN_VAR_A:\n\t\t\tvarabtn.Turn_On();\n\t\t\tbreak;\n\n\t\tcase SCEN_VAR_B:\n\t\t\tvarbbtn.Turn_On();\n\t\t\tbreak;\n\n\t\tcase SCEN_VAR_C:\n\t\t\tvarcbtn.Turn_On();\n\t\t\tbreak;\n\n\t\tcase SCEN_VAR_D:\n\t\t\tvardbtn.Turn_On();\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tCreate the button list\n\t*/\n\tcommands = &editbtn;\n\tvarabtn.Add_Tail(*commands);\n\tvarbbtn.Add_Tail(*commands);\n\tvarcbtn.Add_Tail(*commands);\n\tvardbtn.Add_Tail(*commands);\n\tgdibtn.Add_Tail(*commands);\n\tnodbtn.Add_Tail(*commands);\n\tneubtn.Add_Tail(*commands);\n\tplayermbtn.Add_Tail(*commands);\n\teastbtn.Add_Tail(*commands);\n\twestbtn.Add_Tail(*commands);\n\tokbtn.Add_Tail(*commands);\n\tcancelbtn.Add_Tail(*commands);\n\n\t/*\n\t**\tInit the button states\n\t*/\n\tgdibtn.Turn_Off();\n\tnodbtn.Turn_Off();\n\tneubtn.Turn_Off();\n\tplayermbtn.Turn_Off();\n\tif (playerp == SCEN_PLAYER_MPLAYER) {\n\t\tplayermbtn.Turn_On();\n\t} else {\n\t\tif (PlayerPtr) {\n\t\t\tswitch (PlayerPtr->Class->House) {\n\t\t\t\tcase HOUSE_SPAIN:\n\t\t\t\t\tgdibtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase HOUSE_GREECE:\n\t\t\t\t\tnodbtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase HOUSE_USSR:\n\t\t\t\t\tneubtn.Turn_On();\n\t\t\t\t\tbreak;\n\t\t\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t} else {\n\t\t\tswitch (Scen.ScenarioName[2]) {\n\t\t\t\tcase 'G':\n\t\t\t\t\tgdibtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'U':\n\t\t\t\t\tnodbtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'M':\n\t\t\t\t\tplayermbtn.Turn_On();\n\t\t\t\t\tbreak;\n\t\t\t}\n#endif\n\t\t}\n\t}\n\n\teastbtn.Turn_Off();\n\twestbtn.Turn_Off();\n\tif (dirp == SCEN_DIR_EAST) {\n\t\teastbtn.Turn_On();\n\t} else {\n\t\twestbtn.Turn_On();\n\t}\n\n\t/*\n\t**\tMain Processing Loop\n\t*/\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if needed\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\t\t\tDraw_Caption(caption, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\t\t\tFancy_Text_Print(\"Scenario\", D_DIALOG_CX - 5, D_SCEN_Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_RIGHT | TPF_EFNT | TPF_NOSHADOW);\n\t\t\tcommands->Draw_All();\n\t\t\tShow_Mouse();\n\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t**\tProcess input\n\t\t*/\n\t\tswitch (input) {\n\n\t\t\t/*\n\t\t\t**\tHandle a click on one of the scenario variation group buttons.\n\t\t\t*/\n\t\t\tcase (BUTTON_VAR_A | KN_BUTTON):\n\t\t\tcase (BUTTON_VAR_B | KN_BUTTON):\n\t\t\tcase (BUTTON_VAR_C | KN_BUTTON):\n\t\t\tcase (BUTTON_VAR_D | KN_BUTTON):\n\t\t\t\tvarabtn.Turn_Off();\n\t\t\t\tvarbbtn.Turn_Off();\n\t\t\t\tvarcbtn.Turn_Off();\n\t\t\t\tvardbtn.Turn_Off();\n\t\t\t\tswitch (input) {\n\t\t\t\t\tcase (BUTTON_VAR_A | KN_BUTTON):\n\t\t\t\t\t\tvarp = SCEN_VAR_A;\n\t\t\t\t\t\tvarabtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_VAR_B | KN_BUTTON):\n\t\t\t\t\t\tvarp = SCEN_VAR_B;\n\t\t\t\t\t\tvarbbtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_VAR_C | KN_BUTTON):\n\t\t\t\t\t\tvarp = SCEN_VAR_C;\n\t\t\t\t\t\tvarcbtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_VAR_D | KN_BUTTON):\n\t\t\t\t\t\tvarp = SCEN_VAR_D;\n\t\t\t\t\t\tvardbtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tHandle a click on the east/west variation group.\n\t\t\t*/\n\t\t\tcase (BUTTON_EAST | KN_BUTTON):\n\t\t\tcase (BUTTON_WEST | KN_BUTTON):\n\t\t\t\twestbtn.Turn_Off();\n\t\t\t\teastbtn.Turn_Off();\n\t\t\t\tswitch (input) {\n\t\t\t\t\tcase (BUTTON_EAST | KN_BUTTON):\n\t\t\t\t\t\tdirp = SCEN_DIR_EAST;\n\t\t\t\t\t\teastbtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_WEST | KN_BUTTON):\n\t\t\t\t\t\tdirp = SCEN_DIR_WEST;\n\t\t\t\t\t\twestbtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\n\t\t\t/*\n\t\t\t**\tHandle a click on one of the player category\n\t\t\t**\tgroup buttons.\n\t\t\t*/\n\t\t\tcase (BUTTON_GDI | KN_BUTTON):\n\t\t\tcase (BUTTON_NOD | KN_BUTTON):\n\t\t\tcase (BUTTON_NEUTRAL | KN_BUTTON):\n\t\t\tcase (BUTTON_MPLAYER | KN_BUTTON):\n\t\t\t\tgdibtn.Turn_Off();\n\t\t\t\tnodbtn.Turn_Off();\n\t\t\t\tneubtn.Turn_Off();\n\t\t\t\tplayermbtn.Turn_Off();\n\t\t\t\tswitch (input) {\n\t\t\t\t\tcase (BUTTON_GDI | KN_BUTTON):\n\t\t\t\t\t\tplayerp = SCEN_PLAYER_SPAIN;\n\t\t\t\t\t\tgdibtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_NOD | KN_BUTTON):\n\t\t\t\t\t\tplayerp = SCEN_PLAYER_GREECE;\n\t\t\t\t\t\tnodbtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_NEUTRAL | KN_BUTTON):\n\t\t\t\t\t\tplayerp = SCEN_PLAYER_USSR;\n\t\t\t\t\t\tneubtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_MPLAYER | KN_BUTTON):\n\t\t\t\t\t\tplayerp = SCEN_PLAYER_MPLAYER;\n\t\t\t\t\t\tplayermbtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tcancel = false;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tcancel = true;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_SCENARIO | KN_BUTTON):\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tRedraw the display\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n\n\t/*\n\t**\tIf cancel, just return\n\t*/\n\tif (cancel) {\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tSave selections & return\n\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (scen_buf[0] <= '9' && scen_buf[1] <= '9') {\n\t\tscen_nump = atoi(scen_buf);\n\t} else {\n\t\tchar first = scen_buf[0];\n\t\tchar second = scen_buf[1];\n\t\tif (first <= '9') {\n\t\t\tfirst -= '0';\n\t\t} else {\n\t\t\tif (first >= 'a' && first <= 'z') {\n\t\t\t\tfirst -= 'a';\n\t\t\t} else {\n\t\t\t\tfirst -= 'A';\n\t\t\t}\n\t\t}\n\t\tif (second <= '9') {\n\t\t\tsecond -= '0';\n\t\t} else {\n\t\t\tif (second >= 'a' && second <= 'z') {\n\t\t\t\tsecond = (second - 'a') + 10;\n\t\t\t} else {\n\t\t\t\tsecond = (second - 'A') + 10;\n\t\t\t}\n\t\t}\n\t\tscen_nump = (first * 36) + second;\n//Mono_Printf(\"Converted to: %d, %d = %d\\n\",first, second, scen_nump);Keyboard->Get();Keyboard->Get();\n\t}\n#else\n\tscen_nump = atoi(scen_buf);\n#endif\n\n\treturn(0);\n}\n\n\n/***************************************************************************\n * MapEditClass::Size_Map -- lets user set size & location of map          *\n *                                                                         *\n * Lets the user select a side of the map and expand/shrink it to the      *\n * desired size, or move the whole map around the available map area.      *\n *                                                                         *\n * The entire available map area is displayed, but the map is limited such *\n * that there's always one blank cell around the map; this lets objects    *\n * properly exit the screen, since they have a blank undisplayed cell to   *\n * exit onto.                                                              *\n *                                                                         *\n *   Ŀ               *\n *                                                                       *\n *     Ŀ   Clear Terrain                           *\n *                             Water                                   *\n *                             Tiberium                                *\n *                             Rock/Wall/Road                          *\n *          (Map Area)         GDI Unit                                *\n *                             NOD Unit                                *\n *                             Neutral Unit                            *\n *                             Terrain Object                          *\n *                             Starting Cell                           *\n *                                                *\n *                                                                       *\n *         X            Y            Width      Height                   *\n *         ##           ##            ##          ##                     *\n *                                                                       *\n *                                                                       *\n *                  [OK]            [Cancel]                             *\n *                                                                       *\n *                  *\n *                                                                         *\n * INPUT:                                                                  *\n *      x,y,w,h:      initial size parameters (-1 = center the thing)      *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, -1 = cancel                                                *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/21/1994 BR : Created.                                              *\n *=========================================================================*/\nint MapEditClass::Size_Map(int x, int y, int w, int h)\n{\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tenum {\n\t\tD_DIALOG_W = 350,\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\t\tD_DIALOG_H = 225,\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\t\tD_DIALOG_X = 0,\t\t\t\t// centered x-coord\n\t\tD_DIALOG_Y = 0,\t\t\t\t// centered y-coord\n//\t\tD_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),\t\t// coord of x-center\n\n\t\tD_TXT8_H = 11,\t\t\t\t\t\t\t\t\t\t\t\t// ht of 8-pt text\n\t\tD_MARGIN = 7,\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\t\tD_BORD_X1 = D_DIALOG_X + 45,\n//\t\tD_BORD_X1 = D_DIALOG_X + (D_DIALOG_W / 2 - MAP_CELL_W) / 2,\n\t\tD_BORD_Y1 = D_DIALOG_Y + 25,\n\t\tD_BORD_X2 = D_BORD_X1 + MAP_CELL_W + 1,\n\t\tD_BORD_Y2 = D_BORD_Y1 + MAP_CELL_H + 1,\n\n\t\tD_OK_W = 45,\t\t\t\t\t\t\t\t\t\t\t\t// OK width\n\t\tD_OK_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t\t// OK height\n\t\tD_OK_X = D_DIALOG_X + 45,\t\t\t\t\t// OK x\n\t\tD_OK_Y = D_DIALOG_Y + D_DIALOG_H - D_OK_H - (D_MARGIN + 10),\t// OK y\n\n\t\tD_CANCEL_W = 45,\t\t\t\t\t\t\t\t\t\t\t// Cancel width\n\t\tD_CANCEL_H = 9,\t\t\t\t\t\t\t\t\t\t\t// Cancel height\n\t\tD_CANCEL_X = D_DIALOG_X + D_DIALOG_W - (35 + D_CANCEL_W),\t// Cancel x\n\t\tD_CANCEL_Y = D_DIALOG_Y + D_DIALOG_H - D_CANCEL_H - (D_MARGIN + 10), // Cancel y\n\t};\n\n\t/*\n\t**\tButton enumerations:\n\t*/\n\tenum {\n\t\tBUTTON_OK=100,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t/*\n\t**\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_MAP,\t\t\t\t// includes map interior & coord values\n\t\tREDRAW_BACKGROUND,\t// includes box, map board, key, coord labels, btns\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*\n\t**\tDialog variables:\n\t*/\n\tRedrawType display;\t\t\t\t\t\t\t// requested redraw level\n\tbool cancel = false;\t\t\t\t\t\t\t// true = user cancels\n\tKeyNumType input;\t\t\t\t\t\t\t\t// user input\n\tint grabbed = 0;\t\t\t\t\t\t\t\t// 1=TLeft,2=TRight,3=BRight,4=BLeft\n\tint map_x1;\t\t\t\t\t\t\t\t\t\t// map coords x1, pixel coords\n\tint map_x2;\t\t\t\t\t\t\t\t\t\t// map coords x2, pixel coords\n\tint map_y1;\t\t\t\t\t\t\t\t\t\t// map coords y1, pixel coords\n\tint map_y2;\t\t\t\t\t\t\t\t\t\t// map coords y2, pixel coords\n\tint delta1, delta2;\t\t\t\t\t\t\t// mouse-click proximity\n\tint mx,my;\t\t\t\t\t\t\t\t\t\t// last-saved mouse coords\n//\tchar txt[40];\n\tint txt_x,txt_y;\t\t\t\t\t\t\t\t// for displaying text\n//\tunsigned index;\t\t\t\t\t\t\t\t// for drawing map symbology\n\tCELL cell;\t\t\t\t\t\t\t\t\t\t// for drawing map symbology\n\tint color;\t\t\t\t\t\t\t\t\t\t// for drawing map symbology\n\tObjectClass * occupier;\t\t\t\t\t\t// cell's occupier\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass * commands = NULL;\n\n\tTextButtonClass okbtn (BUTTON_OK, TXT_OK, TPF_EBUTTON, D_OK_X, D_OK_Y, D_OK_W, D_OK_H);\n\n\tTextButtonClass cancelbtn (BUTTON_CANCEL, TXT_CANCEL, TPF_EBUTTON, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W, D_CANCEL_H);\n\n\t/*\n\t**\tInitialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tSet up the actual map area relative to the map's border coords\n\t*/\n\tif (x==-1) {\n\t\tmap_x1 = D_BORD_X1 + (MAP_CELL_W - w) / 2 + 1;\n\t} else {\n\t\tmap_x1 = D_BORD_X1 + x + 1;\n\t}\n\n\tif (y==-1) {\n\t\tmap_y1 = D_BORD_Y1 + (MAP_CELL_H - h) / 2 + 1;\n\t} else {\n\t\tmap_y1 = D_BORD_Y1 + y + 1;\n\t}\n\n\tmap_x2 = map_x1 + w - 1;\n\tmap_y2 = map_y1 + h - 1;\n\n\t/*\n\t**\tBuild the button list\n\t*/\n\tcommands = &okbtn;\n\tcancelbtn.Add_Tail(*commands);\n\n\t/*\n\t**\tMain processing loop\n\t*/\n\tdisplay = REDRAW_ALL;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if needed\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t**\tRedraw the background, map border, key, and coord labels\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\n\t\t\t\t/*\n\t\t\t\t**\tBackground\n\t\t\t\t*/\n\t\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\t\t\t\tDraw_Caption(TXT_SIZE_MAP, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\n\t\t\t\t/*\n\t\t\t\t**\tDraw the map border\n\t\t\t\t*/\n\t\t\t\tif (LogicPage->Lock()) {\n\t\t\t\t\tLogicPage->Draw_Rect(D_BORD_X1, D_BORD_Y1, D_BORD_X2, D_BORD_Y2, scheme->Shadow);\n//\t\t\t\t\tfor (index = D_BORD_X1; index < D_BORD_X2;\n//\t\t\t\t\t\tindex += (320/ICON_PIXEL_W)) {\n//\t\t\t\t\t\tLogicPage->Put_Pixel(index, D_BORD_Y1-1, scheme->Shadow);\n//\t\t\t\t\t\tLogicPage->Put_Pixel(index, D_BORD_Y2+1, scheme->Shadow);\n//\t\t\t\t\t}\n//\t\t\t\t\tfor (index = D_BORD_Y1; index < D_BORD_Y2-8;\n//\t\t\t\t\t\tindex += (200/ICON_PIXEL_H)) {\n//\t\t\t\t\t\tLogicPage->Put_Pixel(D_BORD_X1-1, index, scheme->Shadow);\n//\t\t\t\t\t\tLogicPage->Put_Pixel(D_BORD_X2+1, index, scheme->Shadow);\n//\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDraw the map \"key\"\n\t\t\t\t\t*/\n\t\t\t\t\ttxt_x = D_BORD_X2 + 15;\n\t\t\t\t\ttxt_y = D_BORD_Y1;\n\t\t\t\t\tPlain_Text_Print(\"Clear Terrain\", txt_x, txt_y, GroundColor[LAND_CLEAR], TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"Water\", txt_x, txt_y, GroundColor[LAND_WATER], TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"Tiberium\", txt_x, txt_y, GroundColor[LAND_TIBERIUM], TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"Rock\", txt_x, txt_y, GroundColor[LAND_ROCK], TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"Wall\", txt_x, txt_y, GroundColor[LAND_WALL], TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"Beach\", txt_x, txt_y, GroundColor[LAND_BEACH], TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"Rough\", txt_x, txt_y, GroundColor[LAND_ROUGH], TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"River\", txt_x, txt_y, GroundColor[LAND_RIVER], TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n//\t\t\t\t\ttxt_y += 8;\n//\t\t\t\t\tPlain_Text_Print(\"GDI Unit\", txt_x, txt_y, YELLOW, TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n//\t\t\t\t\ttxt_y += 8;\n//\t\t\t\t\tPlain_Text_Print(\"Nod Unit\", txt_x, txt_y, RED, TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n//\t\t\t\t\ttxt_y += 8;\n//\t\t\t\t\tPlain_Text_Print(\"Neutral Unit\", txt_x, txt_y, PURPLE, TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"Terrain Object\", txt_x, txt_y, DKGREEN, TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"Starting Cell\", txt_x, txt_y, WHITE, TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDraw the coordinate labels\n\t\t\t\t\t*/\n\t\t\t\t\ttxt_x = D_DIALOG_X + D_DIALOG_W / 8;\n\t\t\t\t\ttxt_y = D_DIALOG_Y + D_DIALOG_H - D_OK_H - 43;\n\t\t\t\t\tFancy_Text_Print(\"  X\", txt_x, txt_y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW);\n\n\t\t\t\t\ttxt_x += (D_DIALOG_W - 20) / 4;\n\t\t\t\t\tFancy_Text_Print(\"  Y\", txt_x, txt_y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW);\n\n\t\t\t\t\ttxt_x += (D_DIALOG_W - 20) / 4;\n\t\t\t\t\tFancy_Text_Print(\" Width\", txt_x, txt_y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW);\n\n\t\t\t\t\ttxt_x += (D_DIALOG_W - 20) / 4;\n\t\t\t\t\tFancy_Text_Print(\" Height\", txt_x, txt_y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW);\n\n\t\t\t\t\tLogicPage->Unlock();\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tRedraw the buttons\n\t\t\t\t*/\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRedraw the map symbology & location\n\t\t\t*/\n\t\t\tif (display >= REDRAW_MAP) {\n\n\t\t\t\tif (LogicPage->Lock()) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tErase the map interior\n\t\t\t\t\t*/\n\t\t\t\t\tLogicPage->Fill_Rect(D_BORD_X1 + 1, D_BORD_Y1 + 1, D_BORD_X2 - 1, D_BORD_Y2 - 1, BLACK);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDraw Land map symbols (use color according to Ground[] array).\n\t\t\t\t\t*/\n\t\t\t\t\tfor (cell=0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\t\t\toccupier = (*this)[cell].Cell_Occupier();\n\t\t\t\t\t\tif (occupier == NULL) {\n\t\t\t\t\t\t\tcolor = GroundColor[(*this)[cell].Land_Type()];\n\t\t\t\t\t\t\tLogicPage->Put_Pixel(D_BORD_X1 + Cell_X(cell) + 1, D_BORD_Y1 + Cell_Y(cell) + 1, color);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDraw the actual map location\n\t\t\t\t\t*/\n\t\t\t\t\tLogicPage->Draw_Rect(map_x1, map_y1, map_x2, map_y2, WHITE);\n\t\t\t\t\tswitch (grabbed) {\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tLogicPage->Draw_Line(map_x1, map_y1, map_x1 + 5, map_y1, BLUE);\n\t\t\t\t\t\t\tLogicPage->Draw_Line(map_x1, map_y1, map_x1, map_y1 + 5, BLUE);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tLogicPage->Draw_Line(map_x2, map_y1, map_x2 - 5, map_y1, BLUE);\n\t\t\t\t\t\t\tLogicPage->Draw_Line(map_x2, map_y1, map_x2, map_y1 + 5, BLUE);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tLogicPage->Draw_Line(map_x2, map_y2, map_x2 - 5, map_y2, BLUE);\n\t\t\t\t\t\t\tLogicPage->Draw_Line(map_x2, map_y2, map_x2, map_y2 - 5, BLUE);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\tLogicPage->Draw_Line(map_x1, map_y2, map_x1 + 5, map_y2, BLUE);\n\t\t\t\t\t\t\tLogicPage->Draw_Line(map_x1, map_y2, map_x1, map_y2 - 5, BLUE);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 5:\n\t\t\t\t\t\t\tLogicPage->Draw_Rect(map_x1, map_y1, map_x2, map_y2, BLUE);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDraw Unit map symbols (Use the radar map color according to\n\t\t\t\t\t**\tthat specified in the house type class object.\n\t\t\t\t\t**\tDKGREEN = terrain object\n\t\t\t\t\t*/\n\t\t\t\t\tfor (cell=0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\t\t\toccupier = (*this)[cell].Cell_Occupier();\n\t\t\t\t\t\tif (occupier) {\n\t\t\t\t\t\t\tcolor = DKGREEN;\n\t\t\t\t\t\t\tif (occupier && occupier->Owner() != HOUSE_NONE) {\n\t\t\t\t\t\t\t\tcolor = ColorRemaps[HouseClass::As_Pointer(occupier->Owner())->RemapColor].Color;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tLogicPage->Put_Pixel(D_BORD_X1 + Cell_X(cell) + 1, D_BORD_Y1 + Cell_Y(cell) + 1, color);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDraw Home location\n\t\t\t\t\t*/\n\t\t\t\t\tLogicPage->Put_Pixel(D_BORD_X1 + Cell_X(Scen.Waypoint[WAYPT_HOME]) + 1, D_BORD_Y1 + Cell_Y(Scen.Waypoint[WAYPT_HOME]) + 1, WHITE);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tErase old coordinates\n\t\t\t\t\t*/\n//\t\t\t\t\tLogicPage->Fill_Rect( D_DIALOG_X + 7,\n//\t\t\t\t\t\tD_DIALOG_Y + D_DIALOG_H - D_OK_H - 22,\n//\t\t\t\t\t\tD_DIALOG_X + D_DIALOG_W - 7,\n//\t\t\t\t\t\tD_DIALOG_Y + D_DIALOG_H - D_OK_H - 22 + 10, BLACK);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDraw the coordinates\n\t\t\t\t\t*/\n\t\t\t\t\ttxt_x = D_DIALOG_X + D_DIALOG_W / 8;\n\t\t\t\t\ttxt_y = D_DIALOG_Y + D_DIALOG_H - D_OK_H - 32;\n\t\t\t\t\tFancy_Text_Print(\"%5d\", txt_x, txt_y, GadgetClass::Get_Color_Scheme(), BLACK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW, map_x1 - D_BORD_X1 - 1);\n\n\t\t\t\t\ttxt_x += (D_DIALOG_W - 20) / 4;\n\t\t\t\t\tFancy_Text_Print(\"%5d\", txt_x, txt_y, GadgetClass::Get_Color_Scheme(), BLACK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW, map_y1 - D_BORD_Y1 - 1);\n\n\t\t\t\t\ttxt_x += (D_DIALOG_W - 20) / 4;\n\t\t\t\t\tFancy_Text_Print(\"%5d\", txt_x, txt_y, GadgetClass::Get_Color_Scheme(), BLACK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW, map_x2 - map_x1 + 1);\n\n\t\t\t\t\ttxt_x += (D_DIALOG_W - 20) / 4;\n\t\t\t\t\tFancy_Text_Print(\"%5d\", txt_x, txt_y, GadgetClass::Get_Color_Scheme(), BLACK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW, map_y2 - map_y1 + 1);\n\n\t\t\t\t\tLogicPage->Unlock();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t**\tProcess user input\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\t/*\n\t\t**\tNormal button processing: This is done when the mouse button is NOT\n\t\t**\tbeing held down ('grabbed' is 0).\n\t\t*/\n\t\tif (grabbed == 0) {\n\t\t\tswitch (input) {\n\t\t\t\tcase (KN_RETURN):\n\t\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\t\tcancel = false;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_ESC):\n\t\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\t\tcancel = true;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase KN_LMOUSE:\n\t\t\t\t\t/*\n\t\t\t\t\t**\tGrab top left\n\t\t\t\t\t*/\n\t\t\t\t\tdelta1 =  abs(Keyboard->MouseQX - map_x1);\n\t\t\t\t\tdelta2 =  abs(Keyboard->MouseQY - map_y1);\n\t\t\t\t\tif (delta1 < 3 && delta2 < 3) {\n\t\t\t\t\t\tgrabbed = 1;\n\t\t\t\t\t\tmx = Keyboard->MouseQX;\n\t\t\t\t\t\tmy = Keyboard->MouseQY;\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tGrab top right\n\t\t\t\t\t*/\n\t\t\t\t\tdelta1 =  abs(Keyboard->MouseQX - map_x2);\n\t\t\t\t\tdelta2 =  abs(Keyboard->MouseQY - map_y1);\n\t\t\t\t\tif (delta1 < 3 && delta2 < 3) {\n\t\t\t\t\t\tgrabbed = 2;\n\t\t\t\t\t\tmx = Keyboard->MouseQX;\n\t\t\t\t\t\tmy = Keyboard->MouseQY;\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tGrab bottom right\n\t\t\t\t\t*/\n\t\t\t\t\tdelta1 =  abs(Keyboard->MouseQX - map_x2);\n\t\t\t\t\tdelta2 =  abs(Keyboard->MouseQY - map_y2);\n\t\t\t\t\tif (delta1 < 3 && delta2 < 3) {\n\t\t\t\t\t\tgrabbed = 3;\n\t\t\t\t\t\tmx = Keyboard->MouseQX;\n\t\t\t\t\t\tmy = Keyboard->MouseQY;\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tGrab bottom left\n\t\t\t\t\t*/\n\t\t\t\t\tdelta1 =  abs(Keyboard->MouseQX - map_x1);\n\t\t\t\t\tdelta2 =  abs(Keyboard->MouseQY - map_y2);\n\t\t\t\t\tif (delta1 < 3 && delta2 < 3) {\n\t\t\t\t\t\tgrabbed = 4;\n\t\t\t\t\t\tmx = Keyboard->MouseQX;\n\t\t\t\t\t\tmy = Keyboard->MouseQY;\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tGrab the whole map\n\t\t\t\t\t*/\n\t\t\t\t\tdelta1 = abs(Keyboard->MouseQX - ((map_x1 + map_x2) / 2));\n\t\t\t\t\tdelta2 = abs(Keyboard->MouseQY - ((map_y1 + map_y2) / 2));\n\t\t\t\t\tif (delta1 < (map_x2 - map_x1) / 4 &&\n\t\t\t\t\t\tdelta2 < (map_y2 - map_y1) / 4) {\n\t\t\t\t\t\tgrabbed = 5;\n\t\t\t\t\t\tmx = Keyboard->MouseQX;\n\t\t\t\t\t\tmy = Keyboard->MouseQY;\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tMouse motion processing: This is done while the left mouse button IS\n\t\t\t**\tbeing held down.\n\t\t\t**\t- First, check for the button release; if detected, un-grab\n\t\t\t**\t- Then, handle mouse motion. WWLIB doesn't pass through a KN_MOUSE_MOVE\n\t\t\t**\t  value while the button is being held down, so this case must be\n\t\t\t**\t  trapped as a default.\n\t\t\t*/\n\t\t\tswitch (input) {\n\t\t\t\tcase ((int)KN_LMOUSE | (int)KN_RLSE_BIT):\n\t\t\t\t\tgrabbed = 0;\n\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tdelta1 = Get_Mouse_X() - mx;\n\t\t\t\t\tdelta2 = Get_Mouse_Y() - my;\n\t\t\t\t\tif (delta1==0 && delta2==0) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tMove top left\n\t\t\t\t\t*/\n\t\t\t\t\tif (grabbed==1) {\n\t\t\t\t\t\tmap_x1 += delta1;\n\t\t\t\t\t\tif (map_x1 > map_x2 - 2) {\n\t\t\t\t\t\t\tmap_x1 = map_x2 - 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (map_x1 < D_BORD_X1 + 2) {\n\t\t\t\t\t\t\t\tmap_x1 = D_BORD_X1 + 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmap_y1 += delta2;\n\t\t\t\t\t\tif (map_y1 > map_y2 - 2) {\n\t\t\t\t\t\t\tmap_y1 = map_y2 - 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (map_y1 < D_BORD_Y1 + 2) {\n\t\t\t\t\t\t\t\tmap_y1 = D_BORD_Y1 + 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tmx = Get_Mouse_X();\n\t\t\t\t\t\tmy = Get_Mouse_Y();\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tMove top right\n\t\t\t\t\t*/\n\t\t\t\t\tif (grabbed==2) {\n\t\t\t\t\t\tmap_x2 += delta1;\n\t\t\t\t\t\tif (map_x2 < map_x1 + 2) {\n\t\t\t\t\t\t\tmap_x2 = map_x1 + 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (map_x2 > D_BORD_X2 - 2) {\n\t\t\t\t\t\t\t\tmap_x2 = D_BORD_X2 - 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmap_y1 += delta2;\n\t\t\t\t\t\tif (map_y1 > map_y2 - 2) {\n\t\t\t\t\t\t\tmap_y1 = map_y2 - 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (map_y1 < D_BORD_Y1 + 2) {\n\t\t\t\t\t\t\t\tmap_y1 = D_BORD_Y1 + 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tmx = Get_Mouse_X();\n\t\t\t\t\t\tmy = Get_Mouse_Y();\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tMove bottom right\n\t\t\t\t\t*/\n\t\t\t\t\tif (grabbed==3) {\n\t\t\t\t\t\tmap_x2 += delta1;\n\t\t\t\t\t\tif (map_x2 < map_x1 + 2) {\n\t\t\t\t\t\t\tmap_x2 = map_x1 + 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (map_x2 > D_BORD_X2 - 2) {\n\t\t\t\t\t\t\t\tmap_x2 = D_BORD_X2 - 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmap_y2 += delta2;\n\t\t\t\t\t\tif (map_y2 < map_y1 + 2) {\n\t\t\t\t\t\t\tmap_y2 = map_y1 + 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (map_y2 > D_BORD_Y2 - 2) {\n\t\t\t\t\t\t\t\tmap_y2 = D_BORD_Y2 - 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tmx = Get_Mouse_X();\n\t\t\t\t\t\tmy = Get_Mouse_Y();\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tMove bottom left\n\t\t\t\t\t*/\n\t\t\t\t\tif (grabbed==4) {\n\t\t\t\t\t\tmap_x1 += delta1;\n\t\t\t\t\t\tif (map_x1 > map_x2 - 2) {\n\t\t\t\t\t\t\tmap_x1 = map_x2 - 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (map_x1 < D_BORD_X1 + 2) {\n\t\t\t\t\t\t\t\tmap_x1 = D_BORD_X1 + 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmap_y2 += delta2;\n\t\t\t\t\t\tif (map_y2 < map_y1 + 2) {\n\t\t\t\t\t\t\tmap_y2 = map_y1 + 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (map_y2 > D_BORD_Y2 - 2) {\n\t\t\t\t\t\t\t\tmap_y2 = D_BORD_Y2 - 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tmx = Get_Mouse_X();\n\t\t\t\t\t\tmy = Get_Mouse_Y();\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tMove whole map\n\t\t\t\t\t*/\n\t\t\t\t\tif (grabbed==5) {\n\t\t\t\t\t\tif (map_x1 + delta1 > D_BORD_X1 + 1 && map_x2 + delta1 < D_BORD_X2 - 1) {\n\t\t\t\t\t\t\tmap_x1 += delta1;\n\t\t\t\t\t\t\tmap_x2 += delta1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (map_y1 + delta2 > D_BORD_Y1 + 1 && map_y2 + delta2 < D_BORD_Y2 - 1) {\n\t\t\t\t\t\t\tmap_y1 += delta2;\n\t\t\t\t\t\t\tmap_y2 += delta2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tmx = Get_Mouse_X();\n\t\t\t\t\t\tmy = Get_Mouse_Y();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tRedraw the display\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n\n\t/*\n\t**\tIf cancel, just return\n\t*/\n\tif (cancel) {\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tSave selections\n\t*/\n\tMapCellX = map_x1 - D_BORD_X1 - 1;\n\tMapCellY = map_y1 - D_BORD_Y1 - 1;\n\tMapCellWidth = map_x2 - map_x1 + 1;\n\tMapCellHeight = map_y2 - map_y1 + 1;\n\n\t/*\n\t**\tClip Home Cell to new map size\n\t*/\n\tif (Cell_X(Scen.Waypoint[WAYPT_HOME]) < MapCellX) {\n\t\tScen.Waypoint[WAYPT_HOME] = XY_Cell(MapCellX, Cell_Y(Scen.Waypoint[WAYPT_HOME]));\n\t}\n\n\tif (Cell_X(Scen.Waypoint[WAYPT_HOME]) > MapCellX + MapCellWidth - 1) {\n\t\tScen.Waypoint[WAYPT_HOME] = XY_Cell(MapCellX + MapCellWidth - 1, Cell_Y(Scen.Waypoint[WAYPT_HOME]));\n\t}\n\n\tif (Cell_Y(Scen.Waypoint[WAYPT_HOME]) < MapCellY) {\n\t\tScen.Waypoint[WAYPT_HOME] = XY_Cell(Cell_X(Scen.Waypoint[WAYPT_HOME]), MapCellY);\n\t}\n\n\tif (Cell_Y(Scen.Waypoint[WAYPT_HOME]) > MapCellY + MapCellHeight - 1) {\n\t\tScen.Waypoint[WAYPT_HOME] = XY_Cell(Cell_X(Scen.Waypoint[WAYPT_HOME]), MapCellY + MapCellHeight - 1);\n\t}\n\n\treturn(0);\n}\n\n\n/***************************************************************************\n * MapEditClass::Scenario_Dialog -- scenario global parameters dialog      *\n *                                                                         *\n *    Edits the house specific and general scenario options.               *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, -1 = cancel                                                *\n *                                                                         *\n * WARNINGS:                                                               *\n *      Uses HIDBUFF.                                                      *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/14/1994 BR : Created.                                              *\n *   02/13/1996 JLB : Revamped to new system.                              *\n *=========================================================================*/\nint MapEditClass::Scenario_Dialog(void)\n{\n\tTheaterType orig_theater = Scen.Theater;\t\t// original theater\n\tHousesType house = PlayerPtr->Class->House;\n\tHousesType newhouse = house;\n\tHouseStaticClass hdata[HOUSE_COUNT];\n\n\t/*\n\t**\tFill in the house data for each house that exists.\n\t*/\n\tfor (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\tHouseClass * hptr = HouseClass::As_Pointer(h);\n\t\tif (hptr) {\n\t\t\thdata[h] = hptr->Control;\n\t\t}\n\t}\n\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tenum {\n\t\tD_DIALOG_W = 320 * RESFACTOR,\n\t\tD_DIALOG_H = 200 * RESFACTOR,\n\t\tD_DIALOG_X = ((320 * RESFACTOR - D_DIALOG_W) / 2),\n\t\tD_DIALOG_Y = ((200 * RESFACTOR - D_DIALOG_H) / 2),\n\n\t\tD_OK_W = 45,\n\t\tD_OK_H = 9,\n\t\tD_OK_X = D_DIALOG_X + 15 * RESFACTOR,\n\t\tD_OK_Y = D_DIALOG_Y + D_DIALOG_H - 15 * RESFACTOR,\n\n\t\tD_CANCEL_W = 45,\n\t\tD_CANCEL_H = 9,\n\t\tD_CANCEL_X = D_DIALOG_X + D_DIALOG_W - (D_CANCEL_W+15*RESFACTOR),\n\t\tD_CANCEL_Y = D_DIALOG_Y + D_DIALOG_H - 15*RESFACTOR\n\t};\n\n\t/*\n\t**\tButton enumerations:\n\t*/\n\tenum {\n\t\tLIST_THEATER=100,\n\t\tBUTTON_DESCRIPTION,\n\t\tBUTTON_ALLIES,\n\t\tBUTTON_CONTROL,\n\t\tBUTTON_SMARTIES,\n\t\tBUTTON_BASE,\n\t\tBUTTON_NOSPYPLANE,\n\t\tBUTTON_INHERIT,\n\t\tBUTTON_TIMER,\n\t\tBUTTON_THEME,\n\t\tBUTTON_RECORD,\n\t\tBUTTON_EVAC,\n\t\tBUTTON_MONEYTIB,\n\t\tBUTTON_TECH,\n\t\tBUTTON_TRUCKCRATE,\n\t\tBUTTON_ENDOFGAME,\n\t\tBUTTON_SKIPSCORE,\n\t\tBUTTON_ONETIME,\n\t\tBUTTON_NOMAPSEL,\n\t\tBUTTON_HOUSE,\n\t\tBUTTON_CREDITS,\n\t\tBUTTON_SOURCE,\n\t\tBUTTON_MAXUNIT,\n\t\tBUTTON_INTRO,\n\t\tBUTTON_BRIEFING,\n\t\tBUTTON_ACTION,\n\t\tBUTTON_WIN,\n\t\tBUTTON_LOSE,\n\t\tBUTTON_OK,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t/*\n\t**\tInitialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\tControlClass * commands = NULL;\t\t\t\t// the button list\n\n\t/*\n\t**\tTheater choice drop down list.\n\t*/\n\tchar theatertext[45] = \"\";\n\tDropListClass theaterbtn(LIST_THEATER, theatertext, sizeof(theatertext)-1,\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tD_DIALOG_X+15*RESFACTOR, D_DIALOG_Y+30, 65, 8*5,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (TheaterType t = THEATER_FIRST; t < THEATER_COUNT; t++) {\n\t\ttheaterbtn.Add_Item(Theaters[t].Name);\n\t}\n\ttheaterbtn.Set_Selected_Index(orig_theater);\n\n\tchar description[DESCRIP_MAX] = \"\";\n\tstrcpy(description, Scen.Description);\n\tEditClass desc(BUTTON_DESCRIPTION, description, sizeof(description), TPF_EFNT|TPF_NOSHADOW, theaterbtn.X+theaterbtn.Width+15, theaterbtn.Y, 160);\n\n\t/*\n\t**\tButton that tells if this scenario should inherit buildings from the previous.\n\t*/\n\tCheckBoxClass inherit(BUTTON_INHERIT, theaterbtn.X+theaterbtn.Width+15+250, theaterbtn.Y);\n\tif (Scen.IsToInherit) {\n\t\tinherit.Turn_On();\n\t} else {\n\t\tinherit.Turn_Off();\n\t}\n\n\t/*\n\t**\tRecords scenario disposition into holding slot.\n\t*/\n\tCheckBoxClass record(BUTTON_RECORD, inherit.X, inherit.Y+8);\n\tif (Scen.IsToCarryOver) {\n\t\trecord.Turn_On();\n\t} else {\n\t\trecord.Turn_Off();\n\t}\n\n\t/*\n\t**\tShould Tanya/civilian be automatically evacuated?\n\t*/\n\tCheckBoxClass tanya(BUTTON_EVAC, record.X, record.Y+8);\n\tif (Scen.IsTanyaEvac) {\n\t\ttanya.Turn_On();\n\t} else {\n\t\ttanya.Turn_Off();\n\t}\n\n\t/*\n\t**\tEnd of game with with scenario?\n\t*/\n\tCheckBoxClass endofgame(BUTTON_ENDOFGAME, tanya.X, tanya.Y+8);\n\tif (Scen.IsEndOfGame) {\n\t\tendofgame.Turn_On();\n\t} else {\n\t\tendofgame.Turn_Off();\n\t}\n\n\t/*\n\t**\tTimer inherit logic.\n\t*/\n\tCheckBoxClass timercarry(BUTTON_TIMER, endofgame.X, endofgame.Y+8);\n\tif (Scen.IsInheritTimer) {\n\t\ttimercarry.Turn_On();\n\t} else {\n\t\ttimercarry.Turn_Off();\n\t}\n\n\t/*\n\t**\tDisable spy plane option?\n\t*/\n\tCheckBoxClass nospyplane(BUTTON_NOSPYPLANE, timercarry.X, timercarry.Y+8);\n\tif (Scen.IsNoSpyPlane) {\n\t\tnospyplane.Turn_On();\n\t} else {\n\t\tnospyplane.Turn_Off();\n\t}\n\n\t/*\n\t**\tSkip the score screen?\n\t*/\n\tCheckBoxClass skipscore(BUTTON_SKIPSCORE, nospyplane.X, nospyplane.Y+8);\n\tif (Scen.IsSkipScore) {\n\t\tskipscore.Turn_On();\n\t} else {\n\t\tskipscore.Turn_Off();\n\t}\n\n\t/*\n\t**\tSkip the map selection screen for next mission. Presume goes to\n\t**\tvariation \"B\"?\n\t*/\n\tCheckBoxClass nomapsel(BUTTON_NOMAPSEL, skipscore.X, skipscore.Y+8);\n\tif (Scen.IsNoMapSel) {\n\t\tnomapsel.Turn_On();\n\t} else {\n\t\tnomapsel.Turn_Off();\n\t}\n\n\t/*\n\t**\tReturn to main menu after mission completes?\n\t*/\n\tCheckBoxClass onetime(BUTTON_ONETIME, nomapsel.X, nomapsel.Y+8);\n\tif (Scen.IsOneTimeOnly) {\n\t\tonetime.Turn_On();\n\t} else {\n\t\tonetime.Turn_Off();\n\t}\n\n\t/*\n\t**\tTrucks carry a wood crate?\n\t*/\n\tCheckBoxClass truckcrate(BUTTON_TRUCKCRATE, onetime.X, onetime.Y+8);\n\tif (Scen.IsTruckCrate) {\n\t\ttruckcrate.Turn_On();\n\t} else {\n\t\ttruckcrate.Turn_Off();\n\t}\n\n\t/*\n\t**\tTransfer credits into tiberium storage at scenario start?\n\t*/\n\tCheckBoxClass moneytib(BUTTON_MONEYTIB, truckcrate.X, truckcrate.Y+8);\n\tif (Scen.IsMoneyTiberium) {\n\t\tmoneytib.Turn_On();\n\t} else {\n\t\tmoneytib.Turn_Off();\n\t}\n\n\t/*\n\t**\tIntro movie name.\n\t*/\n\tchar introtext[_MAX_FNAME+_MAX_EXT];\n\tDropListClass intro(BUTTON_INTRO, introtext, sizeof(introtext),\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\ttheaterbtn.X, theaterbtn.Y+theaterbtn.Height+24, 50, 7*10,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tintro.Add_Item(\"<none>\");\n\tfor (VQType v = VQ_FIRST; v < VQ_COUNT; v++) {\n\t\tintro.Add_Item(VQName[v]);\n\t}\n\tintro.Set_Selected_Index((int)Scen.IntroMovie + 1);\n\n\t/*\n\t**\tBriefing movie name.\n\t*/\n\tchar brieftext[_MAX_FNAME+_MAX_EXT];\n\tDropListClass briefing(BUTTON_BRIEFING, brieftext, sizeof(brieftext),\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tintro.X+intro.Width+10, intro.Y, 50, 7*10,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tbriefing.Add_Item(\"<none>\");\n\tfor (v = VQ_FIRST; v < VQ_COUNT; v++) {\n\t\tbriefing.Add_Item(VQName[v]);\n\t}\n\tbriefing.Set_Selected_Index((int)Scen.BriefMovie + 1);\n\n\tchar actiontext[_MAX_FNAME+_MAX_EXT];\n\tDropListClass action(BUTTON_ACTION, actiontext, sizeof(actiontext),\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tbriefing.X+briefing.Width+10, briefing.Y, 50, 7*10,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\taction.Add_Item(\"<none>\");\n\tfor (v = VQ_FIRST; v < VQ_COUNT; v++) {\n\t\taction.Add_Item(VQName[v]);\n\t}\n\taction.Set_Selected_Index((int)Scen.ActionMovie + 1);\n\n\tchar wintext[_MAX_FNAME+_MAX_EXT];\n\tDropListClass win(BUTTON_WIN, wintext, sizeof(wintext),\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\taction.X+action.Width+10, action.Y, 50, 7*10,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\twin.Add_Item(\"<none>\");\n\tfor (v = VQ_FIRST; v < VQ_COUNT; v++) {\n\t\twin.Add_Item(VQName[v]);\n\t}\n\twin.Set_Selected_Index((int)Scen.WinMovie + 1);\n\n\tchar losetext[_MAX_FNAME+_MAX_EXT];\n\tDropListClass lose(BUTTON_LOSE, losetext, sizeof(losetext),\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\twin.X+win.Width+10, win.Y, 50, 7*10,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tlose.Add_Item(\"<none>\");\n\tfor (v = VQ_FIRST; v < VQ_COUNT; v++) {\n\t\tlose.Add_Item(VQName[v]);\n\t}\n\tlose.Set_Selected_Index((int)Scen.LoseMovie + 1);\n\n\t/*\n\t**\tHouse choice list.\n\t*/\n\tListClass housebtn(BUTTON_HOUSE,\n\t\tD_DIALOG_X+15*RESFACTOR, D_DIALOG_Y+105, 55, 7*10,\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\thousebtn.Add_Item(HouseTypeClass::As_Reference(h).IniName);\n\t}\n\thousebtn.Set_Selected_Index(PlayerPtr->Class->House);\n\n\t/*\n\t**\tBase house choice drop down list.\n\t*/\n\tchar basetext[35];\n\tDropListClass basebtn(BUTTON_BASE, basetext, sizeof(basetext),\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tD_DIALOG_X+15*RESFACTOR, D_DIALOG_Y+80, 65, 7*10,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\tbasebtn.Add_Item(HouseTypeClass::As_Reference(h).IniName);\n\t}\n\tif (Base.House != HOUSE_NONE) {\n\t\tbasebtn.Set_Selected_Index(Base.House);\n\t}\n\n\t/*\n\t**\tOpening scenario theme.\n\t*/\n\tchar themetext[65];\n\tDropListClass themebtn(BUTTON_THEME, themetext, sizeof(themetext),\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tbasebtn.X+basebtn.Width+15*RESFACTOR, basebtn.Y, 85, 7*10,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tthemebtn.Add_Item(\"<none>\");\n\tfor (ThemeType th = THEME_FIRST; th < THEME_COUNT; th++) {\n\t\tthemebtn.Add_Item(Theme.Full_Name(th));\n\t}\n\tif (Scen.TransitTheme != THEME_NONE) {\n\t\tthemebtn.Set_Selected_Index(Scen.TransitTheme+1);\n\t} else {\n\t\tthemebtn.Set_Selected_Index(0);\n\t}\n\n\t/*\n\t**\tBuild level (technology).\n\t*/\n\tSliderClass techlevel(BUTTON_TECH, housebtn.X+housebtn.Width+15, housebtn.Y, 100, 8);\n\ttechlevel.Set_Maximum(16);\n\n\tchar statictechbuff[15];\n\tStaticButtonClass techstatic(0, \"999\", TPF_EFNT|TPF_NOSHADOW, techlevel.X+techlevel.Width-20, techlevel.Y-7);\n\n\t/*\n\t**\tStarting credits.\n\t*/\n\tSliderClass creditbtn(BUTTON_CREDITS, housebtn.X+housebtn.Width+15, techlevel.Y+20, 100, 8);\n\tcreditbtn.Set_Maximum(201);\n\n\tchar staticcreditbuff[15];\n\tStaticButtonClass creditstatic(0, \"999999999\", TPF_EFNT|TPF_NOSHADOW, creditbtn.X+creditbtn.Width-50, creditbtn.Y-7);\n\n\t/*\n\t**\tMaximum unit/infantry slider.\n\t*/\n\tSliderClass maxunit(BUTTON_MAXUNIT, housebtn.X+housebtn.Width+15, creditbtn.Y+20, 100, 8);\n\tmaxunit.Set_Maximum(501);\n\n\tchar staticmaxunitbuff[15];\n\tStaticButtonClass maxunitstatic(0, \"999999\", TPF_EFNT|TPF_NOSHADOW, maxunit.X+maxunit.Width-30, maxunit.Y-7);\n\n\t/*\n\t**\tSource of ground delivery reinforcements.\n\t*/\n\tchar sourcetext[25] = \"\";\n\tListClass sourcebtn(BUTTON_SOURCE,\n\t\thousebtn.X+housebtn.Width+15, maxunit.Y+20, 100, 7*4,\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (SourceType source = SOURCE_FIRST; source <= SOURCE_WEST; source++) {\n\t\tsourcebtn.Add_Item(SourceName[source]);\n\t}\n\n\t/*\n\t**\tSmartness lider.\n\t*/\n\tSliderClass smarties(BUTTON_SMARTIES, sourcebtn.X, sourcebtn.Y+sourcebtn.Height+15, 35, 8);\n\tsmarties.Set_Maximum(Rule.MaxIQ+1);\n\n\tchar staticsmartiesbuff[15];\n\tStaticButtonClass smartiesstatic(0, \"9999\", TPF_EFNT|TPF_NOSHADOW, smarties.X+smarties.Width-20, smarties.Y-7);\n\n\t/*\n\t**\tList box of who is allied with whom.\n\t*/\n\tCheckListClass allies(BUTTON_ALLIES,\n\t\ttechlevel.X+techlevel.Width+5, housebtn.Y, 65, 7*10,\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\tallies.Add_Item(HouseTypeClass::As_Reference(h).IniName);\n\t\tif (hdata[house].Allies & (1L << h)) {\n\t\t\tallies.Check_Item(h, true);\n\t\t}\n\t}\n\tallies.Set_Selected_Index(0);\n\n\t/*\n\t**\tList box of who the player can control.\n\t*/\n\tCheckListClass control(BUTTON_CONTROL,\n\t\tallies.X+allies.Width+10, housebtn.Y, 65, 7*10,\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\tcontrol.Add_Item(HouseTypeClass::As_Reference(h).IniName);\n\t\tif (HouseClass::As_Pointer(h)->IsPlayerControl) {\n\t\t\tcontrol.Check_Item(h, true);\n\t\t}\n\t}\n\tcontrol.Set_Selected_Index(0);\n\n\t/*\n\t**\tCreate the ubiquitous \"ok\" and \"cancel\" buttons.\n\t*/\n\tTextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_EBUTTON, D_OK_X, D_OK_Y, D_OK_W, D_OK_H);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_EBUTTON, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W, D_CANCEL_H);\n\n\t/*\n\t**\tCreate the list\n\t*/\n\tcommands = &okbtn;\n\tcancelbtn.Add_Tail(*commands);\n\ttheaterbtn.Add_Tail(*commands);\n\tthemebtn.Add_Tail(*commands);\n\thousebtn.Add_Tail(*commands);\n\ttechlevel.Add_Tail(*commands);\n\ttechstatic.Add_Tail(*commands);\n\tsourcebtn.Add_Tail(*commands);\n\tcreditbtn.Add_Tail(*commands);\n\tcreditstatic.Add_Tail(*commands);\n\tmaxunitstatic.Add_Tail(*commands);\n\tmoneytib.Add_Tail(*commands);\n\tsmartiesstatic.Add_Tail(*commands);\n\tallies.Add_Tail(*commands);\n\tcontrol.Add_Tail(*commands);\n\tmaxunit.Add_Tail(*commands);\n\tnospyplane.Add_Tail(*commands);\n\tskipscore.Add_Tail(*commands);\n\tnomapsel.Add_Tail(*commands);\n\tonetime.Add_Tail(*commands);\n\tinherit.Add_Tail(*commands);\n\ttimercarry.Add_Tail(*commands);\n\ttanya.Add_Tail(*commands);\n\trecord.Add_Tail(*commands);\n\ttruckcrate.Add_Tail(*commands);\n\tendofgame.Add_Tail(*commands);\n\tbriefing.Add_Tail(*commands);\n\tintro.Add_Tail(*commands);\n\taction.Add_Tail(*commands);\n\twin.Add_Tail(*commands);\n\tlose.Add_Tail(*commands);\n\tbasebtn.Add_Tail(*commands);\n\tsmarties.Add_Tail(*commands);\n\tdesc.Add_Tail(*commands);\n\n\t/*\n\t**\tMain Processing Loop\n\t*/\n\tbool housechange = true;\n\tbool display = true;\n\tbool process = true;\n\tbool cancel = false;\t\t// true = user cancels\n\tbool dotext = true;\t\t// display the text.\n\tbool fetch = false;\t\t// Fetch data from dialog into tracking structure.\n\t//Set_Logic_Page(SeenBuff);\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tIf the house changes, then all the gadgets that reflect the settings of the\n\t\t**\thouse should change as well.\n\t\t*/\n\t\tif (housechange) {\n\t\t\tHouseStaticClass * hstatic = &hdata[newhouse];\n\t\t\tcreditbtn.Set_Value(hstatic->InitialCredits/100);\n\t\t\ttechlevel.Set_Value(hstatic->TechLevel);\n\t\t\tsourcebtn.Set_Selected_Index(hstatic->Edge);\n\t\t\tmaxunit.Set_Value(hstatic->MaxUnit + hstatic->MaxInfantry);\n\t\t\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\t\t\tallies.Check_Item(h, hstatic->Allies & (1L << h));\n\t\t\t}\n\t\t\tsmarties.Set_Value(hstatic->IQ);\n\n\t\t\thouse = newhouse;\n\t\t\thousechange = false;\n\t\t\tdisplay = true;\n\t\t}\n\n\t\t/*\n\t\t**\tRefresh display if needed\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t**\tDraw the background\n\t\t\t*/\n\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\t\t\tDraw_Caption(TXT_SCENARIO_OPTIONS, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\n\t\t\t/*\n\t\t\t**\tDisplay the text that doesn't need drawing except when the entire dialog\n\t\t\t**\tneeds to be redrawn.\n\t\t\t*/\n\t\t\tFancy_Text_Print(\"Tech Level =\", techlevel.X, techlevel.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Credits =\", creditbtn.X, creditbtn.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Unit Max =\", maxunit.X, maxunit.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"IQ =\", smarties.X, smarties.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Prebuild Base:\", basebtn.X, basebtn.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Theater:\", theaterbtn.X, theaterbtn.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Scenario Name:\", desc.X, desc.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Country:\", housebtn.X, housebtn.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Home Edge:\", sourcebtn.X, sourcebtn.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Allies:\", allies.X, allies.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Plyr Control:\", control.X, control.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Theme:\", themebtn.X, themebtn.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Intro:\", intro.X, intro.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Briefing:\", briefing.X, briefing.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Action:\", action.X, action.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Win:\", win.X, win.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Lose:\", lose.X, lose.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Store scenario?\", record.X+10, record.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Inherit stored scenario?\", inherit.X+10, inherit.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Auto evac. Tanya (civilian)?\", tanya.X+10, tanya.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Last mission of game?\", endofgame.X+10, endofgame.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Inherit mission timer from last scenario?\", timercarry.X+10, timercarry.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Disable spy plane?\", nospyplane.X+10, nospyplane.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Skip the score screen?\", skipscore.X+10, skipscore.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"No map selection (force var 'B')?\", nomapsel.X+10, nomapsel.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Return to main menu after scenario finishes?\", onetime.X+10, onetime.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Truck carries wood crate?\", truckcrate.X+10, truckcrate.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Initial money is transferred to silos?\", moneytib.X+10, moneytib.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\n\t\t\ttheaterbtn.Collapse();\n\t\t\tthemebtn.Collapse();\n\t\t\tintro.Collapse();\n\t\t\tbriefing.Collapse();\n\t\t\taction.Collapse();\n\t\t\twin.Collapse();\n\t\t\tlose.Collapse();\n\t\t\tbasebtn.Collapse();\n\t\t\tcommands->Draw_All(true);\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t\tdotext = true;\n\t\t}\n\n\t\t/*\n\t\t**\tDisplay the text of the buttons that could change their text as a\n\t\t**\tresult of slider interaction.\n\t\t*/\n\t\tif (dotext) {\n\t\t\tdotext = false;\n\t\t\tHide_Mouse();\n\n\t\t\tsprintf(statictechbuff, \"%2d\", techlevel.Get_Value());\n\t\t\ttechstatic.Set_Text(statictechbuff);\n\t\t\ttechstatic.Draw_Me();\n\n\t\t\tsprintf(staticcreditbuff, \"$%-7d\", creditbtn.Get_Value() * 100);\n\t\t\tcreditstatic.Set_Text(staticcreditbuff);\n\t\t\tcreditstatic.Draw_Me();\n\n\t\t\tsprintf(staticmaxunitbuff, \"%4d\", maxunit.Get_Value());\n\t\t\tmaxunitstatic.Set_Text(staticmaxunitbuff);\n\t\t\tmaxunitstatic.Draw_Me();\n\n\t\t\tsprintf(staticsmartiesbuff, \"%2d\", smarties.Get_Value());\n\t\t\tsmartiesstatic.Set_Text(staticsmartiesbuff);\n\t\t\tsmartiesstatic.Draw_Me();\n\n\t\t\tShow_Mouse();\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t**\tProcess input\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase BUTTON_ALLIES|KN_BUTTON:\n\t\t\t\tallies.Check_Item(house, true);\n\t\t\t\tbreak;\n\n\t\t\tcase BUTTON_CONTROL|KN_BUTTON:\n\t\t\t\tcontrol.Check_Item(house, true);\n\t\t\t\tbreak;\n\n\t\t\tcase BUTTON_THEME|KN_BUTTON:\n\t\t\tcase BUTTON_INTRO|KN_BUTTON:\n\t\t\tcase BUTTON_BRIEFING|KN_BUTTON:\n\t\t\tcase BUTTON_ACTION|KN_BUTTON:\n\t\t\tcase BUTTON_WIN|KN_BUTTON:\n\t\t\tcase BUTTON_LOSE|KN_BUTTON:\n\t\t\tcase BUTTON_BASE|KN_BUTTON:\n\t\t\tcase LIST_THEATER|KN_BUTTON:\n\t\t\t\tbriefing.Collapse();\n\t\t\t\taction.Collapse();\n\t\t\t\twin.Collapse();\n\t\t\t\tthemebtn.Collapse();\n\t\t\t\tintro.Collapse();\n\t\t\t\tlose.Collapse();\n\t\t\t\tbasebtn.Collapse();\n\t\t\t\ttheaterbtn.Collapse();\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\tcase BUTTON_SMARTIES|KN_BUTTON:\n\t\t\tcase BUTTON_MAXUNIT|KN_BUTTON:\n\t\t\tcase BUTTON_CREDITS|KN_BUTTON:\n\t\t\tcase BUTTON_TECH|KN_BUTTON:\n\t\t\t\tbriefing.Collapse();\n\t\t\t\taction.Collapse();\n\t\t\t\twin.Collapse();\n\t\t\t\tlose.Collapse();\n\t\t\t\tbasebtn.Collapse();\n\t\t\t\tthemebtn.Collapse();\n\t\t\t\ttheaterbtn.Collapse();\n\t\t\t\tdotext = true;\n\t\t\t\tbreak;\n\n\t\t\tcase BUTTON_HOUSE|KN_BUTTON:\n\t\t\t\tnewhouse = HousesType(housebtn.Current_Index());\n\t\t\t\thousechange = true;\n\t\t\t\tbriefing.Collapse();\n\t\t\t\taction.Collapse();\n\t\t\t\tthemebtn.Collapse();\n\t\t\t\twin.Collapse();\n\t\t\t\tintro.Collapse();\n\t\t\t\tlose.Collapse();\n\t\t\t\tbasebtn.Collapse();\n\t\t\t\ttheaterbtn.Collapse();\n\t\t\t\tfetch = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tcancel = false;\n\t\t\t\tprocess = false;\n\t\t\t\tfetch = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tcancel = true;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\n\t\t/*\n\t\t**\tIf the house changes, then all the gadgets that reflect the settings of the\n\t\t**\thouse should change as well.\n\t\t*/\n\t\tif (fetch) {\n\t\t\tfetch = false;\n\t\t\tHouseStaticClass * hstatic = &hdata[house];\n\n\t\t\tBase.House = HousesType(basebtn.Current_Index());\n\t\t\thstatic->InitialCredits = creditbtn.Get_Value() * 100;\n\t\t\thstatic->Edge = SourceType(sourcebtn.Current_Index());\n\t\t\thstatic->TechLevel = techlevel.Get_Value();\n\t\t\thstatic->MaxUnit = maxunit.Get_Value()/2;\n\t\t\thstatic->MaxInfantry = maxunit.Get_Value()/2;\n\t\t\thstatic->IQ = smarties.Get_Value();\n\t\t\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\t\t\tif (allies.Is_Checked(h)) {\n\t\t\t\t\thstatic->Allies |= (1L << h);\n\t\t\t\t} else {\n\t\t\t\t\thstatic->Allies &= ~(1L << h);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tRedraw the map\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n\n\t/*\n\t**\tIf cancel, just return\n\t*/\n\tif (cancel) {\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tCopy the dialog data back into the appropriate game data locations.\n\t*/\n\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\tHouseClass * hptr = HouseClass::As_Pointer(h);\n\t\tif (hptr != NULL) {\n\t\t\thptr->Control = hdata[h];\n\t\t\thptr->Allies = hdata[h].Allies;\n\n\t\t\tif (control.Is_Checked(h)) {\n\t\t\t\thptr->IsPlayerControl = true;\n\t\t\t} else {\n\t\t\t\thptr->IsPlayerControl = false;\n\t\t\t}\n\t\t}\n\t}\n\tPlayerPtr->IsPlayerControl = true;\n\tstrncpy(Scen.Description, desc.Get_Text(), sizeof(Scen.Description));\n\tScen.Description[sizeof(Scen.Description)-1] = '\\0';\n\tScen.IntroMovie = VQType(intro.Current_Index()-1);\n\tScen.BriefMovie = VQType(briefing.Current_Index()-1);\n\tScen.ActionMovie = VQType(action.Current_Index()-1);\n\tScen.WinMovie = VQType(win.Current_Index()-1);\n\tScen.LoseMovie = VQType(lose.Current_Index()-1);\n\tScen.IsToInherit = inherit.IsOn;\n\tScen.IsToCarryOver = record.IsOn;\n\tScen.IsTanyaEvac = tanya.IsOn;\n\tScen.IsEndOfGame = endofgame.IsOn;\n\tScen.IsInheritTimer = timercarry.IsOn;\n\tScen.IsNoSpyPlane = nospyplane.IsOn;\n\tScen.IsSkipScore = skipscore.IsOn;\n\tScen.IsNoMapSel = nomapsel.IsOn;\n\tScen.IsOneTimeOnly = onetime.IsOn;\n\tScen.IsTruckCrate = truckcrate.IsOn;\n\tScen.IsMoneyTiberium = moneytib.IsOn;\n\tScen.TransitTheme = ThemeType(themebtn.Current_Index()-1);\n\n\t/*\n\t**\tChange the theater:\n\t**\t- 1st set the Theater global\n\t**\t- scan all cells to check their TType for compatibility with the new\n\t**\t  theater; if not compatible, set TType to TEMPLATE_NONE & TIcon to 0\n\t**\t- Then, re-initialize the TypeClasses for the new Theater\n\t*/\n\tTheaterType theater = TheaterType(theaterbtn.Current_Index());\n\tif (theater != orig_theater) {\n\n\t\tunsigned char theater_mask;\t// template/terrain mask\n\t\tTerrainClass * terrain;\t// cell's terrain pointer\n\n\t\t/*\n\t\t**\tLoop through all cells\n\t\t*/\n\t\tfor (CELL i = 0; i < MAP_CELL_TOTAL; i++) {\n\n\t\t\t/*\n\t\t\t**\tIf this cell has a template icon & that template isn't compatible\n\t\t\t**\twith this theater, set the icon to NONE\n\t\t\t*/\n\t\t\tif ((*this)[i].TType != TEMPLATE_NONE) {\n\t\t\t\ttheater_mask = TemplateTypeClass::As_Reference((*this)[i].TType).Theater;\n\t\t\t\tif ( (theater_mask & (1 << theater))==0) {\n\t\t\t\t\t(*this)[i].TType = TEMPLATE_NONE;\n\t\t\t\t\t(*this)[i].TIcon = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf this cell has terrain in it, and that terrain isn't compatible\n\t\t\t**\twith this theater, delete the terrain object.\n\t\t\t*/\n\t\t\tterrain = (*this)[i].Cell_Terrain();\n\t\t\tif (terrain != NULL) {\n\t\t\t\ttheater_mask = terrain->Class->Theater;\n\t\t\t\tif ( (theater_mask & (1<<theater))==0) {\n\t\t\t\t\tdelete terrain;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Remove any old theater specific uncompressed shapes\n\t\t*/\n#ifdef WIN32\n\t\tReset_Theater_Shapes();\n#endif\t//WIN32\n\t\t/*\n\t\t** Force shapes to reload\n\t\t*/\n\t\tLastTheater = THEATER_NONE;\n\n\t\t/*\n\t\t**\tRe-init the object Type Classes for this theater\n\t\t*/\n\t\tInit_Theater(theater);\n\t\tTerrainTypeClass::Init(theater);\n\t\tTemplateTypeClass::Init(theater);\n\t\tOverlayTypeClass::Init(theater);\n\t\tUnitTypeClass::Init(theater);\n\t\tInfantryTypeClass::Init(theater);\n\t\tBuildingTypeClass::Init(theater);\n\t\tBulletTypeClass::Init(theater);\n\t\tAnimTypeClass::Init(theater);\n\t\tAircraftTypeClass::Init(theater);\n\t\tVesselTypeClass::Init(theater);\n\t\tSmudgeTypeClass::Init(theater);\n\n//\t\tLastTheater = theater;\n\t}\n\n\treturn(0);\n}\n\n\n/***************************************************************************\n * Handle_Triggers -- processes the trigger dialogs                        *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/29/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Handle_Triggers(void)\n{\n\tint rc;\n\n\t/*\n\t**\tTrigger dialog processing loop:\n\t**\t- Invoke the trigger selection dialog. If a trigger's selected, break\n\t**\t  & return\n\t**\t- If user wants to edit the current trigger, do so\n\t**\t- If user wants to create new trigger, new a TriggerClass & edit it\n\t**\t- If user wants to delete trigger, delete the current trigger\n\t**\t- Keep looping until 'OK'\n\t*/\n\twhile (1) {\n\n\t\t/*\n\t\t**\tSelect trigger\n\t\t*/\n\t\trc = Select_Trigger();\n\n\t\t/*\n\t\t**\t'OK'; break\n\t\t*/\n\t\tif (rc==0) break;\n\n\t\t/*\n\t\t**\t'Edit'\n\t\t*/\n\t\tif (rc==1 && CurTrigger) {\n\t\t\tif (CurTrigger->Edit()) {\n\t\t\t\tChanged = 1;\n\t\t\t}\n\t\t\tHidPage.Clear();\n\t\t\tFlag_To_Redraw(true);\n\t\t\tRender();\n\t\t}\n\n\t\t/*\n\t\t**\t'New'\n\t\t*/\n\t\tif (rc==2) {\n\n\t\t\t/*\n\t\t\t**\tCreate a new trigger\n\t\t\t*/\n\t\t\tCurTrigger = new TriggerTypeClass();\n\t\t\tif (CurTrigger) {\n\n\t\t\t\t/*\n\t\t\t\t**\tdelete it if user cancels\n\t\t\t\t*/\n\t\t\t\tif (!CurTrigger->Edit()) {\n\t\t\t\t\tdelete CurTrigger;\n\t\t\t\t\tCurTrigger = NULL;\n\t\t\t\t} else {\n\t\t\t\t\tChanged = 1;\n\t\t\t\t}\n\t\t\t\tHidPage.Clear();\n\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\tRender();\n\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tUnable to create; issue warning\n\t\t\t\t*/\n\t\t\t\tWWMessageBox().Process(\"No more triggers available.\");\n\t\t\t\tHidPage.Clear();\n\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\tRender();\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\t'Delete'\n\t\t*/\n\t\tif (rc==3) {\n\t\t\tif (CurTrigger) {\n\t\t\t\tDetach_This_From_All(CurTrigger->As_Target(), true);\n\t\t\t\tdelete CurTrigger;\n\t\t\t\t//CurTrigger->Remove();\n\t\t\t\tCurTrigger = NULL;\n\t\t\t\tChanged = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tLet the CurTrigger global exist if the trigger can be placed on the\n\t**\tground or on a game object.\n\t*/\n\tif (CurTrigger && !(CurTrigger->Attaches_To() & (ATTACH_OBJECT|ATTACH_CELL))) {\n\t\tCurTrigger = NULL;\n\t}\n}\n\n\n/***************************************************************************\n * MapEditClass::Select_Trigger -- lets user select a trigger              *\n *                                                                         *\n * CurTrigger can be NULL when this function is called.                    *\n *                                                                         *\n *    Ŀ           *\n *                           Triggers                                    *\n *        Ŀ               *\n *         Name     Event     Action    House   Team  \u0018               *\n *         Name     Event     Action    House   Team  Ĵ               *\n *         Name     Event     Action    House   Team                  *\n *         Name     Event     Action    House   Team                  *\n *                                                                    *\n *                                                                    *\n *                                                    Ĵ               *\n *                                                    \u0019               *\n *                       *\n *                                                                       *\n *          [Edit]        [New]        [Delete]      [OK]                *\n *                                                                       *\n *               *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, 1 = Edit, 2 = New, 3 = Delete                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      Uses HIDBUFF.                                                      *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/29/1994 BR : Created.                                              *\n *   05/07/1996 JLB : Streamlined and sort trigger list.                   *\n *=========================================================================*/\nint MapEditClass::Select_Trigger(void)\n{\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tenum {\n\t\tD_DIALOG_W = 400,\n\t\tD_DIALOG_H = 250,\n\t\tD_DIALOG_X = 0,\n\t\tD_DIALOG_Y = 0,\n\n\t\tD_TXT8_H = 11,\n\t\tD_MARGIN = 35,\n\n\t\tD_LIST_W = (D_DIALOG_W-(D_MARGIN*2))-10,\n\t\tD_LIST_H = D_DIALOG_H-70,\n\t\tD_LIST_X = D_DIALOG_X + (D_DIALOG_W-D_LIST_W)/2,\n\t\tD_LIST_Y = D_DIALOG_Y + 25,\n\n\t\tBUTTON_W = 45,\n\t\tBUTTON_H = 9,\n\n\t\tD_EDIT_W = BUTTON_W,\n\t\tD_EDIT_H = BUTTON_H,\n\t\tD_EDIT_X = D_DIALOG_X + D_DIALOG_W - (((D_EDIT_W+10)*4)+25),\n\t\tD_EDIT_Y = D_DIALOG_Y + D_DIALOG_H - 20 - D_EDIT_H,\n\n\t\tD_NEW_W = BUTTON_W,\n\t\tD_NEW_H = BUTTON_H,\n\t\tD_NEW_X = D_EDIT_X + D_EDIT_W + 10,\n\t\tD_NEW_Y = D_DIALOG_Y + D_DIALOG_H - 20 - D_NEW_H,\n\n\t\tD_DELETE_W = BUTTON_W,\n\t\tD_DELETE_H = BUTTON_H,\n\t\tD_DELETE_X = D_NEW_X + D_NEW_W + 10,\n\t\tD_DELETE_Y = D_DIALOG_Y + D_DIALOG_H - 20 - D_DELETE_H,\n\n\t\tD_OK_W = BUTTON_W,\n\t\tD_OK_H = BUTTON_H,\n\t\tD_OK_X = D_DELETE_X + D_DELETE_W + 10,\n\t\tD_OK_Y = D_DIALOG_Y + D_DIALOG_H - 20 - D_OK_H,\n\n\t};\n\n\t/*\n\t**\tButton enumerations:\n\t*/\n\tenum {\n\t\tTRIGGER_LIST=100,\n\t\tBUTTON_EDIT,\n\t\tBUTTON_NEW,\n\t\tBUTTON_DELETE,\n\t\tBUTTON_OK,\n\t};\n\n\t/*\n\t**\tDialog variables:\n\t*/\n\tbool edit_trig = false;\t\t\t\t\t\t// true = user wants to edit\n\tbool new_trig = false;\t\t\t\t\t\t// true = user wants to new\n\tbool del_trig = false;\t\t\t\t\t\t// true = user wants to new\n\tint i;\t\t\t\t\t\t\t\t\t\t\t// loop counter\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass * commands = NULL;\t\t\t\t// the button list\n\n\tTListClass<CCPtr<TriggerTypeClass> > triggerlist(TRIGGER_LIST, D_LIST_X, D_LIST_Y, D_LIST_W, D_LIST_H,\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tTextButtonClass editbtn(BUTTON_EDIT, \"Edit\", TPF_EBUTTON, D_EDIT_X, D_EDIT_Y, D_EDIT_W, D_EDIT_H);\n\tTextButtonClass newbtn(BUTTON_NEW, \"New\", TPF_EBUTTON, D_NEW_X, D_NEW_Y, D_NEW_W, D_NEW_H);\n\tTextButtonClass deletebtn(BUTTON_DELETE, \"Delete\", TPF_EBUTTON, D_DELETE_X, D_DELETE_Y, D_DELETE_W, D_DELETE_H);\n\tTextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_EBUTTON, D_OK_X, D_OK_Y, D_OK_W, D_OK_H);\n\n\t/*\n\t**\tInitialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tFill in the list box\n\t*/\n\tfor (i = 0; i < TriggerTypes.Count(); i++) {\n\t\ttriggerlist.Add_Item(TriggerTypes.Ptr(i));\n\t}\n\n\tPNBubble_Sort(&triggerlist[0], triggerlist.Count());\n\n\tif (CurTrigger) {\n\t\ttriggerlist.Set_Selected_Index(CurTrigger);\n\t} else {\n\t\ttriggerlist.Set_Selected_Index(0);\n\t}\n\n\t/*\n\t**\tSet CurTrigger if it isn't\n\t*/\n\tif (TriggerTypes.Count()==0) {\n\t\tCurTrigger = NULL;\n\t} else {\n\t\tCurTrigger = triggerlist.Current_Item();\n//\t\tif (!CurTrigger) {\n//\t\t\tCurTrigger = &*triggerlist.Current_Item();\n//\t\t}\n\t}\n\n\t/*\n\t**\tCreate the list\n\t*/\n\tcommands = &triggerlist;\n\teditbtn.Add_Tail(*commands);\n\tnewbtn.Add_Tail(*commands);\n\tdeletebtn.Add_Tail(*commands);\n\tokbtn.Add_Tail(*commands);\n\n\t/*\n\t**\tMain Processing Loop\n\t*/\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\t\t/*\n\t\t**\tInvoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if requested.\n\t\t*/\n\t\tif (display /*&& LogicPage->Lock()*/) {\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\t\t\tDraw_Caption(TXT_TRIGGER_EDITOR, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\tcommands->Draw_All();\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n//\t\t\tLogicPage->Unlock();\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t**\tProcess input\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (TRIGGER_LIST | KN_BUTTON):\n\t\t\t\tCurTrigger = &*triggerlist.Current_Item();\n//\t\t\t\tCurTrigger = (TriggerTypeClass *)&*triggerlist.Current_Item();\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_EDIT | KN_BUTTON):\n\t\t\t\tif (CurTrigger) {\t\t// only allow if there's one selected\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tedit_trig = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_NEW | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tnew_trig = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_DELETE | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tdel_trig = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tRedraw the display\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n\n\tif (edit_trig) return(1);\n\tif (new_trig) return(2);\n\tif (del_trig) return(3);\n\treturn(0);\n}\n\n\n#endif\n"
  },
  {
    "path": "CODE/MAPEDIT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MAPEDIT.CPP 2     3/13/97 2:05p Steve_tall $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : MAPEDIT.CPP                              *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : October 20, 1994                         *\n *                                                                         *\n *                  Last Update : February 2, 1995   [BR]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *   Map Editor overloaded routines & utility routines                     *\n *-------------------------------------------------------------------------*\n * Map Editor modules:                                                     *\n * (Yes, they're all one huge class.)                                      *\n *      mapedit.cpp:   overloaded routines, utility routines               *\n *      mapeddlg.cpp:   map editor dialogs, most of the main menu options  *\n *      mapedplc.cpp:   object-placing routines                            *\n *      mapedsel.cpp:   object-selection & manipulation routines           *\n *      mapedtm.cpp:   team-editing routines                               *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   MapEditClass::AI -- The map editor's main logic                       *\n *   MapEditClass::Read_INI -- overloaded Read_INI function                *\n *   MapEditClass::AI_Menu -- menu of AI options                           *\n *   MapEditClass::Add_To_List -- adds a TypeClass to the chooseable list  *\n *   MapEditClass::Clear_List -- clears the internal chooseable object list*\n *   MapEditClass::Cycle_House -- finds next valid house for object type   *\n *   MapEditClass::Draw_It -- overloaded Redraw routine                    *\n *   MapEditClass::Fatal -- exits with error message                       *\n *   MapEditClass::Main_Menu -- main menu processor for map editor         *\n *   MapEditClass::MapEditClass -- class constructor                       *\n *   MapEditClass::Mouse_Moved -- checks for mouse motion                  *\n *   MapEditClass::One_Time -- one-time initialization                     *\n *   MapEditClass::Verify_House -- sees if given house can own given obj   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n#ifdef SCENARIO_EDITOR\n\n/*\n**\tArray of all missions supported by the map editor\n*/\nMissionType MapEditClass::MapEditMissions[] = {\n\tMISSION_GUARD,\n\tMISSION_STICKY,\n\tMISSION_HARMLESS,\n\tMISSION_HARVEST,\n\tMISSION_GUARD_AREA,\n\tMISSION_RETURN,\n\tMISSION_AMBUSH,\n\tMISSION_HUNT,\n\tMISSION_SLEEP,\n};\n#define NUM_EDIT_MISSIONS (sizeof(MapEditClass::MapEditMissions) / sizeof(MapEditClass::MapEditMissions[0]))\n\n\n/*\n**\tFor menu processing\n*/\nextern int UnknownKey;\t\t\t\t\t// in menus.cpp\n\nchar MapEditClass::HealthBuf[20];\n\n\n/***************************************************************************\n * MapEditClass::MapEditClass -- class constructor                         *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/20/1994 BR : Created.                                              *\n *=========================================================================*/\nMapEditClass::MapEditClass(void)\n{\n\t/*\n\t**\tInit data members.\n\t*/\n//\tScenVar = SCEN_VAR_A;\n\tObjCount = 0;\n\tLastChoice = 0;\n\tLastHouse = HOUSE_GOOD;\n\tGrabbedObject = 0;\n\tfor (int i=0; i < NUM_EDIT_CLASSES; i++) {\n\t\tNumType[i] = 0;\n\t\tTypeOffset[i] = 0;\n\t}\n\tScen.Waypoint[WAYPT_HOME] = 0;\n\tCurrentCell = 0;\n\tCurTeam = NULL;\n\tCurTrigger = NULL;\n\tChanged = 0;\n\tLMouseDown = 0;\n\tBaseBuilding = false;\n//\tBasePercent = 100;\n}\n\n\n/***************************************************************************\n * MapEditClass::One_Time -- one-time initialization                       *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/02/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::One_Time(void)\n{\n\tMouseClass::One_Time();\n\n\t/*\n\t**\tThe map: a single large \"button\"\n\t*/\n#ifdef WIN32\n\tMapArea = new ControlClass(MAP_AREA, 0, 8, 640-8, 400-8, GadgetClass::LEFTPRESS | GadgetClass::LEFTRELEASE, false);\n#else\n\tMapArea = new ControlClass(MAP_AREA, 0, 8, 312, 192, GadgetClass::LEFTPRESS | GadgetClass::LEFTRELEASE, false);\n#endif\n\n\t/*\n\t**\tHouse buttons\n\t*/\n\tHouseList = new ListClass(POPUP_HOUSELIST, POPUP_HOUSE_X, POPUP_HOUSE_Y, POPUP_HOUSE_W, POPUP_HOUSE_H,\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\tHouseList->Add_Item(HouseTypeClass::As_Reference(house).IniName);\n\t}\n\n\t/*\n\t**\tThe mission list box\n\t*/\n\tMissionList = new ListClass(POPUP_MISSIONLIST,\n\t\tPOPUP_MISSION_X, POPUP_MISSION_Y, POPUP_MISSION_W, POPUP_MISSION_H,\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tfor (int i = 0; i < NUM_EDIT_MISSIONS; i++) {\n\t\tMissionList->Add_Item(MissionClass::Mission_Name(MapEditMissions[i]));\n\t}\n\n\t/*\n\t**\tThe health bar\n\t*/\n\tHealthGauge = new TriColorGaugeClass(POPUP_HEALTHGAUGE,\n\t\tPOPUP_HEALTH_X, POPUP_HEALTH_Y, POPUP_HEALTH_W, POPUP_HEALTH_H);\n\tHealthGauge->Use_Thumb(true);\n\tHealthGauge->Set_Maximum(0x100);\n\tHealthGauge->Set_Red_Limit(0x3f - 1);\n\tHealthGauge->Set_Yellow_Limit(0x7f - 1);\n\n\t/*\n\t**\tThe health text label\n\t*/\n\tHealthBuf[0] = 0;\n\tHealthText = new TextLabelClass(HealthBuf,\n\t\tPOPUP_HEALTH_X + POPUP_HEALTH_W / 2,\n\t\tPOPUP_HEALTH_Y + POPUP_HEALTH_H + 1,\n\t\tGadgetClass::Get_Color_Scheme(),\n\t\tTPF_CENTER | TPF_FULLSHADOW | TPF_EFNT);\n\n\t/*\n\t**\tBuilding attribute buttons.\n\t*/\n\tSellable = new TextButtonClass(POPUP_SELLABLE, TXT_SELLABLE, TPF_EBUTTON, 320-65, 200-25, 60);\n\tRebuildable = new TextButtonClass(POPUP_REBUILDABLE, TXT_REBUILD, TPF_EBUTTON, 320-65, 200-15, 60);\n\n\t/*\n\t**\tThe facing dial\n\t*/\n\tFacingDial = new Dial8Class(POPUP_FACINGDIAL, POPUP_FACEBOX_X,\n\t\tPOPUP_FACEBOX_Y, POPUP_FACEBOX_W, POPUP_FACEBOX_H, (DirType)0);\n\n\t/*\n\t**\tThe base percent-built slider & its label\n\t*/\n\tBaseGauge = new GaugeClass(POPUP_BASEPERCENT, POPUP_BASE_X, POPUP_BASE_Y, POPUP_BASE_W, POPUP_BASE_H);\n\tBaseLabel = new TextLabelClass (\"Base:\", POPUP_BASE_X - 3, POPUP_BASE_Y, GadgetClass::Get_Color_Scheme(),\n\t\tTPF_RIGHT | TPF_NOSHADOW | TPF_EFNT);\n\tBaseGauge->Set_Maximum(100);\n\tBaseGauge->Set_Value(Scen.Percent);\n}\n\n\n/***********************************************************************************************\n * MapeditClass::Init_IO -- Reinitializes the radar map at scenario start.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MapEditClass::Init_IO(void)\n{\n\t/*\n\t**\tFor normal game mode, jump to the parent's Init routine.\n\t*/\n\tif (!Debug_Map) {\n\n\t\tMouseClass::Init_IO();\n\n\t} else {\n\n\t\t/*\n\t\t**\tFor editor mode, add the map area to the button input list\n\t\t*/\n\t\tButtons = 0;\n\t\tAdd_A_Button(*BaseGauge);\n\t\tAdd_A_Button(*BaseLabel);\n\t\tAdd_A_Button(*MapArea);\n\t}\n}\n\n\n/***************************************************************************\n * MapEditClass::Clear_List -- clears the internal chooseable object list   *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/20/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Clear_List(void)\n{\n\t/*\n\t**\tSet # object type ptrs to 0, set NumType for each type to 0\n\t*/\n\tObjCount = 0;\n\tfor (int i = 0; i < NUM_EDIT_CLASSES; i++) {\n\t\tNumType[i] = 0;\n\t}\n}\n\n\n/***************************************************************************\n * MapEditClass::Add_To_List -- adds a TypeClass to the chooseable list     *\n *                                                                         *\n * Use this routine to add an object to the game object selection list.    *\n * This list is used by the Add_Object function. All items located in the  *\n * list will appear and be chooseable by that function. Make sure to       *\n * clear the list before adding a sequence of items to it. Clearing        *\n * the list is accomplished by the Clear_List() function.                  *\n *                                                                         *\n * INPUT:                                                                  *\n *      object      ptr to ObjectTypeClass to add                          *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      bool: was the object added to the list?  A failure could occur if  *\n *      NULL were passed in or the list is full.                           *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/04/1994 JLB : Created.                                             *\n *=========================================================================*/\nbool MapEditClass::Add_To_List(ObjectTypeClass const * object)\n{\n\t/*\n\t**\tAdd the object if there's room.\n\t*/\n\tif (object && ObjCount < MAX_EDIT_OBJECTS) {\n\t\tObjects[ObjCount++] = object;\n\n\t\t/*\n\t\t**\tUpdate type counters.\n\t\t*/\n\t\tswitch (object->What_Am_I()) {\n\t\t\tcase RTTI_TEMPLATETYPE:\n\t\t\t\tNumType[0]++;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_OVERLAYTYPE:\n\t\t\t\tNumType[1]++;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_SMUDGETYPE:\n\t\t\t\tNumType[2]++;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_TERRAINTYPE:\n\t\t\t\tNumType[3]++;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_UNITTYPE:\n\t\t\t\tNumType[4]++;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_INFANTRYTYPE:\n\t\t\t\tNumType[5]++;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_VESSELTYPE:\n\t\t\t\tNumType[6]++;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_BUILDINGTYPE:\n\t\t\t\tNumType[7]++;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\t\tNumType[8]++;\n\t\t\t\tbreak;\n\t\t}\n\t\treturn(true);\n\t}\n\n\treturn(false);\n}\n\n\n/***************************************************************************\n * MapEditClass::AI -- The map editor's main logic                         *\n *                                                                         *\n * This routine overloads the parent's (DisplayClass) AI function.         *\n * It checks for any input specific to map editing, and calls the parent   *\n * AI routine to handle scrolling and other mainstream map stuff.          *\n *                                                                         *\n * If this detects one of its special input keys, it sets 'input' to 0     *\n * before calling the parent AI routine; this prevents input conflict.     *\n *                                                                         *\n * SUPPORTED INPUT:                                                        *\n * General:                                                                *\n *      F2/RMOUSE:            main menu                                    *\n *      F6:                  toggles show-passable mode                    *\n *      HOME:                  go to the Home Cell (scenario's start position)*\n *      SHIFT-HOME:            set the Home Cell to the current TacticalCell*\n *      ESC:                  exits to DOS                                 *\n * Object Placement:                                                       *\n *      INSERT:               go into placement mode                       *\n *      ESC:                  exit placement mode                          *\n *      LEFT/RIGHT:          prev/next placement object                    *\n *      PGUP/PGDN:            prev/next placement category                 *\n *      HOME:                  1st placement object (clear template)       *\n *      h/H:                  toggle house of placement object             *\n *      LMOUSE:               place the placement object                   *\n *      MOUSE MOTION:         \"paint\" with the placement object            *\n * Object selection:                                                       *\n *      LMOUSE:               select & \"grab\" current object               *\n *                           If no object is present where the mouse is    *\n *                           clicked, the current object is de-selected    *\n *                           If the same object is clicked on, it stays    *\n *                           selected. Also displays the object-editing    *\n *                           gadgets.                                      *\n *      LMOUSE RLSE:         release currently-grabbed object              *\n *      MOUSE MOTION:         if an object is grabbed, moves the object    *\n *      SHIFT|ALT|ARROW:      moves object in that direction               *\n *      DELETE               deletes currently-selected object             *\n * Object-editing controls:                                                *\n *      POPUP_GDI:            makes GDI the owner of this object           *\n *      POPUP_NOD:            makes NOD the owner of this object           *\n *      POPUP_MISSIONLIST:   sets that mission for this object             *\n *      POPUP_HEALTHGAUGE:   sets that health value for this object        *\n *      POPUP_FACINGDIAL:      sets the object's facing                    *\n *                                                                         *\n * Changed is set when you:                                                *\n *      - place an object                                                  *\n *      - move a grabbed object                                            *\n *      - delete an object                                                 *\n *      - size the map                                                     *\n *      - create a new scenario                                            *\n *   Changed is cleared when you:                                          *\n *      - Save the scenario                                                *\n *      - Load a scenario                                                  *\n *      - Play the scenario                                                *\n *                                                                         *\n * INPUT:                                                                  *\n *      input      KN_ value, 0 if none                                    *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/20/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::AI(KeyNumType & input, int x, int y)\n{\n\tint rc;\n\tMissionType mission;\n\tint strength;\n\tCELL cell;\n\tint i;\n\tint found;\t\t\t\t\t\t\t\t\t// for removing a waypoint label\n\tint waypt_idx;\t\t\t\t\t\t\t\t// for labelling a waypoint\n\tBaseNodeClass * node;\t\t\t\t\t\t// for removing from an AI Base\n\tHousesType house;\n\tchar wayname[4];\n\n\t/*\n\t**\tTrap 'F2' regardless of whether we're in game or editor mode\n\t*/\n\tif (Debug_Flag) {\n\t\tif ((input == KN_F2 && Session.Type == GAME_NORMAL) || input == (KN_F2 | KN_CTRL_BIT)) {\n\t\t\tScenarioInit = 0;\n\n\t\t\t/*\n\t\t\t** If we're in editor mode & Changed is set, prompt for saving changes\n\t\t\t*/\n\t\t\tif (Debug_Map && Changed) {\n\t\t\t\trc = WWMessageBox().Process(\"Save Changes?\", TXT_YES, TXT_NO);\n\t\t\t\tHidPage.Clear();\n\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\tRender();\n\n\t\t\t\t/*\n\t\t\t\t**\tUser wants to save\n\t\t\t\t*/\n\t\t\t\tif (rc == 0) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf save cancelled, abort game\n\t\t\t\t\t*/\n\t\t\t\t\tif (Save_Scenario()!=0) {\n\t\t\t\t\t\tinput = KN_NONE;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tChanged = 0;\n\t\t\t\t\t\tGo_Editor(!Debug_Map);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tUser doesn't want to save\n\t\t\t\t\t*/\n\t\t\t\t\tGo_Editor(!Debug_Map);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t** If we're in game mode, set Changed to 0 (so if we didn't save our\n\t\t\t\t** changes above, they won't keep coming back to haunt us with continual\n\t\t\t\t** Save Changes? prompts!)\n\t\t\t\t*/\n\t\t\t\tif (!Debug_Map) {\n\t\t\t\t\tChanged = 0;\n\t\t\t\t}\n\t\t\t\tBaseGauge->Set_Value(Scen.Percent);\n\t\t\t\tGo_Editor(!Debug_Map);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tFor normal game mode, jump to the parent's AI routine.\n\t*/\n\tif (!Debug_Map) {\n\t\tMouseClass::AI(input, x, y);\n\t\treturn;\n\t}\n\n\t::Frame++;\n\n\t/*\n\t**\tDo special mouse processing if the mouse is over the map\n\t*/\n\tif (Get_Mouse_X() > TacPixelX && Get_Mouse_X() <\n\t\tTacPixelX + Lepton_To_Pixel(TacLeptonWidth) &&\n\t\tGet_Mouse_Y() > TacPixelY && Get_Mouse_Y() <\n\t\tTacPixelY + Lepton_To_Pixel(TacLeptonHeight)) {\n\n\t\t/*\n\t\t**\tWhen the mouse moves over a scrolling edge, ScrollClass changes its\n\t\t**\tshape to the appropriate arrow or NO symbol; it's our job to change it\n\t\t**\tback to normal (or whatever the shape is set to by Set_Default_Mouse())\n\t\t**\twhen it re-enters the map area.\n\t\t*/\n\t\tif (CurTrigger) {\n\t\t\tOverride_Mouse_Shape(MOUSE_CAN_MOVE);\n\t\t} else {\n\t\t\tOverride_Mouse_Shape(MOUSE_NORMAL);\n\t\t}\n\t}\n\n\t/*\n\t**\tSet 'ZoneCell' to track the mouse cursor around over the map.  Do this\n\t**\teven if the map is scrolling.\n\t*/\n\tif (Get_Mouse_X() >= TacPixelX && Get_Mouse_X() <=\n\t\tTacPixelX + Lepton_To_Pixel(TacLeptonWidth) &&\n\t\tGet_Mouse_Y() >= TacPixelY && Get_Mouse_Y() <=\n\t\tTacPixelY + Lepton_To_Pixel(TacLeptonHeight)) {\n\n\t\tcell = Click_Cell_Calc(Get_Mouse_X(), Get_Mouse_Y());\n\t\tif (cell != -1) {\n\t\t\tSet_Cursor_Pos(cell);\n\t\t\tif (PendingObject) {\n\t\t\t\tFlag_To_Redraw(true);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck for mouse motion while left button is down.\n\t*/\n\trc = Mouse_Moved();\n\tif (LMouseDown && rc) {\n\n\t\t/*\n\t\t**\t\"Paint\" mode: place current object, and restart placement\n\t\t*/\n\t\tif (PendingObject) {\n\t\t\tFlag_To_Redraw(true);\n\t\t\tif (Place_Object() == 0) {\n\t\t\t\tChanged = 1;\n\t\t\t\tStart_Placement();\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tMove the currently-grabbed object\n\t\t\t*/\n\t\t\tif (GrabbedObject) {\n\t\t\t\tGrabbedObject->Mark(MARK_CHANGE);\n\t\t\t\tif (Move_Grabbed_Object() == 0) {\n\t\t\t\t\tChanged = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tTrap special editing keys; if one is detected, set 'input' to 0 to\n\t**\tprevent a conflict with parent's AI().\n\t*/\n\tswitch (input) {\n\t\t/*\n\t\t** F2/RMOUSE = pop up main menu\n\t\t*/\n\t\tcase KN_RMOUSE:\n\n\t\t\t/*\n\t\t\t**\tTurn off placement mode\n\t\t\t*/\n\t\t\tif (PendingObject) {\n\t\t\t\tif (BaseBuilding) {\n\t\t\t\t\tCancel_Base_Building();\n\t\t\t\t} else {\n\t\t\t\t\tCancel_Placement();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tTurn off trigger placement mode\n\t\t\t*/\n\t\t\tif (CurTrigger) {\n\t\t\t\tStop_Trigger_Placement();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tUnselect object & hide popup controls\n\t\t\t*/\n\t\t\tif (CurrentObject.Count()) {\n\t\t\t\tCurrentObject[0]->Unselect();\n\t\t\t\tPopup_Controls();\n\t\t\t}\n\t\t\tMain_Menu();\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tF6 = toggle passable/impassable display\n\t\t*/\n\t\tcase KN_F6:\n\t\t\tDebug_Passable = (Debug_Passable == false);\n\t\t\tHidPage.Clear();\n\t\t\tFlag_To_Redraw(true);\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tINSERT = go into object-placement mode\n\t\t*/\n\t\tcase KN_INSERT:\n\t\t\tif (!PendingObject) {\n\t\t\t\t/*\n\t\t\t\t**\tUnselect current object, hide popup controls\n\t\t\t\t*/\n\t\t\t\tif (CurrentObject.Count()) {\n\t\t\t\t\tCurrentObject[0]->Unselect();\n\t\t\t\t\tPopup_Controls();\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tGo into placement mode\n\t\t\t\t*/\n\t\t\t\tStart_Placement();\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tESC = exit placement mode, or exit to DOS\n\t\t*/\n\t\tcase KN_ESC:\n\n\t\t\t/*\n\t\t\t**\tExit object placement mode\n\t\t\t*/\n\t\t\tif (PendingObject) {\n\t\t\t\tif (BaseBuilding) {\n\t\t\t\t\tCancel_Base_Building();\n\t\t\t\t} else {\n\t\t\t\t\tCancel_Placement();\n\t\t\t\t}\n\t\t\t\tinput = KN_NONE;\n\t\t\t\tbreak;\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tExit trigger placement mode\n\t\t\t\t*/\n\t\t\t\tif (CurTrigger) {\n\t\t\t\t\tStop_Trigger_Placement();\n\t\t\t\t\tinput = KN_NONE;\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\trc = WWMessageBox().Process(\"Exit Scenario Editor?\", TXT_YES, TXT_NO);\n\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\tRender();\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tUser doesn't want to exit; return to editor\n\t\t\t\t\t*/\n\t\t\t\t\tif (rc==1) {\n\t\t\t\t\t\tinput = KN_NONE;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf changed, prompt for saving\n\t\t\t\t\t*/\n\t\t\t\t\tif (Changed) {\n\t\t\t\t\t\trc = WWMessageBox().Process(\"Save Changes?\", TXT_YES, TXT_NO);\n\t\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\t\tRender();\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tUser wants to save\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (rc == 0) {\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf save cancelled, abort exit\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Save_Scenario()!=0) {\n\t\t\t\t\t\t\t\tinput = KN_NONE;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tChanged = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t//Prog_End();\n\t\t\tEmergency_Exit(0);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tLEFT = go to previous placement object\n\t\t*/\n\t\tcase KN_LEFT:\n\t\t\tif (PendingObject) {\n\t\t\t\tPlace_Prev();\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tRIGHT = go to next placement object\n\t\t*/\n\t\tcase KN_RIGHT:\n\t\t\tif (PendingObject) {\n\t\t\t\tPlace_Next();\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tPGUP = go to previous placement category\n\t\t*/\n\t\tcase KN_PGUP:\n\t\t\tif (PendingObject) {\n\t\t\t\tPlace_Prev_Category();\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tPGDN = go to next placement category\n\t\t*/\n\t\tcase KN_PGDN:\n\t\t\tif (PendingObject) {\n\t\t\t\tPlace_Next_Category();\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tHOME = jump to first placement object, or go to Home Cell\n\t\t*/\n\t\tcase KN_HOME:\n\t\t\tif (PendingObject) {\n\t\t\t\tPlace_Home();\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tSet map position\n\t\t\t\t*/\n\t\t\t\tScenarioInit++;\n\t\t\t\tSet_Tactical_Position(Scen.Waypoint[WAYPT_HOME]);\n\t\t\t\tScenarioInit--;\n\n\t\t\t\t/*\n\t\t\t\t**\tForce map to redraw\n\t\t\t\t*/\n\t\t\t\tHidPage.Clear();\n\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\tRender();\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tSHIFT-HOME: set new Home Cell position\n\t\t*/\n\t\tcase ((int)KN_HOME | (int)KN_SHIFT_BIT):\n\t\t\tif (CurrentCell != 0) {\n\n\t\t\t/*\n\t\t\t** Unflag the old Home Cell, if there are no other waypoints\n\t\t\t** pointing to it\n\t\t\t*/\n\t\t\tcell = Scen.Waypoint[WAYPT_HOME];\n\n\t\t\tif (cell != -1) {\n\t\t\t\tfound = 0;\n\t\t\t\tfor (i = 0; i < WAYPT_COUNT; i++) {\n\t\t\t\t\tif (i != WAYPT_HOME && Scen.Waypoint[i]==cell) {\n\t\t\t\t\t\tfound = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (found==0) {\n\t\t\t\t\t(*this)[cell].IsWaypoint = 0;\n\t\t\t\t\tFlag_Cell(cell);\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Now set the new Home cell\n\t\t\t*/\n//\t\t\tScen.Waypoint[WAYPT_HOME] = Coord_Cell(TacticalCoord);\n//\t\t\t(*this)[TacticalCoord].IsWaypoint = 1;\n//\t\t\tFlag_Cell(Coord_Cell(TacticalCoord));\n\t\t\tScen.Waypoint[WAYPT_HOME] = CurrentCell;\n\t\t\t(*this)[CurrentCell].IsWaypoint = 1;\n\t\t\tFlag_Cell(CurrentCell);\n\n\t\t\tChanged = 1;\n\t\t\tinput = KN_NONE;\n}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tSHIFT-R: set new Reinforcement Cell position.  Don't allow setting\n\t\t**\tthe Reinf. Cell to the same as the Home Cell (for display purposes.)\n\t\t*/\n\t\tcase ((int)KN_R | (int)KN_SHIFT_BIT):\n\t\t\tif (CurrentCell==0 || CurrentCell==Scen.Waypoint[WAYPT_HOME]) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Unflag the old Reinforcement Cell, if there are no other waypoints\n\t\t\t** pointing to it\n\t\t\t*/\n\t\t\tcell = Scen.Waypoint[WAYPT_REINF];\n\n\t\t\tif (cell != -1) {\n\t\t\t\tfound = 0;\n\t\t\t\tfor (i = 0; i < WAYPT_COUNT; i++) {\n\t\t\t\t\tif (i != WAYPT_REINF && Scen.Waypoint[i]==cell) {\n\t\t\t\t\t\tfound = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (found==0) {\n\t\t\t\t\t(*this)[cell].IsWaypoint = 0;\n\t\t\t\t\tFlag_Cell(cell);\n\t\t\t\t}\n\n\t\t\t}\n\t\t\t/*\n\t\t\t** Now set the new Reinforcement cell\n\t\t\t*/\n\t\t\tScen.Waypoint[WAYPT_REINF] = CurrentCell;\n\t\t\t(*this)[CurrentCell].IsWaypoint = 1;\n\t\t\tFlag_Cell(CurrentCell);\n\t\t\tChanged = 1;\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tALT-Letter: Label a waypoint cell\n\t\t*/\n\t\tcase ((int)KN_A | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_B | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_C | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_D | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_E | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_F | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_G | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_H | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_I | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_J | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_K | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_L | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_M | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_N | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_O | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_P | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_Q | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_R | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_S | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_T | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_U | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_V | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_W | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_X | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_Y | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_Z | (int)KN_ALT_BIT):\n\t\t\tif (CurrentCell != 0) {\n#ifdef WIN32\n\t\t\t\twaypt_idx = (input & ~KN_ALT_BIT) - KN_A;\n#else\n\t\t\t\twaypt_idx = KN_To_KA(input & 0x00ff) - KA_a;\n#endif\n\t\t\t\tUpdate_Waypoint(waypt_idx);\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t** ALT-. : Designate an extended (2-letter) waypoint name\n\t\t*/\n\t\tcase KN_PERIOD:\n\t\tcase ((int)KN_PERIOD | (int)KN_ALT_BIT):\n\t\t\tif (CurrentCell != 0 && Get_Waypoint_Name(wayname)) {\n\t\t\t\tint waynm = 0;\n\t\t\t\tif (strlen(wayname)) {\n\t\t\t\t\twayname[0] = toupper(wayname[0]);\n\t\t\t\t\twayname[1] = toupper(wayname[1]);\n\t\t\t\t\tif (wayname[0] >= 'A' && wayname[0] <= 'Z') {\n\t\t\t\t\t\twaynm = wayname[0] - 'A';\n\t\t\t\t\t\tif (wayname[1] >= 'A' && wayname[1] <= 'Z') {\n\t\t\t\t\t\t\twaynm = (waynm+1)*26 + (wayname[1] - 'A');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (waynm < WAYPT_HOME) Update_Waypoint(waynm);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n#ifdef OBSOLETE\n\t\t/*\n\t\t**\tALT-1-4: Designate a cell as a capture-the-flag cell.\n\t\t*/\n\t\tcase ((int)KN_1 | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_2 | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_3 | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_4 | (int)KN_ALT_BIT):\n\n\t\t\t/*\n\t\t\t**\tIf there's a current cell, place the flag & waypoint there.\n\t\t\t*/\n\t\t\tif (CurrentCell != 0) {\n\t\t\t\twaypt_idx = (Keyboard->To_ASCII((KeyNumType)(input & 0xff)) - KA_1);\n//\t\t\t\twaypt_idx = (KN_To_KA(input & 0xff) - KA_1);\n\t\t\t\thouse = (HousesType)(HOUSE_MULTI1 + waypt_idx);\n\t\t\t\tif (HouseClass::As_Pointer(house)) {\n\t\t\t\t\tHouseClass::As_Pointer(house)->Flag_Attach(CurrentCell, true);\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf there's a current object, attach the flag to it and clear the\n\t\t\t\t**\twaypoint.\n\t\t\t\t*/\n\t\t\t\tif (CurrentObject[0] != 0) {\n\t\t\t\t\twaypt_idx = (Keyboard->To_ASCII((KeyNumType)(input & 0xff)) - KA_1);\n\t\t\t\t\thouse = (HousesType)(HOUSE_MULTI1 + waypt_idx);\n\t\t\t\t\tif (HouseClass::As_Pointer(house) && CurrentObject[0]->What_Am_I() == RTTI_UNIT) {\n\t\t\t\t\t\tHouseClass::As_Pointer(house)->Flag_Attach((UnitClass *)CurrentObject[0], true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n#endif\n\n\t\t/*\n\t\t**\tALT-Space: Remove a waypoint designation\n\t\t*/\n\t\tcase ((int)KN_SPACE | (int)KN_ALT_BIT):\n\t\t\tif (CurrentCell != 0) {\n\n\t\t\t\t/*\n\t\t\t\t**\tLoop through letter waypoints; if this cell is one of them,\n\t\t\t\t**\tclear that waypoint.\n\t\t\t\t*/\n\t\t\t\tfor (i = 0 ; i < WAYPT_HOME; i++) {\n\t\t\t\t\tif (Scen.Waypoint[i]==CurrentCell)\n\t\t\t\t\t\tScen.Waypoint[i] = -1;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tLoop through flag home values; if this cell is one of them, clear\n\t\t\t\t**\tthat waypoint.\n\t\t\t\t*/\n\t\t\t\tfor (i = 0; i < MAX_PLAYERS; i++) {\n\t\t\t\t\thouse = (HousesType)(HOUSE_MULTI1 + i);\n\t\t\t\t\tif (HouseClass::As_Pointer(house) &&\n\t\t\t\t\t\tCurrentCell == HouseClass::As_Pointer(house)->FlagHome)\n\t\t\t\t\tHouseClass::As_Pointer(house)->Flag_Remove(As_Target(CurrentCell), true);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf there are no more waypoints on this cell, clear the cell's\n\t\t\t\t**\twaypoint designation.\n\t\t\t\t*/\n\t\t\t\tif (Scen.Waypoint[WAYPT_HOME]!=CurrentCell &&\n\t\t\t\t\tScen.Waypoint[WAYPT_REINF]!=CurrentCell)\n\t\t\t\t\t(*this)[CurrentCell].IsWaypoint = 0;\n\t\t\t\tChanged = 1;\n\t\t\t\tFlag_Cell(CurrentCell);\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\t'H' = toggle current placement object's house\n\t\t*/\n\t\tcase KN_H:\n\t\tcase ((int)KN_H | (int)KN_SHIFT_BIT):\n\t\t\tif (PendingObject) {\n\t\t\t\tToggle_House();\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tLeft-mouse click:\n\t\t**\tButton DOWN:\n\t\t**\t- Toggle LMouseDown\n\t\t**\t- If we're in placement mode, try to place the current object\n\t\t**\t- If success, re-enter placement mode\n\t\t**\t- Otherwise, try to select an object, and \"grab\" it if there is one\n\t\t**\t- If no object, then select that cell as the \"current\" cell\n\t\t**\tButton UP:\n\t\t**\t- Toggle LMouseDown\n\t\t**\t- release any grabbed object\n\t\t*/\n\t\tcase ((int)MAP_AREA | (int)KN_BUTTON):\n\n\t\t\t/*\n\t\t\t**\tLeft Button DOWN\n\t\t\t*/\n\t\t\tif (Keyboard->Down(KN_LMOUSE)) {\n\t\t\t\tLMouseDown = 1;\n\n\t\t\t\t/*\n\t\t\t\t**\tPlacement mode: place an object\n\t\t\t\t*/\n\t\t\t\tif (PendingObject) {\n\t\t\t\t\tif (Place_Object()==0) {\n\t\t\t\t\t\tChanged = 1;\n\t\t\t\t\t\tStart_Placement();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tPlace a trigger\n\t\t\t\t\t*/\n\t\t\t\t\tif (CurTrigger) {\n\t\t\t\t\t\tPlace_Trigger();\n\t\t\t\t\t\tChanged = 1;\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tSelect an object or a cell\n\t\t\t\t\t\t**\tCheck for double-click\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (CurrentObject.Count() &&\n\t\t\t\t\t\t\t((TickCount - LastClickTime) < 15)) {\n\t\t\t\t\t\t;\t// stub\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tSingle-click: select object\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Select_Object()==0) {\n\t\t\t\t\t\t\t\tCurrentCell = 0;\n\t\t\t\t\t\t\t\tGrab_Object();\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t**\tNo object: select the cell\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tCurrentCell = Click_Cell_Calc(Keyboard->MouseQX, Keyboard->MouseQY);\n\t\t\t\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\t\t\t\tRender();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tLastClickTime = TickCount();\n\t\t\t\tinput = KN_NONE;\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tLeft Button UP\n\t\t\t\t*/\n\t\t\t\tLMouseDown = 0;\n\t\t\t\tGrabbedObject = 0;\n\t\t\t\tinput = KN_NONE;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tSHIFT-ALT-Arrow: move the current object\n\t\t*/\n\t\tcase (int)KN_UP | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:\n\t\tcase (int)KN_DOWN | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:\n\t\tcase (int)KN_LEFT | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:\n\t\tcase (int)KN_RIGHT | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:\n\t\t\tif (CurrentObject.Count()) {\n\t\t\t\tCurrentObject[0]->Move(KN_To_Facing(input));\n\t\t\t\tChanged = 1;\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tDELETE: delete currently-selected object\n\t\t*/\n\t\tcase KN_DELETE:\n\n\t\t\t/*\n\t\t\t**\tDelete currently-selected object's trigger, or the object\n\t\t\t*/\n\t\t\tif (CurrentObject.Count()) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDelete trigger\n\t\t\t\t*/\n\t\t\t\tif (CurrentObject[0]->Trigger.Is_Valid()) {\n\t\t\t\t\tCurrentObject[0]->Trigger = NULL;\n\t\t\t\t} else {\n\t\t\t\t\t/*\n\t\t\t\t\t** If the current object is part of the AI's Base, remove it\n\t\t\t\t\t** from the Base's Node list.\n\t\t\t\t\t*/\n\t\t\t\t\tif (CurrentObject[0]->What_Am_I()==RTTI_BUILDING &&\n\t\t\t\t\t\tBase.Is_Node((BuildingClass *)CurrentObject[0])) {\n\t\t\t\t\t\tnode = Base.Get_Node((BuildingClass *)CurrentObject[0]);\n\t\t\t\t\t\tBase.Nodes.Delete(*node);\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDelete current object\n\t\t\t\t\t*/\n\t\t\t\t\tdelete CurrentObject[0];\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tHide the popup controls\n\t\t\t\t\t*/\n\t\t\t\t\tPopup_Controls();\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tForce a redraw\n\t\t\t\t*/\n\t\t\t\tHidPage.Clear();\n\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\tChanged = 1;\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tRemove trigger from current cell\n\t\t\t\t*/\n\t\t\t\tif (CurrentCell) {\n\t\t\t\t\tif ((*this)[CurrentCell].Trigger.Is_Valid()) {\n\t\t\t\t\t\t(*this)[CurrentCell].Trigger = NULL;\n//\t\t\t\t\t\tCellTriggers[CurrentCell] = NULL;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tForce a redraw\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\t\tChanged = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tTAB: select next object on the map\n\t\t*/\n\t\tcase KN_TAB:\n\t\t\tSelect_Next();\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tObject-Editing button: House Button\n\t\t*/\n\t\tcase POPUP_HOUSELIST|KN_BUTTON:\n\t\t\t/*\n\t\t\t**\tDetermine the house desired by examining the currently\n\t\t\t**\tselected index in the house list gadget.\n\t\t\t*/\n\t\t\thouse = HousesType(((ListClass *)Buttons->Extract_Gadget(POPUP_HOUSELIST))->Current_Index());\n\n\t\t\t/*\n\t\t\t**\tIf that house doesn't own this object, try to transfer it\n\t\t\t*/\n\t\t\tif (CurrentObject[0]->Owner() != house) {\n\t\t\t\tif (Change_House(house)) {\n\t\t\t\t\tChanged = 1;\n\t\t\t\t}\n\t\t\t}\n//\t\t\tSet_House_Buttons(CurrentObject[0]->Owner(), Buttons, POPUP_FIRST);\n\t\t\tHidPage.Clear();\n\t\t\tButtons->Flag_List_To_Redraw();\n\t\t\tFlag_To_Redraw(true);\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n//\t\tcase (POPUP_GDI | KN_BUTTON):\n//\t\tcase (POPUP_NOD | KN_BUTTON):\n//\t\tcase (POPUP_NEUTRAL | KN_BUTTON):\n//\t\tcase (POPUP_MULTI1 | KN_BUTTON):\n//\t\tcase (POPUP_MULTI2 | KN_BUTTON):\n//\t\tcase (POPUP_MULTI3 | KN_BUTTON):\n//\t\tcase (POPUP_MULTI4 | KN_BUTTON):\n//\n//\t\t\t/*\n//\t\t\t**\tConvert input value into a house value; assume HOUSE_GOOD is 0\n//\t\t\t*/\n//\t\t\thouse = (HousesType)( (input & (~KN_BUTTON)) - POPUP_FIRST);\n//\n//\t\t\t/*\n//\t\t\t**\tIf that house doesn't own this object, try to transfer it\n//\t\t\t*/\n//\t\t\tif (CurrentObject[0]->Owner()!=house) {\n//\t\t\t\tif (Change_House(house)) {\n//\t\t\t\t\tChanged = 1;\n//\t\t\t\t}\n//\t\t\t}\n//\t\t\tSet_House_Buttons(CurrentObject[0]->Owner(), Buttons, POPUP_FIRST);\n//\t\t\tHidPage.Clear();\n//\t\t\tFlag_To_Redraw(true);\n//\t\t\tinput = KN_NONE;\n//\t\t\tbreak;\n\n\t\tcase POPUP_SELLABLE|KN_BUTTON:\n\t\t\tif (CurrentObject[0]->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\tBuildingClass * building = (BuildingClass *)CurrentObject[0];\n\n\t\t\t\tif (building->Class->Level != -1) {\n//\t\t\t\tif (building->Class->IsBuildable) {\n\t\t\t\t\tbuilding->IsAllowedToSell = (building->IsAllowedToSell == false);\n\t\t\t\t\tbuilding->Mark(MARK_CHANGE);\n\t\t\t\t}\n\t\t\t\tif (building->IsAllowedToSell) {\n\t\t\t\t\tSellable->Turn_On();\n\t\t\t\t} else {\n\t\t\t\t\tSellable->Turn_Off();\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase POPUP_REBUILDABLE|KN_BUTTON:\n\t\t\tif (CurrentObject[0]->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\tBuildingClass * building = (BuildingClass *)CurrentObject[0];\n\n\t\t\t\tif (building->Class->Level != -1) {\n//\t\t\t\tif (building->Class->IsBuildable) {\n\t\t\t\t\tbuilding->IsToRebuild = (building->IsToRebuild == false);\n\t\t\t\t\tbuilding->Mark(MARK_CHANGE);\n\t\t\t\t}\n\t\t\t\tif (building->IsToRebuild) {\n\t\t\t\t\tRebuildable->Turn_On();\n\t\t\t\t} else {\n\t\t\t\t\tRebuildable->Turn_Off();\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tObject-Editing button: Mission\n\t\t*/\n\t\tcase (POPUP_MISSIONLIST | KN_BUTTON):\n\t\t\tif (CurrentObject[0]->Is_Techno()) {\n\t\t\t\t/*\n\t\t\t\t**\tSet new mission\n\t\t\t\t*/\n\t\t\t\tmission = MapEditMissions[MissionList->Current_Index()];\n\t\t\t\tif (CurrentObject[0]->Get_Mission() != mission) {\n\t\t\t\t\t((TechnoClass *)CurrentObject[0])->Set_Mission(mission);\n\t\t\t\t\tChanged = 1;\n\t\t\t\t\tButtons->Flag_List_To_Redraw();\n\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t}\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tObject-Editing button: Health\n\t\t*/\n\t\tcase (POPUP_HEALTHGAUGE | KN_BUTTON):\n\t\t\tif (CurrentObject[0]->Is_Techno()) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDerive strength from current gauge reading\n\t\t\t\t*/\n\t\t\t\tstrength = CurrentObject[0]->Class_Of().MaxStrength * fixed(HealthGauge->Get_Value(), 256);\n//\t\t\t\tstrength = Fixed_To_Cardinal((unsigned)CurrentObject[0]->Class_Of().MaxStrength, (unsigned)HealthGauge->Get_Value());\n\n\t\t\t\t/*\n\t\t\t\t**\tClip to 1\n\t\t\t\t*/\n\t\t\t\tif (strength <= 0) {\n\t\t\t\t\tstrength = 1;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tSet new strength\n\t\t\t\t*/\n\t\t\t\tif (strength != CurrentObject[0]->Strength) {\n\t\t\t\t\tCurrentObject[0]->Strength = strength;\n\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\tChanged = 1;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tUpdate text label\n\t\t\t\t*/\n\t\t\t\tsprintf(HealthBuf, \"%d\", strength);\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tObject-Editing button: Facing\n\t\t*/\n\t\tcase (POPUP_FACINGDIAL | KN_BUTTON):\n\t\t\tif (CurrentObject[0]->Is_Techno()) {\n\n\t\t\t\t/*\n\t\t\t\t**\tSet new facing\n\t\t\t\t*/\n\t\t\t\tif (FacingDial->Get_Direction() !=\n\t\t\t\t\t((TechnoClass *)CurrentObject[0])->PrimaryFacing.Get()) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSet body's facing\n\t\t\t\t\t*/\n\t\t\t\t\t((TechnoClass *)CurrentObject[0])->PrimaryFacing.Set(FacingDial->Get_Direction());\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSet turret facing, if there is one\n\t\t\t\t\t*/\n\t\t\t\t\tif (CurrentObject[0]->What_Am_I()==RTTI_UNIT) {\n\t\t\t\t\t\t((UnitClass *)CurrentObject[0])->SecondaryFacing.Set(FacingDial->Get_Direction());\n\t\t\t\t\t}\n\n\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\tChanged = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tObject-Editing button: Facing\n\t\t*/\n\t\tcase (POPUP_BASEPERCENT | KN_BUTTON):\n\t\t\tif (BaseGauge->Get_Value() != Scen.Percent) {\n\t\t\t\tScen.Percent = BaseGauge->Get_Value();\n\t\t\t\tBuild_Base_To(Scen.Percent);\n\t\t\t\tHidPage.Clear();\n\t\t\t\tFlag_To_Redraw(true);\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tCall parent's AI routine\n\t*/\n\tMouseClass::AI(input, x, y);\n}\n\n\n/***************************************************************************\n * MapEditClass::Draw_It -- overloaded Redraw routine                      *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/17/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Draw_It(bool forced)\n{\n\tchar const * label;\n\tchar buf[40];\n\tchar const * tptr;\n\n\tMouseClass::Draw_It(forced);\n\n\tif (!Debug_Map) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tDisplay the total value of all Tiberium on the map.\n\t*/\n\tFancy_Text_Print(\"Tiberium=%ld   \", 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tBLACK, TPF_EFNT | TPF_NOSHADOW, TotalValue);\n\n\t/*\n\t**\tIf there are no object controls displayed, just invoke parent's Redraw\n\t**\tand return.\n\t*/\n\tif (!Buttons) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tOtherwise, if 'display' is set, invoke the parent's Redraw to refresh\n\t**\tthe HIDPAGE; then, update the buttons & text labels onto HIDPAGE;\n\t**\tthen invoke the parent's Redraw to blit the HIDPAGE to SEENPAGE.\n\t*/\n\tif (forced) {\n\n\t\t/*\n\t\t**\tUpdate the text labels\n\t\t*/\n\t\tif (CurrentObject.Count()) {\n\t\t\t/*\n\t\t\t**\tDisplay the object's name & ID\n\t\t\t*/\n\t\t\tlabel = Text_String(CurrentObject[0]->Full_Name());\n\t\t\ttptr = label;\n\t\t\tsprintf(buf, \"%s (%d)\", tptr, CurrentObject[0]->As_Target());\n\n\t\t\t/*\n\t\t\t**\tprint the label\n\t\t\t*/\n\t\t\tFancy_Text_Print (buf, 160, 0,\n\t\t\t\t&ColorRemaps[PCOLOR_BROWN], TBLACK,\n\t\t\t\tTPF_CENTER | TPF_NOSHADOW | TPF_EFNT);\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * MapEditClass::Mouse_Moved -- checks for mouse motion                    *\n *                                                                         *\n * Reports whether the mouse has moved or not. This varies based on the    *\n * type of object currently selected. If there's an infantry object        *\n *   selected, mouse motion counts even within a cell; for all other types,*\n *   mouse motion counts only if the mouse changes cells.                  *\n *                                                                         *\n *   The reason this routine is needed is to prevent Paint-Mode from putting*\n *   gobs of trees and such into the same cell if the mouse moves just     *\n *   a little bit.                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/08/1994 BR : Created.                                              *\n *=========================================================================*/\nbool MapEditClass::Mouse_Moved(void)\n{\n\tstatic int old_mx = 0;\n\tstatic int old_my = 0;\n\tstatic CELL old_zonecell = 0;\n\tconst ObjectTypeClass * objtype = NULL;\n\tbool retcode = false;\n\n\t/*\n\t**\tReturn if no motion\n\t*/\n\tif (old_mx == Get_Mouse_X() && old_my == Get_Mouse_Y()) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tGet a ptr to ObjectTypeClass\n\t*/\n\tif (PendingObject) {\n\t\tobjtype = PendingObject;\n\t} else {\n\t\tif (GrabbedObject) {\n\t\t\tobjtype = &GrabbedObject->Class_Of();\n\t\t} else {\n\t\t\told_mx = Get_Mouse_X();\n\t\t\told_my = Get_Mouse_Y();\n\t\t\told_zonecell = ZoneCell;\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tInfantry: mouse moved if any motion at all\n\t*/\n\tif (objtype->What_Am_I() == RTTI_INFANTRYTYPE) {\n\t\tretcode = true;\n\t} else {\n\t\t/*\n\t\t**\tOthers: mouse moved only if cell changed\n\t\t*/\n\t\tif (old_zonecell!=ZoneCell) {\n\t\t\tretcode = true;\n\t\t} else {\n\t\t\tretcode = false;\n\t\t}\n\t}\n\n\told_mx = Get_Mouse_X();\n\told_my = Get_Mouse_Y();\n\told_zonecell = ZoneCell;\n\treturn(retcode);\n}\n\n\n/***************************************************************************\n * MapEditClass::Main_Menu -- main menu processor for map editor           *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/20/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Main_Menu(void)\n{\n\tchar const * _menus[MAX_MAIN_MENU_NUM + 1];\n\tint selection;\t\t\t\t\t\t// option the user picks\n\tbool process;\t\t\t\t\t\t// menu stays up while true\n\tint rc;\n\n\t/*\n\t**\tFill in menu items\n\t*/\n\t_menus[0] = \"New Scenario\";\n\t_menus[1] = \"Load Scenario\";\n\t_menus[2] = \"Save Scenario\";\n\t_menus[3] = \"Size Map\";\n\t_menus[4] = \"Add Game Object\";\n\t_menus[5] = \"Scenario Options\";\n\t_menus[6] = \"AI Options\";\n\t_menus[7] = \"Play Scenario\";\n\t_menus[8] = NULL;\n\n\t/*\n\t**\tMain Menu loop\n\t*/\n\tOverride_Mouse_Shape(MOUSE_NORMAL);\t// display default mouse cursor\n\tprocess = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback, to update music\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tInvoke menu\n\t\t*/\n\t\tHide_Mouse();\t\t// Do_Menu assumes the mouse is already hidden\n\t\tselection = Do_Menu(&_menus[0], true);\n\t\tShow_Mouse();\n\t\tif (UnknownKey==KN_ESC || UnknownKey==KN_LMOUSE || UnknownKey==KN_RMOUSE) {\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tProcess selection\n\t\t*/\n\t\tswitch (selection) {\n\n\t\t\t/*\n\t\t\t**\tNew scenario\n\t\t\t*/\n\t\t\tcase 0:\n\t\t\t\tif (Changed) {\n\t\t\t\t\trc = WWMessageBox().Process(\"Save Changes?\", TXT_YES, TXT_NO);\n\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\tRender();\n\t\t\t\t\tif (rc==0) {\n\t\t\t\t\t\tif (Save_Scenario()!=0) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tChanged = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (New_Scenario()==0) {\n\t\t\t\t\tScen.CarryOverMoney = 0;\n\t\t\t\t\tChanged = 1;\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tLoad scenario\n\t\t\t*/\n\t\t\tcase 1:\n\t\t\t\tif (Changed) {\n\t\t\t\t\trc = WWMessageBox().Process(\"Save Changes?\", TXT_YES, TXT_NO);\n\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\tRender();\n\t\t\t\t\tif (rc==0) {\n\t\t\t\t\t\tif (Save_Scenario()!=0) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tChanged = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (Load_Scenario()==0) {\n\t\t\t\t\tScen.CarryOverMoney = 0;\n\t\t\t\t\tChanged = 0;\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tSave scenario\n\t\t\t*/\n\t\t\tcase 2:\n\t\t\t\tif (Save_Scenario() == 0) {\n\t\t\t\t\tChanged = 0;\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tEdit map size\n\t\t\t*/\n\t\t\tcase 3:\n\t\t\t\tif (Size_Map(MapCellX, MapCellY, MapCellWidth, MapCellHeight)==0) {\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tChanged = 1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tAdd an object\n\t\t\t*/\n\t\t\tcase 4:\n\t\t\t\tif (Placement_Dialog() == 0) {\n\t\t\t\t\tStart_Placement();\n\t\t\t\t\tprocess = false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tScenario options\n\t\t\t*/\n\t\t\tcase 5:\n\t\t\t\tif (Scenario_Dialog() == 0) {\n\t\t\t\t\tChanged = 1;\n\t\t\t\t\tprocess = false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tOther options\n\t\t\t*/\n\t\t\tcase 6:\n\t\t\t\tAI_Menu();\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tTest-drive this scenario\n\t\t\t*/\n\t\t\tcase 7:\n\t\t\t\tif (Changed) {\n\t\t\t\t\trc = WWMessageBox().Process(\"Save Changes?\", TXT_YES, TXT_NO, TXT_CANCEL);\n\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\tRender();\n\t\t\t\t\tif (rc == 2) return;\n\t\t\t\t\tif (rc==0) {\n\t\t\t\t\t\tif (Save_Scenario()!=0) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tChanged = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tChanged = 0;\n\t\t\t\tDebug_Map = false;\n\t\t\t\tStart_Scenario(Scen.ScenarioName);\n\t\t\t\treturn;\n\t\t}\n\t}\n\n\t/*\n\t**\tRestore the display:\n\t**\t- Clear HIDPAGE to erase any spurious drawing done by the menu system\n\t**\t- Invoke Flag_To_Redraw to tell DisplayClass to re-render the whole screen\n\t**\t- Invoke Redraw() to update the display\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n}\n\n\n/***************************************************************************\n * MapEditClass::AI_Menu -- menu of AI options                             *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/29/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::AI_Menu(void)\n{\n\tint selection;\t\t\t\t\t\t// option the user picks\n\tbool process;\t\t\t\t\t\t// menu stays up while true\n\tchar const * _menus[MAX_AI_MENU_NUM + 1];\n\n\t/*\n\t**\tFill in menu strings\n\t*/\n\t_menus[0] = \"Pre-Build a Base\";\n\t_menus[1] = \"Edit Triggers\";\n\t_menus[2] = \"Edit Teams\";\n\t_menus[3] = NULL;\n\n\t/*\n\t**\tMain Menu loop\n\t*/\n\tOverride_Mouse_Shape(MOUSE_NORMAL);\t\t// display default mouse cursor\n\tprocess = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback, to update music\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tInvoke menu\n\t\t*/\n\t\tHide_Mouse();\t\t// Do_Menu assumes the mouse is already hidden\n\t\tselection = Do_Menu(&_menus[0], true);\n\t\tShow_Mouse();\n\t\tif (UnknownKey==KN_ESC || UnknownKey==KN_LMOUSE || UnknownKey==KN_RMOUSE) {\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tProcess selection\n\t\t*/\n\t\tswitch (selection) {\n\t\t\t/*\n\t\t\t**\tPre-Build a Base\n\t\t\t*/\n\t\t\tcase 0:\n\t\t\t\tStart_Base_Building();\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tTrigger Editing\n\t\t\t*/\n\t\t\tcase 1:\n\t\t\t\tHandle_Triggers();\n\t\t\t\t/*\n\t\t\t\t**\tGo into trigger placement mode\n\t\t\t\t*/\n\t\t\t\tif (CurTrigger) {\n\t\t\t\t\tStart_Trigger_Placement();\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tTeam Editing\n\t\t\t*/\n\t\t\tcase 2:\n\t\t\t\tHandle_Teams(\"Teams\");\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * MapEditClass::Verify_House -- is this objtype ownable by this house?    *\n *                                                                         *\n * INPUT:                                                                  *\n *      house         house to check                                       *\n *      objtype      ObjectTypeClass to check                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = isn't ownable, 1 = it is                                       *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/16/1994 BR : Created.                                              *\n *=========================================================================*/\nbool MapEditClass::Verify_House(HousesType house, ObjectTypeClass const * objtype)\n{\n\t/*\n\t**\tVerify that new house can own this object\n\t*/\n\treturn((objtype->Get_Ownable() & (1 << house)) != 0);\n}\n\n\n/***************************************************************************\n * MapEditClass::Cycle_House -- finds next valid house for object type     *\n *                                                                         *\n * INPUT:                                                                  *\n *      objtype      ObjectTypeClass ptr to get house for                  *\n *      curhouse      current house value to start with                    *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      HousesType that's valid for this object type                       *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/23/1994 BR : Created.                                              *\n *=========================================================================*/\nHousesType MapEditClass::Cycle_House(HousesType curhouse, ObjectTypeClass const *)\n{\n\tHousesType count;\t\t\t// prevents an infinite loop\n\n\t/*\n\t**\tLoop through all house types, starting with the one after 'curhouse';\n\t**\treturn the first one that's valid\n\t*/\n\tcount = HOUSE_NONE;\n\twhile (1) {\n\n\t\t/*\n\t\t**\tGo to next house\n\t\t*/\n\t\tcurhouse++;\n\t\tif (curhouse == HOUSE_COUNT) {\n\t\t\tcurhouse = HOUSE_FIRST;\n\t\t}\n\n\t\t/*\n\t\t**\tCount # iterations; don't go forever\n\t\t*/\n\t\tcount++;\n\t\tif (count == HOUSE_COUNT) {\n\t\t\tcurhouse = HOUSE_NONE;\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tBreak if this is a valid house\n\t\t*/\n//\t\tif (HouseClass::As_Pointer(curhouse) && Verify_House(curhouse, objtype)) {\n\t\t\tbreak;\n//\t\t}\n\t}\n\n\treturn(curhouse);\n}\n\n\n/***************************************************************************\n * MapEditClass::Fatal -- exits with error message                         *\n *                                                                         *\n * INPUT:                                                                  *\n *      code      tells which message to display; this minimizes the       *\n *               use of character strings in the code.                     *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/12/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Fatal(int txt)\n{\n\t//Prog_End();\n\tprintf(\"%s\\n\", txt);\n\tEmergency_Exit(EXIT_FAILURE);\n}\n\n\nbool MapEditClass::Scroll_Map(DirType facing, int & distance, bool really)\n{\n\tif (Debug_Map) {\n\t\t/*\n\t\t** The popup gadgets require the entire map to be redrawn if we scroll.\n\t\t*/\n\t\tif (really) {\n\t\t\tFlag_To_Redraw(true);\n\t\t}\n\t}\n\treturn(MouseClass::Scroll_Map(facing, distance, really));\n}\n\n\n#ifdef OBSOLETE\nvoid MapEditClass::Flag_To_Redraw(bool complete)\n{\n\tMouseClass::Flag_To_Redraw(complete);\n}\n#endif\n\n\nvoid MapEditClass::Detach(ObjectClass * object)\n{\n\tif (GrabbedObject == object) {\n\t\tGrabbedObject = 0;\n\t}\n}\n\nbool MapEditClass::Get_Waypoint_Name(char wayptname[])\n{\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tenum {\n\t\tD_DIALOG_W = 100,\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\t\tD_DIALOG_H = 56,\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\t\tD_DIALOG_X = ((320 - D_DIALOG_W) / 2),\t\t\t\t// centered x-coord\n\t\tD_DIALOG_Y = ((200 - D_DIALOG_H) / 2),\t\t\t\t// centered y-coord\n\t\tD_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),\t\t// coord of x-center\n\n\t\tD_TXT8_H = 11,\t\t\t\t\t\t\t\t\t\t\t\t// ht of 8-pt text\n\t\tD_MARGIN = 7,\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\t\tD_EDIT_W = D_DIALOG_W - (D_MARGIN * 2),\n\t\tD_EDIT_H = 13,\n\t\tD_EDIT_X = D_DIALOG_X + D_MARGIN,\n\t\tD_EDIT_Y = D_DIALOG_Y + 20,\n\n\t\tD_BUTTON_X = D_DIALOG_X + D_MARGIN,\n\t\tD_BUTTON_Y = D_DIALOG_Y + 40,\n\t\tD_BUTTON_W = 40,\n\t\tD_BUTTON_H = 13,\n\n\t\tD_CANCEL_X = D_DIALOG_X + 53,\n\t\tD_CANCEL_Y = D_DIALOG_Y + 40,\n\t\tD_CANCEL_W = 40,\n\t\tD_CANCEL_H = 13,\n\n\t};\n\n\t/*\n\t**\tButton enumerations\n\t*/\n\tenum {\n\t\tBUTTON_OK = 100,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_EDIT,\n\t};\n\n\t/*\n\t**\tDialog variables\n\t*/\n\tbool cancel = false;\t\t\t\t\t\t// true = user cancels\n\twayptname[0] = 0;\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass * commands = NULL;\t\t// the button list\n\n\tTextButtonClass button (BUTTON_OK, TXT_OK, TPF_EBUTTON, D_BUTTON_X, D_BUTTON_Y, D_BUTTON_W);\n\tTextButtonClass cancelbtn (BUTTON_CANCEL, TXT_CANCEL, TPF_EBUTTON, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W);\n\tEditClass editbtn (BUTTON_EDIT, wayptname, 3, TPF_EFNT|TPF_NOSHADOW, D_EDIT_X, D_EDIT_Y, D_EDIT_W, -1, EditClass::ALPHANUMERIC);\n\n\t/*\n\t**\tInitialize.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tCreate the button list.\n\t*/\n\tcommands = &button;\n\tcancelbtn.Add_Tail(*commands);\n\teditbtn.Add_Tail(*commands);\n\teditbtn.Set_Focus();\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tbool firsttime = true;\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\tCall_Back();\n\t\t} else if (Main_Loop()) {\n\t\t\tprocess = false;\n\t\t\tcancel = true;\n\t\t}\n\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\n\t\t\t/*\n\t\t\t**\tDisplay the dialog box.\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tif (display) {\n\t\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n//\t\t\t\tDraw_Caption(caption, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRedraw the buttons.\n\t\t\t*/\n\t\t\tif (display) {\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t**\tThe first time through the processing loop, set the edit\n\t\t**\tgadget to have the focus. The\n\t\t**\tfocus must be set here since the gadget list has changed\n\t\t**\tand this change will cause any previous focus setting to be\n\t\t**\tcleared by the input processing routine.\n\t\t*/\n\t\tif (firsttime) {\n\t\t\tfirsttime = false;\n\t\t\teditbtn.Set_Focus();\n\t\t\teditbtn.Flag_To_Redraw();\n\t\t}\n\n\t\t/*\n\t\t**\tIf the <RETURN> key was pressed, then default to the appropriate\n\t\t**\taction button according to the style of this dialog box.\n\t\t*/\n\t\tif (input == KN_RETURN) {\n\t\t\tinput = (KeyNumType)(BUTTON_OK|KN_BUTTON);\n\t\t}\n\n\t\t/*\n\t\t**\tProcess input.\n\t\t*/\n\t\tswitch (input) {\n\t\t\t/*\n\t\t\t** Load: if load fails, present a message, and stay in the dialog\n\t\t\t** to allow the user to try another game\n\t\t\t*/\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tHide_Mouse();\n\t\t\t\tSeenPage.Clear();\n\t\t\t\tGamePalette.Set();\n\t\t\t\tShow_Mouse();\n\t\t\t\tprocess = false;\n\t\t\t\tcancel = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t** ESC/Cancel: break\n\t\t\t*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tHide_Mouse();\n\t\t\t\tSeenPage.Clear();\n\t\t\t\tGamePalette.Set();\n\t\t\t\tShow_Mouse();\n\t\t\t\tcancel = true;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tMap.Flag_To_Redraw(true);\n\tif (cancel) return(false);\n\n\treturn(true);\n}\n\nvoid MapEditClass::Update_Waypoint(int waypt_idx)\n{\n\tCELL cell;\n\n\t/*\n\t**\tUnflag cell for this waypoint if there is one\n\t*/\n\tcell = Scen.Waypoint[waypt_idx];\n\tif (cell != -1) {\n\t\tif (Scen.Waypoint[WAYPT_HOME] != cell && Scen.Waypoint[WAYPT_REINF] != cell) {\n\t\t\t(*this)[cell].IsWaypoint = 0;\n\t\t}\n\t\tFlag_Cell(cell);\n\t}\n\tScen.Waypoint[waypt_idx] = CurrentCell;\n\t(*this)[CurrentCell].IsWaypoint = 1;\n\tChanged = 1;\n\tFlag_Cell(CurrentCell);\n}\n\n\n/***************************************************************************\n * MapEditClass::Read_INI -- overloaded Read_INI function                  *\n *                                                                         *\n * Overloading this function gives the map editor a chance to initialize   *\n * certain values every time a new INI is read.                            *\n *                                                                         *\n * INPUT:                                                                  *\n *      buffer      INI staging area                                       *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/16/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Read_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tInvoke parent's Read_INI\n\t*/\n\tMono_Printf(\"We are in Read_INI\\n\");\n\n\tMouseClass::Read_INI(ini);\n\tBaseGauge->Set_Value(Scen.Percent);\n\n\tMono_Clear_Screen();\n\tMono_Printf(\"Scen.Percent = %d\", Scen.Percent);\n\n//\tBaseGauge->Set_Value(Scen.Percent);\n}\n\n\nvoid MapEditClass::Write_INI(CCINIClass & ini)\n{\n\tMouseClass::Write_INI(ini);\n//\tini.Put_Int(\"Basic\", \"Percent\", Scen.Percent);\n}\n\n#endif\n\n#include\t\"mapedsel.cpp\"\n\n"
  },
  {
    "path": "CODE/MAPEDIT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MAPEDIT.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MAPEDIT.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 14, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 14, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *\tThis class is derived from the normal display map class. It exists \t\t                    *\n * only to allow editing and adding items to the map.\t\t\t\t\t\t\t\t                    *\n *---------------------------------------------------------------------------------------------*\n * House-setting functions: The editor contains several house maintenance routines:\t\t\t\t  *\n * Verify_House: tells if the given ObjectType can be owned by the given HousesType\t\t\t\t  *\n * Cycle_House: Finds the next valid house for the given ObjectType; used when a new object\t  *\n *              can't be owned by the current editor HousesType.\t\t\t\t\t\t\t\t\t\t  *\n * Change_House: attempts to change the owner of the currently-selected object\t\t\t\t\t  *\n * Toggle_House: cycles the HousesType of a pending placement object\t\t\t\t\t\t\t\t\t  *\n * Set_House_Buttons: sets house buttons in accordance with the given HousesType\t\t\t\t\t  *\n *---------------------------------------------------------------------------------------------*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MAPEDIT_H\n#define MAPEDIT_H\n\n#include\t\"function.h\"\n\n/*\n**\tThis is the maximum # of ObjectTypeClasses the editor has to deal with.\n*/\nenum MapEdit1Enum {\n\tMAX_EDIT_OBJECTS =\t\t\t\t// max # of ObjectTypeClasses allowed\n\t\t(int)TEMPLATE_COUNT +\n\t\t(int)OVERLAY_COUNT +\n\t\t(int)SMUDGE_COUNT +\n\t\t(int)TERRAIN_COUNT +\n\t\t(int)UNIT_COUNT +\n\t\t(int)INFANTRY_COUNT +\n\t\t(int)VESSEL_COUNT +\n\t\t(int)STRUCT_COUNT,\n\n\tMAX_TEAM_CLASSES =\t\t\t\t// max # ObjectTypeClasses for a team\n\t\t(int)UNIT_COUNT +\n\t\t(int)INFANTRY_COUNT +\n\t\t(int)AIRCRAFT_COUNT,\n\n//\tNUM_EDIT_MISSIONS = 6,\t\t\t// # missions that can be assigned an object\n\n\tNUM_EDIT_CLASSES = 9,\t\t\t// # different classes (templates, terrain, etc)\n\n\tMAX_MAIN_MENU_NUM = 8,\n\tMAX_MAIN_MENU_LEN = 20,\n\n\tMAX_AI_MENU_NUM = 6,\n\tMAX_AI_MENU_LEN = 20,\n\n\tPOPUP_HOUSE_X=10,\n\tPOPUP_HOUSE_Y=100,\n\tPOPUP_HOUSE_W=60,\n\tPOPUP_HOUSE_H=(190-100),\n\n//\tPOPUP_GDI_W = 50,\n//\tPOPUP_GDI_H = 9,\n//\tPOPUP_GDI_X = 10,\n//\tPOPUP_GDI_Y = 160,\n\n//\tPOPUP_NOD_W = 50,\n//\tPOPUP_NOD_H = 9,\n//\tPOPUP_NOD_X = 10,\n//\tPOPUP_NOD_Y = 169,\n\n//\tPOPUP_NEUTRAL_W = 50,\n//\tPOPUP_NEUTRAL_H = 9,\n//\tPOPUP_NEUTRAL_X = 10,\n//\tPOPUP_NEUTRAL_Y = 178,\n\n//\tPOPUP_MULTI1_W = 25,\n//\tPOPUP_MULTI1_H = 9,\n//\tPOPUP_MULTI1_X = 10,\n//\tPOPUP_MULTI1_Y = 160,\n\n//\tPOPUP_MULTI2_W = 25,\n//\tPOPUP_MULTI2_H = 9,\n//\tPOPUP_MULTI2_X = 35,\n//\tPOPUP_MULTI2_Y = 160,\n\n//\tPOPUP_MULTI3_W = 25,\n//\tPOPUP_MULTI3_H = 9,\n//\tPOPUP_MULTI3_X = 10,\n//\tPOPUP_MULTI3_Y = 169,\n\n//\tPOPUP_MULTI4_W = 25,\n//\tPOPUP_MULTI4_H = 9,\n//\tPOPUP_MULTI4_X = 35,\n//\tPOPUP_MULTI4_Y = 169,\n\n\tPOPUP_MISSION_W = 80,\n\tPOPUP_MISSION_H = 40,\n\tPOPUP_MISSION_X = 70,\n\tPOPUP_MISSION_Y = 150,\n\n\tPOPUP_FACEBOX_W = 30,\n\tPOPUP_FACEBOX_H = 30,\n\tPOPUP_FACEBOX_X = 160,\n\tPOPUP_FACEBOX_Y = 160,\n\n\tPOPUP_HEALTH_W = 50,\n\tPOPUP_HEALTH_H = 10,\n\tPOPUP_HEALTH_X = 200,\n\tPOPUP_HEALTH_Y = 170,\n\n\tPOPUP_BASE_W = 50,\n\tPOPUP_BASE_H = 8,\n\tPOPUP_BASE_X = 300 - 50,\n\tPOPUP_BASE_Y = 0\n};\n\n/*\n**\tThese are the button ID's for the pop-up object-editing gizmos.\n**\tThe house button ID's must be sequential, with a 1-to-1 correspondence to\n**\tthe HousesType values.\n*/\nenum MapEditButtonIDEnum{\n\tPOPUP_SPAIN=500,\n\tPOPUP_FIRST=POPUP_SPAIN,\n\tPOPUP_GREECE,\n\tPOPUP_USSR,\n\tPOPUP_ENGLAND,\n\tPOPUP_ITALY,\n\tPOPUP_GERMANY,\n\tPOPUP_FRANCE,\n\tPOPUP_TURKEY,\n\tPOPUP_HOUSELIST,\t\t\t// House selection list.\n\tPOPUP_SELLABLE,\t\t\t// Allowed to sell.\n\tPOPUP_REBUILDABLE,\t\t// Allowed to rebuild.\n\tPOPUP_MISSIONLIST,\t\t// list box for missions\n\tPOPUP_HEALTHGAUGE,\t\t// health of object\n\tPOPUP_FACINGDIAL,\t\t\t// object's facing\n\tPOPUP_BASEPERCENT,\t\t// Base's percent-built slider\n\tMAP_AREA,\t\t\t\t\t// map as a click-able thingy\n\tBUTTON_FLAG=0x8000\n};\n\n\nclass TeamTypeClass;\n\nclass MapEditClass : public MouseClass\n{\n\t/*\n\t**\tPublic Interface\n\t*/\n\tpublic:\n\n\t\t/*\n\t\t**\tmapedit.cpp\n\t\t*/\n\t\tMapEditClass(void);\n\t\tMapEditClass(NoInitClass const & x) : MouseClass(x) {};\n\t\tbool Get_Waypoint_Name(char wayptname[]);\n\t\tvoid Update_Waypoint(int waypt_index);\n\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t\t// One-time init\n\t\tvirtual void Init_IO(void);\t\t\t\t\t\t\t// Inits button list\n\t\tvirtual void AI(KeyNumType &input, int x, int y);\n\t\tvirtual void Draw_It(bool forced = true);\n\t\tvirtual bool Scroll_Map(DirType facing, int & distance, bool really=true);\n\t\tvirtual void Read_INI(CCINIClass & ini);\n\t\tvirtual void Write_INI(CCINIClass & ini);\n\t\tvirtual void Detach(ObjectClass * object);\n\t\tvoid Detach(TARGET target, bool all=true) {MouseClass::Detach(target, all);}\n\t\tvoid Clear_List(void);\n\t\tbool Add_To_List(ObjectTypeClass const *object);\n\t\tvoid Main_Menu(void);\n\t\tvoid AI_Menu(void);\n\t\tbool Mouse_Moved(void);\n\t\tbool Verify_House(HousesType house, ObjectTypeClass const * objtype);\n\t\tHousesType Cycle_House(HousesType curhouse, ObjectTypeClass const * objtype);\n//\t\tint Trigger_Needs_Team(TriggerClass *trigger);\n\t\tvoid Fatal(int txt);\n\n\t\t/*\n\t\t**\tmapeddlg.cpp\n\t\t*/\n\t\tint New_Scenario(void);\n\t\tint Load_Scenario(void);\n\t\tint Save_Scenario(void);\n\t\tint Pick_Scenario(char const * caption, int & scen_nump, ScenarioPlayerType & playerp, ScenarioDirType & dirp, ScenarioVarType & varp);\n\t\tint Size_Map(int x, int y, int w, int h);\n\t\tint Scenario_Dialog(void);\n\t\tvoid Handle_Triggers(void);\n\t\tint Select_Trigger(void);\n\n\t\t/*\n\t\t**\tmapedplc.cpp\n\t\t*/\n\t\tint Placement_Dialog(void);\n\t\tvoid Start_Placement(void);\n\t\tint Place_Object(void);\n\t\tvoid Cancel_Placement(void);\n\t\tvoid Place_Next(void);\n\t\tvoid Place_Prev(void);\n\t\tvoid Place_Next_Category(void);\n\t\tvoid Place_Prev_Category(void);\n\t\tvoid Place_Home(void);\n\t\tvoid Toggle_House(void);\n\t\tvoid Set_House_Buttons(HousesType house, GadgetClass *btnlist, int base_id);\n\t\tvoid Start_Trigger_Placement(void);\n\t\tvoid Stop_Trigger_Placement(void);\n\t\tvoid Place_Trigger(void);\n\t\tvoid Start_Base_Building(void);\n\t\tvoid Cancel_Base_Building(void);\n\t\tvoid Build_Base_To(int percent);\n\n\t\t/*\n\t\t**\tmapedsel.cpp\n\t\t*/\n\t\tint Select_Object(void);\n\t\tvoid Select_Next(void);\n\t\tvoid Popup_Controls(void);\n\t\tvoid Grab_Object(void);\n\t\tint Move_Grabbed_Object(void);\n\t\tbool Change_House(HousesType newhouse);\n\n\t\t/*\n\t\t**\tmapedtm.cpp\n\t\t*/\n\t\tvoid Draw_Member(TechnoTypeClass const * ptr, int index, int quant, HousesType house);\n\t\tvoid Handle_Teams(char const * caption);\n\t\tint Select_Team(char const * caption);\n\t\tint Team_Members(HousesType house);\n\n\t/*\n\t**\tPrivate Interface\n\t*/\n\tprivate:\n\t\t/*\n\t\t**\tThis is the last-requested variation of a loaded/saved/new scenario.\n\t\t*/\n//\t\tScenarioVarType ScenVar;\n\n\t\t/*\n\t\t**\tArray of all TypeClasses the user can add to the map; cleared by\n\t\t**\tClear_List(), added to by Add_To_List()\n\t\t*/\n\t\tObjectTypeClass const * Objects[MAX_EDIT_OBJECTS];\n\t\tint ObjCount;\t\t\t\t\t\t\t// # of objects in the Objects array\n\n\t\t/*\n\t\t**\tLast-selected object to place, and last-selected house of object\n\t\t*/\n\t\tint LastChoice;\t\t\t\t\t\t// index of item user picked last\n\t\tHousesType LastHouse;\t\t\t\t// house of last item picked\n\n\t\t/*\n\t\t**\tVariables for grabbing/moving objects\n\t\t*/\n\t\tObjectClass * GrabbedObject;\t\t// object \"grabbed\" with mouse\n\t\tCELL GrabOffset;\t\t\t\t\t\t// offset to grabbed obj's upper-left\n\t\tunsigned long LastClickTime;\t\t// time of last LMOUSE click\n\n\t\t/*\n\t\t**\tNumber of each type of object in Objects, so we can switch categories\n\t\t*/\n\t\tint NumType[NUM_EDIT_CLASSES];\t\t// # of each type of class:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 0 = Template\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 1 = Overlay\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 2 = Smudge\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 3 = Terrain\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 4 = Unit\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 5 = Infantry\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 6 = Vessels\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 7 = Building\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 8 = Aircraft\n\n\t\t/*\n\t\t**\tThe offset of each type of object within the Objects[] array\n\t\t*/\n\t\tint TypeOffset[NUM_EDIT_CLASSES];\t// offsets within Objects[]\n\n\t\t/*\n\t\t**\tThe \"current\" trigger for point-and-click trigger setting\n\t\t*/\n\t\tTriggerTypeClass * CurTrigger;\t\t\t\t// current trigger\n\n\t\t/*\n\t\t**\tThe \"current\" team type for editing & associating with a trigger\n\t\t*/\n\t\tTeamTypeClass * CurTeam;\t\t\t\t// current team\n\n\t\t/*\n\t\t**\tBitfields for flags & such\n\t\t*/\n\t\tunsigned Changed : 1;\t\t\t\t\t\t// 1 = changes are unsaved\n\t\tunsigned LMouseDown : 1;\t\t\t\t\t// 1 = left mouse is held down\n\t\tunsigned BaseBuilding : 1;\t\t\t\t// 1 = we're in base-building mode\n\n\t\t/*\n\t\t**\tVariables for pre-building a base\n\t\t*/\n//\t\tint BasePercent;\t\t\t\t\t\t// Percentage the base will be built\n\n\t\t/*\n\t\t**\tVariables for supporting the object-editing controls at screen bottom\n\t\t*/\n\t\tListClass * HouseList;\n\t\tListClass * MissionList;\n\t\tTriColorGaugeClass *HealthGauge;\n\t\tDial8Class *FacingDial;\n\t\tControlClass *MapArea;\n\t\tTextLabelClass *HealthText;\n\t\tTextButtonClass * Sellable;\n\t\tTextButtonClass * Rebuildable;\n\t\tstatic char HealthBuf[20];\n\t\tGaugeClass *BaseGauge;\n\t\tTextLabelClass *BaseLabel;\n\t\tstatic MissionType MapEditMissions[];\n};\n\n#endif\n"
  },
  {
    "path": "CODE/MAPEDPLC.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MAPEDPLC.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : MAPEDPLC.CPP                             *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : November 18, 1994                        *\n *                                                                         *\n *                  Last Update : May 12, 1996 [JLB]                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Object-placement routines                                               *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   MapEditClass::Build_Base_To -- builds the AI base to the given percent*\n *   MapEditClass::Cancel_Base_Building -- stops base-building mode        *\n *   MapEditClass::Cancel_Placement -- cancels placement mode              *\n *   MapEditClass::Place_Home -- homes the placement object                *\n *   MapEditClass::Place_Next -- while placing object, goes to next        *\n *   MapEditClass::Place_Next_Category -- places next object category      *\n *   MapEditClass::Place_Object -- attempts to place the current object    *\n *   MapEditClass::Place_Prev -- while placing object, goes to previous    *\n *   MapEditClass::Place_Prev_Category -- places previous object category  *\n *   MapEditClass::Place_Trigger -- assigns trigger to object or cell      *\n *   MapEditClass::Placement_Dialog -- adds an object to the scenario      *\n *   MapEditClass::Set_House_Buttons -- toggles house buttons for btn list *\n *   MapEditClass::Start_Base_Building -- starts base-building mode        *\n *   MapEditClass::Start_Placement -- enters placement mode                *\n *   MapEditClass::Start_Trigger_Placement -- enters trigger placement mode*\n *   MapEditClass::Stop_Trigger_Placement -- exits trigger placement mode  *\n *   MapEditClass::Toggle_House -- toggles current placement object's house*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n#ifdef SCENARIO_EDITOR\n\n\n/***************************************************************************\n * MapEditClass::Placement_Dialog -- adds an object to the scenario        *\n *                                                                         *\n * This function sets LastChoice & LastHouse to the values chosen          *\n * by the user. It's up to the caller to call Start_Placement to enter     *\n * placement mode.                                                         *\n *   This routine does not modify PendingObject or PendingHouse.           *\n *                                                                         *\n *  Ŀ                   *\n *     [GDI]  [NOD]  [Neutral]                                           *\n *                                                                       *\n *     Ŀ                                 *\n *                                     [Template]                      *\n *                                     [Overlay ]                      *\n *                                     [Smudge  ]                      *\n *                                     [Terrain ]                      *\n *           (Object picture)          [Unit    ]                      *\n *                                     [Infantry]                      *\n *                                     [Aircraft]                      *\n *                                     [Building]                      *\n *                                                                     *\n *          Ŀ                    *\n *               [<-]  [->]                  (Grid)                    *\n *                                                                     *\n *           [OK]        [Cancel]                                *\n *                     *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, -1 = cancel                                                *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/21/1994 BR : Created.                                              *\n *   12/13/1995 JLB : Fixed house buttons to handle expanded house list.   *\n *   05/12/1996 JLB : Handles hi-res.                                      *\n *=========================================================================*/\nint MapEditClass::Placement_Dialog(void)\n{\n\tHousesType house;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tenum {\n\t\tD_DIALOG_W = 400,\n\t\tD_DIALOG_H = 180,\n\t\tD_DIALOG_X = 0,\n\t\tD_DIALOG_Y = 0,\n\t\tD_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),\n\n\t\tD_TXT8_H = 11,\n\t\tD_MARGIN = 7,\n\n\t\tD_PICTURE_W = 152,\t\t\t\t\t// must be divisible by 8!\n\t\tD_PICTURE_H = 105,\n\t\tD_PICTURE_X = D_DIALOG_X + 35,\t\t// must start on a byte boundary!\n\t\tD_PICTURE_Y = D_DIALOG_Y + D_MARGIN + D_TXT8_H + D_MARGIN,\n\t\tD_PICTURE_CX = D_PICTURE_X + D_PICTURE_W / 2,\n\n\t\tD_GDI_W = 65,\n\t\tD_GDI_H = 9,\n\t\tD_GDI_X = D_PICTURE_X+D_PICTURE_W+5,\n\t\tD_GDI_Y = D_PICTURE_Y,\n\n\t\tD_LEFT_W = 45,\n\t\tD_LEFT_H = 9,\n\t\tD_LEFT_X = D_PICTURE_CX - 5 - D_LEFT_W,\n\t\tD_LEFT_Y = D_PICTURE_Y + D_PICTURE_H + D_MARGIN,\n\n\t\tD_RIGHT_W = 45,\n\t\tD_RIGHT_H = 9,\n\t\tD_RIGHT_X = D_PICTURE_CX + 5,\n\t\tD_RIGHT_Y = D_PICTURE_Y + D_PICTURE_H + D_MARGIN,\n\n\t\tD_TEMPLATE_W = 70,\n\t\tD_TEMPLATE_H = 9,\n\t\tD_TEMPLATE_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_TEMPLATE_W - 30,\n\t\tD_TEMPLATE_Y = D_PICTURE_Y,\n\n\t\tD_OVERLAY_W = 70,\n\t\tD_OVERLAY_H = 9,\n\t\tD_OVERLAY_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_OVERLAY_W - 30,\n\t\tD_OVERLAY_Y = D_TEMPLATE_Y + D_TEMPLATE_H,\n\n\t\tD_SMUDGE_W = 70,\n\t\tD_SMUDGE_H = 9,\n\t\tD_SMUDGE_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_SMUDGE_W - 30,\n\t\tD_SMUDGE_Y = D_OVERLAY_Y + D_OVERLAY_H,\n\n\t\tD_TERRAIN_W = 70,\n\t\tD_TERRAIN_H = 9,\n\t\tD_TERRAIN_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_TERRAIN_W - 30,\n\t\tD_TERRAIN_Y = D_SMUDGE_Y + D_SMUDGE_H,\n\n\t\tD_UNIT_W = 70,\n\t\tD_UNIT_H = 9,\n\t\tD_UNIT_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_UNIT_W - 30,\n\t\tD_UNIT_Y = D_TERRAIN_Y + D_TERRAIN_H,\n\n\t\tD_INFANTRY_W = 70,\n\t\tD_INFANTRY_H = 9,\n\t\tD_INFANTRY_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_INFANTRY_W - 30,\n\t\tD_INFANTRY_Y = D_UNIT_Y + D_UNIT_H,\n\n\t\tD_AIRCRAFT_W = 70,\n\t\tD_AIRCRAFT_H = 9,\n\t\tD_AIRCRAFT_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_AIRCRAFT_W - 30,\n\t\tD_AIRCRAFT_Y = D_INFANTRY_Y + D_INFANTRY_H,\n\n\t\tD_BUILDING_W = 70,\n\t\tD_BUILDING_H = 9,\n\t\tD_BUILDING_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_BUILDING_W - 30,\n\t\tD_BUILDING_Y = D_AIRCRAFT_Y + D_AIRCRAFT_H,\n\n\t\tD_AIR_W = 70,\n\t\tD_AIR_H = 9,\n\t\tD_AIR_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_AIR_W - 30,\n\t\tD_AIR_Y = D_BUILDING_Y + D_BUILDING_H,\n\n\t\tD_OK_W = 45,\n\t\tD_OK_H = 9,\n\t\tD_OK_X = D_PICTURE_CX - D_OK_W - 5,\n\t\tD_OK_Y = D_DIALOG_Y + D_DIALOG_H - D_OK_H - D_MARGIN - 15,\n\n\t\tD_CANCEL_W = 45,\n\t\tD_CANCEL_H = 9,\n\t\tD_CANCEL_X = D_PICTURE_CX + 5,\n\t\tD_CANCEL_Y = D_DIALOG_Y + D_DIALOG_H - D_CANCEL_H - D_MARGIN - 15,\n\n\t\tGRIDSIZE = 10,\n\t\tGRIDBLOCK_W = 3,\n\t\tGRIDBLOCK_H = 3,\n\t\tD_GRID_X = D_DIALOG_X + D_DIALOG_W - (GRIDSIZE * GRIDBLOCK_W) - D_MARGIN - 35,\n\t\tD_GRID_Y = D_DIALOG_Y + D_DIALOG_H - (GRIDSIZE * GRIDBLOCK_H) - D_MARGIN - 35,\n\t};\n\n\t/*\n\t**\tButton enumerations:\n\t*/\n\tenum {\n\t\tBUTTON_GDI=100,\n\t\tBUTTON_HOUSE,\n\t\tBUTTON_NEXT,\n\t\tBUTTON_PREV,\n\t\tBUTTON_OK,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_TEMPLATE,\n\t\tBUTTON_OVERLAY,\n\t\tBUTTON_SMUDGE,\n\t\tBUTTON_TERRAIN,\n\t\tBUTTON_UNIT,\n\t\tBUTTON_INFANTRY,\n\t\tBUTTON_AIRCRAFT,\n\t\tBUTTON_BUILDING,\n\t\tBUTTON_AIR,\n\t};\n\n\t/*\n\t**\tDialog variables\n\t*/\n\tbool cancel = false;\t\t\t\t\t\t\t// true = user cancels\n\tconst ObjectTypeClass * curobj;\t\t\t// Working object pointer.\n\tint x,y;\t\t\t\t\t\t\t\t\t\t\t// for drawing the grid\n\tKeyNumType input;\t\t\t\t\t\t\t\t// user input\n\tshort const * occupy;\t\t\t\t\t\t\t// ptr into object's OccupyList\n\tint cell;\t\t\t\t\t\t\t\t\t\t// cell index for parsing OccupyList\n\tint i;\n\tint typeindex;\t\t\t\t\t\t\t\t\t// index of class type\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass * commands;\n\n\tListClass housebtn(BUTTON_HOUSE,\n\t\tD_GDI_X, D_GDI_Y, 60, 8*16,\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\thousebtn.Add_Item(HouseTypeClass::As_Reference(house).IniName);\n\t}\n\thouse = HOUSE_FIRST;\n\n\tTextButtonClass nextbtn(BUTTON_NEXT, TXT_RIGHT, TPF_EBUTTON, D_RIGHT_X, D_RIGHT_Y, D_RIGHT_W, D_RIGHT_H);\n\tTextButtonClass prevbtn(BUTTON_PREV, TXT_LEFT, TPF_EBUTTON, D_LEFT_X, D_LEFT_Y, D_LEFT_W, D_LEFT_H);\n\tTextButtonClass okbtn(BUTTON_OK, \"OK\", TPF_EBUTTON, D_OK_X, D_OK_Y, D_OK_W, D_OK_H);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, \"Cancel\", TPF_EBUTTON, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W, D_CANCEL_H);\n\tTextButtonClass templatebtn(BUTTON_TEMPLATE, \"Template\", TPF_EBUTTON, D_TEMPLATE_X, D_TEMPLATE_Y, D_TEMPLATE_W, D_TEMPLATE_H);\n\tTextButtonClass overlaybtn(BUTTON_OVERLAY, \"Overlay\", TPF_EBUTTON, D_OVERLAY_X, D_OVERLAY_Y, D_OVERLAY_W, D_OVERLAY_H);\n\tTextButtonClass smudgebtn(BUTTON_SMUDGE, \"Smudge\", TPF_EBUTTON, D_SMUDGE_X, D_SMUDGE_Y, D_SMUDGE_W, D_SMUDGE_H);\n\tTextButtonClass terrainbtn(BUTTON_TERRAIN, \"Terrain\", TPF_EBUTTON, D_TERRAIN_X, D_TERRAIN_Y, D_TERRAIN_W, D_TERRAIN_H);\n\tTextButtonClass unitbtn(BUTTON_UNIT, \"Unit\", TPF_EBUTTON, D_UNIT_X, D_UNIT_Y, D_UNIT_W, D_UNIT_H);\n\tTextButtonClass infantrybtn(BUTTON_INFANTRY, \"Infantry\", TPF_EBUTTON, D_INFANTRY_X, D_INFANTRY_Y, D_INFANTRY_W, D_INFANTRY_H);\n\tTextButtonClass aircraftbtn(BUTTON_AIRCRAFT, \"Ships\", TPF_EBUTTON, D_AIRCRAFT_X, D_AIRCRAFT_Y, D_AIRCRAFT_W, D_AIRCRAFT_H);\n\tTextButtonClass buildingbtn(BUTTON_BUILDING, \"Building\", TPF_EBUTTON, D_BUILDING_X, D_BUILDING_Y, D_BUILDING_W, D_BUILDING_H);\n\tTextButtonClass airbtn(BUTTON_AIR, \"Aircraft\", TPF_EBUTTON, D_AIR_X, D_AIR_Y, D_AIR_W, D_AIR_H);\n\n\t/*\n\t**\tInitialize addable objects list; we must do this every time in case one\n\t**\tof the object pools has become exhausted; that object won't be available\n\t**\tfor adding.  (Skip aircraft, since they won't be used in the editor.)\n\t*/\n\tClear_List();\n\tTemplateTypeClass::Prep_For_Add();\n\tOverlayTypeClass::Prep_For_Add();\n\tSmudgeTypeClass::Prep_For_Add();\n\tTerrainTypeClass::Prep_For_Add();\n\tUnitTypeClass::Prep_For_Add();\n\tInfantryTypeClass::Prep_For_Add();\n\tVesselTypeClass::Prep_For_Add();\n\tBuildingTypeClass::Prep_For_Add();\n\tAircraftTypeClass::Prep_For_Add();\n\n\t/*\n\t**\tCompute offset of each class type in the Objects array\n\t*/\n\tTypeOffset[0] = 0;\n\tfor (i = 1; i < NUM_EDIT_CLASSES; i++) {\n\t\tTypeOffset[i] = TypeOffset[i-1] + NumType[i-1];\n\t}\n\n\t/*\n\t**\tReturn if no objects to place\n\t*/\n\tif (!ObjCount)  {\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tInitialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\tif (LastChoice >= ObjCount) {\n\t\tLastChoice = 0;\n\t}\n\tcurobj = Objects[LastChoice];\t\t// current object to choose\n\n\tcommands = &nextbtn;\n\thousebtn.Add_Tail(*commands);\n\tprevbtn.Add_Tail(*commands);\n\tokbtn.Add_Tail(*commands);\n\tcancelbtn.Add_Tail(*commands);\n\ttemplatebtn.Add_Tail(*commands);\n\toverlaybtn.Add_Tail(*commands);\n\tsmudgebtn.Add_Tail(*commands);\n\tterrainbtn.Add_Tail(*commands);\n\tunitbtn.Add_Tail(*commands);\n\tinfantrybtn.Add_Tail(*commands);\n\taircraftbtn.Add_Tail(*commands);\n\tbuildingbtn.Add_Tail(*commands);\n\tairbtn.Add_Tail(*commands);\n\n\t/*\n\t**\tMake sure the recorded house selection matches the house list\n\t**\tbox selection.\n\t*/\n\tLastHouse = HousesType(housebtn.Current_Index());\n\n\t/*\n\t**\tMain processing loop\n\t*/\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if needed\n\t\t*/\n\t\tif (display) {\n\n\t\t\t/*\n\t\t\t**\tDisplay the dialog box\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\t\t\tDraw_Caption(TXT_PLACE_OBJECT, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\n\t\t\t/*\n\t\t\t**\tDisplay the current object:\n\t\t\t**\t- save the current window dimensions\n\t\t\t**\t- adjust the window size to the actual drawable area\n\t\t\t**\t- draw the shape\n\t\t\t**\t- reset the window dimensions\n\t\t\t*/\n\t\t\tWindowList[WINDOW_EDITOR][WINDOWX] = D_PICTURE_X;\n\t\t\tWindowList[WINDOW_EDITOR][WINDOWY] = D_PICTURE_Y;\n\t\t\tWindowList[WINDOW_EDITOR][WINDOWWIDTH] = D_PICTURE_W;\n\t\t\tWindowList[WINDOW_EDITOR][WINDOWHEIGHT] = D_PICTURE_H;\n\t\t\tChange_Window((int)WINDOW_EDITOR);\n\t\t\tDraw_Box(D_PICTURE_X, D_PICTURE_Y, D_PICTURE_W, D_PICTURE_H, BOXSTYLE_DOWN, false);\n\t\t\tcurobj->Display(WinW/2, WinH>>1, WINDOW_EDITOR, LastHouse);\n//\t\t\tcurobj->Display(WinW<<2, WinH>>1, WINDOW_EDITOR, LastHouse);\n\n\t\t\t/*\n\t\t\t**\tErase the grid\n\t\t\t*/\n\t\t\tLogicPage->Fill_Rect(D_GRID_X - GRIDBLOCK_W * 2, D_GRID_Y,\n\t\t\t\tD_GRID_X + GRIDSIZE * GRIDBLOCK_W,\n\t\t\t\tD_GRID_Y + GRIDSIZE * GRIDBLOCK_H, BLACK);\n\n\t\t\t/*\n\t\t\t**\tDraw a box for every cell occupied\n\t\t\t*/\n\t\t\toccupy = curobj->Occupy_List();\n\t\t\twhile ( (*occupy) != REFRESH_EOL) {\n\t\t\t\tcell = (*occupy);\n\t\t\t\toccupy++;\n\t\t\t\tx = D_GRID_X + ((cell % MAP_CELL_W) * GRIDBLOCK_W);\n\t\t\t\ty = D_GRID_Y + ((cell / MAP_CELL_W) * GRIDBLOCK_H);\n\t\t\t\tLogicPage->Fill_Rect(x, y, x + GRIDBLOCK_W - 1, y + GRIDBLOCK_H - 1, scheme->Bright);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDraw the grid itself\n\t\t\t*/\n\t\t\tfor (y = 0; y <= GRIDSIZE; y++) {\n\t\t\t\tfor (x = 0; x <= GRIDSIZE; x++) {\n\t\t\t\t\tLogicPage->Draw_Line(D_GRID_X + x * GRIDBLOCK_W, D_GRID_Y,\n\t\t\t\t\t\tD_GRID_X + x * GRIDBLOCK_W,\n\t\t\t\t\t\tD_GRID_Y + GRIDSIZE * GRIDBLOCK_H, scheme->Shadow);\n\t\t\t\t}\n\t\t\t\tLogicPage->Draw_Line(D_GRID_X, D_GRID_Y + y * GRIDBLOCK_H,\n\t\t\t\t\tD_GRID_X + GRIDSIZE * GRIDBLOCK_W, D_GRID_Y + y * GRIDBLOCK_H,\n\t\t\t\t\tscheme->Shadow);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tPrint the object's label from the class's Full_Name().\n\t\t\t**\tWarning: Text_String returns an EMS pointer, so standard string\n\t\t\t**\tfunctions won't work!\n\t\t\t*/\n\t\t\tFancy_Text_Print (curobj->Full_Name(),\n\t\t\t\tD_PICTURE_CX, D_PICTURE_Y + D_MARGIN, scheme, TBLACK,\n\t\t\t\tTPF_CENTER | TPF_EFNT | TPF_NOSHADOW);\n\n\t\t\t/*\n\t\t\t**\tRedraw buttons\n\t\t\t**\tFigure out which class category we're in & highlight that button\n\t\t\t**\tThis updates 'typeindex', which is used below, and it also updates\n\t\t\t**\tthe category button states.\n\t\t\t*/\n\t\t\ti = 0;\n\t\t\tfor (typeindex = 0; typeindex < NUM_EDIT_CLASSES; typeindex++) {\n\t\t\t\ti += NumType[typeindex];\n\t\t\t\tif (LastChoice < i) break;\n\t\t\t}\n\t\t\ttemplatebtn.Turn_Off();\n\t\t\toverlaybtn.Turn_Off();\n\t\t\tsmudgebtn.Turn_Off();\n\t\t\tterrainbtn.Turn_Off();\n\t\t\tunitbtn.Turn_Off();\n\t\t\tinfantrybtn.Turn_Off();\n\t\t\taircraftbtn.Turn_Off();\n\t\t\tairbtn.Turn_Off();\n\t\t\tbuildingbtn.Turn_Off();\n\t\t\tswitch (typeindex + BUTTON_TEMPLATE) {\n\t\t\t\tcase BUTTON_TEMPLATE:\n\t\t\t\t\ttemplatebtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BUTTON_OVERLAY:\n\t\t\t\t\toverlaybtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BUTTON_SMUDGE:\n\t\t\t\t\tsmudgebtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BUTTON_TERRAIN:\n\t\t\t\t\tterrainbtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BUTTON_UNIT:\n\t\t\t\t\tunitbtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BUTTON_INFANTRY:\n\t\t\t\t\tinfantrybtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BUTTON_AIRCRAFT:\n\t\t\t\t\taircraftbtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BUTTON_AIR:\n\t\t\t\t\tairbtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BUTTON_BUILDING:\n\t\t\t\t\tbuildingbtn.Turn_On();\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRedraw buttons\n\t\t\t*/\n\t\t\tcommands->Draw_All();\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\t/*\n\t\t**\tProcess user input\n\t\t*/\n\t\tswitch (input) {\n\n\t\t\t/*\n\t\t\t**\tGDI House\n\t\t\t*/\n\t\t\tcase (BUTTON_HOUSE | KN_BUTTON):\n\t\t\t\thouse = HousesType(housebtn.Current_Index());\n\n\t\t\t\t/*\n\t\t\t\t**\tSet flags & buttons\n\t\t\t\t*/\n\t\t\t\tLastHouse = house;\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tNext in list\n\t\t\t*/\n\t\t\tcase (KN_RIGHT):\n\t\t\tcase (BUTTON_NEXT | KN_BUTTON):\n\t\t\t\t/*\n\t\t\t\t**\tIncrement to next obj\n\t\t\t\t*/\n\t\t\t\tLastChoice++;\n\t\t\t\tif (LastChoice == ObjCount) {\n\t\t\t\t\tLastChoice = 0;\n\t\t\t\t}\n\t\t\t\tcurobj = Objects[LastChoice];\n\n\t\t\t\tnextbtn.Turn_Off();\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tPrevious in list\n\t\t\t*/\n\t\t\tcase (KN_LEFT):\n\t\t\tcase (BUTTON_PREV | KN_BUTTON):\n\n\t\t\t\t/*\n\t\t\t\t**\tDecrement to prev obj\n\t\t\t\t*/\n\t\t\t\tLastChoice--;\n\t\t\t\tif (LastChoice < 0) {\n\t\t\t\t\tLastChoice = ObjCount-1;\n\t\t\t\t}\n\t\t\t\tcurobj = Objects[LastChoice];\n\t\t\t\tprevbtn.Turn_Off();\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tSelect a class type\n\t\t\t*/\n\t\t\tcase (BUTTON_TEMPLATE | KN_BUTTON):\n\t\t\tcase (BUTTON_OVERLAY | KN_BUTTON):\n\t\t\tcase (BUTTON_SMUDGE | KN_BUTTON):\n\t\t\tcase (BUTTON_TERRAIN | KN_BUTTON):\n\t\t\tcase (BUTTON_UNIT | KN_BUTTON):\n\t\t\tcase (BUTTON_INFANTRY | KN_BUTTON):\n\t\t\tcase (BUTTON_AIRCRAFT | KN_BUTTON):\n\t\t\tcase (BUTTON_BUILDING | KN_BUTTON):\n\t\t\tcase (BUTTON_AIR | KN_BUTTON):\n\n\t\t\t\t/*\n\t\t\t\t**\tFind index of class\n\t\t\t\t*/\n\t\t\t\ttypeindex = input - (BUTTON_TEMPLATE | KN_BUTTON);\n\n\t\t\t\t/*\n\t\t\t\t**\tIf no objects of that type, do nothing\n\t\t\t\t*/\n\t\t\t\tif (NumType[typeindex]==0) {\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tSet current object\n\t\t\t\t*/\n\t\t\t\tLastChoice = TypeOffset[typeindex];\n\t\t\t\tcurobj = Objects[LastChoice];\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tNext category\n\t\t\t*/\n\t\t\tcase KN_PGDN:\n\t\t\t\ttypeindex++;\n\t\t\t\tif (typeindex==NUM_EDIT_CLASSES) {\n\t\t\t\t\ttypeindex = 0;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tSet current object\n\t\t\t\t*/\n\t\t\t\tLastChoice = TypeOffset[typeindex];\n\t\t\t\tcurobj = Objects[LastChoice];\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tPrevious category\n\t\t\t*/\n\t\t\tcase KN_PGUP:\n\t\t\t\ttypeindex--;\n\t\t\t\tif (typeindex < 0) {\n\t\t\t\t\ttypeindex = NUM_EDIT_CLASSES - 1;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tSet current object\n\t\t\t\t*/\n\t\t\t\tLastChoice = TypeOffset[typeindex];\n\t\t\t\tcurobj = Objects[LastChoice];\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tJump to 1st choice\n\t\t\t*/\n\t\t\tcase KN_HOME:\n\t\t\t\tLastChoice = 0;\n\n\t\t\t\t/*\n\t\t\t\t**\tSet current object\n\t\t\t\t*/\n\t\t\t\tcurobj = Objects[LastChoice];\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tOK\n\t\t\t*/\n\t\t\tcase (KN_RETURN):\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tcancel = false;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tCancel\n\t\t\t*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tcancel = true;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t}\n\n\t/*\n\t**\tRedraw the display\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n\n\tif (cancel) {\n\t\treturn(-1);\n\t}\n\n\treturn(0);\n}\n\n\n/***************************************************************************\n * MapEditClass::Start_Placement -- enters placement mode                  *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/04/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Start_Placement(void)\n{\n\n\t/*\n\t**\tInitialize addable objects list; we must do this every time in case one\n\t**\tof the object pools has become exhausted; that object won't be available\n\t**\tfor adding. These must be added in the same order expected by the\n\t**\tobject selection dialog (same as button order).\n\t*/\n\tClear_List();\n\tTemplateTypeClass::Prep_For_Add();\n\tOverlayTypeClass::Prep_For_Add();\n\tSmudgeTypeClass::Prep_For_Add();\n\tTerrainTypeClass::Prep_For_Add();\n\tUnitTypeClass::Prep_For_Add();\n\tInfantryTypeClass::Prep_For_Add();\n\tVesselTypeClass::Prep_For_Add();\n\tBuildingTypeClass::Prep_For_Add();\n\tAircraftTypeClass::Prep_For_Add();\n\n\t/*\n\t**\tCompute offset of each class type in the Objects array\n\t*/\n\tTypeOffset[0] = 0;\n\tfor (int i = 1; i < NUM_EDIT_CLASSES; i++) {\n\t\tTypeOffset[i] = TypeOffset[i-1] + NumType[i-1];\n\t}\n\n\t/*\n\t**\tCreate the placement object:\n\t**\t- For normal placement mode, use the last-used index into Objects\n\t**\t  (LastChoice), and the last-used house (LastHouse).\n\t**\t- For base-building mode, force the object to be a building, and use the\n\t**\t  House specified in the Base object\n\t*/\n\tif (!BaseBuilding) {\n\t\tif (LastChoice >= ObjCount) {\n\t\t\tLastChoice = ObjCount - 1;\n\t\t}\n\t\tPendingObject = Objects[LastChoice];\n\t\tPendingHouse = LastHouse;\n\t\tPendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(LastHouse));\n\t} else {\n\t\tif (LastChoice < TypeOffset[7]) {\n\t\t\tLastChoice = TypeOffset[7];\n\t\t}\n\t\tif (LastChoice >= ObjCount) {\n\t\t\tLastChoice = ObjCount - 1;\n\t\t}\n\t\tPendingObject = Objects[LastChoice];\n\t\tPendingHouse = LastHouse = Base.House;\n\t\tPendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(LastHouse));\n\t}\n\n\t/*\n\t**\tError if no more objects available\n\t*/\n\tif (!PendingObjectPtr) {\n\t\tWWMessageBox().Process(\"No more objects of this type available.\");\n\t\tHidPage.Clear();\n\t\tFlag_To_Redraw(true);\n\t\tRender();\n\t\tPendingObject = NULL;\n\t\tif (BaseBuilding) {\n\t\t\tCancel_Base_Building();\n\t\t}\n\t\treturn;\n\t}\n\n\t/*\n\t**\tSet the placement cursor\n\t*/\n\tSet_Cursor_Pos();\n\tSet_Cursor_Shape(PendingObject->Occupy_List());\n}\n\n\n/***************************************************************************\n * MapEditClass::Place_Object -- attempts to place the current object      *\n *                                                                         *\n * Placement of \"real\" objects is simply checked via their Unlimbo routine.*\n * Placement of templates is more complex:                                 *\n * - for every cell in the template's OccupyList, check for objects        *\n *     already in that cell by looking at the cell's OccupyList &          *\n *     OverlapList                                                         *\n * - \"lift\" all the objects in the cell by Mark'ing them                   *\n * - temporarily place the template in that cell                           *\n * - try to Unlimbo all the objects that were in the cell. If any          *\n *     objects fail to Unlimbo onto that template, the template cannot     *\n *     be placed here                                                      *\n *                                                                         *\n * It is assumed that the object being placed is a \"new\" object; the       *\n * object's strength & mission are not set during Unlimbo.                 *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, -1 = unable to place                                       *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/04/1994 BR : Created.                                              *\n *=========================================================================*/\nint MapEditClass::Place_Object(void)\n{\n\tCELL template_cell;\t\t\t\t\t\t// cell being checked for template\n\tCOORDINATE obj_coord;\t\t\t\t\t\t\t// coord of occupier object\n\tint okflag;\t\t\t\t\t\t\t\t\t// OK to place a template?\n\tshort const * occupy;\t\t\t\t\t\t// ptr into template's OccupyList\n\tObjectClass * occupier;\t\t\t\t\t// occupying object\n\tTemplateType save_ttype;\t\t\t\t// for saving cell's TType\n\tunsigned char save_ticon;\t\t\t\t// for saving cell's TIcon\n//\tBaseNodeClass node;\t\t\t\t\t\t// for adding to an AI Base\n\n\t/*\n\t**\tPlacing a template:\n\t**\t- first lift up any objects in the cell\n\t**\t- place the template, and try to replace the objects; if they won't go\n\t**\t  back, the template can't go there\n\t*/\n\t//ScenarioInit++;\n\tif (PendingObject->What_Am_I() == RTTI_TEMPLATETYPE) {\n\n\t\t/*\n\t\t**\tLoop through all cells this template will occupy\n\t\t*/\n\t\tokflag = true;\n\t\toccupy = PendingObject->Occupy_List();\n\t\twhile ((*occupy) != REFRESH_EOL) {\n\n\t\t\t/*\n\t\t\t**\tCheck this cell for an occupier\n\t\t\t*/\n\t\t\ttemplate_cell = (ZoneCell+ZoneOffset) + (*occupy);\n\t\t\tif ((*this)[template_cell].Cell_Occupier()) {\n\t\t\t\toccupier = (*this)[template_cell].Cell_Occupier();\n\n\t\t\t\t/*\n\t\t\t\t**\tSave object's coordinates\n\t\t\t\t*/\n\t\t\t\tobj_coord = occupier->Coord;\n\n\t\t\t\t/*\n\t\t\t\t**\tPlace the object in limbo\n\t\t\t\t*/\n\t\t\t\toccupier->Mark(MARK_UP);\n\n\t\t\t\t/*\n\t\t\t\t**\tSet the cell's template values\n\t\t\t\t*/\n\t\t\t\tsave_ttype = (*this)[template_cell].TType;\n\t\t\t\tsave_ticon = (*this)[template_cell].TIcon;\n\t\t\t\t(*this)[template_cell].TType =\n\t\t\t\t\t((TemplateTypeClass *)PendingObject)->Type;\n\t\t\t\t(*this)[template_cell].TIcon = Cell_X(*occupy) + Cell_Y(*occupy) *\n\t\t\t\t\t((TemplateTypeClass *)PendingObject)->Width;\n\t\t\t\t(*this)[template_cell].Recalc_Attributes();\n\n\t\t\t\t/*\n\t\t\t\t**\tTry to put the object back down\n\t\t\t\t*/\n\t\t\t\tif (occupier->Can_Enter_Cell(Coord_Cell(obj_coord)) != MOVE_OK) {\n\t\t\t\t\tokflag = false;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tPut everything back the way it was\n\t\t\t\t*/\n\t\t\t\t(*this)[template_cell].TType = save_ttype;\n\t\t\t\t(*this)[template_cell].TIcon = save_ticon;\n\t\t\t\t(*this)[template_cell].Recalc_Attributes();\n\n\t\t\t\t/*\n\t\t\t\t**\tMajor error if can't replace the object now\n\t\t\t\t*/\n\t\t\t\toccupier->Mark(MARK_DOWN);\n\t\t\t}\n\t\t\toccupy++;\n\t\t}\n\n\t\t/*\n\t\t**\tIf it's still OK after ALL THAT, place the template\n\t\t*/\n\t\tif (okflag) {\n\t\t\tif (PendingObjectPtr->Unlimbo(Cell_Coord(ZoneCell + ZoneOffset))) {\n\n\t\t\t\t/*\n\t\t\t\t**\tLoop through all cells occupied by this template, and clear the\n\t\t\t\t**\tsmudge & overlay.\n\t\t\t\t*/\n\t\t\t\toccupy = PendingObject->Occupy_List();\n\t\t\t\twhile ((*occupy) != REFRESH_EOL) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tGet cell for this occupy item\n\t\t\t\t\t*/\n\t\t\t\t\ttemplate_cell = (ZoneCell+ZoneOffset) + (*occupy);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tClear smudge & overlay\n\t\t\t\t\t*/\n\t\t\t\t\t(*this)[template_cell].Overlay = OVERLAY_NONE;\n\t\t\t\t\t(*this)[template_cell].OverlayData = 0;\n\t\t\t\t\t(*this)[template_cell].Smudge = SMUDGE_NONE;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tmake adjacent cells recalc attrib's\n\t\t\t\t\t*/\n\t\t\t\t\t(*this)[template_cell].Recalc_Attributes();\n\t\t\t\t\t(*this)[template_cell].Wall_Update();\n\t\t\t\t\t(*this)[template_cell].Concrete_Calc();\n\n\t\t\t\t\toccupy++;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tSet flags etc\n\t\t\t\t*/\n\t\t\t\tPendingObjectPtr = 0;\n\t\t\t\tPendingObject = 0;\n\t\t\t\tPendingHouse = HOUSE_NONE;\n\t\t\t\tSet_Cursor_Shape(0);\n\t\t\t\t//ScenarioInit--;\n\t\t\t\tTotalValue = Overpass();\n\t\t\t\tFlag_To_Redraw(false);\n\t\t\t\treturn(0);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tFailure to deploy results in a returned failure code.\n\t\t\t*/\n\t\t\t//ScenarioInit--;\n\t\t\treturn(-1);\n\t\t}\n\n\t\t/*\n\t\t**\tNot OK; return error\n\t\t*/\n\t\t//ScenarioInit--;\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tPlacing infantry: Infantry can go into cell sub-positions, so find the\n\t**\tsub-position closest to the mouse & put him there\n\t*/\n\tif (PendingObject->What_Am_I() == RTTI_INFANTRYTYPE) {\n\n\t\t/*\n\t\t**\tFind cell sub-position\n\t\t*/\n\t\tif (Is_Spot_Free(Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y()))) {\n\t\t\tobj_coord = Closest_Free_Spot(Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y()));\n\t\t} else {\n\t\t\tobj_coord = NULL;\n\t\t}\n\n\t\t/*\n\t\t**\tNo free spots; don't place the object\n\t\t*/\n\t\tif (obj_coord == NULL) {\n\t\t\t//ScenarioInit--;\n\t\t\treturn(-1);\n\t\t}\n\n\t\t/*\n\t\t**\tUnlimbo the object\n\t\t*/\n\t\tif (PendingObjectPtr->Unlimbo(obj_coord)) {\n\t\t\t((InfantryClass *)PendingObjectPtr)->Set_Occupy_Bit(obj_coord);\n//\t\t\tMap[obj_coord].Flag.Composite |=\n//\t\t\t\t(1 << CellClass::Spot_Index(obj_coord));\n\t\t\tPendingObjectPtr = 0;\n\t\t\tPendingObject = 0;\n\t\t\tPendingHouse = HOUSE_NONE;\n\t\t\tSet_Cursor_Shape(0);\n\t\t\t//ScenarioInit--;\n\t\t\treturn(0);\n\t\t}\n\n\t\t//ScenarioInit--;\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tPlacing an object\n\t*/\n\tif (PendingObjectPtr->Unlimbo(Cell_Coord(ZoneCell + ZoneOffset))) {\n\n\t\t/*\n\t\t** Update the Tiberium computation if we're placing an overlay\n\t\t*/\n\t\tif (PendingObject->What_Am_I() == RTTI_OVERLAYTYPE &&\n\t\t\t((OverlayTypeClass *)PendingObject)->IsTiberium) {\n\t\t\tTotalValue = Overpass();\n\t\t\tFlag_To_Redraw(false);\n\t\t}\n\n\t\t/*\n\t\t** If we're building a base, add this building to the base's Node list.\n\t\t*/\n\t\tif (BaseBuilding && PendingObject->What_Am_I() == RTTI_BUILDINGTYPE) {\n//\t\t\tnode.Type = ((BuildingTypeClass *)PendingObject)->Type;\n//\t\t\tnode.Cell = Coord_Cell(PendingObjectPtr->Coord);\n\t\t\tBase.Nodes.Add(BaseNodeClass(((BuildingTypeClass *)PendingObject)->Type, Coord_Cell(PendingObjectPtr->Coord)));\n\t\t}\n\n\t\tPendingObjectPtr = 0;\n\t\tPendingObject = 0;\n\t\tPendingHouse = HOUSE_NONE;\n\t\tSet_Cursor_Shape(0);\n\t\t//ScenarioInit--;\n\t\treturn(0);\n\t}\n\n\treturn(-1);\n}\n\n\n/***************************************************************************\n * MapEditClass::Cancel_Placement -- cancels placement mode                *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/04/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Cancel_Placement(void)\n{\n\t/*\n\t**\tDelete the placement object\n\t*/\n\tdelete PendingObjectPtr;\n\tPendingObject = 0;\n\tPendingObjectPtr = 0;\n\tPendingHouse = HOUSE_NONE;\n\n\t/*\n\t**\tRestore cursor shape\n\t*/\n\tSet_Cursor_Shape(0);\n\n\t/*\n\t**\tRedraw the map to erase old leftovers\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n}\n\n\n/***************************************************************************\n * MapEditClass::Place_Next -- while placing object, goes to next          *\n *                                                                         *\n * - Deletes the current 'PendingObjectPtr'                                *\n * - Increments LastChoice                                                 *\n * - Tries to create a new 'PendingObjectPtr'; if fails, keeps             *\n *   incrementing until it gets it                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/03/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Place_Next(void)\n{\n\tdelete PendingObjectPtr;\n\tPendingObjectPtr = NULL;\n\tPendingObject = NULL;\n\n\t/*\n\t**\tLoop until we create a valid object\n\t*/\n\twhile (!PendingObjectPtr) {\n\t\t/*\n\t\t**\tGo to next object in Objects list\n\t\t*/\n\t\tLastChoice++;\n\t\tif (LastChoice == ObjCount) {\n\n\t\t\t/*\n\t\t\t** If we're in normal placement mode, wrap to the 1st object;\n\t\t\t** if we're in base-building mode, wrap to the 1st building\n\t\t\t*/\n\t\t\tif (!BaseBuilding) {\n\t\t\t\tLastChoice = 0;\n\t\t\t} else {\n\t\t\t\tLastChoice = TypeOffset[7];\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tCreate placement object\n\t\t*/\n\t\tPendingObject = Objects[LastChoice];\n\t\tPendingHouse = LastHouse;\n\t\tPendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(PendingHouse));\n\t\tif (!PendingObjectPtr) {\n\t\t\tPendingObject = NULL;\n\t\t}\n\t}\n\n\t/*\n\t**\tSet the new cursor shape\n\t*/\n\tSet_Cursor_Pos();\n\tSet_Cursor_Shape(0);\n\tSet_Cursor_Shape(PendingObject->Occupy_List());\n\n\t/*\n\t**\tRedraw the map to erase old leftovers\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n}\n\n\n/***************************************************************************\n * MapEditClass::Place_Prev -- while placing object, goes to previous      *\n *                                                                         *\n * - Deletes the current 'PendingObjectPtr'                                *\n * - Decrements LastChoice                                                 *\n * - Tries to create a new 'PendingObjectPtr'; if fails, keeps             *\n *   decrementing until it gets it                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/03/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Place_Prev(void)\n{\n\tdelete PendingObjectPtr;\n\tPendingObjectPtr = NULL;\n\tPendingObject = NULL;\n\n\t/*\n\t**\tLoop until we create a valid object\n\t*/\n\twhile (!PendingObjectPtr) {\n\n\t\t/*\n\t\t**\tGo to prev object in Objects list\n\t\t*/\n\t\tLastChoice--;\n\n\t\t/*\n\t\t** If we're in normal placement mode, wrap at the 1st object.\n\t\t** If we're building a base, wrap at the 1st building.\n\t\t*/\n\t\tif (!BaseBuilding) {\n\t\t\tif (LastChoice < 0) {\n\t\t\t\tLastChoice = ObjCount - 1;\n\t\t\t}\n\t\t} else {\n\t\t\tif (LastChoice < TypeOffset[7]) {\n\t\t\t\tLastChoice = ObjCount - 1;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tCreate placement object\n\t\t*/\n\t\tPendingObject = Objects[LastChoice];\n\t\tPendingHouse = LastHouse;\n\t\tPendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(PendingHouse));\n\t\tif (!PendingObjectPtr) {\n\t\t\tPendingObject = NULL;\n\t\t}\n\t}\n\n\t/*\n\t**\tSet the new cursor shape\n\t*/\n\tSet_Cursor_Pos();\n\tSet_Cursor_Shape(0);\n\tSet_Cursor_Shape(PendingObject->Occupy_List());\n\n\t/*\n\t**\tRedraw the map to erase old leftovers\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n}\n\n\n/***************************************************************************\n * MapEditClass::Place_Next_Category -- places next category of object     *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/03/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Place_Next_Category(void)\n{\n\tint i;\n\n\t/*\n\t** Don't allow this command if we're building a base; the only valid\n\t** category for base-building is buildings.\n\t*/\n\tif (BaseBuilding) {\n\t\treturn;\n\t}\n\n\tdelete PendingObjectPtr;\n\tPendingObjectPtr = NULL;\n\tPendingObject = NULL;\n\n\t/*\n\t**\tGo to next category in Objects list\n\t*/\n\ti = LastChoice;\n\twhile (Objects[i]->What_Am_I() == Objects[LastChoice]->What_Am_I()) {\n\t\ti++;\n\t\tif (i == ObjCount) {\n\t\t\ti = 0;\n\t\t}\n\t}\n\tLastChoice = i;\n\n\t/*\n\t**\tLoop until we create a valid object\n\t*/\n\twhile (!PendingObjectPtr) {\n\n\t\t/*\n\t\t**\tGet house for this object type\n\t\t*/\n//\t\tif (!Verify_House(LastHouse, Objects[LastChoice])) {\n//\t\t\tLastHouse = Cycle_House(LastHouse, Objects[LastChoice]);\n//\t\t}\n\n\t\t/*\n\t\t**\tCreate placement object\n\t\t*/\n\t\tPendingObject = Objects[LastChoice];\n\t\tPendingHouse = LastHouse;\n\t\tPendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(PendingHouse));\n\n\t\t/*\n\t\t**\tIf this one failed, try the next\n\t\t*/\n\t\tif (!PendingObjectPtr) {\n\t\t\tPendingObject = NULL;\n\t\t\tLastChoice++;\n\t\t\tif (LastChoice == ObjCount) {\n\t\t\t\tLastChoice = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tSet the new cursor shape\n\t*/\n\tSet_Cursor_Pos();\n\tSet_Cursor_Shape(0);\n\tSet_Cursor_Shape(PendingObject->Occupy_List());\n\n\t/*\n\t**\tRedraw the map to erase old leftovers\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n}\n\n\n/***************************************************************************\n * MapEditClass::Place_Prev_Category -- places previous category of object *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/03/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Place_Prev_Category(void)\n{\n\tint i;\n\n\t/*\n\t** Don't allow this command if we're building a base; the only valid\n\t** category for base-building is buildings.\n\t*/\n\tif (BaseBuilding) {\n\t\treturn;\n\t}\n\n\tdelete PendingObjectPtr;\n\tPendingObjectPtr = NULL;\n\tPendingObject = NULL;\n\n\t/*\n\t**\tGo to prev category in Objects list\n\t*/\n\ti = LastChoice;\n\n\t/*\n\t**\tScan for start of this category\n\t*/\n\twhile (Objects[i]->What_Am_I() == Objects[LastChoice]->What_Am_I()) {\n\t\ti--;\n\t\tif (i < 0) {\n\t\t\ti = ObjCount - 1;\n\t\t}\n\t}\n\n\ti--;\n\tif (i < 0) i = ObjCount-1;\n\tLastChoice = i;\n\n\t/*\n\t**\tScan for the previous category\n\t*/\n\twhile (Objects[i]->What_Am_I() == Objects[LastChoice]->What_Am_I()) {\n\t\ti--;\n\t\tif (i < 0) {\n\t\t\ti = ObjCount - 1;\n\t\t}\n\t}\n\n\ti++;\n\tif (i >= ObjCount) i = 0;\n\tLastChoice = i;\n\n\t/*\n\t**\tLoop until we create a valid object\n\t*/\n\twhile (!PendingObjectPtr) {\n\n\t\t/*\n\t\t**\tGet house for this object type\n\t\t*/\n//\t\tif (!Verify_House(LastHouse, Objects[LastChoice])) {\n//\t\t\tLastHouse = Cycle_House(LastHouse, Objects[LastChoice]);\n//\t\t}\n\n\t\t/*\n\t\t**\tCreate placement object\n\t\t*/\n\t\tPendingObject = Objects[LastChoice];\n\t\tPendingHouse = LastHouse;\n\t\tPendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(PendingHouse));\n\n\t\t/*\n\t\t**\tIf this one failed, try the next\n\t\t*/\n\t\tif (!PendingObjectPtr) {\n\t\t\tPendingObject = NULL;\n\t\t\tLastChoice--;\n\t\t\tif (LastChoice < 0) {\n\t\t\t\tLastChoice = ObjCount - 1;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tSet the new cursor shape\n\t*/\n\tSet_Cursor_Pos();\n\tSet_Cursor_Shape(0);\n\tSet_Cursor_Shape(PendingObject->Occupy_List());\n\n\t/*\n\t**\tRedraw the map to erase old leftovers\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n}\n\n\n/***************************************************************************\n * MapEditClass::Place_Home -- homes the placement object                  *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/03/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Place_Home(void)\n{\n\tdelete PendingObjectPtr;\n\tPendingObjectPtr = NULL;\n\tPendingObject = NULL;\n\n\t/*\n\t** Don't allow this command if we're building a base; the only valid\n\t** category for base-building is buildings.\n\t*/\n\tif (BaseBuilding) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tLoop until we create a valid object\n\t*/\n\tLastChoice = 0;\n\twhile (!PendingObjectPtr) {\n\n\t\t/*\n\t\t**\tGet house for this object type\n\t\t*/\n\t\tif (!Verify_House(LastHouse, Objects[LastChoice])) {\n\t\t\tLastHouse = Cycle_House(LastHouse, Objects[LastChoice]);\n\t\t}\n\n\t\t/*\n\t\t**\tCreate placement object\n\t\t*/\n\t\tPendingObject = Objects[LastChoice];\n\t\tPendingHouse = LastHouse;\n\t\tPendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(PendingHouse));\n\n\t\t/*\n\t\t**\tIf this one failed, try the next\n\t\t*/\n\t\tif (!PendingObjectPtr) {\n\t\t\tPendingObject = NULL;\n\t\t\tLastChoice++;\n\t\t\tif (LastChoice == ObjCount) {\n\t\t\t\tLastChoice = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tSet the new cursor shape\n\t*/\n\tSet_Cursor_Pos();\n\tSet_Cursor_Shape(0);\n\tSet_Cursor_Shape(PendingObject->Occupy_List());\n\n\t/*\n\t**\tRedraw the map to erase old leftovers\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n}\n\n\n/***************************************************************************\n * MapEditClass::Toggle_House -- toggles current placement object's house  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/04/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Toggle_House(void)\n{\n\tTechnoClass *tp;\n\n\t/*\n\t** Don't allow this command if we're building a base; the only valid\n\t** house for base-building is the one assigned to the base.\n\t*/\n\tif (BaseBuilding) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tOnly techno objects can be owned by a house; return if not a techno\n\t*/\n\tif (!PendingObjectPtr->Is_Techno()) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tSelect the house that will own this object\n\t*/\n\tLastHouse = Cycle_House(PendingObjectPtr->Owner(), PendingObject);\n\n\t/*\n\t**\tChange the house\n\t*/\n\ttp = (TechnoClass *)PendingObjectPtr;\n\ttp->House = HouseClass::As_Pointer(LastHouse);\n\n\t/*\n\t**\tSet house variables to new house\n\t*/\n\tPendingHouse = LastHouse;\n}\n\n\n/***************************************************************************\n * MapEditClass::Set_House_Buttons -- toggles house buttons for btn list   *\n *                                                                         *\n * Looks in the given button list for the given GDI, NOD & Neutral button  *\n * id's. Sets the On/Off state of the buttons based on the given house,    *\n * only if that button is found in the list.                               *\n *                                                                         *\n * INPUT:                                                                  *\n *      house            house to set buttons to                           *\n *      btnlist         ptr to button list to search                       *\n *      base_id         button ID for GDI; assumes other id's are sequential*\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/23/1994 BR : Created.                                              *\n *   01/26/1996 JLB : Uses new house selection list method.                *\n *=========================================================================*/\nvoid MapEditClass::Set_House_Buttons(HousesType house, GadgetClass *, int )\n//void MapEditClass::Set_House_Buttons(HousesType house, GadgetClass * btnlist, int base_id)\n{\n\tHouseList->Set_Selected_Index(house);\n\n#ifdef NEVER\n\tHousesType h;\n\tint id;\n\tTextButtonClass * btn;\n\n\t/*\n\t**\tLoop through all houses, searching the button list for each one.\n\t*/\n\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\n\t\t/*\n\t\t**\tCompute the desired button ID; get a pointer to the button\n\t\t*/\n\t\tid = (int)h + base_id;\n\t\tbtn = (TextButtonClass *)btnlist->Extract_Gadget(id);\n\t\tif (btn) {\n\n\t\t\t/*\n\t\t\t**\tIf this house value is the desired one, turn the button on;\n\t\t\t**\totherwise, turn it off.\n\t\t\t*/\n\t\t\tif (h == house) {\n\t\t\t\tbtn->Turn_On();\n\t\t\t} else {\n\t\t\t\tbtn->Turn_Off();\n\t\t\t}\n\t\t}\n\t}\n#endif\n}\n\n\n/***************************************************************************\n * MapEditClass::Start_Trigger_Placement -- enters trigger placement mode  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/01/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Start_Trigger_Placement(void)\n{\n\tSet_Default_Mouse(MOUSE_CAN_MOVE);\n\tOverride_Mouse_Shape(MOUSE_CAN_MOVE);\n}\n\n\n/***************************************************************************\n * MapEditClass::Stop_Trigger_Placement -- exits trigger placement mode    *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/01/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Stop_Trigger_Placement(void)\n{\n\tCurTrigger = NULL;\n\tSet_Default_Mouse(MOUSE_NORMAL);\n\tOverride_Mouse_Shape(MOUSE_NORMAL);\n}\n\n\n/***************************************************************************\n * MapEditClass::Place_Trigger -- assigns trigger to object or cell        *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/01/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Place_Trigger(void)\n{\n\tObjectClass * object=NULL;\t\t// Generic object clicked on.\n\tint x,y;\n\tCELL cell;\t\t\t\t\t\t\t\t\t// Cell that was selected.\n\n\t/*\n\t**\tSee if an object was clicked on\n\t*/\n\tx = Keyboard->MouseQX;\n\ty = Keyboard->MouseQY;\n\n\t/*\n\t**\tGet cell for x,y\n\t*/\n\tcell = Click_Cell_Calc(x, y);\n\n\t/*\n\t**\tConvert x,y to offset from cell upper-left\n\t*/\n\tx = (x-TacPixelX) % ICON_PIXEL_W;\n\ty = (y-TacPixelY) % ICON_PIXEL_H;\n\n\t/*\n\t**\tGet object at that x,y\n\t*/\n\tobject = Cell_Object(cell, x, y);\n\n\t/*\n\t**\tAssign trigger to an object\n\t*/\n\tAttachType a1 = CurTrigger->Attaches_To();\n\tif (object && (a1 & ATTACH_OBJECT) != 0) {\n\t\tif (CurTrigger) {\n\t\t\tTriggerClass * tt = Find_Or_Make(CurTrigger);\n\t\t\tif (tt) {\n\t\t\t\tobject->Trigger = tt;\n\t\t\t}\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tAssign trigger to a cell\n\t\t*/\n\t\tif ((a1 & ATTACH_CELL) != 0) {\n\t\t\tif (CurTrigger) {\n\t\t\t\tTriggerClass * tt = Find_Or_Make(CurTrigger);\n\t\t\t\tMap[cell].Trigger = tt;\n\t\t\t}\n//\t\t\tCellTriggers[cell] = CurTrigger;\n\t\t}\n\t}\n\n\t/*\n\t**\tForce map to redraw\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n}\n\n\n/***************************************************************************\n * MapEditClass::Start_Base_Building -- starts base-building mode          *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/01/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Start_Base_Building(void)\n{\n\t/*\n\t** Fully build the base so the user can edit it\n\t*/\n\tBuild_Base_To(100);\n\n\t/*\n\t** Start placement mode\n\t*/\n\tBaseBuilding = true;\n\tStart_Placement();\n\n\t/*\n\t** Force map to redraw\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n}\n\n\n/***************************************************************************\n * MapEditClass::Cancel_Base_Building -- stops base-building mode          *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/01/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Cancel_Base_Building(void)\n{\n\t/*\n\t** Build the base to the proper amount\n\t*/\n\tBuild_Base_To(Scen.Percent);\n\n\t/*\n\t** Cancel placement mode\n\t*/\n\tCancel_Placement();\n\tBaseBuilding = false;\n\n\t/*\n\t** Force map to redraw\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n}\n\n\n/***************************************************************************\n * MapEditClass::Build_Base_To -- builds the AI base to the given percent  *\n *                                                                         *\n * INPUT:                                                                  *\n *      percent      percentage to build base to                           *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/01/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Build_Base_To(int percent)\n{\n\tint i;\n\tint num_buildings;\n\tBuildingTypeClass const * objtype;\n\tBuildingClass * obj;\n\n\t//ScenarioInit++;\n\n\t/*\n\t** Completely dismantle the base, so we start at a known point\n\t*/\n\tfor (i = 0; i < Base.Nodes.Count(); i++) {\n\t\tif (Base.Is_Built(i)) {\n\t\t\tobj = Base.Get_Building(i);\n\t\t\tdelete obj;\n\t\t}\n\t}\n\n\t/*\n\t** Compute number of buildings to build\n\t*/\n\tnum_buildings = (Base.Nodes.Count() * percent) / 100;\n\n\t/*\n\t** Build the base to the desired amount\n\t*/\n\tfor (i = 0; i < num_buildings; i++) {\n\t\t/*\n\t\t** Get a ptr to the type of building to build, create one, and unlimbo it.\n\t\t*/\n\t\tobjtype = &BuildingTypeClass::As_Reference(Base.Nodes[i].Type);\n\t\tobj = (BuildingClass *)objtype->Create_One_Of(HouseClass::As_Pointer(Base.House));\n\n\t\t/*\n\t\t** If unlimbo fails, error out\n\t\t*/\n\t\tScenarioInit++;\n\t\tif (!obj->Unlimbo(Cell_Coord(Base.Nodes[i].Cell))) {\n\t\t\tdelete obj;\n\t\t\tWWMessageBox().Process(\"Unable to build base!\");\n\t\t\tScenarioInit--;\n\t\t\treturn;\n\t\t}\n\t\tScenarioInit--;\n\t}\n\n\t//ScenarioInit--;\n}\n\n\n#endif\n"
  },
  {
    "path": "CODE/MAPEDSEL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MAPEDSEL.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : MAPEDSEL.CPP                             *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : November 18, 1994                        *\n *                                                                         *\n *                  Last Update : April 30, 1996 [JLB]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Object-selection & manipulation routines                                *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   MapEditClass::Change_House -- changes CurrentObject's house           *\n *   MapEditClass::Grab_Object -- grabs the current object                 *\n *   MapEditClass::Move_Grabbed_Object -- moves the grabbed object         *\n *   MapEditClass::Popup_Controls -- shows/hides the pop-up object controls*\n *   MapEditClass::Select_Next -- selects next object on the map           *\n *   MapEditClass::Select_Object -- selects an object for processing       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n#ifdef SCENARIO_EDITOR\n\n\n/***************************************************************************\n * Select_Object -- selects an object for processing                       *\n *                                                                         *\n * INPUT:                                                                  *\n *   none.                                                                 *\n *                                                                         *\n * OUTPUT:                                                                 *\n *   0 = object selected, -1 = none                                        *\n *                                                                         *\n * WARNINGS:                                                               *\n *   none.                                                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/04/1994 BR : Created.                                              *\n *=========================================================================*/\nint MapEditClass::Select_Object(void)\n{\n\tObjectClass\t* object=NULL;\t\t// Generic object clicked on.\n\tint\t\t\tx,y;\n\tCELL\t\t\tcell;\t\t\t\t\t// Cell that was selected.\n\tint\t\t\trc=0;\n\n\t/*\n\t**\tSee if an object was clicked on\n\t*/\n\tx = Keyboard->MouseQX;\n\ty = Keyboard->MouseQY;\n\n\t/*\n\t**\tGet cell for x,y\n\t*/\n\tcell = Click_Cell_Calc(x, y);\n\n\t/*\n\t**\tConvert x,y to offset from cell upper-left\n\t*/\n\tx = (x-TacPixelX) % ICON_PIXEL_W;\n\ty = (y-TacPixelY) % ICON_PIXEL_H;\n\n\t/*\n\t**\tGet object at that x,y\n\t*/\n\tobject = Cell_Object(cell, x, y);\n\n\t/*\n\t**\tIf no object, unselect the current one\n\t*/\n\tif (!object) {\n\t\tif (CurrentObject.Count()) {\n\n\t\t\t/*\n\t\t\t**\tUnselect all current objects\n\t\t\t*/\n\t\t\tUnselect_All();\n\n\t\t\t/*\n\t\t\t**\tTurn off object controls\n\t\t\t*/\n\t\t\tPopup_Controls();\n\t\t}\n\t\trc = -1;\n\t} else {\n\n\t\t/*\n\t\t**\tSelect object only if it's different\n\t\t*/\n\t\tif (!CurrentObject.Count() || (CurrentObject.Count() && object != CurrentObject[0])) {\n\n\t\t\t/*\n\t\t\t**\tUnselect all current objects\n\t\t\t*/\n\t\t\tUnselect_All();\n\t\t\tobject->Select();\n\n\t\t\t/*\n\t\t\t**\tSet mouse shape back to normal\n\t\t\t*/\n\t\t\tSet_Default_Mouse(MOUSE_NORMAL);\n\t\t\tOverride_Mouse_Shape(MOUSE_NORMAL);\n\n\t\t\t/*\n\t\t\t**\tShow the popup controls\n\t\t\t*/\n\t\t\tPopup_Controls();\n\t\t}\n\t}\n\n\t/*\n\t**\tForce map to redraw\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\n\treturn(rc);\n}\n\n\n/***************************************************************************\n * MapEditClass::Select_Next -- selects next object on the map             *\n *                                                                         *\n * INPUT:                                                                  *\n *   none.                                                                 *\n *                                                                         *\n * OUTPUT:                                                                 *\n *   none                                                                  *\n *                                                                         *\n * WARNINGS:                                                               *\n *   none.                                                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Select_Next(void)\n{\n\tObjectClass * obj;\n\tCELL obj_cell;\n\tint smap_w;\t\t\t\t\t\t// screen map width in icons\n\tint smap_h;\t\t\t\t\t\t// screen map height in icons\n\tint cell_x;\t\t\t\t\t\t// cell-x of next object\n\tint cell_y;\t\t\t\t\t\t// cell-y of next object\n\tint tcell_x;\t\t\t\t\t// cell-x of TacticalCell\n\tint tcell_y;\t\t\t\t\t// cell-y of TacticalCell\n\n\t/*\n\t**\tGet next object on the map\n\t*/\n\tobj = Map.Next_Object(CurrentObject[0]);\n\n\tif (obj) {\n\t\t/*\n\t\t**\tUnselect current object if there is one\n\t\t*/\n\t\tUnselect_All();\n\n\t \t/*\n\t\t**\tSelect this object\n\t\t*/\n\t\tobj->Select();\n\t}\n\n\t/*\n\t**\tRestore mouse shape to normal\n\t*/\n\tSet_Default_Mouse(MOUSE_NORMAL);\n\tOverride_Mouse_Shape(MOUSE_NORMAL);\n\n\t/*\n\t**\tShow pop-up controls\n\t*/\n\tPopup_Controls();\n\n\t/*\n\t**\tMake sure object is shown on the screen\n\t*/\n\t/*\n\t**\tcompute screen map dimensions\n\t*/\n\tsmap_w = Lepton_To_Cell(TacLeptonWidth);\n\tsmap_h = Lepton_To_Cell(TacLeptonHeight);\n\n\t/*\n\t**\tcompute x,y of object's cell\n\t*/\n\tobj_cell = Coord_Cell(CurrentObject[0]->Coord);\n\tcell_x = Cell_X(obj_cell);\n\tcell_y = Cell_Y(obj_cell);\n\ttcell_x = Coord_XCell(TacticalCoord);\n\ttcell_y = Coord_YCell(TacticalCoord);\n\n\t/*\n\t**\tIf object is off-screen, move map\n\t*/\n\tif (cell_x < tcell_x) {\n\t\ttcell_x = cell_x;\n\t} else {\n\t\tif (cell_x >= tcell_x + smap_w) {\n\t\t\ttcell_x = cell_x - smap_w + 1;\n\t\t}\n\t}\n\n\tif (cell_y < tcell_y) {\n\t\ttcell_y = cell_y;\n\t} else {\n\t\tif (cell_y >= tcell_y + smap_h) {\n\t\t\ttcell_y = cell_y - smap_h + 1;\n\t\t}\n\t}\n\n\tScenarioInit++;\n\tSet_Tactical_Position(XY_Coord(Cell_To_Lepton(tcell_x), Cell_To_Lepton(tcell_y)));\n\tScenarioInit--;\n\n\t/*\n\t**\tForce map to redraw\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n}\n\n\n/***************************************************************************\n * MapEditClass::Popup_Controls -- shows/hides the pop-up object controls  *\n *                                                                         *\n * Call this routine whenever the CurrentObject changes. The routine will  *\n * selectively enable or disable the popup controls based on whether       *\n * CurrentObject is NULL, or if it's a Techno object, or what type of      *\n * Techno object it is.                                                    *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1994 BR : Created.                                              *\n *   04/30/1996 JLB : Revamped for new buttons and stuff.                  *\n *=========================================================================*/\nvoid MapEditClass::Popup_Controls(void)\n{\n\tconst TechnoTypeClass * objtype = NULL;\n\tHousesType owner;\t\t\t\t\t\t\t// object's current owner\n\tint mission_index;\t\t\t\t\t\t// object's current mission\n\tint strength;\t\t\t\t\t\t\t\t// object's 0-255 strength value\n\tint i;\n\n\t/*\n\t**\tRemove all buttons from GScreen's button list (so none of them provide\n\t**\tinput any more); then, destroy the list by Zapping each button.  Then,\n\t**\twe'll have to add at least the MapArea button back to the Input button\n\t**\tlist before we return, plus any other buttons to process input for.  We\n\t**\talways must add MapArea LAST in the list, so it doesn't intercept the\n\t**\tother buttons' input.\n\t*/\n\tRemove_A_Button(*HouseList);\n\tRemove_A_Button(*MissionList);\n\tRemove_A_Button(*HealthGauge);\n\tRemove_A_Button(*HealthText);\n\tRemove_A_Button(*FacingDial);\n\tRemove_A_Button(*BaseGauge);\n\tRemove_A_Button(*BaseLabel);\n\tRemove_A_Button(*MapArea);\n\n\tRemove_A_Button(*Sellable);\n\tRemove_A_Button(*Rebuildable);\n\n\t/*\n\t**\tIf no current object, hide the list\n\t*/\n\tif (!CurrentObject.Count()) {\n\t\tAdd_A_Button(*BaseGauge);\n\t\tAdd_A_Button(*BaseLabel);\n\t\tAdd_A_Button(*MapArea);\n\t\treturn;\n\t}\n\n\t/*\n\t**\tIf not Techno, no need for editing buttons\n\t*/\n\tif (!CurrentObject[0]->Is_Techno()) {\n\t\tAdd_A_Button(*BaseGauge);\n\t\tAdd_A_Button(*BaseLabel);\n\t\tAdd_A_Button(*MapArea);\n\t\treturn;\n\t}\n\n\tobjtype = (TechnoTypeClass const *)&CurrentObject[0]->Class_Of();\n\n\t/*\n\t**\tGet object's current values\n\t*/\n\towner = CurrentObject[0]->Owner();\n\tmission_index = 0;\n\tfor (i = 0; i < NUM_EDIT_MISSIONS; i++) {\n\t\tif (CurrentObject[0]->Get_Mission() == MapEditMissions[i]) {\n\t\t\tmission_index = i;\n\t\t}\n\t}\n\tstrength = CurrentObject[0]->Health_Ratio()*256;\n\n\tswitch (objtype->What_Am_I()) {\n\t\tcase RTTI_VESSELTYPE:\n\t\tcase RTTI_UNITTYPE:\n\t\tcase RTTI_INFANTRYTYPE:\n\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\tMissionList->Set_Selected_Index(mission_index);\n\t\t\tHealthGauge->Set_Value(strength);\n\t\t\tsprintf(HealthBuf, \"%d\", CurrentObject[0]->Strength);\n\t\t\tFacingDial->Set_Direction(((TechnoClass *)CurrentObject[0])->PrimaryFacing);\n\n\t\t\t/*\n\t\t\t**\tMake the list.\n\t\t\t*/\n\t\t\tAdd_A_Button(*HealthGauge);\n\t\t\tAdd_A_Button(*HouseList);\n\t\t\tHouseList->Set_Selected_Index(owner);\n\t\t\tAdd_A_Button(*MissionList);\n\t\t\tAdd_A_Button(*HealthText);\n\t\t\tAdd_A_Button(*FacingDial);\n\t\t\tbreak;\n\n\t\tcase RTTI_BUILDINGTYPE:\n\t\t\tHealthGauge->Set_Value(strength);\n\t\t\tsprintf(HealthBuf, \"%d\", CurrentObject[0]->Strength);\n\t\t\tAdd_A_Button(*HealthGauge);\n\t\t\tAdd_A_Button(*HouseList);\n\t\t\tHouseList->Set_Selected_Index(owner);\n\t\t\tAdd_A_Button(*HealthText);\n\n\t\t\tAdd_A_Button(*Sellable);\n\t\t\tif (((BuildingClass*)CurrentObject[0])->IsAllowedToSell) {\n\t\t\t\tSellable->Turn_On();\n\t\t\t} else {\n\t\t\t\tSellable->Turn_Off();\n\t\t\t}\n\t\t\tAdd_A_Button(*Rebuildable);\n\t\t\tif (((BuildingClass*)CurrentObject[0])->IsToRebuild) {\n\t\t\t\tRebuildable->Turn_On();\n\t\t\t} else {\n\t\t\t\tRebuildable->Turn_Off();\n\t\t\t}\n\n\t\t\tif (objtype->IsTurretEquipped) {\n\t\t\t\tFacingDial->Set_Direction(((TechnoClass *) CurrentObject[0])->PrimaryFacing);\n\t\t\t\tAdd_A_Button(*FacingDial);\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tAdd the map area last, so it's \"underneath\" the other buttons, and won't\n\t**\tintercept input for those buttons.\n\t*/\n\tAdd_A_Button(*BaseGauge);\n\tAdd_A_Button(*BaseLabel);\n\tAdd_A_Button(*MapArea);\n}\n\n\n/***************************************************************************\n * MapEditClass::Grab_Object -- grabs the current object                   *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/07/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Grab_Object(void)\n{\n\tCELL cell;\n\n\tif (CurrentObject.Count()) {\n\t\tGrabbedObject = CurrentObject[0];\n\n\t\t/*\n\t\t**\tFind out which cell 'ZoneCell' is in relation to the object's current cell\n\t\t*/\n\t\tcell = Coord_Cell(GrabbedObject->Coord);\n\t\tGrabOffset = cell - ZoneCell;\n\t}\n}\n\n\n/***************************************************************************\n * MapEditClass::Move_Grabbed_Object -- moves the grabbed object           *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = object moved, -1 = it didn't                                   *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/07/1994 BR : Created.                                              *\n *=========================================================================*/\nint MapEditClass::Move_Grabbed_Object(void)\n{\n\tCOORDINATE new_coord = 0;\n\tint retval = -1;\n\n\t/*\n\t**\tLift up the object\n\t*/\n\tGrabbedObject->Mark(MARK_UP);\n\n\t/*\n\t**\tIf infantry, use a free spot in this cell\n\t*/\n\tif (GrabbedObject->Is_Infantry()) {\n\n\t\tif (Is_Spot_Free(Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y()))) {\n\t\t\tnew_coord = Closest_Free_Spot(Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y()));\n\n\t\t\t/*\n\t\t\t**\tClear the occupied bit in this infantry's cell.\n\t\t\t*/\n\t\t\t((InfantryClass *)GrabbedObject)->Clear_Occupy_Bit(GrabbedObject->Coord);\n\t\t} else {\n\t\t\tnew_coord = NULL;\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tNon-infantry: use cell's center coordinate\n\t\t*/\n\t\tnew_coord = Cell_Coord(ZoneCell + GrabOffset);\n\n\t\tif (GrabbedObject->What_Am_I() == RTTI_BUILDING ||\n\t\t\tGrabbedObject->What_Am_I() == RTTI_TERRAIN) {\n\n\t\t\tnew_coord = Coord_Whole(new_coord);\n\t\t}\n\n\t\t/*\n\t\t**\tTry to place object at new coordinate\n\t\t*/\n\t\tif (GrabbedObject->Can_Enter_Cell(Coord_Cell(new_coord)) != MOVE_OK) {\n\t\t\tnew_coord = NULL;\n\t\t}\n\t}\n\tif (new_coord != NULL) {\n\n\t\t/*\n\t\t** If this object is part of the AI's Base list, change the coordinate\n\t\t** in the Base's Node list.\n\t\t*/\n\t\tif (GrabbedObject->What_Am_I()==RTTI_BUILDING &&\n\t\t\tBase.Get_Node((BuildingClass *)GrabbedObject))\n\t\t\t\tBase.Get_Node((BuildingClass *)GrabbedObject)->Cell = Coord_Cell(new_coord);\n\n\t\tGrabbedObject->Coord = new_coord;\n\t\tretval = 0;\n\t}\n\tGrabbedObject->Mark(MARK_DOWN);\n\n\t/*\n\t**\tFor infantry, set the bit in its new cell marking that spot as occupied.\n\t*/\n\tif (GrabbedObject->Is_Infantry()) {\n\t\t((InfantryClass *)GrabbedObject)->Set_Occupy_Bit(new_coord);\n\t}\n\n\t/*\n\t**\tRe-select the object, and reset the mouse pointer\n\t*/\n\tSet_Default_Mouse(MOUSE_NORMAL);\n\tOverride_Mouse_Shape(MOUSE_NORMAL);\n\n\tFlag_To_Redraw(true);\n\n\treturn(retval);\n}\n\n\n/***************************************************************************\n * MapEditClass::Change_House -- changes CurrentObject's house             *\n *                                                                         *\n * INPUT:                                                                  *\n *      newhouse      house to change to                                   *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      1 = house was changed, 0 = it wasn't                               *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/17/1994 BR : Created.                                              *\n *=========================================================================*/\nbool MapEditClass::Change_House(HousesType newhouse)\n{\n\tTechnoClass *tp;\n\n\t/*\n\t**\tReturn if no current object\n\t*/\n\tif (!CurrentObject.Count()) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tOnly techno objects can be owned by a house; return if not a techno\n\t*/\n\tif (!CurrentObject[0]->Is_Techno()) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tYou can't change the house if the object is part of the AI's Base.\n\t*/\n\tif (CurrentObject[0]->What_Am_I()==RTTI_BUILDING && Base.Is_Node((BuildingClass *)CurrentObject[0])) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tVerify that the target house exists\n\t*/\n\tif (HouseClass::As_Pointer(newhouse)==NULL) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tVerify that this is a valid owner\n\t*/\n//\tif (!Verify_House(newhouse, &CurrentObject[0]->Class_Of())) {\n//\t\treturn(false);\n//\t}\n\n\t/*\n\t**\tChange the house\n\t*/\n\ttp = (TechnoClass *)CurrentObject[0];\n\ttp->House = HouseClass::As_Pointer(newhouse);\n\n\ttp->IsOwnedByPlayer = false;\n\tif (tp->House == PlayerPtr) {\n\t\ttp->IsOwnedByPlayer = true;\n\t}\n\n\treturn(true);\n}\n\n\n#endif\n"
  },
  {
    "path": "CODE/MAPEDTM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MAPEDTM.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : MAPEDTM.CPP                              *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 7, 1994                         *\n *                                                                         *\n *                  Last Update : May 7, 1996 [JLB]                        *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   MapEditClass::Draw_Member -- Draws a member of the team dialog box.   *\n *   MapEditClass::Handle_Teams -- main team-dialog-handling function      *\n *   MapEditClass::Select_Team -- user selects a team from a list          *\n *   MapEditClass::Team_Members -- user picks makeup of a team             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n#ifdef SCENARIO_EDITOR\n\n\n/***************************************************************************\n * MapEditClass::Handle_Teams -- main team-dialog-handling function        *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/08/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Handle_Teams(char const * caption)\n{\n\tint rc;\n\n\t/*\n\t**\tTeam dialog processing loop:\n\t**\t- Invoke the team selection dialog. If a team's selected, break\n\t**\t  & return\n\t**\t- If user wants to edit the current team, do so\n\t**\t- If user wants to create new team, new a TeamTypeClass & edit it\n\t**\t- If user wants to delete team, delete the current team\n\t**\t- Keep looping until 'OK'\n\t*/\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tSelect team\n\t\t*/\n\t\trc = Select_Team(caption);\n\n\t\t/*\n\t\t**\t'OK'; break\n\t\t*/\n\t\tif (rc == 0) {\n\t\t\tbreak;\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\t'Edit'\n\t\t\t*/\n\t\t\tif (rc == 1 && CurTeam) {\n\t\t\t\tif (CurTeam->Edit()) {\n\t\t\t\t\tChanged = 1;\n\t\t\t\t}\n\t\t\t\tHidPage.Clear();\n\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\tRender();\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\t'New'\n\t\t\t\t*/\n\t\t\t\tif (rc == 2) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCreate a new team\n\t\t\t\t\t*/\n\t\t\t\t\tCurTeam = new TeamTypeClass();\n\t\t\t\t\tif (CurTeam) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tdelete it if user cancels\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (!CurTeam->Edit()) {\n\t\t\t\t\t\t\tdelete CurTeam;\n\t\t\t\t\t\t\tCurTeam = NULL;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tChanged = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\t\tRender();\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tUnable to create; issue warning\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tWWMessageBox().Process(\"No more teams available.\");\n\t\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\t\tRender();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\t'Delete'\n\t\t\t\t\t*/\n\t\t\t\t\tif (rc==3) {\n\t\t\t\t\t\tif (CurTeam) {\n\t\t\t\t\t\t\tDetach_This_From_All(CurTeam->As_Target(), true);\n\t\t\t\t\t\t\tdelete CurTeam;\n\t\t\t\t\t\t\t//CurTeam->Remove();\n\t\t\t\t\t\t\tCurTeam = NULL;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * MapEditClass::Select_Team -- user selects a team from a list            *\n *                                                                         *\n *    Ŀ           *\n *                             Teams                                     *\n *        Ŀ               *\n *         Name     House    Class:Count,Class:Count  \u0018               *\n *         Name     House    Class:Count,Class:Count  Ĵ               *\n *         Name     House    Class:Count,Class:Count                  *\n *         Name     House    Class:Count,Class:Count                  *\n *                                                                    *\n *                                                                    *\n *                                                    Ĵ               *\n *                                                    \u0019               *\n *                       *\n *                                                                       *\n *          [Edit]        [New]        [Delete]      [OK]                *\n *                                                                       *\n *               *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, 1 = Edit, 2 = New, 3 = Delete                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      Uses HIDBUFF.                                                      *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/08/1994 BR : Created.                                              *\n *   05/07/1996 JLB : Streamlined and sorted team list.                    *\n *=========================================================================*/\nint MapEditClass::Select_Team(char const * )\n{\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tenum {\n\t\tD_DIALOG_W = 400,\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\t\tD_DIALOG_H = 250,\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\t\tD_DIALOG_X = 0,\t\t\t\t// centered x-coord\n\t\tD_DIALOG_Y = 0,\t\t\t\t// centered y-coord\n//\t\tD_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),\t\t// coord of x-center\n\n\t\tD_TXT8_H = 11,\t\t\t\t\t\t\t\t\t\t\t\t// ht of 8-pt text\n\t\tD_MARGIN = 25,\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\t\tD_LIST_W = (D_DIALOG_W-(D_MARGIN*2))-20,\n\t\tD_LIST_X = D_DIALOG_X + (D_DIALOG_W-D_LIST_W)/2,\n\t\tD_LIST_Y = D_DIALOG_Y + 20,\n\t\tD_LIST_H = (D_DIALOG_H-50)-D_LIST_Y,\n\n\t\tBUTTON_W = 45,\n\t\tBUTTON_H = 9,\n\n\t\tD_EDIT_W = BUTTON_W,\n\t\tD_EDIT_H = BUTTON_H,\n\t\tD_EDIT_X = D_DIALOG_X + D_DIALOG_W - (((D_EDIT_W+10)*4)+25),\n\t\tD_EDIT_Y = D_DIALOG_Y + D_DIALOG_H - 20 - D_EDIT_H,\n\n\t\tD_NEW_W = BUTTON_W,\n\t\tD_NEW_H = BUTTON_H,\n\t\tD_NEW_X = D_EDIT_X + D_EDIT_W + 10,\n\t\tD_NEW_Y = D_DIALOG_Y + D_DIALOG_H - 20 - D_NEW_H,\n\n\t\tD_DELETE_W = BUTTON_W,\n\t\tD_DELETE_H = BUTTON_H,\n\t\tD_DELETE_X = D_NEW_X + D_NEW_W + 10,\n\t\tD_DELETE_Y = D_DIALOG_Y + D_DIALOG_H - 20 - D_DELETE_H,\n\n\t\tD_OK_W = BUTTON_W,\n\t\tD_OK_H = BUTTON_H,\n\t\tD_OK_X = D_DELETE_X + D_DELETE_W + 10,\n\t\tD_OK_Y = D_DIALOG_Y + D_DIALOG_H - 20 - D_OK_H,\n\n\t\tTEAMTXT_LEN = 43,\t\t\t\t// max length of a team entry\n\t};\n\n\t/*\n\t**\tButton enumerations:\n\t*/\n\tenum {\n\t\tTEAM_LIST=100,\n\t\tBUTTON_EDIT,\n\t\tBUTTON_NEW,\n\t\tBUTTON_DELETE,\n\t\tBUTTON_OK,\n\t};\n\n\t/*\n\t**\tDialog variables\n\t*/\n\tbool edit_team = false;\t\t\t\t\t\t// true = user wants to edit\n\tbool new_team = false;\t\t\t\t\t\t// true = user wants to new\n\tbool del_team = false;\t\t\t\t\t\t// true = user wants to new\n\tstatic int tabs[] = {35, 60, 80, 100};\t// list box tab stops\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t**\tButtons\n\t*/\n\tGadgetClass * commands = NULL;\t\t\t\t// the button list\n\n\tTListClass<CCPtr<TeamTypeClass> > teamlist (TEAM_LIST,\n\t\tD_LIST_X, D_LIST_Y, D_LIST_W, D_LIST_H,\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tTextButtonClass editbtn (BUTTON_EDIT, \"Edit\", TPF_EBUTTON, D_EDIT_X, D_EDIT_Y, D_EDIT_W);\n\tTextButtonClass newbtn (BUTTON_NEW, \"New\", TPF_EBUTTON, D_NEW_X, D_NEW_Y, D_NEW_W);\n\tTextButtonClass deletebtn (BUTTON_DELETE, \"Delete\", TPF_EBUTTON, D_DELETE_X, D_DELETE_Y, D_DELETE_W);\n\tTextButtonClass okbtn (BUTTON_OK, \"OK\", TPF_EBUTTON, D_OK_X, D_OK_Y, D_OK_W);\n\n\t/*\n\t**\tInitialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tFill in team names\n\t*/\n\tfor (int index = 0; index < TeamTypes.Count(); index++) {\n\t\tteamlist.Add_Item(TeamTypes.Ptr(index));\n\t}\n\n\tPNBubble_Sort(&teamlist[0], teamlist.Count());\n\n\tif (!CurTeam || !CurTeam->IsActive) CurTeam = NULL;\n\n\tif (CurTeam) {\n\t\tteamlist.Set_Selected_Index(CurTeam);\n\t\tCurTeam = teamlist.Current_Item();\n\t} else {\n\t\tteamlist.Set_Selected_Index(0);\n\t\tif (TeamTypes.Count()) {\n\t\t\tCurTeam = teamlist.Current_Item();\n\t\t}\n\t}\n\n\t/*\n\t**\tCreate the list\n\t*/\n\tcommands = &teamlist;\n\teditbtn.Add_Tail(*commands);\n\tnewbtn.Add_Tail(*commands);\n\tdeletebtn.Add_Tail(*commands);\n\tokbtn.Add_Tail(*commands);\n\n\t/*\n\t**\tInit tab stops for list\n\t*/\n\tteamlist.Set_Tabs(tabs);\n\n\t/*\n\t**\tMain Processing Loop\n\t*/\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if needed\n\t\t*/\n\t\tif (display /*&& LogicPage->Lock()*/) {\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\t\t\tDraw_Caption(TXT_TEAM_EDIT, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\t\t\tcommands->Draw_All();\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n//\t\t\tLogicPage->Unlock();\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t**\tProcess input\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (TEAM_LIST | KN_BUTTON):\n\t\t\t\tCurTeam = teamlist.Current_Item();\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_EDIT | KN_BUTTON):\n\t\t\t\tif (teamlist.Count()) {\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tedit_team = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_NEW | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tnew_team = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_DELETE | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tdel_team = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tRedraw the display\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n\n\tif (edit_team) return(1);\n\tif (new_team) return(2);\n\tif (del_team) return(3);\n\treturn(0);\n}\n\n\n/***************************************************************************\n * MapEditClass::Team_Members -- user picks makeup of a team               *\n *                                                                         *\n * Team members are rendered in a 24 x 24 area; the Window coordinates     *\n * have to be set to this area when the object's 'Display()' routine is    *\n * called. Thus, the dialog's window coords have to be divisible by        *\n * 24. The height of the dialog is computed based on how many objects      *\n * there are in it.                                                        *\n *                                                                         *\n * 10 pixels are left between rows of objects, so the # of that type of    *\n * object can be displayed underneath the object.                          *\n *                                                                         *\n *  Ŀ                    *\n *                   Team Members                                        *\n *                                                                       *\n *    Ŀ                      *\n *                                                           *\n *    Ĵ                      *\n *                                                           *\n *    Ĵ                      *\n *                                                           *\n *    Ĵ                      *\n *                                                           *\n *    Ĵ                      *\n *                                                           *\n *    Ĵ                      *\n *                                                           *\n *                          *\n *                 [OK]      [Cancel]                                    *\n *                      *\n *                                                                         *\n * INPUT:                                                                  *\n *      house      house to display objects for                            *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, -1 = cancel                                                *\n *                                                                         *\n * WARNINGS:                                                               *\n *      CurTeam must NOT be NULL when this function is called.             *\n *      This routine uses HIDBUFF for data storage.                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/07/1994 BR : Created.                                              *\n *=========================================================================*/\n//#define TEENSY_WEENSY\n/*\n**\tDialog & button dimensions\n*/\nenum {\n\tD_DIALOG_W = 640,\n\tD_DIALOG_X = 0,\n\tD_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),\n\n\tD_TXT6_H = 7,\n\tD_MARGIN = 7,\n\n#ifdef TEENSY_WEENSY\n\tD_PICTURE_W = 32,\n\tD_PICTURE_H = 24,\n#else\n\tD_PICTURE_W = 64,\n\tD_PICTURE_H = 48,\n#endif\n\tD_ROW_H = (D_PICTURE_H + 3),\n\n\tD_OK_W = 50,\n\tD_OK_H = 9,\n\tD_OK_X = D_DIALOG_CX - 5 - D_OK_W,\n\tD_OK_Y = 0,\n\n\tD_CANCEL_W = 50,\n\tD_CANCEL_H = 9,\n\tD_CANCEL_X = D_DIALOG_CX + 5,\n\tD_CANCEL_Y = 0,\n\n};\n\nint MapEditClass::Team_Members(HousesType house)\n{\n\t/*\n\t**\tButton enumerations:\n\t*/\n\tenum {\n\t\tBUTTON_OK = 100,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t/*\n\t**\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t**\t(highest enum is the lowest layer). Each section of the map checks\n\t**\tthe requested redraw level to see if it's supposed to draw; if it's\n\t**\t>= its level, it redraws.\n\t*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\tRedrawType display;\t\t\t\t\t\t\t// requested redraw level\n\tbool process;\t\t\t\t\t\t\t\t\t// loop while true\n\n\t/*\n\t**\tDialog variables\n\t*/\n\tKeyNumType input;\t\t\t\t\t\t\t\t// user input\n\tbool cancel = false;\t\t\t\t\t\t\t// true = user cancels\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t**\tTeam display variables\n\t*/\n\tconst TechnoTypeClass **teamclass;\t\t// array of team classes\n\tint *teamcount;\t\t\t\t\t\t\t\t// array of class counts\n\tint numcols;\t\t\t\t\t\t\t\t\t// # units displayed horizontally\n\tint numrows;\t\t\t\t\t\t\t\t\t// # units displayed vertically\n\n\t/*\n\t**\tDialog dimensions.\n\t*/\n\tint dlg_y;\n\tint dlg_h;\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint msg_y;\t\t\t\t\t\t\t\t\t\t// y-coord for object names\n\n\tint curclass = -1;\t\t\t// current index into 'teamclass'; can be invalid!\n\t\t\t\t\t\t\t\t\t\t// (is based on current mouse position)\n\tint numclasses;\t\t\t\t// current # classes in the team (limited to <=5)\n\tint maxclasses;\t\t\t\t// max # classes available\n\tint i,j;\n\n\t/*\n\t**\tValues for timing when mouse held down.\n\t*/\n\tint lheld = 0;\n\tint rheld = 0;\n\tlong tdelay[3] = {5, 20, 0};\n\tint tindex = 0;\n\tlong heldtime;\n\n\t/*\n\t**\tButtons.\n\t*/\n\tControlClass * commands;\n\n\tTextButtonClass okbtn (BUTTON_OK, TXT_OK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW, D_OK_X, D_OK_Y, D_OK_W, D_OK_H);\n\tTextButtonClass cancelbtn (BUTTON_CANCEL, TXT_CANCEL, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W, D_CANCEL_H);\n\n\t/*\n\t**\tSet up the team data arrays (ObjectTypeClass pointers & count)\n\t*/\n#ifdef WIN32\n\tteamclass = (const TechnoTypeClass **)SysMemPage.Get_Buffer();\n\tteamcount = (int *)SysMemPage.Get_Buffer() + MAX_TEAM_CLASSES * sizeof (ObjectTypeClass *);\n#else\n\tteamclass = (const TechnoTypeClass **)HidPage.Get_Buffer();\n\tteamcount = (int *)HidPage.Get_Buffer() + MAX_TEAM_CLASSES * sizeof (ObjectTypeClass *);\n#endif\n\n\t/*\n\t**\tFill in the ObjectTypeClass array with all available object type ptrs,\n\t**\tchecking to be sure this house can own the object\n\t*/\n\ti = 0;\n\tfor (InfantryType i_id = INFANTRY_FIRST; i_id < INFANTRY_COUNT; i_id++) {\n\t\tteamclass[i] = &InfantryTypeClass::As_Reference(i_id);\n\t\ti++;\n\t}\n\n\tfor (AircraftType a_id = AIRCRAFT_FIRST; a_id < AIRCRAFT_COUNT; a_id++) {\n\t\tteamclass[i] = &AircraftTypeClass::As_Reference(a_id);\n\t\ti++;\n\t}\n\n\tfor (UnitType u_id = UNIT_FIRST; u_id < UNIT_COUNT; u_id++) {\n\t\tteamclass[i] = &UnitTypeClass::As_Reference(u_id);\n\t\ti++;\n\t}\n\n\tfor (VesselType v_id = VESSEL_FIRST; v_id < VESSEL_COUNT; v_id++) {\n\t\tteamclass[i] = &VesselTypeClass::As_Reference(v_id);\n\t\ti++;\n\t}\n\n\t/*\n\t**\tSave max # classes.\n\t*/\n\tmaxclasses = i;\n\n\t/*\n\t**\tFill in the 'count' array with data from the current team:\n\t**\t- For every class in the current team, find that class type in the\n\t**\t  'teamclass' array & set its count value\n\t*/\n\tfor (j = 0; j < maxclasses; j++) {\n\t\tteamcount[j] = 0;\n\t}\n\n\t/*\n\t**\tLoop through all classes in the team.\n\t*/\n\tfor (i = 0; i < CurTeam->ClassCount; i++) {\n\n\t\t/*\n\t\t**\tFind this class in our array.\n\t\t*/\n\t\tfor (j = 0; j < maxclasses; j++) {\n\n\t\t\t/*\n\t\t\t**\tSet the count; detect a match between the team's class & the\n\t\t\t**\t'teamclass' array entry by comparing the actual pointers; typeid\n\t\t\t**\twon't work because E1 & E2 are the same type class.\n\t\t\t*/\n\t\t\tif (CurTeam->Members[i].Class == teamclass[j]) {\n\t\t\t\tteamcount[j] = CurTeam->Members[i].Quantity;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tnumclasses = CurTeam->ClassCount;\n\n\t/*\n\t**\tSet up the dialog dimensions based on number of classes we have to draw\n\t**\n\t**\tCompute picture rows & cols.\n\t*/\n\tnumcols = (D_DIALOG_W - 16) / D_PICTURE_W;\n\tnumrows = (maxclasses + numcols - 1) / numcols;\n\n\t/*\n\t**\tDialog's height = top margin + label + picture rows + margin + label + margin + btn\n\t*/\n\tdlg_h = 400;\n\tdlg_y = 0;\n\tmsg_y = dlg_y+dlg_h - 26 - 15;\n\n\tokbtn.Y = dlg_y + dlg_h - D_MARGIN - D_OK_H - 15;\n\tcancelbtn.Y = dlg_y + dlg_h - D_MARGIN - D_CANCEL_H - 15;\n\n\t/*\n\t**\tDraw to SeenPage.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tMake sure 'house' is valid.\n\t*/\n//\tif (house!=HOUSE_GOOD && house!=HOUSE_BAD && house != HOUSE_MULTI1 &&\n//\t\thouse != HOUSE_MULTI2 && house != HOUSE_MULTI3 && house != HOUSE_MULTI4 ) {\n//\t\tif (Scen.ScenPlayer == SCEN_PLAYER_MPLAYER) {\n//\t\t\thouse = HOUSE_MULTI1;\n//\t\t} else {\n//\t\t\thouse = HOUSE_GOOD;\n//\t\t}\n//\t}\n\n\t/*\n\t**\tCreate the list.\n\t*/\n\tcommands = &okbtn;\n\tcancelbtn.Add_Tail(*commands);\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tdisplay = REDRAW_ALL;\n\tprocess = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\n\t\t\t/*\n\t\t\t**\tDisplay the dialog box.\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDisplay the constant background of this dialog.\n\t\t\t\t*/\n\t\t\t\tDialog_Box(D_DIALOG_X, dlg_y, D_DIALOG_W, dlg_h);\n\t\t\t\tDraw_Caption(TXT_TEAM_MEMBERS, D_DIALOG_X, dlg_y, D_DIALOG_W);\n\n\t\t\t\t/*\n\t\t\t\t**\tDraw the objects.\n\t\t\t\t*/\n\t\t\t\tfor (i = 0; i < maxclasses; i++) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDisplay the object along with any count value for it.\n\t\t\t\t\t*/\n\t\t\t\t\tDraw_Member(teamclass[i], i, teamcount[i], house);\n\t\t\t\t}\n\n\t\t\t\tif ((unsigned)curclass < maxclasses) {\n\t\t\t\t\tFancy_Text_Print(teamclass[curclass]->Full_Name(),\n\t\t\t\t\t\tD_DIALOG_X + D_DIALOG_W / 2, msg_y,\n\t\t\t\t\t\t&ColorRemaps[PCOLOR_BROWN], TBLACK,\n\t\t\t\t\t\tTPF_CENTER|TPF_EFNT|TPF_NOSHADOW);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRedraw the buttons.\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcommands->Draw_All();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\t/*\n\t\t**\tProcess input.\n\t\t*/\n\t\tswitch (input) {\n\n\t\t\t/*\n\t\t\t**\tMouse buttons set or clear 'held' values\n\t\t\t*/\n\t\t\tcase (KN_LMOUSE):\n\t\t\t\tif (curclass >= 0 && curclass < maxclasses) {\n\t\t\t\t\tlheld = 1;\n\t\t\t\t\ttindex = 2;\n\t\t\t\t\theldtime = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RMOUSE):\n\t\t\t\tif (curclass >= 0 && curclass < maxclasses) {\n\t\t\t\t\trheld = 1;\n\t\t\t\t\ttindex = 2;\n\t\t\t\t\theldtime = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ((int)KN_LMOUSE | (int)KN_RLSE_BIT):\n\t\t\t\tlheld = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase ((int)KN_RMOUSE | (int)KN_RLSE_BIT):\n\t\t\t\trheld = 0;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tOK: save values & return.\n\t\t\t*/\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tCancel: abort & return.\n\t\t\t*/\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tcancel = true;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\t/*\n\t\t\t\t**\tCompute new 'curclass' based on mouse position.\n\t\t\t\t*/\n\t\t\t\ti = (Get_Mouse_X() - 32 - D_DIALOG_X) / D_PICTURE_W +\n\t\t\t\t\t((Get_Mouse_Y() - (dlg_y+8+11)) / D_ROW_H) * numcols;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf it's changed, update class label.\n\t\t\t\t*/\n\t\t\t\tif (i != curclass) {\n\n\t\t\t\t\tcurclass = i;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tClear out the previously printed name of the item.\n\t\t\t\t\t*/\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tLogicPage->Fill_Rect(D_DIALOG_X + 32, msg_y, D_DIALOG_X + D_DIALOG_W - 64, msg_y + D_TXT6_H, BLACK);\n\n\t\t\t\t\tif ((unsigned)curclass < maxclasses) {\n\t\t\t\t\t\tFancy_Text_Print(teamclass[curclass]->Full_Name(),\n\t\t\t\t\t\t\tD_DIALOG_X + D_DIALOG_W / 2, msg_y, scheme, TBLACK, TPF_CENTER|TPF_EFNT|TPF_NOSHADOW);\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tForce buttons to not be held.\n\t\t\t\t\t*/\n\t\t\t\t\tlheld = 0;\n\t\t\t\t\trheld = 0;\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tCheck for a 'held' mouse button; if it's down, and the correct\n\t\t**\tamount of time has gone by, increment/decrement the count for the\n\t\t**\tcurrent class.\n\t\t*/\n\t\tif (lheld) {\n\n\t\t\t/*\n\t\t\t**\tThe first time in, TickCount - heldtime will be larger than\n\t\t\t**\ttdelay[2], so we increment the count immediately; then, we decrement\n\t\t\t**\ttindex to go to the next time delay, which is longer; then, decr.\n\t\t\t**\tagain to go to the 1st time delay which is the shortest.\n\t\t\t*/\n\t\t\tif (TickCount - heldtime > tdelay[tindex]) {\n\t\t\t\theldtime = TickCount;\n\t\t\t\tif (tindex) {\n\t\t\t\t\ttindex--;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tDetect addition of a new class.\n\t\t\t\t*/\n\t\t\t\tif (teamcount[curclass]==0) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDon't allow more classes than we can handle.\n\t\t\t\t\t*/\n\t\t\t\t\tif (numclasses == TeamTypeClass::MAX_TEAM_CLASSCOUNT) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tnumclasses++;\n\t\t\t\t}\n\t\t\t\tteamcount[curclass]++;\n\n\t\t\t\t/*\n\t\t\t\t**\tUpdate number label.\n\t\t\t\t*/\n\t\t\t\tDraw_Member(teamclass[curclass], curclass, teamcount[curclass], house);\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif (rheld) {\n\n\t\t\t\t/*\n\t\t\t\t**\tThe first time in, TickCount - heldtime will be larger than\n\t\t\t\t**\ttdelay[2], so we increment the count immediately; then, we decrement\n\t\t\t\t**\ttindex to go to the next time delay, which is longer; then, decr.\n\t\t\t\t**\tagain to go to the 1st time delay which is the shortest.\n\t\t\t\t*/\n\t\t\t\tif (TickCount - heldtime > tdelay[tindex]) {\n\t\t\t\t\tif (tindex) {\n\t\t\t\t\t\ttindex--;\n\t\t\t\t\t}\n\t\t\t\t\theldtime = TickCount;\n\n\t\t\t\t\tif (teamcount[curclass] > 0) {\n\t\t\t\t\t\tteamcount[curclass]--;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDetect removal of a class.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (teamcount[curclass] == 0) {\n\t\t\t\t\t\t\tnumclasses--;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tUpdate number label.\n\t\t\t\t\t*/\n\t\t\t\t\tDraw_Member(teamclass[curclass], curclass, teamcount[curclass], house);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCopy data into team.\n\t*/\n\tif (!cancel) {\n\t\tCurTeam->ClassCount = numclasses;\n\t\ti = 0;\t\t// current team class index\n\t\tfor (j = 0; j < maxclasses; j++) {\n\t\t\tif (teamcount[j] > 0) {\n\t\t\t\tCurTeam->Members[i].Quantity = teamcount[j];\n\t\t\t\tCurTeam->Members[i].Class = teamclass[j];\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tRedraw the display.\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n\n\tif (cancel) return(-1);\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * MapEditClass::Draw_Member -- Draws a member of the team dialog box.                         *\n *                                                                                             *\n *    This routine will display the cameo image of the potential team member. In the corner,   *\n *    it will show the current quantity of this member for the current team being edited.      *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the member object type.                                        *\n *                                                                                             *\n *          index -- The index into the team dialog box array of selectable objects. This is   *\n *                   used to determine the correct X and Y offsets to draw.                    *\n *                                                                                             *\n *          quant -- The quantity number to display in the corner of the image.                *\n *                                                                                             *\n *          house -- The owner of this object.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MapEditClass::Draw_Member(TechnoTypeClass const * ptr, int index, int quant, HousesType house)\n{\n\tint numcols = (D_DIALOG_W - 64) / D_PICTURE_W;\n\tint col = index % numcols;\n\tint row = index / numcols;\n\tint dlg_y = 0;\n\tint x = D_DIALOG_X + 32 + col * D_PICTURE_W;\n\tint y = dlg_y + 8 + 13 + row * D_ROW_H;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t**\tChange the window to this box.\n\t*/\n\tWindowList[WINDOW_EDITOR][WINDOWX] = x;\n\tWindowList[WINDOW_EDITOR][WINDOWY] = y;\n\tWindowList[WINDOW_EDITOR][WINDOWWIDTH] = D_PICTURE_W;\n\tWindowList[WINDOW_EDITOR][WINDOWHEIGHT] = D_PICTURE_H;\n\tChange_Window((int)WINDOW_EDITOR);\n\n\tHide_Mouse();\n\tDraw_Box(x, y, D_PICTURE_W, D_PICTURE_H, BOXSTYLE_DOWN, true);\n\tptr->Display(WinW/2, WinH>>1, WINDOW_EDITOR, house);\n\tif (quant > 0) {\n\t\tFancy_Text_Print(\"%d\", x+1, y+1, scheme, TBLACK, TPF_8POINT|TPF_DROPSHADOW, quant);\n//\t\tFancy_Text_Print(\"%d\", x+1, y+D_PICTURE_H-8, scheme, TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_DROPSHADOW, quant);\n\t}\n\tShow_Mouse();\n}\n\n\n#endif\n"
  },
  {
    "path": "CODE/MAPSEL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MAPSEL.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MAPSEL.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Barry W. Green                                               *\n *                                                                                             *\n *                   Start Date : April 17, 1995                                               *\n *                                                                                             *\n *                  Last Update : April 27, 1995   [BWG]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Bit_It_In -- Pixel fade graphic copy.                                                     *\n *   Map_Selection -- Starts the whole process of selecting next map to go to                  *\n *   Print_Statistics -- Prints statistics on country selected                                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\nvoid Cycle_Call_Back_Delay(int time, PaletteClass &pal);\nextern int ControlQ;\n\nint Mouse_Over_Spot(int house, int scenario);\nvoid Set_Mouse(MouseType shape, int &start, int &count, int &delay, int &xspot, int &yspot);\n//VG for ant mission progression\nconst char* antmission[] = {NULL, \"SCA01EA.INI\", \"SCA02EA.INI\", \"SCA03EA.INI\", \"SCA04EA.INI\"};\n\nstruct point {\n\tint x;\n\tint y;\n} const MapCoords[2][14][3] = {\n {\n {{185,123},{ -1, -1},{ -1, -1}},\n {{173,112},{ -1, -1},{ -1, -1}},\n {{196,100},{200,112},{ -1, -1}},\n {{175,113},{ -1, -1},{ -1, -1}},\n {{187, 91},{202, 93},{206,105}},\n {{207,161},{212,172},{ -1, -1}},\n {{172, 92},{ -1, -1},{ -1, -1}},\n {{132,119},{146,125},{ -1, -1}},\n {{199, 73},{205, 86},{ -1, -1}},\n {{236,114},{ -1, -1},{ -1, -1}},\n {{219, 64},{225, 76},{ -1, -1}},\n {{256, 69},{ -1, -1},{ -1, -1}},\n {{262, 77},{ -1, -1},{ -1, -1}},\n {{249, 97},{ -1, -1},{ -1, -1}}\n },\n// Soviet coords\n {\n {{178,105},{ -1, -1},{ -1, -1}},\n {{163,101},{163,113},{ -1, -1}},\n {{160, 89},{ -1, -1},{ -1, -1}},\n {{142,101},{142,117},{ -1, -1}},\n {{212,163},{ -1, -1},{ -1, -1}},\n {{155,133},{171,144},{ -1, -1}},\n {{216,103},{ -1, -1},{ -1, -1}},\n {{132,145},{154,154},{ -1, -1}},\n {{122,117},{ -1, -1},{ -1, -1}},\n {{117,130},{ -1, -1},{ -1, -1}},\n {{ 99,107},{109,146},{ -1, -1}},\n {{134,125},{ -1, -1},{ -1, -1}},\n {{ 32,156},{ 46,171},{ -1, -1}},\n {{108, 97},{ -1, -1},{ -1, -1}}\n }\n};\n\n#ifndef WIN32\nextern short StreamLowImpact;\n#endif  //WIN32\n\n/***********************************************************************************************\n * Map_Selection -- Starts the whole process of selecting next map to go to                    *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nextern int CopyType;\n#ifndef WIN32\nextern short StreamLowImpact;\n#endif\nchar const * Map_Selection(void)\n{\n\tstatic char scenarioname[_MAX_FNAME+_MAX_EXT];\n\n#ifdef FIXIT_ANTS\n\tif (AntsEnabled)  {\n\t\tstrcpy(scenarioname, Scen.ScenarioName);\n\t\tchar buf[10];\n\t\tsprintf(buf, \"%02d\", Scen.Scenario+1);\n\t\tmemcpy(&scenarioname[3], buf, 2);\n\t\treturn(scenarioname);\n\t}\n\n#endif\n\tchar _filename[]=\"MSAA.WSA\";\n\tint house = (PlayerPtr->Class->House == HOUSE_USSR || PlayerPtr->Class->House == HOUSE_UKRAINE);\n\n\t_filename[2] = house ? 'S' : 'A';\n\t_filename[3] = Scen.Scenario + 'A';\n\tPaletteClass mappalette;\n\n\tint scenario = Scen.Scenario;\n\tint selection;\n\tstatic CDTimerClass<SystemTimerClass> timer;\n\tint start = 0;\n\tint count = 0;\n\tint delay = 0;\n\tint xspot = 0;\n\tint yspot = 0;\n\n\tvoid const * appear1 =  MFCD::Retrieve(\"MAPWIPE2.AUD\");\n\tvoid const * bleep11  = MFCD::Retrieve(\"BLEEP11.AUD\");\n\tvoid const * country4 = MFCD::Retrieve(\"MAPWIPE5.AUD\");\n\tvoid const * toney7 =   MFCD::Retrieve(\"TONEY7.AUD\");\n\tvoid const * bleep17  = MFCD::Retrieve(\"BLEEP17.AUD\");\n\n\tvoid const * scold1 =   MFCD::Retrieve(\"TONEY4.AUD\");\n\tvoid const * country1 = MFCD::Retrieve(\"TONEY10.AUD\");\n\n#ifdef WIN32\n\tGraphicBufferClass *pseudoseenbuff = new GraphicBufferClass(320, 200, (void*)NULL);\n#endif\n\n//\tfixed oldvolume = Options.ScoreVolume;\n//\tOptions.Set_Score_Volume(fixed(4, 10));\n\tTheme.Queue_Song(THEME_MAP);\n\n\tvoid *anim = Open_Animation(_filename, NULL, 0L, (WSAOpenType)(WSA_OPEN_FROM_MEM | WSA_OPEN_TO_PAGE), mappalette);\n\n\tKeyboard->Clear();\n\tSeenPage.Clear();\n\tmappalette.Set(FADE_PALETTE_FAST, Call_Back);\n\n#ifdef WIN32\n\tpseudoseenbuff->Clear();\n\tAnimate_Frame(anim, *pseudoseenbuff, 1);\n\tfor(int x=0; x<256; x++) memset(&PaletteInterpolationTable[x][0],x,256);\n\tCopyType = 1;\n\tInterpolate_2X_Scale(pseudoseenbuff , &SeenBuff , 0);\n#else\n\tHidPage.Clear();\n\tAnimate_Frame(anim, HidPage, 1);\n\tHidPage.Blit(SeenPage);\n#endif\n\n\n\tint frame = 1;\n\tStreamLowImpact = true;\n#ifdef WIN32\n\tPlay_Sample(appear1, 255, Options.Normalize_Volume(170));\n#else\n\tPlay_Sample(appear1, 255, Options.Normalize_Volume(55));\n#endif\n\twhile (frame < Get_Animation_Frame_Count(anim)) {\n#ifdef WIN32\n\t\tCopyType = 1;\n\t\tAnimate_Frame(anim, *pseudoseenbuff, frame++);\n\t\tInterpolate_2X_Scale(pseudoseenbuff , &SeenBuff , NULL);\n\t\tCopyType = 0;\n#else\n\t\tAnimate_Frame(anim, SeenPage, frame++);\n#endif\n\t\tCall_Back_Delay(2);\n\t\tswitch(frame) {\n\t\t\tcase 16:\n#ifdef WIN32\n\t\t\t\tPlay_Sample(bleep11, 255, Options.Normalize_Volume(170));\n#else\n\t\t\t\tPlay_Sample(bleep11, 255, Options.Normalize_Volume(55));\n#endif\n\t\t\t\tbreak;\n\t\t\tcase 30:\n#ifdef WIN32\n\t\t\t\tPlay_Sample(country4, 255, Options.Normalize_Volume(170));\n#else\n\t\t\t\tPlay_Sample(country4, 255, Options.Normalize_Volume(55));\n#endif\n\t\t\t\tbreak;\n\t\t\tcase 51:\n#ifdef WIN32\n\t\t\t\tPlay_Sample(toney7, 255, Options.Normalize_Volume(170));\n#else\n\t\t\t\tPlay_Sample(toney7, 255, Options.Normalize_Volume(55));\n#endif\n\t\t\t\tbreak;\n\t\t\tcase 61:\n#ifdef WIN32\n\t\t\t\tPlay_Sample(bleep17, 255, Options.Normalize_Volume(170));\n#else\n\t\t\t\tPlay_Sample(bleep17, 255, Options.Normalize_Volume(55));\n#endif\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tStreamLowImpact = false;\n\tCall_Back();\n\tClose_Animation(anim);\n\tShow_Mouse();\n\tKeyboard->Clear();\n\n\tbool done = 0;\n\tMouseType shape = MOUSE_NORMAL;\n\twhile (!done) {\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tCopyType = 1;\n\t\t\tInterpolate_2X_Scale(pseudoseenbuff , &SeenBuff , NULL);\n\t\t\tCopyType = 0;\n\t\t}\n#endif\n\t\tCycle_Call_Back_Delay(1, mappalette);\n\t\tint choice = Mouse_Over_Spot(house, scenario);\n\t\tif (choice == -1) {\n\t\t\tshape = MOUSE_NORMAL;\n\t\t} else {\n\t\t\tshape = MOUSE_CAN_ATTACK;\n\t\t}\n\n\t\tSet_Mouse(shape, start, count, delay, xspot, yspot);\n\t\tif (timer == 0) {\n\t\t\tframe++;\n\t\t\tframe %= count;\n\t\t\ttimer = delay;\n\t\t\tSet_Mouse_Cursor(xspot, yspot, Extract_Shape(MouseClass::MouseShapes, start + frame));\n\t\t}\n\t\tif (Keyboard->Check()) {\n\t\t\tif ((Keyboard->Get() & 0x10FF) == KN_LMOUSE) {\n\t\t\t\tif (choice != -1) {\n\t\t\t\t\tdone = 1;\n\t\t\t\t\tselection = choice;\n#ifdef WIN32\n\t\t\t\t\tPlay_Sample(country1, 255, Options.Normalize_Volume(170));\n#else\n\t\t\t\t\tPlay_Sample(country1, 255, Options.Normalize_Volume(50));\n#endif\n\t\t\t\t} else {\n#ifdef WIN32\n\t\t\t\t\tPlay_Sample(scold1, 255, Options.Normalize_Volume(170));\n#else\n\t\t\t\t\tPlay_Sample(scold1, 255, Options.Normalize_Volume(50));\n#endif\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tHide_Mouse();\n\n\t/*\n\t** Restore the mouse to normal shape before leaving this routine.\n\t*/\n\tSet_Mouse(MOUSE_NORMAL, start, count, delay, xspot, yspot);\n\tSet_Mouse_Cursor(xspot, yspot, Extract_Shape(MouseClass::MouseShapes, start));\n\n\tKeyboard->Clear();\n//\tBlackPalette.Set(FADE_PALETTE_SLOW, Call_Back);\n//\tSeenPage.Clear();\n\n\tFancy_Text_Print(TXT_STAND_BY, 160 * RESFACTOR, 190 * RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_DROPSHADOW);\n\n\t/*\n\t**\tCreate the new scenario filename from the selection. The filename is\n\t**\tderived from the previous filename but it has the scenario number\n\t**\tincremented and the chosen variation set.\n\t*/\n\n\t//V.G. added so Ant Missions would progress\n\tif(Scen.ScenarioName[2] == 'A'){\n\t   int antnum = Scen.Scenario++;\t\n\t   if(antnum > 4) antnum = 1;\t\n\t   strcpy(scenarioname, antmission[antnum]);\n\t}\n\telse{\n\t\tstrcpy(scenarioname, Scen.ScenarioName);\n\t\tchar buf[10];\n\t\tsprintf(buf, \"%02d\", Scen.Scenario+1);\n\t\tmemcpy(&scenarioname[3], buf, 2);\n\t\tscenarioname[6] = 'A' + selection;\n\t}\n\tTheme.Fade_Out();\n//\tOptions.Set_Score_Volume(oldvolume);\n\n//\tScen.ScenVar = (ScenarioVarType)selection;\n//Mono_Printf(\"Chose variant %d  \\n\", selection);\n\treturn(scenarioname);\n}\n\nint Mouse_Over_Spot(int house, int scenario)\n{\n\tint retval = -1;\n\tfor (int selection = 0; selection < 3 && MapCoords[house][scenario][selection].x != -1; selection++) {\n\t\tint mousex = Get_Mouse_X() / RESFACTOR;\n\t\tint mousey = Get_Mouse_Y() / RESFACTOR;\n\t\tif (mousex >= MapCoords[house][scenario][selection].x &&\n\t\t\t mousey >= MapCoords[house][scenario][selection].y &&\n\t\t\t mousex <= MapCoords[house][scenario][selection].x+11 &&\n\t\t\t mousey <= MapCoords[house][scenario][selection].y+9) {\n\n\t\t\tretval = selection;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn(retval);\n}\nvoid Cycle_Call_Back_Delay(int time, PaletteClass &pal)\n{\n\tstatic CDTimerClass<SystemTimerClass> _ftimer;\n\tstatic bool _up = false;\n\tstatic int val = 255;\n\n\twhile(time--) {\n\t\t/*\n\t\t**\tProcess the fading white color.\n\t\t*/\n\t\tif (!_ftimer) {\n\t\t\t_ftimer = TIMER_SECOND/6;\n\n\t\t\t#define\tSTEP_RATE\t20\n\t\t\tif (_up) {\n\t\t\t\tval += STEP_RATE;\n\t\t\t\tif (val > 150) {\n\t\t\t\t\tval = 150;\n\t\t\t\t\t_up = false;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tval -= STEP_RATE;\n\t\t\t\tif (val < 0x20) {\n\t\t\t\t\tval = 0x20;\n\t\t\t\t\t_up = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSet the pulse color as the proportional value between white and the\n\t\t\t**\tminimum value for pulsing.\n\t\t\t*/\n\t\t\tpal[254] = GamePalette[WHITE];\n\t\t\tpal[254].Adjust(val, BlackColor);\n\n\t\t\tpal.Set();\n\t\t}\n\t\tCall_Back_Delay(1);\n\t}\n}\n\nvoid Set_Mouse(MouseType shape, int &start, int &count, int &delay, int &xspot, int &yspot)\n{\n\tswitch(shape) {\n\t\tcase MOUSE_NORMAL:\n\t\t\tstart = 0;\n\t\t\tcount = 1;\n\t\t\tdelay = 0;\n\t\t\txspot = 0;\n\t\t\tyspot = 0;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tstart = 21;\n\t\t\tcount = 8;\n\t\t\tdelay = 4;\n\t\t\txspot = 14;\n\t\t\tyspot = 11;\n\t\t\tbreak;\n\t}\n}\n"
  },
  {
    "path": "CODE/MCI.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n* FILE\n*     MCI.cpp\n*\n* DESCRIPTION\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     6/22/98\n*\n****************************************************************************/\n\n#include \"function.h\"\n\n#ifdef MCIMPEG\n#include \"mci.h\"\n\n/****************************************************************************\n*\n* NAME\n*     GetDeviceCount()\n*\n* DESCRIPTION\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Count - Number of MCI device entries\n*\n****************************************************************************/\n\nunsigned int MCI::GetDeviceCount(void)\n\t{\n\tMCIERROR rc;\n\tMCI_SYSINFO_PARMS sysInfo;\n\tunsigned int count;\n\n\tmemset(&sysInfo, 0, sizeof(sysInfo));\n\tsysInfo.lpstrReturn = (LPSTR)&count;\n\tsysInfo.dwRetSize = sizeof(count);\n\n\trc = mciSendCommand(MCI_ALL_DEVICE_ID, MCI_SYSINFO,\n\t\t\tMCI_WAIT | MCI_SYSINFO_QUANTITY, (DWORD)&sysInfo);\n\n\tif (rc)\n\t\treturn 0;\n\n\treturn count;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetDeviceName(entry, name)\n*\n* DESCRIPTION\n*\n* INPUTS\n*     Entry - Entry number to get name for.\n*     Name  - On return; device entry name\n*\n* RESULT\n*     Success - Success / Failure flag\n*\n****************************************************************************/\n\nbool MCI::GetDeviceName(unsigned int item, char* buffer)\n\t{\n\tMCIERROR rc;\n\tMCI_SYSINFO_PARMS sysInfo;\n\n\t// Get device name\n\tmemset(&sysInfo, 0, sizeof(sysInfo));\n\tsysInfo.lpstrReturn = (LPSTR)buffer;\n\tsysInfo.dwRetSize = 63;\n\tsysInfo.dwNumber = item;\n\n\trc = mciSendCommand(MCI_ALL_DEVICE_ID, MCI_SYSINFO,\n\t\t\tMCI_WAIT | MCI_SYSINFO_NAME, (DWORD)&sysInfo);\n\n\tif (rc)\n\t\treturn false;\n\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nbool MCI::GetProductName(MCIDEVICEID id, char* buffer)\n\t{\n\tMCIERROR rc;\n\tMCI_INFO_PARMS info;\n\n\t// Get device product name\n\tmemset(&info, 0, sizeof(info));\n\tinfo.lpstrReturn = (LPSTR)buffer;\n\tinfo.dwRetSize = 63;\n\n\trc = mciSendCommand(id, MCI_INFO, MCI_WAIT | MCI_INFO_PRODUCT,\n\t\t\t(DWORD)&info);\n\n\tif (rc)\n\t\treturn false;\n\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     OpenDevice(name)\n*\n* DESCRIPTION\n*\n* INPUTS\n*     Name - Device name to open\n*\n* RESULT\n*     DeviceID - ID of opened device, 0 if error.\n*\n****************************************************************************/\n\nMCIDEVICEID MCI::OpenDevice(const char* name)\n\t{\n\tMCIERROR rc;\n\tMCI_OPEN_PARMS open;\n\n\tmemset(&open, 0, sizeof(open));\n\topen.lpstrDeviceType = name;\n\n\trc = mciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_TYPE, (DWORD)&open);\n\n\tif (rc)\n\t\treturn 0;\n\n\treturn (open.wDeviceID);\n\t}\n\n\nvoid MCI::CloseDevice(MCIDEVICEID id)\n\t{\n\tMCI_GENERIC_PARMS close;\n\n\tclose.dwCallback = (DWORD)NULL;\n\t\n\tif (id)\n\t\tmciSendCommand(id, MCI_CLOSE, MCI_WAIT, (DWORD)&close);\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetDeviceDescription\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nbool MCI::GetDeviceDescription(const char* name, MCIDevice* caps)\n\t{\n\tMCIDEVICEID id;\n\tunsigned long result;\n\n\t// Copy the name\n\tstrncpy(caps->name, name, 63);\n\n\tif ((id = OpenDevice(name)) == 0)\n\t\treturn false;\n\n\t// Get device product name\n\tGetProductName(id, caps->description);\n\n\t// Get device type\n\tif (GetCapability(id, MCI_GETDEVCAPS_DEVICE_TYPE, &result))\n\t\tcaps->type = result;\n\n\tif (GetCapability(id, MCI_GETDEVCAPS_CAN_EJECT, &result))\n\t\tcaps->canEject = ((result) ? true : false);\n\n\tif (GetCapability(id, MCI_GETDEVCAPS_CAN_PLAY, &result))\n\t\tcaps->canPlay = ((result) ? true : false);\n\n\tif (GetCapability(id, MCI_GETDEVCAPS_CAN_RECORD, &result))\n\t\tcaps->canRecord = ((result) ? true : false);\n\n\tif (GetCapability(id, MCI_GETDEVCAPS_CAN_SAVE, &result))\n\t\tcaps->canSave = ((result) ? true : false);\n\n\tif (GetCapability(id, MCI_GETDEVCAPS_COMPOUND_DEVICE, &result))\n\t\tcaps->usesDevElem = ((result) ? true : false);\n\n\tif (GetCapability(id, MCI_GETDEVCAPS_HAS_AUDIO, &result))\n\t\tcaps->hasAudio = ((result) ? true : false);\n\n\tif (GetCapability(id, MCI_GETDEVCAPS_HAS_VIDEO, &result))\n\t\tcaps->hasVideo = ((result) ? true : false);\n\n\tif (GetCapability(id, MCI_GETDEVCAPS_USES_FILES, &result))\n\t\tcaps->reqElemFile = ((result) ? true : false);\n\n\tCloseDevice(id);\n\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nbool MCI::GetCapability(MCIDEVICEID id, unsigned long capItem,\n\t\tunsigned long* result)\n\t{\n\tMCIERROR rc;\n\tMCI_GETDEVCAPS_PARMS devCaps;\n\n\tmemset(&devCaps, 0, sizeof(devCaps));\n\tdevCaps.dwItem = capItem;\n\trc = mciSendCommand(id, MCI_GETDEVCAPS, MCI_WAIT|MCI_GETDEVCAPS_ITEM,\n\t\t(DWORD)&devCaps);\n\n\tif (rc)\n\t\treturn false;\n\n\t*result = devCaps.dwReturn;\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nconst char* MCI::GetDeviceTypeName(unsigned long type)\n\t{\n\tstatic struct _DeviceType {unsigned long typeID; const char* typeName;}\n\t\t_deviceTypeNames[] =\n\t\t{\n\t\t\t{MCI_DEVTYPE_ANIMATION, \"Animation\"},\n\t\t\t{MCI_DEVTYPE_CD_AUDIO, \"CD Audio\"},\n\t\t\t{MCI_DEVTYPE_DAT, \"DAT\"},\n\t\t\t{MCI_DEVTYPE_DIGITAL_VIDEO, \"Digital Video\"},\n\t\t\t{MCI_DEVTYPE_OTHER, \"Other\"},\n\t\t\t{MCI_DEVTYPE_OVERLAY, \"Overlay\"},\n\t\t\t{MCI_DEVTYPE_SCANNER, \"Scanner\"},\n\t\t\t{MCI_DEVTYPE_SEQUENCER, \"MIDI Sequencer\"},\n\t\t\t{MCI_DEVTYPE_VCR, \"VCR\"},\n\t\t\t{MCI_DEVTYPE_VIDEODISC, \"VideoDisc\"},\n\t\t\t{MCI_DEVTYPE_WAVEFORM_AUDIO, \"Wave Audio\"},\n\t\t\t{0, NULL},\n\t\t};\n\n\tint i = 0;\n\n\twhile (_deviceTypeNames[i].typeID != 0)\n\t\t{\n\t\tif (_deviceTypeNames[i].typeID == type)\n\t\t\treturn _deviceTypeNames[i].typeName;\n\n\t\ti++;\n\t\t}\n\n\treturn NULL;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     MCIEnumerate(callack, context)\n*\n* DESCRIPTION\n*\n* INPUTS\n*     Callback -\n*     Context  -\n*\n* RESULT\n*     Success - Success / Failure flag\n*\n****************************************************************************/\n\nbool MCI::EnumerateDevices(MCIEnumCB* callback, void* context)\n\t{\n\tDWORD count;\n\tDWORD i;\n\tchar name[64];\n\tMCIDevice device;\n\n\t// Get the number of devices\n\tcount = GetDeviceCount();\n\n\t// Do for each device\n\tfor (i = 1; i <= count; i++)\n\t\t{\n\t\tGetDeviceName(i, name);\n\t\tmemset(&device, 0, sizeof(device));\n\n\t\tif (GetDeviceDescription(name, &device))\n\t\t\t{\n\t\t\tif (!callback(&device, context))\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\treturn true;\n\t}\n#endif // MCIMPEG\n\n"
  },
  {
    "path": "CODE/MCI.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef _MCI_H_\n#define _MCI_H_\n/****************************************************************************\n*\n* FILE\n*     MCI.H\n*\n* DESCRIPTION\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     6/22/98\n*\n****************************************************************************/\n\n#include \"function.h\"\n\n#ifdef MCIMPEG\n#include <windows.h>\n#include <mmsystem.h>\n#include <digitalv.h>\n#include \"watcom.h\"\n\n/* MCIDevice - MCI device capabilities and description\n *\n * name        - Name used to open device.\n * description - Product description\n * type        - Device type\n * canEject    - Can eject media flag\n * canPlay     - Can playback media\n * canRecord   - Can record media\n * canSave     - Can save media\n * usesDevElem - Uses device element\n * hasAudio    - Media supports audio\n * hasVideo    - Media supports video\n * reqElemFile - Requires element file\n */\ntypedef struct _MCIDevice\n\t{\n\tchar name[64];\n\tchar description[64];\n\tunsigned long type;\n\tbool canEject;\n\tbool canPlay;\n\tbool canRecord;\n\tbool canSave;\n\tbool usesDevElem;\n\tbool hasAudio;\n\tbool hasVideo;\n\tbool reqElemFile;\n\t} MCIDevice;\n\n/* MCI enumeration callback definition */\ntypedef bool (MCIEnumCB)(MCIDevice* desc, void*);\n\nclass MCI\n\t{\n\tpublic:\n\t\t// Open MCI device\n\t\tMCIDEVICEID OpenDevice(const char* name);\n\t\tvoid CloseDevice(MCIDEVICEID id);\n\n\t\t// Enumerate devices\n\t\tbool EnumerateDevices(MCIEnumCB* callback, void* context);\n\n\t\t// Get number of MCI devices name in registry or [MCI] section\n\t\t// of system.ini\n\t\tunsigned int GetDeviceCount(void);\n\n\t\t// Get device name from registry or [MCI] section of system.ini\n\t\tbool GetDeviceName(unsigned int item, char* buffer);\n\n\t\t// Get general device description\n\t\tbool GetDeviceDescription(const char* name, MCIDevice* caps);\n\n\t\t// Get type name (IE: Digital Video) from type ID (IE: MCI_DEVTYPE_DIGITAL_VIDEO)\n\t\tconst char* GetDeviceTypeName(unsigned long type);\n\n\t\t// Get device product name\n\t\tbool GetProductName(MCIDEVICEID id, char* buffer);\n\n\t\t// Get device capability\n\t\tbool GetCapability(MCIDEVICEID id, unsigned long capItem,\n\t\t\t\tunsigned long* result);\n\t};\n\n#endif // MCIMPEG\n#endif // _MCI_H_\n"
  },
  {
    "path": "CODE/MCIMOVIE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"function.h\"\n\n#ifdef MCIMPEG\n#include \"mcimovie.h\"\n#include <memory.h>\n\n/****************************************************************************\n*\n*\tNAME\n*     MCIMovie - Constructor\n*\n* DESCRIPTION\n*\n* INPUTS\n*     HInstance - Application instance handle\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nMCIMovie::MCIMovie(HWND mainWindow)\n\t: mMainWindow(mainWindow), mMCIWindow(NULL), mName(NULL), mDeviceID(0)\n\t{\n\tmWidth = mHeight = 0;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     ~MCIMovie - Destructor\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nMCIMovie::~MCIMovie()\n\t{\n\t// Stop any playing movie\n\tClose();\n\n\t// Free name\n\tif (mName != NULL)\n\t\tfree(mName);\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     Open()\n*\n* DESCRIPTION\n*     Open the media file in preparation for playback.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Success - Success/Failure flag\n*\n****************************************************************************/\n\nbool MCIMovie::Open(const char* name, const char* device)\n\t{\n\tMCIERROR rc;\n\tMCI_DGV_RECT_PARMS rectParm;\n\tMCI_BREAK_PARMS breakParm;\n\n\t// Stop any currently playing movie\n\tClose();\n\n\t// Copy the movie name for our use\n\tif (mName != NULL)\n\t\tfree(mName);\n\n\tmName = strdup(name);\n\n\tif (device == NULL)\n\t\tdevice = \"mpegvideo\";\n\t\t\n\t// Setup open parameters\n\tmemset((void*)&mOpenParm, 0, sizeof(mOpenParm));\n\tmOpenParm.dwCallback = NULL;\n\tmOpenParm.lpstrDeviceType = device;\n\tmOpenParm.lpstrElementName = name;\n\n\trc = mciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_TYPE |\n\t\tMCI_OPEN_ELEMENT, (DWORD)&mOpenParm);\n\t\t\t\n\tif (rc)\n\t\t{\n\t\tchar buffer[512];\n\t\tmciGetErrorString(rc, buffer, 512);\n\t\treturn false;\n\t\t}\n\n\t// Set device ID\n\tmDeviceID = mOpenParm.wDeviceID;\n\n\t// Retrieve movie dimensions\n\trectParm.dwCallback = NULL;\n\n\trc = mciSendCommand(mDeviceID, MCI_WHERE, MCI_WAIT | MCI_DGV_WHERE_SOURCE,\n\t\t\t(DWORD)&rectParm);\n\n\tif (rc)\n\t\t{\n\t\tchar buffer[512];\n\t\tmciGetErrorString(rc, buffer, 512);\n\t\treturn false;\n\t\t}\n\n\tmWidth = rectParm.rc.right - rectParm.rc.left;\n\tmHeight = rectParm.rc.bottom - rectParm.rc.top;\n\n\t// Set break key to escape\n \tbreakParm.dwCallback = NULL;\n\tbreakParm.nVirtKey = VK_ESCAPE;\n\tbreakParm.hwndBreak = mMainWindow;\n\t\n\trc = mciSendCommand(mDeviceID, MCI_BREAK, MCI_WAIT | MCI_BREAK_HWND |\n\t\tMCI_BREAK_KEY, (DWORD)&breakParm);\n\n\tif (rc)\n\t\t{\n\t\tchar buffer[512];\n\t\tmciGetErrorString(rc, buffer, 512);\n\t\t}\n\t\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     Play - Play the specified movie.\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*     Success - Success/Failure flag\n*\n****************************************************************************/\n\nbool MCIMovie::Play(HWND window)\n\t{\n\tMCIERROR rc;\n\t\n\tif (mDeviceID == 0)\n\t\treturn false;\n\t\t\n\t// Provide window for playback\n\tif (AttachWindow(window))\n\t\t{\n\t\t// Size the video area\n\t\tif (SizeDestination())\n\t\t\t{\n\t\t\t// Start playing\n\t\t\tmemset((void*)&mPlayParm, 0, sizeof(mPlayParm));\n\t\t\tmPlayParm.dwCallback = NULL;\n\n\t\t\trc = mciSendCommand(mDeviceID, MCI_PLAY, MCI_WAIT, (DWORD)&mPlayParm);\n\n\t\t\tif (rc)\n\t\t\t\t{\n\t\t\t\tchar buffer[512];\n\t\t\t\tmciGetErrorString(rc, buffer, 512);\n\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tClose();\n\t\t\t}\n\t\t}\n\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     Pause\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*     Success - Success/Failure flag\n*\n****************************************************************************/\n\nbool MCIMovie::Pause(void)\n\t{\n\tif (mDeviceID == 0)\n\t\treturn false;\n\n\tif (mciSendCommand(mDeviceID, MCI_PAUSE, 0, (DWORD)NULL))\n\t\treturn false;\n\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     Stop\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*     Success - Success/Failure flag\n*\n****************************************************************************/\n\nbool MCIMovie::Close(void)\n\t{\n\tMCIERROR rc;\n\t\n\tif (mDeviceID == 0)\n\t\treturn false;\n\n\trc = mciSendCommand(mDeviceID, MCI_CLOSE, 0, (DWORD)NULL);\n\tmDeviceID = 0;\n\n\tif (rc)\n\t\t{\n\t\tchar buffer[512];\n\t\tmciGetErrorString(rc, buffer, 512);\n\t\treturn false;\n\t\t}\n\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     SizeDestination\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nbool MCIMovie::SizeDestination(void)\n\t{\n\tMCIERROR rc;\n\tMCI_DGV_PUT_PARMS putParm;\n\tRECT rect;\n\n\tif (mMCIWindow == NULL)\n\t\treturn false;\n\n\tGetClientRect(mMCIWindow, &rect);\n\tClientToScreen(mMCIWindow, (LPPOINT)&rect);\n\tClientToScreen(mMCIWindow, (LPPOINT)&rect + 1);\n\n\tputParm.dwCallback = NULL;\n\tputParm.rc.left = rect.left;\n\tputParm.rc.top = rect.top;\n\tputParm.rc.right = rect.right;\n\tputParm.rc.bottom = rect.bottom;\n\n\trc = mciSendCommand(mDeviceID, MCI_PUT, MCI_WAIT | MCI_DGV_RECT |\n\t\tMCI_DGV_PUT_DESTINATION, (DWORD)&putParm);\n\n\tif (rc)\n\t\t{\n\t\tchar buffer[512];\n\t\tmciGetErrorString(rc, buffer, 512);\n\t\treturn false;\n\t\t}\n\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     AttachWindow\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nbool MCIMovie::AttachWindow(HWND window)\n\t{\n\tMCIERROR rc;\n\tMCI_DGV_WINDOW_PARMS winParm;\n\n\tmMCIWindow = window;\n\n\tmemset((void*)&winParm, 0, sizeof(winParm));\n\twinParm.dwCallback = NULL;\n\twinParm.hWnd = window;\n\twinParm.nCmdShow = SW_SHOW;\n\n\trc = mciSendCommand(mDeviceID, MCI_WINDOW, MCI_WAIT| MCI_DGV_WINDOW_HWND |\n\t\t\tMCI_DGV_WINDOW_STATE, (DWORD)&winParm);\n\n\tif (rc)\n\t\t{\n\t\tchar buffer[512];\n\t\tmciGetErrorString(rc, buffer, 512);\n\t\treturn false;\n\t\t}\n\n\treturn true;\n\t}\n\n#endif // MCIMPEG\n\n"
  },
  {
    "path": "CODE/MCIMOVIE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef _MCIMOVIE_H_\n#define _MCIMOVIE_H_\n\n#include \"function.h\"\n\n#ifdef MCIMPEG\n#include <windows.h>\n#include <windowsx.h>\n#include <mmsystem.h>\n#include <digitalv.h>\n#include \"watcom.h\"\n\nclass MCIMovie\n\t{\n\tpublic:\n\t\tMCIMovie(HWND mainWindow);\n\t\t~MCIMovie();\n\n\t\tbool Open(const char* name, const char* device);\n\t\tbool Play(HWND window);\n\t\tbool Pause(void);\n\t\tbool Close(void);\n\n\t\tLONG GetWidth(void)\n\t\t\t{return ((mDeviceID) ? mWidth : 0);}\n\n\t\tLONG GetHeight(void)\n\t\t\t{return ((mDeviceID) ? mHeight : 0);}\n\n\tprotected:\n\t\tHWND mMainWindow; // Application window\n\t\tHWND mMCIWindow; // Callback window\n\t\tchar *mName;\n\t\tUINT mDeviceID;\n\t\tMCI_OPEN_PARMS mOpenParm;\n\t\tMCI_PLAY_PARMS mPlayParm;\n\n\t\t// Video stream dimension\n\t\tLONG mWidth, mHeight;\n\n\tprivate:\n\t\tbool SizeDestination(void);\n\t\tbool AttachWindow(HWND window);\n\n\t\tstatic int mRegistered;\n\t\tstatic WNDCLASS mWndClass;\n\t\tstatic HINSTANCE mInstance;\n\t};\n\n#endif // MCIMPEG\n#endif // _MCIMOVIE_H_\n"
  },
  {
    "path": "CODE/MEMCHECK.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/* #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#\n\n                    MemCheck 3.0 Professional for DOS\n\n            Copyright (c) 1990-1994, StratosWare Corporation.  \n                           All rights reserved.\n\n                             1-800-WE-DEBUG\n\n        Note to Developers:\n        --------------------\n        This file should be #included AFTER any other #includes in\n        each source file which is to be memory checked, and BEFORE\n        any code that performs any operations on allocated pointers.\n        If it isn't, MemCheck will not pick up source file and line\n        information for intercepted functions. \n\n        The MCCONFIG.EXE utility distributed with MemCheck 3.0\n        will do this safely and quickly for you.\n\n        Most specifically, this header file MUST NOT come before\n        any prototypes of routines that MemCheck intercepts, like\n        malloc(), free(), strcpy(), and so on.\n\n        The Final Cut:\n        ---------------\n        To ENTIRELY remove MemCheck from your code, just #define\n        the constant \"NOMEMCHECK\", or equivalently, \"NOMC\".\n        \n        This header file will then automatically 'evaporate' all \n        MemCheck 3.0 calls.  This is MUCH PREFERABLE to placing \n        #if-#endif's around the header file's inclusion, as in\n\n                    #ifdef DEBUG        // DON'T DO THIS!\n                    #include <memcheck.h>\n                    #endif\n\n        Using the \"#ifdef DEBUG\" as above doesn't allow the\n        MemCheck header file to evaporate the MemCheck 3.0 API\n        calls you may have placed in your code, like mc_startcheck()\n        and mc_endcheck().  You would then have to surround\n        each MemCheck API call with additional #if-#endif's.\n\n    Modification History\n\n    WHO     WHEN        WHAT\n    KWB     07/28/93    Gussy for beta\n    KWB     09/11/93    Add new placement overload, NEW() C++ stuff\n    KWB     11/08/93    Final QA/QC for initial release\n    KWB     12/02/93    LINT -save added\n    KWB     02/19/94    Fixed function inlining holes, added macros\n                        for underscore func variants under MSC 7+\n    KWB     07/08/94    Added defines for BC extender (_CC_POWERPACK_)\n    KWB     07/09/94    Added special case for STACKTOP, END under PowerPack\n    KWB     08/04/94    Added cdecl modifier to stklen, atopsp etc. decls\n    KWB     08/11/94    Associated _CC32_ with _PROTECTED_ in ccdefs section;\n                        Changed method of determining compiler model,\n                        e.g. _CC_MSC6_ from if == to if >=\n                        Associated DOSX286 with _PROTECTED_ for Phar Lap\n                        Added MC_SET_EXCEPTF, mc_set/get_exceptf()\n    KWB     08/17/94    Added new[] support filtering (_CPP_ANSI20_)\n    KWB     08/18/94    Changed _MCFARCALL to _MCFARGLUE \n    KWB     09/13/94    Added erf_printf as alias for erf_stdout\n    KWB     09/14/94    Added endf_summary\n    KWB     09/21/94    Added MCCRITF and mc_set_critf() & related\n    KWB     10/10/94    Added #if !defined(setmem) etc. for BC DPMI32\n    KWB     10/11/94    Added _CC_BORLANDx_ comp def, 'x' = major ver\n\n*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# */\n\n\n/* Avoid multiple inclusions */\n#ifndef _MEMCHECK_H_\n#define _MEMCHECK_H_\n\n/* Prevent inclusion in Windows(tm) compilations */\n#if defined(_Windows) || defined(WINDOWS) || defined(_WINDOWS)\n#   if !defined (__DPMI16__) && !defined (__DPMI32__) && !defined (DOSX286)\n#       error DOS version of MemCheck header file #included!\n#   endif\n#endif\n\n/* Shorthand equivalence, V2.0 backwards compatibility... */\n#if defined (NOMC) || defined (NOMEMCHK)\n#   define NOMEMCHECK\n#endif\n\n/*  C++ new interception -- see note later and\n    read the MemCheck 3.0 User's Manual, section\n    \"Integration With C++.\"  Uncommenting the next line\n    and following simple instructions allows seamless\n    transmission of the exact file and line location\n    of new's in your source code.\n*/\n/*  #define NEW_OVERLOADED  */\n\n\n/* *** Backwards compatibility with V2.0 *** */\n\n#define mc_isactive         mc_is_active    /* standardize naming... */\n#define mc_getmode          mc_get_mode\n#define mc_errorstatus      mc_error_flags\n#define mc_verify_memory    mc_check_buffers\n\n#define MC_USEDISK          MC_USING_DISK\n#define MC_USEMEM           MC_USING_MEMORY\n\n\n/* *** Backwards compatibility with V2.1 *** */\n\n#define MCLINENO            MCSL            /* \"MemCheck Source Line\" */\n#define MFUNC               ERF             /* error reporting function */\n\n#define mc_set_msgfunc      mc_set_erf      /* \"Message funcs\" are now    */\n#define mc_get_msgfunc      mc_get_erf      /* universally referred to as */\n#define mc_error_status     mc_error_flags  /* \"error reporting functions\"*/\n\n/*  Maintain source code compatibility with version 2.1.\n    Buffer registration is simplified to\n    just calling \"mc_register\", regardless of model.  \n    Same with buffer checking, e.g. \"mc_check_far\" \n    and \"mc_check_near\" are rolled into \"mc_check\". \n*/\n#define mc_register_near(p,s)   mc_register((void _MCFAR *)(p),s)\n#define mc_register_far(p,s)    mc_register((void _MCFAR *)(p),s)\n#define mc_unregister_near(p)   mc_unregister((void _MCFAR *)(p))\n#define mc_unregister_far(p)    mc_unregister((void _MCFAR *)(p))\n#define mc_check_near(p)        mc_check((void _MCFAR *)(p))\n#define mc_check_far(p)         mc_check((void _MCFAR *)(p))\n\n/*  Error Number Definitions\n    Returned by mc_endcheck() and mc_error_flags().\n    In MemCheck 3.0, there's now a global error number much\n    like the \"errno\" variable in standard C.   \n*/\n#define MCE_NO_ERROR            0       /* it's debugging time & all well */\n#define MCE_NULL_SOURCE         1       /* null source ptr on copy */\n#define MCE_NULL_DEST           2       /* null dest ptr on copy */\n#define MCE_UNDERWRITE          3       /* allocated buf underwritten (front) */\n#define MCE_OVERWRITE           4       /* allocated buf overwritten (end) */\n#define MCE_LEAK                5       /* forgot to free alloc'd memory */\n#define MCE_LEAKAGE             MCE_LEAK\n#define MCE_UNFREED_MEMORY      MCE_LEAK\n#define MCE_NULL_PTR_ASSIGN     6       /* assigned data through null ptr */\n#define MCE_BAD_STACK_PTR       7       /* bad stack pointer */\n#define MCE_STACK_OVERWRITE     8       /* copy trashes stack frame */\n#define MCE_INTERNAL            9       /* internal error msg */\n#define MCE_OVERLAPPING_COPY    10      /* source overlaps dest on copy */\n#define MCE_INVALID_PTR         11      /* bad ptr on free, realloc */\n#define MCE_DEST_OVERWRITE      12      /* copy too big for dest buffer */\n#define MCE_OUT_OF_MEMORY       13      /* out of memory */\n#define MCE_OOM                 MCE_OUT_OF_MEMORY   \n#define MCE_GPF_PTR             14      /* ptr caused GPF */\n\n\n/*  MemCheck Error Flags \n\n    The MemCheck error flag is just an unsigned long \n    (specifically, a MCEFLAGS typedef) with \"sticky\" bits \n    corresponding to the above MCE_... error numbers.  \n    You can use the error flags macro MC_EFLAG(e) to \n    test the global MC_Errno double flag word.\n*/\n/* Returns a long word with the e-th bit set */\n#define MC_EFLAG(e) ( (e) ? ((MCEFLAGS)1 << (e-1)) : (MCEFLAGS)0)\n\n#define EFLAG_NULL_PTR          MC_EFLAG(MCE_NULL_DEST)\n#define EFLAG_BAD_PTR           MC_EFLAG(MCE_UNALLOCED_PTR)\n#define EFLAG_FRONT_MAGIC       MC_EFLAG(MCE_UNDERWRITE)\n#define EFLAG_BACK_MAGIC        MC_EFLAG(MCE_OVERWRITE)\n#define EFLAG_PTRS_NOT_FREED    MC_EFLAG(MCE_LEAK)\n#define EFLAG_TRACK_FILE        0   /*obsolete in 3.0+*/\n#define EFLAG_NULL_ASSIGN       MCE_FLAG(MCE_NULL_PTR_ASSIGN)\n\n/* *** End Compatibility Section *** */\n\n\n/* *** MemCheck Compiler Constant Definitions *** */\n\n/* \n    Compiler            Defines\n    --------            -------\n    Microsoft           _CC_MSC_, _CC_MSC_COMPATIBLE_\n        V8.x            _CC_MSC8_\n        V7.x            _CC_MSC7_\n        V6.x            _CC_MSC6_\n        V5.x            _CC_MSC5_\n    Borland*            _CC_BORLAND_, _CC_BCC_\n        V3.x            _CC_BORLAND3_\n        V4.x            _CC_BORLAND4_\n        PowerPack/16    _CC_POWERPACK_, _CC_POWERPACK16_\n        PowerPack/32    _CC_POWERPACK_, _CC_POWERPACK32_, _CC32_\n    WATCOM              _CC_WATCOM_, _CC_MSC_COMPATIBLE_\n        WAT/386         _CC_WATCOM32_, _CC32_\n\n    * Borland has no good way of determining compiler\n      version.  __BORLANDC__ returns some truly funky\n      hex constant that \"will increase in future versions.\"\n\n    Define              Meaning\n    ------              --------\n    _CC32_ *            32-bit compile\n    _PROTECTED_         16- or 32-bit protected mode compile\n    LCODE               Defined if large code model\n    LDATA               Defined if large data model\n    STACKTOP            Highest stack address (top)\n    STACKEND            Lowest stack address \n    STACKLEN            Stack length (top - end)\n    _CPP_ANSI20_        Compiler supports C++ 2.0, e.g. new[]\n\n    * If _CC32_ is defined, _PROTECTED_ is also defined\n*/\n        \n\n#ifndef _CCDEFS_H_\n#define _CCDEFS_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*  NOTE: Microsoft C 5.x users have to \"#define _MSC_VER 500\"\n    at the top of this file.\n*/\n#if defined(_MSC_VER)\n/*\n     _MSC_VER            Microsoft C version; currently defined as 700.\n     M_I86   _M_I86      Member of the I86 processor family.\n     M_I86mM _M_I86mM    Memory model type:\n                         <m>= T            Tiny\n                              S            Small (default)\n                              C            Compact model\n                              M            Medium model\n                              L            Large model\n                              H            Huge model\n                         Identifiers defined by /AT, /AS, /AC, /AM,\n                         /AL, and /AH, respectively.\n     _MSDOS              MS-DOS operating system.\n     _QC                 Microsoft QuickC Compiler.\n     _WINDLL             Windows protected-mode dynamic-link library\n                         is selected with /GD.\n     _WINDOWS            Windows protected-mode is selected with /GA,\n                         /Gn, /GW, /Mq, or /GD.\n*/\n#   define _CC_MSC_\n#   define _CC_MSC_COMPATIBLE_\n\n#   if (_MSC_VER >= 800)\n#       define _CC_MSC8_\n#   elif (_MSC_VER >= 700)\n#       define _CC_MSC7_\n#   elif (_MSC_VER >= 600)\n#       define _CC_MSC6_\n#   elif (_MSC_VER >= 500)  /* see note above */\n#       define _CC_MSC5_\n#   else\n#       error MemCheck.h: unrecognized version of Microsoft compiler!\n#   endif\n\n#elif defined(__BORLANDC__)\n#   define _CC_BORLAND_ /* Borland product */\n#   define _CC_BCC_     /* Borland C compiler */\n\n    /* Major compiler rev */\n#   if (__BORLANDC__ >= 0x0450)\n#       define _CC_BORLAND4_\n#   elif (__BORLANDC__ >= 0x400)\n#       define _CC_BORLAND3_\n#   else\n        /* not needed */\n#   endif\n\n    /* Borland 4.0 PowerPack BCC.EXE defines (-WX):\n            __DPMI16__ _Windows\n\n       With -WXD, -WXDE:\n            __DLL__ __DPMI16__ _Windows\n\n       Borland 4.0 PowerPack BCC21.EXE defines (-WX):\n            __CONSOLE__ __DPMI32__ __FLAT__ __WIN32__ _Windows\n\n       With -WXD:\n            __DLL__ __CONSOLE__ __DPMI32__ __FLAT__ __WIN32__ _Windows\n    */\n#   if defined(__DPMI16__)\n#       define _CC_POWERPACK_\n#       define _CC_POWERPACK16_\n#       define _PROTECTED_\n#   endif\n#   if defined(__DPMI32__)\n#       define _CC_POWERPACK_\n#       define _CC_POWERPACK32_\n#       define _CC32_       /* flat model */\n#   endif\n\n/* Turbo C++ */\n#elif defined(MCTCP)    /* homebrew */\n#   define _CC_BORLAND_ /* Borland product */\n#   define _CC_TCP_     /* Turbo C++ */\n\n#elif defined(__TURBOC__)\n/*\n        __TURBOC__      Gives the current Turbo C version\n                        number, a hexadecimal number.  Version\n                        1.0 id 0x1000; version 1.2 is 0x0102, etc.\n        __TINY__, __SMALL__, __MEDIUM__, \n        __COMPACT__, __LARGE__, __HUGE__\n                        Model defintions \n        __MSDOS__       Signals that we're not yet in the\n                        twenty-first century\n*/\n#   define _CC_BORLAND_ /* Borland C product */\n#   define _CC_TCC_     /* Turbo C/C++ compiler */\n\n\n#elif defined(_INTELC32_)\n/*\n        _INTELC32_      has the value 1.\n        _ARCHITECTURE_  is 386 if the nomod486 pragma is ineffect,\n                        486 otherwise.\n*/\n#   define _CC_INTEL_       /* Intel Code Builder */\n#   define _CC_MSC_COMPATIBLE_\n#   define _CC32_           /* flat model */\n\n#elif defined(__WATCOMC__) \n/*  \n        __WATCOMC__     Used to determine if the WATCOM C\n                        or C/386 compiler is compiling\n        __386__         identifies the target machine as an\n                        Intel 80386 under the WATCOM C/386 compiler\n        MSDOS           Signals that we're not yet in the\n                        twenty-first century\n        __FLAT__, __SMALL__, __MEDIUM__, \n        __COMPACT__, __LARGE__  \n                        Model defintions (flat is default)\n                        Also id's MSC-compatible model defines\n\n        8.5 and later:\n        __WINDOWS__     Identifies 16-bit Windows (\"zw\" or \"zW\" opts)\n        __WINDOWS_386__ 32-bit Microsoft Windows \"zW\" opt \n        __NETWARE_386__ Novell Netware 386, defined by the \n                        Novell/Watcom C \n        __OS2__         IBM OS/2-hosted version of Watcom \n*/\n#   define _CC_WATCOM_      /* Watcom C product */\n#   define _CC_MSC_COMPATIBLE_\n#   ifdef __386__\n#       define _CC32_       /* flat model */\n#       define _CC_WATCOM32_\n#   endif\n\n\n#elif defined(__STDC__)     /* Standard ANSI C */\n#   define _CC_ANSI_\n#   define _CC32_           /* no segmentation via far/near */\n#   define far\n#   define near\n#   define huge\n#   define cdecl\n\n/* Avoids parameter mismatches from _far, etc. */\n#   define _far\n#   define _near\n#   define _huge\n#   define _cdecl\n\n#else       /* UNSUPPORTED / UNRECOGNIZED COMPILER */\n\n#error MemCheck 3.0: unrecognized compiler\n/*\n    If you're using Microsoft C5.1, you must\n    define the constant _MSC_VER, e.g.\n\n    #define _MSC_VER    500\n\n    Place this statement at the top of this\n    header file or in your project header file\n    BEFORE the MemCheck header file is included.\n\n    Microsoft C 5.0 is NOT supported (it's non-ANSI).\n*/\n    \n#endif  /* compiler constant definitions */\n\n/* END of _CC..._ name setups; ripple & alias */\n\n/* Sheer utility & avoidance of !_CC32_ */\n#ifndef _CC32_\n#   define _CC16_   \n#endif\n\n/* 32-bit compilers are always protected mode */\n#ifdef _CC32_\n#ifndef _PROTECTED_\n#   define _PROTECTED_\n#endif\n#endif  /* CC32 */\n\n/* Phar Lap support */\n#ifdef DOSX286\n#ifndef _PROTECTED_\n#   define _PROTECTED_\n#endif\n#endif  /* DOSX286 */\n\n/* C++ 2.0 compliance: _CPP_ANSI20_ */\n#if defined(_CC_BORLAND_)\n    /* Only BC++ 4.x and later, but Borland has\n       seriously mangled version info (__BORLANDC__) */\n#   if defined (__BCPLUSPLUS__)\n#       if (__BCPLUSPLUS__ > 0x0310)    /* after 3.1 */\n#           define _CPP_ANSI20_\n#       endif\n#   elif defined(_CC_POWERPACK_)\n#           define _CPP_ANSI20_\n#   endif\n#elif defined (_CC_MSC_)\n    /* Current release through 8.x doesn't support new[] */\n#elif defined (_CC_WATCOM_)\n#   if (__WATCOMC__ >= 1000)    /* 10.x */\n#           define _CPP_ANSI20_\n#   endif\n#endif\n\n\n/*******************************************************************/\n/*******************************************************************/\n\n/*  *** Code and Data Size Constants *** \n    LCODE not used by this header file.\n    LDATA *is* used, however.\n\n    May be commented out if these constants are already defined.\n*/\n\n/*  #ifndef LCODE   */\n#if defined(M_I86MM) || defined(M_I86LM) || defined(M_I86HM)\n#   define LCODE    1\n#elif defined(__MEDIUM__) || defined(__LARGE__) || defined(__HUGE__)\n#   define LCODE    1\n#endif\n/*  #endif  */\n\n#if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)\n#   define LDATA    1\n#elif defined(M_I86CM) || defined(M_I86LM) || defined(M_I86HM)\n#   define LDATA    1\n#endif\n\n/* Macro \"aliases\" */\n\n#ifndef _LCODE\n#   ifdef LCODE\n#       define _LCODE   LCODE\n#   endif\n#endif\n\n#ifndef _LDATA\n#   ifdef LDATA\n#       define _LDATA   LDATA\n#   endif\n#endif\n\n/*******************************************************************/\n/*******************************************************************/\n\n/* *** Physical Stack Address *** */\n\n#if defined(_CC_BORLAND_)   /* -------------------------- */\n\n    /*\n    BORLAND RTL Notes:\n    ;----------------------------------------------------------------------\n    ; In large data models, the stack is in its own segment.  The stack\n    ; starts at SS:__stklen and grows down to SS:0.\n    ;\n    ; In small data models, the stack is in the DGROUP, and grows down\n    ; to meet the heap.  The end of the heap is marked by ___brklvl.\n    (KWB: Note that the brklvl is adjusted upwards until it meets\n    _stklen...)\n    ;----------------------------------------------------------------------\n    */\n\n#   define STACKSLOP    256\n    extern unsigned cdecl _stklen;\n\n#   if defined(_CC_POWERPACK_)\n#       define  STACKTOP    (mc_stacktop())\n#       define  STACKEND    (mc_stackend())\n#   else /* not P-Pack */\n#   ifdef LDATA\n            /*  Compact, Large, Huge Models ...\n\n                The stack starts at SS:_stklen and\n                grows downward to SS:0\n            */\n#           define  STACKTOP    ((unsigned) _stklen)\n#           define  STACKEND    ((unsigned) 0 + STACKSLOP)\n\n#   else\n        /*  Small, Medium Models ...\n\n            The stack starts at SS:0xFFFE and grows\n            downwards _stklen bytes.\n        */\n#       define  STACKTOP    ((unsigned) 0xFFFE)\n#       define  STACKEND    (STACKTOP - _stklen + STACKSLOP)\n#   endif\n#   endif   /* not PowerPack */\n\n#elif defined (_CC_MSC_)  /* ------------------------------- */\n\n    extern char cdecl end;              /* end of stack */\n    extern unsigned cdecl _atopsp;      /* top of stack */\n\n#   define  STACKTOP    _atopsp\n#   define  STACKSLOP   256\n\n#   ifdef LDATA\n        /* If in far data, stack could be in its own\n            seg. tho not usually. see /FARSTACK */\n#       define  STACKEND    ((unsigned) ((unsigned long)&end) + STACKSLOP)\n#   else\n        /*  If near data, must be in DS; use near ptr */\n#       define  STACKEND    ((unsigned)&end + STACKSLOP)\n#   endif\n\n#elif defined (_CC_WATCOM_)  /* ------------------------------- */\n\n    extern unsigned _STACKLOW;      /* end of stack */\n    extern unsigned _STACKTOP;      /* top of stack */\n\n#   define  STACKTOP    (_STACKTOP)\n#   define  STACKSLOP   256\n\n#   ifdef LDATA\n#       define  STACKEND    ((unsigned) (_STACKLOW + STACKSLOP))\n#   else\n#       define  STACKEND    ((unsigned) (_STACKLOW + STACKSLOP))\n#   endif\n\n#else                   /* Unknown compiler ---------------- */\n\n#error Unknown compiler at __FILE__(__LINE__)\n\n#endif      /* defining stack top, end */\n\n/*******************************************************************/\n/*******************************************************************/\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif  /* _ccdefs already #included */\n\n/* End CCDEFS */\n\n\n#if !defined (NULL)     /* pull in stdio.h if not already */\n#   include <stdio.h>\n#endif\n\n/* Backup... sometimes NULL defined in other headers */\n#if !defined (_IOFBF)   /* pull in stdio.h if not already */\n#   include <stdio.h>\n#endif\n\n\n/* *** MemCheck Constants *** */\n\n/*  Standard from MemCheck 3.0 onwards.\n    Access major version and revision\n    via mc_version() and mc_revision() macros.\n*/\n#define _MC_VERSION     0x0300      /* welcome 3.0 the powerful */\n\n#define mc_version()    ((int)((_MC_VERSION & 0xFF00) >> 8))\n#define mc_revision()   ((int)(_MC_VERSION & 0x00FF))\n\n#if defined (_CC32_)    /* 32-bit Intel target */\n#define PRT_FP  \"0x%p\"\n#else\n#define PRT_FP  \"%Fp\"\n#endif\n\n/* *** MCID Macro *** */\n\n/*  Allows later flexibility in assigning mapping...\n    Also makes MCIDs formulaic \n*/\n#define _MCID(f)    (MCID)(__paste(MCID_,f))\n\n/*\n    MemCheck Function ID's (MCID's)\n\n    These are the indices used to retrieve information\n    about specific runtime library calls.\n*/\n/* --- MEMCHECK INTERNAL FUNCTIONS --- */\n\n#define _MCID_FIRST_INTERNAL    0       /* index of first internal func */\n\n#define MCID_mc_startcheck      0\n#define MCID_mc_endcheck        1\n#define MCID_mc_check_buffers   2\n#define MCID_mc_check           3\n#define MCID_mc_register        4\n#define MCID_mc_unregister      5\n#define MCID_mc_set_alignsize   6\n#define MCID_mc_set_checkbytes  7\n#define MCID_mc_nullcheck       8\n#define MCID_mc_breakpoint      9\n#define MCID_mc_debug           10\n#define MCID_mc_set_location    11\n#define MCID_mc_stack_trace     12\n#define MCID_mc_report          13\n\n#define _MCID_LAST_INTERNAL         14  /* Set = to last internal ID */\n\n\n/* ***************   STANDARD C ROUTINES     ******************* */\n\n#define _MCID_FIRST_ANSI        (_MCID_LAST_INTERNAL+1)\n\n#define MCID_calloc             (_MCID_FIRST_ANSI + 0)\n#define MCID_free               (_MCID_FIRST_ANSI + 1)\n#define MCID_malloc             (_MCID_FIRST_ANSI + 2)\n#define MCID_memcpy             (_MCID_FIRST_ANSI + 3)\n#define MCID_memmove            (_MCID_FIRST_ANSI + 4)\n#define MCID_memset             (_MCID_FIRST_ANSI + 5)\n#define MCID_realloc            (_MCID_FIRST_ANSI + 6)\n#define MCID_sprintf            (_MCID_FIRST_ANSI + 7)\n#define MCID_strcat             (_MCID_FIRST_ANSI + 8)\n#define MCID_strcpy             (_MCID_FIRST_ANSI + 9)\n#define MCID_strncat            (_MCID_FIRST_ANSI + 10)\n#define MCID_strncpy            (_MCID_FIRST_ANSI + 11)\n#define MCID_vsprintf           (_MCID_FIRST_ANSI + 12)\n\n#define _MCID_LAST_ANSI     MCID_vsprintf       /* define to last ANSI */\n\n\n/* ***************   MICROSOFT C     ******************* */\n\n#if defined(_CC_MSC_COMPATIBLE_)\n\n#define _MCID_FIRST_MSC     (_MCID_LAST_ANSI + 1)\n\n#   define MCID__expand         (_MCID_FIRST_MSC + 0)\n#   define MCID__ffree          (_MCID_FIRST_MSC + 1)\n#   define MCID__fcalloc        (_MCID_FIRST_MSC + 2)\n#   define MCID__fmalloc        (_MCID_FIRST_MSC + 3)\n#   define MCID__fmsize         (_MCID_FIRST_MSC + 4)\n#   define MCID__frealloc       (_MCID_FIRST_MSC + 5)\n#   define MCID__fexpand        (_MCID_FIRST_MSC + 6)\n#   define MCID__msize          (_MCID_FIRST_MSC + 7)\n\n#   define MCID__fmemmove       (_MCID_FIRST_MSC + 8)\n#   define MCID__fmemcpy        (_MCID_FIRST_MSC + 9)\n#   define MCID__fmemset        (_MCID_FIRST_MSC + 10)\n#   define MCID__fmemccpy       (_MCID_FIRST_MSC + 11)\n#   define MCID__fstrcat        (_MCID_FIRST_MSC + 12)\n#   define MCID__fstrncat       (_MCID_FIRST_MSC + 13)\n#   define MCID__fstrcpy        (_MCID_FIRST_MSC + 14)\n#   define MCID__fstrncpy       (_MCID_FIRST_MSC + 15)\n#   define MCID__fstrdup        (_MCID_FIRST_MSC + 16)\n#   define MCID__fstrset        (_MCID_FIRST_MSC + 17)\n#   define MCID__fstrnset       (_MCID_FIRST_MSC + 18)\n\n#   define MCID__nfree          (_MCID_FIRST_MSC + 19)\n#   define MCID__nmalloc        (_MCID_FIRST_MSC + 20)\n#   define MCID__ncalloc        (_MCID_FIRST_MSC + 21)\n#   define MCID__nrealloc       (_MCID_FIRST_MSC + 22)\n#   define MCID__nexpand        (_MCID_FIRST_MSC + 23)\n#   define MCID__nmsize         (_MCID_FIRST_MSC + 24)\n#   define MCID__nstrdup        (_MCID_FIRST_MSC + 25)\n\n#   define MCID__dos_setvect    (_MCID_FIRST_MSC + 26)\n#   define MCID__getdcwd        (_MCID_FIRST_MSC + 27)\n\n/*  Here starts the Great ANSI Divide.\n    MSC6 and earlier have no underscores;\n    MSC7 and later *have* underscores to emphasize\n        departure from ANSI...\n*/\n#if defined(_CC_MSC_) && !defined (MSC6)    /* not MSC6-compatible */\n\n#   define MCID__getcwd         (_MCID_FIRST_MSC + 28)\n#   define MCID__cgets          (_MCID_FIRST_MSC + 29)\n#   define MCID__halloc         (_MCID_FIRST_MSC + 30)\n#   define MCID__hfree          (_MCID_FIRST_MSC + 31)\n#   define MCID__memccpy        (_MCID_FIRST_MSC + 32)\n#   define MCID__strdup         (_MCID_FIRST_MSC + 33)\n#   define MCID__strnset        (_MCID_FIRST_MSC + 34)\n#   define MCID__strset         (_MCID_FIRST_MSC + 35)\n#   define MCID__swab           (_MCID_FIRST_MSC + 36)\n#   define MCID__tempnam        (_MCID_FIRST_MSC + 37)\n\n#else   /*** MSC6 and before; WATCOM ***/\n\n/* No leading underscores */\n\n#   define MCID_getcwd          (_MCID_FIRST_MSC + 28)\n#   define MCID_cgets           (_MCID_FIRST_MSC + 29)\n#   define MCID_halloc          (_MCID_FIRST_MSC + 30)\n#   define MCID_hfree           (_MCID_FIRST_MSC + 31)\n#   define MCID_memccpy         (_MCID_FIRST_MSC + 32)\n#   define MCID_strdup          (_MCID_FIRST_MSC + 33)\n#   define MCID_strnset         (_MCID_FIRST_MSC + 34)\n#   define MCID_strset          (_MCID_FIRST_MSC + 35)\n#   define MCID_swab            (_MCID_FIRST_MSC + 36)\n#   define MCID_tempnam         (_MCID_FIRST_MSC + 37)\n\n#endif  /* MSC6 ANSI calls */\n\n#   define MCID_new             (_MCID_FIRST_MSC + 38)\n#   define MCID_delete          (_MCID_FIRST_MSC + 39)\n#   define MCID__fullpath       (_MCID_FIRST_MSC + 40)\n\n#endif  /* Microsoft C-compatible calls */\n\n\n/* ***************   BORLAND C     ******************* */\n\n#if defined (_CC_BORLAND_)\n\n#define _MCID_FIRST_BC      (_MCID_LAST_ANSI + 1)\n\n#   define MCID__fmemmove       (_MCID_FIRST_BC + 0)\n#   define MCID__fmemcpy        (_MCID_FIRST_BC + 1)\n#   define MCID__fmemset        (_MCID_FIRST_BC + 2)\n#   define MCID__fmemccpy       (_MCID_FIRST_BC + 3)\n#   define MCID__fstrcat        (_MCID_FIRST_BC + 4)\n#   define MCID__fstrncat       (_MCID_FIRST_BC + 5)\n#   define MCID__fstrcpy        (_MCID_FIRST_BC + 6)\n#   define MCID__fstrncpy       (_MCID_FIRST_BC + 7)\n#   define MCID__fstrdup        (_MCID_FIRST_BC + 8)\n#   define MCID__fstrset        (_MCID_FIRST_BC + 9)\n#   define MCID__fstrnset       (_MCID_FIRST_BC + 10)\n\n#   define MCID__dos_setvect    (_MCID_FIRST_BC + 11)\n#   define MCID__getdcwd        (_MCID_FIRST_BC + 12)\n\n#   define MCID_getcwd          (_MCID_FIRST_BC + 13)\n#   define MCID_cgets           (_MCID_FIRST_BC + 14)\n#   define MCID_memccpy         (_MCID_FIRST_BC + 15)\n#   define MCID_strdup          (_MCID_FIRST_BC + 16)\n#   define MCID_strnset         (_MCID_FIRST_BC + 17)\n#   define MCID_strset          (_MCID_FIRST_BC + 18)\n#   define MCID_swab            (_MCID_FIRST_BC + 19)\n#   define MCID_tempnam         (_MCID_FIRST_BC + 20)\n\n#   define MCID_farmalloc       (_MCID_FIRST_BC + 21)\n#   define MCID_farrealloc      (_MCID_FIRST_BC + 22)\n#   define MCID_farfree         (_MCID_FIRST_BC + 23)\n#   define MCID_farcalloc       (_MCID_FIRST_BC + 24)\n#   define MCID_movmem          (_MCID_FIRST_BC + 25)\n#   define MCID_setmem          (_MCID_FIRST_BC + 26)\n#   define MCID_setvect         (_MCID_FIRST_BC + 27)\n#   define MCID_stpcpy          (_MCID_FIRST_BC + 28)\n#   define MCID__fmovmem        (_MCID_FIRST_BC + 29)\n#   define MCID__fsetmem        (_MCID_FIRST_BC + 30)\n#   define MCID_new             (_MCID_FIRST_BC + 31)\n#   define MCID_delete          (_MCID_FIRST_BC + 32)\n#   define MCID__fullpath       (_MCID_FIRST_BC + 33)\n\n#endif\n\n\n/* \n    'TOUCH' macro so high warning levels don't generate\n    'unreferenced variable' warnings, especially when\n    making Production libraries... All MemCheck code\n    compiles without a whymper.\n*/\n#if defined (_CC_WATCOM_)\n#   define TOUCH(var)   var = var\n#elif defined (_CC_BORLAND4_)\n#   define TOUCH(var)   var = var\n#else\n#   define TOUCH(var)   if (var)\n#endif\n\n\n/* Default log name used by stock erf_logfile() and variants... */\n#define MEMCHECK_LOG    \"MEMCHECK.LOG\"\n\n#define MAX_MEMORY  1000    /* 1000K is more than ever possible */\n\n/* User-Modifiable Defaults */\n\n#define D_CheckByteCt   sizeof(int)     /* word size is default */\n#define D_AlignSize     sizeof(int)     /* align returned memory ptrs */\n\n/*  Number of bytes to copy from null segment (to determine null\n    pointer assignments) \n*/\n#define D_NULLCHECK_BYTES_FAR       16      /* at 0000:0000 (far NULL) */\n#define D_NULLCHECK_BYTES_NEAR      16      /* at   DS:0000 (near NULL) */\n#define MAX_NULLCHECK_BYTES_FAR     1024    /* extent of irupt vect tbl */\n#define MAX_NULLCHECK_BYTES_NEAR    66      /* reserved in DS */\n\n/* Unroll the double-negative */\n/*\n    Debugging code specific to MemCheck can be \n    conditionally compiled by placing it within\n    #if-#endif sections:  (NOTE that this is NOT\n    required when just using API functions)\n\n        #ifdef MEMCHECK\n\n        void _MCCALLBACK trackf_special (int op, MEMRECP memrecp)\n        {\n           (... your custom callback code ...)\n        }\n\n        #endif\n\n    instead of the more arcane\n\n        #ifndef NOMEMCHECK\n        :\n        #endif\n\n    (Both approaches work equally well, however...)\n*/\n#ifndef NOMEMCHECK      /* MemCheck active */\n#define MEMCHECK    \n#endif\n\n\n/* *** Calling Conventions *** */\n\n#if !defined (_CC_ANSI_)\n#define     _MCAPI          pascal      /* MemCheck API functions   */\n#define     _FASTAPI        pascal      /* speed-critical functions */\n#define     _MCCDECL        cdecl       /* MemCheck varargs API     */\n#define     _MCCALLBACK     cdecl       /* callback functions       */\n#define     _MCVAR          cdecl       /* MemCheck global variable */\n#else\n#define     _MCAPI          /* MemCheck API functions   */\n#define     _FASTAPI        /* speed-critical functions */\n#define     _MCCDECL        /* MemCheck varargs API     */\n#define     _MCCALLBACK     /* callback functions       */\n#define     _MCVAR          /* MemCheck global variable */\n#endif\n\n#if !defined(_CC_WATCOM_)\n#   define  _RTL            _MCCDECL    /* RTL calling conv */\n#else\n#   define  _RTL                        /* RTL calling conv */\n\n/*  WATCOM C++ does not currently (2/17/94)\n    accept \"cdecl\" as a modifier on variables...  \n*/\n#   undef _MCVAR\n#   define _MCVAR\n#endif  /* _CC_WATCOM_ */\n\n/*   32-bit compiler-independent stuff */\n#if !defined(_CC32_) \n#define _MCFAR      far\n#define _MCFARCALL  far\n#define _MCNEAR     near\n#define _MCNEARCALL near\n#define _MCHUGE     huge\n#else\n#define _MCFAR  \n#define _MCFARCALL\n#define _MCNEAR\n#define _MCNEARCALL\n#define _MCHUGE \n#endif  /* _CC32_ */\n\n/*\n    MSC declares the following routines as \"far\"... \n    So does Borland.  WATCOM does not; define glue.\n\n        _fstrset        _fstrnset       _fstrcpy \n        _fstrncpy       _fstrcat        _fstrncat\n        _fmemset        _fmemmove       _fmemccpy\n*/\n#if !defined(_CC_WATCOM_)\n#   define _MCFARGLUE   far\n#else\n#   define _MCFARGLUE   \n#endif\n\n\n/*  Microsoft C7 and later will not have\n    have a malloc_mc, only _fmalloc_mc; likewise\n    with free_mc.\n    The RTLMALLOC and RTLFREE macros are used\n    to refer to a generically present back-end malloc\n    and free.\n*/\n#if defined (_CC_MSC_)\n#   if defined (LDATA)\n#       define RTLMALLOC    RTL(_fmalloc)\n#       define RTLFREE      RTL(_ffree)\n#   else\n#       define RTLMALLOC    RTL(_nmalloc)\n#       define RTLFREE      RTL(_nfree)\n#   endif\n#else   /* non-MSC */\n#   define RTLMALLOC    RTL(malloc)\n#   define RTLFREE      RTL(free)\n#endif\n\n\n/*  WATCOM defines its atexit funcs as a \"register\",\n    which causes a param type mismatch.  \n    _ATEXITFUNC calling convention smooths this out.\n*/\n#if defined (_CC_WATCOM_)\n#   define _ATEXITFUNC  \n#else\n#   define _ATEXITFUNC      _MCCDECL\n#endif\n\n\n/*  MemCheck Tracking Mode \n    \n    Returned by mc_get_mode().\n    Indicates whether information on each allocation\n    is being stored in memory or on disk.\n*/\n#define MC_USING_MEMORY     1\n#define MC_USING_DISK       2\n\n\n/* Min, max orders for each node in the B-tree */\n\n#define BT_ORDER_MIN        5\n#define BT_ORDER_MAX        255     /* maximum tree order */\n#define BT_ORDER_DEFAULT    19      /* default tree order */\n\n/*\n    Returned by mc_get_speed().\n    Pass as params to mc_set_speed().\n*/\n#define MC_RUN_NORMAL       1\n#define MC_RUN_FAST         2\n\n/*  For mc_report():\n    \"Flags\" field of the MEMREC structure\n    is set to REPORT_START or REPORT_END\n    to indicate begin and end of report.\n\n    NOTE: If REPORT_START or REPORT_END conflicts\n        with defines in your project, just comment\n        them out and use the MC_... variants instead.\n*/\n#define REPORT_START        (MRFLAGS)0xFE\n#define REPORT_END          (MRFLAGS)0xFD\n\n#define MC_REPORT_START     (MRFLAGS)0xFE   /* alternates in case of conflict */\n#define MC_REPORT_END       (MRFLAGS)0xFD\n\n\n/*\n    Maximum number of breakpoints that\n    can be set via mc_breakpoint().\n*/\n#define MC_MAX_BREAKS       50\n\n\n/*  \"Optype\" parameter on Tracking function callback. */\n#define TRACKF_ADD      1       /* record being added to tree */\n#define TRACKF_DEL      2       /* record being deleted from tree */\n\n/*  Used for the mcflags field of MEMREC to indicate\n    whether file & line are exact or approximate\n*/\n#define MRFLAG_EXACT_LOC        ( (MRFLAGS) 0x01)\n\n/*\n    Set if the values for a MEMREC are already converted\n    to \"user\" values.\n*/\n#define MRFLAG_USER_SPECS       ( (MRFLAGS) 0x02)\n#define MRFLAG_NO_CHECKBYTES    ( (MRFLAGS) 0x04)\n\n/* Alternate name */\n#define mc_message      mc_debug \n\n/*\n    Parameter to mc_check_transfer() that\n    specifies that the given data transfer function cannot\n    have overlapping source & destination.\n    (MCID's are unsigned bytes.)\n*/\n#define MCF_NO_OVERLAP      ((unsigned)0x8000)\n#define NO_OVERLAP(mcid)    ((mcid) | MCF_NO_OVERLAP)\n\n/*  Parameter to mc_check_transfer indicating that\n    the found memory record is not needed */\n#define NO_MEMREC           ((MEMRECP)NULL) \n#define NOMEMREC            NO_MEMREC\n\n/*  Parameter to mc_check_transfer indicating that\n    there is no source pointer operand associated\n    with the data transfer being checked: e.g. memset.  */\n#define NO_SOURCE           ((void _MCFAR *)0xFFFFFFFA)\n\n\n/* *** TYPEDEFS *** */\n\ntypedef char *          MCSF;       /* MemCheck source file */\ntypedef unsigned int    MCSL;       /* MemCheck source line */\ntypedef unsigned char   MCID;       /* MemCheck function ID */\n\ntypedef unsigned long   MCEFLAGS;   /* MemCheck error flags */\ntypedef void _MCFAR *   MCPTR;      /* type of ptr stored in tree */\ntypedef unsigned char   MRFLAGS;    /* flags in MEMRECORD */\ntypedef unsigned long   MCFLAGS;    /* MemCheck settings flags */\n\n/* MemCheck Rocket allocator prototypes */\ntypedef void _MCFAR * (_MCFAR *ROCKETALLOCF)    (size_t);\ntypedef void          (_MCFAR *ROCKETFREEF)     (void _MCFAR *);\n\n#pragma pack(1)\n/* \n    Memory Tracking Structure (MEMREC)\n\n    This is the data structure for buffers being\n    tracked by MemCheck.\n*/\ntypedef struct MemRecord \n    {\n        MCPTR           ptr;            /* heap/registered ptr */\n        MCID            mcid;           /* MemCheck function ID */\n        MRFLAGS         flags;          /* internal MC flags */\n        unsigned long   allocno;        /* cardinality of allocation */\n        unsigned long   size;           /* size of block */\n        MCSF            file;           /* source file */\n        MCSL            line;           /* source line */\n\n    } MEMREC, _MCFAR *MEMRECP;\n\n\n/* *** SETTINGS *** */\n/* These are values that describe the life of a MemCheck run. */\n\ntypedef struct MCSETTINGS { \n    /*\n        Bit Flag                What\n        --- ---------------     -----------------------------------\n        0   MCF_ACTIVE          MemCheck active or off\n        1   MCF_FAST_MODE       Fast mode or normal\n        2   MCF_PROTECTED_MODE  Protected mode or real\n        3   MCF_FAR_NULL_CHECK  Check for far NULL ptr assigns *\n        4   MCF_NEAR_NULL_CHECK Check for far NULL ptr assigns *\n        5   MCF_STANDARD_STACK  Standard stack frame *\n        6   MCF_AUTOINIT        Start up automatically *\n        7   MCF_CLEAR_ON_FREE   Clear buffers when freed \n        8   MCF_DISK_ROCKET     Use DiskRocket options\n        9   MCF_IDX_IN_MEMORY   Use memory only for Rocket indexes *\n                                (only if DiskRocket linked)\n        10  MCF_SOURCE_ONLY     Intercept in source code only \n\n        11 - 31 Reserved\n    */\n    MCFLAGS         Flags;              /* Main settings flags */\n\n    unsigned short  MaxMem;             /* Max mem for tree usage, in K */\n    unsigned short  NearNullBytes;      /* bytes to check in near null */\n    unsigned short  FarNullBytes;       /*  \"    \"    \"    \" far   \"   */\n    unsigned char   CheckByteCt;        /* check byte count */\n    unsigned char   AlignSize;          /* alignment boundary size */\n    char            TrackingDir[36];    /* Rocket stores temp files here */\n\n    } MCSETTINGS, *MCSETTINGSP;\n\n\n/* Random 32-bit .CFG file sentinel */\n#define MC_CFG_FILE_SENTINEL        ( (unsigned long) 0x10F23BC4 )\n\ntypedef struct MCCfgInfo {\n\n    unsigned long   sentinel;           /* always MC_CFG_FILE_SENTINEL */\n    MCSETTINGS      MemCheckSettings;   /* saved by user */\n\n    } MCCFGINFO, *MCCFGINFOP;\n\n\n#ifndef _CC32_\n\n/* 16-bit exception stack */\ntypedef struct {\n\n    unsigned    xRetIP;\n    unsigned    xRetCS;\n    unsigned    xErr;\n    unsigned    xIP;\n    unsigned    xCS;\n    unsigned    xFlags;\n    unsigned    xSP;\n    unsigned    xSS;\n\n    } MCEXCEPTINFO;\n\n#else\n\n/* 32-bit exception stack */\ntypedef struct {\n\n    unsigned long   xRetEIP;\n    unsigned short  xRsvd1;\n    unsigned short  xRetCS;\n    unsigned long   xErr;\n    unsigned long   xEIP;\n    unsigned short  xRsvd2;\n    unsigned short  xCS;\n    unsigned long   xFlags;\n    unsigned long   xESP;\n    unsigned short  xRsvd3;\n    unsigned short  xSS;\n\n    } MCEXCEPTINFO;\n\n#endif  /* _CC32_ */\n\n/* Values for MCCRITSECT.action */\n#define MCCS_ENTER_SECTION  0\n#define MCCS_LEAVE_SECTION  1\n\n#define MCCS_ACTION(pMCCS)  (pMCCS->nAction)\n#define MCCS_ENTER(pMCCS)   ((*(pMCCS->pLocked))++) /* inc flag */\n#define MCCS_LEAVE(pMCCS)   ((*(pMCCS->pLocked))--) /* dec flag */\n\n/* \n    Critical section object - ptr to this passed to crit sect callback \n    WARNING:  access these fields ONLY via the MCCS_...() macros.\n        To do otherwise subjects you to changes in implementation\n        of the underlying coordination of critical section locking.\n*/\ntypedef struct {\n    int             nAction;    /* MCCS_ENTER/LEAVE_SECTION */\n    int *           pLocked;    /* # times entered          */\n    unsigned long   ulRsvd;     /* internal use             */\n    } MCCRITSECT;\n\n#pragma pack()\n\n\n#define MC_FEXIT    ( (MCID) 0xFF )\n\n\n/* Error Reporting Function typedef */\n#ifndef _ERF_DEFINED\n#define _ERF_DEFINED\ntypedef void (_MCCALLBACK *ERF) (char *);\n#endif\n\n\n/* *** Callback Functions *** */\n\n/* Interception callback (on every interception) */\ntypedef void (_MCCALLBACK * GLOBALF) (void);\n\n/* Called whenever nodes added to or deleted from MC database */\ntypedef void (_MCCALLBACK *TRACKF) (int, MEMRECP);\n\n/* User-definable check function to add to transfer checking */\ntypedef void (_MCCALLBACK * CHECKF) (\n                int ,           /* 0 or MCE_... error val for this xfer op */\n                void _MCFAR *,  /* user ptr dest */\n                long            /* bytes to copy to dest */\n            );\n\n/* Funcs called at startup or shutdown */\ntypedef void (_MCCALLBACK *STARTF) (void);\ntypedef void (_MCCALLBACK *ENDF)   (void);\n\n/* Report function type passed to mc_report() */\ntypedef void (_MCCALLBACK *REPORTF) (MEMRECP);\n\n/* Additional heap pointer verification (troubleshoot only) */\ntypedef int (_MCCALLBACK *VERIFYF) (void _MCFAR *);\n\ntypedef void (*MCVOIDFP) (void);\n\n/* Exception handler */\ntypedef void (_MCCALLBACK _MCFAR *MCEXCEPTF) (void);\n\n/* Multitasking enter/exit critical section callback.\n   Specify as param to mc_set_critf() at beginning of program;\n   callback function will be called with MCCS_ENTER_SECTION\n   on entry to MemCheck, or MCCS_LEAVE_SECTION on exit.\n\n   NOT TO BE CONFUSED WITH A MEMCHECK \"GLOBAL\" FUNCTION.\n   Global functions (GLOBALF's) are used to perform any\n   actions on the interception of a runtime function;\n   CRITF's must be used ONLY to serialize access to MemCheck.\n*/\ntypedef void (_MCCALLBACK * MCCRITF) (MCCRITSECT *);\n\n\n/*  Stack Frame Handler \n\n    You can define your own function to \n    record, analyze, or inspect each stack frame\n    when mc_stack_trace() is called.\n\n    You *cannot* modify ANY of the values passed\n    in, as the \"const\" typing indicates.  If you need to\n    modify a value, make a copy.  See the MemCheck 3.0\n    documentation for more details on stack frame handlers.\n*/\n\ntypedef void (_MCFAR _MCCDECL *_SSFRAMEHANDLER ) (\n            short    const ,        /* AX: near/far/error flag   */\n            unsigned short const ,  /* CX: near (default) rtn CS */\n            unsigned short const ,  /* ES: far rtn CS            */\n            unsigned const ,        /* DI: rtn offset from stack */\n            short const             /* DX: frame count           */\n    );\n\n/*  Values for \"flag\" constant parameter to a\n    stack frame handler. \n*/\n#define TRACE_BAD_FRAME     0x00        /* couldn't recognize frame     */\n#define TRACE_FAR_CALL      0x01        /* frame represents a far call  */\n#define TRACE_NEAR_CALL     0x02        /*   \"        \"     \" near  \"   */\n#define TRACE_BAD_CHAIN     0x03        /* frame BP chewed up           */\n#define TRACE_BEGIN         0x80        /* signals begin walk           */\n#define TRACE_END           0x81        /* signals end of walk          */\n\n\n/* MC Settings Structure, \"flags\" member: */\n#define MCF_ACTIVE          (MCFLAGS)(0x01)\n#define MCF_FAST_MODE       (MCFLAGS)(0x02)\n#define MCF_PROTECTED_MODE  (MCFLAGS)(0x04)\n#define MCF_FAR_NULL_CHECK  (MCFLAGS)(0x08)\n#define MCF_NEAR_NULL_CHECK (MCFLAGS)(0x10)\n#define MCF_STANDARD_STACK  (MCFLAGS)(0x20)\n#define MCF_AUTOINIT        (MCFLAGS)(0x40)\n#define MCF_CLEAR_ON_FREE   (MCFLAGS)(0x80)\n#define MCF_DISK_ROCKET     (MCFLAGS)(0x100)\n#define MCF_IDX_IN_MEMORY   (MCFLAGS)(0x200)\n#define MCF_SOURCE_ONLY     (MCFLAGS)(0x400)\n\n\n/* *** Conditional Compilation *** */\n\n/* --------------------------------------------------------------\n    If MEMCHECK is not being `compiled out' (via definition\n    of the constant NOMEMCHECK), include this section...\n-------------------------------------------------------------- */\n\n#if !defined(MEMCHECK)\n\n/* Include Section for `MemCheck Not Active' */\n\n/*  *****************************\n     MemCheck Not Active Section\n    *****************************\n\n    This section completely removes or\n    \"evaporates\" all MemCheck function references\n    from your projects when you compile with\n    NOMEMCHECK #defined.\n\n    There's no need to remove any MemCheck\n    headers or statements from your code\n    to produce a full production version\n    of your application.\n\n                    o\n                   ooo\n                 ooooooo\n                ooooooooo\n               ooooooooooo\n                   ooo\n                   ooo\n                   ooo\n                   ooo\n                                    */\n\n#ifndef MEMCHECK_MODULE\n\n/*  Evaporate all MemCheck 3.0 API\n    statements to do nothing, safely... */\n\n#   define  mc_alloc_count()                0L\n#   define  mc_blocks_allocated()           0L\n#   define  mc_blocks_freed()               0L\n#   define  mc_breakpoint(fi)               0\n#   define  mc_bytes_allocated()            0L\n#   define  mc_bytes_freed()                0L\n#   define  mc_check(p)                     0\n#   define  mc_check_buffers()              0\n#   define  mc_cur_file()                   \"No file\"\n#   define  mc_cur_line()                   0\n#   define  mc_debug(s)\n#   define  mc_debugf(_args)\n#   define  mc_debug_on()\n#   define  mc_debug_off()\n#   define  mc_endcheck()                   (MCEFLAGS)0\n#   define  mc_errno()                      MCE_NO_ERROR\n#   define  mc_error_flags()                (MCEFLAGS)0\n#   define  mc_error_text(e)                \"MemCheck not active\"\n#   define  mc_except_text(e)               \"MemCheck not active\"\n#   define  mc_file()                       \"No file\"\n#   define  mc_find_buffer(p,mr)            0\n#   define  mc_func()                       (MCID)0\n#   define  mc_func_name(mcid)              (\"\")\n#   define  mc_get_erf()                    (ERF)NULL\n#   define  mc_get_mode()                   0\n#   define  mc_get_speed()                  0\n#   define  mc_in_source()                  0\n#   define  mc_is_active()                  0\n#   define  mc_line()                       0\n#   define  mc_load_debugger()\n#   define  mc_location_text()              \"MemCheck not active\"\n#   define  mc_memory_leaked()              0L\n#   define  mc_memrec()                     (MEMRECP)NULL\n#   define  mc_memrec_text()                \"MemCheck not active\"\n#   define  mc_msg_continued()              0\n#   define  mc_nullcheck()                  0\n#   define  mc_null_snapshot() \n#   define  mc_register(p,s)    \n#   define  mc_report(_f)\n#   define  mc_set_alignsize(_s)\n#   define  mc_set_breakfile(_f)\n#   define  mc_set_checkbytes(_cb)\n#   define  mc_set_checkf(_f)               (CHECKF)NULL\n#   define  mc_set_critf(_f)                \n#   define  mc_set_endf(erf)                (ENDF)NULL\n#   define  mc_set_erf(erf)                 (ERF)NULL\n#   define  mc_set_globalf(_f)              (GLOBALF)NULL\n#   define  mc_set_globalexitf(_f)          (GLOBALF)NULL\n#   define  mc_set_speed(_s)\n#   define  mc_set_location()\n#   define  mc_set_trackf(_f)               (TRACKF)NULL\n#   define  mc_set_tracefile(_f)\n#   define  mc_set_tree_order(_q)\n#   define  mc_set_track_dir(_dir)          \n#   define  mc_source_ptr()                 (MCPTR)NULL\n#   define  mc_stack_trace(_memo)           0\n#   define  mc_startcheck(_erf)\n#   define  mc_unregister(p)                \n#   define  mc_set_exceptf(f)   \n#   define  mc_get_exceptf()                ((MCEXCEPTF)NULL)\n\n/* *** Stock error reporting functions *** */\n#   define  erf_default(_msg)\n#   define  erf_standard(_msg)\n#   define  erf_logfile(_msg)\n#   define  erf_log_only(_msg)\n#   define  erf_trace(_msg)\n\n/* Internal Helpers */\n#   define  _direct_output(_s)              \n#   define  _mcsl(_f,_l)\n#   define  _mcsl_delete(_f,_l)\n#   define  _mcsl_new(_f,_l)\n#   define  _mcslx(_f,_l,_s)\n#   define  _mc_set_delflag()\n#   define  _mc_set_location(_f,_l)         \n#   define  _mc_set_newflag()\n\n/* Link-time compileouts */\n#   define  MC_SET_AUTOINIT(_toggle)\n#   define  MC_SET_CHECK_FREQ(_freq)    \n#   define  MC_SET_CHECKF(_f)   \n#   define  MC_SET_CRITF(_f)    \n#   define  MC_SET_ENDF(_f) \n#   define  MC_SET_ENV_VAR(_envvarname)\n#   define  MC_SET_ERF(_f)  \n#   define  MC_SET_GLOBALF(_f)  \n#   define  MC_SET_GLOBALEXITF(_f)  \n#   define  MC_SET_LOGFILE(_logfilename)    \n#   define  MC_SET_PANIC_BUFFERS(_q)\n#   define  MC_SET_SSFH(_f) \n#   define  MC_SET_STARTF(_f)   \n#   define  MC_SET_TRACKF(_f)   \n#   define  MC_SET_VERIFYF(_f)  \n\n/* Back-end direct */\n#define RTL(_f)     _f\n\n/* *** C++ *** */\n#ifdef __cplusplus\n\n#define NEW(_object)        new _object\n#define DELETE(_object)     delete _object\n#define DELETE_ARR(_arr)    delete[] _arr\n\n#define cpp_malloc(_s)      malloc(_s)\n#define cpp_calloc(_n,_s)   calloc(_n,_s)\n#define cpp_free(_p)        free(_p)\n\n/* Borland C++ */\n#define cpp_farmalloc(_s)   farmalloc(_s)\n#define cpp_farfree(_fp)    farfree(_fp)\n\n/* Microsoft C++-compatibles */\n#define cpp__fmalloc(_s)    _fmalloc(_s)\n#define cpp__ffree(_fp)     _ffree(_fp)\n\n#endif  /* C++ */\n\n#endif  /* not MEMCHECK_MODULE */\n\n\n/* #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# */\n\n#else   /* MEMCHECK is defined */\n\n/* #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# */\n\n#pragma message (\"MemCheck V3.0\")\n\n/*\n    *************************\n     MemCheck Active Section\n    *************************\n\n    The rest of this header file deals with\n    MemCheck's being compiled into an application.\n\n                                                   */\n\n/* Specify that vars and funcs are straight C.. */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n/* *** ANSI Location Defines *** */\n\n#define _MC_NO_FILE ((MCSF) 0)      /* just in case... */\n#define _MC_NO_LINE ((MCSL) 0)\n\n\n/*  Allow for the possibility of _MCSF_ being\n    defined to reference a single, static module\n    filename.  This prevents a multiplicity of \n    static filenames getting added to the DGROUP, e.g.\n\n        static char *_thisfile = __FILE__;\n        #define _MCSF_  ((MCSF)thisfile)\n        #include <memcheck.h>\n\n    This is only needed under MSC pre-VC++.\n    Borland has \"-d\" Merge duplicate strings.\n    VC++ has \"/Gf\" Elim duplicate strings.\n*/\n#if !defined (_MCSF_)\n#   ifdef __FILE__\n#      define _MCSF_        (MCSF)__FILE__\n#   else\n#      define _MCSF_        _MC_NO_FILE\n#   endif\n#endif\n\n#ifdef __LINE__\n#   define _MCSL_       (MCSL)__LINE__\n#else\n#   define _MCSL_       _MC_NO_LINE\n#endif\n\n\n/* *** Standard ANSI C Includes *** \n\n    For va_list function call args \n    Inclusion of this header won't change\n    the behavior of host code.\n*/\n#if !defined (va_start)     /* avoid multiple inclusion... */\n#   include <stdarg.h>\n#endif\n\n\n/* *** Compiler-specific includes *** */\n\n/*lint -save -e537 Repeated include files (if necessary) */\n#if defined(_CC_MSC_COMPATIBLE_)\n\n#   if !defined (_INC_MALLOC)   /* C7.x and later optimization */\n#       include <malloc.h>\n#   endif\n\n#   if !defined (_INC_STRING)   /* C7.x and later optimization */\n#       include <string.h>\n#   endif   \n\n#elif defined(_CC_BORLAND_)\n\n#   if !defined (__ALLOC_H)\n#       include <alloc.h>           \n#   endif\n\n/* String functions must be proto'd before pragmas */\n#   if !defined (__STRING_H)\n#       include <string.h>\n#   endif\n\n#endif  /* Compiler-specific includes */\n/*lint -restore */\n\n#if defined (_CC_POWERPACK32_)\nextern void cdecl mcinitfp_startcheck (void);\nextern void cdecl mcexitfp_endcheck (void);\n#pragma startup mcinitfp_startcheck     16\n#pragma exit    mcexitfp_endcheck       16\n#endif\n\n/***************************************/\n/* *** MemCheck 3.0 API Prototypes *** */\n/***************************************/\n\n/* Internal helper macro - proto shorthand */\n#define _LOCP   MCSF,MCSL\n\nextern  unsigned long _MCAPI mc_alloc_count (void);\nextern  unsigned long _MCAPI mc_blocks_allocated (void);\nextern  unsigned long _MCAPI mc_blocks_freed     (void);\nextern  unsigned long _MCAPI mc_bytes_allocated  (void);\nextern  unsigned long _MCAPI mc_bytes_freed      (void);\nextern  int         _MCAPI mc_check (void _MCFAR *);\nextern  int         _MCAPI mc_check_buffers (void);\nextern  MCSF        _MCAPI mc_cur_file (void);\nextern  MCSL        _MCAPI mc_cur_line (void);\nextern  void        _MCCDECL mc_debugv (const char *, ...);\nextern  void        _MCAPI mc_debug (const char *);\nextern  MCEFLAGS    _MCAPI mc_endcheck (void);\nextern  MCEFLAGS    _MCAPI mc_error_flags (void);\nextern  char *      _MCAPI mc_error_text (int);\nextern  int         _MCAPI mc_errno (void);\nextern  char *      _MCAPI mc_except_text (unsigned);\nextern  MCSF        _MCAPI mc_file (void);\nextern  int         _MCAPI mc_find_buffer(void _MCFAR *realptr,MEMRECP memrecp);\nextern  MCID        _MCAPI mc_func (void);\nextern  char *      _MCAPI mc_func_name(MCID);\nextern  ERF         _MCAPI mc_get_erf (void);\nextern  MCEXCEPTF   _MCAPI mc_get_exceptf (void);\nextern  int         _MCAPI mc_get_mode (void);\nextern  int         _MCAPI mc_get_speed (void);\nextern  char *      _MCAPI mc_get_tracefile (void);\nextern  int         _MCAPI mc_in_source (void);\nextern  int         _MCAPI mc_is_active (void);\nextern  MCSL        _MCAPI mc_line (void);\nextern  char *      _MCAPI mc_location_text (void);\n#define  mc_load_debugger()     _asm int 3\nextern  unsigned long _MCAPI mc_memory_leaked (void);\nextern  char *      _MCAPI mc_memrec_text (MEMRECP);\nextern  MEMRECP     _MCAPI mc_memrec (void);\nextern  int         _MCAPI mc_msg_continued (void);\nextern  int         _MCAPI mc_nullcheck (void);\nextern  void        _MCAPI mc_null_snapshot (void);\nextern  void        _MCAPI mc_register (void _MCFAR *, unsigned long);\nextern  void        _MCAPI mc_report (REPORTF);\nextern  void        _MCAPI mc_set_alignsize (unsigned int);\nextern  void        _MCAPI mc_set_breakfile (char *);\nextern  void        _MCAPI mc_set_checkbytes (unsigned int);\nextern  CHECKF      _MCAPI mc_set_checkf (CHECKF);\nextern  void        _MCAPI mc_set_critf (MCCRITF);\nextern  ENDF        _MCAPI mc_set_endf (ENDF);\nextern  ERF         _MCAPI mc_set_erf (ERF);\nextern  MCEXCEPTF   _MCAPI mc_set_exceptf (MCEXCEPTF);\nextern  GLOBALF     _MCAPI mc_set_globalf (GLOBALF);\nextern  GLOBALF     _MCAPI mc_set_globalexitf (GLOBALF);\n#define mc_set_location() _mc_set_location(_MCSF_,_MCSL_)\nextern  MCPTR       _MCAPI mc_source_ptr (void);\nextern  void        _MCAPI mc_set_speed (int);\nextern  void        _MCAPI mc_set_tracefile (char *);\nextern  void        _MCAPI mc_set_track_dir (char *);\nextern  TRACKF      _MCAPI mc_set_trackf (TRACKF);\nextern  void        _MCAPI mc_set_tree_order (int);\nextern  int         _MCAPI mc_stack_trace (char *);\nextern  void        _MCAPI mc_startcheck (_LOCP, ERF);\nextern  void        _ATEXITFUNC mc_endcheck_at_exit (void);\nextern  void        _MCAPI mc_unregister (void _MCFAR *);\n\n/* Debugging versions of the MemCheck library only */\nextern  void _MCAPI mc_debug_on  (void);\nextern  void _MCAPI mc_debug_off (void);\nextern  int _MCCALLBACK mc_search_heap (void _MCFAR *);\n\n/* *** INTERNAL API HELPERS *** */\nextern void _MCAPI   _mc_set_location (_LOCP);\nextern void _FASTAPI _mcsl  (MCSF,MCSL);            /* location run-ahead */\nextern void _FASTAPI _mcslx (MCSF,MCSL,size_t);     /* location run-ahead */\nextern void _FASTAPI _mcsl_new (MCSF,MCSL);         /* location run-ahead */\nextern void _FASTAPI _mcsl_delete (MCSF,MCSL);      /* location run-ahead */\nextern void _FASTAPI _mc_set_newflag (void);        /* new's a'comin'     */\nextern void _FASTAPI _mc_set_delflag (void);        /* delete's a'comin'  */\n\n/* Misc - uses INT 9 to output directly to screen */\n#if !defined (_CC_WATCOM32_)\nextern void _MCCDECL _MCFAR _direct_output (char _MCFAR *);\n#else\n#define _direct_output(s)   printf (\"%s\\n\", s)  /* ALERT */\n#endif\n\n/*\n    mc_breakpoint() is now a MemCheck Tracking function (TRACKF).\n    Tracking functions get called every time\n    MemCheck adds or deletes from its database.\n*/\n#define mc_breakpoint(_f)   \\\n            mc_set_trackf( (mc_set_breakfile (_f), trackf_breakpoint) )\n#define mc_breakpoint_trace(_f) \\\n            mc_set_trackf( (mc_set_tracefile (_f), trackf_breakpoint_trace) )\n\n\n/* *** Advanced-user API extenders *** */\n\n/*  extern  int     _MCAPI mc_find_buffer(void _MCFAR *, MEMRECP);  */\nextern  int     _MCAPI mc_check_transfer(\n                            void _MCFAR *,\n                            void _MCFAR *,\n                            unsigned long,\n                            unsigned,\n                            unsigned,\n                            MEMRECP);\n\n/*  mc_get_settings\n\n    Write your own \"get settings\" routine\n    to override the one shipped with MemCheck.\n    You can hard-wire any settings you like, e.g.\n    always ON for versions of your app shipped to \n    testers/QA stations, etc.\n*/\nextern void _MCCALLBACK mc_get_settings (MCSETTINGS *);\n\n\n/* ***  Callbacks / Functionality Extenders *** \n\n    Function Type           Called...\n    --------------          ------------------------------\n    Error reporting         To handle each MemCheck error message \n    Global Interception     On each MemCheck interception\n    Checking                On every data transfer check\n    Tracking                On every allocation/deallocation\n    Start                   On mc_startcheck or AutoInit\n    End                     At mc_endcheck or MemCheck shutdown\n\n    Refer to your MemCheck 3.0 manual for further details.\n\n    *** STOCK FUNCTIONS *** \n    These functions are available in the MemCheck\n    libraries as \"ready-made\" for your programming \n    pleasure in the categories above.\n*/\n\n/* *** Stock error reporting functions *** */\n\nextern  void    _MCCALLBACK erf_default     (char *);\nextern  void    _MCCALLBACK erf_standard    (char *);\nextern  void    _MCCALLBACK erf_logfile     (char *);\nextern  void    _MCCALLBACK erf_log_only    (char *);\nextern  void    _MCCALLBACK erf_trace       (char *);\nextern  void    _MCCALLBACK erf_trace_all   (char *);\nextern  void    _MCCALLBACK erf_trace_obj   (char *);\nextern  void    _MCCALLBACK erf_stdout      (char *);\nextern  void    _MCCALLBACK erf_stderr      (char *);\nextern  void    _MCCALLBACK erf_find_leaks  (char *);\n\n#define erf_printf  erf_stdout      /* alias*/\n\n/* *** Stock Tracking Functions *** */\n\nextern  void    _MCCALLBACK trackf_default          (int, MEMRECP);\nextern  void    _MCCALLBACK trackf_all              (int, MEMRECP);\nextern  void    _MCCALLBACK trackf_all_2            (int, MEMRECP);\nextern  void    _MCCALLBACK trackf_breakpoint       (int, MEMRECP);\nextern  void    _MCCALLBACK trackf_breakpoint_trace (int, MEMRECP);\nextern  void    _MCCALLBACK trackf_big_alloc        (int, MEMRECP);\n\n/* *** Stock End Functions *** */\n\nextern  void    _MCCALLBACK endf_default    (void); /* does nothing */\nextern  void    _MCCALLBACK endf_info       (void); /* write run info to log */\nextern  void    _MCCALLBACK endf_alert      (void); /* warn if run errs */\nextern  void    _MCCALLBACK endf_summary    (void); /* warn if run errs */\n\n/* *** Stock Start functions *** */\n\nextern  void    _MCCALLBACK startf_default  (void); /* does nothing */\nextern  void    _MCCALLBACK startf_info     (void); /* write options to log */\n\n/* *** Stock Check Functions *** */\n\nextern  void    _MCCALLBACK checkf_default (int,void _MCFAR *,long);\nextern  void    _MCCALLBACK checkf_dataseg (\n    int,            /* 0 or MCE_... error val for this xfer op */\n    void _MCFAR *,  /* user ptr dest */\n    long            /* bytes to copy to dest */\n    );\nextern  void    _MCCALLBACK checkf_verify_heap (int,void _MCFAR *,long);\n                            \n/* *** Stock Global Interception Functions *** */\n\nextern  void        _MCCALLBACK globalf_default       (void); /* does nothing */\nextern  void        _MCCALLBACK globalf_supercheck    (void);\nextern  void        _MCCALLBACK globalf_check_buffers (void);\nextern  void        _MCCALLBACK globalf_heapcheck     (void);\n\n/* *** Stock Report Functions *** */\nextern  void        _MCCALLBACK reportf_default (MEMRECP);\n\n/* *** Stock Exception Handlers *** */\nextern void         _MCCALLBACK _MCFAR exceptf_default (void);\n\n/* *** Stock Stack Frame Handlers *** */\nextern void _MCFAR _MCCDECL ssfh_info (\n    short const, unsigned short const, unsigned short const, unsigned const, short const);\n\nextern void _MCFAR _MCCDECL ssfh_fast (\n    short const, unsigned short const, unsigned short const, unsigned const, short const);\n                /*  int         const   _flag,      */\n\nextern void _MCFAR _MCCDECL ssfh_standard (\n    short const, unsigned short const, unsigned short const, unsigned const, short const);\n\nextern void _MCFAR _MCCDECL ssfh_debug (\n    short const, unsigned short const, unsigned short const, unsigned const, short const);\n\n/* */\nextern unsigned int _MCAPI mc_stacktop (void);  /* high address */\nextern unsigned int _MCAPI mc_stackend (void);  /* low  address */\n\n\n/*  Function external variables.\n\n    These are used effectively with MemCheck 3.0's AutoInit\n    setting.  Under AutoInit, MemCheck fires itself up automatically\n    on its first interception.  Under these circumstances,\n    there's no chance to have changed any defaults (like the\n    ERF or error reporting function).  These variables provide\n    a link-level method of setting these functions:\n\n        #include <memcheck.h>\n        :\n        // Sets custom erf at link-time\n        MC_SET_ERF (erf_custom_startup);\n        :\n*/\n/* *** GLOBALS *** */\n\nextern  ERF         _MCVAR MC_ERF;          /* error reporting func ptr     */\nextern  CHECKF      _MCVAR MC_CheckF;       /* transfer check func          */\nextern  MCCRITF     _MCVAR MC_CritF;        /* crit section enter/exit */\nextern  GLOBALF     _MCVAR MC_GlobalF;      /* global interception callback */\nextern  GLOBALF     _MCVAR MC_GlobalExitF;  /* called on exit interception */\nextern  TRACKF      _MCVAR MC_TrackF;       /* alloc/dealloc callback       */\nextern  STARTF      _MCVAR MC_StartF;       /* startup callback             */\nextern  ENDF        _MCVAR MC_EndF;         /* shutdown callback            */\n\nextern  VERIFYF     _MCVAR MC_VerifyF;      /* troubleshooting              */\n\nextern  char *      _MCVAR MC_LogFile;      /* log file name used           */\nextern  char        _MCVAR MC_UserAutoInit;\nextern  int         _MCVAR MC_CheckFreq;    /* for globalf_supercheck() et al */\nextern  char *      _MCVAR MC_EnvVar;       /* Env var to detect 'active'   */\nextern  unsigned short _MCVAR MC_DataSeg;   /* DS value                     */\n\nextern  int         _MCVAR MC_MaxTraceDepth;\nextern  char *      _MCVAR MCST_Desc;       /* trace descrip to mc_..trc()  */\n\nextern  MCSETTINGS  _MCVAR MC_DefaultSettings;  /* default settings         */\nextern  MCSETTINGS  _MCVAR MC_Settings;         /* real settings--\n                                                   USE WITH CARE!!!         */\n\nextern  MCVOIDFP    _MCVAR MC_PMMap1;       /* p-mode func in map seg 1     */\n\n/* Protected mode exception handling */\nextern  unsigned char   _MCVAR MC_ExceptList[]; /* exceptions to handle */\nextern  MCEXCEPTINFO    _MCVAR MC_ExceptInfo;   /* in exception */\nextern  MCEXCEPTF       _MCVAR MC_ExceptF;      /* installed hdler */\n\n/* Rocket Guidance Systems */\nextern ROCKETALLOCF _MCVAR  MC_RocketAllocF;\nextern ROCKETFREEF  _MCVAR  MC_RocketFreeF;\nextern unsigned char _MCVAR MC_PanicBufCount;   /* anti-tree failure        */\n\n/*  This char is used to fill freed buffers\n    if the \"ClearOnFree\" option in effect.\n    Default buffer clear char is 0.\n*/\nextern unsigned char _MCVAR MC_FreedBufferFillChar;\n\n/*  Link-time defaults.\n\n    These macros are \"covers\" to insulate you, the developer,\n    from the underlying implementation, as well as to provide\n    such bennies as compiling clean out of your code when\n    NOMEMCHECK or NOMC is defined.  \n    \n    Use instead of accessing vars directly!\n\n    To use, place the following in ONE MODULE e.g. your main module\n    (any *one* module will work fine) after the MemCheck \n    header file has been included:\n\n        #include <memcheck.h>\n        MC_SET_...(params);\n\n    For example, to change the default log file that MemCheck\n    uses at runtime to C:\\MYDEV\\MYPROG.LOG:\n\n        #include <memcheck.h>\n        MC_SET_LOGFILE (\"C:\\\\MYDEV\\\\MPROG.LOG\");\n\n    Most of these macros have runtime function equivalents,\n    such as mc_set_erf() for MC_SET_ERF(), etc.  Notable\n    exceptions to this are the following values that\n    must generally have link-time initializations:\n\n        MC_SET_LOGFILE()\n        MC_SET_AUTOINIT()\n        MC_SET_STARTF()\n*/\n#define MC_SET_AUTOINIT(_toggle)        \\\n            char _MCVAR MC_UserAutoInit = (_toggle);\n#define MC_SET_CHECKF(_f)   \\\n            CHECKF  _MCVAR MC_CheckF    = (_f)\n#define MC_SET_CHECK_FREQ(_freq)        \\\n            int _MCVAR MC_CheckFreq     = (_freq)\n#define MC_SET_CRITF(_f)    \\\n            MCCRITF _MCVAR MC_CritF     = (_f)\n#define MC_SET_ENDF(_f)     \\\n            ENDF    _MCVAR MC_EndF      = (_f)\n#define MC_SET_ENV_VAR(_envvarname)     \\\n            char *  _MCVAR MC_EnvVar    = (_envvarname)\n#define MC_SET_ERF(_f)      \\\n            ERF     _MCVAR MC_ERF       = (_f)\n#define MC_SET_EXCEPTF(_f)      \\\n            MCEXCEPTF   _MCVAR MC_ExceptF = (_f)\n#define MC_SET_GLOBALF(_f)  \\\n            GLOBALF _MCVAR MC_GlobalF   = (_f)\n#define MC_SET_GLOBALEXITF(_f)  \\\n            GLOBALF _MCVAR MC_GlobalExitF = (_f)\n#define MC_SET_LOGFILE(_f)      \\\n            char *  _MCVAR MC_LogFile   = (_f)\n#define MC_SET_PANIC_BUFFERS(_q)        \\\n            unsigned char _MCVAR MC_PanicBufCount = (_q)\n#define MC_SET_SSFH(_f)     \\\n            _SSFRAMEHANDLER _MCVAR near MC_SFrameHandler = (_f)\n#define MC_SET_STARTF(_f)       \\\n            STARTF  _MCVAR MC_StartF    = (_f)\n#define MC_SET_TRACKF(_f)   \\\n            TRACKF  _MCVAR MC_TrackF    = (_f)\n#define MC_SET_VERIFYF(_f)  \\\n            VERIFYF _MCVAR MC_VerifyF   = (_f)\n\n/*  Use the MC_BEGIN_EXCEPTLIST, MC_HANDLE_EXCEPTION,\n    and MC_END_EXCEPTLIST macros to change the exceptions \n    MemCheck handles in protected mode by default.\n\n    Usage (exactly as typed):\n            #include <memcheck.h>\n            :\n            MC_BEGIN_EXCEPTLIST\n                MC_HANDLE_EXCEPTION (0x0)\n                MC_HANDLE_EXCEPTION (0xD)\n            MC_END_EXCEPTLIST\n\n    NOTE:\n    To turn off MemCheck's exception handling completely, use \n\n            MC_SET_EXCEPTF(NULL);\n\n    instead of trying to define an empty EXCEPTLIST...\n*/\n#define MC_BEGIN_EXCEPTLIST     \\\n            unsigned char _MCVAR MC_ExceptList[] = {\n#define MC_HANDLE_EXCEPTION(e)  \\\n                (unsigned char)(e),\n#define MC_END_EXCEPTLIST       \\\n                (unsigned char)0xFF };      /* 0xFF MUST end list */\n\n/* ------------- End MemCheck 3.0 Library Calls --------------- */\n\n/*  Formulaic rogue varargs interceptions;\n    most host-code-compatible method...\n    \"Are you experienced?\"\n\n    \"It is better to be mugged than\n     to live in fear.\" - Anon.\n*/\n#define _VA_DEF(f,r,p)          \\\n        typedef r (_RTL *p_##f) p;  \\\n        extern p_##f _MCAPI _loc_##f (_LOCP);\n\n/* Declare sprintf helper function */\n_VA_DEF(sprintf,int,(char *, const char *, ...))\n\n                               /* * * * * * * * * * * * * * * * * * * * * * *\n    *************************\n          Back-End RTL\n    *************************\n*/\n\n/* *** Back-end functions *** */\n\n/*  Macro to access true back-end RTL.\n    Used internally by the MemCheck API functions. \n*/\n#define __paste(x,y)    x ## y\n#define RTL(func)       __paste(func,_mc)\n\n/*  Macro to encapsulate the declaration of\n    the renamed (zapped) back-end rtl \n*/\n#define _RTLDECL(f,rctype,params) \\\n        extern rctype _RTL RTL(f) params\n\n\n/*  For the conversion that MSC underwent\n    from C 6 to 7, where non-ANSI calls\n    have underbars \n*/\n#if defined (_CC_MSC_) && !defined (MSC6) \n#if (_MSC_VER >= 700)\n#   define _C7A\n#endif\n#endif\n\n#ifdef _C7A\n#define C7ANSI(func)    _##func\n#else\n#define C7ANSI(func)    func\n#endif\n\n#undef _C7A\n\n\n/* ---------------------------------------------- */\n/* These are the renamed (\"zapped\") RTL functions */\n/* ---------------------------------------------- */\n\n/* *** ANSI *** */\n\n_RTLDECL(malloc,    void *,     (size_t));\n_RTLDECL(calloc,    void *,     (size_t, size_t));\n_RTLDECL(realloc,   void *,     (void *, size_t));\n_RTLDECL(free,      void,       (void *));\n_RTLDECL(memcpy,    void *,     (void *,const void *,size_t));\n_RTLDECL(memmove,   void *,     (void *,const void *,size_t));\n_RTLDECL(memset,    void *,     (void *,int,size_t));\n_RTLDECL(strcpy,    char *,     (char *,const char *));\n_RTLDECL(strncpy,   char *,     (char *,const char *,size_t));\n_RTLDECL(strcat,    char *,     (char *,const char *));\n_RTLDECL(strncat,   char *,     (char *,const char *,size_t));\n_RTLDECL(vsprintf,  int,        (char *,const char *,va_list));\n_RTLDECL(sprintf,   int,        (char *,const char *,...));\n\n#if !defined (_CC_ANSI_)\n/* *** MSC *** */\n\n/* WATCOM doesn't support these... */\n#if !defined(_CC32_)\n_RTLDECL(_fmalloc,  void far *, (size_t));\n_RTLDECL(_fcalloc,  void far *, (size_t, size_t));\n_RTLDECL(_ffree,    void,       (void far *));\n_RTLDECL(_fmsize,   size_t,     (void far *));\n#endif\n\n_RTLDECL(_nmalloc,  void _MCNEAR *,(size_t));\n_RTLDECL(_nfree,    void,       (void _MCNEAR *));\n\n/* *** Borland *** */\n\n#if !defined(_CC_POWERPACK32_)  \n_RTLDECL(farmalloc, void _MCFAR *,  (unsigned long));\n_RTLDECL(farcalloc, void _MCFAR *,  (unsigned long, unsigned long));\n_RTLDECL(farfree,   void,           (void _MCFAR *));\n\n/* *** General Porpoise *** */\n\n_RTLDECL(_fmemset,  void far * _MCFARGLUE,  (void far *,int,size_t));\n_RTLDECL(_fmemcpy,  void far * _MCFARGLUE,  (void far *,const void far *,size_t ));\n_RTLDECL(_fstrcpy,  char far * _MCFARGLUE,  (char far *,const void far *));\n#endif  /* not _CC_POWERPACK32_ */\n\n#endif  /* not STDC/ANSI */\n\n/***************************************************************** \n * --------   Function Call Interception Definitions   --------- * \n *****************************************************************/\n\n#ifndef MEMCHECK_MODULE\n\n/*\n    This section targets user's code only\n*/\n\n/* Func interceptors... */\n#define     _INTERCEPT(_f)      (_mcsl(_MCSF_,_MCSL_),_f)\n#define     _VA_INTERCEPT(_f)   (*_loc_##_f(_MCSF_,_MCSL_))\n#define     _SETLOC(_f)         (mc_set_location(),_f)\n\n/* NOTE near _mcsl with #if (_MCC_NEAR_INTERCEPT == 0) */\n\n/*\n    MC_NO_TRANSFER_SIZE is used to eliminate errors or warnings\n    like \"sizeof returns 0\" or \"Not allowed type in sizeof <expr>\".\n    These occur for unsized variables declared like\n\n        extern unsigned char gHelpString[];     \n\n    The optimal solution is to \"size\" the extern, e.g.\n\n        extern unsigned char gHelpString[80];   \n\n    but where this may not be practical, MC_NO_TRANSFER_SIZE may\n    be defined on a module-by-module OR project-wide basis.\n*/\n#ifdef MC_NO_XFER_SIZE      /* beta compat */\n#   define  MC_NO_TRANSFER_SIZE\n#endif\n#ifdef NO_TRANSFER_SIZE     /* alternate */\n#   define  MC_NO_TRANSFER_SIZE\n#endif\n\n#if defined (MC_NO_TRANSFER_SIZE)\n#   define  _INTERCEPTX(_f,_d)  _INTERCEPT(_f)\n#else   /* standard; transmit sizeof dest */\n#   define  _INTERCEPTX(_f,_d)  (_mcslx(_MCSF_,_MCSL_,sizeof(_d)),_f)\n#endif\n\n\n/*  Intrinsic Function Disabling\n\n    It's important to disable function inlining for\n    all intercepted functions.\n*/\n\n#if defined(_CC_MSC_)\n\n/*  Intrinsics (== in-line functions) not permissible\n    since they're implemented as macros...\n*/\n#pragma function(strcat)\n#pragma function(strcpy)\n#pragma function(memcpy)\n#pragma function(memset)\n\n#pragma function(strset)\n\n#if defined(_MSC_VER)\n#if (_MSC_VER >= 700)\n#pragma function(_fmemcpy)\n#pragma function(_fmemset)\n#pragma function(_fstrcat)\n#pragma function(_fstrcpy)\n#pragma function(_fstrset)\n#pragma function(_strset)\n#endif\n#endif /* defined _MSC_VER */\n\n#elif defined(_CC_BORLAND_)\n\n/* Turbo C not like pragmae */\n#if !defined (_CC_TCC_)\n\n/*  Eliminate duplicate strings.\n    This can save a bit of space in large\n    programs particularly, since each call to \n    MemCheck references an otherwise separate\n    copy of the current filename. \n*/\n#pragma option -d\n\n/*  Intrinsics (== in-line functions) not permissible\n    since they're implemented as macros, for one...\n*/\n#pragma intrinsic -strcat\n#pragma intrinsic -strncat\n#pragma intrinsic -strcpy\n#pragma intrinsic -strncpy\n#pragma intrinsic -stpcpy\n#pragma intrinsic -strset\n#pragma intrinsic -strnset\n#pragma intrinsic -memcpy\n#pragma intrinsic -memset\n\n#endif  /* not Turbo C */\n\n/* end Borland compiler intrinsics */\n\n#elif defined (_CC_WATCOM_)\n\n/*  NOTE:  unfortunately, WATCOM C/C++ compilers\n    force inlining of the strcpy() function regardless\n    of whether you want it inlined or not, all the time.\n    So this pragma, while it should ensure that\n    strcpy() is a function call, does not...  :{\n\n    So we take other measures below: see _mcwatcom_strcpy()\n*/\n#pragma function(strcpy)\n\n#pragma function(strcat)\n#pragma function(memcpy)\n#pragma function(memset)\n\n#pragma function(_fmemcpy)\n#pragma function(_fmemset)\n#pragma function(_fstrcat)\n#pragma function(_fstrcpy)\n\n#endif\n\n/* End disable function inlining */\n\n\n/*lint -save -e652 Define of symbol declared previously */\n#if defined (MC_NO_INTERCEPT)\n#define NO_INTERCEPT\n#endif\n\n#if !defined (NO_INTERCEPT)\n\n/* *** ANSI Standard C *** */\n\n#define calloc(n,_sz)       _INTERCEPT(calloc(n,_sz))\n#define malloc(_sz)         _INTERCEPT(malloc(_sz))\n#define realloc(p,s)        _INTERCEPT(realloc(p,s))\n#define free(p)             _INTERCEPT(free(p))\n\n#define memcpy(d,s,n)       _INTERCEPTX(memcpy(d,s,n),d)\n#define memmove(d,s,n)      _INTERCEPTX(memmove(d,s,n),d)\n#define memset(p,c,n)       _INTERCEPTX(memset(p,c,n),p)\n#define strcat(s1,s2)       _INTERCEPTX(strcat(s1,s2),s1)\n#if defined(_CC_WATCOM_)    \n    /* WATCOM forces inlining of strcpy()... see note above */\n#   define strcpy(d,s)      _INTERCEPTX(_mcwatcom_strcpy(d,s),d)\n    extern char * _RTL _mcwatcom_strcpy (char *, const char *);\n#else\n#   define strcpy(d,s)      _INTERCEPTX(strcpy(d,s),d)\n#endif\n#define strncat(s1,s2,n)    _INTERCEPTX(strncat(s1,s2,n),s1)\n#define strncpy(d,s,n)      _INTERCEPTX(strncpy(d,s,n),d)\n#define vsprintf(s,f,a)     _INTERCEPTX(vsprintf(s,f,a),s)\n\n/*  #define sprintf             _VA_INTERCEPT(sprintf)  */\n#ifndef _lint\n#define sprintf             _INTERCEPT(sprintf)\n#endif  \n\n#if defined(_CC_MSC_COMPATIBLE_)    /* *** Microsoft C *** */\n\n#define _expand(_p,_s)      _INTERCEPT(_expand(_p,_s))\n#define _fcalloc(n,_sz)     _INTERCEPT(_fcalloc(n,_sz))\n#define _fexpand(_p,_s)     _INTERCEPT(_fexpand(_p,_s))\n#define _ffree(p)           _INTERCEPT(_ffree(p))\n#define _fmalloc(_sz)       _INTERCEPT(_fmalloc(_sz))\n#define _frealloc(p,s)      _INTERCEPT(_frealloc(p,s))\n#define _fmsize(p)          _INTERCEPT(_fmsize(p))\n#define _msize(p)           _INTERCEPT(_msize(p))\n#define _nfree(p)           _INTERCEPT(_nfree(p))\n#define _nmalloc(_sz)       _INTERCEPT(_nmalloc(_sz))\n#define _nrealloc(p,s)      _INTERCEPT(_nrealloc(p,s))\n#define _ncalloc(n,_sz)     _INTERCEPT(_ncalloc(n,_sz))\n#define _nexpand(_p,_s)     _INTERCEPT(_nexpand(_p,_s))\n#define _nmsize(p)          _INTERCEPT(_nmsize(p))\n#define _nstrdup(s)         _INTERCEPT(_nstrdup(s))\n/*  #define halloc(n,_sz)       _INTERCEPT(halloc(n,_sz))   */\n/*  #define _halloc(n,_sz)      _INTERCEPT(halloc(n,_sz))   */\n/*  #define hfree(p)            _INTERCEPT(hfree(p))    */\n/*  #define _hfree(p)           _INTERCEPT(hfree(p))    */\n\n#define cgets(s)            _INTERCEPTX(cgets(s),s)\n#define _cgets(s)           _INTERCEPTX(_cgets(s),s)\n#define memccpy(d,s,c,n)    _INTERCEPTX(memccpy(d,s,c,n),d)\n#define _memccpy(d,s,c,n)   _INTERCEPTX(_memccpy(d,s,c,n),d)\n#define strdup(s)           _INTERCEPT(strdup(s))\n#define _strdup(s)          _INTERCEPT(_strdup(s))\n#define _strnset(s,c,n)     _INTERCEPTX(_strnset(s,c,n),s)\n#define strnset(s,c,n)      _INTERCEPTX(strnset(s,c,n),s)\n#define strset(s,c)         _INTERCEPTX(strset(s,c),s)\n#define _strset(s,c)        _INTERCEPTX(_strset(s,c),s)\n#define swab(s,d,n)         _INTERCEPTX(swab(s,d,n),d)\n#define _swab(s,d,n)        _INTERCEPTX(_swab(s,d,n),d)\n#define tempnam(d,pfx)      _INTERCEPT(tempnam(d,pfx))\n#define _tempnam(d,pfx)     _INTERCEPT(_tempnam(d,pfx))\n\n#define _fmemcpy(d,s,n)     _INTERCEPTX(_fmemcpy(d,s,n),d)\n#define _fmemmove(d,s,n)    _INTERCEPTX(_fmemmove(d,s,n),d)\n#define _fmemset(d,c,n)     _INTERCEPTX(_fmemset(d,c,n),d)\n#define _fmemccpy(d,s,c,n)  _INTERCEPTX(_fmemccpy(d,s,c,n),d)\n#define _fstrcat(s1,s2)     _INTERCEPTX(_fstrcat(s1,s2),s1)\n#define _fstrcpy(d,s)       _INTERCEPTX(_fstrcpy(d,s),d)\n#define _fstrncat(s1,s2,n)  _INTERCEPTX(_fstrncat(s1,s2,n),s1)\n#define _fstrncpy(d,s,n)    _INTERCEPTX(_fstrncpy(d,s,n),d)\n#define _fstrdup(s)         _INTERCEPT(_fstrdup(s))\n#define _fstrnset(d,c,n)    _INTERCEPTX(_fstrnset(d,c,n),d)\n#define _fstrset(d,c)       _INTERCEPTX(_fstrset(d,c),d)\n\n#define getcwd(d,n)         _INTERCEPTX(getcwd(d,n),d)\n#define _getcwd(d,n)        _INTERCEPTX(getcwd(d,n),d)\n#define _getdcwd(r,d,n)     _INTERCEPTX(_getdcwd(r,d,n),d)\n#define _dos_setvect(_i,_h) _INTERCEPT(_dos_setvect(_i,_h))\n#define _fullpath(b,p,n)    _INTERCEPTX(_fullpath(b,p,n),b)\n\n/* ----- END Microsoft C/C++ interceptions ----- */\n\n#elif defined (_CC_BORLAND_)    /* *** Borland C/C++ *** */\n\n#ifndef _CC_POWERPACK32_\n#define farfree(p)          _INTERCEPT(farfree(p))\n#define farmalloc(s)        _INTERCEPT(farmalloc(s))\n#define farcalloc(n,s)      _INTERCEPT(farcalloc(n,s))\n#define farrealloc(p,s)     _INTERCEPT(farrealloc(p,s))\n#endif  /* not _CC_POWERPACK32_ */\n\n#define cgets(s)            _INTERCEPTX(cgets(s),s)\n#define memccpy(d,s,c,n)    _INTERCEPTX(memccpy(d,s,c,n),d)\n#if !defined(movmem)\n#define movmem(s,d,l)       _INTERCEPTX(movmem(s,d,l),d)\n#endif\n#if !defined(setmem)\n#define setmem(d,c,v)       _INTERCEPTX(setmem(d,c,v),d)\n#endif\n#define setvect(i,v)        _INTERCEPT(setvect(i,v))\n#define stpcpy(d,s)         _INTERCEPTX(stpcpy(d,s),d)\n#define _stpcpy(d,s)        _INTERCEPTX(_stpcpy(d,s),d)\n#define strdup(s)           _INTERCEPT(strdup(s))\n#define strnset(s,c,n)      _INTERCEPTX(strnset(s,c,n),s)\n#define strset(s,c)         _INTERCEPTX(strset(s,c),s)\n#define swab(s,d,n)         _INTERCEPTX(swab(s,d,n),d)\n#define tempnam(d,pfx)      _INTERCEPT(tempnam(d,pfx))\n\n#define getcwd(d,n)         _INTERCEPTX(getcwd(d,n),d)\n#define _getdcwd(r,d,n)     _INTERCEPTX(_getdcwd(r,d,n),d)\n#define _dos_setvect(_i,_h) _INTERCEPT(_dos_setvect(_i,_h))\n\n#ifndef _CC_POWERPACK32_\n#define _fmemcpy(d,s,n)     _INTERCEPTX(_fmemcpy(d,s,n),d)\n#define _fmemmove(d,s,n)    _INTERCEPTX(_fmemmove(d,s,n),d)\n#define _fmemset(d,c,n)     _INTERCEPTX(_fmemset(d,c,n),d)\n#define _fmemccpy(d,s,c,n)  _INTERCEPTX(_fmemccpy(d,s,c,n),d)\n#define _fmovmem(s,d,l)     _INTERCEPTX(_fmovmem(s,d,l),s)\n#define _fsetmem(d,c,v)     _INTERCEPTX(_fsetmem(d,c,v),d)\n#define _fstrcat(s1,s2)     _INTERCEPTX(_fstrcat(s1,s2),s1)\n#define _fstrcpy(d,s)       _INTERCEPTX(_fstrcpy(d,s),d)\n#define _fstrncat(s1,s2,n)  _INTERCEPTX(_fstrncat(s1,s2,n),s1)\n#define _fstrncpy(d,s,n)    _INTERCEPTX(_fstrncpy(d,s,n),d)\n#define _fstrdup(s)         _INTERCEPT(_fstrdup(s))\n#define _fstrnset(d,c,n)    _INTERCEPTX(_fstrnset(d,c,n),d)\n#define _fstrset(d,c)       _INTERCEPTX(_fstrset(d,c),d)\n#endif  /* not _CC_POWERPACK32_ */\n\n/*\n#define freemem(g)          _INTERCEPT(freemem(g))\n#define vsscanf(d,f,a)      _INTERCEPTX(vsscanf(d,f,a),d)\n*/\n\n/* ----- END Borland C/C++ interceptions ----- */\n\n#else\n\n#error Unknown compiler in MemCheck.h\n\n#endif  /* Compiler-specific Function Mapping Section */\n\n/*  Location Transmitters\n\n    You can add any non-intercepted functions to\n    this bunch... Just updates MemCheck's file and line\n    information via mc_set_location(), which is thousands\n    of times faster than anything that does I/O.\n    The only time this section could be a problem is\n    if the header file is included before any other header\n    files which prototype these routines.\n\n    Borland's TD (Turbo Debugger) also has problems here (see note).\n*/\n#ifndef _lint   /* LINT not like */\n\n/*  Borland's Turbo Debugger gets confoosed and executes\n    a `Run' instead of a `Step' when _SETLOC macro is used...\n*/\n#if !defined (_CC_BORLAND_)\n#if 1   /* Change this to '0' to omit this section */\n\n#define printf              _SETLOC(printf)\n\n#define fopen               _SETLOC(fopen)\n#define fprintf             _SETLOC(fprintf)\n#define fread               _SETLOC(fread)\n#define fwrite              _SETLOC(fwrite)\n#define fclose              _SETLOC(fclose)\n\n#define system              _SETLOC(system)\n#define exec                _SETLOC(exec)\n#define spawnl              _SETLOC(spawnl)\n#define spawnlp             _SETLOC(spawnlp)\n#define spawnle             _SETLOC(spawnle)\n#define spawnlpe            _SETLOC(spawnlpe)\n#define spawnv              _SETLOC(spawnv)\n#define spawnvp             _SETLOC(spawnvp)\n#define spawnve             _SETLOC(spawnve)\n#define spawnvpe            _SETLOC(spawnvpe)\n\n#endif  /* end location transmission section */\n#endif  /* not Borland C++ */\n#endif  /* not def _lint */\n\n\n/* ****  THIRD-PARTY MAPPINGS  **** */\n\n/*  Vermont Views V3.xx\n\n    The following code will transmit the exact file\n    and line of any mem_get() and mem_free() calls to\n    MemCheck, so that it can report on the location where\n    these functions are called, instead of the location of\n    the calloc() or free().\n\n    If you've used MCCONFIG to configure the Vermont Views source \n    code, you *must* either NOT include the MemCheck header file \n    in the MEM_GET.C and MEM_FREE.C modules, or, if you do, then\n    #define NO_INTERCEPT beforehand, e.g.\n\n         Module MEM_GET.C ... \n        :\n        #define NO_INTERCEPT\n        #include <memcheck.h>\n        :\n\n    MCCONFIG may be used to configure even the shrouded\n    Vermont Views source code.\n\n    See also: TechNote \"Using MemCheck 3.0 Professional\n        With Vermont Views\", available on the StratosWare\n        BBS (313) 996-2993 as VIEWS.TXT, or by fax.\n*/\n#if defined (VV_SYS)    /* should do the trick */\n#   define mem_get(s)   _INTERCEPT(mem_get(s))\n#   define mem_free(p)  _INTERCEPT(mem_free(p))\n#endif\n\n\n/* ****  APPLICATION-SPECIFIC MAPPINGS  **** */\n\n/*\n    If your application uses allocation \"cover\" routines,\n    MemCheck will by default report errors and leaks by\n    the file and line of the malloc or free within the\n    cover module.  To get MemCheck to report by file and\n    line where the cover function is actually called, follow\n    the instructtions in MemCheck TechNote \"Transmitting File\n    and Line to MemCheck 3.0 Professional Through Cover Functions.\"\n\n    This is where you can place the cover function macros.\n*/\n\n\n/* end APPLICATION-SPECIFIC MAPPINGS */\n\n#endif  /* not NO_INTERCEPT */\n\n/* Calls that xmit source file, line number if called in source */\n/* *** MemCheck API file & line transmittal *** */\n#define mc_startcheck(erf)      mc_startcheck(_MCSF_,_MCSL_,erf)\n#define mc_stack_trace(_memo)   _INTERCEPT(mc_stack_trace(_memo))\n#define mc_debug(s)             _INTERCEPT(mc_debug(s))\n#define mc_debugf(arglist)      mc_debugv arglist\n#define mc_debugv               _mcsl(_MCSF_,_MCSL_),mc_debugv\n#define mc_endcheck()           _INTERCEPT(mc_endcheck())\n#define mc_check_buffers()      _INTERCEPT(mc_check_buffers())\n#define mc_check(p)             _INTERCEPT(mc_check(p))\n#define mc_register(p,s)        _INTERCEPT(mc_register(p,s))\n#define mc_unregister(p)        _INTERCEPT(mc_unregister(p))\n#define mc_nullcheck()          _INTERCEPT(mc_nullcheck())\n#define mc_report(f)            _INTERCEPT(mc_report(f))\n\n/*lint -restore  652 Define of symbol declared prev */\n\n#endif  /* not MEMCHECK_MODULE, function interceptions */\n\n\n/* End \"C\" call wrapper */\n#ifdef __cplusplus\n}\n\n\n/*  C++ MemCheck Class\n\n    This class can be used as an alternative to\n    AutoInit, or to placing the mc_startcheck() and\n    mc_endcheck() calls in your main() program.\n    Just declaring an object of class 'MemCheck'\n    will start MemCheck up;  usually you will place\n    this 'above' any other global or statically declared\n    C++ objects in your main module.\n\n    Here are some examples of starting MemCheck up\n    via object mechanics:\n\n        MemCheck On;\n        MemCheck Active;\n        MemCheck Rules;\n\n    Use your imagination!  Note that if AutoInit is ON,\n    any calls to mc_startcheck() and mc_endcheck() are\n    ignored.\n*/\n#if !defined (NO_INTERCEPT) /* must not have this def'd */\n\n/* This class def causes a warning under MSC if not used */\n#if !defined (_CC_MSC_)\n\nclass MemCheck {\npublic:\n    MemCheck ()  { mc_startcheck (NULL); }\n    ~MemCheck () { mc_endcheck ();       }\n};\n\n#endif\n\n#endif /* NO_INTERCEPT */\n\n\n/* *** For use in new and delete modules only *** */\n/*\n    Replace 'mallocs' with 'cpp_mallocs', etc.\n    In new and delete modules, NO_INTERCEPT should be #defined, e.g.\n\n        #define NO_INTERCEPT\n        #include <memcheck.h>\n        :\n        void * operator new ( size_t size )\n        {\n            if (!size)  size = 1;\n            return (cpp_malloc (size));\n        }\n        etc.\n*/\n#define cpp_malloc(_s)      (_mc_set_newflag(),     malloc(_s))\n#define cpp_calloc(_n,_s)   (_mc_set_newflag(),     calloc(_n,_s))\n#define cpp_free(_p)        (_mc_set_delflag(),     free(_p))\n\n/* Borland C++ */\n#define cpp_farmalloc(_s)   (_mc_set_newflag(),     farmalloc(_s))\n#define cpp_farfree(_fp)    (_mc_set_delflag(),     farfree(_fp))\n\n/* Microsoft C++-compatibles */\n#define cpp__fmalloc(_s)    (_mc_set_newflag(),     _fmalloc(_s))\n#define cpp__ffree(_fp)     (_mc_set_delflag(),     _ffree(_fp))\n\n\n/* C++ */\n#if !defined (NO_INTERCEPT)\n#if !defined (NO_CPP)\n\n/*\n    This method is off by default, because it\n    requires definition of a new operator like:\n\n      void * new (size_t size, char *file, int lineno);\n\n    Such a new operator is included in your SOURCE\\CPP\n    directory. To have this method used for all modules,\n    #define NEW_OVERLOADED at the top of this header file\n    or in your project #include file, BEFORE the MemCheck\n    header file is #included.\n\n    The substitutions for the new operator\n    may not work in all situations.  To disable\n    MemCheck's interception of new on a module-by-\n    module basis by undefining NEW_OVERLOADED.\n*/\n#if defined (NEW_OVERLOADED)\n\n/*  Method 1: Placement Operators\n\n    Use placement operators to trap file and line location transparently\n    on calls to new.  \n    \n    Thanks for this tip to Dan Saks,\n    C and C++ writer, author, teacher, and columnist--buy his books.\n    He came through when no one else had a clue!\n\n    Please consult your manual, MemCheck technotes, \n    or StratosWare Technical Support (1-800-WE-DEBUG)\n    for details on how to configure your project for\n    use with an overloaded new placement operator.\n*/\n\n/* Declare overloaded new with placement operators */\nvoid *operator new (size_t _sz, char *file, int lineno);\n#if defined (_CPP_ANSI20_)\n/*  Array version; only under supporting compilers \n    COMMENT LINE OUT if it causes a compile error.\n*/\nvoid *operator new[] (size_t _sz, char *file, int lineno);\n#endif\n\n#if !defined (_CC_MSC_)\n#define new     new((char *)__FILE__,(int)__LINE__)\n#else\n#define new     new(__FILE__,__LINE__)\n#endif\n\n/*  NOTE:\n    This placement operator interception syntax has been\n    known to cause syntax errors (in VC++ 1.0) for no apparent reason\n    on statements like\n\n            Domain *d = new Domain ();\n\n    Workaround is to change line (sorry!) to equivalent\n\n            Domain *d = new Domain;\n*/\n\n/* Backwards compatibility with the V2.1 C++ macros */\n#ifndef NEW\n#define NEW(_object)         new _object\n#endif\n#ifdef DELETE\n#define DELETE(_object)      delete _object\n#endif\n#define DELETE_ARR(_arr)     delete[] _arr\n\n#else   /* !NEW_OVERLOADED - end of Placement Operator intercept */\n\n/*  New and Delete Interception, Method 2: NEW() and DELETE()\n\n    The NEW() and DELETE() macros may be used to transmit file\n    and line of new and delete.   These macros, which require\n    modification of source code, i.e. \"NEW(object)\" for \"new object\",\n    should probably be used only if the above overloaded new does\n    not work for your code base.\n    \n    Please consult your manual, MemCheck technotes, \n    or StratosWare Technical Support (1-800-WE-DEBUG)\n    for details on how to configure your project for\n    use with NEW() and DELETE().\n\n    If calling, please have your MemCheck serial number handy.\n*/\n#ifndef NEW\n#define NEW(_object)        (_mcsl_new(_MCSF_,_MCSL_),    new _object)\n#endif\n#ifndef DELETE  /* WINNT.H under BC DPMI32 defines DELETE */\n#define DELETE(_object)     (_mcsl_delete(_MCSF_,_MCSL_), delete _object)\n#endif\n#define DELETE_ARR(_arr)    (_mcsl_delete(_MCSF_,_MCSL_), delete[] _arr)\n\n#endif  /* !NEW_OVERLOADED */\n\n#define delete  _mcsl_delete(_MCSF_,_MCSL_), delete\n\n\n/* *** FAILURES *** */\n\n/*  These macros failed in the purpose of\n    intercepting new transparently in some\n    situation or other.\n*/\n\n/* Failed on \" * new expr \" (TV)  */\n/*  #define new (mc_set_location(),0) ? NULL : new  */\n\n/* Failed on \" x = new Object \" (TV) */\n/*  #define new ((mc_set_location(),0) ? NULL : new)    */\n/*  #define new new (mc_set_location(),0) ? NULL :  */\n\n#endif  /* !NO_CPP */\n#endif  /* NO_INTERCEPT */\n#endif  /* cplusplus */\n/******** End C++ ************/\n\n\n#endif      /* End of Section for MEMCHECK Defined */\n\n/* -------------------------------------------------------------------------- */\n\n#endif  /* _MEMCHECK_H_ */\n\n\n/********************************\n * End of MemCheck 3.0 Header *\n ********************************/\n\n"
  },
  {
    "path": "CODE/MENUS.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MENUS.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MENUS.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Phil W. Gorrow                                               *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : Oct. 24, 1996 Victor Grippi                                  *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Main_Menu -- Menu processing                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#ifdef WIN32\n#include \"ccdde.h\"\n#else\t//WIN32\n#include\t<sys\\timeb.h>\n#endif\n\n/*****************************\n**\tFunction prototypes\n******************************/\n\nPRIVATE int Coordinates_In_Region(int x, int y, int inx1, int iny1, int inx2, int iny2);\nPRIVATE int Select_To_Entry(int select, unsigned long bitfield, int index);\nPRIVATE void Flash_Line(char const *text, int xpix, int ypix, unsigned nfgc, unsigned hfgc, unsigned bgc);\n\nint UnknownKey;\n\nPRIVATE int MenuUpdate=1;\nPRIVATE int MenuSkip;\n\n#ifdef FIXIT_VERSION_3\n#include \"WolStrng.h\"\n#endif\n\n/*=========================================================================*/\n/*\tSELECT_TO_ENTRY:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\tThis routine converts a selection to the correct string entry. It\t   */\n/*\tdoes this by search through a long bitfield starting at position index\t*/\n/*\tuntil it finds the correct conversion to entries.\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\tINPUTS:\tint selection from menu, long the bit field to search, int \t   */\n/*\t\t\t\tthe starting index within the bit field.\t\t\t\t\t\t\t\t*/\n/*\tRETURNS:\tint the index into the table of entries\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nPRIVATE int Select_To_Entry(int select, unsigned long bitfield, int index)\n{\n\tint placement;\n\n\tif (bitfield==0xFFFFFFFFL) \t\t\t\t\t\t\t/* if all bits are set\t*/\n\t\treturn(select);\t\t\t\t\t\t\t\t\t\t/*\t\tthen it as is\t\t*/\n\n\tplacement=0;\t\t\t\t\t\t\t\t\t\t\t\t/* current pos zero\t\t*/\n\twhile (select) {\t\t\t\t\t\t\t\t\t\t\t/* while still ones\t\t*/\n\t\tif (bitfield & (1L<<(placement+index)))\t\t\t/* if this flagged then\t*/\n\t\t\tselect--;\t\t\t\t\t\t\t\t\t\t\t/* decrement counter\t\t*/\n\t\tplacement++;\t\t\t\t\t\t\t\t\t\t\t/* and we moved a place\t*/\n\t}\n\twhile (!(bitfield & (1L<<(placement+index)))) {\n\t\tplacement++;\n\t}\n\n\treturn(placement);\t\t\t\t\t\t\t\t\t\t/* return the position\t*/\n}\n\n\n/*=========================================================================*/\n/*\tFLASH_LINE:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\tThis routine will flash the line at the desired location for the\t\t*/\n/*\tmenu routine. It is way cool awesome!\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\tINPUTS:\tchar *text, int x position on line, int y position, char\t\t   */\n/*\t\t\t\tnormal foreground color, char hilight foreground color, char \t*/\n/*\t\t\t\tbackground color\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\tRETURNS:\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nPRIVATE void Flash_Line(char const *text, int xpix, int ypix, unsigned nfgc, unsigned hfgc, unsigned bgc)\n{\n\tint loop;\n\n\tfor (loop=0;loop<3;loop++) {\n\t\tHide_Mouse();\n\t\tPlain_Text_Print(text, xpix, ypix, hfgc, bgc, TPF_8POINT|TPF_DROPSHADOW);\n\t\tDelay(2);\n\t\tPlain_Text_Print(text, xpix, ypix, nfgc, bgc, TPF_8POINT|TPF_DROPSHADOW);\n\t\tShow_Mouse();\n\t\tDelay(2);\n\t}\n}\n\n/*=========================================================================*/\n/*\tCOORDINATES_IN_REGION:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\tTest to see if a given pair of coordinates are within the given \t\t*/\n/*\trectangular region.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\tINPUTS:\tint x to be tested, int y to be tested, int left x pos,\t\t\t*/\n/*\t\t\t\tint top y pos, int right x pos, int bottom y pos\t\t\t\t\t*/\n/*\tRETURNS:\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nPRIVATE int Coordinates_In_Region(int x, int y, int inx1, int iny1, int inx2, int iny2)\n{\n\treturn((x>=inx1)&&(x<=inx2)&&(y>=iny1)&&(y<=iny2));\n}\n\n#ifdef NEVER\n/*=========================================================================*/\n/*\tFIND_MENU_ITEMS:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\tThis routine finds the real total items in a menu when certain items\t*/\n/*\tmay be disabled by bit fields and the like. This is done by looping\t\t*/\n/*\tthrough the fields, starting at the position passed in index and \t\t\t*/\n/*\tcounting the number of bits that are set.\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\tINPUTS:\tint the maximum number of items possible on the menu, long \t\t*/\n/*\t\t\t\tthe bit field of enabled and disabled items, char the index\t\t*/\n/*\t\t\t\tpoint to start at within the list.\t\t\t\t\t\t\t\t\t\t*/\n/*\tRETURNS:\tint the total number of items in the menu\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n int Find_Menu_Items(int maxitems, unsigned long field, char index)\n {\n\tint loop,ctr;\n\n\tif (field==0xFFFFFFFFL) \t\t\t\t\t\t\t\t\t\t/* if all bits are set\t*/\n\t\treturn(maxitems);\t\t\t\t\t\t\t\t\t\t/* then maxitems set\t\t*/\n\n\tfor (loop=ctr=0;loop<maxitems;loop++) {\t\t\t/* loop through items\t*/\n\t\tif (field & (1L<<(loop+index))) {\t\t\t\t/* if the bit is set\t\t*/\n\t\t\tctr++;\t\t\t\t\t\t\t\t\t\t\t\t/*\t\tcount the item\t\t*/\n\t\t}\n\t}\n\treturn(ctr);\n}\n#endif\n\n\n/*=========================================================================*/\n/*\tSETUP_EOB_MONITOR_MENU:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\tThis routine sets up the eye of the beholder monitor menu.\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\tINPUTS:\tint the menu we are using, char *[] the array of text which\t\t*/\n/*\t\t\t\tmakes up the menu commands, long the info field, int the\t\t\t*/\n/*\t\t\t\tindex into the field, int the number of lines to skip.\t\t\t*/\n/*\tRETURNS:\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Setup_Menu(int menu, char const * text[], unsigned long field, int index, int skip)\n{\n\tint * menuptr,lp;\n\tint menuy,menux,idx,item,num,drawy;\n\n\tmenuptr=&MenuList[menu][0];\t\t\t\t\t\t\t/* get pointer to menu\t*/\n\tmenuy=WinY+menuptr[MENUY];\t\t\t\t\t\t\t\t/* get the absolute \t\t*/\n\tmenux=(WinX+menuptr[MENUX]);\t\t\t\t\t\t/*\t\tcoords of menu\t\t*/\n\titem=Select_To_Entry(menuptr[MSELECTED], field, index);\n\tnum=menuptr[ITEMSHIGH];\n\n\tPlain_Text_Print(0, 0, 0, TBLACK, TBLACK, TPF_8POINT|TPF_DROPSHADOW);\n \tHide_Mouse();\n\tfor (lp=0;lp<num;lp++) {\n\t\tidx=Select_To_Entry(lp, field, index);\n\t\tdrawy=menuy+(lp*FontHeight)+(lp*skip);\n\t\tPlain_Text_Print(text[idx], menux, drawy, menuptr[((idx==item) && (MenuUpdate )) ? HILITE : NORMCOL], TBLACK, TPF_8POINT|TPF_DROPSHADOW);\n//\t\tif ((idx==item) && (MenuUpdate ))\n//\t\t\tText_Print(text[idx], menux, drawy, menuptr[HILITE], TBLACK);\n\t}\n\tMenuSkip=skip;\n\tShow_Mouse();\n\tKeyboard->Clear();\n}\n\n\n/*=========================================================================*/\n/*\tCHECK_MENU:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\tINPUTS:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\tRETURNS:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nint Check_Menu(int menu, char const * text[], char *, long field, int index)\n{\n\tint maxitem,select,key,menuy,menux;\n\tint mx1,mx2,my1,my2,tempy;\n\tint drawy,menuskip,halfskip;\n\tint normcol,litcol,item,newitem,idx;\n\tint * menuptr;\n\n\t//selection++;\t\t\t\t\t\t\t\t\t\t\t\t/* get rid of warning\t*/\n\n\tmenuptr = &MenuList[menu][0];\t\t\t\t\t\t\t/* get pointer to menu\t*/\n\tmaxitem = menuptr[ITEMSHIGH]-1;\t\t\t\t\t\t\t/* find max items\t\t\t*/\n\tnewitem = item = menuptr[MSELECTED]%(maxitem+1);\t/* find selected \t\t\t*/\n\tselect = -1;\t\t\t\t\t\t\t\t\t\t\t\t\t/* no selection made\t\t*/\n\tmenuskip = FontHeight+MenuSkip;\t\t\t\t\t\t\t/* calc new font height\t*/\n\thalfskip = MenuSkip>>1;\t\t\t\t\t\t\t\t\t/* adjustment for menus\t*/\n\n\tmenuy = WinY+menuptr[MENUY];\t\t\t\t\t\t\t\t/* get the absolute \t\t*/\n\tmenux = (WinX+menuptr[MENUX]);\t\t\t\t\t\t/*\t\tcoords of menu\t\t*/\n\tnormcol = menuptr[NORMCOL];\n\tlitcol = menuptr[HILITE];\n\n\t/*\n\t**\tFetch a pending keystroke from the buffer if there is a keystroke\n\t**\tpresent. If no keystroke is pending then simple mouse tracking will\n\t**\tbe done.\n\t*/\n\tkey = 0;\n\tUnknownKey = 0;\n\tif (Keyboard->Check()) {\n#ifdef WIN32\n\t\tkey = (Keyboard->Get() & ~(WWKEY_SHIFT_BIT|WWKEY_ALT_BIT|WWKEY_CTRL_BIT) );\t\t\t/* mask off all but release bit\t*/\n#else\n\t\tkey = (Keyboard->Get()&0x08FF);\t\t\t/* mask off all but release bit\t*/\n#endif\n\t}\n\n\t/*\n\t**\tif we are using the mouse and it is installed, then find the mouse\n\t**\tcoordinates of the menu and if we are not somewhere on the menu get\n\t**\tthe heck outta here. If we are somewhere on the menu, then figure\n\t**\tout the new selected item, and continue forward.\n\t*/\n\tmx1=(WinX)+(menuptr[MENUX]*FontWidth);\t\t/* get menu coords\t\t*/\n\tmy1=(WinY)+(menuptr[MENUY])-halfskip;\t\t\t/*\t\tfrom the menu\t\t*/\n\tmx2=mx1+(menuptr[ITEMWIDTH]*FontWidth)-1;\t\t/*\t\tstructure as\t\t*/\n\tmy2=my1+(menuptr[ITEMSHIGH]*menuskip)-1;\t\t/*\t\tnecessary\t\t\t*/\n\n\t\ttempy=Get_Mouse_Y();\n\t\tif (Coordinates_In_Region(Get_Mouse_X(), tempy, mx1, my1, mx2, my2)&& MenuUpdate) {\n\t\t\tnewitem=(tempy-my1)/menuskip;\n\t\t}\n\n\tswitch (key) {\n\n\t\tcase KN_UP:\t\t\t\t\t\t\t\t\t\t\t\t/* if the key moves up\t*/\n\t\t\tnewitem--;\t\t\t\t\t\t\t\t\t\t\t/* \tnew item up one\t*/\n\t\t\tif (newitem<0) \t\t\t\t\t\t\t\t\t/* if invalid new item\t*/\n\t\t\t\tnewitem=maxitem;\t\t\t\t\t\t\t\t/* put at list bottom\t*/\n\t\t\tbreak;\n\t\tcase KN_DOWN:\t\t\t\t\t\t\t\t\t\t\t/* if key moves down\t\t*/\n\t\t\tnewitem++;\t\t\t\t\t\t\t\t\t\t\t/*\t\tnew item down one\t*/\n\t\t\tif (newitem>maxitem) \t\t\t\t\t\t\t/* if new item past \t\t*/\n\t\t\t\tnewitem=0;\t\t\t\t\t\t\t\t\t\t/*\t\tlist end, clear\t*/\n\t\t\tbreak;\n\t\tcase KN_HOME:\t\t\t\t\t\t\t\t\t\t\t/* if top of list key \t*/\n\t\tcase KN_PGUP:\t\t\t\t\t\t\t\t\t\t\t/*\t\tis selected then\t*/\n\t\t\tnewitem=0;\t\t\t\t\t\t\t\t\t\t\t/*\t\tnew item = top\t\t*/\n\t\t\tbreak;\n\t\tcase KN_END:\t\t\t\t\t\t\t\t\t\t\t/* if bottom of list is\t*/\n\t\tcase KN_PGDN:\t\t\t\t\t\t\t\t\t\t\t/*\t\tselected then\t\t*/\n\t\t\tnewitem=maxitem;\t\t\t\t\t\t\t\t\t/*\t\tnew item = bottom\t*/\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tHandle mouse button press. Set selection and then fall into the\n\t\t**\tnormal menu item select logic.\n\t\t*/\n\t\tcase KN_RMOUSE:\n\t\tcase KN_LMOUSE:\n\t\t\tif (Coordinates_In_Region(Keyboard->MouseQX, Keyboard->MouseQY, mx1, my1, mx2, my2)) {\n\t\t\t\tnewitem = (Keyboard->MouseQY - my1) / menuskip;\n\t\t\t} else {\n\t\t\t\tUnknownKey = key;\t\t\t//\tPass the unprocessed button click back.\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t/*\n\t\t**\tNormal menu item select logic. Will flash line and exit with menu\n\t\t**\tselection number.\n\t\t*/\n\t\tcase KN_RETURN:\t\t\t\t\t\t\t\t\t\t/* if a selection is \t*/\n\t\tcase KN_SPACE:\t\t\t\t\t\t\t\t\t\t\t/*\t\tmade with key\t\t*/\n\t\tcase KN_CENTER:\n\t\t\tselect=newitem;\t\t\t\t\t\t\t\t\t/*\t\tflag it made.\t\t*/\n\t\t\tbreak;\n\n\t\tcase 0:\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tWhen no key was pressed or an unknown key was pressed, set the\n\t\t**\tglobal record of the key and exit normally.\n\t\t**\tEXCEPTION:\tIf the key matches the first letter of any of the\n\t\t**\t\t\t\t\tmenu entries, then presume it as a selection of\n\t\t**\t\t\t\t\tthat entry.\n\t\t*/\n\t\tdefault:\n\t\t\tfor (idx = 0; idx < menuptr[ITEMSHIGH]; idx++) {\n\t\t\t\tif (toupper(*(text[Select_To_Entry(idx, field, index)])) == toupper(Keyboard->To_ASCII((KeyNumType)(key&0x0FF)))) {\n\t\t\t\t\tnewitem = select = idx;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tUnknownKey = key;\n\t\t\tbreak;\n\t}\n\n\tif (newitem!=item) {\n\t\tHide_Mouse();\n\t\tidx=Select_To_Entry(item, field, index);\n\t\tdrawy=menuy+(item*menuskip);\n\t\tPlain_Text_Print(text[idx], menux, drawy, normcol, TBLACK, TPF_8POINT|TPF_DROPSHADOW);\n\t\tidx=Select_To_Entry(newitem, field, index);\n\t\tdrawy=menuy+(newitem*menuskip);\n\t\tPlain_Text_Print(text[idx], menux, drawy, litcol, TBLACK, TPF_8POINT|TPF_DROPSHADOW);\n\t\tShow_Mouse();\t\t\t\t\t\t\t\t\t\t\t\t/* resurrect the mouse\t*/\n\t}\n\n\tif (select!=-1) {\n\t\tidx=Select_To_Entry(select, field, index);\n\t\tHide_Mouse();\t\t\t\t\t\t\t\t\t\t\t\t/* get rid of the mouse\t*/\n\t\tdrawy=menuy+(newitem*menuskip);\n\t\tFlash_Line(text[idx], menux, drawy, normcol, litcol, TBLACK);\n\t\tShow_Mouse();\n\t\tselect=idx;\n\t}\n\n\tmenuptr[MSELECTED]=newitem;\t\t\t\t\t\t\t/* update menu select\t*/\n\n\treturn(select);\n}\n\n\n/***************************************************************************\n * Do_Menu -- Generic menu processor.                                      *\n *                                                                         *\n *    This helper function displays a menu of specified entries and waits  *\n *    for the player to make a selection. If a selection is made, then     *\n *    a whole number (starting at 0) is returned matching the entry        *\n *    selected. If ESC is pressed, then -1 is returned.                    *\n *                                                                         *\n * INPUT:   strings  -- A pointer to an array of pointers to text strings. *\n *                      Each entry in the list will be a menu entry that   *\n *                      can be selected.                                   *\n *                                                                         *\n *          blue     -- Should the special blue color be used to display   *\n *                      the menu?                                          *\n *                                                                         *\n * OUTPUT:  Returns with the cardinal number of the selected menu entry.   *\n *          If ESC was pressed, then -1 is returned.                       *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1994 JLB : Created.                                             *\n *=========================================================================*/\nint Do_Menu(char const ** strings, bool )\n{\n\tint\tcount;\t\t// Number of entries in this menu.\n\tint\tlength;\t\t// The width of the menu (in pixels).\n\tchar\tconst ** ptr;\t\t// Working menu text pointer.\n\tint\tselection;\t// Selection from user.\n\n\tif (!strings) return(-1);\n\tSet_Logic_Page(SeenBuff);\n\tKeyboard->Clear();\n\n\t/*\n\t**\tDetermine the number of entries in this string.\n\t*/\n\tptr = strings;\n\tcount = 0;\n\twhile (*ptr++) {\n\t\tcount++;\n\t}\n\tMenuList[0][ITEMSHIGH] = count;\n\n\t/*\n\t**\tDetermine the width of the menu by finding the length of the\n\t**\tlongest menu entry.\n\t*/\n\tPlain_Text_Print(TXT_NONE, 0, 0, 0, 0, TPF_8POINT|TPF_DROPSHADOW);\n\tlength = 0;\n\tptr = strings;\n\twhile (*ptr) {\n\t\tlength = max(length, (int)String_Pixel_Width(*ptr));\n\t\tptr++;\n\t}\n\tlength += 7;\n\tMenuList[0][ITEMWIDTH] = length >> 3;\n\n\t/*\n\t**\tAdjust the window values to match the size of the\n\t**\tspecified menu.\n\t*/\n\tWindowList[WINDOW_MENU][WINDOWWIDTH] = (MenuList[0][ITEMWIDTH] + 2) * 8;\n\tWindowList[WINDOW_MENU][WINDOWX] = (19 - (length >> 4)) * 8;\n\tWindowList[WINDOW_MENU][WINDOWY] = 174 - (unsigned)(MenuList[0][ITEMSHIGH] * (FontHeight+FontYSpacing));\n\tWindowList[WINDOW_MENU][WINDOWHEIGHT] = MenuList[0][ITEMSHIGH] * FontHeight + 5 /*11*/;\n\n\t/*\n\t**\tDisplay the menu.\n\t*/\n\tChange_Window((int)WINDOW_MENU);\n\tShow_Mouse();\n\tWindow_Box(WINDOW_MENU, BOXSTYLE_RAISED);\n\tSetup_Menu(0, strings, 0xFFFFL, 0, 0);\n\n\tKeyboard->Clear();\n\tselection = -1;\n\tUnknownKey = 0;\n\twhile (selection == -1) {\n\t\tCall_Back();\n\t\tselection = Check_Menu(0, strings, NULL, 0xFFL, 0);\n\t\tif (UnknownKey != 0 || UnknownKey == KN_ESC || UnknownKey==KN_LMOUSE || UnknownKey==KN_RMOUSE) break;\n\t}\n\tKeyboard->Clear();\n\tHide_Mouse();\n\n\tHidPage.Blit(SeenPage);\n//WindowList[WINDOW_MAIN][2] = SeenBuff.Get_Width();//BG\n\tChange_Window((int)WINDOW_MAIN);\n\tMap.Flag_To_Redraw(true);\n\treturn(selection);\n}\n\n\n/***************************************************************************\n * Main_Menu -- Menu processing                                            *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tindex of item selected, -1 if time out\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/17/1995 BRR : Created.                                             *\n *=========================================================================*/\nint Main_Menu(unsigned long )\n{\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tint\td_dialog_w = 152 * RESFACTOR;\n#ifdef FIXIT_VERSION_3\n\tint\td_dialog_h = 100 * RESFACTOR;\n#else\n//#ifdef WIN32\t//Extra 'Internet' option on WIN32 menu\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - No internet play\n\tint\td_dialog_h = 100 * RESFACTOR;\n#else\n//\t#if defined(MPEGMOVIE) // Denzil 6/25/98 - Video settings\n//\tint\td_dialog_h = 100 * RESFACTOR;\n//\t#else\n\tint\td_dialog_h = 80 * RESFACTOR;\n//\t#endif\n#endif\t//WIN32\n#endif\t//FIXIT_VERSION_3\n\tint\td_dialog_x = 85 * RESFACTOR;\n\tint\td_dialog_y = 75 * RESFACTOR;\n\tint\td_dialog_cx = d_dialog_x + (d_dialog_w / 2);\n\n\tint\td_start_w = 118 * RESFACTOR;\n\tint\td_start_h = 9 * RESFACTOR;\n\tint\td_start_x = 102 * RESFACTOR;\n#ifndef FIXIT_VERSION_3\t\t\t//\tRemoved button from main menu.\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - no internet play\n\tint\td_internet_w = 118 * RESFACTOR;\n\tint\td_internet_h = 9 * RESFACTOR;\n\tint\td_internet_x = 102 * RESFACTOR;\n#endif\t//WIN32\n#endif\n\n//#if defined(MPEGMOVIE) // Denzil 6/26/98 Video settings\n//\tint\td_movie_w = 118 * RESFACTOR;\n//\tint\td_movie_h = 9 * RESFACTOR;\n//\tint\td_movie_x = 102 * RESFACTOR;\n//#endif\n\n\tint\td_load_w = 118 * RESFACTOR;\n\tint\td_load_h = 9 * RESFACTOR;\n\tint\td_load_x = 102 * RESFACTOR;\n\n\tint\td_multi_w = 118 * RESFACTOR;\n\tint\td_multi_h = 9 * RESFACTOR;\n\tint\td_multi_x = 102 * RESFACTOR;\n\n\tint\td_intro_w = 118 * RESFACTOR;\n\tint\td_intro_h = 9 * RESFACTOR;\n\tint\td_intro_x = 102 * RESFACTOR;\n\n\tint\td_exit_w = 118 * RESFACTOR;    //changed value to 118 V.Grippi\n\tint\td_exit_h = 9 * RESFACTOR;\n\tint     d_exit_x = 102 *RESFACTOR;   //Added V.Grippi\n\n\tint starty = d_dialog_y + (12 * RESFACTOR);\n\n//#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - No internet play\n//#ifndef FIXIT_VERSION_3\n\tstatic int\tmax_buttons = 7;\n//#else\n//\tstatic int\tmax_buttons = 6;\n//#endif\n\n//#if defined(MPEGMOVIE) // Denzil 6/26/98 Video settings\n//\tmax_buttons++;\n//#endif\n\t/*\n\t**\tButton enumerations:\n\t*/\n\t//\tEnums in Select_Game() must match order of buttons in Main_Menu().\n#ifdef FIXIT_VERSION_3\n\tenum {\n\t\tBUTTON_EXPAND=100,\t\t\t//\t(CS)\n\t\tBUTTON_EXPAND_AM,\n\t\tBUTTON_START,\n\t\tBUTTON_LOAD,\n\t\tBUTTON_MULTI,\n\t\tBUTTON_INTRO,\n\t\tBUTTON_EXIT,\n\t};\n#else\t//\tFIXIT_VERSION_3\n\tenum {\n\t\tBUTTON_EXPAND=100,\n\t\tBUTTON_START,\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - No internet play\n\t\tBUTTON_INTERNET,\n#endif\t//WIN32\n//#if defined(MPEGMOVIE) // Denzil 6/26/98 Video settings\n//\t\tBUTTON_MOVIE,\n//#endif\n\t\tBUTTON_LOAD,\n\t\tBUTTON_MULTI,\n\t\tBUTTON_INTRO,\n\t\tBUTTON_EXIT,\n\t};\n#endif\t//\tFIXIT_VERSION_3\n\n\t/*\n\t**\tDialog variables:\n\t*/\n#ifdef FIXIT_VERSION_3\n\tbool bExpansionCS = Expansion_CS_Present();\n\tbool bExpansionAM = Expansion_AM_Present();\n#else\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tbool expansions = Expansion_CS_Present() | Expansion_AM_Present();\n#else\n\tbool expansions = Expansion_CS_Present();\n#endif\n#endif\n\tKeyNumType input;\t\t\t\t\t\t\t\t// input from user\n\tint retval;\t\t\t\t\t\t\t\t\t\t// return value\n\tint curbutton;\n\tTextButtonClass * buttons[7];\n\tunsigned long starttime;\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass * commands = NULL;\t\t\t\t// the button list\n\n#ifdef FIXIT_VERSION_3\n\tint ystep = 14 * RESFACTOR;\n\tif( bExpansionCS )\n\t{\n\t\tif( bExpansionAM )\n\t\t\tystep = 12 * RESFACTOR;\n\t\telse\n\t\t\tystep = 13 * RESFACTOR;\n\t}\n\telse if( bExpansionAM )\n\t\tystep = 13 * RESFACTOR;\n\n\tTextButtonClass expandbtnCS( BUTTON_EXPAND, TXT_WOL_CS_MISSIONS, TPF_BUTTON, d_start_x, starty, d_start_w, d_start_h );\n\tif( bExpansionCS )\n\t\tstarty += ystep;\n\tTextButtonClass expandbtnAM( BUTTON_EXPAND_AM, TXT_WOL_AM_MISSIONS, TPF_BUTTON, d_start_x, starty, d_start_w, d_start_h );\n\tif( bExpansionAM )\n\t\tstarty += ystep;\n#else\n\tint ystep = 12 * RESFACTOR;\n\tif (expansions) ystep = 10 * RESFACTOR;\n\t\n\tTextButtonClass expandbtn (BUTTON_EXPAND, TXT_NEW_MISSIONS, TPF_BUTTON, d_start_x, starty, d_start_w, d_start_h);\n\tif (expansions) starty += ystep;\n#endif\n\n\tTextButtonClass startbtn(BUTTON_START, TXT_START_NEW_GAME, TPF_BUTTON, d_start_x, starty, d_start_w, d_start_h);\n\tstarty += ystep;\n#ifndef FIXIT_VERSION_3\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - no internet play\n\tTextButtonClass internetbutton (BUTTON_INTERNET, TXT_INTERNET, TPF_BUTTON, d_internet_x, starty, d_internet_w, d_internet_h);\n\tstarty += ystep;\n#endif\t//WIN32\n#endif\n\n//#if defined(MPEGMOVIE) // Denzil 6/26/98 Video settings\n//\tTextButtonClass moviebutton(BUTTON_MOVIE, \"Movie Settings\", TPF_BUTTON, d_movie_x, starty, d_movie_w, d_movie_h);\n//\tstarty += ystep;\n//#endif\t//WIN32\n\n\tTextButtonClass loadbtn(BUTTON_LOAD, TXT_LOAD_MISSION, TPF_BUTTON, d_load_x, starty, d_load_w, d_load_h);\n\tstarty += ystep;\n\n\tTextButtonClass multibtn(BUTTON_MULTI, TXT_MULTIPLAYER_GAME, TPF_BUTTON, d_multi_x, starty, d_multi_w, d_multi_h);\n\tstarty += ystep;\n\n\tTextButtonClass introbtn(BUTTON_INTRO, TXT_INTRO, TPF_BUTTON, d_intro_x, starty, d_intro_w, d_intro_h);\n\tstarty += ystep;\n\n\tTextButtonClass exitbtn(BUTTON_EXIT, TXT_EXIT_GAME, TPF_BUTTON,\n\t\td_exit_x, starty, d_exit_w, d_exit_h);\n\tstarty += ystep;\n\n\t/*\n\t**\tInitialize\n\t*/\n\tif (RequiredCD != -2) {\n\t\tRequiredCD = -1;\n\t\tForce_CD_Available(RequiredCD);\n\t}\n\tSet_Logic_Page(SeenBuff);\n\tKeyboard->Clear();\n\tstarttime = TickCount;\n\n\t/*\n\t**\tCreate the list\n\t*/\n\tcommands = &startbtn;\n#ifdef FIXIT_VERSION_3\n\tif( bExpansionCS )\n\t\texpandbtnCS.Add_Tail(*commands);\n\tif( bExpansionAM )\n\t\texpandbtnAM.Add_Tail(*commands);\n#else\n\tif (expansions) {\n\t\texpandbtn.Add_Tail(*commands);\n\t}\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - No internet play\n\tinternetbutton.Add_Tail(*commands);\n#endif\t//WIN32\n#endif\n//#if defined(MPEGMOVIE) // Denzil 6/26/98 Video settings\n//\tmoviebutton.Add_Tail(*commands);\n//#endif\n\tloadbtn.Add_Tail(*commands);\n\tmultibtn.Add_Tail(*commands);\n\tintrobtn.Add_Tail(*commands);\n\texitbtn.Add_Tail(*commands);\n\n\t/*\n\t**\tFill array of button ptrs\n\t*/\n#ifdef FIXIT_VERSION_3\n\tcurbutton = bExpansionCS ? 0 : ( bExpansionAM ? 1 : 2 );\n\n\tbuttons[0] = &expandbtnCS;\n\tbuttons[1] = &expandbtnAM;\n\tbuttons[2] = &startbtn;\n\tbuttons[3] = &loadbtn;\n\tbuttons[4] = &multibtn;\n\tbuttons[5] = &introbtn;\n\tbuttons[6] = &exitbtn;\n#else\n\tif (expansions) {\n\t\tcurbutton = 0;\n\t} else {\n\t\tcurbutton = 1;\n\t}\n\t\n\tbuttons[0] = &expandbtn;\n\tbuttons[1] = &startbtn;\n\tbuttons[2] = &internetbutton;\n\tbuttons[3] = &loadbtn;\n\tbuttons[4] = &multibtn;\n\tbuttons[5] = &introbtn;\n\tbuttons[6] = &exitbtn;\n#endif\n\n\tbuttons[curbutton]->Turn_On();\n\n\tKeyboard->Clear();\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tTBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\tfixed oldvolume = Options.ScoreVolume;\n\tif (oldvolume == 0) {\n\t\tOptions.Set_Score_Volume(fixed(4, 10), false);\n\t}\n\tTheme.Play_Song(THEME_INTRO);\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = true;\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tIf timeout expires, bail\n\t\t*/\n//\t\tif (timeout && TickCount - starttime > timeout) {\n//\t\t\tretval = -1;\n//\t\t\tprocess = false;\n//\t\t}\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\n\t\t\t/*\n\t\t\t**\tLoad the background picture.\n\t\t\t*/\n\t\t\tLoad_Title_Page();\n\t\t\tCCPalette.Set();\n\n\t\t\t/*\n\t\t\t**\tDisplay the title and text overlay for the menu.\n\t\t\t*/\n\t\t\tSet_Logic_Page(HidPage);\n//\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n//\t\t\tDraw_Caption (TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);\n\t\t\tcommands->Draw_All();\n#ifdef FIXIT_VERSION_3\n\t\t\tFancy_Text_Print(\"V%s\", d_dialog_x+d_dialog_w- (18 * RESFACTOR),\n\t\t\t\td_dialog_y+d_dialog_h-(5 * RESFACTOR), GadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\tTPF_EFNT|TPF_NOSHADOW|TPF_RIGHT,\n\t\t\t\tVersion_Name());\n#else\n#ifndef WIN32\n\t\t\tFancy_Text_Print(\"V%s\", d_dialog_x+d_dialog_w- (18 * RESFACTOR),\n\t\t\t\td_dialog_y+d_dialog_h-(8  * RESFACTOR), GadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\tTPF_EFNT|TPF_NOSHADOW|TPF_RIGHT,\n\t\t\t\tVersion_Name());\n\n#else\n\t\t\tFancy_Text_Print(\"V%s\", d_dialog_x+d_dialog_w- (18 * RESFACTOR),\n\t\t\t\td_dialog_y+d_dialog_h-(11 * RESFACTOR), GadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\tTPF_EFNT|TPF_NOSHADOW|TPF_RIGHT,\n\t\t\t\tVersion_Name());\n\n#endif\n#endif\n\n\t\t\t/*\n\t\t\t**\tCopy the menu to the visible page.\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tHidPage.Blit(SeenPage);\n\t\t\tShow_Mouse();\n\n\t\t\tSet_Logic_Page(SeenBuff);\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet and process player input.\n\t\t*/\n\t\tinput = commands->Input();\n\n#ifndef FIXIT_VERSION_3\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - No Internet play\n\t\t/*\n\t\t** Check to see if WChat has told us to start playing an internet game\n\t\t*/\n\t\tif (DDEServer.Get_MPlayer_Game_Info()) {\n\t\t\tretval = BUTTON_INTERNET - BUTTON_EXPAND;\n\t\t\tprocess = false;\n\t\t\tinput = KN_NONE;\n\t\t}\n#endif\t//WIN32\n#endif\n\n\t\t/*\n\t\t**\tIf there is input, then take this opportunity to seed some bits\n\t\t**\tto the cryptographic random number generator.\n\t\t*/\n\t\tif (input != 0) {\n\t\t\t#ifdef WIN32\n\t\t\t\tSYSTEMTIME t;\n\t\t\t\tGetSystemTime(&t);\n\t\t\t\tCryptRandom.Seed_Byte(t.wMilliseconds);\n\t\t\t#else\n\t\t\t\tstruct timeb t;\n\t\t\t\tftime(&t);\n\t\t\t\tCryptRandom.Seed_Byte(t.millitm);\n\t\t\t#endif\n\t\t}\n\n\t\t/*\n\t\t**\tDispatch the input to be processed.\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_EXPAND | KN_BUTTON):\n\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n#ifdef FIXIT_VERSION_3\n\t\t\tcase (BUTTON_EXPAND_AM | KN_BUTTON):\n\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n#endif\n\n\t\t\tcase (BUTTON_START | KN_BUTTON):\n\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n#ifndef FIXIT_VERSION_3\n\t\t\t#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - Internet play\n\t\t\tcase (BUTTON_INTERNET | KN_BUTTON):\n\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\t\t\t#endif\t//WIN32\n#endif\n\n//\t\t\t#if defined(MPEGMOVIE)\n//\t\t\tcase (BUTTON_MOVIE | KN_BUTTON):\n//\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n//\t\t\t\tprocess = false;\n//\t\t\tbreak;\n//\t\t\t#endif\n\t\t\t\n\t\t\tcase (BUTTON_LOAD | KN_BUTTON):\n\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_MULTI | KN_BUTTON):\n\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_INTRO | KN_BUTTON):\n\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_EXIT | KN_BUTTON):\n\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n#if (0)\n\t\t\tcase KN_BACKSPACE:\n\t\t\t\tShow_Who_Was_Responsible ();\n\t\t\t\tdisplay = true;\n\t\t\t\tTheme.Play_Song(THEME_INTRO);\n\t\t\t\tbreak;\n#endif\t//(0)\n\t\t\tcase KN_UP:\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tcurbutton--;\n#ifdef FIXIT_VERSION_3\n\t\t\t\tswitch( curbutton )\n\t\t\t\t{\n\t\t\t\tcase -1:\n\t\t\t\t\tcurbutton = max_buttons - 1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0:\n\t\t\t\t\tif( !bExpansionCS )\n\t\t\t\t\t\tcurbutton = max_buttons - 1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tif( !bExpansionAM )\n\t\t\t\t\t{\n\t\t\t\t\t\tif( bExpansionCS )\n\t\t\t\t\t\t\tcurbutton = 0;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tcurbutton = max_buttons - 1;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n#else\n\t\t\t\tif (expansions) {\n\t\t\t\t\tif (curbutton < 0) {\n\t\t\t\t\t\tcurbutton = max_buttons-1;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (curbutton < 1) {\n\t\t\t\t\t\tcurbutton = max_buttons-1;\n\t\t\t\t\t}\n\t\t\t\t}\n#endif\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase KN_DOWN:\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tcurbutton++;\n#ifdef FIXIT_VERSION_3\n\t\t\t\tif( curbutton == max_buttons )\n\t\t\t\t{\n\t\t\t\t\tif( bExpansionCS )\n\t\t\t\t\t\tcurbutton = 0;\n\t\t\t\t\telse if( bExpansionAM )\n\t\t\t\t\t\tcurbutton = 1;\n\t\t\t\t\telse\n\t\t\t\t\t\tcurbutton = 2;\n\t\t\t\t}\n\t\t\t\telse if( curbutton == 1 && !bExpansionAM )\n\t\t\t\t\tcurbutton = 2;\n#else\n\t\t\t\tif (curbutton > (max_buttons - 1)) {\n\t\t\t\t\tif (expansions) {\n\t\t\t\t\t\tcurbutton = 0;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcurbutton = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n#endif\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase KN_RETURN:\n\t\t\t\tbuttons[curbutton]->IsPressed = true;\n\t\t\t\tbuttons[curbutton]->Draw_Me(true);\n\t\t\t\tretval = curbutton;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\n\n\t\t\tcase KN_LMOUSE:\n\t\t\t\tif (Coordinates_In_Region(Keyboard->MouseQX, Keyboard->MouseQY,\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t9*RESFACTOR, 10*RESFACTOR,\n\t\t\t\t\t\t\t\t\t\t\t\t\t79*RESFACTOR, 24*RESFACTOR)){\n\t\t\t\t\tShow_Who_Was_Responsible();\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tTheme.Play_Song(THEME_INTRO);\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n#ifdef FIXIT_ANTS\n\t\t\t#ifdef FIXIT_PATCH_108\n\t\t\tif (Is_Counterstrike_Installed() == true)\n\t\t\t\t{\n\t\t\t#endif\n\t\t\t\tif ((Keyboard->Down(KN_LSHIFT) || Keyboard->Down(KN_RSHIFT)) && Coordinates_In_Region(Keyboard->MouseQX, Keyboard->MouseQY, 260*RESFACTOR, 0, 320*RESFACTOR, 50*RESFACTOR))  {\n\t\t\t\t\tAntsEnabled = true;\n\t\t\t\t\tprocess = false;\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\tretval = 2;\t\t//\tTo match SEL_START_NEW_GAME\n#else\n\t\t\t\t\tretval = 1;\n#endif\n\t\t\t\t}\n\t\t\t#ifdef FIXIT_PATCH_108\n\t\t\t}\n\t\t\t#endif\n#endif\n\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tOptions.Set_Score_Volume(oldvolume, false);\n\n\treturn(retval);\n}\n"
  },
  {
    "path": "CODE/MESSAGE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#define MESSAGE_NONE             \t0  \t// \n#define MESSAGE_BUILD_WINDTRAP   \t1  \t// You must build a Windtrap\n#define MESSAGE_STRUCT_CONCRETE  \t2  \t// Concrete: Use concrete to\n#define MESSAGE_STRUCT_PALACE    \t3  \t// Palace: This is your\n#define MESSAGE_STRUCT_LIGHT     \t4  \t// Light Factory: The Light\n#define MESSAGE_STRUCT_HEAVY     \t5  \t// Heavy Factory: The Heavy\n#define MESSAGE_STRUCT_HITECH    \t6  \t// Hi-Tech Factory: The\n#define MESSAGE_STRUCT_IX        \t7  \t// House IX: The IX Research\n#define MESSAGE_STRUCT_WOR       \t8  \t// WOR: Wor is used to train\n#define MESSAGE_STRUCT_CONST     \t9  \t// Construction Facility: All\n#define MESSAGE_STRUCT_WINDTRAP  \t10 \t// Windtrap: The windtrap\n#define MESSAGE_STRUCT_BARRACKS  \t11 \t// Barracks: The Barracks is\n#define MESSAGE_STRUCT_STARPORT  \t12 \t// Startport: The Starport is\n#define MESSAGE_STRUCT_REFINERY  \t13 \t// Spice Refinery: The\n#define MESSAGE_STRUCT_REPAIR    \t14 \t// Repair Facility: The Repair\n#define MESSAGE_STRUCT_WALL      \t15 \t// Wall: The wall is used for\n#define MESSAGE_STRUCT_TURRET    \t16 \t// Gun Turret: The cannon\n#define MESSAGE_STRUCT_RTURRET   \t17 \t// Rocket Turret: The\n#define MESSAGE_STRUCT_SILO      \t18 \t// Spice Silo: The Spice silo\n#define MESSAGE_STRUCT_OUTPOST   \t19 \t// Outpost: The Outpost\n#define MESSAGE_NEED_CONCRETE    \t20 \t// There isn't enough open\n#define MESSAGE_SAND             \t21 \t// Sand: This is sand terrain.\n#define MESSAGE_DUNE             \t22 \t// Sand Dunes: These are an\n#define MESSAGE_ROCK             \t23 \t// Rock: This is rock terrain.\n#define MESSAGE_MOUNT            \t24 \t// Mountain: Mountains on\n#define MESSAGE_SPICE            \t25 \t// Spice Field: This is the\n#define MESSAGE_ADJACENT         \t26 \t// Structures must be placed\n#define MESSAGE_SEARCH4SPICE     \t27 \t// Search for spice fields to\n#define MESSAGE_SANDWORM         \t28 \t// Warning: Sandworms\n"
  },
  {
    "path": "CODE/MISSION.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MISSION.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MISSION.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : September 14, 1996 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   MissionClass::AI -- Processes order script.                                               *\n *   MissionClass::Assign_Mission -- Give an order to a unit.                                  *\n *   MissionClass::Commence -- Start script with new order.                                    *\n *   MissionClass::Debug_Dump -- Dumps status values to mono screen.                           *\n *   MissionClass::Get_Mission -- Fetches the mission that this object is acting under.        *\n *   MissionClass::MissionClass -- Default constructor for the mission object type.            *\n *   MissionClass::Mission_???  -- Stub mission functions that do nothing.                     *\n *   MissionClass::Mission_From_Name -- Fetch order pointer from its name.                     *\n *   MissionClass::Mission_Name -- Converts a mission number into an ASCII string.             *\n *   MissionClass::Override_Mission -- temporarily overrides the units mission                 *\n *   MissionClass::Restore_Mission -- Restores overridden mission                              *\n *   MissionClass::Set_Mission -- Sets the mission to the specified value.                     *\n *   MissionClass::Is_Recruitable_Mission -- Determines if this mission is recruitable for a te*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * MissionClass::MissionClass -- Default constructor for the mission object type.              *\n *                                                                                             *\n *    This is the default constructor for the mission class object. It sets the mission        *\n *    handler into a default -- do nothing -- state.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *   03/01/1996 JLB : Uses initializer lists.                                                  *\n *=============================================================================================*/\nMissionClass::MissionClass(RTTIType rtti, int id) :\n\tObjectClass(rtti, id),\n\tMission(MISSION_NONE),\n\tSuspendedMission(MISSION_NONE),\n\tMissionQueue(MISSION_NONE),\n\tStatus(0),\n\tTimer(0)\n{\n}\n\n\n/***********************************************************************************************\n * MissionClass::Mission_???  -- Stub mission functions that do nothing.                       *\n *                                                                                             *\n *    These are the stub routines that handle the mission logic. They do nothing at this       *\n *    level. Derived classes will override these routine as necessary.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this mission        *\n *          handler again.                                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint MissionClass::Mission_Sleep(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Ambush(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Attack(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Capture(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Guard(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Guard_Area(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Harvest(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Hunt(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Move(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Retreat(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Return(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Stop(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Unload(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Enter(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Construction(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Deconstruction(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Repair(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Missile(void) {return TICKS_PER_SECOND*30;};\n\n\n/***********************************************************************************************\n * MissionClass::Set_Mission -- Sets the mission to the specified value.                       *\n *                                                                                             *\n *    Use this routine to set the current mission for this object. This routine will blast     *\n *    over the current mission, bypassing the queue method. Call it when the mission needs     *\n *    to be changed immediately.                                                               *\n *                                                                                             *\n * INPUT:   mission  -- The mission to set to.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MissionClass::Set_Mission(MissionType mission)\n{\n\tassert(IsActive);\n\n\tMission = mission;\n\tMissionQueue = MISSION_NONE;\n}\n\n\n/***********************************************************************************************\n * MissionClass::Get_Mission -- Fetches the mission that this object is acting under.          *\n *                                                                                             *\n *    Use this routine to fetch the mission that this object is CURRENTLY acting under. The    *\n *    mission queue may be filled with a imminent mission change, but this routine does not    *\n *    consider that. It only returns the CURRENT mission.                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the mission that this unit is currently following.                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nMissionType MissionClass::Get_Mission(void) const\n{\n\tassert(IsActive);\n\n\treturn(Mission == MISSION_NONE ? MissionQueue : Mission);\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * MissionClass::Debug_Dump -- Dumps status values to mono screen.                             *\n *                                                                                             *\n *    This is a debugging function that dumps this class' status to the monochrome screen      *\n *    for review.                                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MissionClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(IsActive);\n\n\tmono->Set_Cursor(1, 9);mono->Printf(\"%-14s\", MissionClass::Mission_Name(Mission));\n\tmono->Set_Cursor(16, 9);mono->Printf(\"%-12s\", MissionClass::Mission_Name(MissionQueue));\n\tmono->Set_Cursor(1, 7);mono->Printf(\"%3d\", (long)Timer);\n\tmono->Set_Cursor(6, 7);mono->Printf(\"%2d\", Status);\n\n\tObjectClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * MissionClass::AI -- Processes order script.                                                 *\n *                                                                                             *\n *    This routine will process the order script for as much time as                           *\n *    possible or until a script delay is detected. This routine should                        *\n *    be called for every unit once per game loop (if possible).                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/23/1994 JLB : Created.                                                                 *\n *   06/25/1995 JLB : Added new missions.                                                      *\n *=============================================================================================*/\nvoid MissionClass::AI(void)\n{\n\tassert(IsActive);\n\n\tObjectClass::AI();\n\n\t/*\n\t**\tIf this is the kind of object that is \"paralyzed with fear\" while it is above\n\t**\tground level (such as when be paradropped), it will perform no mission AI\n\t**\tprocessing.\n\t*/\n\tif ((What_Am_I() == RTTI_INFANTRY || What_Am_I() == RTTI_UNIT || What_Am_I() == RTTI_VESSEL) && Height > 0) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tThis is the script AI equivalent processing.\n\t*/\n\tBStart(BENCH_MISSION);\n\tif (Timer == 0 && Strength > 0) {\n\t\tswitch (Mission) {\n\t\t\tdefault:\n\t\t\t\tTimer = Mission_Sleep();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_HARMLESS:\n\t\t\tcase MISSION_SLEEP:\n\t\t\t\tTimer = Mission_Sleep();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_STICKY:\n\t\t\tcase MISSION_GUARD:\n\t\t\t\tTimer = Mission_Guard();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_ENTER:\n\t\t\t\tTimer = Mission_Enter();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_CONSTRUCTION:\n\t\t\t\tTimer = Mission_Construction();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_DECONSTRUCTION:\n\t\t\t\tTimer = Mission_Deconstruction();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_CAPTURE:\n\t\t\tcase MISSION_SABOTAGE:\n\t\t\t\tTimer = Mission_Capture();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_QMOVE:\n\t\t\tcase MISSION_MOVE:\n\t\t\t\tTimer = Mission_Move();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_ATTACK:\n\t\t\t\tTimer = Mission_Attack();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_RETREAT:\n\t\t\t\tTimer = Mission_Retreat();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_HARVEST:\n\t\t\t\tTimer = Mission_Harvest();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_GUARD_AREA:\n\t\t\t\tTimer = Mission_Guard_Area();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_RETURN:\n\t\t\t\tTimer = Mission_Return();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_STOP:\n\t\t\t\tTimer = Mission_Stop();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_AMBUSH:\n\t\t\t\tTimer = Mission_Ambush();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_HUNT:\n\t\t\tcase MISSION_RESCUE:\n\t\t\t\tTimer = Mission_Hunt();\n\t\t\t\tbreak;\n\n//\t\t\tcase MISSION_TIMED_HUNT:\n//\t\t\t\tTimer = Mission_Timed_Hunt();\n//\t\t\t\tbreak;\n\n\t\t\tcase MISSION_UNLOAD:\n\t\t\t\tTimer = Mission_Unload();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_REPAIR:\n\t\t\t\tTimer = Mission_Repair();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_MISSILE:\n\t\t\t\tTimer = Mission_Missile();\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tBEnd(BENCH_MISSION);\n}\n\n\n/***********************************************************************************************\n * MissionClass::Commence -- Start script with new order.                                      *\n *                                                                                             *\n *    This routine will start script processing according to any queued                        *\n *    order it may have. If there is no queued order, then this routine                        *\n *    does nothing. Call this routine whenever the unit is in a good                           *\n *    position to change its order (such as when it is stopped).                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Did the mission actually change?                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/23/1994 JLB : Created.                                                                 *\n *   07/14/1994 JLB : Simplified.                                                              *\n *   06/17/1995 JLB : Returns success flag.                                                    *\n *=============================================================================================*/\nbool MissionClass::Commence(void)\n{\n\tassert(IsActive);\n\n\tif (MissionQueue != MISSION_NONE) {\n\t\tMission = MissionQueue;\n\t\tMissionQueue = MISSION_NONE;\n\n\t\t/*\n\t\t**\tForce immediate state machine processing at the first state machine state value.\n\t\t*/\n\t\tTimer = 0;\n\t\tStatus = 0;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MissionClass::Assign_Mission -- Give an order to a unit.                                    *\n *                                                                                             *\n *    This routine will assign the specified mission to the mission queue for this object.     *\n *    The actual mission logic will then be performed at the first available and legal         *\n *    opportunity.                                                                             *\n *                                                                                             *\n * INPUT:   order -- Mission to give the unit.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1991 JLB : Created.                                                                 *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nvoid MissionClass::Assign_Mission(MissionType order)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tEnsure that a MISSION_QMOVE is translated into a MISSION_MOVE.\n\t*/\n\tif (order == MISSION_QMOVE) order = MISSION_MOVE;\n\n\tif (order != MISSION_NONE && Mission != order)  {\n\t\tMissionQueue = order;\n\t}\n}\n\n\n/***********************************************************************************************\n * MissionClass::Mission_From_Name -- Fetch order pointer from its name.                       *\n *                                                                                             *\n *    This routine is used to convert an ASCII order name into the actual                      *\n *    order number it represents. Typically, this is used when processing                      *\n *    a scenario INI file.                                                                     *\n *                                                                                             *\n * INPUT:   name  -- The ASCII order name to process.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the actual order number that the ASCII name                           *\n *          represents.                                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *   04/22/1994 JLB : Converted to static member function.                                     *\n *=============================================================================================*/\nMissionType MissionClass::Mission_From_Name(char const * name)\n{\n\tMissionType\torder;\n\n\tif (name) {\n\t\tfor (order = MISSION_FIRST; order < MISSION_COUNT; order++) {\n\t\t\tif (stricmp(Missions[order], name) == 0) {\n\t\t\t\treturn(order);\n\t\t\t}\n\t\t}\n\t}\n\treturn(MISSION_NONE);\n}\n\n\n/***********************************************************************************************\n * MissionClass::Mission_Name -- Converts a mission number into an ASCII string.               *\n *                                                                                             *\n *    Use this routine to convert a mission number into the ASCII string that represents       *\n *    it. Typical use of this is when generating an INI file.                                  *\n *                                                                                             *\n * INPUT:   mission  -- The mission number to convert.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the ASCII string that represents the mission type.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * MissionClass::Mission_Name(MissionType mission)\n{\n\tif (mission != MISSION_NONE)  {\n\t\treturn(Missions[mission]);\n\t}\n\treturn(\"None\");\n}\n\n\n/***********************************************************************************************\n * MissionClass::Override_Mission -- temporarily overrides the units mission                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:      MissionType mission - the mission we want to override                           *\n *               TARGET      tarcom  - the new target we want to override                      *\n *               TARGET      navcom  - the new navigation point to override                    *\n *                                                                                             *\n * OUTPUT:      none                                                                           *\n *                                                                                             *\n * WARNINGS:   If a mission is already overridden, the current mission is                      *\n *               just re-assigned.                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/28/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid MissionClass::Override_Mission(MissionType mission, TARGET, TARGET)\n{\n\tassert(IsActive);\n\n\tif (MissionQueue != MISSION_NONE) {\n\t\tSuspendedMission = MissionQueue;\n\t} else {\n\t\tSuspendedMission = Mission;\n\t}\n\n\tAssign_Mission(mission);\n}\n\n\n/***********************************************************************************************\n * MissionClass::Restore_Mission -- Restores overridden mission                                *\n *                                                                                             *\n * INPUT:      none                                                                            *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/28/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nbool MissionClass::Restore_Mission(void)\n{\n\tassert(IsActive);\n\n\tif (SuspendedMission != MISSION_NONE) {\n\t\tAssign_Mission(SuspendedMission);\n\t \tSuspendedMission= MISSION_NONE;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MissionClass::Is_Recruitable_Mission -- Determines if this mission is recruitable for a tea *\n *                                                                                             *\n *    Some missions preclude recruitment into a team. This routine will examine the mission    *\n *    specified and if not allowed for a team, it will return false.                           *\n *                                                                                             *\n * INPUT:   mission  -- The mission type to examine.                                           *\n *                                                                                             *\n * OUTPUT:  bool; Is an object following this mission allowed to be recruited into a team?     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool MissionClass::Is_Recruitable_Mission(MissionType mission) const\n{\n\tif (mission == MISSION_NONE) {\n\t\treturn(true);\n\t}\n\treturn(MissionControl[mission].IsRecruitable);\n}\n\n\n\nMissionControlClass::MissionControlClass(void) :\n\tMission(MISSION_NONE),\n\tIsNoThreat(false),\n\tIsZombie(false),\n\tIsRecruitable(true),\n\tIsParalyzed(false),\n\tIsRetaliate(true),\n\tIsScatter(true),\n\tRate(\".016\"),\n\tAARate(\".016\")\n{\n}\n\n\nchar const * MissionControlClass::Name(void) const\n{\n\tif (Mission == MISSION_NONE) {\n\t\treturn(\"<none>\");\n\t}\n\treturn(Missions[Mission]);\n}\n\n\n\nbool MissionControlClass::Read_INI(CCINIClass & ini)\n{\n\tif (ini.Is_Present(Name())) {\n\t\tIsNoThreat = ini.Get_Bool(Name(), \"NoThreat\", IsNoThreat);\n\t\tIsZombie = ini.Get_Bool(Name(), \"Zombie\", IsZombie);\n\t\tIsRecruitable = ini.Get_Bool(Name(), \"Recruitable\", IsRecruitable);\n\t\tIsParalyzed = ini.Get_Bool(Name(), \"Paralyzed\", IsParalyzed);\n\t\tIsRetaliate = ini.Get_Bool(Name(), \"Retaliate\", IsRetaliate);\n\t\tIsScatter = ini.Get_Bool(Name(), \"Scatter\", IsScatter);\n\t\tRate = ini.Get_Fixed(Name(), \"Rate\", Rate);\n\t\tAARate = ini.Get_Fixed(Name(), \"AARate\", 0);\n\t\tif (AARate == 0) {\n\t\t\tAARate = Rate;\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "CODE/MISSION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MISSION.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MISSION.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 23, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MISSION_H\n#define MISSION_H\n\n#include \"object.h\"\n#include\t\"monoc.h\"\n\n/****************************************************************************\n**\tThis handles order assignment and tracking. The order is used to guide\n**\toverall AI processing.\n*/\nclass MissionClass : public ObjectClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tThis the tactical strategy to use. It is used by the unit script. This\n\t\t**\tis a general guide for unit AI processing.\n\t\t*/\n\t\tMissionType Mission;\n\t\tMissionType SuspendedMission;\n\n\t\t/*\n\t\t**\tThe order queue is used for orders that should take effect when the vehicle\n\t\t**\thas reached the center point of a cell. The queued order number is +1 when stored here\n\t\t**\tso that 0 will indicated there is no queued order.\n\t\t*/\n\t\tMissionType MissionQueue;\n\n\t\tint Status;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tMissionClass(RTTIType rtti, int id);\n\t\tMissionClass(NoInitClass const & x) : ObjectClass(x), Timer(x) {};\n\t\tvirtual ~MissionClass(void) {};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvoid  Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\n\t\tvoid Shorten_Mission_Timer(void) {Timer = 0;}\n\t\tvirtual MissionType Get_Mission(void) const;\n\t\tvirtual void  Assign_Mission(MissionType mission);\n\t\tvirtual bool Commence(void);\n\t\tvirtual void AI(void);\n\n\t\t/*\n\t\t**\tSupport functions.\n\t\t*/\n\t\tvirtual int Mission_Sleep(void);\n\t\tvirtual int Mission_Ambush(void);\n\t\tvirtual int Mission_Attack(void);\n\t\tvirtual int Mission_Capture(void);\n\t\tvirtual int Mission_Guard(void);\n\t\tvirtual int Mission_Guard_Area(void);\n\t\tvirtual int Mission_Harvest(void);\n\t\tvirtual int Mission_Hunt(void);\n//\t\tvirtual int Mission_Timed_Hunt(void);\n\t\tvirtual int Mission_Move(void);\n\t\tvirtual int Mission_Retreat(void);\n\t\tvirtual int Mission_Return(void);\n\t\tvirtual int Mission_Stop(void);\n\t\tvirtual int Mission_Unload(void);\n\t\tvirtual int Mission_Enter(void);\n\t\tvirtual int Mission_Construction(void);\n\t\tvirtual int Mission_Deconstruction(void);\n\t\tvirtual int Mission_Repair(void);\n\t\tvirtual int Mission_Missile(void);\n\t\tvirtual void  Set_Mission(MissionType mission);\n\t\tstatic bool Is_Recruitable_Mission(MissionType mission);\n\n\t\tstatic char const *  Mission_Name(MissionType order);\n\t\tstatic MissionType  Mission_From_Name(char const *name);\n\t\tvirtual void  Override_Mission(MissionType mission, TARGET, TARGET);\n\t\tvirtual bool Restore_Mission(void);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis the thread processing timer. When this value counts down to zero, then\n\t\t**\tmore script processing may occur.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> Timer;\n};\n\n\n/****************************************************************************\n**\tThis is the mission control (pun) that controls how each mission behaves\n**\twhen it comes to interacting with the game world. Example; some\n**\tmissions allow the object to scatter from threats, while others require\n**\tthe object to remain in place. This kind of characteristics are specfied\n**\tby this class.\n*/\nclass MissionControlClass\n{\n\tpublic:\n\t\tMissionControlClass(void);\n\n\t\tbool Read_INI(CCINIClass & ini);\n\t\tint Normal_Delay(void) const {return(TICKS_PER_MINUTE * Rate);}\n\t\tint AA_Delay(void) const {return(TICKS_PER_MINUTE * AARate);}\n\n\t\t/*\n\t\t**\tThis is the mission identifier that this mission represents.\n\t\t*/\n\t\tMissionType Mission;\n\n\t\tchar const * Name(void) const;\n\n\t\t/*\n\t\t**\tIf the object should not be considered a threat when it\n\t\t**\tcomes to target scanning, then this will be true.\n\t\t*/\n\t\tunsigned IsNoThreat:1;\n\n\t\t/*\n\t\t**\tIf objects in this mission should avoid targeting the enemy and\n\t\t**\talso avoid responding to the enemy, then this will be true.\n\t\t*/\n\t\tunsigned IsZombie:1;\n\n\t\t/*\n\t\t**\tAn ojbect that can be recruited into a team must be on a mission\n\t\t**\tof this type.\n\t\t*/\n\t\tunsigned IsRecruitable:1;\n\n\t\t/*\n\t\t**\tIf the object can behave normally except that it cannot\n\t\t**\tmove to another location, then this flag will be true.\n\t\t*/\n\t\tunsigned IsParalyzed:1;\n\n\t\t/*\n\t\t**\tIf an object on this mission is damaged, it is allowed to\n\t\t**\tretaliate?\n\t\t*/\n\t\tunsigned IsRetaliate:1;\n\n\t\t/*\n\t\t**\tIs the object allowed to scatter from immediate threats?\n\t\t*/\n\t\tunsigned IsScatter:1;\n\n\t\t/*\n\t\t**\tThis specifies the time to delay between calls to the mission handler for those cases\n\t\t**\twhere the delay could be indefinate. The exception would be when timing is critical.\n\t\t**\tTypical use of this would be to regulate the delay between mundane mission processing\n\t\t**\tin order to achieve less game overhead.\n\t\t*/\n\t\tfixed Rate;\n\n\t\t/*\n\t\t**\tAnti-Aircraft buildings (and units) in guard or guard area mode will use this override\n\t\t**\tdelay interval instead of the normal \"Rate\" value.\n\t\t*/\n\t\tfixed AARate;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/MIXFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MIXFILE.CPP 2     3/13/97 2:06p Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MIXFILE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : July 12, 1996 [JLB]                                          *\n *                                                                                             *\n *                                                                                             *\n *                  Modified by Vic Grippi for WwXlat Tool 10/14/96                            *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   MixFileClass::Cache -- Caches the named mixfile into RAM.                                 *\n *   MixFileClass::Cache -- Loads this particular mixfile's data into RAM.                     *\n *   MixFileClass::Finder -- Finds the mixfile object that matches the name specified.         *\n *   MixFileClass::Free -- Uncaches a cached mixfile.                                          *\n *   MixFileClass::MixFileClass -- Constructor for mixfile object.                             *\n *   MixFileClass::Offset -- Searches in mixfile for matching file and returns offset if found.*\n *   MixFileClass::Retrieve -- Retrieves a pointer to the specified data file.                 *\n *   MixFileClass::~MixFileClass -- Destructor for the mixfile object.                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"buff.h\"\n#include\t\"function.h\"\n#include\t<direct.h>\n#include\t<fcntl.h>\n#include\t<io.h>\n#include\t<dos.h>\n#include\t<errno.h>\n#include\t<share.h>\n#include\t\"mixfile.h\"\n\n#include\t\"cdfile.h\"\nextern MFCD temp;\n\n\n//template<class T> int Compare(T const *obj1, T const *obj2) {\n//\tif (*obj1 < *obj2) return(-1);\n//\tif (*obj1 > *obj2) return(1);\n//\treturn(0);\n//};\n\n\n/*\n**\tThis is the pointer to the first mixfile in the list of mixfiles registered\n**\twith the mixfile system.\n*/\ntemplate<class T>\nList<MixFileClass<T> > MixFileClass<T>::List;\n\n\n/***********************************************************************************************\n * MixFileClass::Free -- Uncaches a cached mixfile.                                            *\n *                                                                                             *\n *    Use this routine to uncache a mixfile that has been cached.                              *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the filename of the mixfile that is to be uncached.         *\n *                                                                                             *\n * OUTPUT:  bool; Was the mixfile found and freed?                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool MixFileClass<T>::Free(char const * filename)\n{\n\tMixFileClass * ptr = Finder(filename);\n\n\tif (ptr) {\n\t\tptr->Free();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MixFileClass::~MixFileClass -- Destructor for the mixfile object.                           *\n *                                                                                             *\n *    This destructor will free all memory allocated by this mixfile and will remove it from   *\n *    the system. A mixfile removed in this fashion must be created anew in order to be        *\n *    subsequent used.                                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *   01/06/1995 JLB : Puts mixfile header table into EMS.                                      *\n *=============================================================================================*/\ntemplate<class T>\nMixFileClass<T>::~MixFileClass(void)\n{\n\t/*\n\t**\tDeallocate any allocated memory.\n\t*/\n\tif (Filename) {\n\t\tfree((char *)Filename);\n\t}\n\tif (Data != NULL && IsAllocated) {\n\t\tdelete [] Data;\n\t\tIsAllocated = false;\n\t}\n\tData = NULL;\n\n\tif (HeaderBuffer != NULL) {\n\t\tdelete [] HeaderBuffer;\n\t\tHeaderBuffer = NULL;\n\t}\n\n\t/*\n\t**\tUnlink this mixfile object from the chain.\n\t*/\n\tUnlink();\n}\n\n\n/***********************************************************************************************\n * MixFileClass::MixFileClass -- Constructor for mixfile object.                               *\n *                                                                                             *\n *    This is the constructor for the mixfile object. It takes a filename and a memory         *\n *    handler object and registers the mixfile object with the system. The index block is      *\n *    allocated and loaded from disk by this routine.                                          *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the filename of the mixfile object.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *   07/12/1996 JLB : Handles compressed file header.                                          *\n *=============================================================================================*/\ntemplate<class T>\nMixFileClass<T>::MixFileClass(char const * filename, PKey const * key) :\n\tIsDigest(false),\n\tIsEncrypted(false),\n\tIsAllocated(false),\n\tFilename(0),\n\tCount(0),\n\tDataSize(0),\n\tDataStart(0),\n\tHeaderBuffer(0),\n\tData(0)\n{\n\t/*\n\t**\tCheck to see if the file is available. If it isn't, then\n\t**\tno further processing is needed or possible.\n\t*/\n\tif (!Force_CD_Available(RequiredCD)) {\n\t\t//Prog_End();\n\t\tEmergency_Exit(EXIT_FAILURE);\n\t}\n\n\tT file(filename);\t\t// Working file object.\n\tFilename = strdup(file.File_Name());\n\tFileStraw fstraw(file);\n\tPKStraw pstraw(PKStraw::DECRYPT, CryptRandom);\n\tStraw * straw = &fstraw;\n\n\tif (!file.Is_Available()) return;\n\n\t/*\n\t**\tStuctures used to hold the various file headers.\n\t*/\n\tFileHeader fileheader;\n\tstruct {\n\t\tshort First;\t\t// Always zero for extended mixfile format.\n\t\tshort Second;\t\t// Bitfield of extensions to this mixfile.\n\t} alternate;\n\n\t/*\n\t**\tFetch the first bit of the file. From this bit, it is possible to detect\n\t**\twhether this is an extended mixfile format or the plain format. An\n\t**\textended format may have extra options or data layout.\n\t*/\n\tint got = straw->Get(&alternate, sizeof(alternate));\n\n\t/*\n\t**\tDetect if this is an extended mixfile. If so, then see if it is encrypted\n\t**\tand/or has a message digest attached. Otherwise, just retrieve the\n\t**\tplain mixfile header.\n\t*/\n\tif (alternate.First == 0) {\n\t\tIsDigest = ((alternate.Second & 0x01) != 0);\n\t\tIsEncrypted = ((alternate.Second & 0x02) != 0);\n\n\t\tif (IsEncrypted) {\n\t\t\tpstraw.Key(key);\n\t\t\tpstraw.Get_From(&fstraw);\n\t\t\tstraw = &pstraw;\n\t\t}\n\t\tstraw->Get(&fileheader, sizeof(fileheader));\n\n\t} else {\n\t\tmemmove(&fileheader, &alternate, sizeof(alternate));\n\t\tstraw->Get(((char*)&fileheader)+sizeof(alternate), sizeof(fileheader)-sizeof(alternate));\n\t}\n\n\tCount = fileheader.count;\n\tDataSize = fileheader.size;\n//BGMono_Printf(\"Mixfileclass %s DataSize: %08x   \\n\",filename,DataSize);Get_Key();\n\t/*\n\t**\tLoad up the offset control array. If RAM is exhausted, then the mixfile is invalid.\n\t*/\n\tHeaderBuffer = new SubBlock [Count];\n\tif (HeaderBuffer == NULL) return;\n\tstraw->Get(HeaderBuffer, Count * sizeof(SubBlock));\n\n\t/*\n\t**\tThe start of the embedded mixfile data will be at the current file offset.\n\t**\tThis should be true even if the file header has been encrypted because the file\n\t**\theader was cleverly written with just the sufficient number of padding bytes so\n\t**\tthat this condition would be true.\n\t*/\n\tDataStart = file.Seek(0, SEEK_CUR) + file.BiasStart;\n//\tDataStart = file.Seek(0, SEEK_CUR);\n\n\t/*\n\t**\tAttach to list of mixfiles.\n\t*/\n\tList.Add_Tail(this);\n}\n\n\n/***********************************************************************************************\n * MixFileClass::Retrieve -- Retrieves a pointer to the specified data file.                   *\n *                                                                                             *\n *    This routine will return with a pointer to the specified data file if the file resides   *\n *    in memory. Otherwise, this routine returns NULL. Use this routine to access a resident   *\n *    file directly rather than going through the process of pseudo disk access. This will     *\n *    save both time and RAM.                                                                  *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the filename of the data file to retrieve a pointer to.     *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the data file's data. If the file is not in RAM, then    *\n *          NULL is returned.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid const * MixFileClass<T>::Retrieve(char const * filename)\n{\n\tvoid * ptr = 0;\n\tOffset(filename, &ptr);\n\treturn(ptr);\n};\n\n\n/***********************************************************************************************\n * MixFileClass::Finder -- Finds the mixfile object that matches the name specified.           *\n *                                                                                             *\n *    This routine will scan through all registered mixfiles and return with a pointer to      *\n *    the matching mixfile. If no mixfile could be found that matches the name specified,      *\n *    then NULL is returned.                                                                   *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the filename to search for.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the matching mixfile -- if found.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *   06/08/1996 JLB : Only compares filename and extension.                                    *\n *=============================================================================================*/\ntemplate<class T>\nMixFileClass<T> * MixFileClass<T>::Finder(char const * filename)\n{\n\tMixFileClass<T> * ptr = List.First();\n\twhile (ptr->Is_Valid()) {\n\t\tchar path[_MAX_PATH];\n\t\tchar name[_MAX_FNAME];\n\t\tchar ext[_MAX_EXT];\n\n\t\t/*\n\t\t**\tStrip the drive and path (if present) off of the filename\n\t\t**\tin the mixfile list. This enables a simple comparison to the\n\t\t**\tfilename specified. The filename specified won't have a path attached and\n\t\t**\tthe full pathname in the mixfile list WILL have a path attached. Hence, this\n\t\t** stripping of the path is necessary.\n\t\t*/\n\t\t_splitpath(ptr->Filename, NULL, NULL, name, ext);\n\t\t_makepath(path, NULL, NULL, name, ext);\n\n\t\tif (stricmp(path, filename) == 0) {\n\t\t\treturn(ptr);\n\t\t}\n\t\tptr = ptr->Next();\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * MixFileClass::Cache -- Caches the named mixfile into RAM.                                   *\n *                                                                                             *\n *    This routine will cache the mixfile, specified by name, into RAM.                        *\n *                                                                                             *\n * INPUT:   filename -- The name of the mixfile that should be cached.                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the cache successful?                                                    *\n *                                                                                             *\n * WARNINGS:   This routine could go to disk for a very long time.                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool MixFileClass<T>::Cache(char const * filename, Buffer const * buffer)\n{\n\tMixFileClass<T> * mixer = Finder(filename);\n\n\tif (mixer != NULL) {\n\t\treturn(mixer->Cache(buffer));\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MixFileClass::Cache -- Loads this particular mixfile's data into RAM.                       *\n *                                                                                             *\n *    This load the mixfile data into ram for this mixfile object. This is the counterpart     *\n *    to the Free() function.                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the file load successful?  It could fail if there wasn't enough room     *\n *                to allocate the raw data block.                                              *\n *                                                                                             *\n * WARNINGS:   This routine goes to disk for a potentially very long time.                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *   07/12/1996 JLB : Handles attached message digest.                                         *\n *=============================================================================================*/\ntemplate<class T>\nbool MixFileClass<T>::Cache(Buffer const * buffer)\n{\n\t/*\n\t**\tIf the mixfile is already cached, then no action needs to be performed.\n\t*/\n\tif (Data != NULL) return(true);\n\n\t/*\n\t**\tIf a buffer was supplied (and it is big enough), then use it as the data block\n\t**\tpointer. Otherwise, the data block must be allocated.\n\t*/\n\tif (buffer != NULL) {\n\t\tif (buffer->Get_Size() == 0 || buffer->Get_Size() >= DataSize) {\n\t\t\tData = buffer->Get_Buffer();\n\t\t}\n\t} else {\n\t\tData = new char [DataSize];\n\t\tIsAllocated = true;\n\t}\n\n\t/*\n\t**\tIf there is a data buffer to fill, then fill it now.\n\t*/\n\tif (Data != NULL) {\n\t\tT file(Filename);\n\n\t\tFileStraw fstraw(file);\n\t\tStraw * straw = &fstraw;\n\n\t\t/*\n\t\t**\tIf a message digest is attached, then link a SHA straw segment to the data\n\t\t**\tstream so that the actual SHA can be compared with the attached one.\n\t\t*/\n\t\tSHAStraw sha;\n\t\tif (IsDigest) {\n\t\t\tsha.Get_From(fstraw);\n\t\t\tstraw = &sha;\n\t\t}\n\n\t\t/*\n\t\t**\tBias the file to the actual start of the data. This is necessary because the\n\t\t**\treal data starts some distance (not so easily determined) from the beginning of\n\t\t**\tthe real file.\n\t\t*/\n\t\tfile.Open(READ);\n\t\tfile.Bias(0);\n\t\tfile.Bias(DataStart);\n\n\t\t/*\n\t\t**\tFetch the whole mixfile data in one step. If the number of bytes retrieved\n\t\t**\tdoes not equal that requested, then this indicates a serious error.\n\t\t*/\n\t\tlong actual = straw->Get(Data, DataSize);\n\t\tif (actual != DataSize) {\n\t\t\tdelete [] Data;\n\t\t\tData = NULL;\n\t\t\tfile.Error(EIO);\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is a digest attached to this mixfile, then read it in and\n\t\t**\tcompare it to the generated digest. If they don't match, then\n\t\t**\treturn with the \"failure to cache\" error code.\n\t\t*/\n\t\tif (IsDigest) {\n\t\t\tchar digest1[20];\n\t\t\tchar digest2[20];\n\t\t\tsha.Result(digest2);\n\t\t\tfstraw.Get(digest1, sizeof(digest1));\n\t\t\tif (memcmp(digest1, digest2, sizeof(digest1)) != 0) {\n\t\t\t\tdelete [] Data;\n\t\t\t\tData = NULL;\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t}\n\n\t\treturn(true);\n\t}\n\tIsAllocated = false;\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MixFileClass::Free -- Frees the allocated raw data block (not the index block).             *\n *                                                                                             *\n *    This routine will free the (presumably large) raw data block, but leave the index        *\n *    block intact. By using this in conjunction with the Cache() function, one can maintain   *\n *    tight control of memory usage. If the index block is desired to be freed, then the       *\n *    mixfile object must be deleted.                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid MixFileClass<T>::Free(void)\n{\n\tif (Data != NULL && IsAllocated) {\n\t\tdelete [] Data;\n\t}\n\tData = NULL;\n\tIsAllocated = false;\n}\n\n\nint compfunc(void const * ptr1, void const * ptr2)\n{\n\tif (*(long const *)ptr1 < *(long const *)ptr2) return(-1);\n\tif (*(long const *)ptr1 > *(long const *)ptr2) return(1);\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * MixFileClass::Offset -- Determines the offset of the requested file from the mixfile system.*\n *                                                                                             *\n *    This routine will take the filename specified and search through the mixfile system      *\n *    looking for it. If the file was found, then the mixfile it was found in, the offset      *\n *    from the start of the mixfile, and the size of the embedded file will be returned.       *\n *    Using this method it is possible for the CCFileClass system to process it as a normal    *\n *    file.                                                                                    *\n *                                                                                             *\n * INPUT:   filename    -- The filename to search for.                                         *\n *                                                                                             *\n *          realptr     -- Stores a pointer to the start of the file in memory here. If the    *\n *                         file is not in memory, then NULL is stored here.                    *\n *                                                                                             *\n *          mixfile     -- The pointer to the corresponding mixfile is placed here. If no      *\n *                         mixfile was found that contains the file, then NULL is stored here. *\n *                                                                                             *\n *          offset      -- The starting offset from the beginning of the parent mixfile is     *\n *                         stored here.                                                        *\n *                                                                                             *\n *          size        -- The size of the embedded file is stored here.                       *\n *                                                                                             *\n * OUTPUT:  bool; Was the file found? The file may or may not be resident, but it does exist   *\n *                 and can be opened.                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool MixFileClass<T>::Offset(char const * filename, void ** realptr, MixFileClass ** mixfile, long * offset, long * size) const\n{\n\tMixFileClass<T> * ptr;\n\n\tif (filename == NULL) {\nassert(filename != NULL);//BG\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tCreate the key block that will be used to binary search for the file.\n\t*/\n\tlong crc = Calculate_CRC(strupr((char *)filename), strlen(filename));\n\tSubBlock key;\n\tkey.CRC = crc;\n\n\t/*\n\t**\tSweep through all registered mixfiles, trying to find the file in question.\n\t*/\n\tptr = List.First();\n\twhile (ptr->Is_Valid()) {\n\t\tSubBlock * block;\n\n\t\t/*\n\t\t**\tBinary search for the file in this mixfile. If it is found, then extract the\n\t\t**\tappropriate information and store it in the locations provided and then return.\n\t\t*/\n\t\tblock = (SubBlock *)bsearch(&key, ptr->HeaderBuffer, ptr->Count, sizeof(SubBlock), compfunc);\n\t\tif (block != NULL) {\n\t\t\tif (mixfile != NULL) *mixfile = ptr;\n\t\t\tif (size != NULL) *size = block->Size;\n\t\t\tif (realptr != NULL) *realptr = NULL;\n\t\t\tif (offset != NULL) *offset = block->Offset;\n\t\t\tif (realptr != NULL && ptr->Data != NULL) {\n\t\t\t\t*realptr = (char *)ptr->Data + block->Offset;\n\t\t\t}\n\t\t\tif (ptr->Data == NULL && offset != NULL) {\n\t\t\t\t*offset += ptr->DataStart;\n\t\t\t}\n\t\t\treturn(true);\n\t\t}\n\n\t\t/*\n\t\t**\tAdvance to next mixfile.\n\t\t*/\n\t\tptr = ptr->Next();\n\t}\n\n\t/*\n\t**\tAll the mixfiles have been examined but no match was found. Return with the non success flag.\n\t*/\nassert(1);//BG\n\treturn(false);\n}\n\n"
  },
  {
    "path": "CODE/MIXFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MIXFILE.H 1     3/03/97 10:25a Joe_bostic $ */\n\n#ifndef MIXFILE_H\n#define MIXFILE_H\n\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n#include\t<stdlib.h>\n#include\t\"listnode.h\"\n#include\t\"pk.h\"\n#include \"buff.h\"\n\ntemplate<class T>\nclass MixFileClass : public Node<MixFileClass>\n{\n\tpublic:\n\t\tchar const * Filename;\t\t\t// Filename of mixfile.\n\n\n\t\tMixFileClass(char const *filename, PKey const * key);\n\t\t~MixFileClass(void);\n\n\t\tstatic bool Free(char const *filename);\n\t\tvoid Free(void);\n\t\tbool Cache(Buffer const * buffer = NULL);\n\t\tstatic bool Cache(char const *filename, Buffer const * buffer=NULL);\n\t\tstatic bool Offset(char const *filename, void ** realptr = 0, MixFileClass ** mixfile = 0, long * offset = 0, long * size = 0);\n\t\tstatic void const * Retrieve(char const *filename);\n\n\t\tstruct SubBlock {\n\t\t\tlong CRC;\t\t\t\t// CRC code for embedded file.\n\t\t\tlong Offset;\t\t\t// Offset from start of data section.\n\t\t\tlong Size;\t\t\t\t// Size of data subfile.\n\n\t\t\tint operator < (SubBlock & two) const {return (CRC < two.CRC);};\n\t\t\tint operator > (SubBlock & two) const {return (CRC > two.CRC);};\n\t\t\tint operator == (SubBlock & two) const {return (CRC == two.CRC);};\n\t\t};\n\n\tprivate:\n\t\tstatic MixFileClass * Finder(char const * filename);\n\t\tlong Offset(long crc, long * size = 0) const;\n\n\t\t/*\n\t\t**\tIf this mixfile has an attached message digest, then this flag\n\t\t**\twill be true. The digest is checked only when the mixfile is\n\t\t**\tcached.\n\t\t*/\n\t\tunsigned IsDigest:1;\n\n\t\t/*\n\t\t**\tIf the header to this mixfile has been encrypted, then this flag\n\t\t**\twill be true. Although the header of the mixfile may be encrypted,\n\t\t**\tthe attached data files are not.\n\t\t*/\n\t\tunsigned IsEncrypted:1;\n\n\t\t/*\n\t\t**\tIf the cached memory block was allocated by this routine, then this\n\t\t**\tflag will be true.\n\t\t*/\n\t\tunsigned IsAllocated:1;\n\n\t\t/*\n\t\t**\tThis is the initial file header. It tells how many files are embedded\n\t\t**\twithin this mixfile and the total size of all embedded files.\n\t\t*/\n\t\ttypedef struct {\n\t\t\tshort\tcount;\n\t\t\tlong\tsize;\n\t\t} FileHeader;\n\n\t\t/*\n\t\t**\tThe number of files within the mixfile.\n\t\t*/\n\t\tint Count;\n\n\t\t/*\n\t\t**\tThis is the total size of all the data file embedded within the mixfile.\n\t\t**\tIt does not include the header or digest bytes.\n\t\t*/\n\t\tlong DataSize;\n\n\t\t/*\n\t\t**\tStart of raw data in within the mixfile.\n\t\t*/\n\t\tlong DataStart;\n\n\t\t/*\n\t\t**\tPoints to the file header control block array. Each file in the mixfile will\n\t\t**\thave an entry in this table. The entries are sorted by their (signed) CRC value.\n\t\t*/\n\t\tSubBlock * HeaderBuffer;\n\n\t\t/*\n\t\t**\tIf the mixfile has been cached, then this points to the cached data.\n\t\t*/\n\t\tvoid * Data;\t\t\t\t\t\t// Pointer to raw data.\n\n\t\tstatic List<MixFileClass> List;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/MONOC.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MONOC.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MONO.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 2, 1994                                                 *\n *                                                                                             *\n *                  Last Update : June 5, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   MonoClass::Clear -- Clears the monochrome screen object.                                  *\n *   MonoClass::Draw_Box -- Draws a box using the IBM linedraw characters.                     *\n *   MonoClass::Fill_Attrib -- Fill a block with specified attribute.                          *\n *   MonoClass::MonoClass -- The default constructor for monochrome screen object.             *\n *   MonoClass::Pan -- Scroll the window right or left.                                        *\n *   MonoClass::Print -- Prints the text string at the current cursor coordinates.             *\n *   MonoClass::Print -- Simple print of text number.                                          *\n *   MonoClass::Printf -- Prints a formatted string to the monochrome screen.                  *\n *   MonoClass::Printf -- Prints formatted text using text string number.                      *\n *   MonoClass::Scroll -- Scroll the monochrome screen up by the specified lines.              *\n *   MonoClass::Set_Cursor -- Sets the monochrome cursor to the coordinates specified.         *\n *   MonoClass::Sub_Window -- Partitions the mono screen into a sub-window.                    *\n *   MonoClass::Text_Print -- Prints text to the monochrome object at coordinates indicated.   *\n *   MonoClass::Text_Print -- Simple text printing from text number.                           *\n *   MonoClass::View -- Brings the mono object to the main display.                            *\n *   MonoClass::operator = -- Handles making one mono object have the same imagery as another. *\n *   MonoClass::~MonoClass -- The default destructor for a monochrome screen object.           *\n *   Mono_Clear_Screen -- Clear the currently visible monochrome page.                         *\n *   Mono_Draw_Rect -- Draws rectangle to monochrome screen.                                   *\n *   Mono_Print -- Prints simple text to monochrome screen.                                    *\n *   Mono_Printf -- Prints formatted text to visible page.                                     *\n *   Mono_Text_Print -- Prints text to location specified.                                     *\n *   Mono_X -- Fetches the X cursor position for current visible mono page.                    *\n *   Mono_Y -- Fetches the Y cursor position for current mono page.                            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n//#include\t\"watcom.h\"\n#include\t\"monoc.h\"\n\n#include\t\"function.h\"\n\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<dos.h>\n#include\t<mem.h>\n#include\t<stdarg.h>\n#include\t<string.h>\n\n\n\nextern void output(short port, short data);\n#pragma aux output parm [dx] [ax] =\t\t\\\n\t\t\"out\tdx,al\"\t\t\\\n\t\t\"inc\tdx\"\t\t\t\\\n\t\t\"mov\tal,ah\"\t\t\\\n\t\t\"out\tdx,al\"\n\n\nbool MonoClass::Enabled = 0;\nMonoClass * MonoClass::PageUsage[MonoClass::MAX_MONO_PAGES];\n//MonoClass::MonoPageType * MonoClass::MonoRAM = (MonoClass::MonoPageType *) 0xB0000;\n\n/*\n**\tThese are the IBM linedraw characters.\n*/\nMonoClass::BoxDataType const MonoClass::CharData[MonoClass::COUNT] = {\n\t{0xDA,0xC4,0xBF,0xB3,0xD9,0xC4,0xC0,0xB3},\t// Single line\n\t{0xD5,0xCD,0xB8,0xB3,0xBE,0xCD,0xD4,0xB3},\t// Double horz.\n\t{0xD6,0xC4,0xB7,0xBA,0xBD,0xC4,0xD3,0xBA},\t// Double vert.\n\t{0xC9,0xCD,0xBB,0xBA,0xBC,0xCD,0xC8,0xBA}\t\t// Double horz and vert.\n};\n\n\n#ifdef NEVER\ntemplate<class T>\nT min(T a, T b) {\n\tif (a < b) return(a);\n\treturn(b);\n}\n\ntemplate<class T>\nT max(T a, T b) {\n\tif (a > b) return(a);\n\treturn(b);\n}\n#endif\n\n\n/***********************************************************************************************\n * MonoClass::MonoClass -- The default constructor for monochrome screen object.               *\n *                                                                                             *\n *    This is the constructor for monochrome screen objects. It handles allocating a free      *\n *    monochrome page. If there are no more pages available, then this is a big error. The     *\n *    page allocated may not be the visible one. Call the View function in order to bring      *\n *    it to the displayed page.                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nMonoClass::MonoClass(void) :\n\tX(0),\n\tY(0),\n\tAttrib(NORMAL),\n\tPage(0),\n\tSubX(0),\n\tSubY(0),\n\tSubW(COLUMNS),\n\tSubH(LINES)\n{\n\tint\tindex;\n\n\tfor (index = 0; index < MAX_MONO_PAGES; index++) {\n\t\tif (!PageUsage[index]) {\n\t\t\tPageUsage[index] = this;\n\t\t\tPage = (char)index;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (index == MAX_MONO_PAGES) {\n\t\t// Major error message should pop up here!\n\t\tdelete this;\n\t}\n}\n\n\n/***********************************************************************************************\n * MonoClass::~MonoClass -- The default destructor for a monochrome screen object.             *\n *                                                                                             *\n *    This is the default destructor for a monochrome screen object.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nMonoClass::~MonoClass(void)\n{\n\tPageUsage[Page] = 0;\n}\n\n\n/***********************************************************************************************\n * MonoClass::Pan -- Scroll the window right or left.                                          *\n *                                                                                             *\n *    This routine will scroll the window to the right or left as indicated by the number of   *\n *    rows.                                                                                    *\n *                                                                                             *\n * INPUT:   cols  -- The number of columns to pan the window. Positive numbers pan to the left *\n *                   while negative numbers pan to the right.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Pan(int cols)\n{\n\tif (cols == 0) return;\n\n\tif (abs(cols) >= SubW) {\n\t\tClear();\n\t\treturn;\n\t}\n\n\tCellType cell;\n\tcell.Character = ' ';\n\tcell.Attribute = Attrib;\n\n\tif (cols > 0) {\n\t\tfor (int index = SubY; index < SubY+SubH; index++) {\n\t\t\tmemmove(&Page_Ptr()->Data[index][SubX], &Page_Ptr()->Data[index][SubX+cols], sizeof(CellType)*(SubW-cols));\n\t\t\tfor (int cc = SubX+SubW-cols; cc < SubX+SubW; cc++) {\n\t\t\t\tPage_Ptr()->Data[index][cc] = cell;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tfor (int index = SubY; index < SubY+SubH; index++) {\n\t\t\tmemmove(&Page_Ptr()->Data[index][SubX-cols], &Page_Ptr()->Data[index][SubX], sizeof(CellType)*(SubW+cols));\n\t\t\tfor (int cc = SubX; cc < SubX-cols; cc++) {\n\t\t\t\tPage_Ptr()->Data[index][cc] = cell;\n\t\t\t}\n\t\t}\n\t}\n\tSet_Cursor(X-cols, Y);\n}\n\n\n/***********************************************************************************************\n * MonoClass::Sub_Window -- Partitions the mono screen into a sub-window.                      *\n *                                                                                             *\n *    This routine is used to partition the monochrome screen so that only a sub-window will   *\n *    be processed. By using this, a separate rectangle of the screen can be cleared,          *\n *    scrolled, panned, or printed into.                                                       *\n *                                                                                             *\n * INPUT:   x,y   -- The upper left corner of the new sub-window.                              *\n *                                                                                             *\n *          w,h   -- Dimensions of the sub-window specified in characters.                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The parameters are clipped as necessary.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Sub_Window(int x, int y, int w, int h)\n{\n\t/*\n\t**\tUndo any sub window adjustments to the cursor position.\n\t*/\n\tX += SubX;\n\tY += SubY;\n\n\t/*\n\t**\tEnsure parameters are legal.\n\t*/\n\tx = min(x, COLUMNS-1);\n\tx = max(x, 0);\n\ty = min(y, LINES-1);\n\ty = max(y, 0);\n\tif (w == -1) w = COLUMNS-x;\n\tif (h == -1) h = LINES-y;\n\n\t/*\n\t**\tAssign the new sub-region.\n\t*/\n\tSubX = x;\n\tSubY = y;\n\tSubW = w;\n\tSubH = h;\n\n\t/*\n\t**\tMove the cursor (if necessary) so that it falls within that region.\n\t*/\n\tint xx = X;\n\tint yy = Y;\n\txx = min(xx, SubX+SubW-1);\n\txx = max(xx, SubX);\n\tyy = min(yy, SubY+SubH-1);\n\tyy = max(yy, SubY);\n\tSet_Cursor(xx-SubX, yy-SubY);\n}\n\n\n/***********************************************************************************************\n * MonoClass::Draw_Box -- Draws a box using the IBM linedraw characters.                       *\n *                                                                                             *\n *    Use this routine to draw a box to the monochrome screen. The IBM line draw characters    *\n *    are used to give the it a fancy appearance. There are several line draw modes supported. *\n *                                                                                             *\n * INPUT:   x,y      -- The coordinates of the upper left corner of the box.                   *\n *                                                                                             *\n *          w,y      -- The width and height (respectively) to make the box.                   *\n *                                                                                             *\n *          attrib   -- The text attribute to use when drawing the box outline characters.     *\n *                                                                                             *\n *          thick    -- The thickness style to use. Examine the BoxStyleType enum for          *\n *                      elaboration on the supported styles.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The interior of the box is NOT cleared by this routine. It is advised that this *\n *             area be cleared before the box is drawn.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Draw_Box(int x, int y, int w, int h, MonoAttribute attrib, BoxStyleType thick)\n{\n\tCellType\tcell;\n\tMonoAttribute\toldattrib = Attrib;\n\n\tif (!Enabled || !w || !h) return;\n\n\tx = min(x, SubW);\n\tx = max(x, 0);\n\ty = min(y, SubH);\n\ty = max(y, 0);\n\tw = min(w, SubW-x);\n\tw = max(w, 1);\n\th = min(h, SubH-y);\n\th = max(h, 1);\n\n\tx += SubX;\n\ty += SubY;\n\n\tcell.Attribute = attrib;\n\n\t/*\n\t**\tDraw the horizontal lines.\n\t*/\n\tfor (int xpos = 0; xpos < w-2; xpos++) {\n\t\tcell.Character = CharData[thick].TopEdge;\n\t\tPage_Ptr()->Data[y][x+xpos+1] = cell;\n\t\tcell.Character = CharData[thick].BottomEdge;\n\t\tPage_Ptr()->Data[y+h-1][x+xpos+1] = cell;\n\t}\n\n\t/*\n\t**\tDraw the vertical lines.\n\t*/\n\tfor (int ypos = 0; ypos < h-2; ypos++) {\n\t\tcell.Character = CharData[thick].LeftEdge;\n\t\tPage_Ptr()->Data[y+ypos+1][x] = cell;\n\t\tcell.Character = CharData[thick].RightEdge;\n\t\tPage_Ptr()->Data[y+ypos+1][x+w-1] = cell;\n\t}\n\n\t/*\n\t**\tDraw the four corners.\n\t*/\n\tif (w > 1 && h > 1) {\n\t\tcell.Character = CharData[thick].UpperLeft;\n\t\tPage_Ptr()->Data[y][x] = cell;\n\t\tcell.Character = CharData[thick].UpperRight;\n\t\tPage_Ptr()->Data[y][x+w-1] = cell;\n\t\tcell.Character = CharData[thick].BottomRight;\n\t\tPage_Ptr()->Data[y+h-1][x+w-1] = cell;\n\t\tcell.Character = CharData[thick].BottomLeft;\n\t\tPage_Ptr()->Data[y+h-1][x] = cell;\n\t}\n\n\tAttrib = oldattrib;\n}\n\n\n/***********************************************************************************************\n * MonoClass::Set_Cursor -- Sets the monochrome cursor to the coordinates specified.           *\n *                                                                                             *\n *    Use this routine to set the monochrome's cursor position to the coordinates specified.   *\n *    This is the normal way of controlling where the next Print or Printf will output the     *\n *    text to.                                                                                 *\n *                                                                                             *\n * INPUT:   x,y   -- The coordinate to position the monochrome cursor. 0,0 is the upper left   *\n *                   corner.                                                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Set_Cursor(int x, int y)\n{\n\tx = min(x, SubW);\n\tx = max(x, 0);\n\ty = min(y, SubH);\n\ty = max(y, 0);\n\n\tX = x;\n\tY = y;\n\n\tif (!Enabled) return;\n\n\t/*\n\t**\tUpdate the visible cursor position only if the this mono page is the currently\n\t**\tvisible one.\n\t*/\n\tint pos = ((y+SubY)*COLUMNS)+(x+SubX);\n\tif (Page == 0) {\n\t\toutput(CONTROL_PORT, (short)(0x0E|(pos&0xFF00)));\n\t\toutput(CONTROL_PORT, (short)(0x0F|(pos<<8)));\n\t}\n}\n\n\n/***********************************************************************************************\n * MonoClass::Clear -- Clears the monochrome screen object.                                    *\n *                                                                                             *\n *    This routine will fill the monochrome screen object with spaces. It is clearing the      *\n *    screen of data, making it free for output. The cursor is positioned at the upper left    *\n *    corner of the screen by this routine.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Clear(void)\n{\n\tif (!Enabled) return;\n\n\tSet_Cursor(0, 0);\n\n\tCellType\tcell;\n\tcell.Attribute = Attrib;\n\tcell.Character = ' ';\n\n\tfor (int rows = 0; rows < SubH; rows++) {\n\t\tfor (int cols = 0; cols < SubW; cols++) {\n\t\t\tPage_Ptr()->Data[rows+SubX][cols+SubY] = cell;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MonoClass::Fill_Attrib -- Fill a block with specified attribute.                            *\n *                                                                                             *\n *    This routine will give the specified attribute to the characters within the block        *\n *    but will not change the characters themselves. You can use this routine to change the    *\n *    underline, blink, or inverse characteristics of text.                                    *\n *                                                                                             *\n * INPUT:   x,y      -- The upper left coordinate of the region to change.                     *\n *                                                                                             *\n *          w,h      -- The dimensions of the region to change (in characters).                *\n *                                                                                             *\n *          attrib   -- The attribute to fill into the region specified.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Fill_Attrib(int x, int y, int w, int h, MonoAttribute attrib)\n{\n\tif (!w || !h || (unsigned)x >= SubW || (unsigned)h >= SubH || (unsigned)x+w > SubW || (unsigned)y+h > SubH) return;\n\n\tfor (int rows = y; rows < y+h; rows++) {\n\t\tfor (int cols = x; cols < x+w; cols++) {\n\t\t\tPage_Ptr()->Data[rows+SubY][cols+SubX].Attribute = attrib;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MonoClass::Scroll -- Scroll the monochrome screen up by the specified lines.                *\n *                                                                                             *\n *    Use this routine to scroll the monochrome screen up by the number of lines specified.    *\n *    This routine is typically called by the printing functions so that the monochrome screen *\n *    behaves in the expected manner -- printing at the bottom of the screen scrolls it up     *\n *    to make room for new text.                                                               *\n *                                                                                             *\n * INPUT:   lines -- The number of lines to scroll the monochrome screen.                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Scroll(int lines)\n{\n\tif (!Enabled || lines <= 0) return;\n\n\tif (abs(lines) >= SubH) {\n\t\tClear();\n\t\treturn;\n\t}\n\n\tCellType\tcell;\n\tcell.Attribute = Attrib;\n\tcell.Character = ' ';\n\n\tif (lines > 0) {\n\t\tfor (int row = 0; row < SubH-lines; row++) {\n\t\t\tmemmove(&Page_Ptr()->Data[SubY+row][SubX], &Page_Ptr()->Data[SubY+row+1][SubX], SubW*sizeof(CellType));\n\t\t}\n\t\tfor (int frow = SubH-lines; frow < SubH; frow++) {\n\t\t\tfor (int cc = 0; cc < SubW; cc++) {\n\t\t\t\tPage_Ptr()->Data[SubY+frow][SubX+cc] = cell;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tfor (int row = SubH-1; row >= -lines; row--) {\n\t\t\tmemmove(&Page_Ptr()->Data[SubY+row][SubX], &Page_Ptr()->Data[SubY+row-1][SubX], SubW*sizeof(CellType));\n\t\t}\n\t\tfor (int frow = 0; frow < -lines; frow++) {\n\t\t\tfor (int cc = 0; cc < SubW; cc++) {\n\t\t\t\tPage_Ptr()->Data[SubY+frow][SubX+cc] = cell;\n\t\t\t}\n\t\t}\n\t}\n\n\tSet_Cursor(X, Y-lines);\n}\n\n\n/***********************************************************************************************\n * MonoClass::Printf -- Prints a formatted string to the monochrome screen.                    *\n *                                                                                             *\n *    Use this routine to output a formatted string, using the standard formatting options,    *\n *    to the monochrome screen object's current cursor position.                               *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text to print.                                             *\n *                                                                                             *\n *          ...   -- Any optional parameters to supply in formatting the text.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The total formatted text length must not exceed 255 characters.                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Printf(char const *text, ...)\n{\n\tva_list\tva;\n\t/*\n\t**\tThe buffer object is placed at the end of the local variable list\n\t**\tso that if the sprintf happens to spill past the end, it isn't likely\n\t**\tto trash anything (important). The buffer is then manually truncated\n\t**\tto maximum allowed size before being printed.\n\t*/\n\tchar buffer[256];\n\n\tif (!Enabled) return;\n\n\tva_start(va, text);\n\tvsprintf(buffer, text, va);\n\tbuffer[sizeof(buffer)-1] = '\\0';\n\n\tPrint(buffer);\n\tva_end(va);\n}\n\n\n/***********************************************************************************************\n * MonoClass::Printf -- Prints formatted text using text string number.                        *\n *                                                                                             *\n *    This routine will take the given text string number and print the formatted text to      *\n *    the monochrome screen.                                                                   *\n *                                                                                             *\n * INPUT:   text  -- The text number to convert into real text (by way of external function).  *\n *                                                                                             *\n *          ...   -- Additional parameters as needed.                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Printf(int text, ...)\n{\n\tva_list\tva;\n\n\t/*\n\t**\tThe buffer object is placed at the end of the local variable list\n\t**\tso that if the sprintf happens to spill past the end, it isn't likely\n\t**\tto trash anything (important). The buffer is then manually truncated\n\t**\tto maximum allowed size before being printed.\n\t*/\n\tchar buffer[256];\n\n\tif (!Enabled) return;\n\n\tva_start(va, text);\n\tvsprintf(buffer, Text_String(text), va);\n\tbuffer[sizeof(buffer)-1] = '\\0';\n\n\tPrint(buffer);\n\tva_end(va);\n}\n\n\n/***********************************************************************************************\n * MonoClass::Print -- Prints the text string at the current cursor coordinates.               *\n *                                                                                             *\n *    Use this routine to output the specified text string at the monochrome object's current  *\n *    text coordinate position.                                                                *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the string to print.                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Print(char const * ptr)\n{\n\tint startcol = X;\n\tchar const * text;\n\tCellType\tcell;\n\n\tif (!ptr || !Enabled) return;\n\n\ttext = ptr;\n\tcell.Attribute = Attrib;\n\twhile (*text) {\n\n\t\tcell.Character = *text;\n\n\t\t/*\n\t\t**\tSometimes the character string is used for cursor control instead\n\t\t**\tof plain text output. Check for this case.\n\t\t*/\n\t\tswitch (cell.Character) {\n\n\t\t\t/*\n\t\t\t**\tThe \"return\" code behaves as it did in the old C library\n\t\t\t**\tmono system. That is, it returns the cursor position to\n\t\t\t**\tthe next line but at the starting column of the print.\n\t\t\t*/\n\t\t\tcase '\\r':\n\t\t\t\tif (Y == SubH-1) {\n\t\t\t\t\tScroll(1);\n\t\t\t\t}\n\t\t\t\tSet_Cursor(startcol, Y+1);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tThe TAB character is not currently handled. Convert it to\n\t\t\t**\ta space instead.\n\t\t\t*/\n\t\t\tcase '\\t':\n\t\t\t\tcell.Character = ' ';\n\t\t\t\t// fall into normal print case.\n\n\t\t\t/*\n\t\t\t**\tAll other characters are output directly and the cursor moves\n\t\t\t**\trightward to match. If the cursor wraps past the right\n\t\t\t**\tedge it is moved to the next now down at left margin. If the\n\t\t\t**\tcursor goes off the bottom of the display, the display is scrolled\n\t\t\t**\tupward a line.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\tPage_Ptr()->Data[SubY+Y][SubX+X] = cell;\n\n\t\t\t\tif (X < SubW-1) {\n\t\t\t\t\tSet_Cursor(X+1, Y);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// Fall into newline case.\n\n\t\t\t/*\n\t\t\t**\tThe \"newline\" code behaves like the console newline character.\n\t\t\t**\tThat is, it moves the cursor down one line and at the first\n\t\t\t**\tcolumn.\n\t\t\t*/\n\t\t\tcase '\\n':\n\t\t\t\tif (Y == SubH-1) {\n\t\t\t\t\tScroll(1);\n\t\t\t\t}\n\t\t\t\tSet_Cursor(0, Y+1);\n\t\t\t\tbreak;\n\t\t}\n\t\ttext++;\n\t}\n}\n\n\n/***********************************************************************************************\n * MonoClass::Text_Print -- Prints text to the monochrome object at coordinates indicated.     *\n *                                                                                             *\n *    Use this routine to output text to the monochrome object at the X and Y coordinates      *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text string to display.                                    *\n *                                                                                             *\n *          x,y   -- The X and Y character coordinates to start the printing at.               *\n *                                                                                             *\n *          attrib-- Optional parameter that specifies what text attribute code to use.        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Text_Print(char const *text, int x, int y, MonoAttribute attrib)\n{\n\tint\toldx = X;\n\tint\toldy = Y;\n\tMonoAttribute oldattrib = Attrib;\n\n\tX = (char)x;\n\tY = (char)y;\n\tAttrib = attrib;\n\tPrint(text);\n\tAttrib = oldattrib;\n\tSet_Cursor(oldx, oldy);\n}\n\n\n/***********************************************************************************************\n * MonoClass::Text_Print -- Simple text printing from text number.                             *\n *                                                                                             *\n *    This will print the text (represented by the text number) to the location on the         *\n *    monochrome screen specified.                                                             *\n *                                                                                             *\n * INPUT:   text  -- The text number to print (converted to real text by external routine).    *\n *                                                                                             *\n *          x,y   -- The coordinates to begin the printing at.                                 *\n *                                                                                             *\n *          attrib-- The character attribute to use while printing.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Text_Print(int text, int x, int y, MonoAttribute attrib)\n{\n\tint\toldx = X;\n\tint\toldy = Y;\n\tMonoAttribute oldattrib = Attrib;\n\n\tif (text != 0) {\n\t\tX = (char)x;\n\t\tY = (char)y;\n\t\tAttrib = attrib;\n\t\tPrint(Text_String(text));\n\t\tAttrib = oldattrib;\n\t\tSet_Cursor(oldx, oldy);\n\t}\n}\n\n\n/***********************************************************************************************\n * MonoClass::Print -- Simple print of text number.                                            *\n *                                                                                             *\n *    Prints text represented by the text number specified.                                    *\n *                                                                                             *\n * INPUT:   text  -- The text number to print (converted to real text by external routine).    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Print(int text)\n{\n\tPrint(Text_String(text));\n}\n\n\n/***********************************************************************************************\n * MonoClass::operator = -- Handles making one mono object have the same imagery as another.   *\n *                                                                                             *\n *    The assignment operator will handle copying the imagery from one monochrome object to    *\n *    another. Use this routine in to make two monochrome class objects visually identical.    *\n *                                                                                             *\n * INPUT:   src   -- A reference to the source (right side) monochrome object.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nMonoClass & MonoClass::operator = (MonoClass const & src)\n{\n\tmemmove(Page_Ptr(), src.Page_Ptr(), sizeof(MonoPageType));\n\tSet_Cursor(src.X, src.Y);\n\treturn(*this);\n}\n\n\n/***********************************************************************************************\n * MonoClass::View -- Brings the mono object to the main display.                              *\n *                                                                                             *\n *    Use this routine to display the mono object on the monochrome screen. It is possible     *\n *    that the mono object exists on some background screen memory. Calling this routine will  *\n *    perform the necessary memory swapping to bring the data to the front. The mono object    *\n *    that was currently being viewed is not destroyed by this function. It is merely moved    *\n *    off to some background page. It can be treated normally, except that is just isn't       *\n *    visible.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::View(void)\n{\n\tif (Get_Current() == this) return;\n\n\t/*\n\t**\tIf the visible page is already assigned to a real monochrome page\n\t**\tobject, then it must be swapped with the new one.\n\t*/\n\tMonoClass * displace = Get_Current();\n\tif (displace) {\n\t\tfor (int line = 0; line < LINES; line++) {\n\t\t\tfor (int col = 0; col < COLUMNS; col++) {\n\t\t\t\tCellType temp = Page_Ptr()->Data[line][col];\n\t\t\t\tPage_Ptr()->Data[line][col] = Raw_Ptr(0)->Data[line][col];\n\t\t\t\tRaw_Ptr(0)->Data[line][col] = temp;\n\t\t\t}\n\t\t}\n\t\tdisplace->Page = Page;\n\n\t} else {\n\n\t\t/*\n\t\t**\tJust copy the new page over since the display page is not assigned\n\t\t**\tto a real monochrome page object.\n\t\t*/\n\t\tmemmove(Raw_Ptr(0), Page_Ptr(), sizeof(MonoPageType));\n\t}\n\tPageUsage[Page] = displace;\n\tPageUsage[0] = this;\n\tPage = 0;\n\n\tSet_Cursor(X, Y);\n}\n\n\n\n/************************************************************************************\n**\tThis is the set of C wrapper functions that access the MonoClass support routines.\n**\tSince the C interface doesn't have the ability to write to non-visible pages, it\n**\twill just blast the output to whichever mono page is currently visible. If there is\n**\tno mono class object that is visible, then one will be created -- BUT NOT FREED.\n**\tTypically, this is ok, since the C interface will create only one MonoClass object\n**\tand the system supports up to 8.\n*/\nvoid Mono_Set_Cursor(int x, int y)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Set_Cursor(x, y);\n\t}\n}\n\n\n/***********************************************************************************************\n * Mono_Printf -- Prints formatted text to visible page.                                       *\n *                                                                                             *\n *    This routine will print formatted text (with parameters) to the visible monochrome page  *\n *    at whatever the current cursor location is.                                              *\n *                                                                                             *\n * INPUT:   string   -- The string to use as the main text and formatting control string.      *\n *                                                                                             *\n *          ...      -- Any additional parameters required by the formatting string.           *\n *                                                                                             *\n * OUTPUT:  Returns with the number of characters written to the display.                      *\n *                                                                                             *\n * WARNINGS:   The total size of the formatted text must not exceed 256 characters.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Mono_Printf(char const * string, ...)\n{\n\tva_list\tva;\n\tchar buffer[256];\n\n\tbuffer[0] = '\\0';\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\n\t\tva_start(va, string);\n\t\tvsprintf(buffer, string, va);\n\n\t\tmono->Print(buffer);\n\n\t\tva_end(va);\n\t}\n\treturn((short)strlen(buffer));\n}\n\n\n/***********************************************************************************************\n * Mono_Clear_Screen -- Clear the currently visible monochrome page.                           *\n *                                                                                             *\n *    This routine will clear the currently visible monochrome page.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Mono_Clear_Screen(void)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Clear();\n\t}\n}\n\n\n/***********************************************************************************************\n * Mono_Text_Print -- Prints text to location specified.                                       *\n *                                                                                             *\n *    This routine will print the specified text to the location indicated.                    *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text to print.                                             *\n *                                                                                             *\n *          x,y   -- The coordinate to print the text at.                                      *\n *                                                                                             *\n *          attrib-- The attribute to use when printing the text.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Mono_Text_Print(void const *text, int x, int y, int attrib)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Text_Print((const char*)text, x, y, (MonoClass::MonoAttribute)attrib);\n\t}\n}\n\n\n/***********************************************************************************************\n * Mono_Draw_Rect -- Draws rectangle to monochrome screen.                                     *\n *                                                                                             *\n *    Use this routine to draw a rectangle to the monochrome screen. The dimensions, attribute,*\n *    and line style are controlled by parameters.                                             *\n *                                                                                             *\n * INPUT:   x,y   -- Coordinate of upper left corner of the box to draw.                       *\n *                                                                                             *\n *          w,h   -- The width and height of the box to draw.                                  *\n *                                                                                             *\n *          attrib-- The attribute to use when drawing the box.                                *\n *                                                                                             *\n *          thick -- The line drawing style to use.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Mono_Draw_Rect(int x, int y, int w, int h, int attrib, int thick)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Draw_Box(x, y, w, h, (MonoClass::MonoAttribute)attrib, (MonoClass::BoxStyleType)thick);\n\t}\n}\n\n\n/***********************************************************************************************\n * Mono_Print -- Prints simple text to monochrome screen.                                      *\n *                                                                                             *\n *    This is the non-formatting print to the monochrome screen.                               *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text that will be printed.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Mono_Print(void const *text)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Print((const char*)text);\n\t}\n}\n\n\n/***********************************************************************************************\n * Mono_X -- Fetches the X cursor position for current visible mono page.                      *\n *                                                                                             *\n *    Use this routine to get the current cursor X position. This only applies to the          *\n *    currently visible monochrome page.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with X position of cursor.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Mono_X(void)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\treturn(short)mono->Get_X();\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * Mono_Y -- Fetches the Y cursor position for current mono page.                              *\n *                                                                                             *\n *    This routine will fetch the current Y cursor position for the monochrome page.           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current Y position of the monochrome page.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Mono_Y(void)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\treturn(short)mono->Get_X();\n\t}\n\treturn(0);\n}\n\n\nvoid Mono_Put_Char(char , int )\n{\n}\n\nvoid Mono_Scroll(int )\n{\n}\n\nvoid Mono_View_Page(int )\n{\n}\n\nint Mono_Printf(int string, ...)\n{\n\tva_list\tva;\n\tchar buffer[256];\n\n\tbuffer[0] = '\\0';\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\n\t\tva_start(va, string);\n\t\tvsprintf(buffer, Text_String(string), va);\n\n\t\tmono->Print(buffer);\n\n\t\tva_end(va);\n\t}\n\treturn((short)strlen(buffer));\n}\n\n"
  },
  {
    "path": "CODE/MONOC.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MONOC.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MONO.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 2, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 2, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MONOC_Hx\n#define MONOC_Hx\n\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\nclass MonoClass {\n\tpublic:\n\t\tenum MonoClassPageEnums {\n\t\t\tCOLUMNS=80,\t\t\t\t\t\t// Number of columns.\n\t\t\tLINES=25,\t\t\t\t\t\t// Number of lines.\n\t\t\tMAX_MONO_PAGES=16\t// Maximum RAM pages on mono card.\n\t\t};\n\n      typedef enum MonoAttribute {\n\t\t\tINVISIBLE=0x00,\t\t\t\t// Black on black.\n\t\t\tUNDERLINE=0x01,\t\t\t\t// Underline.\n\t\t\tBLINKING=0x90,\t\t\t\t\t// Blinking white on black.\n\t\t\tNORMAL=0x02,\t\t\t\t\t// White on black.\n\t\t\tINVERSE=0x70,\t\t\t\t\t// Black on white.\n      } MonoAttribute;\n\n\t\t/*\n\t\t**\tThese are the various box styles that may be used.\n\t\t*/\n\t\ttypedef enum BoxStyleType {\n\t\t\tSINGLE,\t\t\t\t// Single thickness.\n\t\t\tDOUBLE_HORZ,\t\t// Double thick on the horizontal axis.\n\t\t\tDOUBLE_VERT,\t\t// Double thick on the vertical axis.\n\t\t\tDOUBLE,\t\t\t\t// Double thickness.\n\n\t\t\tCOUNT\n\t\t} BoxStyleType;\n\n\t\tMonoClass(void);\n\t\t~MonoClass(void);\n\n\t\tstatic void Enable(void) {Enabled = true;};\n\t\tstatic void Disable(void) {Enabled = false;};\n\t\tstatic bool Is_Enabled(void) {return Enabled;};\n\t\tstatic MonoClass * Get_Current(void) {return PageUsage[0];};\n\n\t\tvoid Sub_Window(int x=0, int y=0, int w=-1, int h=-1);\n\t\tvoid Fill_Attrib(int x, int y, int w, int h, MonoAttribute attrib);\n\t\tvoid Draw_Box(int x, int y, int w, int h, MonoAttribute attrib=NORMAL, BoxStyleType thick=SINGLE);\n\t\tvoid Set_Default_Attribute(MonoAttribute attrib) {Attrib = attrib;};\n\t\tvoid Clear(void);\n\t\tvoid Set_Cursor(int x, int y);\n\t\tvoid Print(char const *text);\n\t\tvoid Print(int text);\n\t\tvoid Printf(char const *text, ...);\n\t\tvoid Printf(int text, ...);\n\t\tvoid Text_Print(char const *text, int x, int y, MonoAttribute attrib=NORMAL);\n\t\tvoid Text_Print(int text, int x, int y, MonoAttribute attrib=NORMAL);\n\t\tvoid View(void);\n\t\tvoid Scroll(int lines=1);\n\t\tvoid Pan(int cols=1);\n\t\tint Get_X(void) const {return X;};\n\t\tint Get_Y(void) const {return Y;};\n\t\tint Get_Width(void) const {return(SubW);};\n\t\tint Get_Height(void) const {return(SubH);};\n\n\t\t/*\n\t\t**\tHandles deep copies for the mono class objects. This performs what is essentially\n\t\t**\ta screen copy.\n\t\t*/\n\t\tMonoClass & operator = (MonoClass const & );\n\n\t\t/*\n\t\t**\tThis merely makes a duplicate of the mono object into a newly created mono\n\t\t**\tobject.\n\t\t*/\n\t\tMonoClass (MonoClass const &);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tCursor coordinate (relative to sub-window).\n\t\t*/\n\t\tint X;\n\t\tint Y;\n\n\t\t/*\n\t\t**\tDefault attribute to use when printing text.\n\t\t*/\n\t\tMonoAttribute Attrib;\n\n\t\t/*\n\t\t**\tThe current physical page that this mono class object refers to.\n\t\t*/\n\t\tint Page;\n\n\t\t/*\n\t\t**\tSub window coordinates.\n\t\t*/\n\t\tint SubX;\n\t\tint SubY;\n\t\tint SubW;\n\t\tint SubH;\n\n\t\t/*\n\t\t**\tPointer to the monochrome RAM.\n\t\t*/\n//\t\tstatic MonoPageType * MonoRAM;\n\n\t\t/*\n\t\t** This the the arrays of characters used for drawing boxes.\n\t\t*/\n\t\t/*\n\t\t**\tThis is a private structure that is used to control which characters\n\t\t**\tare used when a box is drawn. Line drawing on the monochrome screen is\n\t\t**\treally made up of characters. This specifies which characters to use.\n\t\t*/\n\t\tstruct BoxDataType {\n\t\t\tchar\tUpperLeft;\n\t\t\tchar\tTopEdge;\n\t\t\tchar\tUpperRight;\n\t\t\tchar\tRightEdge;\n\t\t\tchar\tBottomRight;\n\t\t\tchar\tBottomEdge;\n\t\t\tchar\tBottomLeft;\n\t\t\tchar\tLeftEdge;\n\t\t};\n\t\tstatic BoxDataType const CharData[4];\n\n\t\t/*\n\t\t**\tEach cell is constructed of the actual character that is displayed and the\n\t\t**\tattribute to use. This character pair is located at every position on the\n\t\t**\tdisplay (80 x 25). Since this cell pair can be represented by a \"short\"\n\t\t**\tinteger, certain speed optimizations are taken in the monochrome drawing\n\t\t**\tcode.\n\t\t*/\n\t\tstruct CellType {\n\t\t\tunsigned char Character;\t// Character to display.\n\t\t\tunsigned char Attribute;\t// Attribute.\n\t\t};\n\n\t\tstruct MonoPageType {\n\t\t\tCellType Data[LINES][COLUMNS];\n\t\t};\n\n\t\t/*\n\t\t**\tThese private constants are used in the various monochrome operations.\n\t\t*/\n\t\tenum MonoClassPortEnums {\n\t\t\tCONTROL_PORT=0x03B4,\t\t\t// CRTC control register.\n\t\t\tDATA_PORT=0x03B5,\t\t\t\t// CRTC data register.\n\t\t\tSIZE_OF_PAGE=(int)LINES*(int)COLUMNS*sizeof(CellType)\t// Entire page size.\n\t\t};\n\n\t\t/*\n\t\t**\tThis array contains pointers to the monochrome objects that are assigned\n\t\t**\tto each of the monochrome pages. As the monochrome pages are made visible,\n\t\t**\tthey can be shuffled around between the actual locations. The first entry\n\t\t**\tin this table is the one that is visible.\n\t\t*/\n\t\tstatic MonoClass * PageUsage[MAX_MONO_PAGES];\n\n\t\t/*\n\t\t**\tFetches pointers to the appropriate mono RAM.\n\t\t*/\n\t\tMonoPageType * Raw_Ptr(int page) const {\n\t\t\treturn &((MonoPageType *)0xB0000)[page];\n\t\t}\n\t\tMonoPageType * Page_Ptr(void) const {\n\t\t\treturn(Raw_Ptr(Page));\n\t\t}\n\n\t\t/*\n\t\t**\tIf this is true, then monochrome output is allowed. It defaults to false\n\t\t**\tso that monochrome output must be explicitly enabled.\n\t\t*/\n\t\tstatic bool Enabled;\n};\n\n#ifndef WIN32\nint Mono_Printf(int string, ...);\n#else\nextern void Mono_Set_Cursor(int x, int y);\nextern int Mono_Printf(int string, ...);\nextern int Mono_Printf(char const * string, ...);\nextern void Mono_Clear_Screen(void);\nextern void Mono_Text_Print(void const *text, int x, int y, int attrib);\nextern void Mono_Draw_Rect(int x, int y, int w, int h, int attrib, int thick);\nextern void Mono_Print(void const *text);\nextern int Mono_X(void);\nextern int Mono_Y(void);\n#endif\n\n#endif\n\n"
  },
  {
    "path": "CODE/MOUSE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MOUSE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MOUSE.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : September 21, 1995 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   MouseClass::AI -- Process player input as it relates to the mouse                         *\n *   MouseClass::Init_Clear -- Sets the mouse system to a known state                          *\n *   MouseClass::MouseClass -- Default constructor for the mouse handler class.                *\n *   MouseClass::Mouse_Small -- Controls the sizing of the mouse.                              *\n *   MouseClass::One_Time -- Performs the one time initialization of the mouse system.         *\n *   MouseClass::Override_Mouse_Shape -- Alters the shape of the mouse.                        *\n *   MouseClass::Revert_Mouse_Shape -- Reverts the mouse shape to the non overridden shape.    *\n *   MouseClass::Set_Default_Mouse -- Sets the mouse to match the shape specified.             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/*\n**\tThis points to the loaded mouse shapes.\n*/\nvoid const * MouseClass::MouseShapes;\n\n/*\n**\tThis is the timer that controls the mouse animation. It is always at a fixed\n**\trate so it uses the constant system timer.\n*/\nCDTimerClass<SystemTimerClass> MouseClass::Timer = 0;\n\n\n/***********************************************************************************************\n * MouseClass::MouseClass -- Default constructor for the mouse handler class.                  *\n *                                                                                             *\n *    This is the default constructor for the mouse handling class. It merely sets up the      *\n *    mouse system to its default state.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nMouseClass::MouseClass(void) :\n\tIsSmall(false),\n\tCurrentMouseShape(MOUSE_NORMAL),\n\tNormalMouseShape(MOUSE_NORMAL),\n\tFrame(0)\n{\n}\n\n\n/***********************************************************************************************\n * MouseClass::Set_Default_Mouse -- Sets the mouse to match the shape specified.               *\n *                                                                                             *\n *    This routine is used to inform the display system as to which mouse shape is desired.    *\n *                                                                                             *\n * INPUT:   mouse -- The mouse shape number to set the mouse to.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MouseClass::Set_Default_Mouse(MouseType mouse, bool size)\n{\n\tassert((unsigned)mouse < MOUSE_COUNT);\n\n\tNormalMouseShape = mouse;\n\tOverride_Mouse_Shape(mouse, size);\n}\n\n\n/***********************************************************************************************\n * MouseClass::Revert_Mouse_Shape -- Reverts the mouse shape to the non overridden shape.      *\n *                                                                                             *\n *    Use this routine to cancel the effects of Override_Mouse_Shape(). It will revert the     *\n *    mouse back to the original shape.                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MouseClass::Revert_Mouse_Shape(void)\n{\n\tOverride_Mouse_Shape(NormalMouseShape, false);\n}\n\n\n/***********************************************************************************************\n * MouseClass::Mouse_Small -- Controls the sizing of the mouse.                                *\n *                                                                                             *\n *    This routine is called to change the mouse sizing override. If the mouse can change      *\n *    size to that specified, then the mouse imagery will be changed. If a change of imagery   *\n *    cannot occur (due to lack of appropriate artwork), then no action will be performed.     *\n *                                                                                             *\n * INPUT:   small -- Should the mouse be made small? If not, then it will be made large.       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MouseClass::Mouse_Small(bool wsmall)\n{\n\tMouseStruct const * control = &MouseControl[CurrentMouseShape];\n\n\tif (IsSmall == wsmall) {\n\t\treturn;\n\t}\n\n\tIsSmall\t= wsmall;\n\n\tif (wsmall) {\n\t\tif (control->SmallFrame != -1) {\n\t\t\tSet_Mouse_Cursor(control->X, control->Y, Extract_Shape(MouseShapes, control->SmallFrame + Frame/4));\n\t\t} else {\n\t\t\tSet_Mouse_Cursor(MouseControl[MOUSE_NORMAL].X, MouseControl[MOUSE_NORMAL].Y, Extract_Shape(MouseShapes, MOUSE_NORMAL));\n\t\t}\n\t} else {\n\t\tSet_Mouse_Cursor(control->X, control->Y, Extract_Shape(MouseShapes, control->StartFrame + Frame/4));\n\t}\n}\n\n\n/***********************************************************************************************\n * MouseClass::Override_Mouse_Shape -- Alters the shape of the mouse.                          *\n *                                                                                             *\n *    This routine is used to alter the shape of the mouse as needed.                          *\n *    Typical mouse shape change occurs when scrolling the map or                              *\n *    selecting targets.                                                                       *\n *                                                                                             *\n * INPUT:   mouse -- The mouse shape number to use.                                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the mouse shape changed?                                                 *\n *                                                                                             *\n * WARNINGS:   This is not intended to be used as a means to hide the                          *\n *             mouse. Nor will it work correctly if the mouse shape                            *\n *             file hasn't been loaded.                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1994 JLB : Created.                                                                 *\n *   06/03/1994 JLB : Made into member function.                                               *\n *   12/24/1994 JLB : Added small control parameter.                                           *\n *=============================================================================================*/\n#ifdef WIN32\nvoid Block_Mouse(GraphicBufferClass *buffer);\nvoid Unblock_Mouse(GraphicBufferClass *buffer);\n#endif\n\nbool MouseClass::Override_Mouse_Shape(MouseType mouse, bool wsmall)\n{\n\tassert((unsigned)mouse < MOUSE_COUNT);\n\n\tMouseStruct const * control = &MouseControl[mouse];\n\tstatic bool startup = false;\n\tint baseshp;\n\n\t/*\n\t**\tOnly certain mouse shapes have a small counterpart. If the requested mouse\n\t**\tshape is not one of these, then force the small size override flag to false.\n\t*/\n\tif (control->SmallFrame == -1) {\n\t\twsmall = false;\n\t}\n\n\t/*\n\t**\tIf the mouse shape is going to change, then inform the mouse driver of the\n\t**\tchange.\n\t*/\n\tif (!startup || (MouseShapes && ((mouse != CurrentMouseShape) || (wsmall != IsSmall)))) {\n\t\tstartup = true;\n\n\t\tTimer = control->FrameRate;\n\t\tFrame = 0;\n\n\t\tbaseshp = (wsmall) ? control->SmallFrame : control->StartFrame;\n\t\tif (baseshp == -1) {\n\t\t\tbaseshp = control->StartFrame;\n\t\t}\n\n\t\tSet_Mouse_Cursor(control->X, control->Y, Extract_Shape(MouseShapes, baseshp));\n\t\tCurrentMouseShape = mouse;\n\t\tIsSmall = wsmall;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MouseClass::AI -- Process player input as it relates to the mouse                           *\n *                                                                                             *\n *    This routine will is to be called once per game tick and is passed the player keyboard   *\n *    or mouse input code. It processes this code and updates the mouse shape as appropriate.  *\n *                                                                                             *\n * INPUT:   input -- The player input code as returned from Keyboard->Get().                   *\n *                                                                                             *\n *          x,y   -- The mouse coordinate values to use.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *   12/31/1994 JLB : Uses mouse coordinate parameters.                                        *\n *   03/27/1995 JLB : New animation control.                                                   *\n *   05/28/1995 JLB : Moderates animation so is more steady regardless of speed.               *\n *   06/30/1995 JLB : Uses constant timer system.                                              *\n *=============================================================================================*/\nvoid MouseClass::AI(KeyNumType &input, int x, int y)\n{\n\tMouseStruct const * control = &MouseControl[CurrentMouseShape];\n\n\tif (control->FrameRate && Timer == 0) {\n\n\t\tFrame++;\n\t\tFrame %= control->FrameCount;\n\t\tTimer = control->FrameRate;\n\n\t\tif (!IsSmall || control->SmallFrame != -1) {\n\t\t\tint baseframe = (IsSmall) ? control->SmallFrame : control->StartFrame;\n\t\t\tif (baseframe == -1) baseframe = control->StartFrame;\n\t\t\tSet_Mouse_Cursor(control->X, control->Y, Extract_Shape(MouseShapes, baseframe + Frame));\n\t\t}\n\t}\n\n\tScrollClass::AI(input, x, y);\n}\n\n\n/***********************************************************************************************\n * MouseClass::One_Time -- Performs the one time initialization of the mouse system.           *\n *                                                                                             *\n *    Use this routine to load the mouse data file and perform any other necessary one time    *\n *    preparations for the game.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine ONCE.                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MouseClass::One_Time(void)\n{\n\tScrollClass::One_Time();\n\n\t/*\n\t**\tOverride the mouse shape file with the one in the current directory, but only if there\n\t**\tis an override file available.\n\t*/\n\t#ifndef NDEBUG\n\t\tRawFileClass file(\"MOUSE.SHP\");\n\t\tif (file.Is_Available()) {\n\t\t\tMouseShapes = Load_Alloc_Data(file);\n\t\t} else {\n\t\t\tMouseShapes = MFCD::Retrieve(\"MOUSE.SHP\");\n\t\t}\n\t#else\n\t\tMouseShapes = MFCD::Retrieve(\"MOUSE.SHP\");\n\t#endif\n}\n\n\n/***********************************************************************************************\n * MouseClass::Init_Clear -- Sets the mouse system to a known state                            *\n *                                                                                             *\n *    This routine will reset the mouse handling system. Typically, this routine is called     *\n *    when preparing for the beginning of a new scenario.                                      *\n *                                                                                             *\n * INPUT:   theater  -- The theater that the scenario will take place.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MouseClass::Init_Clear(void)\n{\n\tScrollClass::Init_Clear();\n\tIsSmall = false;\n\tNormalMouseShape = MOUSE_NORMAL;\n}\n\n\n/*\n**\tThis array of structures is used to control the mouse animation\n**\tsequences.\n*/\n//#ifdef WIN32\n//#define\tWD\t45\n//#define\tHT\t36\n//#else\n#define\tWD\t29\n#define\tHT\t23\n//#endif\n\nMouseClass::MouseStruct MouseClass::MouseControl[MOUSE_COUNT] = {\n\t{0, \t1,\t\t0,\t\t80,\t0,\t\t0},\t\t//\tMOUSE_NORMAL\n\t{1, \t1,\t\t0,\t\t-1,\tWD/2,\t0},\t\t//\tMOUSE_N\n\t{2, \t1,\t\t0,\t\t-1,\tWD,\t0},\t\t//\tMOUSE_NE\n\t{3, \t1,\t\t0,\t\t-1,\tWD,\tHT/2},\t//\tMOUSE_E\n\t{4,\t1,\t\t0,\t\t-1,\tWD,\tHT},\t\t//\tMOUSE_SE\n\t{5,\t1,\t\t0,\t\t-1,\tWD/2,\tHT},\t\t//\tMOUSE_S\n\t{6,\t1,\t\t0,\t\t-1,\t0, \tHT},\t\t//\tMOUSE_SW\n\t{7,\t1,\t\t0,\t\t-1,\t0, \tHT/2},\t//\tMOUSE_W\n\t{8,\t1,\t\t0,\t\t-1,\t0, \t0},\t\t//\tMOUSE_NW\n\n\t{124, 1,\t\t0,\t\t-1,\tWD/2,\t0},\t\t//\tMOUSE_NO_N\n\t{125, 1,\t\t0,\t\t-1,\tWD,\t0},\t\t//\tMOUSE_NO_NE\n\t{126, 1,\t\t0,\t\t-1,\tWD,\tHT/2},\t//\tMOUSE_NO_E\n\t{127,\t1,\t\t0,\t\t-1,\tWD,\tHT},\t\t//\tMOUSE_NO_SE\n\t{128,\t1,\t\t0,\t\t-1,\tWD/2,\tHT},\t\t//\tMOUSE_NO_S\n\t{129,\t1,\t\t0,\t\t-1,\t0, \tHT},\t\t//\tMOUSE_NO_SW\n\t{130,\t1,\t\t0,\t\t-1,\t0, \tHT/2},\t//\tMOUSE_NO_W\n\t{131,\t1,\t\t0,\t\t-1,\t0, \t0},\t\t//\tMOUSE_NO_NW\n\n\t{14,\t1,\t\t0,\t\t33,\tWD/2,\tHT/2},\t//\tMOUSE_NO_MOVE\n\t{10,\t4,\t\t4,\t\t29,\tWD/2,\tHT/2},\t//\tMOUSE_CAN_MOVE\n\t{113,\t3,\t\t4,\t\t142,\tWD/2,\tHT/2},\t//\tMOUSE_ENTER\n\t{59,\t9,\t\t4,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_DEPLOY\n\t{15,\t6,\t\t4,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_CAN_SELECT\n\t{21,\t8,\t\t4,\t\t134,\tWD/2,\tHT/2},\t//\tMOUSE_CAN_ATTACK\n\t{68,\t12,\t2,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_SELL_BACK\n\t{148,\t12,\t2,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_SELL_UNIT\n\t{35,\t24,\t2,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_REPAIR\n\t{120,\t1,\t\t0,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_NO_REPAIR\n\t{119,\t1,\t\t0,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_NO_SELL_BACK\n\t{81,\t1,\t\t0,\t\t145,\tWD/2, HT/2},\t//\tMOUSE_RADAR_CURSOR\n\t{90,\t7,\t\t4,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_NUCLEAR_BOMB\n\t{82,\t8,\t\t2,\t\t213,\tWD/2,\tHT/2},\t//\tMOUSE_AIR_STRIKE\n\t{116,\t3,\t\t4,\t\t121,\tWD/2,\tHT/2},\t//\tMOUSE_DEMOLITIONS\n\t{147,\t1,\t\t0,\t\t146,\tWD/2,\tHT/2},\t//\tMOUSE_AREA_GUARD\n\t{160,\t4,\t\t4,\t\t194,\tWD/2,\tHT/2},\t//\tMOUSE_HEAL\n\t{164,\t3,\t\t4,\t\t167,\tWD/2,\tHT/2},\t//\tMOUSE_DAMAGE\n\t{170,\t24,\t2,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_GREPAIR\n\t{195,\t8,\t\t4,\t\t203,\tWD/2,\tHT/2},\t// MOUSE_STAY_ATTACK\n\t{211,\t1,\t\t0,\t\t-1,\tWD/2,\tHT/2},\t// MOUSE_NO_DEPLOY\n\t{212,\t1,\t\t0,\t\t-1,\tWD/2,\tHT/2},\t// MOUSE_NO_ENTER\n\t{213,\t1,\t\t0,\t\t-1,\tWD/2,\tHT/2},\t// MOUSE_NO_REPAIR\n\n\t{97,\t8,\t\t3,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_CHRONO_SELECT\n\t{105,\t8,\t\t2,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_CHRONO_DEST\n\n};\n"
  },
  {
    "path": "CODE/MOUSE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MOUSE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MOUSE.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : December 15, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MOUSE_H\n#define MOUSE_H\n\n#include\t\"stage.h\"\n#include\t\"scroll.h\"\n\nclass MouseClass: public ScrollClass\n{\n\tpublic:\n\t\tMouseClass(void);\n\t\tMouseClass(NoInitClass const & x) : ScrollClass(x) {};\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t\t// One-time inits\n\t\tvirtual void Init_Clear(void);\t\t\t\t\t\t// Clears all to known state\n\n\t\tvirtual void AI(KeyNumType &input, int x, int y);\n\t\tvirtual bool Override_Mouse_Shape(MouseType mouse, bool wsmall=false);\n\t\tvirtual void Revert_Mouse_Shape(void);\n\t\tvirtual MouseType Get_Mouse_Shape(void) const {return NormalMouseShape;};\n\t\tvirtual void Mouse_Small(bool wsmall);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvirtual bool Load(Straw & file);\n\t\tvirtual bool Save(Pipe & file) const;\n\n\t\tvirtual void Set_Default_Mouse(MouseType mouse, bool wsmall = false);\n\n\t\t/*\n\t\t**\tThis allows the tactical map input gadget access to change the\n\t\t**\tmouse shapes.\n\t\t*/\n\t\tfriend class TacticalClass;\n\n\t\t/*\n\t\t**\tThis points to the loaded mouse shapes.\n\t\t*/\n\t\tstatic void const * MouseShapes;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis type is used to control the frames and rates of the mouse\n\t\t**\tpointer. Some mouse pointers are actually looping animations.\n\t\t*/\n\t\ttypedef struct MouseStruct\n\t\t{\n\t\t\tint StartFrame;\t\t\t// Starting frame number.\n\t\t\tint FrameCount;\t\t\t// Number of animation frames.\n\t\t\tint FrameRate;\t\t\t\t// Frame delay between changing frames.\n\t\t\tint SmallFrame;\t\t\t// Start frame number for small version (if any).\n\t\t\tint X,Y;\t\t\t\t\t\t// Hotspot X and Y offset.\n\t\t} MouseStruct;\n\n\t\t/*\n\t\t**\tThe control frames and rates for the various mouse pointers are stored\n\t\t**\tin this static array.\n\t\t*/\n\t\tstatic MouseStruct MouseControl[MOUSE_COUNT];\n\n\tpublic:\n\t\t/*\n\t\t**\tIf the small representation of the mouse is active, then this flag is true.\n\t\t*/\n\t\tunsigned IsSmall:1;\n\n\n\tprivate:\n\t\t/*\n\t\t**\tThe mouse shape is controlled by these variables. These\n\t\t**\thold the current mouse shape (so resetting won't be needlessly performed) and\n\t\t**\tthe normal default mouse shape (when arrow shapes are needed).\n\t\t*/\n\t\tMouseType CurrentMouseShape;\n\t\tMouseType NormalMouseShape;\n\n\t\t/*\n\t\t**\tFor animating mouse shapes, this controls the frame and animation rate.\n\t\t*/\n\t\tstatic CDTimerClass<SystemTimerClass> Timer;\n\t\tint Frame;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/MOVIE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef _MPGMOVIE_H_\n#define _MPGMOVIE_H_\n/****************************************************************************\n*\n* FILE\n*     MpgMovie.h\n*\n* DESCRIPTION\n*     Movie playback using DirectShow Multimedia streaming and DirectDraw\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     May 27, 1998\n*\n****************************************************************************/\n\n#include <windows.h>\n#include <ddraw.h>\n\n#ifdef MPGEXPORT\t\t  \n#define DLLCALL __declspec(dllexport)\n#else\n#define DLLCALL __declspec(dllimport)\n#endif\n\ntypedef enum\n\t{\n\tMPGCMD_ERROR = -1,\n\tMPGCMD_INIT = 0,\n\tMPGCMD_CLEANUP,\n\tMPGCMD_PALETTE,\n\tMPGCMD_UPDATE\n\t} MPG_CMD;\n\ntypedef enum\n\t{\n\tMPGRES_QUIT = -1,\n\tMPGRES_CONTINUE = 0,\n\tMPGRES_LOSTFOCUS,\n\t} MPG_RESPONSE;\n\ntypedef MPG_RESPONSE (far __stdcall *LPMPGCALLBACK)(MPG_CMD cmd, LPVOID data, LPVOID user);\n\nextern \"C\"\n\t{\n\tDLLCALL void __stdcall MpgPlay(const char* name, IDirectDraw* dd,\n\t\tIDirectDrawSurface* surface, RECT* dstRect);\n\tDLLCALL void __stdcall MpgPause(void);\n\tDLLCALL void __stdcall MpgResume(void);\n\tDLLCALL void __stdcall MpgSetCallback(LPMPGCALLBACK callback, LPVOID user);\n\t}\n\n#endif // _MPGMOVIE_H_\n"
  },
  {
    "path": "CODE/MP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MP.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MP.CPP                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 04/26/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   _Byte_Precision -- Determines the number of bytes significant in long integer.            *\n *   memrev -- Reverse the byte order of the buffer specified.                                 *\n *   XMP_Abs -- Perform an absolute value on the specified MP number.                          *\n *   XMP_Add -- Add two MP numbers with a carry option.                                        *\n *   XMP_Add_Int -- Add an integer to an MP number (with carry).                               *\n *   XMP_Compare -- Compare one MP number with another.                                        *\n *   XMP_Count_Bits -- Count the total number of bits (precision) in MP number.                *\n *   XMP_Count_Bytes -- Counts the number of precision bytes in MP number.                     *\n *   XMP_Dec -- Decrement the MP number by one.                                                *\n *   XMP_Decode_ASCII -- Convert ASCII into an MP number.                                      *\n *   XMP_DER_Decode -- Decode a DER number into an MP number.                                  *\n *   XMP_DER_Encode -- Encode a number into a buffer using DER.                                *\n *   XMP_DER_Length_Encode -- Output the length of a DER block.                                *\n *   XMP_Double_Mul -- Double precision MP multiply.                                           *\n *   XMP_Encode -- Encode MP number into buffer as compactly as possible.                      *\n *   XMP_Fermat_Test -- Performs Fermat's Little Theorem on an MP number.                      *\n *   XMP_Hybrid_Mul -- Special hybrid short multiply (with carry).                             *\n *   XMP_Inc -- Increment an MP number by one.                                                 *\n *   XMP_Init -- Initialize an MP number to a starting value.                                  *\n *   XMP_Inverse_A_Mod_B -- Inverts and performs modulus on an MP number.                      *\n *   XMP_Is_Prime -- Determine if the specified MP number is prime.                            *\n *   XMP_Is_Small_Prime -- Determine if MP number is a small prime.                            *\n *   XMP_Mod_Mult -- Perform a multiply - modulus operation.                                   *\n *   XMP_Mod_Mult_Clear -- Remove temporary values from memory.                                *\n *   XMP_Move -- Assign one MP number to another.                                              *\n *   XMP_Neg -- Negate the specified MP number.                                                *\n *   XMP_Not -- Perform bitwise NOT operation on MP number.                                    *\n *   XMP_Prepare_Modulus -- Prepare globals for modulus operation.                             *\n *   XMP_Rabin_Miller_Test -- Performs the Rabin Miller test for primality.                    *\n *   XMP_Randomize -- Generate a random MP number between the boundaries specified.            *\n *   XMP_Randomize -- Generate a random MP number.                                             *\n *   XMP_Reciprocal -- Compute the reciprocal (inverse) of the MP number.                      *\n *   XMP_Rotate_Left -- Rotate specified MP number leftward.                                   *\n *   XMP_Shift_Left_Bits -- Shifts the MP number left by the specified bit count.              *\n *   XMP_Shift_Right_Bits -- Shift the MP number right by specified bit count.                 *\n *   XMP_Signed_Decode -- Decode a number as if it were signed.                                *\n *   XMP_Signed_Div -- Signed divide of one MP number into another.                            *\n *   XMP_Signed_Mult -- A signed multiply between two MP numbers.                              *\n *   XMP_Signed_Mult_Int -- Multiply an MP number by a signed simple integer.                  *\n *   XMP_Significance -- Fetch the precision (bytes) of the MP number.                         *\n *   XMP_Small_Divisors_Test -- Perform the small divisors test on an MP number.               *\n *   XMP_Sub -- Subtract one MP number from another (with borrow).                             *\n *   XMP_Sub_Int -- Subtract an integer from an MP number (with borrow).                       *\n *   XMP_Unsigned_Decode -- Decode a number as if it were unsigned.                            *\n *   XMP_Unsigned_Div -- Unsigned divide of one MP number into another.                        *\n *   XMP_Unsigned_Div_Int -- Perform a short integer divide into an MP number.                 *\n *   XMP_Unsigned_Mult -- Multiply two unsigned MP numbers together.                           *\n *   XMP_Unsigned_Mult_Int -- Multiply an MP number by a simple integer.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t<stdlib.h>\n#include\t<string.h>\n#include\t<ctype.h>\n#include\t<assert.h>\n#include\t<limits.h>\n#include\t\"mp.h\"\n\n\n#ifndef __BORLANDC__\n#define\tmin(a, b)\t(((a) < (b)) ? (a) : (b))\n#define\t_USERENTRY\n#endif\n\n\n/***********************************************************************************************\n * _Byte_Precision -- Determines the number of bytes significant in long integer.              *\n *                                                                                             *\n *    This utility routine will determine the number of precision bytes exist in the long      *\n *    integer specified. There are some optimizations that can occur if the byte precision     *\n *    is known.                                                                                *\n *                                                                                             *\n * INPUT:   value -- The value of the long integer that the byte precision will be calculated  *\n *                   for.                                                                      *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes that the long integer requires (at a minimum)     *\n *          to cover the precision of the integer. The minimum value will be 1, the maximum    *\n *          will be 4.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic int _Byte_Precision(unsigned long value)\n{\n\tint byte_count;\n\tfor (byte_count = sizeof(value); byte_count; byte_count--) {\n\t\tif (value >> ((byte_count-1)*8)) break;\n\t}\n\treturn(byte_count);\n}\n\n\n/***********************************************************************************************\n * XMP_DER_Length_Encode -- Output the length of a DER block.                                  *\n *                                                                                             *\n *    This routine will output the length of the block using Distinguished Encoding Rules.     *\n *    The rest of the block must be filled in as appropriate. For data blocks that are less    *\n *    than 128 bytes long, the header consists of only one byte. Longer buffers lengths        *\n *    can consume up to 5 bytes (depends on magnitude of the length value).                    *\n *                                                                                             *\n * INPUT:   length   -- The length of the data block to be output.                             *\n *                                                                                             *\n *          output   -- Pointer to the memory block that will be set up.                       *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes (header) that was used to store the length        *\n *          value. Subsequent data must be placed after the header.                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_DER_Length_Encode(unsigned long length, unsigned char * output)\n{\n\tassert(output != NULL);\n\n\tint header_length = 0;\n\n\tif (length <= SCHAR_MAX) {\n\t\toutput[header_length++] = (unsigned char)length;\n\t} else {\n\t\toutput[header_length++] = (unsigned char)(_Byte_Precision(length) | 0x80);\n\t\tfor (int byte_counter = _Byte_Precision(length); byte_counter; --byte_counter) {\n\t\t\toutput[header_length++] = (unsigned char)(length >> ((byte_counter-1)*8));\n\t\t}\n\t}\n\treturn(header_length);\n}\n\n\n/***********************************************************************************************\n * XMP_DER_Encode -- Encode a number into a buffer using DER.                                  *\n *                                                                                             *\n *    This routine is used to encode a number into a buffer using Distinguished Encoding       *\n *    Rules. The number of bytes used will be, typically, two bytes more than the number of    *\n *    precision bytes in the number.                                                           *\n *                                                                                             *\n * INPUT:   from     -- Pointer to the multi-precision number.                                 *\n *                                                                                             *\n *          output   -- Pointer to the buffer that will hold the DER encoded number.           *\n *                                                                                             *\n *          precision-- The precision of the multi-precision number.                           *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes used in the output buffer.                        *\n *                                                                                             *\n * WARNINGS:   Make sure the buffer is big enough to hold the DER encoded number. For safety   *\n *             make sure it is precision+6 bytes long.                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_DER_Encode(digit const * from, unsigned char * output, int precision)\n{\n\tassert(from != NULL);\n\tassert(output != NULL);\n\tassert(precision > 0);\n\n\tunsigned char buffer[MAX_UNIT_PRECISION*sizeof(digit)+1];\n\tint header_count = 0;\n\n\tunsigned number_count = XMP_Encode(buffer, from, precision);\n\n\toutput[header_count++] = 0x02;\n\theader_count += XMP_DER_Length_Encode(number_count, &output[header_count]);\n\tmemcpy(&output[header_count], buffer, number_count);\n\n\treturn(header_count+number_count);\n}\n\n\n/***********************************************************************************************\n * XMP_DER_Decode -- Decode a DER number into an MP number.                                    *\n *                                                                                             *\n *    Use this routine to decode a Distinguished Encoding Rules number into a multi-precision  *\n *    number. This is the counterpart function to the XMP_DER_Encode() function.               *\n *                                                                                             *\n * INPUT:   result      -- The buffer the hold the result MP number.                           *\n *                                                                                             *\n *          input       -- Pointer to the DER encoded number.                                  *\n *                                                                                             *\n *          precision   -- The precision of the MP number. This is the maximum precision the   *\n *                         DER number can be.                                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_DER_Decode(digit * result, unsigned char const * input, int precision)\n{\n\tassert(result != NULL);\n\tassert(input != NULL);\n\tassert(precision > 0);\n\n\tif (*input++ == 0x02) {\n\t\tunsigned byte_count;\n\n\t\tif ((*input & 0x80) == 0) {\n\t\t\tbyte_count = *input++;\n\t\t} else {\n\t\t\tint length = *input++ & 0x7f;\n\t\t\tif (length > 2) return;\n\t\t\tbyte_count = *input++;\n\t\t\tif (length > 1) byte_count = (byte_count << 8) | *input++;\n\t\t}\n\t\tif (byte_count <= (precision * sizeof(digit))) {\n\t\t\tXMP_Signed_Decode(result, input, byte_count, precision);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Encode -- Encode MP number into buffer.                                                 *\n *                                                                                             *\n *    This routine will encode an multi-precision number into a buffer of specified length.    *\n *    The number of stored in \"big endian\" format with appropriate sign extension.             *\n *                                                                                             *\n * INPUT:   to       -- Pointer to the buffer to place the number.                             *\n *                                                                                             *\n *          tobytes  -- The number of bytes to use in the destination buffer.                  *\n *                                                                                             *\n *          from     -- Pointer to the MP number to be encoded.                                *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes placed into the destination buffer.               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned XMP_Encode(unsigned char * to, unsigned tobytes, digit const * from, int precision)\n{\n\tassert(to != NULL);\n\tassert(from != NULL);\n\tassert(tobytes > 0);\n\tassert(precision > 0);\n\n\tunsigned frombytes = precision * sizeof(digit);\n\tunsigned char filler = (unsigned char)(XMP_Is_Negative(from, precision) ? 0xff : 0);\n\n\tint index;\n\tfor (index = 0; index < (int)(tobytes-frombytes); index++) {\n\t\t*to++ = filler;\n\t}\n\n\tconst unsigned char * fptr = ((const unsigned char *)from) + min(tobytes, frombytes);\n\tfor (index = 0; index < (int)min(tobytes, frombytes); index++) {\n\t\t*to++ = *--fptr;\n\t}\n\n\treturn(tobytes);\n}\n\n\n/***********************************************************************************************\n * XMP_Encode -- Encode MP number into buffer as compactly as possible.                        *\n *                                                                                             *\n *    This routine will encode the MP number into the specified buffer. The number will be     *\n *    encoded using the least number of bytes possible.                                        *\n *                                                                                             *\n * INPUT:   to       -- The buffer to encode the MP number into.                               *\n *                                                                                             *\n *          from     -- Pointer to the MP number to be encoded.                                *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes used in the destination buffer to hold the        *\n *          encoded number.                                                                    *\n *                                                                                             *\n * WARNINGS:   Be sure the destination buffer is big enough to hold the encoded MP number.     *\n *             A safe size would be the precision plus one.                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\n#pragma warning 364 9\nunsigned XMP_Encode(unsigned char * to, digit const * from, int precision)\n{\n\tassert(to != NULL);\n\tassert(from != NULL);\n\tassert(precision > 0);\n\n\tbool is_negative = XMP_Is_Negative(from, precision);\n\tunsigned char filler = (unsigned char)(is_negative ? 0xff : 0);\n\tunsigned char * number_ptr;\n\n\tunsigned char * const end = (unsigned char *)from;\n\tfor (number_ptr = (unsigned char *)end + precision - 1; number_ptr > (unsigned char *)end; number_ptr--) {\n\t\tif (*number_ptr != filler) break;\n\t}\n\n\tunsigned index = 0;\n\tif (((*number_ptr & 0x80) && !is_negative) || (!(*number_ptr & 0x80) && is_negative)) {\n\t\tto[index++] = filler;\n\t}\n\n\tto[index++] = *number_ptr;\n\n\twhile (number_ptr != end) {\n\t\tto[index++] = *--number_ptr;\n\t}\n\treturn(index);\n}\n\n\n/***********************************************************************************************\n * XMP_Signed_Decode -- Decode a number as if it were signed.                                  *\n *                                                                                             *\n *    Use this routine to convert a coded number back into an MP number. The coded number      *\n *    is presumed to be signed.                                                                *\n *                                                                                             *\n * INPUT:   result   -- Pointer to the buffer that will hold the decoded MP number.            *\n *                                                                                             *\n *          from     -- Pointer to the encoded MP number.                                      *\n *                                                                                             *\n *          frombytes-- The number of bytes consumed by the encoded MP number.                 *\n *                                                                                             *\n *          precision -- The precision of the MP number (maximum) of the result.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure that the precision is sufficient to hold the decoded MP number.         *\n *             Otherwise, the result is undefined.                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Signed_Decode(digit * result, const unsigned char * from, int frombytes, int precision)\n{\n\tassert(result != NULL);\n\tassert(from != NULL);\n\tassert(frombytes > 0);\n\tassert(precision > 0);\n\n\tunsigned char filler = (unsigned char)((*from & 0x80) ? 0xff : 0);\n\n\tint fillcount = precision * sizeof(digit) - frombytes;\n\tunsigned char * dest = (unsigned char *)&result[precision];\n\n\t/*\n\t**\tFill in any excess significant bytes.\n\t*/\n\tint index;\n\tfor (index = 0; index < fillcount; index++) {\n\t\t*--dest = filler;\n\t}\n\n\t/*\n\t**\tMove in the remaining bytes.\n\t*/\n\tfor (index = 0; index < frombytes; index++) {\n\t\t*--dest = *from++;\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Unsigned_Decode -- Decode a number as if it were unsigned.                              *\n *                                                                                             *\n *    Use this routine to decode a MP number and treat it as if it were unsigned.              *\n *                                                                                             *\n * INPUT:   result   -- Pointer to the buffer to hold the result MP number.                    *\n *                                                                                             *\n *          from     -- Pointer to the encoded MP number.                                      *\n *                                                                                             *\n *          frombytes-- The number of bytes in the encoded number.                             *\n *                                                                                             *\n *          precision-- The precision of the result MP number -- maximum precision.            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure the result MP precision is sufficient to hold the decoded number or     *\n *             else the result is undefined.                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Unsigned_Decode(digit * result, const unsigned char * from, int frombytes, int precision)\n{\n\tassert(result != NULL);\n\tassert(from != NULL);\n\tassert(frombytes > 0);\n\tassert(precision > 0);\n\n\tint fillcount = precision * sizeof(digit) - frombytes;\n\tunsigned char * dest = (unsigned char *)&result[precision];\n\n\t/*\n\t**\tFill in any excess significant bytes.\n\t*/\n\tint index;\n\tfor (index = 0; index < fillcount; index++) {\n\t\t*--dest = '\\0';\n\t}\n\n\t/*\n\t**\tMove in the remaining bytes.\n\t*/\n\tfor (index = 0; index < frombytes; index++) {\n\t\t*--dest = *from++;\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Significance -- Fetch the precision (bytes) of the MP number.                           *\n *                                                                                             *\n *    This routine will return with the precision of the MP number expressed as bytes. The     *\n *    MP number is presumed unsigned.                                                          *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to examine.                                   *\n *                                                                                             *\n *          precision-- The precision of the MP number to examine.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the minimum number of bytes consumed by this MP number.               *\n *                                                                                             *\n * WARNINGS:   Passing a signed MP number to this routine will return an artificially greater  *\n *             precision than it really is.                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Significance(const digit * number, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\tnumber += precision;\n\tdo {\n\t\tif (*(--number)) break;\n\t} while (--precision);\n\treturn(precision);\n}\n\n\n/***********************************************************************************************\n * XMP_Inc -- Increment an MP number by one.                                                   *\n *                                                                                             *\n *    This will increment the MP number by one.                                                *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to increment.                                 *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If the number wraps around the maximum precision, the results are undefined.    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Inc(digit * number, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\tdo {\n\t\tif (++(*number)) break;\n\t\tnumber++;\n\t} while (--precision);\n}\n\n\n/***********************************************************************************************\n * XMP_Dec -- Decrement the MP number by one.                                                  *\n *                                                                                             *\n *    Use this routine to decrement the specified MP number by one.                            *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to decrement.                                 *\n *                                                                                             *\n *          precision-- The precision of the MP number to decrement.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If the number wraps below zero, the results are undefined.                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Dec(digit * number, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\tdo {\n\t\t*number -= 1;\n\t\tif ((*number) != ~(digit)0) break;\n\t\tnumber++;\n\t} while (--precision);\n}\n\n\n/***********************************************************************************************\n * XMP_Neg -- Negate the specified MP number.                                                  *\n *                                                                                             *\n *    This routine will negate (reverse sign) of the specified MP number.                      *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to negate.                                    *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Neg(digit * number, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\tXMP_Not(number, precision);\n\tXMP_Inc(number, precision);\n}\n\n\n/***********************************************************************************************\n * XMP_Abs -- Perform an absolute value on the specified MP number.                            *\n *                                                                                             *\n *    This will perform the absolute value function on the specified MP number. That is, if    *\n *    the MP number is negative, it will be transformed into a positive number. If the number  *\n *    is already positive, then it will be left alone.                                         *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to ABS.                                       *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Abs(digit * number, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\tif (XMP_Is_Negative(number, precision)) {\n\t\tXMP_Neg(number, precision);\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Shift_Right_Bits -- Shift the MP number right by specified bit count.                   *\n *                                                                                             *\n *    Use this routine to perform a right shift of the MP number by the number of bits         *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to perform the shift upon.                    *\n *                                                                                             *\n *          bits     -- The number of bits to shift.                                           *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This is an unsigned shift.                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Shift_Right_Bits(digit * number, int bits, int precision)\n{\n\tassert(number != NULL);\n\tassert(bits >= 0);\n\tassert(precision > 0);\n\n\tif (bits == 0) return;\t\t\t/* shift zero bits is a no-op */\n\n\t/*\n\t**\tIf the shift is by whole bytes, then the shift operation can\n\t**\tbe performed very quickly.\n\t*/\n\tif (bits == UNITSIZE) {\n\t\tnumber += precision;\n\t\tdigit carry = 0;\n\t\twhile (precision--) {\n\t\t\tnumber--;\n\t\t\tdigit temp = *number;\n\t\t  \t*number = carry;\n\t\t\tcarry = temp;\n\t\t}\n\t\treturn;\n\t}\n\n\t/*\n\t**\tIf the number of bits to shift is less than one byte, then the\n\t**\tshift operation is a relatively simple \"ripple\" effect through\n\t**\tthe MP number buffer.\n\t*/\n\tif (bits < UNITSIZE) {\n\t\tnumber += precision;\n\t\tdigit carry = 0;\n\t\tdigit bitmask = (1L << bits) - 1;\n\t\tint unbits = UNITSIZE - bits;\n\n\t\twhile (precision--) {\n\t\t\tnumber--;\n\t\t\tdigit temp = *number & bitmask;\n\t\t\t*number >>= bits;\n\t\t\t*number |= carry << unbits;\n\t\t\tcarry = temp;\n\t\t}\n\t\treturn;\n\t}\n\n\t/*\n\t**\tGeneral purpose slow right.\n\t*/\n\tint digits_to_shift = bits / UNITSIZE;\n\tint bits_to_shift = bits % UNITSIZE;\n\n\tint index;\n\tfor (index = digits_to_shift; index < (precision-1); index++) {\n\t\t*number = (*(number + digits_to_shift) >> bits_to_shift) | (*(number + (digits_to_shift + 1)) << (UNITSIZE - bits_to_shift));\n\t\tnumber++;\n\t}\n\n\tif (digits_to_shift < precision) {\n\t\t*number = (*(number + digits_to_shift) >> bits_to_shift);\n\t\tnumber++;\n\t}\n\n\tfor (index= 0; index < min(digits_to_shift, precision); index++) {\n\t\t*number++ = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Shift_Left_Bits -- Shifts the MP number left by the specified bit count.                *\n *                                                                                             *\n *    Use this routine to perform a left shift of the specified MP number.                     *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to perform the shift operation on.            *\n *                                                                                             *\n *          bits     -- The number of bits to shift the MP number leftward.                    *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Shift_Left_Bits(digit * number, int bits, int precision)\n{\n\tassert(number != NULL);\n\tassert(bits >= 0);\n\tassert(precision > 0);\n\n\tif (bits == 0) return;\t\t\t/* shift zero bits is a no-op */\n\n\t/*\n\t**\tIf the shift is by whole bytes, then the shift operation can\n\t**\tbe performed very quickly.\n\t*/\n\tif (bits == UNITSIZE) {\n\t\tdigit carry = 0;\n\t\twhile (precision--) {\n\t\t\tdigit temp = *number;\n\t\t\t*number = carry;\n\t\t\tcarry = temp;\n\t\t\tnumber++;\n\t\t}\n\t\treturn;\n\t}\n\n\t/*\n\t**\tIf the number of bits to shift is less than one byte, then the\n\t**\tshift operation is a relatively simple \"ripple\" effect through\n\t**\tthe MP number buffer.\n\t*/\n\tif (bits < UNITSIZE) {\n\t\tdigit carry = 0;\n\t\tdigit bitmask = ~(((digit)-1) >> bits);\n\t\tint unbits = UNITSIZE - bits;\t/* shift bits must be <= UNITSIZE */\n\n\t\twhile (precision--) {\n\t\t\tdigit temp = *number & bitmask;\n\t\t\t*number = (*number << bits) | (carry >> unbits);\n\t\t\tcarry = temp;\n\t\t\tnumber++;\n\t\t}\n\t\treturn;\n\t}\n\n\t/*\n\t**\tGeneral purpose slow left;\n\t*/\n\tint digits_to_shift = bits / UNITSIZE;\n\tint bits_to_shift = bits % UNITSIZE;\n\n\tint index;\n\tnumber += precision-1;\n\tfor (index = digits_to_shift; index < (precision-1); index++) {\n\t\t*number = (*(number - digits_to_shift) << bits_to_shift) | (*(number - (digits_to_shift + 1)) >> (UNITSIZE - bits_to_shift));\n\t\tnumber--;\n\t}\n\n\tif (digits_to_shift < precision) {\n\t\t*number = (*(number - digits_to_shift) << bits_to_shift);\n\t\tnumber--;\n\t}\n\n\tfor (index = 0; index < min(digits_to_shift, precision); index++) {\n\t\t*number-- = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Rotate_Left -- Rotate specified MP number leftward.                                     *\n *                                                                                             *\n *    This routine will rotate the MP number to the left by one bit. The rotation passes bits  *\n *    through a \"carry\" bit position. The initial value of this \"carry\" bit is passed to the   *\n *    routine and the final value is returned as the result.                                   *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to perform the left rotate upon.              *\n *                                                                                             *\n *          carry    -- The initial value of the \"carry\" bit.                                  *\n *                                                                                             *\n *          precision-- The precision of the MP number specified.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the final value of the carry bit. This is the the bit value of the    *\n *          upper most bit of the MP number prior to the rotate operation.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Rotate_Left(digit * number, bool carry, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\twhile (precision--) {\n\t\tbool temp = ((*number & UPPER_MOST_BIT) != 0);\n\t\t*number = (*number << 1);\n\t\tif (carry) *number = *number + 1;\n\t\tcarry = temp;\n\t\tnumber++;\n\t}\n\treturn carry;\n}\n\n\n/***********************************************************************************************\n * XMP_Not -- Perform bitwise NOT operation on MP number.                                      *\n *                                                                                             *\n *    Perform a bitwise NOT operation.                                                         *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to operate on.                                *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Not(digit * number, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\tfor (int index = 0; index < precision; index++) {\n\t\t*number = ~(*number);\n\t\tnumber++;\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Init -- Initialize an MP number to a starting value.                                    *\n *                                                                                             *\n *    This will initialize (assign) a number to an MP number. The initial value is limited     *\n *    to the precision allowed by a DIGIT type.                                                *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to initialize.                                *\n *                                                                                             *\n *          value    -- Initial integer value to assign to the MP number.                      *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Init(digit * number, digit value, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\tmemset(number, '\\0', precision * sizeof(digit));\n\t*number = value;\n}\n\n\n/***********************************************************************************************\n * XMP_Count_Bits -- Count the total number of bits (precision) in MP number.                  *\n *                                                                                             *\n *    This routine will count the maximum number of bits used by this MP number. The result    *\n *    could be referred to as the \"bit precision\" of the MP number.                            *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to examine.                                   *\n *                                                                                             *\n *          precision-- The (digit) precision of the MP number.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the number of significant bits in the MP number.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned XMP_Count_Bits(const digit * number, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\tint sub_precision = XMP_Significance(number, precision);\n\tif (!sub_precision) return(0);\n\tint total_bit_count = XMP_Digits_To_Bits(sub_precision);\n\tnumber += sub_precision-1;\n\tdigit high_bit_mask = UPPER_MOST_BIT;\n\n\twhile (!((*number) & high_bit_mask)) {\n\t\thigh_bit_mask >>= 1;\n\t\ttotal_bit_count--;\n\t}\n\n\treturn(total_bit_count);\n}\n\n\n/***********************************************************************************************\n * XMP_Count_Bytes -- Counts the number of precision bytes in MP number.                       *\n *                                                                                             *\n *    This routine will scan the MP number and determine the number of bytes needed to         *\n *    represent the MP number. Consider the result the \"byte precision\" of the number.         *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to examine.                                   *\n *                                                                                             *\n *          precision-- Precision of the MP number.                                            *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes required to represent the precision of the number.*\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Count_Bytes(const digit * number, int precision)\n{\n\tunsigned char * ptr = (unsigned char *)number;\n\tint count = 0;\n\tfor (unsigned index = 0; index < precision*sizeof(digit); index++) {\n\t\tif (!*ptr) break;\n\t\tcount++;\n\t\tptr++;\n\t}\n\treturn(count);\n}\n\n\n/***********************************************************************************************\n * XMP_Move -- Assign one MP number to another.                                                *\n *                                                                                             *\n *    This will move one MP number over the top of another.                                    *\n *                                                                                             *\n * INPUT:   dest     -- Destination MP number (will get clobbered).                            *\n *                                                                                             *\n *          source   -- Source MP number.                                                      *\n *                                                                                             *\n *          precision-- Precision of both MP numbers.                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Both MP numbers must have the same precision.                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Move(digit * dest, digit const * source, int precision)\n{\n\tmemcpy(dest, source, precision * sizeof(digit));\n}\n\n\n/***********************************************************************************************\n * XMP_Compare -- Compare one MP number with another.                                          *\n *                                                                                             *\n *    This routine will compare two MP numbers. It will return a value indicating which MP     *\n *    number is greater or if they are equal.                                                  *\n *                                                                                             *\n * INPUT:   left_number -- The left hand MP number.                                            *\n *                                                                                             *\n *          right_number-- The right hand MP number.                                           *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers.                                    *\n *                                                                                             *\n * OUTPUT:  Returns -1 if the left_number is less than the right_number.                       *\n *          Returns 1 if the left_number is greater than the right number.                     *\n *          Returns 0 if both numbers are identical.                                           *\n *                                                                                             *\n * WARNINGS:   Both numbers must have the same precision.                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Compare(const digit * left_number, const digit * right_number, int precision)\n{\n\tleft_number += precision-1;\n\tright_number += precision-1;\n\tdo {\n\t\tif (*left_number < *right_number) return -1;\n\t\tif (*left_number > *right_number) return 1;\n\t\tleft_number--;\n\t\tright_number--;\n\t} while (--precision);\n\treturn 0;\n}\n\n\n/***********************************************************************************************\n * XMP_Add -- Add two MP numbers with a carry option.                                          *\n *                                                                                             *\n *    Use this routine to add one MP number to another. There is an optional \"carry\" value     *\n *    that (when true) will add an additional 1 to the result.                                 *\n *                                                                                             *\n * INPUT:   result   -- Pointer to the MP buffer that will hold the result. This can be the    *\n *                      same value as the left_number or right_number pointers.                *\n *                                                                                             *\n *          left_number -- The left hand MP number.                                            *\n *                                                                                             *\n *          right_number-- The right hand MP number.                                           *\n *                                                                                             *\n *          carry       -- Optional carry flag (typically this will be false).                 *\n *                                                                                             *\n *          precision   -- The precision of the numbers involved.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the carry flag after the addition. If the value is true then an       *\n *          overflow occurred.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Add(digit * result, const digit * left_number, const digit * right_number, bool carry, int precision)\n{\n\twhile (precision--) {\n\t\tdigit term = *left_number + *right_number;\n\t\tdigit final = term + carry;\n\t\tcarry = (term < *left_number || (carry && final == 0));\n\n\t\tright_number++;\n\t\tleft_number++;\n\t\t*result++ = final;\n\t}\n\treturn(carry);\n}\n\n\n/***********************************************************************************************\n * XMP_Add_Int -- Add an integer to an MP number (with carry).                                 *\n *                                                                                             *\n *    This routine will add an integer number to an MP number. There is an optional carry      *\n *    parameter. If the carry flag is true, and additional 1 will be added to the result.      *\n *    This routine is much faster than adding two MP numbers together.                         *\n *                                                                                             *\n * INPUT:   result      -- Pointer to the result MP number. This pointer can be the same as    *\n *                         the left_number parameter.                                          *\n *                                                                                             *\n *          left_number -- Pointer to the left hand MP number.                                 *\n *                                                                                             *\n *          right_number-- The integer number to add to the left hand number.                  *\n *                                                                                             *\n *          carry       -- Input carry flag. If this is true, then an additional one will be   *\n *                         added to the result.                                                *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the result carry flag. A true value means the addition overflowed.    *\n *                                                                                             *\n * WARNINGS:   All MP numbers must share the same precision. Negative numbers are not          *\n *             supported.                                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Add_Int(digit * result, const digit * left_number, digit right_number, bool carry, int precision)\n{\n\twhile (precision--) {\n\t\tdigit term = *left_number + right_number;\n\t\tdigit final = term + carry;\n\t\tcarry = (term < *left_number || (carry && final == 0));\n\n\t\tright_number = 0;\n\t\tleft_number++;\n\t\t*result++ = final;\n\t}\n\treturn(carry);\n}\n\n\n/***********************************************************************************************\n * XMP_Sub -- Subtract one MP number from another (with borrow).                               *\n *                                                                                             *\n *    This routine will subtract one MP number from another. There is an optional borrow       *\n *    flag that can be specified.                                                              *\n *                                                                                             *\n * INPUT:   result      -- Pointer to the MP number that will hold the result. This pointer    *\n *                         can be the same as the left_number or right_number parameters.      *\n *                                                                                             *\n *          left_number -- The left hand number (value will be subtracted from this).          *\n *                                                                                             *\n *          right_number-- The right hand number (the value to subtract from the left number)  *\n *                                                                                             *\n *          borrow      -- The optional borrow flag. If this flag is true, the an extra one    *\n *                         will be subtracted from the result.                                 *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  Returns with the borrow result flag. If the value is true, then an underflow       *\n *          occurred during subtraction.                                                       *\n *                                                                                             *\n * WARNINGS:   All MP numbers must share the same precision.                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Sub(digit * result, const digit * left_number, const digit * right_number, bool borrow, int precision)\n{\n\tconst unsigned short * left_number_ptr = (const unsigned short *)left_number;\n\tconst unsigned short * right_number_ptr = (const unsigned short *)right_number;\n\tunsigned short * result_ptr = (unsigned short *)result;\n\n\tprecision *= 2;\n\twhile (precision--) {\n\t\tdigit x = (digit) *left_number_ptr - (digit) *right_number_ptr - (digit) borrow;\n\t\tright_number_ptr++;\n\t\tleft_number_ptr++;\n\t\t*result_ptr++ = (unsigned short)x;\n\t\tborrow = (((1L << 16) & x) != 0L);\n\t}\n\treturn (borrow);\n}\n\n\n/***********************************************************************************************\n * XMP_Sub_Int -- Subtract an integer from an MP number (with borrow).                         *\n *                                                                                             *\n *    This will subtract an integer from the specified MP number. There is an optional borrow  *\n *    flag available.                                                                          *\n *                                                                                             *\n * INPUT:   result      -- Pointer to the MP buffer that will hold the result.                 *\n *                                                                                             *\n *          left_number -- Pointer to the MP number that will be subtracted FROM.              *\n *                                                                                             *\n *          right_number-- The integer to subtract from the left hand number.                  *\n *                                                                                             *\n *          borrow      -- The optional borrow flag. If this value is true, then an extra one  *\n *                         will be subtracted from the result.                                 *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  Returns with the borrow flag of the result. If this value is true, then an         *\n *          underflow occurred during subtraction.                                             *\n *                                                                                             *\n * WARNINGS:   The precision must be identical between the MP numbers involved.                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Sub_Int(digit * result, const digit * left_number, unsigned short right_number, bool borrow, int precision)\n{\n\tconst unsigned short * left_number_ptr = (const unsigned short *)left_number;\n\tunsigned short * result_ptr = (unsigned short *)result;\n\n\tprecision *= 2;\n\twhile (precision--) {\n\t\tdigit x = (digit) *left_number_ptr - right_number - borrow;\n\t\tleft_number_ptr++;\n\t\t*result_ptr++ = (unsigned short)x;\n\t\tborrow = (((1L << 16) & x) != 0L);\n\n\t\tright_number = 0;\n\t}\n\treturn (borrow);\n}\n\n\n/***********************************************************************************************\n * XMP_Unsigned_Mult -- Multiply two unsigned MP numbers together.                             *\n *                                                                                             *\n *    This routine will multiply two MP numbers together. The result will have the sum of the  *\n *    significance of the two.                                                                 *\n *                                                                                             *\n * INPUT:   prod        -- Pointer to the product MP buffer that will hold the result.         *\n *                                                                                             *\n *          multiplicand-- Pointer to the multiplicand MP number.                              *\n *                                                                                             *\n *          multiplier  -- Pointer to the multiplier MP number.                                *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers.                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure the product will fit within the precision of the result.                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Unsigned_Mult(digit * prod, const digit * multiplicand, const digit * multiplier, int precision)\n{\n\tXMP_Init(prod, 0, precision);\n\n\t/*\n\t**\tMultiplying by zero is always a zero product.\n\t*/\n\tif (XMP_Test_Eq_Int(multiplicand, 0, precision) || XMP_Test_Eq_Int(multiplier, 0, precision)) {\n\t\treturn 0;\n\t}\n\n\tint total_bit_count = XMP_Count_Bits(multiplier, precision);\n\tdigit high_bit_mask = XMP_Bits_To_Mask(total_bit_count);\n\tint sub_precision = XMP_Bits_To_Digits(total_bit_count);\n\tif (!sub_precision) return(0);\n\tmultiplier += sub_precision;\n\n\twhile (total_bit_count--) {\n\t\tXMP_Shift_Left_Bits(prod, 1, precision);\n\n\t\tif ((*(multiplier-1)) & high_bit_mask) {\n\t\t\tXMP_Add(prod, prod, multiplicand, 0, precision);\n\t\t}\n\n\t\thigh_bit_mask >>= 1;\n\t\tif (!high_bit_mask) {\n\t\t\thigh_bit_mask = UPPER_MOST_BIT;\n\t\t\tmultiplier--;\n\t\t}\n\n\t}\n\treturn 0;\n}\n\n\n/***********************************************************************************************\n * XMP_Unsigned_Mult_Int -- Multiply an MP number by a simple integer.                         *\n *                                                                                             *\n *    This is a very fast multiply since the multiplier is just an integer integral.           *\n *                                                                                             *\n * INPUT:   prod        -- Pointer to the product MP number.                                   *\n *                                                                                             *\n *          multiplicand-- Pointer to the MP number that is the multiplicand.                  *\n *                                                                                             *\n *          multiplier  -- The integral integer that is the multiplier.                        *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers.                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The multiplier must fit in a signed integer (although it isn't a signed value). *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Unsigned_Mult_Int(digit * prod, const digit * multiplicand, short multiplier, int precision)\n{\n\tconst unsigned short * m2 = (const unsigned short *)multiplicand;\n\tunsigned short * pr = (unsigned short *)prod;\n\tunsigned long carry = 0;\n\tfor (int i = 0; i < precision*2; ++i) {\n\t\tunsigned long p = (((unsigned long)multiplier) * *m2) + carry;;\n\t\t*pr = (unsigned short) p;\n\t\tcarry = p >> 16;\n\t\tm2++;\n\t\tpr++;\n\t}\n\n\t/* Add carry to the next higher word of product / dividend */\n//\t*pr += (unsigned short)carry;\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * XMP_Signed_Mult_Int -- Multiply an MP number by a signed simple integer.                    *\n *                                                                                             *\n *    This will multiply the specified integer with the MP number. It is a much faster         *\n *    multiply than when multiplying two MP numbers.                                           *\n *                                                                                             *\n * INPUT:   prod        -- Pointer to the product MP number.                                   *\n *                                                                                             *\n *          multiplicand-- Pointer to the MP number that serves as the multiplicand.           *\n *                                                                                             *\n *          multiplier  -- The simple integral integer used as the multiplier.                 *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The multiplier must fist within a signed short integer.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Signed_Mult_Int(digit * prod, const digit * multiplicand, signed short multiplier, int precision)\n{\n\tif (XMP_Is_Negative(multiplicand, precision)) {\n\t\tdigit abs_multiplicand[MAX_UNIT_PRECISION];\n\t\tXMP_Move(abs_multiplicand, multiplicand, precision);\n\t\tXMP_Neg(abs_multiplicand, precision);\n\n\t\tif (multiplier < 0) {\n\t\t\tmultiplier = (signed short)-multiplier;\n\n\t\t\tXMP_Unsigned_Mult_Int(prod, abs_multiplicand, multiplier, precision);\n\t\t} else {\n\t\t\tXMP_Unsigned_Mult_Int(prod, abs_multiplicand, multiplier, precision);\n\t\t\tXMP_Neg(prod, precision);\n\t\t}\n\t} else {\n\t\tif (multiplier < 0) {\n\t\t\tmultiplier = (signed short)-multiplier;\n\n\t\t\tXMP_Unsigned_Mult_Int(prod, multiplicand, multiplier, precision);\n\t\t\tXMP_Neg(prod, precision);\n\t\t} else {\n\t\t\tXMP_Unsigned_Mult_Int(prod, multiplicand, multiplier, precision);\n\t\t}\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * XMP_Signed_Mult -- A signed multiply between two MP numbers.                                *\n *                                                                                             *\n *    This routine will perform a multiply between two signed MP numbers.                      *\n *                                                                                             *\n * INPUT:   prod        -- Pointer to the product MP number buffer.                            *\n *                                                                                             *\n *          multiplicand-- Pointer to the multiplicand MP number.                              *\n *                                                                                             *\n *          multiplier  -- Pointer to the multiplier MP number.                                *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This is not a very fast routine.                                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Signed_Mult(digit * prod, const digit * multiplicand, const digit * multiplier, int precision)\n{\n\tif (XMP_Is_Negative(multiplicand, precision)) {\n\t\tdigit abs_multiplicand[MAX_UNIT_PRECISION];\n\t\tXMP_Move(abs_multiplicand, multiplicand, precision);\n\t\tXMP_Neg(abs_multiplicand, precision);\n\n\t\tif (XMP_Is_Negative(multiplier, precision)) {\n\t\t\tdigit abs_multiplier[MAX_UNIT_PRECISION];\n\t\t\tXMP_Move(abs_multiplier, multiplier, precision);\n\t\t\tXMP_Neg(abs_multiplier, precision);\n\n\t\t\tXMP_Unsigned_Mult(prod, abs_multiplicand, abs_multiplier, precision);\n\t\t} else {\n\t\t\tXMP_Unsigned_Mult(prod, abs_multiplicand, multiplier, precision);\n\t\t\tXMP_Neg(prod, precision);\n\t\t}\n\t} else {\n\t\tif (XMP_Is_Negative(multiplier, precision)) {\n\t\t\tdigit abs_multiplier[MAX_UNIT_PRECISION];\n\t\t\tXMP_Move(abs_multiplier, multiplier, precision);\n\t\t\tXMP_Neg(abs_multiplier, precision);\n\n\t\t\tXMP_Unsigned_Mult(prod, multiplicand, abs_multiplier, precision);\n\t\t\tXMP_Neg(prod, precision);\n\t\t} else {\n\t\t\tXMP_Unsigned_Mult(prod, multiplicand, multiplier, precision);\n\t\t}\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * XMP_Unsigned_Div_Int -- Perform a short integer divide into an MP number.                   *\n *                                                                                             *\n *    This routine performs a fast divide of the specified MP dividend by a simple             *\n *    short integer. The division is an UNSIGNED division however.                             *\n *                                                                                             *\n * INPUT:   quotient    -- Pointer to the MP number buffer where the quotient will go.         *\n *                                                                                             *\n *          dividend    -- Pointer to the MP number that serves as the dividend.               *\n *                                                                                             *\n *          divisor     -- The simple signed short integer that serves as the divisor.         *\n *                                                                                             *\n *          precision   -- The precision that is used by the MP numbers involved.              *\n *                                                                                             *\n * OUTPUT:  Returns with the remainder of the division.                                        *\n *                                                                                             *\n * WARNINGS:   This is an UNSIGNED divide even.                                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned short XMP_Unsigned_Div_Int(digit * quotient, digit const * dividend, unsigned short divisor, int precision)\n{\n\tif (!divisor) return 0;\t\t/* zero divisor means divide error */\n\n\tunsigned short remainder = 0;\n\n\tXMP_Init(quotient, 0, precision);\n\n\tint total_bit_count = XMP_Count_Bits(dividend, precision);\n\tint digit_precision = XMP_Bits_To_Digits(total_bit_count);\n\tdigit const * dividend_ptr = dividend + (digit_precision-1);\n\n\tif (!digit_precision) return(0);\n\n\tdigit high_bit_mask = XMP_Bits_To_Mask(total_bit_count);\n\tdigit * quotient_ptr = quotient + (digit_precision-1);\n\n\twhile (total_bit_count--) {\n\t\tremainder <<= 1;\n\n\t\tif ((*dividend_ptr) & high_bit_mask) remainder++;\n\n\t\tif (remainder >= divisor) {\n\t\t\tremainder -= divisor;\n\t\t\t*quotient_ptr |= high_bit_mask;\n\t\t}\n\n\t\thigh_bit_mask >>= 1;\n\t\tif (!high_bit_mask) {\n\t\t\thigh_bit_mask = UPPER_MOST_BIT;\n\t\t\t--dividend_ptr;\n\t\t\t--quotient_ptr;\n\t\t}\n\t}\n\n\treturn(remainder);\n}\n\n\n/***********************************************************************************************\n * XMP_Unsigned_Div -- Unsigned divide of one MP number into another.                          *\n *                                                                                             *\n *    This will perform the (dog slow) divide of one MP number into another. Because of the    *\n *    slowness of this routine, both the quotient and the remainder are available as a         *\n *    result of the operation.                                                                 *\n *                                                                                             *\n * INPUT:   remainder   -- Pointer to the MP buffer that will hold the remainder of the divide.*\n *                                                                                             *\n *          quotient    -- Pointer to the MP buffer that will hold the quotient of the divide. *\n *                                                                                             *\n *          dividend    -- The MP dividend (numerator) number.                                 *\n *                                                                                             *\n *          divisor     -- The MP divisor (denominator) number.                                *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This is very slow.                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Unsigned_Div(digit * remainder, digit * quotient, digit const * dividend, digit const * divisor, int precision)\n{\n\t// check for divide by zero.\n\tif (XMP_Test_Eq_Int(divisor, 0, precision)) return(-1);\n\n\tXMP_Init(remainder, 0, precision);\n\tXMP_Init(quotient, 0, precision);\n\n\tint total_bit_count = XMP_Count_Bits(dividend, precision);\n\tint digit_precision = XMP_Bits_To_Digits(total_bit_count);\n\tif (!digit_precision) return(0);\n\n\tdigit const * dividend_ptr = dividend + (digit_precision-1);\n\tdigit * quotient_ptr = quotient + (digit_precision-1);\n\n\tdigit high_bit_mask = XMP_Bits_To_Mask(total_bit_count);\n\twhile (total_bit_count--) {\n\t\tXMP_Shift_Left_Bits(remainder, 1, precision);\n\n\t\tif (((*dividend_ptr) & high_bit_mask) != 0) {\n\t\t\tXMP_Inc(remainder, precision);\n\t\t}\n\n\t\tif (XMP_Compare(remainder, divisor, precision) >= 0) {\n\t\t\tXMP_Sub(remainder, remainder, divisor, 0, precision);\n\t\t\t*quotient_ptr |= high_bit_mask;\n\t\t}\n\n\t\thigh_bit_mask >>= 1;\n\t\tif (!high_bit_mask) {\n\t\t\thigh_bit_mask = UPPER_MOST_BIT;\n\t\t\tdividend_ptr--;\n\t\t\tquotient_ptr--;\n\t\t}\n\n\t}\n\treturn 0;\n}\n\n\n/***********************************************************************************************\n * XMP_Signed_Div -- Signed divide of one MP number into another.                              *\n *                                                                                             *\n *    This will perform a signed divide (very very slow) of one MP number into another.        *\n *    Because of the slow nature of this routine, both the quotient and the remainder are      *\n *    available as results.                                                                    *\n *                                                                                             *\n * INPUT:   remainder   -- Pointer to the buffer that will hold the remainder of the divide.   *\n *                                                                                             *\n *          quotient    -- Pointer to the buffer that will hold the quotient of the divide.    *\n *                                                                                             *\n *          dividend    -- The dividend (numerator) MP number.                                 *\n *                                                                                             *\n *          divisor     -- The divisor (denominator) MP number.                                *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This is very very slow.                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Signed_Div(digit * remainder, digit * quotient, digit const * dividend, digit const * divisor, int precision)\n{\n\tbool negative = false;\n\n\tdigit scratch_dividend[MAX_UNIT_PRECISION];\n\tXMP_Move(scratch_dividend, dividend, precision);\n\n\tdigit scratch_divisor[MAX_UNIT_PRECISION];\n\tXMP_Move(scratch_divisor, divisor, precision);\n\n\tif (XMP_Is_Negative(scratch_dividend, precision)) {\n\t\tXMP_Neg(scratch_dividend, precision);\n\t\tnegative = !negative;\n\t}\n\n\tif (XMP_Is_Negative(scratch_divisor, precision)) {\n\t\tXMP_Neg(scratch_divisor, precision);\n\t\tnegative = !negative;\n\t}\n\n\tXMP_Unsigned_Div(remainder, quotient, scratch_dividend, scratch_divisor, precision);\n\n\tif (negative) {\n\t\tXMP_Neg(quotient, precision);\n\t\tif (!XMP_Test_Eq_Int(remainder, 0, precision)) {\n\t\t\tXMP_Dec(quotient, precision);\n\t\t\tXMP_Neg(remainder, precision);\n\t\t\tXMP_Add(remainder, remainder, scratch_divisor, 0, precision);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Inverse_A_Mod_B -- Inverts and performs modulus on an MP number.                        *\n *                                                                                             *\n *    This is a utility routine that will perform an inverse on the MP number and then         *\n *    perform a modulus of that number by another MP number. There are some algorithms that    *\n *    require this process.                                                                    *\n *                                                                                             *\n * INPUT:   result      -- Pointer to the MP buffer that will hold the result.                 *\n *                                                                                             *\n *          number      -- The MP number that will be inverted then modulo-ized.               *\n *                                                                                             *\n *          modulus     -- The MP number to modulus the first number by.                       *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Inverse_A_Mod_B(digit * result, digit const * number, digit const * modulus, int precision)\n{\n\tdigit g[3][MAX_UNIT_PRECISION];\n\tXMP_Move(g[0], modulus, precision);\n\tXMP_Move(g[1], number, precision);\n\n\tdigit v[3][MAX_UNIT_PRECISION];\n\tXMP_Init(v[0], 0, precision);\n\tXMP_Init(v[1], 1, precision);\n\n\tdigit y[MAX_UNIT_PRECISION];\n\n\tint i;\n\tfor (i = 1; !XMP_Test_Eq_Int(g[i%3], 0, precision); i++) {\n\t\tXMP_Unsigned_Div(g[(i+1)%3], y, g[(i-1)%3], g[i%3], precision);\n\n\t\tXMP_Unsigned_Mult(result, v[i%3], y, precision);\n\t\tXMP_Sub(v[(i+1)%3], v[(i-1)%3], result, 0, precision);\n\t}\n\n\tif (XMP_Is_Negative(v[(i-1)%3], precision)) {\n\t\tXMP_Add(v[(i-1)%3], v[(i-1)%3], modulus, 0, precision);\n\t}\n\n\tXMP_Move(result, v[(i-1)%3], precision);\n}\n\n\n/***********************************************************************************************\n * XMP_Reciprocal -- Compute the reciprocal (inverse) of the MP number.                        *\n *                                                                                             *\n *    Use this routine to determine the inverse of the specified MP number. The inverse is     *\n *    defined as 1/number.                                                                     *\n *                                                                                             *\n * INPUT:   result   -- Pointer to the result MP number buffer.                                *\n *                                                                                             *\n *          number   -- The number to be inverted.                                             *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Reciprocal(digit * quotient, const digit * divisor, int precision)\n{\n\tdigit remainder[MAX_UNIT_PRECISION];\n\n\tif (XMP_Test_Eq_Int(divisor, 0, precision)) return -1;\t\t/* zero divisor means divide error */\n\n\tXMP_Init(remainder, 0, precision);\n\tXMP_Init(quotient, 0, precision);\n\n\t/* normalize and compute number of bits in quotient first */\n\tunsigned total_bit_count = XMP_Count_Bits(divisor, precision);\n\tdigit high_bit_mask = XMP_Bits_To_Mask(total_bit_count + 1);\t/* bitmask within a single digit */\n\tint sub_precision = XMP_Bits_To_Digits(total_bit_count + 1);\n\n\tXMP_Set_Bit(remainder, total_bit_count - 1);\n\n\t/* rescale quotient to precision of divisor bits */\n\tquotient += sub_precision-1;\n\n\twhile (total_bit_count--) {\n\t\tXMP_Shift_Left_Bits(remainder, 1, precision);\n\t\tif (XMP_Compare(remainder, divisor, precision) >= 0) {\n\t\t\tXMP_Sub(remainder, remainder, divisor, 0, precision);\n\t\t\t*quotient |= high_bit_mask;\n\t\t}\n\n\t\thigh_bit_mask >>= 1;\n\t\tif (!high_bit_mask) {\n\t\t\thigh_bit_mask = UPPER_MOST_BIT;\n\t\t\tquotient--;\n\t\t}\n\t}\n\n\tXMP_Init(remainder, 0, precision);\n\treturn 0;\n}\n\n\n/***********************************************************************************************\n * XMP_Decode_ASCII -- Convert ASCII into an MP number.                                        *\n *                                                                                             *\n *    This routine will convert a supplied ASCII string into an MP number.                     *\n *                                                                                             *\n * INPUT:   str      -- Pointer to the ASCII string that will be converted.                    *\n *                                                                                             *\n *          mpn      -- Pointer to the MP number buffer that will be initialized.              *\n *                                                                                             *\n *          precision -- The precision of the MP number.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Decode_ASCII(char const * str, digit * mpn, int precision)\n{\n\t/*\n\t**\tInitialize the multiprecision number to zero. From this point\n\t**\tonward, this object can be manipulated as a regular number.\n\t**\tThis is, in fact, what is done as the ascii string is parsed\n\t**\tinto a working number.\n\t*/\n\tXMP_Init(mpn, 0, precision);\n\n\t/*\n\t**\tNo string or zero length is considered '0'.\n\t*/\n\tif (!str) return;\n\tint i = strlen(str);\n\tif (i == 0) return;\n\n\tunsigned short radix;\t\t/* base 2-16 */\n\tswitch (toupper(str[i-1])) {\t\t/* classify radix select suffix character */\n\t\tcase '.':\n\t\t\tradix = 10;\n\t\t\tbreak;\n\n\t\tcase 'H':\n\t\t\tradix = 16;\n\t\t\tbreak;\n\n\t\tcase 'O':\n\t\t\tradix = 8;\n\t\t\tbreak;\n\n\t\tcase 'B':\t\t\t/* caution! 'b' is a hex digit! */\n\t\t\tradix = 2;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tradix = 10;\n\t\t\tbreak;\n\t}\n\n\tbool minus = (*str == '-');\n\tif (minus) str++;\n\n\tdigit c;\n\twhile ((c = (unsigned char)*str++) != 0) {\n\t\tif (c == ',') continue;\t\t/* allow commas in number */\n\n\t\t/*\n\t\t**\tIf not a hexadecimal (highest base) digit then it is\n\t\t**\tclearly the end of the processable string. Bail out\n\t\t**\tof the scan loop.\n\t\t*/\n\t\tif (!isxdigit((char)c)) break;\n\n\t\t/*\n\t\t**\tConvert the character into an integer number 0 through 15.\n\t\t*/\n\t\tif (isdigit((char)c)) {\n\t\t\tc -= '0';\n\t\t} else {\n\t\t\tc = (unsigned char)(toupper((char)c) - 'A') + 10;\n\t\t}\n\n\t\t/*\n\t\t**\tIf the integer digit is greater than the radix, then we\n\t\t**\tknow that further processing should stop. This is the\n\t\t**\tend of the number string.\n\t\t*/\n\t\tif (c >= radix) break;\t\t/* scan terminated by any non-digit */\n\n\n\t\tXMP_Unsigned_Mult_Int(mpn, mpn, radix, precision);\n\t\tXMP_Add_Int(mpn, mpn, c, 0, precision);\n\t}\n\tif (minus) {\n\t\tXMP_Neg(mpn, precision);\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Hybrid_Mul -- Special hybrid short multiply (with carry).                               *\n *                                                                                             *\n *    Multiply the single-word multiplier times the multiprecision integer                     *\n *    in multiplicand, accumulating result in prod.  The resulting                             *\n *    multiprecision prod will be 1 word longer than the multiplicand.                         *\n *    multiplicand is double precision words long.  We add into prod, so caller                *\n *    should zero it out first.  For best results, this time-critical                          *\n *    function should be implemented in assembly.                                              *\n *    NOTE:  Unlike other functions in the multiprecision arithmetic                           *\n *    library, both multiplicand and prod are pointing at the LSB,                             *\n *    regardless of byte order of the machine.  On an 80x86, this makes                        *\n *    no difference.  But if this assembly function is implemented                             *\n *    on a 680x0, it becomes important.                                                        *\n *                                                                                             *\n *    Note that this has been modified from the previous version to allow                      *\n *    better support for Smith's modmult:                                                      *\n *         The final carry bit is added to the existing product                                *\n *         array, rather than simply stored.                                                   *\n *                                                                                             *\n * INPUT:   prod     -- Pointer to the product MP number buffer.                               *\n *                                                                                             *\n *          multiplicand   -- Pointer to the multiplicand MP number.                           *\n *                                                                                             *\n *          multiplier  -- The short integer used as the multiplier.                           *\n *                                                                                             *\n *          precision   -- The precision of the MP number used.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The carry (if any) is added into the integer one beyond the end of the          *\n *             product buffer.                                                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Hybrid_Mul(unsigned short * prod, unsigned short * multiplicand, unsigned short multiplier, int precision)\n{\n\tunsigned long carry = 0;\n\tfor (int i = 0; i < precision; ++i) {\n\t\tunsigned long p = (unsigned long)multiplier * *multiplicand++;\n\t\tp += *prod + carry;\n\t\t*prod++ = (unsigned short) p;\n\t\tcarry = p >> 16;\n\t}\n\n\t/* Add carry to the next higher word of product / dividend */\n\t*prod += (unsigned short) carry;\n}\n\n\n/***********************************************************************************************\n * XMP_Double_Mul -- Double precision MP multiply.                                             *\n *                                                                                             *\n *    This will perform a double precision multiply of MP numbers. This means that the product *\n *    will be twice the precision of the components.                                           *\n *                                                                                             *\n * INPUT:   prod        -- Pointer to the result buffer. This buffer must be able to hold      *\n *                         double the precision specified.                                     *\n *                                                                                             *\n *          multiplicand-- Pointer to the multiplicand MP number.                              *\n *                                                                                             *\n *          multiplier  -- Pointer to the multiplier number.                                   *\n *                                                                                             *\n *          precision   -- The precision of the two component MP numbers.                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure the product buffer can hold a double precision number.                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Double_Mul(digit * prod, const digit * multiplicand, const digit * multiplier, int precision)\n{\n\t/*\n\t**\tClear out the double precision product buffer.\n\t*/\n\tXMP_Init(prod, 0, precision*2);\n\n\tconst unsigned short * multiplier_ptr = (const unsigned short *) multiplier;\n\tunsigned short * product_ptr = (unsigned short *) prod;\n\n\t// Multiply multiplicand by each word in multiplier, accumulating prod.\n\tfor (int i = 0; i < precision*2; ++i) {\n\t\tXMP_Hybrid_Mul(product_ptr++, (unsigned short *)multiplicand, *multiplier_ptr++, precision*2);\n\t}\n}\n\n\n\nstatic int _modulus_shift;\t\t\t\t\t\t\t\t\t// number of bits for recip scaling\nstatic unsigned short _reciprical_high_digit;\t\t// MSdigit of scaled recip\nstatic unsigned short _reciprical_low_digit;\t\t\t// LSdigit of scaled recip\n\nstatic int _modulus_sub_precision;\t\t\t\t\t\t//\tlength of modulus in MULTUNITs\nstatic int _modulus_bit_count;\t\t\t\t\t\t\t//\tnumber of modulus significant bits\nstatic digit _scratch_modulus[MAX_UNIT_PRECISION];\t// modulus\n\n// The double precision modulus staging buffer.\nstatic digit _double_staging_number[MAX_UNIT_PRECISION * 2 + 2];\n\n// most significant digits of modulus.\nstatic digit _mod_quotient[4];\nstatic digit _mod_divisor[4];\n\n\n/***********************************************************************************************\n * XMP_Prepare_Modulus -- Prepare globals for modulus operation.                               *\n *                                                                                             *\n *    Calculate the reciprocal of modulus with a precision of two MULTUNITs.                   *\n *    Assumes that precision has already been adjusted to the                                  *\n *    size of the modulus, plus SLOP_BITS.                                                     *\n *                                                                                             *\n *    Note: This routine was designed to work with large values and                            *\n *    doesn't have the necessary testing or handling to work with a                            *\n *    modulus having less than three significant digits.  For such cases,                      *\n *    the separate multiply and modulus routines can be used.                                  *\n *                                                                                             *\n * INPUT:   modulus  -- Pointer to the modulus number.                                         *\n *                                                                                             *\n *          precision-- The precision of the modulus number.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Prepare_Modulus(const digit * n_modulus, int precision)\n{\n\tXMP_Move(_scratch_modulus, n_modulus, precision);\n\n\t_modulus_bit_count = XMP_Count_Bits(_scratch_modulus, precision);\n\t_modulus_sub_precision = (_modulus_bit_count + 16 - 1) / 16;\n\n\t/*\n\t**\tKeep 2*16 bits in _mod_divisor.\n\t** This will (normally) result in a reciprocal of 2*16+1 bits.\n\t*/\n\tint sub_precision = XMP_Significance(_scratch_modulus, precision);\t// significant digits in modulus\n\tXMP_Move(_mod_divisor, &_scratch_modulus[sub_precision-2], 2);\n\t_modulus_shift = XMP_Count_Bits(_mod_divisor, 2) - 2 * 16;\n\tXMP_Shift_Right_Bits(_mod_divisor, _modulus_shift, 2);\n\n\tXMP_Reciprocal(_mod_quotient, _mod_divisor, 2);\n\tXMP_Shift_Right_Bits(_mod_quotient, 1, 2);\n\n\t/* Reduce to:   0 < _modulus_shift <= 16 */\n\t_modulus_shift = ((_modulus_shift + (16 - 1)) % 16) + 1;\n\n\t/* round up */\n\tXMP_Inc(_mod_quotient, 2);\n\tif (XMP_Count_Bits(_mod_quotient, 2) > 2 * 16) {\n\t\tXMP_Shift_Right_Bits(_mod_quotient, 1, 2);\n\t\t_modulus_shift--;\t\t/* now  0 <= _modulus_shift <= 16 */\n\t}\n\tunsigned short * mpm = (unsigned short *) _mod_quotient;\n\t_reciprical_low_digit = *mpm++;\n\t_reciprical_high_digit = *mpm;\n\n\treturn 0;\n}\n\n\n/***********************************************************************************************\n * XMP_Mod_Mult -- Perform a multiply - modulus operation.                                     *\n *                                                                                             *\n *    This routine will combine a multiply and a modulus operation. This takes advantage of    *\n *    a tremendous speed advantage possible if these two processes are combined rather than    *\n *    being performed separately.                                                              *\n *                                                                                             *\n * INPUT:   prod        -- Pointer to the MP buffer that will hold the result.                 *\n *                                                                                             *\n *          multiplicand-- The number to multiply.                                             *\n *                                                                                             *\n *          multiplier  -- The number to multiply by.                                          *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The modulus must already have been prepared by the routine XMP_Prepare_Modulus. *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Mod_Mult(digit * prod, const digit * multiplicand, const digit * multiplier, int precision)\n{\n\tXMP_Double_Mul(_double_staging_number, multiplicand, multiplier, precision);\n\n\tint double_precision = precision * 2 + 1;\n\n\t_double_staging_number[double_precision - 1] = 0;\t/* leading 0 digit */\n\n\t/*\n\t**\tWe now start working with MULTUNITs.\n\t**\tDetermine the most significant MULTUNIT of the product so we don't\n\t**\thave to process leading zeros in our divide loop.\n\t*/\n\tint dmi = XMP_Significance(_double_staging_number, double_precision) * 2;\t//\tnumber of significant MULTUNITs in product\n\n\tif (dmi >= _modulus_sub_precision) {\n\n\t\t/* Make dividend negative.  This allows the use of mp_single_mul to\n\t\t** \"subtract\" the product of the modulus and the trial divisor\n\t\t** by actually adding to a negative dividend.\n\t\t** The one's complement of the dividend is used, since it causes\n\t\t** a zero value to be represented as all ones.  This facilitates\n\t\t** testing the result for possible overflow, since a sign bit\n\t\t** indicates that no adjustment is necessary, and we should not\n\t\t** attempt to adjust if the result of the addition is zero.\n\t\t*/\n\t\tXMP_Inc(_double_staging_number, double_precision);\n\t\tXMP_Neg(_double_staging_number, double_precision);\n\n\t\tint nqd = dmi + 1 - _modulus_sub_precision; \t// number of quotient digits remaining to be generated\n\n\t\t/* Set msb, lsb, and normal ptrs of dividend */\n\t\tunsigned short * dmph = ((unsigned short *)_double_staging_number) + dmi + 1;\t// points to one higher than precision would indicate\n\t\tunsigned short * dmpl = dmph - _modulus_sub_precision;\n\n\t\t/*\n\t\t** Divide loop.\n\t\t** Each iteration computes the next quotient MULTUNIT digit, then\n\t\t** multiplies the divisor (modulus) by the quotient digit and adds\n\t\t** it to the one's complement of the dividend (equivalent to\n\t\t** subtracting).  If the product was greater than the remaining dividend,\n\t\t** we get a non-negative result, in which case we subtract off the\n\t\t** modulus to get the proper negative remainder.\n\t\t*/\n\t\tfor (; nqd; nqd--) {\n\t\t\t--dmph;\n\t\t\t--dmpl;\n\n\t\t\tunsigned short q = mp_quo_digit(dmph);\t// trial quotient digit\n\t\t\tif (q > 0) {\n\t\t\t\tXMP_Hybrid_Mul(dmpl, (unsigned short *)_scratch_modulus, q, precision*2);\n\n\t\t\t\t/* Perform correction if q too large.\n\t\t\t\t**  This rarely occurs.\n\t\t\t\t*/\n\t\t\t\tif (!(*dmph & SEMI_UPPER_MOST_BIT)) {\n\t\t\t\t\tunsigned short * dmp = dmpl;\n\t\t\t\t\tif (XMP_Sub((unsigned long *)dmp, (unsigned long *)dmp, _scratch_modulus, false, precision)) {\n\t\t\t\t\t\t(*dmph)--;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* d contains the one's complement of the remainder. */\n\t\tXMP_Neg(_double_staging_number, precision);\n\t\tXMP_Dec(_double_staging_number, precision);\n\t}\n\n\tXMP_Move(prod, _double_staging_number, precision);\n\treturn (0);\n}\n\n\n/***********************************************************************************************\n * XMP_Mod_Mult_Clear -- Remove temporary values from memory.                                  *\n *                                                                                             *\n *    Smith's mp_modmult function leaves some internal arrays in memory,                       *\n *    so we have to call modmult_burn() at the end of mp_exponent_mod.                         *\n *    This is so that no cryptographically sensitive data is left in memory                    *\n *    after the program exits.                                                                 *\n *                                                                                             *\n * INPUT:   precision   -- The precision of the numbers involved.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Mod_Mult_Clear(int precision)\n{\n\tXMP_Init(_scratch_modulus, 0, precision);\n\tXMP_Init(_double_staging_number, 0, precision);\n\tXMP_Init(_mod_quotient, 0, ARRAY_SIZE(_mod_quotient));\n\tXMP_Init(_mod_divisor, 0, ARRAY_SIZE(_mod_divisor));\n\t_modulus_shift = _modulus_bit_count = 0;\n\t_reciprical_high_digit = _reciprical_low_digit = 0;\n\t_modulus_sub_precision = /*mutemp =*/ 0;\n}\n\n\n/*\n** The function mp_quo_digit is the heart of Smith's modulo reduction,\n** which uses a form of long division.  It computes a trial quotient\n** \"digit\" (MULTUNIT-sized digit) by multiplying the three most\n** significant MULTUNITs of the dividend by the two most significant\n** MULTUNITs of the reciprocal of the modulus.  Note that this function\n** requires that 16 * 2 <= sizeof(unsigned long).\n**\n** An important part of this technique is that the quotient never be\n** too small, although it may occasionally be too large.  This was\n** done to eliminate the need to check and correct for a remainder\n** exceeding the divisor.       It is easier to check for a negative\n** remainder.  The following technique rarely needs correction for\n** MULTUNITs of at least 16 bits.\n**\n** The following routine has two implementations:\n**\n** Parameter: dividend - points to the most significant MULTUNIT\n**      of the dividend.  Note that dividend actually contains the\n**      one's complement of the actual dividend value (see comments for\n**      XMP_Mod_Mult).\n**\n**  Return: the trial quotient digit resulting from dividing the first\n**      three MULTUNITs at dividend by the upper two MULTUNITs of the\n**      modulus.\n*/\nunsigned short mp_quo_digit(unsigned short * dividend)\n{\n\tunsigned long q, q0, q1, q2;\n\n\t/*\n\t* Compute the least significant product group.\n\t* The last terms of q1 and q2 perform upward rounding, which is\n\t* needed to guarantee that the result not be too small.\n\t*/\n\tq1 = (dividend[-2] ^ SEMI_MASK) * (unsigned long) _reciprical_high_digit + _reciprical_high_digit;\n\tq2 = (dividend[-1] ^ SEMI_MASK) * (unsigned long) _reciprical_low_digit + (1L << 16);\n\tq0 = (q1 >> 1) + (q2 >> 1) + 1;\n\n\t/*      Compute the middle significant product group.   */\n\tq1 = (dividend[-1] ^ SEMI_MASK) * (unsigned long) _reciprical_high_digit;\n\tq2 = (dividend[0] ^ SEMI_MASK) * (unsigned long) _reciprical_low_digit;\n\tq = (q0 >> 16) + (q1 >> 1) + (q2 >> 1) + 1;\n\n\t/*      Compute the most significant term and add in the others */\n\tq = (q >> (16 - 2)) + (((dividend[0] ^ SEMI_MASK) * (unsigned long) _reciprical_high_digit) << 1);\n\tq >>= _modulus_shift;\n\n\t/*      Prevent overflow and then wipe out the intermediate results. */\n\treturn (unsigned short) min(q, (unsigned long)(1L << 16) - 1);\n}\n\n\n/*\n** Russian peasant combined exponentiation/modulo algorithm.\n** Calls modmult instead of mult.\n** Computes:  expout = (expin**exponent) mod modulus\n** WARNING: All the arguments must be less than the modulus!\n*/\nint xmp_exponent_mod(digit * expout, const digit * expin, const digit * exponent_ptr, const digit * modulus, int precision)\n{\n\tdigit product[MAX_UNIT_PRECISION];\n\n\tXMP_Init(expout, 1, precision);\n\tif (XMP_Test_Eq_Int(exponent_ptr, 0, precision)) {\n\t\tif (XMP_Test_Eq_Int(expin, 0, precision)) {\n\t\t\treturn -1;\t\t/* 0 to the 0th power means return error */\n\t\t}\n\t\treturn 0;\t\t/* otherwise, zero exponent means expout is 1 */\n\t}\n\n\tif (XMP_Test_Eq_Int(modulus, 0, precision)) {\n\t\treturn -2;\t\t/* zero modulus means error */\n\t}\n\n\tif (XMP_Compare(expin, modulus, precision) >= 0) {\n\t\treturn -3;\t\t/* if expin >= modulus, return error */\n\t}\n\n\tif (XMP_Compare(exponent_ptr, modulus, precision) >= 0) {\n\t\treturn -4;\t\t/* if exponent >= modulus, return error */\n\t}\n\n\t/* set smallest optimum precision for this modulus */\n\tint limited_precision = XMP_Significance(modulus, precision);\n\n\tif (XMP_Prepare_Modulus(modulus, limited_precision)) {\n\t\treturn -5;\t\t/* unstageable modulus (STEWART algorithm) */\n\t}\n\n\t/* normalize and compute number of bits in exponent first */\n//\tint exp_precision = XMP_Significance(exponent_ptr, limited_precision);\n//\tif (!exp_precision) return(0);\n//\tint bits = XMP_Digits_To_Bits(exp_precision);\n//\texponent_ptr += (exp_precision-1);\n//\tdigit high_bit_mask = UPPER_MOST_BIT;\n//\twhile (! ((*exponent_ptr) & high_bit_mask)) {\n//\t\thigh_bit_mask >>= 1;\n//\t\tbits--;\n//\t}\n\n\tint total_bit_count = XMP_Count_Bits(exponent_ptr, limited_precision);\n\tint sub_precision = XMP_Bits_To_Digits(total_bit_count);\n\tif (!sub_precision) return(0);\n\tdigit high_bit_mask = XMP_Bits_To_Mask(total_bit_count);\n\texponent_ptr += (sub_precision-1);\n\n\t/* We can \"optimize out\" the first modsquare and modmult: */\n\ttotal_bit_count--;\t\t\t/* We know for sure at this point that bits>0 */\n\n\tXMP_Move(expout, expin, limited_precision);\n\n\thigh_bit_mask >>= 1;\n\tif (!high_bit_mask) {\n\t\thigh_bit_mask = UPPER_MOST_BIT;\n\t\texponent_ptr--;\n\t}\n\n\twhile (total_bit_count--) {\n\t\tXMP_Mod_Mult(product, expout, expout, limited_precision);\n\n\t\tif (((*exponent_ptr) & high_bit_mask)) {\n\t\t\tXMP_Mod_Mult(expout, product, expin, limited_precision);\n\t\t} else {\n\t\t\tXMP_Move(expout, product, limited_precision);\n\t\t}\n\n\t\thigh_bit_mask >>= 1;\n\t\tif (!high_bit_mask) {\n\t\t\thigh_bit_mask = UPPER_MOST_BIT;\n\t\t\texponent_ptr--;\n\t\t}\n\n\t}\n\n\tXMP_Init(product, 0, limited_precision);\n\tXMP_Mod_Mult_Clear(limited_precision);\t\t/* ask mp_modmult to also burn its own evidence */\n\n\treturn 0;\n}\n\n\n/***********************************************************************************************\n * memrev -- Reverse the byte order of the buffer specified.                                   *\n *                                                                                             *\n *    This routine will reverse the byte order in the buffer specified.                        *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that will be reversed.                           *\n *                                                                                             *\n *          length   -- The length of the buffer.                                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid memrev(char * buffer, size_t length)\n{\n\tchar * r2 = &(buffer[length - 1]);\n\twhile (buffer < r2) {\n\t\tchar b = *buffer;\n\t\t*buffer++ = *r2;\n\t\t*r2-- = b;\n\t}\n}\n\n\nint _USERENTRY pfunc(const void * pkey, const void * base)\n{\n\tif (*(unsigned short *)pkey < *(unsigned short *)base) return(-1);\n\tif (*(unsigned short *)pkey > *(unsigned short *)base) return(1);\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * XMP_Is_Small_Prime -- Determine if MP number is a small prime.                              *\n *                                                                                             *\n *    This routine will compare the MP number against all known small prime numbers. It will   *\n *    return true if a match was found.                                                        *\n *                                                                                             *\n * INPUT:   candidate   -- Pointer to MP number that is to be tested.                          *\n *                                                                                             *\n *          precision   -- The precision of the MP number specified.                           *\n *                                                                                             *\n * OUTPUT:  bool; Was the MP number a member of the small prime community?                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Is_Small_Prime(const digit * candidate, int precision)\n{\n\t/*\n\t**\tIf the number is too large for comparison to the known small primes table, then\n\t**\tbail immediately.\n\t*/\n\tif (XMP_Significance(candidate, precision) > 1) return(false);\n\tif (*candidate > primeTable[ARRAY_SIZE(primeTable)-1]) return false;\n\n\tunsigned long * ptr = (unsigned long *)bsearch(&candidate, &primeTable[0], ARRAY_SIZE(primeTable), sizeof(primeTable[0]), pfunc);\n\treturn(ptr != NULL);\n}\n\n\n/***********************************************************************************************\n * XMP_Small_Divisors_Test -- Perform the small divisors test on an MP number.                 *\n *                                                                                             *\n *    This test for primality will divide an MP number by the set of small primes. If any of   *\n *    these numbers divides evenly into the candidate number, then it is known that the        *\n *    candidate is NOT prime.                                                                  *\n *                                                                                             *\n * INPUT:   candidate   -- Pointer to the MP number that is to be tested.                      *\n *                                                                                             *\n *          precision   -- The precision of the MP number/                                     *\n *                                                                                             *\n * OUTPUT:  bool; Did the MP number pass the small divisors test?                              *\n *                                                                                             *\n * WARNINGS:   If the MP number passes, it doesn't mean that it is prime, just that is hasn't  *\n *             yet been proven to be not prime.                                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Small_Divisors_Test(const digit * candidate, int precision)\n{\n\tdigit quotient[MAX_UNIT_PRECISION];\n\n\tfor (unsigned i = 0; i < ARRAY_SIZE(primeTable); i++) {\n\t\tif (XMP_Unsigned_Div_Int(quotient, candidate, primeTable[i], precision) == 0) return(false);\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * XMP_Fermat_Test -- Performs Fermat's Little Theorem on an MP number.                        *\n *                                                                                             *\n *    This is a more expensive but thorough test for primality. The aggressiveness of this     *\n *    test can be controlled by the number of rounds specified. Four rounds is usually         *\n *    sufficient.                                                                              *\n *                                                                                             *\n * INPUT:   candidate   -- Pointer to the candidate MP number that is to be tested.            *\n *                                                                                             *\n *          rounds      -- The number of rounds to test the MP number (keep it small).         *\n *                                                                                             *\n *          precision   -- The precision of the MP number.                                     *\n *                                                                                             *\n * OUTPUT:  bool; Was the number not proven to be not prime. A FALSE means that it is not      *\n *                prime. A TRUE means that it might be prime.                                  *\n *                                                                                             *\n * WARNINGS:   This takes a bit of time. The time it takes is directly controlled by the       *\n *             number of rounds specified. Keep the number of rounds as small as possible.     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Fermat_Test(const digit * candidate_prime, unsigned rounds, int precision)\n{\n\tassert(rounds < ARRAY_SIZE(primeTable));\n\n\tdigit term[MAX_UNIT_PRECISION];\n\tXMP_Move(term, candidate_prime, precision);\n\tXMP_Dec(term, precision);\n\n\tfor (unsigned i = 0; i < rounds; i++) {\n\t\t// if ((x**(p-1)) mod p) != 1, then p is not prime\n\t\tdigit result[MAX_UNIT_PRECISION];\n\n\t\tdigit small_prime[MAX_UNIT_PRECISION];\n\t\tXMP_Init(small_prime, primeTable[i], precision);\n\n\t\txmp_exponent_mod(result, small_prime, term, candidate_prime, precision);\n\n\t\tif (!XMP_Test_Eq_Int(result, 1, precision)) return(false);\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * XMP_Rabin_Miller_Test -- Performs the Rabin Miller test for primality.                      *\n *                                                                                             *\n *    This test for primality is even more expensive the Fermat's Little Theorem. It doesn't   *\n *    prove that a number is prime, but it can prove that it is not prime.                     *\n *                                                                                             *\n * INPUT:   rng      -- Reference to to a random number generator.                             *\n *                                                                                             *\n *          candidate-- Pointer to the candidate MP number that is to be tested.               *\n *                                                                                             *\n *          rounds   -- The number of test rounds to perform.                                  *\n *                                                                                             *\n *          precision-- The precision of the MP number specified.                              *\n *                                                                                             *\n * OUTPUT:  bool; Was the number not proven to be not prime? A FALSE means that the number is  *\n *          not prime. A TRUE means that it might be.                                          *\n *                                                                                             *\n * WARNINGS:   This routine takes a long time. Use as few rounds as possible.                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Rabin_Miller_Test(Straw & rng, digit const * w, int rounds, int precision)\n{\n\tdigit wminus1[MAX_UNIT_PRECISION];\n\tXMP_Sub_Int(wminus1, w, 1, 0, precision);\n\n\tunsigned maxbitprecision = precision * sizeof(digit) * 8;\n\tunsigned a;\n\tfor (a = 0; a < maxbitprecision; a++) {\n\t\tif (XMP_Test_Bit(wminus1, a)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tdigit m[MAX_UNIT_PRECISION];\n\tXMP_Move(m, wminus1, precision);\n\tXMP_Shift_Right_Bits(wminus1, a, precision);\n\n\tfor (int i = 0; i < rounds; i++) {\n\t\tdigit b[MAX_UNIT_PRECISION];\n\t\tdigit temp[MAX_UNIT_PRECISION];\n\t\tXMP_Init(temp, 2, precision);\n\t\tXMP_Randomize(b, rng, temp, wminus1, precision);\n\n\t\tdigit z[MAX_UNIT_PRECISION];\n\t\txmp_exponent_mod(z, b, m, w, precision);\n\n\t\tif (XMP_Test_Eq_Int(z, 1, precision) || XMP_Compare(z, wminus1, precision) == 0) {\n\t\t\tcontinue;   // passes this round\n\t\t}\n\n\t\tint j;\n\t\tfor (j = 1; j < a; j++) {\n\t\t\tdigit t2[MAX_UNIT_PRECISION];\n\t\t\txmp_exponent_mod(t2, z, temp, w, precision);\n\n\t\t\tif (XMP_Compare(t2, wminus1, precision) == 0) {\n\t\t\t\tbreak;  // passed this round\n\t\t\t}\n\t\t\tif (XMP_Test_Eq_Int(z, 1, precision)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\tif (j == a) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n\n/***********************************************************************************************\n * XMP_Randomize -- Generate a random MP number.                                               *\n *                                                                                             *\n *    This routine will generate a random MP number with the number of bits precision          *\n *    specified. This is the starting point for generating large random prime numbers. It is   *\n *    very important that the random number generated is truly random.                         *\n *                                                                                             *\n * INPUT:   result   -- Pointer to the buffer that will hold the MP number.                    *\n *                                                                                             *\n *          rng      -- Reference to a random number generator.                                *\n *                                                                                             *\n *          total_bits-- The number of bits precision that the MP number must have.            *\n *                                                                                             *\n *          precision-- The precision of the MP number to be generated (maximum)               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Randomize(digit * result, Straw & rng, int total_bits, int precision)\n{\n\tassert(XMP_Bits_To_Digits(total_bits) <= MAX_UNIT_PRECISION);\n\n\ttotal_bits = min(total_bits, precision * 32);\n\n\tunsigned nbytes = total_bits/8 + 1;\n\n\tXMP_Init(result, 0, precision);\n\trng.Get(result, nbytes);\n\n\t((unsigned char *)result)[nbytes-1] &= (unsigned char)(~((~0) << (total_bits % 8)));\n}\n\n\n/***********************************************************************************************\n * XMP_Randomize -- Generate a random MP number between the boundaries specified.              *\n *                                                                                             *\n *    This routine will generate a random MP number but it will be bounded by the minimum      *\n *    and maximum MP numbers specified.                                                        *\n *                                                                                             *\n * INPUT:   result      -- Pointer to the MP buffer that will hold the result.                 *\n *                                                                                             *\n *          rng         -- Reference to a random number generator to use.                      *\n *                                                                                             *\n *          minval      -- Minimum value allowed.                                              *\n *                                                                                             *\n *          maxval      -- Maximum value allowed.                                              *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Randomize(digit * result, Straw & rng, digit const * minval, digit const * maxval, int precision)\n{\n\tdigit range[MAX_UNIT_PRECISION];\n\tXMP_Sub(range, maxval, minval, 0, precision);\n\tunsigned int bit_count = XMP_Count_Bits(range, precision);\n\tdo\t{\n\t\tXMP_Randomize(result, rng, bit_count, precision);\n\t} while (XMP_Compare(result, range, precision) > 0);\n\n\tXMP_Add(result, result, minval, 0, precision);\n}\n\n\n/***********************************************************************************************\n * XMP_Is_Prime -- Determine if the specified MP number is prime.                              *\n *                                                                                             *\n *    This routine will perform some checks to try and determine if the specified MP number    *\n *    is a prime number. The result of this test is not 100% conclusive, but it is pretty      *\n *    darn close.                                                                              *\n *                                                                                             *\n * INPUT:   prime    -- Pointer to a candidate number to test for primality.                   *\n *                                                                                             *\n *          precision-- The precision of the MP number specified.                              *\n *                                                                                             *\n * OUTPUT:  bool; Was the number not proven to be not prime? If FALSE, then the number is      *\n *          not prime. If TRUE, then it might be.                                              *\n *                                                                                             *\n * WARNINGS:   This can take a very very very very very long time. Especially for the larger   *\n *             numbers.                                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Is_Prime(digit const * prime, int precision)\n{\n\t/*\n\t**\tEven numbers are ALWAYS not prime.\n\t*/\n\tif (!(*prime & 0x01)) return(false);\n\n\t/*\n\t**\tCompare the prime number against the exhaustive list of prime\n\t**\tnumbers below 14 bits in size. If it finds a match, then\n\t**\tthe number is a known prime.\n\t*/\n\tif (XMP_Is_Small_Prime(prime, precision)) return(true);\n\n\t/*\n\t**\tPerform the small divisors test. This is not exhaustive, but\n\t**\twill weed out a large percentage of non-prime numbers.\n\t*/\n\tif (!XMP_Small_Divisors_Test(prime, precision)) return(false);\n\n\t/*\n\t**\tPerform Fermat's Little Theorum on the candidate prime. Run\n\t**\tthe theorum for several rounds to ensure a high degree of\n\t**\tconfidence.\n\t*/\n\tif (!XMP_Fermat_Test(prime, 2, precision)) return(false);\n\n\t/*\n\t**\tIf all of the above tests have not confirmed primality nor\n\t**\tconfirmed non-primality, presume that the number must be prime.\n\t*/\n\treturn(true);\n}\n\n\n/*\n**\tComplete list of all prime numbers that are less than 32719 (inclusive).\n*/\nunsigned short primeTable[3511] = {\n\t0x0002,0x0003,0x0005,0x0007,0x000B,0x000D,0x0011,0x0013,0x0017,0x001D,0x001F,0x0025,0x0029,0x002B,0x002F,0x0035,\n\t0x003B,0x003D,0x0043,0x0047,0x0049,0x004F,0x0053,0x0059,0x0061,0x0065,0x0067,0x006B,0x006D,0x0071,0x007F,0x0083,\n\t0x0089,0x008B,0x0095,0x0097,0x009D,0x00A3,0x00A7,0x00AD,0x00B3,0x00B5,0x00BF,0x00C1,0x00C5,0x00C7,0x00D3,0x00DF,\n\t0x00E3,0x00E5,0x00E9,0x00EF,0x00F1,0x00FB,0x0101,0x0107,0x010D,0x010F,0x0115,0x0119,0x011B,0x0125,0x0133,0x0137,\n\t0x0139,0x013D,0x014B,0x0151,0x015B,0x015D,0x0161,0x0167,0x016F,0x0175,0x017B,0x017F,0x0185,0x018D,0x0191,0x0199,\n\t0x01A3,0x01A5,0x01AF,0x01B1,0x01B7,0x01BB,0x01C1,0x01C9,0x01CD,0x01CF,0x01D3,0x01DF,0x01E7,0x01EB,0x01F3,0x01F7,\n\t0x01FD,0x0209,0x020B,0x021D,0x0223,0x022D,0x0233,0x0239,0x023B,0x0241,0x024B,0x0251,0x0257,0x0259,0x025F,0x0265,\n\t0x0269,0x026B,0x0277,0x0281,0x0283,0x0287,0x028D,0x0293,0x0295,0x02A1,0x02A5,0x02AB,0x02B3,0x02BD,0x02C5,0x02CF,\n\t0x02D7,0x02DD,0x02E3,0x02E7,0x02EF,0x02F5,0x02F9,0x0301,0x0305,0x0313,0x031D,0x0329,0x032B,0x0335,0x0337,0x033B,\n\t0x033D,0x0347,0x0355,0x0359,0x035B,0x035F,0x036D,0x0371,0x0373,0x0377,0x038B,0x038F,0x0397,0x03A1,0x03A9,0x03AD,\n\t0x03B3,0x03B9,0x03C7,0x03CB,0x03D1,0x03D7,0x03DF,0x03E5,0x03F1,0x03F5,0x03FB,0x03FD,0x0407,0x0409,0x040F,0x0419,\n\t0x041B,0x0425,0x0427,0x042D,0x043F,0x0443,0x0445,0x0449,0x044F,0x0455,0x045D,0x0463,0x0469,0x047F,0x0481,0x048B,\n\t0x0493,0x049D,0x04A3,0x04A9,0x04B1,0x04BD,0x04C1,0x04C7,0x04CD,0x04CF,0x04D5,0x04E1,0x04EB,0x04FD,0x04FF,0x0503,\n\t0x0509,0x050B,0x0511,0x0515,0x0517,0x051B,0x0527,0x0529,0x052F,0x0551,0x0557,0x055D,0x0565,0x0577,0x0581,0x058F,\n\t0x0593,0x0595,0x0599,0x059F,0x05A7,0x05AB,0x05AD,0x05B3,0x05BF,0x05C9,0x05CB,0x05CF,0x05D1,0x05D5,0x05DB,0x05E7,\n\t0x05F3,0x05FB,0x0607,0x060D,0x0611,0x0617,0x061F,0x0623,0x062B,0x062F,0x063D,0x0641,0x0647,0x0649,0x064D,0x0653,\n\t0x0655,0x065B,0x0665,0x0679,0x067F,0x0683,0x0685,0x069D,0x06A1,0x06A3,0x06AD,0x06B9,0x06BB,0x06C5,0x06CD,0x06D3,\n\t0x06D9,0x06DF,0x06F1,0x06F7,0x06FB,0x06FD,0x0709,0x0713,0x071F,0x0727,0x0737,0x0745,0x074B,0x074F,0x0751,0x0755,\n\t0x0757,0x0761,0x076D,0x0773,0x0779,0x078B,0x078D,0x079D,0x079F,0x07B5,0x07BB,0x07C3,0x07C9,0x07CD,0x07CF,0x07D3,\n\t0x07DB,0x07E1,0x07EB,0x07ED,0x07F7,0x0805,0x080F,0x0815,0x0821,0x0823,0x0827,0x0829,0x0833,0x083F,0x0841,0x0851,\n\t0x0853,0x0859,0x085D,0x085F,0x0869,0x0871,0x0883,0x089B,0x089F,0x08A5,0x08AD,0x08BD,0x08BF,0x08C3,0x08CB,0x08DB,\n\t0x08DD,0x08E1,0x08E9,0x08EF,0x08F5,0x08F9,0x0905,0x0907,0x091D,0x0923,0x0925,0x092B,0x092F,0x0935,0x0943,0x0949,\n\t0x094D,0x094F,0x0955,0x0959,0x095F,0x096B,0x0971,0x0977,0x0985,0x0989,0x098F,0x099B,0x09A3,0x09A9,0x09AD,0x09C7,\n\t0x09D9,0x09E3,0x09EB,0x09EF,0x09F5,0x09F7,0x09FD,0x0A13,0x0A1F,0x0A21,0x0A31,0x0A39,0x0A3D,0x0A49,0x0A57,0x0A61,\n\t0x0A63,0x0A67,0x0A6F,0x0A75,0x0A7B,0x0A7F,0x0A81,0x0A85,0x0A8B,0x0A93,0x0A97,0x0A99,0x0A9F,0x0AA9,0x0AAB,0x0AB5,\n\t0x0ABD,0x0AC1,0x0ACF,0x0AD9,0x0AE5,0x0AE7,0x0AED,0x0AF1,0x0AF3,0x0B03,0x0B11,0x0B15,0x0B1B,0x0B23,0x0B29,0x0B2D,\n\t0x0B3F,0x0B47,0x0B51,0x0B57,0x0B5D,0x0B65,0x0B6F,0x0B7B,0x0B89,0x0B8D,0x0B93,0x0B99,0x0B9B,0x0BB7,0x0BB9,0x0BC3,\n\t0x0BCB,0x0BCF,0x0BDD,0x0BE1,0x0BE9,0x0BF5,0x0BFB,0x0C07,0x0C0B,0x0C11,0x0C25,0x0C2F,0x0C31,0x0C41,0x0C5B,0x0C5F,\n\t0x0C61,0x0C6D,0x0C73,0x0C77,0x0C83,0x0C89,0x0C91,0x0C95,0x0C9D,0x0CB3,0x0CB5,0x0CB9,0x0CBB,0x0CC7,0x0CE3,0x0CE5,\n\t0x0CEB,0x0CF1,0x0CF7,0x0CFB,0x0D01,0x0D03,0x0D0F,0x0D13,0x0D1F,0x0D21,0x0D2B,0x0D2D,0x0D3D,0x0D3F,0x0D4F,0x0D55,\n\t0x0D69,0x0D79,0x0D81,0x0D85,0x0D87,0x0D8B,0x0D8D,0x0DA3,0x0DAB,0x0DB7,0x0DBD,0x0DC7,0x0DC9,0x0DCD,0x0DD3,0x0DD5,\n\t0x0DDB,0x0DE5,0x0DE7,0x0DF3,0x0DFD,0x0DFF,0x0E09,0x0E17,0x0E1D,0x0E21,0x0E27,0x0E2F,0x0E35,0x0E3B,0x0E4B,0x0E57,\n\t0x0E59,0x0E5D,0x0E6B,0x0E71,0x0E75,0x0E7D,0x0E87,0x0E8F,0x0E95,0x0E9B,0x0EB1,0x0EB7,0x0EB9,0x0EC3,0x0ED1,0x0ED5,\n\t0x0EDB,0x0EED,0x0EEF,0x0EF9,0x0F07,0x0F0B,0x0F0D,0x0F17,0x0F25,0x0F29,0x0F31,0x0F43,0x0F47,0x0F4D,0x0F4F,0x0F53,\n\t0x0F59,0x0F5B,0x0F67,0x0F6B,0x0F7F,0x0F95,0x0FA1,0x0FA3,0x0FA7,0x0FAD,0x0FB3,0x0FB5,0x0FBB,0x0FD1,0x0FD3,0x0FD9,\n\t0x0FE9,0x0FEF,0x0FFB,0x0FFD,0x1003,0x100F,0x101F,0x1021,0x1025,0x102B,0x1039,0x103D,0x103F,0x1051,0x1069,0x1073,\n\t0x1079,0x107B,0x1085,0x1087,0x1091,0x1093,0x109D,0x10A3,0x10A5,0x10AF,0x10B1,0x10BB,0x10C1,0x10C9,0x10E7,0x10F1,\n\t0x10F3,0x10FD,0x1105,0x110B,0x1115,0x1127,0x112D,0x1139,0x1145,0x1147,0x1159,0x115F,0x1163,0x1169,0x116F,0x1181,\n\t0x1183,0x118D,0x119B,0x11A1,0x11A5,0x11A7,0x11AB,0x11C3,0x11C5,0x11D1,0x11D7,0x11E7,0x11EF,0x11F5,0x11FB,0x120D,\n\t0x121D,0x121F,0x1223,0x1229,0x122B,0x1231,0x1237,0x1241,0x1247,0x1253,0x125F,0x1271,0x1273,0x1279,0x127D,0x128F,\n\t0x1297,0x12AF,0x12B3,0x12B5,0x12B9,0x12BF,0x12C1,0x12CD,0x12D1,0x12DF,0x12FD,0x1307,0x130D,0x1319,0x1327,0x132D,\n\t0x1337,0x1343,0x1345,0x1349,0x134F,0x1357,0x135D,0x1367,0x1369,0x136D,0x137B,0x1381,0x1387,0x138B,0x1391,0x1393,\n\t0x139D,0x139F,0x13AF,0x13BB,0x13C3,0x13D5,0x13D9,0x13DF,0x13EB,0x13ED,0x13F3,0x13F9,0x13FF,0x141B,0x1421,0x142F,\n\t0x1433,0x143B,0x1445,0x144D,0x1459,0x146B,0x146F,0x1471,0x1475,0x148D,0x1499,0x149F,0x14A1,0x14B1,0x14B7,0x14BD,\n\t0x14CB,0x14D5,0x14E3,0x14E7,0x1505,0x150B,0x1511,0x1517,0x151F,0x1525,0x1529,0x152B,0x1537,0x153D,0x1541,0x1543,\n\t0x1549,0x155F,0x1565,0x1567,0x156B,0x157D,0x157F,0x1583,0x158F,0x1591,0x1597,0x159B,0x15B5,0x15BB,0x15C1,0x15C5,\n\t0x15CD,0x15D7,0x15F7,0x1607,0x1609,0x160F,0x1613,0x1615,0x1619,0x161B,0x1625,0x1633,0x1639,0x163D,0x1645,0x164F,\n\t0x1655,0x1669,0x166D,0x166F,0x1675,0x1693,0x1697,0x169F,0x16A9,0x16AF,0x16B5,0x16BD,0x16C3,0x16CF,0x16D3,0x16D9,\n\t0x16DB,0x16E1,0x16E5,0x16EB,0x16ED,0x16F7,0x16F9,0x1709,0x170F,0x1723,0x1727,0x1733,0x1741,0x175D,0x1763,0x1777,\n\t0x177B,0x178D,0x1795,0x179B,0x179F,0x17A5,0x17B3,0x17B9,0x17BF,0x17C9,0x17CB,0x17D5,0x17E1,0x17E9,0x17F3,0x17F5,\n\t0x17FF,0x1807,0x1813,0x181D,0x1835,0x1837,0x183B,0x1843,0x1849,0x184D,0x1855,0x1867,0x1871,0x1877,0x187D,0x187F,\n\t0x1885,0x188F,0x189B,0x189D,0x18A7,0x18AD,0x18B3,0x18B9,0x18C1,0x18C7,0x18D1,0x18D7,0x18D9,0x18DF,0x18E5,0x18EB,\n\t0x18F5,0x18FD,0x1915,0x191B,0x1931,0x1933,0x1945,0x1949,0x1951,0x195B,0x1979,0x1981,0x1993,0x1997,0x1999,0x19A3,\n\t0x19A9,0x19AB,0x19B1,0x19B5,0x19C7,0x19CF,0x19DB,0x19ED,0x19FD,0x1A03,0x1A05,0x1A11,0x1A17,0x1A21,0x1A23,0x1A2D,\n\t0x1A2F,0x1A35,0x1A3F,0x1A4D,0x1A51,0x1A69,0x1A6B,0x1A7B,0x1A7D,0x1A87,0x1A89,0x1A93,0x1AA7,0x1AAB,0x1AAD,0x1AB1,\n\t0x1AB9,0x1AC9,0x1ACF,0x1AD5,0x1AD7,0x1AE3,0x1AF3,0x1AFB,0x1AFF,0x1B05,0x1B23,0x1B25,0x1B2F,0x1B31,0x1B37,0x1B3B,\n\t0x1B41,0x1B47,0x1B4F,0x1B55,0x1B59,0x1B65,0x1B6B,0x1B73,0x1B7F,0x1B83,0x1B91,0x1B9D,0x1BA7,0x1BBF,0x1BC5,0x1BD1,\n\t0x1BD7,0x1BD9,0x1BEF,0x1BF7,0x1C09,0x1C13,0x1C19,0x1C27,0x1C2B,0x1C2D,0x1C33,0x1C3D,0x1C45,0x1C4B,0x1C4F,0x1C55,\n\t0x1C73,0x1C81,0x1C8B,0x1C8D,0x1C99,0x1CA3,0x1CA5,0x1CB5,0x1CB7,0x1CC9,0x1CE1,0x1CF3,0x1CF9,0x1D09,0x1D1B,0x1D21,\n\t0x1D23,0x1D35,0x1D39,0x1D3F,0x1D41,0x1D4B,0x1D53,0x1D5D,0x1D63,0x1D69,0x1D71,0x1D75,0x1D7B,0x1D7D,0x1D87,0x1D89,\n\t0x1D95,0x1D99,0x1D9F,0x1DA5,0x1DA7,0x1DB3,0x1DB7,0x1DC5,0x1DD7,0x1DDB,0x1DE1,0x1DF5,0x1DF9,0x1E01,0x1E07,0x1E0B,\n\t0x1E13,0x1E17,0x1E25,0x1E2B,0x1E2F,0x1E3D,0x1E49,0x1E4D,0x1E4F,0x1E6D,0x1E71,0x1E89,0x1E8F,0x1E95,0x1EA1,0x1EAD,\n\t0x1EBB,0x1EC1,0x1EC5,0x1EC7,0x1ECB,0x1EDD,0x1EE3,0x1EEF,0x1EF7,0x1EFD,0x1F01,0x1F0D,0x1F0F,0x1F1B,0x1F39,0x1F49,\n\t0x1F4B,0x1F51,0x1F67,0x1F75,0x1F7B,0x1F85,0x1F91,0x1F97,0x1F99,0x1F9D,0x1FA5,0x1FAF,0x1FB5,0x1FBB,0x1FD3,0x1FE1,\n\t0x1FE7,0x1FEB,0x1FF3,0x1FFF,0x2011,0x201B,0x201D,0x2027,0x2029,0x202D,0x2033,0x2047,0x204D,0x2051,0x205F,0x2063,\n\t0x2065,0x2069,0x2077,0x207D,0x2089,0x20A1,0x20AB,0x20B1,0x20B9,0x20C3,0x20C5,0x20E3,0x20E7,0x20ED,0x20EF,0x20FB,\n\t0x20FF,0x210D,0x2113,0x2135,0x2141,0x2149,0x214F,0x2159,0x215B,0x215F,0x2173,0x217D,0x2185,0x2195,0x2197,0x21A1,\n\t0x21AF,0x21B3,0x21B5,0x21C1,0x21C7,0x21D7,0x21DD,0x21E5,0x21E9,0x21F1,0x21F5,0x21FB,0x2203,0x2209,0x220F,0x221B,\n\t0x2221,0x2225,0x222B,0x2231,0x2239,0x224B,0x224F,0x2263,0x2267,0x2273,0x2275,0x227F,0x2285,0x2287,0x2291,0x229D,\n\t0x229F,0x22A3,0x22B7,0x22BD,0x22DB,0x22E1,0x22E5,0x22ED,0x22F7,0x2303,0x2309,0x230B,0x2327,0x2329,0x232F,0x2333,\n\t0x2335,0x2345,0x2351,0x2353,0x2359,0x2363,0x236B,0x2383,0x238F,0x2395,0x23A7,0x23AD,0x23B1,0x23BF,0x23C5,0x23C9,\n\t0x23D5,0x23DD,0x23E3,0x23EF,0x23F3,0x23F9,0x2405,0x240B,0x2417,0x2419,0x2429,0x243D,0x2441,0x2443,0x244D,0x245F,\n\t0x2467,0x246B,0x2479,0x247D,0x247F,0x2485,0x249B,0x24A1,0x24AF,0x24B5,0x24BB,0x24C5,0x24CB,0x24CD,0x24D7,0x24D9,\n\t0x24DD,0x24DF,0x24F5,0x24F7,0x24FB,0x2501,0x2507,0x2513,0x2519,0x2527,0x2531,0x253D,0x2543,0x254B,0x254F,0x2573,\n\t0x2581,0x258D,0x2593,0x2597,0x259D,0x259F,0x25AB,0x25B1,0x25BD,0x25CD,0x25CF,0x25D9,0x25E1,0x25F7,0x25F9,0x2605,\n\t0x260B,0x260F,0x2615,0x2627,0x2629,0x2635,0x263B,0x263F,0x264B,0x2653,0x2659,0x2665,0x2669,0x266F,0x267B,0x2681,\n\t0x2683,0x268F,0x269B,0x269F,0x26AD,0x26B3,0x26C3,0x26C9,0x26CB,0x26D5,0x26DD,0x26EF,0x26F5,0x2717,0x2719,0x2735,\n\t0x2737,0x274D,0x2753,0x2755,0x275F,0x276B,0x276D,0x2773,0x2777,0x277F,0x2795,0x279B,0x279D,0x27A7,0x27AF,0x27B3,\n\t0x27B9,0x27C1,0x27C5,0x27D1,0x27E3,0x27EF,0x2803,0x2807,0x280D,0x2813,0x281B,0x281F,0x2821,0x2831,0x283D,0x283F,\n\t0x2849,0x2851,0x285B,0x285D,0x2861,0x2867,0x2875,0x2881,0x2897,0x289F,0x28BB,0x28BD,0x28C1,0x28D5,0x28D9,0x28DB,\n\t0x28DF,0x28ED,0x28F7,0x2903,0x2905,0x2911,0x2921,0x2923,0x293F,0x2947,0x295D,0x2965,0x2969,0x296F,0x2975,0x2983,\n\t0x2987,0x298F,0x299B,0x29A1,0x29A7,0x29AB,0x29BF,0x29C3,0x29D5,0x29D7,0x29E3,0x29E9,0x29ED,0x29F3,0x2A01,0x2A13,\n\t0x2A1D,0x2A25,0x2A2F,0x2A4F,0x2A55,0x2A5F,0x2A65,0x2A6B,0x2A6D,0x2A73,0x2A83,0x2A89,0x2A8B,0x2A97,0x2A9D,0x2AB9,\n\t0x2ABB,0x2AC5,0x2ACD,0x2ADD,0x2AE3,0x2AEB,0x2AF1,0x2AFB,0x2B13,0x2B27,0x2B31,0x2B33,0x2B3D,0x2B3F,0x2B4B,0x2B4F,\n\t0x2B55,0x2B69,0x2B6D,0x2B6F,0x2B7B,0x2B8D,0x2B97,0x2B99,0x2BA3,0x2BA5,0x2BA9,0x2BBD,0x2BCD,0x2BE7,0x2BEB,0x2BF3,\n\t0x2BF9,0x2BFD,0x2C09,0x2C0F,0x2C17,0x2C23,0x2C2F,0x2C35,0x2C39,0x2C41,0x2C57,0x2C59,0x2C69,0x2C77,0x2C81,0x2C87,\n\t0x2C93,0x2C9F,0x2CAD,0x2CB3,0x2CB7,0x2CCB,0x2CCF,0x2CDB,0x2CE1,0x2CE3,0x2CE9,0x2CEF,0x2CFF,0x2D07,0x2D1D,0x2D1F,\n\t0x2D3B,0x2D43,0x2D49,0x2D4D,0x2D61,0x2D65,0x2D71,0x2D89,0x2D9D,0x2DA1,0x2DA9,0x2DB3,0x2DB5,0x2DC5,0x2DC7,0x2DD3,\n\t0x2DDF,0x2E01,0x2E03,0x2E07,0x2E0D,0x2E19,0x2E1F,0x2E25,0x2E2D,0x2E33,0x2E37,0x2E39,0x2E3F,0x2E57,0x2E5B,0x2E6F,\n\t0x2E79,0x2E7F,0x2E85,0x2E93,0x2E97,0x2E9D,0x2EA3,0x2EA5,0x2EB1,0x2EB7,0x2EC1,0x2EC3,0x2ECD,0x2ED3,0x2EE7,0x2EEB,\n\t0x2F05,0x2F09,0x2F0B,0x2F11,0x2F27,0x2F29,0x2F41,0x2F45,0x2F4B,0x2F4D,0x2F51,0x2F57,0x2F6F,0x2F75,0x2F7D,0x2F81,\n\t0x2F83,0x2FA5,0x2FAB,0x2FB3,0x2FC3,0x2FCF,0x2FD1,0x2FDB,0x2FDD,0x2FE7,0x2FED,0x2FF5,0x2FF9,0x3001,0x300D,0x3023,\n\t0x3029,0x3037,0x303B,0x3055,0x3059,0x305B,0x3067,0x3071,0x3079,0x307D,0x3085,0x3091,0x3095,0x30A3,0x30A9,0x30B9,\n\t0x30BF,0x30C7,0x30CB,0x30D1,0x30D7,0x30DF,0x30E5,0x30EF,0x30FB,0x30FD,0x3103,0x3109,0x3119,0x3121,0x3127,0x312D,\n\t0x3139,0x3143,0x3145,0x314B,0x315D,0x3161,0x3167,0x316D,0x3173,0x317F,0x3191,0x3199,0x319F,0x31A9,0x31B1,0x31C3,\n\t0x31C7,0x31D5,0x31DB,0x31ED,0x31F7,0x31FF,0x3209,0x3215,0x3217,0x321D,0x3229,0x3235,0x3259,0x325D,0x3263,0x326B,\n\t0x326F,0x3275,0x3277,0x327B,0x328D,0x3299,0x329F,0x32A7,0x32AD,0x32B3,0x32B7,0x32C9,0x32CB,0x32CF,0x32D1,0x32E9,\n\t0x32ED,0x32F3,0x32F9,0x3307,0x3325,0x332B,0x332F,0x3335,0x3341,0x3347,0x335B,0x335F,0x3367,0x336B,0x3373,0x3379,\n\t0x337F,0x3383,0x33A1,0x33A3,0x33AD,0x33B9,0x33C1,0x33CB,0x33D3,0x33EB,0x33F1,0x33FD,0x3401,0x340F,0x3413,0x3419,\n\t0x341B,0x3437,0x3445,0x3455,0x3457,0x3463,0x3469,0x346D,0x3481,0x348B,0x3491,0x3497,0x349D,0x34A5,0x34AF,0x34BB,\n\t0x34C9,0x34D3,0x34E1,0x34F1,0x34FF,0x3509,0x3517,0x351D,0x352D,0x3533,0x353B,0x3541,0x3551,0x3565,0x356F,0x3571,\n\t0x3577,0x357B,0x357D,0x3581,0x358D,0x358F,0x3599,0x359B,0x35A1,0x35B7,0x35BD,0x35BF,0x35C3,0x35D5,0x35DD,0x35E7,\n\t0x35EF,0x3605,0x3607,0x3611,0x3623,0x3631,0x3635,0x3637,0x363B,0x364D,0x364F,0x3653,0x3659,0x3661,0x366B,0x366D,\n\t0x368B,0x368F,0x36AD,0x36AF,0x36B9,0x36BB,0x36CD,0x36D1,0x36E3,0x36E9,0x36F7,0x3701,0x3703,0x3707,0x371B,0x373F,\n\t0x3745,0x3749,0x374F,0x375D,0x3761,0x3775,0x377F,0x378D,0x37A3,0x37A9,0x37AB,0x37C9,0x37D5,0x37DF,0x37F1,0x37F3,\n\t0x37F7,0x3805,0x380B,0x3821,0x3833,0x3835,0x3841,0x3847,0x384B,0x3853,0x3857,0x385F,0x3865,0x386F,0x3871,0x387D,\n\t0x388F,0x3899,0x38A7,0x38B7,0x38C5,0x38C9,0x38CF,0x38D5,0x38D7,0x38DD,0x38E1,0x38E3,0x38FF,0x3901,0x391D,0x3923,\n\t0x3925,0x3929,0x392F,0x393D,0x3941,0x394D,0x395B,0x396B,0x3979,0x397D,0x3983,0x398B,0x3991,0x3995,0x399B,0x39A1,\n\t0x39A7,0x39AF,0x39B3,0x39BB,0x39BF,0x39CD,0x39DD,0x39E5,0x39EB,0x39EF,0x39FB,0x3A03,0x3A13,0x3A15,0x3A1F,0x3A27,\n\t0x3A2B,0x3A31,0x3A4B,0x3A51,0x3A5B,0x3A63,0x3A67,0x3A6D,0x3A79,0x3A87,0x3AA5,0x3AA9,0x3AB7,0x3ACD,0x3AD5,0x3AE1,\n\t0x3AE5,0x3AEB,0x3AF3,0x3AFD,0x3B03,0x3B11,0x3B1B,0x3B21,0x3B23,0x3B2D,0x3B39,0x3B45,0x3B53,0x3B59,0x3B5F,0x3B71,\n\t0x3B7B,0x3B81,0x3B89,0x3B9B,0x3B9F,0x3BA5,0x3BA7,0x3BAD,0x3BB7,0x3BB9,0x3BC3,0x3BCB,0x3BD1,0x3BD7,0x3BE1,0x3BE3,\n\t0x3BF5,0x3BFF,0x3C01,0x3C0D,0x3C11,0x3C17,0x3C1F,0x3C29,0x3C35,0x3C43,0x3C4F,0x3C53,0x3C5B,0x3C65,0x3C6B,0x3C71,\n\t0x3C85,0x3C89,0x3C97,0x3CA7,0x3CB5,0x3CBF,0x3CC7,0x3CD1,0x3CDD,0x3CDF,0x3CF1,0x3CF7,0x3D03,0x3D0D,0x3D19,0x3D1B,\n\t0x3D1F,0x3D21,0x3D2D,0x3D33,0x3D37,0x3D3F,0x3D43,0x3D6F,0x3D73,0x3D75,0x3D79,0x3D7B,0x3D85,0x3D91,0x3D97,0x3D9D,\n\t0x3DAB,0x3DAF,0x3DB5,0x3DBB,0x3DC1,0x3DC9,0x3DCF,0x3DF3,0x3E05,0x3E09,0x3E0F,0x3E11,0x3E1D,0x3E23,0x3E29,0x3E2F,\n\t0x3E33,0x3E41,0x3E57,0x3E63,0x3E65,0x3E77,0x3E81,0x3E87,0x3EA1,0x3EB9,0x3EBD,0x3EBF,0x3EC3,0x3EC5,0x3EC9,0x3ED7,\n\t0x3EDB,0x3EE1,0x3EE7,0x3EEF,0x3EFF,0x3F0B,0x3F0D,0x3F37,0x3F3B,0x3F3D,0x3F41,0x3F59,0x3F5F,0x3F65,0x3F67,0x3F79,\n\t0x3F7D,0x3F8B,0x3F91,0x3FAD,0x3FBF,0x3FCD,0x3FD3,0x3FDD,0x3FE9,0x3FEB,0x3FF1,0x3FFD,0x401B,0x4021,0x4025,0x402B,\n\t0x4031,0x403F,0x4043,0x4045,0x405D,0x4061,0x4067,0x406D,0x4087,0x4091,0x40A3,0x40A9,0x40B1,0x40B7,0x40BD,0x40DB,\n\t0x40DF,0x40EB,0x40F7,0x40F9,0x4109,0x410B,0x4111,0x4115,0x4121,0x4133,0x4135,0x413B,0x413F,0x4159,0x4165,0x416B,\n\t0x4177,0x417B,0x4193,0x41AB,0x41B7,0x41BD,0x41BF,0x41CB,0x41E7,0x41EF,0x41F3,0x41F9,0x4205,0x4207,0x4219,0x421F,\n\t0x4223,0x4229,0x422F,0x4243,0x4253,0x4255,0x425B,0x4261,0x4273,0x427D,0x4283,0x4285,0x4289,0x4291,0x4297,0x429D,\n\t0x42B5,0x42C5,0x42CB,0x42D3,0x42DD,0x42E3,0x42F1,0x4307,0x430F,0x431F,0x4325,0x4327,0x4333,0x4337,0x4339,0x434F,\n\t0x4357,0x4369,0x438B,0x438D,0x4393,0x43A5,0x43A9,0x43AF,0x43B5,0x43BD,0x43C7,0x43CF,0x43E1,0x43E7,0x43EB,0x43ED,\n\t0x43F1,0x43F9,0x4409,0x440B,0x4417,0x4423,0x4429,0x443B,0x443F,0x4445,0x444B,0x4451,0x4453,0x4459,0x4465,0x446F,\n\t0x4483,0x448F,0x44A1,0x44A5,0x44AB,0x44AD,0x44BD,0x44BF,0x44C9,0x44D7,0x44DB,0x44F9,0x44FB,0x4505,0x4511,0x4513,\n\t0x452B,0x4531,0x4541,0x4549,0x4553,0x4555,0x4561,0x4577,0x457D,0x457F,0x458F,0x45A3,0x45AD,0x45AF,0x45BB,0x45C7,\n\t0x45D9,0x45E3,0x45EF,0x45F5,0x45F7,0x4601,0x4603,0x4609,0x4613,0x4625,0x4627,0x4633,0x4639,0x463D,0x4643,0x4645,\n\t0x465D,0x4679,0x467B,0x467F,0x4681,0x468B,0x468D,0x469D,0x46A9,0x46B1,0x46C7,0x46C9,0x46CF,0x46D3,0x46D5,0x46DF,\n\t0x46E5,0x46F9,0x4705,0x470F,0x4717,0x4723,0x4729,0x472F,0x4735,0x4739,0x474B,0x474D,0x4751,0x475D,0x476F,0x4771,\n\t0x477D,0x4783,0x4787,0x4789,0x4799,0x47A5,0x47B1,0x47BF,0x47C3,0x47CB,0x47DD,0x47E1,0x47ED,0x47FB,0x4801,0x4807,\n\t0x480B,0x4813,0x4819,0x481D,0x4831,0x483D,0x4847,0x4855,0x4859,0x485B,0x486B,0x486D,0x4879,0x4897,0x489B,0x48A1,\n\t0x48B9,0x48CD,0x48E5,0x48EF,0x48F7,0x4903,0x490D,0x4919,0x491F,0x492B,0x4937,0x493D,0x4945,0x4955,0x4963,0x4969,\n\t0x496D,0x4973,0x4997,0x49AB,0x49B5,0x49D3,0x49DF,0x49E1,0x49E5,0x49E7,0x4A03,0x4A0F,0x4A1D,0x4A23,0x4A39,0x4A41,\n\t0x4A45,0x4A57,0x4A5D,0x4A6B,0x4A7D,0x4A81,0x4A87,0x4A89,0x4A8F,0x4AB1,0x4AC3,0x4AC5,0x4AD5,0x4ADB,0x4AED,0x4AEF,\n\t0x4B07,0x4B0B,0x4B0D,0x4B13,0x4B1F,0x4B25,0x4B31,0x4B3B,0x4B43,0x4B49,0x4B59,0x4B65,0x4B6D,0x4B77,0x4B85,0x4BAD,\n\t0x4BB3,0x4BB5,0x4BBB,0x4BBF,0x4BCB,0x4BD9,0x4BDD,0x4BDF,0x4BE3,0x4BE5,0x4BE9,0x4BF1,0x4BF7,0x4C01,0x4C07,0x4C0D,\n\t0x4C0F,0x4C15,0x4C1B,0x4C21,0x4C2D,0x4C33,0x4C4B,0x4C55,0x4C57,0x4C61,0x4C67,0x4C73,0x4C79,0x4C7F,0x4C8D,0x4C93,\n\t0x4C99,0x4CCD,0x4CE1,0x4CE7,0x4CF1,0x4CF3,0x4CFD,0x4D05,0x4D0F,0x4D1B,0x4D27,0x4D29,0x4D2F,0x4D33,0x4D41,0x4D51,\n\t0x4D59,0x4D65,0x4D6B,0x4D81,0x4D83,0x4D8D,0x4D95,0x4D9B,0x4DB1,0x4DB3,0x4DC9,0x4DCF,0x4DD7,0x4DE1,0x4DED,0x4DF9,\n\t0x4DFB,0x4E05,0x4E0B,0x4E17,0x4E19,0x4E1D,0x4E2B,0x4E35,0x4E37,0x4E3D,0x4E4F,0x4E53,0x4E5F,0x4E67,0x4E79,0x4E85,\n\t0x4E8B,0x4E91,0x4E95,0x4E9B,0x4EA1,0x4EAF,0x4EB3,0x4EB5,0x4EC1,0x4ECD,0x4ED1,0x4ED7,0x4EE9,0x4EFB,0x4F07,0x4F09,\n\t0x4F19,0x4F25,0x4F2D,0x4F3F,0x4F49,0x4F63,0x4F67,0x4F6D,0x4F75,0x4F7B,0x4F81,0x4F85,0x4F87,0x4F91,0x4FA5,0x4FA9,\n\t0x4FAF,0x4FB7,0x4FBB,0x4FCF,0x4FD9,0x4FDB,0x4FFD,0x4FFF,0x5003,0x501B,0x501D,0x5029,0x5035,0x503F,0x5045,0x5047,\n\t0x5053,0x5071,0x5077,0x5083,0x5093,0x509F,0x50A1,0x50B7,0x50C9,0x50D5,0x50E3,0x50ED,0x50EF,0x50FB,0x5107,0x510B,\n\t0x510D,0x5111,0x5117,0x5123,0x5125,0x5135,0x5147,0x5149,0x5171,0x5179,0x5189,0x518F,0x5197,0x51A1,0x51A3,0x51A7,\n\t0x51B9,0x51C1,0x51CB,0x51D3,0x51DF,0x51E3,0x51F5,0x51F7,0x5209,0x5213,0x5215,0x5219,0x521B,0x521F,0x5227,0x5243,\n\t0x5245,0x524B,0x5261,0x526D,0x5273,0x5281,0x5293,0x5297,0x529D,0x52A5,0x52AB,0x52B1,0x52BB,0x52C3,0x52C7,0x52C9,\n\t0x52DB,0x52E5,0x52EB,0x52FF,0x5315,0x531D,0x5323,0x5341,0x5345,0x5347,0x534B,0x535D,0x5363,0x5381,0x5383,0x5387,\n\t0x538F,0x5395,0x5399,0x539F,0x53AB,0x53B9,0x53DB,0x53E9,0x53EF,0x53F3,0x53F5,0x53FB,0x53FF,0x540D,0x5411,0x5413,\n\t0x5419,0x5435,0x5437,0x543B,0x5441,0x5449,0x5453,0x5455,0x545F,0x5461,0x546B,0x546D,0x5471,0x548F,0x5491,0x549D,\n\t0x54A9,0x54B3,0x54C5,0x54D1,0x54DF,0x54E9,0x54EB,0x54F7,0x54FD,0x5507,0x550D,0x551B,0x5527,0x552B,0x5539,0x553D,\n\t0x554F,0x5551,0x555B,0x5563,0x5567,0x556F,0x5579,0x5585,0x5597,0x55A9,0x55B1,0x55B7,0x55C9,0x55D9,0x55E7,0x55ED,\n\t0x55F3,0x55FD,0x560B,0x560F,0x5615,0x5617,0x5623,0x562F,0x5633,0x5639,0x563F,0x564B,0x564D,0x565D,0x565F,0x566B,\n\t0x5671,0x5675,0x5683,0x5689,0x568D,0x568F,0x569B,0x56AD,0x56B1,0x56D5,0x56E7,0x56F3,0x56FF,0x5701,0x5705,0x5707,\n\t0x570B,0x5713,0x571F,0x5723,0x5747,0x574D,0x575F,0x5761,0x576D,0x5777,0x577D,0x5789,0x57A1,0x57A9,0x57AF,0x57B5,\n\t0x57C5,0x57D1,0x57D3,0x57E5,0x57EF,0x5803,0x580D,0x580F,0x5815,0x5827,0x582B,0x582D,0x5855,0x585B,0x585D,0x586D,\n\t0x586F,0x5873,0x587B,0x588D,0x5897,0x58A3,0x58A9,0x58AB,0x58B5,0x58BD,0x58C1,0x58C7,0x58D3,0x58D5,0x58DF,0x58F1,\n\t0x58F9,0x58FF,0x5903,0x5917,0x591B,0x5921,0x5945,0x594B,0x594D,0x5957,0x595D,0x5975,0x597B,0x5989,0x5999,0x599F,\n\t0x59B1,0x59B3,0x59BD,0x59D1,0x59DB,0x59E3,0x59E9,0x59ED,0x59F3,0x59F5,0x59FF,0x5A01,0x5A0D,0x5A11,0x5A13,0x5A17,\n\t0x5A1F,0x5A29,0x5A2F,0x5A3B,0x5A4D,0x5A5B,0x5A67,0x5A77,0x5A7F,0x5A85,0x5A95,0x5A9D,0x5AA1,0x5AA3,0x5AA9,0x5ABB,\n\t0x5AD3,0x5AE5,0x5AEF,0x5AFB,0x5AFD,0x5B01,0x5B0F,0x5B19,0x5B1F,0x5B25,0x5B2B,0x5B3D,0x5B49,0x5B4B,0x5B67,0x5B79,\n\t0x5B87,0x5B97,0x5BA3,0x5BB1,0x5BC9,0x5BD5,0x5BEB,0x5BF1,0x5BF3,0x5BFD,0x5C05,0x5C09,0x5C0B,0x5C0F,0x5C1D,0x5C29,\n\t0x5C2F,0x5C33,0x5C39,0x5C47,0x5C4B,0x5C4D,0x5C51,0x5C6F,0x5C75,0x5C77,0x5C7D,0x5C87,0x5C89,0x5CA7,0x5CBD,0x5CBF,\n\t0x5CC3,0x5CC9,0x5CD1,0x5CD7,0x5CDD,0x5CED,0x5CF9,0x5D05,0x5D0B,0x5D13,0x5D17,0x5D19,0x5D31,0x5D3D,0x5D41,0x5D47,\n\t0x5D4F,0x5D55,0x5D5B,0x5D65,0x5D67,0x5D6D,0x5D79,0x5D95,0x5DA3,0x5DA9,0x5DAD,0x5DB9,0x5DC1,0x5DC7,0x5DD3,0x5DD7,\n\t0x5DDD,0x5DEB,0x5DF1,0x5DFD,0x5E07,0x5E0D,0x5E13,0x5E1B,0x5E21,0x5E27,0x5E2B,0x5E2D,0x5E31,0x5E39,0x5E45,0x5E49,\n\t0x5E57,0x5E69,0x5E73,0x5E75,0x5E85,0x5E8B,0x5E9F,0x5EA5,0x5EAF,0x5EB7,0x5EBB,0x5ED9,0x5EFD,0x5F09,0x5F11,0x5F27,\n\t0x5F33,0x5F35,0x5F3B,0x5F47,0x5F57,0x5F5D,0x5F63,0x5F65,0x5F77,0x5F7B,0x5F95,0x5F99,0x5FA1,0x5FB3,0x5FBD,0x5FC5,\n\t0x5FCF,0x5FD5,0x5FE3,0x5FE7,0x5FFB,0x6011,0x6023,0x602F,0x6037,0x6053,0x605F,0x6065,0x606B,0x6073,0x6079,0x6085,\n\t0x609D,0x60AD,0x60BB,0x60BF,0x60CD,0x60D9,0x60DF,0x60E9,0x60F5,0x6109,0x610F,0x6113,0x611B,0x612D,0x6139,0x614B,\n\t0x6155,0x6157,0x615B,0x616F,0x6179,0x6187,0x618B,0x6191,0x6193,0x619D,0x61B5,0x61C7,0x61C9,0x61CD,0x61E1,0x61F1,\n\t0x61FF,0x6209,0x6217,0x621D,0x6221,0x6227,0x623B,0x6241,0x624B,0x6251,0x6253,0x625F,0x6265,0x6283,0x628D,0x6295,\n\t0x629B,0x629F,0x62A5,0x62AD,0x62D5,0x62D7,0x62DB,0x62DD,0x62E9,0x62FB,0x62FF,0x6305,0x630D,0x6317,0x631D,0x632F,\n\t0x6341,0x6343,0x634F,0x635F,0x6367,0x636D,0x6371,0x6377,0x637D,0x637F,0x63B3,0x63C1,0x63C5,0x63D9,0x63E9,0x63EB,\n\t0x63EF,0x63F5,0x6401,0x6403,0x6409,0x6415,0x6421,0x6427,0x642B,0x6439,0x6443,0x6449,0x644F,0x645D,0x6467,0x6475,\n\t0x6485,0x648D,0x6493,0x649F,0x64A3,0x64AB,0x64C1,0x64C7,0x64C9,0x64DB,0x64F1,0x64F7,0x64F9,0x650B,0x6511,0x6521,\n\t0x652F,0x6539,0x653F,0x654B,0x654D,0x6553,0x6557,0x655F,0x6571,0x657D,0x658D,0x658F,0x6593,0x65A1,0x65A5,0x65AD,\n\t0x65B9,0x65C5,0x65E3,0x65F3,0x65FB,0x65FF,0x6601,0x6607,0x661D,0x6629,0x6631,0x663B,0x6641,0x6647,0x664D,0x665B,\n\t0x6661,0x6673,0x667D,0x6689,0x668B,0x6695,0x6697,0x669B,0x66B5,0x66B9,0x66C5,0x66CD,0x66D1,0x66E3,0x66EB,0x66F5,\n\t0x6703,0x6713,0x6719,0x671F,0x6727,0x6731,0x6737,0x673F,0x6745,0x6751,0x675B,0x676F,0x6779,0x6781,0x6785,0x6791,\n\t0x67AB,0x67BD,0x67C1,0x67CD,0x67DF,0x67E5,0x6803,0x6809,0x6811,0x6817,0x682D,0x6839,0x683B,0x683F,0x6845,0x684B,\n\t0x684D,0x6857,0x6859,0x685D,0x6863,0x6869,0x686B,0x6871,0x6887,0x6899,0x689F,0x68B1,0x68BD,0x68C5,0x68D1,0x68D7,\n\t0x68E1,0x68ED,0x68EF,0x68FF,0x6901,0x690B,0x690D,0x6917,0x6929,0x692F,0x6943,0x6947,0x6949,0x694F,0x6965,0x696B,\n\t0x6971,0x6983,0x6989,0x6997,0x69A3,0x69B3,0x69B5,0x69BB,0x69C1,0x69C5,0x69D3,0x69DF,0x69E3,0x69E5,0x69F7,0x6A07,\n\t0x6A2B,0x6A37,0x6A3D,0x6A4B,0x6A67,0x6A69,0x6A75,0x6A7B,0x6A87,0x6A8D,0x6A91,0x6A93,0x6AA3,0x6AC1,0x6AC9,0x6AE1,\n\t0x6AE7,0x6B05,0x6B0F,0x6B11,0x6B23,0x6B27,0x6B2D,0x6B39,0x6B41,0x6B57,0x6B59,0x6B5F,0x6B75,0x6B87,0x6B89,0x6B93,\n\t0x6B95,0x6B9F,0x6BBD,0x6BBF,0x6BDB,0x6BE1,0x6BEF,0x6BFF,0x6C05,0x6C19,0x6C29,0x6C2B,0x6C31,0x6C35,0x6C55,0x6C59,\n\t0x6C5B,0x6C5F,0x6C65,0x6C67,0x6C73,0x6C77,0x6C7D,0x6C83,0x6C8F,0x6C91,0x6C97,0x6C9B,0x6CA1,0x6CA9,0x6CAF,0x6CB3,\n\t0x6CC7,0x6CCB,0x6CEB,0x6CF5,0x6CFD,0x6D0D,0x6D0F,0x6D25,0x6D27,0x6D2B,0x6D31,0x6D39,0x6D3F,0x6D4F,0x6D5D,0x6D61,\n\t0x6D73,0x6D7B,0x6D7F,0x6D93,0x6D99,0x6DA5,0x6DB1,0x6DB7,0x6DC1,0x6DC3,0x6DCD,0x6DCF,0x6DDB,0x6DF7,0x6E03,0x6E15,\n\t0x6E17,0x6E29,0x6E33,0x6E3B,0x6E45,0x6E75,0x6E77,0x6E7B,0x6E81,0x6E89,0x6E93,0x6E95,0x6E9F,0x6EBD,0x6EBF,0x6EE3,\n\t0x6EE9,0x6EF3,0x6EF9,0x6EFB,0x6F0D,0x6F11,0x6F17,0x6F1F,0x6F2F,0x6F3D,0x6F4D,0x6F53,0x6F61,0x6F65,0x6F79,0x6F7D,\n\t0x6F83,0x6F85,0x6F8F,0x6F9B,0x6F9D,0x6FA3,0x6FAF,0x6FB5,0x6FBB,0x6FBF,0x6FCB,0x6FCD,0x6FD3,0x6FD7,0x6FE3,0x6FE9,\n\t0x6FF1,0x6FF5,0x6FF7,0x6FFD,0x700F,0x7019,0x701F,0x7027,0x7033,0x7039,0x704F,0x7051,0x7057,0x7063,0x7075,0x7079,\n\t0x7087,0x708D,0x7091,0x70A5,0x70AB,0x70BB,0x70C3,0x70C7,0x70CF,0x70E5,0x70ED,0x70F9,0x70FF,0x7105,0x7115,0x7121,\n\t0x7133,0x7151,0x7159,0x715D,0x715F,0x7163,0x7169,0x7183,0x7187,0x7195,0x71AD,0x71C3,0x71C9,0x71CB,0x71D1,0x71DB,\n\t0x71E1,0x71EF,0x71F5,0x71FB,0x7207,0x7211,0x7217,0x7219,0x7225,0x722F,0x723B,0x7243,0x7255,0x7267,0x7271,0x7277,\n\t0x727F,0x728F,0x7295,0x729B,0x72A3,0x72B3,0x72C7,0x72CB,0x72CD,0x72D7,0x72D9,0x72E3,0x72EF,0x72F5,0x72FD,0x7303,\n\t0x730D,0x7321,0x732B,0x733D,0x7357,0x735B,0x7361,0x737F,0x7381,0x7385,0x738D,0x7393,0x739F,0x73AB,0x73BD,0x73C1,\n\t0x73C9,0x73DF,0x73E5,0x73E7,0x73F3,0x7415,0x741B,0x742D,0x7439,0x743F,0x7441,0x745D,0x746B,0x747B,0x7489,0x748D,\n\t0x749B,0x74A7,0x74AB,0x74B1,0x74B7,0x74B9,0x74DD,0x74E1,0x74E7,0x74FB,0x7507,0x751F,0x7525,0x753B,0x753D,0x754D,\n\t0x755F,0x756B,0x7577,0x7589,0x758B,0x7591,0x7597,0x759D,0x75A1,0x75A7,0x75B5,0x75B9,0x75BB,0x75D1,0x75D9,0x75E5,\n\t0x75EB,0x75F5,0x75FB,0x7603,0x760F,0x7621,0x762D,0x7633,0x763D,0x763F,0x7655,0x7663,0x7669,0x766F,0x7673,0x7685,\n\t0x768B,0x769F,0x76B5,0x76B7,0x76C3,0x76DB,0x76DF,0x76F1,0x7703,0x7705,0x771B,0x771D,0x7721,0x772D,0x7735,0x7741,\n\t0x774B,0x7759,0x775D,0x775F,0x7771,0x7781,0x77A7,0x77AD,0x77B3,0x77B9,0x77C5,0x77CF,0x77D5,0x77E1,0x77E9,0x77EF,\n\t0x77F3,0x77F9,0x7807,0x7825,0x782B,0x7835,0x783D,0x7853,0x7859,0x7861,0x786D,0x7877,0x7879,0x7883,0x7885,0x788B,\n\t0x7895,0x7897,0x78A1,0x78AD,0x78BF,0x78D3,0x78D9,0x78DD,0x78E5,0x78FB,0x7901,0x7907,0x7925,0x792B,0x7939,0x793F,\n\t0x794B,0x7957,0x795D,0x7967,0x7969,0x7973,0x7991,0x7993,0x79A3,0x79AB,0x79AF,0x79B1,0x79B7,0x79C9,0x79CD,0x79CF,\n\t0x79D5,0x79D9,0x79F3,0x79F7,0x79FF,0x7A05,0x7A0F,0x7A11,0x7A15,0x7A1B,0x7A23,0x7A27,0x7A2D,0x7A4B,0x7A57,0x7A59,\n\t0x7A5F,0x7A65,0x7A69,0x7A7D,0x7A93,0x7A9B,0x7A9F,0x7AA1,0x7AA5,0x7AED,0x7AF5,0x7AF9,0x7B01,0x7B17,0x7B19,0x7B1D,\n\t0x7B2B,0x7B35,0x7B37,0x7B3B,0x7B4F,0x7B55,0x7B5F,0x7B71,0x7B77,0x7B8B,0x7B9B,0x7BA1,0x7BA9,0x7BAF,0x7BB3,0x7BC7,\n\t0x7BD3,0x7BE9,0x7BEB,0x7BEF,0x7BF1,0x7BFD,0x7C07,0x7C19,0x7C1B,0x7C31,0x7C37,0x7C49,0x7C67,0x7C69,0x7C73,0x7C81,\n\t0x7C8B,0x7C93,0x7CA3,0x7CD5,0x7CDB,0x7CE5,0x7CED,0x7CF7,0x7D03,0x7D09,0x7D1B,0x7D1D,0x7D33,0x7D39,0x7D3B,0x7D3F,\n\t0x7D45,0x7D4D,0x7D53,0x7D59,0x7D63,0x7D75,0x7D77,0x7D8D,0x7D8F,0x7D9F,0x7DAD,0x7DB7,0x7DBD,0x7DBF,0x7DCB,0x7DD5,\n\t0x7DE9,0x7DED,0x7DFB,0x7E01,0x7E05,0x7E29,0x7E2B,0x7E2F,0x7E35,0x7E41,0x7E43,0x7E47,0x7E55,0x7E61,0x7E67,0x7E6B,\n\t0x7E71,0x7E73,0x7E79,0x7E7D,0x7E91,0x7E9B,0x7E9D,0x7EA7,0x7EAD,0x7EB9,0x7EBB,0x7ED3,0x7EDF,0x7EEB,0x7EF1,0x7EF7,\n\t0x7EFB,0x7F13,0x7F15,0x7F19,0x7F31,0x7F33,0x7F39,0x7F3D,0x7F43,0x7F4B,0x7F5B,0x7F61,0x7F63,0x7F6D,0x7F79,0x7F87,\n\t0x7F8D,0x7FAF,0x7FB5,0x7FC3,0x7FC9,0x7FCD,0x7FCF\n};\n"
  },
  {
    "path": "CODE/MP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MP.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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                 ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MP.H                                                         *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 04/26/96                                                     *\n *                                                                                             *\n *                  Last Update : April 26, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MP_H\n#define MP_H\n\n//lint -e740 -e534 -e537 -e760\n\n//lint -d_LINT=1\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\n#include\t\"straw.h\"\n#include\t<stdlib.h>\n\nextern unsigned short primeTable[3511];\n\n\n#define\tdigit\tunsigned long\n#define\tsigneddigit\tsigned long\n#define\tLOG_UNITSIZE\t\t\t5\n#define\tUNITSIZE\t\t\t\t\t32\n#define\tUPPER_MOST_BIT\t\t\t0x80000000L\n#define\tSEMI_UPPER_MOST_BIT\t0x8000\n#define\tSEMI_MASK\t\t\t\t((unsigned short)~0)\n#define\tMAX_BIT_PRECISION\t\t2048\n#define\tMAX_UNIT_PRECISION\t(MAX_BIT_PRECISION/UNITSIZE)\n#ifndef ARRAY_SIZE\n#define ARRAY_SIZE(a)\t(sizeof(a)/sizeof(a[0]))\n#endif\n\n\nint XMP_Significance(const digit * r, int precision);\nvoid XMP_Inc(digit * r, int precision);\nvoid XMP_Dec(digit * r, int precision);\nvoid XMP_Neg(digit * r, int precision);\nvoid XMP_Abs(digit * r, int precision);\nvoid XMP_Shift_Right_Bits(digit * r1, int bits, int precision);\nvoid XMP_Shift_Left_Bits(digit * r1, int bits, int precision);\nbool XMP_Rotate_Left(digit * r1, bool carry, int precision);\nvoid XMP_Not(digit * digit_ptr, int precision);\nvoid XMP_Init(digit * r, digit value, int precision);\nunsigned XMP_Count_Bits(const digit * r, int precision);\nint XMP_Count_Bytes(const digit * r, int precision);\nvoid XMP_Move(digit * dest, digit const * source, int precision);\nint XMP_Compare(const digit * r1, const digit * r2, int precision);\nbool XMP_Add(digit * result, const digit * r1, const digit * r2, bool carry, int precision);\nbool XMP_Add_Int(digit * result, const digit * r1, digit r2, bool carry, int precision);\nbool XMP_Sub(digit * result, const digit * r1, const digit * r2, bool borrow, int precision);\nbool XMP_Sub_Int(digit * result, const digit * r1, unsigned short r2, bool borrow, int precision);\nint XMP_Unsigned_Mult(digit * prod, const digit * multiplicand, const digit * multiplier, int precision);\nint XMP_Unsigned_Mult_Int(digit * prod, const digit * multiplicand, short multiplier, int precision);\nint XMP_Signed_Mult_Int(digit * prod, const digit * multiplicand, signed short multiplier, int precision);\nint XMP_Signed_Mult(digit * prod, const digit * multiplicand, const digit * multiplier, int precision);\nunsigned short XMP_Unsigned_Div_Int(digit * quotient, digit const * dividend, unsigned short divisor, int precision);\nint XMP_Unsigned_Div(digit * remainder, digit * quotient, digit const * dividend, digit const * divisor, int precision);\nvoid XMP_Signed_Div(digit * remainder, digit * quotient, digit const * dividend, digit const * divisor, int precision);\nint XMP_Reciprocal(digit * quotient, const digit * divisor, int precision);\nvoid XMP_Decode_ASCII(char const * str, digit * mpn, int precision);\nvoid xmp_single_mul(unsigned short * prod, unsigned short * multiplicand, unsigned short multiplier, int precision);\nvoid XMP_Double_Mul(digit * prod, const digit * multiplicand, const digit * multiplier, int precision);\nint xmp_stage_modulus(const digit * n_modulus, int precision);\nint XMP_Mod_Mult(digit * prod, const digit * multiplicand, const digit * multiplier, int precision);\nvoid XMP_Mod_Mult_Clear(int precision);\nunsigned short mp_quo_digit(unsigned short * dividend);\nint xmp_exponent_mod(digit * expout, const digit * expin, const digit * exponent_ptr, const digit * modulus, int precision);\nbool XMP_Is_Small_Prime(const digit * candidate, int precision);\nbool XMP_Small_Divisors_Test(const digit * candidate, int precision);\nbool XMP_Fermat_Test(const digit * candidate_prime, unsigned rounds, int precision);\nvoid XMP_Inverse_A_Mod_B(digit * result, digit const * number, digit const * modulus, int precision);\nvoid XMP_Signed_Decode(digit * result, const unsigned char * from, int frombytes, int precision);\nvoid XMP_Unsigned_Decode(digit * result, const unsigned char * from, int frombytes, int precision);\nunsigned XMP_Encode(unsigned char * to, digit const * from, int precision);\nunsigned XMP_Encode(unsigned char * to, unsigned tobytes, digit const * from, int precision);\nvoid XMP_Randomize(digit * result, Straw & rng, int nbits, int precision);\nvoid XMP_Randomize(digit * result, Straw & rng, digit const * min, digit const * max, int precision);\nbool XMP_Is_Prime(digit const * prime, int precision);\nbool XMP_Rabin_Miller_Test(Straw & rng, digit const * w, int rounds, int precision);\nint XMP_DER_Length_Encode(unsigned long length, unsigned char * output);\nint XMP_DER_Encode(digit const * from, unsigned char * output, int precision);\nvoid XMP_DER_Decode(digit * result, unsigned char const * input, int precision);\n\n\n\ninline int XMP_Digits_To_Bits(int digits)\n{\n\treturn(digits << LOG_UNITSIZE);\n}\n\n\ninline int XMP_Bits_To_Digits(int bits)\n{\n\treturn ((bits + (UNITSIZE-1)) / UNITSIZE);\n}\n\n\ninline digit XMP_Bits_To_Mask(int bits)\n{\n\tif (!bits) return(0);\n\treturn(1 << ((bits-1) % UNITSIZE));\n}\n\n\ninline bool XMP_Is_Negative(const digit * r, int precision)\n{\n\treturn((signeddigit) *(r + (precision-1)) < 0);\n}\n\n\ninline bool XMP_Test_Eq_Int(digit const * r, int i, int p)\n{\n\treturn( (*r == i ) && XMP_Significance(r,p) <= 1 );\n}\n\n\ninline void XMP_Set_Bit(digit * r, unsigned bit)\n{\n\tr[bit >> LOG_UNITSIZE] |= ((digit)1 << (bit & (UNITSIZE-1)));\n}\n\ninline bool XMP_Test_Bit(const digit * r, unsigned bit)\n{\n\treturn (r[bit >> LOG_UNITSIZE] & ((digit)1 << (bit & (UNITSIZE-1))));\n}\n\n\n\n// Misc functions.\nvoid memrev(char * buffer, size_t length);\n\n#endif\n"
  },
  {
    "path": "CODE/MPGSET.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n* FILE\n*     MpgSet.cpp\n*\n* DESCRIPTION\n*     Mpeg movie settings manager\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     June 30, 1998\n*\n****************************************************************************/\n\n#include \"function.h\"\n\n#ifdef DVD\n#include \"mpgset.h\"\n\n#ifdef MCIMPEG\nbool EnumMCI(MCIDevice* desc, void* context);\n#endif\n\n/****************************************************************************\n*\n* NAME\n*     MPGSettings(DeviceName)\n*\n* DESCRIPTION\n*     Default constructor\n*\n* INPUTS\n*     DeviceName - Initial device to use for MPG playback (NULL = DXMedia)\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nMPGSettings::MPGSettings(const char* deviceName)\n\t: mDeviceName(NULL)\n\t{\n\tSetDeviceName(deviceName);\n\n\t#ifdef MCIMPEG\n\tint count = mMCI.GetDeviceCount();\n\n\tmMCIDevices = NULL;\n\tmCount = 0;\n\t\n\tif (count)\n\t\t{\n\t\tmMCIDevices = new MCIDevice[count];\n\t\t\n\t\tif (mMCIDevices)\n\t\t\t{\n\t\t\tmMCI.EnumerateDevices(EnumMCI, this);\n\t\t\t}\n\t\t}\n\t#endif\n\t}\n\n\nMPGSettings::MPGSettings(FileClass& file)\n\t: mDeviceName(NULL)\n\t{\n\tINIClass ini;\n\tchar buffer[256];\n\tchar* device = NULL;\n\n\t#ifdef MCIMPEG\n\tint count = mMCI.GetDeviceCount();\n\n\tmMCIDevices = NULL;\n\tmCount = 0;\n\t\n\t// Enumerate all the MCI devices that can play a movie\n\tif (count)\n\t\t{\n\t\tmMCIDevices = new MCIDevice[count];\n\n\t\tif (mMCIDevices)\n\t\t\t{\n\t\t\tmMCI.EnumerateDevices(EnumMCI, this);\n\t\t\t}\n\t\t}\n\n\t#endif\n\t\n\t// Retrieve the user specified device from the config file\n\tbuffer[0] = '\\0';\n\n\tif (ini.Load(file))\n\t\t{\n\t\tini.Get_String(\"MovieSettings\", \"Device\", \"Default\", buffer, sizeof(buffer));\n\t\t}\n\n\t// If there is a specification in the config and it isn't the default\n\tif ((strlen(buffer) != 0) && (stricmp(buffer, \"Default\") != 0))\n\t\t{\n\t\t#ifdef MCIMPEG\n\t\t// Search for selection\n\t\tfor (int i = 0; i < mCount; i++)\n\t\t\t{\n\t\t\tif (stricmp(buffer, mMCIDevices[i].name) == 0)\n\t\t\t\t{\n\t\t\t\tdevice = mMCIDevices[i].name;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t#endif\n\t\t}\n\n\tSetDeviceName(device);\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     ~MPGSettings\n*\n* DESCRIPTION\n*     Destructor\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nMPGSettings::~MPGSettings(void)\n\t{\n\tif (mDeviceName)\n\t\tfree(mDeviceName);\n\t\t\n\t#ifdef MCIMPEG\n\tif (mMCIDevices)\n\t\tdelete[] mMCIDevices;\n\t#endif\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     SetDeviceName(DeviceName)\n*\n* DESCRIPTION\n*     Change current device used for mpeg playback\n*\n* INPUTS\n*     DeviceName - Device name type (IE: mpegvideo)\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid MPGSettings::SetDeviceName(const char* deviceName)\n\t{\n\tif (mDeviceName)\n\t\tfree(mDeviceName);\n\n\tmDeviceName = NULL;\n\n\tif (deviceName)\n\t\tmDeviceName = strdup(deviceName);\n\t}\n\n\nbool MPGSettings::Save(FileClass& file)\n\t{\n\tINIClass ini;\n\n\tif (ini.Load(file))\n\t\t{\n\t\tconst char* device = GetDeviceName();\n\t\t\n\t\tif (device)\n\t\t\t{\n\t\t\tini.Put_String(\"MovieSettings\", \"Device\", device);\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tini.Put_String(\"MovieSettings\", \"Device\", \"Default\");\n\t\t\t}\n\t\t\t\n\t\tini.Save(file);\n\t\treturn true;\n\t\t}\n\n\treturn false;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     Dialog()\n*\n* DESCRIPTION\n*     Mpeg playback settings dialog\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid MPGSettings::Dialog(void)\n\t{\n\t//\tDialog & button dimensions\n\tint d_dialog_w = 200 *RESFACTOR;\n\tint d_dialog_h = 100 *RESFACTOR;\n\tint d_dialog_x = (((320*RESFACTOR) - d_dialog_w) / 2);\n\tint d_dialog_y = 70 * RESFACTOR;\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\n\n\tint d_txt6_h = 7 *RESFACTOR;\n\tint d_margin = 7 *RESFACTOR;\n\n\tint d_okay_w = 40 *RESFACTOR;\n\tint d_okay_h = 9 *RESFACTOR;\n\tint d_okay_x = d_dialog_x + d_margin + 20;\n\tint d_okay_y = ((d_dialog_y + d_dialog_h) - (d_okay_h + 20));\n\n\tint d_test_w = 40 *RESFACTOR;\n\tint d_test_h = 9 *RESFACTOR;\n\tint d_test_x = (d_dialog_cx - (d_test_w / 2));\n\tint d_test_y = ((d_dialog_y + d_dialog_h) - (d_test_h + 20));\n\n\tint d_cancel_w = 40 *RESFACTOR;\n\tint d_cancel_h = 9 *RESFACTOR;\n\tint d_cancel_x = ((d_dialog_x + d_dialog_w) - (d_cancel_w + d_margin + 20));\n\tint d_cancel_y = ((d_dialog_y + d_dialog_h) - (d_cancel_h + 20));\n\n\tint d_method_w = 165 * RESFACTOR;\n\tint d_method_h = 50 * RESFACTOR;\n\tint d_method_x = (d_dialog_cx - (d_method_w / 2));\n\tint d_method_y = (d_dialog_y + 40);\n\n\t//\tButton enumerations:\n\tenum\n\t\t{\n\t\tBUTTON_OKAY = 100,\n\t\tBUTTON_TEST,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_METHOD,\n\t\tNUM_OF_BUTTONS = 4,\n\t\t};\n\n\tint num_of_buttons = NUM_OF_BUTTONS;\n\t\n\t//\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\ttypedef enum\n\t\t{\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\t\t// includes map interior & coord values\n\t\tREDRAW_BACKGROUND,\t// includes box, map bord, key, coord labels, btns\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t\t} RedrawType;\n\n\t//\tDialog variables:\n\tKeyNumType input;\t\t\t\t\t\t\t\t// input from user\n\tbool process;\t\t\t\t\t\t\t\t\t// loop while true\n\tRedrawType display;\t\t\t\t\t\t\t// true = re-draw everything\n\tint selection;\n\tbool pressed;\n\tint curbutton;\n\tTextButtonClass * buttons[NUM_OF_BUTTONS];\n\tint i;\n\tchar* origDevice = NULL;\n\n\t//\tButtons\n\tControlClass * commands = NULL;\t\t\t\t// the button list\n\n\tTextButtonClass okaybtn(BUTTON_OKAY, TXT_OK, TPF_BUTTON,\n\t\td_okay_x, d_okay_y, d_okay_w, d_okay_h);\n\n\tTextButtonClass testbtn(BUTTON_TEST, \"Test\", TPF_BUTTON,\n\t\td_test_x, d_test_y, d_test_w, d_test_h);\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,\n\t\td_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n\n\tListClass method(BUTTON_METHOD, d_method_x, d_method_y, d_method_w,\n\t\td_method_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\t\t\n\t//\tInitialize\n\tSet_Logic_Page(SeenBuff);\n\t\n\t//\tCreate the list\n\tcommands = &okaybtn;\n\ttestbtn.Add_Tail(*commands);\n\tcancelbtn.Add_Tail(*commands);\n\tmethod.Add_Tail(*commands);\n\n\t//\tFill array of button ptrs\n\tcurbutton = 0;\n\tbuttons[0] = &okaybtn;\n\tbuttons[1] = &testbtn;\n\tbuttons[2] = &cancelbtn;\n\tbuttons[curbutton]->Turn_On();\n\n\tKeyboard->Clear();\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(), TBLACK,\n\t\tTPF_CENTER | TPF_TEXT);\n\n\t// Add device to device control\n\tmethod.Add_Item(\"DirectX Media (Default)\");\n\n\t#ifdef MCIMPEG\n\tfor (i = 0; i < mCount; i++)\n\t\t{\n\t\tif (mMCIDevices[i].description != NULL)\n\t\t\t{\n\t\t\tmethod.Add_Item(mMCIDevices[i].description);\n\t\t\t}\n\t\t}\n\t#endif\n\t\n\tmethod.Set_Selected_Index(0);\n\t\n\t#ifdef MCIMPEG\n\t// Search for current selection\n\tif (GetDeviceName())\n\t\t{\n\t\tfor (i = 0; i < mCount; i++)\n\t\t\t{\n\t\t\tif (stricmp(GetDeviceName(), mMCIDevices[i].name) == 0)\n\t\t\t\t{\n\t\t\t\tmethod.Set_Selected_Index(i + 1);\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t#endif\n\t\n\t// Save original device selection\n\tif (GetDeviceName())\n\t\torigDevice = strdup(GetDeviceName());\n\t\t\t\t\t\t\n\t//------------------------------------------------------------------------\n\t//\tMain Processing Loop\n\t//------------------------------------------------------------------------\n\tdisplay = REDRAW_ALL;\n\tprocess = true;\n\tpressed = false;\n\t\n\twhile (process)\n\t\t{\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored)\n\t\t\t{\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t\t}\n\t\t#endif\n\n\t\t//\tInvoke game callback\n\t\tCall_Back();\n\n\t\t//\tRefresh display if needed\n\t\tif (display)\n\t\t\t{\n\t\t\tHide_Mouse();\n\t\t\t\n\t\t\tif (display >= REDRAW_BACKGROUND)\n\t\t\t\t{\n\t\t\t\t//\tRefresh the backdrop\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tCCPalette.Set();\n\n\t\t\t\t//\tDraw the background\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\t\t\t\tDraw_Caption(\"Movie Settings\", d_dialog_x, d_dialog_y, d_dialog_w);\n\t\t\t\t}\n\n\t\t\t//\tRedraw buttons\n\t\t\tif (display >= REDRAW_BUTTONS)\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t\t\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t\t}\n\n\t\t//\tGet user input\n\t\tinput = commands->Input();\n\n\t\t//\tProcess input\n\t\tswitch (input)\n\t\t\t{\n\t\t\tcase (BUTTON_OKAY | KN_BUTTON):\n\t\t\t\tselection = BUTTON_OKAY;\n\t\t\t\tpressed = true;\n\t\t\tbreak;\n\n\t\t\tcase (BUTTON_TEST | KN_BUTTON):\n\t\t\t\tselection = BUTTON_TEST;\n\t\t\t\tpressed = true;\n\t\t\tbreak;\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tselection = BUTTON_CANCEL;\n\t\t\t\tpressed = true;\n\t\t\tbreak;\n\n\t\t\tcase KN_UP:\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tcurbutton--;\n\t\t\t\t\n\t\t\t\tif (curbutton < 0)\n\t\t\t\t\tcurbutton = (num_of_buttons - 1);\n\t\t\t\t\t\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\tbreak;\n\n\t\t\tcase KN_DOWN:\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tcurbutton++;\n\t\t\t\t\n\t\t\t\tif (curbutton > (num_of_buttons - 1))\n\t\t\t\t\tcurbutton = 0;\n\t\t\t\t\t\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\tbreak;\n\n\t\t\tcase KN_RETURN:\n\t\t\t\tselection = curbutton + BUTTON_OKAY;\n\t\t\t\tpressed = true;\n\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\tbreak;\n\t\t\t}\n\n\t\tif (pressed)\n\t\t\t{\n\t\t\t// to make sure the selection is correct in case they used the mouse\n\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\tcurbutton = selection - BUTTON_OKAY;\n\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\tbuttons[curbutton]->IsPressed = true;\n\t\t\tbuttons[curbutton]->Draw_Me(true);\n\n\t\t\tswitch (selection)\n\t\t\t\t{\n\t\t\t\tcase (BUTTON_TEST):\n\t\t\t\t\tbuttons[curbutton]->IsPressed = false;\n\n\t\t\t\t\tif (method.Current_Index() == 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\tSetDeviceName(NULL);\n\t\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\ti = method.Current_Index();\n\t\t\t\t\t\t#ifdef MCIMPEG\n\t\t\t\t\t\tSetDeviceName(mMCIDevices[i - 1].name);\n\t\t\t\t\t\t#endif\n\t\t\t\t\t\t}\n\n\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tVisiblePage.Clear();\n\t\t\t\t\tPlayMpegMovie(\"acrop\");\n\t\t\t\t\tKeyboard->Clear();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t\tTheme.Queue_Song(THEME_CRUS);\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\n\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\tbuttons[0]->Turn_On();\n\t\t\t\t\tcurbutton = 0;\n\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_OKAY):\n\t\t\t\t\tprocess = false;\n\t\t\t\t\t\n\t\t\t\t\tif (method.Current_Index() == 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\tSetDeviceName(NULL);\n\t\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\ti = method.Current_Index();\n\t\t\t\t\t\t#ifdef MCIMPEG\n\t\t\t\t\t\tSetDeviceName(mMCIDevices[i - 1].name);\n\t\t\t\t\t\t#endif\n\t\t\t\t\t\t}\n\n\t\t\t\t\t{\n\t\t\t\t\tRawFileClass file(CONFIG_FILE_NAME);\n\t\t\t\t\tSave(file);\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_CANCEL):\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tSetDeviceName(origDevice);\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tpressed = false;\n\t\t\t}\n\t\t}\n\n\tif (origDevice)\n\t\tfree(origDevice);\n\t}\n\n\n#ifdef MCIMPEG\n/****************************************************************************\n*\n* NAME\n*     EnumMCI(DeviceDesc, Context)\n*\n* DESCRIPTION\n*     MCI device enumeration callback\n*\n* INPUTS\n*     DeviceDesc - MCI device description\n*     Context    - User defined context variable\n*\n* RESULT\n*     Continue - Continue with next device flag\n*\n****************************************************************************/\n\nbool EnumMCI(MCIDevice* desc, void* context)\n\t{\n\tMPGSettings* mpgset = (MPGSettings*)context;\n\n\t// Digital video device type?\n\tif (desc->type == MCI_DEVTYPE_DIGITAL_VIDEO)\n\t\t{\n\t\tif (MciMovie)\n\t\t\t{\n\t\t\tCCFileClass file;\n\t\t\tconst char* filename;\n\n\t\t\tfilename = file.Set_Name(\"movies\\\\acrop.mpg\");\n\t\n\t\t\tif (!file.Is_Available())\n\t\t\t\t{\n\t\t\t\tchar buffer[256];\n\t\t\t\tsprintf(buffer, \"Couldn't test MCI device %s\\n\", desc->name);\n\t\t\t\tVisiblePage.Clear();\n\t\t\t\tGamePalette.Set();\n\t\t\t\tShow_Mouse();\n\t\t\t\tWWMessageBox().Process(buffer);\n\t\t\t\tHide_Mouse();\n\t\t\t\tVisiblePage.Clear();\n\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\n\t\t\tif (MciMovie->Open(filename, desc->name))\n\t\t\t\t{\n\t\t\t\tMciMovie->Close();\n\t\t\t\tmemcpy((void*)&mpgset->mMCIDevices[mpgset->mCount], (void*)desc,\n\t\t\t\t\tsizeof(MCIDevice));\n\t\t\t\tmpgset->mCount++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\treturn true;\n\t}\n#endif\n#endif\n"
  },
  {
    "path": "CODE/MPGSET.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef _MPGSETTINGS_H_\n#define _MPGSETTINGS_H_\n\n#include \"function.h\"\n\n#ifdef DVD\n#include \"mci.h\"\n#include \"rawfile.h\"\n\nclass MPGSettings\n\t{\n\tpublic:\n\t\tMPGSettings(const char* deviceName);\n\t\tMPGSettings(FileClass& file);\n\t\tvirtual ~MPGSettings(void);\n\n\t\tvoid SetDeviceName(const char* device);\n\t\tconst char* GetDeviceName(void) const\n\t\t\t{return mDeviceName;}\n\t\tbool Save(FileClass& file);\n\t\tvoid Dialog(void);\n\n\t\tchar* mDeviceName;\n\n\t\t#ifdef MCIMPEG\n\t\tMCI mMCI;\n\t\tunsigned int mCount;\n\t\tMCIDevice* mMCIDevices;\n\t\t#endif\n\t};\n\n#endif // DVD\n#endif // _MPGSETTINGS_H_\n"
  },
  {
    "path": "CODE/MPLAYER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MPLAYER.CPP 3     3/13/97 2:06p Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MPLAYER.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Bill Randolph                                                *\n *                                                                                             *\n *                   Start Date : April 14, 1995                                               *\n *                                                                                             *\n *                  Last Update : November 30, 1995 [BRR]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Select_MPlayer_Game -- prompts user for NULL-Modem, Modem, or Network game                *\n *   Clear_Listbox -- clears the given list box                                                *\n *   Clear_Vector -- clears the given NodeNameType vector                                      *\n *   Computer_Message -- \"sends\" a message from the computer                                   *\n *   Garble_Message -- \"garbles\" a message                                                     *\n *   Surrender_Dialog -- Prompts user for surrendering                                         *\n *   Abort_Dialog -- Prompts user for confirmation on aborting the mission\t\t\t\t\t\t\t  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\nextern bool Is_Mission_Counterstrike (char *file_name);\n\n#ifdef WOLAPI_INTEGRATION\n#include \"WolStrng.h\"\n#endif\n\n/***********************************************************************************************\n * Select_MPlayer_Game -- prompts user for NULL-Modem, Modem, or Network game                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      GAME_NORMAL, GAME_MODEM, etc.                                                          *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nGameType Select_MPlayer_Game (void)\n{\n\t//------------------------------------------------------------------------\n\t//\tDialog & button dimensions\n\t//------------------------------------------------------------------------\n\tint d_dialog_w = 190 *RESFACTOR;\n#ifdef WOLAPI_INTEGRATION\n\tint d_dialog_h = 89 * RESFACTOR;\t\t\t//\tajw\n\tint\td_dialog_y = (((255 * RESFACTOR) - d_dialog_h) / 2);\n#else\n\tint d_dialog_h = 78 *RESFACTOR;\n\tint d_dialog_y = 90 * RESFACTOR;\n#endif\n\tint d_dialog_x = (((320*RESFACTOR) - d_dialog_w) / 2);\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\n\n\tint d_txt6_h = 7 *RESFACTOR;\n\tint d_margin = 7 *RESFACTOR;\n\n\tint d_modemserial_w = 80 *RESFACTOR;\n\tint d_modemserial_h = 9 *RESFACTOR;\n\tint d_modemserial_x = d_dialog_cx - d_modemserial_w / 2;\n\tint d_modemserial_y = d_dialog_y + d_margin + d_txt6_h + d_margin;\n\n\tint d_skirmish_w = 80 *RESFACTOR;\n\tint d_skirmish_h = 9 *RESFACTOR;\n\tint d_skirmish_x = d_dialog_cx - d_skirmish_w / 2;\n\tint d_skirmish_y = d_modemserial_y + d_modemserial_h + 2*RESFACTOR;\n\n\tint d_ipx_w = 80 *RESFACTOR;\n\tint d_ipx_h = 9 *RESFACTOR;\n\tint d_ipx_x = d_dialog_cx - d_ipx_w / 2;\n\tint d_ipx_y = d_skirmish_y + d_skirmish_h + 2*RESFACTOR;\n\n#ifdef WOLAPI_INTEGRATION\n\t//\tajw 7/2/98 - added button\n\tint d_wol_w = 80 * RESFACTOR;\n\tint d_wol_h = 9 * RESFACTOR;\n\tint d_wol_x = d_dialog_cx - d_wol_w / 2;\n\tint d_wol_y = d_ipx_y + d_ipx_h + 2*RESFACTOR;\n#endif\n\n\tint d_cancel_w = 60 *RESFACTOR;\n\tint d_cancel_h = 9 *RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - d_cancel_w / 2;\n#ifdef WOLAPI_INTEGRATION\n\tint d_cancel_y = d_wol_y + d_wol_h + d_margin;\n#else\n\tint d_cancel_y = d_ipx_y + d_ipx_h + d_margin;\n#endif\n\n\t#ifdef WIN32\n\tGraphicBufferClass seen_buff_save(VisiblePage.Get_Width(), VisiblePage.Get_Height(), (void*)NULL);\n\t#endif\n\n\t//------------------------------------------------------------------------\n\t//\tButton enumerations:\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tBUTTON_MODEMSERIAL = 100,\n\t\tBUTTON_SKIRMISH,\n\t\tBUTTON_IPX,\n#ifdef WOLAPI_INTEGRATION\n\t\tBUTTON_WOL,\t\t\t\t//\tajw\n#endif\n\t\tBUTTON_CANCEL,\n\n#ifdef WOLAPI_INTEGRATION\n\t\tNUM_OF_BUTTONS = 5,\t\t//\tajw\n#else\n\t\tNUM_OF_BUTTONS = 4,\n#endif\n\t};\n\n\tint num_of_buttons = NUM_OF_BUTTONS - (Ipx.Is_IPX() ? 0 : 1);\n\t//------------------------------------------------------------------------\n\t//\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t//------------------------------------------------------------------------\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\t\t// includes map interior & coord values\n\t\tREDRAW_BACKGROUND,\t// includes box, map bord, key, coord labels, btns\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t//------------------------------------------------------------------------\n\t//\tDialog variables:\n\t//------------------------------------------------------------------------\n\tKeyNumType input;\t\t\t\t\t\t\t\t// input from user\n\tbool process;\t\t\t\t\t\t\t\t\t// loop while true\n\tRedrawType display;\t\t\t\t\t\t\t// true = re-draw everything\n\tGameType retval;\t\t\t\t\t\t\t\t// return value\n\tint selection;\n\tbool pressed;\n\tint curbutton;\n\tTextButtonClass * buttons[NUM_OF_BUTTONS];\n\n\t//------------------------------------------------------------------------\n\t//\tButtons\n\t//------------------------------------------------------------------------\n\tControlClass * commands = NULL;\t\t\t\t// the button list\n\n\n\t//------------------------------------------------------------------------\n\t// If IPX not active then do only the modem serial dialog\n\t//------------------------------------------------------------------------\n//\tif ( !Ipx.Is_IPX() ) {\n//\t\treturn( Select_Serial_Dialog() );\n//\t}\n\n\n\tTextButtonClass modemserialbtn (BUTTON_MODEMSERIAL, TXT_MODEM_SERIAL, TPF_BUTTON,\n\t\td_modemserial_x, d_modemserial_y, d_modemserial_w, d_modemserial_h);\n\n\tTextButtonClass skirmishbtn (BUTTON_SKIRMISH, TXT_SKIRMISH, TPF_BUTTON,\n\t\td_skirmish_x, d_skirmish_y, d_skirmish_w, d_skirmish_h);\n\n\tTextButtonClass ipxbtn (BUTTON_IPX, TXT_NETWORK, TPF_BUTTON,\n\t\td_ipx_x, d_ipx_y, d_ipx_w, d_ipx_h);\n\n#ifdef WOLAPI_INTEGRATION\n\t//\tajw\n\tTextButtonClass wolbtn(BUTTON_WOL, TXT_WOL_INTERNETBUTTON, TPF_BUTTON,\n\t\td_wol_x, d_wol_y, d_wol_w, d_wol_h);\n#endif\n\n\tif(!Ipx.Is_IPX()) {\n\t\td_cancel_y = d_ipx_y;\n\t\td_dialog_h -= d_cancel_h;\n\t}\n\n\tTextButtonClass cancelbtn (BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,\n\t\td_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n\n\t//------------------------------------------------------------------------\n\t//\tInitialize\n\t//------------------------------------------------------------------------\n\tSet_Logic_Page(SeenBuff);\n#ifdef WIN32\n\tVisiblePage.Blit(seen_buff_save);\n#endif\n\t//------------------------------------------------------------------------\n\t//\tCreate the list\n\t//------------------------------------------------------------------------\n\tcommands = &modemserialbtn;\n\tskirmishbtn.Add_Tail(*commands);\n\tif(Ipx.Is_IPX()) {\n\t\tipxbtn.Add_Tail(*commands);\n\t}\n#ifdef WOLAPI_INTEGRATION\n\twolbtn.Add_Tail(*commands);\t\t\t//\tajw\n#endif\n\tcancelbtn.Add_Tail(*commands);\n\n\t//------------------------------------------------------------------------\n\t//\tFill array of button ptrs\n\t//------------------------------------------------------------------------\n\tcurbutton = 0;\n\tbuttons[0] = &modemserialbtn;\n\tbuttons[1] = &skirmishbtn;\n\tif(Ipx.Is_IPX()) {\n\t\tbuttons[2] = &ipxbtn;\n#ifdef WOLAPI_INTEGRATION\n\t\tbuttons[3] = &wolbtn;\t\t\t//\tajw\n\t\tbuttons[4] = &cancelbtn;\n#else\n\t\tbuttons[3] = &cancelbtn;\n#endif\n\t} else {\n#ifdef WOLAPI_INTEGRATION\n\t\tbuttons[2] = &wolbtn;\t\t\t//\tajw\n\t\tbuttons[3] = &cancelbtn;\n#else\n\t\tbuttons[2] = &cancelbtn;\n#endif\n\t}\n\tbuttons[curbutton]->Turn_On();\n\n\tKeyboard->Clear();\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(), TBLACK,\n\t\tTPF_CENTER | TPF_TEXT);\n\n\t//------------------------------------------------------------------------\n\t//\tMain Processing Loop\n\t//------------------------------------------------------------------------\n\tdisplay = REDRAW_ALL;\n\tprocess = true;\n\tpressed = false;\n\twhile (process) {\n\t\t\t#ifdef WIN32\n\t\t\t/*\n\t\t\t** If we have just received input focus again after running in the background then\n\t\t\t** we need to redraw.\n\t\t\t*/\n\t\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\t\tseen_buff_save.Blit(VisiblePage);\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t}\n\t\t\t#endif\n\n\t\t//.....................................................................\n\t\t//\tInvoke game callback\n\t\t//.....................................................................\n\t\tCall_Back();\n\n\t\t//.....................................................................\n\t\t//\tRefresh display if needed\n\t\t//.....................................................................\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tRefresh the backdrop\n\t\t\t\t//...............................................................\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tCCPalette.Set();\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tDraw the background\n\t\t\t\t//...............................................................\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\t\t\t\tDraw_Caption (TXT_SELECT_MPLAYER_GAME, d_dialog_x, d_dialog_y, d_dialog_w);\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw buttons\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tGet user input\n\t\t//.....................................................................\n\t\tinput = commands->Input();\n\n\t\t//.....................................................................\n\t\t//\tProcess input\n\t\t//.....................................................................\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_MODEMSERIAL | KN_BUTTON):\n\t\t\t\tselection = BUTTON_MODEMSERIAL;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_SKIRMISH | KN_BUTTON):\n\t\t\t\tselection = BUTTON_SKIRMISH;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_IPX | KN_BUTTON):\n\t\t\t\tselection = BUTTON_IPX;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\tcase (BUTTON_WOL | KN_BUTTON):\t\t\t//\tajw\n\t\t\t\tselection = BUTTON_WOL;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n#endif\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tselection = BUTTON_CANCEL;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase KN_UP:\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tcurbutton--;\n\t\t\t\tif (curbutton < 0)\n\t\t\t\t\tcurbutton = (num_of_buttons - 1);\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase KN_DOWN:\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tcurbutton++;\n\t\t\t\tif (curbutton > (num_of_buttons - 1) )\n\t\t\t\t\tcurbutton = 0;\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase KN_RETURN:\n\t\t\t\tselection = curbutton + BUTTON_MODEMSERIAL;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (pressed) {\n\n\t\t\t//..................................................................\n\t\t\t// to make sure the selection is correct in case they used the mouse\n\t\t\t//..................................................................\n\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\tcurbutton = selection - BUTTON_MODEMSERIAL;\n\t\t\tif(selection == BUTTON_CANCEL && !Ipx.Is_IPX()) curbutton--;\n\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\tbuttons[curbutton]->IsPressed = true;\n\t\t\tbuttons[curbutton]->Draw_Me(true);\n\n\t\t\tswitch (selection) {\n\t\t\t\tcase (BUTTON_MODEMSERIAL):\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// Pop up the modem/serial/com port dialog\n\t\t\t\t\t//............................................................\n\t\t\t\t\tretval = Select_Serial_Dialog();\n\n\t\t\t\t\tif (retval != GAME_NORMAL) {\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbuttons[curbutton]->IsPressed = false;\n\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_SKIRMISH):\n\t\t\t\t\tSession.Type = GAME_SKIRMISH;\n\t\t\t\t\tif (Com_Scenario_Dialog(true)) {\n\t\t\t\t\t\tretval = GAME_SKIRMISH;\n\t\t\t\t\t\tprocess = false;\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\tbAftermathMultiplayer = Is_Aftermath_Installed();\n\t\t\t\t\t\t//\tajw I'll bet this was needed before also...\n\t\t\t\t\t\tSession.ScenarioIsOfficial = Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official();\n#endif\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbuttons[curbutton]->IsPressed = false;\n\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_IPX):\n\t\t\t\t\tretval = GAME_IPX;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\tcase (BUTTON_WOL):\t\t\t\t//\tajw\n\t\t\t\t\tretval = GAME_INTERNET;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n#endif\n\n\t\t\t\tcase (BUTTON_CANCEL):\n\t\t\t\t\tretval = GAME_NORMAL;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tpressed = false;\n\t\t}\n\t}\n\treturn(retval);\n\n}\t/* end of Select_MPlayer_Game */\n\n\n/***************************************************************************\n * Clear_Listbox -- clears the given list box                              *\n *                                                                         *\n * This routine assumes the items in the given list box are character\t\t*\n * buffers; it deletes each item in the list, then clears the list.\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tlist\t\t\tptr to listbox\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid Clear_Listbox(ListClass * list)\n{\n\tchar * item;\n\n\t//------------------------------------------------------------------------\n\t//\tClear the list box\n\t//------------------------------------------------------------------------\n\twhile (list->Count()) {\n\t\titem = (char *)(list->Get_Item(0));\n\t\tlist->Remove_Item(item);\n\t\tdelete [] item;\n\t}\n\tlist->Flag_To_Redraw();\n\n}\t// end of Clear_Listbox\n\n\n/***************************************************************************\n * Clear_Vector -- clears the given NodeNameType vector                    *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tvector\t\tptr to vector to clear\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid Clear_Vector(DynamicVectorClass <NodeNameType *> * vector)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tClear the 'Players' Vector\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < vector->Count(); i++) {\n\t\tdelete (*vector)[i];\n\t}\n\tvector->Clear();\n\n}\t// end of Clear_Vector\n\n\n/***************************************************************************\n * Computer_Message -- \"sends\" a message from the computer                 *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/06/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid Computer_Message(void)\n{\n#ifdef NEVER\n\tint color;\n\tHousesType house;\n\tHouseClass * ptr;\n\n\t//------------------------------------------------------------------------\n\t//\tFind the computer house that the message will be from\n\t//------------------------------------------------------------------------\n\tfor (house = HOUSE_MULTI1; house < (HOUSE_MULTI1 + Session.MaxPlayers); house++) {\n\t\tptr = HouseClass::As_Pointer(house);\n\n\t\tif (!ptr || ptr->IsHuman || ptr->IsDefeated) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tDecode this house's color\n\t\t//.....................................................................\n\t\tcolor = ptr->RemapColor;\n\n\t\t//.....................................................................\n\t\t//\tWe now have a 1/4 chance of echoing one of the human players'\n\t\t// messages back.\n\t\t//.....................................................................\n\t\tif (Percent_Chance(25)) {\n\n\t\t\t//..................................................................\n\t\t\t//\tNow we have a 1/3 chance of garbling the human message.\n\t\t\t//..................................................................\n\t\t\tif (Percent_Chance(33)) {\n\t\t\t\tGarble_Message(Session.LastMessage);\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tOnly add the message if there is one to add.\n\t\t\t//..................................................................\n\t\t\tif (strlen(Session.LastMessage)) {\n\t\t\t\tSession.Messages.Add_Message(Text_String(TXT_COMPUTER), 0,\n\t\t\t\t\tSession.LastMessage,\n\t\t\t\t\tcolor, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tSession.Messages.Add_Message(Text_String(TXT_COMPUTER), 0,\n\t\t\t\tText_String(TXT_COMP_MSG1 + Random_Pick(0, 12)),\n\t\t\t\tcolor, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\t}\n\n\t\treturn;\n\t}\n#endif\n}\t/* end of Computer_Message */\n\n\n#ifdef NEVER\n/***************************************************************************\n * Garble_Message -- \"garbles\" a message                                   *\n *                                                                         *\n * INPUT:                                                                  *\n *      buf      buffer to garble; stores output message                   *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/06/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Garble_Message(char * buf)\n{\n\tchar txt[80];\n\tchar punct[20];\t\t// for punctuation\n\tchar * p;\t\t\t\t\t// working ptr\n\tint numwords;\t\t\t// # words in the phrase\n\tchar * words[40];\t\t// ptrs to various words in the phrase\n\tint i,j;\n\n\t//------------------------------------------------------------------------\n\t//\tPull off any trailing punctuation\n\t//------------------------------------------------------------------------\n\tp = buf + strlen(buf) - 1;\n\twhile (1) {\n\t\tif (p < buf)\n\t\t\tbreak;\n\t\tif (p[0]=='!' || p[0]=='.' || p[0]=='?') {\n\t\t\tp--;\n\t\t}\n\t\telse {\n\t\t\tp++;\n\t\t\tbreak;\n\t\t}\n\t\tif (strlen(p) >= (sizeof(punct) - 1) ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\tstrcpy (punct, p);\n\tp[0] = 0;\n\n\tfor (i = 0; i < 40; i++) {\n\t\twords[i] = NULL;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCopy the original buffer\n\t//------------------------------------------------------------------------\n\tstrcpy(txt, buf);\n\n\t//------------------------------------------------------------------------\n\t//\tSplit it up into words\n\t//------------------------------------------------------------------------\n\tp = strtok (txt, \" \");\n\tnumwords = 0;\n\twhile (p) {\n\t\twords[numwords] = p;\n\t\tnumwords++;\n\t\tp = strtok (NULL, \" \");\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNow randomly put the words back.  Don't use the real random-number\n\t//\tgenerator, since different machines will have different LastMessage's,\n\t//\tand will go out of sync.\n\t//------------------------------------------------------------------------\n\tbuf[0] = 0;\n\tfor (i = 0; i < numwords; i++) {\n\t\tj = Sim_IRandom(0, numwords);\n\t\tif (words[j] == NULL) {\t\t// this word has been used already\n\t\t\ti--;\n\t\t\tcontinue;\n\t\t}\n\t\tstrcat(buf, words[j]);\n\t\twords[j] = NULL;\n\t\tif (i < numwords-1)\n\t\t\tstrcat(buf, \" \");\n\t}\n\tstrcat(buf, punct);\n\n}\t/* end of Garble_Message */\n#endif\n\n\n/***************************************************************************\n * Surrender_Dialog -- Prompts user for surrendering                       *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = user cancels, 1 = user wants to surrender.                     *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/05/1995 BRR : Created.                                             *\n *=========================================================================*/\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\nint Surrender_Dialog(int text)\n{\n\treturn Surrender_Dialog( Text_String( text ) );\n}\n#endif\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\nint Surrender_Dialog(const char* text)\n#else\nint Surrender_Dialog(int text)\n#endif\n{\n\t//------------------------------------------------------------------------\n\t//\tDialog & button dimensions\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tD_DIALOG_W = 240*RESFACTOR,\t\t\t\t\t\t\t// dialog width\n\t\tD_DIALOG_H = 63*RESFACTOR,\t\t\t\t\t\t\t\t// dialog height\n\t\tD_DIALOG_X = ((320*RESFACTOR - D_DIALOG_W) / 2),// centered x-coord\n\t\tD_DIALOG_Y = ((200*RESFACTOR - D_DIALOG_H) / 2),// centered y-coord\n\t\tD_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),\t\t// coord of x-center\n\n\t\tD_TXT6_H = 7*RESFACTOR,\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\t\tD_MARGIN = 5*RESFACTOR,\t\t\t\t\t\t\t\t\t// margin width/height\n\t\tD_TOPMARGIN = 20*RESFACTOR,\t\t\t\t\t\t\t// top margin\n\n\t\tD_OK_W = 45*RESFACTOR,\t\t\t\t\t\t\t\t\t// OK width\n\t\tD_OK_H = 9*RESFACTOR,\t\t\t\t\t\t\t\t\t// OK height\n\t\tD_OK_X = D_DIALOG_CX - D_OK_W - 5*RESFACTOR,\t\t// OK x\n\t\tD_OK_Y = D_DIALOG_Y + D_DIALOG_H - D_OK_H - D_MARGIN*2,\t// OK y\n\n\t\tD_CANCEL_W = 45*RESFACTOR,\t\t\t\t\t\t\t\t// Cancel width\n\t\tD_CANCEL_H = 9*RESFACTOR,\t\t\t\t\t\t\t\t// Cancel height\n\t\tD_CANCEL_X = D_DIALOG_CX + 5*RESFACTOR,\t\t\t// Cancel x\n\t\tD_CANCEL_Y = D_DIALOG_Y + D_DIALOG_H - D_CANCEL_H - D_MARGIN*2, // Cancel y\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tButton enumerations\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tBUTTON_OK = 100,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tButtons\n\t//------------------------------------------------------------------------\n\tControlClass * commands = NULL;\t\t// the button list\n\n\tTextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_BUTTON, D_OK_X, D_OK_Y, D_OK_W, D_OK_H);\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W, D_CANCEL_H);\n\n\tint curbutton;\n\tTextButtonClass * buttons[2];\n\tcurbutton = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInitialize\n\t//------------------------------------------------------------------------\n\tSet_Logic_Page(SeenBuff);\n\n\t//------------------------------------------------------------------------\n\t//\tCreate the button list\n\t//------------------------------------------------------------------------\n\tcommands = &okbtn;\n\tcancelbtn.Add_Tail(*commands);\n\n\tbuttons[0] = &okbtn;\n\tbuttons[1] = &cancelbtn;\n\tbuttons[curbutton]->Turn_On();\n\n\t//------------------------------------------------------------------------\n\t//\tMain Processing Loop\n\t//------------------------------------------------------------------------\n\tint retcode = 0;\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t//.....................................................................\n\t\t//\tInvoke game callback\n\t\t//.....................................................................\n\t\tif (Session.Type != GAME_SKIRMISH) {\n\t\t\tif (Main_Loop()) {\n\t\t\t\tretcode = 0;\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tRefresh display if needed\n\t\t//.....................................................................\n\t\tif (display) {\n\t\t\tdisplay = false;\n\n\t\t\t//..................................................................\n\t\t\t//\tDisplay the dialog box\n\t\t\t//..................................................................\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\t\t\tDraw_Caption(TXT_NONE, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\n\t\t\t//...............................................................\n\t\t\t//\tDraw the captions\n\t\t\t//...............................................................\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t\tFancy_Text_Print(text,\n\t\t\t\tD_DIALOG_CX, D_DIALOG_Y + D_TOPMARGIN,\n\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\tTPF_CENTER | TPF_TEXT);\n#else\n\t\t\tFancy_Text_Print(Text_String(text),\n\t\t\t\tD_DIALOG_CX, D_DIALOG_Y + D_TOPMARGIN,\n\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\tTPF_CENTER | TPF_TEXT);\n#endif\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw the buttons\n\t\t\t//..................................................................\n\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\tShow_Mouse();\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tGet user input\n\t\t//.....................................................................\n\t\tKeyNumType input = commands->Input();\n\n\t\t//.....................................................................\n\t\t//\tProcess input\n\t\t//.....................................................................\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tretcode = 1;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tretcode = 0;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\t\tif (curbutton == 0) {\n\t\t\t\t\tretcode = 1;\n\t\t\t\t} else {\n\t\t\t\t\tretcode = 0;\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_ESC):\n\t\t\t\tretcode = 0;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RIGHT):\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tcurbutton++;\n\t\t\t\tif (curbutton > 1) {\n\t\t\t\t\tcurbutton = 0;\n\t\t\t\t}\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_LEFT):\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tcurbutton--;\n\t\t\t\tif (curbutton < 0) {\n\t\t\t\t\tcurbutton = 1;\n\t\t\t\t}\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tRedraw the display\n\t//------------------------------------------------------------------------\n\tHidPage.Clear();\n\tMap.Flag_To_Redraw(true);\n\tMap.Render();\n\n\treturn (retcode);\n}\n\n\n/***************************************************************************\n * Abort_Dialog -- Prompts user for confirmation on aborting the mission\t*\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      1 = user confirms abort, 0 = user cancels\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/05/1995 BRR : Created.                                             *\n *=========================================================================*/\nint Abort_Dialog(void)\n{\n\t//------------------------------------------------------------------------\n\t//\tDialog & button dimensions\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tD_DIALOG_W = 170*RESFACTOR,\t\t\t\t\t\t\t// dialog width\n\t\tD_DIALOG_H = 63*RESFACTOR,\t\t\t\t\t\t\t\t// dialog height\n\t\tD_DIALOG_X = ((320*RESFACTOR - D_DIALOG_W) / 2),// centered x-coord\n\t\tD_DIALOG_Y = ((200*RESFACTOR - D_DIALOG_H) / 2),// centered y-coord\n\t\tD_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),\t\t// coord of x-center\n\n\t\tD_TXT6_H = 7*RESFACTOR,\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\t\tD_MARGIN = 5*RESFACTOR,\t\t\t\t\t\t\t\t\t// margin width/height\n\t\tD_TOPMARGIN = 20*RESFACTOR,\t\t\t\t\t\t\t// top margin\n\n\t\tD_YES_W = 45*RESFACTOR,\t\t\t\t\t\t\t\t\t// YES width\n\t\tD_YES_H = 9*RESFACTOR,\t\t\t\t\t\t\t\t\t// YES height\n\t\tD_YES_X = D_DIALOG_CX - D_YES_W - 5*RESFACTOR,\t// YES x\n\t\tD_YES_Y = D_DIALOG_Y + D_DIALOG_H - D_YES_H - D_MARGIN*2,\t// YES y\n\n\t\tD_NO_W = 45*RESFACTOR,\t\t\t\t\t\t\t\t\t// Cancel width\n\t\tD_NO_H = 9*RESFACTOR,\t\t\t\t\t\t\t\t\t// Cancel height\n\t\tD_NO_X = D_DIALOG_CX + 5*RESFACTOR,\t\t\t\t\t// Cancel x\n\t\tD_NO_Y = D_DIALOG_Y + D_DIALOG_H - D_NO_H - D_MARGIN*2, // Cancel y\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tButton enumerations\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tBUTTON_YES = 100,\n\t\tBUTTON_NO,\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tButtons\n\t//------------------------------------------------------------------------\n\tControlClass * commands = NULL;\t\t// the button list\n\n\tTextButtonClass yesbtn(BUTTON_YES, TXT_YES, TPF_BUTTON, D_YES_X, D_YES_Y, D_YES_W, D_YES_H);\n\n\tTextButtonClass nobtn(BUTTON_NO, TXT_NO, TPF_BUTTON, D_NO_X, D_NO_Y, D_NO_W, D_NO_H);\n\n\tint curbutton;\n\tTextButtonClass * buttons[2];\n\tcurbutton = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInitialize\n\t//------------------------------------------------------------------------\n\tSet_Logic_Page(SeenBuff);\n\n\t//------------------------------------------------------------------------\n\t//\tCreate the button list\n\t//------------------------------------------------------------------------\n\tcommands = &yesbtn;\n\tnobtn.Add_Tail(*commands);\n\n\tbuttons[0] = &yesbtn;\n\tbuttons[1] = &nobtn;\n\tbuttons[curbutton]->Turn_On();\n\n\t//------------------------------------------------------------------------\n\t//\tMain Processing Loop\n\t//------------------------------------------------------------------------\n\tint retcode = 0;\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t//.....................................................................\n\t\t//\tInvoke game callback\n\t\t//.....................................................................\n\t\tif (Session.Type != GAME_SKIRMISH) {\n\t\t\tif (Main_Loop()) {\n\t\t\t\tretcode = 0;\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tRefresh display if needed\n\t\t//.....................................................................\n\t\tif (display) {\n\t\t\tdisplay = false;\n\n\t\t\t//..................................................................\n\t\t\t//\tDisplay the dialog box\n\t\t\t//..................................................................\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\t\t\tDraw_Caption(TXT_NONE, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\n\t\t\t//...............................................................\n\t\t\t//\tDraw the captions\n\t\t\t//...............................................................\n\t\t\tFancy_Text_Print(Text_String(TXT_CONFIRM_EXIT),\n\t\t\t\tD_DIALOG_CX, D_DIALOG_Y + D_TOPMARGIN,\n\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\tTPF_CENTER | TPF_TEXT);\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw the buttons\n\t\t\t//..................................................................\n\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\tShow_Mouse();\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tGet user input\n\t\t//.....................................................................\n\t\tKeyNumType input = commands->Input();\n\n\t\t//.....................................................................\n\t\t//\tProcess input\n\t\t//.....................................................................\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_YES | KN_BUTTON):\n\t\t\t\tretcode = 1;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_NO | KN_BUTTON):\n\t\t\t\tretcode = 0;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\t\tif (curbutton == 0) {\n\t\t\t\t\tretcode = 1;\n\t\t\t\t} else {\n\t\t\t\t\tretcode = 0;\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_ESC):\n\t\t\t\tretcode = 0;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RIGHT):\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tcurbutton++;\n\t\t\t\tif (curbutton > 1) {\n\t\t\t\t\tcurbutton = 0;\n\t\t\t\t}\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_LEFT):\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tcurbutton--;\n\t\t\t\tif (curbutton < 0) {\n\t\t\t\t\tcurbutton = 1;\n\t\t\t\t}\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tRedraw the display\n\t//------------------------------------------------------------------------\n\tHidPage.Clear();\n\tMap.Flag_To_Redraw(true);\n\tMap.Render();\n\n\treturn (retcode);\n}\n\n\n#if(TEN)\n/***************************************************************************\n * Read_TEN_Game_Options -- reads multiplayer game options from disk       *\n *                                                                         *\n * This routine is used for multiplayer games which read the game options\t*\n * from disk, rather than through a connection dialog.\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/11/1996 BRR : Created.                                             *\n *=========================================================================*/\nint Read_TEN_Game_Options(void)\n{\n\tINIClass ini;\n\tif (!ini.Load(RawFileClass(Session.OptionsFile))) {\n\t\treturn (0);\n\t}\n\n\tini.Get_String(\"Options\", \"Handle\", \"Noname\",  Session.Handle,\n\t\tsizeof(Session.Handle));\n\tif (Session.TenPlayerID == -1) {\n\t\treturn (0);\n\t}\n\tSession.ColorIdx = (PlayerColorType)Session.TenPlayerID;\n\tSession.House = (HousesType)\n\t\t((int)HOUSE_USSR + ini.Get_Int(\"Options\", \"Side\", 0));\n\tSession.Options.Credits = ini.Get_Int(\"Options\", \"Credits\", 3000);\n\tSession.Options.Bases = ini.Get_Int(\"Options\", \"Bases\", 1);\n\tSession.Options.Tiberium = ini.Get_Int(\"Options\", \"Tiberium\", 1);\n\tSession.Options.Goodies = ini.Get_Int(\"Options\", \"Crates\", 1);\n\tSpecial.IsShadowGrow = ini.Get_Int (\"Options\", \"Shadow\", 0);\n\tBuildLevel = ini.Get_Int(\"Options\", \"BuildLevel\", 3);\n\tSession.Options.UnitCount = ini.Get_Int(\"Options\", \"UnitCount\", 5);\n\tSeed = ini.Get_Int(\"Options\", \"Seed\", 0);\n\tSpecial.IsCaptureTheFlag = ini.Get_Int(\"Options\", \"CapFlag\", 0);\n\tSession.Options.AIPlayers = ini.Get_Int(\"Options\", \"AI\", 0);\n\tSession.NumPlayers = ini.Get_Int(\"Options\", \"Players\", 2);\n\n\tif (Session.Options.AIPlayers){\n\t\tSession.Options.Ghosts = 1;\n\t}\n\n\tif (Session.Options.Tiberium) {\n\t\tSpecial.IsTGrowth = 1;\n\t\tSpecial.IsTSpread = 1;\n\t} else {\n\t\tSpecial.IsTGrowth = 0;\n\t\tSpecial.IsTSpread = 0;\n\t}\n\n\t/*\n\t** Read the scenario name from the .INI and try to match it with a scenario file in our list.\n\t*/\n\tini.Get_String(\"Options\", \"Scenario\", \"Black Acres\",\n\t\t\t\t\t\t\t\t\t\tSession.Options.ScenarioDescription,\n\t\t\t\t\t\t\t\t\t\tsizeof (Session.Options.ScenarioDescription));\n\n\tSession.Options.ScenarioIndex = -1;\n\tfor (int i = 0; i < Session.Scenarios.Count(); i++) {\n\t\tif (!strcmp (Session.Scenarios[i]->Description(),\n\t\t\tSession.Options.ScenarioDescription) ) {\n\t\t\tSession.Options.ScenarioIndex = i;\n\t\t\tstrcpy(Session.ScenarioFileName, Session.Scenarios[i]->Get_Filename());\n\t\t\tstrcpy(Scen.ScenarioName, Session.Scenarios[i]->Get_Filename());\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (Session.Options.ScenarioIndex == -1) {\n\t\tWWMessageBox().Process(\"Scenario not found!\");\n\t\t//Prog_End();\n\t\tEmergency_Exit(0);\n\t}\n\n\tOptions.GameSpeed = 0;\n\n\tSession.MaxAhead = ini.Get_Int(\"Timing\", \"MaxAhead\", 9);\n\tSession.FrameSendRate = ini.Get_Int(\"Timing\", \"SendRate\", 3);\n\tSession.NetResponseTime = ini.Get_Int(\"Timing\",\"Latency\",600);\n\n\treturn (1);\n}\n#endif\t// TEN\n\n\n#if(MPATH)\n/***************************************************************************\n * Read_MPATH_Game_Options -- reads multiplayer game options from disk     *\n *                                                                         *\n * This routine is used for multiplayer games which read the game options\t*\n * from disk, rather than through a connection dialog.\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/11/1996 BRR : Created.                                             *\n *=========================================================================*/\nint Read_MPATH_Game_Options(void)\n{\n\tINIClass ini;\n\tif (!ini.Load(RawFileClass(Session.OptionsFile))) {\n\t\treturn (0);\n\t}\n\n\tini.Get_String(\"Options\", \"Handle\", \"Noname\",  Session.Handle,\n\t\tsizeof(Session.Handle));\n\tSession.ColorIdx = (PlayerColorType)ini.Get_Int(\"Options\", \"Color\", 0);\n\tSession.House = (HousesType)\n\t\t((int)HOUSE_USSR + ini.Get_Int(\"Options\", \"Side\", 0));\n\tSession.Options.Credits = ini.Get_Int(\"Options\", \"Credits\", 3000);\n\tSession.Options.Bases = ini.Get_Int(\"Options\", \"Bases\", 1);\n\tSession.Options.Tiberium = ini.Get_Int(\"Options\", \"Tiberium\", 1);\n\tSession.Options.Goodies = ini.Get_Int(\"Options\", \"Crates\", 1);\n\tSpecial.IsShadowGrow = ini.Get_Int (\"Options\", \"Shadow\", 0);\n\tBuildLevel = ini.Get_Int(\"Options\", \"BuildLevel\", 3);\n\tSession.Options.UnitCount = ini.Get_Int(\"Options\", \"UnitCount\", 5);\n\tSeed = ini.Get_Int(\"Options\", \"Seed\", 0);\n\tSpecial.IsCaptureTheFlag = ini.Get_Int(\"Options\", \"CapFlag\", 0);\n\tSession.Options.AIPlayers = ini.Get_Int(\"Options\", \"AI\", 0);\n\n\tif (Session.Options.AIPlayers){\n\t\tSession.Options.Ghosts = 1;\n\t}\n\n\tif (Session.Options.Tiberium) {\n\t\tSpecial.IsTGrowth = 1;\n\t\tSpecial.IsTSpread = 1;\n\t} else {\n\t\tSpecial.IsTGrowth = 0;\n\t\tSpecial.IsTSpread = 0;\n\t}\n\n\t/*\n\t** Read the scenario name from the .INI and try to match it with a scenario file in our list.\n\t*/\n\tini.Get_String(\"Options\", \"Scenario\", \"Black Acres\",\n\t\t\t\t\t\t\t\t\t\tSession.Options.ScenarioDescription,\n\t\t\t\t\t\t\t\t\t\tsizeof (Session.Options.ScenarioDescription));\n\n\tSession.Options.ScenarioIndex = -1;\n\tfor (int i = 0; i < Session.Scenarios.Count(); i++) {\n\t\tif (!strcmp (Session.Scenarios[i]->Description(),\n\t\t\tSession.Options.ScenarioDescription) ) {\n\t\t\tSession.Options.ScenarioIndex = i;\n\t\t\tstrcpy(Session.ScenarioFileName, Session.Scenarios[i]->Get_Filename());\n\t\t\tstrcpy(Scen.ScenarioName, Session.Scenarios[i]->Get_Filename());\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (Session.Options.ScenarioIndex == -1) {\n\t\tWWMessageBox().Process(\"Scenario not found!\");\n\t\t//Prog_End();\n\t\tEmergency_Exit(0);\n\t}\n\n\tOptions.GameSpeed = 0;\n\n\tSession.MaxAhead = ini.Get_Int(\"Timing\", \"MaxAhead\", 9);\n\tSession.FrameSendRate = ini.Get_Int(\"Timing\", \"SendRate\", 3);\n\tSession.NetResponseTime = ini.Get_Int(\"Timing\",\"Latency\",600);\n\n\treturn (1);\n}\n#endif\t// MPATH\n\n/************************** end of mplayer.cpp *****************************/\n"
  },
  {
    "path": "CODE/MPLIB.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"types.h\"\n#include \"mgenord.h\"\n#include \"magic.h\"\n#include \"rtq.h\"\n#include <mem.h>\n#include <i86.h>\n#include <assert.h>\n#include \"mplib.h\"\n\n#define CHUNNEL_INT 0x48\n\ntypedef union REGS REGISTERS;\n\nvoid\nYield(void)\n{\n   REGISTERS   regs;\n\n   regs.w.ax = 0x1680;\n   int386(0x2f, &regs, &regs);\n}\n\nvoid\nPostWindowsMessage(void)\n{\n   REGISTERS regs;\n\n   regs.x.eax = DPMIAPI_POST_WINDOWS_ORD << 16 | MGENVXD_DEVICE_ID;\n   regs.x.ebx = 0;\n   regs.x.ecx = 0;\n   int386(CHUNNEL_INT, &regs, &regs);\n}\n\nint MGenGetQueueCtr(int qNo)\n{\n   REGISTERS   regs;\n\n   regs.x.eax = MGENVXD_GETQUEUECTR_ORD << 16 | MGENVXD_DEVICE_ID;\n   regs.x.ebx = qNo;\n   int386(CHUNNEL_INT, &regs, &regs);\n\n   return regs.x.eax;\n}\n\nRTQ_NODE *MGenMoveTo(int qFrom, int qTo)\n{\n   REGISTERS   regs;\n\n   regs.x.eax = MGENVXD_MOVENODE_ORD << 16 | MGENVXD_DEVICE_ID;\n   regs.x.ebx = qFrom;\n   regs.x.ecx = qTo;\n   int386(CHUNNEL_INT, &regs, &regs);\n\n   return (RTQ_NODE *) regs.x.eax;\n}\n\nRTQ_NODE *MGenGetNode(int q)\n{\n   REGISTERS   regs;\n\n   regs.x.eax = MGENVXD_GETNODE_ORD << 16 | MGENVXD_DEVICE_ID;\n   regs.x.ebx = q;\n   int386(CHUNNEL_INT, &regs, &regs);\n\n   return (RTQ_NODE *) regs.x.eax;\n}\n\nRTQ_NODE *MGenGetMasterNode(unsigned *size)\n{\n   REGISTERS   regs;\n\n   regs.x.eax = MGENVXD_MASTERNODE_ORD << 16 | MGENVXD_DEVICE_ID;\n   int386(CHUNNEL_INT, &regs, &regs);\n   *size = regs.x.ecx;\n\n   return (RTQ_NODE *) regs.x.eax;\n}\n\nint MGenFlushNodes(int qFrom, int qTo)\n{\n   REGISTERS   regs;\n\n   regs.x.eax = MGENVXD_FLUSHNODE_ORD << 16 | MGENVXD_DEVICE_ID;\n   regs.x.ebx = qFrom;\n   regs.x.ecx = qTo;\n   int386(CHUNNEL_INT, &regs, &regs);\n\n   return regs.x.eax;\n}\n\nint MGenMCount(unsigned lowerOrderBits, unsigned upperOrderBits)\n{\n   REGISTERS   regs;\n\n   regs.x.eax = MGENVXD_MCOUNT_ORD << 16 | MGENVXD_DEVICE_ID;\n   regs.x.ebx = lowerOrderBits;\n   regs.x.ecx = upperOrderBits;\n   int386(CHUNNEL_INT, &regs, &regs);\n\n   return regs.x.eax;\n}\n\nint MGenSanityCheck(void)\n{\n   REGISTERS   regs;\n\n   regs.x.eax = MGENVXD_SANITYCHECK_ORD << 16 | MGENVXD_DEVICE_ID;\n   int386(CHUNNEL_INT, &regs, &regs);\n\n   return regs.x.eax;\n}\n\u001a"
  },
  {
    "path": "CODE/MPLPC.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\nextern \"C\" {\n#include \"lpc.h\"\n#include \"types.h\"\n#include \"services.h\"\n#include \"rtq.h\"\n#include <stdio.h>\n#include <mem.h>\n};\n#include \"mplib.h\"\n\n\n#define IDLE_QUEUE    6\n#define REC_QUEUE     7\n#define SEND_QUEUE    8\n\nvoid\nSetLPCData(LPCData *lpc)\n{\n   lpc->version = 1;\n   lpc->sizeOfArgs = 0;\n   lpc->service = LPC_NOSERVICE;\n}\n\nvoid\nGetGameDef(void *gameDef, int* len)\n{\n   RTQ_NODE  *n = MGenGetNode(IDLE_QUEUE);\n   LPCData   *p;\n   LPCReturn *r;\n   \n   if (!n) {\n      *len = 0;\n      return;    // can't get service!\n   }\n\n   p = (LPCData *) n->rtqDatum;\n   SetLPCData(p);\n   p->service = LPC_GENGETGAMEDEF;\n   MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);\n\n   // make call\n   PostWindowsMessage();\n\n   // wait for return\n   while ((n = MGenGetNode(REC_QUEUE)) == 0)\n      Yield();\n\n   r = (LPCReturn *) n->rtqDatum;\n\n   if (r->sizeOfReturn > *len || r->error != LPC_NOERROR) {\n      *len = 0;\n      return;\n   }\n\n   *len = r->sizeOfReturn;\n   memcpy(gameDef, r->Data, r->sizeOfReturn);\n\n   // get ready for next call\n   MGenMoveTo(REC_QUEUE, IDLE_QUEUE);\n}\n\nint\nLPCGetMPAddr(void)\n{\n   RTQ_NODE  *n = MGenGetNode(IDLE_QUEUE);\n   LPCData   *p;\n   LPCReturn *r;\n   int       retVal;\n\n   p = (LPCData *) n->rtqDatum;\n   SetLPCData(p);\n   p->service = LPC_GETMPADDR;\n   MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);\n\n   PostWindowsMessage();\n\n   while ((n = MGenGetNode(REC_QUEUE)) == 0)\n      Yield();\n\n   r = (LPCReturn *) n->rtqDatum;\n\n   if (r->sizeOfReturn != sizeof(int) || r->error != LPC_NOERROR) {\n      return -1;\n   }\n\n   retVal = *((int *) r->Data);\n   MGenMoveTo(REC_QUEUE, IDLE_QUEUE);\n   return retVal;\n}\n\nvoid\nNullLPC(void)\n{\n   RTQ_NODE  *n = MGenGetNode(IDLE_QUEUE);\n   LPCData   *p;\n\n   p = (LPCData *) n->rtqDatum;\n   SetLPCData(p);\n   p->service = LPC_NULLSERVICE;\n   MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);\n\n   PostWindowsMessage();\n\n   while ((n = MGenGetNode(REC_QUEUE)) == 0)\n      Yield();\n\n   MGenMoveTo(REC_QUEUE, IDLE_QUEUE);\n}\n\u001a"
  },
  {
    "path": "CODE/MPMGRD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"mpmgrd.h\"\n\nextern \"C\" {\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <assert.h>\n#include \"types.h\"\n#include \"rtq.h\"\n#include \"services.h\"\n}\n#include \"mplib.h\"\n#include \"mplpc.h\"\n\n\n#define     STATUS_OK    1\n#define     STATUS_BAD   0\n\n#define     BROADCAST_ADDR    0\n\ntypedef struct {\n   DWORD      address;\n   char       Data[1];\n} packet;\n\n#define min(a,b) (((a) < (b)) ? (a) : (b))\n\n#define     FREEQUEUE            0\n#define     DOSWORKQUEUE         1\n#define     WINWORKQUEUE         2\n#define     WINSENDQUEUE         3\n#define     DOSPENDINGQUEUE      4\n#define     WINWORKQUEUE2        5\n\n// 6, 7, 8, taken up by LPC services\n\n#define     GDOSWORKQUEUE        14\n#define     GWINWORKQUEUE        15\n#define     GWINSENDQUEUE        16\n#define     GDOSPENDINGQUEUE     17\n#define     GWINWORKQUEUE2       18\n\nMPlayerManClass::MPlayerManClass(void) : ConnManClass()\n{\n   unsigned  size;\n\n   MGenGetMasterNode(&size);\n   if (size != sizeof(RTQ_NODE)) {\n      exit(-234);\n   }\n   _myAddr = LPCGetMPAddr();\n   _nConnections = 0;\n\n   for (int i = 0; i < CONNECT_MAX; i++) {\n      _Connections[i] = 0;\n      strcpy(_Names[i], \"\");\n   }\n}\n\n// here's what we do to get private & broadcasts over the same chunnel\n// we package up an extra dword at the beginning to indicate the address\n\nint\nMPlayerManClass::Send_Private_Message(void *buf,\n                                      int buflen,\n                                      int /* ack_req */,\n                                      int conn_id)\n{\n   RTQ_NODE *n;\n\tint idx = Connection_Index(conn_id);\n\n\tif (_nConnections == 0) {\n\t\treturn (STATUS_OK);\n\t}\n\n   while ((n = MGenMoveTo(FREEQUEUE, DOSWORKQUEUE)) == 0);\n\n   packet *p = (packet *) n->rtqDatum;\n\n   if (conn_id == CONNECTION_NONE) {\n      p->address = BROADCAST_ADDR;\n   } else {\n      p->address = _Connections[idx];\n   }\n\n   memcpy(p->Data, buf, buflen);\n   n->rtqUpCtr = (WORD)(buflen + sizeof(DWORD));\n\n   MGenMoveTo(DOSWORKQUEUE, WINSENDQUEUE);\n   PostWindowsMessage();\n   Yield();\n\n   return STATUS_OK;\n}\n\nint\nMPlayerManClass::Get_Private_Message(void *buf, int *buflen,\n                                     int *conn_id)\n{\n   RTQ_NODE *n;\n\tint i;\n\n   if ((n = MGenMoveTo(DOSPENDINGQUEUE, DOSWORKQUEUE)) == 0) {\n      *buflen = 0;\n      return 0;\n   }\n\n   packet *p = (packet *) n->rtqDatum;\n\n   int lentocpy = n->rtqUpCtr - sizeof(DWORD);\n\n   *conn_id = CONNECTION_NONE;\n\tfor (i = 0; i < _nConnections; i++) {\n\t\tif (p->address == _Connections[i]) {\n\t\t\t(*conn_id) = _ID[i];\n\t\t\tbreak;\n\t\t}\n\t}\n\n   memcpy(buf, p->Data, lentocpy);\n\n   *buflen = lentocpy;\n\n   MGenMoveTo(DOSWORKQUEUE, FREEQUEUE);\n\n   return STATUS_OK;\n}\n\nint\nMPlayerManClass::Send_Global_Message(void *buf, int buflen, int /*ack_req*/,\n   int address)\n{\n   RTQ_NODE *n;\n\n   while ((n = MGenMoveTo(FREEQUEUE, DOSWORKQUEUE)) == 0);\n\n   packet *p = (packet *) n->rtqDatum;\n\n   if (address == 0) {\n      p->address = BROADCAST_ADDR;\n   } else {\n      p->address = address;\n   }\n\n   memcpy(p->Data, buf, buflen);\n   n->rtqUpCtr = (WORD)(buflen + sizeof(DWORD));\n\n   MGenMoveTo(DOSWORKQUEUE, GWINSENDQUEUE);\n   PostWindowsMessage();\n   Yield();\n\n   return STATUS_OK;\n}\n\nint\nMPlayerManClass::Get_Global_Message(void *buf, int *buflen, int *address)\n{\n   RTQ_NODE *n;\n\n   if ((n = MGenMoveTo(GDOSPENDINGQUEUE, DOSWORKQUEUE)) == 0) {\n      *buflen = 0;\n      return 0;\n   }\n\n   packet *p = (packet *) n->rtqDatum;\n\n   int lentocpy = n->rtqUpCtr - sizeof(DWORD);\n\n   if (address) {\n      if (p->address == BROADCAST_ADDR) {\n         *address = 0;\n      } else {\n         *address = p->address;\n      }\n   }\n\n   memcpy(buf, p->Data, lentocpy);\n\n   *buflen = lentocpy;\n\n   MGenMoveTo(DOSWORKQUEUE, FREEQUEUE);\n\n   return STATUS_OK;\n}\n\nint\nMPlayerManClass::Service(void)\n{\n   return STATUS_OK;\n}\n\nint\nMPlayerManClass::Create_Connection(int id, char *name, int address)\n{\n   _Connections[_nConnections] = address;\n\t_ID[_nConnections] = id;\n   strcpy(_Names[_nConnections], name);\n   _nConnections++;\n   return STATUS_OK;\n}\n\nint\nMPlayerManClass::Delete_Connection(int id)\n{\n\tint i;\n\tint idx = Connection_Index(id);\n\tif (idx == -1)\n\t\treturn 0;\n\n\tfor (i = idx; i < _nConnections - 1; i++) {\n\t\t_Connections[i] = _Connections[i+1];\n\t\t_ID[i] = _ID[i+1];\n\t\tstrcpy (_Names[i], _Names[i+1]);\n\t}\n   _nConnections--;\n   return STATUS_OK;\n}\n\nchar *\nMPlayerManClass::Connection_Name(int id)\n{\n\tint idx = Connection_Index(id);\n\tif (idx==-1) {\n\t\treturn (NULL);\n\t}\n\n   return _Names[idx];\n}\n\nint\nMPlayerManClass::Connection_Address(int id)\n{\n\tint idx = Connection_Index(id);\n\tif (idx==-1) {\n\t\treturn (0);\n\t}\n\n   return _Connections[idx];\n}\n\nint\nMPlayerManClass::Num_Connections(void)\n{\n   return _nConnections;\n}\n\nint\nMPlayerManClass::Connection_ID(int index)\n{\n   return _ID[index];\n}\n\nint\nMPlayerManClass::Connection_Index(int id)\n{\n\tint i;\n\n\tfor (i = 0; i < _nConnections; i++) {\n\t\tif (_ID[i] == id) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n   return -1;\n}\n\nint\nMPlayerManClass::Global_Num_Send(void)\n{\n   return 0;\n}\n\nint\nMPlayerManClass::Global_Num_Receive(void)\n{\n   return MGenGetQueueCtr(GDOSPENDINGQUEUE);\n}\n\nint\nMPlayerManClass::Private_Num_Send(int /*id*/)\n{\n   return 0;\n}\n\nint\nMPlayerManClass::Private_Num_Receive(int /*id*/)\n{\n   return MGenGetQueueCtr(DOSPENDINGQUEUE);\n}\n\nvoid\nMPlayerManClass::Reset_Response_Time(void)\n{\n   // unsupported\n}\n\nunsigned long\nMPlayerManClass::Response_Time(void)\n{\n   return (160 * 60) / 1000;   // 160 microseconds one way (9 ticks)\n}\n\nvoid\nMPlayerManClass::Set_Timing(unsigned long /*retrydelta*/,\n                            unsigned long /*maxretries*/,\n                            unsigned long /*timeout*/)\n{\n   // unsupported\n}\n\nvoid\nMPlayerManClass::Configure_Debug(int /*index*/, int /*type_offset*/,\n                                 int /*type_size*/, char ** /*names*/,\n                                 int /*namestart*/, int /*namecount*/)\n{\n   // unsupported\n}\n\nvoid\nMPlayerManClass::Mono_Debug_Print(int /*index*/, int /*refresh*/)\n{\n   // unsupported\n}\n\nint\nMPlayerManClass::Init(void)\n{\n   return STATUS_OK;\n}\n\nint MPlayerManClass::Find_Num_Connections(void)\n{\n\tTGAMEDEF game_def;\n\tint sz = sizeof(game_def);\n\n\tGetGameDef(&game_def, &sz);\n\n\treturn (game_def.numPlayers - 1);\n\n}\n\n\nvoid MPlayerManClass::Flush_All(void)\n{\n\tMGenFlushNodes(DOSPENDINGQUEUE, FREEQUEUE);\n\tMGenFlushNodes(GDOSPENDINGQUEUE, FREEQUEUE);\n}\n\n"
  },
  {
    "path": "CODE/MPMGRD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef mpmgr_h\n#define mpmgr_h\n\n#include \"connmgr.h\"\n\n// maximum number of connections\n#define CONNECT_MAX    7\n#define MAX_NAME_LEN   128\n\nclass MPlayerManClass : public ConnManClass {\npublic:\n   MPlayerManClass(void);\n\n   // queues up incoming packets appropriately\n   int   Service(void);\n\n   // initialization\n   int   Init(void);\n\tint Find_Num_Connections(void);\n\tvoid Flush_All(void);\n\n   // send/receive data\n   int  Send_Private_Message(void *buf, int buflen, int ack_req = 1, int conn_id = CONNECTION_NONE);\n   int  Get_Private_Message(void *buf, int *buflen, int *conn_id);\n\n   int  Send_Global_Message(void *buf, int buflen, int ack_req = 0, int address = 0);\n   int  Get_Global_Message(void *buf, int *buflen, int *address = 0);\n\n   // manage connections\n   int  Num_Connections(void);\n   int  Connection_ID(int index);\n   int  Connection_Index(int id);\n   int  Create_Connection(int id, char *name, int address);\n   int  Delete_Connection(int id);\n   char *Connection_Name(int id);\n   int  Connection_Address(int id);\n\n   // queueing routines\n\n   int Global_Num_Send(void);\n   int Global_Num_Receive(void);\n   int Private_Num_Send(int id = CONNECTION_NONE);\n   int Private_Num_Receive(int id = CONNECTION_NONE);\n\n   // timing magnagement\n   void Reset_Response_Time(void);\n   unsigned long Response_Time(void);\n   void Set_Timing(unsigned long retrydelta, unsigned long maxretries, unsigned long timeout);\n\n   // debug\n   void Configure_Debug(int index, int type_offset, int type_size, char **names, int namestart,\n      int namecount);\n   void Mono_Debug_Print(int index, int refresh);\n\nprivate:\n   int  _myAddr;\n   int  _Connections[CONNECT_MAX];\n\tint  _ID[CONNECT_MAX];\n   char _Names[CONNECT_MAX][MAX_NAME_LEN];\n   int  _nConnections;\n};\n\n#endif // mpmgr_h\n\n\u001a"
  },
  {
    "path": "CODE/MPMGRW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef MP_LOAD_DLL_DYNAMICALLY\n#define MP_LOAD_DLL_DYNAMICALLY\n#endif\n\n#include \"mpmgrw.h\"\n\nextern \"C\" {\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <assert.h>\n}\n\n#include <windows.h>\n\n#define     STATUS_OK    1\n#define     STATUS_BAD   0\n\n#define     BROADCAST_ADDR    0\n\n#define PRIVATE 0\n#define PUBLIC  1\n\n#define min(a,b) (((a) < (b)) ? (a) : (b))\n\ntypedef void __cdecl (*MPlayerInit_Type)(void);\ntypedef void __cdecl (*MPlayerDestroy_Type)(void);\ntypedef int __cdecl (*Send_Private_Message_Type)(void *buf,\n\t\t\t\t\t int buflen,\n                     int ack_req,\n                     int conn_id);\ntypedef int __cdecl\t(*Get_Private_Message_Type)(void *buf, int *buflen,\n                    int *conn_id);\ntypedef int __cdecl (*Send_Global_Message_Type)(void *buf, int buflen, int ack_req,\n   int addr);\ntypedef int __cdecl (*Get_Global_Message_Type)(void *buf, int *buflen, int *address);\t\t\ntypedef int __cdecl (*Create_Connection_Type)(int id, char *name, int address);\t\t\ntypedef int __cdecl (*Delete_Connection_Type)(int id);\t\t\ntypedef char * __cdecl (*Connection_Name_Type)(int id);\t\t\t\ntypedef int __cdecl\t(*Connection_Address_Type)(int id);\t\t\ntypedef int __cdecl\t(*Num_Connections_Type)(void);\t\t\t\ntypedef int __cdecl (*Connection_ID_Type)(int id);\t\t\t\ntypedef int __cdecl (*Connection_Index_Type)(int id);\ntypedef int __cdecl\t(*Init_Type)(void);\t\t\t\t\t\ntypedef int __cdecl (*Find_Num_Connections_Type)(void);\n\nMPlayerInit_Type MPlayerManCreate;\nMPlayerDestroy_Type MPlayerManDestroy;\nSend_Private_Message_Type Send_Private_Message_DLL;\nGet_Private_Message_Type Get_Private_Message_DLL;\nSend_Global_Message_Type Send_Global_Message_DLL;\nGet_Global_Message_Type Get_Global_Message_DLL;\nCreate_Connection_Type Create_Connection_DLL;\nDelete_Connection_Type Delete_Connection_DLL;\nConnection_Name_Type Connection_Name_DLL;\nConnection_Address_Type Connection_Address_DLL;\nNum_Connections_Type Num_Connections_DLL;\nConnection_ID_Type Connection_ID_DLL;\nConnection_Index_Type Connection_Index_DLL;\nInit_Type Init_DLL;\nFind_Num_Connections_Type Find_Num_Connections_DLL;\n\n\nFARPROC MPGetProcAddress(HMODULE hModule, LPCSTR lpProcName) {\n        FARPROC ret=GetProcAddress(hModule, lpProcName);\n        if (!ret) {\n                char msg[255];\n                sprintf(msg, \"Unable to load function %s from %s\",\n\t\t\t\t\t\tlpProcName, \"RA95MP.DLL\");\n                MessageBox(0, msg, \"Warning\", MB_OK);\n        }\n        return ret;\n}\n\nMPlayerManClass::MPlayerManClass(void) : ConnManClass()\n{\n\tHMODULE lib;\n\n\tlib = LoadLibrary(\"ra95mp.dll\");\n\tif (lib != 0) {\n\t\tMPlayerManCreate = (MPlayerInit_Type) MPGetProcAddress(lib,\n\t\t\t\"MPlayerManCreate\");\n\t\tMPlayerManDestroy = (MPlayerDestroy_Type) MPGetProcAddress(lib,\n\t\t\t\"MPlayerManDestroy\");\n\t\tSend_Private_Message_DLL = (Send_Private_Message_Type) MPGetProcAddress(lib,\n\t\t\t\"Send_Private_Message\");\n\t\tGet_Private_Message_DLL = (Get_Private_Message_Type) MPGetProcAddress(lib,\n\t\t\t\"Get_Private_Message\");\n\t\tSend_Global_Message_DLL = (Send_Global_Message_Type) MPGetProcAddress(lib,\n\t\t\t\"Send_Global_Message\");\n\t\tGet_Global_Message_DLL = (Get_Global_Message_Type) MPGetProcAddress(lib,\n\t\t\t\"Get_Global_Message\");\n\t\tCreate_Connection_DLL = (Create_Connection_Type) MPGetProcAddress(lib,\n\t\t\t\"Create_Connection\");\n\t\tDelete_Connection_DLL = (Delete_Connection_Type) MPGetProcAddress(lib,\n\t\t\t\"Delete_Connection\");\n\t\tConnection_Name_DLL = (Connection_Name_Type) MPGetProcAddress(lib,\n\t\t\t\"Connection_Name\");\n\t\tConnection_Address_DLL = (Connection_Address_Type) MPGetProcAddress(lib,\n\t\t\t\"Connection_Address\");\n\t\tNum_Connections_DLL = (Num_Connections_Type) MPGetProcAddress(lib,\n\t\t\t\"Num_Connections\");\n\t\tConnection_ID_DLL = (Connection_ID_Type) MPGetProcAddress(lib,\n\t\t\t\"Connection_ID\");\n\t\tConnection_Index_DLL = (Connection_Index_Type) MPGetProcAddress(lib,\n\t\t\t\"Connection_Index\");\n\t\tInit_DLL = (Init_Type) MPGetProcAddress(lib,\n\t\t\t\"Init\");\n\t\tFind_Num_Connections_DLL = (Find_Num_Connections_Type) MPGetProcAddress(lib,\n\t\t\t\"Find_Num_Connections\");\n\t} else {\n       MessageBox(0, \"RA95MP.DLL not found!\", \"Warning\", MB_OK);\n\t\t exit(0);\n\t}\n\t\n\tif (MPlayerManCreate != 0) {\n\t\tMPlayerManCreate();\n\t}\n}\n\nMPlayerManClass::~MPlayerManClass()\n{\n\tMPlayerManDestroy();\n}\n\n// here's what we do to get private & broadcasts over the same chunnel\n// we package up an extra dword at the beginning to indicate the address\n\nint\nMPlayerManClass::Send_Private_Message(void *buf,\n                                      int buflen,\n                                      int ack_req,\n                                      int conn_id)\n{\n\treturn Send_Private_Message_DLL(buf, buflen, ack_req, conn_id);\n}\n\nint\nMPlayerManClass::Get_Private_Message(void *buf, int *buflen,\n                                     int *conn_id)\n{\n\treturn Get_Private_Message_DLL(buf, buflen, conn_id);\n}\n\nint\nMPlayerManClass::Send_Global_Message(void *buf, int buflen, int ack_req,\n   int addr)\n{\n \treturn Send_Global_Message_DLL(buf, buflen, ack_req, addr);\n}\n\nint\nMPlayerManClass::Get_Global_Message(void *buf, int *buflen, int *address)\n{\n\treturn Get_Global_Message_DLL(buf, buflen, address);\n}\n\nint\nMPlayerManClass::Service(void)\n{\n   return STATUS_OK;\n}\n\nint\nMPlayerManClass::Create_Connection(int id, char *name, int address)\n{\n\treturn Create_Connection_DLL(id, name, address);\n}\n\nint\nMPlayerManClass::Delete_Connection(int id)\n{\n\treturn Delete_Connection_DLL(id);\n}\n\nchar *\nMPlayerManClass::Connection_Name(int id)\n{\n\treturn Connection_Name_DLL(id);\n}\n\nint\nMPlayerManClass::Connection_Address(int id)\n{\n\treturn Connection_Address_DLL(id);\n}\n\nint\nMPlayerManClass::Num_Connections(void)\n{\n   return Num_Connections_DLL();\n}\n\nint\nMPlayerManClass::Connection_ID(int index)\n{\n   return Connection_ID_DLL(index);\n}\n\nint\nMPlayerManClass::Connection_Index(int id)\n{\n\treturn Connection_Index_DLL(id);\n}\n\nint\nMPlayerManClass::Global_Num_Send(void)\n{\n   return 0;\n}\n\nint\nMPlayerManClass::Global_Num_Receive(void)\n{\n\treturn 0;\n//   return MGenGetQueueCtr(GDOSPENDINGQUEUE);\n}\n\nint\nMPlayerManClass::Private_Num_Send(int /*id*/)\n{\n   return 0;\n}\n\nint\nMPlayerManClass::Private_Num_Receive(int /*id*/)\n{\n   return 0;\n}\n\nvoid\nMPlayerManClass::Reset_Response_Time(void)\n{\n   // unsupported\n}\n\nunsigned long\nMPlayerManClass::Response_Time(void)\n{\n   return (160 * 60) / 1000;   // 160 microseconds one way (9 ticks)\n}\n\nvoid\nMPlayerManClass::Set_Timing(unsigned long /*retrydelta*/,\n                            unsigned long /*maxretries*/,\n                            unsigned long /*timeout*/)\n{\n   // unsupported\n}\n\nvoid\nMPlayerManClass::Configure_Debug(int /*index*/, int /*type_offset*/,\n                                 int /*type_size*/, char ** /*names*/,\n                                 int /*namestart*/, int /*namecount*/)\n{\n   // unsupported\n}\n\nvoid\nMPlayerManClass::Mono_Debug_Print(int /*index*/, int /*refresh*/)\n{\n   // unsupported\n}\n\nint\nMPlayerManClass::Init(void)\n{\n\treturn Init_DLL();\n}\n\nint MPlayerManClass::Find_Num_Connections(void)\n{\n\treturn Find_Num_Connections_DLL();\n}\n\n\nvoid MPlayerManClass::Flush_All(void)\n{\n}\n\n"
  },
  {
    "path": "CODE/MPMGRW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef mpmgr_h\n#define mpmgr_h\n\n#include \"connmgr.h\"\n#include \"mplayer.h\"\n#include <windows.h>\n\n// maximum number of connections\n#define CONNECT_MAX    7\n#define MAX_NAME_LEN   128\n\nclass MPlayerManClass : public ConnManClass {\npublic:\n   MPlayerManClass(void);\n\t~MPlayerManClass(void);\n\n   // queues up incoming packets appropriately\n   int   Service(void);\n\n   // initialization\n   int   Init(void);\n\tint Find_Num_Connections(void);\n\tvoid Flush_All(void);\n\n   // send/receive data\n   int  Send_Private_Message(void *buf, int buflen, int ack_req = 1, int conn_id = CONNECTION_NONE);\n   int  Get_Private_Message(void *buf, int *buflen, int *conn_id);\n\n   int  Send_Global_Message(void *buf, int buflen, int ack_req = 0, int address = 0);\n   int  Get_Global_Message(void *buf, int *buflen, int *address = 0);\n\n   // manage connections\n   int  Num_Connections(void);\n   int  Connection_ID(int index);\n   int  Connection_Index(int id);\n   int  Create_Connection(int id, char *name, int address);\n   int  Delete_Connection(int id);\n   char *Connection_Name(int id);\n   int  Connection_Address(int id);\n\n   // queueing routines\n\n   int Global_Num_Send(void);\n   int Global_Num_Receive(void);\n   int Private_Num_Send(int id = CONNECTION_NONE);\n   int Private_Num_Receive(int id = CONNECTION_NONE);\n\n   // timing magnagement\n   void Reset_Response_Time(void);\n   unsigned long Response_Time(void);\n   void Set_Timing(unsigned long retrydelta, unsigned long maxretries, unsigned long timeout);\n\n   // debug\n   void Configure_Debug(int index, int type_offset, int type_size, char **names, int namestart,\n      int namecount);\n   void Mono_Debug_Print(int index, int refresh);\n\nprivate:\n  //HGULP _gulp;\n  //HGULP _pgulp;\n  //GAMEDEF _gameDef;\n   //int  _myAddr;\n   //int  _Connections[CONNECT_MAX];\n\t//int  _ID[CONNECT_MAX];\n   //char _Names[CONNECT_MAX][MAX_NAME_LEN];\n   //int  _nConnections;\n};\n\n#endif // mpmgr_h\n\n"
  },
  {
    "path": "CODE/MPU.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MPU.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MPU.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/17/96                                                     *\n *                                                                                             *\n *                  Last Update : July 17, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"mpu.h\"\n\n\n#ifdef __BORLANDC__\nunsigned long __cdecl Get_CPU_Clock(unsigned long & high)\n{\n\t__asm db 0fh,031h\n\t__asm mov [high],edx\n\treturn(_EAX);\n}\n#endif\n"
  },
  {
    "path": "CODE/MPU.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MPU.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MPU.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/15/96                                                     *\n *                                                                                             *\n *                  Last Update : July 17, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Get_CPU_Clock -- Fetches the current CPU clock time.                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MPU_H\n#define MPU_H\n\n\n/***********************************************************************************************\n * Get_CPU_Clock -- Fetches the current CPU clock time.                                        *\n *                                                                                             *\n *    This routine will return the internal Pentium clock accumulator. This accumulator is     *\n *    incremented every clock tick. Since this clock value can get very very large, the value  *\n *    returned is in 64 bits. The low half is returned directly, the high half is stored in    *\n *    location specified.                                                                      *\n *                                                                                             *\n * INPUT:   high  -- Reference to the high value of the 64 bit clock number.                   *\n *                                                                                             *\n * OUTPUT:  Returns with the low half of the CPU clock value.                                  *\n *                                                                                             *\n * WARNINGS:   This instruction is only available on Pentium or later processors.              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned long Get_CPU_Clock(unsigned long & high);\n#ifndef __BORLANDC__\n#pragma aux Get_CPU_Clock parm [esi] \\\n\tmodify [edx] \\\n\tvalue [eax] = \\\n\t\"db 0fh,031h\" \\\n\t\"mov [esi],edx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "CODE/MSGBOX.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MSGBOX.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OPTIONS.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 8, 1994                                                 *\n *                                                                                             *\n *                  Last Update : August 24, 1995 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   WWMessageBox::Process -- Handles all the options graphic interface.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"msgbox.h\"\n#include \"gadget.h\"\n\n\n#ifdef FIXIT_VERSION_3\nbool cancel_current_msgbox = false;\n#endif\n\n/***********************************************************************************************\n * WWMessageBox::Process -- pops up a message with yes/no, etc                                 *\n *                                                                                             *\n * This function displays a dialog box with a one-line message, and                            *\n * up to two buttons. The 2nd button is optional. The buttons default                          *\n * to \"OK\" and nothing, respectively. The hotkeys for the buttons are                          *\n * RETURN and ESCAPE.                                                                          *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      msg         message to display                                                         *\n *      b1txt         text for 1st button                                                      *\n *      b2txt         text for 2nd button; NULL = no 2nd button                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      # of button selected (0 = 1st)                                                         *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      'msg' text must be <= 38 chars                                                         *\n *      'b1txt' and 'b2txt' must each be <= 18 chars                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/08/1994 BR : Created.                                                                  *\n *   05/18/1995 JLB : Uses new font and dialog style.                                          *\n *   08/24/1995 JLB : Handles three buttons.                                                   *\n *=============================================================================================*/\n#define\tBUTTON_1\t\t1\n#define\tBUTTON_2\t\t2\n#define\tBUTTON_3\t\t3\n#define\tBUTTON_FLAG\t0x8000\nint WWMessageBox::Process(const char * msg, const char * b1txt, const char * b2txt, const char * b3txt, bool preserve)\n{\n#define BUFFSIZE (511)\n\tchar buffer[BUFFSIZE];\n\tbool retval;\n\tbool process;\t\t\t\t\t\t\t\t// loop while true\n\tint selection;\n\tbool pressed;\n\tint curbutton;\n\tTextButtonClass * buttons[3];\n\tvoid * back;\n\tBOOL display;\t\t\t\t\t\t\t\t\t// display level\n\tint  realval[5];\n\n#ifndef WIN32\n\tint\tpreservex,preservey,preservew,preserveh;\n#endif\n\n\t#ifdef WIN32\n\tGraphicBufferClass seen_buff_save(VisiblePage.Get_Width(), VisiblePage.Get_Height(), (void*)NULL);\n\t#endif\n\n\tif (b1txt != NULL && *b1txt == '\\0') b1txt = NULL;\n\tif (b2txt != NULL && *b2txt == '\\0') b2txt = NULL;\n\tif (b3txt != NULL && *b3txt == '\\0') b3txt = NULL;\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT);\n\n\t/*\n\t**\tExamine the optional button parameters. Fetch the width and starting\n\t**\tcharacters for each.\n\t*/\n\tint bwidth, bheight;\t\t\t\t// button width and height\n\tint numbuttons = 0;\n\tif (b1txt != NULL) {\n\n\t\t/*\n\t\t**\tBuild the button list.\n\t\t*/\n\t\tbheight = FontHeight + FontYSpacing + (2 * RESFACTOR);\n\t\tbwidth = max((String_Pixel_Width(b1txt) + (8 * RESFACTOR)), (30 * RESFACTOR));\n\n\t\tif (b2txt != NULL) {\n\t\t\tnumbuttons = 2;\n\t\t\tbwidth = max((String_Pixel_Width( b2txt ) + (8 * RESFACTOR)), bwidth);\n\n\t\t\tif (b3txt != NULL) {\n\t\t\t\tnumbuttons = 3;\n\t\t\t}\n\n\t\t} else {\n\t\t\tnumbuttons = 1;\n\t\t}\n\t}\n\n\t/*\n\t**\tDetermine the dimensions of the text to be used for the dialog box.\n\t**\tThese dimensions will control how the dialog box looks.\n\t*/\n\tbuffer[BUFFSIZE-1] = 0;\n\tstrncpy(buffer, msg, BUFFSIZE-1);\n\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT);\n\tint width;\n\tint height;\n\tint lines = Format_Window_String(buffer, 255 * RESFACTOR, width, height);\n\tTextPrintType tpf = TPF_TEXT;\n\n\twidth = max(width, (90 * RESFACTOR));\n\twidth += 40 * RESFACTOR;\n\theight += (numbuttons == 0) ? (40 * RESFACTOR) : (60 * RESFACTOR);\n\n\tint x = (SeenBuff.Get_Width() - width) / 2;\n\tint y = (SeenBuff.Get_Height() - height) / 2;\n\tint printx = x + (20 * RESFACTOR);\n\n\t/*\n\t**\tSpecial hack to center a one line dialog box text.\n\t*/\n\tif (lines == 1) {\n\t\tprintx = x + width/2;\n\t\ttpf = tpf | TPF_CENTER;\n\t}\n\n\t/*\n\t**\tOther inits.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\t#ifdef WIN32\n\tVisiblePage.Blit(seen_buff_save);\n\t#endif\n\n\t/*\n\t**\tInitialize the button structures. All are initialized, even though one (or none) may\n\t**\tactually be added to the button list.\n\t*/\n\t//DOS BUILD GERMAN BUTTONS NEED TO ONE ON TOP OF THE OTHER  VG 11/6/96\n\tTextButtonClass button1(BUTTON_1, b1txt, TPF_BUTTON,\n\t\tx + ((numbuttons == 1) ? ((width - bwidth) >> 1) : (20 * RESFACTOR)), y + height - (bheight + (15 * RESFACTOR)), bwidth);\n\n\t/*\n\t**\tCenter button.\n\t*/\n\tTextButtonClass button2(BUTTON_2, b2txt, TPF_BUTTON,\n\t\tx + width - (bwidth + (20 * RESFACTOR)), y + height - (bheight + (15 * RESFACTOR)), bwidth);\n\n\t/*\n\t**\tRight button.\n\t*/\n\tTextButtonClass button3(BUTTON_3, b3txt, TPF_BUTTON, 0, y + height - (bheight + (15 * RESFACTOR)));\n\tbutton3.X = x + ((width - button3.Width) >> 1);\n\n\tTextButtonClass * buttonlist = 0;\n\tcurbutton = 0;\n\n\t/*\n\t**\tAdd and initialize the buttons to the button list.\n\t*/\n\tmemset(buttons, '\\0', sizeof(buttons));\n\tif (numbuttons > 0) {\n\t\tbuttonlist = &button1;\n\t\tbuttons[0] = &button1;\n\t\trealval[0] = BUTTON_1;\n\t\tif (numbuttons > 2) {\n\t\t\tbutton3.Add(*buttonlist);\n\t\t\tbuttons[1] = &button3;\n\t\t\trealval[1] = BUTTON_3;\n\t\t\tbutton2.Add(*buttonlist);\n\t\t\tbuttons[2] = &button2;\n\t\t\trealval[2] = BUTTON_2;\n\t\t\tbuttons[curbutton]->Turn_On();\n\t\t} else {\n\t\t\tif (numbuttons == 2) {\n\t\t\t\tbutton2.Add(*buttonlist);\n\t\t\t\tbuttons[1] = &button2;\n\t\t\t\trealval[1] = BUTTON_2;\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tDraw the dialog.\n\t*/\n\tHide_Mouse();\n\tif (preserve) {\n#ifndef WIN32\n\tpreservex = max(0, x-4);\n\tpreservey = max(0, y-4);\n\tpreservew = min(width+8, 320-preservex);\n\tpreserveh = min(height+8, 200-preservey);\n\tback = new char[preservew * preserveh];\n\tSeenBuff.To_Buffer(preservex, preservey, preservew, preserveh, back, preservew * preserveh);\n#else\n\t\tback = new char[width * height];\n\t\tSeenBuff.To_Buffer(x, y, width, height, back, width * height);\n#endif\n\t}\n\tDialog_Box(x, y, width, height);\n\tDraw_Caption(Caption, x, y, width);\n\n\t/*\n\t**\tDraw the body of the message.\n\t*/\n\tFancy_Text_Print(buffer, printx, y + 20*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, tpf);\n\n\t/*\n\t**\tRedraw the buttons.\n\t*/\n\tif (buttonlist) {\n\t\tbuttonlist->Draw_All();\n\t}\n\tShow_Mouse();\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tif (buttonlist) {\n\t\tprocess = true;\n\t\tpressed = false;\n\t\twhile (process) {\n\n\t\t\t#ifdef WIN32\n\t\t\t/*\n\t\t\t** If we have just received input focus again after running in the background then\n\t\t\t** we need to redraw.\n\t\t\t*/\n\t\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\t\tAllSurfaces.SurfacesRestored = false;\n\t\t\t\tseen_buff_save.Blit(VisiblePage);\n\t\t\t\tdisplay = true;\n\t\t\t}\n\t\t\t#endif\n\n\t\t\tif (display) {\n\t\t\t\tdisplay = false;\n\n\t\t\t\tHide_Mouse();\n\t\t\t\tDialog_Box(x, y, width, height);\n\t\t\t\tDraw_Caption(Caption, x, y, width);\n\n\t\t\t\t/*\n\t\t\t\t**\tDraw the body of the message.\n\t\t\t\t*/\n\t\t\t\tFancy_Text_Print(buffer, printx, y + 20*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, tpf);\n\n\t\t\t\t/*\n\t\t\t\t**\tRedraw the buttons.\n\t\t\t\t*/\n\t\t\t\tif (buttonlist) {\n\t\t\t\t\tbuttonlist->Draw_All();\n\t\t\t\t}\n\t\t\t\tShow_Mouse();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tInvoke game callback.\n\t\t\t*/\n\t\t\tCall_Back();\n\n\t\t\t/*\n\t\t\t**\tFetch and process input.\n\t\t\t*/\n\t\t\tKeyNumType input = buttonlist->Input();\n#ifdef FIXIT_VERSION_3\n\t\t\t//\tI really hate to do this, but...      ajw\n\t\t\tif( cancel_current_msgbox )\n\t\t\t{\n\t\t\t\tcancel_current_msgbox = false;\n\t\t\t\tinput = KN_ESC;\n\t\t\t}\n#endif\n\t\t\tswitch (input) {\n\t\t\t\tcase (KN_ESC):\n\t\t\t\t\tselection = realval[numbuttons-1];\n\t\t\t\t\tpressed = true;\n\n#ifdef NEVER\n\t\t\t\t\tif (numbuttons > 2) {\n\t\t\t\t\t\tselection = realval[1];\n\t\t\t\t\t\tpressed = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tselection = realval[2];\n\t\t\t\t\t\tpressed = true;\n\t\t\t\t\t}\n#endif\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_1|BUTTON_FLAG):\n\t\t\t\t\tselection = realval[0];\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_2|BUTTON_FLAG):\n\t\t\t\t\tif (numbuttons > 2) {\n\t\t\t\t\t\tselection = realval[2];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tselection = realval[1];\n\t\t\t\t\t}\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_3|BUTTON_FLAG):\n\t\t\t\t\tselection = realval[1];\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_LEFT):\n\t\t\t\t\tif (numbuttons > 1) {\n\t\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\t\t\t\tcurbutton--;\n\t\t\t\t\t\tif (curbutton < 0) {\n\t\t\t\t\t\t\tcurbutton = numbuttons - 1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_RIGHT):\n\t\t\t\t\tif (numbuttons > 1) {\n\t\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\t\t\t\tcurbutton++;\n\t\t\t\t\t\tif (curbutton > (numbuttons - 1) ) {\n\t\t\t\t\t\t\tcurbutton = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_RETURN):\n\t\t\t\t\tselection = realval[curbutton];\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tCheck 'input' to see if it's the 1st char of button text\n\t\t\t\t*/\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (pressed) {\n\n\t\t\t\tTextButtonClass * toggle;\n\t\t\t\t/*\n\t\t\t\t**\tTurn all the buttons off.\n\t\t\t\t*/\n\t\t\t\ttoggle = (TextButtonClass *)buttonlist->Extract_Gadget(BUTTON_1);\n\t\t\t\tif (toggle != NULL) {\n\t\t\t\t\ttoggle->Turn_Off();\n\t\t\t\t\ttoggle->IsPressed = false;\n\t\t\t\t}\n\t\t\t\ttoggle = (TextButtonClass *)buttonlist->Extract_Gadget(BUTTON_2);\n\t\t\t\tif (toggle != NULL) {\n\t\t\t\t\ttoggle->Turn_Off();\n\t\t\t\t\ttoggle->IsPressed = false;\n\t\t\t\t}\n\t\t\t\ttoggle = (TextButtonClass *)buttonlist->Extract_Gadget(BUTTON_3);\n\t\t\t\tif (toggle != NULL) {\n\t\t\t\t\ttoggle->Turn_Off();\n\t\t\t\t\ttoggle->IsPressed = false;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tTurn on and depress the button that was selected.\n\t\t\t\t*/\n\t\t\t\tif (selection == BUTTON_1 || selection == BUTTON_2 || selection == BUTTON_3) {\n\t\t\t\t\tTextButtonClass * toggle = (TextButtonClass *)buttonlist->Extract_Gadget(selection);\n\t\t\t\t\tif (toggle != NULL) {\n\t\t\t\t\t\ttoggle->Turn_On();\n//\t\t\t\t\t\ttoggle->IsOn = true;\n\t\t\t\t\t\ttoggle->IsPressed = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tHide_Mouse();\n\t\t\t\tbuttonlist->Draw_All(true);\n\t\t\t\tShow_Mouse();\n\n\t\t\t\tswitch (selection) {\n\t\t\t\t\tcase (BUTTON_1):\n\t\t\t\t\t\tretval = 0;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_2):\n\t\t\t\t\t\tretval = 1;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase BUTTON_3:\n\t\t\t\t\t\tretval = 2;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tpressed = false;\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\tKeyboard->Clear();\n\t}\n\n\t/*\n\t**\tRestore the screen if necessary.\n\t*/\n\tif (preserve) {\n\t\tHide_Mouse();\n\t\tif (SeenBuff.Lock()) {\n\t\t\t#ifdef WIN32\n\t\t\t\tBuffer_To_Page(x, y, width, height, back, &SeenBuff);\n\t\t\t#else\n\t\t\t\tMCGA_Buffer_To_Page(preservex, preservey, preservew, preserveh, back, &SeenBuff);\n\t\t\t#endif\n\t\t}\n\t\tSeenBuff.Unlock();\n\n\t\tdelete[] back;\n\t\tback = NULL;\n\t\tShow_Mouse();\n\t}\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * WWMessageBox::Process -- this one takes integer text arguments                              *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      msg         message to display                                                         *\n *      b1txt         text for 1st button                                                      *\n *      b2txt         text for 2nd button; NULL = no 2nd button                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      # of button selected (0 = 1st)                                                         *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      'msg' text must be <= 38 chars                                                         *\n *      'b1txt' and 'b2txt' must each be <= 18 chars                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/12/1994 BR : Created.                                                                  *\n *   06/18/1995 JLB : Simplified.                                                              *\n *=============================================================================================*/\nint WWMessageBox::Process(int msg, int b1txt, int b2txt, int b3txt, bool preserve)\n{\n\treturn(Process(Text_String(msg), b1txt, b2txt, b3txt, preserve));\n}\n\n\n/***********************************************************************************************\n * WWMessageBox::Process -- Displays message box.                                              *\n *                                                                                             *\n *    This routine will display a message box and wait for player input. It varies from the    *\n *    other message box functions only in the type of parameters it takes.                     *\n *                                                                                             *\n * INPUT:   msg   -- Pointer to text string for the message itself.                            *\n *                                                                                             *\n *          b1txt -- Text number for the \"ok\" button.                                          *\n *                                                                                             *\n *          b2txt -- Text number for the \"cancel\" button.                                      *\n *                                                                                             *\n * OUTPUT:  Returns with the button selected. \"true\" if \"OK\" was pressed, and \"false\" if       *\n *          \"CANCEL\" was pressed.                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint WWMessageBox::Process(char const * msg, int b1txt, int b2txt, int b3txt, bool preserve)\n{\n\treturn(Process(msg, Text_String(b1txt), Text_String(b2txt), Text_String(b3txt), preserve));\n}\n"
  },
  {
    "path": "CODE/MSGBOX.CPP.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\msgbox.cpv   4.83   29 Oct 1996 23:49:56   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OPTIONS.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 8, 1994                                                 *\n *                                                                                             *\n *                  Last Update : August 24, 1995 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   WWMessageBox::Process -- Handles all the options graphic interface.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"msgbox.h\"\n#include \"gadget.h\"\n\n\n/***********************************************************************************************\n * WWMessageBox::Process -- pops up a message with yes/no, etc                                 *\n *                                                                                             *\n * This function displays a dialog box with a one-line message, and                            *\n * up to two buttons. The 2nd button is optional. The buttons default                          *\n * to \"OK\" and nothing, respectively. The hotkeys for the buttons are                          *\n * RETURN and ESCAPE.                                                                          *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      msg         message to display                                                         *\n *      b1txt         text for 1st button                                                      *\n *      b2txt         text for 2nd button; NULL = no 2nd button                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      # of button selected (0 = 1st)                                                         *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      'msg' text must be <= 38 chars                                                         *\n *      'b1txt' and 'b2txt' must each be <= 18 chars                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/08/1994 BR : Created.                                                                  *\n *   05/18/1995 JLB : Uses new font and dialog style.                                          *\n *   08/24/1995 JLB : Handles three buttons.                                                   *\n *=============================================================================================*/\n#define\tBUTTON_1\t\t1\n#define\tBUTTON_2\t\t2\n#define\tBUTTON_3\t\t3\n#define\tBUTTON_FLAG\t0x8000\nint WWMessageBox::Process(const char * msg, const char * b1txt, const char * b2txt, const char * b3txt, bool preserve)\n{\n#define BUFFSIZE (511)\n\tchar buffer[BUFFSIZE];\n\tbool retval;\n\tbool process;\t\t\t\t\t\t\t\t// loop while true\n\tint selection;\n\tbool pressed;\n\tint curbutton;\n\tTextButtonClass * buttons[3];\n\tvoid * back;\n\tBOOL display;\t\t\t\t\t\t\t\t\t// display level\n\tint  realval[5];\n\n\t#ifdef WIN32\n\tGraphicBufferClass seen_buff_save(VisiblePage.Get_Width(), VisiblePage.Get_Height(), (void*)NULL);\n\t#endif\n\n\tif (*b1txt == '\\0') b1txt = 0;\n\tif (*b2txt == '\\0') b2txt = 0;\n\tif (*b3txt == '\\0') b3txt = 0;\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT);\n\n\t/*\n\t**\tExamine the optional button parameters. Fetch the width and starting\n\t**\tcharacters for each.\n\t*/\n\tint bwidth, bheight;\t\t\t\t// button width and height\n\tint numbuttons = 0;\n\tif (b1txt != NULL) {\n\n\t\t/*\n\t\t**\tBuild the button list.\n\t\t*/\n\t\tbheight = FontHeight + FontYSpacing + (2 * RESFACTOR);\n\t\tbwidth = max((String_Pixel_Width(b1txt) + (8 * RESFACTOR)), (30 * RESFACTOR));\n\n\t\tif (b2txt != NULL) {\n\t\t\tnumbuttons = 2;\n\t\t\tbwidth = max((String_Pixel_Width( b2txt ) + (8 * RESFACTOR)), bwidth);\n\n\t\t\tif (b3txt != NULL) {\n\t\t\t\tnumbuttons = 3;\n\t\t\t}\n\n\t\t} else {\n\t\t\tnumbuttons = 1;\n\t\t}\n\t}\n\n\t/*\n\t**\tDetermine the dimensions of the text to be used for the dialog box.\n\t**\tThese dimensions will control how the dialog box looks.\n\t*/\n\tbuffer[BUFFSIZE-1] = 0;\n\tstrncpy(buffer, msg, BUFFSIZE-1);\n\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT);\n\tint width;\n\tint height;\n\tint lines = Format_Window_String(buffer, 255 * RESFACTOR, width, height);\n\tTextPrintType tpf = TPF_TEXT;\n\n\twidth = max(width, (90 * RESFACTOR));\n\twidth += 40 * RESFACTOR;\n\theight += (numbuttons == 0) ? (40 * RESFACTOR) : (60 * RESFACTOR);\n\n\tint x = (SeenBuff.Get_Width() - width) / 2;\n\tint y = (SeenBuff.Get_Height() - height) / 2;\n\tint printx = x + (20 * RESFACTOR);\n\n\t/*\n\t**\tSpecial hack to center a one line dialog box text.\n\t*/\n\tif (lines == 1) {\n\t\tprintx = x + width/2;\n\t\ttpf = tpf | TPF_CENTER;\n\t}\n\n\t/*\n\t**\tOther inits.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\t#ifdef WIN32\n\tVisiblePage.Blit(seen_buff_save);\n\t#endif\n\n\t/*\n\t**\tInitialize the button structures. All are initialized, even though one (or none) may\n\t**\tactually be added to the button list.\n\t*/\n\n        //DOS BUILD GERMAN BUTTONS NEED TO ONE ON TOP OF THE OTHER  VG 11/6/96\n\n\t#if (GERMAN) && (!WIN32)\n\tTextButtonClass button1(BUTTON_1, b1txt, TPF_BUTTON,\n\t\tx + ((numbuttons == 1) ? ((width - bwidth) >> 1) : (20 * RESFACTOR)), y + height - (bheight + (15 * RESFACTOR)), bwidth);\n\n\t/*\n\t**\tCenter button.\n\t*/\n\tTextButtonClass button2(BUTTON_2, b2txt, TPF_BUTTON,\n\t\tx + width - (bwidth + (20 * RESFACTOR)), y + height - (bheight + (15 * RESFACTOR)), bwidth);\n\n\t#endif\n\n\tTextButtonClass button1(BUTTON_1, b1txt, TPF_BUTTON,\n\t\tx + ((numbuttons == 1) ? ((width - bwidth) >> 1) : (20 * RESFACTOR)), y + height - (bheight + (15 * RESFACTOR)), bwidth);\n\n\t/*\n\t**\tCenter button.\n\t*/\n\tTextButtonClass button2(BUTTON_2, b2txt, TPF_BUTTON,\n\t\tx + width - (bwidth + (20 * RESFACTOR)), y + height - (bheight + (15 * RESFACTOR)), bwidth);\n\n\t/*\n\t**\tRight button.\n\t*/\n\tTextButtonClass button3(BUTTON_3, b3txt, TPF_BUTTON, 0, y + height - (bheight + (15 * RESFACTOR)));\n\tbutton3.X = x + ((width - button3.Width) >> 1);\n\n\tTextButtonClass * buttonlist = 0;\n\tcurbutton = 0;\n\n\t/*\n\t**\tAdd and initialize the buttons to the button list.\n\t*/\n\tmemset(buttons, '\\0', sizeof(buttons));\n\tif (numbuttons > 0) {\n\t\tbuttonlist = &button1;\n\t\tbuttons[0] = &button1;\n\t\trealval[0] = BUTTON_1;\n\t\tif (numbuttons > 2) {\n\t\t\tbutton3.Add(*buttonlist);\n\t\t\tbuttons[1] = &button3;\n\t\t\trealval[1] = BUTTON_3;\n\t\t\tbutton2.Add(*buttonlist);\n\t\t\tbuttons[2] = &button2;\n\t\t\trealval[2] = BUTTON_2;\n\t\t\tbuttons[curbutton]->Turn_On();\n\t\t} else {\n\t\t\tif (numbuttons == 2) {\n\t\t\t\tbutton2.Add(*buttonlist);\n\t\t\t\tbuttons[1] = &button2;\n\t\t\t\trealval[1] = BUTTON_2;\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tDraw the dialog.\n\t*/\n\tHide_Mouse();\n\tif (preserve) {\n\t\tback = new char[width * height];\n\t\tSeenBuff.To_Buffer(x, y, width, height, back, width * height);\n\t}\n\tDialog_Box(x, y, width, height);\n\tDraw_Caption(Caption, x, y, width);\n\n\t/*\n\t**\tDraw the body of the message.\n\t*/\n\tFancy_Text_Print(buffer, printx, y + 20*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, tpf);\n\n\t/*\n\t**\tRedraw the buttons.\n\t*/\n\tif (buttonlist) {\n\t\tbuttonlist->Draw_All();\n\t}\n\tShow_Mouse();\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tif (buttonlist) {\n\t\tprocess = true;\n\t\tpressed = false;\n\t\twhile (process) {\n\n\t\t\t#ifdef WIN32\n\t\t\t/*\n\t\t\t** If we have just received input focus again after running in the background then\n\t\t\t** we need to redraw.\n\t\t\t*/\n\t\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\t\tAllSurfaces.SurfacesRestored = false;\n\t\t\t\tseen_buff_save.Blit(VisiblePage);\n\t\t\t\tdisplay = true;\n\t\t\t}\n\t\t\t#endif\n\n\t\t\tif (display) {\n\t\t\t\tdisplay = false;\n\n\t\t\t\tHide_Mouse();\n\t\t\t\tDialog_Box(x, y, width, height);\n\t\t\t\tDraw_Caption(Caption, x, y, width);\n\n\t\t\t\t/*\n\t\t\t\t**\tDraw the body of the message.\n\t\t\t\t*/\n\t\t\t\tFancy_Text_Print(buffer, printx, y + 20*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, tpf);\n\n\t\t\t\t/*\n\t\t\t\t**\tRedraw the buttons.\n\t\t\t\t*/\n\t\t\t\tif (buttonlist) {\n\t\t\t\t\tbuttonlist->Draw_All();\n\t\t\t\t}\n\t\t\t\tShow_Mouse();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tInvoke game callback.\n\t\t\t*/\n\t\t\tCall_Back();\n\n\t\t\t/*\n\t\t\t**\tFetch and process input.\n\t\t\t*/\n\t\t\tKeyNumType input = buttonlist->Input();\n\t\t\tswitch (input) {\n\t\t\t\tcase (KN_ESC):\n\t\t\t\t\tselection = realval[numbuttons-1];\n\t\t\t\t\tpressed = true;\n\n#ifdef NEVER\n\t\t\t\t\tif (numbuttons > 2) {\n\t\t\t\t\t\tselection = realval[1];\n\t\t\t\t\t\tpressed = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tselection = realval[2];\n\t\t\t\t\t\tpressed = true;\n\t\t\t\t\t}\n#endif\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_1|BUTTON_FLAG):\n\t\t\t\t\tselection = realval[0];\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_2|BUTTON_FLAG):\n\t\t\t\t\tif (numbuttons > 2) {\n\t\t\t\t\t\tselection = realval[2];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tselection = realval[1];\n\t\t\t\t\t}\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_3|BUTTON_FLAG):\n\t\t\t\t\tselection = realval[1];\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_LEFT):\n\t\t\t\t\tif (numbuttons > 1) {\n\t\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\t\t\t\tcurbutton--;\n\t\t\t\t\t\tif (curbutton < 0) {\n\t\t\t\t\t\t\tcurbutton = numbuttons - 1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_RIGHT):\n\t\t\t\t\tif (numbuttons > 1) {\n\t\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\t\t\t\tcurbutton++;\n\t\t\t\t\t\tif (curbutton > (numbuttons - 1) ) {\n\t\t\t\t\t\t\tcurbutton = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_RETURN):\n\t\t\t\t\tselection = realval[curbutton];\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tCheck 'input' to see if it's the 1st char of button text\n\t\t\t\t*/\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (pressed) {\n\n//#ifdef NEVER\n\t\t\t\tTextButtonClass * toggle;\n\t\t\t\t/*\n\t\t\t\t**\tTurn all the buttons off.\n\t\t\t\t*/\n\t\t\t\ttoggle = (TextButtonClass *)buttonlist->Extract_Gadget(BUTTON_1);\n\t\t\t\tif (toggle != NULL) {\n\t\t\t\t\ttoggle->Turn_Off();\n\t\t\t\t\ttoggle->IsPressed = false;\n\t\t\t\t}\n\t\t\t\ttoggle = (TextButtonClass *)buttonlist->Extract_Gadget(BUTTON_2);\n\t\t\t\tif (toggle != NULL) {\n\t\t\t\t\ttoggle->Turn_Off();\n\t\t\t\t\ttoggle->IsPressed = false;\n\t\t\t\t}\n\t\t\t\ttoggle = (TextButtonClass *)buttonlist->Extract_Gadget(BUTTON_3);\n\t\t\t\tif (toggle != NULL) {\n\t\t\t\t\ttoggle->Turn_Off();\n\t\t\t\t\ttoggle->IsPressed = false;\n\t\t\t\t}\n\n//#endif\n\t\t\t\t/*\n\t\t\t\t**\tTurn on and depress the button that was selected.\n\t\t\t\t*/\n\t\t\t\tif (selection == BUTTON_1 || selection == BUTTON_2 || selection == BUTTON_3) {\n\t\t\t\t\tTextButtonClass * toggle = (TextButtonClass *)buttonlist->Extract_Gadget(selection);\n\t\t\t\t\tif (toggle != NULL) {\n//\t\t\t\t\t\ttoggle->Turn_On();\n\t\t\t\t\t\ttoggle->IsOn = true;\n\t\t\t\t\t\ttoggle->IsPressed = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tHide_Mouse();\n\t\t\t\tbuttonlist->Draw_All(true);\n\t\t\t\tShow_Mouse();\n\n\t\t\t\tswitch (selection) {\n\t\t\t\t\tcase (BUTTON_1):\n\t\t\t\t\t\tretval = 0;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_2):\n\t\t\t\t\t\tretval = 1;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase BUTTON_3:\n\t\t\t\t\t\tretval = 2;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tpressed = false;\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\tKeyboard->Clear();\n\t}\n\n\t/*\n\t**\tRestore the screen if necessary.\n\t*/\n\tif (preserve) {\n\t\tHide_Mouse();\n\t\tif (SeenBuff.Lock()) {\n\t\t\t#ifdef WIN32\n\t\t\t\tBuffer_To_Page(x, y, width, height, back, &SeenBuff);\n\t\t\t#else\n\t\t\t\tMCGA_Buffer_To_Page(x, y, width, height, back, &SeenBuff);\n\t\t\t#endif\n\t\t}\n\t\tSeenBuff.Unlock();\n\n\t\tdelete[] back;\n\t\tback = NULL;\n\t\tShow_Mouse();\n\t}\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * WWMessageBox::Process -- this one takes integer text arguments                              *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      msg         message to display                                                         *\n *      b1txt         text for 1st button                                                      *\n *      b2txt         text for 2nd button; NULL = no 2nd button                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      # of button selected (0 = 1st)                                                         *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      'msg' text must be <= 38 chars                                                         *\n *      'b1txt' and 'b2txt' must each be <= 18 chars                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/12/1994 BR : Created.                                                                  *\n *   06/18/1995 JLB : Simplified.                                                              *\n *=============================================================================================*/\nint WWMessageBox::Process(int msg, int b1txt, int b2txt, int b3txt, bool preserve)\n{\n\treturn(Process(Text_String(msg), b1txt, b2txt, b3txt, preserve));\n}\n\n\n/***********************************************************************************************\n * WWMessageBox::Process -- Displays message box.                                              *\n *                                                                                             *\n *    This routine will display a message box and wait for player input. It varies from the    *\n *    other message box functions only in the type of parameters it takes.                     *\n *                                                                                             *\n * INPUT:   msg   -- Pointer to text string for the message itself.                            *\n *                                                                                             *\n *          b1txt -- Text number for the \"ok\" button.                                          *\n *                                                                                             *\n *          b2txt -- Text number for the \"cancel\" button.                                      *\n *                                                                                             *\n * OUTPUT:  Returns with the button selected. \"true\" if \"OK\" was pressed, and \"false\" if       *\n *          \"CANCEL\" was pressed.                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint WWMessageBox::Process(char const * msg, int b1txt, int b2txt, int b3txt, bool preserve)\n{\n\treturn(Process(msg, Text_String(b1txt), Text_String(b2txt), Text_String(b3txt), preserve));\n}\n"
  },
  {
    "path": "CODE/MSGBOX.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MSGBOX.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OPTIONS.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 8, 1994                                                 *\n *                                                                                             *\n *                  Last Update : June 8, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MSGBOX_H\n#define MSGBOX_H\n\n#include\t\"jshell.h\"\n\nclass WWMessageBox\n{\n\t\tint Caption;\n\n\tpublic:\n\t\tWWMessageBox(int caption=TXT_NONE) {Caption = caption;};\n\t\tint Process(const char *msg, const char *b1txt, const char *b2txt=NULL, const char *b3txt=NULL, bool preserve=false);\n\t\tint Process(int msg, int b1txt=TXT_OK, int b2txt=TXT_NONE, int b3txt=TXT_NONE, bool preserve=false);\n\t\tint Process(char const *msg, int b1txt=TXT_OK, int b2txt=TXT_NONE, int b3txt=TXT_NONE, bool preserve=false);\n};\n\n#endif\n\n"
  },
  {
    "path": "CODE/MSGLIST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MSGLIST.CPP 2     3/04/97 2:52p Joe_bostic $ */\n/***************************************************************************\n ***              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               ***\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : MSGLIST.CPP                              *\n *                                                                         *\n *                   Programmer : Bill R. Randolph                         *\n *                                                                         *\n *                   Start Date : 05/22/95                                 *\n *                                                                         *\n *                  Last Update : March 4, 1997 [JLB]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   MessageListClass::MessageListClass -- constructor                     *\n *   MessageListClass::~MessageListClass -- destructor                     *\n *   MessageListClass::Init -- Inits message system, sets options          *\n *   MessageListClass::Add_Message -- displays the given message           *\n *   MessageListClass::Get_Message -- retrieves given message              *\n *   MessageListClass::Get_Label -- retrieves given text label\t\t\t\t\t*\n *   MessageListClass::Concat_Message -- concats the given message         *\n *   MessageListClass::Add_Edit -- Adds editable string to message list    *\n *   MessageListClass::Remove_Edit -- removes the edit field               *\n *   MessageListClass::Get_Edit_Buf -- gets edit buffer                    *\n *   MessageListClass::Set_Edit_Color -- sets color of edit gizmo          *\n *   MessageListClass::Manage -- Manages multiplayer messages              *\n *   MessageListClass::Input -- Handles input for sending messages         *\n *   MessageListClass::Draw -- Draws the messages                          *\n *   MessageListClass::Num_Messages -- returns # messages in the list      *\n *   MessageListClass::Set_Width -- sets allowable width of messages       *\n *   MessageListClass::Trim_Message -- trims chars off start of message    *\n *   MessageListClass::Compute_Y -- recomputes y-coord for all messages    *\n *   MessageListClass::Reset -- Reset so no messages are visible.          * \n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/**************************** Globals **************************************/\n\n\n/***************************************************************************\n * MessageListClass::MessageListClass -- constructor                       *\n *                                                                         *\n * INPUT:                                                                  *\n *    x,y\t\t\tcoord of upper-left of top message                    \t*\n *    max_msg\t\tmax messages allowed, including edit message          \t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    none.                                                              \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nMessageListClass::MessageListClass(void)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t// Init all data members\n\t//------------------------------------------------------------------------\n\tMessageList = 0;\n\tMessageX = 0;\n\tMessageY = 0;\n\tMaxMessages = 0;\n\tMaxChars = 0;\n\tHeight = 0;\n\n\tEnableOverflow = 0;\n\tAdjustEdit = 0;\n\tIsEdit = 0;\n\tEditX = 0;\n\tEditY = 0;\n\tEditLabel = 0;\n\tEditBuf[0] = 0;\n\tOverflowBuf[0] = 0;\n\tEditCurPos = 0;\n\tEditInitPos = 0;\n\tCursorChar = 0;\n\tOverflowStart = 0;\n\tOverflowEnd = 0;\n\n\tfor (i = 0; i < MAX_NUM_MESSAGES; i++) {\n\t\tBufferAvail[i] = 1;\n\t}\n\n}\t// end of MessageListClass\n\n\n/***************************************************************************\n * MessageListClass::~MessageListClass -- destructor                       *\n *                                                                         *\n * INPUT:                                                                  *\n *    x,y\t\t\tcoord of upper-left of top message                     \t*\n *    max_msg\t\tmax messages allowed, including edit message          \t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    none.                                                              \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nMessageListClass::~MessageListClass()\n{\n\tInit(0,0,0,0,0,0,0,0,0,0);\n\n}\t// end of ~MessageListClass\n\n\n/***************************************************************************\n * MessageListClass::Init -- Inits message system, sets options            *\n *                                                                         *\n * INPUT:                                                                  *\n *    x,y\t\t\t\tcoord of upper-left of top message                    *\n *    max_msg\t\t\tmax messages allowed, NOT including edit message      *\n *    maxchars\t\t\tmax # characters allowed per message                \t*\n *\t\theight\t\t\tpixel height of a line of text\t\t\t\t\t\t\t\t*\n *\t\tedit_x\t\t\tx-coord of edit field; -1 = put at the top of the\t\t*\n *\t\t\t\t\t\t\tother messages\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tedit_y\t\t\ty-coord of edit field; -1 = put at the top of the\t\t*\n *\t\t\t\t\t\t\tother messages\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\toverflow_on\t\ttrue = enable the overflow typing feature\t\t\t\t\t*\n *\t\tover_start\t\tstart index for overflow processing\t\t\t\t\t\t\t*\n *\t\tover_end\t\t\tend index for overflow processing\t\t\t\t\t\t\t*\n *     width          pixel width of message buffer                         *\n *                                                                         *\n * OUTPUT:                                                                 *\n *    none.                                                              \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid MessageListClass::Init(int x, int y, int max_msg, int maxchars,\n\tint height, int edit_x, int edit_y, int overflow_on, int over_start,\n\tint over_end, int width)\n{\n\tTextLabelClass * txtlabel;\n\tint i;\n\n\tWidth = width;\n\n\t//------------------------------------------------------------------------\n\t//\tRemove every entry in the list\n\t//------------------------------------------------------------------------\n\ttxtlabel = MessageList;\n\twhile (txtlabel) {\n\t\tMessageList = (TextLabelClass *)txtlabel->Remove();\n\t\tdelete txtlabel;\n\t\ttxtlabel = MessageList;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tMark all buffers as available\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MAX_NUM_MESSAGES; i++) {\n\t\tBufferAvail[i] = 1;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tRemove the editable message\n\t//------------------------------------------------------------------------\n\tif (IsEdit) {\n\t\tdelete EditLabel;\n\t\tEditLabel = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tInit variables\n\t//------------------------------------------------------------------------\n\tMessageList = 0;\n\tMessageX = x;\n\tMessageY = y;\n\n\tMaxMessages = max_msg;\n\tif (MaxMessages > MAX_NUM_MESSAGES)\n\t\tMaxMessages = MAX_NUM_MESSAGES;\n\n\tMaxChars = maxchars;\n\tif (MaxChars > MAX_MESSAGE_LENGTH)\n\t\tMaxChars = MAX_MESSAGE_LENGTH;\n\n\tHeight = height;\n\n\t//------------------------------------------------------------------------\n\t// Init the edit field variables.  If edit_x or edit_y is -1, place the\n\t// edit field above the other messages; otherwise, place it at the desired\n\t// coords.\n\t//------------------------------------------------------------------------\n\tEnableOverflow = overflow_on;\n\tIsEdit = 0;\n\tif (edit_x == -1 || edit_y == -1) {\n\t\tAdjustEdit = 1;\n\t\tEditX = x;\n\t\tEditY = y;\n\t}\n\telse {\n\t\tAdjustEdit = 0;\n\t\tEditX = edit_x;\n\t\tEditY = edit_y;\n\t}\n\tEditLabel = 0;\n\tEditBuf[0] = 0;\n\tOverflowBuf[0] = 0;\n\tEditCurPos = 0;\n\tEditInitPos = 0;\n\tCursorChar = 0;\n\n\t//------------------------------------------------------------------------\n\t// Init the overflow processing indices\n\t//------------------------------------------------------------------------\n\tOverflowStart = over_start;\n\tOverflowEnd = over_end;\n\tif (OverflowEnd >= MaxChars) {\n\t\tOverflowEnd = MaxChars - 1;\n\t}\n\tif (OverflowStart >= OverflowEnd) {\n\t\tOverflowStart = OverflowEnd - 1;\n\t}\n\n}\t// end of Init\n\n\n/*********************************************************************************************** \n * MessageListClass::Reset -- Reset so no messages are visible.                                * \n *                                                                                             * \n *    This routine will reset the message list tracker so that any displayed messages are      * \n *    cleared.                                                                                 * \n *                                                                                             * \n * INPUT:   none                                                                               * \n *                                                                                             * \n * OUTPUT:  none                                                                               * \n *                                                                                             * \n * WARNINGS:   none                                                                            * \n *                                                                                             * \n * HISTORY:                                                                                    * \n *   03/04/1997 JLB : Created.                                                                 * \n *=============================================================================================*/\nvoid MessageListClass::Reset(void)\n{\n\t//------------------------------------------------------------------------\n\t//\tRemove every entry in the list\n\t//------------------------------------------------------------------------\n\tTextLabelClass * txtlabel = MessageList;\n\twhile (txtlabel) {\n\t\tMessageList = (TextLabelClass *)txtlabel->Remove();\n\t\tdelete txtlabel;\n\t\ttxtlabel = MessageList;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tMark all buffers as available\n\t//------------------------------------------------------------------------\n\tfor (int index = 0; index < MAX_NUM_MESSAGES; index++) {\n\t\tBufferAvail[index] = 1;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tRemove the editable message\n\t//------------------------------------------------------------------------\n\tif (IsEdit) {\n\t\tdelete EditLabel;\n\t\tEditLabel = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tInit variables\n\t//------------------------------------------------------------------------\n\tMessageList = 0;\n\tEditLabel = 0;\n\tIsEdit = 0;\n}\n\n\n/***************************************************************************\n * MessageListClass::Add_Message -- displays the given message             *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tname\t\t\tname of sender, NULL = none\t\t\t\t\t\t\t\t\t\t*\n *\t\tid\t\t\t\tnumerical ID for this message\t\t\t\t\t\t\t\t\t\t*\n *    txt         text to display                                        \t*\n *    color       color to draw text in                                \t\t*\n *    style       style to use                                         \t\t*\n *    timeout     # of ticks the thing is supposed to last (-1 = forever)\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    ptr to new TextLabelClass object.                                  \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/05/1995 BRR : Created.                                             *\n *   10/16/1996 JLB : Audio feedback added.                                *\n *=========================================================================*/\nTextLabelClass * MessageListClass::Add_Message(char const * name, int id, char const * txt,\n\tPlayerColorType color, TextPrintType style, int timeout)\n{\n\tTextLabelClass * txtlabel;\n\tint i;\n\tint found;\n\tchar message[MAX_MESSAGE_LENGTH + 30];\n\tchar temp[MAX_MESSAGE_LENGTH + 30];\n\tint print_this_pass;\n\tchar save = 0;\n\tint mess_start;\n\n\t//------------------------------------------------------------------------\n\t// Combine the name & message text, if there's a name given\n\t//------------------------------------------------------------------------\n\tif (name) {\n\t\tsprintf(message, \"%s:%s\", name, txt);\n\t} else {\n\t\tstrcpy(message, txt);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCheck that printing this wont overrun the width of the print area on screen\n\t//------------------------------------------------------------------------\n\n\tprint_this_pass = 0;\n\tFancy_Text_Print(TXT_NONE, 0, 0, &ColorRemaps[color], TBLACK, style);\n\tint wid = String_Pixel_Width(message);\n\tif (wid >= Width-8) {\n\t\t//------------------------------------------------------------------------\n\t\t//\tBugger. Its too long. Loop through and find out how many chars we can print\n\t\t//------------------------------------------------------------------------\n\t\tif (name) {\n\t\t\tsprintf (temp, \"%s:\", name);\n\t\t\tmess_start = strlen (name)+1;\n\t\t} else {\n\t\t\tmess_start = 0;\n\t\t}\n\t\tfor (int i=1 ; i<strlen(txt) ; i++) {\n\t\t\tstrncpy (&temp[mess_start], txt, i);\n\t\t\ttemp [mess_start + i] = 0;\n\t\t\twid = String_Pixel_Width(temp);\n\t\t\tif (wid >= Width-8) {\n\t\t\t\tprint_this_pass = mess_start + i-1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t//------------------------------------------------------------------------\n\t\t//\tPrematurely terminate the string so it doesn't all print.\n\t\t// We will re-enter at the end to print the rest.\n\t\t//------------------------------------------------------------------------\n\t\tif (print_this_pass) {\n\t\t\tsave = message [print_this_pass];\n\t\t\tmessage [print_this_pass] = 0;\n\t\t}\n\t}\n\n\n\n\t//------------------------------------------------------------------------\n\t//\tRemove the top-most message if we're about to exceed the max allowed\n\t//------------------------------------------------------------------------\n\tif ( (MaxMessages > 0) && ((Num_Messages() + 1) > MaxMessages)) {\n\t\ttxtlabel = MessageList;\n\n\t\tif (txtlabel==NULL)\n\t\t\treturn(NULL);\n\n\t\t//.....................................................................\n\t\t//\tRemove this message from the list; mark its buffer as being available.\n\t\t//.....................................................................\n\t\tMessageList = (TextLabelClass *)txtlabel->Remove();\n\t\tfor (i = 0; i < MAX_NUM_MESSAGES; i++) {\n\t\t\tif (txtlabel->Text == MessageBuffers[i])\n\t\t\t\tBufferAvail[i] = 1;\n\t\t}\n\t\tdelete txtlabel;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCreate the message\n\t//------------------------------------------------------------------------\n\ttxtlabel = new TextLabelClass (message, MessageX, MessageY,\n\t\t&ColorRemaps[color], style);\n\tif (timeout==-1) {\n\t\ttxtlabel->UserData1 = 0;\n\t}\n\telse {\n\t\ttxtlabel->UserData1 = TickCount + timeout;\n\t}\n\ttxtlabel->UserData2 = id;\n\n\t//------------------------------------------------------------------------\n\t//\tFind a buffer to store our message in; if there are none, don't add the\n\t//\tmessage.\n\t//------------------------------------------------------------------------\n\tfound = 0;\n\tfor (i = 0; i < MAX_NUM_MESSAGES; i++) {\n\t\tif (BufferAvail[i]) {\n\t\t\tBufferAvail[i] = 0;\n\t\t\tmemset (MessageBuffers[i],0,MAX_MESSAGE_LENGTH + 30);\n\t\t\tstrcpy (MessageBuffers[i],message);\n\t\t\ttxtlabel->Text = MessageBuffers[i];\n\t\t\tfound = 1;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (!found) {\n\t\tdelete txtlabel;\n\t\treturn (NULL);\n\t}\n\n\tSound_Effect(VOC_INCOMING_MESSAGE);\n\n\t//------------------------------------------------------------------------\n\t//\tAttach the message to our list\n\t//------------------------------------------------------------------------\n\tif (MessageList) {\n\t\ttxtlabel->Add_Tail (*MessageList);\n\t}\n\telse {\n\t\tMessageList = txtlabel;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tRecompute all messages' y-coordinate values\n\t//------------------------------------------------------------------------\n\tCompute_Y();\n\n\t//------------------------------------------------------------------------\n\t//\tIf we terminated the string before the end then we need to reenter to\n\t// add a new message with the rest of the string.\n\t//------------------------------------------------------------------------\n\tif (save) {\n\t\tmessage [print_this_pass] = save;\n\t\tAdd_Message (name, id, &message [print_this_pass], color, style, timeout);\n\t}\n\n\treturn(txtlabel);\n\n}\t// end of Add_Message\n\n\n/***************************************************************************\n * MessageListClass::Get_Message -- retrieves given message                *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\t\tID of message to get\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to message text, NULL if not found\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/07/1995 BRR : Created.                                             *\n *=========================================================================*/\nchar * MessageListClass::Get_Message(int id)\n{\n\tTextLabelClass * gadg;\n\n\t//------------------------------------------------------------------------\n\t// Scan the message list, searching for the given ID\n\t//------------------------------------------------------------------------\n\tif (MessageList) {\n\t\tgadg = MessageList;\n\t\twhile (gadg) {\n\t\t\tif (gadg->UserData2 == id) {\n\t\t\t\treturn (gadg->Text);\n\t\t\t}\n\t\t\tgadg = (TextLabelClass *)gadg->Get_Next();\n\t\t}\n\t}\n\n\treturn (NULL);\n\n}\t// end of Get_Message\n\n\n/***************************************************************************\n * MessageListClass::Get_Label -- retrieves given text label\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\t\tID of message to get\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to message text, NULL if not found\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/07/1995 BRR : Created.                                             *\n *=========================================================================*/\nTextLabelClass * MessageListClass::Get_Label(int id)\n{\n\tTextLabelClass * gadg;\n\n\t//------------------------------------------------------------------------\n\t// Scan the message list, searching for the given ID\n\t//------------------------------------------------------------------------\n\tif (MessageList) {\n\t\tgadg = MessageList;\n\t\twhile (gadg) {\n\t\t\tif (gadg->UserData2 == id) {\n\t\t\t\treturn (gadg);\n\t\t\t}\n\t\t\tgadg = (TextLabelClass *)gadg->Get_Next();\n\t\t}\n\t}\n\n\treturn (NULL);\n\n}\t// end of Get_Label\n\n\n/***************************************************************************\n * MessageListClass::Concat_Message -- concats the given message           *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tname\t\t\tname of sender; NULL = none\t\t\t\t\t\t\t\t\t\t*\n *\t\tid\t\t\t\tID of message to concatenate to\t\t\t\t\t\t\t\t\t*\n *\t\ttxt\t\t\ttext to concatenate onto existing message\t\t\t\t\t\t*\n *\t\ttimeout\t\tnew timeout for message\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error (id or name not found)\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tIf the required message doesn't exist, this routine does nothing.\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/07/1995 BRR : Created.                                             *\n *=========================================================================*/\nint MessageListClass::Concat_Message(char const * name, int id, char const * txt, int timeout)\n{\n\tint min_chars;\n\tint max_chars;\n\tchar * msg;\n\tTextLabelClass * tlabel;\n\tint found;\n\n\t//------------------------------------------------------------------------\n\t// If no name is given, or the concatenation feature is turned off,\n\t// don't concatenate the message\n\t//------------------------------------------------------------------------\n\tif (!name || !EnableOverflow) {\n\t\treturn (0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Scan through all active messages, searching for one with a matching\n\t// name & ID\n\t//------------------------------------------------------------------------\n\tfound = 0;\n\tif (MessageList) {\n\t\ttlabel = MessageList;\n\t\twhile (tlabel) {\n\t\t\tif (tlabel->UserData2 == id &&\n\t\t\t\t!memcmp(tlabel->Text,name,strlen(name))) {\n\t\t\t\tfound = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\ttlabel = (TextLabelClass *)tlabel->Get_Next();\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t// name and ID not found; return\n\t//------------------------------------------------------------------------\n\tif (!found) {\n\t\treturn (0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// set a pointer to the text string, plus the name and colon\n\t//------------------------------------------------------------------------\n\tmsg = tlabel->Text + strlen(name) + 1;\n\n\t//------------------------------------------------------------------------\n\t// If there's room enough in the message, just add the given string\n\t//------------------------------------------------------------------------\n\tif ( (strlen(msg) + strlen(txt)) < MaxChars) {\n\n\t\t//---------------------------------------------------------------------\n\t\t// We need to trim the message if there is no room to draw it\n\t\t//---------------------------------------------------------------------\n\t\tchar *concat_test = new char [MaxChars+1];\n\t\tFancy_Text_Print(TXT_NONE, 0, 0, tlabel->Color, TBLACK, tlabel->Style);\n\t\tint name_width = String_Pixel_Width(tlabel->Text) - String_Pixel_Width(msg);\n\t\tint width;\n\n\t\tstrcpy (concat_test, msg);\n\t\tstrcat (concat_test, txt);\n\t\twidth = String_Pixel_Width(concat_test) + name_width;\n\t\tmin_chars = 10;\n\n\t\twhile (width >= Width-8){\n\n\t\t\tmax_chars = strlen (msg);\n\t\t\tif (max_chars < min_chars) {\n\t\t\t\tmax_chars = min_chars;\n\t\t\t}\n\n\t\t\tTrim_Message (NULL, msg, min_chars, max_chars, 0);\n\n\t\t\tstrcpy (concat_test, msg);\n\t\t\tstrcat (concat_test, txt);\n\n\t\t\twidth = String_Pixel_Width(concat_test) + name_width;\n\t\t};\n\n\t\tdelete [] concat_test;\n\n\t\tstrcat (msg,txt);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Otherwise, trim off some characters from the beginning of the\n\t// message.  Trim off at least enough to leave room for the new text.\n\t// Trim from left to right to remove the minimum required text.\n\t//------------------------------------------------------------------------\n\telse {\n\t\tmin_chars = (strlen(msg) + strlen(txt)) - MaxChars;\n\t\tmax_chars = strlen(msg);\n\t\tif (max_chars < min_chars) {\n\t\t\tmax_chars = min_chars;\n\t\t}\n\t\tTrim_Message (NULL, msg, min_chars, max_chars, 0);\n\t\tstrcat (msg, txt);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Set the new timeout value for the message\n\t//------------------------------------------------------------------------\n\tif (timeout==-1) {\n\t\ttlabel->UserData1 = 0;\n\t}\n\telse {\n\t\ttlabel->UserData1 = TickCount + timeout;\n\t}\n\n\treturn (1);\n\n}\t// end of Concat_Message\n\n\n\n/***********************************************************************************************\n * MessageListClass::Set_Edit_Focus -- Give the gadget system focus to the edit box            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/19/96 4:41PM ST : Created                                                             *\n *=============================================================================================*/\nvoid MessageListClass::Set_Edit_Focus (void)\n{\n\tif (IsEdit) EditLabel->Set_Focus();\n}\n\n\n/***********************************************************************************************\n * MessageListClass::Has_Edit_Focus -- Find out if the edit box has the input focus            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/19/96 4:41PM ST : Created                                                             *\n *=============================================================================================*/\nbool MessageListClass::Has_Edit_Focus (void)\n{\n\tif (IsEdit){\n\t\treturn (EditLabel->Has_Focus());\n\t}else{\n\t\treturn(false);\n\t}\n}\n\n\n\n/***************************************************************************\n * MessageListClass::Add_Edit -- Adds editable string to message list      *\n *                                                                         *\n * INPUT:                                                                  *\n *    color\t\t\tcolor of edit message                                \t\t*\n *    style\t\t\tstyle of edit message                                \t\t*\n *    to\t\t\t\tstring: who to send to; NULL = none\t\t\t\t\t\t\t\t*\n *\t\tcursor\t\tcharacter to use as a cursor; 0 = none\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    ptr to new TextLabelClass                                          \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/22/1995 BRR : Created.                                             *\n *=========================================================================*/\nTextLabelClass * MessageListClass::Add_Edit(PlayerColorType color,\n\tTextPrintType style, char * to, char cursor, int width)\n{\n\tint i;\n\tTextLabelClass * txtlabel;\n\n\t//------------------------------------------------------------------------\n\t//\tDo nothing if we're already in \"edit\" mode\n\t//------------------------------------------------------------------------\n\tif (IsEdit) {\n\t\tEditLabel->Set_Focus();\n\t\treturn(NULL);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tRemove the top-most message if we're about to exceed the max allowed\n\t//------------------------------------------------------------------------\n\tif (AdjustEdit && ((Num_Messages() + 1) > MaxMessages)) {\n\t\ttxtlabel = MessageList;\n\t\tMessageList = (TextLabelClass *)txtlabel->Remove();\n\t\tfor (i = 0; i < MAX_NUM_MESSAGES; i++) {\n\t\t\tif (txtlabel->Text == MessageBuffers[i])\n\t\t\t\tBufferAvail[i] = 1;\n\t\t}\n\t\tdelete txtlabel;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// If no 'to' field was passed in, ignore it\n\t//------------------------------------------------------------------------\n\tif (!to) {\n\t\tto = \"\";\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Set the cursor character\n\t//------------------------------------------------------------------------\n\tCursorChar = cursor;\n\n\t//------------------------------------------------------------------------\n\t//\tInitialize the buffer positions; create a new text label object\n\t//------------------------------------------------------------------------\n\tmemset (EditBuf, 0, sizeof(EditBuf));\n\tstrcpy (EditBuf, to);\n\tOverflowBuf[0] = 0;\n\tEditCurPos = EditInitPos = strlen(to);\n\tEditLabel = new TextLabelClass (EditBuf, EditX, EditY,\n\t\t&ColorRemaps[color], style);\n\n\tWidth = width;\n\n\tif (EditLabel) {\n\t\tIsEdit = 1;\n\t\tEditLabel->Set_Focus();\n\t}\n\telse {\n\t\tIsEdit = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// If the edit field appears over the message list, recompute the y-value\n\t// for all messages.  Also, adjust MaxMessages down by one, since there\n\t// is now one less slot available.\n\t//------------------------------------------------------------------------\n\tif (AdjustEdit) {\n\t\tCompute_Y();\n\t\tMaxMessages--;\n\t}\n\n\treturn(EditLabel);\n\n}\t// end of Add_Edit\n\n\n/***************************************************************************\n * MessageListClass::Remove_Edit -- removes the edit field                 *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/06/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid MessageListClass::Remove_Edit(void)\n{\n\t//------------------------------------------------------------------------\n\t// If the edit field is active, delete it\n\t//------------------------------------------------------------------------\n\tif (IsEdit) {\n\t\tIsEdit = 0;\n\t\tdelete EditLabel;\n\n\t\t//.....................................................................\n\t\t// If the edit field appears over the message list, recompute the\n\t\t// y-value for all messages.  Adjust MaxMessages back up, since there\n\t\t// is now a new available slot.\n\t\t//.....................................................................\n\t\tif (AdjustEdit) {\n\t\t\tCompute_Y();\n\t\t\tMaxMessages++;\n\t\t}\n\t}\n\n}\t// end if Remove_Edit\n\n\n/***************************************************************************\n * MessageListClass::Get_Edit_Buf -- gets edit buffer                      *\n *                                                                         *\n * INPUT:                                                                  *\n *    none.                                                              \t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    ptr to edit buffer, minus the \"To:\" header                         \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nchar * MessageListClass::Get_Edit_Buf(void)\n{\n\treturn(EditBuf + EditInitPos);\n\n}\t// end of Get_Edit_Buf\n\n\n/***************************************************************************\n * MessageListClass::Set_Edit_Color -- sets color of edit gizmo            *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tcolor\t\tcolor to set edit label to\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/08/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid MessageListClass::Set_Edit_Color(PlayerColorType color)\n{\n\tif (IsEdit) {\n\t\tEditLabel->Color = &ColorRemaps[color];\n\t}\n\n}\t// end of Set_Edit_Color\n\n\n/***************************************************************************\n * MessageListClass::Manage -- Manages multiplayer messages                *\n *                                                                         *\n * If this routine returns TRUE, the caller should update the display.     *\n *                                                                         *\n * INPUT:                                                                  *\n *    none.                                                              \t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    none.                                                              \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    0 = no change has occurred, 1 = changed                            \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/05/1995 BRR : Created.                                             *\n *=========================================================================*/\nint MessageListClass::Manage (void)\n{\n\tTextLabelClass * txtlabel;\n\tTextLabelClass * next;\n\tint changed = 0;\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tLoop through all messages\n\t//------------------------------------------------------------------------\n\ttxtlabel = MessageList;\n\twhile (txtlabel) {\n\n\t\t//.....................................................................\n\t\t//\tIf this message's time is up, remove it from the list\n\t\t//.....................................................................\n\t\tif (txtlabel->UserData1 != 0 && TickCount > txtlabel->UserData1) {\n\n\t\t\t//..................................................................\n\t\t\t//\tSave the next ptr in the list; remove this entry\n\t\t\t//..................................................................\n\t\t\tnext = (TextLabelClass *)txtlabel->Get_Next();\n\t\t\tMessageList = (TextLabelClass *)txtlabel->Remove();\n\t\t\tfor (i = 0; i < MAX_NUM_MESSAGES; i++) {\n\t\t\t\tif (txtlabel->Text == MessageBuffers[i]) {\n\t\t\t\t\tBufferAvail[i] = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tdelete txtlabel;\n\t\t\tchanged = 1;\n\t\t\ttxtlabel = next;\n\t\t}\n\t\telse {\n\t\t\ttxtlabel = (TextLabelClass *)txtlabel->Get_Next();\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tIf a changed has been made, recompute the y-coord of all messages\n\t//------------------------------------------------------------------------\n\tif (changed) {\n\t\tCompute_Y();\n\t}\n\n\treturn(changed);\n\n}\t// end of Manage\n\n\n/***************************************************************************\n * MessageListClass::Input -- Handles input for sending messages           *\n *                                                                         *\n * INPUT:                                                                  *\n *    input         key value to process                                 \t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    1 = caller should redraw the message list (no need to complete     \t*\n *        refresh, though)                                                 *\n *    2 = caller should completely refresh the display.                  \t*\n *    3 = caller should send the edit message.                           \t*\n *        (sets 'input' to 0 if it processes it.)                          *\n *\t\t4 = caller should send the Overflow buffer\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/05/1995 BRR : Created.                                             *\n *=========================================================================*/\nint MessageListClass::Input(KeyNumType &input)\n{\n\tKeyASCIIType ascii;\n\tint retcode = 0;\n\tint numchars;\n\n\t//------------------------------------------------------------------------\n\t//\tDo nothing if nothing to do.\n\t//------------------------------------------------------------------------\n\tif (input == KN_NONE) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tLeave mouse events alone.\n\t//------------------------------------------------------------------------\n\tif ( (input & (~KN_RLSE_BIT))==KN_LMOUSE ||\n\t\t(input & (~KN_RLSE_BIT))==KN_RMOUSE) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tIf we're in 'edit mode', handle keys\n\t//------------------------------------------------------------------------\n\tif (IsEdit) {\n\n\n\t\tascii = (KeyASCIIType)(Keyboard->To_ASCII(input) & 0x00ff);\n\n#ifdef WIN32\n\t\t/*\n\t\t** Allow numeric keypad presses to map to ascii numbers\n\t\t*/\n\t\tif ((input & WWKEY_VK_BIT) && ascii >='0' && ascii <= '9') {\n\n\t\t\tinput = (KeyNumType)(input & ~WWKEY_VK_BIT);\n\n\t\t} else {\n\t\t\t/*\n\t\t\t** Filter out all special keys except return, escape and backspace\n\t\t\t*/\n\t\t\tif ((!(input & WWKEY_VK_BIT) && !(input & KN_BUTTON)\n\t\t\t\t\t&& ascii >= ' ' && ascii <= 127)\n\t\t\t\t|| (input & 0xff)== (KN_RETURN & 0xff)\n\t\t\t\t|| (input & 0xff)== (KN_BACKSPACE & 0xff)\n\t\t\t\t|| (input & 0xff)== (KN_ESC & 0xff) ) {\n\n\t\t\t\t//ascii = (KeyASCIIType)(Keyboard->To_ASCII(input));\n\t\t\t} else {\n\t\t\t\tinput = KN_NONE;\n\t\t\t\treturn (0);\n\t\t\t}\n\t\t}\n#endif\t//WIN32\n\n\n\n\t\tswitch (ascii) {\n\t\t\t//..................................................................\n\t\t\t//\tESC = abort message\n\t\t\t//..................................................................\n\t\t\tcase KA_ESC & 0xff:\n\t\t\t\tRemove_Edit();\n\t\t\t\tretcode = 2;\n\t\t\t\tinput = KN_NONE;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tRETURN = send the message.\n\t\t\t// Add a space to the end, in case another message gets concatenated\n\t\t\t// onto this one after we send it; then, they won't be mushed\n\t\t\t// together.\n\t\t\t//..................................................................\n\t\t\tcase KA_RETURN & 0xff:\n\t\t\t\tif (EditCurPos == EditInitPos) {\n\t\t\t\t\tretcode = 0;\n\t\t\t\t\tinput = KN_NONE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif ( (EditCurPos - EditInitPos) < (MaxChars - 1) ) {\n\t\t\t\t\tEditBuf[EditCurPos] = ' ';\n\t\t\t\t\tEditCurPos++;\n\t\t\t\t\tEditBuf[EditCurPos] = 0;\n\t\t\t\t}\n\t\t\t\tRemove_Edit();\n\t\t\t\tretcode = 3;\n\t\t\t\tinput = KN_NONE;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tBACKSPACE = remove a character\n\t\t\t//..................................................................\n\t\t\tcase KA_BACKSPACE & 0xff:\n\t\t\t\tif (EditCurPos > EditInitPos) {\n\t\t\t\t\tEditCurPos--;\n\t\t\t\t\tEditBuf[EditCurPos] = 0;\n\t\t\t\t\tretcode = 2;\n\t\t\t\t}\n\t\t\t\tinput = KN_NONE;\n\t\t\t\tEditLabel->Set_Focus();\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t// default: add a character.  Reserve the last buffer position for\n\t\t\t// null.  (EditCurPos - EditInitPos) is the buffer index # of the\n\t\t\t// next character, after the \"To:\" prefix.\n\t\t\t//..................................................................\n\t\t\tdefault:\n\t\t\t\tEditLabel->Set_Focus();\n\t\t\t\tbool overflowed = false;\n\t\t\t\tif (ascii >= ' ' && ascii <= 127) {\n\t\t\t\t\tif ( (EditCurPos - EditInitPos) < (MaxChars - 1) ) {\n\n\t\t\t\t\t\tEditBuf[EditCurPos] = ascii;\n\t\t\t\t\t\tEditCurPos++;\n\t\t\t\t\t\tEditBuf[EditCurPos] = 0;\n\t\t\t\t\t\tretcode = 1;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Verify that the additional character would not overrun the on screen edit box.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tFancy_Text_Print(TXT_NONE, 0, 0, EditLabel->Color, TBLACK, EditLabel->Style);\n\t\t\t\t\t\tint width = String_Pixel_Width(EditBuf);\n\t\t\t\t\t\tif (width >= Width-10) {\n\t\t\t\t\t\t\toverflowed = true;\n\t\t\t\t\t\t\tEditCurPos--;\n\t\t\t\t\t\t\tEditBuf[EditCurPos] = 0;\n\t\t\t\t\t\t\tretcode = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// If there's no room in the buffer, and overflow is enabled,\n\t\t\t\t\t// trim the extra characters off (from right to left, to\n\t\t\t\t\t// remove the max possible characters), and then add the new\n\t\t\t\t\t// character in.\n\t\t\t\t\t//............................................................\n\t\t\t\t\t\toverflowed = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (/*BGEnableOverflow &&*/ overflowed) {\n\t\t\t\t\t\tnumchars = Trim_Message (OverflowBuf, EditBuf + EditInitPos,\n\t\t\t\t\t\t\tOverflowStart,OverflowEnd, 1);\n\t\t\t\t\t\tEditCurPos -= numchars;\n\t\t\t\t\t\tEditBuf[EditCurPos] = ascii;\n\t\t\t\t\t\tEditCurPos++;\n\t\t\t\t\t\tEditBuf[EditCurPos] = 0;\n\t\t\t\t\t\tretcode = 4;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tinput = KN_NONE;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn(retcode);\n\n}\t// end of Input\n\n\n/***************************************************************************\n * MessageListClass::Draw -- draws messages                                *\n *                                                                         *\n * INPUT:                                                                  *\n *    none                                                               \t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    none.                                                              \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/22/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid MessageListClass::Draw(void)\n{\n\tchar txt[2] = {0,0};\n\n\tif (IsEdit) {\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tHide_Mouse();\n\t\t}\n\t\tEditLabel->Draw_Me(true);\n\n\t\tif (CursorChar && (EditCurPos - EditInitPos) < (MaxChars - 1) && EditLabel->Has_Focus()) {\n\t\t\ttxt[0] = CursorChar;\n\t\t\tFancy_Text_Print(txt,\n\t\t\t\tEditLabel->X + String_Pixel_Width(EditLabel->Text),\n\t\t\t\tEditLabel->Y,\n\t\t\t\tEditLabel->Color,\n\t\t\t\tTBLACK,\n\t\t\t\tEditLabel->Style);\n\t\t}\n\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tShow_Mouse();\n\t\t}\n\t}\n\tif (MessageList) {\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tHide_Mouse();\n\t\t}\n\t\tMessageList->Draw_All();\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tShow_Mouse();\n\t\t}\n\t}\n\n}\t// end of Draw\n\n\n/***************************************************************************\n * MessageListClass::Num_Messages -- returns # messages in the list        *\n *                                                                         *\n * INPUT:                                                                  *\n *    none.                                                              \t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    # of messages, including the edit field if it's above the messages\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/26/1995 BRR : Created.                                             *\n *=========================================================================*/\nint MessageListClass::Num_Messages(void)\n{\n\tGadgetClass * gadg;\n\tint num;\n\n\tnum = 0;\n\n\tif (MessageList) {\n\t\tgadg = MessageList;\n\t\twhile (gadg) {\n\t\t\tnum++;\n\t\t\tgadg = gadg->Get_Next();\n\t\t}\n\t}\n\n\tif (IsEdit && AdjustEdit) {\n\t\tnum++;\n\t}\n\n\treturn (num);\n\n}\t// end of Num_Messages\n\n\n/***************************************************************************\n * MessageListClass::Set_Width -- sets allowable width of messages         *\n *                                                                         *\n * INPUT:                                                                  *\n *    width      pixel width                                             \t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    none.                                                              \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/26/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid MessageListClass::Set_Width(int width)\n{\n\tGadgetClass * gadg;\n\n\tif (MessageList) {\n\t\tgadg = MessageList;\n\t\twhile (gadg) {\n\t\t\t((TextLabelClass *)gadg)->PixWidth = width;\n\t\t\tgadg = gadg->Get_Next();\n\t\t}\n\t}\n\n\tif (IsEdit) {\n\t\tEditLabel->PixWidth = width;\n\t}\n\n}\t// end of Set_Width\n\n\n/***************************************************************************\n * MessageListClass::Trim_Message -- trims chars off start of message      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tdest\t\t\t\tbuffer to store removed characters in; NULL = none\t\t*\n *\t\tsrc\t\t\t\ttext buffer to trim\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tmin_chars\t\tmin # chars that must be trimmed off\t\t\t\t\t\t*\n *\t\tmax_chars\t\tmax # chars allowed to trim\t\t\t\t\t\t\t\t\t*\n *\t\tscandir\t\t\t0 = left-to-right, 1 = right-to-left\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# characters removed\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/07/1995 BRR : Created.                                             *\n *=========================================================================*/\nint MessageListClass::Trim_Message(char * dest, char * src, int min_chars,\n\tint max_chars, int scandir)\n{\n\tint i;\n\tint len;\n\tint found;\n\n\t//------------------------------------------------------------------------\n\t// validate parameters\n\t//------------------------------------------------------------------------\n\tif (min_chars <= 0) {\n\t\treturn(0);\n\t}\n\n\tlen = strlen (src);\n\tif (max_chars > len) {\n\t\tmax_chars = len;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// find 1st available white space; if there is none, just trim off\n\t// 'min_chars' characters.  'i' will be the number of chars to trim.\n\t// The chars removed will include the white space.\n\t//------------------------------------------------------------------------\n\tfound = 0;\n\t//........................................................................\n\t// scan from left to right\n\t//........................................................................\n\tif (scandir == 0) {\n\t\tfor (i = min_chars; i <= max_chars; i++) {\n\t\t\tif (isspace(src[i - 1])) {\n\t\t\t\tfound = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t//........................................................................\n\t// scan from right to left\n\t//........................................................................\n\telse {\n\t\tfor (i = max_chars; i >= min_chars; i--) {\n\t\t\tif (isspace(src[i - 1])) {\n\t\t\t\tfound = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t//........................................................................\n\t// If no whitespace was found, just set 'i' to the min # characters\n\t//........................................................................\n\tif (!found) {\n\t\ti = min_chars;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Save trimmed characters in the dest buffer, if there is one\n\t//------------------------------------------------------------------------\n\tif (dest) {\n\t\tmemcpy (dest, src, i);\n\t\tdest[i] ='\\0';\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Shift characters over in the source buffer\n\t//------------------------------------------------------------------------\n\tmemmove (src, src + i, len - i + 1);\n\n\treturn (i);\n\n}\t// end of Trim_Message\n\n\n/***************************************************************************\n * MessageListClass::Compute_Y -- recomputes y-coord for all messages      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/07/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid MessageListClass::Compute_Y(void)\n{\n\tGadgetClass * gadg;\n\tint y;\n\n\t//------------------------------------------------------------------------\n\t// If the editable message is attached to the message list, 'AdjustEdit'\n\t// will be set; so, adjust all y-values downward one line.  Otherwise,\n\t// the editable message has its own screen coordinates.\n\t//------------------------------------------------------------------------\n\tif (IsEdit && AdjustEdit) {\n\t\ty = MessageY + Height;\n\t}\n\telse {\n\t\ty = MessageY;\n\t}\n\tif (MessageList) {\n\t\tgadg = MessageList;\n\t\twhile (gadg) {\n\t\t\tgadg->Y = y;\n\t\t\tgadg = gadg->Get_Next();\n\t\t\ty += Height;\n\t\t}\n\t}\n\n}\t// end of Compute_Y\n\n\n/*************************** end of msglist.cpp ****************************/\n"
  },
  {
    "path": "CODE/MSGLIST.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/MSGLIST.H 2     3/04/97 2:53p Joe_bostic $ */\n/***************************************************************************\n ***              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               ***\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : MSGLIST.H                                *\n *                                                                         *\n *                   Programmer : Bill R. Randolph                         *\n *                                                                         *\n *                   Start Date : 05/22/95                                 *\n *                                                                         *\n *                  Last Update : May 22, 1995 [BRR]                       *\n *                                                                         *\n * Initializing:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Call Init(), giving it the coords of the upper-left corner to display\t*\n *   the messages, the coordinates to display the editable message, max # \t*\n *   messages allowed, max # chars per message, and the pixel height of \t*\n *   the font.  MaxChars should be less than or equal to the define \t\t\t*\n *   MAX_MESSAGE_LENGTH.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tDisplaying a message:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Call Add_Message(); the buffer you pass in is copied into a static\t\t*\n *   buffer in this class.  Each message is given a timeout; after this\t\t*\n *   time, the message is removed from the displayed list.\t\t\t\t\t\t*\n *   Each message also has a 2-byte ID, which can be used to identify the\n *   sender.\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Editing a message:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Call Add_Edit(), giving it the color & style to print in.  An \t\t\t*\n *   optional \"To xxx\" prefix is allowed.  The edit message can appear in \t*\n *   the message list itself (it's placed first), or at a separate screen \t*\n *   location, depending on the values passed to Init().\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tUpdating messages:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   The Input() routine passes new keys to the editable message; this \t\t*\n *   routine's return code tells the app whether to redraw the messages,\t*\n *   and whether to send it the edit message.  As the user types \t\t\t\t*\n *   characters into the edit field, if he overflows the max storage\t\t\t*\n *   for the edit field, the field is parsed & the first few words \t\t\t*\n *   removed; these words are put into the Overflow buffer, and the app\t\t*\n *   is told so; the app should send this buffer across to the destination.*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - MessageList is a gadget list of all current messages\t\t\t\t\t\t*\n * - MessageX & Y are the upper left corner of the 1st message\t\t\t\t\t*\n * - MaxMessages is the max # of messages allowed, including the editable \t*\n *   message; 0 = no limit.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - MaxChars is the max # of chars allowed per message\t\t\t\t\t\t\t*\n * - Height is the pixel height of a single line\t\t\t\t\t\t\t\t\t*\n * - EditLabel points to the textmessage gadget for the current editable\t*\n *   field.  EditBuf points to the char buffer being edited.  EditInitPos\t*\n *   & EditCurPos define buffer index positions.\t\t\t\t\t\t\t\t\t*\n * - EditSendAddress is the IPX Address to send the message to when RETURN\t*\n *   is pressed.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * The low word in the UserData field in the TextLabelClass tells what the *\n * timeout for each message is (0 = none); the high byte of the UserData\t*\n * field is used for the text message ID.\t\t\t\t\t\t\t\t\t\t\t\t*\n * When a message's timeout expires, it's deleted.  When a new message\t\t*\n * is added, the top message is deleted if MPlayerMaxMessages is exceeded.\t*\n *                                                                         *\n * The Edit-able message is never deleted until ESC or RETURN is pressed.\t*\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MSGLIST_H\n#define MSGLIST_H\n\n//***************************************************************************\n// Defines\n//***************************************************************************\n//---------------------------------------------------------------------------\n//\tMax length of inter-player message buffers.  Messages.Init() should specify\n// a value <= this.  For editing messages, the \"to\" field length is added to\n// this length to generate the entire editable message length.  For displayed\n// messages, a \"From\" prefix length should be added to this value to generate\n// the entire max displayable message length.\n//---------------------------------------------------------------------------\n#define\tMAX_MESSAGE_LENGTH\t\t120\n\n//---------------------------------------------------------------------------\n// Max # of allowed messages at one time\n//---------------------------------------------------------------------------\n#define\tMAX_NUM_MESSAGES\t\t\t14\n\n//***************************************************************************\n// Forward declarations\n//***************************************************************************\nclass TextLabelClass;\n\n//***************************************************************************\n// Class declaration\n//***************************************************************************\nclass MessageListClass {\n\tpublic:\n\t\t//.....................................................................\n\t\t// Constructor/Destructor\n\t\t//.....................................................................\n\t\tMessageListClass (void);\n\t\t~MessageListClass ();\n\n\t\t//.....................................................................\n\t\t// Initialization\n\t\t//.....................................................................\n\t\tvoid Reset(void);\n\t\tvoid Init (int x, int y, int max_msg, int maxchars, int height,\n\t\t\tint edit_x, int edit_y, int overflow_on, int over_start,\n\t\t\tint over_end, int width = 640);\n\t\tTextLabelClass * Add_Message (char const * name, int id, char const * txt,\n\t\t\tPlayerColorType color, TextPrintType style, int timeout);\n\t\tint Concat_Message (char const * name, int id, char const * txt, int timeout);\n\n\t\t//.....................................................................\n\t\t// Message access utility routines\n\t\t//.....................................................................\n\t\tchar * Get_Message (int id);\n\t\tTextLabelClass * Get_Label (int id);\n\n\t\t//.....................................................................\n\t\t// Message-editing support routines\n\t\t//.....................................................................\n\t\tTextLabelClass * Add_Edit(PlayerColorType color, TextPrintType style,\n\t\t\tchar *to, char cursor = 0, int width = 640);\n\t\tvoid Remove_Edit (void);\n\t\tchar * Get_Edit_Buf (void);\n\t\tchar * Get_Overflow_Buf (void) {return (OverflowBuf);}\n\t\tvoid Clear_Overflow_Buf (void) {OverflowBuf[0] = 0;}\n\t\tint Is_Edit(void) {return (IsEdit);}\n\t\tvoid Set_Edit_Color(PlayerColorType color);\n\n\t\t//.....................................................................\n\t\t// Maintenance routines\n\t\t//.....................................................................\n\t\tint Manage (void);\n\t\tint Input (KeyNumType &input);\n\t\tvoid Draw(void);\n\t\tint Num_Messages(void);\n\t\tvoid Set_Width(int width);\n\t\tvoid Set_Edit_Focus(void);\n\t\tbool Has_Edit_Focus(void);\n\n\tprivate:\n\n\t\t//.....................................................................\n\t\t// Message parsing\n\t\t//.....................................................................\n\t\tint Trim_Message(char *dest, char *src, int min_chars, int max_chars,\n\t\t\tint scandir);\n\n\t\t//.....................................................................\n\t\t// Compute the y-coord of the message list\n\t\t//.....................................................................\n\t\tvoid Compute_Y(void);\n\n\t\t//.....................................................................\n\t\t// Private Data\n\t\t//.....................................................................\n\t\tTextLabelClass * MessageList;\t\t\t\t// list of messages\n\t\tint MessageX;\t\t\t\t\t\t\t\t\t// x-coord of upper-left\n\t\tint MessageY;\t\t\t\t\t\t\t\t\t// y-coord of upper-left\n\t\tint MaxMessages;\t\t\t\t\t\t\t\t// max messages allowed\n\t\tint MaxChars;\t\t\t\t\t\t\t\t\t// max allowed chars per message\n\t\tint Height;\t\t\t\t\t\t\t\t\t\t// height in pixels\n\n\t\t//.....................................................................\n\t\t// Data for the edit field: the edit field will either appear at\n\t\t// exact coordinates specified by the application, or it will appear\n\t\t// vertically above the other messages.\n\t\t//.....................................................................\n\t\tunsigned EnableOverflow\t: 1;\t\t\t\t\t// 1 = enable overflow feature\n\t\tunsigned IsEdit\t\t\t\t: 1;\t\t\t\t\t// 1 = there's an edit field\n\t\tunsigned AdjustEdit\t\t\t: 1;\t\t\t\t\t// 1 = edit field appears over msgs\n\t\tint EditX;\t\t\t\t\t\t\t\t\t\t// x-coord of edit field\n\t\tint EditY;\t\t\t\t\t\t\t\t\t\t// y-coord of edit field\n\t\tTextLabelClass *EditLabel;\t\t\t\t\t// ptr to current edit label\n\t\tchar EditBuf[MAX_MESSAGE_LENGTH + 30];\t// buffer for editable message\n\t\tchar OverflowBuf[MAX_MESSAGE_LENGTH + 30];\t// overflow area\n\t\tint EditCurPos;\t\t\t\t\t\t\t\t// current edit position\n\t\tint EditInitPos;\t\t\t\t\t\t\t\t// initial edit position\n\t\tchar CursorChar;\t\t\t\t\t\t\t\t// character to use a cursor\n\t\tint OverflowStart;\t\t\t\t\t\t\t// 1st index for overflow trimming\n\t\tint OverflowEnd;\t\t\t\t\t\t\t\t// last index for overflow trimming\n\t\tint Width;\t\t\t\t\t\t\t\t\t\t// Maximum width in pixels of editable string\n\n\t\t//.....................................................................\n\t\t// Buffers provided for messages.  They must be long enough for\n\t\t// both the message, and for the \"To\" prefix on edited messages, or\n\t\t// the \"Name:\" prefix on received messages.\n\t\t//.....................................................................\n\t\tchar MessageBuffers[MAX_NUM_MESSAGES][MAX_MESSAGE_LENGTH + 30];\n\t\tchar BufferAvail[MAX_NUM_MESSAGES];\n};\n\n#endif\n/**************************** end of msglist.h *****************************/\n\n"
  },
  {
    "path": "CODE/NETDLG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/NETDLG.CPP 13    10/13/97 2:20p Steve_t $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                         \t\t\t\t\t\t  *\n *                 Project Name : Command & Conquer                        \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                    File Name : NETDLG.CPP                               \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                   Programmer : Bill Randolph                            \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                   Start Date : January 23, 1995                         \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                  Last Update : December 12, 1995 [BRR]                  \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *---------------------------------------------------------------------------------------------*\n *                                                                         \t\t\t\t\t\t  *\n * These routines establish & maintain peer-to-peer connections between this system\t\t\t\t  *\n * and all others in the game.  Each system finds out the IPX address of the others,\t\t\t  *\n * and forms a direct connection (IPXConnectionClass) to that system.  Systems are\t\t\t\t  *\n * found out via broadcast queries.  Every system broadcasts its queries, and every\t\t\t\t  *\n * system replies to queries it receives.  At the point when the game owner signals\t\t\t\t  *\n * 'OK', every system must know about all the other systems in the game.\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * How Bridges are handled:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * Currently, bridges are handled by specifying the destination IPX address of the\t\t\t\t  *\n * \"server\" (game owner's system) on the command-line.  This address is used to\t\t\t\t\t  *\n * derive a broadcast address to that destination network, and this system's queries\t\t\t  *\n * are broadcast over its network & the server's network; replies to the queries come\t\t\t  *\n * with each system's IPX address attached, so once we have the address, we can form\t\t\t  *\n * a connection with any system on the bridged net.\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * The flaw in this plan is that we can only cross one bridge.  If there are 3 nets\t\t\t\t  *\n * bridged (A, B, & C), and the server is on net B, and we're on net A, our broadcasts\t\t\t  *\n * will reach nets A & B, but not C.  The way to circumvent this (if it becomes a problem)\t  *\n * would be to have the server tell us what other systems are in its game, not each\t\t\t\t  *\n * individual player's system.  Thus, each system would find out about all the other systems\t  *\n * by interacting with the game's owner system (this would be more involved than what\t\t\t  *\n * I'm doing here).\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * Here's a list of all the different packets sent over the Global Channel:\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\tNET_QUERY_GAME\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\t(no other data)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\tNET_ANSWER_GAME\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tName:\t\t\t\t\tgame owner's name\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tGameInfo:\t\t\tgame's version & open state\t\t\t\t\t\t\t\t\t  *\n *\tNET_QUERY_PLAYER\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tName:\t\t\t\t\tname of game we want players to respond for\t\t\t\t  *\n *\tNET_ANSWER_PLAYER\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tName:\t\t\t\t\tplayer's name\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tPlayerInfo:\t\t\tinfo about player\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * NET_CHAT_ANNOUNCE\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tChat:\t\t\t\t\tunique id of the local node, so I can tell\t\t\t\t  *\n *\t\t\t\t\t\t\t\t\t\t\t\t\tif this chat announcement is from myself\t\t\t\t\t  *\n *\tNET_QUERY_JOIN\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tName:\t\t\t\t\tname of player wanting to join\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tPlayerInfo:\t\t\tplayer's requested house, color, & version range\t\t  *\n *\tNET_CONFIRM_JOIN\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tPlayerInfo:\t\t\tapproves player's house & color\t\t\t\t\t\t\t\t  *\n *\tNET_REJECT_JOIN\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tReject.Why:\t\t\ttells why we got rejected\t\t\t\t\t\t\t\t\t\t  *\n *\tNET_GAME_OPTIONS\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tScenarioInfo:\t\tinfo about scenario\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\tNET_SIGN_OFF\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tName:\t\t\t\t\tname of player signing off\t\t\t\t\t\t\t\t\t\t  *\n *\tNET_PING\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\t(no other data)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\tNET_GO\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tDelay:            value of one-way response time, in frames               *\n * \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                              \t\t\t\t\t\t  *\n *   Init_Network -- initializes network stuff                             \t\t\t\t\t\t  *\n *   Shutdown_Network -- shuts down network stuff                          \t\t\t\t\t\t  *\n *   Process_Global_Packet -- responds to remote queries                   \t\t\t\t\t\t  *\n *   Destroy_Connection -- destroys the given connection\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *   Remote_Connect -- handles connecting this user to others              \t\t\t\t\t\t  *\n *   Net_Join_Dialog -- lets user join an existing game, or start a new one\t\t\t\t\t\t  *\n *   Request_To_Join -- Sends a JOIN request packet to game owner           \t \t\t\t\t\t  *\n *   Unjoin_Game -- Cancels joining a game                                                     *\n *   Send_Join_Queries -- sends queries for the Join Dialog\t\t\t\t\t\t\t\t\t\t\t\t  *\n *   Get_Join_Responses -- sends queries for the Join Dialog\t\t\t\t\t\t\t\t\t\t\t  *\n *   Net_New_Dialog -- lets user start a new game\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *   Get_NewGame_Responses -- processes packets for New Game dialog                            *\n *   Compute_Name_CRC -- computes CRC from char string                                         *\n *   Net_Reconnect_Dialog -- Draws/updates the network reconnect dialog                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n//\tWarning - Most disgusting cpp file of all time. ajw\n\n#include \"function.h\"\n#ifdef WIN32\n#ifdef WINSOCK_IPX\n#include\t\"WSProto.h\"\n#else\t//WINSOCK_IPX\n#include \"tcpip.h\"\n#endif\t//WINSOCK_IPX\n#include \"ccdde.h\"\n#else\t//WIN32\n#include \"fakesock.h\"\n#endif\t//WIN32\n\n#include <time.h>\n#include <dos.h>\n\n#include \"WolDebug.h\"\n\n#define SHOW_MONO\t\t0\n//#define OLDWAY\t\t\t1\n\n#ifdef FRENCH\n#define TXT_HACKHACK  \"Connexion En Cours...\"\n#endif\n#if defined(ENGLISH) || defined(GERMAN)\n#define TXT_HACKHACK  Text_String(TXT_CONNECTING)\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nbool Is_Mission_126x126 (char *file_name);\nbool Is_Mission_Aftermath (char *file_name);\nbool Is_Mission_Counterstrike (char *file_name);\nbool bSpecialAftermathScenario( const char* szScenarioDescription );\n#endif\n\n#ifdef FIXIT_VERSION_3\nbool Force_Scenario_Available( const char* szName );\n#endif\n#ifdef WOLAPI_INTEGRATION\n#include \"WolStrng.h\"\n#include \"WolapiOb.h\"\nextern WolapiObject* pWolapi;\n#endif\n\n//---------------------------------------------------------------------------\n//\tThe possible states of the join-game dialog\n//---------------------------------------------------------------------------\ntypedef enum {\n\tJOIN_REJECTED = -1,\t\t// we've been rejected\n\tJOIN_NOTHING,\t\t\t\t// we're not trying to join a game\n\tJOIN_WAIT_CONFIRM,\t\t// we're asking to join, & waiting for confirmation\n\tJOIN_CONFIRMED,\t\t\t// we've been confirmed\n\tJOIN_GAME_START,\t\t\t// the game we've joined is starting\n\tJOIN_GAME_START_LOAD,\t// the game we've joined is starting; load saved game\n} JoinStateType;\n\n//---------------------------------------------------------------------------\n//\tThe possible return codes from Get_Join_Responses()\n//---------------------------------------------------------------------------\ntypedef enum {\n\tEV_NONE,\t\t\t\t\t\t\t// nothing happened\n\tEV_STATE_CHANGE,\t\t\t\t// Join dialog is in a new state\n\tEV_NEW_GAME,\t\t\t\t\t// a new game formed, or is now open\n\tEV_NEW_PLAYER,\t\t\t\t\t// a new player was detected\n\tEV_PLAYER_SIGNOFF,\t\t\t// a player has signed off\n\tEV_GAME_SIGNOFF,\t\t\t\t// a gamed owner has signed off\n\tEV_GAME_OPTIONS,\t\t\t\t// a game options packet was received\n\tEV_MESSAGE,\t\t\t\t\t\t// a message was received\n} JoinEventType;\n\n\n//---------------------------------------------------------------------------\n//\tThe possible reasons we're rejected from joining a game\n//---------------------------------------------------------------------------\ntypedef enum {\n\tREJECT_DUPLICATE_NAME,\t\t// player's name is a duplicate\n\tREJECT_GAME_FULL,\t\t\t\t// game is full\n\tREJECT_VERSION_TOO_OLD,\t\t// joiner's version is too old\n\tREJECT_VERSION_TOO_NEW,\t\t// joiner's version is too new\n\tREJECT_BY_OWNER,\t\t\t\t// game owner clicked \"reject\"\n\tREJECT_DISBANDED,\t\t\t\t// game was disbanded\n\tREJECT_MISMATCH,\t\t\t\t// \"rules.ini\" file mismatch.\n} RejectType;\n\n#ifdef ENGLISH\nchar const *EngMisStr[] = {\n\t\"Coastal Influence (Med)\",\n\t\"Middle Mayhem (Sm)\",\n\t\"Equal Opportunity (Sm)\",\n\t\"Marooned II (Med)\",\n\t\"Keep off the Grass (Sm)\",\n\t\"Isle of Fury (Lg)\",\n\t\"Ivory Wastelands (Sm)\",\n\t\"Shallow Grave (Med)\",\n\t\"North By Northwest (Lg)\",\n\t\"First Come, First Serve (Sm)\",\n\t\"Island Hoppers (Sm)\",\n\t\"Raraku (Lg)\",\n\t\"Central Conflict (Lg)\",\n\t\"Combat Alley (Med)\",\n\t\"Island Wars (Lg)\",\n\t\"Desolation (Lg)\",\n\t\"No Escape (Med)\",\n\t\"No Man's Land (Med)\",\n\t\"Normandy (Med)\",\n\t\"Pond Skirmish (Med)\",\n\t\"Ridge War (Med)\",\n\t\"A Path Beyond (Lg)\",\n\t\"Dugout Isle (Med)\",\n\t\"Treasure Isle (Med)\",\n\n\t\"Africa (Lg)\",\n\t\"Alaska Anarchy (Lg)\",\n\t\"All that Glitters... (Lg)\",\n\t\"Apre's Peace (Lg)\",\n\t\"Antartica (Lg)\",\n\t\"Armourgarden (Lg)\",\n\t\"Austraila (Med)\",\n\t\"Barrier to Entry (Lg)\",\n\t\"Bavarian Blast (Med)\",\n\t\"Be Shore (Med)\",\n\t\"Bearing Straits (Med)\",\n\t\"Blow Holes (Lg)\",\n\t\"Bonsai (Sm)\",\n\t\"Brother Stalin (Lg)\",\n\t\"Bullseye (Lg)\",\n\t\"C&C (Med)\",\n\t\"Camos Canyon (Med)\",\n\t\"Camos Coves (Lg)\",\n\t\"Camos Cross (Lg)\",\n\t\"Camos Crossing (Sm)\",\n\t\"Central Arena (Lg)\",\n\t\"Canyon River (Med)\",\n\t\"Crossroads (Sm)\",\n\t\"Czech Mate (Lg)\",\n\t\"Dday (Med)\",\n\t\"Disaster Central (Lg)\",\n\t\"Docklands (Med)\",\n\t\"East Coast (Med)\",\n\t\"Eastern Seaboard (Lg)\",\n\t\"Finger Lake (Lg)\",\n\t\"Fjords (Med)\",\n\t\"Floodlands (Lg)\",\n\t\"Forest under fire (Lg)\",\n\t\"Four Corners (Lg)\",\n\t\"Frostbit Fjords (Lg)\",\n\t\"Glenboig (Sm)\",\n\t\"Hell Frozen Over (Lg)\",\n\t\"India (Lg)\",\n\t\"Indirect Fire (Lg)\",\n\t\"Island Wars II (Lg)\",\n\t\"Italy (Lg)\",\n\t\"Kabalo (Lg)\",\n\t\"King of the Hills (Lg)\",\n\t\"Lake Divide (Med)\",\n\t\"Lakelands (Lg)\",\n\t\"Land Ladder (Lg)\",\n\t\"Lotsa Lakes (Lg)\",\n\t\"Lunar Battlefield (Lg Special)\",\n\t\"Malibu Fields (Med)\",\n\t\"Marshland (Med)\",\n\t\"MyLai Delta (Med)\",\n\t\"Natural Harbor (Med)\",\n\t\"No Way Out (Lg)\",\n\t\"Normandy Landing (Lg)\",\n\t\"Ore Wars (Med)\",\n\t\"Oz (Lg)\",\n\t\"Pilgrim Fathers II (Lg)\",\n\t\"Pip's Ice Tea (Med)\",\n\t\"Polar Panic (Lg)\",\n\t\"Ponds (Med)\",\n\t\"Putney (Lg)\",\n\t\"Return to Zion (Lg)\",\n\t\"Ring of Land (Lg)\",\n\t\"River Basin (Lg)\",\n\t\"River Delta (Med)\",\n\t\"River Islands (Med)\",\n\t\"River Maze (Sm)\",\n\t\"Rivers (Sm)\",\n\t\"Run the Gauntlet (Med)\",\n\t\"Scappa Flow (Lg)\",\n\t\"Siberian Slaughter (Lg)\",\n\t\"Sleepy Valley (Sm)\",\n\t\"Snake River (Lg)\",\n\t\"Snow Wars (Lg)\",\n\t\"Snowball fight (Lg)\",\n\t\"Snowy Island (Lg)\",\n\t\"So Near So Far (Sm)\",\n\t\"South America (Lg)\",\n\t\"Spring Line (Lg)\",\n\t\"Star (Lg)\",\n\t\"Straighter & Narrower (Sm)\",\n\t\"TerrainSpotting (Sm)\",\n\t\"The Bay (Lg)\",\n\t\"The Garden (Lg)\",\n\t\"The Great Lakes (Med)\",\n\t\"The Ice Arena (Lg)\",\n\t\"The Lake District (Lg)\",\n\t\"The Linked lands (Lg)\",\n\t\"The Mississippi (Med)\",\n\t\"The Sticky Bit (Lg)\",\n\t\"The Valley (Med)\",\n\t\"The Woods Today (Lg)\",\n\t\"Things to Come (Lg)\",\n\t\"Tiger Core (Sm)\",\n\t\"To the Core (Sm)\",\n\t\"Tournament Hills (Lg)\",\n\t\"Tropical Storm (Med)\",\n\t\"Tundra Trouble (Lg)\",\n\t\"Uk (Med)\",\n\t\"Undiscovered Country (Sm)\",\n\t\"United States (Med)\",\n\t\"Volcano (Sm)\",\n\t\"Wastelands (Lg)\",\n\t\"Water Works (Sm)\",\n\t\"World Map (Med)\",\n\t\"Zambezi (Lg)\",\n\n\t\"A Pattern of Islands (Lg 8 players)\",\n\t\"Arena Valley Extreme (Mega 8 players)\",\n\t\"Around the Rim (Sm 4 players)\",\n\t\"Ashes to Ashes (Lg 6 players)\",\n\t\"Artic Wasteland (Mega 8 players)\",\n\t\"Badajoz (Med 4 players)\",\n\t\"Baptism of Fire (Lg 6 players)\",\n\t\"Big Fish, Small Pond (Lg 6 players)\",\n\t\"Blue Lakes (Lg 8 players)\",\n\t\"Booby Traps (Mega 8 players)\",\n\t\"Bridgehead (Lg 6 players)\",\n\t\"Butterfly Bay (Lg 6 players)\",\n\t\"Central Conflict Extreme (Mega 8 players)\",\n\t\"Circles of Death (Mega 8 players)\",\n\t\"Cold Front (Med 6 players)\",\n\t\"Cold Pass (Med 4 players)\",\n\t\"Combat Zones (Mega 8 players)\",\n\t\"Conflict Cove (Sm 4 players)\",\n\t\"Culloden Moor (Med 8 players)\",\n\t\"Damnation Alley (Mega 8 players)\",\n\t\"Death Valley (Mega 8 players)\",\n\t\"Deep Six (Mega 8 players)\",\n\t\"Destruction Derby (Mega 8 players)\",\n\t\"Diamonds Aren't Forever (Mega 8 players)\",\n\t\"Elysium (Sm 4 players)\",\n\t\"Equal Shares (Lg 4 players)\",\n\t\"Frost Bitten (Mega 8 players)\",\n\t\"Frozen Valley (Med 6 players)\",\n\t\"Gettysburg (Sm 4 players)\",\n\t\"Glacial Valley (Sm 4 players)\",\n\t\"Gold Coast (Med 6 players)\",\n\t\"Gold Rush (Lg 4 players)\",\n\t\"Habitat (Lg 4 players)\",\n\t\"Hades Frozen Over (Sm 4 players)\",\n\t\"Hamburger Hill (Mega 8 players)\",\n\t\"Hastings (Sm 4 players)\",\n\t\"Hell's Pass (Med 6 players)\",\n\t\"Holy Grounds (Mega 8 players)\",\n\t\"Ice Bergs (Med 6 players)\",\n\t\"Ice Station (Lg 6 players)\",\n\t\"Ice Queen (Lg 4 players)\",\n\t\"In the Sun (Med 6 players)\",\n\t\"Innocents? (Mega 8 players)\",\n\t\"Islands (Med 8 players)\",\n\t\"Island Plateau (Lg 4 players)\",\n\t\"Island Wars Extreme (Mega 8 players)\",\n\t\"Kananga (Med 6 players)\",\n\t\"King of the Hills Extreme (Mega 8 players)\",\n\t\"Lake Land (Lg 8 players)\",\n\t\"Land Locked (Lg 8 players)\",\n\t\"Lanes (Med 8 players)\",\n\t\"Leipzip (Sm 4 players)\",\n\t\"Meander (Lg 8 players)\",\n\t\"Mekong (Med 8 players)\",\n\t\"Middle Ground (Med 8 players)\",\n\t\"Naval Conquests (Mega 8 players)\",\n\t\"On your Marks (Med 4 players)\",\n\t\"Open Warfare (Mega 8 players)\",\n\t\"Ore Gardens (Lg 8 players)\",\n\t\"Potholes (Mega 8 players)\",\n\t\"Puddles (Med 4 players)\",\n\t\"Random Violence (Mega 8 players)\",\n\t\"Revenge (Med 8 players)\",\n\t\"Rias (Med 8 players)\",\n\t\"River Crossing (Sm 4 players)\",\n\t\"River Rampage (Mega 8 players)\",\n\t\"River Rapids (Lg 6 players)\",\n\t\"Rivers Wild (Mega 8 players)\",\n\t\"Rorkes Drift (Lg 4 players)\",\n\t\"Seaside (Med 4 players)\",\n\t\"Shades (Med 8 players)\",\n\t\"Smuggler's Cove (Lg 6 players)\",\n\t\"Snow Garden (Sm 2 players)\",\n\t\"Stalingrad (Sm 4 players)\",\n\t\"Sticks & Stones (Med 4 players)\",\n\t\"Strathearn Valley (Lg 6 players)\",\n\t\"Super Bridgehead (Mega 8 players)\",\n\t\"Super Mekong (Mega 8 players)\",\n\t\"Super Ore Gardens (Mega 8 players)\",\n\t\"Switch (Med 4 players)\",\n\t\"The Berg (Mega 8 players)\",\n\t\"The Boyne (Med 4 players)\",\n\t\"The Bulge (Sm 4 players)\",\n\t\"The Cauldron (Lg 6 players)\",\n\t\"The Finger (Lg 6 players)\",\n\t\"The Hills Have Eyes (Mega 8 players)\",\n\t\"The Keyes (Med 6 players)\",\n\t\"The Lakes (Med 8 players)\",\n\t\"The Neck (Med 6 players)\",\n\t\"The Web (Lg 6 players)\",\n\t\"To the Core (Lg 4 players)\",\n\t\"Trafalgar (Lg 4 players)\",\n\t\"Twin Rivers (Sm 4 players)\",\n\t\"Umtumbo Gorge (Lg 4 players)\",\n\t\"Watch Your Step Extreme (Mega 8 players)\",\n\t\"Waterfalls (Lg 8 players)\",\n\t\"Waterloo Revisited (Lg 6 players)\",\n\t\"Water Werks (Mega 8 players)\",\n\t\"Warlord's Lake (Sm 4 players)\",\n\t\"Zama (Sm 4 players)\",\n\n\tNULL\n};\n#endif\n\n#ifdef GERMAN\nchar const *EngMisStr[] = {\n\n\t\"A Path Beyond (Lg)\",\t\t\t\t\t\"Weg ins Jenseits (Gr)\",\n\t\"Central Conflict (Lg)\",\t\t\t\t\"Der zentrale Konflikt (Gr)\",\n\t\"Coastal Influence (Med)\",\t\t\t\t\"Sturm an der Kste (Mit)\",\n\t\"Combat Alley (Med)\",\t\t\t\t\t\"Boulevard der Schlachten (Mit)\",\n\t\"Desolation (Lg)\",\t\t\t\t\t\t\"Verwstung (Gr)\",\n\t\"Dugout Isle (Med)\",\t\t\t\t\t\t\"Buddelschiff (Mit)\",\n\t\"Equal Opportunity (Sm)\",\t\t\t\t\"Gleiche Chancen (Kl)\",\n\t\"First Come, First Serve (Sm)\",\t\t\"Wer zuerst kommt... (Kl)\",\n\t\"Island Hoppers (Sm)\",\t\t\t\t\t\"Inselspringen (Kl)\",\n\t\"Island Wars (Lg)\",\t\t\t\t\t\t\"Der Krieg der Eilande (Gr)\",\n\t\"Isle of Fury (Lg)\",\t\t\t\t\t\t\"Insel des Zorns (Gr)\",\n\t\"Ivory Wastelands (Sm)\",\t\t\t\t\"Elfenbeinwste (Kl)\",\n\t\"Keep off the Grass (Sm)\",\t\t\t\t\"Rasen betreten verboten (Kl)\",\n\t\"Marooned II (Med)\",\t\t\t\t\t\t\"Gestrandet (Mit)\",\n\t\"Middle Mayhem (Sm)\",\t\t\t\t\t\"Mittelsmann (Kl)\",\n\t\"No Escape (Med)\",\t\t\t\t\t\t\"Kein Entrinnen (Mit)\",\n\t\"No Man's Land (Med)\",\t\t\t\t\t\"Niemandsland (Mit)\",\n\t\"Normandy (Med)\",\t\t\t\t\t\t\t\"Normandie (Mit)\",\n\t\"North By Northwest (Lg)\",\t\t\t\t\"Nord auf Nordwest (Gr)\",\n\t\"Pond Skirmish (Med)\",\t\t\t\t\t\"Teichgeplnkel (Mit)\",\n\t\"Raraku (Lg)\",\t\t\t\t\t\t\t\t\"Raraku (Gr)\",\n\t\"Ridge War (Med)\",\t\t\t\t\t\t\"Das Tal der Cyborgs (Mit)\",\n\t\"Shallow Grave (Med)\",\t\t\t\t\t\"Ein enges Grab (Mit)\",\n\t\"Treasure Isle (Med)\",\t\t\t\t\t\"Die Schatzinsel (Mit)\",\n\n\t\"Africa (Lg)\",\t\t\t\t\t\t\t\t\"Afrika (Gr)\",\n\t\"Alaska Anarchy (Lg)\",\t\t\t\t\t\"Anarchie in Alaska (Gr)\",\n\t\"All that Glitters... (Lg)\",\t\t\t\"Alles was glnzt... (Gr)\",\n\t\"Apre's Peace (Lg)\",\t\t\t\t\t\t\"Apres Frieden (Gr)\",\n\t\"Antartica (Lg)\",\t\t\t\t\t\t\t\"Antarktica (Gr)\",\n\t\"Armourgarden (Lg)\",\t\t\t\t\t\t\"Garten der Panzer (Gr)\",\n\t\"Austraila (Med)\",\t\t\t\t\t\t\"Koalaland (Mit)\",\n\t\"Barrier to Entry (Lg)\",\t\t\t\t\"Zutritt verboten (Gr)\",\n\t\"Bavarian Blast (Med)\",\t\t\t\t\t\"Bayrische Blasmusik (Mit)\",\n\t\"Be Shore (Med)\",\t\t\t\t\t\t\t\"Strandlufer (Mit)\",\n\t\"Bearing Straits (Med)\",\t\t\t\t\"Die Heringstrasse (Mit)\",\n\t\"Blow Holes (Lg)\",\t\t\t\t\t\t\"Lcheriger Kse (Gr)\",\n\t\"Bonsai (Sm)\",\t\t\t\t\t\t\t\t\"Bonsai (Kl)\",\n\t\"Brother Stalin (Lg)\",\t\t\t\t\t\"Brderchen Stalin (Gr)\",\n\t\"Bullseye (Lg)\",\t\t\t\t\t\t\t\"Bullseye (Gr)\",\n\t\"C&C (Med)\",\t\t\t\t\t\t\t\t\"C&C (Mit)\",\n\t\"Camos Canyon (Med)\",\t\t\t\t\t\"Camos-Canyon (Mit)\",\n\t\"Camos Coves (Lg)\",\t\t\t\t\t\t\"Camos-Grotte (Gr)\",\n\t\"Camos Cross (Lg)\",\t\t\t\t\t\t\"Camos-Kreuz (Gr)\",\n\t\"Camos Crossing (Sm)\",\t\t\t\t\t\"Camos-Kreuzweg (Kl)\",\n\t\"Central Arena (Lg)\",\t\t\t\t\t\"Spielplatz des Teufels (Gr)\",\n\t\"Canyon River (Med)\",\t\t\t\t\t\"Canyonfluss (Mit)\",\n\t\"Crossroads (Sm)\",\t\t\t\t\t\t\"Kreuzung (Kl)\",\n\t\"Czech Mate (Lg)\",\t\t\t\t\t\t\"Tschechische Erffnung (Gr)\",\n\t\"Dday (Med)\",\t\t\t\t\t\t\t\t\"D-Day (Mit)\",\n\t\"Disaster Central (Lg)\",\t\t\t\t\"Endstation Schweinebucht (Gr)\",\n\t\"Docklands (Med)\",\t\t\t\t\t\t\"Docklands (Mit)\",\n\t\"East Coast (Med)\",\t\t\t\t\t\t\"Ostkste (Mit)\",\n\t\"Eastern Seaboard (Lg)\",\t\t\t\t\"Die Passage nach Osten (Gr)\",\n\t\"Finger Lake (Lg)\",\t\t\t\t\t\t\"Fingersee (Gr)\",\n\t\"Fjords (Med)\",\t\t\t\t\t\t\t\"Fjorde (Mit)\",\n\t\"Floodlands (Lg)\",\t\t\t\t\t\t\"Land unter! (Gr)\",\n\t\"Forest under fire (Lg)\",\t\t   \t\"Waldsterben im Feuer (Gr)\",\n\t\"Four Corners (Lg)\",\t\t\t\t\t\t\"Viereck (Gr)\",\n\t\"Frostbit Fjords (Lg)\",\t\t\t\t\t\"Frostbeulenfjord (Gr)\",\n\t\"Glenboig (Sm)\",\t\t\t\t\t\t\t\"Glenboig (Kl)\",\n\t\"Hell Frozen Over (Lg)\",\t\t\t\t\"Winter in der Hlle (Gr)\",\n\t\"India (Lg)\",\t\t\t\t\t\t\t\t\"Indien (Gr)\",\n\t\"Indirect Fire (Lg)\",\t\t\t\t\t\"Indirekter Beschuss (Gr)\",\n\t\"Island Wars II (Lg)\",\t\t\t\t\t\"Krieg der Inseln (Gr)\",\n\t\"Italy (Lg)\",\t\t\t\t\t\t\t\t\"Italien (Gr)\",\n\t\"Kabalo (Lg)\",\t\t\t\t\t\t\t\t\"Kabalo (Gr)\",\n\t\"King of the Hills (Lg)\",\t\t\t\t\"Knig des Maulwurfshgels (Gr)\",\n\t\"Lake Divide (Med)\",\t\t\t\t\t\t\"Wasserscheide (Mit)\",\n\t\"Lakelands (Lg)\",\t\t\t\t\t\t\t\"Seenplatte (Gr)\",\n\t\"Land Ladder (Lg)\",\t\t\t\t\t\t\"Das Leiterspiel (Gr)\",\n\t\"Lotsa Lakes (Lg)\",\t\t\t\t\t\t\"Mehr Seen (Gr)\",\n\t\"Lunar Battlefield (Lg Special)\",\t\"Schlachtfeld Mond (Gr Spezial)\",\n\t\"Malibu Fields (Med)\",\t\t\t\t\t\"Malibu (Mit)\",\n\t\"Marshland (Med)\",\t\t\t\t\t\t\"Schlammschlacht (Mit)\",\n\t\"MyLai Delta (Med)\",\t\t\t\t\t\t\"Das Delta von My Lai (Mit)\",\n\t\"Natural Harbor (Med)\",\t\t\t\t\t\"Natrlicher Hafen (Mit)\",\n\t\"No Way Out (Lg)\",\t\t\t\t\t\t\"Kein Entkommen (Gr)\",\n\t\"Normandy Landing (Lg)\",\t\t\t\t\"Landung in der Normandie (Gr)\",\n\t\"Ore Wars (Med)\",\t\t\t\t\t\t\t\"Die Erz-Kriege (Mit)\",\n\t\"Oz (Lg)\",\t\t\t\t\t\t\t\t\t\"Das Land Oz (Gr)\",\n\t\"Pilgrim Fathers II (Lg)\",\t\t\t\t\"Die Grndervter (Gr)\",\n\t\"Pip's Ice Tea (Med)\",\t\t\t\t\t\"Pips Eistee (Mit)\",\n\t\"Polar Panic (Lg)\",\t\t\t\t\t\t\"Panik am Pol (Gr)\",\n\t\"Ponds (Med)\",\t\t\t\t\t\t\t\t\"Tmpelspringer (Mit)\",\n\t\"Putney (Lg)\",\t\t\t\t\t\t\t\t\"Putney (Gr)\",\n\t\"Return to Zion (Lg)\",\t\t\t\t\t\"Rckkehr nach Zion (Gr)\",\n\t\"Ring of Land (Lg)\",\t\t\t\t\t\t\"Der Landring (Gr)\",\n\t\"River Basin (Lg)\",\t\t\t\t\t\t\"Flusslauf (Gr)\",\n\t\"River Delta (Med)\",\t\t\t\t\t\t\"Flussdelta (Mit)\",\n\t\"River Islands (Med)\",\t\t\t\t\t\"Flussinsel (Mit)\",\n\t\"River Maze (Sm)\",\t\t\t\t\t\t\"Flussgewirr (Kl)\",\n\t\"Rivers (Sm)\",\t\t\t\t\t\t\t\t\"Flsse (Kl)\",\n\t\"Run the Gauntlet (Med)\",\t\t\t\t\"Spiessrutenlauf (Mit)\",\n\t\"Scappa Flow (Lg)\",\t\t\t\t\t\t\"Scapa Flow (Gr)\",\n\t\"Siberian Slaughter (Lg)\",\t\t\t\t\"Sibirisches Gemetzel (Gr)\",\n\t\"Sleepy Valley (Sm)\",\t\t\t\t\t\"Tal der Ahnungslosen (Kl)\",\n\t\"Snake River (Lg)\",\t\t\t\t\t\t\"Am Schlangenfluss (Gr)\",\n\t\"Snow Wars (Lg)\",\t\t\t\t\t\t\t\"Krieg der Flocken (Gr)\",\n\t\"Snowball fight (Lg)\",\t\t\t\t\t\"Schneeballschlacht (Gr)\",\n\t\"Snowy Island (Lg)\",\t\t\t\t\t\t\"Schneeinsel (Gr)\",\n\t\"So Near So Far (Sm)\",\t\t\t\t\t\"So nah und doch so fern (Kl)\",\n\t\"South America (Lg)\",\t\t\t\t\t\"Sdamerika (Gr)\",\n\t\"Spring Line (Lg)\",\t\t\t\t\t\t\"Frhlingsgefhle (Gr)\",\n\t\"Star (Lg)\",\t\t\t\t\t\t\t\t\"Stern (Gr)\",\n\t\"Straighter & Narrower (Sm)\",\t\t\t\"Enger & schmaler (Kl)\",\n\t\"TerrainSpotting (Sm)\",\t\t\t\t\t\"TerrainSpotting (Kl)\",\n\t\"The Bay (Lg)\",\t\t\t\t\t\t\t\"Die Bucht (Gr)\",\n\t\"The Garden (Lg)\",\t\t\t\t\t\t\"Der Garten (Gr)\",\n\t\"The Great Lakes (Med)\",\t\t\t\t\"Die Grossen Seen (Mit)\",\n\t\"The Ice Arena (Lg)\",\t\t\t\t\t\"Eisarena (Gr)\",\n\t\"The Lake District (Lg)\",\t\t\t\t\"Kalte Seenplatte (Gr)\",\n\t\"The Linked lands (Lg)\",\t\t\t\t\"Die verbundenen Lnder (Gr)\",\n\t\"The Mississippi (Med)\",\t\t\t\t\"Grsse von Tom Sawyer (Mit)\",\n\t\"The Sticky Bit (Lg)\",\t\t\t\t\t\"Der klebrige Teil (Gr)\",\n\t\"The Valley (Med)\",\t\t\t\t\t\t\"Das Tal (Mit)\",\n\t\"The Woods Today (Lg)\",\t\t\t\t\t\"Waldlufer (Gr)\",\n\t\"Things to Come (Lg)\",\t\t\t\t\t\"Was die Zukunft bringt (Gr)\",\n\t\"Tiger Core (Sm)\",\t\t\t\t\t\t\"Das Herz des Tigers (Kl)\",\n\t\"To the Core (Sm)\",\t\t\t\t\t\t\"Mitten ins Herz (Kl)\",\n\t\"Tournament Hills (Lg)\",\t\t\t\t\"Hgel der Entscheidung (Gr)\",\n\t\"Tropical Storm (Med)\",\t\t\t\t\t\"Tropenstrme (Mit)\",\n\t\"Tundra Trouble (Lg)\",\t\t\t\t\t\"Tauziehen in der Tundra (Gr)\",\n\t\"Uk (Med)\",\t\t\t\t\t\t\t\t\t\"GB (Mit)\",\n\t\"Undiscovered Country (Sm)\",\t\t\t\"Unentdecktes Land (Kl)\",\n\t\"United States (Med)\",\t\t\t\t\t\"US (Mit)\",\n\t\"Volcano (Sm)\",\t\t\t\t\t\t\t\"Vulkan (Kl)\",\n\t\"Wastelands (Lg)\",\t\t\t\t\t\t\"Wstenei (Gr)\",\n\t\"Water Works (Sm)\",\t\t\t\t\t\t\"Wasserwerke (Kl)\",\n\t\"World Map (Med)\",\t\t\t\t\t\t\"Weltkarte (Kl)\",\n\t\"Zambezi (Lg)\",\t\t\t\t\t\t\t\"Sambesi (Gr)\",\n\n//#if 0\n\t\"A Pattern of Islands (Lg 8 players)\",  \t\t \"Inselmuster (gross, 8 Spieler)\",\n\t\"Arena Valley Extreme (Mega 8 players)\",\t\t \"Arenatal (sehr gross, 8 Spieler)\",\n\t\"Around the Rim (Sm 4 players)\",\t\t\t\t\t \"Um die Kante (klein, 4 Spieler)\",\n\t\"Ashes to Ashes (Lg 6 players)\",\t\t\t\t\t \"Asche zu Asche (gross, 6 Spieler)\",\n\t\"Artic Wasteland (Mega 8 players)\",\t\t\t\t \"Arktische Wste (sehr gross, 8 Spieler)\",\n\t\"Badajoz (Med 4 players)\",\t\t\t\t\t\t\t \"Badjoz (mittelgross, 4 Spieler)\",\n\t\"Baptism of Fire (Lg 6 players)\",\t\t\t\t \"Feuertaufe (gross, 6 Spieler)\",\n\t\"Big Fish, Small Pond (Lg 6 players)\",\t\t\t \"Grosser Fisch im kleinen Teich (gross, 6 Spieler)\",\n\t\"Blue Lakes (Lg 8 players)\",\t\t\t\t\t\t \"Die blauen Seen (gross, 8 Spieler)\",\n\t\"Booby Traps (Mega 8 players)\",\t\t\t\t\t \"Vorsicht, Falle! (sehr gross, 8 Spieler)\",\n\t\"Bridgehead (Lg 6 players)\",\t\t\t\t\t\t \"Brckenkopf im Niemandsland (gross, 6 Spieler)\",\n\t\"Butterfly Bay (Lg 6 players)\",\t\t\t\t\t \"Schmetterlingsbucht (gross, 6 Spieler)\",\n\t\"Central Conflict Extreme (Mega 8 players)\",  \"Zentraler Konflikt fr Knner (sehr gross, 8 Spieler)\",\n\t\"Circles of Death (Mega 8 players)\",\t\t\t \"Todeskreise (sehr gross, 8 Spieler)\",\n\t\"Cold Front (Med 6 players)\",\t\t\t\t\t\t \"Kaltfront ( mittelgross, 6 Spieler)\",\n\t\"Cold Pass (Med 4 players)\",\t\t\t\t\t\t \"Cooler Pass (mittelgross, 4 Spieler)\",\n\t\"Combat Zones (Mega 8 players)\",\t\t\t\t\t \"Kampfgebiete (sehr gross, 8 Spieler)\",\n\t\"Conflict Cove (Sm 4 players)\",\t\t\t\t\t \"Hhlenkonflikt (klein, 4 Spieler)\",\n\t\"Culloden Moor (Med 8 players)\",\t\t\t\t\t \"Culloden-Moor (mittelgross, 8 Spieler)\",\n\t\"Damnation Alley (Mega 8 players)\",\t\t\t\t \"Strasse der Verdammten (sehr gross, 8 Spieler)\",\n\t\"Death Valley (Mega 8 players)\",\t\t\t\t\t \"Tal des Todes (sehr gross, 8 Spieler)\",\n\t\"Deep Six (Mega 8 players)\",\t\t\t\t\t\t \"Tiefe Sechs (sehr gross, 8 Spieler)\",\n\t\"Destruction Derby (Mega 8 players)\",\t\t\t \"Destruction Derby (sehr gross, 8 Spieler)\",\n\t\"Diamonds Aren't Forever (Mega 8 players)\",\t \"Vergngliche Diamanten (sehr gross, 8 Spieler)\",\n\t\"Elysium (Sm 4 players)\",\t\t\t\t\t\t\t \"Elysium (klein, 4 Spieler)\",\n\t\"Equal Shares (Lg 4 players)\",\t\t\t\t\t \"Gleiche Anteile (gross, 4 Spieler)\",\n\t\"Frost Bitten (Mega 8 players)\",\t\t\t\t\t \"Frostbrand (sehr gross, 8 Spieler)\",\n\t\"Frozen Valley (Med 6 players)\",\t\t\t\t\t \"Eisiges Tal (mittelgross, 6 Spieler)\",\n\t\"Gettysburg (Sm 4 players)\",\t\t\t\t\t\t \"Gettysburg (klein, 4 Spieler)\",\n\t\"Glacial Valley (Sm 4 players)\",\t\t\t\t\t \"Gletschertal (klein, 4 Spieler)\",\n\t\"Gold Coast (Med 6 players)\",\t\t\t\t\t\t \"Goldkste (mittelgross, 6 Spieler)\",\n\t\"Gold Rush (Lg 4 players)\",\t\t\t\t\t\t \"Goldrausch (gross, 4 Spieler)\",\n\t\"Habitat (Lg 4 players)\",\t\t\t\t\t\t\t \"Habitat (gross, 4 Spieler)\",\n\t\"Hades Frozen Over (Sm 4 players)\",\t\t\t\t \"Frostschutz fr die Hlle (klein, 4 Spieler)\",\n\t\"Hamburger Hill (Mega 8 players)\",\t\t\t\t \"Hamburger Hill (sehr gross, 8 Spieler)\",\n\t\"Hastings (Sm 4 players)\",\t\t\t\t\t\t\t \"Hastings (klein, 4 Spieler)\",\n\t\"Hell's Pass (Med 6 players)\",\t\t\t\t\t \"Hllenpass (mittelgross, 6 Spieler)\",\n\t\"Holy Grounds (Mega 8 players)\",\t\t\t\t\t \"Heiliger Boden (sehr gross, 8 Spieler)\",\n\t\"Ice Bergs (Med 6 players)\",\t\t\t\t\t\t \"Eisberge (mittelgross, 6 Spieler)\",\n\t\"Ice Station (Lg 6 players)\",\t\t\t\t\t\t \"Eisstation  (gross, 6 Spieler)\",\n\t\"Ice Queen (Lg 4 players)\",\t\t\t\t\t\t \"Eisknigin (gross, 4 Spieler)\",\n\t\"In the Sun (Med 6 players)\",\t\t\t\t\t\t \"Unter der Sonne (mittelgross, 6 Spieler)\",\n\t\"Innocents? (Mega 8 players)\",\t\t\t\t\t \"Unschuldig? Wer? (sehr gross, 8 Spieler)\",\n\t\"Islands (Med 8 players)\",\t\t\t\t\t\t\t \"Inseln im Nebel (mittelgross, 8 Spieler)\",\n\t\"Island Plateau (Lg 4 players)\",\t\t\t\t\t \"Inselplateau (gross, 4 Spieler)\",\n\t\"Island Wars Extreme (Mega 8 players)\",\t\t \"Extremes Inselspringen (sehr gross, 8 Spieler)\",\n\t\"Kananga (Med 6 players)\",\t\t\t\t\t\t\t \"Kananga (mittelgross, 6 Spieler)\",\n\t\"King of the Hills Extreme (Mega 8 players)\", \"Knig des Maulwurfshgels (sehr gross, 8 Spieler)\",\n\t\"Lake Land (Lg 8 players)\",\t\t\t\t\t\t \"Seenland (gross, 8 Spieler)\",\n\t\"Land Locked (Lg 8 players)\",\t\t\t\t\t\t \"Das Verschlossene Land (gross, 8 Spieler)\",\n\t\"Lanes (Med 8 players)\",\t\t\t\t\t\t\t \"Gassenjungen (mittelgross, 8 Spieler)\",\n\t\"Leipzip (Sm 4 players)\",\t\t\t\t\t\t\t \"Leipzig (klein, 4 Spieler)\",\n\t\"Meander (Lg 8 players)\",\t\t\t\t\t\t\t \"Mander (gross, 8 Spieler)\",\n\t\"Mekong (Med 8 players)\",\t\t\t\t\t\t\t \"Mekong (mittelgross, 8 Spieler)\",\n\t\"Middle Ground (Med 8 players)\",\t\t\t\t\t \"Mittelsmann (mittelgross, 8 Spieler)\",\n\t\"Naval Conquests (Mega 8 players)\",\t\t\t\t \"Kommt zur Marine, haben sie gesagt (sehr gross, 8 Spieler)\",\n\t\"On your Marks (Med 4 players)\",\t\t\t\t\t \"Auf die Pltze (mittelgross, 4 Spieler)\",\n\t\"Open Warfare (Mega 8 players)\",\t\t\t\t\t \"Offener Schlagabtausch (sehr gross, 8 Spieler)\",\n\t\"Ore Gardens (Lg 8 players)\",\t\t\t\t\t\t \"Erzparadies (gross, 8 Spieler)\",\n\t\"Potholes (Mega 8 players)\",\t\t\t\t\t\t \"Schlaglcher (sehr gross, 8 Spieler)\",\n\t\"Puddles (Med 4 players)\",\t\t\t\t\t\t\t \"Pftzen (mittelgross, 4 Spieler)\",\n\t\"Random Violence (Mega 8 players)\",\t\t\t\t \"Unberechenbare Gewalt (sehr gross, 8 Spieler)\",\n\t\"Revenge (Med 8 players)\",\t\t\t\t\t\t\t \"Rache (mittelgross, 8 Spieler)\",\n\t\"Rias (Med 8 players)\",\t\t\t\t\t\t\t\t \"Kabul (mittelgross, 8 Spieler)\",\n\t\"River Crossing (Sm 4 players)\",\t\t\t\t\t \"Die Furt (klein, 4 Spieler)\",\n\t\"River Rampage (Mega 8 players)\",\t\t\t\t \"Flussfahrt (sehr gross, 8 Spieler)\",\n\t\"River Rapids (Lg 6 players)\",\t\t\t\t\t \"Stromschnellen (gross, 6 Spieler)\",\n\t\"Rivers Wild (Mega 8 players)\",\t\t\t\t\t \"Wildwasser (sehr gross, 8 Spieler)\",\n\t\"Rorkes Drift (Lg 4 players)\",\t\t\t\t\t \"Rorkes Drift (gross, 4 Spieler)\",\n\t\"Seaside (Med 4 players)\",\t\t\t\t\t\t\t \"Strandleben (mittelgross, 4 Spieler)\",\n\t\"Shades (Med 8 players)\",\t\t\t\t\t\t\t \"Schattenreich (mittelgross, 8 Spieler)\",\n\t\"Smuggler's Cove (Lg 6 players)\",\t\t\t\t \"Schmugglerhhle (gross, 6 Spieler)\",\n\t\"Snow Garden (Sm 2 players)\",\t\t\t\t\t\t \"Schneegestber (klein, 2 Spieler)\",\n\t\"Stalingrad (Sm 4 players)\",\t\t\t\t\t\t \"Stalingrad (klein, 4 Spieler)\",\n\t\"Sticks & Stones (Med 4 players)\",\t\t\t\t \"Holz und Steine (mittelgross, 4 Spieler)\",\n\t\"Strathearn Valley (Lg 6 players)\",\t\t\t\t \"Das Tal von Strathearn (gross, 6 Spieler)\",\n\t\"Super Bridgehead (Mega 8 players)\",\t\t\t \"Super-Brckenkopf (sehr gross, 8 Spieler)\",\n\t\"Super Mekong (Mega 8 players)\",\t\t\t\t\t \"Super-Mekong (sehr gross, 8 Spieler)\",\n\t\"Super Ore Gardens (Mega 8 players)\",\t\t\t \"Super-Erzparadies (sehr gross, 8 Spieler)\",\n\t\"Switch (Med 4 players)\",\t\t\t\t\t\t\t \"Schalter (mittelgross, 4 Spieler)\",\n\t\"The Berg (Mega 8 players)\",\t\t\t\t\t\t \"Der Berg (sehr gross, 8 Spieler)\",\n\t\"The Boyne (Med 4 players)\",\t\t\t\t\t\t \"Boyne (mittelgross, 4 Spieler)\",\n\t\"The Bulge (Sm 4 players)\",\t\t\t\t\t\t \"Die Wlbung (klein, 4 Spieler)\",\n\t\"The Cauldron (Lg 6 players)\",\t\t\t\t\t \"Der Kessel (gross, 6 Spieler)\",\n\t\"The Finger (Lg 6 players)\",\t\t\t\t\t\t \"Der Finger (gross, 6 Spieler)\",\n\t\"The Hills Have Eyes (Mega 8 players)\",\t\t \"Die Hgel haben Augen (sehr gross, 8 Spieler)\",\n\t\"The Keyes (Med 6 players)\",\t\t\t\t\t\t \"Ein Sumpf (mittelgross, 6 Spieler)\",\n\t\"The Lakes (Med 8 players)\",\t\t\t\t\t\t \"Die Seen (mittelgross, 8 Spieler)\",\n\t\"The Neck (Med 6 players)\",\t\t\t\t\t\t \"Der Hals (mittelgross, 6 Spieler)\",\n\t\"The Web (Lg 6 players)\",\t\t\t\t\t\t\t \"Das Netz (gross, 6 Spieler)\",\n\t\"To the Core (Lg 4 players)\",\t\t\t\t\t\t \"Mitten ins Herz (gross, 4 Spieler)\",\n\t\"Trafalgar (Lg 4 players)\",\t\t\t\t\t\t \"Trafalgar (gross, 4 Spieler)\",\n\t\"Twin Rivers (Sm 4 players)\",\t\t\t\t\t\t \"Zwillingsstrme (klein, 4 Spieler)\",\n\t\"Umtumbo Gorge (Lg 4 players)\",\t\t\t\t\t \"Die Umtumbo-Schlucht (gross, 4 Spieler)\",\n\t\"Watch Your Step Extreme (Mega 8 players)\",\t \"Vorsicht, Lebensgefahr (sehr gross, 8 Spieler)\",\n\t\"Waterfalls (Lg 8 players)\",\t\t\t\t\t\t \"Wasserfall (gross, 8 Spieler)\",\n\t\"Waterloo Revisited (Lg 6 players)\",\t\t\t \"Zu Besuch in Waterloo (gross, 6 Spieler)\",\n\t\"Water Werks (Mega 8 players)\",\t\t\t\t\t \"Wasserwerk (sehr gross, 8 Spieler)\",\n\t\"Warlord's Lake (Sm 4 players)\",\t\t\t\t\t \"Der See des Kriegsgottes (klein, 4 Spieler)\",\n\t\"Zama (Sm 4 players)\",\t\t\t\t\t\t\t\t \"Zama (klein, 4 Spieler)\",\n//#endif\n        NULL\n};\n#endif\n#ifdef FRENCH\nchar const *EngMisStr[] = {\n\n\t\"A Path Beyond (Lg)\",\t\t\t\t\t\"Le Passage (Max)\",\n\t\"Central Conflict (Lg)\",\t\t\t\t\"Conflit Central (Max)\",\n\t\"Coastal Influence (Med)\",\t\t\t\t\"Le Chant des Canons (Moy)\",\n\t\"Combat Alley (Med)\",\t\t\t\t\t\"Aux Armes! (Moy)\",\n\t\"Desolation (Lg)\",\t\t\t\t\t\t\"Dsolation (Max)\",\n\t\"Dugout Isle (Med)\",\t\t\t\t\t\t\"L'Ile Maudite (Moy)\",\n\t\"Equal Opportunity (Sm)\",\t\t\t\t\"A Chances Egales (Min)\",\n\t\"First Come, First Serve (Sm)\",\t\t\"La Loi du Plus Fort (Min)\",\n\t\"Island Hoppers (Sm)\",\t\t\t\t\t\"D'une Ile  l'autre (Min)\",\n\t\"Island Wars (Lg)\",\t\t\t\t\t\t\"Guerres Insulaires (Max)\",\n\t\"Isle of Fury (Lg)\",\t\t\t\t\t\t\"L'Ile de la Furie(Max)\",\n\t\"Ivory Wastelands (Sm)\",\t\t\t\t\"Terres d'Ivoire (Min)\",\n\t\"Keep off the Grass (Sm)\",\t\t\t\t\"Hors de mon Chemin (Min)\",\n\t\"Marooned II (Med)\",\t\t\t\t\t\t\"Isolement II (Moy)\",\n\t\"Middle Mayhem (Sm)\",\t\t\t\t\t\"Chaos Interne (Min)\",\n\t\"No Escape (Med)\",\t\t\t\t\t\t\"Le Pige (Moy)\",\n\t\"No Man's Land (Med)\",\t\t\t\t\t\"No Man's Land (Moy)\",\n\t\"Normandy (Med)\",\t\t\t\t\t\t\t\"Normandie (Moy)\",\n\t\"North By Northwest (Lg)\",\t\t\t\t\"Nord, Nord-Ouest (Max)\",\n\t\"Pond Skirmish (Med)\",\t\t\t\t\t\"Bain de Sang (Moy)\",\n\t\"Raraku (Lg)\",\t\t\t\t\t\t\t\t\"Raraku (Max)\",\n\t\"Ridge War (Med)\",\t\t\t\t\t\t\"Guerre au Sommet (Moy)\",\n\t\"Shallow Grave (Med)\",\t\t\t\t\t\"La Saveur de la Mort (Moy)\",\n\t\"Treasure Isle (Med)\",\t\t\t\t\t\"L'Ile au Trsor (Moy)\",\n\n\t\"Africa (Lg)\",\t\t\t\t\t\t\t\t\"Afrique (Max)\",\n\t\"Alaska Anarchy (Lg)\",\t\t\t\t\t\"Anarchie en Alaska (Max)\",\n\t\"All that Glitters... (Lg)\",\t\t\t\"Tout ce qui brille... (Max)\",\n\t\"Apre's Peace (Lg)\",\t\t\t\t\t\t\"Une Paix Durement Ngocie... (Max)\",\n\t\"Antartica (Lg)\",\t\t\t\t\t\t\t\"Antarctique (Max)\",\n\t\"Armourgarden (Lg)\",\t\t\t\t\t\t\"La Guerre des Blinds (Max)\",\n\t\"Austraila (Med)\",\t\t\t\t\t\t\"Australie (Moy)\",\n\t\"Barrier to Entry (Lg)\",\t\t\t\t\"Barrire  l'Entre (Max)\",\n\t\"Bavarian Blast (Med)\",\t\t\t\t\t\"Tonnerre Bavarois (Moy)\",\n\t\"Be Shore (Med)\",\t\t\t\t\t\t\t\"Plages Menaces (Moy)\",\n\t\"Bearing Straits (Med)\",\t\t\t\t\"Droit Devant ! (Moy)\",\n\t\"Blow Holes (Lg)\",\t\t\t\t\t\t\"Cratres (Max)\",\n\t\"Bonsai (Sm)\",\t\t\t\t\t\t\t\t\"Bonsa (Min)\",\n\t\"Brother Stalin (Lg)\",\t\t\t\t\t\"Frre Staline (Max)\",\n\t\"Bullseye (Lg)\",\t\t\t\t\t\t\t\"L'oeil du Taureau (Max)\",\n\t\"C&C (Med)\",\t\t\t\t\t\t\t\t\"C&C (Moy)\",\n\t\"Camos Canyon (Med)\",\t\t\t\t\t\"Le Canyon (Moy)\",\n\t\"Camos Coves (Lg)\",\t\t\t\t\t\t\"Criques (Max)\",\n\t\"Camos Cross (Lg)\",\t\t\t\t\t\t\"La Croix de Guerre (Max)\",\n\t\"Camos Crossing (Sm)\",\t\t\t\t\t\"La Croise des Chemins (Min)\",\n\t\"Central Arena (Lg)\",\t\t\t\t\t\"L'Arne Diabolique (Max)\",\n\t\"Canyon River (Med)\",\t\t\t\t\t\"Au Milieu Coule Une Rivire (Moy)\",\n\t\"Crossroads (Sm)\",\t\t\t\t\t\t\"Carrefours (Min)\",\n\t\"Czech Mate (Lg)\",\t\t\t\t\t\t\"Tchque et Mat (Max)\",\n\t\"Dday (Med)\",\t\t\t\t\t\t\t\t\"Le Jour J (Moy)\",\n\t\"Disaster Central (Lg)\",\t\t\t\t\"Dsastre Central (Max)\",\n\t\"Docklands (Med)\",\t\t\t\t\t\t\"L'Enfer des Docks (Moy)\",\n\t\"East Coast (Med)\",\t\t\t\t\t\t\"Cte Est (Moy)\",\n\t\"Eastern Seaboard (Lg)\",\t\t\t\t\"Rivages de l'Est (Max)\",\n\t\"Finger Lake (Lg)\",\t\t\t\t\t\t\"Le Lac de tous les Dangers (Max)\",\n\t\"Fjords (Med)\",\t\t\t\t\t\t\t\"Fjords (Moy)\",\n\t\"Floodlands (Lg)\",\t\t\t\t\t\t\"Campagne Lacustre (Max)\",\n\t\"Forest under fire (Lg)\",\t\t\t\t\"Fort en flammes (Max)\",\n\t\"Four Corners (Lg)\",\t\t\t\t\t\t\"4 Coins (Max)\",\n\t\"Frostbit Fjords (Lg)\",\t\t\t\t\t\"Fjords Gels (Max)\",\n\t\"Glenboig (Sm)\",\t\t\t\t\t\t\t\"Glenboig (Min)\",\n\t\"Hell Frozen Over (Lg)\",\t\t\t\t\"Enfer de Glace Max)\",\n\t\"India (Lg)\",\t\t\t\t\t\t\t\t\"Inde (Max)\",\n\t\"Indirect Fire (Lg)\",\t\t\t\t\t\"Attaque Indirecte (Max)\",\n\t\"Island Wars II (Lg)\",\t\t\t\t\t\"Guerres Insulaires II (Max)\",\n\t\"Italy (Lg)\",\t\t\t\t\t\t\t\t\"Italie (Max)\",\n\t\"Kabalo (Lg)\",\t\t\t\t\t\t\t\t\"Kabalo (Max)\",\n\t\"King of the Hills (Lg)\",\t\t\t\t\"Le Roi des Montagnes (Max)\",\n\t\"Lake Divide (Med)\",\t\t\t\t\t\t\"La Guerre du Lac (Moy)\",\n\t\"Lakelands (Lg)\",\t\t\t\t\t\t\t\"Terres Submerges (Max)\",\n\t\"Land Ladder (Lg)\",\t\t\t\t\t\t\"Jusqu'au Sommet (Max)\",\n\t\"Lotsa Lakes (Lg)\",\t\t\t\t\t\t\"Terres de Lacs (Max)\",\n\t\"Lunar Battlefield (Lg Special)\",\t\"Combat Lunaire (Max Spcial)\",\n\t\"Malibu Fields (Med)\",\t\t\t\t\t\"Les Champs de Malibu (Moy)\",\n\t\"Marshland (Med)\",\t\t\t\t\t\t\"Marcages (Moy)\",\n\t\"MyLai Delta (Med)\",\t\t\t\t\t\t\"Le Delta Mylai (Moy)\",\n\t\"Natural Harbor (Med)\",\t\t\t\t\t\"Port Naturel (Moy)\",\n\t\"No Way Out (Lg)\",\t\t\t\t\t\t\"Sans Issue (Max)\",\n\t\"Normandy Landing (Lg)\",\t\t\t\t\"Le Dbarquement (Max)\",\n\t\"Ore Wars (Med)\",\t\t\t\t\t\t\t\"La Guerre du Minerai (Moy)\",\n\t\"Oz (Lg)\",\t\t\t\t\t\t\t\t\t\"Oz (Max)\",\n\t\"Pilgrim Fathers II (Lg)\",\t\t\t\t\"Les Plerins 2 (Max)\",\n\t\"Pip's Ice Tea (Med)\",\t\t\t\t\t\"Les Tranches de Glace (Moy)\",\n\t\"Polar Panic (Lg)\",\t\t\t\t\t\t\"Panique Polaire (Max)\",\n\t\"Ponds (Med)\",\t\t\t\t\t\t\t\t\"Les Etangs (Moy)\",\n\t\"Putney (Lg)\",\t\t\t\t\t\t\t\t\"La Meilleure Dfense... (Max)\",\n\t\"Return to Zion (Lg)\",\t\t\t\t\t\"Retour  Sion (Max)\",\n\t\"Ring of Land (Lg)\",\t\t\t\t\t\t\"Le Cycle Infernal (Max)\",\n\t\"River Basin (Lg)\",\t\t\t\t\t\t\"Confrontation Navale (Max)\",\n\t\"River Delta (Med)\",\t\t\t\t\t\t\"Le Delta (Moy)\",\n\t\"River Islands (Med)\",\t\t\t\t\t\"Ctes  Surveiller de Prs (Moy)\",\n\t\"River Maze (Sm)\",\t\t\t\t\t\t\"Labyrinthe Fluvial (Min)\",\n\t\"Rivers (Sm)\",\t\t\t\t\t\t\t\t\"Rivires (Min)\",\n\t\"Run the Gauntlet (Med)\",\t\t\t\t\"Relevons le Dfi ! (Moy)\",\n\t\"Scappa Flow (Lg)\",\t\t\t\t\t\t\"Combats Sanglants (Max)\",\n\t\"Siberian Slaughter (Lg)\",\t\t\t\t\"Carnage Sibrien (Max)\",\n\t\"Sleepy Valley (Sm)\",\t\t\t\t\t\"La Valle Endormie (Min)\",\n\t\"Snake River (Lg)\",\t\t\t\t\t\t\"La Rivire aux Serpents (Max)\",\n\t\"Snow Wars (Lg)\",\t\t\t\t\t\t\t\"Guerres de Neige (Max)\",\n\t\"Snowball fight (Lg)\",\t\t\t\t\t\"Bataille de Boules de Neige (Max)\",\n\t\"Snowy Island (Lg)\",\t\t\t\t\t\t\"L'Ile sous la Neige (Max)\",\n\t\"So Near So Far (Sm)\",\t\t\t\t\t\"Si Loin, Si Proche (Min)\",\n\t\"South America (Lg)\",\t\t\t\t\t\"Amrique du Sud (Max)\",\n\t\"Spring Line (Lg)\",\t\t\t\t\t\t\"Ligne de Front (Max)\",\n\t\"Star (Lg)\",\t\t\t\t\t\t\t\t\"Etoile (Max)\",\n\t\"Straighter & Narrower (Sm)\",\t\t\t\"L'Entonnoir (Min)\",\n\t\"TerrainSpotting (Sm)\",\t\t\t\t\t\"TerrainSpotting (Min)\",\n\t\"The Bay (Lg)\",\t\t\t\t\t\t\t\"La Baie (Max)\",\n\t\"The Garden (Lg)\",\t\t\t\t\t\t\"Le Jardin (Max)\",\n\t\"The Great Lakes (Med)\",\t\t\t\t\"Les Grands Lacs (Moy)\",\n\t\"The Ice Arena (Lg)\",\t\t\t\t\t\"L'Arne de Glace (Max)\",\n\t\"The Lake District (Lg)\",\t\t\t\t\"Un Lac Imprenable (Max)\",\n\t\"The Linked lands (Lg)\",\t\t\t\t\"Passages  Gu (Max)\",\n\t\"The Mississippi (Med)\",\t\t\t\t\"Mississippi (Moy)\",\n\t\"The Sticky Bit (Lg)\",\t\t\t\t\t\"Marasme (Max)\",\n\t\"The Valley (Med)\",\t\t\t\t\t\t\"La Valle (Moy)\",\n\t\"The Woods Today (Lg)\",\t\t\t\t\t\"Aujoud'hui: la Mort ! (Max)\",\n\t\"Things to Come (Lg)\",\t\t\t\t\t\"Dnouement Incertain (Max)\",\n\t\"Tiger Core (Sm)\",\t\t\t\t\t\t\"Le Coeur du Tigre (Min)\",\n\t\"To the Core (Sm)\",\t\t\t\t\t\t\"Le Coeur du Conflit (Min)\",\n\t\"Tournament Hills (Lg)\",\t\t\t\t\"Combat en Altitude (Max)\",\n\t\"Tropical Storm (Med)\",\t\t\t\t\t\"Ouragan Tropical (Moy)\",\n\t\"Tundra Trouble (Lg)\",\t\t\t\t\t\"La Toundra (Max)\",\n\t\"Uk (Med)\",\t\t\t\t\t\t\t\t\t\"Royaume Uni (Moy)\",\n\t\"Undiscovered Country (Sm)\",\t\t\t\"Terre Inconnue (Min)\",\n\t\"United States (Med)\",\t\t\t\t\t\"Etats Unis (Moy)\",\n\t\"Volcano (Sm)\",\t\t\t\t\t\t\t\"Le Volcan (Min)\",\n\t\"Wastelands (Lg)\",\t\t\t\t\t\t\"Terres Dsoles (Max)\",\n\t\"Water Works (Sm)\",\t\t\t\t\t\t\"Jeux d'Eau (Min)\",\n\t\"World Map (Med)\",\t\t\t\t\t\t\"Carte du Monde (Moy)\",\n\t\"Zambezi (Lg)\",\t\t\t\t\t\t\t\"Zambze (Max)\",\n//#if 0\n\t\"A Pattern of Islands (Lg 8 players)\",\t\t\t \"Archipel (Max. 8 joueurs)\",\n\t\"Arena Valley Extreme (Mega 8 players)\",\t\t \"La Valle de l'arne (XL 8 joueurs)\",\n\t\"Around the Rim (Sm 4 players)\",\t\t\t\t\t \"Autour de la crte (Min. 4 joueurs)\",\n\t\"Ashes to Ashes (Lg 6 players)\",\t\t\t\t\t \"Rduit en cendres (Max. 6 joueurs)\",\n\t\"Artic Wasteland (Mega 8 players)\",\t\t\t\t \"Dsolation arctique (XL 8 joueurs)\",\n\t\"Badajoz (Med 4 players)\",\t\t\t\t\t\t\t \"Badjoz (Moy. 4 joueurs)\",\n\t\"Baptism of Fire (Lg 6 players)\",\t\t\t\t \"Baptme du feu (Max. 6 joueurs)\",\n\t\"Big Fish, Small Pond (Lg 6 players)\",\t\t\t \"Gros poisson, Min. Mare (Max. 6 joueurs)\",\n\t\"Blue Lakes (Lg 8 players)\",\t\t\t\t\t\t \"Lacs bleus (Max. 8 joueurs)\",\n\t\"Booby Traps (Mega 8 players)\",\t\t\t\t\t \"Piges (XL 8 joueurs)\",\n\t\"Bridgehead (Lg 6 players)\",\t\t\t\t\t\t \"Tte de pont (Max. 6 joueurs)\",\n\t\"Butterfly Bay (Lg 6 players)\",\t\t\t\t\t \"La baie du papillon (Max. 6 joueurs)\",\n\t\"Central Conflict Extreme (Mega 8 players)\",\t \"Conflit central extrme (XL 8 joueurs)\",\n\t\"Circles of Death (Mega 8 players)\",\t\t\t \"Les cercles de la mort (XL 8 joueurs)\",\n\t\"Cold Front (Med 6 players)\",\t\t\t\t\t\t \"Front froid ( Moy. 6 joueurs)\",\n\t\"Cold Pass (Med 4 players)\",\t\t\t\t\t\t \"La Passe Glace (Moy. 4 joueurs)\",\n\t\"Combat Zones (Mega 8 players)\",\t\t\t\t\t \"Zones de combat (XL 8 joueurs)\",\n\t\"Conflict Cove (Sm 4 players)\",\t\t\t\t\t \"La Crique du conflit (Min. 4 joueurs)\",\n\t\"Culloden Moor (Med 8 players)\",\t\t\t\t\t \"La Lande de Culloden (Moy. 8 joueurs)\",\n\t\"Damnation Alley (Mega 8 players)\",\t\t\t\t \"Le chemin de la damnation (XL 8 joueurs)\",\n\t\"Death Valley (Mega 8 players)\",\t\t\t\t\t \"La valle de la mort (XL 8 joueurs)\",\n\t\"Deep Six (Mega 8 players)\",\t\t\t\t\t\t \"Six de profondeur (XL 8 joueurs)\",\n\t\"Destruction Derby (Mega 8 players)\",\t\t\t \"Stock car (XL 8 joueurs)\",\n\t\"Diamonds Aren't Forever (Mega 8 players)\",\t \"Les diamants ne sont pas ternels (XL 8 joueurs)\",\n\t\"Elysium (Sm 4 players)\",\t\t\t\t\t\t\t \"Elyse (Min. 4 joueurs)\",\n\t\"Equal Shares (Lg 4 players)\",\t\t\t\t\t \"Parts gales (Max. 4 joueurs)\",\n\t\"Frost Bitten (Mega 8 players)\",\t\t\t\t\t \"Engelures (XL 8 joueurs)\",\n\t\"Frozen Valley (Med 6 players)\",\t\t\t\t\t \"La Valle glace (Moy. 6 joueurs)\",\n\t\"Gettysburg (Sm 4 players)\",\t\t\t\t\t\t \"Gettysburg (Min. 4 joueurs)\",\n\t\"Glacial Valley (Sm 4 players)\",\t\t\t\t\t \"Valle de glace (Min. 4 joueurs)\",\n\t\"Gold Coast (Med 6 players)\",\t\t\t\t\t\t \"La cte dore (Moy. 6 joueurs)\",\n\t\"Gold Rush (Lg 4 players)\",\t\t\t\t\t\t \"La rue vers l'or (Max. 4 joueurs)\",\n\t\"Habitat (Lg 4 players)\",\t\t\t\t\t\t\t \"Habitat (Max. 4 joueurs)\",\n\t\"Hades Frozen Over (Sm 4 players)\",\t\t\t\t \"Les enfers glacs (Min. 4 joueurs)\",\n\t\"Hamburger Hill (Mega 8 players)\",\t\t\t\t \"Hamburger Hill (XL 8 joueurs)\",\n\t\"Hastings (Sm 4 players)\",\t\t\t\t\t\t\t \"Hastings (Min. 4 joueurs)\",\n\t\"Hell's Pass (Med 6 players)\",\t\t\t\t\t \"La route de l'enfer (Moy. 6 joueurs)\",\n\t\"Holy Grounds (Mega 8 players)\",\t\t\t\t\t \"Terres saintes (XL 8 joueurs)\",\n\t\"Ice Bergs (Med 6 players)\",\t\t\t\t\t\t \"Icebergs (Moy. 6 joueurs)\",\n\t\"Ice Station (Lg 6 players)\",\t\t\t\t\t\t \"Station glace (Max. 6 joueurs)\",\n\t\"Ice Queen (Lg 4 players)\",\t\t\t\t\t\t \"Reine des glaces (Max. 4 joueurs)\",\n\t\"In the Sun (Med 6 players)\",\t\t\t\t\t\t \"Sous le soleil (Moy. 6 joueurs)\",\n\t\"Innocents? (Mega 8 players)\",\t\t\t\t\t \"Innocents ? (XL 8 joueurs)\",\n\t\"Islands (Med 8 players)\",\t\t\t\t\t\t\t \"Iles (Moy. 8 joueurs)\",\n\t\"Island Plateau (Lg 4 players)\",\t\t\t\t\t \"Plateau des les (Max. 4 joueurs)\",\n\t\"Island Wars Extreme (Mega 8 players)\",\t\t \"Guerres insulaires extrme (XL 8 joueurs)\",\n\t\"Kananga (Med 6 players)\",\t\t\t\t\t\t\t \"Kananga (Moy. 6 joueurs)\",\n\t\"King of the Hills Extreme (Mega 8 players)\", \"Roi des collines extrme (XL 8 joueurs)\",\n\t\"Lake Land (Lg 8 players)\",\t\t\t\t\t\t \"Paysage lacustre (Max. 8 joueurs)\",\n\t\"Land Locked (Lg 8 players)\",\t\t\t\t\t\t \"Enclave (Max. 8 joueurs)\",\n\t\"Lanes (Med 8 players)\",\t\t\t\t\t\t\t \"Le parcours du combattant (Moy. 8 joueurs)\",\n\t\"Leipzip (Sm 4 players)\",\t\t\t\t\t\t\t \"Leipzig (Min. 4 joueurs)\",\n\t\"Meander (Lg 8 players)\",\t\t\t\t\t\t\t \"Mandre (Max. 8 joueurs)\",\n\t\"Mekong (Med 8 players)\",\t\t\t\t\t\t\t \"Mkong (Moy. 8 joueurs)\",\n\t\"Middle Ground (Med 8 players)\",\t\t\t\t\t \"Plateau mdian (Moy. 8 joueurs)\",\n\t\"Naval Conquests (Mega 8 players)\",\t\t\t\t \"Conqutes navales (XL 8 joueurs)\",\n\t\"On your Marks (Med 4 players)\",\t\t\t\t\t \"A vos marques (Moy. 4 joueurs)\",\n\t\"Open Warfare (Mega 8 players)\",\t\t\t\t\t \"Guerre ouverte (XL 8 joueurs)\",\n\t\"Ore Gardens (Lg 8 players)\",\t\t\t\t\t\t \"Jardins de minerai (Max. 8 joueurs)\",\n\t\"Potholes (Mega 8 players)\",\t\t\t\t\t\t \"Nids de poules (XL 8 joueurs)\",\n\t\"Puddles (Med 4 players)\",\t\t\t\t\t\t\t \"Flaques (Moy. 4 joueurs)\",\n\t\"Random Violence (Mega 8 players)\",\t\t\t\t \"Violence alatoire (XL 8 joueurs)\",\n\t\"Revenge (Med 8 players)\",\t\t\t\t\t\t\t \"Vengeance (Moy. 8 joueurs)\",\n\t\"Rias (Med 8 players)\",\t\t\t\t\t\t\t\t \"Rias (Moy. 8 joueurs)\",\n\t\"River Crossing (Sm 4 players)\",\t\t\t\t\t \"Passage  gu (Min. 4 joueurs)\",\n\t\"River Rampage (Mega 8 players)\",\t\t\t\t \"Rivire dchane (XL 8 joueurs)\",\n\t\"River Rapids (Lg 6 players)\",\t\t\t\t\t \"Rapides (Max. 6 joueurs)\",\n\t\"Rivers Wild (Mega 8 players)\",\t\t\t\t\t \"Rivires sauvages (XL 8 joueurs)\",\n\t\"Rorkes Drift (Lg 4 players)\",\t\t\t\t\t \"L'Exode de Rorkes (Max. 4 joueurs)\",\n\t\"Seaside (Med 4 players)\",\t\t\t\t\t\t\t \"Cte (Moy. 4 joueurs)\",\n\t\"Shades (Med 8 players)\",\t\t\t\t\t\t\t \"Ombres (Moy. 8 joueurs)\",\n\t\"Smuggler's Cove (Lg 6 players)\",\t\t\t\t \"La Crique du contrebandier (Max. 6 joueurs)\",\n\t\"Snow Garden (Sm 2 players)\",\t\t\t\t\t\t \"Jardin de neige (Min. 2 joueurs)\",\n\t\"Stalingrad (Sm 4 players)\",\t\t\t\t\t\t \"Stalingrad (Min. 4 joueurs)\",\n\t\"Sticks & Stones (Med 4 players)\",\t\t\t\t \"Bton & Roches (Moy. 4 joueurs)\",\n\t\"Strathearn Valley (Lg 6 players)\",\t\t\t\t \"La Valle de Strathearn (Max. 6 joueurs)\",\n\t\"Super Bridgehead (Mega 8 players)\",\t\t\t \"Super tte de pont (XL 8 joueurs)\",\n\t\"Super Mekong (Mega 8 players)\",\t\t\t\t\t \"Super Mkong (XL 8 joueurs)\",\n\t\"Super Ore Gardens (Mega 8 players)\",\t\t\t \"Super jardin de minerai (XL 8 joueurs)\",\n\t\"Switch (Med 4 players)\",\t\t\t\t\t\t\t \"Permutation (Moy. 4 joueurs)\",\n\t\"The Berg (Mega 8 players)\",\t\t\t\t\t\t \"Le Berg (XL 8 joueurs)\",\n\t\"The Boyne (Med 4 players)\",\t\t\t\t\t\t \"Le Boyne (Moy. 4 joueurs)\",\n\t\"The Bulge (Sm 4 players)\",\t\t\t\t\t\t \"Le bombement (Min. 4 joueurs)\",\n\t\"The Cauldron (Lg 6 players)\",\t\t\t\t\t \"Le chaudron (Max. 6 joueurs)\",\n\t\"The Finger (Lg 6 players)\",\t\t\t\t\t\t \"Le doigt (Max. 6 joueurs)\",\n\t\"The Hills Have Eyes (Mega 8 players)\",\t\t \"Les collines ont des yeux (XL 8 joueurs)\",\n\t\"The Keyes (Med 6 players)\",\t\t\t\t\t\t \"Les Keyes (Moy. 6 joueurs)\",\n\t\"The Lakes (Med 8 players)\",\t\t\t\t\t\t \"Les lacs (Moy. 8 joueurs)\",\n\t\"The Neck (Med 6 players)\",\t\t\t\t\t\t \"Le goulot (Moy. 6 joueurs)\",\n\t\"The Web (Lg 6 players)\",\t\t\t\t\t\t\t \"La toile (Max. 6 joueurs)\",\n\t\"To the Core (Lg 4 players)\",\t\t\t\t\t\t \"Jusqu'au cour (Max. 4 joueurs)\",\n\t\"Trafalgar (Lg 4 players)\",\t\t\t\t\t\t \"Trafalgar (Max. 4 joueurs)\",\n\t\"Twin Rivers (Sm 4 players)\",\t\t\t\t\t\t \"Les deux rivires (Min. 4 joueurs)\",\n\t\"Umtumbo Gorge (Lg 4 players)\",\t\t\t\t\t \"La Gorge de Umtumbo (Max. 4 joueurs)\",\n\t\"Watch Your Step Extreme (Mega 8 players)\",\t \"Pas--pas extrme (XL 8 joueurs)\",\n\t\"Waterfalls (Lg 8 players)\",\t\t\t\t\t\t \"Chutes d'eau (Max. 8 joueurs)\",\n\t\"Waterloo Revisited (Lg 6 players)\",\t\t\t \"Waterloo II (Max. 6 joueurs)\",\n\t\"Water Werks (Mega 8 players)\",\t\t\t\t\t \"Jeux d'eau (XL 8 joueurs)\",\n\t\"Warlord's Lake (Sm 4 players)\",\t\t\t\t\t \"Le lac du guerrier (Min. 4 joueurs)\",\n\t\"Zama (Sm 4 players)\",\t\t\t\t\t\t\t\t \"Zama (Min. 4 joueurs)\",\n//#endif\n\tNULL\n};\n#endif\n\n\n/*\n******************************** Prototypes *********************************\n*/\nstatic int Net_Join_Dialog(void);\nstatic int Request_To_Join (char *playername, int join_index,\n\tHousesType house, PlayerColorType color);\nstatic void Unjoin_Game(char *namebuf,JoinStateType joinstate,\n\tListClass *gamelist, ColorListClass *playerlist, int game_index,\n\tint goto_lobby, int msg_x, int msg_y, int msg_h, int send_x, int send_y,\n\tint msg_len);\nstatic void Send_Join_Queries(int curgame, JoinStateType joinstate,\n\tint gamenow, int playernow, int chatnow, char *myname, int init = 0);\nstatic JoinEventType Get_Join_Responses(JoinStateType *joinstate,\n\tListClass *gamelist, ColorListClass *playerlist, int join_index,\n\tchar *my_name, RejectType *why);\nstatic int Net_New_Dialog(void);\nstatic JoinEventType Get_NewGame_Responses(ColorListClass *playerlist,\n\tint *color_used);\nvoid Start_WWChat(ColorListClass *playerlist);\nint Update_WWChat(void);\n\n\n#define PCOLOR_BROWN\tPCOLOR_GREY\n\n\n/***********************************************************************************************\n * Init_Network -- initializes network stuff                               \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\ttrue = Initialization OK, false = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   02/14/1995 BR : Created.                                              \t\t\t\t\t\t  *\n *=============================================================================================*/\nbool Init_Network (void)\n{\n\tNetNumType net;\n\tNetNodeType node;\n#ifdef WINSOCK_IPX\n\tassert ( PacketTransport != NULL );\n#endif\t//WINSOCK_IPX\n\n\t//------------------------------------------------------------------------\n\t//\tThis call allocates all necessary queue buffers, allocates Real-mode\n\t//\tmemory, and commands IPX to start listening on the Global Channel.\n\t//------------------------------------------------------------------------\n\tif (!Ipx.Init()) {\n\t\treturn(false);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSet up the IPX manager to cross a bridge\n\t//------------------------------------------------------------------------\n\tif (Session.Type != GAME_INTERNET) {\n\t\tif (Session.IsBridge) {\n\t\t\tSession.BridgeNet.Get_Address(net,node);\n\t\t\tIpx.Set_Bridge(net);\n\t\t}\n\t}\n\n\treturn(true);\n\n}\t/* end of Init_Network */\n\n\n/***********************************************************************************************\n * Shutdown_Network -- shuts down network stuff                            \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   02/14/1995 BR : Created.                                              \t\t\t\t\t\t  *\n *=============================================================================================*/\nvoid Shutdown_Network (void)\n{\n//\n// Note: The thought behind this section of code was that if the program\n// terminates early, without an EventClass::EXIT event, it still needs to\n// tell the other systems that it's gone, so it would send a SIGN_OFF packet.\n// BUT, this causes a sync bug if the systems are running slow and this system\n// is running ahead of the others; it will send the NET_SIGN_OFF >>before<<\n// the other system execute their EventClass::EXIT event, and the other systems\n// will kill the connection at some random Frame # & turn my stuff over to\n// the computer possibly at different times.\n// BRR, 10/29/96\n//\n#if 0\n\t//------------------------------------------------------------------------\n\t// If the Players vector contains at least one name, send a sign-off\n\t// packet.  If 'Players' is empty, I have no name, so there's no point\n\t// in sending a sign-off.\n\t//------------------------------------------------------------------------\n\tif (Session.Players.Count()) {\n\t\t//.....................................................................\n\t\t// Build a sign-off packet & send it\n\t\t//.....................................................................\n\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\tstrcpy (Session.GPacket.Name, Session.Players[0]->Name);\n\n\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t0, NULL);\n\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t0, NULL);\n\n\t\tif (Session.IsBridge\t&& !Winsock.Get_Connected()) {\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 0,\n\t\t\t\t&Session.BridgeNet);\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 0,\n\t\t\t\t&Session.BridgeNet);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tWait for the packets to finish going out (or the Global Channel\n\t\t// times out)\n\t\t//.....................................................................\n\t\tfor (;;) {\n\t\t\tif (Ipx.Global_Num_Send()==0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tIpx.Service();\n\t\t}\n\t}\n#endif\n\n\t//------------------------------------------------------------------------\n\t//\tIf I was in a game, I'm not now, so clear the game name\n\t//------------------------------------------------------------------------\n\tSession.GameName[0] = 0;\n\n}\t/* end of Shutdown_Network */\n\n\n/***********************************************************************************************\n * Process_Global_Packet -- responds to remote queries                     \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * The only commands from other systems this routine responds to are NET_QUERY_GAME\t\t\t\t  *\n * and NET_QUERY_PLAYER.  The other commands are too context-specific to be able\t\t\t\t\t  *\n * to handle here, such as joining the game or signing off; but this routine handles\t\t\t  *\n * the majority of the program's needs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tpacket\t\tptr to packet to process\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\taddress\t\tsource address of sender\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\ttrue = packet was processed, false = wasn't\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tSession.GameName must have been filled in before this function can be called.\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   02/15/1995 BR : Created.                                              \t\t\t\t\t\t  *\n *=============================================================================================*/\nbool Process_Global_Packet(GlobalPacketType *packet, IPXAddressClass *address)\n{\n\tGlobalPacketType mypacket;\n\n\t//------------------------------------------------------------------------\n\t// If our Players vector is empty, just return.\n\t//------------------------------------------------------------------------\n\tif (Session.Players.Count()==0) {\n\t\treturn (true);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tAnother system asking what game this is\n\t//------------------------------------------------------------------------\n\tif (packet->Command==NET_QUERY_GAME && Session.NetStealth==0) {\n\n\t\t//.....................................................................\n\t\t//\tIf the game is closed, let every player respond, and let the sender of\n\t\t//\tthe query sort it all out.  This way, if the game's host exits the game,\n\t\t//\tthe game still shows up on other players' dialogs.\n\t\t//\tIf the game is open, only the game owner may respond.\n\t\t//.....................................................................\n\t\tif (strlen(Session.GameName) > 0 && ((!Session.NetOpen) ||\n\t\t\t(Session.NetOpen &&\n\t\t\t\t!strcmp(Session.Players[0]->Name,Session.GameName)))) {\n\n\t\t\tmemset (&mypacket, 0, sizeof(GlobalPacketType));\n\n\t\t\tmypacket.Command = NET_ANSWER_GAME;\n\t\t\tstrcpy(mypacket.Name, Session.GameName);\n\t\t\tmypacket.GameInfo.IsOpen = Session.NetOpen;\n\n\t\t\tIpx.Send_Global_Message (&mypacket, sizeof(GlobalPacketType), 1,\n\t\t\t\taddress);\n\t\t}\n\t\treturn(true);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tAnother system asking what player I am\n\t//------------------------------------------------------------------------\n\telse if (packet->Command==NET_QUERY_PLAYER &&\n\t\t!strcmp (packet->Name, Session.GameName) &&\n\t\t\t(strlen(Session.GameName) > 0) && Session.NetStealth==0) {\n\n\t\tmemset (&mypacket, 0, sizeof(GlobalPacketType));\t\t// changed DRD 9/26\n\n\t\tmypacket.Command = NET_ANSWER_PLAYER;\n\t\tstrcpy(mypacket.Name, Session.Players[0]->Name);\n\t\tmypacket.PlayerInfo.House = Session.House;\n\t\tmypacket.PlayerInfo.Color = Session.ColorIdx;\n\t\tmypacket.PlayerInfo.NameCRC = Compute_Name_CRC(Session.GameName);\n\n\t\tIpx.Send_Global_Message (&mypacket, sizeof(GlobalPacketType), 1, address);\n\t\treturn(true);\n\t}\n\n\treturn(false);\n\n}\t/* end of Process_Global_Packet */\n\n\n/***********************************************************************************************\n * Destroy_Connection -- destroys the given connection\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * Call this routine when a connection goes bad, or another player signs off.\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tid\t\t\tconnection ID to destroy; this should be the HousesType of the player\t\t\t  *\n *             on this connection\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\terror\t\t0 = user signed off; 1 = connection error; otherwise, no error is shown.\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   04/22/1995 BR : Created.                                              \t\t\t\t\t\t  *\n *=============================================================================================*/\nvoid Destroy_Connection(int id, int error)\n{\n\tint i;\n\tHouseClass *housep;\n\tchar txt[80];\n\n\tif (Debug_Print_Events) {\n\t\tprintf(\"Destroying connection for house %d (%s)\\n\",\n\t\t\tid,HouseClass::As_Pointer((HousesType)id)->IniName);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tDo nothing if the house isn't human.\n\t//------------------------------------------------------------------------\n\thousep = HouseClass::As_Pointer((HousesType)id);\n\tif (!housep || !housep->IsHuman)\n\t\treturn;\n\n\t//------------------------------------------------------------------------\n\t//\tCreate a message to display to the user\n\t//------------------------------------------------------------------------\n\ttxt[0] = '\\0';\n\tif (error==1) {\n\t\tsprintf(txt,Text_String(TXT_CONNECTION_LOST), housep->IniName);\n\t} else if (error==0) {\n\t\tsprintf(txt,Text_String(TXT_LEFT_GAME), housep->IniName);\n\t}\n\n\tif (strlen(txt)) {\n\t\tSession.Messages.Add_Message (NULL,0, txt, housep->RemapColor, TPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Remove this player from the Players vector\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\tif (!stricmp(Session.Players[i]->Name,housep->IniName)) {\n\t\t\tdelete Session.Players[i];\n\t\t\tSession.Players.Delete(Session.Players[i]);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tDelete the IPX connection\n\t//------------------------------------------------------------------------\n\tIpx.Delete_Connection(id);\n\n\t//------------------------------------------------------------------------\n\t//\tTurn the player's house over to the computer's AI\n\t//------------------------------------------------------------------------\n\thousep->IsHuman = false;\n\thousep->IQ = Rule.MaxIQ;\n\tstrcpy (housep->IniName,Text_String(TXT_COMPUTER));\n\n\tSession.NumPlayers--;\n\n\t//------------------------------------------------------------------------\n\t//\tIf we're the last player left, tell the user.\n\t//------------------------------------------------------------------------\n\tif (Session.NumPlayers == 1) {\n\t\tsprintf(txt,\"%s\",Text_String(TXT_JUST_YOU_AND_ME));\n\t\tSession.Messages.Add_Message (NULL, 0, txt, housep->RemapColor,\n\t\t\tTPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n}\t/* end of Destroy_Connection */\n\n\n/***********************************************************************************************\n * Remote_Connect -- handles connecting this user to others                \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\ttrue = connections established; false = not\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   02/14/1995 BR : Created.                                              \t\t\t\t\t\t  *\n *=============================================================================================*/\nbool Remote_Connect(void)\n{\n\tint rc;\n\tint stealth;\t\t\t\t// original state of Session.NetStealth flag\n\n\t//------------------------------------------------------------------------\n\t//\tInit network timing parameters; these values should work for both a\n\t// \"real\" network, and a simulated modem network (ie Kali)\n\t//------------------------------------------------------------------------\n\tIpx.Set_Timing (\t30, \t\t// retry 2 times per second\n\t\t\t\t\t\t\t-1, \t\t// ignore max retries\n\t\t\t\t\t\t\t600);\t\t// give up after 10 seconds\n\n\t//------------------------------------------------------------------------\n\t//\tSave the original value of the NetStealth flag, so we can turn stealth\n\t//\toff for now (during this portion of the dialogs, we must show ourselves)\n\t//------------------------------------------------------------------------\n\tstealth = Session.NetStealth;\n\tSession.NetStealth = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInit my game name to 0-length, since I haven't joined any game yet.\n\t//------------------------------------------------------------------------\n\tSession.GameName[0] = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tThe game is now \"open\" for joining.  Close it as soon as we exit this\n\t//\troutine.\n\t//------------------------------------------------------------------------\n\tSession.NetOpen = 1;\n\n\t//------------------------------------------------------------------------\n\t//\tKeep looping until something useful happens.\n\t//------------------------------------------------------------------------\n\twhile (1) {\n\t\t//.....................................................................\n\t\t//\tPop up the network Join/New dialog\n\t\t//.....................................................................\n\t\trc = Net_Join_Dialog();\n\n\t\t//.....................................................................\n\t\t//\t-1 = user selected Cancel\n\t\t//.....................................................................\n\t\tif (rc==-1) {\n\t\t\tSession.NetStealth = stealth;\n\t\t\tSession.NetOpen = 0;\n\t\t\treturn(false);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\t0 = user has joined an existing game; save values & return\n\t\t//.....................................................................\n\t\telse if (rc==0) {\n\t\t\tSession.Write_MultiPlayer_Settings ();\n\t\t\tSession.NetStealth = stealth;\n\t\t\tSession.NetOpen = 0;\n\n\t\t\treturn(true);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\t1 = user requests New Network Game\n\t\t//.....................................................................\n\t\telse if (rc==1) {\n\t\t\t//..................................................................\n\t\t\t//\tPop up the New Network Game dialog; if user selects OK, return\n\t\t\t//\t'true'; otherwise, return to the Join Dialog.\n\t\t\t//..................................................................\n\t\t\tif (Net_New_Dialog()) {\n\t\t\t\tSession.Write_MultiPlayer_Settings ();\n\t\t\t\tSession.NetStealth = stealth;\n\t\t\t\tSession.NetOpen = 0;\n\n\t\t\t\treturn(true);\n\t\t\t} else {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t}\n\n}\t/* end of Remote_Connect */\n\n\n\n/***********************************************************************************************\n * Net_Join_Dialog -- lets user join an existing game or start a new one                       *\n *                                                                                             *\n * This dialog displays an edit field for the player's name, and a list of all non-stealth-    *\n * mode games.  Clicking once on a game name displays a list of who's in that game.  Clicking  *\n * \"New\" takes the user to the Net_New dialog, where he waits for other users to join his      *\n * game.  All other input is done through this dialog.                                         *\n *                                                                                             *\n * The dialog has several \"states\":                                                            *\n *                                                                                             *\n *   1) Initially, it waits for the user to fill in his/her name and then to select Join or    *\n *      New; if New is selected, this dialog is exited.                                        *\n *                                                                                             *\n *   2) If Join is selected, the Join & New buttons are removed, but the Cancel button remains.*\n *      The join request is transmitted to the game's owner, and the message \"Waiting for      *\n *      Confirmation\" is displayed, until a confirmation or denial is received from the game's *\n *      owner.  The user may click Cancel at this point to cancel the join request.            *\n *      (Once Join is selected, the name editing field is disabled, and becomes a display-only *\n *      field.  If cancel is selected, it reappears as an edit field.) The user can still click*\n *      around & see who's in which games.                                                     *\n *                                                                                             *\n *   3) If the join request is denied, the dialog re-initializes to its pre-join state; the    *\n *      Join & New buttons reappear, & the Name field is available again.                      *\n *                                                                                             *\n *   4) If join confirmation is obtained, the message changes to show all the current game\t  *\n *      settings.  The user cannot click around & look at other games any more.\t\t\t\t\t  *\n *                                                                                             *\n * Any game running in Stealth mode won't show up on this dialog.                              *\n *                                                                                             *\n * The 'Players' vector matches one-for-one the contents of the list box.  The local system\t  *\n * is always listed first; the IPX Address of the local system will NOT be valid in the\t\t  *\n * Players vector.  The Games & Players vectors should be left filled in even after this\t\t  *\n * routine is exited; their contents are used to form connections to the other players,\t\t  *\n * after the scenario has been loaded.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * The 'Chat' vector contains the address of everyone who sends me a chat announcement.\t\t  *\n * The address field is used to send everyone my outgoing messages.  The LastTime\t\t\t\t  *\n * field is used as a timeout; if enough time goes by & we don't hear from this node,\t\t\t  *\n * we ping him, requesting a CHAT_ANNOUNCE if he's still in chat.  If we don't hear\t\t\t\t  *\n * from him after that, we remove him from our list.\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      -1 = cancel, 0 = OK, 1 = New net game requested                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nstatic int Net_Join_Dialog(void)\n{\n\t//------------------------------------------------------------------------\n\t//\tDialog & button dimensions\n\t//------------------------------------------------------------------------\n\t\tint d_dialog_w = 320 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\t\tint d_dialog_h = 200 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\t\tint d_dialog_x = ((320*RESFACTOR - d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\t\tint d_dialog_y = ((200*RESFACTOR - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\t\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\t\tint d_txt6_h = 6 *RESFACTOR+1;\t\t\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\t\tint d_margin1 = 17 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// large margin\n\t\tint d_margin2 = 7 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// small margin\n\n\t\tint d_name_w = 70 *RESFACTOR;\n\t\tint d_name_h = 9 *RESFACTOR;\n\t\tint d_name_x = d_dialog_x + (d_dialog_w / 4) - (d_name_w / 2);\n\t\tint d_name_y = d_dialog_y + d_margin2 + d_txt6_h + (2*RESFACTOR);\n\n#ifdef OLDWAY\n\t\tint d_gdi_w = 40 *RESFACTOR;\n\t\tint d_gdi_h = 9 *RESFACTOR;\n\t\tint d_gdi_x = d_dialog_cx - d_gdi_w;\n\t\tint d_gdi_y = d_name_y;\n\n\t\tint d_nod_w = 40 *RESFACTOR;\n\t\tint d_nod_h = 9 *RESFACTOR;\n\t\tint d_nod_x = d_dialog_cx;\n\t\tint d_nod_y = d_name_y;\n#else\n\t\tint d_house_w = 60 *RESFACTOR;\n\t\tint d_house_h = (8 * 5 *RESFACTOR);\n\t\tint d_house_x = d_dialog_cx - (d_house_w / 2);\n\t\tint d_house_y = d_name_y;\n#endif\n\n\t\tint d_color_w = 10 *RESFACTOR;\n\t\tint d_color_h = 9 *RESFACTOR;\n\t\tint d_color_y = d_name_y;\n\t\tint d_color_x = d_dialog_x + ((d_dialog_w / 4) * 3) - (d_color_w * 3);\n\n\t\tint d_gamelist_w = 155 *RESFACTOR;\n\t\tint d_gamelist_h = ((6 * 6) + 3) *RESFACTOR;\t\t// 6 rows high\n\t\tint d_gamelist_x = d_dialog_x + d_margin1 - 2*RESFACTOR;\n\t\tint d_gamelist_y = d_color_y + d_color_h + d_margin2 + 2*RESFACTOR/*KO + d_txt6_h + d_margin2*/;\n\n//BG\t\tint d_playerlist_w = 113 *RESFACTOR;\n\tint d_playerlist_w = 118 *RESFACTOR;\n\t\tint d_playerlist_h = ((6 * 6) + 3) *RESFACTOR;\t\t// 6 rows high\n\t\tint d_playerlist_x = d_dialog_x + d_dialog_w - (d_margin1 + d_playerlist_w - 2*RESFACTOR);\n\t\tint d_playerlist_y = d_color_y + d_color_h + d_margin2 + 2*RESFACTOR/*KO + d_txt6_h + d_margin2*/;\n\n\t\tint d_count_w = 25 *RESFACTOR;\n\t\tint d_count_h = d_txt6_h;\n\t\tint d_count_x = d_gamelist_x + (d_gamelist_w / 2);\n\t\tint d_count_y = d_gamelist_y + d_gamelist_h + d_margin2;\n\n\t\tint d_level_w = 25 *RESFACTOR;\n\t\tint d_level_h = d_txt6_h;\n\t\tint d_level_x = d_gamelist_x + (d_gamelist_w / 2);\n\t\tint d_level_y = d_count_y + d_count_h;\n\n\t\tint d_credits_w = 25 *RESFACTOR;\n\t\tint d_credits_h = d_txt6_h;\n\t\tint d_credits_x = d_gamelist_x + (d_gamelist_w / 2);\n\t\tint d_credits_y = d_level_y + d_level_h;\n\n\t\tint d_aiplayers_w = 25 *RESFACTOR;\n\t\tint d_aiplayers_h = d_txt6_h;\n\t\tint d_aiplayers_x = d_gamelist_x + (d_gamelist_w / 2);\n\t\tint d_aiplayers_y = d_credits_y + d_level_h;\n\n\t\tint d_options_w = d_playerlist_w;\n\t\tint d_options_h = ((5 * 6) + 4) *RESFACTOR;\n\t\tint d_options_x = d_playerlist_x;\n\t\tint d_options_y = d_playerlist_y + d_playerlist_h + d_margin2 - (2*RESFACTOR);\n\n\t\tint d_message1_w = d_dialog_w - (d_margin1 * 2) + 4*RESFACTOR;\n\t\tint d_message1_h = (14 * d_txt6_h) +3*RESFACTOR;\n\t\tint d_message1_x = d_dialog_x + (d_dialog_w-d_message1_w)/2;\n\t\tint d_message1_y = d_dialog_y + d_dialog_h - (27*RESFACTOR + d_message1_h);\n\n\t\tint d_message2_w = d_message1_w;\n\t\tint d_message2_h = (8 * d_txt6_h) + 3*RESFACTOR;\n\t\tint d_message2_x = d_message1_x;\n\t\tint d_message2_y = d_dialog_y + d_dialog_h - (27*RESFACTOR + d_message2_h);\n\n#ifdef FRENCH              //VG2\n\t\tint d_join_w = 60 *RESFACTOR;\n#else\n\t\tint d_join_w = 40 *RESFACTOR;\n#endif\n\t\tint d_join_h = 9 *RESFACTOR;\n\t\tint d_join_x = d_dialog_x + (d_dialog_w / 6) - (d_join_w / 2);\n\t\tint d_join_y = d_dialog_y + d_dialog_h - d_join_h - 8*RESFACTOR;\n\n\t\tint d_cancel_w = 50 *RESFACTOR;\n\t\tint d_cancel_h = 9 *RESFACTOR;\n\t\tint d_cancel_x = d_dialog_cx - d_cancel_w / 2;\n\t\tint d_cancel_y = d_join_y;\n\n#ifdef FRENCH\n\t\tint d_new_w = 60 *RESFACTOR;\n#else\n\t\tint d_new_w = 40 *RESFACTOR;\n#endif\n\t\tint d_new_h = 9 *RESFACTOR;\n\t\tint d_new_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_new_w / 2);\n\t\tint d_new_y = d_join_y;\n\n\t\tint d_send_w = d_message1_w;\n\t\tint d_send_h = 9 *RESFACTOR;\n\t\tint d_send_x = d_message1_x;\n\t\tint d_send_y = d_message1_y + d_message1_h;\n\n\n\t//------------------------------------------------------------------------\n\t//\tButton Enumerations\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tBUTTON_NAME = 100,\n#ifdef OLDWAY\n\t\tBUTTON_GDI,\n\t\tBUTTON_NOD,\n#else\n\t\tBUTTON_HOUSE,\n#endif\n\t\tBUTTON_GAMELIST,\n\t\tBUTTON_PLAYERLIST,\n\t\tBUTTON_JOIN,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_NEW,\n\t\tBUTTON_COUNT,\n\t\tBUTTON_LEVEL,\n\t\tBUTTON_CREDITS,\n\t\tBUTTON_AI_PLAYERS,\n\t\tBUTTON_OPTIONS,\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t//------------------------------------------------------------------------\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PARMS,\n\t\tREDRAW_MESSAGE,\n\t\tREDRAW_COLORS,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t//------------------------------------------------------------------------\n\t//\tDialog variables\n\t//------------------------------------------------------------------------\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\tint cbox_x[] = {\n\t\t\t\t\t\t\td_color_x,\n\t\t\t\t\t\t\td_color_x + d_color_w,\n\t\t\t\t\t\t\td_color_x + (d_color_w * 2),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 3),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 4),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 5),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 6),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 7),\n\t\t\t\t\t\t\t};\n\tchar housetext[25] = \"\";\t\t\t\t// buffer for house droplist\n\tint isdropped = 0;\n\n\tJoinStateType joinstate = JOIN_NOTHING;\t// current \"state\" of this dialog\n\tchar namebuf[MPLAYER_NAME_MAX] = {0};\t\t// buffer for player's name\n\tint playertabs[] = {71 *RESFACTOR};\t\t\t\t// tabs for player list box\n\tint optiontabs[] = {8};\t\t\t\t\t// tabs for player list box\n\tint game_index = -1;\t\t\t\t\t\t// index of currently-selected game\n\tint join_index = -1;\t\t\t\t\t\t// index of game we're joining\n\tint rc = 0;\t\t\t\t\t\t\t\t\t// -1 = user cancelled, 1 = New\n\tJoinEventType event;\t\t\t\t\t\t// event from incoming packet\n\tint i;\t\t\t\t\t\t\t\t\t\t// loop counter\n\tchar txt[128];\n\tchar const *p;\n\tint parms_received = 0;\t\t\t\t\t// 1 = game options received\n\tint found;\n\tNodeNameType *who;\t\t\t\t\t\t// node to add to Players\n\tRejectType why;\t\t\t\t\t\t\t// reason for rejection\n\tTTimerClass<SystemTimerClass> lastclick_timer;\t\t\t// time b/w send periods\n\tint lastclick_idx = 0;\t\t\t\t\t// index of item last clicked on\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\tSession.Options.ScenarioDescription[0] = 0;\t//Flag that we dont know the scenario name yet\n\n\tchar * item;\n\tunsigned long starttime;\n\tint load_game = 0;\t\t\t\t\t\t// 1 = load saved game\n\tint goto_lobby;\n\tbool messages_have_focus = true;\t\t// Gadget focus starts on the message system\n\n\t//------------------------------------------------------------------------\n\t//\tButtons\n\t//------------------------------------------------------------------------\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tEditClass name_edt(BUTTON_NAME, namebuf, MPLAYER_NAME_MAX, TPF_TEXT,\n\t\td_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC);\n\n#ifdef OLDWAY\n\tTextButtonClass gdibtn(BUTTON_GDI, TXT_ALLIES, TPF_BUTTON, d_gdi_x, d_gdi_y, d_gdi_w);\n\tTextButtonClass nodbtn(BUTTON_NOD, TXT_SOVIET, TPF_BUTTON, d_nod_x, d_nod_y, d_nod_w);\n#else\n\tFancy_Text_Print(\"\", 0, 0, 0, 0, TPF_TEXT);\n\tDropListClass housebtn(BUTTON_HOUSE, housetext, sizeof(housetext),\n\t\tTPF_TEXT,\n\t\td_house_x, d_house_y, d_house_w, d_house_h,\n\t\tMFCD::Retrieve(\"BTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"BTN-DN.SHP\"));\n#endif\n\n\tListClass gamelist(BUTTON_GAMELIST, d_gamelist_x, d_gamelist_y, d_gamelist_w, d_gamelist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tTextButtonClass joinbtn(BUTTON_JOIN, TXT_JOIN, TPF_BUTTON, d_join_x, d_join_y, d_join_w);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w);\n\tTextButtonClass newbtn(BUTTON_NEW, TXT_NEW, TPF_BUTTON, d_new_x, d_new_y, d_new_w);\n\tGaugeClass countgauge(BUTTON_COUNT, d_count_x, d_count_y, d_count_w, d_count_h);\n\tGaugeClass levelgauge(BUTTON_LEVEL, d_level_x, d_level_y, d_level_w, d_level_h);\n\tGaugeClass creditsgauge(BUTTON_CREDITS, d_credits_x, d_credits_y, d_credits_w, d_credits_h);\n\tGaugeClass aiplayersgauge(BUTTON_AI_PLAYERS, d_aiplayers_x, d_aiplayers_y, d_aiplayers_w, d_aiplayers_h);\n\tCheckListClass optionlist(BUTTON_OPTIONS, d_options_x, d_options_y, d_options_w, d_options_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tStaticButtonClass descrip(0, \"\", TPF_CENTER|TPF_TEXT, d_dialog_x + 16*RESFACTOR, d_name_y, d_dialog_w - 32*RESFACTOR, d_txt6_h+1);\n\tStaticButtonClass staticcount(0, \"     \", TPF_TEXT, d_count_x + d_count_w + 2*RESFACTOR, d_count_y);\n\tStaticButtonClass staticlevel(0, \"     \", TPF_TEXT, d_level_x + d_level_w + 2*RESFACTOR, d_level_y);\n\tStaticButtonClass staticcredits(0, \"          \", TPF_TEXT, d_credits_x + d_credits_w + 2*RESFACTOR, d_credits_y);\n\tStaticButtonClass staticaiplayers(0, \"     \", TPF_TEXT, d_aiplayers_x + d_aiplayers_w + 2*RESFACTOR, d_aiplayers_y);\n\n\t//------------------------------------------------------------------------\n\t//\tInit the button states\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t// Name & Color\n\t//........................................................................\n\tSession.ColorIdx = Session.PrefColor;\t\t\t// init my preferred color\n\tstrcpy (namebuf, Session.Handle);\t\t\t\t// set my name\n\tname_edt.Set_Text(namebuf,MPLAYER_NAME_MAX);\n\tif (Session.ColorIdx == PCOLOR_DIALOG_BLUE) {\n\t\tname_edt.Set_Color(&ColorRemaps[PCOLOR_REALLY_BLUE]);\n\t} else {\n\t\tname_edt.Set_Color(&ColorRemaps[Session.ColorIdx]);\n\t}\n\n\t//........................................................................\n\t// List boxes\n\t//........................................................................\n\tplayerlist.Set_Tabs(playertabs);\n\tplayerlist.Set_Selected_Style(ColorListClass::SELECT_NORMAL);\n\n\toptionlist.Set_Tabs(optiontabs);\n\toptionlist.Set_Read_Only(1);\n\n\toptionlist.Add_Item(Text_String(TXT_BASES));\n\toptionlist.Add_Item(Text_String(TXT_ORE_SPREADS));\n\toptionlist.Add_Item(Text_String(TXT_CRATES));\n\toptionlist.Add_Item(Text_String(TXT_CAPTURE_THE_FLAG));\n\toptionlist.Add_Item(Text_String(TXT_SHADOW_REGROWS));\n\n\toptionlist.Check_Item(0, Rule.IsMPBasesOn);\n\toptionlist.Check_Item(1, Rule.IsMPTiberiumGrow);\n\toptionlist.Check_Item(2, Rule.IsMPCrates);\n\toptionlist.Check_Item(3, Rule.IsMPCaptureTheFlag);\n\toptionlist.Check_Item(4, Rule.IsMPShadowGrow);\n\n\t//........................................................................\n\t// House buttons\n\t//........................................................................\n#ifdef OLDWAY\n\tif (Session.House==HOUSE_GOOD) {\n\t\tgdibtn.Turn_On();\n\t} else {\n\t\tnodbtn.Turn_On();\n\t}\n#else\n\tfor (HousesType house = HOUSE_USSR; house <= HOUSE_FRANCE; house++) {\n//\tfor (HousesType house = HOUSE_FIRST; house <= HOUSE_TURKEY; house++) {\n\t\thousebtn.Add_Item(Text_String(HouseTypeClass::As_Reference(house).Full_Name()));\n\t}\n\thousebtn.Set_Selected_Index(Session.House - HOUSE_USSR);\n\thousebtn.Set_Read_Only (true);\n#endif\n\n\t//........................................................................\n\t// Option gauges\n\t//........................................................................\n\tcountgauge.Use_Thumb(0);\n\tcountgauge.Set_Maximum(SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]);\n\tcountgauge.Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]);\n\n\tlevelgauge.Use_Thumb(0);\n\tlevelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1);\n\tlevelgauge.Set_Value(BuildLevel - 1);\n\n\tcreditsgauge.Use_Thumb(0);\n\tcreditsgauge.Set_Maximum(Rule.MPMaxMoney);\n\tcreditsgauge.Set_Value(Session.Options.Credits);\n\n\taiplayersgauge.Use_Thumb(0);\n\taiplayersgauge.Set_Maximum(Session.Options.AIPlayers);\n\taiplayersgauge.Set_Value(Session.Options.AIPlayers);\n\n\tFancy_Text_Print(\"\", 0, 0, scheme, TBLACK, TPF_TEXT);\n\n\tSession.Messages.Init (d_message1_x + 1 *RESFACTOR, d_message1_y + 1 *RESFACTOR, 14,\n\t\tMAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 *RESFACTOR, d_send_y + 1 *RESFACTOR, 1,\n\t\t20, MAX_MESSAGE_LENGTH - 5, d_message2_w);\n\tSession.Messages.Add_Edit ((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message2_w);\n\tSession.WWChat = 0;\n\n\tlastclick_timer = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tClear the list of games, players, and the chat list\n\t//------------------------------------------------------------------------\n\tClear_Vector(&Session.Games);\n\tClear_Vector(&Session.Players);\n\tClear_Vector(&Session.Chat);\n\n\t//------------------------------------------------------------------------\n\t// Add myself to the Chat vector\n\t//------------------------------------------------------------------------\n\twho = new NodeNameType;\n\tstrcpy(who->Name, namebuf);\n\twho->Chat.LastTime = 0;\n\twho->Chat.LastChance = 0;\n\twho->Chat.Color = Session.GPacket.Chat.Color;\n\tSession.Chat.Add (who);\n\n\t//------------------------------------------------------------------------\n\t// Create the \"Lobby\" game name on the games list, and create a bogus\n\t// node for the gamelist, so Games[i] will always match gamelist[i]\n\t//------------------------------------------------------------------------\n\twho = new NodeNameType;\n\tstrcpy(who->Name, \"\");\n\twho->Game.IsOpen = 0;\n\twho->Game.LastTime = 0;\n\tSession.Games.Add (who);\n\titem = new char [MPLAYER_NAME_MAX];\n\tstrcpy(item, Text_String(TXT_LOBBY));\n\tgamelist.Add_Item(item);\n\tgamelist.Set_Selected_Index(0);\n\tgame_index = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tSend game-name query & chat announcement; also, initialize timers.\n\t//------------------------------------------------------------------------\n\tSend_Join_Queries (game_index, joinstate, 1, 0, 1, namebuf, 1);\n\tLoad_Title_Page(true);\n\tCCPalette.Set();\t//GamePalette.Set();\n\n\t//------------------------------------------------------------------------\n\t//\tInit Mono Output\n\t//------------------------------------------------------------------------\n\t#if(SHOW_MONO)\n \tIpx.Configure_Debug(-1, sizeof (GlobalHeaderType), sizeof(NetCommandType), GlobalPacketNames, 0, 13);\n\tIpx.Mono_Debug_Print(-1,1);\n\t#endif\n#ifdef WIN32\n//char *fred;\n#endif\n\t//------------------------------------------------------------------------\n\t//\tProcessing loop\n\t//------------------------------------------------------------------------\n\twhile (process) {\n\t\t#if(SHOW_MONO)\n\t\tIpx.Mono_Debug_Print(-1,0);\n\t\t#endif\n\n\t\t/*\n\t\t** Kludge to make sure we redraw the message input line when it loses focus.\n\t\t** If we dont do this then the cursor doesnt disappear.\n\t\t*/\n\t\tif (messages_have_focus) {\n\t\t\tif (name_edt.Has_Focus()) {\n\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\tmessages_have_focus = false;\n\t\t\t}\n\t\t} else {\n\t\t\tif (!name_edt.Has_Focus()) {\n\t\t\t\tmessages_have_focus = true;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Collapse the country list if we are going to redraw the game list\n\t\t*/\n\t\tif (gamelist.Is_To_Redraw() && housebtn.IsDropped) {\n\t\t\thousebtn.Collapse();\n\t\t\tif (display < REDRAW_BACKGROUND) display = REDRAW_BACKGROUND;\n\t\t}\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\t#endif\n\t\t//.....................................................................\n\t\t//\tRefresh display if needed\n\t\t//.....................................................................\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw backgound & dialog box\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\thousebtn.Collapse();\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tDialog & Field labels\n\t\t\t\t//...............................................................\n\t\t\t\tFancy_Text_Print(TXT_CHANNEL_GAMES, d_gamelist_x + (d_gamelist_w / 2), d_gamelist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\tFancy_Text_Print(TXT_PLAYERS, d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\n\t\t\t\t//...............................................................\n\t\t\t\t// For game-browsing, label the name, side, & color buttons:\n\t\t\t\t//...............................................................\n\t\t\t\tif (joinstate < JOIN_CONFIRMED) {\n\t\t\t\t\tFancy_Text_Print(TXT_YOUR_NAME, d_name_x + (d_name_w / 2), d_name_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\n#ifdef OLDWAY\n\t\t\t\t\tFancy_Text_Print(TXT_SIDE_COLON,\n\t\t\t\t\t\td_gdi_x + d_gdi_w,\n\t\t\t\t\t\td_gdi_y - d_txt6_h,\n\t\t\t\t\t\tscheme, TBLACK,\n\t\t\t\t\t\tTPF_CENTER | TPF_TEXT);\n#else\n\t\t\t\t\tFancy_Text_Print(TXT_SIDE_COLON,\n\t\t\t\t\t\td_house_x + (d_house_w / 2),\n\t\t\t\t\t\td_house_y - d_txt6_h,\n\t\t\t\t\t\tscheme, TBLACK,\n\t\t\t\t\t\tTPF_CENTER | TPF_TEXT);\n#endif\n\n\t\t\t\t\tFancy_Text_Print(TXT_COLOR_COLON,\n\t\t\t\t\t\td_dialog_x + ((d_dialog_w / 4) * 3),\n\t\t\t\t\t\td_color_y - d_txt6_h,\n\t\t\t\t\t\tscheme, TBLACK,\n\t\t\t\t\t\tTPF_CENTER | TPF_TEXT);\n\t\t\t\t} else {\n\t\t\t\t\t//...............................................................\n\t\t\t\t\t// If we're joined to a game, just print the player's name & side.\n\t\t\t\t\t//...............................................................\n#ifdef OLDWAY\n\t\t\t\t\tif (Session.House==HOUSE_GOOD) {\n\t\t\t\t\t\tsprintf(txt,Text_String(TXT_S_PLAYING_S),namebuf, Text_String(TXT_ALLIES));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsprintf(txt,Text_String(TXT_S_PLAYING_S),namebuf, Text_String(TXT_SOVIET));\n\t\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\t\tsprintf (txt, Text_String(TXT_S_PLAYING_S), namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\t\t\t\t\tFancy_Text_Print(txt,d_dialog_cx, d_dialog_y + d_margin2 + (1*RESFACTOR),\n\t\t\t\t\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx],\n\t\t\t\t\t\tTBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tRebuild the button list\n\t\t\t\t//...............................................................\n\t\t\t\tcancelbtn.Zap();\n\t\t\t\tgamelist.Zap();\n\t\t\t\tplayerlist.Zap();\n#ifdef OLDWAY\n\t\t\t\tgdibtn.Zap();\n\t\t\t\tnodbtn.Zap();\n#else\n\t\t\t\thousebtn.Zap();\n#endif\n\t\t\t\tname_edt.Zap();\n\t\t\t\tjoinbtn.Zap();\n\t\t\t\tnewbtn.Zap();\n\t\t\t\tcountgauge.Zap();\n\t\t\t\tlevelgauge.Zap();\n\t\t\t\tcreditsgauge.Zap();\n\t\t\t\taiplayersgauge.Zap();\n\t\t\t\tstaticcount.Zap();\n\t\t\t\tstaticlevel.Zap();\n\t\t\t\tstaticcredits.Zap();\n\t\t\t\tstaticaiplayers.Zap();\n\n\t\t\t\tcommands = &cancelbtn;\n\t\t\t\tgamelist.Add_Tail(*commands);\n\t\t\t\tplayerlist.Add_Tail(*commands);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tOnly add the name edit field, the House, Join & New buttons if\n\t\t\t\t//\twe're doing nothing, or we've just been rejected.\n\t\t\t\t//...............................................................\n\t\t\t\tif (joinstate < JOIN_CONFIRMED) {\n#ifdef OLDWAY\n\t\t\t\t\tgdibtn.Add_Tail(*commands);\n\t\t\t\t\tnodbtn.Add_Tail(*commands);\n#else\n\t\t\t\t\thousebtn.Add_Tail(*commands);\n#endif\n\t\t\t\t\tname_edt.Add_Tail(*commands);\n\t\t\t\t\tjoinbtn.Add_Tail(*commands);\n\t\t\t\t\tnewbtn.Add_Tail(*commands);\n\t\t\t\t} else {\n\t\t\t\t\tcountgauge.Add_Tail(*commands);\n\t\t\t\t\tlevelgauge.Add_Tail(*commands);\n\t\t\t\t\tcreditsgauge.Add_Tail(*commands);\n\t\t\t\t\taiplayersgauge.Add_Tail(*commands);\n\t\t\t\t\tstaticcount.Add_Tail(*commands);\n\t\t\t\t\tstaticlevel.Add_Tail(*commands);\n\t\t\t\t\tstaticcredits.Add_Tail(*commands);\n\t\t\t\t\tstaticaiplayers.Add_Tail(*commands);\n\t\t\t\t\toptionlist.Add_Tail(*commands);\n\t\t\t\t\tdescrip.Add_Tail(*commands);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw buttons\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\taiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count());\n\t\t\t\tif (Session.Options.AIPlayers > Rule.MaxPlayers-Session.Players.Count()) {\n\t\t\t\t\taiplayersgauge.Set_Value(Rule.MaxPlayers-Session.Players.Count());\n\t\t\t\t}\n\t\t\t\tcommands->Draw_All();\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tDraw the color boxes\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_COLORS && joinstate < JOIN_CONFIRMED) {\n\t\t\t\tfor (i = 0; i < MAX_MPLAYER_COLORS; i++) {\n\t\t\t\t\tLogicPage->Fill_Rect (cbox_x[i] + 1, d_color_y + 1,\n\t\t\t\t\t\tcbox_x[i] + 1 + d_color_w - 2 *RESFACTOR, d_color_y + 1 + d_color_h - 2,\n\t\t\t\t\t\tColorRemaps[i].Box);\n//\t\t\t\t\t\t(i == PCOLOR_DIALOG_BLUE) ? ColorRemaps[PCOLOR_REALLY_BLUE].Box : ColorRemaps[i].Box);\n\n\t\t\t\t\tif (i == Session.ColorIdx) {\n\t\t\t\t\t\tDraw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_DOWN, false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tDraw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_RAISED, false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// Draw the message system; erase old messages first\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_MESSAGE) {\n\t\t\t\tif (joinstate==JOIN_CONFIRMED) {\n\t\t\t\t\tDraw_Box(d_message2_x, d_message2_y, d_message2_w, d_message2_h, BOXSTYLE_BOX, true);\n\t\t\t\t} else {\n\t\t\t\t\tDraw_Box(d_message1_x, d_message1_y, d_message1_w, d_message1_h, BOXSTYLE_BOX, true);\n\t\t\t\t}\n\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true);\n\t\t\t\tSession.Messages.Draw();\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// Redraw the game options\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_PARMS && parms_received && joinstate >= JOIN_CONFIRMED) {\n\n\t\t\t\t//...............................................................\n\t\t\t\t// Scenario title\n\t\t\t\t//...............................................................\n//\t\t\t\tLogicPage->Fill_Rect(d_dialog_x + 16 *RESFACTOR, d_name_y, d_dialog_x + d_dialog_w - 16 *RESFACTOR, d_name_y + d_txt6_h, BLACK);\n\n\t\t\t\tp = Text_String(TXT_SCENARIO_COLON);\n\t\t\t\tif (Session.Options.ScenarioDescription[0]) {\n\n\t\t\t\t\t// EW - Scenario language translation goes here!!!!!!!! VG\n\t\t\t\t\tfor (int ii = 0; EngMisStr[ii] != NULL;  ii++) {\n\t\t\t\t\t\tif (!strcmp(Session.Options.ScenarioDescription, EngMisStr[ii])) {\n\t\t\t\t\t\t\t#if defined(GERMAN) || defined(FRENCH)\n\t\t\t\t\t\t\t\tsprintf(txt, \"%s %s\", p, EngMisStr[ii+1]);\n\t\t\t\t\t\t\t#else\n\t\t\t\t\t\t\t\tsprintf(txt, \"%s %s\", p, Session.Options.ScenarioDescription);\n\t\t\t\t\t\t\t#endif\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (EngMisStr[ii] == NULL) {\n\t\t\t\t\t\tsprintf(txt, \"%s %s\", p, Session.Options.ScenarioDescription);\n\t\t\t\t\t}\n\t\t\t\t\tdescrip.Set_Text(txt);\n\n//\t\t\t\t\tsprintf(txt, \"%s %s\", p, Session.Options.ScenarioDescription);\n//\t\t\t\t\tdescrip.Set_Text(txt);\n//\t\t\t\t\tFancy_Text_Print(\"%s %s\", d_dialog_cx, d_name_y, scheme, BLACK, TPF_TEXT | TPF_CENTER, p, Session.Options.ScenarioDescription);\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(txt, \"%s %s\", p, Text_String(TXT_NOT_FOUND));\n\t\t\t\t\tdescrip.Set_Text(txt);\n//\t\t\t\t\tFancy_Text_Print(\"%s %s\", d_dialog_cx, d_name_y, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_TEXT | TPF_CENTER, p, Text_String(TXT_NOT_FOUND));\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t// Unit count, tech level, credits, ai players\n\t\t\t\t//...............................................................\n//\t\t\t\tLogicPage->Fill_Rect(d_count_x + d_count_w + 2 *RESFACTOR, d_count_y, d_count_x + d_count_w + 35 *RESFACTOR, d_aiplayers_y + d_aiplayers_h+RESFACTOR, BLACK);\n\n\t\t\t\tFancy_Text_Print(TXT_COUNT, d_count_x - 2 *RESFACTOR, d_count_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\n\t\t\t\tsprintf(txt,\"%d\",Session.Options.UnitCount);\n\t\t\t\tstaticcount.Set_Text(txt);\n\t\t\t\tstaticcount.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_count_x + d_count_w + 2 *RESFACTOR, d_count_y, scheme, BLACK, TPF_TEXT);\n\n\t\t\t\tFancy_Text_Print(TXT_LEVEL, d_level_x - 2 *RESFACTOR, d_level_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tif (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {\n\t\t\t\t\tsprintf(txt,\"%d\",BuildLevel);\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(txt, \"**\");\n\t\t\t\t}\n\t\t\t\tstaticlevel.Set_Text(txt);\n\t\t\t\tstaticlevel.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_level_x + d_level_w + 2 *RESFACTOR, d_level_y, scheme, BLACK, TPF_TEXT);\n\n\t\t\t\tFancy_Text_Print(TXT_CREDITS_COLON, d_credits_x - 2 *RESFACTOR, d_credits_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tsprintf(txt,\"%d\",Session.Options.Credits);\n\t\t\t\tstaticcredits.Set_Text(txt);\n\t\t\t\tstaticcredits.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_credits_x + d_credits_w + 2 *RESFACTOR, d_credits_y, scheme, BLACK, TPF_TEXT);\n\n\t\t\t\tFancy_Text_Print(TXT_AI_PLAYERS_COLON, d_aiplayers_x - 2 * RESFACTOR, d_aiplayers_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tsprintf(txt,\"%d\",Session.Options.AIPlayers);\n\t\t\t\tstaticaiplayers.Set_Text(txt);\n\t\t\t\tstaticaiplayers.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_aiplayers_x + d_aiplayers_w + 2 *RESFACTOR, d_aiplayers_y, scheme, BLACK, TPF_TEXT);\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tGet user input\n\t\t//.....................................................................\n\t\tinput = commands->Input();\n\n\t\tif (input & KN_BUTTON) {\n\t\t\thousebtn.Collapse();\n\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tProcess input\n\t\t//.....................................................................\n\t\tswitch (input) {\n\n\t\t\t//..................................................................\n\t\t\t// Mouse Click:\n\t\t\t// If we're joined to a game, display an error if the user tries to\n\t\t\t// modify a read-only control.\n\t\t\t// If user clicks on a color button:\n\t\t\t//\t- If we've joined a game, don't allow a new color selection\n\t\t\t//\t- otherwise, select that color\n\t\t\t// - Change the color of the user's name & message field to match\n\t\t\t//   the newly-selected color.\n\t\t\t//..................................................................\n\t\t\tcase KN_LMOUSE:\n\t\t\t\tif (joinstate > JOIN_NOTHING) {\n\t\t\t\t\tif ( (Get_Mouse_X() >= d_count_x &&\n\t\t\t\t\t\tGet_Mouse_X() <= d_count_x + d_count_w &&\n\t\t\t\t\t\tGet_Mouse_Y() >= d_count_y &&\n\t\t\t\t\t\tGet_Mouse_Y() <= d_aiplayers_y + d_aiplayers_h) ||\n\t\t\t\t\t\t(Get_Mouse_X() >= d_options_x &&\n\t\t\t\t\t\tGet_Mouse_X() <= d_options_x + d_options_w &&\n\t\t\t\t\t\tGet_Mouse_Y() >= d_options_y &&\n\t\t\t\t\t\tGet_Mouse_Y() <= d_options_y + d_options_h) ) {\n\t\t\t\t\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_ONLY_HOST_CAN_MODIFY), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (Keyboard->MouseQX > cbox_x[0] &&\n\t\t\t\t\tKeyboard->MouseQX < (cbox_x[MAX_MPLAYER_COLORS - 1] + d_color_w) &&\n\t\t\t\t\tKeyboard->MouseQY > d_color_y &&\n\t\t\t\t\tKeyboard->MouseQY < (d_color_y + d_color_h)) {\n\t\t\t\t\t\tSession.PrefColor = (PlayerColorType)\n\t\t\t\t\t\t\t((Keyboard->MouseQX - cbox_x[0]) / d_color_w);\n\t\t\t\t\t\tSession.ColorIdx = Session.PrefColor;\n\n\t\t\t\t\t\tif (Session.ColorIdx == PCOLOR_DIALOG_BLUE) {\n\t\t\t\t\t\t\tname_edt.Set_Color (&ColorRemaps[PCOLOR_REALLY_BLUE]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname_edt.Set_Color (&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tname_edt.Flag_To_Redraw();\n\n\t\t\t\t\t\tSession.Messages.Set_Edit_Color((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx);\n\n\t\t\t\t\t\tdisplay = REDRAW_COLORS;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tUser clicks on the game list:\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_GAMELIST | KN_BUTTON):\n\t\t\t\t//...............................................................\n\t\t\t\t// Handle a double-click\n\t\t\t\t//...............................................................\n\t\t\t\tif (lastclick_timer < 30 && gamelist.Current_Index() == lastclick_idx) {\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// If we're in a game, & the item clicked on is a different\n\t\t\t\t\t// game, un-join the game we're in.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tif ((joinstate==JOIN_CONFIRMED || joinstate==JOIN_WAIT_CONFIRM) &&\n\t\t\t\t\t\tlastclick_idx != game_index) {\n\t\t\t\t\t\tif (gamelist.Current_Index() == 0) {\n\t\t\t\t\t\t\tgoto_lobby = 1;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tgoto_lobby = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tUnjoin_Game(namebuf, joinstate, &gamelist, &playerlist,\n\t\t\t\t\t\t\tgame_index, goto_lobby, d_message1_x, d_message1_y, d_txt6_h,\n\t\t\t\t\t\t\td_send_x, d_send_y, MAX_MESSAGE_LENGTH);\n\t\t\t\t\t\tjoinstate = JOIN_NOTHING;\n\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// Clear the Player vector & the player list box, since\n\t\t\t\t\t\t// our game_index has changed.\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\tClear_Listbox (&playerlist);\n\t\t\t\t\t\tClear_Vector (&Session.Players);\n\t\t\t\t\t\tgame_index = gamelist.Current_Index();\n\t\t\t\t\t}\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// If we clicked on another game, join that game.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tif (joinstate != JOIN_CONFIRMED &&\n\t\t\t\t\t\tjoinstate != JOIN_WAIT_CONFIRM && lastclick_idx > 0) {\n\t\t\t\t\t\tgamelist.Set_Selected_Index(lastclick_idx);\n\t\t\t\t\t\tgame_index = lastclick_idx;\n\t\t\t\t\t\tname_edt.Clear_Focus();\n\t\t\t\t\t\tname_edt.Flag_To_Redraw();\n\t\t\t\t\t\tstrcpy (Session.Handle,namebuf);\n#ifndef OLDWAY\n\t\t\t\t\t\tSession.House = (HousesType)(housebtn.Current_Index()+HOUSE_USSR);\n#endif\n\t\t\t\t\t\tjoin_index = gamelist.Current_Index();\n\t\t\t\t\t\tparms_received = 0;\n\t\t\t\t\t\tif (Request_To_Join (namebuf, join_index, Session.House,\n\t\t\t\t\t\t\tSession.ColorIdx)) {\n\t\t\t\t\t\t\tjoinstate = JOIN_WAIT_CONFIRM;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// Otherwise, we must have joined the lobby\n\t\t\t\t\t//............................................................\n\t\t\t\t\tif (game_index == 0) {\n\t\t\t\t\t\tClear_Listbox (&playerlist);\n\t\t\t\t\t\tSession.Messages.Init (d_message1_x + 1 *RESFACTOR, d_message1_y + 1 *RESFACTOR, 14,\n\t\t\t\t\t\t\tMAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 *RESFACTOR, d_send_y + 1 *RESFACTOR, 1,\n\t\t\t\t\t\t\t20, MAX_MESSAGE_LENGTH - 5, d_message2_w);\n\t\t\t\t\t\tSession.Messages.Add_Edit ((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t TPF_TEXT, NULL, '_', d_message2_w);\n\t\t\t\t\t\tSession.WWChat = 0;\n\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t//...............................................................\n\t\t\t\t// Handle a single-click\n\t\t\t\t//...............................................................\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// If no double-click occurred, set the last-clicked index\n\t\t\t\t\t// & double-click timer.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tlastclick_timer = 0;\n\t\t\t\t\tlastclick_idx = gamelist.Current_Index();\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tIf we've joined a game, don't allow the selected item to\n\t\t\t\t\t// change\n\t\t\t\t\t//............................................................\n\t\t\t\t\tif (joinstate==JOIN_CONFIRMED || joinstate==JOIN_WAIT_CONFIRM) {\n\t\t\t\t\t\tgamelist.Set_Selected_Index(game_index);\n\t\t\t\t\t}\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// If we're not in a game, and the user clicks on a different\n\t\t\t\t\t// entry, clear the player list & send a player query;\n\t\t\t\t\t// init the click timer, to detect a double-click of this item.\n\t\t\t\t\t//............................................................\n\t\t\t\t\telse if (gamelist.Current_Index() != game_index) {\n\n\t\t\t\t\t\tClear_Listbox (&playerlist);\n\t\t\t\t\t\tClear_Vector (&Session.Players);\n\t\t\t\t\t\tgame_index = gamelist.Current_Index();\n\t\t\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n#ifdef OLDWAY\n\t\t\t//..................................................................\n\t\t\t//\tHouse Buttons: set the player's desired House\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_GDI | KN_BUTTON):\n\t\t\t\tSession.House = HOUSE_GOOD;\n\t\t\t\tgdibtn.Turn_On();\n\t\t\t\tnodbtn.Turn_Off();\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_NOD | KN_BUTTON):\n\t\t\t\tSession.House = HOUSE_BAD;\n\t\t\t\tgdibtn.Turn_Off();\n\t\t\t\tnodbtn.Turn_On();\n\t\t\t\tbreak;\n#else\n#endif\n\n\t\t\t//..................................................................\n\t\t\t//\tJOIN: send a join request packet & switch to waiting-for-\n\t\t\t// confirmation mode.\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_JOIN | KN_BUTTON):\n\t\t\t\tname_edt.Clear_Focus();\n\t\t\t\tname_edt.Flag_To_Redraw();\n\t\t\t\tstrcpy (Session.Handle,namebuf);\n#ifndef OLDWAY\n\t\t\t\tSession.House = (HousesType)(housebtn.Current_Index()+HOUSE_USSR);\n#endif\n\t\t\t\tjoin_index = gamelist.Current_Index();\n\t\t\t\tparms_received = 0;\n\t\t\t\tif (Request_To_Join (namebuf, join_index, Session.House,\n\t\t\t\t\tSession.ColorIdx)) {\n\t\t\t\t\tjoinstate = JOIN_WAIT_CONFIRM;\n\t\t\t\t} else {\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t// ESC / CANCEL: send a SIGN_OFF\n\t\t\t// - If we're part of a game, stay in this dialog; otherwise, exit\n\t\t\t//..................................................................\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf we're joined to a game, make extra sure the other players in\n\t\t\t\t//\tthat game know I'm exiting; send my SIGN_OFF as an ack-required\n\t\t\t\t//\tpacket.  Don't send this to myself (index 0).\n\t\t\t\t//...............................................................\n\t\t\t\tif (joinstate == JOIN_CONFIRMED) {\n\t\t\t\t\tUnjoin_Game(namebuf, joinstate, &gamelist, &playerlist,\n\t\t\t\t\t\tgame_index, 1, d_message1_x, d_message1_y, d_txt6_h, d_send_x,\n\t\t\t\t\t\td_send_y, MAX_MESSAGE_LENGTH);\n\t\t\t\t\tjoinstate = JOIN_NOTHING;\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t} else {\n\t\t\t\t//...............................................................\n\t\t\t\t// If I'm not joined to a game, send a SIGN_OFF to all players\n\t\t\t\t// in my Chat vector (but not to myself, index 0)\n\t\t\t\t//...............................................................\n\t\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\t\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\t\t\t\tstrcpy(Session.GPacket.Name,namebuf);\n\t\t\t\t\tfor (i = 1; i < Session.Chat.Count(); i++) {\n\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 1, &(Session.Chat[i]->Address));\n\t\t\t\t\t\tIpx.Service();\n\t\t\t\t\t}\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tNow broadcast a SIGN_OFF just to be thorough\n\t\t\t\t\t//............................................................\n\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\tsizeof (GlobalPacketType), 0, NULL);\n\t\t\t\t\tif (Session.IsBridge) {\n\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\t\tsizeof(GlobalPacketType), 0, &Session.BridgeNet);\n\t\t\t\t\t}\n\n\t\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// exit the dialog\n\t\t\t\t\t//............................................................\n\t\t\t\t\tprocess = false;\n\t\t\t\t\trc = -1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tNEW: bail out with return code 1\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_NEW | KN_BUTTON):\n\t\t\t\t//...............................................................\n\t\t\t\t//\tForce user to enter a name\n\t\t\t\t//...............................................................\n\t\t\t\tif (strlen(namebuf)==0) {\n\t\t\t\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_NAME_ERROR), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tEnsure name is unique\n\t\t\t\t//...............................................................\n\t\t\t\tfound = 0;\n\t\t\t\tfor (i = 1; i < Session.Games.Count(); i++) {\n\t\t\t\t\tif (!stricmp(Session.Games[i]->Name, namebuf)) {\n\t\t\t\t\t\tfound = 1;\n\t\t\t\t\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_GAMENAME_MUSTBE_UNIQUE), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (found) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tSave player & game name\n\t\t\t\t//...............................................................\n\t\t\t\tstrcpy(Session.Handle,namebuf);\n\t\t\t\tstrcpy(Session.GameName,namebuf);\n#ifndef OLDWAY\n\t\t\t\tSession.House = (HousesType)(housebtn.Current_Index()+HOUSE_USSR);\n#endif\n\n\t\t\t\tname_edt.Clear_Focus();\n\t\t\t\tname_edt.Flag_To_Redraw();\n\n\t\t\t\trc = 1;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tDefault: manage the inter-player messages\n\t\t\t//..................................................................\n\t\t\tdefault:\n\t\t\t\tif (Session.Messages.Manage()) {\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tService keyboard input for any message being edited.\n\t\t\t\t//...............................................................\n\t\t\t\ti = Session.Messages.Input(input);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf 'Input' returned 1, it means refresh the message display.\n\t\t\t\t// (We have to redraw the edit line, to erase the cursor.)\n\t\t\t\t//...............................................................\n\t\t\t\tif (i==1) {\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h,\n\t\t\t\t\t\tBOXSTYLE_BOX, true);\n\t\t\t\t\tSession.Messages.Draw();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t} else if (i==2) {\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf 'Input' returned 2, it means redraw the message display.\n\t\t\t\t// Rather than setting 'display', which would redraw all msgs,\n\t\t\t\t// we only need to erase & redraw the edit box here.\n\t\t\t\t//...............................................................\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h,\n\t\t\t\t\t\tBOXSTYLE_BOX, true);\n\t\t\t\t\tSession.Messages.Draw();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t} else if (i==3 || i==4) {\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf 'Input' returned 3, it means send the current message.\n\t\t\t\t//...............................................................\n\t\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\t\t\tSession.GPacket.Command = NET_MESSAGE;\n\t\t\t\t\tstrcpy (Session.GPacket.Name, namebuf);\n\t\t\t\t\tif (i==3) {\n\t\t\t\t\t\tstrcpy (Session.GPacket.Message.Buf,\n\t\t\t\t\t\t\tSession.Messages.Get_Edit_Buf());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstrcpy (Session.GPacket.Message.Buf,\n\t\t\t\t\t\t\tSession.Messages.Get_Overflow_Buf());\n\t\t\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t\t\t}\n\t\t\t\t\tSession.GPacket.Message.Color = Session.ColorIdx;\n\t\t\t\t\tSession.GPacket.Message.NameCRC =\n\t\t\t\t\t\tCompute_Name_CRC(Session.GameName);\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tIf we're joined in a game, send the message to every player\n\t\t\t\t\t// in our player list.  Skip the local system (index 0).\n\t\t\t\t\t//............................................................\n\t\t\t\t\tif (joinstate == JOIN_CONFIRMED) {\n\t\t\t\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\t\t\tsizeof(GlobalPacketType),\n\t\t\t\t\t\t\t\t1, &(Session.Players[i]->Address));\n\t\t\t\t\t\t\tIpx.Service();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// Otherwise, send the message to all players in our chat list.\n\t\t\t\t\t//............................................................\n\t\t\t\t\t\tfor (i = 1; i < Session.Chat.Count(); i++) {\n\t\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\t\t\tsizeof(GlobalPacketType),\n\t\t\t\t\t\t\t\t1, &(Session.Chat[i]->Address));\n\t\t\t\t\t\t\tIpx.Service();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Obfuscate(Session.GPacket.Message.Buf) == 0x72A47EF6) {\n\t\t\t\t\t\t\tSession.WWChat = 1;\n\t\t\t\t\t\t\tClear_Listbox (&playerlist);\n\t\t\t\t\t\t\tStart_WWChat(&playerlist);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tAdd the message to our own list, since we're not in the\n\t\t\t\t\t// player list on this dialog.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tSession.Messages.Add_Message (Session.GPacket.Name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSession.GPacket.Message.Buf,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tTPF_TEXT, -1);\n\t\t\t\t\tSession.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message2_w);\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t}\n\n#ifdef OBSOLETE\n\t\t\t\t//\n\t\t\t\t// This is for the old drop-down list of houses, not used any more.\n\t\t\t\t//\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\tisdropped = 1;\n\t\t\t\t} else if (isdropped) {\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t}\n#endif\n\n\t\t\t\tbreak;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tResend our query packets\n\t\t//.....................................................................\n\t\tSend_Join_Queries(game_index, joinstate, 0, 0, 0, namebuf);\n\n\t\t//.....................................................................\n\t\t//\tProcess incoming packets\n\t\t//.....................................................................\n\t\tevent = Get_Join_Responses(&joinstate, &gamelist, &playerlist,\n\t\t\tjoin_index, namebuf, &why);\n\n\t\t//.....................................................................\n\t\t//\tIf we've changed state, redraw everything; if we're starting the game,\n\t\t//\tbreak out of the loop.  If we've just joined, send out a player query\n\t\t//\tso I'll get added to the list instantly.\n\t\t//.....................................................................\n\t\tif (event == EV_STATE_CHANGE) {\n\t\t\tdisplay = REDRAW_ALL;\n\n\t\t\tif (joinstate==JOIN_GAME_START || joinstate == JOIN_GAME_START_LOAD) {\n\t\t\t\tif (joinstate==JOIN_GAME_START_LOAD) {\n\t\t\t\t\tload_game = 1;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Special new kludge for counterstrike.\n\t\t\t\t**\n\t\t\t\t** Find local scenario will fail to match a counterstrike mission\n\t\t\t\t** unless the CS CD is in the drive. So....\n\t\t\t\t**\n\t\t\t\t** If Counterstrike is installed and this is an official map and\n\t\t\t\t** the file name matches a counterstrike map then tell the host\n\t\t\t\t** that I have the scenario so he can continue while we make\n\t\t\t\t** sure the local user has the Counterstrike CD in the drive.\n\t\t\t\t**\n\t\t\t\t*/\n\t\t\t\t//\tThis is duplicated for Aftermath scenarios. ajw\n\n\t\t\t\tbool ready_packet_was_sent = false;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif (Session.ScenarioIsOfficial &&\n\t\t\t\t\t( (Expansion_CS_Present() && Is_Mission_Counterstrike(Session.ScenarioFileName)) ||\n\t\t\t\t\t  (Expansion_AM_Present() && Is_Mission_Aftermath(Session.ScenarioFileName)) ) ) {\n#else\n\t\t\t\tif ( Expansion_CS_Present() && Session.ScenarioIsOfficial ) {\n#endif\n\n\t\t\t\t\tCCFileClass check_file ( Session.ScenarioFileName );\n\t\t\t\t\tif ( !check_file.Is_Available() ) {\n\n\t\t\t\t\t\tint current_drive = CCFileClass::Get_CD_Drive();\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\tint index = Get_CD_Index(current_drive, 1*60);\n\t\t\t\t\t\tbool needcd = false;\n\t\t\t\t\t\tif (Is_Mission_Counterstrike(Session.ScenarioFileName)) {\n\t\t\t\t\t\t\tif (index != 2 && index != 3) {\n\t\t\t\t\t\t\t\tRequiredCD = 2;\n\t\t\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Is_Mission_Aftermath(Session.ScenarioFileName)) {\n\t\t\t\t\t\t\tif (index != 3) {\n\t\t\t\t\t\t\t\tRequiredCD = 3;\n\t\t\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (needcd) {\n#else\n\t\t\t\t\t\tif ( Get_CD_Index(current_drive, 1*60) != 2 ){\n\t\t\t\t\t\t\tRequiredCD = 2;\n#endif\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** We should have the scenario but the wrong disk is in.\n\t\t\t\t\t\t\t** Tell the host that I am ready to go anyway.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tmemset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket));\n\t\t\t\t\t\t\tSession.GPacket.Command = NET_READY_TO_GO;\n\t\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t\t\t\t1, &Session.HostAddress);\n\t\t\t\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0);\n\t\t\t\t\t\t\tready_packet_was_sent = true;\n\n\t\t\t\t\t\t\tif (!Force_CD_Available (RequiredCD)){\n\t\t\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Update the internal list of scenarios to include the counterstrike\n\t\t\t\t\t\t\t** list.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tSession.Read_Scenario_Descriptions();\n\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\n\t\t\t\t/*\n\t\t\t\t** If the scenario that the host wants to play doesn't exist locally then we\n\t\t\t\t**\tneed to request that it is sent. If we can identify the scenario locally then\n\t\t\t\t**\twe need to fix up the file name so we load the right one.\n\t\t\t\t*/\n\t\t\t\tIpx.Set_Timing (25, (unsigned long) -1, 1000);\n\t\t\t\tif (Find_Local_Scenario (Session.Options.ScenarioDescription,\n\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioFileName,\n\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioFileLength,\n\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioDigest,\n\t\t\t\t\t \t\t\t\t\t\t\tSession.ScenarioIsOfficial)) {\n\n\t\t\t\t\tSession.Options.ScenarioIndex = 1;\t\t//We dont care what it\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//is as long as it isnt -1\n\n\t\t\t\t\t/*\n\t\t\t\t\t** We have the scenario. Tell the host that I am ready to go.\n\t\t\t\t\t*/\n\t\t\t\t\tif ( !ready_packet_was_sent ){\n\t\t\t\t\t\tmemset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket));\n\t\t\t\t\t\tSession.GPacket.Command = NET_READY_TO_GO;\n\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t\t\t1, &Session.HostAddress);\n\n\t\t\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0);\n\t\t\t\t\t}\n\t\t\t\t} else {\n#ifndef FIXIT_VERSION_3\t\t\t//\tRemoved restriction on downloading official maps.\n\t\t\t\t\t/*\n\t\t\t\t\t** Oh dear. Thats a scenario I don't have. Request that the host sends the\n\t\t\t\t\t**\tscenario to me provided it's not an official scenario.\n\t\t\t\t\t**\n\t\t\t\t\t** If the file is received OK then we will get a true return value and the\n\t\t\t\t\t** actual file name to load will be in Session.ScenarioFileName\n\t\t\t\t\t*/\n\t\t\t\t\tif (Session.ScenarioIsOfficial) {\n\t\t\t\t\t\tSession.Options.ScenarioIndex = -1;\n\t\t\t\t\t} else {\n#endif\n\t\t\t\t\t\tSession.Options.ScenarioIndex = 1;\t\t//We dont care what it\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//is as long as it isnt -1\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\tif( bSpecialAftermathScenario( Session.Options.ScenarioDescription ) )\n\t\t\t\t\t\t\tbreak;\n#endif\n\n\t\t\t\t\t\tif (!Get_Scenario_File_From_Host(Session.ScenarioFileName, 1)) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Make sure we dont time-out because of the download\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t}\n#ifndef FIXIT_VERSION_3\n\t\t\t\t\t}\n#endif\n\t\t\t\t}\n\n\t\t\t\tIpx.Set_Timing (30, (unsigned long) -1, 600);\n\t\t\t\tstrcpy (Scen.ScenarioName, Session.ScenarioFileName);\n\t\t\t\trc = 0;\n\t\t\t\tprocess = false;\n\n\t\t\t} else if (joinstate==JOIN_CONFIRMED) {\n\n\t\t\t//..................................................................\n\t\t\t//\tIf we're newly-confirmed, add myself to the Players list, and\n\t\t\t// immediately send out a player query\n\t\t\t//..................................................................\n\t\t\t\t//...............................................................\n\t\t\t\t//\tClear the player list, then add myself to the list.\n\t\t\t\t//...............................................................\n\n\t\t\t\tClear_Listbox(&playerlist);\n\t\t\t\tClear_Vector (&Session.Players);\n\n\t\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\n#ifdef OLDWAY\n\t\t\t\tif (Session.House==HOUSE_GOOD) {\n\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf, Text_String(TXT_ALLIES));\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf, Text_String(TXT_SOVIET));\n\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\tsprintf (item, \"%s\\t%s\", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\t\t\t\tplayerlist.Add_Item(item,\n\t\t\t\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]);\n\n\t\t\t\twho = new NodeNameType;\n\t\t\t\tstrcpy(who->Name, namebuf);\n\t\t\t\twho->Player.House = Session.House;\n\t\t\t\twho->Player.Color = Session.ColorIdx;\n\t\t\t\tSession.Players.Add (who);\n\n\n\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);\n\n\t\t\t\t//...............................................................\n\t\t\t\t// Re-init the message system to its new smaller size\n\t\t\t\t//...............................................................\n\t\t\t\tSession.Messages.Init (d_message2_x + 1 *RESFACTOR, d_message2_y + 1 *RESFACTOR, 8,\n\t\t\t\t\tMAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 *RESFACTOR, d_send_y + 1 *RESFACTOR, 1,\n\t\t\t\t\t20, MAX_MESSAGE_LENGTH - 5, d_message2_w);\n\t\t\t\tSession.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message2_w);\n\t\t\t} else if (joinstate==JOIN_REJECTED) {\n\t\t\t//..................................................................\n\t\t\t//\tIf we've been rejected, clear any messages we may have been\n\t\t\t// typing, add a message stating why we were rejected, and send a\n\t\t\t// chat announcement.\n\t\t\t//..................................................................\n\t\t\t\tSession.Messages.Init (d_message1_x + 1 *RESFACTOR, d_message1_y + 1 *RESFACTOR, 14,\n\t\t\t\t\tMAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 *RESFACTOR, d_send_y + 1 *RESFACTOR, 1,\n\t\t\t\t\t20, MAX_MESSAGE_LENGTH - 5, d_message2_w);\n\t\t\t\tSession.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message2_w);\n\n\t\t\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_REQUEST_DENIED), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\n\t\t\t\titem = NULL;\n\t\t\t\tif (why==REJECT_DUPLICATE_NAME) {\n\t\t\t\t\titem = (char *)Text_String(TXT_NAME_MUSTBE_UNIQUE);\n\t\t\t\t}\n\t\t\t\telse if (why==REJECT_GAME_FULL) {\n\t\t\t\t\titem = (char *)Text_String(TXT_GAME_FULL);\n\t\t\t\t}\n\t\t\t\telse if (why==REJECT_VERSION_TOO_OLD) {\n\t\t\t\t\titem = (char *)Text_String(TXT_YOURGAME_OUTDATED);\n\t\t\t\t}\n\t\t\t\telse if (why==REJECT_VERSION_TOO_NEW) {\n\t\t\t\t\titem = (char *)Text_String(TXT_DESTGAME_OUTDATED);\n\t\t\t\t}\n\t\t\t\telse if (why==REJECT_MISMATCH) {\n\t\t\t\t\titem = (char *)Text_String(TXT_MISMATCH);\n\t\t\t\t}\n\t\t\t\telse if (why==REJECT_DISBANDED) {\n\t\t\t\t\titem = (char *)Text_String(TXT_GAME_CANCELLED);\n\t\t\t\t}\n\t\t\t\tif (item) {\n\t\t\t\t\tSession.Messages.Add_Message(NULL, 0, item, PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t}\n\n\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 0, 1, namebuf);\n\t\t\t\tdisplay = REDRAW_ALL;\n\n\t\t\t}\n\t\t} else if (event == EV_GAME_OPTIONS) {\n\t\t//.....................................................................\n\t\t//\tIf the game options have changed, print them.\n\t\t//.....................................................................\n\t\t\tcountgauge.Set_Maximum(\n\t\t\t\tSessionClass::CountMax[Session.Options.Bases] -\n\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\tcountgauge.Set_Value(Session.Options.UnitCount -\n\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\tlevelgauge.Set_Value(BuildLevel - 1);\n\t\t\tcreditsgauge.Set_Value(Session.Options.Credits);\n\t\t\tif (Session.Options.AIPlayers > Rule.MaxPlayers-Session.Players.Count()) {\n\t\t\t\taiplayersgauge.Set_Value(Rule.MaxPlayers-Session.Players.Count());\n\t\t\t} else {\n\t\t\t\taiplayersgauge.Set_Value(Session.Options.AIPlayers);\n\t\t\t}\n\t\t\toptionlist.Check_Item(0,Session.Options.Bases);\n\t\t\toptionlist.Check_Item(1,Session.Options.Tiberium);\n\t\t\toptionlist.Check_Item(2,Session.Options.Goodies);\n\t\t\toptionlist.Check_Item(3,Special.IsCaptureTheFlag);\n\t\t\toptionlist.Check_Item(4,Special.IsShadowGrow);\n\t\t\toptionlist.Flag_To_Redraw();\n\n\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\n\t\t\tparms_received = 1;\n\t\t\tdisplay = REDRAW_PARMS;\n\t\t} else if (event == EV_MESSAGE) {\n\t\t//.....................................................................\n\t\t//\tDraw an incoming message\n\t\t//.....................................................................\n\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\t\t} else if (event == EV_NEW_GAME) {\n\t\t//.....................................................................\n\t\t// If a new game has formed, or an existing game has changed state\n\t\t// (from open to closed or closed to open), redraw the message system.\n\t\t//.....................................................................\n\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t} else if (event == EV_NEW_PLAYER || event == EV_PLAYER_SIGNOFF) {\n\t\t\taiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count());\n\t\t\tif (Session.Options.AIPlayers > Rule.MaxPlayers-Session.Players.Count()) {\n\t\t\t\taiplayersgauge.Set_Value(Rule.MaxPlayers-Session.Players.Count());\n\t\t\t}\n\t\t} else if (event == EV_GAME_SIGNOFF) {\n\n\t\t//.....................................................................\n\t\t// EV_GAME_SIGNOFF:\n\t\t//\tA game before the one I've selected is gone, so we have a new index\n\t\t// now. 'game_index' must be kept set to the currently-selected list\n\t\t// item, so we send out queries for the currently-selected game.  It's\n\t\t// therefore imperative that we detect any changes to the game list.\n\t\t// If we're joined in a game, we must decrement our game_index to keep\n\t\t// it aligned with the game we're joined to.\n\t\t//.....................................................................\n\t\t\tif (joinstate==JOIN_CONFIRMED) {\n\t\t\t\tgame_index--;\n\t\t\t\tjoin_index--;\n\t\t\t\tgamelist.Set_Selected_Index(join_index);\n\t\t\t} else {\n\t\t\t\tgamelist.Flag_To_Redraw();\n\t\t\t\tClear_Listbox(&playerlist);\n\t\t\t\tClear_Vector (&Session.Players);\n\t\t\t\tgame_index = gamelist.Current_Index();\n\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tService the Ipx connections\n\t\t//.....................................................................\n\t\tIpx.Service();\n\n\t\tif (process) {\n\t\t\t//.....................................................................\n\t\t\t//\tClean out the Game List; if an old entry is found:\n\t\t\t//\t- Remove it\n\t\t\t//\t- Clear the player list\n\t\t\t//\t- Send queries for the new selected game, if there is one\n\t\t\t//.....................................................................\n\t\t\tfor (i = 1; i < Session.Games.Count(); i++) {\n\t\t\t\tif (TickCount - Session.Games[i]->Game.LastTime > 400) {\n\n\t\t\t\t\tdelete Session.Games[i];\n\t\t\t\t\tSession.Games.Delete(Session.Games[i]);\n\n\t\t\t\t\titem = (char *)(gamelist.Get_Item (i));\n\t\t\t\t\tgamelist.Remove_Item (item);\n\t\t\t\t\tdelete [] item;\n\n\t\t\t\t\tgamelist.Flag_To_Redraw();\n\n\t\t\t\t\tif (i <= game_index) {\n\t\t\t\t\t\tif (joinstate==JOIN_CONFIRMED) {\n\t\t\t\t\t\t\tgame_index--;\n\t\t\t\t\t\t\tjoin_index--;\n\t\t\t\t\t\t\tgamelist.Set_Selected_Index(join_index);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tgamelist.Flag_To_Redraw();\n\t\t\t\t\t\t\tClear_Listbox(&playerlist);\n\t\t\t\t\t\t\tClear_Vector (&Session.Players);\n\t\t\t\t\t\t\tgame_index = gamelist.Current_Index();\n\t\t\t\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//.....................................................................\n\t\t\t// If I've changed my name or color, make sure those changes go into\n\t\t\t// the Chat vector.\n\t\t\t//.....................................................................\n\t\t\tstrcpy(Session.Chat[0]->Name, namebuf);\n\t\t\tSession.Chat[0]->Chat.Color = Session.ColorIdx;\n\t\t\tif (Session.Chat[0]->Chat.Color == PCOLOR_DIALOG_BLUE) {\n\t\t\t\t Session.Chat[0]->Chat.Color = PCOLOR_REALLY_BLUE;\n\t\t\t}\n\n\t\t\t//.....................................................................\n\t\t\t// Clean out the chat vector.  If we find a node that we haven't heard\n\t\t\t// from in 6 seconds, delete that node.\n\t\t\t// If we haven't heard from a node in 5 seconds, send him a request\n\t\t\t// for a chat announcement; he then has 1 second to reply.\n\t\t\t//.....................................................................\n\t\t\tfor (i = 1; i < Session.Chat.Count(); i++) {\n\t\t\t\tif (TickCount - Session.Chat[i]->Chat.LastTime > 360) {\n\t\t\t\t\tdelete Session.Chat[i];\n\t\t\t\t\tSession.Chat.Delete(Session.Chat[i]);\n\t\t\t\t} else if (TickCount - Session.Chat[i]->Chat.LastTime > 300 &&\n\t\t\t\t\tSession.Chat[i]->Chat.LastChance == 0) {\n\t\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\t\t\tSession.GPacket.Name[0] = 0;\n\t\t\t\t\tSession.GPacket.Command = NET_CHAT_REQUEST;\n\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\tsizeof(GlobalPacketType), 0, &(Session.Chat[i]->Address));\n\t\t\t\t\tIpx.Service();\n\t\t\t\t\tSession.Chat[i]->Chat.LastChance = 1;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//.....................................................................\n\t\t\t// Manage the Lobby list:\n\t\t\t// If the user has selected the 1st Game (\"Lobby\"), the names of all\n\t\t\t// users in the Chat area show up in the Players list box.\n\t\t\t// Users can be changing their names and their colors at any time, so\n\t\t\t// we scan the Chat list each time to see if anything's changed; if\n\t\t\t// so, we redraw the player list.\n\t\t\t// (If WWChat is on, the Chat list is ignored, and the playerlist\n\t\t\t// contains custom names.)\n\t\t\t//.....................................................................\n\t\t\tif (game_index == 0) {\n\t\t\t\tif (!Session.WWChat) {\n\t\t\t\t\twhile (Session.Chat.Count() > playerlist.Count()) {\n\t\t\t\t\t\titem = new char [MPLAYER_NAME_MAX];\n\t\t\t\t\t\titem[0] = 0;\n\t\t\t\t\t\tplayerlist.Add_Item(item);\n\t\t\t\t\t\tplayerlist.Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t\twhile (playerlist.Count() > Session.Chat.Count()) {\n\t\t\t\t\t\titem = (char *)playerlist.Get_Item(0);\n\t\t\t\t\t\tplayerlist.Remove_Item(item);\n\t\t\t\t\t\tdelete [] item;\n\t\t\t\t\t\tplayerlist.Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t\tfor (i = 0; i < Session.Chat.Count(); i++) {\n\t\t\t\t\t\tif (stricmp(Session.Chat[i]->Name,playerlist.Get_Item(i)) ||\n\t\t\t\t\t\t\t&ColorRemaps[ (Session.Chat[i]->Chat.Color == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.Chat[i]->Chat.Color] !=\n\t\t\t\t\t\t\tplayerlist.Colors[i]) {\n\n\t\t\t\t\t\t\tplayerlist.Colors[i] =\n\t\t\t\t\t\t\t\t&ColorRemaps[Session.Chat[i]->Chat.Color];\n\t\t\t\t\t\t\tif (playerlist.Colors[i] == &ColorRemaps[PCOLOR_DIALOG_BLUE]) {\n\t\t\t\t\t\t\t\tplayerlist.Colors[i] = &ColorRemaps[PCOLOR_REALLY_BLUE];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstrcpy((char *)playerlist.Get_Item(i), Session.Chat[i]->Name);\n\t\t\t\t\t\t\tplayerlist.Flag_To_Redraw();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (stricmp(Session.Chat[0]->Name,playerlist.Get_Item(0)) ||\n\t\t\t\t\t\t&ColorRemaps[Session.Chat[0]->Chat.Color] !=\n\t\t\t\t\t\t\tplayerlist.Colors[0]) {\n\t\t\t\t\t\tplayerlist.Colors[0] = &ColorRemaps[Session.Chat[0]->Chat.Color];\n\t\t\t\t\t\tstrcpy((char *)playerlist.Get_Item(0), Session.Chat[0]->Name);\n\t\t\t\t\t\tplayerlist.Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t\tif (Update_WWChat()) {\n\t\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t\t//.....................................................................\n\t\t//\tService the sounds & score; GameActive must be false at this point,\n\t\t//\tso Call_Back() doesn't intercept global messages from me!\n\t\t//.....................................................................\n\t\tCall_Back();\n\n\t}\t// end of while\n\n\n\t//------------------------------------------------------------------------\n\t//\tEstablish connections with all other players.\n\t//------------------------------------------------------------------------\n\tif (rc == 0) {\n\t\t//.....................................................................\n\t\t//\tIf the other guys are playing a scenario I don't have (sniff), I can't\n\t\t//\tplay.  Try to bail gracefully.\n\t\t//.....................................................................\n\t\tif (Session.Options.ScenarioIndex==-1) {\n\t\t\tWWMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH);\n\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\t\tstrcpy (Session.GPacket.Name, namebuf);\n\n\t\t\t//..................................................................\n\t\t\t// Don't send myself the message.\n\t\t\t//..................................................................\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\tsizeof(GlobalPacketType), 1,\n\t\t\t\t\t&(Session.Players[i]->Address));\n\t\t\t\tIpx.Service();\n\t\t\t}\n\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t0, NULL);\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t0, NULL);\n\n\t\t\tif (Session.IsBridge) {\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType),\n\t\t\t\t\t0, &Session.BridgeNet);\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType),\n\t\t\t\t\t0, &Session.BridgeNet);\n\t\t\t}\n\n\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\trc = -1;\n\n\t\t} else {\n\n\t\t//---------------------------------------------------------------------\n\t\t// Prepare to load the scenario.\n\t\t//---------------------------------------------------------------------\n\t\t\t//..................................................................\n\t\t\t//\tSet the number of players in this game, and the scenario number.\n\t\t\t//..................................................................\n\t\t\tSession.NumPlayers = Session.Players.Count();\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tWait a while, polling the IPX service routines, to give our ACK\n\t\t//\ta chance to get to the other system.  If he doesn't get our ACK,\n\t\t// he'll be waiting the whole time we load MIX files.\n\t\t//.....................................................................\n\t\ti = max(Ipx.Global_Response_Time() * 2, 60);\n\t\tstarttime = TickCount;\n\t\twhile (TickCount - starttime < i) {\n\t\t\tIpx.Service();\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tInit network timing values, using previous response times as a measure\n\t//\tof what our retry delta & timeout should be.\n\t//------------------------------------------------------------------------\n//\tIpx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,\n//\t\tIpx.Global_Response_Time() * 4);\n\tIpx.Set_Timing (Ipx.Global_Response_Time () + 2, (unsigned long) -1, max (120, Ipx.Global_Response_Time () * 8));\n\n\n\t//------------------------------------------------------------------------\n\t//\tClear all lists, but NOT the Games & Players vectors.\n\t//------------------------------------------------------------------------\n\tClear_Listbox(&gamelist);\n\tClear_Listbox(&playerlist);\n\n\t//------------------------------------------------------------------------\n\t// Remove the chat edit box\n\t//------------------------------------------------------------------------\n\tSession.Messages.Remove_Edit();\n\n\t//------------------------------------------------------------------------\n\t//\tRestore screen\n\t//------------------------------------------------------------------------\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n\tShow_Mouse();\n\n\t//------------------------------------------------------------------------\n\t// Load a game if the game owner told us to\n\t//------------------------------------------------------------------------\n\tif (load_game) {\n\t\tif (!Load_Game (-1)) {\n\t\t\tWWMessageBox().Process (TXT_ERROR_LOADING_GAME);\n\t\t\trc = -1;\n\t\t}\n\t\tFrame++;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Clear the Players & Games vectors if we're not joined to a game.\n\t// Clear the Chat vector regardless.\n\t//------------------------------------------------------------------------\n\tif (rc != 0) {\n\t\tClear_Vector(&Session.Games);\n\t\tClear_Vector(&Session.Players);\n\t}\n\tClear_Vector(&Session.Chat);\n\n\treturn(rc);\n\n}\t/* end of Net_Join_Dialog */\n\n\n/***************************************************************************\n * Request_To_Join -- Sends a JOIN request packet to game owner            *\n *                                                                         *\n * Regardless of the return code, the Join Dialog will need to be redrawn\t*\n * after calling this routine.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tplayername\t\tplayer's name\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tjoin_index\t\tindex of game we're joining\t\t\t\t\t\t\t\t\t*\n *\t\thouse\t\t\t\trequested house\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tcolor\t\t\t\trequested color\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = Packet sent, 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\nstatic int Request_To_Join (char *playername, int join_index,\n\tHousesType house, PlayerColorType color)\n{\n\t//------------------------------------------------------------------------\n\t//\tValidate join_index\n\t//------------------------------------------------------------------------\n\tif (join_index < 1) {\n\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_MUST_SELECT_GAME), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\tSound_Effect(VOC_SYS_ERROR);\n\t\treturn(false);\n\t}\n\tif ( (Session.Games.Count()<=1) || join_index > Session.Games.Count()) {\n\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_NOTHING_TO_JOIN), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\tSound_Effect(VOC_SYS_ERROR);\n\t\treturn(false);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tForce user to enter a name\n\t//------------------------------------------------------------------------\n\tif (strlen(playername)==0) {\n\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_NAME_ERROR), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\tSound_Effect(VOC_SYS_ERROR);\n\t\treturn(false);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tThe game must be open\n\t//------------------------------------------------------------------------\n\tif (!Session.Games[join_index]->Game.IsOpen) {\n\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_GAME_IS_CLOSED), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\tSound_Effect(VOC_SYS_ERROR);\n\t\treturn (false);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSend packet to game's owner\n\t//------------------------------------------------------------------------\n\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\tSession.GPacket.Command = NET_QUERY_JOIN;\n\tstrcpy (Session.GPacket.Name, playername);\n\tSession.GPacket.PlayerInfo.House = house;\n\tSession.GPacket.PlayerInfo.Color = color;\n#ifdef FIXIT_VERSION_3\n\t//\tGuest sends host his version.\n\t//\tAdded to the transmitted _min_ version number is a bit indicating presence of Aftermath expansion.\n\tif( Is_Aftermath_Installed() )\n\t{\n//\t\tdebugprint( \"Guest tells host 'I have Aftermath'\\n\" );\n\t\tSession.GPacket.PlayerInfo.MinVersion = VerNum.Min_Version() |  0x80000000;\n\t}\n\telse\n\t{\n//\t\tdebugprint( \"Guest tells host 'I don't have Aftermath'\\n\" );\n\t\tSession.GPacket.PlayerInfo.MinVersion = VerNum.Min_Version();\n\t}\n#else\n\tSession.GPacket.PlayerInfo.MinVersion = VerNum.Min_Version();\n#endif\n\tSession.GPacket.PlayerInfo.MaxVersion = VerNum.Max_Version();\n\tSession.GPacket.PlayerInfo.CheatCheck = RuleINI.Get_Unique_ID();\n\n\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 1,\n\t\t&(Session.Games[join_index]->Address));\n\n\treturn(true);\n\n}\t/* end of Request_To_Join */\n\n\n/***************************************************************************\n * Unjoin_Game -- Cancels joining a game                                   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnamebuf\t\t\tcurrent player name\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tjoinstate\t\tcurrent join state\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tgamelist\t\t\tListBox of game names\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tplayerlist\t\tListBox of player names\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tgame_index\t\tindex in 'gamelist' of game we're leaving\t\t\t\t\t*\n *\t\tgoto_lobby\t\ttrue = we're going to the lobby\t\t\t\t\t\t\t\t*\n *\t\tmsg_x\t\t\t\tmessage system x-coord\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tmsg_y\t\t\t\tmessage system y-coord\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tmsg_h\t\t\t\tmessage system char height\t\t\t\t\t\t\t\t\t\t*\n *\t\tsend_x\t\t\tmessage system send x-coord\t\t\t\t\t\t\t\t\t*\n *\t\tsend_y\t\t\tmessage system send y-coord\t\t\t\t\t\t\t\t\t*\n *\t\tmsg_len\t\t\tmessage system max msg length\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/12/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Unjoin_Game(char *namebuf,JoinStateType joinstate,\n\tListClass *gamelist, ColorListClass *playerlist, int game_index,\n\tint goto_lobby, int msg_x, int msg_y, int msg_h, int send_x, int send_y,\n\tint msg_len)\n{\n\tint i;\n\tchar *item;\n\n\t//------------------------------------------------------------------------\n\t// Fill in a SIGN_OFF packet\n\t//------------------------------------------------------------------------\n\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\tSession.GPacket.Command = NET_SIGN_OFF;\n\tstrcpy(Session.GPacket.Name,namebuf);\n\n\t//------------------------------------------------------------------------\n\t//\tIf we're joined to a game, make extra sure the other players in\n\t//\tthat game know I'm exiting; send my SIGN_OFF as an ack-required\n\t//\tpacket.  Don't send this to myself (index 0).\n\t//------------------------------------------------------------------------\n\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 1,\n\t\t\t&(Session.Players[i]->Address));\n\t\tIpx.Service();\n\t}\n\n\tif (joinstate == JOIN_WAIT_CONFIRM || joinstate == JOIN_CONFIRMED) {\n\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 1,\n\t\t\t&(Session.Games[game_index]->Address));\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Re-init the message system to its new larger size\n\t//------------------------------------------------------------------------\n\tSession.Messages.Init (msg_x + 1, msg_y + 1, 14,\n\t\tmsg_len, msg_h, send_x + 1, send_y + 1, 1,\n\t\t20, msg_len - 5);\n\tSession.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_');\n\n\t//------------------------------------------------------------------------\n\t// Remove myself from the player list, and reset my game name\n\t//------------------------------------------------------------------------\n\tif (playerlist->Count()) {\n\t\titem = (char *)(playerlist->Get_Item(0));\n\t\tplayerlist->Remove_Item(item);\n\t\tdelete [] item;\n\t\tplayerlist->Flag_To_Redraw();\n\t}\n\n\tif (Session.Players.Count() > 0) {\n\t\tdelete Session.Players[0];\n\t\tSession.Players.Delete(Session.Players[0]);\n\t}\n\n\tSession.GameName[0] = 0;\n\n\t//------------------------------------------------------------------------\n\t// Highlight \"Lobby\" on the Game list, Announce I'm ready to chat\n\t//------------------------------------------------------------------------\n\tif (goto_lobby) {\n\t\tgamelist->Set_Selected_Index(0);\n\t\tSend_Join_Queries (game_index, joinstate, 0, 0, 1, namebuf);\n\t}\n\n}\t// end of Unjoin_Game\n\n\n/***********************************************************************************************\n * Send_Join_Queries -- sends queries for the Join Dialog\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * This routine [re]sends the queries related to the Join Dialog:\t\t\t\t\t\t\t\t\t\t  *\n * - NET_QUERY_GAME\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * - NET_QUERY_PLAYER for the game currently selected (if there is one)\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * The queries are \"staggered\" in time so they aren't all sent at once; otherwise, we'd\t\t  *\n * be inundated with reply packets & we'd miss some (even though the replies will require\t\t  *\n * ACK's).\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tcurgame\t\tindex of currently-selected game; -1 = none\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tjoinstate\tour current joinstate\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tgamenow\t\tif 1, will immediately send the game query\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tplayernow\tif 1, will immediately send the player query for currently-selected game\t  *\n *\t\tchatnow\t\tif 1, will immediately send the chat announcement\t\t\t\t\t\t\t\t\t  *\n *\t\tmyname\t\tuser's name\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tinit\t\t\tinitialize the timers\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   02/14/1995 BR : Created.                                              \t\t\t\t\t\t  *\n *   04/15/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nstatic void Send_Join_Queries(int curgame, JoinStateType joinstate,\n\tint gamenow, int playernow, int chatnow, char *myname, int init)\n{\n\t//........................................................................\n\t// These values control the timeouts for sending various types of packets;\n\t// they're designed such that they'll rarely occur simultaneously.\n\t//........................................................................\n\tenum {\n\t\tGAME_QUERY_TIME = 120,\n\t\tPLAYER_QUERY_TIME = 35,\n\t\tCHAT_ANNOUNCE_TIME = 83,\n\t};\n\tstatic CDTimerClass<SystemTimerClass> game_timer;\t\t// time between NET_QUERY_GAME's\n\tstatic CDTimerClass<SystemTimerClass> player_timer;\t// time between NET_QUERY_PLAYERS's\n\tstatic CDTimerClass<SystemTimerClass> chat_timer;\t\t// time between NET_CHAT_ANNOUNCE's\n\n\n\t//------------------------------------------------------------------------\n\t// Initialize timers\n\t//------------------------------------------------------------------------\n\tif (init) {\n\t\tgame_timer = GAME_QUERY_TIME;\n\t\tplayer_timer = PLAYER_QUERY_TIME;\n\t\tchat_timer = CHAT_ANNOUNCE_TIME;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSend the game-name query if the time has expired, or we're told to do\n\t//\tit right now\n\t//------------------------------------------------------------------------\n\tif (!game_timer || gamenow) {\n\n\t\tgame_timer = GAME_QUERY_TIME;\n\n\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\tSession.GPacket.Command = NET_QUERY_GAME;\n\n\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\tsizeof(GlobalPacketType), 0, NULL);\n\n\t\t//.....................................................................\n\t\t//\tIf the user specified a remote server address, broadcast over that\n\t\t//\tnetwork, too.\n\t\t//.....................................................................\n\t\tif (Session.IsBridge) {\n\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\tsizeof(GlobalPacketType), 0, &Session.BridgeNet);\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSend the player query for the game currently clicked on, if the time has\n\t//\texpired and there is a currently-selected game, or we're told to do it\n\t//\tright now\n\t//------------------------------------------------------------------------\n\tif ( ((curgame > 0) && (curgame < Session.Games.Count()) &&\n\t\t!player_timer) || playernow) {\n\n\t\tplayer_timer = PLAYER_QUERY_TIME;\n\n\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\tSession.GPacket.Command = NET_QUERY_PLAYER;\n\t\tstrcpy (Session.GPacket.Name, Session.Games[curgame]->Name);\n\n\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\tsizeof(GlobalPacketType), 0, NULL);\n\n\t\t//.....................................................................\n\t\t//\tIf the user specified a remote server address, broadcast over that\n\t\t//\tnetwork, too.\n\t\t//.....................................................................\n\t\tif (Session.IsBridge) {\n\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\tsizeof(GlobalPacketType), 0, &Session.BridgeNet);\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Send the chat announcement\n\t//------------------------------------------------------------------------\n\tif ((!chat_timer && joinstate!=JOIN_CONFIRMED) || chatnow) {\n\n\t\tchat_timer = CHAT_ANNOUNCE_TIME;\n\n\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\tSession.GPacket.Command = NET_CHAT_ANNOUNCE;\n\t\tstrcpy (Session.GPacket.Name, myname);\n\t\tSession.GPacket.Chat.ID = Session.UniqueID;\n\t\tSession.GPacket.Chat.Color = Session.ColorIdx;\n\n\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\tsizeof(GlobalPacketType), 0, NULL);\n\n\t\tif (Session.IsBridge) {\n\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\tsizeof(GlobalPacketType), 0, &Session.BridgeNet);\n\t\t}\n\t}\n\n}\t/* end of Send_Join_Queries */\n\n\n/***********************************************************************************************\n * Get_Join_Responses -- sends queries for the Join Dialog\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * This routine polls the Global Channel to see if there are any incoming packets;\t\t\t\t  *\n * if so, it processes them.  This routine can change the state of the Join Dialog, or\t\t\t  *\n * the contents of the list boxes, based on what the packet is.\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * The list boxes are passed in as pointers; they can't be made globals, because they\t\t\t  *\n * can't be constructed, because they require shape pointers to the arrow buttons, and\t\t\t  *\n * the mix files won't have been initialized when the global variables' constructors are\t\t  *\n * called.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * This routine sets the globals \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tSession.House\t\t\t\t\t(from NET_CONFIRM_JOIN)\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tSession.ColorIdx\t\t\t\t(from NET_CONFIRM_JOIN)\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tSession.Options.Bases\t\t(from NET_GAME_OPTIONS)\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tSession.Options.Tiberium\t(from NET_GAME_OPTIONS)\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tSession.Options.Goodies\t\t(from NET_GAME_OPTIONS)\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tSession.Options.Ghosts\t\t(from NET_GAME_OPTIONS)\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tScenarioIdx\t\t\t\t(from NET_GAME_OPTIONS; -1 = scenario not found)\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tjoinstate\t\tcurrent state of Join Dialog\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tgamelist\t\t\tlist box containing game names\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tplayerlist\t\tlist box containing player names for the currently-selected game\t\t\t  *\n *\t\tjoin_index\t\tindex of the game we've joined or are asking to join\t\t\t\t\t\t\t  *\n *\t\tmy_name\t\t\tname of local system\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\twhy\t\t\t\tptr: filled in with reason for rejection from a game\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\tEvent that occurred\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   02/14/1995 BR : Created.                                              \t\t\t\t\t\t  *\n *   04/15/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nstatic JoinEventType Get_Join_Responses(JoinStateType *joinstate, ListClass *gamelist,\n\tColorListClass *playerlist, int join_index, char *my_name, RejectType *why)\n{\n\tint rc;\n\tchar * item;\t\t\t\t\t\t// general-purpose string\n\tNodeNameType *who;\t\t\t\t// node to add to Games or Players\n\tint i;\n\tint found;\n\tJoinEventType retcode = EV_NONE;\n\tchar txt[80];\n\n\t//------------------------------------------------------------------------\n\t//\tIf there is no incoming packet, just return\n\t//------------------------------------------------------------------------\n\trc = Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen,\n\t\t&Session.GAddress, &Session.GProductID);\n\tif (!rc || Session.GProductID != IPXGlobalConnClass::COMMAND_AND_CONQUER0)\n\t\treturn(EV_NONE);\n\n\t//------------------------------------------------------------------------\n\t//\tIf we're joined in a game, handle the packet in a standard way; otherwise,\n\t//\tdon't answer standard queries.\n\t//------------------------------------------------------------------------\n\tif ( (*joinstate)==JOIN_CONFIRMED &&\n\t\tProcess_Global_Packet(&Session.GPacket,&Session.GAddress)!=0) {\n\t\treturn(EV_NONE);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_ANSWER_GAME:  Another system is answering our GAME query, so add that\n\t//\tsystem to our list box if it's new.\n\t//------------------------------------------------------------------------\n\tif (Session.GPacket.Command==NET_ANSWER_GAME) {\n\n\t\t//.....................................................................\n\t\t//\tSee if this name is unique\n\t\t//.....................................................................\n\t\tretcode = EV_NONE;\n\t\tfound = 0;\n\t\tfor (i = 1; i < Session.Games.Count(); i++) {\n\t\t\tif (!strcmp(Session.Games[i]->Name, Session.GPacket.Name)) {\n\t\t\t\tfound = 1;\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf name was found, update the node's time stamp & IsOpen flag.\n\t\t\t\t//...............................................................\n\t\t\t\tSession.Games[i]->Game.LastTime = TickCount;\n\t\t\t\tif (Session.Games[i]->Game.IsOpen != Session.GPacket.GameInfo.IsOpen) {\n\t\t\t\t\titem = (char *)gamelist->Get_Item(i);\n\t\t\t\t\tif (Session.GPacket.GameInfo.IsOpen) {\n\t\t\t\t\t\tsprintf(item,Text_String(TXT_THATGUYS_GAME),\n\t\t\t\t\t\t\tSession.GPacket.Name);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tsprintf(item,Text_String(TXT_THATGUYS_GAME_BRACKET),\n\t\t\t\t\t\t\tSession.GPacket.Name);\n\t\t\t\t\t}\n\t\t\t\t\tSession.Games[i]->Game.IsOpen = Session.GPacket.GameInfo.IsOpen;\n\t\t\t\t\tgamelist->Flag_To_Redraw();\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tIf this game has gone from closed to open, copy the\n\t\t\t\t\t// responder's address into our Game slot, since the guy\n\t\t\t\t\t// responding to this must be game owner.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tif (Session.Games[i]->Game.IsOpen) {\n\t\t\t\t\t\tSession.Games[i]->Address = Session.GAddress;\n\t\t\t\t\t}\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// If we're in chat mode, print a message that the state of\n\t\t\t\t\t// this game has changed.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tif (*joinstate < JOIN_CONFIRMED) {\n\t\t\t\t\t\tif (Session.Games[i]->Game.IsOpen) {\n\t\t\t\t\t\t\tsprintf(txt,Text_String(TXT_S_FORMED_NEW_GAME),\n\t\t\t\t\t\t\t\tSession.Games[Session.Games.Count()-1]->Name);\n\t\t\t\t\t\t\tSound_Effect(VOC_GAME_FORMING);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tsprintf(txt,Text_String(TXT_GAME_NOW_IN_PROGRESS),\n\t\t\t\t\t\t\t\tSession.Games[Session.Games.Count()-1]->Name);\n\t\t\t\t\t\t\tSound_Effect(VOC_GAME_CLOSED);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSession.Messages.Add_Message(NULL, 0, txt, PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\t\tretcode = EV_NEW_GAME;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tname not found (or addresses are different); add it to 'Games'\n\t\t//.....................................................................\n\t\tif (found==0) {\n\n\t\t\t//..................................................................\n\t\t\t//\tCreate a new node structure, fill it in, add it to 'Games'\n\t\t\t//..................................................................\n\t\t\twho = new NodeNameType;\n\t\t\tstrcpy(who->Name, Session.GPacket.Name);\n\t\t\twho->Address = Session.GAddress;\n\t\t\twho->Game.IsOpen = Session.GPacket.GameInfo.IsOpen;\n\t\t\twho->Game.LastTime = TickCount;\n\t\t\tSession.Games.Add (who);\n\n\t\t\t//..................................................................\n\t\t\t//\tCreate a string for \"xxx's Game\", leaving room for brackets around\n\t\t\t//\tthe string if it's a closed game\n\t\t\t//..................................................................\n\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\n\t\t\tif (Session.GPacket.GameInfo.IsOpen) {\n\t\t\t\tsprintf(item,Text_String(TXT_THATGUYS_GAME),Session.GPacket.Name);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tsprintf(item,Text_String(TXT_THATGUYS_GAME_BRACKET),\n\t\t\t\t\tSession.GPacket.Name);\n\t\t\t}\n\t\t\tgamelist->Add_Item(item);\n\n\t\t\t//..................................................................\n\t\t\t// If this player's in the Chat vector, remove him from there\n\t\t\t//..................................................................\n\t\t\tfor (i = 1; i < Session.Chat.Count(); i++) {\n\t\t\t\tif (Session.Chat[i]->Address==Session.GAddress) {\n\t\t\t\t\tdelete Session.Chat[i];\n\t\t\t\t\tSession.Chat.Delete(Session.Chat[i]);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// If this game is open, display a message stating that it's\n\t\t\t// now available.\n\t\t\t//..................................................................\n\t\t\tif (Session.GPacket.GameInfo.IsOpen && (*joinstate) < JOIN_CONFIRMED) {\n\t\t\t\tsprintf(txt,Text_String(TXT_S_FORMED_NEW_GAME),\n\t\t\t\t\tSession.GPacket.Name);\n\t\t\t\tSession.Messages.Add_Message(NULL, 0, txt, PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\tSound_Effect(VOC_GAME_FORMING);\n\t\t\t}\n\n\t\t\tretcode = EV_NEW_GAME;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_ANSWER_PLAYER: Another system is answering our PLAYER query, so add\n\t// it to our player list box & the Player Vector if it's new\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_ANSWER_PLAYER) {\n\t\t//.....................................................................\n\t\t//\tSee if this name is unique\n\t\t//.....................................................................\n\t\tretcode = EV_NONE;\n\t\tfound = 0;\n\t\tfor (i = 0; i < Session.Players.Count(); i++) {\n\n\t\t\t//..................................................................\n\t\t\t//\tIf the address is already present, re-copy their name, color &\n\t\t\t//\thouse into the existing entry, in case they've changed it without\n\t\t\t//\tour knowledge; set the 'found' flag so we won't create a new entry.\n\t\t\t//..................................................................\n\t\t\tif (Session.Players[i]->Address==Session.GAddress) {\n\t\t\t\tstrcpy(Session.Players[i]->Name, Session.GPacket.Name);\n\t\t\t\tSession.Players[i]->Player.House = Session.GPacket.PlayerInfo.House;\n\t\t\t\tSession.Players[i]->Player.Color = Session.GPacket.PlayerInfo.Color;\n\n\t\t\t\tplayerlist->Colors[i] =\n\t\t\t\t\t&ColorRemaps[Session.GPacket.PlayerInfo.Color];\n\n\t\t\t\tif (playerlist->Colors[i] == &ColorRemaps[PCOLOR_DIALOG_BLUE]) {\n\t\t\t\t\tplayerlist->Colors[i] = &ColorRemaps[PCOLOR_REALLY_BLUE];\n\t\t\t\t}\n\n\t\t\t\tfound = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tDon't add this player if he's not part of the game that's selected.\n\t\t//.....................................................................\n\t\ti = gamelist->Current_Index();\n\t\tif (Session.Games.Count() && Session.GPacket.PlayerInfo.NameCRC !=\n\t\t\tCompute_Name_CRC(Session.Games[i]->Name)) {\n\t\t\tfound = 1;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tDon't add this player if it's myself.  (We must check the name\n\t\t// since the address of myself in 'Players' won't be valid.)\n\t\t//.....................................................................\n\t\tif (!strcmp (my_name,Session.GPacket.Name)) {\n\t\t\tfound = 1;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tname not found, or address didn't match; add to player list box\n\t\t// & Players Vector\n\t\t//.....................................................................\n\t\tif (found==0) {\n\t\t\t//..................................................................\n\t\t\t//\tCreate & add a node to the Vector\n\t\t\t//..................................................................\n\t\t\twho = new NodeNameType;\n\t\t\tstrcpy(who->Name, Session.GPacket.Name);\n\t\t\twho->Address = Session.GAddress;\n\t\t\twho->Player.House = Session.GPacket.PlayerInfo.House;\n\t\t\twho->Player.Color = Session.GPacket.PlayerInfo.Color;\n\t\t\tSession.Players.Add (who);\n\n\t\t\t//..................................................................\n\t\t\t//\tCreate & add a string to the list box\n\t\t\t//..................................................................\n\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\n#ifdef OLDWAY\n\t\t\tif (Session.GPacket.PlayerInfo.House==HOUSE_GOOD) {\n\t\t\t\tsprintf(item,\"%s\\t%s\",Session.GPacket.Name, Text_String(TXT_ALLIES));\n\t\t\t} else {\n\t\t\t\tsprintf(item,\"%s\\t%s\",Session.GPacket.Name, Text_String(TXT_SOVIET));\n\t\t\t}\n#else\t//OLDWAY\n\t\t\tsprintf (item, \"%s\\t%s\", Session.GPacket.Name, Text_String(HouseTypeClass::As_Reference(Session.GPacket.PlayerInfo.House).Full_Name()));\n#endif\t//OLDWAY\n\t\t\tplayerlist->Add_Item(item,\n\t\t\t\t(who->Player.Color == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[who->Player.Color]);\n\n\t\t\t//..................................................................\n\t\t\t// If this player's in the Chat vector, remove him from there\n\t\t\t//..................................................................\n\t\t\tfor (i = 1; i < Session.Chat.Count(); i++) {\n\t\t\t\tif (Session.Chat[i]->Address==Session.GAddress) {\n\t\t\t\t\tdelete Session.Chat[i];\n\t\t\t\t\tSession.Chat.Delete(Session.Chat[i]);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// If this player has joined our game, play a special sound.\n\t\t\t//..................................................................\n\t\t\tif ((*joinstate)>=JOIN_CONFIRMED) {\n\t\t\t\tSound_Effect(VOC_PLAYER_JOINED);\n\t\t\t}\n\n\t\t\tretcode = EV_NEW_PLAYER;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_CONFIRM_JOIN: The game owner has confirmed our JOIN query; mark us\n\t// as being confirmed, and start answering queries from other systems\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_CONFIRM_JOIN) {\n\t\tif ( (*joinstate) != JOIN_CONFIRMED) {\n\t\t\tstrcpy (Session.GameName, Session.GPacket.Name);\n\t\t\tSession.House = Session.GPacket.PlayerInfo.House;\n\t\t\tSession.ColorIdx = Session.GPacket.PlayerInfo.Color;\n\n\t\t\t(*joinstate) = JOIN_CONFIRMED;\n\t\t\tretcode = EV_STATE_CHANGE;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_REJECT_JOIN: The game owner has turned down our JOIN query; restore\n\t//\tthe dialog state to its first pop-up state.\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_REJECT_JOIN) {\n\t\t//.....................................................................\n\t\t// If we're confirmed in a game, broadcast a sign-off to tell all other\n\t\t// systems that I'm no longer a part of any game; this way, I'll be\n\t\t// properly removed from their dialogs.\n\t\t//.....................................................................\n\t\tif ( (*joinstate) == JOIN_CONFIRMED) {\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\t\tstrcpy (Session.GPacket.Name,my_name);\n\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\tsizeof(GlobalPacketType), 1,\n\t\t\t\t\t&(Session.Players[i]->Address));\n\t\t\t\tIpx.Service();\n\t\t\t}\n\n\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\tsizeof (GlobalPacketType), 0, NULL);\n\t\t\tif (Session.IsBridge) {\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType),\n\t\t\t\t\t0, &Session.BridgeNet);\n\t\t\t}\n\n\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\tSession.GameName[0] = 0;\n\n\t\t\t//..................................................................\n\t\t\t// remove myself from the player list\n\t\t\t//..................................................................\n\t\t\titem = (char *)(playerlist->Get_Item(0));\n\t\t\tplayerlist->Remove_Item(item);\n\t\t\tdelete [] item;\n\t\t\tplayerlist->Flag_To_Redraw();\n\n\t\t\tdelete Session.Players[0];\n\t\t\tSession.Players.Delete(Session.Players[0]);\n\n\t\t\t(*joinstate) = JOIN_REJECTED;\n\t\t\t(*why) = REJECT_BY_OWNER;\n\t\t\tretcode = EV_STATE_CHANGE;\n\t\t}\n\t\t//.....................................................................\n\t\t// If we're waiting for confirmation & got rejected, tell the user why\n\t\t//.....................................................................\n\t\telse if ((*joinstate) == JOIN_WAIT_CONFIRM) {\n\t\t\t(*why) = (RejectType)Session.GPacket.Reject.Why;\n\t\t\t(*joinstate) = JOIN_REJECTED;\n\t\t\tretcode = EV_STATE_CHANGE;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_GAME_OPTIONS: The game owner has changed the game options & is\n\t// sending us the new values.\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_GAME_OPTIONS) {\n\t\tif ( (*joinstate)==JOIN_CONFIRMED || (*joinstate)==JOIN_WAIT_CONFIRM) {\n\t\t\tSession.Options.Credits = Session.GPacket.ScenarioInfo.Credits;\n\t\t\tSession.Options.Bases = Session.GPacket.ScenarioInfo.IsBases;\n\t\t\tSession.Options.Tiberium = Session.GPacket.ScenarioInfo.IsTiberium;\n\t\t\tSession.Options.Goodies = Session.GPacket.ScenarioInfo.IsGoodies;\n//\t\t\tSession.Options.Ghosts = Session.GPacket.ScenarioInfo.IsGhosties;\n\t\t\tSession.Options.AIPlayers = Session.GPacket.ScenarioInfo.AIPlayers;\n\t\t\tBuildLevel = Session.GPacket.ScenarioInfo.BuildLevel;\n\t\t\tSession.Options.UnitCount = Session.GPacket.ScenarioInfo.UnitCount;\n\t\t\tSeed = Session.GPacket.ScenarioInfo.Seed;\n\t\t\tSpecial = Session.GPacket.ScenarioInfo.Special;\n\t\t\tOptions.GameSpeed = Session.GPacket.ScenarioInfo.GameSpeed;\n\n#ifdef FIXIT_VERSION_3\n\t\t\t//\tGuest receives game version number from host.\n\t\t\t//\tAdded to the transmitted version number is a bit indicating presence of Aftermath expansion.\n\t\t\tunsigned long lVersion = Session.GPacket.ScenarioInfo.Version & ~0x80000000;\t//\tActual version number.\n\t\t\tSession.CommProtocol = VerNum.Version_Protocol( lVersion );\n\t\t\tbAftermathMultiplayer = Session.GPacket.ScenarioInfo.Version & 0x80000000;\n//\t\t\tif( bAftermathMultiplayer )\n//\t\t\t\tdebugprint( \"Guest hears host say 'This is an Aftermath game'\\n\" );\n//\t\t\telse\n//\t\t\t\tdebugprint( \"Guest hears host say 'This is NOT an Aftermath game'\\n\" );\n#else\n\t\t\tSession.CommProtocol = VerNum.Version_Protocol(Session.GPacket.ScenarioInfo.Version);\n\t\t\tPlayingAgainstVersion = Session.GPacket.ScenarioInfo.Version;\n#endif\n\n\t\t\tif (Session.Options.Tiberium) {\n\t\t\t\tSpecial.IsTGrowth = 1;\n\t\t\t\tRule.IsTGrowth = 1;\n\t\t\t\tSpecial.IsTSpread = 1;\n\t\t\t\tRule.IsTSpread = 1;\n\t\t\t} else {\n\t\t\t\tSpecial.IsTGrowth = 0;\n\t\t\t\tRule.IsTGrowth = 0;\n\t\t\t\tSpecial.IsTSpread = 0;\n\t\t\t\tRule.IsTSpread = 0;\n\t\t\t}\n\n\t\t\t/*...............................................................\n\t\t\tCopy the information about the scenario that the host wants to\n\t\t\tplay so ee can request this scenario from the host if we don't\n\t\t\thave it locally.\n\t\t\t...............................................................*/\n\t\t\tstrcpy (Session.Options.ScenarioDescription, Session.GPacket.ScenarioInfo.Scenario);\n\t\t\tstrcpy (Session.ScenarioFileName, Session.GPacket.ScenarioInfo.ShortFileName);\n#ifdef WOLAPI_INTEGRATION\n\t\t\tstrncpy (Session.ScenarioDigest, (char*)Session.GPacket.ScenarioInfo.FileDigest, sizeof (Session.GPacket.ScenarioInfo.FileDigest));\n#else\n\t\t\tstrcpy (Session.ScenarioDigest, (char*)Session.GPacket.ScenarioInfo.FileDigest);\n#endif\n\t\t\tSession.ScenarioIsOfficial = Session.GPacket.ScenarioInfo.OfficialScenario;\n\t\t\tSession.ScenarioFileLength = Session.GPacket.ScenarioInfo.FileLength;\n\n\t\t\tretcode = EV_GAME_OPTIONS;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_SIGN_OFF: Another system is signing off: search for that system in\n\t//\tboth the game list & player list, & remove it if found\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_SIGN_OFF) {\n\t\t//.....................................................................\n\t\t//\tRemove this name from the list of games\n\t\t//.....................................................................\n\t\tfor (i = 1; i < Session.Games.Count(); i++) {\n\t\t\tif (!strcmp(Session.Games[i]->Name, Session.GPacket.Name) &&\n\t\t\t\tSession.Games[i]->Address==Session.GAddress) {\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf the system signing off is the currently-selected list\n\t\t\t\t//\titem, clear the player list since that game is no longer\n\t\t\t\t//\tforming.\n\t\t\t\t//...............................................................\n\t\t\t\tif (i==gamelist->Current_Index()) {\n\t\t\t\t\tClear_Listbox (playerlist);\n\t\t\t\t\tClear_Vector (&Session.Players);\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf the system signing off was the owner of our game, mark\n\t\t\t\t//\tourselves as rejected\n\t\t\t\t//...............................................................\n\t\t\t\tif ( (*joinstate) > JOIN_NOTHING && i==join_index) {\n\t\t\t\t\t(*joinstate) = JOIN_REJECTED;\n\t\t\t\t\tretcode = EV_STATE_CHANGE;\n\t\t\t\t\t(*why) = REJECT_DISBANDED;\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tSet my return code\n\t\t\t\t//...............................................................\n\t\t\t\tif (retcode == EV_NONE) {\n\t\t\t\t\tif (i <= gamelist->Current_Index()) {\n\t\t\t\t\t\tretcode = EV_GAME_SIGNOFF;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tretcode = EV_PLAYER_SIGNOFF;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tRemove game name from game list\n\t\t\t\t//...............................................................\n\t\t\t\tdelete Session.Games[i];\n\t\t\t\tSession.Games.Delete(Session.Games[i]);\n\t\t\t\titem = (char *)(gamelist->Get_Item (i));\n\t\t\t\tgamelist->Remove_Item (item);\n\t\t\t\tdelete [] item;\n\t\t\t\tgamelist->Flag_To_Redraw();\n\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tRemove this name from the list of players\n\t\t//.....................................................................\n\t\tfor (i = 0; i < Session.Players.Count(); i++) {\n\n\t\t\t//..................................................................\n\t\t\t//\tName found; remove it\n\t\t\t//..................................................................\n\t\t\tif (Session.Players[i]->Address==Session.GAddress) {\n\t\t\t\titem = (char *)(playerlist->Get_Item(i));\n\t\t\t\tplayerlist->Remove_Item(item);\n\t\t\t\tdelete [] item;\n\n\t\t\t\tdelete Session.Players[i];\n\t\t\t\tSession.Players.Delete(Session.Players[i]);\n\n\t\t\t\tplayerlist->Flag_To_Redraw();\n\n\t\t\t\t//...............................................................\n\t\t\t\t// If this player has left our game, play a special sound.\n\t\t\t\t//...............................................................\n\t\t\t\tif ((*joinstate)>=JOIN_CONFIRMED) {\n\t\t\t\t\tSound_Effect(VOC_PLAYER_LEFT);\n\t\t\t\t}\n\n\t\t\t\tif (retcode == EV_NONE) {\n\t\t\t\t\tretcode = EV_PLAYER_SIGNOFF;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tRemove this name from the chat list\n\t\t//.....................................................................\n\t\tfor (i = 1; i < Session.Chat.Count(); i++) {\n\n\t\t\t//..................................................................\n\t\t\t//\tName found; remove it\n\t\t\t//..................................................................\n\t\t\tif (Session.Chat[i]->Address==Session.GAddress) {\n\n\t\t\t\tdelete Session.Chat[i];\n\t\t\t\tSession.Chat.Delete(Session.Chat[i]);\n\n\t\t\t\tif (retcode == EV_NONE) {\n\t\t\t\t\tretcode = EV_PLAYER_SIGNOFF;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_GO: The game's owner is signalling us to start playing.\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_GO) {\n\t\tif ( (*joinstate)==JOIN_CONFIRMED) {\n\t\t\tSession.MaxAhead = Session.GPacket.ResponseTime.OneWay;\n\t\t\t(*joinstate) = JOIN_GAME_START;\n\t\t\tretcode = EV_STATE_CHANGE;\n\t\t\tSession.HostAddress = Session.GAddress;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_LOADGAME: The game's owner is signalling us to start playing.\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_LOADGAME) {\n\t\tif ( (*joinstate)==JOIN_CONFIRMED) {\n\t\t\tSession.MaxAhead = Session.GPacket.ResponseTime.OneWay;\n\t\t\t(*joinstate) = JOIN_GAME_START_LOAD;\n\t\t\tretcode = EV_STATE_CHANGE;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t// NET_CHAT_ANNOUNCE: Someone is ready to chat; add them to our list, if\n\t// they aren't already on it, and it's not myself.\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_CHAT_ANNOUNCE) {\n\t\tfound = 0;\n\t\t//.....................................................................\n\t\t// If this packet is from myself, don't add it to the list\n\t\t//.....................................................................\n\t\tif (Session.GPacket.Chat.ID == Session.UniqueID) {\n\t\t\tfound = 1;\n\t\t}\n\t\t//.....................................................................\n\t\t// Otherwise, see if we already have this address stored in our list\n\t\t// If so, update that node's time values & name (in case the user\n\t\t// changed it), and return.\n\t\t//.....................................................................\n\t\telse {\n\t\t\tfor (i = 0; i < Session.Chat.Count(); i++) {\n\t\t\t\tif (Session.Chat[i]->Address==Session.GAddress) {\n\t\t\t\t\tstrcpy (Session.Chat[i]->Name, Session.GPacket.Name);\n\t\t\t\t\tSession.Chat[i]->Chat.LastTime = TickCount;\n\t\t\t\t\tSession.Chat[i]->Chat.LastChance = 0;\n\t\t\t\t\tSession.Chat[i]->Chat.Color = Session.GPacket.Chat.Color;\n\t\t\t\t\tfound = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t//.....................................................................\n\t\t// Add a new node to the list\n\t\t//.....................................................................\n\t\tif (!found) {\n\t\t\twho = new NodeNameType;\n\t\t\tstrcpy (who->Name, Session.GPacket.Name);\n\t\t\twho->Address = Session.GAddress;\n\t\t\twho->Chat.LastTime = TickCount;\n\t\t\twho->Chat.LastChance = 0;\n\t\t\twho->Chat.Color = Session.GPacket.Chat.Color;\n\t\t\tSession.Chat.Add (who);\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t// NET_CHAT_REQUEST: Someone is requesting a CHAT_ANNOUNCE from us; send\n\t// one to him directly.\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_CHAT_REQUEST) {\n\t\tif ((*joinstate) != JOIN_WAIT_CONFIRM && (*joinstate) != JOIN_CONFIRMED) {\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\tSession.GPacket.Command = NET_CHAT_ANNOUNCE;\n\t\t\tstrcpy(Session.GPacket.Name, my_name);\n\t\t\tSession.GPacket.Chat.ID = Session.UniqueID;\n\t\t\tSession.GPacket.Chat.Color = Session.ColorIdx;\n\n\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\tsizeof(GlobalPacketType), 1, &Session.GAddress);\n\n\t\t\tIpx.Service();\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t// NET_MESSAGE: Someone is sending us a message\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_MESSAGE) {\n\t\t//.....................................................................\n\t\t// If we're in a game, the sender must be in our game.\n\t\t//.....................................................................\n\t\tif ( (*joinstate)==JOIN_CONFIRMED) {\n\t\t\tif (Session.GPacket.Message.NameCRC ==\n\t\t\t\tCompute_Name_CRC(Session.GameName)) {\n\t\t\t\tSession.Messages.Add_Message (Session.GPacket.Name,\n\t\t\t\t\t(Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,\n\t\t\t\t\tSession.GPacket.Message.Buf,\n\t\t\t\t\t(Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,\n\t\t\t\t\tTPF_TEXT, -1);\n\t\t\t}\n\t\t}\n\t\t//.....................................................................\n\t\t// Otherwise, we're in the chat room; display any old message.\n\t\t//.....................................................................\n\t\telse {\n\t\t\tSession.Messages.Add_Message (Session.GPacket.Name,\n\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\tSession.GPacket.Message.Buf,\n\t\t\t\t(Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,\n\t\t\t\tTPF_TEXT, -1);\n\t\t}\n\n\t\tretcode = EV_MESSAGE;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_PING: Someone is pinging me to get a response time measure (will only\n\t//\thappen after I've joined a game).  Do nothing; the IPX Manager will handle\n\t//\tsending an ACK, and updating the response time measurements.\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_PING) {\n\t\tretcode = EV_NONE;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tDefault case: nothing happened.  (This case will be hit every time I\n\t//\treceive my own NET_QUERY_GAME or NET_QUERY_PLAYER packets.)\n\t//------------------------------------------------------------------------\n\telse {\n\t\tretcode = EV_NONE;\n\t}\n\n\treturn(retcode);\n\n}\t/* end of Get_Join_Responses */\n\n\n/***********************************************************************************************\n * Net_New_Dialog -- lets user start a new game                                                *\n *                                                                                             *\n * This dialog shows a list of who's requesting to join this game, and lets                    *\n * the game initiator selectively approve each user.                                           *\n *                                                                                             *\n * The 'Players' vector matches one-for-one the contents of the list box.  The local system\t  *\n * is always listed first; the IPX Address of the local system will NOT be valid in the\t\t  *\n * Players vector.  The Games & Players vectors should be left filled in even after this\t\t  *\n * routine is exited; their contents are used to form connections to the other players,\t\t  *\n * after the scenario has been loaded.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = success, false = cancel                                                         *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      Session.GameName must contain this player's name.                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nstatic int Net_New_Dialog(void)\n{\n\ttypedef enum {\n\t\tNUM_MESSAGES = 10\n\t} NumMessagesType;\n\n\t//------------------------------------------------------------------------\n\t//\tDialog & button dimensions\n\t//------------------------------------------------------------------------\n\tint d_dialog_w = 320 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 200 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320 *RESFACTOR- d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\tint d_dialog_y = ((200 *RESFACTOR- d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_txt6_h = 6*RESFACTOR+1;\t\t\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_margin1 = 5*RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\tint d_margin2 = 2*RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n//BG\tint d_playerlist_w = 118*RESFACTOR;\n\tint d_playerlist_w = 124*RESFACTOR;\n\tint d_playerlist_h = (6 * d_txt6_h) + 3*RESFACTOR;\t\t\t// 6 rows high\n\tint d_playerlist_x = d_dialog_x + d_margin1 + d_margin1 + 5*RESFACTOR;\n\tint d_playerlist_y = d_dialog_y + d_margin1 + d_txt6_h + 3*RESFACTOR;\n\n\tint d_scenariolist_w = 162*RESFACTOR;\n\tint d_scenariolist_h = (6 * d_txt6_h) + 3*RESFACTOR;\t\t// 6 rows high\n\tint d_scenariolist_x = d_dialog_x + d_dialog_w - d_margin1 - d_margin1 - d_scenariolist_w - (5*RESFACTOR);\n\tint d_scenariolist_y = d_playerlist_y;\n\n\tint d_reject_w = 55*RESFACTOR;\n\tint d_reject_h = 9*RESFACTOR;\n\tint d_reject_x = d_playerlist_x + (d_playerlist_w / 2) - (d_reject_w / 2);\n\tint d_reject_y = d_playerlist_y + d_playerlist_h + d_margin2;\n\n\tint d_count_w = 25*RESFACTOR;\n\tint d_count_h = d_txt6_h;\n\tint d_count_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR;\t\t// (fudged)\n\tint d_count_y = d_reject_y + d_reject_h /*KO+ d_margin2*/;\n\n\tint d_level_w = 25*RESFACTOR;\n\tint d_level_h = d_txt6_h;\n\tint d_level_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR;\t\t// (fudged)\n\tint d_level_y = d_count_y + d_count_h;\n\n\tint d_credits_w = 25*RESFACTOR;\n\tint d_credits_h = d_txt6_h;\n\tint d_credits_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR;\t// (fudged)\n\tint d_credits_y = d_level_y + d_level_h;\n\n\tint d_aiplayers_w = 25*RESFACTOR;\n\tint d_aiplayers_h = d_txt6_h;\n\tint d_aiplayers_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR;\t// (fudged)\n\tint d_aiplayers_y = d_credits_y + d_credits_h;\n\n\tint d_options_w = 106*RESFACTOR;\n\tint d_options_h = ((5 * 6) + 4)*RESFACTOR;\n\tint d_options_x = d_scenariolist_x + ((d_scenariolist_w - d_options_w) / 2);\n\tint d_options_y = d_scenariolist_y + d_scenariolist_h + d_margin1;\n\n\tint d_message_w = d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR;\n\tint d_message_h = (NUM_MESSAGES * d_txt6_h) + 3*RESFACTOR;\t// 10 rows high\n\tint d_message_x = d_dialog_x + d_margin1 + 10*RESFACTOR;\n\tint d_message_y = d_dialog_y + d_dialog_h - (27*RESFACTOR + d_message_h);\n//\tint d_message_y = d_options_y + d_options_h + d_margin1;\n\n\tint d_send_w = d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR;\n\tint d_send_h = 9*RESFACTOR;\n\tint d_send_x = d_dialog_x + d_margin1 + 10*RESFACTOR;\n\tint d_send_y = d_message_y + d_message_h;\n\n\tint d_ok_w = 50*RESFACTOR;\n\tint d_ok_h = 9*RESFACTOR;\n\tint d_ok_x = d_dialog_x + (d_dialog_w / 6) - (d_ok_w / 2);\n\tint d_ok_y = d_dialog_y + d_dialog_h - d_ok_h - d_margin1 - 3*RESFACTOR;\n\n\tint d_cancel_w = 50*RESFACTOR;\n\tint d_cancel_h = 9*RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - (d_cancel_w / 2);\n\tint d_cancel_y = d_dialog_y + d_dialog_h - d_cancel_h - d_margin1 - 3*RESFACTOR;\n\n\tint d_load_w = 50*RESFACTOR;\n\tint d_load_h = 9*RESFACTOR;\n\tint d_load_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_load_w / 2);\n\tint d_load_y = d_dialog_y + d_dialog_h - d_load_h - d_margin1 - 3*RESFACTOR;\n\n\t//------------------------------------------------------------------------\n\t//\tButton Enumerations\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tBUTTON_PLAYERLIST = 100,\n\t\tBUTTON_SCENARIOLIST,\n\t\tBUTTON_REJECT,\n\t\tBUTTON_COUNT,\n\t\tBUTTON_LEVEL,\n\t\tBUTTON_CREDITS,\n\t\tBUTTON_AIPLAYERS,\n\t\tBUTTON_OPTIONS,\n\t\tBUTTON_OK,\n\t\tBUTTON_LOAD,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t//------------------------------------------------------------------------\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PARMS,\n\t\tREDRAW_MESSAGE,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t//------------------------------------------------------------------------\n\t//\tDialog variables\n\t//------------------------------------------------------------------------\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\n\tint transmit;\t\t\t\t\t\t\t\t// 1 = re-transmit new game options\n\n\tlong ok_timer = 0;\t\t\t\t\t\t// for timing OK button\n\tint index;\t\t\t\t\t\t\t\t\t// index for rejecting a player\n\tint rc;\n\tint i,j;\n\tchar *item;\n\tint tabs[] = {77*RESFACTOR};\t\t\t// tabs for player list box\n\tint optiontabs[] = {8*RESFACTOR};\t// tabs for option list box\n\n\tNodeNameType *who;\t\t\t\t\t\t// node to add to Players\n\tlong ping_timer = 0;\t\t\t\t\t\t// for sending Ping packets\n\n\tint color_used[MAX_MPLAYER_COLORS];\t// 1 = color has been used\n\tchar txt[80];\n\tJoinEventType whahoppa;\t\t\t\t\t// event generated by received packets\n\tstatic int first_time = 1;\t\t\t\t// 1 = 1st time this dialog is run\n\tCCFileClass loadfile (\"SAVEGAME.NET\");\n\tint load_game = 0;\t\t\t\t\t\t// 1 = load a saved game\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t//------------------------------------------------------------------------\n\t// Buttons\n\t//------------------------------------------------------------------------\n\tGadgetClass *commands;\t\t\t\t\t// button list\n\n\tColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tListClass scenariolist(BUTTON_SCENARIOLIST, d_scenariolist_x, d_scenariolist_y, d_scenariolist_w, d_scenariolist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tTextButtonClass rejectbtn(BUTTON_REJECT, TXT_REJECT, TPF_BUTTON, d_reject_x, d_reject_y);\n\tGaugeClass countgauge(BUTTON_COUNT, d_count_x, d_count_y, d_count_w, d_count_h);\n\tGaugeClass levelgauge(BUTTON_LEVEL, d_level_x, d_level_y, d_level_w, d_level_h);\n\tGaugeClass creditsgauge(BUTTON_CREDITS, d_credits_x, d_credits_y, d_credits_w, d_credits_h);\n\tGaugeClass aiplayersgauge(BUTTON_AIPLAYERS, d_aiplayers_x, d_aiplayers_y, d_aiplayers_w, d_aiplayers_h);\n\tCheckListClass optionlist(BUTTON_OPTIONS, d_options_x, d_options_y, d_options_w, d_options_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tTextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_BUTTON, d_ok_x, d_ok_y, 60*RESFACTOR);\n\tTextButtonClass loadbtn(BUTTON_LOAD, TXT_LOAD_BUTTON, TPF_BUTTON, d_load_x, d_load_y, 60*RESFACTOR);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, 60*RESFACTOR);\n\n\tStaticButtonClass staticunit(0, \"    \", TPF_TEXT, d_count_x + d_count_w + 2*RESFACTOR, d_count_y);\n\tStaticButtonClass staticlevel(0, \"    \", TPF_TEXT, d_level_x + d_level_w + 2*RESFACTOR, d_level_y);\n\tStaticButtonClass staticcredits(0, \"         \", TPF_TEXT, d_credits_x + d_credits_w + 2*RESFACTOR, d_credits_y);\n\tStaticButtonClass staticaiplayers(0, \"   \", TPF_TEXT, d_aiplayers_x + d_aiplayers_w + 2*RESFACTOR, d_aiplayers_y);\n\n\t//------------------------------------------------------------------------\n\t//\tBuild the button list\n\t//------------------------------------------------------------------------\n\tcommands = &playerlist;\n\tscenariolist.Add_Tail(*commands);\n\trejectbtn.Add_Tail(*commands);\n\tstaticunit.Add_Tail(*commands);\n\tstaticlevel.Add_Tail(*commands);\n\tstaticcredits.Add_Tail(*commands);\n\tstaticaiplayers.Add_Tail(*commands);\n\tcountgauge.Add_Tail(*commands);\n\tcreditsgauge.Add_Tail(*commands);\n\taiplayersgauge.Add_Tail(*commands);\n\tlevelgauge.Add_Tail(*commands);\n\toptionlist.Add_Tail(*commands);\n\tokbtn.Add_Tail(*commands);\n\tcancelbtn.Add_Tail(*commands);\n\tif (loadfile.Is_Available()) {\n#ifdef FIXIT_MULTI_SAVE\n//\t\tloadbtn.Add_Tail(*commands);\n#endif\n\t} else {\n\t\tcancelbtn.X = loadbtn.X;\n\t}\n\tplayerlist.Set_Tabs(tabs);\n\n\t//------------------------------------------------------------------------\n\t//\tInit dialog values, only the first time through\n\t//------------------------------------------------------------------------\n\tSpecial.IsCaptureTheFlag = Rule.IsMPCaptureTheFlag;\n\tif (first_time) {\n\t\tSession.Options.Credits = Rule.MPDefaultMoney;\t\t\t// init credits & credit buffer\n\t\tSession.Options.Bases = Rule.IsMPBasesOn;\t\t\t\t\t// init scenario parameters\n\t\tSession.Options.Tiberium = Rule.IsMPTiberiumGrow;\n\t\tSession.Options.Goodies = Rule.IsMPCrates;\n\t\tSession.Options.AIPlayers = 0;\n\t\tSession.Options.UnitCount =\n\t\t\t(SessionClass::CountMax[Session.Options.Bases] +\n\t\t\tSessionClass::CountMin[Session.Options.Bases]) / 2;\n\t\tfirst_time = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tInit button states\n\t//------------------------------------------------------------------------\n\toptionlist.Set_Tabs(optiontabs);\n\toptionlist.Set_Read_Only(0);\n\n\toptionlist.Add_Item(Text_String(TXT_BASES));\n\toptionlist.Add_Item(Text_String(TXT_ORE_SPREADS));\n\toptionlist.Add_Item(Text_String(TXT_CRATES));\n\toptionlist.Add_Item(Text_String(TXT_CAPTURE_THE_FLAG));\n\toptionlist.Add_Item(Text_String(TXT_SHADOW_REGROWS));\n\n\toptionlist.Check_Item(0, Session.Options.Bases);\n\toptionlist.Check_Item(1, Session.Options.Tiberium);\n\toptionlist.Check_Item(2, Session.Options.Goodies);\n\toptionlist.Check_Item(3, Special.IsCaptureTheFlag);\n\toptionlist.Check_Item(4, Special.IsShadowGrow);\n\n\tcountgauge.Set_Maximum(SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]);\n\tcountgauge.Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]);\n\n\tlevelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1);\n\tlevelgauge.Set_Value(BuildLevel - 1);\n\n\tcreditsgauge.Set_Maximum(Rule.MPMaxMoney);\n\tcreditsgauge.Set_Value(Session.Options.Credits);\n\n\t//------------------------------------------------------------------------\n\t//\tInit other scenario parameters\n\t//------------------------------------------------------------------------\n\tSpecial.IsTGrowth = Session.Options.Tiberium;\n\tRule.IsTGrowth = Session.Options.Tiberium;\n\tSpecial.IsTSpread = Session.Options.Tiberium;\n\tRule.IsTSpread = Session.Options.Tiberium;\n\ttransmit = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInit scenario description list box\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Session.Scenarios.Count(); i++) {\n\t\tfor (j = 0; EngMisStr[j] != NULL;  j++) {\n\t\t\tif (!strcmp(Session.Scenarios[i]->Description(), EngMisStr[j])) {\n#ifdef FIXIT_CSII\t//\tajw Added Aftermath installed checks (before, it was assumed).\n\t\t\t\t//\tAdd mission if it's available to us.\n\t\t\t\tif( !( ( Is_Mission_Counterstrike((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Counterstrike_Installed() ) ||\n\t\t\t\t\t\t( Is_Mission_Aftermath((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Aftermath_Installed() ) ) )\n#endif\n#if defined(GERMAN) || defined(FRENCH)\n\t\t\t\t\tscenariolist.Add_Item(EngMisStr[j+1]);\n#else\n\t\t\t\t\tscenariolist.Add_Item(EngMisStr[j]);\n#endif\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif ( EngMisStr[j] == NULL) {\n#ifdef FIXIT_CSII\t//\tajw Added Aftermath installed checks (before, it was assumed). Added officialness check.\n\t\t\t//\tAdd mission if it's available to us.\n\t\t\tif( !Session.Scenarios[i]->Get_Official() ||\n\t\t\t\t!( ( Is_Mission_Counterstrike((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Counterstrike_Installed() ) ||\n\t\t\t\t\t( Is_Mission_Aftermath((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Aftermath_Installed() ) ) )\n#endif\n\t\t\t{\n\t\t\t\tscenariolist.Add_Item(Session.Scenarios[i]->Description());\n\t\t\t}\n\t\t}\n\t}\n\n\tSession.Options.ScenarioIndex = 0;\t// 1st scenario is selected\n#ifdef FIXIT_VERSION_3\n\tbAftermathMultiplayer = Is_Aftermath_Installed();\n//\tdebugprint( \"Host decides that, initially, bAftermathMultiplayer is %i\\n\", bAftermathMultiplayer );\n#else\n\tPlayingAgainstVersion = VerNum.Version_Number();\n#endif\n\n\t//------------------------------------------------------------------------\n\t//\tInit player color-used flags\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MAX_MPLAYER_COLORS; i++) {\n\t\tcolor_used[i] = 0;\t\t\t\t\t\t\t// init all colors to available\n\t}\n\tcolor_used[Session.ColorIdx] = 1;\t\t\t// set my color to used\n\tplayerlist.Set_Selected_Style(ColorListClass::SELECT_BAR, scheme);\n\n\t//------------------------------------------------------------------------\n\t//\tInit random-number generator, & create a seed to be used for all random\n\t//\tnumbers from here on out\n\t//------------------------------------------------------------------------\n\tsrand(time(NULL));\n\tSeed = rand();\n\n\t//------------------------------------------------------------------------\n\t//\tInit the message display system\n\t//------------------------------------------------------------------------\n\tSession.Messages.Init(d_message_x + 1*RESFACTOR, d_message_y + 1*RESFACTOR, NUM_MESSAGES,\n\t\tMAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1*RESFACTOR, d_send_y + 1*RESFACTOR, 1,\n\t\t20, MAX_MESSAGE_LENGTH - 5, d_message_w);\n\tSession.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message_w);\n\n\t//------------------------------------------------------------------------\n\t//\tInit the version-clipping system\n\t//------------------------------------------------------------------------\n\tVerNum.Init_Clipping();\n\n\t//------------------------------------------------------------------------\n\t//\tClear the list of players\n\t//------------------------------------------------------------------------\n\tClear_Vector(&Session.Players);\n\n\t//------------------------------------------------------------------------\n\t//\tAdd myself to the list, and to the Players vector.\n\t//------------------------------------------------------------------------\n\titem = new char [MPLAYER_NAME_MAX + 64];\n#ifdef OLDWAY\n\tif (Session.House==HOUSE_GOOD) {\n\t\tsprintf(item,\"%s\\t%s\",Session.Handle, Text_String(TXT_ALLIES));\n\t} else {\n\t\tsprintf(item,\"%s\\t%s\",Session.Handle, Text_String(TXT_SOVIET));\n\t}\n#else\t//OLDWAY\n\t\tsprintf (item, \"%s\\t%s\", Session.Handle, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\tplayerlist.Add_Item(item,\n\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]);\n\n\twho = new NodeNameType;\n\tstrcpy(who->Name, Session.Handle);\n\twho->Player.House = Session.House;\n\twho->Player.Color = Session.ColorIdx;\n\tSession.Players.Add (who);\n\tLoad_Title_Page(true);\n\tCCPalette.Set();\t//GamePalette.Set();\n\n\t//\n\t// Now init the max range of the AI players slider.\n\t//\n\taiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count());\n\taiplayersgauge.Set_Value(Session.Options.AIPlayers);\n\n\t//------------------------------------------------------------------------\n\t//\tProcessing loop\n\t//------------------------------------------------------------------------\n\twhile (process) {\n\t\t#if(SHOW_MONO)\n\t\tIpx.Mono_Debug_Print(-1,0);\n\t\t#endif\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\t#endif\n\t\t//.....................................................................\n\t\t//\tRefresh display if needed\n\t\t//.....................................................................\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw backgound & dialog box\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tDialog & Field labels\n\t\t\t\t//...............................................................\n\t\t\t\tFancy_Text_Print(TXT_PLAYERS, d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h, scheme, TBLACK, TPF_TEXT | TPF_CENTER);\n\t\t\t\tFancy_Text_Print(TXT_SCENARIOS, d_scenariolist_x + (d_scenariolist_w / 2), d_scenariolist_y - d_txt6_h, scheme, TBLACK, TPF_TEXT | TPF_CENTER);\n\t\t\t\tFancy_Text_Print(TXT_COUNT, d_count_x - 2*RESFACTOR, d_count_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print(TXT_LEVEL, d_level_x - 2*RESFACTOR, d_level_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print(TXT_CREDITS_COLON, d_credits_x - 2*RESFACTOR, d_credits_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print(TXT_AI_PLAYERS_COLON, d_aiplayers_x - 2*RESFACTOR, d_aiplayers_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw buttons\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\n\t\t\t\t/*\n\t\t\t\t** Zap, Zap, Zap\n\t\t\t\t*/\n\t\t\t\tplayerlist.Zap();\n\t\t\t\tscenariolist.Zap();\n\t\t\t\trejectbtn.Zap();\n\t\t\t\tstaticunit.Zap();\n\t\t\t\tstaticlevel.Zap();\n\t\t\t\tstaticcredits.Zap();\n\t\t\t\tstaticaiplayers.Zap();\n\t\t\t\tcountgauge.Zap();\n\t\t\t\tcreditsgauge.Zap();\n\t\t\t\taiplayersgauge.Zap();\n\t\t\t\tlevelgauge.Zap();\n\t\t\t\toptionlist.Zap();\n\t\t\t\tokbtn.Zap();\n\t\t\t\tcancelbtn.Zap();\n\t\t\t\tloadbtn.Zap();\n\n\n\t\t\t\t/*\n\t\t\t\t** Hack hack, hack\n\t\t\t\t*/\n\t\t\t\tcommands = &playerlist;\n\t\t\t\tscenariolist.Add_Tail(*commands);\n\t\t\t\trejectbtn.Add_Tail(*commands);\n\t\t\t\tstaticunit.Add_Tail(*commands);\n\t\t\t\tstaticlevel.Add_Tail(*commands);\n\t\t\t\tstaticcredits.Add_Tail(*commands);\n\t\t\t\tstaticaiplayers.Add_Tail(*commands);\n\t\t\t\tcountgauge.Add_Tail(*commands);\n\t\t\t\tcreditsgauge.Add_Tail(*commands);\n\t\t\t\taiplayersgauge.Add_Tail(*commands);\n\t\t\t\tlevelgauge.Add_Tail(*commands);\n\t\t\t\toptionlist.Add_Tail(*commands);\n\t\t\t\tokbtn.Add_Tail(*commands);\n\t\t\t\tcancelbtn.Add_Tail(*commands);\n#ifdef FIXIT_VERSION_3\n\t\t\t\tif( loadfile.Is_Available() ) {\n#else\n\t\t\t\tif (loadfile.Is_Available() && PlayingAgainstVersion > VERSION_RED_ALERT_104 ) {\n#endif\n#ifdef FIXIT_MULTI_SAVE\n\t\t\t\t\tloadbtn.Add_Tail(*commands);\n#endif\n\t\t\t\t}\n\t\t\t\tcommands->Draw_All();\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tDraw the messages:\n\t\t\t//\t- Erase an old message first\n\t\t\t//\t- If we're in a game, print the game options (if they've been\n\t\t\t//\t  received)\n\t\t\t//\t- If we've been rejected from a game, print that message\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_MESSAGE) {\n\t\t\t\tDraw_Box(d_message_x, d_message_y, d_message_w, d_message_h, BOXSTYLE_BOX, true);\n\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true);\n\t\t\t\tSession.Messages.Draw();\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// Update game parameter labels\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_PARMS) {\n//\t\t\t\tLogicPage->Fill_Rect(d_count_x + d_count_w + 2*RESFACTOR, d_count_y, d_count_x + d_count_w + 35*RESFACTOR, d_aiplayers_y + d_aiplayers_h+RESFACTOR, BLACK);\n\n\t\t\t\tsprintf(txt,\"%d\",Session.Options.UnitCount);\n\t\t\t\tstaticunit.Set_Text(txt);\n\t\t\t\tstaticunit.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_count_x + d_count_w + 2*RESFACTOR, d_count_y, scheme, BLACK, TPF_TEXT);\n\n\t\t\t\tif (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {\n\t\t\t\t\tsprintf(txt,\"%d\",BuildLevel);\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(txt, \"**\");\n\t\t\t\t}\n\t\t\t\tstaticlevel.Set_Text(txt);\n\t\t\t\tstaticlevel.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_level_x + d_level_w + 2*RESFACTOR, d_level_y, scheme, BLACK, TPF_TEXT);\n\n\t\t\t\tsprintf(txt,\"%d\",Session.Options.Credits);\n\t\t\t\tstaticcredits.Set_Text(txt);\n\t\t\t\tstaticcredits.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_credits_x + d_credits_w + 2*RESFACTOR, d_credits_y, scheme, BLACK, TPF_TEXT);\n\n\t\t\t\tsprintf(txt,\"%d\",Session.Options.AIPlayers);\n\t\t\t\tstaticaiplayers.Set_Text(txt);\n\t\t\t\tstaticaiplayers.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_aiplayers_x + d_aiplayers_w + 2*RESFACTOR, d_aiplayers_y, scheme, BLACK, TPF_TEXT);\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tGet user input\n\t\t//.....................................................................\n\t\tinput = commands->Input();\n\n\t\t//.....................................................................\n\t\t//\tProcess input\n\t\t//.....................................................................\n\t\tswitch (input) {\n\n\t\t\t//..................................................................\n\t\t\t//\tNew Scenario selected.\n\t\t\t//..................................................................\n#ifdef FIXIT_VERSION_3\t\t//\tAll scenarios now allowable as downloads. ajw\n\t\t\tcase (BUTTON_SCENARIOLIST | KN_BUTTON):\n\t\t\t\tif (scenariolist.Current_Index() != Session.Options.ScenarioIndex)\n\t\t\t\t{\n\t\t\t\t\tSession.Options.ScenarioIndex = scenariolist.Current_Index();\n\t\t\t\t\ttransmit = 1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n#else\t//\tFIXIT_VERSION_3\n\t\t\tcase (BUTTON_SCENARIOLIST | KN_BUTTON):\n\t\t\t\tif (scenariolist.Current_Index() != Session.Options.ScenarioIndex) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw\n\t\t\t\t\tif ((PlayingAgainstVersion != VERSION_RED_ALERT_107 && PlayingAgainstVersion != VERSION_RED_ALERT_108 && PlayingAgainstVersion < VERSION_AFTERMATH_CS) &&\n#else\n\t\t\t\t\tif (PlayingAgainstVersion < VERSION_RED_ALERT_107 &&\n#endif\n\t\t\t\t\t\t\t\tSession.Scenarios[scenariolist.Current_Index()]->Get_Expansion()){\n\t\t\t\t\t\tscenariolist.Set_Selected_Index (Session.Options.ScenarioIndex);\n\t\t\t\t\t\tSession.Messages.Add_Message(NULL, 0,\n\t\t\t\t\t\t\t(char *)Text_String(TXT_NO_CS_SCENARIOS), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n#ifdef FIXIT_CSII\t//\tchecked - ajw\n\t\t\t\t\t}else\n\t\t\t\t\tif (PlayingAgainstVersion < VERSION_AFTERMATH_CS &&\n\t\t\t\t\t\t\tIs_Mission_126x126((char *)Session.Scenarios[scenariolist.Current_Index()]->Get_Filename() ) ){\n\t\t\t\t\t\tscenariolist.Set_Selected_Index (Session.Options.ScenarioIndex);\n\t\t\t\t\t\tSession.Messages.Add_Message(NULL, 0,\n\t\t\t\t\t\t\t(char *)Text_String(TXT_NO_CS_SCENARIOS), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n#endif\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSession.Options.ScenarioIndex = scenariolist.Current_Index();\n\t\t\t\t\t\ttransmit = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n#endif\t//\tFIXIT_VERSION_3\n\n\t\t\t//..................................................................\n\t\t\t//\tReject the currently-selected player (don't allow rejecting myself,\n\t\t\t//\twho will be the first entry in the list)\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_REJECT | KN_BUTTON):\n\t\t\t\tindex = playerlist.Current_Index();\n\n\t\t\t\tif (index == 0) {\n\t\t\t\t\tSession.Messages.Add_Message(NULL, 0,\n\t\t\t\t\t\t(char *)Text_String(TXT_CANT_REJECT_SELF), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else if (index < 0 || index >= playerlist.Count()) {\n\t\t\t\t\tSession.Messages.Add_Message(NULL, 0,\n\t\t\t\t\t\t(char *)Text_String(TXT_SELECT_PLAYER_REJECT),\n\t\t\t\t\t\tPCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\t\tSession.GPacket.Command = NET_REJECT_JOIN;\n\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\tsizeof (GlobalPacketType), 1,\n\t\t\t\t\t&(Session.Players[index]->Address));\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tUser adjusts max # units\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_COUNT | KN_BUTTON):\n\t\t\t\tSession.Options.UnitCount = countgauge.Get_Value() +\n\t\t\t\t\tSessionClass::CountMin[Session.Options.Bases];\n\t\t\t\ttransmit = 1;\n\t\t\t\tdisplay = REDRAW_PARMS;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tUser adjusts build level\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_LEVEL | KN_BUTTON):\n\t\t\t\tBuildLevel = levelgauge.Get_Value() + 1;\n\t\t\t\tif (BuildLevel > MPLAYER_BUILD_LEVEL_MAX)\t// if it's pegged, max it out\n\t\t\t\t\tBuildLevel = MPLAYER_BUILD_LEVEL_MAX;\n\t\t\t\ttransmit = 1;\n\t\t\t\tdisplay = REDRAW_PARMS;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tUser edits the credits value; retransmit new game options\n\t\t\t// Round the credits to the nearest 500.\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_CREDITS | KN_BUTTON):\n\t\t\t\tSession.Options.Credits = creditsgauge.Get_Value();\n\t\t\t\tSession.Options.Credits =\n\t\t\t\t\t((Session.Options.Credits + 250) / 500) * 500;\n\t\t\t\ttransmit = 1;\n\t\t\t\tdisplay = REDRAW_PARMS;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tUser adjusts # of AI players\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_AIPLAYERS | KN_BUTTON):\n\t\t\t\tSession.Options.AIPlayers = aiplayersgauge.Get_Value();\n\t\t\t\tif (Session.Options.AIPlayers+Session.Players.Count() > Rule.MaxPlayers) {\t// if it's pegged, max it out\n\t\t\t\t\tSession.Options.AIPlayers = Rule.MaxPlayers - Session.Players.Count();\n\t\t\t\t\taiplayersgauge.Set_Value(Session.Options.AIPlayers);\n\t\t\t\t}\n\t\t\t\ttransmit = 1;\n\t\t\t\tdisplay = REDRAW_PARMS;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t// Toggle-able options:\n\t\t\t// If 'Bases' gets toggled, we have to change the range of the\n\t\t\t// UnitCount slider.\n\t\t\t// Also, if Tiberium gets toggled, we have to set the flags\n\t\t\t// in SpecialClass.\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_OPTIONS | KN_BUTTON):\n\t\t\t\tif (Special.IsCaptureTheFlag != optionlist.Is_Checked(3) && !Special.IsCaptureTheFlag) {\n\t\t\t\t\toptionlist.Check_Item(0, true);\n\t\t\t\t}\n\t\t\t\tif (Session.Options.Bases != optionlist.Is_Checked(0)) {\n\t\t\t\t\tSession.Options.Bases = optionlist.Is_Checked(0);\n\t\t\t\t\tif (Session.Options.Bases) {\n\t\t\t\t\t\tSession.Options.UnitCount = Fixed_To_Cardinal (\n\t\t\t\t\t\t\tSessionClass::CountMax[1] -\n\t\t\t\t\t\t\tSessionClass::CountMin[1],\n\t\t\t\t\t\t\tCardinal_To_Fixed(\n\t\t\t\t\t\t\t\tSessionClass::CountMax[0]-SessionClass::CountMin[0],\n\t\t\t\t\t\t\t\tSession.Options.UnitCount-SessionClass::CountMin[0])) +\n\t\t\t\t\t\t\tSessionClass::CountMin[1];\n\t\t\t\t\t} else {\n\t\t\t\t\t\toptionlist.Check_Item(3, false);\n\t\t\t\t\t\tSession.Options.UnitCount = Fixed_To_Cardinal (\n\t\t\t\t\t\t\tSessionClass::CountMax[0] -\n\t\t\t\t\t\t\tSessionClass::CountMin[0],\n\t\t\t\t\t\t\tCardinal_To_Fixed(\n\t\t\t\t\t\t\t\tSessionClass::CountMax[1]-SessionClass::CountMin[1],\n\t\t\t\t\t\t\t\tSession.Options.UnitCount - SessionClass::CountMin[1])) +\n\t\t\t\t\t\t\tSessionClass::CountMin[0];\n\t\t\t\t\t}\n\t\t\t\t\tcountgauge.Set_Maximum(\n\t\t\t\t\t\tSessionClass::CountMax[Session.Options.Bases] -\n\t\t\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\t\t\tcountgauge.Set_Value(Session.Options.UnitCount -\n\t\t\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\t\t}\n\t\t\t\tSession.Options.Tiberium = optionlist.Is_Checked(1);\n\t\t\t\tSpecial.IsTGrowth = Session.Options.Tiberium;\n\t\t\t\tRule.IsTGrowth = Session.Options.Tiberium;\n\t\t\t\tSpecial.IsTSpread = Session.Options.Tiberium;\n\t\t\t\tRule.IsTSpread = Session.Options.Tiberium;\n\n\t\t\t\tSession.Options.Goodies = optionlist.Is_Checked(2);\n\t\t\t\tSpecial.IsCaptureTheFlag = optionlist.Is_Checked(3);\n\t\t\t\tSpecial.IsShadowGrow = optionlist.Is_Checked(4);\n\n\t\t\t\ttransmit = 1;\n\t\t\t\tdisplay = REDRAW_PARMS;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tOK: exit loop with TRUE status\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_LOAD | KN_BUTTON):\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf a new player has joined in the last second, don't allow\n\t\t\t\t//\tan OK; force a wait longer than 1 second (to give all players\n\t\t\t\t//\ta chance to know about this new guy)\n\t\t\t\t//...............................................................\n\t\t\t\ti = max(Ipx.Global_Response_Time() * 2, 60);\n\t\t\t\twhile (TickCount - ok_timer < i) {\n\t\t\t\t\tIpx.Service();\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf there are at least 2 players, go ahead & play; error otherwise\n\t\t\t\t//...............................................................\n\t\t\t\tif (Session.Players.Count() > 1 ) {\n//\t\t\t\tif (Session.Players.Count() + Session.Options.AIPlayers > 1 ) {\n\t\t\t\t\trc = TRUE;\n\t\t\t\t\tprocess = FALSE;\n\t\t\t\t} else {\n\t\t\t\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_ONLY_ONE), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t}\n\t\t\t\tif (input==(BUTTON_LOAD | KN_BUTTON)) {\n\t\t\t\t\tload_game = 1;\n\t\t\t\t} else {\n\t\t\t\t\tload_game = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tCANCEL: send a SIGN_OFF, bail out with error code\n\t\t\t//..................................................................\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\t\t\tstrcpy (Session.GPacket.Name, Session.Handle);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tBroadcast my sign-off over my network\n\t\t\t\t//...............................................................\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\tsizeof (GlobalPacketType), 0, NULL);\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\tsizeof (GlobalPacketType), 0, NULL);\n\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tBroadcast my sign-off over a bridged network if there is one\n\t\t\t\t//...............................................................\n\t\t\t\tif (Session.IsBridge) {\n\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\tsizeof(GlobalPacketType), 0, &Session.BridgeNet);\n\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\tsizeof(GlobalPacketType), 0, &Session.BridgeNet);\n\t\t\t\t}\n\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tAnd now, just be absolutely sure, send my sign-off to each\n\t\t\t\t//\tplayer in my game.  (If there's a bridge between us, the other\n\t\t\t\t//\tplayer will have specified my address, so he can cross the\n\t\t\t\t//\tbridge; but I may not have specified a bridge address, so the\n\t\t\t\t//\tonly way I have of crossing the bridge is to send a packet\n\t\t\t\t//\tdirectly to him.)\n\t\t\t\t// Don't send this message to myself.\n\t\t\t\t//...............................................................\n\t\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\tsizeof(GlobalPacketType), 1, &(Session.Players[i]->Address));\n\t\t\t\t\tIpx.Service();\n\t\t\t\t}\n\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\t\t\t\tSession.GameName[0] = 0;\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tDefault: manage the inter-player messages\n\t\t\t//..................................................................\n\t\t\tdefault:\n\t\t\t\tif (Session.Messages.Manage()) {\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tRe-draw the messages & service keyboard input for any message\n\t\t\t\t//\tbeing edited.\n\t\t\t\t//...............................................................\n\t\t\t\ti = Session.Messages.Input(input);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf 'Input' returned 1, it means refresh the message display.\n\t\t\t\t//...............................................................\n\t\t\t\tif (i==1) {\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h,\n\t\t\t\t\t\tBOXSTYLE_BOX, true);\t// (erase the cursor)\n\t\t\t\t\tSession.Messages.Draw();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t} else if (i==2) {\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf 'Input' returned 2, it means redraw the message display.\n\t\t\t\t//...............................................................\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h,\n\t\t\t\t\t\tBOXSTYLE_BOX, true);\t// (erase the cursor)\n\t\t\t\t\tSession.Messages.Draw();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t} else if (i==3 || i==4) {\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf 'input' returned 3, it means send the current message.\n\t\t\t\t//...............................................................\n\t\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\t\t\tSession.GPacket.Command = NET_MESSAGE;\n\t\t\t\t\tstrcpy (Session.GPacket.Name, Session.Handle);\n\t\t\t\t\tif (i==3) {\n\t\t\t\t\t\tstrcpy (Session.GPacket.Message.Buf,\n\t\t\t\t\t\t\tSession.Messages.Get_Edit_Buf());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstrcpy (Session.GPacket.Message.Buf,\n\t\t\t\t\t\t\tSession.Messages.Get_Overflow_Buf());\n\t\t\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t\t\t}\n\t\t\t\t\tSession.GPacket.Message.Color = Session.ColorIdx;\n\t\t\t\t\tSession.GPacket.Message.NameCRC =\n\t\t\t\t\t\tCompute_Name_CRC(Session.GameName);\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tSend the message to every player in our player list, except\n\t\t\t\t\t// myself.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\t\tsizeof(GlobalPacketType), 1,\n\t\t\t\t\t\t\t&(Session.Players[i]->Address));\n\t\t\t\t\t\tIpx.Service();\n\t\t\t\t\t}\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tAdd the message to our own list, since we're not in the\n\t\t\t\t\t// player list on this dialog.\n\t\t\t\t\t// If there's no message with this ID already displayed, just\n\t\t\t\t\t// add a new message; if there is one, concatenate it.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tSession.Messages.Add_Message (Session.GPacket.Name,\n\t\t\t\t\t\t(Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,\n\t\t\t\t\t\tSession.GPacket.Message.Buf,\n\t\t\t\t\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\tTPF_TEXT, -1);\n\n\t\t\t\t\tSession.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message_w);\n\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tProcess incoming packets\n\t\t//.....................................................................\n#ifndef FIXIT_VERSION_3\n\t\tint oldversion = PlayingAgainstVersion;\n#endif\n\t\twhahoppa = Get_NewGame_Responses(&playerlist, color_used);\n\t\tif (whahoppa == EV_NEW_PLAYER) {\n\t\t\tok_timer = TickCount;\n\t\t\taiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count());\n\t\t\tSession.Options.AIPlayers = aiplayersgauge.Get_Value();\n\t\t\tif (Session.Options.AIPlayers+Session.Players.Count() > Rule.MaxPlayers) {\t// if it's pegged, max it out\n\t\t\t\tSession.Options.AIPlayers = Rule.MaxPlayers - Session.Players.Count();\n \t\t\t\taiplayersgauge.Set_Value(Session.Options.AIPlayers);\n \t\t\t}\n#ifdef FIXIT_VERSION_3\t\t//\tAll scenarios now allowable for download, regardless of if CS scen. or 126x126 scen.\n\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n#else\t//\tFIXIT_VERSION_3\n\t\t\t\tif (oldversion == PlayingAgainstVersion){\n\t\t\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\t\t\t\t}else{\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If a CS scenario was selected and we now have a red alert only player\n\t\t\t\t\t** in the mix then deselect the cs scenario.\n\t\t\t\t\t*/\n\t#ifdef FIXIT_CSII\t//\tchecked - ajw\n\t\t\t\t\tif ((PlayingAgainstVersion != VERSION_RED_ALERT_107 && PlayingAgainstVersion != VERSION_RED_ALERT_108 && PlayingAgainstVersion < VERSION_AFTERMATH_CS) &&\n\t#else\n\t\t\t\t\tif (PlayingAgainstVersion < VERSION_RED_ALERT_107 &&\n\t#endif\n\t\t\t\t\t\t\t\tSession.Scenarios[scenariolist.Current_Index()]->Get_Expansion()){\n\t\t\t\t\t\tscenariolist.Set_Selected_Index (0);\n\t\t\t\t\t\tSession.Options.ScenarioIndex = scenariolist.Current_Index();\n\t\t\t\t\t}\n\t#ifdef FIXIT_CSII\t//\tchecked - ajw\n\t\t\t\t\t/*\n\t\t\t\t\t** If an AM mega scenario was selected and we now have a non-AM\n\t\t\t\t\t** player in the mix then deselect the mega scenario.\n\t\t\t\t\t*/\n\t\t\t\t\tif (PlayingAgainstVersion < VERSION_AFTERMATH_CS &&\n\t\t\t\t\t\t\t\tIs_Mission_126x126((char *)Session.Scenarios[scenariolist.Current_Index()]->Get_Filename() ) ){\n\t\t\t\t\t\tscenariolist.Set_Selected_Index (0);\n\t\t\t\t\t\tSession.Options.ScenarioIndex = scenariolist.Current_Index();\n\t\t\t\t\t}\n\t#endif\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n#endif\t//\tFIXIT_VERSION_3\n\n\t\t\ttransmit = 1;\n\t\t} else if (whahoppa == EV_MESSAGE) {\n\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t} else if (whahoppa == EV_PLAYER_SIGNOFF) {\n\t\t\taiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count());\n\t\t\tSession.Options.AIPlayers = aiplayersgauge.Get_Value();\n\t\t\tif (Session.Options.AIPlayers+Session.Players.Count() > Rule.MaxPlayers) {\t// if it's pegged, max it out\n\t\t\t\tSession.Options.AIPlayers = Rule.MaxPlayers - Session.Players.Count();\n \t\t\t\taiplayersgauge.Set_Value(Session.Options.AIPlayers);\n\t\t\t\tdisplay = REDRAW_PARMS;\n \t\t\t}\n\t\t\ttransmit = 1;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tIf our Transmit flag is set, we need to send out a game option packet\n\t\t// Don't send it to myself.\n\t\t//.....................................................................\n\t\tif (transmit) {\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\t\tSession.GPacket.Command = NET_GAME_OPTIONS;\n\n\t\t\t\t/*\n\t\t\t\t** Set up the scenario info so the remote player can match the scenario on his machine\n\t\t\t\t** or request a download if it doesnt exist\n\t\t\t\t*/\n\t\t\t\tstrcpy (Session.GPacket.ScenarioInfo.Scenario, Session.Scenarios[Session.Options.ScenarioIndex]->Description());\n\t\t\t\tCCFileClass file (Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename());\n\t\t\t\tSession.GPacket.ScenarioInfo.FileLength = file.Size();\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\tstrcpy( Session.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename() );\n#else\n\t\t\t\tstrncpy (Session.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename(), sizeof(Session.GPacket.ScenarioInfo.ShortFileName));\n#endif\n\t\t\t\tstrncpy ((char*)Session.GPacket.ScenarioInfo.FileDigest, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Digest(), sizeof (Session.GPacket.ScenarioInfo.FileDigest));\n\t\t\t\tSession.GPacket.ScenarioInfo.OfficialScenario = Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official();\n\n\t\t\t\tSession.GPacket.ScenarioInfo.Credits = Session.Options.Credits;\n\t\t\t\tSession.GPacket.ScenarioInfo.IsBases = Session.Options.Bases;\n\t\t\t\tSession.GPacket.ScenarioInfo.IsTiberium = Session.Options.Tiberium;\n\t\t\t\tSession.GPacket.ScenarioInfo.IsGoodies = Session.Options.Goodies;\n\t\t\t\tSession.GPacket.ScenarioInfo.BuildLevel = BuildLevel;\n\t\t\t\tSession.GPacket.ScenarioInfo.UnitCount = Session.Options.UnitCount;\n\t\t\t\tSession.GPacket.ScenarioInfo.AIPlayers = Session.Options.AIPlayers;\n\t\t\t\tSession.GPacket.ScenarioInfo.Seed = Seed;\n\t\t\t\tSession.GPacket.ScenarioInfo.Special = Special;\n\t\t\t\tSession.GPacket.ScenarioInfo.GameSpeed = Options.GameSpeed;\n#ifdef FIXIT_VERSION_3\n\t\t\t\tSession.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version();\n\t\t\t\t//\tHost encodes whether or not this is an Aftermath game in the highest bit.\n\t\t\t\tif( bAftermathMultiplayer )\n\t\t\t\t{\n//\t\t\t\t\tdebugprint( \"Host tells guests 'This is an Aftermath game'\\n\" );\n\t\t\t\t\tSession.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version() | 0x80000000;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n//\t\t\t\t\tdebugprint( \"Host tells guests 'This is NOT an Aftermath game'\\n\" );\n\t\t\t\t\tSession.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version();\n\t\t\t\t}\n#else\n\t\t\t\tSession.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version();\n#endif\n\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t1, &(Session.Players[i]->Address) );\n\t\t\t}\n\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t\ttransmit = 0;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tPing every player in my game, to force the Global Channel to measure\n\t\t//\tthe connection response time.  Don't ping myself (index 0).\n\t\t//.....................................................................\n\t\tif (TickCount - ping_timer > 15) {\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\tSession.GPacket.Command = NET_PING;\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t1, &(Session.Players[i]->Address) );\n\t\t\t}\n\t\t\tping_timer = TickCount;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tService the Ipx connections\n\t\t//.....................................................................\n\t\tIpx.Service();\n\n\t\t//.....................................................................\n\t\t//\tService the sounds & score; GameActive must be false at this point,\n\t\t//\tso Call_Back() doesn't intercept global messages from me!\n\t\t//.....................................................................\n\t\tCall_Back();\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tPrepare to load the scenario\n\t//------------------------------------------------------------------------\n\tif (rc) {\n\t\t//.....................................................................\n\t\t//\tSet the player count & scenario number\n\t\t//.....................................................................\n\t\tSession.NumPlayers = Session.Players.Count();\n\n\t\tScen.Scenario = Session.Options.ScenarioIndex;\n\t\tstrcpy (Scen.ScenarioName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename());\n\n\t\t//.....................................................................\n\t\t//\tCompute frame delay value for packet transmissions:\n\t\t//\t- Divide global channel's response time by 8 (2 to convert to 1-way\n\t\t//\t  value, 4 more to convert from ticks to frames)\n\t\t//.....................................................................\n\t\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\t\tSession.MaxAhead = max( ((((Ipx.Global_Response_Time() / 8) +\n\t\t\t\t(Session.FrameSendRate - 1)) / Session.FrameSendRate) *\n\t\t\t\tSession.FrameSendRate), (Session.FrameSendRate * 2) );\n\t\t}\n\t\telse {\n\t\t\tSession.MaxAhead = max( (Ipx.Global_Response_Time() / 8),\n\t\t\t\t\t\t\t\t\t\t  NETWORK_MIN_MAX_AHEAD );\n\t\t}\n\n\t\tIpx.Set_Timing (25, (unsigned long) -1, 1000);\n\n\t\t//.....................................................................\n\t\t//\tSend all players the NET_GO packet.  Wait until all ACK's have been\n\t\t//\treceived.\n\t\t//.....................................................................\n\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\tif (load_game)\n\t\t\tSession.GPacket.Command = NET_LOADGAME;\n\t\telse\n\t\t\tSession.GPacket.Command = NET_GO;\n\t\tSession.GPacket.ResponseTime.OneWay = Session.MaxAhead;\n\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t1, &(Session.Players[i]->Address) );\n\t\t}\n\t\t//.....................................................................\n\t\t//\tWait for all the ACK's to come in.\n\t\t//.....................................................................\n\t\twhile (Ipx.Global_Num_Send() > 0) {\n\t\t\tIpx.Service();\n\t\t}\n\n\t\t/*\n\t\t** Wait for the go responses from each player in case someone needs the scenario\n\t\t** file to be sent.\n\t\t*/\n\t\tint responses[20];\t\t//In big trub if more than 20 players\n\t\tmemset (responses, 0, sizeof (responses));\n\t\tint num_responses = 0;\n\t\tbool send_scenario = false;\n#ifdef WIN32\n\t\tWWDebugString (\"RA95 - About to wait for 'GO' response.\");\n#endif\n\t\tCDTimerClass<SystemTimerClass> response_timer;\t\t// timeout timer for waiting for responses\n\t\tresponse_timer = 60*10;\t\t// Wait for 10 seconds. If we dont hear by then assume someone crashed\n\n\t\tdo\t{\n\t\t\tIpx.Service();\n\t\t\tint retcode = Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen,\n\t\t\t\t&Session.GAddress, &Session.GProductID);\n\t\t\tif (retcode && Session.GProductID == IPXGlobalConnClass::COMMAND_AND_CONQUER0) {\n\n\t\t\t\tfor ( i=1 ; i<Session.Players.Count() ; i++ ) {\n\t\t\t\t\tif (Session.Players[i]->Address == Session.GAddress) {\n\t\t\t\t\t\tif (!responses[i]) {\n\t\t\t\t\t\t\tif (Session.GPacket.Command == NET_REQ_SCENARIO) {\n\t\t\t\t\t\t\t\tresponses[i] = Session.GPacket.Command;\n\t\t\t\t\t\t\t\tsend_scenario = true;\n\t\t\t\t\t\t\t\tnum_responses++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (Session.GPacket.Command == NET_READY_TO_GO) {\n\t\t\t\t\t\t\t\tresponses[i] = Session.GPacket.Command;\n\t\t\t\t\t\t\t\tnum_responses++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} while ( num_responses < Session.Players.Count()-1 && response_timer );\n\n#ifdef FIXIT_VERSION_3\n\t\tif( Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official() )\n\t\t{\n\t\t\tif( !Force_Scenario_Available( Scen.ScenarioName ) )\n\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t}\n#endif\n\n\t\t/*\n\t\t** If one of the machines requested that the scenario be sent then send it.\n\t\t*/\n\t\tif (send_scenario) {\n\t\t\tmemset (Session.ScenarioRequests, 0, sizeof (Session.ScenarioRequests));\n\t\t\tSession.RequestCount = 0;\n\t\t\tfor ( i=1 ; i<Session.Players.Count() ; i++ ) {\n\t\t\t\tif (responses[i] == NET_REQ_SCENARIO) {\n\t\t\t\t\tSession.ScenarioRequests[Session.RequestCount++] = i;\n\t\t\t\t}\n\t\t\t}\n\t\t\tSend_Remote_File (Scen.ScenarioName, 1);\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tInit network timing values, using previous response times as a measure\n\t//\tof what our retry delta & timeout should be.\n\t//------------------------------------------------------------------------\n\t//Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1, Ipx.Global_Response_Time() * 4);\n\tIpx.Set_Timing (Ipx.Global_Response_Time () + 2, (unsigned long) -1, max (120, Ipx.Global_Response_Time () * 8));\n\n\t//------------------------------------------------------------------------\n\t//\tClear all lists, but NOT the Games or Players vectors.\n\t//------------------------------------------------------------------------\n\twhile (scenariolist.Count()) {\n\t\tscenariolist.Remove_Item(scenariolist.Get_Item(0));\n\t}\n\tClear_Listbox(&playerlist);\n\n\t//------------------------------------------------------------------------\n\t// Remove the chat edit box\n\t//------------------------------------------------------------------------\n\tSession.Messages.Remove_Edit();\n\n\t//------------------------------------------------------------------------\n\t//\tRestore screen\n\t//------------------------------------------------------------------------\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n//#ifdef WIN32\n//\tLoad_Uncompress(CCFileClass(\"TITLE.CPS\"), SysMemPage, SysMemPage, CCPalette);\n//\tSysMemPage.Scale(SeenPage);\n//#else\n//\tLoad_Uncompress(CCFileClass(\"TITLE.CPS\"), HidPage, HidPage, CCPalette);\n//\tHidPage.Blit(SeenPage);\n//#endif\t//WIN32\n\tShow_Mouse();\n\n\tif (load_game) {\n\t\tif (!Load_Game (-1)) {\n\t\t\tWWMessageBox().Process (TXT_ERROR_LOADING_GAME);\n\t\t\trc = false;\n\t\t}\n\t\tFrame++;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Clear the Players vector if we're not starting a game.\n\t//------------------------------------------------------------------------\n\tif (!rc) {\n\t\tClear_Vector(&Session.Players);\n\t}\n\n//\twhile (optionlist.Count()>0) {\n//\t\titem = (char *)optionlist.Get_Item(0);\n//\t\tdelete [] item;\n//\t\toptionlist.Remove_Item(item);\n//\t}\n\n\treturn(rc);\n\n}\t/* end of Net_New_Dialog */\n\n\n/***************************************************************************\n * Get_NewGame_Responses -- processes packets for New Game dialog          *\n *                                                                         *\n * This routine can modify the contents of the given list box, as well\t\t*\n * as the contents of the Players Vector global.\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tplayerlist\t\tlist of players in this game\t\t\t\t\t\t\t\t\t*\n *\t\tcolor_used\t\tarray of color-used flags\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tEV_NONE = nothing happened\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tEV_NEW_PLAYER = a new player has joined; false otherwise\t\t\t\t\t*\n *\t\tEV_PLAYER_SIGNOFF = a player has left\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tEV_MESSAGE = a message was received\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic JoinEventType Get_NewGame_Responses(ColorListClass *playerlist,\n\tint *color_used)\n{\n\tint rc;\n\tchar * item;\t\t\t\t\t\t// general-purpose string\n\tNodeNameType *who;\t\t\t\t// node to add to Players Vector\n\tint i;\n\tint found;\n\tJoinEventType retval = EV_NONE;\n\tint resend;\n\tunsigned long version;\t\t\t// version # to use\n\n\t//------------------------------------------------------------------------\n\t//\tIf there is no incoming packet, just return\n\t//------------------------------------------------------------------------\n\trc = Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen,\n\t\t&Session.GAddress, &Session.GProductID);\n\tif (!rc || Session.GProductID != IPXGlobalConnClass::COMMAND_AND_CONQUER0) {\n\t\treturn(EV_NONE);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tTry to handle the packet in a standard way\n\t//------------------------------------------------------------------------\n\tif (Process_Global_Packet(&Session.GPacket,&Session.GAddress) != 0) {\n\t\treturn(EV_NONE);\n\t} else if (Session.GPacket.Command==NET_QUERY_JOIN) {\n\t//------------------------------------------------------------------------\n\t//\tNET_QUERY_JOIN:\n\t//------------------------------------------------------------------------\n\t\t//.....................................................................\n\t\t//\tSee if this name is unique:\n\t\t//\t- If the name matches, but the address is different, reject this player\n\t\t//\t- If the name & address match, this packet must be a re-send of a\n\t\t//\t  previous request; in this case, do nothing.  The other player must have\n\t\t//\t  received my CONFIRM_JOIN packet (since it was sent with an ACK\n\t\t//\t  required), so we can ignore this resend.\n\t\t//.....................................................................\n\t\tfound = 0;\n\t\tresend = 0;\n\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\tif (!strcmp(Session.Players[i]->Name,Session.GPacket.Name)) {\n\t\t\t\tif (Session.Players[i]->Address != Session.GAddress) {\n\t\t\t\t\tfound = 1;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tresend = 1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t//.....................................................................\n\t\t// If his name is the same as mine, treat it like a duplicate name\n\t\t//.....................................................................\n\t\tif (!strcmp (Session.Players[0]->Name, Session.GPacket.Name)) {\n\t\t\tfound = 1;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tReject if name is a duplicate\n\t\t//.....................................................................\n\t\tif (found) {\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\tSession.GPacket.Command = NET_REJECT_JOIN;\n\t\t\tSession.GPacket.Reject.Why = (int)REJECT_DUPLICATE_NAME;\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t1, &Session.GAddress);\n\t\t\treturn(EV_NONE);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tReject if there are too many players\n\t\t//.....................................................................\n\t\telse if ( (Session.Players.Count() >= Session.MaxPlayers) && !resend) {\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\tSession.GPacket.Command = NET_REJECT_JOIN;\n\t\t\tSession.GPacket.Reject.Why = (int)REJECT_GAME_FULL;\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t1, &Session.GAddress);\n\t\t\treturn(EV_NONE);\n\t\t}\n\n\t\t/*\n\t\t**\tDon't allow joining if the rules.ini file doesn't appear to match.\n\t\t*/\n\t\telse if (Session.GPacket.PlayerInfo.CheatCheck != RuleINI.Get_Unique_ID() && !resend) {\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\tSession.GPacket.Command = NET_REJECT_JOIN;\n\t\t\tSession.GPacket.Reject.Why = (int)REJECT_MISMATCH;\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 1, &Session.GAddress);\n\t\t\treturn(EV_NONE);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tIf this packet is NOT a resend, accept the player.  Grant him the\n\t\t//\trequested color if possible.\n\t\t//.....................................................................\n\t\telse if (!resend) {\n\t\t\t//..................................................................\n\t\t\t//\tCheck the player's version range against our own, to see if\n\t\t\t// there's an overlap region\n\t\t\t//..................................................................\n#ifdef FIXIT_VERSION_3\n\t\t\t//\tAdded to the transmitted _min_ version number is a bit indicating presence of Aftermath expansion.\n\t\t\tbool bGuestHasAftermath = Session.GPacket.PlayerInfo.MinVersion & 0x80000000;\n\t\t\tif( bGuestHasAftermath )\n//\t\t\t\tdebugprint( \"Host hears guest say 'I have Aftermath'\\n\" );\n\t\t\t\t;\n\t\t\telse\n\t\t\t{\n//\t\t\t\tdebugprint( \"Host hears guest say 'I don't have Aftermath'\\n\" );\n\t\t\t\tif( bAftermathMultiplayer )\n\t\t\t\t{\n//\t\t\t\t\tdebugprint( \"Host decides this is no longer an Aftermath game!\\n\" );\n\t\t\t\t\tbAftermathMultiplayer = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tSession.GPacket.PlayerInfo.MinVersion &= ~0x80000000;\t\t//\tStrip special bit.\n#endif\n\t\t\tversion = VerNum.Clip_Version (Session.GPacket.PlayerInfo.MinVersion,\n\t\t\t\tSession.GPacket.PlayerInfo.MaxVersion);\n\n#ifndef FIXIT_VERSION_3\n\t\t\tPlayingAgainstVersion = version;\n#endif\n\n// TCTCTC save off version number\n\n\t\t\t//..................................................................\n\t\t\t// Reject player if his version is too old\n\t\t\t//..................................................................\n\t\t\tif (version == 0) {\n\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\t\tSession.GPacket.Command = NET_REJECT_JOIN;\n\t\t\t\tSession.GPacket.Reject.Why = (int)REJECT_VERSION_TOO_OLD;\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t1, &Session.GAddress);\n\t\t\t\treturn(EV_NONE);\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// Reject player if his version is too new\n\t\t\t//..................................................................\n\t\t\telse if (version == 0xffffffff) {\n\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\t\tSession.GPacket.Command = NET_REJECT_JOIN;\n\t\t\t\tSession.GPacket.Reject.Why = (int)REJECT_VERSION_TOO_NEW;\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t1, &Session.GAddress);\n\t\t\t\treturn(EV_NONE);\n\t\t\t}\n\t\t\t//..................................................................\n\t\t\t// If the player is accepted, our mutually-accepted version may be\n\t\t\t// different; set the CommProtocol accordingly.\n\t\t\t//..................................................................\n\t\t\telse {\n\t\t\t\tSession.CommProtocol = VerNum.Version_Protocol(version);\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tAdd node to the Vector list\n\t\t\t//..................................................................\n\t\t\twho = new NodeNameType;\n\t\t\tstrcpy(who->Name, Session.GPacket.Name);\n\t\t\twho->Address = Session.GAddress;\n\t\t\twho->Player.House = Session.GPacket.PlayerInfo.House;\n\t\t\tSession.Players.Add (who);\n\n\t\t\t//..................................................................\n\t\t\t//\tSet player's color; if requested color isn't used, give it to him;\n\t\t\t//\totherwise, give him the 1st available color.  Mark the color we\n\t\t\t//\tgive him as used.\n\t\t\t//..................................................................\n\t\t\tif (color_used[Session.GPacket.PlayerInfo.Color] == 0) {\n\t\t\t\twho->Player.Color = Session.GPacket.PlayerInfo.Color;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfor (i = 0; i < MAX_MPLAYER_COLORS; i++) {\n\t\t\t\t\tif (color_used[i]==0) {\n\t\t\t\t\t\twho->Player.Color = (PlayerColorType)i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcolor_used[who->Player.Color] = 1;\n\n\t\t\t//..................................................................\n\t\t\t//\tAdd player name to the list box\n\t\t\t//..................................................................\n\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\n#ifdef OLDWAY\n\t\t\tif (Session.GPacket.PlayerInfo.House==HOUSE_GOOD) {\n\t\t\t\tsprintf(item,\"%s\\t%s\",Session.GPacket.Name, Text_String(TXT_ALLIES));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tsprintf(item,\"%s\\t%s\",Session.GPacket.Name, Text_String(TXT_SOVIET));\n\t\t\t}\n#else\t//OLDWAY\n\t\t\tsprintf (item, \"%s\\t%s\", Session.GPacket.Name,\n\t\t\t\t\t\tText_String(HouseTypeClass::As_Reference(Session.GPacket.PlayerInfo.House).Full_Name()));\n#endif\t//OLDWAY\n\t\t\tplayerlist->Add_Item(item,\n\t\t\t\t(who->Player.Color == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[who->Player.Color]);\n\n\t\t\t//..................................................................\n\t\t\t//\tSend a confirmation packet\n\t\t\t//..................................................................\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\tSession.GPacket.Command = NET_CONFIRM_JOIN;\n\t\t\tstrcpy(Session.GPacket.Name,Session.Handle);\n\t\t\tSession.GPacket.PlayerInfo.House = who->Player.House;\n\t\t\tSession.GPacket.PlayerInfo.Color = who->Player.Color;\n\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t1, &Session.GAddress);\n\n\t\t\t//..................................................................\n\t\t\t// Play a special sound.\n\t\t\t//..................................................................\n\t\t\tSound_Effect(VOC_PLAYER_JOINED);\n\n\t\t\tretval = EV_NEW_PLAYER;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_SIGN_OFF: Another system is signing off: search for that system in\n\t//\tthe player list, & remove it if found\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_SIGN_OFF) {\n\t\tfor (i = 0; i < Session.Players.Count(); i++) {\n\n\t\t\t//..................................................................\n\t\t\t//\tName found; remove it\n\t\t\t//..................................................................\n\t\t\tif (!strcmp (Session.Players[i]->Name, Session.GPacket.Name) &&\n\t\t\t\tSession.Players[i]->Address==Session.GAddress) {\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tRemove from the list box\n\t\t\t\t//...............................................................\n\t\t\t\titem = (char *)(playerlist->Get_Item(i));\n\t\t\t\tplayerlist->Remove_Item(item);\n\t\t\t\tplayerlist->Flag_To_Redraw();\n\t\t\t\tdelete [] item;\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tMark his color as available\n\t\t\t\t//...............................................................\n\t\t\t\tcolor_used[Session.Players[i]->Player.Color] = 0;\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tDelete from the Vector list\n\t\t\t\t//...............................................................\n\t\t\t\tdelete Session.Players[i];\n\t\t\t\tSession.Players.Delete(Session.Players[i]);\n\n\t\t\t\t//...............................................................\n\t\t\t\t// Play a special sound.\n\t\t\t\t//...............................................................\n\t\t\t\tSound_Effect(VOC_PLAYER_LEFT);\n\n\t\t\t\tretval = EV_PLAYER_SIGNOFF;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_MESSAGE: Someone is sending us a message\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_MESSAGE) {\n\t\tSession.Messages.Add_Message (Session.GPacket.Name,\n\t\t\t(Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,\n\t\t\tSession.GPacket.Message.Buf,\n\t\t\t(Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,\n\t\t\tTPF_TEXT, -1);\n\n\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\n\t\tretval = EV_MESSAGE;\n\t}\n\n\treturn(retval);\n\n}\t/* end of Get_NewGame_Responses */\n\n\n/***************************************************************************\n * Compute_Name_CRC -- computes CRC from char string                       *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tname\t\tstring to create CRC for\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tCRC\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nunsigned long Compute_Name_CRC(char *name)\n{\n\tchar buf[80];\n\tunsigned long crc = 0L;\n\tint i;\n\n\tstrcpy (buf, name);\n\tstrupr (buf);\n\n\tfor (i = 0; i < strlen(buf); i++) {\n\t\tAdd_CRC (&crc, (unsigned long)buf[i]);\n\t}\n\n\treturn (crc);\n\n}\t/* end of Compute_Name_CRC */\n\n\n/***************************************************************************\n * Net_Reconnect_Dialog -- Draws/updates the network reconnect dialog      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\treconn\t\t\t1 = reconnect, 0 = waiting for first-time connection\t*\n *\t\tfresh\t\t\t\t1 = draw from scratch, 0 = only update time counter\t*\n *\t\toldest_index\tIPX connection index of oldest connection \t\t\t\t*\n *\t\t\t\t\t\t\t(only used for reconnection)\t\t\t\t\t\t\t\t\t*\n *\t\ttimeval\t\t\tvalue to print in the countdown field\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/08/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid Net_Reconnect_Dialog(int reconn, int fresh, int oldest_index,\n\tunsigned long timeval)\n{\n\tstatic int x,y,w,h;\n\tint id;\n\tchar buf1[40] = {0};\n\tchar buf2[40] = {0};\n\tchar const *buf3 = \"\";\n\n\tint d_txt6_h = 6 * RESFACTOR+1;\n\tint d_margin = 5 * RESFACTOR;\n\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n#ifdef WIN32\n\t/*\n\t** If we have just received input focus again after running in the background then\n\t** we need to redraw.\n\t*/\n\tif (AllSurfaces.SurfacesRestored) {\n\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\tfresh = true;\n\t}\n#endif\n\n\t//------------------------------------------------------------------------\n\t//\tDraw the dialog from scratch\n\t//------------------------------------------------------------------------\n\tif (fresh) {\n\t\tFancy_Text_Print(\"\", 0, 0, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\n\t\tswitch ( Session.Type) {\n\t\t\tcase GAME_IPX:\n\t\t\tcase GAME_INTERNET:\n\t\t\tcase GAME_MODEM:\n\t\t\tcase GAME_NULL_MODEM:\n\n\t\t\t\tif (reconn) {\n\t\t\t\t\tid = Ipx.Connection_ID(oldest_index);\n\t\t\t\t\tsprintf(buf1,Text_String(TXT_RECONNECTING_TO),\n\t\t\t\t\t\tIpx.Connection_Name(id));\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(buf1,Text_String(TXT_WAITING_FOR_CONNECTIONS));\n\t\t\t\t}\n\t\t\t\tbreak;\n\n#if(TEN)\n\t\t\tcase GAME_TEN:\n\t\t\t\tif (reconn) {\n\t\t\t\t\tid = Ten->Connection_ID(oldest_index);\n\t\t\t\t\tsprintf(buf1,Text_String(TXT_RECONNECTING_TO),\n\t\t\t\t\t\tTen->Connection_Name(id));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsprintf(buf1,Text_String(TXT_WAITING_FOR_CONNECTIONS));\n\t\t\t\t}\n#endif\t// TEN\n\n#if(MPATH)\n\t\t\tcase GAME_MPATH:\n\t\t\t\tif (reconn) {\n\t\t\t\t\tid = MPath->Connection_ID(oldest_index);\n\t\t\t\t\tsprintf(buf1,Text_String(TXT_RECONNECTING_TO),\n\t\t\t\t\t\tMPath->Connection_Name(id));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsprintf(buf1,Text_String(TXT_WAITING_FOR_CONNECTIONS));\n\t\t\t\t}\n#endif\t// MPATH\n\t\t}\n\n\t\tsprintf(buf2,Text_String(TXT_TIME_ALLOWED), timeval + 1);\n\t\tbuf3 = Text_String(TXT_PRESS_ESC);\n\n\t\tw = max(String_Pixel_Width(buf1),String_Pixel_Width(buf2));\n\n#ifdef FIXIT_VERSION_3\n\t\tchar szNewCancelMessage[ 300 ];\n\t\tsprintf( szNewCancelMessage, \"%s%s\", buf3, TXT_WOL_CANCELMEANSFORFEIT );\n\n\t\tif( Session.Type == GAME_INTERNET && pWolapi && pWolapi->GameInfoCurrent.bTournament )\n\t\t{\n\t\t\tw = max(String_Pixel_Width(szNewCancelMessage), w);\t// * RESFACTOR;\t\twhy was it ever multiplied by this!!!?\n\t\t\tw += (d_margin * 12);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tw = max(String_Pixel_Width(buf3), w) * RESFACTOR;\n\t\t\tw += (d_margin * 5);\n\t\t}\n#else\n\t\tw = max(String_Pixel_Width(buf3), w) * RESFACTOR;\n\t\tw += (d_margin * 5);\n#endif\n\n\t\th = (d_txt6_h * 3) + (d_margin * 6);\n\t\tx = 160*RESFACTOR - (w / 2);\n\t\ty = 100*RESFACTOR - (h / 2);\n\n\t\tHide_Mouse();\n\t\tSet_Logic_Page(SeenBuff);\n\t\tDialog_Box(x, y, w, h);\n\n\t\tFancy_Text_Print (buf1, 160*RESFACTOR, y + (d_margin * 2), scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\n\t\tFancy_Text_Print (buf2, 160*RESFACTOR, y + (d_margin * 2) + d_txt6_h + d_margin, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\n#ifdef FIXIT_VERSION_3\n\t\tif( Session.Type == GAME_INTERNET && pWolapi && pWolapi->GameInfoCurrent.bTournament )\n\t\t\tFancy_Text_Print (szNewCancelMessage, 160*RESFACTOR, y + (d_margin * 2) + (d_txt6_h + d_margin) * 2, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\telse\n\t\t\tFancy_Text_Print (buf3, 160*RESFACTOR, y + (d_margin * 2) + (d_txt6_h + d_margin) * 2, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n#else\n\t\tFancy_Text_Print (buf3, 160*RESFACTOR, y + (d_margin * 2) + (d_txt6_h + d_margin) * 2, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n#endif\n\n\t\tShow_Mouse();\n\t}\n\t//------------------------------------------------------------------------\n\t//\tJust update the timeout value on the dialog\n\t//------------------------------------------------------------------------\n\telse {\n\t\tHide_Mouse();\n\t\tSet_Logic_Page(SeenBuff);\n\n\t\tsprintf(buf2,Text_String(TXT_TIME_ALLOWED), timeval + 1);\n\n\t\tint fillx = 160*RESFACTOR - (String_Pixel_Width (buf2) / 2) -6;\n\t\tLogicPage->Fill_Rect (fillx, y + (d_margin * 2) + d_txt6_h + d_margin,\n\t\t\t\t\t\t\t\t\tfillx + String_Pixel_Width (buf2) + 12,\n\t\t\t\t\t\t\t\t\ty + (d_margin * 2) + d_txt6_h + d_margin + d_txt6_h +1*RESFACTOR,\n\t\t\t\t\t\t\t\t\tBLACK);\n\n\t\tFancy_Text_Print (buf2, 160*RESFACTOR, y + (d_margin * 2) + d_txt6_h + d_margin, scheme, BLACK, TPF_CENTER | TPF_TEXT);\n\n\t\tShow_Mouse();\n\t}\n}\t/* end of Net_Reconnect_Dialog */\n\n#define\tMAX_CHAT_NAME\t\t12\n#define\tMAX_CHAT_PHRASE\t45\n\nstruct WWPerson {\n\tchar Name[MAX_CHAT_NAME];\n\tchar Phrase[MAX_CHAT_PHRASE];\n\tPlayerColorType Color;\n\tunsigned long LastTime;\n};\n\nstruct WWPerson WWPersons[] = {\n\t{ {66,105,108,108,32,82,0,0,0,0,0,0,},\n\t  {72,101,121,44,32,105,115,110,39,116,32,116,104,105,115,32,99,111,111,108,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,105,108,108,32,82,0,0,0,0,0,0,},\n\t  {72,101,121,44,32,119,97,110,116,32,115,111,109,101,32,115,101,97,102,111,111,100,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,97,114,114,121,32,71,0,0,0,0,0,},\n\t  {71,114,101,97,116,46,32,74,117,115,116,32,103,114,101,97,116,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,97,114,114,121,32,71,0,0,0,0,0,},\n\t  {87,111,110,100,101,114,102,117,108,46,32,80,101,114,102,101,99,116,44,32,105,110,32,102,97,99,116,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,105,108,108,32,80,0,0,0,0,0,0,},\n\t  {89,111,117,32,99,97,108,108,32,116,104,105,115,32,65,73,63,32,32,83,104,101,101,115,104,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,105,108,108,32,80,0,0,0,0,0,0,},\n\t  {66,105,108,108,115,32,114,117,108,101,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,114,101,116,116,32,83,0,0,0,0,0,},\n\t  {84,97,107,101,32,116,104,105,115,32,111,117,116,44,32,110,111,119,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,114,101,116,116,32,83,0,0,0,0,0,},\n\t  {87,104,121,32,99,97,110,39,116,32,121,111,117,32,102,105,116,32,97,110,121,32,109,111,114,101,32,108,101,116,116,101,114,115,32,111,110,32,116,104,101,32,108,0,0,},PCOLOR_GREEN,0},\n\t{ {66,114,101,116,116,32,83,0,0,0,0,0,},\n\t  {69,100,44,32,73,32,119,97,110,116,32,116,111,32,116,97,108,107,32,116,111,32,121,111,117,32,97,98,111,117,116,32,116,104,105,115,46,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,114,101,116,116,32,83,0,0,0,0,0,},\n\t  {69,100,44,32,99,111,109,101,32,116,111,32,109,121,32,111,102,102,105,99,101,44,32,110,111,119,33,32,32,91,99,114,97,99,107,33,93,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {80,101,110,105,110,97,32,70,0,0,0,0,},\n\t  {72,97,115,32,97,110,121,111,110,101,32,115,101,101,110,32,109,121,32,115,116,97,112,108,101,114,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {80,101,110,105,110,97,32,70,0,0,0,0,},\n\t  {72,97,115,32,97,110,121,111,110,101,32,115,101,101,110,32,109,121,32,116,104,101,115,97,117,114,117,115,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {80,101,110,105,110,97,32,70,0,0,0,0,},\n\t  {72,97,115,32,97,110,121,111,110,101,32,115,101,101,110,32,109,121,32,112,101,110,99,105,108,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,105,108,111,32,66,0,0,0,0,0,0,},\n\t  {72,101,121,32,83,116,101,118,101,44,32,99,97,110,32,119,101,32,109,101,101,116,32,105,110,32,121,111,117,114,32,111,102,102,105,99,101,63,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,105,108,111,32,66,0,0,0,0,0,0,},\n\t  {83,116,101,118,101,44,32,105,116,39,108,108,32,111,110,108,121,32,116,97,107,101,32,97,32,109,105,110,117,116,101,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {82,111,98,32,83,0,0,0,0,0,0,0,},\n\t  {77,105,108,111,44,32,100,105,97,108,32,50,52,57,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {69,108,115,98,101,116,104,32,87,0,0,0,},\n\t  {84,104,97,116,39,115,32,39,69,108,115,98,101,116,104,39,44,32,119,105,116,104,32,97,110,32,69,45,76,45,83,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {69,108,115,98,101,116,104,32,87,0,0,0,},\n\t  {84,104,97,116,39,115,32,39,69,108,115,98,101,116,104,39,44,32,110,111,116,32,39,69,108,115,98,97,114,102,39,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {69,108,115,98,101,116,104,32,87,0,0,0,},\n\t  {84,104,97,116,39,115,32,39,69,108,115,98,101,116,104,39,44,32,110,111,116,32,39,69,108,102,98,117,116,116,39,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {75,97,114,101,110,32,71,0,0,0,0,0,},\n\t  {84,104,105,115,32,105,115,32,115,111,111,111,32,119,101,105,114,100,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {75,97,114,101,110,32,71,0,0,0,0,0,},\n\t  {68,117,104,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {80,104,105,108,32,71,0,0,0,0,0,0,},\n\t  {72,101,121,44,32,105,116,32,119,111,114,107,101,100,32,111,110,32,109,121,32,99,111,109,112,117,116,101,114,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {80,104,105,108,32,71,0,0,0,0,0,0,},\n\t  {84,104,105,115,32,116,104,105,110,103,32,105,115,32,99,108,101,97,114,108,121,32,97,32,119,97,115,116,101,32,111,102,32,109,101,109,111,114,121,46,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,111,101,32,66,0,0,0,0,0,0,0,},\n\t  {72,109,109,44,32,73,32,115,101,101,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,111,101,32,66,0,0,0,0,0,0,0,},\n\t  {65,104,104,44,32,121,101,115,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,97,114,105,97,32,68,77,77,76,0,0,},\n\t  {78,111,116,32,97,110,111,116,104,101,114,32,105,110,115,116,97,108,108,101,114,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,97,114,105,97,32,68,77,77,76,0,0,},\n\t  {72,65,32,72,65,32,72,65,32,72,65,32,72,65,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,105,107,101,32,76,0,0,0,0,0,0,},\n\t  {84,104,105,115,32,105,115,32,114,101,97,108,108,121,32,99,111,111,108,33,32,32,71,111,115,104,32,103,117,121,115,33,32,32,87,111,119,33,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,105,107,101,32,76,0,0,0,0,0,0,},\n\t  {87,111,119,33,32,32,89,111,117,32,103,117,121,115,32,97,114,101,32,116,104,101,32,103,114,101,97,116,101,115,116,33,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,105,107,101,32,71,0,0,0,0,0,0,},\n\t  {71,114,97,121,102,105,115,104,32,102,111,114,32,108,117,110,99,104,32,97,103,97,105,110,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,105,107,101,32,71,0,0,0,0,0,0,},\n\t  {84,104,105,115,32,105,115,32,108,97,109,101,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {71,108,101,110,110,32,83,0,0,0,0,0,},\n\t  {84,104,105,115,32,116,104,105,110,103,39,115,32,98,117,103,103,101,100,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {71,108,101,110,110,32,83,0,0,0,0,0,},\n\t  {83,104,105,112,32,105,116,33,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {83,116,101,118,101,32,87,0,0,0,0,0,},\n\t  {79,75,32,101,118,101,114,121,111,110,101,44,32,111,117,116,32,111,102,32,109,121,32,111,102,102,105,99,101,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {69,100,32,68,0,0,0,0,0,0,0,0,},\n\t  {65,32,103,111,111,100,32,99,104,97,116,32,112,114,111,103,114,97,109,32,105,115,32,108,105,107,101,32,97,32,110,105,110,106,97,46,46,46,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {69,100,32,68,0,0,0,0,0,0,0,0,},\n\t  {65,32,103,111,111,100,32,110,105,110,106,97,32,105,115,32,108,105,107,101,32,97,32,110,105,110,106,97,46,46,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {69,114,105,107,32,89,0,0,0,0,0,0,},\n\t  {73,32,119,101,97,114,32,100,101,115,105,103,110,101,114,32,106,101,97,110,115,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {69,114,105,107,32,89,0,0,0,0,0,0,},\n\t  {72,101,121,32,66,105,108,108,44,32,116,104,105,115,32,116,104,105,110,103,32,107,101,101,112,115,32,99,114,97,25,26,24,104,105,110,103,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,101,102,102,32,70,0,0,0,0,0,0,},\n\t  {84,104,105,115,32,105,115,32,97,98,115,111,108,117,116,101,108,121,32,116,104,101,32,98,101,115,116,32,101,118,101,114,33,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,101,102,102,32,70,0,0,0,0,0,0,},\n\t  {84,104,105,115,32,105,115,32,97,98,115,111,108,117,116,101,108,121,32,116,104,101,32,119,111,114,115,116,32,101,118,101,114,33,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {82,105,99,107,32,78,0,0,0,0,0,0,},\n\t  {83,111,117,110,100,115,32,108,105,107,101,32,97,32,100,114,105,118,101,114,32,112,114,111,98,108,101,109,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {83,99,111,116,116,32,66,0,0,0,0,0,},\n\t  {73,32,110,101,101,100,32,116,104,105,115,32,102,111,114,32,76,79,76,50,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {83,116,101,118,101,32,84,0,0,0,0,0,},\n\t  {84,104,105,115,32,115,101,101,109,115,32,114,97,116,104,101,114,32,115,105,108,108,121,44,32,97,99,116,117,97,108,108,121,46,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {80,97,117,108,32,77,0,0,0,0,0,0,},\n\t  {78,111,32,46,46,46,46,32,32,87,32,65,32,89,33,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {82,105,99,107,32,80,0,0,0,0,0,0,},\n\t  {65,72,32,72,65,32,72,65,32,72,65,33,33,32,32,72,65,72,65,33,33,32,32,65,72,72,32,72,65,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,111,101,32,75,0,0,0,0,0,0,0,},\n\t  {83,116,97,108,105,110,32,107,105,108,108,101,100,32,109,121,32,102,97,116,104,101,114,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,111,101,32,75,0,0,0,0,0,0,0,},\n\t  {73,32,104,111,112,101,32,121,111,117,39,114,101,32,112,114,111,117,100,32,111,102,32,121,111,117,114,115,101,108,102,44,32,66,105,108,108,46,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,105,103,32,87,105,108,108,121,0,0,0,},\n\t  {65,110,121,98,111,100,121,32,102,101,114,32,97,32,115,112,105,116,116,105,110,39,32,99,111,110,116,101,115,116,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {69,114,105,99,32,87,0,0,0,0,0,0,},\n\t  {75,97,114,97,116,101,32,105,115,32,103,111,111,100,32,98,117,116,32,121,111,117,32,117,115,101,32,105,116,32,102,111,114,32,101,118,105,108,33,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {84,101,100,32,77,0,0,0,0,0,0,0,},\n\t  {72,97,46,32,32,70,117,110,110,121,46,32,32,84,104,105,115,32,105,115,32,102,117,110,110,121,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {68,97,109,111,110,32,82,0,0,0,0,0,},\n\t  {73,32,98,108,97,109,101,32,116,104,101,32,70,114,101,110,99,104,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {68,119,105,103,104,116,32,79,0,0,0,0,},\n\t  {79,104,44,32,109,97,110,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {75,105,97,32,72,0,0,0,0,0,0,0,},\n\t  {73,111,110,32,99,97,110,110,111,110,32,114,101,97,100,121,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {75,105,97,32,72,0,0,0,0,0,0,0,},\n\t  {83,101,108,101,99,116,32,116,97,114,103,101,116,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,114,117,99,101,32,74,0,0,0,0,0,},\n\t  {73,32,97,109,32,116,104,101,32,71,101,110,105,101,32,111,102,32,116,104,101,32,108,97,109,112,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {76,97,117,114,97,32,87,0,0,0,0,0,},\n\t  {71,111,32,97,119,97,121,44,32,66,105,108,108,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {68,97,118,105,100,32,68,0,0,0,0,0,},\n\t  {72,109,109,109,46,46,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,105,107,101,32,76,105,0,0,0,0,0,},\n\t  {67,97,108,108,32,109,101,32,78,97,116,101,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {68,101,110,122,105,108,32,76,0,0,0,0,},\n\t  {84,104,105,115,32,119,111,117,108,100,32,98,101,32,98,101,116,116,101,114,32,111,110,32,116,104,101,32,77,97,99,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {71,114,101,103,32,72,0,0,0,0,0,0,},\n\t  {66,117,116,32,100,111,101,115,32,105,116,32,102,105,116,32,105,110,116,111,32,50,32,77,66,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,111,110,97,116,104,97,110,32,76,0,0,},\n\t  {73,32,116,104,105,110,107,32,73,32,110,101,101,100,32,97,32,104,97,105,114,99,117,116,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {65,100,97,109,32,73,0,0,0,0,0,0,},\n\t  {87,104,97,116,101,118,101,114,46,32,32,66,101,101,102,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {75,117,114,116,32,79,0,0,0,0,0,0,},\n\t  {70,105,120,32,105,116,32,121,111,117,114,115,101,108,102,46,32,32,73,39,109,32,98,117,115,121,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,111,115,101,112,104,32,72,0,0,0,0,},\n\t  {60,73,99,121,32,103,108,97,114,101,62,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,97,116,116,32,72,0,0,0,0,0,0,},\n\t  {73,39,109,32,110,101,118,101,114,32,103,111,111,100,32,119,105,116,104,32,99,108,101,118,101,114,32,111,110,32,116,104,101,32,115,112,111,116,46,46,46,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {67,104,114,105,115,32,82,0,0,0,0,0,},\n\t  {73,32,108,111,118,101,32,109,121,32,106,111,98,46,32,32,89,101,97,104,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {80,97,116,32,67,0,0,0,0,0,0,0,},\n\t  {73,39,109,32,97,32,112,114,111,102,101,115,115,105,111,110,97,108,32,121,111,100,101,108,108,101,114,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {73,97,110,32,76,0,0,0,0,0,0,0,},\n\t  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,97,99,107,32,77,0,0,0,0,0,0,},\n\t  {73,32,108,105,118,101,32,97,98,111,117,116,32,97,32,98,108,111,99,107,32,102,114,111,109,32,116,104,101,32,112,114,111,112,111,115,101,100,32,115,105,116,101,46,0,},PCOLOR_GREEN,0},\n\t{ {74,101,102,102,32,66,0,0,0,0,0,0,},\n\t  {84,104,101,121,32,97,108,108,32,108,111,111,107,32,108,105,107,101,32,97,110,116,115,32,102,114,111,109,32,117,112,32,104,101,114,101,46,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n};\n\nCDTimerClass<SystemTimerClass> wwperson_timer;\n\nvoid Start_WWChat(ColorListClass *playerlist)\n{\n\tchar *item;\n\tint i;\n\tHousesType house;\n\n\t//------------------------------------------------------------------------\n\t// Ensure a different sequence each time\n\t//------------------------------------------------------------------------\n\tScen.RandomNumber = rand();\n\n\t//------------------------------------------------------------------------\n\t// Add myself to the player list\n\t//------------------------------------------------------------------------\n\titem = new char [MPLAYER_NAME_MAX + 64];\n#ifdef OLDWAY\n\tif (Session.House==HOUSE_GOOD) {\n\t\tsprintf(item,\"%s\\t%s\",Session.Handle, Text_String(TXT_ALLIES));\n\t}\n\telse {\n\t\tsprintf(item,\"%s\\t%s\",Session.Handle, Text_String(TXT_SOVIET));\n\t}\n#else\t//OLDWAY\n\tsprintf (item, \"%s\\t%s\", Session.Handle, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\tplayerlist->Add_Item(item,\n\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]);\n\n\t//------------------------------------------------------------------------\n\t// Add everyone else to the list\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < sizeof(WWPersons) / sizeof(struct WWPerson); i++) {\n\t\t//.....................................................................\n\t\t// Add the 1st entry to the list no matter what; for entries after the\n\t\t// 1st, only add the name if it's different from the previous name.\n\t\t//.....................................................................\n\t\tif (i==0 || strcmp(WWPersons[i].Name, WWPersons[i-1].Name)) {\n\t\t\tWWPersons[i].Color = (PlayerColorType)(Random_Pick(0,(int)(PCOLOR_LAST - 1)));\n\t\t\tif (Percent_Chance(50)) {\n\t\t\t\thouse = HOUSE_GREECE;\n\t\t\t} else {\n\t\t\t\thouse = HOUSE_USSR;\n\t\t\t}\n//\t\t\thouse = (HousesType)Random_Pick((int)HOUSE_GOOD,(int)HOUSE_BAD);\n\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\n\t\t\tif (house != HOUSE_USSR && house != HOUSE_UKRAINE) {\n\t\t\t\tsprintf(item,\"%s\\t%s\", WWPersons[i].Name, Text_String(TXT_ALLIES));\n\t\t\t} else {\n\t\t\t\tsprintf(item,\"%s\\t%s\", WWPersons[i].Name, Text_String(TXT_SOVIET));\n\t\t\t}\n\t\t\tplayerlist->Add_Item(item,\n\t\t\t\t(WWPersons[i].Color == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[WWPersons[i].Color]);\n\t\t}\n\t\t//.....................................................................\n\t\t// If this entry's name is the same as the previous, copy the color\n\t\t// value from the previous entry.\n\t\t//.....................................................................\n\t\telse if (i > 0) {\n\t\t\tWWPersons[i].Color = WWPersons[i-1].Color;\n\t\t}\n\n\t}\n\n\t//wwperson_timer = 240;\n\twwperson_timer = Random_Pick(90,360);\n\n}\t// end of Start_WWChat\n\n\nint Update_WWChat(void)\n{\n\tint i;\n\tint j;\n\n\t//------------------------------------------------------------------------\n\t// Do nothing if it's too soon.\n\t//------------------------------------------------------------------------\n\tif (wwperson_timer > 0) {\n\t\treturn(0);\n\t}\n\n\t//wwperson_timer = 240;\n\twwperson_timer = Random_Pick(90,360);\n\n\t//------------------------------------------------------------------------\n\t// Even after the timer's gone off, there's only a 1/8 chance we'll\n\t// print a message.\n\t//------------------------------------------------------------------------\n\tif (Percent_Chance(12)) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Randomly select a message to \"send\"; ensure we pick a message that\n\t// hasn't been recently displayed.\n\t//------------------------------------------------------------------------\n\tj = sizeof(WWPersons) / sizeof(struct WWPerson);\n\ti = Random_Pick (0, j - 1);\n\tif ((TickCount - WWPersons[i].LastTime) < 1800 &&\n\t\tWWPersons[i].LastTime != 0) {\n\t\treturn(0);\n\t}\n\n\tSession.Messages.Add_Message (WWPersons[i].Name,\n\t\t0,\n\t\tWWPersons[i].Phrase, WWPersons[i].Color,\n\t\tTPF_TEXT, -1);\n\tWWPersons[i].LastTime = TickCount;\n\n\treturn (1);\n\n}\t// end of Update_WWChat\n\n\n#if(0)\n/*****************************************************************************/\nvoid Start_Logging(void)\n{\n\tFILE *fp;\n\tstatic char *ColorNames[6] = {\n\t\t\"Yellow\",\n\t\t\"Red\",\n\t\t\"BlueGreen\",\n\t\t\"Orange\",\n\t\t\"Green\",\n\t\t\"Blue\",\n\t};\n\tint i;\n\tint id;\n\tHousesType house;\n\tchar *housenames[] = {\n\t\t\"ALLIES\",\n\t\t\"SOVIET\",\n\t\t\"Neutral\",\n\t\t\"Special\",\n\t\t\"Multi1\",\n\t\t\"Multi2\",\n\t\t\"Multi3\",\n\t\t\"Multi4\",\n\t\t};\n\ttime_t t;\n\n\tfp = fopen(\"NETPLAY.LOG\",\"at\");\n\tif (!fp)\n\t\treturn;\n\n\t/*\n\t**\tPrint game header\n\t*/\n\tt = time(NULL);\n\tfprintf (fp,\"==============================================================\\n\");\n\tfprintf (fp,\"Date:            %s\",ctime(&t));\n\tfprintf (fp,\"Scenario:        %s\\n\",\n\t\tSession.Scenarios[Session.Options.ScenarioIndex].Description());\n\tfprintf (fp,\"Total # players: %d\\n\",Session.NumPlayers);\n\tfprintf (fp,\"==============================================================\\n\");\n\n\t/*\n\t**\tPrint connection info\n\t*/\n\n\t/*\n\t**\tPrint player data\n\t*/\n\tfprintf(fp,\"Local Player:\\n\");\n\tfprintf (fp,\"             Name:%s\\n\", Session.Handle);\n\tfprintf (fp,\"            Color:%s\\n\", ColorNames[Session.ColorIdx]);\n\tfprintf (fp,\"            House:%s\\n\", housenames[Session.House]);\n\tfprintf (fp,\"\\n\");\n\n\tfor (i = 0; i < Ipx.Num_Connections(); i++) {\n\t\tid = Ipx.Connection_ID(i);\n\t\thouse = (HouseClass)id;\n\t\tfprintf(fp,\"Connection %d:\\n\",i);\n\t\tfprintf (fp,\"             Name:%s\\n\", Ipx.Connection_Name(id));\n\t\tfprintf (fp,\"            Color:%s\\n\",\n\t\t\tColorNames[HouseClass::As_Pointer(house)->RemapColor);\n\t\tfprintf (fp,\"            House:%s\\n\", housenames[house]);\n\t\tfprintf (fp,\"\\n\");\n\t}\n\n\t/*\n\t**\tPrint game options\n\t*/\n\tfprintf(fp,\"Game Options:\\n\");\n\tfprintf(fp,\"             Bases:%d\\n\",Session.Options.Bases);\n\tfprintf(fp,\"           Credits:%d\\n\",Session.Options.Credits);\n\tfprintf(fp,\"          Tiberium:%d\\n\",Session.Options.Tiberium);\n\tfprintf(fp,\"            Crates:%d\\n\",Session.Options.Goodies);\n\tfprintf(fp,\"        AI Players:%d\\n\",Session.Options.AIPlayers);\n\tfprintf(fp,\"       Build Level:%d\\n\",BuildLevel);\n\tfprintf(fp,\"        Unit Count:%d\\n\",Session.Options.UnitCount);\n\tfprintf(fp,\"              Seed:%d\\n\",Seed);\n\tfprintf (fp,\"\\n\");\n\n\tfclose(fp);\n\n}\t/* end of Start_Logging */\n\n\nvoid Log_Message(char *msg)\n{\n\tFILE *fp;\n\n\tfp = fopen(\"NETPLAY.LOG\",\"at\");\n\tif (!fp)\n\t\treturn;\n\n\tfprintf(fp,\"%s (Frame:%d)\\n\",msg,Frame);\n\tfclose(fp);\n\tflushall();\n\n}\t/* end of Log_Message */\n#endif\n\n\n\n\n\n#ifndef WOLAPI_INTEGRATION\t\t\t//\tRest of file ifdeffed out.\n\n\n\n\n\nextern bool Spawn_WChat(bool can_launch);\n\n/***********************************************************************************************\n * Net_Fake_New_Dialog -- lets user start a new game                                           *\n *                                                                                             *\n * This dialog shows a list of who's requesting to join this game, and lets                    *\n * the game initiator selectively approve each user.                                           *\n *                                                                                             *\n * The 'Players' vector matches one-for-one the contents of the list box.  The local system\t  *\n * is always listed first; the IPX Address of the local system will NOT be valid in the\t\t  *\n * Players vector.  The Games & Players vectors should be left filled in even after this\t\t  *\n * routine is exited; their contents are used to form connections to the other players,\t\t  *\n * after the scenario has been loaded.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *    Ŀ                                           *\n *                  New Network Game                                                         *\n *                                                                                           *\n *         Players               Scenario                                                    *\n *     Ŀ   Ŀ                                            *\n *      Boffo       .    Green Acres      .                                            *\n *      Bozo        Ĵ    Brown Sewers     Ĵ                                            *\n *      Bonzo                 ...                                                      *\n *                  Ĵ                     Ĵ                                            *\n *                  .                     .                                            *\n *                                                    *\n *         [Reject]             Count:--- ##                                                 *\n *                              Level:--- ##                                                 *\n *                                                                                           *\n *                   Credits: _____                                                          *\n *           [  Bases   ]   [   Crates   ]                                                   *\n *           [ Tiberium ]   [ AI Players ]                                                   *\n *      Ŀ                                              *\n *                                                                                         *\n *                                                                                         *\n *                                                    *\n *      Ŀ                                              *\n *                                                    *\n *                  [OK]    [Cancel]                                                         *\n *                                               *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = success, false = cancel                                                         *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      Session.GameName must contain this player's name.                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nstatic int Net_Fake_New_Dialog(void)\n{\n#ifdef WIN32\n\t//------------------------------------------------------------------------\n\t//\tDialog & button dimensions\n\t//------------------------------------------------------------------------\n\tint d_dialog_w = 120 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 80 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320 *RESFACTOR- d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\tint d_dialog_y = ((200 *RESFACTOR- d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_txt6_h = 6*RESFACTOR+1;\t\t\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_margin1 = 5*RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\tint d_margin2 = 2*RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint d_playerlist_w = 118*RESFACTOR;\n\tint d_playerlist_h = ((6 * 6) + 3)*RESFACTOR;\t\t\t// 6 rows high\n\t//int d_playerlist_x = d_dialog_x + d_margin1 + d_margin1;\n\tint d_playerlist_x = 500*RESFACTOR;\n\tint d_playerlist_y = d_dialog_y + d_margin1 + d_txt6_h;\n\n#if (GERMAN | FRENCH)\n\tint d_cancel_w = 50*RESFACTOR;\n#else\n\tint d_cancel_w = 40*RESFACTOR;\n#endif\n\tint d_cancel_h = 9*RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - d_cancel_w / 2;\n\tint d_cancel_y = d_dialog_y + d_dialog_h - 20*RESFACTOR;\n\n\n\t//------------------------------------------------------------------------\n\t//\tButton Enumerations\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tBUTTON_PLAYERLIST = 100,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t//------------------------------------------------------------------------\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PARMS,\n\t\tREDRAW_MESSAGE,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t//------------------------------------------------------------------------\n\t//\tDialog variables\n\t//------------------------------------------------------------------------\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\n\tint transmit;\t\t\t\t\t\t\t\t// 1 = re-transmit new game options\n\n\tlong ok_timer = 0;\t\t\t\t\t\t// for timing OK button\n\tint rc;\n\tint i;\n\tchar *item;\n\tint tabs[] = {77};\t\t\t\t\t\t// tabs for player list box\n\tint optiontabs[] = {8};\t\t\t\t\t// tabs for option list box\n\n\tNodeNameType *who;\t\t\t\t\t\t// node to add to Players\n\tlong ping_timer = 0;\t\t\t\t\t\t// for sending Ping packets\n\n\tint color_used[MAX_MPLAYER_COLORS];\t// 1 = color has been used\n\tJoinEventType whahoppa;\t\t\t\t\t// event generated by received packets\n\tCCFileClass loadfile (\"SAVEGAME.NET\");\n\tint load_game = 0;\t\t\t\t\t\t// 1 = load a saved game\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\tint\twidth;\n\tint\theight;\n\n\tbool\tplayer_joined = false;\n\tCountDownTimerClass join_timer;\n\n\tFancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);\n\tFormat_Window_String((char*)TXT_HACKHACK, SeenBuff.Get_Height(), width, height);\n\n\t//------------------------------------------------------------------------\n\t// Buttons\n\t//------------------------------------------------------------------------\n\tGadgetClass *commands;\t\t\t\t\t// button list\n\n\tColorListClass playerlist(BUTTON_PLAYERLIST,\n\t\td_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,\n\t\tTPF_TEXT,\n\t\tMFCD::Retrieve(\"BTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"BTN-DN.SHP\"));\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,\n//#if (GERMAN | FRENCH)\n//\t\td_cancel_x, d_cancel_y);\n//#else\n\t\td_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n//#endif\n\n\t//------------------------------------------------------------------------\n\t//\tBuild the button list\n\t//------------------------------------------------------------------------\n\tcommands = &playerlist;\n\tcancelbtn.Add_Tail(*commands);\n\tplayerlist.Set_Tabs(tabs);\n\n\t//------------------------------------------------------------------------\n\t//\tInit other scenario parameters\n\t//------------------------------------------------------------------------\n\tRule.IsTGrowth = Special.IsTGrowth;\n\tSpecial.IsTSpread = Session.Options.Tiberium;\n\tRule.IsTSpread = Special.IsTSpread;\n\ttransmit = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInit player color-used flags\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MAX_MPLAYER_COLORS; i++) {\n\t\tcolor_used[i] = 0;\t\t\t\t\t\t\t// init all colors to available\n\t}\n\tcolor_used[Session.ColorIdx] = 1;\t\t\t// set my color to used\n\tplayerlist.Set_Selected_Style(ColorListClass::SELECT_BAR, scheme);\n\n\t//------------------------------------------------------------------------\n\t//\tInit random-number generator, & create a seed to be used for all random\n\t//\tnumbers from here on out\n\t//------------------------------------------------------------------------\n//\trandomize();\n\tSeed = rand();\n\n\t//------------------------------------------------------------------------\n\t//\tInit the version-clipping system\n\t//------------------------------------------------------------------------\n\tVerNum.Init_Clipping();\n\n\t//------------------------------------------------------------------------\n\t//\tClear the list of players\n\t//------------------------------------------------------------------------\n\tClear_Vector(&Session.Players);\n\t//------------------------------------------------------------------------\n\t//\tAdd myself to the list, and to the Players vector.\n\t//------------------------------------------------------------------------\n\titem = new char [MPLAYER_NAME_MAX + 64];\n#ifdef OLDWAY\n\tif (Session.House==HOUSE_GOOD) {\n\t\tsprintf(item,\"%s\\t%s\",Session.Handle, Text_String(TXT_ALLIES));\n\t}\n\telse {\n\t\tsprintf(item,\"%s\\t%s\",Session.Handle, Text_String(TXT_SOVIET));\n\t}\n#else\t//OLDWAY\n\tsprintf (item, \"%s\\t%s\", Session.Handle, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\tplayerlist.Add_Item(item,\n\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]);\n\n\n\t/*\n\t** Process the message loop until we are in focus.\n\t*/\n\tCDTimerClass<SystemTimerClass> focus_timer;\t\t// Timer to allow a wait after client joins\n\tfocus_timer = 5*60;\n\n\tWWDebugString (\"RA95 - About to enter wait for focus loop.\\n\");\n\tSetForegroundWindow ( MainWindow );\n\tShowWindow ( MainWindow, SW_SHOWMAXIMIZED );\n\n\tif (!GameInFocus) {\n\t\tdo {\n\t\t\tKeyboard->Check();\n\t\t\tif (!focus_timer){\n\t\t\t\tWWDebugString (\"RA95 - Calling SetForgroundWindow.\\n\");\n\t\t\t\tSetForegroundWindow ( MainWindow );\n\t\t\t\tWWDebugString (\"RA95 - Calling ShowWindow.\\n\");\n\t\t\t\tShowWindow ( MainWindow, SW_SHOWMAXIMIZED );\n\t\t\t\tfocus_timer = 5*60;\n\t\t\t}\n\t\t}while (!GameInFocus);\n\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t}\n\n\twho = new NodeNameType;\n\tstrcpy(who->Name, Session.Handle);\n\twho->Player.House = Session.House;\n\twho->Player.Color = Session.ColorIdx;\n\tSession.Players.Add (who);\n\n\tif (LogicPage != &SeenBuff && LogicPage!= &HidPage) {\n\t\tSet_Logic_Page (SeenBuff);\n\t}\n\n\tLoad_Title_Page(true);\n\tCCPalette.Set();\t//GamePalette.Set();\n\n\t//------------------------------------------------------------------------\n\t//\tProcessing loop\n\t//------------------------------------------------------------------------\n\twhile (process) {\n\t\t#if(SHOW_MONO)\n\t\tIpx.Mono_Debug_Print(-1,0);\n\t\t#endif\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\t#endif\n\t\t//.....................................................................\n\t\t//\tRefresh display if needed\n\t\t//.....................................................................\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw backgound & dialog box\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tCCPalette.Set();\t//GamePalette.Set();\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tDialog & Field labels\n\t\t\t\t//...............................................................\n\t\t\t\tFancy_Text_Print(TXT_HACKHACK, d_dialog_cx-width/2, d_dialog_y + 25*RESFACTOR, scheme, TBLACK, TPF_TEXT);\n\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw buttons\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcommands->Draw_All();\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tGet user input\n\t\t//.....................................................................\n\t\tinput = commands->Input();\n\n\t\t//.....................................................................\n\t\t//\tProcess input\n\t\t//.....................................................................\n\t\tswitch (input) {\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\t\t\tstrcpy (Session.GPacket.Name, Session.Handle);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tBroadcast my sign-off over my network\n\t\t\t\t//...............................................................\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\tsizeof (GlobalPacketType), 0, NULL);\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\tsizeof (GlobalPacketType), 0, NULL);\n\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tAnd now, just be absolutely sure, send my sign-off to each\n\t\t\t\t//\tplayer in my game.  (If there's a bridge between us, the other\n\t\t\t\t//\tplayer will have specified my address, so he can cross the\n\t\t\t\t//\tbridge; but I may not have specified a bridge address, so the\n\t\t\t\t//\tonly way I have of crossing the bridge is to send a packet\n\t\t\t\t//\tdirectly to him.)\n\t\t\t\t// Don't send this message to myself.\n\t\t\t\t//...............................................................\n\t\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\tsizeof(GlobalPacketType), 1, &(Session.Players[i]->Address));\n\t\t\t\t\tIpx.Service();\n\t\t\t\t}\n\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\t\t\t\tSession.GameName[0] = 0;\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\t\t\t\tSend_Data_To_DDE_Server (\"Hello\", strlen(\"Hello\"), DDEServerClass::DDE_CONNECTION_FAILED);\n\t\t\t\tGameStatisticsPacketSent = false;\n\t\t\t\tSpawn_WChat(false);\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tDefault: manage the inter-player messages\n\t\t\t//..................................................................\n\t\t\tdefault:\n\t\t\t\tif (Session.Players.Count() > 1) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Wait for several secs after receiving request to join before sending\n\t\t\t\t\t** start game packet\n\t\t\t\t\t*/\n\t\t\t\t\tif (!player_joined) {\n\t\t\t\t\t\tplayer_joined = true;\n\t\t\t\t\t\tjoin_timer.Set (3*60, true);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (join_timer.Time()) break;\n\t\t\t\t\t}\n\n\t\t\t\t\t//...............................................................\n\t\t\t\t\t//\tIf a new player has joined in the last second, don't allow\n\t\t\t\t\t//\tan OK; force a wait longer than 1 second (to give all players\n\t\t\t\t\t//\ta chance to know about this new guy)\n\t\t\t\t\t//...............................................................\n\t\t\t\t\ti = MAX(Ipx.Global_Response_Time() * 2, 60*2);\n\t\t\t\t\twhile (TickCount - ok_timer < i) {\n\t\t\t\t\t\tIpx.Service();\n\t\t\t\t\t}\n\n\t\t\t\t\t//...............................................................\n\t\t\t\t\t//\tIf there are at least 2 players, go ahead & play; error otherwise\n\t\t\t\t\t//...............................................................\n\t\t\t\t\tif (Session.Solo || Session.Players.Count() > 1 || Session.Options.Ghosts) {\n\t\t\t\t\t\trc = TRUE;\n\t\t\t\t\t\tprocess = FALSE;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tWWMessageBox().Process (TXT_ONLY_ONE,TXT_OOPS,NULL);\n\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\t}\n\t\t\t\t\t//if (input==(BUTTON_LOAD | KN_BUTTON))\n\t\t\t\t\t//\tload_game = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tProcess incoming packets\n\t\t//.....................................................................\n\t\twhahoppa = Get_NewGame_Responses(&playerlist, color_used);\n\t\tif (whahoppa == EV_NEW_PLAYER) {\n\t\t\tok_timer = TickCount;\n\t\t\ttransmit = 1;\n\t\t}\n\t\telse if (whahoppa == EV_MESSAGE) {\n\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tIf our Transmit flag is set, we need to send out a game option packet\n\t\t// Don't send it to myself.\n\t\t//.....................................................................\n\t\tif (transmit) {\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\t\tSession.GPacket.Command = NET_GAME_OPTIONS;\n\t\t\t\t/*\n\t\t\t\t** Set up the scenario info so the remote player can match the scenario on his machine\n\t\t\t\t** or request a download if it doesnt exist\n\t\t\t\t*/\n\t\t\t\tstrcpy (Session.GPacket.ScenarioInfo.Scenario, Session.Scenarios[Session.Options.ScenarioIndex]->Description());\n\t\t\t\tCCFileClass file (Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename());\n\n\t\t\t\t//\tajw - I don't understand why this check is done here and not later.\n\t\t\t\tif ( !file.Is_Available() ) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Special new kludge for counterstrike.\n\t\t\t\t\t**\n\t\t\t\t\t** The only time the file can be unavailable is if its a counterstrike\n\t\t\t\t\t** mission and the CS CD is not in the drive so\n\t\t\t\t\t** make sure the counterstrike CD is in the drive.\n\t\t\t\t\t**\n\t\t\t\t\t** If Counterstrike is installed and\n\t\t\t\t\t** the file name matches a counterstrike map then force the CD\n\t\t\t\t\t** to be there.\n\t\t\t\t\t**\n\t\t\t\t\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\tif ( Expansion_CS_Present() || Expansion_AM_Present() ) {\n\t\t\t\t\t\tif ( toupper (Session.ScenarioFileName [2]) == 'M' ){\n\n\t\t\t\t\t\t\tint current_drive = CCFileClass::Get_CD_Drive();\n\t\t\t\t\t\t\tint index = Get_CD_Index(current_drive, 1*60);\n\t\t\t\t\t\t\tbool needcd = false;\n\t\t\t\t\t\t\tif (Is_Mission_Counterstrike(Session.ScenarioFileName) && index!=2 && index!=3) {\n\t\t\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t\t\t\tRequiredCD = 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (Is_Mission_Aftermath(Session.ScenarioFileName) && index!=3) {\n\t\t\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t\t\t\tRequiredCD = 3;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (needcd) {\n#else\n\t\t\t\t\tif ( Expansion_CS_Present() ) {\n\t\t\t\t\t\tif ( toupper (Session.ScenarioFileName [2]) == 'M' ){\n\t\t\t\t\t\t\tint scen_num;\n\t\t\t\t\t\t\tsscanf ( Session.ScenarioFileName, \"SCM%02d\", &scen_num );\n\n\t\t\t\t\t\t\tint current_drive = CCFileClass::Get_CD_Drive();\n\t\t\t\t\t\t\tif ( scen_num>24 && Get_CD_Index(current_drive, 1*60) != 2){\n\t\t\t\t\t\t\t\tRequiredCD = 2;\n#endif\n\t\t\t\t\t\t\t\tif (!Force_CD_Available (RequiredCD)){\n\t\t\t\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** Update the internal list of scenarios to include the counterstrike\n\t\t\t\t\t\t\t\t** list.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tSession.Read_Scenario_Descriptions();\n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t** See if that file is available now. Its fatal if it isnt.\n\t\t\t\t\t*/\n\t\t\t\t\tif ( !file.Is_Available() ) {\n\n\t\t\t\t\t\tWWMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH);\n\n\t\t\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\t\t\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\t\t\t\t\tstrcpy (Session.GPacket.Name, Session.Handle);\n\n\t\t\t\t\t\t//..................................................................\n\t\t\t\t\t\t// Don't send myself the message.\n\t\t\t\t\t\t//..................................................................\n\t\t\t\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\t\t\tsizeof(GlobalPacketType), 1,\n\t\t\t\t\t\t\t\t&(Session.Players[i]->Address));\n\t\t\t\t\t\t\tIpx.Service();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t\t\t0, NULL);\n\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t\t\t0, NULL);\n\n\t\t\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\t\t\t\tClear_Listbox(&playerlist);\n\n\t\t\t\t\t\t//------------------------------------------------------------------------\n\t\t\t\t\t\t//\tRestore screen\n\t\t\t\t\t\t//------------------------------------------------------------------------\n\t\t\t\t\t\tHide_Mouse();\n\t\t\t\t\t\tLoad_Title_Page(true);\n\t\t\t\t\t\tShow_Mouse();\n\n\t\t\t\t\t\t//------------------------------------------------------------------------\n\t\t\t\t\t\t// Clear the Players vector if we're not starting a game.\n\t\t\t\t\t\t//------------------------------------------------------------------------\n\t\t\t\t\t\tClear_Vector(&Session.Players);\n\t\t\t\t\t\treturn (false);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\n\t\t\t\tSession.GPacket.ScenarioInfo.FileLength = file.Size();\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\tstrcpy( Session.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename() );\n#else\n\t\t\t\tstrncpy (Session.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename(), sizeof(Session.GPacket.ScenarioInfo.ShortFileName));\n#endif\n\t\t\t\tstrncpy ((char*)Session.GPacket.ScenarioInfo.FileDigest, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Digest(), sizeof (Session.GPacket.ScenarioInfo.FileDigest));\n\t\t\t\tSession.GPacket.ScenarioInfo.OfficialScenario = Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official();\n\n\t\t\t\tSession.GPacket.ScenarioInfo.Credits = Session.Options.Credits;\n\t\t\t\tSession.GPacket.ScenarioInfo.IsBases = Session.Options.Bases;\n\t\t\t\tSession.GPacket.ScenarioInfo.IsTiberium = Session.Options.Tiberium;\n\t\t\t\tSession.GPacket.ScenarioInfo.IsGoodies = Session.Options.Goodies;\n\t\t\t\t//Session.GPacket.ScenarioInfo.IsGhosties = Session.Options.Ghosts;\n\t\t\t\tSession.GPacket.ScenarioInfo.BuildLevel = BuildLevel;\n\t\t\t\tSession.GPacket.ScenarioInfo.UnitCount = Session.Options.UnitCount;\n\t\t\t\tSession.GPacket.ScenarioInfo.AIPlayers = Session.Options.AIPlayers;\n\t\t\t\tSession.GPacket.ScenarioInfo.Seed = Seed;\n\t\t\t\tSession.GPacket.ScenarioInfo.Special = Special;\n\t\t\t\tSession.GPacket.ScenarioInfo.GameSpeed = Options.GameSpeed;\n\t\t\t\tSession.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version();\n\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t1, &(Session.Players[i]->Address) );\n\t\t\t}\n\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t\ttransmit = 0;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tPing every player in my game, to force the Global Channel to measure\n\t\t//\tthe connection response time.  Don't ping myself (index 0).\n\t\t//.....................................................................\n\t\tif (TickCount - ping_timer > 15) {\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\tSession.GPacket.Command = NET_PING;\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t1, &(Session.Players[i]->Address) );\n\t\t\t}\n\t\t\tping_timer = TickCount;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tService the Ipx connections\n\t\t//.....................................................................\n\t\tIpx.Service();\n\n\t\t//.....................................................................\n\t\t//\tService the sounds & score; GameActive must be false at this point,\n\t\t//\tso Call_Back() doesn't intercept global messages from me!\n\t\t//.....................................................................\n\t\tCall_Back();\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tPrepare to load the scenario\n\t//------------------------------------------------------------------------\n\tif (rc) {\n\t\t//.....................................................................\n\t\t//\tSet the player count & scenario number\n\t\t//.....................................................................\n\t\tSession.NumPlayers = Session.Players.Count();\n\n\t\tScen.Scenario = Session.Options.ScenarioIndex;\n\t\tstrcpy (Scen.ScenarioName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename());\n\n\t\t//.....................................................................\n\t\t//\tCompute frame delay value for packet transmissions:\n\t\t//\t- Divide global channel's response time by 8 (2 to convert to 1-way\n\t\t//\t  value, 4 more to convert from ticks to frames)\n\t\t//.....................................................................\n\t\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\t\tSession.MaxAhead = MAX( ((((Ipx.Global_Response_Time() / 8) +\n\t\t\t\t(Session.FrameSendRate - 1)) / Session.FrameSendRate) *\n\t\t\t\tSession.FrameSendRate), (Session.FrameSendRate * 2) );\n\t\t}\n\t\telse {\n\t\t\tSession.MaxAhead = MAX( (Ipx.Global_Response_Time() / 8),\n\t\t\t\t\t\t\t\t\t\t  NETWORK_MIN_MAX_AHEAD );\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tSend all players the NET_GO packet.  Wait until all ACK's have been\n\t\t//\treceived.\n\t\t//.....................................................................\n\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\tif (load_game)\n\t\t\tSession.GPacket.Command = NET_LOADGAME;\n\t\telse\n\t\t\tSession.GPacket.Command = NET_GO;\n\t\tSession.GPacket.ResponseTime.OneWay = Session.MaxAhead;\n\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t1, &(Session.Players[i]->Address) );\n\t\t}\n\t\t//.....................................................................\n\t\t//\tWait for all the ACK's to come in.\n\t\t//.....................................................................\n\t\twhile (Ipx.Global_Num_Send() > 0) {\n\t\t\tIpx.Service();\n\t\t}\n\n\n\t\t/*\n\t\t** Wait for the go responses from each player in case someone needs the scenario\n\t\t** file to be sent.\n\t\t*/\n\t\tint responses[20];\t\t//In big trub if more than 20 players\n\t\tmemset (responses, 0, sizeof (responses));\n\t\tint num_responses = 0;\n\t\tbool send_scenario = false;\n\t\tWWDebugString (\"RA95 - About to wait for 'GO' response.\\n\");\n\n\t\tCDTimerClass<SystemTimerClass> response_timer;\t\t// timeout timer for waiting for responses\n\t\tresponse_timer = 60*30;\t\t// Wait for 30 seconds. If we dont hear by then assume someone crashed\n\n\t\tdo\t{\n\t\t\tIpx.Service();\n\t\t\tint retcode = Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen,\n\t\t\t\t&Session.GAddress, &Session.GProductID);\n\t\t\tif (retcode && Session.GProductID == IPXGlobalConnClass::COMMAND_AND_CONQUER0) {\n\n\t\t\t\tfor ( i=1 ; i<Session.Players.Count() ; i++ ) {\n\t\t\t\t\tif (Session.Players[i]->Address == Session.GAddress) {\n\t\t\t\t\t\tif (!responses[i]) {\n\t\t\t\t\t\t\tif (Session.GPacket.Command == NET_REQ_SCENARIO) {\n\t\t\t\t\t\t\t\tresponses[i] = Session.GPacket.Command;\n\t\t\t\t\t\t\t\tsend_scenario = true;\n\t\t\t\t\t\t\t\tnum_responses++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (Session.GPacket.Command == NET_READY_TO_GO) {\n\t\t\t\t\t\t\t\tresponses[i] = Session.GPacket.Command;\n\t\t\t\t\t\t\t\tnum_responses++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} while ( num_responses < Session.Players.Count()-1 && response_timer );\n\n\t\tWWDebugString (\"RA95 - Exited response wait loop.\\n\");\n\n\t\t/*\n\t\t** If one of the machines requested that the scenario be sent then send it.\n\t\t*/\n\t\tif (send_scenario) {\n\t\t\tmemset (Session.ScenarioRequests, 0, sizeof (Session.ScenarioRequests));\n\t\t\tSession.RequestCount = 0;\n\t\t\tfor ( i=1 ; i<Session.Players.Count() ; i++ ) {\n\t\t\t\tif (responses[i] == NET_REQ_SCENARIO) {\n\t\t\t\t\tSession.ScenarioRequests[Session.RequestCount++] = i;\n\t\t\t\t}\n\t\t\t}\n\t\t\tSend_Remote_File (Scen.ScenarioName, 1);\n\t\t}\n\n\t}\n\n\t//.....................................................................\n\t//\tWait a while, polling the IPX service routines, to give our ACK\n\t//\ta chance to get to the other system.  If he doesn't get our ACK,\n\t// he'll be waiting the whole time we load MIX files.\n\t//.....................................................................\n\ti = MAX(Ipx.Global_Response_Time() * 2, 60*2);\n\tint starttime = TickCount;\n\twhile (TickCount - starttime < i) {\n\t\tIpx.Service();\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tInit network timing values, using previous response times as a measure\n\t//\tof what our retry delta & timeout should be.\n\t//------------------------------------------------------------------------\n\t//Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,\n\t//\tIpx.Global_Response_Time() * 4);\n\tIpx.Set_Timing (Ipx.Global_Response_Time () + 2, (unsigned long) -1, max (120, Ipx.Global_Response_Time () * 8));\n\n\tClear_Listbox(&playerlist);\n\n\t//------------------------------------------------------------------------\n\t//\tRestore screen\n\t//------------------------------------------------------------------------\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n\tShow_Mouse();\n\n\tif (load_game) {\n\t\tif (!Load_Game (-1)) {\n\t\t\tWWMessageBox().Process (TXT_ERROR_LOADING_GAME);\n\t\t\trc = false;\n\t\t}\n\t\tFrame++;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Clear the Players vector if we're not starting a game.\n\t//------------------------------------------------------------------------\n\tif (!rc) {\n\t\tClear_Vector(&Session.Players);\n\t}\n\n//\twhile (optionlist.Count()>0) {\n//\t\titem = (char *)optionlist.Get_Item(0);\n//\t\tdelete [] item;\n//\t\toptionlist.Remove_Item(item);\n//\t}\n\n\treturn(rc);\n\n#else\t//WIN32\n\n\treturn (0);\n\n#endif\t//WIN32\n}\t/* end of Net_Fake_New_Dialog */\n\n\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Net_Join_Dialog -- lets user join an existing game or start a new one                       *\n *                                                                                             *\n * This dialog displays an edit field for the player's name, and a list of all non-stealth-    *\n * mode games.  Clicking once on a game name displays a list of who's in that game.  Clicking  *\n * \"New\" takes the user to the Net_New dialog, where he waits for other users to join his      *\n * game.  All other input is done through this dialog.                                         *\n *                                                                                             *\n * The dialog has several \"states\":                                                            *\n *                                                                                             *\n *   1) Initially, it waits for the user to fill in his/her name and then to select Join or    *\n *      New; if New is selected, this dialog is exited.                                        *\n *                                                                                             *\n *   2) If Join is selected, the Join & New buttons are removed, but the Cancel button remains.*\n *      The join request is transmitted to the game's owner, and the message \"Waiting for      *\n *      Confirmation\" is displayed, until a confirmation or denial is received from the game's *\n *      owner.  The user may click Cancel at this point to cancel the join request.            *\n *      (Once Join is selected, the name editing field is disabled, and becomes a display-only *\n *      field.  If cancel is selected, it reappears as an edit field.) The user can still click*\n *      around & see who's in which games.                                                     *\n *                                                                                             *\n *   3) If the join request is denied, the dialog re-initializes to its pre-join state; the    *\n *      Join & New buttons reappear, & the Name field is available again.                      *\n *                                                                                             *\n *   4) If join confirmation is obtained, the message changes to show all the current game\t  *\n *      settings.  The user cannot click around & look at other games any more.\t\t\t\t\t  *\n *                                                                                             *\n * Any game running in Stealth mode won't show up on this dialog.                              *\n *                                                                                             *\n * The 'Players' vector matches one-for-one the contents of the list box.  The local system\t  *\n * is always listed first; the IPX Address of the local system will NOT be valid in the\t\t  *\n * Players vector.  The Games & Players vectors should be left filled in even after this\t\t  *\n * routine is exited; their contents are used to form connections to the other players,\t\t  *\n * after the scenario has been loaded.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * The 'Chat' vector contains the address of everyone who sends me a chat announcement.\t\t  *\n * The address field is used to send everyone my outgoing messages.  The LastTime\t\t\t\t  *\n * field is used as a timeout; if enough time goes by & we don't hear from this node,\t\t\t  *\n * we ping him, requesting a CHAT_ANNOUNCE if he's still in chat.  If we don't hear\t\t\t\t  *\n * from him after that, we remove him from our list.\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *    Ŀ                                    *\n *                     Network Games                                                         *\n *                                                                                           *\n *                  Your Name: ____________                                                  *\n *                      House: [GDI] [NOD]                                                   *\n *              Desired Color: [ ][ ][ ][ ]                                                  *\n *                                                                                           *\n *                Games                 Players                                              *\n *     Ŀ Ŀ                                     *\n *     (Bill's Game         ).  Peter Parker GDI .                                     *\n *      Peter Parker's Game  Ĵ  Mary Jane    GDI Ĵ                                     *\n *     (Magnum PI's Game    )   JJ Jameson   NOD                                       *\n *                           Ĵ                   Ĵ                                     *\n *                           .                   .                                     *\n *                                           *\n *               Scenario: Big Long Description                                              *\n *                    Starting Credits: xxxx                                                 *\n *              Count: ---          Level: ---                                               *\n *              Bases: ON          Crates: ON                                                *\n *           Tiberium: ON      AI Players: ON                                                *\n *                                                                                           *\n *      Ŀ                                      *\n *                                                                                         *\n *                                                                                         *\n *                                            *\n *      Ŀ                                      *\n *                                            *\n *                [Join]  [Cancel]    [New]                                                  *\n *                                        *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      -1 = cancel, 0 = OK, 1 = New net game requested                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nstatic int Net_Fake_Join_Dialog(void)\n{\n\n#ifdef WIN32\n\t//------------------------------------------------------------------------\n\t//\tDialog & button dimensions\n\t//------------------------------------------------------------------------\n\t\tint d_dialog_w = 120 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\t\tint d_dialog_h = 80 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\t\tint d_dialog_x = ((320*RESFACTOR - d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\t\tint d_dialog_y = ((200*RESFACTOR - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\t\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\t\tint d_txt6_h = 6 *RESFACTOR+1;\t\t\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\t\tint d_margin1 = 5 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// large margin\n\t\tint d_margin2 = 7 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// small margin\n\n\t\tint d_gamelist_w = 160 *RESFACTOR;\n\t\tint d_gamelist_h = ((6 * 6) + 3) *RESFACTOR;\t\t// 6 rows high\n//\t\tint d_gamelist_x = d_dialog_x + d_margin1 + d_margin1;\n\t\tint d_gamelist_x = 500*RESFACTOR;\t//d_dialog_x + d_margin1 + d_margin1;\n\t\tint d_gamelist_y = 50 + d_margin2 + 2*RESFACTOR/*KO + d_txt6_h + d_margin2*/;\n\n\t\tint d_playerlist_w = 118 *RESFACTOR;\n\t\tint d_playerlist_h = ((6 * 6) + 3) *RESFACTOR;\t\t// 6 rows high\n\t\t//int d_playerlist_x = d_dialog_x + d_dialog_w - d_margin1 - d_margin1 - d_playerlist_w;\n\t\tint d_playerlist_x = 500*RESFACTOR;\n\t\tint d_playerlist_y = 50+ d_margin2 + 2*RESFACTOR/*KO + d_txt6_h + d_margin2*/;\n\n#if (GERMAN | FRENCH)\n\tint d_cancel_w = 50*RESFACTOR;\n#else\n\tint d_cancel_w = 40*RESFACTOR;\n#endif\n\tint d_cancel_h = 9*RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - d_cancel_w / 2;\n\tint d_cancel_y = d_dialog_y + d_dialog_h - 20*RESFACTOR;\n\n\t//------------------------------------------------------------------------\n\t//\tButton Enumerations\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tBUTTON_GAMELIST = 100,\n\t\tBUTTON_PLAYERLIST,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t//------------------------------------------------------------------------\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PARMS,\n\t\tREDRAW_MESSAGE,\n\t\tREDRAW_COLORS,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t//------------------------------------------------------------------------\n\t//\tDialog variables\n\t//------------------------------------------------------------------------\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\tchar housetext[25] = \"\";\t\t\t\t// buffer for house droplist\n\tint isdropped = 0;\n\n\tJoinStateType joinstate = JOIN_NOTHING;\t// current \"state\" of this dialog\n\tchar namebuf[MPLAYER_NAME_MAX] = {0};\t\t// buffer for player's name\n\tint playertabs[] = {77 *RESFACTOR};\t\t\t\t// tabs for player list box\n\tint optiontabs[] = {8};\t\t\t\t\t// tabs for player list box\n\tint game_index = -1;\t\t\t\t\t\t// index of currently-selected game\n\tint join_index = -1;\t\t\t\t\t\t// index of game we're joining\n\tint rc = 0;\t\t\t\t\t\t\t\t\t// -1 = user cancelled, 1 = New\n\tJoinEventType event;\t\t\t\t\t\t// event from incoming packet\n\tint i;\t\t\t\t\t\t\t\t\t\t// loop counter\n\tint parms_received = 0;\t\t\t\t\t// 1 = game options received\n\tNodeNameType *who;\t\t\t\t\t\t// node to add to Players\n\tRejectType why;\t\t\t\t\t\t\t// reason for rejection\n\tTTimerClass<SystemTimerClass> lastclick_timer;\t\t\t// time b/w send periods\n\tint lastclick_idx = 0;\t\t\t\t\t// index of item last clicked on\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\tint ready_to_go = 0;\n\tSession.Options.ScenarioDescription[0] = 0;\t//Flag that we dont know the scenario name yet\n\tint\twidth;\n\tint\theight;\n\n\tFancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);\n\tFormat_Window_String((char*)TXT_HACKHACK, SeenBuff.Get_Height(), width, height);\n\tchar * item;\n\tunsigned long starttime;\n\tint load_game = 0;\t\t\t\t\t\t// 1 = load saved game\n\n\t//------------------------------------------------------------------------\n\t//\tButtons\n\t//------------------------------------------------------------------------\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\n\tListClass gamelist(BUTTON_GAMELIST, d_gamelist_x, d_gamelist_y, d_gamelist_w, d_gamelist_h,\n\t\tTPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\n\tColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,\n\t\tTPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,\n//#if (GERMAN | FRENCH)\n//\t\td_cancel_x, d_cancel_y);\n//#else\n\t\td_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n//#endif\n\n\t//------------------------------------------------------------------------\n\t//\tInit the button states\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t// Name & Color\n\t//........................................................................\n\tSession.ColorIdx = Session.PrefColor;\t\t\t// init my preferred color\n\tstrcpy (namebuf, Session.Handle);\t\t\t\t// set my name\n\n\t//........................................................................\n\t// List boxes\n\t//........................................................................\n\tplayerlist.Set_Tabs(playertabs);\n\tplayerlist.Set_Selected_Style(ColorListClass::SELECT_NORMAL);\n\n\tFancy_Text_Print(\"\", 0, 0, scheme, TBLACK,\n\t\tTPF_CENTER | TPF_TEXT);\n\n\tlastclick_timer = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tClear the list of games, players, and the chat list\n\t//------------------------------------------------------------------------\n\tClear_Vector(&Session.Games);\n\tClear_Vector(&Session.Players);\n\tClear_Vector(&Session.Chat);\n\n\t//------------------------------------------------------------------------\n\t// Add myself to the Chat vector\n\t//------------------------------------------------------------------------\n\twho = new NodeNameType;\n\tstrcpy(who->Name, namebuf);\n\twho->Chat.LastTime = 0;\n\twho->Chat.LastChance = 0;\n\twho->Chat.Color = Session.GPacket.Chat.Color;\n\tSession.Chat.Add (who);\n\n\t//------------------------------------------------------------------------\n\t// Create the \"Lobby\" game name on the games list, and create a bogus\n\t// node for the gamelist, so Games[i] will always match gamelist[i]\n\t//------------------------------------------------------------------------\n\twho = new NodeNameType;\n\tstrcpy(who->Name, \"\");\n\twho->Game.IsOpen = 0;\n\twho->Game.LastTime = 0;\n\tSession.Games.Add (who);\n\titem = new char [MPLAYER_NAME_MAX];\n\tstrcpy(item, Text_String(TXT_LOBBY));\n\tgamelist.Add_Item(item);\n\tgamelist.Set_Selected_Index(0);\n\tgame_index = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tSend game-name query & chat announcement; also, initialize timers.\n\t//------------------------------------------------------------------------\n\tSend_Join_Queries (game_index, joinstate, 1, 0, 1, namebuf, 1);\n\n\t/*\n\t** Process the message loop until we are in focus.\n\t*/\n\tCDTimerClass<SystemTimerClass> focus_timer;\t\t// Timer to allow a wait after client joins\n\tfocus_timer = 5*60;\n\n\tWWDebugString (\"RA95 - About to enter wait for focus loop.\\n\");\n\tSetForegroundWindow ( MainWindow );\n\tShowWindow ( MainWindow, SW_SHOWMAXIMIZED );\n\n\tif (!GameInFocus) {\n\t\tdo {\n\t\t\tKeyboard->Check();\n\t\t\tif (!focus_timer){\n\t\t\t\tWWDebugString (\"RA95 - Calling SetForgroundWindow.\\n\");\n\t\t\t\tSetForegroundWindow ( MainWindow );\n\t\t\t\tWWDebugString (\"RA95 - Calling ShowWindow.\\n\");\n\t\t\t\tShowWindow ( MainWindow, SW_SHOWMAXIMIZED );\n\t\t\t\tfocus_timer = 5*60;\n\t\t\t}\n\t\t}while (!GameInFocus);\n\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t}\n\n\tif (LogicPage != &SeenBuff && LogicPage!= &HidPage) {\n\t\tSet_Logic_Page (SeenBuff);\n\t}\n\n\tLoad_Title_Page(true);\n\tCCPalette.Set();\t//GamePalette.Set();\n\n\t//------------------------------------------------------------------------\n\t//\tProcessing loop\n\t//------------------------------------------------------------------------\n\twhile (process) {\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\t#endif\n\t\t//.....................................................................\n\t\t//\tRefresh display if needed\n\t\t//.....................................................................\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw backgound & dialog box\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tCCPalette.Set();\t//GamePalette.Set();\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tDialog & Field labels\n\t\t\t\t//...............................................................\n\t\t\t\tFancy_Text_Print(TXT_HACKHACK, d_dialog_cx-width/2, d_dialog_y + 25*RESFACTOR, scheme, TBLACK, TPF_TEXT);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tRebuild the button list\n\t\t\t\t//...............................................................\n\t\t\t\tcancelbtn.Zap();\n\t\t\t\tgamelist.Zap();\n\t\t\t\tplayerlist.Zap();\n\n\t\t\t\tcommands = &cancelbtn;\n\t\t\t\tgamelist.Add_Tail(*commands);\n\t\t\t\tplayerlist.Add_Tail(*commands);\n\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw buttons\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcommands->Draw_All();\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tGet user input\n\t\t//.....................................................................\n\t\tinput = commands->Input();\n\n\t\t//.....................................................................\n\t\t//\tProcess input\n\t\t//.....................................................................\n\t\tswitch (input) {\n\n\t\t\t//..................................................................\n\t\t\t// ESC / CANCEL: send a SIGN_OFF\n\t\t\t// - If we're part of a game, stay in this dialog; otherwise, exit\n\t\t\t//..................................................................\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf we're joined to a game, make extra sure the other players in\n\t\t\t\t//\tthat game know I'm exiting; send my SIGN_OFF as an ack-required\n\t\t\t\t//\tpacket.  Don't send this to myself (index 0).\n\t\t\t\t//...............................................................\n\t\t\t\tif (joinstate == JOIN_CONFIRMED) {\n\t\t\t\t\tUnjoin_Game(namebuf, joinstate, &gamelist, &playerlist,\n\t\t\t\t\t\tgame_index, 1, 0, 0, d_txt6_h, 0,\n\t\t\t\t\t\t0, MAX_MESSAGE_LENGTH);\n\t\t\t\t\tjoinstate = JOIN_NOTHING;\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t// If I'm not joined to a game, send a SIGN_OFF to all players\n\t\t\t\t// in my Chat vector (but not to myself, index 0)\n\t\t\t\t//...............................................................\n\t\t\t\telse {\n\t\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\t\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\t\t\t\tstrcpy(Session.GPacket.Name,namebuf);\n\t\t\t\t\tfor (i = 1; i < Session.Chat.Count(); i++) {\n\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\t\tsizeof(GlobalPacketType),\n\t\t\t\t\t\t\t1, &(Session.Chat[i]->Address));\n\t\t\t\t\t\tIpx.Service();\n\t\t\t\t\t}\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tNow broadcast a SIGN_OFF just to be thorough\n\t\t\t\t\t//............................................................\n\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\tsizeof (GlobalPacketType), 0, NULL);\n\t\t\t\t\tif (Session.IsBridge) {\n\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\t\tsizeof(GlobalPacketType), 0, &Session.BridgeNet);\n\t\t\t\t\t}\n\n\t\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// exit the dialog\n\t\t\t\t\t//............................................................\n\t\t\t\t\tSend_Data_To_DDE_Server (\"Hello\", strlen(\"Hello\"), DDEServerClass::DDE_CONNECTION_FAILED);\n\t\t\t\t\tGameStatisticsPacketSent = false;\n\t\t\t\t\tSpawn_WChat(false);\n\t\t\t\t\tprocess = false;\n\t\t\t\t\trc = -1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\n\t\t\t//..................................................................\n\t\t\t//\tJOIN: send a join request packet & switch to waiting-for-\n\t\t\t// confirmation mode.\n\t\t\t//..................................................................\n\t\t\tdefault:\n\t\t\t\tif (joinstate == JOIN_NOTHING && gamelist.Count() >1 ) {\n\t\t\t\t\tgamelist.Set_Selected_Index(1);\t//lastclick_idx);\n\t\t\t\t\tgame_index = 1;\n\t\t\t\t\tstrcpy (Session.Handle,namebuf);\n\t\t\t\t\t//Session.House = (HousesType)housebtn.Current_Index();\n\t\t\t\t\tjoin_index = gamelist.Current_Index();\n\t\t\t\t\tparms_received = 0;\n\t\t\t\t\tif (Request_To_Join (namebuf, join_index, Session.House,\n\t\t\t\t\t\tSession.ColorIdx)) {\n\t\t\t\t\t\tjoinstate = JOIN_WAIT_CONFIRM;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tResend our query packets\n\t\t//.....................................................................\n\t\tSend_Join_Queries(game_index, joinstate, 0, 0, 0, namebuf);\n\n\t\t//.....................................................................\n\t\t//\tProcess incoming packets\n\t\t//.....................................................................\n\t\tevent = Get_Join_Responses(&joinstate, &gamelist, &playerlist,\n\t\t\tjoin_index, namebuf, &why);\n\n\t\t//.....................................................................\n\t\t//\tIf we've changed state, redraw everything; if we're starting the game,\n\t\t//\tbreak out of the loop.  If we've just joined, send out a player query\n\t\t//\tso I'll get added to the list instantly.\n\t\t//.....................................................................\n\t\tif (event == EV_STATE_CHANGE) {\n\t\t\tdisplay = REDRAW_ALL;\n\t\t\tif (joinstate==JOIN_GAME_START || joinstate == JOIN_GAME_START_LOAD) {\n\t\t\t\tif (joinstate==JOIN_GAME_START_LOAD) load_game = 1;\n\n\t\t\t\tbool ready_packet_was_sent = false;\n\n\t\t\t\tif (!load_game){\n\t\t\t\t\t/*\n\t\t\t\t\t** Special new kludge for counterstrike.\n\t\t\t\t\t**\n\t\t\t\t\t** Find local scenario will fail to match a counterstrike mission\n\t\t\t\t\t** unless the CS CD is in the drive. So....\n\t\t\t\t\t**\n\t\t\t\t\t** If Counterstrike is installed and this is an official map and\n\t\t\t\t\t** the file name matches a counterstrike map then tell the host\n\t\t\t\t\t** that I have the scenario so he can continue while we make\n\t\t\t\t\t** sure the local user has the Counterstrike CD in the drive.\n\t\t\t\t\t**\n\t\t\t\t\t*/\n\t\t\t\t\t//\tThis is duplicated for Aftermath scenarios. ajw\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif (Session.ScenarioIsOfficial &&\n\t\t\t\t\t( (Expansion_CS_Present() && Is_Mission_Counterstrike(Session.ScenarioFileName)) ||\n\t\t\t\t\t  (Expansion_AM_Present() && Is_Mission_Aftermath(Session.ScenarioFileName)) ) ) {\n#else\n\t\t\t\t\tif ( Expansion_CS_Present() && Session.ScenarioIsOfficial ) {\n#endif\n\n\t\t\t\t\t\tCCFileClass check_file ( Session.ScenarioFileName );\n\t\t\t\t\t\tif ( !check_file.Is_Available() ) {\n\n\t\t\t\t\t\t\tint current_drive = CCFileClass::Get_CD_Drive();\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\t\tint index = Get_CD_Index(current_drive, 1*60);\n\t\t\t\t\t\t\tbool needcd = false;\n\t\t\t\t\t\t\tif (Is_Mission_Counterstrike(Session.ScenarioFileName)) {\n\t\t\t\t\t\t\t\tif (index != 2 && index != 3) {\n\t\t\t\t\t\t\t\t\tRequiredCD = 2;\n\t\t\t\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (Is_Mission_Aftermath(Session.ScenarioFileName)) {\n\t\t\t\t\t\t\t\tif (index != 3) {\n\t\t\t\t\t\t\t\t\tRequiredCD = 3;\n\t\t\t\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (needcd) {\n#else\n\t\t\t\t\t\t\tif ( Get_CD_Index(current_drive, 1*60) != 2 ){\n\t\t\t\t\t\t\t\tRequiredCD = 2;\n#endif\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** We should have the scenario but the wrong disk is in.\n\t\t\t\t\t\t\t\t** Tell the host that I am ready to go anyway.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tmemset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket));\n\t\t\t\t\t\t\t\tSession.GPacket.Command = NET_READY_TO_GO;\n\t\t\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t\t\t\t\t1, &Session.HostAddress);\n\t\t\t\t\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0);\n\t\t\t\t\t\t\t\tready_packet_was_sent = true;\n\n\t\t\t\t\t\t\t\tif (!Force_CD_Available (RequiredCD)){\n\t\t\t\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tCCFileClass testfile ( Session.ScenarioFileName );\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** Update the internal list of scenarios to include the counterstrike\n\t\t\t\t\t\t\t\t** list.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tSession.Read_Scenario_Descriptions();\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** See if that scenario is available now. Its pretty fatal if it isnt.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tSession.Options.ScenarioIndex = -1;\n\t\t\t\t\t\t\t\tfor (i = 0; i < Session.Scenarios.Count(); i++) {\n\t\t\t\t\t\t\t\t\tif (!strcmp (Session.Scenarios[i]->Description(), Session.Options.ScenarioDescription) ){\n\t\t\t\t\t\t\t\t\t\tSession.Options.ScenarioIndex = i;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If the scenario that the host wants to play doesnt exist locally then we\n\t\t\t\t\t**\tneed to request that it is sent. If we can identify the scenario locally then\n\t\t\t\t\t**\twe need to fix up the file name so we load the right one.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Find_Local_Scenario (Session.Options.ScenarioDescription,\n\t\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioFileName,\n\t\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioFileLength,\n\t\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioDigest,\n\t\t\t\t\t \t\t\t\t\t\t\t\tSession.ScenarioIsOfficial)) {\n\n\t\t\t\t\t\tSession.Options.ScenarioIndex = 1;\t\t//We dont care what it\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//is as long as it isnt -1\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** We have the scenario. Tell the host that I am ready to go.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif ( !ready_packet_was_sent ){\n\t\t\t\t\t\t\tmemset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket));\n\t\t\t\t\t\t\tSession.GPacket.Command = NET_READY_TO_GO;\n\t\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t\t\t\t1, &Session.HostAddress);\n\t\t\t\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n#ifndef FIXIT_VERSION_3\t\t\t//\tRemoved restriction on downloading official maps.\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Oh dear. Thats a scenario I dont have. Request that the host sends the\n\t\t\t\t\t\t**\tscenario to me provided its not an official Westwood scenario.\n\t\t\t\t\t\t**\n\t\t\t\t\t\t** If the file is received OK then we will get a true return value and the\n\t\t\t\t\t\t** actual file name to load will be in Session.ScenarioFileName\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (Session.ScenarioIsOfficial) {\n\t\t\t\t\t\t\tSession.Options.ScenarioIndex = -1;\n\t\t\t\t\t\t} else {\n#endif\n\t\t\t\t\t\t\tSession.Options.ScenarioIndex = 1;\t\t//We dont care what it\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//is as long as it isnt -1\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\tif( bSpecialAftermathScenario( Session.Options.ScenarioDescription ) )\n\t\t\t\t\t\t\t\tbreak;\n#endif\n\n\t\t\t\t\t\t\tif (!Get_Scenario_File_From_Host(Session.ScenarioFileName, 1)) {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** Make sure we dont time-out because of the download\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t}\n#ifndef FIXIT_VERSION_3\n\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t** Make sure we respond to the host in a load game\n\t\t\t\t\t*/\n\t\t\t\t\tmemset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket));\n\t\t\t\t\tSession.GPacket.Command = NET_READY_TO_GO;\n\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t\t1, &Session.HostAddress);\n\t\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0);\n\t\t\t\t}\n\n\t\t\t\tstrcpy (Scen.ScenarioName, Session.ScenarioFileName);\n\n\t\t\t\trc = 0;\n\t\t\t\tprocess = false;\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tIf we're newly-confirmed, add myself to the Players list, and\n\t\t\t// immediately send out a player query\n\t\t\t//..................................................................\n\t\t\telse if (joinstate==JOIN_CONFIRMED) {\n\t\t\t\t//...............................................................\n\t\t\t\t//\tClear the player list, then add myself to the list.\n\t\t\t\t//...............................................................\n\t\t\t\tClear_Listbox(&playerlist);\n\t\t\t\tClear_Vector (&Session.Players);\n\n\t\t\t\titem = new char [MPLAYER_NAME_MAX + 12];\n#ifdef OLDWAY\n\t\t\t\tif (Session.House==HOUSE_GOOD) {\n\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf, Text_String(TXT_ALLIES));\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf, Text_String(TXT_SOVIET));\n\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\tsprintf (item, \"%s\\t%s\", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\t\t\t\tplayerlist.Add_Item(item,\n\t\t\t\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]);\n\n\t\t\t\twho = new NodeNameType;\n\t\t\t\tstrcpy(who->Name, namebuf);\n\t\t\t\twho->Player.House = Session.House;\n\t\t\t\twho->Player.Color = Session.ColorIdx;\n\t\t\t\tSession.Players.Add (who);\n\n\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);\n#if (0)\n\t\t\t\t//...............................................................\n\t\t\t\t// Re-init the message system to its new smaller size\n\t\t\t\t//...............................................................\n\t\t\t\tSession.Messages.Init (0,0, 8,\n\t\t\t\t\tMAX_MESSAGE_LENGTH, d_txt6_h, 0, 0, 1,\n\t\t\t\t\t20, MAX_MESSAGE_LENGTH - 5);\n\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx, TPF_TEXT | TPF_BRIGHT_COLOR, NULL, '_');\n#endif\t//(0)\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tIf we've been rejected, clear any messages we may have been\n\t\t\t// typing, add a message stating why we were rejected, and send a\n\t\t\t// chat announcement.\n\t\t\t//..................................................................\n\t\t\telse if (joinstate==JOIN_REJECTED) {\n\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 0, 1, namebuf);\n\n\t\t\t}\n\t\t}\t// end of state change\n\n\t\t//.....................................................................\n\t\t//\tIf the game options have changed, print them.\n\t\t//.....................................................................\n\t\telse if (event == EV_GAME_OPTIONS) {\n\n\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\n\t\t\tparms_received = 1;\n\t\t\tdisplay = REDRAW_PARMS;\n\t\t}\n\n\n\t\t//.....................................................................\n\t\t// EV_GAME_SIGNOFF:\n\t\t//\tA game before the one I've selected is gone, so we have a new index\n\t\t// now. 'game_index' must be kept set to the currently-selected list\n\t\t// item, so we send out queries for the currently-selected game.  It's\n\t\t// therefore imperative that we detect any changes to the game list.\n\t\t// If we're joined in a game, we must decrement our game_index to keep\n\t\t// it aligned with the game we're joined to.\n\t\t//.....................................................................\n\t\telse if (event == EV_GAME_SIGNOFF) {\n\t\t\tif (joinstate==JOIN_CONFIRMED) {\n\t\t\t\tgame_index--;\n\t\t\t\tjoin_index--;\n\t\t\t\tgamelist.Set_Selected_Index(join_index);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tgamelist.Flag_To_Redraw();\n\t\t\t\tClear_Listbox(&playerlist);\n\t\t\t\tClear_Vector (&Session.Players);\n\t\t\t\tgame_index = gamelist.Current_Index();\n\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tService the Ipx connections\n\t\t//.....................................................................\n\t\tIpx.Service();\n\n\t\tif (process) {\n\t\t\t//.....................................................................\n\t\t\t//\tClean out the Game List; if an old entry is found:\n\t\t\t//\t- Remove it\n\t\t\t//\t- Clear the player list\n\t\t\t//\t- Send queries for the new selected game, if there is one\n\t\t\t//.....................................................................\n\t\t\tfor (i = 1; i < Session.Games.Count(); i++) {\n\t\t\t\tif (TickCount - Session.Games[i]->Game.LastTime > 400) {\n\n\t\t\t\t\tdelete Session.Games[i];\n\t\t\t\t\tSession.Games.Delete(Session.Games[i]);\n\n\t\t\t\t\titem = (char *)(gamelist.Get_Item (i));\n\t\t\t\t\tgamelist.Remove_Item (item);\n\t\t\t\t\tdelete [] item;\n\n\t\t\t\t\tif (i <= game_index) {\n\t\t\t\t\t\tif (joinstate==JOIN_CONFIRMED) {\n\t\t\t\t\t\t\tgame_index--;\n\t\t\t\t\t\t\tjoin_index--;\n\t\t\t\t\t\t\tgamelist.Set_Selected_Index(join_index);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tgamelist.Flag_To_Redraw();\n\t\t\t\t\t\t\tClear_Listbox(&playerlist);\n\t\t\t\t\t\t\tClear_Vector (&Session.Players);\n\t\t\t\t\t\t\tgame_index = gamelist.Current_Index();\n\t\t\t\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n#if (0)\n\t\t/*\n\t\t** If we were flagged to start the game and we recognise both players then quit the loop\n\t\t*/\n\t\tif (ready_to_go && Session.Players.Count() == 2) {\n\t\t\trc = 0;\n\t\t\tprocess = false;\n\t\t}\n#endif\t//(0)\n\n\t\t//.....................................................................\n\t\t//\tService the sounds & score; GameActive must be false at this point,\n\t\t//\tso Call_Back() doesn't intercept global messages from me!\n\t\t//.....................................................................\n\t\tCall_Back();\n\n\t}\t// end of while\n\n\n\t//------------------------------------------------------------------------\n\t//\tEstablish connections with all other players.\n\t//------------------------------------------------------------------------\n\tif (rc == 0) {\n\t\t//.....................................................................\n\t\t//\tIf the other guys are playing a scenario I don't have (sniff), I can't\n\t\t//\tplay.  Try to bail gracefully.\n\t\t//.....................................................................\n\t\tif (Session.Options.ScenarioIndex==-1) {\n\t\t\tWWMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH);\n\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\t\tstrcpy (Session.GPacket.Name, namebuf);\n\n\t\t\t//..................................................................\n\t\t\t// Don't send myself the message.\n\t\t\t//..................................................................\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\tsizeof(GlobalPacketType), 1,\n\t\t\t\t\t&(Session.Players[i]->Address));\n\t\t\t\tIpx.Service();\n\t\t\t}\n\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t0, NULL);\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t0, NULL);\n\n\t\t\tif (Session.IsBridge) {\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType),\n\t\t\t\t\t0, &Session.BridgeNet);\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType),\n\t\t\t\t\t0, &Session.BridgeNet);\n\t\t\t}\n\n\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\trc = -1;\n\n\t\t}\n\t\t//---------------------------------------------------------------------\n\t\t// Prepare to load the scenario.\n\t\t//---------------------------------------------------------------------\n\t\telse {\n\t\t\t//..................................................................\n\t\t\t//\tSet the number of players in this game, and the scenario number.\n\t\t\t//..................................................................\n\t\t\tSession.NumPlayers = Session.Players.Count();\n///*\n//**\tHack to fake a scenario name as if it had been sent over the connection.\n//*/\n//sprintf(Scen.ScenarioName, \"SCM%02dEA.INI\", Session.Options.ScenarioIndex+1);\n\n//\t\t\tScen.Scenario = Session.Options.ScenarioIndex;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tWait a while, polling the IPX service routines, to give our ACK\n\t\t//\ta chance to get to the other system.  If he doesn't get our ACK,\n\t\t// he'll be waiting the whole time we load MIX files.\n\t\t//.....................................................................\n\t\ti = MAX(Ipx.Global_Response_Time() * 2, 60*2);\n\t\tstarttime = TickCount;\n\t\twhile (TickCount - starttime < i) {\n\t\t\tIpx.Service();\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tInit network timing values, using previous response times as a measure\n\t//\tof what our retry delta & timeout should be.\n\t//------------------------------------------------------------------------\n\t//Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,\n\t//\tIpx.Global_Response_Time() * 4);\n\tIpx.Set_Timing (Ipx.Global_Response_Time () + 2, (unsigned long) -1, max (120, Ipx.Global_Response_Time () * 8));\n\n\t//------------------------------------------------------------------------\n\t//\tClear all lists, but NOT the Games & Players vectors.\n\t//------------------------------------------------------------------------\n\tClear_Listbox(&gamelist);\n\tClear_Listbox(&playerlist);\n\n\t//------------------------------------------------------------------------\n\t//\tRestore screen\n\t//------------------------------------------------------------------------\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n\tShow_Mouse();\n\t//------------------------------------------------------------------------\n\t// Load a game if the game owner told us to\n\t//------------------------------------------------------------------------\n\tif (load_game) {\n\t\tif (!Load_Game (-1)) {\n\t\t\tWWMessageBox().Process (TXT_ERROR_LOADING_GAME);\n\t\t\trc = -1;\n\t\t}\n\t\tFrame++;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Clear the Players & Games vectors if we're not joined to a game.\n\t// Clear the Chat vector regardless.\n\t//------------------------------------------------------------------------\n\tif (rc != 0) {\n\t\tClear_Vector(&Session.Games);\n\t\tClear_Vector(&Session.Players);\n\t}\n\tClear_Vector(&Session.Chat);\n\n\treturn(rc);\n\n#else\t//WIN32\n\n\treturn (0);\n\n#endif\t//WIN32\n\n}\t/* end of Net_Join_Dialog */\n\n\n\n\n\n\n\n\n\n\nbool Server_Remote_Connect(void)\n{\n\tint stealth;\t\t\t\t// original state of Session.NetStealth flag\n\n\t//------------------------------------------------------------------------\n\t//\tInit network timing parameters; these values should work for both a\n\t// \"real\" network, and a simulated modem network (ie Kali)\n\t//------------------------------------------------------------------------\n\tIpx.Set_Timing (\t30, \t\t// retry 2 times per second\n\t\t\t\t\t\t\t-1, \t\t// ignore max retries\n\t\t\t\t\t\t\t600);\t\t// give up after 10 seconds\n\n\t//------------------------------------------------------------------------\n\t//\tSave the original value of the NetStealth flag, so we can turn stealth\n\t//\toff for now (during this portion of the dialogs, we must show ourselves)\n\t//------------------------------------------------------------------------\n\tstealth = Session.NetStealth;\n\tSession.NetStealth = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tThe game is now \"open\" for joining.  Close it as soon as we exit this\n\t//\troutine.\n\t//------------------------------------------------------------------------\n\tSession.NetOpen = 1;\n\n\t//------------------------------------------------------------------------\n\t//\tRead in last multiplayer game settings from the .INI file\n\t//------------------------------------------------------------------------\n\tif (!Net_Fake_New_Dialog()) {\n\t\tSession.Write_MultiPlayer_Settings ();\n\t\treturn (false);\n\t}\n\n\tSession.NetOpen = 0;\n\tSession.NetStealth = stealth;\n\tSession.Write_MultiPlayer_Settings ();\n\treturn (true);\n\n}\t/* end of Server_Remote_Connect */\n\n\n\n\n\n\n\nbool Client_Remote_Connect(void)\n{\n\tint rc;\n\tint stealth;\t\t\t\t// original state of Session.NetStealth flag\n\n\t//------------------------------------------------------------------------\n\t//\tInit network timing parameters; these values should work for both a\n\t// \"real\" network, and a simulated modem network (ie Kali)\n\t//------------------------------------------------------------------------\n\tIpx.Set_Timing (\t30, \t\t// retry 2 times per second\n\t\t\t\t\t\t\t-1, \t\t// ignore max retries\n\t\t\t\t\t\t\t600);\t\t// give up after 10 seconds\n\n\t//------------------------------------------------------------------------\n\t//\tSave the original value of the NetStealth flag, so we can turn stealth\n\t//\toff for now (during this portion of the dialogs, we must show ourselves)\n\t//------------------------------------------------------------------------\n\tstealth = Session.NetStealth;\n\tSession.NetStealth = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tThe game is now \"open\" for joining.  Close it as soon as we exit this\n\t//\troutine.\n\t//------------------------------------------------------------------------\n\tSession.NetOpen = 1;\n\n\t//------------------------------------------------------------------------\n\t//\tRead in last multiplayer game settings from the .INI file\n\t//------------------------------------------------------------------------\n\trc = Net_Fake_Join_Dialog();\n\tSession.Write_MultiPlayer_Settings ();\n\n\tSession.NetStealth = stealth;\n\tSession.NetOpen = 0;\n\n\tif (rc == -1) {\n\t\treturn(false);\n\t} else {\n\t\treturn(true);\n\t}\n\n}\t/* end of Client_Remote_Connect */\n\n\n\n/*************************** end of netdlg.cpp *****************************/\n\n#endif\t//#ifndef WOLAPI_INTEGRATION\n"
  },
  {
    "path": "CODE/NOSEQCON.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\noseqcon.cpv   1.10   01 Mar 1996 18:08:30   JOE_BOSTIC  $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : SEQCONN.CPP                              *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 20, 1994                        *\n *                                                                         *\n *                  Last Update : April 9, 1995 [BRR]\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:    \t\t\t                                                   *\n *   NonSequencedConnClass::NonSequencedConnClass -- class constructor     *\n *   NonSequencedConnClass::~NonSequencedConnClass -- class destructor     *\n *   NonSequencedConnClass::Init -- Initializes connection queue to empty\t*\n *   NonSequencedConnClass::Send_Packet -- adds a packet to the send queue\t*\n *   NonSequencedConnClass::Receive_Packet -- adds packet to receive queue\t*\n *   NonSequencedConnClass::Get_Packet -- gets a packet from receive queue\t*\n *   NonSequencedConnClass::Service_Send_Queue -- services the send queue\t*\n *   NonSequencedConnClass::Service_Receive_Queue -- services recieve queue*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/***************************************************************************\n * NonSequencedConnClass::NonSequencedConnClass -- class constructor       *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t\tdesired # of entries for the send queue\t\t\t\t\t*\n *\t\tnumreceive\t\tdesired # of entries for the recieve queue\t\t\t\t*\n *\t\tmaxlen\t\t\tmax length of an application packet\t\t\t\t\t\t\t*\n *\t\tmagicnum\t\t\tthe packet \"magic number\" for this connection\t\t\t*\n *\t\tretry_delta\t\tthe time to wait between sends\t\t\t\t\t\t\t\t*\n *\t\tmax_retries\t\tthe max # of retries allowed for a packet\t\t\t\t\t*\n *\t\t\t\t\t\t\t(-1 means retry forever, based on this parameter)\t\t*\n *\t\ttimeout\t\t\tthe max amount of time before we give up on a packet\t*\n *\t\t\t\t\t\t\t(-1 means retry forever, based on this parameter)\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nNonSequencedConnClass::NonSequencedConnClass (int numsend, int numreceive, \n\tint maxlen, unsigned short magicnum, unsigned long retry_delta,\n\tunsigned long max_retries, unsigned long timeout) :\n\tConnectionClass (maxlen, magicnum, retry_delta, max_retries, timeout)\n{\n\t/*------------------------------------------------------------------------\n\tAllocate the packet Queue.  This will store incoming packets (which will\n\tbe placed there by the Connection Manager), and outgoing packets (which\n\tare placed there by this class when it \"sends\" a packet).\n\t------------------------------------------------------------------------*/\n\tQueue = new CommBufferClass (numsend, numreceive, MaxPacketLen);\n}\n\n\n/***************************************************************************\n * NonSequencedConnClass::~NonSequencedConnClass -- class destructor       *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nNonSequencedConnClass::~NonSequencedConnClass ()\n{\n\tdelete Queue;\n}\n\n\n/***************************************************************************\n * NonSequencedConnClass::Init -- Initializes connection queue to empty\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid NonSequencedConnClass::Init (void)\n{\n\tNumRecNoAck = 0;\n\tNumRecAck = 0;\n\tNumSendNoAck = 0;\n\tNumSendAck = 0;\n\n\tLastSeqID = 0xffffffff;\n\tLastReadID = 0xffffffff;\n\n\tQueue->Init();\n}\n\n\n/***************************************************************************\n * NonSequencedConnClass::Send_Packet -- adds a packet to the send queue\t*\n *                                                                         *\n * This routine prefixes the given buffer with a CommHeaderType and\t\t\t*\n * queues the resulting packet into the Send Queue.  (It's actually the\t\t*\n * Service() routine that handles the hardware-dependent Send of the data).*\n * The packet's MagicNumber, Code, and PacketID are set here.\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tack_req\t\ttrue = ACK is required for this packet; false = isn't\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was queue'd OK, 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NonSequencedConnClass::Send_Packet (void * buf, int buflen, int ack_req)\n{\n\t/*........................................................................\n\tSet the magic # for the packet\n\t........................................................................*/\n\t((CommHeaderType *)PacketBuf)->MagicNumber = MagicNum;\n\n\t/*........................................................................\n\tSet the packet Code: DATA_ACK if it requires an ACK, NOACK if it doesn't\n\tSet the packet ID to the appropriate counter value.\n\t........................................................................*/\n\tif (ack_req) {\n\t\t((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_ACK;\n\t\t((CommHeaderType *)PacketBuf)->PacketID = NumSendAck;\n\t} else {\n\t\t((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_NOACK;\n\t\t((CommHeaderType *)PacketBuf)->PacketID = NumSendNoAck;\n\t}\n\n\t/*........................................................................\n\tNow build the packet\n\t........................................................................*/\n\tmemcpy(PacketBuf + sizeof(CommHeaderType), buf, buflen);\n\n\t/*........................................................................\n\tAdd it to the queue.\n\t........................................................................*/\n\tif (Queue->Queue_Send(PacketBuf,buflen + sizeof(CommHeaderType))) {\n\t\tif (ack_req) {\n// Smart_Printf( \"Packet ack Queued ID %d \\n\", ((CommHeaderType *)PacketBuf)->PacketID );\n\t\t\tNumSendAck++;\n\t\t} else {\n// Smart_Printf( \"Packet noack Queued ID %d \\n\", ((CommHeaderType *)PacketBuf)->PacketID );\n\t\t\tNumSendNoAck++;\n\t\t}\n\t\treturn(true);\n\t} else {\n// Smart_Printf( \"Packet not Queued ID %d \\n\", ((CommHeaderType *)PacketBuf)->PacketID );\n\t\treturn(false);\n\t}\n}\n\n\n/***************************************************************************\n * NonSequencedConnClass::Receive_Packet -- adds packet to the receive queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tbuffer to process (already includes CommHeaderType)\t\t\t*\n *\t\tbuflen\tlength of buffer to process\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was processed OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NonSequencedConnClass::Receive_Packet (void * buf, int buflen)\n{\n\tCommHeaderType *packet;\t\t\t\t\t\t\t\t// ptr to packet header\n\tSendQueueType *send_entry;\t\t\t\t\t\t\t// ptr to send entry header\n\tReceiveQueueType *rec_entry;\t\t\t\t\t\t// ptr to recv entry header\n\tCommHeaderType *entry_data;\t\t\t\t\t\t// ptr to queue entry data\n\tCommHeaderType ackpacket;\t\t\t\t\t\t\t// ACK packet to send\n\tint i;\n\tint save_packet = 1;\t\t\t\t\t\t\t\t\t// 0 = this is a resend\n\tint found;\n\n\t/*\n\t--------------------------- Check the magic # ----------------------------\n\t*/\n\tpacket = (CommHeaderType *)buf;\n\tif (packet->MagicNumber != MagicNum) {\n// Smart_Printf( \"Bad Magic Number\\n\" );\n\t\treturn(false);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tHandle an incoming ACK\n\t------------------------------------------------------------------------*/\n\tif (packet->Code == PACKET_ACK) {\n\n\t\tfor (i = 0; i < Queue->Num_Send(); i++) {\n\t\t\t/*\n\t\t\t....................... Get queue entry ptr ........................\n\t\t\t*/\n\t\t\tsend_entry = Queue->Get_Send(i);\n\t\t\t/*\n\t\t\t............... If ptr is valid, get ptr to its data ...............\n\t\t\t*/\n\t\t\tif (send_entry != NULL) {\n\t\t\t\tentry_data = (CommHeaderType *)send_entry->Buffer;\n\t\t\t\t/*\n\t\t\t\t.............. If ACK is for this entry, mark it ................\n\t\t\t\t*/\n\t\t\t\tif (packet->PacketID==entry_data->PacketID && \n\t\t\t\t\tentry_data->Code == PACKET_DATA_ACK) {\n// Smart_Printf( \"Received ACK for %d \\n\", packet->PacketID );\n\t\t\t\t\tsend_entry->IsACK = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n//{\n//\t\tif (i == Queue->Num_Send() ) {\n// Smart_Printf( \"Received bad ACK for %d \\n\", packet->PacketID );\n//\t\t}\n//}\n\n\t\treturn(true);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tHandle an incoming PACKET_DATA_NOACK packet\n\t------------------------------------------------------------------------*/\n\telse if (packet->Code == PACKET_DATA_NOACK) {\n\t\t/*---------------------------------------------------------------------\n\t\tIf there's only one slot left, don't tie up the queue with this packet\n\t\t---------------------------------------------------------------------*/\n\t\tif (Queue->Max_Receive() - Queue->Num_Receive() <= 1) {\n// Smart_Printf( \"Only one slot left don't tie up with DATA NOACK packet %d \\n\", packet->PacketID );\n\t\t\t\treturn(false);\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tError if we can't queue the packet\n\t\t---------------------------------------------------------------------*/\n\t\tif (!Queue->Queue_Receive (buf, buflen)) {\n// Smart_Printf( \"Can't Queue the packet %d \\n\", packet->PacketID );\n\t\t\treturn(false);\n\t\t}\n\n// Smart_Printf( \"Queued DATA NOACK for %d \\n\", packet->PacketID );\n\t\tNumRecNoAck++;\n\n\t\treturn(true);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tHandle an incoming PACKET_DATA_ACK packet\n\t------------------------------------------------------------------------*/\n\telse if (packet->Code == PACKET_DATA_ACK) {\n// Smart_Printf( \"Looking at ID %d, LastSeqID=%d \\n\", packet->PacketID, LastSeqID );\n\t\t/*....................................................................\n\t\tIf this is a packet requires an ACK, and it's ID is older than our\n\t\t\"oldest\" ID, we know it's a resend; send an ACK, but don't queue it\n\t\t....................................................................*/\n\t\tif (packet->PacketID <= LastSeqID && LastSeqID != 0xffffffff) {\n// Smart_Printf( \"Older than oldest\\n\" );\n\t\t\tsave_packet = 0;\n\t\t}\n\t\t/*....................................................................\n\t\tOtherwise, scan the queue for this entry; if it's found, it's a\n\t\tresend, so don't save it.\n\t\t....................................................................*/\n\t\telse {\n\t\t\tsave_packet = 1;\n\t\t\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\t\t\t\trec_entry = Queue->Get_Receive(i);\n\t\t\t\tif (rec_entry) {\n\t\t\t\t\tentry_data = (CommHeaderType *)rec_entry->Buffer;\n\t\t\t\t\t/*...........................................................\n\t\t\t\t\tPacket is found; it's a resend\n\t\t\t\t\t...........................................................*/\n\t\t\t\t\tif (entry_data->Code == PACKET_DATA_ACK &&\n\t\t\t\t\t\tentry_data->PacketID == packet->PacketID) {\n// Smart_Printf( \"It's a resend\\n\" );\n\t\t\t\t\t\tsave_packet = 0;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\t/* end of scan for resend */\n\n\t\t/*---------------------------------------------------------------------\n\t\tQueue the packet & update our LastSeqID value.\n\t\t---------------------------------------------------------------------*/\n\t\tif (save_packet) {\n\t\t\t/*------------------------------------------------------------------\n\t\t\tIf there's only one slot left, make sure we only put a packet in it if\n\t\t\tthis packet will let us increment our LastSeqID; otherwise, we'll get\n\t\t\tstuck, forever unable to increment LastSeqID.\n\t\t\t------------------------------------------------------------------*/\n\t\t\tif (Queue->Max_Receive() - Queue->Num_Receive() <= 1) {\n\t\t\t\tif (packet->PacketID != (LastSeqID + 1) ) {\n// Smart_Printf( \"One slot left not what we looking for max=%d,num=%d \\n\",\n//\tQueue->Max_Receive(), Queue->Num_Receive() );\n\t\t\t\t\treturn(0);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tIf we can't queue the packet, return; don't send an ACK.\n\t\t\t------------------------------------------------------------------*/\n\t\t\tif (!Queue->Queue_Receive (buf, buflen)) {\n// Smart_Printf( \"unable to queue packet\\n\" );\n\t\t\t\treturn(0);\n\t\t\t}\n\n\t\t\tNumRecAck++;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUpdate our LastSeqID value if we can.  Anything less than LastSeqID\n\t\t\twe'll know is a resend.\n\t\t\t------------------------------------------------------------------*/\n\t\t\tif (packet->PacketID == (LastSeqID + 1)) {\n\t\t\t\tLastSeqID = packet->PacketID;\n\t\t\t\t/*............................................................\n\t\t\t\tNow that we have a new 'LastSeqID', search our Queue to see if\n\t\t\t\tthe next ID is there; if so, keep checking for the next one;\n\t\t\t\tbreak only when the next one isn't found.  This forces \n\t\t\t\tLastSeqID to be the largest possible value.\n\t\t\t\t............................................................*/\n\t\t\t\tdo {\n\t\t\t\t\tfound = 0;\n\t\t\t\t\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\n\t\t\t\t\t\trec_entry = Queue->Get_Receive(i);\n\n\t\t\t\t\t\tif (rec_entry) {\n\t\t\t\t\t\t\tentry_data = (CommHeaderType *)rec_entry->Buffer;\n\n\t\t\t\t\t\t\t/*......................................................\n\t\t\t\t\t\t\tEntry is found\n\t\t\t\t\t\t\t......................................................*/\n\t\t\t\t\t\t\tif (entry_data->Code == PACKET_DATA_ACK &&\n\t\t\t\t\t\t\t\tentry_data->PacketID == (LastSeqID + 1)) {\n\n\t\t\t\t\t\t\t\tLastSeqID = entry_data->PacketID;\n\t\t\t\t\t\t\t\tfound = 1;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} while (found);\n\t\t\t}\n\t\t}\t/* end of save packet */\n\n\t\t/*---------------------------------------------------------------------\n\t\tSend an ACK, regardless of whether this was a resend or not.\n\t\t---------------------------------------------------------------------*/\n\t\tackpacket.MagicNumber = Magic_Num();\n\t\tackpacket.Code = PACKET_ACK;\n\t\tackpacket.PacketID = packet->PacketID;\n// Smart_Printf( \"Sending ACK for %d \\n\", packet->PacketID );\n\t\tSend ((char *)&ackpacket, sizeof(CommHeaderType));\n\n\t\treturn(true);\n\n\t} else {\n// Smart_Printf( \"invalid packet type %d \\n\", packet->Code );\n\t}\n\n\treturn(false);\n}\n\n\n/***************************************************************************\n * NonSequencedConnClass::Get_Packet -- gets a packet from receive queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tlocation to store buffer\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\tfilled in with length of 'buf'\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was read, 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NonSequencedConnClass::Get_Packet (void * buf, int *buflen)\n{\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\tint packetlen;\t\t\t\t\t\t\t\t\t\t// size of received packet\n\tCommHeaderType *entry_data;\n\tint i;\n\n\t/*------------------------------------------------------------------------\n\tEnsure that we read the packets in order.  LastReadID is the ID of the\n\tlast PACKET_DATA_ACK packet we read.\n\t------------------------------------------------------------------------*/\n\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\n\t\trec_entry = Queue->Get_Receive(i);\n\n\t\t/*.....................................................................\n\t\tOnly read this entry if it hasn't been yet\n\t\t.....................................................................*/\n\t\tif (rec_entry && rec_entry->IsRead==0) {\n\n\t\t\tentry_data = (CommHeaderType *)rec_entry->Buffer;\n\n\t\t\t/*..................................................................\n\t\t\tIf this is a DATA_ACK packet, its ID must be one greater than\n\t\t\tthe last one we read.\n\t\t\t..................................................................*/\n\t\t\tif ( (entry_data->Code == PACKET_DATA_ACK) &&\n\t\t\t\t(entry_data->PacketID == (LastReadID + 1))) {\n\n\t\t\t\tLastReadID = entry_data->PacketID;\n\t\t\t\trec_entry->IsRead = 1;\n\n\t\t\t\tpacketlen = rec_entry->BufLen - sizeof(CommHeaderType);\n\t\t\t\tif (packetlen > 0) {\n\t\t\t\t\tmemcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType), packetlen);\n\t\t\t\t}\n\t\t\t\t(*buflen) = packetlen;\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t\t/*..................................................................\n\t\t\tIf this is a DATA_NOACK packet, who cares what the ID is?\n\t\t\t..................................................................*/\n\t\t\telse if (entry_data->Code == PACKET_DATA_NOACK) {\n\n\t\t\t\trec_entry->IsRead = 1;\n\n\t\t\t\tpacketlen = rec_entry->BufLen - sizeof(CommHeaderType);\n\t\t\t\tif (packetlen > 0) {\n\t\t\t\t\tmemcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType), packetlen);\n\t\t\t\t}\n\t\t\t\t(*buflen) = packetlen;\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(false);\n}\n\n\n/***************************************************************************\n * NonSequencedConnClass::Service_Send_Queue -- services the send queue\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NonSequencedConnClass::Service_Send_Queue (void)\n{\n\tint i;\n\tint num_entries;\n\tSendQueueType *send_entry;\t\t\t\t\t\t// ptr to send queue entry\n\tCommHeaderType *packet_hdr;\t\t\t\t\t// packet header\n\tunsigned long curtime;\t\t\t\t\t\t\t// current time\n\tint bad_conn = 0;\n\n\t/*------------------------------------------------------------------------\n\tRemove any ACK'd packets from the queue\n\t------------------------------------------------------------------------*/\n\tfor (i = 0; i < Queue->Num_Send(); i++) {\n\t\t/*\n\t\t------------------------- Get this queue entry ------------------------\n\t\t*/\n\t\tsend_entry = Queue->Get_Send(i);\n\t\t/*\n\t\t---------------- If ACK has been received, unqueue it -----------------\n\t\t*/\n\t\tif (send_entry->IsACK) {\n\t\t\t/*\n\t\t\t................ Update this queue's response time .................\n\t\t\t*/\n\t\t\tpacket_hdr = (CommHeaderType *)send_entry->Buffer;\n\t\t\tif (packet_hdr->Code == PACKET_DATA_ACK) {\n\t\t\t\tQueue->Add_Delay(Time() - send_entry->FirstTime);\n\t\t\t}\n\t\t\t/*\n\t\t\t....................... unqueue the packet .........................\n\t\t\t*/\n\t\t\tQueue->UnQueue_Send(NULL,NULL,i);\n\t\t\ti--;\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tLoop through all entries in the Send queue.  [Re]Send any entries that\n\tneed it.\n\t------------------------------------------------------------------------*/\n\tnum_entries = Queue->Num_Send();\n\n\tfor (i = 0; i < num_entries; i++) {\n\t\tsend_entry = Queue->Get_Send(i);\n\n\t\tif (send_entry->IsACK) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*.....................................................................\n\t\tOnly send the message if time has elapsed.  (The message's Time\n\t\tfields are init'd to 0 when a message is queue'd or unqueue'd, so the\n\t\tfirst time through, the delta time will appear large.)\n\t\t.....................................................................*/\n\t\tcurtime = Time();\n\t\tif (curtime - send_entry->LastTime > RetryDelta) {\n\t\t\t/*\n\t\t\t......................... Send the message .........................\n\t\t\t*/\n#if(0)\n{\n\t\t\tpacket_hdr = (CommHeaderType *)send_entry->Buffer;\n\t\t\tif (send_entry->SendCount) {\n\t\t\t\tif (packet_hdr->Code == PACKET_DATA_NOACK) {\n// Smart_Printf( \"Resending DATA NOACK for %d \\n\", packet_hdr->PacketID );\n\t\t\t\t} else {\n\t\t\t\t\tif (packet_hdr->Code == PACKET_DATA_ACK) {\n// Smart_Printf( \"Resending DATA ACK for %d \\n\", packet_hdr->PacketID );\n\t\t\t\t\t}\n\t\t\t\t} \n\t\t\t} else {\n\t\t\t\tif (packet_hdr->Code == PACKET_DATA_NOACK) {\n// Smart_Printf( \"Sending DATA NOACK for %d \\n\", packet_hdr->PacketID );\n\t\t\t\t} else {\n\t\t\t\t\tif (packet_hdr->Code == PACKET_DATA_ACK) {\n// Smart_Printf( \"Sending DATA ACK for %d \\n\", packet_hdr->PacketID );\n\t\t\t\t\t}\n\t\t\t\t} \n\t\t\t}\n}\n#endif\n\t\t\tSend (send_entry->Buffer, send_entry->BufLen);\n\n\t\t\t/*\n\t\t\t....................... Fill in Time fields ........................\n\t\t\t*/\n\t\t\tsend_entry->LastTime = curtime;\n\t\t\tif (send_entry->SendCount==0) {\n\t\t\t\tsend_entry->FirstTime = curtime;\n\t\t\t\t/*...............................................................\n\t\t\t\tIf this is the 1st time we're sending this packet, and it doesn't\n\t\t\t\trequire an ACK, mark it as ACK'd; then, the next time through,\n\t\t\t\tit will just be removed from the queue.\n\t\t\t\t...............................................................*/\n\t\t\t\tpacket_hdr = (CommHeaderType *)send_entry->Buffer;\n\t\t\t\tif (packet_hdr->Code == PACKET_DATA_NOACK) {\n\t\t\t\t\tsend_entry->IsACK = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\t/*\n\t\t\t......................... Update SendCount .........................\n\t\t\t*/\n\t\t\tsend_entry->SendCount++;\n\t\t\t/*..................................................................\n\t\t\tPerform error detection, based on either MaxRetries or Timeout\n\t\t\t..................................................................*/\n\t\t\tif (MaxRetries != -1 && send_entry->SendCount > MaxRetries) {\n// Smart_Printf( \"Max Retries!!! %d !!! \\n\", MaxRetries );\n\t\t\t\tbad_conn = 1;\n\t\t\t}\n\n\t\t\tif (Timeout != -1 &&\n\t\t\t\t(send_entry->LastTime - send_entry->FirstTime) > Timeout) {\n// Smart_Printf( \"Timed out!!! Time %d, Timeout %d, buflen %d !!! \\n\",\n//\t(send_entry->LastTime - send_entry->FirstTime), Timeout,\n//\tsend_entry->BufLen );\n\t\t\t\tbad_conn = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tIf the connection is going bad, return an error\n\t------------------------------------------------------------------------*/\n\tif (bad_conn) {\n// Smart_Printf( \"Connection going bad!!! \\n\" );\n\t\treturn(false);\n\t} else {\n\t\treturn(true);\n\t}\n}\n\n\n/***************************************************************************\n * NonSequencedConnClass::Service_Receive_Queue -- services recieve queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NonSequencedConnClass::Service_Receive_Queue (void)\n{\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\tCommHeaderType *packet_hdr;\t\t\t\t\t// packet header\n\tint i;\n\n\t/*------------------------------------------------------------------------\n\tRemove all dead packets.  \n\tPACKET_DATA_NOACK: if it's been read, throw it away.\n\tPACKET_DATA_ACK: if it's been read, and its ID is older than LastSeqID,\n\tthrow it away.\n\t------------------------------------------------------------------------*/\n\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\t\trec_entry = Queue->Get_Receive(i);\n\n\t\tif (rec_entry->IsRead) {\n\t\t\tpacket_hdr = (CommHeaderType *)(rec_entry->Buffer);\n\n\t\t\tif (packet_hdr->Code == PACKET_DATA_NOACK) {\n\t\t\t\tQueue->UnQueue_Receive(NULL,NULL,i);\n\t\t\t\ti--;\n\t\t\t} else {\n\t\t\t\tif (packet_hdr->PacketID < LastSeqID) {\n\t\t\t\t\tQueue->UnQueue_Receive(NULL,NULL,i);\n\t\t\t\t\ti--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(true);\n}\n\n\n"
  },
  {
    "path": "CODE/NOSEQCON.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\noseqcon.h_v   1.13   01 Mar 1996 17:32:42   JOE_BOSTIC  $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : NOSEQCON.H                               *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 9, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This class provides a \"Non-Sequenced\" ACK/Retry approach to packet\t\t*\n * transmission.  It sends out as many packets as are in the queue, whose\t*\n * resend delta times have expired; and it ACK's any packets its received\t*\n * who haven't been ACK'd yet.  Thus, order of delivery is NOT guaranteed;\t*\n * however, the performance is better than the Sequenced approach.\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tA derived class must provide:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Init: Initialization of any hardware-specific values.\t\t\t\t\t\t*\n * - Send: a hardware-dependent send routine.\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef NONSEQCONN_H\n#define NONSEQCONN_H\n\n\n/*\n********************************* Includes **********************************\n*/\n#include \"connect.h\"\n#include \"combuf.h\"\n\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass NonSequencedConnClass : public ConnectionClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*.....................................................................\n\t\tConstructor/destructor.\n\t\t.....................................................................*/\n\t\tNonSequencedConnClass (int numsend, int numrecieve, int maxlen, \n\t\t\tunsigned short magicnum, unsigned long retry_delta,\n\t\t\tunsigned long max_retries, unsigned long timeout);\n\t\tvirtual ~NonSequencedConnClass ();\n\n\t\t/*.....................................................................\n\t\tInitialization.\n\t\t.....................................................................*/\n\t\tvirtual void Init (void);\n\n\t\t/*.....................................................................\n\t\tSend/Receive routines.\n\t\t.....................................................................*/\n\t\tvirtual int Send_Packet (void * buf, int buflen, int ack_req);\n\t\tvirtual int Receive_Packet (void * buf, int buflen);\n\t\tvirtual int Get_Packet (void * buf, int *buflen);\n\n\t\t/*.....................................................................\n\t\tThe packet \"queue\"; this non-sequenced version isn't really much of\n\t\ta queue, but more of a repository.\n\t\t.....................................................................*/\n\t\tCommBufferClass *Queue;\n\n\t/*\n\t-------------------------- Protected Interface ---------------------------\n\t*/\n\tprotected:\n\t\t/*.....................................................................\n\t\tRoutines to service the Send & Receive queues.\n\t\t.....................................................................*/\n\t\tvirtual int Service_Send_Queue (void);\n\t\tvirtual int Service_Receive_Queue (void);\n\n\t\t/*.....................................................................\n\t\tRunning totals of # of packets we send & receive which require an ACK, \n\t\tand those that don't.\n\t\t.....................................................................*/\n\t\tunsigned long NumRecNoAck;\n\t\tunsigned long NumRecAck;\n\t\tunsigned long NumSendNoAck;\n\t\tunsigned long NumSendAck;\n\n\t\t/*.....................................................................\n\t\tThis is the ID of the last consecutively-received packet; anything older \n\t\tthan this, we know is a resend.  Anything newer than this MUST be lying \n\t\taround in the Queue for us to detect it as a resend.\n\t\t.....................................................................*/\n\t\tunsigned long LastSeqID;\n\n\t\t/*.....................................................................\n\t\tThis is the ID of the PACKET_DATA_ACK packet we read last; it ensures\n\t\tthat the application reads that type of packet in order.\n\t\t.....................................................................*/\n\t\tunsigned long LastReadID;\n};\n\n#endif\n\n\n"
  },
  {
    "path": "CODE/NULLCONN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/NULLCONN.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : NULLCONN.CPP                             *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : April 5, 1995\t\t                        *\n *                                                                         *\n *                  Last Update : April 20, 1995   [DRD]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:    \t\t\t                                                   *\n *   NullModemConnClass::NullModemConnClass -- class constructor           *\n *   NullModemConnClass::~NullModemConnClass -- class destructor           *\n *   NullModemConnClass::Init -- hardware-dependent initialization\t\t\t*\n *   NullModemConnClass::Send -- hardware-dependent packet sending\t\t\t*\n *   NullModemConnClass::Compute_CRC -- computes CRC for given buffer\t\t*\n *   NullModemConnClass::Packet_Overhead_Size -- number of extra bytes     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#ifdef WIN32\n#include \"wincomm.h\"\n#endif\t//WIN32\n#include <stdio.h>\n#include <mem.h>\n#include \"nullconn.h\"\n\n\n/***************************************************************************\n * NullModemConnClass::NullModemConnClass -- class constructor             *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t\tdesired # send queue entries\t\t\t\t\t\t\t\t\t*\n *\t\tnumreceive\t\tdesired # send receive entries\t\t\t\t\t\t\t\t*\n *\t\tmaxlen\t\t\tmax length of application's packets\t\t\t\t\t\t\t*\n *\t\tmagicnum\t\t\tapplication-defined magic # for the packets\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nNullModemConnClass::NullModemConnClass (int numsend, int numreceive,\n\tint maxlen, unsigned short magicnum) :\n\tConnectionClass (numsend, numreceive, maxlen, magicnum,\n\t\t60, \t\t\t// Retry Delta Time\n\t\t-1, \t\t\t// Max Retries (-1 means ignore this timeout parameter)\n\t\t1200)\t\t\t// Timeout: 20 seconds\n{\n\t/*------------------------------------------------------------------------\n\tPre-set the port value to NULL, so Send won't send until we've been Init'd\n\t------------------------------------------------------------------------*/\n#ifdef WIN32\n\tPortHandle = NULL;\n#else\t//WIN32\n\tPort = NULL;\n#endif\t//WIN32\n\t/*------------------------------------------------------------------------\n\tAllocate the Send Buffer; the parent constructor has set MaxPacketLen,\n\tso we can use it in our computation.\n\t------------------------------------------------------------------------*/\n\tSendBuf = new char [ Actual_Max_Packet() ];\n\n}\t/* end of NullModemConnClass */\n\n\n/***************************************************************************\n * NullModemConnClass::~NullModemConnClass -- class destructor             *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nNullModemConnClass::~NullModemConnClass ()\n{\n\tdelete [] SendBuf;\n\n}\t/* end of ~NullModemConnClass */\n\n\n/***************************************************************************\n * NullModemConnClass::Init -- hardware-dependent initialization\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tport\t\tGreenLeaf port handle\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifdef WIN32\nvoid NullModemConnClass::Init (HANDLE port_handle)\n{\n\tConnectionClass::Init();\n\tPortHandle = port_handle;\n}\n#else\t//WIN32\nvoid NullModemConnClass::Init (PORT *port)\n{\n\tConnectionClass::Init();\n\tPort = port;\n}\t/* end of Init */\n#endif\t//WIN32\n\n/***************************************************************************\n * NullModemConnClass::Send -- hardware-dependent packet sending\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer to send\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textrabuf\t\t(not used by this class)\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textralen\t\t(not used by this class)\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NullModemConnClass::Send (char *buf, int buflen, void *, int )\n{\n\tint *ibuf;\n\tSerialHeaderType *header;\n\tunsigned long sendlen;\n\n\t/*------------------------------------------------------------------------\n\tError if we haven't been properly initialized\n\t------------------------------------------------------------------------*/\n#ifdef WIN32\n\tif ( PortHandle == NULL ) return(false);\n\n#else\t//WIN32\n\tint status;\n\tif ( Port == NULL ) {\n\t\treturn(0);\n\t}\n#endif\t//WIN32\n\n\t/*------------------------------------------------------------------------\n\tPackage the data into the Send Buffer\n\t------------------------------------------------------------------------*/\n\theader = (SerialHeaderType *) SendBuf;\n\theader->MagicNumber\t= PACKET_SERIAL_START;\n\theader->Length\t\t\t= (short) buflen;\n\theader->MagicNumber2\t= PACKET_SERIAL_VERIFY;\n\n\tsendlen = sizeof( SerialHeaderType );\n\tmemcpy (SendBuf + sendlen, buf, buflen);\n\tsendlen += buflen;\n\tibuf = (int *)(SendBuf + sendlen);\n\t*ibuf = Compute_CRC( buf, buflen );\n\tsendlen += sizeof( int );\n\n\t*(SendBuf + sendlen) = '\\r';\n\tsendlen += 1;\n\n\t/*------------------------------------------------------------------------\n\tSend the data\n\t------------------------------------------------------------------------*/\n#ifdef WIN32\n\t\tSerialPort->Write_To_Serial_Port((unsigned char *)SendBuf, (int)sendlen );\n\t\treturn (true);\n\n#else\t//WIN32\n\tstatus = WriteBuffer( Port, SendBuf, sendlen );\n\tif ( status == ASSUCCESS ) {\n\t\treturn(1);\n\t}\n\telse {\n\t\treturn(0);\n\t}\n#endif\t//WIN32\n\n}\t/* end of Send */\n\n\n/***************************************************************************\n * NullModemConnClass::Compute_CRC -- computes CRC for given buffer\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tbuffer to compute CRC for\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\tlength of buffer in bytes\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NullModemConnClass::Compute_CRC (char *buf, int buflen)\n{\n\tunsigned int sum, hibit;\n\n\tsum = 0;\n\tfor (int i = 0; i < buflen; i++) {\n\t\tif ( sum & 0x80000000 ) {\t\t// check hi bit to rotate into low bit\n\t\t\thibit = 1;\n\t\t}\n\t\telse {\n\t\t\thibit = 0;\n\t\t}\n\n\t\tsum <<= 1;\n\t\tsum += (hibit + (unsigned char)buf[i]);\n\t}\n\n\treturn((int)sum);\n\n}\t/* end of Compute_CRC */\n\n\n/***************************************************************************\n * NullModemConnClass::Packet_Overhead_Size -- number of extra bytes       *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnumber of bytes used for communications only.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/20/1995 DRD : Created.                                             *\n *=========================================================================*/\nint NullModemConnClass::Packet_Overhead_Size ( void )\n{\n\t/*------------------------------------------------------------------------\n\tshort for Null Modem Magic Number\n\tshort for Null Modem length of packet\n\tint for Null Modem CRC check\n\tCommHeaderType for Queued packets\n\t------------------------------------------------------------------------*/\n\treturn( (PACKET_SERIAL_OVERHEAD_SIZE + sizeof(CommHeaderType)) );\n\n}\t/* end of Packet_Overhead_Size */\n\n/************************** end of nullconn.cpp ****************************/\n"
  },
  {
    "path": "CODE/NULLCONN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/NULLCONN.H 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : NULLCONN.H                               *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 3, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This is the Connection Class for a NULL-Modem connection.  It inherits\t*\n * a Queue, PacketBuf, timeout variables from ConnectionClass.  It \t\t\t*\n * inherits its Send_/Receive_/Get_Packet functions, and the non-sequenced\t*\n * ACK/Retry logic in Service_Send_Queue & Service_Receive_Queue from\t\t*\n * ConnectionClass.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef NULLCONN_H\n#define NULLCONN_H\n\n\n/*\n********************************* Includes **********************************\n*/\n#include \"connect.h\"\n#include \"commlib.h\"\n\n/*\n********************************** Defines **********************************\n*/\n#define\tPACKET_SERIAL_START\t\t\t\t0xDABD\n#define\tPACKET_SERIAL_VERIFY\t\t\t\t0xDEAF\n\n#define\tPACKET_SERIAL_OVERHEAD_SIZE\t(sizeof( SerialHeaderType ) + sizeof( SerialCRCType ))\n\ntypedef struct {\n\tunsigned short MagicNumber;\n\tunsigned short Length;\n\tunsigned short MagicNumber2;\n} SerialHeaderType;\n\ntypedef struct {\n\tint SerialCRC;\n} SerialCRCType;\n\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass NullModemConnClass : public ConnectionClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*.....................................................................\n\t\tConstructor/destructor.\n\t\t.....................................................................*/\n\t\tNullModemConnClass (int numsend, int numrecieve, int maxlen,\n\t\t\tunsigned short magicnum);\n\t\tvirtual ~NullModemConnClass ();\n\n\t\t/*.....................................................................\n\t\tInitialization.\n\t\t.....................................................................*/\n#ifdef WIN32\n\t\tvoid Init (HANDLE port_handle);\n#else\t//WIN32\n\t\tvoid Init (PORT *port);\n#endif\t//WIN32\n\n\t\t/*.....................................................................\n\t\tUtility routines.\n\t\t.....................................................................*/\n\t\tunsigned long Actual_Max_Packet (void) { return (MaxPacketLen +\n\t\t\t(sizeof(SerialHeaderType)) + sizeof(int) + sizeof (char)); }\n\n\t\t/*.....................................................................\n\t\tThis routine computes a CRC value for the given buffer.\n\t\t.....................................................................*/\n\t\tstatic int Compute_CRC(char *buf, int buflen);\n\n\t\t/*.....................................................................\n\t\tThis routine returns the number of bytes extra added the packet\n\t\tfor communication.\n\t\t.....................................................................*/\n\t\tstatic int Packet_Overhead_Size( void );\n\n\t/*\n\t--------------------------- Private Interface ----------------------------\n\t*/\n\tprotected:\n\t\t/*.....................................................................\n\t\tThis routine actually performs a hardware-dependent data send.\n\t\t.....................................................................*/\n\t\tvirtual int Send (char *buf, int buflen, void *extrabuf, int extralen);\n#ifdef WIN32\n\t\t/*\n\t\t** This is the winsoze port handle\n\t\t*/\n\t\tHANDLE PortHandle;\n#else\t//WIN32\n\t\t/*.....................................................................\n\t\tThis is the PORT value used by the GreenLeaf calls.\n\t\t.....................................................................*/\n\t\tPORT *Port;\n#endif\t//WIN32\n\n\t\t/*.....................................................................\n\t\tThis buffer is a staging area for data sent out; it includes the\n\t\tpacket sent by the parent class (which includes the application's\n\t\tpacket, plus the CommHeaderType header), plus:\n\t\t- 2-byte buffer start ID\n\t\t- 2-byte length\n\t\t- 4-byte CRC value (at the end of the buffer)\n\t\tThis is the actual packet that gets sent across the serial line.\n\t\t.....................................................................*/\n\t\tchar *SendBuf;\n};\n\n#endif\n\n/************************** end of nullconn.h ******************************/\n\n"
  },
  {
    "path": "CODE/NULLDLG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /counterstrike/NULLDLG.CPP 14    3/17/97 1:05a Steve_tall $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : NULLDLG.CPP                              *\n *                                                                         *\n *                   Programmer : Bill R. Randolph                         *\n *                                                                         *\n *                   Start Date : 04/29/95                                 *\n *                                                                         *\n *                  Last Update : Jan. 21, 1997 [V.Grippi]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Build_InitString_Listbox -- [re]builds the initstring entry listbox   *\n *   Build_Phone_Listbox -- [re]builds the phone entry listbox             *\n *   Com_Scenario_Dialog -- Serial game scenario selection dialog\t\t\t\t*\n *   Com_Settings_Dialog -- Lets user select serial port settings          *\n *   Destroy_Null_Connection -- destroys the given connection\t\t\t\t\t*\n *   Edit_Phone_Dialog -- lets user edit a phone book entry                *\n *   Init_Null_Modem -- Initializes Null Modem communications              *\n *   Init_String_Compare -- for qsort\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Phone_Compare -- for qsort\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Phone_Dialog -- Lets user edit phone directory & dial                 *\n *   Reconnect_Null_Modem -- allows user to reconnect\t\t\t\t\t\t\t\t*\n *   Select_Serial_Dialog -- Serial Communications menu dialog             *\n *   Shutdown_Modem -- Shuts down modem/null-modem communications          *\n *   Test_Null_Modem -- Null-Modem test routine                            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#ifdef FIXIT_RANDOM_GAME\n#include \"time.h\"\n#endif\n#ifdef WIN32\n#include \"wincomm.h\"\n#include \"modemreg.h\"\nModemRegistryEntryClass *ModemRegistry = NULL;\t\t//Ptr to modem registry data\n#endif\t//WIN32\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern bool Is_Mission_126x126 (char *file_name);\nextern bool Is_Mission_Counterstrike (char *file_name);\nextern bool Is_Mission_Aftermath( char* file_name );\n#endif\n\n//#include \"WolDebug.h\"\n\n//\n// how much time (ticks) to go by before thinking other system\n// is not responding.\n//\n#define PACKET_SENDING_TIMEOUT\t1800\n#define PACKET_CANCEL_TIMEOUT\t\t900\n\n//extern char const *ForMisStr[];\nextern char const *EngMisStr[];\n\n\n//\n// how much time (ticks) to go by before sending another packet\n// of game options or serial connect.\n//\n#define PACKET_RETRANS_TIME\t30\n#define PACKET_REDRAW_TIME\t\t60\n\nstatic int Reconnect_Null_Modem( void );\nstatic int Com_Settings_Dialog( SerialSettingsType *settings );\nstatic int Phone_Dialog (void);\nstatic void Build_Init_String_Listbox (ListClass *list, EditClass *edit, char *buf, int *index);\nstatic int Init_String_Compare (const void *p1, const void *p2);\nstatic void Build_Phone_Listbox (ListClass *list, EditClass *edit, char *buf);\nstatic int Phone_Compare (const void *p1, const void *p2);\nstatic int Edit_Phone_Dialog (PhoneEntryClass *phone);\nstatic bool Dial_Modem( SerialSettingsType *settings, bool reconnect );\nstatic bool Answer_Modem( SerialSettingsType *settings, bool reconnect );\nstatic void Modem_Echo( char c );\n\nvoid Smart_Printf( char *format, ... );\nvoid Hex_Dump_Data( char *buffer, int length );\nvoid itoh( int i, char *s);\n\n\nstatic SerialPacketType SendPacket;\nstatic SerialPacketType ReceivePacket;\nchar TheirName[MPLAYER_NAME_MAX];\nPlayerColorType TheirColor;\nHousesType TheirHouse;\nstatic char DialString[ CWAITSTRBUF_MAX + PhoneEntryClass::PHONE_MAX_NUM - 1 ];\nstatic SerialSettingsType *DialSettings;\n\n#ifdef FIXIT_VERSION_3\nbool Force_Scenario_Available( const char* szName );\nbool bSpecialAftermathScenario( const char* szScenarioDescription );\n#endif\n\n#define PCOLOR_BROWN\tPCOLOR_GREY\n\n\n#define SHOW_MONO\t0\n\n/***************************************************************************\n * Init_Null_Modem -- Initializes Null Modem communications                *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = OK, false = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t   *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *   8/2/96      ST : Win32 support added                                  *\n *=========================================================================*/\nint Init_Null_Modem( SerialSettingsType *settings )\n{\n\n#ifdef WIN32\n\tif ( NullModem.Init( settings->Port, settings->IRQ,\n\t\t\t\t\t\t\t\tsettings->ModemName,\n\t\t\t\t\t\t\t\tsettings->Baud, 0,  8, 1,\n\t\t\t\t\t\t\t\tsettings->HardwareFlowControl ) ) {\n\t\treturn (true);\n\t} else {\n\t\treturn (false);\n\t}\n\n#else\t//WIN32\n\tif ( NullModem.Init( settings->Port, settings->IRQ,\n\t\t\t\t\t\t\t\tsettings->ModemName,\n\t\t\t\t\t\t\t\tsettings->Baud, 'N',  8, 1,\n\t\t\t\t\t\t\t\tsettings->HardwareFlowControl) ) {\n\t\tNullModem.Change_IRQ_Priority( settings->IRQ );\n\n\t\treturn(true);\n\t} else {\n\t\treturn(false);\n\t}\n#endif\t//WIN32\n}\n\n\n/***************************************************************************\n * Shutdown_Modem -- Shuts down modem/null-modem communications            *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid Shutdown_Modem( void )\n{\n\tif (!Session.Play) {\n\t\tif (Session.Type == GAME_MODEM) {\n\t\t\tNullModem.Hangup_Modem();\n\t\t}\n\t}\n\n\tNullModem.Change_IRQ_Priority( 0 );\t\t// reset priority of interrupts\n\n\t//\n\t// close port\n\t//\n\tNullModem.Shutdown();\n}\n\n\n/***************************************************************************\n * Modem_Signoff -- sends EXIT event\t\t\t\t\t\t\t\t\t\t         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   08/03/1995 DRD : Created.                                             *\n *=========================================================================*/\nvoid Modem_Signoff( void )\n{\n\tunsigned long starttime;\n\tEventClass event;\n\n\tif (!Session.Play) {\n\t\t/*\n\t\t** Send a sign-off packet\n\t\t*/\n\t\tmemset (&event, 0, sizeof(EventClass));\n\t\tevent.Type = EventClass::EXIT;\n\t\tNullModem.Send_Message (&event,sizeof(EventClass),0);\n\t\tNullModem.Send_Message (&event,sizeof(EventClass),0);\n\n\t\tstarttime = TickCount;\n\t\twhile ( (TickCount - starttime) < 30) {\n\t\t\tNullModem.Service();\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * Test_Null_Modem -- Null-Modem test routine                              *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = failure to connect; 1 = I'm the game owner, 2 = I'm not        *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *   8/2/96      ST : Win32 support added                                  *\n *=========================================================================*/\nint Test_Null_Modem( void )\n{\n\t/*\n\t** Get the resolution factor\n\t*/\n//\tint factor\t\t\t= (SeenBuff.Get_Width() == 320) ? 1 : 2;\n\n\t/*\n\t** Button Enumerations\n\t*/\n\tenum {\n\t\tBUTTON_CANCEL = 100,\n\t};\n\n\t/*\n\t** Dialog variables\n\t*/\n\tbool process = true;\t\t\t\t\t\t// process while true\n\n\tint retval;\n\tunsigned long starttime;\n\tint packetlen;\n\n\tint x,y,width,height;\t\t\t\t\t// dialog dimensions\n\tchar buffer[80*3];\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t** Buttons\n\t*/\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\t/*\n\t**\tDetermine the dimensions of the text to be used for the dialog box.\n\t**\tThese dimensions will control how the dialog box looks.\n\t*/\n\tstrcpy( buffer, Text_String( TXT_WAITING_CONNECT ) );\n\tFancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);\n\tFormat_Window_String(buffer, SeenBuff.Get_Height(), width, height);\n\n\twidth = max(width, 50 * RESFACTOR);\n\twidth += 40 * RESFACTOR;\n\theight += 60 * RESFACTOR;\n\n\tx = (SeenBuff.Get_Width() - width) / 2;\n\ty = (SeenBuff.Get_Height() - height) / 2;\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,\n\t\tx + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8 * RESFACTOR)) >> 1),\n\t\ty + height - (FontHeight + FontYSpacing + 2 * RESFACTOR) - 10 * RESFACTOR);\n\n\t/*\n\t** Initialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\tprocess = true;\n\n\t/*\n\t** Create the list\n\t*/\n\tcommands = &cancelbtn;\n\n\tcommands->Flag_List_To_Redraw();\n\n\t/*\n\t** Draw the dialog\n\t*/\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n\n\tDialog_Box(x, y, width, height);\n\tDraw_Caption(TXT_NONE, x, y, width);\n\n\tFancy_Text_Print(buffer, x + 20 * RESFACTOR, y + 25 * RESFACTOR, scheme, TBLACK, TPF_TEXT);\n\n\tcommands->Draw_All();\n\twhile (Get_Mouse_State() > 0) Show_Mouse();\n\n#ifdef WIN32\n\t/*\n\t** This is supposed to be a direct connection so hang up any modem on this port\n\t** just to annoy British Telecom\n\t*/\n\t/*\n\t** Go into break mode\n\t*/\n\tSetCommBreak(SerialPort->Get_Port_Handle());\n\n\t/*\n\t** Send hangup command\n\t*/\n\tSerialPort->Write_To_Serial_Port ((unsigned char*)\"ATH\\r\", strlen(\"ATH\\r\"));\n\tCountDownTimerClass time;\n\ttime.Set(2*60);\n\twhile (time.Time()) {}\n\n\t/*\n\t** Back out of break mode\n\t*/\n\tClearCommBreak(SerialPort->Get_Port_Handle());\n\n\t/*\n\t** Drop DTR as well - just in case the modem still hasnt got the message\n\t*/\n\tEscapeCommFunction(SerialPort->Get_Port_Handle(), CLRDTR);\n#endif\t//WIN32\n\n\n\t/*\n\t** Check for a packet.  If we detect one, the other system has already been\n\t** started.  Wait 1/2 sec for him to receive my ACK, then exit with success.\n\t** Note: The initial time must be a little longer than the resend delay.\n\t** \tJust in case we just missed the packet.\n\t*/\n\tstarttime = TickCount;\n\twhile ( TickCount - starttime < 80) {\n\t\tNullModem.Service();\n\t\tif ( NullModem.Get_Message( &ReceivePacket, &packetlen ) > 0) {\n\t\t\tif (ReceivePacket.Command == SERIAL_CONNECT) {\n\t\t\t\tstarttime = TickCount;\n\t\t\t\twhile (TickCount - starttime < 30)\n\t\t\t\t\tNullModem.Service();\n\t\t\t\tprocess = false;\n\t\t\t\tretval = 2;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Send a packet across.  As long as Num_Send() is non-zero, the other system\n\t** hasn't received it yet.\n\t*/\n\tif (process) {\n\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\tSendPacket.Command = SERIAL_CONNECT;\n\t\t//\n\t\t// put time from start of game for determining the host in case of tie.\n\t\t//\n\t\tSendPacket.ScenarioInfo.Seed = TickCount;\n\t\tSendPacket.ID = (int) buffer;\t\t// address of buffer for more uniqueness.\n\n\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\n\t\tstarttime = TickCount;\n\t\twhile (TickCount - starttime < 80) {\n\t\t\tNullModem.Service();\n\t\t\tif (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) {\n\t\t\t\tif (ReceivePacket.Command == SERIAL_CONNECT) {\n\t\t\t\t\tstarttime = TickCount;\n\t\t\t\t\twhile (TickCount - starttime < 30)\n\t\t\t\t\t\tNullModem.Service();\n\n\t\t\t\t\t//\n\t\t\t\t\t// whoever has the highest time is the host\n\t\t\t\t\t//\n\t\t\t\t\tif (ReceivePacket.ScenarioInfo.Seed > SendPacket.ScenarioInfo.Seed) {\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tretval = 2;\n\t\t\t\t\t} else if (ReceivePacket.ScenarioInfo.Seed == SendPacket.ScenarioInfo.Seed) {\n\t\t\t\t\t\tif (ReceivePacket.ID > SendPacket.ID) {\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\tretval = 2;\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// if they are equal then it's a loopback cable or a modem\n\t\t\t\t\t\t//\n\t\t\t\t\t\t} else if (ReceivePacket.ID == SendPacket.ID) {\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\tretval = 3;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tstarttime = TickCount;\n\n\t/*\n\t** Main Processing Loop\n\t*/\n\twhile (process) {\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tcommands->Draw_All();\n\t\t}\n#endif\t//WIN32\n\t\t/*\n\t\t** Invoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t** Get user input\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t** Process input\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tretval = 0;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\t/*\n\t\t** Service the connection.\n\t\t*/\n\t\tNullModem.Service();\n\t\tif (NullModem.Num_Send() == 0) {\n\t\t\tif (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) {\n\t\t\t\tif (ReceivePacket.Command == SERIAL_CONNECT) {\n\t\t\t\t\tstarttime = TickCount;\n\t\t\t\t\twhile (TickCount - starttime < 30)\n\t\t\t\t\t\tNullModem.Service();\n\n\t\t\t\t\t//\n\t\t\t\t\t// whoever has the highest time is the host\n\t\t\t\t\t//\n\t\t\t\t\tif (ReceivePacket.ScenarioInfo.Seed > SendPacket.ScenarioInfo.Seed) {\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tretval = 2;\n\n\t\t\t\t\t} else if (ReceivePacket.ScenarioInfo.Seed == SendPacket.ScenarioInfo.Seed) {\n\t\t\t\t\t\tif (ReceivePacket.ID > SendPacket.ID) {\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\tretval = 2;\n\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// if they are equal then it's a loopback cable or a modem\n\t\t\t\t\t\t//\n\t\t\t\t\t\t} else if (ReceivePacket.ID == SendPacket.ID) {\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\tretval = 3;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tretval = 0;\n\t\t\t\t\tprocess = false;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tretval = 1;\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\tif (TickCount - starttime > 3600) {\t\t// only wait 1 minute\n\t\t\tretval = 0;\n\t\t\tprocess = false;\n\t\t}\n\t}\t/* end of while */\n\n\treturn( retval );\n\n}\n\n\n/***************************************************************************\n * Reconnect_Modem -- allows user to reconnect\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = failure to connect; 1 = connect OK\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nint Reconnect_Modem( void )\n{\n\tint status;\n\tint modemstatus;\n\n\n\tswitch (Session.ModemType) {\n\t\tcase (MODEM_NULL_HOST):\n\t\tcase (MODEM_NULL_JOIN):\n\t\t\tstatus = Reconnect_Null_Modem();\n\t\t\tbreak;\n\n\t\tcase (MODEM_DIALER):\n\t\t\tmodemstatus = NullModem.Get_Modem_Status();\n\t\t\tif ( (modemstatus & CD_SET) ) {\n\t\t\t\tstatus = Reconnect_Null_Modem();\n\t\t\t} else {\n\t\t\t\tstatus = Dial_Modem( DialSettings, true );\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase (MODEM_ANSWERER):\n\t\t\tmodemstatus = NullModem.Get_Modem_Status();\n\t\t\tif ( (modemstatus & CD_SET) ) {\n\t\t\t\tstatus = Reconnect_Null_Modem();\n\t\t\t} else {\n\t\t\t\tstatus = Answer_Modem( DialSettings, true );\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n\treturn( status );\n}\n\n\n/***************************************************************************\n * Reconnect_Null_Modem -- allows user to reconnect\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = failure to connect; 1 = connect OK\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Reconnect_Null_Modem( void )\n{\n\t/*\n\t** Button Enumerations\n\t*/\n\tenum {\n\t\tBUTTON_CANCEL = 100,\n\t};\n\n\t/*\n\t** Dialog variables\n\t*/\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\n\tint retval;\n\tunsigned long starttime;\n\tunsigned long lastmsgtime;\n\tint packetlen;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\tint x,y,width,height;\t\t\t\t\t// dialog dimensions\n\tchar buffer[80*3];\n\n\t/*\n\t** Buttons\n\t*/\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\n\t/*\n\t**\tDetermine the dimensions of the text to be used for the dialog box.\n\t**\tThese dimensions will control how the dialog box looks.\n\t*/\n\tstrcpy( buffer, Text_String( TXT_NULL_CONNERR_CHECK_CABLES ) );\n\tFancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);\n\tFormat_Window_String(buffer, SeenBuff.Get_Height(), width, height);\n\n\twidth = max(width, 50 * RESFACTOR);\n\twidth += 40 * RESFACTOR;\n\theight += 60 * RESFACTOR;\n\n\tx = (SeenBuff.Get_Width() - width) / 2;\n\ty = (SeenBuff.Get_Height() - height) / 2;\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,\n\t\tx + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8 * RESFACTOR)) >> 1),\n\t\ty + height - (FontHeight + FontYSpacing + 2*RESFACTOR) - 10 * RESFACTOR);\n\n\t/*\n\t** Initialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\tprocess = true;\n\n\t/*\n\t** Create the list\n\t*/\n\tcommands = &cancelbtn;\n\n\tcommands->Flag_List_To_Redraw();\n\n\t/*\n\t** Draw the dialog\n\t*/\n\tHide_Mouse();\n\n\tDialog_Box(x, y, width, height);\n\tDraw_Caption(TXT_NONE, x, y, width);\n\n\tFancy_Text_Print(buffer, x + 20*RESFACTOR, y + 25*RESFACTOR, scheme, TBLACK, TPF_TEXT);\n\n\tcommands->Draw_All();\n\tShow_Mouse();\n\n\t/*\n\t** Main Processing Loop\n\t*/\n\tstarttime = lastmsgtime = TickCount;\n\twhile (process) {\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tcommands->Draw_All();\n\t\t}\n#endif\t//WIN32\n\t\t/*\n\t\t** Invoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t** Get user input\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\t/*\n\t\t** Process input\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tretval = false;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\t/*\n\t\t** Service the connection.\n\t\t*/\n\t\tNullModem.Service();\n\n\t\t/*\n\t\t** Resend our message if it's time\n\t\t*/\n\t\tif (TickCount - starttime > PACKET_RETRANS_TIME) {\n\t\t\tstarttime = TickCount;\n\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\tSendPacket.Command = SERIAL_CONNECT;\n\t\t\tSendPacket.ID = Session.ColorIdx;\n\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 0);\n\t\t}\n\n\t\t/*\n\t\t** Check for an incoming message\n\t\t*/\n\t\tif (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) {\n\n\t\t\tlastmsgtime = TickCount;\n\n\t\t\tif (ReceivePacket.Command == SERIAL_CONNECT) {\n\n\t\t\t\t// are we getting our own packets back??\n\n\t\t\t\tif (ReceivePacket.ID == Session.ColorIdx) {\n\t\t\t\t\tWWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);\n\t\t\t\t\tretval = false;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** OK, we got our message; now we have to make certain the other\n\t\t\t\t** guy gets his, so send him one with an ACK required.\n\t\t\t\t*/\n\t\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\t\tSendPacket.Command = SERIAL_CONNECT;\n\t\t\t\tSendPacket.ID = Session.ColorIdx;\n\t\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\t\t\t\tstarttime = TickCount;\n\t\t\t\twhile (TickCount - starttime < 60)\n\t\t\t\t\tNullModem.Service();\n\t\t\t\tretval = true;\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t// timeout if we do not get any packets\n\t\t//\n\t\tif (TickCount - lastmsgtime > PACKET_CANCEL_TIMEOUT) {\n\t\t\tretval = false;\n\t\t\tprocess = false;\n\t\t}\n\n\t}\t/* end of while */\n\n\treturn( retval );\n\n}\n\n\n/***********************************************************************************************\n * Destroy_Null_Connection -- destroys the given connection\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * Call this routine when a connection goes bad, or another player signs off.\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tid\t\t\tconnection ID to destroy; this should be the HousesType of the player being\t  *\n *             \"destroyed\".\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\terror\t\t0 = user signed off; 1 = connection error\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   07/31/1995 DRD : Created.                                              \t\t\t\t\t\t  *\n *=============================================================================================*/\nvoid Destroy_Null_Connection(int id, int error)\n{\n\tint i;\n\tHouseClass *housep;\n\tchar txt[80];\n\n\n\tif ( Session.NumPlayers == 1 ) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tDo nothing if the house isn't human.\n\t*/\n\thousep = HouseClass::As_Pointer((HousesType)id);\n\tif (!housep || !housep->IsHuman)\n\t\treturn;\n\n\t/*\n\t**\tCreate a message to display to the user\n\t*/\n\ttxt[0] = '\\0';\n\tswitch (error) {\n\t\tcase 1:\n\t\t\tsprintf(txt,Text_String(TXT_CONNECTION_LOST), housep->IniName);\n\t\t\tbreak;\n\n\t\tcase 0:\n\t\t\tsprintf(txt,Text_String(TXT_LEFT_GAME), housep->IniName);\n\t\t\tbreak;\n\n\t\tcase -1:\n\t\t\tNullModem.Delete_Connection();\n\t\t\tbreak;\n\t}\n\n\tif (strlen(txt)) {\n\t\tSession.Messages.Add_Message (NULL, 0, txt,\n\t\t\t(housep->RemapColor == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : housep->RemapColor,\n\t\t\tTPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n\t/*\n\t** Remove this player from the Players vector\n\t*/\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\tif (!stricmp(Session.Players[i]->Name,housep->IniName)) {\n\t\t\tdelete Session.Players[i];\n\t\t\tSession.Players.Delete(Session.Players[i]);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tTurn the player's house over to the computer's AI\n\t*/\n\thousep->IsHuman = false;\n//\thousep->Smartness = IQ_MENSA;\n\thousep->IQ = Rule.MaxIQ;\n\tstrcpy (housep->IniName,Text_String(TXT_COMPUTER));\n\n\tSession.NumPlayers--;\n\n\t/*\n\t**\tIf we're the last player left, tell the user.\n\t*/\n\tif (Session.NumPlayers == 1) {\n\t\tsprintf(txt,\"%s\",Text_String(TXT_JUST_YOU_AND_ME));\n\t\tSession.Messages.Add_Message (NULL, 0, txt,\n\t\t\t(housep->RemapColor == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : housep->RemapColor,\n\t\t\tTPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n}\n\n\n/***************************************************************************\n * Select_Serial_Dialog -- Serial Communications menu dialog               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tGAME_MODEM\t\t\t\tuser wants to play a modem game\t\t\t\t\t\t*\n *\t\tGAME_NULL_MODEM\t\tuser wants to play a null-modem game\t\t\t\t*\n *\t\tGAME_NORMAL\t\t\t\tuser hit Cancel\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nGameType Select_Serial_Dialog( void )\n{\n\tint rc;\n//\tint value, i;\n\tint com = -1, baud = -1;\n\tint error = 0;\n\n\t/*\n\t** Dialog & button dimensions\n\t*/\n\tint d_dialog_w = 160 * RESFACTOR;\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 94 * RESFACTOR;\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2);\t// dialog x-coord\n\tint d_dialog_y = 80*RESFACTOR;\n//\tint d_dialog_y = ((136 * RESFACTOR - d_dialog_h) / 2);\t// dialog y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t// center x-coord\n\n\tint d_txt6_h = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_margin = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint d_dial_w = 90 * RESFACTOR;\n\tint d_dial_h = 9 * RESFACTOR;\n\tint d_dial_x = d_dialog_cx - d_dial_w / 2;\n\tint d_dial_y = d_dialog_y + d_margin + d_txt6_h + d_margin;\n\n\tint d_answer_w = 90 * RESFACTOR;\n\tint d_answer_h = 9 * RESFACTOR;\n\tint d_answer_x = d_dialog_cx - d_answer_w / 2;\n\tint d_answer_y = d_dial_y + d_dial_h + 2;\n\n\tint d_nullmodem_w = 90 * RESFACTOR;\n\tint d_nullmodem_h = 9 * RESFACTOR;\n\tint d_nullmodem_x = d_dialog_cx - d_nullmodem_w / 2;\n\tint d_nullmodem_y = d_answer_y + d_answer_h + 2;\n\n\tint d_settings_w = 90 * RESFACTOR;\n\tint d_settings_h = 9 * RESFACTOR;\n\tint d_settings_x = d_dialog_cx - d_settings_w / 2;\n\tint d_settings_y = d_nullmodem_y + d_nullmodem_h + 2;\n\n\tint d_cancel_w = 50 * RESFACTOR;\n\tint d_cancel_h = 9 * RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - d_cancel_w / 2;\n\tint d_cancel_y = d_settings_y + d_settings_h + d_margin;\n\n\t/*\n\t** Button Enumerations\n\t*/\n\tenum {\n\t\tBUTTON_DIAL = 100,\n\t\tBUTTON_ANSWER,\n\t\tBUTTON_NULLMODEM,\n\t\tBUTTON_SETTINGS,\n\t\tBUTTON_CANCEL,\n\n\t\tNUM_OF_BUTTONS = 5,\n\t};\n\n\t/*\n\t** Redraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*\n\t** Dialog variables\n\t*/\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\tchar namebuf[MPLAYER_NAME_MAX] = {0};\t\t// buffer for player's name\n\tint tabs[] = {77*RESFACTOR};\t\t\t\t// tabs for player list box\n\tGameType retval;\t\t\t\t\t\t\t// return value\n\n\tint selection;\n\tbool pressed;\n\tint curbutton;\n\tTextButtonClass *buttons[NUM_OF_BUTTONS];\n\n\tSerialSettingsType *settings;\n\tbool selectsettings = false;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\n\t/*\n\t** Buttons\n\t*/\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tTextButtonClass dialbtn(BUTTON_DIAL, TXT_DIAL_MODEM, TPF_BUTTON, d_dial_x, d_dial_y, d_dial_w, d_dial_h);\n\tTextButtonClass answerbtn(BUTTON_ANSWER, TXT_ANSWER_MODEM, TPF_BUTTON, d_answer_x, d_answer_y, d_answer_w, d_answer_h);\n\tTextButtonClass nullmodembtn(BUTTON_NULLMODEM, TXT_NULL_MODEM, TPF_BUTTON, d_nullmodem_x, d_nullmodem_y, d_nullmodem_w, d_nullmodem_h);\n\tTextButtonClass settingsbtn(BUTTON_SETTINGS, TXT_SETTINGS, TPF_BUTTON, d_settings_x, d_settings_y, d_settings_w, d_settings_h);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n\n\t/*\n\t** Initialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\tif (Session.SerialDefaults.Port == 0 ||\n\t\tSession.SerialDefaults.IRQ == -1 ||\n\t\tSession.SerialDefaults.Baud == -1) {\n\t\tselectsettings = true;\n\n\t} else if ( NullModem.Detect_Port( &Session.SerialDefaults ) != PORT_VALID ) {\n\t\tselectsettings = true;\n\t}\n\n\t/*\n\t** Create the list\n\t*/\n\tcommands = &dialbtn;\n\tanswerbtn.Add_Tail(*commands);\n\tnullmodembtn.Add_Tail(*commands);\n\tsettingsbtn.Add_Tail(*commands);\n\tcancelbtn.Add_Tail(*commands);\n\n\t/*\n\t** Fill array of button ptrs\n\t*/\n\tcurbutton = 0;\n\tbuttons[0] = &dialbtn;\n\tbuttons[1] = &answerbtn;\n\tbuttons[2] = &nullmodembtn;\n\tbuttons[3] = &settingsbtn;\n\tbuttons[4] = &cancelbtn;\n\tbuttons[curbutton]->Turn_On();\n\n\tKeyboard->Clear();\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\n\t/*\n\t** Main Processing Loop\n\t*/\n\tdisplay = REDRAW_ALL;\n\tprocess = true;\n\tpressed = false;\n\twhile (process) {\n\t\t/*\n\t\t** Invoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t** Refresh display if needed\n\t\t*/\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n#endif\n\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\t/*\n\t\t\t\t** Refresh the backdrop\n\t\t\t\t*/\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\t/*\n\t\t\t\t** Draw the background\n\t\t\t\t*/\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\t\t\t\t/*\n\t\t\t\t** Draw the labels\n\t\t\t\t*/\n\t\t\t\tDraw_Caption (TXT_SELECT_SERIAL_GAME, d_dialog_x, d_dialog_y, d_dialog_w);\n\t\t\t}\n\t\t\tcommands->Draw_All();\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t** Get user input\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\t/*\n\t\t** Process input\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_DIAL | KN_BUTTON):\n\t\t\t\tselection = BUTTON_DIAL;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_ANSWER | KN_BUTTON):\n\t\t\t\tselection = BUTTON_ANSWER;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_NULLMODEM | KN_BUTTON):\n\t\t\t\tselection = BUTTON_NULLMODEM;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_SETTINGS | KN_BUTTON):\n\t\t\t\tselection = BUTTON_SETTINGS;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tselection = BUTTON_CANCEL;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_UP):\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tcurbutton--;\n\t\t\t\tif (curbutton < 0)\n\t\t\t\t\tcurbutton = (NUM_OF_BUTTONS - 1);\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_DOWN):\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tcurbutton++;\n\t\t\t\tif (curbutton > (NUM_OF_BUTTONS - 1) )\n\t\t\t\t\tcurbutton = 0;\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\t\tselection = curbutton + BUTTON_DIAL;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (pressed) {\n\t\t\t//\n\t\t\t// to make sure the selection is correct in case they used the mouse\n\t\t\t//\n\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\tcurbutton = selection - BUTTON_DIAL;\n\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\tbuttons[curbutton]->IsPressed = true;\n\t\t\tbuttons[curbutton]->Draw_Me(true);\n\n\t\t\tswitch (selection) {\n\t\t\t\tcase (BUTTON_DIAL):\n\n\t\t\t\t\tif (selectsettings) {\n\t\t\t\t\t\tWWMessageBox().Process(TXT_SELECT_SETTINGS);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Remote-connect\n\t\t\t\t\t*/\n\t\t\t\t\t} else if ( Phone_Dialog() ) {\n\t\t\t\t\t\tif (Session.PhoneBook[Session.CurPhoneIdx]->Settings.Port == 0) {\n\t\t\t\t\t\t\tsettings = &Session.SerialDefaults;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsettings = &(Session.PhoneBook[Session.CurPhoneIdx]->Settings);\n\t\t\t\t\t\t}\n#ifdef WIN32\n\t\t\t\t\t\tif (SerialPort) {\n\t\t\t\t\t\t\tdelete SerialPort;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSerialPort = new WinModemClass;\n#endif\t//WIN32\n\t\t\t\t\t\tif ( Init_Null_Modem( settings ) ) {\n\n\t\t\t\t\t\t\tif (settings->CallWaitStringIndex == CALL_WAIT_CUSTOM) {\n\t\t\t\t\t\t\t\tstrcpy( DialString, settings->CallWaitString );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tstrcpy( DialString,\n\t\t\t\t\t\t\t\t\tSession.CallWaitStrings[ settings->CallWaitStringIndex ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstrcat( DialString, Session.PhoneBook[ Session.CurPhoneIdx ]->Number );\n\n\t\t\t\t\t\t\tif ( Dial_Modem( settings, false ) ) {\n\t\t\t\t\t\t\t\tSession.ModemType = MODEM_DIALER;\n\t\t\t\t\t\t\t\tif ( Com_Scenario_Dialog() ) {\n\t\t\t\t\t\t\t\t\tretval = GAME_MODEM;\n\t\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (process) {\t\t// restore to default\n\t\t\t\t\t\t\t\tNullModem.Change_IRQ_Priority( 0 );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tWWMessageBox().Process(TXT_SELECT_SETTINGS);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (process) {\n\t\t\t\t\t\tbuttons[curbutton]->IsPressed = false;\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n  \t\t\t\t\t}\n\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_ANSWER):\n\n\t\t\t\t\tif (selectsettings) {\n\t\t\t\t\t\tWWMessageBox().Process(TXT_SELECT_SETTINGS);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Remote-connect\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tsettings = &Session.SerialDefaults;\n#ifdef WIN32\n\t\t\t\t\t\tif (SerialPort) {\n\t\t\t\t\t\t\tdelete SerialPort;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSerialPort = new WinModemClass;\n#endif\t//WIN32\n\t\t\t\t\t\tif ( Init_Null_Modem( settings ) ) {\n\t\t\t\t\t\t\tif ( Answer_Modem( settings, false ) ) {\n\t\t\t\t\t\t\t\tSession.ModemType = MODEM_ANSWERER;\n\t\t\t\t\t\t\t\tif ( Com_Show_Scenario_Dialog() ) {\n\t\t\t\t\t\t\t\t\tretval = GAME_MODEM;\n\t\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (process) {\t\t// restore to default\n\t\t\t\t\t\t\t\tNullModem.Change_IRQ_Priority( 0 );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tWWMessageBox().Process(TXT_SELECT_SETTINGS);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (process) {\n\t\t\t\t\t\tbuttons[curbutton]->IsPressed = false;\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\t}\n\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_NULLMODEM):\n\n\t\t\t\t\tif (selectsettings) {\n\t\t\t\t\t\tWWMessageBox().Process(TXT_SELECT_SETTINGS);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Otherwise, remote-connect; save values if we're recording\n\t\t\t\t\t*/\n\t\t\t\t\t} else if ( Init_Null_Modem( &Session.SerialDefaults ) ) {\n\t\t\t\t\t\trc = Test_Null_Modem();\n\t\t\t\t\t\tswitch (rc) {\n\t\t\t\t\t\t\tcase (1):\n\t\t\t\t\t\t\t\tSession.ModemType = MODEM_NULL_HOST;\n\t\t\t\t\t\t\t\tif ( Com_Scenario_Dialog() ) {\n\t\t\t\t\t\t\t\t\tretval = GAME_NULL_MODEM;\n\t\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase (2):\n\t\t\t\t\t\t\t\tSession.ModemType = MODEM_NULL_JOIN;\n\t\t\t\t\t\t\t\tif ( Com_Show_Scenario_Dialog() ) {\n\t\t\t\t\t\t\t\t\tretval = GAME_NULL_MODEM;\n\t\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase (3):\n\t\t\t\t\t\t\t\tWWMessageBox().Process( TXT_MODEM_OR_LOOPBACK );\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (process) {\t\t// restore to default\n\t\t\t\t\t\t\tNullModem.Change_IRQ_Priority( 0 );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tWWMessageBox().Process(TXT_SELECT_SETTINGS);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (process) {\n\t\t\t\t\t\tbuttons[curbutton]->IsPressed = false;\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\t}\n\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_SETTINGS):\n\t\t\t\t\tif ( Com_Settings_Dialog( &Session.SerialDefaults ) ) {\n\t\t\t\t\t\tSession.Write_MultiPlayer_Settings ();\n\n\t\t\t\t\t\tselectsettings = true;\n\n\t\t\t\t\t\tif (Session.SerialDefaults.Port != 0 &&\n\t\t\t\t\t\t\tSession.SerialDefaults.IRQ != -1 &&\n\t\t\t\t\t\t\tSession.SerialDefaults.Baud != -1) {\n\t\t\t\t\t\t\tif ( NullModem.Detect_Port( &Session.SerialDefaults ) == PORT_VALID) {\n\t\t\t\t\t\t\t\tselectsettings = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbuttons[curbutton]->IsPressed = false;\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_CANCEL):\n\t\t\t\t\tretval = GAME_NORMAL;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tpressed = false;\n\t\t}\n\t}\t/* end of while */\n\n\treturn( retval );\n}\n\n\n\n\n\n\n#ifdef WIN32\n/***********************************************************************************************\n * Advanced_Modem_Settings -- Allows to user to set additional modem settings                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    current settings                                                                  *\n *                                                                                             *\n * OUTPUT:   modified settings                                                                 *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    12/16/96 2:29PM ST : Created                                                             *\n *=============================================================================================*/\nAdvanced_Modem_Settings (SerialSettingsType *settings)\n{\n\n\t/*........................................................................\n\tDialog & button dimensions\n\t........................................................................*/\n#if (FRENCH | GERMAN)\n\tint d_dialog_w = 440;\t\t\t\t\t\t\t\t\t\t\t\t\t// dialog width\n#else\n\tint d_dialog_w = 340;\t\t\t\t\t\t\t\t\t\t\t\t\t// dialog width\n#endif\n\n\tint d_dialog_h = 200;\t\t\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = 320 - d_dialog_w/2;\t\t\t\t\t\t\t\t// dialog x-coord\n\tint d_dialog_y = 200 - d_dialog_h/ 4;\t\t\t\t\t\t\t\t// dialog y-coord\n\n\n\tint d_compression_w = 50;\n\tint d_compression_h = 18;\n\tint d_compression_x = d_dialog_x + d_dialog_w/2 +40;\n\tint d_compression_y = d_dialog_y + 40;\n\n\tint d_errorcorrection_w = 50;\n\tint d_errorcorrection_h = 18;\n\tint d_errorcorrection_x = d_dialog_x + d_dialog_w/2 +40;\n\tint d_errorcorrection_y = d_dialog_y + 65;\n\n\tint d_hardwareflowcontrol_w = 50;\n\tint d_hardwareflowcontrol_h = 18;\n\tint d_hardwareflowcontrol_x = d_dialog_x + d_dialog_w/2 +40;\n\tint d_hardwareflowcontrol_y = d_dialog_y + 90;\n\n\tint d_default_w = 100;\n\tint d_default_h = 18;\n\tint d_default_x = d_dialog_x + d_dialog_w / 2 - d_default_w / 2;\n\tint d_default_y = d_dialog_y + d_dialog_h - 70;\n\n\tint d_ok_w = 100;\n\tint d_ok_h = 18;\n\tint d_ok_x = d_dialog_x + d_dialog_w/2 - d_ok_w / 2;\n\tint d_ok_y = d_dialog_y + d_dialog_h - 40;\n\n\tenum {\n\t\tBUTTON_COMPRESSION = 100,\n\t\tBUTTON_ERROR_CORRECTION,\n\t\tBUTTON_HARDWARE_FLOW_CONTROL,\n\t\tBUTTON_DEFAULT,\n\t\tBUTTON_OK,\n\t};\n\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND,\n\t} RedrawType;\n\n\t/*\n\t** Yes/No strings\n\t*/\n\tchar compress_text [16];\n\tchar correction_text [16];\n\tchar flowcontrol_text[16];\n\n\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t** Initialise the button text\n\t*/\n\tstrcpy (compress_text, settings->Compression ? Text_String (TXT_ON) : Text_String (TXT_OFF) );\n\tstrcpy (correction_text, settings->ErrorCorrection ?\n\t\t\t\t\t\t\t\t\t\t\t\tText_String (TXT_ON) : Text_String (TXT_OFF) );\n\tstrcpy (flowcontrol_text, settings->HardwareFlowControl ?\n\t\t\t\t\t\t\t\t\t\t\t\tText_String (TXT_ON) : Text_String (TXT_OFF) );\n\n\n\t/*\n\t** Create the buttons\n\t*/\n\tTextButtonClass compressionbutton(BUTTON_COMPRESSION, compress_text,\n\t\tTPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n\t\td_compression_x, d_compression_y, d_compression_w, d_compression_h);\n\n\tTextButtonClass errorcorrectionbutton(BUTTON_ERROR_CORRECTION, correction_text,\n\t\tTPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n\t\td_errorcorrection_x, d_errorcorrection_y, d_errorcorrection_w, d_errorcorrection_h);\n\n\tTextButtonClass hardwareflowcontrolbutton(BUTTON_HARDWARE_FLOW_CONTROL, flowcontrol_text,\n\t\tTPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n\t\td_hardwareflowcontrol_x, d_hardwareflowcontrol_y, d_hardwareflowcontrol_w, d_hardwareflowcontrol_h);\n\n\tTextButtonClass defaultbutton(BUTTON_DEFAULT, TXT_DEFAULT,\n\t\tTPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n\t\td_default_x, d_default_y, d_default_w, d_default_h);\n\n\tTextButtonClass okbutton(BUTTON_OK, TXT_OK,\n\t\tTPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n\t\td_ok_x, d_ok_y, d_ok_w, d_ok_h);\n\n\n\t/*\n\t** Misc. variables.\n\t*/\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tBOOL process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\tGadgetClass *commands;\t\t\t\t\t// button list\n\n\n\tcommands = &okbutton;\n\tdefaultbutton.Add_Tail(*commands);\n\tcompressionbutton.Add_Tail(*commands);\n\terrorcorrectionbutton.Add_Tail(*commands);\n\thardwareflowcontrolbutton.Add_Tail(*commands);\n\n\n\t/*\n\t** Main process loop\n\t*/\n\twhile (process) {\n\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored){\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay=REDRAW_ALL;\n\t\t}\n\n\t\t/*\n\t\t........................ Invoke game callback .........................\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t...................... Refresh display if needed ......................\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\t\t\t/*\n\t\t\t.................. Redraw backgound & dialog box ...................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tCCPalette.Set();\n\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t// init font variables\n\n\t\t\t\tFancy_Text_Print(TXT_NONE, 0, 0, scheme, TBLACK, TPF_TEXT);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDialog & Field labels\n\t\t\t\t...............................................................*/\n\t\t\t\tDraw_Caption (TXT_MODEM_INITIALISATION, d_dialog_x, d_dialog_y, d_dialog_w);\n\n\t\t\t\tFancy_Text_Print( TXT_DATA_COMPRESSION,\n\t\t\t\t\td_compression_x - 26, d_compression_y + 2,\n\t\t\t\t\tscheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\n\t\t\t\tFancy_Text_Print( TXT_ERROR_CORRECTION,\n\t\t\t\t\td_errorcorrection_x - 26, d_errorcorrection_y +2,\n\t\t\t\t\tscheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\n\t\t\t\tFancy_Text_Print( TXT_HARDWARE_FLOW_CONTROL,\n\t\t\t\t\td_hardwareflowcontrol_x -26, d_hardwareflowcontrol_y +2,\n\t\t\t\t\tscheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t.......................... Redraw buttons ..........................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcompressionbutton.Flag_To_Redraw();\n\t\t\t\terrorcorrectionbutton.Flag_To_Redraw();\n\t\t\t\thardwareflowcontrolbutton.Flag_To_Redraw();\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t........................... Get user input ............................\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\t/*\n\t\t---------------------------- Process input ----------------------------\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_COMPRESSION | KN_BUTTON):\n\t\t\t\tsettings->Compression = settings->Compression ^ 1;\n\t\t\t\tstrcpy (compress_text, settings->Compression ?\n\t\t\t\t\t\t\t\t\t\tText_String (TXT_ON) : Text_String (TXT_OFF) );\n\t\t\t\tif (display < REDRAW_BUTTONS) display = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_ERROR_CORRECTION | KN_BUTTON):\n\t\t\t\tsettings->ErrorCorrection = settings->ErrorCorrection ^ 1;\n\t\t\t\tstrcpy (correction_text, settings->ErrorCorrection ?\n\t\t\t\t\t\t\t\t\t\tText_String (TXT_ON) : Text_String (TXT_OFF) );\n\t\t\t\tif (display < REDRAW_BUTTONS) display = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_HARDWARE_FLOW_CONTROL | KN_BUTTON):\n\t\t\t\tsettings->HardwareFlowControl = settings->HardwareFlowControl ^ 1;\n\t\t\t\tstrcpy (flowcontrol_text, settings->HardwareFlowControl ?\n\t\t\t\t\t\t\t\t\t\tText_String (TXT_ON) : Text_String (TXT_OFF) );\n\t\t\t\tif (display < REDRAW_BUTTONS) display = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_DEFAULT | KN_BUTTON):\n\t\t\t\tsettings->Compression = false;\n\t\t\t\tsettings->ErrorCorrection = false;\n\t\t\t\tsettings->HardwareFlowControl = true;\n\n\t\t\t\tstrcpy (compress_text, settings->Compression ?\n\t\t\t\t\t\t\t\t\t\tText_String (TXT_ON) : Text_String (TXT_OFF) );\n\n\t\t\t\tstrcpy (correction_text, settings->ErrorCorrection ?\n\t\t\t\t\t\t\t\t\t\tText_String (TXT_ON) : Text_String (TXT_OFF) );\n\n\t\t\t\tstrcpy (flowcontrol_text, settings->HardwareFlowControl ?\n\t\t\t\t\t\t\t\t\t\tText_String (TXT_ON) : Text_String (TXT_OFF) );\n\n\t\t\t\tif (display < REDRAW_BUTTONS)\tdisplay = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n#endif\t//WIN32\n\n\n\n/***************************************************************************\n * Com_Settings_Dialog -- Lets user select serial port settings            *\n *                                                                         *\n *  Ŀ               *\n *                      Settings                                         *\n *                                                                       *\n *       Port:____       IRQ:__        Baud:______                       *\n *    Ŀ  Ŀ  Ŀ                     *\n *                                                                 *\n *                                                                 *\n *                                                                 *\n *                                                                 *\n *                             *\n *                                                                       *\n *     Initialization:        [Add]   [Delete]                           *\n *      _____________________________                                    *\n *     Ŀ                    *\n *                                                                     *\n *                                                                     *\n *                                                                     *\n *                         *\n *                                                                       *\n *     Call Waiting:                                                     *\n *      _______________                                                  *\n *     Ŀ          [Tone Dialing]                       *\n *                                                                     *\n *                                [Pulse Dialing]                      *\n *                                                                     *\n *                                                    *\n *                                                                       *\n *                     [OK]   [Cancel]                                   *\n *                 *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsettings\t\tptr to SerialSettingsType structure\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = OK, false = Cancel\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Com_Settings_Dialog( SerialSettingsType *settings )\n{\n\n\t/*\n\t** Dialog & button dimensions\n\t*/\n\tint d_dialog_w = 320 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 200 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2);\t\t// dialog x-coord\n\tint d_dialog_y = ((200 * RESFACTOR - d_dialog_h) / 2);\t\t// dialog y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_txt6_h = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_margin = 5 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint d_portlist_w = 80 * RESFACTOR + 80*(RESFACTOR-1);\t//Port list wider in hires\n\tint d_portlist_h = 33 * RESFACTOR;\n\tint d_portlist_x = d_dialog_x + (d_dialog_w / 6) - (d_portlist_w / 2);\n#ifdef WIN32\n \td_portlist_x = 0x45;\n#endif\n\tint d_portlist_y = d_dialog_y + ((d_margin + d_txt6_h) * 2) + d_margin + 10 * RESFACTOR;\n\n#ifdef WIN32\n\tint d_port_w = d_portlist_w;\n\tint d_port_x = 0x45;\n#else\n\tint d_port_w = (5 * 6 * RESFACTOR) + 3 * RESFACTOR;\n\n//\tint d_port_x = d_portlist_x + 29 * RESFACTOR;\n#ifdef FRENCH  //VG2\n\tint d_port_x = (d_portlist_x + 29 * RESFACTOR) + 5;\n#else\n\tint d_port_x = d_portlist_x + 29 * RESFACTOR;\n#endif\n\n#endif\t//WIN32\n\tint d_port_h = 9 * RESFACTOR;\n\tint d_port_y = d_portlist_y - d_margin - d_txt6_h;\n\n\tint d_irqlist_w = 80 * RESFACTOR;\n\tint d_irqlist_h = 33 * RESFACTOR;\n\tint d_irqlist_x = d_dialog_x + (d_dialog_w / 2) - (d_irqlist_w / 2);\n\tint d_irqlist_y = d_portlist_y;\n\n\tint d_irq_w = ((IRQBUF_MAX - 1) * 6 * RESFACTOR) + 3 * RESFACTOR;\n\tint d_irq_h = 9 * RESFACTOR;\n\tint d_irq_x = d_irqlist_x + 25 * RESFACTOR;\n\tint d_irq_y = d_irqlist_y - d_margin - d_txt6_h;\n\n\tint d_baudlist_w = 80 * RESFACTOR;\n\tint d_baudlist_h = 33 * RESFACTOR;\n\tint d_baudlist_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_baudlist_w / 2);\n#ifdef WIN32\n d_baudlist_x -= 32;\n#endif\n\tint d_baudlist_y = d_irqlist_y;\n\n\tint d_baud_w = ((BAUDBUF_MAX - 1) * 6 * RESFACTOR) + 3 * RESFACTOR;\n\tint d_baud_h = 9 * RESFACTOR;\n\tint d_baud_x = d_baudlist_x + 29 * RESFACTOR;\n\tint d_baud_y = d_baudlist_y - d_margin - d_txt6_h;\n\n\tint d_initstrlist_w = ((INITSTRBUF_MAX - 1) * 6 * RESFACTOR) + 8 * RESFACTOR + 3 * RESFACTOR;\n\tint d_initstrlist_h = 21 * RESFACTOR;\n\tint d_initstrlist_x = d_dialog_cx - (d_initstrlist_w / 2);\n\tint d_initstrlist_y = d_portlist_y + d_portlist_h + ((d_margin + d_txt6_h) * 2) + d_margin + 4;\n\n\tint d_initstr_w = ((INITSTRBUF_MAX - 1) * 6 * RESFACTOR) + 3 * RESFACTOR;\n\tint d_initstr_h = 9 * RESFACTOR;\n\tint d_initstr_x = d_initstrlist_x;\n\tint d_initstr_y = d_initstrlist_y - d_margin - d_txt6_h;\n\n\tint d_add_w = 45 * RESFACTOR;\n#ifdef FRENCH\n\tint d_add_x = d_dialog_cx - (d_add_w / 2);\n#else\n\tint d_add_x = (d_dialog_cx - (d_add_w / 2)) + 30;\n#endif\n\tint d_add_h = 9 * RESFACTOR;\n\tint d_add_y = d_initstr_y - d_add_h - 3 * RESFACTOR;\n\n\tint d_delete_w = 45 * RESFACTOR;\n#ifdef FRENCH\n\tint d_delete_x = (d_dialog_x + ((d_dialog_w * 3) / 4) - (d_delete_w / 2)) + 10;\n#else\n\tint d_delete_x = d_dialog_x + ((d_dialog_w * 3) / 4) - (d_delete_w / 2);\n#endif\n\tint d_delete_h = 9 * RESFACTOR;\n\tint d_delete_y = d_initstr_y - d_add_h - 3 * RESFACTOR;\n\n\tint d_cwaitstrlist_w = (((CWAITSTRBUF_MAX - 1) + 9) * 6) * RESFACTOR + 3 * RESFACTOR;\n\tint d_cwaitstrlist_h = 27 * RESFACTOR;\n\tint d_cwaitstrlist_x = d_initstrlist_x;\n\tint d_cwaitstrlist_y = d_initstrlist_y + d_initstrlist_h + ((d_margin + d_txt6_h) * 2) + 2;\n\n\tint d_cwaitstr_w = ((CWAITSTRBUF_MAX - 1) * 6) * RESFACTOR + 3 * RESFACTOR;\n\tint d_cwaitstr_h = 9 * RESFACTOR;\n\tint d_cwaitstr_x = d_cwaitstrlist_x;\n\tint d_cwaitstr_y = d_cwaitstrlist_y - d_margin - d_txt6_h;\n\n\tint d_tone_w = 80 * RESFACTOR;\n\tint d_tone_h = 9 * RESFACTOR;\n\tint d_tone_x = d_dialog_x + ((d_dialog_w * 3) / 4) - (d_tone_w / 2);\n\tint d_tone_y = d_cwaitstrlist_y;\n\n\tint d_pulse_w = 80 * RESFACTOR;\n\tint d_pulse_h = 9 * RESFACTOR;\n\tint d_pulse_x = d_dialog_x + ((d_dialog_w * 3) / 4) - (d_pulse_w / 2);\n\tint d_pulse_y = d_tone_y + d_tone_h + d_margin;\n\n#ifdef FRENCH\n\tint d_save_w = 80 * RESFACTOR;\n#else\n\tint d_save_w = 40 * RESFACTOR;\n#endif\n\tint d_save_h = 9 * RESFACTOR;\n\tint d_save_x = d_dialog_x + (d_dialog_w / 5) - (d_save_w / 2);\n\tint d_save_y = d_dialog_y + d_dialog_h - d_save_h - d_margin - 4*RESFACTOR;\n\n\tint d_cancel_w = 50 * RESFACTOR;\n\tint d_cancel_h = 9 * RESFACTOR;\n\tint d_cancel_x = d_dialog_x + ((d_dialog_w * 4) / 5) - (d_cancel_w / 2);\n\tint d_cancel_y = d_dialog_y + d_dialog_h - d_cancel_h - d_margin - 4*RESFACTOR;\n\n#if (GERMAN | FRENCH)\n\tint d_advanced_w = 50*RESFACTOR;\n#else\n\tint d_advanced_w = 40*RESFACTOR;\n#endif\n\tint d_advanced_h = 9*RESFACTOR;\n\tint d_advanced_x = d_dialog_x + ((d_dialog_w) / 2) - (d_advanced_w / 2);\n\tint d_advanced_y = d_dialog_y + d_dialog_h - d_advanced_h - d_margin - 4 *RESFACTOR;\n\n\t/*\n\t** Button Enumerations\n\t*/\n\tenum {\n\t\tBUTTON_PORT = 100,\n\t\tBUTTON_PORTLIST,\n\t\tBUTTON_IRQ,\n\t\tBUTTON_IRQLIST,\n\t\tBUTTON_BAUD,\n\t\tBUTTON_BAUDLIST,\n\t\tBUTTON_INITSTR,\n\t\tBUTTON_INITSTRLIST,\n\t\tBUTTON_ADD,\n\t\tBUTTON_DELETE,\n\t\tBUTTON_CWAITSTR,\n\t\tBUTTON_CWAITSTRLIST,\n\t\tBUTTON_TONE,\n\t\tBUTTON_PULSE,\n\t\tBUTTON_SAVE,\n\t\tBUTTON_ADVANCED,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t/*\n\t** Redraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\tstatic char *portname[4] = {\n\t\t\"COM1 - 3F8\",\n\t\t\"COM2 - 2F8\",\n\t\t\"COM3 - 3E8\",\n\t\t\"COM4 - 2E8\",\n\t};\n\n\tstatic char custom_port[10 + MODEM_NAME_MAX] = {\"CUSTOM - ????\"};\n\n\n\n#ifndef WIN32\t\t// No IRQ dialog in Win version\n\tstatic char *irqname[5] = {\n\t\t\"2 / 9\",\n\t\t\"3 - [COM2 & 4]\",\n\t\t\"4 - [COM1 & 3]\",\n\t\t\"5\",\n\t\t\"CUSTOM - ??\"\n\t};\n\n\tstatic int _irqidx[4] = {\n\t\t2,\n\t\t1,\n\t\t2,\n\t\t1\n\t};\n\n#endif\t//WIN32\n\n#ifdef WIN32\n\tstatic char *baudname[5] = {\n\t\t\"14400\",\n\t\t\"19200\",\n\t\t\"28800\",\n\t\t\"38400\",\n\t\t\"57600\",\n\t};\n\n\tstatic char modemnames[10][MODEM_NAME_MAX];\n\n#else\t//WIN32\n\tstatic char *baudname[5] = {\n\t\t\"9600\",\n\t\t\"14400\",\n\t\t\"19200\",\n\t\t\"28800\",\n\t\t\"38400\"\n\t};\n#endif\t//WIN32\n\t/*\n\t** Dialog variables\n\t*/\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\tchar * item;\t\t\t\t\t\t\t\t// general-purpose string\n\tchar * temp;\t\t\t\t\t\t\t\t// general-purpose string\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\tchar portbuf[ PORTBUF_MAX ] = {0};\t// buffer for port\n\tchar irqbuf[ IRQBUF_MAX ] = {0};\t\t// buffer for irq\n\tchar baudbuf[ BAUDBUF_MAX ] = {0};\t// buffer for baud\n\tchar initstrbuf[ INITSTRBUF_MAX ] = {0};\t\t// buffer for init string\n\tchar cwaitstrbuf[ CWAITSTRBUF_MAX ] = {0};\t// buffer for call waiting string\n\n\tint port_index = 1;\t// index of currently-selected port (default = com2)\n\tint port_custom_index = 4;\t//index of custom entry in port list\n\tint irq_index = 1;\t// index of currently-selected irq (default = 3)\n\tint baud_index = 1;\t// index of currently-selected baud (default = 19200)\n\tint initstr_index = 0;\t// index of currently-selected modem init (default = \"ATZ\")\n\tint cwaitstr_index = CALL_WAIT_CUSTOM;\t// index of currently-selected call waiting (default = \"\")\n\tint rc = 0;\t\t\t\t\t\t\t\t\t// -1 = user cancelled, 1 = New\n\tint i;\t\t\t\t\t\t\t\t\t\t// loop counter\n\tint pos;\n\tint len;\n\tbool firsttime = true;\n\tSerialSettingsType tempsettings;\n\tDetectPortType dpstatus;\n\n\t/*\n\t** Buttons\n\t*/\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tEditClass port_edt (BUTTON_PORT, portbuf, PORTBUF_MAX,\n\t\tTPF_TEXT, d_port_x, d_port_y, d_port_w, d_port_h, EditClass::ALPHANUMERIC);\n\n\tListClass portlist(BUTTON_PORTLIST, d_portlist_x, d_portlist_y, d_portlist_w, d_portlist_h,\n\t\tTPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n#ifndef WIN32\n\tEditClass irq_edt (BUTTON_IRQ, irqbuf, IRQBUF_MAX, TPF_TEXT, d_irq_x, d_irq_y, d_irq_w, d_irq_h, EditClass::NUMERIC);\n\n\tListClass irqlist(BUTTON_IRQLIST, d_irqlist_x, d_irqlist_y, d_irqlist_w, d_irqlist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n#endif\t//WIN32\n\n\tEditClass baud_edt (BUTTON_BAUD, baudbuf, BAUDBUF_MAX, TPF_TEXT, d_baud_x, d_baud_y, d_baud_w, d_baud_h, EditClass::NUMERIC);\n\tListClass baudlist(BUTTON_BAUDLIST, d_baudlist_x, d_baudlist_y, d_baudlist_w, d_baudlist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tEditClass initstr_edt (BUTTON_INITSTR, initstrbuf, INITSTRBUF_MAX, TPF_TEXT, d_initstr_x, d_initstr_y, d_initstr_w, d_initstr_h, EditClass::ALPHANUMERIC);\n\tListClass initstrlist(BUTTON_INITSTRLIST, d_initstrlist_x, d_initstrlist_y, d_initstrlist_w, d_initstrlist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tTextButtonClass addbtn(BUTTON_ADD, TXT_ADD, TPF_BUTTON, d_add_x, d_add_y, d_add_w, d_add_h);\n\tTextButtonClass deletebtn(BUTTON_DELETE, TXT_DELETE_BUTTON, TPF_BUTTON, d_delete_x, d_delete_y, d_delete_w, d_delete_h);\n\tEditClass cwaitstr_edt (BUTTON_CWAITSTR, cwaitstrbuf, CWAITSTRBUF_MAX, TPF_TEXT, d_cwaitstr_x, d_cwaitstr_y, d_cwaitstr_w, d_cwaitstr_h, EditClass::ALPHANUMERIC);\n\tListClass cwaitstrlist(BUTTON_CWAITSTRLIST, d_cwaitstrlist_x, d_cwaitstrlist_y, d_cwaitstrlist_w, d_cwaitstrlist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tTextButtonClass tonebtn(BUTTON_TONE, TXT_TONE_BUTTON, TPF_BUTTON, d_tone_x, d_tone_y, d_tone_w, d_tone_h);\n\tTextButtonClass pulsebtn(BUTTON_PULSE, TXT_PULSE_BUTTON, TPF_BUTTON, d_pulse_x, d_pulse_y, d_pulse_w, d_pulse_h);\n\tTextButtonClass savebtn(BUTTON_SAVE, TXT_SAVE_BUTTON, TPF_BUTTON, d_save_x, d_save_y, d_save_w, d_save_h);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n#ifdef WIN32\n\tTextButtonClass advancedbutton(BUTTON_ADVANCED, TXT_ADVANCED, TPF_BUTTON, d_advanced_x, d_advanced_y, d_advanced_w, d_advanced_h);\n#endif\t//WIN32\n\t/*\n\t** Various Inits\n\t*/\n\tmemcpy( &tempsettings, settings, sizeof(SerialSettingsType) );\n\n\tif (tempsettings.Port == 0) {\n\t\ttempsettings.Port = 0x2f8;\n\t}\n\n\tif (tempsettings.IRQ == -1) {\n\t\ttempsettings.IRQ = 3;\n\t}\n\n\tif (tempsettings.Baud == -1) {\n#ifdef WIN32\n\t\ttempsettings.Baud = 19200;\n#else\t//WIN32\n\t\ttempsettings.Baud = 9600;\n#endif\t//WIN32\n\t}\n\n\n\t/*\n\t** Set the current indices\n\t*/\n#ifndef WIN32\n\tswitch ( tempsettings.IRQ ) {\n\t\tcase ( 2 ):\n\t\t\tirq_index = 0;\n\t\t\tstrcpy (irqbuf, \"2\");\n\t\t\tbreak;\n\n\t\tcase ( 3 ):\n\t\t\tirq_index = 1;\n\t\t\tstrcpy (irqbuf, \"3\");\n\t\t\tbreak;\n\n\t\tcase ( 4 ):\n\t\t\tirq_index = 2;\n\t\t\tstrcpy (irqbuf, \"4\");\n\t\t\tbreak;\n\n\t\tcase ( 5 ):\n\t\t\tirq_index = 3;\n\t\t\tstrcpy (irqbuf, \"5\");\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tirq_index = 4;\n\t\t\tsprintf (irqbuf, \"%d\", tempsettings.IRQ);\n\t\t\ttemp = strchr( irqname[4], '-' );\n\t\t\tif ( temp ) {\n\t\t\t\tpos = (int)(temp - irqname[4]) + 2;\n\t\t\t\tlen = strlen( irqbuf );\n\t\t\t\tstrncpy( irqname[4] + pos, irqbuf, len );\n\t\t\t\t*(irqname[4] + pos + len) = 0;\n\t\t\t}\n\t\t\tbreak;\n\t}\n#endif\t//WIN32\n\n#ifdef WIN32\n\tif (tempsettings.Baud == 14400) {\n\t\tbaud_index = 0;\n\t} else if (tempsettings.Baud == 19200) {\n\t\tbaud_index = 1;\n\t} else if (tempsettings.Baud == 28800) {\n\t\tbaud_index = 2;\n\t} else if (tempsettings.Baud == 38400) {\n\t\tbaud_index = 3;\n\t} else {\n\t\tbaud_index = 4;\n\t}\n#else\t//WIN32\n\tif (tempsettings.Baud == 9600) {\n\t\tbaud_index = 0;\n\t} else if (tempsettings.Baud == 14400) {\n\t\tbaud_index = 1;\n\t} else if (tempsettings.Baud == 19200) {\n\t\tbaud_index = 2;\n\t} else if (tempsettings.Baud == 28800) {\n\t\tbaud_index = 3;\n\t} else {\n\t\tbaud_index = 4;\n\t}\n#endif\t//WIN32\n\tsprintf (baudbuf, \"%d\", tempsettings.Baud);\n\n\t/*\n\t** Set up the port list box & edit box\n\t*/\n\tfor (i = 0; i < 4; i++) {\n\t\tportlist.Add_Item( portname[ i ] );\n\t}\n\n#ifdef WIN32\n\t/*\n\t** Loop through the first 10 possible modem entries in the registry. Frankly, its just\n\t** tough luck if the user has more than 10 modems attached!\n\t*/\n\tif (ModemRegistry) {\n\t\tdelete ModemRegistry;\n\t}\n\tint modems_found = 0;\n\tfor (i=0 ; i<10 ; i++) {\n\t\tModemRegistry = new ModemRegistryEntryClass (i);\n\t\tif (ModemRegistry->Get_Modem_Name()) {\n\t\t\tstrncpy (modemnames[modems_found], ModemRegistry->Get_Modem_Name(), MODEM_NAME_MAX);\n\t\t\tportlist.Add_Item( modemnames [modems_found++] );\n\t\t\tport_custom_index ++;\n\t\t}\n\t\tdelete ModemRegistry;\n\t}\n\tModemRegistry = NULL;\n\n#endif\t//WIN32\n\n\tportlist.Add_Item ( custom_port );\n\n\n\t/*\n\t** Work out the current port index\n\t*/\n\tport_index = -1;\n#ifdef WIN32\n\tif (tempsettings.ModemName[0]) {\n\t\tfor ( i=0 ; i<port_custom_index ; i++) {\n\t\t\tif (!stricmp (portlist.Get_Item(i), tempsettings.ModemName)) {\n\t\t\t\tport_index = i;\n\t\t\t\tstrcpy (portbuf, tempsettings.ModemName);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t/*\n\t\t** The modem name specified wasnt in the registry so add it as a custom entry\n\t\t*/\n\t\tif (port_index == -1) {\n\t\t\ttemp = strchr( custom_port, '-' );\n\t\t\tif ( temp ) {\n\t\t\t\tpos = (int)(temp - custom_port) + 2;\n\t\t\t\tlen = strlen( tempsettings.ModemName );\n\t\t\t\tstrncpy( custom_port + pos, tempsettings.ModemName, len );\n\t\t\t\t*(custom_port + pos + len) = 0;\n\t\t\t\tstrcpy (portbuf, tempsettings.ModemName);\n\t\t\t\tport_index = port_custom_index;\n\t\t\t}\n\t\t}\n\t}\n#endif\t//WIN32\n\n\tif (port_index == -1) {\n\t\tswitch ( tempsettings.Port ) {\n\t\t\tcase ( 0x3f8 ):\n\t\t\t\tport_index = 0;\n\t\t\t\tstrcpy (portbuf, \"COM1\");\n\t\t\t\tbreak;\n\n\t\t\tcase ( 0x2f8 ):\n\t\t\t\tport_index = 1;\n\t\t\t\tstrcpy (portbuf, \"COM2\");\n\t\t\t\tbreak;\n\n\t\t\tcase ( 0x3e8 ):\n\t\t\t\tport_index = 2;\n\t\t\t\tstrcpy (portbuf, \"COM3\");\n\t\t\t\tbreak;\n\n\t\t\tcase ( 0x2e8 ):\n\t\t\t\tport_index = 3;\n\t\t\t\tstrcpy (portbuf, \"COM4\");\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tport_index = port_custom_index;\n\t\t\t\tsprintf (portbuf, \"%x\", tempsettings.Port);\n\t\t\t\ttemp = strchr( custom_port, '-' );\n\t\t\t\tif ( temp ) {\n\t\t\t\t\tpos = (int)(temp - custom_port) + 2;\n\t\t\t\t\tlen = strlen( portbuf );\n\t\t\t\t\tstrncpy( custom_port + pos, portbuf, len );\n\t\t\t\t\t*(custom_port + pos + len) = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tportlist.Set_Selected_Index( port_index );\n\n\n\n\t/*\n\t** Set up the port edit box\n\t*/\n\tport_edt.Set_Text( portbuf, PORTBUF_MAX );\n#ifndef WIN32\n\t/*\n\t** Set up the IRQ list box & edit box\n\t*/\n\tfor (i = 0; i < 5; i++) {\n\t\tirqlist.Add_Item( irqname[ i ] );\n\t}\n\n\tirqlist.Set_Selected_Index( irq_index );\n\tirq_edt.Set_Text( irqbuf, IRQBUF_MAX );\n#endif\t//WIN32\n\t/*\n\t** Set up the baud rate list box & edit box\n\t*/\n\tfor (i = 0; i < 5; i++) {\n\t\tbaudlist.Add_Item( baudname[ i ] );\n\t}\n\n\tbaudlist.Set_Selected_Index( baud_index );\n\tbaud_edt.Set_Text( baudbuf, BAUDBUF_MAX );\n\n\tinitstr_index = tempsettings.InitStringIndex;\n\tBuild_Init_String_Listbox(&initstrlist, &initstr_edt, initstrbuf, &initstr_index);\n\n\t/*\n\t** Set up the cwait rate list box & edit box\n\t*/\n\tcwaitstr_index = tempsettings.CallWaitStringIndex;\n\tfor (i = 0; i < CALL_WAIT_STRINGS_NUM; i++) {\n\t\tif ( i == CALL_WAIT_CUSTOM ) {\n\t\t\titem = Session.CallWaitStrings[ i ];\n\t\t\ttemp = strchr( item, '-' );\n\t\t\tif ( temp ) {\n\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\tlen = strlen( tempsettings.CallWaitString );\n\t\t\t\tstrncpy( item + pos, tempsettings.CallWaitString, len );\n\t\t\t\t*(item + pos + len) = 0;\n\t\t\t\tif (i == cwaitstr_index) {\n\t\t\t\t\tstrncpy( cwaitstrbuf, item + pos, CWAITSTRBUF_MAX );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (i == cwaitstr_index) {\n\t\t\tstrncpy( cwaitstrbuf, Session.CallWaitStrings[ i ], CWAITSTRBUF_MAX );\n\t\t}\n\t\tcwaitstrlist.Add_Item( Session.CallWaitStrings[ i ] );\n\t}\n\n\tcwaitstrlist.Set_Selected_Index( cwaitstr_index );\n\tcwaitstr_edt.Set_Text( cwaitstrbuf, CWAITSTRBUF_MAX );\n\n\t/*\n\t** Build the button list\n\t*/\n\tcommands = &cancelbtn;\n\tport_edt.Add_Tail(*commands);\n\tportlist.Add_Tail(*commands);\n#ifndef WIN32\n\tirq_edt.Add_Tail(*commands);\n\tirqlist.Add_Tail(*commands);\n#endif\t//WIN32\n\tbaud_edt.Add_Tail(*commands);\n\tbaudlist.Add_Tail(*commands);\n\tinitstr_edt.Add_Tail(*commands);\n\tinitstrlist.Add_Tail(*commands);\n\taddbtn.Add_Tail(*commands);\n\tdeletebtn.Add_Tail(*commands);\n\tcwaitstr_edt.Add_Tail(*commands);\n\tcwaitstrlist.Add_Tail(*commands);\n\ttonebtn.Add_Tail(*commands);\n\tpulsebtn.Add_Tail(*commands);\n\tsavebtn.Add_Tail(*commands);\n#ifdef WIN32\n\tadvancedbutton.Add_Tail(*commands);\n#endif\t//WIN32\n\n\tif (tempsettings.DialMethod == DIAL_TOUCH_TONE) {\n\t\ttonebtn.Turn_On();\n\t} else {\n\t\tpulsebtn.Turn_On();\n\t}\n\n\t/*\n\t** Processing loop\n\t*/\n\twhile (process) {\n\t\t/*\n\t\t** Invoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t** Dont allow editing of non-custom ports to fix the problem of the cursor appearing\n\t\t** outside the edit box.\n\t\t*/\n\t\tif (port_index == port_custom_index) {\n\t\t\tport_edt.Set_Read_Only(false);\n\t\t}else{\n\t\t\tport_edt.Set_Read_Only(true);\n\t\t}\n\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n#endif\n\t\t/*\n\t\t** Refresh display if needed\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\t\t\t/*\n\t\t\t** Redraw backgound & dialog box\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tCCPalette.Set();\n\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t// init font variables\n\n\t\t\t\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_CENTER | TPF_TEXT);\n\n\t\t\t\t/*\n\t\t\t\t** Dialog & Field labels\n\t\t\t\t*/\n\t\t\t\tDraw_Caption(TXT_SETTINGS, d_dialog_x, d_dialog_y, d_dialog_w);\n\n\t\t\t\tFancy_Text_Print(TXT_PORT_COLON, d_port_x - 3 * RESFACTOR, d_port_y + 1 * RESFACTOR, scheme, TBLACK, TPF_RIGHT | TPF_TEXT);\n#ifndef WIN32\n\t\t\t\tFancy_Text_Print(TXT_IRQ_COLON, d_irq_x - 3 * RESFACTOR, d_irq_y + 1 * RESFACTOR, scheme, TBLACK, TPF_RIGHT | TPF_TEXT);\n#endif\t//WIN32\n\t\t\t\tFancy_Text_Print(TXT_BAUD_COLON, d_baud_x - 3 * RESFACTOR, d_baud_y + 1 * RESFACTOR, scheme, TBLACK, TPF_RIGHT | TPF_TEXT);\n\n\t\t\t\tFancy_Text_Print(TXT_INIT_STRING, d_initstr_x, d_initstr_y - d_txt6_h - 3 * RESFACTOR, scheme, TBLACK, TPF_TEXT);\n\n\t\t\t\tFancy_Text_Print(TXT_CWAIT_STRING, d_cwaitstr_x, d_cwaitstr_y - d_txt6_h - 3 * RESFACTOR, scheme, TBLACK, TPF_TEXT);\n\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Redraw buttons\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcancelbtn.Flag_To_Redraw();\n\t\t\t\tport_edt.Flag_To_Redraw();\n\t\t\t\tportlist.Flag_To_Redraw();\n#ifndef WIN32\n\t\t\t\tirq_edt.Flag_To_Redraw();\n\t\t\t\tirqlist.Flag_To_Redraw();\n#endif\t//WIN32\n\t\t\t\tbaud_edt.Flag_To_Redraw();\n\t\t\t\tbaudlist.Flag_To_Redraw();\n#ifdef WIN32\n\t\t\t\tadvancedbutton.Flag_To_Redraw();\n#endif\t//WIN32\n\t\t\t\tinitstr_edt.Flag_To_Redraw();\n\t\t\t\tinitstrlist.Flag_To_Redraw();\n\t\t\t\taddbtn.Flag_To_Redraw();\n\t\t\t\tdeletebtn.Flag_To_Redraw();\n\t\t\t\tcwaitstr_edt.Flag_To_Redraw();\n\t\t\t\tcwaitstrlist.Flag_To_Redraw();\n\t\t\t\ttonebtn.Flag_To_Redraw();\n\t\t\t\tpulsebtn.Flag_To_Redraw();\n\t\t\t\tsavebtn.Flag_To_Redraw();\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t** Get user input\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\tif ( firsttime ) {\n//\t\t\tport_edt.Set_Focus();\n\t\t\tport_edt.Flag_To_Redraw();\n\t\t\tinput = commands->Input();\n\t\t\tfirsttime = false;\n\t\t}\n\n\t\t/*\n\t\t** Process input\n\t\t*/\n\t\tswitch (input) {\n\n#ifdef WIN32\n\t\t\tcase (BUTTON_ADVANCED | KN_BUTTON):\n\t\t\t\tAdvanced_Modem_Settings (&tempsettings);\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbreak;\n#endif\t//WIN32\n\n\t\t\tcase (BUTTON_PORT | KN_BUTTON):\n\t\t\t\titem = (char *)portlist.Current_Item();\n\t\t\t\tif (port_index < 4) {\n\t\t\t\t\ttemp = strchr( item, ' ' );\n\t\t\t\t\tif ( !temp ) {\n\t\t\t\t\t\tstrncpy( portbuf, item, PORTBUF_MAX );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpos = (int)(temp - item);\n\t\t\t\t\t\tstrncpy( portbuf, item, pos );\n\t\t\t\t\t\tportbuf[pos] = 0;\n\t\t\t\t\t}\n\t\t\t\t\tport_edt.Set_Text( portbuf, PORTBUF_MAX );\n\t\t\t\t\tport_edt.Flag_To_Redraw();\n#ifndef WIN32\n\t\t\t\t\tirq_edt.Set_Focus();\n\t\t\t\t\tirq_edt.Flag_To_Redraw();\n#endif\t//WIN32\n\t\t\t\t} else {\n\t\t\t\t\tstrupr( portbuf );\n\t\t\t\t\tif ( stricmp(portbuf, \"3F8\") == 0 ) {\n\t\t\t\t\t\tport_index = 0;\n\t\t\t\t\t\tportlist.Set_Selected_Index( port_index );\n\t\t\t\t\t\tstrcpy (portbuf, \"COM1\");\n\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\n\t\t\t\t\t} else if ( stricmp(portbuf, \"2F8\") == 0 ) {\n\t\t\t\t\t\tport_index = 1;\n\t\t\t\t\t\tportlist.Set_Selected_Index( port_index );\n\t\t\t\t\t\tstrcpy (portbuf, \"COM2\");\n\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\n\t\t\t\t\t} else if ( stricmp(portbuf, \"3E8\") == 0 ) {\n\t\t\t\t\t\tport_index = 2;\n\t\t\t\t\t\tportlist.Set_Selected_Index( port_index );\n\t\t\t\t\t\tstrcpy (portbuf, \"COM3\");\n\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\n\t\t\t\t\t} else if ( stricmp(portbuf, \"2E8\") == 0 ) {\n\t\t\t\t\t\tport_index = 3;\n\t\t\t\t\t\tportlist.Set_Selected_Index( port_index );\n\t\t\t\t\t\tstrcpy (portbuf, \"COM4\");\n\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\n\t\t\t\t\t} else if ( strncmp(portbuf, \"COM\", 3) == 0 ) {\n\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\n\t\t\t\t\t\tswitch ( (portbuf[3] - '0') ) {\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\tport_index = 0;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\tport_index = 1;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\tport_index = 2;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\t\tport_index = 3;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n#ifdef WIN32\n\t\t\t\t\t\t\t\tif (portbuf[3] <= '9' && portbuf[3] >'0') {\n\t\t\t\t\t\t\t\t\tportbuf[4] = 0;\n\t\t\t\t\t\t\t\t\tport_index = port_custom_index;\n\t\t\t\t\t\t\t\t\ttemp = strchr( item, '-' );\n\t\t\t\t\t\t\t\t\tif ( temp ) {\n\t\t\t\t\t\t\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\t\t\t\t\t\t\tlen = strlen( portbuf );\n\t\t\t\t\t\t\t\t\t\tstrncpy( item + pos, portbuf, len );\n\t\t\t\t\t\t\t\t\t\t*(item + pos + len) = 0;\n\t\t\t\t\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n#endif\t//WIN32\n\t\t\t\t\t\t\t\tWWMessageBox().Process( TXT_INVALID_PORT_ADDRESS );\n\t\t\t\t\t\t\t\tport_edt.Set_Focus();\n\t\t\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tportlist.Set_Selected_Index( port_index );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttemp = strchr( item, '-' );\n\t\t\t\t\t\tif ( temp ) {\n\t\t\t\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\t\t\t\tlen = strlen( portbuf );\n\t\t\t\t\t\t\tstrncpy( item + pos, portbuf, len );\n\t\t\t\t\t\t\t*(item + pos + len) = 0;\n\t\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n#ifndef WIN32\n\t\t\t\t\tif (display == REDRAW_BUTTONS) {\n\t\t\t\t\t\tirq_edt.Set_Focus();\n\t\t\t\t\t\tirq_edt.Flag_To_Redraw();\n\t\t\t\t\t}\n#endif\t//WIN32\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_PORTLIST | KN_BUTTON):\n\t\t\t\tif (portlist.Current_Index() != port_index) {\n\t\t\t\t\tport_index = portlist.Current_Index();\n\t\t\t\t\titem = (char *)portlist.Current_Item();\n\t\t\t\t\tif (port_index < 4) {\n\t\t\t\t\t\ttemp = strchr( item, ' ' );\n\t\t\t\t\t\tpos = (int)(temp - item);\n\t\t\t\t\t\tstrncpy( portbuf, item, pos );\n\t\t\t\t\t\tportbuf[pos] = 0;\n\t\t\t\t\t\tport_edt.Clear_Focus();\n\n\t\t\t\t\t\t// auto select the irq for port\n#ifndef WIN32\n\t\t\t\t\t\tirq_index = _irqidx[ port_index ];\n\t\t\t\t\t\tirqlist.Set_Selected_Index( irq_index );\n\t\t\t\t\t\titem = (char *)irqlist.Current_Item();\n\t\t\t\t\t\ttemp = strchr( item, ' ' );\n\t\t\t\t\t\tif ( !temp ) {\n\t\t\t\t\t\t\tstrncpy( irqbuf, item, 2 );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tpos = (int)(temp - item);\n\t\t\t\t\t\t\tstrncpy( irqbuf, item, pos );\n\t\t\t\t\t\t\tirqbuf[pos] = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tirq_edt.Clear_Focus();\n#endif\t//WIN32\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (port_index == port_custom_index) {\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** This is the custom entry\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\ttemp = strchr( item, '-' );\n\t\t\t\t\t\t\tif ( temp ) {\n\t\t\t\t\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\t\t\t\t\tif ( *(item + pos) == '?' ) {\n\t\t\t\t\t\t\t\t\tportbuf[0] = 0;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstrncpy( portbuf, item + pos, PORTBUF_MAX );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tport_edt.Set_Focus();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Must be a modem name entry so just copy iy\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tstrncpy (portbuf, item, PORTBUF_MAX);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tport_edt.Set_Text( portbuf, PORTBUF_MAX );\n\t\t\t\t} else if (port_index < port_custom_index) {\n\t\t\t\t\tport_edt.Clear_Focus();\n\t\t\t\t} else {\n\t\t\t\t\tport_edt.Set_Focus();\n\t\t\t\t}\n\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n#ifndef WIN32\n\t\t\tcase (BUTTON_IRQ | KN_BUTTON):\n\t\t\t\titem = (char *)irqlist.Current_Item();\n\t\t\t\tif (irq_index < 4) {\n\t\t\t\t\ttemp = strchr( item, ' ' );\n\t\t\t\t\tif ( !temp ) {\n\t\t\t\t\t\tstrncpy( irqbuf, item, IRQBUF_MAX );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpos = (int)(temp - item);\n\t\t\t\t\t\tstrncpy( irqbuf, item, pos );\n\t\t\t\t\t\tirqbuf[pos] = 0;\n\t\t\t\t\t}\n\t\t\t\t\tirq_edt.Set_Text( irqbuf, IRQBUF_MAX );\n\t\t\t\t\tirq_edt.Flag_To_Redraw();\n\t\t\t\t} else {\n\t\t\t\t\ttemp = strchr( item, '-' );\n\t\t\t\t\tif ( temp ) {\n\t\t\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\t\t\tlen = strlen( irqbuf );\n\t\t\t\t\t\tstrncpy( item + pos, irqbuf, len );\n\t\t\t\t\t\t*(item + pos + len) = 0;\n\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbaud_edt.Set_Focus();\n\t\t\t\tbaud_edt.Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_IRQLIST | KN_BUTTON):\n\t\t\t\tif (irqlist.Current_Index() != irq_index) {\n\t\t\t\t\tirq_index = irqlist.Current_Index();\n\t\t\t\t\titem = (char *)irqlist.Current_Item();\n\t\t\t\t\tif (irq_index < 4) {\n\t\t\t\t\t\ttemp = strchr( item, ' ' );\n\t\t\t\t\t\tif ( !temp ) {\n\t\t\t\t\t\t\tstrncpy( irqbuf, item, IRQBUF_MAX );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tpos = (int)(temp - item);\n\t\t\t\t\t\t\tstrncpy( irqbuf, item, pos );\n\t\t\t\t\t\t\tirqbuf[pos] = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tirq_edt.Clear_Focus();\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttemp = strchr( item, '-' );\n\t\t\t\t\t\tif ( temp ) {\n\t\t\t\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\t\t\t\tif ( *(item + pos) == '?' ) {\n\t\t\t\t\t\t\t\tirqbuf[0] = 0;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tstrncpy( irqbuf, item + pos, IRQBUF_MAX );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tirq_edt.Set_Focus();\n\t\t\t\t\t}\n\t\t\t\t\tirq_edt.Set_Text( irqbuf, IRQBUF_MAX );\n\t\t\t\t} else if (irq_index < 4) {\n\t\t\t\t\tirq_edt.Clear_Focus();\n\t\t\t\t} else {\n\t\t\t\t\tirq_edt.Set_Focus();\n\t\t\t\t}\n\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n#endif\t//WIN32\n\t\t\tcase (BUTTON_BAUD | KN_BUTTON):\n\t\t\t\titem = (char *)baudlist.Current_Item();\n\t\t\t\tstrncpy( baudbuf, item, BAUDBUF_MAX );\n\t\t\t\tbaud_edt.Set_Text( baudbuf, BAUDBUF_MAX );\n\t\t\t\tinitstr_edt.Set_Focus();\n\t\t\t\tinitstr_edt.Flag_To_Redraw();\n\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_BAUDLIST | KN_BUTTON):\n\t\t\t\tif (baudlist.Current_Index() != baud_index) {\n\t\t\t\t\tbaud_index = baudlist.Current_Index();\n\t\t\t\t\titem = (char *)baudlist.Current_Item();\n\t\t\t\t\tstrncpy( baudbuf, item, BAUDBUF_MAX );\n\t\t\t\t\tbaud_edt.Set_Text( baudbuf, BAUDBUF_MAX );\n\t\t\t\t\tbaud_edt.Clear_Focus();\n\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n#if 0\n\t\t\tcase (BUTTON_INITSTR | KN_BUTTON):\n\t\t\t\tstrupr( initstrbuf );\n\t\t\t\tstrncpy( Session.InitStrings[ initstr_index ], initstrbuf, INITSTRBUF_MAX );\n\t\t\t\tBuild_Init_String_Listbox(&initstrlist, &initstr_edt, initstrbuf,\n\t\t\t\t\t&initstr_index);\n\t\t\t\tcwaitstr_edt.Set_Focus();\n\t\t\t\tcwaitstr_edt.Flag_To_Redraw();\n\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n#endif\n\n\t\t\tcase (BUTTON_INITSTRLIST | KN_BUTTON):\n\t\t\t\tif (initstrlist.Current_Index() != initstr_index) {\n\t\t\t\t\tinitstr_index = initstrlist.Current_Index();\n\t\t\t\t\titem = (char *)initstrlist.Current_Item();\n\t\t\t\t\tstrncpy( initstrbuf, item, INITSTRBUF_MAX );\n\t\t\t\t\tinitstr_edt.Set_Text( initstrbuf, INITSTRBUF_MAX );\n\t\t\t\t}\n\t\t\t\tinitstr_edt.Set_Focus();\n\t\t\t\tinitstr_edt.Flag_To_Redraw();\n\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t** Add a new InitString entry\n\t\t\t*/\n\t\t\tcase (BUTTON_ADD | KN_BUTTON):\n\n\t\t\t\titem = new char[ INITSTRBUF_MAX ];\n\t\t\t\tmemset (item, 0, INITSTRBUF_MAX);\n\n\t\t\t\tstrupr ( initstrbuf );\n\t\t\t\tstrncpy ( item, initstrbuf, INITSTRBUF_MAX-1 );\n\n\t\t\t\tSession.InitStrings.Add ( item );\n\t\t\t\tBuild_Init_String_Listbox (&initstrlist, &initstr_edt, initstrbuf,\n\t\t\t\t\t&initstr_index);\n\t\t\t\t/*............................................................\n\t\t\t\tSet the current listbox index to the newly-added item.\n\t\t\t\t............................................................*/\n\t\t\t\tfor (i = 0; i < Session.InitStrings.Count(); i++) {\n\t\t\t\t\tif (item == Session.InitStrings[i]) {\n\t\t\t\t\t\tinitstr_index = i;\n\t\t\t\t\t\tstrcpy( initstrbuf, Session.InitStrings[ initstr_index ] );\n\t\t\t\t\t\tinitstr_edt.Set_Text( initstrbuf, INITSTRBUF_MAX );\n\t\t\t\t\t\tinitstrlist.Set_Selected_Index( initstr_index );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tinitstr_edt.Set_Focus();\n\t\t\t\tinitstr_edt.Flag_To_Redraw();\n\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tDelete the current InitString entry\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_DELETE | KN_BUTTON):\n\n\t\t\t\tif ( Session.InitStrings.Count() && initstr_index != -1) {\n\t\t\t\t\tSession.InitStrings.Delete( initstr_index );\n\t\t\t\t\tBuild_Init_String_Listbox(&initstrlist, &initstr_edt, initstrbuf,\n\t\t\t\t\t\t&initstr_index);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_CWAITSTR | KN_BUTTON):\n\t\t\t\titem = (char *)cwaitstrlist.Current_Item();\n\t\t\t\tif (cwaitstr_index < 3) {\n\t\t\t\t} else {\n\t\t\t\t\ttemp = strchr( item, '-' );\n\t\t\t\t\tif ( temp ) {\n\t\t\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\t\t\tlen = strlen( cwaitstrbuf );\n\t\t\t\t\t\tstrncpy( item + pos, cwaitstrbuf, len );\n\t\t\t\t\t\t*(item + pos + len) = 0;\n\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_CWAITSTRLIST | KN_BUTTON):\n\t\t\t\tif (cwaitstrlist.Current_Index() != cwaitstr_index) {\n\t\t\t\t\tcwaitstr_index = cwaitstrlist.Current_Index();\n\t\t\t\t\titem = (char *)cwaitstrlist.Current_Item();\n\t\t\t\t\tif (cwaitstr_index < 3) {\n\t\t\t\t\t\tstrncpy( cwaitstrbuf, item, CWAITSTRBUF_MAX );\n\t\t\t\t\t\tcwaitstr_edt.Clear_Focus();\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttemp = strchr( item, '-' );\n\t\t\t\t\t\tif ( temp ) {\n\t\t\t\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\t\t\t\tstrncpy( cwaitstrbuf, item + pos, CWAITSTRBUF_MAX );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcwaitstr_edt.Set_Focus();\n\t\t\t\t\t}\n\t\t\t\t\tcwaitstr_edt.Set_Text( cwaitstrbuf, CWAITSTRBUF_MAX );\n\t\t\t\t} else if (cwaitstr_index < 3) {\n\t\t\t\t\tcwaitstr_edt.Clear_Focus();\n\t\t\t\t} else {\n\t\t\t\t\tcwaitstr_edt.Set_Focus();\n\t\t\t\t}\n\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_TONE | KN_BUTTON):\n\t\t\t\ttempsettings.DialMethod = DIAL_TOUCH_TONE;\n\t\t\t\ttonebtn.Turn_On();\n\t\t\t\tpulsebtn.Turn_Off();\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_PULSE | KN_BUTTON):\n\t\t\t\ttempsettings.DialMethod = DIAL_PULSE;\n\t\t\t\ttonebtn.Turn_Off();\n\t\t\t\tpulsebtn.Turn_On();\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tSAVE: save the com settings\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (KN_RETURN):\n\t\t\tcase (BUTTON_SAVE | KN_BUTTON):\n\t\t\t\tswitch (port_index) {\n\t\t\t\t\tcase ( 0 ):\n\t\t\t\t\t\ttempsettings.Port = 0x3f8;\n\t\t\t\t\t\ttempsettings.ModemName[0] = 0;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase ( 1 ):\n\t\t\t\t\t\ttempsettings.Port = 0x2f8;\n\t\t\t\t\t\ttempsettings.ModemName[0] = 0;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase ( 2 ):\n\t\t\t\t\t\ttempsettings.Port = 0x3e8;\n\t\t\t\t\t\ttempsettings.ModemName[0] = 0;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase ( 3 ):\n\t\t\t\t\t\ttempsettings.Port = 0x2e8;\n\t\t\t\t\t\ttempsettings.ModemName[0] = 0;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tif (port_index == port_custom_index) {\n#ifdef WIN32\n\t\t\t\t\t\t\tstrncpy ( tempsettings.ModemName, portbuf, MODEM_NAME_MAX );\n\t\t\t\t\t\t\ttempsettings.Port = 1;\n#else\t//WIN32\n\t\t\t\t\t\t\tsscanf( portbuf, \"%x\", &tempsettings.Port );\n\t\t\t\t\t\t\ttempsettings.ModemName[0] = 0;\n#endif\t//WIN32\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Must be a modem name index\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tstrcpy (tempsettings.ModemName, portlist.Current_Item());\n\t\t\t\t\t\t\ttempsettings.Port = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\n#ifndef WIN32\n\t\t\t\tswitch (irq_index) {\n\t\t\t\t\tcase ( 0 ):\n\t\t\t\t\t\ttempsettings.IRQ = 2;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase ( 1 ):\n\t\t\t\t\t\ttempsettings.IRQ = 3;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase ( 2 ):\n\t\t\t\t\t\ttempsettings.IRQ = 4;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase ( 3 ):\n\t\t\t\t\t\ttempsettings.IRQ = 5;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tsscanf( irqbuf, \"%d\", &tempsettings.IRQ );\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n#endif\t//WIN32\n\t\t\t\tsscanf( baudbuf, \"%d\", &tempsettings.Baud );\n\n\t\t\t\ttempsettings.InitStringIndex = initstr_index;\n\t\t\t\ttempsettings.CallWaitStringIndex = cwaitstr_index;\n\n\t\t\t\titem = Session.CallWaitStrings[ CALL_WAIT_CUSTOM ];\n\t\t\t\ttemp = strchr( item, '-' );\n\t\t\t\tif ( temp ) {\n\t\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\t\tstrncpy( cwaitstrbuf, item + pos, CWAITSTRBUF_MAX );\n\t\t\t\t} else {\n\t\t\t\t\tcwaitstrbuf[ 0 ] = 0;\n\t\t\t\t}\n\n\t\t\t\tstrncpy( tempsettings.CallWaitString, cwaitstrbuf, CWAITSTRBUF_MAX );\n\n\t\t\t\tdpstatus = NullModem.Detect_Port( &tempsettings );\n\n\t\t\t\tif (dpstatus == PORT_VALID) {\n\t\t\t\t\tprocess = false;\n\t\t\t\t\trc = true;\n\n\t\t\t\t} else if (dpstatus == PORT_INVALID) {\n#ifdef WIN32\n\t\t\t\t\tWWMessageBox().Process( TXT_UNABLE_TO_OPEN_PORT );\n#else\t//WIN32\n\t\t\t\t\tWWMessageBox().Process( TXT_INVALID_SETTINGS );\n#endif\t//WIN32\n\t\t\t\t\tfirsttime = true;\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\n\t\t\t\t} else if (dpstatus == PORT_IRQ_INUSE) {\n\t\t\t\t\tWWMessageBox().Process( TXT_IRQ_ALREADY_IN_USE );\n\t\t\t\t\tfirsttime = true;\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tCANCEL: send a SIGN_OFF, bail out with error code\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\t\t\t\tbreak;\n\t\t}\n\n\t}\t/* end of while */\n\n\t/*------------------------------------------------------------------------\n\tRestore screen\n\t------------------------------------------------------------------------*/\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n\tShow_Mouse();\n\n\t/*------------------------------------------------------------------------\n\tSave values into the Settings structure\n\t------------------------------------------------------------------------*/\n\tif (rc) {\n\t\tmemcpy( settings, &tempsettings, sizeof(SerialSettingsType) );\n\t}\n\n\treturn(rc);\n\n}\t/* end of Com_Settings_Dialog */\n\n\n/***************************************************************************\n * Build_Init_String_Listbox -- [re]builds the initstring listbox          *\n *                                                                         *\n * This routine rebuilds the initstring list box from scratch; it also\t\t*\n * updates the contents of the initstring edit field.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tlist\t\tptr to list box\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tedit\t\tptr to edit box\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuf\t\tptr to buffer for initstring\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/08/1995 DRD : Created.                                             *\n *=========================================================================*/\nstatic void Build_Init_String_Listbox (ListClass *list, EditClass *edit, char *buf, int *index)\n{\n\tint i, curidx;\n\tchar *item;\n\n\n\tcuridx = *index;\n\n\t/*........................................................................\n\tClear the list\n\t........................................................................*/\n\twhile (list->Count()) {\n\t\titem = (char *)(list->Get_Item(0));\n\t\tlist->Remove_Item(item);\n\t\tdelete [] item;\n\t}\n\n\t/*\n\t** Now sort the init string list by name then number\n\t*/\n\tqsort ((void *)(&Session.InitStrings[0]), Session.InitStrings.Count(), sizeof(char *), Init_String_Compare);\n\n\t/*........................................................................\n\tBuild the list\n\t........................................................................*/\n\tfor (i = 0; i < Session.InitStrings.Count(); i++) {\n\t\titem = new char[ INITSTRBUF_MAX ];\n\t\tstrcpy( item, Session.InitStrings[i] );\n\t\tlist->Add_Item(item);\n\t}\n\tlist->Flag_To_Redraw();\n\n\t/*........................................................................\n\tInit the current phone book index\n\t........................................................................*/\n\tif (list->Count() == 0 || curidx < -1) {\n\t\tcuridx = -1;\n\t} else if (curidx >= list->Count() ) {\n\t\tcuridx = 0;\n\t}\n\n\t/*........................................................................\n\tFill in initstring edit buffer\n\t........................................................................*/\n\tif (curidx > -1) {\n\t\tstrcpy (buf, Session.InitStrings[ curidx ]);\n\t\tedit->Set_Text (buf, INITSTRBUF_MAX );\n\t\tlist->Set_Selected_Index( curidx );\n\t}\n\n\t*index = curidx;\n}\n\n\n/***************************************************************************\n * Init_String_Compare -- for qsort\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tp1,p2\t\tptrs to elements to compare\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = same, -1 = (*p1) goes BEFORE (*p2), 1 = (*p1) goes AFTER (*p2)\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/08/1995 DRD : Created.                                             *\n *=========================================================================*/\nstatic int Init_String_Compare (const void *p1, const void *p2)\n{\n\treturn( strcmp( *((char **)p1), *((char **)p2) ) );\n}\n\n\n/***********************************************************************************************\n * Com_Scenario_Dialog -- Serial game scenario selection dialog\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\ttrue = success, false = cancel\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   02/14/1995 BR : Created.\n *   01/21/97 V.Grippi added check for CS before sending scenario file                                             \t\t\t\t\t\t  *\n *=============================================================================================*/\nint Com_Scenario_Dialog(bool skirmish)\n{\n\t/*........................................................................\n\tDialog & button dimensions\n\t........................................................................*/\n\tint d_dialog_w = 320 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 200 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2);\t\t// dialog x-coord\n\tint d_dialog_y = ((200 * RESFACTOR - d_dialog_h) / 2);\t\t// dialog y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_txt6_h = 6 * RESFACTOR+1;\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_margin1 = 5 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// margin width/height\n\tint d_margin2 = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint d_name_w = 70 * RESFACTOR;\n\tint d_name_h = 9 * RESFACTOR;\n\tint d_name_x = d_dialog_x + (d_dialog_w / 4) - (d_name_w / 2);\n\tint d_name_y = d_dialog_y + d_margin2 + d_txt6_h + 1 * RESFACTOR;\n\n#ifdef OLDWAY\n\tint d_gdi_w = 40 * RESFACTOR;\n\tint d_gdi_h = 9 * RESFACTOR;\n\tint d_gdi_x = d_dialog_cx - d_gdi_w;\n\tint d_gdi_y = d_name_y;\n\n\tint d_nod_w = 40 * RESFACTOR;\n\tint d_nod_h = 9 * RESFACTOR;\n\tint d_nod_x = d_dialog_cx;\n\tint d_nod_y = d_name_y;\n#else\n\tint d_house_w = 60 *RESFACTOR;\n\tint d_house_h = (8 * 5 *RESFACTOR);\n\tint d_house_x = d_dialog_cx - (d_house_w / 2);\n\tint d_house_y = d_name_y;\n#endif\n\n\tint d_color_w = 10 * RESFACTOR;\n\tint d_color_h = 9 * RESFACTOR;\n\tint d_color_y = d_name_y;\n\tint d_color_x = d_dialog_x + ((d_dialog_w / 4) * 3) - (d_color_w * 3);\n\n\tint d_playerlist_w = 118 * RESFACTOR;\n\tint d_playerlist_h = (6 * 6 * RESFACTOR) + 3 * RESFACTOR;\t\t\t// 6 rows high\n\tint d_playerlist_x = d_dialog_x + d_margin1 + d_margin1 + 5*RESFACTOR;\n\tint d_playerlist_y = d_color_y + d_color_h + d_margin2 + 2*RESFACTOR/*KO + d_txt6_h*/;\n\n\tint d_scenariolist_w = 162 * RESFACTOR;\n\tint d_scenariolist_h = (6 * 6 * RESFACTOR) + 3 * RESFACTOR;\t\t// 6 rows high\n\n\tif (skirmish) {\n\t\td_scenariolist_h *= 2;\n\t}\n\n\n\tint d_scenariolist_x = d_dialog_x + d_dialog_w - d_margin1 - d_margin1 - d_scenariolist_w - 5*RESFACTOR;\n\tint d_scenariolist_y = d_color_y + d_color_h + d_margin2 + 2*RESFACTOR;\n\n\tif (skirmish) {\n\t\td_scenariolist_x = d_dialog_x + (d_dialog_w-d_scenariolist_w)/2;\n\t}\n\n\tint d_count_w = 25 * RESFACTOR;\n\tint d_count_h = d_txt6_h;\n\tint d_count_x = d_playerlist_x + (d_playerlist_w / 2) + 20 * RESFACTOR;\t\t// (fudged)\n\tint d_count_y = d_playerlist_y + d_playerlist_h + (d_margin1 * 2) - 2 * RESFACTOR;\n\n\tif (skirmish) {\n\t\td_count_y = d_scenariolist_y + d_scenariolist_h + d_margin1 - 2*RESFACTOR;\n\t}\n\n\tint d_level_w = 25 * RESFACTOR;\n\tint d_level_h = d_txt6_h;\n\tint d_level_x = d_playerlist_x + (d_playerlist_w / 2) + 20 * RESFACTOR;\t\t// (fudged)\n\tint d_level_y = d_count_y + d_count_h;\n\n\tint d_credits_w = 25 * RESFACTOR;\n\tint d_credits_h = d_txt6_h;\n\tint d_credits_x = d_playerlist_x + (d_playerlist_w / 2) + 20 * RESFACTOR;\t// (fudged)\n\tint d_credits_y = d_level_y + d_level_h;\n\n\tint d_aiplayers_w = 25*RESFACTOR;\n\tint d_aiplayers_h = d_txt6_h;\n\tint d_aiplayers_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR;\t// (fudged)\n\tint d_aiplayers_y = d_credits_y + d_credits_h;\n\n\tint d_options_w = 106 * RESFACTOR;\n\tint d_options_h = (5 * 6* RESFACTOR) + 4*RESFACTOR;\n\tint d_options_x = d_dialog_x + d_dialog_w - 149 * RESFACTOR;\n\tint d_options_y = d_scenariolist_y + d_scenariolist_h + d_margin1 - 2*RESFACTOR;\n\n\tint d_message_w = d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR;\n\tint d_message_h = (8 * d_txt6_h) + 3 * RESFACTOR;\t\t// 4 rows high\n\tint d_message_x = d_dialog_x + d_margin1 + 10*RESFACTOR;\n\tint d_message_y = d_options_y + d_options_h + 2*RESFACTOR;\n\n\tint d_send_w = d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR;\n\tint d_send_h = 9 * RESFACTOR;\n\tint d_send_x = d_dialog_x + d_margin1 + 10*RESFACTOR;\n\tint d_send_y = d_message_y + d_message_h;\n\n\tint d_ok_w = 45 * RESFACTOR;\n\tint d_ok_h = 9 * RESFACTOR;\n\tint d_ok_x = d_dialog_x + (d_dialog_w / 6) - (d_ok_w / 2);\n\tint d_ok_y = d_dialog_y + d_dialog_h - d_ok_h - d_margin1 - RESFACTOR*6;\n\n\tint d_cancel_w = 45 * RESFACTOR;\n\tint d_cancel_h = 9 * RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - (d_cancel_w / 2);\n\tint d_cancel_y = d_dialog_y + d_dialog_h - d_cancel_h - d_margin1 - RESFACTOR*6;\n\n\tint d_load_w = 45 * RESFACTOR;\n\tint d_load_h = 9 * RESFACTOR;\n\tint d_load_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_load_w / 2);\n\tint d_load_y = d_dialog_y + d_dialog_h - d_load_h - d_margin1 - RESFACTOR*6;\n\n\n\t/*........................................................................\n\tButton Enumerations\n\t........................................................................*/\n\tenum {\n\t\tBUTTON_NAME = 100,\n#ifdef OLDWAY\n\t\tBUTTON_GDI,\n\t\tBUTTON_NOD,\n#else\n\t\tBUTTON_HOUSE,\n#endif\n\t\tBUTTON_CREDITS,\n\t\tBUTTON_AIPLAYERS,\n\t\tBUTTON_OPTIONS,\n\t\tBUTTON_PLAYERLIST,\n\t\tBUTTON_SCENARIOLIST,\n\t\tBUTTON_COUNT,\n\t\tBUTTON_LEVEL,\n\t\tBUTTON_OK,\n\t\tBUTTON_LOAD,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_DIFFICULTY,\n\t};\n\n\t/*........................................................................\n\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t........................................................................*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PARMS,\n\t\tREDRAW_MESSAGE,\n\t\tREDRAW_COLORS,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*........................................................................\n\tDialog variables\n\t........................................................................*/\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\n\tint playertabs[] = {77*RESFACTOR};\t// tabs for player list box\n\tint optiontabs[] = {8};\t\t\t\t\t// tabs for player list box\n\tchar namebuf[MPLAYER_NAME_MAX] = {0};\t\t// buffer for player's name\n\tbool transmit;\t\t\t\t\t\t\t\t// 1 = re-transmit new game options\n\tint cbox_x[] = {\n\t\t\t\t\t\t\td_color_x,\n\t\t\t\t\t\t\td_color_x + d_color_w,\n\t\t\t\t\t\t\td_color_x + (d_color_w * 2),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 3),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 4),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 5),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 6),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 7)\n\t\t\t\t\t\t\t};\n\tbool parms_received = false;\t\t\t\t\t// 1 = game options received\n\tbool changed = false;\t\t\t\t\t\t\t// 1 = user has changed an option\n\n\tint rc;\n\tint recsignedoff = false;\n\tint i;\n\tunsigned long version;\n\tunsigned long starttime;\n\tunsigned long timingtime;\n\tunsigned long lastmsgtime;\n\tunsigned long lastredrawtime;\n\tunsigned long transmittime = 0;\n\tunsigned long theirresponsetime;\n\tint packetlen;\n\tstatic bool first_time = true;\n\tbool oppscorescreen = false;\n\tbool gameoptions = Session.Type == GAME_SKIRMISH;\n\tEventClass *event;\t\t\t\t\t// event ptr\n\tunsigned long msg_timeout = 1200;\t// init to 20 seconds\n\n\tCCFileClass loadfile (\"SAVEGAME.NET\");\n\tbool load_game = false;\t\t\t\t\t// 1 = load a saved game\n\tNodeNameType *who;\t\t\t\t\t// node to add to Players\n\tchar *item;\t\t\t\t\t\t\t\t// for filling in lists\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\tbool messages_have_focus = true;\t\t// Gadget focus starts on the message system\n\n\tSet_Logic_Page(SeenBuff);\n\n\tCDTimerClass<SystemTimerClass> kludge_timer;\t\t// Timer to allow a wait after client joins\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// game before game can start\n\tbool ok_button_added = false;\n\n\t/*........................................................................\n\tButtons\n\t........................................................................*/\n\tGadgetClass * commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tEditClass name_edt(BUTTON_NAME, namebuf, MPLAYER_NAME_MAX, TPF_TEXT, d_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC);\n\n#ifdef OLDWAY\n\tTextButtonClass gdibtn(BUTTON_GDI, TXT_ALLIES, TPF_BUTTON, d_gdi_x, d_gdi_y, d_gdi_w, d_gdi_h);\n\tTextButtonClass nodbtn(BUTTON_NOD, TXT_SOVIET, TPF_BUTTON, d_nod_x, d_nod_y, d_nod_w, d_nod_h);\n#else\n\tchar housetext[25] = \"\";\n\tFancy_Text_Print(\"\", 0, 0, 0, 0, TPF_TEXT);\n\tDropListClass housebtn(BUTTON_HOUSE, housetext, sizeof(housetext),\n\t\tTPF_TEXT,\n\t\td_house_x, d_house_y, d_house_w, d_house_h,\n\t\tMFCD::Retrieve(\"BTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"BTN-DN.SHP\"));\n#endif\n\tColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tListClass scenariolist(BUTTON_SCENARIOLIST, d_scenariolist_x, d_scenariolist_y, d_scenariolist_w, d_scenariolist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tGaugeClass countgauge(BUTTON_COUNT, d_count_x, d_count_y, d_count_w, d_count_h);\n\n\tchar staticcountbuff[35];\n\tStaticButtonClass staticcount(0, \"     \", TPF_TEXT, d_count_x+d_count_w+3*RESFACTOR, d_count_y);\n\n\tGaugeClass levelgauge(BUTTON_LEVEL, d_level_x, d_level_y, d_level_w, d_level_h);\n\n\tchar staticlevelbuff[35];\n\tStaticButtonClass staticlevel(0, \"     \", TPF_TEXT, d_level_x+d_level_w+3*RESFACTOR, d_level_y);\n\n\tGaugeClass creditsgauge(BUTTON_CREDITS, d_credits_x, d_credits_y, d_credits_w, d_credits_h);\n\n\tchar staticcreditsbuff[35];\n\tStaticButtonClass staticcredits(0, \"         \", TPF_TEXT, d_credits_x+d_credits_w+3*RESFACTOR, d_credits_y);\n\n\tGaugeClass aiplayersgauge(BUTTON_AIPLAYERS, d_aiplayers_x, d_aiplayers_y, d_aiplayers_w, d_aiplayers_h);\n\n\tchar staticaibuff[35];\n\tStaticButtonClass staticai(0, \"     \", TPF_TEXT, d_aiplayers_x+d_aiplayers_w+3*RESFACTOR, d_aiplayers_y);\n\n\tCheckListClass optionlist(BUTTON_OPTIONS, d_options_x, d_options_y, d_options_w, d_options_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tTextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_BUTTON, d_ok_x, d_ok_y, d_ok_w, d_ok_h);\n\tTextButtonClass loadbtn(BUTTON_LOAD, TXT_LOAD_BUTTON, TPF_BUTTON, d_load_x, d_load_y, d_load_w, d_load_h);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n\n\tSliderClass difficulty(BUTTON_DIFFICULTY, d_name_x, optionlist.Y + optionlist.Height + d_margin1 + d_margin1, d_dialog_w - (d_name_x-d_dialog_x)*2, 8*RESFACTOR, true);\n\tif (Rule.IsFineDifficulty) {\n\t\tdifficulty.Set_Maximum(5);\n\t\tdifficulty.Set_Value(2);\n\t} else {\n\t\tdifficulty.Set_Maximum(3);\n\t\tdifficulty.Set_Value(1);\n\t}\n\n\t/*\n\t------------------------- Build the button list --------------------------\n\t*/\n\tcommands = &name_edt;\n\tstaticcount.Add_Tail(*commands);\n\tstaticcredits.Add_Tail(*commands);\n\tstaticai.Add_Tail(*commands);\n\tstaticlevel.Add_Tail(*commands);\n\tif (!skirmish) {\n\t\tplayerlist.Add_Tail(*commands);\n\t} else {\n\t\tdifficulty.Add_Tail(*commands);\n\t}\n\tscenariolist.Add_Tail(*commands);\n\tcountgauge.Add_Tail(*commands);\n\tlevelgauge.Add_Tail(*commands);\n\tcreditsgauge.Add_Tail(*commands);\n\taiplayersgauge.Add_Tail(*commands);\n\toptionlist.Add_Tail(*commands);\n\tif (Session.Type == GAME_SKIRMISH){\n\t\tokbtn.Add_Tail(*commands);\n\t}\n\tcancelbtn.Add_Tail(*commands);\n\tif (!skirmish && loadfile.Is_Available()) {\n#ifdef FIXIT_MULTI_SAVE\n\t\t//Load button added only when other player has arrived\n\t\t//loadbtn.Add_Tail(*commands);\n#endif\n\t} else {\n\t\tcancelbtn.X = loadbtn.X;\n\t}\n#ifdef OLDWAY\n\tgdibtn.Add_Tail(*commands);\n\tnodbtn.Add_Tail(*commands);\n#else\n\thousebtn.Add_Tail(*commands);\n#endif\n\n\n\t/*\n\t----------------------------- Various Inits ------------------------------\n\t*/\n\t/*........................................................................\n\tInit player name & house\n\t........................................................................*/\n\tSession.ColorIdx = Session.PrefColor;\t\t\t// init my preferred color\n\tstrcpy (namebuf, Session.Handle);\t\t\t\t// set my name\n\tname_edt.Set_Text(namebuf,MPLAYER_NAME_MAX);\n\tname_edt.Set_Color(&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]);\n\n#ifdef OLDWAY\n\tif (Session.House==HOUSE_GOOD) {\n\t\tgdibtn.Turn_On();\n\t} else {\n\t\tnodbtn.Turn_On();\n\t}\n#else\n\tfor (HousesType house = HOUSE_USSR; house <= HOUSE_FRANCE; house++) {\n\t\thousebtn.Add_Item(Text_String(HouseTypeClass::As_Reference(house).Full_Name()));\n\t}\n\thousebtn.Set_Selected_Index(Session.House - HOUSE_USSR);\n\thousebtn.Set_Read_Only (true);\n#endif\n\n\t/*........................................................................\n\tInit scenario values, only the first time through\n\t........................................................................*/\n\tSpecial.IsCaptureTheFlag = Rule.IsMPCaptureTheFlag;\n\tif (first_time) {\n\t\tSession.Options.Credits = Rule.MPDefaultMoney;\t// init credits & credit buffer\n\t\tSession.Options.Bases = Rule.IsMPBasesOn;\t\t\t// init scenario parameters\n\t\tSession.Options.Tiberium = Rule.IsMPTiberiumGrow;\n\t\tSession.Options.Goodies = Rule.IsMPCrates;\n\t\tSession.Options.AIPlayers = 0;\n\t\tSpecial.IsShadowGrow = Rule.IsMPShadowGrow;\n\t\tSession.Options.UnitCount = (SessionClass::CountMax[Session.Options.Bases] + SessionClass::CountMin[Session.Options.Bases]) / 2;\n\t\tfirst_time = false;\n\t}\n\n\t/*........................................................................\n\tInit button states\n\t........................................................................*/\n\tplayerlist.Set_Tabs(playertabs);\n\tplayerlist.Set_Selected_Style(ColorListClass::SELECT_NORMAL);\n\n\toptionlist.Set_Tabs(optiontabs);\n\toptionlist.Set_Read_Only(0);\n\n\toptionlist.Add_Item(Text_String(TXT_BASES));\n\toptionlist.Add_Item(Text_String(TXT_ORE_SPREADS));\n\toptionlist.Add_Item(Text_String(TXT_CRATES));\n\toptionlist.Add_Item(Text_String(TXT_SHADOW_REGROWS));\n\tif (!skirmish) {\n\t\toptionlist.Add_Item(Text_String(TXT_CAPTURE_THE_FLAG));\n\t}\n\n\toptionlist.Check_Item(0, Session.Options.Bases);\n\toptionlist.Check_Item(1, Session.Options.Tiberium);\n\toptionlist.Check_Item(2, Session.Options.Goodies);\n\toptionlist.Check_Item(3, Special.IsShadowGrow);\n\tif (!skirmish) {\n\t\toptionlist.Check_Item(4, Special.IsCaptureTheFlag);\n\t}\n\n\tcountgauge.Set_Maximum(SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]);\n\tcountgauge.Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]);\n\n\tlevelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1);\n\tlevelgauge.Set_Value(BuildLevel - 1);\n\n\tcreditsgauge.Set_Maximum(Rule.MPMaxMoney);\n\tcreditsgauge.Set_Value(Session.Options.Credits);\n\n\tint maxp = Rule.MaxPlayers - 2;\n//\tint maxp = Rule.MaxPlayers - (skirmish ? 1 : 2);\n\taiplayersgauge.Set_Maximum(maxp);\n\n\tif (skirmish) {\n\t\tif ( Session.Options.AIPlayers > 7 ) {\n\t\t\tSession.Options.AIPlayers = 7;\n\t\t}\n\t\tSession.Options.AIPlayers = max(Session.Options.AIPlayers, 1);\n\t}else{\n\t\tif ( Session.Options.AIPlayers > 6 ) {\n\t\t\tSession.Options.AIPlayers = 6;\n\t\t}\n\t}\n\n\taiplayersgauge.Set_Value(Session.Options.AIPlayers - (skirmish ? 1 : 0));\n\n\t/*........................................................................\n\tInit other scenario parameters\n\t........................................................................*/\n\tSpecial.IsTGrowth = //Session.Options.Tiberium;\n\t\tRule.IsTGrowth = //Session.Options.Tiberium;\n\t\t\tSpecial.IsTSpread = //Session.Options.Tiberium;\n\t\t\t\tRule.IsTSpread = Session.Options.Tiberium;\n\ttransmit = true;\n\n\t/*........................................................................\n\tClear the Players vector\n\t........................................................................*/\n\tClear_Vector(&Session.Players);\n\n\t/*........................................................................\n\tInit scenario description list box\n\t........................................................................*/\n\tfor (i = 0; i < Session.Scenarios.Count(); i++) {\n\t\tfor (int j = 0; EngMisStr[j] != NULL;  j++) {\n\t\t\tif (!strcmp(Session.Scenarios[i]->Description(), EngMisStr[j])) {\n#ifdef FIXIT_CSII\t//\tajw Added Aftermath installed checks (before, it was assumed).\n\t\t\t//\tAdd mission if it's available to us.\n\t\t\tif( !( ( Is_Mission_Counterstrike((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Counterstrike_Installed() ) ||\n\t\t\t\t\t( Is_Mission_Aftermath((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Aftermath_Installed() ) ) )\n#endif\n#if defined(GERMAN) || defined(FRENCH)\n\t\t\t\tscenariolist.Add_Item(EngMisStr[j+1]);\n#else\n\t\t\t\tscenariolist.Add_Item(EngMisStr[j]);\n#endif\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (EngMisStr[j] == NULL) {\n#ifdef FIXIT_CSII\t//\tajw Added Aftermath installed checks (before, it was assumed). Added officialness check.\n\t\t\t//\tAdd mission if it's available to us.\n\t\t\tif( !Session.Scenarios[i]->Get_Official() ||\n\t\t\t\t!( ( Is_Mission_Counterstrike((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Counterstrike_Installed() ) ||\n\t\t\t\t\t( Is_Mission_Aftermath((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Aftermath_Installed() ) ) )\n#endif\n\t\t\tscenariolist.Add_Item(Session.Scenarios[i]->Description());\n\t\t}\n\t}\n\n\tSession.Options.ScenarioIndex = 0;\t\t// 1st scenario is selected\n\n\t/*........................................................................\n\tInit random-number generator, & create a seed to be used for all random\n\tnumbers from here on out\n\t........................................................................*/\n#ifdef FIXIT_RANDOM_GAME\n\tsrand(time(NULL));\n\tSeed = rand();\n#else\n//\trandomize();\n//\tSeed = rand();\n#endif\n\n\t/*........................................................................\n\tInit the message display system\n\t........................................................................*/\n\tif (!skirmish) {\n\t\tSession.Messages.Init (d_message_x + 1, d_message_y + 1, 8,\n\t\t\tMAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1, d_send_y + 1, 1,\n\t\t\t20, MAX_MESSAGE_LENGTH - 5, d_message_w);\n\t\tSession.Messages.Add_Edit ((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message_w);\n\t}\n\n\t/*........................................................................\n\tInit version number clipping system\n\t........................................................................*/\n\tVerNum.Init_Clipping();\n\tLoad_Title_Page(true);\n\tCCPalette.Set();\n\n\textern char ModemRXString[];\n\n\tif (strlen(ModemRXString) > 36)\n\t\tModemRXString[36] = 0;\n\n\tif (strlen(ModemRXString) > 0)\n\t\tSession.Messages.Add_Message (NULL, 0, ModemRXString, PCOLOR_BROWN,\n\t\t\tTPF_TEXT, -1);\n\n\tModemRXString[0] = '\\0';\n\n\t/*\n\t---------------------------- Init Mono Output ----------------------------\n\t*/\n\t#if(SHOW_MONO)\n\tif (!skirmish) {\n\t\tNullModem.Configure_Debug(sizeof (CommHeaderType),sizeof (SerialCommandType),\n\t\t\tSerialPacketNames, 100, 8);\n\t\tNullModem.Mono_Debug_Print(1);\n\t}\n\t#endif\n\n\t/*\n\t---------------------------- Processing loop -----------------------------\n\t*/\n\tif (!skirmish) {\n\t\tNullModem.Reset_Response_Time();\t\t// clear response time\n\t}\n\ttheirresponsetime = 10000;\t\t\t\t// initialize to an invalid value\n\ttimingtime = lastmsgtime = lastredrawtime = TickCount;\n\n\n\t/*\n\t** Those easily offended should avert their eyes from the following line. And whatever\n\t** you do, dont search for 'goto'.\n\t*/\noh_dear_its_a_label:\n\n\twhile (process) {\n\t\t#if(SHOW_MONO)\n\t\tif (!skirmish) {\n\t\t\tNullModem.Mono_Debug_Print(0);\n\t\t}\n\t\t#endif\n\n\t\tif (!skirmish){\n\t\t\tif (!ok_button_added && gameoptions && kludge_timer == 0){\n\t\t\t\tokbtn.Add_Tail(*commands);\n\t\t\t\tok_button_added = true;\n#ifdef FIXIT_VERSION_3\n\t\t\t\tif( loadfile.Is_Available() )\n\t\t\t\t{\n\t\t\t\t\tloadbtn.Add_Tail( *commands );\n\t\t\t\t}\n#else\n#ifdef FIXIT_MULTI_SAVE\n\t\t\t\tif ( loadfile.Is_Available() && PlayingAgainstVersion > VERSION_RED_ALERT_104 ) {\n\t\t\t\t\tloadbtn.Add_Tail ( *commands );\n\t\t\t\t}\n#endif\n#endif\n\t\t\t\tif (display < REDRAW_BUTTONS) display = REDRAW_BUTTONS;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Kludge to make sure we redraw the message input line when it loses focus.\n\t\t** If we dont do this then the cursor doesnt disappear.\n\t\t*/\n\t\tif (!skirmish) {\n\t\t\tif (messages_have_focus) {\n\t\t\t\tif (name_edt.Has_Focus()) {\n\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\tmessages_have_focus = false;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!name_edt.Has_Focus()) {\n\t\t\t\t\tmessages_have_focus = true;\n\t\t\t\t\tif (display < REDRAW_MESSAGE)\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t\tSession.Messages.Set_Edit_Focus();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t........................ Invoke game callback .........................\n\t\t*/\n\t\tCall_Back();\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\t#endif\n\n\t\t/*\n\t\t...................... Refresh display if needed ......................\n\t\t*/\n\t\tif (display) {\n\t\t\tif (housebtn.IsDropped) {\n\t\t\t\thousebtn.Collapse();\n\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t}\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t.................. Redraw backgound & dialog box ...................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t// init font variables\n\n\t\t\t\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_CENTER | TPF_TEXT);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDialog & Field labels\n\t\t\t\t...............................................................*/\n\t\t\t\tFancy_Text_Print(TXT_YOUR_NAME, d_name_x + (d_name_w / 2), d_name_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n#ifdef OLDWAY\n\t\t\t\tFancy_Text_Print(TXT_SIDE_COLON, d_gdi_x + d_gdi_w, d_gdi_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n#else\n\t\t\t\tFancy_Text_Print(TXT_SIDE_COLON, d_house_x + (d_house_w / 2), d_house_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n#endif\n\t\t\t\tFancy_Text_Print(TXT_COLOR_COLON, d_dialog_x + ((d_dialog_w / 4) * 3), d_color_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\tif (!skirmish) {\n\t\t\t\t\tFancy_Text_Print(TXT_PLAYERS, d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\t} else {\n\t\t\t\t\tFancy_Text_Print(TXT_EASY, difficulty.X, difficulty.Y-8*RESFACTOR, scheme, TBLACK, TPF_TEXT);\n\t\t\t\t\tFancy_Text_Print(TXT_HARD, difficulty.X + difficulty.Width, difficulty.Y-8*RESFACTOR, scheme, TBLACK, TPF_RIGHT|TPF_TEXT);\n\t\t\t\t\tFancy_Text_Print(TXT_NORMAL, difficulty.X + difficulty.Width/2, difficulty.Y-8*RESFACTOR, scheme, TBLACK, TPF_CENTER|TPF_TEXT);\n\t\t\t\t}\n\t\t\t\tFancy_Text_Print(TXT_SCENARIOS, d_scenariolist_x + (d_scenariolist_w / 2), d_scenariolist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\tFancy_Text_Print(TXT_COUNT, d_count_x - 2, d_count_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print(TXT_LEVEL, d_level_x - 2, d_level_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print(TXT_CREDITS_COLON, d_credits_x - 2, d_credits_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print(TXT_AI_PLAYERS_COLON, d_aiplayers_x - 2*RESFACTOR, d_aiplayers_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tDraw the color boxes\n\t\t\t..................................................................*/\n\t\t\tif (display >= REDRAW_COLORS) {\n\t\t\t\tfor (i = 0; i < MAX_MPLAYER_COLORS; i++) {\n\t\t\t\t\tLogicPage->Fill_Rect (cbox_x[i] + 1, d_color_y + 1,\n\t\t\t\t\t\tcbox_x[i] + 1 + d_color_w - 2, d_color_y + 1 + d_color_h - 2,\n\t\t\t\t\t\tColorRemaps[i].Box);\n//\t\t\t\t\t\t(i == PCOLOR_DIALOG_BLUE) ? ColorRemaps[PCOLOR_REALLY_BLUE].Box : ColorRemaps[i].Box);\n\n\t\t\t\t\tif (i == Session.ColorIdx) {\n\t\t\t\t\t\tDraw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_DOWN, false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tDraw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_RAISED, false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tDraw the message system; erase old messages first\n\t\t\t..................................................................*/\n\t\t\tif (display >= REDRAW_MESSAGE && !skirmish) {\n\t\t\t\tDraw_Box(d_message_x, d_message_y, d_message_w, d_message_h, BOXSTYLE_BOX, true);\n\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true);\n\t\t\t\tSession.Messages.Draw();\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// Update game parameter labels\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_PARMS) {\n\n//\t\t\t\tLogicPage->Fill_Rect(d_count_x + d_count_w + 2, d_count_y, d_count_x + d_count_w + 35 * RESFACTOR, d_aiplayers_y + d_aiplayers_h+RESFACTOR, BLACK);\n\n\t\t\t\tsprintf(staticcountbuff, \"%d\", Session.Options.UnitCount);\n\t\t\t\tstaticcount.Set_Text(staticcountbuff);\n\t\t\t\tstaticcount.Draw_Me();\n//\t\t\t\tFancy_Text_Print(\"%d \", d_count_x + d_count_w + 3 * RESFACTOR, d_count_y, scheme, BLACK, TPF_TEXT, Session.Options.UnitCount);\n\n\t\t\t\tif (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {\n\t\t\t\t\tsprintf(staticlevelbuff, \"%d \", BuildLevel);\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(staticlevelbuff, \"**\");\n\t\t\t\t}\n\t\t\t\tstaticlevel.Set_Text(staticlevelbuff);\n\t\t\t\tstaticlevel.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_level_x + d_level_w + 3 * RESFACTOR, d_level_y, scheme, BLACK, TPF_TEXT);\n\n\t\t\t\tsprintf(staticcreditsbuff, \"%d\", Session.Options.Credits);\n\t\t\t\tstaticcredits.Set_Text(staticcreditsbuff);\n\t\t\t\tstaticcredits.Draw_Me();\n//\t\t\t\tFancy_Text_Print(\"%d\", d_credits_x + d_credits_w + 2 * RESFACTOR, d_credits_y, scheme, BLACK, TPF_TEXT, Session.Options.Credits);\n\n\t\t\t\tsprintf(staticaibuff, \"%d\", Session.Options.AIPlayers);\n\t\t\t\tstaticai.Set_Text(staticaibuff);\n\t\t\t\tstaticai.Draw_Me();\n//\t\t\t\tFancy_Text_Print(\"%d\", d_aiplayers_x + d_aiplayers_w + 2*RESFACTOR, d_aiplayers_y, scheme, BLACK, TPF_TEXT, Session.Options.AIPlayers);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t.......................... Redraw buttons ..........................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t\tcommands->Draw_All();\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t........................... Get user input ............................\n\t\t*/\n\t\tmessages_have_focus = Session.Messages.Has_Edit_Focus();\n\t\tbool droplist_is_dropped = housebtn.IsDropped;\n\t\tinput = commands->Input();\n\n\t\t/*\n\t\t** Sort out the input focus between the name edit box and the message system\n\t\t*/\n\t\tif (!skirmish) {\n\t\t\tif (messages_have_focus) {\n\t\t\t\tif (!name_edt.Has_Focus()) {\n\t\t\t\t\tSession.Messages.Set_Edit_Focus();\n\t\t\t\t} else {\n\t\t\t\t\tmessages_have_focus = false;\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Redraw everything if the droplist collapsed\n\t\t*/\n\t\tif (droplist_is_dropped && !housebtn.IsDropped) {\n\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t}\n\n\t\tif (input & KN_BUTTON) {\n\t\t\tif (housebtn.IsDropped) {\n\t\t\t\thousebtn.Collapse();\n\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t}\n\t\t}\n\n\n\t\t/*\n\t\t---------------------------- Process input ----------------------------\n\t\t*/\n\t\tswitch (input) {\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUser clicks on a color button\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase KN_LMOUSE:\n\t\t\t\tif (Keyboard->MouseQX > cbox_x[0] &&\n\t\t\t\t\t\tKeyboard->MouseQX < (cbox_x[MAX_MPLAYER_COLORS - 1] + d_color_w) &&\n\t\t\t\t\t\tKeyboard->MouseQY > d_color_y &&\n\t\t\t\t\t\tKeyboard->MouseQY < (d_color_y + d_color_h)) {\n\n\t\t\t\t\tSession.PrefColor = (PlayerColorType)((Keyboard->MouseQX - cbox_x[0]) / d_color_w);\n\t\t\t\t\tSession.ColorIdx = Session.PrefColor;\n\t\t\t\t\tif (display < REDRAW_COLORS) display = REDRAW_COLORS;\n\n\t\t\t\t\tname_edt.Set_Color (&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]);\n\t\t\t\t\tname_edt.Flag_To_Redraw();\n\t\t\t\t\tSession.Messages.Set_Edit_Color((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx);\n\t\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\t\ttransmit = true;\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUser edits the name field; retransmit new game options\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_NAME | KN_BUTTON):\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\ttransmit = true;\n\t\t\t\tchanged = true;\n\t\t\t\tbreak;\n\n#ifdef OLDWAY\n\t\t\t/*------------------------------------------------------------------\n\t\t\tHouse Buttons: set the player's desired House\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_GDI | KN_BUTTON):\n\t\t\t\tSession.House = HOUSE_GOOD;\n\t\t\t\tgdibtn.Turn_On();\n\t\t\t\tnodbtn.Turn_Off();\n\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\ttransmit = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_NOD | KN_BUTTON):\n\t\t\t\tSession.House = HOUSE_BAD;\n\t\t\t\tgdibtn.Turn_Off();\n\t\t\t\tnodbtn.Turn_On();\n\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\ttransmit = true;\n\t\t\t\tbreak;\n#else\n\t\t\tcase (BUTTON_HOUSE | KN_BUTTON):\n\t\t\t\tSession.House = HousesType(housebtn.Current_Index()+HOUSE_USSR);\n\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\ttransmit = true;\n\t\t\t\tbreak;\n#endif\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tNew Scenario selected.\n\t\t\t------------------------------------------------------------------*/\n#ifdef FIXIT_VERSION_3\t\t//\tAll scenarios now allowable as downloads. ajw\n\t\t\tcase (BUTTON_SCENARIOLIST | KN_BUTTON):\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\tif (scenariolist.Current_Index() != Session.Options.ScenarioIndex)\n\t\t\t\t{\n\t\t\t\t\tSession.Options.ScenarioIndex = scenariolist.Current_Index();\n\t\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\t\ttransmit = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n#else\t//\tFIXIT_VERSION_3\t\tWhoever duplicated Netdlg into Nulldlg should be shot. Wasn't it enough?\n\n\t\t\t\tAbandon all hope ye who hit enter here.\n\n\t\t\tcase (BUTTON_SCENARIOLIST | KN_BUTTON):\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\tif (scenariolist.Current_Index() != Session.Options.ScenarioIndex) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw\n\t\t\t\t\tif ( !skirmish && (PlayingAgainstVersion != VERSION_RED_ALERT_107 && PlayingAgainstVersion != VERSION_RED_ALERT_108 && PlayingAgainstVersion < VERSION_AFTERMATH_CS) &&\n#else\n\t\t\t\t\tif ( !skirmish && PlayingAgainstVersion < VERSION_RED_ALERT_107 &&\n#endif\n\t\t\t\t\t\t\t\tSession.Scenarios[scenariolist.Current_Index()]->Get_Expansion()){\n\t\t\t\t\t\tscenariolist.Set_Selected_Index (Session.Options.ScenarioIndex);\n\t\t\t\t\t\tSession.Messages.Add_Message(NULL, 0,\n\t\t\t\t\t\t\t(char *)Text_String(TXT_NO_CS_SCENARIOS), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n#ifdef FIXIT_CSII\t//\tchecked - ajw\n\t\t\t\t\t} else\n\t\t\t\t\tif ( !skirmish && PlayingAgainstVersion < VERSION_AFTERMATH_CS &&\n\t\t\t\t\t\t\tIs_Mission_126x126((char *)Session.Scenarios[scenariolist.Current_Index()]->Get_Filename() ) ){\n\t\t\t\t\t\tscenariolist.Set_Selected_Index (Session.Options.ScenarioIndex);\n\t\t\t\t\t\tSession.Messages.Add_Message(NULL, 0,\n\t\t\t\t\t\t\t(char *)Text_String(TXT_NO_CS_SCENARIOS), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n#endif\n\t\t\t\t\t}else{\n\t\t\t\t\t\tSession.Options.ScenarioIndex = scenariolist.Current_Index();\n\t\t\t\t\t\ttransmit = 1;\n\t\t\t\t\t}\n\n\t\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\t\ttransmit = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n#endif\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUser adjusts max # units\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_COUNT | KN_BUTTON):\n\t\t\t\tSession.Options.UnitCount = countgauge.Get_Value() + SessionClass::CountMin[Session.Options.Bases];\n\t\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\ttransmit = true;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUser adjusts build level\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_LEVEL | KN_BUTTON):\n\t\t\t\tBuildLevel = levelgauge.Get_Value() + 1;\n\t\t\t\tif (BuildLevel > MPLAYER_BUILD_LEVEL_MAX)\t// if it's pegged, max it out\n\t\t\t\t\tBuildLevel = MPLAYER_BUILD_LEVEL_MAX;\n\t\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\ttransmit = true;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUser adjusts max # units\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_CREDITS | KN_BUTTON):\n\t\t\t\tSession.Options.Credits = creditsgauge.Get_Value();\n\t\t\t\tSession.Options.Credits = ((Session.Options.Credits + 250) / 500) * 500;\n\t\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\ttransmit = true;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tUser adjusts # of AI players\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_AIPLAYERS | KN_BUTTON):\n\t\t\t\t{\n\t\t\t\t\tSession.Options.AIPlayers = aiplayersgauge.Get_Value();\n\t\t\t\t\tint humans = 2;\t\t\t// Two humans.\n\t\t\t\t\tif (skirmish) {\n\t\t\t\t\t\tSession.Options.AIPlayers += 1;\t// Always one forced AI player.\n\t\t\t\t\t\thumans = 1;\t\t\t// One human.\n\t//\t\t\t\t\t\tif (Session.Options.AIPlayers == 0) {\n\t//\t\t\t\t\t\t\tSession.Options.AIPlayers = 1;\n\t//\t\t\t\t\t\t\taiplayersgauge.Set_Value(0);\n\t//\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (Session.Options.AIPlayers+humans >= Rule.MaxPlayers) {\t// if it's pegged, max it out\n\t\t\t\t\t\tSession.Options.AIPlayers = Rule.MaxPlayers - humans;\n\t\t\t\t\t\taiplayersgauge.Set_Value(Session.Options.AIPlayers - (skirmish ? 1 : 0));\n\t\t\t\t\t}\n\t\t\t\t\ttransmit = true;\n\t\t\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\n\t\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t//------------------------------------------------------------------\n\t\t\t// Toggle-able options:\n\t\t\t// If 'Bases' gets toggled, we have to change the range of the\n\t\t\t// UnitCount slider.\n\t\t\t// Also, if Tiberium gets toggled, we have to set the flags\n\t\t\t// in SpecialClass.\n\t\t\t//------------------------------------------------------------------\n\t\t\tcase (BUTTON_OPTIONS | KN_BUTTON):\n\t\t\t\tif (!skirmish && Special.IsCaptureTheFlag != optionlist.Is_Checked(4) && !Special.IsCaptureTheFlag) {\n\t\t\t\t\toptionlist.Check_Item(0, true);\n\t\t\t\t}\n\t\t\t\tif (Session.Options.Bases != optionlist.Is_Checked(0)) {\n\t\t\t\t\tSession.Options.Bases = optionlist.Is_Checked(0);\n\t\t\t\t\tif (Session.Options.Bases) {\n\t\t\t\t\t\tSession.Options.UnitCount = Fixed_To_Cardinal (\n\t\t\t\t\t\t\tSessionClass::CountMax[1] -\n\t\t\t\t\t\t\tSessionClass::CountMin[1],\n\t\t\t\t\t\t\tCardinal_To_Fixed(\n\t\t\t\t\t\t\t\tSessionClass::CountMax[0]-SessionClass::CountMin[0],\n\t\t\t\t\t\t\t\tSession.Options.UnitCount-SessionClass::CountMin[0])) +\n\t\t\t\t\t\t\tSessionClass::CountMin[1];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!skirmish) optionlist.Check_Item(4, false);\n\t\t\t\t\t\tSession.Options.UnitCount = Fixed_To_Cardinal (\n\t\t\t\t\t\t\tSessionClass::CountMax[0] -\n\t\t\t\t\t\t\tSessionClass::CountMin[0],\n\t\t\t\t\t\t\tCardinal_To_Fixed(\n\t\t\t\t\t\t\t\tSessionClass::CountMax[1]-SessionClass::CountMin[1],\n\t\t\t\t\t\t\t\tSession.Options.UnitCount - SessionClass::CountMin[1])) +\n\t\t\t\t\t\t\tSessionClass::CountMin[0];\n\t\t\t\t\t}\n\t\t\t\t\tcountgauge.Set_Maximum(\n\t\t\t\t\t\tSessionClass::CountMax[Session.Options.Bases] -\n\t\t\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\t\t\tcountgauge.Set_Value(Session.Options.UnitCount -\n\t\t\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\t\t}\n\t\t\t\tSession.Options.Tiberium = optionlist.Is_Checked(1);\n\t\t\t\tSpecial.IsTGrowth = Session.Options.Tiberium;\n\t\t\t\tRule.IsTGrowth = Session.Options.Tiberium;\n\t\t\t\tSpecial.IsTSpread = Session.Options.Tiberium;\n\t\t\t\tRule.IsTSpread = Session.Options.Tiberium;\n\n\t\t\t\tSession.Options.Goodies = optionlist.Is_Checked(2);\n\t\t\t\tSpecial.IsShadowGrow = optionlist.Is_Checked(3);\n\t\t\t\tif (!skirmish) {\n\t\t\t\t\tSpecial.IsCaptureTheFlag = optionlist.Is_Checked(4);\n\t\t\t\t}\n\n\t\t\t\ttransmit = true;\n\t\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tOK: exit loop with true status\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_LOAD | KN_BUTTON):\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\t//\n\t\t\t\t// make sure we got a game options packet from the other player\n\t\t\t\t//\n\t\t\t\tif (gameoptions) {\n\t\t\t\t\trc = true;\n\t\t\t\t\tprocess = false;\n\n\t\t\t\t\t// force transmitting of game options packet one last time\n\n\t\t\t\t\ttransmit = true;\n\t\t\t\t\ttransmittime = 0;\n\t\t\t\t} else {\n\t\t\t\t\tWWMessageBox().Process (TXT_ONLY_ONE,TXT_OOPS,NULL);\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t}\n\t\t\t\tif (input==(BUTTON_LOAD | KN_BUTTON))\n\t\t\t\t\tload_game = true;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tCANCEL: send a SIGN_OFF, bail out with error code\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tDefault: manage the inter-player messages\n\t\t\t------------------------------------------------------------------*/\n\t\t\tdefault:\n\t\t\t\tif (!skirmish) {\n\t\t\t\t\tif (Session.Messages.Manage()) {\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*...............................................................\n\t\t\t\t\tService keyboard input for any message being edited.\n\t\t\t\t\t...............................................................*/\n\t\t\t\t\ti = Session.Messages.Input(input);\n\n\t\t\t\t\t/*...............................................................\n\t\t\t\t\tIf 'Input' returned 1, it means refresh the message display.\n\t\t\t\t\t(We have to redraw the edit line, to erase the cursor.)\n\t\t\t\t\t...............................................................*/\n\t\t\t\t\tif (i==1) {\n\t\t\t\t\t\tHide_Mouse();\n\t\t\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h,\n\t\t\t\t\t\t\tBOXSTYLE_BOX, true);\n\t\t\t\t\t\tSession.Messages.Draw();\n\t\t\t\t\t\tShow_Mouse();\n\t\t\t\t\t} else if (i==2) {\n\t\t\t\t\t/*...............................................................\n\t\t\t\t\tIf 'Input' returned 2, it means redraw the message display.\n\t\t\t\t\tRather than setting 'display', which would redraw all msgs,\n\t\t\t\t\twe only need to erase & redraw the edit box here.\n\t\t\t\t\t...............................................................*/\n\t\t\t\t\t\tHide_Mouse();\n\t\t\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true);\n\t\t\t\t\t\tSession.Messages.Draw();\n\t\t\t\t\t\tShow_Mouse();\n\t\t\t\t\t} else if (i==3 || i==4) {\n\t\t\t\t\t/*...............................................................\n\t\t\t\t\tIf 'input' returned 3, it means send the current message.\n\t\t\t\t\t...............................................................*/\n\t\t\t\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\t\t\t\tSendPacket.Command = SERIAL_MESSAGE;\n\t\t\t\t\t\tstrcpy (SendPacket.Name, namebuf);\n\t\t\t\t\t\tSendPacket.ID = Session.ColorIdx;\n\t\t\t\t\t\tif (i==3) {\n\t\t\t\t\t\t\tstrcpy (SendPacket.Message.Message, Session.Messages.Get_Edit_Buf());\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tstrcpy (SendPacket.Message.Message, Session.Messages.Get_Overflow_Buf());\n\t\t\t\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*..................................................................\n\t\t\t\t\t\tSend the message\n\t\t\t\t\t\t..................................................................*/\n\t\t\t\t\t\tif (!skirmish) {\n\t\t\t\t\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\t\t\t\t\t\t\tNullModem.Service();\n\t\t\t\t\t\t}\n\t\t\t\t\t\t/*..................................................................\n\t\t\t\t\t\tAdd the message to our own screen\n\t\t\t\t\t\t..................................................................*/\n\t\t\t\t\t\tSession.Messages.Add_Message (SendPacket.Name, SendPacket.ID,\n\t\t\t\t\t\t\tSendPacket.Message.Message,\n\t\t\t\t\t\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\tTPF_TEXT, -1);\n\t\t\t\t\t\tSession.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message_w);\n\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\t}\t/* end of send message */\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tDetect editing of the name buffer, transmit new values to players\n\t\t---------------------------------------------------------------------*/\n\t\tif (strcmp (namebuf, Session.Handle)) {\n\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\ttransmit = true;\n\t\t\tchanged = true;\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tIf our Transmit flag is set, we need to send out a game option packet.\n\t\tThis message requires an ACK.  The first time through the loop, transmit\n\t\tshould be set, so we send out our default options; we'll then send\n\t\tany changes we make to the defaults.\n\t\t---------------------------------------------------------------------*/\n\t\tif (skirmish) {\n\t\t\ttransmit = false;\n\t\t}\n\n\t\tif (transmit && (TickCount - transmittime) > PACKET_RETRANS_TIME) {\n\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\tSendPacket.Command = SERIAL_GAME_OPTIONS;\n\t\t\tstrcpy (SendPacket.Name, namebuf);\n\t\t\tSendPacket.ScenarioInfo.CheatCheck = RuleINI.Get_Unique_ID();\n\t\t\tSendPacket.ScenarioInfo.MinVersion = VerNum.Min_Version();\n\t\t\tSendPacket.ScenarioInfo.MaxVersion = VerNum.Max_Version();\n\t\t\tSendPacket.ScenarioInfo.House = Session.House;\n\t\t\tSendPacket.ScenarioInfo.Color = Session.ColorIdx;\n\t\t\tSendPacket.ScenarioInfo.Credits = Session.Options.Credits;\n\t\t\tSendPacket.ScenarioInfo.IsBases = Session.Options.Bases;\n\t\t\tSendPacket.ScenarioInfo.IsTiberium = Session.Options.Tiberium;\n\t\t\tSendPacket.ScenarioInfo.IsGoodies = Session.Options.Goodies;\n\t\t\tSendPacket.ScenarioInfo.AIPlayers = Session.Options.AIPlayers;\n\t\t\tSendPacket.ScenarioInfo.BuildLevel = BuildLevel;\n\t\t\tSendPacket.ScenarioInfo.UnitCount = Session.Options.UnitCount;\n\t\t\tSendPacket.ScenarioInfo.Seed = Seed;\n\t\t\tSendPacket.ScenarioInfo.Special = Special;\n\t\t\tSendPacket.ScenarioInfo.GameSpeed = Options.GameSpeed;\n\t\t\tSendPacket.ID = Session.ModemType;\n\n\t\t\t/*\n\t\t\t** Set up the scenario info so the remote player can match the scenario on his machine\n\t\t\t** or request a download if it doesnt exist\n\t\t\t*/\n\t\t\tstrcpy (SendPacket.ScenarioInfo.Scenario, Session.Scenarios[Session.Options.ScenarioIndex]->Description());\n\t\t\tCCFileClass file (Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename());\n\n\t\t\tSendPacket.ScenarioInfo.FileLength = file.Size();\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\tstrcpy( SendPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename() );\n#else\n\t\t\tstrncpy (SendPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename(), sizeof(SendPacket.ScenarioInfo.ShortFileName));\n#endif\n\t\t\tstrncpy ((char*)SendPacket.ScenarioInfo.FileDigest, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Digest(), sizeof SendPacket.ScenarioInfo.FileDigest);\n\t\t\tSendPacket.ScenarioInfo.OfficialScenario = Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official();\n\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\n\t\t\ttransmittime = TickCount;\n\t\t\ttransmit = false;\n\n\t\t\t//..................................................................\n\t\t\t// Keep the player list up to date\n\t\t\t//..................................................................\n\t\t\tif (playerlist.Count()) {\n\t\t\t\titem = (char *)playerlist.Get_Item(0);\n#ifdef OLDWAY\n\t\t\t\tif (Session.House==HOUSE_GOOD) {\n\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf,\n\t\t\t\t\t\tText_String(TXT_ALLIES));\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf,\n\t\t\t\t\t\tText_String(TXT_SOVIET));\n\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\tsprintf (item, \"%s\\t%s\", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\t\t\t\tplayerlist.Colors[0] = &ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx];\n\t\t\t\tplayerlist.Flag_To_Redraw();\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// Play a little sound effect\n\t\t\t//..................................................................\n\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t}\n\n\t\t//\n\t\t// send a timing packet if enough time has gone by.\n\t\t//\n\t\tif (!skirmish &&  (TickCount - timingtime) > PACKET_TIMING_TIMEOUT) {\n\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\tSendPacket.Command = SERIAL_TIMING;\n\t\t\tSendPacket.ScenarioInfo.ResponseTime = NullModem.Response_Time();\n\t\t\tSendPacket.ID = Session.ModemType;\n\n\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 0);\n\t\t\ttimingtime = TickCount;\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tCheck for an incoming message\n\t\t---------------------------------------------------------------------*/\n\t\tif (!skirmish && NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) {\n\n\t\t\tlastmsgtime = TickCount;\n\t\t\tmsg_timeout = 600;\t\t// reset timeout value to 10 seconds\n\t\t\t\t\t\t\t\t\t\t\t// (only the 1st time through is 20 seconds)\n\n\t\t\t// are we getting our own packets back??\n\n\t\t\tif (ReceivePacket.Command >= SERIAL_CONNECT &&\n\t\t\t\tReceivePacket.Command < SERIAL_LAST_COMMAND &&\n\t\t\t\tReceivePacket.Command != SERIAL_MESSAGE &&\n\t\t\t\tReceivePacket.ID == Session.ModemType) {\n\n\t\t\t\tWWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);\n\n\t\t\t\t// to skip the other system not responding msg\n\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\n\t\t\t\t// say we did receive sign off to keep from sending one\n\t\t\t\trecsignedoff = true;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tevent = (EventClass *)&ReceivePacket;\n\t\t\tif (event->Type <= EventClass::FRAMEINFO) {\n\t\t\t\tif ( (TickCount - lastredrawtime) > PACKET_REDRAW_TIME) {\n\t\t\t\t\tlastredrawtime = TickCount;\n\t\t\t\t\toppscorescreen = true;\n\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\tparms_received = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tswitch ( ReceivePacket.Command ) {\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tSign-off: Give the other machine time to receive my ACK, display a\n\t\t\t\t\tmessage, and exit.\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tcase (SERIAL_SIGN_OFF):\n\t\t\t\t\t\tstarttime = TickCount;\n\t\t\t\t\t\twhile (TickCount - starttime < 60)\n\t\t\t\t\t\t\tNullModem.Service();\n\t\t\t\t\t\tWWMessageBox().Process(TXT_USER_SIGNED_OFF);\n\n\t\t\t\t\t\t// to skip the other system not responding msg\n\t\t\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\trc = false;\n\t\t\t\t\t\trecsignedoff = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tGame Options:  Store the other machine's name, color & house;\n\t\t\t\t\tIf they've picked the same color as myself, re-transmit my settings\n\t\t\t\t\tto force him to choose a different color.  (Com_Show_Scenario_Dialog\n\t\t\t\t\tis responsible for ensuring the colors are different.)\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tcase (SERIAL_GAME_OPTIONS):\n\t\t\t\t\t\toppscorescreen = false;\n\t\t\t\t\t\tgameoptions = true;\n\t\t\t\t\t\tkludge_timer = 2*60;\n\t\t\t\t\t\tstrcpy (TheirName, ReceivePacket.Name);\n\t\t\t\t\t\tTheirColor = ReceivePacket.ScenarioInfo.Color;\n\t\t\t\t\t\tTheirHouse = ReceivePacket.ScenarioInfo.House;\n\t\t\t\t\t\ttransmit = true;\n\n\t\t\t\t\t\tparms_received = true;\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// \"Clip\" the other system's version range to our own\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\tversion = VerNum.Clip_Version(ReceivePacket.ScenarioInfo.MinVersion,\n\t\t\t\t\t\t\tReceivePacket.ScenarioInfo.MaxVersion);\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t// If the greatest-common-version comes back 0, the other\n\t\t\t\t\t\t// system's range is too low for ours\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\tif (version == 0) {\n\t\t\t\t\t\t\tWWMessageBox().Process (TXT_DESTGAME_OUTDATED);\n\n\t\t\t\t\t\t\t// to skip the other system not responding msg\n\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\trc = false;\n\t\t\t\t\t\t} else if (version == 0xffffffff) {\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t// If the greatest-common-version comes back 0xffffffff,\n\t\t\t\t\t\t// the other system's range is too high for ours\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t\tWWMessageBox().Process (TXT_YOURGAME_OUTDATED);\n\n\t\t\t\t\t\t\t// to skip the other system not responding msg\n\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\trc = false;\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tif (ReceivePacket.ScenarioInfo.CheatCheck != RuleINI.Get_Unique_ID()) {\n\t\t\t\t\t\t\t\tWWMessageBox().Process (TXT_MISMATCH);\n\n\t\t\t\t\t\t\t\t// to skip the other system not responding msg\n\t\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\trc = false;\n\n\t\t\t\t\t\t\t} else {\n\n\n\t\t\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t\t\t// Otherwise, 'version' is the highest version we have in\n\t\t\t\t\t\t\t\t// common; look up the protocol that goes with this version.\n\t\t\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t\t\tSession.CommProtocol = VerNum.Version_Protocol(version);\n#ifndef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\tPlayingAgainstVersion = version;\n#endif\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t/*.........................................................\n\t\t\t\t\t\tIf this is the first game-options packet we've received,\n\t\t\t\t\t\tinit the game & player lists\n\t\t\t\t\t\t.........................................................*/\n\t\t\t\t\t\tif (playerlist.Count()==0) {\n\t\t\t\t\t\t\t//......................................................\n\t\t\t\t\t\t\t// Add two strings to the player list\n\t\t\t\t\t\t\t//......................................................\n\t\t\t\t\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\t//Need room to display country name\n\t\t\t\t\t\t\tplayerlist.Add_Item(item,\n\t\t\t\t\t\t\t\t&ColorRemaps[Session.ColorIdx]);\n\t\t\t\t\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\t//Need room to display country name\n\t\t\t\t\t\t\tplayerlist.Add_Item(item,\n\t\t\t\t\t\t\t\t&ColorRemaps[TheirColor]);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// Ensure the player list has the latest, greatest copy of\n\t\t\t\t\t\t// our names & colors.  Do this every time we receive an\n\t\t\t\t\t\t// options packet.\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\titem = (char *)playerlist.Get_Item(0);\n#ifdef OLDWAY\n\t\t\t\t\t\tif (Session.House==HOUSE_GOOD) {\n\t\t\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf,\n\t\t\t\t\t\t\t\tText_String(TXT_ALLIES));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf,\n\t\t\t\t\t\t\t\tText_String(TXT_SOVIET));\n\t\t\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\t\t\tsprintf (item, \"%s\\t%s\", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\t\t\t\t\t\tplayerlist.Colors[0] = &ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx];\n\n\t\t\t\t\t\titem = (char *)playerlist.Get_Item(1);\n#ifdef\tOLDWAY\n\t\t\t\t\t\tif (TheirHouse==HOUSE_GOOD) {\n\t\t\t\t\t\t\tsprintf(item,\"%s\\t%s\",TheirName,\n\t\t\t\t\t\t\t\tText_String(TXT_ALLIES));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsprintf(item,\"%s\\t%s\",TheirName,\n\t\t\t\t\t\t\t\tText_String(TXT_SOVIET));\n\t\t\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\t\t\tsprintf (item, \"%s\\t%s\", TheirName, Text_String(HouseTypeClass::As_Reference(TheirHouse).Full_Name()));\n#endif\t//OLDWAY\n\t\t\t\t\t\tplayerlist.Colors[1] = &ColorRemaps[(TheirColor == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : TheirColor];\n\n\t\t\t\t\t\tplayerlist.Flag_To_Redraw();\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// Play a little sound effect\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tIncoming message: add to our list\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tcase (SERIAL_MESSAGE):\n\t\t\t\t\t\toppscorescreen = false;\n\n\t\t\t\t\t\tSession.Messages.Add_Message (ReceivePacket.Name,\n\t\t\t\t\t\t\t((PlayerColorType)ReceivePacket.ID == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : (PlayerColorType)ReceivePacket.ID,\n\t\t\t\t\t\t\tReceivePacket.Message.Message,\n\t\t\t\t\t\t\t((PlayerColorType)ReceivePacket.ID == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : (PlayerColorType)ReceivePacket.ID,\n\t\t\t\t\t\t\tTPF_TEXT, -1);\n\n\t\t\t\t\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t//\n\t\t\t\t\t// get their response time\n\t\t\t\t\t//\n\t\t\t\t\tcase (SERIAL_TIMING):\n\t\t\t\t\t\toppscorescreen = false;\n\t\t\t\t\t\ttheirresponsetime = ReceivePacket.ScenarioInfo.ResponseTime;\n\n\t\t\t\t\t\tif ( !gameoptions ) {\n\n\t\t\t\t\t\t\t// retransmit of game options packet again\n\t\t\t\t\t\t\ttransmit = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t//\n\t\t\t\t\t// print msg waiting for opponent\n\t\t\t\t\t//\n\t\t\t\t\tcase (SERIAL_SCORE_SCREEN):\n\t\t\t\t\t\toppscorescreen = true;\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\t\tparms_received = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if we haven't received a msg for 10 seconds exit\n\n\t\tif (!skirmish && (TickCount - lastmsgtime) > msg_timeout) {\n\t\t\tWWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);\n\t\t\tprocess = false;\n\t\t\trc = false;\n\n\t\t\t// say we did receive sign off to keep from sending one\n\t\t\trecsignedoff = true;\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tService the connection\n\t\t---------------------------------------------------------------------*/\n\t\tif (!skirmish) {\n\t\t\tNullModem.Service();\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tPrepare to load the scenario\n\t------------------------------------------------------------------------*/\n\tif (rc) {\n\t\tSession.NumPlayers = skirmish ? 1 : 2;\n\n\t\tScen.Scenario = Session.Options.ScenarioIndex;\n\t\tstrcpy (Scen.ScenarioName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename());\n\n\t\t/*.....................................................................\n\t\tAdd both players to the Players vector; the local system is always\n\t\tindex 0.\n\t\t.....................................................................*/\n\t\twho = new NodeNameType;\n\t\tstrcpy(who->Name, namebuf);\n\t\twho->Player.House = Session.House;\n\t\twho->Player.Color = Session.ColorIdx;\n\t\twho->Player.ProcessTime = -1;\n\t\tSession.Players.Add (who);\n\n\t\t/*\n\t\t**\tFetch the difficulty setting when in skirmish mode.\n\t\t*/\n\t\tif (skirmish) {\n\t\t\tint diff = difficulty.Get_Value() * (Rule.IsFineDifficulty ? 1 : 2);\n\t\t\tswitch (diff) {\n\t\t\t\tcase 0:\n\t\t\t\t\tScen.CDifficulty = DIFF_HARD;\n\t\t\t\t\tScen.Difficulty = DIFF_EASY;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 1:\n\t\t\t\t\tScen.CDifficulty = DIFF_HARD;\n\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 2:\n\t\t\t\t\tScen.CDifficulty = DIFF_NORMAL;\n\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 3:\n\t\t\t\t\tScen.CDifficulty = DIFF_EASY;\n\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 4:\n\t\t\t\t\tScen.CDifficulty = DIFF_EASY;\n\t\t\t\t\tScen.Difficulty = DIFF_HARD;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\tScen.CDifficulty = DIFF_NORMAL;\n\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t}\n\n\t\tif (!skirmish) {\n\t\t\twho = new NodeNameType;\n\n\t\t\t#ifdef FIXIT_MODEM_LOAD_CRASH\n\t\t\t/* If the names of the players are the same then we MUST force them\n\t\t\t * be be unique. This is necessary to prevent a crash after loading\n\t\t\t * a modem save game.\n\t\t\t */\n\t\t\tif (strcmp(TheirName, namebuf) == 0)\n\t\t\t\t{\n\t\t\t\tif (strlen(TheirName) == (MPLAYER_NAME_MAX - 1))\n\t\t\t\t\t{\n\t\t\t\t\tTheirName[MPLAYER_NAME_MAX - 1] = '\\0';\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tstrcat(TheirName, \"2\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t#endif\n\n\t\t\tstrcpy(who->Name, TheirName);\n\t\t\twho->Player.House = TheirHouse;\n\t\t\twho->Player.Color = TheirColor;\n\t\t\twho->Player.ProcessTime = -1;\n\t\t\tSession.Players.Add (who);\n\t\t}\n\n\t\t/*.....................................................................\n\t\tSend all players a GO packet.\n\t\t.....................................................................*/\n\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\tif (load_game) {\n\t\t\tSendPacket.Command = SERIAL_LOADGAME;\n\t\t} else {\n\t\t\tSendPacket.Command = SERIAL_GO;\n\t\t}\n\n\t\tif (!skirmish) {\n\t\t\tSendPacket.ScenarioInfo.ResponseTime = NullModem.Response_Time();\n\t\t\tif ( theirresponsetime == 10000 ) {\n\t\t\t\t;\n\t\t\t} else if (SendPacket.ScenarioInfo.ResponseTime < theirresponsetime) {\n\t\t\t\tSendPacket.ScenarioInfo.ResponseTime = theirresponsetime;\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t// calculated one way delay for a packet and overall delay to execute\n\t\t// a packet\n\t\t//\n\t\tif (!skirmish) {\n\t\t\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\t\t\tSession.MaxAhead = max( ((((SendPacket.ScenarioInfo.ResponseTime / 8) +\n\t\t\t\t\t(Session.FrameSendRate - 1)) / Session.FrameSendRate) *\n\t\t\t\t\tSession.FrameSendRate), (Session.FrameSendRate * 2)\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tSession.MaxAhead = max( (SendPacket.ScenarioInfo.ResponseTime / 8),\n\t\t\t\t\t\t\t\t\t\t\t  MODEM_MIN_MAX_AHEAD );\n\t\t\t}\n\t\t}\n\t\tSendPacket.ID = Session.ModemType;\n\n\t\tif (!skirmish) {\n\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\t\t\tstarttime = TickCount;\n\t\t\twhile ( ( NullModem.Num_Send()\n\t\t\t\t&& ((TickCount - starttime) < PACKET_SENDING_TIMEOUT) )\n\t\t\t\t|| ((TickCount - starttime) < 60) ) {\n\t\t\t\t#if(SHOW_MONO)\n\t\t\t\tNullModem.Mono_Debug_Print(0);\n\t\t\t\t#endif\n\n\t\t\t\tNullModem.Service();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Wait for the go response. This will be either a 'GO' reply, a\n\t\t\t** request for the scenario to be sent or a reply to say that the scenario\n\t\t\t** cant be played.\n\t\t\t*/\n#ifdef WIN32\n\t\t\tWWDebugString (\"RA95 - About to wait for 'GO' response.\\n\");\n#endif\n\t\t\tdo {\n\t\t\t\tNullModem.Service();\n\n\t\t\t\tif (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) {\n\n#ifdef FIXIT_VERSION_3\n \t\t\t\t\tif (ReceivePacket.Command == SERIAL_READY_TO_GO)\n\t\t\t\t\t{\n\t\t\t\t\t\tif( Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official() )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif( !Force_Scenario_Available( Scen.ScenarioName ) )\n\t\t\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n#else\n \t\t\t\t\tif (ReceivePacket.Command == SERIAL_READY_TO_GO) break;\n#endif\n\n\t\t\t\t\tif (ReceivePacket.Command == SERIAL_NO_SCENARIO) {\n\t\t\t\t\t\tWWMessageBox().Process(TXT_NO_EXPANSION_SCENARIO, TXT_CANCEL);\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** We have to recover from this somehow so....\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tprocess = true;\n\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t\tlastmsgtime = TickCount;\n\t\t\t\t\t\tgoto oh_dear_its_a_label;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (ReceivePacket.Command == SERIAL_REQ_SCENARIO) {\n#ifdef WIN32\n\t\t\t\t\t\tWWDebugString (\"RA95 - About to call 'Send_Remote_File'.\\n\");\n\n#endif\n\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\tif( Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official() )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif( !Force_Scenario_Available( Scen.ScenarioName ) )\n\t\t\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t\t}\n#endif\n\n\t\t\t\t\t\tSend_Remote_File (Scen.ScenarioName, 0);\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} while ( !Keyboard->Check() );\n\n\t\t// clear queue to keep from doing any resends\n\t\t\tNullModem.Init_Send_Queue();\n\t\t}\n\n\t} else {\n\t\tif ( !recsignedoff ) {\n\t\t\t/*.....................................................................\n\t\t\tBroadcast my sign-off over my network\n\t\t\t.....................................................................*/\n\t\t\tif (!skirmish) {\n\t\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\t\tSendPacket.Command = SERIAL_SIGN_OFF;\n\t\t\t\tSendPacket.ScenarioInfo.Color = Session.ColorIdx;\t\t// use Color for ID\n\t\t\t\tSendPacket.ID = Session.ModemType;\n\t\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\n\t\t\t\tstarttime = TickCount;\n\t\t\t\twhile ( (NullModem.Num_Send()\n\t\t\t\t\t&& ((TickCount - starttime) < PACKET_CANCEL_TIMEOUT) )\n\t\t\t\t\t|| ((TickCount - starttime) < 60) ) {\n\t\t\t\t\t#if(SHOW_MONO)\n\t\t\t\t\tNullModem.Mono_Debug_Print(0);\n\t\t\t\t\t#endif\n\n\t\t\t\t\tif ( NullModem.Get_Message( &ReceivePacket, &packetlen ) > 0) {\n\n\t\t\t\t\t\t// are we getting our own packets back??\n\n\t\t\t\t\t\tif (ReceivePacket.Command == SERIAL_SIGN_OFF\n\t\t\t\t\t\t\t&& ReceivePacket.ID == Session.ModemType) {\n\n\t\t\t\t\t\t\t// exit while\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tNullModem.Service();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!skirmish) Shutdown_Modem();\n\t}\n\n\t/*------------------------------------------------------------------------\n\tClear all lists\n\t------------------------------------------------------------------------*/\n\twhile (scenariolist.Count()) {\n\t\tscenariolist.Remove_Item(scenariolist.Get_Item(0));\n\t}\n\n\t/*------------------------------------------------------------------------\n\tClean up the list boxes\n\t------------------------------------------------------------------------*/\n\twhile (playerlist.Count()>0) {\n\t\titem = (char *)playerlist.Get_Item(0);\n\t\tdelete [] item;\n\t\tplayerlist.Remove_Item(item);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tRemove the chat edit box\n\t------------------------------------------------------------------------*/\n\tSession.Messages.Remove_Edit();\n\n\t/*------------------------------------------------------------------------\n\tRestore screen\n\t------------------------------------------------------------------------*/\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n\tShow_Mouse();\n\n\t/*------------------------------------------------------------------------\n\tSave any changes made to our options\n\t------------------------------------------------------------------------*/\n\tif (changed) {\n\t\tSession.Write_MultiPlayer_Settings();\n\t}\n\n\tif (load_game && !skirmish) {\n\t\tif (!Load_Game (-1)) {\n\t\t\tWWMessageBox().Process (TXT_ERROR_LOADING_GAME);\n\t\t\trc = false;\n\t\t}\n\t\tFrame++;\n\t}\n\n\treturn(rc);\n}\n\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern bool Is_Mission_Aftermath (char *file_name);\n#endif\n\n/***********************************************************************************************\n * Find_Local_Scenario -- finds the file name of the scenario with matching attributes         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to Scenario description                                                       *\n *           ptr to Scenario filename to fix up                                                *\n *           length of file for trivial rejection of scenario files                            *\n *           ptr to digest. Digests must match.                                                *\n *                                                                                             *\n *                                                                                             *\n * OUTPUT:   true if scenario is available locally                                             *\n *                                                                                             *\n * WARNINGS: We need to reject files that don't match exactly because scenarios with the same  *\n *           description can exist on both machines but have different contents. For example   *\n *           there will be lots of scenarios called 'my map' and 'crap' and 'aaaaaa'.          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/23/96 12:36PM ST : Created                                                             *\n *=============================================================================================*/\nbool Find_Local_Scenario (char *description, char *filename, unsigned int length, char *digest, bool official)\n{\n//FILE *fp;\n//fp = fopen(\"findscen.txt\",\"wt\");\n//debugprint(\"looking for local scenario: description = %s, name=%s, length=%d, digest=%s, official=%d\\n\", description, filename, length, digest, official);\n\n\tchar digest_buffer[32];\n\t/*\n\t** Scan through the scenario list looking for scenarios with matching descriptions.\n\t*/\n\tfor (int index = 0; index < Session.Scenarios.Count(); index++) {\n\n//debugprint( \"Checking against scenario: %s\\n\", Session.Scenarios[index]->Description());\n\t\tif (!strcmp (Session.Scenarios[index]->Description(), description)) {\n//debugprint(\"found matching description.\\n\");\n\t\t\tCCFileClass file (Session.Scenarios[index]->Get_Filename());\n\n\t\t\t/*\n\t\t\t** Possible rejection on the basis of availability.\n\t\t\t*/\n\t\t\tif (file.Is_Available()) {\n//debugprint(\"file is available.\\n\");\n\t\t\t\t/*\n\t\t\t\t** Possible rejection on the basis of size.\n\t\t\t\t*/\n\t\t\t\tif (file.Size() == length) {\n//debugprint(\"length matches.\\n\");\n\t\t\t\t\t/*\n\t\t\t\t\t** We don't know the digest for 'official' scenarios so assume its correct\n\t\t\t\t\t*/\n\t\t\t\t\tif (!official) {\n//debugprint(\"!official.\\n\");\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Possible rejection on the basis of digest\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tINIClass ini;\n\t\t\t\t\t\tini.Load(file);\n\t\t\t\t\t\tini.Get_String (\"Digest\", \"1\", \"No digest here mate. Nope.\", digest_buffer, sizeof (digest_buffer) );\n\t\t\t\t\t}\n//debugprint(\"digest = %s, digest_buffer = %s.\\n\", digest, digest_buffer);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98. But don't know why this happens. Because of autodownload?\n\t\t\t\t\t/*\n\t\t\t\t\t** If this is an aftermath scenario then ignore the digest and return success.\n\t\t\t\t\t*/\n\t\t\t\t\tif ( Is_Mission_Aftermath ((char*)Session.Scenarios[index]->Get_Filename()) ) {\n//debugprint(\"a 1match!\\n\");\n\t\t\t\t\t\tstrcpy (filename, Session.Scenarios[index]->Get_Filename());\n\t\t\t\t\t\treturn (true);\n\t\t\t\t\t}\n#endif\n\n\t\t\t\t\t/*\n\t\t\t\t\t** This must be the same scenario. Copy the name and return true.\n\t\t\t\t\t*/\n\t\t\t\t\tif (official || !strcmp (digest, digest_buffer)) {\n//debugprint(\"a match!\\n\");\n\t\t\t\t\t\tstrcpy (filename, Session.Scenarios[index]->Get_Filename());\n\t\t\t\t\t\treturn (true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n//\t\t\telse\n//\t\t\t\tdebugprint(\"file not available '%s'.\\n\", Session.Scenarios[index]->Get_Filename());\n\n\t\t}\n\t}\n//debugprint(\"failed match.\\n\");\n\t/*\n\t** Couldnt find the scenario locally. Return failure.\n\t*/\n\treturn (false);\n}\n\n\n\n\n\n\n/***********************************************************************************************\n * Com_Show_Scenario_Dialog -- Serial game scenario selection dialog\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * The 'Players' vector is filled in by this routine, when the game starts; this\t\t\t\t\t  *\n * is for the Assign_Houses routine, which expects this vector to contain all\t\t\t\t\t\t  *\n * players' names & houses & colors.  Other than that, the Players vector, Games\t\t\t\t\t  *\n * vector, and Chat vector aren't used at all by this routine.  The Game & Players\t\t\t\t  *\n * list boxes are filled in manually in the processing loop.\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *    Ŀ                      \t  *\n *                            Serial Game                                                \t  *\n *                                                                                      \t  *\n *                       Your Name: __________                         \t\t\t\t\t\t\t  *\n *                           House: [GDI] [NOD]                   \t\t\t\t\t\t\t\t\t  *\n *                   Desired Color: [ ][ ][ ][ ]                   \t   \t\t\t\t\t\t  *\n *                                                                                    \t \t  *\n *                         Opponent: Name                                             \t \t  *\n *                         Scenario: Description                     \t\t\t\t\t\t\t\t  *\n *                          Credits: xxxx                            \t\t\t\t\t\t\t\t  *\n *                            Bases: ON                                              \t \t  *\n *                           Crates: ON                                              \t \t  *\n *                         Tiberium: ON                                              \t \t  *\n *                           Ghosts: ON                                              \t \t  *\n *                                                                                   \t \t  *\n *                             [Cancel]                                               \t \t  *\n *                                                                                   \t \t  *\n *       Ŀ                      \t \t  *\n *                                                                                 \t \t  *\n *                                                                                 \t \t  *\n *                             \t \t  *\n *                           [Send Message]                                          \t \t  *\n *                          \t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\ttrue = success, false = cancel\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   02/14/1995 BR : Created.                                              \t\t\t\t\t\t  *\n *=============================================================================================*/\nint Com_Show_Scenario_Dialog(void)\n{\n\t/*........................................................................\n\tDialog & button dimensions\n\t........................................................................*/\n\tint d_dialog_w = 320 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 200 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2);\t\t// dialog x-coord\n\tint d_dialog_y = ((200 * RESFACTOR - d_dialog_h) / 2);\t\t// dialog y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_txt6_h = 6 * RESFACTOR+1;\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_margin1 = 5 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// margin width/height\n\tint d_margin2 = 2 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint d_name_w = 70 * RESFACTOR;\n\tint d_name_h = 9 * RESFACTOR;\n\tint d_name_x = d_dialog_x + (d_dialog_w / 4) - (d_name_w / 2);\n\tint d_name_y = d_dialog_y + d_margin1 + d_margin2 + d_txt6_h + 1*RESFACTOR;\n\n#ifdef OLDWAY\n\tint d_gdi_w = 40 * RESFACTOR;\n\tint d_gdi_h = 9 * RESFACTOR;\n\tint d_gdi_x = d_dialog_cx - d_gdi_w;\n\tint d_gdi_y = d_name_y;\n\n\tint d_nod_w = 40 * RESFACTOR;\n\tint d_nod_h = 9 * RESFACTOR;\n\tint d_nod_x = d_dialog_cx;\n\tint d_nod_y = d_name_y;\n\n#else\t//OLDWAY\n\n\tint d_house_w = 60 *RESFACTOR;\n\tint d_house_h = (8 * 5 *RESFACTOR);\n\tint d_house_x = d_dialog_cx - (d_house_w / 2);\n\tint d_house_y = d_name_y;\n\n#endif\t//OLDWAY\n\n\tint d_color_w = 10 * RESFACTOR;\n\tint d_color_h = 9 * RESFACTOR;\n\tint d_color_x = d_dialog_x + ((d_dialog_w / 4) * 3) - (d_color_w * 3);\n\tint d_color_y = d_name_y;\n\n\tint d_scenario_y = d_name_y + d_name_h + d_margin2;\n\n\tint d_gamelist_w = 160 * RESFACTOR;\n\tint d_gamelist_h = (6 * 6 * RESFACTOR) + 3 * RESFACTOR;\t\t// 6 rows high\n\tint d_gamelist_x = d_dialog_x + d_margin1 + 10*RESFACTOR;\n\tint d_gamelist_y = d_scenario_y + d_txt6_h + d_margin2 + d_txt6_h + d_margin2;\n\n//BG\tint d_playerlist_w = 112 * RESFACTOR;\n\tint d_playerlist_w = 118 * RESFACTOR;\n\tint d_playerlist_h = (6 * 6 * RESFACTOR) + 3 * RESFACTOR;\t\t// 6 rows high\n\tint d_playerlist_x = d_dialog_x + d_dialog_w - d_margin1 - d_margin1 - d_playerlist_w - 5*RESFACTOR;\n\tint d_playerlist_y = d_gamelist_y;\n\n\tint d_count_w = 25 * RESFACTOR;\n\tint d_count_h = d_txt6_h;\n\tint d_count_x = d_gamelist_x + (d_gamelist_w / 2);\n\tint d_count_y = d_gamelist_y + d_gamelist_h + (d_margin1 * 2) - d_margin2;\n\n\tint d_level_w = 25 * RESFACTOR;\n\tint d_level_h = d_txt6_h;\n\tint d_level_x = d_gamelist_x + (d_gamelist_w / 2);\n\tint d_level_y = d_count_y + d_count_h;\n\n\tint d_credits_w = 25 * RESFACTOR;\n\tint d_credits_h = d_txt6_h;\n\tint d_credits_x = d_gamelist_x + (d_gamelist_w / 2);\n\tint d_credits_y = d_level_y + d_level_h;\n\n\tint d_aiplayers_w = 25 * RESFACTOR;\n\tint d_aiplayers_h = d_txt6_h;\n\tint d_aiplayers_x = d_gamelist_x + (d_gamelist_w / 2);\n\tint d_aiplayers_y = d_credits_y + d_credits_h;\n\n\tint d_options_w = 112 * RESFACTOR;\n\tint d_options_h = (5 * 6* RESFACTOR) + 4*RESFACTOR;\n\tint d_options_x = d_playerlist_x;\n\tint d_options_y = d_playerlist_y + d_playerlist_h + d_margin1 - d_margin2;\n\n\tint d_message_w = d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR;\n\tint d_message_h = (7 * d_txt6_h) + 3 * RESFACTOR;\t\t// 7 rows high\n\tint d_message_x = d_gamelist_x;//d_dialog_x + d_margin1 + 10*RESFACTOR;\n\tint d_message_y = d_options_y + d_options_h + d_margin2/*KO + d_margin1*/;\n\n\tint d_send_w = d_message_w;\n\tint d_send_h = 9 * RESFACTOR;\n\tint d_send_x = d_message_x;\n\tint d_send_y = d_message_y + d_message_h;\n\n\tint d_cancel_w = 45 * RESFACTOR;\n\tint d_cancel_h = 9 * RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - (d_cancel_w / 2);\n\tint d_cancel_y = d_send_y + d_send_h/*KO + d_margin2*/;\n\n\t/*........................................................................\n\tButton Enumerations\n\t........................................................................*/\n\tenum {\n\t\tBUTTON_NAME = 100,\n#ifdef OLDWAY\n\t\tBUTTON_GDI,\n\t\tBUTTON_NOD,\n#else\t//OLDWAY\n\t\tBUTTON_HOUSE,\n#endif\t//OLDWAY\n\t\tBUTTON_GAMELIST,\n\t\tBUTTON_PLAYERLIST,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_COUNT,\n\t\tBUTTON_LEVEL,\n\t\tBUTTON_CREDITS,\n\t\tBUTTON_AI_PLAYERS,\n\t\tBUTTON_OPTIONS,\n\t};\n\n\t/*........................................................................\n\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t........................................................................*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PARMS,\n\t\tREDRAW_MESSAGE,\n\t\tREDRAW_COLORS,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*........................................................................\n\tDialog variables\n\t........................................................................*/\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tint cbox_x[] = {\n\t\t\t\t\t\t\td_color_x,\n\t\t\t\t\t\t\td_color_x + d_color_w,\n\t\t\t\t\t\t\td_color_x + (d_color_w * 2),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 3),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 4),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 5),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 6),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 7)\n\t\t\t\t\t\t\t};\n\n\tchar namebuf[MPLAYER_NAME_MAX] = {0};\t\t// buffer for player's name\n//BG\tint playertabs[] = {77};\t\t\t\t// tabs for player list box\n\tint playertabs[] = {71*RESFACTOR};\t\t\t\t// tabs for player list box\n\tint optiontabs[] = {8};\t\t\t\t\t// tabs for options list box\n\tbool transmit;\t\t\t\t\t\t\t\t\t\t// 1 = re-transmit new game options\n\tbool first;\t\t\t\t\t\t\t\t\t\t\t// 1 = no packets received yet\n\tbool parms_received = false;\t\t\t\t\t// 1 = game options received\n\tbool changed = false;\t\t\t\t\t\t\t// 1 = user has changed an option\n\n\tint rc;\n\tint recsignedoff = 0;\n\tint i;\n\tunsigned long version;\n\tchar txt[80];\n\tunsigned long starttime;\n\tunsigned long timingtime;\n\tunsigned long lastmsgtime;\n\tunsigned long lastredrawtime;\n\tunsigned long transmittime = 0;\n\tint packetlen;\n\tbool oppscorescreen = false;\n\tbool gameoptions = false;\n\tEventClass *event;\t\t\t\t\t// event ptr\n\tunsigned long msg_timeout = 1200;\t// init to 20 seconds\n\tbool load_game = false;\t\t\t\t\t// 1 = load saved game\n\tNodeNameType *who;\t\t\t\t\t// node to add to Players\n\tchar *item;\t\t\t\t\t\t\t\t// for filling in lists\n\tchar *p;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\tSession.Options.ScenarioDescription[0] = 0;\t//Flag that we dont know the scenario name yet\n\tbool messages_have_focus = true;\n\tbool ready_packet_was_sent = false;\n\n\t/*........................................................................\n\tButtons\n\t........................................................................*/\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tEditClass name_edt(BUTTON_NAME, namebuf, MPLAYER_NAME_MAX, TPF_TEXT, d_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC);\n#ifdef OLDWAY\n\tTextButtonClass gdibtn(BUTTON_GDI, TXT_ALLIES, TPF_BUTTON, d_gdi_x, d_gdi_y, d_gdi_w, d_gdi_h);\n\tTextButtonClass nodbtn(BUTTON_NOD, TXT_SOVIET, TPF_BUTTON, d_nod_x, d_nod_y, d_nod_w, d_nod_h);\n#else\t//OLDWAY\n\tchar housetext[25] = \"\";\n\tFancy_Text_Print(\"\", 0, 0, 0, 0, TPF_TEXT);\n\tDropListClass housebtn(BUTTON_HOUSE, housetext, sizeof(housetext),\n\t\tTPF_TEXT,\n\t\td_house_x, d_house_y, d_house_w, d_house_h,\n\t\tMFCD::Retrieve(\"BTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"BTN-DN.SHP\"));\n#endif\t//OLDWAY\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w);\n\tListClass gamelist(BUTTON_GAMELIST, d_gamelist_x, d_gamelist_y, d_gamelist_w, d_gamelist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\n\tGaugeClass countgauge(BUTTON_COUNT, d_count_x, d_count_y, d_count_w, d_count_h);\n\tchar staticcountbuff[35];\n\tStaticButtonClass staticcount(0, \"     \", TPF_TEXT, d_count_x+d_count_w+3*RESFACTOR, d_count_y);\n\n\tGaugeClass levelgauge(BUTTON_LEVEL, d_level_x, d_level_y, d_level_w, d_level_h);\n\tchar staticlevelbuff[35];\n\tStaticButtonClass staticlevel(0, \"     \", TPF_TEXT, d_level_x+d_level_w+3*RESFACTOR, d_level_y);\n\n\tGaugeClass creditsgauge(BUTTON_CREDITS, d_credits_x, d_credits_y, d_credits_w, d_credits_h);\n\tchar staticcreditsbuff[35];\n\tStaticButtonClass staticcredits(0, \"         \", TPF_TEXT, d_credits_x+d_credits_w+3*RESFACTOR, d_credits_y);\n\n\tGaugeClass aiplayersgauge(BUTTON_AI_PLAYERS, d_aiplayers_x, d_aiplayers_y, d_aiplayers_w, d_aiplayers_h);\n\tchar staticaibuff[35];\n\tStaticButtonClass staticai(0, \"     \", TPF_TEXT, d_aiplayers_x+d_aiplayers_w+3*RESFACTOR, d_aiplayers_y);\n\n\tCheckListClass optionlist(BUTTON_OPTIONS, d_options_x, d_options_y, d_options_w, d_options_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\n\t/*\n\t------------------------- Build the button list --------------------------\n\t*/\n\tcommands = &name_edt;\n\tstaticcount.Add_Tail(*commands);\n\tstaticcredits.Add_Tail(*commands);\n\tstaticai.Add_Tail(*commands);\n\tstaticlevel.Add_Tail(*commands);\n\tcancelbtn.Add_Tail(*commands);\n\tgamelist.Add_Tail(*commands);\n\tplayerlist.Add_Tail(*commands);\n\tcountgauge.Add_Tail(*commands);\n\tlevelgauge.Add_Tail(*commands);\n\tcreditsgauge.Add_Tail(*commands);\n\taiplayersgauge.Add_Tail(*commands);\n\toptionlist.Add_Tail(*commands);\n#ifdef OLDWAY\n\tgdibtn.Add_Tail(*commands);\n\tnodbtn.Add_Tail(*commands);\n#else\t//OLDWAY\n\thousebtn.Add_Tail(*commands);\n#endif\t//OLDWAY\n\n\n\t//------------------------------------------------------------------------\n\t//\tInit the button states\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t// Name & Color\n\t//........................................................................\n\tSession.ColorIdx = Session.PrefColor;\t\t\t// init my preferred color\n\tstrcpy (namebuf, Session.Handle);\t\t\t\t// set my name\n\tname_edt.Set_Text(namebuf,MPLAYER_NAME_MAX);\n\tname_edt.Set_Color(&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]);\n\n\t//........................................................................\n\t// List boxes\n\t//........................................................................\n\tplayerlist.Set_Tabs(playertabs);\n\tplayerlist.Set_Selected_Style(ColorListClass::SELECT_NORMAL);\n\n\toptionlist.Set_Tabs(optiontabs);\n\toptionlist.Set_Read_Only(1);\n\n\toptionlist.Add_Item(Text_String(TXT_BASES));\n\toptionlist.Add_Item(Text_String(TXT_ORE_SPREADS));\n\toptionlist.Add_Item(Text_String(TXT_CRATES));\n\toptionlist.Add_Item(Text_String(TXT_CAPTURE_THE_FLAG));\n\toptionlist.Add_Item(Text_String(TXT_SHADOW_REGROWS));\n\n\toptionlist.Check_Item(0, Session.Options.Bases);\n\toptionlist.Check_Item(1, Session.Options.Tiberium);\n\toptionlist.Check_Item(2, Session.Options.Goodies);\n\toptionlist.Check_Item(3, Special.IsCaptureTheFlag);\n\toptionlist.Check_Item(4, Special.IsShadowGrow);\n\n\t//........................................................................\n\t// House buttons\n\t//........................................................................\n#ifdef OLDWAY\n\tif (Session.House==HOUSE_GOOD) {\n\t\tgdibtn.Turn_On();\n\t} else {\n\t\tnodbtn.Turn_On();\n\t}\n#else\t//OLDWAY\n\tfor (HousesType house = HOUSE_USSR; house <= HOUSE_FRANCE; house++) {\n\t\thousebtn.Add_Item(Text_String(HouseTypeClass::As_Reference(house).Full_Name()));\n\t}\n\thousebtn.Set_Selected_Index(Session.House - HOUSE_USSR);\n\thousebtn.Set_Read_Only (true);\n#endif\t//OLDWAY\n\n\t//........................................................................\n\t// Option gauges\n\t//........................................................................\n\tcountgauge.Use_Thumb(0);\n\tcountgauge.Set_Maximum(SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]);\n\tcountgauge.Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]);\n\n\tlevelgauge.Use_Thumb(0);\n\tlevelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1);\n\tlevelgauge.Set_Value(BuildLevel - 1);\n\n\tcreditsgauge.Use_Thumb(0);\n\tcreditsgauge.Set_Maximum(Rule.MPMaxMoney);\n\tcreditsgauge.Set_Value(Session.Options.Credits);\n\n\taiplayersgauge.Use_Thumb(0);\n\taiplayersgauge.Set_Maximum(Rule.MaxPlayers-2);\n\taiplayersgauge.Set_Value(Session.Options.AIPlayers);\n\n\tFancy_Text_Print(\"\", 0, 0, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\n\ttransmit = true;\n\tfirst = true;\n\n\t/*........................................................................\n\tClear the Players vector\n\t........................................................................*/\n\tClear_Vector(&Session.Players);\n\n\t/*........................................................................\n\tInit the message display system\n\t........................................................................*/\n\tSession.Messages.Init (d_message_x + 1, d_message_y + 1, 7,\n\t\tMAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 * RESFACTOR, d_send_y + 1 * RESFACTOR, 1,\n\t\t20, MAX_MESSAGE_LENGTH - 5, d_message_w);\n\tSession.Messages.Add_Edit ((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message_w);\n\tSession.WWChat = 0;\n\n\t/*........................................................................\n\tInit version number clipping system\n\t........................................................................*/\n\tVerNum.Init_Clipping();\n\tLoad_Title_Page(true);\n\tCCPalette.Set();\n\n\textern char ModemRXString[];\n\n\tif (strlen(ModemRXString) > 36)\n\t\tModemRXString[36] = 0;\n\n\tif (strlen(ModemRXString) > 0)\n\t\tSession.Messages.Add_Message (NULL, 0, ModemRXString, PCOLOR_BROWN,\n\t\t\tTPF_TEXT, -1);\n\n\tModemRXString[0] = '\\0';\n\n\t/*\n\t---------------------------- Init Mono Output ----------------------------\n\t*/\n\t#if(SHOW_MONO)\n\tNullModem.Configure_Debug(sizeof (CommHeaderType),sizeof (SerialCommandType),\n\t\tSerialPacketNames, 100, 8);\n\tNullModem.Mono_Debug_Print(1);\n\t#endif\n\n\t/*\n\t---------------------------- Processing loop -----------------------------\n\t*/\n\tNullModem.Reset_Response_Time();\t\t// clear response time\n\ttimingtime = lastmsgtime = lastredrawtime = TickCount;\n\n\tbool process = true;\t\t\t\t\t\t// process while true\n\twhile (process) {\n\t\t#if(SHOW_MONO)\n\t\tNullModem.Mono_Debug_Print(0);\n\t\t#endif\n\n\t\t/*\n\t\t** Kludge to make sure we redraw the message input line when it loses focus.\n\t\t** If we dont do this then the cursor doesnt disappear.\n\t\t*/\n\t\tif (messages_have_focus) {\n\t\t\tif (name_edt.Has_Focus()) {\n\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\tmessages_have_focus = false;\n\t\t\t}\n\t\t} else {\n\t\t\tif (!name_edt.Has_Focus()) {\n\t\t\t\tmessages_have_focus = true;\n\t\t\t\tif (display < REDRAW_MESSAGE)\tdisplay = REDRAW_MESSAGE;\n\t\t\t\tSession.Messages.Set_Edit_Focus();\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t........................ Invoke game callback .........................\n\t\t*/\n\t\tCall_Back();\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\t#endif\n\n\t\t/*\n\t\t...................... Refresh display if needed ......................\n\t\t*/\n\t\tif (display) {\n\t\t\tif (housebtn.IsDropped) {\n\t\t\t\thousebtn.Collapse();\n\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t}\n\t\t\tHide_Mouse();\n\t\t\t/*\n\t\t\t.................. Redraw backgound & dialog box ...................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDialog & Field labels\n\t\t\t\t...............................................................*/\n\t\t\t\tFancy_Text_Print(TXT_CHANNEL_GAMES, d_gamelist_x + (d_gamelist_w / 2), d_gamelist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\tFancy_Text_Print(TXT_PLAYERS, d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\tFancy_Text_Print(TXT_YOUR_NAME, d_name_x + (d_name_w / 2), d_name_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n#ifdef OLDWAY\n\t\t\t\tFancy_Text_Print(TXT_SIDE_COLON, d_gdi_x + d_gdi_w, d_gdi_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n#else\n\t\t\t\tFancy_Text_Print(TXT_SIDE_COLON, d_house_x + (d_house_w / 2), d_house_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n#endif\n\t\t\t\tFancy_Text_Print(TXT_COLOR_COLON, d_dialog_x + ((d_dialog_w / 4) * 3), d_color_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\tFancy_Text_Print (TXT_COUNT, d_count_x - 2 * RESFACTOR, d_count_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print (TXT_LEVEL, d_level_x - 2 * RESFACTOR, d_level_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print (TXT_CREDITS_COLON, d_credits_x - 2 * RESFACTOR, d_credits_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print (TXT_AI_PLAYERS_COLON, d_aiplayers_x - 2 * RESFACTOR, d_aiplayers_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\n\t\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tDraw the color boxes\n\t\t\t..................................................................*/\n\t\t\tif (display >= REDRAW_COLORS) {\n\t\t\t\tfor (i = 0; i < MAX_MPLAYER_COLORS; i++) {\n\t\t\t\t\tLogicPage->Fill_Rect (cbox_x[i] + 1 * RESFACTOR, d_color_y + 1 * RESFACTOR,\n\t\t\t\t\t\tcbox_x[i] + 1 * RESFACTOR + d_color_w - 2 * RESFACTOR, d_color_y + 1 * RESFACTOR + d_color_h - 2 * RESFACTOR,\n\t\t\t\t\t\tColorRemaps[i].Box);\n//\t\t\t\t\t\t(i == PCOLOR_DIALOG_BLUE) ? ColorRemaps[PCOLOR_REALLY_BLUE].Box : ColorRemaps[i].Box);\n\n\t\t\t\t\tif (i == Session.ColorIdx) {\n\t\t\t\t\t\tDraw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h,\n\t\t\t\t\t\t\tBOXSTYLE_DOWN, false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tDraw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h,\n\t\t\t\t\t\t\tBOXSTYLE_RAISED, false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tDraw the message system; erase old messages first\n\t\t\t..................................................................*/\n\t\t\tif (display >= REDRAW_MESSAGE) {\n\t\t\t\tDraw_Box(d_message_x, d_message_y, d_message_w, d_message_h,\n\t\t\t\t\tBOXSTYLE_BOX, true);\n\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h,\n\t\t\t\t\tBOXSTYLE_BOX, true);\n\t\t\t\tSession.Messages.Draw();\n\n\t\t\t//..................................................................\n\t\t\t// Redraw the game options\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_PARMS && parms_received) {\n\t\t\t\t\tif (oppscorescreen) {\n\t\t\t\t\t\tsprintf(txt,\"%s\",Text_String(TXT_WAITING_FOR_OPPONENT));\n\n\t\t\t\t\t\tint txtwidth = String_Pixel_Width( txt );\n\n\t\t\t\t\t\tFancy_Text_Print(txt, d_dialog_cx, d_scenario_y, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t/*............................................................\n\t\t\t\t\t\tScenario description\n\t\t\t\t\t\t............................................................*/\n\t\t\t\t\t\t//LogicPage->Fill_Rect(d_dialog_x + 16*RESFACTOR, d_scenario_y,\n\t\t\t\t\t\t//\td_dialog_x + d_dialog_w - 16*RESFACTOR, d_scenario_y + d_txt6_h, BLACK);\n\n\t\t\t\t\t\tp = (char *)Text_String(TXT_SCENARIO_COLON);\n\t\t\t\t\t\tif (Session.Options.ScenarioDescription[0]) {\n//\t\t\t\t\t\t\tsprintf(txt,\"%s %s\",p, Session.Options.ScenarioDescription);\n//\t\t\t\t\t\t\tFancy_Text_Print (txt, d_dialog_cx, d_scenario_y, scheme, TBLACK, TPF_TEXT | TPF_CENTER);\n\n\t\t\t\t\t\t\t// EW - Scenario language translation goes here!!!!!!!! VG\n\t\t\t\t\t\t\tfor (i = 0; EngMisStr[i] != NULL;  i++) {\n\t\t\t\t\t\t\t\tif (!strcmp(Session.Options.ScenarioDescription, EngMisStr[i])) {\n#if defined(GERMAN) || defined(FRENCH)\n\t\t\t\t\t\t\t\t\tsprintf(txt, \"%s %s\", p, EngMisStr[i+1]);\n#else\n\t\t\t\t\t\t\t\t\tsprintf(txt, \"%s %s\", p, Session.Options.ScenarioDescription);\n#endif\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (EngMisStr[i] == NULL) {\n\t\t\t\t\t\t\t\tsprintf(txt, \"%s %s\", p, Session.Options.ScenarioDescription);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tFancy_Text_Print (txt, d_dialog_cx, d_scenario_y, scheme, TBLACK, TPF_TEXT | TPF_CENTER);\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsprintf(txt,\"%s %s\",p,Text_String(TXT_NOT_FOUND));\n\n\t\t\t\t\t\t\tFancy_Text_Print (txt, d_dialog_cx, d_scenario_y, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_TEXT | TPF_CENTER);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// Unit count, tech level, credits\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t//LogicPage->Fill_Rect(d_count_x + d_count_w + 2 * RESFACTOR, d_count_y,\n\t\t\t\t\t\t//\td_count_x + d_count_w + 35 * RESFACTOR, d_aiplayers_y + d_aiplayers_h+RESFACTOR,\n\t\t\t\t\t\t//\tBLACK);\n\n\t\t\t\t\t\tsprintf(staticcountbuff, \"%d\", Session.Options.UnitCount);\n\t\t\t\t\t\tstaticcount.Set_Text(staticcountbuff);\n\t\t\t\t\t\tstaticcount.Draw_Me();\n\t\t\t\t\t\tif (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {\n\t\t\t\t\t\t\tsprintf(staticlevelbuff, \"%d \", BuildLevel);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsprintf(staticlevelbuff, \"**\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstaticlevel.Set_Text(staticlevelbuff);\n\t\t\t\t\t\tstaticlevel.Draw_Me();\n\n\t\t\t\t\t\tsprintf(staticcreditsbuff, \"%d\", Session.Options.Credits);\n\t\t\t\t\t\tstaticcredits.Set_Text(staticcreditsbuff);\n\t\t\t\t\t\tstaticcredits.Draw_Me();\n\n\t\t\t\t\t\tsprintf(staticaibuff, \"%d\", Session.Options.AIPlayers);\n\t\t\t\t\t\tstaticai.Set_Text(staticaibuff);\n\t\t\t\t\t\tstaticai.Draw_Me();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t.......................... Redraw buttons ..........................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t........................... Get user input ............................\n\t\t*/\n\t\tmessages_have_focus = Session.Messages.Has_Edit_Focus();\n\t\tbool droplist_is_dropped = housebtn.IsDropped;\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t** Sort out the input focus between the name edit box and the message system\n\t\t*/\n\t\tif (messages_have_focus) {\n\t\t\tif (!name_edt.Has_Focus()) {\n\t\t\t\tSession.Messages.Set_Edit_Focus();\n\t\t\t} else {\n\t\t\t\tmessages_have_focus = false;\n\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Redraw everything if the droplist collapsed\n\t\t*/\n\t\tif (droplist_is_dropped && !housebtn.IsDropped) {\n\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t}\n\n\t\t/*\n\t\t---------------------------- Process input ----------------------------\n\t\t*/\n\t\tswitch (input) {\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUser clicks on a color button\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase KN_LMOUSE:\n\t\t\t\tif (Keyboard->MouseQX > cbox_x[0] &&\n\t\t\t\t\tKeyboard->MouseQX < (cbox_x[MAX_MPLAYER_COLORS - 1] + d_color_w) &&\n\t\t\t\t\tKeyboard->MouseQY > d_color_y &&\n\t\t\t\t\tKeyboard->MouseQY < (d_color_y + d_color_h)) {\n\t\t\t\t\t\t/*.........................................................\n\t\t\t\t\t\tCompute my preferred color as the one I clicked on.\n\t\t\t\t\t\t.........................................................*/\n\t\t\t\t\t\tSession.PrefColor = (PlayerColorType)\n\t\t\t\t\t\t\t((Keyboard->MouseQX - cbox_x[0]) / d_color_w);\n\t\t\t\t\t\tchanged = true;\n\n\t\t\t\t\t\t/*.........................................................\n\t\t\t\t\t\tIf 'TheirColor' is set to the other player's color, make\n\t\t\t\t\t\tsure we can't pick that color.\n\t\t\t\t\t\t.........................................................*/\n\t\t\t\t\t\tif (parms_received) {\n\t\t\t\t\t\t\tif (Session.PrefColor == TheirColor)\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSession.ColorIdx = Session.PrefColor;\n\n\t\t\t\t\t\tname_edt.Set_Color(&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx]);\n\t\t\t\t\t\tname_edt.Flag_To_Redraw();\n\t\t\t\t\t\tSession.Messages.Set_Edit_Color((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx);\n\t\t\t\t\t\tif (display < REDRAW_COLORS) display = REDRAW_COLORS;\n\t\t\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\t\t\ttransmit = true;\n\t\t\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t\t\t}\n\t\t\t\t} else if ( (Get_Mouse_X() >= d_count_x &&\n\t\t\t\t\tGet_Mouse_X() <= d_count_x + d_count_w &&\n\t\t\t\t\tGet_Mouse_Y() >= d_count_y &&\n\t\t\t\t\tGet_Mouse_Y() <= d_aiplayers_y + d_aiplayers_h) ||\n\t\t\t\t\t(Get_Mouse_X() >= d_options_x &&\n\t\t\t\t\tGet_Mouse_X() <= d_options_x + d_options_w &&\n\t\t\t\t\tGet_Mouse_Y() >= d_options_y &&\n\t\t\t\t\tGet_Mouse_Y() <= d_options_y + d_options_h) ) {\n\t\t\t\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_ONLY_HOST_CAN_MODIFY), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n#ifdef OLDWAY\n\t\t\t/*------------------------------------------------------------------\n\t\t\tHouse Buttons: set the player's desired House\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_GDI | KN_BUTTON):\n\t\t\t\tSession.House = HOUSE_GOOD;\n\t\t\t\tgdibtn.Turn_On();\n\t\t\t\tnodbtn.Turn_Off();\n\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\ttransmit = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_NOD | KN_BUTTON):\n\t\t\t\tSession.House = HOUSE_BAD;\n\t\t\t\tgdibtn.Turn_Off();\n\t\t\t\tnodbtn.Turn_On();\n\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\ttransmit = true;\n\t\t\t\tbreak;\n#else\t//OLDWAY\n\t\t\tcase (BUTTON_HOUSE | KN_BUTTON):\n\t\t\t\tSession.House = HousesType(housebtn.Current_Index()+HOUSE_USSR);\n\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\ttransmit = true;\n\t\t\t\t//display = REDRAW_BACKGROUND;\n\t\t\t\tbreak;\n#endif\t//OLDWAY\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUser edits the name value; retransmit\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_NAME | KN_BUTTON):\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\ttransmit = true;\n\t\t\t\tchanged = true;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tCANCEL: send a SIGN_OFF, bail out with error code\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tDefault: manage the inter-player messages\n\t\t\t------------------------------------------------------------------*/\n\t\t\tdefault:\n\t\t\t\tif (Session.Messages.Manage()) {\n\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t}\n\n\t\t\t\t/*...............................................................\n\t\t\t\tService keyboard input for any message being edited.\n\t\t\t\t...............................................................*/\n\t\t\t\ti = Session.Messages.Input(input);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tIf 'Input' returned 1, it means refresh the message display.\n\t\t\t\t(We have to redraw the edit line, to erase the cursor.)\n\t\t\t\t...............................................................*/\n\t\t\t\tif (i==1) {\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h,\n\t\t\t\t\t\tBOXSTYLE_BOX, true);\n\t\t\t\t\tSession.Messages.Draw();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t} else if (i==2) {\n\t\t\t\t/*...............................................................\n\t\t\t\tIf 'Input' returned 2, it means redraw the message display.\n\t\t\t\tRather than setting 'display', which would redraw all msgs,\n\t\t\t\twe only need to erase & redraw the edit box here.\n\t\t\t\t...............................................................*/\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h,\n\t\t\t\t\t\tBOXSTYLE_BOX, true);\n\t\t\t\t\tSession.Messages.Draw();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t} else if (i==3 || i==4) {\n\t\t\t\t/*...............................................................\n\t\t\t\tIf 'input' returned 3, it means send the current message.\n\t\t\t\t...............................................................*/\n\t\t\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\t\t\tSendPacket.Command = SERIAL_MESSAGE;\n\t\t\t\t\tstrcpy (SendPacket.Name, namebuf);\n\t\t\t\t\tSendPacket.ID = Session.ColorIdx;\n\t\t\t\t\tif (i==3) {\n\t\t\t\t\t\tstrcpy (SendPacket.Message.Message, Session.Messages.Get_Edit_Buf());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstrcpy (SendPacket.Message.Message, Session.Messages.Get_Overflow_Buf());\n\t\t\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t\t\t}\n\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tSend the message\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\t\t\t\t\tNullModem.Service();\n\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tAdd the message to our own screen\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tSession.Messages.Add_Message (SendPacket.Name, SendPacket.ID,\n\t\t\t\t\t\tSendPacket.Message.Message,\n\t\t\t\t\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\tTPF_TEXT, -1);\n\t\t\t\t\tSession.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message_w);\n\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tDetect editing of the name buffer, transmit new values to players\n\t\t---------------------------------------------------------------------*/\n\t\tif (strcmp (namebuf, Session.Handle)) {\n\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\ttransmit = true;\n\t\t\tchanged = true;\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tIf our Transmit flag is set, we need to send out a game option packet\n\t\t---------------------------------------------------------------------*/\n\t\tif (transmit && (TickCount - transmittime) > PACKET_RETRANS_TIME) {\n\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\tSendPacket.Command = SERIAL_GAME_OPTIONS;\n\t\t\tstrcpy (SendPacket.Name, namebuf);\n\t\t\tSendPacket.ScenarioInfo.CheatCheck = RuleINI.Get_Unique_ID();\n\t\t\tSendPacket.ScenarioInfo.MinVersion = VerNum.Min_Version();\n\t\t\tSendPacket.ScenarioInfo.MaxVersion = VerNum.Max_Version();\n\t\t\tSendPacket.ScenarioInfo.House = Session.House;\n\t\t\tSendPacket.ScenarioInfo.Color = Session.ColorIdx;\n\t\t\tSendPacket.ID = Session.ModemType;\n\n\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\n\t\t\ttransmittime = TickCount;\n\t\t\ttransmit = false;\n\n\t\t\t//..................................................................\n\t\t\t// Keep the player list up to date\n\t\t\t//..................................................................\n\t\t\tif (playerlist.Count()) {\n\t\t\t\titem = (char *)playerlist.Get_Item(0);\n#ifdef\tOLDWAY\n\t\t\t\tif (Session.House==HOUSE_GOOD) {\n\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf,\n\t\t\t\t\t\tText_String(TXT_ALLIES));\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf,\n\t\t\t\t\t\tText_String(TXT_SOVIET));\n\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\tsprintf (item, \"%s\\t%s\", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\t\t\t\tplayerlist.Colors[0] = &ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx];\n\t\t\t\tplayerlist.Flag_To_Redraw();\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// Play a little sound effect\n\t\t\t//..................................................................\n\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t}\n\n\t\t//\n\t\t// send a timing packet if enough time has gone by.\n\t\t//\n\t\tif ((TickCount - timingtime) > PACKET_TIMING_TIMEOUT) {\n\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\tSendPacket.Command = SERIAL_TIMING;\n\t\t\tSendPacket.ScenarioInfo.ResponseTime = NullModem.Response_Time();\n\t\t\tSendPacket.ID = Session.ModemType;\n\n\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 0);\n\t\t\ttimingtime = TickCount;\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tCheck for an incoming message\n\t\t---------------------------------------------------------------------*/\n\t\tif (NullModem.Get_Message(&ReceivePacket, &packetlen) > 0) {\n\n\t\t\tlastmsgtime = TickCount;\n\n\t\t\tmsg_timeout = 600;\n\n\t\t\t// are we getting our own packets back??\n\n\t\t\tif (ReceivePacket.Command >= SERIAL_CONNECT &&\n\t\t\t\tReceivePacket.Command < SERIAL_LAST_COMMAND &&\n\t\t\t\tReceivePacket.Command != SERIAL_MESSAGE &&\n\t\t\t\tReceivePacket.ID == Session.ModemType) {\n\n\t\t\t\tWWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);\n\n\t\t\t\t// to skip the other system not responding msg\n\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\n\t\t\t\t// say we did receive sign off to keep from sending one\n\t\t\t\trecsignedoff = true;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tevent = (EventClass *)&ReceivePacket;\n\t\t\tif (event->Type <= EventClass::FRAMEINFO) {\n\t\t\t\tif ( (TickCount - lastredrawtime) > PACKET_REDRAW_TIME) {\n\t\t\t\t\tlastredrawtime = TickCount;\n\t\t\t\t\toppscorescreen = true;\n\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\tparms_received = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tswitch ( ReceivePacket.Command ) {\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tOther system signs off:  Give it time to receive my ACK, then show\n\t\t\t\t\ta message.\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tcase (SERIAL_SIGN_OFF):\n\t\t\t\t\t\tstarttime = TickCount;\n\t\t\t\t\t\twhile ( (TickCount - starttime) < 60)\n\t\t\t\t\t\t\tNullModem.Service();\n\t\t\t\t\t\tWWMessageBox().Process(TXT_USER_SIGNED_OFF);\n\n\t\t\t\t\t\t// to skip the other system not responding msg\n\t\t\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\trc = false;\n\t\t\t\t\t\trecsignedoff = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tGame Options: Store all options; check my color & game version.\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tcase (SERIAL_GAME_OPTIONS):\n\t\t\t\t\t\toppscorescreen = false;\n\t\t\t\t\t\tgameoptions = true;\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\t\tparms_received = true;\n\n\t\t\t\t\t\tstrcpy (TheirName, ReceivePacket.Name);\n\t\t\t\t\t\tTheirColor = ReceivePacket.ScenarioInfo.Color;\n\t\t\t\t\t\tTheirHouse = ReceivePacket.ScenarioInfo.House;\n\n\t\t\t\t\t\t/*...............................................................\n\t\t\t\t\t\tMake sure I don't have the same color as the other guy.\n\t\t\t\t\t\t...............................................................*/\n\t\t\t\t\t\tif (Session.ColorIdx == TheirColor) {\n\n\t\t\t\t\t\t\t// force transmitting of game options packet\n\n\t\t\t\t\t\t\ttransmit = true;\n\t\t\t\t\t\t\ttransmittime = 0;\n\n\t\t\t\t\t\t\tSession.ColorIdx = (PlayerColorType)(TheirColor + 1);\n\t\t\t\t\t\t\tif (Session.ColorIdx >= 6) {\n\t\t\t\t\t\t\t\tSession.ColorIdx = PCOLOR_FIRST;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tname_edt.Set_Color(&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]);\n\t\t\t\t\t\t\tname_edt.Flag_To_Redraw();\n\t\t\t\t\t\t\tif (display < REDRAW_COLORS) display = REDRAW_COLORS;\n\t\t\t\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*...............................................................\n\t\t\t\t\t\tSave scenario settings.\n\t\t\t\t\t\t...............................................................*/\n\t\t\t\t\t\tSession.Options.Credits = ReceivePacket.ScenarioInfo.Credits;\n\t\t\t\t\t\tSession.Options.Bases = ReceivePacket.ScenarioInfo.IsBases;\n\t\t\t\t\t\tSession.Options.Tiberium = ReceivePacket.ScenarioInfo.IsTiberium;\n\t\t\t\t\t\tSession.Options.Goodies = ReceivePacket.ScenarioInfo.IsGoodies;\n\t\t\t\t\t\tSession.Options.AIPlayers = ReceivePacket.ScenarioInfo.AIPlayers;\n\t\t\t\t\t\tBuildLevel = ReceivePacket.ScenarioInfo.BuildLevel;\n\t\t\t\t\t\tSession.Options.UnitCount = ReceivePacket.ScenarioInfo.UnitCount;\n\t\t\t\t\t\tSeed = ReceivePacket.ScenarioInfo.Seed;\n\t\t\t\t\t\tSpecial = ReceivePacket.ScenarioInfo.Special;\n\t\t\t\t\t\tOptions.GameSpeed = ReceivePacket.ScenarioInfo.GameSpeed;\n\n\t\t\t\t\t\tif (Session.Options.Tiberium) {\n\t\t\t\t\t\t\tSpecial.IsTGrowth = true;\n\t\t\t\t\t\t\tRule.IsTGrowth = true;\n\t\t\t\t\t\t\tSpecial.IsTSpread = true;\n\t\t\t\t\t\t\tRule.IsTSpread = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSpecial.IsTGrowth = false;\n\t\t\t\t\t\t\tRule.IsTGrowth = false;\n\t\t\t\t\t\t\tSpecial.IsTSpread = false;\n\t\t\t\t\t\t\tRule.IsTSpread = false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// Adjust the gauges\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\tcountgauge.Set_Maximum(\n\t\t\t\t\t\t\tSessionClass::CountMax[Session.Options.Bases] -\n\t\t\t\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\t\t\t\tcountgauge.Set_Value(Session.Options.UnitCount -\n\t\t\t\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\t\t\t\tlevelgauge.Set_Value(BuildLevel - 1);\n\t\t\t\t\t\tcreditsgauge.Set_Value(Session.Options.Credits);\n\t\t\t\t\t\taiplayersgauge.Set_Value(Session.Options.AIPlayers);\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// Update the options list box\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\toptionlist.Check_Item(0, Session.Options.Bases);\n\t\t\t\t\t\toptionlist.Check_Item(1, Session.Options.Tiberium);\n\t\t\t\t\t\toptionlist.Check_Item(2, Session.Options.Goodies);\n\t\t\t\t\t\toptionlist.Check_Item(3, Special.IsCaptureTheFlag);\n\t\t\t\t\t\toptionlist.Check_Item(4, Special.IsShadowGrow);\n\t\t\t\t\t\toptionlist.Flag_To_Redraw();\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** If the scenario name changed then we need to redraw the whole lot.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (strcmp (Session.Options.ScenarioDescription, ReceivePacket.ScenarioInfo.Scenario)) {\n\t\t\t\t\t\t\tif (display < REDRAW_BACKGROUND) display = REDRAW_BACKGROUND;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*...............................................................\n\t\t\t\t\t\tCopy the information about the scenario that the host wants to\n\t\t\t\t\t\tplay so ee can request this scenario from the host if we don't\n\t\t\t\t\t\thave it locally.\n\t\t\t\t\t\t...............................................................*/\n\t\t\t\t\t\tstrcpy (Session.Options.ScenarioDescription, ReceivePacket.ScenarioInfo.Scenario);\n\t\t\t\t\t\tstrcpy (Session.ScenarioFileName, ReceivePacket.ScenarioInfo.ShortFileName);\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\t\t\tstrncpy (Session.ScenarioDigest, (char*)ReceivePacket.ScenarioInfo.FileDigest, sizeof( ReceivePacket.ScenarioInfo.FileDigest ));\n#else\n\t\t\t\t\t\tstrcpy (Session.ScenarioDigest, (char*)ReceivePacket.ScenarioInfo.FileDigest);\n#endif\n\t\t\t\t\t\tSession.ScenarioIsOfficial = ReceivePacket.ScenarioInfo.OfficialScenario;\n\t\t\t\t\t\tSession.ScenarioFileLength = ReceivePacket.ScenarioInfo.FileLength;\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// \"Clip\" the other system's version range to our own\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\tversion = VerNum.Clip_Version(ReceivePacket.ScenarioInfo.MinVersion,\n\t\t\t\t\t\t\tReceivePacket.ScenarioInfo.MaxVersion);\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t// If the greatest-common-version comes back 0, the other\n\t\t\t\t\t\t// system's range is too low for ours\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\tif (version == 0) {\n\t\t\t\t\t\t\tWWMessageBox().Process (TXT_DESTGAME_OUTDATED);\n\n\t\t\t\t\t\t\t// to skip the other system not responding msg\n\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\trc = false;\n\t\t\t\t\t\t} else if (version == 0xffffffff) {\n\t\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t\t// If the greatest-common-version comes back 0xffffffff,\n\t\t\t\t\t\t\t// the other system's range is too high for ours\n\t\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t\tWWMessageBox().Process (TXT_YOURGAME_OUTDATED);\n\n\t\t\t\t\t\t\t// to skip the other system not responding msg\n\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\trc = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t// Otherwise, 'version' is the highest version we have in\n\t\t\t\t\t\t// common; look up the protocol that goes with this version.\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\telse {\n\n\t\t\t\t\t\t\tif (ReceivePacket.ScenarioInfo.CheatCheck != RuleINI.Get_Unique_ID()) {\n\t\t\t\t\t\t\t\tWWMessageBox().Process(TXT_MISMATCH);\n\n\t\t\t\t\t\t\t\t// to skip the other system not responding msg\n\t\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\trc = false;\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\tSession.CommProtocol = VerNum.Version_Protocol(version);\n#ifndef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\tPlayingAgainstVersion = version;\n#endif\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*.........................................................\n\t\t\t\t\t\tIf this is the first game-options packet we've received,\n\t\t\t\t\t\tinit the game & player lists, then transmit our options\n\t\t\t\t\t\tto him.\n\t\t\t\t\t\t.........................................................*/\n\t\t\t\t\t\tif (first) {\n\t\t\t\t\t\t\t//......................................................\n\t\t\t\t\t\t\t// Add a string to the game list, and two to the player\n\t\t\t\t\t\t\t// list\n\t\t\t\t\t\t\t//......................................................\n\t\t\t\t\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\n\t\t\t\t\t\t\tgamelist.Add_Item(item);\n\t\t\t\t\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\t//Need room to display country name\n\t\t\t\t\t\t\tplayerlist.Add_Item(item,\n\t\t\t\t\t\t\t\t&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx]);\n\t\t\t\t\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\t//Need room to display country name\n\t\t\t\t\t\t\tplayerlist.Add_Item(item,\n\t\t\t\t\t\t\t\t&ColorRemaps[(TheirColor == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : TheirColor]);\n\n\t\t\t\t\t\t\tfirst = false;\n\t\t\t\t\t\t\ttransmit = true;\n\t\t\t\t\t\t\ttransmittime = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// Ensure the game list & player list have the latest,\n\t\t\t\t\t\t// greatest copy of our names & colors.  Do this every time\n\t\t\t\t\t\t// we receive an options packet.\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\titem = (char *)gamelist.Get_Item(0);\n\t\t\t\t\t\tsprintf(item,Text_String(TXT_THATGUYS_GAME),\n\t\t\t\t\t\t\tTheirName);\n\t\t\t\t\t\titem = (char *)playerlist.Get_Item(0);\n#ifdef\tOLDWAY\n\t\t\t\t\t\tif (Session.House==HOUSE_GOOD) {\n\t\t\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf,\n\t\t\t\t\t\t\t\tText_String(TXT_ALLIES));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf,\n\t\t\t\t\t\t\t\tText_String(TXT_SOVIET));\n\t\t\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\t\t\tsprintf (item, \"%s\\t%s\", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n\n#endif\t//OLDWAY\n\t\t\t\t\t\tplayerlist.Colors[0] = &ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx];\n\n\t\t\t\t\t\titem = (char *)playerlist.Get_Item(1);\n#ifdef\tOLDWAY\n\t\t\t\t\t\tif (TheirHouse==HOUSE_GOOD) {\n\t\t\t\t\t\t\tsprintf(item,\"%s\\t%s\",TheirName,\n\t\t\t\t\t\t\t\tText_String(TXT_ALLIES));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsprintf(item,\"%s\\t%s\",TheirName,\n\t\t\t\t\t\t\t\tText_String(TXT_SOVIET));\n\t\t\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\t\t\tsprintf (item, \"%s\\t%s\", TheirName, Text_String(HouseTypeClass::As_Reference(TheirHouse).Full_Name()));\n#endif\t//OLDWAY\n\t\t\t\t\t\tplayerlist.Colors[1] = &ColorRemaps[(TheirColor == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : TheirColor];\n\n\t\t\t\t\t\tgamelist.Flag_To_Redraw();\n\t\t\t\t\t\tplayerlist.Flag_To_Redraw();\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// Play a little sound effect\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tGO: Exit this routine with a success code.\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tcase (SERIAL_LOADGAME):\n\t\t\t\t\t\tload_game = true;\n\t\t\t\t\tcase (SERIAL_GO):\n\n\t\t\t\t\t\tready_packet_was_sent = false;\n\n\t\t\t\t\t\tif (!load_game){\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Special new kludge for counterstrike.\n\t\t\t\t\t\t\t**\n\t\t\t\t\t\t\t** Find local scenario will fail to match a counterstrike mission\n\t\t\t\t\t\t\t** unless the CS CD is in the drive. So....\n\t\t\t\t\t\t\t**\n\t\t\t\t\t\t\t** If Counterstrike is installed and this is an official map and\n\t\t\t\t\t\t\t** the file name matches a counterstrike map then tell the host\n\t\t\t\t\t\t\t** that I have the scenario so he can continue while we make\n\t\t\t\t\t\t\t** sure the local user has the Counterstrike CD in the drive.\n\t\t\t\t\t\t\t**\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t//\tThis is duplicated for Aftermath scenarios. ajw\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\t\tif (Session.ScenarioIsOfficial &&\n\t\t\t\t\t\t\t\t( (Expansion_CS_Present() && Is_Mission_Counterstrike(Session.ScenarioFileName)) ||\n\t\t\t\t\t\t\t\t  (Expansion_AM_Present() && Is_Mission_Aftermath(Session.ScenarioFileName)) ) ) {\n#else\n\t\t\t\t\t\t\tif ( Expansion_CS_Present() && Session.ScenarioIsOfficial ) {\n#endif\n\n\t\t\t\t\t\t\t\tCCFileClass check_file ( Session.ScenarioFileName );\n\t\t\t\t\t\t\t\tif ( !check_file.Is_Available() ) {\n\n\t\t\t\t\t\t\t\t\tint current_drive = CCFileClass::Get_CD_Drive();\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\t\t\t\tint index = Get_CD_Index(current_drive, 1*60);\n\t\t\t\t\t\t\t\t\tbool needcd = false;\n\t\t\t\t\t\t\t\t\tif (Is_Mission_Counterstrike(Session.ScenarioFileName)) {\n\t\t\t\t\t\t\t\t\t\tif (index != 2 && index != 3) {\n\t\t\t\t\t\t\t\t\t\t\tRequiredCD = 2;\n\t\t\t\t\t\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (Is_Mission_Aftermath(Session.ScenarioFileName)) {\n\t\t\t\t\t\t\t\t\t\tif (index != 3) {\n\t\t\t\t\t\t\t\t\t\t\tRequiredCD = 3;\n\t\t\t\t\t\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (needcd) {\n#else\n\t\t\t\t\t\t\t\t\tif ( Get_CD_Index(current_drive, 1*60) != 2 ){\n\t\t\t\t\t\t\t\t\t\tRequiredCD = 2;\n#endif\n\t#ifdef WIN32\n\t\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Counterstrike CD is not in drive\\n\");\n\t#endif\n\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t** We should have the scenario but the wrong disk is in.\n\t\t\t\t\t\t\t\t\t\t** Tell the host that I am ready to go anyway.\n\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\tmemset ((void*)&SendPacket, 0, sizeof (SendPacket));\n\t\t\t\t\t\t\t\t\t\tSendPacket.Command = SERIAL_READY_TO_GO;\n\t\t\t\t\t\t\t\t\t\tNullModem.Send_Message (&SendPacket, sizeof (SendPacket), 1);\n\n\t\t\t\t\t\t\t\t\t\tstarttime = TickCount;\n\t\t\t\t\t\t\t\t\t\twhile ( ( NullModem.Num_Send()\n\t\t\t\t\t\t\t\t\t\t\t&& ((TickCount - starttime) < PACKET_SENDING_TIMEOUT) )\n\t\t\t\t\t\t\t\t\t\t\t|| ((TickCount - starttime) < 60) ) {\n\t\t\t\t\t\t\t\t\t\t\tNullModem.Service();\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tready_packet_was_sent = true;\n\n\t\t\t\t\t\t\t\t\t\tif (!Force_CD_Available (RequiredCD)){\n\t\t\t\t\t\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t** Update the internal list of scenarios to include the counterstrike\n\t\t\t\t\t\t\t\t\t\t** list.\n\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\tSession.Read_Scenario_Descriptions();\n\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t** Make sure we dont time out because of the disk swap\n\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** If the scenario that the host wants to play doesnt exist locally then we\n\t\t\t\t\t\t\t**\tneed to request that it is sent. If we can identify the scenario locally then\n\t\t\t\t\t\t\t**\twe need to fix up the file name so we load the right one.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Find_Local_Scenario (Session.Options.ScenarioDescription,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioFileName,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioFileLength,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioDigest,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioIsOfficial)) {\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** We have the scenario. Tell the host that I am ready to go.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tif (!ready_packet_was_sent) {\n\t\t\t\t\t\t\t\t\tmemset ((void*)&SendPacket, 0, sizeof (SendPacket));\n\t\t\t\t\t\t\t\t\tSendPacket.Command = SERIAL_READY_TO_GO;\n\t\t\t\t\t\t\t\t\tNullModem.Send_Message (&SendPacket, sizeof (SendPacket), 1);\n\t\t\t\t\t\t\t\t\t\tstarttime = TickCount;\n\n\t\t\t\t\t\t\t\t\twhile ( ( NullModem.Num_Send()\n\t\t\t\t\t\t\t\t\t\t&& ((TickCount - starttime) < PACKET_SENDING_TIMEOUT) )\n\t\t\t\t\t\t\t\t\t\t|| ((TickCount - starttime) < 60) ) {\n\t\t\t\t\t\t\t\t\t\tNullModem.Service();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n#ifndef FIXIT_VERSION_3\t\t\t//\tRemoved restriction on downloading official maps.\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** Oh dear. Thats a scenario I dont have. Request that the host sends the\n\t\t\t\t\t\t\t\t**\tscenario to me provided it isnt an official Westwood scenario.\n\t\t\t\t\t\t\t\t**\n\t\t\t\t\t\t\t\t** If the file is received OK then we will get a true return value and the\n\t\t\t\t\t\t\t\t** actual file name to load will be in Session.ScenarioFileName\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tif (Session.ScenarioIsOfficial) {\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t** We dont have the scenario and we dont want to request that it gets\n\t\t\t\t\t\t\t\t\t** sent because its an official one.\n\t\t\t\t\t\t\t\t\t** Print up a message saying we cant play this scenario and reply to the\n\t\t\t\t\t\t\t\t\t** host, telling him to select another.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tmemset ((void*)&SendPacket, 0, sizeof (SendPacket));\n\t\t\t\t\t\t\t\t\tSendPacket.Command = SERIAL_NO_SCENARIO;\n\t\t\t\t\t\t\t\t\tNullModem.Send_Message (&SendPacket, sizeof (SendPacket), 1);\n\t\t\t\t\t\t\t\t\tNullModem.Service();\n\t\t\t\t\t\t\t\t\tWWMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH);\n\t\t\t\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t} else {\n#endif\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\t\tif( bSpecialAftermathScenario( Session.Options.ScenarioDescription ) )\n\t\t\t\t\t\t\t\t\t\tbreak;\n#endif\n\t\t\t\t\t\t\t\t\tif (!Get_Scenario_File_From_Host(Session.ScenarioFileName, 0)) {\n\t\t\t\t\t\t\t\t\t\trc = false;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t** Make sure we dont time-out because of the download\n\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\t\t\t\t\t\t\t\t\t}\n#ifndef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Make sure we respond to the host in a load game\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tmemset ((void*)&SendPacket, 0, sizeof (SendPacket));\n\t\t\t\t\t\t\tSendPacket.Command = SERIAL_READY_TO_GO;\n\t\t\t\t\t\t\tNullModem.Send_Message (&SendPacket, sizeof (SendPacket), 1);\n\t\t\t\t\t\t\t\tstarttime = TickCount;\n\n\t\t\t\t\t\t\twhile ( ( NullModem.Num_Send()\n\t\t\t\t\t\t\t\t&& ((TickCount - starttime) < PACKET_SENDING_TIMEOUT) )\n\t\t\t\t\t\t\t\t|| ((TickCount - starttime) < 60) ) {\n\t\t\t\t\t\t\t\tNullModem.Service();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Fall through here...\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tstrcpy (Scen.ScenarioName, Session.ScenarioFileName);\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// calculated one way delay for a packet and overall delay\n\t\t\t\t\t\t// to execute a packet\n\t\t\t\t\t\t//\n\t\t\t\t\t\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\t\t\t\t\t\tSession.MaxAhead = max( ((((ReceivePacket.ScenarioInfo.ResponseTime / 8) +\n\t\t\t\t\t\t\t\t(Session.FrameSendRate - 1)) / Session.FrameSendRate) *\n\t\t\t\t\t\t\t\tSession.FrameSendRate), (Session.FrameSendRate * 2) );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSession.MaxAhead = max( (ReceivePacket.ScenarioInfo.ResponseTime / 8),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  MODEM_MIN_MAX_AHEAD );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\trc = true;\n\t\t\t\t\t\tif (ReceivePacket.Command == SERIAL_LOADGAME)\n\t\t\t\t\t\t\tload_game = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tIncoming message: add to our list\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tcase (SERIAL_MESSAGE):\n\t\t\t\t\t\toppscorescreen = false;\n\n\t\t\t\t\t\tSession.Messages.Add_Message (ReceivePacket.Name,\n\t\t\t\t\t\t\t((PlayerColorType)ReceivePacket.ID == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : (PlayerColorType)ReceivePacket.ID,\n\t\t\t\t\t\t\tReceivePacket.Message.Message,\n\t\t\t\t\t\t\t((PlayerColorType)ReceivePacket.ID == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : (PlayerColorType)ReceivePacket.ID,\n\t\t\t\t\t\t\tTPF_TEXT, -1);\n\n\t\t\t\t\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t//\n\t\t\t\t\t// throw away timing packet\n\t\t\t\t\t//\n\t\t\t\t\tcase (SERIAL_TIMING):\n\t\t\t\t\t\toppscorescreen = false;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t//\n\t\t\t\t\t// print msg waiting for opponent\n\t\t\t\t\t//\n\t\t\t\t\tcase (SERIAL_SCORE_SCREEN):\n\t\t\t\t\t\toppscorescreen = true;\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\t\tparms_received = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if we haven't received a msg for 10 seconds exit\n\n\t\tif ((TickCount - lastmsgtime) > msg_timeout) {\n\t\t\tWWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);\n\t\t\tprocess = false;\n\t\t\trc = false;\n\n\t\t\t// say we did receive sign off to keep from sending one\n\t\t\trecsignedoff = true;\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tService the connection\n\t\t---------------------------------------------------------------------*/\n\t\tNullModem.Service();\n\t}\n\n\t/*------------------------------------------------------------------------\n\tPrepare to load the scenario\n\t------------------------------------------------------------------------*/\n\tif (rc) {\n\t\tSession.NumPlayers = 2;\n\n\t\t/*.....................................................................\n\t\tAdd both players to the Players vector; the local system is always\n\t\tindex 0.\n\t\t.....................................................................*/\n\t\twho = new NodeNameType;\n\n\t\t#ifdef FIXIT_MODEM_LOAD_CRASH\n\t\t/* If the names of the players are the same then we MUST force them\n\t\t * be be unique. This is necessary to prevent a crash after loading\n\t\t * a modem save game.\n\t\t */\n\t\tif (strcmp(TheirName, namebuf) == 0)\n\t\t\t{\n\t\t\tif (strlen(TheirName) == (MPLAYER_NAME_MAX - 1))\n\t\t\t\t{\n\t\t\t\tnamebuf[MPLAYER_NAME_MAX - 1] = '\\0';\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tstrcat(namebuf, \"2\");\n\t\t\t\t}\n\t\t\t}\n\t\t#endif\n\n\t\tstrcpy(who->Name, namebuf);\n\t\twho->Player.House = Session.House;\n\t\twho->Player.Color = Session.ColorIdx;\n\t\twho->Player.ProcessTime = -1;\n\t\tSession.Players.Add (who);\n\n\t\twho = new NodeNameType;\n\t\tstrcpy(who->Name, TheirName);\n\t\twho->Player.House = TheirHouse;\n\t\twho->Player.Color = TheirColor;\n\t\twho->Player.ProcessTime = -1;\n\t\tSession.Players.Add (who);\n\n\t\tstarttime = TickCount;\n\t\twhile ( ( NullModem.Num_Send()\n\t\t\t&& ((TickCount - starttime) < PACKET_SENDING_TIMEOUT) )\n\t\t\t|| ((TickCount - starttime) < 60) ) {\n\t\t\t#if(SHOW_MONO)\n\t\t\tNullModem.Mono_Debug_Print(0);\n\t\t\t#endif\n\n\t\t\tNullModem.Service();\n\t\t}\n\n\t\t// clear queue to keep from doing any resends\n\t\tNullModem.Init_Send_Queue();\n\n\t} else {\n\t\tif ( !recsignedoff ) {\n\t\t\t/*.....................................................................\n\t\t\tBroadcast my sign-off over my network\n\t\t\t.....................................................................*/\n\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\tSendPacket.Command = SERIAL_SIGN_OFF;\n\t\t\tSendPacket.ScenarioInfo.Color = Session.ColorIdx;\t\t// use Color for ID\n\t\t\tSendPacket.ID = Session.ModemType;\n\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\n\t\t\tstarttime = TickCount;\n\t\t\twhile ( (NullModem.Num_Send()\n\t\t\t\t&& ((TickCount - starttime) < PACKET_CANCEL_TIMEOUT) )\n\t\t\t\t|| ((TickCount - starttime) < 60) ) {\n\t\t\t\t#if(SHOW_MONO)\n\t\t\t\tNullModem.Mono_Debug_Print(0);\n\t\t\t\t#endif\n\n\t\t\t\tif ( NullModem.Get_Message( &ReceivePacket, &packetlen ) > 0) {\n\n\t\t\t\t\t// are we getting our own packets back??\n\n\t\t\t\t\tif (ReceivePacket.Command == SERIAL_SIGN_OFF\n\t\t\t\t\t\t&& ReceivePacket.ID == Session.ModemType) {\n\n\t\t\t\t\t\t// exit while\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tNullModem.Service();\n\t\t\t}\n\t\t}\n\n\t\tShutdown_Modem();\n\t}\n\n\t/*------------------------------------------------------------------------\n\tClean up the list boxes\n\t------------------------------------------------------------------------*/\n//\twhile (optionlist.Count()>0) {\n//\t\titem = (char *)optionlist.Get_Item(0);\n//\t\tdelete [] item;\n//\t\toptionlist.Remove_Item(item);\n//\t}\n\twhile (gamelist.Count()>0) {\n\t\titem = (char *)gamelist.Get_Item(0);\n\t\tdelete [] item;\n\t\tgamelist.Remove_Item(item);\n\t}\n\twhile (playerlist.Count()>0) {\n\t\titem = (char *)playerlist.Get_Item(0);\n\t\tdelete [] item;\n\t\tplayerlist.Remove_Item(item);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tRemove the chat edit box\n\t------------------------------------------------------------------------*/\n\tSession.Messages.Remove_Edit();\n\n\t/*------------------------------------------------------------------------\n\tRestore screen\n\t------------------------------------------------------------------------*/\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n//#ifdef WIN32\n//\tLoad_Uncompress(CCFileClass(\"TITLE.CPS\"), SysMemPage, SysMemPage, CCPalette);\n//\tSysMemPage.Scale(SeenPage);\n//#else\n//\tLoad_Uncompress(CCFileClass(\"TITLE.CPS\"), HidPage, HidPage, CCPalette);\n//\tHidPage.Blit(SeenPage);\n//#endif\n\tShow_Mouse();\n\n\t/*------------------------------------------------------------------------\n\tSave any changes made to our options\n\t------------------------------------------------------------------------*/\n\tif (changed) {\n\t\tSession.Write_MultiPlayer_Settings ();\n\t}\n\n\tif (load_game) {\n\t\tif (!Load_Game (-1)) {\n\t\t\tWWMessageBox().Process (TXT_ERROR_LOADING_GAME);\n\t\t\trc = false;\n\t\t}\n\t\tFrame++;\n\t}\n\n\treturn(rc);\n\n}\t/* end of Com_Show_Scenario_Dialog */\n\n\n/***************************************************************************\n * Phone_Dialog -- Lets user edit phone directory & dial                   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = dial the current phone book entry, false = cancel.\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tSerial options must have been read from CC.INI.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Phone_Dialog (void)\n{\n\t/*........................................................................\n\tDialog & button dimensions\n\t........................................................................*/\n\tint d_dialog_w = 280 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 160 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2);\t\t// dialog x-coord\n\tint d_dialog_y = ((200 * RESFACTOR - d_dialog_h) / 2);\t\t// dialog y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_txt6_h = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_margin = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint d_phonelist_w = 248 * RESFACTOR;\n\tint d_phonelist_h = 87 * RESFACTOR;\n\tint d_phonelist_x = d_dialog_cx - (d_phonelist_w / 2);\n\tint d_phonelist_y = d_dialog_y + d_margin + d_txt6_h + 11 * RESFACTOR;\n\n\tint d_add_w = 45 * RESFACTOR;\n\tint d_add_h = 9 * RESFACTOR;\n\tint d_add_x = d_dialog_cx - (d_add_w / 2) - d_margin - d_add_w;\n\tint d_add_y = d_phonelist_y + d_phonelist_h + d_margin;\n\n\tint d_edit_w = 45 * RESFACTOR;\n\tint d_edit_h = 9 * RESFACTOR;\n\tint d_edit_x = d_dialog_cx - (d_edit_w / 2);\n\tint d_edit_y = d_phonelist_y + d_phonelist_h + d_margin;\n\n\tint d_delete_w = 45 * RESFACTOR;\n\tint d_delete_h = 9 * RESFACTOR;\n\tint d_delete_x = d_dialog_cx + (d_delete_w / 2) + d_margin;\n\tint d_delete_y = d_phonelist_y + d_phonelist_h + d_margin;\n\n\tint d_numedit_w = ( (PhoneEntryClass::PHONE_MAX_NUM - 1) * 6) * RESFACTOR + 3 * RESFACTOR;\n\tint d_numedit_h = 9 * RESFACTOR;\n\tint d_numedit_x = d_dialog_cx - (d_numedit_w / 2);\n\tint d_numedit_y = d_add_y + d_add_h + d_margin;\n\n\tint d_dial_w = 45 * RESFACTOR;\n\tint d_dial_h = 9 * RESFACTOR;\n\tint d_dial_x = d_dialog_cx - (d_numedit_w / 2) - d_margin - d_dial_w;\n\tint d_dial_y = d_add_y + d_add_h + d_margin;\n\n\tint d_cancel_w = 45 * RESFACTOR;\n\tint d_cancel_h = 9 * RESFACTOR;\n\tint d_cancel_x = d_dialog_cx + (d_numedit_w / 2) + d_margin;\n\tint d_cancel_y = d_add_y + d_add_h + d_margin;\n\n\t/*........................................................................\n\tButton Enumerations\n\t........................................................................*/\n\tenum {\n\t\tBUTTON_PHONELIST = 100,\n\t\tBUTTON_ADD,\n\t\tBUTTON_EDIT,\n\t\tBUTTON_DELETE,\n\t\tBUTTON_DIAL,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_NUMEDIT,\n\t};\n\n\t/*........................................................................\n\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t........................................................................*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*........................................................................\n\tDialog variables\n\t........................................................................*/\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\n\tchar phone_num[ PhoneEntryClass::PHONE_MAX_NUM ] = { 0 }; // buffer for editing phone #\n\tint rc;\n\tint i;\n\tint tabs[] = {123*RESFACTOR, 207*RESFACTOR};\t\t\t\t// tabs for list box\n\tchar *item;\t\t\t\t\t\t\t\t\t// for removing items from list box\n\tPhoneEntryClass *p_entry;\t\t\t\t// for creating / editing phonebook entries\n\tbool changed = false;\t\t\t\t\t// 1 = save changes to INI file\n\tbool firsttime = false;\n\n\t/*........................................................................\n\tButtons\n\t........................................................................*/\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tListClass phonelist(BUTTON_PHONELIST, d_phonelist_x, d_phonelist_y, d_phonelist_w, d_phonelist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tTextButtonClass addbtn(BUTTON_ADD, TXT_ADD, TPF_BUTTON, d_add_x, d_add_y, d_add_w, d_add_h);\n\tTextButtonClass editbtn(BUTTON_EDIT, TXT_EDIT, TPF_BUTTON, d_edit_x, d_edit_y, d_edit_w, d_edit_h);\n\tTextButtonClass deletebtn(BUTTON_DELETE, TXT_DELETE_BUTTON, TPF_BUTTON, d_delete_x, d_delete_y, d_delete_w, d_delete_h);\n\tTextButtonClass dialbtn(BUTTON_DIAL, TXT_DIAL, TPF_BUTTON, d_dial_x, d_dial_y, d_dial_w, d_dial_h);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n\tEditClass numedit (BUTTON_NUMEDIT, phone_num, PhoneEntryClass::PHONE_MAX_NUM, TPF_TEXT, d_numedit_x, d_numedit_y, d_numedit_w, d_numedit_h, EditClass::ALPHANUMERIC);\n\n\t/*\n\t------------------------- Build the button list --------------------------\n\t*/\n\tcommands = &phonelist;\n\taddbtn.Add_Tail(*commands);\n\teditbtn.Add_Tail(*commands);\n\tdeletebtn.Add_Tail(*commands);\n\tdialbtn.Add_Tail(*commands);\n\tcancelbtn.Add_Tail(*commands);\n\tnumedit.Add_Tail(*commands);\n\tdialbtn.Turn_On();\n\n\t/*\n\t----------------------------- Various Inits ------------------------------\n\t*/\n\t/*........................................................................\n\tFill in the phone directory list box\n\t........................................................................*/\n\tphonelist.Set_Tabs(tabs);\n\tBuild_Phone_Listbox(&phonelist, &numedit, phone_num);\n\n\tif (Session.CurPhoneIdx == -1) {\n\t\tfirsttime = true;\n\t}\n\n\t/*\n\t---------------------------- Processing loop -----------------------------\n\t*/\n\twhile (process) {\n\t\t/*\n\t\t........................ Invoke game callback .........................\n\t\t*/\n\t\tCall_Back();\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\t#endif\n\t\t/*\n\t\t...................... Refresh display if needed ......................\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\t\t\t/*\n\t\t\t.................. Redraw backgound & dialog box ...................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tCCPalette.Set();\n\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t// init font variables\n\n\t\t\t\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_CENTER | TPF_TEXT);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDialog & Field labels\n\t\t\t\t...............................................................*/\n\t\t\t\tDraw_Caption (TXT_PHONE_LIST, d_dialog_x, d_dialog_y, d_dialog_w);\n\t\t\t\tphonelist.Draw_Me (true);\n\t\t\t}\n\t\t\t/*\n\t\t\t.......................... Redraw buttons ..........................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\taddbtn.Flag_To_Redraw();\n\t\t\t\teditbtn.Flag_To_Redraw();\n\t\t\t\tdeletebtn.Flag_To_Redraw();\n\t\t\t\tdialbtn.Flag_To_Redraw();\n\t\t\t\tcancelbtn.Flag_To_Redraw();\n\t\t\t\tnumedit.Flag_To_Redraw();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t........................... Get user input ............................\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\tif ( firsttime ) {\n\t\t\tnumedit.Set_Focus();\n\t\t\tnumedit.Flag_To_Redraw();\n\t\t\tinput = commands->Input();\n\t\t\tfirsttime = false;\n\t\t}\n\n\t\t/*\n\t\t---------------------------- Process input ----------------------------\n\t\t*/\n\t\tswitch (input) {\n\t\t\t/*------------------------------------------------------------------\n\t\t\tNew phone listing selected.\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_PHONELIST | KN_BUTTON):\n\t\t\t\t/*...............................................................\n\t\t\t\tDetect a change in the selected item; update CurPhoneIdx, and\n\t\t\t\tthe edit box buffer.\n\t\t\t\t...............................................................*/\n\t\t\t\t#ifdef FIXIT_PHONELIST_CRASH\n\t\t\t\tif (Session.CurPhoneIdx != -1) {\n\t\t\t\t#endif\n\t\t\t\t\tif (phonelist.Current_Index() != Session.CurPhoneIdx) {\n\t\t\t\t\t\tSession.CurPhoneIdx = phonelist.Current_Index();\n\t\t\t\t\t\tstrcpy (phone_num, Session.PhoneBook[Session.CurPhoneIdx]->Number);\n\t\t\t\t\t\tnumedit.Set_Text (phone_num, PhoneEntryClass::PHONE_MAX_NUM );\n\t\t\t\t\t\tchanged = true;\n\t\t\t\t\t}\n\t\t\t\t#ifdef FIXIT_PHONELIST_CRASH\n\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tAdd a new entry\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_ADD | KN_BUTTON):\n\n\t\t\t\t/*...............................................................\n\t\t\t\tAllocate a new phone book entry\n\t\t\t\t...............................................................*/\n\t\t\t\tp_entry = new PhoneEntryClass();\n\t\t\t\tp_entry->Name[0] = 0;\n\t\t\t\tp_entry->Number[0] = 0;\n\t\t\t\tp_entry->Settings.Port = 0;\n\t\t\t\tp_entry->Settings.IRQ = -1;\n\t\t\t\tp_entry->Settings.Baud = -1;\n\t\t\t\tp_entry->Settings.DialMethod = DIAL_TOUCH_TONE;\n\t\t\t\tp_entry->Settings.InitStringIndex = 0;\n\t\t\t\tp_entry->Settings.CallWaitStringIndex = CALL_WAIT_CUSTOM;\n\t\t\t\tp_entry->Settings.CallWaitString[0] = 0;\n\n\t\t\t\t/*...............................................................\n\t\t\t\tInvoke the entry editor; if user clicks Save, add the new entry\n\t\t\t\tto the list, and rebuild the list box.\n\t\t\t\t...............................................................*/\n\t\t\t\tif ( Edit_Phone_Dialog( p_entry ) ) {\n\t\t\t\t\tSession.PhoneBook.Add (p_entry);\n\t\t\t\t\tBuild_Phone_Listbox( &phonelist, &numedit, phone_num );\n\t\t\t\t\t/*............................................................\n\t\t\t\t\tSet the current listbox index to the newly-added item.\n\t\t\t\t\t............................................................*/\n\t\t\t\t\tfor (i = 0; i < Session.PhoneBook.Count(); i++) {\n\t\t\t\t\t\tif (p_entry == Session.PhoneBook[i]) {\n\t\t\t\t\t\t\tSession.CurPhoneIdx = i;\n\t\t\t\t\t\t\tstrcpy (phone_num, Session.PhoneBook[Session.CurPhoneIdx]->Number);\n\t\t\t\t\t\t\tnumedit.Set_Text (phone_num, PhoneEntryClass::PHONE_MAX_NUM );\n\t\t\t\t\t\t\tphonelist.Set_Selected_Index( Session.CurPhoneIdx );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tchanged = true;\n\t\t\t\t} else {\n\n\t\t\t\t\t/*...............................................................\n\t\t\t\t\tIf the user clicked Cancel, delete the entry & keep looping.\n\t\t\t\t\t...............................................................*/\n\t\t\t\t\tdelete p_entry;\n\t\t\t\t}\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tEdit the current entry\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_EDIT | KN_BUTTON):\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDo nothing if no entry is selected.\n\t\t\t\t...............................................................*/\n\t\t\t\tif (Session.CurPhoneIdx==-1)\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*...............................................................\n\t\t\t\tAllocate a new entry & copy the currently-selected entry into it\n\t\t\t\t...............................................................*/\n\t\t\t\tp_entry = new PhoneEntryClass();\n\t\t\t\t(*p_entry) = (*Session.PhoneBook[Session.CurPhoneIdx]);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tPass the new entry to the entry editor; if the user selects OK,\n\t\t\t\tcopy the data back into our phone book.  Rebuild the list so\n\t\t\t\tthe changes show up in the list box.\n\t\t\t\t...............................................................*/\n\t\t\t\tif ( Edit_Phone_Dialog( p_entry ) ) {\n\t\t\t\t\t(*Session.PhoneBook[Session.CurPhoneIdx]) = (*p_entry);\n\t\t\t\t\tBuild_Phone_Listbox(&phonelist, &numedit, phone_num);\n\t\t\t\t\t/*............................................................\n\t\t\t\t\tSet the current listbox index to the newly-added item.\n\t\t\t\t\t............................................................*/\n\t\t\t\t\tfor (i = 0; i < Session.PhoneBook.Count(); i++) {\n\t\t\t\t\t\tif (Session.PhoneBook[Session.CurPhoneIdx] == Session.PhoneBook[i]) {\n\t\t\t\t\t\t\tSession.CurPhoneIdx = i;\n\t\t\t\t\t\t\tstrcpy (phone_num, Session.PhoneBook[Session.CurPhoneIdx]->Number);\n\t\t\t\t\t\t\tnumedit.Set_Text (phone_num, PhoneEntryClass::PHONE_MAX_NUM );\n\t\t\t\t\t\t\tphonelist.Set_Selected_Index( Session.CurPhoneIdx );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t\tdelete p_entry;\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tDelete the current entry\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_DELETE | KN_BUTTON):\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDo nothing if no entry is selected.\n\t\t\t\t...............................................................*/\n\t\t\t\tif (Session.CurPhoneIdx == -1)\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDelete the current item & rebuild the phone listbox\n\t\t\t\t...............................................................*/\n\t\t\t\tSession.PhoneBook.Delete (Session.CurPhoneIdx);\n\t\t\t\tBuild_Phone_Listbox(&phonelist, &numedit, phone_num);\n\n\t\t\t\tif (Session.CurPhoneIdx == -1) {\n\t\t\t\t\t*phone_num = 0;\n\t\t\t\t\tnumedit.Set_Text (phone_num, PhoneEntryClass::PHONE_MAX_NUM );\n\t\t\t\t}\n\t\t\t\tchanged = true;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tDial the current number\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (KN_RETURN):\n\t\t\t\tdialbtn.IsPressed = true;\n\t\t\t\tdialbtn.Draw_Me(true);\n\t\t\t\t// fall thru\n\n\t\t\tcase (BUTTON_DIAL | KN_BUTTON):\n\n\t\t\t\t/*...............................................................\n\t\t\t\tIf no item is selected, just dial the number in the phone #\n\t\t\t\tedit box:\n\t\t\t\t- Create a new phone entry\n\t\t\t\t- Copy the phone number into it\n\t\t\t\t- Set settings to defaults\n\t\t\t\t...............................................................*/\n\t\t\t\tif (Session.CurPhoneIdx == -1 ||\n\t\t\t\t\tstrcmp( Session.PhoneBook[Session.CurPhoneIdx]->Number, phone_num) ) {\n\n\t\t\t\t\tif ( strlen(phone_num) == 0) {\t// do not dial\n\t\t\t\t\t\tdialbtn.IsPressed = true;\n\t\t\t\t\t\tdialbtn.Flag_To_Redraw();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tp_entry = new PhoneEntryClass();\n\t\t\t\t\tstrcpy( p_entry->Name, \"NONAME\" );\n\t\t\t\t\tstrcpy( p_entry->Number, phone_num);\n\t\t\t\t\tp_entry->Settings.Port = 0;\n\t\t\t\t\tp_entry->Settings.IRQ = -1;\n\t\t\t\t\tp_entry->Settings.Baud = -1;\n\t\t\t\t\tp_entry->Settings.DialMethod = DIAL_TOUCH_TONE;\n\t\t\t\t\tp_entry->Settings.InitStringIndex = 0;\n\t\t\t\t\tp_entry->Settings.CallWaitStringIndex = CALL_WAIT_CUSTOM;\n\t\t\t\t\tp_entry->Settings.CallWaitString[0] = 0;\n\n\t\t\t\t\tSession.PhoneBook.Add (p_entry);\n\t\t\t\t\tBuild_Phone_Listbox(&phonelist, &numedit, phone_num);\n\t\t\t\t\t/*............................................................\n\t\t\t\t\tSet the current listbox index to the newly-added item.\n\t\t\t\t\t............................................................*/\n\t\t\t\t\tfor (i = 0; i < Session.PhoneBook.Count(); i++) {\n\t\t\t\t\t\tif (p_entry == Session.PhoneBook[i]) {\n\t\t\t\t\t\t\tSession.CurPhoneIdx = i;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\n\t\t\t\tprocess = false;\n\t\t\t\trc = true;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tCANCEL: bail out\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\t\t\t\tbreak;\n\t\t}\n\n\t}\t/* end of while */\n\n\t/*------------------------------------------------------------------------\n\tSave any changes we've made to the phone list or settings\n\t------------------------------------------------------------------------*/\n\tif (changed) {\n\t\tSession.Write_MultiPlayer_Settings ();\n\t}\n\n\t/*------------------------------------------------------------------------\n\tClear the list box\n\t------------------------------------------------------------------------*/\n\twhile (phonelist.Count()) {\n\t\titem = (char *)phonelist.Get_Item(0);\n\t\tphonelist.Remove_Item(item);\n\t\tdelete [] item;\n\t}\n\n\treturn(rc);\n\n}\t/* end of Phone_Dialog */\n\n\n/***************************************************************************\n * Build_Phone_Listbox -- [re]builds the phone entry listbox               *\n *                                                                         *\n * This routine rebuilds the phone list box from scratch; it also updates\t*\n * the contents of the phone # edit field.\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tlist\t\tptr to list box\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tedit\t\tptr to edit box\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuf\t\tptr to buffer for phone #\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Build_Phone_Listbox (ListClass *list, EditClass *edit, char *buf)\n{\n\tint i;\n\tchar *item;\n\tchar phonename[21];\n\tchar phonenum[15];\n\n\t/*........................................................................\n\tClear the list\n\t........................................................................*/\n\twhile (list->Count()) {\n\t\titem = (char *)(list->Get_Item(0));\n\t\tlist->Remove_Item(item);\n\t\tdelete [] item;\n\t}\n\n\t/*\n\t** Now sort the phone list by name then number\n\t*/\n\tqsort ((void *)(&Session.PhoneBook[0]), Session.PhoneBook.Count(), sizeof(class PhoneEntryClass *), Phone_Compare);\n\n\t/*........................................................................\n\tBuild the list\n\t........................................................................*/\n\tfor (i = 0; i < Session.PhoneBook.Count(); i++) {\n\t\titem = new char[80];\n\t\tif ( !(strlen( Session.PhoneBook[i]->Name )) ) {\n\t\t\tstrcpy( phonename, \" \" );\n\t\t} else {\n\t\t\tstrncpy( phonename, Session.PhoneBook[i]->Name, 20 );\n\t\t\tphonename[21] = 0;\n\t\t}\n\n\t\tif ( !(strlen( Session.PhoneBook[i]->Number )) ) {\n\t\t\tstrcpy( phonenum, \" \" );\n\t\t} else {\n\t\t\tif ( strlen( Session.PhoneBook[i]->Number ) < 14) {\n\t\t\t\tstrcpy( phonenum, Session.PhoneBook[i]->Number );\n\t\t\t} else {\n\t\t\t\tstrncpy( phonenum, Session.PhoneBook[i]->Number, 12 );\n\t\t\t\tphonenum[12] = 0;\n\t\t\t\tstrcat( phonenum, \"...\" );\n\t\t\t}\n\t\t}\n\n\t\tif (Session.PhoneBook[i]->Settings.Baud != -1) {\n\t\t\tsprintf(item,\"%s\\t%s\\t%d\", phonename, phonenum,\n\t\t\t\tSession.PhoneBook[i]->Settings.Baud);\n\t\t} else {\n\t\t\tsprintf(item,\"%s\\t%s\\t[%s]\", phonename, phonenum,\n\t\t\t\tText_String(TXT_DEFAULT));\n\t\t}\n\t\tlist->Add_Item(item);\n\t}\n\tlist->Flag_To_Redraw();\n\n\t/*........................................................................\n\tInit the current phone book index\n\t........................................................................*/\n\tif (list->Count() == 0 || Session.CurPhoneIdx < -1) {\n\t\tSession.CurPhoneIdx = -1;\n\t} else {\n\t\tif (Session.CurPhoneIdx >= list->Count() ) {\n\t\t\tSession.CurPhoneIdx = 0;\n\t\t}\n\t}\n\n\t/*........................................................................\n\tFill in phone number edit buffer\n\t........................................................................*/\n\tif (Session.CurPhoneIdx > -1) {\n\t\tstrcpy (buf, Session.PhoneBook[Session.CurPhoneIdx]->Number);\n\t\tedit->Set_Text (buf, PhoneEntryClass::PHONE_MAX_NUM );\n\t\tlist->Set_Selected_Index( Session.CurPhoneIdx );\n\t}\n}\n\n\n/***************************************************************************\n * Phone_Compare -- for qsort\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tp1,p2\t\tptrs to elements to compare\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = same, -1 = (*p1) goes BEFORE (*p2), 1 = (*p1) goes AFTER (*p2)\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   02/14/1995 BR : Created.                                              *\n *=========================================================================*/\nstatic int Phone_Compare (const void *p1, const void *p2)\n{\n\tclass PhoneEntryClass *pe1,*pe2;\n\tint result;\n\n\tpe1 = *((class PhoneEntryClass **)p1);\n\tpe2 = *((class PhoneEntryClass **)p2);\n\n\tresult = strcmp( pe1->Name, pe2->Name );\n\n\t// if strings are equal then check the phone number\n\n\tif ( !result ) {\n\t\tresult = strcmp( pe1->Number, pe2->Number );\n\t}\n\n\treturn(result);\n}\n\n\n/***************************************************************************\n * Edit_Phone_Dialog -- lets user edit a phone book entry                  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tphone\t\tentry to edit\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = OK, false = cancel\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Edit_Phone_Dialog (PhoneEntryClass *phone)\n{\n\t/*........................................................................\n\tDialog & button dimensions\n\t........................................................................*/\n\tint d_dialog_w = 230 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 110 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2);\t\t// dialog x-coord\n\tint d_dialog_y = ((136 * RESFACTOR - d_dialog_h) / 2);\t\t// dialog y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_txt6_h = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_margin = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint d_name_w = ( (PhoneEntryClass::PHONE_MAX_NAME - 1) * 6) * RESFACTOR + 3 * RESFACTOR;\n\tint d_name_h = 9 * RESFACTOR;\n\tint d_name_x = d_dialog_x + (((d_dialog_w - d_name_w) * 3) / 4) - 5 * RESFACTOR;\n\tint d_name_y = d_dialog_y + 25 * RESFACTOR;\n\n\tint d_number_w = ( (PhoneEntryClass::PHONE_MAX_NUM - 1) * 6) * RESFACTOR + 3 * RESFACTOR;\n\tint d_number_h = 9 * RESFACTOR;\n\tint d_number_x = d_dialog_x + (((d_dialog_w - d_number_w) * 3) / 4) - 5 * RESFACTOR;\n\tint d_number_y = d_name_y + d_name_h + d_margin;\n\n\tint d_default_w = 130 * RESFACTOR;\n\tint d_default_h = 9 * RESFACTOR;\n\tint d_default_x = d_dialog_cx - (d_default_w / 2);\n\tint d_default_y = d_number_y + d_number_h + d_margin;\n\n\tint d_custom_w = 130 * RESFACTOR;\n\tint d_custom_h = 9 * RESFACTOR;\n\tint d_custom_x = d_dialog_cx - (d_default_w / 2);\n\tint d_custom_y = d_default_y + d_default_h + d_margin;\n\n\tint d_save_w = 55 * RESFACTOR;\n\tint d_save_h = 9 * RESFACTOR;\n\tint d_save_x = d_dialog_cx - d_margin - d_save_w;\n\tint d_save_y = d_dialog_y + d_dialog_h - d_margin - d_save_h - 5*RESFACTOR;\n\n\tint d_cancel_w = 55 * RESFACTOR;\n\tint d_cancel_h = 9 * RESFACTOR;\n\tint d_cancel_x = d_dialog_cx + d_margin;\n\tint d_cancel_y = d_dialog_y + d_dialog_h - d_margin - d_cancel_h - 5*RESFACTOR;\n\n\t/*........................................................................\n\tButton Enumerations\n\t........................................................................*/\n\tenum {\n\t\tBUTTON_NAME = 100,\n\t\tBUTTON_NUMBER,\n\t\tBUTTON_DEFAULT,\n\t\tBUTTON_CUSTOM,\n\t\tBUTTON_SAVE,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t/*........................................................................\n\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t........................................................................*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*........................................................................\n\tDialog variables\n\t........................................................................*/\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\n\tchar namebuf[PhoneEntryClass::PHONE_MAX_NAME] = { 0 };\t// buffer for editing name\n\tchar numbuf[PhoneEntryClass::PHONE_MAX_NUM] = { 0 };\t\t// buffer for editing phone #\n\tint rc;\n\tSerialSettingsType settings;\n\tbool custom = false;\n\tbool firsttime = true;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*........................................................................\n\tButtons\n\t........................................................................*/\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tEditClass nameedit(BUTTON_NAME, namebuf, PhoneEntryClass::PHONE_MAX_NAME, TPF_TEXT, d_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC);\n\tEditClass numedit(BUTTON_NUMBER, numbuf, PhoneEntryClass::PHONE_MAX_NUM, TPF_TEXT, d_number_x, d_number_y, d_number_w, d_number_h, EditClass::ALPHANUMERIC);\n\tTextButtonClass defaultbtn(BUTTON_DEFAULT, TXT_DEFAULT_SETTINGS, TPF_BUTTON, d_default_x, d_default_y, d_default_w, d_default_h);\n\tTextButtonClass custombtn(BUTTON_CUSTOM, TXT_CUSTOM_SETTINGS, TPF_BUTTON, d_custom_x, d_custom_y, d_custom_w, d_custom_h);\n\tTextButtonClass savebtn(BUTTON_SAVE, TXT_SAVE_BUTTON, TPF_BUTTON, d_save_x, d_save_y, d_save_w, d_save_h);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n\n\t/*\n\t------------------------- Build the button list --------------------------\n\t*/\n\tcommands = &nameedit;\n\tnumedit.Add_Tail(*commands);\n\tdefaultbtn.Add_Tail(*commands);\n\tcustombtn.Add_Tail(*commands);\n\tsavebtn.Add_Tail(*commands);\n\tcancelbtn.Add_Tail(*commands);\n\n\t/*\n\t----------------------------- Various Inits ------------------------------\n\t*/\n\t/*........................................................................\n\tInit the settings; if the phone entry is set to use defaults, init our\n\tsettings to sensible values (in case we invoke the setting editor);\n\totherwise, copy the entry's settings.\n\t........................................................................*/\n\tif (phone->Settings.Port == 0 || phone->Settings.IRQ == -1 ||\n\t\tphone->Settings.Baud == -1) {\n\t\tsettings = Session.SerialDefaults;\n\t\tdefaultbtn.Turn_On();\n\t\tcustom = false;\n\t} else {\n\t\tsettings = phone->Settings;\n\t\tcustombtn.Turn_On();\n\t\tcustom = true;\n\t}\n\n\tstrcpy (namebuf, phone->Name);\n\tnameedit.Set_Text (namebuf, PhoneEntryClass::PHONE_MAX_NAME);\n\n\tstrcpy (numbuf, phone->Number);\n\tnumedit.Set_Text (numbuf, PhoneEntryClass::PHONE_MAX_NUM);\n\n\t/*\n\t---------------------------- Processing loop -----------------------------\n\t*/\n\tbool process = true;\t\t\t\t\t\t// process while true\n\twhile (process) {\n\t\t/*\n\t\t........................ Invoke game callback .........................\n\t\t*/\n\t\tCall_Back();\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\t#endif\n\t\t/*\n\t\t...................... Refresh display if needed ......................\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\t\t\t/*\n\t\t\t.................. Redraw backgound & dialog box ...................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tCCPalette.Set();\n\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\t\t\t\tDraw_Caption (TXT_PHONE_LISTING, d_dialog_x, d_dialog_y, d_dialog_w);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDialog & Field labels\n\t\t\t\t...............................................................*/\n\t\t\t\tFancy_Text_Print (TXT_NAME_COLON, d_name_x - 5 * RESFACTOR, d_name_y + 1 * RESFACTOR, scheme, TBLACK, TPF_RIGHT | TPF_TEXT);\n\t\t\t\tFancy_Text_Print (TXT_NUMBER_COLON, d_number_x - 5 * RESFACTOR, d_number_y + 1 * RESFACTOR, scheme, TBLACK, TPF_RIGHT | TPF_TEXT);\n\t\t\t}\n\t\t\t/*\n\t\t\t.......................... Redraw buttons ..........................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t........................... Get user input ............................\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\tif ( firsttime ) {\n\t\t\tnameedit.Set_Focus();\n\t\t\tnameedit.Flag_To_Redraw();\n\t\t\tinput = commands->Input();\n\t\t\tfirsttime = false;\n\t\t}\n\n\t\t/*\n\t\t---------------------------- Process input ----------------------------\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_NAME | KN_BUTTON):\n\t\t\t\tnumedit.Set_Focus();\n\t\t\t\tnumedit.Flag_To_Redraw();\n\t\t\t\tbreak;\n\n//\t\t\tcase (BUTTON_NUMBER | KN_BUTTON):\n//\t\t\t\tnameedit.Clear_Focus();\n//\t\t\t\tnameedit.Flag_To_Redraw();\n//\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUse Default Serial Settings\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_DEFAULT | KN_BUTTON):\n\t\t\t\tcustombtn.Turn_Off();\n\t\t\t\tdefaultbtn.Turn_On();\n\t\t\t\tcustom = false;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUse Custom Serial Settings\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_CUSTOM | KN_BUTTON):\n\t\t\t\tif (Com_Settings_Dialog (&settings)) {\n\t\t\t\t\tcustombtn.Turn_On();\n\t\t\t\t\tdefaultbtn.Turn_Off();\n\t\t\t\t}\n\t\t\t\tcustom = true;\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tCANCEL: bail out\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tSave: save changes\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (KN_RETURN):\n\t\t\tcase (BUTTON_SAVE | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\trc = true;\n\t\t\t\tbreak;\n\t\t}\n\n\t}\t/* end of while */\n\n\t/*------------------------------------------------------------------------\n\tIf 'Save', save all current settings\n\t------------------------------------------------------------------------*/\n\tif (rc) {\n\t\tstrcpy( phone->Name, strupr( namebuf ) );\n\n\t\t// if nothing was entered then make if NONAME\n\n\t\tif ( !(phone->Name[0]) ) {\n\t\t\tstrcpy( phone->Name, \"NONAME\" );\n\t\t}\n\n\t\tstrcpy( phone->Number, strupr( numbuf ) );\n\n\t\tif (custom) {\n\t\t\tphone->Settings = settings;\n\t\t} else {\n\t\t\tphone->Settings.Port = 0;\n\t\t\tphone->Settings.IRQ = -1;\n\t\t\tphone->Settings.Baud = -1;\n\t\t\tphone->Settings.DialMethod = DIAL_TOUCH_TONE;\n\t\t\tphone->Settings.InitStringIndex = 0;\n\t\t\tphone->Settings.CallWaitStringIndex = CALL_WAIT_CUSTOM;\n\t\t\tphone->Settings.CallWaitString[0] = 0;\n\t\t}\n\t}\n\n\treturn(rc);\n\n\n}\t/* end of Edit_Phone_Dialog */\n\n\nstatic bool Dial_Modem( SerialSettingsType *settings, bool reconnect )\n{\n\tbool connected = false;\n\tDialStatusType dialstatus;\n\tint modemstatus;\n\n\t/*\n\t**\tTurn modem servicing off in the callback routine.\n\t*/\n\tSession.ModemService = false;\n\n\t// save for later to reconnect\n\n\tDialSettings = settings;\n\n\tmodemstatus = NullModem.Get_Modem_Status();\n\tif (reconnect) {\n\t\tif ( (modemstatus & CD_SET) ) {\n\t\t\tconnected = true;\n\t\t\tSession.ModemService = true;\n\t\t\treturn( connected );\n\t\t}\n\t} else if ( (modemstatus & CD_SET) ) {\n\t\tNullModem.Hangup_Modem();\n\t\tSession.ModemService = false;\n\t}\n\n\tNullModem.Setup_Modem_Echo( Modem_Echo );\n\n\tmodemstatus = NullModem.Detect_Modem( settings, reconnect );\n\tif ( !modemstatus ) {\n\t\tNullModem.Remove_Modem_Echo();\n\t\tNullModem.Print_EchoBuf();\n\t\tNullModem.Reset_EchoBuf();\n//#ifndef WIN32\n\t\t/*\n\t\t** If our first attempt to detect the modem failed, and we're at\n\t\t** 14400 or 28800, bump up to the next baud rate & try again.\n\t\t*/\n\t\tswitch (settings->Baud) {\n\t\t\tcase 14400:\n\t\t\t\tsettings->Baud = 19200;\n\t\t\t\tShutdown_Modem();\n\t\t\t\tInit_Null_Modem(settings);\n\t\t\t\tNullModem.Setup_Modem_Echo( Modem_Echo );\n\t\t\t\tmodemstatus = NullModem.Detect_Modem( settings, reconnect );\n\t\t\t\tif ( !modemstatus ) {\n\t\t\t\t\tNullModem.Remove_Modem_Echo();\n\t\t\t\t\tNullModem.Print_EchoBuf();\n\t\t\t\t\tNullModem.Reset_EchoBuf();\n\t\t\t\t\tWWMessageBox().Process( TXT_UNABLE_FIND_MODEM );\n\t\t\t\t\tSession.ModemService = true;\n\t\t\t\t\treturn( connected );\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 28800:\n\t\t\t\tsettings->Baud = 38400;\n\t\t\t\tShutdown_Modem();\n\t\t\t\tInit_Null_Modem(settings);\n\t\t\t\tNullModem.Setup_Modem_Echo( Modem_Echo );\n\t\t\t\tmodemstatus = NullModem.Detect_Modem( settings, reconnect );\n\t\t\t\tif ( !modemstatus ) {\n\t\t\t\t\tNullModem.Remove_Modem_Echo();\n\t\t\t\t\tNullModem.Print_EchoBuf();\n\t\t\t\t\tNullModem.Reset_EchoBuf();\n\t\t\t\t\tWWMessageBox().Process( TXT_UNABLE_FIND_MODEM );\n\t\t\t\t\tSession.ModemService = true;\n\t\t\t\t\treturn( connected );\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tWWMessageBox().Process( TXT_UNABLE_FIND_MODEM );\n\t\t\t\tSession.ModemService = true;\n\t\t\t\treturn( connected );\n\n\t\t}\n//#else\t//WIN32\n//\t\tSession.ModemService = true;\n//\t\treturn( connected );\n//#endif\t//WIN32\n\n\n\t} else if ( modemstatus == -1 ) {\n\t\tNullModem.Remove_Modem_Echo();\n\t\tNullModem.Print_EchoBuf();\n\t\tNullModem.Reset_EchoBuf();\n\t\tWWMessageBox().Process( TXT_ERROR_IN_INITSTRING );\n//\t\tWWMessageBox().Process( \"Error in the InitString.\" );\n\t\tSession.ModemService = true;\n\t\treturn( connected );\n\t}\n\n\n#ifdef WIN32\n#ifdef FIXIT_APTIVA_MODEM\n\n\t/*\n\t** Completely disable audio. This is required for MWave devices like those\n\t** found in the IBM Aptiva.\n\t*/\n\tThemeType old_theme = THEME_NONE;\n\tif (SoundOn){\n\t\told_theme = Theme.What_Is_Playing();\n\t\tTheme.Stop();\n\t\tCountDownTimerClass wait;\n\t\tCall_Back();\n\t\twait.Set (60,true);\n\t\twhile ( wait.Time() ) {\n\t\t\tCall_Back();\n\t\t}\n\t\tSound_End();\n\t\tCall_Back();\n\t\twait.Set (60,true);\n\t\twhile ( wait.Time() ) {\n\t\t\tCall_Back();\n\t\t}\n\t\tSoundOn = 0;\n\t}\n#endif\t//FIXIT_APTIVA_MODEM\n#endif\t//WIN32\n\n\tdialstatus = NullModem.Dial_Modem( DialString, settings->DialMethod, reconnect );\n\n\tif (reconnect) {\n\t\t/*\n\t\t--------------------------- Redraw the display ---------------------------\n\t\t*/\n\t\tHidPage.Clear();\n\t\tMap.Flag_To_Redraw(true);\n\t\tMap.Render();\n\t}\n\n\tswitch ( dialstatus ) {\n\t\tcase DIAL_CONNECTED:\n\t\t\tconnected = true;\n\t\t\tbreak;\n\n\t\tcase DIAL_NO_CARRIER:\n\t\t\tWWMessageBox().Process(TXT_NO_CARRIER);\n\t\t\tconnected = false;\n\t\t\tbreak;\n\n\t\tcase DIAL_BUSY:\n\t\t\tWWMessageBox().Process(TXT_LINE_BUSY);\n\t\t\tconnected = false;\n\t\t\tbreak;\n\n\t\tcase DIAL_ERROR:\n\t\t\tWWMessageBox().Process(TXT_NUMBER_INVALID);\n\t\t\tconnected = false;\n\t\t\tbreak;\n\n\t\tcase DIAL_NO_DIAL_TONE:\n\t\t\tWWMessageBox().Process(TXT_NO_DIAL_TONE);\n\t\t\tconnected = false;\n\t\t\tbreak;\n\n\t\tcase DIAL_CANCELED:\n\t\t\tNullModem.Hangup_Modem();\n\t\t\tSession.ModemService = false;\n\t\t\tWWMessageBox().Process(TXT_DIALING_CANCELED);\n\t\t\tconnected = false;\n\t\t\tbreak;\n\t}\n\n\tNullModem.Remove_Modem_Echo();\n\tNullModem.Print_EchoBuf();\n\tNullModem.Reset_EchoBuf();\n\n#ifdef WIN32\n#ifdef FIXIT_APTIVA_MODEM\n\t/*\n\t** Restore audio capability\n\t*/\n\tSoundOn = Audio_Init ( MainWindow , 16 , false , 11025*2 , 0 );\n\tif (SoundOn){\n\t\tTheme.Play_Song (old_theme);\n\t}\n#endif\t//FIXIT_APTIVA_MODEM\n#endif\t//WIN32\n\n\tSession.ModemService = true;\n\treturn( connected );\n\n}\t/* end of Dial_Modem */\n\n\nstatic bool Answer_Modem( SerialSettingsType *settings, bool reconnect )\n{\n\tbool connected = false;\n\tDialStatusType dialstatus;\n\tint modemstatus;\n\n\t/*\n\t**\tTurn modem servicing off in the callback routine.\n\t*/\n\tSession.ModemService = false;\n\n\t// save for later to reconnect\n\n\tDialSettings = settings;\n\n\tmodemstatus = NullModem.Get_Modem_Status();\n\tif (reconnect) {\n\t\tif ( (modemstatus & CD_SET) ) {\n\t\t\tconnected = true;\n\t\t\tSession.ModemService = true;\n\t\t\treturn( connected );\n\t\t}\n\t} else if ( (modemstatus & CD_SET) ) {\n\t\tNullModem.Hangup_Modem();\n\t\tSession.ModemService = false;\n\t}\n\n\tNullModem.Setup_Modem_Echo( Modem_Echo );\n\n\tmodemstatus = NullModem.Detect_Modem( settings, reconnect );\n\tif ( !modemstatus ) {\n\t\tNullModem.Remove_Modem_Echo();\n\t\tNullModem.Print_EchoBuf();\n\t\tNullModem.Reset_EchoBuf();\n//#ifndef WIN32\n\t\t/*\n\t\t** If our first attempt to detect the modem failed, and we're at\n\t\t** 14400 or 28800, bump up to the next baud rate & try again.\n\t\t*/\n\t\tswitch (settings->Baud) {\n\t\t\tcase 14400:\n\t\t\t\tsettings->Baud = 19200;\n\t\t\t\tShutdown_Modem();\n\t\t\t\tInit_Null_Modem(settings);\n\t\t\t\tNullModem.Setup_Modem_Echo( Modem_Echo );\n\t\t\t\tmodemstatus = NullModem.Detect_Modem( settings, reconnect );\n\t\t\t\tif ( !modemstatus ) {\n\t\t\t\t\tNullModem.Remove_Modem_Echo();\n\t\t\t\t\tNullModem.Print_EchoBuf();\n\t\t\t\t\tNullModem.Reset_EchoBuf();\n\t\t\t\t\tWWMessageBox().Process( TXT_UNABLE_FIND_MODEM );\n\t\t\t\t\tSession.ModemService = true;\n\t\t\t\t\treturn( connected );\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 28800:\n\t\t\t\tsettings->Baud = 38400;\n\t\t\t\tShutdown_Modem();\n\t\t\t\tInit_Null_Modem(settings);\n\t\t\t\tNullModem.Setup_Modem_Echo( Modem_Echo );\n\t\t\t\tmodemstatus = NullModem.Detect_Modem( settings, reconnect );\n\t\t\t\tif ( !modemstatus ) {\n\t\t\t\t\tNullModem.Remove_Modem_Echo();\n\t\t\t\t\tNullModem.Print_EchoBuf();\n\t\t\t\t\tNullModem.Reset_EchoBuf();\n\t\t\t\t\tWWMessageBox().Process( TXT_UNABLE_FIND_MODEM );\n\t\t\t\t\tSession.ModemService = true;\n\t\t\t\t\treturn( connected );\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tWWMessageBox().Process( TXT_UNABLE_FIND_MODEM );\n\t\t\t\tSession.ModemService = true;\n\t\t\t\treturn( connected );\n\n\t\t}\n//#else\t//WIN32\n//\t\tSession.ModemService = true;\n//\t\treturn( connected );\n//#endif\t//WIN32\n\t} else if ( modemstatus == -1 ) {\n\t\tNullModem.Remove_Modem_Echo();\n\t\tNullModem.Print_EchoBuf();\n\t\tNullModem.Reset_EchoBuf();\n\t\tWWMessageBox().Process( TXT_ERROR_IN_INITSTRING );\n\t\tSession.ModemService = true;\n\t\treturn( connected );\n\t}\n\n\n#ifdef WIN32\n#ifdef FIXIT_APTIVA_MODEM\n\t/*\n\t** Completely disable audio. This is required for some MWave devices like those\n\t** found in the IBM Aptiva.\n\t*/\n\tThemeType old_theme = THEME_NONE;\n\tif (SoundOn){\n\t\told_theme = Theme.What_Is_Playing();\n\t\tTheme.Stop();\n\t\tCountDownTimerClass wait;\n\t\tCall_Back();\n\t\twait.Set (60,true);\n\t\twhile ( wait.Time() ) {\n\t\t\tCall_Back();\n\t\t}\n\t\tSound_End();\n\t\tCall_Back();\n\t\twait.Set (60,true);\n\t\twhile ( wait.Time() ) {\n\t\t\tCall_Back();\n\t\t}\n\t\tSoundOn = 0;\n\t}\n#endif\t//FIXIT_APTIVA_MODEM\n#endif\t//WIN32\n\n\tdialstatus = NullModem.Answer_Modem( reconnect );\n\n\tswitch ( dialstatus ) {\n\t\tcase DIAL_CONNECTED:\n\t\t\tconnected = true;\n\t\t\tbreak;\n\n\t\tcase DIAL_NO_CARRIER:\n\t\t\tWWMessageBox().Process(TXT_NO_CARRIER);\n\t\t\tconnected = false;\n\t\t\tbreak;\n\n//\t\tcase DIAL_BUSY:\n//\t\t\tWWMessageBox().Process(TXT_LINE_BUSY);\n//\t\t\tconnected = false;\n//\t\t\tbreak;\n\n\t\tcase DIAL_ERROR:\n\t\t\tWWMessageBox().Process(TXT_NUMBER_INVALID);\n\t\t\tconnected = false;\n\t\t\tbreak;\n\n\t\tcase DIAL_CANCELED:\n\t\t\tWWMessageBox().Process(TXT_ANSWERING_CANCELED);\n\t\t\tconnected = false;\n\t\t\tbreak;\n\t}\n\n\tNullModem.Remove_Modem_Echo();\n\tNullModem.Print_EchoBuf();\n\tNullModem.Reset_EchoBuf();\n\n#ifdef WIN32\n#ifdef FIXIT_APTIVA_MODEM\n\t/*\n\t** Restore audio capability\n\t*/\n\tSoundOn = Audio_Init ( MainWindow , 16 , false , 11025*2 , 0 );\n\tif (SoundOn){\n\t\tTheme.Play_Song (old_theme);\n\t}\n#endif\t//FIXIT_APTIVA_MODEM\n#endif\t//WIN32\n\n\tSession.ModemService = true;\n\treturn( connected );\n\n}\t/* end of Answer_Modem */\n\n\nstatic void Modem_Echo( char c )\n{\n\tif (NullModem.EchoCount < (NullModem.EchoSize - 1) ) {\n\t\t*(NullModem.EchoBuf + NullModem.EchoCount) = c;\n\t\t*(NullModem.EchoBuf + NullModem.EchoCount + 1) = 0;\n\t\tNullModem.EchoCount++;\n\t}\n\n}\t/* end of Modem_Echo */\n\n\nvoid Smart_Printf( char *format, ... )\n{\n\tva_list arglist;\n\tchar buf[501];\n\n\n\tva_start(arglist,format);\n\tvsprintf(buf,format,arglist);\n\tva_end(arglist);\n\n\tif (Debug_Smart_Print) {\n\t\tif (MonoClass::Is_Enabled()) {\n\t\t\tMono_Printf(\"%s\",buf);\n\t\t} else {\n\t\t\tprintf(\"%s\",buf);\n\t\t}\n\t} else {\n\t\tif (Debug_Heap_Dump) {\n\t\t\tprintf(\"%s\",buf);\n\t\t}\n\t\tif (Debug_Modem_Dump) {\n\t\t\tprintf(\"%s\",buf);\n\t\t}\n\t}\n}\n\n\nvoid Hex_Dump_Data( char *buffer, int length )\n{\n\tint i;\n\tint offset = 0;\n\tchar buff[10];\n\tchar ptr[16];\n\tchar c;\n\n\n\twhile (length >= 16) {\n\t\tmemcpy( ptr, (buffer + offset), 16);\n\n\t\tSmart_Printf(\"%05lX  \", offset);\n\n\t\tfor (i = 0; i < 16; i++) {\n\n\t\t\tc = ptr[i];\n\t\t\titoh(c, buff);\n\n\t\t\tif (!(i & 0x3) && i) {\n\t\t\t\tSmart_Printf(\" \");\n\t\t\t}\n\n\t\t\tSmart_Printf(\"%s \", buff);\n\t\t}\n\n\t\tSmart_Printf(\"  \");\n\n\t\tfor (i = 0; i < 16; i++) {\n\t\t\tc = ptr[i];\n\n\t\t\tif (c && ((c < 7) || (c > 11)) && (c != 13)) {\n\t\t\t\tSmart_Printf(\"%c\", c);\n\t\t\t} else {\n\t\t\t\tSmart_Printf(\".\");\n\t\t\t}\n\t\t}\n\n\t\tSmart_Printf(\"\\n\");\n\n\t\toffset += 16;\n\t\tlength -= 16;\n\t}\n\n\tif (length) {\n\t\tmemcpy( ptr, (buffer + offset), 16);\n\n\t\tSmart_Printf(\"%05lX  \", offset);\n\n\t\tfor (i = 0; i < 16; i++) {\n\t\t\tif (i < length) {\n\t\t\t\tc = ptr[i];\n\t\t\t\titoh(c, buff);\n\t\t\t\tif (!(i & 0x3) && i) {\n\t\t\t\t\tSmart_Printf(\" \");\n\t\t\t\t}\n\t\t\t\tSmart_Printf(\"%s \", buff);\n\t\t\t} else {\n\t\t\t\tif (!(i & 0x3) && i) {\n\t\t\t\t\tSmart_Printf(\"  \");\n\t\t\t\t}\n\t\t\t\tSmart_Printf(\"   \");\n\t\t\t}\n\t\t}\n\n\t\tSmart_Printf(\"  \");\n\n\t\tfor (i = 0; i < length; i++) {\n\n\t\t\tc = ptr[i];\n\n\t\t\tif (c && ((c < 7) || (c > 11)) && (c != 13)) {\n\t\t\t\tSmart_Printf(\"%c\", c);\n\t\t\t} else {\n\t\t\t\tSmart_Printf(\".\");\n\t\t\t}\n\t\t}\n\n\t\tSmart_Printf(\"\\n\");\n\t}\n\n}\t/* end of Hex_Dump_Data */\n\n\nvoid itoh( int i, char *s)\n{\n\n\tint nibble, loop;\n\n//\t*s++ = '0';\n//\t*s++ = 'x';\n\n\tif (i == 0) {\n\t\t*s++ = '0';\n\t\t*s++ = '0';\n\t} else {\n\t\tfor (loop = 1; loop >= 0; loop--) {\n\t\t\tnibble = (i >> (loop << 2)) & 0x000F;\n\n\t\t\t/* decimal range */\n\t\t\tif (nibble < 10) {\n\t\t\t\t*s++ = '0' + nibble;\n\t\t\t} else {\n\t\t\t\t*s++ = 'A' + (nibble - 10);\n\t\t\t}\n\t\t}\n\t}\n\t*s = 0;\t\t\t\t\t\t\t/* null terminate it */\n}\n\nvoid Log_Start_Time( char *string )\n{\n//\tLogDump_Print = true;\n\n\tLogLevel = 0;\n\tLogLevelTime[ LogLevel ] = LogLastTime = TickCount;\n\n\tSmart_Printf( \"start tick=%d, %s \\n\", LogLastTime, string );\n}\n\n\nvoid Log_End_Time( char *string )\n{\n\tint i;\n\tunsigned long currtime;\n\tunsigned long ticks;\n\n\n\tcurrtime = TickCount;\n\twhile (LogLevel >= 0) {\n\t\tif (LogLevel < MAX_LOG_LEVEL) {\n\t\t\t//\n\t\t\t// put one space for each level as indenting\n\t\t\t//\n\t\t\ti = 0;\n\t\t\twhile (i++ < LogLevel) {\n\t\t\t\tSmart_Printf( \" \" );\n\t\t\t}\n\t\t} else {\n\t\t\tSmart_Printf( \"LogLevel %d too large!-! \\n\", LogLevel);\n\t\t\tLogLevel = MAX_LOG_LEVEL - 1;\n\t\t}\n\n\t\tticks = currtime - LogLevelTime[ LogLevel-- ];\n\t\tSmart_Printf( \"end tick=%d, ticks=%d, tsecs=%d, %s \\n\",\n\t\t\tcurrtime, ticks, ((ticks * 10) / 60), string );\n\t}\n\n\tLogDump_Print = false;\n}\n\n\nvoid Log_Time( char *string )\n{\n\tint i;\n\tunsigned long currtime;\n\tunsigned long ticks;\n\n\n\tcurrtime = TickCount;\n\n\tif (LogLevel < MAX_LOG_LEVEL) {\n\t\t//\n\t\t// put one space for each level as indenting\n\t\t//\n\t\ti = 0;\n\t\twhile (i++ < LogLevel) {\n\t\t\tSmart_Printf( \" \" );\n\t\t}\n\t} else {\n\t\tSmart_Printf( \"LogLevel %d too large!-! \\n\", LogLevel);\n\t\tLogLevel = MAX_LOG_LEVEL - 1;\n\t}\n\n\tticks = currtime - LogLastTime;\n\n\tSmart_Printf( \"tick=%d, ticks=%d, tsecs=%d, %s \\n\",\n\t\tcurrtime, ticks, ((ticks * 10) / 60), string );\n\n\tLogLastTime = currtime;\n}\n\n\nvoid Log_Start_Nest_Time( char *string )\n{\n\tint i;\n\tunsigned long currtime;\n\tunsigned long ticks;\n\n\n\tcurrtime = TickCount;\n\n\tif (LogLevel < MAX_LOG_LEVEL) {\n\t\t//\n\t\t// put one space for each level as indenting\n\t\t//\n\t\ti = 0;\n\t\twhile (i++ < LogLevel) {\n\t\t\tSmart_Printf( \" \" );\n\t\t}\n\t} else {\n\t\tSmart_Printf( \"LogLevel %d too large!-! \\n\", LogLevel);\n\t\tLogLevel = MAX_LOG_LEVEL - 1;\n\t}\n\n\tticks = currtime - LogLastTime;\n\tSmart_Printf( \"start ntick=%d, ticks=%d, tsecs=%d, %s \\n\",\n\t\tcurrtime, ticks, ((ticks * 10) / 60), string );\n\n\tif (LogLevel >= (MAX_LOG_LEVEL - 1) ) {\n\t\tSmart_Printf( \"Could not start another nesting Maxed at %d,%d!-! \\n\",\n\t\t\tLogLevel, (MAX_LOG_LEVEL - 1) );\n\t} else {\n\t\tLogLevelTime[ ++LogLevel ] = currtime;\n\t}\n\n\tLogLastTime = currtime;\n}\n\n\nvoid Log_End_Nest_Time( char *string )\n{\n\tint i;\n\tunsigned long currtime;\n\tunsigned long ticks;\n\n\n\tcurrtime = TickCount;\n\n\tif (LogLevel <= 0) {\n\t\tSmart_Printf( \"Could not end another nesting Mined at %d,%d!-! \\n\",\n\t\t\tLogLevel, 0 );\n\t\tLogLevel = 0;\n\t}\n\n\tif (LogLevel < MAX_LOG_LEVEL) {\n\t\t//\n\t\t// put one space for each level as indenting\n\t\t//\n\t\ti = 0;\n\t\twhile (i++ < LogLevel) {\n\t\t\tSmart_Printf( \" \" );\n\t\t}\n\t} else {\n\t\tSmart_Printf( \"LogLevel %d too large!-! \\n\", LogLevel);\n\t\tLogLevel = MAX_LOG_LEVEL - 1;\n\t}\n\n\tticks = currtime - LogLevelTime[ LogLevel ];\n\tSmart_Printf( \"end ntick=%d, ticks=%d, secs=%d, %s \\n\",\n\t\tcurrtime, ticks, ((ticks * 10) / 60), string );\n\n\tif (LogLevel) {\n\t\tLogLevel--;\n\t}\n\n\tLogLastTime = currtime;\n}\n"
  },
  {
    "path": "CODE/NULLMGR.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /counterstrike/NULLMGR.CPP 2     3/07/97 6:40p Steve_tall $ */\n/***************************************************************************\n ***              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               ***\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : NULLMGR.CPP                              *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : April 5, 1995       \t \t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : May 1, 1995 [BRR]                        *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:    \t\t\t                                                   *\n *   NullModemClass::NullModemClass -- class constructor                   *\n *   NullModemClass::~NullModemClass -- class destructor                   *\n *   NullModemClass::Init -- initialization\t\t\t\t\t\t\t\t\t\t\t*\n *   NullModemClass::Send_Message -- sends a message\t\t\t\t\t\t\t\t*\n *   NullModemClass::Get_Message -- polls the Queue for a message\t\t\t\t*\n *   NullModemClass::Service -- main polling routine\t\t\t\t\t\t\t\t*\n *   NullModemClass::Num_Send -- Returns # of unACK'd send entries\t\t\t*\n *   NullModemClass::Num_Receive -- Returns # entries in the receive queue *\n *   NullModemClass::Response_Time -- Returns Queue's avg response time    *\n *   NullModemClass::Reset_Response_Time -- Resets response time computatio*\n *   NullModemClass::Oldest_Send -- Returns ptr to oldest unACK'd send buf *\n *   NullModemClass::Detect_Modem -- Detects and initializes the modem     *\n *   NullModemClass::Dial_Modem -- dials a number passed                   *\n *   NullModemClass::Answer_Modem -- waits for call and answers            *\n *   NullModemClass::Hangup_Modem -- hangs up the modem                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#ifdef WIN32\n#include \"wincomm.h\"\n#include \"modemreg.h\"\nextern ModemRegistryEntryClass *ModemRegistry;\n#endif\t//WIN32\n#include \"i86.h\"\n\n\n// Turn off \"expression is not meaningful\".\n#pragma warning 628 9\n\n\n// the following line was taken from Greenleaf's <ibmkeys.h> <asciidef.h>\n// because of other define conflicts\n\n#define ESC\t\t         27\n#define NOKEY           0xffff\n#define INIT_COMMAND_RETRIES\t2\n\n// this time is in milliseconds\n\n#define DEFAULT_TIMEOUT\t\t\t1500\n\n//\n// the following is for a fix around a greenleaf bug\n// where they do not check for the value of abortkey\n// to determine whether or not they call the abort modem function.\n//\nextern \"C\" {\n\textern void (*_AbortModemFunctionPtr)(int);\n}\n\nstatic void (*NullModemClass::OrigAbortModemFunc)(int);\n\nstatic KeyNumType NullModemClass::Input;\nstatic GadgetClass *NullModemClass::Commands;\t\t// button list\n\n/*\n** Ugly hack: this string stores the string received from the modem\n*/\nchar ModemRXString[80];\n\n\n/***************************************************************************\n * NullModemClass::NullModemClass -- class constructor                     *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t\t# desired entries for the send queue\t\t\t\t\t\t*\n *\t\tnumreceive\t\t# desired entries for the receive queue\t\t\t\t\t*\n *\t\tmaxlen\t\t\tapplication's max packet length\t\t\t\t\t\t\t\t*\n *\t\tmagicnum\t\t\tapplication-specific magic # (so we don't \t\t\t\t*\n *\t\t\t\t\t\t\taccidentally end up talking to another one of our own\t*\n *\t\t\t\t\t\t\tproducts using the same protocol)\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nNullModemClass::NullModemClass (int numsend, int numreceive, int maxlen,\n\tunsigned short magicnum) : ConnManClass()\n{\n\t/*------------------------------------------------------------------------\n\tInit Port to NULL; we haven't opened Greenleaf yet.\n\t------------------------------------------------------------------------*/\n#ifdef WIN32\n\tPortHandle = NULL;\n#else\t//WIN32\n\tPort = NULL;\n#endif\t//WIN32\n\n\tConnection = NULL;\n\n\tNumSend = numsend;\n\tNumReceive = numreceive;\n\tMaxLen = maxlen;\n\tMagicNum = magicnum;\n\n\tRXBuf = 0;\n\tBuildBuf = 0;\n\n\tEchoSize = 500;\n\tEchoBuf = 0;\n\n\tOldIRQPri = -1;\n\n\tModemVerboseOn = false;\t\t\t\t\t// default true\n\tModemEchoOn = false;\t\t\t\t\t\t// default true\n\tModemWaitCarrier = 50000;\t\t\t\t// default 50 * 1000ms = 50 secs\n\tModemCarrierDetect = 600;\t\t\t\t// default 6  * 100ms  = .6 secs\n\tModemCarrierLoss = 1400;\t\t\t\t// default 14 * 100ms  = 1.4 secs\n\tModemHangupDelay = 20000;\t\t\t\t// default 20 * 1000ms = 20 secs\n\tModemGuardTime = 1000;\t\t\t\t\t// default 50 * 20ms   = 1 sec\n\tModemEscapeCode = '+';\t\t\t\t\t// default ASCII 43\n\n\tSendOverflows = 0;\n\tReceiveOverflows = 0;\n\tCRCErrors = 0;\n\n\tNumConnections = 0;\n\n\t/*------------------------------------------------------------------------\n\tInit timing parameters\n\t------------------------------------------------------------------------*/\n\tRetryDelta = 60;\t\t// 60 ticks between retries\n\tMaxRetries = -1;\t\t// disregard # retries\n\tTimeout = 1200;\t\t// report bad connection after 20 seconds\n\n}\t/* end of NullModemClass */\n\n\n/***************************************************************************\n * NullModemClass::~NullModemClass -- class destructor                     *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nNullModemClass::~NullModemClass ()\n{\n\tDelete_Connection();\n\n}\t/* end of ~NullModemClass */\n\n\n/***************************************************************************\n * NullModemClass::Init -- initialization\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tport\t\t\t\taddress  \t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tirq\t\t\t\t2-15     \t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *     dev_name\t\t\tname of communications device (win32 only)           *\n *\t\tbaud\t\t\t\t300, 1200, 9600, etc\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tparity\t\t\t'O' (odd), 'E' (even), 'N' (none), 'S' (space),\t\t  *\n *\t\t\t\t\t\t\t'M' (mark)\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\twordlength\t\t5, 6, 7, or 8\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tstopbits\t\t\t1 or 2\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *   10/9/1996  ST : Modified to take device name in win32                 *\n *=========================================================================*/\nint NullModemClass::Init (int port, int irq, char *dev_name, int baud, char parity, int wordlen, int stopbits, int flowcontrol)\n{\n\tint com;\n\n#ifdef WIN32\n\n\t/*\n\t** Get rid of the 'no reference to' warning\n\t*/\n\tirq = irq;\n\n\t/*\n\t** Make sure the port is closed before we start\n\t*/\n\tif (PortHandle) {\n\t\tCloseHandle (PortHandle);\n\t\tPortHandle = NULL;\n\t}\n\n\tif (!Connection) {\n\n#else\t//WIN32\n\n\tint irqnum;\n\tint address;\n\tint status;\n\n\t/*\n\t** Get rid of the 'no reference to' warning\n\t*/\n\tdev_name = dev_name;\n\n\tif (Port) {\n\t\tPortClose(Port);\n\t\tPort = NULL;\n\t}else {\n\n#endif\t//WIN32\n\n\t/*------------------------------------------------------------------------\n\tInit our Connection\n\t------------------------------------------------------------------------*/\n\t\tConnection = new NullModemConnClass (NumSend, NumReceive, MaxLen,\n\t\t\tMagicNum);\n\n\t\tConnection->Set_Retry_Delta (RetryDelta);\n\t\tConnection->Set_Max_Retries (MaxRetries);\n\t\tConnection->Set_TimeOut (Timeout);\n\n\t\t/*---------------------------------------------------------------------\n\t\tAllocate our packet parsing buffer; make it the same # of packets as the\n\t\t# of receive queue entries the application has requested.  Use the\n\t\t\"Actual\" maximum packet size, given from the connection; this allows for\n\t\tboth headers that get added to the packet.\n\t\t---------------------------------------------------------------------*/\n\t\tRXSize = Connection->Actual_Max_Packet() * NumReceive;\n\t\tRXBuf = new char [RXSize];\n\n\t\tBuildBuf = new char [MaxLen];\n\n\t\tEchoBuf = new char [ EchoSize ];\n\t}\n\n\tRXCount = 0;\n\tEchoCount = 0;\n\n\n\t/*------------------------------------------------------------------------\n\tThis call allocates all necessary queue buffers\n\t------------------------------------------------------------------------*/\n\tswitch (port) {\n\t\tcase 0x3f8:\n\t\t\tcom = COM1;\n\t\t\tbreak;\n\n\t\tcase 0x2f8:\n\t\t\tcom = COM2;\n\t\t\tbreak;\n\n\t\tcase 0x3e8:\n\t\t\tcom = COM3;\n\t\t\tbreak;\n\n\t\tcase 0x2e8:\n\t\t\tcom = COM4;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tcom = COM5;\n\t\t\tbreak;\n\t}\n\n#ifdef WIN32\n\tint\ti;\n\n\t/*\n\t** Create a new modem class for our com port\n\t*/\n\tif (!SerialPort) {\n\t\tSerialPort = new WinModemClass;\n\t}\n\n\t/*\n\t** Shift up the baud rate to sensible values\n\t*/\n//\tif (baud == 14400) baud = 19200;\n//\tif (baud == 28800) baud = 38400;\n\n\tstatic char com_ids[9][5]={\n\t\t\"COM1\",\n\t\t\"COM2\",\n\t\t\"COM3\",\n\t\t\"COM4\",\n\t\t\"COM5\",\n\t\t\"COM6\",\n\t\t\"COM7\",\n\t\t\"COM8\",\n\t\t\"COM9\"\n\t};\n\n\tchar *device;\n\n\tswitch ( port ) {\n\n\t\tcase 0x3f8:\n\t\t\tdevice = com_ids[0];\n\t\t\tbreak;\n\n\t\tcase 0x2f8:\n\t\t\tdevice = com_ids[1];\n\t\t\tbreak;\n\n\t\tcase 0x3e8:\n\t\t\tdevice = com_ids[2];\n\t\t\tbreak;\n\n\t\tcase 0x2e8:\n\t\t\tdevice = com_ids[3];\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\t/*\n\t\t\t** 1 is a special value. It means use the device name not the port address.\n\t\t\t*/\n\t\t\tdevice = dev_name;\n\n\t\t\t/*\n\t\t\t** If we can match a registry entry with the device name then use that, otherwise use\n\t\t\t** the device name directly to open the port with.\n\t\t\t*/\n\t\t\tif (ModemRegistry){\n\t\t\t\tdelete ModemRegistry;\n\t\t\t\tModemRegistry = NULL;\n\t\t\t}\n\t\t\tfor ( i=0 ; i<10 ; i++ ){\n\t\t\t\tModemRegistry = new ModemRegistryEntryClass (i);\n\t\t\t\tif (ModemRegistry->Get_Modem_Name()){\n\t\t\t\t\tif (!strcmp (dev_name, ModemRegistry->Get_Modem_Name() )){\n\t\t\t\t\t\tdevice = ModemRegistry->Get_Modem_Device_Name();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete ModemRegistry;\n\t\t\t\tModemRegistry = NULL;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tdevice = NULL;\n\t}\n\n\n\n\t/*\n\t** Open the com port\n\t*/\n\tPortHandle = SerialPort->Serial_Port_Open (device, baud, parity, wordlen, stopbits, flowcontrol);\n\tif (PortHandle == INVALID_HANDLE_VALUE) {\n\t\tShutdown();\n\t\treturn(false);\n\t}\n\n\tConnection->Init (PortHandle);\n\n#else\t//WIN32\n\n\tstatus = FastGetPortHardware( com, &irqnum, &address );\n\tif (status == ASSUCCESS) {\n\t\tif (port != address || irq != irqnum) {\n\n\t\t\tstatus = FastSetPortHardware( com, irq, port );\n\n\t\t\tif (status < ASSUCCESS) {\n\t\t\t\tMono_Printf( \"Unable to set Com port status %d\\n\", status );\n\t\t\t\tMono_Printf( \"Com port number %d with address %x, irq %d\\n\",\n\t\t\t\t\tcom + 1, port, irq );\n\t\t\t} else {\n\t\t\t\tMono_Printf( \"Changed Com port number %d to address %x, irq %d\\n\",\n\t\t\t\t\tcom + 1, port, irq );\n\t\t\t}\n\t\t} else {\n\t\t\tMono_Printf( \"No changes to Com port number %d with address %x, irq %d\\n\",\n\t\t\t\tcom + 1, port, irq );\n\t\t}\n\t} else {\n\t\tMono_Printf( \"Com port number %d\\n\", com + 1 );\n\t}\n\n\tif (status != ASSUCCESS) {\n\t\tDelete_Connection();\n\t\treturn(false);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tOpen the Greenleaf port\n\t------------------------------------------------------------------------*/\n\tPort = PortOpenGreenleafFast (com, baud, parity, wordlen, stopbits);\n\n\tif (Port->status != ASSUCCESS) {\n\t\tShutdown();\n\t\treturn(false);\n\t}\n\n//\tUseRtsCts( Port, 1 );\t\t\t// use RTS CTS hardware flow control\n\n\t/*------------------------------------------------------------------------\n\tInit the Connection\n\t------------------------------------------------------------------------*/\n\tConnection->Init(Port);\n\t//because Watcom is so stupid\n\tflowcontrol = flowcontrol;\n\n#endif\t//WIN32\n\n\tNumConnections = 1;\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * NMC::Num_Connections -- returns NumConnections member                                       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   NumConnections                                                                    *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 11:44AM ST : Documented / Win32 support                                           *\n *=============================================================================================*/\nint NullModemClass::Num_Connections( void )\n{\n\treturn(NumConnections);\n}\n\n\n/***********************************************************************************************\n * NMC::Delete_Connection -- removes the connection                                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   true                                                                              *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 11:44AM ST : Documented / Win32 support                                           *\n *=============================================================================================*/\nint NullModemClass::Delete_Connection( void )\n{\n\tif (Connection) {\n\t\tdelete Connection;\n\t\tConnection = NULL;\n\t}\n\n\tif (RXBuf) {\n\t\tdelete [] RXBuf;\n\t\tRXBuf = NULL;\n\t}\n\n\tif (BuildBuf) {\n\t\tdelete [] BuildBuf;\n\t\tBuildBuf = NULL;\n\t}\n\n\tif (EchoBuf) {\n\t\tdelete [] EchoBuf;\n\t\tEchoBuf = NULL;\n\t}\n\n\tNumConnections = 0;\n\n\treturn( true );\n}\t/* end of Delete_Connection */\n\n\n\n/***********************************************************************************************\n * NMC::Init_Send_Queue -- Initialises the connections send queue                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   true                                                                              *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 11:46AM ST : Documented / Win32 support                                           *\n *=============================================================================================*/\nint NullModemClass::Init_Send_Queue( void )\n{\n\n\t/*------------------------------------------------------------------------\n\tInit the send queue\n\t------------------------------------------------------------------------*/\n\tif ( Connection ) {\n\t\tConnection->Queue->Init_Send_Queue();\n\t}\n\n\treturn(true);\n}\n\n\n\n/***********************************************************************************************\n * NMC::Detect_Port -- Checks that the specified com port exists                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to SerialSettingsType                                                         *\n *                                                                                             *\n * OUTPUT:   true if port is valid                                                             *\n *                                                                                             *\n * WARNINGS: Win32 version always returns true as win95 shouldnt allow us to open the          *\n *           port if it doesnt exist or is in use by the mouse                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 11:47AM ST : Documented / Win32 support                                           *\n *=============================================================================================*/\nDetectPortType NullModemClass::Detect_Port( SerialSettingsType *settings )\n{\n\n#ifdef WIN32\n\n\tstatic char com_ids[9][5]={\n\t\t\"COM1\",\n\t\t\"COM2\",\n\t\t\"COM3\",\n\t\t\"COM4\",\n\t\t\"COM5\",\n\t\t\"COM6\",\n\t\t\"COM7\",\n\t\t\"COM8\",\n\t\t\"COM9\"\n\t};\n\n\tint\ti;\n\n\t/*\n\t** Create a new modem class for our com port\n\t*/\n\tif (!SerialPort) {\n\t\tSerialPort = new WinModemClass;\n\t}else{\n\t\tSerialPort->Serial_Port_Close();\n\t}\n\n\t/*\n\t** Shift up the baud rate to sensible values\n\t*/\n\tint baud = settings->Baud;\n//\tif (baud == 14400) baud = 19200;\n//\tif (baud == 28800) baud = 38400;\n\n\n\t/*\n\t** Translate the port address into a usable device name\n\t*/\n\tchar *device;\n\n\tswitch ( settings->Port ) {\n\n\t\tcase 0x3f8:\n\t\t\tdevice = com_ids[0];\n\t\t\tbreak;\n\n\t\tcase 0x2f8:\n\t\t\tdevice = com_ids[1];\n\t\t\tbreak;\n\n\t\tcase 0x3e8:\n\t\t\tdevice = com_ids[2];\n\t\t\tbreak;\n\n\t\tcase 0x2e8:\n\t\t\tdevice = com_ids[3];\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\t/*\n\t\t\t** 1 is a special value. It means use the device name not the port address.\n\t\t\t*/\n\t\t\tdevice = settings->ModemName;\n\n\t\t\t/*\n\t\t\t** If we can match a registry entry with the device name then use that, otherwise use\n\t\t\t** the device name directly to open the port with.\n\t\t\t*/\n\t\t\tif (ModemRegistry){\n\t\t\t\tdelete ModemRegistry;\n\t\t\t\tModemRegistry = NULL;\n\t\t\t}\n\t\t\tfor ( i=0 ; i<10 ; i++){\n\t\t\t\tModemRegistry = new ModemRegistryEntryClass (i);\n\t\t\t\tif (ModemRegistry->Get_Modem_Name()){\n\t\t\t\t\tif (!strcmp (device, ModemRegistry->Get_Modem_Name() )){\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Got a match. Break out leaving the registry info intact.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tdevice = ModemRegistry->Get_Modem_Device_Name();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete ModemRegistry;\n\t\t\t\tModemRegistry = NULL;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn (PORT_INVALID);\n\t}\n\n\t/*\n\t** Open the com port\n\t*/\n\tHANDLE porthandle = SerialPort->Serial_Port_Open (device, baud, 0, 8, 1, settings->HardwareFlowControl);\n\n\tif (porthandle == INVALID_HANDLE_VALUE){\n\t\treturn (PORT_INVALID);\n\t}\n\n\tSerialPort->Serial_Port_Close();\n\treturn (PORT_VALID);\n\n\n\n#else\t//WIN32\n\n\tunion REGS\t\tregs ;\n\tint com;\n\tint irqnum;\n\tint address;\n\tint status;\n\n\n\t// shutdown previous port\n\n\tShutdown();\n\n\tif (settings->IRQ > 0xf) {\n\t\treturn( PORT_INVALID );\n\t}\n\n\t//\n\t// check if the IRQ is the same as the mouse\n\t// call mouse func to get mouse IRQ number\n\t//\n\n\tregs.x.eax = 0x0024;\n\tint386( 0x33, &regs, &regs );\n\n\t//\n\t// check for error\n\t//\n\tif (regs.w.ax != 0xffff) {\n\t\t//\n\t\t// is the mouse IRQ the same as that they selected\n\t\t//\n\t\tif (regs.h.cl == 0) {\t// PS/2 IRQ 0xc\n\t\t\tif (settings->IRQ == 0xc) {\n\t\t\t\treturn( PORT_IRQ_INUSE );\n\t\t\t}\n\t\t} else if (regs.h.cl == (unsigned char)(settings->IRQ)) {\n\t\t\treturn( PORT_IRQ_INUSE );\n\t\t}\n\t}\n\n\tif (settings->IRQ < 2\t\t\t\t\t// 0 timer, 1 keyboard\n\t\t|| settings->IRQ == 6\t\t\t\t// floppy disk\n\t\t|| settings->IRQ == 8\t\t\t\t// CMOS real-time clock\n\t\t|| settings->IRQ == 0xd\t\t\t\t// math coprocessor error\n\t\t|| settings->IRQ == 0xe) {\t\t\t// hard disk\n\t\treturn( PORT_IRQ_INUSE );\n\t}\n\n\t/*------------------------------------------------------------------------\n\tThis call allocates all necessary queue buffers\n\t------------------------------------------------------------------------*/\n\tswitch ( settings->Port ) {\n\t\tcase 0x3f8:\n\t\t\tcom = COM1;\n\t\t\tbreak;\n\n\t\tcase 0x2f8:\n\t\t\tcom = COM2;\n\t\t\tbreak;\n\n\t\tcase 0x3e8:\n\t\t\tcom = COM3;\n\t\t\tbreak;\n\n\t\tcase 0x2e8:\n\t\t\tcom = COM4;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tcom = COM5;\n\t\t\tbreak;\n\t}\n\n\tstatus = FastGetPortHardware( com, &irqnum, &address );\n\tif (status == ASSUCCESS) {\n\t\tif (settings->Port != address || settings->IRQ != irqnum) {\n\t\t\tstatus = FastSetPortHardware( com, settings->IRQ, settings->Port );\n\t\t}\n\t}\n\n\tif (status != ASSUCCESS) {\n\t\treturn( PORT_INVALID );\n\t}\n\n\t/*------------------------------------------------------------------------\n\tOpen the Greenleaf port\n\t------------------------------------------------------------------------*/\n\tPort = PortOpenGreenleafFast (com, settings->Baud, 'N', 8, 1);\n\n\tstatus = Port->status;\n\n\tPortClose(Port);\n\tPort = NULL;\n\n\tif (status == ASIRQINUSE) {\n\t\treturn( PORT_IRQ_INUSE );\n\t} else if (status != ASSUCCESS) {\n\t\treturn( PORT_INVALID );\n\t}\n\n\treturn( PORT_VALID );\n#endif\t//WIN32\n}\n\n\n/***********************************************************************************************\n * NullModemClass::ShutDown -- Closes serial port and removes the connection                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 11:43AM ST : Documented / Win32 support                                           *\n *=============================================================================================*/\nvoid NullModemClass::Shutdown ( void )\n{\n\n#ifdef WIN32\n\n\tif (PortHandle && SerialPort) {\n\t\tSerialPort->Serial_Port_Close();\n\t\tdelete SerialPort;\n\t\tSerialPort = NULL;\n\t\tPortHandle = NULL;\n\t\tDelete_Connection();\n\t}\n\n#else\t//WIN32\n\tif (Port) {\n\t\tPortClose(Port);\n\t\tPort = NULL;\n\t\tDelete_Connection();\n\t}\n\n#endif\t//WIN32\n\n}\t/* end of Shutdown */\n\n\n/***************************************************************************\n * NullModemClass::Set_Timing -- sets timing for all connections\t\t\t\t*\n *                                                                         *\n * This will set the timing parameters.  This allows an application to\t\t*\n * measure the Response_Time while running, and adjust timing accordingly.\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tretrydelta\tvalue to set for retry delta \t\t\t\t\t\t\t\t\t\t*\n *\t\tmaxretries\tvalue to set for max # retries\t\t\t\t\t\t\t\t\t*\n *\t\ttimeout\t\tvalue to set for connection timeout\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   08/07/1995 DRD : Created.                                             *\n *=========================================================================*/\nvoid NullModemClass::Set_Timing (unsigned long retrydelta,\n\tunsigned long maxretries, unsigned long timeout)\n{\n\tRetryDelta = retrydelta;\n\tMaxRetries = maxretries;\n\tTimeout = timeout;\n\n\tConnection->Set_Retry_Delta (RetryDelta);\n\tConnection->Set_Max_Retries (MaxRetries);\n\tConnection->Set_TimeOut (Timeout);\n\n}\t/* end of Set_Timing */\n\n\n/***************************************************************************\n * NullModemClass::Send_Message -- sends a message\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * For clarity's sake, here's what happens to the buffer passed in:\t\t\t*\n * - It gets passed to the Connection's Send_Packet() routine\t\t\t\t\t*\n * - The CommHeaderType header gets tacked onto it\t\t\t\t\t\t\t\t\t*\n * - The resulting buffer gets added to the Connection's Send Queue\t\t\t*\n * - When Service() determines that it needs to send the data, it\t\t\t\t*\n *   copies the entire packet (CommHeaderType and all) into its local \t\t*\n *   SendBuf, adds the packet start ID, length, and CRC, then sends it out.*\n *                                                                         *\n * The ack_req argument will almost always be '1' (the default).  The only\t*\n * reason to use 0 is if you don't know whether the other system is\t\t\t*\n * ready or not, so you have to periodically send out a query packet,\t\t*\n * and wait for a response.  (Using the connection's built-in retry\t\t\t*\n * system would just blast out useless data if the other system isn't\t\t*\n * even there.)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tack_req\t\t1 = ACK is required; 0 = not\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK; 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NullModemClass::Send_Message (void *buf, int buflen, int ack_req)\n{\n\tint rc;\n\n\tif (NumConnections == 0) {\n\t\treturn( false );\n\t}\n\n\trc = Connection->Send_Packet(buf,buflen,ack_req);\n\tif (!rc)\n\t\tSendOverflows++;\n\n\treturn(rc);\n\n}\t/* end of Send_Message */\n\n\n/***************************************************************************\n * NullModemClass::Get_Message -- polls the Queue for a message\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to store message in\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tptr filled in with length of message\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = message was received; 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NullModemClass::Get_Message (void *buf, int *buflen)\n{\n\tif (NumConnections == 0) {\n\t\treturn( false );\n\t}\n\treturn( Connection->Get_Packet( buf, buflen ) );\n}\n\n\n/***************************************************************************\n * NullModemClass::Service -- main polling routine\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = connection has gone bad\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *   8/2/96     ST : Win32 support                                         *\n *=========================================================================*/\nint NullModemClass::Service (void)\n{\n\tint pos;\t\t\t\t// current position in RXBuf\n\tint i;\t\t\t\t// loop counter\n\tunsigned short length;\n\tSerialHeaderType *header;\t// decoded packet start, length\n\tSerialCRCType *crc;\t\t\t// decoded packet CRC\n\tchar moredata = 0;\n\n\tif (NumConnections == 0) {\n\t\treturn( false );\n\t}\n\n#ifdef WIN32\n\n\tRXCount += SerialPort->Read_From_Serial_Port((unsigned char*)(RXBuf + RXCount), int(RXSize - RXCount) );\n\n#else\t//WIN32\n\n\tint status;\n\tstatic unsigned long last_time = 0;\n\n\t/*------------------------------------------------------------------------\n\tFirst, copy all the bytes we can from the Greenleaf RX buffer to our\n\town buffer.\n\t(For Win95, only call GetLineStatus() 60 times a second at most.\n\tOtherwise, we don't receive any packets!)\n\t------------------------------------------------------------------------*/\n\tif ( (TickCount - last_time) > 0) {\n\t\tif ( GetLineStatus( Port ) ) {\n\t\t\tMono_Set_Cursor(0,0);\n\t\t\tClearLineStatus( Port );\n\t\t}\n\t\tlast_time = TickCount;\n\t}\n\n\tstatus = SpaceUsedInRXBuffer( Port );\n\n\tif ( status < ASSUCCESS) {\n//\t\tSmart_Printf( \"SpaceUsedInRXBuffer status = %d, port status = %d \\n\", status, Port->status );\n\n\t\tif ( Port->status < ASSUCCESS ) {\n\t\t\tClearError( Port );\n\t\t}\n\n\t} else if (status > 0) {\n\t\tstatus = ReadBuffer( Port, RXBuf + RXCount, RXSize - RXCount );\n\n#if (CONN_DEBUG)\n\t\tprintf( \"ReadBuffer status = %d, port status = %d, count = %d \\n\", status, Port->status, Port->count );\n#endif\n//\t\t\tSmart_Printf( \"ReadBuffer status = %d, port status = %d, count = %d \\n\", status, Port->status, Port->count );\n\t\tif (status < ASSUCCESS && status != ASBUFREMPTY) {\n//\t\t\t\tSmart_Printf( \"ReadBuffer ERRRRRRORRRRRR! \\n\" );\n\t\t} else {\n\t\t\tmoredata = 1;\n\t\t}\n\n\t\tif ( Port->status < ASSUCCESS ) {\n\t\t\tClearError( Port );\n\t\t}\n\n\t\tRXCount += Port->count;\n\t}\n\n\n#endif\t//WIN32\n\n\t// minimum packet size\n\n\tif ( RXCount < (PACKET_SERIAL_OVERHEAD_SIZE + 1) ) {\n\t\treturn( Connection->Service() );\n\t}\n\n\t/*------------------------------------------------------------------------\n\tNow scan the buffer for the start of a packet.\n\t------------------------------------------------------------------------*/\n\tpos = -1;\n\tfor (i = 0; i <= RXCount - sizeof( short ); i++) {\n\t\tif ( *((unsigned short *)(RXBuf + i)) == PACKET_SERIAL_START ) {\n\t\t\tpos = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tNo start code was found; throw away all bytes except the last few, and\n\treturn.\n\t------------------------------------------------------------------------*/\n\tif (pos==-1) {\n// Smart_Printf( \"No magic number found \\n\" );\n\t\t/*.....................................................................\n\t\tmove the remaining, un-checked bytes to the start of the buffer\n\t\t.....................................................................*/\n\t\tmemmove (RXBuf, RXBuf + i, sizeof( short ) - 1);\n\t\tRXCount = sizeof( short ) - 1;\n\t\treturn( Connection->Service() );\n\t}\n\n\t/*------------------------------------------------------------------------\n\tCheck to see if there are enough bytes for the header to be decoded\n\t------------------------------------------------------------------------*/\n\tif ( (RXCount - pos) < sizeof( SerialHeaderType ) ) {\n\t\tmemmove (RXBuf, RXBuf + pos, RXCount - pos);\n\t\tRXCount -= pos;\n\t\treturn(Connection->Service());\n\t}\n\n\t/*------------------------------------------------------------------------\n\tA start code was found; check the packet's length & CRC\n\t------------------------------------------------------------------------*/\n\theader = (SerialHeaderType *)(RXBuf + pos);\n\n\t/*------------------------------------------------------------------------\n\tIf we lost a byte in the length, we may end up waiting a very long time\n\tfor the buffer to get to the right length; check the verify value to\n\tmake sure this didn't happen.\n\t------------------------------------------------------------------------*/\n\tif ( header->MagicNumber2 != PACKET_SERIAL_VERIFY ) {\n// Smart_Printf( \"Verify failed\\n\");\n//\t\tHex_Dump_Data( (RXBuf + pos), PACKET_SERIAL_OVERHEAD_SIZE );\n\n\t\tpos += sizeof ( short );\t\t// throw away the bogus start code\n\t\tmemmove (RXBuf, RXBuf + pos, RXCount - pos);\n\t\tRXCount -= pos;\n\t\treturn(Connection->Service());\n\t}\n\n\tlength = header->Length;\n\n\t/*------------------------------------------------------------------------\n\tSpecial case: if the length comes out too long for us to process:\n\t- Assume the packet is bad\n\t- Throw away the bogus packet-start code\n\t- Return;  we'll search for another packet-start code next time.\n\t------------------------------------------------------------------------*/\n\tif (length > MaxLen) {\n#if (CONN_DEBUG)\n\t\tprintf( \"length too lonnng\\n\" );\n#endif\n// Smart_Printf( \"length too lonnng %d, max %d \\n\", length, MaxLen );\n\n\t\tpos += sizeof ( short );\t\t// throw away the bogus start code\n\t\tmemmove (RXBuf, RXBuf + pos, RXCount - pos);\n\t\tRXCount -= pos;\n\t\treturn(Connection->Service());\n\t}\n\n\t/*------------------------------------------------------------------------\n\tIf the entire packet isn't stored in our buffer, copy the remaining bytes\n\tto the front of the buffer & return.\n\t------------------------------------------------------------------------*/\n\tif ( (pos + length + PACKET_SERIAL_OVERHEAD_SIZE) > RXCount) {\n\n\t\tif ( moredata ) {\n// Smart_Printf( \"waiting for more data %d, pos = %d \\n\", ((length + PACKET_SERIAL_OVERHEAD_SIZE) - (RXCount - pos)), pos );\n\t\t}\n\n\t\tif (pos) {\n\t\t\tmemmove (RXBuf, RXBuf + pos, RXCount - pos);\n\t\t\tRXCount -= pos;\n\t\t}\n\t\treturn(Connection->Service());\n\t}\n\n\t/*------------------------------------------------------------------------\n\tNow grab the CRC value in the packet, & compare it to the CRC value\n\tcomputed from the actual data.  If they don't match, throw away the bogus\n\tstart-code, move the rest to the front of the buffer, & return.\n\tWe'll continue parsing this data when we're called next time.\n\t------------------------------------------------------------------------*/\n\tcrc = (SerialCRCType *)(RXBuf + pos + sizeof( SerialHeaderType ) + length);\n\tif (NullModemConnClass::Compute_CRC(RXBuf + pos +\n\t\tsizeof( SerialHeaderType ), length) != crc->SerialCRC) {\n\n\t\tCRCErrors++;\n\n#if (CONN_DEBUG)\n\t\tprintf( \"CRC check failed\\n\" );\n#endif\n// Smart_Printf( \"CRC check failed for packet of length %d \\n\", length );\n\n//\t\tif (length < 100) {\n//\t\t\tHex_Dump_Data( (RXBuf + pos), (PACKET_SERIAL_OVERHEAD_SIZE + length) );\n//\t\t}\n\n\t\tpos += sizeof ( short );\t\t// throw away the bogus start code\n\t\tmemmove (RXBuf, RXBuf + pos, RXCount - pos);\n\t\tRXCount -= pos;\n\t\treturn(Connection->Service());\n\t}\n\n#if(0)\n// Mono_Printf( \"received %d bytes \\n\", sendlen );\n Debug_Modem_Dump = true;\n Smart_Printf( \"Received tick=%d, Protocol=%d \\n\",  TickCount, Session.CommProtocol );\n Hex_Dump_Data( (RXBuf + pos), (sizeof( SerialHeaderType) + length) );\n Debug_Modem_Dump = false;\n#endif\n\n\t/*------------------------------------------------------------------------\n\tGive the new packet to the Connection to process.\n\t------------------------------------------------------------------------*/\n\tif (!Connection->Receive_Packet(RXBuf + pos + sizeof( SerialHeaderType ), length)) {\n\t\tReceiveOverflows++;\n// Smart_Printf( \"Received overflows %d \\n\", ReceiveOverflows );\n\t}\n\n#if(0)\n\telse {\n// Mono_Printf( \"added packet \\n\", sendlen );\n Debug_Modem_Dump = true;\n Smart_Printf( \"Received Packet \\n\" );\n Debug_Modem_Dump = false;\n\t}\n#endif\n\n#if (0)\n\tHex_Dump_Data( (RXBuf + pos), (PACKET_SERIAL_OVERHEAD_SIZE + length) );\n#endif\n\n\t/*------------------------------------------------------------------------\n\tMove all data past this packet to the front of the buffer.\n\t------------------------------------------------------------------------*/\n\tpos += (PACKET_SERIAL_OVERHEAD_SIZE + length);\n\tmemmove (RXBuf, RXBuf + pos, RXCount - pos);\n\tRXCount -= pos;\n\n\t/*------------------------------------------------------------------------\n\tNow, service the connection's Queue's; this will handle ACK & Retries.\n\t------------------------------------------------------------------------*/\n\treturn(Connection->Service());\n\n}\t/* end of Service */\n\n\n/***************************************************************************\n * NullModemClass::Num_Send -- Returns # of unACK'd send entries\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/01/1995 BRR : Created.                                             *\n *=========================================================================*/\nint NullModemClass::Num_Send(void)\n{\n\tif (Connection)\n\t\treturn( Connection->Queue->Num_Send() );\n\telse\n\t\treturn (0);\n\n}\t/* end of Num_Send */\n\n\n/***************************************************************************\n * NullModemClass::Num_Receive -- Returns # entries in the receive queue   *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/01/1995 BRR : Created.                                             *\n *=========================================================================*/\nint NullModemClass::Num_Receive(void)\n{\n\tif (Connection)\n\t\treturn( Connection->Queue->Num_Receive() );\n\telse\n\t\treturn (0);\n\n}\t/* end of Num_Receive */\n\n\n/***************************************************************************\n * NullModemClass::Response_Time -- Returns Queue's avg response time      *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/01/1995 BRR : Created.                                             *\n *=========================================================================*/\nunsigned long NullModemClass::Response_Time(void)\n{\n\tif (Connection)\n\t\treturn( Connection->Queue->Avg_Response_Time() );\n\telse\n\t\treturn (0);\n\n}\t/* end of Response_Time */\n\n\n/***************************************************************************\n * NullModemClass::Reset_Response_Time -- Resets response time computation *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/01/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid NullModemClass::Reset_Response_Time(void)\n{\n\tif (Connection)\n\t\tConnection->Queue->Reset_Response_Time();\n\n}\t/* end of Reset_Response_Time */\n\n\n/***************************************************************************\n * Oldest_Send -- Returns ptr to oldest unACK'd send buffer                *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/01/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid * NullModemClass::Oldest_Send(void)\n{\n\tint i;\n\tSendQueueType *send_entry;\t\t\t\t// ptr to send entry header\n\tCommHeaderType *packet;\n\tvoid *buf = NULL;\n\n\tfor (i = 0; i < Connection->Queue->Num_Send(); i++) {\n\t\tsend_entry = Connection->Queue->Get_Send(i);\n\t\tif (send_entry) {\n\t\t\tpacket = (CommHeaderType *)send_entry->Buffer;\n\t\t\tif (packet->Code == ConnectionClass::PACKET_DATA_ACK && send_entry->IsACK == 0) {\n\t\t\t\tbuf = send_entry->Buffer;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(buf);\n\n}\t/* end of Oldest_Send */\n\n\n/***************************************************************************\n * NullModemClass::Configure_Debug -- sets up special debug values         *\n *                                                                         *\n * Mono_Debug_Print2() can look into a packet to pull out a particular\t\t*\n * ID, and can print both that ID and a string corresponding to\t\t\t\t*\n * that ID.  This routine configures these values so it can find\t\t\t\t*\n * and decode the ID.  This ID is used in addition to the normal\t\t\t\t*\n * CommHeaderType values.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\t\t(not used)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\ttype_offset\t\tID's byte offset into packet\t\t\t\t\t\t\t\t\t*\n *\t\ttype_size\t\tsize of ID, in bytes; 0 if none\t\t\t\t\t\t\t\t*\n *\t\tnames\t\t\t\tptr to array of names; use ID as an index into this\t*\n *\t\tnamestart\t\tnumerical start of the 1st name value\t\t\t\t\t\t*\n *\t\tnamecount\t\t# in the names array; 0 if none.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tNames shouldn't be longer than 12 characters.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/31/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid NullModemClass::Configure_Debug(int, int type_offset, int type_size,\n\tchar **names, int namestart, int namecount)\n{\n\tif (Connection)\n\t\tConnection->Queue->Configure_Debug (type_offset, type_size, names,\n\t\t\tnamestart, namecount);\n}\n\n#ifdef CHEAT_KEYS\n/***************************************************************************\n * Mono_Debug_Print -- Debug output routine                                *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\t\t(not used)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\trefresh\t\t1 = clear screen & completely refresh\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/02/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid NullModemClass::Mono_Debug_Print(int,int refresh)\n{\n\tif (!Connection)\n\t\treturn;\n\n\tConnection->Queue->Mono_Debug_Print (refresh);\n\n\tif (refresh) {\n\t\tMono_Set_Cursor (31,1);\n\t\tMono_Printf (\"Serial Port Queues\");\n\n\t\tMono_Set_Cursor (9,2);\n\t\tMono_Printf (\"Average Response Time:\");\n\n\t\tMono_Set_Cursor (20,3);\n\t\tMono_Printf (\"CRC Errors:\");\n\n\t\tMono_Set_Cursor (43,2);\n\t\tMono_Printf (\"Send Overflows:\");\n\n\t\tMono_Set_Cursor (40,3);\n\t\tMono_Printf (\"Receive Overflows:\");\n\t}\n\n\tMono_Set_Cursor (32,2);\n\tMono_Printf (\"%d  \", Connection->Queue->Avg_Response_Time());\n\n\tMono_Set_Cursor (32,3);\n\tMono_Printf (\"%d  \", CRCErrors);\n\n\tMono_Set_Cursor (59,2);\n\tMono_Printf (\"%d  \", SendOverflows);\n\n\tMono_Set_Cursor (59,3);\n\tMono_Printf (\"%d  \", ReceiveOverflows);\n\n\tMono_Set_Cursor (2,5);\n\tMono_Printf (\"%d  \", Num_Send());\n\n\tMono_Set_Cursor (41,5);\n\tMono_Printf (\"%d  \", Num_Receive());\n\n}\t/* end of Mono_Debug_Print */\n#endif\n\n\n/***************************************************************************\n * NullModemClass::Detect_Modem -- Detects and initializes the modem       *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsettings\t\tptr to SerialSettings structure     \t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t-1\t\t\t\tinit string invalid\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t0\t\t\t\tno modem found\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t1\t\t\t\tmodem found\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/02/1995 DRD : Created.                                             *\n *   8/2/96      ST : Added Win32 support                                  *\n *=========================================================================*/\nint NullModemClass::Detect_Modem( SerialSettingsType *settings, bool reconnect )\n{\n\t/*------------------------------------------------------------------------\n\tButton Enumerations\n\t------------------------------------------------------------------------*/\n\tint status;\n\tint error_count = 0;\n\n\tint x,y,width,height;\t\t\t\t\t// dialog dimensions\n\tchar buffer[80*3];\n\n\t/*\n\t** Get resolution factor\n\t*/\n//\tint\tfactor = SeenBuff.Get_Width()/320;\n\n\t/*------------------------------------------------------------------------\n\tDetermine the dimensions of the text to be used for the dialog box.\n\tThese dimensions will control how the dialog box looks.\n\t------------------------------------------------------------------------*/\n\tstrcpy( buffer, Text_String( TXT_INITIALIZING_MODEM ) );\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT);\n\tint lines = Format_Window_String(buffer, SeenBuff.Get_Height(), width, height);\n\n\twidth = max(width, 90 * RESFACTOR);\n\twidth += 40 * RESFACTOR;\n\theight += 40 * RESFACTOR;\n\n\tx = (SeenBuff.Get_Width() - width) / 2;\n\ty = (SeenBuff.Get_Height() - height) / 2;\n\n\t/*------------------------------------------------------------------------\n\tInitialize\n\t------------------------------------------------------------------------*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*------------------------------------------------------------------------\n\tDraw the dialog\n\t------------------------------------------------------------------------*/\n\tHide_Mouse();\n\tif ( !reconnect ) {\n\t\tLoad_Title_Page(true);\n\t}\n\n\tDialog_Box(x, y, width, height);\n\tDraw_Caption(TXT_NONE, x, y, width);\n\n\tif (lines == 1) {\n\t\tFancy_Text_Print(buffer, x + width/2, y + 25, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT|TPF_CENTER);\n\t} else {\n\t\tFancy_Text_Print(buffer, x + 20*RESFACTOR, y + 25, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT);\n\t}\n\n\tShow_Mouse();\n\n\n\tHMWaitForOK( 0, NULL );\n\n\n\t/*\n\t** OK, lets not mess about any more. Just turn on echo, verbose, and result codes\n\t** before we even begin. At least this way when we get an error later on we have already\n\t** removed all the steps we use to try and recover.\n\t** The timeouts need to be quite small in case the modem is turned off.\n\t*/\n\n\t/*\n\t** Turn on result codes.\n\t*/\n\tSend_Modem_Command ( \"ATQ0\", '\\r', buffer, 81, DEFAULT_TIMEOUT / 2, 2);\n\n\t/*\n\t** Make result codes verbose.\n\t*/\n\tSend_Modem_Command ( \"ATV1\", '\\r', buffer, 81, DEFAULT_TIMEOUT / 2, 2);\n\n\t/*\n\t** Turn on echo.\n\t*/\n\tSend_Modem_Command ( \"ATE1\", '\\r', buffer, 81, DEFAULT_TIMEOUT / 2, 2);\n\n\tModemVerboseOn = true;\n\tModemEchoOn = true;\n\n\n\n\n\n\t/*\n\t** Try sending a plain old AT command to the modem. Now that we have theoretically\n\t** turned on verbose result codes we should get an 'OK' back.\n\t**\n\t*/\n\tstatus = Send_Modem_Command( \"AT\", '\\r', buffer, 81, DEFAULT_TIMEOUT, 2 );\n\n\tif (status < ASSUCCESS) {\n#ifdef FIXIT_MULTI_SAVE\n\t\treturn(false);\n#else\n\t\tif (WWMessageBox().Process(TXT_ERROR_NO_RESP, TXT_IGNORE, TXT_CANCEL)) return( false );\n\t\terror_count++;\n#endif\n\t}\n\n\t/*\n\t** Send the user supplied modem init string\n\t*/\n\tif (settings->InitStringIndex == -1) {\n\t\tstatus = Send_Modem_Command( \"\", '\\r', buffer, 81, 300, 1 );\n\t} else {\n\t\t/*\n\t\t** Split up the init string into seperate strings if it contains one or more '|' characters.\n\t\t** This character acts as a carriage return/pause.\n\t\t*/\n\t\tchar *istr = new char [2 + strlen( Session.InitStrings [settings->InitStringIndex] )];\n\t\tchar *tokenptr;\n\t\tstrcpy (istr, Session.InitStrings [settings->InitStringIndex] );\n\n\t\t/*\n\t\t** Tokenise the string and send it in chunks\n\t\t*/\n\t\ttokenptr = strtok ( istr, \"|\" );\n\t\twhile ( tokenptr ) {\n\n\t\t\tstatus = Send_Modem_Command( tokenptr, '\\r', buffer, 81, 3000, 1 );\n\t\t\t/*\n\t\t\t** Handle error case.\n\t\t\t*/\n\t\t\tif (status < ASSUCCESS) {\n\t\t\t\tif (WWMessageBox().Process(TXT_ERROR_NO_INIT, TXT_IGNORE, TXT_CANCEL)) {\n\t\t\t\t\tdelete istr;\n\t\t\t\t\treturn( false );\n\t\t\t\t}\n#ifdef WIN32\n\t\t\t\terror_count++;\n#endif\t//WIN32\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\ttokenptr = strtok ( NULL, \"|\");\n\n\t\t}\n\t}\n\n#ifdef WIN32\n\n\tif (settings->Port == 1 && ModemRegistry) {\n\t\t/*\n\t\t** Send the init strings from the registry if available\n\t\t*/\n\t\tchar send_string[256] = {\"AT\"};\n\n\t\t/*\n\t\t** Send the init string for hardware flow control\n\t\t*/\n\t\tif (settings->HardwareFlowControl){\n\t\t\tif (ModemRegistry->Get_Modem_Hardware_Flow_Control()) {\n\t\t\t\tstrcpy (&send_string[2], ModemRegistry->Get_Modem_Hardware_Flow_Control());\n\t\t\t\tstatus = Send_Modem_Command (send_string, '\\r', buffer, 81, 300, 1);\n\t\t\t\tif (status != MODEM_CMD_OK && status != MODEM_CMD_0) {\n\t\t\t\t\tif (WWMessageBox().Process(TXT_NO_FLOW_CONTROL_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t** Send the init string for no flow control\n\t\t\t*/\n\t\t\tif (ModemRegistry->Get_Modem_No_Flow_Control()) {\n\t\t\t\tstrcpy (&send_string[2], ModemRegistry->Get_Modem_No_Flow_Control());\n\t\t\t\tstatus = Send_Modem_Command (send_string, '\\r', buffer, 81, DEFAULT_TIMEOUT, 1);\n\t\t\t\tif (status != MODEM_CMD_OK && status != MODEM_CMD_0) {\n\t\t\t\t\tif (WWMessageBox().Process(TXT_NO_FLOW_CONTROL_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\n\t\t/*\n\t\t** Send the string for data compresseion\n\t\t*/\n\t\tif (settings->Compression){\n\n\t\t\tif (ModemRegistry->Get_Modem_Compression_Enable()) {\n\t\t\t\tstrcpy (&send_string[2], ModemRegistry->Get_Modem_Compression_Enable());\n\t\t\t\tSend_Modem_Command (send_string, '\\r', buffer, 81, DEFAULT_TIMEOUT, 1);\n\t\t\t\tif (status != MODEM_CMD_OK && status != MODEM_CMD_0) {\n\t\t\t\t\tif (WWMessageBox().Process(TXT_NO_COMPRESSION_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\n\t\t\tif (ModemRegistry->Get_Modem_Compression_Disable()) {\n\t\t\t\tstrcpy (&send_string[2], ModemRegistry->Get_Modem_Compression_Disable());\n\t\t\t\tSend_Modem_Command (send_string, '\\r', buffer, 81, DEFAULT_TIMEOUT, 1);\n\t\t\t\tif (status != MODEM_CMD_OK && status != MODEM_CMD_0) {\n\t\t\t\t\tif (WWMessageBox().Process(TXT_NO_COMPRESSION_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\n\t\t/*\n\t\t** Send the string for error correction\n\t\t*/\n\t\tif (settings->ErrorCorrection){\n\n\t\t\tif (ModemRegistry->Get_Modem_Error_Correction_Enable()) {\n\t\t\t\tstrcpy (&send_string[2], ModemRegistry->Get_Modem_Error_Correction_Enable());\n\t\t\t\tSend_Modem_Command (send_string, '\\r', buffer, 81, DEFAULT_TIMEOUT, 1);\n\t\t\t\tif (status != MODEM_CMD_OK && status != MODEM_CMD_0) {\n\t\t\t\t\tif (WWMessageBox().Process(TXT_NO_ERROR_CORRECTION_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\tif (ModemRegistry->Get_Modem_Error_Correction_Disable()) {\n\t\t\t\tstrcpy (&send_string[2], ModemRegistry->Get_Modem_Error_Correction_Disable());\n\t\t\t\tSend_Modem_Command (send_string, '\\r', buffer, 81, DEFAULT_TIMEOUT, 1);\n\t\t\t\tif (status != MODEM_CMD_OK && status != MODEM_CMD_0) {\n\t\t\t\t\tif (WWMessageBox().Process(TXT_NO_ERROR_CORRECTION_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n#endif\t//WIN32\n\n\n\t/*\n\t** We require that auto-answer be disabled so turn it off now.\n\t*/\n\tstatus = Send_Modem_Command( \"ATS0=0\", '\\r', buffer, 81, DEFAULT_TIMEOUT, INIT_COMMAND_RETRIES );\n\tif (status != MODEM_CMD_OK) {\n\t\tif (WWMessageBox().Process(TXT_ERROR_NO_DISABLE, TXT_IGNORE, TXT_CANCEL)) return( false );\n\t\terror_count++;\n\t}\n\n\t/*\n\t** If we had an unreasonable number of ignored errors then return failure\n\t*/\n\tif (error_count >= 3) {\n\t\tWWMessageBox().Process(TXT_ERROR_TOO_MANY, TXT_OK);\n\t\treturn (false);\n\t}\n\n\treturn( true );\n}\n\n\n/***************************************************************************\n * NullModemClass::Dial_Modem -- dials a number passed                     *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsettings\t\tptr to SerialSettings structure     \t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tstatus\t\tDialStatus\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/02/1995 DRD : Created.                                             *\n *   8/2/96      ST : Win32 support                                        *\n *=========================================================================*/\nDialStatusType NullModemClass::Dial_Modem( char *string, DialMethodType method, bool reconnect )\n{\n\t/*\n\t** Get the resolution factor\n\t*/\n//\tint factor = SeenBuff.Get_Width()/320;\n\n\t/*------------------------------------------------------------------------\n\tButton Enumerations\n\t------------------------------------------------------------------------*/\n\tenum {\n\t\tBUTTON_CANCEL = 100,\n\t};\n\n\t/*------------------------------------------------------------------------\n\tDialog variables\n\t------------------------------------------------------------------------*/\n\tbool process = true;\t\t\t\t\t\t// process while true\n#ifndef WIN32\n\tint status;\n#endif\t//WIN32\n\tint delay;\n\tDialStatusType dialstatus;\n\n\tint x,y,width,height;\t\t\t\t\t// dialog dimensions\n\tchar buffer[80*3];\n\n\n\t/*------------------------------------------------------------------------\n\tDetermine the dimensions of the text to be used for the dialog box.\n\tThese dimensions will control how the dialog box looks.\n\t------------------------------------------------------------------------*/\n\tif (reconnect) {\n\t\tstrcpy( buffer, Text_String( TXT_MODEM_CONNERR_REDIALING ) );\n\t} else {\n\t\tstrcpy( buffer, Text_String( TXT_DIALING ) );\n\t}\n\n\tFancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_TEXT);\n\tFormat_Window_String(buffer, SeenBuff.Get_Height(), width, height);\n\n\tint text_width = width;\n\twidth = max(width, 90 * RESFACTOR);\n\twidth += 40 * RESFACTOR;\n\theight += 60 * RESFACTOR;\n\n\tx = (SeenBuff.Get_Width() - width) / 2;\n\ty = (SeenBuff.Get_Height() - height) / 2;\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,\n\t\tx + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8 * RESFACTOR)) >> 1),\n\t\ty + height - (FontHeight + FontYSpacing + 2 * RESFACTOR) - 10 * RESFACTOR);\n\n\t/*------------------------------------------------------------------------\n\tInitialize\n\t------------------------------------------------------------------------*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*------------------------------------------------------------------------\n\tCreate the list\n\t------------------------------------------------------------------------*/\n\tCommands = &cancelbtn;\n\n\tCommands->Flag_List_To_Redraw();\n\n\t/*------------------------------------------------------------------------\n\tDraw the dialog\n\t------------------------------------------------------------------------*/\n\tHide_Mouse();\n\tif ( !reconnect ) {\n\t\tLoad_Title_Page(true);\n\t}\n\n\tDialog_Box(x, y, width, height);\n\tDraw_Caption(TXT_NONE, x, y, width);\n\n\tFancy_Text_Print(buffer, SeenBuff.Get_Width()/2 - text_width/2, y + 25 *RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT);\n\n\tCommands->Draw_All();\n\tShow_Mouse();\n\n\t/*\n\t** Start waiting for connection response\n\t*/\n#ifdef WIN32\n\tSerialPort->Set_Modem_Dial_Type((WinCommDialMethodType) method);\n\t/*\n\t** Clear out any old modem results that might be hanging around\n\t*/\n\tSerialPort->Get_Modem_Result(60, buffer, 81);\n\t/*\n\t** Dial that sucker\n\t*/\n\tSerialPort->Dial_Modem(string);\n\n#else\t//WIN32\n\tHMSetDialingMethod( Port, (int)method );\n\tstatus = HMDial( Port, string );\n\n#endif\t//WIN32\n\n\n\t/*\n\t** Sets up the ability to abort modem commands when any input is in the\n\t** Keyboard buffer.  This also calls the game CallBack().\n\t*/\n\tSetup_Abort_Modem();\n\n\t/*------------------------------------------------------------------------\n\tMain Processing Loop\n\t------------------------------------------------------------------------*/\n\tprocess = true;\n\tdelay = ModemWaitCarrier;\n\twhile (process) {\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tCommands->Draw_All();\n\t\t}\n\n\t\tdelay = SerialPort->Get_Modem_Result(delay, buffer, 81);\n#else\t//WIN32\n\t\tdelay = HMInputLine( Port, delay, buffer, 81 );\n#endif\t//WIN32\n\n\t\t/*.....................................................................\n\t\tProcess input\n\t\t.....................................................................*/\n\t\tswitch (Input) {\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tdialstatus = DIAL_CANCELED;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (process) {\n\t\t\tif ( strncmp( buffer, \"CON\", 3 ) == 0 ) {\n\t\t\t\tmemset (ModemRXString, 0, 80);\n\t\t\t\tstrncpy (ModemRXString, buffer, 79);\n\t\t\t\tdialstatus = DIAL_CONNECTED;\n\t\t\t\tprocess = false;\n\t\t\t} else if ( strncmp( buffer, \"BUSY\", 4 ) == 0 ) {\n\t\t\t\tdialstatus = DIAL_BUSY;\n\t\t\t\tprocess = false;\n\t\t\t} else if ( strncmp( buffer, \"NO C\", 4 ) == 0 ) {\n\t\t\t\tdialstatus = DIAL_NO_CARRIER;\n\t\t\t\tprocess = false;\n\t\t\t} else if ( strncmp( buffer, \"NO D\", 4 ) == 0 ) {\n\t\t\t\tdialstatus = DIAL_NO_DIAL_TONE;\n\t\t\t\tprocess = false;\n\t\t\t} else if ( strncmp( buffer, \"ERRO\", 4 ) == 0 ) {\n\t\t\t\tdialstatus = DIAL_ERROR;\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\tif (delay <= 0) {\n\t\t\tprocess = false;\n\t\t}\n\t}\n\n\tRemove_Abort_Modem();\n\n\treturn( dialstatus );\n\n}\t/* end of Dial_Modem */\n\n\n/***************************************************************************\n * NullModemClass::Answer_Modem -- waits for call and answers              *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\treconnect\twhether this is to reconnect\t\t     \t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tstatus\t\tDialStatus\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/02/1995 DRD : Created.                                             *\n *   8/2/96      ST : Added Win32 support                                  *\n *=========================================================================*/\nDialStatusType NullModemClass::Answer_Modem( bool reconnect )\n{\n\t/*\n\t** Get the resolution factor\n\t*/\n//\tint factor \t\t= (SeenBuff.Get_Width() == 320) ? 1 : 2;\n\n\t/*------------------------------------------------------------------------\n\tButton Enumerations\n\t------------------------------------------------------------------------*/\n\tenum {\n\t\tBUTTON_CANCEL = 100,\n\t};\n\n\t/*------------------------------------------------------------------------\n\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t------------------------------------------------------------------------*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*------------------------------------------------------------------------\n\tDialog variables\n\t------------------------------------------------------------------------*/\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n#ifndef WIN32\n\tint status;\n#endif\t//WIN32\n\tint delay;\n\tDialStatusType dialstatus;\n\tbool ring = false;\n\n\tint x,y,width,height;\t\t\t\t\t// dialog dimensions\n\tint text_width;\n\tchar text_buffer[80*3];\n\tchar comm_buffer[80*3];\n\n\t/*------------------------------------------------------------------------\n\tDetermine the dimensions of the text to be used for the dialog box.\n\tThese dimensions will control how the dialog box looks.\n\t------------------------------------------------------------------------*/\n\tif (reconnect) {\n\t\tstrcpy( text_buffer, Text_String( TXT_MODEM_CONNERR_WAITING ) );\n\t} else {\n\t\tstrcpy( text_buffer, Text_String( TXT_WAITING_FOR_CALL ) );\n\t}\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT);\n\tFormat_Window_String(text_buffer, SeenBuff.Get_Height(), width, height);\n\n\ttext_width = width;\n\twidth = max(width, 90 * RESFACTOR);\n\twidth += 40 * RESFACTOR;\n\theight += 60 * RESFACTOR;\n\n\tx = (SeenBuff.Get_Width() - width) / 2;\n\ty = (SeenBuff.Get_Height() - height) / 2;\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,\n\t\tx + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8 * RESFACTOR)) >> 1),\n\t\ty + height - (FontHeight + FontYSpacing + 2 * RESFACTOR) - 10 * RESFACTOR);\n\n\t/*------------------------------------------------------------------------\n\tInitialize\n\t------------------------------------------------------------------------*/\n\tSet_Logic_Page(SeenBuff);\n\tLoad_Title_Page(true);\n\n\tInput = KN_NONE;\n\n\t/*------------------------------------------------------------------------\n\tCreate the list\n\t------------------------------------------------------------------------*/\n\tCommands = &cancelbtn;\n\n\tCommands->Flag_List_To_Redraw();\n\n\t/*\n\t** Sets up the ability to abort modem commands when any input is in the\n\t** Keyboard buffer.  This also calls the game CallBack() and Input().\n\t*/\n\tSetup_Abort_Modem();\n\n\t/*------------------------------------------------------------------------\n\tMain Processing Loop\n\t------------------------------------------------------------------------*/\n\tprocess = true;\n\tdelay = 60000;\n\twhile (process) {\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay=REDRAW_ALL;\n\t\t}\n#endif\t//WIN32\n\n\t\t/*.....................................................................\n\t\tRefresh display if needed\n\t\t.....................................................................*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\t/*...............................................................\n\t\t\t\tRefresh the backdrop\n\t\t\t\t...............................................................*/\n\t\t\t\tif ( !reconnect ) {\n\t\t\t\t\tLoad_Title_Page(true);\n\t\t\t\t}\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDraw the background\n\t\t\t\t...............................................................*/\n\t\t\t\tDialog_Box(x, y, width, height);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDraw the labels\n\t\t\t\t...............................................................*/\n\t\t\t\tDraw_Caption(TXT_NONE, x, y, width);\n\n\t\t\t\tFancy_Text_Print(text_buffer, SeenBuff.Get_Width()/2 - text_width/2, y + 25 * RESFACTOR,\n\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT);\n\n\t\t\t\tCommands->Draw_All();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n#ifdef WIN32\n\t\tdelay = SerialPort->Get_Modem_Result(delay, comm_buffer, 81);\n#else\t//WIN32\n\t\tdelay = HMInputLine( Port, delay, comm_buffer, 81 );\n#endif\t//WIN32\n\n\n\t\t/*.....................................................................\n\t\tProcess input\n\t\t.....................................................................*/\n\t\tif (!Input) Input = Commands->Input();\n\t\tswitch (Input) {\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tdialstatus = DIAL_CANCELED;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (process) {\n\t\t\tif ( strncmp( comm_buffer, \"RING\", 4 ) == 0 ) {\n\n\t\t\t\tstrcpy( text_buffer, Text_String( TXT_ANSWERING ) );\n\n\t\t\t\tFancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_TEXT);\n\t\t\t\tFormat_Window_String(text_buffer, SeenBuff.Get_Height(), width, height);\n\n\t\t\t\ttext_width = width;\n\t\t\t\twidth = max(width, 90 * RESFACTOR);\n\t\t\t\twidth += 40 * RESFACTOR;\n\t\t\t\theight += 60 * RESFACTOR;\n\n\t\t\t\tx = (SeenBuff.Get_Width() - width) / 2;\n\t\t\t\ty = (SeenBuff.Get_Height() - height) / 2;\n\n#ifdef WIN32\n\t\t\t\tSerialPort->Write_To_Serial_Port ((unsigned char*)\"ATA\\r\", strlen(\"ATA\\r\"));\n#else\t//WIN32\n\t\t\t\tPortKillTime( Port, 100 );\n\t\t\t\tHMWaitForOK( 0, NULL );\n\t\t\t\tstatus = HMAnswer( Port );\n#endif\t//WIN32\n\n\t\t\t\tring = true;\n\t\t\t\tdelay = ModemWaitCarrier;\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t} else if ( strncmp( comm_buffer, \"CON\", 3 ) == 0 ) {\n\t\t\t\tmemset (ModemRXString, 0, 80);\n\t\t\t\tstrncpy (ModemRXString, comm_buffer, 79);\n\t\t\t\tdialstatus = DIAL_CONNECTED;\n\t\t\t\tprocess = false;\n\t\t\t} else if ( strncmp( comm_buffer, \"BUSY\", 4 ) == 0 ) {\n\t\t\t\tdialstatus = DIAL_BUSY;\n\t\t\t\tprocess = false;\n\t\t\t} else if ( strncmp( comm_buffer, \"NO C\", 4 ) == 0 ) {\n\t\t\t\tdialstatus = DIAL_NO_CARRIER;\n\t\t\t\tprocess = false;\n\t\t\t} else if ( strncmp( comm_buffer, \"ERRO\", 4 ) == 0 ) {\n\t\t\t\tdialstatus = DIAL_ERROR;\n\t\t\t\tWWMessageBox().Process(TXT_ERROR_ERROR, TXT_OK);\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n#ifdef WIN32\n\n\t\tif (delay <= 0) {\n\t\t\tif (ring) {\n\t\t\t\tif (SerialPort->Get_Modem_Status() & CD_SET) {\n\t\t\t\t\tsprintf(ModemRXString, \"%s\", \"Connected\");\n\t\t\t\t\tdialstatus = DIAL_CONNECTED;\n\t\t\t\t} else {\n\t\t\t\t\tdialstatus = DIAL_ERROR;\n\t\t\t\t\tWWMessageBox().Process(TXT_ERROR_TIMEOUT, TXT_OK);\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t} else {\n\t\t\t\tdelay = 60000;\n\t\t\t}\n\t\t}\n#else\t//WIN32\n\n\t\tif (delay <= 0) {\n\t\t\tif (ring) {\n\t\t\t\tprocess = false;\n\t\t\t} else {\n\t\t\t\tdelay = 60000;\n\t\t\t}\n\t\t}\n#endif\t//WIN32\n\n\t}\n\n\tRemove_Abort_Modem();\n\n\treturn( dialstatus );\n\n}\t/* end of Answer_Modem */\n\n\n/***************************************************************************\n * NullModemClass::Hangup_Modem -- hangs up the modem                      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tstatus\t\tsuccessful or not\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/02/1995 DRD : Created.                                             *\n *   8/2/96         : Added Win32 support                                  *\n *=========================================================================*/\nbool NullModemClass::Hangup_Modem( void )\n{\n\tint status;\n\tint delay;\n\tchar buffer[81];\n\tchar escape[4];\n\n\t/*\n\t**\tTurn modem servicing off in the callback routine.\n\t*/\n\tSession.ModemService = false;\n\n\tstatus = Send_Modem_Command( \"AT\", '\\r', buffer, 81, DEFAULT_TIMEOUT, 1 );\n\n\tif (status == MODEM_CMD_OK) {\n\t\tSession.ModemService = true;\n\t\treturn( true );\n\t}\n\n\t/*\n\t** Toggle DTR low then high\n\t*/\n#ifdef WIN32\n\tSerialPort->Set_Serial_DTR(FALSE);\n\tDelay(3200/60);\n\tSerialPort->Set_Serial_DTR(TRUE);\n#else\t//WIN32\n\n\tSetDtr( Port, 0 );\n\tPortKillTime( Port, 3200 );\n\tSetDtr( Port, 1 );\n#endif\t//WIN32\n\n\tstatus = Send_Modem_Command( \"AT\", '\\r', buffer, 81, DEFAULT_TIMEOUT, 1 );\n\n\tif (status == MODEM_CMD_OK) {\n\t\tSession.ModemService = true;\n\t\treturn( true );\n\t}\n\n\tdelay = ModemGuardTime;\n\twhile ( delay > 0 ) {\n#ifdef WIN32\n\t\tdelay = SerialPort->Get_Modem_Result(delay, buffer, 81);\n#else\t//WIN32\n\t\tdelay = HMInputLine( Port, delay, buffer, 81 );\n#endif\t//WIN32\n\t}\n\n\t/*\n\t** Send modem break commmand\n\t*/\n\tescape[0] = ModemEscapeCode;\n\tescape[1] = ModemEscapeCode;\n\tescape[2] = ModemEscapeCode;\n\tescape[3] = 0;\n\n#ifdef WIN32\n\tSerialPort->Write_To_Serial_Port((unsigned char*)escape, 3);\n#else\t//WIN32\n\tstatus = HMSendStringNoWait( Port, escape, -1 );\n#endif\t//WIN32\n\n\n\tdelay = ModemGuardTime;\n\twhile ( delay > 0 ) {\n#ifdef WIN32\n\t\tdelay = SerialPort->Get_Modem_Result(delay, buffer, 81);\n#else\t//WIN32\n\t\tdelay = HMInputLine( Port, delay, buffer, 81 );\n#endif\t//WIN32\n\n\t\tif ( strncmp( buffer, \"OK\", 2 ) == 0 ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t** Send the hangup command\n\t*/\n\tstatus = Send_Modem_Command( \"ATH\", '\\r', buffer, 81, ModemHangupDelay, 1 );\n\n\tif (status == MODEM_CMD_OK) {\n\t} else {\n\t\tSession.ModemService = true;\n\t\treturn( false );\n\t}\n\n\t/*\n\t** Send spurious ATZ command for no apparent reason\n\t*/\n\tstatus = Send_Modem_Command( \"ATZ\", '\\r', buffer, 81, 5000, 1 );\n\n\tif (status != MODEM_CMD_OK) {\n\t\tSession.ModemService = true;\n\t\treturn( false );\n\t}\n\n\tSession.ModemService = true;\n\treturn( true );\n\n}\t/* end of Hangup_Modem */\n\n\n/***********************************************************************************************\n * NMC::Setup_Modem_Echo -- Sets the echo callback function pointer                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Ptr to callback function                                                          *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 12:48PM ST : Documented and added WIn32 support                                   *\n *=============================================================================================*/\nvoid NullModemClass::Setup_Modem_Echo( void ( *func )( char c) )\n{\n#ifdef WIN32\n\tSerialPort->Set_Echo_Function(func);\n#else\t//WIN32\n\tHMSetUpEchoRoutine( func );\n#endif\t//WIN32\n\n}\t/* end of Setup_Modem_Echo */\n\n\n/***********************************************************************************************\n * NMC::Remove_Modem_Echo -- Set the echo function callback pointer to null                    *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 12:50PM ST : Documented / Win32 support added                                     *\n *=============================================================================================*/\nvoid NullModemClass::Remove_Modem_Echo( void )\n{\n//\tSmart_Printf( \"Remove Echo modem code\\n\" );\n\tHMSetUpEchoRoutine( NULL );\n\n}\t/* end of Remove_Modem_Echo */\n\n\n\n/***********************************************************************************************\n * NMC::Print_EchoBuf -- Print out the contents of the echo buffer                             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 12:51PM ST : Documented                                                           *\n *=============================================================================================*/\nvoid NullModemClass::Print_EchoBuf( void )\n{\n\tfor (int i = 0; i < strlen(NullModem.EchoBuf); i++) {\n\t\tif (NullModem.EchoBuf[i] == '\\r') {\n\t\t\tNullModem.EchoBuf[i] = 1;\n\t\t} else {\n\t\t\tif (NullModem.EchoBuf[i] == '\\n') {\n\t\t\t\tNullModem.EchoBuf[i] = 2;\n\t\t\t}\n\t\t}\n\t}\n//\tSmart_Printf( \"Echo buffer length %d (%s)\\n\", NullModem.EchoCount, NullModem.EchoBuf );\n}\n\n\n\n/***********************************************************************************************\n * NMC::Reset_EchoBuf -- Empties the echo buffer                                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 12:51PM ST : Documented                                                           *\n *=============================================================================================*/\nvoid NullModemClass::Reset_EchoBuf( void )\n{\n\t*EchoBuf = 0;\n\tEchoCount = 0;\n}\n\n\n/***********************************************************************************************\n * NMC::Abort_Modem -- Checks for user input so that modem operations can be aborted           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   ASUSERABORT if abort key pressed. ASSUCESS otherwise.                             *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 12:52PM ST : Documented                                                           *\n *=============================================================================================*/\nint NullModemClass::Abort_Modem( PORT * )\n{\n\t/*\n\t** Button Enumerations\n\t*/\n\tenum {\n\t\tBUTTON_CANCEL = 100,\n\t};\n\n\t/*\n\t** Invoke game callback\n\t*/\n\tCall_Back();\n\n\t/*\n\t** Get user input\n\t*/\n\tInput = Commands->Input();\n\n\tswitch ( Input ) {\n\t\tcase (KN_ESC):\n\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\treturn( ASUSERABORT );\n\t}\n\n\treturn( ASSUCCESS );\n\n}\t/* end of Abort_Modem */\n\n\n/***********************************************************************************************\n * NMC::Setup_Abort_Modem -- sets the modem abort function pointer                             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 2:59PM ST : Documented / Win32 support added                                      *\n *=============================================================================================*/\nvoid NullModemClass::Setup_Abort_Modem( void )\n{\n\n#ifdef WIN32\n\n\tSerialPort->Set_Abort_Function((int(*)(void))Abort_Modem);\n\n#else\t//WIN32\n\t/*\n\t** save off original abort modem function to later restore\n\t*/\n\tOrigAbortModemFunc = _AbortModemFunctionPtr;\n\tHMSetUpAbortKey( ESC );\n\tSetAbortModemFunctionPtr( Abort_Modem );\n#endif\t//WIN32\n\n}\t/* end of Setup_Abort_Modem */\n\n\n/***********************************************************************************************\n * NMC::Remove_Abort_Modem -- Removes the modem abort function pointer                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 3:01PM ST : Documented / Win32 support added                                      *\n *=============================================================================================*/\nvoid NullModemClass::Remove_Abort_Modem( void )\n{\n\n#ifdef WIN32\n\tSerialPort->Set_Abort_Function(NULL);\n\n#else\t//WIN32\n\n\tHMSetUpAbortKey( NOKEY );\n\n\t/*\n\t** Restore the original abort modem function\n\t*/\n\t_AbortModemFunctionPtr = OrigAbortModemFunc;\n#endif\t//WIN32\n\n}\t/* end of Remove_Abort_Modem */\n\n\n\n/***********************************************************************************************\n * NMC::Change_IRQ_Priority -- Increases the priority of the serial interrupt                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Interrupt request number                                                          *\n *                                                                                             *\n * OUTPUT:   ASSUCCESS if changed                                                              *\n *                                                                                             *\n * WARNINGS: The Win32 version of this function does nothing.                                  *\n *           Priorities are controlled by windoze                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 3:03PM ST : Documented / Win32 support added                                      *\n *=============================================================================================*/\nint NullModemClass::Change_IRQ_Priority( int irq )\n{\n#ifdef WIN32\n\n\tirq = irq;\n\treturn ( ASSUCCESS );\n\n#else\t//WIN32\n\n\tif (irq != OldIRQPri) {\n\t\tOldIRQPri = irq;\n\t\treturn( Change8259Priority( irq ) );\n\t} else {\n\t\treturn( ASSUCCESS );\n\t}\n\n#endif\t//WIN32\n\n}\t/* end of Change_IRQ_Priority */\n\n\n\n/***********************************************************************************************\n * NMC::Get_Modem_Status -- returns status of modem control bits                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Modem status                                                                      *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 3:06PM ST : Documented / Win32 support added                                      *\n *=============================================================================================*/\nint NullModemClass::Get_Modem_Status( void )\n{\n\tint modemstatus;\n\tint status;\n\tchar buffer[81];\n\n#ifdef WIN32\n\tmodemstatus = SerialPort->Get_Modem_Status();\n#else\t//WIN32\n\tmodemstatus = GetModemStatus( Port );\n#endif\t//WIN32\n\n\tstatus = Send_Modem_Command( \"AT\", '\\r', buffer, 81, DEFAULT_TIMEOUT, 1 );\n\n\tif (status == MODEM_CMD_OK) {\n\t\tmodemstatus &= (~CD_SET);\n\t}\n\n\treturn( modemstatus );\n\n}\t/* end of Get_Modem_Status */\n\n\n/***********************************************************************************************\n * NMC::Send_Modem_Command -- Sends an 'AT' command to the modem and gets the response         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    command to send to modem. e.g. 'ATZ'                                              *\n *           terminator byte for command string                                                *\n *           buffer to put modem response into                                                 *\n *           length of above buffer                                                            *\n *           delay to wait for response                                                        *\n *           number of times to retry when modem doesnt respond                                *\n *                                                                                             *\n * OUTPUT:   input delay less the time it took the modem to respond                            *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 3:09PM ST : Documented / Win32 support added                                      *\n *=============================================================================================*/\nint NullModemClass::Send_Modem_Command( char *command, char terminator, char *buffer, int buflen, int delay, int retries )\n{\n\n#ifdef WIN32\n\treturn (SerialPort->Send_Command_To_Modem(command, terminator, buffer, buflen, delay, retries));\n#else\t//WIN32\n\n\tint status, tmpdelay, retry;\n\tchar tempbuf[81];\n\n\n\t*buffer = 0;\n\n\tfor ( retry = 0; retry < retries; retry++ ) {\n\n\t\tPortKillTime( Port, 100 );\n\n\t\tstatus = HMSendStringNoWait( Port, command, terminator );\n\n\n\t\tif (status < ASSUCCESS) {\n\t\t\treturn( status );\n\t\t}\n\n\t\ttmpdelay = delay;\n\t\twhile ( tmpdelay > 0 ) {\n\n\t\t\ttmpdelay = HMInputLine( Port, tmpdelay, tempbuf, 81 );\n\n\t\t\tif ( strcmp( tempbuf, \"OK\" ) == 0 ) {\n\t\t\t\treturn( MODEM_CMD_OK );\n\t\t\t} else if ( strcmp( tempbuf, \"0\" ) == 0 ) {\n\t\t\t\treturn( MODEM_CMD_0 );\n\t\t\t} else if ( strcmp( tempbuf, \"ERROR\" ) == 0 ) {\n\t\t\t\treturn( MODEM_CMD_ERROR );\n\t\t\t} else if ( tempbuf[0] != 0 ) {\n\t\t\t\tstrncpy( buffer, tempbuf, buflen );\n\t\t\t}\n\t\t}\n\n\t\tPortKillTime( Port, 100 );\n\n\t\t/*\n\t\t**\tSend and extra return to help clear out any problems with the modem (if any).\n\t\t*/\n\t\tHMWaitForOK( 300, NULL );\n\t\tstatus = HMSendString( Port, \"\" );\n\t\tHMWaitForOK( 0, NULL );\n\t}\n\n\treturn( tmpdelay );\n\n#endif\t//WIN32\n}\n\n\n/***********************************************************************************************\n * NMC::Verify_And_Convert_To_Int -- converts a text string of numbers to an int               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to buffer                                                                     *\n *                                                                                             *\n * OUTPUT:   value of text number in buffer                                                    *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 3:13PM ST : Documented                                                            *\n *=============================================================================================*/\nint NullModemClass::Verify_And_Convert_To_Int( char *buffer )\n{\n\tint value = 0;\n\tint len = strlen(buffer);\n\n\n\tfor (int i = 0; i < len; i++) {\n\t\tif ( !isdigit( *(buffer + i) ) ) {\n\t\t\tvalue = -1;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (value == 0) {\n\t\tvalue = atoi( buffer );\n\t}\n\n\treturn( value );\n\n}\t/* end of Verify_And_Convert_To_Int */\n\n/*************************** end of nullmgr.cpp ****************************/\n\n"
  },
  {
    "path": "CODE/NULLMGR.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/NULLMGR.H 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : CONNECT.H                                *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 3, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This is the Connection Manager for a NULL-Modem connection.\t\t\t\t\t*\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef NULLMODEM_H\n#define NULLMODEM_H\n\n\n/*\n********************************* Includes **********************************\n*/\n#include \"nullconn.h\"\n#include \"connmgr.h\"\n#include \"commlib.h\"\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass NullModemClass : public ConnManClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\tenum SendModemEnum {\n\t\t\tMODEM_CMD_TIMEOUT = 0,\n\t\t\tMODEM_CMD_OK,\n\t\t\tMODEM_CMD_0,\n\t\t\tMODEM_CMD_ERROR\n\t\t};\n\n\t\tchar *BuildBuf;\n\t\tint MaxLen;\n\n\t\tchar *EchoBuf;\n\t\tint EchoSize;\n\t\tint EchoCount;\n\n\t\tint OldIRQPri;\n\n\t\tint ModemVerboseOn;\n\t\tint ModemEchoOn;\n\t\tint ModemWaitCarrier;\n\t\tint ModemCarrierDetect;\n\t\tint ModemCarrierLoss;\n\t\tint ModemHangupDelay;\n\t\tint ModemGuardTime;\n\t\tchar ModemEscapeCode;\n\n\t\tstatic void (*OrigAbortModemFunc)(int);\n\t\tstatic KeyNumType Input;\n\t\tstatic GadgetClass *Commands;\t\t\t\t\t\t\t// button list\n\n\t\t/*\n\t\t**\tConstructor/destructor.\n\t\t*/\n\t\tNullModemClass (int numsend, int numreceive, int maxlen, unsigned short magicnum);\n\t\tvirtual ~NullModemClass ();\n\n\t\t/*\n\t\t**\tThis is the main initialization routine.\n\t\t*/\n\t\tint Init( int port, int irq, char *dev_name, int baud, char parity, int wordlength, int stopbits, int flowcontrol );\n\t\tint Delete_Connection( void );\n\t\tvirtual int Num_Connections(void);\n\t\tvirtual int Connection_ID(int ) {return (0);}\n\t\tvirtual int Connection_Index(int ) {return (0);}\n\t\tint Init_Send_Queue( void );\n\t\tvoid Shutdown( void );\n\n\t\tvirtual void Set_Timing (unsigned long retrydelta,\n\t\t\tunsigned long maxretries, unsigned long timeout);\n\n\t\t/*\n\t\t**\tThis is how the application sends & receives messages.\n\t\t*/\n\t\tint Send_Message (void *buf, int buflen, int ack_req = 1);\n\t\tint Get_Message (void *buf, int *buflen);\n\n\t\t/*\n\t\t** These are for compatibility\n\t\t*/\n\t\tvirtual int Send_Private_Message (void *buf, int buflen,\n\t\t\tint ack_req = 1, int = CONNECTION_NONE)\n\t\t\t{return (Send_Message(buf,buflen,ack_req));}\n\t\tvirtual int Get_Private_Message (void *buf, int *buflen, int *)\n\t\t\t{return (Get_Message(buf,buflen));}\n\n\t\t/*\n\t\t**\tThe main polling routine; should be called as often as possible.\n\t\t*/\n\t\tvirtual int Service (void);\n\n\t\t/*\n\t\t**\tQueue utility routines.  The application can determine how many\n\t\t**\tmessages are in the send/receive queues, and the queue's average\n\t\t**\tresponse time (in clock ticks).\n\t\t*/\n\t\tint Num_Send(void);\n\t\tint Num_Receive(void);\n\t\tvirtual unsigned long Response_Time(void);\n\t\tvirtual void Reset_Response_Time(void);\n\t\tvoid * Oldest_Send(void);\n\t\tvirtual void Configure_Debug(int index, int type_offset, int type_size,\n\t\t\tchar **names, int namestart, int namecount);\n#ifdef CHEAT_KEYS\n\t\tvirtual void Mono_Debug_Print(int index, int refresh = 0);\n#endif\n\n\t\t/*\n\t\t** These are for compatibility\n\t\t*/\n\t\tvirtual int Global_Num_Send(void) {return (Num_Send());}\n\t\tvirtual int Global_Num_Receive(void) {return (Num_Receive());}\n\t\tvirtual int Private_Num_Send(int = CONNECTION_NONE)\n\t\t\t{return (Num_Send());}\n\t\tvirtual int Private_Num_Receive(int = CONNECTION_NONE)\n\t\t\t{return (Num_Receive());}\n\n\t\tDetectPortType Detect_Port( SerialSettingsType *settings );\n\t\tint Detect_Modem( SerialSettingsType *settings, int reconnect = 0 );\n\t\tDialStatusType Dial_Modem(char *string, DialMethodType method, int reconnect = 0);\n\t\tDialStatusType Answer_Modem(int reconnect = 0);\n\t\tint Hangup_Modem(void);\n\t\tvoid Setup_Modem_Echo(void (*func)(char c));\n\t\tvoid Remove_Modem_Echo(void);\n\t\tvoid Print_EchoBuf(void);\n\t\tvoid Reset_EchoBuf(void);\n\t\tstatic int Abort_Modem(PORT *);\n\t\tvoid Setup_Abort_Modem(void);\n\t\tvoid Remove_Abort_Modem(void);\n\n\t\tint Change_IRQ_Priority(int irq);\n\t\tint Get_Modem_Status(void);\n\t\tint Send_Modem_Command( char *command, char terminator, char *buffer, int buflen, int delay, int retries );\n\t\tint Verify_And_Convert_To_Int( char *buffer );\n\n\t/*\n\t**\tPrivate Interface.\n\t*/\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is a pointer to the NULL-Modem Connection object.\n\t\t*/\n\t\tNullModemConnClass *Connection;\n\t\tint NumConnections;\t\t\t\t\t\t// # connection objects in use\n\n#ifdef WIN32\n\t\t/*\n\t\t** This is the Win95 port handle\n\t\t*/\n\t\tHANDLE\tPortHandle;\n#else\t//WIN32\n\t\t/*\n\t\t**\tThis is the Greenleaf port handle.\n\t\t*/\n\t\tPORT *Port;\n#endif\t//WIN32\n\n\t\tint NumSend;\n\t\tint NumReceive;\n\t\tunsigned short MagicNum;\n\n\t\t/*\n\t\t**\tThis is the staging buffer for parsing incoming packets.\n\t\t**\tRXSize is the allocated size of the RX buffer.\n\t\t**\tRXCount is the # of characters we currently have in our buffer.\n\t\t*/\n\t\tchar *RXBuf;\n\t\tint RXSize;\n\t\tint RXCount;\n\n\t\t/*.....................................................................\n\t\tTiming parameters for all connections\n\t\t.....................................................................*/\n\t\tunsigned long RetryDelta;\n\t\tunsigned long MaxRetries;\n\t\tunsigned long Timeout;\n\n\t\t/*\n\t\t**\tVarious Statistics\n\t\t*/\n\t\tint SendOverflows;\n\t\tint ReceiveOverflows;\n\t\tint CRCErrors;\n};\n\n#endif\n\n/*************************** end of nullmgr.h ******************************/\n"
  },
  {
    "path": "CODE/NUMBER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n\n\n\n\n/*\n**\tMethod to raise a number by an arbitrary whole exponent and then\n**\tmodulo the result by another number.\n*/\nunsigned long Power_Mod(unsigned long root, unsigned long exponent, unsigned long mod)\n{\n\tunsigned long s = 1;\n\tunsigned long t = root;\n\tunsigned long u = exponent;\n\n\twhile (u) {\n\t\tif (u & 1) {\n\t\t\ts = (s*t) % mod;\n\t\t}\n\t\tu >>= 1;\n\t\tt = (t*t) % mod;\n\t}\n\treturn(s);\n}\n\n\n/*\n**\tThis routine finds the greatest common divisor common\n**\tto two specified numbers.\n*/\nint Greatest_Common_Divisor(int x, int y)\n{\n\n\tif (x < 0) {\n\t\tx = -x;\n\t}\n\tif (y < 0) {\n\t\ty = -y;\n\t}\n\tif (x + y == 0) {\n\t\treturn(0);\t\t\t// This is an error condition.\n\t}\n\n\tint greatest = y;\n\twhile (x > 0) {\n\t\t\tgreatest = x;\n\t\t\tx = y % x;\n\t\t\ty = greatest;\n\t}\n\treturn(g);\n}\n\n\n/*\n**\tComputes the greatest common divisor for a vector\n**\tof integers.\n*/\nint Grestest_Common_Divisor(int count, int * data)\n{\n\tif (count < 1) {\n\t\treturn(0);\n\t}\n\n\tgreatest = data[0];\n\tfor (int i = 1; i < count; i++) {\n\t\tgreatest = Greatest_Common_Divisor(greatest, data[i]);\n\t\tif (greatest == 1) {\n\t\t\treturn(1);\n\t\t}\n\t}\n\treturn(greatest);\n}"
  },
  {
    "path": "CODE/OBJECT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/OBJECT.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OBJECT.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 29, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 6, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ObjectClass::AI -- Handles generic object AI processing.                                  *\n *   ObjectClass::Active_Click_With -- Dispatches action on the object specified.              *\n *   ObjectClass::Active_Click_With -- Dispatches action on the specified cell.                *\n *   ObjectClass::Attach_Trigger -- Attach specified trigger to object.                        *\n *   ObjectClass::Can_Demolish -- Queries whether this object can be sold back.                *\n *   ObjectClass::Can_Player_Fire -- Can the player give this object an attack mission?        *\n *   ObjectClass::Can_Player_Move -- Can the player give this object a movement mission?       *\n *   ObjectClass::Can_Repair -- Queries whether this object can be repaired.                   *\n *   ObjectClass::Catch_Fire -- Called when animation is attached to this object.              *\n *   ObjectClass::Center_Coord -- Fetches the center coordinate for the object.                *\n *   ObjectClass::Clicked_As_Target -- Triggers target selection animation.                    *\n *   ObjectClass::Debug_Dump -- Displays status of the object class to the mono monitor.       *\n *   ObjectClass::Detach -- Detach the specified target from this object.                      *\n *   ObjectClass::Detach_All -- Removes the object from all tracking systems.                  *\n *   ObjectClass::Do_Shimmer -- Shimmers this object if it is cloaked.                         *\n *   ObjectClass::Docking_Coord -- Fetches the coordinate to dock at this object.              *\n *   ObjectClass::Exit_Coord -- Return with the exit coordinate for this object.               *\n *   ObjectClass::Exit_Object -- Causes the specified object to leave this object.             *\n *   ObjectClass::Fire_Coord -- Fetches the coordinate a projectile will launch from.          *\n *   ObjectClass::Fire_Out -- Informs object that attached animation has finished.             *\n *   ObjectClass::Get_Mission -- Fetches the current mission of this object.                   *\n *   ObjectClass::Get_Ownable -- Fetches the house owner legality options for this object.     *\n *   ObjectClass::Hidden -- Called when this object becomes hidden from the player.            *\n *   ObjectClass::In_Range -- Determines if the coordinate is within weapon range.             *\n *   ObjectClass::In_Which_Layer -- Fetches what layer this object is located in.              *\n *   ObjectClass::Init -- Initializes the basic object system.                                 *\n *   ObjectClass::Limbo -- Brings the object into a state of limbo.                            *\n *   ObjectClass::Look -- Called when this object needs to reveal terrain.                     *\n *   ObjectClass::Mark -- Handles basic marking logic.                                         *\n *   ObjectClass::Mark_For_Redraw -- Marks object and system for redraw.                       *\n *   ObjectClass::Move -- Moves (by force) the object in the desired direction.                *\n *   ObjectClass::Name -- Fetches the identification name of this object.                      *\n *   ObjectClass::ObjectClass -- Default constructor for objects.                              *\n *   ObjectClass::Paradrop -- Unlimbos object in paradrop mode.                                *\n *   ObjectClass::Passive_Click_With -- Right mouse button click process.                      *\n *   ObjectClass::Receive_Message -- Processes an incoming radio message.                      *\n *   ObjectClass::Record_The_Kill -- Records this object as killed by the specified object.    *\n *   ObjectClass::Render -- Displays the object onto the map.                                  *\n *   ObjectClass::Render_Coord -- Fetches the coordinate to draw this object at.               *\n *   ObjectClass::Repair -- Handles object repair control.                                     *\n *   ObjectClass::Revealed -- Reveals this object to the house specified.                      *\n *   ObjectClass::Scatter -- Tries to scatter this object.                                     *\n *   ObjectClass::Select -- Try to make this object the \"selected\" object.                     *\n *   ObjectClass::Sell_Back -- Sells the object -- if possible.                                *\n *   ObjectClass::Sort_Y -- Returns the coordinate used for display order sorting.             *\n *   ObjectClass::Take_Damage -- Applies damage to the object.                                 *\n *   ObjectClass::Target_Coord -- Fetches the coordinate if this object is a target.           *\n *   ObjectClass::Unlimbo -- Brings the object into the game system.                           *\n *   ObjectClass::Unselect -- This will un-select the object if it was selected.               *\n *   ObjectClass::Value -- Fetches the target value of this object.                            *\n *   ObjectClass::Weapon_Range -- Returns the weapon range for the weapon specified.           *\n *   ObjectClass::What_Action -- Determines what action to perform on specified object.        *\n *   ObjectClass::What_Action -- Returns with the action to perform for this object.           *\n *   ObjectTypeClass::Cost_Of -- Returns the cost to buy this unit.                            *\n *   ObjectTypeClass::Dimensions -- Gets the dimensions of the object in pixels.               *\n *   ObjectTypeClass::Get_Cameo_Data -- Fetches pointer to cameo data for this object type.    *\n *   ObjectTypeClass::Max_Pips -- Fetches the maximum pips allowed for this object.            *\n *   ObjectTypeClass::ObjectTypeClass -- Normal constructor for object type class objects.     *\n *   ObjectTypeClass::Occupy_List -- Returns with simple occupation list for object.           *\n *   ObjectTypeClass::One_Time -- Handles one time processing for object types.                *\n *   ObjectTypeClass::Overlap_List -- Returns a pointer to a simple overlap list.              *\n *   ObjectTypeClass::Time_To_Build -- Fetches the time to construct this object.              *\n *   ObjectTypeClass::Who_Can_Build_Me -- Determine what building can build this object type.  *\n *   ObjectTypeClass::Who_Can_Build_Me -- Finds the factory building that can build this object*\n *   ObjectClass::Get_Image_Data -- Fetches the image data to use for this object.             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n/*\n**\tSelected objects have a special marking box around them. This is the shapes that are\n**\tused for this purpose.\n*/\nvoid const * ObjectTypeClass::SelectShapes = 0;\n\nvoid const * ObjectTypeClass::PipShapes = 0;\n\n\n/***********************************************************************************************\n * ObjectClass::ObjectClass -- Default constructor for objects.                                *\n *                                                                                             *\n *    This is the default constructor for objects. It is called as an inherent part of the     *\n *    construction process for all the normal game objects instantiated. It serves merely to   *\n *    initialize the object values to a common (default) state.                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Objects always start in a state of limbo. They must be Unlimbo()ed before they  *\n *             can be used.                                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass::ObjectClass(RTTIType rtti, int id) :\n\tAbstractClass(rtti, id),\n\tIsDown(false),\n\tIsToDamage(false),\n\tIsToDisplay(false),\n\tIsInLimbo(true),\n\tIsSelected(false),\n\tIsAnimAttached(false),\n\tIsFalling(false),\n\tRiser(0),\n\tNext(0),\n\tTrigger(NULL),\n\tStrength(255)\n{\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Get_Image_Data -- Fetches the image data to use for this object.               *\n *                                                                                             *\n *    This routine will return with a pointer to the image data that should be used when       *\n *    this object is drawn.                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the shape data for this object.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid const * ObjectClass::Get_Image_Data(void) const\n{\n\treturn(Class_Of().Get_Image_Data());\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Name -- Fetches the identification name of this object.                        *\n *                                                                                             *\n *    This routine will return a pointer to the identifier name for this object. This name     *\n *    is usually short and is used in the INI files to identify this object.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the text identifier name of this object.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * ObjectClass::Name(void) const\n{\n\treturn(Class_Of().Name());\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Exit_Coord -- Return with the exit coordinate for this object.                 *\n *                                                                                             *\n *    Ths exit coordinate is the location that a piggy back or newly produced object will      *\n *    appear at when it exits this object. Transports and factory buildings will utilize this  *\n *    routine.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate that an object will appear at when exiting this        *\n *          object.                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE ObjectClass::Exit_Coord(void) const\n{\n\treturn(Center_Coord());\n}\n\n\n/***********************************************************************************************\n * ObjectClass::AI -- Handles generic object AI processing.                                    *\n *                                                                                             *\n *    This routine is used to handle the AI processing that occurs for all object types.       *\n *    Typically, this isn't much, but there is the concept of falling that all objects can     *\n *    be subjected to (e.g., grenades).                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/07/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::AI(void)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\t/*\n\t**\tFalling logic is handled here.\n\t*/\n\tif (IsFalling) {\n\t\tLayerType layer = In_Which_Layer();\n\n\t\tHeight += Riser;\n\t\tif (Height <= 0) {\n\t\t\tHeight = 0;\n\t\t\tIsFalling = false;\n\t\t\tPer_Cell_Process(PCP_END);\n\n\t\t\tShorten_Attached_Anims(this);\n\t\t}\n\t\tif (IsAnimAttached) {\n\t\t\tRiser -= 1;\n\t\t\tRiser = max(Riser, -3);\n\t\t} else {\n\t\t\tRiser -= Rule.Gravity;\n//\t\t\tRiser -= GRAVITY;\n\t\t\tRiser = max(Riser, -100);\n\t\t}\n\n\t\tif (layer != In_Which_Layer()) {\n\t\t\tMap.Remove(this, layer);\n\t\t\tMap.Submit(this, In_Which_Layer());\n\n\t\t\tif (Class_Of().IsFootprint) {\n\t\t\t\tif (In_Which_Layer() == LAYER_GROUND) {\n\t\t\t\t\tMap.Place_Down(Coord_Cell(Center_Coord()), this);\n\t\t\t\t} else {\n\t\t\t\t\tMap.Pick_Up(Coord_Cell(Center_Coord()), this);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * ObjectClass::What_Action -- Determines what action to perform on specified object.          *\n *                                                                                             *\n *    This routine will return that action that this object could perform if the mouse were    *\n *    clicked over the object specified.                                                       *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object to check this object against when determining    *\n *                      the action to perform.                                                 *\n *                                                                                             *\n * OUTPUT:  It returns that action that will be performed if the mouse were clicked over the   *\n *          object. Since non-derived objects cannot do anything, and cannot even be           *\n *          instantiated, this routine will always return ACTION_NONE.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType ObjectClass::What_Action(ObjectClass const *) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(ACTION_NONE);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::What_Action -- Returns with the action to perform for this object.             *\n *                                                                                             *\n *    This routine is called when information on a potential action if the mouse were clicked  *\n *    on the cell specified. This routine merely serves as a virtual placeholder so that       *\n *    object types that can actually perform some action will override this routine to provide *\n *    true functionality.                                                                      *\n *                                                                                             *\n * INPUT:   cell  -- The cell that the mouse is over and might be clicked on.                  *\n *                                                                                             *\n * OUTPUT:  Returns with the action that this object would try to perform if the mouse were    *\n *          clicked. Since objects at this level have no ability to do anything, this routine  *\n *          will always returns ACTION_NONE unless it is overridden.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType ObjectClass::What_Action(CELL) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(ACTION_NONE);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::In_Which_Layer -- Fetches what layer this object is located in.                *\n *                                                                                             *\n *    The default layer for object location is the LAYER_GROUND. Aircraft will override this   *\n *    routine and make adjustments as necessary according to the aircraft's altitude.          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the layer that this object is located in.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLayerType ObjectClass::In_Which_Layer(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tif (Height < (FLIGHT_LEVEL - (FLIGHT_LEVEL/3))) {\n\t\treturn(LAYER_GROUND);\n\t}\n\treturn(LAYER_TOP);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Get_Ownable -- Fetches the house owner legality options for this object.       *\n *                                                                                             *\n *    This routine will return the ownable bits for this object. Objects at this level can't   *\n *    really be owned by anyone, but return the full spectrum of legality just to be safe.     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the ownable flags (as a combined bitfield) for this object.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ObjectClass::Get_Ownable(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(HOUSEF_ALLIES | HOUSEF_SOVIET | HOUSEF_OTHERS);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Can_Repair -- Queries whether this object can be repaired.                     *\n *                                                                                             *\n *    Most objects cannot be repaired. This routine defaults to returning \"false\", but is      *\n *    overridden by derived functions defined by object types that can support repair.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Can this object be repaired?                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Can_Repair(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Can_Demolish -- Queries whether this object can be sold back.                  *\n *                                                                                             *\n *    This routine is used to determine if this object can be sold. Most objects cannot be     *\n *    but for those objects that can, this routine will be overridden as necessary.            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Can this object be sold back? Typically, the answer is no.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Can_Demolish(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Can_Player_Fire -- Can the player give this object an attack mission?          *\n *                                                                                             *\n *    This routine is used to determine if attacking is an option under player control with    *\n *    respect to this unit. This routine will be overridden as necessary for those objects     *\n *    that have the ability to attack.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Can this object be given an attack order by the player?                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Can_Player_Fire(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Can_Player_Move -- Can the player give this object a movement mission?         *\n *                                                                                             *\n *    This routine is used to determine if the player has the ability to command this object   *\n *    with a movement mission. This routine will be overridden as necessary to support this    *\n *    ability.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Can this object be given a movement mission by the player?                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Can_Player_Move(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Target_Coord -- Fetches the coordinate if this object is a target.             *\n *                                                                                             *\n *    When the coordinate to use when firing at this object is needed, this routine will       *\n *    provide it. Normal objects just use the center of the object for this, but there are     *\n *    some more sophisticated objects that are not fired upon the center.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate to fire at if this object is a target.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE ObjectClass::Target_Coord(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(Coord_Add(XY_Coord(0, -Height), Center_Coord()));\n//\treturn(Center_Coord());\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Center_Coord -- Fetches the center coordinate for the object.                  *\n *                                                                                             *\n *    This routine will return the center coordinate for the object. The center coordinate is  *\n *    typically the coordinate recorded in the object structure. Exceptions to this include    *\n *    the trees and other terrain elements.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the coordinate that is considered the center point of this object.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE ObjectClass::Center_Coord(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(Coord);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Render_Coord -- Fetches the coordinate to draw this object at.                 *\n *                                                                                             *\n *    This routine will return the coordinate to base the drawing of this object's graphic     *\n *    at. This is adjusted according to the nature of the graphic associated with this         *\n *    object.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the coordinate to draw the graphic of this object at.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE ObjectClass::Render_Coord(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(Center_Coord());\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Docking_Coord -- Fetches the coordinate to dock at this object.                *\n *                                                                                             *\n *    This routine returns the coordinate that a potential docking object should home in on.   *\n *    Typically, this the center of the object, but in certain cases it is adjusted off center *\n *    according to the object type. An example of this would be the airfield.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate that a docking object should head for.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE ObjectClass::Docking_Coord(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(Center_Coord());\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Sort_Y -- Returns the coordinate used for display order sorting.               *\n *                                                                                             *\n *    This routine will return the value to be used for object sorting. The sorting ensures    *\n *    that the object are rendered from a top to bottom order. Certain object use a sorting    *\n *    value different from their center coordinate. This is true if the object \"touches the    *\n *    ground\" at a point that is different from the object's center point.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the value to use as the Y sorting value.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE ObjectClass::Sort_Y(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(Coord);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Fire_Coord -- Fetches the coordinate a projectile will launch from.            *\n *                                                                                             *\n *    For those objects that fire, the coordinate that the projectile it launches will appear  *\n *    at the location specified by the return value from this function.                        *\n *                                                                                             *\n * INPUT:   which -- Which weapon to consider when determining fire coordinate?                *\n *                   0: primary weapon                                                         *\n *                   1: secondary weapon                                                       *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate that a launched projectile will appear at if this      *\n *          object were to fire the weapon specified.                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE ObjectClass::Fire_Coord(int ) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(Coord);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Record_The_Kill -- Records this object as killed by the specified object.      *\n *                                                                                             *\n *    This routine is called when this object is killed. If the source of the death is known,  *\n *    then a pointer to the responsible object is provided as a parameter.                     *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the cause of this unit's death.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Record_The_Kill(TechnoClass * )\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Do_Shimmer -- Shimmers this object if it is cloaked.                           *\n *                                                                                             *\n *    When an object is cloaked, there are several conditions that would cause it to shimmer   *\n *    and thus reveal itself. When such a condition arrises, this function is called. If the   *\n *    object is cloaked, then it will shimmer. At this derivation level, cloaking is           *\n *    undefined. Objects that can cloak will override this function as necessary.              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Do_Shimmer(void)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Exit_Object -- Causes the specified object to leave this object.               *\n *                                                                                             *\n *    This routine is called, typically, by a transport building type that requires an object  *\n *    to leave it. This routine will place the object at a suitable location or return         *\n *    a value indicating why not.                                                              *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that wishes to leave this object.                *\n *                                                                                             *\n * OUTPUT:  Returns the success value of the attempt:                                          *\n *             0: Object could not be placed -- ever                                           *\n *             1: Object placement is temporarily delayed -- try again later.                  *\n *             2: Object placement proceeded normally                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ObjectClass::Exit_Object(TechnoClass *)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Hidden -- Called when this object becomes hidden from the player.              *\n *                                                                                             *\n *    This routine is called when the object becomes hidden from the player. It can result in  *\n *    lost targeting and tracking abilities with respect to the hidden object.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Hidden(void)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Look -- Called when this object needs to reveal terrain.                       *\n *                                                                                             *\n *    This routine is called when the object needs to look around the terrain. For player      *\n *    owned objects, the terrain is revealed. For non-player objects, not effect occurs.       *\n *                                                                                             *\n * INPUT:   incremental -- If true, then the looking algorithm will only examine the edges     *\n *                         of the sight range. This is more efficient and work well if the     *\n *                         object has only moved one cell since the last time it has performed *\n *                         the look operation.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This can be a time consuming operation. Call only when necessary.               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Look(bool )\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Active_Click_With -- Dispatches action on the object specified.                *\n *                                                                                             *\n *    This routine is called when this object is selected and the mouse was clicked on the     *\n *    tactical map. An action is required from the object. The object that the mouse was       *\n *    over and the tentative action to perform are provided as parameters.                     *\n *                                                                                             *\n * INPUT:   action   -- The requested action to perform with the object specified.             *\n *                                                                                             *\n *          object   -- The object that the action should be performed on. This object is      *\n *                      what the mouse was over when the click occurred.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Active_Click_With(ActionType , ObjectClass *)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Active_Click_With -- Dispatches action on the specified cell.                  *\n *                                                                                             *\n *    This routine will dispatch the action requested upon the cell specified. It is called    *\n *    when the mouse is clicked over a cell while this object is selected.                     *\n *                                                                                             *\n * INPUT:   action   -- The action to perform.                                                 *\n *                                                                                             *\n *          cell     -- The location (cell) to perform this action upon.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Active_Click_With(ActionType , CELL )\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Clicked_As_Target -- Triggers target selection animation.                      *\n *                                                                                             *\n *    This routine is called when this object is the target of some player click action.       *\n *    For more sophisticated object, this will trigger the object to begin flashing a few      *\n *    times. At this level, no action is performed.                                            *\n *                                                                                             *\n * INPUT:   flashes  -- The requested number of times to flash this object.                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Clicked_As_Target(int)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::In_Range -- Determines if the coordinate is within weapon range.               *\n *                                                                                             *\n *    This routine will determine if the specified coordinate is within weapon range.          *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to check to see if it is within weapon range.              *\n *                                                                                             *\n *          which -- The weapon to check against.                                              *\n *                   0: primary weapon                                                         *\n *                   1: secondary weapon                                                       *\n *                                                                                             *\n * OUTPUT:  bool; Is the specified coordinate within weapon range for the weapon type          *\n *                specified?                                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::In_Range(COORDINATE , int) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Weapon_Range -- Returns the weapon range for the weapon specified.             *\n *                                                                                             *\n *    This routine will return the weapon range according to the type of weapon specified.     *\n *                                                                                             *\n * INPUT:   which -- The weapon to fetch the range from.                                       *\n *                   0: primary weapon                                                         *\n *                   1: secondary weapon                                                       *\n *                                                                                             *\n * OUTPUT:  Returns with the range (in leptons) of the weapon specified.                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ObjectClass::Weapon_Range(int) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Scatter -- Tries to scatter this object.                                       *\n *                                                                                             *\n *    This routine is used when the object should scatter from its current location. It        *\n *    applies to units that have the ability to move.                                          *\n *                                                                                             *\n * INPUT:   coord -- The source of the threat that is causing the scatter.                     *\n *                                                                                             *\n *          forced-- Whether this scatter attempt is serious and scattering should occur       *\n *                   regardless of what is doing now.                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This may or may not cause the object to scatter. It is merely a request to the  *\n *             object that it would be good if it were to scatter.                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Scatter(COORDINATE , bool, bool)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Catch_Fire -- Called when animation is attached to this object.                *\n *                                                                                             *\n *    This routine is called when an animation is attached to this object. It might be a       *\n *    fire animation (hence the name), but it might also be smoke or any other animation       *\n *    as well.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the object caught on fire by this routine? Actually, this is really      *\n *                the answer to this question; \"Is this animation attaching to this object     *\n *                that doesn't already have an animation attached?\"                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Catch_Fire(void)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn false;\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Fire_Out -- Informs object that attached animation has finished.               *\n *                                                                                             *\n *    This routine is called if there is an attached animation on this object and that         *\n *    animation has finished. Typically, this is necessary for when trees are on fire.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Fire_Out(void)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Value -- Fetches the target value of this object.                              *\n *                                                                                             *\n *    This routine will return the target value of this object. The higher the number, the     *\n *    better the object will be as a target. This routine is called when searching for         *\n *    targets. Generic objects have no target potential, and this routine returns zero to      *\n *    reflect that. Other object types will override this routine to return the appropriate    *\n *    target value.                                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the value of this object as a target. Higher values mean better       *\n *          target.                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ObjectClass::Value(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Get_Mission -- Fetches the current mission of this object.                     *\n *                                                                                             *\n *    Generic objects don't have a mission, so this routine will just return MISSION_NONE.     *\n *    However, techno objects do have a mission and this routine is overloaded to handle       *\n *    those objects in order to return the correct mission value.                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current mission being followed by this object.                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nMissionType ObjectClass::Get_Mission(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(MISSION_NONE);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Repair -- Handles object repair control.                                       *\n *                                                                                             *\n *    This routine will control object repair mode. At the object level, no repair is          *\n *    possible, so it is expected that any object that can repair will override this function  *\n *    as necessary.                                                                            *\n *                                                                                             *\n * INPUT:   control  -- The repair control parameter.                                          *\n *                      0  = turn repair off                                                   *\n *                      1  = turn repair on                                                    *\n *                      -1 = toggle repair state                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Repair(int )\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Sell_Back -- Sells the object -- if possible.                                  *\n *                                                                                             *\n *    This routine is called to sell back the object. Override this routine for the more       *\n *    sophisticated objects that can actually be sold back. Normal objects can't be sold and   *\n *    this routine does nothing as a consequence.                                              *\n *                                                                                             *\n * INPUT:   control  -- How to control the sell state of this object.                          *\n *                      0  = stop selling.                                                     *\n *                      1  = start selling.                                                    *\n *                      -1 = toggle selling state.                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Sell_Back(int )\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Move -- Moves (by force) the object in the desired direction.                  *\n *                                                                                             *\n *    This routine will instantly move the object one cell in the specified direction. It      *\n *    moves the object by force. This is typically ONLY used by the scenario editor            *\n *    process.                                                                                 *\n *                                                                                             *\n * INPUT:   facing   -- The direction to move the object.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Naturally, this can cause illegal placement situations -- use with caution.     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Move(FacingType facing)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tCOORDINATE\tcoord;\n\n\tMark(MARK_UP);\n\tcoord = Adjacent_Cell(Coord, facing);\n\tif (Can_Enter_Cell(Coord_Cell(coord)) == MOVE_OK) {\n\t\tCoord = coord;\n\t}\n\tMark(MARK_DOWN);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Unselect -- This will un-select the object if it was selected.                 *\n *                                                                                             *\n *    This routine brings a currently selected object into an unselected state. This is        *\n *    needed when another object becomes selected as well as if the object is destroyed.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Unselect(void)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tif (IsSelected) {\n\t\tCurrentObject.Delete(this);\n\t\tif (In_Which_Layer() == LAYER_GROUND) Mark(MARK_OVERLAP_UP);\n\t\tIsSelected = false;\n\t\tif (In_Which_Layer() == LAYER_GROUND) Mark(MARK_OVERLAP_DOWN);\n\t}\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Select -- Try to make this object the \"selected\" object.                       *\n *                                                                                             *\n *    This routine is used to make this object into the one that is \"selected\". A selected     *\n *    object usually displays a floating bar graph and is available to be given orders from    *\n *    the player's I/O.                                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1994 JLB : Created.                                                                 *\n *   06/12/1995 JLB : Cannot select a loaner object.                                           *\n *   07/23/1995 JLB : Adds to head or tail depending on leader type flag.                      *\n *=============================================================================================*/\nbool ObjectClass::Select(void)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tif (!Debug_Map && (IsSelected || !Class_Of().IsSelectable)) {\n\t\treturn(false);\n\t}\n\n\tif (!Debug_Map && Can_Player_Move() && Is_Techno() && ((TechnoClass *)this)->IsALoaner) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tDon't allow selection if the object is still in the air.\n\t*/\n\tif (Height > 0 && (What_Am_I() == RTTI_UNIT || What_Am_I() == RTTI_VESSEL || What_Am_I() == RTTI_INFANTRY)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tDon't allow selection of object when in building placement mode.\n\t*/\n\tif (Map.PendingObject) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf selecting an object of a different house than the player's, make sure that\n\t**\tthe entire selection list is cleared.\n\t*/\n\tif (CurrentObject.Count() > 0) {\n\t\tHouseClass * tryhptr = HouseClass::As_Pointer(Owner());\n\t\tHouseClass * oldhptr = HouseClass::As_Pointer(CurrentObject[0]->Owner());\n//\t\tif (Owner() != CurrentObject[0]->Owner() || CurrentObject[0]->Owner() != PlayerPtr->Class->House) {\n\t\tif (oldhptr->IsPlayerControl != tryhptr->IsPlayerControl || !oldhptr->IsPlayerControl) {\n\t\t\tUnselect_All();\n\t\t}\n\t}\n\tif (((TechnoTypeClass const &)Class_Of()).IsLeader) {\n\t\tCurrentObject.Add_Head(this);\n\t} else {\n\t\tCurrentObject.Add(this);\n\t}\n\n\tif (In_Which_Layer() == LAYER_GROUND) Mark(MARK_OVERLAP_UP);\n\tIsSelected = true;\n\tif (In_Which_Layer() == LAYER_GROUND) Mark(MARK_OVERLAP_DOWN);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Render -- Displays the object onto the map.                                    *\n *                                                                                             *\n *    This routine will determine the location of the object and if it is roughly on the       *\n *    visible screen, it will display it. Not displaying objects that are not on the screen    *\n *    will save valuable time.                                                                 *\n *                                                                                             *\n * INPUT:   bool; Should the render be forced regardless of whether the object is flagged to   *\n *                be redrawn?                                                                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the draw code called for this object?                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Render(bool forced) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tint\tx, y;\n\tCOORDINATE coord = Render_Coord();\n\tCELL cell = Coord_Cell(coord);\n\n\tif (Debug_Map || Debug_Unshroud || ((forced || IsToDisplay) && IsDown && !IsInLimbo)) {\n\t\tIsToDisplay = false;\n\n\t\tif (Map.Coord_To_Pixel(coord, x, y)) {\n\n\t\t\t/*\n\t\t\t**\tDraw the object itself\n\t\t\t*/\n\t\t\tDraw_It(x, y, WINDOW_TACTICAL);\n\n#ifdef SCENARIO_EDITOR\n\t\t\t/*\n\t\t\t**\tDraw the trigger attached to the object. Draw_It is window-\n\t\t\t**\trelative, so add the window's x-coord to 'x'.\n\t\t\t*/\n\t\t\tif (Debug_Map && Trigger.Is_Valid()) {\n\t\t\t\tFancy_Text_Print(Trigger->Class->IniName,\n\t\t\t\t\tx + (WinX), y,\n\t\t\t\t\t&ColorRemaps[PCOLOR_RED], TBLACK,\n\t\t\t\t\tTPF_CENTER | TPF_NOSHADOW | TPF_6POINT);\n\t\t\t}\n#endif\n\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * ObjectClass::Debug_Dump -- Displays status of the object class to the mono monitor.         *\n *                                                                                             *\n *    This routine is used to display the current status of the object class to the mono       *\n *    monitor.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Debug_Dump(MonoClass * mono) const\n{\n\tmono->Set_Cursor(1, 1);mono->Printf(\"%-18.18s\", Text_String(Full_Name()));\n\tif (Next != NULL) {\n\t\tmono->Set_Cursor(20, 5);mono->Printf(\"%08X\", Next->As_Target());\n\t}\n\tif (Trigger.Is_Valid()) {\n\t\tmono->Text_Print(Trigger->Class->IniName, 11, 3);\n\t}\n\tmono->Set_Cursor(34, 1);mono->Printf(\"%3d\", Strength);\n\n\tmono->Fill_Attrib(1, 13, 12, 1, IsDown ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 14, 12, 1, IsToDamage ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 15, 12, 1, IsToDisplay ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 16, 12, 1, IsInLimbo ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 17, 12, 1, IsSelected ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(14, 13, 12, 1, IsAnimAttached ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Set_Cursor(23, 14);mono->Printf(\"%d\", Riser);\n\tmono->Fill_Attrib(14, 12, 14, 1, IsFalling ? MonoClass::INVERSE : MonoClass::NORMAL);\n\n\tAbstractClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * ObjectClass::Mark_For_Redraw -- Marks object and system for redraw.                         *\n *                                                                                             *\n *    This routine will mark the object and inform the display system                          *\n *    that appropriate rendering is needed. Whenever it is determined                          *\n *    that an object needs to be redrawn, call this routine.                                   *\n *                                                                                             *\n * INPUT:      none                                                                            *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   This is a subordinate function to the function Mark(). If an object needs to    *\n *             be redrawn it is probably better to call the function Mark(MARK_CHANGE) rather  *\n *             than this function. This function does not inform the map system that           *\n *             overlapping objects are to be redrawn and thus unless you are really sure that  *\n *             this routine should be called, don't.                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1994 JLB : Created.                                                                 *\n *   12/23/1994 JLB : Flags map and flags unit only.                                           *\n *=============================================================================================*/\nvoid ObjectClass::Mark_For_Redraw(void)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tif (!IsToDisplay) {\n\t\tIsToDisplay = true;\n\n\t\t/*\n\t\t**\tThis tells the map rendering logic to \"go through the motions\" and call the\n\t\t**\trendering function. In the rendering function, it will sort out what gets\n\t\t**\trendered and what doesn't.\n\t\t*/\n\t\tMap.Flag_To_Redraw(false);\n\t}\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Limbo -- Brings the object into a state of limbo.                              *\n *                                                                                             *\n *    An object brought into a state of limbo by this routine can be safely deleted. This      *\n *    routine will remove the object from all game lists and tracking systems. It is called    *\n *    prior to deleting the object or placing the object \"on ice\".                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the object successfully placed in limbo?                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Limbo(void)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tif (GameActive && !IsInLimbo) {\n\n\t\tUnselect();\n\t\tDetach_All();\n\t\tMark(MARK_UP);\n\n\t\t/*\n\t\t**\tRemove the object from the appropriate display list.\n\t\t*/\n\t\tMap.Remove(this, In_Which_Layer());\n\n\t\t/*\n\t\t**\tRemove the object from the logic processing list.\n\t\t*/\n\t\tif (Class_Of().IsSentient) {\n\t\t\tLogic.Delete(this);\n\t\t}\n\n\t\tHidden();\n\t\tIsInLimbo = true;\n\t\tIsToDisplay = false;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Unlimbo -- Brings the object into the game system.                             *\n *                                                                                             *\n *    This routine will place the object into the game tracking and display systems. It is     *\n *    called as a consequence of creating the object. Every game object must be unlimboed at   *\n *    some point.                                                                              *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to place the object into the game system.                  *\n *                                                                                             *\n *          dir (optional) -- initial facing direction for this object                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the game object successfully unlimboed?                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *   12/23/1994 JLB : Sets object strength.                                                    *\n *=============================================================================================*/\nbool ObjectClass::Unlimbo(COORDINATE coord, DirType )\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\tif (GameActive && IsInLimbo && !IsDown) {\n\t\tif (ScenarioInit || Can_Enter_Cell(Coord_Cell(coord), FACING_NONE) == MOVE_OK) {\n\t\t\tIsInLimbo = false;\n\t\t\tIsToDisplay = false;\n\t\t\tCoord = Class_Of().Coord_Fixup(coord);\n\n\t\t\tif (Mark(MARK_DOWN)) {\n\t\t\t\tif (IsActive) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tAdd the object to the appropriate map layer. This layer is used\n\t\t\t\t\t**\tfor rendering purposes.\n\t\t\t\t\t*/\n\t\t\t\t\tif (In_Which_Layer() != LAYER_NONE) {\n\t\t\t\t\t\tMap.Submit(this, In_Which_Layer());\n\t\t\t\t\t}\n\n\t\t\t\t\tif (Class_Of().IsSentient) {\n\t\t\t\t\t\tLogic.Submit(this);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Detach -- Detach the specified target from this object.                        *\n *                                                                                             *\n *    This routine is called when the object (as specified) is to be removed from the game     *\n *    engine and thus, all references to it must be severed. Typically, the only thing         *\n *    checked for at this level is the attached trigger.                                       *\n *                                                                                             *\n * INPUT:   target   -- The target that will be removed from the game system.                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Detach(TARGET target, bool )\n{\n\tif (Trigger.Is_Valid() && Is_Target_Trigger(target) && Trigger->As_Target() == target) {\n\t\tAttach_Trigger(NULL);\n\t}\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Detach_All -- Removes the object from all tracking systems.                    *\n *                                                                                             *\n *    This routine will take the object and see that it is removed from all miscellaneous      *\n *    tracking systems in the game. This operation is vital when deleting an object. It is     *\n *    necessary so that when the object is removed from the game, existing game objects won't  *\n *    be referencing a now invalid game object. This typically affects the targeting           *\n *    and navigation computers of other game objects.                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Detach_All(bool all)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\t/*\n\t**\tUnselect this object if it was selected.\n\t*/\n\tif (all || Owner() != PlayerPtr->Class->House) {\n\t\tUnselect();\n\t}\n\n\tMap.Detach(this);\n\n\t/*\n\t**\tRemove from targeting computers.\n\t*/\n\tDetach_This_From_All(As_Target(), all);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Receive_Message -- Processes an incoming radio message.                        *\n *                                                                                             *\n *    Any radio message received that applies to objects in general are handled by this        *\n *    routine. Typically, this is the \"redraw\" message, which occurs when another object is    *\n *    loading or unloading and thus overlapping.                                               *\n *                                                                                             *\n * INPUT:   message  -- The message received.                                                  *\n *                                                                                             *\n * OUTPUT:  Returns with the appropriate radio response. If the message was recognized, then   *\n *          RADIO_ROGER is returned, otherwise, just RADIO_STATIC is returned.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nRadioMessageType ObjectClass::Receive_Message(RadioClass *, RadioMessageType message, long & )\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tswitch (message) {\n\n\t\t/*\n\t\t**\tThis message serves as a rendering convenience. It lets the system\n\t\t**\tknow that there might be a visual conflict and the unit in radio\n\t\t**\tcontact should be redrawn. This typically occurs when a vehicle\n\t\t**\tis being unloaded from a hover lander.\n\t\t*/\n\t\tcase RADIO_REDRAW:\n\t\t\tMark(MARK_CHANGE);\n\t\t\treturn(RADIO_ROGER);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(RADIO_STATIC);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Take_Damage -- Applies damage to the object.                                   *\n *                                                                                             *\n *    This routine applies damage to the object according to the damage parameters. It handles *\n *    reducing the strength of the object and also returns the result of that damage. The      *\n *    result value can be examined to determine if the object was destroyed, greatly damaged,  *\n *    or other results.                                                                        *\n *                                                                                             *\n * INPUT:   damage   -- Reference to the damage number to apply. This number will be adjusted  *\n *                      according to defensive armor and distance. Examine this value after    *\n *                      the call to determine the actual amount of damage applied.             *\n *                                                                                             *\n *          distance -- The distance (in leptons) from the center of the damage causing        *\n *                      explosion to the object itself.                                        *\n *                                                                                             *\n *          warhead  -- The warhead type that is causing the damage.                           *\n *                                                                                             *\n *          source   -- The perpetrator of this damage.                                        *\n *                                                                                             *\n *          forced   -- Is the damage forced upon the object regardless of whether it          *\n *                      is normally immune?                                                    *\n *                                                                                             *\n * OUTPUT:  Returns the ResultType that indicates what the affect of the damage was.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/29/1994 JLB : Created.                                                                 *\n *   12/27/1994 JLB : Trigger event processing for attacked or destroyed.                      *\n *   01/01/1995 JLB : Reduces damage greatly depending on range.                               *\n *=============================================================================================*/\nResultType ObjectClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, int forced)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tResultType result = RESULT_NONE;\n\tint oldstrength = Strength;\n\n\tif (oldstrength && damage != 0 && (forced || !Class_Of().IsImmune)) {\n\t\tint maxstrength = Class_Of().MaxStrength;\n\n\t\t/*\n\t\t**\tModify damage based on the warhead type and the armor of the object. This results\n\t\t**\tin a reduced damage value, but never below 1 damage point.  Unless\n\t\t** it's forced damage, in which case we want full damage.\n\t\t*/\n\t\tif (!forced /*&& damage > 0*/) {\n\t\t\tdamage = Modify_Damage(damage, warhead, Class_Of().Armor, distance);\n\n\t\t\t/*\n\t\t\t**\tSpecial hack to ensure that dogs only do damage to intended victim and no\n\t\t\t**\tdamage to others.\n\t\t\t*/\n\t\t\tif (source && source->What_Am_I() == RTTI_INFANTRY && ((InfantryClass *)source)->Class->IsDog) {\n\t\t\t\tif (source->TarCom == As_Target()) {\n\t\t\t\t\tdamage = Strength;\n\t\t\t\t} else {\n\t\t\t\t\tdamage = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (damage == 0) return(RESULT_NONE);\n\n\t\t/*\n\t\t** Are we healing/repairing?  If so, add strength, but in\n\t\t** any case, return that no damage was done.\n\t\t*/\n\t\tif (damage < 0) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif (What_Am_I() == RTTI_INFANTRY || What_Am_I() == RTTI_UNIT || What_Am_I() == RTTI_AIRCRAFT) {\n#else\n\t\t\tif (What_Am_I() == RTTI_INFANTRY) {\n#endif\n\t\t\t\tClicked_As_Target(7);\n\t\t\t\tStrength -= damage;\n\t\t\t\tif (Strength > maxstrength) {\n\t\t\t\t\tStrength = maxstrength;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn(RESULT_NONE);\n\t\t}\n\n\t\t/*\n\t\t**\tAt this point, we KNOW that at least light damage has occurred.\n\t\t*/\n\t\tresult = RESULT_LIGHT;\n\n\t\t/*\n\t\t**\tA non-fatal blow has occurred. Check to see if the object transitioned to below\n\t\t**\thalf strength or if it is now down to one hit point.\n\t\t*/\n\t\tif (oldstrength > damage) {\n\n\t\t\tif (oldstrength >= (maxstrength >> 1) && (oldstrength-damage) < (maxstrength >> 1)) {\n\t\t\t\tresult = RESULT_HALF;\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tWhen an object is damaged to destruction, it will instead stop at one\n\t\t\t**\tdamage point. This will prolong the damage state as well as\n\t\t\t**\tgive greater satisfaction when it is finally destroyed.\n\t\t\t*/\n\t\t\tdamage = oldstrength;\n\t\t}\n\n\t\t/*\n\t\t**\tApply the damage to the object.\n\t\t*/\n\t\tStrength = oldstrength - damage;\n\n\t\t/*\n\t\t**\tCheck to see if the object is majorly damaged or destroyed.\n\t\t*/\n\t\tswitch (Strength) {\n\t\t\tcase 0:\n\t\t\t\tRecord_The_Kill(source);\n\t\t\t\tresult = RESULT_DESTROYED;\n\t\t\t\tif (this->Is_Techno()) {\n\t\t\t\t\tif (this == ::As_Object(((TechnoClass *)this)->House->UnitToTeleport)) ((TechnoClass *)this)->House->UnitToTeleport = 0;\n\t\t\t\t}\n\t\t\t\tDetach_All();\n\t\t\t\tbreak;\n\n\t\t\tcase 1:\n\t\t\t\tresult = RESULT_MAJOR;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tHandle any trigger event associated with this object.\n\t\t*/\n\t\tif (source && Trigger.Is_Valid() && result != RESULT_DESTROYED) {\n\t\t\tTrigger->Spring(TEVENT_ATTACKED, this);\n\t\t}\n\n\t\t/*\n\t\t**\tIf any damage was assessed and this object is selected, then flag\n\t\t**\tthe object to be redrawn so that the health bar will be updated.\n\t\t*/\n\t\tif (result != RESULT_NONE && IsSelected) {\n\t\t\tMark(MARK_CHANGE);\n\t\t}\n\t}\n\n\t/*\n\t**\tReturn with the result of the damage taken.\n\t*/\n\treturn(result);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Mark -- Handles basic marking logic.                                           *\n *                                                                                             *\n *    This routine handles the base logic for marking an object up or down on the map. It      *\n *    manages the IsDown flag as well as flagging the object to be redrawn if necessary.       *\n *    Whenever an object is to be marked, it should call this base class function first. If    *\n *    this function returns true, then the higher level function should proceed with its own   *\n *    logic.                                                                                   *\n *                                                                                             *\n * INPUT:   mark  -- The marking method to use for this object. It can be either MARK_DOWN,    *\n *                   MARK_UP, or MARK_CHANGE.                                                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the object marked successfully?                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Mark(MarkType mark)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tif (!IsInLimbo && IsActive) {\n\n\t\t/*\n\t\t**\tA mark for change is always successful UNLESS the object\n\t\t**\tis not placed down or has already been flagged as changed\n\t\t**\tthis game frame.\n\t\t*/\n\t\tif (mark == MARK_CHANGE || mark == MARK_CHANGE_REDRAW) {\n\t\t\tif (IsToDisplay && mark != MARK_CHANGE_REDRAW) return(false);\n\t\t\tif (IsDown) {\n\t\t\t\tMark_For_Redraw();\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t** Handle adding or removing the object in the cells' overlap lists\n\t\t*/\n\t\tif (mark == MARK_OVERLAP_UP) {\n\t\t\tif (IsDown == true) {\n\t\t\t\tif (Class_Of().IsFootprint) {\n\t\t\t\t\tMap.Overlap_Up(Coord_Cell(Coord), this);\n\t\t\t\t}\n\t\t\t\tMark_For_Redraw();\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t\tif (mark == MARK_OVERLAP_DOWN) {\n\t\t\tif (IsDown == true) {\n\t\t\t\tif (Class_Of().IsFootprint) {\n\t\t\t\t\tMap.Overlap_Down(Coord_Cell(Coord), this);\n\t\t\t\t}\n\t\t\t\tMark_For_Redraw();\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** It is important to know whether the object is a techno class\n\t\t** or not to see if we have to adjust the regional threat ratings\n\t\t*/\n\t\tint threat = 0;\n\t\tHousesType house = HOUSE_NONE;\n\t\tCELL cell = 0;\n\t\tTechnoClass * tech;\n\t\tif (Is_Techno()) {\n\t\t\ttech \t = (TechnoClass *)this;\n\t\t\tthreat = tech->Risk();\n\t\t\thouse  = tech->Owner();\n\t\t\tcell   = Coord_Cell(Coord);\n\t\t} else {\n\t\t\ttech = NULL;\n\t\t}\n\n\t\t/*\n\t\t**\tMarking down is only successful if the object isn't already\n\t\t**\tplaced down.\n\t\t*/\n\t\tif (mark == MARK_DOWN && !IsDown) {\n\t\t\tif (tech && Session.Type == GAME_NORMAL && In_Which_Layer() == LAYER_GROUND) {\n\t\t\t\tMap[cell].Adjust_Threat(house, threat);\n\t\t\t}\n\t\t\tIsDown = true;\n\t\t\tMark_For_Redraw();\n\t\t\treturn(true);\n\t\t}\n\n\t\t/*\n\t\t**\tLifting up is only successful if the object isn't already\n\t\t**\tlifted up from the map.\n\t\t*/\n\t\tif (mark == MARK_UP && IsDown) {\n\t\t\tif (tech && Session.Type == GAME_NORMAL && In_Which_Layer() == LAYER_GROUND) {\n\t\t\t\tMap[cell].Adjust_Threat(house, -threat);\n\t\t\t}\n\t\t\tIsDown = false;\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Init -- Initializes the basic object system.                                   *\n *                                                                                             *\n *    This routine should be called when the basic object system needs to be initialized. This *\n *    occurs when the scenario is about to be loaded.                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Init(void)\n{\n\tCurrentObject.Clear();\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Revealed -- Reveals this object to the house specified.                        *\n *                                                                                             *\n *    This routine is called when this object gets revealed to the house specified.            *\n *                                                                                             *\n * INPUT:   house -- Pointer to the house that this object is being revealed to.               *\n *                                                                                             *\n * OUTPUT:  Was this object revealed for the first time to this house? Generic objects always  *\n *          return true unless an invalid house pointer was specified.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Revealed(HouseClass * house)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(house != NULL);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Paradrop -- Unlimbos object in paradrop mode.                                  *\n *                                                                                             *\n *    Call this routine as a replacement for Unlimbo() if the object is to be paradropped onto *\n *    the playing field.                                                                       *\n *                                                                                             *\n * INPUT:   coord -- The desired landing coordinate to give the dropping unit.                 *\n *                                                                                             *\n * OUTPUT:  bool; Was the object successfully unlimboed and has begun paradropping?            *\n *                                                                                             *\n * WARNINGS:   The unit may not be successful in paradropping if the desired destination       *\n *             location cannot be occupied by the object.                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/07/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Paradrop(COORDINATE coord)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tHeight = FLIGHT_LEVEL;\n\tIsFalling = true;\n\tif (Unlimbo(coord, DIR_S)) {\n\t\tAnimClass * anim = NULL;\n\n\t\tif (What_Am_I() == RTTI_BULLET) {\n\t\t\tanim = new AnimClass(ANIM_PARA_BOMB, Coord_Move(Center_Coord(), DIR_N, 0x0030 + Height));\n\t\t} else {\n\t\t\tanim = new AnimClass(ANIM_PARACHUTE, Coord_Move(Center_Coord(), DIR_N, 0x0030 + Height));\n\t\t}\n\n\t\t/*\n\t\t**\tIf the animation was created, then attach it to this object.\n\t\t*/\n\t\tif (anim != NULL) {\n\t\t\tanim->Attach_To(this);\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Attach_Trigger -- Attach specified trigger to object.                          *\n *                                                                                             *\n *    This routine is used to attach the specified trigger to the object.                      *\n *                                                                                             *\n * INPUT:   trigger  -- Pointer to the trigger to attach. If any existing trigger is desired   *\n *                      to be detached, then pass NULL to this routine.                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the trigger attached?                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Attach_Trigger(TriggerClass * trigger)\n{\n\tif (Trigger.Is_Valid()) {\n\t\tTriggerClass * tptr = Trigger;\n\t\ttptr->AttachCount--;\n\t\tTrigger = NULL;\n\t}\n\n\tif (trigger) {\n\t\tTrigger = trigger;\n\t\ttrigger->AttachCount++;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n// These can't be made inline (for various reasons).\nshort const * ObjectClass::Occupy_List(bool placement) const {return(Class_Of().Occupy_List(placement));};\nshort const * ObjectClass::Overlap_List(bool ) const {return(Class_Of().Overlap_List());};\nBuildingClass * ObjectClass::Who_Can_Build_Me(bool intheory, bool legal) const {return(Class_Of().Who_Can_Build_Me(intheory, legal, Owner()));};\nfixed ObjectClass::Health_Ratio(void) const {return(fixed(Strength, Class_Of().MaxStrength));};\nint ObjectClass::Full_Name(void) const {return Class_Of().Full_Name();};\n\n\n//**********************************************************************************************\n// MODULE SEPARATION -- ObjectTypeClass member functions follow.\n//**********************************************************************************************\n\n\n/***********************************************************************************************\n * ObjectTypeClass::ObjectTypeClass -- Normal constructor for object type class objects.       *\n *                                                                                             *\n *    This is the base constructor that is used when constructing the object type classes.     *\n *    Every tangible game piece type calls this constructor for the ObjectTypeClass. This      *\n *    class holds static information that is common to objects in general.                     *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectTypeClass::ObjectTypeClass(\n\t\t\t\t\t\tRTTIType rtti,\n\t\t\t\t\t\tint id,\n\t\t\t\t\t\tbool is_sentient,\n\t\t\t\t\t\tbool is_stealthy,\n\t\t\t\t\t\tbool is_selectable,\n\t\t\t\t\t\tbool is_legal_target,\n\t\t\t\t\t\tbool is_insignificant,\n\t\t\t\t\t\tbool is_immune,\n\t\t\t\t\t\tbool is_footprint,\n\t\t\t\t\t\tint name,\n\t\t\t\t\t\tchar const * ini) :\n\tAbstractTypeClass(rtti, id, name, ini),\n\tIsCrushable(false),\n\tIsStealthy(is_stealthy),\n\tIsSelectable(is_selectable),\n\tIsLegalTarget(is_legal_target),\n\tIsInsignificant(is_insignificant),\n\tIsImmune(is_immune),\n\tIsSentient(is_sentient),\n\tIsFootprint(is_footprint),\n\tArmor(ARMOR_NONE),\n\tMaxStrength(0),\n\tImageData(0),\n\tRadarIcon(0)\n{\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::Max_Pips -- Fetches the maximum pips allowed for this object.              *\n *                                                                                             *\n *    This routine will return the maximum number of pips that can be displayed for this       *\n *    object. When dealing with generic objects, this value is always zero.                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of pip boxes (empty or otherwise) to display.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ObjectTypeClass::Max_Pips(void) const\n{\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::Dimensions -- Gets the dimensions of the object in pixels.                 *\n *                                                                                             *\n *    This routine will fetch the dimensions of this object expressed as pixels width and      *\n *    pixels height. This information can be used to intelligently update the clipping         *\n *    rectangles.                                                                              *\n *                                                                                             *\n * INPUT:   width    -- Reference to the width variable that will be filled in.                *\n *                                                                                             *\n *          height   -- Reference to the height variable that will be filled in.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectTypeClass::Dimensions(int &width, int &height) const\n{\n\twidth = 10;\n\theight = 10;\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::Cost_Of -- Returns the cost to buy this unit.                              *\n *                                                                                             *\n *    This routine will return the cost to purchase this unit. This routine is expected to be  *\n *    overridden by the objects that can actually be purchased. All other object types can     *\n *    simply return zero since this value won't be used.                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the cost of the object.                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ObjectTypeClass::Cost_Of(void) const\n{\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::Time_To_Build -- Fetches the time to construct this object.                *\n *                                                                                             *\n *    This routine will fetch the time in takes to construct this object. Objects that can     *\n *    be constructed will override this routine in order to return a useful value.             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the time units (arbitrary) that it takes to construct this object.    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ObjectTypeClass::Time_To_Build(void) const\n{\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::Get_Cameo_Data -- Fetches pointer to cameo data for this object type.      *\n *                                                                                             *\n *    This routine will return with the cameo data pointer for this object type. It is         *\n *    expected that objects that can appear on the sidebar will override this routine in order *\n *    to provide proper cameo data pointer.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the cameo shape data.                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid const * ObjectTypeClass::Get_Cameo_Data(void) const\n{\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::Occupy_List -- Returns with simple occupation list for object.             *\n *                                                                                             *\n *    This routine returns a pointer to a simple occupation list for this object. Since at     *\n *    this tier of the object class chain, the exact shape of the object is indeterminate,     *\n *    this function merely returns a single cell occupation list. This actually works for      *\n *    most vehicles.                                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to a simple occupation list.                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * ObjectTypeClass::Occupy_List(bool) const\n{\n\tstatic short const _list[] = {0, REFRESH_EOL};\n\treturn(_list);\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::Overlap_List -- Returns a pointer to a simple overlap list.                *\n *                                                                                             *\n *    This function returns a pointer to an overlap list for the object. An overlap list is    *\n *    the offsets from the object's cell to get the cells the imagery overlaps, but is object  *\n *    is not considered to occupy. Since at this stage, the overlap information is not         *\n *    available, this function merely returns a pointer to an empty list.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to the generic overlap list.                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * ObjectTypeClass::Overlap_List(void) const\n{\n\tstatic short const _list[] = {REFRESH_EOL};\n\treturn(_list);\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::One_Time -- Handles one time processing for object types.                  *\n *                                                                                             *\n *    This routine is used to handle the once per game processing required for object types.   *\n *    This consists of loading any data and initializing any data tables the game requires.    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine goes to disk.                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectTypeClass::One_Time(void)\n{\n\tSelectShapes = MFCD::Retrieve(\"SELECT.SHP\");\n\n\t#ifndef NDEBUG\n\t\tRawFileClass file(\"PIPS.SHP\");\n\t\tif (file.Is_Available()) {\n\t\t\tPipShapes = Load_Alloc_Data(file);\n\t\t} else {\n\t\t\tPipShapes = MFCD::Retrieve(\"PIPS.SHP\");\n\t\t}\n\t#else\n\t\tPipShapes = MFCD::Retrieve(\"PIPS.SHP\");\n\t#endif\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::Who_Can_Build_Me -- Determine what building can build this object type.    *\n *                                                                                             *\n *    This routine will scan through all available factory buildings and determine which       *\n *    is capable of building this object type. The scan can be controlled to scan for only     *\n *    factory buildings that are free to produce now or those that could produce this          *\n *    object type if conditions permit.                                                        *\n *                                                                                             *\n * INPUT:   intheory -- Should the general (when conditions permit) case be examined to see    *\n *                      if a building could build this object type \"in theory\" even though it  *\n *                      might currently be otherwise occupied?                                 *\n *                                                                                             *\n *          legal    -- Check for building prerequisite and technology level rules? Usually    *\n *                      this would be 'true' for human controlled requests and 'false' for     *\n *                      the computer. This is because the computer is usually not under        *\n *                      the normal restrictions that the player is under.                      *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the building that can produce the object of this         *\n *          type. If no suitable factory building could be found, then NULL is returned.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuildingClass * ObjectTypeClass::Who_Can_Build_Me(bool intheory, bool legal, HousesType house) const\n{\n\tBuildingClass * anybuilding = NULL;\n\n\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\tBuildingClass * building = Buildings.Ptr(index);\n\t\tassert(building != NULL);\n\n\t\tif (\t!building->IsInLimbo &&\n\t\t\t\tbuilding->House->Class->House == house &&\n\t\t\t\tbuilding->Class->ToBuild == RTTI &&\n\t\t\t\tbuilding->Mission != MISSION_DECONSTRUCTION && building->MissionQueue != MISSION_DECONSTRUCTION &&\n\t\t\t\t((1L << building->ActLike) & Get_Ownable()) &&\n\t\t\t\t(!legal || building->House->Can_Build(this, building->ActLike)) &&\n\t\t\t\t(intheory || !building->In_Radio_Contact())) {\n\n\t\t\t// BG: Hack so only kennels can build dogs, and no other, and barracks can\n\t\t\t//     only build humans and no other.\n\t\t\tif (What_Am_I() == RTTI_INFANTRYTYPE) {\n\t\t\t\tInfantryTypeClass * me = (InfantryTypeClass *)this;\n\t\t\t\tif (me->IsDog) {\n\t\t\t\t\tif (*building == STRUCT_KENNEL) {\n\t\t\t\t\t\tif (building->IsLeader) return(building);\n\t\t\t\t\t\tanybuilding = building;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (*building != STRUCT_KENNEL) {\n\t\t\t\t\t\tif (building->IsLeader) return(building);\n\t\t\t\t\t\tanybuilding = building;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tHACK ALERT: Helipads can build aircraft and airstrips can build\n\t\t\t\t**\tfixed wing craft only.\n\t\t\t\t*/\n\t\t\t\tif (What_Am_I() == RTTI_AIRCRAFTTYPE) {\n\t\t\t\t\tAircraftTypeClass * air = (AircraftTypeClass *)this;\n\t\t\t\t\tif ((*building == STRUCT_HELIPAD && !air->IsFixedWing) || (*building == STRUCT_AIRSTRIP && air->IsFixedWing)) {\n\t\t\t\t\t\tif (building->IsLeader) return(building);\n\t\t\t\t\t\tanybuilding = building;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tif (building->IsLeader) return(building);\n\t\t\t\t\tanybuilding = building;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(anybuilding);\n}\n"
  },
  {
    "path": "CODE/OBJECT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/OBJECT.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OBJECT.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 29, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 29, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef OBJECT_H\n#define OBJECT_H\n\n#include\t\"abstract.h\"\n\nclass ObjectClass;\nclass TechnoClass;\nclass ObjectTypeClass;\nclass HouseClass;\nclass BuildingClass;\nclass RadioClass;\nclass TriggerClass;\n\n\n/**********************************************************************\n**\tEvery game object (that can exist on the map) is ultimately derived from this object\n**\tclass. It holds the common information between all objects. This is primarily the\n**\tobject unique ID number and its location in the world. All common operations between\n**\tgame objects are represented by virtual functions in this class.\n*/\nclass ObjectClass : public AbstractClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThe object can be in one of two states -- placed down on the map, or not. If the\n\t\t**\tobject is placed down on the map, then this flag will be true.\n\t\t*/\n\t\tunsigned IsDown:1;\n\n\t\t/*\n\t\t**\tThis is a support flag that is only used while building a list of objects to\n\t\t**\tbe damaged by a proximity affect (explosion). When this flag is set, this object\n\t\t**\twill not be added to the list of units to damage. When damage is applied to the\n\t\t**\tobject, this flag is cleared again. This process ensures that an object is never\n\t\t**\tsubject to \"double jeopardy\".\n\t\t*/\n\t\tunsigned IsToDamage:1;\n\n\t\t/*\n\t\t**\tIs this object flagged to be displayed during the next rendering process?  This\n\t\t**\tflag could be set by many different circumstances. It is automatically cleared\n\t\t**\twhen the object is rerendered.\n\t\t*/\n\t\tunsigned IsToDisplay:1;\n\n\t\t/*\n\t\t**\tAn object in the game may be valid yet held in a state of \"limbo\". Units are in such\n\t\t**\ta state if they are being transported or are otherwise \"inside\" another unit. They can\n\t\t**\talso be in limbo if they have been created but are being held until the proper time\n\t\t**\tfor delivery.\n\t\t*/\n\t\tunsigned IsInLimbo:1;\n\n\t\t/*\n\t\t**\tWhen an object is \"selected\" it is given a floating bar graph or other graphic imagery\n\t\t**\tto display this fact. When the player performs I/O, the actions may have a direct\n\t\t**\tbearing on the actions of the currently selected object. For quick checking purposes,\n\t\t**\tif this object is the one that is \"selected\", this flag will be true.\n\t\t*/\n\t\tunsigned IsSelected:1;\n\n\t\t/*\n\t\t**\tIf an animation is attached to this object, then this flag will be true.\n\t\t*/\n\t\tunsigned IsAnimAttached:1;\n\n\t\t/*\n\t\t**\tIf this object should process falling logic, then this flag will be true. Such\n\t\t**\tobjects might be ballistic projectiles, grenades, or parachuters.\n\t\t*/\n\t\tunsigned IsFalling:1;\n\t\tint Riser;\n\n\t\t/*\n\t\t**\tSeveral objects could exist in the same cell list. This is a pointer to the\n\t\t**\tnext object in the cell list. The objects in this list are not in any\n\t\t**\tsignificant order.\n\t\t*/\n\t\tSmartPtr<ObjectClass> Next;\n\n\t\t/*\n\t\t** Every object can be assigned a trigger; the same trigger can be assigned\n\t\t** to multiple objects.\n\t\t*/\n\t\tCCPtr<TriggerClass> Trigger;\n\n\t\t/*\n\t\t**\tThis is the current strength of this object.\n\t\t*/\n\t\tshort Strength;\n\n\t\t/*-----------------------------------------------------------------------------------\n\t\t**\tConstructor & destructors.\n\t\t*/\n\t\tObjectClass(RTTIType rtti, int id);\n\t\tObjectClass(NoInitClass const & x) : AbstractClass(x), Next(x), Trigger(x) {};\n\t\tvirtual ~ObjectClass(void) {Next = 0;};\n\t\tint operator < (ObjectClass const & object) const {return Sort_Y() < object.Sort_Y();};\n\t\tint operator > (ObjectClass const & object) const {return Sort_Y() > object.Sort_Y();};\n\n\t\t/*\n\t\t**\tObject selection control.\n\t\t*/\n\t\tstatic void Init(void);\n\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tvirtual bool Is_Players_Army(void) const {return(false);}\n\t\tvirtual void const * Get_Image_Data(void) const;\n\t\tvirtual ActionType What_Action(ObjectClass const *) const;\n\t\tvirtual ActionType What_Action(CELL) const;\n\t\tvirtual LayerType In_Which_Layer(void) const;\n\t\tbool Is_Infantry(void) const {return(RTTI == RTTI_INFANTRY);};\n\t\tbool Is_Foot(void) const {return(RTTI == RTTI_INFANTRY || RTTI == RTTI_UNIT || RTTI == RTTI_VESSEL || RTTI == RTTI_AIRCRAFT);};\n\t\tbool Is_Techno(void) const {return(RTTI == RTTI_BUILDING || RTTI == RTTI_UNIT || RTTI == RTTI_INFANTRY || RTTI == RTTI_VESSEL || RTTI == RTTI_AIRCRAFT);};\n\t\tvirtual int Get_Ownable(void) const;\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const = 0;\n\t\tvirtual char const * Name(void) const;\n\t\tvirtual int Full_Name(void) const;\n\t\tvirtual bool Can_Repair(void) const;\n\t\tvirtual bool Can_Demolish(void) const;\n\t\tvirtual bool Can_Player_Fire(void) const;\n\t\tvirtual bool Can_Player_Move(void) const;\n\n\t\t/*\n\t\t**\tCoordinate inquiry functions. These are used for both display and\n\t\t**\tcombat purposes.\n\t\t*/\n\t\tvirtual COORDINATE Docking_Coord(void) const;\n\t\tvirtual COORDINATE Target_Coord(void) const;\n\t\tvirtual COORDINATE Center_Coord(void) const;\n\t\tvirtual COORDINATE Render_Coord(void) const;\n\t\tvirtual COORDINATE Sort_Y(void) const;\n\t\tvirtual COORDINATE Fire_Coord(int which) const;\n\t\tvirtual COORDINATE Exit_Coord(void) const;\n\n\t\t/*\n\t\t**\tObject entry and exit from the game system.\n\t\t*/\n\t\tvirtual bool Limbo(void);\n\t\tvirtual bool Unlimbo(COORDINATE , DirType facing = DIR_N);\n\t\tvirtual void Detach(TARGET target, bool all=true);\n\t\tvirtual void Detach_All(bool all=true);\n\t\tvirtual void Record_The_Kill(TechnoClass * );\n\t\tvirtual bool Paradrop(COORDINATE coord);\n\t\tbool Attach_Trigger(TriggerClass * trigger);\n\n\t\t/*\n\t\t**\tDisplay and rendering support functionality. Supports imagery and how\n\t\t**\tobject interacts with the map and thus indirectly controls rendering.\n\t\t*/\n\t\tvirtual void Do_Shimmer(void);\n\t\tvirtual int Exit_Object(TechnoClass *);\n\t\tvirtual bool Render(bool forced) const;\n\t\tvirtual short const * Occupy_List(bool placement=false) const;\n\t\tvirtual short const * Overlap_List(bool redraw=false) const;\n\t\tvirtual fixed Health_Ratio(void) const;\n\t\tvirtual void Draw_It(int x, int y, WindowNumberType ) const = 0;\n\t\tvirtual void Hidden(void);\n\t\tvirtual void Look(bool incremental=false);\n\t\tvirtual bool Mark(MarkType=MARK_CHANGE);\n\n\tprivate:\n\t\tvirtual void Mark_For_Redraw(void);\n\n\tpublic:\n\n\t\t/*\n\t\t**\tUser I/O.\n\t\t*/\n\t\tvirtual void Active_Click_With(ActionType , ObjectClass *);\n\t\tvirtual void Active_Click_With(ActionType , CELL );\n\t\tvirtual void Clicked_As_Target(int = 7);\n\t\tvirtual bool Select(void);\n\t\tvirtual void Unselect(void);\n\n\t\t/*\n\t\t**\tCombat related.\n\t\t*/\n\t\tvirtual bool In_Range(COORDINATE , int=0) const;\n\t\tvirtual int Weapon_Range(int =0) const;\n\t\tvirtual ResultType Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source=0, bool forced=false);\n\t\tvirtual void Scatter(COORDINATE , bool forced=false, bool nokidding=false);\n\t\tvirtual bool Catch_Fire(void);\n\t\tvirtual void Fire_Out(void);\n\t\tvirtual int Value(void) const;\n\t\tvirtual MissionType Get_Mission(void) const;\n\n\t\t/*\n\t\t**\tAI.\n\t\t*/\n\t\tvirtual void Per_Cell_Process(PCPType) {}\n\t\tvirtual BuildingClass * Who_Can_Build_Me(bool intheory, bool legal) const;\n\t\tvirtual RadioMessageType Receive_Message(RadioClass * from, RadioMessageType message, long & param);\n\t\tvirtual bool Revealed(HouseClass * house);\n\t\tvirtual void Repair(int );\n\t\tvirtual void Sell_Back(int );\n\t\tvirtual void AI(void);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n\n\t\t/*\n\t\t**\tScenario and debug support.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\t\tvirtual void Move(FacingType);\n\n\t\tenum {FLIGHT_LEVEL=256};\n};\n\n#endif\n"
  },
  {
    "path": "CODE/ODATA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/ODATA.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ODATA.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 16, 1994                                                 *\n *                                                                                             *\n *                  Last Update : August 14, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   OverlayTypeClass::As_Reference -- Fetch a reference to the overlay type specified.        *\n *   OverlayTypeClass::Coord_Fixup -- Adjust the coord to be legal for assignment.             *\n *   OverlayTypeClass::Create_And_Place -- Creates and places a overlay object on the map.     *\n *   OverlayTypeClass::Create_One_Of -- Creates an object of this overlay type.                *\n *   OverlayTypeClass::Display -- Displays a generic representation of overlay.                *\n *   OverlayTypeClass::Draw_It -- Draws the overlay image at location specified.               *\n *   OverlayTypeClass::From_Name -- Determine overlay from ASCII name.                         *\n *   OverlayTypeClass::Init -- Initialize the overlay graphic data per theater.                *\n *   OverlayTypeClass::Init_Heap -- Initialize the overlay type class heap.                    *\n *   OverlayTypeClass::Occupy_List -- Determines occupation list.                              *\n *   OverlayTypeClass::One_Time -- Loads all the necessary general overlay shape data.         *\n *   OverlayTypeClass::OverlayTypeClass -- Constructor for overlay type objects.               *\n *   OverlayTypeClass::Prep_For_Add -- Prepares to add overlay to scenario.                    *\n *   OverlayTypeClass::Radar_Icon -- Gets a pointer to the radar icons                         *\n *   OverlayTypeClass::operator delete -- Returns an overlay type object back to the pool.     *\n *   OverlayTypeClass::operator new -- Allocate an overlay type class object from pool.        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"type.h\"\n\n\nstatic OverlayTypeClass const Sandbag(\n\tOVERLAY_SANDBAG_WALL,\t// Overlay type number.\n\t\"SBAG\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_SANDBAG_WALL,\t\t\t// Full name of overlay.\n\tLAND_WALL,\t\t\t\t\t// What kind of ground is it?\n\t1,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t20,\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\ttrue,\t\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\ttrue,\t\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Cyclone(\n\tOVERLAY_CYCLONE_WALL,\t// Overlay type number.\n\t\"CYCL\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_CYCLONE_WALL,\t\t\t// Full name of overlay.\n\tLAND_WALL,\t\t\t\t\t// What kind of ground is it?\n\t2,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t10,\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\ttrue,\t\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\ttrue,\t\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Brick(\n\tOVERLAY_BRICK_WALL,\t\t// Overlay type number.\n\t\"BRIK\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_BRICK_WALL,\t\t\t// Full name of overlay.\n\tLAND_WALL,\t\t\t\t\t// What kind of ground is it?\n\t3,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t70,\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\ttrue,\t\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\ttrue,\t\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\ttrue,\t\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Barbwire(\n\tOVERLAY_BARBWIRE_WALL,\t// Overlay type number.\n\t\"BARB\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_BARBWIRE_WALL,\t\t// Full name of overlay.\n\tLAND_WALL,\t\t\t\t\t// What kind of ground is it?\n\t1,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t2,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\ttrue,\t\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\ttrue,\t\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Wood(\n\tOVERLAY_WOOD_WALL,\t\t// Overlay type number.\n\t\"WOOD\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_WOOD_WALL,\t\t\t\t// Full name of overlay.\n\tLAND_WALL,\t\t\t\t\t// What kind of ground is it?\n\t1,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t2,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\ttrue,\t\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\ttrue,\t\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\ttrue,\t\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Fence(\n\tOVERLAY_FENCE,\t// Overlay type number.\n\t\"FENC\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_FENCE,\t\t\t\t\t// Full name of overlay.\n\tLAND_WALL,\t\t\t\t\t// What kind of ground is it?\n\t2,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t10,\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\ttrue,\t\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\ttrue,\t\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\n\nstatic OverlayTypeClass const Gold1(\n\tOVERLAY_GOLD1,\t\t\t\t// Overlay type number.\n\t\"GOLD01\",\t\t\t\t\t// INI name of overlay.\n\tTXT_GOLD,\t\t\t\t\t// Full name of overlay.\n\tLAND_TIBERIUM,\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\ttrue,\t\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Gold2(\n\tOVERLAY_GOLD2,\t\t\t\t// Overlay type number.\n\t\"GOLD02\",\t\t\t\t\t// INI name of overlay.\n\tTXT_GOLD,\t\t\t\t\t// Full name of overlay.\n\tLAND_TIBERIUM,\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\ttrue,\t\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Gold3(\n\tOVERLAY_GOLD3,\t\t\t\t// Overlay type number.\n\t\"GOLD03\",\t\t\t\t\t// INI name of overlay.\n\tTXT_GOLD,\t\t\t\t\t// Full name of overlay.\n\tLAND_TIBERIUM,\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\ttrue,\t\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Gold4(\n\tOVERLAY_GOLD4,\t\t\t\t// Overlay type number.\n\t\"GOLD04\",\t\t\t\t\t// INI name of overlay.\n\tTXT_GOLD,\t\t\t\t\t// Full name of overlay.\n\tLAND_TIBERIUM,\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\ttrue,\t\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\n\nstatic OverlayTypeClass const Gems1(\n\tOVERLAY_GEMS1,\t\t\t\t// Overlay type number.\n\t\"GEM01\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_GEMS,\t\t\t\t\t// Full name of overlay.\n\tLAND_TIBERIUM,\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\ttrue,\t\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Gems2(\n\tOVERLAY_GEMS2,\t\t\t\t// Overlay type number.\n\t\"GEM02\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_GEMS,\t\t\t\t\t// Full name of overlay.\n\tLAND_TIBERIUM,\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\ttrue,\t\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Gems3(\n\tOVERLAY_GEMS3,\t\t\t\t// Overlay type number.\n\t\"GEM03\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_GEMS,\t\t\t\t\t// Full name of overlay.\n\tLAND_TIBERIUM,\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\ttrue,\t\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Gems4(\n\tOVERLAY_GEMS4,\t\t\t\t// Overlay type number.\n\t\"GEM04\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_GEMS,\t\t\t\t\t// Full name of overlay.\n\tLAND_TIBERIUM,\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\ttrue,\t\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const V12(\n\tOVERLAY_V12,\t\t\t\t// Overlay type number.\n\t\"V12\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_CIV12,\t\t\t\t\t// Full name of overlay.\n\tLAND_ROCK,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const V13(\n\tOVERLAY_V13,\t\t\t\t// Overlay type number.\n\t\"V13\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_CIV13,\t\t\t\t\t// Full name of overlay.\n\tLAND_ROCK,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const V14(\n\tOVERLAY_V14,\t\t\t\t// Overlay type number.\n\t\"V14\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_CIV14,\t\t\t\t\t// Full name of overlay.\n\tLAND_ROCK,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const V15(\n\tOVERLAY_V15,\t\t\t\t// Overlay type number.\n\t\"V15\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_CIV15,\t\t\t\t\t// Full name of overlay.\n\tLAND_ROCK,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const V16(\n\tOVERLAY_V16,\t\t\t\t// Overlay type number.\n\t\"V16\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_CIV16,\t\t\t\t\t// Full name of overlay.\n\tLAND_ROCK,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const V17(\n\tOVERLAY_V17,\t\t\t\t// Overlay type number.\n\t\"V17\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_CIV17,\t\t\t\t\t// Full name of overlay.\n\tLAND_ROCK,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const V18(\n\tOVERLAY_V18,\t\t\t\t// Overlay type number.\n\t\"V18\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_CIV18,\t\t\t\t\t// Full name of overlay.\n\tLAND_ROCK,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const FlagSpot(\n\tOVERLAY_FLAG_SPOT,\t\t// Overlay type number.\n\t\"FPLS\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_FLAG_SPOT,\t\t\t\t// Full name of overlay.\n\tLAND_CLEAR,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const WoodCrate(\n\tOVERLAY_WOOD_CRATE,\t\t// Overlay type number.\n\t\"WCRATE\",\t\t\t\t\t// INI name of overlay.\n\tTXT_WOOD_CRATE,\t\t\t// Full name of overlay.\n\tLAND_CLEAR,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\ttrue\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const WaterCrate(\n\tOVERLAY_WATER_CRATE,\t\t// Overlay type number.\n\t\"WWCRATE\",\t\t\t\t\t// INI name of overlay.\n\tTXT_WATER_CRATE,\t\t\t// Full name of overlay.\n\tLAND_WATER,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\ttrue\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const SteelCrate(\n\tOVERLAY_STEEL_CRATE,\t\t// Overlay type number.\n\t\"SCRATE\",\t\t\t\t\t// INI name of overlay.\n\tTXT_STEEL_CRATE,\t\t\t// Full name of overlay.\n\tLAND_CLEAR,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\ttrue\t\t\t\t\t\t\t// Is this a crate?\n);\n\n\n/***********************************************************************************************\n * OverlayTypeClass::OverlayTypeClass -- Constructor for overlay type objects.                 *\n *                                                                                             *\n *    This is the constructor for the overlay types.                                           *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nOverlayTypeClass::OverlayTypeClass(\n\tOverlayType iconset,\n\tchar const * ininame,\n\tint fullname,\n\tLandType ground,\n\tint  damagelevels,\n\tint  damagepoints,\n\tbool isradarvisible,\n\tbool iswooden,\n\tbool istarget,\n\tbool iscrushable,\n\tbool istiberium,\n\tbool high,\n\tbool theater,\n\tbool walltype,\n\tbool iscrate) :\n\t\tObjectTypeClass(RTTI_OVERLAYTYPE,\n\t\t\t\t\t\t\tint(iconset),\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tistarget,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tfullname,\n\t\t\t\t\t\t\tininame),\n\tType(iconset),\n\tLand(ground),\n\tDamageLevels(damagelevels),\n\tDamagePoints(damagepoints),\n\tIsTheater(theater),\n\tIsWall(walltype),\n\tIsHigh(high),\n\tIsTiberium(istiberium),\n\tIsWooden(iswooden),\n\tIsCrate(iscrate),\n\tIsRadarVisible(isradarvisible)\n{\n\tIsCrushable = iscrushable;\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::operator new -- Allocate an overlay type class object from pool.          *\n *                                                                                             *\n *    This will allocate an overlay type class object from the special memory pool that is     *\n *    for that purpose.                                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the overlay type class object allocated. If there is     *\n *          insufficient memory to fulfill the request, then NULL is returned.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * OverlayTypeClass::operator new(size_t)\n{\n\treturn(OverlayTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::operator delete -- Returns an overlay type object back to the pool.       *\n *                                                                                             *\n *    This will return a previously allcoated overaly type object to the special memory        *\n *    pool that it was allocated from.                                                         *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to the overlay type class object to return the memory pool.    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OverlayTypeClass::operator delete(void * pointer)\n{\n\tOverlayTypes.Free((OverlayTypeClass *)pointer);\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::Init_Heap -- Initialize the overlay type class heap.                      *\n *                                                                                             *\n *    This will initialize the overlay type heap by pre-allocated all overlay types known      *\n *    to exist.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   It should be called once and before the rules.ini file is processed.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OverlayTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese overlay type class objects must be allocated in the exact order that they\n\t**\tare specified in the OverlayType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew OverlayTypeClass(Sandbag);\t\t//\tOVERLAY_SANDBAG_WALL\n\tnew OverlayTypeClass(Cyclone);\t\t//\tOVERLAY_CYCLONE_WALL\n\tnew OverlayTypeClass(Brick);\t\t\t//\tOVERLAY_BRICK_WALL\n\tnew OverlayTypeClass(Barbwire);\t\t//\tOVERLAY_BARBWIRE_WALL\n\tnew OverlayTypeClass(Wood);\t\t\t//\tOVERLAY_WOOD_WALL\n\tnew OverlayTypeClass(Gold1);\t\t\t// OVERLAY_GOLD1\n\tnew OverlayTypeClass(Gold2);\t\t\t// OVERLAY_GOLD2\n\tnew OverlayTypeClass(Gold3);\t\t\t// OVERLAY_GOLD3\n\tnew OverlayTypeClass(Gold4);\t\t\t// OVERLAY_GOLD4\n\tnew OverlayTypeClass(Gems1);\t\t\t// OVERLAY_GEMS1\n\tnew OverlayTypeClass(Gems2);\t\t\t// OVERLAY_GEMS2\n\tnew OverlayTypeClass(Gems3);\t\t\t// OVERLAY_GEMS3\n\tnew OverlayTypeClass(Gems4);\t\t\t// OVERLAY_GEMS4\n\tnew OverlayTypeClass(V12);\t\t\t\t//\tOVERLAY_V12\n\tnew OverlayTypeClass(V13);\t\t\t\t//\tOVERLAY_V13\n\tnew OverlayTypeClass(V14);\t\t\t\t//\tOVERLAY_V14\n\tnew OverlayTypeClass(V15);\t\t\t\t//\tOVERLAY_V15\n\tnew OverlayTypeClass(V16);\t\t\t\t//\tOVERLAY_V16\n\tnew OverlayTypeClass(V17);\t\t\t\t//\tOVERLAY_V17\n\tnew OverlayTypeClass(V18);\t\t\t\t//\tOVERLAY_V18\n\tnew OverlayTypeClass(FlagSpot);\t\t//\tOVERLAY_FLAG_SPOT\n\tnew OverlayTypeClass(WoodCrate);\t\t// OVERLAY_WOOD_CRATE\n\tnew OverlayTypeClass(SteelCrate);\t// OVERLAY_STEEL_CRATE\n\tnew OverlayTypeClass(Fence);\t\t\t// OVERLAY_FENCE\n\tnew OverlayTypeClass(WaterCrate);\t// OVERLAY_WATER_CRATE\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::One_Time -- Loads all the necessary general overlay shape data.           *\n *                                                                                             *\n *    This routine should be called once when the game first starts. It will establish         *\n *    pointers to the graphic data of the overlay objects.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OverlayTypeClass::One_Time(void)\n{\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::From_Name -- Determine overlay from ASCII name.                           *\n *                                                                                             *\n *    This routine is used to determine the overlay number given only                          *\n *    an ASCII representation. The scenario loader uses this routine                           *\n *    to construct the map from the INI control file.                                          *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the ASCII name of the overlay.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the overlay number. If the name had no match,                         *\n *          then returns with OVERLAY_NONE.                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nOverlayType OverlayTypeClass::From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (OverlayType index = OVERLAY_FIRST; index < OVERLAY_COUNT; index++) {\n\t\t\tif (stricmp(As_Reference(index).IniName, name) == 0) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t}\n\t}\n\treturn(OVERLAY_NONE);\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::Occupy_List -- Determines occupation list.                                *\n *                                                                                             *\n *    This routine is used to examine the overlay map and build an                             *\n *    occupation list. This list is used to render a overlay cursor as                         *\n *    well as placement of icon numbers.                                                       *\n *                                                                                             *\n * INPUT:   placement   -- Is this for placement legality checking only? The normal condition  *\n *                         is for marking occupation flags.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the overlay occupation list.                             *\n *                                                                                             *\n * WARNINGS:   The return pointer is valid only until the next time that                       *\n *             this routine is called.                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * OverlayTypeClass::Occupy_List(bool) const\n{\n\tstatic short _simple[] = {0, REFRESH_EOL};\n\n\treturn(_simple);\n}\n\n\n/***************************************************************************\n * OverlayTypeClass::Radar_Icon -- Gets a pointer to the radar icons       *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1995 PWG : Created.                                             *\n *=========================================================================*/\nunsigned char * OverlayTypeClass::Radar_Icon(int data) const\n{\n\tunsigned char * icon = (unsigned char *)Get_Radar_Data();\t\t// Get pointer to radar icons\n\tif (icon != NULL) icon += (data * 9) + 2;\t\t\t// move icon ptr to correct icon\n\treturn(icon);\t\t\t\t\t\t\t\t\t\t\t// Return the correct icon\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***********************************************************************************************\n * OverlayTypeClass::Display -- Displays a generic representation of overlay.                  *\n *                                                                                             *\n *    This routine is used to display a generic view of the overlay                            *\n *    object. This is necessary for selection in the scenario editor.                          *\n *                                                                                             *\n * INPUT:   x,y   -- The coordinates to center the display about.                              *\n *                                                                                             *\n *          window-- The window to base the coordinates upon.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OverlayTypeClass::Display(int x, int y, WindowNumberType window, HousesType ) const\n{\n\tif (Get_Image_Data() != NULL) {\n\t\tint frame = 0;\n\n\t\tif (IsTiberium) {\n\t\t\tframe = 7;\n\t\t}\n\t\tif (Type == OVERLAY_GEMS1 || Type == OVERLAY_GEMS2 || Type == OVERLAY_GEMS3 || Type == OVERLAY_GEMS4) {\n\t\t\tframe = 2;\n\t\t}\n\n\t\tIsTheaterShape = IsTheater;\n\t\tCC_Draw_Shape(Get_Image_Data(), frame, x, y, window, SHAPE_NORMAL|SHAPE_CENTER|SHAPE_WIN_REL);\n\t\tIsTheaterShape = false;\n\t}\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::Prep_For_Add -- Prepares to add overlay to scenario.                      *\n *                                                                                             *\n *    This routine prepares a list of overlay objects so that the                              *\n *    scenario editor can use this list to display a dialog box. The                           *\n *    selection of a overlay object will allow its placement upon the                          *\n *    map.                                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1994 JLB : Created                                                                  *\n *=============================================================================================*/\nvoid OverlayTypeClass::Prep_For_Add(void)\n{\n\tfor (OverlayType index = OVERLAY_FIRST; index < OVERLAY_COUNT; index++) {\n\t\tOverlayTypeClass const & overlay = As_Reference(index);\n\t\tif (overlay.Get_Image_Data() != NULL &&\n\t\t\t!overlay.IsWall &&\n\t\t\t(!overlay.IsTiberium || index == OVERLAY_GOLD1 || index == OVERLAY_GEMS1)) {\n\n\t\t\tMap.Add_To_List(&overlay);\n\t\t}\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * OverlayTypeClass::Create_And_Place -- Creates and places a overlay object on the map.       *\n *                                                                                             *\n *    This support routine is used by the scenario editor to add a overlay object to the map   *\n *    and to the game.                                                                         *\n *                                                                                             *\n * INPUT:   cell  -- The cell to place the overlay object.                                     *\n *                                                                                             *\n * OUTPUT:  bool; Was the overlay object placed successfully?                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool OverlayTypeClass::Create_And_Place(CELL cell, HousesType ) const\n{\n\tif (new OverlayClass(Type, cell)) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::Create_One_Of -- Creates an object of this overlay type.                  *\n *                                                                                             *\n *    This routine will create an object of this type. For certain overlay objects, such       *\n *    as walls, it is actually created as a building. The \"building\" wall is converted into    *\n *    a overlay at the moment of placing down on the map.                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the appropriate object for this overlay type.            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * OverlayTypeClass::Create_One_Of(HouseClass *) const\n{\n\treturn(new OverlayClass(Type, -1));\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::Draw_It -- Draws the overlay image at location specified.                 *\n *                                                                                             *\n *    This routine will draw the overlay shape at the coordinates specified. It is presumed    *\n *    that all the underlying layers have already been rendered by the time this routine is    *\n *    called.                                                                                  *\n *                                                                                             *\n * INPUT:   x, y  -- Coordinate (upper left) of cell where overlay image is to be drawn.       *\n *                                                                                             *\n *          data  -- Cell specific data that controls the imagery of the overlay.              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OverlayTypeClass::Draw_It(int x, int y, int data) const\n{\n\tIsTheaterShape = IsTheater;\n\tCC_Draw_Shape(Get_Image_Data(), data, Map.TacPixelX+x+(CELL_PIXEL_W>>1), Map.TacPixelY+y+(CELL_PIXEL_H>>1), WINDOW_MAIN, SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_GHOST, NULL, Map.UnitShadow);\n\tIsTheaterShape = false;\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::Init -- Initialize the overlay graphic data per theater.                  *\n *                                                                                             *\n *    This routine will update the overlay graphic data according to the theater specified.    *\n *    It is typically called when the scenario is first loaded (theater change).               *\n *                                                                                             *\n * INPUT:   theater  -- The theater to load specific data for.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OverlayTypeClass::Init(TheaterType theater)\n{\n\tif (theater != LastTheater) {\n\n\t\tfor (OverlayType index = OVERLAY_FIRST; index < OVERLAY_COUNT; index++) {\n\t\t\tOverlayTypeClass & overlay = As_Reference(index);\n\t\t\tchar fullname[_MAX_FNAME+_MAX_EXT];\t// Fully constructed iconset name.\n\n\t\t\tif (overlay.IsTheater) {\n\t\t\t\t_makepath(fullname, NULL, NULL, overlay.IniName, Theaters[theater].Suffix);\n\t\t\t} else {\n\t\t\t\t_makepath(fullname, NULL, NULL, overlay.IniName, \".SHP\");\n\t\t\t}\n\t\t\toverlay.ImageData = MFCD::Retrieve(fullname);\n\n\t\t\tIsTheaterShape = overlay.IsTheater;\t\t//Tell Build_Frame if this is a theater specific shape\n\t\t\tif (overlay.RadarIcon != NULL) delete[] (char *)overlay.RadarIcon;\n\t\t\toverlay.RadarIcon = Get_Radar_Icon(overlay.Get_Image_Data(), 0, -1, 3);\n\t\t\tIsTheaterShape = false;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::As_Reference -- Fetch a reference to the overlay type specified.          *\n *                                                                                             *\n *    Use this routine to get a reference that corresponds to the overlay type.                *\n *                                                                                             *\n * INPUT:   type  -- The overlay type to fetch a reference to.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the overlay type specified.                            *\n *                                                                                             *\n * WARNINGS:   Be sure that the overlay type specified is legal. Illegal type value will       *\n *             result in undefined behavior.                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nOverlayTypeClass & OverlayTypeClass::As_Reference(OverlayType type)\n{\n\treturn(*OverlayTypes.Ptr(type));\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::Coord_Fixup -- Adjust the coord to be legal for assignment.               *\n *                                                                                             *\n *    This will adjust the coordinate specified so that it will be of legal format to          *\n *    assign as the coordinate of an overlay. Overlays are always relative to the upper left   *\n *    corner of the cell, so this routine drops the fractional cell components.                *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to fixup to be legal for assignment.                       *\n *                                                                                             *\n * OUTPUT:  Returns with a properly fixed up coordinate.                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE OverlayTypeClass::Coord_Fixup(COORDINATE coord) const\n{\n\treturn Coord_Whole(coord);\n}\n"
  },
  {
    "path": "CODE/OPTIONS.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/OPTIONS.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OPTIONS.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 8, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   OptionsClass::Adjust_Palette -- Adjusts the palette according to the settings specified.  *\n *   OptionsClass::Fixup_Palette -- Adjusts the real palette to match the palette sliders.     *\n *   OptionsClass::Get_Brightness -- Fetches the current brightness setting.                   *\n *   OptionsClass::Get_Contrast -- Gets the current contrast setting.                          *\n *   OptionsClass::Get_Game_Speed -- Fetches the current game speed setting.                   *\n *   OptionsClass::Get_Saturation -- Fetches the current color setting.                        *\n *   OptionsClass::Get_Scroll_Rate -- Fetches the current scroll rate setting.                 *\n *   OptionsClass::Get_Tint -- Fetches the current tint setting.                               *\n *   OptionsClass::Load_Settings -- reads options settings from the INI file                   *\n *   OptionsClass::Normalize_Delay -- Normalizes delay factor to keep rate constant.           *\n *   OptionsClass::Normalize_Volume -- Convert to a real volume value.                         *\n *   OptionsClass::One_Time -- This performs any one time initialization for the options class.*\n *   OptionsClass::OptionsClass -- The default constructor for the options class.              *\n *   OptionsClass::Process -- Handles all the options graphic interface.                       *\n *   OptionsClass::Save_Settings -- writes options settings to the INI file                    *\n *   OptionsClass::Set -- Sets options based on current settings                               *\n *   OptionsClass::Set_Brightness -- Sets the brightness level to that specified.              *\n *   OptionsClass::Set_Contrast -- Sets the contrast to the value specified.                   *\n *   OptionsClass::Set_Game_Speed -- Sets the game speed as specified.                         *\n *   OptionsClass::Set_Repeat -- Controls the score repeat option.                             *\n *   OptionsClass::Set_Saturation -- Sets the color to the value specified.                    *\n *   OptionsClass::Set_Score_Volume -- Sets the global score volume to that specified.         *\n *   OptionsClass::Set_Scroll_Rate -- Sets the scroll rate as specified.                       *\n *   OptionsClass::Set_Shuffle -- Controls the play shuffle setting.                           *\n *   OptionsClass::Set_Sound_Volume -- Sets the sound effects volume level.                    *\n *   OptionsClass::Set_Tint -- Sets the tint setting.                                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"options.h\"\n\n\n#ifdef WIN32\nchar const * const OptionsClass::HotkeyName = \"WinHotkeys\";\n#else\nchar const * const OptionsClass::HotkeyName = \"DOSHotkeys\";\n#endif\n\n\n/***********************************************************************************************\n * OptionsClass::OptionsClass -- The default constructor for the options class.                *\n *                                                                                             *\n *    This is the constructor for the options class. It handles setting up all the globals     *\n *    necessary for the options. This includes setting them to their default state.            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/21/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nOptionsClass::OptionsClass(void) :\n\tGameSpeed(3),\n\tScrollRate(3),\n#ifdef WIN32\n\tVolume(\".40\"),\t\t\t// was .295\n\tScoreVolume(\".25\"),\n#ifdef FIXIT_VERSION_3\n\tMultiScoreVolume(\"0\"),\n#endif\n#else\n\tVolume(\".8\"),\n\tScoreVolume(\".6\"),\n#endif\n\tBrightness(fixed::_1_2),\n\tTint(fixed::_1_2),\n\tSaturation(fixed::_1_2),\n\tContrast(fixed::_1_2),\n\tAutoScroll(true),\n\tIsScoreRepeat(false),\n\tIsScoreShuffle(false),\n\tIsPaletteScroll(true),\n\n\tKeyForceMove1(KN_LALT),\n\tKeyForceMove2(KN_RALT),\n\tKeyForceAttack1(KN_LCTRL),\n\tKeyForceAttack2(KN_RCTRL),\n\tKeySelect1(KN_LSHIFT),\n\tKeySelect2(KN_RSHIFT),\n\tKeyScatter(KN_X),\n\tKeyStop(KN_S),\n\tKeyGuard(KN_G),\n\tKeyNext(KN_N),\n\tKeyPrevious(KN_B),\n\tKeyFormation(KN_F),\n\tKeyHome1(KN_HOME),\n\tKeyHome2(KN_E_HOME),\n\tKeyBase(KN_H),\n\tKeyResign(KN_R),\n\tKeyAlliance(KN_A),\n\tKeyBookmark1(KN_F9),\n\tKeyBookmark2(KN_F10),\n\tKeyBookmark3(KN_F11),\n\tKeyBookmark4(KN_F12),\n\tKeySelectView(KN_E),\n\tKeyRepair(KN_T),\n\tKeyRepairOn(KN_NONE),\n\tKeyRepairOff(KN_NONE),\n\tKeySell(KN_Y),\n\tKeySellOn(KN_NONE),\n\tKeySellOff(KN_NONE),\n\tKeyMap(KN_U),\n\tKeySidebarUp(KN_UP),\n\tKeySidebarDown(KN_DOWN),\n\tKeyOption1(KN_ESC),\n\tKeyOption2(KN_SPACE),\n\tKeyScrollLeft(KN_NONE),\n\tKeyScrollRight(KN_NONE),\n\tKeyScrollUp(KN_NONE),\n\tKeyScrollDown(KN_NONE),\n\tKeyQueueMove1(KN_Q),\n\tKeyQueueMove2(KN_Q),\n\tKeyTeam1(KN_1),\n\tKeyTeam2(KN_2),\n\tKeyTeam3(KN_3),\n\tKeyTeam4(KN_4),\n\tKeyTeam5(KN_5),\n\tKeyTeam6(KN_6),\n\tKeyTeam7(KN_7),\n\tKeyTeam8(KN_8),\n\tKeyTeam9(KN_9),\n\tKeyTeam10(KN_0)\n{\n}\n\n\n/***********************************************************************************************\n * OptionsClass::One_Time -- This performs any one time initialization for the options class.  *\n *                                                                                             *\n *    This routine should be called only once and it will perform any initializations for the  *\n *    options class that is needed. This may include things like file loading and memory       *\n *    allocation.                                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once.                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/21/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::One_Time(void)\n{\n\tSet_Score_Vol(ScoreVolume * 256);\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Process -- Handles all the options graphic interface.                         *\n *                                                                                             *\n *    This routine is the main control for the visual representation of the options            *\n *    screen. It handles the visual overlay and the player input.                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/21/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Process(void)\n{\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set_Shuffle -- Controls the play shuffle setting.                             *\n *                                                                                             *\n *    This routine will control the score shuffle flag. The setting to use is provided as      *\n *    a parameter. When shuffling is on, the score play order is scrambled.                    *\n *                                                                                             *\n * INPUT:   on -- Should the shuffle option be activated?                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set_Shuffle(int on)\n{\n\tIsScoreShuffle = on;\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set_Repeat -- Controls the score repeat option.                               *\n *                                                                                             *\n *    This routine is used to control whether scores repeat or not. The setting to use for     *\n *    the repeat flag is provided as a parameter.                                              *\n *                                                                                             *\n * INPUT:   on -- Should the scores repeat?                                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set_Repeat(int on)\n{\n\tIsScoreRepeat = on;\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set_Score_Volume -- Sets the global score volume to that specified.           *\n *                                                                                             *\n *    This routine will set the global score volume to the value specified. The value ranges   *\n *    from zero to 255.                                                                        *\n *                                                                                             *\n * INPUT:   volume   -- The new volume setting to use for scores.                              *\n *                                                                                             *\n *          feedback -- Should a feedback sound effect be generated?                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set_Score_Volume(fixed volume, bool feedback)\n{\n\tScoreVolume = Sub_Saturate(volume, 1);\n\tSet_Score_Vol(ScoreVolume * 256);\n\tif (feedback && !Theme.Still_Playing()) {\n\t\tSound_Effect(VOC_BEEP, ScoreVolume);\n\t}\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set_Sound_Volume -- Sets the sound effects volume level.                      *\n *                                                                                             *\n *    This routine will set the sound effect volume level as indicated. It can generate a      *\n *    sound effect for feedback purposes if desired. The volume setting can range from zero    *\n *    to 255. The value of 255 is the loudest.                                                 *\n *                                                                                             *\n * INPUT:   volume   -- The volume setting to use for the new value. 0 to 255.                 *\n *                                                                                             *\n *          feedback -- Should a feedback sound effect be generated?                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set_Sound_Volume(fixed volume, bool feedback)\n{\n\tVolume = Sub_Saturate(volume, 1);\n\tif (feedback) {\n\t\tSound_Effect(VOC_BEEP);\n\t}\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set_Brightness -- Sets the brightness level to that specified.                *\n *                                                                                             *\n *    This routine will set the current brightness level to the value specified. This value    *\n *    can range from zero to 255, with 128 being the normal (default) brightness level.        *\n *                                                                                             *\n * INPUT:   brightness  -- The brightness level to set as current.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set_Brightness(fixed brightness)\n{\n\tBrightness = fixed::_1_4 + (fixed::_1_2 * brightness);\n\tAdjust_Palette(OriginalPalette, InGamePalette, Brightness, Saturation, Tint, Contrast);\n\tInGamePalette.Set();\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Get_Brightness -- Fetches the current brightness setting.                     *\n *                                                                                             *\n *    This routine will fetch the current setting for the brightness level. The value ranges   *\n *    from zero to 255, with 128 being the normal (default) value.                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current brightness setting.                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed OptionsClass::Get_Brightness(void) const\n{\n\treturn((Brightness - fixed::_1_4) / fixed::_1_2);\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set_Saturation -- Sets the color to the value specified.                      *\n *                                                                                             *\n *    This routine will set the color value to that specified. The value specified can range   *\n *    from zero to 255. The value of 128 is the normal default color setting.                  *\n *                                                                                             *\n * INPUT:   color -- The new color value to set as current.                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set_Saturation(fixed color)\n{\n\tSaturation = color;\n\tAdjust_Palette(OriginalPalette, InGamePalette, Brightness, Saturation, Tint, Contrast);\n\tInGamePalette.Set();\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Get_Saturation -- Fetches the current color setting.                          *\n *                                                                                             *\n *    This routine will fetch the current color setting. This value ranges from zero to        *\n *    255.                                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current color setting. The value of 128 is the normal (default)   *\n *          color setting.                                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed OptionsClass::Get_Saturation(void) const\n{\n\treturn(Saturation);\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set_Contrast -- Sets the contrast to the value specified.                     *\n *                                                                                             *\n *    This routine will set the contrast to the setting specified. This setting ranges from    *\n *    zero to 255. The value o 128 is the normal default value.                                *\n *                                                                                             *\n * INPUT:   contrast -- The contrast setting to make as the current setting.                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set_Contrast(fixed contrast)\n{\n\tContrast = fixed::_1_4 + (fixed::_1_2 * contrast);\n\tAdjust_Palette(OriginalPalette, InGamePalette, Brightness, Saturation, Tint, Contrast);\n\tInGamePalette.Set();\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Get_Contrast -- Gets the current contrast setting.                            *\n *                                                                                             *\n *    This routine will get the current contrast setting. The value returned is in the range   *\n *    of zero to 255.                                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the current contrast setting. A setting of 128 is the normal default value.*\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed OptionsClass::Get_Contrast(void) const\n{\n\treturn((Contrast - fixed::_1_4) / fixed::_1_2);\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set_Tint -- Sets the tint setting.                                            *\n *                                                                                             *\n *    This routine will change the current tint setting according to the value specified.      *\n *                                                                                             *\n * INPUT:   tint  -- The desired tint setting. This value ranges from zero to 255.             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The value of 128 is the default (normal) tint setting.                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set_Tint(fixed tint)\n{\n\tTint = tint;\n\tAdjust_Palette(OriginalPalette, InGamePalette, Brightness, Saturation, Tint, Contrast);\n\tInGamePalette.Set();\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Get_Tint -- Fetches the current tint setting.                                 *\n *                                                                                             *\n *    This fetches the current tint setting. The value is returned as a number between         *\n *    zero and 255. This has been adjusted for the valid range allowed.                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current tint setting. Normal tint setting is 128.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed OptionsClass::Get_Tint(void) const\n{\n\treturn(Tint);\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Adjust_Palette -- Adjusts the palette according to the settings specified.    *\n *                                                                                             *\n *    This routine is used to adjust the palette according to the settings provided. It is     *\n *    used by the options class to monkey with the palette.                                    *\n *                                                                                             *\n * INPUT:   oldpal      -- Pointer to the original (unmodified) palette.                       *\n *                                                                                             *\n *          newpal      -- The new palette to create according to the settings provided.       *\n *                                                                                             *\n *          brightness  -- The brightness level (0..255).                                      *\n *                                                                                             *\n *          color       -- The color level (0..255).                                           *\n *                                                                                             *\n *          tint        -- The tint (hue) level (0..255).                                      *\n *                                                                                             *\n *          contrast    -- The contrast level (0..255).                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/21/1994 JLB : Created.                                                                 *\n *   12/02/1995 JLB : Uses palette class objects.                                              *\n *=============================================================================================*/\nvoid OptionsClass::Adjust_Palette(PaletteClass const & oldpal, PaletteClass & newpal, fixed brightness, fixed color, fixed tint, fixed contrast) const\n{\n\tif (!oldpal || !newpal) return;\n\n\t/*\n\t**\tAdjust for palette.\n\t*/\n\tfor (int index = 0; index < PaletteClass::COLOR_COUNT; index++) {\n\t\tif (index == CC_MOUSE_COLOR) {\n\t\t\tnewpal[index] = oldpal[index];\n\t\t} else {\n\t\t\t/*\n\t\t\t**\tConvert the working palette entry into an HSV format for\n\t\t\t**\tmanipulation.\n\t\t\t*/\n\t\t\tHSVClass hsv = oldpal[index];\n\n\t\t\t/*\n\t\t\t**\tAdjust contrast by moving the value toward the center according to the\n\t\t\t**\tpercentage indicated.\n\t\t\t*/\n\t\t\tint temp;\n\t\t\ttemp = (hsv.Value_Component() * (brightness * 256)) / 0x80;\t\t// Brightness\n\t\t\ttemp = Bound(temp, 0, 0xFF);\n\t\t\tint v = temp;\n\t\t\ttemp = (((((int)v) - 0x80) * (contrast * 256)) / 0x80) + 0x80;\t// Contrast\n\t\t\ttemp = Bound(temp, 0, 0xFF);\n\t\t\tv = temp;\n\t\t\ttemp = (hsv.Saturation_Component() * (color * 256)) / 0x80;\t\t// Color\n\t\t\ttemp = Bound(temp, 0, 0xFF);\n\t\t\tint s = temp;\n\t\t\ttemp = (hsv.Hue_Component() * (tint * 256)) / 0x80;\t\t\t\t\t// Tint\n\t\t\ttemp = Bound(temp, 0, 0xFF);\n\t\t\tint h = temp;\n\n\t\t\t/*\n\t\t\t**\tReplace the working palette entry according to the newly calculated\n\t\t\t**\thue, saturation, and value.\n\t\t\t*/\n\t\t\tnewpal[index] = HSVClass(h, s, v);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Load_Settings -- reads options settings from the INI file                     *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *   07/03/1996 JLB : Reworked to use new INI handler.                                         *\n *   07/30/1996 JLB : Handles hotkeys.                                                         *\n *=============================================================================================*/\nvoid OptionsClass::Load_Settings(void)\n{\n\t/*\n\t**\tCreate filename and read the file.\n\t*/\n\tCCFileClass file(CONFIG_FILE_NAME);\n\tINIClass ini;\n\tini.Load(file);\n\n\t/*\n\t**\tRead in the Options values\n\t*/\n\tstatic char const * const OPTIONS = \"Options\";\n\tGameSpeed = ini.Get_Int(OPTIONS, \"GameSpeed\", GameSpeed);\n\tScrollRate = ini.Get_Int(OPTIONS, \"ScrollRate\", ScrollRate);\n\tSet_Brightness(ini.Get_Fixed(OPTIONS, \"Brightness\", Brightness));\n\tSet_Sound_Volume(ini.Get_Fixed(OPTIONS, \"Volume\", Volume), false);\n\tSet_Score_Volume(ini.Get_Fixed(OPTIONS, \"ScoreVolume\", ScoreVolume), false);\n#ifdef FIXIT_VERSION_3\n\tMultiScoreVolume = ini.Get_Fixed(OPTIONS, \"MultiplayerScoreVolume\", MultiScoreVolume);\n#endif\n\tSet_Contrast(ini.Get_Fixed(OPTIONS, \"Contrast\", Contrast));\n\tSet_Saturation(ini.Get_Fixed(OPTIONS, \"Color\", Saturation));\n\tSet_Tint(ini.Get_Fixed(OPTIONS, \"Tint\", Tint));\n\tAutoScroll = ini.Get_Bool(OPTIONS, \"AutoScroll\", AutoScroll);\n\tSet_Repeat(ini.Get_Bool(OPTIONS, \"IsScoreRepeat\", IsScoreRepeat));\n\tSet_Shuffle(ini.Get_Bool(OPTIONS, \"IsScoreShuffle\", IsScoreShuffle));\n\tSlowPalette = ini.Get_Bool(OPTIONS, \"SlowPalette\", SlowPalette);\n\tIsPaletteScroll = ini.Get_Bool(OPTIONS, \"PaletteScroll\", IsPaletteScroll);\n\n\tKeyForceMove1 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyForceMove1\", KeyForceMove1);\n\tKeyForceMove2 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyForceMove2\", KeyForceMove2);\n\tKeyForceAttack1 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyForceAttack1\", KeyForceAttack1);\n\tKeyForceAttack2 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyForceAttack2\", KeyForceAttack2);\n\tKeySelect1 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeySelect1\", KeySelect1);\n\tKeySelect2 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeySelect2\", KeySelect2);\n\tKeyScatter = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyScatter\", KeyScatter);\n\tKeyStop = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyStop\", KeyStop);\n\tKeyGuard = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyGuard\", KeyGuard);\n\tKeyNext = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyNext\", KeyNext);\n\tKeyPrevious = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyPrevious\", KeyPrevious);\n\tKeyFormation = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyFormation\", KeyFormation);\n\tKeyHome1 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyHome1\", KeyHome1);\n\tKeyHome2 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyHome2\", KeyHome2);\n\tKeyBase = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyBase\", KeyBase);\n\tKeyResign = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyResign\", KeyResign);\n\tKeyAlliance = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyAlliance\", KeyAlliance);\n\tKeyBookmark1 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyBookmark1\", KeyBookmark1);\n\tKeyBookmark2 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyBookmark2\", KeyBookmark2);\n\tKeyBookmark3 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyBookmark3\", KeyBookmark3);\n\tKeyBookmark4 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyBookmark4\", KeyBookmark4);\n\tKeySelectView =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeySelectView\", KeySelectView);\n\tKeyRepair =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyRepairToggle\", KeyRepair);\n\tKeyRepairOn = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyRepairOn\", KeyRepairOn);\n\tKeyRepairOff = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyRepairOff\", KeyRepairOff);\n\tKeySell =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeySellToggle\", KeySell);\n\tKeySellOn = (KeyNumType)ini.Get_Int(HotkeyName, \"KeySellOn\", KeySellOn);\n\tKeySellOff = (KeyNumType)ini.Get_Int(HotkeyName, \"KeySellOff\", KeySellOff);\n\tKeyMap =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyMapToggle\", KeyMap);\n\tKeySidebarUp =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeySidebarUp\", KeySidebarUp);\n\tKeySidebarDown =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeySidebarDown\", KeySidebarDown);\n\tKeyOption1 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyOption1\", KeyOption1);\n\tKeyOption2 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyOption2\", KeyOption2);\n\tKeyScrollLeft =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyScrollLeft\", KeyScrollLeft);\n\tKeyScrollRight =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyScrollRight\", KeyScrollRight);\n\tKeyScrollUp =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyScrollUp\", KeyScrollUp);\n\tKeyScrollDown =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyScrollDown\", KeyScrollDown);\n\tKeyQueueMove1 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyQueueMove1\", KeyQueueMove1);\n\tKeyQueueMove2 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyQueueMove2\", KeyQueueMove2);\n\tKeyTeam1 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam1\", KeyTeam1);\n\tKeyTeam2 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam2\", KeyTeam2);\n\tKeyTeam3 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam3\", KeyTeam3);\n\tKeyTeam4 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam4\", KeyTeam4);\n\tKeyTeam5 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam5\", KeyTeam5);\n\tKeyTeam6 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam6\", KeyTeam6);\n\tKeyTeam7 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam7\", KeyTeam7);\n\tKeyTeam8 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam8\", KeyTeam8);\n\tKeyTeam9 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam9\", KeyTeam9);\n\tKeyTeam10 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam10\", KeyTeam10);\n\n\n#ifdef WIN32\n\tKeyForceMove1 = (KeyNumType)(KeyForceMove1 & ~WWKEY_VK_BIT);\n\tKeyForceMove2 = (KeyNumType)(KeyForceMove2 & ~WWKEY_VK_BIT);\n\tKeyForceAttack1 = (KeyNumType)(KeyForceAttack1 & ~WWKEY_VK_BIT);\n\tKeyForceAttack2 = (KeyNumType)(KeyForceAttack2 & ~WWKEY_VK_BIT);\n\tKeySelect1 = (KeyNumType)(KeySelect1 & ~WWKEY_VK_BIT);\n\tKeySelect2 = (KeyNumType)(KeySelect2 & ~WWKEY_VK_BIT);\n\tKeyScatter = (KeyNumType)(KeyScatter & ~WWKEY_VK_BIT);\n\tKeyStop = (KeyNumType)(KeyStop & ~WWKEY_VK_BIT);\n\tKeyGuard = (KeyNumType)(KeyGuard & ~WWKEY_VK_BIT);\n\tKeyNext = (KeyNumType)(KeyNext & ~WWKEY_VK_BIT);\n\tKeyPrevious = (KeyNumType)(KeyPrevious & ~WWKEY_VK_BIT);\n\tKeyFormation = (KeyNumType)(KeyFormation & ~WWKEY_VK_BIT);\n\tKeyHome1 = (KeyNumType)(KeyHome1 & ~WWKEY_VK_BIT);\n\tKeyHome2 = (KeyNumType)(KeyHome2 & ~WWKEY_VK_BIT);\n\tKeyBase = (KeyNumType)(KeyBase & ~WWKEY_VK_BIT);\n\tKeyResign = (KeyNumType)(KeyResign & ~WWKEY_VK_BIT);\n\tKeyAlliance = (KeyNumType)(KeyAlliance & ~WWKEY_VK_BIT);\n\tKeyBookmark1 = (KeyNumType)(KeyBookmark1 & ~WWKEY_VK_BIT);\n\tKeyBookmark2 = (KeyNumType)(KeyBookmark2 & ~WWKEY_VK_BIT);\n\tKeyBookmark3 = (KeyNumType)(KeyBookmark3 & ~WWKEY_VK_BIT);\n\tKeyBookmark4 = (KeyNumType)(KeyBookmark4 & ~WWKEY_VK_BIT);\n\tKeySelectView = (KeyNumType)(KeySelectView & ~WWKEY_VK_BIT);\n\tKeyRepair = (KeyNumType)(KeyRepair & ~WWKEY_VK_BIT);\n\tKeyRepairOn = (KeyNumType)(KeyRepairOn & ~WWKEY_VK_BIT);\n\tKeyRepairOff = (KeyNumType)(KeyRepairOff & ~WWKEY_VK_BIT);\n\tKeySell = (KeyNumType)(KeySell & ~WWKEY_VK_BIT);\n\tKeySellOn = (KeyNumType)(KeySellOn & ~WWKEY_VK_BIT);\n\tKeySellOff = (KeyNumType)(KeySellOff & ~WWKEY_VK_BIT);\n\tKeyMap = (KeyNumType)(KeyMap & ~WWKEY_VK_BIT);\n\tKeySidebarUp = (KeyNumType)(KeySidebarUp & ~WWKEY_VK_BIT);\n\tKeySidebarDown = (KeyNumType)(KeySidebarDown & ~WWKEY_VK_BIT);\n\tKeyOption1 = (KeyNumType)(KeyOption1 & ~WWKEY_VK_BIT);\n\tKeyOption2 = (KeyNumType)(KeyOption2 & ~WWKEY_VK_BIT);\n\tKeyScrollLeft = (KeyNumType)(KeyScrollLeft & ~WWKEY_VK_BIT);\n\tKeyScrollRight = (KeyNumType)(KeyScrollRight & ~WWKEY_VK_BIT);\n\tKeyScrollUp = (KeyNumType)(KeyScrollUp & ~WWKEY_VK_BIT);\n\tKeyScrollDown = (KeyNumType)(KeyScrollDown & ~WWKEY_VK_BIT);\n\tKeyQueueMove1 = (KeyNumType)(KeyQueueMove1 & ~WWKEY_VK_BIT);\n\tKeyQueueMove2 = (KeyNumType)(KeyQueueMove2 & ~WWKEY_VK_BIT);\n\tKeyTeam1 = (KeyNumType)(KeyTeam1 & ~WWKEY_VK_BIT);\n\tKeyTeam2 = (KeyNumType)(KeyTeam2 & ~WWKEY_VK_BIT);\n\tKeyTeam3 = (KeyNumType)(KeyTeam3 & ~WWKEY_VK_BIT);\n\tKeyTeam4 = (KeyNumType)(KeyTeam4 & ~WWKEY_VK_BIT);\n\tKeyTeam5 = (KeyNumType)(KeyTeam5 & ~WWKEY_VK_BIT);\n\tKeyTeam6 = (KeyNumType)(KeyTeam6 & ~WWKEY_VK_BIT);\n\tKeyTeam7 = (KeyNumType)(KeyTeam7 & ~WWKEY_VK_BIT);\n\tKeyTeam8 = (KeyNumType)(KeyTeam8 & ~WWKEY_VK_BIT);\n\tKeyTeam9 = (KeyNumType)(KeyTeam9 & ~WWKEY_VK_BIT);\n\tKeyTeam10 = (KeyNumType)(KeyTeam10 & ~WWKEY_VK_BIT);\n#endif\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Save_Settings -- writes options settings to the INI file                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *   07/03/1996 JLB : Revamped and tightened up.                                               *\n *   07/30/1996 JLB : Handles hotkeys.                                                         *\n *=============================================================================================*/\nvoid OptionsClass::Save_Settings (void)\n{\n\tCCFileClass file(CONFIG_FILE_NAME);\n\tINIClass ini;\n\n\t/*\n\t**\tLoad any existing options file because it may contain entries that won't be\n\t**\texplicitly written out by this routine. By preloading the database, these entries\n\t**\twill be carried over.\n\t*/\n\tif (file.Is_Available()) {\n\t\tini.Load(file);\n\t}\n\n\t/*\n\t**\tSave Options settings\n\t*/\n\tstatic char const * const OPTIONS = \"Options\";\n\tini.Put_Int(OPTIONS, \"GameSpeed\", GameSpeed);\n\tini.Put_Int(OPTIONS, \"ScrollRate\", ScrollRate);\n\tini.Put_Fixed(OPTIONS, \"Brightness\", Brightness);\n\tini.Put_Fixed(OPTIONS, \"Volume\", Volume);\n#ifdef FIXIT_VERSION_3\n\tif( Session.Type == GAME_NORMAL )\t\t//\tSave only when non-multiplayer.\n\t\tini.Put_Fixed(OPTIONS, \"ScoreVolume\", ScoreVolume);\n#else\n\tini.Put_Fixed(OPTIONS, \"ScoreVolume\", ScoreVolume);\n#endif\n#ifdef FIXIT_VERSION_3\n\tini.Put_Fixed(OPTIONS, \"MultiplayerScoreVolume\", MultiScoreVolume);\n#endif\n\tini.Put_Fixed(OPTIONS, \"Contrast\", Contrast);\n\tini.Put_Fixed(OPTIONS, \"Color\", Saturation);\n\tini.Put_Fixed(OPTIONS, \"Tint\", Tint);\n\tini.Put_Bool(OPTIONS, \"AutoScroll\", AutoScroll);\n\tini.Put_Bool(OPTIONS, \"IsScoreRepeat\", IsScoreRepeat);\n\tini.Put_Bool(OPTIONS, \"IsScoreShuffle\", IsScoreShuffle);\n\tini.Put_Bool(OPTIONS, \"PaletteScroll\", IsPaletteScroll);\n\n\tini.Put_Int(HotkeyName, \"KeyForceMove1\", KeyForceMove1);\n\tini.Put_Int(HotkeyName, \"KeyForceMove2\", KeyForceMove2);\n\tini.Put_Int(HotkeyName, \"KeyForceAttack1\", KeyForceAttack1);\n\tini.Put_Int(HotkeyName, \"KeyForceAttack2\", KeyForceAttack2);\n\tini.Put_Int(HotkeyName, \"KeySelect1\", KeySelect1);\n\tini.Put_Int(HotkeyName, \"KeySelect2\", KeySelect2);\n\tini.Put_Int(HotkeyName, \"KeyScatter\", KeyScatter);\n\tini.Put_Int(HotkeyName, \"KeyStop\", KeyStop);\n\tini.Put_Int(HotkeyName, \"KeyGuard\", KeyGuard);\n\tini.Put_Int(HotkeyName, \"KeyNext\", KeyNext);\n\tini.Put_Int(HotkeyName, \"KeyPrevious\", KeyPrevious);\n\tini.Put_Int(HotkeyName, \"KeyFormation\", KeyFormation);\n\tini.Put_Int(HotkeyName, \"KeyHome1\", KeyHome1);\n\tini.Put_Int(HotkeyName, \"KeyHome2\", KeyHome2);\n\tini.Put_Int(HotkeyName, \"KeyBase\", KeyBase);\n\tini.Put_Int(HotkeyName, \"KeyResign\", KeyResign);\n\tini.Put_Int(HotkeyName, \"KeyAlliance\", KeyAlliance);\n\tini.Put_Int(HotkeyName, \"KeyBookmark1\", KeyBookmark1);\n\tini.Put_Int(HotkeyName, \"KeyBookmark2\", KeyBookmark2);\n\tini.Put_Int(HotkeyName, \"KeyBookmark3\", KeyBookmark3);\n\tini.Put_Int(HotkeyName, \"KeyBookmark4\", KeyBookmark4);\n\tini.Put_Int(HotkeyName, \"KeySelectView\", KeySelectView);\n\tini.Put_Int(HotkeyName, \"KeyRepairToggle\", KeyRepair);\n\tini.Put_Int(HotkeyName, \"KeyRepairOn\", KeyRepairOn);\n\tini.Put_Int(HotkeyName, \"KeyRepairOff\", KeyRepairOff);\n\tini.Put_Int(HotkeyName, \"KeySellToggle\", KeySell);\n\tini.Put_Int(HotkeyName, \"KeySellOn\", KeySellOn);\n\tini.Put_Int(HotkeyName, \"KeySellOff\", KeySellOff);\n\tini.Put_Int(HotkeyName, \"KeyMapToggle\", KeyMap);\n\tini.Put_Int(HotkeyName, \"KeySidebarUp\", KeySidebarUp);\n\tini.Put_Int(HotkeyName, \"KeySidebarDown\", KeySidebarDown);\n\tini.Put_Int(HotkeyName, \"KeyOption1\", KeyOption1);\n\tini.Put_Int(HotkeyName, \"KeyOption2\", KeyOption2);\n\tini.Put_Int(HotkeyName, \"KeyScrollLeft\", KeyScrollLeft);\n\tini.Put_Int(HotkeyName, \"KeyScrollRight\", KeyScrollRight);\n\tini.Put_Int(HotkeyName, \"KeyScrollUp\", KeyScrollUp);\n\tini.Put_Int(HotkeyName, \"KeyScrollDown\", KeyScrollDown);\n\tini.Put_Int(HotkeyName, \"KeyQueueMove1\", KeyQueueMove1);\n\tini.Put_Int(HotkeyName, \"KeyQueueMove2\", KeyQueueMove2);\n\tini.Put_Int(HotkeyName, \"KeyTeam1\", KeyTeam1);\n\tini.Put_Int(HotkeyName, \"KeyTeam2\", KeyTeam2);\n\tini.Put_Int(HotkeyName, \"KeyTeam3\", KeyTeam3);\n\tini.Put_Int(HotkeyName, \"KeyTeam4\", KeyTeam4);\n\tini.Put_Int(HotkeyName, \"KeyTeam5\", KeyTeam5);\n\tini.Put_Int(HotkeyName, \"KeyTeam6\", KeyTeam6);\n\tini.Put_Int(HotkeyName, \"KeyTeam7\", KeyTeam7);\n\tini.Put_Int(HotkeyName, \"KeyTeam8\", KeyTeam8);\n\tini.Put_Int(HotkeyName, \"KeyTeam9\", KeyTeam9);\n\tini.Put_Int(HotkeyName, \"KeyTeam10\", KeyTeam10);\n\n\t/*\n\t**\tWrite the INI data out to a file.\n\t*/\n\tini.Save(file);\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set -- Sets options based on current settings                                 *\n *                                                                                             *\n * Use this routine to adjust the palette or sound settings after a fresh scenario load.       *\n * It assumes the values needed are already loaded into OptionsClass.                          *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set(void)\n{\n\tSet_Brightness(Brightness);\n\tSet_Contrast(Contrast);\n\tSet_Saturation(Saturation);\n\tSet_Tint(Tint);\n\tSet_Sound_Volume(Volume, false);\n\tSet_Score_Volume(ScoreVolume, false);\n\tSet_Repeat(IsScoreRepeat);\n\tSet_Shuffle(IsScoreShuffle);\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Normalize_Delay -- Normalizes delay factor to keep rate constant.             *\n *                                                                                             *\n *    This routine is used to adjust delay factors that MUST be synchronized on all machines   *\n *    but should maintain a speed as close to constant as possible. Building animations are    *\n *    a good example of this.                                                                  *\n *                                                                                             *\n * INPUT:   delay -- The normal delay factor.                                                  *\n *                                                                                             *\n * OUTPUT:  Returns with the delay to use that has been modified so that a reasonably constant *\n *          rate will result.                                                                  *\n *                                                                                             *\n * WARNINGS:   This calculation is crude due to the coarse resolution that a 1/15 second timer *\n *             allows.                                                                         *\n *                                                                                             *\n *             Use of this routine ASSUMES that the GameSpeed is synchronized on all machines. *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/18/1995 JLB : Created.                                                                 *\n *   06/30/1995 JLB : Handles low values in a more consistent manner.                          *\n *=============================================================================================*/\nint OptionsClass::Normalize_Delay(int delay) const\n{\n\tstatic int _adjust[][8] = {\n\t\t{2,2,1,1,1,1,1,1},\n\t\t{3,3,3,2,2,2,1,1},\n\t\t{5,4,4,3,3,2,2,1},\n\t\t{7,6,5,4,4,4,3,2}\n\t};\n\tif (delay) {\n\t\tif (delay < 5) {\n\t\t\tdelay = _adjust[delay-1][GameSpeed];\n\t\t} else {\n\t\t\tdelay = ((delay * 8) / (GameSpeed+1));\n\t\t}\n\t}\n\treturn(delay);\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Fixup_Palette -- Adjusts the real palette to match the palette sliders.       *\n *                                                                                             *\n *    This routine is used to adjust the real palette to match the values for the palette      *\n *    control. The adjusted palette is placed into the palette buffer specified.               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The palette is not actually set by this routine.                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Fixup_Palette(void) const\n{\n\tAdjust_Palette(OriginalPalette, InGamePalette, Brightness, Saturation, Tint, Contrast);\n\tCCPalette = InGamePalette;\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Normalize_Volume -- Convert to a real volume value.                           *\n *                                                                                             *\n *    This routine will take a relative volume value and convert it to the real volume value   *\n *    to use. This allows all the game volumes to be corrected to the correct global volume.   *\n *                                                                                             *\n * INPUT:   volume   -- Requested volume level.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the actual volume level to use.                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint OptionsClass::Normalize_Volume(int volume) const\n{\n\treturn(volume * Volume);\n}\n"
  },
  {
    "path": "CODE/OPTIONS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/OPTIONS.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OPTIONS.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 8, 1994                                                 *\n *                                                                                             *\n *                  Last Update : June 8, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef OPTIONS_H\n#define OPTIONS_H\n\nclass OptionsClass {\n\tpublic:\n\t\tenum {\n\t\t\tMAX_SCROLL_SETTING=7,\n\t\t\tMAX_SPEED_SETTING=7\n\t\t};\n\n\t\tOptionsClass(void);\n\n\t\tvoid One_Time(void);\n\t\tvoid Process(void);\n\n\t\tvoid Fixup_Palette(void) const;\n\t\tvoid Set_Shuffle(int on);\n\t\tvoid Set_Repeat(int on);\n\t\tvoid Set_Score_Volume(fixed volume, bool feedback);\n\t\tvoid Set_Sound_Volume(fixed volume, bool feedback);\n\t\tvoid Set_Brightness(fixed brightness);\n\t\tfixed Get_Brightness(void) const;\n\t\tvoid Set_Saturation(fixed color);\n\t\tfixed Get_Saturation(void) const;\n\t\tvoid Set_Contrast(fixed contrast);\n\t\tfixed Get_Contrast(void) const;\n\t\tvoid Set_Tint(fixed tint);\n\t\tfixed Get_Tint(void) const;\n\t\tint Normalize_Delay(int delay) const;\n\t\tint Normalize_Volume(int volume) const;\n\n\t\t/*\n\t\t** File I/O routines\n\t\t*/\n\t\tvoid Load_Settings(void);\n\t\tvoid Save_Settings(void);\n\n\t\tvoid Set(void);\n\n\t\t/*\n\t\t**\tThis is actually the delay between game frames expressed as 1/60 of\n\t\t**\ta second. The default value is 4 (1/15 second).\n\t\t*/\n\t\tunsigned int GameSpeed;\n\n\t\tint ScrollRate;\t\t// Distance to scroll.\n\t\tfixed Volume;\t\t\t// Volume for sound effects.\n\t\tfixed ScoreVolume;\t// Volume for scores.\n#ifdef FIXIT_VERSION_3\n\t\tfixed MultiScoreVolume;\t\t//\tVolume for scores during multiplayer games.\n#endif\n\t\tfixed Brightness;\t\t// Brightness.\n\t\tfixed Tint;\t\t\t\t// Hue\n\t\tfixed Saturation;\t\t// Saturation\n\t\tfixed Contrast;\t\t// Value\n\t\tunsigned AutoScroll:1;\t\t// Does map autoscroll?\n\t\tunsigned IsScoreRepeat:1;\t// Score should repeat?\n\t\tunsigned IsScoreShuffle:1;\t// Score list should shuffle?\n\t\tunsigned IsPaletteScroll:1;// Allow palette scrolling?\n\n\t\t/*\n\t\t**\tThese are the hotkeys used for keyboard control.\n\t\t*/\n\t\tKeyNumType KeyForceMove1;\n\t\tKeyNumType KeyForceMove2;\n\t\tKeyNumType KeyForceAttack1;\n\t\tKeyNumType KeyForceAttack2;\n\t\tKeyNumType KeySelect1;\n\t\tKeyNumType KeySelect2;\n\t\tKeyNumType KeyScatter;\n\t\tKeyNumType KeyStop;\n\t\tKeyNumType KeyGuard;\n\t\tKeyNumType KeyNext;\n\t\tKeyNumType KeyPrevious;\n\t\tKeyNumType KeyFormation;\n\t\tKeyNumType KeyHome1;\n\t\tKeyNumType KeyHome2;\n\t\tKeyNumType KeyBase;\n\t\tKeyNumType KeyResign;\n\t\tKeyNumType KeyAlliance;\n\t\tKeyNumType KeyBookmark1;\n\t\tKeyNumType KeyBookmark2;\n\t\tKeyNumType KeyBookmark3;\n\t\tKeyNumType KeyBookmark4;\n\t\tKeyNumType KeySelectView;\n\t\tKeyNumType KeyRepair;\n\t\tKeyNumType KeyRepairOn;\n\t\tKeyNumType KeyRepairOff;\n\t\tKeyNumType KeySell;\n\t\tKeyNumType KeySellOn;\n\t\tKeyNumType KeySellOff;\n\t\tKeyNumType KeyMap;\n\t\tKeyNumType KeySidebarUp;\n\t\tKeyNumType KeySidebarDown;\n\t\tKeyNumType KeyOption1;\n\t\tKeyNumType KeyOption2;\n\t\tKeyNumType KeyScrollLeft;\n\t\tKeyNumType KeyScrollRight;\n\t\tKeyNumType KeyScrollUp;\n\t\tKeyNumType KeyScrollDown;\n\t\tKeyNumType KeyQueueMove1;\n\t\tKeyNumType KeyQueueMove2;\n\t\tKeyNumType KeyTeam1;\n\t\tKeyNumType KeyTeam2;\n\t\tKeyNumType KeyTeam3;\n\t\tKeyNumType KeyTeam4;\n\t\tKeyNumType KeyTeam5;\n\t\tKeyNumType KeyTeam6;\n\t\tKeyNumType KeyTeam7;\n\t\tKeyNumType KeyTeam8;\n\t\tKeyNumType KeyTeam9;\n\t\tKeyNumType KeyTeam10;\n\n\t\tvoid Adjust_Palette(PaletteClass const & oldpal, PaletteClass & newpal, fixed brightness, fixed color, fixed tint, fixed contrast) const;\n\tprotected:\n\n\tprivate:\n\n\t\tstatic char const * const HotkeyName;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/OPTIONS.LNT",
    "content": "// Please note -- this is a representative set of error suppression\n//                options.  Please adjust to suit your own policies\n//                See PC-lint for C/C++ manual (chapter LIVING WITH LINT)\n//                for further details.\n\n-e502 -e713 -e737 -eau  // don't report on signed/unsigned mismatches\n-e734                   // allow sub-integer loss of information\n-e701 -e703             // shifting int left is OK\n-e537                   // don't care about repeated include file\n-e641                   // converting enum to int is ok\n-e1042                  // operator ++/-- don't need class parameters\n-e963 -e763             // redundant declarations are ok\n-e1712                  // no default constructor defined is ok\n-e1704                  // private constructors are ok\n-e534                   // ignoring return value is ok\n-e732                   // going from signed to unsigned parameter is ok\n-e1411                  // functions hiding base functions is ok\n-e788                   // switch with default doesn't need all values specified\n-e655 -e656             // compatable enum bit and arithmetic operations are ok\n-e1542                  // members possibly not initialized isn't a valid warning\n-e522                   // calling 'new' without assignment isn't always an error\n\n\n-e1401 // uninitialized by constructor warning disabled.\n\n\n"
  },
  {
    "path": "CODE/OVERLAY.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/OVERLAY.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OVERLAY.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 17, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 24, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   OverlayClass::Read_INI -- Reads the overlay data from an INI file.                        *\n *   OverlayClass::Init -- Resets the overlay object system.                                   *\n *   OverlayClass::Mark -- Marks the overlay down on the map.                                  *\n *   OverlayClass::OverlayClass -- Overlay object constructor.                                 *\n *   OverlayClass::delete -- Returns a overlay object to the pool.                             *\n *   OverlayClass::new -- Allocates a overlay object from pool                                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"overlay.h\"\n\n\nHousesType OverlayClass::ToOwn = HOUSE_NONE;\n\n\n\n/***********************************************************************************************\n * OverlayClass::Init -- Resets the overlay object system.                                     *\n *                                                                                             *\n *    This routine resets the overlay object system. It is called                              *\n *    prior to loading a new scenario.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OverlayClass::Init(void)\n{\n\tOverlays.Free_All();\n}\n\n\n/***********************************************************************************************\n * OverlayClass::new -- Allocates a overlay object from pool                                   *\n *                                                                                             *\n *    This routine is used to allocate a overlay object from the                               *\n *    overlay object pool.                                                                     *\n *                                                                                             *\n * INPUT:   size  -- The size of a overlay object (not used).                                  *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to an available overlay object.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * OverlayClass::operator new(size_t )\n{\n\tvoid * ptr = Overlays.Allocate();\n\tif (ptr) {\n\t\t((OverlayClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * OverlayClass::delete -- Returns a overlay object to the pool.                               *\n *                                                                                             *\n *    This routine will return a overlay object to the overlay object                          *\n *    pool. A overlay so returned is available for allocation again.                           *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the object to be returned.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OverlayClass::operator delete(void * ptr)\n{\n\tif (ptr) {\n\t\t((OverlayClass *)ptr)->IsActive = false;\n\t}\n\tOverlays.Free((OverlayClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * OverlayClass::OverlayClass -- Overlay object constructor.                                   *\n *                                                                                             *\n *    This is the constructor for a overlay object.                                            *\n *                                                                                             *\n * INPUT:   type  -- The overlay object this is to become.                                     *\n *                                                                                             *\n *          pos   -- The position on the map to place the object.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nOverlayClass::OverlayClass(OverlayType type, CELL pos, HousesType house) :\n\tObjectClass(RTTI_OVERLAY, Overlays.ID(this)),\n\tClass(OverlayTypes.Ptr((int)type))\n{\n\tif (pos != -1) {\n\t\tToOwn = house;\n\t\tUnlimbo(Cell_Coord(pos));\n\t\tToOwn = HOUSE_NONE;\n\t}\n}\n\n\n/***********************************************************************************************\n * OverlayClass::Mark -- Marks the overlay down on the map.                                    *\n *                                                                                             *\n *    This routine will place the overlay onto the map. The overlay object is deleted by this  *\n *    operation. The map is updated to reflect the presence of the overlay.                    *\n *                                                                                             *\n * INPUT:   mark  -- The type of marking to perform. Only MARK_DOWN is supported.              *\n *                                                                                             *\n * OUTPUT:  bool; Was the overlay successfully marked? Failure occurs if it is not being       *\n *                marked down.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *   12/23/1994 JLB : Checks low level legality before proceeding.                             *\n *=============================================================================================*/\nbool OverlayClass::Mark(MarkType mark)\n{\n\tassert(Overlays.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (ObjectClass::Mark(mark)) {\n\t\tif (mark == MARK_DOWN) {\n\t\t\tCELL\tcell = Coord_Cell(Coord);\n\t\t\tCellClass * cellptr = &Map[cell];\n\n\t\t\t/*\n\t\t\t**\tWalls have special logic when they are marked down.\n\t\t\t*/\n\t\t\tif (Class->IsWall) {\n\t\t\t\tif (cellptr->Is_Clear_To_Build()) {\n\t\t\t\t\tcellptr->Overlay = Class->Type;\n\t\t\t\t\tcellptr->OverlayData = 0;\n\t\t\t\t\tcellptr->Redraw_Objects();\n\t\t\t\t\tcellptr->Wall_Update();\n\t\t\t\t\tMap.Zone_Reset(Class->IsCrushable ? MZONE_NORMAL : MZONE_NORMAL|MZONE_CRUSHER);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tFlag ownership of the cell if the 'global' ownership flag indicates that this\n\t\t\t\t\t**\tis necessary for the overlay.\n\t\t\t\t\t*/\n\t\t\t\t\tif (ToOwn != HOUSE_NONE) {\n\t\t\t\t\t\tcellptr->Owner = ToOwn;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tdelete this;\n\t\t\t\t\treturn(false);\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\tbool clear = false;\n\t\t\t\tif (!ScenarioInit) {\n\t\t\t\t\tif (Class->Type == OVERLAY_WATER_CRATE) {\n\t\t\t\t\t\tclear = cellptr->Is_Clear_To_Move(SPEED_FLOAT, false, false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (Class->Type == OVERLAY_STEEL_CRATE || Class->Type == OVERLAY_WOOD_CRATE) {\n\t\t\t\t\t\t\tclear = cellptr->Is_Clear_To_Move(SPEED_TRACK, false, false);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tclear = cellptr->Is_Clear_To_Move(SPEED_TRACK, true, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tclear = true;\n\t\t\t\t}\n\n\t\t\t\tif ((ScenarioInit || cellptr->Overlay == OVERLAY_NONE) && clear) {\n\n\t\t\t\t\tcellptr->Overlay = Class->Type;\n\t\t\t\t\tcellptr->OverlayData = 0;\n\n\t\t\t\t\tcellptr->Redraw_Objects();\n\t\t\t\t\tif (Class->Land == LAND_TIBERIUM) {\n\t\t\t\t\t\tcellptr->OverlayData = 1;\n\t\t\t\t\t\tcellptr->Tiberium_Adjust();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\t*****  Is this really needed?\n\t\t\t*/\n\t\t\tcellptr->Recalc_Attributes();\n\n\t\t\t/*\n\t\t\t**\tRemove the overlay and make sure the system thinks it was never placed down!\n\t\t\t*/\n\t\t\tMap.Overlap_Up(Coord_Cell(Coord), this);\n\t\t\tIsDown = false;\n\t\t\tIsInLimbo = true;\n\n\t\t\tdelete this;\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * OverlayClass::Read_INI -- Reads the overlay data from an INI file.                          *\n *                                                                                             *\n *    This routine is used to load a scenario's overlay data. The overlay objects are read     *\n *    from the INI file and then created on the map.                                           *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the INI file staging buffer.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Requires that all the buildings be placed first, so the scan for assigning wall *\n *             ownership to the nearest building will work.                                    *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *   07/24/1995 JLB : Specifically forbid manual crates in multiplayer scenarios.              *\n *=============================================================================================*/\nvoid OverlayClass::Read_INI(CCINIClass & ini)\n{\n\tif (NewINIFormat > 1) {\n\t\tint len = ini.Get_UUBlock(\"OverlayPack\", _staging_buffer, sizeof(_staging_buffer));\n\n\t\tif (len > 0) {\n\t\t\tBufferStraw bpipe(_staging_buffer, len);\n\t\t\tLCWStraw uncomp(LCWStraw::DECOMPRESS);\n\t\t\tuncomp.Get_From(&bpipe);\n\n\t\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\tOverlayType classid;\n\n\t\t\t\tuncomp.Get(&classid, sizeof(classid));\n\n\t\t\t\tif (classid != OVERLAY_NONE) {\n\n\t\t\t\t\tif (Session.Type == GAME_NORMAL || !OverlayTypeClass::As_Reference(classid).IsCrate) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDon't allow placement of overlays on the top or bottom rows of\n\t\t\t\t\t\t**\tthe map.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (cell >= MAP_CELL_W && cell <= MAP_CELL_TOTAL - MAP_CELL_W) {\n\t\t\t\t\t\t\tnew OverlayClass(classid, cell);\n\n\t\t\t\t\t\t\t// Assign house ownership to cells with walls in 'em.\n\t\t\t\t\t\t\tif (OverlayTypeClass::As_Reference(classid).IsWall) {\n\t\t\t\t\t\t\t\tHousesType owner = HOUSE_NONE;\n\t\t\t\t\t\t\t\tint distance = 0x7FFFFFFF;\n\t\t\t\t\t\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\t\t\t\t\tBuildingClass * building = Buildings.Ptr(index);\n\t\t\t\t\t\t\t\t\tint newdist = ::Distance(building->Center_Coord(), Cell_Coord(cell));\n\t\t\t\t\t\t\t\t\tif (newdist < distance) {\n\t\t\t\t\t\t\t\t\t\tdistance = newdist;\n\t\t\t\t\t\t\t\t\t\towner = building->Owner();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tMap[cell].Owner = owner;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (NewINIFormat < 2 || ini.Is_Present(\"Overlay\")) {\n\t\tint len = ini.Entry_Count(INI_Name());\n\t\tfor (int index = 0; index < len; index++) {\n\t\t\tchar const * entry = ini.Get_Entry(INI_Name(), index);\n\t\t\tCELL cell = atoi(entry);\n\t\t\tOverlayType classid = ini.Get_OverlayType(INI_Name(), entry, OVERLAY_NONE);\n\n\t\t\t/*\n\t\t\t**\tDon't allow placement of crates in the multiplayer scenarios.\n\t\t\t*/\n\t\t\tif (classid != OVERLAY_NONE && (Session.Type == GAME_NORMAL || !OverlayTypeClass::As_Reference(classid).IsCrate)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDon't allow placement of overlays on the top or bottom rows of\n\t\t\t\t**\tthe map.\n\t\t\t\t*/\n\t\t\t\tif (cell >= MAP_CELL_W && cell <= MAP_CELL_TOTAL - MAP_CELL_W) {\n\t\t\t\t\tnew OverlayClass(classid, cell);\n\n\t\t\t\t\t// Assign house ownership to cells with walls in 'em.\n\t\t\t\t\tif (OverlayTypeClass::As_Reference(classid).IsWall) {\n\t\t\t\t\t\tHousesType owner = HOUSE_NONE;\n\t\t\t\t\t\tint distance = 0x7FFFFFFF;\n\t\t\t\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\t\t\tBuildingClass * building = Buildings.Ptr(index);\n\t\t\t\t\t\t\tint newdist = ::Distance(building->Center_Coord(), Cell_Coord(cell));\n\t\t\t\t\t\t\tif (newdist < distance) {\n\t\t\t\t\t\t\t\tdistance = newdist;\n\t\t\t\t\t\t\t\towner = building->Owner();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tMap[cell].Owner = owner;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nvoid OverlayClass::Write_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tFirst, clear out all existing unit data from the ini file.\n\t*/\n\tini.Clear(INI_Name());\n\tini.Clear(\"OverlayPack\");\n\n\tBufferPipe bpipe(_staging_buffer, sizeof(_staging_buffer));\n\tLCWPipe comppipe(LCWPipe::COMPRESS);\n\n\tcomppipe.Put_To(&bpipe);\n\n\tint total = 0;\n\tCellClass * cellptr = &Map[(CELL)0];\n\tfor (CELL index = 0; index < MAP_CELL_TOTAL; index++) {\n\t\ttotal += comppipe.Put(&cellptr->Overlay, sizeof(cellptr->Overlay));\n\t\tcellptr++;\n\t}\n\tif (total) {\n\t\tini.Put_UUBlock(\"OverlayPack\", _staging_buffer, total);\n\t}\n\n//\tfor (CELL index = 0; index < MAP_CELL_TOTAL; index++) {\n//\t\tCellClass * cellptr = &Map[index];\n//\t\tif (cellptr->Overlay != OVERLAY_NONE) {\n//\t\t\tchar\tuname[10];\n//\t\t\tsprintf(uname, \"%d\", index);\n//\t\t\tini.Put_Overlay(INI_Name(), uname, cellptr->Overlay);\n//\t\t}\n//\t}\n}\n"
  },
  {
    "path": "CODE/OVERLAY.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/OVERLAY.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OVERLAY.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 17, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 17, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef OVERLAY_H\n#define OVERLAY_H\n\n#include\t\"object.h\"\n#include\t\"type.h\"\n\n/******************************************************************************\n**\tThis class controls the overlay object. Overlay objects function congruously\n**\tto carpet on a floor. They have no depth, but merely control the icon to be rendered\n**\tas the cell's bottom most layer.\n*/\nclass OverlayClass : public ObjectClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis is a pointer to the overlay object's class.\n\t\t*/\n\t\tCCPtr<OverlayTypeClass> Class;\n\n\t\t/*-------------------------------------------------------------------\n\t\t**\tConstructors and destructors.\n\t\t*/\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\t\tOverlayClass(OverlayType type, CELL pos=-1, HousesType = HOUSE_NONE);\n\t\tOverlayClass(NoInitClass const & x) : ObjectClass(x), Class(x) {};\n\t\tvirtual ~OverlayClass(void) {if (GameActive) OverlayClass::Limbo();Class=0;};\n\t\toperator OverlayType(void) const {return Class->Type;};\n\n\t\tstatic void Init(void);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tstatic void Read_INI(CCINIClass & ini);\n\t\tstatic void Write_INI(CCINIClass & ini);\n\t\tstatic char *INI_Name(void) {return \"OVERLAY\";};\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\n\t\t/*\n\t\t**\tVirtual support functionality.\n\t\t*/\n\t\tvirtual bool Mark(MarkType);\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const {return *Class;};\n\t\tvirtual void Draw_It(int , int , WindowNumberType ) const {};\n\n\tprivate:\n\t\t/*\n\t\t**\tThis is used to control the marking process of the overlay. If this is\n\t\t**\tset to a valid house number, then the cell that the overlay is marked down\n\t\t**\tupon will be flagged as being owned by the specified house.\n\t\t*/\n\t\tstatic HousesType ToOwn;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/PACKET.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Auto Registration App           *\n *                                                                         *\n *                    File Name : PACKET.CPP                               *\n *                                                                         *\n *                   Programmer : Philip W. Gorrow                         *\n *                                                                         *\n *                   Start Date : 04/22/96                                 *\n *                                                                         *\n *                  Last Update : April 24, 1996 [PWG]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   *PacketClass::Find_Field -- Finds a field if it exists in the packets *\n *   Get_Field -- Find specified name and returns data                     *\n *   PacketClass::~PacketClass -- destroys a packet class be freeing list  *\n *   PacketClass::Add_Field -- Adds a FieldClass entry to head of packet li*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include <stdlib.h>\n#include <mem.h>\n#include <string.h>\n\nenum {false=0,true=1};\ntypedef int bool;\n\n#include \"packet.h\"\n\n\n/**************************************************************************\n * PACKETCLASS::~PACKETCLASS -- destroys a packet class be freeing list   *\n *                                                                        *\n * INPUT:\t\tnone                                                       *\n *                                                                        *\n * OUTPUT:     none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/24/1996 PWG : Created.                                            *\n *========================================================================*/\nPacketClass::~PacketClass(void)\n{\n\tFieldClass *current;\n\tFieldClass *next;\n\t//\n\t// Loop through the entire field list and delete each entry.\n\t//\n\tfor (current = Head; current; current = next) {\n\t\tnext = current->Next;\n\t\tdelete current;\n\t}\n}\n\n\n/**************************************************************************\n * PACKETCLASS::ADD_FIELD -- Adds a FieldClass entry to head of packet li *\n *                                                                        *\n * INPUT:\t\tFieldClass * - a properly constructed field class entry.\t  *\n *                                                                        *\n * OUTPUT:     none                                                       *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/24/1996 PWG : Created.                                            *\n *========================================================================*/\nvoid PacketClass::Add_Field(FieldClass *field)\n{\n\tfield->Next = Head;\n\tHead = field;\n}\n\n/**************************************************************************\n * PACKETCLASS::PACKETCLASS -- Creates a Packet object from a COMMS packe *\n *                                                                        *\n * INPUT:                                                                 *\n *                                                                        *\n * OUTPUT:                                                                *\n *                                                                        *\n * WARNINGS:                                                              *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/22/1996 PWG : Created.                                            *\n *========================================================================*/\nPacketClass::PacketClass(char *curbuf)\n{\n\tint remaining_size;\n\t//\n\t// Pull the size and packet ID out of the linear packet stream.\n\t//\n\tSize = *(unsigned short *)curbuf;\n\tcurbuf += sizeof (unsigned short);\n\tSize = ntohs(Size);\n\tID\t  = *(short *)curbuf;\n\tcurbuf += sizeof (short);\n\tID   = ntohs(ID);\n\tHead = NULL;\n\n\t//\n\t// Calculate the remaining size so that we can loop through the\n\t//   packets and extract them.\n\t//\n\tremaining_size = Size - 4;\n\n\t//\n\t// Loop through the linear packet until we run out of room and\n\t// create a field for each.\n\t//\n\twhile (remaining_size > 0) {\n\t\tFieldClass *field = new FieldClass;\n\n\t\t//\n\t\t// Copy the adjusted header into the buffer and then advance the buffer\n\t\t//\n\t\tmemcpy(field, curbuf, FIELD_HEADER_SIZE);\n\t\tcurbuf += FIELD_HEADER_SIZE;\n\t\tremaining_size   -= FIELD_HEADER_SIZE;\n\n\t\t//\n\t\t// Copy the data into the buffer\n\t\t//\n\t\tint size\t\t\t= ntohs(field->Size);\n\t\tfield->Data\t\t= new char[size];\n\t\tmemcpy(field->Data, curbuf, size);\n\t\tcurbuf\t\t\t+= size;\n\t\tremaining_size\t-= size;\n\t\t//\n\t\t// Make sure we allow for the pad bytes.\n\t\t//\n\t\tint pad = (4 - (ntohs(field->Size) & 3)) & 3;\n\t\tcurbuf += pad;\n\t\tremaining_size   -= pad;\n\n\t\t//\n\t\t// Convert the field back to the host format\n\t\t//\n\t\tfield->Net_To_Host();\n\n\t\t//\n\t\t// Finally add the field to the field list in the packet\n\t\t// structure.\n\t\t//\n\t\tAdd_Field(field);\n\t}\n}\n\n/**************************************************************************\n * CREATE_COMMS_PACKET -- Walks field list creating a packet              *\n *                                                                        *\n * INPUT:\t\tshort - the id of the packet so the server can identify it *\n *\t\t\t\t\tunsigned short & - the size of the packet returned here    *\n *                                                                        *\n * OUTPUT:     void * pointer to the linear packet data                   *\n *                                                                        *\n * WARNINGS: \tThis routine allocates memory that the user is responsible *\n *  \t\t\t\tfor freeing.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/22/1996 PWG : Created.                                            *\n *========================================================================*/\nchar *PacketClass::Create_Comms_Packet(int &size)\n{\n\tFieldClass *current;\n\n\t//\n\t// Size starts at four because that is the size of the packet header.\n\t//\n\tsize = 4;\n\n\t//\n\t// Take a quick spin through and calculate the size of the packet we\n\t//   are building.\n\t//\n\tfor (current = Head; current; current=current->Next) {\n\t\tsize += (unsigned short)FIELD_HEADER_SIZE;\t\t\t// add in packet header size\n\t\tsize += current->Size;\t\t\t\t// add in data size\n\t\tsize += (4 - (size & 3)) & 3; \t// add in pad value to dword align next packet\n\t}\n\n\t//\n\t// Now that we know the size allocate a buffer big enough to hold the\n\t// packet.\n\t//\n\tchar *retval = new char[size];\n\tchar *curbuf = retval;\n\n\t//\n\t// write the size into the packet header\n\t//\n\t*(unsigned short *)curbuf = (unsigned short)htons((unsigned short)size);\n\tcurbuf += sizeof (unsigned short);\n\t*(short *)curbuf = htons(ID);\n\tcurbuf += sizeof (short);\n\n\t//\n\t// Ok now that the actual header information has been written we need to write out\n\t// field information.\n\t//\n\tfor (current = Head; current; current = current->Next) {\n\t\t//\n\t\t// Temporarily convert the packet to net format (this saves alot of\n\t\t//   effort, and seems safe...)\n\t\t//\n\t\tcurrent->Host_To_Net();\n\n\t\t//\n\t\t// Copy the adjusted header into the buffer and then advance the buffer\n\t\t//\n\t\tmemcpy(curbuf, current, FIELD_HEADER_SIZE);\n\t\tcurbuf += FIELD_HEADER_SIZE;\n\n\t\t//\n\t\t// Copy the data into the buffer and then advance the buffer\n\t\t//\n\t\tmemcpy(curbuf, current->Data, ntohs(current->Size));\n\t\tcurbuf += ntohs(current->Size);\n\n\t\t//\n\t\t// Finally take care of any pad bytes by setting them to 0\n\t\t//\n\t\tint pad = (4 - (ntohs(current->Size) & 3)) & 3;\n\n\t\t//\n\t\t//\tIf there is any pad left over, make sure you memset it\n\t\t// to zeros, so it looks like a pad.\n\t\t//\n\t\tif (pad) {\n\t\t\tmemset(curbuf, 0, pad);\n\t\t\tcurbuf += pad;\n\t\t}\n\n\t\tcurrent->Net_To_Host();\n\t}\n\treturn(retval);\n}\n\n\n/**************************************************************************\n * PACKETCLASS::FIND_FIELD -- Finds a field if it exists in the packets   *\n *                                                                        *\n * INPUT:\t\tchar *  - the id of the field we are looking for.\t\t\t  *\n *                                                                        *\n * OUTPUT:     FieldClass * pointer to the field class                    *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/23/1996 PWG : Created.                                            *\n *========================================================================*/\nFieldClass *PacketClass::Find_Field(char *id)\n{\n\tfor (FieldClass *current = Head; current; current = current->Next) {\n\t\tif ( strncmp(id, current->ID, 4) == 0)\n\t\t\treturn current;\n\t}\n\treturn NULL;\n}\n\n\n/**************************************************************************\n * GET_FIELD -- Find specified name and returns data                      *\n *                                                                        *\n * INPUT:\t\tchar *   - the id of the field that holds the data.\t\t  *\n *\t\t\t\t\tchar &   - the reference to store the data into\t\t\t\t  *\n *                                                                        *\n * OUTPUT:\t\ttrue if the field was found, false if it was not.\t\t\t  *\n *                                                                        *\n * WARNINGS:\tThe data reference is not changed if the field is not\t\t  *\n *\t\t\t\t\tfound.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/23/1996 PWG : Created.                                            *\n *========================================================================*/\nbool PacketClass::Get_Field(char *id, char &data)\n{\n\tFieldClass *field = Find_Field(id);\n\tif (field) {\n\t\tdata = *((char *)field->Data);\n\t}\n\treturn((field) ? true : false);\n}\n\n\n/**************************************************************************\n * GET_FIELD -- Find specified name and returns data                      *\n *                                                                        *\n * INPUT:\t\tchar *   - the id of the field that holds the data.\t\t  *\n *\t\t\t\t\tunsigned char &   - the reference to store the data into\t  *\n *                                                                        *\n * OUTPUT:\t\ttrue if the field was found, false if it was not.\t\t\t  *\n *                                                                        *\n * WARNINGS:\tThe data reference is not changed if the field is not\t\t  *\n *\t\t\t\t\tfound.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/23/1996 PWG : Created.                                            *\n *========================================================================*/\nbool PacketClass::Get_Field(char *id, unsigned char &data)\n{\n\tFieldClass *field = Find_Field(id);\n\tif (field) {\n\t\tdata = *((unsigned char *)field->Data);\n\t}\n\treturn((field) ? true : false);\n}\n\n\n/**************************************************************************\n * GET_FIELD -- Find specified name and returns data                      *\n *                                                                        *\n * INPUT:\t\tchar *   - the id of the field that holds the data.\t\t  *\n *\t\t\t\t\tshort &   - the reference to store the data into\t        *\n *                                                                        *\n * OUTPUT:\t\ttrue if the field was found, false if it was not.\t\t\t  *\n *                                                                        *\n * WARNINGS:\tThe data reference is not changed if the field is not\t\t  *\n *\t\t\t\t\tfound.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/23/1996 PWG : Created.                                            *\n *========================================================================*/\nbool PacketClass::Get_Field(char *id, short &data)\n{\n\tFieldClass *field = Find_Field(id);\n\tif (field) {\n\t\tdata = *((short *)field->Data);\n\t}\n\treturn((field) ? true : false);\n}\n\n\n/**************************************************************************\n * GET_FIELD -- Find specified name and returns data                      *\n *                                                                        *\n * INPUT:\t\tchar *   - the id of the field that holds the data.\t\t  *\n *\t\t\t\t\tunsigned short &   - the reference to store the data into  *\n *                                                                        *\n * OUTPUT:\t\ttrue if the field was found, false if it was not.\t\t\t  *\n *                                                                        *\n * WARNINGS:\tThe data reference is not changed if the field is not\t\t  *\n *\t\t\t\t\tfound.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/23/1996 PWG : Created.                                            *\n *========================================================================*/\nbool PacketClass::Get_Field(char *id, unsigned short &data)\n{\n\tFieldClass *field = Find_Field(id);\n\tif (field) {\n\t\tdata = *((unsigned short *)field->Data);\n\t}\n\treturn((field) ? true : false);\n}\n\n\n/**************************************************************************\n * GET_FIELD -- Find specified name and returns data                      *\n *                                                                        *\n * INPUT:\t\tchar *   - the id of the field that holds the data.\t\t  *\n *\t\t\t\t\tlong &   - the reference to store the data into  \t\t\t  *\n *                                                                        *\n * OUTPUT:\t\ttrue if the field was found, false if it was not.\t\t\t  *\n *                                                                        *\n * WARNINGS:\tThe data reference is not changed if the field is not\t\t  *\n *\t\t\t\t\tfound.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/23/1996 PWG : Created.                                            *\n *========================================================================*/\nbool PacketClass::Get_Field(char *id, long &data)\n{\n\tFieldClass *field = Find_Field(id);\n\tif (field) {\n\t\tdata = *((long *)field->Data);\n\t}\n\treturn((field) ? true : false);\n}\n\n/**************************************************************************\n * GET_FIELD -- Find specified name and returns data as a string          *\n *                                                                        *\n * INPUT:\t\tchar *   - the id of the field that holds the data.\t\t  *\n *\t\t\t\t\tchar *   - the string to store the data into\t\t\t\t\t  *\n *                                                                        *\n * OUTPUT:\t\ttrue if the field was found, false if it was not.\t\t\t  *\n *                                                                        *\n * WARNINGS:\tThe string is not changed if the field is not found.  It   *\n *\t\t\t\t\tis assumed that the string variabled specified by the      *\n *\t\t\t\t\tpointer is large enough to hold the data.\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/23/1996 PWG : Created.                                            *\n *========================================================================*/\nbool PacketClass::Get_Field(char *id, char *data)\n{\n\tFieldClass *field = Find_Field(id);\n\tif (field) {\n\t\tstrcpy(data, (char *)field->Data);\n\t}\n\treturn((field) ? true : false);\n}\n\n/**************************************************************************\n * GET_FIELD -- Find specified name and returns data                      *\n *                                                                        *\n * INPUT:\t\tchar *   - the id of the field that holds the data.\t\t  *\n *\t\t\t\t\tunsigned long &   - the reference to store the data into   *\n *                                                                        *\n * OUTPUT:\t\ttrue if the field was found, false if it was not.\t\t\t  *\n *                                                                        *\n * WARNINGS:\tThe data reference is not changed if the field is not\t\t  *\n *\t\t\t\t\tfound.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/23/1996 PWG : Created.                                            *\n *========================================================================*/\nbool PacketClass::Get_Field(char *id, unsigned long &data)\n{\n\tFieldClass *field = Find_Field(id);\n\tif (field) {\n\t\tdata = *((unsigned long *)field->Data);\n\t}\n\treturn((field) ? true : false);\n}\n\n\n/**************************************************************************\n * GET_FIELD -- Find specified name and returns data                      *\n *                                                                        *\n * INPUT:\t\tchar *   - the id of the field that holds the data.\t\t    *\n *\t\t\t\tvoid * - the reference to store the data into                *\n *           int    - the length of the buffer passed in                  *\n *                                                                        *\n * OUTPUT:\t\ttrue if the field was found, false if it was not.\t\t\t *\n *                                                                        *\n * WARNINGS:\tThe data reference is not changed if the field is not\t\t    *\n *\t\t\t\t\tfound.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t *\n *                                                                        *\n * HISTORY:                                                               *\n *   6/4/96 4:46PM ST : Created                                           *\n *========================================================================*/\nbool PacketClass::Get_Field(char *id, void *data, int &length)\n{\n\tFieldClass *field = Find_Field(id);\n\tif (field) {\n\t\tmemcpy (data, field->Data, min(field->Size, length));\n\t\tlength = (int) field->Size;\n\t}\n\treturn((field) ? true : false);\n}\n"
  },
  {
    "path": "CODE/PACKET.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Auto Registration App           *\n *                                                                         *\n *                    File Name : PACKET.H                                 *\n *                                                                         *\n *                   Programmer : Philip W. Gorrow                         *\n *                                                                         *\n *                   Start Date : 04/19/96                                 *\n *                                                                         *\n *                  Last Update : April 19, 1996 [PWG]                     *\n *                                                                         *\n * This header defines the functions for the PacketClass.  The packet      *\n * class is used to create a linked list of field entries which can be     *\n * converted to a linear packet in a COMMS API compatible format.          *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Packets can be created empty and then have fields added to them or can  *\n * be created from an existing linear packet.  \t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef __PACKET_H\n#define __PACKET_H\n\n\n#include \"field.h\"\n\nclass PacketClass {\n\tpublic:\n\t\tPacketClass(short id = 0)\n\t\t{\n\t\t\tSize \t\t\t= 0;\n\t\t\tID\t\t\t\t= id;\n\t\t\tHead\t\t\t= 0;\n\t\t}\n\t\tPacketClass(char *cur_buf);\n\t\t~PacketClass(void);\n\n\t\t//\n\t\t// This function allows us to add a field to the start of the list.  As the field is just\n\t\t//   a big linked list it makes no difference which end we add a member to.\n\t\t//\n\t\tvoid Add_Field(FieldClass *field);\n\n\t\t//\n\t\t// These conveniance functions allow us to add a field directly to the list without\n\t\t// having to worry about newing one first.\n\t\t//\n\t\tvoid Add_Field(char *field, char data) {Add_Field(new FieldClass(field, data));};\n\t\tvoid Add_Field(char *field, unsigned char data) {Add_Field(new FieldClass(field, data));};\n\t\tvoid Add_Field(char *field, short data) {Add_Field(new FieldClass(field, data));};\n\t\tvoid Add_Field(char *field, unsigned short data) {Add_Field(new FieldClass(field, data));};\n\t\tvoid Add_Field(char *field, long data) {Add_Field(new FieldClass(field, data));};\n\t\tvoid Add_Field(char *field, unsigned long data) {Add_Field(new FieldClass(field, data));};\n\t\tvoid Add_Field(char *field, char *data) {Add_Field(new FieldClass(field, data));};\n\t\tvoid Add_Field(char *field, void *data, int length) {Add_Field(new FieldClass(field, data, length));};\n\n\t\t//\n\t\t// These functions search for a field of a given name in the list and\n\t\t// return the data via a reference value.\n\t\t//\n\t\tFieldClass *Find_Field(char *id);\n\t\tbool Get_Field(char *id, char &data);\n\t\tbool Get_Field(char *id, unsigned char &data);\n\t\tbool Get_Field(char *id, short &data);\n\t\tbool Get_Field(char *id, unsigned short &data);\n\t\tbool Get_Field(char *id, long &data);\n\t\tbool Get_Field(char *id, unsigned long &data);\n\t\tbool Get_Field(char *id, char *data);\n\t\tbool Get_Field(char *id, void *data, int &length);\n\n\t\tchar *Create_Comms_Packet(int &size);\n\n\tprivate:\n\t\tunsigned short \tSize;\n\t\tshort \t\t\t\tID;\n\t\tFieldClass\t\t\t*Head;\n\t\tFieldClass\t\t\t*Current;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/PIPE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/PIPE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PIPE.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/29/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Pipe::Put_To -- Connect a pipe to flow data into from this pipe.                          *\n *   Pipe::Flush -- Flush all pending data out the pipe.                                       *\n *   Pipe::Put -- Feed some data through the pipe.                                             *\n *   Pipe::~Pipe -- Destructor for pipe class object.                                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"pipe.h\"\n#include\t<stddef.h>\n#include\t<string.h>\n\n\n/***********************************************************************************************\n * Pipe::~Pipe -- Destructor for pipe class object.                                            *\n *                                                                                             *\n *    This destructor will unlink itself from any other pipes that it may be chained to. In    *\n *    the process, it will flush any output it may have pending.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nPipe::~Pipe(void)\n{\n\tif (ChainTo != NULL) {\n\t\tChainTo->ChainFrom = ChainFrom;\n\t}\n\tif (ChainFrom != NULL) {\n\t\tChainFrom->Put_To(ChainTo);\n\t}\n\n\tChainFrom = NULL;\n\tChainTo = NULL;\n}\n\n\n/***********************************************************************************************\n * Pipe::Put_To -- Connect a pipe to flow data into from this pipe.                            *\n *                                                                                             *\n *    This routine will link two pipes together. The specified pipe will be fed data from      *\n *    this pipe.                                                                               *\n *                                                                                             *\n * INPUT:   pipe  -- Pointer to the pipe that data will flow to.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Pipe::Put_To(Pipe * pipe)\n{\n\tif (ChainTo != pipe) {\n\t\tif (pipe != NULL && pipe->ChainFrom != NULL) {\n\t\t\tpipe->ChainFrom->Put_To(NULL);\n\t\t\tpipe->ChainFrom = NULL;\n\t\t}\n\n\t\tif (ChainTo != NULL) {\n\t\t\tChainTo->ChainFrom = NULL;\n\t\t\tChainTo->Flush();\n\t\t}\n\n\t\tChainTo = pipe;\n\t\tif (ChainTo != NULL) {\n\t\t\tChainTo->ChainFrom = this;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Pipe::Put -- Feed some data through the pipe.                                               *\n *                                                                                             *\n *    Use this to force feed data through the pipe. It is guaranteed to accept data as fast    *\n *    as you can supply it.                                                                    *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the data to feed to this routine.                           *\n *                                                                                             *\n *          length   -- The number of bytes of data to submit.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes actually output at the other far distant final    *\n *          end of the pipe.                                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Pipe::Put(void const * source, int length)\n{\n\tif (ChainTo != NULL) {\n\t\treturn(ChainTo->Put(source, length));\n\t}\n\treturn(length);\n}\n\n\n/***********************************************************************************************\n * Pipe::Flush -- Flush all pending data out the pipe.                                         *\n *                                                                                             *\n *    Then the pipe needs to be flushed, this routine will be called. Since pipe segments      *\n *    might have internal staging buffer for the data, this routine is necessary to force      *\n *    all staging buffers to be clear. This routine is called when the pipe is being           *\n *    destroyed.                                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes output at the far distant final end of the pipe   *\n *          chain.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Pipe::Flush(void)\n{\n\tif (ChainTo != NULL) {\n\t\treturn(ChainTo->Flush());\n\t}\n\treturn(0);\n}\n\n\n"
  },
  {
    "path": "CODE/PIPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/PIPE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PIPE.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/29/96                                                     *\n *                                                                                             *\n *                  Last Update : June 29, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef PIPE_H\n#define PIPE_H\n\n#include\t<stddef.h>\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\n/*\n**\tA \"push through\" pipe interface abstract class used for such purposes as compression\n**\tand translation of data. In STL terms, this is functionally similar to an output\n**\titerator but with a few enhancements. A pipe class object that is not derived into\n**\tanother useful class serves only as a pseudo null-pipe. It will accept data but\n**\tjust throw it away but pretend that it sent it somewhere.\n*/\nclass Pipe\n{\n\tpublic:\n\t\tPipe(void) : ChainTo(0), ChainFrom(0) {}\n\t\tvirtual ~Pipe(void);\n\n\t\tvirtual int Flush(void);\n\t\tvirtual int End(void) {return(Flush());}\n\t\tvirtual void Put_To(Pipe * pipe);\n\t\tvoid Put_To(Pipe & pipe) {Put_To(&pipe);}\n\t\tvirtual int Put(void const * source, int slen);\n\n\t\t/*\n\t\t**\tPointer to the next pipe segment in the chain.\n\t\t*/\n\t\tPipe * ChainTo;\n\t\tPipe * ChainFrom;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tDisable the copy constructor and assignment operator.\n\t\t*/\n\t\tPipe(Pipe & rvalue);\n\t\tPipe & operator = (Pipe const & pipe);\n};\n\n#endif\n"
  },
  {
    "path": "CODE/PK.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/PK.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PK.CPP                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/04/96                                                     *\n *                                                                                             *\n *                  Last Update : July 10, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   PKey::Decode_Exponent -- Decodes the exponent back into the key.                          *\n *   PKey::Decode_Modulus -- Decodes the modulus value back into the key.                      *\n *   PKey::Decrypt -- Decrypt supplied cyphertext into its original plaintext.                 *\n *   PKey::Encode_Exponent -- Encode the exponent portion of the key into a buffer.            *\n *   PKey::Encode_Modulus -- Encode the modulus portion of the key.                            *\n *   PKey::Encrypt -- Encrypt blocks of plaintext.                                             *\n *   PKey::Generate -- Generate a public and private key.                                      *\n *   PKey::PKey -- Construct a key using encoded strings.                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"pk.h\"\n#include\t\"rndstraw.h\"\n\n\n/***********************************************************************************************\n * PKey::PKey -- Construct a key using encoded strings.                                        *\n *                                                                                             *\n *    This constructor will construct a key based on the encoded strings supplied.             *\n *                                                                                             *\n * INPUT:   exponent -- The encoded string for the exponent portion of the key.                *\n *                                                                                             *\n *          modulus  -- The encoded string for the modulus portion of the key.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nPKey::PKey(void const * exponent, void const * modulus)\n{\n\tModulus.DERDecode((unsigned char *)modulus);\n\tExponent.DERDecode((unsigned char *)exponent);\n\tBitPrecision = Modulus.BitCount()-1;\n}\n\n\n/***********************************************************************************************\n * PKey::Encode_Modulus -- Encode the modulus portion of the key.                              *\n *                                                                                             *\n *    This will store the modulus portion of the key into a buffer. The number of bytes        *\n *    stored into the buffer depends on the value of the key.                                  *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that will hold the encoded modulus value.        *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes stored to the buffer.                             *\n *                                                                                             *\n * WARNINGS:   Be sure that the buffer can hold the encoded bytes. This is normally around the *\n *             same size as the Crypt_Block_Size() (plus a byte or two).                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKey::Encode_Modulus(void * buffer) const\n{\n\tif (buffer == NULL) {\n\t\treturn(0);\n\t}\n\treturn(Modulus.DEREncode((unsigned char *)buffer));\n}\n\n\n/***********************************************************************************************\n * PKey::Encode_Exponent -- Encode the exponent portion of the key into a buffer.              *\n *                                                                                             *\n *    This routine will encode the exponent portion of the key. This is only necessary for the *\n *    slow key since the fast key always has an exponent of 65537.                             *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that will be filled with the encoded exponent.   *\n *                                                                                             *\n * OUTPUT:  Returns with the nuber of bytes stored into the buffer.                            *\n *                                                                                             *\n * WARNINGS:   Be sure the buffer is big enough to hold the encoded exponent. Usually this is  *\n *             about the same size as the Crypt_Block_Size (plus a byte or two).               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKey::Encode_Exponent(void * buffer) const\n{\n\tif (buffer == NULL) {\n\t\treturn(0);\n\t}\n\treturn(Exponent.DEREncode((unsigned char *)buffer));\n}\n\n\n/***********************************************************************************************\n * PKey::Decode_Modulus -- Decodes the modulus value back into the key.                        *\n *                                                                                             *\n *    This is the counterpart to the Encode_Modulus() function. It will initialize the         *\n *    modulus portion of the key with the encoded data supplied.                               *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that holds the previously encoded modulus value. *\n *                                                                                             *\n * OUTPUT:  void                                                                               *\n *                                                                                             *\n * WARNINGS:   void                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PKey::Decode_Modulus(void * buffer)\n{\n\tModulus.DERDecode((unsigned char *)buffer);\n\tBitPrecision = Modulus.BitCount()-1;\n}\n\n\n/***********************************************************************************************\n * PKey::Decode_Exponent -- Decodes the exponent back into the key.                            *\n *                                                                                             *\n *    This is the counterpart to the Encode_Exponent function. It will decode a previously     *\n *    encoded exponent portion back into the key.                                              *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that holds the encoded exponent value.           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PKey::Decode_Exponent(void * buffer)\n{\n\tExponent.DERDecode((unsigned char *)buffer);\n}\n\n\n/***********************************************************************************************\n * PKey::Generate -- Generate a public and private key.                                        *\n *                                                                                             *\n *    Public key cryptography relies on having two paired keys. The key used to encrypt        *\n *    data must be decrypted by using the other key. Which key designated as the public or     *\n *    private key is arbitrary. However, one is faster than the other. Use the faster key for  *\n *    the more common operation.                                                               *\n *                                                                                             *\n * INPUT:   random   -- Reference to a source of random data.                                  *\n *                                                                                             *\n *          bits     -- The number of bits to use for key generation. Use a number greater     *\n *                      than 16 but less than 2048. The ideal bit size is one that is evenly   *\n *                      divisible by 8 and then add one. Practical numbers range from 65 to    *\n *                      1025 bits.                                                             *\n *                                                                                             *\n *          fastkey  -- Reference to the key that has fast encryption/decryption properties.   *\n *                                                                                             *\n *          slowkey  -- Reference to the mate key of the other.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine can take a very long time. It can take MINUTES to generate a       *\n *             1024 bit key (even on a Pentium Pro 200Mghz machine).                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/05/1996 JLB : Created.                                                                 *\n *   07/10/1996 JLB : Must supply source of random data.                                       *\n *=============================================================================================*/\nvoid PKey::Generate(Straw & random, int bits, PKey & fastkey, PKey & slowkey)\n{\n\t/*\n\t**\tKey generation consists of create a key pair and then testing the key\n\t**\tpair. If the test fails, then repeat the process. The test and repeat\n\t**\tmethod is required since the prime number generating process can't\n\t**\tguarantee the generation of a prime number -- it can only generate a\n\t**\thighly likely prime number.\n\t*/\n\tfor (;;) {\n\t\t/*\n\t\t**\tGenerate the two random prime numbers. This is the longest\n\t\t**\tstep.\n\t\t*/\n\t\tBigInt p = Generate_Prime(random, bits, &p);\n\t\tBigInt q = Generate_Prime(random, bits, &q);\n\n\t\t/*\n\t\t**\tThe exponent factors are easy to calculate from the prime numbers.\n\t\t*/\n\t\tBigInt e = Fast_Exponent();\n\t\tBigInt n = p * q;\n\t\tBigInt pqmin = (p-(unsigned short)1)*(q-(unsigned short)1);\n\t\tBigInt d = e.Inverse(pqmin);\n\n\t\t/*\n\t\t**\tStore the data into the key objects. Notice that the modulus is the\n\t\t**\tsame for both the fast and slow keys. Also notice that the exponent for\n\t\t**\tthe fast key is ALWAYS 65537. Given this, it is possible to economize the\n\t\t**\tfast key into being just the modulus and the slow key to being just the\n\t\t**\texponent (presuming the slow key also has access to the fast key so that\n\t\t**\tit can get the modulus).\n\t\t*/\n\t\tfastkey.Exponent = e;\n\t\tfastkey.Modulus = n;\n\t\tfastkey.BitPrecision = n.BitCount()-1;\n\n\t\tslowkey.Exponent = d;\n\t\tslowkey.Modulus = n;\n\t\tslowkey.BitPrecision = fastkey.BitPrecision;\n\n\t\t/*\n\t\t**\tTest the keys by encrypting a block of random bytes. If it decrypts\n\t\t**\tcorrectly, then a valid key pair has been generated -- bail.\n\t\t*/\n\t\tchar before[256];\n\t\tchar after[256];\n\n\t\tfor (int index = 0; index < fastkey.Plain_Block_Size(); index++) {\n\t\t\tbefore[index] = (char)rand();\n\t\t}\n\t\tfastkey.Encrypt(before, fastkey.Plain_Block_Size(), after);\n\t\tslowkey.Decrypt(after, slowkey.Crypt_Block_Size(), after);\n\n\t\t/*\n\t\t**\tCompare the pre and post processing buffer. A match indicates\n\t\t**\ta valid key pair.\n\t\t*/\n\t\tif (memcmp(before, after, fastkey.Plain_Block_Size()) == 0) break;\n\t}\n}\n\n\n/***********************************************************************************************\n * PKey::Encrypt -- Encrypt blocks of plaintext.                                               *\n *                                                                                             *\n *    This routine will encrypt the supplied plaintext into cyphertext by processing the input *\n *    in block. The source is processed in whole blocks. Partial blocks are not supported by   *\n *    public key cryptography.                                                                 *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the source plaintext that will be encrypted.                *\n *                                                                                             *\n *          length   -- The length of the plaintext to encrypt.                                *\n *                                                                                             *\n *          dest     -- Pointer to the buffer that will hold the encrypted data.               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of cypher text bytes placed into the destination buffer.   *\n *                                                                                             *\n * WARNINGS:   Be sure that the destination buffer is big enough to hold the output.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKey::Encrypt(void const * source, int slen, void * dest) const\n{\n\tint total = 0;\n\n\t/*\n\t**\tEncrypt the source data in full blocks. Partial blocks are not processed and are not\n\t**\tcopied to the destination buffer.\n\t*/\n\twhile (slen >= Plain_Block_Size()) {\n\n\t\t/*\n\t\t**\tPerform the encryption of the block.\n\t\t*/\n\t\tBigInt temp = 0;\n\t\tmemmove(&temp, source, Plain_Block_Size());\n\t\ttemp = temp.exp_b_mod_c(Exponent, Modulus);\n\n\t\t/*\n\t\t**\tMove the cypher block to the destination.\n\t\t*/\n\t\tmemmove(dest, &temp, Crypt_Block_Size());\n\t\tslen -= Plain_Block_Size();\n\t\tsource = (char *)source + Plain_Block_Size();\n\t\tdest = (char *)dest + Crypt_Block_Size();\n\t\ttotal += Crypt_Block_Size();\n\t}\n\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * PKey::Decrypt -- Decrypt supplied cyphertext into its original plaintext.                   *\n *                                                                                             *\n *    This routine will process the supplied cyphertext by breaking it up into blocks and      *\n *    then decrypting each block in turn. The block size is dependant upon the key. By NOT     *\n *    embedding this information into the cypher data, it makes the encryption more secure.    *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the cypher text to be decrypted.                            *\n *                                                                                             *\n *          length   -- The number of cypher text bytes supplied to this routine.              *\n *                                                                                             *\n *          dest     -- Pointer to the buffer to hold the plaintext.                           *\n *                                                                                             *\n * OUTPUT:  Returns with the number of plaintext bytes output to the destination buffer.       *\n *                                                                                             *\n * WARNINGS:   Only whole blocks are processed. If the source has any partial block sized      *\n *             data, then it will be left unprocessed.                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKey::Decrypt(void const * source, int slen, void * dest) const\n{\n\tint total = 0;\n\tBigInt temp;\n\n\t/*\n\t**\tDecrypt the source data in full blocks. Partial blocks are not processed in any way.\n\t*/\n\twhile (slen >= Crypt_Block_Size()) {\n\n\t\t/*\n\t\t**\tPerform the encryption.\n\t\t*/\n\t\ttemp = 0;\n\t\tmemmove(&temp, source, Crypt_Block_Size());\n\t\ttemp = temp.exp_b_mod_c(Exponent, Modulus);\n\n\t\t/*\n\t\t**\tMove the cypher block to the destination.\n\t\t*/\n\t\tmemmove(dest, &temp, Plain_Block_Size());\n\t\tslen -= Crypt_Block_Size();\n\t\tsource = (char *)source + Crypt_Block_Size();\n\t\tdest = (char *)dest + Plain_Block_Size();\n\t\ttotal += Plain_Block_Size();\n\t}\n\n\treturn(total);\n}\n"
  },
  {
    "path": "CODE/PK.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/PK.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PK.H                                                         *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/03/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef PK_H\n#define PK_H\n\n#include\t\"int.h\"\n\n/*\n**\tThis class holds a public or private key used in Public Key Cryptography. It also serves\n**\tas the conduit for encrypting/decrypting data using that key. Cryptography, using this\n**\tmethod, has a couple of characteristics that affect how it is used. One, the process of\n**\tencrypting/decrypting is very slow. This limits the effective quantity of data that can\n**\tbe processed. Two, the ciphertext is larger than the plaintext. This property generally\n**\tlimits its use to streaming data as opposed to random access data. The data is processed\n**\tin blocks. The size of the ciphertext and plaintext blocks can be determined only from\n**\tthe key itself.\n**\n**\tA reasonable use of this technology would be to encrypt only critical data such as the\n**\tpassword for a fast general purpose cryptographic algorithm.\n*/\nclass PKey\n{\n\tpublic:\n\t\tPKey(void) : Modulus(0), Exponent(0), BitPrecision(0) {}\n\t\tPKey(void const * exponent, void const * modulus);\t\t// DER initialization.\n\n\t\tint Encrypt(void const * source, int slen, void * dest) const;\n\t\tint Decrypt(void const * source, int slen, void * dest) const;\n\n\t\tstatic void Generate(Straw & random, int bits, PKey & fastkey, PKey & slowkey);\n\n\t\tint Plain_Block_Size(void) const {return((BitPrecision-1)/8);}\n\t\tint Crypt_Block_Size(void) const {return(Plain_Block_Size()+1);}\n\t\tint Block_Count(int plaintext_length) const {return((((plaintext_length-1)/Plain_Block_Size())+1));}\n\n\t\tint Encode_Modulus(void * buffer) const;\n\t\tint Encode_Exponent(void * buffer) const;\n\n\t\tvoid Decode_Modulus(void * buffer);\n\t\tvoid Decode_Exponent(void * buffer);\n\n\t\tstatic long Fast_Exponent(void) {return(65537L);}\n\n\tprivate:\n\n\t\t// p*q\n\t\tBigInt Modulus;\n\n\t\t// 65537 or\n\t\t// inverse of (p-1)(q-1).\n\t\tBigInt Exponent;\n\n\t\t// Maximum bits allowed for block.\n\t\tint BitPrecision;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/PKPIPE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/PKPIPE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                                                                                             *\n *                    File Name : PKPIPE.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/07/96                                                     *\n *                                                                                             *\n *                  Last Update : July 12, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   PKPipe::Encrypted_Key_Length -- Fetch the encrypted key length.                           *\n *   PKPipe::Key -- Submit a key to enable processing of data flow.                            *\n *   PKPipe::PKPipe -- Constructor for the public key pipe object.                             *\n *   PKPipe::Plain_Key_Length -- Returns the number of bytes to encrypt key.                   *\n *   PKPipe::Put -- Submit data to the pipe for processing.                                    *\n *   PKPipe::Put_To -- Chains one pipe to another.                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"pkpipe.h\"\n\n\n/***********************************************************************************************\n * PKPipe::PKPipe -- Constructor for the public key pipe object.                               *\n *                                                                                             *\n *    This will construct the public key pipe object.                                          *\n *                                                                                             *\n * INPUT:   control  -- The method used to process the data flow (encrypt or decrypt).         *\n *                                                                                             *\n *          rnd      -- Reference to a random number generate used to create the internal      *\n *                      blowfish key.                                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nPKPipe::PKPipe(CryptControl control, RandomStraw & rnd) :\n\tIsGettingKey(true),\n\tRand(rnd),\n\tBF((control == ENCRYPT) ? BlowPipe::ENCRYPT : BlowPipe::DECRYPT),\n\tControl(control),\n\tCipherKey(NULL),\n\tCounter(0),\n\tBytesLeft(0)\n{\n}\n\n\n/***********************************************************************************************\n * PKPipe::Put_To -- Chains one pipe to another.                                               *\n *                                                                                             *\n *    This handles linking of one pipe to this pipe. Data will flow from this PKPipe to the    *\n *    pipe segment specified. Special handling is done so that piping actually flows to the    *\n *    embedded blowfish pipe and then flows to the designated pipe.                            *\n *                                                                                             *\n * INPUT:   pipe  -- Pointer to the pipe that this pipe segment is to send data to.            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PKPipe::Put_To(Pipe * pipe)\n{\n\tif (BF.ChainTo != pipe) {\n\t\tif (pipe != NULL && pipe->ChainFrom != NULL) {\n\t\t\tpipe->ChainFrom->Put_To(NULL);\n\t\t\tpipe->ChainFrom = NULL;\n\t\t}\n\n\t\tif (BF.ChainTo != NULL) {\n\t\t\tBF.ChainTo->ChainFrom = NULL;\n\t\t}\n\t\tBF.ChainTo = pipe;\n\t\tif (pipe != NULL) {\n\t\t\tpipe->ChainFrom = &BF;\n\t\t}\n\t\tBF.ChainFrom = this;\n\t\tChainTo = &BF;\n\t}\n}\n\n\n/***********************************************************************************************\n * PKPipe::Key -- Submit a key to enable processing of data flow.                              *\n *                                                                                             *\n *    This routine must be called with a valid key pointer in order for encryption/description *\n *    to be performed on the data stream. Prior to calling this routine or after calling this  *\n *    routine with a NULL pointer, the data stream will pass through this pipe without         *\n *    modification.                                                                            *\n *                                                                                             *\n * INPUT:   key   -- Pointer to the key to use for processing. Pass NULL if process is to be   *\n *                   terminated.                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/07/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PKPipe::Key(PKey const * key)\n{\n\tif (key == NULL) {\n\t\tFlush();\n\t\tIsGettingKey = false;\n\t}\n\tCipherKey = key;\n\n\tif (CipherKey != NULL) {\n\t\tIsGettingKey = true;\n\t\tif (Control == DECRYPT) {\n\t\t\tCounter = BytesLeft = Encrypted_Key_Length();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * PKPipe::Put -- Submit data to the pipe for processing.                                      *\n *                                                                                             *\n *    This routine (if processing as been enabled by a previous key submission) will           *\n *    encrypt or decrypt the data stream that passes through it. When encrypting, the data     *\n *    stream will increase in size by about 10% (bit it varies according to the key used).     *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the data to be submitted to the pipe stream.                *\n *                                                                                             *\n *          length   -- The number of bytes submitted.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of byte output at the final end of the pipe.        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/07/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKPipe::Put(void const * source, int length)\n{\n\t/*\n\t**\tIf the parameter seem illegal, then pass the pipe request to the\n\t**\tnext pipe in the chain and let them deal with it.\n\t*/\n\tif (source == NULL || length < 1 || CipherKey == NULL) {\n\t\treturn(Pipe::Put(source, length));\n\t}\n\n\tint total = 0;\n\n\t/*\n\t**\tPerform a special process if the this is the first part of the data flow. The special\n\t**\tkey must be processed first. After this initial key processing, the rest of the data flow\n\t**\tis processed by the blowfish pipe and ignored by the PKPipe.\n\t*/\n\tif (IsGettingKey) {\n\n\t\t/*\n\t\t**\tWhen encrypting, first make the key block and then pass the data through the\n\t\t**\tnormal blowfish processor.\n\t\t*/\n\t\tif (Control == ENCRYPT) {\n\n\t\t\t/*\n\t\t\t**\tGenerate the largest blowfish key possible.\n\t\t\t*/\n\t\t\tchar buffer[MAX_KEY_BLOCK_SIZE];\n\t\t\tmemset(buffer, '\\0', sizeof(buffer));\n\t\t\tRand.Get(buffer, BLOWFISH_KEY_SIZE);\n\n\t\t\t/*\n\t\t\t**\tEncrypt the blowfish key (along with any necessary pad bytes).\n\t\t\t*/\n\t\t\tint didput = CipherKey->Encrypt(buffer, Plain_Key_Length(), Buffer);\n\t\t\ttotal += Pipe::Put(Buffer, didput);\n\t\t\tBF.Key(buffer, BLOWFISH_KEY_SIZE);\n\n\t\t\tIsGettingKey = false;\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tFirst try to accumulate a full key.\n\t\t\t*/\n\t\t\tint toget = (BytesLeft < length) ? BytesLeft : length;\n\t\t\tmemmove(&Buffer[Counter-BytesLeft], source, toget);\n\t\t\tlength -= toget;\n\t\t\tBytesLeft -= toget;\n\t\t\tsource = (char *)source + toget;\n\n\t\t\t/*\n\t\t\t**\tIf a full key has been accumulated, then decrypt it and feed the\n\t\t\t**\tkey to the blowfish engine.\n\t\t\t*/\n\t\t\tif (BytesLeft == 0) {\n\t\t\t\tchar buffer[MAX_KEY_BLOCK_SIZE];\n\t\t\t\tCipherKey->Decrypt(Buffer, Counter, buffer);\n\t\t\t\tBF.Key(buffer, BLOWFISH_KEY_SIZE);\n\n\t\t\t\tIsGettingKey = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there are any remaining bytes to pipe through, then\n\t**\tpipe them through now -- they will be processed by the\n\t**\tblowfish engine.\n\t*/\n\ttotal += Pipe::Put(source, length);\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * PKPipe::Encrypted_Key_Length -- Fetch the encrypted key length.                             *\n *                                                                                             *\n *    This returns the total number of bytes (after encryption) that the blowfish key will     *\n *    consume. It should be possible to get a block of this size, then pass it to the          *\n *    public key decrypter and the result will be the full blowfish key.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes that the encrypted blowfish key required.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKPipe::Encrypted_Key_Length(void) const\n{\n\tif (CipherKey == NULL) return(0);\n\treturn(CipherKey->Block_Count(BLOWFISH_KEY_SIZE) * CipherKey->Crypt_Block_Size());\n}\n\n\n/***********************************************************************************************\n * PKPipe::Plain_Key_Length -- Returns the number of bytes to encrypt key.                     *\n *                                                                                             *\n *    This is the number of plain (unencrypted) bytes that the blowfish key will take up. This *\n *    is actually the number of plain blocks minimum that can contain the full blowfish        *\n *    key. The public key cryptography system encrypts in whole blocks only.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the total number of bytes that will contain the full blowfish key     *\n *          and still be an even block size for the public key cryptography process.           *\n *                                                                                             *\n * WARNINGS:   This value is probably be larger than the actual blowfish key length.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKPipe::Plain_Key_Length(void) const\n{\n\tif (CipherKey == NULL) return(0);\n\treturn(CipherKey->Block_Count(BLOWFISH_KEY_SIZE) * CipherKey->Plain_Block_Size());\n}\n"
  },
  {
    "path": "CODE/PKPIPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/PKPIPE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PKPIPE.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/06/96                                                     *\n *                                                                                             *\n *                  Last Update : July 6, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef PKPIPE_H\n#define PKPIPE_H\n\n#include\t\"pipe.h\"\n#include\t\"pk.h\"\n#include \"rndstraw.h\"\n#include\t\"blowpipe.h\"\n\n\n/*\n**\tThis pipe will encrypt/decrypt the data stream. The data is encrypted by generating a\n**\tsymetric key that is then encrypted using the public key system. This symetric key is then\n**\tused to encrypt the remaining data.\n*/\nclass PKPipe : public Pipe\n{\n\tpublic:\n\t\ttypedef enum CryptControl {\n\t\t\tENCRYPT,\n\t\t\tDECRYPT\n\t\t} CryptControl;\n\n\t\tPKPipe(CryptControl control, RandomStraw & rnd);\n\n\t\tvirtual void Put_To(Pipe * pipe);\n\t\tvirtual void Put_To(Pipe & pipe) {Put_To(&pipe);}\n\n\t\t// Feed data through for processing.\n\t\tvirtual int Put(void const * source, int length);\n\n\t\t// Submit key for encryption/decryption.\n\t\tvoid Key(PKey const * key);\n\n\tprivate:\n\t\tenum {\n\t\t\tBLOWFISH_KEY_SIZE=BlowfishEngine::MAX_KEY_LENGTH,\n\t\t\tMAX_KEY_BLOCK_SIZE=256\t\t// Maximum size of pk encrypted blowfish key.\n\t\t};\n\n\t\t/*\n\t\t**\tThis flag indicates whether the PK (fetch blowfish key) phase is\n\t\t**\tin progress or not.\n\t\t*/\n\t\tbool IsGettingKey;\n\n\t\t/*\n\t\t**\tThis is the random straw that is needed to generate the\n\t\t**\tblowfish key.\n\t\t*/\n\t\tRandomStraw & Rand;\n\n\t\t/*\n\t\t**\tThis is the attached blowfish pipe. After the blowfish key has been\n\t\t**\tdecrypted, then the PK processor goes dormant and the blowfish processor\n\t\t**\ttakes over the data flow.\n\t\t*/\n\t\tBlowPipe BF;\n\n\t\t/*\n\t\t**\tControls the method of processing the data stream.\n\t\t*/\n\t\tCryptControl Control;\n\n\t\t/*\n\t\t**\tPointer to the key to use for encryption/decryption. The actual process\n\t\t**\tperformed is controlled by the Control member. A key can be used for\n\t\t**\teither encryption or decryption -- it makes no difference. However, whichever\n\t\t**\tprocess is performed, the opposite process must be performed using the\n\t\t**\tother key.\n\t\t*/\n\t\tPKey const * CipherKey;\n\n\t\t/*\n\t\t**\tThis is the staging buffer for the block of data. This block must be as large as\n\t\t**\tthe largest possible key size or the largest blowfish key (whichever is greater).\n\t\t*/\n\t\tchar Buffer[MAX_KEY_BLOCK_SIZE];\n\n\t\t/*\n\t\t**\tThe working counter that holds the number of bytes in the staging buffer.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tThis records the number of bytes remaining in the current block. This\n\t\t**\twill be the number of bytes left to accumulate before the block can be\n\t\t**\tprocessed either for encryption or decryption.\n\t\t*/\n\t\tint BytesLeft;\n\n\t\tint Encrypted_Key_Length(void) const;\n\t\tint Plain_Key_Length(void) const;\n\n\t\tPKPipe(PKPipe & rvalue);\n\t\tPKPipe & operator = (PKPipe const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/PKSTRAW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/PKSTRAW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PKSTRAW.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/08/96                                                     *\n *                                                                                             *\n *                  Last Update : July 11, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   PKStraw::Encrypted_Key_Length -- Fetch the encrypted key length.                          *\n *   PKStraw::Get -- Fetch data and process it accordingly.                                    *\n *   PKStraw::Get_From -- Chains one straw to another.                                         *\n *   PKStraw::Key -- Assign a key to the cipher process straw.                                 *\n *   PKStraw::PKStraw -- Initialize the public key straw object.                               *\n *   PKStraw::Plain_Key_Length -- Returns the number of bytes to encrypt key.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"pkstraw.h\"\n#include\t\"rndstraw.h\"\n#include\t\"blwstraw.h\"\n\n\n/***********************************************************************************************\n * PKStraw::PKStraw -- Initialize the public key straw object.                                 *\n *                                                                                             *\n *    This constructs the public key straw object. The operation to perform (encrypt or        *\n *    decrypt) as well as a random number generator must be provided.                          *\n *                                                                                             *\n * INPUT:   control  -- What operation to perform on the data. Pass in either ENCRYPT or       *\n *                      DECRYPT.                                                               *\n *                                                                                             *\n *          rnd      -- Reference to a random number straw that is used internally to          *\n *                      generate the sub-key. The final strength of the cipher depends on      *\n *                      quality of this random number generator.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nPKStraw::PKStraw(CryptControl control, RandomStraw & rnd) :\n\tIsGettingKey(true),\n\tRand(rnd),\n\tBF((control == ENCRYPT) ? BlowStraw::ENCRYPT : BlowStraw::DECRYPT),\n\tControl(control),\n\tCipherKey(NULL),\n\tCounter(0),\n\tBytesLeft(0)\n{\n\tStraw::Get_From(BF);\n}\n\n\n/***********************************************************************************************\n * PKStraw::Get_From -- Chains one straw to another.                                           *\n *                                                                                             *\n *    This routine handles the special case of this straw object in that there is an           *\n *    embedded blowfish straw segment. It must be chained on correctly.                        *\n *                                                                                             *\n * INPUT:   straw -- Pointer to the straw segment that this segment is to receive data from.   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PKStraw::Get_From(Straw * straw)\n{\n\tif (BF.ChainTo != straw) {\n\t\tif (straw != NULL && straw->ChainFrom != NULL) {\n\t\t\tstraw->ChainFrom->Get_From(NULL);\n\t\t\tstraw->ChainFrom = NULL;\n\t\t}\n\n\t\tif (BF.ChainTo != NULL) {\n\t\t\tBF.ChainTo->ChainFrom = NULL;\n\t\t}\n\n\t\tBF.ChainTo = straw;\n\t\tBF.ChainFrom = this;\n\t\tChainTo = &BF;\n\t\tif (BF.ChainTo != NULL) {\n\t\t\tBF.ChainTo->ChainFrom = this;\n\t\t}\n\t}\n}\n\n\n\n/***********************************************************************************************\n * PKStraw::Key -- Assign a key to the cipher process straw.                                   *\n *                                                                                             *\n *    This routine will assign the key (or NULL if the current key is to be removed) to the    *\n *    cipher stream process. When a key has been assigned, encryption or decryption will       *\n *    take place. In the absence (NULL key pointer) of a key, the data passes through          *\n *    unchanged.                                                                               *\n *                                                                                             *\n * INPUT:   key   -- Pointer to the key to assign to the stream. If the key pointer is NULL,   *\n *                   then this causes the cipher stream to stop processing the data and will   *\n *                   pass the data through unchanged.                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure that the key passed to this routine is the opposite key to that used    *\n *             to process the stream originally (when decrypting).                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PKStraw::Key(PKey const * key)\n{\n\tCipherKey = key;\n\tif (key != NULL) {\n\t\tIsGettingKey = true;\n\t}\n\tCounter = 0;\n\tBytesLeft = 0;\n}\n\n\n/***********************************************************************************************\n * PKStraw::Get -- Fetch data and process it accordingly.                                      *\n *                                                                                             *\n *    This routine will fetch the number of bytes requested. If a valid key has been assigned  *\n *    to this stream, then the data will be processed as it passes through.                    *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer that will hold the requested data.               *\n *                                                                                             *\n *          length   -- The number of data bytes requested.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of data bytes stored to the destination buffer. If  *\n *          this number is less than that requested, then it indicates that the data source    *\n *          has been exhausted.                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKStraw::Get(void * source, int length)\n{\n\t/*\n\t**\tIf the parameters seem invalid, then pass the request on so that someone\n\t**\telse can deal with it.\n\t*/\n\tif (source == NULL || length < 1 || CipherKey == NULL) {\n\t\treturn(Straw::Get(source, length));\n\t}\n\n\tint total = 0;\n\n\t/*\n\t**\tThe first part of the data flow must process the special key. After the special\n\t**\tkey has been processed, the data flows through this straw without direct\n\t**\tmodification (the blowfish straw will process the data).\n\t*/\n\tif (IsGettingKey) {\n\n\t\tif (Control == DECRYPT) {\n\n\t\t\t/*\n\t\t\t**\tRetrieve the pk encrypted blowfish key block.\n\t\t\t*/\n\t\t\tchar cbuffer[MAX_KEY_BLOCK_SIZE];\n\t\t\tint got = Straw::Get(cbuffer, Encrypted_Key_Length());\n\n\t\t\t/*\n\t\t\t**\tIf the entire key block could not be retrieved, then this indicates\n\t\t\t**\ta major data flow error -- just return with no action performed.\n\t\t\t*/\n\t\t\tif (got != Encrypted_Key_Length()) return(0);\n\n\t\t\t/*\n\t\t\t**\tDecrypt the blowfish key and then activate the blowfish straw\n\t\t\t**\twith that key.\n\t\t\t*/\n\t\t\tCipherKey->Decrypt(cbuffer, got, Buffer);\n\t\t\tBF.Key(Buffer, BLOWFISH_KEY_SIZE);\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tGenerate the blowfish key by using random numbers.\n\t\t\t*/\n\t\t\tchar buffer[MAX_KEY_BLOCK_SIZE];\n\t\t\tmemset(buffer, '\\0', sizeof(buffer));\n\t\t\tRand.Get(buffer, BLOWFISH_KEY_SIZE);\n\n\t\t\t/*\n\t\t\t**\tEncrypt the blowfish key (along with any necessary pad bytes).\n\t\t\t*/\n\t\t\tCounter = BytesLeft = CipherKey->Encrypt(buffer, Plain_Key_Length(), Buffer);\n\t\t\tBF.Key(buffer, BLOWFISH_KEY_SIZE);\n\t\t}\n\n\t\t/*\n\t\t**\tThe first phase of getting the special key has been accomplished. Now, all\n\t\t**\tsubsequent data is passed (unmodified) though this straw segment. The blowfish\n\t\t**\tstraw takes over the compression/decompression from this point forward.\n\t\t*/\n\t\tIsGettingKey = false;\n\t}\n\n\t/*\n\t**\tIf there are any pending bytes in the buffer, then pass\n\t**\tthese on first. The only time this should be is when the blowfish\n\t**\tkey has first been generated.\n\t*/\n\tif (BytesLeft > 0) {\n\t\tint tocopy = (length < BytesLeft) ? length : BytesLeft;\n\t\tmemmove(source, &Buffer[Counter-BytesLeft], tocopy);\n\t\tsource = (char *)source + tocopy;\n\t\tBytesLeft -= tocopy;\n\t\tlength -= tocopy;\n\t\ttotal += tocopy;\n\t}\n\n\t/*\n\t**\tAny requested bytes that haven't been satisfied are copied over now by\n\t**\tdrawing the data through the blowfish engine. The blowfish engine happens\n\t**\tto be linked to the chain so a normal Get() operation is sufficient.\n\t*/\n\ttotal += Straw::Get(source, length);\n\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * PKStraw::Encrypted_Key_Length -- Fetch the encrypted key length.                            *\n *                                                                                             *\n *    This returns the total number of bytes (after encryption) that the blowfish key will     *\n *    consume. It should be possible to get a block of this size, then pass it to the          *\n *    public key decrypter and the result will be the full blowfish key.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes that the encrypted blowfish key required.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKStraw::Encrypted_Key_Length(void) const\n{\n\tif (CipherKey == NULL) return(0);\n\treturn(CipherKey->Block_Count(BLOWFISH_KEY_SIZE) * CipherKey->Crypt_Block_Size());\n}\n\n\n/***********************************************************************************************\n * PKStraw::Plain_Key_Length -- Returns the number of bytes to encrypt key.                    *\n *                                                                                             *\n *    This is the number of plain (unencrypted) bytes that the blowfish key will take up. This *\n *    is actually the number of plain blocks minimum that can contain the full blowfish        *\n *    key. The public key cryptography system encrypts in whole blocks only.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the total number of bytes that will contain the full blowfish key     *\n *          and still be an even block size for the public key cryptography process.           *\n *                                                                                             *\n * WARNINGS:   This value is probably be larger than the actual blowfish key length.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKStraw::Plain_Key_Length(void) const\n{\n\tif (CipherKey == NULL) return(0);\n\treturn(CipherKey->Block_Count(BLOWFISH_KEY_SIZE) * CipherKey->Plain_Block_Size());\n}\n"
  },
  {
    "path": "CODE/PKSTRAW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/PKSTRAW.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PKSTRAW.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/08/96                                                     *\n *                                                                                             *\n *                  Last Update : July 8, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef PKSTRAW_H\n#define PKSTRAW_H\n\n#include\t\"pk.h\"\n#include \"pkstraw.h\"\n#include \"rndstraw.h\"\n#include\t\"blwstraw.h\"\n\nclass PKStraw : public Straw\n{\n\tpublic:\n\t\ttypedef enum CryptControl {\n\t\t\tENCRYPT,\n\t\t\tDECRYPT\n\t\t} CryptControl;\n\n\t\tPKStraw(CryptControl control, RandomStraw & rnd);\n\n\t\tvirtual void Get_From(Straw * straw);\n\t\tvirtual void Get_From(Straw & straw) {Get_From(&straw);}\n\n\t\tvirtual int Get(void * source, int slen);\n\n\t\t// Submit key to be used for encryption/decryption.\n\t\tvoid Key(PKey const * key);\n\n\tprivate:\n\t\tenum {\n\t\t\tBLOWFISH_KEY_SIZE=BlowfishEngine::MAX_KEY_LENGTH,\n\t\t\tMAX_KEY_BLOCK_SIZE=256\t\t// Maximum size of pk encrypted blowfish key.\n\t\t};\n\n\t\t/*\n\t\t**\tThis flag indicates whether the PK (fetch blowfish key) phase is\n\t\t**\tin progress or not.\n\t\t*/\n\t\tbool IsGettingKey;\n\n\t\t/*\n\t\t**\tThis is the random straw that is needed to generate the\n\t\t**\tblowfish key.\n\t\t*/\n\t\tRandomStraw & Rand;\n\n\t\t/*\n\t\t**\tThis is the attached blowfish pipe. After the blowfish key has been\n\t\t**\tdecrypted, then the PK processor goes dormant and the blowfish processor\n\t\t**\ttakes over the data flow.\n\t\t*/\n\t\tBlowStraw BF;\n\n\t\t/*\n\t\t**\tThis control member tells what method (encryption or decryption) that should\n\t\t**\tbe performed on the data stream.\n\t\t*/\n\t\tCryptControl Control;\n\n\t\t/*\n\t\t**\tPointer to the key to use for encryption or decryption. If this pointer is NULL, then\n\t\t**\tthe data passing through this segment will not be modified.\n\t\t*/\n\t\tPKey const * CipherKey;\n\n\t\t/*\n\t\t**\tThis is the staging buffer for the block of data. This block must be as large as\n\t\t**\tthe largest possible key size or the largest blowfish key size (whichever is\n\t\t**\tgreater).\n\t\t*/\n\t\tchar Buffer[256];\n\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tThis records the number of bytes remaining in the current block. This\n\t\t**\twill be the number of bytes left to accumulate before the block can be\n\t\t**\tprocessed either for encryption or decryption.\n\t\t*/\n\t\tint BytesLeft;\n\n\t\tint Encrypted_Key_Length(void) const;\n\t\tint Plain_Key_Length(void) const;\n\n\t\tPKStraw(PKStraw & rvalue);\n\t\tPKStraw & operator = (PKStraw const & straw);\n};\n\n#endif\n"
  },
  {
    "path": "CODE/POWER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/POWER.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : POWER.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : October 14, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   PowerClass::AI -- Process the power bar logic.                                            *\n *   PowerClass::Draw_It -- Renders the power bar graphic.                                     *\n *   PowerClass::Init_Clear -- Clears all the power bar variables.                             *\n *   PowerClass::One_Time -- One time processing for the power bar.                            *\n *   PowerClass::PowerButtonClass::Action -- Handles the mouse over the power bar area.        *\n *   PowerClass::PowerClass -- Default constructor for the power bar class.                    *\n *   PowerClass::Refresh_Cells -- Intercepts the redraw logic to see if sidebar to redraw too. *\n *   PowerClass::Power_Height -- Given a value figure where it falls on bar                    *\n *   PowerClass::Flash_Power -- Flag the power bar to flash.                                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/*\n**\tPoints to the shape to use for the \"desired\" power level indicator.\n*/\nvoid const * PowerClass::PowerShape;\nvoid const * PowerClass::PowerBarShape;\n\nPowerClass::PowerButtonClass PowerClass::PowerButton;\n\n\n/***********************************************************************************************\n * PowerClass::PowerClass -- Default constructor for the power bar class.                      *\n *                                                                                             *\n *    This is the default constructor for the power bar class. It doesn't really do anything.  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/20/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nPowerClass::PowerClass(void) :\n\tIsToRedraw(false),\n\tIsActive(false),\n\tFlashTimer(0),\n\tRecordedDrain(-1),\n\tRecordedPower(-1),\n\tDesiredDrainHeight(0),\n\tDesiredPowerHeight(0),\n\tDrainHeight(0),\n\tPowerHeight(0),\n\tDrainBounce(0),\n\tPowerBounce(0),\n\tPowerDir(0),\n\tDrainDir(0)\n{\n}\n\n\n/***********************************************************************************************\n * PowerClass::Init_Clear -- Clears all the power bar variables.                               *\n *                                                                                             *\n *    This routine is called in preparation for the start of a scenario. The power bar is      *\n *    initialized into the null state by this routine. As soon as the scenario starts, the     *\n *    power bar will rise to reflect the actual power output and drain.                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/07/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PowerClass::Init_Clear(void)\n{\n\tRadarClass::Init_Clear();\n\tRecordedDrain = -1;\n\tRecordedPower = -1;\n\tDesiredDrainHeight = 0;\n\tDesiredPowerHeight = 0;\n\tDrainHeight = 0;\n\tPowerHeight = 0;\n\tPowerBounce = 0;\n\tDrainBounce = 0;\n\tDrainDir = 0;\n\tPowerDir = 0;\n\tFlashTimer = 0;\n}\n\n\n/***********************************************************************************************\n * PowerClass::One_Time -- One time processing for the power bar.                              *\n *                                                                                             *\n * This routine is for code that truly only needs to be done once per game run.                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PowerClass::One_Time(void)\n{\n\tRadarClass::One_Time();\n\tPowerButton.X = POWER_X * RESFACTOR;\n\tPowerButton.Y = POWER_Y * RESFACTOR;\n\tPowerButton.Width = (POWER_WIDTH * RESFACTOR)-1;\n\tPowerButton.Height = POWER_HEIGHT * RESFACTOR;\n\tPowerShape = MFCD::Retrieve(\"POWER.SHP\");\n\tPowerBarShape = MFCD::Retrieve(\"POWERBAR.SHP\");\n}\n\n\n/***********************************************************************************************\n * PowerClass::Draw_It -- Renders the power bar graphic.                                       *\n *                                                                                             *\n *    This routine will draw the power bar graphic to the LogicPage.                           *\n *                                                                                             *\n * INPUT:   complete -- Should the power bar be redrawn even if it isn't specifically flagged  *\n *                      to do so?                                                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/20/1994 JLB : Created.                                                                 *\n *   12/27/1994 JLB : Changes power bar color depending on amount of power.                    *\n *=============================================================================================*/\nvoid PowerClass::Draw_It(bool complete)\n{\n\tstatic int _modtable[]={\n\t\t0, -1, 0, 1, 0, -1, -2, -1, 0, 1, 2, 1 ,0\n\t};\n\n\tif (complete || IsToRedraw) {\n\t\tBStart(BENCH_POWER);\n\n\t\tif (LogicPage->Lock()) {\n\t\t\tif (Map.IsSidebarActive) {\n\t\t\t\tIsToRedraw = false;\n\t\t\t\tShapeFlags_Type flags = SHAPE_NORMAL;\n\t\t\t\tvoid const * remap = NULL;\n\n\t\t\t\tif (FlashTimer > 1 && ((FlashTimer % 3) & 0x01) != 0) {\n\t\t\t\t\tflags = flags | SHAPE_FADING;\n\t\t\t\t\tremap = Map.FadingRed;\n\t\t\t\t}\n\n//\t\t\t\tLogicPage->Fill_Rect(POWER_X, POWER_Y, POWER_X+POWER_WIDTH-1, POWER_Y+POWER_HEIGHT-1, LTGREY);\n\t\t\t\tCC_Draw_Shape(PowerBarShape, 0, 240 * RESFACTOR, 88 * RESFACTOR, WINDOW_MAIN, flags | SHAPE_NORMAL | SHAPE_WIN_REL, remap);\n\n#ifdef WIN32\n\t\t\t\t/*\n\t\t\t\t** Hires power strip is too big to fit into a shape so it is in two parts\n\t\t\t\t*/\n\t\t\t\tCC_Draw_Shape(PowerBarShape, 1, 240 * RESFACTOR, (88 * RESFACTOR) + (56*RESFACTOR), WINDOW_MAIN, flags | SHAPE_NORMAL | SHAPE_WIN_REL, remap);\n#endif\n\t\t\t\t/*\n\t\t\t\t**\tDetermine how much the power production exceeds or falls short\n\t\t\t\t**\tof power demands.\n\t\t\t\t*/\n\t\t\t\tint bottom       = (POWER_Y + POWER_HEIGHT - 1) * RESFACTOR;\n\t\t\t\tint power_height  = (PowerHeight == DesiredPowerHeight) ? PowerHeight + (_modtable[PowerBounce] * PowerDir) : PowerHeight;\n\t\t\t\tint drain_height  = (DrainHeight == DesiredDrainHeight) ? DrainHeight + (_modtable[DrainBounce] * DrainDir) : DrainHeight;\n\t\t\t\tpower_height = Bound(power_height, 0, POWER_HEIGHT - 2);\n\t\t\t\tdrain_height = Bound(drain_height, 0, POWER_HEIGHT - 2);\n\n\t\t\t\t/*\n\t\t\t\t**\tDraw the power output graphic on top of the power bar framework.\n\t\t\t\t*/\n\t\t\t\tif (power_height) {\n\t\t\t\t\tint color1 = 3;\n\t\t\t\t\tint color2 = 4;\n\n\t\t\t\t\tif (PlayerPtr->Drain > PlayerPtr->Power) {\n\t\t\t\t\t\tcolor1 = 214;\n\t\t\t\t\t\tcolor2 = 211;\n\t\t\t\t\t}\n\t\t\t\t\tif (PlayerPtr->Drain > (PlayerPtr->Power * 2)) {\n\t\t\t\t\t\tcolor1 = 235;\n\t\t\t\t\t\tcolor2 = 230;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t** New power bar is in slightly different place\n\t\t\t\t\t**\n\t\t\t\t\t** Old power bar was 107 pixels high. New bar is 153 pixels high.\n\t\t\t\t\t**\n\t\t\t\t\t** ST - 5/2/96 11:23AM\n\t\t\t\t\t*/\n#ifdef WIN32\n\t\t\t\t\tpower_height = (power_height*(76*RESFACTOR+1)) / (53*RESFACTOR+1);\n\t\t\t\t\tdrain_height = (drain_height*(76*RESFACTOR+1)) / (53*RESFACTOR+1);\n#endif\n\t\t\t\t\tbottom = (175*RESFACTOR)+1;\n\n\t\t\t\t\tLogicPage->Fill_Rect(245*RESFACTOR, bottom-power_height, 245*RESFACTOR+1, bottom, color2);\n\t\t\t\t\tLogicPage->Fill_Rect(246*RESFACTOR, bottom-power_height, 246*RESFACTOR+1, bottom, color1);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tDraw the power drain threshold marker.\n\t\t\t\t*/\n\t\t\t\tCC_Draw_Shape(PowerShape, 0, (POWER_X * RESFACTOR)+RESFACTOR, bottom - (drain_height + (2 * RESFACTOR)), WINDOW_MAIN, flags | SHAPE_NORMAL, remap);\n\t\t\t}\n\t\t\tLogicPage->Unlock();\n\t\t}\n\t\tBEnd(BENCH_POWER);\n\t}\n\tRadarClass::Draw_It(complete);\n}\n\n\n/***********************************************************************************************\n * PowerClass::AI -- Process the power bar logic.                                              *\n *                                                                                             *\n *    Use this routine to process the power bar logic. This consists of animation effects.     *\n *                                                                                             *\n * INPUT:   input -- The player input value to be consumed or ignored as appropriate.          *\n *                                                                                             *\n *          x,y   -- Mouse coordinate parameters to use.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/20/1994 JLB : Created.                                                                 *\n *   12/31/1994 JLB : Uses mouse coordinate parameters.                                        *\n *=============================================================================================*/\nvoid PowerClass::AI(KeyNumType &input, int x, int y)\n{\n\tif (Map.IsSidebarActive /*IsActive*/) {\n\t\tint olddrain = DrainHeight;\n\t\tint oldpower  = PowerHeight;\n\n\n\t\t/*\n\t\t** If the recorded power value has changed we need to adjust for\n\t\t** it.\n\t\t*/\n\t\tif (PlayerPtr->Power != RecordedPower) {\n\t\t\tDesiredPowerHeight = Power_Height(PlayerPtr->Power);\n\t\t\tRecordedPower\t\t = PlayerPtr->Power;\n\t\t\tPowerBounce\t\t\t = 12;\n\t\t\tif (PowerHeight > DesiredPowerHeight) {\n\t\t\t\tPowerDir = -1;\n\t\t\t} else if (PowerHeight < DesiredPowerHeight) {\n\t\t\t\tPowerDir = 1;\n\t\t\t} else {\n\t\t\t\tPowerBounce = 0;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** If the recorded drain value has changed we need to adjust for\n\t\t** it.\n\t\t*/\n\t\tif (PlayerPtr->Drain != RecordedDrain) {\n\t\t\tDesiredDrainHeight = Power_Height(PlayerPtr->Drain);\n\t\t\tRecordedDrain\t\t = PlayerPtr->Drain;\n\t\t\tDrainBounce\t\t\t = 12;\n\t\t\tif (DrainHeight > DesiredDrainHeight) {\n\t\t\t\tDrainDir = -1;\n\t\t\t} else if (DrainHeight < DesiredDrainHeight) {\n\t\t\t\tDrainDir = 1;\n\t\t\t} else {\n\t\t\t\tDrainBounce = 0;\n\t\t\t}\n\t\t}\n\n\t\tif (DrainBounce && DrainHeight == DesiredDrainHeight) {\n\t\t\tIsToRedraw = true;\n\t\t\tFlag_To_Redraw(false);\n\t\t\tDrainBounce--;\n\t\t} else {\n\t\t\t/*\n\t\t\t** If we need to move the drain height then do so.\n\t\t\t*/\n\t\t\tif (DrainHeight != DesiredDrainHeight) {\n\t\t\t\tDrainHeight += DrainDir;\n\t\t\t}\n\t\t}\n\n\t\tif (PowerBounce && PowerHeight == DesiredPowerHeight) {\n\t\t\tIsToRedraw = true;\n\t\t\tFlag_To_Redraw(false);\n\t\t\tPowerBounce--;\n\t\t} else {\n\t\t\t/*\n\t\t\t** If we need to move the power height then do so.\n\t\t\t*/\n\t\t\tif (PowerHeight != DesiredPowerHeight) {\n\t\t\t\tPowerHeight += PowerDir;\n\t\t\t}\n\t\t}\n\n\t\tif (olddrain != DrainHeight || oldpower != PowerHeight) {\n\t\t\tIsToRedraw = true;\n\t\t\tFlag_To_Redraw(false);\n\t\t}\n\n\t\t/*\n\t\t**\tFlag to redraw if the power bar flash effect has expired.\n\t\t*/\n//\t\tif (FlashTimer == 1) {\n\t\tif (FlashTimer > 0) {\n\t\t\tIsToRedraw = true;\n\t\t\tFlag_To_Redraw(false);\n\t\t}\n\t}\n\tRadarClass::AI(input, x, y);\n}\n\n\n/***********************************************************************************************\n * PowerClass::Refresh_Cells -- Intercepts the redraw logic to see if sidebar to redraw too.   *\n *                                                                                             *\n *    This routine will examine a refresh list request and determine if the sidebar would be   *\n *    affect. If so, it will flag the sidebar to be redrawn.                                   *\n *                                                                                             *\n * INPUT:   cell  -- The cell that the offset list is base on.                                 *\n *                                                                                             *\n *          list  -- The list of cell offset used to flag for redraw. If the special sidebar   *\n *                   affecting cell magic offset number is detected, the sidebar is flagged    *\n *                   for redraw and the magic offset is removed.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/01/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PowerClass::Refresh_Cells(CELL cell, short const * list)\n{\n\tif (*list == REFRESH_SIDEBAR) {\n\t\tIsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\t}\n\tRadarClass::Refresh_Cells(cell, list);\n}\n\n\n/***************************************************************************\n * PowerClass::Power_Height -- Given a value figure where it falls on bar  *\n *                                                                         *\n * INPUT:\t\tint value - the value we are testing                        *\n *                                                                         *\n * OUTPUT:     int the height of the point that this value is on graph     *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/14/1995 PWG : Created.                                             *\n *=========================================================================*/\nint PowerClass::Power_Height(int value)\n{\n\tint num\t\t= value/ POWER_STEP_LEVEL;\t\t// figure out the initial num of DRAIN_VALUE's\n\tint retval\t= 0;\t\t\t\t\t\t\t\t\t// currently there is no power\n\n\t/*\n\t** Loop through the different hundreds figuring out the fractional piece\n\t** of each.\n\t*/\n\tfor (int lp = 0; lp < num; lp ++)  {\n\t\tretval  = retval + (((POWER_HEIGHT - 2) - retval) / POWER_STEP_FACTOR);\n\t\tvalue  -= POWER_STEP_LEVEL;\n\t}\n\n\t/*\n\t** Adjust the retval to factor in the remainder\n\t*/\n\tif (value) {\n\t\tretval = retval + (((((POWER_HEIGHT - 2) - retval) / POWER_STEP_FACTOR) * value) / POWER_STEP_LEVEL);\n\t}\n\n\tretval = Bound(retval, 0, POWER_HEIGHT-2);\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * PowerClass::PowerButtonClass::Action -- Handles the mouse over the power bar area.          *\n *                                                                                             *\n *    This routine handles input on the power bar area. Since no input is used for the power   *\n *    bar, this routine just pops up appropriate help text for the power bar.                  *\n *                                                                                             *\n * INPUT:   flags    -- The event flags that triggered this action call.                       *\n *                                                                                             *\n *          key      -- The key code (if any) associated with the trigger event.               *\n *                                                                                             *\n * OUTPUT:  Should further button processing be stopped?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/07/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PowerClass::PowerButtonClass::Action(unsigned flags, KeyNumType & key)\n{\n\tif (!Map.IsSidebarActive) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tForce any help label to disappear when the mouse is held over the\n\t**\tradar map.\n\t*/\n\tMap.Override_Mouse_Shape(MOUSE_NORMAL);\n\tif (PlayerPtr->Power_Fraction() < 1 && PlayerPtr->Power > 0) {\n\t\tMap.Help_Text(TXT_POWER_OUTPUT_LOW, -1, -1, GadgetClass::Get_Color_Scheme()->Color);\n\t} else {\n\t\tMap.Help_Text(TXT_POWER_OUTPUT, -1, -1, GadgetClass::Get_Color_Scheme()->Color);\n\t}\n\tGadgetClass::Action(flags, key);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * PowerClass::Flash_Power -- Flag the power bar to flash.                                     *\n *                                                                                             *\n *    This will cause the power bar to display with a flash so as to draw attention to         *\n *    itself. Typical use of this effect is when power is low.                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PowerClass::Flash_Power(void)\n{\n\tFlashTimer = TICKS_PER_SECOND;\n\tIsToRedraw = true;\n\tFlag_To_Redraw(false);\n}\n"
  },
  {
    "path": "CODE/POWER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/POWER.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : POWER.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : December 15, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef POWER_H\n#define POWER_H\n\n#include\t\"radar.h\"\n\nclass PowerClass : public RadarClass\n{\n\tpublic:\n\t\tPowerClass(void);\n\t\tPowerClass(NoInitClass const & x) : RadarClass(x), FlashTimer(x) {};\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t\t// One-time inits\n\n\t\tvirtual void Init_Clear(void);\t\t\t\t\t\t// Clears all to known state\n\t\tvirtual void Draw_It(bool complete=false);\n\t\tvirtual void AI(KeyNumType &input, int x, int y);\n\t\tvirtual void Refresh_Cells(CELL cell, short const *list);\n\t\tvoid Flash_Power(void);\n\n\t\tunsigned IsToRedraw:1;\n\n\tprotected:\n\t\t/*\n\t\t**\tThis gadget is used to capture mouse input on the power bar.\n\t\t*/\n\t\tclass PowerButtonClass : public GadgetClass {\n\t\t\tpublic:\n\t\t\t\tPowerButtonClass(void) : GadgetClass(0,0,0,0,LEFTPRESS|LEFTRELEASE|LEFTHELD|LEFTUP|RIGHTPRESS,true) {};\n\n\t\t\tprotected:\n\t\t\t\tvirtual int Action(unsigned flags, KeyNumType & key);\n\t\t\tfriend class PowerClass;\n\t\t};\n\n\t\t/*\n\t\t**\tThis is the \"button\" that tracks all input to the tactical map.\n\t\t** It must be available to derived classes, for Save/Load purposes.\n\t\t*/\n\t\tstatic PowerButtonClass PowerButton;\n\n\t\tenum PowerEnums {\n\t\t\tPOWER_X=10*ICON_PIXEL_W,\n#ifdef WIN32\n\t\t\tPOWER_Y= (7+70+13),\n\t\t\tPOWER_HEIGHT=(200-(7+70+13)),\n#else\n\t\t\tPOWER_Y= (88+9),\n\t\t\tPOWER_HEIGHT=80,\n#endif\n\t\t\tPOWER_WIDTH=8,\n\t\t\tPOWER_LINE_SPACE=5,\n\t\t\tPOWER_LINE_WIDTH=3,\n\t\t\tPOWER_STEP_LEVEL=100,\n\t\t\tPOWER_STEP_FACTOR=5\n\t\t};\n\n\tprivate:\n\t\tint Power_Height(int value);\n\n\t\tunsigned IsActive:1;\n\n\t\t/*\n\t\t**\tIf the power bar should be rendered with some flash effect then\n\t\t**\tthis specifies the duration that the flash will occur.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> FlashTimer;\n\n\t\tint RecordedDrain;\n\t\tint RecordedPower;\n\t\tint DesiredDrainHeight;\n\t\tint DesiredPowerHeight;\n\t\tint DrainHeight;\n\t\tint PowerHeight;\n\t\tint DrainBounce;\n\t\tint PowerBounce;\n\t\tshort PowerDir;\n\t\tshort DrainDir;\n\n\t\t/*\n\t\t**\tPoints to the shape to use for the \"desired\" power level indicator.\n\t\t*/\n\t\tstatic void const * PowerShape;\n\t\tstatic void const * PowerBarShape;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/PROFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/PROFILE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PROFILE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : September 10, 1993   [JLB]                                   *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   WWGetPrivateProfileInt -- Fetches integer value from INI.                                 *\n *   WWGetPrivateProfileString -- Fetch string from INI.                                       *\n *   WWWritePrivateProfileInt -- Write a profile int to the profile data block.                *\n *   WWWritePrivateProfileString -- Write a string to the profile data block.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\nstatic char * WriteBinBuffer = NULL;\nstatic int WriteBinBufferLen = 0;\nstatic int WriteBinBufferPos = 0;\nstatic int WriteBinBufferMax = 0;\nstatic char * ReadBinBuffer = NULL;\nstatic int ReadBinBufferLen = 0;\nstatic int ReadBinBufferPos = 0;\nstatic int ReadBinBufferMax = 0;\n\n\n/***************************************************************************\n * Read_Private_Config_Struct -- Fetches override integer value.           *\n *                                                                         *\n * INPUT:                                                                  *\n * OUTPUT:                                                                 *\n * WARNINGS:                                                               *\n * HISTORY:                                                                *\n *   08/05/1992 JLB : Created.                                             *\n *=========================================================================*/\nbool Read_Private_Config_Struct(FileClass & file, NewConfigType * config)\n{\n\tINIClass ini;\n\tini.Load(file);\n\n\tconfig->DigitCard \t= ini.Get_Hex(\"Sound\", \"Card\", 0);\n\tconfig->IRQ \t\t\t= ini.Get_Int(\"Sound\", \"IRQ\", 0);\n\tconfig->DMA \t\t\t= ini.Get_Int(\"Sound\", \"DMA\", 0);\n\tconfig->Port \t\t\t= ini.Get_Hex(\"Sound\", \"Port\", 0);\n\tconfig->BitsPerSample= ini.Get_Int(\"Sound\", \"BitsPerSample\", 0);\n\tconfig->Channels \t\t= ini.Get_Int(\"Sound\", \"Channels\", 0);\n\tconfig->Reverse      = ini.Get_Int(\"Sound\", \"Reverse\", 0);\n\tconfig->Speed        = ini.Get_Int(\"Sound\", \"Speed\", 0);\n\tini.Get_String(\"Language\", \"Language\", NULL, config->Language, sizeof(config->Language));\n\n\n//\tconfig->DigitCard \t= WWGetPrivateProfileHex(\"Sound\", \"Card\", \t\t\t profile);\n//\tconfig->IRQ \t\t\t= WWGetPrivateProfileInt(\"Sound\", \"IRQ\", \t\t\t 0,profile);\n//\tconfig->DMA \t\t\t= WWGetPrivateProfileInt(\"Sound\", \"DMA\", \t\t\t 0,profile);\n//\tconfig->Port \t\t\t= WWGetPrivateProfileHex(\"Sound\", \"Port\", \t\t\t profile);\n//\tconfig->BitsPerSample= WWGetPrivateProfileInt(\"Sound\", \"BitsPerSample\",0,profile);\n//\tconfig->Channels \t\t= WWGetPrivateProfileInt(\"Sound\", \"Channels\",\t\t 0,profile);\n//\tconfig->Reverse      = WWGetPrivateProfileInt(\"Sound\", \"Reverse\", \t\t 0,profile);\n//\tconfig->Speed        = WWGetPrivateProfileInt(\"Sound\", \"Speed\", \t\t 0,profile);\n//\tWWGetPrivateProfileString(\"Language\", \"Language\", NULL, config->Language, 3, profile);\n\n\treturn((config->DigitCard == 0) && (config->IRQ == 0) && (config->DMA == 0));\n}\n\n\n/***************************************************************************\n * Get_Private_Profile_Hex -- Fetches override integer value.              *\n *                                                                         *\n * INPUT:                                                                  *\n * OUTPUT:                                                                 *\n * WARNINGS:                                                               *\n * HISTORY:                                                                *\n *   08/05/1992 MML : Created.                                             *\n *=========================================================================*/\nunsigned WWGetPrivateProfileHex (char const * section, char const * entry, char * profile)\n{\n\tchar\tbuffer[16];\t\t\t\t\t// Integer staging buffer.\n\tunsigned card;\n\n\tmemset (buffer, '0', sizeof(buffer));\t\t// MAX_ENTRY_SIZE = 15\n\tbuffer[sizeof(buffer)-1] = '\\0';\n\n\tWWGetPrivateProfileString(section, entry, \"0\", buffer, sizeof(buffer), profile);\n\n\tif (strlen (buffer) > 0) {\n\t\tsscanf (buffer, \"%x\", &card);\n\t} else {\n\t\tcard = 0;\n\t}\n\n\treturn(card);\n}\n\n\n/***********************************************************************************************\n * WWGetPrivateProfileInt -- Fetches integer value.                                            *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      section      section to read from                                                      *\n *                                                                                             *\n *      entry         name of entry to read                                                    *\n *                                                                                             *\n *      def         default value, if entry isn't found                                        *\n *                                                                                             *\n *      profile      buffer containing INI data                                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      integer requested                                                                      *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nint WWGetPrivateProfileInt(char const * section, char const * entry, int def, char * profile)\n{\n\tchar\tbuffer[16];\t\t\t// Integer staging buffer.\n\n\t/*\n\t**\tStore the default in the buffer.\n\t*/\n\tsprintf(buffer, \"%d\", def);\n\n\t/*\n\t**\tGet the buffer; use itself as the default.\n\t*/\n\tWWGetPrivateProfileString(section, entry, buffer, buffer, sizeof(buffer)-1, profile);\n\n\t/*\n\t**\tConvert to int & return.\n\t*/\n\treturn(atoi(buffer));\n}\n\n\n/***********************************************************************************************\n * WWWritePrivateProfileInt -- Write a profile int to the profile data block.                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      section      section name to write to                                                  *\n *                                                                                             *\n *      entry         name of entry to write; if NULL, the entire section is deleted           *\n *                                                                                             *\n *      value         value to write                                                           *\n *                                                                                             *\n *      profile      INI buffer                                                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = success, false = failure                                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WWWritePrivateProfileInt(char const * section, char const * entry, int value, char * profile)\n{\n\tchar\tbuffer[250];\t\t\t// Working section buffer.\n\n\t/*\n\t**\tJust return if nothing to do.\n\t*/\n\tif (!profile || !section) {\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tGenerate string to save.\n\t*/\n\tsprintf(buffer, \"%d\", value);\n\n\t/*\n\t**\tSave the string.\n\t*/\n\treturn(WWWritePrivateProfileString(section, entry, buffer, profile));\n}\n\n\n/***********************************************************************************************\n * WWGetPrivateProfileString -- Fetch game override string.                                    *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      section      section name to read from                                                 *\n *                                                                                             *\n *      entry         name of entry to read; if NULL, all entry names are returned             *\n *                                                                                             *\n *      def         default string to use if not found; can be NULL                            *\n *                                                                                             *\n *      retbuffer   buffer to store result in                                                  *\n *                                                                                             *\n *      retlen      max length of return buffer                                                *\n *                                                                                             *\n *      profile      INI buffer                                                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      ptr to entry found in INI buf; NULL if not found                                       *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      On the PC, the \"\\n\" (10) is translated to \"\\r\\n\" (13,10) when it's written             *\n *      to disk. This routine must take this into consideration, by searching                  *\n *      for \\n when scanning backward, and for \\r when scanning forward.                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar * WWGetPrivateProfileString(char const * section, char const * entry, char const * def, char * retbuffer, int retlen, char const * profile)\n{\n\tchar const * workptr;\t\t// Working pointer into profile block.\n\tchar * altworkptr;\t// Alternate work pointer.\n\tchar\tsec[50];\t\t\t// Working section buffer.\n\tchar\tconst * retval;\t\t\t// Start of section or entry pointer.\n\tchar\t* next;\t\t\t// Pointer to start of next section (or EOF).\n\tchar\tc,c2;\t\t\t\t// Working character values.\n\tint\tlen;\t\t\t\t// Working substring length value.\n\tint\tentrylen;\t\t// Byte length of specified entry.\n\tchar * orig_retbuf;\t// original retbuffer ptr\n\n//\tif (!retlen) return(NULL);\n\n\t/*\n\t**\tFill in the default value just in case the entry could not be found.\n\t*/\n\tif (retbuffer) {\n\t\tretbuffer[0] = '\\0';\n\t\tif (retlen > 1 || retlen == 0) retbuffer[1] = '\\0';\n\t\tif (def) {\n\t\t\tstrncpy(retbuffer, def, retlen);\n\t\t}\n\t\tretbuffer[retlen-1] = '\\0';\n\t\torig_retbuf = retbuffer;\n\t}\n\n\t/*\n\t**\tMake sure a profile string was passed in\n\t*/\n\tif (!profile || !section) {\n\t\treturn(retbuffer);\n\t}\n\n\t/*\n\t**\tBuild section string to match file image.\n\t*/\n\tsprintf(sec, \"[%s]\", section);\t// sec = section name including []'s\n\tstrupr(sec);\n\tlen = strlen(sec);\t\t\t\t\t// len = section name length, incl []'s\n\n\t/*\n\t**\tScan for a matching section\n\t*/\n\tretval = profile;\n\tworkptr = profile;\n\tfor (;;) {\n\n\t\t/*\n\t\t**\t'workptr' = start of next section\n\t\t*/\n\t\tworkptr = strchr(workptr, '[');\n\n\t\t/*\n\t\t**\tIf the end has been reached without finding the desired section\n\t\t**\tthen abort with a failure flag.\n\t\t*/\n\t\tif (!workptr) {\n\t\t\treturn(NULL);\n\t\t}\n\n\t\t/*\n\t\t**\t'c' = character just before the '['\n\t\t*/\n\t\tif (workptr==profile) {\n\t\t\tc = '\\n';\n\t\t} else {\n\t\t\tc = *(workptr-1);\n\t\t}\n\n\t\t/*\n\t\t**\tIf this is the section name & the character before is a newline,\n\t\t**\tprocess this section\n\t\t*/\n\t\tif (memicmp(workptr, sec, len) == 0 && (c == '\\n')) {\n\n\t\t\t/*\n\t\t\t**\tSkip work pointer to start of first valid entry.\n\t\t\t*/\n\t\t\tworkptr += len;\n\t\t\twhile (isspace(*workptr)) {\n\t\t\t\tworkptr++;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the section name is empty, we will have stepped onto the start\n\t\t\t**\tof the next section name; inserting new entries here will leave\n\t\t\t**\ta blank line between this section's name & 1st entry. So, check\n\t\t\t**\tfor 2 newlines in a row & step backward.\n\t\t\t*/\n\t\t\tif (workptr - profile > 4) {\n\t\t\t\tif ( *(workptr-1)=='\\n' && *(workptr-3)=='\\n')\n\t\t\t\t\tworkptr -= 2;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\t'next = end of section or end of file.\n\t\t\t*/\n\t\t\tnext = strchr(workptr, '[');\n\t\t\tfor (;;) {\n\t\t\t\tif (next) {\n\n\t\t\t\t\tc = *(next-1);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf character before '[' is newline, this is the start of the\n\t\t\t\t\t**\tnext section\n\t\t\t\t\t*/\n\t\t\t\t\tif (c == '\\n') {\n\t\t\t\t\t\tif (*(next-1)=='\\n' && *(next-3)=='\\n') {\n\t\t\t\t\t\t\tnext -= 2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThis bracket was in the section; keep looking\n\t\t\t\t\t*/\n\t\t\t\t\tnext = strchr(next+1, '[');\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tNo bracket found; set 'next' to the end of the file\n\t\t\t\t\t*/\n\t\t\t\t\tnext = (char*)workptr + strlen(workptr)-1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf a specific entry was specified then return with the associated\n\t\t\t**\tstring.\n\t\t\t*/\n\t\t\tif (entry) {\n\t\t\t\tretval = workptr;\n\t\t\t\tentrylen = strlen(entry);\n\n\t\t\t\tfor (;;) {\n\t\t\t\t\t/*\n\t\t\t\t\t** Search for the 1st character of the entry\n\t\t\t\t\t*/\n\t\t\t\t\tworkptr = strchr(workptr, *entry);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the end of the file has been reached or we have spilled\n\t\t\t\t\t**\tinto the next section, then abort\n\t\t\t\t\t*/\n\t\t\t\t\tif (!workptr || workptr >= next) {\n\t\t\t\t\t\treturn(NULL);\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\t'c' = character before possible entry; must be a newline\n\t\t\t\t\t**\t'c2' = character after possible entry; must be '=' or space\n\t\t\t\t\t*/\n\t\t\t\t\tc = *(workptr-1);\n\t\t\t\t\tc2 = *(workptr+entrylen);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tEntry found; extract it\n\t\t\t\t\t*/\n\t\t\t\t\tif (memicmp(workptr, entry, entrylen) == 0 && (c == '\\n') &&\n\t\t\t\t\t\t(c2 == '=' || isspace(c2))) {\n\t\t\t\t\t\tretval = workptr;\n\t\t\t\t\t\tworkptr += entrylen;\t\t\t\t\t\t\t// skip entry name\n\t\t\t\t\t\tworkptr = strchr(workptr, '=');\t\t\t// find '='\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** 'altworkptr' = next newline; \\r is used here since we're\n\t\t\t\t\t\t** scanning forward!\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (workptr) {\n\t\t\t\t\t\t\taltworkptr = strchr(workptr, '\\r');\t// find next newline\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tReturn if there was no '=', or if the newline is before\n\t\t\t\t\t\t**\tthe next '='\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (workptr == NULL || altworkptr < workptr) {\n\t\t\t\t\t\t\treturn((char *)retval);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tSkip any white space after the '=' and before the first\n\t\t\t\t\t\t**\tvalid character of the parameter.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tworkptr++;\t\t\t\t\t\t\t\t\t\t// Skip the '='.\n\t\t\t\t\t\twhile (isspace(*workptr)) {\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tJust return if there's no entry past the '='.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (workptr >= altworkptr)\n\t\t\t\t\t\t\t\treturn((char*)retval);\n\n\t\t\t\t\t\t\tworkptr++;\t\t\t\t\t\t\t\t\t// Skip the whitespace\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tCopy the entry into the return buffer.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tlen = (int)(altworkptr - workptr);\n\t\t\t\t\t\tif (len > retlen-1) {\n\t\t\t\t\t\t\tlen = retlen-1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (retbuffer) {\n\t\t\t\t\t\t\tmemcpy(retbuffer, workptr, len);\n\t\t\t\t\t\t\t*(retbuffer + len) = '\\0';\t\t// Insert trailing null.\n\t\t\t\t\t\t\tstrtrim(retbuffer);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn((char*)retval);\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tEntry was not found; go to the next one\n\t\t\t\t\t*/\n\t\t\t\t\tworkptr++;\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tNo entry was specified, so build a list of all entries.\n\t\t\t\t**\t'workptr' is at 1st entry after section name\n\t\t\t\t**\t'next' is next bracket, or end of file\n\t\t\t\t*/\n\t\t\t\tretval = workptr;\n\n\t\t\t\tif (retbuffer) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tKeep accumulating the identifier strings in the retbuffer.\n\t\t\t\t\t*/\n\t\t\t\t\twhile (workptr && workptr < next) {\n\t\t\t\t\t\taltworkptr = strchr(workptr, '=');\t\t// find '='\n\n\t\t\t\t\t\tif (altworkptr && altworkptr < next) {\n\t\t\t\t\t\t\tint\tlength;\t\t\t\t\t\t\t\t// Length of ID string.\n\n\t\t\t\t\t\t\tlength = (int)(altworkptr - workptr);\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tMake sure we don't write past the end of the retbuffer;\n\t\t\t\t\t\t\t**\tadd '3' for the 3 NULL's at the end\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (retbuffer - orig_retbuf + length + 3 < retlen) {\n\t\t\t\t\t\t\t\tmemcpy(retbuffer, workptr, length);\t// copy entry name\n\t\t\t\t\t\t\t\t*(retbuffer+length) = '\\0';\t\t\t// NULL-terminate it\n\t\t\t\t\t\t\t\tstrtrim(retbuffer);\t\t\t\t\t\t// trim spaces\n\t\t\t\t\t\t\t\tretbuffer += strlen(retbuffer)+1;\t// next pos in dest buf\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tAdvance the work pointer to the start of the next line\n\t\t\t\t\t\t\t**\tby skipping the end of line character.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tworkptr = strchr(altworkptr, '\\n');\n\t\t\t\t\t\t\tif (!workptr) {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tworkptr++;\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf no '=', break out of loop\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tFinal trailing terminator. Make double sure the double\n\t\t\t\t\t**\ttrailing null is added.\n\t\t\t\t\t*/\n\t\t\t\t\t*retbuffer++ = '\\0';\n\t\t\t\t\t*retbuffer++ = '\\0';\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tSection name not found; go to the next bracket & try again\n\t\t\t**\tAdvance past '[' and keep scanning.\n\t\t\t*/\n\t\t\tworkptr++;\n\t\t}\n\t}\n\n\treturn((char*)retval);\n}\n\n\n/***********************************************************************************************\n * WritePrivateProfileString -- Write a string to the profile data block.                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      section      section name to write to                                                  *\n *      entry         name of entry to write; if NULL, the section is deleted                  *\n *      string      string to write; if NULL, the entry is deleted                             *\n *      profile      INI buffer                                                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = success, false = failure                                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      This function has to translate newlines into \\r\\n sequences.                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WWWritePrivateProfileString(char const * section, char const * entry, char const * string, char * profile)\n{\n\tchar\tbuffer[250];\t\t\t// Working section buffer\n\tchar const * offset;\n\tchar const * next;\t\t\t\t\t\t// ptr to next section\n\tchar\tc;\t\t\t\t\t\t\t// Working character value\n\n\t/*\n\t**\tJust return if nothing to do.\n\t*/\n\tif (!profile || !section) {\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tTry to find the section. WWGetPrivateProfileString with NULL entry name\n\t**\twill return all entry names in the given buffer, truncated to the given\n\t**\tbuffer length. 'offset' will point to 1st entry in the section, NULL if\n\t**\tsection not found.\n\t*/\n\toffset = WWGetPrivateProfileString(section, NULL, NULL, NULL, 0, profile);\n\n\t/*\n\t**\tIf the section could not be found, then add it to the end. Don't add\n\t**\tanything if a removal of an entry is requested (it is obviously already\n\t**\tnon-existent). Make sure two newlines precede the section name.\n\t*/\n\tif (!offset && entry) {\n\t\tsprintf(buffer, \"\\r\\n[%s]\\r\\n\", section);\n\t\tstrcat(profile, buffer);\n\t}\n\n\t/*\n\t**\tIf the section is there and 'entry' is NULL, remove the entire section\n\t*/\n\tif (offset && !entry) {\n\n\t\t/*\n\t\t**\t'next = end of section or end of file.\n\t\t*/\n\t\tnext = strchr(offset, '[');\n\t\tfor (;;) {\n\t\t\tif (next) {\n\t\t\t\tc = *(next-1);\n\n\t\t\t\t/*\n\t\t\t\t**\tIf character before '[' is newline, this is the start of the\n\t\t\t\t**\tnext section\n\t\t\t\t*/\n\t\t\t\tif (c == '\\n') {\n\t\t\t\t\tif ( *(next-1)=='\\n' && *(next-3)=='\\n') {\n\t\t\t\t\t\tnext -= 2;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tThis bracket was in the section; keep looking\n\t\t\t\t*/\n\t\t\t\tnext = strchr(next+1, '[');\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tNo bracket found; set 'next' to the end of the file\n\t\t\t\t*/\n\t\t\t\tnext = offset + strlen(offset);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tRemove the section\n\t\t*/\n\t\tstrcpy((char*)offset, (char*)next);\n\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tFind the matching entry within the desired section. A NULL return buffer\n\t**\twith 0 length will just return the offset of the found entry, NULL if\n\t**\tentry not found.\n\t*/\n\toffset = WWGetPrivateProfileString(section, entry, NULL, NULL, 0, profile);\n\n\t/*\n\t**\tRemove any existing entry\n\t*/\n\tif (offset) {\n\t\tint\teol;\t\t\t// Working EOL offset.\n\n\t\t/*\n\t\t**\tGet # characters up to newline; \\n is used since we're after the end\n\t\t**\tof this line\n\t\t*/\n\t\teol = strcspn(offset, \"\\n\");\n\n\t\t/*\n\t\t**\tErase the entry by strcpy'ing the entire INI file over this entry\n\t\t*/\n\t\tif (eol) {\n\t\t\tstrcpy((char*)offset, offset + eol + 1);\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tEntry doesn't exist, so point 'offset' to the 1st entry position in\n\t\t**\tthe section.\n\t\t*/\n\t\toffset = WWGetPrivateProfileString(section, NULL, NULL, NULL, 0, profile);\n\t}\n\n\t/*\n\t**\tAdd the desired entry.\n\t*/\n\tif (entry && string) {\n\n\t\t/*\n\t\t**\tGenerate entry string.\n\t\t*/\n\t\tsprintf(buffer, \"%s=%s\\r\\n\", entry, string);\n\n\t\t/*\n\t\t**\tMake room for new entry.\n\t\t*/\n\t\tmemmove((char*)offset+strlen(buffer), offset, strlen(offset)+1);\n\n\t\t/*\n\t\t**\tCopy the entry into the INI buffer.\n\t\t*/\n\t\tmemcpy((char*)offset, buffer, strlen(buffer));\n\t}\n\n\treturn(true);\n}\n\n\nchar * Read_Bin_Buffer( void )\n{\n\treturn( ReadBinBuffer );\n}\n\n\nbool Read_Bin_Init( char * buffer, int length )\n{\n\tReadBinBuffer = buffer;\n\tReadBinBufferLen = length;\n\tReadBinBufferPos = 0;\n\tReadBinBufferMax = 0;\n\treturn( true );\n}\n\n\nint Read_Bin_Length( char * buffer )\n{\n\tif (buffer != ReadBinBuffer) {\n\t\treturn( -1 );\n\t} else {\n\t\treturn( ReadBinBufferMax );\n\t}\n}\n\n\nbool Read_Bin_Num( void * num, int length, char * buffer )\n{\n\tchar * ptr;\n\n\tif (buffer != ReadBinBuffer || length <= 0 || length > 4 ||\n\t\t (ReadBinBufferPos + length) >= ReadBinBufferLen) {\n\t\treturn( false );\n\t} else {\n\t\tptr = ReadBinBuffer + ReadBinBufferPos;\n\t\tmemcpy( num, ptr, length );\n\t\tReadBinBufferPos += length;\n\n\t\tif (ReadBinBufferPos > ReadBinBufferMax) {\n\t\t\tReadBinBufferMax = ReadBinBufferPos;\n\t\t}\n\n\t\treturn( true );\n\t}\n}\n\n\nint Read_Bin_Pos( char * buffer )\n{\n\tif (buffer != ReadBinBuffer) {\n\t\treturn( -1 );\n\t} else {\n\t\treturn( ReadBinBufferPos );\n\t}\n}\n\n\nint Read_Bin_PosSet( unsigned int pos, char * buffer )\n{\n\tif (buffer != ReadBinBuffer) {\n\t\treturn( -1 );\n\t} else {\n\t\tReadBinBufferPos = pos;\n\t\treturn( ReadBinBufferPos );\n\t}\n}\n\n\nbool Read_Bin_String( char * string, char * buffer )\n{\n\tchar * ptr;\n\tunsigned char length;\n\n\tif (buffer != ReadBinBuffer ||\n\t\t ReadBinBufferPos >= ReadBinBufferLen) {\n\t\treturn( false );\n\t} else {\n\t\tptr = ReadBinBuffer + ReadBinBufferPos;\n\t\tlength = (unsigned char)*ptr++;\n\t\tif ( (ReadBinBufferPos + length + 2) <= ReadBinBufferLen) {\n\t\t\tmemcpy( string, ptr, (unsigned int)(length + 1) );\n\t\t\tReadBinBufferPos += (length + 2);\n\n\t\t\tif (ReadBinBufferPos > ReadBinBufferMax) {\n\t\t\t\tReadBinBufferMax = ReadBinBufferPos;\n\t\t\t}\n\n\t\t\treturn( true );\n\t\t} else {\n\t\t\treturn( false );\n\t\t}\n\t}\n}\n\n\nchar * Write_Bin_Buffer( void )\n{\n\treturn( WriteBinBuffer );\n}\n\n\nbool Write_Bin_Init( char * buffer, int length )\n{\n\tWriteBinBuffer = buffer;\n\tWriteBinBufferLen = length;\n\tWriteBinBufferPos = 0;\n\tWriteBinBufferMax = 0;\n\treturn( true );\n}\n\n\nint Write_Bin_Length( char * buffer )\n{\n\tif (buffer != WriteBinBuffer) {\n\t\treturn( -1 );\n\t} else {\n\t\treturn( WriteBinBufferMax );\n\t}\n}\n\n\nbool Write_Bin_Num( void * num, int length, char * buffer )\n{\n\tchar * ptr;\n\n\tif (buffer != WriteBinBuffer || length <= 0 || length > 4 ||\n\t\t (WriteBinBufferPos + length) > WriteBinBufferLen) {\n\t\treturn( false );\n\t} else {\n\t\tptr = WriteBinBuffer + WriteBinBufferPos;\n\t\tmemcpy( ptr, num, length );\n\t\tWriteBinBufferPos += length;\n\n\t\tif (WriteBinBufferPos > WriteBinBufferMax) {\n\t\t\tWriteBinBufferMax = WriteBinBufferPos;\n\t\t}\n\n\t\treturn( true );\n\t}\n}\n\n\nint Write_Bin_Pos( char * buffer )\n{\n\tif (buffer != WriteBinBuffer) {\n\t\treturn( -1 );\n\t} else {\n\t\treturn( WriteBinBufferPos );\n\t}\n}\n\n\nint Write_Bin_PosSet( unsigned int pos, char * buffer )\n{\n\tif (buffer != WriteBinBuffer) {\n\t\treturn( -1 );\n\t} else {\n\t\tWriteBinBufferPos = pos;\n\t\treturn( WriteBinBufferPos );\n\t}\n}\n\n\nbool Write_Bin_String( char * string, int length, char * buffer )\n{\n\tchar * ptr;\n\n\tif (buffer != WriteBinBuffer || length < 0 || length > 255 ||\n\t\t (WriteBinBufferPos + length + 2) > WriteBinBufferLen) {\n\t\treturn( false );\n\t} else {\n\t\tptr = WriteBinBuffer + WriteBinBufferPos;\n\t\t*ptr++ = (char)length;\n\t\tmemcpy( ptr, string, (length + 1) );\n\t\tWriteBinBufferPos += (length + 2);\n\n\t\tif (WriteBinBufferPos > WriteBinBufferMax) {\n\t\t\tWriteBinBufferMax = WriteBinBufferPos;\n\t\t}\n\n\t\treturn( true );\n\t}\n}\n\n"
  },
  {
    "path": "CODE/PROFILE.DEF",
    "content": "#\tPRFILE CONQUER, COORD, TARGET, DISPLAY\n#\tPRFILE OBJ\n#\tPRCLASS CODE\n#\tCODECLASS CODE\n\tPRSYMBOL $$VMGETPAGE\t\t\t\t# Watches VM overhead.\n\tNOPRFILE soundio.obj\n\tNOPRFILE wwlib.lib, nomidi.lib, emu.lib, mathl.lib, cl.lib\n\tPRSHOWVECTOR\n\t# Symbols that shouldn't be profiled.\n\tNOPRSYMBOL _DigiCallback\n\tNOPRSYMBOL __MMODEL\n\tNOPRSYMBOL __terminate\n\tNOPRSYMBOL _abort\n\tNOPRSYMBOL __restorezero\n\tNOPRSYMBOL __cleanup\n\tNOPRSYMBOL DGROUP@\n\tNOPRSYMBOL __checknull\n\n# Make sure that all symbols that start with \"@$xt\"\n# or contain \"$XL$\" are not profiled. These appear to be\n# mysterious internal routines and they break when profile vectored.\n\n\tNOPRSYMBOL \"@$xt$n11BulletClass\"\n\tNOPRSYMBOL \"@$xt$9FootClass\"\n\tNOPRSYMBOL \"@$xt$32%ArrayOf$t13AircraftClass$ii$10%\"\n\tNOPRSYMBOL \"@$xt$a10$13AircraftClass\"\n\tNOPRSYMBOL \"@$xt$11BulletClass\"\n\tNOPRSYMBOL \"@$xt$9FuseClass\"\n\tNOPRSYMBOL \"@$xt$n13AircraftClass\"\n\tNOPRSYMBOL \"@$xt$nc\"\n\tNOPRSYMBOL \"@$xt$c\"\n\tNOPRSYMBOL \"@$xt$13AircraftClass\"\n\tNOPRSYMBOL \"@$xt$12RawFileClass\"\n\tNOPRSYMBOL \"@$xt$9FileClass\"\n\tNOPRSYMBOL \"@$xt$11CDFileClass\"\n\tNOPRSYMBOL \"@$xt$12ExtFileClass\"\n\tNOPRSYMBOL \"@$xt$15ObjectTypeClass\"\n\tNOPRSYMBOL \"@$xt$11CCFileClass\"\n\tNOPRSYMBOL \"@$xt$15TechnoTypeClass\"\n\tNOPRSYMBOL \"@$xt$17AircraftTypeClass\"\n\tNOPRSYMBOL \"@$xt$10RadioClass\"\n\tNOPRSYMBOL \"@$xt$8FlyClass\"\n\tNOPRSYMBOL \"@$xt$11TechnoClass\"\n\tNOPRSYMBOL \"@$xt$11ObjectClass\"\n\tNOPRSYMBOL \"@$xt$12FlasherClass\"\n\tNOPRSYMBOL \"@$xt$10StageClass\"\n\tNOPRSYMBOL \"@$xt$10CargoClass\"\n\tNOPRSYMBOL \"@$xt$12MissionClass\"\n\tNOPRSYMBOL \"@$xt$13AnimTypeClass\"\n\tNOPRSYMBOL \"@$xt$n9AnimClass\"\n\tNOPRSYMBOL \"@$xt$n11SmudgeClass\"\n\tNOPRSYMBOL \"@$xt$27%ArrayOf$t9AnimClass$ii$25%\"\n\tNOPRSYMBOL \"@$xt$a25$9AnimClass\"\n\tNOPRSYMBOL \"@$xt$11SmudgeClass\"\n\tNOPRSYMBOL \"@$xt$9AnimClass\"\n\tNOPRSYMBOL \"@$xt$15BulletTypeClass\"\n\tNOPRSYMBOL \"@$xt$n13BuildingClass\"\n\tNOPRSYMBOL \"@$xt$10CacheClass\"\n\tNOPRSYMBOL \"@$xt$13BuildingClass\"\n\tNOPRSYMBOL \"@$xt$17BuildingTypeClass\"\n\tNOPRSYMBOL \"@$xt$n18ReinforcementClass\"\n\tNOPRSYMBOL \"@$xt$13InfantryClass\"\n\tNOPRSYMBOL \"@$xt$9UnitClass\"\n\tNOPRSYMBOL \"@$xt$32%ArrayOf$t13BuildingClass$ii$50%\"\n\tNOPRSYMBOL \"@$xt$a50$13BuildingClass\"\n\tNOPRSYMBOL \"@$xt$11TarComClass\"\n\tNOPRSYMBOL \"@$xt$18ReinforcementClass\"\n\tNOPRSYMBOL \"@$xt$8typeinfo\"\n\tNOPRSYMBOL \"@$xt$11TurretClass\"\n\tNOPRSYMBOL \"@$xt$10DriveClass\"\n\tNOPRSYMBOL \"@$xt$30%ArrayOf$t11BulletClass$ii$20%\"\n\tNOPRSYMBOL \"@$xt$a20$11BulletClass\"\n\tNOPRSYMBOL \"@$xt$n13TemplateClass\"\n\tNOPRSYMBOL \"@$xt$13TemplateClass\"\n\tNOPRSYMBOL \"@$xt$17TemplateTypeClass\"\n\tNOPRSYMBOL \"@$xt$12TerrainClass\"\n\tNOPRSYMBOL \"@$xt$x15ObjectTypeClass\"\n\tNOPRSYMBOL \"@$xt$16OverlayTypeClass\"\n\tNOPRSYMBOL \"@$xt$15SmudgeTypeClass\"\n\tNOPRSYMBOL \"@$xt$n12OverlayClass\"\n\tNOPRSYMBOL \"@$xt$12OverlayClass\"\n\tNOPRSYMBOL \"@$xt$n12MixFileClass\"\n\tNOPRSYMBOL \"@$xt$n11CCFileClass\"\n\tNOPRSYMBOL \"@$xt$16TerrainTypeClass\"\n\tNOPRSYMBOL \"@$xt$13UnitTypeClass\"\n\tNOPRSYMBOL \"@$xt$17InfantryTypeClass\"\n\tNOPRSYMBOL \"@$xt$12MixFileClass\"\n\tNOPRSYMBOL \"@$xt$n9UnitClass\"\n\tNOPRSYMBOL \"@$xt$a16$9MonoClass\"\n\tNOPRSYMBOL \"@$xt$10LogicClass\"\n\tNOPRSYMBOL \"@$xt$12DisplayClass\"\n\tNOPRSYMBOL \"@$xt$28%EMSListOf$tp12TriggerClass%\"\n\tNOPRSYMBOL \"@$xt$8MapClass\"\n\tNOPRSYMBOL \"@$xt$12SidebarClass\"\n\tNOPRSYMBOL \"@$xt$9HelpClass\"\n\tNOPRSYMBOL \"@$xt$a3$10LayerClass\"\n\tNOPRSYMBOL \"@$xt$10LayerClass\"\n\tNOPRSYMBOL \"@$xt$9MonoClass\"\n\tNOPRSYMBOL \"@$xt$11MemoryClass\"\n\tNOPRSYMBOL \"@$xt$16DebugMemoryClass\"\n\tNOPRSYMBOL \"@$xt$14EMSMemoryClass\"\n\tNOPRSYMBOL \"@$xt$27%EMSListOf$tp11ObjectClass%\"\n\tNOPRSYMBOL \"@$xt$n10HouseClass\"\n\tNOPRSYMBOL \"@$xt$a3$10HouseClass\"\n\tNOPRSYMBOL \"@$xt$10HouseClass\"\n\tNOPRSYMBOL \"@$xt$n13InfantryClass\"\n\tNOPRSYMBOL \"@$xt$32%ArrayOf$t13InfantryClass$ii$50%\"\n\tNOPRSYMBOL \"@$xt$a50$13InfantryClass\"\n\tNOPRSYMBOL \"@$xt$n9MonoClass\"\n\tNOPRSYMBOL \"@$xt$15DOSSegmentClass\"\n\tNOPRSYMBOL \"@$xt$30%ArrayOf$t12OverlayClass$ii$3%\"\n\tNOPRSYMBOL \"@$xt$a3$12OverlayClass\"\n\tNOPRSYMBOL \"@$xt$x15TechnoTypeClass\"\n\tNOPRSYMBOL \"@$xt$37%ArrayOf$t18ReinforcementClass$ii$15%\"\n\tNOPRSYMBOL \"@$xt$a15$18ReinforcementClass\"\n\tNOPRSYMBOL \"@$xt$29%ArrayOf$t11SmudgeClass$ii$1%\"\n\tNOPRSYMBOL \"@$xt$a1$11SmudgeClass\"\n\tNOPRSYMBOL \"@$xt$n12TerrainClass\"\n\tNOPRSYMBOL \"@$xt$31%ArrayOf$t13TemplateClass$ii$1%\"\n\tNOPRSYMBOL \"@$xt$a1$13TemplateClass\"\n\tNOPRSYMBOL \"@$xt$32%ArrayOf$t12TerrainClass$ii$120%\"\n\tNOPRSYMBOL \"@$xt$a120$12TerrainClass\"\n\tNOPRSYMBOL \"@$xt$n12TriggerClass\"\n\tNOPRSYMBOL \"@$xt$31%ArrayOf$t12TriggerClass$ii$26%\"\n\tNOPRSYMBOL \"@$xt$a26$12TriggerClass\"\n\tNOPRSYMBOL \"@$xt$12TriggerClass\"\n\tNOPRSYMBOL \"@$xt$28%ArrayOf$t9UnitClass$ii$120%\"\n\tNOPRSYMBOL \"@$xt$a120$9UnitClass\"\n\n\tNOPRSYMBOL \"cell.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"cell.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"combat.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"combat.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"display.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"display.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"display.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"display.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"display.cpp_NONPUB_$XL$4\"\n\tNOPRSYMBOL \"display.cpp_NONPUB_$XL$5\"\n\tNOPRSYMBOL \"foot.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"foot.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"globals.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"globals.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"house.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"house.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"house.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"house.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"idata.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"idata.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"idata.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"idata.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"infantry.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"infantry.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"infantry.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"infantry.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"infantry.cpp_NONPUB_$XL$4\"\n\tNOPRSYMBOL \"infantry.cpp_NONPUB_$XL$5\"\n\tNOPRSYMBOL \"infantry.cpp_NONPUB_$XL$6\"\n\tNOPRSYMBOL \"infantry.cpp_NONPUB_$XL$7\"\n\tNOPRSYMBOL \"init.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"init.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$4\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$5\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$6\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$7\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$8\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$9\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$10\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$11\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$12\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$13\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$14\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$15\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$16\"\n\tNOPRSYMBOL \"mono.cpp_NONPUB_$XL$17\"\n\tNOPRSYMBOL \"odata.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"odata.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"odata.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"odata.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"overlay.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"overlay.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"overlay.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"overlay.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"reinf.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"reinf.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"reinf.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"reinf.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"reinf.cpp_NONPUB_$XL$4\"\n\tNOPRSYMBOL \"reinf.cpp_NONPUB_$XL$5\"\n\tNOPRSYMBOL \"sdata.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"sdata.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"sdata.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"sdata.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"smudge.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"smudge.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"smudge.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"smudge.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"tdata.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"tdata.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"tdata.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"tdata.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"template.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"template.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"template.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"template.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"terrain.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"terrain.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"terrain.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"terrain.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"terrain.cpp_NONPUB_$XL$4\"\n\tNOPRSYMBOL \"terrain.cpp_NONPUB_$XL$5\"\n\tNOPRSYMBOL \"trigger.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"trigger.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"trigger.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"trigger.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"turret.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"turret.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"udata.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"udata.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"udata.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"udata.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"unit.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"unit.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"unit.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"unit.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"unit.cpp_NONPUB_$XL$4\"\n\tNOPRSYMBOL \"unit.cpp_NONPUB_$XL$5\"\n\tNOPRSYMBOL \"unit.cpp_NONPUB_$XL$6\"\n\tNOPRSYMBOL \"unit.cpp_NONPUB_$XL$7\"\n\tNOPRSYMBOL \"building.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"building.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"building.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"building.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"building.cpp_NONPUB_$XL$4\"\n\tNOPRSYMBOL \"building.cpp_NONPUB_$XL$5\"\n\tNOPRSYMBOL \"building.cpp_NONPUB_$XL$6\"\n\tNOPRSYMBOL \"building.cpp_NONPUB_$XL$7\"\n\tNOPRSYMBOL \"building.cpp_NONPUB_$XL$8\"\n\tNOPRSYMBOL \"building.cpp_NONPUB_$XL$9\"\n\tNOPRSYMBOL \"building.cpp_NONPUB_$XL$10\"\n\tNOPRSYMBOL \"building.cpp_NONPUB_$XL$11\"\n\tNOPRSYMBOL \"aadata.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"aadata.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"aircraft.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"aircraft.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"aircraft.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"aircraft.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"aircraft.cpp_NONPUB_$XL$4\"\n\tNOPRSYMBOL \"aircraft.cpp_NONPUB_$XL$5\"\n\tNOPRSYMBOL \"anim.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"anim.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"anim.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"anim.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"bdata.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"bdata.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"bdata.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"bdata.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"bdata.cpp_NONPUB_$XL$4\"\n\tNOPRSYMBOL \"bdata.cpp_NONPUB_$XL$5\"\n\tNOPRSYMBOL \"bullet.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"bullet.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"bullet.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"bullet.cpp_NONPUB_$XL$3\"\n\tNOPRSYMBOL \"cdata.cpp_NONPUB_$XL$0\"\n\tNOPRSYMBOL \"cdata.cpp_NONPUB_$XL$1\"\n\tNOPRSYMBOL \"cdata.cpp_NONPUB_$XL$2\"\n\tNOPRSYMBOL \"cdata.cpp_NONPUB_$XL$3\"\n\n\tPRFILE AIRCRAFT.OBJ\n\tPRFILE ANIM.OBJ\n\tPRFILE BBDATA.OBJ\n\tPRFILE BULLET.OBJ\n\tPRFILE AADATA.OBJ\n\tPRFILE ADATA.OBJ\n\tPRFILE ALLOC.OBJ\n\tPRFILE AUDIO.OBJ\n\tPRFILE BDATA.OBJ\n\tPRFILE BUTTON.OBJ\n\tPRFILE BUILDING.OBJ\n\tPRFILE CACHE.OBJ\n\tPRFILE CARGO.OBJ\n\tPRFILE CCFILE.OBJ\n\tPRFILE CDATA.OBJ\n\tPRFILE CDFILE.OBJ\n\tPRFILE CELL.OBJ\n\tPRFILE COMBAT.OBJ\n\tPRFILE CONQUER.OBJ\n\tPRFILE CONST.OBJ\n\tPRFILE COORD.OBJ\n\tPRFILE CREDITS.OBJ\n\tPRFILE CREW.OBJ\n\tPRFILE CURSOR.OBJ\n\tPRFILE DEBUG.OBJ\n\tPRFILE DIALOG.OBJ\n\tPRFILE DISPLAY.OBJ\n\tPRFILE DPMI.OBJ\n\tPRFILE DRIVE.OBJ\n\tPRFILE EXTFILE.OBJ\n\tPRFILE FINDPATH.OBJ\n\tPRFILE FLASHER.OBJ\n\tPRFILE FLY.OBJ\n\tPRFILE FOOT.OBJ\n\tPRFILE FUSE.OBJ\n\tPRFILE GLOBALS.OBJ\n\tPRFILE HDATA.OBJ\n\tPRFILE HOUSE.OBJ\n\tPRFILE IDATA.OBJ\n\tPRFILE INFANTRY.OBJ\n\tPRFILE INI.OBJ\n\tPRFILE INIT.OBJ\n\tPRFILE JSHELL.OBJ\n\tPRFILE LAYER.OBJ\n\tPRFILE LOGIC.OBJ\n\tPRFILE MAP.OBJ\n\tPRFILE MAPEDDLG.OBJ\n\tPRFILE MAPEDIT.OBJ\n\tPRFILE MAPEDPLC.OBJ\n\tPRFILE MAPEDSEL.OBJ\n\tPRFILE MEMORY.OBJ\n\tPRFILE MENUS.OBJ\n\tPRFILE MISSION.OBJ\n\tPRFILE MIXFILE.OBJ\n\tPRFILE MONO.OBJ\n\tPRFILE OBJECT.OBJ\n\tPRFILE HELP.OBJ\n\tPRFILE ODATA.OBJ\n\tPRFILE OPTIONS.OBJ\n\tPRFILE OVERLAY.OBJ\n\tPRFILE PROFILE.OBJ\n\tPRFILE RADIO.OBJ\n\tPRFILE RAWFILE.OBJ\n\tPRFILE REINF.OBJ\n\tPRFILE SAVELOAD.OBJ\n\tPRFILE SCENARIO.OBJ\n\tPRFILE SCORE.OBJ\n\tPRFILE SDATA.OBJ\n\tPRFILE SIDEBAR.OBJ\n\tPRFILE SMUDGE.OBJ\n\tPRFILE STARTUP.OBJ\n\tPRFILE SUPPORT.OBJ\n\tPRFILE TARCOM.OBJ\n\tPRFILE TARGET.OBJ\n\tPRFILE TDATA.OBJ\n\tPRFILE TECHNO.OBJ\n\tPRFILE TEMPLATE.OBJ\n\tPRFILE TERRAIN.OBJ\n\tPRFILE TEXT.OBJ\n\tPRFILE THEME.OBJ\n\tPRFILE TRIGGER.OBJ\n\tPRFILE TURRET.OBJ\n\tPRFILE UDATA.OBJ\n\tPRFILE UNIT.OBJ\n\n\tPRMODULE addlong.asm\n\tPRMODULE iconset.c\n\tPRMODULE addlong.asm\n\tPRMODULE bitblit.asm\n\tPRMODULE buff.asm\n\tPRMODULE buffer.asm\n\tPRMODULE buffpage.asm\n\tPRMODULE button.c\n\tPRMODULE clear.asm\n\tPRMODULE dipthong.c\n\tPRMODULE drawchar.asm\n\tPRMODULE drawline.asm\n\tPRMODULE drawrect.c\n\tPRMODULE drawshp.asm\n\tPRMODULE ems.asm\n\tPRMODULE emsmem.c\n\tPRMODULE fadeblit.c\n\tPRMODULE fillrect.asm\n\tPRMODULE font.c\n\tPRMODULE iconset.c\n\tPRMODULE iff.c\n\tPRMODULE input.c\n\tPRMODULE irandom.c\n\tPRMODULE lib.c\n\tPRMODULE load.c\n\tPRMODULE locking.c\n\tPRMODULE lpage.c\n\tPRMODULE mem_copy.asm\n\tPRMODULE palette.c\n\tPRMODULE putpixel.asm\n\tPRMODULE remap.asm\n\tPRMODULE select.asm\n\tPRMODULE shakescr.asm\n\tPRMODULE shape.c\n\tPRMODULE shapeinf.asm\n\tPRMODULE sizeof.asm\n\tPRMODULE stamp.asm\n\tPRMODULE textprnt.asm\n\tPRMODULE uncomp.asm\n\tPRMODULE windows.c\n\tPRSYMBOL _ldiv\n\tPRSYMBOL __ldiv\n#\tPRMODULE shape.c\n#\tPRMODULE uncomp.asm\n\n"
  },
  {
    "path": "CODE/QUEUE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /counterstrike/QUEUE.CPP 6     3/14/97 5:12p Steve_tall $ */\n/***************************************************************************\n ***              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               ***\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : QUEUE.CPP                                *\n *                                                                         *\n *                   Programmer : Bill R. Randolph                         *\n *                                                                         *\n *                   Start Date : 11/28/95                                 *\n *                                                                         *\n *                  Last Update : October 14, 1996 [BRR]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions for Queueing Events:                                          *\n *   Queue_Mission -- Queue a mega mission event.                          *\n *   Queue_Options -- Queue the options event.                             *\n *   Queue_Exit -- Add the exit game event to the queue.                   *\n *                                                                         *\n * Functions for processing Queued Events:\t\t\t\t\t\t\t\t\t\t\t*\n *   Queue_AI -- Process all queued events.                                *\n *   Queue_AI_Normal -- Process all queued events.                         *\n *   Queue_AI_Multiplayer -- Process all queued events.                    *\n *                                                                         *\n * Main Multiplayer Queue Logic:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Wait_For_Players -- Waits for other systems to come on-line           *\n *   Generate_Timing_Event -- computes & queues a RESPONSE_TIME event      *\n *   Process_Send_Period -- timing for sending packets every 'n' frames    *\n *   Send_Packets -- sends out events from the OutList                     *\n *   Send_FrameSync -- Sends a FRAMESYNC packet                            *\n *   Process_Receive_Packet -- processes an incoming packet                *\n *   Process_Serial_Packet -- Handles an incoming serial packet            *\n *   Can_Advance -- determines if it's OK to advance to the next frame     *\n *   Process_Reconnect_Dialog -- processes the reconnection dialog         *\n *   Handle_Timeout -- attempts to reconnect; if fails, bails.             *\n *   Stop_Game -- stops the game\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * Packet Compression / Decompression:\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Build_Send_Packet -- Builds a big packet from a bunch of little ones.\t*\n *   Add_Uncompressed_Events -- adds uncompressed events to a packet       *\n *   Add_Compressed_Events -- adds compressed events to a packet        \t*\n *   Breakup_Receive_Packet -- Splits a big packet into little ones.\t\t\t*\n *   Extract_Uncompressed_Events -- extracts events from a packet\t\t\t\t*\n *   Extract_Compressed_Events -- extracts events from a packet            *\n *                                                                         *\n * DoList Management:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Execute_DoList -- Executes commands from the DoList                   *\n *   Clean_DoList -- Cleans out old events from the DoList                 *\n *   Queue_Record -- Records the DoList to disk                            *\n *   Queue_Playback -- plays back queue entries from a record file         *\n *                                                                         *\n * Debugging:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Compute_Game_CRC -- Computes a CRC value of the entire game.\t\t\t\t*\n *   Add_CRC -- Adds a value to a CRC                                      *\n *   Print_CRCs -- Prints a data file for finding Sync Bugs\t\t\t\t\t\t*\n *   Init_Queue_Mono -- inits mono display                                 *\n *   Update_Queue_Mono -- updates mono display                             *\n *   Print_Framesync_Values -- displays frame-sync variables               *\n *   Check_Mirror -- Checks mirror memory                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include\t\"function.h\"\n\n#ifdef WOLAPI_INTEGRATION\n//#include \"WolDebug.h\"\n#include \"WolapiOb.h\"\nextern WolapiObject* pWolapi;\n\nbool bReconnectDialogCancelled;\n#endif\n\n\n/********************************** Defines *********************************/\n#define SHOW_MONO\t0\n\n\n/********************************** Globals *********************************/\n//---------------------------------------------------------------------------\n//\tGameCRC is the current computed CRC value for this frame.\n//\tCRC[] is a record of our last 32 game CRC's.\n// ColorNames is for debug output in Print_CRCs\n//---------------------------------------------------------------------------\nstatic unsigned long GameCRC;\nstatic unsigned long CRC[32] =\n\t{0,0,0,0,0,0,0,0,0,0,\n\t 0,0,0,0,0,0,0,0,0,0,\n\t 0,0,0,0,0,0,0,0,0,0,\n\t 0,0};\nstatic char *ColorNames[8] = {\n\t\"Yellow\",\n\t\"LtBlue\",\n\t\"Red\",\n\t\"Green\",\n\t\"Orange\",\n\t\"Grey\",\n\t\"Blue\",\n\t\"Brown\"\n};\n\n//...........................................................................\n// Mono debugging variables:\n// NetMonoMode: 0 = show connection output, 1 = flowcount output\n// NewMonoMode: set by anything that toggles NetMonoMode; re-inits screen\n// IsMono: used for taking control of Mono screen away from the engine\n//...........................................................................\nint NetMonoMode = 1;\nint NewMonoMode = 1;\nstatic int IsMono = 0;\n\n//---------------------------------------------------------------------------\n// Several routines return various codes; here's an enum for all of them.\n//---------------------------------------------------------------------------\ntypedef enum RetcodeEnum {\n\tRC_NORMAL,\t\t\t\t\t\t// no news is good news\n\tRC_PLAYER_READY,\t\t\t\t// a new player has been heard from\n\tRC_SCENARIO_MISMATCH,\t\t// scenario mismatch\n\tRC_DOLIST_FULL,\t\t\t\t// DoList is full\n\tRC_SERIAL_PROCESSED,\t\t\t// modem: SERIAL packet was processed\n\tRC_PLAYER_LEFT,\t\t\t\t// modem: other player left the game\n\tRC_HUNG_UP,\t\t\t\t\t\t// modem has hung up\n\tRC_NOT_RESPONDING,\t\t\t// other player not responding (timeout/hung up)\n\tRC_CANCEL,\t\t\t\t\t\t// user cancelled\n} RetcodeType;\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern void Enable_Secret_Units(void);\n#endif\n\n/********************************* Prototypes *******************************/\n//...........................................................................\n// Main multiplayer queue logic\n//...........................................................................\nstatic void Queue_AI_Normal(void);\nstatic void Queue_AI_Multiplayer(void);\nstatic RetcodeType Wait_For_Players(int first_time, ConnManClass *net,\n\tint resend_delta, int dialog_time, int timeout, char *multi_packet_buf,\n\tint my_sent, long *their_frame,  unsigned short *their_sent,\n\tunsigned short *their_recv);\nstatic void Generate_Timing_Event(ConnManClass *net, int my_sent);\nstatic void Generate_Real_Timing_Event(ConnManClass *net, int my_sent);\nstatic void Generate_Process_Time_Event(ConnManClass *net);\nstatic int Process_Send_Period(ConnManClass *net);\t//, int init);\nstatic int Send_Packets(ConnManClass *net, char *multi_packet_buf,\n\tint multi_packet_max, int max_ahead, int my_sent);\nstatic void Send_FrameSync(ConnManClass *net, int cmd_count);\nstatic RetcodeType Process_Receive_Packet(ConnManClass *net,\n\tchar *multi_packet_buf, int id, int packetlen, long *their_frame,\n\tunsigned short *their_sent, unsigned short *their_recv);\nstatic RetcodeType Process_Serial_Packet(char *multi_packet_buf,\n\tint first_time);\nstatic int Can_Advance(ConnManClass *net, int max_ahead, long *their_frame,\n\tunsigned short *their_sent, unsigned short *their_recv);\nstatic int Process_Reconnect_Dialog(CDTimerClass<SystemTimerClass> *timeout_timer,\n\tlong *their_frame, int num_conn, int reconn, int fresh);\nstatic int Handle_Timeout(ConnManClass *net, long *their_frame,\n\tunsigned short *their_sent, unsigned short *their_recv);\nstatic void Stop_Game(void);\n\n//...........................................................................\n// Packet compression/decompression:\n//...........................................................................\nstatic int Build_Send_Packet(void *buf, int bufsize, int frame_delay,\n\tint num_cmds, int cap);\nint Add_Uncompressed_Events(void *buf, int bufsize, int frame_delay, int size,\n\tint cap);\nint Add_Compressed_Events(void *buf, int bufsize, int frame_delay, int size,\n\tint cap);\nstatic int Breakup_Receive_Packet(void *buf, int bufsize );\nint Extract_Uncompressed_Events(void *buf, int bufsize);\nint Extract_Compressed_Events(void *buf, int bufsize);\n\n//...........................................................................\n// DoList management:\n//...........................................................................\nstatic int Execute_DoList(int max_houses, HousesType base_house,\n\tConnManClass *net, CDTimerClass<FrameTimerClass> *skip_crc,\n//\tConnManClass *net, TCountDownTimerClass *skip_crc,\n\tlong *their_frame, unsigned short *their_sent, unsigned short *their_recv);\nstatic void Clean_DoList(ConnManClass *net);\nstatic void Queue_Record(void);\nstatic void Queue_Playback(void);\n\n//...........................................................................\n// Debugging:\n//...........................................................................\nstatic void Compute_Game_CRC(void);\nvoid Add_CRC(unsigned long *crc, unsigned long val);\nstatic void Print_CRCs(EventClass *ev);\nstatic void Init_Queue_Mono(ConnManClass *net);\nstatic void Update_Queue_Mono(ConnManClass *net, int flow_index);\nstatic void Print_Framesync_Values(long curframe, unsigned long max_ahead,\n\tint num_connections, unsigned short *their_recv,\n\tunsigned short *their_sent, unsigned short my_sent);\n\nextern void Keyboard_Process(KeyNumType &input);\nvoid Dump_Packet_Too_Late_Stuff(EventClass *event, ConnManClass *net,\n\tlong *their_frame, unsigned short *their_sent, unsigned short *their_recv);\nvoid Check_Mirror(void);\n\n\n/***************************************************************************\n * Queue_Mission -- Queue a mega mission event.                            *\n *                                                                         *\n * This routine is called when the player causes a change to a game unit. \t*\n * The event that initiates the change is queued to as a result of a call \t*\n * to this routine.                 \t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\twhom\t\tWhom this mission request applies to (a friendly unit).     *\n *    mission\tThe mission to assign to this object.                       *\n *    target\tThe target of this mission (if any).                        *\n *    dest\t\tThe movement destination for this mission (if any).         *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tWas the mission request queued successfully?                         *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.                                                                *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/21/1995 JLB : Created.                                             *\n *=========================================================================*/\nbool Queue_Mission(TargetClass whom, MissionType mission, TARGET target, TARGET destination)\n{\n\tif (! OutList.Add(EventClass(whom, mission, TargetClass(target), TargetClass(destination)))) {\n\t\treturn(false);\n\t} else {\n\t\treturn(true);\n\t}\n}\n\n\n/***********************************************************************************************\n * Queue_Mission -- Queue a mega mission event, formation override for common speed.           *\n *                                                                                             *\n *    This routine is called when the player causes a change to a game unit. The event that    *\n *    initiates the change is queued to as a result of a call to this routine.                 *\n *                                                                                             *\n * INPUT:   whom     -- Whom this mission request applies to (a friendly unit).                *\n *                                                                                             *\n *          mission  -- The mission to assign to this object.                                  *\n *                                                                                             *\n *          target   -- The target of this mission (if any).                                   *\n *                                                                                             *\n *          dest     -- The movement destination for this mission (if any).                    *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\tspeed\t   -- The override speed for this unit.\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\tmaxspeed -- The override maximum speed for this unit.\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:  Was the mission request queued successfully?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool Queue_Mission(TargetClass whom, MissionType mission, TARGET target, TARGET destination, SpeedType speed, MPHType maxspeed)\n{\n\tif (! OutList.Add(EventClass(whom, mission, TargetClass(target), TargetClass(destination), speed, maxspeed))) {\n\t\treturn(false);\n\t} else {\n\t\treturn(true);\n\t}\n}\n\n\n/***************************************************************************\n * Queue_Options -- Queue the options event.                               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tWas the options screen event queued successfully?                    *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/21/1995 JLB : Created.                                             *\n *=========================================================================*/\nbool Queue_Options(void)\n{\n\tif (! OutList.Add(EventClass(EventClass::OPTIONS))) {\n\t\treturn(false);\n\t}\n\telse {\n\t\treturn(true);\n\t}\n\n}\t\t/* end of Queue_Options */\n\n\n/***************************************************************************\n * Queue_Exit -- Add the exit game event to the queue.                     *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tWas the exit event queued successfully?                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/21/1995 JLB : Created.                                             *\n *=========================================================================*/\nbool Queue_Exit(void)\n{\n\tif (! OutList.Add(EventClass(EventClass::EXIT))) {\n\t\treturn(false);\n\t}\n\telse {\n\t\treturn(true);\n\t}\n\n}\t\t/* end of Queue_Exit */\n\n\n/***************************************************************************\n * Queue_AI -- Process all queued events.                                  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/21/1995 JLB : Created.                                             *\n *=========================================================================*/\nvoid Queue_AI(void)\n{\n\tif (Session.Play) {\n\t\tQueue_Playback();\n\t}\n\n\telse {\n\n\t\tswitch (Session.Type) {\n\n\t\t\tcase GAME_SKIRMISH:\n\t\t\tcase GAME_NORMAL:\n\t\t\t\tQueue_AI_Normal();\n\t\t\t\tbreak;\n\n\t\t\tcase GAME_MODEM:\n\t\t\tcase GAME_NULL_MODEM:\n\t\t\tcase GAME_IPX:\n\t\t\tcase GAME_INTERNET:\n\t\t\tcase GAME_TEN:\n\t\t\tcase GAME_MPATH:\n\t\t\t\tQueue_AI_Multiplayer();\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n}\t/* end of Queue_AI */\n\n\n/***************************************************************************\n * Queue_AI_Normal -- Process all queued events.                           *\n *                                                                         *\n * This is the \"normal\" version of the queue management routine.  It does \t*\n * the following:\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Transfers items in the OutList to the DoList\t\t\t\t\t\t\t\t\t*\n * - Executes any commands in the DoList that are supposed to be done on \t*\n *   this frame #\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Cleans out the DoList\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/21/1995 JLB : Created.                                             *\n *=========================================================================*/\nstatic void Queue_AI_Normal(void)\n{\n\t//------------------------------------------------------------------------\n\t//\tMove events from the OutList (events generated by this player) into the\n\t//\tDoList (the list of events to execute).\n\t//------------------------------------------------------------------------\n\twhile (OutList.Count) {\n\t\tOutList.First().IsExecuted = false;\n\t\tif (!DoList.Add(OutList.First())) {\n\t\t\t;\n\t\t}\n\t\t#ifdef MIRROR_QUEUE\n\t\tMirrorList.Add(OutList.First());\n\t\t#endif\n\t\tOutList.Next();\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Save the DoList to disk, if we're in \"Record\" mode\n\t//------------------------------------------------------------------------\n\tif (Session.Record) {\n\t\tQueue_Record();\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Execute the DoList; if an error occurs, bail out.\n\t//------------------------------------------------------------------------\n\tif (!Execute_DoList(1, PlayerPtr->Class->House, NULL, NULL, NULL,\n\t\tNULL, NULL)) {\n\t\tGameActive = 0;\n\t\treturn;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tClean out the DoList\n\t//------------------------------------------------------------------------\n\tClean_DoList(NULL);\n\n}\t/* end of Queue_AI_Normal */\n\n\n/***************************************************************************\n * Queue_AI_Multiplayer -- Process all queued events.                      *\n *                                                                         *\n * This is the network version of the queue management routine.  It does \t*\n * the following:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - If this is the 1st frame, waits for other systems to signal ready\t\t*\n * - Generates a timing event, to allow the connection time to be dynamic\t*\n * - Handles timing related to sending packets every 'n' frames\t\t\t\t*\n * - Sends outgoing events\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Frame-syncs to the other systems (see below)\t\t\t\t\t\t\t\t\t*\n * - Executes & cleans out the DoList\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The Frame-Sync'ing logic is the heart & soul of network play.  It works\t*\n * by ensuring that any system won't out-run the other system by more than\t*\n * 'Session.MaxAhead' frames; this in turn ensures that a packet's \t\t\t*\n * execution frame # won't have been passed by the time that packet is \t\t*\n * received by all systems.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * To achieve this, the system must keep track of all other system's \t\t*\n * current frame #'s; these are stored in an array called 'their_frame[]'. *\n * However, because current frame #'s are sent in FRAMEINFO packets, which *\n * don't require an ACK, and command packets are sent in packets requiring *\n * an ACK, it's possible for a command packet to get lost, and the next \t*\n * frame's FRAMEINFO packet to not get lost; the other system may then \t\t*\n * advance past the frame # the command is to execute on!  So, to prevent \t*\n * this, all FRAMEINFO packets include a CommandCount field.  This value \t*\n * tells the other system how many events it should have received by this \t*\n * time.  This system can therefore keep track of how many commands it's\t*\n * actually received, and compare it to the CommandCount field, to see if \t*\n * it's missed an event packet.  The # of events we've received from each \t*\n * system is stored in 'their_recv[]', and the # events they say they've \t*\n * sent is stored in 'their_sent[]'.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * Thus, two conditions must be met in order to advance to the next frame:\t*\n * - Our current frame # must be < their_frame + Session.MaxAhead\t\t\t\t*\n * - their_recv[i] must be >= their_sent[i]\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * 'their_frame[] is updated by Process_Receive_Packet()\t\t\t\t\t\t\t*\n * 'their_recv[] is updated by Process_Receive_Packet()\t\t\t\t\t\t\t*\n * 'their_sent[] is updated by Process_Receive_Packet()\t\t\t\t\t\t\t*\n * 'my_sent' is updated by this routine.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The order of the arrays their_frame[] etc is the same order the \t\t\t*\n * connections are created in.  The Sender's ID is passed to \t\t\t\t\t*\n * Connection_Index() to obtain the array index.\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The only routines allowed to pop up dialogs are:\t\t\t\t\t\t\t\t*\n * \tWait_For_Players() (only pops up the reconnect dialog)\t\t\t\t\t*\n * \tExecute_DoList() (tells if out of sync, or packet recv'd too late)\t*\n *                                                                         *\n * Sign-off's are detected by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Timing out while waiting for a packet\t\t\t\t\t\t\t\t\t\t\t*\n * - Detecting that the other player is now at the score screen or \t\t\t*\n *   connection dialog (serial)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - If we see an EventClass::EXIT event on the private channel\t\t\t\t*\n *                                                                         *\n * The current communications protocol, COMM_PROTOCOL_MULTI_E_COMP, has \t*\n * the following properties:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - It compresses packets, so that the minimum number of bytes are \t\t\t*\n *   transmitted.  Packets are compressed by extracting all info common to *\n *   the events into the packet header, and then sending only the bytes \t*\n *   relevant to each type of event.  For instance, if 100 infantry guys \t*\n *   are told to move to the same location, the command itself & the \t\t*\n *   location will be included in the 1st movement command only; after \t\t*\n *   that, there will be a rep count then 99 infantry TARGET numbers, \t\t*\n *   identifying all the infantry told to move.\t\t\t\t\t\t\t\t\t\t*\n * - The protocol also only sends packets out every 'n' frames.  This cuts *\n *   the data rate dramatically.  It means that 'Session.MaxAhead' must be *\n *   divisible by 'n'; also, the minimum value for 'Session.MaxAhead' is \t*\n *   'n * 2', to give both sides some \"breathing\" room in case a FRAMEINFO\t*\n *   packet gets missed.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * Note:  For synchronization-waiting loops (like waiting to hear from all *\n * other players, waiting to advance to the next frame, etc), use \t\t\t*\n * Net.Num_Connections() rather than Session.NumPlayers; this reflects the *\n * actual # of connections, and can be \"faked\" into playing even when \t\t*\n * there aren't any other players actually there.  A typical example of \t*\n * this is playing back a recorded game.  For command-execution loops, use *\n * Session.NumPlayers.  This ensures all commands get executed, even if \t*\n * there isn't a human generating those commands.\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The modem works a little differently from the network in this respect:\t*\n * - The connection has to stay \"alive\" even if the other player exits to \t*\n *   the join dialog.  This prevents each system from timing out & hanging *\n *   the modem up.  Thus, packets are sent back & forth & just thrown away,*\n *   but each system knows the other is still there.  Messages may be sent\t*\n *   between systems, though. \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Destroy_Null_Connection doesn't hang up the modem, so \t\t\t\t\t\t*\n *   Num_Connections() still reports a value of 1 even though the other \t*\n *   player has left.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Any waits on Num_Connections() must also check for \t\t\t\t\t\t\t*\n *   Session.NumPlayers > 1, to keep from waiting forever if the other \t\t*\n *   guy has left\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Packets sent to a player who's left require no ACK\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Queue_AI_Multiplayer(void)\n{\n\tif(Session.Type == GAME_SKIRMISH) return;\n\n\t//........................................................................\n\t// Enums:\n\t//........................................................................\n\tenum {\n\t\tMIXFILE_RESEND_DELTA = 120,\t// ticks b/w resends\n\t\tMIXFILE_TIMEOUT = 3600*2,\t\t// timeout waiting for mixfiles.\n\t\tFRAMESYNC_DLG_TIME = (3*60),\t// time until displaying reconnect dialog\n\t\tFRAMESYNC_TIMEOUT = (15*60),\t// timeout waiting for frame sync packet\n\t};\n\n\tint timeout_factor = (Session.Type == GAME_INTERNET) ? 6 : 1;\n\n\t//........................................................................\n\t// Variables for sending, receiving & parsing packets:\n\t//........................................................................\n\tConnManClass *net;\t\t\t\t\t// ptr to access all multiplayer functions\n\tEventClass packet;\t\t\t\t\t// for sending single frame-sync's\n\tchar *multi_packet_buf;\t\t\t\t// buffer for sending/receiving\n\tint multi_packet_max;\t\t\t\t// max length of multi_packet_buf\n\n\t//........................................................................\n\t// Frame-sync'ing variables\n\t//........................................................................\n\tstatic long\n\t\ttheir_frame[MAX_PLAYERS - 1];\t// other players' frame #'s\n\tstatic unsigned short\n\t\ttheir_sent[MAX_PLAYERS - 1];\t// # cmds other player claims to have sent\n\tstatic unsigned short\n\t\ttheir_recv[MAX_PLAYERS - 1];\t// # cmds actually received from others\n\tstatic unsigned short\n\t\tmy_sent;\t\t\t\t\t\t\t\t// # cmds I've sent out\n\n\t//........................................................................\n\t// Timing variables\n\t//........................................................................\n\tstatic CDTimerClass<FrameTimerClass> skip_crc;\t// to delay the CRC check\n//\tstatic TCountDownTimerClass skip_crc;\t// to delay the CRC check\n\n\t//........................................................................\n\t// Other misc variables\n\t//........................................................................\n\tint i;\n\tRetcodeType rc;\n\tint reconnect_dlg = 0;\t\t\t\t// 1 = the reconnect dialog is displayed\n\n\t//------------------------------------------------------------------------\n\t//\tInitialize the packet buffer pointer & its max size\n\t//------------------------------------------------------------------------\n\tif (Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) {\n\t\tmulti_packet_buf = NullModem.BuildBuf;\n\t\tmulti_packet_max = NullModem.MaxLen - sizeof (CommHeaderType);\n\t\tnet = &NullModem;\n\t} else if (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) {\n\t\tmulti_packet_buf = Session.MetaPacket;\n\t\tmulti_packet_max = Session.MetaSize;\n\t\tnet = &Ipx;\n\t}\n#if(TEN)\n\telse if (Session.Type == GAME_TEN) {\n\t\tmulti_packet_buf = Session.TenPacket;\n\t\tmulti_packet_max = Session.TenSize;\n\t\tnet = Ten;\n\t}\n#endif\n#if(MPATH)\n\telse if (Session.Type == GAME_MPATH) {\n\t\tmulti_packet_buf = Session.MPathPacket;\n\t\tmulti_packet_max = Session.MPathSize;\n\t\tnet = MPath;\n\t}\n#endif\n\n\t//------------------------------------------------------------------------\n\t//\tDebug stuff\n\t//------------------------------------------------------------------------\n\tInit_Queue_Mono(net);\n\tUpdate_Queue_Mono (net, 0);\n\n\t//------------------------------------------------------------------------\n\t//\tCompute the Game's CRC\n\t//------------------------------------------------------------------------\n\tCompute_Game_CRC();\n\tCRC[Frame & 0x001f] = GameCRC;\n\n\t//------------------------------------------------------------------------\n\t//\tIf we've just started a game, or loaded a multiplayer game, we must\n\t// wait for all other systems to signal ready.\n\t//------------------------------------------------------------------------\n\tif (Frame==0 || Session.LoadGame) {\n\t\t//.....................................................................\n\t\t//\tInitialize static locals\n\t\t//.....................................................................\n\t\tfor (i = 0; i < MAX_PLAYERS - 1; i++) {\n\t\t\ttheir_frame[i] = -1;\n\t\t\ttheir_sent[i] = 0;\n\t\t\ttheir_recv[i] = 0;\n\t\t}\n\t\tmy_sent = 0;\n#ifdef FIXIT_MULTI_SAVE\n\t\tskip_crc = 32;\n#else\n\t\tskip_crc = Frame + 32;\n#endif\t// FIXIT_MULTI_SAVE\n\t\tfor (i = 0; i < 32; i++)\n\t\t\tCRC[i] = 0;\n\n\t\t//.....................................................................\n\t\t// If we've loaded a saved game:\n\t\t// - If this game was saved as the result of a lost connection, clear\n\t\t//   the CRC value so it will always match the other system's\n\t\t// - Otherwise, use the GameCRC value, so we'll compare save-game files\n\t\t//   rather than scenario INI files\n\t\t//.....................................................................\n\t\tif (Session.LoadGame) {\n\t\t\tif (Session.EmergencySave)\n\t\t\t\tScenarioCRC = 0;\n\t\t\telse\n\t\t\t\tScenarioCRC = GameCRC;\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Send our initial FRAMESYNC packet\n\t\t//.....................................................................\n\t\tSend_FrameSync(net, my_sent);\n\n\t\t//.....................................................................\n\t\t// Wait for the other guys\n\t\t//.....................................................................\n\t\trc = Wait_For_Players (1, net, MIXFILE_RESEND_DELTA, FRAMESYNC_DLG_TIME*timeout_factor,\n\t\t\tMIXFILE_TIMEOUT, multi_packet_buf, my_sent, their_frame,\n\t\t\ttheir_sent, their_recv);\n\n\t\tif (rc != RC_NORMAL) {\n#ifdef WIN32\n\t\t\tif (Session.Type == GAME_INTERNET){\n\t\t\t\tRegister_Game_End_Time();\n\t\t\t}\n#endif\t//WIN32\n\n\t\t\tif (rc == RC_NOT_RESPONDING) {\n\t\t\t\tWWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);\n\t\t\t}\n\t\t\telse if (rc == RC_SCENARIO_MISMATCH) {\n\t\t\t\tWWMessageBox().Process (TXT_SCENARIOS_DO_NOT_MATCH);\n\t\t\t}\n\t\t\telse if (rc == RC_DOLIST_FULL) {\n\t\t\t\tWWMessageBox().Process(TXT_QUEUE_FULL);\n\t\t\t}\n\t\t\tStop_Game();\n\t\t\treturn;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tRe-initialize frame numbers (in case somebody signed off while I was\n\t\t//\twaiting for MIX files to load; we would have fallen through, but\n\t\t//\ttheir frame # would still be -1).\n\t\t//.....................................................................\n\t\tfor (i = 0; i < MAX_PLAYERS - 1; i++)\n\t\t\ttheir_frame[i] = 0;\n\n\t\t//.....................................................................\n\t\t//\tReset the network response time computation, now that we're both\n\t\t// sending data again  (loading MIX files will have introduced\n\t\t// deceptively large values).\n\t\t//.....................................................................\n\t\tnet->Reset_Response_Time();\n\n\t\t//.....................................................................\n\t\t// Initialize the frame timers\n\t\t//.....................................................................\n\t\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\t\tProcess_Send_Period(net);//, 1);\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Turn off our special load-game flags\n\t\t//.....................................................................\n\t\tif (Session.LoadGame) {\n\t\t\tSession.EmergencySave = false;\n\t\t\tSession.LoadGame = false;\n\t\t}\n\n\t} \t// end of Frame 0 wait\n\n\t//------------------------------------------------------------------------\n\t// Adjust connection timing parameters every 128 frames.\n\t//------------------------------------------------------------------------\n\n\telse if ( (Frame & 0x007f) == 0) {\n\t\t//\n\t\t// If we're using the new spiffy protocol, do proper timing handling.\n\t\t// If we're the net \"master\", compute our desired frame rate & new\n\t\t// 'MaxAhead' value.\n\t\t//\n\t\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\n\t\t\t//\n\t\t\t// All systems will transmit their required process time.\n\t\t\t//\n\t\t\tGenerate_Process_Time_Event(net);\n\n\t\t\t//\n\t\t\t// The game \"host\" will transmit timing adjustment events.\n\t\t\t//\n\t\t\tif (Session.Am_I_Master()) {\n\t\t\t\tGenerate_Real_Timing_Event(net, my_sent);\n\t\t\t}\n\t\t} else {\n\t\t\t//\n\t\t\t// For the older protocols, do the old broken timing handling.\n\t\t\t//\n\t\t\tGenerate_Timing_Event(net, my_sent);\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Only process every 'FrameSendRate' frames\n\t//------------------------------------------------------------------------\n\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\tif (!Process_Send_Period(net)) {\t//, 0)) {\n\t\t\tif (IsMono) {\n\t\t\t\tMonoClass::Disable();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Send our data packet(s); update my command-sent counter\n\t//------------------------------------------------------------------------\n\tmy_sent += Send_Packets(net, multi_packet_buf, multi_packet_max,\n\t\tSession.MaxAhead, my_sent);\n\n\t//------------------------------------------------------------------------\n\t//\tIf this is our first time through, we're done.\n\t//------------------------------------------------------------------------\n\tif (Frame==0) {\n\t\tif (IsMono) {\n\t\t\tMonoClass::Disable();\n\t\t}\n\t\treturn;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tFrame-sync'ing: wait until it's OK to advance to the next frame.\n\t//------------------------------------------------------------------------\n#ifdef FIXIT_VERSION_3\n\tint iFramesyncTimeout;\n\tif( Session.Type == GAME_INTERNET && pWolapi && pWolapi->GameInfoCurrent.iPlayerCount > 2 )\n\t\t//\tShortened resync timeout for non-2 player games.\n\t\tiFramesyncTimeout = 5 * 60;\t\t//\tOne minute.\n\telse\n\t\tiFramesyncTimeout = FRAMESYNC_TIMEOUT;\n\n\trc = Wait_For_Players (0, net,\n\t\t(Session.MaxAhead << 3),\n\t\tMAX ( net->Response_Time() * 3, FRAMESYNC_DLG_TIME*timeout_factor ),\n\t\tiFramesyncTimeout * (2*timeout_factor),\n\t\tmulti_packet_buf, my_sent, their_frame,\n\t\ttheir_sent, their_recv);\n#else\n\t\trc = Wait_For_Players (0, net,\n\t\t(Session.MaxAhead << 3),\n\t\tMAX ( net->Response_Time() * 3, FRAMESYNC_DLG_TIME*timeout_factor ),\n\t\tFRAMESYNC_TIMEOUT* (2*timeout_factor),\n\t\tmulti_packet_buf, my_sent, their_frame,\n\t\ttheir_sent, their_recv);\n#endif\n\n\tif (rc != RC_NORMAL) {\n#ifdef WIN32\n\t\t\tif (Session.Type == GAME_INTERNET){\n\t\t\t\tRegister_Game_End_Time();\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\t//\tNew rule - if you cancel a waiting to reconnect dialog, you lose.\n\t\t\t\tbReconnectDialogCancelled = ( rc == RC_CANCEL );\n#endif\n\t\t\t}\n#endif\t//WIN32\n\t\tif (rc == RC_NOT_RESPONDING) {\n\t\t\tWWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);\n\t\t}\n\t\telse if (rc == RC_SCENARIO_MISMATCH) {\n\t\t\tWWMessageBox().Process (TXT_SCENARIOS_DO_NOT_MATCH);\n\t\t}\n\t\telse if (rc == RC_DOLIST_FULL) {\n\t\t\tWWMessageBox().Process(TXT_QUEUE_FULL);\n\t\t}\n\t\tStop_Game();\n\t\treturn;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSave the DoList to disk, if we're in \"Record\" mode\n\t//------------------------------------------------------------------------\n\tif (Session.Record) {\n\t\tQueue_Record();\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Execute the DoList; if an error occurs, bail out.\n\t//------------------------------------------------------------------------\n\tif (!Execute_DoList(Session.MaxPlayers, HOUSE_MULTI1, net, &skip_crc,\n\t\ttheir_frame, their_sent, their_recv)) {\n#ifdef WIN32\n\t\tif (Session.Type == GAME_INTERNET){\n\t\t\tRegister_Game_End_Time();\n\t\t}\n#endif\t//WIN32\n\t\tStop_Game();\n\t\treturn;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tClean out the DoList\n\t//------------------------------------------------------------------------\n\tClean_DoList(net);\n\n\tif (IsMono) {\n\t\tMonoClass::Disable();\n\t}\n\n}\t// end of Queue_AI_Multiplayer\n\n\n/***************************************************************************\n * Wait_For_Players -- Waits for other systems to come on-line             *\n *                                                                         *\n * This routine performs the most critical logic in multiplayer; that of\t*\n * synchronizing my frame number with those of the other systems.\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfirst_time\t\t\t\t1 = 1st time this routine is called\t\t\t\t\t*\n *\t\tnet\t\t\t\t\t\tptr to connection manager\t\t\t\t\t\t\t\t*\n *\t\tresend_delta\t\t\ttime (ticks) between FRAMESYNC resends\t\t\t\t*\n *\t\tdialog_time\t\t\t\ttime (ticks) until pop up a reconnect dialog\t\t*\n *\t\ttimeout\t\t\t\t\ttime (ticks) until we give up the ghost\t\t\t*\n *\t\tmulti_packet_buf\t\tbuffer to store packets in\t\t\t\t\t\t\t\t*\n *\t\tmy_sent\t\t\t\t\t# commands I've sent so far\t\t\t\t\t\t\t*\n *\t\ttheir_frame\t\t\t\tarray of their frame #'s\t\t\t\t\t\t\t\t*\n *\t\ttheir_sent\t\t\t\tarray of their CommandCount values\t\t\t\t\t*\n *\t\ttheir_recv\t\t\t\tarray of # cmds I've received from them\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tRC_NORMAL\t\t\t\tOK to advance to the next frame\t\t\t\t\t\t*\n *\t\tRC_CANCEL\t\t\t\tuser hit 'Cancel' at the timeout countdown dlg\t*\n *\t\tRC_NOT_RESPONDING\t\tother player(s) not responding\t\t\t\t\t\t*\n *\t\tRC_SCENARIO_MISMATCH\tscenario's don't match (first_time only)\t\t\t*\n *\t\tRC_DOLIST_FULL\t\t\tDoList was full\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic RetcodeType Wait_For_Players(int first_time, ConnManClass *net,\n\tint resend_delta, int dialog_time, int timeout, char *multi_packet_buf,\n\tint my_sent, long *their_frame, unsigned short *their_sent,\n\tunsigned short *their_recv)\n{\n\t//........................................................................\n\t// Variables for sending, receiving & parsing packets:\n\t//........................................................................\n\tEventClass *event;\t\t\t\t\t// event ptr for parsing incoming packets\n\tint packetlen;\t\t\t\t\t\t\t// size of meta-packet sent, & received\n\tint id;\t\t\t\t\t\t\t\t\t// id of other player\n\tint messages_this_loop;\t\t\t\t// to limit # messages processed each loop\n\tint message_limit;\t\t\t\t\t// max # messages we'll read each frame\n\n\t//........................................................................\n\t// Variables used only if 'first_time':\n\t//........................................................................\n\tint num_ready;\t\t\t\t\t\t\t// # players signalling ready\n\n\t//........................................................................\n\t// Timing variables\n\t//........................................................................\n\tCDTimerClass<SystemTimerClass> retry_timer;\t\t// time between FRAMESYNC packet resends\n\tCDTimerClass<SystemTimerClass> dialog_timer;\t// time to pop up a dialog\n\tCDTimerClass<SystemTimerClass> timeout_timer;\t// general-purpose timeout\n\n\t//........................................................................\n\t// Dialog variables\n\t//........................................................................\n\tint reconnect_dlg = 0;\t\t\t\t// 1 = the reconnect dialog is displayed\n\n\t//........................................................................\n\t// Other misc variables\n\t//........................................................................\n\tKeyNumType input;\t\t\t\t\t\t// for user input\n\tint x,y;\t\t\t\t\t\t\t\t\t// for map input\n\tRetcodeType rc;\n\n\t//------------------------------------------------------------------------\n\t// Wait to hear from all other players\n\t//------------------------------------------------------------------------\n\tnum_ready = 0;\n\tretry_timer = resend_delta;\t// time to retry\n\tdialog_timer = dialog_time;\t// time to show dlg\n\ttimeout_timer = timeout;\t\t// time to bail out\n\n\twhile (1) {\n\t\tKeyboard->Check();\n\n\t\tUpdate_Queue_Mono (net, 2);\n\n\t\t//---------------------------------------------------------------------\n\t\t//\tResend a frame-sync packet if longer than one propagation delay goes\n\t\t// by; this prevents a \"deadlock\".  If he's waiting for me to advance,\n\t\t// but has missed my last few FRAMEINFO packets, I may be waiting for\n\t\t// him to advance.  Resending a FRAMESYNC ensures he knows what frame\n\t\t// number I'm on.\n\t\t//---------------------------------------------------------------------\n\t\tif (!retry_timer) {\n\t\t\tretry_timer = resend_delta;\t\t// time to retry\n\t\t\tUpdate_Queue_Mono (net, 3);\n\t\t\tSend_FrameSync(net, my_sent);\n\t\t}\n\n\t\t//---------------------------------------------------------------------\n\t\t//\tService the connections\n\t\t//---------------------------------------------------------------------\n\t\tnet->Service();\n\n\t\t//---------------------------------------------------------------------\n\t\t//\tPop up a reconnect dialog if enough time goes by\n\t\t//---------------------------------------------------------------------\n\t\tif (!dialog_timer && SpecialDialog==SDLG_NONE) {\n\t\t\tif (reconnect_dlg == 0 && first_time == 0) {\n\t\t\t\tFILE *fp;\n\t\t\t\tint i;\n\t\t\t\tHouseClass *housep;\n\n\t\t\t\tfp = fopen(\"recon.txt\",\"wt\");\n\t\t\t\tif (fp) {\n\t\t\t\t\tfprintf(fp,\"# Connections: %d\\n\",net->Num_Connections());\n\t\t\t\t\tfprintf(fp,\"   My Frame #: %d\\n\",Frame);\n\t\t\t\t\tfor (i = 0; i < net->Num_Connections(); i++) {\n\t\t\t\t\t\thousep = HouseClass::As_Pointer((HousesType)(net->Connection_ID(i)));\n\t\t\t\t\t\tfprintf(fp,\"%15s: Their Sent:%d  Their Recv:%d  Their Frame:%d\\n\",\n\t\t\t\t\t\t\thousep->IniName, their_sent[i], their_recv[i], their_frame[i]);\n\t\t\t\t\t}\n\t\t\t\t\tfclose(fp);\n\t\t\t\t}\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\t//\t\"Reconnecting\" dialog is about to be shown.\n\t\t\t\t//\tAt this point, begin wolapi \"disconnect pinging\", if appropriate.\n\t\t\t\tif( Session.Type == GAME_INTERNET && pWolapi && pWolapi->GameInfoCurrent.bTournament )\n\t\t\t\t\tpWolapi->Init_DisconnectPinging();\n#endif\n\t\t\t}\n\n\t\t\tif (Process_Reconnect_Dialog(&timeout_timer, their_frame,\t\t\t\t//\t(Returns immediately.)\n\t\t\t\tnet->Num_Connections(), (first_time==0), (reconnect_dlg==0))) {\n\t\t\t\treturn (RC_CANCEL);\n\t\t\t}\n\t\t\treconnect_dlg = 1;\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\t//\tContinue wolapi \"disconnect pinging\", if appropriate.\n\t\t\t\tif( Session.Type == GAME_INTERNET && pWolapi && pWolapi->bDoingDisconnectPinging )\n\t\t\t\t\tpWolapi->Pump_DisconnectPinging();\n#endif\n\t\t}\n\n\t\t//---------------------------------------------------------------------\n\t\t//\tExit if too much time goes by (the other system has crashed or\n\t\t// bailed)\n\t\t//---------------------------------------------------------------------\n\t\tif (!timeout_timer) {\n\t\t\t//..................................................................\n\t\t\t// For the first-time run, just give up; something's wrong.\n\t\t\t//..................................................................\n\t\t\tif (first_time) {\n\t\t\t\treturn (RC_NOT_RESPONDING);\n\t\t\t}\n\t\t\t//..................................................................\n\t\t\t// Otherwise, we're in the middle of a game; so, the modem &\n\t\t\t// network must deal with a timeout differently.\n\t\t\t//..................................................................\n\t\t\telse {\n\t\t\t\tUpdate_Queue_Mono (net, 4);\n\n\t\t\t\tif (Handle_Timeout(net, their_frame, their_sent, their_recv)) {\n\t\t\t\t\tMap.Flag_To_Redraw(true);\t// erase modem reconnect dialog\n\t\t\t\t\tMap.Render();\n\t\t\t\t\tretry_timer = resend_delta;\n\t\t\t\t\tdialog_timer = dialog_time;\n\t\t\t\t\ttimeout_timer = timeout;\n\t\t\t\t}\n#ifdef FIXIT_MULTI_SAVE\n#ifdef FIXIT_VERSION_3\n\t\t\t\telse if ((Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) ) {\n#else\n\t\t\t\telse if ((Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) &&\n\t\t\t\t\t        PlayingAgainstVersion != VERSION_RED_ALERT_104) {\n#endif\n\t\t\t\t\tif (WWMessageBox().Process (TXT_ASK_EMERGENCY_SAVE_NOT_RESPONDING,\n\t\t\t\t\t\tTXT_YES, TXT_NO, TXT_NONE) == 0) {\n\t\t\t\t\t\tSession.EmergencySave = 1;\n//printf(\"Saving emergency game; frame:%d, CRC:%d\\n\",Frame,GameCRC);\n//Print_CRCs(NULL);\n//printf(\"Before Save: Count1:%d, Count2:%d, Seed:%d\\n\",\n//\tScen.RandomNumber.Count1,\n//\tScen.RandomNumber.Count2,\n//\tScen.RandomNumber.Seed);\n\t\t\t\t\t\tSave_Game(-1, (char *)Text_String(TXT_MULTIPLAYER_GAME));\n//printf(\"After Save: Count1:%d, Count2:%d, Seed:%d\\n\",\n//\tScen.RandomNumber.Count1,\n//\tScen.RandomNumber.Count2,\n//\tScen.RandomNumber.Seed);\n\t\t\t\t\t\tSession.EmergencySave = 0;\n\t\t\t\t\t}\n\t\t\t\t\treturn (RC_CANCEL);\n\t\t\t\t}\n#endif\t// FIXIT_MULTI_SAVE\n\t\t\t\telse {\n\t\t\t\t\treturn (RC_NOT_RESPONDING);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//---------------------------------------------------------------------\n\t\t//\tCheck for an incoming message.  We must still process commands\n\t\t// even if 'first_time' is set, in case the other system got my 1st\n\t\t// FRAMESYNC, but I didn't get his; he'll be at the next frame, and\n\t\t// may be sending commands.\n\t\t// We have to limit the number of incoming messages we handle; it's\n\t\t// possible to go into an infinite loop processing modem messages.\n\t\t// (This feature is disabled for Ten; we need to keep the TCP buffers\n\t\t// clear, so we read all the packets we can every time.)\n\t\t//---------------------------------------------------------------------\n\t\tmessages_this_loop = 0;\n\t\tmessage_limit = 5;\n\n\t\tif (Session.Type == GAME_TEN || Session.Type == GAME_MPATH) {\n\t\t\tmessage_limit = 9999;\n\t\t}\n\n\t\twhile ( (messages_this_loop++ < message_limit) &&\n\t\t\tnet->Get_Private_Message (multi_packet_buf, &packetlen, &id) ) {\n\n\t\t\tKeyboard->Check();\n\n\t\t\tUpdate_Queue_Mono (net, 5);\n\n\t\t\t/*..................................................................\n\t\t\tGet an event ptr to the incoming message\n\t\t\t..................................................................*/\n\t\t\tevent = (EventClass *)multi_packet_buf;\n\n\t\t\t//------------------------------------------------------------------\n\t\t\t// Special processing for a modem game: process SERIAL packets\n\t\t\t//------------------------------------------------------------------\n\t\t\tif (Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) {\n\t\t\t\trc = Process_Serial_Packet(multi_packet_buf, first_time);\n\t\t\t\t//...............................................................\n\t\t\t\t// SERIAL packet received & processed\n\t\t\t\t//...............................................................\n\t\t\t\tif (rc == RC_SERIAL_PROCESSED) {\n\t\t\t\t\tnet->Service();\n\t\t\t\t\tretry_timer = resend_delta;\n\t\t\t\t\tdialog_timer = dialog_time;\n\t\t\t\t\ttimeout_timer = timeout;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t// other player has left the game\n\t\t\t\t//...............................................................\n\t\t\t\telse if (rc == RC_PLAYER_LEFT) {\n\t\t\t\t\tif (first_time) {\n\t\t\t\t\t\tnum_ready++;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t// Connection was lost\n\t\t\t\t//...............................................................\n\t\t\t\telse if (rc == RC_HUNG_UP) {\n#ifdef FIXIT_MULTI_SAVE\n#ifndef FIXIT_VERSION_3\n\t\t\t\t\tif (PlayingAgainstVersion != VERSION_RED_ALERT_104){\n#endif\n\t\t\t\t\t\tif (WWMessageBox().Process (TXT_ASK_EMERGENCY_SAVE_HUNG_UP,\n\t\t\t\t\t\t\tTXT_YES, TXT_NO, TXT_NONE) == 0) {\n\t\t\t\t\t\t\tSession.EmergencySave = 1;\n\t//printf(\"Saving emergency game; frame:%d, CRC:%d\\n\",Frame,GameCRC);\n\t//Print_CRCs(NULL);\n\t//printf(\"Before Save: Count1:%d, Count2:%d, Seed:%d\\n\",\n\t//\tScen.RandomNumber.Count1,\n\t//\tScen.RandomNumber.Count2,\n\t//\tScen.RandomNumber.Seed);\n\t\t\t\t\t\t\tSave_Game (-1, (char *)Text_String(TXT_MULTIPLAYER_GAME));\n\t//printf(\"After Save: Count1:%d, Count2:%d, Seed:%d\\n\",\n\t//\tScen.RandomNumber.Count1,\n\t//\tScen.RandomNumber.Count2,\n\t//\tScen.RandomNumber.Seed);\n\t\t\t\t\t\t\tSession.EmergencySave = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn (RC_CANCEL);\n#ifndef FIXIT_VERSION_3\n\t\t\t\t\t}else{\n\t\t\t\t\t\treturn (RC_NOT_RESPONDING);\n\t\t\t\t\t}\n#endif\n\n#else\n\t\t\t\t\treturn (RC_NOT_RESPONDING);\n#endif\t// FIXIT_MULTI_SAVE\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t// If it was any other type of serial packet, break\n\t\t\t\t//...............................................................\n\t\t\t\telse if (rc != RC_NORMAL) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//------------------------------------------------------------------\n\t\t\t//\tProcess the incoming packet\n\t\t\t//------------------------------------------------------------------\n\t\t\trc = Process_Receive_Packet(net, multi_packet_buf, id, packetlen,\n\t\t\t\ttheir_frame, their_sent, their_recv);\n\t\t\t//..................................................................\n\t\t\t// New player heard from\n\t\t\t//..................................................................\n\t\t\tif (rc == RC_PLAYER_READY) {\n\t\t\t\tnum_ready++;\n\t\t\t}\n\t\t\t//..................................................................\n\t\t\t// Scenario's don't match\n\t\t\t//..................................................................\n\t\t\telse if (rc == RC_SCENARIO_MISMATCH) {\n\t\t\t\treturn (RC_SCENARIO_MISMATCH);\n\t\t\t}\n\t\t\t//..................................................................\n\t\t\t// DoList was full\n\t\t\t//..................................................................\n\t\t\telse if (rc == RC_DOLIST_FULL) {\n\t\t\t\treturn (RC_DOLIST_FULL);\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tService the connection, to clean out the receive queues\n\t\t\t//..................................................................\n\t\t\tnet->Service();\n\t\t}\n\n\t\t//---------------------------------------------------------------------\n\t\t// Debug output\n\t\t//---------------------------------------------------------------------\n\t\tPrint_Framesync_Values(Frame, Session.MaxAhead, net->Num_Connections(),\n\t\t\ttheir_recv, their_sent, my_sent);\n\n\t\t//---------------------------------------------------------------------\n\t\t//\tAttempt to advance to the next frame.\n\t\t//---------------------------------------------------------------------\n\t\t//.....................................................................\n\t\t// For the first-time run, just check to see if we've heard from\n\t\t// everyone.\n\t\t//.....................................................................\n\t\tif (first_time) {\n\t\t\tif (num_ready >= net->Num_Connections()) {\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t//.....................................................................\n\t\t// For in-game processing, we have to check their_sent, their_recv,\n\t\t// their_frame, etc.\n\t\t//.....................................................................\n\t\telse {\n\t\t\tif (Can_Advance(net, Session.MaxAhead, their_frame, their_sent,\n\t\t\t\ttheir_recv)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t//---------------------------------------------------------------------\n\t\t//\tService game stuff.  Servicing the map's input, and rendering the\n\t\t//\tmap, allows the map to scroll even though we're hung up waiting for\n\t\t//\tpackets.  Don't do this if 'first_time' is set, since users could be\n\t\t// waiting a very long time for all systems to load the scenario, and\n\t\t// it gets frustrating being able to scroll around without doing\n\t\t// anything.\n\t\t//---------------------------------------------------------------------\n\t\tCall_Back();\n\t\tif (!first_time && SpecialDialog == SDLG_NONE && reconnect_dlg==0) {\n#ifdef WIN32\n\t\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#endif\t//WIN32\n\t\t\tMap.Input(input, x, y);\n\t\t\tif (input)\n\t\t\t\tKeyboard_Process(input);\n\t\t\tMap.Render();\n\t\t}\n\n\t}\t/* end of while */\n\n\t//------------------------------------------------------------------------\n\t//\tIf the reconnect dialog was shown, force the map to redraw.\n\t//------------------------------------------------------------------------\n\tif (reconnect_dlg) {\n\t\tMap.Flag_To_Redraw(true);\n\t\tMap.Render();\n\t}\n\n\treturn (RC_NORMAL);\n\n}\t// end of Wait_For_Players\n\n\n/***************************************************************************\n * Generate_Timing_Event -- computes & queues a RESPONSE_TIME event        *\n *                                                                         *\n * This routine adjusts the connection timing on the local system; it also\t*\n * optionally generates a RESPONSE_TIME event, to tell all systems to\t\t*\n * dynamically adjust the current MaxAhead value.  This allows both the\t\t*\n * MaxAhead & the connection retry logic to have dynamic timing, to adjust\t*\n * to varying line conditions.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\tptr to connection manager\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tmy_sent\t\t# commands I've sent out so far\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Generate_Timing_Event(ConnManClass *net, int my_sent)\n{\n\tunsigned long resp_time;\t\t\t// connection response time, in ticks\n\tEventClass ev;\n\n\t//\n\t// For now, TEN & MPATH don't measure the net's response time, so there's\n\t// no point in adjusting our timing.  Do nothing.\n\t//\n\tif (Session.Type == GAME_TEN || Session.Type == GAME_MPATH) {\n\t\treturn;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Measure the current connection response time.  This time will be in\n\t// 60ths of a second, and represents full round-trip time of a packet.\n\t// To convert to one-way packet time, divide by 2; to convert to game\n\t// frames, divide again by 4, assuming a game rate of 15 fps.\n\t//------------------------------------------------------------------------\n\tresp_time = net->Response_Time();\n\n\t//------------------------------------------------------------------------\n\t//\tAdjust my connection retry timing; only do this if I've sent out more\n\t//\tthan 5 commands, so I know I have a measure of the response time.\n\t//------------------------------------------------------------------------\n\tif (my_sent > 5) {\n\n\t\tnet->Set_Timing (resp_time + 10, -1, (resp_time * 4)+15);\n\n\t\t//.....................................................................\n\t\t// If I'm the network \"master\", I'm also responsible for updating the\n\t\t// MaxAhead value on all systems, so do that here too.\n\t\t//.....................................................................\n\t\tif (Session.Am_I_Master()) {\n\t\t\tev.Type = EventClass::RESPONSE_TIME;\n\t\t\t//..................................................................\n\t\t\t// For multi-frame compressed events, the MaxAhead must be an even\n\t\t\t// multiple of the FrameSendRate.\n\t\t\t//..................................................................\n\t\t\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\t\t\tev.Data.FrameInfo.Delay = max( ((((resp_time / 8) +\n\t\t\t\t\t(Session.FrameSendRate - 1)) / Session.FrameSendRate) *\n\t\t\t\t\tSession.FrameSendRate), (Session.FrameSendRate * 2) );\n\t\t\t}\n\t\t\t//..................................................................\n\t\t\t// For sending packets every frame, just use the 1-way connection\n\t\t\t// response time.\n\t\t\t//..................................................................\n\t\t\telse {\n\t\t\t\tif (Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) {\n\t\t\t\t\tev.Data.FrameInfo.Delay = max( (resp_time / 8),\n\t\t\t\t\t\t MODEM_MIN_MAX_AHEAD );\n\t\t\t\t} else if (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) {\n\t\t\t\t\tev.Data.FrameInfo.Delay = max( (resp_time / 8),\n\t\t\t\t\t\t NETWORK_MIN_MAX_AHEAD );\n\t\t\t\t}\n\t\t\t\telse if (Session.Type == GAME_TEN || Session.Type == GAME_MPATH) {\n\t\t\t\t\tev.Data.FrameInfo.Delay = max( (resp_time / 8),\n\t\t\t\t\t\t MODEM_MIN_MAX_AHEAD );\n\t\t\t\t}\n\t\t\t}\n\t\t\tOutList.Add(ev);\n\t\t}\n\t}\n\n}\t// end of Generate_Timing_Event\n\n\n/***************************************************************************\n * Generate_Real_Timing_Event -- Generates a TIMING event                  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\tptr to connection manager\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tmy_sent\t\t# commands I've sent out so far\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/02/1996 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Generate_Real_Timing_Event(ConnManClass *net, int my_sent)\n{\n\tunsigned long resp_time;\t\t\t// connection response time, in ticks\n\tEventClass ev;\n\tint highest_ticks;\n\tint i;\n\tint specified_frame_rate;\n\tint maxahead;\n\n\t//\n\t// If we haven't sent out at least 5 guaranteed-delivery packets, don't\n\t// bother trying to measure our connection response time; just return.\n\t//\n\tif (my_sent < 5) {\n\t\treturn;\n\t}\n\n\t//\n\t// Find the highest processing time we have stored\n\t//\n\thighest_ticks = 0;\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\n\t\t//\n\t\t// If we haven't heard from all systems yet, bail out.\n\t\t//\n\t\tif (Session.Players[i]->Player.ProcessTime == -1) {\n\t\t\treturn;\n\t\t}\n\t\tif (Session.Players[i]->Player.ProcessTime > highest_ticks) {\n\t\t\thighest_ticks = Session.Players[i]->Player.ProcessTime;\n\t\t}\n\t}\n\n\t//\n\t// Compute our \"desired\" frame rate as the lower of:\n\t// - What the user has dialed into the options screen\n\t// - What we're really able to run at\n\t//\n\tif (highest_ticks == 0) {\n\t\tSession.DesiredFrameRate = 60;\n\t} else {\n\t\tSession.DesiredFrameRate = 60 / highest_ticks;\n\t}\n\n\tif (Options.GameSpeed == 0) {\n\t\tspecified_frame_rate = 60;\n\t} else {\n\t\tspecified_frame_rate = 60 / Options.GameSpeed;\n\t}\n\n\tSession.DesiredFrameRate = MIN (Session.DesiredFrameRate, specified_frame_rate);\n\n\t//\n\t// Measure the current connection response time.  This time will be in\n\t// 60ths of a second, and represents full round-trip time of a packet.\n\t// To convert to one-way packet time, divide by 2; to convert to game\n\t// frames, ....uh....\n\t//\n\tresp_time = net->Response_Time();\n\n\t//\n\t// Compute our new 'MaxAhead' value, based upon the response time of our\n\t// connection and our desired frame rate.\n\t// 'MaxAhead' in frames is:\n\t//\n\t// (resp_time / 2 ticks) * (1 sec/60 ticks) * (n Frames / sec)\n\t//\n\t// resp_time is divided by 2 because, as reported, it represents a round-\n\t// trip, and we only want to use a one-way trip.\n\t//\n\tmaxahead = (resp_time * Session.DesiredFrameRate) / (2 * 60);\n\n\t//\n\t// Now, we have to round 'maxahead' so it's an even multiple of our\n\t// send rate.  It also must be at least thrice the FrameSendRate.\n\t// (Isn't \"thrice\" a cool word?)\n\t//\n\tmaxahead = ((maxahead + Session.FrameSendRate - 1) / Session.FrameSendRate) * Session.FrameSendRate;\n\tmaxahead = MAX (maxahead, Session.FrameSendRate * 3);\n\n\tev.Type = EventClass::TIMING;\n\tev.Data.Timing.DesiredFrameRate = Session.DesiredFrameRate;\n\tev.Data.Timing.MaxAhead = maxahead;\n\n\tOutList.Add(ev);\n\n\t//\n\t//\tAdjust my connection retry timing.  These values set the retry timeout\n\t// to just over one round-trip time, the 'maxretries' to -1, and the\n\t// connection timeout to allow for about 4 retries.\n\t//\n\t//net->Set_Timing (resp_time + 10, -1, (resp_time * 4)+15);\n\n\tif (Session.Type == GAME_INTERNET) {\n\t\tnet->Set_Timing (resp_time + 10, -1, ((resp_time + 10)* 8)+15);\n\t}else{\n\t\tnet->Set_Timing (resp_time + 10, -1, (resp_time * 4)+15);\n\t}\n\n}\n\n\n/***************************************************************************\n * Generate_Process_Time_Event -- Generates a PROCESS_TIME event           *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\tptr to connection manager\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/02/1996 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Generate_Process_Time_Event(ConnManClass *net)\n{\n\tEventClass ev;\n\tint avgticks;\n\tunsigned long resp_time;\t\t\t// connection response time, in ticks\n\n\t//\n\t// Measure the current connection response time.  This time will be in\n\t// 60ths of a second, and represents full round-trip time of a packet.\n\t// To convert to one-way packet time, divide by 2; to convert to game\n\t// frames, ....uh....\n\t//\n\tresp_time = net->Response_Time();\n\n\t//\n\t//\tAdjust my connection retry timing.  These values set the retry timeout\n\t// to just over one round-trip time, the 'maxretries' to -1, and the\n\t// connection timeout to allow for about 4 retries.\n\t//\n\t//net->Set_Timing (resp_time + 10, -1, (resp_time * 4)+15);\n\tif (Session.Type == GAME_INTERNET) {\n\t\tnet->Set_Timing (resp_time + 10, -1, ((resp_time + 10)* 8)+15);\n\t}else{\n\t\tnet->Set_Timing (resp_time + 10, -1, (resp_time * 4)+15);\n\t}\n\n\n\tif (IsMono) {\n\t\tMonoClass::Enable();\n\t\tMono_Set_Cursor(0,23);\n\t\tMono_Printf(\"Processing Ticks:%03d Frames:%03d\\n\", Session.ProcessTicks,Session.ProcessFrames);\n\t\tMonoClass::Disable();\n\t}\n\n\tavgticks = Session.ProcessTicks / Session.ProcessFrames;\n\n\tev.Type = EventClass::PROCESS_TIME;\n\tev.Data.ProcessTime.AverageTicks = avgticks;\n\tOutList.Add(ev);\n\n\tSession.ProcessTicks = 0;\n\tSession.ProcessFrames = 0;\n}\n\n\n/***************************************************************************\n * Process_Send_Period -- timing for sending packets every 'n' frames      *\n *                                                                         *\n * This function is for a CommProtocol of COMM_PROTOCOL_MULTI_E_COMP only.\t*\n * It determines if it's time to send a packet or not.\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tptr to connection manager\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = it's time to send a packet; 0 = don't send a packet this frame.\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Process_Send_Period(ConnManClass *net)\t//, int init)\n{\n\t//------------------------------------------------------------------------\n\t// If the current frame # is not an even multiple of 'FrameSendRate', then\n\t// it's not time to send a packet; just return.\n\t//------------------------------------------------------------------------\n\tif (Frame != (((Frame + (Session.FrameSendRate - 1)) /\n\t\tSession.FrameSendRate) * Session.FrameSendRate) ) {\n\n\t\tnet->Service();\n\n\t\tif (IsMono) {\n\t\t\tMonoClass::Disable();\n\t\t}\n\n\t\treturn (0);\n\t}\n\n\treturn (1);\n\n\n}\t// end of Process_Send_Period\n\n\n/***************************************************************************\n * Send_Packets -- sends out events from the OutList                       *\n *                                                                         *\n * This routine computes how many events can be sent this frame, and then\t*\n * builds the \"meta-packet\" & sends it.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The 'cap' value is the max # of events we can send.  Ideally, it should\t*\n * be based upon the bandwidth of our connection.  Currently, it's just\t\t*\n * hardcoded to prevent the modem from having to resend \"too much\" data,\t*\n * which is about 200 bytes per frame.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\t\t\t\tptr to connection manager\t\t\t\t\t\t\t\t*\n *\t\tmulti_packet_buf\t\tbuffer to store packets in\t\t\t\t\t\t\t\t*\n *\t\tmulti_packet_max\t\tmax size of multi_packet_buf\t\t\t\t\t\t\t*\n *\t\tmax_ahead\t\t\t\tcurrent game MaxAhead value\t\t\t\t\t\t\t*\n *\t\tmy_sent\t\t\t\t\t# commands I've sent this game\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# events sent, NOT including the FRAMEINFO event\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Send_Packets(ConnManClass *net, char *multi_packet_buf,\n\tint multi_packet_max, int max_ahead, int my_sent)\n{\n\tint cap;\t\t\t\t// max # events to send, NOT including FRAMEINFO event\n\tint do_once;\t\t// true: only go through packet loop once\n\tint ack_req;\t\t// 0 = no ack required on outgoing packet\n\tint packetlen;\t\t// size of meta-packet sent\n\n\t//------------------------------------------------------------------------\n\t//\tDetermine how many events it's OK to send this frame.\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t// If we have 4 or more packets queued for sending, don't add any more\n\t// this frame.\n\t//........................................................................\n\tif (net->Private_Num_Send() >= 4) {\n\t\tcap = 0;\n\t\tdo_once = 1;\n\t}\n\t//........................................................................\n\t// If there are 2 or more packets queued, the entire packet we send must\n\t// fit within a single ComQueue buffer, so limit # events to 5.\n\t// (The Modem connection manager has a max buffer size of 200 bytes, which\n\t// is large enough for 6 uncompressed events, which leaves room for 5\n\t// events plus a FRAMEINFO.)\n\t//........................................................................\n\telse if (net->Private_Num_Send() >= 2) {\n\t\tcap = 5;\n\t\tdo_once = 1;\n\n\t}\n\t//........................................................................\n\t// Otherwise, just send all events in the OutList\n\t//........................................................................\n\telse {\n\t\tcap = OutList.Count;\n\t\tdo_once = 0;\n\t}\n\n\t//........................................................................\n\t// Make sure we aren't sending more events than are in the OutList\n\t//........................................................................\n\tif (cap > OutList.Count) {\n\t\tcap = OutList.Count;\n\t}\n\n\t//........................................................................\n\t// Make sure we don't send so many events that our DoList fills up\n\t//........................................................................\n\tif (cap > (MAX_EVENTS * 64) - DoList.Count) {\n\t\tcap = (MAX_EVENTS * 64) - DoList.Count;\n\t}\n\n\t//\n\t// 10/21/96 5:12PM - ST\n\t//\n\tif (Session.Type == GAME_INTERNET || Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM){\n\t\tcap = OutList.Count;\n\t\tdo_once = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tBuild our meta-packet & transmit it.\n\t//------------------------------------------------------------------------\n\twhile (1) {\n\t\tKeyboard->Check();\n\n\t\tUpdate_Queue_Mono (net, 1);\n\n\t\t//.....................................................................\n\t\t//\tIf there are no commands this frame, we'll just be sending a FRAMEINFO\n\t\t//\tpacket; no ack is required.  For the modem's sake, check\n\t\t// Session.NumPlayers; no ACK is needed if we're just sending to someone\n\t\t// who's left the game.\n\t\t//.....................................................................\n\t\tif (cap == 0 || OutList.Count == 0 || Session.NumPlayers == 1) {\n\t\t\tack_req = 0;\n\t\t}\n\t\telse {\n\t\t\tack_req = 1;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tBuild & send out our message\n\t\t//.....................................................................\n\t\tpacketlen = Build_Send_Packet (multi_packet_buf, multi_packet_max,\n\t\t\tmax_ahead, my_sent, cap);\n\t\tnet->Send_Private_Message (multi_packet_buf, packetlen, ack_req);\n\n\t\t//.....................................................................\n\t\t//\tCall Service() to actually send the packet\n\t\t//.....................................................................\n\t\tnet->Service();\n\n\t\t//.....................................................................\n\t\t//\tStop if there's no more data to send, or if our send queue is\n\t\t// filling up.\n\t\t//.....................................................................\n\t\tif (OutList.Count == 0 || do_once) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn (cap);\n\n}\t// end of Send_Packets\n\n\n/***************************************************************************\n * Send_FrameSync -- Sends a FRAMESYNC packet                              *\n *                                                                         *\n * This routine is used to periodically remind the other systems that \t\t*\n * we're still here, and to tell them what frame # we're on, in case\t\t\t*\n * they've missed my FRAMEINFO packets.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\t\tptr to connection manager\t\t\t\t\t\t\t\t\t\t*\n *\t\tcmd_count\t\t# commands I've sent so far\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Send_FrameSync(ConnManClass *net, int cmd_count)\n{\n\tEventClass packet;\n\n\t//------------------------------------------------------------------------\n\t//\tBuild a frame-sync event to send.  FRAMESYNC packets contain a\n\t// scenario-based CRC rather than a game-state-based CRC, to let the\n\t// games compare scenario CRC's on startup.\n\t//------------------------------------------------------------------------\n\tmemset (&packet, 0, sizeof(EventClass));\n\tpacket.Type = EventClass::FRAMESYNC;\n\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\tpacket.Frame = ((Frame + Session.MaxAhead + (Session.FrameSendRate - 1)) /\n\t\t\t Session.FrameSendRate) * Session.FrameSendRate;\n\t}\n\telse {\n\t\tpacket.Frame = Frame + Session.MaxAhead;\n\t}\n\tpacket.ID = PlayerPtr->ID;\n\tpacket.Data.FrameInfo.CRC = ScenarioCRC;\n\tpacket.Data.FrameInfo.CommandCount = cmd_count;\n\tpacket.Data.FrameInfo.Delay = Session.MaxAhead;\n\n\t//------------------------------------------------------------------------\n\t// Send the event.  For modem, this just sends to the other player;\n\t// for network, it sends to everyone we're connected to.\n\t//------------------------------------------------------------------------\n\n\tnet->Send_Private_Message (&packet, (offsetof(EventClass, Data) +\n\t\tsize_of(EventClass, Data.FrameInfo)), 0 );\n\n\treturn;\n\n}\t// end of Send_FrameSync\n\n\n/***************************************************************************\n * Process_Receive_Packet -- processes an incoming packet                  *\n *                                                                         *\n * This routine receives a packet from another system, adds it to our\t\t*\n * execution queue (the DoList), and updates my arrays of their frame #,\t*\n * their commands-sent, and their commands-received.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\t\t\tptr to connection manager\t\t\t\t\t\t\t\t\t*\n *\t\tmulti_packet_buf\tbuffer containing packet(s) to parse\t\t\t\t\t*\n *\t\tid\t\t\t\t\t\tid of sender\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\ttheir_frame\t\t\tarray containing frame #'s of other players\t\t\t*\n *\t\ttheir_sent\t\t\tarray containing command count of other players\t\t*\n *\t\ttheir_recv\t\t\tarray containing # recv'd cmds from other players\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tRC_NORMAL:\t\t\t\t\tnothing unusual happened, although \t\t\t\t*\n * \t\t\t\t\t\t\t\t\ttheir_sent or their_recv may have been \t\t*\n *\t\t\t\t\t\t\t\t\t\taltered\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tRC_PLAYER_READY:\t\t\tplayer has been heard from for the 1st time; *\n * \t\t\t\t\t\t\t\t\tthis presumes that his original \t\t\t\t\t*\n * \t\t\t\t\t\t\t\t\t'their_frame[]' value was -1 when this \t\t*\n * \t\t\t\t\t\t\t\t\troutine was called\t\t\t\t\t\t\t\t\t*\n *\t\tRC_SCENARIO_MISMATCH:\tFRAMEINFO scenario CRC doesn't match; \t\t\t*\n * \t\t\t\t\t\t\t\t\tnormally only applies after loading a new \t*\n * \t\t\t\t\t\t\t\t\tscenario or save-game\t\t\t\t\t\t\t\t*\n *\t\tRC_DOLIST_FULL:\t\t\tfatal error; unable to add events to DoList\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic RetcodeType Process_Receive_Packet(ConnManClass *net,\n\tchar *multi_packet_buf, int id, int packetlen, long *their_frame,\n\tunsigned short *their_sent, unsigned short *their_recv)\n{\n\tEventClass *event;\n\tint index;\n\tRetcodeType retcode = RC_NORMAL;\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tGet an event ptr to the incoming message\n\t//------------------------------------------------------------------------\n\tevent = (EventClass *)multi_packet_buf;\n\n\t//------------------------------------------------------------------------\n\t//\tGet the index of the sender\n\t//------------------------------------------------------------------------\n\tindex = net->Connection_Index(id);\n\n\t//------------------------------------------------------------------------\n\t//\tCompute the other player's frame # (at the time this packet was sent)\n\t//------------------------------------------------------------------------\n\tif (their_frame[index] <\n\t\t(int)(event->Frame - event->Data.FrameInfo.Delay)) {\n\n\t\t//.....................................................................\n\t\t// If the original frame # for this player is -1, it means we've heard\n\t\t// from this player for the 1st time; return the appropriate value.\n\t\t//.....................................................................\n\t\tif (their_frame[index]==-1) {\n\t\t\tretcode = RC_PLAYER_READY;\n\t\t}\n\n\t\ttheir_frame[index] = event->Frame - event->Data.FrameInfo.Delay;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tExtract the other player's CommandCount.  This count will include\n\t//\tthe commands in this packet, if there are any.\n\t//------------------------------------------------------------------------\n\tif (event->Data.FrameInfo.CommandCount > their_sent[index]) {\n\n\t\tif ( abs(their_sent[index] - event->Data.FrameInfo.CommandCount) > 500) {\n\t\t\tFILE *fp;\n\t\t\tfp = fopen(\"badcount.txt\",\"wt\");\n\t\t\tif (fp) {\n\t\t\t\tfprintf(fp,\"Event Type:%s\\n\",EventClass::EventNames[event->Type]);\n\t\t\t\tfprintf(fp,\"Frame:%d  ID:%d  IsExec:%d\\n\",\n\t\t\t\t\tevent->Frame,\n\t\t\t\t\tevent->ID,\n\t\t\t\t\tevent->IsExecuted);\n\t\t\t\tif (event->Type != EventClass::FRAMEINFO) {\n\t\t\t\t\tfprintf(fp,\"Wrong Event Type!\\n\");\n\t\t\t\t} else {\n\t\t\t\t\tfprintf(fp,\"CRC:%x  CommandCount:%d  Delay:%d\\n\",\n\t\t\t\t\t\tevent->Data.FrameInfo.CRC,\n\t\t\t\t\t\tevent->Data.FrameInfo.CommandCount,\n\t\t\t\t\t\tevent->Data.FrameInfo.Delay);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttheir_sent[index] = event->Data.FrameInfo.CommandCount;\n\t}\n\n\tif (Debug_Print_Events) {\n\t\tif (event->Type == EventClass::FRAMESYNC) {\n\t\t\tprintf(\"(%d) Received FRAMESYNC: \", Frame);\n\t\t} else {\n\t\t\tprintf(\"(%d) Received FRAMEINFO: \", Frame);\n\t\t}\n\t\tprintf(\"EvFrame:%d ID:%d CRC:%x CmdCount:%d Delay:%d\\n\",\n\t\t\tevent->Frame,\n\t\t\tevent->ID,\n\t\t\tevent->Data.FrameInfo.CRC,\n\t\t\tevent->Data.FrameInfo.CommandCount,\n\t\t\tevent->Data.FrameInfo.Delay);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tIf this packet was not a FRAMESYNC packet:\n\t//\t- Add the events in it to our DoList\n\t//\t- Increment our commands-received counter by the number of non-\n\t//\t  FRAMEINFO packets received\n\t//------------------------------------------------------------------------\n\tif (event->Type != EventClass::FRAMESYNC) {\n\t\t//.....................................................................\n\t\t// Break up the packet into its component events.  A returned packet\n\t\t// count of -1 indicates a fatal queue-full error.\n\t\t//.....................................................................\n\t\ti = Breakup_Receive_Packet( multi_packet_buf, packetlen);\n\t\tif (i==-1) {\n\t\t\treturn (RC_DOLIST_FULL);\n\t\t}\n\t\t//.....................................................................\n\t\t// Compute the actual # commands in the packet by subtracting off the\n\t\t// FRAMEINFO event\n\t\t//.....................................................................\n\t\tif ( (event->Type==EventClass::FRAMEINFO) && (i > 0)) {\n\t\t\ti--;\n\t\t}\n\n\t\ttheir_recv[index] += i;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tIf the event was a FRAMESYNC packet, there will be no commands to add,\n\t//\tbut we must check the ScenarioCRC value.\n\t//------------------------------------------------------------------------\n\telse if (event->Data.FrameInfo.CRC != ScenarioCRC) {\n\t\treturn (RC_SCENARIO_MISMATCH);\n\t}\n\n\treturn (retcode);\n\n}\t// end of Process_Receive_Packet\n\n\n/***************************************************************************\n * Process_Serial_Packet -- Handles an incoming serial packet              *\n *                                                                         *\n * This routine is needed because the modem classes don't support a \t\t\t*\n * \"global channel\" like the network classes do, but that functionality is\t*\n * still needed for modem communications.  Specifically, the modem dialogs\t*\n * transmit their own special packets back & forth, and messages are sent\t*\n * using a special packet type.  Thus, we have to call this routine when\t*\n * we receive a modem packet, to allow it to process messages & dialog\t\t*\n * packets.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tmulti_packet_buf\t\tpacket buffer to process\t\t\t\t\t\t\t\t*\n *\t\tfirst_time\t\t\t\t1 = this is the 1st game frame\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tRC_NORMAL:\t\t\t\tthis wasn't a SERIAL-type packet\t\t\t\t\t\t*\n *\t\tRC_SERIAL_PROCESSED:\tthis was a SERIAL-type packet, and was \t\t\t*\n * \t\t\t\t\t\t\t\tprocessed; the other player is still connected,\t*\n * \t\t\t\t\t\t\t\teven if he's not in the game.\t\t\t\t\t\t\t*\n *\t\tRC_PLAYER_LEFT:\t\tother player has left the game\t\t\t\t\t\t*\n *\t\tRC_HUNG_UP:\t\t\t\twe're getting our own packets back; thus, the \t*\n * \t\t\t\t\t\t\t\tmodem is mirroring our packets, which means the *\n * \t\t\t\t\t\t\t\tmodem hung up!\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic RetcodeType Process_Serial_Packet(char *multi_packet_buf,\n\tint first_time)\n{\n\tSerialPacketType *serial_packet;\t\t// for parsing serial packets\n\tint player_gone;\n\tEventClass *event;\n\n\t//------------------------------------------------------------------------\n\t//\tDetermine if this packet means that the other player has left the game\n\t//------------------------------------------------------------------------\n\tserial_packet = (SerialPacketType *)multi_packet_buf;\n\tplayer_gone = 0;\n\t//........................................................................\n\t// On Frame 0, only a SIGN_OFF means the other player left; the other\n\t// packet types may be left over from a previous session.\n\t//........................................................................\n\tif (first_time) {\n\t\tif (serial_packet->Command == SERIAL_SIGN_OFF) {\n\t\t\tplayer_gone = 1;\n\t\t}\n\t}\n\t//........................................................................\n\t// On subsequent frames, any of SIGN_OFF, TIMING, or SCORE_SCREEN means\n\t// the other player is gone.\n\t//........................................................................\n\telse {\n\t\tif (serial_packet->Command == SERIAL_SIGN_OFF ||\n\t\t\tserial_packet->Command == SERIAL_TIMING ||\n\t\t\tserial_packet->Command == SERIAL_SCORE_SCREEN ) {\n\t\t\tplayer_gone = 1;\n\t\t}\n\t}\n\tif (player_gone) {\n\t\tDestroy_Null_Connection(serial_packet->ScenarioInfo.Color, 0);\n\t\treturn (RC_PLAYER_LEFT);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Process an incoming message\n\t//------------------------------------------------------------------------\n\tif (serial_packet->Command == SERIAL_MESSAGE) {\n\t\tif (!Session.Messages.Concat_Message(serial_packet->Name,\n\t\t\tserial_packet->ID, serial_packet->Message.Message, Rule.MessageDelay * TICKS_PER_MINUTE)) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98 - Appears to do nothing\n\tchar *ptr = &serial_packet->Message.Message[0];\n\tif (!strncmp(ptr,\"SECRET UNITS ON \",15) && NewUnitsEnabled) {\n\t\tEnable_Secret_Units();\n\t}\n#endif\n\t\t\tSession.Messages.Add_Message (serial_packet->Name,\n\t\t\t\tserial_packet->ID, serial_packet->Message.Message,\n\t\t\t\t(PlayerColorType)serial_packet->ID,\n\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\n\t\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tSave this message in our last-message buffer\n\t\t//.....................................................................\n\t\tif (strlen (serial_packet->Message.Message)) {\n\t\t\tstrcpy (Session.LastMessage, serial_packet->Message.Message);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tTell the map to do a partial update (just to force the\n\t\t// messages to redraw).\n\t\t//.....................................................................\n\t\t//Map.Flag_To_Redraw(false);\n\t\tMap.Flag_To_Redraw(true);\n\t\treturn (RC_SERIAL_PROCESSED);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Any other SERIAL-type packet means the other player is still there;\n\t// throw them away, but let the caller know the connection is OK.\n\t//------------------------------------------------------------------------\n\tif ( (serial_packet->Command >= SERIAL_CONNECT &&\n\t\tserial_packet->Command < SERIAL_LAST_COMMAND) ||\n\t\t(serial_packet->Command >= SERIAL_REQ_SCENARIO &&\n\t\t serial_packet->Command <= SERIAL_NO_SCENARIO) ||\n\t\tSession.NumPlayers == 1) {\n\t\treturn (RC_SERIAL_PROCESSED);\n\t}\n\n\t//........................................................................\n\t//\tare we getting our own packets back??\n\t//........................................................................\n\tevent = (EventClass *)multi_packet_buf;\n\n\tif (event->Type <= EventClass::EMPTY || event->Type >= EventClass::LAST_EVENT) return (RC_SERIAL_PROCESSED);\n\n\tif (event->ID == PlayerPtr->ID) {\n\t\treturn (RC_HUNG_UP);\n\t}\n\n\treturn (RC_NORMAL);\n\n}\t// end of Process_Serial_Packet\n\n\n/***************************************************************************\n * Can_Advance -- determines if it's OK to advance to the next frame       *\n *                                                                         *\n * This routine uses the current values stored in their_frame[], \t\t\t\t*\n * their_send[], and their_recv[] to see if it's OK to advance to the next\t*\n * game frame.  We must not advance if:\t\t\t\t\t\t\t\t\t\t\t\t*\n * - If our frame # would be too far ahead of the slowest player (the \t\t*\n *   lowest their_frame[] value).  \"Too far\" means \t\t\t\t\t\t\t\t*\n *   (Frame >= their_frame + MaxAhead).\t\t\t\t\t\t\t\t\t\t\t\t*\n * - our current command count doesn't match the sent command count of one\t*\n *   other player (meaning that we've missed a command packet from that \t*\n *   player, and thus the frame # we're receiving from him may be due to a\t*\n *   FRAMEINFO packet sent later than the command, so we shouldn't use \t\t*\n *   this frame # to see if we should advance; we should wait until we \t\t*\n *   have all the commands before we advance.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * Of course, this routine assumes the values in their_frame[] etc are\t\t*\n * kept current by the caller.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\t\tptr to connection manager\t\t\t\t\t\t\t\t\t\t*\n *\t\tmax_ahead\t\tmax frames ahead\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\ttheir_frame\t\tarray of their frame #'s\t\t\t\t\t\t\t\t\t\t*\n *\t\ttheir_sent\t\tarray of their sent command count\t\t\t\t\t\t\t*\n *\t\ttheir_recv\t\tarray of their # received commands\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK to advance; 0 = not OK\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Can_Advance(ConnManClass *net, int max_ahead, long *their_frame,\n\tunsigned short *their_sent, unsigned short *their_recv)\n{\n\tlong their_oldest_frame;\t\t\t// other players' oldest frame #\n\tint count_ok;\t\t\t\t\t\t\t// true = my cmd count matches theirs\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t// Special case for modem: if the other player has left, go ahead and\n\t// advance to the next frame; don't wait on him.\n\t//------------------------------------------------------------------------\n\tif (Session.NumPlayers == 1) {\n\t\treturn (1);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tFind the oldest frame # in 'their_frame'\n\t//------------------------------------------------------------------------\n\ttheir_oldest_frame = Frame + 1000;\n\tfor (i = 0; i < net->Num_Connections(); i++) {\n\t\tif (their_frame[i] < their_oldest_frame)\n\t\t\ttheir_oldest_frame = their_frame[i];\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tI can advance to the next frame IF:\n\t//\t1) I'm less than a one-way propagation delay ahead of the other\n\t//    players' frame numbers, AND\n\t//\t2) their_recv[i] >= their_sent[i] (ie I've received all the commands\n\t//\t   the other players have sent so far).\n\t//------------------------------------------------------------------------\n\tcount_ok = 1;\n\tfor (i = 0; i < net->Num_Connections(); i++) {\n\t\tif (their_recv[i] < their_sent[i]) {\n\t\t\tcount_ok = 0;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (count_ok && (Frame < (their_oldest_frame + max_ahead))) {\n\t\treturn (1);\n\t}\n\n\treturn (0);\n\n}\t// end of Can_Advance\n\n\n/***************************************************************************\n * Process_Reconnect_Dialog -- processes the reconnection dialog           *\n *                                                                         *\n * This routine [re]draws the reconnection dialog; if 'reconn' is set,\t\t*\n * it tells the user who we're trying to reconnect to; otherwise, is just\t*\n * says something generic like \"Waiting for connections\".\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\ttimeout_timer\tptr to count down timer, showing time remaining\t\t\t*\n *\t\ttheir_frame\t\tarray of other players' frame #'s\t\t\t\t\t\t\t*\n *\t\tnum_conn\t\t\t# connections in 'their_frame'\t\t\t\t\t\t\t\t*\n *\t\treconn\t\t\t1 = reconnect, 0 = waiting for first-time connection\t*\n *\t\tfresh\t\t\t\t1 = draw from scratch, 0 = only update time counter\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = user wants to cancel, 0 = not\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Process_Reconnect_Dialog(CDTimerClass<SystemTimerClass> *timeout_timer,\n\tlong *their_frame, int num_conn, int reconn, int fresh)\n{\n\tstatic int displayed_time = 0;\t// time value currently displayed\n\tint new_time;\n\tint oldest_index;\t\t\t\t\t\t// index of person requiring a reconnect\n\tint i,j;\n\n\t//------------------------------------------------------------------------\n\t// Convert the timer to seconds\n\t//------------------------------------------------------------------------\n\tnew_time = *timeout_timer / 60;\n\n\t//------------------------------------------------------------------------\n\t// If the timer has changed, or 'fresh' is set, redraw the dialog\n\t//------------------------------------------------------------------------\n\tif (fresh || (new_time != displayed_time)) {\n\t\t//.....................................................................\n\t\t// Find the index of the person we're trying to reconnect to\n\t\t//.....................................................................\n\t\tif (reconn) {\n\t\t\tj = 0x7fffffff;\n\t\t\toldest_index = 0;\n\t\t\tfor (i = 0; i < num_conn; i++) {\n\t\t\t\tif (their_frame[i] < j) {\n\t\t\t\t\tj = their_frame[i];\n\t\t\t\t\toldest_index = i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tNet_Reconnect_Dialog(reconn, fresh, oldest_index, new_time);\n\t}\n\tdisplayed_time = new_time;\n\n\t//........................................................................\n\t//\tIf user hits ESC, bail out\n\t//........................................................................\n\tif (Keyboard->Check()) {\n\t\tif (Keyboard->Get() == KN_ESC) {\n\t\t\treturn (1);\n\t\t}\n\t}\n\n\treturn (0);\n\n}\t// end of Process_Reconnect_Dialog\n\n\n/***************************************************************************\n * Handle_Timeout -- handles a timeout in the wait-for-players loop\t\t\t*\n *                                                                         *\n * This routine \"gracefully\" handles a timeout in the frame-sync loop.\t\t*\n * The timeout must be handled differently by a modem game or network \t\t*\n * game.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The modem game must detect if the other player is still connected\t\t\t*\n * physically, even if he's not playing the game any more; if so, this\t\t*\n * routine returns an OK status.  If the other player isn't even \t\t\t\t*\n * physically connected, an error is returned.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The network game must find the connection that's causing the timeout,\t*\n * and destroy it.  The game continues, even if there are no more human\t\t*\n * players left.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\t\t\tptr to connection manager\t\t\t\t\t\t\t\t\t*\n *\t\ttheir_frame\t\t\tarray containing frame #'s of other players\t\t\t*\n *\t\ttheir_sent\t\t\tarray containing command count of other players\t\t*\n *\t\ttheir_recv\t\t\tarray containing # recv'd cmds from other players\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = it's OK; reset timeout timers & keep processing\t\t\t\t\t\t*\n *\t\t0 = game over, man\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Handle_Timeout(ConnManClass *net, long *their_frame,\n\tunsigned short *their_sent, unsigned short *their_recv)\n{\n\tint oldest_index;\t\t\t\t\t\t// index of person requiring a reconnect\n\tint i,j;\n\tint id;\n\n\t//------------------------------------------------------------------------\n\t// For modem, attempt to reconnect; if that fails, save the game & bail.\n\t//------------------------------------------------------------------------\n\tif (Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) {\n\t\tif ( net->Num_Connections() ) {\n\t\t\tif (!Reconnect_Modem()) {\n#ifndef FIXIT_MULTI_SAVE\n\t\t\t\t//...............................................................\n\t\t\t\t// Set 'Session.EmergencySave', so when this game is loaded, we\n\t\t\t\t// won't check the CRC of the game state (this system & the\n\t\t\t\t// other may be on different frames, in which case the CRC\n\t\t\t\t// won't match).\n\t\t\t\t//...............................................................\n\t\t\t\tSession.EmergencySave = 1;\n\t\t\t\t//Save_Game (-1, (char *)Text_String(TXT_MULTIPLAYER_GAME));\n\t\t\t\tSession.EmergencySave = 0;\n#endif\t// FIXIT_MULTI_SAVE\n\t\t\t\treturn (0);\n\t\t\t} else {\n\t\t\t\treturn (1);\n\t\t\t}\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tFor network, destroy the oldest connection\n\t//------------------------------------------------------------------------\n\telse if (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET ||\n\t\tSession.Type == GAME_TEN || Session.Type == GAME_MPATH) {\n\t\tj = 0x7fffffff;\n\t\toldest_index = 0;\n\t\tfor (i = 0; i < net->Num_Connections(); i++) {\n\t\t\tif (their_frame[i] < j) {\n\t\t\t\tj = their_frame[i];\n\t\t\t\toldest_index = i;\n\t\t\t}\n\t\t}\n\n\t\tid = net->Connection_ID(oldest_index);\n#ifdef WIN32\n\t\t/*\n\t\t** Send the game statistics packet now if the game is effectivly over\n\t\t*/\n\t\tif (Session.Players.Count() == 2 &&\n\t\t\t\tSession.Type == GAME_INTERNET &&\n\t\t\t\t!GameStatisticsPacketSent) {\n\t\t\tRegister_Game_End_Time();\n\t\t\tConnectionLost = true;\n\t\t\tSend_Statistics_Packet();\t\t//\tDisconnect, and I'll be the only one left.\n\t\t}\n#endif\t//WIN32\n\n\t\tif (id != ConnManClass::CONNECTION_NONE) {\n\t\t\tfor (i = oldest_index; i < net->Num_Connections() - 1; i++) {\n\t\t\t\ttheir_frame[i] = their_frame[i+1];\n\t\t\t\ttheir_sent[i] = their_sent[i+1];\n\t\t\t\ttheir_recv[i] = their_recv[i+1];\n\t\t\t}\n\t\t\tif (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) {\n\t\t\t\tDestroy_Connection(id,1);\n\t\t\t}\n#if(TEN)\n\t\t\telse if (Session.Type == GAME_TEN) {\n\t\t\t\tDestroy_TEN_Connection(id,1);\n\t\t\t}\n#endif\n#if(MPATH)\n\t\t\telse if (Session.Type == GAME_MPATH) {\n\t\t\t\tDestroy_MPATH_Connection(id,1);\n\t\t\t}\n#endif\n\t\t}\n\t}\n\n\treturn (1);\n\n}\t// end of Handle_Timeout\n\n\n/***************************************************************************\n * Stop_Game -- stops the game\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * This routine clears any global flags that need it, in preparation for\t*\n * halting the game prematurely.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Stop_Game(void)\n{\n\tSession.LoadGame = false;\n\tSession.EmergencySave = false;\n\tGameActive = 0;\n\tif (IsMono) {\n\t\tMonoClass::Disable();\n\t}\n#ifdef WIN32\n\tif (Session.Type == GAME_INTERNET){\n\t\tConnectionLost = true;\n\t\tSend_Statistics_Packet();\t\t\t//\tStop_Game()\n\t}\n#endif\t//WIN32\n\n\treturn;\n\n}\t// end of Stop_Game\n\n\n/***************************************************************************\n * Build_Send_Packet -- Builds a big packet from a bunch of little ones.\t*\n *                                                                         *\n * This routine takes events from the OutList, and puts them into a \t\t\t*\n * \"meta-packet\", which is transmitted to all systems we're connected to.\t*\n * Also, these events are added to our own DoList.\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * Every Meta-Packet we send uses a FRAMEINFO packet as a header; this \t\t*\n * tells the other systems what frame we're on, as well as serving as a \t*\n * standard packet header.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\t\tbuffer to store packet in\t\t\t\t\t\t\t\t\t\t*\n *\t\tbufsize\t\t\tmax size of buffer\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tframe_delay\t\tdesired frame delay to attach to all outgoing packets\t*\n *\t\tnum_cmds\t\t\tvalue to use for the CommandCount field\t\t\t\t\t*\n *\t\tcap\t\t\t\tmax # events to send\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnew size of packet\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n * 'num_cmds' should be the total of of commands, including all those sent *\n * this frame!\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Build_Send_Packet(void *buf, int bufsize, int frame_delay,\n\tint num_cmds, int cap)\n{\n\tint size = 0;\n\tEventClass *finfo;\n\n\t//------------------------------------------------------------------------\n\t// All events start with a FRAMEINFO event; fill this part in.\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t// Set the event type\n\t//........................................................................\n\tfinfo = (EventClass *)buf;\n\tfinfo->Type = EventClass::FRAMEINFO;\n\t//........................................................................\n\t// Set the frame to execute this event on; this is protocol-specific\n\t//........................................................................\n\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\tfinfo->Frame = ((Frame + frame_delay + (Session.FrameSendRate - 1)) /\n\t\t\t Session.FrameSendRate) * Session.FrameSendRate;\n\t}\n\telse {\n\t\tfinfo->Frame = Frame + frame_delay;\n\t}\n\t//........................................................................\n\t// Fill in the rest of the event\n\t//........................................................................\n\tfinfo->ID = PlayerPtr->ID;\n\tfinfo->Data.FrameInfo.CRC = GameCRC;\n\tfinfo->Data.FrameInfo.CommandCount = num_cmds;\n\tfinfo->Data.FrameInfo.Delay = frame_delay;\n\n\t//------------------------------------------------------------------------\n\t// Initialize the # of bytes processed; this is protocol-specific\n\t//------------------------------------------------------------------------\n\tif (Session.CommProtocol==COMM_PROTOCOL_SINGLE_NO_COMP) {\n\t\tsize += sizeof(EventClass);\n\t}\n\telse {\n\t\tsize += (offsetof(EventClass, Data) +\n\t\t\tsize_of(EventClass, Data.FrameInfo));\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tTransfer all events from the OutList into the DoList, building our\n\t//\tpacket while we go.\n\t//------------------------------------------------------------------------\n\tswitch (Session.CommProtocol) {\n\t\t//.....................................................................\n\t\t// COMM_PROTOCOL_SINGLE_NO_COMP:\n\t\t// We'll send at least a FRAMEINFO every single frame, no compression\n\t\t//.....................................................................\n\t\tcase (COMM_PROTOCOL_SINGLE_NO_COMP):\n\t\t\tsize = Add_Uncompressed_Events(buf, bufsize, frame_delay, size, cap);\n\t\t\tbreak;\n\n\t\t//.....................................................................\n\t\t// COMM_PROTOCOL_SINGLE_E_COMP:\n\t\t//   Compress a group of packets into our send buffer; send out\n\t\t//   compressed packets every frame.\n\t\t// COMM_PROTOCOL_MULTI_E_COMP:\n\t\t//   Compress a group of packets into our send buffer; send out\n\t\t//   compressed packets every 'n' frames.\n\t\t//.....................................................................\n\t\tcase (COMM_PROTOCOL_SINGLE_E_COMP):\n\t\tcase (COMM_PROTOCOL_MULTI_E_COMP):\n\t\t\tsize = Add_Compressed_Events(buf, bufsize, frame_delay, size, cap);\n\t\t\tbreak;\n\n\t\t//.....................................................................\n\t\t// Default: We have no idea what to do, so do nothing.\n\t\t//.....................................................................\n\t\tdefault:\n\t\t\tsize = 0;\n\t\t\tbreak;\n\t}\n\n\treturn( size );\n\n}\t/* end of Build_Send_Packet */\n\n\n/***************************************************************************\n * Add_Uncompressed_Events -- adds uncompressed events to a packet         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\t\tbuffer to store packet in\t\t\t\t\t\t\t\t\t\t*\n *\t\tbufsize\t\t\tmax size of buffer\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tframe_delay\t\tdesired frame delay to attach to all outgoing packets\t*\n *\t\tsize\t\t\t\tcurrent packet size\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tcap\t\t\t\tmax # events to process\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnew size value\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tThis routine MUST check to be sure it doesn't overflow the buffer.\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 DRD : Created.                                             *\n *=========================================================================*/\nstatic int Add_Uncompressed_Events(void *buf, int bufsize, int frame_delay,\n\tint size, int cap)\n{\n\tint num = 0;\t\t\t// # of events processed\n\tint ev_size;\t\t\t// size of event we're adding\n\n\t//------------------------------------------------------------------------\n\t// Loop until there are no more events, or we've processed our max # of\n\t// events, or the buffer is full.\n\t//------------------------------------------------------------------------\n\twhile (OutList.Count && (num < cap)) {\n\n\t\tKeyboard->Check();\n\n\t\tif (OutList.First().Type==EventClass::ADDPLAYER) {\n\t\t\tev_size = sizeof(EventClass) + OutList.First().Data.Variable.Size;\n\t\t}\n\t\telse {\n\t\t\tev_size = sizeof(EventClass);\n\t\t}\n\t\t//.....................................................................\n\t\t// Will the next event exceed the size of the buffer?  If so, break.\n\t\t//.....................................................................\n\t\tif ( (size + ev_size) > bufsize ) {\n\t\t\treturn (size);\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Set the event's frame delay\n\t\t//.....................................................................\n\t\tOutList.First().Frame = Frame + frame_delay;\n\n\t\t//.....................................................................\n\t\t// Set the event's ID\n\t\t//.....................................................................\n\t\tOutList.First().ID = PlayerPtr->ID;\n\n\t\t//.....................................................................\n\t\t// Transfer the event in OutList to DoList, un-queue the OutList\n\t\t// event.  If the DoList is full, stop transferring immediately.\n\t\t//.....................................................................\n\t\tOutList.First().IsExecuted = 0;\n\t\tif (!DoList.Add(OutList.First())) {\n\t\t\treturn (size);\n\t\t}\n\t\t#ifdef MIRROR_QUEUE\n\t\tMirrorList.Add(OutList.First());\n\t\t#endif\n\n\t\t//.....................................................................\n\t\t// Add event to the send packet\n\t\t//.....................................................................\n\t\tif (OutList.First().Type==EventClass::ADDPLAYER) {\n\t\t\tmemcpy ( ((char *)buf) + size, &OutList.First(), sizeof(EventClass) );\n\t\t\tsize += sizeof(EventClass);\n\t\t\tmemcpy ( ((char *)buf) + size,\n\t\t\t\tOutList.First().Data.Variable.Pointer,\n\t\t\t\tOutList.First().Data.Variable.Size);\n\t\t\tsize += OutList.First().Data.Variable.Size;\n\t\t}\n\t\telse {\n\t\t\tmemcpy ( ((char *)buf) + size, &OutList.First(), sizeof(EventClass) );\n\t\t\tsize += sizeof(EventClass);\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Increment our event counter; delete the last event from the queue\n\t\t//.....................................................................\n\t\tnum++;\n\t\tOutList.Next();\n\t}\n\n\treturn (size);\n\n}\t// end of Add_Uncompressed_Events\n\n\n/***************************************************************************\n * Add_Compressed_Events -- adds an compressed events to a packet          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\t\tbuffer to store packet in\t\t\t\t\t\t\t\t\t\t*\n *\t\tbufsize\t\t\tmax size of buffer\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tframe_delay\t\tdesired frame delay to attach to all outgoing packets\t*\n *\t\tsize\t\t\t\treference to current packet size\t\t\t\t\t\t\t\t*\n *\t\tcap\t\t\t\tmax # events to process\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnew size value\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tThis routine MUST check to be sure it doesn't overflow the buffer.\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 DRD : Created.                                             *\n *=========================================================================*/\nstatic int Add_Compressed_Events(void *buf, int bufsize, int frame_delay,\n\tint size, int cap)\n{\n\tint num = 0;\t\t\t\t\t\t\t// # of events processed\n\tEventClass::EventType eventtype;\t// type of event being compressed\n\tEventClass prevevent;\t\t\t\t// last event processed\n\tint datasize;\t\t\t\t\t\t\t// size of element plucked from event union\n\tint storedsize;\t\t\t\t\t\t// actual # bytes stored from event\n\tunsigned char *unitsptr = NULL;\t// ptr to buffer pos to store mega. rep count\n\tunsigned char numunits = 0;\t\t// megamission rep count value\n\tbool missiondup = false;\t\t\t// flag: is this event a megamission repeat?\n\n\t//------------------------------------------------------------------------\n\t// clear previous event\n\t//------------------------------------------------------------------------\n\tmemset (&prevevent, 0, sizeof(EventClass));\n\n\tif (Debug_Print_Events) {\n\t\tprintf(\"\\n(%d) Building Send Packet\\n\", Frame);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Loop until there are no more events, we've processed our max # of\n\t// events, or the buffer is full.\n\t//------------------------------------------------------------------------\n\twhile (OutList.Count && (num < cap)) {\n\n\t\tKeyboard->Check();\n\n\t\teventtype = OutList.First().Type;\n\t\tdatasize = EventClass::EventLength[ eventtype ];\n\t\t//.....................................................................\n\t\t// For a variable-sized event, pull the size from the event; otherwise,\n\t\t// the size will be the data element size plus the event type value.\n\t\t// (The other data elements in the event, Frame, ID, etc, are stored\n\t\t// in the packet header.)\n\t\t//.....................................................................\n\t\tif (eventtype==EventClass::ADDPLAYER) {\n\t\t\tstoredsize = datasize + sizeof (EventClass::EventType) +\n\t\t\t\tOutList.First().Data.Variable.Size;\n\t\t}\n\t\telse {\n\t\t\tstoredsize = datasize + sizeof (EventClass::EventType);\n\t\t}\n\n\t\t//.....................................................................\n\t\t// MegaMission compression:  MegaMissions are stored as:\n\t\t//   EventType\n\t\t//   Rep Count\n\t\t//   MegaMission structure (event # 1 only)\n\t\t//   Whom #2\n\t\t//   Whom #3\n\t\t//   Whom #4\n\t\t//   ...\n\t\t//   Whom #n\n\t\t//.....................................................................\n\t\tif (prevevent.Type == EventClass::MEGAMISSION) {\n\t\t\t//..................................................................\n\t\t\t// If previous & current events are both MegaMissions:\n\t\t\t//..................................................................\n\t\t\tif (eventtype == EventClass::MEGAMISSION) {\n\t\t\t\t//...............................................................\n\t\t\t\t// If the Mission, Target, & Destination are the same, compress\n\t\t\t\t// the events into one:\n\t\t\t\t// - Change datasize to the size of the 'Whom' field only\n\t\t\t\t// - set total # bytes to store to the size of the 'Whom' only\n\t\t\t\t// - increment the MegaMission rep count\n\t\t\t\t// - set the MegaMission rep flag\n\t\t\t\t//...............................................................\n\t\t\t\tif (OutList.First().Data.MegaMission.Mission ==\n\t\t\t\t\tprevevent.Data.MegaMission.Mission &&\n\t\t\t\t\tOutList.First().Data.MegaMission.Target ==\n\t\t\t\t\t\tprevevent.Data.MegaMission.Target &&\n\t\t\t\t\tOutList.First().Data.MegaMission.Destination ==\n\t\t\t\t\t\tprevevent.Data.MegaMission.Destination) {\n\n\t\t\t\t\tif (Debug_Print_Events) {\n\t\t\t\t\t\tprintf(\"      adding Whom:%x (%x) Mission:%s Target:%x (%x) Dest:%x (%x)\\n\",\n\t\t\t\t\t\tOutList.First().Data.MegaMission.Whom.As_TARGET(),\n\t\t\t\t\t\tOutList.First().Data.MegaMission.Whom,\n\t\t\t\t\t\tMissionClass::Mission_Name(OutList.First().Data.MegaMission.Mission),\n\t\t\t\t\t\tOutList.First().Data.MegaMission.Target.As_TARGET(),\n\t\t\t\t\t\tOutList.First().Data.MegaMission.Target,\n\t\t\t\t\t\tOutList.First().Data.MegaMission.Destination.As_TARGET(),\n\t\t\t\t\t\tOutList.First().Data.MegaMission.Destination);\n\t\t\t\t\t}\n\n\t\t\t\t\tdatasize = sizeof(prevevent.Data.MegaMission.Whom);\n\t\t\t\t\tstoredsize = datasize;\n\t\t\t\t\tnumunits++;\n\t\t\t\t\tmissiondup = true;\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t// Data doesn't match; start a new run of MegaMissions:\n\t\t\t\t// - Store previous MegaMission rep count\n\t\t\t\t// - Init 'unitsptr' to buffer pos after next EventType\n\t\t\t\t// - set total # bytes to store to 'datasize' + sizeof(EventType) +\n\t\t\t\t//   sizeof (numunits)\n\t\t\t\t// - init the MegaMission rep count to 1\n\t\t\t\t// - clear the MegaMission rep flag\n\t\t\t\t//...............................................................\n\t\t\t\telse {\n\n\t\t\t\t\tif (Debug_Print_Events) {\n\t\t\t\t\t\tprintf(\"  New MEGAMISSION run:\\n\");\n\t\t\t\t\t}\n\n\t\t\t\t\t*unitsptr = numunits;\n\t\t\t\t\tunitsptr = ((unsigned char *)buf) + size +\n\t\t\t\t\t\tsizeof(EventClass::EventType);\n\t\t\t\t\tstoredsize += sizeof(numunits);\n\t\t\t\t\tnumunits = 1;\n\t\t\t\t\tmissiondup = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\t//..................................................................\n\t\t\t// Previous event was a MegaMission, but this one isn't: end the\n\t\t\t// run of MegaMissions:\n\t\t\t// - Store previous MegaMission rep count\n\t\t\t// - Clear variables\n\t\t\t//..................................................................\n\t\t\telse {\n\t\t\t\t*unitsptr = numunits;\t\t// save # events in our run\n\t\t\t\tunitsptr = NULL;\t\t\t\t// init other values\n\t\t\t\tnumunits = 0;\n\t\t\t\tmissiondup = false;\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t// The previous event is not a MEGAMISSION but the current event is:\n\t\t// Set up a new run of MegaMissions:\n\t\t// - Init 'unitsptr' to buffer pos after next EventType\n\t\t// - set total # bytes to store to 'datasize' + sizeof(EventType) +\n\t\t//   sizeof (numunits)\n\t\t// - init the MegaMission rep count to 1\n\t\t// - clear the MegaMission rep flag\n\t\t//.....................................................................\n\t\telse if (eventtype == EventClass::MEGAMISSION) {\n\n\t\t\tif (Debug_Print_Events) {\n\t\t\t\tprintf(\"  New MEGAMISSION run:\\n\");\n\t\t\t}\n\n\t\t\tunitsptr = ((unsigned char *)buf) + size +\n\t\t\t\tsizeof(EventClass::EventType);\n\t\t\tstoredsize += sizeof(numunits);\n\t\t\tnumunits = 1;\n\t\t\tmissiondup = false;\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Will the next event exceed the size of the buffer?  If so,\n\t\t// stop compressing.\n\t\t//.....................................................................\n\t\tif ( (size + storedsize) > bufsize )\n\t\t\tbreak;\n\n\t\t//.....................................................................\n\t\t// Set the event's frame delay (this is protocol-dependent)\n\t\t//.....................................................................\n\t\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\t\tOutList.First().Frame = ((Frame + frame_delay +\n\t\t\t\t(Session.FrameSendRate - 1)) / Session.FrameSendRate) *\n\t\t\t\tSession.FrameSendRate;\n\t\t}\n\t\telse {\n\t\t\tOutList.First().Frame = Frame + frame_delay;\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Set the event's ID\n\t\t//.....................................................................\n\t\tOutList.First().ID = PlayerPtr->ID;\n\n\t\t//.....................................................................\n\t\t// Transfer the event in OutList to DoList, un-queue the OutList event.\n\t\t// If the DoList is full, stop transferring immediately.\n\t\t//.....................................................................\n\t\tOutList.First().IsExecuted = 0;\n\t\tif ( !DoList.Add( OutList.First() ) ) {\n\t\t\tbreak;\n\t\t}\n\t\t#ifdef MIRROR_QUEUE\n\t\tMirrorList.Add(OutList.First());\n\t\t#endif\n\n\t\t//---------------------------------------------------------------------\n\t\t// Compress the event into the send packet buffer\n\t\t//---------------------------------------------------------------------\n\t\tswitch ( eventtype ) {\n\t\t\t//..................................................................\n\t\t\t// RESPONSE_TIME: just use the Delay field of the FrameInfo union\n\t\t\t//..................................................................\n\t\t\tcase (EventClass::RESPONSE_TIME):\n\n\t\t\t\t*(EventClass::EventType *)( ((char *)buf) + size) = eventtype;\n\n\t\t\t\tmemcpy ( ((char *)buf) + size + sizeof(EventClass::EventType),\n\t\t\t\t\t&OutList.First().Data.FrameInfo.Delay, datasize );\n\n\t\t\t\tsize += (datasize + sizeof(EventClass::EventType));\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t// MEGAMISSION:\n\t\t\t//..................................................................\n\t\t\tcase (EventClass::MEGAMISSION):\n\t\t\t\t//...............................................................\n\t\t\t\t// Repeated mission in a run:\n\t\t\t\t//   - Update the rep count (in case we break out)\n\t\t\t\t//   - Copy the Whom field only\n\t\t\t\t//...............................................................\n\t\t\t\tif (missiondup) {\n\t\t\t\t\t*unitsptr = numunits;\n\n\t\t\t\t\tmemcpy ( ((char *)buf) + size,\n\t\t\t\t\t\t&OutList.First().Data.MegaMission.Whom, datasize );\n\n\t\t\t\t\tsize += datasize;\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t// 1st mission in a run:\n\t\t\t\t//   - Init the rep count (in case we break out)\n\t\t\t\t//   - Set the EventType\n\t\t\t\t//   - Copy the MegaMission structure, leaving room for 'numunits'\n\t\t\t\t//...............................................................\n\t\t\t\telse {\n\t\t\t\t\t*unitsptr = numunits;\n\n\t\t\t\t\t*(EventClass::EventType *)( ((char *)buf) + size) = eventtype;\n\n\t\t\t\t\tmemcpy ( ((char *)buf) + size +\n\t\t\t\t\t\tsizeof(EventClass::EventType) + sizeof(numunits),\n\t\t\t\t\t\t&OutList.First().Data.MegaMission, datasize );\n\n\t\t\t\t\tsize += (datasize + sizeof(EventClass::EventType) + sizeof(numunits));\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t// Variable-sized packets: Copy the packet Size & the buffer\n\t\t\t//..................................................................\n\t\t\tcase (EventClass::ADDPLAYER):\n\t\t\t\t*(EventClass::EventType *)( ((char *)buf) + size) = eventtype;\n\n\t\t\t\tmemcpy ( ((char *)buf) + size + sizeof(EventClass::EventType),\n\t\t\t\t\t&OutList.First().Data.Variable.Size, datasize );\n\t\t\t\tsize += (datasize + sizeof(EventClass::EventType));\n\n\t\t\t\tmemcpy ( ((char *)buf) + size,\n\t\t\t\t\tOutList.First().Data.Variable.Pointer,\n\t\t\t\t\tOutList.First().Data.Variable.Size);\n\t\t\t\tsize += OutList.First().Data.Variable.Size;\n\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t// Default case: Just copy over the data field from the union\n\t\t\t//..................................................................\n\t\t\tdefault:\n\t\t\t\t*(EventClass::EventType *)( ((char *)buf) + size) = eventtype;\n\n\t\t\t\tmemcpy ( ((char *)buf) + size + sizeof(EventClass::EventType),\n\t\t\t\t\t&OutList.First().Data, datasize );\n\n\t\t\t\tsize += (datasize + sizeof(EventClass::EventType));\n\n\t\t\t\tbreak;\n\t\t}\n\n\t\t//---------------------------------------------------------------------\n\t\t// update # events processed\n\t\t//---------------------------------------------------------------------\n\t\tnum++;\n\n\t\t//---------------------------------------------------------------------\n\t\t// Update 'prevevent'\n\t\t//---------------------------------------------------------------------\n\t\tmemcpy ( &prevevent, &OutList.First(), sizeof(EventClass) );\n\n\t\t//---------------------------------------------------------------------\n\t\t// Go to the next event to process\n\t\t//---------------------------------------------------------------------\n\t\tOutList.Next();\n\t}\n\n\tif (Debug_Print_Events) {\n\t\tprintf(\"\\n\");\n\t}\n\n\treturn (size);\n\n}\t// end of Add_Compressed_Events\n\n\n/***************************************************************************\n * Breakup_Receive_Packet -- Splits a big packet into little ones.\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to break up\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbufsize\t\tlength of buffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# events added to queue, -1 if fatal error (queue is full)\t\t\t\t*\n *    (return value includes any FRAMEINFO packets encountered; \t\t\t\t*\n *\t\tFRAMESYNC's are ignored)\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Breakup_Receive_Packet(void *buf, int bufsize )\n{\n\tint count = 0;\n\n\t/*\n\t** is there enough leftover for another record\n\t*/\n\tswitch (Session.CommProtocol) {\n\t\tcase (COMM_PROTOCOL_SINGLE_NO_COMP):\n\t\t\tcount = Extract_Uncompressed_Events(buf, bufsize);\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tcount = Extract_Compressed_Events(buf, bufsize);\n\t\t\tbreak;\n\t}\n\n\treturn (count);\n\n}\t/* end of Breakup_Receive_Packet */\n\n\n/***************************************************************************\n * Extract_Uncompressed_Events -- extracts events from a packet            *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer containing events to extract\t\t\t\t\t\t\t\t*\n *\t\tbufsize\t\tlength of 'buf'\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# events extracted\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 DRD : Created.                                             *\n *=========================================================================*/\nstatic int Extract_Uncompressed_Events(void *buf, int bufsize)\n{\n\tint count = 0;\n\tint pos = 0;\n\tint leftover = bufsize;\n\tEventClass *event;\n\n\t//------------------------------------------------------------------------\n\t// Loop until there are no more events in the packet\n\t//------------------------------------------------------------------------\n\twhile (leftover >= sizeof(EventClass) ) {\n\n\t\tKeyboard->Check();\n\n\t\tevent = (EventClass *)(((char *)buf) + pos);\n\n\t\t//.....................................................................\n\t\t// add event to the DoList, only if it's not a FRAMESYNC\n\t\t// (but FRAMEINFO's do get added.)\n\t\t//.....................................................................\n\t\tif (event->Type != EventClass::FRAMESYNC) {\n\t\t\tevent->IsExecuted = 0;\n\n\t\t\t//..................................................................\n\t\t\t// Special processing for variable-sized events\n\t\t\t//..................................................................\n\t\t\tif (event->Type == EventClass::ADDPLAYER) {\n\t\t\t\tevent->Data.Variable.Pointer = new char[event->Data.Variable.Size];\n\t\t\t\tmemcpy (event->Data.Variable.Pointer,\n\t\t\t\t\t((char *)buf) + sizeof(EventClass),\n\t\t\t\t\tevent->Data.Variable.Size);\n\n\t\t\t\tpos += event->Data.Variable.Size;\n\t\t\t\tleftover -= event->Data.Variable.Size;\n\t\t\t}\n\n\t\t\tif (!DoList.Add( *event )) {\n\t\t\t\tif (event->Type == EventClass::ADDPLAYER) {\n\t\t\t\t\tdelete [] event->Data.Variable.Pointer;\n\t\t\t\t}\n\t\t\t\treturn (-1);\n\t\t\t}\n\t\t\t#ifdef MIRROR_QUEUE\n\t\t\tMirrorList.Add(*event);\n\t\t\t#endif\n\n\t\t\t//..................................................................\n\t\t\t// Keep count of how many events we add to the queue\n\t\t\t//..................................................................\n\t\t\tcount++;\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Point to the next position in the buffer; decrement our 'leftover'\n\t\t//.....................................................................\n\t\tpos += sizeof(EventClass);\n\t\tleftover -= sizeof(EventClass);\n\t}\n\n\treturn (count);\n\n}\t// end of Extract_Uncompressed_Events\n\n\n/***************************************************************************\n * Extract_Compressed_Events -- extracts events from a packet   \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer containing events to extract\t\t\t\t\t\t\t\t*\n *\t\tbufsize\t\tlength of 'buf'\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# events extracted\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 DRD : Created.                                             *\n *=========================================================================*/\nstatic int Extract_Compressed_Events(void *buf, int bufsize)\n{\n\tint pos = 0;\t\t\t\t\t\t// current buffer parsing position\n\tint leftover = bufsize;\t\t\t// # bytes left to process\n\tEventClass *event;\t\t\t\t// event ptr for parsing buffer\n\tint count = 0;\t\t\t\t\t\t// # events processed\n\tint datasize = 0;\t\t\t\t\t// size of data to copy\n\tEventClass eventdata;\t\t\t// stores Frame, ID, etc\n\tunsigned char numunits = 0;\t// # units stored in compressed MegaMissions\n\n\t//------------------------------------------------------------------------\n\t// Clear work event structure\n\t//------------------------------------------------------------------------\n\tmemset (&eventdata, 0, sizeof(EventClass));\n\n\t//------------------------------------------------------------------------\n\t// Assume the first event is a FRAMEINFO event\n\t// Init 'datasize' to the amount of data to copy, minus the EventType value\n\t// For the 1st packet only, this will include all info before the Data\n\t// union, plus the size of the FrameInfo structure, minus the EventType size.\n\t//------------------------------------------------------------------------\n\tdatasize = (offsetof(EventClass, Data) +\n\t\tsize_of(EventClass, Data.FrameInfo)) - sizeof(EventClass::EventType);\n\tevent = (EventClass *)(((char *)buf) + pos);\n\n\twhile (leftover >= (datasize + sizeof(EventClass::EventType)) ) {\n\n\t\tKeyboard->Check();\n\n\t\t//.....................................................................\n\t\t// add event to the DoList, only if it's not a FRAMESYNC\n\t\t// (but FRAMEINFO's do get added.)\n\t\t//.....................................................................\n\t\tif (event->Type != EventClass::FRAMESYNC) {\n\t\t\t//..................................................................\n\t\t\t// initialize the common data from the FRAMEINFO event\n\t\t\t// keeping IsExecuted 0\n\t\t\t//..................................................................\n\t\t\tif (event->Type == EventClass::FRAMEINFO) {\n\t\t\t\teventdata.Frame = event->Frame;\n\t\t\t\teventdata.ID = event->ID;\n\n\t\t\t\t//...............................................................\n\t\t\t\t// Adjust position past the common data\n\t\t\t\t//...............................................................\n\t\t\t\tpos += (offsetof(EventClass, Data) -\n\t\t\t\t\t\t sizeof(EventClass::EventType));\n\t\t\t\tleftover -= (offsetof(EventClass, Data) -\n\t\t\t\t\t\t\t\tsizeof(EventClass::EventType));\n\t\t\t}\n\t\t\t//..................................................................\n\t\t\t// if MEGAMISSION event get the number of units (events to generate)\n\t\t\t//..................................................................\n\t\t\telse if (event->Type == EventClass::MEGAMISSION) {\n\t\t\t\tnumunits = *(((unsigned char *)buf) + pos + sizeof(eventdata.Type));\n\t\t\t\tpos += sizeof(numunits);\n\t\t\t\tleftover -= sizeof(numunits);\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// clear the union data portion of the event\n\t\t\t//..................................................................\n\t\t\tmemset (&eventdata.Data, 0, sizeof(eventdata.Data));\n\t\t\teventdata.Type = event->Type;\n\t\t\tdatasize = EventClass::EventLength[ eventdata.Type ];\n\n\t\t\tswitch (eventdata.Type) {\n\t\t\t\tcase (EventClass::RESPONSE_TIME):\n\t\t\t\t\tmemcpy ( &eventdata.Data.FrameInfo.Delay,\n\t\t\t\t\t\t((char *)buf) + pos + sizeof(EventClass::EventType),\n\t\t\t\t\t\tdatasize );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (EventClass::ADDPLAYER):\n\n\t\t\t\t\tmemcpy ( &eventdata.Data.Variable.Size,\n\t\t\t\t\t\t((char *)buf) + pos + sizeof(EventClass::EventType),\n\t\t\t\t\t\tdatasize );\n\n\t\t\t\t\teventdata.Data.Variable.Pointer =\n\t\t\t\t\t\tnew char[eventdata.Data.Variable.Size];\n\t\t\t\t\tmemcpy (eventdata.Data.Variable.Pointer,\n\t\t\t\t\t\t((char *)buf) + pos + sizeof(EventClass::EventType) + datasize,\n\t\t\t\t\t\teventdata.Data.Variable.Size);\n\n\t\t\t\t\tpos += eventdata.Data.Variable.Size;\n\t\t\t\t\tleftover -= eventdata.Data.Variable.Size;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (EventClass::MEGAMISSION):\n\t\t\t\t\tmemcpy ( &eventdata.Data.MegaMission,\n\t\t\t\t\t\t((char *)buf) + pos + sizeof(EventClass::EventType),\n\t\t\t\t\t\tdatasize );\n\n\t\t\t\t\tif (numunits > 1) {\n\t\t\t\t\t\tpos += (datasize + sizeof(EventClass::EventType));\n\t\t\t\t\t\tleftover -= (datasize + sizeof(EventClass::EventType));\n\t\t\t\t\t\tdatasize = sizeof(eventdata.Data.MegaMission.Whom);\n\n\t\t\t\t\t\twhile (numunits) {\n\n\t\t\t\t\t\t\tKeyboard->Check();\n\n\t\t\t\t\t\t\tif ( !DoList.Add( eventdata ) ) {\n\t\t\t\t\t\t\t\treturn (-1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t#ifdef MIRROR_QUEUE\n\t\t\t\t\t\t\tMirrorList.Add( eventdata );\n\t\t\t\t\t\t\t#endif\n\n\t\t\t\t\t\t\t//......................................................\n\t\t\t\t\t\t\t// Keep count of how many events we add to the queue\n\t\t\t\t\t\t\t//......................................................\n\t\t\t\t\t\t\tcount++;\n\t\t\t\t\t\t\tnumunits--;\n\t\t\t\t\t\t\tmemcpy ( &eventdata.Data.MegaMission.Whom,\n\t\t\t\t\t\t\t\t((char *)buf) + pos, datasize );\n\n\t\t\t\t\t\t\t//......................................................\n\t\t\t\t\t\t\t// if one unit left fall thru to normal code\n\t\t\t\t\t\t\t//......................................................\n\t\t\t\t\t\t\tif (numunits == 1) {\n\t\t\t\t\t\t\t\tdatasize -= sizeof(EventClass::EventType);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tpos += datasize;\n\t\t\t\t\t\t\t\tleftover -= datasize;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tmemcpy ( &eventdata.Data,\n\t\t\t\t\t\t((char *)buf) + pos + sizeof(EventClass::EventType),\n\t\t\t\t\t\tdatasize );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif ( !DoList.Add( eventdata ) ) {\n\t\t\t\tif (eventdata.Type == EventClass::ADDPLAYER) {\n\t\t\t\t\tdelete [] eventdata.Data.Variable.Pointer;\n\t\t\t\t}\n\t\t\t\treturn (-1);\n\t\t\t}\n\t\t\t#ifdef MIRROR_QUEUE\n\t\t\tMirrorList.Add( eventdata );\n\t\t\t#endif\n\n\t\t\t//..................................................................\n\t\t\t// Keep count of how many events we add to the queue\n\t\t\t//..................................................................\n\t\t\tcount++;\n\n\t\t\tpos += (datasize + sizeof(EventClass::EventType));\n\t\t\tleftover -= (datasize + sizeof(EventClass::EventType));\n\n\t\t\tif (leftover) {\n\t\t\t\tevent = (EventClass *)(((char *)buf) + pos);\n\t\t\t\tdatasize = EventClass::EventLength[ event->Type ];\n\t\t\t\tif (event->Type == EventClass::MEGAMISSION) {\n\t\t\t\t\tdatasize += sizeof(numunits);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t//.....................................................................\n\t\t// FRAMESYNC event: This >should< be the only event in the buffer,\n\t\t// and it will be uncompressed.\n\t\t//.....................................................................\n\t\telse {\n\t\t\tpos += (datasize + sizeof(EventClass::EventType));\n\t\t\tleftover -= (datasize + sizeof(EventClass::EventType));\n\t\t\tevent = (EventClass *)(((char *)buf) + pos);\n\n\t\t\t//..................................................................\n\t\t\t// size of FRAMESYNC event - EventType size\n\t\t\t//..................................................................\n\t\t\tdatasize = (offsetof(EventClass, Data) +\n\t\t\t\t\t\t\tsize_of(EventClass, Data.FrameInfo)) -\n\t\t\t\t\t\t\tsizeof(EventClass::EventType);\n\t\t}\n\t}\n\n\treturn (count);\n\n}\t// end of Extract_Compressed_Events\n\n\n/***************************************************************************\n * Execute_DoList -- Executes commands from the DoList                     *\n *                                                                         *\n * This routine executes any events in the DoList that need to be executed\t*\n * on the current game frame.  The events must be executed in a special\t\t*\n * order, so that all systems execute all events in exactly the same\t\t\t*\n * order.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * This routine also handles checking the Game CRC sent by other systems\t*\n * against my own, to be sure we're still in sync.\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tmax_houses\t# houses to execute commands for\t\t\t\t\t\t\t\t\t*\n *\t\tbase_house\tHousesType to start with\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tnet\t\t\tptr to connection manager; NULL if none\t\t\t\t\t\t*\n *\t\tskip_crc\t\ta frame-based countdown timer; if it's non-zero, the\t\t*\n *\t\t\t\t\t\tCRC check will be skipped.  Ignored if NULL.\t\t\t\t\t*\n *\t\ttheir_frame\tarray of their frame #'s\t\t\t\t\t\t\t\t\t\t\t*\n *\t\ttheir_sent\tarray of # commands they've sent\t\t\t\t\t\t\t\t\t*\n *\t\ttheir_recv\tarray of # commands I've received from them\t\t\t\t\t*\n *                                                                         *\n * (their_xxx are ignored if 'net' is NULL.)\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = some error occurred (CRC error, packet rcv'd too late.)\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Execute_DoList(int max_houses, HousesType base_house,\n\tConnManClass *net, CDTimerClass<FrameTimerClass> *skip_crc,\n\tlong *their_frame, unsigned short *their_sent, unsigned short *their_recv)\n{\n\tHousesType house;\n\tHouseClass *hptr;\n\tint i,j,k;\n\tint index;\n\tint check_crc;\n\n\tCheck_Mirror();\n\n#if(TIMING_FIX)\n\t//\n\t// If MPlayerMaxAhead is recomputed such that it increases, the systems\n\t// may try to free-run to the new MaxAhead value.  If so, they may miss\n\t// an event that was generated after the TIMING event was created, but\n\t// before it executed; this event will be scheduled with the older,\n\t// shorter MaxAhead value.  If a system doesn't receive this event, it\n\t// may execute past the frame it's scheduled to execute on, creating\n\t// a Packet-Recieved-Too-Late error.  To prevent this, find any events\n\t// that are scheduled to execute during this \"period of vulnerability\",\n\t// and re-schedule for the end of that period.\n\t//\n\tfor (j = 0; j < DoList.Count; j++) {\n\t\tif (DoList[j].Type != EventClass::FRAMEINFO &&\n\t\t\tDoList[j].Frame > NewMaxAheadFrame1 &&\n\t\t\tDoList[j].Frame < NewMaxAheadFrame2) {\n\t\t\tDoList[j].Frame = NewMaxAheadFrame2;\n\t\t\t#ifdef MIRROR_QUEUE\n\t\t\tMirrorList[j].Frame = NewMaxAheadFrame2;\n\t\t\t#endif\n\t\t}\n\t}\n#endif\n\n\t//------------------------------------------------------------------------\n\t//\tExecute the DoList.  Events must be executed in the same order on all\n\t//\tsystems; so, execute them in the order of the HouseClass array.  This\n\t//\tarray is stored in the same order on all systems.\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < max_houses; i++) {\n\t\t//.....................................................................\n\t\t//\tConvert our index into a HousesType value\n\t\t//.....................................................................\n\t\thouse = (HousesType)(i + base_house);\n\t\thptr = HouseClass::As_Pointer(house);\n\n\t\t//.....................................................................\n\t\t// If for some reason this house doesn't exist, skip it.\n\t\t// Also, if this house has exited the game, skip it.  (The user can\n\t\t// generate events after he exits, because the exit event is scheduled\n\t\t// at least FrameSendRate*3 frames ahead.  If one system gets these\n\t\t// packets & another system doesn't, they'll go out of sync because\n\t\t// they aren't checking the CommandCount for that house, since that\n\t\t// house isn't connected any more.)\n\t\t//.....................................................................\n\t\tif (!hptr) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (!hptr->IsHuman) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tLoop through all events\n\t\t//.....................................................................\n\t\tfor (j = 0; j < DoList.Count; j++) {\n\n\t\t\tif (net)\n\t\t\t\tUpdate_Queue_Mono (net, 6);\n\n\t\t\t//..................................................................\n\t\t\t//\tIf this event was from the currently-executing player ID, and it's\n\t\t\t//\ttime to execute it, execute it.\n\t\t\t//..................................................................\n\t\t\tif (DoList[j].ID == hptr->ID && Frame >= DoList[j].Frame &&\n\t\t\t\t!DoList[j].IsExecuted) {\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tError if it's too late to execute this packet!\n\t\t\t\t// (Hack: disable this check for solo or skirmish mode.)\n\t\t\t\t//...............................................................\n\t\t\t\tif (Frame > DoList[j].Frame && DoList[j].Type !=\n\t\t\t\t\tEventClass::FRAMEINFO && Session.Type != GAME_NORMAL &&\n\t\t\t\t\tSession.Type != GAME_SKIRMISH) {\n\n#if(TEN)\n\t\t\t\t\tSend_TEN_Packet_Too_Late();\n#endif\t// TEN\n\n#if(MPATH)\n\t\t\t\t\t//Send_MPATH_Packet_Too_Late();\n#endif\t// MPATH\n\n\t\t\t\t\tDump_Packet_Too_Late_Stuff(&DoList[j], net, their_frame,\n\t\t\t\t\t\ttheir_sent, their_recv);\n\t\t\t\t\tWWMessageBox().Process (TXT_PACKET_TOO_LATE);\n\t\t\t\t\treturn (0);\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tOnly execute EXIT & OPTIONS commands if they're from myself.\n\t\t\t\t//...............................................................\n\t\t\t\tif (DoList[j].Type==EventClass::EXIT ||\n\t\t\t\t\t\tDoList[j].Type==EventClass::OPTIONS) {\n\n#ifdef WIN32\n\t\t\t\t\tif (DoList[j].Type==EventClass::EXIT) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Flag that this house lost because it quit.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tHousesType quithouse;\n\t\t\t\t\t\tHouseClass *quithptr;\n\n\t\t\t\t\t\tfor (int player = 0; player < max_houses ; player++) {\n\t\t\t\t\t\t\tquithouse = (HousesType)(player + base_house);\n\t\t\t\t\t\t\tquithptr = HouseClass::As_Pointer(quithouse);\n\t\t\t\t\t\t\tif (!quithptr) {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (quithptr->ID == DoList[j].ID) {\n\t\t\t\t\t\t\t\tquithptr->IsGiverUpper = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Send the game statistics packet now since the game is effectivly over\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (Session.Players.Count() == 2 &&\n\t\t\t\t\t\t\t\tSession.Type == GAME_INTERNET &&\n\t\t\t\t\t\t\t\t!GameStatisticsPacketSent) {\n\t\t\t\t\t\t\tRegister_Game_End_Time();\n\t\t\t\t\t\t\tSend_Statistics_Packet();\t\t//\tEvent - player aborted, and there were only 2 left.\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n#endif\t//WIN32\n\n\t\t\t\t\tif (Debug_Print_Events) {\n\t\t\t\t\t\tif (DoList[j].Type==EventClass::EXIT) {\n\t\t\t\t\t\t\tprintf(\"(%d) Executing EXIT, ID:%d (%s), EvFrame:%d\\n\",\n\t\t\t\t\t\t\t\tFrame,\n\t\t\t\t\t\t\t\tDoList[j].ID,\n\t\t\t\t\t\t\t\t(HouseClass::As_Pointer((HousesType)(DoList[j].ID)))->IniName,\n\t\t\t\t\t\t\t\tDoList[j].Frame);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (DoList[j].ID == PlayerPtr->ID) {\n\t\t\t\t\t\tDoList[j].Execute();\n\t\t\t\t\t} else if (DoList[j].Type==EventClass::EXIT) {\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tIf this EXIT event isn't from myself, destroy the connection\n\t\t\t\t\t//\tfor that player.  The HousesType for this event is the\n\t\t\t\t\t// connection ID.\n\t\t\t\t\t//............................................................\n\t\t\t\t\t\tif (Session.Type == GAME_MODEM ||\n\t\t\t\t\t\t\tSession.Type == GAME_NULL_MODEM) {\n\t\t\t\t\t\t\tDestroy_Null_Connection( house, 0 );\n\t\t\t\t\t\t} else if ((Session.Type == GAME_IPX ||\n\t\t\t\t\t\t\tSession.Type == GAME_INTERNET ||\n\t\t\t\t\t\t\tSession.Type == GAME_TEN ||\n\t\t\t\t\t\t\tSession.Type == GAME_MPATH) && net) {\n\t\t\t\t\t\t\tindex = net->Connection_Index (house);\n\t\t\t\t\t\t\tif (index != -1) {\n\t\t\t\t\t\t\t\tfor (k = index; k < net->Num_Connections() - 1; k++) {\n\t\t\t\t\t\t\t\t\ttheir_frame[k] = their_frame[k+1];\n\t\t\t\t\t\t\t\t\ttheir_sent[k] = their_sent[k+1];\n\t\t\t\t\t\t\t\t\ttheir_recv[k] = their_recv[k+1];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (Session.Type == GAME_IPX ||\n\t\t\t\t\t\t\t\t\tSession.Type == GAME_INTERNET) {\n\t\t\t\t\t\t\t\t\tDestroy_Connection(house,0);\n\t\t\t\t\t\t\t\t}\n#if(TEN)\n\t\t\t\t\t\t\t\telse if (Session.Type == GAME_TEN) {\n\t\t\t\t\t\t\t\t\tDestroy_TEN_Connection(house,0);\n\t\t\t\t\t\t\t\t}\n#endif\t// TEN\n#if(MPATH)\n\t\t\t\t\t\t\t\telse if (Session.Type == GAME_MPATH) {\n\t\t\t\t\t\t\t\t\tDestroy_MPATH_Connection(house,0);\n\t\t\t\t\t\t\t\t}\n#endif\t// MPATH\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// Special case for recording playback: turn the house over\n\t\t\t\t\t\t// to the computer.\n\t\t\t\t\t\t//\n\t\t\t\t\t\tif (Session.Play && DoList[j].Type==EventClass::EXIT) {\n\t\t\t\t\t\t\thptr->IsHuman = false;\n\t\t\t\t\t\t\thptr->IQ = Rule.MaxIQ;\n\t\t\t\t\t\t\thptr->Computer_Paranoid();\n\t\t\t\t\t\t\tstrcpy (hptr->IniName,Text_String(TXT_COMPUTER));\n\t\t\t\t\t\t\tSession.NumPlayers--;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tFor a FRAMEINFO event, check the CRC value.\n\t\t\t\t//...............................................................\n\t\t\t\telse if (DoList[j].Type == EventClass::FRAMEINFO) {\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// Skip the CRC check if we're less than 32 frames into the game;\n\t\t\t\t\t// this will prevent a newly-loaded modem game from instantly\n\t\t\t\t\t// going out of sync, if the games were saved at different\n\t\t\t\t\t// frame numbers.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tif (!skip_crc || *skip_crc == 0) {\n\t\t\t\t\t\tcheck_crc = 1;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tcheck_crc = 0;\n\t\t\t\t\t}\n\t\t\t\t\tif (check_crc\n\t\t\t\t\t\t&& DoList[j].Frame == Frame\n\t\t\t\t\t\t&& DoList[j].Data.FrameInfo.Delay < 32) {\n\t\t\t\t\t\tindex = ((DoList[j].Frame - DoList[j].Data.FrameInfo.Delay) &\n\t\t\t\t\t\t\t0x001f);\n\t\t\t\t\t\tif (CRC[index] != DoList[j].Data.FrameInfo.CRC) {\n\t\t\t\t\t\t\tPrint_CRCs(&DoList[j]);\n\n#if(TEN)\n\t\t\t\t\t\t\tSend_TEN_Out_Of_Sync();\n#endif\t// TEN\n\n#if(MPATH)\n\t\t\t\t\t\t\t//Send_MPATH_Out_Of_Sync();\n#endif\t// MPATH\n\n\t\t\t\t\t\t\tif (WWMessageBox().Process (TXT_OUT_OF_SYNC,\n\t\t\t\t\t\t\t\tTXT_CONTINUE, TXT_STOP) == 0) {\n\t\t\t\t\t\t\t\tif (Session.Type == GAME_MODEM ||\n\t\t\t\t\t\t\t\t\tSession.Type == GAME_NULL_MODEM) {\n\t\t\t\t\t\t\t\t\tDestroy_Null_Connection( house, -1 );\n\t\t\t\t\t\t\t\t\tShutdown_Modem();\n\t\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse if ((Session.Type == GAME_IPX ||\n\t\t\t\t\t\t\t\t\tSession.Type == GAME_INTERNET) && net) {\n\t\t\t\t\t\t\t\t\twhile (net->Num_Connections()) {\n\t\t\t\t\t\t\t\t\t\tKeyboard->Check();\n\t\t\t\t\t\t\t\t\t\tDestroy_Connection (net->Connection_ID(0), -1);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n#if(TEN)\n\t\t\t\t\t\t\t\telse if (Session.Type == GAME_TEN && net) {\n\t\t\t\t\t\t\t\t\twhile (net->Num_Connections()) {\n\t\t\t\t\t\t\t\t\t\tDestroy_TEN_Connection (net->Connection_ID(0), -1);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n#endif\n#if(MPATH)\n\t\t\t\t\t\t\t\telse if (Session.Type == GAME_MPATH && net) {\n\t\t\t\t\t\t\t\t\twhile (net->Num_Connections()) {\n\t\t\t\t\t\t\t\t\t\tDestroy_MPATH_Connection (net->Connection_ID(0), -1);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\t\t\tMap.Flag_To_Redraw(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\treturn (0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn (1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t//\tExecute other commands\n\t\t\t\t//...............................................................\n\t\t\t\telse {\n\t\t\t\t\tDoList[j].Execute();\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tMark this event as executed.\n\t\t\t\t//...............................................................\n\t\t\t\tDoList[j].IsExecuted = 1;\n\t\t\t\t#ifdef MIRROR_QUEUE\n\t\t\t\tMirrorList[j].IsExecuted = 1;\n\t\t\t\t#endif\n\t\t\t}\n\t\t}\n\t}\n\n\treturn (1);\n\n}\t// end of Execute_DoList\n\n\n/***************************************************************************\n * Clean_DoList -- Cleans out old events from the DoList                   *\n *                                                                         *\n * Currently, an event can only be removed from the DoList if it's at the\t*\n * head of the list; and event can't be removed from the middle.  So,\t\t*\n * this routine loops as long as the next event in the DoList has been\t\t*\n * executed, it's removed.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tptr to connection manager; ignored if NULL\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Clean_DoList(ConnManClass *net)\n{\n\twhile (DoList.Count) {\n\n\t\tKeyboard->Check();\n\n\t\tif (net)\n\t\t\tUpdate_Queue_Mono (net, 7);\n\n\t\t//.....................................................................\n\t\t//\tDiscard events that have been executed, OR it's too late to execute.\n\t\t//\t(This happens if another player exits the game; he'll leave FRAMEINFO\n\t\t//\tevents lying around in my queue.  They won't have been \"executed\",\n\t\t//\tbecause his IPX connection was destroyed.)\n\t\t//.....................................................................\n\t\tif ( (DoList.First().IsExecuted) || (Frame > DoList.First().Frame) ) {\n\t\t\tDoList.Next();\n\t\t\t#ifdef MIRROR_QUEUE\n\t\t\tMirrorList.Next();\n\t\t\t#endif\n\t\t}\n\t\telse {\n\t\t\tbreak;\n\t\t}\n\t}\n\n}\t// end of Clean_DoList\n\n\n/***************************************************************************\n * Queue_Record -- Records the DoList to disk                              *\n *                                                                         *\n * This routine just saves any events in the DoList to disk; we can later\t*\n * \"play back\" the recording just be pulling events from disk rather than\t*\n * from the network!\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   08/14/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Queue_Record(void)\n{\n\tint i,j;\n\n\t//------------------------------------------------------------------------\n\t//\tCompute # of events to save this frame\n\t//------------------------------------------------------------------------\n\tj = 0;\n\tfor (i = 0; i < DoList.Count; i++) {\n\t\tif (Frame == DoList[i].Frame && !DoList[i].IsExecuted) {\n\t\t\tj++;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSave the # of events, then all events.\n\t//------------------------------------------------------------------------\n\tSession.RecordFile.Write (&j,sizeof(j));\n\tfor (i = 0; i < DoList.Count; i++) {\n\t\tif (Frame == DoList[i].Frame && !DoList[i].IsExecuted) {\n\t\t\tSession.RecordFile.Write (&DoList[i],sizeof (EventClass));\n\t\t\tj--;\n\t\t}\n\t}\n\n}\t/* end of Queue_Record */\n\n\n/***************************************************************************\n * Queue_Playback -- plays back queue entries from a record file           *\n *                                                                         *\n * This routine reads events from disk, putting them into the DoList;\t\t*\n * it then executes the DoList just like the network version does.  The\t\t*\n * result is that the game \"plays back\" like a recording.\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This routine detects mouse motion and stops playback, so it can work\t\t*\n * like an \"attract\" mode, showing a demo of the game itself.\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/15/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Queue_Playback(void)\n{\n\tint numevents;\n\tEventClass event;\n\tint i;\n\tint ok;\n  \tstatic int mx,my;\n\tint max_houses;\n\tHousesType base_house;\n\tint key;\n\tint testframe;\n\n\t//------------------------------------------------------------------------\n\t//\tIf the user hits ESC, stop the playback\n\t//------------------------------------------------------------------------\n\tif (Keyboard->Check()) {\n\t\tkey = Keyboard->Get();\n\t\tif (key == KA_ESC || Session.Attract) {\n\t\t\tGameActive = 0;\n\t\t\treturn;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t// If we're in \"Attract\" mode, and the user moves the mouse, stop the\n\t// playback.\n\t//------------------------------------------------------------------------\n\tif (Session.Attract && Frame > 0 &&\n\t\t(mx != Get_Mouse_X() || my != Get_Mouse_Y())) {\n\t\tGameActive = 0;\n\t\treturn;\n\t}\n\tmx = Get_Mouse_X();\n\tmy = Get_Mouse_Y();\n\n\t//------------------------------------------------------------------------\n\t//\tCompute the Game's CRC\n\t//------------------------------------------------------------------------\n\tCompute_Game_CRC();\n\tCRC[Frame & 0x001f] = GameCRC;\n\n\t//------------------------------------------------------------------------\n\t// If we've reached the CRC print frame, do so & exit\n\t//------------------------------------------------------------------------\n\tif (Frame >= Session.TrapPrintCRC) {\n\t\tPrint_CRCs(NULL);\n\t\t//Prog_End();\n\t\tEmergency_Exit(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tDon't read anything the first time through (since the Queue_AI_Network\n\t//\troutine didn't write anything the first time through); do this after the\n\t//\tCRC is computed, since we'll still need a CRC for Frame 0.\n\t//------------------------------------------------------------------------\n\tif (Frame==0 && Session.Type!=GAME_NORMAL) {\n\t\treturn;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Only process every 'FrameSendRate' frames\n\t//------------------------------------------------------------------------\n\ttestframe = ((Frame + (Session.FrameSendRate - 1)) /\n\t\tSession.FrameSendRate) * Session.FrameSendRate;\n\tif ( (Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH) &&\n\t\tSession.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\tif (Frame != testframe) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tRead the DoList from disk\n\t//------------------------------------------------------------------------\n\tok = 1;\n\tif (Session.RecordFile.Read (&numevents, sizeof(numevents)) ==\n\t\tsizeof(numevents)) {\n\t\tfor (i = 0; i < numevents; i++) {\n\t\t\tif (Session.RecordFile.Read (&event, sizeof(EventClass)) ==\n\t\t\t\tsizeof(EventClass)) {\n\t\t\t\tevent.IsExecuted = 0;\n\t\t\t\tDoList.Add (event);\n\t\t\t\t#ifdef MIRROR_QUEUE\n\t\t\t\tMirrorList.Add(event);\n\t\t\t\t#endif\n\t\t\t}\n\t\t\telse {\n\t\t\t\tok = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\telse {\n\t\tok = 0;\n\t}\n\n\tif (!ok) {\n\t\tGameActive = 0;\n\t\treturn;\n\t}\n\n\n\t//------------------------------------------------------------------------\n\t// Execute the DoList; if an error occurs, bail out.\n\t//------------------------------------------------------------------------\n\tif (Session.Type == GAME_NORMAL) {\n\t\tmax_houses = 1;\n\t\tbase_house = PlayerPtr->Class->House;\n\t}\n\telse {\n\t\tmax_houses = Session.MaxPlayers;\n\t\tbase_house = HOUSE_MULTI1;\n\t}\n\tif (!Execute_DoList(max_houses, base_house, NULL, NULL, NULL, NULL, NULL)) {\n\t\tGameActive = 0;\n\t\treturn;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tClean out the DoList\n\t//------------------------------------------------------------------------\n\tClean_DoList(NULL);\n\n}\t/* end of Queue_Playback */\n\n\n/***************************************************************************\n * Compute_Game_CRC -- Computes a CRC value of the entire game.\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/09/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Compute_Game_CRC(void)\n{\n\tint i,j;\n\tVesselClass *vessp;\n\tInfantryClass *infp;\n\tUnitClass *unitp;\n\tBuildingClass *bldgp;\n\tObjectClass *objp;\n\tHouseClass *housep;\n\n\tGameCRC = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInfantry\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Infantry.Count(); i++) {\n\t\tinfp = (InfantryClass *)Infantry.Active_Ptr(i);\n\t\tAdd_CRC (&GameCRC, (int)infp->Coord + (int)infp->PrimaryFacing);\n\t\tAdd_CRC (&GameCRC, (int)infp->Speed + (int)infp->NavCom);\n\t\tAdd_CRC (&GameCRC, (int)infp->Mission + (int)infp->TarCom);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tUnits\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Units.Count(); i++) {\n\t\tunitp = (UnitClass *)Units.Active_Ptr(i);\n\t\tAdd_CRC (&GameCRC, (int)unitp->Coord + (int)unitp->PrimaryFacing +\n\t\t\t(int)unitp->SecondaryFacing);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tShippies\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Vessels.Count(); i++) {\n\t\tvessp = (VesselClass *)Vessels.Active_Ptr(i);\n\t\tAdd_CRC (&GameCRC, (int)vessp->Coord + (int)vessp->PrimaryFacing);\n\t\tAdd_CRC (&GameCRC, (int)vessp->Speed + (int)vessp->NavCom);\n\t\tAdd_CRC (&GameCRC, (int)vessp->Strength);\n\t\tAdd_CRC (&GameCRC, (int)vessp->Mission + (int)vessp->TarCom);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tBuildings\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Buildings.Count(); i++) {\n\t\tbldgp = (BuildingClass *)Buildings.Active_Ptr(i);\n\t\tAdd_CRC (&GameCRC, (int)bldgp->Coord + (int)bldgp->PrimaryFacing);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tHouses\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Houses.Count(); i++) {\n\t\thousep = (HouseClass *)Houses.Active_Ptr(i);\n\t\tAdd_CRC (&GameCRC, (int)housep->Credits + (int)housep->Power +\n\t\t\t(int)housep->Drain);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tMap Layers\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < LAYER_COUNT; i++) {\n\t\tfor (j = 0; j < Map.Layer[i].Count(); j++) {\n\t\t\tobjp = Map.Layer[i][j];\n\t\t\tAdd_CRC (&GameCRC, (int)objp->Coord + (int)objp->What_Am_I());\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tLogic Layers\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Logic.Count(); i++) {\n\t\tobjp = Logic[i];\n\t\tAdd_CRC (&GameCRC, (int)objp->Coord + (int)objp->What_Am_I());\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tA random #\n\t//------------------------------------------------------------------------\n//\tAdd_CRC(&GameCRC, Scen.RandomNumber.Seed);\n\tAdd_CRC(&GameCRC, Scen.RandomNumber);\n\n}\t/* end of Compute_Game_CRC */\n\n\n/***************************************************************************\n * Add_CRC -- Adds a value to a CRC                                        *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tcrc\t\tptr to crc\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tval\t\tvalue to add\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/09/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid Add_CRC(unsigned long *crc, unsigned long val)\n{\n\tint hibit;\n\n\tif ( (*crc) & 0x80000000) {\n\t\thibit = 1;\n\t}\n\telse {\n\t\thibit = 0;\n\t}\n\n\t(*crc) <<= 1;\n\t(*crc) += val;\n\t(*crc) += hibit;\n\n}\t/* end of Add_CRC */\n\n/***************************************************************************\n * Print_CRCs -- Prints a data file for finding Sync Bugs\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tev -- event to display\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/09/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Print_CRCs(EventClass *ev)\n{\n\tint i,j;\n\tInfantryClass *infp;\n\tUnitClass *unitp;\n\tVesselClass *vesselp;\n\tBuildingClass *bldgp;\n\tObjectClass *objp;\n\tFILE *fp;\n\tHouseClass *housep;\n\tHousesType house;\n\tint color;\n\n\tMono_Clear_Screen();\n\tMono_Set_Cursor (0,0);\n\tfp = fopen(\"OUT.TXT\",\"wt\");\n\tif (fp==NULL) {\n\t\treturn;\n\t}\n\n\tfor (i = 0; i < 32; i++) {\n\t\tfprintf(fp,\"CRC[%d]=%x\\n\",i,CRC[i]);\n\t}\n\n\t//\n\t// Houses\n\t//\n\tfor (house = HOUSE_MULTI1; house <= HOUSE_MULTI8; house++) {\n\t\tGameCRC = 0;\n\t\thousep = HouseClass::As_Pointer (house);\n\t\tif (housep) {\n\t\t\tHousesType actlike = housep->ActLike;\n\t\t\tcolor = housep->RemapColor;\n\t\t\tfprintf(fp,\"%s: IsHuman:%d  Color:%s  ID:%d  ActLike:%s\\n\",\n\t\t\t\thousep->IniName,\n\t\t\t\thousep->IsHuman,\n\t\t\t\tColorNames[color],\n\t\t\t\thousep->ID,\n\t\t\t\tHouseClass::As_Pointer(actlike)->Class->Name());\n\t\t\tAdd_CRC (&GameCRC, (int)housep->Credits + (int)housep->Power +\n\t\t\t\t(int)housep->Drain);\n\t\t\tMono_Printf(\"House %s:%x\\n\",housep->Class->Name(),GameCRC);\n\t\t}\n\t}\n\n\t//\n\t// Infantry\n\t//\n\tfor (house = HOUSE_MULTI1; house <= HOUSE_MULTI8; house++) {\n\t\thousep = HouseClass::As_Pointer (house);\n\t\tif (housep) {\n\t\t\tGameCRC = 0;\n\t\t\tfprintf(fp,\"-------------------- %s Infantry -------------------\\n\",\n\t\t\t\thousep->Class->Name());\n\t\t\tfor (i = 0; i < Infantry.Count(); i++) {\n\t\t\t\tinfp = (InfantryClass *)Infantry.Active_Ptr(i);\n\t\t\t\tif (infp->Owner()==house) {\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)infp->Coord + (int)infp->PrimaryFacing);\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)infp->Speed + (int)infp->NavCom);\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)infp->Mission + (int)infp->TarCom);\n\t\t\t\t\tfprintf(fp,\"COORD:%x   Facing:%d   Mission:%d   Type:%d   Tgt:%x Speed:%d NavCom:%x\\n\",\n\t\t\t\t\t\tinfp->Coord,(int)infp->PrimaryFacing,infp->Get_Mission(),\n\t\t\t\t\t\tinfp->Class->Type, infp->As_Target(), infp->Speed, infp->NavCom);\n\t\t\t\t}\n\t\t\t}\n\t\t\tMono_Printf(\"%s Infantry:%x\\n\",housep->Class->Name(),GameCRC);\n\t\t}\n\t}\n\n\t//\n\t// Units\n\t//\n\tfor (house = HOUSE_MULTI1; house <= HOUSE_MULTI8; house++) {\n\t\thousep = HouseClass::As_Pointer (house);\n\t\tif (housep) {\n\t\t\tGameCRC = 0;\n\t\t\tfprintf(fp,\"-------------------- %s Units -------------------\\n\",\n\t\t\t\thousep->Class->Name());\n\t\t\tfor (i = 0; i < Units.Count(); i++) {\n\t\t\t\tunitp = (UnitClass *)Units.Active_Ptr(i);\n\t\t\t\tif (unitp->Owner()==house) {\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)unitp->Coord + (int)unitp->PrimaryFacing +\n\t\t\t\t\t\t(int)unitp->SecondaryFacing);\n\t\t\t\t\tfprintf(fp,\n\t\t\t\t\t\t\"COORD:%x   Facing:%d   Facing2:%d   Mission:%d   Type:%d   Tgt:%x\\n\",\n\t\t\t\t\t\tunitp->Coord,(int)unitp->PrimaryFacing,\n\t\t\t\t\t\t(int)unitp->SecondaryFacing,unitp->Get_Mission(),\n\t\t\t\t\t\tunitp->Class->Type, unitp->As_Target());\n\t\t\t\t}\n\t\t\t}\n\t\t\tMono_Printf(\"%s Units:%x\\n\",housep->Class->Name(),GameCRC);\n\t\t}\n\t}\n\n\t//\n\t// Vessels\n\t//\n\tfor (house = HOUSE_MULTI1; house <= HOUSE_MULTI8; house++) {\n\t\thousep = HouseClass::As_Pointer (house);\n\t\tif (housep) {\n\t\t\tGameCRC = 0;\n\t\t\tfprintf(fp,\"-------------------- %s Vessels -------------------\\n\",\n\t\t\t\thousep->Class->Name());\n\t\t\tfor (i = 0; i < Vessels.Count(); i++) {\n\t\t\t\tvesselp = (VesselClass *)Vessels.Active_Ptr(i);\n\t\t\t\tif (vesselp->Owner()==house) {\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)vesselp->Coord + (int)vesselp->PrimaryFacing);\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)vesselp->Speed + (int)vesselp->NavCom);\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)vesselp->Strength);\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)vesselp->Mission + (int)vesselp->TarCom);\n\t\t\t\t\tfprintf(fp,\n\t\t\t\t\t\t\"COORD:%x   Facing:%d   Mission:%d   Strength:%d Type:%d   Tgt:%x\\n\",\n\t\t\t\t\t\tvesselp->Coord,(int)vesselp->PrimaryFacing,\n\t\t\t\t\t\tvesselp->Get_Mission(), vesselp->Strength,\n\t\t\t\t\t\tvesselp->Class->Type, vesselp->As_Target());\n\t\t\t\t}\n\t\t\t}\n\t\t\tMono_Printf(\"%s Vessels:%x\\n\",housep->Class->Name(),GameCRC);\n\t\t}\n\t}\n\n\t//\n\t// Buildings\n\t//\n\tfor (house = HOUSE_MULTI1; house <= HOUSE_MULTI8; house++) {\n\t\thousep = HouseClass::As_Pointer (house);\n\t\tif (housep) {\n\t\t\tGameCRC = 0;\n\t\t\tfprintf(fp,\"-------------------- %s Buildings -------------------\\n\",\n\t\t\t\thousep->Class->Name());\n\t\t\tfor (i = 0; i < Buildings.Count(); i++) {\n\t\t\t\tbldgp = (BuildingClass *)Buildings.Active_Ptr(i);\n\t\t\t\tif (bldgp->Owner()==house) {\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)bldgp->Coord + (int)bldgp->PrimaryFacing);\n\t\t\t\t\tfprintf(fp,\"COORD:%x   Facing:%d   Mission:%d   Type:%d   Tgt:%x\\n\",\n\t\t\t\t\t\tbldgp->Coord,(int)bldgp->PrimaryFacing,bldgp->Get_Mission(),\n\t\t\t\t\t\tbldgp->Class->Type, bldgp->As_Target());\n\t\t\t\t}\n\t\t\t}\n\t\t\tMono_Printf(\"%s Buildings:%x\\n\",housep->Class->Name(),GameCRC);\n\t\t}\n\t}\n\n\t//\n\t// Animations\n\t//\n\tAnimClass *animp;\n\t\tfprintf(fp,\"-------------------- Animations -------------------\\n\");\n\tfor (i = 0; i < Anims.Count(); i++) {\n\t\tanimp = (AnimClass *)Anims.Active_Ptr(i);\n\t\tfprintf(fp,\"Target:%x OwnerHouse:%d Loops:%d\\n\",\n\t\t\tanimp->xObject,\n\t\t\tanimp->OwnerHouse,\n\t\t\tanimp->Loops);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tMap Layers\n\t//------------------------------------------------------------------------\n\tGameCRC = 0;\n\tfor (i = 0; i < LAYER_COUNT; i++) {\n\t\tfprintf(fp,\">>>> MAP LAYER %d <<<<\\n\",i);\n\t\tfor (j = 0; j < Map.Layer[i].Count(); j++) {\n\t\t\tobjp = Map.Layer[i][j];\n\t\t\tAdd_CRC (&GameCRC, (int)objp->Coord + (int)objp->What_Am_I());\n\t\t\tfprintf(fp,\"Object %d: %x \",j,objp->Coord);\n\n\t\t\tif (objp->What_Am_I() == RTTI_AIRCRAFT)\n\t\t\t\tfprintf(fp,\"Aircraft  (Type:%d) \",\n\t\t\t\t\t(AircraftType)(*((AircraftClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_ANIM)\n\t\t\t\tfprintf(fp,\"Anim      (Type:%d) \",\n\t\t\t\t\t(AnimType)(*((AnimClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_BUILDING)\n\t\t\t\tfprintf(fp,\"Building  (Type:%d) \",\n\t\t\t\t\t(StructType)(*((BuildingClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_BULLET)\n\t\t\t\tfprintf(fp,\"Bullet    (Type:%d) \",\n\t\t\t\t\t(BulletType)(*((BulletClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_INFANTRY)\n\t\t\t\tfprintf(fp,\"Infantry  (Type:%d) \",\n\t\t\t\t\t(InfantryType)(*((InfantryClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_OVERLAY)\n\t\t\t\tfprintf(fp,\"Overlay   (Type:%d) \",\n\t\t\t\t\t(OverlayType)(*((OverlayClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_SMUDGE)\n\t\t\t\tfprintf(fp,\"Smudge    (Type:%d) \",\n\t\t\t\t\t(SmudgeType)(*((SmudgeClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_TEMPLATE)\n\t\t\t\tfprintf(fp,\"Template  (Type:%d) \",\n\t\t\t\t\t(TemplateType)(*((TemplateClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_TERRAIN)\n\t\t\t\tfprintf(fp,\"Terrain   (Type:%d) \",\n\t\t\t\t\t(TerrainType)(*((TerrainClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_UNIT)\n\t\t\t\tfprintf(fp,\"Unit      (Type:%d) \",\n\t\t\t\t\t(UnitType)(*((UnitClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_VESSEL)\n\t\t\t\tfprintf(fp,\"Vessel    (Type:%d) \",\n\t\t\t\t\t(VesselType)(*((VesselClass *)objp)));\n\n\t\t\thouse = objp->Owner();\n\t\t\tif (house!=HOUSE_NONE) {\n\t\t\t\thousep = HouseClass::As_Pointer (house);\n\t\t\t\tfprintf(fp,\"Owner: %s\\n\",housep->Class->IniName);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfprintf(fp,\"Owner: NONE\\n\");\n\t\t\t}\n\t\t}\n\t}\n\tMono_Printf(\"Map Layers:%x  \\n\",GameCRC);\n\n\t//------------------------------------------------------------------------\n\t//\tLogic Layers\n\t//------------------------------------------------------------------------\n\tGameCRC = 0;\n\tfprintf(fp,\">>>> LOGIC LAYER <<<<\\n\");\n\tfor (i = 0; i < Logic.Count(); i++) {\n\t\tobjp = Logic[i];\n\t\tAdd_CRC (&GameCRC, (int)objp->Coord + (int)objp->What_Am_I());\n\t\tfprintf(fp,\"Object %d: %x \",i,objp->Coord);\n\n\t\tif (objp->What_Am_I() == RTTI_AIRCRAFT)\n\t\t\tfprintf(fp,\"Aircraft  (Type:%d) \",\n\t\t\t\t(AircraftType)(*((AircraftClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_ANIM)\n\t\t\tfprintf(fp,\"Anim      (Type:%d) \",\n\t\t\t\t(AnimType)(*((AnimClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_BUILDING)\n\t\t\tfprintf(fp,\"Building  (Type:%d) \",\n\t\t\t\t(StructType)(*((BuildingClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_BULLET)\n\t\t\tfprintf(fp,\"Bullet    (Type:%d) \",\n\t\t\t\t(BulletType)(*((BulletClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_INFANTRY)\n\t\t\tfprintf(fp,\"Infantry  (Type:%d) \",\n\t\t\t\t(InfantryType)(*((InfantryClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_OVERLAY)\n\t\t\tfprintf(fp,\"Overlay   (Type:%d) \",\n\t\t\t\t(OverlayType)(*((OverlayClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_SMUDGE)\n\t\t\tfprintf(fp,\"Smudge    (Type:%d) \",\n\t\t\t\t(SmudgeType)(*((SmudgeClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_TEMPLATE)\n\t\t\tfprintf(fp,\"Template  (Type:%d) \",\n\t\t\t\t(TemplateType)(*((TemplateClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_TERRAIN)\n\t\t\tfprintf(fp,\"Terrain   (Type:%d) \",\n\t\t\t\t(TerrainType)(*((TerrainClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_UNIT)\n\t\t\tfprintf(fp,\"Unit      (Type:%d) \",\n\t\t\t\t(UnitType)(*((UnitClass *)objp)));\n\n\t\thouse = objp->Owner();\n\t\tif (house!=HOUSE_NONE) {\n\t\t\thousep = HouseClass::As_Pointer (house);\n\t\t\tfprintf(fp,\"Owner: %s\\n\",housep->Class->IniName);\n\t\t}\n\t\telse {\n\t\t\tfprintf(fp,\"Owner: NONE\\n\");\n\t\t}\n\t}\n\tMono_Printf(\"Logic:%x  \\n\",GameCRC);\n\n\t//------------------------------------------------------------------------\n\t//\tRandom # generator, frame #\n\t//------------------------------------------------------------------------\n\tMono_Printf(\"Random Number:%x  \\n\",Scen.RandomNumber.Seed);\n#ifdef RANDOM_COUNT\n\tfprintf(fp,\"\\nRandom Number:%x (Count1:%d, Count2:%d)\\n\",\n\t\tScen.RandomNumber.Seed,\n\t\tScen.RandomNumber.Count1,\n\t\tScen.RandomNumber.Count2);\n#else\n\tfprintf(fp,\"\\nRandom Number:%x\\n\",Scen.RandomNumber.Seed);\n#endif\n\n\tMono_Printf(\"My Frame:%d  \\n\",Frame);\n\tfprintf(fp,\"My Frame:%d\\n\",Frame);\n\n\tif (ev) {\n\t\tfprintf(fp,\"\\n\");\n\t\tfprintf(fp,\"Offending event:\\n\");\n\t\tfprintf(fp,\"  Type:         %d\\n\",ev->Type);\n\t\tfprintf(fp,\"  Frame:        %d\\n\",ev->Frame);\n\t\tfprintf(fp,\"  ID:           %x\\n\",ev->ID);\n\t\tfprintf(fp,\"  CRC:          %x\\n\",ev->Data.FrameInfo.CRC);\n\t\tfprintf(fp,\"  CommandCount: %d\\n\",ev->Data.FrameInfo.CommandCount);\n\t\tfprintf(fp,\"  Delay:        %d\\n\",ev->Data.FrameInfo.Delay);\n\t}\n\n\tfclose(fp);\n\n}\t/* end of Print_CRCs */\n\n\n/***************************************************************************\n * Init_Queue_Mono -- inits mono display                                   *\n *                                                                         *\n * This routine steals control of the mono screen away from the rest of\t\t*\n * the engine, by setting the global IsMono; if IsMono is set, the other\t*\n * routines in this module turn off the Mono display when they're done\t\t*\n * with it, so the rest of the engine won't over-write what we're writing.\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tptr to connection manager\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Init_Queue_Mono(ConnManClass *net)\n{\n#if(SHOW_MONO)\n\t//------------------------------------------------------------------------\n\t// Set 'IsMono' so we can steal the mono screen from the engine\n\t//------------------------------------------------------------------------\n\tif ((Frame==0 || Session.LoadGame) && MonoClass::Is_Enabled()) {\n\t\tIsMono = true;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Enable mono output for our stuff; we must Disable it before we return\n\t// control to the engine.\n\t//------------------------------------------------------------------------\n\tif (IsMono)\n\t\tMonoClass::Enable();\n\n\tif (net->Num_Connections() > 0) {\n\t\t//.....................................................................\n\t\t//\tNetwork mono debugging screen\n\t\t//.....................................................................\n\t\tif (NetMonoMode==0) {\n\t\t\tif (Frame==0 || Session.LoadGame || NewMonoMode) {\n\t\t\t\tnet->Configure_Debug (0, sizeof (CommHeaderType),\n\t\t\t\t\tsizeof(EventClass::EventType), EventClass::EventNames, 0, 27);\n\t\t\t\tnet->Mono_Debug_Print (0,1);\n\t\t\t\tNewMonoMode = 0;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tnet->Mono_Debug_Print (0,0);\n\t\t\t}\n\t\t}\n\t\t//.....................................................................\n\t\t//\tFlow control debugging output\n\t\t//.....................................................................\n\t\telse {\n\t\t\tif (NewMonoMode) {\n\t\t\t\tMono_Clear_Screen();\n\t\t\t\tMono_Printf(\"                         Queue AI:\\n\");\t// flowcount[0]\n\t\t\t\tMono_Printf(\"                Build Packet Loop:\\n\");\t// flowcount[1]\n\t\t\t\tMono_Printf(\"                       Frame Sync:\\n\");\t// flowcount[2]\n\t\t\t\tMono_Printf(\"                Frame Sync Resend:\\n\");\t// flowcount[3]\n\t\t\t\tMono_Printf(\"               Frame Sync Timeout:\\n\");\t// flowcount[4]\n\t\t\t\tMono_Printf(\"           Frame Sync New Message:\\n\");\t// flowcount[5]\n\t\t\t\tMono_Printf(\"                 DoList Execution:\\n\");\t// flowcount[6]\n\t\t\t\tMono_Printf(\"                  DoList Cleaning:\\n\");\t// flowcount[7]\n\t\t\t\tMono_Printf(\"\\n\");\n\t\t\t\tMono_Printf(\"                            Frame:\\n\");\n\t\t\t\tMono_Printf(\"                 Session.MaxAhead:\\n\");\n\t\t\t\tMono_Printf(\"                       their_recv:\\n\");\n\t\t\t\tMono_Printf(\"                       their_sent:\\n\");\n\t\t\t\tMono_Printf(\"                          my_sent:\\n\");\n\t\t\t\tNewMonoMode = 0;\n\t\t\t}\n\t\t}\n\t}\n#else\n\tnet = net;\n#endif\n}\t// end of Init_Queue_Mono\n\n\n/***************************************************************************\n * Update_Queue_Mono -- updates mono display                               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\t\tptr to connection manager\t\t\t\t\t\t\t\t\t\t*\n *\t\tflow_index\t\tindex # for flow-count updates\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t-1: display\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Update_Queue_Mono(ConnManClass *net, int flow_index)\n{\n#if(SHOW_MONO)\n\tstatic int flowcount[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};\n\n\t//------------------------------------------------------------------------\n\t// If 'NetMonoMode' is 1, display flowcount info\n\t//------------------------------------------------------------------------\n\tif (NetMonoMode==1) {\n\t\tif (flow_index >= 0 && flow_index < 20) {\n\t\t\tMono_Set_Cursor(35,flow_index);\n\t\t\tflowcount[flow_index]++;\n\t\t\tMono_Printf(\"%d\",flowcount[flow_index]);\n\t\t}\n\t}\n\t//------------------------------------------------------------------------\n\t// Otherwise, display the connection debug screen\n\t//------------------------------------------------------------------------\n\telse {\n\t\tnet->Mono_Debug_Print (0,0);\n\t}\n\n#else\n\tflow_index = flow_index;\n\tnet = net;\n#endif\n\n}\t// end of Update_Queue_Mono\n\n\n/***************************************************************************\n * Print_Framesync_Values -- displays frame-sync variables                 *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tcurframe\t\t\t\t\tcurrent game Frame #\t\t\t\t\t\t\t\t\t\t*\n *\t\tmax_ahead\t\t\t\tmax-ahead value\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tnum_connections\t\t# connections\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\ttheir_recv\t\t\t\t# commands I've received from my connections\t\t*\n *\t\ttheir_sent\t\t\t\t# commands each connection claims to have sent\t*\n *\t\tmy_sent\t\t\t\t\t# commands I've sent\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Print_Framesync_Values(long curframe, unsigned long max_ahead,\n\tint num_connections, unsigned short *their_recv,\n\tunsigned short *their_sent, unsigned short my_sent)\n{\n#if(SHOW_MONO)\n\tint i;\n\n\tif (NetMonoMode==1) {\n\t\tMono_Set_Cursor(35,9);\n\t\tMono_Printf(\"%d\",curframe);\n\n\t\tMono_Set_Cursor(35,10);\n\t\tMono_Printf(\"%d\",max_ahead);\n\n\t\tfor (i = 0; i < num_connections; i++) {\n\t\t\tMono_Set_Cursor(35 + i*5,11);\n\t\t\tMono_Printf(\"%4d\",(int)their_recv[i]);\n\t\t}\n\n\t\tfor (i = 0; i < num_connections; i++) {\n\t\t\tMono_Set_Cursor(35 + i*5,12);\n\t\t\tMono_Printf(\"%4d\",(int)their_sent[i]);\n\t\t}\n\n\t\tMono_Set_Cursor(35,13);\n\t\tMono_Printf(\"%4d\",(int)my_sent);\n\t}\n#else\n\tcurframe = curframe;\n\tmax_ahead = max_ahead;\n\tnum_connections = num_connections;\n\ttheir_recv = their_recv;\n\ttheir_sent = their_sent;\n\tmy_sent = my_sent;\n#endif\n}\t// end of Print_Framesync_Values\n\n\n/***************************************************************************\n * Dump_Packet_Too_Late_Stuff -- Dumps a debug file to disk                *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tevent\t\tptr to event to print\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/28/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Dump_Packet_Too_Late_Stuff(EventClass *event, ConnManClass *net,\n\tlong *their_frame, unsigned short *their_sent, unsigned short *their_recv)\n{\n\tFILE *fp;\n\tint i;\n\tHousesType house;\n\n\tfp = fopen(\"toolate.txt\", \"wt\");\n\tif (!fp) {\n\t\treturn;\n\t}\n\tfprintf(fp,\"----------------- Event data: ----------------------\\n\");\n\tfprintf(fp,\"Type:       %s\\n\",EventClass::EventNames[event->Type]);\n\tfprintf(fp,\"Frame:      %d\\n\",event->Frame);\n\tfprintf(fp,\"ID:         %d\\n\",event->ID);\n\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\tif (event->ID == Session.Players[i]->Player.ID) {\n\t\t\tfprintf(fp,\"Player's Name: %s\",Session.Players[i]->Name);\n\t\t}\n\t}\n\tfprintf(fp,\"\\n\");\n\n\tfprintf(fp,\"--------------------- My data: ---------------------\\n\");\n\tfprintf(fp,\"My Frame:%d\\n\",Frame);\n\tfprintf(fp,\"My MaxAhead:%d\\n\",Session.MaxAhead);\n\n\tif (net) {\n\t\tfprintf(fp,\"-------------------- Frame Stats: ------------------\\n\");\n\t\tfprintf(fp,\"Name          ID  TheirFrame  TheirSent  TheirRecv\\n\");\n\t\tfor (i = 0; i < net->Num_Connections(); i++) {\n\t\t\thouse = (HousesType)(net->Connection_ID(i));\n\t\t\tfprintf(fp,\"%12s  %2d    %6d      %6d      %6d\\n\",\n\t\t\t\t(HouseClass::As_Pointer(house))->IniName,\n\t\t\t\tnet->Connection_ID(i),\n\t\t\t\ttheir_frame[i],\n\t\t\t\ttheir_sent[i],\n\t\t\t\ttheir_recv[i]);\n\t\t}\n\t}\n\n\tfclose(fp);\n}\n\n/***************************************************************************\n * Check_Mirror -- Checks mirror memory                                    *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/14/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Check_Mirror(void)\n{\n#ifdef MIRROR_QUEUE\n\tint i;\n\tchar txt[80];\n\tunsigned long *ptr;\n\tint found_5s = 0;\n\n\tptr = (unsigned long *)(DoList.Get_Array());\n\tfor (i = 0; i < (MAX_EVENTS * 64 * sizeof(EventClass)) /\n\t\tsizeof(unsigned long); i++) {\n\t\tif (ptr[i] == 0x55555555) {\n\t\t\tsprintf(txt,\"55555555 found in DoList! Addr:%p\", &(ptr[i]));\n\t\t\tWWMessageBox().Process (txt);\n\t\t\tfound_5s = 1;\n\t\t}\n\t}\n\n\tptr = (unsigned long *)(MirrorList.Get_Array());\n\tfor (i = 0; i < (MAX_EVENTS * 64 * sizeof(EventClass)) /\n\t\tsizeof(unsigned long); i++) {\n\t\tif (ptr[i] == 0x55555555) {\n\t\t\tsprintf(txt,\"55555555 found in MirrorList! Addr:%p\", &(ptr[i]));\n\t\t\tWWMessageBox().Process (txt);\n\t\t\tfound_5s = 1;\n\t\t}\n\t}\n\n\tptr = (unsigned long *)(DoList.Get_Array());\n\tfor (i = 0; i < (MAX_EVENTS * 64 * sizeof(EventClass)) /\n\t\tsizeof(unsigned long); i++) {\n\t\tif (ptr[i] == 0xAAAAAAAA) {\n\t\t\tsprintf(txt,\"AAAAAAAA found in DoList! Addr:%p\", &(ptr[i]));\n\t\t\tWWMessageBox().Process (txt);\n\t\t\tfound_5s = 1;\n\t\t}\n\t}\n\n\tptr = (unsigned long *)(MirrorList.Get_Array());\n\tfor (i = 0; i < (MAX_EVENTS * 64 * sizeof(EventClass)) /\n\t\tsizeof(unsigned long); i++) {\n\t\tif (ptr[i] == 0xAAAAAAAA) {\n\t\t\tsprintf(txt,\"AAAAAAAA found in MirrorList! Addr:%p\", &(ptr[i]));\n\t\t\tWWMessageBox().Process (txt);\n\t\t\tfound_5s = 1;\n\t\t}\n\t}\n\n\tfor (i = 0; i < DoList.Count; i++) {\n\t\tif (memcmp(&DoList[i], &MirrorList[i], sizeof(EventClass)) != 0) {\n\t\t\tsprintf(txt,\"Queue Memory Trashed!  Head:%d Tail:%d, Addr:%p or %p\",\n\t\t\t\tDoList.Get_Head(),\n\t\t\t\tDoList.Get_Tail(),\n\t\t\t\tDoList.Get_Array() + i,\n\t\t\t\tMirrorList.Get_Array() + i);\n\t\t\tWWMessageBox().Process (txt);\n\t\t\t//Prog_End();\n\t\t\tEmergency_Exit(0);\n\t\t}\n\t}\n\n\tif (found_5s) {\n\t\t//Prog_End();\n\t\tEmergency_Exit(0);\n\t}\n\n#endif\n}\t// end of Check_Mirror\n\n\n/*************************** end of queue.cpp ******************************/\n"
  },
  {
    "path": "CODE/QUEUE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/QUEUE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : QUEUE.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/08/94                                                     *\n *                                                                                             *\n *                  Last Update : December 9, 1994 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   QueueClass<T,size>::Add -- Add object to queue.                                           *\n *   QueueClass<T,size>::First -- Fetches reference to first object in list.                   *\n *   QueueClass<T,size>::Init -- Initializes queue to empty state.                             *\n *   QueueClass<T,size>::Next -- Throws out the head of the line.                              *\n *   QueueClass<T,size>::operator[] -- Fetches reference to sub object in queue.               *\n *   QueueClass<T,size>::QueueClass -- Default constructor for QueueClass objects.             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef QUEUE_H\n#define QUEUE_H\n\n#include\t\"mission.h\"\n#include\t\"target.h\"\n#include\t\"defines.h\"\n\n#pragma warn -inl\n\n/*\n**\tThis class implements a classic FIFO queue (also known as - standing in line). Objects\n**\tare added to the end (tail) of the line. Objects are removed from the start (first) of\n**\tthe line. A keyboard buffer is a good example of a common computer use of a queue. There\n**\tis no provision for \"taking cuts\" or leaving the line once an object has been added.\n**\n**\tThe implementation uses a circular list of objects. This allows adding and deleting of\n**\telements without any maintenance moves of remaining objects that would otherwise be\n**\tnecessary in a simple array storage method. A side effect of this means that accessing the\n**\tinternal array directly is not allowed. Supporting functions are provided for this purpose.\n**\n**\tWARNING WARNING WARNING WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n**\tThe size parameter MUST be an exact power of two (2, 4, 8, 16, etc.) otherwise the internal\n**\tindexing algorithm will fail.\n*/\ntemplate<class T, int size>\nclass QueueClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis is the count of the number of objects in the queue. If this count is zero,\n\t\t**\tthen the operator[], First(), and Next() functions are undefined. Check this\n\t\t**\tvalue BEFORE calling these functions.\n\t\t*/\n\t\tconst int Count;\n\n\t\t//-------------- Functions --------------------\n\t\tQueueClass(void);\t\t\t\t\t\t// Default constructor.\n\n\t\t/*\n\t\t**\tThe bracket subscript operator functions similarly to the way a normal subscript\n\t\t**\toperator works except that entry [0] matches the first-in-line and entry\n\t\t**\t[Count-1] matches the last-in-line. This is ensured regardless of the actual position\n\t\t**\tof the object in the circular internal list.\n\t\t*/\n\t\tT & operator[](int);\n\n\t\t/*\n\t\t**\tThis function will return a reference to the \"head of the line\" object.\n\t\t*/\n\t\tT & First(void);\n\n\t\t/*\n\t\t**\tThis function clears the list of objects.\n\t\t*/\n\t\tvoid Init(void);\n\n\t\t/*\n\t\t**\tThis function discards the head-of-the-line object and advances all the remaining\n\t\t**\tobjects up by one. Mnemonic: Imagine a broadway audition and the director yells\n\t\t**\t\"NEXT!\"\n\t\t*/\n\t\tint Next(void);\n\n\t\t/*\n\t\t**\tThis will add an object to the tail of the line. If there is no more room to add\n\t\t**\tthe object, then false will be returned.\n\t\t*/\n\t\tint Add(T const &);\n\n\t\tint Get_Head(void);\n\t\tint Get_Tail(void);\n\t\tT * Get_Array(void);\n\n\tprivate:\n\t\tint Head;\t\t\t\t\t\t\t\t// Index of element in list the longest.\n\t\tint Tail;\t\t\t\t\t\t\t\t// Index where next new addition will go.\n\n\t\tT Array[size];\t\t\t\t\t\t\t// Raw array of objects.\n};\n\n\n/***********************************************************************************************\n * QueueClass<T,size>::QueueClass -- Default constructor for QueueClass objects.               *\n *                                                                                             *\n *    This default constructor for QueueClass objects initializes the queue to an empty        *\n *    state.                                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T, int size>\ninline QueueClass<T,size>::QueueClass(void) : Count(0)\n{\n\tInit();\n}\n\n\n/***********************************************************************************************\n * QueueClass<T,size>::Init -- Initializes queue to empty state.                               *\n *                                                                                             *\n *    This function resets the queue to an empty state.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T, int size>\ninline void QueueClass<T,size>::Init(void)\n{\n\t((int &)Count) = 0;\n\tHead = 0;\n\tTail = 0;\n}\n\n\n/***********************************************************************************************\n * QueueClass<T,size>::Add -- Add object to queue.                                             *\n *                                                                                             *\n *    This function is used to add an object to the tail of the line. If the queue cannot      *\n *    accept any more entries, then the object won't be added and false will be returned.      *\n *                                                                                             *\n * INPUT:   object   -- The object that is to be added to the queue.                           *\n *                                                                                             *\n * OUTPUT:  bool; Was the object added successfully?                                           *\n *                                                                                             *\n * WARNINGS:   If the queue is full, then the object won't be added. Be sure to check for this.*\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T, int size>\ninline int QueueClass<T,size>::Add(T const &q)\n{\n\tif (Count < size) {\n\t\tArray[Tail] = q;\n\t\tTail = (Tail + 1) & (size-1);\n\t\t((int &)Count) = Count + 1;\n\t\treturn(true);\n\t}\n\treturn (false);\n}\n\n\n/***********************************************************************************************\n * QueueClass<T,size>::Next -- Throws out the head of the line.                                *\n *                                                                                             *\n *    This routine is used to discard the object at the head of the line. All remaining        *\n *    objects \"move up\" one. No actual movement occurs, merely the index is adjusted, but      *\n *    the affect is that the next oldest object in the queue will now be returned with the     *\n *    next call to the First() function.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the number of object remaining in the queue.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T, int size>\ninline int QueueClass<T,size>::Next(void)\n{\n\tif (Count) {\n\t\tHead = (Head + 1) & (size-1);\n\t\t((int &)Count) = Count - 1;\n\t}\n\treturn (Count);\n}\n\n\n/***********************************************************************************************\n * QueueClass<T,size>::operator[] -- Fetches reference to sub object in queue.                 *\n *                                                                                             *\n *    Use this routine to examine individual objects within the queue. The oldest object in    *\n *    the queue is referenced by an index value of zero. The newest object in the queue is     *\n *    referenced by a value of Count-1. If there are no objects in the queue, then this        *\n *    operator is undefined. Although this operator allows examination of the queue, there is  *\n *    no corresponding ability to insert or delete objects from the middle of the queue.       *\n *                                                                                             *\n * INPUT:   index -- The index into the queue of objects. Valid values range from zero to      *\n *                   Count-1. All other values return an undefined reference!                  *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the object indicated by the index.                     *\n *                                                                                             *\n * WARNINGS:   Check to make sure that Count is not zero before using this operator. Failure   *\n *             to do so will return a reference to an undefined object.                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T, int size>\ninline T & QueueClass<T,size>::operator[](int index)\n{\n\treturn Array[(Head + index) & (size-1)];\n}\n\n\n/***********************************************************************************************\n * QueueClass<T,size>::First -- Fetches reference to first object in list.                     *\n *                                                                                             *\n *    This routine is used to fetch the first object in the list (head of the line). This      *\n *    object is the oldest in the list. Typical use of this function is to get and process     *\n *    the first object so that it may be discarded with the Next() function in order to bring  *\n *    subsequent objects to the first position.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the oldest object in the queue.                        *\n *                                                                                             *\n * WARNINGS:   If there are no objects in the queue, then this function returns an undefined   *\n *             reference. Be sure to check Count against zero before calling this function.    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T, int size>\ninline T & QueueClass<T,size>::First(void)\n{\n\treturn Array[Head];\n}\n\ntemplate<class T, int size>\ninline int QueueClass<T,size>::Get_Head(void)\n{\n\treturn Head;\n}\n\ntemplate<class T, int size>\ninline int QueueClass<T,size>::Get_Tail(void)\n{\n\treturn Tail;\n}\n\ntemplate<class T, int size>\ninline T * QueueClass<T,size>::Get_Array(void)\n{\n\treturn Array;\n}\n\n#endif\n"
  },
  {
    "path": "CODE/RA-HDOS.PJT",
    "content": ";Codewright Project File (do not remove or modify this line)\n[ProjInit]\nProjSetConfigFlags=0x00010140\n\n[Files]\ne:\\c&czero\\code\\2KEYFRAM.CPP\ne:\\c&czero\\code\\AADATA.CPP\ne:\\c&czero\\code\\ABSTRACT.CPP\ne:\\c&czero\\code\\ABSTRACT.H\ne:\\c&czero\\code\\ADATA.CPP\ne:\\c&czero\\code\\AIRCRAFT.CPP\ne:\\c&czero\\code\\AIRCRAFT.H\ne:\\c&czero\\code\\ANIM.CPP\ne:\\c&czero\\code\\ANIM.H\ne:\\c&czero\\code\\AUDIO.CPP\ne:\\c&czero\\code\\B64PIPE.CPP\ne:\\c&czero\\code\\B64PIPE.H\ne:\\c&czero\\code\\B64STRAW.CPP\ne:\\c&czero\\code\\B64STRAW.H\ne:\\c&czero\\code\\BAR.CPP\ne:\\c&czero\\code\\BAR.H\ne:\\c&czero\\code\\BASE.CPP\ne:\\c&czero\\code\\BASE.H\ne:\\c&czero\\code\\BASE64.CPP\ne:\\c&czero\\code\\BASE64.H\ne:\\c&czero\\code\\BBDATA.CPP\ne:\\c&czero\\code\\BDATA.CPP\ne:\\c&czero\\code\\BENCH.CPP\ne:\\c&czero\\code\\BENCH.H\ne:\\c&czero\\code\\BFIOFILE.CPP\ne:\\c&czero\\code\\BFIOFILE.H\ne:\\c&czero\\code\\BLOWFISH.CPP\ne:\\c&czero\\code\\BLOWFISH.H\ne:\\c&czero\\code\\BLOWPIPE.CPP\ne:\\c&czero\\code\\BLOWPIPE.H\ne:\\c&czero\\code\\BLWSTRAW.CPP\ne:\\c&czero\\code\\BLWSTRAW.H\ne:\\c&czero\\code\\BUFF.CPP\ne:\\c&czero\\code\\BUFF.H\ne:\\c&czero\\code\\BUFFERX.H\ne:\\c&czero\\code\\BUILDING.CPP\ne:\\c&czero\\code\\BUILDING.H\ne:\\c&czero\\code\\BULLET.CPP\ne:\\c&czero\\code\\BULLET.H\ne:\\c&czero\\code\\CARGO.CPP\ne:\\c&czero\\code\\CARGO.H\ne:\\c&czero\\code\\CARRY.CPP\ne:\\c&czero\\code\\CARRY.H\ne:\\c&czero\\code\\CCDDE.CPP\ne:\\c&czero\\code\\CCDDE.H\ne:\\c&czero\\code\\CCFILE.CPP\ne:\\c&czero\\code\\CCFILE.H\ne:\\c&czero\\code\\CCINI.CPP\ne:\\c&czero\\code\\CCINI.H\ne:\\c&czero\\code\\CCPTR.CPP\ne:\\c&czero\\code\\CCPTR.H\ne:\\c&czero\\code\\CDATA.CPP\ne:\\c&czero\\code\\CDFILE.CPP\ne:\\c&czero\\code\\CDFILE.H\ne:\\c&czero\\code\\CELL.CPP\ne:\\c&czero\\code\\CELL.H\ne:\\c&czero\\code\\CHECKBOX.CPP\ne:\\c&czero\\code\\CHECKBOX.H\ne:\\c&czero\\code\\CHEKLIST.CPP\ne:\\c&czero\\code\\CHEKLIST.H\ne:\\c&czero\\code\\COLRLIST.CPP\ne:\\c&czero\\code\\COLRLIST.H\ne:\\c&czero\\code\\COMBAT.CPP\ne:\\c&czero\\code\\COMBUF.CPP\ne:\\c&czero\\code\\COMBUF.H\ne:\\c&czero\\code\\COMPAT.H\ne:\\c&czero\\code\\CONNECT.CPP\ne:\\c&czero\\code\\CONNECT.H\ne:\\c&czero\\code\\CONNMGR.H\ne:\\c&czero\\code\\CONQUER.CPP\ne:\\c&czero\\code\\CONQUER.H\ne:\\c&czero\\code\\CONST.CPP\ne:\\c&czero\\code\\CONTROL.CPP\ne:\\c&czero\\code\\CONTROL.H\ne:\\c&czero\\code\\COORD.CPP\ne:\\c&czero\\code\\CRATE.CPP\ne:\\c&czero\\code\\CRATE.H\ne:\\c&czero\\code\\CRC.CPP\ne:\\c&czero\\code\\CRC.H\ne:\\c&czero\\code\\CRCPIPE.CPP\ne:\\c&czero\\code\\CRCPIPE.H\ne:\\c&czero\\code\\CRCSTRAW.CPP\ne:\\c&czero\\code\\CRCSTRAW.H\ne:\\c&czero\\code\\CREDITS.CPP\ne:\\c&czero\\code\\CREDITS.H\ne:\\c&czero\\code\\CREW.CPP\ne:\\c&czero\\code\\CREW.H\ne:\\c&czero\\code\\DDE.CPP\ne:\\c&czero\\code\\DDE.H\ne:\\c&czero\\code\\DEBUG.CPP\ne:\\c&czero\\code\\DEBUG.H\ne:\\c&czero\\code\\DEFINES.H\ne:\\c&czero\\code\\DESCDLG.CPP\ne:\\c&czero\\code\\DESCDLG.H\ne:\\c&czero\\code\\DIAL8.CPP\ne:\\c&czero\\code\\DIAL8.H\ne:\\c&czero\\code\\DIALOG.CPP\ne:\\c&czero\\code\\DISPLAY.CPP\ne:\\c&czero\\code\\DISPLAY.H\ne:\\c&czero\\code\\DOOR.CPP\ne:\\c&czero\\code\\DOOR.H\ne:\\c&czero\\code\\DRIVE.CPP\ne:\\c&czero\\code\\DRIVE.H\ne:\\c&czero\\code\\DROP.CPP\ne:\\c&czero\\code\\DROP.H\ne:\\c&czero\\code\\EDIT.CPP\ne:\\c&czero\\code\\EDIT.H\ne:\\c&czero\\code\\EGOS.CPP\ne:\\c&czero\\code\\EGOS.H\ne:\\c&czero\\code\\ENDING.CPP\ne:\\c&czero\\code\\ENDING.H\ne:\\c&czero\\code\\EVENT.CPP\ne:\\c&czero\\code\\EVENT.H\ne:\\c&czero\\code\\EXPAND.CPP\ne:\\c&czero\\code\\EXTERNS.H\ne:\\c&czero\\code\\FACE.CPP\ne:\\c&czero\\code\\FACE.H\ne:\\c&czero\\code\\FACING.CPP\ne:\\c&czero\\code\\FACING.H\ne:\\c&czero\\code\\FACTORY.CPP\ne:\\c&czero\\code\\FACTORY.H\ne:\\c&czero\\code\\FAKESOCK.H\ne:\\c&czero\\code\\FIELD.CPP\ne:\\c&czero\\code\\FIELD.H\ne:\\c&czero\\code\\FILEPCX.H\ne:\\c&czero\\code\\FINDPATH.CPP\ne:\\c&czero\\code\\FIXED.CPP\ne:\\c&czero\\code\\FIXED.H\ne:\\c&czero\\code\\FLASHER.CPP\ne:\\c&czero\\code\\FLASHER.H\ne:\\c&czero\\code\\FLY.CPP\ne:\\c&czero\\code\\FLY.H\ne:\\c&czero\\code\\FOOT.CPP\ne:\\c&czero\\code\\FOOT.H\ne:\\c&czero\\code\\FTIMER.H\ne:\\c&czero\\code\\FUNCTION.H\ne:\\c&czero\\code\\FUSE.CPP\ne:\\c&czero\\code\\FUSE.H\ne:\\c&czero\\code\\GADGET.CPP\ne:\\c&czero\\code\\GADGET.H\ne:\\c&czero\\code\\GAMEDLG.CPP\ne:\\c&czero\\code\\GAMEDLG.H\ne:\\c&czero\\code\\GAUGE.CPP\ne:\\c&czero\\code\\GAUGE.H\ne:\\c&czero\\code\\GETCPU.CPP\ne:\\c&czero\\code\\GLOBALS.CPP\ne:\\c&czero\\code\\GOPTIONS.CPP\ne:\\c&czero\\code\\GOPTIONS.H\ne:\\c&czero\\code\\GSCREEN.CPP\ne:\\c&czero\\code\\GSCREEN.H\ne:\\c&czero\\code\\HDATA.CPP\ne:\\c&czero\\code\\HEAP.CPP\ne:\\c&czero\\code\\HEAP.H\ne:\\c&czero\\code\\HELP.CPP\ne:\\c&czero\\code\\HELP.H\ne:\\c&czero\\code\\HOUSE.CPP\ne:\\c&czero\\code\\HOUSE.H\ne:\\c&czero\\code\\HSV.CPP\ne:\\c&czero\\code\\HSV.H\ne:\\c&czero\\code\\IDATA.CPP\ne:\\c&czero\\code\\INFANTRY.CPP\ne:\\c&czero\\code\\INFANTRY.H\ne:\\c&czero\\code\\INI.CPP\ne:\\c&czero\\code\\INI.H\ne:\\c&czero\\code\\INIT.CPP\ne:\\c&czero\\code\\INLINE.H\ne:\\c&czero\\code\\INT.CPP\ne:\\c&czero\\code\\INT.H\ne:\\c&czero\\code\\INTERNET.CPP\ne:\\c&czero\\code\\INTERPAL.CPP\ne:\\c&czero\\code\\INTRO.CPP\ne:\\c&czero\\code\\INTRO.H\ne:\\c&czero\\code\\IOMAP.CPP\ne:\\c&czero\\code\\IOOBJ.CPP\ne:\\c&czero\\code\\IPX.CPP\ne:\\c&czero\\code\\IPX.H\ne:\\c&czero\\code\\IPX95.CPP\ne:\\c&czero\\code\\IPX95.H\ne:\\c&czero\\code\\IPXADDR.CPP\ne:\\c&czero\\code\\IPXADDR.H\ne:\\c&czero\\code\\IPXCONN.CPP\ne:\\c&czero\\code\\IPXCONN.H\ne:\\c&czero\\code\\IPXGCONN.CPP\ne:\\c&czero\\code\\IPXGCONN.H\ne:\\c&czero\\code\\IPXMGR.CPP\ne:\\c&czero\\code\\IPXMGR.H\ne:\\c&czero\\code\\JSHELL.CPP\ne:\\c&czero\\code\\JSHELL.H\ne:\\c&czero\\code\\KEYFRAME.CPP\ne:\\c&czero\\code\\LANGUAGE.H\ne:\\c&czero\\code\\LAYER.CPP\ne:\\c&czero\\code\\LAYER.H\ne:\\c&czero\\code\\LCW.CPP\ne:\\c&czero\\code\\LCW.H\ne:\\c&czero\\code\\LCWPIPE.CPP\ne:\\c&czero\\code\\LCWPIPE.H\ne:\\c&czero\\code\\LCWSTRAW.CPP\ne:\\c&czero\\code\\LCWSTRAW.H\ne:\\c&czero\\code\\LCWUNCMP.CPP\ne:\\c&czero\\code\\LINK.CPP\ne:\\c&czero\\code\\LINK.H\ne:\\c&czero\\code\\LINT.H\ne:\\c&czero\\code\\LIST.CPP\ne:\\c&czero\\code\\LIST.H\ne:\\c&czero\\code\\LISTNODE.H\ne:\\c&czero\\code\\LOADDLG.CPP\ne:\\c&czero\\code\\LOADDLG.H\ne:\\c&czero\\code\\LOGIC.CPP\ne:\\c&czero\\code\\LOGIC.H\ne:\\c&czero\\code\\LZO.H\ne:\\c&czero\\code\\LZO_CONF.H\ne:\\c&czero\\code\\LZO1X.H\ne:\\c&czero\\code\\LZO1X_C.CPP\ne:\\c&czero\\code\\LZO1X_D.CPP\ne:\\c&czero\\code\\LZOCONF.H\ne:\\c&czero\\code\\LZOPIPE.CPP\ne:\\c&czero\\code\\LZOPIPE.H\ne:\\c&czero\\code\\LZOSTRAW.CPP\ne:\\c&czero\\code\\LZOSTRAW.H\ne:\\c&czero\\code\\LZW.CPP\ne:\\c&czero\\code\\LZW.H\ne:\\c&czero\\code\\LZWOTRAW.CPP\ne:\\c&czero\\code\\LZWPIPE.CPP\ne:\\c&czero\\code\\LZWPIPE.H\ne:\\c&czero\\code\\LZWSTRAW.CPP\ne:\\c&czero\\code\\LZWSTRAW.H\ne:\\c&czero\\code\\MAP.CPP\ne:\\c&czero\\code\\MAP.H\ne:\\c&czero\\code\\MAPEDDLG.CPP\ne:\\c&czero\\code\\MAPEDIT.CPP\ne:\\c&czero\\code\\MAPEDIT.H\ne:\\c&czero\\code\\MAPEDPLC.CPP\ne:\\c&czero\\code\\MAPEDSEL.CPP\ne:\\c&czero\\code\\MAPEDTM.CPP\ne:\\c&czero\\code\\MAPSEL.CPP\ne:\\c&czero\\code\\MENUS.CPP\ne:\\c&czero\\code\\MESSAGE.H\ne:\\c&czero\\code\\MISSION.CPP\ne:\\c&czero\\code\\MISSION.H\ne:\\c&czero\\code\\MIXFILE.CPP\ne:\\c&czero\\code\\MIXFILE.H\ne:\\c&czero\\code\\MONOC.CPP\ne:\\c&czero\\code\\MONOC.H\ne:\\c&czero\\code\\MOUSE.CPP\ne:\\c&czero\\code\\MOUSE.H\ne:\\c&czero\\code\\MP.CPP\ne:\\c&czero\\code\\MP.H\ne:\\c&czero\\code\\MPLAYER.CPP\ne:\\c&czero\\code\\MPU.CPP\ne:\\c&czero\\code\\MPU.H\ne:\\c&czero\\code\\MSGBOX.CPP\ne:\\c&czero\\code\\MSGBOX.H\ne:\\c&czero\\code\\MSGLIST.CPP\ne:\\c&czero\\code\\MSGLIST.H\ne:\\c&czero\\code\\NETDLG.CPP\ne:\\c&czero\\code\\NULLCONN.CPP\ne:\\c&czero\\code\\NULLCONN.H\ne:\\c&czero\\code\\NULLDLG.CPP\ne:\\c&czero\\code\\NULLMGR.CPP\ne:\\c&czero\\code\\NULLMGR.H\ne:\\c&czero\\code\\OBJECT.CPP\ne:\\c&czero\\code\\OBJECT.H\ne:\\c&czero\\code\\ODATA.CPP\ne:\\c&czero\\code\\OPTIONS.CPP\ne:\\c&czero\\code\\OPTIONS.H\ne:\\c&czero\\code\\OVERLAY.CPP\ne:\\c&czero\\code\\OVERLAY.H\ne:\\c&czero\\code\\PACKET.CPP\ne:\\c&czero\\code\\PACKET.H\ne:\\c&czero\\code\\PALETTE.CPP\ne:\\c&czero\\code\\PALETTE.H\ne:\\c&czero\\code\\PCX.H\ne:\\c&czero\\code\\PHONE.H\ne:\\c&czero\\code\\PIPE.CPP\ne:\\c&czero\\code\\PIPE.H\ne:\\c&czero\\code\\PK.CPP\ne:\\c&czero\\code\\PK.H\ne:\\c&czero\\code\\PKPIPE.CPP\ne:\\c&czero\\code\\PKPIPE.H\ne:\\c&czero\\code\\PKSTRAW.CPP\ne:\\c&czero\\code\\PKSTRAW.H\ne:\\c&czero\\code\\POWER.CPP\ne:\\c&czero\\code\\POWER.H\ne:\\c&czero\\code\\PROFILE.CPP\ne:\\c&czero\\code\\QUEUE.CPP\ne:\\c&czero\\code\\QUEUE.H\ne:\\c&czero\\code\\RADAR.CPP\ne:\\c&czero\\code\\RADAR.H\ne:\\c&czero\\code\\RADIO.CPP\ne:\\c&czero\\code\\RADIO.H\ne:\\c&czero\\code\\RAMFILE.CPP\ne:\\c&czero\\code\\RAMFILE.H\ne:\\c&czero\\code\\RANDOM.CPP\ne:\\c&czero\\code\\RANDOM.H\ne:\\c&czero\\code\\RAWFILE.CPP\ne:\\c&czero\\code\\RAWFILE.H\ne:\\c&czero\\code\\READLINE.CPP\ne:\\c&czero\\code\\READLINE.H\ne:\\c&czero\\code\\RECT.CPP\ne:\\c&czero\\code\\RECT.H\ne:\\c&czero\\code\\REGION.H\ne:\\c&czero\\code\\REINF.CPP\ne:\\c&czero\\code\\RGB.CPP\ne:\\c&czero\\code\\RGB.H\ne:\\c&czero\\code\\RNDSTRAW.CPP\ne:\\c&czero\\code\\RNDSTRAW.H\ne:\\c&czero\\code\\RNG.H\ne:\\c&czero\\code\\ROTBMP.CPP\ne:\\c&czero\\code\\ROTBMP.H\ne:\\c&czero\\code\\RULES.CPP\ne:\\c&czero\\code\\RULES.H\ne:\\c&czero\\code\\SAVEDLG.H\ne:\\c&czero\\code\\SAVELOAD.CPP\ne:\\c&czero\\code\\SCENARIO.CPP\ne:\\c&czero\\code\\SCENARIO.H\ne:\\c&czero\\code\\SCORE.CPP\ne:\\c&czero\\code\\SCORE.H\ne:\\c&czero\\code\\SCREEN.H\ne:\\c&czero\\code\\SCROLL.CPP\ne:\\c&czero\\code\\SCROLL.H\ne:\\c&czero\\code\\SDATA.CPP\ne:\\c&czero\\code\\SENDFILE.CPP\ne:\\c&czero\\code\\SESSION.CPP\ne:\\c&czero\\code\\SESSION.H\ne:\\c&czero\\code\\SHA.CPP\ne:\\c&czero\\code\\SHA.H\ne:\\c&czero\\code\\SHAPEBTN.CPP\ne:\\c&czero\\code\\SHAPEBTN.H\ne:\\c&czero\\code\\SHAPIPE.CPP\ne:\\c&czero\\code\\SHAPIPE.H\ne:\\c&czero\\code\\SHASTRAW.CPP\ne:\\c&czero\\code\\SHASTRAW.H\ne:\\c&czero\\code\\SIDEBAR.CPP\ne:\\c&czero\\code\\SIDEBAR.H\ne:\\c&czero\\code\\SLIDER.CPP\ne:\\c&czero\\code\\SLIDER.H\ne:\\c&czero\\code\\SMUDGE.CPP\ne:\\c&czero\\code\\SMUDGE.H\ne:\\c&czero\\code\\SOUNDDLG.CPP\ne:\\c&czero\\code\\SOUNDDLG.H\ne:\\c&czero\\code\\SPECIAL.CPP\ne:\\c&czero\\code\\SPECIAL.H\ne:\\c&czero\\code\\SPRITE.CPP\ne:\\c&czero\\code\\STAGE.H\ne:\\c&czero\\code\\STARTUP.CPP\ne:\\c&czero\\code\\STATBTN.CPP\ne:\\c&czero\\code\\STATBTN.H\ne:\\c&czero\\code\\STATS.CPP\ne:\\c&czero\\code\\STRAW.CPP\ne:\\c&czero\\code\\STRAW.H\ne:\\c&czero\\code\\STYLE.H\ne:\\c&czero\\code\\SUPER.CPP\ne:\\c&czero\\code\\SUPER.H\ne:\\c&czero\\code\\TAB.CPP\ne:\\c&czero\\code\\TAB.H\ne:\\c&czero\\code\\TACTION.CPP\ne:\\c&czero\\code\\TACTION.H\ne:\\c&czero\\code\\TARCOM.CPP\ne:\\c&czero\\code\\TARGET.CPP\ne:\\c&czero\\code\\TARGET.H\ne:\\c&czero\\code\\TCPIP.CPP\ne:\\c&czero\\code\\TCPIP.H\ne:\\c&czero\\code\\TDATA.CPP\ne:\\c&czero\\code\\TEAM.CPP\ne:\\c&czero\\code\\TEAM.H\ne:\\c&czero\\code\\TEAMTYPE.CPP\ne:\\c&czero\\code\\TEAMTYPE.H\ne:\\c&czero\\code\\TECHNO.CPP\ne:\\c&czero\\code\\TECHNO.H\ne:\\c&czero\\code\\TEMPLATE.CPP\ne:\\c&czero\\code\\TEMPLATE.H\ne:\\c&czero\\code\\TERRAIN.CPP\ne:\\c&czero\\code\\TERRAIN.H\ne:\\c&czero\\code\\TEVENT.CPP\ne:\\c&czero\\code\\TEVENT.H\ne:\\c&czero\\code\\TEXTBTN.CPP\ne:\\c&czero\\code\\TEXTBTN.H\ne:\\c&czero\\code\\THEME.CPP\ne:\\c&czero\\code\\THEME.H\ne:\\c&czero\\code\\TOGGLE.CPP\ne:\\c&czero\\code\\TOGGLE.H\ne:\\c&czero\\code\\TRACKER.CPP\ne:\\c&czero\\code\\TRIGGER.CPP\ne:\\c&czero\\code\\TRIGGER.H\ne:\\c&czero\\code\\TRIGTYPE.CPP\ne:\\c&czero\\code\\TRIGTYPE.H\ne:\\c&czero\\code\\TXTLABEL.CPP\ne:\\c&czero\\code\\TXTLABEL.H\ne:\\c&czero\\code\\TYPE.H\ne:\\c&czero\\code\\UDATA.CPP\ne:\\c&czero\\code\\UNIT.CPP\ne:\\c&czero\\code\\UNIT.H\ne:\\c&czero\\code\\UTRACKER.CPP\ne:\\c&czero\\code\\UTRACKER.H\ne:\\c&czero\\code\\VDATA.CPP\ne:\\c&czero\\code\\VECTOR.CPP\ne:\\c&czero\\code\\VECTOR.H\ne:\\c&czero\\code\\VERSION.CPP\ne:\\c&czero\\code\\VERSION.H\ne:\\c&czero\\code\\VESSEL.CPP\ne:\\c&czero\\code\\VESSEL.H\ne:\\c&czero\\code\\VISUDLG.CPP\ne:\\c&czero\\code\\VISUDLG.H\ne:\\c&czero\\code\\VORTEX.CPP\ne:\\c&czero\\code\\VORTEX.H\ne:\\c&czero\\code\\WARHEAD.CPP\ne:\\c&czero\\code\\WARHEAD.H\ne:\\c&czero\\code\\WATCOM.H\ne:\\c&czero\\code\\WEAPON.CPP\ne:\\c&czero\\code\\WEAPON.H\ne:\\c&czero\\code\\WINSTUB.CPP\ne:\\c&czero\\code\\WRITEPCX.CPP\ne:\\c&czero\\code\\WWFILE.H\ne:\\c&czero\\code\\XPIPE.CPP\ne:\\c&czero\\code\\XPIPE.H\ne:\\c&czero\\code\\XSTRAW.CPP\ne:\\c&czero\\code\\XSTRAW.H\n\n\n[State]\nSysSetCwd='E:\\C&CZERO\\CODE'\nSrchSetFlags=0x000320aa\nFileSortMode=0x0\nStateWindowFrame=37,16,923,511,0x62c9f5fa\n_StateWindow=44,44,792,452,0x00100018,'E:\\C&CZERO\\CODE\\STATBTN.CPP',240,15,244,32,32,0,32,32,32,32,8,4294967295,4294967295,1,10,'',12,255,48,0,7,243,252,253,247,249,247,107,1,400,0,246,252,248,244,247,15,15,15,15,0,0\n_StateBuffer='E:\\C&CZERO\\CODE\\STATBTN.CPP',0x0400048e,107,1,25,'4 7','',0x0,''\n_StateHistory=FILELIST,'E:\\C&CZERO\\CODE\\STATBTN.CPP','E:\\C&CZERO\\CODE\\MAKEFILE'\n_StateHistory=EDITFILE,'E:\\C&CZERO\\CODE\\statbtn.cpp','makefile'\n\n[Editor]\nClipboardSetTermStr='\\r\\n',0\nClipboardEnableTermStr=1\nClipboardSetSepStr='\\r\\n',0\nClipboardEnableSepStr=1\nScrapSetCount=1\nVCSProject=''\nVCSProjectPath=''\nVCSProjectLocalPath=''\n_RestoreSysFlags=0x62c9f5fa, 0xfffffffc\n\n[Compiler]\nTagSetCmd='${HOME}${WTAGS} -oc -d -t${TAGFILE}.tag -p${TAGFILE}.ptg',0x8000060\nBrowseSetFile='E:\\C&CZERO\\CODE\\Ra-hdos.ptg'\nTagSetFile='E:\\C&CZERO\\CODE\\Ra-hdos.tag'\nCompilerAddCmd='Microsoft Assembler','ftee masm -w2 -zi %r%e;',1073741824,'',0,'',16,'',16,'',0,'',0,'_MicrosoftErrorInfo','','','','%v%p'\nCompilerAddResponse='Microsoft Assembler',\nCompilerAddCmd='Borland C++','ftee bcc -S %r.c',1073741824,'',0,'ftee make %r.obj',16,'ftee make %r.obj',16,'',0,'',0,'_BorlandCppErrorInfo','','','','%v%p'\nCompilerAddResponse='Borland C++',\nCompilerAddCmd='Borland Turbo Assembler','ftee make %r.obj',1073741824,'',0,'ftee make %r.obj',16,'',16,'',0,'',0,'_TasmErrorInfo','','','','%v%p'\nCompilerAddResponse='Borland Turbo Assembler',\nCompilerAddCmd='$_cw_proj_hash_$','',1073741825,'',1,'watcom\\binw\\wmake %r.obj',449,'wmake WIN32=1',449,'ftee joemake',209,'g.bat cheater -xqm',224,'_MSLinkErrorInfo','_MicrosoftErrorInfo','_NMakeErrorInfo','proj.err','e:\\c&czero\\code'\nCompilerAddResponse='$_cw_proj_hash_$',\nCompilerAddCmd='Default Project','',1073741824,'',0,'ftee make',16,'ftee make',16,'',0,'',0,'_ErrorInfoDefault','','','proj.err','%v%p'\nCompilerAddResponse='Default Project',\nCompilerAddCmd='Microsoft C','ftee cl -c -AL -Gsw -Ow -Zpe  %r%e',1073741824,'',0,'',16,'',16,'',0,'',0,'_MicrosoftErrorInfo','','','','%v%p'\nCompilerAddResponse='Microsoft C',\nCompilerAddCmd='Script','ftee make %r.inf',1073741824,'',0,'ftee make',16,'ftee make',16,'',0,'',0,'_BorlandCppErrorInfo','','','',''\nCompilerAddResponse='Script',\nCompilerAddCmd='Zortech C++','ftee ztc -a -b -c -g -ml -W %r%e',1073741824,'',0,'',16,'',16,'',0,'',0,'_ZortechCppErrorInfo','','','','%v%p'\nCompilerAddResponse='Zortech C++',\nCompilerAddCmd='Microsoft C(NT-i386)','${FTEE} cl -DSTRICT -c -W3 -G3 -D_X86_=1 -DWIN32 %r%e',1073741936,'${FTEE} cl -DSTRICT -c -W3 -G3 -D_X86_=1 -DWIN32 %r%e',112,'',144,'',144,'',0,'',0,'_MicrosoftErrorInfo','','','',''\nCompilerAddResponse='Microsoft C(NT-i386)',\nCompilerAssign='Borland C++','.scr'\nCompilerNewExt=.bas\nCompilerAssign='Borland C++','.int'\nCompilerAssign='Borland C++','.c'\nCompilerNewExt=.prg\nCompilerAssign='Microsoft C','.h'\nCompilerAssign='Borland C++','.cpp'\nCompilerAssign='Default Project','.*'\nCompilerAssign='Microsoft C(NT-i386)','.cxx'\nCompilerAssign='Borland Turbo Assembler','.asm'\nCompilerAssign='Microsoft C(NT-i386)','.hpp'\n"
  },
  {
    "path": "CODE/RA-HOME.PJT",
    "content": ";Codewright Project File (do not remove or modify this line)\n[ProjInit]\nProjSetConfigFlags=0x00010140\n\n[Files]\ne:\\c&czero\\code\\2KEYFRAM.CPP\ne:\\c&czero\\code\\AADATA.CPP\ne:\\c&czero\\code\\ABSTRACT.CPP\ne:\\c&czero\\code\\ABSTRACT.H\ne:\\c&czero\\code\\ADATA.CPP\ne:\\c&czero\\code\\AIRCRAFT.CPP\ne:\\c&czero\\code\\AIRCRAFT.H\ne:\\c&czero\\code\\ANIM.CPP\ne:\\c&czero\\code\\ANIM.H\ne:\\c&czero\\code\\AUDIO.CPP\ne:\\c&czero\\code\\B64PIPE.CPP\ne:\\c&czero\\code\\B64PIPE.H\ne:\\c&czero\\code\\B64STRAW.CPP\ne:\\c&czero\\code\\B64STRAW.H\ne:\\c&czero\\code\\BAR.CPP\ne:\\c&czero\\code\\BAR.H\ne:\\c&czero\\code\\BASE.CPP\ne:\\c&czero\\code\\BASE.H\ne:\\c&czero\\code\\BASE64.CPP\ne:\\c&czero\\code\\BASE64.H\ne:\\c&czero\\code\\BBDATA.CPP\ne:\\c&czero\\code\\BDATA.CPP\ne:\\c&czero\\code\\BENCH.CPP\ne:\\c&czero\\code\\BENCH.H\ne:\\c&czero\\code\\BFIOFILE.CPP\ne:\\c&czero\\code\\BFIOFILE.H\ne:\\c&czero\\code\\BLOWFISH.CPP\ne:\\c&czero\\code\\BLOWFISH.H\ne:\\c&czero\\code\\BLOWPIPE.CPP\ne:\\c&czero\\code\\BLOWPIPE.H\ne:\\c&czero\\code\\BLWSTRAW.CPP\ne:\\c&czero\\code\\BLWSTRAW.H\ne:\\c&czero\\code\\BUFF.CPP\ne:\\c&czero\\code\\BUFF.H\ne:\\c&czero\\code\\BUFFERX.H\ne:\\c&czero\\code\\BUILDING.CPP\ne:\\c&czero\\code\\BUILDING.H\ne:\\c&czero\\code\\BULLET.CPP\ne:\\c&czero\\code\\BULLET.H\ne:\\c&czero\\code\\CARGO.CPP\ne:\\c&czero\\code\\CARGO.H\ne:\\c&czero\\code\\CARRY.CPP\ne:\\c&czero\\code\\CARRY.H\ne:\\c&czero\\code\\CCDDE.CPP\ne:\\c&czero\\code\\CCDDE.H\ne:\\c&czero\\code\\CCFILE.CPP\ne:\\c&czero\\code\\CCFILE.H\ne:\\c&czero\\code\\CCINI.CPP\ne:\\c&czero\\code\\CCINI.H\ne:\\c&czero\\code\\CCPTR.CPP\ne:\\c&czero\\code\\CCPTR.H\ne:\\c&czero\\code\\CDATA.CPP\ne:\\c&czero\\code\\CDFILE.CPP\ne:\\c&czero\\code\\CDFILE.H\ne:\\c&czero\\code\\CELL.CPP\ne:\\c&czero\\code\\CELL.H\ne:\\c&czero\\code\\CHECKBOX.CPP\ne:\\c&czero\\code\\CHECKBOX.H\ne:\\c&czero\\code\\CHEKLIST.CPP\ne:\\c&czero\\code\\CHEKLIST.H\ne:\\c&czero\\code\\COLRLIST.CPP\ne:\\c&czero\\code\\COLRLIST.H\ne:\\c&czero\\code\\COMBAT.CPP\ne:\\c&czero\\code\\COMBUF.CPP\ne:\\c&czero\\code\\COMBUF.H\ne:\\c&czero\\code\\COMPAT.H\ne:\\c&czero\\code\\CONNECT.CPP\ne:\\c&czero\\code\\CONNECT.H\ne:\\c&czero\\code\\CONNMGR.H\ne:\\c&czero\\code\\CONQUER.CPP\ne:\\c&czero\\code\\CONQUER.H\ne:\\c&czero\\code\\CONST.CPP\ne:\\c&czero\\code\\CONTROL.CPP\ne:\\c&czero\\code\\CONTROL.H\ne:\\c&czero\\code\\COORD.CPP\ne:\\c&czero\\code\\CRATE.CPP\ne:\\c&czero\\code\\CRATE.H\ne:\\c&czero\\code\\CRC.CPP\ne:\\c&czero\\code\\CRC.H\ne:\\c&czero\\code\\CRCPIPE.CPP\ne:\\c&czero\\code\\CRCPIPE.H\ne:\\c&czero\\code\\CRCSTRAW.CPP\ne:\\c&czero\\code\\CRCSTRAW.H\ne:\\c&czero\\code\\CREDITS.CPP\ne:\\c&czero\\code\\CREDITS.H\ne:\\c&czero\\code\\CREW.CPP\ne:\\c&czero\\code\\CREW.H\ne:\\c&czero\\code\\DDE.CPP\ne:\\c&czero\\code\\DDE.H\ne:\\c&czero\\code\\DEBUG.CPP\ne:\\c&czero\\code\\DEBUG.H\ne:\\c&czero\\code\\DEFINES.H\ne:\\c&czero\\code\\DESCDLG.CPP\ne:\\c&czero\\code\\DESCDLG.H\ne:\\c&czero\\code\\DIAL8.CPP\ne:\\c&czero\\code\\DIAL8.H\ne:\\c&czero\\code\\DIALOG.CPP\ne:\\c&czero\\code\\DISPLAY.CPP\ne:\\c&czero\\code\\DISPLAY.H\ne:\\c&czero\\code\\DOOR.CPP\ne:\\c&czero\\code\\DOOR.H\ne:\\c&czero\\code\\DRIVE.CPP\ne:\\c&czero\\code\\DRIVE.H\ne:\\c&czero\\code\\DROP.CPP\ne:\\c&czero\\code\\DROP.H\ne:\\c&czero\\code\\EDIT.CPP\ne:\\c&czero\\code\\EDIT.H\ne:\\c&czero\\code\\EGOS.CPP\ne:\\c&czero\\code\\EGOS.H\ne:\\c&czero\\code\\ENDING.CPP\ne:\\c&czero\\code\\ENDING.H\ne:\\c&czero\\code\\EVENT.CPP\ne:\\c&czero\\code\\EVENT.H\ne:\\c&czero\\code\\EXPAND.CPP\ne:\\c&czero\\code\\EXTERNS.H\ne:\\c&czero\\code\\FACE.CPP\ne:\\c&czero\\code\\FACE.H\ne:\\c&czero\\code\\FACING.CPP\ne:\\c&czero\\code\\FACING.H\ne:\\c&czero\\code\\FACTORY.CPP\ne:\\c&czero\\code\\FACTORY.H\ne:\\c&czero\\code\\FAKESOCK.H\ne:\\c&czero\\code\\FIELD.CPP\ne:\\c&czero\\code\\FIELD.H\ne:\\c&czero\\code\\FILEPCX.H\ne:\\c&czero\\code\\FINDPATH.CPP\ne:\\c&czero\\code\\FIXED.CPP\ne:\\c&czero\\code\\FIXED.H\ne:\\c&czero\\code\\FLASHER.CPP\ne:\\c&czero\\code\\FLASHER.H\ne:\\c&czero\\code\\FLY.CPP\ne:\\c&czero\\code\\FLY.H\ne:\\c&czero\\code\\FOOT.CPP\ne:\\c&czero\\code\\FOOT.H\ne:\\c&czero\\code\\FTIMER.H\ne:\\c&czero\\code\\FUNCTION.H\ne:\\c&czero\\code\\FUSE.CPP\ne:\\c&czero\\code\\FUSE.H\ne:\\c&czero\\code\\GADGET.CPP\ne:\\c&czero\\code\\GADGET.H\ne:\\c&czero\\code\\GAMEDLG.CPP\ne:\\c&czero\\code\\GAMEDLG.H\ne:\\c&czero\\code\\GAUGE.CPP\ne:\\c&czero\\code\\GAUGE.H\ne:\\c&czero\\code\\GETCPU.CPP\ne:\\c&czero\\code\\GLOBALS.CPP\ne:\\c&czero\\code\\GOPTIONS.CPP\ne:\\c&czero\\code\\GOPTIONS.H\ne:\\c&czero\\code\\GSCREEN.CPP\ne:\\c&czero\\code\\GSCREEN.H\ne:\\c&czero\\code\\HDATA.CPP\ne:\\c&czero\\code\\HEAP.CPP\ne:\\c&czero\\code\\HEAP.H\ne:\\c&czero\\code\\HELP.CPP\ne:\\c&czero\\code\\HELP.H\ne:\\c&czero\\code\\HOUSE.CPP\ne:\\c&czero\\code\\HOUSE.H\ne:\\c&czero\\code\\HSV.CPP\ne:\\c&czero\\code\\HSV.H\ne:\\c&czero\\code\\IDATA.CPP\ne:\\c&czero\\code\\INFANTRY.CPP\ne:\\c&czero\\code\\INFANTRY.H\ne:\\c&czero\\code\\INI.CPP\ne:\\c&czero\\code\\INI.H\ne:\\c&czero\\code\\INIT.CPP\ne:\\c&czero\\code\\INLINE.H\ne:\\c&czero\\code\\INT.CPP\ne:\\c&czero\\code\\INT.H\ne:\\c&czero\\code\\INTERNET.CPP\ne:\\c&czero\\code\\INTERPAL.CPP\ne:\\c&czero\\code\\INTRO.CPP\ne:\\c&czero\\code\\INTRO.H\ne:\\c&czero\\code\\IOMAP.CPP\ne:\\c&czero\\code\\IOOBJ.CPP\ne:\\c&czero\\code\\IPX.CPP\ne:\\c&czero\\code\\IPX.H\ne:\\c&czero\\code\\IPX95.CPP\ne:\\c&czero\\code\\IPX95.H\ne:\\c&czero\\code\\IPXADDR.CPP\ne:\\c&czero\\code\\IPXADDR.H\ne:\\c&czero\\code\\IPXCONN.CPP\ne:\\c&czero\\code\\IPXCONN.H\ne:\\c&czero\\code\\IPXGCONN.CPP\ne:\\c&czero\\code\\IPXGCONN.H\ne:\\c&czero\\code\\IPXMGR.CPP\ne:\\c&czero\\code\\IPXMGR.H\ne:\\c&czero\\code\\JSHELL.CPP\ne:\\c&czero\\code\\JSHELL.H\ne:\\c&czero\\code\\KEYFRAME.CPP\ne:\\c&czero\\code\\LANGUAGE.H\ne:\\c&czero\\code\\LAYER.CPP\ne:\\c&czero\\code\\LAYER.H\ne:\\c&czero\\code\\LCW.CPP\ne:\\c&czero\\code\\LCW.H\ne:\\c&czero\\code\\LCWPIPE.CPP\ne:\\c&czero\\code\\LCWPIPE.H\ne:\\c&czero\\code\\LCWSTRAW.CPP\ne:\\c&czero\\code\\LCWSTRAW.H\ne:\\c&czero\\code\\LCWUNCMP.CPP\ne:\\c&czero\\code\\LINK.CPP\ne:\\c&czero\\code\\LINK.H\ne:\\c&czero\\code\\LINT.H\ne:\\c&czero\\code\\LIST.CPP\ne:\\c&czero\\code\\LIST.H\ne:\\c&czero\\code\\LISTNODE.H\ne:\\c&czero\\code\\LOADDLG.CPP\ne:\\c&czero\\code\\LOADDLG.H\ne:\\c&czero\\code\\LOGIC.CPP\ne:\\c&czero\\code\\LOGIC.H\ne:\\c&czero\\code\\LZO.H\ne:\\c&czero\\code\\LZO_CONF.H\ne:\\c&czero\\code\\LZO1X.H\ne:\\c&czero\\code\\LZO1X_C.CPP\ne:\\c&czero\\code\\LZO1X_D.CPP\ne:\\c&czero\\code\\LZOCONF.H\ne:\\c&czero\\code\\LZOPIPE.CPP\ne:\\c&czero\\code\\LZOPIPE.H\ne:\\c&czero\\code\\LZOSTRAW.CPP\ne:\\c&czero\\code\\LZOSTRAW.H\ne:\\c&czero\\code\\LZW.CPP\ne:\\c&czero\\code\\LZW.H\ne:\\c&czero\\code\\LZWOTRAW.CPP\ne:\\c&czero\\code\\LZWPIPE.CPP\ne:\\c&czero\\code\\LZWPIPE.H\ne:\\c&czero\\code\\LZWSTRAW.CPP\ne:\\c&czero\\code\\LZWSTRAW.H\ne:\\c&czero\\code\\MAP.CPP\ne:\\c&czero\\code\\MAP.H\ne:\\c&czero\\code\\MAPEDDLG.CPP\ne:\\c&czero\\code\\MAPEDIT.CPP\ne:\\c&czero\\code\\MAPEDIT.H\ne:\\c&czero\\code\\MAPEDPLC.CPP\ne:\\c&czero\\code\\MAPEDSEL.CPP\ne:\\c&czero\\code\\MAPEDTM.CPP\ne:\\c&czero\\code\\MAPSEL.CPP\ne:\\c&czero\\code\\MENUS.CPP\ne:\\c&czero\\code\\MESSAGE.H\ne:\\c&czero\\code\\MISSION.CPP\ne:\\c&czero\\code\\MISSION.H\ne:\\c&czero\\code\\MIXFILE.CPP\ne:\\c&czero\\code\\MIXFILE.H\ne:\\c&czero\\code\\MONOC.CPP\ne:\\c&czero\\code\\MONOC.H\ne:\\c&czero\\code\\MOUSE.CPP\ne:\\c&czero\\code\\MOUSE.H\ne:\\c&czero\\code\\MP.CPP\ne:\\c&czero\\code\\MP.H\ne:\\c&czero\\code\\MPLAYER.CPP\ne:\\c&czero\\code\\MPU.CPP\ne:\\c&czero\\code\\MPU.H\ne:\\c&czero\\code\\MSGBOX.CPP\ne:\\c&czero\\code\\MSGBOX.H\ne:\\c&czero\\code\\MSGLIST.CPP\ne:\\c&czero\\code\\MSGLIST.H\ne:\\c&czero\\code\\NETDLG.CPP\ne:\\c&czero\\code\\NULLCONN.CPP\ne:\\c&czero\\code\\NULLCONN.H\ne:\\c&czero\\code\\NULLDLG.CPP\ne:\\c&czero\\code\\NULLMGR.CPP\ne:\\c&czero\\code\\NULLMGR.H\ne:\\c&czero\\code\\OBJECT.CPP\ne:\\c&czero\\code\\OBJECT.H\ne:\\c&czero\\code\\ODATA.CPP\ne:\\c&czero\\code\\OPTIONS.CPP\ne:\\c&czero\\code\\OPTIONS.H\ne:\\c&czero\\code\\OVERLAY.CPP\ne:\\c&czero\\code\\OVERLAY.H\ne:\\c&czero\\code\\PACKET.CPP\ne:\\c&czero\\code\\PACKET.H\ne:\\c&czero\\code\\PALETTE.CPP\ne:\\c&czero\\code\\PALETTE.H\ne:\\c&czero\\code\\PCX.H\ne:\\c&czero\\code\\PHONE.H\ne:\\c&czero\\code\\PIPE.CPP\ne:\\c&czero\\code\\PIPE.H\ne:\\c&czero\\code\\PK.CPP\ne:\\c&czero\\code\\PK.H\ne:\\c&czero\\code\\PKPIPE.CPP\ne:\\c&czero\\code\\PKPIPE.H\ne:\\c&czero\\code\\PKSTRAW.CPP\ne:\\c&czero\\code\\PKSTRAW.H\ne:\\c&czero\\code\\POWER.CPP\ne:\\c&czero\\code\\POWER.H\ne:\\c&czero\\code\\PROFILE.CPP\ne:\\c&czero\\code\\QUEUE.CPP\ne:\\c&czero\\code\\QUEUE.H\ne:\\c&czero\\code\\RADAR.CPP\ne:\\c&czero\\code\\RADAR.H\ne:\\c&czero\\code\\RADIO.CPP\ne:\\c&czero\\code\\RADIO.H\ne:\\c&czero\\code\\RAMFILE.CPP\ne:\\c&czero\\code\\RAMFILE.H\ne:\\c&czero\\code\\RANDOM.CPP\ne:\\c&czero\\code\\RANDOM.H\ne:\\c&czero\\code\\RAWFILE.CPP\ne:\\c&czero\\code\\RAWFILE.H\ne:\\c&czero\\code\\READLINE.CPP\ne:\\c&czero\\code\\READLINE.H\ne:\\c&czero\\code\\RECT.CPP\ne:\\c&czero\\code\\RECT.H\ne:\\c&czero\\code\\REGION.H\ne:\\c&czero\\code\\REINF.CPP\ne:\\c&czero\\code\\RGB.CPP\ne:\\c&czero\\code\\RGB.H\ne:\\c&czero\\code\\RNDSTRAW.CPP\ne:\\c&czero\\code\\RNDSTRAW.H\ne:\\c&czero\\code\\RNG.H\ne:\\c&czero\\code\\ROTBMP.CPP\ne:\\c&czero\\code\\ROTBMP.H\ne:\\c&czero\\code\\RULES.CPP\ne:\\c&czero\\code\\RULES.H\ne:\\c&czero\\code\\SAVEDLG.H\ne:\\c&czero\\code\\SAVELOAD.CPP\ne:\\c&czero\\code\\SCENARIO.CPP\ne:\\c&czero\\code\\SCENARIO.H\ne:\\c&czero\\code\\SCORE.CPP\ne:\\c&czero\\code\\SCORE.H\ne:\\c&czero\\code\\SCREEN.H\ne:\\c&czero\\code\\SCROLL.CPP\ne:\\c&czero\\code\\SCROLL.H\ne:\\c&czero\\code\\SDATA.CPP\ne:\\c&czero\\code\\SENDFILE.CPP\ne:\\c&czero\\code\\SESSION.CPP\ne:\\c&czero\\code\\SESSION.H\ne:\\c&czero\\code\\SHA.CPP\ne:\\c&czero\\code\\SHA.H\ne:\\c&czero\\code\\SHAPEBTN.CPP\ne:\\c&czero\\code\\SHAPEBTN.H\ne:\\c&czero\\code\\SHAPIPE.CPP\ne:\\c&czero\\code\\SHAPIPE.H\ne:\\c&czero\\code\\SHASTRAW.CPP\ne:\\c&czero\\code\\SHASTRAW.H\ne:\\c&czero\\code\\SIDEBAR.CPP\ne:\\c&czero\\code\\SIDEBAR.H\ne:\\c&czero\\code\\SLIDER.CPP\ne:\\c&czero\\code\\SLIDER.H\ne:\\c&czero\\code\\SMUDGE.CPP\ne:\\c&czero\\code\\SMUDGE.H\ne:\\c&czero\\code\\SOUNDDLG.CPP\ne:\\c&czero\\code\\SOUNDDLG.H\ne:\\c&czero\\code\\SPECIAL.CPP\ne:\\c&czero\\code\\SPECIAL.H\ne:\\c&czero\\code\\SPRITE.CPP\ne:\\c&czero\\code\\STAGE.H\ne:\\c&czero\\code\\STARTUP.CPP\ne:\\c&czero\\code\\STATBTN.CPP\ne:\\c&czero\\code\\STATBTN.H\ne:\\c&czero\\code\\STATS.CPP\ne:\\c&czero\\code\\STRAW.CPP\ne:\\c&czero\\code\\STRAW.H\ne:\\c&czero\\code\\STYLE.H\ne:\\c&czero\\code\\SUPER.CPP\ne:\\c&czero\\code\\SUPER.H\ne:\\c&czero\\code\\SURFACE.CPP\ne:\\c&czero\\code\\SURFACE.H\ne:\\c&czero\\code\\TAB.CPP\ne:\\c&czero\\code\\TAB.H\ne:\\c&czero\\code\\TACTION.CPP\ne:\\c&czero\\code\\TACTION.H\ne:\\c&czero\\code\\TARCOM.CPP\ne:\\c&czero\\code\\TARGET.CPP\ne:\\c&czero\\code\\TARGET.H\ne:\\c&czero\\code\\TCPIP.CPP\ne:\\c&czero\\code\\TCPIP.H\ne:\\c&czero\\code\\TDATA.CPP\ne:\\c&czero\\code\\TEAM.CPP\ne:\\c&czero\\code\\TEAM.H\ne:\\c&czero\\code\\TEAMTYPE.CPP\ne:\\c&czero\\code\\TEAMTYPE.H\ne:\\c&czero\\code\\TECHNO.CPP\ne:\\c&czero\\code\\TECHNO.H\ne:\\c&czero\\code\\TEMPLATE.CPP\ne:\\c&czero\\code\\TEMPLATE.H\ne:\\c&czero\\code\\TERRAIN.CPP\ne:\\c&czero\\code\\TERRAIN.H\ne:\\c&czero\\code\\TEVENT.CPP\ne:\\c&czero\\code\\TEVENT.H\ne:\\c&czero\\code\\TEXTBTN.CPP\ne:\\c&czero\\code\\TEXTBTN.H\ne:\\c&czero\\code\\THEME.CPP\ne:\\c&czero\\code\\THEME.H\ne:\\c&czero\\code\\TOGGLE.CPP\ne:\\c&czero\\code\\TOGGLE.H\ne:\\c&czero\\code\\TRACKER.CPP\ne:\\c&czero\\code\\TRIGGER.CPP\ne:\\c&czero\\code\\TRIGGER.H\ne:\\c&czero\\code\\TRIGTYPE.CPP\ne:\\c&czero\\code\\TRIGTYPE.H\ne:\\c&czero\\code\\TXTLABEL.CPP\ne:\\c&czero\\code\\TXTLABEL.H\ne:\\c&czero\\code\\TYPE.H\ne:\\c&czero\\code\\UDATA.CPP\ne:\\c&czero\\code\\UNIT.CPP\ne:\\c&czero\\code\\UNIT.H\ne:\\c&czero\\code\\UTRACKER.CPP\ne:\\c&czero\\code\\UTRACKER.H\ne:\\c&czero\\code\\VDATA.CPP\ne:\\c&czero\\code\\VECTOR.CPP\ne:\\c&czero\\code\\VECTOR.H\ne:\\c&czero\\code\\VERSION.CPP\ne:\\c&czero\\code\\VERSION.H\ne:\\c&czero\\code\\VESSEL.CPP\ne:\\c&czero\\code\\VESSEL.H\ne:\\c&czero\\code\\VISUDLG.CPP\ne:\\c&czero\\code\\VISUDLG.H\ne:\\c&czero\\code\\VORTEX.CPP\ne:\\c&czero\\code\\VORTEX.H\ne:\\c&czero\\code\\WARHEAD.CPP\ne:\\c&czero\\code\\WARHEAD.H\ne:\\c&czero\\code\\WATCOM.H\ne:\\c&czero\\code\\WEAPON.CPP\ne:\\c&czero\\code\\WEAPON.H\ne:\\c&czero\\code\\WINSTUB.CPP\ne:\\c&czero\\code\\WRITEPCX.CPP\ne:\\c&czero\\code\\WWFILE.H\ne:\\c&czero\\code\\XPIPE.CPP\ne:\\c&czero\\code\\XPIPE.H\ne:\\c&czero\\code\\XSTRAW.CPP\ne:\\c&czero\\code\\XSTRAW.H\n\n[State]\nSysSetCwd='E:\\c&czero\\code'\nSrchSetFlags=0x000320aa\nFileSortMode=0x0\nStateWindowFrame=37,16,923,511,0x62c9f4fa\n_StateWindow=0,0,991,648,0x00100008,'E:\\c&czero\\code\\TECHNO.CPP',240,15,244,32,32,0,32,32,32,32,8,4294967295,4294967295,1,10,'',12,255,48,0,7,243,252,253,247,249,247,1567,23,400,0,246,252,248,244,247,15,15,15,15,0,0\n_StateBuffer='E:\\c&czero\\code\\TECHNO.CPP',0x0400048e,1567,23,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\DEFINES.H',0x0400048e,736,4,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\FOOT.H',0x0400048e,105,16,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\OBJECT.H',0x0400048e,134,12,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\TARGET.H',0x0400048e,34,13,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\AIRCRAFT.CPP',0x0400048e,2975,1,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\HOUSE.H',0x0400048e,608,16,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\HOUSE.CPP',0x0400048e,4722,7,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\TODO.TXT',0x0400048e,3,1,25,'5 9','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\UNIT.CPP',0x0c00048e,4248,19,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\DRIVE.CPP',0x0400048e,31,18,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\KEY.CPP',0x0c00048e,740,1,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\KEY.H',0x0400048e,84,7,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\DISPLAY.CPP',0x0c00048e,3579,34,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\MAP.CPP',0x0400048e,1262,76,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\INI.CPP',0x0400048e,371,1,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\INI.H',0x0400048e,121,1,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\SENDFILE.CPP',0x0400048e,1,1,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\search.h',0x0400048e,611,16,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\run\\RULES.INI',0x0400048e,250,1,25,'5 9','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\RULES.CPP',0x0400048e,669,92,25,'4 7','',0x0,''\n_StateBuffer='E:\\c&czero\\code\\RULES.H',0x0400048e,68,1,25,'4 7','',0x0,''\n_StateHistory=SEARCH,'THREAT_','_TIBERIUM','In_Which','Zone','Which_Zone','::Mission_Attack','::Good_Fire_Loca','Is_Tar','Is_','IsDr'\n_StateHistory=REPLACE,'ph','tx','ty','tw','th','Structure','trycell','Is_Clear_To_Build','Is_Clear_To_Move','Archive'\n_StateHistory=XMACRO,'sort'\n_StateHistory=FILELIST,'E:\\c&czero\\code\\RULES.CPP','E:\\c&czero\\run\\RULES.INI','E:\\c&czero\\code\\DEFINES.H','E:\\c&czero\\code\\AIRCRAFT.CPP','E:\\c&czero\\code\\defines.g','E:\\c&czero\\code\\TECHNO.CPP','E:\\c&czero\\code\\HOUSE.H','E:\\c&czero\\code\\TARGET.H','E:\\c&czero\\code\\OBJECT.H','E:\\c&czero\\code\\FOOT.H'\n_StateHistory=EDITFILE,'techno.cpp','house.cpp','house.h','aircraft.cpp','target.h','object.h','foot.h','todo.txt','techno.cpp','house.h'\n_StateHistory=DIRECTORY,'E:\\C&CZero\\code'\n_StateHistory=GOTOMARK,'1'\n_StateHistory=GOTOLINE,'122','371','366','372','575','655','656','664','611','1567'\n_StateMark=MARK_GLOBAL,1,'E:\\c&czero\\code\\HOUSE.CPP',4732,1,0\n\n[Editor]\nClipboardSetTermStr='\\r\\n',0\nClipboardEnableTermStr=1\nClipboardSetSepStr='\\r\\n',0\nClipboardEnableSepStr=1\nScrapSetCount=1\nVCSProject=''\nVCSProjectPath=''\nVCSProjectLocalPath=''\n_RestoreSysFlags=0x62c9f5fa, 0xfffffffc\n\n[Compiler]\nTagSetCmd='${HOME}${WTAGS} -oc -d -t${TAGFILE}.tag -p${TAGFILE}.ptg',0x8000060\nBrowseSetFile='e:\\C&Czero\\code\\RA-Home.ptg'\nTagSetFile='e:\\C&Czero\\code\\RA-Home.tag'\nCompilerAddCmd='Microsoft Assembler','ftee masm -w2 -zi %r%e;',1073741824,'',0,'',16,'',16,'',0,'',0,'_MicrosoftErrorInfo','','','','%v%p'\nCompilerAddResponse='Microsoft Assembler',\nCompilerAddCmd='Borland C++','ftee bcc -S %r.c',1073741824,'',0,'ftee make %r.obj',16,'ftee make %r.obj',16,'',0,'',0,'_BorlandCppErrorInfo','','','','%v%p'\nCompilerAddResponse='Borland C++',\nCompilerAddCmd='Borland Turbo Assembler','ftee make %r.obj',1073741824,'',0,'ftee make %r.obj',16,'',16,'',0,'',0,'_TasmErrorInfo','','','','%v%p'\nCompilerAddResponse='Borland Turbo Assembler',\nCompilerAddCmd='$_cw_proj_hash_$','',1073741825,'',1,'watcom\\binw\\wmake WIN32=1 %r.obj',209,'wmake WIN32=1',209,'ftee joemake',209,'r.bat -hansolo cheater -xqm',224,'_MSLinkErrorInfo','_MicrosoftErrorInfo','_NMakeErrorInfo','proj.err','e:\\c&czero\\code'\nCompilerAddResponse='$_cw_proj_hash_$',\nCompilerAddCmd='Microsoft C','ftee cl -c -AL -Gsw -Ow -Zpe  %r%e',1073741824,'',0,'',16,'',16,'',0,'',0,'_MicrosoftErrorInfo','','','','%v%p'\nCompilerAddResponse='Microsoft C',\nCompilerAddCmd='Default Project','',1073741824,'',0,'ftee make',16,'ftee make',16,'',0,'',0,'_ErrorInfoDefault','','','proj.err','%v%p'\nCompilerAddResponse='Default Project',\nCompilerAddCmd='Zortech C++','ftee ztc -a -b -c -g -ml -W %r%e',1073741824,'',0,'',16,'',16,'',0,'',0,'_ZortechCppErrorInfo','','','','%v%p'\nCompilerAddResponse='Zortech C++',\nCompilerAddCmd='Script','ftee make %r.inf',1073741824,'',0,'ftee make',16,'ftee make',16,'',0,'',0,'_BorlandCppErrorInfo','','','',''\nCompilerAddResponse='Script',\nCompilerAddCmd='Microsoft C(NT-i386)','${FTEE} cl -DSTRICT -c -W3 -G3 -D_X86_=1 -DWIN32 %r%e',1073741936,'${FTEE} cl -DSTRICT -c -W3 -G3 -D_X86_=1 -DWIN32 %r%e',112,'',144,'',144,'',0,'',0,'_MicrosoftErrorInfo','','','',''\nCompilerAddResponse='Microsoft C(NT-i386)',\nCompilerAssign='Borland C++','.scr'\nCompilerNewExt=.bas\nCompilerAssign='Borland C++','.int'\nCompilerAssign='Borland C++','.c'\nCompilerNewExt=.prg\nCompilerAssign='Microsoft C','.h'\nCompilerAssign='Borland C++','.cpp'\nCompilerAssign='Default Project','.*'\nCompilerAssign='Microsoft C(NT-i386)','.cxx'\nCompilerAssign='Borland Turbo Assembler','.asm'\nCompilerAssign='Microsoft C(NT-i386)','.hpp'\n"
  },
  {
    "path": "CODE/RA95.PJT",
    "content": ";Codewright Project File (do not remove or modify this line)\n[ProjInit]\nProjSetConfigFlags=0x00010940\nProjCheckPath='C:\\PROJECTS\\RedAlert\\code\\\\'\n\n[Files]\nC:\\projects\\redalert\\code\\2KEYFRAM.CPP\nC:\\projects\\redalert\\code\\AADATA.CPP\nC:\\projects\\redalert\\code\\ABSTRACT.CPP\nC:\\projects\\redalert\\code\\ABSTRACT.H\nC:\\projects\\redalert\\code\\ADATA.CPP\nC:\\projects\\redalert\\code\\AIRCRAFT.CPP\nC:\\projects\\redalert\\code\\AIRCRAFT.H\nC:\\projects\\redalert\\code\\ANIM.CPP\nC:\\projects\\redalert\\code\\ANIM.H\nC:\\projects\\redalert\\code\\AUDIO.CPP\nC:\\projects\\redalert\\code\\B64PIPE.CPP\nC:\\projects\\redalert\\code\\B64PIPE.H\nC:\\projects\\redalert\\code\\B64STRAW.CPP\nC:\\projects\\redalert\\code\\B64STRAW.H\nC:\\projects\\redalert\\code\\BAR.CPP\nC:\\projects\\redalert\\code\\BAR.H\nC:\\projects\\redalert\\code\\BASE.CPP\nC:\\projects\\redalert\\code\\BASE.H\nC:\\projects\\redalert\\code\\BASE64.CPP\nC:\\projects\\redalert\\code\\BASE64.H\nC:\\projects\\redalert\\code\\BBDATA.CPP\nC:\\projects\\redalert\\code\\BDATA.CPP\nC:\\projects\\redalert\\code\\BENCH.CPP\nC:\\projects\\redalert\\code\\BENCH.H\nC:\\projects\\redalert\\code\\BFIOFILE.CPP\nC:\\projects\\redalert\\code\\BFIOFILE.H\nC:\\projects\\redalert\\code\\BLOWFISH.CPP\nC:\\projects\\redalert\\code\\BLOWFISH.H\nC:\\projects\\redalert\\code\\BLOWPIPE.CPP\nC:\\projects\\redalert\\code\\BLOWPIPE.H\nC:\\projects\\redalert\\code\\BLWSTRAW.CPP\nC:\\projects\\redalert\\code\\BLWSTRAW.H\nC:\\projects\\redalert\\code\\BUFF.CPP\nC:\\projects\\redalert\\code\\BUFF.H\nC:\\projects\\redalert\\code\\BUFFERX.H\nC:\\projects\\redalert\\code\\BUILDING.CPP\nC:\\projects\\redalert\\code\\BUILDING.H\nC:\\projects\\redalert\\code\\BULLET.CPP\nC:\\projects\\redalert\\code\\BULLET.H\nC:\\projects\\redalert\\code\\CARGO.CPP\nC:\\projects\\redalert\\code\\CARGO.H\nC:\\projects\\redalert\\code\\CARRY.CPP\nC:\\projects\\redalert\\code\\CARRY.H\nC:\\projects\\redalert\\code\\CCDDE.CPP\nC:\\projects\\redalert\\code\\CCDDE.H\nC:\\projects\\redalert\\code\\CCFILE.CPP\nC:\\projects\\redalert\\code\\CCFILE.H\nC:\\projects\\redalert\\code\\CCINI.CPP\nC:\\projects\\redalert\\code\\CCINI.H\nC:\\projects\\redalert\\code\\CCMPATH.CPP\nC:\\projects\\redalert\\code\\CCPTR.CPP\nC:\\projects\\redalert\\code\\CCPTR.H\nC:\\projects\\redalert\\code\\CCTEN.CPP\nC:\\projects\\redalert\\code\\CDATA.CPP\nC:\\projects\\redalert\\code\\CDFILE.CPP\nC:\\projects\\redalert\\code\\CDFILE.H\nC:\\projects\\redalert\\code\\CELL.CPP\nC:\\projects\\redalert\\code\\CELL.H\nC:\\projects\\redalert\\code\\CHECKBOX.CPP\nC:\\projects\\redalert\\code\\CHECKBOX.H\nC:\\projects\\redalert\\code\\CHEKLIST.CPP\nC:\\projects\\redalert\\code\\CHEKLIST.H\nC:\\projects\\redalert\\code\\CLASS.CPP\nC:\\projects\\redalert\\code\\COLRLIST.CPP\nC:\\projects\\redalert\\code\\COLRLIST.H\nC:\\projects\\redalert\\code\\COMBAT.CPP\nC:\\projects\\redalert\\code\\COMBUF.CPP\nC:\\projects\\redalert\\code\\COMBUF.H\nC:\\projects\\redalert\\code\\COMPAT.H\nC:\\projects\\redalert\\code\\CONNECT.CPP\nC:\\projects\\redalert\\code\\CONNECT.H\nC:\\projects\\redalert\\code\\CONNMGR.H\nC:\\projects\\redalert\\code\\CONQUER.CPP\nC:\\projects\\redalert\\code\\CONQUER.H\nC:\\projects\\redalert\\code\\CONST.CPP\nC:\\projects\\redalert\\code\\CONTROL.CPP\nC:\\projects\\redalert\\code\\CONTROL.H\nC:\\projects\\redalert\\code\\COORD.CPP\nC:\\projects\\redalert\\code\\CRATE.CPP\nC:\\projects\\redalert\\code\\CRATE.H\nC:\\projects\\redalert\\code\\CRC.CPP\nC:\\projects\\redalert\\code\\CRC.H\nC:\\projects\\redalert\\code\\CRCPIPE.CPP\nC:\\projects\\redalert\\code\\CRCPIPE.H\nC:\\projects\\redalert\\code\\CRCSTRAW.CPP\nC:\\projects\\redalert\\code\\CRCSTRAW.H\nC:\\projects\\redalert\\code\\CREDITS.CPP\nC:\\projects\\redalert\\code\\CREDITS.H\nC:\\projects\\redalert\\code\\CREW.CPP\nC:\\projects\\redalert\\code\\CREW.H\nC:\\projects\\redalert\\code\\CSTRAW.CPP\nC:\\projects\\redalert\\code\\CSTRAW.H\nC:\\projects\\redalert\\code\\DDE.CPP\nC:\\projects\\redalert\\code\\DDE.H\nC:\\projects\\redalert\\code\\DEBUG.CPP\nC:\\projects\\redalert\\code\\DEBUG.H\nC:\\projects\\redalert\\code\\DEFINES.H\nC:\\projects\\redalert\\code\\DESCDLG.CPP\nC:\\projects\\redalert\\code\\DESCDLG.H\nC:\\projects\\redalert\\code\\DIAL8.CPP\nC:\\projects\\redalert\\code\\DIAL8.H\nC:\\projects\\redalert\\code\\DIALOG.CPP\nC:\\projects\\redalert\\code\\DISPLAY.CPP\nC:\\projects\\redalert\\code\\DISPLAY.H\nC:\\projects\\redalert\\code\\DOOR.CPP\nC:\\projects\\redalert\\code\\DOOR.H\nC:\\projects\\redalert\\code\\DRIVE.CPP\nC:\\projects\\redalert\\code\\DRIVE.H\nC:\\projects\\redalert\\code\\DROP.CPP\nC:\\projects\\redalert\\code\\DROP.H\nC:\\projects\\redalert\\code\\DYNAVEC.CPP\nC:\\projects\\redalert\\code\\EDIT.CPP\nC:\\projects\\redalert\\code\\EDIT.H\nC:\\projects\\redalert\\code\\EGOS.CPP\nC:\\projects\\redalert\\code\\EGOS.H\nC:\\projects\\redalert\\code\\ENDING.CPP\nC:\\projects\\redalert\\code\\ENDING.H\nC:\\projects\\redalert\\code\\EVENT.CPP\nC:\\projects\\redalert\\code\\EVENT.H\nC:\\projects\\redalert\\code\\EXPAND.CPP\nC:\\projects\\redalert\\code\\EXTERNS.H\nC:\\projects\\redalert\\code\\FACE.CPP\nC:\\projects\\redalert\\code\\FACE.H\nC:\\projects\\redalert\\code\\FACING.CPP\nC:\\projects\\redalert\\code\\FACING.H\nC:\\projects\\redalert\\code\\FACTORY.CPP\nC:\\projects\\redalert\\code\\FACTORY.H\nC:\\projects\\redalert\\code\\FAKESOCK.H\nC:\\projects\\redalert\\code\\FIELD.CPP\nC:\\projects\\redalert\\code\\FIELD.H\nC:\\projects\\redalert\\code\\FILEPCX.H\nC:\\projects\\redalert\\code\\FINDPATH.CPP\nC:\\projects\\redalert\\code\\FIXED.CPP\nC:\\projects\\redalert\\code\\FIXED.H\nC:\\projects\\redalert\\code\\FLASHER.CPP\nC:\\projects\\redalert\\code\\FLASHER.H\nC:\\projects\\redalert\\code\\FLY.CPP\nC:\\projects\\redalert\\code\\FLY.H\nC:\\projects\\redalert\\code\\FOOT.CPP\nC:\\projects\\redalert\\code\\FOOT.H\nC:\\projects\\redalert\\code\\FTIMER.H\nC:\\projects\\redalert\\code\\FUNCTION.H\nC:\\projects\\redalert\\code\\FUSE.CPP\nC:\\projects\\redalert\\code\\FUSE.H\nC:\\projects\\redalert\\code\\GADGET.CPP\nC:\\projects\\redalert\\code\\GADGET.H\nC:\\projects\\redalert\\code\\GAMEDLG.CPP\nC:\\projects\\redalert\\code\\GAMEDLG.H\nC:\\projects\\redalert\\code\\GAUGE.CPP\nC:\\projects\\redalert\\code\\GAUGE.H\nC:\\projects\\redalert\\code\\GETCPU.CPP\nC:\\projects\\redalert\\code\\GLOBALS.CPP\nC:\\projects\\redalert\\code\\GOPTIONS.CPP\nC:\\projects\\redalert\\code\\GOPTIONS.H\nC:\\projects\\redalert\\code\\GSCREEN.CPP\nC:\\projects\\redalert\\code\\GSCREEN.H\nC:\\projects\\redalert\\code\\HDATA.CPP\nC:\\projects\\redalert\\code\\HEAP.CPP\nC:\\projects\\redalert\\code\\HEAP.H\nC:\\projects\\redalert\\code\\HELP.CPP\nC:\\projects\\redalert\\code\\HELP.H\nC:\\projects\\redalert\\code\\HOUSE.CPP\nC:\\projects\\redalert\\code\\HOUSE.H\nC:\\projects\\redalert\\code\\HSV.CPP\nC:\\projects\\redalert\\code\\HSV.H\nC:\\projects\\redalert\\code\\IDATA.CPP\nC:\\projects\\redalert\\code\\INFANTRY.CPP\nC:\\projects\\redalert\\code\\INFANTRY.H\nC:\\projects\\redalert\\code\\INI.CPP\nC:\\projects\\redalert\\code\\INI.H\nC:\\projects\\redalert\\code\\INIT.CPP\nC:\\projects\\redalert\\code\\INLINE.H\nC:\\projects\\redalert\\code\\INT.CPP\nC:\\projects\\redalert\\code\\INT.H\nC:\\projects\\redalert\\code\\INTERNET.CPP\nC:\\projects\\redalert\\code\\INTERPAL.CPP\nC:\\projects\\redalert\\code\\INTRO.CPP\nC:\\projects\\redalert\\code\\INTRO.H\nC:\\projects\\redalert\\code\\IOMAP.CPP\nC:\\projects\\redalert\\code\\IOOBJ.CPP\nC:\\projects\\redalert\\code\\IPX.CPP\nC:\\projects\\redalert\\code\\IPX.H\nC:\\projects\\redalert\\code\\IPX95.CPP\nC:\\projects\\redalert\\code\\IPX95.H\nC:\\projects\\redalert\\code\\IPXADDR.CPP\nC:\\projects\\redalert\\code\\IPXADDR.H\nC:\\projects\\redalert\\code\\IPXCONN.CPP\nC:\\projects\\redalert\\code\\IPXCONN.H\nC:\\projects\\redalert\\code\\IPXGCONN.CPP\nC:\\projects\\redalert\\code\\IPXGCONN.H\nC:\\projects\\redalert\\code\\IPXMGR.CPP\nC:\\projects\\redalert\\code\\IPXMGR.H\nC:\\projects\\redalert\\code\\JSHELL.CPP\nC:\\projects\\redalert\\code\\JSHELL.H\nC:\\projects\\redalert\\code\\KEY.CPP\nC:\\projects\\redalert\\code\\KEY.H\nC:\\projects\\redalert\\code\\KEYFRAME.CPP\nC:\\projects\\redalert\\code\\LANGUAGE.H\nC:\\projects\\redalert\\code\\LAYER.CPP\nC:\\projects\\redalert\\code\\LAYER.H\nC:\\projects\\redalert\\code\\LCW.CPP\nC:\\projects\\redalert\\code\\LCW.H\nC:\\projects\\redalert\\code\\LCWPIPE.CPP\nC:\\projects\\redalert\\code\\LCWPIPE.H\nC:\\projects\\redalert\\code\\LCWSTRAW.CPP\nC:\\projects\\redalert\\code\\LCWSTRAW.H\nC:\\projects\\redalert\\code\\LCWUNCMP.CPP\nC:\\projects\\redalert\\code\\LINK.CPP\nC:\\projects\\redalert\\code\\LINK.H\nC:\\projects\\redalert\\code\\LINT.H\nC:\\projects\\redalert\\code\\LIST.CPP\nC:\\projects\\redalert\\code\\LIST.H\nC:\\projects\\redalert\\code\\LISTNODE.H\nC:\\projects\\redalert\\code\\LOADDLG.CPP\nC:\\projects\\redalert\\code\\LOADDLG.H\nC:\\projects\\redalert\\code\\LOGIC.CPP\nC:\\projects\\redalert\\code\\LOGIC.H\nC:\\projects\\redalert\\code\\LZO.H\nC:\\projects\\redalert\\code\\LZO_CONF.H\nC:\\projects\\redalert\\code\\LZO1X.H\nC:\\projects\\redalert\\code\\LZO1X_C.CPP\nC:\\projects\\redalert\\code\\LZO1X_D.CPP\nC:\\projects\\redalert\\code\\LZOCONF.H\nC:\\projects\\redalert\\code\\LZOPIPE.CPP\nC:\\projects\\redalert\\code\\LZOPIPE.H\nC:\\projects\\redalert\\code\\LZOSTRAW.CPP\nC:\\projects\\redalert\\code\\LZoSTRAW.H\nC:\\projects\\redalert\\code\\LZW.CPP\nC:\\projects\\redalert\\code\\LZW.H\nC:\\projects\\redalert\\code\\LZWOTRAW.CPP\nC:\\projects\\redalert\\code\\LZWPIPE.CPP\nC:\\projects\\redalert\\code\\LZWPIPE.H\nC:\\projects\\redalert\\code\\LZWSTRAW.CPP\nC:\\projects\\redalert\\code\\LZWSTRAW.H\nC:\\projects\\redalert\\code\\MAP.CPP\nC:\\projects\\redalert\\code\\MAP.H\nC:\\projects\\redalert\\code\\MAPEDDLG.CPP\nC:\\projects\\redalert\\code\\MAPEDIT.CPP\nC:\\projects\\redalert\\code\\MAPEDIT.H\nC:\\projects\\redalert\\code\\MAPEDPLC.CPP\nC:\\projects\\redalert\\code\\MAPEDSEL.CPP\nC:\\projects\\redalert\\code\\MAPEDTM.CPP\nC:\\projects\\redalert\\code\\MAPSEL.CPP\nC:\\projects\\redalert\\code\\MENUS.CPP\nC:\\projects\\redalert\\code\\MESSAGE.H\nC:\\projects\\redalert\\code\\MISSION.CPP\nC:\\projects\\redalert\\code\\MISSION.H\nC:\\projects\\redalert\\code\\MIXFILE.CPP\nC:\\projects\\redalert\\code\\MIXFILE.H\nC:\\projects\\redalert\\code\\MONOC.CPP\nC:\\projects\\redalert\\code\\MONOC.H\nC:\\projects\\redalert\\code\\MOUSE.CPP\nC:\\projects\\redalert\\code\\MOUSE.H\nC:\\projects\\redalert\\code\\MP.CPP\nC:\\projects\\redalert\\code\\MP.H\nC:\\projects\\redalert\\code\\MPLAYER.CPP\nC:\\projects\\redalert\\code\\MPLIB.CPP\nC:\\projects\\redalert\\code\\MPLPC.CPP\nC:\\projects\\redalert\\code\\MPMGRD.CPP\nC:\\projects\\redalert\\code\\MPMGRD.H\nC:\\projects\\redalert\\code\\MPMGRW.CPP\nC:\\projects\\redalert\\code\\MPMGRW.H\nC:\\projects\\redalert\\code\\MPU.CPP\nC:\\projects\\redalert\\code\\MPU.H\nC:\\projects\\redalert\\code\\MSGBOX.CPP\nC:\\projects\\redalert\\code\\MSGBOX.H\nC:\\projects\\redalert\\code\\MSGLIST.CPP\nC:\\projects\\redalert\\code\\MSGLIST.H\nC:\\projects\\redalert\\code\\NETDLG.CPP\nC:\\projects\\redalert\\code\\NULLCONN.CPP\nC:\\projects\\redalert\\code\\NULLCONN.H\nC:\\projects\\redalert\\code\\NULLDLG.CPP\nC:\\projects\\redalert\\code\\NULLMGR.CPP\nC:\\projects\\redalert\\code\\NULLMGR.H\nC:\\projects\\redalert\\code\\OBJECT.CPP\nC:\\projects\\redalert\\code\\OBJECT.H\nC:\\projects\\redalert\\code\\ODATA.CPP\nC:\\projects\\redalert\\code\\OPTIONS.CPP\nC:\\projects\\redalert\\code\\OPTIONS.H\nC:\\projects\\redalert\\code\\OVERLAY.CPP\nC:\\projects\\redalert\\code\\OVERLAY.H\nC:\\projects\\redalert\\code\\PACKET.CPP\nC:\\projects\\redalert\\code\\PACKET.H\nC:\\projects\\redalert\\code\\palette.cpp\nC:\\projects\\redalert\\code\\PALETTE.H\nC:\\projects\\redalert\\code\\PCX.H\nC:\\projects\\redalert\\code\\PHONE.H\nC:\\projects\\redalert\\code\\PIPE.CPP\nC:\\projects\\redalert\\code\\PIPE.H\nC:\\projects\\redalert\\code\\PK.CPP\nC:\\projects\\redalert\\code\\PK.H\nC:\\projects\\redalert\\code\\PKPIPE.CPP\nC:\\projects\\redalert\\code\\PKPIPE.H\nC:\\projects\\redalert\\code\\PKSTRAW.CPP\nC:\\projects\\redalert\\code\\PKSTRAW.H\nC:\\projects\\redalert\\code\\POWER.CPP\nC:\\projects\\redalert\\code\\POWER.H\nC:\\projects\\redalert\\code\\PROFILE.CPP\nC:\\projects\\redalert\\code\\QUEUE.CPP\nC:\\projects\\redalert\\code\\QUEUE.H\nC:\\projects\\redalert\\code\\RADAR.CPP\nC:\\projects\\redalert\\code\\RADAR.H\nC:\\projects\\redalert\\code\\RADIO.CPP\nC:\\projects\\redalert\\code\\RADIO.H\nC:\\projects\\redalert\\code\\RAMFILE.CPP\nC:\\projects\\redalert\\code\\RAMFILE.H\nC:\\projects\\redalert\\code\\RANDOM.CPP\nC:\\projects\\redalert\\code\\RANDOM.H\nC:\\projects\\redalert\\code\\RAWFILE.CPP\nC:\\projects\\redalert\\code\\RAWFILE.H\nC:\\projects\\redalert\\code\\READLINE.CPP\nC:\\projects\\redalert\\code\\READLINE.H\nC:\\projects\\redalert\\code\\RECT.CPP\nC:\\projects\\redalert\\code\\RECT.H\nC:\\projects\\redalert\\code\\REGION.H\nC:\\projects\\redalert\\code\\REINF.CPP\nC:\\projects\\redalert\\code\\RGB.CPP\nC:\\projects\\redalert\\code\\RGB.H\nC:\\projects\\redalert\\code\\RNDSTRAW.CPP\nC:\\projects\\redalert\\code\\RNDSTRAW.H\nC:\\projects\\redalert\\code\\RNG.H\nC:\\projects\\redalert\\code\\ROTBMP.CPP\nC:\\projects\\redalert\\code\\ROTBMP.H\nC:\\projects\\redalert\\code\\RULES.CPP\nC:\\projects\\redalert\\code\\RULES.H\nC:\\projects\\redalert\\code\\SAVEDLG.H\nC:\\projects\\redalert\\code\\SAVELOAD.CPP\nC:\\projects\\redalert\\code\\SCENARIO.CPP\nC:\\projects\\redalert\\code\\SCENARIO.H\nC:\\projects\\redalert\\code\\SCORE.CPP\nC:\\projects\\redalert\\code\\SCORE.H\nC:\\projects\\redalert\\code\\SCREEN.H\nC:\\projects\\redalert\\code\\SCROLL.CPP\nC:\\projects\\redalert\\code\\SCROLL.H\nC:\\projects\\redalert\\code\\SDATA.CPP\nC:\\projects\\redalert\\code\\SEARCH.H\nC:\\projects\\redalert\\code\\SENDFILE.CPP\nC:\\projects\\redalert\\code\\SESSION.CPP\nC:\\projects\\redalert\\code\\SESSION.H\nC:\\projects\\redalert\\code\\SHA.CPP\nC:\\projects\\redalert\\code\\SHA.H\nC:\\projects\\redalert\\code\\SHAPEBTN.CPP\nC:\\projects\\redalert\\code\\SHAPEBTN.H\nC:\\projects\\redalert\\code\\SHAPIPE.CPP\nC:\\projects\\redalert\\code\\SHAPIPE.H\nC:\\projects\\redalert\\code\\SHASTRAW.CPP\nC:\\projects\\redalert\\code\\SHASTRAW.H\nC:\\projects\\redalert\\code\\SIDEBAR.CPP\nC:\\projects\\redalert\\code\\SIDEBAR.H\nC:\\projects\\redalert\\code\\SLIDER.CPP\nC:\\projects\\redalert\\code\\SLIDER.H\nC:\\projects\\redalert\\code\\SMUDGE.CPP\nC:\\projects\\redalert\\code\\SMUDGE.H\nC:\\projects\\redalert\\code\\SOUNDDLG.CPP\nC:\\projects\\redalert\\code\\SOUNDDLG.H\nC:\\projects\\redalert\\code\\SPECIAL.CPP\nC:\\projects\\redalert\\code\\SPECIAL.H\nC:\\projects\\redalert\\code\\SPRITE.CPP\nC:\\projects\\redalert\\code\\STAGE.H\nC:\\projects\\redalert\\code\\STARTUP.CPP\nC:\\projects\\redalert\\code\\STATBTN.CPP\nC:\\projects\\redalert\\code\\STATBTN.H\nC:\\projects\\redalert\\code\\STATS.CPP\nC:\\projects\\redalert\\code\\STRAW.CPP\nC:\\projects\\redalert\\code\\STRAW.H\nC:\\projects\\redalert\\code\\STYLE.H\nC:\\projects\\redalert\\code\\SUPER.CPP\nC:\\projects\\redalert\\code\\SUPER.H\nC:\\projects\\redalert\\code\\SURFACE.CPP\nC:\\projects\\redalert\\code\\SURFACE.H\nC:\\projects\\redalert\\code\\TAB.CPP\nC:\\projects\\redalert\\code\\TAB.H\nC:\\projects\\redalert\\code\\TACTION.CPP\nC:\\projects\\redalert\\code\\TACTION.H\nC:\\projects\\redalert\\code\\TARCOM.CPP\nC:\\projects\\redalert\\code\\TARGET.CPP\nC:\\projects\\redalert\\code\\TARGET.H\nC:\\projects\\redalert\\code\\TCPIP.CPP\nC:\\projects\\redalert\\code\\TCPIP.H\nC:\\projects\\redalert\\code\\TDATA.CPP\nC:\\projects\\redalert\\code\\TEAM.CPP\nC:\\projects\\redalert\\code\\TEAM.H\nC:\\projects\\redalert\\code\\TEAMTYPE.CPP\nC:\\projects\\redalert\\code\\TEAMTYPE.H\nC:\\projects\\redalert\\code\\TECHNO.CPP\nC:\\projects\\redalert\\code\\TECHNO.H\nC:\\projects\\redalert\\code\\TEMP.CPP\nC:\\projects\\redalert\\code\\TEMPLATE.CPP\nC:\\projects\\redalert\\code\\TEMPLATE.H\nC:\\projects\\redalert\\code\\TENMGR.CPP\nC:\\projects\\redalert\\code\\TENMGR.H\nC:\\projects\\redalert\\code\\TERRAIN.CPP\nC:\\projects\\redalert\\code\\TERRAIN.H\nC:\\projects\\redalert\\code\\TEVENT.CPP\nC:\\projects\\redalert\\code\\TEVENT.H\nC:\\projects\\redalert\\code\\TEXTBTN.CPP\nC:\\projects\\redalert\\code\\TEXTBTN.H\nC:\\projects\\redalert\\code\\THEME.CPP\nC:\\projects\\redalert\\code\\THEME.H\nC:\\projects\\redalert\\code\\TOGGLE.CPP\nC:\\projects\\redalert\\code\\TOGGLE.H\nC:\\projects\\redalert\\code\\TRACKER.CPP\nC:\\projects\\redalert\\code\\TRIGGER.CPP\nC:\\projects\\redalert\\code\\TRIGGER.H\nC:\\projects\\redalert\\code\\TRIGTYPE.CPP\nC:\\projects\\redalert\\code\\TRIGTYPE.H\nC:\\projects\\redalert\\code\\TXTLABEL.CPP\nC:\\projects\\redalert\\code\\TXTLABEL.H\nC:\\projects\\redalert\\code\\TYPE.H\nC:\\projects\\redalert\\code\\UDATA.CPP\nC:\\projects\\redalert\\code\\UNIT.CPP\nC:\\projects\\redalert\\code\\UNIT.H\nC:\\projects\\redalert\\code\\UTRACKER.CPP\nC:\\projects\\redalert\\code\\UTRACKER.H\nC:\\projects\\redalert\\code\\VDATA.CPP\nC:\\projects\\redalert\\code\\VECTOR.CPP\nC:\\projects\\redalert\\code\\VECTOR.H\nC:\\projects\\redalert\\code\\VERSION.CPP\nC:\\projects\\redalert\\code\\VERSION.H\nC:\\projects\\redalert\\code\\VESSEL.CPP\nC:\\projects\\redalert\\code\\VESSEL.H\nC:\\projects\\redalert\\code\\VISUDLG.CPP\nC:\\projects\\redalert\\code\\VISUDLG.H\nC:\\projects\\redalert\\code\\VORTEX.CPP\nC:\\projects\\redalert\\code\\VORTEX.H\nC:\\projects\\redalert\\code\\WARHEAD.CPP\nC:\\projects\\redalert\\code\\WARHEAD.H\nC:\\projects\\redalert\\code\\WATCOM.H\nC:\\projects\\redalert\\code\\WEAPON.CPP\nC:\\projects\\redalert\\code\\WEAPON.H\nC:\\projects\\redalert\\code\\WINSTUB.CPP\nC:\\projects\\redalert\\code\\WRITEPCX.CPP\nC:\\projects\\redalert\\code\\WWFILE.H\nC:\\projects\\redalert\\code\\XPIPE.CPP\nC:\\projects\\redalert\\code\\XPIPE.H\nC:\\projects\\redalert\\code\\XSTRAW.CPP\nC:\\projects\\redalert\\code\\XSTRAW.H\nC:\\projects\\redalert\\code\\2KEYFBUF.ASM\nC:\\projects\\redalert\\code\\2support.asm\nC:\\projects\\redalert\\code\\2TXTPRNT.ASM\nC:\\projects\\redalert\\code\\coorda.asm\nC:\\projects\\redalert\\code\\CPUID.ASM\nC:\\projects\\redalert\\code\\ipxprot.asm\nC:\\projects\\redalert\\code\\ipxreal.asm\nC:\\projects\\redalert\\code\\KEYFBUFF.ASM\nC:\\projects\\redalert\\code\\LCWCOMP.ASM\nC:\\projects\\redalert\\code\\pagfault.asm\nC:\\projects\\redalert\\code\\SUPPORT.ASM\nC:\\projects\\redalert\\code\\txtprnt.asm\nC:\\projects\\redalert\\code\\winasm.asm\n\n[State]\nSysSetCwd='C:\\projects\\redalert\\code'\nSrchSetFlags=0x000320aa\nFileSortMode=0x3\nStateWindowFrame=0,0,923,616,0x6181f5fa\n_StateWindow=0,0,904,618,0x00000118,'C:\\projects\\redalert\\code\\bfile.mak',240,7,244,28,20,0,249,26,32,176,8,4294967295,4294967295,1,10,'',12,255,48,0,4,243,0,0,241,252,249,1731,4,400,0,246,252,245,242,240,240,240,240,240,0,0,253,224,252,1720,1,208\n_StateBuffer='C:\\projects\\redalert\\code\\bfile.mak',0x0400048e,1731,4,25,'4 7','',0x0,'',1,72\n_StateBuffer='C:\\projects\\redalert\\code\\CONQUER.CPP',0x0c00058e,113,11,25,'4 7','',0x0,'',1,72\n_StateBuffer='C:\\projects\\redalert\\code\\INIT.CPP',0x0400058e,547,1,25,'4 7','',0x0,'',1,72\n_StateBuffer='C:\\projects\\redalert\\code\\SCENARIO.CPP',0x0400058e,1027,4,25,'4 7','',0x0,'',1,72\n_StateBuffer='C:\\projects\\redalert\\code\\IDATA.CPP',0x0400058e,20,6,25,'4 7','',0x0,'',1,72\n_StateHistory=FILELIST,'C:\\projects\\redalert\\code\\CONQUER.H','C:\\projects\\redalert\\code\\DISPLAY.CPP','C:\\projects\\redalert\\code\\IDATA.CPP','C:\\projects\\redalert\\code\\VERSION.CPP','C:\\projects\\redalert\\code\\SCENARIO.CPP','C:\\projects\\redalert\\code\\STARTUP.CPP','C:\\projects\\redalert\\code\\CONQUER.CPP','C:\\projects\\redalert\\code\\INIT.CPP','C:\\projects\\redalert\\code\\bfile.mak'\n_StateHistory=SEARCH,'Goodie_Check','selection','GNRL','ENEMY_S','TXT_ENEMY_SOLDIER','Force_CD_A','Read_Scenario','Start_Scenario','Force_CD','TUTORI'\n_StateHistory=REPLACE,'index','coord','Ukraine','r0','obj','MAP_CELL_W','} else {',') {','PCOLOR_DIALOG_BLUE','difficulty'\n_StateHistory=XMACRO,'ShowVisibles','Visibles 1','Visibles on','Visibles 0','Visibles true','Visibles','LoadLibrary westwood.dll','load westwood.dll','loadlib westwood.dll','sort'\n_StateHistory=XSYMBOL,'Stop','Emergency_Exit','new','Scan','CCINIClass','Process','bool','if','Force_CD_Available','Set_Search_Drives'\n_StateHistory=EDITFILE,'map.cpp','i:\\projects\\redalert\\code\\map.cpp','cell.cpp','conquer.h','idata.cpp','version.cpp','scenario.cpp','init.cpp','conquer.cpp','bfile.mak'\n_StateHistory=DIRECTORY,'C:\\PROJECTS\\C&Czero\\code','c:\\projects\\redalert\\code'\n_StateHistory=GOTOMARK,'1','3'\n_StateHistory=OUTNAME,'lzwstraw.h','lzwstraw.cpp','lzwpipe.h','lzwpipe.cpp','c:\\test.ini'\n_StateHistory=GOTOLINE,'1365','1460','264','5724','5742','152','3820','1904','169','2633'\n_StateHistory=DIFFFILE,'C:\\projects\\redalert\\code\\y\\SCENARIO.CPP','C:\\projects\\redalert\\code\\y\\TECHNO.CPP','C:\\projects\\redalert\\code\\v\\language.h','C:\\projects\\redalert\\code\\LANGUAGE.H','C:\\projects\\redalert\\code\\v\\techno.cpp','C:\\projects\\redalert\\code\\TECHNO.CPP','C:\\projects\\redalert\\code\\CRATE.CPP','I:\\PROJECTS\\RedAlert\\code\\Crate.cpp','C:\\projects\\redalert\\code\\CELL.CPP','i:\\projects\\redalert\\code\\CELL.CPP'\n_StateMark=MARK_GLOBAL,1,'C:\\projects\\redalert\\code\\INIT.CPP',547,1,0,'',0\n\n[Editor]\nClipboardSetTermStr='\\r\\n',0\nClipboardEnableTermStr=1\nClipboardSetSepStr='\\r\\n',0\nClipboardEnableSepStr=1\nScrapSetCount=1\nVCSProject=''\nVCSProjectPath=''\nVCSProjectLocalPath=''\n_RestoreSysFlags=0x62c9f5fa, 0xfffffffc\n\n[Compiler]\nTagSetCmd='${HOME}${WTAGS} -oc -d -t${TAGFILE}.tag -p${TAGFILE}.ptg',0x8000060\nBrowseSetFile='C:\\PROJECTS\\redalert\\code\\ra95.ptg'\nTagSetFile='C:\\PROJECTS\\redalert\\code\\ra95.tag'\nCompilerAddCmd='Microsoft Assembler','ftee masm -w2 -zi %r%e;',1073741824,'',0,'',16,'',16,'',0,'',0,'_MicrosoftErrorInfo','','','','%v%p'\nCompilerAddResponse='Microsoft Assembler',\nCompilerAddCmd='Borland C++','ftee bcc -S %r.c',1073741824,'',0,'ftee make %r.obj',16,'ftee make %r.obj',16,'',0,'',0,'_BorlandCppErrorInfo','','','','%v%p'\nCompilerAddResponse='Borland C++',\nCompilerAddCmd='Borland Turbo Assembler','ftee make %r.obj',1073741824,'',0,'ftee make %r.obj',16,'',16,'',0,'',0,'_TasmErrorInfo','','','','%v%p'\nCompilerAddResponse='Borland Turbo Assembler',\nCompilerAddCmd='$_cw_proj_hash_$','',1073741825,'',1,'ftee wmake WIN32=1 %b.obj',497,'ftee wmake',497,'ftee joemake',209,'r.bat cheater -xm',224,'_NMakeErrorInfo','_MicrosoftErrorInfo','_ErrorInfoParser Microsoft','proj.err','%x'\nCompilerAddResponse='$_cw_proj_hash_$',\nCompilerAddCmd='Microsoft C','ftee cl -c -AL -Gsw -Ow -Zpe  %r%e',1073741824,'',0,'',16,'',16,'',0,'',0,'_MicrosoftErrorInfo','','','','%v%p'\nCompilerAddResponse='Microsoft C',\nCompilerAddCmd='Default Project','',1073741824,'',0,'ftee make',16,'ftee make',16,'',0,'',0,'_ErrorInfoDefault','','','proj.err','%v%p'\nCompilerAddResponse='Default Project',\nCompilerAddCmd='Zortech C++','ftee ztc -a -b -c -g -ml -W %r%e',1073741824,'',0,'',16,'',16,'',0,'',0,'_ZortechCppErrorInfo','','','','%v%p'\nCompilerAddResponse='Zortech C++',\nCompilerAddCmd='Script','ftee make %r.inf',1073741824,'',0,'ftee make',16,'ftee make',16,'',0,'',0,'_BorlandCppErrorInfo','','','',''\nCompilerAddResponse='Script',\nCompilerAddCmd='Microsoft C(NT-i386)','${FTEE} cl -DSTRICT -c -W3 -G3 -D_X86_=1 -DWIN32 %r%e',1073741936,'${FTEE} cl -DSTRICT -c -W3 -G3 -D_X86_=1 -DWIN32 %r%e',112,'',144,'',144,'',0,'',0,'_MicrosoftErrorInfo','','','',''\nCompilerAddResponse='Microsoft C(NT-i386)',\nCompilerNewExt=.htm\nCompilerAssign='Borland C++','.scr'\nCompilerNewExt=.bas\nCompilerAssign='Borland C++','.int'\nCompilerAssign='Borland C++','.c'\nCompilerNewExt=.prg\nCompilerNewExt=.pas\nCompilerAssign='Microsoft C','.h'\nCompilerNewExt=.ini\nCompilerNewExt=.html\nCompilerAssign='Borland C++','.cpp'\nCompilerAssign='Default Project','.*'\nCompilerAssign='Microsoft C(NT-i386)','.cxx'\nCompilerNewExt=.txt\nCompilerAssign='Borland Turbo Assembler','.asm'\nCompilerAssign='Microsoft C(NT-i386)','.hpp'\n\n[Project]\nConfigSetLinkDBFilename='D:\\CW32\\cwright.ldb'\nConfigSetSymbolDBFilename='D:\\CW32\\cwright.sbl'\nConfigSetMarkDBFilename='D:\\CW32\\cwright.mrk'\nEditSetPath=''\n\n[VersionControl:PVCS]\nVCSSetCmd=VCS_CHECKIN_ID,'put -n -T@%Q -M@%Q %b%e',0x8000040\nVCSSetCmd=VCS_CHECKINLOCK_ID,'put -n -T@%Q -M@%Q -l %b%e',0x8000040\nVCSSetCmd=VCS_CHECKOUT_ID,'i:\\vss\\ss.exe Get %b%e',0x8000040\nVCSSetCmd=VCS_CHECKOUTLOCK_ID,'i:\\vss\\ss.exe Checkout %b%e',0x8000040\nVCSSetCmd=VCS_CHECKLOCK_ID,'vcs -l %b%e',0x8000040\nVCSSetCmd=VCS_CHECKUNLOCK_ID,'vcs -u %b%e',0x8000040\nVCSSetCmd=VCS_CHECKLABEL_ID,'vcs -v${VCSLABEL} %b%e',0x8000040\nVCSSetCmd=VCS_CHECKLOG_ID,'vlog %b%e',0x8000040\nVCSSetCmd=VCS_CHECKPROP_ID,'vlog -b %b%e',0x8000040\nVCSSetCmd=VCS_CHECKDIFF_ID,'vdiff -r %b%e',0x8000040\nVCSSetCmd=VCS_CHECKMENU_ID,'pvcswinu',0x8000000\n"
  },
  {
    "path": "CODE/RADAR.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RADAR.CPP 3     3/12/97 2:35p Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RADAR.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : September 16, 1996 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Get_Multi_Color -- Get the multi color offset number                                      *\n *   RadarClass::AI -- Processes radar input (non-tactical).                                   *\n *   RadarClass::Cell_On_Radar -- Determines if a cell is currently visible on radar.          *\n *   RadarClass::Click_Cell_Calc -- Determines what cell the pixel coordinate is over.         *\n *   RadarClass::Click_In_Radar -- Check to see if a click is in radar map                     *\n *   RadarClass::Click_In_Radar -- Converts a radar click into cell X and Y coordinate.        *\n *   RadarClass::Draw_It -- Displays the radar map of the terrain.                             *\n *   RadarClass::Draw_Names -- draws players' names on the radar map                           *\n *   RadarClass::Get_Jammed -- Fetch the current radar jammed state for the player.            *\n *   RadarClass::Init_Clear -- Sets the radar map to a known state                             *\n *   RadarClass::Is_Radar_Active -- Determines if the radar map is currently being displayed.  *\n *   RadarClass::Is_Radar_Existing -- Queries to see if radar map is available.                *\n *   RadarClass::Is_Zoomable -- Determines if the map can be zoomed.                           *\n *   RadarClass::Map_Cell -- Updates radar map when a cell becomes mapped.                     *\n *   RadarClass::One_Time -- Handles one time processing for the radar map.                    *\n *   RadarClass::Player_Names -- toggles the Player-Names mode of the radar map                *\n *   RadarClass::Plot_Radar_Pixel -- Updates the radar map with a terrain pixel.               *\n *   RadarClass::RTacticalClass::Action -- I/O function for the radar map.                     *\n *   RadarClass::RadarClass -- Default constructor for RadarClass object.                      *\n *   RadarClass::Radar_Activate -- Controls radar activation.                                  *\n *   RadarClass::Radar_Anim -- Renders current frame of radar animation                        *\n *   RadarClass::Radar_Cursor -- Adjust the position of the radar map cursor.                  *\n *   RadarClass::Radar_Pixel -- Mark a cell to be rerendered on the radar map.                 *\n *   RadarClass::Radar_Position -- Returns with the current position of the radar map.         *\n *   RadarClass::Refresh_Cells -- Intercepts refresh request and updates radar if needed       *\n *   RadarClass::Render_Infantry -- Displays objects on the radar map.                         *\n *   RadarClass::Render_Overlay -- Renders an icon for given overlay                           *\n *   RadarClass::Render_Terrain -- Render the terrain over the given cell                      *\n *   RadarClass::Set_Map_Dimensions -- Sets the tactical map dimensions.                       *\n *   RadarClass::Set_Radar_Position -- Sets the radar position to center around specified cell.*\n *   RadarClass::Set_Tactical_Position -- Called when setting the tactical display position.   *\n *   RadarClass::Set_Tactical_Position -- Called when setting the tactical display position.   *\n *   RadarClass::Set_Tactical_Position -- Sets the map's tactical position and adjusts radar to*\n *   RadarClass::Zoom_Mode(void) -- Handles toggling zoom on the map                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n//void const * RadarClass::CoverShape;\nRadarClass::RTacticalClass RadarClass::RadarButton;\n\nvoid const * RadarClass::RadarAnim  = NULL;\nvoid const * RadarClass::RadarPulse = NULL;\nvoid const * RadarClass::RadarFrame = NULL;\n\nstatic bool FullRedraw = false;\n\nstatic GraphicBufferClass _IconStage(3,3);\nstatic GraphicBufferClass _TileStage(24,24);\n\n\n/***********************************************************************************************\n * RadarClass::RadarClass -- Default constructor for RadarClass object.                        *\n *                                                                                             *\n *    This default constructor merely sets the radar specific values to default settings. The  *\n *    radar must be deliberately activated in order for it to be displayed.                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/16/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nRadarClass::RadarClass(void) :\n\tIsToRedraw(false),\n\tRadarCursorRedraw(false),\n\tIsPulseActive(false),\n\tRadarPulseFrame(0),\n\tDoesRadarExist(false),\n\tIsRadarActive(false),\n\tIsRadarActivating(false),\n\tIsRadarDeactivating(false),\n\tIsRadarJammed(false),\n\tSpecialRadarFrame(0),\n\tRadarAnimFrame(0),\n\tRadarX(0),\n\tRadarY(0),\n\tRadarCellWidth(0),\n\tRadarCellHeight(0),\n\tRadarCell(0),\n\tBaseX(0),\n\tBaseY(0),\n\tRadarWidth(0),\n\tRadarHeight(0),\n\tIsZoomed(true),\n\tZoomFactor(0),\n\tIsPlayerNames(false),\n\tIsHouseSpy(false),\n\tSpyingOn(HOUSE_SPAIN),\n\tPixelPtr(0)\n{\n}\n\n\n/***********************************************************************************************\n * RadarClass::One_Time -- Handles one time processing for the radar map.                      *\n *                                                                                             *\n *    This routine handles any one time processing required in order for the radar map to      *\n *    function. This actually only requires an allocation of the radar staging buffer. This    *\n *    buffer is needed for those cases where the radar area of the page is being destroyed     *\n *    and it needs to be destroyed.                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure to call this routine only ONCE.                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::One_Time(void)\n{\n\tRadWidth\t\t= 80 * RESFACTOR;\n\tRadHeight \t= 70 * RESFACTOR;\n\tRadX \t\t\t= SeenBuff.Get_Width() - RadWidth;\n\tRadY \t\t\t= 7 * RESFACTOR;\n\tRadPWidth \t= 64 * RESFACTOR;\n\tRadPHeight \t= 64 * RESFACTOR;\n\t#ifdef WIN32\n\t\tRadOffX \t\t= 6;\n\t\tRadOffY \t\t= 7;\n\t\tRadIWidth \t= 128+18;//************\n\t\tRadIHeight\t= 128+2;//************\n\t#else\n\t\tRadOffX \t\t= 4;\n\t\tRadOffY \t\t= 1;\n\t\tRadIWidth \t= 72;\n\t\tRadIHeight\t= 69;\n\t#endif\n\n\tDisplayClass::One_Time();\n#ifdef OBSOLETE\n\tRadarButton.X\t\t\t= RadX+RadOffX;\n\tRadarButton.Y \t\t\t= RadY+RadOffY;\n\tRadarButton.Width \t= RadIWidth;\n\tRadarButton.Height \t= RadIHeight;\n#else\n\tRadarButton.X\t\t\t= RadX;\n\tRadarButton.Y \t\t\t= RadY;\n\tRadarButton.Width \t= RadWidth;\n\tRadarButton.Height \t= RadHeight;\n#endif\n}\n\n\n/***********************************************************************************************\n * RadarClass::Init_Clear -- Sets the radar map to a known state.                              *\n *                                                                                             *\n *    This routine is used to initialize the radar map at the start of the scenario. It        *\n *    sets the radar map position and starts it in the disabled state.                         *\n *                                                                                             *\n * INPUT:   theater  -- The theater that the scenario is starting (unused by this routine).    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Init_Clear(void)\n{\n\tDisplayClass::Init_Clear();\n\tIsRadarActive\t\t\t= false;\n\tIsToRedraw \t\t\t\t= true;\n\tRadarCursorRedraw    = true;\n\tIsRadarActivating \t= false;\n\tIsRadarDeactivating \t= false;\n\tDoesRadarExist \t\t= false;\n\tPixelPtr \t\t\t\t= 0;\n\tIsPlayerNames\t\t\t= false;\n\n\t/*\n\t** If we have a valid map lets make sure that we set it correctly\n\t*/\n\tif (MapCellWidth || MapCellHeight) {\n#ifdef WIN32\n\t\tIsZoomed = false;\n#else\n\t\tIsZoomed = true;\n#endif\n\t\tZoom_Mode(Coord_Cell(Map.TacticalCoord));\n\t}\n}\n\n\n/***********************************************************************************************\n * RadarClass::Radar_Activate -- Controls radar activation.                                    *\n *                                                                                             *\n *    Use this routine to turn the radar map on or off.                                        *\n *                                                                                             *\n * INPUT:   control  -- What to do with the radar map:                                         *\n *                      0 = Turn radar off.                                                    *\n *                      1 = Turn radar on.                                                     *\n *                      2 = Remove Radar Gadgets                                               *\n *                      3 = Add Radar Gadgets                                                  *\n *                      4 = Remove radar.                                                      *\n *                      -1= Toggle radar on or off.                                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the radar map already on?                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/11/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Radar_Activate(int control)\n{\n\tbool old = IsRadarActive;\n\n\tswitch (control) {\n\n\t\t/*\n\t\t** Toggle the state of the radar map on or off.\n\t\t*/\n\t\tcase -1:\n\t\t\t{\n\t\t\t\tint temp = (IsRadarActive == false);\n\t\t\t\tif (temp) {\n\t\t\t\t\tRadar_Activate(1);\n\t\t\t\t} else {\n\t\t\t\t\tRadar_Activate(0);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t** Turn the radar map off properly.\n\t\t*/\n\t\tcase 0:\n\t\t\tif (Map.IsSidebarActive) {\n\t\t\t\tif (IsRadarActive && !IsRadarDeactivating) {\n\t\t\t\t\tSound_Effect(VOC_RADAR_OFF);\n\t\t\t\t\tIsRadarDeactivating = true;\n\t\t\t\t\tIsRadarActive = false;\n\t\t\t\t\tif (IsRadarActivating == true) {\n\t\t\t\t\t\tIsRadarActivating = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tRadarAnimFrame = RADAR_ACTIVATED_FRAME;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tRadar_Activate(2);\n\t\t\t}\n\t\t\treturn(old);\n\n\t\tcase 1:\n\t\t\tif (Map.IsSidebarActive) {\n\t\t\t\tif (!IsRadarActivating && !IsRadarActive) {\n\t\t\t\t\tSound_Effect(VOC_RADAR_ON);\n\t\t\t\t\tIsRadarActivating = true;\n\t\t\t\t\tif (IsRadarDeactivating == true) {\n\t\t\t\t\t\tIsRadarDeactivating = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (DoesRadarExist) {\n\t\t\t\t\t\t\tRadarAnimFrame = MAX_RADAR_FRAMES;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tRadarAnimFrame = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tRadar_Activate(3);\n\t\t\t}\n\t\t\treturn(old);\n\n\t\tcase 2:\n\t\t\tif (Session.Type==GAME_NORMAL) {\n\t\t\t\tSidebarClass::Zoom.Disable();\n\t\t\t} else {\n\t\t\t\tSidebarClass::Zoom.Enable();\n\t\t\t}\n\t\t\tIsRadarActive = false;\n\t\t\tIsRadarActivating = false;\n\t\t\tIsRadarDeactivating = false;\n\t\t\tbreak;\n\n\t\tcase 3:\n\t\t\tif (Session.Type == GAME_NORMAL && Is_Zoomable()) {\n\t\t\t\tSidebarClass::Zoom.Enable();\n\t\t\t}\n\t\t\tIsRadarActive = true;\n\t\t\tIsRadarActivating = false;\n\t\t\tIsRadarDeactivating = false;\n\t\t\tbreak;\n\n\t\tcase 4:\n\t\t\tIsRadarActive\t\t\t= false;\n\t\t\tIsRadarActivating\t\t= false;\n\t\t\tIsRadarDeactivating\t= false;\n\t\t\tDoesRadarExist \t\t= false;\n\t\t\tFlag_To_Redraw(false);\n\t\t\tIsToRedraw = true;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tif (IsRadarActive != old) {\n\t\tIsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\t}\n\tFullRedraw = IsRadarActive;\n\treturn(old);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Draw_It -- Displays the radar map of the terrain.                               *\n *                                                                                             *\n *    This is used to display the radar map that appears in the lower                          *\n *    right corner. The main changes to this map are the vehicles and                          *\n *    structure pixels.                                                                        *\n *                                                                                             *\n * INPUT:      none                                                                            *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/24/1991 JLB : Created.                                                                 *\n *   05/08/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nvoid RadarClass::Draw_It(bool forced)\n{\n\tDisplayClass::Draw_It(forced);\n\n\tstatic char * _hiresradarnames[]={\n\t\t\"natoradr.shp\",\t//HOUSE_SPAIN,\n\t\t\"natoradr.shp\",   //HOUSE_GREECE,\n\t\t\"ussrradr.shp\",   //HOUSE_USSR,\n\t\t\"natoradr.shp\",   //HOUSE_ENGLAND,\n\t\t\"ussrradr.shp\",   //HOUSE_UKRAINE,\n\t\t\"natoradr.shp\",   //HOUSE_GERMANY,\n\t\t\"natoradr.shp\",   //HOUSE_FRANCE,\n\t\t\"natoradr.shp\",\t//HOUSE_TURKEY,\n\t\t\"natoradr.shp\",\t//HOUSE_GOOD\n\t\t\"ussrradr.shp\",\t//HOUSE_BAD\n\t};\n\tstatic char * _frames[]={\n\t\t\"nradrfrm.shp\",   //HOUSE_SPAIN,\n\t\t\"nradrfrm.shp\",   //HOUSE_GREECE,\n\t\t\"uradrfrm.shp\",   //HOUSE_USSR,\n\t\t\"nradrfrm.shp\",   //HOUSE_ENGLAND,\n\t\t\"uradrfrm.shp\",   //HOUSE_UKRAINE,\n\t\t\"nradrfrm.shp\",   //HOUSE_GERMANY,\n\t\t\"nradrfrm.shp\",   //HOUSE_FRANCE,\n\t\t\"nradrfrm.shp\",   //HOUSE_TURKEY,\n\t\t\"nradrfrm.shp\",\t//HOUSE_GOOD\n\t\t\"uradrfrm.shp\",\t//HOUSE_BAD\n\t};\n\n\tint radarforced = 0;\n\n\t/*\n\t**\tDon't perform any rendering if none is requested.\n\t*/\n\tif (!forced && !IsToRedraw && !FullRedraw) return;\n\n\tBStart(BENCH_RADAR);\n\n\tstatic HousesType _house = HOUSE_NONE;\n\n\tif (PlayerPtr->ActLike != _house) {\n\t\tchar name[_MAX_FNAME + _MAX_EXT];\n\n//\t\tstrcpy(name, \"NATORADR.SHP\" );\n//\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\tstrcpy(name, _hiresradarnames[PlayerPtr->ActLike]);\n//\t\t}\n\t\t#ifndef NDEBUG\n\t\t\tRawFileClass file(name);\n\t\t\tif (file.Is_Available()) {\n\t\t\t\tRadarAnim = Load_Alloc_Data(file);\n\t\t\t} else {\n\t\t\t\tRadarAnim = MFCD::Retrieve(name);\n\t\t\t}\n\t\t\tstrcpy(name, \"PULSE.SHP\");\n\t\t\tRawFileClass file2(name);\n\t\t\tif (file2.Is_Available()) {\n\t\t\t\tRadarPulse = Load_Alloc_Data(file2);\n\t\t\t} else {\n\t\t\t\tRadarPulse = MFCD::Retrieve(name);\n\t\t\t}\n\t\t\tstrcpy(name, _frames[PlayerPtr->ActLike]);\n\t\t\tRawFileClass file3(name);\n\t\t\tif (file3.Is_Available()) {\n\t\t\t\tRadarFrame = Load_Alloc_Data(file3);\n\t\t\t} else {\n\t\t\t\tRadarFrame = MFCD::Retrieve(_frames[PlayerPtr->ActLike]);\n\t\t\t}\n\t\t#else\n\t\t\tRadarAnim = MFCD::Retrieve(name);\n\t\t\tstrcpy(name, \"PULSE.SHP\");\n\t\t\tRawFileClass file3(name);\n\t\t\tif (file3.Is_Available()) {\n\t\t\t\tRadarPulse = Load_Alloc_Data(file3);\n\t\t\t} else {\n\t\t\t\tRadarPulse = MFCD::Retrieve(name);\n\t\t\t}\n\t\tRadarFrame = MFCD::Retrieve(_frames[PlayerPtr->ActLike]);\n\t\t#endif\n\t\t_house = PlayerPtr->ActLike;\n\t}\n\n\t/*\n\t** If in player name mode, just draw player names\n\t*/\n\tif (IsPlayerNames) {\n\t\tDraw_Names();\n\t\tIsToRedraw = false;\n\t\tBEnd(BENCH_RADAR);\n\t\treturn;\n\t}\n\n\t/*\n\t** If in spy-on-radar facility mode, draw the appropriate info.\n\t*/\n\tif (IsHouseSpy) {\n\t\tIsToRedraw = false;\n\t\tif (Draw_House_Info()) {\n\t\t\tBEnd(BENCH_RADAR);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (IsRadarActivating || IsRadarDeactivating || IsRadarJammed) {\n\t\tRadar_Anim();\n\t\tMap.Repair.Draw_Me(true);\n\t\tMap.Upgrade.Draw_Me(true);\n\t\tMap.Zoom.Draw_Me(true);\n\t\tIsToRedraw = false;\n\t\tBEnd(BENCH_RADAR);\n\t\treturn;\n\t}\n\n\tif (Map.IsSidebarActive) {\n\t\tif (IsRadarActive) {\n\n\t\t\t/*\n\t\t\t**\tIf only a few of the radar pixels need to be redrawn, then find and redraw\n\t\t\t**\tonly these.\n\t\t\t*/\n\t\t\tif (!forced && IsToRedraw && !FullRedraw && !IsPulseActive) {\n\t\t\t\tIsToRedraw = false;\n\n\t\t\t\tif (PixelPtr) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tRender all pixels in the \"to redraw\" stack.\n\t\t\t\t\t*/\n\t\t\t\t\tif (LogicPage->Lock()) {\n\t\t\t\t\t\tfor (int index = 0; index < PixelPtr; index++) {\n\t\t\t\t\t\t\tCELL cell = PixelStack[index];\n\t\t\t\t\t  \t\tif (Cell_On_Radar(cell)) {\n\t\t\t\t\t\t\t\t(*this)[cell].IsPlot = false;\n\t\t\t\t\t\t\t\tPlot_Radar_Pixel(cell);\n\t\t\t\t\t\t\t\tRadarCursorRedraw |= (*this)[cell].IsRadarCursor;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tLogicPage->Unlock();\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tRefill the stack if there is pending pixels yet to be plotted.\n\t\t\t\t\t**\tThis should only process in sections for speed reasons\n\t\t\t\t\t*/\n\t\t\t\t\tif (PixelPtr == PIXELSTACK) {\n\t\t\t\t\t\tPixelPtr = 0;\n\n\t\t\t\t\t\tfor (int y = 0; y < MapCellHeight; y++) {\n\t\t\t\t\t\t\tfor (int x = 0; x < MapCellWidth; x++) {\n\t\t\t\t\t\t\t\tCELL cell = XY_Cell(MapCellX + x, MapCellY + y);\n\t\t\t\t\t\t\t  \tif (Cell_On_Radar(cell)) {\n\n\t\t\t\t\t\t\t\t\tif ((*this)[cell].IsPlot) {\n\t\t\t\t\t\t\t\t\t\tPixelStack[PixelPtr++] = cell;\n\t\t\t\t\t\t\t\t\t\tIsToRedraw = true;\n\t\t\t\t\t\t\t\t\t\tif\t(PixelPtr == PIXELSTACK) break;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif\t(PixelPtr == PIXELSTACK) break;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tPixelPtr = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tRadar_Cursor(RadarCursorRedraw);\n\n\t\t\t} else {\n\n#ifdef WIN32\n\t\t\t\tGraphicViewPortClass * oldpage\t= Set_Logic_Page(HidPage);\n#else\n\t\t\t\tGraphicBufferClass * oldpage\t= Set_Logic_Page(HidPage);\n#endif\n\n\t\t\t\tCC_Draw_Shape(RadarFrame, 1, RadX, RadY+(1 * RESFACTOR), WINDOW_MAIN, SHAPE_NORMAL);\n\t\t\t\tif (BaseX || BaseY) {\n\n\t\t\t\t\tif (!IsZoomed && BaseX && BaseY && RadarWidth< (RadIWidth-1) && RadarHeight < (RadIHeight-1)) {\n#ifdef WIN32\n\t\t\t\t\t\tLogicPage->Draw_Rect(RadX + RadOffX + BaseX -1,\n\t\t\t\t\t\t\t\t\t\t\t\t\tRadY + RadOffY + BaseY -1,\n\t\t\t\t\t\t\t\t\t\t\t\t\tRadX + RadOffX + BaseX + RadarWidth,\n//\t\t\t\t\t\t\t\t\t\t\t\t\tRadX + RadOffX + BaseX + RadarWidth +1,\n\t\t\t\t\t\t\t\t\t\t\t\t\tRadY + RadOffY + BaseY + RadarHeight,\n//\t\t\t\t\t\t\t\t\t\t\t\t\tRadY + RadOffY + BaseY + RadarHeight +1,\n\t\t\t\t\t\t\t\t\t\t\t\t\tWHITE);\n#endif\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tLogicPage->Fill_Rect(\tRadX + RadOffX,\n\t\t\t\t\t\t\t\t\t\t\t\t\tRadY + RadOffY,\n\t\t\t\t\t\t\t\t\t\t\t\t\tRadX + RadOffX + RadIWidth - 1,\n\t\t\t\t\t\t\t\t\t\t\t\t\tRadY + RadOffY + RadIHeight - 1,\n\t\t\t\t\t\t\t\t\t\t\t\t\tBLACK);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Draw the entire radar map.\n\t\t\t\t*/\n\t\t\t\tif (LogicPage->Lock()) {\n\t\t\t\t\tfor (int index = 0; index < MAP_CELL_TOTAL; index++) {\n\t\t\t\t\t\tif (In_Radar(index) && Cell_On_Radar(index)) {\n\t\t\t\t\t\t\tPlot_Radar_Pixel(index);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (IsPulseActive) {\n\t\t\t\t\t\tCC_Draw_Shape(RadarPulse, RadarPulseFrame++, RadX + RadOffX, RadY+1*RESFACTOR, WINDOW_MAIN, SHAPE_NORMAL);\n\t\t\t\t\t}\n\t\t\t\t\tLogicPage->Unlock();\n\t\t\t\t}\n\n\t\t\t\tRadar_Cursor(true);\n\t\t\t\tFullRedraw = false;\n\t\t\t\tIsToRedraw = false;\n\n\t\t\t\tMap.Repair.Draw_Me(true);\n\t\t\t\tMap.Upgrade.Draw_Me(true);\n\t\t\t\tMap.Zoom.Draw_Me(true);\n\n\t\t\t\tif (oldpage == &SeenBuff) {\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tLogicPage->Blit(SeenBuff, RadX, RadY, RadX, RadY, RadWidth, RadHeight);\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t}\n\n\t\t\t\tSet_Logic_Page(oldpage);\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf the radar is not active, then only draw the cover plate if forced to do so.\n\t\t\t*/\n\t\t\tint val = (DoesRadarExist) ?  MAX_RADAR_FRAMES : 0;\n\t\t\tCC_Draw_Shape(RadarAnim, val, RadX, RadY + (1 * RESFACTOR), WINDOW_MAIN, SHAPE_NORMAL);\n\t\t\tFullRedraw = false;\n\t\t\tIsToRedraw = false;\n\n\t\t\t/*\n\t\t\t**\tDisplay the country name on the cover plate when in multi play only.\n\t\t\t*/\n\t\t\tif (Session.Type != GAME_NORMAL) {\n\t\t\t\tFancy_Text_Print(Text_String(HouseTypeClass::As_Reference(PlayerPtr->ActLike).Full_Name()), RadX+RadWidth/2, RadY+RadHeight-10*RESFACTOR, &ColorRemaps[PlayerPtr->RemapColor], TBLACK, TPF_CENTER|TPF_TEXT|TPF_DROPSHADOW);\n\t\t\t}\n\n\t\t\tMap.Repair.Draw_Me(true);\n\t\t\tMap.Upgrade.Draw_Me(true);\n\t\t\tMap.Zoom.Draw_Me(true);\n\n\t\t}\n\n\t}\n\tBEnd(BENCH_RADAR);\n}\n\n\n/***************************************************************************\n * RadarClass::Render_Terrain -- Render the terrain over the given cell    *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/12/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid RadarClass::Render_Terrain(CELL cell, int x, int y, int size)\n{\n\tTerrainClass\t* list[4] = {0,0,0,0};\n\tint\t\t\t\tlistidx = 0;\n\tint\t\t\t\tlp,lp2;\n\n\n\tObjectClass * obj = Map[cell].Cell_Occupier();\n\n\t/*\n\t** If the cell is occupied by a terrain type, add it to the sortable\n\t** list.\n\t*/\n\tif (obj && obj->What_Am_I() == RTTI_TERRAIN)\n\t\tlist[listidx++] = (TerrainClass *)obj;\n\n\t/*\n\t** Now loop through all the occupiers and add them to the list if they\n\t** are terrain type.\n\t*/\n\tfor (lp = 0; lp < ARRAY_SIZE(Map[cell].Overlapper); lp ++) {\n\t\tobj = Map[cell].Overlapper[lp];\n\t\tif (obj && obj->What_Am_I() == RTTI_TERRAIN)\n\t\t\tlist[listidx++] = (TerrainClass *)obj;\n\t}\n\n\t/*\n\t** If there are no entries in our list then just get out.\n\t*/\n\tif (!listidx) return;\n\n\t/*\n\t**\tIf there is terrain in this cell then draw a dark pixel to\n\t** represent it.\n\t*/\n\tif (size == 1) {\n\t\tLogicPage->Put_Pixel(x, y, 21);\n//\t\tLogicPage->Put_Pixel(x, y, 60);\n\t\treturn;\n\t}\n\n\t/*\n\t** Sort the list by its sort Y value so that we can render in the proper\n\t** order.\n\t*/\n\tfor (lp = 0; lp < listidx - 1; lp ++) {\n\t\tfor (lp2 = lp + 1; lp2 < listidx; lp2++) {\n\t\t\tif (list[lp]->Sort_Y() > list[lp2]->Sort_Y()) {\n\t\t\t\tTerrainClass * terrain = list[lp];\n\t\t\t\tlist[lp] = list[lp2];\n\t\t\t\tlist[lp2] = terrain;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** loop through the list and take care of rendering the correct icon.\n\t*/\n\tfor (lp = 0; lp < listidx; lp ++) {\n\t\tunsigned char * icon = list[lp]->Radar_Icon(cell);\n\t\tif (!icon) continue;\n#ifdef WIN32\n\t\tBuffer_To_Page(0, 0, 3, 3, icon, _IconStage);\n\t\t_IconStage.Scale(*LogicPage, 0, 0, x, y, 3, 3, ZoomFactor, ZoomFactor, TRUE, (char *)&FadingBrighten[0]);\n#else\n\t\tfor (int lpy = 0; lpy < 3; lpy++) {\n\t\t\tfor (int lpx = 0; lpx < 3; lpx++) {\n\t\t\t\tif (*icon) {\n\t\t\t\t\tLogicPage->Put_Pixel(x + lpx, y + lpy, FadingBrighten[*icon]);\n\t\t\t\t}\n\t\t\t\ticon++;\n\t\t\t}\n\t\t}\n#endif\t//WIN32\n\t}\n}\n\n\n/***********************************************************************************************\n * RadarClass::Render_Infantry -- Displays objects on the radar map.                           *\n *                                                                                             *\n *    This routine will display an object imagery at the location specified according to the   *\n *    condition of the specified cell.                                                         *\n *                                                                                             *\n * INPUT:   cell  -- The cell to use as reference when drawing the radar pixel.                *\n *                                                                                             *\n *          x,y   -- The pixel coordinate to render the radar \"pixel\" at.                      *\n *                                                                                             *\n *          size  -- The size of the \"pixel\". When zoomed in, this value will be \"3\".          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/17/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Render_Infantry(CELL cell, int x, int y, int size)\n{\n\tObjectClass * obj;\n\n\tobj = (ObjectClass *)Map[cell].Cell_Occupier();\n\twhile (obj) {\n\t\tif (obj->Is_Techno() && ((TechnoClass *)obj)->Is_Visible_On_Radar()) {\n\t\t\tint color = ColorRemaps[((InfantryClass *)obj)->House->RemapColor].Bar;\n//\t\t\tint color = ColorRemaps[((InfantryClass *)obj)->House->RemapColor].BrightColor;\n\t\t\tint xoff;\n\t\t\tint yoff;\n\t\t\tint subsize = max(1, size/3);\n\n\t\t\tswitch (obj->What_Am_I()) {\n\t\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t\txoff = (Coord_XLepton(obj->Coord) / (CELL_LEPTON_W/(size+1))) - subsize/2;\n\t\t\t\t\txoff = max(xoff, 0);\n\t\t\t\t\txoff = min(xoff, size-subsize);\n\t\t\t\t\tyoff = (Coord_YLepton(obj->Coord) / (CELL_LEPTON_H/(size+1))) - subsize/2;\n\t\t\t\t\tyoff = max(yoff, 0);\n\t\t\t\t\tyoff = min(yoff, size-subsize);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Draw the infantryman's pixel.  If he's a spy, draw in my house color\n\t\t\t\t\t*/\n\t\t\t\t\tif (*(InfantryClass *)obj == INFANTRY_SPY) {\n\t\t\t\t\t\tcolor = ColorRemaps[PlayerPtr->RemapColor].Bar;\n//\t\t\t\t\t\tcolor = ColorRemaps[PlayerPtr->RemapColor].BrightColor;\n\t\t\t\t\t}\n\t\t\t\t\tLogicPage->Fill_Rect(x+xoff, y+yoff, x+xoff+(subsize-1), y+yoff+(subsize-1), color);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase RTTI_UNIT:\n\t\t\t\tcase RTTI_VESSEL:\n\t\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\t\tLogicPage->Fill_Rect(x, y, x+size-1, y+size-1, color);\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tobj = obj->Next;\n\t}\n\n}\n\n\n/***************************************************************************\n * RadarClass::Render_Overlay -- Renders an icon for given overlay         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid RadarClass::Render_Overlay(CELL cell, int x, int y, int size)\n{\n\t//int lpx,lpy;\n\n\tOverlayType overlay = (*this)[cell].Overlay;\n \tif (overlay != OVERLAY_NONE) {\n\t\tOverlayTypeClass const * otype = &OverlayTypeClass::As_Reference(overlay);\n\n\t\tif (otype->IsRadarVisible) {\n\t\t\tunsigned char * icon = otype->Radar_Icon((*this)[cell].OverlayData);\n\t\t\tif (!icon) return;\n#ifdef WIN32\n\t\t\tBuffer_To_Page(0, 0, 3, 3, icon, _IconStage);\n\t\t\tif (otype->IsTiberium) {\n\t\t\t\tif (size == 1) {\n\t\t\t\t\tLogicPage->Put_Pixel(x, y, DKGREY);\n\n//\t\t\t\t\t_IconStage.Scale(*LogicPage, 0, 0, x, y, 3, 3, size, size, TRUE, (char *)&FadingShade[0]);\n\t\t\t\t} else {\n\t\t\t\t\t_IconStage.Scale(*LogicPage, 0, 0, x, y, 3, 3, size, size, TRUE, (char *)&FadingYellow[0]);\n\t\t\t\t}\n//\t\t\t\t_IconStage.Scale(*LogicPage, 0, 0, x, y, 3, 3, size, size, TRUE, (char *)&FadingGreen[0]);\n//\t\t\t} else {\n//\t\t\t\t_IconStage.Scale(*LogicPage, 0, 0, x, y, 3, 3, size, size, TRUE, (char *)&FadingBrighten[0]);\n\t\t\t}\n\n#else\n\t\t\tfor (int lpy = 0; lpy < size; lpy++) {\n\t\t\t\tfor (int lpx = 0; lpx < size; lpx++) {\n\t\t\t\t\tif (size == 1) icon+=4;\n\t\t\t\t\tif (*icon) {\n\t\t\t\t\t\tif (otype->IsTiberium) {\n\t\t\t\t\t\t\tif (size == 1) {\n\t\t\t\t\t\t\t\tLogicPage->Put_Pixel(x + lpx, y + lpy, DKGREY);\n//\t\t\t\t\t\t\t\tLogicPage->Put_Pixel(x + lpx, y + lpy, FadingShade[*icon]);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tLogicPage->Put_Pixel(x + lpx, y + lpy, FadingYellow[*icon]);\n\t\t\t\t\t\t\t}\n//\t\t\t\t\t\t\tLogicPage->Put_Pixel(x + lpx, y + lpy, FadingGreen[*icon]);\n//\t\t\t\t\t\t} else {\n//\t\t\t\t\t\t\tLogicPage->Put_Pixel(x + lpx, y + lpy, FadingBrighten[*icon]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (size == 1) {\n\t\t\t\t\t\ticon+=5;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ticon++;\n\t\t\t\t\t}\n\t\t\t\t\ticon++;\n\t\t\t\t}\n\t\t\t}\n#endif\t//WIN32\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * RadarClass::Zoom_Mode -- Handles toggling zoom on the map               *\n *                                                                         *\n * INPUT:      none                                                        *\n *                                                                         *\n * OUTPUT:  \tnone                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/29/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid RadarClass::Zoom_Mode(CELL cell)\n{\n\tint map_c_width;\n\tint map_c_height;\n\n\t/*\n\t** Set all of the initial zoom mode variables to the correct\n\t** setting.\n\t*/\n#ifdef WIN32\n\tif (Is_Zoomable()) {\n\t\tIsZoomed\t\t\t\t= !IsZoomed;\n\t} else {\n\t\tIsZoomed = true;\n\t}\n#else\n\tIsZoomed\t\t\t\t= false;\n#endif\n\tBaseX\t\t\t\t\t= 0;\n\tBaseY\t\t\t\t\t= 0;\n\n\t/*\n\t** Figure out exactly what size we need to zoom the map to.\n\t*/\n\tif (!IsZoomed) {\n\t\tint xfactor\t\t\t= RadIWidth / MapCellWidth;\n\t\tint yfactor\t\t\t= RadIHeight / MapCellHeight;\n\t\tZoomFactor\t\t\t= max(min(xfactor, yfactor) , 1);\n\t\tmap_c_width\t\t\t= MapCellWidth;\n\t\tmap_c_height      = MapCellHeight;\n\t} else {\n\t\tZoomFactor\t\t\t= 3;\n//\t\tZoomFactor\t\t\t= 6;\n\t\tmap_c_width\t\t\t= RadIWidth / ZoomFactor;\n\t\tmap_c_height\t\t= RadIHeight / ZoomFactor;\n\t}\n\n\t/*\n\t** Make sure we do not show more cells than are on the map.\n\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n#ifdef WIN32\n\tmap_c_width\t\t\t= min(map_c_width, RadIWidth);\n\tmap_c_width\t\t\t= min(map_c_width, MapCellWidth);\n\tmap_c_height\t\t= min(map_c_height, RadIHeight);\n\tmap_c_height\t\t= min(map_c_height, MapCellHeight);\n#else\n\tmap_c_width\t\t\t= min(map_c_width, 62 * RESFACTOR);\n\tmap_c_width\t\t\t= min(map_c_width, MapCellWidth);\n\tmap_c_height\t\t= min(map_c_height, 62 * RESFACTOR);\n\tmap_c_height\t\t= min(map_c_height, MapCellHeight);\n#endif\n#else\n\tmap_c_width\t\t\t= min(map_c_width, 62 * RESFACTOR);\n\tmap_c_width\t\t\t= min(map_c_width, MapCellWidth);\n\tmap_c_height\t\t= min(map_c_height, 62 * RESFACTOR);\n\tmap_c_height\t\t= min(map_c_height, MapCellHeight);\n#endif\n\n\t/*\n\t** Find the amount of remainder because this will let us calculate\n\t** how to center the thing.\n\t*/\n\tint rem_x \t\t\t= RadIWidth - (map_c_width * ZoomFactor);\n\tint rem_y \t\t\t= RadIHeight - (map_c_height * ZoomFactor);\n\n\t/*\n\t** Finally mark the map so it shows just as much as it is supposed\n\t** to.\n\t*/\n\tBaseX\t\t\t\t\t= rem_x / 2;\n\tBaseY\t\t\t\t\t= rem_y / 2;\n\tRadarCellWidth \t= map_c_width;\n\tRadarCellHeight \t= map_c_height;\n\tRadarWidth\t\t\t= RadIWidth - rem_x;\n\tRadarHeight\t\t\t= RadIHeight - rem_y;\n\n\t/*\n\t** Set the radar position to the current cell.\n\t*/\n\tSet_Radar_Position(cell);\n\n\t/*\n\t** When zoom mode changes then we need to redraw the radar\n\t** area.\n\t*/\n\tIsToRedraw = true;\n\n\t/*\n\t** Notify the map that we need to redraw a portion\n\t*/\n\tFlag_To_Redraw(false);\n\n\t/*\n\t** Since we have made a vast change we must redraw everything\n\t*/\n\tFullRedraw = true;\n}\n\n\n/***********************************************************************************************\n * RadarClass::Is_Zoomable -- Determines if the map can be zoomed.                             *\n *                                                                                             *\n *    This will check to see if the zoomed mode of the map would be just the same size as      *\n *    the non-zoomed mode. If this is true, then zooming would have no effect, so return       *\n *    false indicating that zooming is not allowed.                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is zooming allowed?                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Is_Zoomable(void) const\n{\n\tint xfactor = RadIWidth / MapCellWidth;\n\tint yfactor = RadIHeight / MapCellHeight;\n\tint factor = max(min(xfactor, yfactor) , 1);\n\tif (factor == 3) {\n\t\treturn(false);\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Plot_Radar_Pixel -- Updates the radar map with a terrain pixel.                 *\n *                                                                                             *\n *    This will update the radar map with a pixel. It is used to display                       *\n *    vehicle positions on the radar map.                                                      *\n *                                                                                             *\n * INPUT:   unit  -- Pointer to unit to render at the given position. If                       *\n *                   NULL is passed in, then the underlying terrain is                         *\n *                   displayed instead.                                                        *\n *                                                                                             *\n *          pos   -- Position on the map to update.                                            *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   This routine does NOT hide the mouse. It is up to you to                        *\n *             do so.                                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1991 JLB : Created.                                                                 *\n *   06/21/1991 JLB : Large blips for units & buildings.                                       *\n *   02/14/1994 JLB : Revamped.                                                                *\n *   04/17/1995 PWG : Created.                                                                 *\n *   04/18/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Plot_Radar_Pixel(CELL cell)\n{\n\tif (cell == -1) cell = 1;\n\n\tint\tx,y;\t\t\t\t\t// Coordinate of cell location.\n\n\t/*\n\t**\tPerform any clipping on the cell coordinate.\n\t*/\n\tif (!IsRadarActive || (unsigned)cell > MAP_CELL_TOTAL) {\n\t\treturn;\n\t}\n\n\tif (!In_Radar(cell) || !Cell_On_Radar(cell)) {\n\t\treturn;\n\t}\n\n\t/*\n\t** If we are zoomed in then calculate the pixel based off of the portion\n\t** of the map the radar is viewing.\n\t*/\n\tx = Cell_X(cell) - RadarX;\n\ty = Cell_Y(cell) - RadarY;\n\tif ((unsigned)x >= RadarCellWidth || (unsigned)y >= RadarCellHeight) {\n\t\treturn;\n\t}\n\n\tbool usjamming = false;\n\tif (LogicPage->Lock()) {\n\t\tCellClass * cellptr = &(*this)[cell];\n \t\tx = RadX + RadOffX + BaseX + (x * ZoomFactor);\n \t\ty = RadY + RadOffY + BaseY + (y * ZoomFactor);\n\n \t\t/*\n \t\t**\tDetermine what (if any) vehicle or unit should be rendered in this blip.\n \t\t*/\n\t\tint color=TBLACK;\t\t// Color of the pixel to plot.\n\t\tint housebit = (1 << PlayerPtr->Class->House);\n\t\tint celljammed = (*this)[cell].Jammed;\n\t\tint jammed = celljammed & (0xFFFF - housebit);\n \t\tif (!jammed && ((*this)[cell].IsMapped || Debug_Unshroud)) {\n// \t\tif (!jammed && ((*this)[cell].IsVisible || Debug_Unshroud)) {\n \t\t\tcolor = cellptr->Cell_Color(true);\n\t\t\tif ( (celljammed & housebit) && (color == TBLACK) ) {\n\t\t\t\tcolor = BLACK;//FadingWayDark[color];\n\t\t\t\tusjamming = true;\n\t\t\t}\n \t\t} else  {\n \t\t\tcolor = BLACK;\n \t\t}\n\n \t\t/*\n \t\t**\tIf no color override occurs for this cell, then render the underlying\n \t\t**\tterrain.\n \t\t*/\n\t\tif (color == TBLACK) {\n\t\t\tif (ZoomFactor > 1) {\n\t\t\t\tvoid const * ptr = NULL;\n\t\t\t\tint icon;\n\n\t\t\t\t/*\n\t\t\t\t**\tFetch the template pointer and template icon number for the\n\t\t\t\t**\tspecified cell.\n\t\t\t\t*/\n\t\t\t\tif (cellptr->TType != TEMPLATE_NONE && cellptr->TType != 255) {\n\t\t\t\t\tptr = TemplateTypeClass::As_Reference(cellptr->TType).Get_Image_Data();\n\t\t\t\t\ticon = cellptr->TIcon;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the template pointer is still NULL, then this means either a clear\n\t\t\t\t**\ttemplate or an illegal one. Setup for a clear template.\n\t\t\t\t*/\n\t\t\t\tif (ptr == NULL) {\n\t\t\t\t\tptr = TemplateTypeClass::As_Reference(TEMPLATE_CLEAR1).Get_Image_Data();\n\t\t\t\t\ticon = cellptr->Clear_Icon();\n\t\t\t\t}\n\n\t\t\t\tIconsetClass const * iconset = (IconsetClass const *)ptr;\n\t\t\t\tunsigned char const * icondata = iconset->Icon_Data();\n\n\n\t\t\t\t/*\n\t\t\t\t**\tConvert the logical icon number into the actual icon number.\n\t\t\t\t*/\n\t\t\t\ticon &= 0x00FF;\n\t\t\t\ticon = *(iconset->Map_Data() + icon);\n\n\t\t\t\tunsigned char * data = (unsigned char *)icondata + icon*(24*24);\n\t\t\t\tBuffer_To_Page(0, 0, 24, 24, data, _TileStage);\n\t\t\t\t_TileStage.Scale(*LogicPage, 0, 0, x, y, 24, 24, ZoomFactor, ZoomFactor, TRUE);\n\t\t\t} else {\n//\t\t\t\tLogicPage->Fill_Rect(x, y, x+ZoomFactor-1, y+ZoomFactor-1, cellptr->Cell_Color(false));\n/*BG*/\t\tLogicPage->Put_Pixel(x, y, cellptr->Cell_Color(false));\n\t\t\t}\n\t\t} else {\n\t\t\tLogicPage->Fill_Rect(x, y, x+ZoomFactor-1, y+ZoomFactor-1, color);\n///*BG*/\t\tLogicPage->Put_Pixel(x, y, color);\n\t\t}\n\t\tif (color != BLACK) {\n\t\t\tRender_Overlay(cell, x, y, ZoomFactor);\n\t \t\tRender_Terrain(cell, x, y, ZoomFactor);\n\t\t\tRender_Infantry(cell, x, y, ZoomFactor);\n\t\t} else {\n\t\t\tif(usjamming) {\n\t\t\t\tRender_Infantry(cell, x, y, ZoomFactor);\n\t\t\t}\n\t\t}\n\t\tLogicPage->Unlock();\n\t}\n}\n\n\n/***********************************************************************************************\n * RadarClass::Radar_Pixel -- Mark a cell to be rerendered on the radar map.                   *\n *                                                                                             *\n *    This routine is used to inform the system that a pixel needs to be                       *\n *    rerendered on the radar map. The pixel(s) will be rendered the                           *\n *    next time the map is refreshed.                                                          *\n *                                                                                             *\n * INPUT:   cell  -- The map cell to be rerendered.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/12/1992 JLB : Created.                                                                 *\n *   05/08/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nvoid RadarClass::Radar_Pixel(CELL cell)\n{\n\tif (IsRadarActive && Map.IsSidebarActive && Cell_On_Radar(cell)) {\n\t\tIsToRedraw = true;\n\t\t(*this)[cell].IsPlot = true;\n\t\tif (PixelPtr < PIXELSTACK) {\n\t\t\tPixelStack[PixelPtr++] = cell;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * RadarClass::Click_In_Radar -- Converts a radar click into cell X and Y coordinate.          *\n *                                                                                             *\n *    This routine will examine the X and Y coordinate and convert them into the X and Y       *\n *    cell coordinate value that corresponds to the location.                                  *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y mouse coordinate already normalized to the radar upper left   *\n *                   corner.                                                                   *\n *                                                                                             *\n * OUTPUT:  Returns with success rating in addition, the X and Y values will now hold the      *\n *          cell coordinates of the cell the pixel offsets indicated.                          *\n *             Result 1 = click was in radar region                                            *\n *             Result 0 = click was outside radar region completely                            *\n *             Result-1 = click in radar area but not on clickable region of radar.            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/30/1995 PWG : Created.                                                                 *\n *   07/16/1995 JLB : Recognizes when sidebar is closed now.                                   *\n *=============================================================================================*/\nint RadarClass::Click_In_Radar(int &ptr_x, int &ptr_y, bool change) const\n{\n\tint x\t= ptr_x;\n\tint y\t= ptr_y;\n\n\t/*\n\t** If radar is not active the click could have been on a radar point\n\t*/\n\tif (!IsRadarActive || !Map.IsSidebarActive) return(0);\n\n\tx -= (RadX + RadOffX);\n\ty -= (RadY + RadOffY);\n\tif ((unsigned)x < RadIWidth && (unsigned)y < RadIHeight) {\n\t\tx -= BaseX;\n\t\ty -= BaseY;\n\n\t\tif ((unsigned)x < RadarWidth + (ZoomFactor-1) && (unsigned)y < RadarHeight + (ZoomFactor-1)) {\n//\t\tif ((unsigned)x < RadarWidth && (unsigned)y < RadarHeight) {\n\t\t\tx = RadarX + (x / ZoomFactor);\n\t\t\ty = RadarY + (y / ZoomFactor);\n\t\t\tif (change) {\n\t\t\t\tptr_x = x;\n\t\t\t\tptr_y = y;\n\t\t\t}\n\t\t\treturn(1);\n\t\t}\n\t\treturn(-1);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Click_Cell_Calc -- Determines what cell the pixel coordinate is over.           *\n *                                                                                             *\n *    This routine will examine the pixel coordinate provided and determine what cell it       *\n *    represents. If the radar map is not active or the coordinates are not positioned over    *\n *    the radar map, then it will fall into the base class corresponding routine.              *\n *                                                                                             *\n * INPUT:   x,y   -- The pixel coordinate to convert into a cell number.                       *\n *                                                                                             *\n * OUTPUT:  Returns with the cell number that the coordinate is over or -1 if not over any     *\n *          cell.                                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL RadarClass::Click_Cell_Calc(int x, int y) const\n{\n\tint result = Click_In_Radar(x, y, true);\n\tswitch (result) {\n\t\tcase 1:\n\t\t\treturn(XY_Cell(x, y));\n\n\t\tcase -1:\n\t\t\treturn(-1);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(DisplayClass::Click_Cell_Calc(x, y));\n}\n\n\n/***********************************************************************************************\n * RadarClass::Map_Cell -- Updates radar map when a cell becomes mapped.                       *\n *                                                                                             *\n *    This routine will update the radar map if a cell becomes mapped.                         *\n *                                                                                             *\n * INPUT:   cell  -- The cell that is being mapped.                                            *\n *                                                                                             *\n *          house -- The house that is doing the mapping.                                      *\n *                                                                                             *\n * OUTPUT:  bool; Was the cell mapped (for the first time) by this routine?                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Map_Cell(CELL cell, HouseClass * house)\n{\n\tif (DisplayClass::Map_Cell(cell, house)) {\n\t\tRadar_Pixel(cell);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n\nvoid RadarClass::Cursor_Cell(CELL cell, int value)\n{\n\t/*\n\t** If this cell is not on the radar don't bother doing anything.\n\t*/\n\tif (Cell_On_Radar(cell)) {\n\n\t\tint temp = (*this)[cell].IsRadarCursor;\n\n\t\tif (temp != value) {\n\n\t\t\t/*\n\t\t\t**\tRecord the new state of this cell.\n\t\t\t*/\n\t\t\t(*this)[cell].IsRadarCursor\t= value;\n\n\t\t\t/*\n\t\t\t**\tIf we are erasing then erase the cell.\n\t\t\t*/\n\t\t\tif (value == FALSE) \t{\n\t\t\t\tPlot_Radar_Pixel(cell);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nvoid RadarClass::Mark_Radar(int x1, int y1, int x2, int y2, int value, int barlen)\n{\n\tint x, y;\n\t/*\n\t** First step is to convert pixel coordinates back to a CellX and CellY.\n\t*/\n\tx1 = RadarX + (x1 / ZoomFactor);\n\ty1 = RadarY + (y1 / ZoomFactor);\n\tx2 = RadarX + (x2 / ZoomFactor);\n\ty2 = RadarY + (y2 / ZoomFactor);\n\n\t/*\n\t** Now we need to convert the Pixel length to a cell length.\n\t*/\n\tbarlen = (barlen / ZoomFactor) + 1;\n\n\t/*\n\t** Now lets loop through and mark the map with the proper value.\n\t*/\n\tfor (int lp = 0; lp <= barlen; lp++) {\n\t\t/*\n\t\t** Do Horizontal action to upper and lower left corners.\n\t\t*/\n\t\tx = x1 + lp;\n\t\tCursor_Cell(XY_Cell(x, y1), value);\n\t\tCursor_Cell(XY_Cell(x, y2), value);\n\t\t/*\n\t\t** Do Horizontal Action to upper and lower right corners\n\t\t*/\n\t\tx = x2 - lp;\n\t\tCursor_Cell(XY_Cell(x, y1), value);\n\t\tCursor_Cell(XY_Cell(x, y2), value);\n\t\t/*\n\t\t** Do Vertical Action to left and right upper corners\n\t\t*/\n\t\ty = y1 + lp;\n\t\tCursor_Cell(XY_Cell(x1, y), value);\n\t\tCursor_Cell(XY_Cell(x2, y), value);\n\n\t\t/*\n\t\t** Do Vertical action to left and right lower corners.\n\t\t*/\n\t\ty = y2 - lp;\n\t\tCursor_Cell(XY_Cell(x1, y), value);\n\t\tCursor_Cell(XY_Cell(x2, y), value);\n\t}\n}\n\n\n\n/***********************************************************************************************\n * RadarClass::Cell_XY_To_Radar_Pixel-- Adjust the position of the radar map cursor.           *\n *                                                                                             *\n *    This routine will adjust the location (and visibility) of the radar                      *\n *    map cursor. It handles all restoration, drawing, and flashing.                           *\n *                                                                                             *\n * INPUT:   pos   - Cell position for the cursor. If the value is -1 then                      *\n *                  the cursor will be hidden. If the value is equal to                        *\n *                  the last value passed in then cursor flashing will                         *\n *                  be maintained.                                                             *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1991 JLB : Created.                                                                 *\n *   11/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Cell_XY_To_Radar_Pixel(int cellx, int celly, int &x, int &y)\n{\n\tx = (cellx - RadarX) * ZoomFactor;\n\ty = (celly - RadarY) * ZoomFactor;\n}\n\n\n/***********************************************************************************************\n * RadarClass::Jam_Cell -- Updates radar map when a cell becomes jammed.                       *\n *                                                                                             *\n *    This routine will update the radar map if a cell becomes jammed.                         *\n *                                                                                             *\n * INPUT:   cell  -- The cell that is being jammed.                                            *\n *                                                                                             *\n *          house -- The house that is doing the jamming.                                      *\n *                                                                                             *\n * OUTPUT:  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/09/1995 BWG : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Jam_Cell(CELL cell, HouseClass * house/*KO, bool shadeit*/)\n{\n\tunsigned short jam = 1 << house->Class->House;\n\t(*this)[cell].Jammed |= jam;\n\tif (house != PlayerPtr) Shroud_Cell(cell/*KO, shadeit*/);\n\tRadar_Pixel(cell);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RadarClass::UnJam_Cell -- Updates radar map when a cell becomes jammed.                     *\n *                                                                                             *\n *    This routine will update the radar map if a cell becomes jammed.                         *\n *                                                                                             *\n * INPUT:   cell  -- The cell that is being jammed.                                            *\n *                                                                                             *\n *          house -- The house that is doing the jamming.                                      *\n *                                                                                             *\n * OUTPUT:  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/09/1995 BWG : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::UnJam_Cell(CELL cell, HouseClass * house)\n{\n\tunsigned short jam = 1 << house->Class->House;\n\t(*this)[cell].Redraw_Objects();\n\t(*this)[cell].Jammed &= (0xFFFF - jam);\n\tRadar_Pixel(cell);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Radar_Cursor -- Adjust the position of the radar map cursor.                    *\n *                                                                                             *\n *    This routine will adjust the location (and visibility) of the radar                      *\n *    map cursor. It handles all restoration, drawing, and flashing.                           *\n *                                                                                             *\n * INPUT:   pos   - Cell position for the cursor. If the value is -1 then                      *\n *                  the cursor will be hidden. If the value is equal to                        *\n *                  the last value passed in then cursor flashing will                         *\n *                  be maintained.                                                             *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1991 JLB : Created.                                                                 *\n *   11/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\n#pragma argsused\nvoid RadarClass::Radar_Cursor(int forced)\n{\n\tstatic \t\t\t\t\t_last_pos = -1;\n\tstatic \t\t\t\t\t_last_frame = -1;\n#ifdef WIN32\n\tGraphicViewPortClass \t* oldpage;\n#else\n\tGraphicBufferClass \t* oldpage;\n#endif\n\tint\t\t\t\t\t\tx1, y1, x2, y2;\n\n\t/*\n\t** figure out these function calls as we will need to call them multiple times.\n\t*/\n\tint\ttac_cell    = Coord_Cell(TacticalCoord);\n\tint\ttac_cell_x\t= Cell_X(tac_cell);\n\tint\ttac_cell_y\t= Cell_Y(tac_cell);\n\tint\tbarlen      = 6;\n\n\t/*\n\t** If the current tactical cell is invalid or we haven't moved and we are not forced to redraw then\n\t** just skip the redraw process.\n\t*/\n\tif (tac_cell != -1 && _last_pos == tac_cell && _last_frame == SpecialRadarFrame && !forced) return;\n\n\tif ( _last_pos != -1 ) {\n\t\t/*\n\t\t** The first thing we need to do is take care of erasing the last radar cell position.  We do this\n\t\t** by converting to pixel coordinates, then adjusting for the pixel coords for the current frame and\n\t\t** finally taking care of calling the erase procedure which will convert the pixel coordinates back\n\t\t** to the cells that need to be redraw.\n\t\t**/\n\t\tint last_cell_x\t= Cell_X(_last_pos);\n\t\tint last_cell_y\t= Cell_Y(_last_pos);\n\n\t\tCell_XY_To_Radar_Pixel(last_cell_x, last_cell_y, x1, y1);\n\t\tCell_XY_To_Radar_Pixel(last_cell_x + Lepton_To_Cell(TacLeptonWidth), last_cell_y + Lepton_To_Cell(TacLeptonHeight), x2, y2);\n\t\tx2--;\n\t\ty2--;\n\n\t\t/*\n\t\t** Adjust the current coordinates based on the last animation frame.\n\t\t*/\n\t\tx1-= _last_frame;\n\t\ty1-= _last_frame;\n\t\tx2+= _last_frame;\n\t\ty2+= _last_frame;\n\n\t\t/*\n\t\t** Finally mark the map (actually remove the marks that indicate the radar cursor was there\n\t\t*/\n\t\tMark_Radar(x1, y1, x2, y2, FALSE, barlen);\n\t}\n\n\n\t/*\n\t** Find the upper left and lower right corners of the radar cursor.\n\t** Remember to adjust x2 and y2 back by one pixel as they will not be\n\t** pointing to the right value otherwise.  They point one cell ahead\n\t** of where they should.\n\t*/\n\tCell_XY_To_Radar_Pixel(tac_cell_x, tac_cell_y, x1, y1);\n\tCell_XY_To_Radar_Pixel(tac_cell_x + Lepton_To_Cell(TacLeptonWidth), tac_cell_y + Lepton_To_Cell(TacLeptonHeight), x2, y2);\n\tx2--;\n\ty2--;\n\n\t/*\n\t** Adjust the coordinates based on the current frame of radar animation.\n\t*/\n\tx1-= SpecialRadarFrame;\n\ty1-= SpecialRadarFrame;\n\tx2+= SpecialRadarFrame;\n\ty2+= SpecialRadarFrame;\n\n\tMark_Radar(x1, y1, x2, y2, TRUE, barlen);\n\n\t/*\n\t** setup a graphic view port class so we can write all the pixels relative\n\t** to 0,0 rather than relative to full screen coordinates.\n\t*/\n\toldpage = Set_Logic_Page(HidPage);\n\tGraphicViewPortClass draw_window(LogicPage->Get_Graphic_Buffer(),\n\t\t\t\t\t\t\t\t\t\t\t\tRadX + RadOffX + BaseX + LogicPage->Get_XPos(),\n\t\t\t\t\t\t\t\t\t\t\t\tRadY + RadOffY + BaseY + LogicPage->Get_YPos(),\n\t\t\t\t\t\t\t\t\t\t\t\tRadarWidth,\n\t\t\t\t\t\t\t\t\t\t\t\tRadarHeight);\n\n\tdraw_window.Draw_Line(x1, \ty1,\tx1 + barlen,\ty1, \tLTGREEN);\n\tdraw_window.Draw_Line(x1,\ty1,\tx1,\ty1 + barlen,\tLTGREEN);\n\n\t// Draw upper right hand corner\n\tdraw_window.Draw_Line(x2 - barlen,\ty1,\tx2,\ty1, \tLTGREEN);\n\tdraw_window.Draw_Line(x2, \ty1, \tx2, \ty1 + barlen,\tLTGREEN);\n\n\t// Draw lower left hand corner\n\tdraw_window.Draw_Line(x1,\ty2 - barlen,\tx1,\ty2,\tLTGREEN);\n\tdraw_window.Draw_Line(x1,\ty2,\tx1 + barlen,\ty2, \tLTGREEN);\n\n\t// Draw lower right hand corner\n\tdraw_window.Draw_Line(x2,\ty2 - barlen,\tx2, \ty2, \tLTGREEN);\n\tdraw_window.Draw_Line(x2 - barlen, \ty2,\tx2,\ty2, \tLTGREEN);\n\n\tSet_Logic_Page(oldpage);\n\t_last_pos = tac_cell;\n\t_last_frame = SpecialRadarFrame;\n\tRadarCursorRedraw = FALSE;\n}\n\n\n/***************************************************************************\n * RadarClass::Radar_Anim -- Renders current frame of radar animation      *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid RadarClass::Radar_Anim(void)\n{\n\t/*\n\t** Do nothing if we're in player-name mode\n\t*/\n\tif (IsPlayerNames)\n\t\treturn;\n\n\tif (!Map.IsSidebarActive) return;\n\n#ifdef WIN32\n\tGraphicViewPortClass \t* oldpage= Set_Logic_Page(HidPage);\n\tGraphicViewPortClass draw_window(LogicPage->Get_Graphic_Buffer(),\n\t\t\t\t\t\t\t\t\t\t\t\tRadX + RadOffX + LogicPage->Get_XPos(),\n\t\t\t\t\t\t\t\t\t\t\t\tRadY + RadOffY + LogicPage->Get_YPos(),\n\t\t\t\t\t\t\t\t\t\t\t\tRadIWidth,\n\t\t\t\t\t\t\t\t\t\t\t\tRadIHeight);\n#else\n\tGraphicBufferClass \t* oldpage= Set_Logic_Page(HidPage);\n\tGraphicViewPortClass draw_window(LogicPage,\n\t\t\t\t\t\t\t\t\t\t\t\tRadX + RadOffX,\n\t\t\t\t\t\t\t\t\t\t\t\tRadY + RadOffY,\n\t\t\t\t\t\t\t\t\t\t\t\tRadIWidth,\n\t\t\t\t\t\t\t\t\t\t\t\tRadIHeight-2);\n#endif\n//Mono_Set_Cursor(0,0);\n#ifdef WIN32\n\tDraw_Box(RadX+RadOffX-1, RadY+RadOffY-1, RadIWidth+2, RadIHeight+2, BOXSTYLE_RAISED, true);\n#endif\n\tdraw_window.Clear();\n\tCC_Draw_Shape(RadarAnim, RadarAnimFrame, RadX, RadY+1*RESFACTOR, WINDOW_MAIN, SHAPE_NORMAL);\n\tFlag_To_Redraw(false);\n\tSet_Logic_Page(oldpage);\n}\n\n\n/***********************************************************************************************\n * RadarClass::AI -- Processes radar input (non-tactical).                                     *\n *                                                                                             *\n *    This routine intercepts any player input that concerns the radar map, but not those      *\n *    areas that represent the tactical map. These are handled by the tactical map AI          *\n *    processor. Primarily, this routine handles the little buttons that border the radar      *\n *    map.                                                                                     *\n *                                                                                             *\n * INPUT:   input -- The player input code.                                                    *\n *                                                                                             *\n *          x,y   -- Mouse coordinate parameters to use.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/23/1994 JLB : Created.                                                                 *\n *   12/26/1994 JLB : Moves tactical map with click or drag.                                   *\n *   12/31/1994 JLB : Uses mouse coordinate parameters.                                        *\n *=============================================================================================*/\nvoid RadarClass::AI(KeyNumType & input, int x, int y)\n{\n\t/*\n\t** Check to see if we need to animate the radar cursor\n\t*/\n\tif (IsRadarActive && Map.IsSidebarActive && SpecialRadarFrame) {\n\t\tSpecialRadarFrame--;\n\t\tRadarCursorRedraw = TRUE;\n\t\tIsToRedraw = TRUE;\n\t\tFlag_To_Redraw(FALSE);\n\t}\n\n\t/*\n\t** Check goes here to see if there is enough power to run the radar\n\t*/\n\tif (IsRadarActivating) {\n\t\tif (!DoesRadarExist) {\n\t\t\tRadarAnimFrame++;\n\t\t\tif (RadarAnimFrame < RADAR_ACTIVATED_FRAME) {\n\t\t\t\tIsToRedraw = true;\n\t\t\t\tFlag_To_Redraw(false);\n\t\t\t} else {\n\t\t\t\tDoesRadarExist = true;\n\t\t\t\tRadar_Activate(3);\n\t\t\t}\n\t\t} else {\n\t\t\tRadarAnimFrame--;\n\t\t\tif (RadarAnimFrame > RADAR_ACTIVATED_FRAME) {\n\t\t\t\tIsToRedraw = true;\n\t\t\t\tFlag_To_Redraw(false);\n\t\t\t} else {\n\t\t\t\tRadar_Activate(3);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Check goes here to see if there is enough power to run the radar\n\t*/\n\tif (IsRadarDeactivating) {\n\t\tRadarAnimFrame++;\n\t\tif (RadarAnimFrame == MAX_RADAR_FRAMES) {\n\t\t\tIsRadarDeactivating = false;\n\t\t} else {\n\t\t\tIsToRedraw = true;\n\t\t\tFlag_To_Redraw(false);\n\t\t}\n\t}\n\n\t/*\n\t** Check here to see if radar is being jammed, so we can update the\n\t** animation with snow.\n\t*/\n\tif (!IsRadarActivating && !IsRadarDeactivating && IsRadarJammed) {\n\t\tRadarAnimFrame++;\n\t\tif (RadarAnimFrame < RADAR_ACTIVATED_FRAME) RadarAnimFrame = RADAR_ACTIVATED_FRAME;\n\t\tif (RadarAnimFrame > (3 + RADAR_ACTIVATED_FRAME)) RadarAnimFrame = RADAR_ACTIVATED_FRAME;\n\t\tIsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\t}\n\n\t/*\n\t** Check here to see if the sonar pulse is active, and if it is, flag the\n\t** radar to redraw so the pulse ping will display.\n\t*/\n\tif (IsPulseActive) {\n\t\tFlag_To_Redraw(true);\n\t\tIsToRedraw = true;\n\t\tif (RadarPulseFrame >= 8) {\n\t\t\tRadarPulseFrame = 0;\n\t\t\tIsPulseActive = false;\n\t\t}\n\t}\n\n\tDisplayClass::AI(input, x, y);\n}\n\n\n/***********************************************************************************************\n * RadarClass::RTacticalClass::Action -- I/O function for the radar map.                       *\n *                                                                                             *\n *    This is the main action function for handling player I/O on the radar map. It processes  *\n *    mouse clicks as well as mouse moves.                                                     *\n *                                                                                             *\n * INPUT:   flags -- The event flags that trigger this function call.                          *\n *                                                                                             *\n *          key   -- Reference the keyboard event that applies to the trigger event.           *\n *                                                                                             *\n * OUTPUT:  Should further processing of the input list be aborted?                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RadarClass::RTacticalClass::Action(unsigned flags, KeyNumType & key)\n{\n\tCELL\t\t\tcell;\t\t\t\t\t\t\t// cell num click happened over\n\tint\t\t\tx,y;\t\t\t\t\t\t\t// Sub cell pixel coordinates.\n\tint\t\t\tcellx,celly;\t\t\t\t// Sub cell pixel coordinates.\n\tbool\t\t\tshadow;\t\t\t\t\t\t// is the cell in shadow or not\n\tObjectClass * object = 0;\t\t\t\t// what object is in the cell\n\tActionType \taction = ACTION_NONE;\t// Action possible with currently selected object.\n\n\t/*\n\t**\tForce any help label to disappear when the mouse is held over the\n\t**\tradar map.\n\t*/\n\tif (Map.IsSidebarActive) {\n\t\tMap.Help_Text(TXT_NONE);\n\t}\n\n\tif (!Map.IsRadarActive) {\n\t\tif (Map.IsSidebarActive) {\n\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL);\n//\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, true);\n\t\t}\n\t\treturn(false);\n\t}\n\n\t/*\n\t** Disable processing if the player names are up\n\t*/\n\tif (Map.Is_Player_Names()) {\n\t\tGadgetClass::Action(0, key);\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tSet some working variables that depend on the mouse position. For the press\n\t**\tor release event, special mouse queuing storage variables are used. Other\n\t**\tevents must use the current mouse position globals.\n\t*/\n\tif (flags & (LEFTPRESS|LEFTRELEASE|RIGHTPRESS|RIGHTRELEASE)) {\n\t\tx = Keyboard->MouseQX;\n\t\ty = Keyboard->MouseQY;\n\t} else {\n\t\tx = Get_Mouse_X();\n\t\ty = Get_Mouse_Y();\n\t}\n\n\t/*\n\t**\tSee if the mouse is over the radar general area, but not yet\n\t**\tover the active region of the radar map. In such a case, the\n\t**\tmouse is overridden to be the normal cursor and no other\n\t**\taction is performed.\n\t*/\n\tif (x < Map.RadX+Map.RadOffX || x >= Map.RadX+Map.RadIWidth || y < Map.RadY+Map.RadOffY || y >= Map.RadY+Map.RadIHeight) {\n\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL);\n\t\treturn(false);\n\t}\n\n\tint result = Map.RadarClass::Click_In_Radar(x, y, false);\n\n\tif (result == 1) {\n\t\tcell = Map.RadarClass::Click_Cell_Calc(x, y);\n\t\tif (cell != -1 && Map.In_Radar(cell)) {\n\t\t\tshadow\t= (!Map[cell].IsMapped && !Debug_Unshroud);\n//\t\t\tshadow\t= (!Map[cell].IsVisible && !Debug_Unshroud);\n\t\t\tcellx\t   = 12;\n\t\t\tcelly\t   = 12;\n\n\t\t\t/*\n\t\t\t**\tDetermine the object that the mouse is currently over.\n\t\t\t*/\n\t\t\tif (!shadow) {\n\t\t\t\tobject = Map.Cell_Object(cell, cellx, celly);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf there is a currently selected object, then the action to perform if\n\t\t\t**\tthe left mouse button were clicked must be determined.\n\t\t\t*/\n\t\t\tif (CurrentObject.Count()) {\n\t\t\t\tif (object) {\n\t\t\t\t\taction = CurrentObject[0]->What_Action(object);\n\t\t\t\t} else {\n\t\t\t\t\taction = CurrentObject[0]->What_Action(cell);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** If this is not a valid radar map action then we are not going to do\n\t\t\t\t** anything.\n\t\t\t\t*/\n\t\t\t\tswitch (action) {\n\t\t\t\t\tcase ACTION_MOVE:\n\t\t\t\t\tcase ACTION_NOMOVE:\n\t\t\t\t\tcase ACTION_ATTACK:\n\t\t\t\t\tcase ACTION_ENTER:\n\t\t\t\t\tcase ACTION_CAPTURE:\n\t\t\t\t\tcase ACTION_SABOTAGE:\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\taction = ACTION_NONE;\n\t\t\t\t\t\tobject = NULL;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** On the radar map the only reason we would want the normal cursor to\n\t\t\t\t** appear is if we were over one of our own selected units.  Otherwise\n\t\t\t\t** we can't move there.\n\t\t\t\t**/\n\t\t\t\tif (action == ACTION_NONE) {\n\t\t\t\t\tif (object && object->IsSelected) {\n\t\t\t\t\t\tobject = NULL;\n\t\t\t\t\t} else {\n\t\t\t\t\t\taction = ACTION_NOMOVE;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tA right mouse button press toggles the zoom mode.\n\t\t\t\t*/\n\t\t\t\tif (flags & RIGHTPRESS) {\n\t\t\t\t\tMap.Mouse_Right_Press();\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tWhen the mouse buttons aren't pressed, only the mouse cursor shape is processed.\n\t\t\t\t**\tThe shape changes depending on what object the mouse is currently over and what\n\t\t\t\t**\tobject is currently selected.\n\t\t\t\t*/\n\t\t\t\tif (flags & LEFTUP) {\n\t\t\t\t\tMap.Mouse_Left_Up(-1, shadow, object, action, true);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tNormal actions occur when the mouse button is released. The press event is\n\t\t\t\t**\tintercepted and possible rubber-band mode is flagged.\n\t\t\t\t*/\n\t\t\t\tif (flags & LEFTPRESS) {\n\t\t\t\t\tMap.Mouse_Left_Release(cell, cellx, celly, object, action, true);\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tMap.Set_Default_Mouse(MOUSE_RADAR_CURSOR, !Map.IsZoomed);\n\n\t\t\t\tif (flags & LEFTPRESS) {\n\n\t\t\t\t\tcell = Map.RadarClass::Click_Cell_Calc(x, y);\n\t\t\t\t\tif (cell != -1) {\n\t\t\t\t\t\tint cellx = Cell_X(cell);\n\t\t\t\t\t\tint celly = Cell_Y(cell);\n\t\t\t\t\t\tcellx -= Lepton_To_Cell(Map.TacLeptonWidth) / 2;\n\t\t\t\t\t\tcellx = max(cellx, Map.MapCellX);\n\t\t\t\t\t\tcelly -= Lepton_To_Cell(Map.TacLeptonHeight) / 2;\n\t\t\t\t\t\tcelly = max(celly, Map.MapCellY);\n\t\t\t\t\t\tcell = XY_Cell(cellx, celly);\n\t\t\t\t\t\tshadow = (!Map[cell].IsMapped && !Debug_Unshroud);\n//\t\t\t\t\t\tshadow = (!Map[cell].IsVisible && !Debug_Unshroud);\n\t\t\t\t\t\tMap.Set_Tactical_Position(Cell_Coord(cell));\n\t\t\t\t\t\tcell = Coord_Cell(Map.DesiredTacticalCoord);\n\t\t\t\t\t\tMap.DisplayClass::IsToRedraw = true;\n\t\t\t\t\t\tMap.Flag_To_Redraw(true);\n\t\t\t\t\t\tMap.SpecialRadarFrame = 4;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tA right mouse button press toggles the zoom mode.\n\t\t\t\t*/\n\t\t\t\tif (flags & RIGHTPRESS) {\n\t\t\t\t\tMap.Zoom_Mode(cell);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (result == -1) {\n\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, true);\n\t}\n\tGadgetClass::Action(0, key);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Refresh_Cells -- Intercepts refresh request and updates radar if needed         *\n *                                                                                             *\n *    This routine intercepts the refresh cells request and if it detects that the sidebar     *\n *    should be rerendered, it flags the radar map to redraw during the next draw operation.   *\n *                                                                                             *\n * INPUT:   cell  -- The origin cell that the refresh cell offset list is based upon.          *\n *                                                                                             *\n *          list  -- Pointer to the list of offsets from the origin cell that specifies the    *\n *                   cells to be flagged for redraw. If the list starts with the special       *\n *                   code to refresh the sidebar, then this routine recognizes it and flags    *\n *                   the radar map to be redrawn accordingly.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/01/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Refresh_Cells(CELL cell, short const * list)\n{\n\tif (*list == REFRESH_SIDEBAR) {\n\t\tIsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\t}\n\tDisplayClass::Refresh_Cells(cell, list);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Set_Radar_Position -- Sets the radar position to center around specified cell.  *\n *                                                                                             *\n *    This routine will try to center the radar map around the cell position specified.        *\n *                                                                                             *\n * INPUT:   cell  -- The cell to try and position the radar map around.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Set_Radar_Position(CELL cell)\n{\n#ifdef WIN32\n\tint oldx, oldy;\n\tint newx, newy;\n\tint newcell;\n\n\tif (ZoomFactor != 1) {\n\t\toldx = (Cell_X(cell) - MapCellX);\n\t\toldy = (Cell_Y(cell) - MapCellY);\n\t} else {\n\t\toldx = 0;\n\t\toldy = 0;\n\t}\n\n\tConfine_Rect(&oldx, &oldy, RadarCellWidth, RadarCellHeight, MapCellWidth, MapCellHeight);\n\n\tnewx \t\t= oldx + MapCellX;\n\tnewy \t\t= oldy + MapCellY;\n\tnewcell\t= XY_Cell(newx, newy);\n\n\tif (RadarCell != newcell) {\n   \tint forced = FALSE;\n\t\tint xmod = newx;\n\t\tint ymod = newy;\n\n\t\tint radx = (Cell_X(RadarCell)) - xmod;\n\t\tint rady = (Cell_Y(RadarCell)) - ymod;\n\n\t\tRadarX \t\t= newx;\n\t\tRadarY \t\t= newy;\n\t\tRadarCell \t= newcell;\n\n\t\tif (Map.IsSidebarActive && Map.IsRadarActive) {\n\t\t\tint radw = RadarCellWidth-ABS(radx);\t\t\t// Replicable width.\n\t\t\tint radh = RadarCellHeight-ABS(rady);\t\t// Replicable height.\n\n\t\t\tif (radw < 1) forced = true;\n\t\t\tif (radh < 1) forced = true;\n\n\t\t\tif (!forced && (radw != RadarWidth || radh != RadarHeight)) {\n\t\t\t\t/*\n\t\t\t\t** Blit the section that is actually overlapping.\n\t\t\t\t**\n\t\t\t\t** If the video card isnt able to blit overlapped regions then we have\n\t\t\t\t** to do the blit in two stages via an intermediate buffer. The test to allow\n\t\t\t\t** overlapped blits is done in the library at the time of setting the video mode.\n\t\t\t\t*/\n\t\t\t\tif (OverlappedVideoBlits || !HidPage.Get_IsDirectDraw()) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Overlapped blits are OK or we dont have a video memory hid page so blits are\n\t\t\t\t\t** always done in software by the library anyway.\n\t\t\t\t\t*/\n\t\t\t\t\tHidPage.Blit(HidPage,\n\t\t\t\t\t\t\t\t\t(((radx < 0) ? -radx : 0) * ZoomFactor) + RadX + RadOffX + BaseX,\n\t\t\t\t\t\t\t\t\t(((rady < 0) ? -rady : 0) * ZoomFactor) + RadY + RadOffY + BaseY,\n\t\t\t\t\t\t\t\t\t(((radx < 0) ? 0 : radx) * ZoomFactor) + RadX+ RadOffX + BaseX,\n\t\t\t\t\t\t\t\t\t(((rady < 0) ? 0 : rady) * ZoomFactor) + RadY + RadOffY + BaseY,\n\t\t\t\t\t\t\t\t\tradw * ZoomFactor,\n\t\t\t\t\t\t\t\t\tradh * ZoomFactor);\n\n\t\t\t\t} else {\n\t\t\t\t\t/*\n\t\t\t\t\t** Create a temporary intermediate surface\n\t\t\t\t\t*/\n\t\t\t\t\tGraphicBufferClass temp_surface;\n\t\t\t\t\ttemp_surface.Init((RadarWidth + 16) & 0xfffffff0,\n\t\t\t\t\t\t\t\t\t\t\t(RadarHeight + 16) & 0xfffffff0,\n\t\t\t\t\t\t\t\t\t\t\tNULL, 0, (GBC_Enum) GBC_VIDEOMEM);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Do the blit in 2 stages.\n\t\t\t\t\t*/\n\t\t\t\t\tHidPage.Blit(temp_surface,\n\t\t\t\t\t\t\t\t\t(((radx < 0) ? -radx : 0) * ZoomFactor) + RadX + RadOffX + BaseX,\n\t\t\t\t\t\t\t\t\t(((rady < 0) ? -rady : 0) * ZoomFactor) + RadY + RadOffY + BaseY,\n\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\tRadarWidth,\n\t\t\t\t\t\t\t\t\tRadarHeight);\n\n\t\t\t\t\ttemp_surface.Blit(HidPage,\n\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t(((radx < 0) ? 0 : radx) * ZoomFactor) + RadX+ RadOffX + BaseX,\n\t\t\t\t\t\t\t\t\t(((rady < 0) ? 0 : rady) * ZoomFactor) + RadY + RadOffY + BaseY,\n\t\t\t\t\t\t\t\t\tradw * ZoomFactor,\n\t\t\t\t\t\t\t\t\tradh * ZoomFactor);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Now we need to flag the section of the map that is going to redraw.\n\t\t\t\t*/\n\t\t\t\tif ( radx != 0 ) {\n\t\t\t\t\tint min;\n\t\t\t\t\tint max;\n\t\t\t\t\tif ( radx < 0 ) {  \t\t\t\t\t\t\t\t// this mean regen the right edge\n\t\t\t\t\t\tmin = radw;\n\t\t\t\t\t\tmax = radw+ABS(radx);\n\t\t\t\t\t} else {\t\t\t\t\t\t\t\t\t\t\t\t//\tthis mean regen the left edge\n\t\t\t\t\t\tmin = 0;\n\t\t\t\t\t\tmax = radx;\n\t\t\t\t\t}\n\t\t\t\t\tfor (int x = min; x < max; x++ ) {\n\t\t\t\t\t\tfor (int y = 0; y < RadarCellHeight; y++ ) {\n\t\t\t\t\t\t\tRadar_Pixel(XY_Cell(newx + x, newy + y));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( newy != 0 ) {\n\t\t\t\t\tint min;\n\t\t\t\t\tint max;\n\t\t\t\t\tif ( rady < 0 ) {  \t\t\t\t\t\t\t\t// this mean regen the bottom edge\n\t\t\t\t\t\tmin = radh;\n\t\t\t\t\t\tmax = radh+ABS(rady);\n\t\t\t\t\t} else {\t\t\t\t\t\t\t\t\t\t\t\t// this mean regen the top edge\n\t\t\t\t\t\tmin = 0;\n\t\t\t\t\t\tmax = rady;\n\t\t\t\t\t}\n\t\t\t\t\tfor (int y = min; y < max; y++ ) {\n\t\t\t\t\t\tfor ( int x = 0; x < RadarCellWidth; x++ ) {\n\t\t\t\t\t\t\tRadar_Pixel(XY_Cell(newx + x, newy + y));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tRadarCursorRedraw = IsRadarActive;\n\t\tIsToRedraw \t= IsRadarActive;\n\t\tFlag_To_Redraw(false);\n\t\tif (ZoomFactor > 4) {\n\t\t\tFullRedraw = forced;\n\t\t}\n\t} else {\n\t\tRadarCursorRedraw = IsRadarActive;\n\t\tIsToRedraw \t= IsRadarActive;\n\t\tFlag_To_Redraw(false);\n\t}\n#else\n\n\tif (cell != RadarCell) {\n\t\tint oldx = RadarX;\n\t\tint oldy = RadarY;\n\t\tCELL oldcell = RadarCell;\n\t\tint x = Cell_X(cell);\n\t\tint y = Cell_Y(cell);\n\n\t\t/*\n\t\t**\tIf the new radar position is not too close to the edge of the\n\t\t**\tcurrent radar display, then don't bother to change the radar position.\n\t\t*/\n\t\tif ((unsigned)(x - (RadarX+10)) > RadarCellWidth-20) {\n\t\t\toldx = (Cell_X(cell)-MapCellX)-RadarCellWidth/2;\n\t\t} else {\n\t\t\toldx = Cell_X(RadarCell)-MapCellX;\n\t\t}\n\t\tif ((unsigned)(y - (RadarY+10)) > RadarCellHeight-20) {\n\t\t\toldy = (Cell_Y(cell)-MapCellY)-RadarCellHeight/2;\n\t\t} else {\n\t\t\toldy = Cell_Y(RadarCell)-MapCellY;\n\t\t}\n\n#ifdef NEVER\n\t\tif ((unsigned)(x - (RadarX+10)) > RadarWidth-20 || (unsigned)(y - (RadarY+10)) > RadarHeight-20) {\n\t\t\toldx = (Cell_X(cell)-MapCellX)-RadarCellWidth/2;\n\t\t\toldy = (Cell_Y(cell)-MapCellY)-RadarCellHeight/2;\n\t\t} else {\n\t\t\toldx = Cell_X(RadarCell)-MapCellX;\n\t\t\toldy = Cell_Y(RadarCell)-MapCellY;\n\t\t}\n#endif\n\n\t\tConfine_Rect(&oldx, &oldy, RadarCellWidth, RadarCellHeight, MapCellWidth, MapCellHeight);\n\t\tRadarX = oldx + MapCellX;\n\t\tRadarY = oldy + MapCellY;\n\t\tRadarCell = XY_Cell(RadarX, RadarY);\n\t\tIsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\t\tif (oldcell != RadarCell) {\n\t\t\tFullRedraw = IsRadarActive;\n\t\t}\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * RadarClass::Radar_Position -- Returns with the current position of the radar map.           *\n *                                                                                             *\n *    This returns the cell number of the upper left corner of the radar map.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the radar map upper left corner cell position.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL RadarClass::Radar_Position(void)\n{\n\treturn(RadarCell);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Set_Map_Dimensions -- Sets the tactical map dimensions.                         *\n *                                                                                             *\n *    This routine is called when the tactical map changes its dimensions. This occurs when    *\n *    the tactical map moves and when the sidebar pops on or off.                              *\n *                                                                                             *\n * INPUT:   x,y   -- The cell coordinate of the upper left corner of the tactical map.         *\n *                                                                                             *\n *          w,y   -- The cell width and height of the tactical map.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Set_Map_Dimensions(int x, int y, int w, int h)\n{\n\tSet_Radar_Position(XY_Cell(x, y));\n\tDisplayClass::Set_Map_Dimensions(x, y, w, h);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Set_Tactical_Position -- Sets the map's tactical position and adjusts radar to  *\n *                                                                                             *\n *    This routine is called when the tactical map is to change position. The radar map might  *\n *    be adjusted as well by this routine.                                                     *\n *                                                                                             *\n * INPUT:   coord -- The new coordinate to use for the upper left corner of the tactical       *\n *                   map.                                                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/17/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Set_Tactical_Position(COORDINATE coord)\n{\n\tDisplayClass::Set_Tactical_Position(coord);\n\tSet_Radar_Position(Coord_Cell(TacticalCoord));\n}\n\n\n/***********************************************************************************************\n * RadarClass::Cell_On_Radar -- Determines if a cell is currently visible on radar.            *\n *                                                                                             *\n *    This routine will examine the specified cell number and return whether it is visible     *\n *    on the radar map. This depends on the radar map position.                                *\n *                                                                                             *\n * INPUT:   cell  -- The cell number to check.                                                 *\n *                                                                                             *\n * OUTPUT:  Is the specified cell visible on the radar map currently?                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/03/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Cell_On_Radar(CELL cell)\n{\n\tif ((unsigned)cell > MAP_CELL_TOTAL)\n\t\treturn(false);\n\n\tif (!IsZoomed) {\n\t\treturn(true);\n\t}\n\treturn(!(((Cell_X(cell) - RadarX) > RadarCellWidth) || ((Cell_Y(cell) - RadarY) > RadarCellHeight)));\n}\n\n\n/***********************************************************************************************\n * RadarClass::Player_Names -- toggles the Player-Names mode of the radar map                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      on         true = turn on; false = turn off                                            *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/07/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Player_Names(bool on)\n{\n\tIsPlayerNames = on;\n\tIsToRedraw = true;\n\tif (on) {\n\t\tFlag_To_Redraw(true);\n//\t\tFlag_To_Redraw(false);\n\t} else {\n\t\tFlag_To_Redraw(true);\t\t// force drawing of the plate\n\t}\n}\n\n\n/***********************************************************************************************\n * RadarClass::Spy_Next_House -- advances to the next house we're spying on, or returns NULL\t  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      0 = no house to spy on, 1 = found house to spy on                                      *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Spy_Next_House(void)\n{\n\tbool\ttospy = false;\n\tint spiedby = (1<<(PlayerPtr->Class->House));\n\n\tIsPlayerNames = false;\n\tIsToRedraw = true;\n\n\tHousesType maxhouse;\n\tHousesType firsthouse;\n\tHousesType house;\n\n\tif (Session.Type == GAME_NORMAL) {\n\t\tfirsthouse = HOUSE_SPAIN;\n\t\tmaxhouse = HOUSE_GOOD;\n\t} else {\n\t\tfirsthouse = HOUSE_MULTI1;\n\t\tmaxhouse = HOUSE_COUNT;\n\t}\n\n\tif (IsHouseSpy) {\n\t \thouse = (HousesType)(SpyingOn+1);\n\t} else {\n\t\thouse = firsthouse;\n\t}\n\n\tif (house < firsthouse) house = firsthouse;\n\n\twhile (house < maxhouse && !tospy) {\n\t\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\t\tif (hptr && hptr->IsActive && hptr != PlayerPtr) {\n\t\t\tif (hptr->RadarSpied & spiedby) {\n\t\t\t\ttospy = true;\n\t\t\t\tSpyingOn = house;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\thouse++;\n\t}\n\n\tIsHouseSpy = tospy;\n\n\tFlag_To_Redraw(true);\t\t// force drawing of the plate\n\treturn(tospy);\n}\n\n\n/***********************************************************************************************\n * Draw_House_Info -- Print house statistics on the radar map\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Draw_House_Info(void)\n{\n\tint y;\n\tchar txt[40];\n\t/*\n\t** Do nothing if the sidebar isn't there\n\t*/\n\tif (!Map.IsSidebarActive) {\n\t\treturn false;\n\t}\n\tCC_Draw_Shape(RadarFrame, 1, RadX, RadY + 1*RESFACTOR, WINDOW_MAIN, SHAPE_NORMAL);\n\ty = RadY + RadOffY + (2*RESFACTOR);\n\n\tMap.Repair.Draw_Me(true);\n\tMap.Upgrade.Draw_Me(true);\n\tMap.Zoom.Draw_Me(true);\n\n\tFancy_Text_Print (TXT_SPY_INFO, RadX + RadOffX + (6 * RESFACTOR), y,\n\t\t&ColorRemaps[PCOLOR_GREY], TBLACK,\n\t\tTPF_6PT_GRAD | TPF_NOSHADOW);\n\ty += 7*RESFACTOR;\n\n\tHouseClass * ptr = HouseClass::As_Pointer(SpyingOn);\n\tif (ptr && (ptr->RadarSpied & (1<<(PlayerPtr->Class->House))) ) {\n\t\tPlayerColorType c_idx;\n\t\tRemapControlType * color;\n\t\tTextPrintType style;\n\n\t\tc_idx = ptr->RemapColor;\n\t\tcolor = &ColorRemaps[c_idx];\n\t\tstyle = TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW;\n\n\t\t/*\n\t\t** Print house's name below 'spy report'\n\t\t*/\n\t\ttxt[0] = 0;\n\t\tsprintf(txt, \"%s\", ptr->IniName);//Text_String(ptr->Class->FullName));\n//\t\tsprintf(txt, \"%s\", ptr->Name());//Text_String(ptr->Class->FullName));\n\t\tif (strlen(txt)) {\n\t\t\tif (strlen(txt) > 9) {\n\t\t\t\ttxt[9] = '.';\n\t\t\t\ttxt[10] = '\\0';\n\t\t\t}\n\t\t\tFancy_Text_Print (txt, RadX + RadOffX + (6 * RESFACTOR), y, color, BLACK, style);\n\t\t} else {\n\t\t\tstrcpy(txt,\"________\");\n\t\t}\n\t\ty += (6 * RESFACTOR) + 1;\n\n\t\tFancy_Text_Print(TXT_BUILDNGS, RadX + RadOffX + (6 * RESFACTOR), y, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_6PT_GRAD | TPF_NOSHADOW);\n\t\ty += (6 * RESFACTOR) + 1;\n\n// count & print buildings\n\t\titoa(ptr->CurBuildings, txt, 10);\n\t\tFancy_Text_Print(txt, RadX + RadOffX + (6 * RESFACTOR), y, color, BLACK, style);\n\t\ty += (6 * RESFACTOR) + 1;\n\n\t\tFancy_Text_Print(TXT_UNITS, RadX + RadOffX + (6 * RESFACTOR), y, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_6PT_GRAD | TPF_NOSHADOW);\n\t\ty += (6 * RESFACTOR) + 1;\n// count & print units\n\t\titoa(ptr->CurUnits, txt, 10);\n\t\tFancy_Text_Print(txt, RadX + RadOffX + 6 * RESFACTOR, y, color, BLACK, style);\n\t\ty += (6 * RESFACTOR) + 1;\n\n\t\tFancy_Text_Print(TXT_INFANTRY, RadX + RadOffX + (6 * RESFACTOR), y, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_6PT_GRAD | TPF_NOSHADOW);\n\t\ty += (6 * RESFACTOR) + 1;\n// count & print infantry\n\t\titoa(ptr->CurInfantry, txt, 10);\n\t\tFancy_Text_Print(txt, RadX + RadOffX + (6 * RESFACTOR), y, color, BLACK, style);\n#if(0)\n\t\ty += (6 * RESFACTOR) + 1;\n\n\t\tFancy_Text_Print(TXT_AIRCRAFT, RADAR_X + RADAR_OFF_X + 6, y,\n\t\t\t\t\t\t\t\t&ColorRemaps[PCOLOR_GREY], TBLACK,\n\t\t\t\t\t\t\t\tTPF_6PT_GRAD | TPF_NOSHADOW);\n\t\ty += (6 * RESFACTOR) + 1;\n// count & print aircraft\n\t\tfor (i = AIRCRAFT_NONE+1, count = 0; i < AIRCRAFT_COUNT; i++) {\n\t\t\tcount += ptr->AQuantity[i];\n\t\t}\n\t\titoa(count, txt, 10);\n\t\tFancy_Text_Print(txt, RadX + RadOffX, y,\n\t\t\t\tcolor, BLACK, style);\n#endif\n\t\treturn(true);\n\t} else {\n\t\treturn(false);\n\t}\n}\n\n\n/***********************************************************************************************\n * Draw_Names -- draws players' names on the radar map                                         *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/07/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Draw_Names(void)\n{\n\tPlayerColorType c_idx;\n\tHousesType house;\n\tHouseClass * ptr;\n\tint y;\n\tchar txt[40];\n\tHousesType h;\n\tint kills;\n\tRemapControlType * color;\n\tTextPrintType style;\n\n\t/*\n\t** Do nothing if the sidebar isn't there\n\t*/\n\tif (!Map.IsSidebarActive) {\n\t\treturn;\n\t}\n\n//\tCC_Draw_Shape(RadarAnim, RADAR_ACTIVATED_FRAME, RADAR_X, RADAR_Y+1,\n//\t\tWINDOW_MAIN, SHAPE_NORMAL);\n\tCC_Draw_Shape(RadarFrame, 1, RadX, RadY + 1*RESFACTOR, WINDOW_MAIN, SHAPE_NORMAL);\n\n\ty = RadY + RadOffY+(2*RESFACTOR);\n\n\tFancy_Text_Print (TXT_NAME_COLON, RadX + RadOffX, y, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_6PT_GRAD | TPF_NOSHADOW);\n\tFancy_Text_Print (TXT_KILLS_COLON, RadX + RadOffX + RadIWidth - 2, y, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_RIGHT | TPF_6PT_GRAD | TPF_NOSHADOW);\n\ty += 6*RESFACTOR+1;\n\n\tLogicPage->Draw_Line(RadX + RadOffX, y, RadX + RadOffX + RadIWidth - 1, y, LTGREY);\n\ty += 2*RESFACTOR;\n\n\tfor (house = HOUSE_MULTI1; house < (HOUSE_MULTI1 + Session.MaxPlayers); house++) {\n\t\tptr = HouseClass::As_Pointer(house);\n\n\t\tif (!ptr) continue;\n\n\t\t/*\n\t\t**\tDecode this house's color\n\t\t*/\n\t\tc_idx = ptr->RemapColor;\n\n\t\tif (ptr->IsDefeated) {\n\t\t\tcolor = &GreyScheme;\n\t\t\tstyle = TPF_6PT_GRAD | TPF_NOSHADOW;\n\t\t} else {\n\t\t\tcolor = &ColorRemaps[c_idx];\n\t\t\tstyle = TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW;\n\t\t}\n\n\t\t/*\n\t\t**\tInitialize our message\n\t\t*/\n\t\ttxt[0] = 0;\n//\t\tsprintf(txt, \"%s\", ptr->Name());\n\t\tsprintf(txt, \"%s\", ptr->IsHuman ? ptr->IniName : Text_String(TXT_COMPUTER));\n\n\t\tif (strlen(txt) == 0) {\n\t\t\tstrcpy(txt,\"________\");\n\t\t}\n\n\t\t/*\n\t\t**\tPrint the player name, and the # of kills\n\t\t*/\n#ifdef WIN32\n\t\tif (strlen(txt) > 9) {\n\t\t\ttxt[9] = '.';\n\t\t\ttxt[10] = '\\0';\n\t\t}\n#else\n\t\tif (strlen(txt) > 8) {\n\t\t\ttxt[8] = '.';\n\t\t\ttxt[9] = '\\0';\n\t\t}\n#endif\n\t\tFancy_Text_Print (txt, RadX + RadOffX, y, color, TBLACK, style);\n\n\t\tkills = 0;\n\t\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\t\tkills += ptr->UnitsKilled[h];\n\t\t\tkills += ptr->BuildingsKilled[h];\n\t\t}\n\t\tsprintf(txt, \"%2d\", kills);\n\t\tFancy_Text_Print (txt, RadX + RadOffX + RadIWidth - 2, y, color, TBLACK, style | TPF_RIGHT);\n\n\t\ty += 6*RESFACTOR+1;\n\n\t}\n\n\tMap.Repair.Draw_Me(true);\n\tMap.Upgrade.Draw_Me(true);\n\tMap.Zoom.Draw_Me(true);\n}\n\n\nvoid RadarClass::Activate_Pulse(void)\n{\n\tif (IsRadarActive || PlayerPtr->IsGPSActive) {\n\t\tIsPulseActive = true;\n\t\tRadarPulseFrame = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * RadarClass::Is_Radar_Active -- Determines if the radar map is currently being displayed.    *\n *                                                                                             *\n *    Determines if the radar map is currently being displayed.                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the radar map currently being displayed as active?                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Is_Radar_Active(void)\n{\n\treturn(IsRadarActive || PlayerPtr->IsGPSActive);\n//\treturn IsRadarActive || PlayerPtr->IsGPSActive;\n}\n\n\n/***********************************************************************************************\n * RadarClass::Is_Radar_Existing -- Queries to see if radar map is available.                  *\n *                                                                                             *\n *    This will determine if the radar map is available. If available, the radar will show     *\n *    representations of terrain, units, and buildings.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the radar map available to be displayed?                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Is_Radar_Existing(void)\n{\n\treturn(DoesRadarExist || PlayerPtr->IsGPSActive);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Get_Jammed -- Fetch the current radar jammed state for the player.              *\n *                                                                                             *\n *    This will fetch the current state of the radar jamming for the player.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the radar currently jammed?                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Get_Jammed(void)\n{\n\tif(PlayerPtr->IsGPSActive) return(false);\n\treturn(IsRadarJammed);\n}\n\n\nvoid RadarClass::Flag_Cell(CELL cell)\n{\n//\tRadar_Pixel(cell);\n\tDisplayClass::Flag_Cell(cell);\n}\n"
  },
  {
    "path": "CODE/RADAR.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RADAR.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RADAR.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : December 15, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef RADAR_H\n#define RADAR_H\n\n#include\t\"display.h\"\n\nclass RadarClass: public DisplayClass\n{\n\tpublic:\n\t\tRadarClass(void);\n\t\tRadarClass(NoInitClass const & x) : DisplayClass(x) {};\n\n\t\t/*\n\t\t**\tThe dimensions and coordinates of the radar map.\n\t\t*/\n\t\tint RadX;\n\t\tint RadOffX;\n\t\tint RadY;\n\t\tint RadOffY;\n\t\tint RadWidth;\n\t\tint RadHeight;\n\t\tint RadIWidth;\n\t\tint RadIHeight;\n\t\tint RadPWidth;\n\t\tint RadPHeight;\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t\t// One-time inits\n\t\tvirtual void Init_Clear(void);\t\t\t\t\t\t// Clears all to known state\n\n\t\tvirtual void Flag_Cell(CELL cell);\n\t\tvirtual bool Map_Cell(CELL cell, HouseClass * house);\n\t\tvirtual bool Jam_Cell(CELL cell, HouseClass * house);\n\t\tvirtual bool UnJam_Cell(CELL cell, HouseClass * house);\n\t\tvirtual CELL Click_Cell_Calc(int x, int y) const;\n\t\tvirtual void AI(KeyNumType &input, int x, int y);\n\t\tvirtual void Draw_It(bool complete=false);\n\t\tvirtual void Refresh_Cells(CELL cell, short const *list);\n\t\tvirtual void Set_Map_Dimensions(int x, int y, int w, int h);\n\t\tvirtual void Set_Tactical_Position(COORDINATE coord);\n\t\tvoid\tZoom_Mode(CELL cell);\n\t\tint Click_In_Radar(int &x, int &y, bool change=false) const;\n\t\tvoid Cell_XY_To_Radar_Pixel(int cellx, int celly, int &x, int &y);\n\n\t\tbool Is_Zoomable(void) const;\n\t\tvoid Set_Radar_Position(CELL cell);\n\t\tCELL Radar_Position(void);\n\t\tbool Radar_Activate(int control);\n\t\tvoid Plot_Radar_Pixel(CELL cell);\n\t\tvoid Radar_Pixel(CELL cell);\n\t\tvoid Coord_To_Radar_Pixel(COORDINATE coord, int &x, int &y);\n\t\tvoid Cursor_Cell(CELL cell, int value);\n\t\tvoid RadarClass::Mark_Radar(int x1, int y1, int x2, int y2, int value, int barlen);\n\t\tvoid Radar_Cursor(int forced = false);\n\t\tvoid Render_Terrain(CELL cell, int x, int y, int size);\n\t\tbool Cell_On_Radar(CELL cell);\n\t\tvoid Render_Infantry(CELL cell, int x, int y, int size);\n\t\tvoid Render_Overlay(CELL cell, int x, int y, int size);\n\t\tvoid Radar_Anim(void);\n\t\tbool Is_Radar_Active(void);\n\t\tbool Is_Radar_Existing(void);\n\n\t\t/*\n\t\t** Toggles player names on & off\n\t\t*/\n\t\tvoid Player_Names(bool on);\n\t\tint Is_Player_Names(void) {return IsPlayerNames;}\n\t\tbool Spying_On_House(void) {return IsHouseSpy;}\n\t\tvoid Draw_Names(void);\n\t\tbool Draw_House_Info(void);\n\t\tint Is_Zoomed(void) {return IsZoomed;}\n\t\tbool Get_Jammed(void);\n\t\tvoid Set_Jammed(bool jam) {IsRadarJammed = jam;}\n\t\tbool Spy_Next_House(void);\n\t\tvoid Activate_Pulse(void);\n\n\tprotected:\n\n\t\t/*\n\t\t**\tRadar map constant values.\n\t\t*/\n\t\tenum RadarClassEnums {\n\t\t\tRADAR_ACTIVATED_FRAME=22,\n\t\t\tMAX_RADAR_FRAMES = 41\n\t\t};\n\n\t\t/*\n\t\t**\tIf the radar map must be completely redrawn, then this flag will be true.\n\t\t**\tTypical causes of this would be when the radar first appears, or when the\n\t\t**\tscreen has been damaged.\n\t\t*/\n\t\tunsigned IsToRedraw:1;\n\t\tunsigned RadarCursorRedraw:1;\n\n\t\t/*\n\t\t**\tIf the radar map is visible then this flag is true.\n\t\t*/\n\t\tunsigned DoesRadarExist:1;\n\t\tunsigned IsRadarActive:1;\n\t\tunsigned IsRadarActivating:1;\n\t\tunsigned IsRadarDeactivating:1;\n\t\tunsigned IsRadarJammed:1;\n\n\t\t/*\n\t\t** Flag to tell whether sonar pulse should be displayed on radar map\n\t\t*/\n\t\tunsigned IsPulseActive:1;\n\t\tint\tRadarPulseFrame;\n\n\t\t/*\n\t\t** Special radar frame is set when a new location is selected on the\n\t\t** radar map.  It counts down through the special radar cursors until\n\t\t** either the radar cursor becomes normal or the radar cursor is moved\n\t\t** again.\n\t\t*/\n\t\tint SpecialRadarFrame;\n\t\tint RadarAnimFrame;\n\n\t\tstatic void const * RadarAnim;\n\t\tstatic void const * RadarPulse;\n\t\tstatic void const * RadarFrame;\n\n\t\t/*\n\t\t**\tThis gadget class is used for capturing input to the tactical map. All mouse input\n\t\t**\twill be routed through this gadget.\n\t\t*/\n\t\tclass RTacticalClass : public GadgetClass {\n\t\t\tpublic:\n\t\t\t\tRTacticalClass(void) : GadgetClass(0,0,0,0,LEFTPRESS|LEFTRELEASE|LEFTHELD|LEFTUP|RIGHTPRESS,true) {};\n\n\t\t\tprotected:\n\t\t\t\tvirtual int Action(unsigned flags, KeyNumType & key);\n\t\t\tfriend class RadarClass;\n\t\t};\n\t\tfriend class RTacticalClass;\n\n\t\t/*\n\t\t**\tThis is the \"button\" that tracks all input to the tactical map.\n\t\t** It must be available to derived classes, for Save/Load purposes.\n\t\t*/\n\t\tstatic RTacticalClass RadarButton;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThe current radar position as the upper left corner cell for the\n\t\t**\tradar map display. The width and height is controlled by the\n\t\t**\tactual dimensions of the radar map display box (in pixels).\n\t\t*/\n\t\tunsigned RadarX;\n\t\tunsigned RadarY;\n\t\tunsigned RadarCellWidth;\n\t\tunsigned RadarCellHeight;\n\t\tunsigned RadarCell;\n\n\t\t/*\n\t\t**\tThis is the origin (pixel offsets) for the upper left corner\n\t\t**\tof the radar map within the full radar map area of the screen.\n\t\t**\tThis is biased so that the radar map, when smaller than full\n\t\t**\tsize will appear centered.\n\t\t*/\n\t\tunsigned BaseX;\n\t\tunsigned BaseY;\n\n\t\tunsigned RadarWidth;\n\t\tunsigned RadarHeight;\n\n\t\t/*\n\t\t**\tIf the radar map is in zoom mode, then this value will be true.\n\t\t*/\n\t\tunsigned IsZoomed:1;\n\n\t\t/*\n\t\t** This flag is true if the radar map is in its special show-the-player\n\t\t** names mode.\n\t\t*/\n\t\tunsigned IsPlayerNames:1;\n\n\t\t/*\n\t\t** This flag is true if the radar map is in its special show-the-units\n\t\t** of-another-house mode.\n\t\t*/\n\t\tunsigned IsHouseSpy:1;\n\n\t\t/*\n\t\t**\tThis is the zoom factor to use. This value is the number of pixels wide\n\t\t**\teach cell will occupy on the radar map. Completely zoomed out would be a\n\t\t**\tvalue of 1.\n\t\t*/\n\t\tint ZoomFactor;\n\n\t\t/*\n\t\t** If we're spying on a house's radar facility, this field shows the\n\t\t** name of the house we're spying on.\n\t\t*/\n\t\tHousesType SpyingOn;\n\n\t\t/*\n\t\t**\tThis is the list of radar pixels that need to be updated. Only a partial\n\t\t**\tlist is maintained for maximum speed.\n\t\t*/\n\t\tunsigned PixelPtr;\n\t\tenum PixelStackEnums {PIXELSTACK=400};\n\t\tCELL PixelStack[PIXELSTACK];\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/RADIO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RADIO.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RADIO.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : June 5, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RadioClass::Debug_Dump -- Displays the current status of the radio to the mono monitor.   *\n *   RadioClass::Limbo -- When limboing a unit will always break radio contact.                *\n *   RadioClass::Receive_Message -- Handles receipt of a radio message.                        *\n *   RadioClass::Transmit_Message -- Transmit message from one object to another.              *\n *   RadioClass::Transmit_Message -- Transmits a message to the object specified.              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/*\n**\tThese are the text representations of the radio messages that can be transmitted.\n*/\nchar const * RadioClass::Messages[RADIO_COUNT] = {\n\t\"static (no message)\",\n\t\"Roger.\",\n\t\"Come in.\",\n\t\"Over and out.\",\n\t\"Requesting transport.\",\n\t\"Attach to transport.\",\n\t\"I've got a delivery for you.\",\n\t\"I'm performing load/unload maneuver. Be careful.\",\n\t\"I'm clear.\",\n\t\"You are clear to unload. Driving away now.\",\n\t\"Am unable to comply.\",\n\t\"I'm starting construction now... act busy.\",\n\t\"I've finished construction. You are free.\",\n\t\"We bumped, redraw yourself please.\",\n\t\"I'm trying to load up now.\",\n\t\"May I become a passenger?\",\n\t\"Are you ready to receive shipment?\",\n\t\"Are you trying to become a passenger?\",\n\t\"Move to location X.\",\n\t\"Do you need to move?\",\n\t\"All right already. Now what?\",\n\t\"I'm a passenger now.\",\n\t\"Backup into refinery now.\",\n\t\"Run away!\",\n\t\"Tether established.\",\n\t\"Tether broken.\",\n\t\"Repair one step.\",\n\t\"Are you prepared to fight?\",\n\t\"Attack this target please.\",\n\t\"Reload one step.\",\n\t\"Circumstances prevent success.\",\n\t\"All done with the request.\",\n\t\"Do you need service depot work?\",\n\t\"Are you sitting on service depot?\"\n};\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * RadioClass::Debug_Dump -- Displays the current status of the radio to the mono monitor.     *\n *                                                                                             *\n *    This displays the radio connection value to the monochrome monitor.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RadioClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(IsActive);\n\n\tmono->Set_Cursor(29, 7);mono->Printf(\"0-%-47s\", Messages[Old[0]]);\n\tmono->Set_Cursor(29, 8);mono->Printf(\"1-%-47s\", Messages[Old[1]]);\n\tmono->Set_Cursor(29, 9);mono->Printf(\"2-%-47s\", Messages[Old[2]]);\n\tif (Radio) {\n\t\tmono->Set_Cursor(20, 7);mono->Printf(\"%08X\", Radio->As_Target());\n\t}\n\tMissionClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * RadioClass::Receive_Message -- Handles receipt of a radio message.                          *\n *                                                                                             *\n *    This is the base version of what should happen when a radio message is received. It      *\n *    turns the radio off when the \"OVER_OUT\" message is received. All other messages are      *\n *    merely acknowledged with a \"ROGER\".                                                      *\n *                                                                                             *\n * INPUT:   from     -- The object that is initiating this radio message (always valid).       *\n *                                                                                             *\n *          message  -- The radio message received.                                            *\n *                                                                                             *\n *          param    -- Reference to optional value that might be used to return more          *\n *                      information than can be conveyed in the simple radio response          *\n *                      messages.                                                              *\n *                                                                                             *\n * OUTPUT:  Returns with the response radio message.                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *   09/24/1994 JLB : Streamlined to be only a communications carrier.                         *\n *   05/22/1995 JLB : Recognized who is sending the message                                    *\n *   06/05/1996 JLB : Radio message history tracking.                                          *\n *=============================================================================================*/\nRadioMessageType RadioClass::Receive_Message(RadioClass * from, RadioMessageType message, long & param)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tKeep a record of the last message received by this radio.\n\t*/\n\tif (message != Old[0]) {\n\t\tOld[2] = Old[1];\n\t\tOld[1] = Old[0];\n\t\tOld[0] = message;\n\t}\n\n\t/*\n\t**\tWhen this message is received, it means that the other object\n\t**\thas already turned its radio off. Turn this radio off as well.\n\t**\tThis only applies if the message is coming from the object that\n\t**\thas an established conversation with this object.\n\t*/\n\tif (from == Radio && message == RADIO_OVER_OUT) {\n\t\tMissionClass::Receive_Message(from, message, param);\n\t\tRadio_Off();\n\t\treturn(RADIO_ROGER);\n\t}\n\n\t/*\n\t**\tThe \"hello\" message is an attempt to establish contact. If this radio\n\t**\tis already in an established conversation with another object, then\n\t**\treturn with \"negative\". If all is well, return with \"roger\".\n\t*/\n\tif (message == RADIO_HELLO && Strength) {\n\t\tif (Radio == from || Radio == NULL) {\n\t\t\tRadio = from;\n\t\t\treturn(RADIO_ROGER);\n\t\t}\n\t\treturn(RADIO_NEGATIVE);\n\t}\n\n\treturn(MissionClass::Receive_Message(from, message, param));\n}\n\n\n/***********************************************************************************************\n * RadioClass::Transmit_Message -- Transmit message from one object to another.                *\n *                                                                                             *\n *    This routine is used to transmit a radio message from this object to another. Most       *\n *    inter object coordination is handled through this mechanism.                             *\n *                                                                                             *\n * INPUT:   to       -- Pointer to the object that will receive the radio message.             *\n *                                                                                             *\n *          message  -- The message itself (see RadioType).                                    *\n *                                                                                             *\n *          param    -- Optional reference to parameter that might be used to pass or          *\n *                      receive additional information.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with the response radio message from the receiving object.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nRadioMessageType RadioClass::Transmit_Message(RadioMessageType message, long & param, RadioClass * to)\n{\n\tassert(IsActive);\n\n\tif (to == NULL) {\n\t\tto = Contact_With_Whom();\n\t}\n\n\t/*\n\t**\tIf there is no target for the radio message, then always return static.\n\t*/\n\tif (to == NULL) return(RADIO_STATIC);\n\n\t/*\n\t**\tHandle some special case processing that occurs when certain messages\n\t**\tare transmitted.\n\t*/\n\tif (to == Radio && message == RADIO_OVER_OUT) {\n\t\tRadio = 0;\n\t}\n\n\t/*\n\t**\tIf this object is not in radio contact but the message\n\t**\tindicates that radio contact should be established, then\n\t**\ttry to do so. If the other party agrees then contact\n\t**\tis established.\n\t*/\n\tif (message == RADIO_HELLO) {\n\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\tif (to->Receive_Message(this, message, param) == RADIO_ROGER) {\n\t\t\tRadio = to;\n\t\t\treturn(RADIO_ROGER);\n\t\t}\n\t\treturn(RADIO_NEGATIVE);\n\t}\n\n\treturn(to->Receive_Message(this, message, param));\n}\n\n\n/***********************************************************************************************\n * RadioClass::Limbo -- When limboing a unit will always break radio contact.                  *\n *                                                                                             *\n *    This routine will break radio contact as the object is entering limbo state.             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the object successfully limboed?                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RadioClass::Limbo(void)\n{\n\tassert(IsActive);\n\n\tif (!IsInLimbo) {\n\t\tTransmit_Message(RADIO_OVER_OUT);\n\t}\n\treturn(MissionClass::Limbo());\n}\n\n\n/***********************************************************************************************\n * RadioClass::Transmit_Message -- Transmits a message to the object specified.                *\n *                                                                                             *\n *    This routine will transmit the specified message to the object. This routine differs     *\n *    from the normal Transmit_Message in that the LParam value is \"faked\" into the            *\n *    parameter list. It is presumed that the message sent with this function does not         *\n *    require the LParam.                                                                      *\n *                                                                                             *\n * INPUT:   message  -- The message to transmit.                                               *\n *                                                                                             *\n *          to       -- The requested receiver of this message.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the radio response from the receiver.                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nRadioMessageType RadioClass::Transmit_Message(RadioMessageType message, RadioClass * to)\n{\n\tassert(IsActive);\n\n\treturn(Transmit_Message(message, LParam, to));\n}\n"
  },
  {
    "path": "CODE/RADIO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RADIO.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RADIO.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 23, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef RADIO_H\n#define RADIO_H\n\n#include\t\"mission.h\"\n\nclass ObjectClass;\nclass TechnoClass;\n\n\n/****************************************************************************\n**\tRadio contact is controlled by this class. It handles the mundane chore\n**\tof keeping the radio contact alive as well as broadcasting messages\n**\tto the receiving radio. Radio contact is primarily used when one object\n**\tis in \"command\" of another.\n*/\nclass RadioClass : public MissionClass {\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is a record of the last message received by this receiver.\n\t\t*/\n\t\tRadioMessageType Old[3];\n\n\t\t/*\n\t\t**\tThis is the object that radio communication has been established\n\t\t**\twith. Although is is only a one-way reference, it is required that\n\t\t**\tthe receiving radio is also tuned to the object that contains this\n\t\t**\tradio set.\n\t\t*/\n\t\tRadioClass * Radio;\n\n\t\t/*\n\t\t**\tThis is a text representation of all the possible radio messages. This\n\t\t**\ttext is used for monochrome debug printing.\n\t\t*/\n\t\tstatic char const * Messages[RADIO_COUNT];\n\n\tpublic:\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tRadioClass(RTTIType rtti, int id) : MissionClass(rtti, id), Radio(0) {};\n\t\tRadioClass(NoInitClass const & x) : MissionClass(x) {};\n\t\tvirtual ~RadioClass(void) {Radio=0;};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tbool In_Radio_Contact(void) const {return (Radio != 0);};\n\t\tvoid Radio_Off(void) {Radio = 0;};\n\t\tTechnoClass * Contact_With_Whom(void) const {return (TechnoClass *)Radio;};\n\n\t\t// Inherited from base class(es).\n\t\tvirtual RadioMessageType Receive_Message(RadioClass * from, RadioMessageType message, long & param);\n\t\tvirtual RadioMessageType Transmit_Message(RadioMessageType message, long & param=LParam, RadioClass * to=NULL);\n\t\tvirtual RadioMessageType Transmit_Message(RadioMessageType message, RadioClass * to);\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\t\tvirtual bool Limbo(void);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n};\n\n#endif\n"
  },
  {
    "path": "CODE/RADOS.PJT",
    "content": ";Codewright Project File (do not remove or modify this line)\n[ProjInit]\nProjSetConfigFlags=0x00010140\n\n[Files]\nC:\\PROJECTS\\C&Czero\\code\\2KEYFRAM.CPP\nC:\\PROJECTS\\C&Czero\\code\\aadata.cpp\nC:\\PROJECTS\\C&Czero\\code\\abstract.cpp\nC:\\PROJECTS\\C&Czero\\code\\abstract.h\nC:\\PROJECTS\\C&Czero\\code\\adata.cpp\nC:\\PROJECTS\\C&Czero\\code\\adpcm.cpp\nC:\\PROJECTS\\C&Czero\\code\\aircraft.cpp\nC:\\PROJECTS\\C&Czero\\code\\aircraft.h\nC:\\PROJECTS\\C&Czero\\code\\anim.cpp\nC:\\PROJECTS\\C&Czero\\code\\anim.h\nC:\\PROJECTS\\C&Czero\\code\\audio.cpp\nC:\\PROJECTS\\C&Czero\\code\\audio.h\nC:\\PROJECTS\\C&Czero\\code\\base.cpp\nC:\\PROJECTS\\C&Czero\\code\\base.h\nC:\\PROJECTS\\C&Czero\\code\\bbdata.cpp\nC:\\PROJECTS\\C&Czero\\code\\bdata.cpp\nC:\\PROJECTS\\C&Czero\\code\\bfiofile.cpp\nC:\\PROJECTS\\C&Czero\\code\\BFIOFILE.H\nC:\\PROJECTS\\C&Czero\\code\\BLOWFISH.CPP\nC:\\PROJECTS\\C&Czero\\code\\BLOWFISH.H\nC:\\PROJECTS\\C&Czero\\code\\BUFFERX.H\nC:\\PROJECTS\\C&Czero\\code\\building.cpp\nC:\\PROJECTS\\C&Czero\\code\\building.h\nC:\\PROJECTS\\C&Czero\\code\\bullet.cpp\nC:\\PROJECTS\\C&Czero\\code\\bullet.h\nC:\\PROJECTS\\C&Czero\\code\\cargo.cpp\nC:\\PROJECTS\\C&Czero\\code\\cargo.h\nC:\\PROJECTS\\C&Czero\\code\\carry.cpp\nC:\\PROJECTS\\C&Czero\\code\\carry.h\nC:\\PROJECTS\\C&Czero\\code\\ccfile.cpp\nC:\\PROJECTS\\C&Czero\\code\\ccfile.h\nC:\\PROJECTS\\C&Czero\\code\\ccini.cpp\nC:\\PROJECTS\\C&Czero\\code\\ccini.h\nC:\\PROJECTS\\C&Czero\\code\\cdata.cpp\nC:\\PROJECTS\\C&Czero\\code\\cdfile.cpp\nC:\\PROJECTS\\C&Czero\\code\\cdfile.h\nC:\\PROJECTS\\C&Czero\\code\\cell.cpp\nC:\\PROJECTS\\C&Czero\\code\\cell.h\nC:\\PROJECTS\\C&Czero\\code\\checkbox.cpp\nC:\\PROJECTS\\C&Czero\\code\\checkbox.h\nC:\\PROJECTS\\C&Czero\\code\\cheklist.cpp\nC:\\PROJECTS\\C&Czero\\code\\cheklist.h\nC:\\PROJECTS\\C&Czero\\code\\colrlist.cpp\nC:\\PROJECTS\\C&Czero\\code\\colrlist.h\nC:\\PROJECTS\\C&Czero\\code\\combat.cpp\nC:\\PROJECTS\\C&Czero\\code\\combuf.cpp\nC:\\PROJECTS\\C&Czero\\code\\combuf.h\nC:\\PROJECTS\\C&Czero\\code\\compat.h\nC:\\PROJECTS\\C&Czero\\code\\confdlg.cpp\nC:\\PROJECTS\\C&Czero\\code\\confdlg.h\nC:\\PROJECTS\\C&Czero\\code\\connect.cpp\nC:\\PROJECTS\\C&Czero\\code\\connect.h\nC:\\PROJECTS\\C&Czero\\code\\connmgr.h\nC:\\PROJECTS\\C&Czero\\code\\conquer.cpp\nC:\\PROJECTS\\C&Czero\\code\\conquer.h\nC:\\PROJECTS\\C&Czero\\code\\const.cpp\nC:\\PROJECTS\\C&Czero\\code\\control.cpp\nC:\\PROJECTS\\C&Czero\\code\\control.h\nC:\\PROJECTS\\C&Czero\\code\\coord.cpp\nC:\\PROJECTS\\C&Czero\\code\\crc.cpp\nC:\\PROJECTS\\C&Czero\\code\\crc.h\nC:\\PROJECTS\\C&Czero\\code\\credits.cpp\nC:\\PROJECTS\\C&Czero\\code\\credits.h\nC:\\PROJECTS\\C&Czero\\code\\crew.cpp\nC:\\PROJECTS\\C&Czero\\code\\crew.h\nC:\\PROJECTS\\C&Czero\\code\\debug.cpp\nC:\\PROJECTS\\C&Czero\\code\\debug.h\nC:\\PROJECTS\\C&Czero\\code\\defines.h\nC:\\PROJECTS\\C&Czero\\code\\descdlg.cpp\nC:\\PROJECTS\\C&Czero\\code\\descdlg.h\nC:\\PROJECTS\\C&Czero\\code\\dial8.cpp\nC:\\PROJECTS\\C&Czero\\code\\dial8.h\nC:\\PROJECTS\\C&Czero\\code\\dialog.cpp\nC:\\PROJECTS\\C&Czero\\code\\display.cpp\nC:\\PROJECTS\\C&Czero\\code\\display.h\nC:\\PROJECTS\\C&Czero\\code\\door.cpp\nC:\\PROJECTS\\C&Czero\\code\\door.h\nC:\\PROJECTS\\C&Czero\\code\\dpmi.cpp\nC:\\PROJECTS\\C&Czero\\code\\dpmi.h\nC:\\PROJECTS\\C&Czero\\code\\drive.cpp\nC:\\PROJECTS\\C&Czero\\code\\drive.h\nC:\\PROJECTS\\C&Czero\\code\\drop.cpp\nC:\\PROJECTS\\C&Czero\\code\\drop.h\nC:\\PROJECTS\\C&Czero\\code\\dtable.cpp\nC:\\PROJECTS\\C&Czero\\code\\edit.cpp\nC:\\PROJECTS\\C&Czero\\code\\edit.h\nC:\\PROJECTS\\C&Czero\\code\\ending.cpp\nC:\\PROJECTS\\C&Czero\\code\\ending.h\nC:\\PROJECTS\\C&Czero\\code\\event.cpp\nC:\\PROJECTS\\C&Czero\\code\\event.h\nC:\\PROJECTS\\C&Czero\\code\\expand.cpp\nC:\\PROJECTS\\C&Czero\\code\\externs.h\nC:\\PROJECTS\\C&Czero\\code\\face.cpp\nC:\\PROJECTS\\C&Czero\\code\\face.h\nC:\\PROJECTS\\C&Czero\\code\\facing.cpp\nC:\\PROJECTS\\C&Czero\\code\\facing.h\nC:\\PROJECTS\\C&Czero\\code\\factory.cpp\nC:\\PROJECTS\\C&Czero\\code\\factory.h\nC:\\PROJECTS\\C&Czero\\code\\FILEPCX.H\nC:\\PROJECTS\\C&Czero\\code\\findpath.cpp\nC:\\PROJECTS\\C&Czero\\code\\flasher.cpp\nC:\\PROJECTS\\C&Czero\\code\\flasher.h\nC:\\PROJECTS\\C&Czero\\code\\fly.cpp\nC:\\PROJECTS\\C&Czero\\code\\fly.h\nC:\\PROJECTS\\C&Czero\\code\\foot.cpp\nC:\\PROJECTS\\C&Czero\\code\\foot.h\nC:\\PROJECTS\\C&Czero\\code\\ftimer.h\nC:\\PROJECTS\\C&Czero\\code\\function.h\nC:\\PROJECTS\\C&Czero\\code\\fuse.cpp\nC:\\PROJECTS\\C&Czero\\code\\fuse.h\nC:\\PROJECTS\\C&Czero\\code\\gadget.cpp\nC:\\PROJECTS\\C&Czero\\code\\gadget.h\nC:\\PROJECTS\\C&Czero\\code\\gamedlg.cpp\nC:\\PROJECTS\\C&Czero\\code\\gamedlg.h\nC:\\PROJECTS\\C&Czero\\code\\gauge.cpp\nC:\\PROJECTS\\C&Czero\\code\\gauge.h\nC:\\PROJECTS\\C&Czero\\code\\globals.cpp\nC:\\PROJECTS\\C&Czero\\code\\goptions.cpp\nC:\\PROJECTS\\C&Czero\\code\\goptions.h\nC:\\PROJECTS\\C&Czero\\code\\gscreen.cpp\nC:\\PROJECTS\\C&Czero\\code\\gscreen.h\nC:\\PROJECTS\\C&Czero\\code\\hdata.cpp\nC:\\PROJECTS\\C&Czero\\code\\heap.cpp\nC:\\PROJECTS\\C&Czero\\code\\heap.h\nC:\\PROJECTS\\C&Czero\\code\\help.cpp\nC:\\PROJECTS\\C&Czero\\code\\help.h\nC:\\PROJECTS\\C&Czero\\code\\house.cpp\nC:\\PROJECTS\\C&Czero\\code\\house.h\nC:\\PROJECTS\\C&Czero\\code\\hsv.cpp\nC:\\PROJECTS\\C&Czero\\code\\HSV.H\nC:\\PROJECTS\\C&Czero\\code\\idata.cpp\nC:\\PROJECTS\\C&Czero\\code\\infantry.cpp\nC:\\PROJECTS\\C&Czero\\code\\infantry.h\nC:\\PROJECTS\\C&Czero\\code\\ini.cpp\nC:\\PROJECTS\\C&Czero\\code\\ini.h\nC:\\PROJECTS\\C&Czero\\code\\inibin.cpp\nC:\\PROJECTS\\C&Czero\\code\\inicode.cpp\nC:\\PROJECTS\\C&Czero\\code\\init.cpp\nC:\\PROJECTS\\C&Czero\\code\\INT.CPP\nC:\\PROJECTS\\C&Czero\\code\\INT.H\nC:\\PROJECTS\\C&Czero\\code\\interpal.cpp\nC:\\PROJECTS\\C&Czero\\code\\intro.cpp\nC:\\PROJECTS\\C&Czero\\code\\intro.h\nC:\\PROJECTS\\C&Czero\\code\\iomap.cpp\nC:\\PROJECTS\\C&Czero\\code\\ioobj.cpp\nC:\\PROJECTS\\C&Czero\\code\\ipx.cpp\nC:\\PROJECTS\\C&Czero\\code\\ipx.h\nC:\\PROJECTS\\C&Czero\\code\\ipxaddr.cpp\nC:\\PROJECTS\\C&Czero\\code\\ipxaddr.h\nC:\\PROJECTS\\C&Czero\\code\\ipxconn.cpp\nC:\\PROJECTS\\C&Czero\\code\\ipxconn.h\nC:\\PROJECTS\\C&Czero\\code\\ipxgconn.cpp\nC:\\PROJECTS\\C&Czero\\code\\ipxgconn.h\nC:\\PROJECTS\\C&Czero\\code\\ipxmgr.cpp\nC:\\PROJECTS\\C&Czero\\code\\ipxmgr.h\nC:\\PROJECTS\\C&Czero\\code\\itable.cpp\nC:\\PROJECTS\\C&Czero\\code\\jshell.cpp\nC:\\PROJECTS\\C&Czero\\code\\jshell.h\nC:\\PROJECTS\\C&Czero\\code\\keyframe.cpp\nC:\\PROJECTS\\C&Czero\\code\\language.h\nC:\\PROJECTS\\C&Czero\\code\\layer.cpp\nC:\\PROJECTS\\C&Czero\\code\\layer.h\nC:\\PROJECTS\\C&Czero\\code\\lcwuncmp.cpp\nC:\\PROJECTS\\C&Czero\\code\\led.h\nC:\\PROJECTS\\C&Czero\\code\\link.cpp\nC:\\PROJECTS\\C&Czero\\code\\link.h\nC:\\PROJECTS\\C&Czero\\code\\lint.h\nC:\\PROJECTS\\C&Czero\\code\\list.cpp\nC:\\PROJECTS\\C&Czero\\code\\list.h\nC:\\PROJECTS\\C&Czero\\code\\listnode.h\nC:\\PROJECTS\\C&Czero\\code\\loaddlg.cpp\nC:\\PROJECTS\\C&Czero\\code\\loaddlg.h\nC:\\PROJECTS\\C&Czero\\code\\logic.cpp\nC:\\PROJECTS\\C&Czero\\code\\logic.h\nC:\\PROJECTS\\C&Czero\\code\\map.cpp\nC:\\PROJECTS\\C&Czero\\code\\map.h\nC:\\PROJECTS\\C&Czero\\code\\mapeddlg.cpp\nC:\\PROJECTS\\C&Czero\\code\\mapedit.cpp\nC:\\PROJECTS\\C&Czero\\code\\mapedit.h\nC:\\PROJECTS\\C&Czero\\code\\mapedplc.cpp\nC:\\PROJECTS\\C&Czero\\code\\mapedsel.cpp\nC:\\PROJECTS\\C&Czero\\code\\mapedtm.cpp\nC:\\PROJECTS\\C&Czero\\code\\mapsel.cpp\nC:\\PROJECTS\\C&Czero\\code\\menus.cpp\nC:\\PROJECTS\\C&Czero\\code\\message.h\nC:\\PROJECTS\\C&Czero\\code\\mission.cpp\nC:\\PROJECTS\\C&Czero\\code\\mission.h\nC:\\PROJECTS\\C&Czero\\code\\mixfile.cpp\nC:\\PROJECTS\\C&Czero\\code\\mixfile.h\nC:\\PROJECTS\\C&Czero\\code\\monoc.cpp\nC:\\PROJECTS\\C&Czero\\code\\monoc.h\nC:\\PROJECTS\\C&Czero\\code\\mouse.cpp\nC:\\PROJECTS\\C&Czero\\code\\mouse.h\nC:\\PROJECTS\\C&Czero\\code\\MP.CPP\nC:\\PROJECTS\\C&Czero\\code\\MP.H\nC:\\PROJECTS\\C&Czero\\code\\mplayer.cpp\nC:\\PROJECTS\\C&Czero\\code\\msgbox.cpp\nC:\\PROJECTS\\C&Czero\\code\\msgbox.h\nC:\\PROJECTS\\C&Czero\\code\\msglist.cpp\nC:\\PROJECTS\\C&Czero\\code\\msglist.h\nC:\\PROJECTS\\C&Czero\\code\\netdlg.cpp\nC:\\PROJECTS\\C&Czero\\code\\nullconn.cpp\nC:\\PROJECTS\\C&Czero\\code\\nullconn.h\nC:\\PROJECTS\\C&Czero\\code\\nulldlg.cpp\nC:\\PROJECTS\\C&Czero\\code\\nullmgr.cpp\nC:\\PROJECTS\\C&Czero\\code\\nullmgr.h\nC:\\PROJECTS\\C&Czero\\code\\object.cpp\nC:\\PROJECTS\\C&Czero\\code\\object.h\nC:\\PROJECTS\\C&Czero\\code\\odata.cpp\nC:\\PROJECTS\\C&Czero\\code\\options.cpp\nC:\\PROJECTS\\C&Czero\\code\\options.h\nC:\\PROJECTS\\C&Czero\\code\\overlay.cpp\nC:\\PROJECTS\\C&Czero\\code\\overlay.h\nC:\\PROJECTS\\C&Czero\\code\\palette.cpp\nC:\\PROJECTS\\C&Czero\\code\\PALETTE.H\nC:\\PROJECTS\\C&Czero\\code\\phone.h\nC:\\PROJECTS\\C&Czero\\code\\power.cpp\nC:\\PROJECTS\\C&Czero\\code\\power.h\nC:\\PROJECTS\\C&Czero\\code\\profile.cpp\nC:\\PROJECTS\\C&Czero\\code\\queue.cpp\nC:\\PROJECTS\\C&Czero\\code\\queue.h\nC:\\PROJECTS\\C&Czero\\code\\radar.cpp\nC:\\PROJECTS\\C&Czero\\code\\radar.h\nC:\\PROJECTS\\C&Czero\\code\\radio.cpp\nC:\\PROJECTS\\C&Czero\\code\\radio.h\nC:\\PROJECTS\\C&Czero\\code\\rand.cpp\nC:\\PROJECTS\\C&Czero\\code\\random.cpp\nC:\\PROJECTS\\C&Czero\\code\\RANDOM.H\nC:\\PROJECTS\\C&Czero\\code\\rawfile.cpp\nC:\\PROJECTS\\C&Czero\\code\\rawfile.h\nC:\\PROJECTS\\C&Czero\\code\\region.h\nC:\\PROJECTS\\C&Czero\\code\\reinf.cpp\nC:\\PROJECTS\\C&Czero\\code\\rgb.cpp\nC:\\PROJECTS\\C&Czero\\code\\RGB.H\nC:\\PROJECTS\\C&Czero\\code\\RNG.H\nC:\\PROJECTS\\C&Czero\\code\\rotbmp.cpp\nC:\\PROJECTS\\C&Czero\\code\\ROTBMP.H\nC:\\PROJECTS\\C&Czero\\code\\rules.cpp\nC:\\PROJECTS\\C&Czero\\code\\rules.h\nC:\\PROJECTS\\C&Czero\\code\\savedlg.h\nC:\\PROJECTS\\C&Czero\\code\\saveload.cpp\nC:\\PROJECTS\\C&Czero\\code\\scenario.cpp\nC:\\PROJECTS\\C&Czero\\code\\SCENARIO.H\nC:\\PROJECTS\\C&Czero\\code\\score.cpp\nC:\\PROJECTS\\C&Czero\\code\\score.h\nC:\\PROJECTS\\C&Czero\\code\\screen.h\nC:\\PROJECTS\\C&Czero\\code\\scroll.cpp\nC:\\PROJECTS\\C&Czero\\code\\scroll.h\nC:\\PROJECTS\\C&Czero\\code\\sdata.cpp\nC:\\PROJECTS\\C&Czero\\code\\session.cpp\nC:\\PROJECTS\\C&Czero\\code\\SESSION.H\nC:\\PROJECTS\\C&Czero\\code\\SHA.CPP\nC:\\PROJECTS\\C&Czero\\code\\SHA.H\nC:\\PROJECTS\\C&Czero\\code\\shapebtn.cpp\nC:\\PROJECTS\\C&Czero\\code\\shapebtn.h\nC:\\PROJECTS\\C&Czero\\code\\sidebar.cpp\nC:\\PROJECTS\\C&Czero\\code\\sidebar.h\nC:\\PROJECTS\\C&Czero\\code\\slider.cpp\nC:\\PROJECTS\\C&Czero\\code\\slider.h\nC:\\PROJECTS\\C&Czero\\code\\smudge.cpp\nC:\\PROJECTS\\C&Czero\\code\\smudge.h\nC:\\PROJECTS\\C&Czero\\code\\sounddlg.cpp\nC:\\PROJECTS\\C&Czero\\code\\sounddlg.h\nC:\\PROJECTS\\C&Czero\\code\\special.cpp\nC:\\PROJECTS\\C&Czero\\code\\special.h\nC:\\PROJECTS\\C&Czero\\code\\sprite.cpp\nC:\\PROJECTS\\C&Czero\\code\\stage.h\nC:\\PROJECTS\\C&Czero\\code\\startup.cpp\nC:\\PROJECTS\\C&Czero\\code\\super.cpp\nC:\\PROJECTS\\C&Czero\\code\\super.h\nC:\\PROJECTS\\C&Czero\\code\\tab.cpp\nC:\\PROJECTS\\C&Czero\\code\\tab.h\nC:\\PROJECTS\\C&Czero\\code\\taction.cpp\nC:\\PROJECTS\\C&Czero\\code\\TACTION.H\nC:\\PROJECTS\\C&Czero\\code\\tarcom.cpp\nC:\\PROJECTS\\C&Czero\\code\\target.cpp\nC:\\PROJECTS\\C&Czero\\code\\target.h\nC:\\PROJECTS\\C&Czero\\code\\tcpip.h\nC:\\PROJECTS\\C&Czero\\code\\tdata.cpp\nC:\\PROJECTS\\C&Czero\\code\\team.cpp\nC:\\PROJECTS\\C&Czero\\code\\team.h\nC:\\PROJECTS\\C&Czero\\code\\teamtype.cpp\nC:\\PROJECTS\\C&Czero\\code\\teamtype.h\nC:\\PROJECTS\\C&Czero\\code\\techno.cpp\nC:\\PROJECTS\\C&Czero\\code\\techno.h\nC:\\PROJECTS\\C&Czero\\code\\template.cpp\nC:\\PROJECTS\\C&Czero\\code\\template.h\nC:\\PROJECTS\\C&Czero\\code\\terrain.cpp\nC:\\PROJECTS\\C&Czero\\code\\terrain.h\nC:\\PROJECTS\\C&Czero\\code\\tevent.cpp\nC:\\PROJECTS\\C&Czero\\code\\TEVENT.H\nC:\\PROJECTS\\C&Czero\\code\\textbtn.cpp\nC:\\PROJECTS\\C&Czero\\code\\textbtn.h\nC:\\PROJECTS\\C&Czero\\code\\theme.cpp\nC:\\PROJECTS\\C&Czero\\code\\theme.h\nC:\\PROJECTS\\C&Czero\\code\\toggle.cpp\nC:\\PROJECTS\\C&Czero\\code\\toggle.h\nC:\\PROJECTS\\C&Czero\\code\\trigger.cpp\nC:\\PROJECTS\\C&Czero\\code\\trigger.h\nC:\\PROJECTS\\C&Czero\\code\\txtlabel.cpp\nC:\\PROJECTS\\C&Czero\\code\\txtlabel.h\nC:\\PROJECTS\\C&Czero\\code\\type.h\nC:\\PROJECTS\\C&Czero\\code\\udata.cpp\nC:\\PROJECTS\\C&Czero\\code\\unit.cpp\nC:\\PROJECTS\\C&Czero\\code\\unit.h\nC:\\PROJECTS\\C&Czero\\code\\vdata.cpp\nC:\\PROJECTS\\C&Czero\\code\\vector.cpp\nC:\\PROJECTS\\C&Czero\\code\\vector.h\nC:\\PROJECTS\\C&Czero\\code\\version.cpp\nC:\\PROJECTS\\C&Czero\\code\\VERSION.H\nC:\\PROJECTS\\C&Czero\\code\\vessel.cpp\nC:\\PROJECTS\\C&Czero\\code\\vessel.h\nC:\\PROJECTS\\C&Czero\\code\\visudlg.cpp\nC:\\PROJECTS\\C&Czero\\code\\visudlg.h\nC:\\PROJECTS\\C&Czero\\code\\warhead.cpp\nC:\\PROJECTS\\C&Czero\\code\\warhead.h\nC:\\PROJECTS\\C&Czero\\code\\watcom.h\nC:\\PROJECTS\\C&Czero\\code\\weapon.cpp\nC:\\PROJECTS\\C&Czero\\code\\weapon.h\nC:\\PROJECTS\\C&Czero\\code\\winstub.cpp\nC:\\PROJECTS\\C&Czero\\code\\wwfile.h\n\n\n[State]\nSysSetCwd='C:\\projects\\c&czero\\code'\nSrchSetFlags=0x000320aa\nFileSortMode=0x0\nStateWindowFrame=62,134,923,511,0x62c9f5fa\n_StateWindow=0,0,990,647,0x00100018,'C:\\projects\\c&czero\\code\\RECT.CPP',240,15,244,32,32,0,32,32,32,32,8,4294967295,4294967295,1,10,'',12,255,48,0,7,243,252,253,247,249,247,24,1,400,0,246,252,248,244,247,15,15,15,15,0,0\n_StateWindow=0,0,990,647,0x00100008,'C:\\projects\\c&czero\\code\\eng\\conquer.txt',240,15,244,32,32,0,32,32,32,32,8,4294967295,4294967295,0,10,'',12,255,48,0,7,243,252,253,247,249,247,1,1,400,0,246,252,248,244,247,15,15,15,15,0,0\n_StateBuffer='C:\\projects\\c&czero\\code\\RECT.CPP',0x0400048e,24,1,25,'4 7','',0x0,''\n_StateBuffer='C:\\projects\\c&czero\\code\\eng\\conquer.txt',0x0000048e,1,1,25,'5 9','',0x0,''\n_StateBuffer='C:\\projects\\c&czero\\code\\2KEYFRAM.CPP',0x0c00048e,198,40,25,'4 7','',0x0,''\n_StateHistory=SEARCH,'MCV','Official','Create_Units','Create_U','Is_Forced_','Create_U','FIX','Take_Dam','threat','MAP_ERRO'\n_StateHistory=REPLACE,'buffer','pointer','unit','} else {','_cd_name','_CD_Volume_Label','DEBUG_LEVEL_2'\n_StateHistory=XMACRO,'sort','upper','sort'\n_StateHistory=FILELIST,'C:\\projects\\c&czero\\code\\INFANTRY.CPP','C:\\projects\\c&czero\\code\\VERSION.CPP','C:\\projects\\c&czero\\code\\FINDPATH.CPP','C:\\projects\\c&czero\\code\\todo.txt','D:\\CW32\\NOSPLASH','C:\\projects\\c&czero\\code\\eng\\conquer.txt','C:\\projects\\c&czero\\code\\LANGUAGE.H','C:\\projects\\c&czero\\code\\CONQUER.CPP','C:\\projects\\c&czero\\code\\2KEYFRAM.CPP','C:\\projects\\c&czero\\code\\RECT.CPP'\n_StateHistory=EDITFILE,'bullet.cpp','scenario.cpp','infantry.cpp','version.cpp','findpath.cpp','todo.txt','eng\\conquer.txt','language.h','conquer.cpp','2keyfram.cpp'\n_StateHistory=GOTOLINE,'754','344','3649','634','210'\n\n[Editor]\nClipboardSetTermStr='\\r\\n',0\nClipboardEnableTermStr=1\nClipboardSetSepStr='\\r\\n',0\nClipboardEnableSepStr=1\nScrapSetCount=1\nVCSProject=''\nVCSProjectPath=''\nVCSProjectLocalPath=''\n_RestoreSysFlags=0x62c9f5fa, 0xfffffffc\n\n[Compiler]\nTagSetCmd='${HOME}${WTAGS} -oc -d -t${TAGFILE}.tag -p${TAGFILE}.ptg',0x8000060\nBrowseSetFile='C:\\PROJECTS\\C&Czero\\code\\rados.ptg'\nTagSetFile='C:\\PROJECTS\\C&Czero\\code\\rados.tag'\nCompilerAddCmd='Microsoft Assembler','ftee masm -w2 -zi %r%e;',1073741824,'',0,'',16,'',16,'',0,'',0,'_MicrosoftErrorInfo','','','','%v%p'\nCompilerAddResponse='Microsoft Assembler',\nCompilerAddCmd='Borland C++','ftee bcc -S %r.c',1073741824,'',0,'ftee make %r.obj',16,'ftee make %r.obj',16,'',0,'',0,'_BorlandCppErrorInfo','','','','%v%p'\nCompilerAddResponse='Borland C++',\nCompilerAddCmd='Borland Turbo Assembler','ftee make %r.obj',1073741824,'',0,'ftee make %r.obj',16,'',16,'',0,'',0,'_TasmErrorInfo','','','','%v%p'\nCompilerAddResponse='Borland Turbo Assembler',\nCompilerAddCmd='$_cw_proj_hash_$','',1073741825,'',1,'ftee watcom\\binw\\wmake %r.obj',209,'ftee m.bat',209,'ftee joemake',209,'g.bat',224,'_MSLinkErrorInfo','_MicrosoftErrorInfo','_NMakeErrorInfo','proj.err','c:\\projects\\c&czero\\code'\nCompilerAddResponse='$_cw_proj_hash_$',\nCompilerAddCmd='Microsoft C','ftee cl -c -AL -Gsw -Ow -Zpe  %r%e',1073741824,'',0,'',16,'',16,'',0,'',0,'_MicrosoftErrorInfo','','','','%v%p'\nCompilerAddResponse='Microsoft C',\nCompilerAddCmd='Default Project','',1073741824,'',0,'ftee make',16,'ftee make',16,'',0,'',0,'_ErrorInfoDefault','','','proj.err','%v%p'\nCompilerAddResponse='Default Project',\nCompilerAddCmd='Zortech C++','ftee ztc -a -b -c -g -ml -W %r%e',1073741824,'',0,'',16,'',16,'',0,'',0,'_ZortechCppErrorInfo','','','','%v%p'\nCompilerAddResponse='Zortech C++',\nCompilerAddCmd='Script','ftee make %r.inf',1073741824,'',0,'ftee make',16,'ftee make',16,'',0,'',0,'_BorlandCppErrorInfo','','','',''\nCompilerAddResponse='Script',\nCompilerAddCmd='Microsoft C(NT-i386)','${FTEE} cl -DSTRICT -c -W3 -G3 -D_X86_=1 -DWIN32 %r%e',1073741936,'${FTEE} cl -DSTRICT -c -W3 -G3 -D_X86_=1 -DWIN32 %r%e',112,'',144,'',144,'',0,'',0,'_MicrosoftErrorInfo','','','',''\nCompilerAddResponse='Microsoft C(NT-i386)',\nCompilerAssign='Borland C++','.scr'\nCompilerNewExt=.bas\nCompilerAssign='Borland C++','.int'\nCompilerAssign='Borland C++','.c'\nCompilerNewExt=.prg\nCompilerAssign='Microsoft C','.h'\nCompilerAssign='Borland C++','.cpp'\nCompilerAssign='Default Project','.*'\nCompilerAssign='Microsoft C(NT-i386)','.cxx'\nCompilerAssign='Borland Turbo Assembler','.asm'\nCompilerAssign='Microsoft C(NT-i386)','.hpp'\n"
  },
  {
    "path": "CODE/RAMFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RAMFILE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RAMFILE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RAMFileClass::Close -- This will 'close' the ram file.                                    *\n *   RAMFileClass::Create -- Effectively clears the buffer of data.                            *\n *   RAMFileClass::Delete -- Effectively clears the buffer of data.                            *\n *   RAMFileClass::Is_Available -- Determines if the \"file\" is available.                      *\n *   RAMFileClass::Is_Open -- Is the file open?                                                *\n *   RAMFileClass::Open -- Opens a RAM based file for read or write.                           *\n *   RAMFileClass::Open -- Opens the RAM based file.                                           *\n *   RAMFileClass::RAMFileClass -- Construct a RAM buffer based \"file\" object.                 *\n *   RAMFileClass::Read -- Read data from the file.                                            *\n *   RAMFileClass::Seek -- Controls the ram file virtual read position.                        *\n *   RAMFileClass::Size -- Returns with the size of the ram file.                              *\n *   RAMFileClass::Write -- Copies data to the ram file.                                       *\n *   RAMFileClass::~RAMFileClass -- Destructor for the RAM file class.                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"ramfile.h\"\n#include\t<string.h>\n\n\n/***********************************************************************************************\n * RAMFileClass::RAMFileClass -- Construct a RAM buffer based \"file\" object.                   *\n *                                                                                             *\n *    This routine will construct a \"file\" object that actually is just a front end processor  *\n *    for a buffer. Access to the buffer will appear as if it was accessing a file. This       *\n *    is different from the caching ability of the buffered file class in that this file       *\n *    class has no real file counterpart. Typical use of this is for algorithms that were      *\n *    originally designed for file processing, but are now desired to work with a buffer.      *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer to use for this file. The buffer will already    *\n *                      contain data if the file is opened for READ. It will be considered     *\n *                      a scratch buffer if opened for WRITE. If the buffer pointer is NULL    *\n *                      but the length parameter is not, then a buffer will be allocated       *\n *                      of the specified length. This case is only useful for opening the      *\n *                      file for WRITE.                                                        *\n *                                                                                             *\n *          length   -- The length of the buffer submitted to this routine.                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRAMFileClass::RAMFileClass(void * buffer, int len) :\n\tBuffer((char *)buffer),\n\tMaxLength(len),\n\tLength(len),\n\tOffset(0),\n\tAccess(READ),\n\tIsOpen(false),\n\tIsAllocated(false)\n{\n\tif (buffer == NULL && len > 0) {\n\t\tBuffer = new char[len];\n\t\tIsAllocated = true;\n\t}\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::~RAMFileClass -- Destructor for the RAM file class.                           *\n *                                                                                             *\n *    The destructor will deallocate any buffer that it allocated. Otherwise it does nothing.  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRAMFileClass::~RAMFileClass(void)\n{\n\tClose();\n\tif (IsAllocated) {\n\t\tdelete [] Buffer;\n\t\tBuffer = NULL;\n\t\tIsAllocated = false;\n\t}\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Create -- Effectively clears the buffer of data.                              *\n *                                                                                             *\n *    This routine \"clears\" the buffer of data. It only makes the buffer appear empty by       *\n *    resetting the internal length to zero.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the file reset in this fashion?                                                *\n *                                                                                             *\n * WARNINGS:   If the file was open, then resetting by this routine is not allowed.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RAMFileClass::Create(void)\n{\n\tif (!Is_Open()) {\n\t\tLength = 0;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Delete -- Effectively clears the buffer of data.                              *\n *                                                                                             *\n *    This routine \"clears\" the buffer of data. It only makes the buffer appear empty by       *\n *    resetting the internal length to zero.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the file reset in this fashion?                                                *\n *                                                                                             *\n * WARNINGS:   If the file was open, then resetting by this routine is not allowed.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RAMFileClass::Delete(void)\n{\n\tif (!Is_Open()) {\n\t\tLength = 0;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Is_Available -- Determines if the \"file\" is available.                        *\n *                                                                                             *\n *    RAM files are always available.                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  TRUE                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RAMFileClass::Is_Available(int )\n{\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Is_Open -- Is the file open?                                                  *\n *                                                                                             *\n *    This answers the question whether the file is open or not.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file open?                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RAMFileClass::Is_Open(void) const\n{\n\treturn(IsOpen);\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Open -- Opens a RAM based file for read or write.                             *\n *                                                                                             *\n *    This routine will open the ram file. The name is meaningless so that parameter is        *\n *    ignored. If the access mode is for write, then the pseudo-file can be written until the  *\n *    buffer is full. If the file is opened for read, then the buffer is presumed to be full   *\n *    of the data to be read.                                                                  *\n *                                                                                             *\n * INPUT:   name  -- ignored.                                                                  *\n *                                                                                             *\n *          access-- The access method to use for the data buffer -- either READ or WRITE.     *\n *                                                                                             *\n * OUTPUT:  bool; Was the open successful?                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RAMFileClass::Open(char const * , int access)\n{\n\treturn(Open(access));\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Open -- Opens the RAM based file.                                             *\n *                                                                                             *\n *    This will open the ram based file for read or write. If the file is opened for write,    *\n *    the the 'file' can be written up to the limit of the buffer's size. If the file is       *\n *    opened for read, then the buffer is presumed to hold the data to be read.                *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RAMFileClass::Open(int access)\n{\n\tif (Buffer == NULL || Is_Open()) {\n\t\treturn(false);\n\t}\n\n\tOffset = 0;\n\tAccess = access;\n\tIsOpen = true;\n\n\tswitch (access) {\n\t\tdefault:\n\t\tcase READ:\n\t\t\tbreak;\n\n\t\tcase WRITE:\n\t\t\tLength = 0;\n\t\t\tbreak;\n\n\t\tcase READ|WRITE:\n\t\t\tbreak;\n\t}\n\n\treturn(Is_Open());\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Read -- Read data from the file.                                              *\n *                                                                                             *\n *    Use this routine just like a normal file read. It will copy the bytes from the ram       *\n *    buffer to the destination specified. When the ram buffer is exhausted, less bytes than   *\n *    requested will be read.                                                                  *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer to store the data to.                            *\n *                                                                                             *\n *          size     -- The number of bytes to 'read' into the specified buffer.               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes copied to the destination buffer. If the number   *\n *          of bytes returned is less than requested, then this indicates that the source      *\n *          buffer is exhausted.                                                               *\n *                                                                                             *\n * WARNINGS:   The read function only applies to ram 'files' opened for read access.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RAMFileClass::Read(void * buffer, long size)\n{\n\tif (Buffer == NULL || buffer == NULL || size == 0) {\n\t\treturn(0);\n\t}\n\n\tbool hasopened = false;\n\tif (!Is_Open()) {\n\t\tOpen(READ);\n\t\thasopened = true;\n\t} else {\n\t\tif ((Access & READ) == 0) {\n\t\t\treturn(0);\n\t\t}\n\t}\n\n\tint tocopy = (size < (Length-Offset)) ? size : (Length-Offset);\n\tmemmove(buffer, &Buffer[Offset], tocopy);\n\tOffset += tocopy;\n\n\tif (hasopened) {\n\t\tClose();\n\t}\n\n\treturn(tocopy);\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Seek -- Controls the ram file virtual read position.                          *\n *                                                                                             *\n *    This routine will move the read/write position of the ram file to the location specified *\n *    by the offset and direction parameters. It functions similarly to the regular file       *\n *    seek method.                                                                             *\n *                                                                                             *\n * INPUT:   pos   -- The signed offset from the home position specified by the \"dir\"           *\n *                   parameter.                                                                *\n *                                                                                             *\n *          dir   -- The home position to base the position offset on. This will either be     *\n *                   the start of the file, the end of the file, or the current read/write     *\n *                   position.                                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the new file position.                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RAMFileClass::Seek(long pos, int dir)\n{\n\tif (Buffer == NULL || !Is_Open()) {\n\t\treturn(Offset);\n\t}\n\n\tint maxoffset = Length;\n\tif ((Access & WRITE) != 0) {\n\t\tmaxoffset = MaxLength;\n\t}\n\n\tswitch (dir) {\n\t\tcase SEEK_CUR:\n\t\t\tOffset += pos;\n\t\t\tbreak;\n\n\t\tcase SEEK_SET:\n\t\t\tOffset = 0 + pos;\n\t\t\tbreak;\n\n\t\tcase SEEK_END:\n\t\t\tOffset = maxoffset + pos;\n\t\t\tbreak;\n\t}\n\n\tif (Offset < 0) Offset = 0;\n\tif (Offset > maxoffset) Offset = maxoffset;\n\n\tif (Offset > Length) {\n\t\tLength = Offset;\n\t}\n\n\treturn(Offset);\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Size -- Returns with the size of the ram file.                                *\n *                                                                                             *\n *    This will return the size of the 'real' data in the ram file. The real data is either    *\n *    the entire buffer, if opened for READ, or just the written data if opened for WRITE.     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes that the ram file system considers to be valid    *\n *          data of the 'file'.                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RAMFileClass::Size(void)\n{\n\treturn(Length);\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Write -- Copies data to the ram file.                                         *\n *                                                                                             *\n *    This function similarly to the regular write operation supported for files. It copies    *\n *    the data specified to the current write position in the ram file.                        *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the data to be written.                                     *\n *                                                                                             *\n *          size     -- The number of bytes to write to the file.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes written. This will be less than requested  *\n *          if the buffer is exhausted of space prematurely.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RAMFileClass::Write(void const * buffer, long size)\n{\n\tif (Buffer == NULL || buffer == NULL || size == 0) {\n\t\treturn(0);\n\t}\n\n\tbool hasopened = false;\n\tif (!Is_Open()) {\n\t\tOpen(WRITE);\n\t\thasopened = true;\n\t} else {\n\t\tif ((Access & WRITE) == 0) {\n\t\t\treturn(0);\n\t\t}\n\t}\n\n\tint maxwrite = MaxLength - Offset;\n\tint towrite = (size < maxwrite) ? size : maxwrite;\n\tmemmove(&Buffer[Offset], buffer, towrite);\n\tOffset += towrite;\n\n\tif (Offset > Length) {\n\t\tLength = Offset;\n\t}\n\n\tif (hasopened) {\n\t\tClose();\n\t}\n\n\treturn(towrite);\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Close -- This will 'close' the ram file.                                      *\n *                                                                                             *\n *    Closing a ram file actually does nothing but record that it is now closed.               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RAMFileClass::Close(void)\n{\n\tIsOpen = false;\n}\n"
  },
  {
    "path": "CODE/RAMFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RAMFILE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RAMFILE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef RAMFILE_H\n#define RAMFILE_H\n\n#include\t\"wwfile.h\"\n\n\nclass RAMFileClass : public FileClass\n{\n\tpublic:\n\t\tRAMFileClass(void * buffer, int len);\n\t\tvirtual ~RAMFileClass(void);\n\n\t\tvirtual char const * File_Name(void) const {return(\"UNKNOWN\");}\n\t\tvirtual char const * Set_Name(char const * ) {return(File_Name());}\n\t\tvirtual int Create(void);\n\t\tvirtual int Delete(void);\n\t\tvirtual int Is_Available(int forced=false);\n\t\tvirtual int Is_Open(void) const;\n\t\tvirtual int Open(char const * filename, int access=READ);\n\t\tvirtual int Open(int access=READ);\n\t\tvirtual long Read(void * buffer, long size);\n\t\tvirtual long Seek(long pos, int dir=SEEK_CUR);\n\t\tvirtual long Size(void);\n\t\tvirtual long Write(void const * buffer, long size);\n\t\tvirtual void Close(void);\n\t\tvirtual unsigned long Get_Date_Time(void) {return(0);}\n\t\tvirtual bool Set_Date_Time(unsigned long ) {return(true);}\n\t\tvirtual void Error(int , int = false, char const * =NULL) {}\n\n\t\toperator char const * () {return File_Name();}\n\n\tprivate:\n\n\t\t/*\n\t\t**\tPointer to the buffer that the \"file\" will reside in.\n\t\t*/\n\t\tchar * Buffer;\n\n\t\t/*\n\t\t**\tThe maximum size of the buffer. The file occupying the buffer\n\t\t**\tmay be smaller than this size.\n\t\t*/\n\t\tint MaxLength;\n\n\t\t/*\n\t\t**\tThe number of bytes in the sub-file occupying the buffer.\n\t\t*/\n\t\tint Length;\n\n\t\t/*\n\t\t**\tThe current file position offset within the buffer.\n\t\t*/\n\t\tint Offset;\n\n\t\t/*\n\t\t**\tThe file was opened with this access mode.\n\t\t*/\n\t\tint Access;\n\n\t\t/*\n\t\t**\tIs the file currently open?\n\t\t*/\n\t\tbool IsOpen;\n\n\t\t/*\n\t\t**\tWas the file buffer allocated during construction of this object?\n\t\t*/\n\t\tbool IsAllocated;\n};\n\n\n\n\n#endif\n"
  },
  {
    "path": "CODE/RAND.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\rand.cpv   4.35   04 Jul 1996 16:14:56   JOE_BOSTIC  $ */\n/*************************************************************************** \n *                                                                         * \n *                 Project Name : Command & Conquer                        * \n *                                                                         * \n *                    File Name : RAND.CPP                                 * \n *                                                                         * \n *                   Programmer : Bill R. Randolph                         * \n *                                                                         * \n *                   Start Date : 04/25/95                                 * \n *                                                                         * \n *                  Last Update : June 17, 1995 [JLB]                      * \n *                                                                         * \n *-------------------------------------------------------------------------* \n * Functions:                                                              * \n *   Sim_IRandom -- Returns minval to maxval, inclusive                    *\n *   Sim_Random -- Returns 0 - 255                                         * \n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\nint SimRandIndex = 0;\n\n/*************************************************************************** \n * Sim_Random -- Returns 0 - 255                                           * \n *                                                                         * \n * INPUT:                                                                  * \n *      none.                                                              *\n *                                                                         * \n * OUTPUT:                                                                 * \n *      0 - 255, at random                                                 *\n *                                                                         * \n * WARNINGS:                                                               * \n *      none.                                                              *\n *                                                                         * \n * HISTORY:                                                                * \n *   04/25/1995 BRR : Created.                                             * \n *   06/17/1995 JLB : Takes advantage of character math wrap.              * \n *=========================================================================*/\nint Sim_Random(void)\n{\n\tstatic unsigned char _randvals[] = {\n\t\t0x47, 0xce, 0xc6, 0x6e, 0xd7, 0x9f, 0x98, 0x29, 0x92, 0x0c, 0x74, 0xa2, \n\t\t0x65, 0x20, 0x4b, 0x4f, 0x1e, 0xed, 0x3a, 0xdf, 0xa5, 0x7d, 0xb5, 0xc8,\n\t\t0x86, 0x01, 0x81, 0xca, 0xf1, 0x17, 0xd6, 0x23, 0xe1, 0xbd, 0x0e, 0xe4, \n\t\t0x62, 0xfa, 0xd9, 0x5c, 0x68, 0xf5, 0x7f, 0xdc, 0xe7, 0xb9, 0xc4, 0xb3,\n\t\t0x7a, 0xd8, 0x06, 0x3e, 0xeb, 0x09, 0x1a, 0x31, 0x3f, 0x46, 0x28, 0x12, \n\t\t0xf0, 0x10, 0x84, 0x76, 0x3b, 0xc5, 0x53, 0x18, 0x14, 0x73, 0x7e, 0x59,\n\t\t0x48, 0x93, 0xaa, 0x1d, 0x5d, 0x79, 0x24, 0x61, 0x1b, 0xfd, 0x2b, 0xa8, \n\t\t0xc2, 0xdb, 0xe8, 0x2a, 0xb0, 0x25, 0x95, 0xab, 0x96, 0x83, 0xfc, 0x5f,\n\t\t0x9c, 0x32, 0x78, 0x9a, 0x9e, 0xe2, 0x8e, 0x35, 0x4c, 0x41, 0xa1, 0x69, \n\t\t0x5a, 0xfe, 0xa7, 0xa4, 0xf6, 0x6d, 0xc1, 0x58, 0x0a, 0xcf, 0xea, 0xc3,\n\t\t0xba, 0x85, 0x99, 0x8d, 0x36, 0xb6, 0xdd, 0xd3, 0x04, 0xe6, 0x45, 0x0d,\n\t\t0x60, 0xae, 0xa3, 0x22, 0x4d, 0xe9, 0xc9, 0x9b, 0xb7, 0x0f, 0x02, 0x42,\n\t\t0xf9, 0x0b, 0x8f, 0x43, 0x44, 0x87, 0x70, 0xbe, 0xe3, 0xf8, 0xee, 0xa9, \n\t\t0xbc, 0xc0, 0x67, 0x33, 0x16, 0x37, 0x57, 0xad, 0x5e, 0x9d, 0x64, 0x40,\n\t\t0x54, 0x05, 0x2c, 0xe0, 0xb2, 0x97, 0x08, 0xaf, 0x75, 0x8a, 0x5b, 0xfb,\n\t\t0x4e, 0xbf, 0x91, 0xf3, 0xcb, 0x7c, 0x63, 0xef, 0x89, 0x52, 0x6c, 0x2f,\n\t\t0x21, 0x4a, 0xf7, 0xcd, 0x2e, 0xf4, 0xc7, 0x6f, 0x19, 0xb1, 0x66, 0xcc,\n\t\t0x90, 0x8c, 0x50, 0x51, 0x26, 0x7b, 0xda, 0x49, 0x80, 0x30, 0x55, 0x1f, \n\t\t0xd2, 0xb4, 0xd1, 0xd5, 0x6b, 0xf2, 0x72, 0xbb, 0x13, 0x3d, 0xff, 0x15,\n\t\t0x38, 0xe5, 0xd4, 0xde, 0x2d, 0x27, 0x94, 0xa0, 0xd0, 0x39, 0x82, 0x8b,\n\t\t0x03, 0xac, 0x3c, 0x34, 0x77, 0xb8, 0xec, 0x00, 0x07, 0x1c, 0x88, 0xa6,\n\t\t0x56, 0x11, 0x71, 0x6a,\n\t};\n\n\t((unsigned char&)SimRandIndex)++;\n//\tSimRandIndex &= 0xff;\n\treturn(_randvals[SimRandIndex]);\n}\n\n\n/*************************************************************************** \n * Sim_IRandom -- returns minval to maxval, inclusive                      *\n *                                                                         * \n * INPUT:                                                                  * \n *      minval,maxval      range limits                                    *\n *                                                                         * \n * OUTPUT:                                                                 * \n *      random value                                                       *\n *                                                                         * \n * WARNINGS:                                                               * \n *      none.                                                              *\n *                                                                         * \n * HISTORY:                                                                * \n *   04/25/1995 BRR : Created.                                             * \n *   06/17/1995 JLB : Uses fixed point math helper routine.                * \n *=========================================================================*/\nint Sim_IRandom(int minval, int maxval)\n{\n\treturn(Fixed_To_Cardinal((maxval-minval), Sim_Random()) + minval);\n}\n\n\n/*\n**\tThis routine can be used to create the _RandVals[] table.  It will be \n**\tdifferent every time it's run.\n*/\n#if 0\n#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n#include <conio.h>\n\nvoid main(void);\n\nvoid main(void)\n{\n\tint i;\n\tFILE *fp;\n\tint r;\n\tchar is_used[256];\n\tchar rand_val[256];\n\n\tsrand ( time ( NULL ) ) ;\n\n\tfor (i = 0; i < 256; i++) {\n\t\tis_used[i] = 0;\n\t}\n\n\t/*\n\t** Store the digits 0 to 255 in a random order within the 'rand_val' array\n\t** This ensures our random number sequence represents every value.\n\t*/\n\tfor (i = 0; i < 256; i++) {\n\t\tif (kbhit()!=0) {\n\t\t\tprintf(\"ABORTED!\\n\");\n\t\t\tbreak;\n\t\t}\n\t\tr = (rand() * 256) / RAND_MAX;\t\t// r is the index into array\n\t\tif (is_used[r]==0) {\n\t\t\tis_used[r] = 1;\n\t\t\trand_val[r] = i;\n\t\t} else {\n\t\t\ti--;\n\t\t}\n\t}\n\n\tfp = fopen(\"rand.cpp\",\"wt\");\n\tif (fp==NULL) {\n\t\tprintf(\"File error\\n\");\n\t\texit(0);\n\t}\n\n\tfprintf(fp, \"unsigned char _RandVals[] = {\\n\");\n\tfor (i = 0; i < 256; i++) {\n\t\tfprintf(fp,\"0x%02x,\\n\",rand_val[i]);\n\t}\n\tfprintf(fp,\"};\\n\");\n\tfclose(fp);\n\n}\n\n#endif\n\n"
  },
  {
    "path": "CODE/RANDOM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RANDOM.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RAND.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/28/96                                                     *\n *                                                                                             *\n *                  Last Update : February 28, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RandomClass::RandomClass -- Constructor for the random number class.                      *\n *   RandomClass::operator() -- Fetches the next random number in the sequence.                *\n *   RandomClass::operator() -- Ranged random number generator.                                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"random.h\"\n#ifdef RANDOM_COUNT\n#include <stdio.h>\nextern long Frame;\n#endif\n\n/***********************************************************************************************\n * RandomClass::RandomClass -- Constructor for the random number class.                        *\n *                                                                                             *\n *    This constructor can take an integer as a parameter. This allows the class to be         *\n *    constructed by assigning an integer to an existing object. The compiler creates a        *\n *    temporary with the constructor and then performs a copy constructor operation.           *\n *                                                                                             *\n * INPUT:   seed  -- The optional starting seed value to use.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/27/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRandomClass::RandomClass(unsigned seed) :\n\tSeed(seed)\n{\n#ifdef RANDOM_COUNT\n\tCount1 = 0;\n\tCount2 = 0;\n#endif\n}\n\n\n/***********************************************************************************************\n * RandomClass::operator() -- Fetches the next random number in the sequence.                  *\n *                                                                                             *\n *    This routine will fetch the next random number in the sequence.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the next random number.                                               *\n *                                                                                             *\n * WARNINGS:   This routine modifies the seed value so that subsequent calls will not return   *\n *             the same value. Take note that this routine only returns 15 bits of             *\n *             random number.                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/27/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RandomClass::operator ()(void)\n{\n#ifdef RANDOM_COUNT\n\tCount1++;\n\tprintf(\"Frame %d: Random Count1:%d Count2:%d (%x)\\n\",Frame,Count1,Count2,Seed);\n#endif\n\n\t/*\n\t**\tTransform the seed value into the next number in the sequence.\n\t*/\n\tSeed = (Seed * MULT_CONSTANT) + ADD_CONSTANT;\n\n\t/*\n\t**\tExtract the 'random' bits from the seed and return that value as the\n\t**\trandom number result.\n\t*/\n\treturn((Seed >> THROW_AWAY_BITS) & (~((~0) << SIGNIFICANT_BITS)));\n}\n\n\n/***********************************************************************************************\n * RandomClass::operator() -- Ranged random number generator.                                  *\n *                                                                                             *\n *    This function will return with a random number within the range specified. This replaces *\n *    the functionality of IRandom() in the old library.                                       *\n *                                                                                             *\n * INPUT:   minval   -- The minimum value to return from the function.                         *\n *                                                                                             *\n *          maxval   -- The maximum value to return from the function.                         *\n *                                                                                             *\n * OUTPUT:  Returns with a random number that falls between the minval and maxval (inclusive). *\n *                                                                                             *\n * WARNINGS:   The range specified must fall within the maximum bit significance of the        *\n *             random number algorithm (15 bits), otherwise the value returned will be         *\n *             decidedly non-random.                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/27/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RandomClass::operator() (int minval, int maxval)\n{\n#ifdef RANDOM_COUNT\n\tCount2++;\n\tprintf(\"Frame %d: Random Count1:%d Count2:%d (%x)\\n\",Frame,Count1,Count2,Seed);\n#endif\n\n\t/*\n\t**\tTest for shortcut case where the range is null and thus\n\t**\tthe number to return is actually implicit from the\n\t**\tparameters.\n\t*/\n\tif (minval == maxval) return(minval);\n\n\t/*\n\t**\tEnsure that the min and max range values are in proper order.\n\t*/\n\tif (minval > maxval) {\n\t\tint temp = minval;\n\t\tminval = maxval;\n\t\tmaxval = temp;\n\t}\n\n\t/*\n\t**\tFind the highest bit that fits within the magnitude of the\n\t**\trange of random numbers desired. Notice that the scan is\n\t**\tlimited to the range of significant bits returned by the\n\t**\trandom number algorithm.\n\t*/\n\tint magnitude = maxval - minval;\n\tint highbit = SIGNIFICANT_BITS-1;\n\twhile ((magnitude & (1 << highbit)) == 0 && highbit > 0) {\n\t\thighbit--;\n\t}\n\n\t/*\n\t**\tCreate a full bit mask pattern that has all bits set that just\n\t**\tbarely covers the magnitude of the number range desired.\n\t*/\n\tint mask = ~( (~0L) << (highbit+1) );\n\n\t/*\n\t**\tKeep picking random numbers until it fits within the magnitude desired.\n\t*/\n\tint pick = magnitude+1;\n\twhile (pick > magnitude) {\n\t\tpick = operator()() & mask;\n\t}\n\n\t/*\n\t**\tFinally, bias the random number pick to the start of the range\n\t**\trequested.\n\t*/\n\treturn(pick + minval);\n}\n\n"
  },
  {
    "path": "CODE/RANDOM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RANDOM.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RANDOM.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/27/96                                                     *\n *                                                                                             *\n *                  Last Update : February 27, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef RANDOM_H\n#define RANDOM_H\n\n/**********************************************************************\n** Enable this define to turn on the random # counters.  This must not\n** be defined for the release version, or saved games won't work!\n*/\n//#define RANDOM_COUNT\n\n\n/*\n**\tThis class functions like a 'magic' int value that returns a random number\n**\tevery time it is read. To set the \"random seed\" for this, just assign a number\n**\tto the object (just as you would if it were a true 'int' value). Take note that although\n**\tthis class will return an 'int', the actual significance of the random number is\n**\tlimited to 15 bits (0..32767).\n*/\nclass RandomClass {\n\tpublic:\n\t\tRandomClass(unsigned seed=0);\n\n\t\toperator int(void) {return(operator()());};\n\t\tint operator() (void);\n\t\tint operator() (int minval, int maxval);\n\n\t\tenum {\n\t\t\tSIGNIFICANT_BITS=15\t\t\t\t// Random number bit significance.\n\t\t};\n\n\t\tunsigned long Seed;\n\n#ifdef RANDOM_COUNT\n\t\tunsigned long Count1;\n\t\tunsigned long Count2;\n#endif\n\n\tprotected:\n\t\t/*\n\t\t**\tInternal working constants that are used to generate the next\n\t\t**\trandom number.\n\t\t*/\n\t\tenum {\n\t\t\tMULT_CONSTANT=0x41C64E6D,\t\t// K multiplier value.\n\t\t\tADD_CONSTANT=0x00003039,\t\t// K additive value.\n\t\t\tTHROW_AWAY_BITS=10\t\t\t\t// Low bits to throw away.\n\t\t};\n};\n\n#endif\n"
  },
  {
    "path": "CODE/RAWFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RAWFILE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Library                                             *\n *                                                                                             *\n *                    File Name : RAWFILE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : August 4, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RawFileClass::Bias -- Bias a file with a specific starting position and length.           *\n *   RawFileClass::Close -- Perform a closure of the file.                                     *\n *   RawFileClass::Create -- Creates an empty file.                                            *\n *   RawFileClass::Delete -- Deletes the file object from the disk.                            *\n *   RawFileClass::Error -- Handles displaying a file error message.                           *\n *   RawFileClass::Get_Date_Time -- Gets the date and time the file was last modified.         *\n *   RawFileClass::Is_Available -- Checks to see if the specified file is available to open.   *\n *   RawFileClass::Open -- Assigns name and opens file in one operation.                       *\n *   RawFileClass::Open -- Opens the file object with the rights specified.                    *\n *   RawFileClass::RawFileClass -- Simple constructor for a file object.                       *\n *   RawFileClass::Raw_Seek -- Performs a seek on the unbiased file                            *\n *   RawFileClass::Read -- Reads the specified number of bytes into a memory buffer.           *\n *   RawFileClass::Seek -- Reposition the file pointer as indicated.                           *\n *   RawFileClass::Set_Date_Time -- Sets the date and time the file was last modified.         *\n *   RawFileClass::Set_Name -- Manually sets the name for a file object.                       *\n *   RawFileClass::Size -- Determines size of file (in bytes).                                 *\n *   RawFileClass::Write -- Writes the specified data to the buffer specified.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<string.h>\n#include\t<direct.h>\n#include\t<share.h>\n#include\t<stddef.h>\n\n#include\t\"rawfile.h\"\n\n#ifndef WIN32\n#include\t<fcntl.h>\n#include\t<io.h>\n#include\t<dos.h>\nextern short Hard_Error_Occured;\n#endif\n\n\n/***********************************************************************************************\n * RawFileClass::Error -- Handles displaying a file error message.                             *\n *                                                                                             *\n *    Display an error message as indicated. If it is allowed to retry, then pressing a key    *\n *    will return from this function. Otherwise, it will exit the program with \"exit()\".       *\n *                                                                                             *\n * INPUT:   error    -- The error number (same as the DOSERR.H error numbers).                 *\n *                                                                                             *\n *          canretry -- Can this routine exit normally so that retrying can occur? If this is  *\n *                      false, then the program WILL exit in this routine.                     *\n *                                                                                             *\n *          filename -- Optional filename to report with this error. If no filename is         *\n *                      supplied, then no filename is listed in the error message.             *\n *                                                                                             *\n * OUTPUT:  none, but this routine might not return at all if the \"canretry\" parameter is      *\n *          false or the player pressed ESC.                                                   *\n *                                                                                             *\n * WARNINGS:   This routine may not return at all. It handles being in text mode as well as    *\n *             if in a graphic mode.                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RawFileClass::Error(int , int , char const * )\n{\n}\n\n\n/***********************************************************************************************\n * RawFileClass::RawFileClass -- Simple constructor for a file object.                         *\n *                                                                                             *\n *    This constructor is called when a file object is created with a supplied filename, but   *\n *    not opened at the same time. In this case, an assumption is made that the supplied       *\n *    filename is a constant string. A duplicate of the filename string is not created since   *\n *    it would be wasteful in that case.                                                       *\n *                                                                                             *\n * INPUT:   filename -- The filename to assign to this file object.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nRawFileClass::RawFileClass(char const * filename) :\n\tRights(0),\n\tBiasStart(0),\n\tBiasLength(-1),\n\tHandle(NULL_HANDLE),\n\tFilename(filename),\n\tDate(0),\n\tTime(0),\n\tAllocated(false)\n{\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Set_Name -- Manually sets the name for a file object.                         *\n *                                                                                             *\n *    This routine will set the name for the file object to the name specified. This name is   *\n *    duplicated in free store. This allows the supplied name to be a temporarily constructed  *\n *    text string. Setting the name in this fashion doesn't affect the closed or opened state  *\n *    of the file.                                                                             *\n *                                                                                             *\n * INPUT:   filename -- The filename to assign to this file object.                            *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocated copy of this filename. This pointer is     *\n *          guaranteed to remain valid for the duration of this file object or until the name  *\n *          is changed -- whichever is sooner.                                                 *\n *                                                                                             *\n * WARNINGS:   Because of the allocation this routine must perform, memory could become        *\n *             fragmented.                                                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * RawFileClass::Set_Name(char const * filename)\n{\n\tif (Filename != NULL && Allocated) {\n\t\tfree((char *)Filename);\n\t\t((char *&)Filename) = 0;\n\t\tAllocated = false;\n\t}\n\n\tif (filename == NULL) return(NULL);\n\n\tBias(0);\n\n\t((char *&)Filename) = strdup(filename);\n\tif (Filename == NULL) {\n\t\tError(ENOMEM, false, filename);\n\t}\n\tAllocated = true;\n\treturn(Filename);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Open -- Assigns name and opens file in one operation.                         *\n *                                                                                             *\n *    This routine will assign the specified filename to the file object and open it at the    *\n *    same time. If the file object was already open, then it will be closed first. If the     *\n *    file object was previously assigned a filename, then it will be replaced with the new    *\n *    name. Typically, this routine is used when an anonymous file object has been crated and  *\n *    now it needs to be assigned a name and opened.                                           *\n *                                                                                             *\n * INPUT:   filename -- The filename to assign to this file object.                            *\n *                                                                                             *\n *          rights   -- The open file access rights to use.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened? The return value of this is moot, since the open file   *\n *          is designed to never return unless it succeeded.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Open(char const * filename, int rights)\n{\n\tSet_Name(filename);\n\treturn(Open(rights));\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Open -- Opens the file object with the rights specified.                      *\n *                                                                                             *\n *    This routine is used to open the specified file object with the access rights indicated. *\n *    This only works if the file has already been assigned a filename. It is guaranteed, by   *\n *    the error handler, that this routine will always return with success.                    *\n *                                                                                             *\n * INPUT:   rights   -- The file access rights to use when opening this file. This is a        *\n *                      combination of READ and/or WRITE bit flags.                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened successfully? This will always return true by reason of  *\n *          the error handler.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Open(int rights)\n{\n\tClose();\n\n\t/*\n\t**\tVerify that there is a filename associated with this file object. If not, then this is a\n\t**\tbig error condition.\n\t*/\n\tif (Filename == NULL) {\n\t\tError(ENOENT, false);\n\t}\n\n\t/*\n\t**\tRecord the access rights used for this open call. These rights will be used if the\n\t**\tfile object is duplicated.\n\t*/\n\tRights = rights;\n\n\t/*\n\t**\tRepetitively try to open the file. Abort if a fatal error condition occurs.\n\t*/\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tTry to open the file according to the access rights specified.\n\t\t*/\n\t\t#ifndef WIN32\n\t\t\tHard_Error_Occured = 0;\n\t\t#endif\n\t\tswitch (rights) {\n\n\t\t\t/*\n\t\t\t**\tIf the access rights are not recognized, then report this as\n\t\t\t**\tan invalid access code.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\terrno = EINVAL;\n\t\t\t\tbreak;\n\n\t\t\tcase READ:\n\t\t\t\t#ifdef WIN32\n\t\t\t\t\tHandle = CreateFile(Filename, GENERIC_READ, FILE_SHARE_READ,\n\t\t\t\t\t\t\t\t\t\t\t\tNULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n\t\t\t\t#else\n\t\t\t\t\t_dos_open(Filename, O_RDONLY|SH_DENYNO, &Handle);\n\t\t\t\t#endif\n\t\t\t\tbreak;\n\n\t\t\tcase WRITE:\n\t\t\t\t#ifdef WIN32\n\t\t\t\t\tHandle = CreateFile(Filename, GENERIC_WRITE, 0,\n\t\t\t\t\t\t\t\t\t\t\t\tNULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);\n\t\t\t\t#else\n\t\t\t\t\t_dos_creat(Filename, 0, &Handle);\n\t\t\t\t#endif\n\t\t\t\tbreak;\n\n\t\t\tcase READ|WRITE:\n\t\t\t\t#ifdef WIN32\n\t\t\t\t\tHandle = CreateFile(Filename, GENERIC_READ | GENERIC_WRITE, 0,\n\t\t\t\t\t\t\t\t\t\t\t\tNULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);\n\t\t\t\t#else\n\t\t\t\t\t_dos_open(Filename, O_RDWR|O_CREAT|SH_DENYWR, &Handle);\n\t\t\t\t#endif\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tBiased files must be positioned past the bias start position.\n\t\t*/\n\t\tif (BiasStart != 0 || BiasLength != -1) {\n\t\t\tSeek(0, SEEK_SET);\n\t\t}\n\n\t\t/*\n\t\t**\tIf the handle indicates the file is not open, then this is an error condition.\n\t\t**\tFor the case of the file cannot be found, then allow a retry. All other cases\n\t\t**\tare fatal.\n\t\t*/\n\t\tif (Handle == NULL_HANDLE) {\n\n#ifdef WIN32\n//\t\t\treturn(false);\n\t\t\tError(GetLastError(), false, Filename);\n//\t\t\tcontinue;\n#else\n\t\t\t/*\n\t\t\t**\tIf this flag is set, then some hard error occurred. Just assume that the error\n\t\t\t**\tis probably a removed CD-ROM and allow a retry.\n\t\t\t*/\n\t\t\tif (Hard_Error_Occured) {\n\t\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\t} else {\n\t\t\t\tif (errno == ENOENT) {\n\t\t\t\t\tError(ENOENT, true, Filename);\n\t\t\t\t} else {\n\t\t\t\t\tError(errno, false, Filename);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue;\n#endif\n\t\t}\n\t\tbreak;\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Is_Available -- Checks to see if the specified file is available to open.     *\n *                                                                                             *\n *    This routine will examine the disk system to see if the specified file can be opened     *\n *    or not. Use this routine before opening a file in order to make sure that is available   *\n *    or to perform other necessary actions.                                                   *\n *                                                                                             *\n * INPUT:   force -- Should this routine keep retrying until the file becomes available? If    *\n *                   in this case it doesn't become available, then the program will abort.    *\n *                                                                                             *\n * OUTPUT:  bool; Is the file available to be opened?                                          *\n *                                                                                             *\n * WARNINGS:   Depending on the parameter passed in, this routine may never return.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Is_Available(int forced)\n{\n#ifndef WIN32\n\tbool open_failed;\n#endif\n\n\tif (Filename == NULL) return(false);\n\n\t/*\n\t**\tIf the file is already open, then is must have already passed the availability check.\n\t**\tReturn true in this case.\n\t*/\n\tif (Is_Open()) return(true);\n\n\t/*\n\t**\tIf this is a forced check, then go through the normal open channels, since those\n\t**\tchannels ensure that the file must exist.\n\t*/\n\tif (forced) {\n\t\tRawFileClass::Open(READ);\n\t\tRawFileClass::Close();\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tPerform a raw open of the file. If this open fails for ANY REASON, including a missing\n\t**\tCD-ROM, this routine will return a failure condition. In all but the missing file\n\t**\tcondition, go through the normal error recover channels.\n\t*/\n\tfor (;;) {\n\n#ifdef WIN32\n\t\tHandle = CreateFile(Filename, GENERIC_READ, FILE_SHARE_READ,\n\t\t\t\t\t\t\t\t\t\t\tNULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n\t\tif (Handle == NULL_HANDLE) {\n\t\t\treturn(false);\n\t\t}\n\t\tbreak;\n#else\n\n\t\tHard_Error_Occured = 0;\n\t\topen_failed = _dos_open(Filename, O_RDONLY|SH_DENYNO, &Handle);\n\n\t\t/*\n\t\t**\tIf DOS reports that everything is just fine except that the file is not present,\n\t\t**\tthen return with this fact. Any other case will fall through to the error handler\n\t\t**\troutine.\n\t\t*/\n\t\tif (open_failed && errno == ENOENT) return(false);\n\n\t\t/*\n\t\t** If we got an access error it could be because there is no cd in\n\t\t** the drive.  Call the error handler but allow a continue if it\n\t\t** returns.\n\t\t*/\n\t\tif (open_failed && errno == EACCES) {\n\t\t\tError(errno, true, Filename);\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tIf the file could not be found, then return with this information. If a more\n\t\t**\tserious error occurred, then display the error message and abort.\n\t\t*/\n\t\tif (Hard_Error_Occured) {\n\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\tcontinue;\n\t\t} else {\n\t\t\tif (open_failed) {\n\t\t\t\t/*\n\t\t\t\t**\tAn unhandled error condition is fatal. Display the error message and then\n\t\t\t\t**\tabort.\n\t\t\t\t*/\n\t\t\t\tError(errno, false, Filename);\n\t\t\t}\n\t\t}\n\t\tif (!open_failed) break;\n#endif\n\t}\n\n\t/*\n\t**\tSince the file could be opened, then close it and return that the file exists.\n\t*/\n#ifdef WIN32\n\tif (!CloseHandle(Handle)) {\n\t\tError(GetLastError(), false, Filename);\n\t}\n#else\n\tif (_dos_close(Handle)) {\n\t\tError(errno, false, Filename);\n\t}\n#endif\n\tHandle = NULL_HANDLE;\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Close -- Perform a closure of the file.                                       *\n *                                                                                             *\n *    Close the file object. In the rare case of an error, handle it as appropriate.           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Some rare error conditions may cause this routine to abort the program.         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RawFileClass::Close(void)\n{\n\t/*\n\t**\tIf the file is open, then close it. If the file is already closed, then just return. This\n\t**\tisn't considered an error condition.\n\t*/\n\tif (Is_Open()) {\n\n#ifdef WIN32\n\t\t/*\n\t\t**\tTry to close the file. If there was an error (who knows what that could be), then\n\t\t**\tcall the error routine.\n\t\t*/\n\t\tif (!CloseHandle(Handle)) {\n\t\t\tError(GetLastError(), false, Filename);\n\t\t}\n#else\n\t\tfor (;;) {\n\t\t\t/*\n\t\t\t**\tClose the file. If there was an error in the close operation -- abort.\n\t\t\t*/\n\t\t\tHard_Error_Occured = 0;\n\t\t\tif (_dos_close(Handle)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tBy definition, this error can only be a bad file handle. This a fatal condition\n\t\t\t\t**\tof course, so abort with an error message.\n\t\t\t\t*/\n\t\t\t\tError(errno, false, Filename);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIn the condition (if it is even possible) of a hard error occurring, then\n\t\t\t**\tassume it is the case of missing media. Display an error message and try\n\t\t\t**\tagain if indicated.\n\t\t\t*/\n\t\t\tif (Hard_Error_Occured) {\n\t\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n#endif\n\n\t\t/*\n\t\t**\tAt this point the file must have been closed. Mark the file as empty and return.\n\t\t*/\n\t\tHandle = NULL_HANDLE;\n\t}\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Read -- Reads the specified number of bytes into a memory buffer.             *\n *                                                                                             *\n *    This routine will read the specified number of bytes and place the data into the buffer  *\n *    indicated. It is legal to call this routine with a request for more bytes than are in    *\n *    the file. This condition can result in fewer bytes being read than requested. Determine  *\n *    this by examining the return value.                                                      *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer to read data into. If NULL is passed, no read    *\n *                      is performed.                                                          *\n *                                                                                             *\n *          size     -- The number of bytes to read. If NULL is passed, then no read is        *\n *                      performed.                                                             *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes read into the buffer. If this number is less      *\n *          than requested, it indicates that the file has been exhausted.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Read(void * buffer, long size)\n{\n\tlong\tbytesread = 0;\t\t\t// Running count of the number of bytes read into the buffer.\n\tint\topened = false;\t\t// Was the file opened by this routine?\n\n\t/*\n\t**\tIf the file isn't opened, open it. This serves as a convenience\n\t**\tfor the programmer.\n\t*/\n\tif (!Is_Open()) {\n\n\t\t/*\n\t\t**\tThe error check here is moot. Open will never return unless it succeeded.\n\t\t*/\n\t\tif (!Open(READ)) {\n\t\t\treturn(0);\n\t\t}\n\t\topened = true;\n\t}\n\n\t/*\n\t**\tA biased file has the requested read length limited to the bias length of\n\t**\tthe file.\n\t*/\n\tif (BiasLength != -1) {\n\t\tint remainder = BiasLength - Seek(0);\n\t\tsize = size < remainder ? size : remainder;\n\t}\n\n#ifdef WIN32\n\tlong total = 0;\n\twhile (size > 0) {\n\t\tbytesread = 0;\n\n\t\tSetErrorMode(SEM_FAILCRITICALERRORS);\n\t\tif (!ReadFile(Handle, buffer, size, &(unsigned long&)bytesread, NULL)) {\n\t\t\tsize -= bytesread;\n\t\t\ttotal += bytesread;\n\t\t\tError(GetLastError(), true, Filename);\n\t\t\tSetErrorMode(0);\n\t\t\tcontinue;\n\t\t}\n\t\tSetErrorMode(0);\n\t\tsize -= bytesread;\n\t\ttotal += bytesread;\n\t\tif (bytesread == 0) break;\n\t}\n\tbytesread = total;\n\n#else\n\n\tint\treadresult;\n\n\t/*\n\t**\tRead the file in convenient chunk sizes. When the actual number\n\t**\tof bytes read does not match the desired, then assume that the file\n\t**\tis exhausted and bail. This loop was adjusted to take into\n\t**\tconsideration the fact that \"read\" returns a SIGNED value whereas\n\t**\tit takes an UNSIGNED value as the byte count.\n\t*/\n\twhile (size) {\n\t\tunsigned\tdesired;\t\t// Bytes desired to be read this pass.\n\t\tunsigned actual;\t\t// Actual number of bytes read.\n\n\t\t/*\n\t\t**\tBreak the read request into chunks no bigger than the low level DOS read\n\t\t**\tcan handle.\n\t\t*/\n\t\tdesired = size < 32000L ? size : 32000L;\n\n\t\tHard_Error_Occured = 0;\n\t\treadresult = _dos_read(Handle, buffer, desired, &actual);\n\n\t\t/*\n\t\t**\tIf a hard error occurred, then assume that it is the case of the CD-ROM or\n\t\t**\tfloppy media having been removed. Display the error and retry as directed.\n\t\t*/\n\t\tif (Hard_Error_Occured) {\n\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\tcontinue;\t\t\t// Not technically needed, but to be consistent...\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf negative one is returned from the read operation, then this indicates\n\t\t\t**\teither a bad file number or invalid access. These are fatal conditions, so\n\t\t\t**\tdisplay the error and then abort.\n\t\t\t*/\n\t\t\tif (readresult != 0) {\n\t\t\t\tError(errno, false, Filename);\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tNo error occurred during the read. Adjust the pointers and size counters and\n\t\t\t\t**\tloop again if more data is needed to be read.\n\t\t\t\t*/\n\t\t\t\tbuffer = (char *)buffer + actual;\n\t\t\t\tbytesread += actual;\n\t\t\t\tsize -= actual;\n\t\t\t\tif (actual != desired) break;\t\t// No more data?\n\t\t\t}\n\t\t}\n\t}\n#endif\t//WIN32\n\n\t/*\n\t**\tClose the file if it was opened by this routine and return\n\t**\tthe actual number of bytes read into the buffer.\n\t*/\n\tif (opened) Close();\n\treturn(bytesread);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Write -- Writes the specified data to the buffer specified.                   *\n *                                                                                             *\n *    This routine will write the data specified to the file.                                  *\n *                                                                                             *\n * INPUT:   buffer   -- The buffer that holds the data to write.                               *\n *                                                                                             *\n *          size     -- The number of bytes to write to the file.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes written to the file. This routine catches the     *\n *          case of a disk full condition, so this routine will always return with the number  *\n *          matching the size request.                                                         *\n *                                                                                             *\n * WARNINGS:   A fatal file condition could cause this routine to never return.                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Write(void const * buffer, long size)\n{\n\tlong\tbytesread = 0;\n\tint\topened = false;\t\t// Was the file manually opened?\n\n\t/*\n\t**\tCheck to open status of the file. If the file is open, then merely write to\n\t**\tit. Otherwise, open the file for writing and then close the file when the\n\t**\toutput is finished.\n\t*/\n\tif (!Is_Open()) {\n\t\tif (!Open(WRITE)) {\n\t\t\treturn(0);\n\t\t}\n\t\topened = true;\n\t}\n\n#ifdef WIN32\n\tif (!WriteFile(Handle, buffer, size, &(unsigned long&)bytesread, NULL)) {\n\t\tError(GetLastError(), false, Filename);\n\t}\n\n#else\n\n\tint\twriteresult;\n\t/*\n\t**\tWrite the data to the file in chunks no bigger than what the low level DOS write\n\t**\tcan handle.\n\t*/\n\twhile (size) {\n\t\tunsigned\tdesired;\t\t// Bytes desired to be write this pass.\n\t\tunsigned actual;\t\t// Actual number of bytes written.\n\n\t\tHard_Error_Occured = 0;\n//\t\tdesired = (unsigned)MIN(size, Transfer_Block_Size());\n\t\tdesired = size;\n\t\twriteresult = _dos_write(Handle, buffer, desired, &actual);\n\n\t\t/*\n\t\t**\tIf a hard error occurred, then assume it is the case of the media being\n\t\t**\tremoved. Print the error message an retry as directed.\n\t\t*/\n\t\tif (Hard_Error_Occured) {\n\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\tcontinue;\t\t\t// Not technically needed, but to be consistent...\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf negative one is returned by the DOS read, then this indicates a bad file\n\t\t\t**\thandle or invalid access. Either condition is fatal -- display error condition\n\t\t\t**\tand abort.\n\t\t\t*/\n\t\t\tif (writeresult != 0) {\n\t\t\t\tError(errno, false, Filename);\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tA successful write occurred. Update pointers and byte counter as appropriate.\n\t\t\t\t*/\n\t\t\t\tbuffer = (char *)buffer + actual;\n\t\t\t\tbytesread += actual;\n\t\t\t\tsize -= actual;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the actual bytes written is less than requested, assume this is a case of\n\t\t\t\t**\tthe disk being full. Consider this a fatal error condition.\n\t\t\t\t*/\n\t\t\t\tif (actual != desired) {\n\t\t\t\t\tError(ENOSPC, false, Filename);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#endif\t//WIN32\n\n\t/*\n\t**\tFixup the bias length if necessary.\n\t*/\n\tif (BiasLength != -1) {\n\t\tif (Raw_Seek(0) > BiasStart+BiasLength) {\n\t\t\tBiasLength = Raw_Seek(0) - BiasStart;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf this routine had to open the file, then close it before returning.\n\t*/\n\tif (opened) {\n\t\tClose();\n\t}\n\n\t/*\n\t**\tReturn with the number of bytes written. This will always be the number of bytes\n\t**\trequested, since the case of the disk being full is caught by this routine.\n\t*/\n\treturn(bytesread);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Seek -- Reposition the file pointer as indicated.                             *\n *                                                                                             *\n *    Use this routine to move the filepointer to the position indicated. It can move either   *\n *    relative to current position or absolute from the beginning or ending of the file. This  *\n *    routine will only return if it successfully performed the seek.                          *\n *                                                                                             *\n * INPUT:   pos   -- The position to seek to. This is interpreted as relative to the position  *\n *                   indicated by the \"dir\" parameter.                                         *\n *                                                                                             *\n *          dir   -- The relative position to relate the seek to. This can be either SEEK_SET  *\n *                   for the beginning of the file, SEEK_CUR for the current position, or      *\n *                   SEEK_END for the end of the file.                                         *\n *                                                                                             *\n * OUTPUT:  This routine returns the position that the seek ended up at.                       *\n *                                                                                             *\n * WARNINGS:   If there was a file error, then this routine might never return.                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Seek(long pos, int dir)\n{\n\n\t/*\n\t**\tA file that is biased will have a seek operation modified so that the file appears to\n\t**\texist only within the bias range. All bytes outside of this range appear to be\n\t**\tnon-existant.\n\t*/\n\tif (BiasLength != -1) {\n\t\tswitch (dir) {\n\t\t\tcase SEEK_SET:\n\t\t\t\tif (pos > BiasLength) {\n\t\t\t\t\tpos = BiasLength;\n\t\t\t\t}\n\t\t\t\tpos += BiasStart;\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_CUR:\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_END:\n\t\t\t\tdir = SEEK_SET;\n\t\t\t\tpos += BiasStart + BiasLength;\n//\t\t\t\tpos = (pos <= BiasStart+BiasLength) ? pos : BiasStart+BiasLength;\n//\t\t\t\tpos = (pos >= BiasStart) ? pos : BiasStart;\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tPerform the modified raw seek into the file.\n\t\t*/\n\t\tlong newpos = Raw_Seek(pos, dir) - BiasStart;\n\n\t\t/*\n\t\t**\tPerform a final double check to make sure the file position fits with the bias range.\n\t\t*/\n\t\tif (newpos < 0) {\n\t\t\tnewpos = Raw_Seek(BiasStart, SEEK_SET) - BiasStart;\n\t\t}\n\t\tif (newpos > BiasLength) {\n\t\t\tnewpos = Raw_Seek(BiasStart+BiasLength, SEEK_SET) - BiasStart;\n\t\t}\n\t\treturn(newpos);\n\t}\n\n\t/*\n\t**\tIf the file is not biased in any fashion, then the normal seek logic will\n\t**\twork just fine.\n\t*/\n\treturn(Raw_Seek(pos, dir));\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Size -- Determines size of file (in bytes).                                   *\n *                                                                                             *\n *    Use this routine to determine the size of the file. The file must exist or this is an    *\n *    error condition.                                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes in the file.                                      *\n *                                                                                             *\n * WARNINGS:   This routine handles error conditions and will not return unless the file       *\n *             exists and can successfully be queried for file length.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Size(void)\n{\n\tlong\tsize = 0;\n\n\t/*\n\t**\tA biased file already has its length determined.\n\t*/\n\tif (BiasLength != -1) {\n\t\treturn(BiasLength);\n\t}\n\n\t/*\n\t**\tIf the file is open, then proceed normally.\n\t*/\n\tif (Is_Open()) {\n\n#ifdef WIN32\n\t\tsize = GetFileSize(Handle, NULL);\n\n\t\t/*\n\t\t**\tIf there was in internal error, then call the error function.\n\t\t*/\n\t\tif (size == 0xFFFFFFFF) {\n\t\t\tError(GetLastError(), false, Filename);\n\t\t}\n#else\n\n\t\t/*\n\t\t**\tRepetitively try to determine the file size until a fatal error condition or success\n\t\t**\tis achieved.\n\t\t*/\n\t\tfor (;;) {\n\t\t\tHard_Error_Occured = 0;\n\t\t\tsize = filelength(Handle);\n\n\t\t\t/*\n\t\t\t**\tIf a hard error occurred, then assume it is the case of removed media. Display an\n\t\t\t**\terror condition and allow retry.\n\t\t\t*/\n\t\t\tif (Hard_Error_Occured) {\n\t\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\t\tcontinue;\n\t\t\t} else {\n\t\t\t\tif (size == -1) {\n\t\t\t\t\tError(errno, false, Filename);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n#endif\n\n\t} else {\n\n\t\t/*\n\t\t**\tIf the file wasn't open, then open the file and call this routine again. Count on\n\t\t**\tthe fact that the open function must succeed.\n\t\t*/\n\t\tif (Open()) {\n\t\t\tsize = Size();\n\n\t\t\t/*\n\t\t\t**\tSince we needed to open the file we must remember to close the file when the\n\t\t\t**\tsize has been determined.\n\t\t\t*/\n\t\t\tClose();\n\t\t}\n\t}\n\n\tBiasLength = size-BiasStart;\n\treturn(BiasLength);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Create -- Creates an empty file.                                              *\n *                                                                                             *\n *    This routine will create an empty file from the file object. The file object's filename  *\n *    must already have been assigned before this routine will function.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the file successfully created? This routine will always return true.     *\n *                                                                                             *\n * WARNINGS:   A fatal error condition could occur with this routine. Especially if the disk   *\n *             is full or a read-only media was selected.                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Create(void)\n{\n\tClose();\n\tif (Open(WRITE)) {\n\n\t\t/*\n\t\t**\tA biased file must be at least as long as the bias offset. Seeking to the\n\t\t**\tappropriate start offset has the effect of lengthening the file to the\n\t\t**\tcorrect length.\n\t\t*/\n\t\tif (BiasLength != -1) {\n\t\t\tSeek(0, SEEK_SET);\n\t\t}\n\n\t\tClose();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Delete -- Deletes the file object from the disk.                              *\n *                                                                                             *\n *    This routine will delete the file object from the disk. If the file object doesn't       *\n *    exist, then this routine will return as if it had succeeded (since the effect is the     *\n *    same).                                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the file deleted? If the file was already missing, the this value will   *\n *                be false.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Delete(void)\n{\n\t/*\n\t**\tIf the file was open, then it must be closed first.\n\t*/\n\tClose();\n\n\t/*\n\t**\tIf there is no filename associated with this object, then this indicates a fatal error\n\t**\tcondition. Report this and abort.\n\t*/\n\tif (!Filename) {\n\t\tError(ENOENT, false);\n\t}\n\n\t/*\n\t**\tRepetitively try to delete the file if possible. Either return with success, or\n\t**\tabort the program with an error.\n\t*/\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tIf the file is already missing, then return with this fact. No action is necessary.\n\t\t**\tThis can occur as this section loops if the file exists on a floppy and the floppy\n\t\t**\twas removed, the file deleted on another machine, and then the floppy was\n\t\t**\treinserted. Admittedly, this is a rare case, but is handled here.\n\t\t*/\n\t\tif (!Is_Available()) {\n\t\t\treturn(false);\n\t\t}\n\n#ifdef WIN32\n\t\tif (!DeleteFile(Filename)) {\n\t\t\tError(GetLastError(), false, Filename);\n\t\t\treturn(false);\n\t\t}\n#else\n\t\tHard_Error_Occured = 0;\n\t\tif (remove(Filename) == -1) {\n\n\t\t\t/*\n\t\t\t**\tIf a hard error occurred, then assume that the media has been removed. Display\n\t\t\t**\terror message and retry as directed.\n\t\t\t*/\n\t\t\tif (Hard_Error_Occured) {\n\t\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf at this point, DOS says the file doesn't exist, then just exit with this\n\t\t\t**\tfact. It should have been caught earlier, but in any case, this is a legal\n\t\t\t**\tcondition.\n\t\t\t*/\n\t\t\tif (errno == ENOENT) break;\n\n\t\t\t/*\n\t\t\t**\tThe only way it can reach this point is if DOS indicates that access is denied\n\t\t\t**\ton the file. This occurs when trying to delete a file on a read-only media such\n\t\t\t**\tas a CD-ROM. Report this as a fatal error and then abort.\n\t\t\t*/\n\t\t\tError(errno, false, Filename);\n\t\t}\n#endif\n\t\tbreak;\n\t}\n\n\t/*\n\t**\tDOS reports that the file was successfully deleted. Return with this fact.\n\t*/\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Get_Date_Time -- Gets the date and time the file was last modified.           *\n *                                                                                             *\n *    Use this routine to get the date and time of the file.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the file date and time as a long.                                     *\n *          Use the YEAR(long), MONTH(),....                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *   07/13/1996 JLB : Handles win32 method.                                                    *\n *=============================================================================================*/\nunsigned long RawFileClass::Get_Date_Time(void)\n{\n#ifdef WIN32\n\tBY_HANDLE_FILE_INFORMATION info;\n\n\tif (GetFileInformationByHandle(Handle, &info)) {\n\t\tWORD dosdate;\n\t\tWORD dostime;\n\t\tFileTimeToDosDateTime(&info.ftLastWriteTime, &dosdate, &dostime);\n\t\treturn((dosdate << 16) | dostime);\n\t}\n\treturn(0);\n#else\n\tunsigned short time;\n\tunsigned short date;\n\tunsigned long datetime = 0;\n\n\n\t//\n\t//\tIf the file is open, then proceed normally.\n\t//\n\tif ( RawFileClass::Is_Open() ) {\n\t\tif ( _dos_getftime( Handle, &date, &time ) ) {\n\t\t\t//\n\t\t\t// return 0 indicating error with no date and time\n\t\t\t//\n\t\t\treturn( datetime );\n\t\t}\n\t} else {\n\n\t\t//\n\t\t//\tIf the file wasn't open, then see if the file exists.\n\t\t//\n\t\tif ( RawFileClass::Is_Available() ) {\n\t\t\tRawFileClass::Open();\n\n\t\t\tif ( _dos_getftime( Handle, &date, &time ) ) {\n\t\t\t\tRawFileClass::Close();\n\t\t\t\t//\n\t\t\t\t// return 0 indicating error with no date and time\n\t\t\t\t//\n\t\t\t\treturn( datetime );\n\t\t\t}\n\n\t\t\tRawFileClass::Close();\n\t\t} else {\n\t\t\t//\n\t\t\t// return 0 indicating error with no date and time\n\t\t\t//\n\t\t\treturn( datetime );\n\t\t}\n\t}\n\n\t//\n\t// combine the date and time as a long\n\t//\n\tdatetime = (date << 16) + time;\n\n\treturn( datetime );\n#endif\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Set_Date_Time -- Sets the date and time the file was last modified.           *\n *                                                                                             *\n *    Use this routine to set the date and time of the file.                                   *\n *                                                                                             *\n * INPUT:   the file date and time as a long                                                   *\n *                                                                                             *\n * OUTPUT:  successful or not if the file date and time was changed.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *   07/13/1996 JLB : Handles win 32 method                                                    *\n *=============================================================================================*/\nbool RawFileClass::Set_Date_Time(unsigned long datetime)\n{\n#ifdef WIN32\n\tif (RawFileClass::Is_Open()) {\n\t\tBY_HANDLE_FILE_INFORMATION info;\n\n\t\tif (GetFileInformationByHandle(Handle, &info)) {\n\t\t\tFILETIME filetime;\n\t\t\tif (DosDateTimeToFileTime((WORD)(datetime >> 16), (WORD)(datetime & 0x0FFFF), &filetime)) {\n\t\t\t\treturn(SetFileTime(Handle, &info.ftCreationTime, &filetime, &filetime));\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n#else\n\tunsigned short time;\n\tunsigned short date;\n\n\t//\n\t//\tIf the file is open, then proceed normally.\n\t//\n\tif ( RawFileClass::Is_Open() ) {\n\t\t//\n\t\t// only set the date and time if open for READ only\n\t\t//\n\t\tif ( Rights == READ ) {\n\t\t\ttime = (unsigned short)(datetime & 0xFFFF);\n\t\t\tdate = (unsigned short)((datetime >> 16) & 0xFFFF);\n\n\t\t\tif ( !_dos_setftime( Handle, date, time ) ) {\n\t\t\t\t//\n\t\t\t\t// return true indicating success\n\t\t\t\t//\n\t\t\t\treturn( true );\n\t\t\t}\n\t\t}\n\t} else {\n\n\t\t//\n\t\t//\tIf the file wasn't open, then see if the file exists.\n\t\t//\n\t\tif ( RawFileClass::Is_Available() ) {\n\t\t\tRawFileClass::Open();\n\n\t\t\ttime = (unsigned short)(datetime & 0xFFFF);\n\t\t\tdate = (unsigned short)((datetime >> 16) & 0xFFFF);\n\n\t\t\tif ( !_dos_setftime( Handle, date, time ) ) {\n\t\t\t\tRawFileClass::Close();\n\t\t\t\t//\n\t\t\t\t// return true indicating success\n\t\t\t\t//\n\t\t\t\treturn( true );\n\t\t\t}\n\n\t\t\tRawFileClass::Close();\n\t\t}\n\t}\n\n\t//\n\t// return false indicating error\n\t//\n\treturn( false );\n#endif\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Bias -- Bias a file with a specific starting position and length.             *\n *                                                                                             *\n *    This will bias a file by giving it an artificial starting position and length. By        *\n *    using this routine, it is possible to 'fool' the file into ignoring a header and         *\n *    trailing extra data. An example of this would be a file inside of a mixfile.             *\n *                                                                                             *\n * INPUT:   start    -- The starting offset that will now be considered the start of the       *\n *                      file.                                                                  *\n *                                                                                             *\n *          length   -- The forced length of the file. For files that are opened for write,    *\n *                      this serves as the artificial constraint on the file's length. For     *\n *                      files opened for read, this limits the usable file size.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RawFileClass::Bias(int start, int length)\n{\n\tif (start == 0) {\n\t\tBiasStart = 0;\n\t\tBiasLength = -1;\n\t\treturn;\n\t}\n\n\tBiasLength = RawFileClass::Size();\n\tBiasStart += start;\n\tif (length != -1) {\n\t\tBiasLength = BiasLength < length ? BiasLength : length;\n\t}\n\tBiasLength = BiasLength > 0 ? BiasLength : 0;\n\n\t/*\n\t**\tMove the current file offset to a legal position if necessary and the\n\t**\tfile was open.\n\t*/\n\tif (Is_Open()) {\n\t\tRawFileClass::Seek(0, SEEK_SET);\n\t}\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Raw_Seek -- Performs a seek on the unbiased file                              *\n *                                                                                             *\n *    This will perform a seek on the file as if it were unbiased. This is in spite of any     *\n *    bias setting the file may have. The ability to perform a raw seek in this fasion is      *\n *    necessary to maintain the bias ability.                                                  *\n *                                                                                             *\n * INPUT:   pos   -- The position to seek the file relative to the \"dir\" parameter.            *\n *                                                                                             *\n *          dir   -- The origin of the seek operation.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the new position of the seek operation.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Raw_Seek(long pos, int dir)\n{\n\t/*\n\t**\tIf the file isn't opened, then this is a fatal error condition.\n\t*/\n\tif (!Is_Open()) {\n\t\tError(EBADF, false, Filename);\n\t}\n\n#ifdef WIN32\n\tswitch (dir) {\n\t\tcase SEEK_SET:\n\t\t\tdir = FILE_BEGIN;\n\t\t\tbreak;\n\n\t\tcase SEEK_CUR:\n\t\t\tdir = FILE_CURRENT;\n\t\t\tbreak;\n\n\t\tcase SEEK_END:\n\t\t\tdir = FILE_END;\n\t\t\tbreak;\n\t}\n\n\tpos = SetFilePointer(Handle, pos, NULL, dir);\n\n\t/*\n\t**\tIf there was an error in the seek, then bail with an error condition.\n\t*/\n\tif (pos == 0xFFFFFFFF) {\n\t\tError(GetLastError(), false, Filename);\n\t}\n#else\n\n\t/*\n\t**\tKeep trying to seek until a non-retry condition occurs.\n\t*/\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tPerform the low level seek on the file.\n\t\t*/\n\t\tHard_Error_Occured = 0;\n\t\tpos = lseek(Handle, pos, dir);\n\n\t\t/*\n\t\t**\tIf a hard error occurred, then assume that it is the case of removed media. Display\n\t\t**\terror message and retry.\n\t\t*/\n\t\tif (Hard_Error_Occured) {\n\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\tcontinue;\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tA negative one indicates a fatal error with the seek operation. Display error\n\t\t\t**\tcondition and then abort.\n\t\t\t*/\n\t\t\tif (pos == -1) {\n\t\t\t\tError(errno, false, Filename);\n\t\t\t}\n\t\t}\n\t\tbreak;\n\t}\n#endif\n\n\t/*\n\t**\tReturn with the new position of the file. This will range between zero and the number of\n\t**\tbytes the file contains.\n\t*/\n\treturn(pos);\n}\n"
  },
  {
    "path": "CODE/RAWFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RAWFILE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Library                                             *\n *                                                                                             *\n *                    File Name : RAWFILE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 18, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RawFileClass::File_Name -- Returns with the filename associate with the file object.      *\n *   RawFileClass::RawFileClass -- Default constructor for a file object.                      *\n *   RawFileClass::~RawFileClass -- Default deconstructor for a file object.                   *\n *   RawFileClass::Is_Open -- Checks to see if the file is open or not.                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef RAWFILE_Hx\n#define RAWFILE_Hx\n\n#include\t<limits.h>\n#include\t<errno.h>\n#include\t<stddef.h>\n#include\t<stdlib.h>\n\n#ifdef WIN32\n#include\t<windows.h>\n\n#define\tNULL_HANDLE\t\tINVALID_HANDLE_VALUE\n#define\tHANDLE_TYPE\t\tHANDLE\n#else\n#define\tNULL_HANDLE\t\t-1\n#define\tHANDLE_TYPE\t\tint\n#endif\n\n#include\t\"wwfile.h\"\n\n#ifdef NEVER\n\t/*\n\t**\tThis is a duplicate of the error numbers. The error handler for the RawFileClass handles\n\t**\tthese errors. If the error routine is overridden and additional errors are defined, then\n\t**\tuse numbers starting with 100. Note that these errors here are listed in numerical order.\n\t**\tThese errors are defined in the standard header file \"ERRNO.H\".\n\t*/\n\tEZERO,\t\t\t\t// Non-error.\n\tEINVFNC,\t\t\t\t// Invalid function number.\n\tENOFILE,\t\t\t\t// File not found.\n\tENOENT=ENOFILE,\t// No such file or directory.\n\tENOPATH,\t\t\t\t// Path not found.\n\tEMFILE,\t\t\t\t// Too many open files.\n\tEACCES,\t\t\t\t// Permission denied.\n\tEBADF,\t\t\t\t// Bad file number.\n\tECONTR,\t\t\t\t// Memory blocks destroyed.\n\tENOMEM,\t\t\t\t// Not enough core memory.\n\tEINVMEM,\t\t\t\t// Invalid memory block address.\n\tEINVENV,\t\t\t\t// Invalid environment.\n\tEINVFMT,\t\t\t\t// Invalid format.\n\tEINVACC,\t\t\t\t// Invalid access code.\n\tEINVDAT,\t\t\t\t// Invalid data.\n\tEFAULT,\t\t\t\t// Unknown error.\n\tEINVDRV,\t\t\t\t// Invalid drive specified.\n\tENODEV=EINVDRV,\t// No such device.\n\tECURDIR,\t\t\t\t// Attempt to remove CurDir.\n\tENOTSAM,\t\t\t\t// Not same device.\n\tENMFILE,\t\t\t\t// No more files.\n\tEINVAL,\t\t\t\t// Invalid argument.\n\tE2BIG,\t\t\t\t// Argument list too long.\n\tENOEXEC,\t\t\t\t// exec format error.\n\tEXDEV,\t\t\t\t// Cross-device link.\n\tENFILE,\t\t\t\t// Too many open files.\n\tECHILD,\t\t\t\t// No child process.\n\tENOTTY,\t\t\t\t// not used\n\tETXTBSY,\t\t\t\t// not used\n\tEFBIG,\t\t\t\t// not used\n\tENOSPC,\t\t\t\t// No space left on device.\n\tESPIPE,\t\t\t\t// Illegal seek.\n\tEROFS,\t\t\t\t// Read-only file system.\n\tEMLINK,\t\t\t\t// not used\n\tEPIPE,\t\t\t\t// Broken pipe.\n\tEDOM,\t\t\t\t\t// Math argument.\n\tERANGE,\t\t\t\t// Result too large.\n\tEEXIST,\t\t\t\t// File already exists.\n\tEDEADLOCK,\t\t\t// Locking violation.\n\tEPERM,\t\t\t\t// Operation not permitted.\n\tESRCH,\t\t\t\t// not used\n\tEINTR,\t\t\t\t// Interrupted function call.\n\tEIO,\t\t\t\t\t// Input/output error.\n\tENXIO,\t\t\t\t// No such device or address.\n\tEAGAIN,\t\t\t\t// Resource temporarily unavailable.\n\tENOTBLK,\t\t\t\t// not used\n\tEBUSY,\t\t\t\t// Resource busy.\n\tENOTDIR,\t\t\t\t// not used\n\tEISDIR,\t\t\t\t// not used\n\tEUCLEAN,\t\t\t\t// not used\n#endif\n\n#ifndef WWERROR\n#define WWERROR\t-1\n#endif\n\n/*\n**\tThis is the definition of the raw file class. It is derived from the abstract base FileClass\n**\tand handles the interface to the low level DOS routines. This is the first class in the\n**\tchain of derived file classes that actually performs a useful function. With this class,\n**\tI/O is possible. More sophisticated features, such as packed files, CD-ROM support,\n**\tfile caching, and XMS/EMS memory support, are handled by derived classes.\n**\n**\tOf particular importance is the need to override the error routine if more sophisticated\n**\terror handling is required. This is more than likely if greater functionality is derived\n**\tfrom this base class.\n*/\nclass RawFileClass : public FileClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tThis is a record of the access rights used to open the file. These rights are\n\t\t**\tused if the file object is duplicated.\n\t\t*/\n\t\tint Rights;\n\n\t\tRawFileClass(char const *filename);\n\t\tRawFileClass(void);\n\t\tRawFileClass (RawFileClass const & f);\n\t\tRawFileClass & operator = (RawFileClass const & f);\n\t\tvirtual ~RawFileClass(void);\n\n\t\tvirtual char const * File_Name(void) const;\n\t\tvirtual char const * Set_Name(char const *filename);\n\t\tvirtual int Create(void);\n\t\tvirtual int Delete(void);\n\t\tvirtual int Is_Available(int forced=false);\n\t\tvirtual int Is_Open(void) const;\n\t\tvirtual int Open(char const *filename, int rights=READ);\n\t\tvirtual int Open(int rights=READ);\n\t\tvirtual long Read(void *buffer, long size);\n\t\tvirtual long Seek(long pos, int dir=SEEK_CUR);\n\t\tvirtual long Size(void);\n\t\tvirtual long Write(void const *buffer, long size);\n\t\tvirtual void Close(void);\n\t\tvirtual unsigned long Get_Date_Time(void);\n\t\tvirtual bool Set_Date_Time(unsigned long datetime);\n\t\tvirtual void Error(int error, int canretry = false, char const * filename=NULL);\n\n\t\tvoid Bias(int start, int length=-1);\n\n\t\tHANDLE_TYPE Get_File_Handle(void) { return (Handle); };\n\n\t\t/*\n\t\t**\tThese bias values enable a sub-portion of a file to appear as if it\n\t\t**\twere the whole file. This comes in very handy for multi-part files such as\n\t\t**\tmixfiles.\n\t\t*/\n\t\tint BiasStart;\n\t\tint BiasLength;\n\n\tprotected:\n\n\t\t/*\n\t\t**\tThis function returns the largest size a low level DOS read or write may\n\t\t**\tperform. Larger file transfers are performed in chunks of this size or less.\n\t\t*/\n\t\tlong Transfer_Block_Size(void) {return (long)((unsigned)UINT_MAX)-16L;};\n\n\t\tlong Raw_Seek(long pos, int dir=SEEK_CUR);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is the low level DOS handle. A -1 indicates an empty condition.\n\t\t*/\n\t\tHANDLE_TYPE Handle;\n\n\t\t/*\n\t\t**\tThis points to the filename as a NULL terminated string. It may point to either a\n\t\t**\tconstant or an allocated string as indicated by the \"Allocated\" flag.\n\t\t*/\n\t\tchar const * const Filename;\n\n\t\t//\n\t\t// file date and time are in the following formats:\n\t\t//\n\t\t//      date   bits 0-4   day (0-31)\n\t\t//             bits 5-8   month (1-12)\n\t\t//             bits 9-15  year (0-119 representing 1980-2099)\n\t\t//\n\t\t//      time   bits 0-4   second/2 (0-29)\n\t\t//             bits 5-10  minutes (0-59)\n\t\t//             bits 11-15 hours (0-23)\n\t\t//\n\t\tunsigned short Date;\n\t\tunsigned short Time;\n\n\t\t/*\n\t\t**\tFilenames that were assigned as part of the construction process\n\t\t**\tare not allocated. It is assumed that the filename string is a\n\t\t**\tconstant in that case and thus making duplication unnecessary.\n\t\t**\tThis value will be non-zero if the filename has be allocated\n\t\t**\t(using strdup()).\n\t\t*/\n\t\tunsigned Allocated:1;\n};\n\n\n/***********************************************************************************************\n * RawFileClass::File_Name -- Returns with the filename associate with the file object.        *\n *                                                                                             *\n *    Use this routine to determine what filename is associated with this file object. If no   *\n *    filename has yet been assigned, then this routing will return NULL.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the file name associated with this file object or NULL   *\n *          if one doesn't exist.                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline char const * RawFileClass::File_Name(void) const\n{\n\treturn(Filename);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::RawFileClass -- Default constructor for a file object.                        *\n *                                                                                             *\n *    This constructs a null file object. A null file object has no file handle or filename    *\n *    associated with it. In order to use a file object created in this fashion it must be     *\n *    assigned a name and then opened.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline RawFileClass::RawFileClass(void) :\n\tRights(READ),\n\tBiasStart(0),\n\tBiasLength(-1),\n\t#ifdef WIN32\n\tHandle(INVALID_HANDLE_VALUE),\n\t#else\n\tHandle(-1),\n\t#endif\n\tFilename(0),\n\tDate(0),\n\tTime(0),\n\tAllocated(false)\n{\n}\n\n\n/***********************************************************************************************\n * RawFileClass::~RawFileClass -- Default deconstructor for a file object.                     *\n *                                                                                             *\n *    This constructs a null file object. A null file object has no file handle or filename    *\n *    associated with it. In order to use a file object created in this fashion it must be     *\n *    assigned a name and then opened.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline RawFileClass::~RawFileClass(void)\n{\n\tClose();\n\tif (Allocated && Filename) {\n\t\tfree((char *)Filename);\n\t\t((char *&)Filename) = 0;\n\t\tAllocated = false;\n\t}\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Is_Open -- Checks to see if the file is open or not.                          *\n *                                                                                             *\n *    Use this routine to determine if the file is open. It returns true if it is.             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file open?                                                            *\n *                                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int RawFileClass::Is_Open(void) const\n{\n#ifdef WIN32\n\treturn(Handle != INVALID_HANDLE_VALUE);\n#else\n\treturn (Handle >= 0);\n#endif\n}\n\n#endif\n"
  },
  {
    "path": "CODE/RAWOLAPI.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifdef WOLAPI_INTEGRATION\n\n//\trawolapi.cpp - Core WOLAPI interface functions stuff.\n//\tDefinitions for RAChatEventSink, RADownloadEventSink, RANetUtilEventSink.\n//\tajw 07/10/98\n\n#include \"RAWolapi.h\"\n#define IID_DEFINED\n#include \"wolapi\\wolapi_i.c\"\n#include \"WolapiOb.h\"\n#include \"WolStrng.h\"\n#include \"Wol_gsup.h\"\n#include \"wolapi\\netutildefs.h\"\n\n#include \"WolDebug.h\"\n\nbool operator<( const User& u1, const User& u2 );\n\nconst char* Game_Registry_Key();\n\n//\tThe definitions of QueryInterface, AddRef, and Release are needed because we are not including\n//\tfiles that ordinarily (under MSVC) would define these for us, as part of CComObjectRoot, I believe.\n//\tThis Watcom has no equivalent we can use, so we do it manually...\n\n//***********************************************************************************************\nRAChatEventSink::RAChatEventSink( WolapiObject* pOwnerIn ) : m_cRef( 0 ), \t//\tinit the reference count\n\tbRequestServerListWait( false ),\n\tpOwner( pOwnerIn ),\n\tpServer( NULL ),\n\tbConnected( false ),\n\thresRequestConnectionError( 0 ),\n\tpChannelList( NULL ),\n\tpUserList( NULL ),\n\tpUserTail( NULL ),\n\tszMotd( NULL ),\n\tbJoined( false ),\n\tbGotKickedTrigger( false ),\n\tbIgnoreChannelLists( false ),\n\tbRequestChannelListForLobbiesWait( false ),\n\tpGameUserList( NULL ),\n\tbRequestGameStartWait( false ),\n\tpUserIPList( NULL ),\n\tpUserIPListTail( NULL ),\n\tiGameID( 0 )\n{\n}\n\n//***********************************************************************************************\nRAChatEventSink::~RAChatEventSink()\n{\n//\tdebugprint( \"RAChatEventSink destructor\\n\" );\n\tdelete pServer;\n\tdelete [] szMotd;\n\tDeleteChannelList();\n\tDeleteUserList();\n\tDeleteUserIPList();\n}\n\n//\t\t\tInterface IUnknown Methods\n//***********************************************************************************************\n// QueryInterface\n//\nHRESULT __stdcall\nRAChatEventSink::QueryInterface(const IID& iid, void** ppv)\n{\n//\tdebugprint( \"RAChatEventSink::QueryInterface\\n\" );\n\tif ((iid == IID_IUnknown) ||(iid == IID_IChatEvent))\n\t{\n\t\t*ppv = (IChatEvent*)this;\t\t//\tRemoved static_cast<> ajw\n\t}\n\telse\n\t{\n\t\t*ppv = NULL;\n\t\treturn E_NOINTERFACE;\n\t}\n\t((IUnknown*)(*ppv))->AddRef();\t\t//\tRemoved reinterpret_cast<> ajw\n\treturn S_OK ;\n}\n\n//***********************************************************************************************\n// AddRef\n//\nULONG __stdcall\nRAChatEventSink::AddRef()\n{\n//\tdebugprint( \"RAChatEventSink::AddRef\\n\" );\n\treturn InterlockedIncrement(&m_cRef) ;\n}\n\n//***********************************************************************************************\n// Release\n//\nULONG __stdcall\nRAChatEventSink::Release()\n{\n//\tdebugprint( \"RAChatEventSink::Release\\n\" );\n\tif (InterlockedDecrement(&m_cRef) == 0)\n\t{\n\t\tdelete this ;\n\t\treturn 0 ;\n\t}\n\treturn m_cRef;\n}\n\n//***********************************************************************************************\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnServerList( HRESULT hRes, Server* pServerHead )\n{\n\t//strcpy( szLadderServerHost, \"games.westwood.com\" );\n\t//iLadderServerPort = 3840;\n\t//strcpy( szGameResServerHost, \"games.westwood.com\" );\n\n//\tdebugprint( \">>> OnServerList got: %i \", hRes );\n\tDebugChatDef( hRes );\n\n\tif( pServer )\n\t{\n\t\tdelete pServer;\n\t\tpServer = NULL;\n\t}\n\n\tif( SUCCEEDED( hRes ) )\n\t{\n\t\twhile( pServerHead )\n\t\t{\n\t\t\t//\tCopy the first IRC Server to use in the RequestConnection() call.\n\t\t\tif( !pServer && ( strcmp( (char*)pServerHead->connlabel, \"IRC\" ) == 0 ) )\n\t\t\t{\n\t\t\t\tpServer = new Server;\n\t\t\t\t*pServer = *pServerHead;\n\t\t\t}\n\t\t\telse if( !*pOwner->szLadderServerHost && ( strcmp( (char*)pServerHead->connlabel, \"LAD\" ) == 0 ) )\n\t\t\t{\n//\t\t\t\tdebugprint( \"Scanning '%s'\\n\", (char*)pServerHead->conndata );\n\t\t\t\tchar* token;\n\t\t\t\ttoken = strtok( (char*)pServerHead->conndata, \";\" );\n\t\t\t\ttoken = strtok( NULL, \";\" );\n\t\t\t\tstrcpy( pOwner->szLadderServerHost, token );\n\t\t\t\ttoken = strtok( NULL, \";\" );\n\t\t\t\tpOwner->iLadderServerPort = atoi( token );\n//\t\t\t\tdebugprint( \"Ladder is at: %s, port %i\\n\", pOwner->szLadderServerHost, pOwner->iLadderServerPort );\n\t\t\t}\n\t\t\telse if( !*pOwner->szGameResServerHost1 && ( strcmp( (char*)pServerHead->connlabel, \"GAM\" ) == 0 ) )\n\t\t\t{\n\t\t\t\t//\tThis is the Red Alert game results port.\n\t\t\t\tchar* token;\n\t\t\t\ttoken = strtok( (char*)pServerHead->conndata, \";\" );\n\t\t\t\ttoken = strtok( NULL, \";\" );\n\t\t\t\tstrcpy( pOwner->szGameResServerHost1, token );\n\t\t\t\ttoken = strtok( NULL, \";\" );\n\t\t\t\tpOwner->iGameResServerPort1 = atoi( token );\n//\t\t\t\tdebugprint( \"GameRes is at: %s, port %i\\n\", pOwner->szGameResServerHost, pOwner->iGameResServerPort );\n\t\t\t}\n\t\t\telse if( !*pOwner->szGameResServerHost2 && ( strcmp( (char*)pServerHead->connlabel, \"GAM\" ) == 0 ) )\n\t\t\t{\n\t\t\t\t//\tThis is the Aftermath game results port.\n\t\t\t\tchar* token;\n\t\t\t\ttoken = strtok( (char*)pServerHead->conndata, \";\" );\n\t\t\t\ttoken = strtok( NULL, \";\" );\n\t\t\t\tstrcpy( pOwner->szGameResServerHost2, token );\n\t\t\t\ttoken = strtok( NULL, \";\" );\n\t\t\t\tpOwner->iGameResServerPort2 = atoi( token );\n//\t\t\t\tdebugprint( \"GameRes is at: %s, port %i\\n\", pOwner->szGameResServerHost, pOwner->iGameResServerPort );\n\t\t\t}\n\t\t\tpServerHead = pServerHead->next;\n\t\t}\n\t}\n\n\tbRequestServerListWait = false;\n\treturn(S_OK);\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnPageSend( HRESULT hRes )\n{\n//\tdebugprint( \">>> OnPageSend got: %i \", hRes );\n\tDebugChatDef( hRes );\n\n\tif( hRes != CHAT_S_PAGE_NOTHERE && hRes != CHAT_S_PAGE_OFF && hRes != S_OK )\n\t\thRes = E_FAIL;\n\n\thresRequestPageResult = hRes;\n\n\tbRequestPageWait = false;\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnPaged( HRESULT, User* pUser, LPCSTR szMessage )\n{\n//\tdebugprint( \">>> OnPaged got: %s \", szMessage );\n\n\tchar* szPrint = new char[ strlen( (char*)pUser->name ) + strlen( szMessage ) + strlen( TXT_WOL_ONPAGE ) ];\n\tsprintf( szPrint, TXT_WOL_ONPAGE, (char*)pUser->name, szMessage );\n\tif( !pOwner->bInGame )\n\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_PAGE );\n\telse\n\t{\n\t\tSession.Messages.Add_Message( NULL, 0, szPrint, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );\n\t\tif( !pOwner->bFreezeExternalPager )\n\t\t\tstrcpy( pOwner->szExternalPager, (char*)pUser->name );\n\t\tMap.Flag_To_Redraw(true);\n\t}\n\n\tdelete [] szPrint;\n\n\tSound_Effect( WOLSOUND_ONPAGE );\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnFind( HRESULT hRes, Channel* pChannel )\n{\n//\tdebugprint( \">>> OnFind got: %i \", hRes );\n\tDebugChatDef( hRes );\n\n\tif( hRes != CHAT_S_FIND_NOTHERE && hRes != CHAT_S_FIND_NOCHAN && hRes != CHAT_S_FIND_OFF && hRes != S_OK )\n\t\thRes = E_FAIL;\n\n\tif( hRes == S_OK )\n\t\tOnFindChannel = *pChannel;\n\n\thresRequestFindResult = hRes;\n\n\tbRequestFindWait = false;\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnLogout( HRESULT hRes, User* pUser )\n{\n//\tdebugprint( \">>> OnLogout got: \" );\n\tDebugChatDef( hRes );\n\n\tif( hRes == S_OK )\n\t{\n\t\t//\tSomeone has been logged out by the chat server due to inactivity.\n\t\t//\tFake a call to OnChannelLeave(), as the processing is identical.\n//\t\tdebugprint( \"OnLogout calling OnChannelLeave for %s, owner=%i\\n\", (char*)pUser->name, ( pUser->flags & CHAT_USER_CHANNELOWNER ) );\n\t\tOnChannelLeave( S_OK, NULL, pUser );\n\t}\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnBusy(HRESULT)\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnIdle(HRESULT)\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnConnection( HRESULT hRes, LPCSTR motd )\n{\n//\tdebugprint( \">>> OnConnection got: \" );\n\tDebugChatDef( hRes );\n\n\tif( hRes == S_OK )\n\t{\n\n\t\t//\tPrepare a new string for a modified version of motd.\n\t\tszMotd = new char[ strlen( motd ) + 1 ];\n\t\t//\tReplace single line breaks with a space.\n\t\t//\tReplace double line breaks with double carriage returns.\n\n\t\tbool\tbJustDidBreak = false;\n\t\tconst char*\tszIn = motd;\n\t\tchar*   szOut = szMotd;\n\n\t\twhile( *szIn )\n\t\t{\n\t\t\tif( *szIn == '\\r' && *( szIn + 1 ) == '\\n' )\n\t\t\t{\n\t\t\t\tif( !bJustDidBreak )\n\t\t\t\t{\n\t\t\t\t\t*szOut++ = ' ';\n\t\t\t\t\tbJustDidBreak = true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tszOut--;\n\t\t\t\t\t*szOut++ = '\\r';\n\t\t\t\t\t*szOut++ = '\\r';\n\t\t\t\t\tbJustDidBreak = false;\n//\t\t\t\t\tdebugprint( \"^\" );\n\t\t\t\t}\n\t\t\t\tszIn += 2;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t*szOut++ = *szIn++;\n\t\t\t\tbJustDidBreak = false;\n\t\t\t}\n//\t\t\tdebugprint( \"%c\", *( szOut - 1 ) );\n\t\t}\n\t\t*szOut = 0;\t\t//\tNull-terminate.\n//\t\tdebugprint( \"\\n\" );\n\n//\t\tpOwner->PrintMessage( szMotd );\n\n\t\tbConnected = true;\n\t}\n\telse\n\t{\n\t\thresRequestConnectionError = hRes;\n\n\t\tchar szError[150];\n\t\tChatDefAsText( szError, hRes );\n\t\tstrcat( szError, \" (Connect Error)\" );\n//\t\tdebugprint( szError );\n\t}\n\n\tbRequestConnectionWait = false;\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnChannelCreate( HRESULT hRes, Channel* )\n{\n//\tdebugprint( \">>> OnChannelCreate got: %i \", hRes );\n\tDebugChatDef( hRes );\n\n//\tif( bJoined )\n//\t{\n//\t\tWWMessageBox().Process( \"RAChatEventSink::OnChannelCreate called when bJoined is true!\" );\n//\t\tFatal( \"RAChatEventSink::OnChannelCreate called when bJoined is true!\" );\n//\t}\n\n\tif( SUCCEEDED( hRes ) )\n\t{\n\t\tbJoined = true;\n\t}\n\tbRequestChannelCreateWait = false;\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnChannelModify(HRESULT, Channel *)\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnChannelJoin( HRESULT hRes, Channel* /*pChannel*/, User* pUser )\n{\n//\tif( SUCCEEDED( hRes ) )\n//\t\tdebugprint( \">>> OnChannelJoin got: channel '%s', user '%s', %i \", (char*)pChannel->name, (char*)pUser->name, hRes );\n//\telse\n//\t\tdebugprint( \">>> OnChannelJoin got: %i \", hRes );\n\tDebugChatDef( hRes );\n\n//\t//\tSpecial case - ignore OnChannelJoin when waiting for a UserList.\n//\tif( bRequestUserListWait )\n//\t{\n//\t\tdebugprint( \"bRequestUserListWait is true - ignoring join.\\n\" );\n//\t\treturn S_OK;\n//\t}\n\n\thresRequestJoinResult = hRes;\n\tif( SUCCEEDED( hRes ) )\n\t{\n\t\tif( pUser->flags & CHAT_USER_MYSELF )\n\t\t{\n\t\t\tbJoined = true;\n\t\t\tbRequestChannelJoinWait = false;\n\t\t\tif( pUserList )\n\t\t\t{\n\t\t\t\t//\tShould never happen.\n//\t\t\t\tdebugprint( \"pUserList should be NULL (as I am the joiner)!!! Deleting user list...\\n\" );\n\t\t\t\tDeleteUserList();\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif( pOwner->CurrentLevel == WOL_LEVEL_INGAMECHANNEL )\n\t\t\t{\n\t\t\t\tif( pOwner->pGSupDlg && \n\t\t\t\t\t( pOwner->pGSupDlg->bHostSayGo || pOwner->pGSupDlg->bHostWaitingForGoTrigger || \n\t\t\t\t\t\tpOwner->pGSupDlg->bExitForGameTrigger || iGameID ) )\n\t\t\t\t{\n\t\t\t\t\t//\tA game has this moment entered the \"must start\" phase. We can ignore the fact that others are leaving the channel.\n//\t\t\t\t\tdebugprint( \"Ignoring leave because game is starting.\\n\" );\n\t\t\t\t\treturn S_OK;\n\t\t\t\t}\n\t\t\t}\n\t\t\t//\tAdd user to our current channel users list.\n\t\t\tif( !pUserList )\n\t\t\t{\n//\t\t\t\tdebugprint( \"pUserList is null in OnChannelJoin - ignoring %s join... \\n\", (char*)pUser->name );\n\t\t\t\treturn S_OK;\n\t\t\t}\n//\t\t\tif( !pUserList )\n//\t\t\t{\n//\t\t\t\t//\tThere has to be at least one user there - you.\n//\t\t\t\tdebugprint( \"pUserList is null in OnChannelJoin!!! users: %s\\n\", (char*)pUser->name );\n//\t\t\t\tFatal( \"pUserList is null in OnChannelJoin!!!\\n\" );\n//\t\t\t}\n\t\t\t\n\t\t\tUser* pUserNew = new User;\n\t\t\t*pUserNew = *pUser;\n\t\t\tpUserNew->next = NULL;\t\t\t//\t(We don't want the value that was just copied!)\n\n\t\t\t//\tInsert user into list alphabetically.\n\t\t\tInsertUserSorted( pUserNew );\n\n\t\t\t//\tUpdate the shown list.\n\t\t\tpOwner->ListChannelUsers();\n\n\t\t\tif( pOwner->CurrentLevel == WOL_LEVEL_INGAMECHANNEL )\n\t\t\t{\n\t\t\t\t_ASSERTE( pOwner->pGSupDlg );\n\t\t\t\tpOwner->pGSupDlg->OnGuestJoin( pUser );\n\n\t\t\t\t//\tAsk for this player's IP address.\n\t\t\t\tpOwner->RequestIPs( (char*)pUser->name );\n\t\t\t}\n\n\t\t\tif( pOwner->CurrentLevel == WOL_LEVEL_INGAMECHANNEL || pOwner->CurrentLevel == WOL_LEVEL_INLOBBY )\n\t\t\t{\n\t\t\t\t//\tRequest ladder results for new user.\n\t\t\t\tpOwner->RequestLadders( (char*)pUser->name );\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tbRequestChannelJoinWait = false;\n\t}\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nvoid RAChatEventSink::InsertUserSorted( User* pUserNew )\n{\n\tif( !pUserList )\n\t{\n\t\tpUserList = pUserNew;\n\t\tpUserTail = pUserNew;\n\t}\n\telse\n\t{\n\t\tif( *pUserNew < *pUserList )\n\t\t{\n\t\t\t//\tInsert user at beginning.\n\t\t\tpUserNew->next = pUserList;\n\t\t\tpUserList = pUserNew;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tUser* pUserCheck = pUserList;\n\t\t\tUser* pUserInsertAfter = NULL;\n\t\t\twhile( pUserCheck->next )\n\t\t\t{\n\t\t\t\tif( *pUserNew < *pUserCheck->next )\n\t\t\t\t{\n\t\t\t\t\tpUserInsertAfter = pUserCheck;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tpUserCheck = pUserCheck->next;\n\t\t\t}\n\t\t\tif( pUserInsertAfter )\n\t\t\t{\n\t\t\t\tpUserNew->next = pUserInsertAfter->next;\n\t\t\t\tpUserInsertAfter->next = pUserNew;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//\tAdd user to end.\n\t\t\t\tpUserTail->next = pUserNew;\n\t\t\t\tpUserTail = pUserNew;\n\t\t\t}\n\t\t}\n\t}\n}\n\n//***********************************************************************************************\nbool operator<( const User& u1, const User& u2 )\n{\n\tif( u1.flags & CHAT_USER_CHANNELOWNER && !( u2.flags & CHAT_USER_CHANNELOWNER ) )\n\t\treturn true;\n\tif( !( u1.flags & CHAT_USER_CHANNELOWNER ) && u2.flags & CHAT_USER_CHANNELOWNER )\n\t\treturn false;\n\tif( u1.flags & CHAT_USER_VOICE && !( u2.flags & CHAT_USER_VOICE ) )\n\t\treturn true;\n\tif( !( u1.flags & CHAT_USER_VOICE ) && u2.flags & CHAT_USER_VOICE )\n\t\treturn false;\n\treturn ( _stricmp( (char*)u1.name, (char*)u2.name ) < 0 );\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnChannelLeave( HRESULT hRes, Channel*, User* pUser )\n{\n\t//\tNote: This is also called directly from OnUserKick(), below, when someone is kicked from a channel.\n\t//\tAlso now from OnLogout().\n\n//\tdebugprint( \">>> OnChannelLeave got %s: \", (char*)pUser->name );\n\tDebugChatDef( hRes );\n\n//\t//\tSpecial case - ignore OnChannelLeave when waiting for a UserList.\n//\tif( bRequestUserListWait )\n//\t{\n//\t\tdebugprint( \"bRequestUserListWait is true - ignoring leave.\\n\" );\n//\t\treturn S_OK;\n//\t}\n\n\tif( SUCCEEDED( hRes ) )\n\t{\n\t\tif( pUser->flags & CHAT_USER_MYSELF )\n\t\t{\n\t\t\tbJoined = false;\n\t\t\tbRequestChannelLeaveWait = false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//\tRemove user from our current channel users list.\n\t\t\tif( !pUserList )\n\t\t\t{\n//\t\t\t\tdebugprint( \"pUserList is null in OnChannelLeave - ignoring %s leave... \\n\", (char*)pUser->name );\n\t\t\t\treturn S_OK;\n\t\t\t}\n\t\t\tif( pOwner->CurrentLevel == WOL_LEVEL_INGAMECHANNEL )\n\t\t\t{\n\t\t\t\tif( pOwner->pGSupDlg && \n\t\t\t\t\t( pOwner->pGSupDlg->bHostSayGo || pOwner->pGSupDlg->bHostWaitingForGoTrigger || \n\t\t\t\t\t\tpOwner->pGSupDlg->bExitForGameTrigger || iGameID ) )\n\t\t\t\t{\n\t\t\t\t\t//\tA game has this moment entered the \"must start\" phase. We must ignore the fact that others are leaving the channel.\n//\t\t\t\t\tdebugprint( \"Ignoring leave because game is starting.\\n\" );\n\t\t\t\t\treturn S_OK;\n\t\t\t\t}\n\t\t\t}\n\t\t\tUser* pUserSearch = pUserList;\n\t\t\tUser* pUserPrevious = NULL;\n\t\t\tbool bFound = false;\n\t\t\twhile( pUserSearch )\n\t\t\t{\n\t\t\t\tif( _stricmp( (char*)pUserSearch->name, (char*)pUser->name ) == 0 )\n\t\t\t\t{\n\t\t\t\t\t//\tRemove from list.\n\t\t\t\t\tif( !pUserPrevious )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tHead of list is being removed.\n\t\t\t\t\t\tpUserList = pUserSearch->next;\n\t\t\t\t\t\tif( !pUserList )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//\tThis means all entries were removed. Can't happen, as you are still there.\n//\t\t\t\t\t\t\tdebugprint( \"This means all entries were removed. Can't happen, as you are still there. (OnChannelLeave)\\n\" );\n\t\t\t\t\t\t\tFatal( \"This means all entries were removed. Can't happen, as you are still there. (OnChannelLeave)\\n\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tpUserPrevious->next = pUserSearch->next;\n\t\t\t\t\t\tif( !pUserPrevious->next )\n\t\t\t\t\t\t\tpUserTail = pUserPrevious;\t\t//\tNew list tail.\n\t\t\t\t\t}\n\t\t\t\t\t//\tDestroy removed user.\n\t\t\t\t\tdelete pUserSearch;\n\t\t\t\t\tbFound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tpUserPrevious = pUserSearch;\n\t\t\t\tpUserSearch = pUserSearch->next;\n\t\t\t}\n\t\t\tif( !bFound )\n\t\t\t{\n\t\t\t\t//\tUser has to be found. This should not happen.\n//\t\t\t\tdebugprint( \"User not found for removal in OnChannelLeave!!!\\n\" );\n\t\t\t\treturn S_OK;\n\t\t\t}\n\n\t\t\tif( pOwner->CurrentLevel == WOL_LEVEL_INGAMECHANNEL )\n\t\t\t{\n\t\t\t\t//\tNote that the following is done before removing the user from the playerlist.\n\t\t\t\tchar* szPrint = new char[ strlen( TXT_WOL_PLAYERLEFTGAME ) + strlen( (char*)pUser->name ) + 5 ];\n\t\t\t\tsprintf( szPrint, TXT_WOL_PLAYERLEFTGAME, (char*)pUser->name );\n\t\t\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\t\tdelete [] szPrint;\n\t\t\t\tpOwner->pGSupDlg->OnGuestLeave( pUser );\n\t\t\t}\n\n\t\t\t//\tUpdate the shown list.\n\t\t\tpOwner->ListChannelUsers();\n\t\t}\n\t}\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnChannelTopic(HRESULT, Channel *, LPCSTR)\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnGroupList(HRESULT, Group *)\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnPublicMessage( HRESULT, Channel*, User* pUserSender, LPCSTR szMessage )\n{\n\tif( *szMessage )\n\t{\n\t\tif( strlen( szMessage ) > 3 && szMessage[0] == 35 && szMessage[1] == 97 && szMessage[2] == 106 && szMessage[3] == 119 )\n\t\t{\n\t\t\tif( strlen( szMessage ) > 4 )\n\t\t\t{\n\t\t\t\tint i = atoi( szMessage + 4 );\n\t\t\t\tif( i >= VOX_ACCOMPLISHED && i <= VOX_LOAD1 && pOwner->bEggSounds )\n\t\t\t\t\tSpeak( (VoxType)i );\n\t\t\t\tchar* szPrint = new char[ strlen( (char*)pUserSender->name ) + 16 ];\n\t\t\t\tsprintf( szPrint, \"%s!\", (char*)pUserSender->name );\n\t\t\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\t\tdelete [] szPrint;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tchar* szPrint = new char[ strlen( (char*)pUserSender->name ) + strlen( szMessage ) + 110 ];\n\t\t\tsprintf( szPrint, \"%s: %s\", (char*)pUserSender->name, szMessage );\n\t\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_PUBLICMESSAGE );\n\t\t\tdelete [] szPrint;\n\t\t}\n\t}\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnPrivateMessage( HRESULT, User* pUserSender, LPCSTR szMessage )\n{\n\t//\tIgnore private messages sent to myself by myself.\n\tif( pUserSender->flags & CHAT_USER_MYSELF )\n\t\treturn S_OK;\n\n\tif( *szMessage )\n\t{\n\t\tchar ci1[] = \"VGhpcyBpcyBBZGFtLiBIYXZlIHdlIG5vdCBwZXJjaGFuY2UgbWV0IGJlZm9yZT8=\";\n\t\tchar co1[48];\n\t\tBase64_Decode( ci1, strlen( ci1 ), co1, 47 );\n\t\tco1[47] = 0;\n\t\tif( strcmp( szMessage, co1 ) == 0 )\n\t\t{\n\t\t\tSYSTEMTIME SysTime;\n\t\t\t::GetSystemTime( &SysTime );\n\t\t\tchar szOut[60];\n\t\t\tchar ci2[] = \"SSBhbSB5b3VyIGFibGUgYW5kIHdpbGxpbmcgc2xhdmUu\";\n\t\t\tchar co2[34];\n\t\t\tBase64_Decode( ci2, strlen( ci2 ), co2, 33 );\n\t\t\tco2[33] = 0;\n\t\t\tsprintf( szOut, \"%s (%i/%i/%i)\", co2, SysTime.wMonth, SysTime.wDay, SysTime.wYear );\n\t\t\tUser UserReply;\n\t\t\tUserReply = *pUserSender;\n\t\t\tUserReply.next = NULL;\n\t\t\tpOwner->pChat->RequestPrivateMessage( &UserReply, szOut );\n\t\t\treturn S_OK;\n\t\t}\n\t\tif( !bSpecialMessage( szMessage ) )\n\t\t{\n\t\t\tif( strlen( szMessage ) > 3 && szMessage[0] == 35 && szMessage[1] == 97 && szMessage[2] == 106 && szMessage[3] == 119 )\n\t\t\t{\n\t\t\t\tif( strlen( szMessage ) > 4 )\n\t\t\t\t{\n\t\t\t\t\tint i = atoi( szMessage + 4 );\n\t\t\t\t\tif( i >= VOX_ACCOMPLISHED && i <= VOX_LOAD1 && pOwner->bEggSounds )\n\t\t\t\t\t\tSpeak( (VoxType)i );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tchar* szPrint = new char[ strlen( (char*)pUserSender->name ) + strlen( szMessage ) + 116 ];\n\t\t\t\tsprintf( szPrint, \"%s%s: %s\", (char*)pUserSender->name, TXT_WOL_PRIVATE, szMessage );\n\t\t\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_PRIVATEMESSAGE );\n\t\t\t\tSound_Effect( VOC_INCOMING_MESSAGE );\n\t\t\t\tdelete [] szPrint;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tchar* szOut = new char[ strlen( szMessage ) + 10 ];\n\t\t\tstrcpy( szOut, &szMessage[8] );\n\t\t\tpOwner->pChat->RequestPublicMessage( szOut );\n\t\t\tchar* szPrint = new char[ strlen( szOut ) + strlen( pOwner->szMyName ) + 10 ];\n\t\t\tsprintf( szPrint, \"%s: %s\", pOwner->szMyName, szOut );\n\t\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_SELFSPEAKING );\n\t\t\tdelete [] szPrint;\n\t\t\tdelete [] szOut;\n\t\t}\n\t}\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nbool RAChatEventSink::bSpecialMessage( const char* szMessage )\n{\n\tif( strlen( szMessage ) < 9 )\n\t\treturn false;\n\tif( szMessage[0] != 33 || szMessage[1] != 97 || szMessage[2] != 106 || szMessage[3] != 119 )\n\t\treturn false;\n\tSYSTEMTIME SysTime;\n\t::GetSystemTime( &SysTime );\n\tchar szCode[5];\n\tmemcpy( (void*)szCode, (void*)&szMessage[4], 4 );\n\tszCode[4] = 0;\n\tint iCode = atoi( szCode );\n\treturn ( iCode == ( ( SysTime.wMonth * 99 ^ SysTime.wDay * 33 ) ^ SysTime.wYear ) );\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnSystemMessage(HRESULT, LPCSTR)\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnNetStatus( HRESULT hRes )\n{\n//\tdebugprint( \">>> OnNetStatus got: \" );\n\tDebugChatDef( hRes );\n\n\tif( !SUCCEEDED( hRes ) )\n\t{\n\t\t//\tIf we are waiting for a server list, this error might indicate that we're not going to\n\t\t//\tget one, so bail out of waiting for it.\n\t\tbRequestServerListWait = false;\n\t\t//\tSame for logout.\n\t\tbRequestLogoutWait = false;\n\t}\n\n\tif( hRes == CHAT_S_CON_DISCONNECTED )\n\t{\n\t\tif( bRequestLogoutWait || !bConnected )\n\t\t{\n\t\t\t//\tOk. We are waiting to logout or already have.\n\t\t\tbRequestLogoutWait = false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//\tUh oh. We got disconnected unexpectedly.\n\t\t\tif( pOwner->bInGame )\n\t\t\t\t//\tSet flag for wolapi destruction if connection is lost during game.\n\t\t\t\tpOwner->bConnectionDown = true;\n\t\t\telse\n\t\t\t{\n\t\t\t\tif( !pOwner->bSelfDestruct )\n\t\t\t\t{\n\t\t\t\t\t//\tSet flag for wolapi destruction.\n\t\t\t\t\tWWMessageBox().Process( TXT_WOL_WOLAPIGONE );\n\t\t\t\t\tpOwner->bSelfDestruct = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnChannelList( HRESULT, Channel* pChannelListIn )\n{\n\tif( bIgnoreChannelLists )\t\t//\tResponse to channel lists has been temporarily turned off.\n\t{\n//\t\tdebugprint( \">>> IGNORED OnChannelList, filter = %i, WO's LastUpdateChannelCallLevel = %i \\n\", ChannelFilter, pOwner->LastUpdateChannelCallLevel );\n\t\treturn S_OK;\n\t}\n\n\t//\tSpecial case for modal GetLobbyChannels(). Because we want to be sure this OnChannelList is one that was caused\n\t//\tby a Request for gametype 0, and not one arriving from an earlier Request for games.\n\t//\tThis OnChannelList might not actually match the Request in GetLobbyChannels(), but as long as it's type 0 it'll do.\n\tif( bRequestChannelListForLobbiesWait )\n\t{\n\t\tif( pChannelListIn && pChannelListIn->type != 0 )\n\t\t{\n//\t\t\tdebugprint( \">>> IGNORED OnChannelList, bRequestChannelListForLobbiesWait if\\n\" );\n\t\t\treturn S_OK;\n\t\t}\n\t\t//\tNote: if no channels in list, can't tell what kind of Request call gave us this list.\n\t\t//\t(In our case assume it was the one asking for lobbies and allow to fail later naturally due to no lobbies available.)\n\t}\n\n\tDeleteChannelList();\n//\tdebugprint( \">>> OnChannelList, filter = %i, WO's LastUpdateChannelCallLevel = %i \\n\", ChannelFilter, pOwner->LastUpdateChannelCallLevel );\n\n\tint iLobbyCur = iChannelLobbyNumber( (unsigned char*)pOwner->szChannelNameCurrent );\n\n\tChannel* pChannelListTail = NULL;\n\n\t//\tCopy channel list to our own list.\n\twhile( pChannelListIn )\n\t{\n//\t\tdebugprint( \"OnChannelList got %s\\n\", pChannelListIn->name );\n\t\tswitch( ChannelFilter )\n\t\t{\n\t\tcase CHANNELFILTER_OFFICIAL:\n\t\t\tif( pChannelListIn->official != 1 || iChannelLobbyNumber( pChannelListIn->name ) != -1 )\n\t\t\t{\n//\t\t\t\tdebugprint( \"(OnChannelList filtered this one.)\\n\", pChannelListIn->name );\n\t\t\t\tpChannelListIn = pChannelListIn->next;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase CHANNELFILTER_UNOFFICIAL:\n\t\t\tif( pChannelListIn->official == 1 || iChannelLobbyNumber( pChannelListIn->name ) != -1 )\n\t\t\t{\n//\t\t\t\tdebugprint( \"(OnChannelList filtered this one.)\\n\", pChannelListIn->name );\n\t\t\t\tpChannelListIn = pChannelListIn->next;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase CHANNELFILTER_LOBBIES:\n\t\t{\n\t\t\tint iLobby = iChannelLobbyNumber( pChannelListIn->name );\n\t\t\tif( iLobby == -1 )\n\t\t\t{\n//\t\t\t\tdebugprint( \"(OnChannelList filtered this one.)\\n\", pChannelListIn->name );\n\t\t\t\tpChannelListIn = pChannelListIn->next;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase CHANNELFILTER_LOCALLOBBYGAMES:\n\t\t\t//\tWe are listing games of our type, and may have to filter out non-local-lobby games.\n\t\t\tif( !pOwner->bAllGamesShown )\n\t\t\t{\n\t\t\t\tint iGameSourceLobby = pChannelListIn->reserved & 0x00FFFFFF;\n\t\t\t\tif( iLobbyCur == -1 || iGameSourceLobby != iLobbyCur )\n\t\t\t\t{\n\t\t\t\t\tpChannelListIn = pChannelListIn->next;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tChannel* pChannelNew = new Channel;\n\t\t*pChannelNew = *pChannelListIn;\n\t\tpChannelNew->next = NULL;\t\t\t//\t(We don't want the value that was just copied!)\n\t\tif( !pChannelListTail )\n\t\t{\n\t\t\t//\tFirst channel in list.\n\t\t\tpChannelList = pChannelNew;\t\t//\tThis is the head of our channel list.\n\t\t\tpChannelListTail = pChannelNew;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpChannelListTail->next = pChannelNew;\n\t\t\tpChannelListTail = pChannelNew;\n\t\t}\n\t\tpChannelListIn = pChannelListIn->next;\n\t}\n\n//\tbRequestChannelListWait = false;\n\n\tif( bRequestChannelListForLobbiesWait )\n\t\tbRequestChannelListForLobbiesWait = false;\n\telse\n\t\tpOwner->OnChannelList();\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nvoid RAChatEventSink::DeleteChannelList()\n{\n\t//\tDelete all channels allocated on the heap.\n\t//\tpChannelList points to the head element of a linked list of channels, copied during OnChannelList().\n//\tdebugprint( \"DeleteChannelList\\n\" );\n\twhile( pChannelList )\n\t{\n\t\tChannel* pChannelHead = pChannelList;\n\t\tpChannelList = pChannelHead->next;\n\t\tdelete pChannelHead;\n\t}\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnUserList(HRESULT, Channel*, User* pUserListIn )\n{\n\t//\tMaintenance of users list is like that for channels list.\n//\tdebugprint( \">>> OnUserList\\n\" );\n\tDeleteUserList();\n\n\t//\tCopy channel list to our own list.\n\twhile( pUserListIn )\n\t{\n//\t\tdebugprint( \"OnUserList got %s\\n\", pUserListIn->name );\n\t\tUser* pUserNew = new User;\n\t\t*pUserNew = *pUserListIn;\n\t\tpUserNew->next = NULL;\t\t\t//\t(We don't want the value that was just copied!)\n\t\tif( !pUserTail )\n\t\t{\n\t\t\t//\tFirst User in list.\n\t\t\tpUserList = pUserNew;\t\t//\tThis is the head of our User list.\n\t\t\tpUserTail = pUserNew;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpUserTail->next = pUserNew;\n\t\t\tpUserTail = pUserNew;\n\t\t}\n\t\tpUserListIn = pUserListIn->next;\n\t}\n\n//\tbRequestUserListWait = false;\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nvoid RAChatEventSink::DeleteUserList()\n{\n\t//\tDelete all Users allocated on the heap.\n\t//\tpUserList points to the head element of a linked list of Users, copied during OnUserList().\n//\tdebugprint( \"DeleteUserList\\n\" );\n\twhile( pUserList )\n\t{\n\t\tUser* pUserHead = pUserList;\n\t\tpUserList = pUserHead->next;\n\t\tdelete pUserHead;\n\t}\n\tpUserTail = NULL;\n}\n\n\n//***********************************************************************************************\n// We got a list of updates to apply\n//\nSTDMETHODIMP RAChatEventSink::OnUpdateList( HRESULT hRes, Update* pUpdateList )\n{\n//\tdebugprint( \">>> OnUpdateList got: \" );\n\tDebugChatDef( hRes );\n\n\tif( !pUpdateList )\t\t//\tShouldn't happen.\n\t\treturn S_OK;\n\n\t//\tCount the updates.\n\tint iUpdates = 0;\n\tUpdate* pUpdate\t= pUpdateList;\n\n\twhile( pUpdate != NULL )\n\t{\n\t\tpUpdate = pUpdate->next;\n\t\t++iUpdates;\n\t}\n//\tdebugprint( \"%i updates\\n\", iUpdates );\n\n\tif( WWMessageBox().Process( TXT_WOL_PATCHQUESTION, TXT_YES, TXT_NO ) == 0 )\n\t{\n\t\t//\tGet the updates. (I ignore the concept of \"optional\" downloads here.)\n\t\tif( DownloadUpdates( pUpdateList, iUpdates ) )\n\t\t\tpOwner->hresPatchResults = PATCHDOWNLOADED;\n\t\telse\n\t\t\tpOwner->hresPatchResults = PATCHAVOIDED;\n\t}\n\telse\n\t\t//\tUser says don't do the download.\n\t\t//\tSet flag to tell WolapiObject what has happened.\n\t\tpOwner->hresPatchResults = PATCHAVOIDED;\n\n\treturn S_OK;\n}\n\nextern bool WOL_Download_Dialog( IDownload* pDownload, RADownloadEventSink* pDownloadSink, const char* szTitle );\n//***********************************************************************************************\nbool RAChatEventSink::DownloadUpdates( Update* pUpdateList, int iUpdates )\n{\n\t//\tFirst we create a Download and Download Sink interface object, like Chat and ChatSink.\n\tbool bReturn = true;\n\t//\tThis is all like WolapiObject::bSetupCOMStuff().\n//debugprint( \"Do all the COM crap.\\n\" );\n\tIDownload* pDownload;\n\tCoCreateInstance( CLSID_Download, NULL, CLSCTX_INPROC_SERVER, IID_IDownload, (void**)&pDownload );\n\t_ASSERTE( pDownload );\n\tRADownloadEventSink* pDownloadSink = new RADownloadEventSink();\n\tpDownloadSink->AddRef();\n\tIConnectionPoint*\t\t\tpConnectionPoint = NULL;\n\tIConnectionPointContainer*\tpContainer = NULL;\n\tHRESULT hRes = pDownload->QueryInterface( IID_IConnectionPointContainer, (void**)&pContainer );\n\t_ASSERTE(SUCCEEDED(hRes));\n\thRes = pContainer->FindConnectionPoint( IID_IDownloadEvent, &pConnectionPoint );\n\t_ASSERTE(SUCCEEDED(hRes));\n\tDWORD dwDownloadAdvise;\n\thRes = pConnectionPoint->Advise( (IDownloadEvent*)pDownloadSink, &dwDownloadAdvise );\n\t_ASSERTE(SUCCEEDED(hRes));\n\t//\tPresumably the above calls will succeed, because they did so when we did bSetupComStuff().\n\n\tpContainer->Release();\n\tpConnectionPoint->Release();\n\n\tUpdate* pUpdate = pUpdateList;\n\tint iUpdateCurrent = 0;\n\t//\tSave current directory.\n\tchar szCurDirSave[_MAX_PATH];\n\t::GetCurrentDirectory( _MAX_PATH, szCurDirSave );\n\twhile( pUpdate )\n\t{\n\t\t++iUpdateCurrent;\n\t\tchar szTitle[ 120 ];\n\t\tsprintf( szTitle, TXT_WOL_DOWNLOADING, iUpdateCurrent, iUpdates );\n\t\tchar fullpath[ _MAX_PATH ];\n\t\tsprintf( fullpath, \"%s\\\\%s\", pUpdate->patchpath, pUpdate->patchfile );\n\t\t//\tDownloading in WOLAPI is in a state of disarray somewhat.\n\t\t//\tMake sure the destination directory exists, and make it the current directory during the download.\n//debugprint( \"Switching to %s dir.\\n\", (char*)pUpdate->localpath );\n\t\tif( !::SetCurrentDirectory( (char*)pUpdate->localpath ) )\n\t\t{\n\t\t\t//\tCreate the destination directory.\n//\t\t\tdebugprint( \"Creating dir.\\n\" );\n\t\t\t::CreateDirectory( (char*)pUpdate->localpath, NULL );\n\t\t\t::SetCurrentDirectory( (char*)pUpdate->localpath );\n\t\t}\n\t\t//\tNote: Unknown what the reg key value is actually used for...\n//debugprint( \"Asking to download %s to %s. Server '%s', login '%s', password '%s'\\n\", fullpath, (char*)pUpdate->patchfile,\n//\t\t   (char*)pUpdate->server, (char*)pUpdate->login, (char*)pUpdate->password );\n\t\tpDownload->DownloadFile( (char*)pUpdate->server, (char*)pUpdate->login, (char*)pUpdate->password, fullpath, \n\t\t\t\t\t\t\t\t\t(char*)pUpdate->patchfile, Game_Registry_Key() );\n//\t\tdebugprint( \"Call WOL_Download_Dialog()\\n\" );\n\t\tif( !WOL_Download_Dialog( pDownload, pDownloadSink, szTitle ) )\n\t\t{\n\t\t\tbReturn = false;\n\t\t\tbreak;\n\t\t}\n\t\tpUpdate = pUpdate->next;\n\t}\n\t::SetCurrentDirectory( szCurDirSave );\n\n\t//\tUndo all the COM crap.\n//debugprint( \"Undo all the COM crap.\\n\" );\n\tpConnectionPoint = NULL;\n\tpContainer = NULL;\n\thRes = pDownload->QueryInterface( IID_IConnectionPointContainer, (void**)&pContainer );\n\t_ASSERTE(SUCCEEDED(hRes));\n\thRes = pContainer->FindConnectionPoint( IID_IDownloadEvent, &pConnectionPoint );\n\t_ASSERTE(SUCCEEDED(hRes));\n\tpConnectionPoint->Unadvise( dwDownloadAdvise );\n\n\tpContainer->Release();\n\tpConnectionPoint->Release();\n\t\n\tpDownload->Release();\n\tpDownloadSink->Release();\t//\tThis results in pDownloadSink deleting itself for us.\n\n\treturn bReturn;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnServerError( HRESULT hRes )\n{\n//\tdebugprint( \">>> OnServerError got: \" );\n\tDebugChatDef( hRes );\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnMessageOfTheDay(HRESULT, LPCSTR)\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nvoid RAChatEventSink::ActionEggSound( const char* szMessage )\n{\n\t//\tEaster egg related.\n\tif( strstr( szMessage, \"<<groans>>\" ) || strstr( szMessage, \"<<groaning>>\" ) || \n\t\tstrstr( szMessage, \"<<dies>>\" ) || strstr( szMessage, \"<<dying>>\" ) || strstr( szMessage, \"<<groan>>\" ) ||\n\t\tstrstr( szMessage, \"<<died>>\" ) )\n\t{\n\t\tint i = rand() % 30;\n\t\tif( i == 0 )\n\t\t\tSound_Effect( VOC_DOG_HURT );\n\t\telse if( i == 1 )\n\t\t\tSound_Effect( VOC_ANTDIE );\n\t\telse\n\t\t\tSound_Effect( (VocType)( VOC_SCREAM1 + rand() % 9 ) );\n\t}\n\telse if( strstr( szMessage, \"<<whines>>\" ) || strstr( szMessage, \"<<whining>>\" ) \n\t\t|| strstr( szMessage, \"<<bitching>>\" ) || strstr( szMessage, \"<<whine>>\" ) )\n\t\tSound_Effect( VOC_DOG_WHINE );\n\telse if( strstr( szMessage, \"<<shoots>>\" ) || strstr( szMessage, \"<<shooting>>\" ) || \n\t\tstrstr( szMessage, \"<<shoot>>\" ) || strstr( szMessage, \"<<shot>>\" ) )\n\t{\n\t\tswitch( rand() % 6 )\n\t\t{\n\t\tcase 0:\t\t\tSound_Effect( VOC_CANNON1 );\t\t\tbreak;\n\t\tcase 1:\t\t\tSound_Effect( VOC_CANNON2 );\t\t\tbreak;\n\t\tcase 2:\t\t\tSound_Effect( VOC_GUN_RIFLE );\t\t\tbreak;\n\t\tcase 3:\t\t\tSound_Effect( VOC_SILENCER );\t\t\tbreak;\n\t\tcase 4:\t\t\tSound_Effect( VOC_CANNON6 );\t\t\tbreak;\n\t\tcase 5:\t\t\tSound_Effect( VOC_CANNON8 );\t\t\tbreak;\n\t\t}\n\t}\n\telse if( strstr( szMessage, \"<<explodes>>\" ) || strstr( szMessage, \"<<exploding>>\" ) || \n\t\tstrstr( szMessage, \"<<explode>>\" ) || strstr( szMessage, \"<<exploded>>\" ) ||\n\t\tstrstr( szMessage, \"<<boom>>\" ) || strstr( szMessage, \"<<nukes>>\" ) )\n\t{\n\t\tswitch( rand() % 5 )\n\t\t{\n\t\tcase 0:\t\t\tSound_Effect( VOC_KABOOM1 );\t\t\tbreak;\n\t\tcase 1:\t\t\tSound_Effect( VOC_KABOOM12 );\t\t\tbreak;\n\t\tcase 2:\t\t\tSound_Effect( VOC_KABOOM15 );\t\t\tbreak;\n\t\tcase 3:\t\t\tSound_Effect( VOC_KABOOM30 );\t\t\tbreak;\n\t\tcase 4:\t\t\tSound_Effect( VOC_KABOOM25 );\t\t\tbreak;\n\t\t}\n\t}\n\telse if( strstr( szMessage, \"<<aye>>\" ) || strstr( szMessage, \"<<ok>>\" ) ||\n\t\tstrstr( szMessage, \"<<yes>>\" ) || strstr( szMessage, \"<<yeah>>\" ) )\n\t{\n\t\tswitch( rand() % 8 )\n\t\t{\n\t\tcase 0:\t\tSound_Effect( VOC_E_AH );\t\t\t\t\tbreak;\n\t\tcase 1:\t\tSound_Effect( VOC_E_YES );\t\t\t\t\tbreak;\n\t\tcase 2:\t\tSound_Effect( VOC_THIEF_YEA );\t\t\t\tbreak;\n\t\tcase 3:\t\tSound_Effect( VOC_SPY_YESSIR );\t\t\t\tbreak;\n\t\tcase 4:\t\tSound_Effect( VOC_SPY_INDEED );\t\t\t\tbreak;\n\t\tcase 5:\t\tSound_Effect( VOC_ENG_YES );\t\t\t\tbreak;\n\t\tcase 6:\t\tSound_Effect( VOC_MED_YESSIR );\t\t\t\tbreak;\n\t\tcase 7:\t\tSound_Effect( VOC_MED_AFFIRM );\t\t\t\tbreak;\n\t\t}\n\t}\n\telse if( strstr( szMessage, \"<<incredible>>\" ) || strstr( szMessage, \"<<adam>>\" ) || strstr( szMessage, \"<<Adam>>\" ))\n\t\tSound_Effect( VOC_E_OK );\n\telse if( strstr( szMessage, \"<<coming>>\" )|| strstr( szMessage, \"<<on my way>>\" ) || strstr( szMessage, \"<<moving out>>\" ) )\n\t{\n\t\tswitch( rand() % 5 )\n\t\t{\n\t\tcase 0:\t\tSound_Effect( VOC_SPY_ONWAY );\t\t\t\tbreak;\n\t\tcase 1:\t\tSound_Effect( VOC_ENG_MOVEOUT );\t\t\tbreak;\n\t\tcase 2:\t\tSound_Effect( VOC_SPY_KING );\t\t\t\tbreak;\n\t\tcase 3:\t\tSound_Effect( VOC_MED_MOVEOUT );\t\t\tbreak;\n\t\tcase 4:\t\tSound_Effect( VOC_THIEF_MOVEOUT );\t\t\tbreak;\n\t\t}\n\t}\n\telse if( strstr( szMessage, \"<<water>>\" ) )\n\t\tSound_Effect( VOC_SPLASH );\n\telse if( strstr( szMessage, \"<<charging>>\" ) || strstr( szMessage, \"<<powering>>\" ) )\n\t\tSound_Effect( VOC_TESLA_POWER_UP );\n\telse if( strstr( szMessage, \"<<zap>>\" ) || strstr( szMessage, \"<<zaps>>\" ) )\n\t\tSound_Effect( VOC_TESLA_ZAP );\n\telse if( strstr( szMessage, \"<<torpedo>>\" ) || strstr( szMessage, \"<<torpedoes>>\" ) )\n\t\tSound_Effect( VOC_TORPEDO );\n\telse if( strstr( szMessage, \"<<appears>>\" ) || strstr( szMessage, \"<<surfaces>>\" ) || strstr( szMessage, \"<<emerges>>\" ))\n\t\tSound_Effect( VOC_SUBSHOW );\n\telse if( strstr( szMessage, \"<<bark>>\" ) || strstr( szMessage, \"<<barks>>\" ) )\n\t\tSound_Effect( VOC_DOG_BARK );\n\telse if( strstr( szMessage, \"<<growl>>\" ) || strstr( szMessage, \"<<growls>>\" ) )\n\t\tSound_Effect( VOC_DOG_GROWL2 );\n\telse if( strstr( szMessage, \"<<chronoshift>>\" ) || strstr( szMessage, \"<<disappears>>\" ) )\n\t\tSound_Effect( VOC_CHRONO );\n\telse if( strstr( szMessage, \"<<crumble>>\" ) || strstr( szMessage, \"<<crumbles>>\" ) ||\n\t\tstrstr( szMessage, \"<<collapse>>\" ) || strstr( szMessage, \"<<collapses>>\" ) )\n\t\tSound_Effect( VOC_CRUMBLE );\n\telse if( strstr( szMessage, \"<<sell>>\" ) || strstr( szMessage, \"<<sells>>\" ) ||\n\t\tstrstr( szMessage, \"<<cash>>\" ) || strstr( szMessage, \"<<money>>\" ) )\n\t\tSound_Effect( VOC_CASHTURN );\n\telse if( strstr( szMessage, \"<<heal>>\" ) || strstr( szMessage, \"<<heals>>\" ) )\n\t\tSound_Effect( VOC_HEAL );\n\telse if( strstr( szMessage, \"<<missile>>\" ) )\n\t{\n\t\tswitch( rand() % 3 )\n\t\t{\n\t\tcase 0:\t\tSound_Effect( VOC_MISSILE_1 );\t\t\t\tbreak;\n\t\tcase 1:\t\tSound_Effect( VOC_MISSILE_2 );\t\t\t\tbreak;\n\t\tcase 2:\t\tSound_Effect( VOC_MISSILE_3 );\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnPrivateAction( HRESULT, User* pUserSender, LPCSTR szMessage )\n{\n\t//\tIgnore private messages sent to myself by myself.\n\tif( pUserSender->flags & CHAT_USER_MYSELF )\n\t\treturn S_OK;\n\n\tif( *szMessage )\n\t{\n\t\tchar* szPrint = new char[ strlen( (char*)pUserSender->name ) + strlen( szMessage ) + 116 ];\n\t\tsprintf( szPrint, \"%s %s %s\", TXT_WOL_PRIVATE, (char*)pUserSender->name, szMessage );\n\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_ACTION );\n\t\tdelete [] szPrint;\n\t\t//\tEaster egg related.\n\t\tif( pOwner->bEggSounds )\n\t\t\tActionEggSound( szMessage );\n\t}\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnPublicAction( HRESULT, Channel*, User* pUserSender, LPCSTR szMessage )\n{\n\tif( *szMessage )\n\t{\n\t\tchar* szPrint = new char[ strlen( (char*)pUserSender->name ) + strlen( szMessage ) + 110 ];\n\t\tsprintf( szPrint, \"%s %s\", (char*)pUserSender->name, szMessage );\n\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_ACTION );\n\t\tdelete [] szPrint;\n\t\t//\tEaster egg related.\n\t\tif( pOwner->bEggSounds )\n\t\t\tActionEggSound( szMessage );\n\t}\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnPrivateGameOptions( HRESULT, User* pUser, LPCSTR szRequest )\n{\n//\tdebugprint( \">>> OnPrivateGameOptions\\n\" );\n//\tDebugChatDef( hRes );\n\n\tchar szRequestCopy[ 600 ];\n\tstrcpy( szRequestCopy, szRequest );\n\n\tif( pOwner->pGSupDlg )\n\t{\n\t\tif( pOwner->pGSupDlg->bHost )\n\t\t\tpOwner->pGSupDlg->ProcessGuestRequest( pUser, szRequestCopy );\n\t\telse\n\t\t\tpOwner->pGSupDlg->ProcessInform( szRequestCopy );\t\t//\tMust be private message to guest from game host.\n\t}\n//\telse\n//\t\tdebugprint( \"OnPrivateGameOptions bizarreness.\\n\" );\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnPublicGameOptions( HRESULT, Channel*, User*, LPCSTR szInform )\n{\n//\tdebugprint( \">>> OnPublicGameOptions: %s\\n\", szInform );\n\n\tchar szInformCopy[ 600 ];\n\tstrcpy( szInformCopy, szInform );\n\n\tif( pOwner->pGSupDlg )\n\t{\n\t\tpOwner->pGSupDlg->ProcessInform( szInformCopy );\n\t}\n//\telse\n//\t\tdebugprint( \"OnPublicGameOptions bizarreness.\\n\" );\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnGameStart( HRESULT hRes, Channel*, User* pUserIn, int iGameID )\n{\n\t//\tNote: All players receive this, not just the host that requested it.\n\n//\tdebugprint( \">>> OnGameStart got: \" );\n\tDebugChatDef( hRes );\n\n//\tif( bRequestGameStartWait )\t\t//\tImplies user is the host that did RequestGameStart().\n//\t{\n\n\t\t//\tCreate the list of users that are actually involved in a game.\n\t\t//\tMost likely will always match pUserList, but there is a chance of someone leaving or joining\n\t\t//\tat the wrong moment, so from this point on, the pGameUserList is used.\n\n\t\t//\tNote: pUserIPList was added later, for pre-start pinging. It duplicates pGameUserList ip information,\n\t\t//\tstrictly speaking.\n\n\t\t//\tDelete any existing list.\n\t\twhile( pGameUserList )\n\t\t{\n\t\t\tUser* pGameUserHead = pGameUserList;\n\t\t\tpGameUserList = pGameUserList->next;\n\t\t\tdelete pGameUserHead;\n\t\t}\n\t\t//\tCopy incoming user list.\n\t\tUser* pGameUserListTail = NULL;\n\t\twhile( pUserIn )\n\t\t{\n//\t\t\tdebugprint( \"OnGameStart got %s\\n\", (char*)pUserIn->name );\n\t\t\tUser* pUserNew = new User;\n\t\t\t*pUserNew = *pUserIn;\n\t\t\tpUserNew->next = NULL;\t\t\t//\t(We don't want the value that was just copied!)\n\t\t\tif( !pGameUserListTail )\n\t\t\t{\n\t\t\t\t//\tFirst User in list.\n\t\t\t\tpGameUserList = pUserNew;\t\t//\tThis is the head of our User list.\n\t\t\t\tpGameUserListTail = pUserNew;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tpGameUserListTail->next = pUserNew;\n\t\t\t\tpGameUserListTail = pUserNew;\n\t\t\t}\n\t\t\tpUserIn = pUserIn->next;\n\t\t}\n\n\t\tbRequestGameStartWait = false;\n//\t}\n\n//\tdebugprint( \"iGameID is %i\\n\", iGameID );\n\tthis->iGameID = iGameID;\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nunsigned long RAChatEventSink::GetPlayerGameIP( const char* szPlayerName ) const\n{\n\t//\tReturns ipaddr value of player if found in pGameUserList, else 0.\n\tUser* pUser = pGameUserList;\n\twhile( pUser )\n\t{\n\t\tif( _stricmp( (char*)pUser->name, szPlayerName ) == 0 )\n\t\t\treturn pUser->ipaddr;\n\t\tpUser = pUser->next;\n\t}\n\treturn 0;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnUserKick( HRESULT hRes, Channel*, User* pUserKicked,  User* pUserKicker )\n{\n//\tdebugprint( \">>> OnUserKick got: \" );\n\tDebugChatDef( hRes );\n\n\tif( hRes == S_OK )\n\t{\n\t\t//\tSomeone was kicked.\n\t\t//\tFake a call to OnChannelLeave(), as the processing is identical.\n\t\tOnChannelLeave( S_OK, NULL, pUserKicked );\n\t\tif( pUserKicked->flags & CHAT_USER_MYSELF )\n\t\t{\n\t\t\t//\tTrigger a channel exit later on, when we have left this callback.\n\t\t\tbGotKickedTrigger = true;\n\t\t\tchar* szPrint = new char[ strlen( (char*)pUserKicker->name ) + strlen( TXT_WOL_USERKICKEDYOU ) + 5 ];\n\t\t\tsprintf( szPrint, TXT_WOL_USERKICKEDYOU, (char*)pUserKicker->name );\n\t\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_KICKORBAN );\n\t\t\tdelete [] szPrint;\n\t\t\t//\tEnsure that the bGotKickedTrigger is acted upon immediately...\n\t\t\tpOwner->dwTimeNextWolapiPump = ::timeGetTime();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tchar* szPrint = new char[ strlen( (char*)pUserKicker->name ) + strlen( (char*)pUserKicked->name ) + \n\t\t\t\t\t\t\t\t\t\tstrlen( TXT_WOL_USERKICKEDUSER ) + 5 ];\n\t\t\tsprintf( szPrint, TXT_WOL_USERKICKEDUSER, (char*)pUserKicker->name, (char*)pUserKicked->name );\n\t\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_KICKORBAN );\n\t\t\tdelete [] szPrint;\n\t\t}\n\t\tswitch( rand() % 4 )\n\t\t{\n\t\tcase 0:\n\t\t\tSound_Effect( VOC_TANYA_CHEW );\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tSound_Effect( VOC_TANYA_LAUGH );\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tSound_Effect( VOC_TANYA_CHING );\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tSound_Effect( VOC_TANYA_KISS );\n\t\t\tbreak;\n\t\t}\n\t}\n\telse\n\t{\n\t\t//\tYou tried to kick someone, but the user wasn't found.\n\t\t//\tIgnore.\n//\t\tdebugprint( \"OnUserKick non S_OK value\\n\" );\n\t}\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnUserIP( HRESULT hRes, User* pUser )\n{\n\t//\tA list of users is kept, separate from other user lists, to preserve the ipaddr's we've found through this\n\t//\tcallback. OnUserList (for some dumb reason) doesn't hold valid ipaddr's, so we have to go through\n\t//\tall this rigamarole...\n\t//\t(List is cleared when entering game channel. Users are added initially and on joins, not removed on leaves.)\n//\tdebugprint( \">>> OnUserIP got: \" );\n\tDebugChatDef( hRes );\n\n\tif( SUCCEEDED( hRes ) )\n\t{\n\t\t//\tLook for user in our current users list.\n\t\tUser* pUserSearch = pUserIPList;\n\t\twhile( pUserSearch )\n\t\t{\n\t\t\tif( _stricmp( (char*)pUserSearch->name, (char*)pUser->name ) == 0 )\n\t\t\t{\n\t\t\t\t//\tFound matching user. Replace it's ipaddr value, in case it changed.(?)\n\t\t\t\tpUserSearch->ipaddr = pUser->ipaddr;\n\t\t\t\treturn S_OK;\n\t\t\t}\n\t\t\tpUserSearch = pUserSearch->next;\n\t\t}\n\t\t//\tUser not found in current list. Add.\n\t\tUser* pUserNew = new User;\n\t\t*pUserNew = *pUser;\n\t\tpUserNew->next = NULL;\t\t\t//\t(We don't want the value that was just copied!)\n\t\tif( !pUserIPListTail )\n\t\t{\n\t\t\t//\tFirst user in list.\n\t\t\tpUserIPList = pUserNew;\t\t//\tThis is the head of our list.\n\t\t\tpUserIPListTail = pUserNew;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpUserIPListTail->next = pUserNew;\n\t\t\tpUserIPListTail = pUserNew;\n\t\t}\n\t}\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nvoid RAChatEventSink::DeleteUserIPList()\n{\n\t//\tSame as DeleteUserList but for pUserIPList.\n//\tdebugprint( \"DeleteUserIPList\\n\" );\n\twhile( pUserIPList )\n\t{\n\t\tUser* pUserHead = pUserIPList;\n\t\tpUserIPList = pUserHead->next;\n\t\tdelete pUserHead;\n\t}\n\tpUserIPListTail = NULL;\n}\n\n//***********************************************************************************************\nunsigned long RAChatEventSink::GetUserIP( const char* szName ) const\n{\n\t//\tLooks in pUserIPList for the ipaddr of user with name szName.\n\t//\tThis is used only while in game channels.\n\t//\tThis is for step 2 in acquiring fellow player ping times. To get the IP addresses into pUserIPList\n\t//\twe had to go through request/callbacks. Now pings are requested on these addresses, and the results\n\t//\ttallied in NetUtilSink for our retrieval later.\n\t//\tReturns 0 if not found.\n\n\t//\tFind szName in list.\n\tUser* pUser = pUserIPList;\n\twhile( pUser )\n\t{\n\t\tif( _stricmp( (char*)pUser->name, szName ) == 0 )\n\t\t\treturn pUser->ipaddr;\n\t\tpUser = pUser->next;\n\t}\n\treturn 0;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnServerError(HRESULT , LPCSTR )\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnServerBannedYou(HRESULT , time_t )\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnUserFlags( HRESULT hRes, LPCSTR name, unsigned int flags, unsigned int )\n{\n//\tdebugprint( \">>> OnUserFlags got: \" );\n\tDebugChatDef( hRes );\n\n\tif( pOwner->CurrentLevel == WOL_LEVEL_INGAMECHANNEL )\n\t{\n\t\tif( pOwner->pGSupDlg && \n\t\t\t( pOwner->pGSupDlg->bHostSayGo || pOwner->pGSupDlg->bHostWaitingForGoTrigger || \n\t\t\t\tpOwner->pGSupDlg->bExitForGameTrigger || iGameID ) )\n\t\t{\n\t\t\t//\tA game has this moment entered the \"must start\" phase. We must ignore the fact that others are leaving the channel.\n//\t\t\tdebugprint( \"Ignoring OnUserFlags because game is starting.\\n\" );\t\t//\t(Shouldn't ever happen.)\n\t\t\treturn S_OK;\n\t\t}\n\t}\n\n\t//\tFind user in our current users list.\n\tUser* pUserPrior = NULL;\n\tUser* pUserSearch = pUserList;\n\twhile( pUserSearch )\n\t{\n\t\tif( _stricmp( (char*)pUserSearch->name, name ) == 0 )\n\t\t{\n\t\t\t//\tSet user's flags to new value.\n\t\t\tpUserSearch->flags = flags;\n\t\t\t\n\t\t\t//\tRemove user from userlist and reinsert appropriately sorted.\n\t\t\tif( !pUserPrior )\n\t\t\t{\n\t\t\t\t//\tUser was head of list.\n\t\t\t\tpUserList = pUserSearch->next;\n\t\t\t\tif( pUserSearch == pUserTail )\n\t\t\t\t\t//\tUser was also tail of list.\n\t\t\t\t\tpUserTail = NULL;\n\t\t\t\telse\n\t\t\t\t\tpUserSearch->next = NULL;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//\tUser was not head of list.\n\t\t\t\tpUserPrior->next = pUserSearch->next;\n\t\t\t\tif( pUserSearch == pUserTail )\n\t\t\t\t\t//\tUser was tail of list.\n\t\t\t\t\tpUserTail = pUserPrior;\n\t\t\t\telse\n\t\t\t\t\tpUserSearch->next = NULL;\n\t\t\t}\n\t\t\tInsertUserSorted( pUserSearch );\n\n\t\t\t//\tUpdate shown list.\n\t\t\tpOwner->ListChannelUsers();\n\t\t\tbreak;\n\t\t}\n\t\tpUserPrior = pUserSearch;\n\t\tpUserSearch = pUserSearch->next;\n\t}\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnChannelBan( HRESULT , LPCSTR name, int banned )\n{\n\tif( banned && strcmp( name, \"*\" ) != 0 )\n\t{\n\t\tchar* szPrint = new char[ strlen( name ) + strlen( TXT_WOL_USERWASBANNED ) + 5 ];\n\t\tsprintf( szPrint, TXT_WOL_USERWASBANNED, name );\n\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_KICKORBAN );\n\t\tdelete [] szPrint;\n\t}\n\t\n\treturn S_OK;\n}\n\n\n//***********************************************************************************************\n//***********************************************************************************************\nRADownloadEventSink::RADownloadEventSink() :\n\tbFlagEnd( false ),\n\tbFlagError( false ),\n\tbFlagProgressUpdate( false ),\n\tbFlagStatusUpdate( false ),\n\tbFlagQueryResume( false )\n{\n\tm_cRef=0;\t\t// Ref counter\n}\n\n//\t\t\tInterface IUnknown Methods\n//***********************************************************************************************\n// QueryInterface\n//\nHRESULT __stdcall\nRADownloadEventSink::QueryInterface(const IID& iid, void** ppv)\n{\n\tif ((iid == IID_IUnknown) ||(iid == IID_IDownloadEvent))\n\t{\n\t\t*ppv = (IDownloadEvent*)this;\t\t//\tRemoved static_cast<> ajw\n\t}\n\telse\n\t{\n\t\t*ppv = NULL;\n\t\treturn E_NOINTERFACE;\n\t}\n\t((IUnknown*)(*ppv))->AddRef();\t\t//\tRemoved reinterpret_cast<> ajw\n\treturn S_OK ;\n}\n\n//***********************************************************************************************\n// AddRef\n//\nULONG __stdcall\nRADownloadEventSink::AddRef()\n{\n\treturn InterlockedIncrement(&m_cRef) ;\n}\n\n//***********************************************************************************************\n// Release\n//\nULONG __stdcall\nRADownloadEventSink::Release()\n{\n\tif (InterlockedDecrement(&m_cRef) == 0)\n\t{\n\t\tdelete this ;\n\t\treturn 0 ;\n\t}\n\treturn m_cRef;\n}\n\n//***********************************************************************************************\n//***********************************************************************************************\nSTDMETHODIMP RADownloadEventSink::OnEnd(void)\n{\n//\tdebugprint( \">>> OnEnd\\n\" );\n\tbFlagEnd = true;\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RADownloadEventSink::OnError( int /*iCode*/ )\n{\n//\tdebugprint( \">>> OnError got: %i\\n\", iCode );\n//#define DOWNLOADEVENT_NOSUCHSERVER\t\t1\n//#define DOWNLOADEVENT_COULDNOTCONNECT\t\t2\n//#define DOWNLOADEVENT_LOGINFAILED\t\t\t3\n//#define DOWNLOADEVENT_NOSUCHFILE\t\t\t4\n//#define DOWNLOADEVENT_LOCALFILEOPENFAILED\t5\n//#define DOWNLOADEVENT_TCPERROR\t\t\t6\n//#define DOWNLOADEVENT_DISCONNECTERROR\t\t7\n\n\tbFlagError = true;\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RADownloadEventSink::OnProgressUpdate( int bytesread, int totalsize, int timetaken, int timeleft )\n{\n//\tdebugprint( \">>> OnProgressUpdate\\n\" );\n\tbFlagProgressUpdate = true;\n\n\tiBytesRead = bytesread;\n\tiTotalSize = totalsize;\n\tiTimeTaken = timetaken;\n\tiTimeLeft = timeleft;\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RADownloadEventSink::OnStatusUpdate( int status )\n{\n//\tdebugprint( \">>> OnStatusUpdate, status = %i\\n\", status );\n\tbFlagStatusUpdate = true;\n\n\tiStatus = status;\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\n// Just tell the FTP module to go ahead and resume\n//\nSTDMETHODIMP RADownloadEventSink::OnQueryResume()\n{\n//\tdebugprint( \">>> OnQueryResume\\n\" );\n\tbFlagQueryResume = true;\n\n\tbResumed = true;\n\n\treturn DOWNLOADEVENT_RESUME;\n}\n\n\n//***********************************************************************************************\n//***********************************************************************************************\nRANetUtilEventSink::RANetUtilEventSink( WolapiObject* pOwnerIn ) : m_cRef( 0 ), \t//\tinit the reference count\n\tpOwner( pOwnerIn ),\n\tpLadderList( NULL ),\n\tpLadderTail( NULL ),\n\tpLadderListAM( NULL ),\n\tpLadderTailAM( NULL )\n{\n//\tdebugprint( \"RANetUtilEventSink constructor\\n\" );\n}\n\n//***********************************************************************************************\nRANetUtilEventSink::~RANetUtilEventSink()\n{\n//\tdebugprint( \"RANetUtilEventSink destructor\\n\" );\n\tDeleteLadderList();\n}\n\n//\t\t\tInterface IUnknown Methods\n//***********************************************************************************************\n// QueryInterface\n//\nHRESULT __stdcall\nRANetUtilEventSink::QueryInterface(const IID& iid, void** ppv)\n{\n//\tdebugprint( \"RANetUtilEventSink::QueryInterface\\n\" );\n\tif ((iid == IID_IUnknown) ||(iid == IID_INetUtilEvent))\n\t{\n\t\t*ppv = (INetUtilEvent*)this;\t\t//\tRemoved static_cast<> ajw\n\t}\n\telse\n\t{\n\t\t*ppv = NULL;\n\t\treturn E_NOINTERFACE;\n\t}\n\t((IUnknown*)(*ppv))->AddRef();\t\t//\tRemoved reinterpret_cast<> ajw\n\treturn S_OK ;\n}\n\n//***********************************************************************************************\n// AddRef\n//\nULONG __stdcall\nRANetUtilEventSink::AddRef()\n{\n//\tdebugprint( \"RANetUtilEventSink::AddRef\\n\" );\n\treturn InterlockedIncrement(&m_cRef) ;\n}\n\n//***********************************************************************************************\n// Release\n//\nULONG __stdcall\nRANetUtilEventSink::Release()\n{\n//\tdebugprint( \"RANetUtilEventSink::Release\\n\" );\n\tif (InterlockedDecrement(&m_cRef) == 0)\n\t{\n\t\tdelete this ;\n\t\treturn 0 ;\n\t}\n\treturn m_cRef;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RANetUtilEventSink::OnGameresSent( HRESULT hRes )\n{\n//\tdebugprint( \">>> OnGameresSent got: \" );\n\tDebugChatDef( hRes );\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RANetUtilEventSink::OnLadderList( HRESULT hRes, Ladder* pLadderListIn, int /*totalCount*/, long /*timeStamp*/, int /*keyRung*/ )\n{\n\t//\tMaintenance of ladders list is like that for channels list above.\n\t//\tDeleteLadderList();\t\t-> This is done once, before a set of RequestLadderList() calls are made.\n//\tdebugprint( \">>> OnLadderList got: \" );\n\tDebugChatDef( hRes );\n\n\tif( SUCCEEDED( hRes ) )\n\t{\n//\t\tdebugprint( \"(SUCCEEDED)\\n\" );\n\t\t//\tCopy ladder list to our own list.\n\t\twhile( pLadderListIn )\n\t\t{\n//\t\t\tdebugprint( \"OnLadderList got %s, rung %u\\n\", pLadderListIn->login_name, pLadderListIn->rung );\n\t\t\tif( *pLadderListIn->login_name != 0 && pLadderListIn->rung != -1 )\n\t\t\t{\n\t\t\t\tLadder* pLadderNew = new Ladder;\n\t\t\t\t*pLadderNew = *pLadderListIn;\n\t\t\t\tpLadderNew->next = NULL;\t\t\t//\t(We don't want the value that was just copied!)\n\t\t\t\tif( pLadderNew->sku == LADDER_CODE_RA )\n\t\t\t\t{\n\t\t\t\t\tif( !pLadderTail )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tFirst Ladder in list.\n\t\t\t\t\t\tpLadderList = pLadderNew;\t\t//\tThis is the head of our Ladder list.\n\t\t\t\t\t\tpLadderTail = pLadderNew;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tpLadderTail->next = pLadderNew;\n\t\t\t\t\t\tpLadderTail = pLadderNew;\n\t\t\t\t\t}\n\t\t\t\t\tif( _stricmp( (char*)pLadderNew->login_name, pOwner->szMyName ) == 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tSet up local player's win/loss string.\n\t\t\t\t\t\tsprintf( pOwner->szMyRecord, TXT_WOL_PERSONALWINLOSSRECORD, pOwner->szMyName, \n\t\t\t\t\t\t\t\t\tpLadderNew->rung, pLadderNew->wins, pLadderNew->losses, pLadderNew->points );\n\t\t\t\t\t\tpOwner->bMyRecordUpdated = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\t\t//\tsku must be LADDER_CODE_AM\n\t\t\t\t{\n\t\t\t\t\tif( !pLadderTailAM )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tFirst Ladder in list.\n\t\t\t\t\t\tpLadderListAM = pLadderNew;\t\t//\tThis is the head of our Ladder list.\n\t\t\t\t\t\tpLadderTailAM = pLadderNew;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tpLadderTailAM->next = pLadderNew;\n\t\t\t\t\t\tpLadderTailAM = pLadderNew;\n\t\t\t\t\t}\n\t\t\t\t\tif( _stricmp( (char*)pLadderNew->login_name, pOwner->szMyName ) == 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tSet up local player's win/loss string for Aftermath.\n\t\t\t\t\t\tsprintf( pOwner->szMyRecordAM, TXT_WOL_PERSONALWINLOSSRECORDAM, pOwner->szMyName, \n\t\t\t\t\t\t\t\t\tpLadderNew->rung, pLadderNew->wins, pLadderNew->losses, pLadderNew->points );\n\t\t\t\t\t\tpOwner->bMyRecordUpdated = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tpLadderListIn = pLadderListIn->next;\n\t\t}\n\t\t//\tUpdate shown list.\n\t\tpOwner->ListChannelUsers();\n\t}\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RANetUtilEventSink::OnPing( HRESULT hRes, int time, unsigned long ip, int /*handle*/ )\n{\n\tif( pOwner->bDoingDisconnectPinging )\n\t{\n//\t\tdebugprint( \">>> OnPing got : ip %i, time %i, \", ip, time );\n\t\tDebugChatDef( hRes );\n\n\t\tif( ip == pOwner->TournamentOpponentIP )\n\t\t{\n\t\t\t//\tThis is the result of the opponent ping.\n\t\t\tif( time != -1 )\n\t\t\t\tpOwner->DisconnectPingResult_Opponent[ pOwner->iDisconnectPingCurrent ] = PING_GOOD;\n\t\t\telse\n\t\t\t\tpOwner->DisconnectPingResult_Opponent[ pOwner->iDisconnectPingCurrent ] = PING_BAD;\n//\t\t\tdebugprint( \"Set ping #%i for Opponent\\n\", pOwner->iDisconnectPingCurrent );\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//\tThis is the result of the game server ping.\n\t\t\tif( time != -1 )\n\t\t\t\tpOwner->DisconnectPingResult_Server[ pOwner->iDisconnectPingCurrent ] = PING_GOOD;\n\t\t\telse\n\t\t\t\tpOwner->DisconnectPingResult_Server[ pOwner->iDisconnectPingCurrent ] = PING_BAD;\n//\t\t\tdebugprint( \"Set ping #%i for Server\\n\", pOwner->iDisconnectPingCurrent );\n\t\t}\n\t}\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nvoid RANetUtilEventSink::DeleteLadderList()\n{\n//\tdebugprint( \"DeleteLadderList()\\n\" );\n\t//\tDelete all Ladders allocated on the heap.\n\twhile( pLadderList )\n\t{\n\t\tLadder* pLadderHead = pLadderList;\n\t\tpLadderList = pLadderHead->next;\n\t\tdelete pLadderHead;\n\t}\n\tpLadderTail = NULL;\n}\n\n//***********************************************************************************************\nunsigned int RANetUtilEventSink::GetUserRank( const char* szName, bool bRankRA )\n{\n\t//\tSearches for szName in ladder list, returns player rank if found, else 0.\n\t//\tSlow linear search.\n\t//\tIf bRankRA, returns RA rank, else returns AM rank.\n//\tdebugprint( \"GetUserRank: Asked for %s, \", szName );\n\tLadder* pLad;\n\tif( bRankRA )\n\t\tpLad = pLadderList;\n\telse\n\t\tpLad = pLadderListAM;\n\n\twhile( pLad )\n\t{\n//\t\tdebugprint( \"  comparing %s\\n\", (char*)pLad->login_name );\n\t\tif( _stricmp( (char*)pLad->login_name, szName ) == 0 )\n\t\t{\n//\t\t\tdebugprint( \"found rung value %u\\n\", pLad->rung );\n\t\t\treturn pLad->rung;\n\t\t}\n\t\tpLad = pLad->next;\n\t}\n//\tdebugprint( \"couldn't find in my ladder list.\\n\", szName );\n\n\treturn 0;\n}\n\n//***********************************************************************************************\n//***********************************************************************************************\nvoid ChatDefAsText( char* szDesc, HRESULT hRes )\n{\n\t//\tSets szDesc to the text meaning of hRes.\n\t//\tMake sure szDesc is as long as the longest of the below.\n\tswitch( hRes )\n\t{\n\tcase CHAT_E_NICKINUSE       :\n\t\tsprintf( szDesc, \"Your nick is still logged into chat\" );\n\t\tbreak;\n\tcase CHAT_E_BADPASS         :\n\t\tsprintf( szDesc, \"Your password is incorrect during login\" );\n\t\tbreak;\n\tcase CHAT_E_NONESUCH\t\t   :\n\t\tsprintf( szDesc, \"Reference made to non-existant user or channel\" );\n\t\tbreak;\n\tcase CHAT_E_CON_NETDOWN        :\n\t\tsprintf( szDesc, \"The network layer is down or cannot be initialized for some reason\" );\n\t\tbreak;\n\tcase CHAT_E_CON_LOOKUP_FAILED  :\n\t\tsprintf( szDesc, \"Name lookup (e.g DNS) failed for some reason\" );\n\t\tbreak;\n\tcase CHAT_E_CON_ERROR          :\n\t\tsprintf( szDesc, \"Some fatal error occured with the net connection\" );\n\t\tbreak;\n\tcase CHAT_E_TIMEOUT            :\n\t\tsprintf( szDesc, \"General request timeout for a request\" );\n\t\tbreak;\n\tcase CHAT_E_MUSTPATCH        :\n\t\tsprintf( szDesc, \"Must patch before continuing\" );\n\t\tbreak;\n\tcase CHAT_E_STATUSERROR\t\t:\n\t\tsprintf( szDesc, \"Miscellaneous internal status error\" );\n\t\tbreak;\n\tcase CHAT_E_UNKNOWNRESPONSE\t:\n\t\tsprintf( szDesc, \"Server has returned something we don't recognise\" );\n\t\tbreak;\n\tcase CHAT_E_CHANNELFULL\t\t:\n\t\tsprintf( szDesc, \"Tried to join a channel that has enough players already\" );\n\t\tbreak;\n\tcase CHAT_E_CHANNELEXISTS\t:\n\t\tsprintf( szDesc, \"Tried to create a channel that already exists\" );\n\t\tbreak;\n\tcase CHAT_E_CHANNELDOESNOTEXIST\t\t:\n\t\tsprintf( szDesc, \"Tried to join a channel that does not exist\" );\n\t\tbreak;\n\tcase CHAT_E_BADCHANNELPASSWORD\t\t:\n\t\tsprintf( szDesc, \"Tried to join a channel with the wrong password\" );\n\t\tbreak;\n\tcase CHAT_E_BANNED            :\n\t\tsprintf( szDesc, \"You've been banned from the server / channel\" );\n\t\tbreak;\n\tcase CHAT_E_NOT_OPER           :\n\t\tsprintf( szDesc, \"You tried to do something that required operator status\" );\n\t\tbreak;\n\n\tcase CHAT_S_CON_CONNECTING     :\n\t\tsprintf( szDesc, \"A network connection is underway\" );\n\t\tbreak;\n\tcase CHAT_S_CON_CONNECTED      :\n\t\tsprintf( szDesc, \"A network connection is complete\" );\n\t\tbreak;\n\tcase CHAT_S_CON_DISCONNECTING  :\n\t\tsprintf( szDesc, \"A network connection is going down\" );\n\t\tbreak;\n\tcase CHAT_S_CON_DISCONNECTED   :\n\t\tsprintf( szDesc, \"A network connection is closed\" );\n\t\tbreak;\n\tcase CHAT_S_FIND_NOTHERE   :\n\t\tsprintf( szDesc, \"Find - Nick not in system\" );\n\t\tbreak;\n\tcase CHAT_S_FIND_NOCHAN   :\n\t\tsprintf( szDesc, \"Find - Not in any channels\" );\n\t\tbreak;\n\tcase CHAT_S_FIND_OFF   :\n\t\tsprintf( szDesc, \"Find - user has find turned off\" );\n\t\tbreak;\n\tcase CHAT_S_PAGE_NOTHERE   :\n\t\tsprintf( szDesc, \"Page - Nick not in system\" );\n\t\tbreak;\n\tcase CHAT_S_PAGE_OFF   :\n\t\tsprintf( szDesc, \"Page - user has page turned off\" );\n\t\tbreak;\n\tcase CHAT_E_NOTCONNECTED    :\n\t\tsprintf( szDesc, \"You are not connected to the chat server\" );\n\t\tbreak;\n\tcase CHAT_E_NOCHANNEL       :\n\t\tsprintf( szDesc, \"You are not in a channel\" );\n\t\tbreak;\n\tcase CHAT_E_NOTIMPLEMENTED  :\n\t\tsprintf( szDesc, \"Feature is not implemented\" );\n\t\tbreak;\n\tcase CHAT_E_PENDINGREQUEST  :\n\t\tsprintf( szDesc, \"The request was made while while a conflicting request was still pending\" );\n\t\tbreak;\n\tcase CHAT_E_PARAMERROR\t   :\n\t\tsprintf( szDesc, \"Invalid parameter passed - usually a NULL pointer\" );\n\t\tbreak;\n\tcase CHAT_E_LEAVECHANNEL\t\t:\n\t\tsprintf( szDesc, \"Tried to create or join a channel before leaving the previous one\" );\n\t\tbreak;\n\tcase CHAT_E_JOINCHANNEL\t\t:\n\t\tsprintf( szDesc, \"Tried to send something to a channel when not a member of any channel\" );\n\t\tbreak;\n\tcase CHAT_E_UNKNOWNCHANNEL\t:\n\t\tsprintf( szDesc, \"Tried to join a non-existant channel\" );\n\t\tbreak;\n\tcase S_OK:\n\t\tsprintf( szDesc, \"S_OK\" );\n\t\tbreak;\n\tcase E_FAIL:\n\t\tsprintf( szDesc, \"E_FAIL\" );\n\t\tbreak;\n\tdefault:\n\t\tsprintf( szDesc, \"ERROR - Value not recognized!\" );\n\t\tbreak;\n\t}\n\t//\tAppend NetUtil errors.\n\tswitch( hRes )\n\t{\n\tcase NETUTIL_E_ERROR:\n\t\tstrcat( szDesc, \"  NetUtil: NETUTIL_E_ERROR\" );\n\t\tbreak;\n\tcase NETUTIL_E_BUSY:\n\t\tstrcat( szDesc, \"  NetUtil: NETUTIL_E_BUSY\"  );\n\t\tbreak;\n\tcase NETUTIL_S_FINISHED:\n\t\tstrcat( szDesc, \"  NetUtil: NETUTIL_S_FINISHED\" );\n\t\tbreak;\n\t}\n}\n\n//***********************************************************************************************\nvoid DebugChatDef( HRESULT hRes )\n{\n\tchar szText[200];\n\tChatDefAsText( szText, hRes );\n//\tdebugprint( \"%s\\n\", szText );\n}\n\n//***********************************************************************************************\nint iChannelLobbyNumber( const unsigned char* szChannelName )\n{\n\t//\tReturns lobby number of channel, or -1 for \"channel is not a lobby\".\n\tif( strncmp( (char*)szChannelName, LOB_PREFIX, strlen( LOB_PREFIX ) ) == 0 )\n\t{\n\t\tchar szNum[10];\n\t\tstrcpy( szNum, (char*)szChannelName + strlen( LOB_PREFIX ) );\n//\t\tdebugprint( \" ^ iChannelLobbyNumber returning atoi of %s\\n\", szNum );\n\t\treturn atoi( szNum );\n\t}\n\telse\n\t\treturn -1;\n}\n\n//***********************************************************************************************\nvoid InterpretLobbyNumber( char* szLobbyNameToSet, int iLobby )\n{\n\t//\tHard-coded translation of lobby number to apparent lobby name.\n\tswitch( iLobby )\n\t{\n\tcase 0:\n\t\tstrcpy( szLobbyNameToSet, \"Combat Alley\" );\n\t\tbreak;\n\tcase 1:\n\t\tstrcpy( szLobbyNameToSet, \"No Man's Land\" );\n\t\tbreak;\n\tcase 2:\n\t\tstrcpy( szLobbyNameToSet, \"Hell's Pass\" );\n\t\tbreak;\n\tcase 3:\n\t\tstrcpy( szLobbyNameToSet, \"Lost Vegas\" );\n\t\tbreak;\n\tcase 4:\n\t\tstrcpy( szLobbyNameToSet, \"Death Valley\" );\n\t\tbreak;\n\tcase 5:\n\t\tstrcpy( szLobbyNameToSet, \"The Wastelands\" );\n\t\tbreak;\n\tcase 6:\n\t\tstrcpy( szLobbyNameToSet, \"Isle of Fury\" );\n\t\tbreak;\n\tcase 7:\n\t\tstrcpy( szLobbyNameToSet, \"Armourgarden\" );\n\t\tbreak;\n\tcase 8:\n\t\tstrcpy( szLobbyNameToSet, \"The Hive\" );\n\t\tbreak;\n\tcase 9:\n\t\tstrcpy( szLobbyNameToSet, \"North by Northwest\" );\n\t\tbreak;\n\tcase 10:\n\t\tstrcpy( szLobbyNameToSet, \"Decatur High\" );\n\t\tbreak;\n\tcase 11:\n\t\tstrcpy( szLobbyNameToSet, \"Damnation Alley\" );\n\t\tbreak;\n\tdefault:\n\t\tsprintf( szLobbyNameToSet, \"%ith Division\", iLobby );\n\t\tbreak;\n\t}\n}\n\n#endif\n"
  },
  {
    "path": "CODE/RAWOLAPI.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifdef WOLAPI_INTEGRATION\n\n#ifndef WIN32\n#error WOLAPI_INTEGRATION can't be specified for non WIN32 version!\n#endif\n\n//\trawolapi.h - WOLAPI sinks declarations.\n//\tajw 07/10/98\n\n//\tBased somewhat on Neal's Borlandized version, \"chatapi.h\".\n\n#ifndef RAWOLAPI_H\n#define RAWOLAPI_H\n\n#include \"function.h\"\n\n//#include \"cominit.h\"\n#include <stdio.h>\n\n//\tFrom OBJBASE.H\n#define interface struct\n\n//\tFrom RPCNDR.H\n#define DECLSPEC_UUID(x)\n\n#include <commctrl.h>\n\n//namespace WOL\t\t//\tnamespace is workaround due to the use of \"Server\" as a global in Red Alert.\n//\tajw - Can't use namespaces in Watcom 10.5 it seems...\n//{\n\t#include \"wolapi\\wolapi.h\"\n\t#define IID_DEFINED\n\t//#include \"wlib/wdebug.h\"\n\t#include \"wolapi\\chatdefs.h\"\n\t#include \"wolapi\\downloaddefs.h\"\n\t#include \"wolapi\\ftpdefs.h\"\n//};\n//using namespace WOL;\n#include <winerror.h>\n//#include <ocidl.h>\n#include <olectl.h>\n\n//***********************************************************************************************\n//\tFor debugging chat defined hresults...\nvoid ChatDefAsText( char* szDesc, HRESULT hRes );\nvoid DebugChatDef( HRESULT hRes );\n\nint iChannelLobbyNumber( const unsigned char* szChannelName );\n#define REASONABLELOBBYINTERPRETEDNAMELEN\t50\nvoid InterpretLobbyNumber( char* szLobbyNameToSet, int iLobby );\n\nclass WolapiObject;\n\n#define MAXCHATSENDLENGTH 71\t//\tMainly aesthetic, and because of the length of edit line.\n\nenum CHANNELFILTER\n{\n\tCHANNELFILTER_NO,\n\tCHANNELFILTER_OFFICIAL,\n\tCHANNELFILTER_UNOFFICIAL,\n\tCHANNELFILTER_LOBBIES,\n\tCHANNELFILTER_LOCALLOBBYGAMES,\n};\n\n#define WOLCOLORREMAP_ACTION\t\t\tPCOLOR_GREY\n#define WOLCOLORREMAP_SELFSPEAKING\t\tPCOLOR_RED\n#define WOLCOLORREMAP_LOCALMACHINEMESS\tPCOLOR_REALLY_BLUE\t\t//\tColor of system messages that originate locally.\n#define WOLCOLORREMAP_PAGE\t\t\t\tPCOLOR_GOLD\n#define WOLCOLORREMAP_KICKORBAN\t\t\tPCOLOR_GREEN\t//LTBLUE\n#define WOLCOLORREMAP_PUBLICMESSAGE\t\tPCOLOR_NONE\n#define WOLCOLORREMAP_PRIVATEMESSAGE\tPCOLOR_ORANGE\n\n#define WOLSOUND_ERROR\t\t\t\t\tVOC_SYS_ERROR\n#define WOLSOUND_LOGIN\t\t\t\t\tVOC_RADAR_ON\n#define WOLSOUND_LOGOUT\t\t\t\t\tVOC_RADAR_OFF\n#define WOLSOUND_ENTERCHAN\t\t\t\tVOC_PLAYER_JOINED\n#define WOLSOUND_EXITCHAN\t\t\t\tVOC_PLAYER_LEFT\n#define WOLSOUND_ONPAGE\t\t\t\t\tVOC_INCOMING_MESSAGE\n#define WOLSOUND_KICKORBAN\t\t\t\tVOC_TANYA_KISS\n#define WOLSOUND_ENTERGAME\t\t\t\tVOC_INVULNERABLE\n#define WOLSOUND_EXITGAME\t\t\t\tVOC_DOOR\n\nenum DISCONNECT_PING_STATUS\n{\n\tPING_UNSTARTED,\n\tPING_WAITING,\n\tPING_GOOD,\n\tPING_BAD,\n};\n#define DISCONNECT_PING_COUNT\t\t5\n\n//***********************************************************************************************\nclass RAChatEventSink : /////public CComObjectRoot, /////public IConnectionPoint,\n\tpublic IChatEvent\n{\n public:\n\tRAChatEventSink( WolapiObject* pOwner );\n\tvirtual ~RAChatEventSink();\n\n//    BEGIN_COM_MAP(RAChatEventSink)\n//\t  COM_INTERFACE_ENTRY(IChatEvent)\n//    END_COM_MAP()\n\n\t// IUnknown\n\tSTDMETHOD(QueryInterface)(const IID& iid, void **ppv);\n\tSTDMETHOD_(ULONG,AddRef)();\n\tSTDMETHOD_(ULONG,Release)();\n\n\t// IChatEvent\n\tSTDMETHOD(OnServerList)(HRESULT res, Server* servers);\n\tSTDMETHOD(OnLogout)(HRESULT r, User *user);\n\tSTDMETHOD(OnBusy)(HRESULT r);\n\tSTDMETHOD(OnIdle)(HRESULT r);\n\tSTDMETHOD(OnPageSend)(HRESULT r);\n\tSTDMETHOD(OnPaged)(HRESULT r, User *, LPCSTR);\n\tSTDMETHOD(OnFind)(HRESULT r, Channel *);\n\tSTDMETHOD(OnConnection)(HRESULT r,LPCSTR motd);\n\tSTDMETHOD(OnChannelCreate)(HRESULT r, Channel *channel);\n\tSTDMETHOD(OnChannelModify)(HRESULT r, Channel *channel);\n\tSTDMETHOD(OnChannelJoin)(HRESULT r,  Channel *channel,  User *user);\n\tSTDMETHOD(OnChannelLeave)(HRESULT r, Channel *channel,  User *user);\n\tSTDMETHOD(OnChannelTopic)(HRESULT r, Channel *channel,  LPCSTR topic);\n\tSTDMETHOD(OnGroupList)(HRESULT r,  Group *);\n\tSTDMETHOD(OnPublicMessage)(HRESULT r,  Channel *channel, User *user, LPCSTR text);\n\tSTDMETHOD(OnPrivateMessage)(HRESULT r,  User *user,LPCSTR text);\n\tSTDMETHOD(OnSystemMessage)(HRESULT r, LPCSTR);\n\tSTDMETHOD(OnNetStatus)(HRESULT r);\n\tSTDMETHOD(OnChannelList)(HRESULT r, Channel* channels);\n\tSTDMETHOD(OnUserList)(HRESULT r, Channel* channel, User* users);\n\tSTDMETHOD(OnUpdateList)(HRESULT res, Update *);\n\tSTDMETHOD(OnServerError)(HRESULT res);\n\tSTDMETHOD(OnMessageOfTheDay)(HRESULT res, LPCSTR);\n\tSTDMETHOD(OnPrivateAction)(HRESULT r, User *,  LPCSTR);\n\tSTDMETHOD(OnPublicAction)(HRESULT r, Channel *, User *,  LPCSTR);\n\tSTDMETHOD(OnPrivateGameOptions)(HRESULT r, User *,  LPCSTR);\n\tSTDMETHOD(OnPublicGameOptions)(HRESULT r, Channel *, User *,  LPCSTR);\n\tSTDMETHOD(OnGameStart)(HRESULT r, Channel *, User *,  int);\n\tSTDMETHOD(OnUserKick)(HRESULT r, Channel *, User *,  User *);\n\tSTDMETHOD(OnUserIP)(HRESULT r, User *);\n\tSTDMETHOD(OnServerError)(HRESULT res, LPCSTR ircmsg);\n\tSTDMETHOD(OnServerBannedYou)(HRESULT r, time_t bannedTill);\n\tSTDMETHOD(OnUserFlags)(HRESULT r, LPCSTR name, unsigned int flags, unsigned int mask);\n\tSTDMETHOD(OnChannelBan)(HRESULT r, LPCSTR name, int banned);\n\n\tunsigned long\tGetPlayerGameIP( const char* szPlayerName ) const;\n\tvoid\t\t\tDeleteUserList();\t\t//\tDeletes from heap all users pointed to through pUserList.\n\tvoid\t\t\tDeleteUserIPList();\n\tunsigned long\tGetUserIP( const char* szName ) const;\n\t\n\tvoid\t\t\tActionEggSound( const char* szMessage );\n\npublic:\n\t//\tThese vars are rather hackish. Basically, they are set before a callback is expected to be fired, and\n\t//\tthen checked immediately afterwards. The rest of the time, their values are meaningless.\n\t//\tThe idea is to force wolapi act in a modal way. In many places I \"block\" until a callback response to a \n\t//\twolapi request has been received.\n\tbool\tbRequestServerListWait;\n\tbool\tbRequestConnectionWait;\n\tbool\tbRequestLogoutWait;\n//\tbool\tbRequestChannelListWait;\n\tbool\tbRequestChannelJoinWait;\n\tbool\tbRequestChannelLeaveWait;\n\tbool\tbRequestUserListWait;\n\tbool\tbRequestChannelCreateWait;\n\tbool\tbRequestFindWait;\n\tbool\tbRequestPageWait;\n\n\tbool\tbRequestChannelListForLobbiesWait;\n\n\tbool\tbIgnoreChannelLists;\t\t\t//\tUsed to temporarily turn off response to channel lists, when we are in the midst\n\t\t\t\t\t\t\t\t\t\t\t//\tof some processing that depends on pChannelList remaining constant.\n\n\tbool\tbRequestGameStartWait;\n\n\tServer*\t\t\tpServer;\t\t\t\t//\tServer to connect to, acquired from OnServerList.\n\tbool\t\t\tbConnected;\t\t\t\t//\tTrue when user is logged in to chat server.\n\tbool\t\t\tbJoined;\t\t\t\t//\tTrue when user has joined a channel.\n\n\tChannel*\t\tpChannelList;\t\t\t//\tFirst element of channel list, or null.\n\tCHANNELFILTER\tChannelFilter;\t\t\t//\tAffects what channels are included in channel list when built.\n\n\tUser*\t\t\tpUserList;\t\t\t\t//\tFirst element of user list, or null.\n\tUser*\t\t\tpUserTail;\t\t\t\t//\tLast element of user list, or null.\n\n\tchar*\t\t\tszMotd;\t\t\t\t\t//\tMessage of the day.\n\tHRESULT\t\t\thresRequestConnectionError;\t\t//\tUsed to pass error hresult.\n\t\n\tHRESULT\t\t\thresRequestFindResult;\t//\tUsed to pass hresult.\n\tChannel\t\t\tOnFindChannel;\n\n\tHRESULT\t\t\thresRequestPageResult;\t//\tUsed to pass hresult.\n\n\tHRESULT\t\t\thresRequestJoinResult;\t//\tUsed to pass hresult.\n\n\tbool\t\t\tbGotKickedTrigger;\t\t//\tSpecial flag meaning do some more processing after callback has exited.\n\n\tUser*\t\t\tpGameUserList;\t\t\t//\tFirst element of start game user list, or null.\n\tint\t\t\t\tiGameID;\t\t\t\t//\tWW Online game id received from OnGameStart.\n\t\t\t\t\t\t\t\t\t\t\t//\tIs also a flag indicating \"OnGameStart() called, TriggerGameStart() not yet called\".\n\n\tUser*\t\t\tpUserIPList;\t\t\t//\tList that holds user IP's, used for pinging in game channel.\n\tUser*\t\t\tpUserIPListTail;\n\nprotected:\n\tWolapiObject*\tpOwner;\t\t\t\t\t//\tLink back to the object that contains me.\n\n\tvoid\t\t\tDeleteChannelList();\t//\tDeletes from heap all channels pointed to through pChannelList.\n\tbool\t\t\tDownloadUpdates( Update* pUpdateList, int iUpdates );\n\tbool\t\t\tbSpecialMessage( const char* szMessage );\n\tvoid\t\t\tInsertUserSorted( User* pUserNew );\n\nprivate:\n\tlong m_cRef;  // Reference Count\n\n};\n\n//***********************************************************************************************\nclass RADownloadEventSink : \n///////////\tpublic CComObjectRoot,\n\tpublic IDownloadEvent\n{\npublic:\n\tRADownloadEventSink();\n\tvirtual ~RADownloadEventSink() {};\n\n//  BEGIN_COM_MAP(RADownloadEventSink)\n//    COM_INTERFACE_ENTRY(IDownloadEvent)\n//  END_COM_MAP()\n\n\t// IUnknown\n\tSTDMETHOD(QueryInterface)(const IID& iid, void **ppv);\n\tSTDMETHOD_(ULONG,AddRef)();\n\tSTDMETHOD_(ULONG,Release)();\n\n\t// IDownloadEvent\n\tSTDMETHOD(OnEnd)(void);\n\tSTDMETHOD(OnError)(int error);\n\tSTDMETHOD(OnProgressUpdate)(int bytesread, int totalsize, int timetaken, int timeleft);\n\tSTDMETHOD(OnStatusUpdate)(int status);\n\tSTDMETHOD(OnQueryResume)(void);\n\npublic:\n\tbool\t\tbFlagEnd;\n\tbool\t\tbFlagError;\n\tbool\t\tbFlagProgressUpdate;\n\tbool\t\tbFlagStatusUpdate;\n\tbool\t\tbFlagQueryResume;\n\tint\t\t\tiBytesRead;\n\tint\t\t\tiTotalSize;\n\tint\t\t\tiTimeTaken;\n\tint\t\t\tiTimeLeft;\n\tint\t\t\tiStatus;\n\tbool\t\tbResumed;\n\nprivate:\n\tlong m_cRef;  // Ref count\n};\n\n//***********************************************************************************************\nclass RANetUtilEventSink :\n//    public CComObjectRoot,\n    public INetUtilEvent\n{\npublic:\n\tRANetUtilEventSink( WolapiObject* pOwner );\n\tvirtual ~RANetUtilEventSink();\n\n//BEGIN_COM_MAP(CNetUtilEventSink)\n//\tCOM_INTERFACE_ENTRY(INetUtilEvent)\n//END_COM_MAP()\n\n\t// IUnknown\n\tSTDMETHOD(QueryInterface)(const IID& iid, void **ppv);\n\tSTDMETHOD_(ULONG,AddRef)();\n\tSTDMETHOD_(ULONG,Release)();\n\n\t// INetUtilEvent\n\n\tSTDMETHOD(OnGameresSent)(HRESULT res);\n\tSTDMETHOD(OnLadderList)(HRESULT res, Ladder *list, int totalCount, long timeStamp, int keyRung);\n\tSTDMETHOD(OnPing)(HRESULT res, int time, unsigned long ip, int handle);\n\n\n\tvoid\t\t\tDeleteLadderList();\t\t//\tDeletes from heap all users pointed to through pUserList.\n\tunsigned int\tGetUserRank( const char* szName, bool bRankRA );\n\n\tLadder*\t\t\tpLadderList;\t\t\t\t//\tFirst element of Ladder list, or null.\n\tLadder*\t\t\tpLadderTail;\t\t\t\t//\tLast element of Ladder list, or null.\n\tLadder*\t\t\tpLadderListAM;\t\t\t\t//\tFirst element of Aftermath Ladder list, or null.\n\tLadder*\t\t\tpLadderTailAM;\t\t\t\t//\tLast element of Aftermath Ladder list, or null.\n\nprotected:\n\tWolapiObject*\tpOwner;\t\t\t\t\t//\tLink back to the object that contains me.\n\nprivate:\n\tlong m_cRef;  // Reference Count\n};\n\n//***********************************************************************************************\n\n//\tSKU, reported to WOLAPI for the purpose of finding patches.\n#ifdef ENGLISH\n#define GAME_SKU\t\t0x1500\n#else\n#ifdef GERMAN\n#define GAME_SKU\t\t0x1502\n#else\n#define GAME_SKU\t\t0x1503\n#endif\n#endif\n\n#define GAME_VERSION\t0x00030003\n#define GAME_TYPE\t\t21\n#define LOB_PREFIX\t\t\"Lob_21_\"\n\n//\tSent to gameres server in order to receive Red Alert or Aftermath ladder rankings. (Sent in RequestLadderList.)\n#define LADDER_CODE_RA\t\t1005\n#define LADDER_CODE_AM\t\t500\n\n#endif\n\n#endif\n"
  },
  {
    "path": "CODE/READLINE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#include\t<ctype.h>\n#include\t<string.h>\n#include\t\"wwfile.h\"\n#include\t\"xstraw.h\"\n#include\t\"readline.h\"\n\n\n// Disable the \"temporary object used to initialize a non-constant reference\" warning.\n#pragma warning 665 9\n\n\nvoid strtrim(char * buffer)\n{\n\tif (buffer) {\n\n\t\t/*\n\t\t**\tStrip leading white space from the string.\n\t\t*/\n\t\tchar * source = buffer;\n\t\twhile (isspace(*source)) {\n\t\t\tsource++;\n\t\t}\n\t\tif (source != buffer) {\n\t\t\tstrcpy(buffer, source);\n\t\t}\n\n\t\t/*\n\t\t**\tClip trailing white space from the string.\n\t\t*/\n\t\tfor (int index = strlen(buffer)-1; index >= 0; index--) {\n\t\t\tif (isspace(buffer[index])) {\n\t\t\t\tbuffer[index] = '\\0';\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\nint Read_Line(FileClass & file, char * buffer, int len, bool & eof)\n{\n\treturn(Read_Line(FileStraw(file), buffer, len, eof));\n}\n\n\nint Read_Line(Straw & file, char * buffer, int len, bool & eof)\n{\n\tif (len == 0 || buffer == NULL) return(0);\n\n\tint count = 0;\n\tfor (;;) {\n\t\tchar c;\n\t\tif (file.Get(&c, sizeof(c)) != sizeof(c)) {\n\t\t\teof = true;\n\t\t\tbuffer[0] = '\\0';\n\t\t\tbreak;\n\t\t}\n\n\t\tif (c == '\\x0A') break;\n\t\tif (c != '\\x0D' && count+1 < len) {\n\t\t\tbuffer[count++] = c;\n\t\t}\n\t}\n\tbuffer[count] = '\\0';\n\n\tstrtrim(buffer);\n\treturn(strlen(buffer));\n}\n"
  },
  {
    "path": "CODE/READLINE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#include\t\"wwfile.h\"\n#include\t\"straw.h\"\n\nvoid strtrim(char * buffer);\nint Read_Line(FileClass & file, char * buffer, int len, bool & eof);\nint Read_Line(Straw & file, char * buffer, int len, bool & eof);\n\n"
  },
  {
    "path": "CODE/RECT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RECT.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RECT.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/22/96                                                     *\n *                                                                                             *\n *                  Last Update : July 22, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Rect::Rect -- Constructs a rectangle object.                                              *\n *   Rect::Is_Valid -- Determines if the rectangle is valid.                                   *\n *   Rect::Intersect -- Find the intersection between two rectangles.                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"rect.h\"\n\n\n/***********************************************************************************************\n * Rect::Rect -- Constructs a rectangle object.                                                *\n *                                                                                             *\n *    This will construct a rectangle object according to the parameters specified.            *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y values of the upper left corner of the rectangle.             *\n *                                                                                             *\n *          w,h   -- The width and height values of the rectangle.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/22/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRect::Rect(int x, int y, int w, int h) :\n\tX(x),\n\tY(y),\n\tWidth(w),\n\tHeight(h)\n{\n}\n\n\n/***********************************************************************************************\n * Rect::Is_Valid -- Determines if the rectangle is valid.                                     *\n *                                                                                             *\n *    An invalid rectangle has values that do not make any sense. This is a useful state since *\n *    this can be used to determine if a rectangle has been initialized correctly or for       *\n *    detecting an error return condition for rectangle manipulation routines.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Does this rectangle appear valid?                                            *\n *                                                                                             *\n * WARNINGS:   An invalid rectangle is one that has a width or height of less than one.        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/22/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool Rect::Is_Valid(void) const\n{\n\treturn(Width > 0 && Height > 0);\n}\n\n\n/***********************************************************************************************\n * Rect::Intersect -- Find the intersection between two rectangles.                            *\n *                                                                                             *\n *    This routine will take the specified rectangle and use it like a \"cookie cutter\" on this *\n *    rectangle. The intersection of these two rectangles is returned. An optional X and       *\n *    Y parameter is supplied so that an absolute coordinate can be maintained to the new      *\n *    rectangle.                                                                               *\n *                                                                                             *\n * INPUT:   rectangle   -- Reference to the rectangle to use as a cookie cutter.               *\n *                                                                                             *\n *          x,y         -- Optional pointer to a coordinate that will be adjusted to stay      *\n *                         in an absolute position in coordinates even though it is a          *\n *                         relative offset.                                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the rectangle that is the intersection of the one specified and       *\n *          this rectangle.                                                                    *\n *                                                                                             *\n * WARNINGS:   The rectangle returned may be invalid. This can occur if there is no legal      *\n *             intersection between the rectangles.                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/22/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRect const Rect::Intersect(Rect const & rectangle, int * x, int * y) const\n{\n\tRect rect(0, 0, 0, 0);\t\t\t// Dummy (illegal) rectangle.\n\tRect r = rectangle;\t\t\t\t// Working rectangle.\n\n\t/*\n\t**\tBoth rectangles must be valid or else no intersection can occur. In such\n\t**\ta case, return an illegal rectangle.\n\t*/\n\tif (!Is_Valid() || !rectangle.Is_Valid()) return(rect);\n\n\t/*\n\t**\tThe rectangle spills past the left edge.\n\t*/\n\tif (r.X < X) {\n\t\tr.Width -= X - r.X;\n\t\tr.X = X;\n\t}\n\tif (r.Width < 1) return(rect);\n\n\t/*\n\t**\tThe rectangle spills past top edge.\n\t*/\n\tif (r.Y < Y) {\n\t\tr.Height -= Y - r.Y;\n\t\tr.Y = Y;\n\t}\n\tif (r.Height < 1) return(rect);\n\n\t/*\n\t**\tThe rectangle spills past the right edge.\n\t*/\n\tif (r.X + r.Width > X + Width) {\n\t\tr.Width -= (r.X + r.Width) - (X + Width);\n\t}\n\tif (r.Width < 1) return(rect);\n\n\t/*\n\t**\tThe rectangle spills past the bottom edge.\n\t*/\n\tif (r.Y + r.Height > Y + Height) {\n\t\tr.Height -= (r.Y + r.Height) - (Y + Height);\n\t}\n\tif (r.Height < 1) return(rect);\n\n\t/*\n\t**\tAdjust Height relative draw position according to Height new rectangle\n\t**\tunion.\n\t*/\n\tif (x != NULL) {\n\t\t*x -= (r.X-X);\n\t}\n\tif (y != NULL) {\n\t\t*y -= (r.Y-Y);\n\t}\n\n\treturn(r);\n}\n\n\nRect const Union(Rect const & rect1, Rect const & rect2)\n{\n\tif (rect1.Is_Valid()) {\n\t\tif (rect2.Is_Valid()) {\n\t\t\tRect result = rect1;\n\n\t\t\tif (result.X > rect2.X) {\n\t\t\t\tresult.Width += result.X-rect2.X;\n\t\t\t\tresult.X = rect2.X;\n\t\t\t}\n\t\t\tif (result.Y > rect2.Y) {\n\t\t\t\tresult.Height += result.Y-rect2.Y;\n\t\t\t\tresult.Y = rect2.Y;\n\t\t\t}\n\t\t\tif (result.X+result.Width < rect2.X+rect2.Width) {\n\t\t\t\tresult.Width = ((rect2.X+rect2.Width)-result.X)+1;\n\t\t\t}\n\t\t\tif (result.Y+result.Height < rect2.Y+rect2.Height) {\n\t\t\t\tresult.Height = ((rect2.Y+rect2.Height)-result.Y)+1;\n\t\t\t}\n\t\t\treturn(result);\n\t\t}\n\t\treturn(rect1);\n\t}\n\treturn(rect2);\n}\n"
  },
  {
    "path": "CODE/RECT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RECT.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RECT.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/21/96                                                     *\n *                                                                                             *\n *                  Last Update : July 21, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef RECT_H\n#define RECT_H\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n#include\t<stddef.h>\n\nclass Rect\n{\n\tpublic:\n\t\tRect(int x=0, int y=0, int w=0, int h=0);\n\n\t\tRect const Intersect(Rect const & rectangle, int * x=NULL, int * y=NULL) const;\n\t\tfriend Rect const Union(Rect const & rect1, Rect const & rect2);\n\n\t\tbool Is_Valid(void) const;\n\t\tint Size(void) const {return(Width*Height);}\n\n//\tprivate:\n\t\tint X;\n\t\tint Y;\n\t\tint Width;\n\t\tint Height;\n};\n\n\n#endif\n\n"
  },
  {
    "path": "CODE/REGION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/REGION.H 1     3/03/97 10:25a Joe_bostic $ */\n/*********************************************************************************************** \n ***              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               *** \n *********************************************************************************************** \n *                                                                                             * \n *                 Project Name : Command & Conquer                                            * \n *                                                                                             * \n *                    File Name : REGION.H                                                     * \n *                                                                                             * \n *                   Programmer : Joe L. Bostic                                                * \n *                                                                                             * \n *                   Start Date : 03/09/95                                                     * \n *                                                                                             * \n *                  Last Update : March 9, 1995 [JLB]                                          * \n *                                                                                             * \n *---------------------------------------------------------------------------------------------* \n * Functions:                                                                                  * \n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef REGION_H\n#define REGION_H\n\n\nclass RegionClass {\n\tpublic:\n\t\tRegionClass(void) {Threat = 0;};\n\t\t~RegionClass(void) {};\n\t\tint operator != (RegionClass const & region) {return memcmp(this, &region, sizeof(RegionClass));};\n\t\tint operator == (RegionClass const & region) {return !memcmp(this, &region, sizeof(RegionClass));};\n\t\tint operator > (RegionClass const & region) {return memcmp(this, &region, sizeof(RegionClass)) > 0;};\n\t\tint operator < (RegionClass const & region) {return memcmp(this, &region, sizeof(RegionClass)) < 0;};\n\n\t\tvoid Reset_Threat(void) {Threat = 0;};\n\t\tvoid Adjust_Threat(int threat, int neg) {if (neg) Threat -= threat; else Threat+= threat;};\n\t\tint Threat_Value(void) const {return Threat;};\n\n\tprotected:\n\t\tlong  Threat;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/REINF.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/REINF.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : REINF.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 24, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 26, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Create_Air_Reinforcement -- Creates air strike reinforcement                              *\n *   Create_Special_Reinforcement -- Ad hoc reinforcement handler.                             *\n *   Do_Reinforcements -- Create and place a reinforcement team.                               *\n *   _Consists_Only_Of_Infantry -- Determine if this group consists only of infantry.          *\n *   _Create_Group -- Create a group given team specification.                                 *\n *   _Pop_Group_Out_Of_Object -- Process popping the group out of the object.                  *\n *   _Who_Can_Pop_Out_Of -- Find a suitable host for these reinforcements.                     *\n *   _Need_To_Take -- Examines unit to determine if it should be confiscated.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * _Pop_Group_Out_Of_Object -- Process popping the group out of the object.                    *\n *                                                                                             *\n *    This routine will cause the group to pop out of the object specified.                    *\n *                                                                                             *\n * INPUT:   group    -- Pointer to the first object in the group to be popped out.             *\n *                                                                                             *\n *          object   -- Pointer to the object that the group is to pop out of.                 *\n *                                                                                             *\n * OUTPUT:  bool; Was the group popped out of the specified object?                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic bool _Pop_Group_Out_Of_Object(FootClass * group, TechnoClass * object)\n{\n\tassert(group != NULL && object != NULL);\n\tint quantity = 0;\n\n\t/*\n\t**\tTake every infantry member of this group and detach it from the group list\n\t**\tand then make it pop out of the candidate source.\n\t*/\n\twhile (group != NULL) {\n\t\tTechnoClass * todo = group;\n\t\tgroup = (FootClass *)(ObjectClass *)group->Next;\n\t\ttodo->Next = NULL;\n\n\t\tswitch (object->What_Am_I()) {\n\n\t\t\t/*\n\t\t\t**\tThe infantry just walks out of a building.\n\t\t\t*/\n\t\t\tcase RTTI_BUILDING:\n\t\t\t\tif (object->Exit_Object(todo) != 2) {\n\t\t\t\t\tdelete todo;\n\t\t\t\t} else {\n\t\t\t\t\t++quantity;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tInfantry get attached to transport vehicles and then unload.\n\t\t\t*/\n\t\t\tcase RTTI_UNIT:\n\t\t\tcase RTTI_VESSEL:\n\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\tobject->Attach((FootClass *)todo);\n\t\t\t\tobject->Assign_Mission(MISSION_UNLOAD);\n\t\t\t\t++quantity;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tdelete todo;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn (quantity != 0);\n}\n\n\n/***********************************************************************************************\n * _Need_To_Take -- Examines unit to determine if it should be confiscated.                    *\n *                                                                                             *\n *    The unit is examined and if the owning house needs to confiscate it, then this routine   *\n *    will return TRUE. In other cases, the unit should be left to its own devices.            *\n *                                                                                             *\n * INPUT:   unit  -- Pointer to the object to examine.                                         *\n *                                                                                             *\n * OUTPUT:  bool; Should the object be confiscated by the player so that it becomes one of     *\n *                his normal game objects?                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool _Need_To_Take(AircraftClass const * air)\n{\n\tif (*air == AIRCRAFT_YAK || *air == AIRCRAFT_MIG) {\n\t\tint deficit = air->House->Get_Quantity(STRUCT_AIRSTRIP);\n//\t\tint deficit = air->House->Get_Quantity(STRUCT_AIRSTRIP) - (air->House->Get_Quantity(AIRCRAFT_YAK)+air->House->Get_Quantity(AIRCRAFT_MIG));\n\n\t\t/*\n\t\t**\tLoop through all aircraft and subtract all the ones that are NOT loaners.\n\t\t*/\n\t\tfor (int index = 0; index < Aircraft.Count(); index++) {\n\t\t\tAircraftClass const * airptr = Aircraft.Ptr(index);\n\t\t\tif ((*airptr == AIRCRAFT_YAK || *airptr == AIRCRAFT_MIG) && airptr->IsOwnedByPlayer && !airptr->IsALoaner && airptr != air) {\n\t\t\t\tdeficit -= 1;\n\t\t\t\tif (deficit == 0) break;\n\t\t\t}\n\t\t}\n\n\t\tif (deficit > 0) return(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * _Create_Group -- Create a group given team specification.                                   *\n *                                                                                             *\n *    This routine will create all members of the group as specified by the team type.         *\n *                                                                                             *\n * INPUT:   teamtype -- Pointer to the team type that specifies what objects should be         *\n *                      created in this group.                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the first member of the group created.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic FootClass * _Create_Group(TeamTypeClass const * teamtype)\n{\n\tassert(teamtype != NULL);\n\n\tTeamClass * team = new TeamClass(teamtype);\n\tif (team != NULL) {\n\t\tteam->Force_Active();\n\t}\n\n\tbool hasunload = false;\n\tfor (int tm = 0; tm < teamtype->MissionCount; tm++) {\n\t\tif (teamtype->MissionList[tm].Mission == TMISSION_UNLOAD) {\n\t\t\thasunload = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tNow that the official source for the reinforcement has been determined, the\n\t**\tobjects themselves must be created.\n\t*/\n\tFootClass * transport = NULL;\n\tFootClass * object = NULL;\n\tfor (int index = 0; index < teamtype->ClassCount; index++) {\n\t\tTechnoTypeClass const * tclass = teamtype->Members[index].Class;\n\n\t\tfor (int sub = 0; sub < teamtype->Members[index].Quantity; sub++) {\n\t\t\tScenarioInit++;\n\t\t\tFootClass * temp = (FootClass *)tclass->Create_One_Of(HouseClass::As_Pointer(teamtype->House));\n\t\t\tScenarioInit--;\n\n\t\t\tif (temp != NULL) {\n\n\t\t\t\t/*\n\t\t\t\t**\tAdd the member to the team.\n\t\t\t\t*/\n\t\t\t\tif (team != NULL) {\n\t\t\t\t\tScenarioInit++;\n\t\t\t\t\tbool ok = team->Add(temp);\n//Mono_Printf(\"Added to team = %d.\\n\", ok);Keyboard->Get();\n\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t\ttemp->IsInitiated = true;\n\t\t\t\t}\n\n\t\t\t\tif (temp->What_Am_I() == RTTI_AIRCRAFT && !_Need_To_Take((AircraftClass const *)temp)) {\n\t\t\t\t\ttemp->IsALoaner = true;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tBuild the list of transporters and passengers.\n\t\t\t\t*/\n\t\t\t\tif (tclass->Max_Passengers() > 0) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tLink to the list of transports.\n\t\t\t\t\t*/\n\t\t\t\t\ttemp->Next = transport;\n\t\t\t\t\ttransport = temp;\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tLink to the list of normal objects.\n\t\t\t\t\t*/\n\t\t\t\t\ttemp->Next = object;\n\t\t\t\t\tobject = temp;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the group consists of transports and normal objects, then assign the normal\n\t**\tobjects to be passengers on the transport.\n\t*/\n\tif (transport != NULL && object != NULL) {\n\t\ttransport->Attach(object);\n\n\t\t/*\n\t\t**\tHACK ALERT! If the this team has an unload mission, then flag the transport\n\t\t**\tas a loaner so that it will exit from the map when the unload process is\n\t\t**\tcomplete, but only if the transport is an aircraft type.\n\t\t*/\n\t\tif (hasunload && (transport->What_Am_I() == RTTI_AIRCRAFT || transport->What_Am_I() == RTTI_VESSEL)) {\n\t\t\ttransport->IsALoaner = true;\n\t\t}\n\t}\n\n\t/*\n\t**\tFor JUST transport helicopters, consider the loaner a gift if there are\n\t**\tno passengers.\n\t*/\n\tif (transport != NULL && object == NULL && transport->What_Am_I() == RTTI_AIRCRAFT && *((AircraftClass *)transport) == AIRCRAFT_TRANSPORT) {\n\t\ttransport->IsALoaner = false;\n\t}\n\n\tif (transport == 0 && object == 0) {\n\t\tif (team != NULL) delete team;\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tIf this group consists only of non-transport object, then just return with a pointer\n\t**\tto the first member of the group.\n\t*/\n\tif (transport == NULL) {\n\t\treturn(object);\n\t}\n\n\treturn(transport);\n}\n\n\n/***********************************************************************************************\n * _Consists_Only_Of_Infantry -- Determine if this group consists only of infantry.            *\n *                                                                                             *\n *    Use this to determine if the specified group only contains infantry. Such a reinforcement*\n *    group is a candidate for popping out of a building or transport vehicle rather than      *\n *    driving/walking/sailing/flying onto the map under its own power.                         *\n *                                                                                             *\n * INPUT:   first -- Pointer to the first object in the group to examine.                      *\n *                                                                                             *\n * OUTPUT:  bool; Is the entire group composed of infantry type units?                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic bool _Consists_Only_Of_Infantry(FootClass const * first)\n{\n\twhile (first != NULL) {\n\t\tif (first->What_Am_I() != RTTI_INFANTRY) {\n\t\t\treturn(false);\n\t\t}\n\t\tfirst = (FootClass const *)((ObjectClass *)first->Next);\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * _Who_Can_Pop_Out_Of -- Find a suitable host for these reinforcements.                       *\n *                                                                                             *\n *    This routine is used to scan nearby locations to determine if there is a suitable host   *\n *    for these reinforcements to \"pop out of\" (apologies to Aliens). Typical hosts include    *\n *    buildings and transport vehicles (of any kind).                                          *\n *                                                                                             *\n * INPUT:   origin   -- The cell that should be scanned from. Only this location and immediate *\n *                      adjacent locations will be scanned.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a suitable host. If none could be found then NULL is     *\n *          returned.                                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic TechnoClass * _Who_Can_Pop_Out_Of(CELL origin)\n{\n\tCellClass * cellptr = &Map[origin];\n\tTechnoClass * candidate = NULL;\n\n\tfor (int f = -1; f < 8; f++) {\n\t\tCellClass * ptr = cellptr;\n\t\tif (f != -1) {\n\t\t\tptr = &ptr->Adjacent_Cell(FacingType(f));\n\t\t}\n\n\t\tBuildingClass * building = ptr->Cell_Building();\n\t\tif (building && building->Strength > 0) {\n\t\t\tcandidate = building;\n\t\t}\n\n\t\tUnitClass * unit = ptr->Cell_Unit();\n\t\tif (unit && unit->Strength && unit->Class->Max_Passengers() > 0) {\n\t\t\treturn(unit);\n\t\t}\n\t}\n\treturn(candidate);\n}\n\n\n/***********************************************************************************************\n * Do_Reinforcements -- Create and place a reinforcement team.                                 *\n *                                                                                             *\n *    This routine is called when a reinforcement team must be created and placed on the map.  *\n *    It will create all members of the team and place them at the location determined from    *\n *    the team composition. The reinforcement team should follow team orders until overridden  *\n *    by AI or player intervention.                                                            *\n *                                                                                             *\n * INPUT:   teamtype -- Pointer to the team type to create as a reinforcement.                 *\n *                                                                                             *\n * OUTPUT:  Was the reinforcement successfully created and placed?                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *   05/18/1995 JLB : Returns success or failure condition.                                    *\n *   06/19/1995 JLB : Announces reinforcements.                                                *\n *   02/15/1996 JLB : Recognizes team reinforcement location.                                  *\n *=============================================================================================*/\nbool Do_Reinforcements(TeamTypeClass const * teamtype)\n{\n\tassert(teamtype != 0);\n\n\t/*\n\t**\tperform some preliminary checks for validity.\n\t*/\n\tif (!teamtype || !teamtype->ClassCount) return(false);\n\n\t/*\n\t**\tHACK ALERT!\n\t**\tGive this team an attack waypoint mission that will attack the waypoint location of this\n\t**\tteam if there are no team missions previously assigned.\n\t*/\n\tif (teamtype->MissionCount == 0) {\n\t\tTeamTypeClass * tt = (TeamTypeClass *)teamtype;\n\t\ttt->MissionCount = 1;\n\t\ttt->MissionList[0].Mission = TMISSION_ATT_WAYPT;\n\t\ttt->MissionList[0].Data.Value = teamtype->Origin;\n\t}\n\n\tFootClass * object = _Create_Group(teamtype);\n\n\n//Mono_Printf(\"%d-%s (object=%p, team=%d).\\n\", __LINE__, __FILE__, object, object->Team.Is_Valid());Keyboard->Get();\n\n\n\t/*\n\t**\tBail on this reinforcement if no reinforcements could be created.\n\t**\tThis is probably because the object maximum was reached.\n\t*/\n\tif (!object) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tSpecial case code to handle infantry types that run from a building. This presumes\n\t**\tthat infantry are never a transport (which is safe to do).\n\t*/\n\tif (object != NULL && teamtype->Origin != -1 && _Consists_Only_Of_Infantry(object)) {\n\n\t\t/*\n\t\t**\tSearch for an object that these infantry can pop out of.\n\t\t*/\n\t\tTechnoClass * candidate = _Who_Can_Pop_Out_Of(Scen.Waypoint[teamtype->Origin]);\n\n\t\tif (candidate != NULL) {\n\t\t\treturn(_Pop_Group_Out_Of_Object(object, candidate));\n\t\t}\n\t}\n\n\t/*\n\t**\tThe reinforcements must be delivered the old fashioned way -- by moving onto the\n\t**\tmap using their own power. First order of business is to determine where they\n\t**\tshould arrive from.\n\t*/\n\tSourceType source = HouseClass::As_Pointer(teamtype->House)->Control.Edge;\n\tif (source == SOURCE_NONE) {\n\t\tsource = SOURCE_NORTH;\n\t}\n\n\t/*\n\t**\tPick the location where the reinforcements appear and then place\n\t**\tthem there.\n\t*/\n\tbool placed = false;\n\n\tFacingType eface = (FacingType)(source << 1);\t// Facing to enter map.\n\n\tCELL cell = Map.Calculated_Cell(source, teamtype->Origin, -1, object->Techno_Type_Class()->Speed);\n#ifdef FIXIT_ANTS\n\t/*\n\t**\tFor the ants, they will pop out of the ant hill directly.\n\t*/\n\tif (teamtype->Origin != -1 && object->What_Am_I() == RTTI_UNIT && \n\t\t\t(*((UnitClass*)object) == UNIT_ANT1 ||\n\t\t\t*((UnitClass*)object) == UNIT_ANT2 ||\n\t\t\t*((UnitClass*)object) == UNIT_ANT3))  {\n\t\tCELL newcell = Scen.Waypoint[teamtype->Origin];\n\t\tif (newcell != -1)  {\n\t\t\tif (Map[newcell].TType == TEMPLATE_HILL01)  {\n\t\t\t\tcell = newcell;\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n\tCELL newcell = cell;\n\n\tFootClass * o = (FootClass *)(ObjectClass *)object->Next;\n\tobject->Next = 0;\n\tbool okvoice = false;\n\twhile (newcell > 0 && object != NULL) {\n\t\tDirType desiredfacing = Facing_Dir(eface);\n\t\tif (object->What_Am_I() == RTTI_AIRCRAFT) {\n\t\t\tdesiredfacing = Random_Pick(DIR_N, DIR_MAX);\n\t\t}\n\n\t\tScenarioInit++;\n\t\tif (object->Unlimbo(Cell_Coord(newcell), desiredfacing)) {\n\t\t\tokvoice = true;\n\n\t\t\t/*\n\t\t\t**\tIf this object is part of a team, then the mission for this\n\t\t\t**\tobject will be guard. The team handler will assign the proper\n\t\t\t**\tmission that it should follow.\n\t\t\t*/\n\t\t\tif (object->What_Am_I() != RTTI_AIRCRAFT) {\n\t\t\t\tobject->Assign_Mission(MISSION_GUARD);\n\t\t\t\tobject->Commence();\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tCould not unlimbo at location specified so find an adjacent location that it can\n\t\t\t**\tbe unlimboed at. If this fails, then abort the whole placement process.\n\t\t\t*/\n\t\t\tfor (FacingType adj = FACING_N; adj < FACING_COUNT; adj++) {\n\t\t\t\tCELL trycell = Adjacent_Cell(newcell, adj);\n\t\t\t\tif (!Map.In_Radar(trycell) && object->Can_Enter_Cell(trycell, adj) == MOVE_OK) {\n\t\t\t\t\tnewcell = trycell;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (adj < FACING_COUNT) continue;\n\t\t\tnewcell = -1;\n\t\t}\n\t\tScenarioInit--;\n\n\t\tobject = o;\n\t\tif (object != NULL) {\n\t\t\to = (FootClass *)(ObjectClass *)object->Next;\n\t\t\tobject->Next = 0;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there are still objects that could not be placed, then delete them.\n\t*/\n\tif (o != NULL) {\n\t\twhile (o != NULL) {\n\t\t\tFootClass * old = o;\n\t\t\to = (FootClass *)(ObjectClass *)o->Next;\n\t\t\told->Next = 0;\n\n\t\t\tdelete old;\n\t\t}\n\t}\n\n\t/*\n\t**\tAnnounce when the reinforcements have arrived.\n\t*/\n\tif (okvoice && teamtype->House == PlayerPtr->Class->House) {\n\t\tSpeak(VOX_REINFORCEMENTS);\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Create_Special_Reinforcement -- Ad hoc reinforcement handler.                               *\n *                                                                                             *\n *    Use this routine to bring on a reinforcement that hasn't been anticipated by the trigger *\n *    system. An example of this would be replacement harvesters or airfield ordered units.    *\n *    The appropriate transport is created (if necessary) and a mission is assigned such that  *\n *    the object will legally bring itself onto the playing field.                             *\n *                                                                                             *\n * INPUT:   house    -- The owner of this reinforcement.                                       *\n *                                                                                             *\n *          type     -- The object to bring on.                                                *\n *                                                                                             *\n *          another  -- This is reserved for the transport class in those cases where the      *\n *                      transport MUST be forced to a specific type.                           *\n *                                                                                             *\n *          mission  -- The mission to assign this reinforcement team.                         *\n *                                                                                             *\n *          argument -- Optional team mission argument (usually a waypoint).                   *\n *                                                                                             *\n * OUTPUT:  Was the special reinforcement created without error?                               *\n *                                                                                             *\n * WARNINGS:   This routine will fail if a team type cannot be created.                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool Create_Special_Reinforcement(HouseClass * house, TechnoTypeClass const * type, TechnoTypeClass const * another, TeamMissionType mission, int argument)\n{\n\tassert(house != 0);\n\tassert(type != 0);\n\n\tif (house && type) {\n\t\tTeamTypeClass * team = new TeamTypeClass();\n\n\t\tif (team) {\n\n\t\t\t/*\n\t\t\t**\tIf there is no overridden mission assign to this special reinforcement, then\n\t\t\t**\twe must assign something. If not, the reinforcement will just sit at the edge\n\t\t\t**\tof the map.\n\t\t\t*/\n\t\t\tif (!another && mission == TMISSION_NONE) {\n\t\t\t\tmission = TMISSION_MOVECELL;\n\t\t\t\targument = Map.Calculated_Cell(house->Control.Edge);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tFill in the team characteristics.\n\t\t\t*/\n\t\t\tstrcpy((char *)&team->IniName[0], \"TEMP\");\n\t\t\tteam->IsReinforcable = false;\n\t\t\tteam->IsTransient = true;\n\t\t\tteam->ClassCount = 1;\n\t\t\tteam->Members[0].Class = type;\n\t\t\tteam->Members[0].Quantity = 1;\n\t\t\tteam->MissionCount = 1;\n\t\t\tif (mission == TMISSION_NONE) {\n\t\t\t\tteam->MissionList[0].Mission\t= TMISSION_UNLOAD;\n\t\t\t\tteam->MissionList[0].Data.Value = WAYPT_REINF;\n\t\t\t} else {\n\t\t\t\tteam->MissionList[0].Mission\t= mission;\n\t\t\t\tteam->MissionList[0].Data.Value = argument;\n\t\t\t}\n\t\t\tteam->House = house->Class->House;\n\t\t\tif (another) {\n\t\t\t\tteam->ClassCount++;\n\t\t\t\tteam->Members[1].Class = another;\n\t\t\t\tteam->Members[1].Quantity = 1;\n\t\t\t}\n\n\t\t\tbool ok = Do_Reinforcements(team);\n\t\t\tif (!ok) delete team;\n\t\t\treturn(ok);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * Create_Air_Reinforcement -- Creates air strike reinforcement                                *\n *                                                                                             *\n *    This routine is used to launch an airstrike. It will create the necessary aircraft and   *\n *    assign them to attack the target specified. This routine bypasses the normal             *\n *    reinforcement logic since it doesn't need the sophistication of unloading and following  *\n *    team mission lists.                                                                      *\n *                                                                                             *\n * INPUT:   house    -- The perpetrator of this air strike.                                    *\n *                                                                                             *\n *          air      -- The type of aircraft to make up this airstrike.                        *\n *                                                                                             *\n *          number   -- The number of aircraft in this airstrike.                              *\n *                                                                                             *\n *          mission  -- The mission to assign the aircraft.                                    *\n *                                                                                             *\n *          tarcom   -- The target to assign these aircraft.                                   *\n *                                                                                             *\n *          navcom   -- The navigation target to assign (if necessary).                        *\n *                                                                                             *\n * OUTPUT:  Returns the number of aircraft created for this airstrike.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Commented.                                                               *\n *=============================================================================================*/\nint Create_Air_Reinforcement(HouseClass * house, AircraftType air, int number, MissionType mission, TARGET tarcom, TARGET navcom, InfantryType passenger)\n{\n\tassert(house != 0);\n\tassert((unsigned)air < AIRCRAFT_COUNT);\n\tassert(number != 0);\n\tassert((unsigned)mission < MISSION_COUNT);\n\t/*\n\t** Get a pointer to the class of the object that we are going to create.\n\t*/\n\tTechnoTypeClass const * type = (TechnoTypeClass *)&AircraftTypeClass::As_Reference(air);\n\n\t/*\n\t** Abort the airstrike if Tanya is the passenger and she's dead.\n\t*/\n\tif (passenger == INFANTRY_TANYA && IsTanyaDead) {\n\t\tnumber = 0;\n\t}\n\n\t/*\n\t** Loop through the number of objects we are supposed to create and\n\t** \tcreate and place them on the map.\n\t*/\n\tfor (int sub = 0; sub < number; sub++) {\n\n\t\t/*\n\t\t** Create one of the required objects.  If this fails we could have\n\t\t** a real problem.\n\t\t*/\n\t\tScenarioInit++;\n\t\tTechnoClass * obj = (TechnoClass *)type->Create_One_Of(house);\n\t\tScenarioInit--;\n\t\tif (!obj) return(sub);\n\n\t\t/*\n\t\t** Flying objects always have the IsALoaner bit set.\n\t\t*/\n\t\tobj->IsALoaner = true;\n\n\t\t/*\n\t\t** Find a cell for the object to come in on.  This is stolen from the\n\t\t** the code that handles a SOURCE_AIR in the normal logic.\n\t\t*/\n\t\tSourceType source = house->Control.Edge;\n\t\tswitch (source) {\n\t\t\tcase SOURCE_NORTH:\n\t\t\tcase SOURCE_EAST:\n\t\t\tcase SOURCE_SOUTH:\n\t\t\tcase SOURCE_WEST:\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tsource = SOURCE_NORTH;\n\t\t\t\tbreak;\n\t\t}\n\t\tCELL newcell = Map.Calculated_Cell(source, -1, -1, SPEED_WINGED);\n\n\t\t/*\n\t\t** Try and place the object onto the map.\n\t\t*/\n\t\tScenarioInit++;\n\t\tint placed = obj->Unlimbo(Cell_Coord(newcell), DIR_N);\n\t\tScenarioInit--;\n\t\tif (placed) {\n\n\t\t\t/*\n\t\t\t** If we succeeded in placing the obj onto the map then\n\t\t\t** now we need to give it a mission and destination.\n\t\t\t*/\n\t\t\tobj->Assign_Mission(mission);\n\n\t\t\t/*\n\t\t\t** If a navcom was specified then set it.\n\t\t\t*/\n\t\t\tif (navcom != TARGET_NONE) {\n\t\t\t\tobj->Assign_Destination(navcom);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If a tarcom was specified then set it.\n\t\t\t*/\n\t\t\tif (tarcom != TARGET_NONE) {\n\t\t\t\tobj->Assign_Target(tarcom);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAssign generic passenger value here. This value is used to determine\n\t\t\t**\tif this aircraft should drop parachute reinforcements.\n\t\t\t*/\n\t\t\tif (obj->What_Am_I() == RTTI_AIRCRAFT) {\n\t\t\t\tAircraftClass * aircraft = (AircraftClass *)obj;\n\t\t\t\tif (passenger != INFANTRY_NONE) {\n\t\t\t\t\taircraft->Passenger = passenger;\n\t\t\t\t}\n//\t\t\t\tif (Passenger == INFANTRY_TANYA) {\n//\t\t\t\t\taircraft->Ammo = 1;\n\t\t\t\t\t//aircraft->AttacksRemaining = 1;\n//\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Start the object into action.\n\t\t\t*/\n\t\t\tobj->Commence();\n\t\t} else {\n\t\t\tdelete obj;\n\t\t\tsub--;\n\t\t\treturn(sub);\n\t\t}\n\t}\n\treturn(sub);\n}\n"
  },
  {
    "path": "CODE/RGB.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RGB.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RGB.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/02/95                                                     *\n *                                                                                             *\n *                  Last Update : February 20, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RGBClass::Adjust -- Adjust one RGB value toward another.                                  *\n *   RGBClass::Difference -- Determines the \"distance\" between two colors.                     *\n *   RGBClass::Set -- Set the color index to the RGB object specified.                         *\n *   RGBClass::operator HSVClass -- Conversion operator for RGB to HSV object.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"watcom.h\"\n#include \"rgb.h\"\n#include\t\"hsv.h\"\n#include\t\"palette.h\"\n\nRGBClass const BlackColor(0, 0, 0);\n\n\n/***********************************************************************************************\n * RGBClass::Adjust -- Adjust one RGB value toward another.                                    *\n *                                                                                             *\n *    This routine is used to modify an RGB value to proportionately match another RGB value   *\n *    according to the ratio parameter specified. Typical use of this routine is in palette    *\n *    fading from one palette to another or to black.                                          *\n *                                                                                             *\n * INPUT:   ratio    -- The ration of transformation. This value is in the form of 0 to 255,   *\n *                      with 0 being no change, and 255 being 100% transformed into the        *\n *                      destination color.                                                     *\n *                                                                                             *\n *          rgb      -- Reference to the destination RGB color to transform this color into.   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RGBClass::Adjust(int ratio, RGBClass const & rgb)\n{\n\t/*\n\t**\tRatio conversion is limited to 0 through 100%. This is\n\t**\tthe range of 0 to 255.\n\t*/\n\tratio &= 0x00FF;\n\n\t/*\n\t**\tAdjust the color guns by the ratio specified toward the\n\t**\tdestination color.\n\t*/\n\tint value = (int)rgb.Red - (int)Red;\n\tRed = (int)Red + (value * ratio) / 256;\n\n\tvalue = (int)rgb.Green - (int)Green;\n\tGreen = (int)Green + (value * ratio) / 256;\n\n\tvalue = (int)rgb.Blue - (int)Blue;\n\tBlue = (int)Blue + (value * ratio) / 256;\n}\n\n\n/***********************************************************************************************\n * RGBClass::Difference -- Determines the \"distance\" between two colors.                       *\n *                                                                                             *\n *    This routine is used to calculate a relative distance between two colors. The value is   *\n *    relative only to itself and thus is useful only for determining the magnitude of         *\n *    color difference rather than the nature of the color difference. Palette remapping       *\n *    code uses this routine to find closest matches for colors.                               *\n *                                                                                             *\n * INPUT:   rgb   -- Reference to the color to be compared to this color.                      *\n *                                                                                             *\n * OUTPUT:  Returns the difference between the two colors. The value returned is zero if the   *\n *          colors exactly match. The greater the positive value the greater the difference    *\n *          between the colors.                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RGBClass::Difference(RGBClass const & rgb) const\n{\n\tint r = (int)Red - (int)rgb.Red;\n\tif (r < 0) r = -r;\n\n\tint g = (int)Green - (int)rgb.Green;\n\tif (g < 0) g = -g;\n\n\tint b = (int)Blue - (int)rgb.Blue;\n\tif (b < 0) b = -b;\n\n\treturn(r*r + g*g + b*b);\n}\n\n\n/***********************************************************************************************\n * RGBClass::operator HSVClass -- Conversion operator for RGB to HSV object.                   *\n *                                                                                             *\n *    This conversion operator will convert an RGBClass object into an HSVClass object.        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a reference (implicit) to the HSVClass object that most closely       *\n *          represents the RGBClass object.                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRGBClass::operator HSVClass (void) const\n{\n\tint hue;\n\tint saturation;\n\tint value;\n\n\t/*\n\t**\tFetch working component values for the color guns.\n\t*/\n\tint red = Red_Component();\n\tint green = Green_Component();\n\tint blue = Blue_Component();\n\n\t/*\n\t**\tThe hue defaults to none. Only if there is a saturation value will the\n\t**\thue be calculated.\n\t*/\n\thue = 0;\n\n\t/*\n\t**\tSet the value (brightness) to match the brightest color gun.\n\t*/\n\tvalue = (red > green) ? red : green;\n\tif (blue > value) value = blue;\n\n\t/*\n\t**\tDetermine the amount of true white present in the color. This is the\n\t**\tminimum color gun value. The white component is used to determine\n\t**\tcolor saturation.\n\t*/\n\tint white = (red < green) ? red : green;\n\tif (blue < white) white = blue;\n\n\t/*\n\t**\tDetermine the saturation (intensity) of the color by comparing the\n\t**\tratio of true white as a component of the overall color. The more\n\t**\twhite component, the less saturation.\n\t*/\n\tsaturation = 0;\n\tif (value) {\n\t\tsaturation = ((value - white) * 255) / value;\n\t}\n\n\t/*\n\t** If there is any saturation at all, then the hue must be calculated. The\n\t**\thue is based on a six sided color wheel.\n\t*/\n\tif (saturation != 0) {\n\t\tunsigned int tmp = value - white;\n\t \tunsigned int r1 = ((value - red) * 255) / tmp;\n\t \tunsigned int g1 = ((value - green) * 255) / tmp;\n\t \tunsigned int b1 = ((value - blue) * 255) / tmp;\n\n\t\t// Find effect of second most predominant color.\n\t\t// In which section of the hexagon of colors does the color lie?\n\t\tif (value == red) {\n\t\t \tif (white == green) {\n\t\t\t\ttmp = 5 * 256 + b1;\n\t\t\t} else {\n\t\t\t\ttmp = 1 * 256 - g1;\n\t\t\t}\n\t\t} else {\n\t\t\tif (value == green) {\n\t\t\t \tif (white == blue) {\n\t\t\t\t\ttmp = 1 * 256 + r1;\n\t\t\t\t} else {\n\t\t\t\t\ttmp = 3 * 256 - b1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t \tif (white == red) {\n\t\t\t\t\ttmp = 3 * 256 + g1;\n\t\t\t\t} else {\n\t\t\t\t\ttmp = 5 * 256 - r1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Divide by six and round.\n\t\thue = tmp / 6;\n\t}\n\n\treturn(HSVClass(hue, saturation, value));\n}\n\n\n/***********************************************************************************************\n * RGBClass::Set -- Set the color index to the RGB object specified.                           *\n *                                                                                             *\n *    This routine will set the specified color index with this RGBClass object. Use this      *\n *    routine to set one color.                                                                *\n *                                                                                             *\n * INPUT:   color -- The color index to set with this RGBClass object.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RGBClass::Set(int color) const\n{\n\tRaw_Color_Prep(color);\n\tRaw_Set();\n\n\t((RGBClass &)PaletteClass::CurrentPalette[color]) = *this;\n}\n\n"
  },
  {
    "path": "CODE/RGB.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RGB.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RGB.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/02/95                                                     *\n *                                                                                             *\n *                  Last Update : December 2, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef RGB_H\n#define RGB_H\n\nclass PaletteClass;\nclass HSVClass;\n\n#ifndef OUTPORTB\n#define OUTPORTB\nextern void outportb(int port, unsigned char data);\n#pragma aux outportb parm [edx] [al] =\t\t\\\n\t\t\"out\tdx,al\"\n\nextern void outport(int port, unsigned short data);\n#pragma aux outport parm [edx] [ax] =\t\t\\\n\t\t\"out\tdx,al\"\t\t\\\n\t\t\"inc\tdx\"\t\t\t\\\n\t\t\"mov\tal,ah\"\t\t\\\n\t\t\"out\tdx,al\"\n#endif\n\nextern void outrgb(unsigned char red, unsigned char green, unsigned char blue);\n#pragma aux outrgb parm [al] [bl] [cl] \\\n\t\tmodify [dx al] = \\\n\t\t\"mov\tdx,03C9h\"\t\\\n\t\t\"out\tdx,al\"\t\t\\\n\t\t\"jmp\te1\"\t\t\t\\\n\t\t\"e1:\"\t\t\t\t\t\\\n\t\t\"mov\tal,bl\" \t\t\\\n\t\t\"out\tdx,al\"\t\t\\\n\t\t\"jmp\te2\"\t\t\t\\\n\t\t\"e2:\" \t\t\t\t\\\n\t\t\"mov\tal,cl\" \t\t\\\n\t\t\"out\tdx,al\"\t\t\\\n\t\t\"jmp\te3\"\t\t\t\\\n\t\t\"e3:\"\n\n/*\n**\tEach color entry is represented by this class. It holds the values for the color\n**\tguns. The gun values are recorded in device dependant format, but the interface\n**\tuses gun values from 0 to 255.\n*/\nclass RGBClass\n{\n//\tstatic RGBClass const BlackColor;\n\n\tpublic:\n\t\tRGBClass(void) : Red(0), Green(0), Blue(0) {};\n\t\tRGBClass(unsigned char red, unsigned char green, unsigned char blue) :\n\t\t\t\tRed((unsigned char)(red>>2)),\n\t\t\t\tGreen((unsigned char)(green>>2)),\n\t\t\t\tBlue((unsigned char)(blue>>2))\n\t\t\t{};\n\t\toperator HSVClass (void) const;\n\t\tRGBClass & operator = (RGBClass const & rgb) {\n\t\t\tif (this == &rgb) return(*this);\n\n\t\t\tRed = rgb.Red;\n\t\t\tGreen = rgb.Green;\n\t\t\tBlue = rgb.Blue;\n\t\t\treturn(*this);\n\t\t};\n\n\t\tenum {\n\t\t\tMAX_VALUE=255\n\t\t};\n\n\t\tvoid Adjust(int ratio, RGBClass const & rgb);\n//\t\tvoid Adjust(int ratio, RGBClass const & rgb = BlackColor);\n\t\tint Difference(RGBClass const & rgb) const;\n\t\tint Red_Component(void) const {return ((Red << 2) | (Red >> 6));};\n\t\tint Green_Component(void) const {return((Green << 2) | (Green >> 6));};\n\t\tint Blue_Component(void) const {return((Blue << 2) | (Blue >> 6));};\n\t\tvoid Set(int color) const;\n\n\tprivate:\n\n\t\tfriend class PaletteClass;\n\n\t\tvoid Raw_Set(void) const {\n\t\t\toutrgb(Red, Green, Blue);\n//\t\t\toutportb(0x03C9, Red);\n//\t\t\toutportb(0x03C9, Green);\n//\t\t\toutportb(0x03C9, Blue);\n\t\t};\n\n\t\tstatic void Raw_Color_Prep(unsigned char color) {\n\t\t\toutportb(0x03C8, color);\n\t\t};\n\n\t\t/*\n\t\t**\tThese hold the actual color gun values in machine dependant scale. This\n\t\t**\tmeans the values range from 0 to 63.\n\t\t*/\n\t\tunsigned char Red;\n\t\tunsigned char Green;\n\t\tunsigned char Blue;\n};\n\nextern RGBClass const BlackColor;\n\n#endif\n"
  },
  {
    "path": "CODE/RNDSTRAW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RNDSTRAW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RNDSTRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/04/96                                                     *\n *                                                                                             *\n *                  Last Update : July 10, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RandomStraw::Get -- Fetch random data.                                                    *\n *   RandomStraw::RandomStraw -- Constructor for the random straw class.                       *\n *   RandomStraw::Reset -- Reset the data to known initial state.                              *\n *   RandomStraw::Scramble_Seed -- Masks any coorelation between the seed bits.                *\n *   RandomStraw::Seed_Bit -- Add a random bit to the accumulated seed value.                  *\n *   RandomStraw::Seed_Bits_Needed -- Fetches the number of seed bits needed.                  *\n *   RandomStraw::Seed_Byte -- Submit 8 bits to the random number seed.                        *\n *   RandomStraw::Seed_Long -- Submit 32 bits to the random number seed.                       *\n *   RandomStraw::Seed_Short -- Submit 16 bits to the random number seed.                      *\n *   RandomStraw::~RandomStraw -- Destructor for random straw class.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t<limits.h>\n#include\t<string.h>\n#include\t\"rndstraw.h\"\n#include\t\"sha.h\"\n\n\n/***********************************************************************************************\n * RandomStraw::RandomStraw -- Constructor for the random straw class.                         *\n *                                                                                             *\n *    This will initialize the random straw into a known state. The initial state is useless   *\n *    for cryptographic purposes. It must be seeded before it should be used.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRandomStraw::RandomStraw(void) :\n\tSeedBits(0),\n\tCurrent(0)\n{\n\tReset();\n}\n\n\n/***********************************************************************************************\n * RandomStraw::~RandomStraw -- Destructor for random straw class.                             *\n *                                                                                             *\n *    This destructor will clear out the seed data so that there won't be any sensitive        *\n *    information left over in the memory this object occupied.                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRandomStraw::~RandomStraw(void)\n{\n\tReset();\n}\n\n\n/***********************************************************************************************\n * RandomStraw::Reset -- Reset the data to known initial state.                                *\n *                                                                                             *\n *    This routine is functionally equivalent to performing an placement new on the object. It *\n *    clears out all the seed data.                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   You must reseed it before fetching random numbers.                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RandomStraw::Reset(void)\n{\n\tSeedBits = 0;\n\tCurrent = 0;\n\tmemset(Random, '\\0', sizeof(Random));\n}\n\n\n/***********************************************************************************************\n * RandomStraw::Seed_Bits_Needed -- Fetches the number of seed bits needed.                    *\n *                                                                                             *\n *    This routine is used when seeding the random straw. Keep feeding random bits to this     *\n *    class until the Seed_Bits_Needed value returns zero. Random bits should be gathered from *\n *    sources external to the immediate program. Examples would be the system clock (good for  *\n *    a few bits), the delay between player keystrokes (good for a few bits per keystroke),    *\n *    etc. When gathering random bits from integers, use the low order bits (since they        *\n *    characteristically are less predictable and more 'random' than the others).              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bits required in order to fully seed this random        *\n *          number generator.                                                                  *\n *                                                                                             *\n * WARNINGS:   Even if this routine returns zero, you are still allowed and encouraged to feed *\n *             more random bits when the opportunity arrises.                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RandomStraw::Seed_Bits_Needed(void) const\n{\n\tconst int total = sizeof(Random) * CHAR_BIT;\n\tif (SeedBits < total) {\n\t\treturn(total - SeedBits);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * RandomStraw::Seed_Bit -- Add a random bit to the accumulated seed value.                    *\n *                                                                                             *\n *    This routine should be called to feed a single random bit to the random straw object.    *\n *    You must feed as many bits as requested by the Seed_Bits_Needed() function. Submitting   *\n *    additional bits is not only allowed, but encouraged.                                     *\n *                                                                                             *\n * INPUT:   seed  -- The bit (lowest order bit) to feed to the random number seed.             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RandomStraw::Seed_Bit(int seed)\n{\n\tchar * ptr = ((char *)&Random[0]) + ((SeedBits / CHAR_BIT) % sizeof(Random));\n\tchar frac = (char)(1 << (SeedBits & (CHAR_BIT-1)));\n\n\tif (seed & 0x01) {\n\t\t*ptr ^= frac;\n\t}\n\tSeedBits++;\n\n\tif (SeedBits == (sizeof(Random) * CHAR_BIT)) {\n\t\tScramble_Seed();\n\t}\n}\n\n\n/***********************************************************************************************\n * RandomStraw::Seed_Byte -- Submit 8 bits to the random number seed.                          *\n *                                                                                             *\n *    This will submit 8 bits (as specified) to the random number seed.                        *\n *                                                                                             *\n * INPUT:   seed  -- The seed bits to submit.                                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RandomStraw::Seed_Byte(char seed)\n{\n\tfor (int index = 0; index < CHAR_BIT; index++) {\n\t\tSeed_Bit(seed);\n\t\tseed >>= 1;\n\t}\n}\n\n\n/***********************************************************************************************\n * RandomStraw::Seed_Short -- Submit 16 bits to the random number seed.                        *\n *                                                                                             *\n *    This will submit 16 bits to the accumulated seed.                                        *\n *                                                                                             *\n * INPUT:   seed  -- The 16 bits to submit to the seed.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RandomStraw::Seed_Short(short seed)\n{\n\tfor (int index = 0; index < (sizeof(seed)*CHAR_BIT); index++) {\n\t\tSeed_Bit(seed);\n\t\tseed >>= 1;\n\t}\n}\n\n\n/***********************************************************************************************\n * RandomStraw::Seed_Long -- Submit 32 bits to the random number seed.                         *\n *                                                                                             *\n *    This will submit a full 32 bits to the accumulated seed value.                           *\n *                                                                                             *\n * INPUT:   seed  -- The 32 bits to submit.                                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RandomStraw::Seed_Long(long seed)\n{\n\tfor (int index = 0; index < (sizeof(seed)*CHAR_BIT); index++) {\n\t\tSeed_Bit(seed);\n\t\tseed >>= 1;\n\t}\n}\n\n\n/***********************************************************************************************\n * RandomStraw::Scramble_Seed -- Masks any coorelation between the seed bits.                  *\n *                                                                                             *\n *    This routine is called when a full set of seed bits has been accumulated. It will take   *\n *    the existing seed and scramble the bits. An effective way of doing this is to use the    *\n *    Secure Hash Algorithm. It is necessary to have this routine because there might be       *\n *    some coorelation in the seed bits. Even more important is that this routine will result  *\n *    in every bit of the seed having a scrambling effect on every other bit.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RandomStraw::Scramble_Seed(void)\n{\n\tSHAEngine sha;\n\n\tfor (int index = 0; index < sizeof(Random); index++) {\n\t\tchar digest[20];\n\n\t\tsha.Hash(&Random[0], sizeof(Random));\n\t\tsha.Result(digest);\n\n\t\tint tocopy = sizeof(digest) < (sizeof(Random)-index) ? sizeof(digest) : (sizeof(Random)-index);\n\t\tmemmove(((char *)&Random[0]) + index, digest, tocopy);\n\t}\n}\n\n\n/***********************************************************************************************\n * RandomStraw::Get -- Fetch random data.                                                      *\n *                                                                                             *\n *    This routine will fetch random data and store it into the buffer specified.              *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer to fill with random data.                        *\n *                                                                                             *\n *          length   -- The number of bytes to store into the buffer.                          *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes stored into the buffer. This will always   *\n *          be the number of bytes requested since random numbers are unexhaustible.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *   07/10/1996 JLB : Revamped to make cryptographically secure.                               *\n *=============================================================================================*/\nint RandomStraw::Get(void * source, int slen)\n{\n\tif (source == NULL || slen < 1) {\n\t\treturn(Straw::Get(source, slen));\n\t}\n\n\tint total = 0;\n\twhile (slen > 0) {\n\t\t*(char *)source = (char)Random[Current++];\n\t\tCurrent = Current % (sizeof(Random) / sizeof(Random[0]));\n\t\tsource = (char*)source + sizeof(char);\n\t\tslen--;\n\t\ttotal++;\n\t}\n\treturn(total);\n}\n"
  },
  {
    "path": "CODE/RNDSTRAW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RNDSTRAW.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RNDSTRAW.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/04/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef RNDSTRAW_H\n#define RNDSTRAW_H\n\n\n#include\t\"straw.h\"\n#include\t\"random.h\"\n\n/*\n**\tThis is a straw terminator class. It will generate random numbers to fill the data request.\n**\tUnlike regular straw terminators, this class will never run out of \"data\".\n*/\nclass RandomStraw : public Straw\n{\n\tpublic:\n\t\tRandomStraw(void);\n\t\tvirtual ~RandomStraw(void);\n\n\t\tvirtual int Get(void * source, int slen);\n\n\t\tvoid Reset(void);\n\t\tvoid Seed_Bit(int seed);\n\t\tvoid Seed_Byte(char seed);\n\t\tvoid Seed_Short(short seed);\n\t\tvoid Seed_Long(long seed);\n\n\t\tint Seed_Bits_Needed(void) const;\n\n\tprivate:\n\t\t/*\n\t\t**\tCounter of the number of seed bits stored to this random number\n\t\t**\tgenerator.\n\t\t*/\n\t\tint SeedBits;\n\n\t\t/*\n\t\t**\tThe current random generator to use when fetching the next random\n\t\t**\tbyte of data.\n\t\t*/\n\t\tint Current;\n\n\t\t/*\n\t\t**\tArray of generators. There must be at least 448 bits of random number seed\n\t\t**\tin order to be reasonably secure, however, using 1024 bits would be best.\n\t\t*/\n\t\tRandomClass Random[32];\n\n\t\tvoid Scramble_Seed(void);\n\n\t\tRandomStraw(RandomStraw & rvalue);\n\t\tRandomStraw & operator = (RandomStraw const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/RNG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RNG.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RNG.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 04/26/96                                                     *\n *                                                                                             *\n *                  Last Update : April 26, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef RNG_H\n#define RNG_H\n\n/*\n**\tThis is an abstract interface class for a random number generator. It serves only to\n**\tprovide random numbers.\n*/\nclass RandomNumberGenerator {\n\tpublic:\n\t\tvirtual ~RandomNumberGenerator() {}\n\n\t\tvirtual void Get_Block(void * output, unsigned int size) = 0;\n};\n\n\n#endif\n\n"
  },
  {
    "path": "CODE/ROTBMP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/ROTBMP.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ROTBMP.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/05/96                                                     *\n *                                                                                             *\n *                  Last Update : July 5, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n//#include\t\"function.h\"\n#include\t\"watcom.h\"\n#include \"rotbmp.h\"\n#define FILE_H\n#define WWMEM_H\n#include\t<wwlib32.h>\n\n\nint Rotate_Bitmap(GraphicViewPortClass * srcvp, GraphicViewPortClass * destvp, int angle);\n\nstruct WPPOINT {\n\tint x;\n\tint y;\n};\n\n/***************************************************************************\n * Rotate_bitmap -- rotate a bitmap from srcvp to destvp                   *\n *                                                                         *\n * INPUT: note that angles are 0 - 255 (best if used in increments of 4!)  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t   destvp should be a square. width and height should be equal to : \t \t*\n * \tMAX(srcvp->width,srcvp->height) * 1.7 (square root of 2!!)    \t\t \t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t*\n * HISTORY:                                                                *\n *   01/02/1996  BP : Created.                                             *\n *=========================================================================*/\nRotate_Bitmap(GraphicViewPortClass * srcvp, GraphicViewPortClass * destvp, int a)\n{\n\tint shift = 7;\n\tint fixpoint1 = 1 << shift; // this is a fixed point 1\n\tint Deltax;\n\tint Deltay;\n\tint sx,sy,dx,dy;\n\tint Error = 0;\n\tint Decimal = 0;\n\t// this is used if I walk in Y\n\tint buffwidth = srcvp->Get_Width() + srcvp->Get_XAdd();\n\tint buffwid2 = destvp->Get_Width() + destvp->Get_XAdd();\n\tchar * dest;\n\tchar * src;\n\tint sa,ca;\n\tint t;\n\tint x,y;\n\tint rx,ry;\n\tint w,h;\n\tint dw = destvp->Get_Width();\n\tint dh = destvp->Get_Height();\n\tWPPOINT sp[4];\n\tWPPOINT dp[4];\n\tsa = Sin256[a];\n\tca = Cos256[a];\n\t// get rectangle size\n\tx = 0;\n\ty = 0;\n\tw = srcvp->Get_Width();\n\th = srcvp->Get_Height();\n\n\tint halfws = w >> 1;\n\tint halfhs = h >> 1;\n\tint halfwd = dw >> 1;\n\tint halfhd = dh >> 1;\n\n\n\t// make the src rectangle\n\tsp[0].x = x;\n\tsp[0].y = y;\n\n\tsp[1].x = x + w;\n\tsp[1].y = y;\n\n\t// now calculate the rotated rectangle\n\tdp[0].x = ( ((sp[0].x - halfws) * ca) - ((sp[0].y - halfhs) * sa) ) >> shift;\n\tdp[0].x += halfwd;\n\n\tdp[0].y = ( ((sp[0].x - halfws) * sa) + ((sp[0].y - halfhs) * ca) ) >> shift;\n\tdp[0].y += halfhd;\n\n\tdp[1].x = ( ((sp[1].x - halfws) * ca) - ((sp[1].y - halfhs) * sa) ) >> shift;\n\tdp[1].x += halfwd;\n\n\tdp[1].y = ( ((sp[1].x - halfws) * sa) + ((sp[1].y - halfhs) * ca) ) >> shift;\n\tdp[1].y += halfhd;\n\n\trx = dp[0].x;\n\try = dp[0].y;\n\t// now calculate slope\n\n\t// diff from new to old x\n\n\tDeltax = (dp[1].x - dp[0].x);\n\n\t// diff from new to old y\n\n\tDeltay = (dp[1].y - dp[0].y);\n\n\t// handle the easy cases\n\n\t// no change in x\n\tint r;\n\tif (!Deltax) { // must be 90 or 270 degree transpose!\n\t\tif (Deltay < 0) {\n\t\t\t// walk across source in the x + dir\n\t\t\t// walk across dest in the y - dir\n\n\t\t\tx = 0;\n\t\t\tdy = 0;\n\t\t\tdx = 0;\n\t\t\tfor (t = 0; t< h; t++) {\n\t\t\t\tx = 0;\n\t\t\t\tsrc = MAKE_PTR(srcvp, x, y);\n\t\t\t\tdest = MAKE_PTR(destvp, rx + dx, ry - dy);\n\t\t\t\tfor (r = 0; r< w; r++) {\n\t\t\t\t\t// transparency\n\t\t\t\t\tif (* src)\n\t\t\t\t\t\t*dest = *src;\n\t\t\t\t\tsrc++;\n\t\t\t\t\tdest -= buffwid2;\n\t\t\t\t}\n\t\t\t\ty++;\n\t\t\t\tdx++;\n\t\t\t}\n\t\t} else {\n\t\t\t// walk across source in the x + dir\n\t\t\t// walk across dest in the y + dir\n\n\t\t\tx = 0;\n\t\t\tdy = 0;\n\t\t\tdx = 0;\n\t\t\tfor (t = 0; t< h; t++) {\n\t\t\t\tx = 0;\n\t\t\t\tsrc = MAKE_PTR(srcvp, x, y);\n\t\t\t\tdest = MAKE_PTR(destvp, rx - dx, ry + dy);\n\t\t\t\tfor (r = 0; r< w; r++) {\n\t\t\t\t\t// transparency\n\t\t\t\t\tif (*src)\n\t\t\t\t\t\t*dest = *src;\n\t\t\t\t\tsrc++;\n\t\t\t\t\tdest += buffwid2;\n\t\t\t\t}\n\t\t\t\ty++;\n\t\t\t\tdx++;\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\t// no change in y\n\n\tif (!Deltay) { // must be 0 or 180 degree transpose !\n\t\tif (Deltax < 0) {\n\t\t\ty = 0;\n\t\t\tfor (y = 0; y< h; y++) {\n\t\t\t\tx = 0;\n\t\t\t\tsrc = MAKE_PTR(srcvp, x, y);\n\t\t\t\tdest = MAKE_PTR(destvp, rx - x , ry - y);\n\t\t\t\tfor (x = 0 ; x< w; x++) {\n\t\t\t\t\t// transparency\n\t\t\t\t\tif (*src)\n\t\t\t\t\t\t*dest = *src;\n\t\t\t\t\tdest--;\n\t\t\t\t\tsrc++;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor (y = 0; y< h; y++) {\n\t\t\t\tx = 0;\n\t\t\t\tsrc = MAKE_PTR(srcvp, x, y);\n\t\t\t\tdest = MAKE_PTR(destvp, rx + x, ry + y);\n\t\t\t\tfor (x = 0 ; x< w; x++) {\n\t\t\t\t\t// transparency\n\t\t\t\t\tif (*src)\n\t\t\t\t\t\t*dest = *src;\n\t\t\t\t\tdest++;\n\t\t\t\t\tsrc++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\n\n\t// ok now the hard part\n\n\t// make them 16.16\n\tif ( ABS(Deltax) < ABS(Deltay)) { // ok this means we want to walk in y\n\n\t\t// walk in  + x in the src and\n\t\t// walk in  + y in the dest\n\t\tError = 0;\n\t\t// start at left top corner in src and dest\n\n\t\tsx = 0;\n\t\tsy = 0;\n\n\t\tdx = 0;\n\t\tdy = 0;\n\n\t\tdest = MAKE_PTR(destvp, rx + dx, ry + dy);\n\n\t\tsrc = MAKE_PTR(srcvp, x + sx, y + sy);\n\n\t\t// this gets added to error each inc of x\n\t\t// when error is > 1 then inc y!\n\t\tint xinc = 1;\n\t\tif (Deltax < 0) {\n\t\t\tDeltax = -Deltax;\n\t\t\txinc = -1;\n\t\t}\n\t\tint yinc = 1;\n\t\tint yinc1 = 1;\n\t\tif (Deltay < 0) {\n\t\t\tDeltay = - Deltay;\n\t\t\tbuffwid2 = - buffwid2;\n\t\t}\n\t\tDecimal = ( Deltax << shift) / Deltay ;\n\t\t// walk in X\n\n\t\tint Deltax2 = Deltax << shift;\n\t\tint Deltay2 = Deltay << shift;\n\n\t\t// this is the ratio between the source height and the dest height\n\t\t// as the rectangle rotates the height and width change\n\t\tint DeltaH = (w << shift) / Deltay;\n\t\tint Error2 = 0;\n\t\tsy = 0;\n\t\tfor (int r = 0; r< h ;r++) {\n\t\t\t// now we walk across the top calculating each rotated point\n\t\t\t// along the side\n\t\t\t// the use delta formula to walk in x and y in destination space\n\t\t\t// always walking in the x in the source!\n\t\t\t// figure out rotated location to start in dest\n\t\t\trx = ( ( (sx - halfws) * ca) - ( (sy - halfhs) * sa) ) >> shift;\n\t\t\trx += halfwd;\n\t\t\try = ( ( (sx - halfws) * sa) + ( (sy - halfhs) * ca) ) >> shift;\n\t\t\try += halfhd;\n\n\t\t\t// this is the end point of the line\n\n\t\t\tint y2 = ( ( ((w) - halfws) * sa) + ( (sy - halfhs) * ca) ) >> shift;\n\t\t\ty2 += halfhd;\n\n\t\t\t// length of line\n\n\t\t\tint diff = ABS(y2 - ry);\n\n\t\t\t// if walking backwards reveres diff to reflect sign\n\n\t\t\tsrc = MAKE_PTR(srcvp, x, y + sy);\n\n\t\t\tdest = MAKE_PTR(destvp, rx, ry);\n\n\t\t\tError = 0;\n\t\t\tError2 = 0;\n\t\t\tchar * baseptr = src;\n\t\t\t// while walking line\n\t\t\twhile (diff--) {\n\t\t\t\tchar c = *src;\n\t\t\t\t// transparency\n\t\t\t\tif (c)\n\t\t\t\t\t*dest = *src;\n\t\t\t\tError2 += DeltaH;\n\t\t\t\tdest += buffwid2;\n\t\t\t\tError += Decimal;\n\t\t\t\tsrc = baseptr + (Error2 >> shift) ;\n\t\t\t\t// this is time to inc x in src y in dest\n\t\t\t\tif (Error >= fixpoint1) {\n\t\t\t\t\tError -= fixpoint1;\n\t\t\t\t\tif (*src)\n\t\t\t\t\t\t*dest = *src;\n\t\t\t\t\tdest += xinc;\n\t\t\t\t}\n\t\t\t}\n\t\t\tsy += yinc;\n\t\t}\n\t\treturn 0;\n\t} else { // else we walk in X\n\t\tint lasterror = 0;\n\t\tError = 0;\n\t\t// start at left top corner in src and dest\n\n\t\tsx = 0;\n\t\tsy = 0;\n\n\t\tdx = 0;\n\t\tdy = 0;\n\n\t\tdest = MAKE_PTR(destvp, rx + dx, ry + dy);\n\n\t\tsrc = MAKE_PTR(srcvp, x + sx, y + sy);\n\n\t\t// this gets added to error each inc of x\n\t\t// when error is > 1 then inc y!\n\t\tint xinc = 1;\n\t\tif (Deltax < 0) {\n\t\t\tDeltax = -Deltax;\n\t\t\txinc = -1;\n\t\t}\n\t\tint yinc = 1;\n\t\tif (Deltay < 0) {\n\t\t\tDeltay = - Deltay;\n\t\t\tbuffwid2 = - buffwid2;\n\t\t\tsy = sy + h - 1;\n\t\t\tyinc = -1;\n\t\t}\n\n\n\t\tDecimal = ( Deltay << shift) / Deltax ;\n\t\t// walk in X\n\n\t\tint Deltax2 = Deltax << shift;\n\t\tint Deltay2 = Deltay << shift;\n\n\t\t// this is the ratios between the source width and the dest width\n\t\t// as the rectangle rotates the actual size changes!\n\n\t\tint DeltaW = (w << shift) / Deltax;\n\t\tint Error2 = 0;\n\t\tfor (int r = 0; r< h ;r++) {\n\t\t\tsx = 0;\n\n\t\t\t// now we walk across the side calculating each rotated point\n\t\t\t// along the side\n\t\t\t// the use delta formula to walk in x and y in destination space\n\t\t\t// always walking in the x in the source!\n\t\t\t// figure out rotated location to start\n\n\t\t\trx = ( ( (sx - halfws) * ca) - ( (sy - halfhs) * sa) ) >> shift;\n\t\t\trx += halfwd;\n\t\t\try = ( ( (sx - halfws) * sa) + ( (sy - halfhs) * ca) ) >> shift;\n\t\t\try += halfhd;\n\t\t\t// this is the other side of the box\n\n\t\t\tint x2 = ( ( ((sx + w) - halfws) * ca) - ( (sy - halfhs) * sa) ) >> shift;\n\n\t\t\tx2 += halfwd;\n\n\t\t\tint diff = x2 - rx;\n\n\n\t\t\tdx = 0;\n\t\t\tdy = 0;\n\n\t\t\tif (xinc == -1) {\n\t\t\t\tdiff = -diff;\n\t\t\t}\n\n\t\t\tsrc = MAKE_PTR(srcvp, x + sx, y + sy);\n\n\t\t\tdest = MAKE_PTR(destvp, rx + dx, ry + dy);\n\t\t\tError = 0;\n\t\t\tError2 = 0;\n\t\t\tchar * baseptr = src;\n\n\t\t\twhile (diff--) {\n\t\t\t\tchar c = *src;\n\t\t\t\t// transparency\n\t\t\t\tif (c)\n\t\t\t\t\t*dest = *src;\n\t\t\t\tError2 += DeltaW;\n \t\t\t\trx++;\n\t\t\t\tdest += xinc;\n\t\t\t\tError += Decimal;\n\t\t\t\tsrc = baseptr + (Error2 >> shift);\n\t\t\t\tif (Error >= fixpoint1) {\n\t\t\t\t\tError -= fixpoint1;\n\t\t\t\t\tif (*src)\n\t\t\t\t\t\t*dest = *src;\n\t\t\t\t\tdest += buffwid2;\n\t\t\t\t}\n\t\t\t}\n\t\t\tsy += yinc;\n\t\t}\n\t}\n\treturn 0;\n}\n"
  },
  {
    "path": "CODE/ROTBMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n// list of 256 sines\n\n#define MAKE_PTR(vp,x,y) (char *) (vp->Get_Offset() + ((y) * (vp->Get_Width() + vp->Get_XAdd())) + (x))\n#define MAKE_PTR2(vp,x,y) (char *) (vp->Get_Offset() + (((y)<<1) * (vp->Get_Width() + vp->Get_XAdd())) + ((x)<<1))\n\n#ifndef WIN32\nclass BitmapClass\n{\n\tpublic:\n\t\tBitmapClass(int w, int h, unsigned char * data) :\n\t\t\tWidth(w), Height(h), Data(data) {};\n\n\t\tint Width;\n\t\tint Height;\n\t\tunsigned char * Data;\n};\n\nclass TPoint2D\n{\n\tpublic:\n\t\tTPoint2D(int xx, int yy) : x(xx), y(yy) {};\n\t\tTPoint2D(void) : x(0), y(0) {};\n\n\t\tint x;\n\t\tint y;\n};\n#endif\n\n\nlong Cos256[] = {\n     128,     127,     127,     127,     127,     127,     126,     126,\n     125,     124,     124,     123,     122,     121,     120,     119,\n     118,     116,     115,     114,     112,     111,     109,     107,\n     106,     104,     102,     100,      98,      96,      94,      92,\n      90,      87,      85,      83,      80,      78,      75,      73,\n      70,      68,      65,      62,      59,      57,      54,      51,\n      48,      45,      42,      39,      36,      33,      30,      27,\n      24,      21,      18,      14,      11,       8,       5,       2,\n       0,      -3,      -7,     -10,     -13,     -16,     -19,     -22,\n     -25,     -28,     -31,     -35,     -38,     -41,     -44,     -46,\n     -49,     -52,     -55,     -58,     -61,     -63,     -66,     -69,\n     -72,     -74,     -77,     -79,     -82,     -84,     -86,     -89,\n     -91,     -93,     -95,     -97,     -99,    -101,    -103,    -105,\n    -107,    -108,    -110,    -112,    -113,    -114,    -116,    -117,\n    -118,    -119,    -120,    -121,    -122,    -123,    -124,    -125,\n    -125,    -126,    -126,    -127,    -127,    -127,    -127,    -127,\n    -127,    -127,    -127,    -127,    -127,    -126,    -126,    -125,\n    -125,    -124,    -123,    -122,    -121,    -120,    -119,    -118,\n    -117,    -116,    -114,    -113,    -112,    -110,    -108,    -107,\n    -105,    -103,    -101,     -99,     -97,     -95,     -93,     -91,\n     -89,     -86,     -84,     -82,     -79,     -77,     -74,     -72,\n     -69,     -66,     -64,     -61,     -58,     -55,     -52,     -49,\n     -46,     -44,     -41,     -38,     -35,     -31,     -28,     -25,\n     -22,     -19,     -16,     -13,     -10,      -7,      -3,       0,\n       2,       5,       8,      11,      14,      18,      21,      24,\n      27,      30,      33,      36,      39,      42,      45,      48,\n      51,      54,      57,      59,      62,      65,      68,      70,\n      73,      75,      78,      80,      83,      85,      87,      90,\n      92,      94,      96,      98,     100,     102,     104,     106,\n     107,     109,     111,     112,     114,     115,     116,     118,\n     119,     120,     121,     122,     123,     124,     124,     125,\n     126,     126,     127,     127,     127,     127,     127,     127,\n};\nlong Sin256[] = {\n       0,       3,       6,       9,      12,      15,      18,      21,\n      25,      28,      31,      34,      37,      40,      43,      46,\n      49,      52,      54,      57,      60,      63,      66,      68,\n      71,      73,      76,      79,      81,      83,      86,      88,\n      90,      92,      95,      97,      99,     101,     103,     104,\n     106,     108,     110,     111,     113,     114,     115,     117,\n     118,     119,     120,     121,     122,     123,     124,     125,\n     125,     126,     126,     127,     127,     127,     127,     127,\n     127,     127,     127,     127,     127,     126,     126,     125,\n     125,     124,     123,     123,     122,     121,     120,     119,\n     117,     116,     115,     113,     112,     110,     109,     107,\n     105,     104,     102,     100,      98,      96,      94,      91,\n      89,      87,      85,      82,      80,      77,      75,      72,\n      70,      67,      64,      61,      59,      56,      53,      50,\n      47,      44,      41,      38,      35,      32,      29,      26,\n      23,      20,      17,      14,      11,       7,       4,       1,\n      -1,      -4,      -7,     -11,     -14,     -17,     -20,     -23,\n     -26,     -29,     -32,     -35,     -38,     -41,     -44,     -47,\n     -50,     -53,     -56,     -59,     -61,     -64,     -67,     -70,\n     -72,     -75,     -77,     -80,     -82,     -85,     -87,     -89,\n     -91,     -94,     -96,     -98,    -100,    -102,    -104,    -105,\n    -107,    -109,    -110,    -112,    -113,    -115,    -116,    -117,\n    -119,    -120,    -121,    -122,    -123,    -123,    -124,    -125,\n    -125,    -126,    -126,    -127,    -127,    -127,    -127,    -127,\n    -127,    -127,    -127,    -127,    -127,    -126,    -126,    -125,\n    -125,    -124,    -123,    -122,    -121,    -120,    -119,    -118,\n    -117,    -115,    -114,    -113,    -111,    -110,    -108,    -106,\n    -104,    -103,    -101,     -99,     -97,     -95,     -92,     -90,\n     -88,     -86,     -83,     -81,     -79,     -76,     -73,     -71,\n     -68,     -66,     -63,     -60,     -57,     -54,     -52,     -49,\n     -46,     -43,     -40,     -37,     -34,     -31,     -28,     -25,\n     -21,     -18,     -15,     -12,      -9,      -6,      -3,       0,\n};\n"
  },
  {
    "path": "CODE/RULES.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RULES.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RULES.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/12/96                                                     *\n *                                                                                             *\n *                  Last Update : September 10, 1996 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Difficulty_Get -- Fetch the difficulty bias values.                                       *\n *   RulesClass::AI -- Processes the AI control constants from the database.                   *\n *   RulesClass::General -- Process the general main game rules.                               *\n *   RulesClass::Heap_Maximums -- Fetch and process the heap override values.                  *\n *   RulesClass::IQ -- Fetches the IQ control values from the INI database.                    *\n *   RulesClass::Land_Types -- Inits the land type values.                                     *\n *   RulesClass::MPlayer -- Fetch and process the multiplayer default settings.                *\n *   RulesClass::Powerups -- Process the powerup values from the database.                     *\n *   RulesClass::Process -- Fetch the bulk of the rule data from the control file.             *\n *   RulesClass::Recharge -- Process the super weapon recharge statistics.                     *\n *   RulesClass::RulesClass -- Default constructor for rules class object.                     *\n *   RulesClass::Themes -- Fetches the theme control values from the INI database.             *\n *   Techno_Get -- Get rule data common for all techno type objects.                           *\n *   _Scale_To_256 -- Scales a 1..100 number into a 1..255 number.                             *\n *   RulesClass::Difficulty -- Fetch the various difficulty group settings.                    *\n *   RulesClass::Objects -- Fetch all the object characteristic values.                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n#include\t\"vortex.h\"\n\n\n/***********************************************************************************************\n * _Scale_To_256 -- Scales a 1..100 number into a 1..255 number.                               *\n *                                                                                             *\n *    This is a helper routine that will take a decimal percentage number and convert it       *\n *    into a game based fixed point number.                                                    *\n *                                                                                             *\n * INPUT:   val   -- Decimal percent number to convert.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with the decimal percent number converted to a game fixed point number.    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic inline int _Scale_To_256(int val)\n{\n\tval = fixed(100, 256) * val;\n\tval = min(val, 255);\n\treturn(val);\n}\n\n\n/***********************************************************************************************\n * RulesClass::RulesClass -- Default constructor for rules class object.                       *\n *                                                                                             *\n *    This is the default constructor for the rules class object. Although it initializes the  *\n *    rule data with default values, it is expected that they will all be overridden by the    *\n *    rules control file.                                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRulesClass::RulesClass(void) :\n\tTurboBoost(\"1.5\"),\n\tAttackInterval(3),\n\tAttackDelay(5),\n\tPowerEmergencyFraction(fixed::_3_4),\n\tBadgerBombCount(1),\n\tAirstripRatio(\".12\"),\n\tAirstripLimit(5),\n\tHelipadRatio(\".12\"),\n\tHelipadLimit(5),\n\tTeslaRatio(\".16\"),\n\tTeslaLimit(10),\n\tAARatio(\".14\"),\n\tAALimit(10),\n\tDefenseRatio(\".5\"),\n\tDefenseLimit(40),\n\tWarRatio(\".1\"),\n\tWarLimit(2),\n\tBarracksRatio(\".16\"),\n\tBarracksLimit(2),\n\tRefineryLimit(4),\n\tRefineryRatio(\".16\"),\n\tBaseSizeAdd(3),\n\tPowerSurplus(50),\n\tInfantryReserve(2000),\n\tInfantryBaseMult(2),\n\tChronoDuration(3),\n\tWaterCrateChance(\".2\"),\n\tSoloCrateMoney(2000),\n\tGPSTechLevel(0),\n\tUnitCrateType(UNIT_NONE),\n\tPatrolTime(\".016\"),\n\tTeamDelay(\".6\"),\n\tCloakDelay(0),\n\tGameSpeedBias(1),\n\tNervousBias(1),\n\tVortexRange(10*CELL_LEPTON_W),\n\tVortexSpeed((MPHType)10),\n\tVortexDamage(200),\n\tVortexChance(\".2\"),\n\tExplosionSpread(fixed::_1_2),\n\tSupressRadius(CELL_LEPTON_W),\n\tParaInfantryTechLevel(10),\n\tSpyPlaneTechLevel(10),\n\tParaBombTechLevel(10),\n\tMaxIQ(5),\n\tIQSuperWeapons(4),\n\tIQProduction(5),\n\tIQGuardArea(4),\n\tIQRepairSell(3),\n\tIQCrush(2),\n\tIQScatter(3),\n\tIQContentScan(4),\n\tIQAircraft(4),\n\tIQHarvester(3),\n\tIQSellBack(2),\n\tSilverCrate(CRATE_HEAL_BASE),\n\tWoodCrate(CRATE_MONEY),\n\tWaterCrate(CRATE_MONEY),\n\tCrateMinimum(1),\n\tCrateMaximum(255),\n\tLZScanRadius(16*CELL_LEPTON_W),\n\tMPDefaultMoney(3000),\n\tMPMaxMoney(10000),\n\tIsMPShadowGrow(true),\n\tIsMPBasesOn(true),\n\tIsMPTiberiumGrow(true),\n\tIsMPCrates(true),\n\tIsMPAIPlayers(false),\n\tIsMPCaptureTheFlag(false),\n\tDropZoneRadius(4*CELL_LEPTON_W),\n\tMessageDelay(\".6\"),\n\tSavourDelay(\".03\"),\n\tAVMineDamage(1200),\n\tAPMineDamage(1000),\n\tMaxPlayers(8),\n\tBaseDefenseDelay(fixed::_1_4),\n\tSuspendPriority(20),\n\tSuspendDelay(2),\n\tSurvivorFraction(fixed::_1_2),\n\tReloadRate(\".05\"),\n\tAutocreateTime(5),\n\tBuildupTime(\".05\"),\n\tOreDumpRate(2),\n\tAtomDamage(1000),\n\tIsComputerParanoid(true),\n\tIsCurleyShuffle(false),\n\tIsFlashLowPower(true),\n\tIsCompEasyBonus(true),\n\tIsFineDifficulty(false),\n\tIsExplosiveHarvester(false),\n\tIsHealthBar(true),\n\tIsMCVDeploy(false),\n\tIsAllyReveal(true),\n\tIsSeparate(false),\n\tIsTreeTarget(false),\n\tIsMineAware(true),\n\tIsTGrowth(true),\n\tIsTSpread(true),\n\tIsNamed(false),\n\tIsAutoCrush(false),\n\tIsSmartDefense(false),\n\tIsScatter(false),\n\tIsChronoKill(true),\n\tProneDamageBias(fixed::_1_2),\n\tQuakeDamagePercent(\".33\"),\n\tQuakeChance(\".2\"),\n\tGrowthRate(2),\n\tShroudRate(4),\n\tCrateTime(10),\n\tTimerWarning(2),\n\tChronoTechLevel(1),\n\tSonarTime(14),\n\tChronoTime(3),\n\tParaBombTime(14),\n\tParaInfantryTime(2),\n\tParaSaboteurTime(14),\n\tSpyTime(2),\n\tIronCurtainTime(14),\n\tGPSTime(1),\n\tNukeTime(14),\n\tSpeakDelay(2),\n\tDamageDelay(1),\n\tGravity(3),\n\tGapShroudRadius(10),\n\tGapRegenInterval(\".1\"),\n\tRadarJamRadius(10*CELL_LEPTON_W),\n\tIncoming(MPH_IMMOBILE),\n\tMinDamage(1),\n\tMaxDamage(1000),\n\tRepairStep(5),\n\tRepairPercent(fixed::_1_4),\n\tURepairStep(5),\n\tURepairPercent(fixed::_1_4),\n\tRepairRate(\".016\"),\n\tConditionGreen(1),\n\tConditionYellow(fixed::_1_2),\n\tConditionRed(fixed::_1_4),\n\tRandomAnimateTime(\".083\"),\n\tBailCount(28),\n\tGoldValue(35),\n\tGemValue(110),\n\tAircraftMax(100),\n\tAnimMax(100),\n\tBuildingMax(500),\n\tBulletMax(40),\n\tFactoryMax(20),\n\tInfantryMax(500),\n\tOverlayMax(1),\n\tSmudgeMax(1),\n\tTeamMax(60),\n\tTeamTypeMax(60),\n\tTemplateMax(1),\n\tTerrainMax(500),\n\tTriggerMax(60),\n\tUnitMax(500),\n\tVesselMax(100),\n\tProjectileMax(20),\n\tWeaponMax(20),\n\tWarheadMax(20),\n\tTrigTypeMax(80),\n\tCloseEnoughDistance(0x0280),\n\tStrayDistance(0x0200),\n\tCrushDistance(0x0180),\n\tCrateRadius(0x0280),\n\tHomingScatter(0x0200),\n\tBallisticScatter(0x0100),\n\tRefundPercent(fixed::_1_2),\n\tIronCurtainDuration(fixed::_1_2),\n\tBridgeStrength(1000),\n\tBuildSpeedBias(1),\n\tC4Delay(\".03\"),\n\tRepairThreshhold(1000),\n\tPathDelay(\".016\"),\n\tMovieTime(fixed::_1_4),\n\tTiberiumShortScan(0x0600),\n\tTiberiumLongScan(0x2000)\n{\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tNewUnitsEnabled = SecretUnitsEnabled = 0;\n\tMTankDistance = 30;\n\tQuakeUnitDamage = 0x080;\n\tQuakeBuildingDamage = 0x040;\n\tQuakeInfantryDamage = 0;\n\tQuakeDelay      = 120;\n\tChronoTankDuration = 0x300;\n#ifdef FIXIT_ENGINEER\t//\tchecked - ajw 9/28/98\n\tEngineerDamage=(fixed)1 / (fixed)3;\t// Amount of damage an engineer does\n\tEngineerCaptureLevel=ConditionRed;\t// Building damage level before engineer can capture\n#endif\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tCarrierLaunchDelay = 60;\n#endif\n#endif\n}\n\n\n/***********************************************************************************************\n * Difficulty_Get -- Fetch the difficulty bias values.                                         *\n *                                                                                             *\n *    This will fetch the difficulty bias values for the section specified.                    *\n *                                                                                             *\n * INPUT:   ini   -- Reference the INI database to fetch the values from.                      *\n *                                                                                             *\n *          diff  -- Reference to the difficulty class object to fill in with the values.      *\n *                                                                                             *\n *          section  -- The section identifier to lift the values from.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Difficulty_Get(CCINIClass & ini, DifficultyClass & diff, char const * section)\n{\n\tif (ini.Is_Present(section)) {\n\t\tdiff.FirepowerBias = ini.Get_Fixed(section, \"FirePower\", 1);\n\t\tdiff.GroundspeedBias = ini.Get_Fixed(section, \"Groundspeed\", 1);\n\t\tdiff.AirspeedBias = ini.Get_Fixed(section, \"Airspeed\", 1);\n\t\tdiff.ArmorBias = ini.Get_Fixed(section, \"Armor\", 1);\n\t\tdiff.ROFBias = ini.Get_Fixed(section, \"ROF\", 1);\n\t\tdiff.CostBias = ini.Get_Fixed(section, \"Cost\", 1);\n\t\tdiff.RepairDelay = ini.Get_Fixed(section, \"RepairDelay\", \".02\");\n\t\tdiff.BuildDelay = ini.Get_Fixed(section, \"BuildDelay\", \".03\");\n\t\tdiff.IsBuildSlowdown = ini.Get_Bool(section, \"BuildSlowdown\", false);\n\t\tdiff.BuildSpeedBias = ini.Get_Fixed(section, \"BuildTime\", 1);\n\t\tdiff.IsWallDestroyer = ini.Get_Bool(section, \"DestroyWalls\", true);\n\t\tdiff.IsContentScan = ini.Get_Bool(section, \"ContentScan\", false);\n\t}\n}\n\n\n/***********************************************************************************************\n * RulesClass::Process -- Fetch the bulk of the rule data from the control file.               *\n *                                                                                             *\n *    This routine will fetch the rule data from the control file.                             *\n *                                                                                             *\n * INPUT:   file  -- Reference to the rule file to process.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the rule file processed?                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::Process(CCINIClass & ini)\n{\n\tBStart(BENCH_RULES);\n\n\tGeneral(ini);\n\tMPlayer(ini);\n\tRecharge(ini);\n\tHeap_Maximums(ini);\n\tAI(ini);\n\tPowerups(ini);\n\tLand_Types(ini);\n\tThemes(ini);\n\tIQ(ini);\n\tObjects(ini);\n\tDifficulty(ini);\n\n\tBEnd(BENCH_RULES);\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RulesClass::General -- Process the general main game rules.                                 *\n *                                                                                             *\n *    This fetches the control constants uses for regular game processing. Any game behavior   *\n *    controlling values that don't properly fit in any of the other catagories will be        *\n *    stored here.                                                                             *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the database to fetch the values from.                       *\n *                                                                                             *\n * OUTPUT:  bool; Was the general section found and processed?                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::General(CCINIClass & ini)\n{\n\tstatic char const * const GENERAL = \"General\";\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tstatic char const * const AFTERMATH = \"Aftermath\";\n\n\tif(ini.Is_Present(AFTERMATH)) {\n//debugprint( \"NewUnitsEnabled previously %i\\n\", NewUnitsEnabled );\n\t\tNewUnitsEnabled = ini.Get_Int(AFTERMATH, \"NewUnitsEnabled\", 0);\n//debugprint( \"NewUnitsEnabled set to %i by Rules\\n\", NewUnitsEnabled );\n\t\tMTankDistance = ini.Get_Int(AFTERMATH,\"MTankDistance\",MTankDistance);\n\t\tQuakeUnitDamage = ini.Get_Fixed(AFTERMATH, \"QuakeUnitDamage\", QuakeUnitDamage);\n\t\tQuakeBuildingDamage = ini.Get_Fixed(AFTERMATH, \"QuakeBuildingDamage\", QuakeBuildingDamage);\n\t\tQuakeInfantryDamage = ini.Get_Int(AFTERMATH,\"QuakeInfantryDamage\",QuakeInfantryDamage);\n\t\tQuakeDelay      = ini.Get_Int(AFTERMATH,\"QuakeDelay\",QuakeDelay);\n\t\tChronoTankDuration = ini.Get_Fixed(AFTERMATH, \"ChronoTankDuration\", ChronoTankDuration);\n//Mono_Set_Cursor(0,0);Mono_Printf(\"Chrono duration: %08x \\n\",ChronoTankDuration);Keyboard->Get();Keyboard->Get();\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\tCarrierLaunchDelay = ini.Get_Int(AFTERMATH,\"CarrierLaunchDelay\",120);\n#endif\n#ifdef FIXIT_ENGINEER\t//\tchecked - ajw 9/28/98\n\t\t//\tEngineer changing fields were specifically left out of Aftrmath.ini, thus these values are not found to set. ajw\n\t\t//\tImplies interesting security hole if user creates a separate Aftrmath.ini file!\n\t\tEngineerDamage = ini.Get_Fixed(AFTERMATH, \"EngineerDamage\", EngineerDamage);\t// Amount of damage an engineer does\n\t\tEngineerCaptureLevel = ini.Get_Fixed(AFTERMATH, \"EngineerCaptureLevel\", EngineerCaptureLevel);\t// Building damage level before engineer can capture\n#endif\n\t}\n\n#endif\n\n\tif (ini.Is_Present(GENERAL)) {\n\t\tTurboBoost = ini.Get_Fixed(GENERAL, \"TurboBoost\", TurboBoost);\n\t\tBadgerBombCount = ini.Get_Int(GENERAL, \"BadgerBombCount\", BadgerBombCount);\n\t\tIsCurleyShuffle = ini.Get_Bool(GENERAL, \"CurleyShuffle\", IsCurleyShuffle);\n\t\tIsFlashLowPower = ini.Get_Bool(GENERAL, \"FlashLowPower\", IsFlashLowPower);\n\t\tIsChronoKill = ini.Get_Bool(GENERAL, \"ChronoKillCargo\", IsChronoKill);\n\t\tChronoDuration = ini.Get_Fixed(GENERAL, \"ChronoDuration\", ChronoDuration);\n\t\tIsFineDifficulty = ini.Get_Bool(GENERAL, \"FineDiffControl\", IsFineDifficulty);\n\t\tWaterCrateChance = ini.Get_Fixed(GENERAL, \"WaterCrateChance\", WaterCrateChance);\n\t\tSoloCrateMoney = ini.Get_Int(GENERAL, \"SoloCrateMoney\", SoloCrateMoney);\n\t\tParaBombTechLevel = ini.Get_Int(GENERAL, \"ParabombTech\", ParaBombTechLevel);\n\t\tGPSTechLevel = ini.Get_Int(GENERAL, \"GPSTechLevel\", GPSTechLevel);\n\t\tUnitCrateType = ini.Get_UnitType(GENERAL, \"UnitCrateType\", UnitCrateType);\n\t\tIsExplosiveHarvester = ini.Get_Fixed(GENERAL, \"OreExplosive\", IsExplosiveHarvester);\n\t\tGapRegenInterval = ini.Get_Fixed(GENERAL, \"GapRegenInterval\", GapRegenInterval);\n\t\tTeamDelay = ini.Get_Fixed(GENERAL, \"TeamDelay\", TeamDelay);\n\t\tCloakDelay = ini.Get_Fixed(GENERAL, \"SubmergeDelay\", CloakDelay);\n\t\tGameSpeedBias = ini.Get_Fixed(GENERAL, \"GameSpeedBias\", GameSpeedBias);\n\t\tNervousBias = ini.Get_Fixed(GENERAL, \"BaseBias\", NervousBias);\n\t\tExplosionSpread = ini.Get_Fixed(GENERAL, \"ExpSpread\", ExplosionSpread);\n\t\tSupressRadius = ini.Get_Lepton(GENERAL, \"FireSupress\", SupressRadius);\n\t\tParaInfantryTechLevel = ini.Get_Int(GENERAL, \"ParaTech\", ParaInfantryTechLevel);\n\t\tSpyPlaneTechLevel = ini.Get_Int(GENERAL, \"SpyPlaneTech\", SpyPlaneTechLevel);\n\t\tSilverCrate = ini.Get_CrateType(GENERAL, \"SilverCrate\", SilverCrate);\n\t\tWoodCrate = ini.Get_CrateType(GENERAL, \"WoodCrate\", WoodCrate);\n\t\tWaterCrate = ini.Get_CrateType(GENERAL, \"WaterCrate\", WaterCrate);\n\t\tCrateMinimum = ini.Get_Int(GENERAL, \"CrateMinimum\", CrateMinimum);\n\t\tCrateMaximum = ini.Get_Int(GENERAL, \"CrateMaximum\", CrateMaximum);\n\t\tIsScatter = ini.Get_Bool(GENERAL, \"PlayerScatter\", IsScatter);\n\t\tIsSmartDefense = ini.Get_Bool(GENERAL, \"PlayerReturnFire\", IsSmartDefense);\n\t\tIsAutoCrush = ini.Get_Bool(GENERAL, \"PlayerAutoCrush\", IsAutoCrush);\n\t\tIsNamed = ini.Get_Bool(GENERAL, \"NamedCivilians\", IsNamed);\n\t\tIsTGrowth = ini.Get_Bool(GENERAL, \"OreGrows\", IsTGrowth);\n\t\tIsTSpread = ini.Get_Bool(GENERAL, \"OreSpreads\", IsTSpread);\n\t\tIsMineAware = ini.Get_Bool(GENERAL, \"MineAware\", IsMineAware);\n\t\tIsTreeTarget = ini.Get_Bool(GENERAL, \"TreeTargeting\", IsTreeTarget);\n\t\tIsSeparate = ini.Get_Bool(GENERAL, \"SeparateAircraft\", IsSeparate);\n\t\tDropZoneRadius = ini.Get_Lepton(GENERAL, \"DropZoneRadius\", DropZoneRadius);\n\t\tMessageDelay = ini.Get_Fixed(GENERAL, \"MessageDelay\", MessageDelay);\n\t\tSavourDelay = ini.Get_Fixed(GENERAL, \"SavourDelay\", SavourDelay);\n\t\tAVMineDamage = ini.Get_Int(GENERAL, \"AVMineDamage\", AVMineDamage);\n\t\tAPMineDamage = ini.Get_Int(GENERAL, \"APMineDamage\", APMineDamage);\n\t\tBaseDefenseDelay = ini.Get_Fixed(GENERAL, \"BaseDefenseDelay\", BaseDefenseDelay);\n\t\tSuspendPriority = ini.Get_Int(GENERAL, \"SuspendPriority\", SuspendPriority);\n\t\tSuspendDelay = ini.Get_Fixed(GENERAL, \"SuspendDelay\", SuspendDelay);\n\t\tSurvivorFraction = ini.Get_Fixed(GENERAL, \"SurvivorRate\", SurvivorFraction);\n\t\tRadarJamRadius = ini.Get_Lepton(GENERAL, \"RadarJamRadius\", RadarJamRadius);\n\t\tReloadRate = ini.Get_Fixed(GENERAL, \"ReloadRate\", ReloadRate);\n\t\tRandomAnimateTime = ini.Get_Fixed(GENERAL, \"IdleActionFrequency\", RandomAnimateTime);\n\t\tBuildupTime = ini.Get_Fixed(GENERAL, \"BuildupTime\", BuildupTime);\n\t\tOreDumpRate = ini.Get_Int(GENERAL, \"OreTruckRate\", OreDumpRate);\n\t\tAtomDamage = ini.Get_Int(GENERAL, \"AtomDamage\", AtomDamage);\n\t\tBailCount = ini.Get_Int(GENERAL, \"BailCount\", BailCount);\n\t\tBallisticScatter = ini.Get_Lepton(GENERAL, \"BallisticScatter\", BallisticScatter);\n\t\tBridgeStrength = ini.Get_Int(GENERAL, \"BridgeStrength\", BridgeStrength);\n\t\tBuildSpeedBias = ini.Get_Fixed(GENERAL, \"BuildSpeed\", BuildSpeedBias);\n\t\tConditionGreen = 1;\n\t\tConditionRed = ini.Get_Fixed(GENERAL, \"ConditionRed\", ConditionRed);\n\t\tConditionYellow = ini.Get_Fixed(GENERAL, \"ConditionYellow\", ConditionYellow);\n\t\tCrateRadius = ini.Get_Lepton(GENERAL, \"CrateRadius\", CrateRadius);\n\t\tCrushDistance = ini.Get_Lepton(GENERAL, \"Crush\", CrushDistance);\n\t\tDamageDelay = ini.Get_Fixed(GENERAL, \"DamageDelay\", DamageDelay);\n\t\tGapShroudRadius = ini.Get_Int(GENERAL, \"GapRadius\", GapShroudRadius);\n\t\tGemValue = ini.Get_Int(GENERAL, \"GemValue\", GemValue);\n\t\tGoldValue = ini.Get_Int(GENERAL, \"GoldValue\", GoldValue);\n\t\tGravity = ini.Get_Int(GENERAL, \"Gravity\", Gravity);\n\t\tGrowthRate = ini.Get_Fixed(GENERAL, \"GrowthRate\", GrowthRate);\n\t\tHomingScatter = ini.Get_Lepton(GENERAL, \"HomingScatter\", HomingScatter);\n\t\tIncoming = ini.Get_MPHType(GENERAL, \"Incoming\", MPH_IMMOBILE);\n\t\tIronCurtainDuration = ini.Get_Fixed(GENERAL, \"IronCurtain\", IronCurtainDuration);\n\t\tIsAllyReveal = ini.Get_Bool(GENERAL, \"AllyReveal\", IsAllyReveal);\n\t\tIsHealthBar = ini.Get_Bool(GENERAL, \"EnemyHealth\", IsHealthBar);\n\t\tIsMCVDeploy = ini.Get_Bool(GENERAL, \"MCVUndeploy\", IsMCVDeploy);\n\t\tMaxDamage = ini.Get_Int(GENERAL, \"MaxDamage\", MaxDamage);\n\t\tMinDamage = ini.Get_Int(GENERAL, \"MinDamage\", MinDamage);\n\t\tProneDamageBias = ini.Get_Fixed(GENERAL, \"ProneDamage\", ProneDamageBias);\n\t\tQuakeDamagePercent = ini.Get_Fixed(GENERAL, \"QuakeDamage\", QuakeDamagePercent);\n\t\tQuakeChance = ini.Get_Fixed(GENERAL, \"QuakeChance\", QuakeChance);\n\t\tRefundPercent = ini.Get_Fixed(GENERAL, \"RefundPercent\", RefundPercent);\n\t\tRepairPercent = ini.Get_Fixed(GENERAL, \"RepairPercent\", RepairPercent);\n\t\tRepairStep = ini.Get_Int(GENERAL, \"RepairStep\", RepairStep);\n\t\tURepairPercent = ini.Get_Fixed(GENERAL, \"URepairPercent\", URepairPercent);\n\t\tURepairStep = ini.Get_Int(GENERAL, \"URepairStep\", URepairStep);\n\t\tRepairRate = ini.Get_Fixed(GENERAL, \"RepairRate\", RepairRate);\n\t\tShroudRate = ini.Get_Fixed(GENERAL, \"ShroudRate\", ShroudRate);\n\t\tSpeakDelay = ini.Get_Fixed(GENERAL, \"SpeakDelay\", SpeakDelay);\n\t\tStrayDistance = ini.Get_Lepton(GENERAL, \"Stray\", StrayDistance);\n\t\tCloseEnoughDistance = ini.Get_Lepton(GENERAL, \"CloseEnough\", CloseEnoughDistance);\n\t\tTimerWarning = ini.Get_Fixed(GENERAL, \"TimerWarning\", TimerWarning);\n\t\tMovieTime = ini.Get_Fixed(GENERAL, \"MovieTime\", MovieTime);\n\t\tC4Delay = ini.Get_Fixed(GENERAL, \"C4Delay\", C4Delay);\n\t\tChronoTechLevel = ini.Get_Int(GENERAL, \"ChronoTechLevel\", ChronoTechLevel);\n\t\tCrateTime = ini.Get_Fixed(GENERAL, \"CrateRegen\", CrateTime);\n\t\tVortexRange = ini.Get_Lepton(GENERAL, \"VortexRange\", VortexRange);\n\t\tVortexSpeed = MPHType(_Scale_To_256(ini.Get_Int(GENERAL, \"VortexSpeed\", VortexSpeed)));\n\t\tVortexDamage = ini.Get_Int(GENERAL, \"VortexDamage\", VortexDamage);\n\t\tVortexChance = ini.Get_Fixed(GENERAL, \"VortexChance\", VortexChance);\n\n\t\tChronalVortex.Set_Range(VortexRange / CELL_LEPTON_W);\n\t\tChronalVortex.Set_Speed(VortexSpeed);\n\t\tChronalVortex.Set_Damage(VortexDamage);\n\n\t\t//ChronalVortex.Set_Range ( ini.Get_Int (GENERAL, \"VortexRange\", ChronalVortex.Get_Range() ) );\n\t\t//ChronalVortex.Set_Speed ( ini.Get_Int (GENERAL, \"VortexSpeed\", ChronalVortex.Get_Speed() ) );\n\t\t//ChronalVortex.Set_Damage ( ini.Get_Int (GENERAL, \"VortexDamage\", ChronalVortex.Get_Damage() ) );\n\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RulesClass::MPlayer -- Fetch and process the multiplayer default settings.                  *\n *                                                                                             *\n *    This is used to set the default settings for the multiplayer system.                     *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database.                                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the multiplayer default override section found and processed?            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::MPlayer(CCINIClass & ini)\n{\n\tstatic char const * const MPLAYER = \"MultiplayerDefaults\";\n\tif (ini.Is_Present(MPLAYER)) {\n\t\tMPDefaultMoney = ini.Get_Int(MPLAYER, \"Money\", MPDefaultMoney);\n\t\tMPMaxMoney = ini.Get_Int(MPLAYER, \"MaxMoney\", MPMaxMoney);\n\t\tIsMPShadowGrow = ini.Get_Bool(MPLAYER, \"ShadowGrow\", IsMPShadowGrow);\n\t\tIsMPBasesOn = ini.Get_Bool(MPLAYER, \"Bases\", IsMPBasesOn);\n\t\tIsMPTiberiumGrow = ini.Get_Bool(MPLAYER, \"OreGrows\", IsMPTiberiumGrow);\n\t\tIsMPCrates = ini.Get_Bool(MPLAYER, \"Crates\", IsMPCrates);\n\t\tIsMPCaptureTheFlag = ini.Get_Bool(MPLAYER, \"CaptureTheFlag\", IsMPCaptureTheFlag);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RulesClass::Recharge -- Process the super weapon recharge statistics.                       *\n *                                                                                             *\n *    Use this to set the recharge times for the various super weapons available.              *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the database.                                                *\n *                                                                                             *\n * OUTPUT:  bool; Was the recharge section found and processed?                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::Recharge(CCINIClass & ini)\n{\n\tstatic char const * const RECHARGE = \"Recharge\";\n\tif (ini.Is_Present(RECHARGE)) {\n\t\tSonarTime = ini.Get_Fixed(RECHARGE, \"Sonar\", SonarTime);\n\t\tChronoTime = ini.Get_Fixed(RECHARGE, \"Chrono\", ChronoTime);\n\t\tParaBombTime = ini.Get_Fixed(RECHARGE, \"ParaBomb\", ParaBombTime);\n\t\tParaInfantryTime = ini.Get_Fixed(RECHARGE, \"Paratrooper\", ParaInfantryTime);\n\t\tSpyTime = ini.Get_Fixed(RECHARGE, \"SpyPlane\", SpyTime);\n\t\tIronCurtainTime = ini.Get_Fixed(RECHARGE, \"IronCurtain\", IronCurtainTime);\n\t\tGPSTime = ini.Get_Fixed(RECHARGE, \"GPS\", GPSTime);\n\t\tNukeTime = ini.Get_Fixed(RECHARGE, \"Nuke\", NukeTime);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RulesClass::Heap_Maximums -- Fetch and process the heap override values.                    *\n *                                                                                             *\n *    This fetches the maximum heap sizes from the database specified. The heaps will be       *\n *    initialized by this routine as indicated.                                                *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database.                                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the maximum section found and processed?                                 *\n *                                                                                             *\n * WARNINGS:   This process is catastrophic to any data currently existing in the heaps        *\n *             modified. This should only be processed during the game initialization stage.   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::Heap_Maximums(CCINIClass & ini)\n{\n\t/*\n\t**\tHeap maximum values.\n\t*/\n\tstatic char const * const MAXIMUMS = \"Maximums\";\n\tif (ini.Is_Present(MAXIMUMS)) {\n\t\tMaxPlayers = ini.Get_Int(MAXIMUMS, \"Players\", MaxPlayers);\n\t\tAircraftMax = ini.Get_Int(MAXIMUMS, \"Aircraft\", AircraftMax);\n\t\tAnimMax = ini.Get_Int(MAXIMUMS, \"Anim\", AnimMax);\n\t\tBuildingMax = ini.Get_Int(MAXIMUMS, \"Building\", BuildingMax);\n\t\tBulletMax = ini.Get_Int(MAXIMUMS, \"Bullet\", BulletMax);\n\t\tFactoryMax = ini.Get_Int(MAXIMUMS, \"Factory\", FactoryMax);\n\t\tInfantryMax = ini.Get_Int(MAXIMUMS, \"Infantry\", InfantryMax);\n\t\tOverlayMax = ini.Get_Int(MAXIMUMS, \"Overlay\", OverlayMax);\n\t\tSmudgeMax = ini.Get_Int(MAXIMUMS, \"Smudge\", SmudgeMax);\n\t\tTeamMax = ini.Get_Int(MAXIMUMS, \"Team\", TeamMax);\n\t\tTeamTypeMax = ini.Get_Int(MAXIMUMS, \"TeamType\", TeamTypeMax);\n\t\tTemplateMax = ini.Get_Int(MAXIMUMS, \"Template\", TemplateMax);\n\t\tTerrainMax = ini.Get_Int(MAXIMUMS, \"Terrain\", TerrainMax);\n\t\tTriggerMax = ini.Get_Int(MAXIMUMS, \"Trigger\", TriggerMax);\n\t\tUnitMax = ini.Get_Int(MAXIMUMS, \"Unit\", UnitMax);\n\t\tVesselMax = ini.Get_Int(MAXIMUMS, \"Vessel\", VesselMax);\n\t\tProjectileMax = ini.Get_Int(MAXIMUMS, \"Projectile\", ProjectileMax);\n\t\tWeaponMax = ini.Get_Int(MAXIMUMS, \"Weapon\", WeaponMax);\n\t\tWarheadMax = ini.Get_Int(MAXIMUMS, \"Warhead\", WarheadMax);\n\t\tTrigTypeMax = ini.Get_Int(MAXIMUMS, \"TrigType\", TrigTypeMax);\n\t}\n\n\t/*\n\t**\tAny heaps that use the maximums that were just loaded, must\n\t**\tbe initialized as necessary.\n\t*/\n\tWarheads.Set_Heap(WarheadMax);\n\tnew WarheadTypeClass(\"SA\");\n\tnew WarheadTypeClass(\"HE\");\n\tnew WarheadTypeClass(\"AP\");\n\tnew WarheadTypeClass(\"Fire\");\n\tnew WarheadTypeClass(\"HollowPoint\");\n\tnew WarheadTypeClass(\"Super\");\n\tnew WarheadTypeClass(\"Organic\");\n\tnew WarheadTypeClass(\"Nuke\");\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tnew WarheadTypeClass(\"Mechanical\");\n#endif\n\n\tWeapons.Set_Heap(WeaponMax);\n\tnew WeaponTypeClass(\"Colt45\");\n\tnew WeaponTypeClass(\"ZSU-23\");\n\tnew WeaponTypeClass(\"Vulcan\");\n\tnew WeaponTypeClass(\"Maverick\");\n\tnew WeaponTypeClass(\"Camera\");\n\tnew WeaponTypeClass(\"FireballLauncher\");\n\tnew WeaponTypeClass(\"Sniper\");\n\tnew WeaponTypeClass(\"ChainGun\");\n\tnew WeaponTypeClass(\"Pistol\");\n\tnew WeaponTypeClass(\"M1Carbine\");\n\tnew WeaponTypeClass(\"Dragon\");\n\tnew WeaponTypeClass(\"Hellfire\");\n\tnew WeaponTypeClass(\"Grenade\");\n\tnew WeaponTypeClass(\"75mm\");\n\tnew WeaponTypeClass(\"90mm\");\n\tnew WeaponTypeClass(\"105mm\");\n\tnew WeaponTypeClass(\"120mm\");\n\tnew WeaponTypeClass(\"TurretGun\");\n\tnew WeaponTypeClass(\"MammothTusk\");\n\tnew WeaponTypeClass(\"155mm\");\n\tnew WeaponTypeClass(\"M60mg\");\n\tnew WeaponTypeClass(\"Napalm\");\n\tnew WeaponTypeClass(\"TeslaZap\");\n\tnew WeaponTypeClass(\"Nike\");\n\tnew WeaponTypeClass(\"8Inch\");\n\tnew WeaponTypeClass(\"Stinger\");\n\tnew WeaponTypeClass(\"TorpTube\");\n\tnew WeaponTypeClass(\"2Inch\");\n\tnew WeaponTypeClass(\"DepthCharge\");\n\tnew WeaponTypeClass(\"ParaBomb\");\n\tnew WeaponTypeClass(\"DogJaw\");\n\tnew WeaponTypeClass(\"Heal\");\n\tnew WeaponTypeClass(\"SCUD\");\n\tnew WeaponTypeClass(\"Flamer\");\n\tnew WeaponTypeClass(\"RedEye\");\n\n#ifdef FIXIT_ANTS\n\tnew WeaponTypeClass(\"Mandible\");\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tnew WeaponTypeClass(\"PortaTesla\");\n\tnew WeaponTypeClass(\"GoodWrench\");\n\tnew WeaponTypeClass(\"SubSCUD\");\n\tnew WeaponTypeClass(\"TTankZap\");\n\tnew WeaponTypeClass(\"APTusk\");\n\tnew WeaponTypeClass(\"Democharge\");\n#endif\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tnew WeaponTypeClass(\"AirAssault\");\n#endif\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RulesClass::AI -- Processes the AI control constants from the database.                     *\n *                                                                                             *\n *    This will examine the database specified and set the AI override values accordingly.     *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database that holds the AI overrides.                *\n *                                                                                             *\n * OUTPUT:  bool; Was the AI section found and processed?                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::AI(CCINIClass & ini)\n{\n\tstatic char const * const AI = \"AI\";\n\tif (ini.Is_Present(AI)) {\n\t\tAttackInterval = ini.Get_Fixed(AI, \"AttackInterval\", AttackInterval);\n\t\tAttackDelay = ini.Get_Fixed(AI, \"AttackDelay\", AttackDelay);\n\t\tPatrolTime = ini.Get_Fixed(AI, \"PatrolScan\", PatrolTime);\n\t\tRepairThreshhold = ini.Get_Int(AI, \"CreditReserve\", RepairThreshhold);\n\t\tPathDelay = ini.Get_Fixed(AI, \"PathDelay\", PathDelay);\n\t\tTiberiumShortScan = ini.Get_Lepton(AI, \"OreNearScan\", TiberiumShortScan);\n\t\tTiberiumLongScan = ini.Get_Lepton(AI, \"OreFarScan\", TiberiumLongScan);\n\t\tAutocreateTime = ini.Get_Fixed(AI, \"AutocreateTime\", AutocreateTime);\n\t\tInfantryReserve = ini.Get_Int(AI, \"InfantryReserve\", InfantryReserve);\n\t\tInfantryBaseMult = ini.Get_Int(AI, \"InfantryBaseMult\", InfantryBaseMult);\n\t\tPowerSurplus = ini.Get_Int(AI, \"PowerSurplus\", PowerSurplus);\n\t\tBaseSizeAdd = ini.Get_Int(AI, \"BaseSizeAdd\", BaseSizeAdd);\n\t\tRefineryRatio = ini.Get_Fixed(AI, \"RefineryRatio\", RefineryRatio);\n\t\tRefineryLimit = ini.Get_Int(AI, \"RefineryLimit\", RefineryLimit);\n\t\tBarracksRatio = ini.Get_Fixed(AI, \"BarracksRatio\", BarracksRatio);\n\t\tBarracksLimit = ini.Get_Int(AI, \"BarracksLimit\", BarracksLimit);\n\t\tWarRatio = ini.Get_Fixed(AI, \"WarRatio\", WarRatio);\n\t\tWarLimit = ini.Get_Int(AI, \"WarLimit\", WarLimit);\n\t\tDefenseRatio = ini.Get_Fixed(AI, \"DefenseRatio\", DefenseRatio);\n\t\tDefenseLimit = ini.Get_Int(AI, \"DefenseLimit\", DefenseLimit);\n\t\tAARatio = ini.Get_Fixed(AI, \"AARatio\", AARatio);\n\t\tAALimit = ini.Get_Int(AI, \"AALimit\", AALimit);\n\t\tTeslaRatio = ini.Get_Fixed(AI, \"TeslaRatio\", TeslaRatio);\n\t\tTeslaLimit = ini.Get_Int(AI, \"TeslaLimit\", TeslaLimit);\n\t\tHelipadRatio = ini.Get_Fixed(AI, \"HelipadRatio\", HelipadRatio);\n\t\tHelipadLimit = ini.Get_Int(AI, \"HelipadLimit\", HelipadLimit);\n\t\tAirstripRatio = ini.Get_Fixed(AI, \"AirstripRatio\", AirstripRatio);\n\t\tAirstripLimit = ini.Get_Int(AI, \"AirstripLimit\", AirstripLimit);\n\t\tIsCompEasyBonus = ini.Get_Bool(AI, \"CompEasyBonus\", IsCompEasyBonus);\n\t\tIsComputerParanoid = ini.Get_Bool(AI, \"Paranoid\", IsComputerParanoid);\n\t\tPowerEmergencyFraction = ini.Get_Fixed(AI, \"PowerEmergency\", PowerEmergencyFraction);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RulesClass::Powerups -- Process the powerup values from the database.                       *\n *                                                                                             *\n *    This will examine the database and initialize the powerup override values accordingly.   *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database the the powerup values are to be            *\n *                   initialized from.                                                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the powerup section found and processed?                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::Powerups(CCINIClass & ini)\n{\n\tstatic char const * const POWERUPS = \"Powerups\";\n\tif (ini.Is_Present(POWERUPS)) {\n\t\tfor (CrateType crate = CRATE_FIRST; crate < CRATE_COUNT; crate++) {\n\t\t\tchar buffer[128];\n\t\t\tif (ini.Get_String(POWERUPS, CrateNames[crate], \"0,NONE\", buffer, sizeof(buffer))) {\n\n\t\t\t\t/*\n\t\t\t\t**\tShare odds.\n\t\t\t\t*/\n\t\t\t\tchar * token = strtok(buffer, \",\");\n\t\t\t\tif (token) {\n\t\t\t\t\tstrtrim(token);\n\t\t\t\t\tCrateShares[crate] = atoi(token);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAnimation to use.\n\t\t\t\t*/\n\t\t\t\ttoken = strtok(NULL, \",\");\n\t\t\t\tif (token) {\n\t\t\t\t\tstrtrim(token);\n\t\t\t\t\tCrateAnims[crate] = Anim_From_Name(token);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tOptional data number.\n\t\t\t\t*/\n\t\t\t\ttoken = strtok(NULL, \",\");\n\t\t\t\tif (token != NULL) {\n\t\t\t\t\tif (strpbrk(token, \".%\") != NULL) {\n\t\t\t\t\t\tCrateData[crate] = fixed(token) * 256;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstrtrim(token);\n\t\t\t\t\t\tCrateData[crate] = atoi(token);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RulesClass::Land_Types -- Inits the land type values.                                       *\n *                                                                                             *\n *    This will set the land movement attributes from the database specified.                  *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the database that has the land value overrides.              *\n *                                                                                             *\n * OUTPUT:  bool; Was the land type sections found and processed?                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::Land_Types(CCINIClass & ini)\n{\n\t/*\n\t**\tFetch the movement characteristic data for terrain types.\n\t*/\n\tfor (LandType land = LAND_FIRST; land < LAND_COUNT; land++) {\n\t\tstatic char const * _lands[LAND_COUNT] = {\n\t\t\t\"Clear\",\n\t\t\t\"Road\",\n\t\t\t\"Water\",\n\t\t\t\"Rock\",\n\t\t\t\"Wall\",\n\t\t\t\"Ore\",\n\t\t\t\"Beach\",\n\t\t\t\"Rough\",\n\t\t\t\"River\"\n\t\t};\n\n\t\tGroundType * gptr = &Ground[land];\n\n\t\tif (ini.Is_Present(_lands[land])) {\n\t\t\tgptr->Cost[SPEED_FOOT] = Sub_Saturate(ini.Get_Fixed(_lands[land], \"Foot\", 1), 1);\n\t\t\tgptr->Cost[SPEED_TRACK] = Sub_Saturate(ini.Get_Fixed(_lands[land], \"Track\", 1), 1);\n\t\t\tgptr->Cost[SPEED_WHEEL] = Sub_Saturate(ini.Get_Fixed(_lands[land], \"Wheel\", 1), 1);\n\t\t\tgptr->Cost[SPEED_WINGED] = Sub_Saturate(1, 1);\n\t\t\tgptr->Cost[SPEED_FLOAT] = Sub_Saturate(ini.Get_Fixed(_lands[land], \"Float\", 1), 1);\n\t\t\tgptr->Build = ini.Get_Bool(_lands[land], \"Buildable\", false);\n\t\t}\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RulesClass::Themes -- Fetches the theme control values from the INI database.               *\n *                                                                                             *\n *    The musical theme availability is controlled by the scenario and the player's house      *\n *    choice. These controls can be specified in the theme control section of the INI          *\n *    database.                                                                                *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to process.                                 *\n *                                                                                             *\n * OUTPUT:  bool; Was the theme section found and processed?                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::Themes(CCINIClass & ini)\n{\n\tstatic char const * const THEMECONTROL = \"ThemeControl\";\n\n\tif (ini.Is_Present(THEMECONTROL)) {\n\t\tfor (ThemeType theme = THEME_FIRST; theme < THEME_COUNT; theme++) {\n\t\t\tif (ini.Is_Present(THEMECONTROL, Theme.Base_Name(theme))) {\n\n\t\t\t\tchar buffer[128];\n\t\t\t\tint scen = 1;\n\t\t\t\tint owners = HOUSEF_ALLIES | HOUSEF_SOVIET | HOUSEF_OTHERS;\n\n\t\t\t\tini.Get_String(THEMECONTROL, Theme.Base_Name(theme), \"\", buffer, sizeof(buffer));\n\t\t\t\tchar const * token = strtok(buffer, \",\");\n\t\t\t\tif (token != NULL) {\n\t\t\t\t\tscen = atoi(token);\n\t\t\t\t}\n\n\t\t\t\ttoken = strtok(NULL, \",\");\n\t\t\t\tif (token != NULL) {\n\t\t\t\t\towners = Owner_From_Name(token);\n\t\t\t\t}\n\n\t\t\t\tTheme.Set_Theme_Data(theme, scen, owners);\n\t\t\t}\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RulesClass::IQ -- Fetches the IQ control values from the INI database.                      *\n *                                                                                             *\n *    This will scan the database specified and retrieve the IQ control values from it. These  *\n *    IQ control values are what gives the IQ rating meaning. It fundimentally controls how    *\n *    the computer behaves.                                                                    *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to read the IQ controls from.               *\n *                                                                                             *\n * OUTPUT:  bool; Was the IQ section found and processed?                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::IQ(CCINIClass & ini)\n{\n\tstatic char const * const IQCONTROL = \"IQ\";\n\tif (ini.Is_Present(IQCONTROL)) {\n\t\tMaxIQ = ini.Get_Int(IQCONTROL, \"MaxIQLevels\", MaxIQ);\n\t\tIQSuperWeapons = ini.Get_Int(IQCONTROL, \"SuperWeapons\", IQSuperWeapons);\n\t\tIQProduction = ini.Get_Int(IQCONTROL, \"Production\", IQProduction);\n\t\tIQGuardArea = ini.Get_Int(IQCONTROL, \"GuardArea\", IQGuardArea);\n\t\tIQRepairSell = ini.Get_Int(IQCONTROL, \"RepairSell\", IQRepairSell);\n\t\tIQCrush = ini.Get_Int(IQCONTROL, \"AutoCrush\", IQCrush);\n\t\tIQScatter = ini.Get_Int(IQCONTROL, \"Scatter\", IQScatter);\n\t\tIQContentScan = ini.Get_Int(IQCONTROL, \"ContentScan\", IQContentScan);\n\t\tIQAircraft = ini.Get_Int(IQCONTROL, \"Aircraft\", IQAircraft);\n\t\tIQHarvester = ini.Get_Int(IQCONTROL, \"Harvester\", IQHarvester);\n\t\tIQSellBack = ini.Get_Int(IQCONTROL, \"SellBack\", IQSellBack);\n\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RulesClass::Objects -- Fetch all the object characteristic values.                          *\n *                                                                                             *\n *    This will parse the specified INI database and fetch all the object characteristic       *\n *    values specified therein.                                                                *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the ini database to scan.                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::Objects(CCINIClass & ini)\n{\n\t/*\n\t**\tFetch the game object values from the rules file.\n\t*/\n\tfor (int index = 0; index < Warheads.Count(); index++) {\n\t\tWarheads.Ptr(index)->Read_INI(ini);\n\t}\n\n\tfor (int proj = 0; proj < BulletTypes.Count(); proj++) {\n\t\tBulletTypes.Ptr(proj)->Read_INI(ini);\n\t}\n\n\tfor (int windex = 0; windex < Weapons.Count(); windex++) {\n\t\tWeapons.Ptr(windex)->Read_INI(ini);\n\t}\n\n\tfor (int uindex = 0; uindex < UnitTypes.Count(); uindex++) {\n\t\tUnitTypes.Ptr(uindex)->Read_INI(ini);\n\t}\n\n\tfor (int iindex = 0; iindex < InfantryTypes.Count(); iindex++) {\n\t\tInfantryTypes.Ptr(iindex)->Read_INI(ini);\n\t}\n\n\tfor (int vindex = 0; vindex < VesselTypes.Count(); vindex++) {\n\t\tVesselTypes.Ptr(vindex)->Read_INI(ini);\n\t}\n\n\tfor (int aindex = 0; aindex < AircraftTypes.Count(); aindex++) {\n\t\tAircraftTypes.Ptr(aindex)->Read_INI(ini);\n\t}\n\n\tfor (int bindex = 0; bindex < BuildingTypes.Count(); bindex++) {\n\t\tBuildingTypes.Ptr(bindex)->Read_INI(ini);\n\t}\n\n\t/*\n\t**\tFetch the house attribute override values.\n\t*/\n\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\tHouseTypeClass::As_Reference(house).Read_INI(ini);\n\t}\n\n\t/*\n\t**\tFetch the mission control values.\n\t*/\n\tfor (MissionType mission = MISSION_FIRST; mission < MISSION_COUNT; mission++) {\n\t\tMissionControlClass * miss = &MissionControl[mission];\n\t\tmiss->Mission = mission;\n\t\tmiss->Read_INI(ini);\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RulesClass::Difficulty -- Fetch the various difficulty group settings.                      *\n *                                                                                             *\n *    This routine is used to fetch the various group settings for the difficulty levels.      *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database that has the difficulty setting values.     *\n *                                                                                             *\n * OUTPUT:  bool; Was the difficulty section found and processed.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::Difficulty(CCINIClass & ini)\n{\n\tDifficulty_Get(ini, Diff[DIFF_EASY], \"Easy\");\n\tDifficulty_Get(ini, Diff[DIFF_NORMAL], \"Normal\");\n\tDifficulty_Get(ini, Diff[DIFF_HARD], \"Difficult\");\n\treturn(true);\n}\n"
  },
  {
    "path": "CODE/RULES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/RULES.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RULES.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/12/96                                                     *\n *                                                                                             *\n *                  Last Update : May 12, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef RULES_H\n#define RULES_H\n\n#include\t\"ccini.h\"\n\nclass DifficultyClass\n{\n\tpublic:\n\t\tfixed FirepowerBias;\n\t\tfixed GroundspeedBias;\n\t\tfixed AirspeedBias;\n\t\tfixed ArmorBias;\n\t\tfixed ROFBias;\n\t\tfixed CostBias;\n\t\tfixed BuildSpeedBias;\n\n\t\tfixed RepairDelay;\n\t\tfixed BuildDelay;\n\n\t\tunsigned IsBuildSlowdown:1;\n\t\tunsigned IsWallDestroyer:1;\n\t\tunsigned IsContentScan:1;\n};\n\nclass RulesClass {\n\tpublic:\n\n\t\tRulesClass(void);\n\n\t\tbool Process(CCINIClass & file);\n\t\tbool General(CCINIClass & ini);\n\t\tbool MPlayer(CCINIClass & ini);\n\t\tbool Recharge(CCINIClass & ini);\n\t\tbool Heap_Maximums(CCINIClass & ini);\n\t\tbool AI(CCINIClass & ini);\n\t\tbool Powerups(CCINIClass & ini);\n\t\tbool Land_Types(CCINIClass & ini);\n\t\tbool Themes(CCINIClass & ini);\n\t\tbool IQ(CCINIClass & ini);\n\t\tbool Objects(CCINIClass & ini);\n\t\tbool Difficulty(CCINIClass & ini);\n\n\t\t/*\n\t\t**\tThis specifies the turbo boost speed for missiles when they are fired upon\n\t\t**\taircraft and the weapon is specified as having a turbo boost bonus.\n\t\t*/\n\t\tfixed TurboBoost;\n\n\t\t/*\n\t\t**\tThis specifies the average number of minutes between each computer attack.\n\t\t*/\n\t\tfixed AttackInterval;\n\n\t\t/*\n\t\t**\tThis specifies the average minutes delay before the computer will begin\n\t\t**\tits first attack upon the player. The duration is also modified by the\n\t\t**\tdifficulty level.\n\t\t*/\n\t\tfixed AttackDelay;\n\n\t\t/*\n\t\t**\tIf the power ratio falls below this percentage, then a power emergency is\n\t\t**\tin effect. At such times, the computer might decide to sell off some\n\t\t**\tpower hungry buildings in order to alleviate the situation.\n\t\t*/\n\t\tfixed PowerEmergencyFraction;\n\n\t\t/*\n\t\t**\tThe number of badgers that arrive when the parabomb option is used.\n\t\t*/\n\t\tint BadgerBombCount;\n\n\t\t/*\n\t\t**\tThis specifies the percentage of the base (by building quantity) that should\n\t\t**\tbe composed of airstrips.\n\t\t*/\n\t\tfixed AirstripRatio;\n\n\t\t/*\n\t\t**\tLimit the number of airstrips to this amount.\n\t\t*/\n\t\tint AirstripLimit;\n\n\t\t/*\n\t\t**\tThis specifies the percentage of the base (by building quantity) that should\n\t\t**\tbe composed of helipads.\n\t\t*/\n\t\tfixed HelipadRatio;\n\n\t\t/*\n\t\t**\tLimit the number of helipads to this amount.\n\t\t*/\n\t\tint HelipadLimit;\n\n\t\t/*\n\t\t**\tThis specifies the percentage of the base (by building quantity) that should\n\t\t**\tbe composed of Tesla Coils.\n\t\t*/\n\t\tfixed TeslaRatio;\n\n\t\t/*\n\t\t**\tLimit tesla coil production to this maximum.\n\t\t*/\n\t\tint TeslaLimit;\n\n\t\t/*\n\t\t**\tThis specifies the percentage of the base (by building quantity) that should\n\t\t**\tbe composed of anti-aircraft defense.\n\t\t*/\n\t\tfixed AARatio;\n\n\t\t/*\n\t\t**\tLimit anti-aircraft building quantity to this amount.\n\t\t*/\n\t\tint AALimit;\n\n\t\t/*\n\t\t**\tThis specifies the percentage of the base (by building quantity) that should\n\t\t**\tbe composed of defensive structures.\n\t\t*/\n\t\tfixed DefenseRatio;\n\n\t\t/*\n\t\t**\tThis is the limit to the number of defensive building that can be built.\n\t\t*/\n\t\tint DefenseLimit;\n\n\t\t/*\n\t\t**\tThis specifies the percentage of the base (by building quantity) that should\n\t\t**\tbe composed of war factories.\n\t\t*/\n\t\tfixed WarRatio;\n\n\t\t/*\n\t\t**\tWar factories are limited to this quantity for the computer controlled player.\n\t\t*/\n\t\tint WarLimit;\n\n\t\t/*\n\t\t**\tThis specifies the percentage of the base (by building quantity) that should\n\t\t**\tbe composed of infantry producing structures.\n\t\t*/\n\t\tfixed BarracksRatio;\n\n\t\t/*\n\t\t**\tNo more than this many barracks can be built.\n\t\t*/\n\t\tint BarracksLimit;\n\n\t\t/*\n\t\t**\tRefinery building is limited to this many refineries.\n\t\t*/\n\t\tint RefineryLimit;\n\n\t\t/*\n\t\t**\tThis specifies the percentage of the base (by building quantity) that should\n\t\t**\tbe composed of refineries.\n\t\t*/\n\t\tfixed RefineryRatio;\n\n\t\t/*\n\t\t**\tThe computer is limited in the size of the base it can build. It is limited to the\n\t\t**\tsize of the largest human opponent base plus this surplus count.\n\t\t*/\n\t\tint BaseSizeAdd;\n\n\t\t/*\n\t\t**\tIf the power surplus is less than this amount, then the computer will\n\t\t**\tbuild power plants.\n\t\t*/\n\t\tint PowerSurplus;\n\n\t\t/*\n\t\t**\tThe computer will build infantry if their cash reserve is greater than this amount.\n\t\t*/\n\t\tint InfantryReserve;\n\n\t\t/*\n\t\t**\tThis factor is multiplied by the number of buildings in the computer's base and infantry\n\t\t**\tare always built until it matches that number.\n\t\t*/\n\t\tint InfantryBaseMult;\n\n\t\t/*\n\t\t**\tThis specifies the duration that a unit will remain chronoshifted before it\n\t\t**\twill be returned to its starting location.\n\t\t*/\n\t\tfixed ChronoDuration;\n\n\t\t/*\n\t\t**\tPercent chance that a water crate will be generated instead of a land\n\t\t**\tcrate when crates are on and in a multiplay game.\n\t\t*/\n\t\tfixed WaterCrateChance;\n\n\t\t/*\n\t\t**\tSolo play has money crate amount fixed according to this rule value.\n\t\t*/\n\t\tint SoloCrateMoney;\n\n\t\t/*\n\t\t**\tGPS tech level control.\n\t\t*/\n\t\tint GPSTechLevel;\n\n\t\t/*\n\t\t**\tIf a unit type is specified here, then the unit crate will generate\n\t\t**\ta unit of this type (always).\n\t\t*/\n\t\tUnitType UnitCrateType;\n\n\t\t/*\n\t\t**\tThis is the time to delay between patrol-to-waypoint target scanning.\n\t\t*/\n\t\tfixed PatrolTime;\n\n\t\t/*\n\t\t**\tThis is the time interval that checking to create teams will span. The\n\t\t**\tsmaller this number, the more often checking for team creation will occur.\n\t\t*/\n\t\tfixed TeamDelay;\n\n\t\t/*\n\t\t**\tThis is the arbitrary delay to make all cloaking objects remain uncloaked\n\t\t**\tbefore having it recloak.\n\t\t*/\n\t\tfixed CloakDelay;\n\n\t\t/*\n\t\t**\tThis is an overall game apparent speed bias to use for object\n\t\t**\tmovement purposes.\n\t\t*/\n\t\tfixed GameSpeedBias;\n\n\t\t/*\n\t\t**\tIf a potential target is close to the base then increase\n\t\t**\tthe likelyhood of attacking it by this bias factor.\n\t\t*/\n\t\tfixed NervousBias;\n\n\t\t/*\n\t\t**\tControls the Chronal vortex characteristics.\n\t\t*/\n\t\tLEPTON VortexRange;\n\t\tMPHType VortexSpeed;\n\t\tint VortexDamage;\n\t\tfixed VortexChance;\n\n\t\t/*\n\t\t**\tWhen an explosive object explodes, the damage will spread out\n\t\t**\tby this factor. The value represents the number of cells radius\n\t\t**\tthat the damage will spread for every 100 points of raw damage at\n\t\t**\tthe explosion center point.\n\t\t*/\n\t\tfixed ExplosionSpread;\n\n\t\t/*\n\t\t**\tFor weapons specially marked to check for nearby friendly buildings\n\t\t**\twhen scanning for good targets, this indicates the scan radius. Such\n\t\t**\tweapons will supress firing on enemies if they are in close proximity\n\t\t**\tto allied buildings.\n\t\t*/\n\t\tLEPTON SupressRadius;\n\n\t\t/*\n\t\t**\tThis is the tech level that para infantry are granted free to the owner\n\t\t**\tof an airstrip.\n\t\t*/\n\t\tint ParaInfantryTechLevel;\n\n\t\t/*\n\t\t**\tThis is the tech level that spy planes are granted free to the owner of\n\t\t**\tan airstrip.\n\t\t*/\n\t\tint SpyPlaneTechLevel;\n\n\t\t/*\n\t\t**\tThis is the tech level that the parabombs are granted free to the owner\n\t\t**\tof an airstrip.\n\t\t*/\n\t\tint ParaBombTechLevel;\n\n\t\t/*\n\t\t**\tThis is the maximum number of IQ settings available. The human player is\n\t\t**\tpresumed to be at IQ level zero.\n\t\t*/\n\t\tint MaxIQ;\n\n\t\t/*\n\t\t**\tThe IQ level at which super weapons will be automatically fired by the computer.\n\t\t*/\n\t\tint IQSuperWeapons;\n\n\t\t/*\n\t\t**\tThe IQ level at which production is automatically controlled by the computer.\n\t\t*/\n\t\tint IQProduction;\n\n\t\t/*\n\t\t**\tThe IQ level at which newly produced units start out in guard area mode instead\n\t\t**\tof normal guard mode.\n\t\t*/\n\t\tint IQGuardArea;\n\n\t\t/*\n\t\t**\tThe IQ level at which the computer will be able to decide what gets repaired\n\t\t**\tor sold.\n\t\t*/\n\t\tint IQRepairSell;\n\n\t\t/*\n\t\t**\tAt this IQ level or higher, a unit is allowed to automatically try to crush\n\t\t**\tan atagonist if possible.\n\t\t*/\n\t\tint IQCrush;\n\n\t\t/*\n\t\t**\tThe unit/infantry will try to scatter if an incoming threat\n\t\t**\tis detected.\n\t\t*/\n\t\tint IQScatter;\n\n\t\t/*\n\t\t**\tTech level at which the computer will scan the contents of a transport\n\t\t**\tin order to pick the best target to fire upon.\n\t\t*/\n\t\tint IQContentScan;\n\n\t\t/*\n\t\t**\tAircraft replacement production occurs at this IQ level or higher.\n\t\t*/\n\t\tint IQAircraft;\n\n\t\t/*\n\t\t**\tChecks for and replaces lost harvesters.\n\t\t*/\n\t\tint IQHarvester;\n\n\t\t/*\n\t\t**\tIs allowed to sell a structure being damaged.\n\t\t*/\n\t\tint IQSellBack;\n\n\t\t/*\n\t\t**\tThe silver and wood crates in solo play will have these powerups.\n\t\t*/\n\t\tCrateType SilverCrate;\n\t\tCrateType WoodCrate;\n\t\tCrateType WaterCrate;\n\n\t\t/*\n\t\t**\tThis specifies the minimum number of crates to place on the map in spite\n\t\t**\tof the number of actual human players.\n\t\t*/\n\t\tint CrateMinimum;\n\n\t\t/*\n\t\t**\tThis specifies the crate maximum quantity to use.\n\t\t*/\n\t\tint CrateMaximum;\n\n\t\t/*\n\t\t**\tLanding zone maximum alternate zone scan radius.\n\t\t*/\n\t\tLEPTON LZScanRadius;\n\n\t\t/*\n\t\t**\tMultiplayer default settings.\n\t\t*/\n\t\tint MPDefaultMoney;\n\t\tint MPMaxMoney;\n\t\tunsigned IsMPShadowGrow:1;\n\t\tunsigned IsMPBasesOn:1;\n\t\tunsigned IsMPTiberiumGrow:1;\n\t\tunsigned IsMPCrates:1;\n\t\tunsigned IsMPAIPlayers:1;\n\t\tunsigned IsMPCaptureTheFlag:1;\n\n\t\t/*\n\t\t**\tDrop zone reveal radius.\n\t\t*/\n\t\tLEPTON DropZoneRadius;\n\n\t\t/*\n\t\t**\tThis is the delay that multiplayer messages will remain on the screen.\n\t\t*/\n\t\tfixed MessageDelay;\n\n\t\t/*\n\t\t**\tSavour delay between when scenario detects end and the actual\n\t\t**\tend of the play.\n\t\t*/\n\t\tfixed SavourDelay;\n\n\t\t/*\n\t\t**\tThis specifies the damage to inflict for two differnt styles of\n\t\t**\tland mine.\n\t\t*/\n\t\tint AVMineDamage;\n\t\tint APMineDamage;\n\n\t\t/*\n\t\t**\tThis is the maximum number of multiplayers allowed.\n\t\t*/\n\t\tint MaxPlayers;\n\n\t\t/*\n\t\t**\tThis is the delay between 'panic attacks' when the computer's base is under\n\t\t**\tattack. This delay gives the previously assigned units a chance to affect the\n\t\t**\tattacker before the computer sends more.\n\t\t*/\n\t\tfixed BaseDefenseDelay;\n\n\t\t/*\n\t\t**\tThese values control the team suspension logic for dealing with immedate base threats.\n\t\t**\tWhen the base is attacked, all teams with less than the specified priority will be\n\t\t**\ttemporarily put on hold for the number of minutes specified.\n\t\t*/\n\t\tint SuspendPriority;\n\t\tfixed SuspendDelay;\n\n\t\t/*\n\t\t**\tThis serves as the fraction of a building's original cost that is converted\n\t\t**\tinto survivors (of some fashion). There are rounding and other marginal\n\t\t**\tfudge effects, but this value is the greatest control over the survivor rate.\n\t\t*/\n\t\tfixed SurvivorFraction;\n\n\t\t/*\n\t\t**\tThis is the aircraft reload rate expressed in minutes per ammo load.\n\t\t*/\n\t\tfixed ReloadRate;\n\n\t\t/*\n\t\t**\tThe average time (in minutes) between the computer autocreating a team\n\t\t**\tfrom the team's autocreate list.\n\t\t*/\n\t\tfixed AutocreateTime;\n\n\t\t/*\n\t\t**\tBuild up time for buildings (minutes).\n\t\t*/\n\t\tfixed BuildupTime;\n\n\t\t/*\n\t\t**\tOre truck speed for dumping.\n\t\t*/\n\t\tint OreDumpRate;\n\n\t\t/*\n\t\t**\tThis is the amount of damage done by the atom bomb in solo missions. The\n\t\t**\tdamage done during multiplay will be 1/5th this value.\n\t\t*/\n\t\tint AtomDamage;\n\n\t\t/*\n\t\t**\tThis array controls the difficulty affects on the game. There is one\n\t\t**\tdifficulty class object for each difficulty level.\n\t\t*/\n\t\tDifficultyClass Diff[DIFF_COUNT];\n\n\t\t/*\n\t\t**\tIs the computer paranoid? If so, then it will band together with other computer\n\t\t**\tparanoid players when the situation looks rough.\n\t\t*/\n\t\tbool IsComputerParanoid:1;\n\n\t\t/*\n\t\t**\tShould helicopters shuffle their position between firing on their\n\t\t**\ttarget?\n\t\t*/\n\t\tbool IsCurleyShuffle:1;\n\n\t\t/*\n\t\t**\tFlash the power bar when the power goes below 100%.\n\t\t*/\n\t\tbool IsFlashLowPower:1;\n\n\t\t/*\n\t\t**\tIf the computer players will go to easy mode if there is more\n\t\t**\tthan one human player, this flag will be true.\n\t\t*/\n\t\tbool IsCompEasyBonus:1;\n\n\t\t/*\n\t\t**\tIf fine control of difficulty settings is desired, then set this value to true.\n\t\t**\tFine control allows 5 settings. The coarse control only allows three settings.\n\t\t*/\n\t\tbool IsFineDifficulty:1;\n\n\t\t/*\n\t\t**\tIf the harvester is to explode more violently than normal\n\t\t**\tif it is carrying cargo, then this flag will be true.\n\t\t*/\n\t\tunsigned IsExplosiveHarvester:1;\n\n\t\t/*\n\t\t**\tShow the health bar on the enemy units?\n\t\t*/\n\t\tunsigned IsHealthBar:1;\n\n\t\t/*\n\t\t**\tIf this flag is true, then the construction yard can undeploy back into an MCV.\n\t\t*/\n\t\tunsigned IsMCVDeploy:1;\n\n\t\t/*\n\t\t**\tIf the base is to be revealed to a new ally, then this\n\t\t**\tflag will be true.\n\t\t*/\n\t\tunsigned IsAllyReveal:1;\n\n\t\t/*\n\t\t**\tCan the helipad (and airfield) be purchased separately from the associated\n\t\t**\taircraft.\n\t\t*/\n\t\tunsigned IsSeparate:1;\n\n\t\t/*\n\t\t**\tGive target cursor for trees? Doing this will make targetting of trees easier.\n\t\t*/\n\t\tunsigned IsTreeTarget:1;\n\n\t\t/*\n\t\t**\tAre friendly units automatically aware of mines so that they can avoid them?\n\t\t*/\n\t\tunsigned IsMineAware:1;\n\n\t\t/*\n\t\t**\tIf Tiberium is allowed to grow, then this flag will be true.\n\t\t*/\n\t\tunsigned IsTGrowth:1;\n\n\t\t/*\n\t\t**\tIf Tiberium is allowed to spread, then this flag will be true.\n\t\t*/\n\t\tunsigned IsTSpread:1;\n\n\t\t/*\n\t\t**\tShould civilan buildings and civilians display their true name rather than\n\t\t**\tthe generic \"Civilian Building\" and \"Civilain\"?\n\t\t*/\n\t\tunsigned IsNamed:1;\n\n\t\t/*\n\t\t**\tShould player controlled vehicles automatically try to crush nearby infantry\n\t\t**\tinstead of required the player to manually direct them to crush.\n\t\t*/\n\t\tunsigned IsAutoCrush:1;\n\n\t\t/*\n\t\t**\tShould the player controlled buildings and units automatically return fire when\n\t\t**\tfired upon?\n\t\t*/\n\t\tunsigned IsSmartDefense:1;\n\n\t\t/*\n\t\t**\tShould player controlled units try to scatter more easily in order to\n\t\t**\tavoid damage or threats?\n\t\t*/\n\t\tunsigned IsScatter:1;\n\n\t\t/*\n\t\t**\tIf the chronoshift effect should kill all cargo, then this flag will\n\t\t**\tbe set to true.\n\t\t*/\n\t\tunsigned IsChronoKill:1;\n\n\t\t/*\n\t\t**\tWhen infantry are prone or when civilians are running around like crazy,\n\t\t**\tthey are less prone to damage. This specifies the multiplier to the damage\n\t\t**\t(as a fixed point number).\n\t\t*/\n\t\tfixed ProneDamageBias;\n\n\t\t/*\n\t\t**\tThe time quake will do this percentage of damage to all units and buildings\n\t\t**\tin the game. The number is expressed as a fixed point percentage.\n\t\t*/\n\t\tfixed QuakeDamagePercent;\n\n\t\t/*\n\t\t**\tPercentage chance that a time quake will occur with each chronoshift use.\n\t\t*/\n\t\tfixed QuakeChance;\n\n\t\t/*\n\t\t**\tOre (Tiberium) growth rate. The value is the number of minutes between\n\t\t**\tgrowth steps.\n\t\t*/\n\t\tfixed GrowthRate;\n\n\t\t/*\n\t\t**\tThis specifies the number of minutes between each shroud regrowth process.\n\t\t*/\n\t\tfixed ShroudRate;\n\n\t\t/*\n\t\t**\tThis is the average minutes between each generation of a random crate\n\t\t**\tto be placed on the map if generating of random crates is indicated.\n\t\t*/\n\t\tfixed CrateTime;\n\n\t\t/*\n\t\t**\tThis specifies the number of minutes remaining before that if the mission timer\n\t\t**\tgets to this level or below, it will be displayed in red.\n\t\t*/\n\t\tfixed TimerWarning;\n\n\t\t/*\n\t\t**\tThis specifies the minutes of delay between recharges for these\n\t\t**\tspecial weapon types.\n\t\t*/\n\t\tfixed SonarTime;\n\t\tfixed ChronoTime;\n\t\tfixed ParaBombTime;\n\t\tfixed ParaInfantryTime;\n\t\tfixed ParaSaboteurTime;\n\t\tfixed SpyTime;\n\t\tfixed IronCurtainTime;\n\t\tfixed GPSTime;\n\t\tfixed NukeTime;\n\n\t\t/*\n\t\t**\tOther miscellaneous delay times.\n\t\t*/\n\t\tfixed SpeakDelay;\n\t\tfixed DamageDelay;\n\n\t\t/*\n\t\t**\tThis is the gravity constant used to control the arcing and descent of ballistic\n\t\t**\tobject such as grenades and artillery.\n\t\t*/\n\t\tint Gravity;\n\n\t\t/*\n\t\t**\tGap generators have a shroud radius of this many cells.\n\t\t*/\n\t\tint GapShroudRadius;\n\n\t\t/*\n\t\t**\tThis is the minute interval between the gap generators refreshing\n\t\t**\ttheir zones of gapping.\n\t\t*/\n\t\tfixed GapRegenInterval;\n\n\t\t/*\n\t\t**\tMobile radar jammer radius of effect.\n\t\t*/\n\t\tLEPTON RadarJamRadius;\n\n\t\t/*\n\t\t**\tThe speed at which a projectile that travels at or slower will cause\n\t\t**\tobjects in the target location to scatter. This simulates the ability\n\t\t**\tof targets to run for cover if the projectile gives them enough time\n\t\t**\tto react.\n\t\t*/\n\t\tMPHType Incoming;\n\n\t\t/*\n\t\t**\tMinimum and maximum damage allowed per shot.\n\t\t*/\n\t\tint MinDamage;\n\t\tint MaxDamage;\n\n\t\t/*\n\t\t**\tThis is the rate of repair for units and buildings. The rate is the\n\t\t**\tnumber of strength points repaired per repair clock tick. The cost of\n\t\t**\trepair is the (fixed point) fractional cost to repair the object based\n\t\t**\ton the full price of the object. Example; a value of 50% means that to\n\t\t**\trepair the object from 1 damage point to full strength would cost 50% of\n\t\t**\tthe cost to build it from scratch.\n\t\t*/\n\t\tint RepairStep;\n\t\tfixed RepairPercent;\n\t\tint URepairStep;\n\t\tfixed URepairPercent;\n\n\t\t/*\n\t\t**\tThis is the rate that objects with self healing will heal. They will repair a bit\n\t\t**\tevery 'this' number of minutes.\n\t\t*/\n\t\tfixed RepairRate;\n\n\t\t/*\n\t\t**\tThese fixed point values are used to determine the status (health bar\n\t\t**\tcolor) of the game objects. Objects in the 'yellow' are in a cautionary\n\t\t**\tstate. Object in the 'red' are in a danger state.\n\t\t*/\n\t\tfixed ConditionGreen;\n\t\tfixed ConditionYellow;\n\t\tfixed ConditionRed;\n\n\t\t/*\n\t\t**\tAverage number of minutes between infantry random idle animations.\n\t\t*/\n\t\tfixed RandomAnimateTime;\n\n\t\t/*\n\t\t**\tThese control the capacity and value of the ore types that a harvester\n\t\t**\tmay carry. The harvester carries a maximum discrete number of 'bails'.\n\t\t**\tThe value of each bail depends on the ore it is composed of.\n\t\t*/\n\t\tint BailCount;\t\t// was STEP_COUNT\n\t\tint GoldValue;\t\t// was GOLD_WORTH\n\t\tint GemValue;\t\t// was GEM_WORTH\n\n\t\t/*\n\t\t**\tThis specifies the heap maximum for the various game objects.\n\t\t*/\n\t\tint AircraftMax;\n\t\tint AnimMax;\n\t\tint BuildingMax;\n\t\tint BulletMax;\n\t\tint FactoryMax;\n\t\tint InfantryMax;\n\t\tint OverlayMax;\n\t\tint SmudgeMax;\n\t\tint TeamMax;\n\t\tint TeamTypeMax;\n\t\tint TemplateMax;\n\t\tint TerrainMax;\n\t\tint TriggerMax;\n\t\tint UnitMax;\n\t\tint VesselMax;\n\t\tint ProjectileMax;\n\t\tint WeaponMax;\n\t\tint WarheadMax;\n\t\tint TrigTypeMax;\n\n\t\t/*\n\t\t**\tClose enough distance that is used to determine if the object should\n\t\t**\tstop movement when blocked. If the distance to the desired destination\n\t\t**\tis equal to this distance or less, but the path is blocked, then consider\n\t\t**\tthe object to have gotten \"close enough\" to the destination to stop.\n\t\t*/\n\t\tLEPTON CloseEnoughDistance;\n\n\t\t/*\n\t\t**\tStray distance to group team members within. The larger the distance,\n\t\t**\tthe looser the teams will move.\n\t\t*/\n\t\tLEPTON StrayDistance;\n\n\t\t/*\n\t\t**\tIf a vehicle is closer than this range to a target that it can crush\n\t\t**\tby driving over it, then it will try to drive over it instead of firing\n\t\t**\tupon it. The larger the value, the greater the 'bigfoot crush syndrome' is\n\t\t**\thas.\n\t\t*/\n\t\tLEPTON CrushDistance;\n\n\t\t/*\n\t\t**\tFor area effect crate bonus items will affect all objects within this radius.\n\t\t*/\n\t\tLEPTON CrateRadius;\n\n\t\t/*\n\t\t**\tMaximum scatter distances for homing and non-homing projectiles.\n\t\t*/\n\t\tLEPTON HomingScatter;\n\t\tLEPTON BallisticScatter;\n\n\t\t/*\n\t\t**\tThis is the refund percentage when selling off buildings and units\n\t\t**\ton the repair pad (service depot).\n\t\t*/\n\t\tfixed RefundPercent;\n\n\t\t/*\n\t\t**\tThe Iron Curtain invulnerability effect lasts for this many minutes.\n\t\t*/\n\t\tfixed IronCurtainDuration;\n\n\t\t/*\n\t\t**\tThe strength of bridges is held here. By corollary, the strength of the\n\t\t**\tdemolition charge carried by Tanya is equal to this value as well.\n\t\t*/\n\t\tint BridgeStrength;\n\n\t\t/*\n\t\t**\tThis is the overall build speed bias. Multiply this value by the normal build\n\t\t**\tdelay to get the effective build delay.\n\t\t*/\n\t\tfixed BuildSpeedBias;\n\n\t\t/*\n\t\t**\tWeapon type array pointer should go here. Dynamic type.\n\t\t*/\n\n\n\t\t/*\n\t\t**\tWarhead type class array pointer should go here. Dynamic type.\n\t\t*/\n\n\n\t\t/*\n\t\t**\tGround type and speed affect data should go here.\n\t\t*/\n\n\n\t\t/*\n\t\t**\tThis is the delay between the time a C4 bomb is planted and the time it will\n\t\t**\texplode. The longer the delay, the greater safety margin for a demolitioner\n\t\t**\ttype. The short the delay, the less time the victim has to sell the building\n\t\t**\toff.\n\t\t*/\n\t\tfixed C4Delay;\n\n\t\t/*\n\t\t**\tThe computer will only repair a structure if it has spare money greater than this\n\t\t**\tamount. The thinking is that this will prevent the computer from frittering away\n\t\t**\tall it's cash on repairing and thus leaving nothing for production of defenses.\n\t\t*/\n\t\tint RepairThreshhold;\n\n\t\t/*\n\t\t**\tThis is the delay (in minutes) between retries of a failed path. The longer the\n\t\t**\tdelay the faster the system, but the longer the units take to react to a blocked\n\t\t**\tterrain event.\n\t\t*/\n\t\tfixed PathDelay;\n\n\t\t/*\n\t\t**\tThis is the special (debug version only) movie recorder timeout value. Each second\n\t\t**\tresults in about 2-3 megabytes.\n\t\t*/\n\t\tfixed MovieTime;\n\n\t\t/*\n\t\t** This is the level at or above which the chronosphere facility can\n\t\t** actually produce the chronosphere effect.  Below this tech level,\n\t\t** the facility is merely a showpiece and has no effect.\n\t\t*/\n\t\tint ChronoTechLevel;\n\n\t\t/*\n\t\t**\tThese are the Tiberium scan distances. The short range scan is used to determine if the\n\t\t**\tcurrent field has been exhausted. The long range scan is used when finding a Tiberium\n\t\t**\tfield to harvest. Keep these ranges as small as possible.\n\t\t*/\n\t\tLEPTON TiberiumShortScan;\n\t\tLEPTON TiberiumLongScan;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/RULES.MAK",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n# Size of the program shape buffer (passed to MAKESHPS.EXE)\nSHAPEBUFFSIZE = 20000\n\n# Default paths to use\nROOTCD = v:\\projects\\c&c0\\cstrike2\\cd\\\\\nROOTDIR = ..\\\\\nMAPDIR  = ..\\\\\nROOTCODEDIR = .\\\\\nABSROOT = ..\\\\\nWAVDIR  = f:\\projects\\c&c0\\audio\\amingame\\\\\nSCOREDIR = f:\\projects\\c&c0\\audio\\amingame\\scores\\\\\nVQADIR  = f:\\projects\\c&c0\\art\\movies\\\\\nLANGDIR =\nINGAMEDIR = ingame\nTEMPDIR = s:\n\n\n# Override paths\n!if $d(GERMAN)\nROOTCD = v:\\projects\\c&c0\\cstrike2\\cdger\\\\\nROOTDIR = ..\\\\\nMAPDIR  = ..\\ger\nROOTCODEDIR = .\\\\\nABSROOT = ..\\\\\nWAVDIR  = f:\\projects\\c&c0\\audio\\amingame\\\\\nLANGDIR = \\german\nINGAMEDIR = ingamegr\n#VQADIR = s:t\\\\\nVQADIR = t:movies\\\\\nTEMPDIR = s:\n!endif\n\n!if $d(FRENCH)\nROOTCD = v:\\projects\\c&c0\\cstrike2\\cdfre\\\\\nROOTDIR = ..\\\\\nMAPDIR  = ..\\fre\nROOTCODEDIR = .\\\\\nABSROOT = ..\\\\\nWAVDIR  = f:\\projects\\c&c0\\audio\\amingame\\\nLANGDIR = \\french\nINGAMEDIR=ingamefr\nVQADIR  = t:movies\\\\\nTEMPDIR = s:\n!endif\n\n\n# Directory where temporary mixfiles can be stored.\n!if $d(TEMP_MIX_DIR)\nTEMP_MIX_DIR = $(TEMP_MIX_DIR)\n!else\nTEMP_MIX_DIR = $(TEMPDIR)t\\m\n!endif\n\n!if $d(CPS)\nTEMP_CPS_DIR = $(CPS)\n!else\nTEMP_CPS_DIR = $(TEMPDIR)t\n!endif\n\n\n#.path.a6a = $(TEMP_CPS_DIR)\\\\            # Game formatted audio data\n#.path.a6j = $(TEMP_CPS_DIR)\\\\            # Game formatted audio data\n#.path.a8  = $(TEMP_CPS_DIR)\\\\            # Game formatted audio data\n#.path.a80 = $(TEMP_CPS_DIR)\\\\            # Game formatted audio data\n#.path.a81 = $(TEMP_CPS_DIR)\\\\            # Game formatted audio data\n#.path.a82 = $(TEMP_CPS_DIR)\\\\            # Game formatted audio data\n#.path.a83 = $(TEMP_CPS_DIR)\\\\            # Game formatted audio data\n#.path.a84 = $(TEMP_CPS_DIR)\\\\            # Game formatted audio data\n#.path.a8a = $(TEMP_CPS_DIR)\\\\            # Game formatted audio data\n#.path.a8j = $(TEMP_CPS_DIR)\\\\            # Game formatted audio data\n.path.a6  = $(TEMP_CPS_DIR)\\\\            # Game formatted audio data\n.path.anm = $(ROOTDIR)art\\$(INGAMEDIR)\\\\    # Raw animation file\n.path.ash = .\\\\                          # Autogenerated assembly header file\n.path.asm = .\\\\                          # Raw assembly file\n.path.aud = $(TEMP_CPS_DIR)\\\\            # Game formatted audio data\n.path.c   = .\\\\                          # Raw C file\n.path.cd1 = $(ROOTCD)CD4\\\\               # CD #1 (Allies)\n.path.cd2 = $(ROOTCD)CD2\\\\               # CD #1 (Soviet)\n.path.cpp = .\\\\                          # Raw C++ file\n.path.cps = $(TEMP_CPS_DIR)\\\\            # Compressed art\n.path.dat = $(TEMP_CPS_DIR)\\\\            # Generic data\n.path.des = $(TEMP_CPS_DIR)\\\\            # Desert icons\n.path.dip = $(TEMP_CPS_DIR)\\\\            # Generic compressed text (obsolete)\n.path.eng = $(TEMP_CPS_DIR)\\\\            # English compressed text\n.path.exe = $(ROOTDIR)run\\\\              # Executable (relative path from OBJ directory)\n.path.fin = $(ROOTDIR)art\\ingame\\fin\\\\   # Finale source animation\n.path.fnt = $(TEMP_CPS_DIR)\\\\            # Font (compressed)\n.path.foc = $(ROOTDIR)audio\\french\\\\     # French digitized voices\n.path.fre = $(TEMP_CPS_DIR)\\\\            # French compressed text\n.path.gdi = $(TEMP_CPS_DIR)\\\\            # Good guy compressed files\n.path.ger = $(TEMP_CPS_DIR)\\\\            # German compressed text\n.path.goc = $(ROOTDIR)audio\\german\\\\     # German digitized voices\n.path.h   = .\\\\                          # C header file\n.path.hi  = $(TEMP_CPS_DIR)\\\\            # Shape file (processed)\n.path.hnt = $(TEMP_CPS_DIR)\\\\            # Font (compressed)\n.path.i   = .\\\\                          # Assembly header\n.path.icn = $(TEMP_CPS_DIR)\\\\            # Icon file (compressed)\n.path.ini = $(MAPDIR)maps\\\\              # INI control files\n.path.int = $(TEMP_CPS_DIR)\\\\            # Interior icons\n.path.j6  = $(TEMP_CPS_DIR)\\\\            # Game formatted audio data\n.path.jp  = $(TEMP_CPS_DIR)\\\\            # Dinosaur compressed files\n.path.jun = $(TEMP_CPS_DIR)\\\\            # Jungle icons\n.path.juv = $(TEMP_CPS_DIR)\\\\            # Juvenile sound effects.\n.path.lbm = $(ROOTDIR)art\\ingame\\\\ # Source art (uncompressed)\n.path.lnt = $(TEMP_CPS_DIR)\\\\            # Font (compressed)\n.path.low = $(TEMP_CPS_DIR)\\\\            # Shape file (processed)\n.path.lut = $(TEMP_CPS_DIR)\\\\            # Look up tables\n.path.mak = .\\\\                          # Shape making control file\n.path.map = $(TEMP_CPS_DIR)\\\\            # Icon map data file\n.path.mid = $(ROOTDIR)audio\\mid\\\\        # Midi file\n.path.mix = $(TEMP_MIX_DIR)\\\\            # Mix-file location.\n.path.mpr = $(MAPDIR)maps\\\\              # Multiplayer scenario files\n.path.mrf = $(TEMP_CPS_DIR)\\\\            # Palette morph data files\n.path.nod = $(TEMP_CPS_DIR)\\\\            # Bad guy compressed files\n.path.o   = obj\\\\                        # Overlay object file\n.path.obj = obj\\\\                        # Object file\n.path.out = .\\\\                          # Temporary parser file.\n.path.pak = $(ROOTDIR)run\\\\              # Packed file\n.path.pal = $(TEMP_CPS_DIR)\\\\            # Palette file (processed)\n.path.pcx = $(TEMP_CPS_DIR)\\\\            #.pcx files\n.path.pkt = $(MAPDIR)maps\\\\              # Scenario grouping control files\n.path.r00 = $(TEMP_CPS_DIR)\\\\            # Infantry response.\n.path.r01 = $(TEMP_CPS_DIR)\\\\            # Infantry response.\n.path.r02 = $(TEMP_CPS_DIR)\\\\            # Infantry response.\n.path.r03 = $(TEMP_CPS_DIR)\\\\            # Infantry response.\n.path.shp = $(TEMP_CPS_DIR)\\\\            # Shape file (processed)\n.path.sno = $(TEMP_CPS_DIR)\\\\            # Snow icons\n.path.sym = .\\\\                          # Precompiled header symbol file.\n.path.tbl = $(TEMP_CPS_DIR)\\\\            # Remap table file.\n.path.tem = $(TEMP_CPS_DIR)\\\\            # Temperate icons\n.path.txt = $(ROOTDIR)code\\eng\\\\         # Default location for text files.\n.path.v00 = $(TEMP_CPS_DIR)\\\\            # Infantry response.\n.path.v01 = $(TEMP_CPS_DIR)\\\\            # Infantry response.\n.path.v02 = $(TEMP_CPS_DIR)\\\\            # Infantry response.\n.path.v03 = $(TEMP_CPS_DIR)\\\\            # Infantry response.\n.path.v16 = $(TEMP_CPS_DIR)\\\\            # Game formatted audio data\n.path.vqa = $(VQADIR)vq$(LANGDIR)\\\\      # VQA movie files location.\n.path.vqp = $(VQADIR)vq$(LANGDIR)\\\\      # VQA Movie Interpolated palette files\n!if $d(FRENCH)\n.path.vqa = $(VQADIR)vq\\french\\\\      # VQA movie files location.\n.path.vqp = $(VQADIR)vq\\french\\\\      # VQA Movie Interpolated palette files\n!endif\n.path.wav = $(WAVDIR)                    # Digitized sample file (generic)\n.path.win = $(TEMP_CPS_DIR)\\\\            # Winter icons\n.path.wsa = $(TEMP_CPS_DIR)\\\\            # Processed animation file\n.path.wv  = $(ROOTDIR)audio\\wv\\\\         # Digitized sample file (generic)\n.path.xmi = $(ROOTDIR)audio\\xmi\\\\        # MT-32 midi scores\n\n\n##########################################################################\n# Rules\n\n#\n# Rule for converting anim files.\n#\n.anm.wsa:\n\tutils\\animate $*.anm $(.path.anm)$&.lbm $(.path.wsa)$&.wsa -l -f -p\n\n#\n# Rule for converting art files.\n#\n.lbm.cps:\n\tutils\\wwcomp $*.lbm $(.path.cps)$&.cps -ex -i\n\n#\n# Rule for converting outtake first frame art files.\n#\n{$(.path.lbm)outtake}.lbm.cps:\n\tutils\\wwcomp $*.lbm $(.path.cps)$&.cps -ex\n\n{$(.path.anm)outtake}.anm.wsa:\n\tutils\\animate $*.anm $(.path.anm)outtake\\$&.lbm $(.path.wsa)$&.wsa -l -f -p\n\n{$(.path.anm)score}.anm.wsa:\n\tutils\\animate $*.anm $(.path.wsa)$&.wsa -p\n\n#########################################################\n# Rule for creating palette files.\n#\n{$(.path.lbm)palettes}.lbm.pal:\n\tutils\\wwcomp $*.lbm -ppal\n\tcopy $&.pal $(.path.pal)$&.pal\n\tdel $&.pal\n\n{$(.path.lbm)score}.lbm.pal:\n\tutils\\wwcomp $*.lbm -ppal\n\tcopy $&.pal $(.path.pal)$&.pal\n\tdel $&.pal\n\n#########################################################\n# Rule for creating vehicles.\n{$(.path.anm)units}.anm.shp:\n\tutils\\keyframe $*.anm $(.path.shp)$&.shp -l\n\n#########################################################\n# Rule for creating buildings.\n{$(.path.anm)building}.anm.shp:\n\tutils\\keyframe $*.anm $(.path.shp)$&.shp -l\n\n#########################################################\n# Rule for creating misc shape animations.\n{$(.path.anm)anim}.anm.shp:\n\tutils\\keyframe $*.anm $(.path.shp)$&.shp -l\n\n#########################################################\n# Rule for converting font files.\n{$(.path.lbm)fonts}.lbm.fnt:\n\techo Creating font file \"$&.fnt\".\n\tutils\\fontmake $*.lbm -o$(.path.fnt)$&.fnt\n\n{$(.path.lbm)hires}.lbm.hnt:\n\techo Creating hi-res font file \"$&.fnt\".\n\tutils\\fontmake $*.lbm -o$(.path.hnt)$&.hnt\n\n{$(.path.lbm)hires}.lbm.fnt:\n\techo Creating lo-res font file \"$&.fnt\".\n\tutils\\fontmake $*.lbm -o$(.path.hnt)$&.fnt\n\n{$(.path.lbm)lores}.lbm.lnt:\n\techo Creating lo-res font file \"$&.fnt\".\n\tutils\\fontmake $*.lbm -o$(.path.lnt)$&.lnt\n\n{$(.path.lbm)lores}.lbm.fnt:\n\techo Creating lo-res font file \"$&.fnt\".\n\tutils\\fontmake $*.lbm -o$(.path.lnt)$&.fnt\n\n#########################################################\n# Rules for creating overlay files.\n{$(.path.lbm)overlay}.lbm.cps:\n\tutils\\wwcomp $*.lbm $(.path.cps)$&.cps\n\n{$(.path.anm)overlay}.anm.shp:\n\tutils\\keyframe $*.anm $(.path.shp)$&.shp -l\n\n#########################################################\n# Rules for creating temperate files.\n{$(.path.lbm)temperat}.lbm.tem:\n\tutils\\iconmap -r -w3 -o$(.path.tem)$&.tem $*.lbm\n\n{$(.path.anm)temperat}.anm.tem:\n\tutils\\keyframe $*.anm $(.path.tem)$&.tem -l\n\n#########################################################\n# Rules for creating interior files.\n{$(.path.lbm)interior}.lbm.int:\n\tutils\\iconmap -r -w3 -o$(.path.int)$&.int $*.lbm\n\n{$(.path.anm)interior}.anm.int:\n\tutils\\keyframe $*.anm $(.path.int)$&.int -l\n\n#########################################################\n# Rules for creating winter files.\n{$(.path.lbm)snow}.lbm.sno:\n\tutils\\iconmap -r -w3 -o$(.path.sno)$&.sno $*.lbm\n\n{$(.path.anm)snow}.anm.sno:\n\tutils\\keyframe $*.anm $(.path.sno)$&.sno -l\n\n#########################################################\n# Rules for creating desert files.\n{$(.path.lbm)desert}.lbm.des:\n\tutils\\iconmap -r -w3 -o$(.path.des)$&.des $*.lbm\n\n{$(.path.anm)desert}.anm.des:\n\tutils\\keyframe $*.anm $(.path.des)$&.des -l\n\n#########################################################\n# Generic icon file creation.\n.lbm.icn:\n\tutils\\iconmap -r -w3 -o$(.path.icn)$&.icn $*.lbm\n\n\n#########################################################\n# Text files.\n{eng}.txt.eng:\n\tutils\\textmake $*.txt $(.path.eng)$&.eng $&.h\n\n{ger}.txt.ger:\n\tutils\\textmake $*.txt $(.path.ger)$&.ger $&.h\n\n{fre}.txt.fre:\n\tutils\\textmake $*.txt $(.path.fre)$&.fre $&.h\n\n#########################################################\n# Score/mapsel files.\n{$(.path.anm)score}.anm.shp:\n\tutils\\keyframe $*.anm $(.path.shp)$&.shp -l\n\n{$(.path.lbm)score}.lbm.cps:\n\tutils\\wwcomp $*.lbm $(.path.cps)$&.cps -ex -i\n\n\n#########################################################\n# Generic shape files.\n#.lbm.shp:\n#       utils\\makeshps -q $*.lbm $&.mak $(.path.cps)$&.shp $(SHAPEBUFFSIZE)\n\n{$(.path.anm)generic}.anm.shp:\n\tutils\\keyframe $*.anm $(.path.shp)$&.shp -l\n\n.c.lob:\n\tutils\\LINT -ml -si2 -sl4 +v $(WWLIB)WWLIB.LNT $*.c >$&.err\n\n# Generic shape file creation.\n{$(.path.anm)}.anm.shp:\n\tutils\\keyframe $*.anm $(.path.shp)$&.shp -l\n\n{$(.path.lbm)units}.lbm.cps:\n\tutils\\wwcomp $*.lbm $(.path.cps)$&.cps -ex -i\n\n\n##########################################################\n# Hi-res data files\n#\n{$(.path.anm)hires}.anm.hi:\n\tutils\\keyframe $*.anm $(.path.hi)$&.hi -l\n\n# Hi-res font files\n{$(.path.lbm)hires}.lbm.fnt:\n\techo Creating font file \"$&.fnt\".\n\tutils\\fontmake $*.lbm -o$(.path.fnt)$&.fnt\n\n#########################################################\n# Rule for creating low res data files.\n{$(.path.anm)lores}.anm.low:\n\tutils\\keyframe $*.anm $(.path.low)$&.low -l\n\n{$(.path.lbm)lores}.lbm.cps:\n\tutils\\wwcomp $*.lbm $(.path.cps)$&.cps -ex -i\n\n#######################################\n# Rules to convert 16 bit audio files.\n{$(SCOREDIR)}.wav.aud:\n\tutils\\audiomak $(SCOREDIR)$&.wav $(.path.aud)$&.aud\n\n{$(.path.wav)speech$(LANGDIR)}.wav.aud:\n\tutils\\audiomak $(.path.wav)speech$(LANGDIR)\\$&.wav $(.path.aud)$&.aud\n\n{$(.path.wav)sfx\\tanya$(LANGDIR)}.wav.aud:\n\tutils\\audiomak $(.path.wav)sfx\\tanya$(LANGDIR)\\$&.wav $(.path.aud)$&.aud\n\n{$(.path.wav)sfx$(LANGDIR)}.wav.aud:\n\tutils\\audiomak $(.path.wav)sfx$(LANGDIR)\\$&.wav $(.path.aud)$&.aud\n\n{$(.path.wav)sfx\\v00$(LANGDIR)}.wav.v00:\n\tutils\\audiomak $(.path.wav)sfx\\v00$(LANGDIR)\\$&.wav $(.path.aud)$&.v00\n\n{$(.path.wav)sfx\\v01$(LANGDIR)}.wav.v01:\n\tutils\\audiomak $(.path.wav)sfx\\v01$(LANGDIR)\\$&.wav $(.path.aud)$&.v01\n\n{$(.path.wav)sfx\\v02$(LANGDIR)}.wav.v02:\n\tutils\\audiomak $(.path.wav)sfx\\v02$(LANGDIR)\\$&.wav $(.path.aud)$&.v02\n\n{$(.path.wav)sfx\\v03$(LANGDIR)}.wav.v03:\n\tutils\\audiomak $(.path.wav)sfx\\v03$(LANGDIR)\\$&.wav $(.path.aud)$&.v03\n\n{$(.path.wav)sfx\\r00$(LANGDIR)}.wav.r00:\n\tutils\\audiomak $(.path.wav)sfx\\r00$(LANGDIR)\\$&.wav $(.path.aud)$&.r00\n\n{$(.path.wav)sfx\\r01$(LANGDIR)}.wav.r01:\n\tutils\\audiomak $(.path.wav)sfx\\r01$(LANGDIR)\\$&.wav $(.path.aud)$&.r01\n\n{$(.path.wav)sfx\\r02$(LANGDIR)}.wav.r02:\n\tutils\\audiomak $(.path.wav)sfx\\r02$(LANGDIR)\\$&.wav $(.path.aud)$&.r02\n\n{$(.path.wav)sfx\\r03$(LANGDIR)}.wav.r03:\n\tutils\\audiomak $(.path.wav)sfx\\r03$(LANGDIR)\\$&.wav $(.path.aud)$&.r03\n\n"
  },
  {
    "path": "CODE/SAVEDLG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SAVEDLG.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               *** \n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SAVEDLG.H                                                    *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg, Joe L. Bostic                   *\n *                                                                                             *\n *                   Start Date : Jan 8, 1995                                                  * \n *                                                                                             *\n *                  Last Update : Jan 18, 1995   [MML]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SAVEDLG_H\n#define SAVEDLG_H\n\n#include \"gadget.h\"\n\nclass SaveOptionsClass \n{\n\tprivate:\n\n\t\tenum SaveOptionsClassEnums {\n\t\t\tBUTTON_CANCEL=200,\n\t\t\tBUTTON_SAVE,\n\t\t\tOPTION_WIDTH=216,\n\t\t\tOPTION_HEIGHT=122,\n\t\t\tOPTION_X=((320 - OPTION_WIDTH) / 2) & ~7,\n\t\t\tOPTION_Y=(200 - OPTION_HEIGHT) / 2,\n\t\t\tNUMBER_OF_BUTTONS=2,\n\t\t\tCAPTION_Y_POS=5,\n\t\t\tBORDER1_LEN=49,\n\t\t\tBUTTON_CANCEL_X=90,\n\t\t\tBUTTON_CANCEL_Y=103,\n\t\t\tLISTBOX_X=40,\n\t\t\tLISTBOX_Y=24,\n\t\t\tLISTBOX_W=136,\n\t\t\tLISTBOX_H=72\n\t\t};\n\n\tpublic:\n\t\tSaveOptionsClass (void) { };\n\t\tvoid Process (void);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/SAVELOAD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /counterstrike/SAVELOAD.CPP 9     3/17/97 1:04a Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SAVELOAD.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 23, 1994                                              *\n *                                                                                             *\n *                  Last Update : July 8, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Code_All_Pointers -- Code all pointers.                                                   *\n *   Decode_All_Pointers -- Decodes all pointers.                                              *\n *   Get_Savefile_Info -- gets description, scenario #, house                                  *\n *   Load_Game -- loads a saved game                                                           *\n *   Load_MPlayer_Values -- Loads multiplayer-specific values                                  *\n *   Load_Misc_Values -- loads miscellaneous variables                                         *\n *   MPlayer_Save_Message -- pops up a \"saving...\" message                                     *\n *   Put_All -- Store all save game data to the pipe.                                          *\n *   Reconcile_Players -- Reconciles loaded data with the 'Players' vector\t\t\t\t\t\t\t  *\n *   Save_Game -- saves a game to disk                                                         *\n *   Save_MPlayer_Values -- Saves multiplayer-specific values                                  *\n *   Save_Misc_Values -- saves miscellaneous variables                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"vortex.h\"\n#ifdef WIN32\n#include \"tcpip.h\"\n#include \"ccdde.h\"\n\n//#include \"WolDebug.h\"\n\nextern bool SpawnedFromWChat;\n#endif\n\n//#define\tSAVE_BLOCK_SIZE\t512\n#define\tSAVE_BLOCK_SIZE\t4096\n//#define\tSAVE_BLOCK_SIZE\t1024\n\n/*\n********************************** Defines **********************************\n*/\n#define\tSAVEGAME_VERSION\t\t(DESCRIP_MAX + \\\n\t\t\t\t\t\t\t\t\t\t0x01000006 + ( \\\n\t\t\t\t\t\t\t\t\t\tsizeof(AircraftClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(AircraftTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(AnimClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(AnimTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(BaseClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(BuildingClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(BuildingTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(BulletClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(BulletTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(CellClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(FactoryClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(HouseClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(HouseTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(InfantryClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(InfantryTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(LayerClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(MouseClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(OverlayClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(OverlayTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(SmudgeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(SmudgeTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(TeamClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(TeamTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(TemplateClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(TemplateTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(TerrainClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(TerrainTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(TriggerClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(TriggerTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(UnitClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(UnitTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(VesselClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(ScenarioClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(ChronalVortexClass)))\n//\t\t\t\t\t\t\t\t\t\tsizeof(Waypoint)))\n\n\nstatic int Reconcile_Players(void);\nextern bool Is_Mission_Counterstrike (char *file_name);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern bool Is_Mission_Aftermath (char *file_name);\n#endif\n\n/***********************************************************************************************\n * Put_All -- Store all save game data to the pipe.                                            *\n *                                                                                             *\n *    This is the bulk processor of the game related save game data. All the game object       *\n *    and state data is stored to the pipe specified.                                          *\n *                                                                                             *\n * INPUT:   pipe  -- Reference to the pipe that will receive the save game data.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Put_All(Pipe & pipe, int save_net)\n{\n\t/*\n\t**\tSave the scenario global information.\n\t*/\n\tpipe.Put(&Scen, sizeof(Scen));\n\n\t/*\n\t**\tSave the map.  The map must be saved first, since it saves the Theater.\n\t*/\n\tif (!save_net) Call_Back();\n\tMap.Save(pipe);\n\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tSave all game objects.  This code saves every object that's stored in a\n\t**\tTFixedIHeap class.\n\t*/\n\tHouses.Save(pipe);\n\tif (!save_net) Call_Back();\n\tTeamTypes.Save(pipe);\n\tif (!save_net) Call_Back();\n\tTeams.Save(pipe);\n\tif (!save_net) Call_Back();\n\tTriggerTypes.Save(pipe);\n\tif (!save_net) Call_Back();\n\tTriggers.Save(pipe);\n\tif (!save_net) Call_Back();\n\tAircraft.Save(pipe);\n\tif (!save_net) Call_Back();\n\tAnims.Save(pipe);\n\n\tif (!save_net) Call_Back();\n\n\tBuildings.Save(pipe);\n\tif (!save_net) Call_Back();\n\tBullets.Save(pipe);\n\tif (!save_net) Call_Back();\n\tInfantry.Save(pipe);\n\tif (!save_net) Call_Back();\n\tOverlays.Save(pipe);\n\tif (!save_net) Call_Back();\n\tSmudges.Save(pipe);\n\tif (!save_net) Call_Back();\n\tTemplates.Save(pipe);\n\tif (!save_net) Call_Back();\n\tTerrains.Save(pipe);\n\tif (!save_net) Call_Back();\n\tUnits.Save(pipe);\n\tif (!save_net) Call_Back();\n\tFactories.Save(pipe);\n\tif (!save_net) Call_Back();\n\tVessels.Save(pipe);\n\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tSave the Logic & Map layers\n\t*/\n\tLogic.Save(pipe);\n\n\tint count = MapTriggers.Count();\n\tpipe.Put(&count, sizeof(count));\n\tfor (int index = 0; index < MapTriggers.Count(); index++) {\n\t\tTARGET target = MapTriggers[index]->As_Target();\n\t\tpipe.Put(&target, sizeof(target));\n\t}\n\tif (!save_net) Call_Back();\n\tcount = LogicTriggers.Count();\n\tpipe.Put(&count, sizeof(count));\n\tfor (index = 0; index < LogicTriggers.Count(); index++) {\n\t\tTARGET target = LogicTriggers[index]->As_Target();\n\t\tpipe.Put(&target, sizeof(target));\n\t}\n\tif (!save_net) Call_Back();\n\tfor (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\tcount = HouseTriggers[h].Count();\n\t\tpipe.Put(&count, sizeof(count));\n\t\tfor (index = 0; index < HouseTriggers[h].Count(); index++) {\n\t\t\tTARGET target = HouseTriggers[h][index]->As_Target();\n\t\t\tpipe.Put(&target, sizeof(target));\n\t\t}\n\t}\n\tif (!save_net) Call_Back();\n\n\tfor (int i = 0; i < LAYER_COUNT; i++) {\n\t\tMap.Layer[i].Save(pipe);\n\t}\n\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tSave the Score\n\t*/\n\tpipe.Put(&Score, sizeof(Score));\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tSave the AI Base\n\t*/\n\tBase.Save(pipe);\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tSave out the carry over list (if present). First see how\n\t**\tmany carry over objects are in the list.\n\t*/\n\tint carry_count = 0;\n\tCarryoverClass const * cptr = Carryover;\n\twhile (cptr != NULL) {\n\t\tcarry_count++;\n\t\tcptr = (CarryoverClass const *)cptr->Get_Next();\n\t}\n\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tSave out the number of objects in the list.\n\t*/\n\tpipe.Put(&carry_count, sizeof(carry_count));\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tNow write out the objects themselves.\n\t*/\n\tCarryoverClass const * object_to_write = Carryover;\n\twhile (object_to_write != NULL) {\n\t\tpipe.Put(object_to_write, sizeof(*object_to_write));\n\t\tobject_to_write = (CarryoverClass const *)object_to_write->Get_Next();\n\t}\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tSave miscellaneous variables.\n\t*/\n\tSave_Misc_Values(pipe);\n\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tSave multiplayer values\n\t*/\n\tif (save_net) {\n\t\tSave_MPlayer_Values(pipe);\n\t}\n\n\tpipe.Flush();\n}\n\n\n/***************************************************************************\n * Save_Game -- saves a game to disk                                       *\n *                                                                         *\n * Saving the Map:                                                         *\n *     DisplayClass::Save() invokes CellClass's Write() for every cell     *\n *     that needs to be saved.  A cell needs to be saved if it contains    *\n *     any special data at all, such as a TIcon, or an Occupier.           *\n *   The cell saves its own CellTrigger pointer, converted to a TARGET.    *\n *                                                                         *\n * Saving game objects:                                                    *\n *   - Any object stored in an ArrayOf class needs to be saved.  The ArrayOf*\n *     Save() routine invokes each object's Write() routine, if that       *\n *     object's IsActive is set.                                           *\n *                                                                         *\n * Saving the layers:                                                      *\n *   The Map's Layers (Ground, Air, etc) of things that are on the map,    *\n *     and the Logic's Layer of things to process both need to be saved.   *\n *     LayerClass::Save() writes the entire layer array to disk            *\n *                                                                         *\n * Saving the houses:                                                      *\n *   Each house needs to be saved, to record its Credits, Power, etc.      *\n *                                                                         *\n * Saving miscellaneous data:                                              *\n *   There are a lot of miscellaneous variables to save, such as the       *\n *     map's dimensions, the player's house, etc.                          *\n *                                                                         *\n * INPUT:                                                                  *\n *      id      numerical ID, for the file extension                       *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      true = OK, false = error                                           *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/28/1994 BR : Created.                                              *\n *   02/27/1996 JLB : Uses simpler game control value save operation.      *\n *=========================================================================*/\nbool Save_Game(int id, char const * descr, bool )\n{\n\tchar name[_MAX_FNAME+_MAX_EXT];\n\tunsigned scenario;\n\tHousesType house;\n\tint save_net = 0;\t\t\t\t\t\t\t\t\t// 1 = save network/modem game\n\n\tscenario = Scen.Scenario;\t\t\t\t\t\t// get current scenario #\n\thouse = PlayerPtr->Class->House;\t\t\t\t// get current house\n\n\t/*\n\t**\tGenerate the filename to save.  If 'id' is -1, it means save a\n\t** network/modem game; otherwise, use 'id' as the file extension.\n\t*/\n\tif (id==-1) {\n\t\tstrcpy(name, NET_SAVE_FILE_NAME);\n\t\tsave_net = 1;\n\t} else {\n\t\tsprintf(name, \"SAVEGAME.%03d\", id);\n\t}\n\n\t/*\n\t**\tCode everybody's pointers\n\t*/\n\tCode_All_Pointers();\n\n\t/*\n\t**\tOpen the file\n\t*/\n\tBufferIOFileClass file(name);\n\n\tFilePipe fpipe(&file);\n\n\t/*\n\t**\tSave the description, scenario #, and house\n\t**\t(scenario # & house are saved separately from the actual Scenario &\n\t**\tPlayerPtr globals for convenience; we can quickly find out which\n\t**\thouse & scenario this save-game file is for by reading these values.\n\t**\tAlso, PlayerPtr is stored in a coded form in Save_Misc_Values(),\n\t**\twhich may or may not be a HousesType number; so, saving 'house'\n\t**\there ensures we can always pull out the house for this file.)\n\t*/\n\tchar descr_buf[DESCRIP_MAX];\n\tmemset(descr_buf, '\\0', sizeof(descr_buf));\n\tsprintf(descr_buf, \"%s\\r\\n\", descr);\t\t\t// put CR-LF after text\n\tdescr_buf[strlen(descr_buf) + 1] = 26;\t\t// put CTRL-Z after NULL\n\tfpipe.Put(descr_buf, DESCRIP_MAX);\n\n\tfpipe.Put(&scenario, sizeof(scenario));\n\n\tfpipe.Put(&house, sizeof(house));\n\n\t/*\n\t**\tSave the save-game version, for loading verification\n\t*/\n\tunsigned long version = SAVEGAME_VERSION;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tversion++;\n#endif\n\tfpipe.Put(&version, sizeof(version));\n\n\tint pos = file.Seek(0, SEEK_CUR);\n\n\t/*\n\t**\tStore a dummy message digest.\n\t*/\n\tchar digest[20];\n\tfpipe.Put(digest, sizeof(digest));\n\n\n\t/*\n\t**\tDump the save game data to the file. The data is compressed\n\t**\tand then encrypted. The message digest is calculated in the\n\t**\tprocess by using the data just as it is written to disk.\n\t*/\n\tSHAPipe sha;\n\tBlowPipe bpipe(BlowPipe::ENCRYPT);\n\tLZOPipe pipe(LZOPipe::COMPRESS, SAVE_BLOCK_SIZE);\n//\tLZWPipe pipe(LZWPipe::COMPRESS, SAVE_BLOCK_SIZE);\n//\tLCWPipe pipe(LCWPipe::COMPRESS, SAVE_BLOCK_SIZE);\n\tbpipe.Key(&FastKey, BlowfishEngine::MAX_KEY_LENGTH);\n\n\tsha.Put_To(fpipe);\n\tbpipe.Put_To(sha);\n\tpipe.Put_To(bpipe);\n\tPut_All(pipe, save_net);\n\n\t/*\n\t**\tOutput the real final message digest. This is the one that is of\n\t**\tthe data image as it exists on the disk.\n\t*/\n\tpipe.Flush();\n\tfile.Seek(pos, SEEK_SET);\n\tsha.Result(digest);\n\tfpipe.Put(digest, sizeof(digest));\n\n\tpipe.End();\n\n\tDecode_All_Pointers();\n\n\treturn(true);\n}\n\n\n/***************************************************************************\n * Load_Game -- loads a saved game                                         *\n *                                                                         *\n * This routine loads the data in the same way it was saved out.           *\n *                                                                         *\n * Loading the Map:                                                        *\n *   - DisplayClass::Load() invokes CellClass's Load() for every cell      *\n *     that was saved.                                                     *\n * - The cell loads its own CellTrigger pointer.                           *\n *                                                                         *\n * Loading game objects:                                                   *\n * - IHeap's Load() routine loads the # of objects stored, and loads       *\n *   each object.                                                          *\n * - Triggers: Add themselves to the HouseTriggers if they're associated   *\n *   with a house                                                          *\n *                                                                         *\n * Loading the layers:                                                     *\n *     LayerClass::Load() reads the entire layer array to disk             *\n *                                                                         *\n * Loading the houses:                                                     *\n *   Each house is loaded in its entirety.                                 *\n *                                                                         *\n * Loading miscellaneous data:                                             *\n *   There are a lot of miscellaneous variables to load, such as the       *\n *     map's dimensions, the player's house, etc.                          *\n *                                                                         *\n * INPUT:                                                                  *\n *      id         numerical ID, for the file extension                    *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      true = OK, false = error                                           *\n *                                                                         *\n * WARNINGS:                                                               *\n *      If this routine returns false, the entire game will be in an       *\n *      unknown state, so the scenario will have to be re-initialized.     *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/28/1994 BR : Created. \t\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n *   1/20/97  V.Grippi Added expansion CD check                            *\n *=========================================================================*/\nbool Load_Game(int id)\n{\n\tchar name[_MAX_FNAME+_MAX_EXT];\n\tint i;\n\tunsigned scenario;\n\tHousesType house;\n\tchar descr_buf[DESCRIP_MAX];\n\tint load_net = 0;\t\t\t\t\t\t\t\t\t// 1 = save network/modem game\n\n\n\t/*\n\t**\tGenerate the filename to load.  If 'id' is -1, it means save a\n\t** network/modem game; otherwise, use 'id' as the file extension.\n\t*/\n\tif (id == -1) {\n\t\tstrcpy(name, NET_SAVE_FILE_NAME);\n\t\tload_net = 1;\n\t} else {\n\t\tsprintf(name, \"SAVEGAME.%03d\", id);\n\t}\n\n\t/*\n\t**\tOpen the file\n\t*/\n\tRawFileClass file(name);\n\tif (!file.Is_Available()) {\n\t\treturn(false);\n\t}\n\n\tFileStraw fstraw(file);\n\n\tCall_Back();\n\n\t/*\n\t**\tRead & discard the save-game's header info\n\t*/\n\tif (fstraw.Get(descr_buf, DESCRIP_MAX) != DESCRIP_MAX) {\n\t\treturn(false);\n\t}\n\n\tif (fstraw.Get(&scenario, sizeof(scenario)) != sizeof(scenario)) {\n\t\treturn(false);\n\t}\n\n\tif (fstraw.Get(&house, sizeof(house)) != sizeof(house)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tRead in & verify the save-game ID code\n\t*/\n\tunsigned long version;\n\tif (fstraw.Get(&version, sizeof(version)) != sizeof(version)) {\n\t\treturn(false);\n\t}\n\tGameVersion = version;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (version != SAVEGAME_VERSION && ((version-1) != SAVEGAME_VERSION) ) {\n\t      \treturn(false);\n\t}\n#else\n\tif (version != SAVEGAME_VERSION /*&& version != 0x0100616D*/){\n\t      \treturn(false);\n\t}\n#endif\n\t/*\n\t**\tGet the message digest that is embedded in the file.\n\t*/\n\tchar digest[20];\n\tfstraw.Get(digest, sizeof(digest));\n\n\t/*\n\t**\tRemember the file position since we must seek back here to\n\t**\tperform the real saved game read.\n\t*/\n\tlong pos = file.Seek(0, SEEK_CUR);\n\n\t/*\n\t**\tPass the rest of the file through the hash straw so that\n\t**\tthe digest can be compaired to the one in the file.\n\t*/\n\tSHAStraw sha;\n\tsha.Get_From(fstraw);\n\tfor (;;) {\n\t\tif (sha.Get(_staging_buffer, sizeof(_staging_buffer)) != sizeof(_staging_buffer)) break;\n\t}\n\tchar actual[20];\n\tsha.Result(actual);\n\tsha.Get_From(NULL);\n\n\tCall_Back();\n\n\t/*\n\t**\tCompare the two digests. If they differ then return a failure condition\n\t**\tbefore any damage could be done.\n\t*/\n\tif (memcmp(actual, digest, sizeof(digest)) != 0) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tSet up the pipe so that the scenario data can be read.\n\t*/\n\tfile.Seek(pos, SEEK_SET);\n\tBlowStraw bstraw(BlowStraw::DECRYPT);\n\tLZOStraw straw(LZOStraw::DECOMPRESS, SAVE_BLOCK_SIZE);\n//\tLZWStraw straw(LZWStraw::DECOMPRESS, SAVE_BLOCK_SIZE);\n//\tLCWStraw straw(LCWStraw::DECOMPRESS, SAVE_BLOCK_SIZE);\n\n\tbstraw.Key(&FastKey, BlowfishEngine::MAX_KEY_LENGTH);\n\tbstraw.Get_From(fstraw);\n\tstraw.Get_From(bstraw);\n\n\t/*\n\t**\tClear the scenario so we start fresh; this calls the Init_Clear() routine\n\t**\tfor the Map, and all object arrays.  It has the following important\n\t**\teffects:\n\t**\t- Every cell is cleared to 0's, via MapClass::Init_Clear()\n\t**\t- All heap elements' are cleared\n\t**\t- The Houses are Initialized, which also clears their HouseTriggers\n\t**\t  array\n\t**\t- The map's Layers & Logic Layer are cleared to empty\n\t**\t- The list of currently-selected objects is cleared\n\t*/\n\tClear_Scenario();\n\n\t/*\n\t**\tLoad the scenario global information.\n\t*/\n\tstraw.Get(&Scen, sizeof(Scen));\n\n\t/*\n\t**\tFixup the Sessionclass scenario info so we can work out which\n\t** CD to request later\n\t*/\n\tif ( load_net ){\n\n\t\tCCFileClass scenario_file (Scen.ScenarioName);\n\t\tif ( !scenario_file.Is_Available() ){\n\n\t\t\tint cd = -1;\n\t\t\tif (Is_Mission_Counterstrike (Scen.ScenarioName)) {\n\t\t\t\tcd = 2;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif (Expansion_AM_Present()) {\n\t\t\t\t\tint current_drive = CCFileClass::Get_CD_Drive();\n\t\t\t\t\tint index = Get_CD_Index(current_drive, 1*60);\n\t\t\t\t\tif (index == 3) cd = 3;\n\t\t\t\t}\n#endif\n\t\t\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif (Is_Mission_Aftermath (Scen.ScenarioName)) {\n\t\t\t\tcd = 3;\n#ifdef BOGUSCD\n\tcd = -1;\n#endif\n\t\t\t}\n#endif\n\t\t\tRequiredCD = cd;\n\t\t\tif (!Force_CD_Available (RequiredCD)) {\n\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Update the internal list of scenarios to include the counterstrike\n\t\t\t** list.\n\t\t\t*/\n\t\t\tSession.Read_Scenario_Descriptions();\n\t\t} else {\n\t\t\t/*\n\t\t\t** The scenario is available so set RequiredCD to whatever is currently\n\t\t\t** in the drive.\n\t\t\t*/\n\t\t\tint current_drive = CCFileClass::Get_CD_Drive();\n\t\t\tRequiredCD = Get_CD_Index(current_drive, 1*60);\n\t\t}\n\t}\n\n\t/*\n\t**\tLoad the map.  The map comes first, since it loads the Theater & init's\n\t**\tmixfiles.  The map calls all the type-class's Init routines, telling them\n\t**\twhat the Theater is; this must be done before any objects are created, so\n\t**\tthey'll be properly created.\n\t*/\n\tMap.Load(straw);\n\n\tCall_Back();\n\n\t/*\n\t**\tLoad the object data.\n\t*/\n\tHouses.Load(straw);\n\tTeamTypes.Load(straw);\n\tTeams.Load(straw);\n\tTriggerTypes.Load(straw);\n\tTriggers.Load(straw);\n\tAircraft.Load(straw);\n\tAnims.Load(straw);\n\tBuildings.Load(straw);\n\tBullets.Load(straw);\n\n\tCall_Back();\n\n\tInfantry.Load(straw);\n\tOverlays.Load(straw);\n\tSmudges.Load(straw);\n\tTemplates.Load(straw);\n\tTerrains.Load(straw);\n\tUnits.Load(straw);\n\tFactories.Load(straw);\n\tVessels.Load(straw);\n\n\t/*\n\t**\tLoad the Logic & Map Layers\n\t*/\n\tLogic.Load(straw);\n\n\tint count;\n\tstraw.Get(&count, sizeof(count));\n\tMapTriggers.Clear();\n\tfor (int index = 0; index < count; index++) {\n\t\tTARGET target;\n\t\tstraw.Get(&target, sizeof(target));\n\t\tMapTriggers.Add(As_Trigger(target));\n\t}\n\n\tstraw.Get(&count, sizeof(count));\n\tLogicTriggers.Clear();\n\tfor (index = 0; index < count; index++) {\n\t\tTARGET target;\n\t\tstraw.Get(&target, sizeof(target));\n\t\tLogicTriggers.Add(As_Trigger(target));\n\t}\n\n\tfor (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\tstraw.Get(&count, sizeof(count));\n\t\tHouseTriggers[h].Clear();\n\t\tfor (index = 0; index < count; index++) {\n\t\t\tTARGET target;\n\t\t\tstraw.Get(&target, sizeof(target));\n\t\t\tHouseTriggers[h].Add(As_Trigger(target));\n\t\t}\n\t}\n\n\tfor (i = 0; i < LAYER_COUNT; i++) {\n\t\tMap.Layer[i].Load(straw);\n\t}\n\n\tCall_Back();\n\n\t/*\n\t**\tLoad the Score\n\t*/\n\tstraw.Get(&Score, sizeof(Score));\n\tnew(&Score) ScoreClass(NoInitClass());\n\n\t/*\n\t**\tLoad the AI Base\n\t*/\n\tBase.Load(straw);\n\n\t/*\n\t**\tDelete any carryover pseudo-saved game list.\n\t*/\n\twhile (Carryover != NULL) {\n\t\tCarryoverClass * cptr = (CarryoverClass *)Carryover->Get_Next();\n\t\tCarryover->Remove();\n\t\tdelete Carryover;\n\t\tCarryover = cptr;\n\t}\n\n\t/*\n\t**\tLoad any carryover pseudo-saved game list.\n\t*/\n\tint carry_count = 0;\n\tstraw.Get(&carry_count, sizeof(carry_count));\n\twhile (carry_count) {\n\t\tCarryoverClass * cptr = new CarryoverClass;\n\t\tassert(cptr != NULL);\n\n\t\tstraw.Get(cptr, sizeof(CarryoverClass));\n\t\tnew (cptr) CarryoverClass(NoInitClass());\n\t\tcptr->Zap();\n\n\t\tif (!Carryover) {\n\t\t\tCarryover = cptr;\n\t\t} else {\n\t\t\tcptr->Add_Tail(*Carryover);\n\t\t}\n\t\tcarry_count--;\n\t}\n\n\tCall_Back();\n\n\t/*\n\t**\tLoad miscellaneous variables, including the map size & the Theater\n\t*/\n\tLoad_Misc_Values(straw);\n\n\t/*\n\t**\tLoad multiplayer values\n\t*/\n\tif (load_net) {\n\t\tLoad_MPlayer_Values(straw);\n\t}\n\n\tfile.Close();\n\tDecode_All_Pointers();\n\tMap.Init_IO();\n\tMap.Flag_To_Redraw(true);\n\n\t/*\n\t**\tFixup any expediency data that can be inferred from the physical\n\t**\tdata loaded.\n\t*/\n\tPost_Load_Game(load_net);\n\n\tCall_Back();\n\n\t/*\n\t**\tSet the required CD to be in the drive according to the scenario\n\t**\tloaded.\n\t*/\n\tif (RequiredCD != -2 && !load_net) {\n\n#ifdef FIXIT_ANTS\n\t\t/*\n\t\t**\tDetermines if this an ant mission. Since the ant mission looks no different from\n\t\t**\ta regular mission, examining of the scenario name is the only way to tell.\n\t\t*/\n\t\tif (toupper(Scen.ScenarioName[0]) == 'S' &&\n\t\t\ttoupper(Scen.ScenarioName[1]) == 'C' &&\n\t\t\ttoupper(Scen.ScenarioName[2]) == 'A' &&\n\t\t\ttoupper(Scen.ScenarioName[3]) == '0' &&\n\t\t\ttoupper(Scen.ScenarioName[5]) == 'E' &&\n\t\t\ttoupper(Scen.ScenarioName[6]) == 'A') {\n\n\t\t\tAntsEnabled = true;\n\t\t} else{\n\t\t\tAntsEnabled = false;\n\t\t}\n#endif\n\n\t\tif (Scen.Scenario == 1) {\n\t\t\tRequiredCD = -1;\n\t\t} else {\n#ifdef FIXIT_ANTS\n\t\t\tif (Scen.Scenario > 19 || AntsEnabled) {\n\t\t\t   RequiredCD = 2;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif(Scen.Scenario >= 36) {\n\t\t\t\t\tRequiredCD = 3;\n#ifdef BOGUSCD\n\tRequiredCD = -1;\n#endif\n\t\t\t\t}\n#endif\n\t\t\t} else {\n#endif\t//FIXIT_ANTS\n\t\t\t\tif (PlayerPtr->Class->House != HOUSE_USSR  && PlayerPtr->Class->House != HOUSE_UKRAINE) {\n\t\t\t\t\tRequiredCD = 0;\n\t\t\t\t} else {\n\t\t\t\t\tRequiredCD = 1;\n\t\t\t\t}\n#ifdef FIXIT_ANTS\n\t\t\t}\n#endif\t//FIXIT_ANTS\n\t\t}\n\n\t}else{\n\n\t\tif ( load_net ){\n\n\t\t\tCCFileClass scenario_file (Scen.ScenarioName);\n\n\t\t\t/*\n\t\t\t** Fix up the session class variables\n\t\t\t*/\n\t\t\tfor ( int s=0 ; s<Session.Scenarios.Count() ; s++ ) {\n\t\t\t\tif (Session.Scenarios[s]->Description() == Scen.Description){\n\n\t\t\t\t\tmemcpy (Session.Options.ScenarioDescription, Scen.Description,\n\t\t\t\t\t\t\t\tsizeof (Session.Options.ScenarioDescription));\n\t\t\t\t\tmemcpy (Session.ScenarioFileName, Scen.ScenarioName,\n\t\t\t\t\t\t\t\tsizeof (Session.ScenarioFileName));\n\t\t\t\t\tSession.ScenarioFileLength = scenario_file.Size();\n\t\t\t\t\tmemcpy (Session.ScenarioDigest, Session.Scenarios[s]->Get_Digest(),\n\t\t\t\t\t\t\t\tsizeof (Session.ScenarioDigest));\n\t\t\t\t\tSession.ScenarioIsOfficial = Session.Scenarios[s]->Get_Official();\n\t\t\t\t\tScen.Scenario = s;\n\t\t\t\t\tSession.Options.ScenarioIndex = s;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!Force_CD_Available(RequiredCD)) {\n\t\t//Prog_End();\n\t\tEmergency_Exit(EXIT_FAILURE);\n\t}\n\n\tScenarioInit = 0;\n\n\tif (load_net) {\n\n\t\tif (!Reconcile_Players()) {\t// (must do after Decode pointers)\n\t\t\treturn(false);\n\t\t}\n\t\t//!!!!!!!!!! put Fixup_Player_Units() here\n\t\tSession.LoadGame = true;\n\t}\n\n\tMap.Reload_Sidebar();\t// re-load sidebar art.\n\n\t/*\n\t**\tRescan the scenario file for any rules updates.\n\t*/\n\tCCINIClass ini;\n\tint result = ini.Load(CCFileClass(Scen.ScenarioName), true);\n\n\t/*\n\t**\tReset the rules values to their initial settings.\n\t*/\n\tRule.General(RuleINI);\n\tRule.Recharge(RuleINI);\n\tRule.AI(RuleINI);\n\tRule.Powerups(RuleINI);\n\tRule.Land_Types(RuleINI);\n\tRule.Themes(RuleINI);\n\tRule.IQ(RuleINI);\n\tRule.Objects(RuleINI);\n\tRule.Difficulty(RuleINI);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98 - But does this incorporate *changes*? - NO.\n\tRule.General(AftermathINI);\n\tRule.Recharge(AftermathINI);\n\tRule.AI(AftermathINI);\n\tRule.Powerups(AftermathINI);\n\tRule.Land_Types(AftermathINI);\n\tRule.Themes(AftermathINI);\n\tRule.IQ(AftermathINI);\n\tRule.Objects(AftermathINI);\n\tRule.Difficulty(AftermathINI);\n#endif\n\n\t/*\n\t**\tOverride any rules values specified in this\n\t**\tparticular scenario file.\n\t*/\n\tRule.General(ini);\n\tRule.Recharge(ini);\n\tRule.AI(ini);\n\tRule.Powerups(ini);\n\tRule.Land_Types(ini);                               \\\n\tRule.Themes(ini);\n\tRule.IQ(ini);\n\tRule.Objects(ini);\n\tRule.Difficulty(ini);\n#ifdef FIXIT_CSII\t//\tajw - Added runtime check for Aftermath to skirmish mode.\n\tif (load_net) {\n\t\tbool readini = false;\n\t\tswitch(Session.Type) {\n\t\t\tcase GAME_NORMAL:\n\t\t\t\treadini = false;\n\t\t\t\tbreak;\n\t\t\tcase GAME_SKIRMISH:\n\t\t\t\treadini = Is_Aftermath_Installed();\n\t\t\t\tbreak;\n\t\t\tdefault:\n#ifdef FIXIT_VERSION_3\n\t\t\t\treadini = bAftermathMultiplayer;\n#else\n\t\t\t\tif (PlayingAgainstVersion >= VERSION_AFTERMATH_CS) {\n\t\t\t\t\treadini = true;\n\t\t\t\t}\n#endif\n\t\t\t\tbreak;\n\t\t}\n\t\tif(readini) {\n\t\t\t/*\n\t\t\t** Find out if the CD in the current drive is the Aftermath disc.\n\t\t  \t*/\n\t\t\tif(Get_CD_Index(CCFileClass::Get_CD_Drive(), 1*60) != 3) {\n\t\t\t\tGamePalette.Set(FADE_PALETTE_FAST, Call_Back);\n\t\t\t\tif (!Force_CD_Available(3)) {\t// force Aftermath CD in drive.\n   \t   \t\t//Prog_End();\n#ifndef FIXIT_VERSION_3\t\t\t//\tWChat eliminated.\n#ifdef WIN32\nif(Special.IsFromWChat || SpawnedFromWChat) {\n\tchar packet[10] = {\"Hello\"};\n\tSend_Data_To_DDE_Server (packet, strlen(packet), DDEServerClass::DDE_CONNECTION_FAILED);\n}\n#endif\n#endif\n\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t     \t}\n\t\t\t}\n\t\t\tCCINIClass mpini;\n\t\t\tif (mpini.Load(CCFileClass(\"MPLAYER.INI\"), false)) {\n\t\t\t\tRule.General(mpini);\n\t\t\t\tRule.Recharge(mpini);\n\t\t\t\tRule.AI(mpini);\n\t\t\t\tRule.Powerups(mpini);\n\t\t\t\tRule.Land_Types(mpini);\n\t\t\t\tRule.Themes(mpini);\n\t\t\t\tRule.IQ(mpini);\n\t\t\t\tRule.Objects(mpini);\n\t\t\t\tRule.Difficulty(mpini);\n\t\t\t}\n\t\t}\n\n\t}\n#endif\n\tif (Scen.TransitTheme == THEME_NONE) {\n\t\tTheme.Queue_Song(THEME_FIRST);\n\t} else {\n\t\tTheme.Queue_Song(Scen.TransitTheme);\n\t}\n\treturn(true);\n}\n\n\n/***************************************************************************\n * Save_Misc_Values -- saves miscellaneous variables                       *\n *                                                                         *\n * INPUT:                                                                  *\n *      file      file to use for writing                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      true = success, false = failure                                    *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/29/1994 BR : Created.                                              *\n *   03/12/1996 JLB : Simplified.                                          *\n *=========================================================================*/\nbool Save_Misc_Values(Pipe & file)\n{\n\tint i;\n\tint count;\t\t\t\t\t\t\t\t// # ptrs in 'CurrentObject'\n\tObjectClass * ptr;\t\t\t\t\t// for saving 'CurrentObject' ptrs\n\n\t/*\n\t**\tPlayer's House.\n\t*/\n\tint x = PlayerPtr->Class->House;\n\tfile.Put(&x, sizeof(x));\n\n\t/*\n\t**\tSave frame #.\n\t*/\n\tfile.Put(&Frame, sizeof(Frame));\n\n\t/*\n\t**\tSave currently-selected objects list.\n\t**\tSave the # of ptrs in the list.\n\t*/\n\tcount = CurrentObject.Count();\n\tfile.Put(&count, sizeof(count));\n\n\t/*\n\t**\tSave the pointers.\n\t*/\n\tfor (i = 0; i < count; i++) {\n\t\tptr = CurrentObject[i];\n\t\tfile.Put(&ptr, sizeof(ptr));\n\t}\n\n\t/*\n\t** Save the chronal vortex\n\t*/\n\tChronalVortex.Save(file);\n\n\t/*\n\t**\tSave Tanya flags.\n\t*/\n\tfile.Put(&IsTanyaDead, sizeof(IsTanyaDead));\n\tfile.Put(&SaveTanya, sizeof(SaveTanya));\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Load_Misc_Values -- Loads miscellaneous variables.                                          *\n *                                                                                             *\n * INPUT:   file  -- The file to load the misc values from.                                    *\n *                                                                                             *\n * OUTPUT:  Was the misc load process successful?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/24/1995 BRR : Created.                                                                 *\n *   03/12/1996 JLB : Simplified.                                                              *\n *=============================================================================================*/\nbool Load_Misc_Values(Straw & file)\n{\n\tObjectClass * ptr;\t\t\t\t\t// for loading 'CurrentObject' ptrs\n\n\t/*\n\t**\tPlayer's House.\n\t*/\n\tint x;\n\tfile.Get(&x, sizeof(x));\n//\tfile.Get(&PlayerPtr, sizeof(PlayerPtr));\n\tPlayerPtr = HouseClass::As_Pointer((HousesType)x);\n\n\t/*\n\t**\tLoad frame #.\n\t*/\n\tfile.Get(&Frame, sizeof(Frame));\n\n\t/*\n\t**\tLoad currently-selected objects list.\n\t**\tLoad the # of ptrs in the list.\n\t*/\n\tint count;\t\t\t\t\t\t\t\t// # ptrs in 'CurrentObject'\n\tfile.Get(&count, sizeof(count));\n\n\t/*\n\t**\tLoad the pointers.\n\t*/\n\tfor (int i = 0; i < count; i++) {\n\t\tfile.Get(&ptr, sizeof(ptr));\n\t\tCurrentObject.Add(ptr);\t// add to the list\n\t}\n\n\t/*\n\t** Load the chronal vortex\n\t*/\n\tChronalVortex.Load(file);\n\n\t/*\n\t**\tSave Tanya flags.\n\t*/\n\tfile.Get(&IsTanyaDead, sizeof(IsTanyaDead));\n\tfile.Get(&SaveTanya, sizeof(SaveTanya));\n\n\treturn(true);\n}\n\n\n/***************************************************************************\n * Save_MPlayer_Values -- Saves multiplayer-specific values                *\n *                                                                         *\n * This routine saves multiplayer values that need to be restored for a\t\t*\n * save game.  In addition to saving the random # seed for this scenario, \t*\n * it saves the contents of the actual random number generator; this \t\t*\n * ensures that the random # sequencer will pick up where it left off when\t*\n * the game was saved.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This routine also saves the header for a Recording file, so it must \t\t*\n * save some data not needed specifically by a save-game file (ie Seed).\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\tfile to save to\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = success, false = failure\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/28/1995 BRR : Created.                                             *\n *=========================================================================*/\nbool Save_MPlayer_Values(Pipe & file)\n{\n\tSession.Save(file);\n\tfile.Put(&BuildLevel, sizeof(BuildLevel));\n\tfile.Put(&Debug_Unshroud, sizeof(Debug_Unshroud));\n\tfile.Put(&Seed, sizeof(Seed));\n\tfile.Put(&Whom, sizeof(Whom));\n\tfile.Put(&Special, sizeof(SpecialClass));\n\tfile.Put(&Options, sizeof(GameOptionsClass));\n\n\treturn (true);\n}\n\n\n/***************************************************************************\n * Load_MPlayer_Values -- Loads multiplayer-specific values                *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\t\tfile to load from\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = success, false = failure\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/28/1995 BRR : Created.                                             *\n *=========================================================================*/\nbool Load_MPlayer_Values(Straw & file)\n{\n\tSession.Load(file);\n\tfile.Get(&BuildLevel, sizeof(BuildLevel));\n\tfile.Get(&Debug_Unshroud, sizeof(Debug_Unshroud));\n\tfile.Get(&Seed, sizeof(Seed));\n\tfile.Get(&Whom, sizeof(Whom));\n\tfile.Get(&Special, sizeof(SpecialClass));\n\tfile.Get(&Options, sizeof(GameOptionsClass));\n\n\treturn (true);\n}\n\n\n/***********************************************************************************************\n * Code_All_Pointers -- Code all pointers.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid Code_All_Pointers(void)\n{\n\tint i;\n\n\t/*\n\t**\tThe Map.\n\t*/\n\tMap.Code_Pointers();\n\n\t/*\n\t**\tThe ArrayOf's.\n\t*/\n\tTeamTypes.Code_Pointers();\n\tTeams.Code_Pointers();\n\tTriggers.Code_Pointers();\n\tAircraft.Code_Pointers();\n\tAnims.Code_Pointers();\n\tBuildings.Code_Pointers();\n\tBullets.Code_Pointers();\n\tInfantry.Code_Pointers();\n\tOverlays.Code_Pointers();\n\tSmudges.Code_Pointers();\n\tTemplates.Code_Pointers();\n\tTerrains.Code_Pointers();\n\tUnits.Code_Pointers();\n\tFactories.Code_Pointers();\n\tVessels.Code_Pointers();\n\n\t/*\n\t**\tThe Layers.\n\t*/\n\tLogic.Code_Pointers();\n\tfor (i = 0; i < LAYER_COUNT; i++) {\n\t\tMap.Layer[i].Code_Pointers();\n\t}\n\n\t/*\n\t**\tThe Score.\n\t*/\n\tScore.Code_Pointers();\n\n\t/*\n\t**\tThe Base.\n\t*/\n\tBase.Code_Pointers();\n\n\t/*\n\t**\tPlayerPtr.\n\t*/\n//\tPlayerPtr = (HouseClass *)(PlayerPtr->Class->House);\n\n\t/*\n\t**\tCurrently-selected objects.\n\t*/\n\tfor (i = 0; i < CurrentObject.Count(); i++) {\n\t\tCurrentObject[i] = (ObjectClass *)CurrentObject[i]->As_Target();\n\t}\n\n\t/*\n\t** Houses must be coded last, because the Class->House member of the HouseClass\n\t** is used to code HouseClass pointers for all other objects, and if Class is\n\t** coded, it will point to a meaningless value.\n\t*/\n\tHouses.Code_Pointers();\n}\n\n\n/***********************************************************************************************\n * Decode_All_Pointers -- Decodes all pointers.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid Decode_All_Pointers(void)\n{\n\t/*\n\t**\tThe Map.\n\t*/\n\tMap.Decode_Pointers();\n\n\t/*\n\t** Decode houses first, so we can properly decode all other objects'\n\t** House pointers\n\t*/\n\tHouses.Decode_Pointers();\n\n\t/*\n\t**\tThe ArrayOf's.\n\t*/\n\tTeamTypes.Decode_Pointers();\n\tTeams.Decode_Pointers();\n\tTriggers.Decode_Pointers();\n\tAircraft.Decode_Pointers();\n\tAnims.Decode_Pointers();\n\tBuildings.Decode_Pointers();\n\tBullets.Decode_Pointers();\n\tInfantry.Decode_Pointers();\n\tOverlays.Decode_Pointers();\n\tSmudges.Decode_Pointers();\n\tTemplates.Decode_Pointers();\n\tTerrains.Decode_Pointers();\n\tUnits.Decode_Pointers();\n\tFactories.Decode_Pointers();\n\tVessels.Decode_Pointers();\n\n\t/*\n\t**\tThe Layers.\n\t*/\n\tLogic.Decode_Pointers();\n\tfor (int i = 0; i < LAYER_COUNT; i++) {\n\t\tMap.Layer[i].Decode_Pointers();\n\t}\n\n\t/*\n\t**\tThe Score.\n\t*/\n\tScore.Decode_Pointers();\n\n\t/*\n\t**\tThe Base.\n\t*/\n\tBase.Decode_Pointers();\n\n\t/*\n\t**\tPlayerPtr.\n\t*/\n//\tPlayerPtr = HouseClass::As_Pointer((HousesType)PlayerPtr);\n\tWhom = PlayerPtr->Class->House;\n\tassert(PlayerPtr != NULL);\n\n\t/*\n\t**\tCurrently-selected objects.\n\t*/\n\tfor (int index = 0; index < CurrentObject.Count(); index++) {\n\t\tCurrentObject[index] = As_Object((TARGET)CurrentObject[index]);\n\t\tassert(CurrentObject[index] != NULL);\n\t}\n\n\t/*\n\t**\tLast-Minute Fixups; to resolve these pointers properly requires all other\n\t**\tpointers to be loaded & decoded.\n\t*/\n\tif (Map.PendingObjectPtr) {\n\t\tMap.PendingObject = &Map.PendingObjectPtr->Class_Of();\n\t\tassert(Map.PendingObject != NULL);\n\t\tMap.Set_Cursor_Shape(Map.PendingObject->Occupy_List(true));\n#ifdef BG\n\t\tMap.Set_Placement_List(Map.PendingObject->Placement_List(true));\n#endif\n\t} else {\n\t\tMap.PendingObject = 0;\n\t\tMap.Set_Cursor_Shape(0);\n\t}\n}\n\n\n/***************************************************************************\n * Get_Savefile_Info -- gets description, scenario #, house                *\n *                                                                         *\n * INPUT:                                                                  *\n *      id         numerical ID, for the file extension                    *\n *      buf      buffer to store description in                            *\n *      scenp      ptr to variable to hold scenario                        *\n *      housep   ptr to variable to hold house                             *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      true = OK, false = error (save-game file invalid)                  *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/12/1995 BR : Created.                                              *\n *=========================================================================*/\nbool Get_Savefile_Info(int id, char * buf, unsigned * scenp, HousesType * housep)\n{\n\tchar name[_MAX_FNAME+_MAX_EXT];\n\tunsigned long version;\n\tchar descr_buf[DESCRIP_MAX];\n\n\t/*\n\t**\tGenerate the filename to load\n\t*/\n\tsprintf(name, \"SAVEGAME.%03d\", id);\n\tBufferIOFileClass file(name);\n\n\tFileStraw straw(file);\n\n\t/*\n\t**\tRead in the description, scenario #, and the house\n\t*/\n\tif (straw.Get(descr_buf, DESCRIP_MAX) != DESCRIP_MAX) {\n\t\treturn(false);\n\t}\n\n\tdescr_buf[strlen(descr_buf) - 2] = '\\0';\t// trim off CR/LF\n\tstrcpy(buf, descr_buf);\n\n\tif (straw.Get(scenp, sizeof(unsigned)) != sizeof(unsigned)) {\n\t\treturn(false);\n\t}\n\n\tif (straw.Get(housep, sizeof(HousesType)) != sizeof(HousesType)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tRead & verify the save-game version #\n\t*/\n\tif (straw.Get(&version, sizeof(version)) != sizeof(version)) {\n\t\treturn(false);\n\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (version != SAVEGAME_VERSION && ((version-1 != SAVEGAME_VERSION)) ) {\n#else\n\tif (version != SAVEGAME_VERSION) {\n#endif\n\t\treturn(false);\n\t}\n\treturn(true);\n}\n\n\n/***************************************************************************\n * Reconcile_Players -- Reconciles loaded data with the 'Players' vector\t*\n *                                                                         *\n * This function is for supporting loading a saved multiplayer game.  \t\t*\n * When the game is loaded, we have to figure out which house goes with\t\t*\n * which entry in the Players vector.  We also have to figure out if \t\t*\n * everyone who was originally in the game is still with us, and if not, \t*\n * turn their stuff over to the computer.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * So, this function does the following:\t\t\t\t\t\t\t\t\t\t\t\t*\n * - For every name in 'Players', makes sure that name is in the House\t\t*\n *   array; if not, it's a fatal error.\t\t\t\t\t\t\t\t\t\t\t\t*\n * - For every human-controlled house, makes sure there's a player\t \t\t*\n *   with that name; if not, it turns that house over to the computer.\t\t*\n * - Fills in the Player's house ID\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * This assumes that each player MUST keep their name the same as it was\t*\n * when the game was saved!  It's also assumed that the network \t\t\t\t*\n * connections have not been formed yet, since Player[i]->Player.ID will\t*\n * be invalid until this routine has been called.\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = OK, false = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Reconcile_Players(void)\n{\n\tint i;\n\tint found;\n\tHousesType house;\n\tHouseClass * housep;\n\n\t/*\n\t**\tIf there are no players, there's nothing to do.\n\t*/\n\tif (Session.Players.Count()==0)\n\t\treturn (true);\n\n\t/*\n\t**\tMake sure every name we're connected to can be found in a House\n\t*/\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\tfound = 0;\n\t\tfor (house = HOUSE_MULTI1; house < HOUSE_MULTI1 +\n\t\t\tSession.MaxPlayers; house++) {\n\n\t\t\thousep = HouseClass::As_Pointer(house);\n\t\t\tif (!housep) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!stricmp(Session.Players[i]->Name, housep->IniName)) {\n\t\t\t\tfound = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!found)\n\t\t\treturn (false);\n\t}\n\n\t//\n\t// Loop through all Houses; if we find a human-owned house that we're\n\t// not connected to, turn it over to the computer.\n\t//\n\tfor (house = HOUSE_MULTI1; house < HOUSE_MULTI1 +\n\t\tSession.MaxPlayers; house++) {\n\t\thousep = HouseClass::As_Pointer(house);\n\t\tif (!housep) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t//\n\t\t// Skip this house if it wasn't human to start with.\n\t\t//\n\t\tif (!housep->IsHuman) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t//\n\t\t// Try to find this name in the Players vector; if it's found, set\n\t\t// its ID to this house.\n\t\t//\n\t\tfound = 0;\n\t\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\t\tif (!stricmp(Session.Players[i]->Name, housep->IniName)) {\n\t\t\t\tfound = 1;\n\t\t\t\tSession.Players[i]->Player.ID = house;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf this name wasn't found, remove it\n\t\t*/\n\t\tif (!found) {\n\n\t\t\t/*\n\t\t\t**\tTurn the player's house over to the computer's AI\n\t\t\t*/\n\t\t\thousep->IsHuman = false;\n\t\t\thousep->IsStarted = true;\n//\t\t\thousep->Smartness = IQ_MENSA;\n\t\t\thousep->IQ = Rule.MaxIQ;\n\t\t\tstrcpy (housep->IniName, Text_String(TXT_COMPUTER));\n\n\t\t\tSession.NumPlayers--;\n\t\t}\n\t}\n\n\t//\n\t// If all went well, our Session.NumPlayers value should now equal the value\n\t// from the saved game, minus any players we removed.\n\t//\n\tif (Session.NumPlayers == Session.Players.Count()) {\n\t\treturn (true);\n\t} else {\n\t\treturn (false);\n\t}\n}\n\n\n/***************************************************************************\n * MPlayer_Save_Message -- pops up a \"saving...\" message                   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/30/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid MPlayer_Save_Message(void)\n{\n\t//char *txt = Text_String(\n}\n\n"
  },
  {
    "path": "CODE/SCENARIO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n//Mono_Printf(\"%d %s\\n\",__LINE__,__FILE__);\n/* $Header: /CounterStrike/SCENARIO.CPP 15    3/13/97 2:06p Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SCENARIO.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : October 21, 1996 [JLB]                                       *\n *                                                                                             *\n * This module handles the scenario reading and writing. Scenario related                      *\n * code that is executed between scenario play can also be here.                               *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Assign_Houses -- Assigns multiplayer houses to various players                            *\n *   Clear_Flag_Spots -- Clears flag overlays off the map                                      *\n *   Clear_Scenario -- Clears all data in preparation for scenario load.                       *\n *   Clip_Move -- moves in given direction from given cell; clips to map                       *\n *   Clip_Scatter -- randomly scatters from given cell; won't fall off map                     *\n *   Create_Units -- Creates infantry & units, for non-base multiplayer                        *\n *   Do_Lose -- Display losing comments.                                                       *\n *   Do_Restart -- Handle the restart mission process.                                         *\n *   Do_Win -- Display winning congratulations.                                                *\n *   Fill_In_Data -- Recreate all data that is not loaded with scenario.                       *\n *   Post_Load_Game -- Fill in an inferred data from the game state.                           *\n *   Read_Scenario -- Reads a scenario from disk.                                              *\n *   Read_Scenario_INI -- Read specified scenario INI file.                                    *\n *   Remove_AI_Players -- Removes the computer AI houses & their units                         *\n *   Restate_Mission -- Handles restating the mission objective.                               *\n *   Scan_Place_Object -- places an object >near< the given cell                               *\n *   ScenarioClass::ScenarioClass -- Constructor for the scenario control object.              *\n *   ScenarioClass::Set_Global_To -- Set scenario global to value specified.                   *\n *   Set_Scenario_Name -- Creates the INI scenario name string.                                *\n *   Start_Scenario -- Starts the scenario.                                                    *\n *   Write_Scenario_INI -- Write the scenario INI file.                                        *\n *   ScenarioClass::Do_BW_Fade -- Cause the palette to temporarily shift to B/W.               *\n *   ScenarioClass::Do_Fade_AI -- Process the palette fading effect.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#ifdef WIN32\n#include \"tcpip.h\"\n#include \"ccdde.h\"\n\nextern bool SpawnedFromWChat;\n#endif\nextern int PreserveVQAScreen;\n\n//#include \"WolDebug.h\"\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n#include \"WolStrng.h\"\n#endif\n\nstatic void Remove_AI_Players(void);\nstatic void Create_Units(bool official);\nstatic CELL Clip_Scatter(CELL cell, int maxdist);\nstatic CELL Clip_Move(CELL cell, FacingType facing, int dist);\n\n\nstatic int _build_tech[11] = {\n\t2,2,\t\t\t// Tech level 0 and 1 are the same (tech 0 is never used).\n\t4,\n\t5,\n\t7,\n\t8,\n\t9,\n\t10,\n\t11,\n\t12,\n\t13\n};\n\n\n#ifdef FRENCH\n#define TXT_HACKHACK  \"Accomplie\"\n#endif\n#if defined(ENGLISH) || defined(GERMAN)\n#define TXT_HACKHACK  Text_String(TXT_ACCOMPLISHED)\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nbool Is_Mission_Counterstrike (char *file_name);\nbool Is_Mission_Aftermath (char *file_name);\n#endif\n\n/***********************************************************************************************\n * ScenarioClass::ScenarioClass -- Constructor for the scenario control object.                *\n *                                                                                             *\n *    This constructs the default scenario control object. Normally, all the default values    *\n *    are meaningless since the act of starting a scenario will fill in all of the values with *\n *    settings retrieved from the scenario control file.                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nScenarioClass::ScenarioClass(void) :\n\tDifficulty(DIFF_NORMAL),\n\tCDifficulty(DIFF_NORMAL),\n\tTimer(0),\n\tMissionTimer(0),\n\tShroudTimer(TICKS_PER_MINUTE * Rule.ShroudRate),\n\tScenario(1),\n\tTheater(THEATER_TEMPERATE),\n\tIntroMovie(VQ_NONE),\n\tBriefMovie(VQ_NONE),\n\tWinMovie(VQ_NONE),\n\tLoseMovie(VQ_NONE),\n\tActionMovie(VQ_NONE),\n\tTransitTheme(THEME_NONE),\n\tPlayerHouse(HOUSE_GREECE),\n\tCarryOverPercent(0),\n\tCarryOverMoney(0),\n\tCarryOverCap(0),\n\tPercent(0),\n\tBridgeCount(0),\n\tCarryOverTimer(0),\n\tIsBridgeChanged(false),\n\tIsGlobalChanged(false),\n\tIsToCarryOver(false),\n\tIsToInherit(false),\n\tIsTanyaEvac(false),\n\tIsFadingBW(false),\n\tIsFadingColor(false),\n\tIsEndOfGame(false),\n\tIsInheritTimer(false),\n\tIsNoSpyPlane(false),\n\tIsSkipScore(false),\n\tIsOneTimeOnly(false),\n\tIsNoMapSel(false),\n\tIsTruckCrate(false),\n\tIsMoneyTiberium(false),\n#ifdef FIXIT_VERSION_3\t\t\t//\tFor endgame auto-sonar pulse.\n#define AUTOSONAR_PERIOD\tTICKS_PER_SECOND * 40\n\tAutoSonarTimer( AUTOSONAR_PERIOD ),\n#endif\n\tFadeTimer(0)\n{\n\tfor (int index = 0; index < ARRAY_SIZE(Waypoint); index++) {\n\t\tWaypoint[index] = -1;\n\t}\n\tstrcpy(Description, \"\");\n\tstrcpy(ScenarioName, \"\");\n\tstrcpy(BriefingText, \"\");\n\tmemset(GlobalFlags, '\\0', sizeof(GlobalFlags));\n\tmemset(Views, '\\0', sizeof(Views));\n}\n\n\n/***********************************************************************************************\n * ScenarioClass::Do_BW_Fade -- Cause the palette to temporarily shift to B/W.                 *\n *                                                                                             *\n *    This routine will start the palette to fade to B/W for a brief moment.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ScenarioClass::Do_BW_Fade(void)\n{\n\tIsFadingBW = true;\n\tIsFadingColor = false;\n\tFadeTimer = GRAYFADETIME;\n}\n\n\n/***********************************************************************************************\n * ScenarioClass::Do_Fade_AI -- Process the palette fading effect.                             *\n *                                                                                             *\n *    This routine will handle the maintenance of the palette fading effect. It should be      *\n *    called once per game frame.                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ScenarioClass::Do_Fade_AI(void)\n{\n\tif (IsFadingColor) {\n\t\tif (FadeTimer == 0) {\n\t\t\tIsFadingColor = false;\n\t\t}\n\t\tfixed newsat = Options.Get_Saturation() * fixed(GRAYFADETIME-FadeTimer, GRAYFADETIME);\n\t\tOptions.Adjust_Palette(OriginalPalette, GamePalette, Options.Get_Brightness(), newsat, Options.Get_Tint(), Options.Get_Contrast());\n\t\tGamePalette.Set();\n\t}\n\tif (IsFadingBW) {\n\t\tif (FadeTimer == 0) {\n\t\t\tIsFadingBW = false;\n\t\t}\n\t\tfixed newsat = Options.Get_Saturation() * fixed(FadeTimer, GRAYFADETIME);\n\t\tOptions.Adjust_Palette(OriginalPalette, GamePalette, Options.Get_Brightness(), newsat, Options.Get_Tint(), Options.Get_Contrast());\n\t\tGamePalette.Set();\n\t\tif (!IsFadingBW) {\n\t\t\tIsFadingColor = true;\n\t\t\tFadeTimer = GRAYFADETIME;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * ScenarioClass::Set_Global_To -- Set scenario global to value specified.                     *\n *                                                                                             *\n *    This routine will set the global flag to the falue (true/false) specified. It will       *\n *    also scan for and spring any triggers that are dependant upon that global.               *\n *                                                                                             *\n * INPUT:   global   -- The global flag to change.                                             *\n *                                                                                             *\n *          value    -- The value to change the global flag to.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the previous value of the flag.                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ScenarioClass::Set_Global_To(int global, bool value)\n{\n\tif ((unsigned)global < ARRAY_SIZE(Scen.GlobalFlags)) {\n\n\t\tbool previous = GlobalFlags[global];\n\t\tif (previous != value) {\n\t\t\tGlobalFlags[global] = value;\n\t\t\tIsGlobalChanged = true;\n\n\t\t\t/*\n\t\t\t**\tSpecial case to scan through all triggers and if any are found that depend on this\n\t\t\t**\tglobal being set/cleared, then if there is an elapsed time event associated, it\n\t\t\t**\twill be reset at this time.\n\t\t\t*/\n\t\t\tfor (int index = 0; index < Triggers.Count(); index++) {\n\t\t\t\tTriggerClass * tp = Triggers.Ptr(index);\n\t\t\t\tif ((tp->Class->Event1.Event == TEVENT_GLOBAL_SET || tp->Class->Event1.Event == TEVENT_GLOBAL_CLEAR) && tp->Class->Event1.Data.Value == global) {\n\t\t\t\t\ttp->Class->Event2.Reset(tp->Event1);\n\t\t\t\t}\n\t\t\t\tif ((tp->Class->Event2.Event == TEVENT_GLOBAL_SET || tp->Class->Event2.Event == TEVENT_GLOBAL_CLEAR) && tp->Class->Event2.Data.Value == global) {\n\t\t\t\t\ttp->Class->Event1.Reset(tp->Event1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn(previous);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * Start_Scenario -- Starts the scenario.                                                      *\n *                                                                                             *\n *    This routine will start the scenario. In addition to loading the scenario data, it will  *\n *    play the briefing and action movies.                                                     *\n *                                                                                             *\n * INPUT:   root     -- Pointer to the filename root for this scenario (e.g., \"SCG01EA\").      *\n *                                                                                             *\n *          briefing -- Should the briefing be played? Normally this is true except when the   *\n *                      scenario is restarting.                                                *\n *                                                                                             *\n * OUTPUT:  Was the scenario started without error?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool Start_Scenario(char * name, bool briefing)\n{\n//BG\tTheme.Queue_Song(THEME_QUIET);\nTheme.Stop();\n\tIsTanyaDead = SaveTanya;\n\tif (!Read_Scenario(name)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tPlay the winning movie and then start the next scenario.\n\t*/\n\tRequiredCD = -1;\n//\tif (RequiredCD != -2 && Session.Type == GAME_NORMAL) {\n//\t\tif (Scen.Scenario == 1)\n//\t\t\tRequiredCD = -1;\n//\t\telse {\n//\t\t\t if((Scen.Scenario >= 20 && Scen.ScenarioName[2] == 'G' || Scen.ScenarioName[2] == 'U') || Scen.ScenarioName[2] == 'A'\n//\t\t\t\t|| (Scen.ScenarioName[2] == 'M' && Scen.Scenario >= 25))\n//\t\t       \t    RequiredCD = 2;\n//\t\t\t else if(Scen.ScenarioName[2] == 'U')\n//\t\t\t    RequiredCD = 1;\n//\t\t\t else if(Scen.ScenarioName[2] == 'G')\n//\t\t\t    RequiredCD = 0;\n//\t\t\t}\n//\n//#ifdef FIXIT_FORCE_CD\n// Forces the CD to be inserted according to the scenario being loaded.\n//Hide_Mouse();\n//VisiblePage.Clear();\n//Show_Mouse();\n//GamePalette.Set();\n//if (!Force_CD_Available(RequiredCD)) {\n//       \tProg_End();\n//       \texit(EXIT_FAILURE);\n//}\n//#endif\n\n\n\n//   \t}\n\tTheme.Stop();\n\n\tif (briefing) {\n\t\tHide_Mouse();\n\t\tVisiblePage.Clear();\n\t\tShow_Mouse();\n\t\tPlay_Movie(Scen.IntroMovie);\n\t\tPlay_Movie(Scen.BriefMovie);\n\t}\n\n\t/*\n\t** If there's no briefing movie, restate the mission at the beginning.\n\t*/\n\tchar buffer[25];\n\tif (Scen.BriefMovie != VQ_NONE) {\n\t\tsprintf(buffer, \"%s.VQA\", VQName[Scen.BriefMovie]);\n\t}\n\tif (Session.Type == GAME_NORMAL && (Scen.BriefMovie == VQ_NONE || !CCFileClass(buffer).Is_Available())) {\n\t\t/*\n\t\t** Make sure the mouse is visible before showing the restatement.\n\t\t*/\n\t\twhile(Get_Mouse_State()) {\n\t\t\tShow_Mouse();\n\t\t}\n\t\tRestate_Mission(Scen.ScenarioName, TXT_OK, TXT_NONE);\n\t}\n\n\tif (briefing) {\n\t\tHide_Mouse();\n\t\tVisiblePage.Clear();\n\t\tShow_Mouse();\n\t\tPlay_Movie(Scen.ActionMovie, Scen.TransitTheme);\n\t}\n\n\tif (Scen.TransitTheme == THEME_NONE) {\n\t\tTheme.Queue_Song(THEME_FIRST);\n\t}\n\n\t/*\n\t** Set the options values, since the palette has been initialized by Read_Scenario\n\t*/\n\tOptions.Set();\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Read_Scenario -- Reads a scenario from disk.                                                *\n *                                                                                             *\n *    This will read a scenario from disk. Use this to begin a scenario.                       *\n *    It doesn't perform any rendering, it merely sets up the system                           *\n *    with the proper data. Setting of the right game state will start                         *\n *    the scenario running.                                                                    *\n *                                                                                             *\n * INPUT:   root     -- Scenario root filename                                                 *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   You must clear out the system variables before calling                          *\n *             this function. Use the Clear_Scenario() function.                               *\n *               It is assumed that Scenario is set to the current scenario number.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/22/1991     : Created.                                                                 *\n *   02/03/1992 JLB : Uses house identification.                                               *\n *=============================================================================================*/\nbool Read_Scenario(char * name)\n{\n\tBStart(BENCH_SCENARIO);\n\tClear_Scenario();\n\tScenarioInit++;\n\tif (Read_Scenario_INI(name)) {\n#ifdef FIXIT_CSII\t//\tajw - Added runtime check for Aftermath to skirmish mode case.\n\t\tbool readini = false;\n\t\tswitch(Session.Type) {\n\t\t\tcase GAME_NORMAL:\n\t\t\t\treadini = false;\n\t\t\t\tbreak;\n\t\t\tcase GAME_SKIRMISH:\n#ifdef FIXIT_VERSION_3\n\t\t\t\treadini = bAftermathMultiplayer;\n#endif\n\t\t\t\tbreak;\n\t\t\tcase GAME_INTERNET:\n#ifndef FIXIT_VERSION_3\t\t\t//\tLoading of Aftermath rules depends on bAftermathMultiplayer now.\n\t\t\t\tif (Is_Mission_Counterstrike(name)) {\n\t\t\t\t\treadini = false;\t// Don't allow AM units on a CS map in WChat\n\t\t\t\t\tbreak;\n\t\t\t\t}\n#endif\t\t//\t( Note lack of break; )\n\t\t\tdefault:\n#ifdef FIXIT_VERSION_3\n\t\t\t\treadini = bAftermathMultiplayer;\n#else\n\t\t\t\tif (PlayingAgainstVersion >= VERSION_AFTERMATH_CS) {\n\t\t\t\t\treadini = true;\n\t\t\t\t}\n#endif\n\t\t\t\tbreak;\n\t\t}\n\t\tif(readini) {\n\t\t\t/*\n\t\t\t** Find out if the CD in the current drive is the Aftermath disc.\n\t\t  \t*/\n#ifdef FIXIT_VERSION_3\n\t\t\tint cd_index = Get_CD_Index(CCFileClass::Get_CD_Drive(), 1*60);\n\t\t\tif( !( Using_DVD() && cd_index == 5 ) && cd_index != 3 ) {\n#else\n\t\t\tif(Get_CD_Index(CCFileClass::Get_CD_Drive(), 1*60) != 3) {\n#endif\n\t\t\t\tGamePalette.Set(FADE_PALETTE_FAST, Call_Back);\n\t\t\t\tRequiredCD = 3;\n\t\t\t\tif (!Force_CD_Available(RequiredCD)) {\t// force Aftermath CD in drive.\n#ifndef WOLAPI_INTEGRATION\n\t\t\t\t\t#ifdef WIN32\n\t\t\t\t\tif(Special.IsFromWChat || SpawnedFromWChat) {\n\t\t\t\t\t\tchar packet[10] = {\"Hello\"};\n\t\t\t\t\tSend_Data_To_DDE_Server (packet, strlen(packet), DDEServerClass::DDE_CONNECTION_FAILED);\n\t\t\t\t\t\t}\n\t\t\t\t\t#endif\n#endif\n\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t     \t}\n\t\t\t}\n\t\t\tCCINIClass ini;\n\t\t\tif (ini.Load(CCFileClass(\"MPLAYER.INI\"), false)) {\n\t\t\t\tRule.General(ini);\n\t\t\t\tRule.Recharge(ini);\n\t\t\t\tRule.AI(ini);\n\t\t\t\tRule.Powerups(ini);\n\t\t\t\tRule.Land_Types(ini);\n\t\t\t\tRule.Themes(ini);\n\t\t\t\tRule.IQ(ini);\n\t\t\t\tRule.Objects(ini);\n\t\t\t\tRule.Difficulty(ini);\n\t\t\t}\n\t\t}\n#endif\n\t\tFill_In_Data();\n\t} else {\n\t\tGamePalette.Set(FADE_PALETTE_FAST, Call_Back);\n//\t\tFade_Palette_To(GamePalette, FADE_PALETTE_FAST, Call_Back);\n\t\tShow_Mouse();\n\t\tWWMessageBox().Process(TXT_UNABLE_READ_SCENARIO);\n\t\tHide_Mouse();\n\t\tBEnd(BENCH_SCENARIO);\n\t\treturn(false);\n\t}\n\tScenarioInit--;\n\tBEnd(BENCH_SCENARIO);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Fill_In_Data -- Recreate all data that is not loaded with scenario.                         *\n *                                                                                             *\n *    This routine is called after the INI file for the scenario has been processed. It will   *\n *    infer the game state from the scenario INI data.                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Fill_In_Data(void)\n{\n\t/*\n\t**\tThe basic scenario data load does not contain the full set of\n\t**\tgame data. We now must fill in the missing pieces.\n\t*/\n\tScenarioInit++;\n\n\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\tBuildings.Ptr(index)->Update_Buildables();\n\t}\n\n\tMap.Flag_To_Redraw(true);\n\n\t/*\n\t**\tReset the movement zones according to the terrain passability.\n\t*/\n\tMap.Zone_Reset(MZONEF_ALL);\n\n\n#ifdef WIN32\n\t/*\n\t**\tSince the sidebar starts up activated, adjust the home start position so that\n\t**\tthe right edge of the map will still be visible.\n\t*/\n\tif (!Debug_Map) {\n\t\tMap.SidebarClass::Activate(1);\n//\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\tScen.Views[0] = Scen.Views[1] = Scen.Views[2] = Scen.Views[3] = Scen.Waypoint[WAYPT_HOME];\n\t\t\tMap.Set_Tactical_Position(Cell_Coord((Scen.Waypoint[WAYPT_HOME] - (MAP_CELL_W * 4 * RESFACTOR)) - (5*RESFACTOR)));\n//\t\t}\n\t}\n#endif\n\n\t/*\n\t**\tHandle any data resetting that can be safely inferred from the actual\n\t**\tdata that has been loaded.\n\t*/\n\t/*\n\t**\tDistribute the trigger pointers to the appropriate working lists.\n\t*/\n\tfor (index = 0; index < TriggerTypes.Count(); index++) {\n\t\tTriggerTypeClass * tp = TriggerTypes.Ptr(index);\n\n\t\tassert(tp != NULL);\n\n\t\tif (tp->Attaches_To() & ATTACH_MAP) {\n\t\t\tMapTriggers.Add(Find_Or_Make(tp));\n\t\t}\n\t\tif (tp->Attaches_To() & ATTACH_GENERAL) {\n\t\t\tLogicTriggers.Add(Find_Or_Make(tp));\n\t\t}\n\t\tif (tp->Attaches_To() & ATTACH_HOUSE) {\n\t\t\tHouseTriggers[tp->House].Add(Find_Or_Make(tp));\n\t\t}\n\t}\n\n\tScenarioInit--;\n\n\t/*\n\t** Now go through and set all the cells ringing the map to be visible, so\n\t** we won't get the wall of shadow at the edge of the map.\n\t*/\n\tint x,y;\n\tfor (x = Map.MapCellX-1; x < ((unsigned)(Map.MapCellX + Map.MapCellWidth + 1)); x++) {\n\t\tMap[XY_Cell(x, Map.MapCellY-1)].IsVisible =\n\t\t\tMap[XY_Cell(x, Map.MapCellY-1)].IsMapped = true;\n\n\t\tMap[XY_Cell(x, Map.MapCellY+(unsigned)Map.MapCellHeight)].IsVisible =\n\t\t\tMap[XY_Cell(x, Map.MapCellY+(unsigned)Map.MapCellHeight)].IsMapped = true;\n\t}\n\tfor (y = Map.MapCellY; y < (Map.MapCellY + Map.MapCellHeight); y++) {\n\t\tMap[XY_Cell(Map.MapCellX-1, y)].IsVisible =\n\t\t\tMap[XY_Cell(Map.MapCellX-1, y)].IsMapped = true;\n\t\tMap[XY_Cell(Map.MapCellX+Map.MapCellWidth, y)].IsVisible =\n\t\t\tMap[XY_Cell(Map.MapCellX+Map.MapCellWidth, y)].IsMapped = true;\n\t}\n\n\t/*\n\t**\tIf inheriting from a previous scenario was indicated, then create the carry over\n\t**\tobjects at this time.\n\t*/\n\tif (Scen.IsToInherit) {\n\t\tCarryoverClass * cptr = Carryover;\n\t\twhile (cptr != NULL) {\n\t\t\tcptr->Create();\n\t\t\tcptr = (CarryoverClass *)cptr->Get_Next();\n\t\t}\n\t}\n\n\t/*\n\t**\tThe \"allow win\" action is a special case that is handled here. The total number\n\t**\tof triggers that have this action must be recorded.\n\t*/\n\tfor (index = 0; index < TriggerTypes.Count(); index++) {\n\t\tTriggerTypeClass * tp = TriggerTypes.Ptr(index);\n\t\tif (tp->Action1.Action == TACTION_ALLOWWIN ||\n\t\t\t(tp->ActionControl != MULTI_ONLY && tp->Action2.Action == TACTION_ALLOWWIN)) {\n\n\t\t\tHouseClass::As_Pointer(tp->House)->Blockage++;\n\t\t}\n\t}\n\n\t/*\n\t**\tMove available money to silos, if the scenario flag so indicates.\n\t*/\n\tif (Scen.IsMoneyTiberium) {\n\t\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\t\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\t\t\tif (hptr != NULL) {\n\t\t\t\tint tomove = hptr->Capacity - hptr->Tiberium;\n\t\t\t\thptr->Credits -= tomove;\n\t\t\t\thptr->Tiberium += tomove;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCount all non-destroyed bridges on the map.\n\t*/\n\tScen.BridgeCount = Map.Intact_Bridge_Count();\n\n\tMap.All_To_Look(true);\n}\n\n\n/***********************************************************************************************\n * Post_Load_Game -- Fill in an inferred data from the game state.                             *\n *                                                                                             *\n *    This routine is typically called after a game has been loaded. Some working data lists   *\n *    can be rebuild from the game state. This working data is rebuilt rather than being       *\n *    stored with the game data file.                                                          *\n *                                                                                             *\n * INPUT:   load_multi -- true if we're loading a multiplayer game                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Although it is safe to call this routine whenever, it is only needed after a    *\n *             game load.                                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/30/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Post_Load_Game(int load_multi)\n{\n\t//\n\t// Do NOT call Overpass if we're loading a multiplayer game; it calls the\n\t// random # generator, which throws the games out of sync if they were\n\t// saved on different frame #'s.\n\t//\n\tif (!load_multi) {\n\t\tMap.Overpass();\n\t}\n\tScen.BridgeCount = Map.Intact_Bridge_Count();\n\tMap.Zone_Reset(MZONEF_ALL);\n}\n\n\n/***********************************************************************************************\n * Clear_Scenario -- Clears all data in preparation for scenario load.                         *\n *                                                                                             *\n *    This routine will clear out all data specific to a scenario in                           *\n *    preparation for a subsequent scenario data load. This will free                          *\n *    all units, animations, and icon maps.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/22/1991     : Created.                                                                 *\n *   03/21/1992 JLB : Changed buffer allocations, so changes memset code.                      *\n *   07/13/1995 JLB : End count down moved here.                                               *\n *=============================================================================================*/\nvoid Clear_Scenario(void)\n{\n// TCTCTC -- possibly just use in-place new of scenario object?\n\n\tScen.MissionTimer = 0;\n\tScen.MissionTimer.Stop();\n\tScen.Timer = 0;\n\tScen.ShroudTimer = 0;\n\tScen.IntroMovie = VQ_NONE;\n\tScen.BriefMovie = VQ_NONE;\n\tScen.WinMovie = VQ_NONE;\n\tScen.LoseMovie = VQ_NONE;\n\tScen.ActionMovie = VQ_NONE;\n\tScen.IsNoSpyPlane = false;\n\tScen.IsTanyaEvac = false;\n\tScen.IsEndOfGame = false;\n\tScen.IsInheritTimer = false;\n\tScen.IsToCarryOver = false;\n\tScen.IsSkipScore = false;\n\tScen.IsOneTimeOnly = false;\n\tScen.IsTruckCrate = false;\n\tScen.IsMoneyTiberium = false;\n\tScen.IsNoMapSel = false;\n\tScen.CarryOverCap = 0;\n\tScen.CarryOverPercent = 0;\n\tScen.TransitTheme = THEME_NONE;\n\tScen.Percent = 0;\n\n\tmemset(Scen.GlobalFlags, 0, sizeof(Scen.GlobalFlags));\n\n\tMapTriggers.Clear();\n\tLogicTriggers.Clear();\n\n\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\tHouseTriggers[house].Clear();\n\t}\n\n\t/*\n\t** Call everyone's Init routine, except the Map's; for the Map, only call\n\t** MapClass::Init, which clears the Cell array.  The Display::Init requires\n\t** a Theater argument, and the theater is not known at this point; also, it\n\t** would reload MixFiles, which isn't desired.  Display::Read_INI calls its\n\t** own Init, which will Init the entire Map hierarchy.\n\t*/\n\tMap.Init_Clear();\n\tScore.Init();\n\tLogic.Init();\n\n\tHouseClass::Init();\n\tObjectClass::Init();\n\tTeamTypeClass::Init();\n\tTeamClass::Init();\n\tTriggerClass::Init();\n\tTriggerTypeClass::Init();\n\tAircraftClass::Init();\n\tAnimClass::Init();\n\tBuildingClass::Init();\n\tBulletClass::Init();\n\tInfantryClass::Init();\n\tOverlayClass::Init();\n\tSmudgeClass::Init();\n\tTemplateClass::Init();\n\tTerrainClass::Init();\n\tUnitClass::Init();\n\tVesselClass::Init();\n\n\tFactoryClass::Init();\n\n\tBase.Init();\n\n\tCurrentObject.Clear();\n\n\tfor (int index = 0; index < WAYPT_COUNT; index++) {\n\t\tScen.Waypoint[index] = -1;\n\t}\n\n#ifdef FIXIT_VERSION_3\t\t\t//\tFor endgame auto-sonar pulse.\n\tbAutoSonarPulse = false;\n#endif\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\tScen.bLocalProposesDraw = false;\n\tScen.bOtherProposesDraw = false;\n#endif\n\n}\n\n\n/***********************************************************************************************\n * Do_Win -- Display winning congratulations.                                                  *\n *                                                                                             *\n *    Perform the win the mission process. This will display any winning movies and the score  *\n *    screen. Followed by the map selection screen and then the load of the new scenario.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1992 JLB : Created.                                                                 *\n *   01/01/1995 JLB : Carries money forward into next scenario.                                *\n *=============================================================================================*/\nvoid Do_Win(void)\n{\n\tMap.Set_Default_Mouse(MOUSE_NORMAL);\n\tHide_Mouse();\n\tTheme.Queue_Song(THEME_QUIET);\n\n\t/*\n\t** If this is a multiplayer game, clear the game's name so we won't respond\n\t** to game queries any more (in Call_Back)\n\t*/\n\tif (Session.Type != GAME_NORMAL) {\n\t\tSession.GameName[0] = 0;\n\t}\n\n\t/*\n\t**\tDetermine a cosmetic center point for the text.\n\t*/\n\tint x = Map.TacPixelX + (Lepton_To_Pixel(Map.TacLeptonWidth)/2);\n\n\t/*\n\t** Hack section.  If it's allied scenario 10, variation A, then skip the\n\t** score and map selection, don't increment scenario, and set it to\n\t** variation B.\n\t*/\n#ifdef FIXIT_ANTS\n\tif (Session.Type != GAME_NORMAL || !Scen.IsSkipScore || AntsEnabled) {\n#else\n\tif (Session.Type != GAME_NORMAL || !Scen.IsSkipScore ) {\n#endif\t//FIXIT_ANTS\n\n\t\t/*\n\t\t**\tAnnounce win to player.\n\t\t*/\n\t\tSet_Logic_Page(SeenBuff);\n\t\tMap.Flag_To_Redraw (true);\n\t\tMap.Render();\n#ifdef WIN32\n\t\tFancy_Text_Print(TXT_SCENARIO_WON, x, 90*RESFACTOR, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_CENTER|TPF_VCR|TPF_USE_GRAD_PAL|TPF_DROPSHADOW);\n#else\n\t\tFancy_Text_Print(TXT_MISSION, x, 90*RESFACTOR, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_CENTER|TPF_VCR|TPF_USE_GRAD_PAL|TPF_DROPSHADOW);\n\t\tFancy_Text_Print(TXT_HACKHACK, x, 110*RESFACTOR, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_CENTER|TPF_VCR|TPF_USE_GRAD_PAL|TPF_DROPSHADOW);\n#endif\n\t\tCountDownTimer = TIMER_SECOND * 3;\n\t\twhile (Is_Speaking()) {};\n\t\tSpeak(VOX_ACCOMPLISHED);\n\t\twhile (CountDownTimer || Is_Speaking()) {\n\t\t\tCall_Back();\n\t\t}\n\t}\n\n\t/*\n\t** Stop here if this is a multiplayer game.\n\t*/\n\tif (Session.Type != GAME_NORMAL) {\n\t\tif (!Session.Play) {\n\t\t\tSession.GamesPlayed++;\n\t\t\tMulti_Score_Presentation();\n\t\t\tSession.CurGame++;\n\t\t\tif (Session.CurGame >= MAX_MULTI_GAMES) {\n\t\t\t\tSession.CurGame = MAX_MULTI_GAMES - 1;\n\t\t\t}\n\t\t}\n\t\tGameActive = 0;\n\t\tShow_Mouse();\n\t\treturn;\n\t}\n\n\tHide_Mouse();\n\tVisiblePage.Clear();\n\tShow_Mouse();\n\tPlay_Movie(Scen.WinMovie);\n\n\tKeyboard->Clear();\n\n\tSaveTanya = IsTanyaDead;\n\tScen.CarryOverTimer = Scen.MissionTimer;\n//\tint timer = Scen.MissionTimer;\n\n\t/*\n\t**\tDo the ending screens only if not playing back a recorded game.\n\t*/\n\tif (!Session.Play) {\n\t\t/*\n\t\t**\tIf the score presentation should be performed, then do\n\t\t**\tso now.\n\t\t*/\n\t\tKeyboard->Clear();\n\t\tif (!Scen.IsSkipScore) {\n\t\t\tScore.Presentation();\n\t\t}\n\n\n\t\tif (Scen.IsOneTimeOnly) {\n\t\t\tGameActive = false;\n\t\t\tShow_Mouse();\n#ifdef FIXIT_ANTS\n\t\t\tAntsEnabled = false;\n//\t\t\tMono_Printf(\"Scenario.cpp one time only antsenabled is false\\n\");\n#endif\n\t\t\treturn;\n\t\t}\n\n\t\t/*\n\t\t** If this scenario is flagged as ending the game then print the credits and exit.\n\t\t*/\n\t\tif (Scen.IsEndOfGame) {\n\t\t\tif (PlayerPtr->ActLike == HOUSE_USSR) {\n\t\t\t\tPlay_Movie(VQ_SOVFINAL);\n\t\t\t} else {\n\t\t\t\tPlay_Movie(VQ_ALLYEND);\n\t\t\t}\n\t\t\tShow_Who_Was_Responsible();\n\t\t\tGameActive = false;\n\t\t\tShow_Mouse();\n#ifdef FIXIT_ANTS\n\t\t\tAntsEnabled = false;\n#endif\n\t\t\treturn;\n\t\t}\n\n\t\t/*\n\t\t** Hack section.  If it's allied scenario 10, variation A, then skip the\n\t\t** score and map selection, don't increment scenario, and set it to\n\t\t** variation B.\n\t\t*/\n\t\tif (Scen.IsNoMapSel) {\n\t\t\t// force it to play the second half of scenario 10\n#ifdef FIXIT_ANTS\n\t\t\tif (AntsEnabled) {\n\t\t\t\tchar scenarioname[24];\n\t\t\t\tstrcpy(scenarioname, Scen.ScenarioName);\n\t\t\t\tchar buf[10];\n\t\t\t\tScen.Scenario++;\n\t\t\t\tsprintf(buf, \"%02d\", Scen.Scenario);\n\t\t\t\tmemcpy(&scenarioname[3], buf, 2);\n\t\t\t\tScen.Set_Scenario_Name(scenarioname);\n\t\t\t} else {\n\t\t\t\tScen.ScenarioName[6] = 'B';\n\t\t\t}\n\n#else\n\t\t\tScen.ScenarioName[6] = 'B';\n#endif\n\n\t\t} else {\n\t\t\tScen.Set_Scenario_Name(Map_Selection());\n\t\t}\n\n\t\tKeyboard->Clear();\n\t}\n\n\tScen.CarryOverMoney = PlayerPtr->Credits;\n\n\t/*\n\t**\tIf requested, record the scenario's objects in the carry over list\n\t**\tfor possible use in a future scenario.\n\t*/\n\tif (Scen.IsToCarryOver) {\n\n\t\t/*\n\t\t**\tFirst delete any existing carry over list. Any old list will be\n\t\t**\tblasted over by the new list -- there is only one logic carryover\n\t\t**\tlist to be maintained.\n\t\t*/\n\t\twhile (Carryover) {\n\t\t\tCarryoverClass * cptr = (CarryoverClass *)Carryover->Get_Next();\n\t\t\tCarryover->Remove();\n\t\t\tdelete Carryover;\n\t\t\tCarryover = cptr;\n\t\t}\n\n\t\t/*\n\t\t**\tRecord all objects, that are to be part of the carry over set, into\n\t\t**\tthe carry over list.\n\t\t*/\n\t\tfor (int building_index = 0; building_index < Buildings.Count(); building_index++) {\n\t\t\tBuildingClass * building = Buildings.Ptr(building_index);\n\n\t\t\tif (building && !building->IsInLimbo && building->Strength > 0) {\n\t\t\t\tCarryoverClass * cptr = new CarryoverClass(building);\n\n\t\t\t\tif (cptr) {\n\t\t\t\t\tif (Carryover) {\n\t\t\t\t\t\tcptr->Add_Tail(*Carryover);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCarryover = cptr;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (int unit_index = 0; unit_index < Units.Count(); unit_index++) {\n\t\t\tUnitClass * unit = Units.Ptr(unit_index);\n\n\t\t\tif (unit && !unit->IsInLimbo && unit->Strength > 0) {\n\t\t\t\tCarryoverClass * cptr = new CarryoverClass(unit);\n\n\t\t\t\tif (cptr) {\n\t\t\t\t\tif (Carryover) {\n\t\t\t\t\t\tcptr->Add_Tail(*Carryover);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCarryover = cptr;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (int infantry_index = 0; infantry_index < Infantry.Count(); infantry_index++) {\n\t\t\tInfantryClass * infantry = Infantry.Ptr(infantry_index);\n\n\t\t\tif (infantry && !infantry->IsInLimbo && infantry->Strength > 0) {\n\t\t\t\tCarryoverClass * cptr = new CarryoverClass(infantry);\n\n\t\t\t\tif (cptr) {\n\t\t\t\t\tif (Carryover) {\n\t\t\t\t\t\tcptr->Add_Tail(*Carryover);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCarryover = cptr;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (int vessel_index = 0; vessel_index < Vessels.Count(); vessel_index++) {\n\t\t\tVesselClass * vessel = Vessels.Ptr(vessel_index);\n\n\t\t\tif (vessel && !vessel->IsInLimbo && vessel->Strength > 0) {\n\t\t\t\tCarryoverClass * cptr = new CarryoverClass(vessel);\n\n\t\t\t\tif (cptr) {\n\t\t\t\t\tif (Carryover) {\n\t\t\t\t\t\tcptr->Add_Tail(*Carryover);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCarryover = cptr;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Generate a new scenario filename\n\t*/\n//\tScen.Set_Scenario_Name(Scen.Scenario, Scen.ScenPlayer, Scen.ScenDir, Scen.ScenVar);\n\tStart_Scenario(Scen.ScenarioName);\n\n\t/*\n\t**\tIf the mission timer is to be inheriteded from the previous scenario then do it now.\n\t*/\n\tif (Scen.IsInheritTimer) {\n\t\tScen.MissionTimer = Scen.CarryOverTimer;\n\t\tScen.MissionTimer.Start();\n\t}\n\n//\tPlayerPtr->NukePieces = nukes;\n\n\tMap.Render();\n\tGamePalette.Set(FADE_PALETTE_FAST, Call_Back);\n//\tFade_Palette_To(GamePalette, FADE_PALETTE_FAST, Call_Back);\n\tShow_Mouse();\n}\n\n\n/***********************************************************************************************\n * Do_Lose -- Display losing comments.                                                         *\n *                                                                                             *\n *    Performs the lose mission processing. This will generally display a \"would you like      *\n *    to replay\" dialog and then either reload the scenario or set flags such that the main    *\n *    menu will appear.                                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Do_Lose(void)\n{\n\tMap.Set_Default_Mouse(MOUSE_NORMAL);\n\tHide_Mouse();\n\n\tTheme.Queue_Song(THEME_QUIET);\n\n\t/*\n\t** If this is a multiplayer game, clear the game's name so we won't respond\n\t** to game queries any more (in Call_Back)\n\t*/\n\tif (Session.Type != GAME_NORMAL) {\n\t\tSession.GameName[0] = 0;\n\t}\n\n\t/*\n\t**\tDetermine a cosmetic center point for the text.\n\t*/\n\tint x = Map.TacPixelX + (Lepton_To_Pixel(Map.TacLeptonWidth)/2);\n\n\t/*\n\t**\tAnnounce win to player.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\tFancy_Text_Print(TXT_SCENARIO_LOST, x, 90*RESFACTOR, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_CENTER|TPF_VCR|TPF_USE_GRAD_PAL|TPF_DROPSHADOW);\n\tCountDownTimer = TIMER_SECOND * 3;\n\twhile (Is_Speaking()) {};\n\tSpeak(VOX_FAIL);\n\twhile (CountDownTimer || Is_Speaking()) {\n\t\tCall_Back();\n\t}\n\n\t/*\n\t** Stop here if this is a multiplayer game.\n\t*/\n\tif (Session.Type != GAME_NORMAL) {\n\t\tif (!Session.Play) {\n\t\t\tSession.GamesPlayed++;\n\t\t\tMulti_Score_Presentation();\n\t\t\tSession.CurGame++;\n\t\t\tif (Session.CurGame >= MAX_MULTI_GAMES) {\n\t\t\t\tSession.CurGame = MAX_MULTI_GAMES - 1;\n\t\t\t}\n\t\t}\n\t\tGameActive = 0;\n\t\tShow_Mouse();\n\t\treturn;\n\t}\n\n\tHide_Mouse();\n\tVisiblePage.Clear();\n\tShow_Mouse();\n#ifdef CHEAT_KEYS\n//\tMono_Printf(\"Trying to play lose movie\\n\");\n#endif //CHEAT_KEYS\n\tPlay_Movie(Scen.LoseMovie);\n\n\t/*\n\t** Start same scenario again\n\t*/\n\tGamePalette.Set();\n\tShow_Mouse();\n\tif (!Session.Play && !WWMessageBox().Process(TXT_TO_REPLAY, TXT_YES, TXT_NO)) {\n\t\tHide_Mouse();\n\t\tKeyboard->Clear();\n\t\tStart_Scenario(Scen.ScenarioName, false);\n\n\t\t/*\n\t\t**\tStart the scenario timer with the carried over value if necessary.\n\t\t*/\n\t\tif (Scen.IsInheritTimer) {\n\t\t\tScen.MissionTimer = Scen.CarryOverTimer;\n\t\t\tScen.MissionTimer.Start();\n\t\t}\n\n\t\tMap.Render();\n\t} else {\n\t\tHide_Mouse();\n\t\tGameActive = 0;\n\t}\n\n\tGamePalette.Set(FADE_PALETTE_FAST, Call_Back);\n\tShow_Mouse();\n}\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n/***********************************************************************************************\n * Do_Draw -- Parallels Do_Win and Do_Lose, for multiplayer games that end in a draw.\n *=============================================================================================*/\nvoid Do_Draw(void)\n{\n\tMap.Set_Default_Mouse(MOUSE_NORMAL);\n\tHide_Mouse();\n\n\tTheme.Queue_Song(THEME_QUIET);\n\n\t/*\n\t** If this is a multiplayer game, clear the game's name so we won't respond\n\t** to game queries any more (in Call_Back)\n\t*/\n\tif (Session.Type != GAME_NORMAL) {\n\t\tSession.GameName[0] = 0;\n\t}\n\n\t/*\n\t**\tDetermine a cosmetic center point for the text.\n\t*/\n\tint x = Map.TacPixelX + (Lepton_To_Pixel(Map.TacLeptonWidth)/2);\n\n\t/*\n\t**\tAnnounce win to player.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\tFancy_Text_Print(TXT_WOL_DRAW, x, 90*RESFACTOR, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_CENTER|TPF_VCR|TPF_USE_GRAD_PAL|TPF_DROPSHADOW);\n\tCountDownTimer = TIMER_SECOND * 3;\n\twhile (Is_Speaking()) {};\n\tSpeak(VOX_CONTROL_EXIT);\n\twhile (CountDownTimer || Is_Speaking()) {\n\t\tCall_Back();\n\t}\n\n\t/*\n\t** Stop here if this is a multiplayer game.\n\t*/\n\tif (!Session.Play) {\n\t\tSession.GamesPlayed++;\n\t\tMulti_Score_Presentation();\n\t\tSession.CurGame++;\n\t\tif (Session.CurGame >= MAX_MULTI_GAMES) {\n\t\t\tSession.CurGame = MAX_MULTI_GAMES - 1;\n\t\t}\n\t}\n\tGameActive = 0;\n\tShow_Mouse();\n}\n#endif\n\n/***********************************************************************************************\n * Do_Restart -- Handle the restart mission process.                                           *\n *                                                                                             *\n *    This routine is called in the main game loop when the mission must be restarted. This    *\n *    routine will throw away the current game and reload the appropriate mission. The         *\n *    game will \"resume\" at the start of the mission.                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Do_Restart(void)\n{\n\t/*\n\t** Start a timer going, before we restart the scenario\n\t*/\n\tCDTimerClass<SystemTimerClass> timer;\n\ttimer = TICKS_PER_SECOND * 4;\n\tTheme.Queue_Song(THEME_QUIET);\n\n\tWWMessageBox().Process(TXT_RESTARTING, TXT_NONE);\n\n\tMap.Set_Default_Mouse(MOUSE_NORMAL);\n\tKeyboard->Clear();\n\tStart_Scenario(Scen.ScenarioName, false);\n\n\t/*\n\t**\tStart the scenario timer with the carried over value if necessary.\n\t*/\n\tif (Scen.IsInheritTimer) {\n\t\tScen.MissionTimer = Scen.CarryOverTimer;\n\t\tScen.MissionTimer.Start();\n\t}\n\n\t/*\n\t** Make sure the message stays displayed for at least 1 second\n\t*/\n\twhile (timer > 0) {\n\t\tCall_Back();\n\t}\n\tKeyboard->Clear();\n\n\tMap.Render();\n}\n\n\n/***********************************************************************************************\n * Restate_Mission -- Handles restating the mission objective.                                 *\n *                                                                                             *\n *    This routine will display the mission objective (as text). It will also give the         *\n *    option to redisplay the mission briefing video.                                          *\n *                                                                                             *\n * INPUT:   name  -- The scenario name. This is the unique identifier for the scenario         *\n *                   briefing text as it appears in the \"MISSION.INI\" file.                    *\n *                                                                                             *\n * OUTPUT:  Returns the response from the dialog. This will either be 1 if the video was       *\n *          requested, or 0 if the return to game options button was selected.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/23/1995 JLB : Created.                                                                 *\n *   08/06/1995 JLB : Uses preloaded briefing text.                                            *\n *=============================================================================================*/\nbool Restate_Mission(char const * name, int button1, int button2)\n{\n\tif (name) {\n\n\t\tbool brief = true;\n\t\tchar buffer[25];\n\t\tif (Scen.BriefMovie != VQ_NONE) {\n\t\t\tsprintf(buffer, \"%s.VQA\", VQName[Scen.BriefMovie]);\n\t\t}\n\n\t\tif (Scen.BriefMovie == VQ_NONE || !CCFileClass(buffer).Is_Available()) {\n\t\t\tbutton2 = TXT_OK;\n\t\t\tbutton1 = TXT_NONE;\n\t\t\tbrief = false;\n\t\t}\n\n\t\t/*\n\t\t**\tIf mission object text was found, then display it.\n\t\t*/\n\t\tif (strlen(Scen.BriefingText)) {\n\t\t\tstrcpy(_ShapeBuffer, Scen.BriefingText);\n\t\t\tBlackPalette.Set(FADE_PALETTE_MEDIUM, Call_Back);\n\t\t\tif (BGMessageBox(_ShapeBuffer, button2, button1)) {\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t\tif (!brief) return(true);\n\t\t\treturn(false);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n#define\tBUTTON_1\t\t1\n#define\tBUTTON_2\t\t2\n#define\tBUTTON_3\t\t3\n#define\tBUTTON_FLAG\t0x8000\nbool BGMessageBox(char const * msg, int btn1, int btn2)\n{\n#define BUFFSIZE 511\n\tchar buffer[BUFFSIZE];\n\tbool retval;\n\tbool process;\t\t\t\t\t\t\t\t// loop while true\n\tKeyNumType input;\t\t\t\t\t\t\t// user input\n\tint selection;\n\tbool pressed;\n\tint curbutton;\n\tTextButtonClass * buttons[3];\n\tBOOL display;\t\t\t\t\t\t\t\t\t// display level\n\tint  realval[5];\n\tint  morebutton = 3;\t\t\t\t\t\t// which button says \"more\": 2 or 3?\n\n\tconst char * b1txt = Text_String(btn1);\n\tconst char * b2txt = Text_String(btn2);\n#ifdef FRENCH\n\tconst char * b3txt = \"SUITE\";\n#else\n#ifdef GERMAN\n\tconst char * b3txt = \"MEHR\";\n#else\n\tconst char * b3txt = \"MORE\";\n#endif\n#endif\n\n\tconst void *briefsnd = MFCD::Retrieve(\"BRIEFING.AUD\");\n\n\tGadgetClass::Set_Color_Scheme(&ColorRemaps[PCOLOR_TYPE]);\n\n\t/*\n\t** If the message won't be needing the 'more' button, get rid of it.\n\t*/\n\tif (strlen(msg) <= BUFFSIZE-1) {\n\t\tb3txt = \"\";\n\t}\n\n#ifdef WIN32\n\tGraphicBufferClass seen_buff_save(VisiblePage.Get_Width(), VisiblePage.Get_Height(), (void*)NULL);\n#endif\n\n\t/*\n\t** If there's no text for button one, zero it out.\n\t*/\n\tif (*b1txt == '\\0') {\n\t\tb1txt = b2txt;\n\t\tb2txt = \"\";\n\t\tif(*b1txt == '\\0') {\n\t\t\tb1txt=0;\n\t\t}\n\t}\n\n\t/*\n\t** If there's no text for button two, zero it out.  However, if there\n\t** is text for button three, move its text (always \"MORE\") to button two,\n\t** and set the morebutton flag to point to button two.  Then, clear out\n\t** button 3.\n\t*/\n\tif (*b2txt == '\\0') {\n\t\tb2txt = 0;\n\t\tif (*b3txt != '\\0') {\n\t\t\tb2txt = b3txt;\n\t\t\tb3txt = \"\";\n\t\t\tmorebutton = 1;\n\t\t}\n\t}\n\n\t/*\n\t** If there's no text for button three, zero it out.\n\t*/\n\tif (*b3txt == '\\0') b3txt = 0;\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, &ColorRemaps[PCOLOR_TYPE], TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL);\n\t/*\n\t**\tExamine the optional button parameters. Fetch the width and starting\n\t**\tcharacters for each.\n\t*/\n\tchar b1char, b2char, b3char;\t// 1st char of each string\n\tint bwidth, bheight;\t\t\t\t// button width and height\n\tint numbuttons = 0;\n\tif (b1txt) {\n\t\tb1char = toupper(b1txt[0]);\n\n\t\t/*\n\t\t**\tBuild the button list.\n\t\t*/\n\t\tbheight = FontHeight + FontYSpacing + 2;\n\t\tbwidth = max((String_Pixel_Width(b1txt) + 8), 80);\n\t\tif (b2txt) {\n\t\t\tnumbuttons = 2;\n\t\t\tb2char = toupper(b2txt[0]);\n\t\t\tbwidth = max((String_Pixel_Width( b2txt ) + 8), bwidth);\n//\t\t\tb1x = x + 10;\t\t\t\t\t\t\t\t// left side\n\n\t\t\tif (b3txt) {\n\t\t\t\tnumbuttons = 3;\n\t\t\t\tb3char = toupper(b3txt[0]);\n\t\t\t\tbwidth = max((String_Pixel_Width( b3txt ) + 8), bwidth);\n\t\t\t}\n\n\t\t} else {\n\t\t\tnumbuttons = 1;\n//\t\t\tb1x = x + ((width - bwidth) >> 1);\t\t// centered\n\t\t}\n\t}\n\n\t/*\n\t**\tDetermine the dimensions of the text to be used for the dialog box.\n\t**\tThese dimensions will control how the dialog box looks.\n\t*/\n\tbuffer[BUFFSIZE-1] = 0;\n\tint buffend = BUFFSIZE-1;\n\tstrncpy(buffer, msg, BUFFSIZE-1);\n\t/*\n\t** Scan through the string to see if it got clipped, and if so, we'll\n\t** trim it back to the last space so it'll clip on a word.\n\t*/\n\tif (strlen(buffer) != strlen(msg)) {\n\t\twhile (buffer[buffend] != ' ') buffend--;\n\t\tbuffer[buffend]=0;\n\t}\n\tFancy_Text_Print(TXT_NONE, 0, 0, &ColorRemaps[PCOLOR_TYPE], TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL);\n\tint width;\n\tint height;\n\tFormat_Window_String(buffer, 300, width, height);\n\theight += (numbuttons == 0) ? 30 : 60;\n\n\tint x = (SeenBuff.Get_Width() - width) / 2;\n\tint y = (SeenBuff.Get_Height() - height) / 2;\n\n\t/*\n\t**\tOther inits.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tInitialize the button structures. All are initialized, even though one (or none) may\n\t**\tactually be added to the button list.\n\t*/\n\tTextButtonClass button1(BUTTON_1, b1txt, TPF_BUTTON,\n\t\tx + ((numbuttons == 1) ? ((width - bwidth) >> 1) : 10), y + height - (bheight + 5), bwidth);\n\n\tTextButtonClass button2(BUTTON_2, b2txt, TPF_BUTTON,\n\t\tx + width - (bwidth + 10), y + height - (bheight + 5), bwidth);\n\n\tTextButtonClass button3(BUTTON_3, b3txt, TPF_BUTTON,\n\t\t0, y + height - (bheight + 5));\n\tbutton3.X = x + ((width - button3.Width) >> 1);\n\n\tTextButtonClass * buttonlist = 0;\n\tcurbutton = 0;\n\n\t/*\n\t**\tAdd and initialize the buttons to the button list.\n\t*/\n\tif (numbuttons) {\n\t\tbuttonlist = &button1;\n\t\tbuttons[0] = &button1;\n\t\trealval[0] = BUTTON_1;\n\t\tif (numbuttons > 2) {\n\t\t\tbutton3.Add(*buttonlist);\n\t\t\tbuttons[1] = &button3;\n\t\t\trealval[1] = BUTTON_3;\n\t\t\tbutton2.Add(*buttonlist);\n\t\t\tbuttons[2] = &button2;\n\t\t\trealval[2] = BUTTON_2;\n\t\t\tbuttons[curbutton]->Turn_On();\n\t\t} else if (numbuttons == 2) {\n\t\t\tbutton2.Add(*buttonlist);\n\t\t\tbuttons[1] = &button2;\n\t\t\trealval[1] = BUTTON_2;\n\t\t\tbuttons[curbutton]->Turn_On();\n\t\t}\n\t}\n\n\t/*\n\t**\tDraw the dialog.\n\t*/\n\tHide_Mouse();\n\n\tPaletteClass temp;\n#ifdef WIN32\n\tchar *filename = \"SOVPAPER.PCX\";\n\tif (PlayerPtr->Class->House != HOUSE_USSR && PlayerPtr->Class->House != HOUSE_UKRAINE) {\n\t\tfilename = \"ALIPAPER.PCX\";\n\t}\n\tLoad_Title_Screen(filename, &HidPage, temp);\n#else\n\tchar *filename = \"SOVPAPER.CPS\";\n\tif (PlayerPtr->Class->House != HOUSE_USSR && PlayerPtr->Class->House != HOUSE_UKRAINE) {\n\t\tfilename = \"ALIPAPER.CPS\";\n\t}\n\tLoad_Uncompress(CCFileClass(filename), HidPage, HidPage, temp);\n#endif\n\tHidPage.Blit(SeenPage);\n\n\t#ifdef WIN32\n\tVisiblePage.Blit(seen_buff_save);\n\t#endif\n\n\tstatic char _scorepal[]={0,1,12,13,4,5,6,7,8,9,10,255,252,253,14,248};\n\tSet_Font_Palette(_scorepal);\n\ttemp.Set(FADE_PALETTE_MEDIUM, Call_Back);\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\n\tint bufindex = 0;\n\n\tKeyboard->Clear();\n\n\tSet_Font_Palette(_scorepal);\n\tint xprint = x + 20;\n\tint yprint = y + 25;\n\tdo {\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored = false;\n\t\t\tHide_Mouse();\n\t\t\tseen_buff_save.Blit(VisiblePage);\n\t\t\tdisplay = true;\n\t\t\tShow_Mouse();\n\t\t}\n\t\t#endif\n\t\tchar bufprint[2];\n\t\tbufprint[1]=0;\n\t\tbufprint[0] = buffer[bufindex];\n\t\tif (bufprint[0] == '\\r' || bufprint[0] == '@') {\n\t\t\txprint = x + 20;\n\t\t\typrint += FontHeight + FontYSpacing;\n\n\t\t} else {\n\t\t\tif (bufprint[0] != 20) {\n\t\t\t\tSeenPage.Print(bufprint, xprint, yprint, TBLACK, TBLACK);\n#ifdef WIN32\n\t\t\t\tseen_buff_save.Print(bufprint, xprint, yprint, TBLACK, TBLACK);\n#endif\n\t\t\t\txprint += Char_Pixel_Width(bufprint[0]);\n\t\t\t}\n\t\t}\n\t\tif (bufprint[0] == '\\r' || bufprint[0] == '@') {\n#ifdef WIN32\n\t\t\tPlay_Sample(briefsnd, 255, Options.Normalize_Volume(135));\n#else\n\t\t\tPlay_Sample(briefsnd, 255, Options.Normalize_Volume(45));\n#endif\n\t\t\tCDTimerClass<SystemTimerClass> cd;\n\t\t\tcd = 5;\n\t\t\tdo {\n\t\t\t\tCall_Back();\n\t\t\t} while(!Keyboard->Check() && cd);\n\t\t}\n\t} while (buffer[++bufindex]);\n\n\tShow_Mouse();\n\tKeyboard->Clear();\n\n\tif (buttonlist) {\n\t\tprocess = true;\n\t\tpressed = false;\n\t\twhile (process) {\n\t\t\t#ifdef WIN32\n\t\t\t/*\n\t\t\t** If we have just received input focus again after running in the background then\n\t\t\t** we need to redraw.\n\t\t\t*/\n\t\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\t\tAllSurfaces.SurfacesRestored = false;\n\t\t\t\tHide_Mouse();\n\t\t\t\tseen_buff_save.Blit(VisiblePage);\n\t\t\t\tdisplay = true;\n\t\t\t\tShow_Mouse();\n\t\t\t}\n\t\t\t#endif\n\n\t\t\tif (display) {\n\t\t\t\tdisplay = false;\n\n\t\t\t\tHide_Mouse();\n\n\t\t\t\t/*\n\t\t\t\t**\tRedraw the buttons.\n\t\t\t\t*/\n\t\t\t\tif (buttonlist) {\n\t\t\t\t\tbuttonlist->Draw_All();\n\t\t\t\t}\n\t\t\t\tShow_Mouse();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tInvoke game callback.\n\t\t\t*/\n\t\t\tCall_Back();\n\n\t\t\t/*\n\t\t\t**\tFetch and process input.\n\t\t\t*/\n\t\t\tinput = buttonlist->Input();\n\t\t\tswitch (input) {\n\t\t\t\tcase (BUTTON_1|BUTTON_FLAG):\n\t\t\t\t\tselection = realval[0];\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_ESC):\n\t\t\t\t\tif (numbuttons > 2) {\n\t\t\t\t\t\tselection = realval[1];\n\t\t\t\t\t\tpressed = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tselection = realval[2];\n\t\t\t\t\t\tpressed = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_2|BUTTON_FLAG):\n\t\t\t\t\tselection = BUTTON_2;\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_3|BUTTON_FLAG):\n\t\t\t\t\tselection = realval[1];\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_LEFT):\n\t\t\t\t\tif (numbuttons > 1) {\n\t\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\t\t\t\tcurbutton--;\n\t\t\t\t\t\tif (curbutton < 0) {\n\t\t\t\t\t\t\tcurbutton = numbuttons - 1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_RIGHT):\n\t\t\t\t\tif (numbuttons > 1) {\n\t\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\t\t\t\tcurbutton++;\n\t\t\t\t\t\tif (curbutton > (numbuttons - 1) ) {\n\t\t\t\t\t\t\tcurbutton = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_RETURN):\n\t\t\t\t\tselection = curbutton + BUTTON_1;\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tCheck 'input' to see if it's the 1st char of button text\n\t\t\t\t*/\n\t\t\t\tdefault:\n\t\t\t\t\tif (b1char == toupper(Keyboard->To_ASCII((KeyNumType)(input & 0xFF)))) {\n\t\t\t\t\t\tselection = BUTTON_1;\n\t\t\t\t\t\tpressed = true;\n\t\t\t\t\t} else if (b2txt!=NULL &&\n\t\t\t\t\t\tb2char == toupper(Keyboard->To_ASCII((KeyNumType)(input & 0xFF)))) {\n\t\t\t\t\t\tselection = BUTTON_2;\n\t\t\t\t\t\tpressed = true;\n\t\t\t\t\t} else if (b3txt!=NULL &&\n\t\t\t\t\t\tb3char == toupper(Keyboard->To_ASCII((KeyNumType)(input & 0xFF)))) {\n\t\t\t\t\t\tselection = BUTTON_3;\n\t\t\t\t\t\tpressed = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (pressed) {\n\t\t\t\tswitch (selection) {\n\t\t\t\t\tcase (BUTTON_1):\n\t\t\t\t\t\tretval = 1;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_2):\n\t\t\t\t\t\tretval = 0;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase BUTTON_3:\n\t\t\t\t\t\tretval = 2;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tpressed = false;\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\tKeyboard->Clear();\n\t}\n\n\tif (retval == (morebutton-1) && strlen(msg) > BUFFSIZE-1) {\n\t\tretval = BGMessageBox(msg + buffend + 1, btn1, btn2);\n\t}\n\t/*\n\t** Restore the screen.\n\t*/\n\tHide_Mouse();\n\t/*\n\t** Now set the palette, depending on if we're going to show the video or\n\t** go back to the main menu.\n\t*/\n\tswitch (retval) {\n\t\tcase 0:\n//\t\t\tBlackPalette.Set(FADE_PALETTE_MEDIUM, Call_Back);\n//\t\t\tSeenPage.Clear();\n////\t\t\tCCPalette.Set();\n//\t\t\tbreak;\n\t\tcase 1:\n\t\t\tBlackPalette.Set(FADE_PALETTE_MEDIUM, Call_Back);\n\t\t\tSeenPage.Clear();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tShow_Mouse();\n\n\tGadgetClass::Set_Color_Scheme(&ColorRemaps[PCOLOR_DIALOG_BLUE]);\n\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * Set_Scenario_Name -- Creates the INI scenario name string.                                  *\n *                                                                                             *\n *    This routine is used by the scenario loading and saving code. It generates the scenario  *\n *    INI root file name for the specified scenario parameters.                                *\n *                                                                                             *\n * INPUT:                                                                                      *\n *         buf         buffer to store filename in; must be long enough for root.ext           *\n *       scenario      scenario number                                                         *\n *       player      player type for this game (GDI, NOD, multi-player, ...)                   *\n *       dir         directional parameter for this game (East/West)                           *\n *       var         variation of this game (Lose, A/B/C/D, etc)                               *\n *                                                                                             *\n * OUTPUT:  none.                                                                              *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *   05/01/1995 BRR : 2-player scenarios use same names as multiplayer                         *\n *=============================================================================================*/\nvoid ScenarioClass::Set_Scenario_Name(int scenario, ScenarioPlayerType player, ScenarioDirType dir, ScenarioVarType var)\n{\n\tScenario = scenario;\n//\tScenPlayer = player;\n//\tScenDir = dir;\n//\tScenVar = var;\n\n\tchar c_player;\t\t\t// character representing player type\n\tchar c_dir;\t\t\t\t// character representing direction type\n\tchar c_var;\t\t\t\t// character representing variation type\n\tScenarioVarType i;\n\tchar fname[_MAX_FNAME+_MAX_EXT];\n\n\t/*\n\t** Set the player-type value.\n\t*/\n\tswitch (player) {\n\t\tcase SCEN_PLAYER_SPAIN:\n\t\t\tc_player = HouseTypeClass::As_Reference(HOUSE_SPAIN).Prefix;\n\t\t\tbreak;\n\n\t\tcase SCEN_PLAYER_GREECE:\n\t\t\tc_player = HouseTypeClass::As_Reference(HOUSE_GREECE).Prefix;\n\t\t\tbreak;\n\n\t\tcase SCEN_PLAYER_USSR:\n\t\t\tc_player = HouseTypeClass::As_Reference(HOUSE_USSR).Prefix;\n\t\t\tbreak;\n\n\t\tcase SCEN_PLAYER_JP:\n\t\t\tc_player = HouseTypeClass::As_Reference(HOUSE_JP).Prefix;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tMulti player scenario.\n\t\t*/\n\t\tdefault:\n\t\t\tc_player = HouseTypeClass::As_Reference(HOUSE_MULTI1).Prefix;\n\t\t\tbreak;\n\t}\n\n\t/*\n\t** Set the directional character value.\n\t** If SCEN_DIR_NONE is specified, randomly pick a direction; otherwise, use 'E' or 'W'\n\t*/\n\tswitch (dir) {\n\t\tcase SCEN_DIR_EAST:\n\t\t\tc_dir = 'E';\n\t\t\tbreak;\n\n\t\tcase SCEN_DIR_WEST:\n\t\t\tc_dir = 'W';\n\t\t\tbreak;\n\n\t\tdefault:\n\t\tcase SCEN_DIR_NONE:\n\t\t\tc_dir = Percent_Chance(50) ? 'W' : 'E';\n\t\t\tbreak;\n\t}\n\n\t/*\n\t** Set the variation value.\n\t*/\n\tif (var == SCEN_VAR_NONE) {\n\n\t\t/*\n\t\t** Find which variations are available for this scenario\n\t\t*/\n\t\tfor (i = SCEN_VAR_FIRST; i < SCEN_VAR_COUNT; i++) {\n\t\t\tsprintf(fname, \"SC%c%02d%c%c.INI\", c_player, scenario, c_dir, 'A' + i);\n\t\t\tif (!CCFileClass(fname).Is_Available()) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (i==SCEN_VAR_FIRST) {\n\t\t\tc_var = 'X';\t\t\t\t\t\t// indicates an error\n\t\t} else {\n\t\t\tc_var = 'A' + Random_Pick(0, i-1);\n//\t\t\tScenVar = (ScenarioVarType)i;\n\t\t}\n\t} else {\n\t\tswitch (var) {\n\t\t\tcase SCEN_VAR_A:\n\t\t\t\tc_var = 'A';\n\t\t\t\tbreak;\n\n\t\t\tcase SCEN_VAR_B:\n\t\t\t\tc_var = 'B';\n\t\t\t\tbreak;\n\n\t\t\tcase SCEN_VAR_C:\n\t\t\t\tc_var = 'C';\n\t\t\t\tbreak;\n\n\t\t\tcase SCEN_VAR_D:\n\t\t\t\tc_var = 'D';\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tc_var = 'L';\n\t\t\t\tbreak;\n\n\t\t}\n\t}\n\n\t/*\n\t** generate the filename\n\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n//Mono_Printf(\"In set_scenario_name, scenario # = %d\\n\",scenario);Keyboard->Get();Keyboard->Get();\n\tif (scenario < 100) {\n\t\tsprintf(ScenarioName, \"SC%c%02d%c%c.INI\", c_player, scenario, c_dir, c_var);\n\t} else {\n\t\tchar first = (scenario / 36) + 'A';\n\t\tchar second = scenario % 36;\n\n\t\tif (second < 10) {\n\t\t\tsecond += '0';\n\t\t} else {\n\t\t\tsecond = (second - 10) + 'A';\n\t\t}\n\n\t\tsprintf(ScenarioName, \"SC%c%c%c%c%c.INI\", c_player, first, second, c_dir, c_var);\n\t}\n#else\n\tsprintf(ScenarioName, \"SC%c%02d%c%c.INI\", c_player, scenario, c_dir, c_var);\n#endif\n}\n\n\nvoid ScenarioClass::Set_Scenario_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tstrncpy(ScenarioName, name, sizeof(ScenarioName));\n\t\tScenarioName[ARRAY_SIZE(ScenarioName)-1] = '\\0';\n\n\t\tchar buf[3];\n\t\tmemcpy(buf, &ScenarioName[3], 2);\n\t\tbuf[2] = '\\0';\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tif (buf[0] > '9' || buf[1] > '9') {\n\t\t\tchar first = buf[0];\n\t\t\tchar second = buf[1];\n\t\t\tif (first <= '9') {\n\t\t\t\tfirst -= '0';\n\t\t\t} else {\n\t\t\t\tfirst -= 'A';\n\t\t\t}\n\n\t\t\tif (second <= '9') {\n\t\t\t\tsecond -= '0';\n\t\t\t} else {\n\t\t\t\tsecond = (second - 'A') + 10;\n\t\t\t}\n\n\t\t\tScenario = (36 * first) + second;\n\t\t} else {\n\t\t\tScenario = atoi(buf);\n\t\t}\n#else\n\t\tScenario = atoi(buf);\n#endif\n\t}\n}\n\n\n\n/***********************************************************************************************\n * Read_Scenario_INI -- Read specified scenario INI file.                                      *\n *                                                                                             *\n *    Read in the scenario INI file. This routine only sets the game                           *\n *    globals with that data that is explicitly defined in the INI file.                       *\n *    The remaining necessary interpolated data is generated elsewhere.                        *\n *                                                                                             *\n * INPUT:                                                                                      *\n *          root      root filename for scenario file to read                                  *\n *                                                                                             *\n *          fresh      true = should the current scenario be cleared?                          *\n *                                                                                             *\n * OUTPUT:  bool; Was the scenario read successful?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.  V.Grippi added CS check 2/5/97                                                               *\n *=============================================================================================*/\nbool Read_Scenario_INI(char * fname, bool )\n{\n//\tchar fname[_MAX_FNAME+_MAX_EXT];\t\t\t// full INI filename\n\n\n\tScenarioInit++;\n\n\tClear_Scenario();\n#ifdef OBSOLETE\n\t/*\n\t** If we are not dealing with scenario 1, or a multi player scenario\n\t** then make sure the correct disk is in the drive.\n\t*/\n\tif (RequiredCD != -2) {\n\t\tRequiredCD = -1;\n\t}\n#endif\n\n\t/*\n\t** Only force a CD check if this is a single player game or if its\n\t** a multiplayer game on an official scenario. If its non-official\n\t** (a user scenario) then we dont care which CD is in because the\n\t** scenario is stored locally on the hard drive. In this case, we\n\t** have already verified its existance. ST 3/1/97 4:52PM.\n\t*/\n#ifdef FIXIT_VERSION_3\t\t//\tAvoid CD check if official scenario was downloaded.\n\tif( ( Session.Type == GAME_NORMAL || Session.ScenarioIsOfficial ) && _stricmp( Scen.ScenarioName, \"download.tmp\" ) ){\n#else\n\tif (Session.Type == GAME_NORMAL || Session.ScenarioIsOfficial){\n#endif\n\n\t\t/*\n\t\t** If this is scenario 1 then it should be on all CDs unless its an ant scenario\n\t\t*/\n\t\tif (Scen.Scenario == 1 && Scen.ScenarioName[2] != 'A') {\n\t   \tRequiredCD = -1;\n\t\t} else {\n//\t\t\tMono_Printf(\"Read_SCen_INI scenario is: %s\\n\", Scen.ScenarioName);\n\t\t\t/*\n\t\t\t** If this is a multiplayer scenario we need to find out if its a counterstrike\n\t\t\t** scenario. If so then we need CD 2. The original multiplayer scenarios are on\n\t\t\t** all CDs.\n\t\t\t*/\n\t\t\tif (Session.Type != GAME_NORMAL) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tRequiredCD = -1;\t// default that any CD will do.\n// If it's a counterstrike mission, require the counterstrike CD, unless the\n// Aftermath CD is already in the drive, in which case, leave it there.\n// Note, this works because this section only tests for multiplayer scenarios.\n\t\t\t\tif (Is_Mission_Counterstrike(Scen.ScenarioName)) {\n\t\t\t\t\tRequiredCD = 2;\n\t\t\t\t\tif( Is_Aftermath_Installed() || Get_CD_Index(CCFileClass::Get_CD_Drive(), 1*60) == 3 )\n\t\t\t\t\t{\n\t\t\t\t\t\tRequiredCD = 3;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(Is_Mission_Aftermath(Scen.ScenarioName)) {\n\t\t\t\t\tRequiredCD = 3;\n\t\t\t\t}\n#else\n\t\t\t\tif (Scen.Scenario > 24) {\n\t\t\t\t\tRequiredCD = 2;\n\t\t\t\t} else {\n\t\t\t\t\tRequiredCD = -1;\n\t\t\t\t}\n#endif\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t** This is a solo game. If the scenario number is >= 20 or its an ant mission\n\t\t\t\t** then we need the counterstrike CD (2)\n\t\t\t\t*/\n     \t\t\tif (Scen.Scenario >= 20 || Scen.ScenarioName[2] == 'A') {\n\t\t\t\t\tRequiredCD = 2;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n     \t\t\t\tif (Scen.Scenario >= 36 && Scen.ScenarioName[2] != 'A') {\n\t\t\t\t\t\tRequiredCD = 3;\n#ifdef BOGUSCD\n\tRequiredCD = -1;\n#endif\n\t\t\t\t\t}\n#endif\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** This is a solo mission from the original Red Alert. Choose the Soviet or\n\t\t\t\t\t** allied CD depending on the scenario name.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Scen.ScenarioName[2] == 'U') {\n\t\t\t\t\t\tRequiredCD = 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (Scen.ScenarioName[2] == 'G') {\n//\t\t\t\t\t\t\tMono_Printf(\"We are setting REquiredCD to 0\");\n\t\t\t\t\t\t\tRequiredCD = 0;\n\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n     \t\t\t}\n\t\t\t}\n\t\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// If we're asking for a CD swap, check to see if we need to set the palette\n// to avoid a black screen.  If this is a normal RA game, and the CD being\n// requested is an RA CD, then don't set the palette, leave the map screen up.\n\n#ifdef FIXIT_VERSION_3\n\t\tint cd_index = Get_CD_Index(CCFileClass::Get_CD_Drive(), 1*60);\n\t\tif( !( Using_DVD() && cd_index == 5 ) && cd_index != RequiredCD ) {\n#else\n\t\tif (Get_CD_Index(CCFileClass::Get_CD_Drive(), 1*60) != RequiredCD) {\n#endif\n\t\t\tif ((RequiredCD == 0 || RequiredCD == 1) && Session.Type == GAME_NORMAL) {\n\t\t\t\tSeenPage.Clear();\n\t\t\t}\n\t\t\tGamePalette.Set(FADE_PALETTE_FAST, Call_Back);\n\t\t}\n#endif\n\t\tif (!Force_CD_Available(RequiredCD)) {\n      \t\t//Prog_End();\n\t\t\tEmergency_Exit(EXIT_FAILURE);\n     \t}\n\t} else {\n\t\t/*\n\t\t** This is a user scenario so any old CD will do.\n\t\t*/\n\t\tRequiredCD = -1;\n\t}\n\n\n\t/*\n\t**\tCreate scenario filename and read the file.\n\t*/\n//\tsprintf(fname, \"%s.INI\", root);\n\tCCINIClass ini;\n\tCCFileClass file(fname);\n//\tfile.Cache();\n\n\tint result = ini.Load(file, true);\n\tif (result == 0) {\n//\t\tMono_Printf(\"ini.Load failed\");\n\t\treturn(false);\n\t}\n\n\t/*\n\t** If the scenario digest is wrong then the return code will be a 2.\n\t*/\n\tif (result == 2) {\n//\t\tif (Session.Type == GAME_NORMAL || Session.ScenarioIsOfficial) {\n\t\t\t/*\n\t\t\t**\tMake a special exception so that multiplayer maps from 1 through\n\t\t\t**\t24 will not care if the message digest is in error. All other\n\t\t\t**\tmaps will abort the scenario load.\n\t\t\t*/\n\t\t\tif (Scen.ScenarioName[2] != 'M' || Scen.Scenario >= 25) {\n\t\t\t\tGamePalette.Set();\n\t\t\t\tWWMessageBox().Process(TXT_SCENARIO_ERROR, TXT_OK);\n#ifdef RELEASE_VERSION\n\t\t\t\treturn(false);\n#endif\n\t\t\t}\n//\t\t}\n\t}\n\n\t/*\n\t**\tReset the rules values to their initial settings.\n\t*/\n#ifdef FIXIT_NAME_OVERRIDE\n\tfor (int index = 0; index < ARRAY_SIZE(NameOverride); index++) {\n\t\tif (NameOverride[index] != NULL) free((void*)NameOverride[index]);\n\t\tNameOverride[index] = NULL;\n\t\tNameIDOverride[index] = 0;\n\t}\n\tif (Session.Type == GAME_NORMAL)  {\n\t\tSpecial.IsShadowGrow = false;\n\t}\n#endif\n\n#ifdef FIXIT_ANTS\n\tSession.Messages.Reset();\n//\tSession.Messages.Add_Message(NULL, 0, NULL, PCOLOR_GREEN, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, 1);\n//\tSession.Messages.Add_Message(NULL, 0, NULL, PCOLOR_GREEN, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, 1);\n//\tSession.Messages.Add_Message(NULL, 0, NULL, PCOLOR_GREEN, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, 1);\n//\tSession.Messages.Add_Message(NULL, 0, NULL, PCOLOR_GREEN, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, 1);\n//\tSession.Messages.Add_Message(NULL, 0, NULL, PCOLOR_GREEN, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, 1);\n//\tSession.Messages.Add_Message(NULL, 0, NULL, PCOLOR_GREEN, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, 1);\n\tWeaponTypeClass::As_Pointer(WEAPON_FLAMER)->Sound = VOC_NONE;\n\tInfantryTypeClass::As_Reference(INFANTRY_THIEF).IsDoubleOwned = false;\n\tInfantryTypeClass::As_Reference(INFANTRY_E4).IsDoubleOwned = false;\n\tInfantryTypeClass::As_Reference(INFANTRY_SPY).PrimaryWeapon = NULL;\n\tInfantryTypeClass::As_Reference(INFANTRY_SPY).SecondaryWeapon = NULL;\n\tInfantryTypeClass::As_Reference(INFANTRY_GENERAL).IsBomber = false;\n\tUnitTypeClass::As_Reference(UNIT_HARVESTER).IsExploding = false;\n\tUnitTypeClass::As_Reference(UNIT_ANT1).Level = -1;\n\tUnitTypeClass::As_Reference(UNIT_ANT2).Level = -1;\n\tUnitTypeClass::As_Reference(UNIT_ANT3).Level = -1;\n\tBuildingTypeClass::As_Reference(STRUCT_QUEEN).Level = -1;\n\tBuildingTypeClass::As_Reference(STRUCT_LARVA1).Level = -1;\n\tBuildingTypeClass::As_Reference(STRUCT_LARVA2).Level = -1;\n#endif\n\n\n\tRule.General(RuleINI);\n\tRule.Recharge(RuleINI);\n\tRule.AI(RuleINI);\n\tRule.Powerups(RuleINI);\n\tRule.Land_Types(RuleINI);\n\tRule.Themes(RuleINI);\n\tRule.IQ(RuleINI);\n\tRule.Objects(RuleINI);\n\tRule.Difficulty(RuleINI);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98 - Except does this _change_ any rules, or just add to them? - Just adds.\n\tRule.General(AftermathINI);\n\tRule.Recharge(AftermathINI);\n\tRule.AI(AftermathINI);\n\tRule.Powerups(AftermathINI);\n\tRule.Land_Types(AftermathINI);\n\tRule.Themes(AftermathINI);\n\tRule.IQ(AftermathINI);\n\tRule.Objects(AftermathINI);\n\tRule.Difficulty(AftermathINI);\n#endif\n\t/*\n\t**\tOverride any rules values specified in this\n\t**\tparticular scenario file.\n\t*/\n\tRule.General(ini);\n\tRule.Recharge(ini);\n\tRule.AI(ini);\n\tRule.Powerups(ini);\n\tRule.Land_Types(ini);\n\tRule.Themes(ini);\n\tRule.IQ(ini);\n\tRule.Objects(ini);\n\tRule.Difficulty(ini);\n\t/*\n\t** Init the Scenario CRC value\n\t*/\n\tScenarioCRC = 0;\n#ifdef TOFIX\n\tlen = strlen(buffer);\n\tfor (int i = 0; i < len; i++) {\n\t\tval = (unsigned char)buffer[i];\n\t\tAdd_CRC(&ScenarioCRC, (unsigned long)val);\n\t}\n#endif\n\n\t/*\n\t**\tFetch the appropriate movie names from the INI file.\n\t*/\n\tconst char * const BASIC = \"Basic\";\n\tini.Get_String(BASIC, \"Name\", \"<none>\", Scen.Description, sizeof(Scen.Description));\n\tScen.IntroMovie = ini.Get_VQType(BASIC, \"Intro\", Scen.IntroMovie);\n\tScen.BriefMovie = ini.Get_VQType(BASIC, \"Brief\", Scen.BriefMovie);\n\tScen.WinMovie = ini.Get_VQType(BASIC, \"Win\", Scen.WinMovie);\n\tScen.LoseMovie = ini.Get_VQType(BASIC, \"Lose\", Scen.LoseMovie);\n\tScen.ActionMovie = ini.Get_VQType(BASIC, \"Action\", Scen.ActionMovie);\n\tScen.IsToCarryOver = ini.Get_Bool(BASIC, \"ToCarryOver\", Scen.IsToCarryOver);\n\tScen.IsToInherit = ini.Get_Bool(BASIC, \"ToInherit\", Scen.IsToInherit);\n\tScen.IsInheritTimer = ini.Get_Bool(BASIC, \"TimerInherit\", Scen.IsInheritTimer);\n\tScen.IsEndOfGame = ini.Get_Bool(BASIC, \"EndOfGame\", Scen.IsEndOfGame);\n\tScen.IsTanyaEvac = ini.Get_Bool(BASIC, \"CivEvac\", Scen.IsTanyaEvac);\n\tScen.TransitTheme = ini.Get_ThemeType(BASIC, \"Theme\", THEME_NONE);\n\tNewINIFormat = ini.Get_Int(BASIC, \"NewINIFormat\", 0);\n\tScen.CarryOverPercent = ini.Get_Fixed(BASIC, \"CarryOverMoney\", Scen.CarryOverPercent);\n\tScen.CarryOverPercent = Saturate(Scen.CarryOverPercent, 1);\n\tScen.CarryOverCap = ini.Get_Int(BASIC, \"CarryOverCap\", Scen.CarryOverCap);\n\tScen.IsNoSpyPlane = ini.Get_Bool(BASIC, \"NoSpyPlane\", Scen.IsNoSpyPlane);\n\tScen.IsSkipScore = ini.Get_Bool(BASIC, \"SkipScore\", Scen.IsSkipScore);\n\tScen.IsOneTimeOnly = ini.Get_Bool(BASIC, \"OneTimeOnly\", Scen.IsOneTimeOnly);\n\tScen.IsNoMapSel = ini.Get_Bool(BASIC, \"SkipMapSelect\", Scen.IsNoMapSel);\n\tScen.IsTruckCrate = ini.Get_Bool(BASIC, \"TruckCrate\", Scen.IsTruckCrate);\n\tScen.IsMoneyTiberium = ini.Get_Bool(BASIC, \"FillSilos\", Scen.IsMoneyTiberium);\n\tScen.Percent = ini.Get_Int(BASIC, \"Percent\", Scen.Percent);\n\n\t/*\n\t**\tRead in the specific information for each of the house types.  This creates\n\t**\tthe houses of different types.\n\t*/\n\tHouseClass::Read_INI(ini);\n\tCall_Back();\n\n\t/*\n\t**\tRead in the team-type data. The team types must be created before any\n\t**\ttriggers can be created.\n\t*/\n\tTeamTypeClass::Read_INI(ini);\n\tCall_Back();\n\n\n\t/*\n\t**\tAssign PlayerPtr by reading the player's house from the INI;\n\t**\tMust be done before any TechnoClass objects are created.\n\t*/\n\tif (Session.Type == GAME_NORMAL) {\n\t\tPlayerPtr = HouseClass::As_Pointer(ini.Get_HousesType(BASIC, \"Player\", HOUSE_GREECE));\n\t\tPlayerPtr->Assign_Handicap(Scen.Difficulty);\n\t\tint carryover;\n\t\tif (Scen.CarryOverCap != -1) {\n\t\t\tcarryover = min(Scen.CarryOverMoney * Scen.CarryOverPercent, Scen.CarryOverCap);\n\t\t} else {\n\t\t\tcarryover = Scen.CarryOverMoney * Scen.CarryOverPercent;\n\t\t}\n\t\tPlayerPtr->Credits += carryover;\n\t\tPlayerPtr->Control.InitialCredits += carryover;\n\t} else {\n\t\tAssign_Houses();\n\t}\n\tPlayerPtr->IsHuman = true;\n\tPlayerPtr->IsPlayerControl = true;\n\n\t/*\n\t**\tRead in the trigger data. The triggers must be created before any other\n\t**\tobjects can be initialized.\n\t*/\n\tTriggerTypeClass::Read_INI(ini);\n\tCall_Back();\n\n\n\t/*\n\t**\tRead in the map control values. This includes dimensions\n\t**\tas well as theater information.\n\t*/\n\tMap.Read_INI(ini);\n\tCall_Back();\n\n\n\n//\tif (NewINIFormat < 2 || !ini.Is_Present(\"MapPack\")) {\n//\t\tMap.Read_Binary(root, &ScenarioCRC);\n//\t}\n\n\n\t/*\n\t**\tRead in and place the 3D terrain objects.\n\t*/\n\tTerrainClass::Read_INI(ini);\n\tCall_Back();\n\t/*\n\t**\tRead in and place the units (all sides).\n\t*/\n\tUnitClass::Read_INI(ini);\n\tCall_Back();\n\n    \tVesselClass::Read_INI(ini);\n\tCall_Back();\n\n\t/*\n\t**\tRead in and place the infantry units (all sides).\n\t*/\n\tInfantryClass::Read_INI(ini);\n\tCall_Back();\n\n\n\n\t/*\n\t**\tRead in and place all the buildings on the map.\n\t*/\n\tBuildingClass::Read_INI(ini);\n\tCall_Back();\n\n\t/*\n\t**\tRead in the AI's base information.\n\t*/\n\tBase.Read_INI(ini);\n\tCall_Back();\n\n      \t/*\n\t**\tRead in any normal overlay objects.\n\t*/\n\tOverlayClass::Read_INI(ini);\n\tCall_Back();\n\n\t/*\n\t**\tRead in any smudge overlays.\n\t*/\n\tSmudgeClass::Read_INI(ini);\n\tCall_Back();\n\n\t/*\tMoved above ini.Get_TextBlock(...) so Xlat mission.ini could be loaded\n\t**\tIf the briefing text could not be found in the INI file, then search\n\t**\tthe mission.ini file.  VG 10/17/96\n\t*/\n\tINIClass mini;\n\tmini.Load(CCFileClass(\"MISSION.INI\"));\n\tmini.Get_TextBlock(fname, Scen.BriefingText, sizeof(Scen.BriefingText));\n\n\t/*\n\t**\tRead in any briefing text.\n\t*/\n\tif (Scen.BriefingText[0] == '\\0') {\n\t\tini.Get_TextBlock(\"Briefing\", Scen.BriefingText, sizeof(Scen.BriefingText));\n\t}\n\t/*\n\t**\tPerform a final overpass of the map. This handles smoothing of certain\n\t**\ttypes of terrain (tiberium).\n\t*/\n\tMap.Overpass();\n\tCall_Back();\n\n\t/*\n\t**\tMulti-player last-minute fixups:\n\t**\t- If computer players are disabled, remove all computer-owned houses\n\t**\t- If bases are disabled, create the scenario dynamically\n\t**\t- Remove any flag spot overlays lying around\n\t**\t- If capture-the-flag is enabled, assign flags to cells.\n\t*/\n\tif (Session.Type != GAME_NORMAL /*|| Scen.ScenPlayer == SCEN_PLAYER_2PLAYER || Scen.ScenPlayer == SCEN_PLAYER_MPLAYER*/) {\n\n\t\t/*\n\t\t**\tIf Ghosts are disabled and we're not editing, remove computer players\n\t\t**\t(Must be done after all objects are read in from the INI)\n\t\t*/\n\t\tif ( (Session.Options.AIPlayers + Session.Players.Count() < Rule.MaxPlayers) && !Debug_Map) {\n\t\t\tRemove_AI_Players();\n\t\t}\n\n\t\t/*\n\t\t**\tUnits must be created for each house.  If bases are ON, this routine\n\t\t**\twill create an MCV along with the units; otherwise, it will just create\n\t\t**\ta whole bunch of units.  Session.Options.UnitCount is the total # of units\n\t\t**\tto create.\n\t\t*/\n\t\tif (!Debug_Map) {\n\t\t\tint save_init = ScenarioInit;\t\t\t// turn ScenarioInit off\n\t\t\tScenarioInit = 0;\n\t\t\tCreate_Units(ini.Get_Bool(\"Basic\", \"Official\", false));\n\t\t\tScenarioInit = save_init;\t\t\t\t// turn ScenarioInit back on\n\t\t}\n\n\t\t/*\n\t\t**\tPlace crates if random crates are enabled for\n\t\t**\tthis scenario.\n\t\t*/\n\t\tif (Session.Options.Goodies) {\n\t\t\tint count = max(Rule.CrateMinimum, Session.NumPlayers);\n\t\t\tcount = min(count, Rule.CrateMaximum);\n\t\t\tfor (int index = 0; index < count; index++) {\n\t\t\t\tMap.Place_Random_Crate();\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tCompute my starting location as the average Coord of all my stuff.\n\t\t*/\n\t\tMap.Compute_Start_Pos();\n\t}\n\n\tCall_Back();\n\n\t/*\n\t**\tReturn with flag saying that the scenario file was read.\n\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98 - Added runtime check.\n\tif( Is_Aftermath_Installed() )\n\t{\n\t\tif (Session.Type == GAME_SKIRMISH) {\n\t\t\tbAftermathMultiplayer = NewUnitsEnabled = true;\n\t\t}\n\t}\t\n#endif\n\tScenarioInit--;\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Write_Scenario_INI -- Write the scenario INI file.                                          *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      root      root filename for the scenario                                               *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *   05/11/1995 JLB : Updates movie data.                                                      *\n *=============================================================================================*/\nvoid Write_Scenario_INI(char * fname)\n{\n#ifndef CHEAT_KEYS\n\tfname = fname;\n#else\n//\tCCFileClass file(fname);\n\n\tCCINIClass ini;\n\n\t/*\n\t**\tPreload the old scenario if it is present because there may\n\t**\tbe some fields in the INI that are processed but not written\n\t**\tout. Preloading the scenario will preserve these manually\n\t**\tmaintained entries.\n\t*/\n\tif (CCFileClass(fname).Is_Available()) {\n\t\tini.Load(CCFileClass(fname), true);\n\t}\n\n\tstatic char const * const BASIC = \"Basic\";\n\tini.Clear(BASIC);\n\tini.Put_String(BASIC, \"Name\", Scen.Description);\n\tini.Put_VQType(BASIC, \"Intro\", Scen.IntroMovie);\n\tini.Put_VQType(BASIC, \"Brief\", Scen.BriefMovie);\n\tini.Put_VQType(BASIC, \"Win\", Scen.WinMovie);\n\tini.Put_VQType(BASIC, \"Lose\", Scen.LoseMovie);\n\tini.Put_VQType(BASIC, \"Action\", Scen.ActionMovie);\n\tini.Put_HousesType(BASIC, \"Player\", PlayerPtr->Class->House);\n\tini.Put_ThemeType(BASIC, \"Theme\", Scen.TransitTheme);\n\tini.Put_Fixed(BASIC, \"CarryOverMoney\", Scen.CarryOverPercent);\n\tini.Put_Bool(BASIC, \"ToCarryOver\", Scen.IsToCarryOver);\n\tini.Put_Bool(BASIC, \"ToInherit\", Scen.IsToInherit);\n\tini.Put_Bool(BASIC, \"TimerInherit\", Scen.IsInheritTimer);\n\tini.Put_Bool(BASIC, \"CivEvac\", Scen.IsTanyaEvac);\n\tini.Put_Int(BASIC, \"NewINIFormat\", 3);\n\tini.Put_Int(BASIC, \"CarryOverCap\", Scen.CarryOverCap/100);\n\tini.Put_Bool(BASIC, \"EndOfGame\", Scen.IsEndOfGame);\n\tini.Put_Bool(BASIC, \"NoSpyPlane\", Scen.IsNoSpyPlane);\n\tini.Put_Bool(BASIC, \"SkipScore\", Scen.IsSkipScore);\n\tini.Put_Bool(BASIC, \"OneTimeOnly\", Scen.IsOneTimeOnly);\n\tini.Put_Bool(BASIC, \"SkipMapSelect\", Scen.IsNoMapSel);\n\tini.Put_Bool(BASIC, \"Official\", true);\n\tini.Put_Bool(BASIC, \"FillSilos\", Scen.IsMoneyTiberium);\n\tini.Put_Bool(BASIC, \"TruckCrate\", Scen.IsTruckCrate);\n\tini.Put_Int(BASIC, \"Percent\", Scen.Percent);\n\n\tHouseClass::Write_INI(ini);\n\tTeamTypeClass::Write_INI(ini);\n\tTriggerTypeClass::Write_INI(ini);\n\tMap.Write_INI(ini);\n\tTerrainClass::Write_INI(ini);\n\tUnitClass::Write_INI(ini);\n\tVesselClass::Write_INI(ini);\n\tInfantryClass::Write_INI(ini);\n\tBuildingClass::Write_INI(ini);\n\tBase.Write_INI(ini);\n\tOverlayClass::Write_INI(ini);\n\tSmudgeClass::Write_INI(ini);\n\n\tif (strlen(Scen.BriefingText)) {\n\t\tini.Put_TextBlock(\"Briefing\", Scen.BriefingText);\n\t}\n//\tsprintf(fname, \"%s.INI\", root);\n\tRawFileClass rawfile(fname);\n\tini.Save(rawfile, true);\n#endif\n}\n\n\n/***********************************************************************************************\n * Assign_Houses -- Assigns multiplayer houses to various players                              *\n *                                                                                             *\n * This routine assigns all players to a multiplayer house slot; it forms network connections  *\n * to each player.  The Connection ID used is the value for that player's HousesType.\t\t\t  *\n *                                                                                             *\n * PlayerPtr is also set here.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *\t\tThis routine assumes the 'Players' vector has been properly filled in with players'\t\t  *\n *\t\tnames, addresses, color, etc.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tAlso, it's assumed that the HouseClass's have all been created & initialized.\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/09/1995 BRR : Created.                                                                 *\n *   07/14/1995 JLB : Records name of player in house structure.                               *\n *=============================================================================================*/\nvoid Assign_Houses(void)\n{\n\tint assigned[MAX_PLAYERS];\n\tint color_used[8];\n\tint i,j;\n\tHousesType house;\n\tHouseClass * housep;\n\tint lowest_color;\n\tint index;\n\tHousesType pref_house;\n\tint color;\n\n\t//------------------------------------------------------------------------\n\t// Initialize\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MAX_PLAYERS; i++) {\n\t\tassigned[i] = 0;\n\t\tcolor_used[i] = 0;\n\t}\n\n//\tdebugprint( \"Assign_Houses()\\n\" );\n\t//------------------------------------------------------------------------\n\t// Assign each player in 'Players' to a multiplayer house.  Players will\n\t// be sorted by their chosen color value (this value must be unique among\n\t// all the players).\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\n\t\t//.....................................................................\n\t\t// Find the player with the lowest color index\n\t\t//.....................................................................\n\t\tindex = 0;\n\t\tlowest_color = 255;\n\t\tfor (j = 0; j < Session.Players.Count(); j++) {\n\t\t\t//..................................................................\n\t\t\t// If we've already assigned this house, skip it.\n\t\t\t//..................................................................\n\t\t\tif (assigned[j]) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (Session.Players[j]->Player.Color < lowest_color) {\n\t\t\t\tlowest_color = Session.Players[j]->Player.Color;\n\t\t\t\tindex = j;\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Mark this player as having been assigned.\n\t\t//.....................................................................\n\t\tassigned[index] = 1;\n\t\tcolor_used[Session.Players[index]->Player.Color] = 1;\n\n\t\t//.....................................................................\n\t\t// Assign the lowest-color'd player to the next available slot in the\n\t\t// HouseClass array.\n\t\t//.....................................................................\n\t\thouse = (HousesType)(i + HOUSE_MULTI1);\n\t\thousep = HouseClass::As_Pointer(house);\n\t\tmemset((char *)housep->IniName, 0, MPLAYER_NAME_MAX);\n\t\tstrncpy((char *)housep->IniName, Session.Players[index]->Name, MPLAYER_NAME_MAX - 1);\n#ifdef WOLAPI_INTEGRATION\n\t\t//\tMake another copy of name, permanent throughout entire game.\n\t\tstrncpy((char *)housep->InitialName, Session.Players[index]->Name, MPLAYER_NAME_MAX - 1);\n#endif\n\t\thousep->IsHuman = true;\n\t\thousep->Init_Data((PlayerColorType)(Session.Players[index]->Player.Color),\n\t\t\tSession.Players[index]->Player.House, Session.Options.Credits);\n\t\tif (index == 0) {\n\t\t\tPlayerPtr = housep;\n\t\t}\n\t\t/*\n\t\t**\tConvert the build level into an actual tech level to assign to the house.\n\t\t**\tThere isn't a one-to-one correspondence.\n\t\t*/\n\t\thousep->Control.TechLevel = _build_tech[BuildLevel];\n\n\t\thousep->Assign_Handicap(Scen.Difficulty);\n\n\t\t//.....................................................................\n\t\t// Record where we placed this player\n\t\t//.....................................................................\n\t\tSession.Players[index]->Player.ID = house;\n\n//\t\tdebugprint( \"Assigned ID of %i to %s\\n\", house, Session.Players[index]->Name );\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Now assign computer players to the remaining houses.\n\t//------------------------------------------------------------------------\n\tfor (i = Session.Players.Count(); i < Session.Players.Count() + Session.Options.AIPlayers; i++) {\n\t\thouse = (HousesType)(i + HOUSE_MULTI1);\n\t\thousep = HouseClass::As_Pointer(house);\n\t\tif (Percent_Chance(50)) {\n\t\t\tpref_house = HOUSE_GREECE;\n\t\t} else {\n\t\t\tpref_house = HOUSE_USSR;\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Pick a color for this house; keep looping until we find one.\n\t\t//.....................................................................\n\t\twhile (1) {\n\t\t\tcolor = Random_Pick(0, 7);\n\t\t\tif (color_used[color] == false) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tcolor_used[color] = true;\n\n\t\t//.....................................................................\n\t\t// Set up the house\n\t\t//.....................................................................\n//\t\thousep->Control.MaxUnit = 80;\n//\t\thousep->Control.MaxInfantry = 60;\n//\t\thousep->Control.MaxBuilding = 60;\n//\t\thousep->Control.MaxVessel = 60;\n\t\thousep->IsHuman = false;\n\t\thousep->IsStarted = true;\n\n\t\tstrcpy(housep->IniName, Text_String(TXT_COMPUTER));\n\n\t\tif (Session.Type != GAME_NORMAL) {\n\t\t\thousep->IQ = Rule.MaxIQ;\n\t\t}\n\n\t\thousep->Init_Data((PlayerColorType)color, pref_house, Session.Options.Credits);\n\t\thousep->Control.TechLevel = _build_tech[BuildLevel];\n//\t\thousep->Control.TechLevel = BuildLevel;\n\n\t\tDiffType difficulty = Scen.CDifficulty;\n\n\t\tif (Session.Players.Count() > 1 && Rule.IsCompEasyBonus && difficulty > DIFF_EASY) {\n\t\t\tdifficulty = (DiffType)(difficulty - 1);\n\t\t}\n\t\thousep->Assign_Handicap(difficulty);\n\t}\n\n\tfor (i = Session.Players.Count()+Session.Options.AIPlayers; i < Rule.MaxPlayers; i++) {\n\t\thouse = (HousesType)(i + HOUSE_MULTI1);\n\t\thousep = HouseClass::As_Pointer(house);\n\t\tif (housep != NULL) {\n\t\t\thousep->IsDefeated = true;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Remove_AI_Players -- Removes the computer AI houses & their units                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/09/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nstatic void Remove_AI_Players(void)\n{\n\tint i;\n\tint aicount = 0;\n\tHousesType house;\n\tHouseClass * housep;\n\n\tfor (i = 0; i < MAX_PLAYERS; i++) {\n\t\thouse = (HousesType)(i + (int)HOUSE_MULTI1);\n\t\thousep = HouseClass::As_Pointer (house);\n\t\tif (housep->IsHuman == false) {\n\t\t\taicount++;\n\t\t\tif(aicount > Session.Options.AIPlayers) {\n\t\t\t\thousep->Clobber_All();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Create_Units -- Creates infantry & units, for non-base multiplayer                          *\n *                                                                                             *\n * This routine uses data tables to determine which units to create for either                 *\n * a GDI or NOD house, and how many of each.                                                   *\n *                                                                                             *\n * It also sets each house's FlagHome & FlagLocation to the Waypoint selected                  *\n * as that house's \"home\" cell.                                                                *\n *                                                                                             *\n * INPUT:   official -- Directs the placement logic to use the full set of waypoints rather    *\n *                      than biasing toward the first four.                                    *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/09/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nstatic void Create_Units(bool official)\n{\n\tstatic struct {\n\t\tint MinLevel;\n\t\tUnitType AllyType[2];\n\t\tUnitType SovietType[2];\n\t} utable[] = {\n\t\t{4,\t{UNIT_MTANK2,   UNIT_LTANK}, \t{UNIT_MTANK,\t\t UNIT_NONE}},\n\t\t{5,\t{UNIT_APC,      UNIT_NONE},  \t{UNIT_V2_LAUNCHER, UNIT_NONE}},\n\t\t{8,\t{UNIT_ARTY,     UNIT_JEEP},  \t{UNIT_MTANK,\t\t UNIT_NONE}},\n\t\t{10,\t{UNIT_MTANK2,   UNIT_MTANK2},\t{UNIT_HTANK,\t\t UNIT_NONE}}\n\t};\n\tstatic int num_units[ARRAY_SIZE(utable)];\t\t// # of each type of unit to create\n\tint tot_units;\t\t\t\t\t\t\t\t\t\t\t\t// total # units to create\n\n\tstatic struct {\n\t\tint MinLevel;\n\t\tint AllyCount;\n\t\tInfantryType AllyType;\n\t\tint SovietCount;\n\t\tInfantryType SovietType;\n\t} itable[] = {\n\t\t{0,\t1,INFANTRY_E1,\t\t\t\t1,INFANTRY_E1},\n\t\t{2,\t1,INFANTRY_E3,\t\t\t\t1,INFANTRY_E2},\n\t\t{4,\t1,INFANTRY_E3,\t\t\t\t1,INFANTRY_E4},\n\n// removed because of bug B478 (inappropriate infantry given in a bases off scenario).\n//\t\t{5,\t1,INFANTRY_RENOVATOR,\t1,INFANTRY_RENOVATOR},\n//\t\t{6,\t1,INFANTRY_SPY,\t\t\t1,INFANTRY_DOG},\n//\t\t{10,\t1,INFANTRY_THIEF,\t\t\t1,INFANTRY_DOG},\n//\t\t{12,\t1,INFANTRY_MEDIC,\t\t\t2,INFANTRY_DOG}\n\t};\n\tstatic int num_infantry[ARRAY_SIZE(itable)];// # of each type of infantry to create\n\tint tot_infantry;\t\t\t\t\t\t\t\t\t\t\t// total # infantry to create\n\n\n\tCELL centroid;\t\t\t// centroid of this house's stuff\n\tCELL centerpt;\t\t\t// centroid for a category of objects, as a CELL\n\n\tint u_limit=0;\t\t\t// last allowable index of units for this BuildLevel\n\tint i_limit=0;\t\t\t// last allowable index of infantry for this BuildLevel\n\tTechnoClass * obj;\t\t// newly-created object\n\tint i,j,k;\t\t\t\t// loop counters\n\tint scaleval;\t\t\t// value to scale # units or infantry\n\n\t/*\n\t**\tFor the current BuildLevel, find the max allowable index into the tables\n\t*/\n\tfor (i = 0; i < ARRAY_SIZE(utable); i++) {\n\t\tif (PlayerPtr->Control.TechLevel >= utable[i].MinLevel) {\n\t\t\tu_limit = i+1;\n\t\t}\n\t}\n\tfor (i = 0; i < ARRAY_SIZE(itable); i++) {\n\t\tif (PlayerPtr->Control.TechLevel >= itable[i].MinLevel) {\n\t\t\ti_limit = i+1;\n\t\t}\n\t}\n\n\t/*\n\t**\tCompute how many of each buildable category to create\n\t*/\n\t/*\n\t**\tCompute allowed # units\n\t*/\n\ttot_units = (Session.Options.UnitCount * 2) / 3;\n\tif (u_limit == 0) tot_units = 0;\n\n\t/*\n\t**\tInit # of each category to 0\n\t*/\n\tfor (i = 0; i < u_limit; i++) {\n\t\tnum_units[i] = 0;\n\t}\n\n\t/*\n\t**\tIncrement # of each category, until we've used up all units\n\t*/\n\tj = 0;\n\tfor (i = 0; i < tot_units; i++) {\n\t\tnum_units[j]++;\n\t\tj++;\n\t\tif (j >= u_limit) {\n\t\t\tj = 0;\n\t\t}\n\t}\n\n\t/*\n\t**\tCompute allowed # infantry\n\t*/\n\ttot_infantry = Session.Options.UnitCount - tot_units;\n\n\t/*\n\t**\tInit # of each category to 0\n\t*/\n\tfor (i = 0; i < i_limit; i++) {\n\t\tnum_infantry[i] = 0;\n\t}\n\n\t/*\n\t**\tIncrement # of each category, until we've used up all infantry\n\t*/\n\tj = 0;\n\tfor (i = 0; i < tot_infantry; i++) {\n\t\tnum_infantry[j]++;\n\t\tj++;\n\t\tif (j >= i_limit) {\n\t\t\tj = 0;\n\t\t}\n\t}\n\n\t/*\n\t**\tBuild a list of the valid waypoints. This normally shouldn't be\n\t**\tnecessary because the scenario level designer should have assigned\n\t**\tvalid locations to the first N waypoints, but just in case, this\n\t**\tloop verifies that.\n\t*/\n\tbool taken[26];\n\tCELL waypts[26];\n\tassert(Rule.MaxPlayers < ARRAY_SIZE(waypts));\n\tint num_waypts = 0;\n\n\t/*\n\t**\tCalculate the number of waypoints (as a minimum) that will be lifted from the\n\t**\tmission file. Bias this number so that only the first 4 waypoints are used\n\t**\tif there are 4 or fewer players. Unofficial maps will pick from all the\n\t**\tavailable waypoints.\n\t*/\n\tint look_for = max(4, Session.Players.Count()+Session.Options.AIPlayers);\n\tif (!official) {\n\t\tlook_for = 8;\n\t}\n\n\tfor (int waycount = 0; waycount < look_for; waycount++) {\n//\tfor (int waycount = 0; waycount < max(4, Session.Players.Count()+Session.Options.AIPlayers); waycount++) {\n\t\tif (Scen.Waypoint[waycount] != -1) {\n\t\t\twaypts[num_waypts] = Scen.Waypoint[waycount];\n\t\t\ttaken[num_waypts] = false;\n\t\t\tnum_waypts++;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there are insufficient waypoints to account for all players, then randomly assign\n\t**\tstarting points until there is enough.\n\t*/\n\tint deficiency = look_for - num_waypts;\n//\tint deficiency = (Session.Players.Count() + Session.Options.AIPlayers) - num_waypts;\n\tif (deficiency > 0) {\n\t\tfor (int index = 0; index < deficiency; index++) {\n\t\t\tCELL trycell = XY_Cell(Map.MapCellX + Random_Pick(0, Map.MapCellWidth-1), Map.MapCellY + Random_Pick(0, Map.MapCellHeight-1));\n\n\t\t\ttrycell = Map.Nearby_Location(trycell, SPEED_TRACK);\n\t\t\twaypts[num_waypts] = trycell;\n\t\t\ttaken[num_waypts] = false;\n\t\t\tnum_waypts++;\n\t\t}\n\t}\n\n\t/*\n\t**\tLoop through all houses.  Computer-controlled houses, with Session.Options.Bases\n\t**\tON, are treated as though bases are OFF (since we have no base-building\n\t**\tAI logic.)\n\t*/\n\tint numtaken = 0;\n\tfor (HousesType house = HOUSE_MULTI1; house < (HOUSE_MULTI1 + Session.MaxPlayers); house++) {\n\n\t\t/*\n\t\t**\tGet a pointer to this house; if there is none, go to the next house\n\t\t*/\n\t\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\t\tif (hptr == NULL) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tPick the starting location for this house. The first house just picks\n\t\t**\tone of the valid locations at random. The other houses pick the furthest\n\t\t**\twapoint from the existing houses.\n\t\t*/\n\t\tif (numtaken == 0) {\n\t\t\tint pick = Random_Pick(0, num_waypts-1);\n\t\t\tcentroid = waypts[pick];\n\t\t\ttaken[pick] = true;\n\t\t\tnumtaken++;\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tSet all waypoints to have a score of zero in preparation for giving\n\t\t\t**\ta distance score to all waypoints.\n\t\t\t*/\n\t\t\tint score[26];\n\t\t\tmemset(score, '\\0', sizeof(score));\n\n\t\t\t/*\n\t\t\t**\tScan through all waypoints and give a score as a value of the sum\n\t\t\t**\tof the distances from this waypoint to all taken waypoints.\n\t\t\t*/\n\t\t\tfor (int index = 0; index < num_waypts; index++) {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this waypoint has not already been taken, then accumulate the\n\t\t\t\t**\tsum of the distance between this waypoint and all other taken\n\t\t\t\t**\twaypoints.\n\t\t\t\t*/\n\t\t\t\tif (!taken[index]) {\n\t\t\t\t\tfor (int trypoint = 0; trypoint < num_waypts; trypoint++) {\n\n\t\t\t\t\t\tif (taken[trypoint]) {\n\t\t\t\t\t\t\tscore[index] += Distance(Cell_Coord(waypts[index]), Cell_Coord(waypts[trypoint]));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tNow find the waypoint with the largest score. This waypoint is the one\n\t\t\t**\tthat is furthest from all other taken waypoints.\n\t\t\t*/\n\t\t\tint best = 0;\n\t\t\tint bestvalue = 0;\n\t\t\tfor (int searchindex = 0; searchindex < num_waypts; searchindex++) {\n\t\t\t\tif (score[searchindex] > bestvalue || bestvalue == 0) {\n\t\t\t\t\tbestvalue = score[searchindex];\n\t\t\t\t\tbest = searchindex;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAssign this best position to the house.\n\t\t\t*/\n\t\t\tcentroid = waypts[best];\n\t\t\ttaken[best] = true;\n\t\t\tnumtaken++;\n\t\t}\n\n\t\t/*\n\t\t**\tAssign the center of this house to the waypoint location.\n\t\t*/\n\t\thptr->Center = Cell_Coord(centroid);\n\n\t\t/*\n\t\t**\tIf Bases are ON, human & computer houses are treated differently\n\t\t*/\n\t\tif (Session.Options.Bases) {\n\n\t\t\t/*\n\t\t\t**\t- For a human-controlled house:\n\t\t\t**\t  - Set 'scaleval' to 1\n\t\t\t**\t  - Create an MCV\n\t\t\t**\t  - Attach a flag to it for capture-the-flag mode\n\t\t\t*/\n\t\t\tscaleval = 1;\n\t\t\tobj = new UnitClass (UNIT_MCV, house);\n\t\t\tif (!obj->Unlimbo(Cell_Coord(centroid), DIR_N)) {\n\t\t\t\tif (!Scan_Place_Object(obj, centroid)) {\n\t\t\t\t\tdelete obj;\n\t\t\t\t\tobj = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (obj != NULL) {\n\t\t\t\thptr->FlagHome = 0;\n\t\t\t\thptr->FlagLocation = 0;\n\t\t\t\tif (Special.IsCaptureTheFlag) {\n\t\t\t\t\thptr->Flag_Attach((UnitClass *)obj, true);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf bases are OFF, set 'scaleval' to 1 & create a Mobile HQ for\n\t\t\t**\tcapture-the-flag mode.\n\t\t\t*/\n\t\t\tscaleval = 1;\n#ifdef TOFIX\n\t\t\tif (Special.IsCaptureTheFlag) {\n\t\t\t\tobj = new UnitClass (UNIT_TRUCK, house);\n\t\t\t\tobj->Unlimbo(Cell_Coord(centroid), DIR_N);\n\t\t\t\thptr->FlagHome = 0;\t\t\t\t\t// turn house's flag off\n\t\t\t\thptr->FlagLocation = 0;\n\t\t\t}\n#endif\n\t\t}\n\n\t\t/*\n\t\t**\tCreate units for this house\n\t\t*/\n\t\tfor (i = 0; i < u_limit; i++) {\n\n\t\t\t/*\n\t\t\t**\tFind the center point for this category.\n\t\t\t*/\n\t\t\tcenterpt = Clip_Scatter(centroid, 4);\n\n\t\t\t/*\n\t\t\t**\tPlace objects; loop through all unit in this category\n\t\t\t*/\n\t\t\tfor (j = 0; j < num_units[i] * scaleval; j++) {\n\n\t\t\t\t/*\n\t\t\t\t**\tCreate an Ally unit\n\t\t\t\t*/\n\t\t\t\tif (hptr->ActLike != HOUSE_USSR && hptr->ActLike != HOUSE_UKRAINE) {\n\t\t\t\t\tfor (k = 0; k < 2; k++) if(utable[i].AllyType[k] != UNIT_NONE) {\n\t\t\t\t\t\tobj = new UnitClass (utable[i].AllyType[k], house);\n\t\t\t\t\t\tif (!Scan_Place_Object(obj, centerpt)) {\n\t\t\t\t\t\t\tdelete obj;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (!hptr->IsHuman) {\n\t\t\t\t\t\t\t\tobj->Set_Mission(MISSION_GUARD_AREA);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tobj->Set_Mission(MISSION_GUARD);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCreate a Soviet unit\n\t\t\t\t\t*/\n\t\t\t\t\tfor (k = 0; k < 2; k++) if(utable[i].SovietType[k] != UNIT_NONE) {\n\t\t\t\t\t\tobj = new UnitClass (utable[i].SovietType[k], house);\n\t\t\t\t\t\tif (!Scan_Place_Object(obj, centerpt)) {\n\t\t\t\t\t\t\tdelete obj;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (!hptr->IsHuman) {\n\t\t\t\t\t\t\t\tobj->Set_Mission(MISSION_GUARD_AREA);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tobj->Set_Mission(MISSION_GUARD);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tCreate infantry\n\t\t*/\n\t\tfor (i = 0; i < i_limit; i++) {\n\t\t\t/*\n\t\t\t**\tFind the center point for this category.\n\t\t\t*/\n\t\t\tcenterpt = Clip_Scatter(centroid, 4);\n\n\t\t\t/*\n\t\t\t**\tPlace objects; loop through all unit in this category\n\t\t\t*/\n\t\t\tfor (j = 0; j < num_infantry[i] * scaleval; j++) {\n\n\t\t\t\t/*\n\t\t\t\t**\tCreate Ally infantry (Note: Unlimbo calls Enter_Idle_Mode(), which\n\t\t\t\t**\tassigns the infantry to HUNT; we must use Set_Mission() to override\n\t\t\t\t**\tthis state.)\n\t\t\t\t*/\n\t\t\t\tif (hptr->ActLike != HOUSE_USSR && hptr->ActLike != HOUSE_UKRAINE) {\n\t\t\t\t\tfor (k = 0; k < itable[i].AllyCount; k++) {\n\t\t\t\t\t\tobj = new InfantryClass (itable[i].AllyType, house);\n\t\t\t\t\t\tif (!Scan_Place_Object(obj, centerpt)) {\n\t\t\t\t\t\t\tdelete obj;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (!hptr->IsHuman) {\n\t\t\t\t\t\t\t\tobj->Set_Mission(MISSION_GUARD_AREA);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tobj->Set_Mission(MISSION_GUARD);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCreate Soviet infantry\n\t\t\t\t\t*/\n\t\t\t\t\tfor (k = 0; k < itable[i].SovietCount; k++) {\n\t\t\t\t\t\tobj = new InfantryClass (itable[i].SovietType, house);\n\t\t\t\t\t\tif (!Scan_Place_Object(obj, centerpt)) {\n\t\t\t\t\t\t\tdelete obj;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (!hptr->IsHuman) {\n\t\t\t\t\t\t\t\tobj->Set_Mission(MISSION_GUARD_AREA);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tobj->Set_Mission(MISSION_GUARD);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Scan_Place_Object -- places an object >near< the given cell                                 *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      obj      ptr to object to Unlimbo                                                      *\n *      cell      center of search area                                                        *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = object was placed; false = it wasn't                                            *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/09/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nint Scan_Place_Object(ObjectClass * obj, CELL cell)\n{\n\tint dist;\t\t\t\t// for object placement\n\tFacingType rot;\t\t// for object placement\n\tFacingType fcounter;\t// for object placement\n\tint tryval;\n\tCELL newcell;\n\tTechnoClass * techno;\n\tint skipit;\n\n\t/*\n\t**\tFirst try to unlimbo the object in the given cell.\n\t*/\n\tif (Map.In_Radar(cell)) {\n\t\ttechno = Map[cell].Cell_Techno();\n\t\tif (!techno || (techno->What_Am_I()==RTTI_INFANTRY &&\n\t\t\tobj->What_Am_I()==RTTI_INFANTRY)) {\n\t\t\tif (obj->Unlimbo(Cell_Coord(cell), DIR_N)) {\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tLoop through distances from the given center cell; skip the center cell.\n\t**\tFor each distance, try placing the object along each rotational direction;\n\t**\tif none are available, try each direction with a random scatter value.\n\t**\tIf that fails, go to the next distance.\n\t**\tThis ensures that the closest coordinates are filled first.\n\t*/\n\tfor (dist = 1; dist < 32; dist++) {\n\n\t\t/*\n\t\t**\tPick a random starting direction\n\t\t*/\n\t\trot = Random_Pick(FACING_N, FACING_NW);\n\n\t\t/*\n\t\t**\tTry all directions twice\n\t\t*/\n\t\tfor (tryval = 0 ; tryval < 2; tryval++) {\n\n\t\t\t/*\n\t\t\t**\tLoop through all directions, at this distance.\n\t\t\t*/\n\t\t\tfor (fcounter = FACING_N; fcounter <= FACING_NW; fcounter++) {\n\n\t\t\t\tskipit = false;\n\n\t\t\t\t/*\n\t\t\t\t**\tPick a coordinate along this directional axis\n\t\t\t\t*/\n\t\t\t\tnewcell = Clip_Move(cell, rot, dist);\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this is our second try at this distance, add a random scatter\n\t\t\t\t**\tto the desired cell, so our units aren't all aligned along spokes.\n\t\t\t\t*/\n\t\t\t\tif (tryval > 0) {\n\t\t\t\t\tnewcell = Clip_Scatter (newcell, 1);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf, by randomly scattering, we've chosen the exact center, skip\n\t\t\t\t**\tit & try another direction.\n\t\t\t\t*/\n\t\t\t\tif (newcell==cell) {\n\t\t\t\t\tskipit = true;\n\t\t\t\t}\n\n\t\t\t\tif (!skipit) {\n\t\t\t\t\t/*\n\t\t\t\t\t**\tOnly attempt to Unlimbo the object if:\n\t\t\t\t\t**\t- there is no techno in the cell\n\t\t\t\t\t**\t- the techno in the cell & the object are both infantry\n\t\t\t\t\t*/\n\t\t\t\t\ttechno = Map[newcell].Cell_Techno();\n\t\t\t\t\tif (!techno || (techno->What_Am_I()==RTTI_INFANTRY &&\n\t\t\t\t\t\tobj->What_Am_I()==RTTI_INFANTRY)) {\n\t\t\t\t\t\tif (obj->Unlimbo(Cell_Coord(newcell), DIR_N)) {\n\t\t\t\t\t\t\treturn(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\trot++;\n\t\t\t\tif (rot > FACING_NW) {\n\t\t\t\t\trot = FACING_N;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * Clip_Scatter -- randomly scatters from given cell; won't fall off map                       *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      cell      cell to scatter from                                                         *\n *      maxdist   max distance to scatter                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      new cell number                                                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nstatic CELL Clip_Scatter(CELL cell, int maxdist)\n{\n\tint x,y;\n\tint xdist;\n\tint ydist;\n\tint xmin,xmax;\n\tint ymin,ymax;\n\n\t/*\n\t**\tGet X & Y coords of given starting cell\n\t*/\n\tx = Cell_X(cell);\n\ty = Cell_Y(cell);\n\n\t/*\n\t**\tCompute our x & y limits\n\t*/\n\txmin = Map.MapCellX;\n\txmax = xmin + Map.MapCellWidth - 1;\n\tymin = Map.MapCellY;\n\tymax = ymin + Map.MapCellHeight - 1;\n\n\t/*\n\t**\tAdjust the x-coordinate\n\t*/\n\txdist = Random_Pick(0, maxdist);\n\tif (Percent_Chance(50)) {\n\t\tx += xdist;\n\t\tif (x > xmax) {\n\t\t\tx = xmax;\n\t\t}\n\t} else {\n\t\tx -= xdist;\n\t\tif (x < xmin) {\n\t\t\tx = xmin;\n\t\t}\n\t}\n\n\t/*\n\t**\tAdjust the y-coordinate\n\t*/\n\tydist = Random_Pick(0, maxdist);\n\tif (Percent_Chance(50)) {\n\t\ty += ydist;\n\t\tif (y > ymax) {\n\t\t\ty = ymax;\n\t\t}\n\t} else {\n\t\ty -= ydist;\n\t\tif (y < ymin) {\n\t\t\ty = ymin;\n\t\t}\n\t}\n\n\treturn (XY_Cell(x, y));\n}\n\n\n/***********************************************************************************************\n * Clip_Move -- moves in given direction from given cell; clips to map                         *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      cell      cell to start from                                                           *\n *      facing   direction to move                                                             *\n *      dist      distance to move                                                             *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      new cell number                                                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nstatic CELL Clip_Move(CELL cell, FacingType facing, int dist)\n{\n\tint x,y;\n\tint xmin,xmax;\n\tint ymin,ymax;\n\n\t/*\n\t**\tGet X & Y coords of given starting cell\n\t*/\n\tx = Cell_X(cell);\n\ty = Cell_Y(cell);\n\n\t/*\n\t**\tCompute our x & y limits\n\t*/\n\txmin = Map.MapCellX;\n\txmax = xmin + Map.MapCellWidth - 1;\n\tymin = Map.MapCellY;\n\tymax = ymin + Map.MapCellHeight - 1;\n\n\t/*\n\t**\tAdjust the x-coordinate\n\t*/\n\tswitch (facing) {\n\t\tcase FACING_N:\n\t\t\ty -= dist;\n\t\t\tbreak;\n\n\t\tcase FACING_NE:\n\t\t\tx += dist;\n\t\t\ty -= dist;\n\t\t\tbreak;\n\n\t\tcase FACING_E:\n\t\t\tx += dist;\n\t\t\tbreak;\n\n\t\tcase FACING_SE:\n\t\t\tx += dist;\n\t\t\ty += dist;\n\t\t\tbreak;\n\n\t\tcase FACING_S:\n\t\t\ty += dist;\n\t\t\tbreak;\n\n\t\tcase FACING_SW:\n\t\t\tx -= dist;\n\t\t\ty += dist;\n\t\t\tbreak;\n\n\t\tcase FACING_W:\n\t\t\tx -= dist;\n\t\t\tbreak;\n\n\t\tcase FACING_NW:\n\t\t\tx -= dist;\n\t\t\ty -= dist;\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tClip to the map\n\t*/\n\tif (x > xmax)\n\t\tx = xmax;\n\tif (x < xmin)\n\t\tx = xmin;\n\n\tif (y > ymax)\n\t\ty = ymax;\n\tif (y < ymin)\n\t\ty = ymin;\n\n\treturn (XY_Cell(x, y));\n}\n\n\nvoid Disect_Scenario_Name(char const * name, int & scenario, ScenarioPlayerType & player, ScenarioDirType & dir, ScenarioVarType & var)\n{\n\tif (name == NULL) return;\n\n\t/*\n\t**\tFetch the scenario number.\n\t*/\n\tchar buf[3];\n\tmemcpy(buf, &name[3], 2);\n\tbuf[2] = '\\0';\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tchar first = buf[0];\n\tchar second = buf[1];\n\tif (first <= '9' && second <= '9') {\n\t\tscenario = atoi(buf);\n\t} else {\n\t\tif (first <= '9') {\n\t\t\tfirst -= '0';\n\t\t} else {\n\t\t\tif (first >= 'a' && first <= 'z') {\n\t\t\t\tfirst -= 'a';\n\t\t\t} else {\n\t\t\t\tfirst -= 'A';\n\t\t\t}\n\t\t}\n\t\tif (second <= '9') {\n\t\t\tsecond -= '0';\n\t\t} else {\n\t\t\tif (second >= 'a' && second <= 'z') {\n\t\t\t\tsecond = (second - 'a') + 10;\n\t\t\t} else {\n\t\t\t\tsecond = (second - 'A') + 10;\n\t\t\t}\n\t\t}\n\t\tscenario = (36 * first) + second;\n\t}\n#else\n\tscenario = atoi(buf);\n#endif\n\n\t/*\n\t**\tFetch the scenario player (side).\n\t*/\n\tplayer = SCEN_PLAYER_GREECE;\n\tif (name[2] == HouseTypeClass::As_Reference(HOUSE_SPAIN).Prefix) {\n\t\tplayer = SCEN_PLAYER_SPAIN;\n\t}\n\tif (name[2] == HouseTypeClass::As_Reference(HOUSE_GREECE).Prefix) {\n\t\tplayer = SCEN_PLAYER_GREECE;\n\t}\n\tif (name[2] == HouseTypeClass::As_Reference(HOUSE_USSR).Prefix) {\n\t\tplayer = SCEN_PLAYER_USSR;\n\t}\n\n\t/*\n\t**\tFetch the direction.\n\t*/\n\tdir = SCEN_DIR_EAST;\n\tif (name[5] == 'E') {\n\t\tdir = SCEN_DIR_EAST;\n\t} else {\n\t\tdir = SCEN_DIR_WEST;\n\t}\n\n\t/*\n\t**\tFetch the variation.\n\t*/\n\tvar = SCEN_VAR_A;\n\tvar = ScenarioVarType((name[6] - 'A') + SCEN_VAR_A);\n}\n"
  },
  {
    "path": "CODE/SCENARIO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SCENARIO.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SCENARIO.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/26/96                                                     *\n *                                                                                             *\n *                  Last Update : February 26, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef SCENARIO_H\n#define SCENARIO_H\n\n\n/*\n**\tThis class holds the information about the current game being played. This information is\n**\tglobal to the scenario and is generally of a similar nature to the information that was held\n**\tin the controlling scenario INI file. It is safe to write this structure out as a whole since\n**\tit doesn't contain any embedded pointers.\n*/\nclass ScenarioClass {\n\tpublic:\n\n\t\t// Constructor.\n\t\tScenarioClass(void);\n\t\tvoid Set_Scenario_Name(int scenario, ScenarioPlayerType player, ScenarioDirType dir = SCEN_DIR_NONE, ScenarioVarType var = SCEN_VAR_NONE);\n\t\tvoid Set_Scenario_Name(char const * name);\n\n\t\tbool Set_Global_To(int global, bool value);\n\t\tvoid Do_BW_Fade(void);\n\t\tvoid Do_Fade_AI(void);\n\n\t\t/*\n\t\t**\tThis is the source of the random numbers used in the game. This controls\n\t\t**\tthe game logic and thus must be in sync with any networked machines.\n\t\t*/\n\t\tRandomClass RandomNumber;\n\n\t\t/*\n\t\t**\tThis is the difficulty setting of the game.\n\t\t*/\n\t\tDiffType Difficulty;\t\t\t// For human player.\n\t\tDiffType CDifficulty;\t\t// For computer players.\n\n\t\t/*\n\t\t**\tThis is the main mission timer. This is the timer that is reset at the\n\t\t**\tstart of the mission. It, effectively, holds the elapsed time of the\n\t\t**\tmission.\n\t\t*/\n\t\tTTimerClass<FrameTimerClass> Timer;\n\n\t\t/*\n\t\t**\tThis is an array of waypoints; each waypoint corresponds to a letter of\n\t\t** the alphabet, and points to a cell number.  -1 means unassigned.\n\t\t** The CellClass has a bit that tells if that cell has a waypoint attached to\n\t\t** it; the only way to find which waypoint it is, is to scan this array.  This\n\t\t** shouldn't be needed often; usually, you know the waypoint & you want the CELL.\n\t\t*/\n\t\tCELL Waypoint[WAYPT_COUNT];\n\n\t\t/*\n\t\t**\tThis holds the system wide mission countdown timer. Time based missions\n\t\t**\tare governed by this timer. Various trigger events can modify and examine\n\t\t**\tthis timer. The current value of this timer will display on the game\n\t\t**\tscreen.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> MissionTimer;\n\n\t\t/*\n\t\t**\tThe shroud regrowth (if enabled) is regulated by this timer. When the\n\t\t**\ttimer expires, the shroud will regrow one step.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> ShroudTimer;\n\n\t\t/*\n\t\t**\tThe scenario number.\n\t\t*/\n\t\tint Scenario;\n\n\t\t/*\n\t\t**\tThe theater of the current scenario.\n\t\t*/\n\t\tTheaterType Theater;\n\n\t\t/*\n\t\t**\tThe full name of the scenario (as it exists on disk).\n\t\t*/\n\t\tchar ScenarioName[_MAX_FNAME+_MAX_EXT];\n\n\t\t/*\n\t\t**\tDescription of the scenario.\n\t\t*/\n\t\tchar Description[DESCRIP_MAX];\n\n\t\t/*\n\t\t**\tThe filename of the introduction movie.\n\t\t*/\n\t\tVQType IntroMovie;\n\n\t\t/*\n\t\t**\tThe filename of the briefing movie.\n\t\t*/\n\t\tVQType BriefMovie;\n\n\t\t/*\n\t\t**\tThe filename of the movie to play if the scenario is won.\n\t\t*/\n\t\tVQType WinMovie;\n\n\t\t/*\n\t\t**\tThe filename of the movie to play if the scenario is lost.\n\t\t*/\n\t\tVQType LoseMovie;\n\n\t\t/*\n\t\t**\tThe filename of the movie to play right after the briefing and\n\t\t**\tjust before the game.\n\t\t*/\n\t\tVQType ActionMovie;\n\n\t\t/*\n\t\t**\tThis is the full text of the briefing. This text will be\n\t\t**\tdisplayed when the player commands the \"restate mission\n\t\t**\tobjectives\" operation.\n\t\t*/\n\t\tchar BriefingText[1024];\n\n\t\t/*\n\t\t**\tThis is the theme to start playing at the beginning of the action\n\t\t**\tmovie. A score started in this fashion will continue to play as\n\t\t**\tthe game progresses.\n\t\t*/\n\t\tThemeType TransitTheme;\n\n\t\t/*\n\t\t**\tThe house that the player is to be (obsolete).\n\t\t*/\n\t\tHousesType PlayerHouse;\n\n\t\t/*\n\t\t**\tThe percentage of money that is allowed to be carried over into the\n\t\t**\tfollowing scenario.\n\t\t*/\n\t\tfixed CarryOverPercent;\n\n\t\t/*\n\t\t**\tThis is the amount of money that was left over in the previous\n\t\t**\tscenario.\n\t\t*/\n\t\tint CarryOverMoney;\n\n\t\t/*\n\t\t**\tThis specifies the maximum amount of money that is allowed to be\n\t\t**\tcarried over from the previous scenario. This limits the amount\n\t\t**\tregardless of what the carry over percentage is set to.\n\t\t*/\n\t\tint CarryOverCap;\n\n\t\t/*\n\t\t**\tThis is the percent that the computer controlled base is to be\n\t\t**\tbuilt up to at the scenario start.\n\t\t*/\n\t\tint Percent;\n\n\t\t/*\n\t\t**\tGlobal flags that are used in the trigger system and are persistent\n\t\t**\tover the course of the game.\n\t\t*/\n\t\tbool GlobalFlags[30];\n\n\t\t/*\n\t\t**\tThis records the bookmark view locations the player has recorded.\n\t\t*/\n\t\tCELL Views[4];\n\n\t\t/*\n\t\t**\tThis is the number of active passable bridges in the current game.\n\t\t*/\n\t\tint BridgeCount;\n\n\t\t/*\n\t\t**\tThis records the carry over timer value that is used when the mission\n\t\t**\tstarts (presuming the appropriate flag is set) and also used when the\n\t\t**\tscenario restarts.\n\t\t*/\n\t\tint CarryOverTimer;\n\n\t\t/*\n\t\t**\tIf a bridge has been destroyed, then this flag will be set to true.\n\t\t**\tIf there is a trigger that depends on this, it might be triggered.\n\t\t*/\n\t\tunsigned IsBridgeChanged:1;\n\n\t\t/*\n\t\t**\tIf a global has changed and global change trigger events must be\n\t\t**\tprocessed, then this flag will be set to true.\n\t\t*/\n\t\tunsigned IsGlobalChanged:1;\n\n\t\t/*\n\t\t**\tAre the buildings and units in this scenario to carry over into\n\t\t**\tsome (unspecified) later scenario and thus have to be recorded\n\t\t**\tat the end?\n\t\t*/\n\t\tunsigned IsToCarryOver:1;\n\n\t\t/*\n\t\t**\tIs this scenario to begin by taking the previously recorded\n\t\t**\tcarryover objects and creating them onto the map?\n\t\t*/\n\t\tunsigned IsToInherit:1;\n\n\t\t/*\n\t\t**\tIf Tanya or a civilian is to be automatically evacuated when they enter\n\t\t**\ta transport vehicle, then this flag will be true.\n\t\t*/\n\t\tunsigned IsTanyaEvac:1;\n\n\t\t/*\n\t\t** These variables are assigned to the chronosphere effect, and control\n\t\t** whether the palette should be fading towards b&w or towards color.\n\t\t*/\n\t\tunsigned IsFadingBW:1;\n\t\tunsigned IsFadingColor:1;\n\n\t\t/*\n\t\t**\tIf this scenario is to be the last mission of the game (for this side), then\n\t\t**\tthis flag will be true.\n\t\t*/\n\t\tunsigned IsEndOfGame:1;\n\n\t\t/*\n\t\t**\tIf the mission countdown timer is to be inherited from the previous\n\t\t**\tscenario, then this flag will be set to true.\n\t\t*/\n\t\tunsigned IsInheritTimer:1;\n\n\t\t/*\n\t\t**\tIf the spy plane is to be disabled in this scenario even though circumstances\n\t\t**\tmight otherwise indicate that it should appear, then this flag will be true.\n\t\t*/\n\t\tunsigned IsNoSpyPlane:1;\n\n\t\t/*\n\t\t**\tIf the score screen (and \"mission accomplished\" voice) is to be skipped when\n\t\t**\tthis scenario is finished, then this flag will be true.\n\t\t*/\n\t\tunsigned IsSkipScore:1;\n\n\t\t/*\n\t\t**\tIf this is to be a one time only mission such that when it is completed, the game\n\t\t**\twill return to the main menu, then this flag will be set to true.\n\t\t*/\n\t\tunsigned IsOneTimeOnly:1;\n\n\t\t/*\n\t\t**\tIf the map selection is to be skipped then this flag will be true. If this\n\t\t**\tins't a one time only scenario, then the next scenario will have the same\n\t\t**\tname as the current one but will be for variation \"B\".\n\t\t*/\n\t\tunsigned IsNoMapSel:1;\n\n\t\t/*\n\t\t**\tIf trucks are supposed to drop wood crates when they explode, then this flag\n\t\t**\twill be set to true.\n\t\t*/\n\t\tunsigned IsTruckCrate:1;\n\n\t\t/*\n\t\t**\tIf the initial money is to be assigned as ore in available silos, then\n\t\t**\tthis flag will be set to true.\n\t\t*/\n\t\tunsigned IsMoneyTiberium:1;\n\n\t\t/*\n\t\t**\tThis is the fading countdown timer.  As this timer counts down, the\n\t\t**\tfading to b&w or color will progress.  This timer represents a\n\t\t** percentage of the Options.Get_Saturation() to fade towards.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> FadeTimer;\n\n#ifdef FIXIT_VERSION_3\t\t\t//\tFor endgame auto-sonar pulse.\n\t\t//\tTimer to set the period for checking if an auto-sonar pulse should be performed.\n\t\t//\tThis will take place if a player has nothing but subs left in the game.\n\t\tCDTimerClass<FrameTimerClass> AutoSonarTimer;\n#endif\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\tbool\tbLocalProposesDraw;\t\t\t\t//\tTrue if the local player in a 2-player game has a draw offer extended.\n\t\tbool\tbOtherProposesDraw;\t\t\t\t//\tTrue if the other player in a 2-player game has a draw offer extended.\n#endif\n\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/SCORE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /counterstrike/SCORE.CPP 3     3/14/97 12:02a Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SCORE.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 19, 1994                                               *\n *                                                                                             *\n *                  Last Update : May 3, 1995   [BWG]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Call_Back_Delay -- Combines Call_Back() and Delay() functions                             *\n *   Draw_Bar_Graphs -- Draw \"Casualties\" bar graphs                                           *\n *   Draw_InfantryMan -- Draw one guy in score screen, update animation                        *\n *   Draw_Infantrymen -- Draw all the guys on the score screen                                 *\n *   New_Infantry_Anim -- Start up a new animation for one of the infantrymen                  *\n *   ScoreClass::Count_Up_Print -- Prints a number (up to its max) into a string, cleanly      *\n *   ScoreClass::DO_GDI_GRAPH -- Show # of people or buildings killed on GDI score screen      *\n *   ScoreClass::Delay -- Pauses waiting for keypress.                                         *\n *   ScoreClass::Presentation -- Main routine to display score screen.                         *\n *   ScoreClass::Print_Graph_Title -- Prints title on score screen.                            *\n *   ScoreClass::Print_Minutes -- Print out hours/minutes up to max                            *\n *   ScoreClass::Pulse_Bar_Graph -- Pulses the bargraph color.                                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WIN32\nextern short StreamLowImpact;\n#endif\n\n#include\t\"function.h\"\n\n#define SCORETEXT_X\t\t184\n#define SCORETEXT_Y\t\t8\n#define CASUALTY_Y\t\t88\n#define BUILDING_X\t\t256\n#define BUILDING_Y\t\t128\n#define BARGRAPH_X\t\t266\n#define MAX_BAR_X\t\t\t318\t\t// max possible is 319 because of bar's right shadow\n#define SIZEGBAR\t\t\t118\n#define HALLFAME_X\t\t11\n#define HALLFAME_Y\t\t120\n\n#define\tMULTISCOREX\t\t30\n\n#define TEDIT_FAME\t\t\t\t1\n#define NUMINFANTRYMEN\t\t\t10\n#define NUMFAMENAMES\t\t\t\t7\n#define MAX_FAMENAME_LENGTH\t11\n\n#ifndef WIN32\nextern short StreamLowImpact;\n#endif  //WIN32\n\nGraphicBufferClass *PseudoSeenBuff;\n\nstruct InfantryAnim {\n\tint xpos;\n\tint ypos;\n\tvoid const *shapefile;\n\tvoid const *remap;\n\tint anim;\n\tint stage;\n\tchar delay;\n\tInfantryTypeClass const *Class;\n} InfantryMan[NUMINFANTRYMEN];\nvoid Draw_InfantryMen(void);\nvoid Draw_InfantryMan(int index);\nvoid New_Infantry_Anim(int index, int anim);\nvoid Draw_Bar_Graphs(int i, int gkilled, int nkilled);\nvoid Animate_Cursor(int pos, int ypos);\nvoid Animate_Score_Objs(void);\nvoid Cycle_Wait_Click(bool cycle=true);\n\n#ifdef FIXIT_SCORE_CRASH\nvoid Disable_Uncompressed_Shapes (void);\nvoid Enable_Uncompressed_Shapes (void);\n#endif\t//FIXIT\n\nvoid const * Beepy6;\nint ControlQ;\t// cheat key to skip past score/mapsel screens\nbool StillUpdating;\n\n#ifdef WIN32\nchar *ScreenNames[2]={\"ALIBACKH.PCX\", \"SOVBACKH.PCX\"};\n#else\nchar *ScreenNames[2]={\"ALI-TRAN.WSA\", \"SOV-TRAN.WSA\"};\n#endif\n\n//#ifdef WIN32\n//TextBlitClass BlitList;\n//#endif\n\n\nstruct Fame {\n\tchar\tname[MAX_FAMENAME_LENGTH];\n\tint\tscore;\n\tint\tlevel;\n\tint\tside;\n};\n\nScoreAnimClass *ScoreObjs[MAXSCOREOBJS];\n\n\nScoreAnimClass::ScoreAnimClass(int x, int y, void const * data)\n{\n\tXPos = x * RESFACTOR;\n\tYPos = y * RESFACTOR;\n\tTimer = 0;\n\tDataPtr = data;\n}\n\n\nScoreTimeClass::ScoreTimeClass(int xpos, int ypos, void const * data, int maxval, int xtimer) :\n\tScoreAnimClass(xpos, ypos, data)\n{\n\tStage = 0;\n\tMaxStage = maxval;\n\tTimerReset = xtimer;\n}\n\nvoid ScoreTimeClass::Update(void)\n{\n#ifdef WIN32\n\tGraphicViewPortClass *oldpage;\n#else\n\tGraphicBufferClass *oldpage;\n#endif\n\tif (!Timer) {\n\t\tTimer = TimerReset;\n\t\tif (++Stage >= MaxStage) Stage = 0;\n\t\toldpage = LogicPage;\n\t\tSet_Logic_Page(SeenBuff);\n\t\tCC_Draw_Shape(DataPtr, Stage, XPos, YPos, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n#ifdef WIN32\n\t\tSet_Logic_Page(*PseudoSeenBuff);\n\t\tCC_Draw_Shape(DataPtr, Stage, XPos, YPos, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n#endif\n\t\tSet_Logic_Page(oldpage);\n\t}\n}\n\nScoreCredsClass::ScoreCredsClass(int xpos, int ypos, void const * data, int maxval, int xtimer) :\n\tScoreAnimClass(xpos, ypos, data)\n{\n\tStage = 0;\n\tMaxStage = maxval;\n\tTimerReset = xtimer;\n\tClock1 = MFCD::Retrieve(\"CLOCK1.AUD\");\n\tCashTurn = MFCD::Retrieve(\"CASHTURN.AUD\");\n}\n\n\nvoid ScoreCredsClass::Update(void)\n{\n#ifdef WIN32\n\tGraphicViewPortClass *oldpage;\n#else\n\tGraphicBufferClass *oldpage;\n#endif\n\tif (!Timer) {\n\t\tTimer = TimerReset;\n\t\tif (++Stage >= MaxStage) Stage = 0;\n\t\toldpage = LogicPage;\n\t\tSet_Logic_Page(SeenBuff);\n#ifdef WIN32\n\t\tPlay_Sample(Clock1, 255, Options.Normalize_Volume(130));\n#else\n\t\tPlay_Sample(Clock1, 255, Options.Normalize_Volume(50));\n#endif\n\t\tCC_Draw_Shape(DataPtr, Stage, XPos, YPos, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n#ifdef WIN32\n\t\tSet_Logic_Page(*PseudoSeenBuff);\n\t\tCC_Draw_Shape(DataPtr, Stage, XPos, YPos, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n#endif\n\t\tSet_Logic_Page(oldpage);\n\t}\n}\n\n\nScorePrintClass::ScorePrintClass(int string, int xpos, int ypos, void const * palette, int background) :\n\tScoreAnimClass(xpos, ypos, Text_String(string))\n{\n\tBackground = background;\n\tPrimaryPalette = palette;\n\tStage = 0;\n}\n\n\nScorePrintClass::ScorePrintClass(void const * string, int xpos, int ypos, void const * palette, int background) :\n\tScoreAnimClass(xpos, ypos, string)\n{\n\tBackground = background;\n\tPrimaryPalette = palette;\n\tStage = 0;\n}\n\n\nvoid ScorePrintClass::Update(void)\n{\n\tstatic char localstr[2]={0,0};\n\tstatic char _whitepal[]={0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F};\n\n\tif (Stage && (((char *)DataPtr)[Stage-1]==0) ) {\n\t\tfor (int i = 0; i < MAXSCOREOBJS; i++) {\n\t\t\tif (ScoreObjs[i] == this) {\n\t\t\t\tScoreObjs[i] = 0;\n\t\t\t}\n\t\t}\n\t\tdelete this;\n\t\treturn;\n\t}\n\n#ifdef WIN32\n\tStillUpdating = true;\n#endif\n\tif (!Timer) {\n\t\tTimer = 1;\n\n\t\tint pos = XPos+(Stage*(6*RESFACTOR));\n// print the letter properly\n\t\tif (Stage) {\n\t\t\tSet_Font_Palette(PrimaryPalette);\n\t\t\tlocalstr[0]=((char *)DataPtr)[Stage-1];\n\t\t\tHidPage.Print(localstr, pos-6*RESFACTOR, YPos,   TBLACK, TBLACK);\n\t\t\tHidPage.Blit(SeenPage, pos-6*RESFACTOR, YPos-1*RESFACTOR, pos-6*RESFACTOR, YPos-1*RESFACTOR, 7*RESFACTOR, 8*RESFACTOR);\n#ifdef WIN32\n\t\t\tHidPage.Blit(*PseudoSeenBuff, pos-6*RESFACTOR, YPos-1*RESFACTOR, pos-6*RESFACTOR, YPos-1*RESFACTOR, 7*RESFACTOR, 8*RESFACTOR);\n\t\t\tPseudoSeenBuff->Print(localstr, pos-6*RESFACTOR, YPos,   TBLACK, TBLACK);\n#endif\n\t\t}\n\t\tif (((char *)DataPtr)[Stage]) {\n\t\t\tlocalstr[0]=((char *)DataPtr)[Stage];\n\t\t\tSet_Font_Palette(_whitepal);\n\t\t\tSeenPage.Print(localstr, pos,  YPos-1, TBLACK, TBLACK);\n\t\t\tSeenPage.Print(localstr, pos,  YPos+1, TBLACK, TBLACK);\n\t\t\tSeenPage.Print(localstr, pos+1, YPos  , TBLACK, TBLACK);\n#ifdef WIN32\n\t\t\tPseudoSeenBuff->Print(localstr, pos,  YPos-1, TBLACK, TBLACK);\n\t\t\tPseudoSeenBuff->Print(localstr, pos,  YPos+1, TBLACK, TBLACK);\n\t\t\tPseudoSeenBuff->Print(localstr, pos+1, YPos  , TBLACK, TBLACK);\n#endif\n\t\t}\n\t\tStage++;\n\t}\n}\n\n\nScoreScaleClass::ScoreScaleClass(void const * string, int xpos, int ypos, char const palette[]) :\n\tScoreAnimClass(xpos, ypos, string)\n{\n\tPalette = &palette[0];\n#ifdef WIN32\n\tStage = 0;\n#else\n\tStage = 5;\n#endif\n}\n\n\nvoid ScoreScaleClass::Update(void)\n{\n\tstatic int _destx[]={0,80,107,134,180,228};\n\tstatic int _destw[]={6,20, 30, 40, 60, 80};\n\n\t/*\n\t** Restore the background for the scaled-up letter\n\t*/\n\tif (!Timer) {\n\t\tTimer = 1;\n#ifndef WIN32\n\t\tif (Stage != 5) {\n\t\t\tint destx = _destx[Stage+1]*RESFACTOR;\n\t\t\tint destw = _destw[Stage+1]*RESFACTOR;\n\t\t\tHidPage.Blit(SeenPage, destx, YPos, destx, YPos, (destx + destw) <= 320 * RESFACTOR ? destw : (320 * RESFACTOR) - destx, (YPos + destw) <= 200 * RESFACTOR ? destw : (200 * RESFACTOR) - YPos);\n\t\t}\n#endif\n\t\tif (Stage) {\n\t\t\tSet_Font_Palette(Palette);\n\t\t\tHidPage.Fill_Rect(0, 0, 7*RESFACTOR, 7*RESFACTOR, TBLACK);\n\t\t\tHidPage.Print((char *)DataPtr, 0, 0,   TBLACK, TBLACK);\n\t\t\tHidPage.Scale(SeenPage, 0, 0, _destx[Stage]*RESFACTOR, YPos, 5*RESFACTOR, 6*RESFACTOR, _destw[Stage]*RESFACTOR, _destw[Stage]*RESFACTOR, true);\n\t\t\tStage--;\n\t\t} else {\n\t\t\tSet_Font_Palette(Palette);\n\t\t\tfor (int i = 0; i < MAXSCOREOBJS; i++) {\n\t\t\t\tif (ScoreObjs[i]==this) ScoreObjs[i] = 0;\n\t\t\t}\n\t\t\tHidPage.Print((char *)DataPtr, XPos, YPos,   TBLACK, TBLACK);\n\t\t\tHidPage.Blit(SeenPage, XPos, YPos, XPos, YPos, 6*RESFACTOR, 6*RESFACTOR);\n#ifdef WIN32\n\t\t\tHidPage.Blit(*PseudoSeenBuff, XPos, YPos, XPos, YPos, 6*RESFACTOR, 6*RESFACTOR);\n#endif\n\t\t\tdelete this;\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nint Alloc_Object(ScoreAnimClass *obj)\n{\n\tint i,ret;\n\n\tfor (i = ret = 0; i < MAXSCOREOBJS; i++) {\n\t\tif (!ScoreObjs[i]) {\n\t\t\tScoreObjs[i] = obj;\n\t\t\tret = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn(ret);\n}\n\n\n\n/***********************************************************************************************\n * ScoreClass::Presentation -- Main routine to display score screen.                           *\n *                                                                                             *\n *    This is the main routine that displays the score screen graphics.                        *\n *    It gets called at the end of each scenario and is used to present                        *\n *    the results and a rating of the player's battle.                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/02/1994     : Created.                                                                 *\n *=============================================================================================*/\nstatic char const  _bluepal[]={0xC0,0xC1,0xC1,0xC3,0xC2,0xC5,0xC3,0xC7,0xC4,0xC9,0xCA,0xCB,0xCC,0xCD,0xC0,0xCF};\nstatic char const _greenpal[]={0x70,0x71,0x7C,0x73,0x7D,0x75,0x7E,0x77,0x7F,0x79,0x7A,0x7B,0x7C,0x7D,0x7C,0x7F};\nstatic char const   _redpal[]={0xD0,0xD1,0xD7,0xD3,0xD9,0xD5,0xDA,0xD7,0xDB,0xD9,0xDA,0xDB,0xDC,0xDD,0xD6,0xDF};\nstatic char const _yellowpal[]={0x0,0x0,0xEC,0x0,0xEB,0x0,0xEA,0x0,0xE9,0x0,0x0,0x0,0x0,0x0,0xED,0x0};\nvoid ScoreClass::Presentation(void)\n{\n#ifdef WIN32\n//\tif (Keyboard != NULL) return;\n#endif\n\tstatic int const _casuax[2]={144,150};\n\tstatic int const _casuay[2]={ 78, 78};\n\tstatic int const _gditxy[2]={ 90, 90};\n\n#if defined(FRENCH) || defined(GERMAN)\n\tstatic int const _gditxx[2]={130,150};\n\tstatic int const _nodtxx[2]={130,150};\n#else\n\tstatic int const _gditxx[2]={135,150};\n\tstatic int const _nodtxx[2]={135,150};\n#endif\n\tstatic int const _nodtxy[2]={102,102};\n\tstatic int const _bldggy[2]={138,138};\n\tstatic int const _bldgny[2]={150,150};\n\n#ifdef WIN32\n#ifdef FIXIT_SCORE_CRASH\n\t/*\n\t** Fix for the score screen crash due to uncompressed shape buffer overflow.\n\t*/\n\tDisable_Uncompressed_Shapes();\n#endif\t//FIXIT\n\tPseudoSeenBuff = new GraphicBufferClass(SeenBuff.Get_Width(),SeenBuff.Get_Height(),(void*)NULL);\n#endif\n\tint i;\n\tvoid const * yellowptr;\n\tvoid const * redptr;\n\tCCFileClass file(FAME_FILE_NAME);\n\tstruct Fame hallfame[NUMFAMENAMES];\n\tvoid *oldfont;\n\tint oldfontxspacing = FontXSpacing;\n\tint house = (PlayerPtr->Class->House == HOUSE_USSR || PlayerPtr->Class->House == HOUSE_UKRAINE);\t\t// 0 or 1\n#ifdef WIN32\n\tchar inter_pal[15];\n\tsprintf(inter_pal, \"SCORPAL1.PAL\");\n#endif\n\n\tControlQ = 0;\n\tFontXSpacing = 0;\n\tMap.Override_Mouse_Shape(MOUSE_NORMAL);\n\tTheme.Queue_Song(THEME_SCORE);\n\n#ifdef WIN32\n\tVisiblePage.Clear();\n\tSysMemPage.Clear();\n\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n\tHiddenPage.Clear();\n\tSet_Logic_Page(SysMemPage);\n#else\n\tSeenPage.Clear();\n\tHidPage.Clear();\n\tSet_Logic_Page(HidPage);\n#endif\n\tBlackPalette.Set();\n\n\n\tvoid const * country4 = MFCD::Retrieve(\"COUNTRY4.AUD\");\n\tvoid const * sfx4 = MFCD::Retrieve(\"SFX4.AUD\");\n\tBeepy6 = MFCD::Retrieve(\"BEEPY6.AUD\");\n\n\t/*\n\t** Load the background for the score screen\n\t*/\n#ifndef WIN32\n\tvoid *anim = Open_Animation(ScreenNames[house], NULL, 0L, (WSAOpenType)(WSA_OPEN_FROM_MEM | WSA_OPEN_TO_PAGE), ScorePalette);\n#endif\n\n\tunsigned minutes = (unsigned)((ElapsedTime / (long)TIMER_MINUTE))+1;\n\n// Load up the shapes for the Nod score screen\n#ifdef WIN32\n\tyellowptr = MFCD::Retrieve(\"BAR3BHR.SHP\");\n\tredptr = MFCD::Retrieve(\"BAR3RHR.SHP\");\n#else\n\tif (!house) {\n\t\tyellowptr = MFCD::Retrieve(\"BAR3BLU.SHP\");\n\t\tredptr = MFCD::Retrieve(\"BAR3RED.SHP\");\n\t}\n#endif\n\n/* Change to the six-point font for Text_Print */\n\toldfont = Set_Font(ScoreFontPtr);\n\tCall_Back();\n\n/* --- Now display the background animation --- */\n\tHide_Mouse();\n#ifdef WIN32\n\tLoad_Title_Screen(ScreenNames[house], &HidPage, ScorePalette);\n\tIncrease_Palette_Luminance (ScorePalette , 30, 30, 30, 63);\n\tHidPage.Blit(SeenPage);\n\tHidPage.Blit(*PseudoSeenBuff);\n#else\n\tAnimate_Frame(anim, HidPage, 1);\n\tHidPage.Blit(SeenPage);\n#endif\n\tScorePalette.Set(FADE_PALETTE_FAST, Call_Back);\n#ifdef WIN32\n\tPlay_Sample(country4, 255, Options.Normalize_Volume(150));\n#else\n\tPlay_Sample(country4, 255, Options.Normalize_Volume(60));\n#endif\n\n#ifndef WIN32\n\tint frame = 1;\n\tStreamLowImpact = true;\n\twhile (frame < Get_Animation_Frame_Count(anim)) {\n\t\tAnimate_Frame(anim, SeenPage, frame++);\n\t\tCall_Back_Delay(2);\n\t}\n\tStreamLowImpact = false;\n\tCall_Back();\n\tClose_Animation(anim);\n#endif\n\n\t/*\n\t** Background's up, so now load various shapes and animations\n\t*/\n#ifdef WIN32\n\tvoid const * timeshape = \t  MFCD::Retrieve(\"TIMEHR.SHP\");\n\tvoid const * hiscore1shape = MFCD::Retrieve(\"HISC1-HR.SHP\");\n\tvoid const * hiscore2shape = MFCD::Retrieve(\"HISC2-HR.SHP\");\n#else\n\tvoid const * timeshape = \t  MFCD::Retrieve(\"TIME.SHP\");\n\tvoid const * hiscore1shape = MFCD::Retrieve(\"HISCORE1.SHP\");\n\tvoid const * hiscore2shape = MFCD::Retrieve(\"HISCORE2.SHP\");\n#endif\n\tScoreObjs[0] = new ScoreTimeClass(238, 2, timeshape, 30, 4);\n\tScoreObjs[1] = new ScoreTimeClass(4, 89, hiscore1shape, 10, 4);\n\tScoreObjs[2] = new ScoreTimeClass(4, 180, hiscore2shape, 10, 4);\n\n\t/* Now display the stuff */\n#ifdef WIN32\n#else\n\tSeenPage.Blit(HidPage);\n#endif\n\tSet_Logic_Page(SeenBuff);\n\n\n#ifdef FRENCH\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_TIME, 198,  9, _greenpal));\n#else\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_TIME, 204,  9, _greenpal));\n#endif\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_LEAD, 164, 26, _greenpal));\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_EFFI, 164, 38, _greenpal));\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_TOTA, 164, 50, _greenpal));\n#ifdef WIN32\n\tPlay_Sample(sfx4, 255, Options.Normalize_Volume(150));\n#else\n\tPlay_Sample(sfx4, 255, Options.Normalize_Volume(60));\n#endif\n\tCall_Back_Delay(13);\n\n\tint scorecounter = 0;\n\n\tKeyboard->Clear();\n\n\t/*\n\t**\tDetermine leadership rating.\n\t*/\n\tint leadership = 0;\n\tfor (int index = 0; index < Logic.Count(); index++) {\n\t\tObjectClass * object = Logic[index];\n\t\tHousesType owner = object->Owner();\n\t\tif ( (house) && (owner == HOUSE_USSR || owner == HOUSE_BAD || owner == HOUSE_UKRAINE) ) {\n\t\t\tleadership++;\n\t\t} else {\n\t\t\tif ( (!house) && (object->Owner() == HOUSE_GREECE) ) {\n\t\t\t\tleadership++;\n\t\t\t}\n\t\t}\n\t}\n\tint uspoints = 0;\n\n\tfor (HousesType hous = HOUSE_SPAIN; hous <= HOUSE_BAD; hous++) {\n\t\tHouseClass *hows = HouseClass::As_Pointer(hous);\n\t\tif (hous == HOUSE_USSR || hous == HOUSE_BAD || hous == HOUSE_UKRAINE) {\n\t\t\tNKilled += hows->UnitsLost;\n\t\t\tNBKilled += hows->BuildingsLost;\n\t\t} else {\n\t\t\tGKilled += hows->UnitsLost;\n\t\t\tGBKilled += hows->BuildingsLost;\n\t\t}\n\t\tif (PlayerPtr->Is_Ally(hous) ) {\n\t\t\tuspoints += hows->PointTotal;\n\t\t}\n\t}\n//\tif(uspoints < 0) uspoints = 0;\n//\tuspoints += 1000; //BG 1000 bonus points for winning mission\n\n\t/*\n\t**\tBias the base score upward according to the difficulty level.\n\t*/\n\tswitch (PlayerPtr->Difficulty) {\n\t\tcase DIFF_EASY:\n\t\t\tuspoints += 500;\n\t\t\tbreak;\n\n\t\tcase DIFF_NORMAL:\n\t\t\tuspoints += 1500;\n\t\t\tbreak;\n\n\t\tcase DIFF_HARD:\n\t\t\tuspoints += 3500;\n\t\t\tbreak;\n\t}\n\n\n\tif (!leadership) leadership++;\n\tleadership = 100*fixed(leadership, (house ? NKilled+NBKilled+leadership : GKilled+GBKilled+leadership));\n\tleadership = min(150,leadership);\n\n\t/*\n\t**\tDetermine economy rating.\n\t*/\n\tint init = PlayerPtr->Control.InitialCredits;\n\tint cred = PlayerPtr->Available_Money();\n\n\tint economy = 100*fixed((unsigned)PlayerPtr->Available_Money()+1+PlayerPtr->StolenBuildingsCredits, PlayerPtr->HarvestedCredits + (unsigned)PlayerPtr->Control.InitialCredits+1);\n\teconomy=min(economy,150);\n\n\tint total = ((uspoints * leadership) / 100) + ((uspoints * economy) / 100);\n\tif (total < -9999) total = -9999;\n\ttotal = min(total, 99999);\n\nKeyboard->Clear();\n\tfor (i = 0; i <= 130; i++) {\n\t\tSet_Font_Palette(_greenpal);\n\t\tint lead = (leadership * i) / 100;\n\t\tCount_Up_Print(\"%3d%%\", lead, leadership,     244, 26);\n\t\tif (i>=30) {\n\t\t\tint econo = (economy * (i-30)) / 100;\n\t\t\tCount_Up_Print(\"%3d%%\", econo, economy, 244, 38);\n\t\t}\n\t\tPrint_Minutes(minutes);\n\t\tCall_Back_Delay(1);\n#ifdef WIN32\n\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(100));\n#else\n\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(40));\n#endif\n\t\tif ( (i >= 30) && (i >= leadership) && ((i-30) >= economy) ) break;\n//BG\t\tif (Keyboard->Check()) break;\n\t}\n\tCount_Up_Print(\"%3d%%\", leadership, leadership, 244, 26);\n\tCount_Up_Print(\"%3d%%\", economy,    economy,    244, 38);\n\n\tchar buffer[16];\n\tsprintf(buffer, \"x %5d\",uspoints);\n\tAlloc_Object(new ScorePrintClass(buffer, 274,  26, _greenpal));\n\tAlloc_Object(new ScorePrintClass(buffer, 274,  38, _greenpal));\n\tCall_Back_Delay(8);\n\tSeenBuff.Draw_Line(274*RESFACTOR, 48*RESFACTOR, 313*RESFACTOR, 48*RESFACTOR, WHITE);\n\tCall_Back_Delay(1);\n\tSeenBuff.Draw_Line(274*RESFACTOR, 48*RESFACTOR, 313*RESFACTOR, 48*RESFACTOR, GREEN);\n\n\tsprintf(buffer,\"%5d\", total);\n\tAlloc_Object(new ScorePrintClass(buffer, 286,  50, _greenpal));\n\n//BG\tif (!Keyboard->Check()) {\n\t\tCall_Back_Delay(60);\n//BG\t}\n\n\tif (house) Show_Credits(house, _greenpal);\n\n/*BG\tif (!Keyboard->Check()) */ Call_Back_Delay(60);\n\n\t/*\n\t** Show stats on # of units killed\n\t*/\n\tSet_Logic_Page(SeenBuff);\n#ifdef WIN32\n\tPlay_Sample(sfx4, 255, Options.Normalize_Volume(150));\n#else\n\tPlay_Sample(sfx4, 255, Options.Normalize_Volume(60));\n#endif\n\tint indx = house;\n#ifdef WIN32\n\tindx = 0;\n#endif\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_CASU, _casuax[indx], _casuay[indx], _greenpal));\n\tCall_Back_Delay(9);\n\tif (house) {\n\t\tAlloc_Object(new ScorePrintClass(TXT_SOVIET, _nodtxx[indx], _gditxy[indx], _redpal));\n\t\tAlloc_Object(new ScorePrintClass(TXT_ALLIES, _gditxx[indx], _nodtxy[indx], _bluepal));\n\t} else {\n\t\tAlloc_Object(new ScorePrintClass(TXT_ALLIES, _gditxx[indx], _gditxy[indx], _bluepal));\n\t\tAlloc_Object(new ScorePrintClass(TXT_SOVIET, _nodtxx[indx], _nodtxy[indx], _redpal));\n\t}\n\tCall_Back_Delay(6);\n\n\tSet_Font_Palette(_redpal);\n#ifdef WIN32\n\t\tDo_GDI_Graph(yellowptr, redptr, GKilled + CKilled, NKilled, 89);\n#else\n\tif (house) {\n\t\tDo_Nod_Casualties_Graph();\n\t} else {\n\t\tDo_GDI_Graph(yellowptr, redptr, GKilled + CKilled, NKilled, 89);\n\t}\n#endif\n\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t** Print out stats on buildings destroyed\n\t*/\n#ifdef WIN32\n\tPlay_Sample(sfx4, 255, Options.Normalize_Volume(150));\n#else\n\tPlay_Sample(sfx4, 255, Options.Normalize_Volume(60));\n#endif\n#ifdef WIN32\n\t\tAlloc_Object(new ScorePrintClass(TXT_SCORE_BUIL, 144, 126, _greenpal));\n\t\tCall_Back_Delay(9);\n#else\n\tif (!house) {\n\t\tAlloc_Object(new ScorePrintClass(TXT_SCORE_BUIL, 144, 126, _greenpal));\n\t\tCall_Back_Delay(9);\n\t} else {\n\t\tAlloc_Object(new ScorePrintClass(TXT_SCORE_BUIL1, 150, 118, _greenpal));\n\t\tAlloc_Object(new ScorePrintClass(TXT_SCORE_BUIL2, 150, 126, _greenpal));\n\t\tCall_Back_Delay(13);\n\t}\n#endif\n\tif(house) {\n\t\tAlloc_Object(new ScorePrintClass(TXT_SOVIET, _gditxx[indx], _bldggy[indx], _redpal));\n\t\tAlloc_Object(new ScorePrintClass(TXT_ALLIES, _gditxx[indx], _bldgny[indx], _bluepal));\n\t} else {\n\t\tAlloc_Object(new ScorePrintClass(TXT_ALLIES, _gditxx[indx], _bldggy[indx], _bluepal));\n\t\tAlloc_Object(new ScorePrintClass(TXT_SOVIET, _gditxx[indx], _bldgny[indx], _redpal));\n\t}\n\tCall_Back_Delay(7);\n#ifdef WIN32\n\t\tDo_GDI_Graph(yellowptr, redptr, GBKilled + CBKilled, NBKilled, 137);\n#else\n\tif (house) {\n\t\tCall_Back_Delay(6);\n\t\tSet_Font_Palette(_greenpal);\n\t\tDo_Nod_Buildings_Graph();\n\t} else {\n\t\tDo_GDI_Graph(yellowptr, redptr, GBKilled + CBKilled, NBKilled, 137);\n\t}\n#endif\n\n#ifdef WIN32\n\t// Wait for text printing to complete\n\twhile (StillUpdating) {\n\t\tCall_Back_Delay(1);\n\t}\n#endif\n\n\tKeyboard->Clear();\n\n\tif (!house) Show_Credits(house, _greenpal);\n\t/*\n\t** Hall of fame display and processing\n\t*/\n#ifdef WIN32\n\tPlay_Sample(sfx4, 255, Options.Normalize_Volume(150));\n#else\n\tPlay_Sample(sfx4, 255, Options.Normalize_Volume(60));\n#endif\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_TOP, 28, 110, _greenpal));\n\tCall_Back_Delay(9);\n\n\t/*\n\t** First check for the existence of the file, and if there isn't one,\n\t** make a new one filled with blanks.\n\t*/\n\tif (!file.Is_Available()) {\n\n\t\t// hall of fame doesn't exist, so blank it out & write it\n\t\tfile.Open(WRITE);\n\n\t\tfor (i = 0; i < NUMFAMENAMES; i++) {\n\t\t\thallfame[i].name[0] =\n\t\t\thallfame[i].score   =\n\t\t\thallfame[i].level   = 0;\n\t\t\thallfame[i].side\t  = 0;\n\t\t\tfile.Write(&hallfame[i], sizeof(struct Fame));\n\t\t}\n\n\t\tfile.Close();\n\t}\n\n\tfile.Open(READ);\n\tfor (i = 0; i < NUMFAMENAMES; i++) {\n\t\tfile.Read(&hallfame[i], sizeof(struct Fame));\n\t}\n\tfile.Close();\n\n\t/*\n\t** If the player's score is good enough to bump someone off the list,\n\t** remove their data, move everyone down a notch, and set index = where\n\t** their info goes\n\t*/\n\tif (hallfame[NUMFAMENAMES-1].score >= total)\n\t\t\t\t\t\t\t\thallfame[NUMFAMENAMES-1].score = 0;\n\tfor (index = 0; index < NUMFAMENAMES; index++) {\n\t\tif (total > hallfame[index].score) {\n\t\t\tif (index < (NUMFAMENAMES-1)) for (i = (NUMFAMENAMES-1); i > index; i--) hallfame[i] = hallfame[i-1];\n\t\t\thallfame[index].score = total;\n\t\t\thallfame[index].level = Scen.Scenario;\n\t\t\thallfame[index].name[0] = 0;\t// blank out the name\n\t\t\thallfame[index].side = house;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t** Now display the hall of fame\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n#ifdef WIN32\n\tchar maststr[NUMFAMENAMES*32];\n#endif\n\tchar const *pal;\n\tfor (i = 0; i < NUMFAMENAMES; i++) {\n\t\tpal = hallfame[i].side ? _redpal : _bluepal;\n\t\tAlloc_Object(new ScorePrintClass(hallfame[i].name, HALLFAME_X, HALLFAME_Y + (i*8), pal));\n\t\tif (hallfame[i].score) {\n#ifdef WIN32\n\t\t\tchar *str = maststr + i*32;\n#else\n\t\t\tchar *str = (char *)(HidPage.Get_Buffer()) + i*32;\n#endif\n\t\t\tsprintf(str, \"%d\", hallfame[i].score);\n\t\t\tAlloc_Object(new ScorePrintClass(str, HALLFAME_X+(6*14), HALLFAME_Y + (i*8), pal, BLACK));\n\t\t\tif (hallfame[i].level < 20) {\n\t\t\t\tsprintf(str+16, \"%d\", hallfame[i].level);\n\t\t\t} else {\n\t\t\t\tstrcpy(str+16, \"**\");\n\t\t\t}\n\t\t\tAlloc_Object(new ScorePrintClass(str+16, HALLFAME_X+(6*11), HALLFAME_Y + (i*8), pal, BLACK));\n\t\t\tCall_Back_Delay(13);\n\t\t}\n\t}\n#ifdef WIN32\n\t// Wait for text printing to complete\n\twhile (StillUpdating) {\n\t\tCall_Back_Delay(1);\n\t}\n#endif\n\t/*\n\t** If the player's on the hall of fame, have him enter his name now\n\t*/\n\tKeyboard->Clear();\n\n\tif (index < NUMFAMENAMES) {\n\t\tpal = hallfame[index].side ? _redpal : _bluepal;\n\t\tInput_Name(hallfame[index].name, HALLFAME_X, HALLFAME_Y + (index*8), pal);\n\n\t\tfile.Open(WRITE);\n\t\tfor (i = 0; i < NUMFAMENAMES; i++) {\n\t\t\tfile.Write(&hallfame[i], sizeof(struct Fame));\n\t\t}\n\t\tfile.Close();\n\t} else {\n\t\tAlloc_Object(new ScorePrintClass(TXT_CLICK_CONTINUE, 149, 190, _yellowpal));\n\t\tControlQ = false;\n\t\tCycle_Wait_Click();\n\t}\n\n\tKeyboard->Clear();\n\n/* get rid of all the animating objects */\n\tfor (i = 0; i < MAXSCOREOBJS; i++) if (ScoreObjs[i]) {\n\t\tdelete ScoreObjs[i];\n\t\tScoreObjs[i] = 0;\n\t}\n\tBlackPalette.Set(FADE_PALETTE_FAST, NULL);\n#ifdef WIN32\n\tVisiblePage.Clear();\n#else\n\tSeenPage.Clear();\n#endif\n\tShow_Mouse();\n//\tMap_Selection();\n//\tScen.ScenVar = SCEN_VAR_A;\n//\tScen.ScenDir = SCEN_DIR_EAST;\n\n\tTheme.Queue_Song(THEME_NONE);\n\n\tBlackPalette.Set(FADE_PALETTE_FAST, NULL);\n#ifdef WIN32\n\tVisiblePage.Clear();\n#else\n\tSeenPage.Clear();\n#endif\n\tGamePalette.Set();\n\n\tSet_Font(oldfont);\n\tFontXSpacing = oldfontxspacing;\n\tControlQ = 0;\n\n#ifdef WIN32\n\tdelete PseudoSeenBuff;\n#ifdef FIXIT_SCORE_CRASH\n\t/*\n\t** Fix for the score screen crash due to uncompressed shape buffer overflow.\n\t*/\n\tEnable_Uncompressed_Shapes();\n#endif\t//FIXIT\n\n#endif\n}\n\n\nvoid Cycle_Wait_Click(bool cycle)\n{\n\tint counter = 0;\n\tint minclicks = 20;\n\tunsigned long timingtime = TickCount;\n\tSerialPacketType sendpacket;\n\tSerialPacketType receivepacket;\n\tint packetlen;\n\n\n\tKeyboard->Clear();\n\twhile (minclicks || (!Keyboard->Check() && !ControlQ) ) {\n\n\t\tif (Session.Type == GAME_NULL_MODEM ||\n\t\t\tSession.Type == GAME_MODEM) {\n\n\t\t\t//\n\t\t\t// send a timing packet if enough time has gone by.\n\t\t\t//\n\t\t\tif ( (TickCount - timingtime) > PACKET_TIMING_TIMEOUT) {\n\t\t\t\tmemset (&sendpacket, 0, sizeof(SerialPacketType));\n\t\t\t\tsendpacket.Command = SERIAL_SCORE_SCREEN;\n\t\t\t\tsendpacket.ScenarioInfo.ResponseTime = NullModem.Response_Time();\n\t\t\t\tsendpacket.ID = Session.ModemType;\n\n\t\t\t\tNullModem.Send_Message (&sendpacket, sizeof(sendpacket), 0);\n\t\t\t\ttimingtime = TickCount;\n\t\t\t}\n\n\t\t\tif (NullModem.Get_Message (&receivepacket, &packetlen) > 0) {\n\t\t\t\t// throw packet away\n\t\t\t\tpacketlen = packetlen;\n\t\t\t}\n\n\t\t\tNullModem.Service();\n\t\t}\n\n\t\tCall_Back_Delay(1);\n\t\tif (minclicks) {\n\t\t\tminclicks--;\n\t\t\tKeyboard->Clear();\n\t\t}\n\n\t\tif(cycle) {\n\t\t\tcounter = ((++counter) & 7);\n\t\t\tif (counter == 0 && Options.IsPaletteScroll) {\n\t\t\t\tRGBClass rgb = ScorePalette[233];\n\t\t\t\tfor (int i = 233; i < 237; i++) {\n\t\t\t\t\tScorePalette[i] = ScorePalette[i+1];\n\t\t\t\t}\n\t\t\t\tScorePalette[237] = rgb;\n\t\t\t\tScorePalette.Set();\n\t\t\t}\n\t\t}\n\t}\n\tKeyboard->Clear();\n}\n\nvoid ScoreClass::Do_Nod_Buildings_Graph(void)\n{\n\tint shapenum;\n\tInfantryTypeClass const *ramboclass;\n\n\tvoid const * factptr   = MFCD::Retrieve(\"POWR.SHP\");\n\tvoid const * rmboptr   = MFCD::Retrieve(\"E7.SHP\");\n\tvoid const * fball1ptr = MFCD::Retrieve(\"FBALL1.SHP\");\n\tramboclass = &InfantryTypeClass::As_Reference(INFANTRY_TANYA);\n\n\t/*\n\t** Print the # of buildings on the hidpage so we only need to do it once\n\t*/\n\tSeenPage.Blit(HidPage);\n\tSet_Logic_Page(HidPage);\n\tCall_Back_Delay(30);\n\tSet_Font_Palette(_redpal);\n\tHidPage.Print( 0, BUILDING_X + 16, BUILDING_Y + 10, TBLACK, TBLACK);\n\tSet_Font_Palette(_bluepal);\n\tHidPage.Print( 0, BUILDING_X + 16, BUILDING_Y + 22, TBLACK, TBLACK);\n\n\t/*\n\t** Here's the animation/draw loop for blowing up the factory\n\t*/\n\tfor (int i=0; i<98; i++) {\n\t\tHidPage.Blit(HidPage, BUILDING_X, BUILDING_Y, 0, 0, 320-BUILDING_X, 48);\n\t\tshapenum = 0;\t// no damage\n\t\tif (i >= 60) {\n\t\t\tshapenum = Extract_Shape_Count(factptr) - 2;\t// some damage\n\t\t\tif (i == 60) {\n\t\t\t\tShake_The_Screen(6);\n\t\t\t\tSound_Effect(VOC_CRUMBLE);\n\t\t\t}\n\t\t\tif (i > 65) {\n\t\t\t\tshapenum = Extract_Shape_Count(factptr) - 1;\t// mega damage\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Draw the building before Rambo\n\t\t*/\n\t\tif (i < 68) {\n\t\t\tCC_Draw_Shape(factptr, shapenum, 0, 0, WINDOW_MAIN,\n\t\t\t\t\t  SHAPE_GHOST|SHAPE_FADING|SHAPE_WIN_REL, ColorRemaps[PCOLOR_GOLD].RemapTable, DisplayClass::UnitShadow);\n\n\t\t}\n\n\t\t/*\n\t\t** Now draw some fires, if appropriate\n\t\t*/\n\t\tif (i >= 61) {\n\t\t\tint firecount = Extract_Shape_Count(fball1ptr);\n\t\t\tint shapeindex = (i-61) / 2;\n\t\t\tif (shapeindex < firecount) {\n\t\t\t\tCC_Draw_Shape(fball1ptr, shapeindex, 10, 10, WINDOW_MAIN,\n\t\t\t\t\t\t  SHAPE_CENTER|SHAPE_WIN_REL);\n\t\t\t}\n\t\t\tif (i > 64) {\n\t\t\t\tshapeindex = (i-64) / 2;\n\t\t\t\tif (shapeindex < firecount) {\n\t\t\t\t\tCC_Draw_Shape(fball1ptr, shapeindex, 50, 30, WINDOW_MAIN,\n\t\t\t\t\t\t  SHAPE_CENTER|SHAPE_WIN_REL);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t/*\n\t\t** Draw the Tanya character running away from the building\n\t\t*/\n\t\tCC_Draw_Shape(rmboptr, (ramboclass->DoControls[DO_WALK].Frame + ramboclass->DoControls[DO_WALK].Jump*6) + ((unsigned(i)>>1)%ramboclass->DoControls[DO_WALK].Count),\n\t\t\t\t\t\t  i+32, 40, WINDOW_MAIN,\n\t\t\t\t\t\t  SHAPE_FADING|SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_GHOST,\n\t\t\t\t\t\t  ColorRemaps[PCOLOR_RED].RemapTable, DisplayClass::UnitShadow);\n\t\tHidPage.Blit(SeenPage, 0, 0, BUILDING_X, BUILDING_Y, 320-BUILDING_X, 48);\n/*BG\t\tif (!Keyboard->Check()) */ Call_Back_Delay(1);\n\t}\n\n\ti = max(GBKilled, NBKilled);\n\tfor (int q = 0; q <= i; q++) {\n\t\tSet_Font_Palette(_redpal);\n\t\tCount_Up_Print( \"%d\", q, NBKilled, BUILDING_X + 16, BUILDING_Y + 10);\n\t\tSet_Font_Palette(_bluepal);\n\t\tCount_Up_Print( \"%d\", q, GBKilled, BUILDING_X + 16, BUILDING_Y + 22);\n//BG\t\tif (!Keyboard->Check()) {\n#ifdef WIN32\n\t\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(150));\n#else\n\t\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(60));\n#endif\n\t\t\tCall_Back_Delay(1);\n//BG\t\t}\n\t}\n\tSet_Font_Palette(_redpal);\n\tCount_Up_Print( \"%d\", NBKilled, NBKilled, BUILDING_X + 16, BUILDING_Y + 10);\n\tSet_Font_Palette(_bluepal);\n\tCount_Up_Print( \"%d\", GBKilled, GBKilled, BUILDING_X + 16, BUILDING_Y + 22);\n}\n\n\n/***************************************************************************\n * DO_GDI_GRAPH -- Show # of people or buildings killed on GDI score screen*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:   yellowptr, redptr = pointers to shape file for graphs          *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1995 BWG : Created.                                             *\n *=========================================================================*/\n\nvoid ScoreClass::Do_GDI_Graph(void const * yellowptr, void const * redptr, int gkilled, int nkilled, int ypos)\n{\n\tint i, maxval;\n#ifdef WIN32\n\tint xpos = 174;\n\tint house = (PlayerPtr->Class->House == HOUSE_USSR || PlayerPtr->Class->House == HOUSE_UKRAINE);\t\t// 0 or 1\n\tif(house) {\n\t\tint temp = gkilled;\n\t\tgkilled = nkilled;\n\t\tnkilled = temp;\n\t\tvoid const *tempptr = yellowptr;\n\t\tyellowptr = redptr;\n\t\tredptr = tempptr;\n\t}\n#else\n\tint xpos = 173;\n#endif\n\tint gdikilled = gkilled, nodkilled=nkilled;\n\n\tmaxval = max(gdikilled, nodkilled);\n\tif (!maxval) maxval=1;\n\n\tgdikilled = (gdikilled * SIZEGBAR) / maxval;\n\tnodkilled = (nodkilled * SIZEGBAR) / maxval;\n\tif (maxval < 20) {\n\t\tgdikilled = gkilled * 5;\n\t\tnodkilled = nkilled * 5;\n\t}\n\n\tmaxval = max(gdikilled, nodkilled);\n\tif (!maxval) maxval=1;\n\n\t// Draw the white-flash shape on the hidpage\n\tSet_Logic_Page(HidPage);\n\tHidPage.Fill_Rect(0, 0, 124*RESFACTOR, 9*RESFACTOR, TBLACK);\n\tCC_Draw_Shape(redptr, 119, 0, 0, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n\tSet_Logic_Page(SeenBuff);\n#ifdef WIN32\n\tSet_Font_Palette(house ? _redpal : _bluepal);\n#else\n\tSet_Font_Palette(_bluepal);\n#endif\n\n\tfor (i = 1; i <= gdikilled; i++) {\n\t\tif (i != gdikilled) {\n#ifdef WIN32\n\t\t\tSet_Logic_Page(*PseudoSeenBuff);\n\t\t\tCC_Draw_Shape(yellowptr, i, xpos*RESFACTOR, ypos*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n\t\t\tSet_Logic_Page(SeenBuff);\n#endif\n\t\t\tCC_Draw_Shape(yellowptr, i, xpos*RESFACTOR, ypos*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n\t\t} else {\n\t\t\tHidPage.Blit(SeenPage, 0, 0, xpos*RESFACTOR, ypos*RESFACTOR, (3+gdikilled)*RESFACTOR, 8*RESFACTOR);\n#ifdef WIN32\n\t\t\tHidPage.Blit(*PseudoSeenBuff, 0, 0, xpos*RESFACTOR, ypos*RESFACTOR, (3+gdikilled)*RESFACTOR, 8*RESFACTOR);\n#endif\n\t\t}\n\n\t\tCount_Up_Print(\"%d\", (i*gkilled) / maxval, gkilled, 297, ypos+2);\n//BG\t\tif (!Keyboard->Check()) {\n#ifdef WIN32\n\t\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(150));\n#else\n\t\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(60));\n#endif\n\t\t\tCall_Back_Delay(2);\n//BG\t\t}\n\t}\n\tCC_Draw_Shape(yellowptr, gdikilled, xpos*RESFACTOR, ypos*RESFACTOR   , WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n#ifdef WIN32\n\tSet_Logic_Page(*PseudoSeenBuff);\n\tCC_Draw_Shape(yellowptr, gdikilled, xpos*RESFACTOR, ypos*RESFACTOR   , WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n\tSet_Logic_Page(SeenBuff);\n#endif\n\tCount_Up_Print(\"%d\", gkilled, gkilled, 297, ypos+ 2);\n/*BG\tif (!Keyboard->Check()) */ Call_Back_Delay(40);\n\n#ifdef WIN32\n\tSet_Font_Palette(house ? _bluepal : _redpal);\n#else\n\tSet_Font_Palette(_redpal);\n#endif\n\tfor (i = 1; i <= nodkilled; i++) {\n\t\tif (i != nodkilled) {\n#ifdef WIN32\n\t\t\tSet_Logic_Page(*PseudoSeenBuff);\n\t\t\tCC_Draw_Shape(redptr, i, xpos*RESFACTOR, (ypos+12)*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n\t\t\tSet_Logic_Page(SeenBuff);\n#endif\n\t\t\tCC_Draw_Shape(redptr, i, xpos*RESFACTOR, (ypos+12)*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n\t\t} else {\n\t\t\tHidPage.Blit(SeenPage, 0, 0, xpos*RESFACTOR, (ypos+12)*RESFACTOR, (3+nodkilled)*RESFACTOR, 8*RESFACTOR);\n#ifdef WIN32\n\t\t\tHidPage.Blit(*PseudoSeenBuff, 0, 0, xpos*RESFACTOR, (ypos+12)*RESFACTOR, (3+nodkilled)*RESFACTOR, 8*RESFACTOR);\n#endif\n\t\t}\n\n\t\tCount_Up_Print(\"%d\", (i*nkilled) / maxval, nkilled, 297, ypos+14);\n//BG\t\tif (!Keyboard->Check()) {\n#ifdef WIN32\n\t\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(150));\n#else\n\t\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(60));\n#endif\n\t\t\tCall_Back_Delay(2);\n//BG\t\t}\n\t}\n\n//\tif (Keyboard::Check()) Keyboard::Clear();\n\n\t/*\n\t** Make sure accurate count is printed at end\n\t*/\n#ifdef WIN32\n\tSet_Logic_Page(*PseudoSeenBuff);\n\tCC_Draw_Shape(   redptr, nodkilled, xpos*RESFACTOR, (ypos+12)*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n\tSet_Logic_Page(SeenBuff);\n#endif\n\tCC_Draw_Shape(   redptr, nodkilled, xpos*RESFACTOR, (ypos+12)*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n\tCount_Up_Print(\"%d\", nkilled, nkilled, 297, ypos+14);\n/*BG\tif (!Keyboard->Check()) */ Call_Back_Delay(40);\n}\n\n\nvoid ScoreClass::Do_Nod_Casualties_Graph(void)\n{\n\tint i, gdikilled, nodkilled, maxval;\n\n\tvoid const * e1ptr = MFCD::Retrieve(\"E1.SHP\");\n\n\tgdikilled = GKilled;\n\tnodkilled = NKilled;\n\tmaxval = max(gdikilled, nodkilled);\n\n\tif (!maxval) maxval=1;\n\tif ((gdikilled > (MAX_BAR_X - BARGRAPH_X)) || (nodkilled > (MAX_BAR_X - BARGRAPH_X)) ) {\n\t\tgdikilled = (gdikilled * (MAX_BAR_X - BARGRAPH_X)) / maxval;\n\t\tnodkilled = (nodkilled * (MAX_BAR_X - BARGRAPH_X)) / maxval;\n\t}\n\n\tmaxval = max(gdikilled, nodkilled);\n\tif (!maxval) maxval=1;\n\n\t/*\n\t** Initialize a bunch of objects for the infantrymen who pose for the bar\n\t** graphs of casualties.\n\t*/\n\tint r = NUMINFANTRYMEN/2;\n\tfor (i = 0; i < NUMINFANTRYMEN/2; i++) {\n\t\tInfantryMan[i+0].xpos =\n\t\tInfantryMan[i+r].xpos =  (i*10) + 7;\n\t\tInfantryMan[i+0].ypos = 11;\n\t\tInfantryMan[i+r].ypos = 21;\n\t\tInfantryMan[i+0].shapefile =\n\t\tInfantryMan[i+r].shapefile = e1ptr;\n\t\tInfantryMan[i+0].remap = ColorRemaps[PCOLOR_RED].RemapTable;\n\t\tInfantryMan[i+r].remap = ColorRemaps[PCOLOR_BLUE].RemapTable;\n\t\tInfantryMan[i+0].anim  =\n\t\tInfantryMan[i+r].anim  = 0;\n\t\tInfantryMan[i+0].stage =\n\t\tInfantryMan[i+r].stage = 0;\n\t\tInfantryMan[i+0].delay =\n\t\tInfantryMan[i+r].delay = NonCriticalRandomNumber & 0x1F;\n\t\tInfantryMan[i+0].Class =\n\t\tInfantryMan[i+r].Class = &InfantryTypeClass::As_Reference(INFANTRY_E1);\n\t}\n\n\t/*\n\t** Draw the infantrymen and pause briefly before running the graph\n\t*/\n\tDraw_InfantryMen();\n\tHidPage.Blit(SeenPage, 0, 0, BARGRAPH_X, CASUALTY_Y, 320-BARGRAPH_X, 34);\n\tCall_Back_Delay(40);\n\n\tfor (i = 1; i <= maxval; i++) {\n\t\t// Draw & update infantrymen 3 times for every tick on the graph (i)\n\t\tfor (int index = 0; index < 3; index++) {\n\t\t\tDraw_InfantryMen();\n\t\t\tDraw_Bar_Graphs(i, nodkilled, gdikilled);\n\t\t\tHidPage.Blit(SeenPage, 0, 0, BARGRAPH_X, CASUALTY_Y, 320-BARGRAPH_X, 34);\n\n\t\t\tSet_Font_Palette(_redpal);\n\t\t\tCount_Up_Print(\"%d\", (i*NKilled) / maxval, NKilled, SCORETEXT_X+64, CASUALTY_Y +  2);\n\t\t\tSet_Font_Palette(_bluepal);\n\t\t\tCount_Up_Print(\"%d\", (i*GKilled) / maxval, GKilled, SCORETEXT_X+64, CASUALTY_Y + 14);\n/*BG\t\t\tif (!Keyboard->Check()) */ Call_Back_Delay(3);\n\t\t}\n#ifdef WIN32\n\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(150));\n#else\n\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(60));\n#endif\n\t}\n//BG\tif (Keyboard->Check()) Keyboard->Clear();\n\n\t/*\n\t** Make sure accurate count is printed at end\n\t*/\n\tSet_Font_Palette(_redpal);\n\tCount_Up_Print(\"%d\", NKilled, NKilled, SCORETEXT_X+64, CASUALTY_Y +  2);\n\tSet_Font_Palette(_bluepal);\n\tCount_Up_Print(\"%d\", GKilled, GKilled, SCORETEXT_X+64, CASUALTY_Y + 14);\n\n\t/*\n\t** Finish up death animations, if there are any active\n\t*/\n\tint k = 1;\n\twhile (k) {\n\t\tfor (i=k=0; i<NUMINFANTRYMEN; i++) {\n\t\t\tif (InfantryMan[i].anim >= DO_GUN_DEATH) {\n\t\t\t\tk=1;\n\t\t\t}\n\t\t}\n\t\tif (k) {\n\t\t\tDraw_InfantryMen();\n\t\t}\n\t\tDraw_Bar_Graphs(maxval, nodkilled, gdikilled);\n\t\tHidPage.Blit(SeenPage, 0, 0, BARGRAPH_X, CASUALTY_Y, 320-BARGRAPH_X, 34);\n\t\tCall_Back_Delay(1);\n\t}\n}\n\n\nvoid ScoreClass::Show_Credits(int house, char const pal[])\n{\n\tstatic int _credsx[2]={276,276};\n\tstatic int _credsy[2]={173,58};\n\tstatic int _credpx[2]={228,236};\n#ifdef GERMAN\n\tstatic int _credpy[2]={181, 74};\n\tstatic int _credtx[2]={162,162};\n\tstatic int _credty[2]={173, 62};\n#else\n\tstatic int _credpy[2]={189-12, 74};\n\tstatic int _credtx[2]={182,182};\n\tstatic int _credty[2]={179-12, 62};\n#endif\n\n\tint credobj,i;\n\tint minval,add;\n\n#ifdef WIN32\n\tvoid const * credshape = MFCD::Retrieve(house ? \"CREDSUHR.SHP\" : \"CREDSAHR.SHP\");\n#else\n\tvoid const * credshape = MFCD::Retrieve(house ? \"CREDSU.SHP\" : \"CREDSA.SHP\");\n#endif\n\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_ENDCRED, _credtx[house], _credty[house], pal));\n\tCall_Back_Delay(15);\n\n\tcredobj = Alloc_Object(new ScoreCredsClass(_credsx[house], _credsy[house], credshape, 32, 2));\n\tminval = PlayerPtr->Available_Money() / 100;\n\n\t/*\n\t** Print out total credits left at end of scenario\n\t*/\n\ti = -50;\n\n\tdo {\n\t\tadd = 5;\n\t\tif ((PlayerPtr->Available_Money() - i) > 100 ) add += 15;\n\t\tif ((PlayerPtr->Available_Money() - i) > 500 ) add += 30;\n\t\tif ((PlayerPtr->Available_Money() - i) > 1000) add += PlayerPtr->Available_Money() / 40;\n\t\tif (add < minval) add = minval;\n\t\ti += add;\n\n\t\tif (i < 0) i=0;\n\n\t\tSet_Font_Palette(pal);\n\t\tCount_Up_Print(\"%d\", i, PlayerPtr->Available_Money(), _credpx[house], _credpy[house]);\n\t\tCall_Back_Delay(2);\n/*BG\t\tif (Keyboard->Check()) {\n\t\t\tCount_Up_Print(\"%d\", PlayerPtr->Available_Money(), PlayerPtr->Available_Money(), _credpx[house], _credpy[house]);\n\t\t\tKeyboard->Clear();\n\t\t\tbreak;\n\t\t}*/\n\t} while (i < PlayerPtr->Available_Money()) ;\n\n\tdelete ScoreObjs[credobj];\n\tScoreObjs[credobj] = 0;\n}\n\n\n/***************************************************************************\n * SCORECLASS::PRINT_MINUTES -- Print out hours/minutes up to max          *\n *                                                                         *\n *    Same as count-up-print, but for the time                             *\n *                                                                         *\n * INPUT:   current minute count and maximum                               *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/13/1995 BWG : Created.                                             *\n *=========================================================================*/\nvoid ScoreClass::Print_Minutes(int minutes)\n{\n\tchar str[20];\n\tif (minutes >= 60) {\n\t\tif ((minutes/60) > 9) minutes = (9*60 + 59);\n\t\tsprintf(str, Text_String(TXT_SCORE_TIMEFORMAT1), (minutes / 60), (minutes % 60));\n\t} else {\n\t\tsprintf(str, Text_String(TXT_SCORE_TIMEFORMAT2), minutes);\n\t}\n\tSeenPage.Print(str, 275*RESFACTOR, 9*RESFACTOR, TBLACK, TBLACK);\n#ifdef WIN32\n\tPseudoSeenBuff->Print(str, 275*RESFACTOR, 9*RESFACTOR, TBLACK, TBLACK);\n#endif\n}\n\n\n/***********************************************************************************************\n * ScoreClass::Count_Up_Print -- Prints a number (up to its max) into a string, cleanly.       *\n *                                                                                             *\n *    This routine prints out a number (like 70) or its maximum number, into a string,   onto  *\n *    the screen, on a clean section of the screen, and blits it forward to the seenpage so you*\n *    can print without flashing and can print over something (to count up %'s).               *\n *                                                                                             *\n * INPUT:   str = string to print into                                                         *\n *            percent = # to print                                                             *\n *            max = # to print if percent > max                                                *\n *            xpos = x pixel coord                                                             *\n *            ypos = y pixel coord                                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/07/1995 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid ScoreClass::Count_Up_Print(char *str, int percent, int maxval, int xpos, int ypos)\n{\n\tchar destbuf[64];\n\n\tsprintf(destbuf, str, percent <= maxval ? percent : maxval);\n\tSeenPage.Print(\tdestbuf, xpos * RESFACTOR, ypos * RESFACTOR, TBLACK, BLACK);\n#ifdef WIN32\n\tPseudoSeenBuff->Print(\tdestbuf, xpos * RESFACTOR, ypos * RESFACTOR, TBLACK, BLACK);\n#endif\n}\n\n\n/***********************************************************************************************\n * ScoreClass::Input_Name -- Gets the name from the keyboard                                   *\n *                                                                                             *\n *      This routine handles keyboard input, and does a nifty zooming letter effect too.       *\n *                                                                                             *\n * INPUT:   str = string to put user's typing into                                             *\n *            xpos = x pixel coord                                                             *\n *            ypos = y pixel coord                                                             *\n *            pal  = text remapping palette to print using                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/15/1995 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid ScoreClass::Input_Name(char str[], int xpos, int ypos, char const pal[])\n{\n\tint key = 0;\n\tint ascii, index=0;\n\n\tvoid const * keystrok = MFCD::Retrieve(\"KEYSTROK.AUD\");\n\n\t/*\n\t** Ready the hidpage so it can restore background under zoomed letters\n\t*/\n\tSeenPage.Blit(HidPage);\n\n\t/*\n\t** Put a copy of the high score area on a spare area of the hidpage, so\n\t** we can use it to restore the letter's background instead of filling\n\t** with black.\n\t*/\n\tHidPage.Blit(HidPage, 0, 100*RESFACTOR, 0, 0, 100*RESFACTOR, 100*RESFACTOR);\n\n\tdo {\n\t\tCall_Back();\n\t\tAnimate_Score_Objs();\n\t\tAnimate_Cursor(index, ypos);\n\t\tif (Keyboard->Check()) {\n\t\t\tkey = Keyboard->To_ASCII(Keyboard->Get()) & 0xFF;\n\t\t\tCall_Back();\n\n\t\t\tif (index == MAX_FAMENAME_LENGTH-2) {\n\t\t\t\twhile (Keyboard->Check()) {\n\t\t\t\t\tKeyboard->Get();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If they hit 'backspace' when they're on the last letter,\n\t\t\t** turn it into a space instead.\n\t\t\t*/\n\t\t\tif ((key == KA_BACKSPACE) && (index == MAX_FAMENAME_LENGTH-2) ) {\n\t\t\t\tif (str[index] && str[index]!=32) key = 32;\n\t\t\t}\n\t\t\tif (key == KA_BACKSPACE) {\t\t\t\t\t\t\t//if (key == KN_BACKSPACE) {\n\t\t\t\tif (index) {\n\t\t\t\t\tstr[--index] = 0;\n\n\t\t\t\t\tint xposindex6 = (xpos+(index*6))*RESFACTOR;\n\t\t\t\t\tHidPage.Blit(SeenPage, xposindex6, (ypos-100)*RESFACTOR, xposindex6, ypos*RESFACTOR, 6*RESFACTOR, 6*RESFACTOR);\n\t\t#ifdef WIN32\n\t\t\t\t\tHidPage.Blit(*PseudoSeenBuff, xposindex6, (ypos-100)*RESFACTOR, xposindex6, ypos*RESFACTOR, 6*RESFACTOR, 6*RESFACTOR);\n\t\t#endif\n\t\t\t\t\tHidPage.Blit(HidPage,  xposindex6, (ypos-100)*RESFACTOR, xposindex6, ypos*RESFACTOR, 6*RESFACTOR, 6*RESFACTOR);\n\t\t\t\t}\n\n\t\t\t} else if (key != KA_RETURN) {\t\t\t//else if (key != KN_RETURN && key!=KN_KEYPAD_RETURN) {\n\t\t\t\tascii = key;\t\t\t\t\t//ascii = KN_To_KA(key);\n\t\t\t\tif (ascii >= 'a' && ascii <= 'z') ascii -= ('a' - 'A');\n\t\t\t\tif ( (ascii >= '!' && ascii <= KA_TILDA) || ascii == ' ') {\n\t\t\t\t\tHidPage.Blit(SeenPage, (xpos + (index*6))*RESFACTOR, (ypos-100)*RESFACTOR, (xpos + (index*6))*RESFACTOR, ypos*RESFACTOR, 6*RESFACTOR, 6*RESFACTOR);\n\t\t#ifdef WIN32\n\t\t\t\t\tHidPage.Blit(*PseudoSeenBuff, (xpos + (index*6))*RESFACTOR, (ypos-100)*RESFACTOR, (xpos + (index*6))*RESFACTOR, ypos*RESFACTOR, 6*RESFACTOR, 6*RESFACTOR);\n\t\t#endif\n\t\t\t\t\tHidPage.Blit(HidPage, (xpos + (index*6))*RESFACTOR, (ypos-100)*RESFACTOR, (xpos + (index*6))*RESFACTOR, ypos*RESFACTOR, 6*RESFACTOR, 6*RESFACTOR);\n\t\t\t\t\tstr[index] = ascii;\n\t\t\t\t\tstr[index+1] = 0;\n\n\t\t\t\t\tint objindex;\n#ifdef WIN32\n\t\t\t\t\tPlay_Sample(keystrok, 255, Options.Normalize_Volume(150));\n#else\n\t\t\t\t\tPlay_Sample(keystrok, 255, Options.Normalize_Volume(105));\n#endif\n\t\t\t\t\tobjindex = Alloc_Object(new ScoreScaleClass(str+index, xpos+(index*6), ypos, pal));\n\t\t\t\t\twhile (ScoreObjs[objindex]) Call_Back_Delay(1);\n\n\t\t\t\t\tif (index < (MAX_FAMENAME_LENGTH-2) ) index++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} while (key != KA_RETURN);\t\t\t\t\t//\t} while(key != KN_RETURN && key!=KN_KEYPAD_RETURN);\n}\n\n\nvoid Animate_Cursor(int pos, int ypos)\n{\n\tstatic int _lastpos = 0, _state;\n\tstatic CDTimerClass<SystemTimerClass> _timer;\n\n\typos += 6;\t// move cursor to bottom of letter\n\n\typos *= RESFACTOR;\n\n\t// If they moved the cursor, erase old one and force state=0, to make green draw right away\n\tif (pos != _lastpos) {\n\t\tHidPage.Blit(SeenPage, (HALLFAME_X + (_lastpos*6))*RESFACTOR, ypos-100*RESFACTOR, (HALLFAME_X + (_lastpos*6))*RESFACTOR, ypos, 6*RESFACTOR, 1*RESFACTOR);\n#ifdef WIN32\n\t\tHidPage.Blit(*PseudoSeenBuff, (HALLFAME_X + (_lastpos*6))*RESFACTOR, ypos-100*RESFACTOR, (HALLFAME_X + (_lastpos*6))*RESFACTOR, ypos, 6*RESFACTOR, 1*RESFACTOR);\n#endif\n\t\t_lastpos = pos;\n\t\t_state = 0;\n\t}\n\tSeenBuff.Draw_Line((HALLFAME_X + (pos*6))*RESFACTOR, ypos, (HALLFAME_X + (pos*6)+5)*RESFACTOR, ypos, _state ? LTBLUE : TBLACK);\n#ifdef WIN32\n\tPseudoSeenBuff->Draw_Line((HALLFAME_X + (pos*6))*RESFACTOR, ypos, (HALLFAME_X + (pos*6)+5)*RESFACTOR, ypos, _state ? LTBLUE : TBLACK);\n#endif\n\t/*\n\t** Toggle the color of the cursor, green or black, if it's time to do so.\n\t*/\n\tif (!_timer) {\n\t\t_state ^= 1;\n\t\t_timer = 5;\n\t}\n}\n\n\n/***************************************************************************\n * Draw_InfantryMen -- Draw all the guys on the score screen               *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/13/1995 BWG : Created.                                             *\n *=========================================================================*/\nvoid Draw_InfantryMen()\n{\n\tint k;\n\n// Only draw the infantrymen if we're playing USSR... Allies wouldn't execute\n//\tpeople like that.\n\n\t/*\n\t** First restore the background\n\t*/\n\tHidPage.Blit(HidPage, BARGRAPH_X, CASUALTY_Y, 0, 0, 320-BARGRAPH_X, 34);\n\tSet_Logic_Page(HidPage);\n\n\t/*\n\t** Then draw all the infantrymen on the clean hidpage\n\t*/\n\tfor (k = 0; k < NUMINFANTRYMEN; k++) Draw_InfantryMan(k);\n\t/*\n\t** They'll all be blitted over to the seenpage after the graphs are drawn\n\t*/\n}\n\n/***************************************************************************\n * Draw_InfantryMan -- Draw one guy in score screen, update animation      *\n *                                                                         *\n *    This routine draws one of the infantrymen in the \"Casualties\" area   *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/13/1995 BWG : Created.                                             *\n *=========================================================================*/\nvoid Draw_InfantryMan(int index)\n{\n\tint stage;\n\n\t/* If the infantryman's dead, just abort this function */\n\tif (InfantryMan[index].anim == -1) return;\n\n\tstage = InfantryMan[index].stage + InfantryMan[index].Class->DoControls[InfantryMan[index].anim].Frame;\n\n\tCC_Draw_Shape(InfantryMan[index].shapefile,\n\t\t\t\t\t  stage,\n\t\t\t\t\t  InfantryMan[index].xpos,\n\t\t\t\t\t  InfantryMan[index].ypos,\n\t\t\t\t\t  WINDOW_MAIN,\n\t\t\t\t\t  SHAPE_FADING|SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_GHOST,\n\t\t\t\t\t  InfantryMan[index].remap,\n\t\t\t\t\t  DisplayClass::UnitShadow);\n\t/*\n\t** see if it's time to run a new anim\n\t*/\n\tif (--InfantryMan[index].delay <= 0) {\n\t\tInfantryMan[index].delay = 3;\n\t\tif (++InfantryMan[index].stage >= InfantryMan[index].Class->DoControls[InfantryMan[index].anim].Count) {\n\n\t\t\t/*\n\t\t\t** was he playing a death anim? If so, and it's done, erase him\n\t\t\t*/\n\t\t\tif (InfantryMan[index].anim >= DO_GUN_DEATH) {\n\t\t\t\tInfantryMan[index].anim = -1;\n\t\t\t} else {\n\t\t\t\tNew_Infantry_Anim(index, DO_STAND_READY);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * New_Infantry_Anim -- Start up a new animation for one of the infantrymen*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:   index: which of the 30 infantrymen to affect                   *\n *          anim:  which animation sequence to start him into              *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/13/1995 BWG : Created.                                             *\n *=========================================================================*/\nvoid New_Infantry_Anim(int index, int anim)\n{\n\tInfantryMan[index].anim = anim;\n\tInfantryMan[index].stage = 0;\n\tif (anim >= DO_GUN_DEATH) {\n\t\tInfantryMan[index].delay = 1;\t// start right away\n\t} else {\n\t\tInfantryMan[index].delay = NonCriticalRandomNumber & 15;\n\t}\n}\n\n\n/***************************************************************************\n * Draw_Bar_Graphs -- Draw \"Casualties\" bar graphs                         *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:   i = current count of how far to draw graph                     *\n *          gkilled = # of GDI forces killed (adjusted to fit in space)    *\n *          nkilled = # of Nod forces killed (adjusted to fit in space)    *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/13/1995 BWG : Created.                                             *\n *   07/02/1996 BWG : Removed references to civilians.                     *\n *=========================================================================*/\nvoid Draw_Bar_Graphs(int i, int gkilled, int nkilled)\n{\n\n\tif (gkilled) {\n\t\tLogicPage->Fill_Rect(0,   0+4*RESFACTOR, 0+min(i, gkilled)*RESFACTOR,   0+5*RESFACTOR, RED);\n\t\tLogicPage->Draw_Line(0+1*RESFACTOR, 0+6*RESFACTOR, (0+min(i, gkilled)+1)*RESFACTOR, 0+6*RESFACTOR, TBLACK);\n\t\tLogicPage->Draw_Line((0+MIN(i, gkilled)+1)*RESFACTOR, 0+5*RESFACTOR, (0+min(i, gkilled)+1)*RESFACTOR, 0+5*RESFACTOR, TBLACK);\n\t\tif (i <= gkilled) {\n\t\t\tint anim = InfantryMan[i/11].anim;\n\t\t\tif (anim!=-1 && anim < DO_GUN_DEATH) {\n\t\t\t\tif (i/11) {\n\t\t\t\t\tNew_Infantry_Anim(i/11, DO_GUN_DEATH + (NonCriticalRandomNumber & 3));\n\t\t\t\t} else {\n\t\t\t\t\tNew_Infantry_Anim(i/11, DO_GUN_DEATH);\n\t\t\t\t}\n//\t\t\t\tSound_Effect(Random_Pick(VOC_SCREAM1, VOC_SCREAM5));\n\t\t\t}\n\t\t}\n\t}\n\tif (nkilled) {\n\t\tLogicPage->Fill_Rect( 0,          0+16*RESFACTOR,  0+min(i, nkilled)*RESFACTOR,    0+17*RESFACTOR, LTCYAN);\n\t\tLogicPage->Draw_Line( 0+1*RESFACTOR, 0+18*RESFACTOR, (0+min(i, nkilled)+1)*RESFACTOR, 0+18*RESFACTOR, TBLACK);\n\t\tLogicPage->Draw_Line((0+MIN(i, nkilled)+1)*RESFACTOR, 0+17*RESFACTOR, (0+min(i, nkilled)+1)*RESFACTOR, 0+17*RESFACTOR, TBLACK);\n\t\tif (i <= nkilled) {\n\t\t\tint anim = InfantryMan[(NUMINFANTRYMEN/2)+(i/11)].anim;\n\t\t\tif (anim!=-1 && anim < DO_GUN_DEATH) {\n\t\t\t\tif (i/11) {\n\t\t\t\t\tNew_Infantry_Anim((NUMINFANTRYMEN/2)+(i/11), DO_GUN_DEATH + (NonCriticalRandomNumber & 3));\n\t\t\t\t} else {\n\t\t\t\t\tNew_Infantry_Anim((NUMINFANTRYMEN/2)+(i/11), DO_GUN_DEATH);\n\t\t\t\t}\n//\t\t\t\tSound_Effect(Random_Pick(VOC_SCREAM1, VOC_SCREAM5));\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * Call_Back_Delay -- Combines Call_Back() and Delay() functions           *\n *                                                                         *\n *    This is just to cut down on code size and typing a little.           *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/13/1995 BWG : Created.                                             *\n *=========================================================================*/\nvoid Call_Back_Delay(int time)\n{\n\tif (time < 0 ) time = 0;\n\tif (time > 60) time = 60;\n\tCDTimerClass<SystemTimerClass> cd;\n\tCDTimerClass<SystemTimerClass> callbackcd = 0;\n\n\tif (!ControlQ) {\n\t\tif (Keyboard->Down(KN_LCTRL) && Keyboard->Down(KN_Q)) {\n\t\t\tControlQ = 1;\n\t\t\tKeyboard->Clear();\n\t\t}\n\t}\n\tif (ControlQ) time=0;\n\n\tcd = time;\n\tStreamLowImpact = true;\n\tdo {\n\t\tif (callbackcd == 0) {\n\t\t\tCall_Back();\n\t\t\tcallbackcd = TIMER_SECOND/4;\n\t\t}\n\t\tAnimate_Score_Objs();\n\t} while (cd);\n\tStreamLowImpact = false;\n}\n\n\nvoid Animate_Score_Objs()\n{\n#ifdef WIN32\n\tStillUpdating = false;\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tPseudoSeenBuff->Blit(SeenPage);\n\t\t}\n#endif\n\tfor (int i = 0; i < MAXSCOREOBJS; i++) {\n\t\tif (ScoreObjs[i]) {\n\t\t\tScoreObjs[i]->Update();\n\t\t}\n\t}\n}\n\nchar *Int_Print(int a)\n{\n\tstatic char str[10];\n\n\tsprintf(str, \"%d\", a);\n\treturn str;\n}\n\n\n/***********************************************************************************************\n * Multi_Score_Presentation -- Multiplayer routine to display score screen.                    *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/11/1995  BWG: Created.                                                                 *\n *=============================================================================================*/\nextern int CopyType;\n\nvoid Multi_Score_Presentation(void)\n{\n\tchar remap[16];\n#ifdef WIN32\n\tGraphicBufferClass *pseudoseenbuff = new GraphicBufferClass(320, 200, (void*)NULL);\n\tPseudoSeenBuff = new GraphicBufferClass(SeenBuff.Get_Width(),SeenBuff.Get_Height(),(void*)NULL);\n#endif\n\n\tint i,k;\n\tvoid *oldfont;\n\tint oldfontxspacing = FontXSpacing;\n\n\tFontXSpacing = 0;\n\tMap.Override_Mouse_Shape(MOUSE_NORMAL);\n//\tTheme.Queue_Song(THEME_WIN);\n\n\tBlackPalette.Set();\n\tSeenPage.Clear();\n\tHidPage.Clear();\n\tHide_Mouse();\n\tvoid *anim = Open_Animation(\"MLTIPLYR.WSA\", NULL, 0L, (WSAOpenType)(WSA_OPEN_FROM_MEM | WSA_OPEN_TO_PAGE), ScorePalette);\n\t/*\n\t** Display the background animation\n\t*/\n#ifdef WIN32\n\tpseudoseenbuff->Clear();\n\tAnimate_Frame(anim, *pseudoseenbuff, 1);\nfor(int x=0; x<256; x++) memset(&PaletteInterpolationTable[x][0],x,256);\nCopyType = 1;\n\tInterpolate_2X_Scale(pseudoseenbuff , &SeenBuff , 0);\n#else\n\tAnimate_Frame(anim, HidPage, 1);\n\tHidPage.Blit(SeenPage);\n#endif\n\tScorePalette.Set(FADE_PALETTE_FAST, Call_Back);\n\n\tint frame = 1;\n\twhile (frame < Get_Animation_Frame_Count(anim)) {\n#ifdef WIN32\n\t\tAnimate_Frame(anim, *pseudoseenbuff, frame++);\n\t\tCopyType = 1;\n\t\tInterpolate_2X_Scale(pseudoseenbuff , &SeenBuff , NULL);\n\t\tCopyType = 0;\n#else\n\t\tAnimate_Frame(anim, SeenPage, frame++);\n#endif\n\t\tCall_Back_Delay(2);\n\t}\n\tClose_Animation(anim);\n\n#ifdef WIN32\n\tCopyType = 1;\n\tInterpolate_2X_Scale(pseudoseenbuff , PseudoSeenBuff , NULL);\n\tCopyType = 0;\n#endif\n\n\t/* Change to the six-point font for Text_Print */\n\toldfont = Set_Font(ScoreFontPtr);\n\tCall_Back();\n\n\tSet_Logic_Page(SeenBuff);\n\n#ifdef FRENCH\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_TOP,   113,  13, _greenpal));\n#else\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_TOP,   130,  13, _greenpal));\n#endif\n\tCall_Back_Delay(5);\n\tAlloc_Object(new ScorePrintClass(TXT_COMMANDER,    27,  31, _greenpal));\n\tCall_Back_Delay(10);\n#ifdef FRENCH\n\tAlloc_Object(new ScorePrintClass(TXT_BATTLES_WON, 113,  31, _greenpal));\n#endif\n#ifdef GERMAN\n\tAlloc_Object(new ScorePrintClass(TXT_BATTLES_WON, 118,  31, _greenpal));\n#endif\n#ifdef ENGLISH\n\tAlloc_Object(new ScorePrintClass(TXT_BATTLES_WON, 126,  31, _greenpal));\n#endif\n\tCall_Back_Delay(13);\n\tAlloc_Object(new ScorePrintClass(TXT_KILLS_COLON, 249,  31, _greenpal));\n\tCall_Back_Delay(6);\n\n\t/*\n\t** Move all the scores over a notch if there's more games than can be\n\t** shown (which is known by Session.CurGame == MAX_MULTI_GAMES-1);\n\t*/\n\tif (Session.CurGame == MAX_MULTI_GAMES-1) {\n\t\tfor (i = 0; i < MAX_MULTI_NAMES; i++) {\n\t\t\tfor (k = 0; k < MAX_MULTI_GAMES-1; k++) {\n\t\t\t\tSession.Score[i].Kills[k] = Session.Score[i].Kills[k+1];\n\t\t\t}\n\t\t}\n\t}\n\n\tint y = 41;\n\tfor (i = 0; i < MAX_MULTI_NAMES; i++) {\n\t\tif (strlen(Session.Score[i].Name)) {\n\t\t\tint color = Session.Score[i].Color;\n\t\t\tremap[ 8] = ColorRemaps[color].FontRemap[11];\n\t\t\tremap[ 6] = ColorRemaps[color].FontRemap[12];\n\t\t\tremap[ 4] = ColorRemaps[color].FontRemap[13];\n\t\t\tremap[ 2] = ColorRemaps[color].FontRemap[14];\n\t\t\tremap[14] = ColorRemaps[color].FontRemap[15];\n\n\t\t\tAlloc_Object(new ScorePrintClass(Session.Score[i].Name, 15,  y, remap));\n\t\t\tCall_Back_Delay(20);\n\n\t\t\tAlloc_Object(new ScorePrintClass(Int_Print(Session.Score[i].Wins), 118, y, remap));\n\t\t\tCall_Back_Delay(6);\n\n\t\t\tfor (k = 0; k <= min(Session.CurGame, MAX_MULTI_GAMES-2); k++) {\n\t\t\t\tif (Session.Score[i].Kills[k] >= 0) {\n\t\t\t\t\tAlloc_Object(new ScorePrintClass(Int_Print(Session.Score[i].Kills[k]), 225+(24*k), y, remap));\n\t\t\t\t\tCall_Back_Delay(6);\n\t\t\t\t}\n\t\t\t}\n\t\t\ty += 12;\n\t\t}\n\t}\n\n#if defined(GERMAN) || defined(FRENCH)\n\tAlloc_Object(new ScorePrintClass(TXT_CLICK_CONTINUE, 95 /*(320-strlen(Text_String(TXT_MAP_CLICK2)))/2*/, 190, _yellowpal));\n#else\n\tAlloc_Object(new ScorePrintClass(TXT_CLICK_CONTINUE, 109 /*(320-strlen(Text_String(TXT_MAP_CLICK2)))/2*/, 190, _yellowpal));\n#endif\n\tCycle_Wait_Click(false);\n\n/* get rid of all the animating objects */\n\tfor (i = 0; i < MAXSCOREOBJS; i++) if (ScoreObjs[i]) {\n\t\tdelete ScoreObjs[i];\n\t\tScoreObjs[i] = 0;\n\t}\n\n\tTheme.Queue_Song(THEME_NONE);\n\n\tBlackPalette.Set(FADE_PALETTE_FAST, NULL);\n\tSeenPage.Clear();\n\tGamePalette.Set();\n#ifdef WIN32\n\tdelete PseudoSeenBuff;\n#endif\n\tSet_Font(oldfont);\n\tFontXSpacing = oldfontxspacing;\n\tControlQ = 0;\n\tShow_Mouse();\n}\n\nvoid ScoreClass::Init(void)\n{\n\tScore = 0;\n\tNKilled = 0;\n\tGKilled = 0;\n\tCKilled = 0;\n\tNBKilled = 0;\n\tGBKilled = 0;\n\tCBKilled = 0;\n\tNHarvested = 0;\n\tGHarvested = 0;\n\tCHarvested = 0;\n\tElapsedTime = 0;\n\tRealTime = 0;\n\tChangingGun = 0;\n}\n"
  },
  {
    "path": "CODE/SCORE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SCORE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SCORE.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 19, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 19, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SCORE_H\n#define SCORE_H\n\n#include\t\"unit.h\"\n#include\t\"building.h\"\n\nclass ScoreClass {\n\tpublic:\n\t\tScoreClass(void) {};\n\t\tScoreClass(NoInitClass const &) {};\n\n\t\tint Score;\n\t\tint NKilled;\n\t\tint GKilled;\n\t\tint CKilled;\n\t\tint NBKilled;\n\t\tint GBKilled;\n\t\tint CBKilled;\n\t\tint NHarvested;\n\t\tint GHarvested;\n\t\tint CHarvested;\n\t\tunsigned long ElapsedTime;\n\t\tTTimerClass<SystemTimerClass> RealTime;\n\n\t\tvoid Init(void);\n\t\tvoid Presentation(void);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\t\tvoid Code_Pointers(void);\n\t\tvoid Decode_Pointers(void);\n\n\tprivate:\n\t\tunsigned char *ChangingGun;\n\n\t\tvoid ScoreDelay(int ticks);\n\t\tvoid Pulse_Bar_Graph(void);\n\t\tvoid Print_Graph_Title(int,int);\n\t\tvoid Print_Minutes(int minutes);\n\t\tvoid Count_Up_Print(char *str, int percent, int max, int xpos, int ypos);\n\t\tvoid Show_Credits(int house, char const pal[]);\n\t\tvoid Do_GDI_Graph(void const * yellowptr, void const * redptr, int gdikilled, int nodkilled, int ypos);\n\t\tvoid Do_Nod_Casualties_Graph(void);\n\t\tvoid Do_Nod_Buildings_Graph(void);\n\t\tvoid Input_Name(char str[], int xpos, int ypos, char const pal[]);\n};\n\nclass ScoreAnimClass {\n\tpublic:\n\t\tScoreAnimClass(int x, int y, void const * data);\n\t\tint XPos;\n\t\tint YPos;\n\t\tCDTimerClass<SystemTimerClass> Timer;\n\t\tvoid const * DataPtr;\n\t\tvirtual void Update(void) {} ;\n\t\tvirtual ~ScoreAnimClass(void) {DataPtr=0;} ;\n};\n\nclass ScoreCredsClass : public ScoreAnimClass {\n\tpublic:\n\t\tint Stage;\n\t\tint MaxStage;\n\t\tint TimerReset;\n\t\tvoid const * CashTurn;\n\t\tvoid const * Clock1;\n\n\t\tvirtual void Update(void);\n\t\tScoreCredsClass(int xpos, int ypos, void const * data, int max, int timer);\n\t\tvirtual ~ScoreCredsClass(void) {CashTurn=0;Clock1=0;};\n};\n\nclass ScoreTimeClass : public ScoreAnimClass {\n\tpublic:\n\t\tint Stage;\n\t\tint MaxStage;\n\t\tint TimerReset;\n\t\tvirtual void Update(void);\n\t\tScoreTimeClass(int xpos, int ypos, void const * data, int max, int timer);\n\t\tvirtual ~ScoreTimeClass(void) {};\n};\n\nclass ScorePrintClass : public ScoreAnimClass {\n\tpublic:\n\t\tint Background;\n\t\tint Stage;\n\t\tvoid const * PrimaryPalette;\n\t\tvirtual void Update(void);\n\t\tScorePrintClass(void const * string, int xpos, int ypos, void const * palette, int background=TBLACK);\n\t\tScorePrintClass( int  string, int xpos, int ypos, void const * palette, int background=TBLACK);\n\t\tvirtual ~ScorePrintClass(void) {PrimaryPalette=0;};\n};\n\nclass ScoreScaleClass : public ScoreAnimClass {\n\tpublic:\n\t\tint Stage;\n\t\tchar const * Palette;\n\t\tvirtual void Update(void);\n\t\tScoreScaleClass(void const * data, int xpos, int ypos, char const pal[]);\n\t\tvirtual ~ScoreScaleClass(void) {Palette=0;};\n\n};\n\n#define MAXSCOREOBJS\t\t8\nextern ScoreAnimClass *ScoreObjs[MAXSCOREOBJS];\n\nvoid Multi_Score_Presentation(void);\n\n#endif\n"
  },
  {
    "path": "CODE/SCREEN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SCREEN.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               *** \n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SCREEN.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 2, 1994                                                 *\n *                                                                                             *\n *                  Last Update : June 2, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SCREEN_H\n#define SCREEN_H\n\n\nclass ScreenClass\n{\n\t\t/*\n\t\t**\tThe mouse shape is controlled by these variables. These\n\t\t**\thold the current mouse shape (so resetting won't be needlessly performed) and\n\t\t**\tthe normal default mouse shape (when arrow shapes are needed).\n\t\t*/\n\t\tMouseShapeType CurrentMouseShape;\n\t\tMouseShapeType NormalMouseShape;\n\n\tpublic:\n\n\t\tScreenClass(void) {\n\t\t\tCurrentMouseShape = SHP_NONE;\n\t\t\tNormalMouseShape = SHP_MOUSE;\n\t\t};\n\t\t\n\n\t\tInit(void);\n\t\tSet_Default_Mouse(MouseShapeType mouse);\n\t\tForce_Mouse_Shape(MouseShapeType mouse);\n\n\t\tunsigned char *GamePalette;\n\t\tunsigned char *BlackPalette;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/SCROLL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SCROLL.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SCROLL.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/08/95                                                     *\n *                                                                                             *\n *                  Last Update : August 25, 1995 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ScrollClass::AI -- Handles scroll AI processing.                                          *\n *   ScrollClass::ScrollClass -- Constructor for the scroll class object.                      *\n *   ScrollClass::Set_Autoscroll -- Turns autoscrolling on or off.                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n#ifdef WIN32\n#define\tSCROLL_DELAY\t1\n#else\n#define\tSCROLL_DELAY\t2\n#endif\n\nCDTimerClass<SystemTimerClass> ScrollClass::Counter;\n\n\n/***********************************************************************************************\n * ScrollClass::ScrollClass -- Constructor for the scroll class object.                        *\n *                                                                                             *\n *    This is the constructor for the scroll class object.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nScrollClass::ScrollClass(void) :\n\tIsAutoScroll(true)\n{\n\tCounter = SCROLL_DELAY;\n\tInertia = 0;\n}\n\n\n/***********************************************************************************************\n * ScrollClass::AI -- Handles scroll AI processing.                                            *\n *                                                                                             *\n *    This routine is called every game frame for purposes of input processing.                *\n *                                                                                             *\n * INPUT:   input    -- Reference to the keyboard/mouse event that just occurred.              *\n *                                                                                             *\n *          x,y      -- The mouse coordinates.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/10/1995 JLB : Created.                                                                 *\n *   08/10/1995 JLB : Revamped for free smooth scrolling.                                      *\n *   08/25/1995 JLB : Handles new scrolling option.                                            *\n *=============================================================================================*/\n#define\tEVA_WIDTH\t\t80\nvoid ScrollClass::AI(KeyNumType &input, int x, int y)\n{\n\tbool\t\tplayer_scrolled=false;\n\tstatic \tDirType\tdirection;\n\tint\t\trate;\n\n\n\t/*\n\t**\tIf rubber band mode is in progress, then don't allow scrolling of the tactical map.\n\t*/\n\tif (!IsRubberBand /*&& !IsTentative*/) {\n\n\t\t/*\n\t\t**\tSpecial check to not scroll within the special no-scroll regions.\n\t\t*/\n\t\tbool noscroll = false;\n\n\t\tif (!noscroll) {\n\t\t\tbool at_screen_edge = (y == 0 || x == 0 || x >= SeenBuff.Get_Width()-1 || y >= SeenBuff.Get_Height()-1);\n\n\t\t\t/*\n\t\t\t**\tVerify that the mouse is over a scroll region.\n\t\t\t*/\n\t\t\tif (Inertia || at_screen_edge) {\n\t\t\t\tif (at_screen_edge) {\n\n\t\t\t\t\tplayer_scrolled=true;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tAdjust the mouse coordinates to emphasize the\n\t\t\t\t\t**\tcardinal directions over the diagonals.\n\t\t\t\t\t*/\n\t\t\t\t\tint altx = x;\n\t\t\t\t\tif (altx < 50 * RESFACTOR) altx -= ((50 * RESFACTOR)-altx);\n\t\t\t\t\taltx = max(altx, 0);\n\t\t\t\t\tif (altx > ((320-50) * RESFACTOR)) altx += altx-((320-50) * RESFACTOR);\n\t\t\t\t\taltx = min(altx, (320 * RESFACTOR));\n\t\t\t\t\tif (altx > (50 * RESFACTOR) && altx < ((320-50) * RESFACTOR)) {\n\t\t\t\t\t\taltx += (((320/2) * RESFACTOR)-altx)/2;\n\t\t\t\t\t}\n\n\t\t\t\t\tint alty = y;\n\t\t\t\t\tif (alty < (50 * RESFACTOR)) alty -= (50 * RESFACTOR)-alty;\n\t\t\t\t\talty = max(alty, 0);\n\t\t\t\t\tif (alty > (150 * RESFACTOR)) alty += alty-(150 * RESFACTOR);\n\t\t\t\t\talty = min(alty, 200 * RESFACTOR);\n\n\t\t\t\t\tdirection = (DirType)Desired_Facing256((320/2) * RESFACTOR, (200/2) * RESFACTOR, altx, alty);\n\t\t\t\t}\n\n\t\t\t\tint control = Dir_Facing(direction);\n\n\t\t\t\t/*\n\t\t\t\t**\tThe mouse is over a scroll region so set the mouse shape accordingly if the map\n\t\t\t\t**\tcan be scrolled in the direction indicated.\n\t\t\t\t*/\n\t\t\t\tstatic int _rate[9] = {\n\t\t\t\t\t0x00E0*RESFACTOR,\n\t\t\t\t\t0x00C0*RESFACTOR,\n\t\t\t\t\t0x00A0*RESFACTOR,\n\t\t\t\t\t0x0080*RESFACTOR,\n\t\t\t\t\t0x0060*RESFACTOR,\n\t\t\t\t\t0x0040*RESFACTOR,\n\t\t\t\t\t0x0020*RESFACTOR,\n\t\t\t\t\t0x0010*RESFACTOR,\n\t\t\t\t\t0x0008*RESFACTOR\n\t\t\t\t};\n\t\t\t\tif (Debug_Map) {\n\t\t\t\t\trate = Options.ScrollRate+1;\n\t\t\t\t} else {\n\t\t\t\t\trate = 8-Inertia;\n\t\t\t\t}\n\n\t\t\t\tif (rate < Options.ScrollRate+1) {\n\t\t\t\t\trate = Options.ScrollRate+1;\n\t\t\t\t\tInertia = 8-rate;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIncrease the scroll rate if the mouse button is held down.\n\t\t\t\t*/\n\t//\t\t\tif (Keyboard->Down(KN_LMOUSE)) {\n\t//\t\t\t\trate = Bound(rate-3, 0, 4);\n\t//\t\t\t}\n\t\t\t\tif (Keyboard->Down(KN_RMOUSE)) {\n\t\t\t\t\trate = Bound(rate+1, 4, (int)(sizeof(_rate)/sizeof(_rate[0]))-1);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf options indicate that scrolling should be forced to\n\t\t\t\t**\tone of the 8 facings, then adjust the direction value\n\t\t\t\t**\taccordingly.\n\t\t\t\t*/\n\t\t\t\tdirection = Facing_Dir(Dir_Facing(direction));\n\n\t\t\t\tint distance = _rate[rate]/2;\n\n\t\t\t\tif (!Scroll_Map(direction, distance, false)) {\n\t\t\t\t\tOverride_Mouse_Shape((MouseType)(MOUSE_NO_N+control), false);\n\t\t\t\t} else {\n\t\t\t\t\tOverride_Mouse_Shape((MouseType)(MOUSE_N+control), false);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the mouse button is pressed or auto scrolling is active, then scroll\n\t\t\t\t\t**\tthe map if the delay counter indicates.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Keyboard->Down(KN_LMOUSE) || IsAutoScroll) {\n\t\t\t\t\t\tdistance = _rate[rate];\n\n\t\t\t\t\t\tif (Debug_Map) {\n\t\t\t\t\t\t\tScroll_Map(direction, distance, true);\n\t\t\t\t\t\t\tCounter = SCROLL_DELAY;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdistance = _rate[rate];\n\t\t\t\t\t\t\tScroll_Map(direction, distance, true);\n\n\t\t\t\t\t\t\tif (Counter == 0 && player_scrolled) {\n\t\t\t\t\t\t\t\tCounter = SCROLL_DELAY;\n\t\t\t\t\t\t\t\tInertia++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif (!Debug_Map && !player_scrolled) {\n\t\t\t\tif (!Counter) {\n\t\t\t\t\tInertia--;\n\t\t\t\t\tif (Inertia<0) Inertia++;\n\t\t\t\t\tCounter = SCROLL_DELAY;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\n\tHelpClass::AI(input, x, y);\n}\n\n\n/***********************************************************************************************\n * ScrollClass::Set_Autoscroll -- Turns autoscrolling on or off.                               *\n *                                                                                             *\n *    This routine controls the autoscrolling setting. Autoscroll, when active, will cause the *\n *    map to scroll if the mouse is held over the scroll region. This is regardless of whether *\n *    any mouse button is held down or not.                                                    *\n *                                                                                             *\n * INPUT:   control  -- Should the autoscroll be turned on?                                    *\n *                      0  = turn off                                                          *\n *                      1  = turn on                                                           *\n *                      -1 = toggle current setting                                            *\n *                                                                                             *\n * OUTPUT:  Returns with the old setting of the autoscroll flag.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ScrollClass::Set_Autoscroll(int control)\n{\n\tbool old = IsAutoScroll;\n\n\tswitch (control) {\n\t\tcase -1:\n\t\t\tIsAutoScroll = !IsAutoScroll;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tIsAutoScroll = control;\n\t\t\tbreak;\n\t}\n\treturn(old);\n}\n\n\n"
  },
  {
    "path": "CODE/SCROLL.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SCROLL.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SCROLL.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/18/94                                                     *\n *                                                                                             *\n *                  Last Update : November 18, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SCROLL_H\n#define SCROLL_H\n\n#include\t\"help.h\"\n\n\nclass ScrollClass: public HelpClass\n{\n\t\t/*\n\t\t**\tIf map scrolling is automatic, then this flag is true. Automatic scrolling will\n\t\t**\tcause the map to scroll if the mouse is in the scroll region, regardless of\n\t\t**\twhether or not the mouse button is held down.\n\t\t*/\n\t\tunsigned IsAutoScroll:1;\n\n\t\t/*\n\t\t**\tScroll speed is regulated by this count down timer. When this value reaches zero,\n\t\t**\tscroll the map in the direction required and reset this timer.\n\t\t*/\n\t\tstatic CDTimerClass<SystemTimerClass> Counter;\n\n\t\t/*\n\t\t** Inertia control for scrolling\n\t\t*/\n\t\tint\tInertia;\n\n\tpublic:\n\t\tScrollClass(void);\n\t\tScrollClass(NoInitClass const & x) : HelpClass(x) {};\n\n\t\tbool Set_Autoscroll(int control);\n\n\t\tvirtual void AI(KeyNumType &input, int x, int y);\n\t\tvirtual void Init_IO(void) {Counter = 0;HelpClass::Init_IO();};\n};\n\n#endif\n"
  },
  {
    "path": "CODE/SDATA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SDATA.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SDATA.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 9, 1994                                               *\n *                                                                                             *\n *                  Last Update : July 9, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SmudgeTypeClass::As_Reference -- Fetches a reference to the smudge type specified.        *\n *   SmudgeTypeClass::Create_And_Place -- Creates and places on map, a smudge object.          *\n *   SmudgeTypeClass::Create_One_Of -- Creates a smudge object of this type.                   *\n *   SmudgeTypeClass::Display -- Draws a generic version of this smudge type.                  *\n *   SmudgeTypeClass::Draw_It -- Renders the smudge image at the coordinate specified.         *\n *   SmudgeTypeClass::From_Name -- Converts an ASCII name into a smudge type.                  *\n *   SmudgeTypeClass::Init -- Performs theater specific initializations.                       *\n *   SmudgeTypeClass::Init_Heap -- Initialize the smudge type class object heap.               *\n *   SmudgeTypeClass::One_Time -- Performs one-time initialization                             *\n *   SmudgeTypeClass::Prep_For_Add -- Prepares the scenario editor for adding a smudge object. *\n *   SmudgeTypeClass::SmudgeTypeClass -- Constructor for smudge type objects.                  *\n *   SmudgeTypeClass::operator delete -- Returns a smudge type class object to the pool.       *\n *   SmudgeTypeClass::operator new -- Allocate a smudge type object from the memory pool.      *\n *   SmudgetypeClass::Occupy_List -- Determines occupation list for smudge object.             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"type.h\"\n\n\nstatic SmudgeTypeClass const Crater1 (\n\tSMUDGE_CRATER1,\n\t\"CR1\",\n\tTXT_CRATER,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\ttrue\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Crater2 (\n\tSMUDGE_CRATER2,\n\t\"CR2\",\n\tTXT_CRATER,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\ttrue\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Crater3 (\n\tSMUDGE_CRATER3,\n\t\"CR3\",\n\tTXT_CRATER,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\ttrue\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Crater4 (\n\tSMUDGE_CRATER4,\n\t\"CR4\",\n\tTXT_CRATER,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\ttrue\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Crater5 (\n\tSMUDGE_CRATER5,\n\t\"CR5\",\n\tTXT_CRATER,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\ttrue\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Crater6 (\n\tSMUDGE_CRATER6,\n\t\"CR6\",\n\tTXT_CRATER,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\ttrue\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Scorch1 (\n\tSMUDGE_SCORCH1,\n\t\"SC1\",\n\tTXT_SCORCH,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Scorch2 (\n\tSMUDGE_SCORCH2,\n\t\"SC2\",\n\tTXT_SCORCH,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Scorch3 (\n\tSMUDGE_SCORCH3,\n\t\"SC3\",\n\tTXT_SCORCH,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Scorch4 (\n\tSMUDGE_SCORCH4,\n\t\"SC4\",\n\tTXT_SCORCH,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Scorch5 (\n\tSMUDGE_SCORCH5,\n\t\"SC5\",\n\tTXT_SCORCH,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Scorch6 (\n\tSMUDGE_SCORCH6,\n\t\"SC6\",\n\tTXT_SCORCH,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\n\nstatic SmudgeTypeClass const Bibx1 (\n\tSMUDGE_BIB1,\n\t\"BIB1\",\n\tTXT_BIB,\n\t4,2,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\ttrue,\t\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Bibx2 (\n\tSMUDGE_BIB2,\n\t\"BIB2\",\n\tTXT_BIB,\n\t3,2,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\ttrue,\t\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Bibx3 (\n\tSMUDGE_BIB3,\n\t\"BIB3\",\n\tTXT_BIB,\n\t2,2,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\ttrue,\t\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::SmudgeTypeClass -- Constructor for smudge type objects.                    *\n *                                                                                             *\n *    This constructor is used to create the smudge type objects. These type objects contain   *\n *    static information about the various smudge types supported in the game.                 *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nSmudgeTypeClass::SmudgeTypeClass(\n\tSmudgeType smudge,\n\tchar const * ininame,\n\tint fullname,\n\tint width,\n\tint height,\n\tbool isbib,\n\tbool iscrater) :\n\t\tObjectTypeClass(\n\t\t\tRTTI_SMUDGETYPE,\n\t\t\tint(smudge),\n\t\t\tfalse,\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t\ttrue,\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t\tfullname,\n\t\t\tininame),\n\tType(smudge),\n\tWidth(width),\n\tHeight(height),\n\tIsCrater(iscrater),\n\tIsBib(isbib)\n{\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::operator new -- Allocate a smudge type object from the memory pool.        *\n *                                                                                             *\n *    This will allocate a smudge type class object from the special memory pool for that      *\n *    purpose.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the newly allocated smudge type class object. If there is insufficient*\n *          memory in the pool to fulfill the request, then NULL is returned.                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * SmudgeTypeClass::operator new(size_t)\n{\n\treturn(SmudgeTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::operator delete -- Returns a smudge type class object to the pool.         *\n *                                                                                             *\n *    This will return the smudge type class object back to the memory pool from whence it     *\n *    was originally allocated.                                                                *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to the smudge type class object to return the pool.            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeTypeClass::operator delete(void * pointer)\n{\n\tSmudgeTypes.Free((SmudgeTypeClass *)pointer);\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::Init_Heap -- Initialize the smudge type class object heap.                 *\n *                                                                                             *\n *    This will initialize the special heap for smudge type class objects, by pre-allocated    *\n *    all known smudge types.                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine only once and before the rules.ini file is processed.         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese smudge type class objects must be allocated in the exact order that they\n\t**\tare specified in the SmudgeType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew SmudgeTypeClass(Crater1);\t\t\t// SMUDGE_CRATER1\n\tnew SmudgeTypeClass(Crater2);\t\t\t// SMUDGE_CRATER2\n\tnew SmudgeTypeClass(Crater3);\t\t\t// SMUDGE_CRATER3\n\tnew SmudgeTypeClass(Crater4);\t\t\t// SMUDGE_CRATER4\n\tnew SmudgeTypeClass(Crater5);\t\t\t// SMUDGE_CRATER5\n\tnew SmudgeTypeClass(Crater6);\t\t\t// SMUDGE_CRATER6\n\tnew SmudgeTypeClass(Scorch1);\t\t\t// SMUDGE_SCORCH1\n\tnew SmudgeTypeClass(Scorch2);\t\t\t// SMUDGE_SCORCH2\n\tnew SmudgeTypeClass(Scorch3);\t\t\t// SMUDGE_SCORCH3\n\tnew SmudgeTypeClass(Scorch4);\t\t\t// SMUDGE_SCORCH4\n\tnew SmudgeTypeClass(Scorch5);\t\t\t// SMUDGE_SCORCH5\n\tnew SmudgeTypeClass(Scorch6);\t\t\t// SMUDGE_SCORCH6\n\tnew SmudgeTypeClass(Bibx1);\t\t\t// SMUDGE_BIB1\n\tnew SmudgeTypeClass(Bibx2);\t\t\t//\tSMUDGE_BIB2\n\tnew SmudgeTypeClass(Bibx3);\t\t\t// SMUDGE_BIB3\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::From_Name -- Converts an ASCII name into a smudge type.                    *\n *                                                                                             *\n *    This converts an ASCII name into a smudge type number. This is typically necessary       *\n *    when processing scenario INI files and not used otherwise.                               *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the name to convert.                                           *\n *                                                                                             *\n * OUTPUT:  Returns with the SmudgeType number that matches the name supplied. If no match     *\n *          was found, then SMUDGE_NONE is returned.                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nSmudgeType SmudgeTypeClass::From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (SmudgeType index = SMUDGE_FIRST; index < SMUDGE_COUNT; index++) {\n\t\t\tif (stricmp(As_Reference(index).IniName, name) == 0) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t}\n\t}\n\treturn(SMUDGE_NONE);\n}\n\n\n/***********************************************************************************************\n * SmudgetypeClass::Occupy_List -- Determines occupation list for smudge object.               *\n *                                                                                             *\n *    Smudges are always only one icon in dimension, so this routine always returns a cell     *\n *    occupation offset list of the center cell.                                               *\n *                                                                                             *\n * INPUT:   placement   -- Is this for placement legality checking only? The normal condition  *\n *                         is for marking occupation flags.                                    *\n *                                                                                             *\n * OUTPUT:  Returns occupation list specifying all the cells that the overlay occupies. This   *\n *          is just the center cell.                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * SmudgeTypeClass::Occupy_List(bool) const\n{\n\tstatic short _occupy[4*4];\n\tshort * ptr = &_occupy[0];\n\n\tfor (int x = 0; x < Width; x++) {\n\t\tfor (int y = 0; y < Height; y++) {\n\t\t\t*ptr++ = x + (y*MAP_CELL_W);\n\t\t}\n\t}\n\t*ptr = REFRESH_EOL;\n\treturn(_occupy);\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::Init -- Performs theater specific initializations.                         *\n *                                                                                             *\n *    Smudge object imagery varies between theaters. This routine will load the appropriate    *\n *    imagery for the theater specified.                                                       *\n *                                                                                             *\n * INPUT:   theater  -- The theater to prepare for.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeTypeClass::Init(TheaterType theater)\n{\n\tif (theater != LastTheater) {\n\t\tfor (SmudgeType index = SMUDGE_FIRST; index < SMUDGE_COUNT; index++) {\n\t\t\tSmudgeTypeClass const & smudge = As_Reference(index);\n\t\t\tchar fullname[_MAX_FNAME+_MAX_EXT];\t// Fully constructed smudge data set name.\n\n\t\t\t_makepath(fullname, NULL, NULL, smudge.IniName, Theaters[theater].Suffix);\n\t\t\t((void const *&)smudge.ImageData) = MFCD::Retrieve(fullname);\n\t\t}\n\t}\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***********************************************************************************************\n * SmudgeTypeClass::Display -- Draws a generic version of this smudge type.                    *\n *                                                                                             *\n *    The scenario object editor will call this routine to display a typical imagery of this   *\n *    smudge object for graphical identification purposes.                                     *\n *                                                                                             *\n * INPUT:   x,y   -- Coordinate to render the smudge at.                                       *\n *                                                                                             *\n *          window-- The window to base the coordinate rendering upon.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeTypeClass::Display(int x, int y, WindowNumberType window, HousesType ) const\n{\n\tvoid const * ptr = Get_Image_Data();\n\n\tx += WindowList[window][WINDOWX];\n\ty += WindowList[window][WINDOWY];\n\n\tIsTheaterShape = true;\t\t// Smudges are theater specific\n\tif (ptr != NULL) {\n\t\tfor (int w = 0; w < Width; w++) {\n\t\t\tfor (int h = 0; h < Height; h++) {\n\t\t\t\tCC_Draw_Shape(ptr, w + (h*Width), x + w*ICON_PIXEL_W, y + h*ICON_PIXEL_H, WINDOW_TACTICAL, SHAPE_WIN_REL);\n\t\t\t}\n\t\t}\n\t}\n\tIsTheaterShape = false;\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::Prep_For_Add -- Prepares the scenario editor for adding a smudge object.   *\n *                                                                                             *\n *    This routine adds smudge objects to the list of objects that the scenario editor can     *\n *    place upon the ground. It is only called from the scenario editor.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeTypeClass::Prep_For_Add(void)\n{\n\tfor (SmudgeType index = SMUDGE_FIRST; index < SMUDGE_COUNT; index++) {\n\t\tif (As_Reference(index).Get_Image_Data()) {\n\t\t\tMap.Add_To_List(&As_Reference(index));\n\t\t}\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::Create_And_Place -- Creates and places on map, a smudge object.            *\n *                                                                                             *\n *    This routine will, in one motion, create a smudge object and place it upon the map.      *\n *    Since placing a smudge on the map will destroy the object, this routine will leave the   *\n *    smudge object count unchanged. Typically, this routine is used by the scenario editor    *\n *    for creating smudges and placing them on the map.                                        *\n *                                                                                             *\n * INPUT:   cell  -- The cell to place the smudge object.                                      *\n *                                                                                             *\n * OUTPUT:  bool; Was the placement successful?                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SmudgeTypeClass::Create_And_Place(CELL cell, HousesType ) const\n{\n\tif (new SmudgeClass(Type, Cell_Coord(cell))) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::Create_One_Of -- Creates a smudge object of this type.                     *\n *                                                                                             *\n *    This routine will create a smudge object of the appropriate type. Smudge objects are     *\n *    transitory in nature. They exist only from the point of creation until they are given    *\n *    a spot on the map to reside. At that time the map data is updated and the smudge         *\n *    object is destroyed.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a created smudge object. If none could be created, then  *\n *          NULL is returned.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * SmudgeTypeClass::Create_One_Of(HouseClass *) const\n{\n\treturn(new SmudgeClass(Type, -1));\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::Draw_It -- Renders the smudge image at the coordinate specified.           *\n *                                                                                             *\n *    This routine will draw the smudge overlay image at the coordinate (upper left)           *\n *    specified. The underlying terrain icon is presumed to have already been rendered.        *\n *                                                                                             *\n * INPUT:   x,y   -- Coordinate of the upper left corner of icon to render the smudge object.  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeTypeClass::Draw_It(int x, int y, int data) const\n{\n\tvoid const * ptr = Get_Image_Data();\n\tif (ptr != NULL) {\n\t\tIsTheaterShape = true;\t\t// Smudges are theater specific\n\t\tCC_Draw_Shape(ptr, data, x, y, WINDOW_TACTICAL, SHAPE_WIN_REL);\n\t\tIsTheaterShape = false;\n\t}\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::One_Time -- Performs one-time initialization                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeTypeClass::One_Time(void)\n{\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::As_Reference -- Fetches a reference to the smudge type specified.          *\n *                                                                                             *\n *    Use this routine to get a reference to the smudge type class object when given just      *\n *    the smudge type identifier.                                                              *\n *                                                                                             *\n * INPUT:   type  -- The smudge type identifier to convert into a reference.                   *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the smudge type class object.                          *\n *                                                                                             *\n * WARNINGS:   Be sure that the smudge type specified is legal. An illegal type value will     *\n *             produce undefined results.                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nSmudgeTypeClass & SmudgeTypeClass::As_Reference(SmudgeType type)\n{\n\treturn(*SmudgeTypes.Ptr(type));\n}\n"
  },
  {
    "path": "CODE/SEARCH.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SEARCH.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SEARCH.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/02/96                                                     *\n *                                                                                             *\n *                  Last Update : November 2, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   IndexClass<T>::Add_Index -- Add element to index tracking system.                         *\n *   IndexClass<T>::Clear -- Clear index handler to empty state.                               *\n *   IndexClass<T>::Count -- Fetch the number of index entries recorded.                       *\n *   IndexClass<T>::Fetch_Index -- Fetch data from specified index.                            *\n *   IndexClass<T>::Increase_Table_Size -- Increase the internal index table capacity.         *\n *   IndexClass<T>::IndexClass -- Constructor for index handler.                               *\n *   IndexClass<T>::Invalidate_Archive -- Invalidate the archive pointer.                      *\n *   IndexClass<T>::Is_Archive_Same -- Checks to see if archive pointer is same as index.      *\n *   IndexClass<T>::Is_Present -- Checks for presense of index entry.                          *\n *   IndexClass<T>::Remove_Index -- Find matching index and remove it from system.             *\n *   IndexClass<T>::Search_For_Node -- Perform a search for the specified node ID              *\n *   IndexClass<T>::Set_Archive -- Records the node pointer into the archive.                  *\n *   IndexClass<T>::Sort_Nodes -- Sorts nodes in preparation for a binary search.              *\n *   IndexClass<T>::~IndexClass -- Destructor for index handler object.                        *\n *   compfunc -- Support function for bsearch and bsort.                                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef SEARCH_H\n#define SEARCH_H\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n#ifndef __BORLANDC__\n#define\t_USERENTRY\n#endif\n\n/*\n**\tThis class is used to create and maintain an index. It does this by assigning a unique\n**\tidentifier number to the type objects that it is indexing. The regular binary sort and search\n**\tfunction are used for speedy index retreival. Typical use of this would be to index pointers to\n**\tnormal data objects, but it can be used to hold the data objects themselves. Keep in mind that\n**\tthe data object \"T\" is copied around by this routine in the internal tables so not only must\n**\tit have a valid copy constructor, it must also be efficient. The internal algorithm will\n**\tcreate an arbitrary number of default constructed objects of type \"T\". Make sure it has a\n**\tdefault constructor that is effecient. The constructor need not perform any actual\n**\tinitialization since this class has prior knowledge about the legality of these temporary\n**\tobjects and doesn't use them until after the copy constructor is used to initialize them.\n*/\n\ntemplate<class T>\nclass IndexClass\n{\n\tpublic:\n\t\tIndexClass(void);\n\t\t~IndexClass(void);\n\n\t\t/*\n\t\t**\tAdd element to index table.\n\t\t*/\n\t\tbool Add_Index(int id, T data);\n\n\t\t/*\n\t\t**\tRemoves an index entry from the index table.\n\t\t*/\n\t\tbool Remove_Index(int id);\n\n\t\t/*\n\t\t**\tCheck to see if index is present.\n\t\t*/\n\t\tbool Is_Present(int id) const;\n\n\t\t/*\n\t\t**\tFetch number of indexes in the table.\n\t\t*/\n\t\tint Count(void) const;\n\n\t\t/*\n\t\t**\tActually a fetch an index data element from the table.\n\t\t*/\n\t\tT Fetch_Index(int id) const;\n\n\t\t/*\n\t\t**\tClear out the index table to null (empty) state.\n\t\t*/\n\t\tvoid Clear(void);\n\n\tprivate:\n\t\t/*\n\t\t**\tThis node object is used to keep track of the connection between the data\n\t\t**\tobject and the index identifier number.\n\t\t*/\n\t\tstruct NodeElement {\n\t\t\tint ID;\t\t\t// ID number (must be first element in this structure).\n\t\t\tT Data;\t\t\t// Data element assigned to this ID number.\n\t\t};\n\n\t\t/*\n\t\t**\tThis is the pointer to the allocated index table. It contains all valid nodes in\n\t\t**\ta sorted order.\n\t\t*/\n\t\tNodeElement * IndexTable;\n\n\t\t/*\n\t\t**\tThis records the number of valid nodes within the index table.\n\t\t*/\n\t\tint IndexCount;\n\n\t\t/*\n\t\t**\tThe total size (in nodes) of the index table is recorded here. If adding a node\n\t\t**\twould cause the index count to exceed this value, the index table must be resized\n\t\t**\tto make room.\n\t\t*/\n\t\tint IndexSize;\n\n\t\t/*\n\t\t**\tIf the index table is sorted and ready for searching, this flag will be true. Sorting\n\t\t**\tof the table only occurs when absolutely necessary.\n\t\t*/\n\t\tbool IsSorted;\n\n\t\t/*\n\t\t**\tThis records a pointer to the last element found by the Is_Present() function. Using\n\t\t**\tthis last recorded value can allow quick fetches of data whenever possible.\n\t\t*/\n\t\tNodeElement const * Archive;\n\n\t\t//-------------------------------------------------------------------------------------\n\t\tIndexClass(IndexClass const & rvalue);\n\t\tIndexClass * operator = (IndexClass const & rvalue);\n\n\t\t/*\n\t\t**\tIncrease size of internal index table by amount specified.\n\t\t*/\n\t\tbool Increase_Table_Size(int amount);\n\n\t\t/*\n\t\t**\tCheck if archive pointer is the same as that requested.\n\t\t*/\n\t\tbool Is_Archive_Same(int id) const;\n\n\t\t/*\n\t\t**\tInvalidate the archive pointer.\n\t\t*/\n\t\tvoid Invalidate_Archive(void);\n\n\t\t/*\n\t\t**\tSet archive to specified value.\n\t\t*/\n\t\tvoid Set_Archive(NodeElement const * node);\n\n\t\t/*\n\t\t**\tSearch for the node in the index table.\n\t\t*/\n\t\tNodeElement const * Search_For_Node(int id) const;\n\n\t\tstatic int _USERENTRY search_compfunc(void const * ptr, void const * ptr2);\n};\n\n\n/***********************************************************************************************\n * IndexClass<T>::IndexClass -- Constructor for index handler.                                 *\n *                                                                                             *\n *    This constructs an empty index handler.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nIndexClass<T>::IndexClass(void) :\n\tIndexTable(0),\n\tIndexCount(0),\n\tIndexSize(0),\n\tIsSorted(false),\n\tArchive(0)\n{\n\tInvalidate_Archive();\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::~IndexClass -- Destructor for index handler object.                          *\n *                                                                                             *\n *    This will destruct and free any resources managed by this index handler.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nIndexClass<T>::~IndexClass(void)\n{\n\tClear();\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Clear -- Clear index handler to empty state.                                 *\n *                                                                                             *\n *    This routine will free all internal resources and bring the index handler into a         *\n *    known empty state. After this routine, the index handler is free to be reused.           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid IndexClass<T>::Clear(void)\n{\n\tdelete [] IndexTable;\n\tIndexTable = 0;\n\tIndexCount = 0;\n\tIndexSize = 0;\n\tIsSorted = false;\n\tInvalidate_Archive();\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Increase_Table_Size -- Increase the internal index table capacity.           *\n *                                                                                             *\n *    This helper function will increase the capacity of the internal index table without      *\n *    performing any alterations to the index data. Use this routine prior to adding a new     *\n *    element if the existing capacity is insufficient.                                        *\n *                                                                                             *\n * INPUT:   amount   -- The number of index element spaces to add to its capacity.             *\n *                                                                                             *\n * OUTPUT:  bool; Was the internal capacity increased without error?                           *\n *                                                                                             *\n * WARNINGS:   If there is insufficient RAM, then this routine will fail.                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool IndexClass<T>::Increase_Table_Size(int amount)\n{\n\t/*\n\t**\tCheck size increase parameter for legality.\n\t*/\n\tif (amount < 0) return(false);\n\n\tNodeElement * table = new NodeElement[IndexSize + amount];\n\tif (table != NULL) {\n\n\t\t/*\n\t\t**\tCopy all valid nodes into the new table.\n\t\t*/\n\t\tfor (int index = 0; index < IndexCount; index++) {\n\t\t\ttable[index] = IndexTable[index];\n\t\t}\n\n\t\t/*\n\t\t**\tMake the new table the current one (and delete the old one).\n\t\t*/\n\t\tdelete [] IndexTable;\n\t\tIndexTable = table;\n\t\tIndexSize += amount;\n\t\tInvalidate_Archive();\n\n\t\t/*\n\t\t**\tReturn with success flag.\n\t\t*/\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tFailure to allocate the memory results in a failure to increase\n\t**\tthe size of the index table.\n\t*/\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Count -- Fetch the number of index entries recorded.                         *\n *                                                                                             *\n *    This will return the quantity of index entries that have been recored by this index      *\n *    handler.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with number of recored indecies present.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint IndexClass<T>::Count(void) const\n{\n\treturn(IndexCount);\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Is_Present -- Checks for presense of index entry.                            *\n *                                                                                             *\n *    This routine will scan for the specified index entry. If it was found, then 'true' is    *\n *    returned.                                                                                *\n *                                                                                             *\n * INPUT:   id -- The index ID to search for.                                                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the index entry found in this index handler object?                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool IndexClass<T>::Is_Present(int id) const\n{\n\t/*\n\t**\tIf there are no data elements in the index table, then it can\n\t**\tnever find the specified index. Check for and return failure\n\t**\tin this case.\n\t*/\n\tif (IndexCount == 0) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tCheck to see if this same index element was previously searched for. If\n\t**\tso and it was previously found, then there is no need to search for it\n\t**\tagain -- just return true.\n\t*/\n\tif (Is_Archive_Same(id)) {\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tPerform a binary search on the index nodes in order to look for a\n\t**\tmatching index value.\n\t*/\n\tNodeElement const * nodeptr = Search_For_Node(id);\n\n\t/*\n\t**\tIf a matching index was found, then record it for future reference and return success.\n\t*/\n\tif (nodeptr != 0) {\n\t\t((IndexClass<T> *)this)->Set_Archive(nodeptr);\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tCould not find element so return failure condition.\n\t*/\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Fetch_Index -- Fetch data from specified index.                              *\n *                                                                                             *\n *    This routine will find the specified index and return the data value associated with it. *\n *                                                                                             *\n * INPUT:   id -- The index ID to search for.                                                  *\n *                                                                                             *\n * OUTPUT:  Returns with the data value associated with the index value.                       *\n *                                                                                             *\n * WARNINGS:   This routine presumes that the index exists. If it doesn't exist, then the      *\n *             default constructed object \"T\" is returned instead. To avoid this problem,      *\n *             always verfiy the existance of the index by calling Is_Present() first.         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nT IndexClass<T>::Fetch_Index(int id) const\n{\n\tif (Is_Present(id)) {\n\n\t\t/*\n\t\t**\tCount on the fact that the archive pointer is always valid after a call to Is_Present\n\t\t**\tthat returns \"true\".\n\t\t*/\n\t\treturn(Archive->Data);\n\t}\n\treturn(T());\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Is_Archive_Same -- Checks to see if archive pointer is same as index.        *\n *                                                                                             *\n *    This routine compares the specified index ID with the previously recorded index archive  *\n *    pointer in order to determine if they match.                                             *\n *                                                                                             *\n * INPUT:   id -- The index ID to compare to the archive index object pointer.                 *\n *                                                                                             *\n * OUTPUT:  bool; Does the specified index match the archive pointer?                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool IndexClass<T>::Is_Archive_Same(int id) const\n{\n\tif (Archive != 0 && Archive->ID == id) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Invalidate_Archive -- Invalidate the archive pointer.                        *\n *                                                                                             *\n *    This routine will set the archive pointer to an invalid state. This must be performed    *\n *    if ever the archive pointer would become illegal (such as when the element it refers to  *\n *    is deleted).                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid IndexClass<T>::Invalidate_Archive(void)\n{\n\tArchive = 0;\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Set_Archive -- Records the node pointer into the archive.                    *\n *                                                                                             *\n *    This routine records the specified node pointer. Use this routine when there is a        *\n *    good chance that the specified node will be requested in the immediate future.           *\n *                                                                                             *\n * INPUT:   node  -- Pointer to the node to assign to the archive.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid IndexClass<T>::Set_Archive(NodeElement const * node)\n{\n\tArchive = node;\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Add_Index -- Add element to index tracking system.                           *\n *                                                                                             *\n *    This routine will record the index information into this index manager object. It        *\n *    associates the index number with the data specified. The data is copied to an internal   *\n *    storage location.                                                                        *\n *                                                                                             *\n * INPUT:   id    -- The ID number to associate with the data.                                 *\n *                                                                                             *\n *          data  -- The data to store.                                                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the element added without error? Failure indicates that RAM has been     *\n *                exhausted.                                                                   *\n *                                                                                             *\n * WARNINGS:   The data is COPIED to internal storage. This means that the data object must    *\n *             have a functional and efficient copy constructor and assignment operator.       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool IndexClass<T>::Add_Index(int id, T data)\n{\n\t/*\n\t**\tEnsure that there is enough room to add this index. If not, then increase the\n\t**\tcapacity of the internal index table.\n\t*/\n\tif (IndexCount + 1 > IndexSize) {\n\t\tif (!Increase_Table_Size(IndexSize == 0 ? 10 : IndexSize)) {\n\n\t\t\t/*\n\t\t\t**\tFailure to increase the size of the index table means failure to add\n\t\t\t**\tthe index element.\n\t\t\t*/\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tAdd the data to the end of the index data and then sort the index table.\n\t*/\n\tIndexTable[IndexCount].ID = id;\n\tIndexTable[IndexCount].Data = data;\n\tIndexCount++;\n\tIsSorted = false;\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Remove_Index -- Find matching index and remove it from system.               *\n *                                                                                             *\n *    This will scan through the previously added index elements and if a match was found, it  *\n *    will be removed.                                                                         *\n *                                                                                             *\n * INPUT:   id -- The index ID to search for and remove.                                       *\n *                                                                                             *\n * OUTPUT:  bool; Was the index element found and removed?                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool IndexClass<T>::Remove_Index(int id)\n{\n\t/*\n\t**\tFind the array index into the table that matches the specified id value.\n\t*/\n\tint found_index = -1;\n\tfor (int index = 0; index < IndexCount; index++) {\n\t\tif (IndexTable[index].ID == id) {\n\t\t\tfound_index = index;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the array index was found, then copy all higher index entries\n\t**\tdownward to fill the vacated location. We cannot use memcpy here because the type\n\t**\tobject may not support raw copies. C++ defines the assignment operator to deal\n\t**\twith this, so that is what we use.\n\t*/\n\tif (found_index != -1) {\n\n\t\tfor (int index = found_index+1; index < IndexCount; index++) {\n\t\t\tIndexTable[index-1] = IndexTable[index];\n\t\t}\n\t\tIndexCount--;\n\n\t\tNodeElement fake;\n\t\tfake.ID = 0;\n\t\tfake.Data = T();\n\t\tIndexTable[IndexCount] = fake;\t\t// zap last (now unused) element\n\n\t\tInvalidate_Archive();\n\t\treturn(true);\n\t}\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * compfunc -- Support function for bsearch and bsort.                                         *\n *                                                                                             *\n *    This compare function presumes that its parameters are pointing to NodeElements and that *\n *    the first \"int\" in the node is the index ID number to be used for comparison.            *\n *                                                                                             *\n * INPUT:   ptr1  -- Pointer to first node.                                                    *\n *                                                                                             *\n *          ptr2  -- Pointer to second node.                                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the comparision value between the two nodes.                          *\n *                                                                                             *\n * WARNINGS:   This is highly dependant upon the layout of the NodeElement structure.          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nstatic int _USERENTRY IndexClass<T>::search_compfunc(void const * ptr1, void const * ptr2)\n{\n\tif (*(int const *)ptr1 == *(int const *)ptr2) {\n\t\treturn(0);\n\t}\n\tif (*(int const *)ptr1 < *(int const *)ptr2) {\n\t\treturn(-1);\n\t}\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Search_For_Node -- Perform a search for the specified node ID                *\n *                                                                                             *\n *    This routine will perform a binary search on the previously recorded index values and    *\n *    if a match was found, it will return a pointer to the NodeElement.                       *\n *                                                                                             *\n * INPUT:   id -- The index ID to search for.                                                  *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the NodeElement that matches the index ID specified. If  *\n *          no matching index could be found, then NULL is returned.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nIndexClass<T>::NodeElement const * IndexClass<T>::Search_For_Node(int id) const\n{\n\t/*\n\t**\tIf there are no elements in the list, then it certainly can't find any matches.\n\t*/\n\tif (IndexCount == 0) {\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tIf the list has not yet been sorted, then do so now. Binary searching requires\n\t**\tthe list to be sorted.\n\t*/\n\tif (!IsSorted) {\n\t\tqsort(&IndexTable[0], IndexCount, sizeof(IndexTable[0]), search_compfunc);\n\t\t((IndexClass<T> *)this)->Invalidate_Archive();\n\t\t((IndexClass<T> *)this)->IsSorted = true;\n\t}\n\n\t/*\n\t**\tThis list is sorted and ready to perform a binary search upon it.\n\t*/\n\tNodeElement node;\n\tnode.ID = id;\n\treturn((NodeElement const *)bsearch(&node, &IndexTable[0], IndexCount, sizeof(IndexTable[0]), search_compfunc));\n}\n\n\n#endif\n\n\n"
  },
  {
    "path": "CODE/SEDITDLG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifdef WOLAPI_INTEGRATION\n\n//\tSEditDlg.cpp - \"SimpleEditDlgClass\": An ok/cancel type dialog with 1 or 2 edit boxes.\n//\t\t\t\t\tMostly a hack for what I need right now - not necessarily very flexible.\n//\t\t\t\t\tStill - I can't believe there isn't a set of dialog classes in here already.\n//\tajw 07/21/98\n\n#include \"SEditDlg.h\"\n#include \"WOLEdit.h\"\n\nextern bool cancel_current_msgbox;\nbool disable_current_msgbox = false;\n\n//***********************************************************************************************\nSimpleEditDlgClass::SimpleEditDlgClass( int iDialogWidth, const char* szTitle, const char* szPrompt, int iEditCharsAccept,\n\t\t\t\t\t\t\t\t\t\t\tconst char* szPrompt2 /* = NULL */, int iEditCharsAccept2 /* = 0 */ )\n\t: iDialogWidth( iDialogWidth ), iEditCharsAccept( iEditCharsAccept ), iEditCharsAccept2( iEditCharsAccept2 )\n{\n\t//\tCopy strings.\n\tif( szTitle )\n\t{\n\t\tthis->szTitle = new char[ strlen( szTitle ) + 1 ];\n\t\tstrcpy( this->szTitle, szTitle );\n\t}\n\telse\n\t\tthis->szTitle = NULL;\n\n\tif( szPrompt )\n\t{\n\t\tthis->szPrompt = new char[ strlen( szPrompt ) + 1 ];\n\t\tstrcpy( this->szPrompt, szPrompt );\n\t}\n\telse\n\t\tthis->szPrompt = NULL;\t\t//\tI wouldn't try this ... not totally implemented.\n\n\tif( szPrompt2 )\n\t{\n\t\tthis->szPrompt2 = new char[ strlen( szPrompt2 ) + 1 ];\n\t\tstrcpy( this->szPrompt2, szPrompt2 );\n\t}\n\telse\n\t\tthis->szPrompt2 = NULL;\t\t//\tThis is the flag for whether or not there is a second edit box.\n\n\t*szEdit = 0;\n\t*szEdit2 = 0;\n\n\tszOkButton = Text_String( TXT_OK );\n\tszCancelButton = Text_String( TXT_CANCEL );\n\tszMiddleButton = NULL;\n}\n\n//***********************************************************************************************\nSimpleEditDlgClass::~SimpleEditDlgClass()\n{\n\tdelete [] szTitle;\n\tdelete [] szPrompt;\n\tdelete [] szPrompt2;\n}\n\n//***********************************************************************************************\nvoid SimpleEditDlgClass::SetButtons( const char* szOk, const char* szCancel, const char* szMiddle /*= NULL*/ )\n{\n\tszOkButton = szOk;\n\tszCancelButton = szCancel;\n\tszMiddleButton = szMiddle;\n}\n\n//***********************************************************************************************\nconst char* SimpleEditDlgClass::Show()\n{\n\t//\tShows dialog, returns text of button pressed.\n\t//\tUnless SetButtons() is used, value will be TXT_OK or TXT_CANCEL string values.\n\n\tbool bEscapeDown = false;\n\tbool bReturnDown = false;\n\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tint x_margin = 18 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\tint y_margin = 10 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\tint d_gap_y = 5 * RESFACTOR;\n\n\tint d_dialog_w = iDialogWidth;\n\tint d_dialog_h = szPrompt2 ? ( 29 * RESFACTOR ) + 2 * d_gap_y + 2 * y_margin : ( 19 * RESFACTOR ) + d_gap_y + 2 * y_margin;\n\tif( szTitle )\n\t\td_dialog_h += 10 * RESFACTOR + 2 * d_gap_y;\n\tint d_dialog_x = (((320 * RESFACTOR) - d_dialog_w) / 2);\n\tint d_dialog_y = (((200 * RESFACTOR) - d_dialog_h) / 2);\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// coord of x-center\n\n/*\n\tif( szTitle )\n\t{\n\t\td_title_w = String_Pixel_Width( szTitle );\n\t\td_title_h = 10 * RESFACTOR;\n\t\td_title_x = d_dialog_cx - d_title_w / 2;\n\t\td_title_y = d_dialog_y + d_gap_y;\n\t}\n*/\n\n\tint d_prompt_w = String_Pixel_Width( szPrompt );\n\tint d_prompt_h = 10 * RESFACTOR;\n\tint d_prompt_x = d_dialog_x + x_margin;\n\tint d_prompt_y = szTitle ? ( d_dialog_y + 3 * d_gap_y + 10 * RESFACTOR ) : ( d_dialog_y + d_gap_y );\n\n\tint d_edit_w = d_dialog_w - d_prompt_w - 2 * x_margin;\n\tint d_edit_h = 10 * RESFACTOR;\n\tint d_edit_x = d_dialog_x + d_prompt_w + x_margin;\n\tint d_edit_y = d_prompt_y;\n\n\tint d_prompt2_w = szPrompt2 ? String_Pixel_Width( szPrompt2 ) : 0;\n\tint d_prompt2_h = 10 * RESFACTOR;\n\tint d_prompt2_x = d_dialog_x + x_margin;\n\tint d_prompt2_y = d_prompt_y + d_prompt2_h + d_gap_y;\n\n\tint d_edit2_w = d_dialog_w - d_prompt2_w - 2 * x_margin;\n\tint d_edit2_h = 10 * RESFACTOR;\n\tint d_edit2_x = d_dialog_x + d_prompt2_w + x_margin;\n\tint d_edit2_y = d_prompt2_y;\n\n\tint d_ok_w, d_ok_h,\td_ok_x, d_ok_y, d_cancel_w, d_cancel_h, d_cancel_x, d_cancel_y, d_mid_x, d_mid_y, d_mid_w, d_mid_h;\n\n\tif( !szMiddleButton )\n\t{\n\t\td_ok_w = 40 * RESFACTOR;\n\t\td_ok_h = 9 * RESFACTOR;\n\t\td_ok_x = d_dialog_cx - d_ok_w - 10 * RESFACTOR;\n\t\td_ok_y = d_dialog_y + d_dialog_h - d_ok_h - y_margin;\n\n\t\td_cancel_w = 40 * RESFACTOR;\n\t\td_cancel_h = 9 * RESFACTOR;\n\t\td_cancel_x = d_dialog_cx + 10 * RESFACTOR;\n\t\td_cancel_y = d_ok_y;\n\t}\n\telse\n\t{\n\t\td_ok_w = 40 * RESFACTOR;\n\t\td_ok_h = 9 * RESFACTOR;\n\t\td_ok_x = d_dialog_cx - d_ok_w - 30 * RESFACTOR;\n\t\td_ok_y = d_dialog_y + d_dialog_h - d_ok_h - y_margin;\n\n\t\td_mid_w = 40 * RESFACTOR;\n\t\td_mid_h = 9 * RESFACTOR;\n\t\td_mid_x = d_dialog_cx - ( d_mid_w / 2 );\n\t\td_mid_y = d_ok_y;\n\n\t\td_cancel_w = 40 * RESFACTOR;\n\t\td_cancel_h = 9 * RESFACTOR;\n\t\td_cancel_x = d_dialog_cx + 30 * RESFACTOR;\n\t\td_cancel_y = d_ok_y;\n\t}\n\n\t/*\n\t**\tButton enumerations\n\t*/\n\tenum {\n\t\tBUTTON_OK = 100,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_MIDDLE,\n\t\tBUTTON_EDIT,\n\t\tBUTTON_EDIT2\n\t};\n\n\t/*\n\t**\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*\n\t**\tDialog variables\n\t*/\n\tconst char* szReturn = NULL;\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass* commands = NULL;\t\t// the button list\n\n\tTextButtonClass OkBtn( BUTTON_OK, szOkButton, TPF_BUTTON, d_ok_x, d_ok_y, d_ok_w );\n\tTextButtonClass CancelBtn( BUTTON_CANCEL, szCancelButton, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w );\n\tTextButtonClass MiddleBtn( BUTTON_MIDDLE, szMiddleButton, TPF_BUTTON, d_mid_x, d_mid_y, d_mid_w );\n\n\tWOLEditClass EditBox( BUTTON_EDIT, szEdit, min( sizeof(szEdit), iEditCharsAccept ), TPF_6PT_GRAD|TPF_NOSHADOW, \n\t\t\t\t\t\t\td_edit_x, d_edit_y, d_edit_w, -1, EditClass::ALPHANUMERIC );\n\tWOLEditClass EditBox2( BUTTON_EDIT2, szEdit2, min( sizeof(szEdit2), iEditCharsAccept2 ), TPF_6PT_GRAD|TPF_NOSHADOW, \n\t\t\t\t\t\t\td_edit2_x, d_edit2_y, d_edit2_w, -1, EditClass::ALPHANUMERIC );\n\n\t/*\n\t**\tInitialize.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tCreate the button list.\n\t*/\n\tcommands = &OkBtn;\n\tCancelBtn.Add_Tail(*commands);\n\tif( szMiddleButton )\n\t\tMiddleBtn.Add_Tail(*commands);\n\tEditBox.Add_Tail(*commands);\n\tif( szPrompt2 )\n\t\tEditBox2.Add_Tail(*commands);\n\tEditBox.Set_Focus();\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tKeyboard->Clear();\n\tbool firsttime = true;\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tCall_Back();\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = true;\n\t\t}\n\t\t#endif\n\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\n\t\t\t/*\n\t\t\t**\tDisplay the dialog box.\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tif (display) {\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\t\t\t\tif( szTitle )\n\t\t\t\t\tDraw_Caption( szTitle, d_dialog_x, d_dialog_y, d_dialog_w );\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRedraw the buttons.\n\t\t\t*/\n\t\t\tif (display) {\n\t\t\t\tFancy_Text_Print( szPrompt, d_prompt_x, d_prompt_y,\n\t\t\t\t\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT );\n\t\t\t\tif( szPrompt2 )\n\t\t\t\t\tFancy_Text_Print( szPrompt2, d_prompt2_x, d_prompt2_y,\n\t\t\t\t\t\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT );\n\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t**\tThe first time through the processing loop, set the edit\n\t\t**\tgadget to have the focus. The\n\t\t**\tfocus must be set here since the gadget list has changed\n\t\t**\tand this change will cause any previous focus setting to be\n\t\t**\tcleared by the input processing routine.\n\t\t*/\n\t\tif (firsttime ) {\n\t\t\tfirsttime = false;\n\t\t\tEditBox.Set_Focus();\n\t\t\tEditBox.Flag_To_Redraw();\n\t\t}\n\n\t\t//\tMy hack for triggering escape and return on key up instead of down...\n\t\t//\tThe problem that was occurring was that the calling dialog would act on the key up,\n\t\t//\tthough this dialog handled the key down. ajw\n\t\tif( ( ::GetAsyncKeyState( VK_ESCAPE ) & 0x8000 ) )\n\t\t{\n\t\t\tbEscapeDown = true;\n\t\t}\n\t\telse if( bEscapeDown )\n\t\t{\n\t\t\tinput = (KeyNumType)( BUTTON_CANCEL | KN_BUTTON );\n\t\t\tbEscapeDown = false;\n\t\t}\n\t\tif( ( ::GetAsyncKeyState( VK_RETURN ) & 0x8000 ) )\n\t\t{\n\t\t\tbReturnDown = true;\n\t\t}\n\t\telse if( bReturnDown )\n\t\t{\n\t\t\tinput = (KeyNumType)( BUTTON_OK | KN_BUTTON );\n\t\t\tbReturnDown = false;\n\t\t}\n\n\t\t//\tI really hate to do this, but...      ajw\n\t\tif( cancel_current_msgbox )\n\t\t{\n\t\t\tcancel_current_msgbox = false;\n\t\t\tinput = (KeyNumType)( BUTTON_CANCEL | KN_BUTTON );\n\t\t}\n\n\t\tif( disable_current_msgbox )\n\t\t{\n\t\t\tdisable_current_msgbox = false;\n\t\t\tEditBox.Disable();\n\t\t\t//\tThese do not actually draw. I am actually clearing the \"draw\" flag!\n\t\t\t//\tProblem is Disable sets them to redraw, and I don't want to, and there is no Flag_To_Redraw( false ).\n\t\t\tEditBox.GadgetClass::Draw_Me( true );\n\t\t\tif( szPrompt2 )\n\t\t\t{\n\t\t\t\tEditBox2.Disable();\n\t\t\t\tEditBox2.GadgetClass::Draw_Me( true );\n\t\t\t}\n\t\t\tOkBtn.Disable();\n\t\t\tOkBtn.GadgetClass::Draw_Me( true );\n\t\t\tCancelBtn.Disable();\n\t\t\tCancelBtn.GadgetClass::Draw_Me( true );\n\t\t\tif( szMiddleButton )\n\t\t\t{\n\t\t\t\tMiddleBtn.Disable();\n\t\t\t\tMiddleBtn.GadgetClass::Draw_Me( true );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tProcess input.\n\t\t*/\n\t\tswitch( input )\n\t\t{\n//\t\tcase ( KN_ESC ):\n\t\tcase ( BUTTON_CANCEL | KN_BUTTON ):\n\t\t\tszReturn = szCancelButton;\n\t\t\tprocess = false;\n\t\t\tbreak;\n\n//\t\tcase KN_RETURN:\n\t\tcase ( BUTTON_EDIT | KN_BUTTON ):\t\t\t//\t(Return pressed while on edit.)\n\t\tcase ( BUTTON_OK | KN_BUTTON ):\n\t\t\tszReturn = szOkButton;\n\t\t\tprocess = false;\n\t\t\tbreak;\n\n\t\tcase ( BUTTON_MIDDLE | KN_BUTTON ):\n\t\t\tszReturn = szMiddleButton;\n\t\t\tprocess = false;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn szReturn;\n}\n\n#endif\n"
  },
  {
    "path": "CODE/SEDITDLG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifdef WOLAPI_INTEGRATION\n\n//\tSEditDlg.h - \"SimpleEditDlgClass\": An ok/cancel type dialog with a single edit box.\n//\tajw 07/21/98\n\n#include \"function.h\"\n\nclass SimpleEditDlgClass\n{\npublic:\n\tSimpleEditDlgClass( int iDialogWidth, const char* szTitle, const char* szPrompt, int iEditCharsAccept,\n\t\t\t\t\t\t\tconst char* szPrompt2 = NULL, int iEditCharsAccept2 = 0 );\n\tvirtual ~SimpleEditDlgClass();\n\n\tconst char* Show();\t\t\t\t\t//\tShows dialog, returns text of button pressed.\n\t\t\t\t\t\t\t\t\t\t//\tUnless SetButtons() is used, value will be TXT_OK or TXT_CANCEL string values.\n\n\tvoid\t\tSetButtons( const char* szOk, const char* szCancel, const char* szMiddle = NULL );\n\n\tchar\t\tszEdit[ 300 ];\t\t\t//\tiEditCharsAccept upper limit.\n\tchar\t\tszEdit2[ 300 ];\n\nprotected:\n\tint\t\t\tiDialogWidth;\t\t\t//\tX pixels width of entire dialog.\n\tchar*\t\tszTitle;\t\t\t\t//\tTitle of dialog, or NULL for no title.\n\n\tchar*\t\tszPrompt;\t\t\t\t//\tText appearing to the left of edit box.\n\tint\t\t\tiEditCharsAccept;\t\t//\tMax length of string allowed in edit, includes null-terminator.\n\n\tchar*\t\tszPrompt2;\n\tint\t\t\tiEditCharsAccept2;\n\n\tconst char*\tszOkButton;\t\t\t\t//\tText of button that acts like an Ok button. Appears on left.\n\tconst char*\tszCancelButton;\t\t\t//\tText of button that acts like an Cancel button. Appears on right.\n\tconst char* szMiddleButton;\t\t\t//\tOptional middle button text. Null = no middle button.\n};\n\n#endif\n"
  },
  {
    "path": "CODE/SENDFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/*************************************************************************************\n **   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                  **\n *************************************************************************************\n *                                                                                   *\n *                 Project Name : Command & Conquer - Red Alert                      *\n *                                                                                   *\n *                    File Name : SENDFILE.CPP                                       *\n *                                                                                   *\n *                   Programmer : Steve Tall                                         *\n *                                                                                   *\n *                   Start Date : Audust 20th, 1996                                  *\n *                                                                                   *\n *                  Last Update : August 20th, 1996 [ST]                             *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Overview:                                                                         *\n *                                                                                   *\n *  Functions for scenario file transfer between machines                            *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Functions:                                                             \t \t\t\t*\n *                                                                         \t\t\t\t*\n *                                                                         \t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"function.h\"\n\n//#include \"WolDebug.h\"\n\n#ifdef WINSOCK_IPX\n#include \"WSProto.h\"\n#else\n\n#ifdef WIN32\n#include\t\"tcpip.h\"\n#else\n#include\t\"fakesock.h\"\n#endif\t//WIN32\n\n#endif\t//WINSOCK_IPX\n\nbool Receive_Remote_File ( char *file_name, unsigned int file_length, int gametype);\nbool Send_Remote_File ( char *file_name, int gametype );\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern bool Is_Mission_Counterstrike (char *file_name);\nextern bool Is_Mission_Aftermath (char *file_name);\n#endif\n\n#define RESPONSE_TIMEOUT\t60*60\n\n#ifdef WOLAPI_INTEGRATION\n#include \"WolapiOb.h\"\nextern WolapiObject* pWolapi;\n#endif\n\n/***********************************************************************************************\n * Get_Scenario_File_From_Host -- Initiates download of scenario file from game host           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to buffer to copy file name into                                              *\n *           game type - 0 for modem/null modem, 1 otherwise                                   *\n *                                                                                             *\n * OUTPUT:   true if file sucessfully downloaded                                               *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/22/96 3:06PM ST : Created                                                              *\n *=============================================================================================*/\nbool Get_Scenario_File_From_Host(char *return_name, int gametype)\n{\n\t//WWDebugString (\"RA95 - In Get_Scenario_From_Host\\n\");\n\n\tunsigned int file_length;\n\n\tSerialPacketType \tsend_packet;\n\tSerialPacketType \treceive_packet;\n\tGlobalPacketType\tnet_send_packet;\n\tGlobalPacketType\tnet_receive_packet;\n\tunsigned int\t\tpacket_len;\n\tunsigned short\t\tproduct_id;\n\n\tIPXAddressClass\tsender_address;\n\n\tCDTimerClass<SystemTimerClass> response_timer;\t\t// timeout timer for waiting for responses\n\n\t/*\n\t** Send the scenario request using guaranteed delivery.\n\t*/\n\tif (!gametype) {\n\t\tmemset ((void*)&send_packet, 0, sizeof (send_packet));\n\t\tsend_packet.Command = SERIAL_REQ_SCENARIO;\n\t\tNullModem.Send_Message (&send_packet, sizeof(send_packet), 1);\n\t} else {\n\t\tmemset ((void*)&net_send_packet, 0, sizeof (net_send_packet));\n\t\tnet_send_packet.Command = NET_REQ_SCENARIO;\n\t\tIpx.Send_Global_Message (&net_send_packet, sizeof (net_send_packet),\n\t\t\t1, &(Session.HostAddress) );\n\t}\n\n\n\n\t//WWDebugString (\"RA95 - Waiting for response from host\\n\");\n\n\t/*\n\t** Wait for host to respond with a file info packet\n\t*/\n\tresponse_timer = RESPONSE_TIMEOUT;\n\tif (!gametype){\n\t\tdo {\n\t\t\tNullModem.Service();\n\n\t\t\tif (NullModem.Get_Message ((void*)&receive_packet, (int*)&packet_len) > 0) {\n\n\t\t\t\tif (receive_packet.Command == SERIAL_FILE_INFO){\n\t\t\t\t\tstrcpy (return_name, receive_packet.ScenarioInfo.ShortFileName);\n\t\t\t\t\tfile_length = receive_packet.ScenarioInfo.FileLength;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} while ( response_timer );\n\t}else{\n\t\tdo {\n\t\t\tIpx.Service();\n\t\t\tint receive_packet_length = sizeof (net_receive_packet);\n\t\t\tif (Ipx.Get_Global_Message (&net_receive_packet, &receive_packet_length,\n\t\t\t\t&sender_address, &product_id)){\n\n//WWDebugString (\"RA95 - Got packet from host\\n\");\n#ifdef WINSOCK_IPX\n\t\t\t\tif (net_receive_packet.Command == NET_FILE_INFO && sender_address == Session.HostAddress) {\n#else\t//WINSOCK_IPX\n\t\t\t\tif (net_receive_packet.Command == NET_FILE_INFO &&\n\t\t\t\t\t\t(Winsock.Get_Connected() || sender_address == Session.HostAddress)){\n#endif\t//WINSOCK_IPX\n\t\t\t\t\tstrcpy (return_name, net_receive_packet.ScenarioInfo.ShortFileName);\n\t\t\t\t\tfile_length = net_receive_packet.ScenarioInfo.FileLength;\n//WWDebugString (\"RA95 - Got file info packet from host\\n\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\tif( Session.Type == GAME_INTERNET && pWolapi && ( ::timeGetTime() > pWolapi->dwTimeNextWolapiPump ) )\n\t\t\t{\n\t\t\t\tpWolapi->pChat->PumpMessages();\n\t\t\t\tpWolapi->dwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT;\n\t\t\t}\n#endif\n\t\t} while ( response_timer );\n\t}\n\n//char rt[80];\n//sprintf (rt, \"RA95 - response_timer = %d\\n\", response_timer );\n//WWDebugString (rt);\n\n\t/*\n\t** If we timed out then something horrible has happened to the other player so just\n\t** return failure.\n\t*/\n\tif (!response_timer) return (false);\n\n//\tdebugprint( \"about to download '%s'\\n\", return_name );\n\n\t/*\n\t** Receive the file from the host\n\t*/\n\treturn (Receive_Remote_File ( return_name, file_length, gametype));\n}\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Receive_Remote_File -- Handles incoming file download packets from the game host            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    file name to save as                                                              *\n *           length of file to expect                                                          *\n *           game type - 0 for modem/null modem, 1 otherwise                                   *\n *                                                                                             *\n * OUTPUT:   true if file downloaded was completed                                             *\n *                                                                                             *\n * WARNINGS: This fuction can modify the file name passed in                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   8/22/96 3:07PM ST : Created                                                               *\n *=============================================================================================*/\nbool Receive_Remote_File ( char *file_name, unsigned int file_length, int gametype)\n{\n\n\t//WWDebugString (\"RA95 - In Receive_Remote_File\\n\");\n\tunsigned short\t\tproduct_id;\n\tIPXAddressClass\tsender_address;\n\n\t/*\n\t** Dialog & button dimensions\n\t*/\n\tint d_dialog_w = 200 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 90*RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320*RESFACTOR - d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\tint d_dialog_y = ((200*RESFACTOR - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_margin1=10;\n\tint d_txt6_h=15;\n\n#if (GERMAN | FRENCH)\n\tint d_cancel_w = 50*RESFACTOR;\n#else\n\tint d_cancel_w = 40*RESFACTOR;\n#endif\n\tint d_cancel_h = 9*RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - d_cancel_w / 2;\n\tint d_cancel_y = d_dialog_y + d_dialog_h - 20*RESFACTOR;\n\n\tint d_progress_w = 100*RESFACTOR;\n\tint d_progress_h = 10*RESFACTOR;\n\tint d_progress_x = (SeenBuff.Get_Width()/2) - d_progress_w/2;\n\tint d_progress_y = d_dialog_y + 45*RESFACTOR;\n\n\tint\twidth;\n\tint\theight;\n\n\tchar *info_string = (char*)Text_String (TXT_RECEIVING_SCENARIO);\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tTBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\tFormat_Window_String(info_string, SeenBuff.Get_Height(), width, height);\n\n\n\t/*\n\t** Button Enumerations\n\t*/\n\tenum {\n\t\tBUTTON_CANCEL = 100,\n\t\tBUTTON_PROGRESS\n\t};\n\n\t/*\n\t** Buttons\n\t*/\n\t//TextButtonClass *buttons;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,\n\t\tTPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n#if (GERMAN | FRENCH)\n\t\td_cancel_x, d_cancel_y);\n#else\n\t\td_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n#endif\n\n\tGaugeClass progress_meter (BUTTON_PROGRESS,\n\t\td_progress_x, d_progress_y, d_progress_w, d_progress_h);\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tTBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PROGRESS,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\n\tbool \t\t\tprocess = true;\n\tRedrawType \tdisplay = REDRAW_ALL;\t\t// redraw level\n\tKeyNumType \tinput;\n\tGadgetClass *commands;\t\t\t\t\t// button list\n\tbool\t\t\treturn_code;\n\tint\t\t\tupdate_time = 0;\n\n\n\n\tRemoteFileTransferType receive_packet;\n\n\tint \t\t\t\tlast_received_block = -1;\t\t//No blocks received yet\n\tunsigned int \ttotal_length = 0;\n\tunsigned int\tpacket_len;\n\n\t/*\n\t** If the file name is already in use, use the temp file name\n\t*/\n\tCCFileClass test_file (file_name);\n\tif (test_file.Is_Available()){\n\t\tstrcpy (file_name, \"DOWNLOAD.TMP\");\n\t}\n\n\tRawFileClass save_file (file_name);\n\n\t/*\n\t** If the file already exists then delete it and re-create it.\n\t*/\n\tif (save_file.Is_Available()) save_file.Delete();\n\n\t/*\n\t** Open the file for write\n\t*/\n\tsave_file.Open ( WRITE );\n\n\tcommands = &cancelbtn;\n\tcommands->Add_Tail (progress_meter);\n\n\tprogress_meter.Set_Maximum(100);\t\t// Max is 100%\n\tprogress_meter.Set_Value(0);\t\t\t// Current is 0%\n\n\t/*\n\t** Wait for all the blocks to arrive\n\t*/\n\n\tdo\t{\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n#endif\n\n#ifdef WOLAPI_INTEGRATION\n\t\tif( Session.Type == GAME_INTERNET && pWolapi && ( ::timeGetTime() > pWolapi->dwTimeNextWolapiPump ) )\n\t\t{\n\t\t\tpWolapi->pChat->PumpMessages();\n\t\t\tpWolapi->dwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT;\n\t\t}\n#endif\n\n\t\tif (display){\n\n\t\t\tif (display >= REDRAW_BACKGROUND){\n\n\t\t\t\tHide_Mouse();\n\t\t\t\t/*\n\t\t\t\t** Redraw backgound & dialog box\n\t\t\t\t*/\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tSet_Palette(CCPalette);\n\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t/*\n\t\t\t\t** Dialog & Field labels\n\t\t\t\t*/\n\t\t\t\tDraw_Caption (TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);\n\n\t\t\t\tFancy_Text_Print(info_string, d_dialog_cx-width/2, d_dialog_y + 25*RESFACTOR,\n\t\t\t\t\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\t\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);\n\n\t\t\t\tShow_Mouse();\n\n\t\t\t}\n\n\t\t\tif (display >= REDRAW_BUTTONS){\n\n\t\t\t\tcommands->Draw_All();\n\n\t\t\t}\n\n\t\t\tif (display >= REDRAW_PROGRESS){\n\t\t\t\tprogress_meter.Draw_Me(true);\n\t\t\t}\n\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\n\t\tif (!gametype){\n\t\t\tNullModem.Service();\n\n\t\t\tif (NullModem.Get_Message ((void*)&receive_packet, (int*)&packet_len) > 0) {\n\n\t\t\t\tif (receive_packet.Command == NET_FILE_CHUNK){\n\n\t\t\t\t\tif (receive_packet.BlockNumber == last_received_block + 1){\n\n\t\t\t\t\t\tsave_file.Write ( receive_packet.RawData, receive_packet.BlockLength );\n\t\t\t\t\t\ttotal_length += receive_packet.BlockLength;\n\t\t\t\t\t\tlast_received_block ++;\n\n\t\t\t\t\t\tupdate_time++;\n\t\t\t\t\t\tif (update_time >7){\n\t\t\t\t\t\t\tprogress_meter.Set_Value ( (total_length*100) / file_length );\n\t\t\t\t\t\t\tdisplay = REDRAW_PROGRESS;\n\t\t\t\t\t\t\tupdate_time = 0;;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (total_length >= file_length){\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\treturn_code = true;\n\t\t\t\t\t\t\tprogress_meter.Set_Value ( 100 );\n\t\t\t\t\t\t\tprogress_meter.Draw_Me(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\tIpx.Service();\n\n\t\t\tint receive_packet_len = sizeof (receive_packet);\n\t\t\tif (Ipx.Get_Global_Message (&receive_packet, &receive_packet_len,\n\t\t\t\t&sender_address, &product_id)){\n\n#ifdef WINSOCK_IPX\n\t\t\t\tif (receive_packet.Command == NET_FILE_CHUNK && sender_address == Session.HostAddress){\n#else\t//WINSOCK_IPX\n\t\t\t\tif (receive_packet.Command == NET_FILE_CHUNK &&\n\t\t\t\t\t\t\t(Winsock.Get_Connected() || sender_address == Session.HostAddress)){\n#endif\t//WINSOCK_IPX\n\n\t\t\t\t\tif (receive_packet.BlockNumber == last_received_block + 1){\n\n\t\t\t\t\t\tsave_file.Write ( receive_packet.RawData, receive_packet.BlockLength );\n\t\t\t\t\t\ttotal_length += receive_packet.BlockLength;\n\t\t\t\t\t\tlast_received_block ++;\n\n\t\t\t\t\t\tupdate_time++;\n\t\t\t\t\t\tif (update_time >7){\n\t\t\t\t\t\t\tprogress_meter.Set_Value ( (total_length*100) / file_length );\n\t\t\t\t\t\t\tdisplay = REDRAW_PROGRESS;\n\t\t\t\t\t\t\tupdate_time = 0;;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (total_length >= file_length){\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\treturn_code = true;\n\t\t\t\t\t\t\tprogress_meter.Set_Value ( 100 );\n\t\t\t\t\t\t\tprogress_meter.Draw_Me(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\n\t\tif (process){\n\t\t\tinput = cancelbtn.Input();\n\n\t\t\t/*\n\t\t\t---------------------------- Process input ----------------------------\n\t\t\t*/\n\t\t\tswitch (input) {\n\n\t\t\t\t/*\n\t\t\t\t** Cancel. Just return to the main menu\n\t\t\t\t*/\n\t\t\t\tcase (KN_ESC):\n\t\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\t\tprocess = false;\n\t\t\t\t\treturn_code = false;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\n\t} while ( process );\n\n\tsave_file.Close();\n\n\t/*\n\t** Update the internal list of scenarios to include the downloaded one so we know about it\n\t**  for the next game.\n\t*/\n\tSession.Read_Scenario_Descriptions();\n\n\treturn (return_code);\n}\n\n\n\n\n\n\n/***********************************************************************************************\n * Send_Remote_File -- Sends a file to game clients                                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    File name                                                                         *\n *                                                                                             *\n * OUTPUT:   true if file transfer was successfully completed                                  *\n *           game type - 0 for modem/null modem, 1 otherwise                                   *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/22/96 3:09PM ST : Created                                                              *\n *=============================================================================================*/\nbool Send_Remote_File ( char *file_name, int gametype )\n{\n\t//WWDebugString (\"RA95 - In Send_Remote_File\\n\");\n\n\t/*\n\t** Dialog & button dimensions\n\t*/\n\tint factor\t\t\t= (SeenBuff.Get_Width() == 320) ? 1 : 2;\n\n\tint d_dialog_w = 240 *factor;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 90*factor;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320*factor - d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\tint d_dialog_y = ((200*factor - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_margin1=10;\n\tint d_txt6_h=15;\n\n#if (GERMAN | FRENCH)\n\tint d_cancel_w = 50*factor;\n#else\n\tint d_cancel_w = 40*factor;\n#endif\n\tint d_cancel_h = 9*factor;\n\tint d_cancel_x = d_dialog_cx - d_cancel_w / 2;\n\tint d_cancel_y = d_dialog_y + d_dialog_h - 20*factor;\n\n\tint d_progress_w = 100*factor;\n\tint d_progress_h = 10*factor;\n\tint d_progress_x = (SeenBuff.Get_Width()/2) - d_progress_w/2;\n\tint d_progress_y = d_dialog_y + 45*factor;\n\n\tint\twidth;\n\tint\theight;\n\n\tchar *info_string = (char*)Text_String (TXT_SENDING_SCENARIO);\n\n\tCDTimerClass<SystemTimerClass> response_timer;\t\t// timeout timer for waiting for responses\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tTBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\tFormat_Window_String(info_string, SeenBuff.Get_Height(), width, height);\n\n\n\t/*\n\t** Button Enumerations\n\t*/\n\tenum {\n\t\tBUTTON_CANCEL = 100,\n\t\tBUTTON_PROGRESS\n\t};\n\n\t/*\n\t** Buttons\n\t*/\n\t//TextButtonClass *buttons;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,\n\t\tTPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n#if (GERMAN | FRENCH)\n\t\td_cancel_x, d_cancel_y);\n#else\n\t\td_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n#endif\n\n\tGaugeClass progress_meter (BUTTON_PROGRESS,\n\t\td_progress_x, d_progress_y, d_progress_w, d_progress_h);\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tTBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PROGRESS,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\n\tbool \t\t\tprocess = true;\n\tRedrawType \tdisplay = REDRAW_ALL;\t\t// redraw level\n\tKeyNumType \tinput;\n\tGadgetClass *commands;\t\t\t\t\t// button list\n\tbool\t\t\treturn_code;\n\tint\t\t\tupdate_time = 0;\n\n\n\tint file_length;\n\tint block_number;\n\tint max_chunk_size;\n\tint total_blocks;\n\tint bytes_left;\n\n\tvoid *read_ptr;\n\n\tRemoteFileTransferType\tsend_packet;\n\tSerialPacketType\t\t\tfile_info;\n\tGlobalPacketType\t\t\tnet_file_info;\n\n\n\tCCFileClass send_file (file_name);\n\n\tif ( !send_file.Is_Available() ){\n\t\t//WWDebugString (\"RA95 - Error - could not find file to send to client\\n\");\n//\t\tdebugprint(\"RA95 - Error - could not find file to send to client\\n\");\n\t\treturn (false);\n\t}\n\tfile_length = send_file.Size();\n\n\tresponse_timer = RESPONSE_TIMEOUT;\n\n\t/*\n\t** Send the file info to the remote machine(s)\n\t*/\n\tif (!gametype){\n\t\tfile_info.Command = SERIAL_FILE_INFO;\n\t\tstrcpy (&file_info.ScenarioInfo.ShortFileName[0], file_name);\n#ifdef FIXIT_VERSION_3\n\t\t//\tIf we're sending an official map, always send it to 'download.tmp'.\n\t\tif( Is_Mission_Counterstrike( file_name ) || Is_Mission_Aftermath( file_name ) ) {\n\t\t\tstrcpy (&file_info.ScenarioInfo.ShortFileName[0], \"DOWNLOAD.TMP\");\n\t\t}\n#else\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// If we're sending an Aftermath map, always send it to 'download.tmp'.\n\t\tif (Is_Mission_Aftermath(file_name)) {\n\t\t\tstrcpy (&file_info.ScenarioInfo.ShortFileName[0], \"DOWNLOAD.TMP\");\n\t\t}\n#endif\n#endif\n\t\tfile_info.ScenarioInfo.FileLength = file_length;\n\t\tNullModem.Send_Message (&file_info, sizeof (file_info), 1);\n\t\twhile (NullModem.Num_Send() > 0 && response_timer){\n\t\t\tNullModem.Service();\n\t\t}\n\t} else {\n\t\tnet_file_info.Command = NET_FILE_INFO;\n\t\tstrcpy (&net_file_info.ScenarioInfo.ShortFileName[0], file_name);\n//\t\tdebugprint( \"Uploading '%s'\\n\", file_name );\n#ifdef FIXIT_VERSION_3\n\t\t//\tIf we're sending an official map, always send it to 'download.tmp'.\n\t\tif( Is_Mission_Counterstrike( file_name ) || Is_Mission_Aftermath( file_name ) ) {\n\t\t\tstrcpy (&net_file_info.ScenarioInfo.ShortFileName[0], \"DOWNLOAD.TMP\");\n\t\t}\n#else\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// If we're sending an Aftermath map, always send it to 'download.tmp'.\n\t\tif (Is_Mission_Aftermath(file_name)) {\n\t\t\tstrcpy (&file_info.ScenarioInfo.ShortFileName[0], \"DOWNLOAD.TMP\");\n\t\t\t//\tThere was a bug here: s/b net_file_info. This means that players that don't have Aftermath could have been \n\t\t\t//\taccumulating Aftermath maps all this time!!! (File wasn't getting renamed to \"DOWNLOAD.TMP\".)\n\t\t}\n#endif\n#endif\n//\t\tdebugprint( \"ShortFileName is '%s'\\n\", net_file_info.ScenarioInfo.ShortFileName );\n\t\tnet_file_info.ScenarioInfo.FileLength = file_length;\n\n\t\tfor (int i=0 ; i<Session.RequestCount ; i++){\n\t\t\tIpx.Send_Global_Message (&net_file_info, sizeof (GlobalPacketType),\n\t\t\t\t1, &(Session.Players[Session.ScenarioRequests[i]]->Address) );\n\t\t}\n\n\t\twhile (Ipx.Global_Num_Send() > 0 && response_timer) {\n\t\t\tIpx.Service();\n\t\t}\n\t}\n\n\n\tmax_chunk_size = MAX_SEND_FILE_PACKET_SIZE;\n\ttotal_blocks = (file_length + max_chunk_size-1) / max_chunk_size;\n\tbytes_left = file_length;\n\n\tsend_file.Open ( READ );\n\n\n\tcommands = &cancelbtn;\n\tcommands->Add_Tail (progress_meter);\n\n\tprogress_meter.Set_Maximum(100);\t\t// Max is 100%\n\tprogress_meter.Set_Value(0);\t\t\t// Current is 0%\n\n\n\tblock_number = 0;\n\n\twhile ( process ){\n\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n#endif\n\n#ifdef WOLAPI_INTEGRATION\n\t\tif( Session.Type == GAME_INTERNET && pWolapi && ( ::timeGetTime() > pWolapi->dwTimeNextWolapiPump ) )\n\t\t{\n\t\t\tpWolapi->pChat->PumpMessages();\n\t\t\tpWolapi->dwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT;\n\t\t}\n#endif\n\n\t\tif (display){\n\n\t\t\tif (display >= REDRAW_BACKGROUND){\n\n\t\t\t\tHide_Mouse();\n\t\t\t\t/*\n\t\t\t\t** Redraw backgound & dialog box\n\t\t\t\t*/\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tSet_Palette(CCPalette);\n\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t/*\n\t\t\t\t** Dialog & Field labels\n\t\t\t\t*/\n\t\t\t\tDraw_Caption (TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);\n\n\t\t\t\tFancy_Text_Print(info_string, d_dialog_cx-width/2, d_dialog_y + 25*factor,\n\t\t\t\t\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\t\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);\n\n\t\t\t\tShow_Mouse();\n\n\t\t\t}\n\n\t\t\tif (display >= REDRAW_BUTTONS){\n\n\t\t\t\tcommands->Draw_All();\n\n\t\t\t}\n\n\t\t\tif (display >= REDRAW_PROGRESS){\n\t\t\t\tprogress_meter.Draw_Me(true);\n\t\t\t}\n\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\n\t\tif (!gametype){\n\t\t\tNullModem.Service();\n\n\n\t\t\tif (block_number < total_blocks){\n\n\t\t\t\tif ( NullModem.Num_Send() <2 ){\n\n\t\t\t\t\tsend_packet.Command = SERIAL_FILE_CHUNK;\n\t\t\t\t\tsend_packet.BlockNumber = block_number;\n\t\t\t\t\tsend_packet.BlockLength = MIN (file_length, max_chunk_size);\n\n\t\t\t\t\tfile_length -= send_packet.BlockLength;\n\n\t\t\t\t\tread_ptr = &send_packet.RawData[0];\n\n\t\t\t\t\tif (send_file.Read (read_ptr , send_packet.BlockLength) == send_packet.BlockLength){\n\t\t\t\t\t\tNullModem.Send_Message ((void*)&send_packet, sizeof(send_packet), 1);\n\t\t\t\t\t}\n\n\t\t\t\t\tblock_number++;\n\n\t\t\t\t\tupdate_time++;\n\t\t\t\t\tif (update_time >7){\n\t\t\t\t\t\tprogress_meter.Set_Value ( (block_number*100) / total_blocks );\n\t\t\t\t\t\tdisplay = REDRAW_PROGRESS;\n\t\t\t\t\t\tupdate_time = 0;;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tif (NullModem.Num_Send() == 0){\n\t\t\t\t\tprocess = false;\n\t\t\t\t\treturn_code = true;\n\t\t\t\t\tprogress_meter.Set_Value ( 100 );\n\t\t\t\t\tprogress_meter.Draw_Me(true);\n\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t}else{\n\t\t\tIpx.Service();\n\n\t\t\tif (block_number < total_blocks){\n\n\t\t\t\tif ( Ipx.Global_Num_Send() == 0 ){\n\n\t\t\t\t\tsend_packet.Command = SERIAL_FILE_CHUNK;\n\t\t\t\t\tsend_packet.BlockNumber = block_number;\n\t\t\t\t\tsend_packet.BlockLength = MIN (file_length, max_chunk_size);\n\n\t\t\t\t\tfile_length -= send_packet.BlockLength;\n\n\t\t\t\t\tread_ptr = &send_packet.RawData[0];\n\n\t\t\t\t\tif (send_file.Read (read_ptr , send_packet.BlockLength) == send_packet.BlockLength){\n\t\t\t\t\t\tfor (int i=0 ; i<Session.RequestCount ; i++){\n\t\t\t\t\t\t\tIpx.Send_Global_Message (&send_packet, sizeof (send_packet),\n\t\t\t\t\t\t\t\t1, &(Session.Players[Session.ScenarioRequests[i]]->Address) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tblock_number++;\n\n\t\t\t\t\tupdate_time++;\n\t\t\t\t\tif (update_time >7){\n\t\t\t\t\t\tprogress_meter.Set_Value ( (block_number*100) / total_blocks );\n\t\t\t\t\t\tdisplay = REDRAW_PROGRESS;\n\t\t\t\t\t\tupdate_time = 0;;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tif (Ipx.Global_Num_Send() == 0){\n\t\t\t\t\tprocess = false;\n\t\t\t\t\treturn_code = true;\n\t\t\t\t\tprogress_meter.Set_Value ( 100 );\n\t\t\t\t\tprogress_meter.Draw_Me(true);\n\t\t\t\t}\n\t\t\t}\n\n\n\n\t\t}\n\n\n\t\tif (process){\n\t\t\tinput = cancelbtn.Input();\n\n\t\t\t/*\n\t\t\t---------------------------- Process input ----------------------------\n\t\t\t*/\n\t\t\tswitch (input) {\n\n\t\t\t\t/*\n\t\t\t\t** Cancel. Just return to the main menu\n\t\t\t\t*/\n\t\t\t\tcase (KN_ESC):\n\t\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\t\tprocess = false;\n\t\t\t\t\treturn_code = false;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t}\n\n\treturn (return_code);\n}\n"
  },
  {
    "path": "CODE/SEQCONN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\seqconn.cpv   1.10   01 Mar 1996 18:29:54   JOE_BOSTIC  $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : SEQCONN.CPP                              *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 20, 1994                        *\n *                                                                         *\n *                  Last Update : April 9, 1995 [BRR]\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:    \t\t\t                                                   *\n *   SequencedConnClass::SequencedConnClass -- class constructor           *\n *   SequencedConnClass::~SequencedConnClass -- class destructor           *\n *   SequencedConnClass::Init -- Initializes connection queue to empty\t\t*\n *   SequencedConnClass::Send_Packet -- adds a packet to the send queue\t\t*\n *   SequencedConnClass::Receive_Packet -- adds packet to receive queue\t\t*\n *   SequencedConnClass::Get_Packet -- gets a packet from receive queue\t\t*\n *   SequencedConnClass::Service_Send_Queue -- services the send queue\t\t*\n *   SequencedConnClass::Service_Receive_Queue -- services recieve queue\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n#include \"WolDebug.h\"\n\n/***************************************************************************\n * SequencedConnClass::SequencedConnClass -- class constructor             *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t\tdesired # of entries for the send queue\t\t\t\t\t*\n *\t\tnumreceive\t\tdesired # of entries for the recieve queue\t\t\t\t*\n *\t\tmaxlen\t\t\tmax length of an application packet\t\t\t\t\t\t\t*\n *\t\tmagicnum\t\t\tthe packet \"magic number\" for this connection\t\t\t*\n *\t\tretry_delta\t\tthe time to wait between sends\t\t\t\t\t\t\t\t*\n *\t\tmax_retries\t\tthe max # of retries allowed for a packet\t\t\t\t\t*\n *\t\t\t\t\t\t\t(-1 means retry forever, based on this parameter)\t\t*\n *\t\ttimeout\t\t\tthe max amount of time before we give up on a packet\t*\n *\t\t\t\t\t\t\t(-1 means retry forever, based on this parameter)\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nSequencedConnClass::SequencedConnClass (int numsend, int numreceive, \n\tint maxlen, unsigned short magicnum, unsigned long retry_delta,\n\tunsigned long max_retries, unsigned long timeout) :\n\tConnectionClass (maxlen, magicnum, retry_delta, max_retries, timeout)\n{\n\tNumRecNoAck = 0;\n\tNumRecAck = 0;\n\tNumSendNoAck = 0;\n\tNumSendAck = 0;\n\n\t/*------------------------------------------------------------------------\n\tAllocate the packet Queue.  This will store incoming packets (which will\n\tbe placed there by the Connection Manager), and outgoing packets (which\n\tare placed there by this class when it \"sends\" a packet).\n\t------------------------------------------------------------------------*/\n\tQueue = new CommQueueClass (numsend, numreceive, MaxPacketLen);\n\n}\t/* end of SequencedConnClass */\n\n\n/***************************************************************************\n * SequencedConnClass::~SequencedConnClass -- class destructor             *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nSequencedConnClass::~SequencedConnClass ()\n{\n\tdelete Queue;\n}\n\n\n/***************************************************************************\n * SequencedConnClass::Init -- Initializes connection queue to empty\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid SequencedConnClass::Init (void)\n{\n\tQueue->Init();\n\n}\t/* end of Init */\n\n\n/***************************************************************************\n * SequencedConnClass::Send_Packet -- adds a packet to the send queue\t\t*\n *                                                                         *\n * This routine prefixes the given buffer with a CommHeaderType and\t\t\t*\n * queues the resulting packet into the Send Queue.  (It's actually the\t\t*\n * Service() routine that handles the hardware-dependent Send of the data).*\n * The packet's MagicNumber, Code, and PacketID are set here.\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tack_req\t\ttrue = ACK is required for this packet; false = isn't\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was queue'd OK, 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint SequencedConnClass::Send_Packet (void * buf, int buflen, int ack_req)\n{\n\t/*........................................................................\n\tSet the magic # for the packet\n\t........................................................................*/\n\t((CommHeaderType *)PacketBuf)->MagicNumber = MagicNum;\n\n\t/*........................................................................\n\tSet the packet Code: DATA_ACK if it requires an ACK, NOACK if it doesn't\n\tSet the packet ID to the appropriate counter value.\n\t........................................................................*/\n\tif (ack_req) {\n\t\t((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_ACK;\n\t\t((CommHeaderType *)PacketBuf)->PacketID = NumSendAck;\n\t} else {\n\t\t((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_NOACK;\n\t\t((CommHeaderType *)PacketBuf)->PacketID = NumSendNoAck;\n\t}\n\n\t/*........................................................................\n\tNow build the packet\n\t........................................................................*/\n\tmemcpy(PacketBuf + sizeof(CommHeaderType), buf, buflen);\n\n\t/*........................................................................\n\tAdd it to the queue.\n\t........................................................................*/\n\tif (Queue->Queue_Send(PacketBuf,buflen + sizeof(CommHeaderType))) {\n\t\tif (ack_req) {\n\t\t\tNumSendAck++;\n\t\t} else {\n\t\t\tNumSendNoAck++;\n\t\t}\n\t\treturn(true);\n\n\t} else {\n\t\treturn(false);\n\t}\n}\n\n\n/***************************************************************************\n * SequencedConnClass::Receive_Packet -- adds packet to the receive queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tbuffer to process (already includes CommHeaderType)\t\t\t*\n *\t\tbuflen\tlength of buffer to process\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was processed OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint SequencedConnClass::Receive_Packet (void * buf, int buflen)\n{\n\tCommHeaderType *packet;\t\t\t\t\t// ptr to this packet\n\tSendQueueType *send_entry;\t\t\t\t// ptr to send entry header\n\tReceiveQueueType *rec_entry;\t\t\t// ptr to receive entry header\n\tCommHeaderType *entry_data;\t\t\t// ptr to queue entry data\n\tint save_packet = 1;\t\t\t\t\t\t// 0 = this is a resend, or \n\t\t\t\t\t\t\t\t\t\t\t\t\t//  out-of-order packet\n\n\t/*\n\t--------------------------- Check the magic # ----------------------------\n\t*/\n\tpacket = (CommHeaderType *)buf;\n\tif (packet->MagicNumber!=MagicNum)\n\t\treturn(false);\n\t\n\t/*------------------------------------------------------------------------\n\tProcess the packet based on its Code\n\t------------------------------------------------------------------------*/\n\tswitch (packet->Code) {\n\t\t/*.....................................................................\n\t\tDATA: If this is a No-Ack packet, always save it.  Otherwise, only\n\t\tsave it if it's received in the proper sequence.\n\t\t.....................................................................*/\n\t\tcase PACKET_DATA_ACK:\n\t\tcase PACKET_DATA_NOACK:\n\t\t\tif (packet->Code == PACKET_DATA_NOACK) {\n#ifdef DEBUG_SEQ\nprintf(\"PACKET_DATA_NOACK received (%d)\\n\",packet->PacketID);\n#endif\n\t\t\t\tsave_packet = 1;\n\t\t\t} else {\n#ifdef DEBUG_SEQ\nprintf(\"PACKET_DATA_ACK received (%d)\\n\",packet->PacketID);\n#endif\n\t\t\t\tif ((packet->PacketID == NumRecAck)) {\n\t\t\t\t\tsave_packet = 1;\n\t\t\t\t} else {\n\t\t\t\t\tsave_packet = 0;\n\t\t\t\t\t/*...............................................................\n\t\t\t\t\tIf this is a resend of our next-available received message, it \n\t\t\t\t\tmeans the other app didn't get our ACK, so mark it as \n\t\t\t\t\tnon-acknowledged to tell Service_Receive_Queue to send an ACK.\n\t\t\t\t\t...............................................................*/\n\t\t\t\t\trec_entry = Queue->Next_Receive();\n\t\t\t\t\tif (rec_entry) {\n\t\t\t\t\t\tentry_data = (CommHeaderType *)rec_entry->Buffer;\n\t\t\t\t\t\tif (entry_data->PacketID==packet->PacketID &&\n\t\t\t\t\t\t\tentry_data->Code == PACKET_DATA_ACK) {\n\t\t\t\t\t\t\trec_entry->IsACK = 0;\n#ifdef DEBUG_SEQ\nprintf(\"(Resend)\\n\");\n#endif\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t...................... queue this packet ........................\n\t\t\t*/\n\t\t\tif (save_packet) {\n\t\t\t\tif (!Queue->Queue_Receive(buf, buflen)) {\n\t\t\t\t\treturn(false);\n\t\t\t\t}\n\t\t\t\tif (packet->Code == PACKET_DATA_ACK) {\n\t\t\t\t\tNumRecAck++;\n\t\t\t\t} else {\n\t\t\t\t\tNumRecNoAck++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*.....................................................................\n\t\tACK: If this ACK is for the latest-sent packet, mark that packet as \n\t\tacknowledged, then throw this packet away.  Otherwise, ignore the ACK \n\t\t(if we re-sent before we received the other system's first ACK, this \n\t\tACK will be a leftover)\n\t\t.....................................................................*/\n\t\tcase PACKET_ACK:\n#ifdef DEBUG_SEQ\nprintf(\"ACK received (%d)\\n\",packet->PacketID);\n#endif\n\t\t\t/*\n\t\t\t....................... Get queue entry ptr ........................\n\t\t\t*/\n\t\t\tsend_entry = Queue->Next_Send();\n\t\t\t/*\n\t\t\t............... If ptr is valid, get ptr to its data ...............\n\t\t\t*/\n\t\t\tif (send_entry!=NULL) {\n\t\t\t\tentry_data = (CommHeaderType *)send_entry->Buffer;\n\n\t\t\t\t/*\n\t\t\t\t.............. If ACK is for this entry, mark it ................\n\t\t\t\t*/\n\t\t\t\tif (packet->PacketID==entry_data->PacketID && \n\t\t\t\t\tentry_data->Code == PACKET_DATA_ACK) {\n\t\t\t\t\tsend_entry->IsACK = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t\n\t\t/*.....................................................................\n\t\tDefault: ignore the packet\n\t\t.....................................................................*/\n\t\tdefault:\n\t\t\tbreak;\n\n\t}\t/* end of switch */\n\n\treturn(true);\n}\n\n\n/***************************************************************************\n * SequencedConnClass::Get_Packet -- gets a packet from the receive queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tlocation to store buffer\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\tfilled in with length of 'buf'\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was read, 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint SequencedConnClass::Get_Packet (void * buf, int *buflen)\n{\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\tint packetlen;\t\t\t\t\t\t\t\t\t\t// size of received packet\n\n\t/*\n\t------------------ Get ptr to the next available entry -------------------\n\t*/\n\trec_entry = Queue->Next_Receive();\n\n\t/*\n\t------------------------ Read it if it's un-read -------------------------\n\t*/\n\tif (rec_entry!=NULL && rec_entry->IsRead==0) {\n\t\t/*\n\t\t........................... Mark as read ..............................\n\t\t*/\n\t\trec_entry->IsRead = 1;\n\n\t\t/*\n\t\t.......................... Copy data packet ...........................\n\t\t*/\n\t\tpacketlen = rec_entry->BufLen - sizeof(CommHeaderType);\n\t\tif (packetlen > 0) {\n\t\t\tmemcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType), packetlen);\n\t\t}\n\t\t(*buflen) = packetlen;\n\t\treturn(true);\n\t}\n\n\treturn(false);\n}\n\n\n/***************************************************************************\n * SequencedConnClass::Service_Send_Queue -- services the send queue\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint SequencedConnClass::Service_Send_Queue (void)\n{\n\tSendQueueType *send_entry;\t\t\t\t\t\t// ptr to send queue entry\n\tCommHeaderType *packet_hdr;\t\t\t\t\t// packet header\n\tunsigned long curtime;\t\t\t\t\t\t\t// current time\n\n\t/*------------------------------------------------------------------------\n\t- If the next packet is ACK'd remove it from the queue\n\t- If the next packet isn't ACK'd, [re-]send it\n\t------------------------------------------------------------------------*/\n\t/*\n\t......................... Get ptr to data to send ........................\n\t*/\n\tsend_entry = Queue->Next_Send();\n\tif (send_entry==NULL)\n\t\treturn(true);\n\n\t/*\n\t------------------ If ACK has been received, unqueue it ------------------\n\t*/\n\tif (send_entry->IsACK) {\n\n\t\t/*\n\t\t.................. Update this queue's response time ..................\n\t\t*/\n\t\tpacket_hdr = (CommHeaderType *)send_entry->Buffer;\n\t\tif (packet_hdr->Code == PACKET_DATA_ACK) {\n\t\t\tQueue->Add_Delay(Time() - send_entry->FirstTime);\n\t\t}\n\n\t\t/*\n\t\t......................... unqueue the packet ..........................\n\t\t*/\n#ifdef DEBUG_SEQ\nprintf(\">>>Unqueueing Receive packet #%d<<<\\n\",packet_hdr->PacketID);\n#endif\n\t\tQueue->UnQueue_Send(NULL,NULL);\n\t} else {\n\n\t\t/*\n\t\t----------------- ACK not received yet, [re-]send packet -----------------\n\t\t*/\n\t\t/*.....................................................................\n\t\tOnly send the message if time has elapsed.  (The message's Time\n\t\tfields are init'd to 0 when a message is queue'd or unqueue'd, so the\n\t\tfirst time through, the delta time will appear large.)\n\t\t.....................................................................*/\n\t\tcurtime = Time();\n\t\tif (curtime - send_entry->LastTime > RetryDelta) {\n\t\t\t/*\n\t\t\t......................... Send the message .........................\n\t\t\t*/\n\t\t\tSend (send_entry->Buffer, send_entry->BufLen);\n\t\t\t/*\n\t\t\t....................... Fill in Time fields ........................\n\t\t\t*/\n\t\t\tsend_entry->LastTime = curtime;\n\t\t\tif (send_entry->SendCount==0) {\n\t\t\t\tsend_entry->FirstTime = curtime;\n\t\t\t\t/*...............................................................\n\t\t\t\tIf this is the 1st time we're sending this packet, and it doesn't\n\t\t\t\trequire an ACK, mark it as ACK'd; then, the next time through,\n\t\t\t\tit will just be removed from the queue.\n\t\t\t\t...............................................................*/\n\t\t\t\tpacket_hdr = (CommHeaderType *)send_entry->Buffer;\n\t\t\t\tif (packet_hdr->Code == PACKET_DATA_NOACK)\n\t\t\t\t\tsend_entry->IsACK = 1;\n\t\t\t}\n\n#ifdef DEBUG_SEQ\npacket_hdr = (CommHeaderType *)send_entry->Buffer;\nif (packet_hdr->Code == PACKET_DATA_NOACK) {\n\tprintf(\"Sending PACKET_DATA_NOACK (%d)\\n\",packet_hdr->PacketID);\n} else {\n\tprintf(\"Sending PACKET_DATA_ACK (%d)\\n\",packet_hdr->PacketID);\n}\n#endif\n\t\t\t/*\n\t\t\t......................... Update SendCount .........................\n\t\t\t*/\n\t\t\tsend_entry->SendCount++;\n\t\t\t/*..................................................................\n\t\t\tPerform error detection, based on either MaxRetries or Timeout\n\t\t\t..................................................................*/\n\t\t\tif (MaxRetries != -1 && send_entry->SendCount > MaxRetries)\n\t\t\t\treturn(false);\n\t\t\tif (Timeout != -1 && send_entry->LastTime - \n\t\t\t\tsend_entry->FirstTime > Timeout)\n\t\t\t\treturn(false);\n\n\t\t}\n\t}\n\n\treturn(true);\n}\n\n\n/***************************************************************************\n * SequencedConnClass::Service_Receive_Queue -- services the recieve queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint SequencedConnClass::Service_Receive_Queue (void)\n{\n\tCommHeaderType ackpacket;\t\t\t\t\t\t// ACK packet to send\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\tCommHeaderType *packet_hdr;\t\t\t\t\t// packet header\n\n\t/*------------------------------------------------------------------------\n\tGet a pointer to the next received entry\n\t------------------------------------------------------------------------*/\n\trec_entry = Queue->Next_Receive();\n\tif (rec_entry==NULL)\n\t\treturn(true);\n\n\t/*------------------------------------------------------------------------\n\tIf this packet doesn't require an ACK, mark it as ACK'd.\n\t------------------------------------------------------------------------*/\n\tpacket_hdr = (CommHeaderType *)(rec_entry->Buffer);\n\tif (packet_hdr->Code==PACKET_DATA_NOACK)\n\t\trec_entry->IsACK = 1;\n\n\t/*------------------------------------------------------------------------\n\tIf this packet hasn't been ACK'd, send an ACK:\n\t- Fill in the MagicNum & the Code\n\t- Set the PacketID to the same ID that the sending system used, so the\n\t  sending system knows which packet the ACK is for\n\t------------------------------------------------------------------------*/\n\tif (rec_entry->IsACK==0) {\n#ifdef DEBUG_SEQ\nprintf(\"Sending ACK (%d)\\n\",packet_hdr->PacketID);\n#endif\n\t\tackpacket.MagicNumber = MagicNum;\n\t\tackpacket.Code = PACKET_ACK;\n\t\tackpacket.PacketID = packet_hdr->PacketID;\n\n\t\tSend((char *)&ackpacket, sizeof(CommHeaderType));\n\n\t\trec_entry->IsACK = 1;\n\t}\n\t\t\t\n\t/*------------------------------------------------------------------------\n\tIf this packet has been read by the application, and has been ACK'd, and\n\tthere is another packet in the queue behind this one, it means the other\n\tsystem got the ACK we sent for this packet; remove this packet from the\n\tqueue.\n\t------------------------------------------------------------------------*/\n\tif (rec_entry!=NULL && rec_entry->IsRead && rec_entry->IsACK &&\n\t\tQueue->Num_Receive() > 1) {\n#ifdef DEBUG_SEQ\nprintf(\">>>Unqueueing Send packet #%d<<<\\n\",packet_hdr->PacketID);\n#endif\n\t\tQueue->UnQueue_Receive(NULL,NULL);\n\t}\n\n\treturn(true);\n}\n\n"
  },
  {
    "path": "CODE/SEQCONN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\seqconn.h_v   1.13   01 Mar 1996 17:45:24   JOE_BOSTIC  $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : SEQCONN.H                                *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 9, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This class provides a \"Sequenced\" ACK/Retry approach to packet\t\t\t\t*\n * transmission.  It waits until the last packet has been ACK'd before\t\t*\n * sending another packet.  Thus, it guarantees order of delivery of\t\t\t*\n * packets, but its performance will be slower than the Non-Sequenced\t\t*\n * approach.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tA derived class must provide:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Init: Initialization of any hardware-specific values.\t\t\t\t\t\t*\n * - Send: a hardware-dependent send routine.\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SEQCONN_H\n#define SEQCONN_H\n\n#include \"connect.h\"\n#include \"comqueue.h\"\n\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass SequencedConnClass : public ConnectionClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*.....................................................................\n\t\tConstructor/destructor.\n\t\t.....................................................................*/\n\t\tSequencedConnClass (int numsend, int numrecieve, int maxlen, \n\t\t\tunsigned short magicnum, unsigned long retry_delta,\n\t\t\tunsigned long max_retries, unsigned long timeout);\n\t\tvirtual ~SequencedConnClass ();\n\n\t\t/*.....................................................................\n\t\tInitialization.\n\t\t.....................................................................*/\n\t\tvirtual void Init (void);\n\n\t\t/*.....................................................................\n\t\tSend/Receive routines.\n\t\t.....................................................................*/\n\t\tvirtual int Send_Packet (void * buf, int buflen, int ack_req);\n\t\tvirtual int Receive_Packet (void * buf, int buflen);\n\t\tvirtual int Get_Packet (void * buf, int *buflen);\n\n\t\t/*.....................................................................\n\t\tThe packet queue.\n\t\t.....................................................................*/\n\t\tCommQueueClass *Queue;\n\n\t/*\n\t-------------------------- Protected Interface ---------------------------\n\t*/\n\tprotected:\n\t\t/*.....................................................................\n\t\tRoutines to service the Send & Receive queues.\n\t\t.....................................................................*/\n\t\tvirtual int Service_Send_Queue (void);\n\t\tvirtual int Service_Receive_Queue (void);\n\n\t\t/*.....................................................................\n\t\tRunning totals of # of packets we send & receive which require an ACK, \n\t\tand those that don't.\n\t\t.....................................................................*/\n\t\tunsigned long NumRecNoAck;\n\t\tunsigned long NumRecAck;\n\t\tunsigned long NumSendNoAck;\n\t\tunsigned long NumSendAck;\n\n};\n\n#endif\n/*************************** end of seqconn.h ******************************/\n"
  },
  {
    "path": "CODE/SESSION.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /counterstrike/SESSION.CPP 3     3/10/97 6:23p Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SESSION.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Bill R. Randolph                                             *\n *                                                                                             *\n *                   Start Date : 11/30/95                                                     *\n *                                                                                             *\n *                  Last Update : September 10, 1996 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SessionClass::SessionClass -- Constructor                                                 *\n *   SessionClass::~SessionClass -- Destructor                                                 *\n *   SessionClass::One_Time -- one-time initializations                                        *\n *   SessionClass::Init -- Initializes all values                                              *\n *   SessionClass::Create_Connections -- forms connections to other players                    *\n *   SessionClass::Am_I_Master -- tells if the local system is the \"master\"                    *\n *   SessionClass::Save -- Saves this class to a file                                          *\n *   SessionClass::Load -- Loads this class from a file                                        *\n *   SessionClass::Read_MultiPlayer_Settings -- reads settings from INI                        *\n *   SessionClass::Write_MultiPlayer_Settings -- writes settings to INI                        *\n *   SessionClass::Read_Scenario_Descriptions -- reads scen. descriptions                      *\n *   SessionClass::Free_Scenario_Descriptions -- frees scen. descriptions                      *\n *   SessionClass::Trap_Object -- searches for an object, for debugging                        *\n *   SessionClass::Compute_Unique_ID -- computes unique local ID number                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include <dos.h>\t\t\t// for station ID computation\n#include <time.h>\t\t\t// for station ID computation\n\n//#include \"WolDebug.h\"\n\n/***************************** Globals *************************************/\n//---------------------------------------------------------------------------\n//\tThis is the array of remap colors.  Each player in a network game is\n// assigned one of these colors.  The 'G' is for graphics drawing; the 'T'\n// is for text printing (indicates a remap table for the font to use).\n//---------------------------------------------------------------------------\n//int SessionClass::GColors[MAX_MPLAYER_COLORS] = {\n\t//5, \t\t\t// Yellow\n\t//127, \t\t\t// Red\n\t//135, \t\t\t// BlueGreen\n\t//26,\t\t\t// Orange\n\t//4,\t\t\t\t// Green\n\t//202\t\t\t// Blue-Grey\n//};\n\n//int SessionClass::TColors[MAX_MPLAYER_COLORS] = {\n\t//CC_GDI_COLOR, \t\t\t// Yellow\n\t//CC_NOD_COLOR, \t\t\t// Red\n\t//CC_BLUE_GREEN, \t\t// BlueGreen\n\t//CC_ORANGE,\t\t\t\t// Orange\n\t//CC_GREEN,\t\t\t\t// Green\n\t//CC_BLUE_GREY,\t\t\t// Blue\n//};\n\n/*---------------------------------------------------------------------------\nMin & Max unit count values; index0 = bases OFF, index1 = bases ON\n---------------------------------------------------------------------------*/\nint SessionClass::CountMin[2] = {1,0};\nint SessionClass::CountMax[2] = {50,12};\n\n//---------------------------------------------------------------------------\n//\tThis is a list of all the names of the multiplayer scenarios\n//---------------------------------------------------------------------------\nchar SessionClass::Descriptions[100][40];\n\n//---------------------------------------------------------------------------\n// These values are used purely for the Mono debug display.  They show the\n// names of the Global Channel packet types, and the event types.\n//---------------------------------------------------------------------------\nchar * SessionClass::GlobalPacketNames[] = {\n\t\"Game?\",\n\t\"Game!\",\n\t\"Player?\",\n\t\"Player!\",\n\t\"Join?\",\n\t\"Join!\",\n\t\"Reject\",\n\t\"GameOptions\",\n\t\"Sign Off\",\n\t\"GO!\",\n\t\"Message\",\n\t\"Ping\",\n\t\"Load\"\n};\n\nchar * SessionClass::SerialPacketNames[] = {\n\t\"CONNECT\",\n\t\"GAME_OPTIONS\",\n\t\"SIGN_OFF\",\n\t\"GO\",\n\t\"MESSAGE\",\n\t\"TIMING\",\n\t\"SCORE_SCREEN\",\n\t\"LOADGAME\",\n\t\"LAST_COMMAND\",\n};\n\n\nchar * SessionClass::DialMethodCheck[ DIAL_METHODS ] = {\n\t\"T\",\n\t\"P\"\n};\n\nchar *SessionClass::CallWaitStrings[ CALL_WAIT_STRINGS_NUM ] = {\n\t\"*70,\",\n\t\"70#,\",\n\t\"1170,\",\n\t\"CUSTOM -                \"\n};\n\n/***************************************************************************\n * SessionClass::SessionClass -- Constructor                               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/30/1995 BRR : Created.                                             *\n *=========================================================================*/\nSessionClass::SessionClass(void)\n{\n\tType = GAME_NORMAL;\n\tCommProtocol = DEFAULT_COMM_PROTOCOL;\n\n\tOptions.ScenarioIndex = 0;\n\tOptions.Bases = 0;\n\tOptions.Credits = 0;\n\tOptions.Tiberium = 0;\n\tOptions.Goodies = 0;\n\tOptions.Ghosts = 0;\n\tOptions.UnitCount = 0;\n\n\tUniqueID = 0;\n\n\tHandle[0] = 0;\n\tPrefColor = PCOLOR_FIRST;\n\tColorIdx = PCOLOR_FIRST;\n\tHouse = HOUSE_GOOD;\n\tObiWan = 0;\n\tSolo = 0;\n\n\tMaxPlayers = 8;\n\tNumPlayers = 0;\n\n\tMaxAhead = 5;\n\tFrameSendRate = DEFAULT_FRAME_SEND_RATE;\n\n\tLoadGame = 0;\n\tEmergencySave = 0;\n\n\tLastMessage[0] = 0;\n\tWWChat = 0;\n\n\tRecordFile.Set_Name(\"RECORD.BIN\");\t\t// always uses this name\n\tRecord= 0;\t\t\t\t\t\t\t\t\t\t// set via command line\n\tPlay = 0;\t\t\t\t\t\t\t\t\t\t// set via command line\n\tAttract = 0;\t\t\t\t\t\t\t\t\t// set via command line\n\n\tIsBridge = 0;\n\tNetStealth = 0;\n\tNetProtect = 1;\n\tNetOpen = 0;\n\tGameName[0] = 0;\n\tGProductID = 0;\n\n\tMetaSize = MAX_IPX_PACKET_SIZE;\n\n\tModemService = true;\n\tCurPhoneIdx = 0;\t\t\t\t\t\t\t\t\t\t// set from INI file\n\tSerialDefaults.Port = 0x2f8;\t\t\t\t\t\t// set from INI file\n\tSerialDefaults.IRQ = 3;\t\t\t\t\t\t\t\t// set from INI file\n\tSerialDefaults.Baud = 9600;\t\t\t\t\t\t// set from INI file\n\tSerialDefaults.DialMethod = DIAL_TOUCH_TONE;\t// set from INI file\n\tSerialDefaults.InitStringIndex = 0;\t\t\t\t// set from INI file\n\tSerialDefaults.CallWaitStringIndex = 0;\t\t// set from INI file\n\tstrcpy(SerialDefaults.CallWaitString,\"\");\n\tModemType = MODEM_NULL_HOST;\t\t\t\t\t\t// set from INI file\n\n\tTrapFrame = 0x7fffffff;\t\t// frame to start trapping object values at\n\tTrapObjType = RTTI_NONE;\t// type of object to trap\n\tTrapObject.Ptr.All = NULL;\t// ptr to object being trapped\n\tTrapCoord = 0;\t\t\t\t\t// COORDINATE of object to trap\n\tTrapTarget = TARGET_NONE;\t// TARGET value of object to trap\n\tTrapCell = NULL;\t\t\t\t// for trapping a cell\n\tTrapCheckHeap = 0;\t\t\t// start checking the Heap\n\tTrapPrintCRC = 0;\t\t\t\t// output CRC file\n\n#if(TEN)\n\tTenPacket = NULL;\n\tTenSize = 200;\n\tTenPlayerID = -1;\n\tOptionsFile[0] = 0;\n\tAllowSolo = 0;\n\tNetResponseTime = 600;\n#endif\t// TEN\n\n#if(MPATH)\n\tMPathPacket = NULL;\n\tMPathSize = 200;\n\tOptionsFile[0] = 0;\n\tAllowSolo = 0;\n\tNetResponseTime = 600;\n#endif\t// MPATH\n\n}\t// end of SessionClass\n\n\n/***************************************************************************\n * SessionClass::~SessionClass -- Destructor                               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/30/1995 BRR : Created.                                             *\n *=========================================================================*/\nSessionClass::~SessionClass(void)\n{\n}\t// end of ~SessionClass\n\n\n/***************************************************************************\n * SessionClass::One_Time -- one-time initializations                      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/01/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid SessionClass::One_Time(void)\n{\n\tRead_MultiPlayer_Settings();\n\tRead_Scenario_Descriptions();\n\n\tUniqueID = Compute_Unique_ID();\n\n}\t// end of One_Time\n\n\n/***************************************************************************\n * SessionClass::Init -- Initializes all values                            *\n *                                                                         *\n * This function should be called for every new game played; it only sets\t*\n * those variables that should be set for a new game.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/30/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid SessionClass::Init(void)\n{\n\n}\t// end of Init\n\n\n/***************************************************************************\n * SessionClass::Create_Connections -- forms connections to other players  *\n *                                                                         *\n * This routine uses the contents of the Players vector, combined with\t\t*\n * that of the Houses array, to create connections to each other player.\t*\n * It is assumed that 'Players' contains all the other players to connect\t*\n * to, and that the HouseClass's have been filled in with players' data.\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = success, 0 = failure\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/30/1995 BRR : Created.                                             *\n *=========================================================================*/\nint SessionClass::Create_Connections(void)\n{\n\tint i;\n\n\tif (Session.Type != GAME_IPX && Session.Type != GAME_INTERNET) {\n\t\treturn (0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Loop through all entries in 'Players'.  To avoid connecting to myself,\n\t// skip the 1st entry.\n\t//------------------------------------------------------------------------\n\tfor (i = 1; i < Players.Count(); i++) {\n\t\t//.....................................................................\n\t\t// Make sure the name matches before creating the connection\n\t\t//.....................................................................\n\t\tif (!stricmp (Players[i]->Name,\n\t\t\tHouseClass::As_Pointer(Players[i]->Player.ID)->IniName)) {\n\t\t\tIpx.Create_Connection((int)Players[i]->Player.ID, Players[i]->Name,\n\t\t\t\t&(Players[i]->Address) );\n\t\tPlayers[i]->Player.ProcessTime = -1;\n\t\t}\n\t\telse {\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\treturn (1);\n\n}\t// end of Create_Connections\n\n\n#if(TEN)\n/***************************************************************************\n * SessionClass::Create_TEN_Connections -- forms connections to TEN players*\n *                                                                         *\n * This routine uses the contents of the Players vector, combined with\t\t*\n * that of the Houses array, to create connections to each other player.\t*\n * It is assumed that 'Players' contains all the other players to connect\t*\n * to, and that the HouseClass's have been filled in with players' data.\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = success, 0 = failure\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/30/1995 BRR : Created.                                             *\n *=========================================================================*/\nint SessionClass::Create_TEN_Connections(void)\n{\n\tint i;\n\n\tif (Session.Type != GAME_TEN) {\n\t\treturn (0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Loop through all entries in 'Players'.  To avoid connecting to myself,\n\t// skip the 1st entry.\n\t//------------------------------------------------------------------------\n\tfor (i = 1; i < Players.Count(); i++) {\n\t\t//.....................................................................\n\t\t// Make sure the name matches before creating the connection\n\t\t//.....................................................................\n\t\tif (!stricmp (Players[i]->Name,\n\t\t\tHouseClass::As_Pointer(Players[i]->Player.ID)->IniName)) {\n\t\t\tTen->Create_Connection((int)Players[i]->Player.ID, Players[i]->Name,\n\t\t\t\tPlayers[i]->TenAddress);\n\t\t\tPlayers[i]->Player.ProcessTime = -1;\n\t\t}\n\t\telse {\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\treturn (1);\n\n}\t// end of Create_TEN_Connections\n\n#endif\t// TEN\n\n\n#if(MPATH)\n/***************************************************************************\n * SessionClass::Create_MPATH_Connections -- forms connections to MPATH players*\n *                                                                         *\n * This routine uses the contents of the Players vector, combined with\t\t*\n * that of the Houses array, to create connections to each other player.\t*\n * It is assumed that 'Players' contains all the other players to connect\t*\n * to, and that the HouseClass's have been filled in with players' data.\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = success, 0 = failure\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/30/1995 BRR : Created.                                             *\n *=========================================================================*/\nint SessionClass::Create_MPATH_Connections(void)\n{\n\tint i;\n\n\tif (Session.Type != GAME_MPATH) {\n\t\treturn (0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Loop through all entries in 'Players'.  To avoid connecting to myself,\n\t// skip the 1st entry.\n\t//------------------------------------------------------------------------\n\tfor (i = 1; i < Players.Count(); i++) {\n\t\t//.....................................................................\n\t\t// Make sure the name matches before creating the connection\n\t\t//.....................................................................\n\t\tif (!stricmp (Players[i]->Name,\n\t\t\tHouseClass::As_Pointer(Players[i]->Player.ID)->IniName)) {\n\t\t\tMPath->Create_Connection((int)Players[i]->Player.ID, Players[i]->Name,\n\t\t\t\tPlayers[i]->MPathAddress);\n\t\t\tPlayers[i]->Player.ProcessTime = -1;\n\t\t}\n\t\telse {\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\treturn (1);\n\n}\t// end of Create_MPATH_Connections\n\n#endif\t// MPATH\n\n\n/***************************************************************************\n * SessionClass::Am_I_Master -- tells if the local system is the \"master\"  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nbool SessionClass::Am_I_Master(void)\n{\n\tint i;\n\tHousesType house;\n\tHouseClass *hptr;\n\n\t//------------------------------------------------------------------------\n\t// Check every house; if PlayerPtr points to the first human house, we're\n\t// the master.\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Session.MaxPlayers; i++) {\n\t\thouse = (HousesType)((int)HOUSE_MULTI1 + i);\n\t\thptr = HouseClass::As_Pointer(house);\n\t\tif (hptr->IsHuman) {\n\t\t\tif (PlayerPtr == hptr) {\n\t\t\t\treturn (true);\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn (false);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn (false);\n\n}\t// end of Am_I_Master\n\n\n/***************************************************************************\n * SessionClass::Save -- Saves this class to a file                        *\n *                                                                         *\n * Only certain members of this class should be saved into a save-game\t\t*\n * file; this routine saves only those members.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\tfile to save to\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nSessionClass::Save(Pipe & file) const\n{\n#ifdef FIXIT_MULTI_SAVE\n\tfile.Put(&CommProtocol, sizeof(CommProtocol));\n\tfile.Put(&MaxAhead, sizeof(MaxAhead));\n\tfile.Put(&FrameSendRate, sizeof(FrameSendRate));\n\tfile.Put(&DesiredFrameRate, sizeof(DesiredFrameRate));\n#endif\t// FIXIT_MULTI_SAVE\n\tfile.Put(&PrefColor, sizeof(PrefColor));\n\tfile.Put(&ColorIdx, sizeof(ColorIdx));\n\tfile.Put(&House, sizeof(House));\n\tfile.Put(&NumPlayers, sizeof(NumPlayers));\n\tfile.Put(&Options.Bases, sizeof(Options.Bases));\n\tfile.Put(&Options.Credits, sizeof(Options.Credits));\n\tfile.Put(&Options.Tiberium, sizeof(Options.Tiberium));\n\tfile.Put(&Options.Goodies, sizeof(Options.Goodies));\n\tfile.Put(&Options.Ghosts, sizeof(Options.Ghosts));\n\tfile.Put(&Options.UnitCount, sizeof(Options.UnitCount));\n\tfile.Put(&Options.AIPlayers, sizeof(Options.AIPlayers));\n\tfile.Put(&ObiWan, sizeof(ObiWan));\n\tfile.Put(&EmergencySave, sizeof(EmergencySave));\n\n\treturn (1);\n\n}\t// end of Save\n\n\n/***************************************************************************\n * SessionClass::Load -- Loads this class from a file                      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\tfile to load from\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nSessionClass::Load(Straw & file)\n{\n#ifdef FIXIT_MULTI_SAVE\n//\tif(GameVersion != 0x0100616D){\n\tfile.Get(&CommProtocol, sizeof(CommProtocol));\n\tfile.Get(&MaxAhead, sizeof(MaxAhead));\n\tfile.Get(&FrameSendRate, sizeof(FrameSendRate));\n\tfile.Get(&DesiredFrameRate, sizeof(DesiredFrameRate));\n//\t}\n#endif\t// FIXIT_MULTI_SAVE\n\tfile.Get(&PrefColor, sizeof(PrefColor));\n\tfile.Get(&ColorIdx, sizeof(ColorIdx));\n\tfile.Get(&House, sizeof(House));\n\tfile.Get(&NumPlayers, sizeof(NumPlayers));\n\tfile.Get(&Options.Bases, sizeof(Options.Bases));\n\tfile.Get(&Options.Credits, sizeof(Options.Credits));\n\tfile.Get(&Options.Tiberium, sizeof(Options.Tiberium));\n\tfile.Get(&Options.Goodies, sizeof(Options.Goodies));\n\tfile.Get(&Options.Ghosts, sizeof(Options.Ghosts));\n\tfile.Get(&Options.UnitCount, sizeof(Options.UnitCount));\n\tfile.Get(&Options.AIPlayers, sizeof(Options.AIPlayers));\n\tfile.Get(&ObiWan, sizeof(ObiWan));\n\tfile.Get(&EmergencySave, sizeof(EmergencySave));\n\n\treturn (1);\n\n}\t// end of Load\n\n\n/***************************************************************************\n * SessionClass::Save -- Saves this class to a file                        *\n *                                                                         *\n * Only certain members of this class should be saved into a save-game\t\t*\n * file; this routine saves only those members.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\tfile to save to\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nSessionClass::Save(CCFileClass & file)\n{\n\tint i;\n\n\tfile.Write(&Type, sizeof(Type));\n\tfile.Write(&CommProtocol, sizeof(CommProtocol));\n\tfile.Write(&FrameSendRate, sizeof(FrameSendRate));\n\tfile.Write(&PrefColor, sizeof(PrefColor));\n\tfile.Write(&ColorIdx, sizeof(ColorIdx));\n\tfile.Write(&House, sizeof(House));\n\tfile.Write(&NumPlayers, sizeof(NumPlayers));\n\tfile.Write(&Options.Bases, sizeof(Options.Bases));\n\tfile.Write(&Options.Credits, sizeof(Options.Credits));\n\tfile.Write(&Options.Tiberium, sizeof(Options.Tiberium));\n\tfile.Write(&Options.Goodies, sizeof(Options.Goodies));\n\tfile.Write(&Options.Ghosts, sizeof(Options.Ghosts));\n\tfile.Write(&Options.UnitCount, sizeof(Options.UnitCount));\n\tfile.Write(&Options.AIPlayers, sizeof(Options.AIPlayers));\n\tfile.Write(&ObiWan, sizeof(ObiWan));\n\tfile.Write(&EmergencySave, sizeof(EmergencySave));\n\n\ti = Players.Count();\n\tfile.Write(&i, sizeof(i));\n\tfor (i = 0; i < Players.Count(); i++) {\n\t\tfile.Write(Players[i], sizeof(NodeNameType));\n\t}\n\n\treturn (1);\n\n}\t// end of Save\n\n\n/***************************************************************************\n * SessionClass::Load -- Loads this class from a file                      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\tfile to load from\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nSessionClass::Load(CCFileClass & file)\n{\n\tint count;\n\tint i;\n\tNodeNameType *node;\n\n\tfile.Read(&Type, sizeof(Type));\n\tfile.Read(&CommProtocol, sizeof(CommProtocol));\n\tfile.Read(&FrameSendRate, sizeof(FrameSendRate));\n\tfile.Read(&PrefColor, sizeof(PrefColor));\n\tfile.Read(&ColorIdx, sizeof(ColorIdx));\n\tfile.Read(&House, sizeof(House));\n\tfile.Read(&NumPlayers, sizeof(NumPlayers));\n\tfile.Read(&Options.Bases, sizeof(Options.Bases));\n\tfile.Read(&Options.Credits, sizeof(Options.Credits));\n\tfile.Read(&Options.Tiberium, sizeof(Options.Tiberium));\n\tfile.Read(&Options.Goodies, sizeof(Options.Goodies));\n\tfile.Read(&Options.Ghosts, sizeof(Options.Ghosts));\n\tfile.Read(&Options.UnitCount, sizeof(Options.UnitCount));\n\tfile.Read(&Options.AIPlayers, sizeof(Options.AIPlayers));\n\tfile.Read(&ObiWan, sizeof(ObiWan));\n\tfile.Read(&EmergencySave, sizeof(EmergencySave));\n\n\tfile.Read(&count, sizeof(count));\n\tfor (i = 0; i < count; i++) {\n\t\tnode = new NodeNameType;\n\t\tfile.Read(node, sizeof(NodeNameType));\n\t\tPlayers.Add(node);\n\t}\n\n\treturn (1);\n\n}\t// end of Load\n\n\n/***************************************************************************\n * SessionClass::Read_MultiPlayer_Settings -- reads settings INI           *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/14/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid SessionClass::Read_MultiPlayer_Settings (void)\n{\n\tchar *tokenptr;\t\t\t\t\t\t// ptr to token\n\tPhoneEntryClass *phone;\t\t\t\t// a phone book entry\n\tchar *entry;\t\t\t\t\t\t\t// a phone book entry\n\tchar buf[128];\t\t\t\t\t\t\t// buffer for parsing INI entry\n\tint i;\n\tCELL cell;\n\n//\tCCFileClass file (CONFIG_FILE_NAME);\n\n\t//------------------------------------------------------------------------\n\t//\tClear the initstring entries\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < InitStrings.Count(); i++) {\n\t\tdelete[] InitStrings[i];\n\t}\n\tInitStrings.Clear();\n\n\t//\tClear the dialing entries\n\tfor (i = 0; i < PhoneBook.Count(); i++) {\n\t\tdelete[] PhoneBook[i];\n\t}\n\tPhoneBook.Clear();\n\n\t//\tCreate filename and read the file.\n\tINIClass ini;\n\tif (ini.Load(RawFileClass(CONFIG_FILE_NAME))) {\n\n\t\t//\tGet the player's last-used Handle\n\t\tini.Get_String(\"MultiPlayer\", \"Handle\", \"Noname\", Handle, sizeof(Handle));\n\n\t\t//\tGet the player's last-used Color\n\t\tPrefColor = (PlayerColorType)ini.Get_Int(\"MultiPlayer\", \"Color\", 0);\n#ifdef FIXIT_VERSION_3\n\t\tint iSide = ini.Get_Int(\"MultiPlayer\", \"Side\", HOUSE_USSR);\n\t\tiSide = max( 2, min( 6, iSide ) );\n\t\tHouse = (HousesType)iSide;\n#else\n\t\tHouse = (HousesType)ini.Get_Int(\"MultiPlayer\", \"Side\", HOUSE_USSR);\n#endif\n\t\tCurPhoneIdx = ini.Get_Int(\"MultiPlayer\", \"PhoneIndex\", -1);\n\t\tTrapCheckHeap = ini.Get_Int(\"MultiPlayer\", \"CheckHeap\", 0);\n\n\t\t//\tRead in default serial settings\n\t\tini.Get_String(\"SerialDefaults\", \"ModemName\", \"NoName\", SerialDefaults.ModemName, MODEM_NAME_MAX);\n\t\tif (!strcmp ( SerialDefaults.ModemName, \"NoName\")) {\n\t\t\tSerialDefaults.ModemName[0] = 0;\n\t\t}\n\t\tSerialDefaults.Port = ini.Get_Int(\"SerialDefaults\", \"Port\", 0);\n\t\tSerialDefaults.IRQ = ini.Get_Int(\"SerialDefaults\", \"IRQ\", -1);\n\t\tSerialDefaults.Baud = ini.Get_Int(\"SerialDefaults\", \"Baud\", -1);\n\t\tSerialDefaults.Compression = ini.Get_Int (\"SerialDefaults\", \"Compression\", 0);\n\t\tSerialDefaults.ErrorCorrection = ini.Get_Int (\"SerialDefaults\", \"ErrorCorrection\", 0);\n\t\tSerialDefaults.HardwareFlowControl = ini.Get_Int (\"SerialDefaults\", \"HardwareFlowControl\", 1);\n\n\t\tini.Get_String(\"SerialDefaults\", \"DialMethod\", \"T\", buf, 2);\n\n#ifndef WIN32\n\t\t/*\n\t\t** Ignore any modem name in DOS. This should only be nessasary if the user\n\t\t** previously set up the modem in the windows version.\n\t\t*/\n\t\tif (SerialDefaults.ModemName[0] && SerialDefaults.Port == 1) {\n\t\t\tSerialDefaults.Port = 0x3F8;\n\t\t\tSerialDefaults.ModemName[0] = 0;\n\t\t}\n#endif\t//WIN32\n\n\t\t// find dial method\n\t\tfor (i = 0; i < DIAL_METHODS; i++) {\n\t\t\tif ( !strcmpi( buf, DialMethodCheck[ i ]) ) {\n\t\t\t\tSerialDefaults.DialMethod = (DialMethodType)i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// if method not found set to touch tone\n\t\tif (i == DIAL_METHODS) {\n\t\t\tSerialDefaults.DialMethod = DIAL_TOUCH_TONE;\n\t\t}\n\n\t\tSerialDefaults.InitStringIndex = ini.Get_Int(\"SerialDefaults\", \"InitStringIndex\", 0);\n\n\t\tSerialDefaults.CallWaitStringIndex = ini.Get_Int(\"SerialDefaults\", \"CallWaitStringIndex\", CALL_WAIT_CUSTOM);\n\n\t\tini.Get_String(\"SerialDefaults\", \"CallWaitString\", \"\", SerialDefaults.CallWaitString, CWAITSTRBUF_MAX);\n\n\t\tif (SerialDefaults.IRQ == 0 || SerialDefaults.Baud == 0) {\n\t\t\tSerialDefaults.Port = 0;\n\t\t\tSerialDefaults.IRQ = -1;\n\t\t\tSerialDefaults.Baud = -1;\n\t\t}\n\n\t\tint initcount = ini.Entry_Count(\"InitStrings\");\n\t\tfor (int index = 0; index < initcount; index++) {\n\t\t\tentry = new char[ INITSTRBUF_MAX ];\n\t\t\tentry[0] = 0;\n\t\t\tini.Get_String(\"InitStrings\", ini.Get_Entry(\"InitStrings\", index), NULL, entry, INITSTRBUF_MAX);\n\t\t\tstrupr( entry );\n\t\t\tInitStrings.Add( entry );\n\t\t}\n\n\t\t//\tif no entries then have at least one\n\t\tif (initcount == 0) {\n\t\t\tentry = new char[ INITSTRBUF_MAX ];\n\t\t\tstrcpy( entry, \"ATZ\" );\n\t\t\tInitStrings.Add( entry );\n\t\t\tSerialDefaults.InitStringIndex = 0;\n\t\t}\n\n\t\t//\tRead the entry names in\n\t\tint phonecount = ini.Entry_Count(\"PhoneBook\");\n\t\tfor (index = 0; index < phonecount; index++) {\n\t\t\t//\tCreate a new phone book entry\n\t\t\tphone = new PhoneEntryClass();\n\n\t\t\t//\tRead the entire entry in\n\t\t\tini.Get_String(\"PhoneBook\", ini.Get_Entry(\"PhoneBook\", index), NULL, buf, sizeof(buf));\n\n\t\t\t//\tExtract name, phone # & serial port settings\n\t\t\ttokenptr = strtok( buf, \"|\" );\n\t\t\tif (tokenptr) {\n\t\t\t\tstrcpy( phone->Name, tokenptr );\n\t\t\t\tstrupr( phone->Name );\n\t\t\t} else {\n\t\t\t\tphone->Name[0] = 0;\n\t\t\t}\n\n\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\tif (tokenptr) {\n\t\t\t\tstrcpy( phone->Number, tokenptr );\n\t\t\t\tstrupr( phone->Number );\n\t\t\t} else {\n\t\t\t\tphone->Number[0] = 0;\n\t\t\t}\n\n\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\tif (tokenptr) {\n\t\t\t\tsscanf( tokenptr, \"%x\", &phone->Settings.Port );\n\t\t\t} else {\n\t\t\t\tphone->Settings.Port = 0;\n\t\t\t}\n\n\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\tif (tokenptr) {\n\t\t\t\tphone->Settings.IRQ = atoi( tokenptr );\n\t\t\t} else {\n\t\t\t\tphone->Settings.IRQ = -1;\n\t\t\t}\n\n\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\tif (tokenptr) {\n\t\t\t\tphone->Settings.Baud = atoi( tokenptr );\n\t\t\t} else {\n\t\t\t\tphone->Settings.Baud = -1;\n\t\t\t}\n\n\t\t\tphone->Settings.Compression = 0;\n\t\t\tphone->Settings.ErrorCorrection = 0;\n\t\t\tphone->Settings.HardwareFlowControl = 1;\n\n\t\t\t/*\n\t\t\t** Find out if this phonebook entry has the new settings included. If not\n\t\t\t** then we need to skip this section.\n\t\t\t*/\n\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\tif (tokenptr){\n\t\t\t\tstrcpy( buf, tokenptr );\n\n\t\t\t\t// find dial method\n\n\t\t\t\tfor (i = 0; i < DIAL_METHODS; i++) {\n\t\t\t\t\tif ( !strcmpi( buf, DialMethodCheck[ i ]) ) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** This must be an old phonebook entry\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Method wasnt found - assume its a new phonebook entry so get the extra settings\n\t\t\t\t*/\n\t\t\t\t// if method not found set to touch tone\n\n\t\t\t\tif (i == DIAL_METHODS) {\n\n\t\t\t\t\tphone->Settings.Compression = atoi( tokenptr );\n\n\t\t\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\t\t\tif (tokenptr) {\n\t\t\t\t\t\tphone->Settings.ErrorCorrection = atoi( tokenptr );\n\t\t\t\t\t}\n\n\t\t\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\t\t\tif (tokenptr) {\n\t\t\t\t\t\tphone->Settings.HardwareFlowControl = atoi( tokenptr );\n\t\t\t\t\t}\n\n\t\t\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\tif (tokenptr) {\n\t\t\t\tstrcpy( buf, tokenptr );\n\n\t\t\t\t//\tfind dial method\n\t\t\t\tfor (i = 0; i < DIAL_METHODS; i++) {\n\t\t\t\t\tif ( !strcmpi( buf, DialMethodCheck[ i ]) ) {\n\t\t\t\t\t\tphone->Settings.DialMethod = (DialMethodType)i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t//\tif method not found set to touch tone\n\t\t\t\tif (i == DIAL_METHODS) {\n\t\t\t\t\tphone->Settings.DialMethod = DIAL_TOUCH_TONE;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tphone->Settings.DialMethod = DIAL_TOUCH_TONE;\n\t\t\t}\n\n\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\tif (tokenptr) {\n\t\t\t\tphone->Settings.InitStringIndex = atoi( tokenptr );\n\t\t\t} else {\n\t\t\t\tphone->Settings.InitStringIndex = 0;\n\t\t\t}\n\n\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\tif (tokenptr) {\n\t\t\t\tphone->Settings.CallWaitStringIndex = atoi( tokenptr );\n\t\t\t} else {\n\t\t\t\tphone->Settings.CallWaitStringIndex = CALL_WAIT_CUSTOM;\n\t\t\t}\n\n\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\tif (tokenptr) {\n\t\t\t\tstrcpy (phone->Settings.CallWaitString, tokenptr);\n\t\t\t} else {\n\t\t\t\tphone->Settings.CallWaitString[0] = 0;\n\t\t\t}\n\n\t\t\t//\tAdd it to our list\n\t\t\tPhoneBook.Add(phone);\n\t\t}\n\n\t\t//\tRead special recording playback values, to help find sync bugs\n\t\tTrapFrame = ini.Get_Int(\"SyncBug\", \"Frame\", 0x7fffffff);\n\n\t\tini.Get_String(\"SyncBug\", \"Type\", \"NONE\", buf, 80);\n\n\t\tif (!stricmp(buf,\"AIRCRAFT\"))\n\t\t\tTrapObjType = RTTI_AIRCRAFT;\n\t\telse if (!stricmp(buf,\"ANIM\"))\n\t\t\tTrapObjType = RTTI_ANIM;\n\t\telse if (!stricmp(buf,\"BUILDING\"))\n\t\t\tTrapObjType = RTTI_BUILDING;\n\t\telse if (!stricmp(buf,\"BULLET\"))\n\t\t\tTrapObjType = RTTI_BULLET;\n\t\telse if (!stricmp(buf,\"INFANTRY\"))\n\t\t\tTrapObjType = RTTI_INFANTRY;\n\t\telse if (!stricmp(buf,\"UNIT\"))\n\t\t\tTrapObjType = RTTI_UNIT;\n\t\telse {\n\t\t\tTrapObjType = RTTI_NONE;\n\t\t}\n\n\t\tini.Get_String(\"SyncBug\", \"Coord\", \"0\", buf, 80);\n\t\tsscanf(buf,\"%x\",&TrapCoord);\n\n\t\tini.Get_String(\"SyncBug\", \"Target\", \"0\", buf, 80);\n\t\tsscanf(buf,\"%x\",&TrapTarget);\n\n\t\tini.Get_String(\"SyncBug\", \"Cell\", \"0\", buf, 80);\n\t\tcell = atoi(buf);\n\t\tif (cell) {\n\t\t\tTrapCell = &(Map[cell]);\n\t\t}\n\n\t\tTrapPrintCRC = ini.Get_Int(\"SyncBug\", \"PrintCRC\", 0x7fffffff);\n\t}\n}\n\n\n/***************************************************************************\n * SessionClass::Write_MultiPlayer_Settings -- writes settings INI         *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/14/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid SessionClass::Write_MultiPlayer_Settings (void)\n{\n#ifdef NEVER\n\tchar * buffer;\t\t\t\t\t// INI staging buffer pointer.\n\tCCFileClass file;\n\tint i;\n\tchar entrytext[4];\n\tchar buf[128];\t\t\t\t\t// buffer for parsing INI entry\n\n\t//------------------------------------------------------------------------\n\t//\tGet a working pointer to the INI staging buffer. Make sure that the\n\t// buffer starts cleared out of any data.\n\t//------------------------------------------------------------------------\n\tbuffer = (char *)_ShapeBuffer;\n\tmemset(buffer, '\\0', _ShapeBufferSize);\n\n\tfile.Set_Name(CONFIG_FILE_NAME);\n\tif (file.Is_Available()) {\n\t\tfile.Open(READ);\n\t\tfile.Read(buffer, _ShapeBufferSize-1);\n\t\tfile.Close();\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSave the player's last-used Handle & Color\n\t//------------------------------------------------------------------------\n\tWWWritePrivateProfileInt(\"MultiPlayer\", \"PhoneIndex\", CurPhoneIdx, buffer);\n\tWWWritePrivateProfileInt (\"MultiPlayer\", \"Color\", (int)PrefColor, buffer);\n\tWWWritePrivateProfileInt (\"MultiPlayer\", \"Side\", House, buffer);\n\tWWWritePrivateProfileString(\"MultiPlayer\", \"Handle\", Handle, buffer);\n\n\t//------------------------------------------------------------------------\n\t//\tClear all existing Settings.SerialDefault entries.\n\t//------------------------------------------------------------------------\n\tWWWritePrivateProfileString (\"SerialDefaults\", NULL, NULL, buffer);\n\n\t//------------------------------------------------------------------------\n\t//\tSave default serial settings in opposite order you want to see them\n\t//------------------------------------------------------------------------\n\tWWWritePrivateProfileString(\"SerialDefaults\", \"CallWaitString\", SerialDefaults.CallWaitString, buffer);\n\tWWWritePrivateProfileInt (\"SerialDefaults\", \"CallWaitStringIndex\", SerialDefaults.CallWaitStringIndex, buffer);\n\tWWWritePrivateProfileInt (\"SerialDefaults\", \"InitStringIndex\", SerialDefaults.InitStringIndex, buffer);\n\tWWWritePrivateProfileString(\"SerialDefaults\", \"DialMethod\", DialMethodCheck[ SerialDefaults.DialMethod ], buffer);\n\tWWWritePrivateProfileInt (\"SerialDefaults\", \"Baud\", SerialDefaults.Baud, buffer);\n\tWWWritePrivateProfileInt (\"SerialDefaults\", \"IRQ\", SerialDefaults.IRQ, buffer);\n\tsprintf(buf, \"%x\", SerialDefaults.Port);\n\tWWWritePrivateProfileString(\"SerialDefaults\", \"Port\", buf, buffer);\n\tWWWritePrivateProfileInt (\"SerialDefaults\", \"Compression\", SerialDefaults.Compression , buffer);\n\tWWWritePrivateProfileInt (\"SerialDefaults\", \"ErrorCorrection\", SerialDefaults.ErrorCorrection, buffer);\n\tWWWritePrivateProfileInt (\"SerialDefaults\", \"HardwareFlowControl\", SerialDefaults.HardwareFlowControl, buffer);\n\n\t//------------------------------------------------------------------------\n\t//\tClear all existing InitString entries.\n\t//------------------------------------------------------------------------\n\tWWWritePrivateProfileString (\"InitStrings\", NULL, NULL, buffer);\n\n\t//------------------------------------------------------------------------\n\t//\tSave all InitString entries.  In descending order so they come out in\n\t//\tascending order.\n\t//------------------------------------------------------------------------\n\tfor (i = (InitStrings.Count() - 1); i >= 0; i--) {\n\t\tsprintf( buf, \"%03d\", i);\n\t\tWWWritePrivateProfileString (\"InitStrings\", buf, InitStrings[i], buffer);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tClear all existing Phone Book entries.\n\t//------------------------------------------------------------------------\n\tWWWritePrivateProfileString (\"PhoneBook\", NULL, NULL, buffer);\n\n\t//------------------------------------------------------------------------\n\t//\tSave all Phone Book entries.\n\t//\tFormat: Entry=Name,PhoneNum,Port,IRQ,Baud,InitString\n\t//------------------------------------------------------------------------\n\tfor (i = (PhoneBook.Count() - 1); i >= 0; i--) {\n\t\tsprintf(buf,\"%s|%s|%x|%d|%d|%d|%d|%d|%s|%d|%d|%s\",\n\t\t\tPhoneBook[i]->Name,\n\t\t\tPhoneBook[i]->Number,\n\t\t\tPhoneBook[i]->Settings.Port,\n\t\t\tPhoneBook[i]->Settings.IRQ,\n\t\t\tPhoneBook[i]->Settings.Baud,\n\t\t\tPhoneBook[i]->Settings.Compression,\n\t\t\tPhoneBook[i]->Settings.ErrorCorrection,\n\t\t\tPhoneBook[i]->Settings.HardwareFlowControl,\n\t\t\tDialMethodCheck[ PhoneBook[i]->Settings.DialMethod ],\n\t\t\tPhoneBook[i]->Settings.InitStringIndex,\n\t\t\tPhoneBook[i]->Settings.CallWaitStringIndex,\n\t\t\tPhoneBook[i]->Settings.CallWaitString);\n\t\tsprintf( entrytext, \"%03d\", i );\n\t\tWWWritePrivateProfileString (\"PhoneBook\", entrytext, buf, buffer);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tWrite the INI data out to a file.\n\t//------------------------------------------------------------------------\n\tfile.Open(WRITE);\n\tfile.Write(buffer,strlen(buffer));\n\tfile.Close();\n#endif\n\n\tINIClass ini;\n\tRawFileClass file(CONFIG_FILE_NAME);\n\tif (ini.Load(file)) {\n\n\t\t//\tSave the player's last-used Handle & Color\n\t\tini.Put_Int(\"MultiPlayer\", \"PhoneIndex\", CurPhoneIdx);\n\t\tini.Put_Int(\"MultiPlayer\", \"Color\", (int)PrefColor);\n\t\tini.Put_Int(\"MultiPlayer\", \"Side\", House);\n\t\tini.Put_String(\"MultiPlayer\", \"Handle\", Handle);\n\n\t\t//\tClear all existing Settings.SerialDefault entries.\n\t\tini.Clear(\"SerialDefaults\");\n\n\t\t//\tSave default serial settings in opposite order you want to see them\n\t\tini.Put_String(\"SerialDefaults\", \"CallWaitString\", SerialDefaults.CallWaitString);\n\t\tini.Put_Int(\"SerialDefaults\", \"CallWaitStringIndex\", SerialDefaults.CallWaitStringIndex);\n\t\tini.Put_Int(\"SerialDefaults\", \"InitStringIndex\", SerialDefaults.InitStringIndex);\n\t\tini.Put_String(\"SerialDefaults\", \"DialMethod\", DialMethodCheck[ SerialDefaults.DialMethod ]);\n\t\tini.Put_Int(\"SerialDefaults\", \"Baud\", SerialDefaults.Baud);\n\t\tini.Put_Int(\"SerialDefaults\", \"IRQ\", SerialDefaults.IRQ);\n\t\tini.Put_Int(\"SerialDefaults\", \"Port\", SerialDefaults.Port, 1);\n\t\tini.Put_String(\"SerialDefaults\", \"ModemName\", SerialDefaults.ModemName);\n\t\tini.Put_Int (\"SerialDefaults\", \"Compression\", SerialDefaults.Compression );\n\t\tini.Put_Int (\"SerialDefaults\", \"ErrorCorrection\", SerialDefaults.ErrorCorrection );\n\t\tini.Put_Int (\"SerialDefaults\", \"HardwareFlowControl\", SerialDefaults.HardwareFlowControl );\n\n\t\t//\tClear all existing InitString entries.\n\t\tini.Clear(\"InitStrings\");\n\n\t\t//\tSave all InitString entries.\n\t\tfor (int index = 0; index < InitStrings.Count(); index++) {\n\t\t\tchar buf[10];\n\t\t\tsprintf( buf, \"%03d\", index);\n\t\t\tini.Put_String(\"InitStrings\", buf, InitStrings[index]);\n\t\t}\n\n\t\t//\tClear all existing Phone Book entries.\n\t\tini.Clear(\"PhoneBook\");\n\n\t\t//\tSave all Phone Book entries.\n\t\t//\tFormat: Entry=Name,PhoneNum,Port,IRQ,Baud,InitString\n\t\tfor (int i = (PhoneBook.Count() - 1); i >= 0; i--) {\n\t\t\tchar buf[128];\n\t\t\tchar entrytext[10];\n\t\t\tsprintf(buf,\"%s|%s|%x|%d|%d|%d|%d|%d|%s|%d|%d|%s\",\n\t\t\t\tPhoneBook[i]->Name,\n\t\t\t\tPhoneBook[i]->Number,\n\t\t\t\tPhoneBook[i]->Settings.Port,\n\t\t\t\tPhoneBook[i]->Settings.IRQ,\n\t\t\t\tPhoneBook[i]->Settings.Baud,\n\t\t\t\tPhoneBook[i]->Settings.Compression,\n\t\t\t\tPhoneBook[i]->Settings.ErrorCorrection,\n\t\t\t\tPhoneBook[i]->Settings.HardwareFlowControl,\n\t\t\t\tDialMethodCheck[ PhoneBook[i]->Settings.DialMethod ],\n\t\t\t\tPhoneBook[i]->Settings.InitStringIndex,\n\t\t\t\tPhoneBook[i]->Settings.CallWaitStringIndex,\n\t\t\t\tPhoneBook[i]->Settings.CallWaitString);\n\t\t\tsprintf( entrytext, \"%03d\", i );\n\t\t\tini.Put_String(\"PhoneBook\", entrytext, buf);\n\t\t}\n\n\t\t//\tWrite the INI data out to a file.\n\t\tini.Save(file);\n\t}\n}\n\n\n// Determine if a mission is from counterstrike or aftermath, or either.\n// Multiplayer maps >24, with a numerical name, are Counterstrike.\n// Multiplayer maps with an alphabetical name, like SCMJGEA.INI, are Aftermath.\n\nbool Is_Mission_Counterstrike (char *file_name)\n{\n\tint scenario_number = 0;\n\n\tif ( isdigit ( file_name[5] )){\n\t\tsscanf (file_name, \"SCM%03d\", &scenario_number);\n\t} else {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tif (!isdigit(file_name[3]) || !isdigit(file_name[4])) {\n\t\t\treturn(false);\n\t\t}\n#endif\n\t\tsscanf (file_name, \"SCM%02d\", &scenario_number);\n\t}\n\treturn ( scenario_number > 24 );\n}\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nbool Is_Mission_Aftermath (char *file_name)\n{\n\t//\tajw added\n\t//\tMust start with \"scm\".\n\tchar szCopy[ _MAX_PATH + 1 ];\n\tstrcpy( szCopy, file_name );\n\t_strlwr( szCopy );\n\tif( strstr( szCopy, \"scm\" ) != szCopy )\n\t\treturn false;\n\n\tif (isdigit(file_name[5])) {\n\t\treturn(false);\n\t}\n\n\tif ( !isdigit(file_name[3]) || !isdigit(file_name[4]) ) {\n\t\treturn (true);\n\t}\n\treturn (false);\n}\n\n/*\n** Certain missions are 126x126 size, and those can't be downloaded to a\n** non-Aftermath player, so this function checks to see if the map in\n** question is one of those.  We'll know that by the file name: if it's\n** K0 -> M9, it's 126x126.\n*/\nbool Is_Mission_126x126 (char *file_name)\t\t//\tThis is no longer used. ajw\n{\n\tif (isdigit(file_name[5])) {\n\t\treturn(false);\n\t}\n\n\tif ( (file_name[3] >= 'k' && file_name[3] <= 'm') ||\n\t\t\t(file_name[3] >= 'K' && file_name[3] <= 'M') ) {\n\t\treturn (true);\n\t}\n\treturn (false);\n}\n\n#endif\n\n\n\n\n\n/***************************************************************************\n * SessionClass::Read_Scenario_Descriptions -- reads scen. descriptions    *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/14/1995 BR : Created.                                              *\n *   09/10/1996 JLB : Searches using different method.                     *\n *=========================================================================*/\nvoid SessionClass::Read_Scenario_Descriptions (void)\n{\n\n\t//\tClear the scenario description lists\n\tScenarios.Clear();\n\n\t/*\n\t**\tFetch the main multiplayer scenario packet data.\n\t*/\n\tCCFileClass file(\"MISSIONS.PKT\");\n\tif (file.Is_Available()) {\n\t\tINIClass ini;\n\t\tini.Load(file);\n\t\tint count = ini.Entry_Count(\"Missions\");\n//debugprint( \"Found %i missions in Missions.pkt\\n\", count );\n\t\tfor (int index = 0; index < count; index++) {\n\t\t\tchar const * fname = ini.Get_Entry(\"Missions\", index);\n\t\t\tchar buffer[128];\n\t\t\tini.Get_String(\"Missions\", fname, \"\", buffer, sizeof(buffer));\n#ifdef FIXIT_VERSION_3\n\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, true,\n\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#else\t//\tFIXIT_VERSION_3\n#ifdef FIXIT_CSII\t//\tchecked - ajw\n\t\t\tbool official = Is_Mission_126x126( (char *)fname);\n\t\t\tif (!official) {\n\t\t\t\tofficial = !Is_Mission_Aftermath((char *)fname);\n\t\t\t}\n\n\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, official,\n\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#else\n\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, true,\n\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#endif\n#endif\t//\tFIXIT_VERSION_3\n\t\t}\n/*\t\t//\tajw Copy file for viewing.\n\t\tCCFileClass fileCopy( \"msns_pkt.txt\" );\n\t\tfile.Seek( 0, SEEK_SET );\n\t\tlong lSize = file.Size();\n\t\tchar* pData = new char[ lSize + 1 ];\n\t\tfile.Read( pData, lSize );\n\t\tfileCopy.Write( pData, lSize );\n\t\tfileCopy.Close();\n*/\t}\n\n\t/*\n\t**\tFetch any scenario packet lists and apply them first.\n\t*/\n#ifdef WIN32\n\tWIN32_FIND_DATA block;\n\tHANDLE handle = FindFirstFile(\"*.PKT\", &block);\n\twhile (handle != INVALID_HANDLE_VALUE) {\n\t\tif ((block.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY)) == 0) {\n\t\t\tchar const * name = &block.cAlternateFileName[0];\n\t\t\tif (*name == '\\0') name = &block.cFileName[0];\n//Mono_Printf(\"Found file '%s'.\\n\", block.cAlternateFileName);\n//Mono_Printf(\"Found file '%s'.\\n\", block.cFileName);\n//debugprint(\"Found file '%s'.\\n\", block.cAlternateFileName);\n//debugprint(\"Found file '%s'.\\n\", block.cFileName);\n//debugprint( \"Found alternate PKT file.\\n\" );\n\t\t\tCCFileClass file(name);\n\t\t\tINIClass ini;\n\t\t\tini.Load(file);\n\n\t\t\tint count = ini.Entry_Count(\"Missions\");\n\t\t\tfor (int index = 0; index < count; index++) {\n\t\t\t\tchar const * fname = ini.Get_Entry(\"Missions\", index);\n\t\t\t\tchar buffer[128];\n\t\t\t\tini.Get_String(\"Missions\", fname, \"\", buffer, sizeof(buffer));\n\n#ifdef FIXIT_VERSION_3\n\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, true,\n\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#else\t//\tFIXIT_VERSION_3\n#ifdef FIXIT_CSII\t//\tchecked - ajw\n\t\t\t\tbool official = Is_Mission_126x126( (char *)fname);\n\t\t\t\tif (!official) {\n\t\t\t\t\tofficial = !Is_Mission_Aftermath((char *)fname);\n\t\t\t\t}\n\t\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, official,\n\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#else\n\t\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, true,\n\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#endif\n#endif\t//\tFIXIT_VERSION_3\n\t\t\t}\n\t\t}\n\n\t\tif (FindNextFile(handle, &block) == 0) break;\n\t}\n\n\n  #ifdef FIXIT_CSII\t\t//\tchecked - ajw\n\t/*\n\t**\tFetch the Counterstrike multiplayer scenario packet data.\n\t** Load the scenarios regardless of whether counterstrike's installed,\n\t** and at the point of hosting a network game, enable the counterstrike\n\t** maps only if they have CS installed.  If they don't, then the maps\n\t** are available as a guest, but not as a host, which fixes a multitude\n\t** of problems without obviously giving the maps away to non-CS owners.\n\t*/\n#ifdef FIXIT_VERSION_3\n\tif( Is_Counterstrike_Installed() )\n\t{\n#endif\n\t\tCCFileClass file2(\"CSTRIKE.PKT\");\n\t\tif (file2.Is_Available()) {\n\t\t\tINIClass ini;\n\t\t\tini.Load(file2);\n\t\t\tint count = ini.Entry_Count(\"Missions\");\n//debugprint( \"Found %i missions in cstrike.pkt\\n\", count );\n\t\t\tfor (int index = 0; index < count; index++) {\n\t\t\t\tchar const * fname = ini.Get_Entry(\"Missions\", index);\n\t\t\t\tchar buffer[128];\n\t\t\t\tini.Get_String(\"Missions\", fname, \"\", buffer, sizeof(buffer));\n#ifdef FIXIT_VERSION_3\n\t\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, true,\n\t\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#else\n\t\t\t\tbool official = Is_Mission_126x126( (char *)fname);\n\t\t\t\tif (!official) {\n\t\t\t\t\tofficial = !Is_Mission_Aftermath((char *)fname);\n\t\t\t\t}\n\t\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, official,\n\t\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#endif\n\t\t\t}\n/*\t\t\t//\tajw Copy file for viewing.\n\t\t\tCCFileClass fileCopy( \"cs_pkt.txt\" );\n\t\t\tfile2.Seek( 0, SEEK_SET );\n\t\t\tlong lSize = file2.Size();\n\t\t\tchar* pData = new char[ lSize + 1 ];\n\t\t\tfile2.Read( pData, lSize );\n\t\t\tfileCopy.Write( pData, lSize );\n\t\t\tfileCopy.Close();\n*/\t\t}\n#ifdef FIXIT_VERSION_3\n\t}\n#endif\n  #endif\n\n#ifdef FIXIT_VERSION_3\t\t//\tAftermath scenarios are now in their own pkt file.\n\tif( Is_Aftermath_Installed() )\n\t{\n\t\tCCFileClass file2(\"AFTMATH.PKT\");\n\t\tif (file2.Is_Available()) {\n\t\t\tINIClass ini;\n\t\t\tini.Load(file2);\n\t\t\tint count = ini.Entry_Count(\"Missions\");\n//debugprint( \"Found %i missions in aftmath.pkt\\n\", count );\n\t\t\tfor (int index = 0; index < count; index++) {\n\t\t\t\tchar const * fname = ini.Get_Entry(\"Missions\", index);\n\t\t\t\tchar buffer[128];\n\t\t\t\tini.Get_String(\"Missions\", fname, \"\", buffer, sizeof(buffer));\n\t\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, true,\n\t\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n\t/*\n\t** Scan the current directory for any loose .MPR files and build the appropriate entries\n\t**  into the scenario list list\n\t*/\n\tchar const * file_name;\n\tchar name_buffer[128];\n\tchar digest_buffer[32];\n\n\thandle = FindFirstFile ( \"*.MPR\" , &block );\n\twhile (handle != INVALID_HANDLE_VALUE) {\n\t\tif ((block.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY)) == 0) {\n\t\t\tfile_name = &block.cAlternateFileName[0];\n\t\t\tif (*file_name == '\\0') file_name = &block.cFileName[0];\n//debugprint( \"Found MPR '%s'\\n\", file_name );\n\t\t\tCCFileClass file(file_name);\n\t\t\tINIClass ini;\n\t\t\tini.Load(file);\n\n\t\t\tini.Get_String (\"Basic\", \"Name\", \"No Name\", name_buffer, sizeof (name_buffer) );\n\t\t\tini.Get_String (\"Digest\", \"1\", \"No Digest\", digest_buffer, sizeof (digest_buffer) );\n\t\t\tScenarios.Add (new MultiMission (file_name, name_buffer, digest_buffer,ini.Get_Bool(\"Basic\", \"Official\", false), false ));\n\t\t}\n\n\t\tif (FindNextFile(handle, &block) == 0) break;\n\t}\n\n#else\t//WIN32\n\n#error\tWhat? You think you can still build the DOS version after all this time?\n\n\tchar name_buffer[128];\n\tchar digest_buffer[32];\n\n\tstruct find_t block;\n\tif (_dos_findfirst(\"*.PKT\", _A_NORMAL, &block) == 0) {\n\t\tdo {\n\t\t\tCCFileClass file(block.name);\n\t\t\tINIClass ini;\n\t\t\tini.Load(file);\n\t\t\tint count = ini.Entry_Count(\"Missions\");\n\t\t\tfor (int index = 0; index < count; index++) {\n\t\t\t\tchar const * fname = ini.Get_Entry(\"Missions\", index);\n\t\t\t\tchar buffer[128];\n\t\t\t\tini.Get_String(\"Missions\", fname, \"\", buffer, sizeof(buffer));\n#ifdef FIXIT_CSII\n\t\t\t\tbool official = Is_Mission_126x126( (char *)fname);\n\t\t\t\tif (!official) {\n\t\t\t\t\tofficial = !Is_Mission_Aftermath((char *)fname);\n\t\t\t\t}\n\t\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, official,\n\t\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#else\n\t\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, true,\n\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#endif\n\t\t\t}\n\n\t\t} while(_dos_findnext(&block) == 0);\n\t}\n\n\n\t/*\n\t** Scan the current directory for any loose .MPR files and build the appropriate entries\n\t**  into the scenario list list\n\t*/\n\tif (_dos_findfirst(\"*.MPR\", _A_NORMAL, &block) == 0) {\n\t\tdo {\n\t\t\tCCFileClass file(block.name);\n\t\t\tINIClass ini;\n\t\t\tini.Load(file);\n\t\t\tini.Get_String (\"Basic\", \"Name\", \"No Name\", name_buffer, sizeof (name_buffer) );\n\t\t\tini.Get_String (\"Digest\", \"1\", \"No Digest\", digest_buffer, sizeof (digest_buffer) );\n\t\t\tbool official = ini.Get_Bool(\"Basic\", \"Official\", false);\n\t\t\tScenarios.Add (new MultiMission (block.name, name_buffer, digest_buffer, official, false ));\n\t\t} while(_dos_findnext(&block) == 0);\n\t}\n\n  #ifdef FIXIT_CSII\n\t/*\n\t**\tFetch the Counterstrike multiplayer scenario packet data.\n\t** Load the scenarios regardless of whether counterstrike's installed,\n\t** and at the point of hosting a network game, enable the counterstrike\n\t** maps only if they have CS installed.  If they don't, then the maps\n\t** are available as a guest, but not as a host, which fixes a multitude\n\t** of problems without obviously giving the maps away to non-CS owners.\n\t*/\n//\tif (Is_Counterstrike_Installed()) {\n\t\tCCFileClass file2(\"CSTRIKE.PKT\");\n\t\tif (file2.Is_Available()) {\n\t\t\tINIClass ini;\n\t\t\tini.Load(file2);\n\t\t\tint count = ini.Entry_Count(\"Missions\");\n\t\t\tfor (int index = 0; index < count; index++) {\n\t\t\t\tchar const * fname = ini.Get_Entry(\"Missions\", index);\n\t\t\t\tchar buffer[128];\n\t\t\t\tini.Get_String(\"Missions\", fname, \"\", buffer, sizeof(buffer));\n\t\t\t\tbool official = Is_Mission_126x126( (char *)fname);\n\t\t\t\tif (!official) {\n\t\t\t\t\tofficial = !Is_Mission_Aftermath((char *)fname);\n\t\t\t\t}\n\n\t\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, official,\n\t\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n\t\t\t}\n\t\t}\n//\t}\n  #endif\n\n#endif\t//WIN32\n}\n\n\n/***************************************************************************\n * SessionClass::Free_Scenario_Descriptions -- frees scen. descriptions    *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/05/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid SessionClass::Free_Scenario_Descriptions(void)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tClear the scenario descriptions & filenames\n\t//------------------------------------------------------------------------\n\tfor (int index = 0; index < Scenarios.Count(); index++) {\n\t\tdelete Scenarios[index];\n\t}\n\tScenarios.Clear();\n//\tFilenum.Clear();\n\n\t//------------------------------------------------------------------------\n\t//\tClear the initstring entries\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < InitStrings.Count(); i++) {\n\t\tdelete InitStrings[i];\n\t}\n\tInitStrings.Clear();\n\n\t//------------------------------------------------------------------------\n\t//\tClear the dialing entries\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < PhoneBook.Count(); i++) {\n\t\tdelete PhoneBook[i];\n\t}\n\tPhoneBook.Clear();\n\n}\t/* end of Free_Scenario_Descriptions */\n\n\n/***************************************************************************\n * SessionClass::Trap_Object -- searches for an object, for debugging\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/02/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid SessionClass::Trap_Object(void)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t// Initialize\n\t//------------------------------------------------------------------------\n\tTrapObject.Ptr.All = NULL;\n\n\t//------------------------------------------------------------------------\n\t// Search for the object based upon its type, then its coordinate or\n\t// 'this' pointer value.\n\t//------------------------------------------------------------------------\n\tswitch (TrapObjType) {\n\t\tcase RTTI_AIRCRAFT:\n\t\t\tfor (i = 0; i < Aircraft.Count(); i++) {\n\t\t\t\tif (Aircraft.Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tAircraft.Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Aircraft = Aircraft.Ptr(i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_ANIM:\n\t\t\tfor (i = 0; i < Anims.Count(); i++) {\n\t\t\t\tif (Anims.Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tAnims.Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Anim = Anims.Ptr(i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_BUILDING:\n\t\t\tfor (i = 0; i < Buildings.Count(); i++) {\n\t\t\t\tif (Buildings.Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tBuildings.Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Building = Buildings.Ptr(i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_BULLET:\n\t\t\tfor (i = 0; i < Bullets.Count(); i++) {\n\t\t\t\tif (Bullets.Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tBullets.Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Bullet = Bullets.Ptr(i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_INFANTRY:\n\t\t\tfor (i = 0; i < Infantry.Count(); i++) {\n\t\t\t\tif (Infantry.Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tInfantry.Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Infantry = Infantry.Ptr(i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_UNIT:\n\t\t\tfor (i = 0; i < Units.Count(); i++) {\n\t\t\t\tif (Units.Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tUnits.Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Unit = Units.Ptr(i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t//.....................................................................\n\t\t// Last-ditch find-the-object-right-now-darnit loop\n\t\t//.....................................................................\n\t\tcase RTTI_NONE:\n\t\t\tfor (i = 0; i < Aircraft.Count(); i++) {\n\t\t\t\tif (Aircraft.Raw_Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tAircraft.Raw_Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Aircraft = Aircraft.Raw_Ptr(i);\n\t\t\t\t\tTrapObjType = RTTI_AIRCRAFT;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (i = 0; i < Anims.Count(); i++) {\n\t\t\t\tif (Anims.Raw_Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tAnims.Raw_Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Anim = Anims.Raw_Ptr(i);\n\t\t\t\t\tTrapObjType = RTTI_ANIM;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (i = 0; i < Buildings.Count(); i++) {\n\t\t\t\tif (Buildings.Raw_Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tBuildings.Raw_Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Building = Buildings.Raw_Ptr(i);\n\t\t\t\t\tTrapObjType = RTTI_BUILDING;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (i = 0; i < Bullets.Count(); i++) {\n\t\t\t\tif (Bullets.Raw_Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tBullets.Raw_Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Bullet = Bullets.Raw_Ptr(i);\n\t\t\t\t\tTrapObjType = RTTI_BULLET;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (i = 0; i < Infantry.Count(); i++) {\n\t\t\t\tif (Infantry.Raw_Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tInfantry.Raw_Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Infantry = Infantry.Raw_Ptr(i);\n\t\t\t\t\tTrapObjType = RTTI_INFANTRY;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (i = 0; i < Units.Count(); i++) {\n\t\t\t\tif (Units.Raw_Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tUnits.Raw_Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Unit = Units.Raw_Ptr(i);\n\t\t\t\t\tTrapObjType = RTTI_UNIT;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n\n/***************************************************************************\n * SessionClass::Compute_Unique_ID -- computes unique local ID number      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/07/1995 BRR : Created.                                             *\n *=========================================================================*/\nunsigned long SessionClass::Compute_Unique_ID(void)\n{\n\ttime_t tm;\n\tunsigned long id;\n\tstruct diskfree_t dtable;\n\tchar *path;\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t// Start with the seconds since Jan 1, 1970 (system local time)\n\t//------------------------------------------------------------------------\n\ttime(&tm);\n\tid = (unsigned long)tm;\n\n\t//------------------------------------------------------------------------\n\t// Now add in the free space on the hard drive\n\t//------------------------------------------------------------------------\n\tif (_dos_getdiskfree(3, &dtable) == 0) {\n\t\tAdd_CRC(&id, (unsigned long)dtable.avail_clusters);\n\t\tAdd_CRC(&id, (unsigned long)dtable.total_clusters);\n\t\tAdd_CRC(&id, (unsigned long)dtable.bytes_per_sector);\n\t\tAdd_CRC(&id, (unsigned long)dtable.sectors_per_cluster);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Add in every byte in the user's path environment variable\n\t//------------------------------------------------------------------------\n\tpath = getenv(\"PATH\");\n\tif (path) {\n\t\tfor (i = 0; i < strlen(path); i++) {\n\t\t\tAdd_CRC(&id, (unsigned long)path[i]);\n\t\t}\n\t}\n\n\treturn (id);\n\n}\t// end of Compute_Unique_ID\n\n\n\n\nMultiMission::MultiMission(char const * filename, char const * description, char const * digest, bool official, bool expansion)\n{\n\tSet_Filename(filename);\n\tSet_Description(description);\n\tSet_Digest(digest);\n\tSet_Official(official);\n\tSet_Expansion(expansion);\n}\n\n\nvoid MultiMission::Draw_It(int , int x, int y, int width, int height, bool selected, TextPrintType flags) const\n{\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\tstatic int _tabs[] = {35, 60, 80, 100};\n\tif ((flags & 0x0F) == TPF_6PT_GRAD || (flags & 0x0F) == TPF_EFNT) {\n\n\t\tif (selected) {\n\t\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\t\tLogicPage->Fill_Rect(x, y, x + width - 1, y + height - 1, scheme->Shadow);\n\t\t} else {\n\t\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t\t}\n\t\t}\n\n\t\tConquer_Clip_Text_Print(ScenarioDescription, x, y, scheme, TBLACK, flags, width, _tabs);\n\t} else {\n\t\tConquer_Clip_Text_Print(ScenarioDescription, x, y, (selected ? &ColorRemaps[PCOLOR_DIALOG_BLUE] : &ColorRemaps[PCOLOR_GREY]), TBLACK, flags, width, _tabs);\n\t}\n}\n\n\nvoid MultiMission::Set_Description(char const * description)\n{\n\tif (description != NULL) {\n\t\tstrncpy(ScenarioDescription, description, ARRAY_SIZE(ScenarioDescription));\n\t\tScenarioDescription[ARRAY_SIZE(ScenarioDescription)-1] = '\\0';\n\t}\n}\n\n\nvoid MultiMission::Set_Filename(char const * filename)\n{\n\tif (filename != NULL) {\n\t\tstrncpy(Filename, filename, ARRAY_SIZE(Filename));\n\t\tFilename[ARRAY_SIZE(Filename)-1] = '\\0';\n\t}\n}\n\nvoid MultiMission::Set_Digest(char const * digest)\n{\n\tif (digest != NULL) {\n\t\tstrncpy(Digest, digest, ARRAY_SIZE(Digest));\n\t\tDigest[ARRAY_SIZE(Digest)-1] = '\\0';\n\t}\n\telse\n\t{\n\t\tstrcpy( Digest, \"NODIGEST\" );\n\t}\n}\n\nvoid MultiMission::Set_Official (bool official)\n{\n\tIsOfficial = official;\n}\n\nvoid MultiMission::Set_Expansion (bool expansion)\n{\n\tIsExpansion = expansion;\n}\n\n\n/************************** end of session.cpp *****************************/\n"
  },
  {
    "path": "CODE/SESSION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /counterstrike/SESSION.H 4     3/10/97 6:23p Steve_tall $ */\n/***************************************************************************\n ***              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               ***\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : SESSION.H                                *\n *                                                                         *\n *                   Programmer : Bill R. Randolph                         *\n *                                                                         *\n *                   Start Date : 11/30/95                                 *\n *                                                                         *\n *                  Last Update : November 30, 1995 [BRR]                  *\n *                                                                         *\n * The purpose of this class is to contain those variables & routines\t\t*\n * specifically related to a multiplayer game.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef SESSION_H\n#define SESSION_H\n\n#include \"ipxaddr.h\"\n#include \"msglist.h\"\n#include \"connect.h\"\n\n//---------------------------------------------------------------------------\n// Forward declarations\n//---------------------------------------------------------------------------\nclass AircraftClass;\nclass AnimClass;\nclass BuildingClass;\nclass BulletClass;\nclass InfantryClass;\nclass UnitClass;\nclass PhoneEntryClass;\nclass CellClass;\n\n//---------------------------------------------------------------------------\n// Defines\n//---------------------------------------------------------------------------\n//...........................................................................\n// Various limiting values\n//...........................................................................\n#define\tMPLAYER_BUILD_LEVEL_MAX\t\t10\t\t// max build level in multiplay\n#define\tMAX_MPLAYER_COLORS\t\t\t8\t\t// max # of colors\n\n//...........................................................................\n// Max sizes of packets we want to send\n// The IPX packet's size is IPX's max size (546), rounded down to accommodate\n// the max number of events possible.\n//...........................................................................\n#define\tMAX_IPX_PACKET_SIZE\t\t\t(((546 - sizeof(CommHeaderType)) / \\\n\t\t\t\t\t\t\t\t\t\t\t\tsizeof(EventClass) ) * sizeof(EventClass))\n#define\tMAX_SERIAL_PACKET_SIZE\t\t256\n\n//...........................................................................\n// Max length of player names fields; attempt to use the constant for the\n// HouseClass, if it's been defined; otherwise, define it myself.\n//...........................................................................\n#ifdef HOUSE_NAME_MAX\n#define\tMPLAYER_NAME_MAX\t\t\t\tHOUSE_NAME_MAX\n#else\n#define\tMPLAYER_NAME_MAX\t\t\t\t12\t\t// max length of a player's name\n#endif\n\n//...........................................................................\n// Values to control the multiplayer score screen\n//...........................................................................\n#define\tMAX_MULTI_NAMES\t8\t\t// max # names (rows) on the score screen\n#define\tMAX_MULTI_GAMES\t4\t\t// max # games (columns) on the score screen\n\n//...........................................................................\n// Min value for MaxAhead, for both net & modem; only applies for\n// COMM_PROTOCOL_MULTI_E_COMP.\n//...........................................................................\n#define MODEM_MIN_MAX_AHEAD\t\t\t5\n#define NETWORK_MIN_MAX_AHEAD\t\t\t2\n\n//...........................................................................\n// Send period (in frames) for COMM_PROTOCOL_MULTI_E_COMP and above\n//...........................................................................\n#define DEFAULT_FRAME_SEND_RATE\t\t3\n\n//...........................................................................\n// Modem-specific constants\n//...........................................................................\n#define\tPORTBUF_MAX\t\t\t\t\t\t64\t\t// dialog field sizes\n#define\tIRQBUF_MAX\t\t\t\t\t\t3\n#define\tBAUDBUF_MAX\t\t\t\t\t\t7\n#define\tINITSTRBUF_MAX\t\t\t\t\t41\n#define\tCWAITSTRBUF_MAX\t\t\t\t16\n#define\tCREDITSBUF_MAX\t\t\t\t\t5\n#define\tPACKET_TIMING_TIMEOUT\t\t40\t\t// ticks b/w sending a timing packet\n#define\tMODEM_NAME_MAX\t\t\t\t\tPORTBUF_MAX - 1\t// Max length of modem name in list box\n\n//---------------------------------------------------------------------------\n// Enums\n//---------------------------------------------------------------------------\n//...........................................................................\n// Types of games; used to tell which protocol we're using\n//...........................................................................\ntypedef enum GameEnum {\n\tGAME_NORMAL,\t\t\t\t\t\t\t\t\t// not multiplayer\n\tGAME_MODEM,\t\t\t\t\t\t\t\t\t\t// modem game\n\tGAME_NULL_MODEM,\t\t\t\t\t\t\t\t// NULL-modem\n\tGAME_IPX,\t\t\t\t\t\t\t\t\t\t// IPX Network game\n\tGAME_INTERNET,\t\t\t\t\t\t\t\t\t// Internet H2H\n\tGAME_SKIRMISH,\t\t\t\t\t\t\t\t\t// 1 plr vs. AI's\n\tGAME_TEN,\t\t\t\t\t\t\t\t\t\t// TEN Network game\n\tGAME_MPATH\t\t\t\t\t\t\t\t\t\t// MPath Network game\n} GameType;\n\n//...........................................................................\n// Various Modem-specific enums\n//...........................................................................\ntypedef enum DetectPortType {\n\tPORT_VALID = 0,\n\tPORT_INVALID,\n\tPORT_IRQ_INUSE\n} DetectPortType;\n\ntypedef enum DialStatusType {\n\tDIAL_CONNECTED\t\t\t= 0,\n\tDIAL_NO_CARRIER,\n\tDIAL_BUSY,\n\tDIAL_ERROR,\n\tDIAL_NO_DIAL_TONE,\n\tDIAL_CANCELED\n} DialStatusType;\n\ntypedef enum DialMethodType {\n\tDIAL_TOUCH_TONE = 0,\n\tDIAL_PULSE,\n\tDIAL_METHODS\n} DialMethodType;\n\ntypedef enum CallWaitStringType {\n\tCALL_WAIT_TONE_1 = 0,\n\tCALL_WAIT_TONE_2,\n\tCALL_WAIT_PULSE,\n\tCALL_WAIT_CUSTOM,\n\tCALL_WAIT_STRINGS_NUM\n} CallWaitStringType;\n\ntypedef enum ModemGameType {\n\tMODEM_NULL_HOST = 0,\n\tMODEM_NULL_JOIN,\n\tMODEM_DIALER,\n\tMODEM_ANSWERER\n} ModemGameType;\n\n//...........................................................................\n// Commands sent over the serial Global Channel\n//...........................................................................\ntypedef enum SerialCommandType {\n\tSERIAL_CONNECT\t\t\t= 100,\t// Are you there?  Hello?  McFly?\n\tSERIAL_GAME_OPTIONS\t= 101,\t// Hey, dudes, here's some new game options\n\tSERIAL_SIGN_OFF\t\t= 102,\t// Bogus, dudes, my boss is coming; I'm outta here!\n\tSERIAL_GO\t\t\t\t= 103,\t// OK, dudes, jump into the game loop!\n\tSERIAL_MESSAGE\t\t\t= 104,\t// Here's a message\n\tSERIAL_TIMING\t\t\t= 105,\t// timimg packet\n\tSERIAL_SCORE_SCREEN\t= 106,\t// player at score screen\n\tSERIAL_LOADGAME\t\t= 107,\t// Start the game, loading a saved game first\n\tSERIAL_LAST_COMMAND,\t\t\t\t// last command\n\tSERIAL_REQ_SCENARIO\t= 1000,\t// Reqest that host sends the scenario file to the other players.\n\tSERIAL_FILE_INFO\t\t= 1001,\t// Info about the file that is going to be transferred\n\tSERIAL_FILE_CHUNK\t\t= 1002,\t// A chunk of scenario\n\tSERIAL_READY_TO_GO\t= 1003,\t// Sent in response to a 'GO' command\n\tSERIAL_NO_SCENARIO\t= 1004\t// Scenario isnt available on remote machine so we cant play\n} SerialCommandType;\n\n//...........................................................................\n// Commands sent over the network Global Channel\n//...........................................................................\ntypedef enum NetCommandType {\n\tNET_QUERY_GAME,\t\t\t// Hey, what games are out there?\n\tNET_ANSWER_GAME,\t\t\t// Yo, Here's my game's name!\n\tNET_QUERY_PLAYER,\t\t\t// Hey, what players are in this game?\n\tNET_ANSWER_PLAYER,\t\t// Yo, I'm in that game!\n\tNET_CHAT_ANNOUNCE,\t\t// I'm at the chat screen\n\tNET_CHAT_REQUEST,\t\t\t// Respond with a CHAT_ANNOUNCE, please.\n\tNET_QUERY_JOIN,\t\t\t// Hey guys, can I play too?\n\tNET_CONFIRM_JOIN,\t\t\t// Well, OK, if you really want to.\n\tNET_REJECT_JOIN,\t\t\t// No, you can't join; sorry, dude.\n\tNET_GAME_OPTIONS,\t\t\t// Hey, dudes, here's some new game options\n\tNET_SIGN_OFF,\t\t\t\t// Bogus, dudes, my boss is coming; I'm outta here!\n\tNET_GO,\t\t\t\t\t\t// OK, jump into the game loop!\n\tNET_MESSAGE,\t\t\t\t// Here's a message\n\tNET_PING,\t\t\t\t\t// I'm pinging you to take a time measurement\n\tNET_LOADGAME,\t\t\t\t// start a game by loading a saved game\n\tNET_REQ_SCENARIO  =1000,// Reqest that host sends the scenario file to the other players.\n\tNET_FILE_INFO\t\t=1001,// Info about the file that is going to be transferred\n\tNET_FILE_CHUNK\t\t=1002,// A chunk of scenario\n\tNET_READY_TO_GO\t=1003,// Sent in response to a 'GO' command\n\tNET_NO_SCENARIO\t=1004\t// Scenario isnt available on remote machine so we cant play\n} NetCommandType;\n\n//---------------------------------------------------------------------------\n// Structures\n//---------------------------------------------------------------------------\n//...........................................................................\n// An entry on the score screen is defined by this structure\n//...........................................................................\ntypedef struct {\n\tchar Name[MPLAYER_NAME_MAX];\n\tint Wins;\n\tint Kills[MAX_MULTI_GAMES];\n\tPlayerColorType Color;\n} MPlayerScoreType;\n\n//...........................................................................\n// Settings for the serial port\n//...........................................................................\ntypedef struct {\n\tint Port;\n\tint IRQ;\n\tint Baud;\n\tDialMethodType DialMethod;\n\tint InitStringIndex;\n\tint CallWaitStringIndex;\n\tchar CallWaitString[ CWAITSTRBUF_MAX ];\n\tbool Compression;\n\tbool ErrorCorrection;\n\tbool HardwareFlowControl;\n\tchar ModemName [ MODEM_NAME_MAX ];\n} SerialSettingsType;\n\n//...........................................................................\n//\tThis is a \"node\", used for the lists of available games & players.  The\n//\t'Game' structure is used for games; the 'Player' structure for players.\n//...........................................................................\ntypedef struct NodeNameTag {\n\tchar Name[MPLAYER_NAME_MAX];\t\t// player or game name\n\t\tIPXAddressClass Address;\n#if(TEN)\n\t\tint TenAddress;\n#endif\n#if(MPATH)\n\t\tint MPathAddress;\n#endif\n\tunion {\n\t\tstruct {\n\t\t\tunsigned char IsOpen;\t\t// is the game open?\n\t\t\tunsigned long LastTime;\t\t// last time we heard from this guy\n\t\t} Game;\n\t\tstruct {\n\t\t\tHousesType House;\t\t\t\t// \"ActLike\" House of this player\n\t\t\tPlayerColorType Color;\t\t// Color of this player\n\t\t\tHousesType ID;\t\t\t\t\t// Actual House of this player\n\t\t\tint ProcessTime;\t\t\t\t// Length of time to process players main loop\n\t\t} Player;\n\t\tstruct {\n\t\t\tunsigned long LastTime;\t\t// last time we heard from this guy\n\t\t\tunsigned char LastChance;\t// we're about to remove him from the list\n\t\t\tPlayerColorType Color;\t\t// chat player's color\n\t\t} Chat;\n\t};\n} NodeNameType;\n\n\n//...........................................................................\n// Packet sent over the serial Global Channel\n//...........................................................................\ntypedef struct {\n\tSerialCommandType Command;\t\t\t\t\t// One of the enum's defined above\n\tchar Name[MPLAYER_NAME_MAX];\t\t\t\t// Player or Game Name\n\tunsigned char ID;\t\t\t\t\t\t\t\t// unique ID of sender of message\n\tunion {\n\t\tstruct {\n\t\t\tHousesType House;\t\t\t\t\t\t\t\t// player's House\n\t\t\tPlayerColorType Color;\t\t\t\t\t\t// player's color or SIGNOFF ID\n\t\t\tunsigned long MinVersion;\t\t\t\t\t// min version this game supports\n\t\t\tunsigned long MaxVersion;\t\t\t\t\t// max version this game supports\n\t\t\tchar Scenario[DESCRIP_MAX];\t\t\t\t// Scenario name\n\t\t\tunsigned int Credits;\t\t\t\t\t\t// player's credits\n\t\t\tunsigned int IsBases\t\t: 1;\t\t\t\t// 1 = bases are allowed\n\t\t\tunsigned int IsTiberium\t: 1;\t\t\t\t// 1 = tiberium is allowed\n\t\t\tunsigned int IsGoodies\t: 1;\t\t\t\t// 1 = goodies are allowed\n\t\t\tunsigned int IsGhosties\t: 1;\t\t\t\t// 1 = ghosts are allowed\n\t\t\tunsigned int OfficialScenario : 1;\t\t//\tIs this scenario an official Westwood one?\n\t\t\tint CheatCheck;\t\t\t\t\t\t\t\t// Unique ID of \"rules.ini\" file.\n\t\t\tunsigned char BuildLevel;\t\t\t\t\t// buildable level\n\t\t\tunsigned char UnitCount;\t\t\t\t\t// max # units\n\t\t\tunsigned char AIPlayers;\t\t\t\t\t// # of AI players allowed\n\t\t\tint Seed;\t\t\t\t\t\t\t\t\t\t// random number seed\n\t\t\tSpecialClass Special;\t\t\t\t\t\t// command-line options\n\t\t\tunsigned int GameSpeed;\t\t\t\t\t\t// Game Speed\n\t\t\tunsigned long ResponseTime;\t\t\t\t// packet response time\n\t\t\tunsigned int FileLength;\t\t\t\t\t// Length of scenario file to expect from host.\n#ifdef WOLAPI_INTEGRATION\n\t\t\tchar ShortFileName[13];\t\t\t\t\t\t// Name of scenario file to expect from host\n#else\n\t\t\tchar ShortFileName[12];\t\t\t\t\t\t// Name of scenario file to expect from host\n#endif\n\t\t\tunsigned char FileDigest[32];\t\t\t\t// Digest of scenario file to expect from host\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\tajw - This is not necessarily null-terminated.\n\t\t} ScenarioInfo;\n\t\tstruct {\n\t\t\tchar Message[MAX_MESSAGE_LENGTH];\t\t// inter-player message\n\t\t\tPlayerColorType Color;\t\t\t\t\t\t// player's color or SIGNOFF ID\n\t\t} Message;\n\t\tstruct {\n\t\t\tPlayerColorType Color;\t\t\t\t\t\t// player's color or SIGNOFF ID\n\t\t} Chat;\n\t};\n} SerialPacketType;\n\n//...........................................................................\n// Other packet sent over the serial global channel (for file transfers)\n//...........................................................................\n#define MAX_SEND_FILE_PACKET_SIZE MAX_SERIAL_PACKET_SIZE - 64\ntypedef struct {\n\tSerialCommandType\tCommand;\t\t\t\t\t// Enum defined above. Should be a file transfer enum.\n\tunsigned short \tBlockNumber;\t\t\t// Index position of this file chunk in the file\n\tunsigned short\t\tBlockLength;\t\t\t// Length of data in the RawData buffer\n\tunsigned char \t\tRawData\t[MAX_SEND_FILE_PACKET_SIZE];\n} RemoteFileTransferType;\n\n\n//...........................................................................\n// Packet sent over the network Global Channel\n//...........................................................................\ntypedef struct GlobalPacketType {\n\tNetCommandType Command;\t\t\t\t\t\t// One of the enum's defined above\n\tchar Name[MPLAYER_NAME_MAX];\t\t\t\t// Player or Game Name\n\tunion {\n\t\tstruct {\n\t\t\tunsigned int IsOpen\t\t: 1;\t\t// 1 = game is open for joining\n\t\t} GameInfo;\n\t\tstruct {\n\t\t\tHousesType House;\t\t\t\t\t\t// player's House\n\t\t\tPlayerColorType Color;\t\t\t\t// player's color\n\t\t\tunsigned long NameCRC;\t\t\t\t// CRC of player's game's name\n\t\t\tunsigned long MinVersion;\t\t\t// game's min supported version\n\t\t\tunsigned long MaxVersion;\t\t\t// game's max supported version\n\t\t\tint CheatCheck;\t\t\t\t\t\t// Unique ID of \"rules.ini\" file.\n\t\t} PlayerInfo;\n\t\tstruct {\n\t\t\tchar Scenario[DESCRIP_MAX];\t\t// Scenario Name\n\t\t\tunsigned int Credits;\t\t\t\t// player's credits\n\t\t\tunsigned int IsBases\t\t: 1;\t\t// 1 = bases are allowed\n\t\t\tunsigned int IsTiberium\t: 1;\t\t// 1 = tiberium is allowed\n\t\t\tunsigned int IsGoodies\t: 1;\t\t// 1 = goodies are allowed\n\t\t\tunsigned int IsGhosties\t: 1;\t\t// 1 = ghosts are allowed\n\t\t\tunsigned int OfficialScenario :1;// Is this scenario an official Westwood one?\n\t\t\tunsigned char BuildLevel;\t\t\t// buildable level\n\t\t\tunsigned char UnitCount;\t\t\t// max # units\n\t\t\tunsigned char AIPlayers;\t\t\t// # of AI players allowed\n\t\t\tint Seed;\t\t\t\t\t\t\t\t// random number seed\n\t\t\tSpecialClass Special;\t\t\t\t// command-line options\n\t\t\tunsigned int GameSpeed;\t\t\t\t// Game Speed\n\t\t\tunsigned long Version;\t\t\t\t// version # common to all players\n\t\t\tunsigned int FileLength;\t\t\t// Length of scenario file to expect from host.\n#ifdef WOLAPI_INTEGRATION\n\t\t\tchar ShortFileName[13];\t\t\t\t// Name of scenario file to expect from host\n#else\n\t\t\tchar ShortFileName[12];\t\t\t\t// Name of scenario file to expect from host\n#endif\n\t\t\tunsigned char FileDigest[32];\t\t// Digest of scenario file to expect from host\n\t\t\t\t\t\t\t\t\t\t\t\t//\tajw - This is not necessarily null-terminated.\n\t\t} ScenarioInfo;\n\t\tstruct {\n\t\t\tchar Buf[MAX_MESSAGE_LENGTH];\t\t// inter-user message\n\t\t\tPlayerColorType Color;\t\t\t\t\t// color of sender of message\n\t\t\tunsigned long NameCRC;\t\t\t\t// CRC of sender's Game Name\n\t\t} Message;\n\t\tstruct {\n\t\t\tint OneWay;\t\t\t\t\t\t\t\t// one-way response time\n\t\t} ResponseTime;\n\t\tstruct {\n\t\t\tint Why;\t\t\t\t\t\t\t\t\t// why were we rejected from the game?\n\t\t} Reject;\n\t\tstruct {\n\t\t\tunsigned long ID;\t\t\t\t\t\t// unique ID for this chat node\n\t\t\tPlayerColorType Color;\t\t\t\t// my color\n\t\t} Chat;\n\t};\n} GlobalPacketType;\n\n\n//...........................................................................\n// For finding sync bugs; filled in by the engine when certain conditions\n// are met; the pointers allow examination of objects in the debugger.\n//...........................................................................\ntypedef struct {\n\tunion {\n\t\tAircraftClass *Aircraft;\n\t\tAnimClass *Anim;\n\t\tBuildingClass *Building;\n\t\tBulletClass *Bullet;\n\t\tInfantryClass *Infantry;\n\t\tUnitClass *Unit;\n\t\tvoid *All;\n\t} Ptr;\n} TrapObjectType;\n\n/*\n**\tThis is the identifier for a multiplayer mission. This can be used to\n**\tidentify the filename of the mission as well as display the mission in a\n**\tmission selection list.\n*/\nclass MultiMission\n{\n\tpublic:\n\t\tMultiMission(char const * filename = NULL, char const * description = NULL, char const *digest = NULL, bool official = true, bool expansion = false);\n\n\t\tvoid Set_Description(char const * description);\n\t\tvoid Set_Filename(char const * filename);\n\t\tvoid Set_Digest(char const * digest);\n\t\tvoid Set_Official(bool official);\n\t\tvoid Set_Expansion(bool expansion);\n\t\tvoid Draw_It(int index, int x, int y, int width, int height, bool selected, TextPrintType flags) const;\n\t\tchar const * Description(void) const {return(ScenarioDescription);}\n\t\tchar const * Get_Filename(void) const {return(Filename);}\n\t\tchar const * Get_Digest(void) const {return(Digest);}\n\t\tbool Get_Official(void) { return (IsOfficial); }\n\t\tbool Get_Expansion(void) { return (IsExpansion); }\t//\tImplied \"IsCounterstrike\". No longer used. -ajw\n\n\tprivate:\n\t\tchar ScenarioDescription[DESCRIP_MAX];\n\t\tchar Filename[_MAX_FNAME+_MAX_EXT];\n\t\tchar Digest[32];\n\t\tbool IsOfficial;\n\t\tbool IsExpansion;\n};\n\n\ntypedef struct {\n\tint \tScenarioIndex;\t\t//Used on host machine only as index into scenario list\n\tint \tBases;\n\tint \tCredits;\n\tint \tTiberium;\n\tint \tGoodies;\n\tint \tGhosts;\n\tint \tUnitCount;\n\tint \tAIPlayers;\t\t\t// # of AI players allowed to be built\n\tchar\tScenarioDescription [DESCRIP_MAX];\t//Used on client machines only\n} GameOptionsType;\n\n//---------------------------------------------------------------------------\n// Class Definition\n//---------------------------------------------------------------------------\nclass SessionClass\n{\n\t//------------------------------------------------------------------------\n\t// Public interface\n\t//------------------------------------------------------------------------\n\tpublic:\n\t\t//.....................................................................\n\t\t// Constructor/Destructor\n\t\t//.....................................................................\n\t\tSessionClass(void);\n\t\t~SessionClass(void);\n\n\t\t//.....................................................................\n\t\t// Initialization\n\t\t//.....................................................................\n\t\tvoid One_Time(void);\n\t\tvoid Init(void);\n\n\t\t//.....................................................................\n\t\t// Reads/writes to the INI file\n\t\t//.....................................................................\n\t\tvoid Read_MultiPlayer_Settings (void);\n\t\tvoid Write_MultiPlayer_Settings (void);\n\t\tvoid Read_Scenario_Descriptions (void);\n\t\tvoid Free_Scenario_Descriptions(void);\n\n\t\t//.....................................................................\n\t\t// Utility functions\n\t\t//.....................................................................\n\t\tint Create_Connections(void);\n\t\tbool Am_I_Master(void);\n\t\tunsigned long Compute_Unique_ID(void);\n\n#if(TEN)\n\t\tint Create_TEN_Connections(void);\n#endif\t// TEN\n\n#if(MPATH)\n\t\tint Create_MPATH_Connections(void);\n#endif\t// MPATH\n\n\t\t//.....................................................................\n\t\t// File I/O\n\t\t//.....................................................................\n\t\tint Save(Pipe & file) const;\n\t\tint Load(Straw & file);\n\t\tint Save(CCFileClass & file);\n\t\tint Load(CCFileClass & file);\n\n\t\t//.....................................................................\n\t\t// Debugging / Sync Bugs\n\t\t//.....................................................................\n\t\tvoid Trap_Object(void);\n\n\t\t//---------------------------------------------------------------------\n\t\t// Public Data\n\t\t//---------------------------------------------------------------------\n\t\t//.....................................................................\n\t\t// The type of session being played\n\t\t//.....................................................................\n\t\tGameType Type;\n\n\t\t//.....................................................................\n\t\t// The current communications protocol\n\t\t//.....................................................................\n\t\tCommProtocolType CommProtocol;\n\n\t\t//.....................................................................\n\t\t// Game options\n\t\t//.....................................................................\n\t\tGameOptionsType Options;\n\n\t\t//.....................................................................\n\t\t// Unique workstation ID, for detecting my own packets\n\t\t//.....................................................................\n\t\tunsigned long UniqueID;\n\n\t\t//.....................................................................\n\t\t// Player's local options\n\t\t//.....................................................................\n\t\tchar Handle[MPLAYER_NAME_MAX];\t\t// player name\n\t\tPlayerColorType PrefColor;\t\t\t\t// preferred color index\n\t\tPlayerColorType ColorIdx;\t\t\t\t// actual color index\n\t\tHousesType House;\t\t\t\t\t\t\t// GDI / NOD\n\t\tint ObiWan;\t\t\t\t\t\t\t\t\t// 1 = player can see all\n\t\tint Solo;\t\t\t\t\t\t\t\t\t// 1 = player can play alone\n\n\t\t//.....................................................................\n\t\t// Max allowable # of players & actual # of (human) players\n\t\t//.....................................................................\n\t\tint MaxPlayers;\n\t\tint NumPlayers;\n\n\t\t//.....................................................................\n\t\t// Frame-sync'ing timing variables\n\t\t// 'MaxAhead' is the number of frames ahead of this one to execute\n\t\t// a given packet.  It's set by the RESPONSE_TIME event.\n\t\t// 'FrameSendRate' is the # frames between data packets\n\t\t//.....................................................................\n\t\tunsigned long MaxAhead;\n\t\tunsigned long FrameSendRate;\n\n\t\tint\t\t\tDesiredFrameRate;\n\n\t\tint\t\t\tProcessTimer;\n\t\tint\t\t\tProcessTicks;\n\t\tint\t\t\tProcessFrames;\n\n\t\t//.....................................................................\n\t\t// This flag is set when we've loaded a multiplayer game.\n\t\t//.....................................................................\n\t\tint LoadGame;\n\n\t\t//.....................................................................\n\t\t// This flag is set when the modem game saves the game due to a lost\n\t\t// connection.\n\t\t//.....................................................................\n\t\tint EmergencySave;\n\n\t\t//.....................................................................\n\t\t// List of scenarios & their file numbers\n\t\t//.....................................................................\n\t\tDynamicVectorClass<MultiMission *> Scenarios;\n//\t\tDynamicVectorClass <char *> Scenarios;\n//\t\tDynamicVectorClass <int> Filenum;\n\n\t\tchar ScenarioFileName[_MAX_FNAME+_MAX_EXT+1];\t//File name of scenario to load\n\n\t\tchar ScenarioDigest [32];\t\t\t\t\t\t\t\t//Digest of scenario to load\n\t\tunsigned int ScenarioFileLength;\n\t\tbool ScenarioIsOfficial;\n\n\t\tchar ScenarioRequests[20];\t\t//Which players requested scenario files\n\t\tint  RequestCount;\n\t\tIPXAddressClass\tHostAddress;\n\n\t\t//.....................................................................\n\t\t// This is the multiplayer messaging system\n\t\t//.....................................................................\n\t\tMessageListClass Messages;\n\t\tIPXAddressClass MessageAddress;\n\t\tchar LastMessage[MAX_MESSAGE_LENGTH];\n\t\tunsigned WWChat\t\t: 1;\t// 1 = go into special WW Chat mode\n\n\t\t//.....................................................................\n\t\t// This is the multiplayer scorekeeping system\n\t\t//.....................................................................\n\t\tMPlayerScoreType Score[MAX_MULTI_NAMES];\n\t\tint GamesPlayed;\t\t// # games played this run\n\t\tint NumScores;\t\t\t// # active entries in MPlayerScore\n\t\tint Winner;\t\t\t\t// index of winner of last game\n\t\tint CurGame;\t\t\t// index of current game being played\n\n\t\t//.....................................................................\n\t\t// Static arrays\n\t\t//.....................................................................\n\t\tstatic char Descriptions[100][40];\n\t\tstatic int CountMin[2];\n\t\tstatic int CountMax[2];\n\t\tstatic char * GlobalPacketNames[];\n\t\tstatic char * SerialPacketNames[];\n\n\t\t//.....................................................................\n\t\t// For Recording & Playing back a file\n\t\t//.....................................................................\n\t\tCCFileClass RecordFile;\n\t\tunsigned Record\t\t\t\t: 1;\n\t\tunsigned Play\t\t\t\t \t: 1;\n\t\tunsigned Attract\t\t\t \t: 1;\n\n\t\t//.....................................................................\n\t\t// IPX-specific variables\n\t\t//.....................................................................\n\t\tint IsBridge;\t\t\t\t\t\t\t\t// 1 = we're crossing a bridge\n\t\tIPXAddressClass BridgeNet;\t\t\t\t// address of bridge\n\t\tbool NetStealth;\t\t\t\t\t\t\t// makes us invisible\n\t\tbool NetProtect;\t\t\t\t\t\t\t// keeps others from messaging us\n\t\tbool NetOpen;\t\t\t\t\t\t\t\t// 1 = game is open for joining\n\t\tchar GameName[MPLAYER_NAME_MAX];\t\t// game's name\n\t\tGlobalPacketType GPacket;\t\t\t\t// global packet\n\t\tint GPacketlen;\t\t\t\t\t\t\t// global packet length\n\t\tIPXAddressClass GAddress;\t\t\t\t// address of sender\n\t\tunsigned short GProductID;\t\t\t\t// product ID of sender\n\t\tchar MetaPacket[MAX_IPX_PACKET_SIZE]; // packet building buffer\n\t\tint MetaSize;\t\t\t\t\t\t\t\t// size of MetaPacket\n\t\tDynamicVectorClass <NodeNameType *> Games;\t// list of games\n\t\tDynamicVectorClass <NodeNameType *> Players;\t// list of players\n\t\tDynamicVectorClass <NodeNameType *> Chat;\t\t// list of chat nodes\n\n\t\t//.....................................................................\n\t\t// Modem-specific variables\n\t\t//.....................................................................\n\t\tunsigned ModemService\t\t: 1;\t\t\t\t// 1 = service modem in Call_Back\n\t\tint CurPhoneIdx;\t\t\t\t\t\t\t// phone listing index\n\t\tSerialSettingsType SerialDefaults;\t// default serial settings\n\t\tModemGameType ModemType;\t\t\t\t// caller or answerer?\n\n\t\tDynamicVectorClass<PhoneEntryClass *> PhoneBook;\n\t\tDynamicVectorClass <char *> InitStrings;\n\t\tstatic char * DialMethodCheck[ DIAL_METHODS ];\n\t\tstatic char * CallWaitStrings[ CALL_WAIT_STRINGS_NUM ];\n\n\t\t//.....................................................................\n\t\t// For finding Sync Bugs\n\t\t//.....................................................................\n\t\tlong TrapFrame;\t\t\t\t// frame # to start trapping 'TrapObject'\n\t\tRTTIType TrapObjType;\t\t// type of object to trap\n\t\tTrapObjectType TrapObject;\t// ptr to object to trap (watch)\n\t\tCOORDINATE TrapCoord;\t\t// coord of object, 0 = ignore\n\t\tTARGET TrapTarget;\t\t\t// Target # of object, 0 = ignore\n\t\tCellClass * TrapCell;\t\t// Ptr to cell to trap (watch)\n\t\tint TrapCheckHeap;\t\t\t// true = check the heap as of TrapFrame\n\t\tlong TrapPrintCRC;\t\t\t// Frame # to print CRC state file\n\n#if(TEN)\n\t\t//\n\t\t// TEN-specific variables\n\t\t//\n\t\tchar *TenPacket;\n\t\tint TenSize;\n\t\tint TenMessageAddress;\n\t\tint TenAddress;\n\t\tint TenPlayerID;\n\t\tchar OptionsFile[256];\n\t\tint AllowSolo;\n\t\tint NetResponseTime;\n#endif\t// TEN\n\n#if(MPATH)\n\t\t//\n\t\t// MPATH-specific variables\n\t\t//\n\t\tchar *MPathPacket;\n\t\tint MPathSize;\n\t\tint MPathMessageAddress;\n\t\tint MPathAddress;\n\t\tchar OptionsFile[256];\n\t\tint AllowSolo;\n\t\tint NetResponseTime;\n#endif\t// MPATH\n};\n\n#endif\t\t// SESSION_H\n\n/*************************** end of session.h ******************************/\n"
  },
  {
    "path": "CODE/SHA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SHA.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SHA.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/03/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SHAEngine::Result -- Fetch the current digest.                                            *\n *   SHAEngine::Hash -- Process an arbitrarily long data block.                                *\n *   SHAEngine::Process_Partial -- Helper routine to process any partially accumulated data blo*\n *   SHAEngine::Process_Block -- Process a full data block into the hash accumulator.          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t<stdlib.h>\n#include\t<iostream.h>\n#include\t\"sha.h\"\n\n\n\n#if !defined(__BORLANDC__) && !defined(min)\n#define\tmin(a, b)\t\t((a)<(b))?(a):(b)\n#endif\n\n\n/***********************************************************************************************\n * SHAEngine::Process_Partial -- Helper routine to process any partially accumulated data bloc *\n *                                                                                             *\n *    This routine will see if there is a partial block already accumulated in the holding     *\n *    buffer. If so, then the data is fetched from the source such that a full buffer is       *\n *    accumulated and then processed. If there is insufficient data to fill the buffer, then   *\n *    it accumulates what data it can and then returns so that this routine can be called      *\n *    again later.                                                                             *\n *                                                                                             *\n * INPUT:   data  -- Reference to a pointer to the data. This pointer will be modified if      *\n *                   this routine consumes any of the data in the buffer.                      *\n *                                                                                             *\n *          length-- Reference to the length of the data available. If this routine consumes   *\n *                   any of the data, then this length value will be modified.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SHAEngine::Process_Partial(void const * & data, long & length)\n{\n\tif (length == 0 || data == NULL) return;\n\n\t/*\n\t**\tIf there is no partial buffer and the source is greater than\n\t**\ta source block size, then partial processing is unnecessary.\n\t**\tBail out in this case.\n\t*/\n\tif (PartialCount == 0 && length >= SRC_BLOCK_SIZE) return;\n\n\t/*\n\t**\tAttach as many bytes as possible from the source data into\n\t**\tthe staging buffer.\n\t*/\n\tint add_count = min((int)length, SRC_BLOCK_SIZE - PartialCount);\n\tmemcpy(&Partial[PartialCount], data, add_count);\n\tdata = ((char const *&)data) + add_count;\n\tPartialCount += add_count;\n\tlength -= add_count;\n\n\t/*\n\t**\tIf a full staging buffer has been accumulated, then process\n\t**\tthe staging buffer and then bail.\n\t*/\n\tif (PartialCount == SRC_BLOCK_SIZE) {\n\t\tProcess_Block(&Partial[0], Acc);\n\t\tLength += (long)SRC_BLOCK_SIZE;\n\t\tPartialCount = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * SHAEngine::Hash -- Process an arbitrarily long data block.                                  *\n *                                                                                             *\n *    This is the main access routine to the SHA engine. It will take the arbitrarily long     *\n *    data block and process it. The hash value is accumulated with any previous calls to      *\n *    this routine.                                                                            *\n *                                                                                             *\n * INPUT:   data     -- Pointer to the data block to process.                                  *\n *                                                                                             *\n *          length   -- The number of bytes to process.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SHAEngine::Hash(void const * data, long length)\n{\n\tIsCached = false;\n\n\t/*\n\t**\tCheck for and handle any smaller-than-512bit blocks. This can\n\t**\tresult in all of the source data submitted to this routine to be\n\t**\tconsumed at this point.\n\t*/\n\tProcess_Partial(data, length);\n\n\t/*\n\t**\tIf there is no more source data to process, then bail. Speed reasons.\n\t*/\n\tif (length == 0) return;\n\n\t/*\n\t**\tFirst process all the whole blocks available in the source data.\n\t*/\n\tlong blocks = (length / SRC_BLOCK_SIZE);\n\tlong const * source = (long const *)data;\n\tfor (int bcount = 0; bcount < blocks; bcount++) {\n\t\tProcess_Block(source, Acc);\n\t\tLength += (long)SRC_BLOCK_SIZE;\n\t\tsource += SRC_BLOCK_SIZE/sizeof(long);\n\t\tlength -= (long)SRC_BLOCK_SIZE;\n\t}\n\n\t/*\n\t**\tProcess any remainder bytes. This data is stored in the source\n\t**\taccumulator buffer for future processing.\n\t*/\n\tdata = source;\n\tProcess_Partial(data, length);\n}\n\n\n#define\tReverse_LONG(a)\t((a>>24)&0x000000FFL) | ((a>>8)&0x0000FF00L) | ((a<<8)&0x00FF0000L) | ((a<<24)&0xFF000000L)\n\n\n/***********************************************************************************************\n * SHAEngine::Result -- Fetch the current digest.                                              *\n *                                                                                             *\n *    This routine will return the digest as it currently stands.                              *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to the buffer that will hold the digest -- 20 bytes.           *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes copied into the buffer. This will always be       *\n *          20.                                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint SHAEngine::Result(void * result) const\n{\n\t/*\n\t**\tIf the final hash result has already been calculated for the\n\t**\tcurrent data state, then immediately return with the precalculated\n\t**\tvalue.\n\t*/\n\tif (IsCached) {\n\t\tmemcpy(result, &FinalResult, sizeof(FinalResult));\n\t}\n\n\tlong length = Length + PartialCount;\n\tint partialcount = PartialCount;\n\tchar partial[SRC_BLOCK_SIZE];\n\tmemcpy(partial, Partial, sizeof(Partial));\n\n\t/*\n\t**\tCap the end of the source data stream with a 1 bit.\n\t*/\n\tpartial[partialcount] = 0x80;\n\n\t/*\n\t**\tDetermine if there is insufficient room to append the\n\t**\tdata length number to the hash source. If not, then\n\t**\tfill out the rest of the accumulator and flush it to\n\t**\tthe hash so that there will be room for the final\n\t**\tcount value.\n\t*/\n\tSHADigest acc = Acc;\n\tif ((SRC_BLOCK_SIZE - partialcount) < 9) {\n\t\tif (partialcount+1 < SRC_BLOCK_SIZE) {\n\t\t\tmemset(&partial[partialcount+1], '\\0', SRC_BLOCK_SIZE - (partialcount+1));\n\t\t}\n\t\tProcess_Block(&partial[0], acc);\n\t\tpartialcount = 0;\n\t} else {\n\t\tpartialcount++;\n\t}\n\n\t/*\n\t**\tPut the length of the source data as a 64 bit integer in the\n\t**\tlast 8 bytes of the pseudo-source data.\n\t*/\n\tmemset(&partial[partialcount], '\\0', SRC_BLOCK_SIZE - partialcount);\n\t*(long *)(&partial[SRC_BLOCK_SIZE-4]) = Reverse_LONG((length*8));\n\tProcess_Block(&partial[0], acc);\n\n\tmemcpy((char *)&FinalResult, &acc, sizeof(acc));\n\tfor (int index = 0; index < sizeof(FinalResult)/sizeof(long); index++) {\n//\tfor (int index = 0; index < SRC_BLOCK_SIZE/sizeof(long); index++) {\n\t\t(long &)FinalResult.Long[index] = Reverse_LONG(FinalResult.Long[index]);\n\t}\n\t(bool&)IsCached = true;\n\tmemcpy(result, &FinalResult, sizeof(FinalResult));\n\treturn(sizeof(FinalResult));\n}\n\n/*\n**\tThis pragma to turn off the warning \"Conversion may lose significant digits\" is to\n**\twork around a bug within the Borland compiler. It will give this warning when the\n**\t_rotl() function is called but will NOT give the warning when the _lrotl() function\n**\tis called even though they both have the same parameters and declaration attributes.\n*/\n#pragma warn -sig\ntemplate<class T>\nT _rotl(T X, int n)\n{\n\treturn(T)( ( X << n ) | ( (unsigned)X >> ((sizeof(T)*8) - n) ) );\n}\n//unsigned long _RTLENTRY _rotl(unsigned long X, int n)\n//{\n//\treturn(unsigned long)( (unsigned long)( (unsigned long)( (unsigned long)X ) << (int)n ) | (unsigned long)( ((unsigned long) X ) >> ( (int)((int)(sizeof(long)*(long)8) - (long)n) ) ) );\n//}\nvoid memrev(char * buffer, size_t length);\n\n\n/***********************************************************************************************\n * SHAEngine::Process_Block -- Process a full data block into the hash accumulator.            *\n *                                                                                             *\n *    This helper routine is called when a full block of data is available for processing      *\n *    into the hash.                                                                           *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the block of data to process.                               *\n *                                                                                             *\n *          acc      -- Reference to the hash accumulator that this hash step will be          *\n *                      accumulated into.                                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SHAEngine::Process_Block(void const * source, SHADigest & acc) const\n{\n\t/*\n\t**\tThe hash is generated by performing operations on a\n\t**\tblock of generated/seeded data.\n\t*/\n\tlong block[PROC_BLOCK_SIZE/sizeof(long)];\n\n\t/*\n\t**\tExpand the source data into a large 80 * 32bit buffer. This is the working\n\t**\tdata that will be transformed by the secure hash algorithm.\n\t*/\n\tlong const * data = (long const *)source;\n\tint index;\n\tfor (index = 0; index < SRC_BLOCK_SIZE/sizeof(long); index++) {\n\t\tblock[index] = Reverse_LONG(data[index]);\n\t}\n\n\tfor (index = SRC_BLOCK_SIZE/sizeof(long); index < PROC_BLOCK_SIZE/sizeof(long); index++) {\n//\t\tblock[index] = _rotl(block[(index-3)&15] ^ block[(index-8)&15] ^ block[(index-14)&15] ^ block[(index-16)&15], 1);\n\t\tblock[index] = _rotl(block[index-3] ^ block[index-8] ^ block[index-14] ^ block[index-16], 1);\n\t}\n\n\t/*\n\t**\tThis is the core algorithm of the Secure Hash Algorithm. It is a block\n\t**\ttransformation of 512 bit source data with a 2560 bit intermediate buffer.\n\t*/\n\tSHADigest alt = acc;\n\tfor (index = 0; index < PROC_BLOCK_SIZE/sizeof(long); index++) {\n\t\tlong temp = _rotl(alt.Long[0], 5) + Do_Function(index, alt.Long[1], alt.Long[2], alt.Long[3]) + alt.Long[4] + block[index] + Get_Constant(index);\n\t\talt.Long[4] = alt.Long[3];\n\t\talt.Long[3] = alt.Long[2];\n\t\talt.Long[2] = _rotl(alt.Long[1], 30);\n\t\talt.Long[1] = alt.Long[0];\n\t\talt.Long[0] = temp;\n\t}\n\tacc.Long[0] += alt.Long[0];\n\tacc.Long[1] += alt.Long[1];\n\tacc.Long[2] += alt.Long[2];\n\tacc.Long[3] += alt.Long[3];\n\tacc.Long[4] += alt.Long[4];\n}\n\n"
  },
  {
    "path": "CODE/SHA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SHA.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SHA.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 04/26/96                                                     *\n *                                                                                             *\n *                  Last Update : April 26, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef SHA_H\n#define SHA_H\n\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\n#include\t<stdio.h>\n#include\t<string.h>\n#include\t<stdlib.h>\n#include\t<new.h>\n\n\n/*\n**\tThis implements the Secure Hash Algorithm. It is a cryptographically\n**\tsecure hash with no known weaknesses. It generates a 160 bit hash\n**\tresult given an arbitrary length data source.\n*/\nclass SHAEngine\n{\n\tpublic:\n\t\tSHAEngine(void) : IsCached(false), Length(0), PartialCount(0) {\n\t\t\tAcc.Long[0] = SA;\n\t\t\tAcc.Long[1] = SB;\n\t\t\tAcc.Long[2] = SC;\n\t\t\tAcc.Long[3] = SD;\n\t\t\tAcc.Long[4] = SE;\n\t\t};\n\n\t\tvoid Init(void) {\n\t\t\tnew ((void*)this) SHAEngine;\n\t\t};\n\n\t\t// Fetch result as if source data were to stop now.\n\t\tint Result(void * result) const;\n\n\t\tvoid Hash(void const * data, long length);\n\n\t\tstatic int Digest_Size(void) {return(sizeof(SHADigest));}\n\n\tprivate:\n\n\t\ttypedef union {\n\t\t\tunsigned long Long[5];\n\t\t\tunsigned char Char[20];\n\t\t} SHADigest;\n\n\t\t/*\n\t\t**\tThis holds the calculated final result. It is cached\n\t\t**\there to avoid the overhead of recalculating it over\n\t\t**\tmultiple sequential requests.\n\t\t*/\n\t\tbool IsCached;\n\t\tSHADigest FinalResult;\n\n\t\tenum {\n\t\t\t// These are the initial seeds to the block accumulators.\n\t\t\tSA=0x67452301L,\n\t\t\tSB=0xefcdab89L,\n\t\t\tSC=0x98badcfeL,\n\t\t\tSD=0x10325476L,\n\t\t\tSE=0xc3d2e1f0L,\n\n\t\t\t// These are the constants used in the block transformation.\n\t\t\tK1=0x5a827999L,\t\t// t=0..19\t\t2^(1/2)/4\n\t\t\tK2=0x6ed9eba1L,\t\t// t=20..39\t\t3^(1/2)/4\n\t\t\tK3=0x8f1bbcdcL,\t\t// t=40..59\t\t5^(1/2)/4\n\t\t\tK4=0xca62c1d6L,\t\t// t=60..79\t\t10^(1/2)/4\n\n\t\t\t// Source data is grouped into blocks of this size.\n\t\t\tSRC_BLOCK_SIZE=16*sizeof(long),\n\n\t\t\t// Internal processing data is grouped into blocks this size.\n\t\t\tPROC_BLOCK_SIZE=80*sizeof(long)\n\t\t};\n\n\t\tlong Get_Constant(int index) const {\n\t\t\tif (index < 20) return K1;\n\t\t\tif (index < 40) return K2;\n\t\t\tif (index < 60) return K3;\n\t\t\treturn K4;\n\t\t};\n\n\t\t// Used for 0..19\n\t\tlong Function1(long X, long Y, long Z) const {\n\t\t\treturn(Z ^ ( X & ( Y ^ Z ) ) );\n\t\t};\n\n\t\t// Used for 20..39\n\t\tlong Function2(long X, long Y, long Z) const {\n\t\t\treturn( X ^ Y ^ Z );\n\t\t};\n\n\t\t// Used for 40..59\n\t\tlong Function3(long X, long Y, long Z) const {\n\t\t\treturn( (X & Y) | (Z & (X | Y) ) );\n\t\t};\n\n\t\t// Used for 60..79\n\t\tlong Function4(long X, long Y, long Z) const {\n\t\t\treturn( X ^ Y ^ Z );\n\t\t};\n\n\t\tlong Do_Function(int index, long X, long Y, long Z) const {\n\t\t\tif (index < 20) return Function1(X, Y, Z);\n\t\t\tif (index < 40) return Function2(X, Y, Z);\n\t\t\tif (index < 60) return Function3(X, Y, Z);\n\t\t\treturn Function4(X, Y, Z);\n\t\t};\n\n\t\t// Process a full source data block.\n\t\tvoid Process_Block(void const * source, SHADigest & acc) const;\n\n\t\t// Processes a partially filled source accumulator buffer.\n\t\tvoid Process_Partial(void const * & data, long & length);\n\n\t\t/*\n\t\t**\tThis is the running accumulator values. These values\n\t\t**\tare updated by a block processing step that occurs\n\t\t**\tevery 512 bits of source data.\n\t\t*/\n\t\tSHADigest Acc;\n\n\t\t/*\n\t\t**\tThis is the running length of the source data\n\t\t**\tprocessed so far. This total is used to modify the\n\t\t**\tresulting hash value as if it were appended to the end\n\t\t**\tof the source data.\n\t\t*/\n\t\tlong Length;\n\n\t\t/*\n\t\t**\tThis holds any partial source block. Partial source blocks are\n\t\t**\ta consequence of submitting less than block sized data chunks\n\t\t**\tto the SHA Engine.\n\t\t*/\n\t\tint PartialCount;\n\t\tchar Partial[SRC_BLOCK_SIZE];\n};\n\n\n#define\tSHA_SOURCE1\t\t\"abc\"\n#define\tSHA_DIGEST1a\t\"\\xA9\\x99\\x3E\\x36\\x47\\x06\\x81\\x6A\\xBA\\x3E\\x25\\x71\\x78\\x50\\xC2\\x6C\\x9C\\xD0\\xD8\\x9D\"\n#define\tSHA_DIGEST1b\t\"\\x01\\x64\\xB8\\xA9\\x14\\xCD\\x2A\\x5E\\x74\\xC4\\xF7\\xFF\\x08\\x2C\\x4D\\x97\\xF1\\xED\\xF8\\x80\"\n\n\n#define\tSHA_SOURCE2\t\t\"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\"\n#define\tSHA_DIGEST2a\t\"\\x84\\x98\\x3E\\x44\\x1C\\x3B\\xD2\\x6E\\xBA\\xAE\\x4A\\xA1\\xF9\\x51\\x29\\xE5\\xE5\\x46\\x70\\xF1\"\n#define\tSHA_DIGEST2b\t\"\\xD2\\x51\\x6E\\xE1\\xAC\\xFA\\x5B\\xAF\\x33\\xDF\\xC1\\xC4\\x71\\xE4\\x38\\x44\\x9E\\xF1\\x34\\xC8\"\n\n#define\tSHA_SOURCE3\t\t\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n#define\tSHA_DIGEST3a\t\"\\x34\\xAA\\x97\\x3C\\xD4\\xC4\\xDA\\xA4\\xF6\\x1E\\xEB\\x2B\\xDB\\xAD\\x27\\x31\\x65\\x34\\x01\\x6F\"\n#define\tSHA_DIGEST3b\t\"\\x32\\x32\\xAF\\xFA\\x48\\x62\\x8A\\x26\\x65\\x3B\\x5A\\xAA\\x44\\x54\\x1F\\xD9\\x0D\\x69\\x06\\x03\"\n\n#endif\n"
  },
  {
    "path": "CODE/SHAPEBTN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SHAPEBTN.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SHAPEBTN.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : September 20, 1995 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ShapeButtonClass::Draw_Me -- Renders the shape button's imagery.                          *\n *   ShapeButtonClass::Set_Shape -- Assigns a shape to this shape button.                      *\n *   ShapeButtonClass::ShapeButtonClass -- Constructor for a shape type button.                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include \"shapebtn.h\"\n\n\n/***********************************************************************************************\n * ShapeButtonClass::ShapeButtonClass -- Default Constructor for a shape type button.          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   You must call Set_Shape() before using a button constructed with this function, *\n *             and you must set X & Y, and ID.                                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nShapeButtonClass::ShapeButtonClass(void) :\n\tToggleClass(0, 0, 0, 0, 0),\n\tReflectButtonState(false)\n{\n}\n\n\n/***********************************************************************************************\n * ShapeButtonClass::ShapeButtonClass -- Constructor for a shape type button.                  *\n *                                                                                             *\n *    This is the normal constructor for a shape type button. Shape buttons are ones that      *\n *    have their imagery controlled by a shape file. The various states of the button are      *\n *    given a visual form as one of these shapes. Button dimensions are controlled by the      *\n *    first shape.                                                                             *\n *                                                                                             *\n * INPUT:   id    -- The button ID.                                                            *\n *                                                                                             *\n *          shape -- Pointer to the shape file that controls the button's display.             *\n *                                                                                             *\n *          x,y   -- The pixel coordinate of the upper left corner of the button.              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The width and height of the shape is controlled by the first shape in the       *\n *             shape file provided. This means that all the shapes in the shape file must be   *\n *             the same size.                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nShapeButtonClass::ShapeButtonClass(unsigned id, void const * shape, int x, int y) :\n\tToggleClass(id, x, y, 0, 0),\n\tReflectButtonState(false)\n{\n//\tWidth = 0;\n//\tHeight = 0;\n\tSet_Shape(shape);\n}\n\n\n/***********************************************************************************************\n * ShapeButtonClass::Set_Shape -- Assigns a shape to this shape button.                        *\n *                                                                                             *\n *    This routine will assign the specified shape to this shape object.                       *\n *                                                                                             *\n * INPUT:   data  -- Pointer to the shape to assign.                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ShapeButtonClass::Set_Shape(void const * data)\n{\n\tShapeData = data;\n\tif (ShapeData) {\n\t\tWidth = Get_Build_Frame_Width(ShapeData);\n\t\tHeight = Get_Build_Frame_Height(ShapeData);\n\t}\n}\n\n\n/***********************************************************************************************\n * ShapeButtonClass::Draw_Me -- Renders the shape button's imagery.                            *\n *                                                                                             *\n *    This function is called when the button detects that it must be redrawn. The actual      *\n *    shape to use is controled by the button's state and the shape file provided when then    *\n *    button was constructed.                                                                  *\n *                                                                                             *\n * INPUT:   forced   -- Should the button be redrawn regardless of the redraw flag?            *\n *                                                                                             *\n * OUTPUT:  bool; Was the shape redrawn?                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ShapeButtonClass::Draw_Me(int forced)\n{\n\tif (ControlClass::Draw_Me(forced) && ShapeData) {\n\n\t\t/*\n\t\t**\tHide the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Hide_Mouse(X, Y, X+Width-1, Y+Height-1);\n\t\t}\n\n\t\t/*\n\t\t**\tDraw the body & set text color.\n\t\t*/\n\t\tint shapenum = 0;\n\t\tif (IsDisabled) {\n\t\t\tshapenum = DISABLED_SHAPE;\n\t\t} else {\n\n\t\t\tif (!ReflectButtonState) {\n\n\t\t\t\tif (IsPressed) {\n\t\t\t\t\tshapenum = DOWN_SHAPE;\n\t\t\t\t} else {\n\t\t\t\t\tshapenum = UP_SHAPE;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tshapenum = IsOn;\n\t\t\t}\n\n\t\t}\n\t\tCC_Draw_Shape(ShapeData, shapenum, X, Y, WINDOW_MAIN, SHAPE_NORMAL);\n\t\t/*\n\t\t**\tDisplay the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Show_Mouse();\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n\n"
  },
  {
    "path": "CODE/SHAPEBTN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SHAPEBTN.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SHAPEBTN.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SHAPEBTN_H\n#define SHAPEBTN_H\n\n#include\t\"toggle.h\"\n\nclass ShapeButtonClass : public ToggleClass\n{\n\tpublic:\n\t\tShapeButtonClass(void);\n\t\tShapeButtonClass(unsigned id, void const * shapes, int x, int y);\n\t\tvirtual int Draw_Me(int forced=false);\n\t\tvirtual void Set_Shape(void const * data);\n\t\tvoid const * Get_Shape_Data(void) {return(ShapeData);};\n\n\t\tenum ShapeButtonClassEnums {\n\t\t\tUP_SHAPE,\t\t\t\t// Shape to use when button is \"up\".\n\t\t\tDOWN_SHAPE,\t\t\t\t// Shape to use when button is \"down\".\n\t\t\tDISABLED_SHAPE\t\t\t// Shape to use when button is disabled.\n\t\t};\n\n\t\tunsigned ReflectButtonState:1;\n\n\tprotected:\n\n\t\t/*\n\t\t**\tThis points to the shape data file. This file contains the appropriate shapes\n\t\t**\tfor this button in the offsets specified above.\n\t\t*/\n\t\tvoid const * ShapeData;\n};\n#endif\n"
  },
  {
    "path": "CODE/SHAPIPE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SHAPIPE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SHAPIPE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SHAPipe::Result -- Fetches the current SHA value.                                         *\n *   SHAPipe::Put -- Pass data through the pipe, but use it to build a SHA digest.             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"shapipe.h\"\n\n\n/***********************************************************************************************\n * SHAPipe::Put -- Pass data through the pipe, but use it to build a SHA digest.               *\n *                                                                                             *\n *    This pipe segment will not modify the data, but it will examine the data and use it when *\n *    building a SHA digest.                                                                   *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the data to flow through the pipe.                          *\n *                                                                                             *\n *          length   -- The number of bytes to submit.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes output at the distant final end of the     *\n *          pipe chain.                                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint SHAPipe::Put(void const * source, int slen)\n{\n\tSHA.Hash(source, slen);\n\treturn(Pipe::Put(source, slen));\n}\n\n\n/***********************************************************************************************\n * SHAPipe::Result -- Fetches the current SHA value.                                           *\n *                                                                                             *\n *    This routine will return the SHA digest for the data that has passed through this        *\n *    link in the pipe chain. It is a non-destructive read.                                    *\n *                                                                                             *\n * INPUT:   result   -- Pointer to the buffer to hold the SHA digest. This buffer must be      *\n *                      20 bytes long.                                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes copied into the buffer. This will be 20.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint SHAPipe::Result(void * result) const\n{\n\treturn(SHA.Result(result));\n}\n\n\n"
  },
  {
    "path": "CODE/SHAPIPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SHAPIPE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SHAPIPE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef SHAPIPE_H\n#define SHAPIPE_H\n\n#include\t\"pipe.h\"\n#include\t\"sha.h\"\n\n/*\n**\tThis class serves as a pipe that generates a Secure Hash from the data stream that flows\n**\tthrough it. It doesn't modify the data stream in any fashion.\n*/\nclass SHAPipe : public Pipe\n{\n\tpublic:\n\t\tSHAPipe(void) {}\n\t\tvirtual int Put(void const * source, int slen);\n\n\t\t// Fetch the SHA hash value (stored in result buffer -- 20 bytes long).\n\t\tint Result(void * result) const;\n\n\tprotected:\n\t\tSHAEngine SHA;\n\n\tprivate:\n\t\tSHAPipe(SHAPipe & rvalue);\n\t\tSHAPipe & operator = (SHAPipe const & pipe);\n};\n\n#endif\n"
  },
  {
    "path": "CODE/SHASTRAW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SHASTRAW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SHASTRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SHAStraw::Get -- Fetch data from the straw and process the SHA with the data.             *\n *   SHAStraw::Result -- Fetches the current SHA digest.                                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"shastraw.h\"\n\n\n/***********************************************************************************************\n * SHAStraw::Get -- Fetch data from the straw and process the SHA with the data.               *\n *                                                                                             *\n *    This routine will fetch the requested data and as it passes through this straw it will   *\n *    submit it to the SHA processor. The data that passes through is unmodified by this       *\n *    straw segment.                                                                           *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer that will hold the requested data.               *\n *                                                                                             *\n *          length   -- The length of the data requested.                                      *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes stored in the buffer. If this number is less      *\n *          than the number requested, then this indicates that the data stream has been       *\n *          exhausted.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint SHAStraw::Get(void * source, int slen)\n{\n\tif (source == NULL || slen < 1) {\n\t\treturn(0);\n\t}\n\n\tint counter = Straw::Get(source, slen);\n\tSHA.Hash(source, counter);\n\treturn(counter);\n}\n\n\n/***********************************************************************************************\n * SHAStraw::Result -- Fetches the current SHA digest.                                         *\n *                                                                                             *\n *    Use this routine to fetch the current SHA digest from the straw. It will return the      *\n *    digest of the data that has passed through this straw segment.                           *\n *                                                                                             *\n * INPUT:   result   -- Pointer to the buffer to hold the message digest. The buffer must be   *\n *                      20 bytes long.                                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes stored into the digest buffer. This will always   *\n *          be 20.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint SHAStraw::Result(void * result) const\n{\n\treturn(SHA.Result(result));\n}\n"
  },
  {
    "path": "CODE/SHASTRAW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SHASTRAW.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SHASTRAW.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef SHASTRAW_H\n#define SHASTRAW_H\n\n\n#include\t\"straw.h\"\n#include\t\"sha.h\"\n\n/*\n**\tThis class serves as a straw that generates a Secure Hash from the data stream that flows\n**\tthrough it. It doesn't modify the data stream in any fashion.\n*/\nclass SHAStraw : public Straw\n{\n\tpublic:\n\t\tSHAStraw(void) {}\n\t\tvirtual int Get(void * source, int slen);\n\n\t\t// Fetch the SHA hash value (stored in result buffer -- 20 bytes long).\n\t\tint Result(void * result) const;\n\n\tprotected:\n\t\tSHAEngine SHA;\n\n\tprivate:\n\t\tSHAStraw(SHAStraw & rvalue);\n\t\tSHAStraw & operator = (SHAStraw const & straw);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/SIDEBAR.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /counterstrike/SIDEBAR.CPP 2     3/17/97 1:05a Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SIDEBAR.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : October 20, 1994                                             *\n *                                                                                             *\n *                  Last Update : October 9, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SidebarClass::AI -- Handles player clicking on sidebar area.                              *\n *   SidebarClass::Abandon_Production -- Stops production of the object specified.             *\n *   SidebarClass::Activate -- Controls the sidebar activation.                                *\n *   SidebarClass::Activate_Demolish -- Controls the demolish button on the sidebar.           *\n *   SidebarClass::Activate_Repair -- Controls the repair button on the sidebar.               *\n *   SidebarClass::Activate_Upgrade -- Controls the upgrade button on the sidebar.             *\n *   SidebarClass::Add -- Adds a game object to the sidebar list.                              *\n *   SidebarClass::Draw_It -- Renders the sidebar display.                                     *\n *   SidebarClass::Factory_Link -- Links a factory to a sidebar strip.                         *\n *   SidebarClass::Init_Clear -- Sets sidebar to a known (and deactivated) state               *\n *   SidebarClass::Init_IO -- Adds buttons to the button list                                  *\n *   SidebarClass::Init_Theater -- Performs theater-specific initialization                    *\n *   SidebarClass::One_Time -- Handles the one time game initializations.                      *\n *   SidebarClass::One_Time -- Handles the one time game initializations.                      *\n *   SidebarClass::Recalc -- Examines the sidebar data and updates it as necessary.            *\n *   SidebarClass::Refresh_Cells -- Intercepts the refresh, looking for sidebar controls.      *\n *   SidebarClass::SBGadgetClass::Action -- Special function that controls the mouse over the s*\n *   SidebarClass::Scroll -- Handles scrolling the sidebar object strip.                       *\n *   SidebarClass::Set_Current -- Sets a specified object that controls the sidebar display.   *\n *   SidebarClass::SidebarClass -- Default constructor for the sidebar.                        *\n *   SidebarClass::SidebarClass -- This is the no initialization constructor for the sidebar.  *\n *   SidebarClass::StripClass::AI -- Input and AI processing for the side strip.               *\n *   SidebarClass::StripClass::Abandon_Produ -- Abandons production associated with sidebar.   *\n *   SidebarClass::StripClass::Activate -- Adds the strip buttons to the input system.         *\n *   SidebarClass::StripClass::Add -- Add an object to the side strip.                         *\n *   SidebarClass::StripClass::Deactivate -- Removes the side strip buttons from the input syst*\n *   SidebarClass::StripClass::Draw_It -- Render the sidebar display.                          *\n *   SidebarClass::StripClass::Factory_Link -- Links a factory to a sidebar button.            *\n *   SidebarClass::StripClass::Flag_To_Redra -- Flags the sidebar strip to be redrawn.         *\n *   SidebarClass::StripClass::Get_Special_Cameo -- Fetches the special event cameo shape.     *\n *   SidebarClass::StripClass::Init_Clear -- Sets sidebar to a known (and deactivated) state   *\n *   SidebarClass::StripClass::Init_IO -- Adds buttons to the button list                      *\n *   SidebarClass::StripClass::Init_Theater -- Performs theater-specific initialization        *\n *   SidebarClass::StripClass::One_Time -- Performs one time actions necessary for the side str*\n *   SidebarClass::StripClass::Recalc -- Revalidates the current sidebar list of objects.      *\n *   SidebarClass::StripClass::Scroll -- Causes the side strip to scroll.                      *\n *   SidebarClass::StripClass::SelectClass:: -- Action function when buildable cameo is selecte*\n *   SidebarClass::StripClass::SelectClass:: -- Assigns special values to a buildable select bu*\n *   SidebarClass::StripClass::SelectClass::SelectClass -- Default constructor.                *\n *   SidebarClass::StripClass::StripClass -- Default constructor for the side strip class.     *\n *   SidebarClass::Which_Column -- Determines which column a given type should appear.         *\n *   SidebarClass::Zoom_Mode_Control -- Handles the zoom mode toggle operation.                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\nvoid * SidebarClass::SidebarShape = NULL;\nvoid * SidebarClass::SidebarMiddleShape = NULL;\nvoid * SidebarClass::SidebarBottomShape = NULL;\n\n\n/***************************************************************************\n**\tThis holds the translucent table for use with the construction clock\n**\tanimation.\n*/\nchar SidebarClass::StripClass::ClockTranslucentTable[(1+1)*256];\n\n\n/***************************************************************************\n**\tThis points to the main sidebar shapes. These include the upgrade and\n**\trepair buttons.\n*/\n//TheaterType SidebarClass::StripClass::LastTheater = THEATER_NONE;\n\ntypedef enum ButtonNumberType {\n\tBUTTON_RADAR = 100,\n\tBUTTON_REPAIR,\n\tBUTTON_DEMOLISH,\n\tBUTTON_UPGRADE,\n\tBUTTON_SELECT,\n\tBUTTON_ZOOM\n} ButtonNumberType;\n\n/*\n** Sidebar buttons\n*/\nSidebarClass::SBGadgetClass SidebarClass::Background;\nShapeButtonClass SidebarClass::Repair;\nShapeButtonClass SidebarClass::Upgrade;\nShapeButtonClass SidebarClass::Zoom;\nShapeButtonClass SidebarClass::StripClass::UpButton[COLUMNS];\nShapeButtonClass SidebarClass::StripClass::DownButton[COLUMNS];\nSidebarClass::StripClass::SelectClass\nSidebarClass::StripClass::SelectButton[COLUMNS][MAX_VISIBLE];\n\n/*\n** Shape data pointers\n*/\nvoid * SidebarClass::StripClass::LogoShapes = NULL;\nvoid const * SidebarClass::StripClass::ClockShapes;\nvoid const * SidebarClass::StripClass::SpecialShapes[SPC_COUNT];\n\n\n/***********************************************************************************************\n * SidebarClass::SidebarClass -- Default constructor for the sidebar.                          *\n *                                                                                             *\n *    Constructor for the sidebar handler. It basically sets up the sidebar to the empty       *\n *    condition.                                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nSidebarClass::SidebarClass(void) :\n\tIsSidebarActive(false),\n\tIsToRedraw(true),\n\tIsRepairActive(false),\n\tIsUpgradeActive(false),\n\tIsDemolishActive(false)\n{\n\t/*\n\t**\tThis sets up the clipping window. This window is used by the shape drawing\n\t**\tcode so that as the sidebar buildable buttons scroll, they get properly\n\t**\tclipped at the top and bottom edges.\n\t*/\n\tWindowList[WINDOW_SIDEBAR][WINDOWX] = (SIDE_X+8);\n\tWindowList[WINDOW_SIDEBAR][WINDOWY] = SIDE_Y + 1 + TOP_HEIGHT;\n\tWindowList[WINDOW_SIDEBAR][WINDOWWIDTH] = SIDE_WIDTH;\n\tWindowList[WINDOW_SIDEBAR][WINDOWHEIGHT] = StripClass::MAX_VISIBLE * StripClass::OBJECT_HEIGHT;\n//\tWindowList[WINDOW_SIDEBAR][WINDOWHEIGHT] = StripClass::MAX_VISIBLE * StripClass::OBJECT_HEIGHT-1;\n\n\t/*\n\t**\tSet up the coordinates for the sidebar strips. These coordinates are for\n\t**\tthe upper left corner.\n\t*/\n\tnew (&Column[0]) StripClass(InitClass());\n\tnew (&Column[1]) StripClass(InitClass());\n\n\tColumn[0].X = COLUMN_ONE_X * RESFACTOR;\n\tColumn[0].Y = COLUMN_ONE_Y * RESFACTOR;\n\tColumn[1].X = COLUMN_TWO_X * RESFACTOR;\n\tColumn[1].Y = COLUMN_TWO_Y * RESFACTOR;\n}\n\n\n/***********************************************************************************************\n * SidebarClass::SidebarClass -- This is the no initialization constructor for the sidebar.    *\n *                                                                                             *\n *    Unlike the normal constructor, this one doesn't do any initialization. There is one      *\n *    exception to this. The stip classes can't call an explicit NoInitClass constructor       *\n *    since they are an array. Since the default constructor is called for these strips, we    *\n *    must reset the X and Y location to what we know they should be.                          *\n *                                                                                             *\n * INPUT:   flag to indicate that this is a no initialization constructor.                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nSidebarClass::SidebarClass(NoInitClass const & x) : PowerClass(x)\n{\n\t/*\n\t**\tSet up the coordinates for the sidebar strips. These coordinates are for\n\t**\tthe upper left corner.\n\t*/\n//\tColumn[0].X = COLUMN_ONE_X * RESFACTOR;\n//\tColumn[0].Y = COLUMN_ONE_Y * RESFACTOR;\n//\tColumn[1].X = COLUMN_TWO_X * RESFACTOR;\n//\tColumn[1].Y = COLUMN_TWO_Y * RESFACTOR;\n}\n\n\n/***********************************************************************************************\n * SidebarClass::One_Time -- Handles the one time game initializations.                        *\n *                                                                                             *\n *    This routine is used to load the graphic data that is needed by the sidebar display. It  *\n *    should only be called ONCE.                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once when the game first starts.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/28/94   JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::One_Time(void)\n{\n\tPowerClass::One_Time();\n\n\t/*\n\t**\tThis sets up the clipping window. This window is used by the shape drawing\n\t**\tcode so that as the sidebar buildable buttons scroll, they get properly\n\t**\tclipped at the top and bottom edges.\n\t*/\n\tWindowList[WINDOW_SIDEBAR][WINDOWX] = ((SIDE_X+8))  * RESFACTOR;\n\tWindowList[WINDOW_SIDEBAR][WINDOWY] = (SIDE_Y + 1 + TOP_HEIGHT) * RESFACTOR;\n\tWindowList[WINDOW_SIDEBAR][WINDOWWIDTH] = (SIDE_WIDTH) * RESFACTOR;\n\tWindowList[WINDOW_SIDEBAR][WINDOWHEIGHT] = (StripClass::MAX_VISIBLE * StripClass::OBJECT_HEIGHT) * RESFACTOR;\n//\tWindowList[WINDOW_SIDEBAR][WINDOWHEIGHT] = (StripClass::MAX_VISIBLE * StripClass::OBJECT_HEIGHT-1) * RESFACTOR;\n\n\t/*\n\t** Top of the window seems to be wrong for the new sidebar. ST - 5/2/96 2:49AM\n\t*/\n\tWindowList[WINDOW_SIDEBAR][WINDOWY] -= 1*RESFACTOR;\n\n\t/*\n\t**\tSet up the coordinates for the sidebar strips. These coordinates are for\n\t**\tthe upper left corner.\n\t*/\n//\tColumn[0].X = COLUMN_ONE_X * RESFACTOR;\n//\tColumn[0].Y = COLUMN_ONE_Y * RESFACTOR;\n//\tColumn[1].X = COLUMN_TWO_X * RESFACTOR;\n//\tColumn[1].Y = COLUMN_TWO_Y * RESFACTOR;\n\tColumn[0].One_Time(0);\n\tColumn[1].One_Time(1);\n\n\t/*\n\t**\tLoad the sidebar shape in at this time. (Hi-Res sidebar is theater dependant)\n\t*/\n\tif (SidebarShape == NULL) {\n\t\tSidebarShape = (void*)MFCD::Retrieve(\"SIDEBAR.SHP\");\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Init_Clear -- Sets sidebar to a known (and deactivated) state                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::Init_Clear(void)\n{\n\n\tPowerClass::Init_Clear();\n\n\tIsToRedraw = true;\n\tIsRepairActive = false;\n\tIsUpgradeActive = false;\n\tIsDemolishActive = false;\n\n\tColumn[0].Init_Clear();\n\tColumn[1].Init_Clear();\n\n\tActivate(false);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Init_IO -- Adds buttons to the button list                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::Init_IO(void)\n{\n\tPowerClass::Init_IO();\n\n\t/*\n\t** Add the sidebar's buttons only if we're not in editor mode.\n\t*/\n\tif (!Debug_Map) {\n\n\t\tRepair.IsSticky = true;\n\t\tRepair.ID = BUTTON_REPAIR;\n\t\tRepair.X = (0x1f2/2)*RESFACTOR;\n\t\tRepair.Y = (0x96/2)*RESFACTOR;\n\t\tRepair.IsPressed = false;\n\t\tRepair.IsToggleType = true;\n\t\tRepair.ReflectButtonState = true;\n\t\tRepair.Set_Shape(MFCD::Retrieve(\"REPAIR.SHP\"));\n\n\t\tUpgrade.IsSticky = true;\n\t\tUpgrade.ID = BUTTON_UPGRADE;\n#ifdef WIN32\n\t\tUpgrade.X = 0x21f;\n#else\n\t\tUpgrade.X = ((0x21f/2)+1)*RESFACTOR;\n#endif\n\t\tUpgrade.Y = (0x96/2)*RESFACTOR;\n\t\tUpgrade.IsPressed = false;\n\t\tUpgrade.IsToggleType = true;\n\t\tUpgrade.ReflectButtonState = true;\n\t\tUpgrade.Set_Shape(MFCD::Retrieve(\"SELL.SHP\"));\n\n\t\tZoom.IsSticky = true;\n\t\tZoom.ID = BUTTON_ZOOM;\n\t\tZoom.X = (0x24c/2)*RESFACTOR;\n\t\tZoom.Y = (0x96/2)*RESFACTOR;\n\t\tZoom.IsPressed = false;\n\t\tZoom.Set_Shape(MFCD::Retrieve(\"MAP.SHP\"));\n\n\t\tif ((IsRadarActive && Is_Zoomable()) || Session.Type != GAME_NORMAL) {\n\t\t\tZoom.Enable();\n\t\t} else {\n\t\t\tZoom.Disable();\n\t\t}\n\t\tColumn[0].Init_IO(0);\n\t\tColumn[1].Init_IO(1);\n\n\t\t/*\n\t\t** If a game was loaded & the sidebar was enabled, pop it up now\n\t\t*/\n\t\tif (IsSidebarActive) {\n\t\t\tIsSidebarActive = false;\n\t\t\tActivate(1);\n//\t\t\tBackground.Zap();\n//\t\t\tAdd_A_Button(Background);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Init_Theater -- Performs theater-specific initialization                      *\n *                                                                                             *\n * INPUT:   theater  -- The theater that is being initialized. Sometimes this has an effect on *\n *                      the data that is loaded.                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::Init_Theater(TheaterType theater)\n{\n\tReload_Sidebar();\n\n\tPowerClass::Init_Theater(theater);\n\n\tColumn[0].Init_Theater(theater);\n\tColumn[1].Init_Theater(theater);\n}\n\n/***********************************************************************************************\n * SidebarClass::Reload_Sidebar -- Loads appropriate sidebar shapes depending on house\t\t\t  *\n *                                                                                             *\n * INPUT:  none \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   9/18/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::Reload_Sidebar(void)\n{\n\tstatic char * sidebarnames[]={\n\t\t\"SIDE?NA.SHP\",\t\t//NATO\n\t\t\"SIDE?NA.SHP\",\n\t\t\"SIDE?US.SHP\",\t\t//USSR\n\t\t\"SIDE?NA.SHP\",\n\t\t\"SIDE?US.SHP\",\t\t//UKRAINE\n\t\t\"SIDE?NA.SHP\",\n\t\t\"SIDE?NA.SHP\",\n\t\t\"SIDE?NA.SHP\",\n\t\t\"SIDE?NA.SHP\",\t\t//HOUSE_GOOD\n\t\t\"SIDE?US.SHP\"\t\t//HOUSE_BAD\n\t};\n\tint houseloaded = 0;\n\n\tif(PlayerPtr) {\n\t\thouseloaded = PlayerPtr->ActLike;\n\t}\n\n\tchar * sidename = sidebarnames[houseloaded];\n\t*(sidename+4) = '1';\n\tSidebarShape = (void*)MFCD::Retrieve(sidename);\n\t*(sidename+4) = '2';\n\tSidebarMiddleShape = (void*)MFCD::Retrieve(sidename);\n\t*(sidename+4) = '3';\n\tSidebarBottomShape = (void*)MFCD::Retrieve(sidename);\n\n\tColumn[0].Reload_LogoShapes();\n\tColumn[1].Reload_LogoShapes();\n}\n\n/***********************************************************************************************\n * SidebarClass::Which_Column -- Determines which column a given type should appear.           *\n *                                                                                             *\n *    Use this function to resolve what column the specified object type should be placed      *\n *    into.                                                                                    *\n *                                                                                             *\n * INPUT:   otype -- Pointer to the object type class of the object in question.               *\n *                                                                                             *\n * OUTPUT:  Returns with the column number that the object should be placed in.                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/01/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint SidebarClass::Which_Column(RTTIType type)\n{\n\tif (type == RTTI_BUILDINGTYPE || type == RTTI_BUILDING) {\n\t\treturn(0);\n\t}\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Factory_Link -- Links a factory to a sidebar strip.                           *\n *                                                                                             *\n *    This routine will link the specified factory to the sidebar strip. A factory must be     *\n *    linked to the sidebar so that as the factory production progresses, the sidebar will     *\n *    show the production progress.                                                            *\n *                                                                                             *\n * INPUT:   factory  -- The factory number to attach.                                          *\n *                                                                                             *\n *          type     -- The object type number.                                                *\n *                                                                                             *\n *          id       -- The object sub-type number.                                            *\n *                                                                                             *\n * OUTPUT:  Was the factory successfully attached to the sidebar strip?                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::Factory_Link(int factory, RTTIType type, int id)\n{\n\tassert((unsigned)type < RTTI_COUNT);\n\tassert(id >= 0);\n\n\treturn(Column[Which_Column(type)].Factory_Link(factory, type, id));\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Refresh_Cells -- Intercepts the refresh, looking for sidebar controls.        *\n *                                                                                             *\n *    This routine intercepts the Refresh_Cells call in order to see if the sidebar needs      *\n *    to be refreshed as well. If the special code to refresh the sidebar was found, it        *\n *    flags the sidebar to be redrawn and then removes the code from the list.                 *\n *                                                                                             *\n * INPUT:   cell  -- The cell to base the refresh list on.                                     *\n *                                                                                             *\n *          list  -- Pointer to the cell offset list that elaborates all the cells that        *\n *                   need to be flagged for redraw.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::Refresh_Cells(CELL cell, short const * list)\n{\n\tif (*list == REFRESH_SIDEBAR) {\n\t\tIsToRedraw = true;\n\t\tColumn[0].IsToRedraw = true;\n\t\tColumn[1].IsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\t}\n\tPowerClass::Refresh_Cells(cell, list);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Activate_Repair -- Controls the repair button on the sidebar.                 *\n *                                                                                             *\n *    Use this routine to turn the repair sidebar button on and off. Typically, the button     *\n *    is enabled when the currently selected structure is friendly and damaged.                *\n *                                                                                             *\n * INPUT:   control  -- The controls how the button is to be activated or deactivated;         *\n *                      0  -- Turn button off.                                                 *\n *                      1  -- Turn button on.                                                  *\n *                      -1 -- Toggle button state.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the button previously activated?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::Activate_Repair(int control)\n{\n\tbool old = IsRepairActive;\n\n\tif (control == -1) {\n\t\tcontrol = IsRepairActive ? 0 : 1;\n\t}\n\tswitch (control) {\n\t\tcase 1:\n\t\t\tIsRepairActive = true;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\tcase 0:\n\t\t\tIsRepairActive = false;\n\t\t\tbreak;\n\t}\n\tif (old != IsRepairActive) {\n\t\tFlag_To_Redraw(false);\n\t\tIsToRedraw = true;\n\n\t\tif (!IsRepairActive) {\n\t\t\tHelp_Text(TXT_NONE);\n\t\t\tSet_Default_Mouse(MOUSE_NORMAL, false);\n\t\t}\n\t}\n\treturn(old);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Activate_Upgrade -- Controls the upgrade button on the sidebar.               *\n *                                                                                             *\n *    Use this routine to turn the upgrade sidebar button on and off. Typically, the button    *\n *    is enabled when the currently selected structure can be upgraded and disabled otherwise. *\n *                                                                                             *\n * INPUT:   control  -- The controls how the button is to be activated or deactivated;         *\n *                      0  -- Turn button off.                                                 *\n *                      1  -- Turn button on.                                                  *\n *                      -1 -- Toggle button state.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the button previously activated?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::Activate_Upgrade(int control)\n{\n\tbool old = IsUpgradeActive;\n\tif (control == -1) {\n\t\tcontrol = IsUpgradeActive ? 0 : 1;\n\t}\n\tswitch (control) {\n\t\tcase 1:\n\t\t\tIsUpgradeActive = true;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\tcase 0:\n\t\t\tIsUpgradeActive = false;\n\t\t\tbreak;\n\t}\n\tif (old != IsUpgradeActive) {\n\t\tFlag_To_Redraw(false);\n\t\tIsToRedraw = true;\n\t\tif (!IsUpgradeActive) {\n\t\t\tSet_Default_Mouse(MOUSE_NORMAL, false);\n\t\t}\n\t}\n\treturn(old);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Activate_Demolish -- Controls the demolish button on the sidebar.             *\n *                                                                                             *\n *    Use this routine to turn the demolish/dismantle sidebar button on and off. Typically,    *\n *    the button is enabled when a friendly building is selected and disabled otherwise.       *\n *                                                                                             *\n * INPUT:   control  -- The controls how the button is to be activated or deactivated;         *\n *                      0  -- Turn button off.                                                 *\n *                      1  -- Turn button on.                                                  *\n *                      -1 -- Toggle button state.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the button previously activated?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::Activate_Demolish(int control)\n{\n\tbool old = IsDemolishActive;\n\n\tif (control == -1) {\n\t\tcontrol = IsDemolishActive ? 0 : 1;\n\t}\n\tswitch (control) {\n\t\tcase 1:\n\t\t\tIsDemolishActive = true;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\tcase 0:\n\t\t\tIsDemolishActive = false;\n\t\t\tbreak;\n\t}\n\tif (old != IsDemolishActive) {\n\t\tFlag_To_Redraw(false);\n\t\tIsToRedraw = true;\n\t\tif (!IsDemolishActive) {\n\t\t\tSet_Default_Mouse(MOUSE_NORMAL, false);\n\t\t}\n\t}\n\treturn(old);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Add -- Adds a game object to the sidebar list.                                *\n *                                                                                             *\n *    This routine is used to add a game object to the sidebar. Call this routine when a       *\n *    factory type building is created. It handles the case of adding an item that has already *\n *    been added -- it just ignores it.                                                        *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that is being added.                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the object added to the sidebar?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::Add(RTTIType type, int id)\n{\n\tassert((unsigned)type < RTTI_COUNT);\n\n\t/*\n\t** Add the sidebar only if we're not in editor mode.\n\t*/\n\tif (!Debug_Map) {\n\t\tint column = Which_Column(type);\n\n\t\tif (Column[column].Add(type, id)) {\n\t\t\tActivate(1);\n\t\t\tIsToRedraw = true;\n\t\t\tFlag_To_Redraw(false);\n\t\t\treturn(true);\n\t\t}\n\t\treturn(false);\n\t}\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Scroll -- Handles scrolling the sidebar object strip.                         *\n *                                                                                             *\n *    This routine is used to scroll the sidebar strip of objects. The strip appears whenever  *\n *    a building is selected that can produce units. If the number of units to produce is      *\n *    greater than what the sidebar can hold, this routine is used to scroll the other object  *\n *    into view so they can be selected.                                                       *\n *                                                                                             *\n * INPUT:   up -- Should the scroll be upwards? Upward scrolling reveals object that are       *\n *                later in the list of objects.                                                *\n *                                                                                             *\n * OUTPUT:  bool; Did scrolling occur?                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/28/94   JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::Scroll(bool up, int column)\n{\n\tif (column == -1) {\n\t\tbool scr = false;\n\t\tscr |= Column[0].Scroll(up);\n\t\tscr |= Column[1].Scroll(up);\n\t\tif (!scr) {\n\t\t\tSound_Effect(VOC_SCOLD);\n\t\t}\n\t\tif (scr) {\n\t\t\tIsToRedraw = true;\n\t\t\tFlag_To_Redraw(false);\n\t\t\treturn(true);\n\t\t}\n\t\treturn(false);\n\t}\n\n\tif (Column[column].Scroll(up)) {\n\t\t// No need to redraw the whole sidebar juts because we scrolled a strip is there? ST - 10/15/96 7:29PM\n\t\t//IsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Draw_It -- Renders the sidebar display.                                       *\n *                                                                                             *\n *    This routine performs the actual drawing of the sidebar display.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the sidebar imagery changed at all?                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/28/94   JLB : Created.                                                                 *\n *   12/31/1994 JLB : Split rendering off into the sidebar strip class.                        *\n *=============================================================================================*/\nvoid SidebarClass::Draw_It(bool complete)\n{\n\tPowerClass::Draw_It(complete);\n\n\tBStart(BENCH_SIDEBAR);\n\n\tif (IsSidebarActive && (IsToRedraw || complete) && !Debug_Map) {\n\t\tIsToRedraw = false;\n\n\t\tif (LogicPage->Lock()) {\n\t\t\t/*\n\t\t\t**\tDraw the outline box around the sidebar buttons.\n\t\t\t*/\n\t\t\tint shape = complete ? 0 : 1;\n\n\t\t\t/*\n\t\t\t** The sidebar shape is too big in 640x400 so it needs to be drawn in three chunks.\n\t\t\t*/\n\t\t\tCC_Draw_Shape(SidebarShape, 0, SIDE_X * RESFACTOR, 8*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL);\n\t\t\tCC_Draw_Shape(SidebarMiddleShape, shape, SIDE_X * RESFACTOR, (8+80)*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL);\n\t\t\tCC_Draw_Shape(SidebarBottomShape, shape, SIDE_X * RESFACTOR, (8+80+50)*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL);\n\n\t\t\tRepair.Draw_Me(true);\n\t\t\tUpgrade.Draw_Me(true);\n\t\t\tZoom.Draw_Me(true);\n\t\t\tLogicPage->Unlock();\n\t\t}\n\t}\n\n\t/*\n\t**\tDraw the side strip elements by calling their respective draw functions.\n\t*/\n\tif (IsSidebarActive) {\n\t\tColumn[0].Draw_It(complete);\n\t\tColumn[1].Draw_It(complete);\n\n\t\tif (complete || IsToRedraw) {\n\t\t\tRepair.Draw_Me(true);\n\t\t\tUpgrade.Draw_Me(true);\n\t\t\tZoom.Draw_Me(true);\n\t\t}\n\t}\n\tIsToRedraw = false;\n\n\tBEnd(BENCH_SIDEBAR);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::AI -- Handles player clicking on sidebar area.                                *\n *                                                                                             *\n *    This routine handles the processing necessary when the player clicks on the sidebar.     *\n *    Typically, this is selection of the item to build.                                       *\n *                                                                                             *\n * INPUT:   input -- Reference to the keyboard input value.                                    *\n *                                                                                             *\n *          x,y   -- Mouse coordinates at time of input.                                       *\n *                                                                                             *\n * OUTPUT:  bool; Was the click handled?                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/28/94   JLB : Created.                                                                 *\n *   11/11/1994 JLB : Processes input directly.                                                *\n *   12/26/1994 JLB : Uses factory manager class for construction handling.                    *\n *   12/31/1994 JLB : Simplified to use the sidebar strip class handlers.                      *\n *   12/31/1994 JLB : Uses mouse coordinate parameters.                                        *\n *   06/27/1995 JLB : <TAB> key toggles sidebar.                                               *\n *=============================================================================================*/\nvoid SidebarClass::AI(KeyNumType & input, int x, int y)\n{\n\tbool redraw = false;\n\n\t/*\n\t**\tToggle the sidebar in and out with the <TAB> key.\n\t*/\n#ifndef WIN32\n\tif (input == KN_TAB) {\n\t\tActivate(-1);\n\t}\n#else\n\tif (!Debug_Map) {\n\t\tActivate(1);\t// Force the sidebar always on in Win95 mode\n\t}\n#endif\t//WIN32\n\tif (!Debug_Map) {\n\t\tColumn[0].AI(input, x, y);\n\t\tColumn[1].AI(input, x, y);\n\t}\n\n#ifdef NEVER\n\tif (IsSidebarActive && !Debug_Map) {\n\n\t\tif (input == KN_DOWN) {\n\t\t\tint scr = 0;\n\t\t\tscr |= Column[0].Scroll(false);\n\t\t\tscr |= Column[1].Scroll(false);\n\t\t\tif (!scr) {\n\t\t\t\tSound_Effect(VOC_SCOLD);\n\t\t\t}\n\t\t\tredraw |= scr;\n\t\t\tinput = KN_NONE;\n\t\t}\n\t\tif (input == KN_UP) {\n\t\t\tint scr = 0;\n\t\t\tscr |= Column[0].Scroll(true);\n\t\t\tscr |= Column[1].Scroll(true);\n\t\t\tif (!scr) {\n\t\t\t\tSound_Effect(VOC_SCOLD);\n\t\t\t}\n\t\t\tredraw |= scr;\n\t\t\tinput = KN_NONE;\n\t\t}\n\t}\n#endif\n\n\n\tif (IsSidebarActive) {\n\n\t\t/*\n\t\t**\tIf there are any buildings in the payer's inventory, then allow the repair\n\t\t**\toption.\n\t\t*/\n\t\tif (PlayerPtr->BScan) {\n\t\t\tActivate_Repair(true);\n\t\t} else {\n\t\t\tActivate_Repair(false);\n\t\t}\n\n\t\tif (input == (BUTTON_REPAIR|KN_BUTTON)) {\n\t\t\tRepair_Mode_Control(-1);\n\t\t}\n\n\t\tif (input == (BUTTON_ZOOM|KN_BUTTON)) {\n\t\t\tZoom_Mode_Control();\n\t\t}\n\n\t\tif (input == (BUTTON_UPGRADE|KN_BUTTON)) {\n\t\t\tSell_Mode_Control(-1);\n\t\t}\n\n\t\tif (redraw) {\n\t\t\t//IsToRedraw = true;\n\t\t\tColumn[0].Flag_To_Redraw();\n\t\t\tColumn[1].Flag_To_Redraw();\n\n\t\t\tFlag_To_Redraw(false);\n\t\t}\n\t}\n\n\tif ((!IsRepairMode) && Repair.IsOn) {\n\t\tRepair.Turn_Off();\n\t}\n\n\tif ((!IsSellMode) && Upgrade.IsOn) {\n\t\tUpgrade.Turn_Off();\n\t}\n\n\tPowerClass::AI(input, x, y);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Recalc -- Examines the sidebar data and updates it as necessary.              *\n *                                                                                             *\n *    Occasionally a factory gets destroyed. This routine must be called in such a case        *\n *    because it might be possible that sidebar object need to be removed. This routine will   *\n *    examine all existing objects in the sidebar class and if no possible factory can         *\n *    produce it, then it will be removed.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine is exhaustive and thus time consuming. Only call it when really    *\n *             necessary. Such as when a factory is destroyed rather than when a non-factory   *\n *             is destroyed.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/30/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::Recalc(void)\n{\n\tbool redraw = false;\n\n\tredraw |= Column[0].Recalc();\n\tredraw |= Column[1].Recalc();\n\n\tif (redraw) {\n\t\tIsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Activate -- Controls the sidebar activation.                                  *\n *                                                                                             *\n *    Use this routine to turn the sidebar on or off. This routine handles updating the        *\n *    necessary flags.                                                                         *\n *                                                                                             *\n * INPUT:   control  -- Tells what to do with the sidebar according to the following:          *\n *                         0 = Turn sidebar off.                                               *\n *                         1 = Turn sidebar on.                                                *\n *                         -1= Toggle sidebar on or off.                                       *\n *                                                                                             *\n * OUTPUT:  bool; Was the sidebar already on?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::Activate(int control)\n{\n\tbool old = IsSidebarActive;\n\n\tif (Session.Play)\n\t\treturn (old);\n\n\t/*\n\t**\tDetermine the new state of the sidebar.\n\t*/\n\tswitch (control) {\n\t\tcase -1:\n\t\t\tIsSidebarActive = IsSidebarActive == false;\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tIsSidebarActive = true;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\tcase 0:\n\t\t\tIsSidebarActive = false;\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tOnly if there is a change in the state of the sidebar will anything\n\t**\tbe done to change it.\n\t*/\n\tif (IsSidebarActive != old) {\n\n\t\t/*\n\t\t**\tIf the sidebar is activated but was on the right side of the screen, then\n\t\t**\tactivate it on the left side of the screen.\n\t\t*/\n\t\tif (IsSidebarActive /*&& X*/) {\n\t\t\tSet_View_Dimensions(0, 8 * RESFACTOR, ((320-SIDE_WIDTH)/ICON_PIXEL_W) * RESFACTOR);\n\t\t\tIsToRedraw = true;\n\t\t\tHelp_Text(TXT_NONE);\n\t\t\tRepair.Zap();\n\t\t\tAdd_A_Button(Repair);\n\t\t\tUpgrade.Zap();\n\t\t\tAdd_A_Button(Upgrade);\n\t\t\tZoom.Zap();\n\t\t\tAdd_A_Button(Zoom);\n\t\t\tColumn[0].Activate();\n\t\t\tColumn[1].Activate();\n\t\t\tBackground.Zap();\n\t\t\tAdd_A_Button(Background);\n\t\t\tMap.RadarButton.Zap();\n\t\t\tAdd_A_Button(Map.RadarButton);\n\t\t\tMap.PowerButton.Zap();\n\t\t\tAdd_A_Button(Map.PowerButton);\n\t\t} else  {\n\t\t\tHelp_Text(TXT_NONE);\n\t\t\tSet_View_Dimensions(0, 8 * RESFACTOR);\n\t\t\tRemove_A_Button(Repair);\n\t\t\tRemove_A_Button(Upgrade);\n\t\t\tRemove_A_Button(Zoom);\n\t\t\tRemove_A_Button(Background);\n\t\t\tColumn[0].Deactivate();\n\t\t\tColumn[1].Deactivate();\n\t\t\tRemove_A_Button(Map.RadarButton);\n\t\t\tRemove_A_Button(Map.PowerButton);\n\t\t}\n\n\t\t/*\n\t\t**\tSince the sidebar status has changed, update the map so that the graphics\n\t\t**\twill be rendered correctly.\n\t\t*/\n\t\tFlag_To_Redraw(true);\n\t}\n\n\treturn(old);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::StripClass -- Default constructor for the side strip class.       *\n *                                                                                             *\n *    This constructor is used to reset the side strip to default empty state.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nSidebarClass::StripClass::StripClass(InitClass const & ) :\n\tX(0),\n\tY(0),\n\tID(0),\n\tIsToRedraw(true),\n\tIsBuilding(false),\n\tIsScrollingDown(false),\n\tIsScrolling(false),\n\tFlasher(-1),\n\tTopIndex(0),\n\tScroller(0),\n\tSlid(0),\n\tBuildableCount(0)\n{\n\tfor (int index = 0; index < MAX_BUILDABLES; index++) {\n\t\tBuildables[index].BuildableID = 0;\n\t\tBuildables[index].BuildableType = RTTI_NONE;\n\t\tBuildables[index].Factory = -1;\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::One_Time -- Performs one time actions necessary for the side stri *\n *                                                                                             *\n *    Call this routine ONCE at the beginning of the game. It handles retrieving pointers to   *\n *    the shape files it needs for rendering.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::One_Time(int )\n{\n\t/*\n\t** Sidebar is player team specific in Hires\n\t*/\n\tClockShapes = MFCD::Retrieve(\"CLOCK.SHP\");\n\n\tfor (SpecialWeaponType lp = SPC_FIRST; lp < SPC_COUNT; lp++) {\n\t\tchar buffer[_MAX_FNAME];\n\t\tsprintf(buffer, \"%sICON\", SpecialWeaponFile[lp]);\n\n\t\tchar\tfullname[_MAX_FNAME+_MAX_EXT];\n\t\t_makepath(fullname, NULL, NULL, buffer, \".SHP\");\n\t\tSpecialShapes[lp] = MFCD::Retrieve(fullname);\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Get_Special_Cameo -- Fetches the special event cameo shape.       *\n *                                                                                             *\n *    This routine will return with a pointer to the cameo data for the special objects that   *\n *    can appear on the sidebar (e.g., nuclear bomb).                                          *\n *                                                                                             *\n * INPUT:   type  -- The special type to fetch the cameo imagery for.                          *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the cameo imagery for the specified special object.      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/19/1995 JLB : commented                                                                *\n *=============================================================================================*/\nvoid const * SidebarClass::StripClass::Get_Special_Cameo(SpecialWeaponType type)\n{\n\tif ((unsigned)type < SPC_COUNT) {\n\t\treturn(SpecialShapes[type]);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Init_Clear -- Sets sidebar to a known (and deactivated) state     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::Init_Clear(void)\n{\n\tIsScrollingDown = false;\n\tIsScrolling = false;\n\tIsBuilding = false;\n\tFlasher = -1;\n\tTopIndex = 0;\n\tSlid = 0;\n\tBuildableCount = 0;\n\n\t/*\n\t** Since we're resetting the strips, clear out all the buildables & factory pointers.\n\t*/\n\tfor (int index = 0; index < MAX_BUILDABLES; index++) {\n\t\tBuildables[index].BuildableID = 0;\n\t\tBuildables[index].BuildableType = RTTI_NONE;\n\t\tBuildables[index].Factory = -1;\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Init_IO -- Initializes the strip's buttons                        *\n *                                                                                             *\n * This routine doesn't actually add any buttons to the list.                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::Init_IO(int id)\n{\n\tID = id;\n\n\tUpButton[ID].IsSticky = true;\n\tUpButton[ID].ID = BUTTON_UP+id;\n\tUpButton[ID].X = X+(UP_X_OFFSET * RESFACTOR);\n\tUpButton[ID].Y = Y+(UP_Y_OFFSET * RESFACTOR);\n\n#if (FRENCH)\n#ifdef WIN32\n\tUpButton[ID].Set_Shape(MFCD::Retrieve(\"STRIPUP.SHP\"));\n#else\n\tUpButton[ID].Set_Shape(MFCD::Retrieve(\"STUP_FIX.SHP\"));\n#endif\n#else\t//FRENCH\n\tUpButton[ID].Set_Shape(MFCD::Retrieve(\"STRIPUP.SHP\"));\n#endif\t//FRENCH\n\n\tDownButton[ID].IsSticky = true;\n\tDownButton[ID].ID = BUTTON_DOWN+id;\n\tDownButton[ID].X = X+(DOWN_X_OFFSET * RESFACTOR);\n\tDownButton[ID].Y = Y+(DOWN_Y_OFFSET * RESFACTOR);\n\n\t/*\n\t** Buttons are in a slightly different position in the new sidebar\n\t*/\n\tUpButton[ID].Y--;\n\tDownButton[ID].Y--;\n\n\tDownButton[ID].Set_Shape(MFCD::Retrieve(\"STRIPDN.SHP\"));\n\n\tfor (int index = 0; index < MAX_VISIBLE; index++) {\n\t\tSelectClass & g = SelectButton[ID][index];\n\t\tg.ID = BUTTON_SELECT;\n\t\tg.X = X;\n\t\tg.Y = Y + ((OBJECT_HEIGHT*index) * RESFACTOR);\n\t\tg.Width = OBJECT_WIDTH * RESFACTOR;\n\t\tg.Height = OBJECT_HEIGHT * RESFACTOR;\n\t\tg.Set_Owner(*this, index);\n\t}\n\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Init_Theater -- Performs theater-specific initialization          *\n *                                                                                             *\n * INPUT:   theater                                                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::Init_Theater(TheaterType theater)\n{\n\n\tReload_LogoShapes();\n\n\tif ( (theater != THEATER_NONE) && (theater != ::LastTheater)) {\n\n\t\tstatic TLucentType const ClockCols[1] = {\n\t\t\t{GREEN, BLACK, 100, 0}\n//\t\t\t{GREEN, LTGREY, 180, 0}\n\t\t};\n\n\t\t/*\n\t\t**\tMake sure that remapping doesn't occur on the colors that cycle.\n\t\t*/\n\t\tPaletteClass pal = OriginalPalette;\n\t\tmemset(&pal[CYCLE_COLOR_START*3], 0x3f, CYCLE_COLOR_COUNT*3);\n\t\tBuild_Translucent_Table(pal, &ClockCols[0], 1, (void*)ClockTranslucentTable);\n\n//\t\tMem_Copy(GamePalette, OriginalPalette, 768);\n//\t\tmemset(&GamePalette[CYCLE_COLOR_START*3], 0x3f, CYCLE_COLOR_COUNT*3);\n\n\t\t/*\n\t\t**\tCreate the translucent table used for the sidebar.\n\t\t*/\n//\t\tBuild_Translucent_Table(GamePalette, &ClockCols[0], 1, (void*)ClockTranslucentTable);\n//\t\tGamePalette = OriginalPalette;\n\n\t\tConquer_Build_Fading_Table(GamePalette, &ClockTranslucentTable[256], BLACK, 100);\n\t}\n}\n\nvoid SidebarClass::StripClass::Reload_LogoShapes(void)\n{\n\t/*\n\t** Load hi-res strip art here since it is player side specific\n\t*/\n\tstatic char * stripnames[]={\n\t\t\"stripna.shp\",\t\t//Nato\n\t\t\"stripna.shp\",\n\t\t\"stripus.shp\",\t\t//USSR\n\t\t\"stripna.shp\",\n\t\t\"stripus.shp\",\t\t//UKRAINE\n\t\t\"stripna.shp\",\n\t\t\"stripna.shp\",\n\t\t\"stripna.shp\",\n\t\t\"stripna.shp\",\t\t//HOUSE_GOOD\n\t\t\"stripus.shp\",\t\t//HOUSE_BAD\n\t};\n\tint houseloaded = 0;\n\n\t/*\n\t** Sidebar art is dependent on the side of the player\n\t*/\n\n\tif(PlayerPtr) {\n\t\thouseloaded = PlayerPtr->ActLike;\n\t}\n\tLogoShapes = (void*)MFCD::Retrieve(stripnames[houseloaded]);\n}\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Activate -- Adds the strip buttons to the input system.           *\n *                                                                                             *\n *    This routine will add the side strip buttons to the map's input system. This routine     *\n *    should be called once when the sidebar activates.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Never call this routine a second time without first calling Deactivate().       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::Activate(void)\n{\n\tUpButton[ID].Zap();\n\tMap.Add_A_Button(UpButton[ID]);\n\n\tDownButton[ID].Zap();\n\tMap.Add_A_Button(DownButton[ID]);\n\n\tfor (int index = 0; index < MAX_VISIBLE; index++) {\n\t\tSelectButton[ID][index].Zap();\n\t\tMap.Add_A_Button(SelectButton[ID][index]);\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Deactivate -- Removes the side strip buttons from the input syste *\n *                                                                                             *\n *    Call this routine to remove all the buttons on the side strip from the map's input       *\n *    system.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Never call this routine unless the Activate() function was previously called.   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::Deactivate(void)\n{\n\tMap.Remove_A_Button(UpButton[ID]);\n\tMap.Remove_A_Button(DownButton[ID]);\n\tfor (int index = 0; index < MAX_VISIBLE; index++) {\n\t\tMap.Remove_A_Button(SelectButton[ID][index]);\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Add -- Add an object to the side strip.                           *\n *                                                                                             *\n *    Use this routine to add a buildable object to the side strip.                            *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object type that can be built and is to be added to     *\n *                      the side strip.                                                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the object successfully added to the side strip? Failure could be the    *\n *                result of running out of room in the side strip array or the object might    *\n *                already be in the list.                                                      *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::StripClass::Add(RTTIType type, int id)\n{\n\tif (BuildableCount <= MAX_BUILDABLES) {\n\t\tfor (int index = 0; index < BuildableCount; index++) {\n\t\t\tif (Buildables[index].BuildableType == type && Buildables[index].BuildableID == id) {\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t}\n\t\tif (!ScenarioInit && type != RTTI_SPECIAL) {\n\t\t\tSpeak(VOX_NEW_CONSTRUCT);\n\t\t}\n\t\tBuildables[BuildableCount].BuildableType = type;\n\t\tBuildables[BuildableCount].BuildableID = id;\n\t\tBuildableCount++;\n\t\tIsToRedraw = true;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Scroll -- Causes the side strip to scroll.                        *\n *                                                                                             *\n *    Use this routine to flag the side strip to scroll. The direction scrolled is controlled  *\n *    by the parameter. Scrolling is merely initiated by this routine. Subsequent calls to     *\n *    the AI function and the Draw_It function are required to properly give the appearance    *\n *    of scrolling.                                                                            *\n *                                                                                             *\n * INPUT:   bool; Should the side strip scroll UP? If it is to scroll down then pass false.    *\n *                                                                                             *\n * OUTPUT:  bool; Was the side strip started to scroll in the desired direction?               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/31/1994 JLB : Created.                                                                 *\n *   07/29/1995 JLB : Simplified scrolling logic.                                              *\n *=============================================================================================*/\nbool SidebarClass::StripClass::Scroll(bool up)\n{\n\tif (up) {\n\t\tif (!TopIndex) return(false);\n\t\tScroller--;\n\t} else {\n\t\tif (TopIndex+MAX_VISIBLE >= BuildableCount) return(false);\n\t\tScroller++;\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Flag_To_Redra -- Flags the sidebar strip to be redrawn.           *\n *                                                                                             *\n *    This utility routine is called when something changes on the sidebar and it must be      *\n *    reflected the next time drawing is performed.                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::Flag_To_Redraw(void)\n{\n\tIsToRedraw = true;\n\t//Map.SidebarClass::IsToRedraw = true;\n\tMap.Flag_To_Redraw(false);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::AI -- Input and AI processing for the side strip.                 *\n *                                                                                             *\n *    The side strip AI processing is performed by this function. This function not only       *\n *    checks for player input, but also handles any graphic logic updating necessary as a      *\n *    result of flashing or construction animation.                                            *\n *                                                                                             *\n * INPUT:   input -- The player input code.                                                    *\n *                                                                                             *\n *          x,y   -- Mouse coordinate to use.                                                  *\n *                                                                                             *\n * OUTPUT:  bool; Did the AI detect that it will need a rendering change? If this routine      *\n *                returns true, then the Draw_It function should be called at the              *\n *                earliest opportunity.                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/31/1994 JLB : Created.                                                                 *\n *   12/31/1994 JLB : Uses mouse coordinate parameters.                                        *\n *=============================================================================================*/\nbool SidebarClass::StripClass::AI(KeyNumType & input, int , int )\n{\n\tbool redraw = false;\n\n\t/*\n\t**\tIf this is scroll button for this side strip, then scroll the strip as\n\t**\tindicated.\n\t*/\n\tif (input == (UpButton[ID].ID|KN_BUTTON)) {\t// && !IsScrolling\n\t\tUpButton[ID].IsPressed = false;\n\t\tif (!Scroll(true)) {\n\t\t\tSound_Effect(VOC_SCOLD);\n\t\t}\n\t}\n\tif (input == (DownButton[ID].ID|KN_BUTTON)) {\t// && !IsScrolling\n\t\tDownButton[ID].IsPressed = false;\n\t\tif (!Scroll(false)) {\n\t\t\tSound_Effect(VOC_SCOLD);\n\t\t}\n\t}\n\n\t/*\n\t**\tReflect the scroll desired direction/value into the scroll\n\t**\tlogic handler. This might result in up or down scrolling.\n\t*/\n\tif (!IsScrolling && Scroller) {\n\t\tif (BuildableCount <= MAX_VISIBLE) {\n\t\t\tScroller = 0;\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tTop of list is moving toward lower ordered entries in the object list. It looks like\n\t\t\t**\tthe \"window\" to the object list is moving up even though the actual object images are\n\t\t\t**\tscrolling downward.\n\t\t\t*/\n\t\t\tif (Scroller < 0) {\n\t\t\t\tif (!TopIndex) {\n\t\t\t\t\tScroller = 0;\n\t\t\t\t} else {\n\t\t\t\t\tScroller++;\n\t\t\t\t\tIsScrollingDown = false;\n\t\t\t\t\tIsScrolling = true;\n\t\t\t\t\tTopIndex--;\n\t\t\t\t\tSlid = 0;\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tif (TopIndex+MAX_VISIBLE >= BuildableCount) {\n\t\t\t\t\tScroller = 0;\n\t\t\t\t} else {\n\t\t\t\t\tScroller--;\n\t\t\t\t\tSlid = OBJECT_HEIGHT;\n\t\t\t\t\tIsScrollingDown = true;\n\t\t\t\t\tIsScrolling = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tScroll logic is handled here.\n\t*/\n\tif (IsScrolling) {\n\t\tif (IsScrollingDown) {\n\t\t\tSlid -= SCROLL_RATE;\n\t\t\tif (Slid <= 0) {\n\t\t\t\tIsScrolling = false;\n\t\t\t\tSlid = 0;\n\t\t\t\tTopIndex++;\n\t\t\t}\n\t\t} else {\n\t\t\tSlid += SCROLL_RATE;\n\t\t\tif (Slid >= OBJECT_HEIGHT) {\n\t\t\t\tIsScrolling = false;\n\t\t\t\tSlid = 0;\n\t\t\t}\n\t\t}\n\t\tredraw = true;\n\t}\n\n\t/*\n\t**\tHandle any flashing logic. Flashing occurs when the player selects an object\n\t**\tand provides the visual feedback of a recognized and legal selection.\n\t*/\n\tif (Flasher != -1) {\n\t\tif (Graphic_Logic()) {\n\t\t\tredraw = true;\n\t\t\tif (Fetch_Stage() >= 7) {\n\t\t\t\tSet_Rate(0);\n\t\t\t\tSet_Stage(0);\n\t\t\t\tFlasher = -1;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tHandle any building clock animation logic.\n\t*/\n\tif (IsBuilding) {\n\t\tfor (int index = 0; index < BuildableCount; index++) {\n\t\t\tint factoryid = Buildables[index].Factory;\n\n\t\t\tif (factoryid != -1) {\n\t\t\t\tFactoryClass * factory = Factories.Raw_Ptr(factoryid);\n\n\t\t\t\tif (factory && factory->Has_Changed()) {\n\t\t\t\t\tredraw = true;\n\t\t\t\t\tif (factory->Has_Completed()) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tConstruction has been completed. Announce this fact to the player and\n\t\t\t\t\t\t**\ttry to get the object to automatically leave the factory. Buildings are\n\t\t\t\t\t\t**\tthe main exception to the ability to leave the factory under their own\n\t\t\t\t\t\t**\tpower.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tTechnoClass * pending = factory->Get_Object();\n\t\t\t\t\t\tif (pending != NULL) {\n\t\t\t\t\t\t\tswitch (pending->What_Am_I()) {\n\t\t\t\t\t\t\t\tcase RTTI_VESSEL:\n\t\t\t\t\t\t\t\tcase RTTI_UNIT:\n\t\t\t\t\t\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PLACE, pending->What_Am_I(), -1));\n\t\t\t\t\t\t\t\t\tSpeak(VOX_UNIT_READY);\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase RTTI_BUILDING:\n\t\t\t\t\t\t\t\t\tSpeak(VOX_CONSTRUCTION);\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PLACE, pending->What_Am_I(), -1));\n\t\t\t\t\t\t\t\t\tSpeak(VOX_UNIT_READY);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf any of the logic determined that this side strip needs to be redrawn, then\n\t**\tset the redraw flag for this side strip.\n\t*/\n\tif (redraw) {\n\t\tFlag_To_Redraw();\n\t}\n\treturn(redraw);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Draw_It -- Render the sidebar display.                            *\n *                                                                                             *\n *    Use this routine to render the sidebar display. It checks to see if it needs to be       *\n *    redrawn and only redraw if necessary. If the \"complete\" parameter is true, then it       *\n *    will force redraw the entire strip.                                                      *\n *                                                                                             *\n * INPUT:   complete -- Should the redraw be forced? A force redraw will ignore the redraw     *\n *                      flag.                                                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/31/1994 JLB : Created.                                                                 *\n *   08/06/1995 JLB : Handles multi factory tracking in same strip.                            *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::Draw_It(bool complete)\n{\n\tif (IsToRedraw || complete) {\n\t\tIsToRedraw = false;\n\n\t\tSidebarRedraws++;\n\n\t\t/*\n\t\t**\tFills the background to the side strip. We shouldnt need to do this if the strip\n\t\t** has a full complement of icons.\n\t\t*/\n\t\t/*\n\t\t** New sidebar needs to be drawn not filled\n\t\t*/\n\t\tif (BuildableCount < MAX_VISIBLE) {\n\t\t\tCC_Draw_Shape(LogoShapes, ID,\tX+(2*RESFACTOR),\tY,\tWINDOW_MAIN, SHAPE_WIN_REL|SHAPE_NORMAL,\t0);\n\t\t}\n\n\t\t/*\n\t\t**\tRedraw the scroll buttons.\n\t\t*/\n\t\tUpButton[ID].Draw_Me(true);\n\t\tDownButton[ID].Draw_Me(true);\n\n\t\t/*\n\t\t**\tLoop through all the buildable objects that are visible in the strip and render\n\t\t**\tthem. Their Y offset may be adjusted if the strip is in the process of scrolling.\n\t\t*/\n\t\tfor (int i = 0; i < MAX_VISIBLE + (IsScrolling ? 1 : 0); i++) {\n\t\t\tbool production;\n\t\t\tbool completed;\n\t\t\tint  stage;\n\t\t\tbool darken = false;\n\t\t\tvoid const * shapefile = 0;\n\t\t\tint shapenum = 0;\n\t\t\tvoid const * remapper = 0;\n\t\t\tFactoryClass * factory = 0;\n\t\t\tint index = i+TopIndex;\n\t\t\tint x = X;\n\t\t\tint y = Y + (i*OBJECT_HEIGHT * RESFACTOR);\n\n\t\t\t/*\n\t\t\t**\tIf the strip is scrolling, then the offset is adjusted accordingly.\n\t\t\t*/\n\t\t\tif (IsScrolling) {\n\t\t\t\ty -= (OBJECT_HEIGHT - Slid)  * RESFACTOR;\n//\t\t\t\ty -= OBJECT_HEIGHT - Slid;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tFetch the shape number for the object type located at this current working\n\t\t\t**\tslot. This shape pointer is used to draw the underlying graphic there.\n\t\t\t*/\n\t\t\tif ((unsigned)index < BuildableCount) {\n\t\t\t\tObjectTypeClass const * obj = NULL;\n\t\t\t\tSpecialWeaponType spc = SPC_NONE;\n\n\t\t\t\tif (Buildables[index].BuildableType != RTTI_SPECIAL) {\n\n\t\t\t\t\tobj = Fetch_Techno_Type(Buildables[index].BuildableType, Buildables[index].BuildableID);\n\t\t\t\t\tif (obj != NULL) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tFetch the remap table that is appropriate for this object\n\t\t\t\t\t\t**\ttype.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tremapper = PlayerPtr->Remap_Table(false, ((TechnoTypeClass const *)obj)->Remap);\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf there is already a factory producing this kind of object, then all\n\t\t\t\t\t\t**\tobjects of this type are displays in a disabled state.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tbool isbusy = (PlayerPtr->Fetch_Factory(Buildables[index].BuildableType) != NULL);\n\t\t\t\t\t\tif (!isbusy && PlayerPtr->Is_Hack_Prevented(Buildables[index].BuildableType, Buildables[index].BuildableID)) {\n\t\t\t\t\t\t\tisbusy = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tInfantry don't get remapped in the sidebar (special case).\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (Buildables[index].BuildableType == RTTI_INFANTRYTYPE) {\n\t\t\t\t\t\t\tremapper = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tshapefile = obj->Get_Cameo_Data();\n\t\t\t\t\t\tshapenum  = 0;\n\t\t\t\t\t\tif (Buildables[index].Factory != -1) {\n\t\t\t\t\t\t\tfactory \t\t= Factories.Raw_Ptr(Buildables[index].Factory);\n\t\t\t\t\t\t\tproduction\t= true;\n\t\t\t\t\t\t\tcompleted\t= factory->Has_Completed();\n\t\t\t\t\t\t\tstage\t\t\t= factory->Completion();\n\t\t\t\t\t\t\tdarken\t\t= false;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tproduction  = false;\n//\t\t\t\t\t\t\tdarken      = IsBuilding;\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tDarken the imagery if a factory of a matching type is\n\t\t\t\t\t\t\t**\talready busy.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tdarken = isbusy;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdarken = PlayerPtr->Is_Hack_Prevented(Buildables[index].BuildableType, Buildables[index].BuildableID);\n\t\t\t\t\t}\n\n\t\t\t\t} else  {\n\n\t\t\t\t\tspc = SpecialWeaponType(Buildables[index].BuildableID);\n\t\t\t\t\tshapefile = Get_Special_Cameo(spc);\n\t\t\t\t\tshapenum = 0;\n\n\t\t\t\t\tproduction = true;\n\t\t\t\t\tcompleted = PlayerPtr->SuperWeapon[spc].Is_Ready();\n\t\t\t\t\tstage = PlayerPtr->SuperWeapon[spc].Anim_Stage();\n\t\t\t\t\tdarken = false;\n\t\t\t\t}\n\n\t\t\t\tif (obj != NULL || spc != SPC_NONE) {\n\t\t\t\t\t/*\n\t\t\t\t\t** If this item is flashing then take care of it.\n\t\t\t\t\t**\n\t\t\t\t\t*/\n\t\t\t\t\tif (Flasher == index && (Fetch_Stage() & 0x01)) {\n\t\t\t\t\t\tremapper = Map.FadingLight;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tshapefile\t= LogoShapes;\n\t\t\t\t\tif (!darken) {\n\t\t\t\t\t\tshapenum\t\t= SB_BLANK;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tshapefile\t= LogoShapes;\n\t\t\t\tshapenum\t\t= SB_BLANK;\n\t\t\t\tproduction\t= false;\n\t\t\t}\n\n\t\t\tremapper = 0;\n\t\t\t/*\n\t\t\t**\tNow that the shape of the object at the current working slot has been found,\n\t\t\t**\tdraw it and any graphic overlays as necessary.\n\t\t\t**\n\t\t\t** Don't draw blank shapes over the new 640x400 sidebar art - ST 5/1/96 6:01PM\n\t\t\t*/\n\t\t\tif (shapenum != SB_BLANK || shapefile != LogoShapes) {\n\t\t\t\tCC_Draw_Shape(shapefile, shapenum,\n\t\t\t\t\tx-(WindowList[WINDOW_SIDEBAR][WINDOWX])+(LEFT_EDGE_OFFSET * RESFACTOR),\n\t\t\t\t\ty-WindowList[WINDOW_SIDEBAR][WINDOWY],\n\t\t\t\t\tWINDOW_SIDEBAR,\n\t\t\t\t\tSHAPE_NORMAL|SHAPE_WIN_REL| (remapper ? SHAPE_FADING : SHAPE_NORMAL),\n\t\t\t\t\tremapper);\n\n\t\t\t\t/*\n\t\t\t\t**\tDarken this object because it cannot be produced or is otherwise\n\t\t\t\t**\tunavailable.\n\t\t\t\t*/\n\t\t\t\tif (darken) {\n\t\t\t\t\tCC_Draw_Shape(ClockShapes, 0,\n\t\t\t\t\t\t\tx-(WindowList[WINDOW_SIDEBAR][WINDOWX])+(LEFT_EDGE_OFFSET * RESFACTOR),\n\t\t\t\t\t\t\ty-WindowList[WINDOW_SIDEBAR][WINDOWY],\n\t\t\t\t\t\t\tWINDOW_SIDEBAR,\n\t\t\t\t\t\t\tSHAPE_NORMAL|SHAPE_WIN_REL|SHAPE_GHOST,\n\t\t\t\t\t\t\tNULL, ClockTranslucentTable);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDraw the overlapping clock shape if this is object is being constructed.\n\t\t\t**\tIf the object is completed, then display \"Ready\" with no clock shape.\n\t\t\t*/\n\t\t\tif (production) {\n\t\t\t\tif (completed) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDisplay text showing that the object is ready to place.\n\t\t\t\t\t*/\n\t\t\t\t\tCC_Draw_Shape(ObjectTypeClass::PipShapes, PIP_READY,\n\t\t\t\t\t(x-(WindowList[WINDOW_SIDEBAR][WINDOWX]))+(LEFT_EDGE_OFFSET+15) * RESFACTOR,\n\t\t\t\t\t(y-WindowList[WINDOW_SIDEBAR][WINDOWY])+(4 * RESFACTOR),\n\t\t\t\t\tWINDOW_SIDEBAR, SHAPE_CENTER);\n\t\t\t\t} else {\n\n\t\t\t\t\tCC_Draw_Shape(ClockShapes, stage+1,\n\t\t\t\t\t\t\tx-(WindowList[WINDOW_SIDEBAR][WINDOWX])+(LEFT_EDGE_OFFSET * RESFACTOR),\n\t\t\t\t\t\t\ty-WindowList[WINDOW_SIDEBAR][WINDOWY],\n\t\t\t\t\t\t\tWINDOW_SIDEBAR,\n\t\t\t\t\t\t\tSHAPE_NORMAL|SHAPE_WIN_REL|SHAPE_GHOST,\n\t\t\t\t\t\t\tNULL, ClockTranslucentTable);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDisplay text showing that the construction is temporarily on hold.\n\t\t\t\t\t*/\n\t\t\t\t\tif (factory && !factory->Is_Building()) {\n\t\t\t\t\t\tCC_Draw_Shape(ObjectTypeClass::PipShapes, PIP_HOLDING,\n\t\t\t\t\t\t(x-(WindowList[WINDOW_SIDEBAR][WINDOWX])) + ((LEFT_EDGE_OFFSET+15) * RESFACTOR),\n\t\t\t\t\t\t(y-WindowList[WINDOW_SIDEBAR][WINDOWY])+(4 * RESFACTOR),\n\t\t\t\t\t\tWINDOW_SIDEBAR, SHAPE_CENTER);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\tLastSlid = Slid;\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Recalc -- Revalidates the current sidebar list of objects.        *\n *                                                                                             *\n *    This routine will revalidate all the buildable objects in the sidebar. This routine      *\n *    comes in handy when a factory has been destroyed, and the sidebar needs to reflect any   *\n *    change that this requires. It checks every object to see if there is a factory available *\n *    that could produce it. If none can be found, then the object is removed from the         *\n *    sidebar.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; The sidebar has changed as a result of this call?                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *   06/26/1995 JLB : Doesn't collapse sidebar when buildables removed.                        *\n *=============================================================================================*/\nbool SidebarClass::StripClass::Recalc(void)\n{\n\tint ok;\n\n\tif (Debug_Map || !BuildableCount) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tSweep through all objects listed in the sidebar. If any of those object can\n\t**\tnot be created -- even in theory -- then they must be removed form the sidebar and\n\t**\tany current production must be abandoned.\n\t*/\n\tbool redraw = false;\n\tfor (int index = 0; index < BuildableCount; index++) {\n\t\tTechnoTypeClass const * tech = Fetch_Techno_Type(Buildables[index].BuildableType, Buildables[index].BuildableID);\n\t\tif (tech != NULL) {\n\t\t\tok = tech->Who_Can_Build_Me(true, false, PlayerPtr->Class->House) != NULL;\n\t\t} else {\n\t\t\tif ((unsigned)Buildables[index].BuildableID < SPC_COUNT) {\n\t\t\t\tok = PlayerPtr->SuperWeapon[Buildables[index].BuildableID].Is_Present();\n\t\t\t} else {\n\t\t\t\tok = false;\n\t\t\t}\n\t\t}\n\n\t\tif (!ok) {\n\n\t\t\t/*\n\t\t\t**\tRemoves this entry from the list.\n\t\t\t*/\n\t\t\tif (BuildableCount > 1 && index < BuildableCount-1) {\n\t\t\t\tmemcpy(&Buildables[index], &Buildables[index+1], sizeof(Buildables[0])*((BuildableCount-index)-1));\n\t\t\t}\n\t\t\tTopIndex = 0;\n\t\t\tIsToRedraw = true;\n\t\t\tredraw = true;\n\t\t\tBuildableCount--;\n\t\t\tindex--;\n\t\t}\n\t}\n\n#ifdef NEVER\n\t/*\n\t**\tIf there are no more buildable objects to display, make the sidebar go away.\n\t*/\n\tif (!BuildableCount) {\n\t\tMap.SidebarClass::Activate(0);\n\t}\n#endif\n\treturn(redraw);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::SelectClass::SelectClass -- Default constructor.                  *\n *                                                                                             *\n *    This is the default constructor for the button that controls the buildable cameos on     *\n *    the sidebar strip.                                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The coordinates are set to zero by this routine. They must be set to the        *\n *             correct values before this button will function.                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nSidebarClass::StripClass::SelectClass::SelectClass(void) :\n\tControlClass(0, 0, 0, (OBJECT_WIDTH-1) * RESFACTOR, OBJECT_HEIGHT * RESFACTOR, LEFTPRESS|RIGHTPRESS|LEFTUP),\n\tStrip(0),\n\tIndex(0)\n{\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::SelectClass:: -- Assigns special values to a buildable select but *\n *                                                                                             *\n *    Use this routine to set custom buildable vars for this particular select button. It      *\n *    uses this information to properly know what buildable object to start or stop production *\n *    on.                                                                                      *\n *                                                                                             *\n * INPUT:   strip    -- Reference to the strip that owns this buildable button.                *\n *                                                                                             *\n *          index    -- The index (0 .. MAX_VISIBLE-1) of this button. This is used to let     *\n *                      the owning strip know what index this button refers to.                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::SelectClass::Set_Owner(StripClass & strip, int index)\n{\n\tStrip = &strip;\n\tIndex = index;\n\tX = strip.X;\n\tY = strip.Y + ((index * OBJECT_HEIGHT) * RESFACTOR);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::SelectClass:: -- Action function when buildable cameo is selected *\n *                                                                                             *\n *    This function is called when the buildable icon (cameo) is clicked on. It handles        *\n *    starting and stopping production as indicated.                                           *\n *                                                                                             *\n * INPUT:   flags -- The input event that triggered the call.                                  *\n *                                                                                             *\n *          key   -- The keyboard value at the time of the input.                              *\n *                                                                                             *\n * OUTPUT:  Returns with whether the input list should be scanned further.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *   10/09/1996 JLB : Sonar pulse converted to regular event type.                             *\n *=============================================================================================*/\nint SidebarClass::StripClass::SelectClass::Action(unsigned flags, KeyNumType & key)\n{\n\tint index = Strip->TopIndex + Index;\n\tRTTIType otype = Strip->Buildables[index].BuildableType;\n\tint oid = Strip->Buildables[index].BuildableID;\n\tint fnumber = Strip->Buildables[index].Factory;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\tObjectTypeClass const * choice = NULL;\n\tSpecialWeaponType spc = SPC_NONE;\n\n\t/*\n\t**\tDetermine the factory number that would apply to objects of the type\n\t**\tthe mouse is currently addressing. This doesn't mean that the factory number\n\t**\tfetched is actually producing the indicated object, merely that that particular\n\t**\tkind of factory is specified by the \"genfactory\" value. This can be used to see\n\t**\tif the factory type is currently busy or not.\n\t*/\n\tFactoryClass * factory = PlayerPtr->Fetch_Factory(otype);\n\n\tMap.Override_Mouse_Shape(MOUSE_NORMAL);\n\n\tif (index < Strip->BuildableCount) {\n\t\tif (otype != RTTI_SPECIAL) {\n\t\t\tchoice  = Fetch_Techno_Type(otype, oid);\n\t\t} else {\n\t\t\tspc = SpecialWeaponType(oid);\n\t\t}\n\n\t\tif (fnumber != -1) {\n\t\t\tfactory = Factories.Raw_Ptr(fnumber);\n\t\t}\n\n  \t} else {\n  \t\tMap.Help_Text(TXT_NONE);\n  \t}\n\n\tif (spc != SPC_NONE) {\n\n\t\t/*\n\t\t**\tDisplay the help text if the mouse is over the button.\n\t\t*/\n\t\tif (flags & LEFTUP) {\n\t\t\tMap.Help_Text(SpecialWeaponHelp[spc], X, Y, scheme->Color, true);\n\t\t\tflags &= ~LEFTUP;\n\t\t}\n\n\t\t/*\n\t\t**\tA right mouse button signals \"cancel\".  If we are in targeting\n\t\t** mode then we don't want to be any more.\n\t\t*/\n\t\tif (flags & RIGHTPRESS) {\n\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t}\n\t\t/*\n\t\t**\tA left mouse press signal \"activate\".  If our weapon type is\n\t\t** available then we should activate it.\n\t\t*/\n\t\tif (flags & LEFTPRESS) {\n\n\t\t\tif ((unsigned)spc < SPC_COUNT) {\n\t\t\t\tif (PlayerPtr->SuperWeapon[spc].Is_Ready()) {\n\t\t\t\t\tif (spc != SPC_SONAR_PULSE) {\n\t\t\t\t\t\tMap.IsTargettingMode = spc;\n\t\t\t\t\t\tUnselect_All();\n\t\t\t\t\t\tSpeak(VOX_SELECT_TARGET);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tOutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_SONAR_PULSE, 0));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tPlayerPtr->SuperWeapon[spc].Impatient_Click();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\tif (choice != NULL) {\n\n\t\t\t/*\n\t\t\t**\tDisplay the help text if the mouse is over the button.\n\t\t\t*/\n\t\t\tif (flags & LEFTUP) {\n\t\t\t\tMap.Help_Text(choice->Full_Name(), X, Y, scheme->Color, true);\n\t\t\t\tMap.Set_Cost(choice->Cost_Of() * PlayerPtr->CostBias);\n\t\t\t\tflags &= ~LEFTUP;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tA right mouse button signals \"cancel\".\n\t\t\t*/\n\t\t\tif (flags & RIGHTPRESS) {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf production is in progress, put it on hold. If production is already\n\t\t\t\t**\ton hold, then abandon it. Money will be refunded, the factory\n\t\t\t\t**\tmanager deleted, and the object under construction is returned to\n\t\t\t\t**\tthe free pool.\n\t\t\t\t*/\n\t\t\t\tif (factory != NULL) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCancels placement mode if the sidebar factory is abandoned or\n\t\t\t\t\t**\tsuspended.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Map.PendingObjectPtr && Map.PendingObjectPtr->Is_Techno()) {\n\t\t\t\t\t\tMap.PendingObjectPtr = 0;\n\t\t\t\t\t\tMap.PendingObject = 0;\n\t\t\t\t\t\tMap.PendingHouse = HOUSE_NONE;\n\t\t\t\t\t\tMap.Set_Cursor_Shape(0);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!factory->Is_Building()) {\n\t\t\t\t\t\tSpeak(VOX_CANCELED);\n\t\t\t\t\t\tOutList.Add(EventClass(EventClass::ABANDON, otype, oid));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSpeak(VOX_SUSPENDED);\n\t\t\t\t\t\tOutList.Add(EventClass(EventClass::SUSPEND, otype, oid));\n\t\t\t\t\t\tMap.Column[0].IsToRedraw = true;\n\t\t\t\t\t\tMap.Column[1].IsToRedraw = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (flags & LEFTPRESS) {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf there is already a factory attached to this strip but the player didn't click\n\t\t\t\t**\ton the icon that has the attached factory, then say that the factory is busy and\n\t\t\t\t**\tignore the click.\n\t\t\t\t*/\n\t\t\t\tif (fnumber == -1 && factory != NULL) {\n\t\t\t\t\tSpeak(VOX_NO_FACTORY);\n\t\t\t\t\tControlClass::Action(flags, key);\n\t\t\t\t\treturn(true);\n\t\t\t\t}\n\n\t\t\t\tif (factory != NULL) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf this object is currently being built, then give a scold sound and text and then\n\t\t\t\t\t**\tbail.\n\t\t\t\t\t*/\n\t\t\t\t\tif (factory->Is_Building()) {\n\t\t\t\t\t\tSpeak(VOX_NO_FACTORY);\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf production has completed, then attempt to have the object exit\n\t\t\t\t\t\t**\tthe factory or go into placement mode.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (factory->Has_Completed()) {\n\n\t\t\t\t\t\t\tTechnoClass * pending = factory->Get_Object();\n\t\t\t\t\t\t\tif (!pending && factory->Get_Special_Item()) {\n\t\t\t\t\t\t\t\tMap.IsTargettingMode = SPC_ANY;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tBuildingClass * builder = pending->Who_Can_Build_Me(false, false);\n\t\t\t\t\t\t\t\tif (!builder) {\n\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::ABANDON, otype, oid));\n\t\t\t\t\t\t\t\t\tSpeak(VOX_NO_FACTORY);\n\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t**\tIf the completed object is a building, then change the\n\t\t\t\t\t\t\t\t\t**\tgame state into building placement mode. This fact is\n\t\t\t\t\t\t\t\t\t**\tnot transmitted to any linked computers until the moment\n\t\t\t\t\t\t\t\t\t**\tthe building is actually placed down.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tif (pending->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\t\t\t \t\tPlayerPtr->Manual_Place(builder, (BuildingClass *)pending);\n\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t**\tFor objects that can leave the factory under their own\n\t\t\t\t\t\t\t\t\t\t**\tpower, queue this event and process through normal house\n\t\t\t\t\t\t\t\t\t\t**\tproduction channels.\n\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PLACE, otype, -1));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tif (PlayerPtr->Is_Hack_Prevented(otype, oid)) {\n\t\t\t\t\t\t\t\t// Eva scolds the player here.\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t**\tThe factory must have been in a suspended state. Resume construction\n\t\t\t\t\t\t\t\t**\tnormally.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tif (otype == RTTI_INFANTRYTYPE) {\n\t\t\t\t\t\t\t\t\tSpeak(VOX_TRAINING);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tSpeak(VOX_BUILDING);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PRODUCE, Strip->Buildables[index].BuildableType, Strip->Buildables[index].BuildableID));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif (PlayerPtr->Is_Hack_Prevented(otype, oid)) {\n\t\t\t\t\t\t// Eva scolds the player here.\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf this side strip is already busy with production, then ignore the\n\t\t\t\t\t\t**\tinput and announce this fact.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (otype == RTTI_INFANTRYTYPE) {\n\t\t\t\t\t\t\tSpeak(VOX_TRAINING);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSpeak(VOX_BUILDING);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PRODUCE, Strip->Buildables[index].BuildableType, Strip->Buildables[index].BuildableID));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tflags = 0;\n\t\t}\n\t}\n\n\tControlClass::Action(flags, key);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::SBGadgetClass::Action -- Special function that controls the mouse over the si *\n *                                                                                             *\n *    This routine is called whenever the mouse is over the sidebar. It makes sure that the    *\n *    mouse is always the normal shape while over the sidebar.                                 *\n *                                                                                             *\n * INPUT:   flags -- The event flags that resulted in this routine being called.               *\n *                                                                                             *\n *          key   -- Reference the keyboard code that may be present.                          *\n *                                                                                             *\n * OUTPUT:  Returns that no further keyboard processing is necessary.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint SidebarClass::SBGadgetClass::Action(unsigned , KeyNumType & )\n{\n\tMap.Help_Text(TXT_NONE);\n\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Factory_Link -- Links a factory to a sidebar button.              *\n *                                                                                             *\n *    This routine will link the specified factory to this sidebar strip. The exact button to  *\n *    link to is determined from the object type and id specified. A linked button is one that *\n *    will show appropriate construction animation (clock shape) that matches the state of     *\n *    the factory.                                                                             *\n *                                                                                             *\n * INPUT:   factory  -- The factory number to link to the sidebar.                             *\n *                                                                                             *\n *          type     -- The object type that this factory refers to.                           *\n *                                                                                             *\n *          id       -- The object sub-type that this factory refers to.                       *\n *                                                                                             *\n * OUTPUT:  Was the factory successfully attached? Failure would indicate that there is no     *\n *          object of the specified type and sub-type in the sidebar list.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::StripClass::Factory_Link(int factory, RTTIType type, int id)\n{\n\tfor (int index = 0; index < BuildableCount; index++) {\n\t\tif (Buildables[index].BuildableType == type && Buildables[index].BuildableID == id) {\n\t\t\tBuildables[index].Factory = factory;\n\t\t\tIsBuilding = true;\n\t\t\t/*\n\t\t\t** Flag that all the icons on this strip need to be redrawn\n\t\t\t*/\n\t\t\tFlag_To_Redraw();\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Abandon_Production -- Stops production of the object specified.               *\n *                                                                                             *\n *    This routine is used to abandon production of the object specified. The factory will     *\n *    be completely disabled by this call.                                                     *\n *                                                                                             *\n * INPUT:   type     -- The object type that is to be abandoned. The sub-type is not needed    *\n *                      since it is presumed there can be only one type in production at any   *\n *                      one time.                                                              *\n *                                                                                             *\n *          factory  -- The factory number that is doing the production.                       *\n *                                                                                             *\n * OUTPUT:  Was the factory successfully abandoned?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::Abandon_Production(RTTIType type, int factory)\n{\n\treturn(Column[Which_Column(type)].Abandon_Production(factory));\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Abandon_Produ -- Abandons production associated with sidebar.     *\n *                                                                                             *\n *    Production of the object associated with this sidebar is abandoned when this routine is  *\n *    called.                                                                                  *\n *                                                                                             *\n * INPUT:   factory  -- The factory index that is to be suspended.                             *\n *                                                                                             *\n * OUTPUT:  Was the production abandonment successful?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *   08/06/1995 JLB : More intelligent abandon logic for multiple factories.                   *\n *=============================================================================================*/\nbool SidebarClass::StripClass::Abandon_Production(int factory)\n{\n\tbool noprod = true;\n\tbool abandon = false;\n\tfor (int index = 0; index < BuildableCount; index++) {\n\t\tif (Buildables[index].Factory == factory) {\n\t\t\tFactories.Raw_Ptr(factory)->Abandon();\n\t\t\tBuildables[index].Factory = -1;\n\t\t\tabandon = true;\n\t\t} else {\n\t\t\tif (Buildables[index].Factory != -1) {\n\t\t\t\tnoprod = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there was a change to the strip, then flag the strip to be redrawn.\n\t*/\n\tif (abandon) {\n\t\tFlag_To_Redraw();\n\t}\n\n\t/*\n\t**\tIf there is no production whatsoever on this strip, then flag it so.\n\t*/\n\tif (noprod) {\n\t\tIsBuilding = false;\n\t}\n\treturn(abandon);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Zoom_Mode_Control -- Handles the zoom mode toggle operation.                  *\n *                                                                                             *\n *    This is the function that is called when the map button is pressed. It will toggle       *\n *    between the different modes that the radar map can assume.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/31/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::Zoom_Mode_Control(void)\n{\n#ifdef WIN32\n\t/*\n\t** If radar is active, cycle as follows:\n\t** Zoomed => not zoomed\n\t** not zoomed => player status (multiplayer only)\n\t** player status => radar spying readout\n\t** radar spying readout => zoomed\n\t*/\n\tif (IsRadarActive) {\n\t\tif (Is_Zoomed() || Session.Type==GAME_NORMAL) {\n\t\t\tif (Is_Zoomed() || !Spy_Next_House()) {\n\t\t\t\tZoom_Mode(Coord_Cell(TacticalCoord));\n\t\t\t}\n\t\t} else {\n\t\t\tif (!Spying_On_House() && !Is_Player_Names()) {\n\t\t\t\tPlayer_Names(1);\n\t\t\t} else {\n\t\t\t\tPlayer_Names(0);\n\t\t\t\tif (!Spy_Next_House()) {\n\t\t\t\t\tZoom_Mode(Coord_Cell(TacticalCoord));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (Session.Type!=GAME_NORMAL) {\n\t\t\tPlayer_Names(Is_Player_Names()==0);\n\t\t}\n\t}\n#else\n\t/*\n\t** If radar is active, cycle as follows:\n\t** not zoomed => player status (multiplayer only)\n\t** player status => radar spying readout\n\t** radar spying readout => not zoomed\n\t*/\n\tif (IsRadarActive) {\n\t\tif (Session.Type==GAME_NORMAL) {\n\t\t\tif (!Spy_Next_House()) {\n\t\t\t\tZoom_Mode(Coord_Cell(TacticalCoord));\n\t\t\t}\n\t\t} else {\n\t\t\tif (!Spying_On_House() && !Is_Player_Names()) {\n\t\t\t\tPlayer_Names(1);\n\t\t\t} else {\n\t\t\t\tPlayer_Names(0);\n\t\t\t\tif (!Spy_Next_House()) {\n\t\t\t\t\tZoom_Mode(Coord_Cell(TacticalCoord));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (Session.Type!=GAME_NORMAL) {\n\t\t\tPlayer_Names(Is_Player_Names()==0);\n\t\t}\n\t}\n#endif\n}\n"
  },
  {
    "path": "CODE/SIDEBAR.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SIDEBAR.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SIDEBAR.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : October 20, 1994                                             *\n *                                                                                             *\n *                  Last Update : October 20, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SIDEBAR_H\n#define SIDEBAR_H\n\n#include\t\"function.h\"\n#include\t\"power.h\"\n#include\t\"factory.h\"\n\nclass InitClass {};\n\nclass SidebarClass: public PowerClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThese constants are used to control the sidebar rendering. They are instantiated\n\t\t**\tas enumerations since C++ cannot use \"const\" in this context.\n\t\t*/\n\t\tenum SideBarClassEnums {\n\t\t\tBUTTON_ACTIVATOR=100,\t\t\t// Button ID for the activator.\n\t\t\tSIDE_X=320-80,\t\t\t\t\t// The X position of sidebar upper left corner.\n\t\t\tSIDE_Y=7+70,\t// The Y position of sidebar upper left corner.\n\t\t\tSIDE_WIDTH=SIDEBAR_WID,\t\t\t// Width of the entire sidebar (in pixels).\n\t\t\tSIDE_HEIGHT=200-(7+70),\t\t\t// Height of the entire sidebar (in pixels).\n\t\t\tTOP_HEIGHT=13,\t\t\t\t\t\t// Height of top section (with repair/sell buttons).\n\t\t\tCOLUMN_ONE_X=(320-80)+8,\t\t\t// Sidestrip upper left coordinates...\n\t\t\tCOLUMN_ONE_Y=int(SIDE_Y)+int(TOP_HEIGHT),\n\t\t\tCOLUMN_TWO_X=(320-80)+8+((80-16)/2)+3,\n\t\t\tCOLUMN_TWO_Y=7+70+13,\n\n//BGA: changes to all buttons\n#ifdef GERMAN\n\t\t\tBUTTON_ONE_WIDTH=20,\t\t\t\t// Button width.\n\t\t\tBUTTON_TWO_WIDTH=27,\t\t\t\t// Button width.\n\t\t\tBUTTON_THREE_WIDTH=26,\t\t\t// Button width.\n\t\t\tBUTTON_HEIGHT=9,\t\t\t\t\t// Button height.\n\t\t\tBUTTON_ONE_X=SIDE_X+2,\t\t\t// Left button X coordinate.\n\t\t\tBUTTON_ONE_Y=SIDE_Y+2,\t\t\t// Left button Y coordinate.\n\t\t\tBUTTON_TWO_X=SIDE_X+24,\t\t\t// Right button X coordinate.\n\t\t\tBUTTON_TWO_Y=SIDE_Y+2,\t\t\t// Right button Y coordinate.\n\t\t\tBUTTON_THREE_X=SIDE_X+53,\t\t\t// Right button X coordinate.\n\t\t\tBUTTON_THREE_Y=SIDE_Y+2,\t\t\t// Right button Y coordinate.\n#endif\n\n#ifdef FRENCH\n\t\t\tBUTTON_ONE_WIDTH=20,\t\t\t\t// Button width.\n\t\t\tBUTTON_TWO_WIDTH=27,\t\t\t\t// Button width.\n\t\t\tBUTTON_THREE_WIDTH=26,\t\t\t// Button width.\n\t\t\tBUTTON_HEIGHT=9,\t\t\t\t\t// Button height.\n\t\t\tBUTTON_ONE_X=SIDE_X+2,\t\t\t// Left button X coordinate.\n\t\t\tBUTTON_ONE_Y=SIDE_Y+2,\t\t\t// Left button Y coordinate.\n\t\t\tBUTTON_TWO_X=SIDE_X+24,\t\t\t// Right button X coordinate.\n\t\t\tBUTTON_TWO_Y=SIDE_Y+2,\t\t\t// Right button Y coordinate.\n\t\t\tBUTTON_THREE_X=SIDE_X+53,\t\t\t// Right button X coordinate.\n\t\t\tBUTTON_THREE_Y=SIDE_Y+2,\t\t\t// Right button Y coordinate.\n#endif\n\n#ifdef ENGLISH\n\t\t\tBUTTON_ONE_WIDTH=32,\t\t\t\t// Button width.\n\t\t\tBUTTON_TWO_WIDTH=20,\t\t\t\t// Button width.\n\t\t\tBUTTON_THREE_WIDTH=20,\t\t\t// Button width.\n\t\t\tBUTTON_HEIGHT=9,\t\t\t\t\t// Button height.\n\t\t\tBUTTON_ONE_X=(int)SIDE_X+2,\t\t\t// Left button X coordinate.\n\t\t\tBUTTON_ONE_Y=(int)SIDE_Y+2,\t\t\t// Left button Y coordinate.\n\t\t\tBUTTON_TWO_X=(int)SIDE_X+36,\t\t\t// Right button X coordinate.\n\t\t\tBUTTON_TWO_Y=(int)SIDE_Y+2,\t\t\t// Right button Y coordinate.\n\t\t\tBUTTON_THREE_X=(int)SIDE_X+58,\t\t\t// Right button X coordinate.\n\t\t\tBUTTON_THREE_Y=(int)SIDE_Y+2,\t\t\t// Right button Y coordinate.\n#endif\n\n\t\t\tCOLUMNS=2\t\t\t\t\t\t\t// Number of side strips on sidebar.\n\t\t};\n\n\t\tstatic void * SidebarShape;\n\t\tstatic void * SidebarMiddleShape;\t//Only used in Win95 version\n\t\tstatic void * SidebarBottomShape;\t//Only used in Win95 version\n\n\t\tSidebarClass(void);\n\t\tSidebarClass(NoInitClass const & x);\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t\t// One-time inits\n\t\tvirtual void Init_Clear(void);\t\t\t\t\t\t// Clears all to known state\n\t\tvirtual void Init_IO(void);\t\t\t\t\t\t\t// Inits button list\n\t\tvirtual void Init_Theater(TheaterType theater);\t// Theater-specific inits\n\t\tvoid Reload_Sidebar(void);\t\t\t\t\t\t\t\t// Loads house-specific sidebar art\n\n\t\tvirtual void AI(KeyNumType & input, int x, int y);\n\t\tvirtual void Draw_It(bool complete);\n\t\tvirtual void Refresh_Cells(CELL cell, short const *list);\n\n\t\tvoid Zoom_Mode_Control(void);\n\t\tbool Abandon_Production(RTTIType type, int factory);\n\t\tbool Activate(int control);\n\t\tbool Add(RTTIType type, int ID);\n\t\tbool Sidebar_Click(KeyNumType & input, int x, int y);\n\t\tvoid Recalc(void);\n\t\tbool Factory_Link(int factory, RTTIType type, int id);\n\n\t\t/*\n\t\t**\tEach side strip is managed by this class. It handles all strip specific\n\t\t**\tactions.\n\t\t*/\n\t\tclass StripClass : public StageClass\n\t\t{\n\t\t\tclass SelectClass : public ControlClass\n\t\t\t{\n\t\t\t\tpublic:\n\t\t\t\t\tSelectClass(void);\n\t\t\t\t\tSelectClass(NoInitClass const & x) : ControlClass(x) {};\n\n\t\t\t\t\tvoid Set_Owner(StripClass & strip, int index);\n\n\t\t\t\t\tStripClass * Strip;\n\t\t\t\t\tint Index;\n\n\t\t\t\tprotected:\n\t\t\t\t\tvirtual int Action(unsigned flags, KeyNumType & key);\n\t\t\t};\n\n\t\t\tpublic:\n\t\t\t\tStripClass(void) {}\n\t\t\t\tStripClass(InitClass const &);\n\t\t\t\tStripClass(NoInitClass const & ) {};\n\n\t\t\t\tbool Add(RTTIType type, int ID);\n\t\t\t\tbool Abandon_Production(int factory);\n\t\t\t\tbool Scroll(bool up);\n\t\t\t\tbool AI(KeyNumType & input, int x, int y);\n\t\t\t\tvoid Draw_It(bool complete);\n\t\t\t\tvoid One_Time(int id);\n\t\t\t\tvoid Init_Clear(void);\n\t\t\t\tvoid Init_IO(int id);\n\t\t\t\tvoid Init_Theater(TheaterType theater);\n\t\t\t\tvoid Reload_LogoShapes(void);\n\t\t\t\tbool Recalc(void);\n\t\t\t\tvoid Activate(void);\n\t\t\t\tvoid Deactivate(void);\n\t\t\t\tvoid Flag_To_Redraw(void);\n\t\t\t\tbool Factory_Link(int factory, RTTIType type, int id);\n\t\t\t\tvoid const * Get_Special_Cameo(SpecialWeaponType type);\n\n\t\t\t\t/*\n\t\t\t\t**\tFile I/O.\n\t\t\t\t*/\n\t\t\t\tbool Load(Straw & file);\n\t\t\t\tbool Save(Pipe & file) const;\n\n\t\t\t\t/*\n\t\t\t\t**\tWorking numbers used when rendering and processing the side strip.\n\t\t\t\t*/\n\t\t\t\tenum SideBarGeneralEnums {\n\t\t\t\t\tBUTTON_UP=200,\n\t\t\t\t\tBUTTON_DOWN=210,\n\t\t\t\t\tBUTTON_SELECT=220,\n\t\t\t\t\tMAX_BUILDABLES=75,\t\t\t// Maximum number of object types in sidebar.\n\t\t\t\t\tOBJECT_HEIGHT=24,\t\t\t\t// Pixel height of each buildable object.\n\t\t\t\t\tOBJECT_WIDTH=32,\t\t\t\t// Pixel width of each buildable object.\n\t\t\t\t\tSTRIP_WIDTH=35,\t\t\t\t// Width of strip (not counting border lines).\n\t\t\t\t\tMAX_VISIBLE=4,\t\t\t\t\t// Number of object slots visible at any one time.\n#ifdef WIN32\n\t\t\t\t\tSCROLL_RATE=12,\t\t\t\t// The pixel jump while scrolling (larger is faster).\n#else\n\t\t\t\t\tSCROLL_RATE=8,\t\t\t\t\t// The pixel jump while scrolling (larger is faster).\n#endif\n\t\t\t\t\tUP_X_OFFSET=2,\t\t\t\t\t// Scroll up arrow coordinates.\n#ifdef WIN32\n\t\t\t\t\tUP_Y_OFFSET=int(MAX_VISIBLE)*int(OBJECT_HEIGHT)+1,\n#else\n\t\t\t\t\tUP_Y_OFFSET=int(MAX_VISIBLE)*int(OBJECT_HEIGHT)+2,\n#endif\n\t\t\t\t\tDOWN_X_OFFSET=18,\t\t\t\t// Scroll down arrow coordinates.\n\t\t\t\t\tDOWN_Y_OFFSET=UP_Y_OFFSET,//BGint(MAX_VISIBLE)*int(OBJECT_HEIGHT)+1,\n\t\t\t\t\tSBUTTON_WIDTH=16,\t\t\t\t// Width of the mini-scroll button.\n\t\t\t\t\tSBUTTON_HEIGHT=12,\t\t\t\t// Height of the mini-scroll button.\n\t\t\t\t\tLEFT_EDGE_OFFSET=2,\t\t\t// Offset from left edge for building shapes.\n\t\t\t\t\tTEXT_X_OFFSET=18,\t\t\t\t// X offset to print \"ready\" text.\n\t\t\t\t\tTEXT_Y_OFFSET=15,\t\t\t\t// Y offset to print \"ready\" text.\n\t\t\t\t\tTEXT_COLOR=255\t\t\t\t\t// Color to use for the \"Ready\" text.\n\t\t\t\t};\n\n\t\t\t\t/*\n\t\t\t\t**\tThis is the coordinate of the upper left corner that this side strip\n\t\t\t\t**\tuses for rendering.\n\t\t\t\t*/\n\t\t\t\tint X,Y;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis is a unique identifier for the sidebar strip. Using this identifier,\n\t\t\t\t**\tit is possible to differentiate the button messages that arrive from the\n\t\t\t\t**\tcommon input button list.  It >MUST< be equal to the strip's index into\n\t\t\t\t** the Column[] array, because the strip uses it to access the stripclass\n\t\t\t\t** buttons.\n\t\t\t\t*/\n\t\t\t\tint ID;\n\n\t\t\t\t/*\n\t\t\t\t**\tShape numbers for the shapes in the STRIP.SHP file.\n\t\t\t\t*/\n\t\t\t\tenum SideBarStipShapeEnums {\n\t\t\t\t\tSB_BLANK,\t\t\t// The blank rectangle to use if there are no objects present.\n\t\t\t\t\tSB_FRAME\n\t\t\t\t};\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this particular side strip needs to be redrawn, then this flag\n\t\t\t\t**\twill be true.\n\t\t\t\t*/\n\t\t\t\tunsigned IsToRedraw:1;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf construction is in progress (no other objects in this strip can\n\t\t\t\t**\tbe started), then this flag will be true. It will be cleared when\n\t\t\t\t**\tthe strip is free to start production again.\n\t\t\t\t*/\n\t\t\t\tunsigned IsBuilding:1;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis controls the sidebar slide direction. If this is true, then the sidebar\n\t\t\t\t**\twill scroll downward -- revealing previous objects.\n\t\t\t\t*/\n\t\t\t\tunsigned IsScrollingDown:1;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the sidebar is scrolling, then this flag is true. Otherwise it is false.\n\t\t\t\t*/\n\t\t\t\tunsigned IsScrolling:1;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis is the object (sidebar slot) that is flashing. Only one slot can be flashing\n\t\t\t\t**\tat any one instant. This is usually the result of a click on the slot and construction\n\t\t\t\t**\thas commenced.\n\t\t\t\t*/\n\t\t\t\tint Flasher;\n\n\t\t\t\t/*\n\t\t\t\t**\tAs the sidebar scrolls up and down, this variable holds the index for the topmost\n\t\t\t\t**\tvisible sidebar slot.\n\t\t\t\t*/\n\t\t\t\tint TopIndex;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis is the queued scroll direction and amount. The sidebar\n\t\t\t\t**\twill scroll the number of slots indicated by this value. This\n\t\t\t\t**\tvalue is set according to the scroll buttons.\n\t\t\t\t*/\n\t\t\t\tint Scroller;\n\n\t\t\t\t/*\n\t\t\t\t**\tThe sidebar has smooth scrolling. This is the number of pixels the sidebar\n\t\t\t\t**\thas slide down. Thus, if this value were 5, then there would be 5 pixels of\n\t\t\t\t**\tthe TopIndex-1 sidebar object visible. When the Slid value reaches 24, then\n\t\t\t\t**\tthe value resets to zero and the TopIndex is decremented. For sliding in the\n\t\t\t\t**\topposite direction, change the IsScrollingDown flag.\n\t\t\t\t*/\n\t\t\t\tint Slid;\n\n\t\t\t\t/*\n\t\t\t\t** The value of Slid the last time we rendered the sidebar.\n\t\t\t\t*/\n\t\t\t\tint LastSlid;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis is the count of the number of sidebar slots that are active.\n\t\t\t\t*/\n\t\t\t\tint BuildableCount;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis is the array of buildable object types. This array is sorted in the order\n\t\t\t\t**\tthat it is to be displayed. This array keeps track of which objects are building\n\t\t\t\t**\tand ready to be placed. The very nature of this method precludes simultaneous\n\t\t\t\t**\tconstruction of the same object type.\n\t\t\t\t*/\n\t\t\t\ttypedef struct BuildType {\n\t\t\t\t\tint BuildableID;\n\t\t\t\t\tRTTIType BuildableType;\n\t\t\t\t\tint Factory;\t\t\t\t\t\t\t\t// Production manager.\n\t\t\t\t} BuildType;\n\t\t\t\tBuildType Buildables[MAX_BUILDABLES];\n\n\t\t\t\t/*\n\t\t\t\t**\tPointer to the shape data for small versions of the logos. These are used as\n\t\t\t\t**\tplaceholder pieces on the side bar.\n\t\t\t\t*/\n\t\t\t\tstatic void * LogoShapes;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis points to the animation sequence of frames used to mark the passage of time\n\t\t\t\t**\tas an object is undergoing construction.\n\t\t\t\t*/\n\t\t\t\tstatic void const * ClockShapes;\n\n\t\t\t\t/*\n\t\t\t\t** This points to the animation sequence which deals with special\n\t\t\t\t** shapes which handle non-production based icons.\n\t\t\t\t*/\n\t\t\t\tstatic void const * SpecialShapes[SPC_COUNT];\n\n\t\t\t\t/*\n\t\t\t\t**\tThis is the last theater that the special palette remap table was loaded\n\t\t\t\t**\tfor. If the current theater differs from this recorded value, then the\n\t\t\t\t**\tremap tables are reloaded.\n\t\t\t\t*/\n//\t\t\t\tstatic TheaterType LastTheater;\n\n\t\t\t\tstatic ShapeButtonClass UpButton[COLUMNS];\n\t\t\t\tstatic ShapeButtonClass DownButton[COLUMNS];\n\t\t\t\tstatic SelectClass SelectButton[COLUMNS][MAX_VISIBLE];\n\n\t\t\t\t/*\n\t\t\t\t**\tThis points to the shapes that are used for the clock overlay. This displays\n\t\t\t\t**\tprogress of construction.\n\t\t\t\t*/\n\t\t\t\tstatic char ClockTranslucentTable[(1+1)*256];\n\n\t\t} Column[COLUMNS];\n\n\n\t\t/*\n\t\t**\tIf the sidebar is active then this flag is true.\n\t\t*/\n\t\tunsigned IsSidebarActive:1;\n\n\t\t/*\n\t\t**\tThis flag tells the rendering system that the sidebar needs to be redrawn.\n\t\t*/\n\t\tunsigned IsToRedraw:1;\n\n\t\tclass SBGadgetClass: public GadgetClass {\n\t\t\tpublic:\n//#ifdef WIN32\n\t\t\t\tSBGadgetClass(void) : GadgetClass((int)((int)SIDE_X+8)*RESFACTOR, (int)SIDE_Y*RESFACTOR, (int)((int)SIDE_WIDTH-1)*RESFACTOR-1, (int)((int)SIDE_HEIGHT-1)*RESFACTOR, LEFTUP) {};\n//#else\n//\t\t\t\tSBGadgetClass(void) : GadgetClass((int)SIDE_X+8, (int)SIDE_Y, (int)SIDE_WIDTH-1, (int)SIDE_HEIGHT-1, LEFTUP) {};\n//#endif\n\t\t\tprotected:\n\t\t\t\tvirtual int Action(unsigned flags, KeyNumType & key);\n\t\t};\n\n\t\t/*\n\t\t**\tThis is the button that is used to collapse and expand the sidebar.\n\t\t** These buttons must be available to derived classes, for Save/Load.\n\t\t*/\n\t\tstatic ShapeButtonClass Repair;\n\t\tstatic ShapeButtonClass Upgrade;\n\t\tstatic ShapeButtonClass Zoom;\n\t\tstatic SBGadgetClass Background;\n\n\t\tbool Scroll(bool up, int column);\n\n\tprivate:\n\t\tbool Activate_Repair(int control);\n\t\tbool Activate_Upgrade(int control);\n\t\tbool Activate_Demolish(int control);\n\t\tint Which_Column(RTTIType type);\n\n\t\tunsigned IsRepairActive:1;\n\t\tunsigned IsUpgradeActive:1;\n\t\tunsigned IsDemolishActive:1;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/SLIDER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SLIDER.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SLIDER.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : September 20, 1995 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SliderClass::Action -- Handles input processing for the slider.                           *\n *   SliderClass::Bump -- Bumps the slider one \"thumb size\" up or down.                        *\n *   SliderClass::Recalc_Thumb -- Recalculates the thumb pixel size and starting offset.       *\n *   SliderClass::Set_Maximum -- Sets the maximum value for this slider.                       *\n *   SliderClass::Set_Thumb_Size -- Sets the size of the thumb in \"slider units\".              *\n *   SliderClass::Set_Value -- Sets the current thumb position for the slider.                 *\n *   SliderClass::SliderClass -- Normal constructor for a slider (with thumb) gadget.          *\n *   SliderClass::Step -- Steps the slider one value up or down.                               *\n *   SliderClass::Draw_Thumb -- Draws the \"thumb\" for this slider.                             *\n *   SliderClass::~SliderClass -- Destructor for slider object.                                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include \"slider.h\"\n\n\n/***********************************************************************************************\n * SliderClass::SliderClass -- Normal constructor for a slider (with thumb) gadget.            *\n *                                                                                             *\n *    This is the normal constructor for the slider gadget.                                    *\n *                                                                                             *\n * INPUT:   id    -- The ID number to assign to this gadget.                                   *\n *          x,y   -- The pixel coordinate of the upper left corner for this gadget.            *\n *          w,h   -- The width and height of the slider gadget. The slider automatically       *\n *                   adapts for horizontal or vertical operation depending on which of these   *\n *                   dimensions is greater.                                                    *\n * OUTPUT:     none                                                                            *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/15/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nSliderClass::SliderClass(unsigned id, int x, int y, int w, int h, int belong_to_list)\n\t: GaugeClass(id, x, y, w, h)\n{\n\tBelongToList = belong_to_list ? true : false;\n\n\tPlusGadget = 0;\n\tMinusGadget = 0;\n\tif (!BelongToList) {\n\t\tPlusGadget  = new ShapeButtonClass(id, MFCD::Retrieve(\"BTN-PLUS.SHP\"), X+Width+2, Y);\n\t\tMinusGadget = new ShapeButtonClass(id, MFCD::Retrieve(\"BTN-MINS.SHP\"), X-6, Y);\n\n\t\tif (PlusGadget) {\n\t\t\tPlusGadget->Make_Peer(*this);\n\t\t\tPlusGadget->Add(*this);\n\t\t\tPlusGadget->Flag_To_Redraw();\n\t\t}\n\t\tif (MinusGadget) {\n\t\t\tMinusGadget->Make_Peer(*this);\n\t\t\tMinusGadget->Add(*this);\n\t\t\tMinusGadget->Flag_To_Redraw();\n\t\t}\n\t}\n\tSet_Thumb_Size(1);\n\tRecalc_Thumb();\n\n\t/*\n\t** Gauges have at least 2 colors, but sliders should only have one.\n\t*/\n\tIsColorized = 0;\n}\n\n\n/***********************************************************************************************\n * SliderClass::~SliderClass -- Destructor for slider object.                                  *\n *                                                                                             *\n *    This cleans up the slider object in preparation for deletion.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvirtual SliderClass::~SliderClass(void)\n{\n\tif (PlusGadget) {\n\t\tdelete PlusGadget;\n\t\tPlusGadget = 0;\n\t}\n\tif (MinusGadget) {\n\t\tdelete MinusGadget;\n\t\tMinusGadget = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * SliderClass::Set_Maximum -- Sets the maximum value for this slider.                         *\n *                                                                                             *\n *    This sets the maximum value that the slider can be set at. The maximum value controls    *\n *    the size of the thumb and the resolution of the thumb's movement.                        *\n *                                                                                             *\n * INPUT:   value -- The value to set for the slider's maximum.                                *\n * OUTPUT:  bool; Was the maximum value changed? A false indicates a set to the value it       *\n *                is currently set to already.                                                 *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/15/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nint SliderClass::Set_Maximum(int value)\n{\n\tif (GaugeClass::Set_Maximum(value)) {\n\t\tRecalc_Thumb();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SliderClass::Set_Thumb_Size -- Sets the size of the thumb in \"slider units\".                *\n *                                                                                             *\n *    This routine will set the size of the thumb as it relates to the maximum value the       *\n *    slider can achieve. This serves to display a proportionally sized thumb as well as       *\n *    control how the slider \"bumps\" up or down.                                               *\n *                                                                                             *\n * INPUT:   value -- The new value of the thumb. It should never be larger than the slider     *\n *                   maximum.                                                                  *\n * OUTPUT:     none                                                                            *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/15/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nvoid SliderClass::Set_Thumb_Size(int value)\n{\n\tThumb = min(value, MaxValue);\n\tThumb = max(Thumb, 1);\n\tFlag_To_Redraw();\n\tRecalc_Thumb();\n}\n\n\n/***********************************************************************************************\n * SliderClass::Set_Value -- Sets the current thumb position for the slider.                   *\n *                                                                                             *\n *    This routine will set the thumb position for the slider.                                 *\n *                                                                                             *\n * INPUT:   value -- The position to set the slider. This position is relative to the maximum  *\n *                   value for the slider.                                                     *\n *                                                                                             *\n * OUTPUT:  bool; Was the slider thumb position changed at all?                                *\n * WARNINGS:  none                                                                             *\n * HISTORY:   01/15/1995 JLB : Created.                                                        *\n *=============================================================================================*/\nint SliderClass::Set_Value(int value)\n{\n\tvalue = min(value, MaxValue-Thumb);\n\n\tif (GaugeClass::Set_Value(value)) {\n\t\tRecalc_Thumb();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SliderClass::Recalc_Thumb -- Recalculates the thumb pixel size and starting offset.         *\n *                                                                                             *\n *    This takes the current thumb logical size and starting value and calculates the pixel    *\n *    size and starting offset accordingly. This function should be called whenever one of     *\n *    these elements has changed.                                                              *\n *                                                                                             *\n * INPUT:      none                                                                            *\n * OUTPUT:     none                                                                            *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/15/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nvoid SliderClass::Recalc_Thumb(void)\n{\n\tint length = IsHorizontal ? Width : Height;\n\tint size   = length * fixed(Thumb, MaxValue);\n//\tint size   = Fixed_To_Cardinal(length, Cardinal_To_Fixed(MaxValue, Thumb));\n\tThumbSize  = max(size, 4);\n\tint start  = length * fixed(CurValue, MaxValue);\n//\tint start  = Fixed_To_Cardinal(length, Cardinal_To_Fixed(MaxValue, CurValue));\n\tThumbStart = min(start, length-ThumbSize);\n}\n\n\n/***********************************************************************************************\n * SliderClass::Action -- Handles input processing for the slider.                             *\n *                                                                                             *\n *    This routine is called when a qualifying input event has occurred. This routine will     *\n *    process that event and make any adjustments to the slider as necessary.                  *\n *                                                                                             *\n * INPUT:   flags -- Flag bits that tell the input event that caused this function to          *\n *                   be called.                                                                *\n *          key   -- Reference to the key that caused the input event.                         *\n * OUTPUT:  bool; Was the event consumed and further processing of the gadget list should be   *\n *                aborted?                                                                     *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/15/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nint SliderClass::Action(unsigned flags, KeyNumType &key)\n{\n\t/*\n\t**\tHandle the mouse click in a special way. If the click was not on the thumb, then\n\t**\tjump the thumb position one \"step\" in the appropriate direction. Otherwise, let normal\n\t**\tprocessing take place -- the slider then \"sticks\" and the thumb moves according to\n\t**\tmouse position.\n\t*/\n\tif (flags & LEFTPRESS) {\n\t\tint mouse;\t\t// Mouse pixel position.\n\t\tint edge;\t\t// Edge of slider.\n\n\t\tif (IsHorizontal) {\n\t\t\tmouse = Get_Mouse_X();\n\t\t\tedge = X;\n\t\t} else {\n\t\t\tmouse = Get_Mouse_Y();\n\t\t\tedge = Y;\n\t\t}\n\t\tedge += 1;\n\n\t\t/*\n\t\t** Clicking outside the thumb: invoke parent's Action to process flags etc,\n\t\t** but turn off the event & return true so processing stops at this button.\n\t\t*/\n\t\tif (mouse < edge+ThumbStart) {\n\t\t\tBump(true);\n\t\t\tGaugeClass::Action(0, key);\n\t\t\tkey = KN_NONE;\n\t\t\treturn(true);\n\t\t} else {\n\t\t\tif (mouse > edge+ThumbStart+ThumbSize) {\n\t\t\t\tBump(false);\n\t\t\t\tGaugeClass::Action(0, key);\n\t\t\t\tkey = KN_NONE;\n\t\t\t\treturn(true);\n\t\t\t} else {\n\t\t\t\tGaugeClass::Action(flags, key);\n\t\t\t\tkey = KN_NONE;\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**  CHANGE GAUGECLASS::ACTION -- REMOVE (LEFTRELEASE) FROM IF STMT\n\t*/\n\treturn(GaugeClass::Action(flags, key));\n}\n\n\n/***********************************************************************************************\n * SliderClass::Bump -- Bumps the slider one \"thumb size\" up or down.                          *\n *                                                                                             *\n *    This support function will bump the slider one \"step\" or the size of the thumb up or     *\n *    down as specified. It is typically called when the slider is clicked outside of the      *\n *    thumb region but still inside of the slider.                                             *\n *                                                                                             *\n * INPUT:   up -- Should the bump be to increase the current position?                         *\n * OUTPUT:  bool; Was the slider changed at all? A false indicates that the slider is already  *\n *                at one end or the other.                                                     *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/15/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nint SliderClass::Bump(int up)\n{\n\tif (up) {\n\t\treturn(Set_Value(CurValue - Thumb));\n\t}\n\treturn(Set_Value(CurValue + Thumb));\n}\n\n\n/***********************************************************************************************\n * SliderClass::Step -- Steps the slider one value up or down.                                 *\n *                                                                                             *\n *    This routine will move the slider thumb one step in the direction specified.             *\n *                                                                                             *\n * INPUT:   up -- Should the step be up (i.e., forward)?                                       *\n * OUTPUT:  bool; Was the slider changed at all? A false indicates that the slider is already  *\n *                at one end or the other.                                                     *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/15/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nint SliderClass::Step(int up)\n{\n\tif (up) {\n\t\treturn(Set_Value(CurValue - 1));\n\t}\n\treturn(Set_Value(CurValue + 1));\n}\n\n\n/***********************************************************************************************\n * SliderClass::Draw_Thumb -- Draws the \"thumb\" for this slider.                               *\n *                                                                                             *\n *    This will draw the thumb graphic for this slider. Sometimes the thumb requires special   *\n *    drawing, thus the need for this function separate from the normal Draw_Me function.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n * OUTPUT:  none                                                                               *\n * WARNINGS:   The mouse is guaranteed to be hidden when this routine is called.               *\n * HISTORY:    01/16/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nvoid SliderClass::Draw_Thumb(void)\n{\n\tif (IsHorizontal) {\n\t\tDraw_Box(X+ThumbStart, Y, ThumbSize, Height, BOXSTYLE_RAISED, true);\n\t} else {\n\t\tDraw_Box(X, Y+ThumbStart, Width, ThumbSize, BOXSTYLE_RAISED, true);\n\t}\n}\n\n\n/***********************************************************************************************\n * SliderClass::Draw_Me -- Draws the body of the gauge.                                        *\n *                                                                                             *\n *    This routine will draw the body of the gauge if necessary.                               *\n *                                                                                             *\n * INPUT:   forced   -- Should the gauge be redrawn regardless of the current redraw flag?     *\n * OUTPUT:  bool; Was the gauge redrawn?                                                       *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/16/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nint SliderClass::Draw_Me(int forced)\n{\n\tif (BelongToList) {\n\t\tif (ControlClass::Draw_Me(forced)) {\n\n\t\t\t/*\n\t\t\t**\tHide the mouse.\n\t\t\t*/\n\t\t\tif (LogicPage == &SeenBuff) {\n\t\t\t\tConditional_Hide_Mouse(X, Y, X+Width, Y+Height);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDraw the body & set text color.\n\t\t\t*/\n\t\t\tDraw_Box (X, Y, Width, Height, BOXSTYLE_DOWN, true);\n\t\t\tDraw_Thumb();\n\n\t\t\t/*\n\t\t\t**\tDisplay the mouse.\n\t\t\t*/\n\t\t\tif (LogicPage == &SeenBuff) {\n\t\t\t\tConditional_Show_Mouse();\n\t\t\t}\n\t\t\treturn(true);\n\t\t}\n\t}\n\n\t/*\n\t**\tIf it does not belong to a listbox...\n\t*/\n\treturn(GaugeClass::Draw_Me(forced));\n}\n\n\n/***********************************************************************************************\n * SliderClass::Peer_To_Peer -- A peer gadget was touched -- make adjustments.                 *\n *                                                                                             *\n *    This routine is called when one of the peer gadgets (the scroll arrows or the slider)    *\n *    was touched in some fashion. This routine will sort out whom and why and then make       *\n *    any necessary adjustments to the list box.                                               *\n *                                                                                             *\n * INPUT:   flags    -- The event flags that affected the peer gadget.                         *\n *          key      -- The key value at the time of the event.                                *\n *          whom     -- Which gadget is being touched.                                         *\n * OUTPUT:  none                                                                               *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/16/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nvoid SliderClass::Peer_To_Peer(unsigned flags, KeyNumType & , ControlClass & whom)\n{\n\tif (flags & LEFTRELEASE) {\n\t\tif (&whom == PlusGadget) {\n\t\t\tStep(false);\n\t\t}\n\t\tif (&whom == MinusGadget) {\n\t\t\tStep(true);\n\t\t}\n\t}\n}\n\n\n"
  },
  {
    "path": "CODE/SLIDER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SLIDER.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SLIDER.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SLIDER_H\n#define SLIDER_H\n\n#include \"gauge.h\"\n#include \"shapebtn.h\"\n\n\n/***************************************************************************\n * SliderClass -- Like a Windows ListBox structure\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:      int id-- id of gadget\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint x -- x position of gadget\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint y -- y position of gadget\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint w -- width of gadget\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint h -- height of gadget\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint belong_to_list -- does this slider go with a listclass? *\n *                                                                         *\n * OUTPUT:     none.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t*\n * HISTORY:    01/03/1995 MML : Created.                                   *\n *=========================================================================*/\nclass SliderClass : public GaugeClass\n{\n\tpublic:\n\t\tSliderClass(unsigned id, int x, int y, int w, int h, int belong_to_list=false);\n\t\tvirtual ~SliderClass(void);\n\n\t\tvirtual void Set_Thumb_Size(int value);\n\t\tvirtual int  Set_Maximum(int value);\n\t\tvirtual int  Set_Value(int);\n\t\tvirtual int  Bump(int up);\n\t\tvirtual int  Step(int up);\n\t\tvirtual int  Draw_Me(int forced);\n\t\tvirtual void Peer_To_Peer(unsigned flags, KeyNumType & key, ControlClass & whom);\n\n\t\tvirtual int Thumb_Pixels(void) { return (ThumbSize);}\n\n\tprotected:\n\n\t\t/*\n\t\t**\tIf the slider bar has been created, these point to the respective gadgets\n\t\t**\tthat it is composed of.\n\t\t*/\n\t\tShapeButtonClass * PlusGadget;\n\t\tShapeButtonClass * MinusGadget;\n\n\t\t/*\n\t\t**\tIf I belong to a listbox, I have to draw myself differently...\n\t\t**/\n\t\tunsigned BelongToList:1;\n\n\t\t/*\n\t\t**\tThis is the logical size of the thumb. This value is used when drawing\n\t\t**\tthe thumb imagery. It is also the amount that is bumped when the\n\t\t**\tBump() function is called.  (This value is in application units.)\n\t\t*/\n\t\tint Thumb;\n\n\t\t/*\n\t\t**\tThis is the current thumb pixel size and starting offset from beginning\n\t\t**\tof slider region.  (These values are in pixels.)\n\t\t*/\n\t\tint ThumbSize;\n\t\tint ThumbStart;\t\t\t// x or y position for the thumb\n\n\t\tvirtual int  Action(unsigned flags, KeyNumType &key);\n\t\tvirtual void Draw_Thumb(void);\n\n\tprivate:\n\t\tvoid Recalc_Thumb(void);\n};\n\n#endif\n"
  },
  {
    "path": "CODE/SMUDGE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SMUDGE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SMUDGE.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 9, 1994                                               *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SmudgeClass::Disown -- Disowns (removes) a building bib piece.                            *\n *   SmudgeClass::Init -- Initialize the smudge tracking system.                               *\n *   SmudgeClass::Mark -- Marks a smudge down on the map.                                      *\n *   SmudgeClass::Read_INI -- Reads smudge data from an INI file.                              *\n *   SmudgeClass::SmudgeClass -- Constructor for smudge objects.                               *\n *   SmudgeClass::Write_INI -- Store all the smudge data to the INI database.                  *\n *   SmudgeClass::operator delete -- Deletes the smudge from the tracking system.              *\n *   SmudgeClass::operator new -- Creator of smudge objects.                                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"smudge.h\"\n\n\n\nHousesType SmudgeClass::ToOwn = HOUSE_NONE;\n\n\n/***********************************************************************************************\n * SmudgeClass::operator new -- Creator of smudge objects.                                     *\n *                                                                                             *\n *    This routine will allocate a smudge object from the smudge tracking pool.                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a newly allocated smudge object. If one couldn't be      *\n *          found, then NULL is returned.                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * SmudgeClass::operator new(size_t )\n{\n\tvoid * ptr = Smudges.Allocate();\n\tif (ptr != NULL) {\n\t\t((SmudgeClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * SmudgeClass::operator delete -- Deletes the smudge from the tracking system.                *\n *                                                                                             *\n *    This routine is used to remove the smudge from the tracking system.                      *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the smudge to delete.                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeClass::operator delete(void * ptr)\n{\n\tif (ptr != NULL) {\n\t\t((SmudgeClass *)ptr)->IsActive = false;\n\t}\n\tSmudges.Free((SmudgeClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * SmudgeClass::SmudgeClass -- Constructor for smudge objects.                                 *\n *                                                                                             *\n *    This is the typical constructor for smudge objects. If the position to place the         *\n *    smudge is not given, then the smudge will be initialized in a limbo state. If the        *\n *    smudge is placed on the map, then this operation causes the smudge object itself to be   *\n *    deleted and special map values updated to reflect the presence of a smudge.              *\n *                                                                                             *\n * INPUT:   type  -- The type of smudge to construct.                                          *\n *                                                                                             *\n *          pos   -- The position to place the smudge. If -1, then the smudge is initialized   *\n *                   into a limbo state.                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nSmudgeClass::SmudgeClass(SmudgeType type, COORDINATE pos, HousesType house) :\n\tObjectClass(RTTI_SMUDGE, Smudges.ID(this)),\n\tClass(SmudgeTypes.Ptr((int)type))\n{\n\tif (pos != -1) {\n\t\tToOwn = house;\n\t\tif (!Unlimbo(pos)) {\n\t\t\tdelete this;\n\t\t} else {\n\t\t\tToOwn = HOUSE_NONE;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * SmudgeClass::Init -- Initialize the smudge tracking system.                                 *\n *                                                                                             *\n *    This routine is used during the scenario clearing process to initialize the smudge       *\n *    object tracking system to a null state.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeClass::Init(void)\n{\n\tSmudges.Free_All();\n}\n\n\n/***********************************************************************************************\n * SmudgeClass::Mark -- Marks a smudge down on the map.                                        *\n *                                                                                             *\n *    This routine will place the smudge on the map. If the map cell allows.                   *\n *                                                                                             *\n * INPUT:   mark  -- The type of marking to perform. Only MARK_DOWN is supported.              *\n *                                                                                             *\n * OUTPUT:  bool; Was the smudge marked successfully? Failure occurs if the smudge isn't       *\n *                marked DOWN.                                                                 *\n *                                                                                             *\n * WARNINGS:   The smudge object is DELETED by this routine.                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1994 JLB : Created.                                                                 *\n *   12/23/1994 JLB : Checks low level legality before proceeding.                             *\n *=============================================================================================*/\nbool SmudgeClass::Mark(MarkType mark)\n{\n\tassert(Smudges.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (ObjectClass::Mark(mark)) {\n\t\tif (mark == MARK_DOWN) {\n\t\t\tCELL origin = Coord_Cell(Coord);\n\n\t\t\tfor (int w = 0; w < Class->Width; w++) {\n\t\t\t\tfor (int h = 0; h < Class->Height; h++) {\n\t\t\t\t\tCELL newcell = origin + w + (h*MAP_CELL_W);\n\t\t\t\t\tif (Map.In_Radar(newcell)) {\n\t\t\t\t\t\tCellClass * cell = &Map[newcell];\n\n\t\t\t\t\t\tif (Class->IsBib) {\n\t\t\t\t\t\t\tcell->Smudge = Class->Type;\n\t\t\t\t\t\t\tcell->SmudgeData = w + (h*Class->Width);\n\t\t\t\t\t\t\tcell->Owner = ToOwn;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (cell->Is_Clear_To_Move(SPEED_TRACK, true, true)) {\n\t\t\t\t\t\t\t\tif (Class->IsCrater && cell->Smudge != SMUDGE_NONE && SmudgeTypeClass::As_Reference(cell->Smudge).IsCrater) {\n\t\t\t\t\t\t\t\t\tcell->SmudgeData++;\n\t\t\t\t\t\t\t\t\tcell->SmudgeData = (int)min((int)cell->SmudgeData, (int)4);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (cell->Smudge == SMUDGE_NONE) {\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t**\tSpecial selection of a crater that starts as close to the\n\t\t\t\t\t\t\t\t\t**\tspecified coordinate as possible.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tif (Class->IsCrater) {\n\t\t\t\t\t\t\t\t\t\tcell->Smudge = (SmudgeType)(SMUDGE_CRATER1 + CellClass::Spot_Index(Coord));\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tcell->Smudge = Class->Type;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tcell->SmudgeData = 0;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tFlag everything that might be overlapping this cell to redraw itself.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcell->Redraw_Objects();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tWhether it was successful in placing, or not, delete the smudge object. It isn't\n\t\t\t**\tneeded once the map has been updated with the proper smudge data. Fake this object\n\t\t\t**\tas if it were never placed down!\n\t\t\t*/\n\t\t\tMap.Overlap_Up(Coord_Cell(Coord), this);\n\t\t\tIsDown = false;\n\t\t\tIsInLimbo = true;\n\t\t\tdelete this;\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SmudgeClass::Disown -- Disowns (removes) a building bib piece.                              *\n *                                                                                             *\n *    This routine is used when a building is removed from the game. If there was any bib      *\n *    attached, this routine will be called to disown the cells and remove the bib artwork.    *\n *                                                                                             *\n * INPUT:   cell  -- The origin cell for this bib removal.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This is actually working on a temporary bib object. It is created for the sole  *\n *             purpose of calling this routine. It will be deleted immediately afterward.      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeClass::Disown(CELL cell)\n{\n\tassert(Smudges.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsBib) {\n\t\tfor (int w = 0; w < Class->Width; w++) {\n\t\t\tfor (int h = 0; h < Class->Height; h++) {\n\t\t\t\tCellClass & cellptr = Map[(CELL)(cell + w + (h*MAP_CELL_W))];\n\n\t\t\t\tif (cellptr.Overlay == OVERLAY_NONE || !OverlayTypeClass::As_Reference(cellptr.Overlay).IsWall) {\n\t\t\t\t\tcellptr.Smudge = SMUDGE_NONE;\n\t\t\t\t\tcellptr.SmudgeData = 0;\n\t\t\t\t\tif (!cellptr.IsFlagged) {\n\t\t\t\t\t\tcellptr.Owner = HOUSE_NONE;\n\t\t\t\t\t}\n\t\t\t\t\tcellptr.Redraw_Objects();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * SmudgeClass::Read_INI -- Reads smudge data from an INI file.                                *\n *                                                                                             *\n *    This routine is used by the scenario loader to read the smudge data in an INI file and   *\n *    create the appropriate smudge objects on the map.                                        *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the INI file staging buffer.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *   07/24/1995 JLB : Sets the smudge data value as well.                                      *\n *=============================================================================================*/\nvoid SmudgeClass::Read_INI(CCINIClass & ini)\n{\n\tchar\tbuf[128];\t// Working string staging buffer.\n\n\tint len = ini.Entry_Count(INI_Name());\n\tfor (int index = 0; index < len; index++) {\n\t\tchar const * entry = ini.Get_Entry(INI_Name(), index);\n\t\tSmudgeType\tsmudge;\t\t// Smudge type.\n\n\t\tini.Get_String(INI_Name(), entry, NULL, buf, sizeof(buf));\n\t\tsmudge = SmudgeTypeClass::From_Name(strtok(buf, \",\"));\n\t\tif (smudge != SMUDGE_NONE) {\n\t\t\tchar * ptr = strtok(NULL, \",\");\n\t\t\tif (ptr != NULL) {\n\t\t\t\tint data = 0;\n\t\t\t\tCELL cell = atoi(ptr);\n\t\t\t\tptr = strtok(NULL, \",\");\n\t\t\t\tif (ptr != NULL) data = atoi(ptr);\n\t\t\t\tnew SmudgeClass(smudge, Cell_Coord(cell));\n\t\t\t\tif (Map[cell].Smudge == smudge && data != 0) {\n\t\t\t\t\tMap[cell].SmudgeData = data;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * SmudgeClass::Write_INI -- Store all the smudge data to the INI database.                    *\n *                                                                                             *\n *    This routine will output all the smudge data to the INI database.                        *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database object.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeClass::Write_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tFirst, clear out all existing template data from the ini file.\n\t*/\n\tini.Clear(INI_Name());\n\n\t/*\n\t**\tFind all templates and write them to the file.\n\t*/\n\tfor (CELL index = 0; index < MAP_CELL_TOTAL; index++) {\n\t\tCellClass * ptr;\n\n\t\tptr = &Map[index];\n\t\tif (ptr->Smudge != SMUDGE_NONE) {\n\t\t\tSmudgeTypeClass const * stype = &SmudgeTypeClass::As_Reference(ptr->Smudge);\n\t\t\tif (!stype->IsBib) {\n\t\t\t\tchar\tuname[10];\n\t\t\t\tchar\tbuf[127];\n\n\t\t\t\tsprintf(uname, \"%d\", index);\n\t\t\t\tsprintf(buf, \"%s,%d,%d\", stype->IniName, index, ptr->SmudgeData);\n\t\t\t\tini.Put_String(INI_Name(), uname, buf);\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "CODE/SMUDGE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SMUDGE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SMUDGE.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 9, 1994                                               *\n *                                                                                             *\n *                  Last Update : August 9, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SMUDGE_H\n#define SMUDGE_H\n\n#include\t\"object.h\"\n#include\t\"type.h\"\n\n\n/******************************************************************************\n**\tThis is the transitory form for smudges. They exist as independent objects\n**\tonly in the transition stage from creation to placement upon the map. Once\n**\tthey are placed on the map, they merely become 'smudges' in the cell data. This\n**\tobject is then destroyed.\n*/\nclass SmudgeClass : public ObjectClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis is a pointer to the template object's class.\n\t\t*/\n\t\tCCPtr<SmudgeTypeClass> Class;\n\n\t\t/*-------------------------------------------------------------------\n\t\t**\tConstructors and destructors.\n\t\t*/\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\t\tSmudgeClass(SmudgeType type, COORDINATE pos=0xFFFFFFFFUL, HousesType house = HOUSE_NONE);\n\t\tSmudgeClass(NoInitClass const & x) : ObjectClass(x), Class(x) {};\n\t\toperator SmudgeType(void) const {return Class->Type;};\n\t\tvirtual ~SmudgeClass(void) {if (GameActive) SmudgeClass::Limbo();Class=0;};\n\n\t\tstatic void Init(void);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tstatic void Read_INI(CCINIClass & ini);\n\t\tstatic void Write_INI(CCINIClass & ini);\n\t\tstatic char *INI_Name(void) {return \"SMUDGE\";};\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const {return *Class;};\n\t\tvirtual bool Mark(MarkType);\n\t\tvirtual void Draw_It(int , int , WindowNumberType ) const {};\n\n\t\tvoid Disown(CELL cell);\n\n\tprivate:\n\n\t\tstatic HousesType ToOwn;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/SOUNDDLG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SOUNDDLG.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SOUNDDLG.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready-Legg, Joe L. Bostic                   *\n *                                                                                             *\n *                   Start Date : Jan 8, 1995                                                  *\n *                                                                                             *\n *                  Last Update : September 22, 1995 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   MusicListClass::Draw_Entry -- Draw the score line in a list box.                          *\n *   SoundControlsClass::Process -- Handles all the options graphic interface.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"sounddlg.h\"\n\nclass MusicListClass : public ListClass\n{\n\tpublic:\n\t\tMusicListClass(int id, int x, int y, int w, int h) :\n\t\t\tListClass(id, x, y, w, h, TPF_6PT_GRAD|TPF_NOSHADOW, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"))\n\t\t{};\n\t\tvirtual ~MusicListClass(void) {};\n\n\tprotected:\n\t\tvirtual void Draw_Entry(int index, int x, int y, int width, int selected);\n};\n\n\n/***********************************************************************************************\n * SoundControlsClass::Process -- Handles all the options graphic interface.                   *\n *                                                                                             *\n *    This routine is the main control for the visual representation of the options            *\n *    screen. It handles the visual overlay and the player input.                              *\n *                                                                                             *\n * INPUT:      none                                                                            *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:    12/31/1994 MML : Created.                                                       *\n *=============================================================================================*/\nvoid SoundControlsClass::Process(void)\n{\n\n\t/*\n\t** Adjust dialog controls for resolution\n\t*/\n\tint option_width=   \tOPTION_WIDTH * RESFACTOR;\n\tint option_height=  \tOPTION_HEIGHT * RESFACTOR;\n\n\tint option_x=       \tOPTION_X * RESFACTOR;\n\tint option_y=       \tOPTION_Y * RESFACTOR;\n\n\tint listbox_x=      \tLISTBOX_X * RESFACTOR;\n\tint listbox_y=      \tLISTBOX_Y * RESFACTOR;\n\tint listbox_w=      \tLISTBOX_W * RESFACTOR;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n#ifdef WIN32\n\tint listbox_h=      \t(LISTBOX_H * RESFACTOR)+2;\n#else\n\tint listbox_h=      \tLISTBOX_H * RESFACTOR;\n#endif\n#else\n\tint listbox_h=      \tLISTBOX_H * RESFACTOR;\n#endif\n\n\tint button_width=   \tBUTTON_WIDTH * RESFACTOR;\n\tint button_x=       \tBUTTON_X * RESFACTOR;\n\tint button_y=       \tBUTTON_Y * RESFACTOR;\n\n\tint stop_x=         \tSTOP_X * RESFACTOR;\n\tint stop_y=         \tSTOP_Y * RESFACTOR;\n\n\tint play_x=         \tPLAY_X * RESFACTOR;\n\tint play_y=         \tPLAY_Y * RESFACTOR;\n\n\tint onoff_width=    \tONOFF_WIDTH * RESFACTOR;\n\tint shuffle_x=      \tSHUFFLE_X * RESFACTOR;\n\tint shuffle_y=      \tSHUFFLE_Y * RESFACTOR;\n\tint repeat_x=       \tREPEAT_X * RESFACTOR;\n\tint repeat_y=       \tREPEAT_Y * RESFACTOR;\n\n\tint mslider_x=      \tMSLIDER_X * RESFACTOR;\n\tint mslider_y=      \tMSLIDER_Y * RESFACTOR;\n\tint mslider_w=      \tMSLIDER_W * RESFACTOR;\n\tint mslider_height= \tMSLIDER_HEIGHT * RESFACTOR;\n\n\tint fxslider_x=     \tFXSLIDER_X * RESFACTOR;\n\tint fxslider_y=     \tFXSLIDER_Y * RESFACTOR;\n\tint fxslider_w=     \tFXSLIDER_W * RESFACTOR;\n\tint fxslider_height=\tFXSLIDER_HEIGHT * RESFACTOR;\n\n\tint button_stop=    \tBUTTON_STOP;\n\tint button_play=    \tBUTTON_PLAY;\n\tint button_shuffle= \tBUTTON_SHUFFLE;\n\tint button_repeat=  \tBUTTON_REPEAT;\n\tint button_options= \tBUTTON_OPTIONS;\n\tint slider_music=   \tSLIDER_MUSIC;\n\tint slider_sound=   \tSLIDER_SOUND;\n\tint button_listbox= \tBUTTON_LISTBOX;\n\n\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n//\tThemeType theme;\n\n\t/*\n\t**\tList box that holds the score text strings.\n\t*/\n\tMusicListClass listbox(0, option_x+listbox_x, option_y+listbox_y, listbox_w, listbox_h);\n\n\t/*\n\t**\tReturn to options menu button.\n\t*/\n\tTextButtonClass returnto(BUTTON_OPTIONS, TXT_OK, TPF_BUTTON, option_x+button_x, option_y+button_y, button_width);\n//\tTextButtonClass returnto(BUTTON_OPTIONS, TXT_OPTIONS_MENU, TPF_BUTTON,\n\n\t/*\n\t**\tStop playing button.\n\t*/\n\tShapeButtonClass stopbtn(BUTTON_STOP, MFCD::Retrieve(\"BTN-ST.SHP\"), option_x+stop_x, option_y+stop_y);\n\n\t/*\n\t**\tStart playing button.\n\t*/\n\tShapeButtonClass playbtn(BUTTON_PLAY, MFCD::Retrieve(\"BTN-PL.SHP\"), option_x+play_x, option_y+play_y);\n\n\t/*\n\t**\tShuffle control.\n\t*/\n\tTextButtonClass shufflebtn(BUTTON_SHUFFLE, TXT_OFF, TPF_BUTTON, option_x+shuffle_x, option_y+shuffle_y, onoff_width);\n//\tTextButtonClass shufflebtn(BUTTON_SHUFFLE, TXT_OFF, TPF_BUTTON, option_x+shuffle_x, option_y+shuffle_y, ONOFF_WIDTH);\n\n\t/*\n\t**\tRepeat control.\n\t*/\n\tTextButtonClass repeatbtn(BUTTON_REPEAT, TXT_OFF, TPF_BUTTON, option_x+repeat_x, option_y+repeat_y, onoff_width);\n\n\t/*\n\t**\tMusic volume slider.\n\t*/\n\tSliderClass music(SLIDER_MUSIC, option_x+mslider_x, option_y+mslider_y, mslider_w, mslider_height, true);\n\n\t/*\n\t**\tSound volume slider.\n\t*/\n\tSliderClass sound(SLIDER_SOUND, option_x+fxslider_x, option_y+fxslider_y, fxslider_w, fxslider_height, true);\n\n\t/*\n\t**\tCauses left mouse clicks inside the dialog area, but not on any\n\t**\tparticular button, to be ignored.\n\t*/\n\tGadgetClass area(option_x, option_y, option_width, option_height, GadgetClass::LEFTPRESS);\n\n\t/*\n\t**\tCauses right clicks anywhere or left clicks outside of the dialog\n\t**\tbox area to be the same a clicking the return to game options button.\n\t*/\n\tControlClass ctrl(BUTTON_OPTIONS, 0, 0, SeenBuff.Get_Width(), SeenBuff.Get_Height(), GadgetClass::RIGHTPRESS|GadgetClass::LEFTPRESS);\n\n\t/*\n\t**\tThe repeat and shuffle buttons are of the toggle type. They toggle\n\t**\tbetween saying \"on\" and \"off\".\n\t*/\n\tshufflebtn.IsToggleType = true;\n\tif (Options.IsScoreShuffle) {\n\t\tshufflebtn.Turn_On();\n\t} else {\n\t\tshufflebtn.Turn_Off();\n\t}\n\tshufflebtn.Set_Text(shufflebtn.IsOn ? TXT_ON : TXT_OFF);\n\n\trepeatbtn.IsToggleType = true;\n\tif (Options.IsScoreRepeat) {\n\t\trepeatbtn.Turn_On();\n\t} else {\n\t\trepeatbtn.Turn_Off();\n\t}\n\trepeatbtn.Set_Text(repeatbtn.IsOn ? TXT_ON : TXT_OFF);\n\n\t/*\n\t**\tSet the initial values of the sliders.\n\t*/\n\tmusic.Set_Maximum(255);\n\tmusic.Set_Thumb_Size(16);\n\tmusic.Set_Value(Options.ScoreVolume * 256);\n\tsound.Set_Maximum(255);\n\tsound.Set_Thumb_Size(16);\n\tsound.Set_Value(Options.Volume * 256);\n\n\t/*\n\t**\tSet up the window.  Window x-coords are in bytes not pixels.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tCreate Buttons.\n\t*/\n\tGadgetClass * optionsbtn = &returnto;\n\tlistbox.Add_Tail(*optionsbtn);\n\tstopbtn.Add_Tail(*optionsbtn);\n\tplaybtn.Add_Tail(*optionsbtn);\n\tshufflebtn.Add_Tail(*optionsbtn);\n\trepeatbtn.Add_Tail(*optionsbtn);\n\tmusic.Add_Tail(*optionsbtn);\n\tsound.Add_Tail(*optionsbtn);\n\tarea.Add_Tail(*optionsbtn);\n\tctrl.Add_Tail(*optionsbtn);\n\n\t/*\n\t**\tAdd all the themes to the list box. The list box entries are constructed\n\t**\tand then stored into allocated EMS memory blocks.\n\t*/\n\tfor (ThemeType index = THEME_FIRST; index < Theme.Max_Themes(); index++) {\n\t\tif (Theme.Is_Allowed(index)) {\n\t\t\tchar buffer[100];\n\t\t\tint length = Theme.Track_Length(index);\n\t\t\tchar const * fullname = Theme.Full_Name(index);\n\n\t\t\tvoid * ptr = new char [sizeof(buffer)];\n\t\t\tif (ptr) {\n\t\t\t\tsprintf((char *)ptr, \"%cTrack %d\\t%d:%02d\\t%s\", index, listbox.Count()+1, length / 60, length % 60, fullname);\n\t\t\t\tlistbox.Add_Item((char const *)ptr);\n\t\t\t}\n\n\t\t\tif (Theme.What_Is_Playing() == index) {\n\t\t\t\tlistbox.Set_Selected_Index(listbox.Count()-1);\n\t\t\t}\n\t\t}\n\t}\n\tstatic int _tabs[] = {\n\t\t55 * RESFACTOR, 72 * RESFACTOR, 90 * RESFACTOR\n\t};\n\tlistbox.Set_Tabs(_tabs);\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tbool display = true;\n\tbool process = true;\n\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tif (Session.Type == GAME_NORMAL || Session.Type == GAME_SKIRMISH) {\n\t\t\tCall_Back();\n\t\t} else {\n\t\t\tif (Main_Loop()) {\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = true;\n\t\t}\n\t\t#endif\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t**\tDraw the background.\n\t\t\t*/\n\t\t\tDialog_Box(option_x, option_y, option_width, option_height);\n\n\t\t\tDraw_Caption(TXT_SOUND_CONTROLS, option_x, option_y, option_width);\n\n\t\t\t/*\n\t\t\t** Draw the Music, Speech & Sound titles.\n\t\t\t*/\n\t\t\tFancy_Text_Print(TXT_MUSIC_VOLUME, option_x+mslider_x-(5 * RESFACTOR), option_y+mslider_y-(2 * RESFACTOR), scheme, TBLACK, TPF_TEXT|TPF_RIGHT);\n\t\t\tFancy_Text_Print(TXT_SOUND_VOLUME, option_x+fxslider_x-(5 * RESFACTOR), option_y+fxslider_y-(2 * RESFACTOR), scheme, TBLACK, TPF_TEXT|TPF_RIGHT);\n\n#if defined(GERMAN) || defined(FRENCH)\n\t\t\tFancy_Text_Print(TXT_SHUFFLE, option_x+4+shuffle_x-(5 * RESFACTOR), option_y+shuffle_y+(1 * RESFACTOR), scheme, TBLACK, TPF_TEXT|TPF_RIGHT);\n#else\n\t\t\tFancy_Text_Print(TXT_SHUFFLE, option_x+shuffle_x-(5 * RESFACTOR), option_y+shuffle_y+(1 * RESFACTOR), scheme, TBLACK, TPF_TEXT|TPF_RIGHT);\n#endif\n\t\t\tFancy_Text_Print(TXT_REPEAT, option_x+repeat_x-(5 * RESFACTOR), option_y+repeat_y+(1 * RESFACTOR), scheme, TBLACK, TPF_TEXT|TPF_RIGHT);\n\n\t\t\toptionsbtn->Draw_All();\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tKeyNumType input = optionsbtn->Input();\n\n\t\t/*\n\t\t**\tProcess Input.\n\t\t*/\n\t\tswitch (input) {\n\n\t\t\tcase KN_ESC:\n\t\t\tcase BUTTON_OPTIONS|KN_BUTTON:\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tControl music volume.\n\t\t\t*/\n\t\t\tcase SLIDER_MUSIC|KN_BUTTON:\n\t\t\t\tOptions.Set_Score_Volume(fixed(music.Get_Value(), 256), true);\n#ifdef FIXIT_VERSION_3\n\t\t\t\tif( Session.Type != GAME_NORMAL )\n\t\t\t\t\tOptions.MultiScoreVolume = Options.ScoreVolume;\n#endif\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tControl sound volume.\n\t\t\t*/\n\t\t\tcase SLIDER_SOUND|KN_BUTTON:\n\t\t\t\tOptions.Set_Sound_Volume(fixed(sound.Get_Value(), 256), true);\n\t\t\t\tbreak;\n\n\t\t\tcase BUTTON_LISTBOX|KN_BUTTON:\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tStop all themes from playing.\n\t\t\t*/\n\t\t\tcase BUTTON_STOP|KN_BUTTON:\n\t\t\t\tTheme.Stop();\n\t\t\t\tTheme.Queue_Song(THEME_QUIET);\n//\t\t\t\tTheme.Queue_Song(THEME_NONE);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tStart the currently selected theme to play.\n\t\t\t*/\n\t\t\tcase KN_SPACE:\n\t\t\tcase BUTTON_PLAY|KN_BUTTON:\n\t\t\t\tTheme.Queue_Song( (ThemeType)*((unsigned char *)listbox.Current_Item()) );\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tToggle the shuffle button.\n\t\t\t*/\n\t\t\tcase BUTTON_SHUFFLE|KN_BUTTON:\n\t\t\t\tshufflebtn.Set_Text(shufflebtn.IsOn ? TXT_ON : TXT_OFF);\n\t\t\t\tOptions.Set_Shuffle(shufflebtn.IsOn);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tToggle the repeat button.\n\t\t\t*/\n\t\t\tcase BUTTON_REPEAT|KN_BUTTON:\n\t\t\t\trepeatbtn.Set_Text(repeatbtn.IsOn ? TXT_ON : TXT_OFF);\n\t\t\t\tOptions.Set_Repeat(repeatbtn.IsOn);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the score volume was turned all the way down, then actually\n\t**\tstop the scores from being played.\n\t*/\n\tif (Options.ScoreVolume == 0) {\n\t\tTheme.Stop();\n\t}\n\n\t/*\n\t**\tFree the items from the list box.\n\t*/\n\twhile (listbox.Count()) {\n\t\tchar const * ptr = listbox.Get_Item(0);\n\t\tlistbox.Remove_Item(ptr);\n\t\tdelete [] (void*)ptr;\n\t}\n}\n\n\n/***********************************************************************************************\n * MusicListClass::Draw_Entry -- Draw the score line in a list box.                            *\n *                                                                                             *\n *    This routine will display the score line in a list box. It overrides the list box        *\n *    handler for line drawing.                                                                *\n *                                                                                             *\n * INPUT:   index    -- The index within the list box that is being drawn.                     *\n *                                                                                             *\n *          x,y      -- The pixel coordinates of the upper left position of the line.          *\n *                                                                                             *\n *          width    -- The width of the line that drawing is allowed to use.                  *\n *                                                                                             *\n *          selected-- Is the current line selected?                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MusicListClass::Draw_Entry(int index, int x, int y, int width, int selected)\n{\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\tif (TextFlags & TPF_6PT_GRAD) {\n\t\tTextPrintType flags = TextFlags;\n\n\t\tif (selected) {\n\t\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\t\tLogicPage->Fill_Rect (x, y, x + width - 1, y + LineHeight - 1,\n\t\t\t\tGadgetClass::Get_Color_Scheme()->Shadow);\n\t\t} else {\n\t\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t\t}\n\t\t}\n\n\t\tConquer_Clip_Text_Print((char *)List[index] + 1, x, y, scheme, TBLACK, flags, width, Tabs);\n\n\t} else {\n\t\tConquer_Clip_Text_Print((char *)List[index] + 1, x, y,\n\t\t\t(selected ? &ColorRemaps[PCOLOR_DIALOG_BLUE] : &ColorRemaps[PCOLOR_GREY]), TBLACK, TextFlags, width, Tabs);\n\t}\n}\n"
  },
  {
    "path": "CODE/SOUNDDLG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SOUNDDLG.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OPTIONS.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 8, 1994                                                 *\n *                                                                                             *\n *                  Last Update : June 8, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SOUNDDLG_H\n#define SOUNDDLG_H\n\n#include \"gadget.h\"\n\nclass SoundControlsClass\n{\n\tenum SoundControlsClassEnums {\n#ifdef FRENCH\n\t\tOPTION_WIDTH=308,\n#else\n\t\tOPTION_WIDTH=292,\n#endif\n\t\tOPTION_HEIGHT=146,\n\n\t\tOPTION_X=((320 - OPTION_WIDTH) / 2),\n\t\tOPTION_Y=(200 - OPTION_HEIGHT) / 2,\n\n\t\tLISTBOX_X=17,\n\t\tLISTBOX_Y=54,\n\t\tLISTBOX_W=OPTION_WIDTH-(LISTBOX_X*2),\n\t\tLISTBOX_H=72,\n\n\t\tBUTTON_WIDTH=70,\n\t\tBUTTON_X=OPTION_WIDTH-(BUTTON_WIDTH+17),\t \t\t\t\t// Options button x pos\n\t\tBUTTON_Y=128, \t\t\t\t\t// Options button y pos\n\n\t\tSTOP_X=17,\t\t\t\t\t\t// Stop button X.\n\t\tSTOP_Y=128,\t\t\t\t\t\t//\tStop button Y.\n\n\t\tPLAY_X=35,\n\t\tPLAY_Y=128,\n\n\t\tONOFF_WIDTH=25,\n#ifdef GERMAN\n\t\tSHUFFLE_X=79,//BGA:91,\n#else\n#ifdef FRENCH\n\t\tSHUFFLE_X=99,\n#else\n\t\tSHUFFLE_X=97,\n#endif\n#endif\n\t\tSHUFFLE_Y=128,\n\n#ifdef FRENCH\n\t\tREPEAT_X=169,\n#else\n\t\tREPEAT_X=164,\n#endif\n\t\tREPEAT_Y=128,\n\n\t\tMSLIDER_X=147,\n\t\tMSLIDER_Y=28,\n\t\tMSLIDER_W=108,\n\t\tMSLIDER_HEIGHT=5,\n\n\t\tFXSLIDER_X=147,\n\t\tFXSLIDER_Y=40,\n\t\tFXSLIDER_W=108,\n\t\tFXSLIDER_HEIGHT=5,\n\n\t\tBUTTON_STOP = 605,\n\t\tBUTTON_PLAY,\n\t\tBUTTON_SHUFFLE,\n\t\tBUTTON_REPEAT,\n\t\tBUTTON_OPTIONS,\n\t\tSLIDER_MUSIC,\n\t\tSLIDER_SOUND,\n\t\tBUTTON_LISTBOX,\n\t};\n\n\tpublic:\n\t\tSoundControlsClass(void) {}\n\t\tvoid Process(void);\n};\n\n#endif\n"
  },
  {
    "path": "CODE/SPECIAL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SPECIAL.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SPECIAL.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/27/95                                                     *\n *                                                                                             *\n *                  Last Update : August 20, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Fetch_Difficulty -- Fetches the difficulty setting desired.                               *\n *   Fetch_Password -- Prompts for a password entry from client.                               *\n *   PWEditClass::Draw_Text -- Draws password style obscured text.                             *\n *   Special_Dialog -- Handles the special options dialog.                                     *\n *   SpecialClass::Init -- Initialize the special class of options.                            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n#ifdef WIN32\n#define\tOPTION_WIDTH\t236*2\n#define\tOPTION_HEIGHT\t162*2\n#define\tOPTION_X\t\t\t((640 - OPTION_WIDTH) / 2)\n#define\tOPTION_Y\t\t\t(400 - OPTION_HEIGHT) / 2\n#else\n#define\tOPTION_WIDTH\t236\n#define\tOPTION_HEIGHT\t162\n#define\tOPTION_X\t\t\t((320 - OPTION_WIDTH) / 2)\n#define\tOPTION_Y\t\t\t(200 - OPTION_HEIGHT) / 2\n#endif\n\n\n/***********************************************************************************************\n * SpecialClass::Init -- Initialize the special class of options.                              *\n *                                                                                             *\n *    This initialization function is required (as opposed to using a constructor) because     *\n *    the SpecialClass is declared as part of a union. A union cannot have a member with a     *\n *    constructor. Other than this anomoly, the function serves the same purpose as a          *\n *    normal constructor.                                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SpecialClass::Init(void)\n{\n\tIsShadowGrow = false;\n\tIsSpeedBuild = false;\n\tIsFromInstall = false;\n\tIsCaptureTheFlag = false;\n\tIsInert = false;\n\tIsThreePoint = false;\n\tIsTGrowth = true;\n\tIsTSpread = true;\n}\n\n\n/***********************************************************************************************\n * Special_Dialog -- Handles the special options dialog.                                       *\n *                                                                                             *\n *    This dialog is used when setting the special game options. It does not appear in the     *\n *    final version of the game.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Special_Dialog(bool simple)\n{\n\tSpecialClass oldspecial = Special;\n\tGadgetClass * buttons = NULL;\n\tstatic struct {\n\t\tint Description;\n\t\tint Setting;\n\t\tCheckBoxClass * Button;\n\t} _options[] = {\n\t\t{TXT_THREE_POINT, 0, 0},\n\t\t{TXT_SPEED_BUILD, 0, 0},\n\t};\n\n\tTextButtonClass ok(200, TXT_OK, TPF_BUTTON, OPTION_X+15*RESFACTOR, OPTION_Y+OPTION_HEIGHT-15*RESFACTOR);\n\tTextButtonClass cancel(201, TXT_CANCEL, TPF_BUTTON, OPTION_X+OPTION_WIDTH-60*RESFACTOR, OPTION_Y+OPTION_HEIGHT-15*RESFACTOR);\n\tbuttons = &ok;\n\tcancel.Add(*buttons);\n\n\tfor (int index = 0; index < sizeof(_options)/sizeof(_options[0]); index++) {\n\t\t_options[index].Button = new CheckBoxClass(100+index, OPTION_X+17*RESFACTOR, OPTION_Y+20*RESFACTOR+(index*10*RESFACTOR));\n\t\tif (_options[index].Button) {\n\t\t\t_options[index].Button->Add(*buttons);\n\n\t\t\tbool value = false;\n\t\t\tswitch (_options[index].Description) {\n\t\t\t\tcase TXT_THREE_POINT:\n\t\t\t\t\tvalue = Special.IsThreePoint;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TXT_SPEED_BUILD:\n\t\t\t\t\tvalue = Special.IsSpeedBuild;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t_options[index].Setting = value;\n\t\t\tif (value) {\n\t\t\t\t_options[index].Button->Turn_On();\n\t\t\t} else {\n\t\t\t\t_options[index].Button->Turn_Off();\n\t\t\t}\n\t\t}\n\t}\n\n\tMap.Override_Mouse_Shape(MOUSE_NORMAL);\n\tSet_Logic_Page(SeenBuff);\n\tbool recalc = true;\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\tCall_Back();\n\t\t} else {\n\t\t\tif (Main_Loop()) {\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\tif (display) {\n\t\t\tdisplay = false;\n\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(OPTION_X, OPTION_Y, OPTION_WIDTH, OPTION_HEIGHT);\n\t\t\tDraw_Caption(TXT_SPECIAL_OPTIONS, OPTION_X, OPTION_Y, OPTION_WIDTH);\n\n\t\t\tfor (index = 0; index < sizeof(_options)/sizeof(_options[0]); index++) {\n\t\t\t\tFancy_Text_Print(_options[index].Description, _options[index].Button->X+10*RESFACTOR, _options[index].Button->Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\t\t\t}\n\t\t\tbuttons->Draw_All();\n\t\t\tShow_Mouse();\n\t\t}\n\n\t\tKeyNumType input = buttons->Input();\n\t\tswitch (input) {\n\t\t\tcase KN_ESC:\n\t\t\tcase 200|KN_BUTTON:\n\t\t\t\tprocess = false;\n\t\t\t\tfor (index = 0; index < sizeof(_options)/sizeof(_options[0]); index++) {\n\t\t\t\t\tbool setting = _options[index].Setting;\n\t\t\t\t\tswitch (_options[index].Description) {\n\t\t\t\t\t\tcase TXT_THREE_POINT:\n\t\t\t\t\t\t\toldspecial.IsThreePoint = setting;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TXT_SPEED_BUILD:\n\t\t\t\t\t\t\toldspecial.IsSpeedBuild = setting;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!simple) {\n\t\t\t\t\tOutList.Add(EventClass(oldspecial));\n\t\t\t\t} else {\n\t\t\t\t\tSpecial = oldspecial;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 201|KN_BUTTON:\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase KN_NONE:\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tindex = (input & ~KN_BUTTON) - 100;\n\t\t\t\tif ((unsigned)index < sizeof(_options)/sizeof(_options[0])) {\n\t\t\t\t\t_options[index].Setting = _options[index].Button->IsOn;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (!simple) {\n\t\tMap.Revert_Mouse_Shape();\n\t\tHidPage.Clear();\n\t\tMap.Flag_To_Redraw(true);\n\t\tMap.Render();\n\t}\n}\n\n\n/*\n**\tDerived from the edit class, this class allows entry of passwords style text\n**\tas an edit box. This style is characterized by \"*\" being displayed for every\n**\treal character entered.\n*/\nclass PWEditClass : public EditClass\n{\n\tpublic:\n\t\tPWEditClass(int id, char * text, int max_len, TextPrintType flags, int x, int y, int w=-1, int h=-1) :\n\t\t\tEditClass(id, text, max_len, flags, x, y, w, h, ALPHANUMERIC) {};\n\n\tprotected:\n\t\tvirtual void Draw_Text(char const * text);\n};\n\n\n/***********************************************************************************************\n * PWEditClass::Draw_Text -- Draws password style obscured text.                               *\n *                                                                                             *\n *    This routine is used by the password style edit box in order to display the entered      *\n *    text. The text will be displayed as asterisks instead of the actual characters the       *\n *    edit box may contain. This is necessary to obscure the password entry from glancing      *\n *    eyes.                                                                                    *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text that is to be rendered.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PWEditClass::Draw_Text(char const * text)\n{\n\tchar buffer[80];\n\n\tmemset(buffer, '\\0', sizeof(buffer));\n\tmemset(buffer, '*', strlen(text));\n\n\tif (FontPtr == GradFont6Ptr) {\n\t\tTextPrintType flags;\n\n\t\tif (Has_Focus()) {\n\t\t\tflags = TPF_BRIGHT_COLOR;\n\t\t} else {\n\t\t\tflags = (TextPrintType)0;\n\t\t}\n\n\t\tConquer_Clip_Text_Print(buffer, X+1, Y+1, Color, TBLACK, TextFlags | flags, Width-2);\n\n\t\tif (Has_Focus() && strlen(buffer) < MaxLength) {\n\t\t\tConquer_Clip_Text_Print( \"_\", X+1+String_Pixel_Width(buffer), Y+1, Color, TBLACK, TextFlags | flags);\n\t\t}\n\t} else {\n\t\tConquer_Clip_Text_Print(buffer, X+1, Y+1, Has_Focus() ?\n\t\t\t&ColorRemaps[PCOLOR_DIALOG_BLUE] : &ColorRemaps[PCOLOR_GREY],\n\t\t\tTBLACK, TextFlags, Width-2);\n\n\t\tif (Has_Focus() && strlen(buffer) < MaxLength) {\n\t\t\tConquer_Clip_Text_Print(\"_\", X+1+String_Pixel_Width(buffer), Y+1,\n\t\t\t\t&ColorRemaps[PCOLOR_DIALOG_BLUE], TBLACK, TextFlags);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Fetch_Password -- Prompts for a password entry from client.                                 *\n *                                                                                             *\n *    This routine will prompt for and return a password entry from the player.                *\n *                                                                                             *\n * INPUT:   caption  -- The  caption to use for the top of the prompt dialog.                  *\n *                                                                                             *\n *          message  -- The body of the message to display in the dialog.                      *\n *                                                                                             *\n *          btext    -- The button text to use to finish the dialog box entry.                 *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the password text entered. This pointer is valid         *\n *          only until the next time that this routine is called.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\n#define BUFFSIZE (511)\nchar const * Fetch_Password(int caption, int message, int btext)\n{\n\tchar buffer[BUFFSIZE];\n\tbool process;\t\t\t\t\t\t\t\t// loop while true\n\tKeyNumType input;\t\t\t\t\t\t\t// user input\n\tbool pressed;\n\tint curbutton;\n\tTextButtonClass ok;\n\n\tif (btext == TXT_NONE) btext = TXT_OK;\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW);\n\n\t/*\n\t**\tExamine the optional button parameters. Fetch the width and starting\n\t**\tcharacters for each.\n\t*/\n\tint bwidth, bheight;\t\t\t\t// button width and height\n\n\t/*\n\t**\tBuild the button list.\n\t*/\n\tbheight = FontHeight + FontYSpacing + 2*RESFACTOR;\n\tbwidth = max((String_Pixel_Width(Text_String(btext)) + 8*RESFACTOR), 30*RESFACTOR);\n\n\t/*\n\t**\tDetermine the dimensions of the text to be used for the dialog box.\n\t**\tThese dimensions will control how the dialog box looks.\n\t*/\n\tbuffer[BUFFSIZE-1] = 0;\n\tstrncpy(buffer, Text_String(message), BUFFSIZE-1);\n\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW);\n\tint width;\n\tint height;\n\tFormat_Window_String(buffer, 255, width, height);\n\n\twidth = max(width, 50*RESFACTOR);\n\twidth += 40*RESFACTOR;\n\theight += (60+25)*RESFACTOR;\n\n\tint x = (SeenBuff.Get_Width() - width) / 2;\n\tint y = (SeenBuff.Get_Height() - height) / 2;\n\n\t/*\n\t**\tCreate the \"ok\" and password edit buttons.\n\t*/\n\tTextButtonClass button1(1, btext, TPF_BUTTON,\n\t\tx + ((width - bwidth) >> 1), y + height - (bheight + 5*RESFACTOR), bwidth);\n\n\tstatic char pbuffer[45];\n\tmemset(pbuffer, '\\0', sizeof(pbuffer));\n\tint editx = x+26*RESFACTOR;\n\tint editwidth = (SeenBuff.Get_Width()/2 - editx) * 2;\n\tPWEditClass button2(2, &pbuffer[0], sizeof(pbuffer), TPF_6PT_GRAD|TPF_NOSHADOW, editx, (y+height)-35*RESFACTOR, editwidth, 10*RESFACTOR);\n\n\tTextButtonClass * buttonlist = 0;\n\tcurbutton = 0;\n\n\t/*\n\t**\tAdd and initialize the buttons to the button list.\n\t*/\n\tbuttonlist = &button1;\n\tbutton2.Add(*buttonlist);\n\n\t/*\n\t**\tDraw the background of the dialog.\n\t*/\n\tHide_Mouse();\n\tSet_Logic_Page(SeenBuff);\n\tDialog_Box(x, y, width, height);\n\tDraw_Caption(caption, x, y, width);\n\n\t/*\n\t**\tDraw the body of the message box.\n\t*/\n\tFancy_Text_Print(buffer, x + 20*RESFACTOR, y + 25*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\t/*\n\t**\tRedraw the buttons.\n\t*/\n\tif (buttonlist) {\n\t\tbuttonlist->Draw_All();\n\t}\n\tShow_Mouse();\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tprocess = true;\n\tpressed = false;\n\tbool first = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tCall_Back();\n\n#ifdef WIN32\n\t\t/*\n\t\t** Handle possible surface loss due to a focus switch\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tprocess = false;\n\t\t\tbreak;\n\t\t}\n#endif\t//WIN32\n\n\t\t/*\n\t\t**\tFetch and process input.\n\t\t*/\n\t\tinput = buttonlist->Input();\n\t\tif (first) {\n\t\t\tbutton2.Set_Focus();\n\t\t\tbutton2.Flag_To_Redraw();\n\t\t\tfirst = false;\n\t\t}\n\t\tswitch (input) {\n\t\t\tcase (1|BUTTON_FLAG):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase (2|BUTTON_FLAG):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn(pbuffer);\n}\n\n\n/***********************************************************************************************\n * Fetch_Difficulty -- Fetches the difficulty setting desired.                                 *\n *                                                                                             *\n *    This will display a dialog box that requests the player to specify a difficulty          *\n *    setting.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a difficulty setting of 0 for easiest and 4 for hardest.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nint Fetch_Difficulty(bool amath)\n#else\nint Fetch_Difficulty(void)\n#endif\n{\n\tint const w = 250 * RESFACTOR;\n\tint const h = 80 * RESFACTOR;\n\tint const x = ((320 * RESFACTOR)/2) - w/2;\n\tint const y = ((200 * RESFACTOR)/2) - h/2;\n\tint const bwidth = 30 * RESFACTOR;\n\n\t/*\n\t**\tFill the description buffer with the description text. Break\n\t**\tthe text into appropriate spacing.\n\t*/\n\tchar buffer[512];\n\tstrncpy(buffer, Text_String(TXT_DIFFICULTY), sizeof(buffer)-1);\n\tbuffer[sizeof(buffer)-1] = '\\0';\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// If it's an aftermath mission, trim the sentence to get rid of the campaign stuff.\n\tif (amath) {\n\t\tint index=0;\n\t\twhile (buffer[index] && buffer[index]!='.') index++;\n\t\tif (buffer[index]=='.') {\n\t\t\tbuffer[index+1]=0;\n\t\t}\n\t}\n#endif\n\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW);\n\tint width;\n\tint height;\n\tFormat_Window_String(buffer, w-60*RESFACTOR, width, height);\n\n\t/*\n\t**\tCreate the OK button.\n\t*/\n\tTextButtonClass okbutton(1, TXT_OK, TPF_BUTTON, (x+w) - (bwidth+20*RESFACTOR) , (y+h) - (18*RESFACTOR), bwidth);\n\tGadgetClass * buttonlist = &okbutton;\n\n\t/*\n\t**\tCreate the slider button.\n\t*/\n\tSliderClass slider(2, x+20*RESFACTOR, y+h - 29*RESFACTOR, w - 40*RESFACTOR, 8*RESFACTOR, true);\n\tif (Rule.IsFineDifficulty) {\n\t\tslider.Set_Maximum(5);\n\t\tslider.Set_Value(2);\n\t} else {\n\t\tslider.Set_Maximum(3);\n\t\tslider.Set_Value(1);\n\t}\n\tslider.Add(*buttonlist);\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\tbool redraw = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\tif (redraw) {\n\t\t\tredraw = false;\n\n\t\t\t/*\n\t\t\t**\tDraw the background of the dialog.\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(x, y, w, h);\n\n\t\t\t/*\n\t\t\t**\tDraw the body of the message.\n\t\t\t*/\n//\t\t\tFancy_Text_Print(buffer, x + 20*RESFACTOR, y + 15*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(buffer, x + 20*RESFACTOR, y + 15*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW);\n\n\t\t\t/*\n\t\t\t**\tDisplay the descripton of the slider range.\n\t\t\t*/\n\t\t\tFancy_Text_Print(TXT_HARD, slider.X+slider.Width, slider.Y-9*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_RIGHT|TPF_6PT_GRAD|TPF_DROPSHADOW);\n\t\t\tFancy_Text_Print(TXT_EASY, slider.X, slider.Y-9*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_DROPSHADOW);\n\t\t\tFancy_Text_Print(TXT_NORMAL, slider.X + (slider.Width/2), slider.Y-9*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_DROPSHADOW);\n\n\t\t\t/*\n\t\t\t**\tRedraw the buttons.\n\t\t\t*/\n\t\t\tif (buttonlist) {\n\t\t\t\tbuttonlist->Draw_All();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t}\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tCall_Back();\n\n#ifdef WIN32\n\t\t/*\n\t\t** Handle possible surface loss due to a focus switch\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tredraw = true;\n\t\t\tcontinue;\n\t\t}\n#endif\t//WIN32\n\n\t\t/*\n\t\t**\tFetch and process input.\n\t\t*/\n\t\tKeyNumType input = buttonlist->Input();\n\n\t\tswitch (input) {\n\t\t\tcase KN_RETURN:\n\t\t\tcase (1|BUTTON_FLAG):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn(slider.Get_Value() * (Rule.IsFineDifficulty ? 1 : 2));\n}\n"
  },
  {
    "path": "CODE/SPECIAL.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SPECIAL.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SPECIAL.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/27/95                                                     *\n *                                                                                             *\n *                  Last Update : February 27, 1995 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SPECIAL_H\n#define SPECIAL_H\n\nclass SpecialClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tThis initializes all members just like a constructor. A constructor\n\t\t**\tcannot be used for this class because it is part of a union.\n\t\t*/\n\t\tvoid Init(void);\n\n\t\t/*\n\t\t**\tIf the shroud should regenerated, then this flag will be true.\n\t\t*/\n\t\tunsigned IsShadowGrow:1;\n\n\t\t/*\n\t\t**\tControls the speedy build option -- used for testing.\n\t\t*/\n\t\tunsigned IsSpeedBuild:1;\n\n\t\t/*\n\t\t** If from install, then play the special installation movie and\n\t\t** skip asking them what type of game they want to play.\n\t\t*/\n\t\tunsigned IsFromInstall:1;\n\n\t\t/*\n\t\t**\tIf capture the flag mode is on, this flag will be true. With this\n\t\t**\tflag enabled, then the flag is initially placed at the start of\n\t\t**\tthe scenario.\n\t\t*/\n\t\tunsigned IsCaptureTheFlag:1;\n\n\t\t/*\n\t\t**\tThis flags controls whether weapons are inert. An inert weapon doesn't do any\n\t\t**\tdamage. Effectively, if this is true, then the units never die.\n\t\t*/\n\t\tunsigned IsInert:1;\n\n\t\t/*\n\t\t**\tIf wheeled vehicles should do a 3-point turn when rotating in place, then\n\t\t**\tthis flag is true.\n\t\t*/\n\t\tunsigned IsThreePoint:1;\n\n\t\t/*\n\t\t**\tIf Tiberium is allowed to spread and grow, then these flags will be true.\n\t\t**\tThese are duplicated from the rules.ini file and also controlled by the\n\t\t**\tmultiplayer dialog box.\n\t\t*/\n\t\tunsigned IsTGrowth:1;\n\t\tunsigned IsTSpread:1;\n\n\t\t/*\n\t\t** Flag that we were spawned from WChat.\n\t\t*/\n\t\tunsigned IsFromWChat:1;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/SPRITE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SPRITE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/**********************************************************************\n\n\tSprite.cpp\n\n\tDec 28,1995\n\n\tGraphicBufferClass member functions for blitting, scaling,\n\tand rotating bitmaps\n\n**********************************************************************/\n\n#ifndef WIN32\nclass BitmapClass\n{\n\tpublic:\n\t\tBitmapClass(int w, int h, unsigned char * data) :\n\t\t\tWidth(w), Height(h), Data(data) {};\n\n\t\tint Width;\n\t\tint Height;\n\t\tunsigned char * Data;\n};\n\nclass TPoint2D\n{\n\tpublic:\n\t\tTPoint2D(int xx, int yy) : x(xx), y(yy) {};\n\t\tTPoint2D(void) : x(0), y(0) {};\n\n\t\tint x;\n\t\tint y;\n};\n#endif\n\n\n//#include\t\"function.h\"\n#define FILE_H\n#define RAWFILE_H\n#define WWMEM_H\n#define WWFILE_Hx\n#include\t<wwlib32.h>\n#include <stdio.h>\n//#include \"gbuffer.h\"\n//#include \"math.h\"\n\n\nlong _SineTab[256] = {\n0 ,6 ,12 , 18 , 25 , 31 , 37 , 43 , 49 , 56 , 62 , 68 , 74 , 80 , 86 ,\n92 , 97 , 103 , 109 , 115 , 120 , 126 , 131 , 136 , 142 , 147 , 152 ,\n157 , 162 , 167 , 171 , 176 , 180 , 185 , 189 , 193 , 197 , 201 , 205 ,\n209 , 212 , 216 , 219 , 222 , 225 , 228 , 231 , 233 , 236 , 238 , 240 ,\n243 , 244 , 246 , 248 , 249 , 251 , 252 , 253 , 254 , 254 , 255 , 255 ,\n255 , 255 , 255 , 255 , 255 , 254 , 254 , 253 , 252 , 251 , 249 , 248 ,\n246 , 245 , 243 , 241 , 238 , 236 , 234 , 231 , 228 , 225 , 222 , 219 ,\n216 , 213 , 209 , 205 , 201 , 198 , 194 , 189 , 185 , 181 , 176 , 172 ,\n167 , 162 , 157 , 152 , 147 , 142 , 137 , 131 , 126 , 120 , 115 , 109 ,\n104 , 98 , 92 , 86 , 80 , 74 , 68 , 62 , 56 , 50 , 44 , 37 , 31 , 25 ,\n19 , 12 , 6 , 0 , -5 , -12 , -18 , -24 , -30 , -37 , -43 , -49 , -55 ,\n-61 , -67 , -73 , -79 , -85 , -91 , -97 , -103 , -109 , -114 , -120 ,\n-125 , -131 , -136 , -141 , -147 , -152 , -157 , -162 , -166 , -171 ,\n-176 , -180 , -185 , -189 , -193 , -197 , -201 , -205 , -208 , -212 ,\n-215 , -219 , -222 , -225 , -228 , -231 , -233 , -236 , -238 , -240 ,\n-242 , -244 , -246 , -248 , -249 , -250 , -252 , -253 , -254 , -254 ,\n-255 , -255 , -255 , -255 , -255 , -255 , -255 , -254 , -254 , -253 ,\n-252 , -251 , -249 , -248 , -246 , -245 , -243 , -241 , -239 , -236 ,\n-234 , -231 , -228 , -226 , -223 , -219 , -216 , -213 , -209 , -206 ,\n-202 , -198 , -194 , -190 , -185 , -181 , -177 , -172 , -167 , -162 ,\n-158 , -153 , -148 , -142 , -137 , -132 , -126 , -121 , -115 , -110 ,\n-104 , -98 , -92 , -86 , -81 , -75 , -69 , -62 , -56 , -50 , -44 ,\n-38 , -32 , -25 , -19 , -13 , -7 ,\n};\n\nlong _CosineTab[256] = {\n256 , 255 , 255 , 255 , 254 , 254 , 253 , 252 , 251 , 249 , 248 , 246 ,\n244 , 243 , 241 , 238 , 236 , 234 , 231 , 228 , 225 , 222 , 219 , 216 ,\n212 , 209 , 205 , 201 , 197 , 193 , 189 , 185 , 181 , 176 , 171 , 167 ,\n162 , 157 , 152 , 147 , 142 , 137 , 131 , 126 , 120 , 115 , 109 , 103 ,\n98 , 92 , 86 , 80 , 74 , 68 , 62 , 56 , 50 , 43 , 37 , 31 , 25 , 19 ,\n12 , 6 , 0 , -6 , -12 , -18 , -24 , -31 , -37 , -43 , -49 , -55 , -61 ,\n-68 , -74 , -80 , -86 , -91 , -97 , -103 , -109 , -114 , -120 , -125 , -131 ,\n-136 , -141 , -147 , -152 , -157 , -162 , -166 , -171 , -176 , -180 ,\n-185 , -189 , -193 , -197 , -201 , -205 , -209 , -212 , -216 , -219 , -222 ,\n-225 , -228 , -231 , -233 , -236 , -238 , -240 , -242 , -244 , -246 ,\n-248 , -249 , -251 , -252 , -253 , -254 , -254 , -255 , -255 , -255 ,\n-255 , -255 , -255 , -255 , -254 , -254 , -253 , -252 , -251 , -249 , -248 ,\n-246 , -245 , -243 , -241 , -239 , -236 , -234 , -231 , -228 , -225 ,\n-222 , -219 , -216 , -213 , -209 , -205 , -202 , -198 , -194 , -190 , -185 ,\n-181 , -176 , -172 , -167 , -162 , -157 , -152 , -147 , -142 , -137 , -132 ,\n-126 , -121 , -115 , -109 , -104 , -98 , -92 , -86 , -80 , -74 , -68 ,\n-62 , -56 , -50 , -44 , -38 , -31 , -25 , -19 , -13 , -6 , 0 , 5 , 11 ,\n18 , 24 , 30 , 36 , 43 , 49 , 55 , 61 , 67 , 73 , 79 , 85 , 91 , 97 , 103 ,\n108 , 114 , 120 , 125 , 131 , 136 , 141 , 146 , 151 , 156 , 161 , 166 ,\n171 , 176 , 180 , 184 , 189 , 193 , 197 , 201 , 205 , 208 , 212 , 215 ,\n219 , 222 , 225 , 228 , 231 , 233 , 236 , 238 , 240 , 242 , 244 , 246 ,\n248 , 249 , 250 , 252 , 253 , 253 , 254 , 255 , 255 , 255 ,\n};\n\n\n\n/***************************************************************\n*\n*\tScale_Rotate\n*\n*\tFUNCTION:\n*\n*\tUsing Bi-Linear Interpolation, draws a scaled and rotated\n*\tbitmap onto the buffer.  No clipping is performed so beware.\n*\n*\tINPUTS\n*\n*\tbmp\t\t- bitmap to draw\n*\tpt\t\t\t- desired position of the center\n*\tscale\t\t- 24.8 fixed point scale factor\n*\tangle\t\t- 8bit angle (0=0deg, 255=360deg)\n*\n***************************************************************/\n\nvoid GraphicBufferClass::Scale_Rotate(BitmapClass &bmp,TPoint2D const &pt,long scale,unsigned char angle)\n{\n\tunsigned int scrpos;\n\tunsigned int temp;\n\n\tint i,j;\t\t\t// counter vars\n\tint pxerror\t=0;\t\t// these three vars will be used in an\n\tint pyerror\t=0;\t\t// integer difference alg to keep track\n\tint pixpos\t=0;\t\t// of what pixel to draw.\n\tunsigned char pixel;\n\n\tTPoint2D p0;\t// \"upper left\" corner of the rectangle\n\tTPoint2D p1;\t// \"upper right\" corner of the rectangle\n\tTPoint2D p2;\t// \"lower left\" corner of the rectangle\n\n\t/*-------------------------------------------------\n\t\tCompute three corner points of the rectangle\n\t-------------------------------------------------*/\n\t{\n\t\tangle &= 0x0FF;\n\t\tlong c = _CosineTab[angle];\n \t\tlong s = _SineTab[angle];\n\t\tlong W = (scale*bmp.Width)>>1;\n\t\tlong L = (scale*bmp.Height)>>1;\n\n\t\tp0.x = (pt.x + ((( (L*c) >> 8)-((W*s) >> 8)) >> 8));\n\t\tp0.y = (pt.y + (((-(L*s) >> 8)-((W*c) >> 8)) >> 8));\n\t\tp1.x = (pt.x + ((( (L*c) >> 8)+((W*s) >> 8)) >> 8));\n\t\tp1.y = (pt.y + (((-(L*s) >> 8)+((W*c) >> 8)) >> 8));\n\t\tp2.x = (pt.x + (((-(L*c) >> 8)-((W*s) >> 8)) >> 8));\n\t\tp2.y = (pt.y + ((( (L*s) >> 8)-((W*c) >> 8)) >> 8));\n\t}\n\n\t/*-----------------------------------\n\t\tInitialize Breshnam constants\n\t-----------------------------------*/\n\n\t// This breshnam line goes across the FRONT of the rectangle\n\t// In the bitmap, this will step from left to right\n\n\tint f_deltax\t=(p1.x-p0.x);\n\tint f_deltay\t=(p1.y-p0.y);\n\tint f_error\t\t=0;\n\tint f_xstep\t\t=1;\n\tint f_ystep\t\t=Width;\n\n\t// This breshnam line goes down the SIDE of the rectangle\n\t// In the bitmap, this line will step from top to bottom\n\n\tint s_deltax\t=(p2.x-p0.x);\n\tint s_deltay\t=(p2.y-p0.y);\n\tint s_error\t\t=0;\n\tint s_xstep\t\t=1;\n\tint s_ystep\t\t=Width;\n\n\t/*--------------------------------\n\t\tfixup deltas and step values\n\t--------------------------------*/\n\n\tif (f_deltay<0) {\n\t\tf_deltay=-f_deltay;\n\t\tf_ystep=-Width;\n\t};\n\n\tif (f_deltax<0) {\n\t\tf_deltax=-f_deltax;\n\t\tf_xstep=-1;\n\t};\n\n\tif (s_deltay<0) {\n\t\ts_deltay=-s_deltay;\n\t\ts_ystep=-Width;\n\t};\n\n\tif (s_deltax<0) {\n\t\ts_deltax=-s_deltax;\n\t\ts_xstep=-1;\n\t};\n\n\tscrpos=p0.x+Width*p0.y; \t//address of initial screen pos.\n\ttemp=scrpos;\n\n\t/*---------------------------------------------------------------------\n\t\tNow all of the differences, errors, and steps are set up so we can\n\t\tbegin drawing the bitmap...\n\n\t\tThere are two cases here,\n\t\t1 - the \"Front\" line has a slope of <  1.0 (45 degrees)\n\t\t2 - the \"Front\" line has a slope of >= 1.0\n\n\t\tFor case 1, we step along the X direction, for case 2, step in y\n\t---------------------------------------------------------------------*/\n\n\tif (f_deltax>f_deltay) {\t\t//CASE 1, step front in X, side in Y\n\n\t\t// outer loop steps from top to bottom of the rectangle\n\t\tfor (j=0;j<s_deltay;j++)\n\t\t{\n\t\t\ttemp=scrpos;\n\n\t\t\t// The inner loop steps across the rectangle\n\t\t\tfor (i=0;i<f_deltax;i++)\n\t\t\t{\n\t\t\t\tpixel=bmp.Data[pixpos];\t\t\t\t//read pixel\n\t\t\t\tif (pixel) ((unsigned char *)Get_Buffer())[scrpos]=pixel;\t//draw if not transparent\n//\t\t\t\tif (pixel) Data[scrpos]=pixel;\t//draw if not transparent\n\t\t\t\tpxerror+=bmp.Width;\t\t \t\t\t//update position in bitmap\n\t\t\t\twhile (pxerror>f_deltax)\n\t\t\t\t{\n\t\t\t\t\tpixpos++;\n\t\t\t\t\tpxerror-=f_deltax;\n\t\t\t\t};\n\t\t\t\tscrpos+=f_xstep;\t\t\t\t\t\t//step to next screen pos\n\t\t\t\tf_error+=f_deltay;\n\t\t\t\tif (f_error>f_deltax)\n\t\t\t\t{\n\t\t\t\t\tif (pixel) ((unsigned char *)Get_Buffer())[scrpos]=pixel;\n\t\t\t\t\tf_error-=f_deltax;\n\t\t\t\t\tscrpos+=f_ystep;\n\t\t\t\t};\n\t\t\t};\n\t\t\tpxerror=0;\n\t\t\tpixpos-=bmp.Width-1;\n\t\t\tpyerror+=bmp.Height;\n\n\t\t\twhile (pyerror>s_deltay)\n\t\t\t{\n\t\t\t\tpixpos+=bmp.Width;\n\t\t\t\tpyerror-=s_deltay;\n\t\t\t};\n\n\t\t\tf_error=0;\n\t\t\tscrpos=temp;\n\t\t\tscrpos+=s_ystep;\n\t\t\ts_error+=s_deltax;\n\n\t\t\tif (s_error>s_deltay)\n\t\t\t{\n\t\t\t\ts_error-=s_deltay;\n\t\t\t\tscrpos+=s_xstep;\n\t\t\t};\n\t\t}\n\n\t} else {\t\t// CASE 2, Step front line in X, side line in Y\n\n\t\t// outer loop steps from top to bottom of the rectangle\n\t\tfor (j=0;j<s_deltax;j++)\n\t\t{\n\t\t\ttemp=scrpos;\n\n\t\t\t// The inner loop steps across the rectangle\n\t\t\tfor (i=0;i<f_deltay;i++)\n\t\t\t{\n\t\t\t\tpixel=bmp.Data[pixpos];\t\t\t\t//read pixel\n\t\t\t\tif (pixel) ((unsigned char *)Get_Buffer())[scrpos]=pixel;\t//draw if not transparent\n\t\t\t\tpxerror+=bmp.Width;\t\t\t\t\t//update position in bitmap\n\t\t\t\twhile (pxerror>f_deltay)\n\t\t\t\t{\n\t\t\t\t\tpixpos++;\n\t\t\t\t\tpxerror-=f_deltay;\n\t\t\t\t};\n\n\t\t\t\tscrpos+=f_ystep;\t\t\t\t\t\t//step to next screen pos\n\t\t\t\tf_error+=f_deltax;\n\t\t\t\tif (f_error>f_deltay)\n\t\t\t\t{\n\t\t\t\t\tif (pixel) ((unsigned char *)Get_Buffer())[scrpos]=pixel;\n\t\t\t\t\tf_error-=f_deltay;\n\t\t\t\t\tscrpos+=f_xstep;\n\t\t\t\t};\n\t\t\t};\n\n\t\t\tpxerror=0;\n\t\t\tpixpos-=bmp.Width-1;\n\t\t\tpyerror+=bmp.Height;\n\t\t\twhile (pyerror>s_deltax)\n\t\t\t{\n\t\t\t\tpixpos+=bmp.Width;\n\t\t\t\tpyerror-=s_deltax;\n\t\t\t};\n\n\t\t\tscrpos=temp;\n\t\t\tscrpos+=s_xstep;\n\t\t\ts_error+=s_deltay;\n\t\t\tf_error=0;\n\t\t\tif (s_error>s_deltax)\n\t\t\t{\n\t\t\t\ts_error-=s_deltax;\n\t\t\t\tscrpos+=s_ystep;\n\t\t\t};\n\t\t}\n\t}\n}"
  },
  {
    "path": "CODE/STAGE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/STAGE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : STAGE.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 17, 1994                                                *\n *                                                                                             *\n *                  Last Update : June 17, 1994   [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef STAGE_H\n#define STAGE_H\n\nclass StageClass {\n\n\t\t/*\n\t\t**\tThis handles the animation stage of the object. This includes smoke, walking,\n\t\t**\tflapping, and rocket flames.\n\t\t*/\n\t\tunsigned Stage;\n\n\t\t/*\n\t\t**\tThis is the countdown timer for stage animation. When this counts down\n\t\t**\tto zero, then the stage increments by one and the time cycle starts\n\t\t**\tover again.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> Timer;\n\n\t\t/*\n\t\t**\tThis is the value to assign the StageTimer whenever it needs to be reset. Thus,\n\t\t**\tthis value is the control of how fast the stage value increments.\n\t\t*/\n\t\tint Rate;\n\n\tpublic:\n\t\tStageClass(void) : Stage(0), Timer(0), Rate(0) {};\n\t\tStageClass(NoInitClass const & x) : Timer(x) {};\n\n\t\tint Fetch_Stage(void) const {return(Stage);};\n\t\tint Fetch_Rate(void) const {return(Rate);};\n\t\tvoid Set_Stage(int stage) {Stage = stage;};\n\t\tvoid Set_Rate(int rate) {Timer = rate; Rate = rate;};\n\t\tvoid AI(void) {};\n\t\tbool About_To_Change(void) const {return(Timer == 0 && Rate != 0);}\n\t\tbool Graphic_Logic(void) {\n\t\t\tif (About_To_Change()) {\n\t\t\t\tStage++;\n\t\t\t\tTimer = Rate;\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t\treturn(false);\n\t\t};\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/STARTUP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /counterstrike/STARTUP.CPP 6     3/15/97 7:18p Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : STARTUP.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : October 3, 1994                                              *\n *                                                                                             *\n *                  Last Update : September 30, 1996 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Prog_End -- Cleans up library systems in prep for game exit.                              *\n *   main -- Initial startup routine (preps library systems).                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t<conio.h>\n#include\t<io.h>\n\n#ifdef WIN32\n#include  \"ccdde.h\"\n#include\t\"ipx95.h\"\n#endif\t//WIN32\n\n#ifdef MCIMPEG // Denzil 6/15/98\n#include \"mcimovie.h\"\n#endif\n\n#ifdef WOLAPI_INTEGRATION\n//#include \"WolDebug.h\"\n#endif\n\nbool Read_Private_Config_Struct(FileClass & file, NewConfigType * config);\nvoid Print_Error_End_Exit(char * string);\nvoid Print_Error_Exit(char * string);\n\n#ifdef WIN32\n//WinTimerClass * WinTimer;\nextern void Create_Main_Window ( HANDLE instance , int command_show , int width , int height);\nextern bool RA95AlreadyRunning;\nHINSTANCE\tProgramInstance;\nvoid Check_Use_Compressed_Shapes (void);\nvoid Read_Setup_Options(RawFileClass *config_file);\nbool VideoBackBufferAllowed = true;\n#else\nBOOL Init_Timer_System(unsigned int freq, int partial = FALSE);\nBOOL Remove_Timer_System(VOID);\n#endif\t//WIN32\n\nconst char* Game_Registry_Key();\n\n#if (ENGLISH)\n#define WINDOW_NAME\t\t\"Red Alert\"\n#endif\n\n#if (FRENCH)\n#define WINDOW_NAME\t\t\"Alerte Rouge\"\n#endif\n\n#if (GERMAN)\n#define WINDOW_NAME\t\t\"Alarmstufe Rot\"\n#endif\n\n\n\n/***********************************************************************************************\n * main -- Initial startup routine (preps library systems).                                    *\n *                                                                                             *\n *    This is the routine that is first called when the program starts up. It basically        *\n *    handles the command line parsing and setting up library systems.                         *\n *                                                                                             *\n * INPUT:   argc  -- Number of command line arguments.                                         *\n *                                                                                             *\n *          argv  -- Pointer to array of command line argument strings.                        *\n *                                                                                             *\n * OUTPUT:  Returns with execution failure code (if any).                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef WIN32\n//int PASCAL WinMain(HINSTANCE, HINSTANCE, char *, int )\nint PASCAL WinMain ( HINSTANCE instance , HINSTANCE , char * command_line , int command_show )\n#else\t//WIN32\nint main(int argc, char * argv[])\n#endif\t//WIN32\n\n{\n#ifdef WIN32\n\n\t#ifndef MPEGMOVIE // Denzil 6/10/98\n\tDDSCAPS\tsurface_capabilities;\n\t#endif\n\n\t/*\n\t** First thing to do is check if there is another instance of Red Alert already running\n\t**  and if so, switch to the existing instance and terminate ourselves.\n\t*/\n\tSpawnedFromWChat = false;\n\n\tif (RA95AlreadyRunning) {\t//Set in the DDEServer constructor\n\t\t//MessageBox (NULL, \"Error - attempt to restart Red Alert 95 when already running.\", \"Red Alert\", MB_ICONEXCLAMATION|MB_OK);\n\n\t\tHWND ccwindow;\n    \tccwindow = FindWindow (WINDOW_NAME, WINDOW_NAME);\n    \tif (ccwindow) {\n    \t\tSetForegroundWindow ( ccwindow );\n    \t\tShowWindow ( ccwindow, SW_RESTORE );\n    \t}\n\n\t\treturn (EXIT_SUCCESS);\n\t}\n\n\n#endif\n//printf(\"in program.\\n\");getch();\n//printf(\"ram free = %ld\\n\",Ram_Free(MEM_NORMAL));getch();\n#ifdef WIN32\n\tif (Ram_Free(MEM_NORMAL) < 7000000) {\n#else\n\n\tvoid *temp_mem = malloc (13*1024*1024);\n\tif (temp_mem) {\n\t\tfree (temp_mem);\n\t}else{\n\n\t//if (Ram_Free(MEM_NORMAL) < 13000000) {\n//\tif (Ram_Free(MEM_NORMAL) < 3500000) {\n#endif\n\t\tprintf (TEXT_NO_RAM);\n\n#ifndef WIN32\n\t\tprintf (TEXT_USE_START_MENU);\n\t\tgetch();\n#endif\n\n#if (0)\n\n\t\t/*\n\t\t** Take a stab at finding out how much memory there is available.\n\t\t*/\n\n\t\tfor ( int mem = 13*1024*1024 ; mem >0 ; mem -=1024 ) {\n\t\t\ttemp_mem = malloc (mem);\n\t\t\tif (temp_mem){\n\t\t\t\tfree (temp_mem);\n\t\t\t\tprintf (\"Memory available: %d\", mem);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tgetch();\n#endif\t//(0)\n\t\treturn(EXIT_FAILURE);\n\t}\n\n#ifdef WIN32\n\n\tif (strstr(command_line, \"f:\\\\projects\\\\c&c0\") != NULL ||\n\t\t\tstrstr(command_line, \"F:\\\\PROJECTS\\\\C&C0\") != NULL) {\n\t\tMessageBox(0, \"Playing off of the network is not allowed.\", \"Red Alert\", MB_OK|MB_ICONSTOP);\n\t\treturn(EXIT_FAILURE);\n\t}\n\n\tint\t\targc;\t\t\t\t//Command line argument count\n\tunsigned\tcommand_scan;\n\tchar\t\tcommand_char;\n\tchar *\targv[20];\t\t//Pointers to command line arguments\n\tchar\t\tpath_to_exe[132];\n\n\tProgramInstance = instance;\n\n\t/*\n\t** Get the full path to the .EXE\n\t*/\n\tGetModuleFileName (instance, &path_to_exe[0], 132);\n\n\t/*\n\t** First argument is supposed to be a pointer to the .EXE that is running\n\t**\n\t*/\n\targc=1;\t\t\t\t\t\t\t//Set argument count to 1\n\targv[0]=&path_to_exe[0];\t//Set 1st command line argument to point to full path\n\n\t/*\n\t** Get pointers to command line arguments just like if we were in DOS\n\t**\n\t** The command line we get is cr/zero? terminated.\n\t**\n\t*/\n\n\tcommand_scan=0;\n\n\tdo {\n\t\t/*\n\t\t** Scan for non-space character on command line\n\t\t*/\n\t\tdo {\n\t\t\tcommand_char = *( command_line+command_scan++ );\n\t\t} while ( command_char==' ' );\n\n\t\tif ( command_char!=0 && command_char != 13 ) {\n\t\t\targv[argc++]=command_line+command_scan-1;\n\n\t\t\t/*\n\t\t\t** Scan for space character on command line\n\t\t\t*/\n\t\t\tdo {\n\t\t\t\tcommand_char = *( command_line+command_scan++ );\n\t\t\t} while ( command_char!=' ' && command_char != 0 && command_char!=13 );\n\t\t*( command_line+command_scan-1 ) = 0;\n\t\t}\n\n\t} while ( command_char != 0 && command_char != 13 && argc<20 );\n\n#endif\t//WIN32\n\n\t/*\n\t**\tRemember the current working directory and drive.\n\t*/\n\tunsigned olddrive;\n\tchar oldpath[PATH_MAX];\n\tgetcwd(oldpath, sizeof(oldpath));\n\t_dos_getdrive(&olddrive);\n\n\t/*\n\t**\tChange directory to the where the executable is located. Handle the\n\t**\tcase where there is no path attached to argv[0].\n\t*/\n\tchar drive[_MAX_DRIVE];\n\tchar path[_MAX_PATH];\n\tunsigned drivecount;\n\t_splitpath(argv[0], drive, path, NULL, NULL);\n\tif (!drive[0]) {\n\t\tdrive[0] = ('A' + olddrive)-1;\n\t}\n\tif (!path[0]) {\n\t\tstrcpy(path, \".\");\n\t}\n\t_dos_setdrive(toupper((drive[0])-'A')+1, &drivecount);\n\tif (path[strlen(path)-1] == '\\\\') {\n\t\tpath[strlen(path)-1] = '\\0';\n\t}\n\tchdir(path);\n\n#ifdef WOLAPI_INTEGRATION\n\t//\tLook for special wolapi install program, used after the patch to version 3, to install \"Shared Internet Components\".\n\tWIN32_FIND_DATA wfd;\n\tHANDLE hWOLSetupFile = FindFirstFile( \"wolsetup.exe\", &wfd );\n\tbool bWOLSetupFile = ( hWOLSetupFile != INVALID_HANDLE_VALUE );\n//\tif( bWOLSetupFile )\n//\t\tdebugprint( \"Found wolsetup.exe\\n\" );\n\tFindClose( hWOLSetupFile );\n\t//\tLook for special registry entry that tells us when the setup exe has done its thing.\n\tHKEY hKey;\n\tRegOpenKeyEx( HKEY_LOCAL_MACHINE, Game_Registry_Key(), 0, KEY_READ, &hKey );\n\tDWORD dwValue;\n\tDWORD dwBufSize = sizeof( DWORD );\n\tif( RegQueryValueEx( hKey, \"WolapiInstallComplete\", 0, NULL, (LPBYTE)&dwValue, &dwBufSize ) == ERROR_SUCCESS )\n\t{\n//\t\tdebugprint( \"Found WolapiInstallComplete in registry\\n\" );\n\t\t//\tSetup has finished. Delete the setup exe and remove reg key.\n\t\tif( bWOLSetupFile )\n\t\t{\n\t\t\tif( DeleteFile( \"wolsetup.exe\" ) )\n\t\t\t\tRegDeleteValue( hKey, \"WolapiInstallComplete\" );\n\t\t}\n\t\telse\n\t\t\tRegDeleteValue( hKey, \"WolapiInstallComplete\" );\n\t}\n\tRegCloseKey( hKey );\n\n\t//\tI've been having problems getting the patch to delete \"conquer.eng\", which is present in the game\n\t//\tdirectory for 1.08, but which must NOT be present for this version (Aftermath mix files provide the\n\t//\tstring overrides that the 1.08 separate conquer.eng did before Aftermath).\n\t//\tDelete conquer.eng if it's found.\n\tif( FindFirstFile( \"conquer.eng\", &wfd ) != INVALID_HANDLE_VALUE )\n\t\tDeleteFile( \"conquer.eng\" );\n\n#endif\n\n\tif (Parse_Command_Line(argc, argv)) {\n\n#if(TEN)\n\t//\n\t// Only allow the TEN version of the game to run if the TEN\n\t// or AllowSoloPlayOptions arguments are specified.\n\t//\n\tif (Session.AllowSolo==0 && Session.Type != GAME_TEN) {\n#ifdef WIN32\n\t\tMessageBox(NULL, \"Red Alert for TEN\\n (c) 1996 Westwood Studios\",\n\t\t\t\"Red Alert\", MB_OK);\n\t\texit(0);\n#else\n\t\tprintf(\"\\n\");\n\t\tprintf(\"                         Red Alert for TEN\\n\");\n\t\tprintf(\"                     (c) 1996 Westwood Studios\\n\");\n\t\tprintf(\"\\n\");\n\t\texit(0);\n#endif\t// WIN32\n\t}\n#endif\t// TEN\n\n#if(MPATH)\n\t//\n\t// Only allow the MPATH version of the game to run if the MPATH\n\t// or AllowSoloPlayOptions arguments are specified.\n\t//\n\tif (Session.AllowSolo==0 && Session.Type != GAME_MPATH) {\n#ifdef WIN32\n\t\tMessageBox(NULL, \"Red Alert for MPATH\\n (c) 1996 Westwood Studios\",\n\t\t\t\"Red Alert\", MB_OK);\n\t\texit(0);\n#else\n\t\tprintf(\"\\n\");\n\t\tprintf(\"                        Red Alert for MPATH\\n\");\n\t\tprintf(\"                     (c) 1996 Westwood Studios\\n\");\n\t\tprintf(\"\\n\");\n\t\texit(0);\n#endif\t// WIN32\n\t}\n#endif\t// MPATH\n\n#ifdef WIN32\n\t\tWindowsTimer = new WinTimerClass(60, FALSE);\n\n\t\tint time_test = WindowsTimer->Get_System_Tick_Count();\n\t\tSleep (1000);\n\t\tif (WindowsTimer->Get_System_Tick_Count() == time_test){\n\t\t\tMessageBox(0, TEXT_ERROR_TIMER, TEXT_SHORT_TITLE, MB_OK|MB_ICONSTOP);\n\t\t\treturn(EXIT_FAILURE);\n\t\t}\n#else\t//WIN32\n\t\tInit_Timer_System(60, true);\n#endif\t//WIN32\n\t\tRawFileClass cfile(CONFIG_FILE_NAME);\n\n#ifndef WIN32\n\t\tInstall_Keyboard_Interrupt(Get_RM_Keyboard_Address(), Get_RM_Keyboard_Size());\n#endif\t//WIN32\n\n#ifdef NEVER\n\t\tKeyboard->IsLibrary = true;\n\t\tif (Debug_Flag) {\n\t\t\tKeyboard_Attributes_On(DEBUGINT);\n\t\t}\n#endif\n\n\t\tKeyboard = new KeyboardClass();\n\n#ifdef WIN32\n\t\t/*\n\t\t** If there is loads of memory then use uncompressed shapes\n\t\t*/\n\t\tCheck_Use_Compressed_Shapes();\n#endif\n\n\t\t/*\n\t\t** If there is not enough disk space free, don't allow the product to run.\n\t\t*/\n\t\tif (Disk_Space_Available() < INIT_FREE_DISK_SPACE) {\n\n#ifdef WIN32\n\t\t\tchar\tdisk_space_message [512];\n\t\t\tsprintf (disk_space_message, TEXT_CRITICALLY_LOW, (INIT_FREE_DISK_SPACE) / (1024 * 1024));\n\t\t\tint reply = MessageBox(NULL, disk_space_message, TEXT_SHORT_TITLE, MB_ICONQUESTION|MB_YESNO);\n\t\t\tif (reply == IDNO) {\n\t\t\t\tif ( WindowsTimer )\n\t\t\t\t\tdelete WindowsTimer;\n\t\t\t\treturn (EXIT_FAILURE);\n\t\t\t}\n#else\n\t\t\tprintf(TEXT_INSUFFICIENT);\n\t\t\tprintf(TEXT_MUST_HAVE, INIT_FREE_DISK_SPACE / (1024 * 1024));\n\t\t\tprintf(\"\\n\");\n\t\t\tif (Keyboard) Keyboard->Get();\n//\t\t\tKeyboard::IsLibrary = false;\n\t\t\tRemove_Keyboard_Interrupt();\n\t\t\tRemove_Timer_System();\n\t\t\treturn(EXIT_FAILURE);\n#endif\n\t\t}\n\n\t\tif (cfile.Is_Available()) {\n\n\t\t\tRead_Private_Config_Struct(cfile, &NewConfig);\n\n#ifdef WIN32\n\n\t\t\t/*\n\t\t\t** Set the options as requested by the ccsetup program\n\t\t\t*/\n\t\t\tRead_Setup_Options( &cfile );\n\n\t\t\tCreate_Main_Window( instance , command_show , ScreenWidth , ScreenHeight );\n\t\t\tSoundOn = Audio_Init ( MainWindow , 16 , false , 11025*2 , 0 );\n#else\t//WIN32\n\t\t\tif (!Debug_Quiet) {\n\t\t\t\tAudio_Init(NewConfig.DigitCard,\n\t\t\t\t\t\tNewConfig.Port,\n\t\t\t\t\t\tNewConfig.IRQ,\n\t\t\t\t\t\tNewConfig.DMA,\n\t\t\t\t\t\tPLAYBACK_RATE_NORMAL,\n//\t\t\t\t\t\t(NewConfig.Speed) ? PLAYBACK_RATE_SLOW : PLAYBACK_RATE_NORMAL,\n\t\t\t\t\t\tNewConfig.BitsPerSample,\n//\t\t\t\t\t\t4,\n\t\t\t\t\t\t(Get_CPU() < 5) ? 3 : 5,\n//\t\t\t\t\t\t(NewConfig.Speed) ? 3 : 5,\n\t\t\t\t\t\tNewConfig.Reverse);\n\t\t\t\tSoundOn = true;\n\t\t\t} else {\n\t\t\t\tAudio_Init(0, -1, -1, -1, PLAYBACK_RATE_NORMAL, 8, 5, false);\n\t\t\t}\n#endif\t//WIN32\n\n\n#ifdef WIN32\n\t\t\t#ifdef MPEGMOVIE // Denzil 6/10/98\n\t\t\tif (!InitDDraw())\n\t\t\t\treturn (EXIT_FAILURE);\n\t\t\t#else\n\t\t\tBOOL video_success = FALSE;\n\t\t\t/*\n\t\t\t** Set 640x400 video mode. If its not available then try for 640x480\n\t\t\t*/\n\t\t\tif (ScreenHeight == 400) {\n\t\t\t\tif (Set_Video_Mode (MainWindow, ScreenWidth, ScreenHeight, 8)) {\n\t\t\t\t\tvideo_success = TRUE;\n\t\t\t\t} else {\n\t\t\t\t\tif (Set_Video_Mode (MainWindow, ScreenWidth, 480, 8)) {\n\t\t\t\t\t\tvideo_success = TRUE;\n\t\t\t\t\t\tScreenHeight = 480;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (Set_Video_Mode (MainWindow, ScreenWidth, ScreenHeight, 8)) {\n\t\t\t\t\tvideo_success = TRUE;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!video_success) {\n\t\t\t\tMessageBox(MainWindow, TEXT_VIDEO_ERROR, TEXT_SHORT_TITLE, MB_ICONEXCLAMATION|MB_OK);\n\t\t\t\tif (WindowsTimer) delete WindowsTimer;\n\t\t\t\t//if (Palette) delete Palette;\n\t\t\t\treturn (EXIT_FAILURE);\n\t\t\t}\n\n\t\t\tif (ScreenWidth==320) {\n\t\t\t\tVisiblePage.Init( ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)0);\n\t\t\t\tModeXBuff.Init( ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)(GBC_VISIBLE | GBC_VIDEOMEM));\n\t\t\t} else {\n\t\t\t\tVisiblePage.Init( ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)(GBC_VISIBLE | GBC_VIDEOMEM));\n\n\t\t\t\t/*\n\t\t\t\t** Check that we really got a video memory page. Failure is fatal.\n\t\t\t\t*/\n\t\t\t\tmemset (&surface_capabilities, 0, sizeof(surface_capabilities));\n\t\t\t\tVisiblePage.Get_DD_Surface()->GetCaps(&surface_capabilities);\n\t\t\t\tif (surface_capabilities.dwCaps & DDSCAPS_SYSTEMMEMORY) {\n\t\t\t\t\t/*\n\t\t\t\t\t** Aaaarrgghh!\n\t\t\t\t\t*/\n\t\t\t\t\tWWDebugString(TEXT_DDRAW_ERROR);WWDebugString(\"\\n\");\n\t\t\t\t\tMessageBox(MainWindow, TEXT_DDRAW_ERROR, TEXT_SHORT_TITLE, MB_ICONEXCLAMATION|MB_OK);\n\t\t\t\t\tif (WindowsTimer) delete WindowsTimer;\n\t\t\t\t\treturn (EXIT_FAILURE);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** If we have enough left then put the hidpage in video memory unless...\n\t\t\t\t**\n\t\t\t\t** If there is no blitter then we will get better performance with a system\n\t\t\t\t** memory hidpage\n\t\t\t\t**\n\t\t\t\t** Use a system memory page if the user has specified it via the ccsetup program.\n\t\t\t\t*/\n\t\t\t\tunsigned video_memory = Get_Free_Video_Memory();\n\t\t\t\tunsigned video_capabilities = Get_Video_Hardware_Capabilities();\n\t\t\t\tif (video_memory < ScreenWidth*ScreenHeight ||\n\t\t\t\t\t\t(! (video_capabilities & VIDEO_BLITTER)) ||\n\t\t\t\t\t\t(video_capabilities & VIDEO_NO_HARDWARE_ASSIST) ||\n\t\t\t\t\t\t!VideoBackBufferAllowed) {\n\t\t\t\t\tHiddenPage.Init (ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)0);\n\t\t\t\t} else {\n\t\t\t\t\t//HiddenPage.Init (ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)0);\n\t\t\t\t\tHiddenPage.Init (ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)GBC_VIDEOMEM);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Make sure we really got a video memory hid page. If we didnt then things\n\t\t\t\t\t** will run very slowly.\n\t\t\t\t\t*/\n\t\t\t\t\tmemset (&surface_capabilities, 0, sizeof(surface_capabilities));\n\t\t\t\t\tHiddenPage.Get_DD_Surface()->GetCaps(&surface_capabilities);\n\t\t\t\t\tif (surface_capabilities.dwCaps & DDSCAPS_SYSTEMMEMORY) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Oh dear, big trub. This must be an IBM crAptiva or something similarly cruddy.\n\t\t\t\t\t\t** We must redo the Hidden Page as system memory.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tAllSurfaces.Remove_DD_Surface(HiddenPage.Get_DD_Surface());  // Remove the old surface from the AllSurfaces list\n\t\t\t\t\t\tHiddenPage.Get_DD_Surface()->Release();\n\t\t\t\t\t\tHiddenPage.Init (ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)0);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tVisiblePage.Attach_DD_Surface(&HiddenPage);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tScreenHeight = 400;\n\n\t\t\tif (VisiblePage.Get_Height() == 480) {\n\t\t\t\tSeenBuff.Attach(&VisiblePage, 0, 40, 640, 400);\n\t\t\t\tHidPage.Attach(&HiddenPage, 0, 40, 640, 400);\n\t\t\t} else {\n\t\t\t\tSeenBuff.Attach(&VisiblePage, 0, 0, 640, 400);\n\t\t\t\tHidPage.Attach(&HiddenPage, 0, 0, 640, 400);\n\t\t\t}\n\t\t\t#endif // MPEGMOVIE - Denzil 6/10/98\n\t\t\t\n\t\t\tOptions.Adjust_Variables_For_Resolution();\n\n\t\t\t/*\n\t\t\t** Install the memory error handler\n\t\t\t*/\n\t\t\tMemory_Error = &Memory_Error_Handler;\n\n\t\t\tWindowList[0][WINDOWWIDTH] \t= SeenBuff.Get_Width();\n\t\t\tWindowList[0][WINDOWHEIGHT]\t= SeenBuff.Get_Height();\n\t\t\tWindowList[WINDOW_EDITOR][WINDOWWIDTH] = SeenBuff.Get_Width();\n\t\t\tWindowList[WINDOW_EDITOR][WINDOWHEIGHT]= SeenBuff.Get_Height();\n\n\t\t\tWWMouse = new WWMouseClass(&SeenBuff, 48, 48);\n\t\t\tMouseInstalled = TRUE;\n\n\t\t\tCDFileClass::Set_CD_Drive (CDList.Get_First_CD_Drive());\n\n#else\t//WIN32\n\n\t\t\tOptions.Adjust_Variables_For_Resolution();\n\t\t\tif (!Special.IsFromInstall) {\n\t\t\t\tBlackPalette.Set();\n//\t\t\t\tSet_Palette(Palette);\n\t\t\t\tSet_Video_Mode(MCGA_MODE);\n\t\t\t}\n\t\t\tMouseInstalled = Install_Mouse(32, 24, 320, 200);\n#endif\t//WIN32\n\n\t\t\t/*\n\t\t\t** See if we should run the intro\n\t\t\t*/\n\t\t\tINIClass ini;\n\t\t\tini.Load(cfile);\n\n\t\t\t/*\n\t\t\t**\tCheck for forced intro movie run disabling. If the conquer\n\t\t\t**\tconfiguration file says \"no\", then don't run the intro.\n\t\t\t** Don't do this for TEN & MPath.\n\t\t\t*/\n\t\t\tif (!Special.IsFromInstall && Session.Type != GAME_TEN &&\n\t\t\t\tSession.Type != GAME_MPATH) {\n\t\t\t\tSpecial.IsFromInstall = ini.Get_Bool(\"Intro\", \"PlayIntro\", true);\n\t\t\t}\n\t\t\tSlowPalette = ini.Get_Bool(\"Options\", \"SlowPalette\", false);\n\n\t\t\t/*\n\t\t\t** Regardless of whether we should run it or not, here we're\n\t\t\t** gonna change it to say \"no\" in the future.\n\t\t\t*/\n\t\t\tif (Special.IsFromInstall) {\n\t\t\t\tBreakoutAllowed = true;\n//\t\t\t\tBreakoutAllowed = false;\n\t\t\t\tini.Put_Bool(\"Intro\", \"PlayIntro\", false);\n\t\t\t\tini.Save(cfile);\n\t\t\t}\n\n#ifndef WOLAPI_INTEGRATION\n#ifdef WIN32\n\t\t\t/*\n\t\t\t** If WChat has been trying to send us a game start packet then receive it and\n\t\t\t** flag that we were spawned from WCHat so we dont play the into movie.\n\t\t\t*/\n\t\t\tif (DDEServer.Get_MPlayer_Game_Info()){\n\t\t\t\tCheck_From_WChat(NULL);\n\t\t\t}else{\n\t\t\t\t//Check_From_WChat(\"C&CSPAWN.INI\");\n\t\t\t\t//if (Special.IsFromWChat){\n\t\t\t\t//\tDDEServer.Disable();\n\t\t\t\t//}\n\t\t\t}\n#endif\t//WIN32\n#endif\n\t\t\t/*\n\t\t\t**\tIf the intro is being run for the first time, then don't\n\t\t\t**\tallow breaking out of it with the <ESC> key.\n\t\t\t*/\n\t\t\tif (Special.IsFromInstall) {\n\t\t\t\tBreakoutAllowed = true;\n//\t\t\t\tBreakoutAllowed = false;\n\t\t\t}\n\n\t\t\tMemory_Error_Exit = Print_Error_End_Exit;\n\n\t\t\tMain_Game(argc, argv);\n\n\t\t\t#ifdef MPEGMOVIE // Denzil 6/15/98\n\t\t\tif (MpgSettings != NULL)\n\t\t\t\tdelete MpgSettings;\n\t\n\t\t\t#ifdef MCIMPEG\n\t\t\tif (MciMovie != NULL)\n\t\t\t\tdelete MciMovie;\n\t\t\t#endif\n\t\t\t#endif\n\t\t\t\n#ifdef WIN32\n\t\t\tVisiblePage.Clear();\n\t\t\tHiddenPage.Clear();\n#else\t//WIN32\n\t\t\tSeenPage.Clear();\n\t\t\tSet_Video_Mode(RESET_MODE);\n#endif\t//WIN32\n\t\t\tMemory_Error_Exit = Print_Error_Exit;\n\n#ifdef WIN32\n\t\t\t/*\n\t\t\t** Flag that this is a clean shutdown (not killed with Ctrl-Alt-Del)\n\t\t\t*/\n\t\t\tReadyToQuit = 1;\n\n\t\t\t/*\n\t\t\t** Post a message to our message handler to tell it to clean up.\n\t\t\t*/\n\t\t\tPostMessage(MainWindow, WM_DESTROY, 0, 0);\n\n\t\t\t/*\n\t\t\t** Wait until the message handler has dealt with the message\n\t\t\t*/\n\t\t\tdo\n\t\t\t{\n\t\t\t\tKeyboard->Check();\n\t\t\t}while (ReadyToQuit == 1);\n\n\t\t\treturn (EXIT_SUCCESS);\n\n#else\t//WIN32\n\t\t\tRemove_Mouse();\n\t\t\tSound_End();\n#endif\t//WIN32\n\t\t} else {\n\t\t\tputs(TEXT_SETUP_FIRST);\n\t\t\tKeyboard->Get();\n\t\t}\n\n#ifdef WIN32\n\t\tif (WindowsTimer) {\n\t\t \tdelete WindowsTimer;\n\t\t \tWindowsTimer = NULL;\n\t\t}\n\n#else\t//WIN32\n\t\tRemove_Keyboard_Interrupt();\n\t\tRemove_Timer_System();\n#endif\t//WIN32\n\t}\n\t/*\n\t**\tRestore the current drive and directory.\n\t*/\n#ifndef WIN32\n\t_dos_setdrive(olddrive, &drivecount);\n\tchdir(oldpath);\n#endif\t//WIN32\n\treturn(EXIT_SUCCESS);\n}\n\n\n/* Initialize DirectDraw and surfaces */\nbool InitDDraw(void)\n\t{\n\tDDSCAPS\tsurface_capabilities;\n\tBOOL video_success = FALSE;\n\n\t/* Set 640x400 video mode. If its not available then try for 640x480 */\n\tif (ScreenHeight == 400)\n\t\t{\n\t\tif (Set_Video_Mode(MainWindow, ScreenWidth, ScreenHeight, 8))\n\t\t\t{\n\t\t\tvideo_success = TRUE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif (Set_Video_Mode(MainWindow, ScreenWidth, 480, 8))\n\t\t\t\t{\n\t\t\t\tvideo_success = TRUE;\n\t\t\t\tScreenHeight = 480;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif (Set_Video_Mode(MainWindow, ScreenWidth, ScreenHeight, 8))\n\t\t\t{\n\t\t\tvideo_success = TRUE;\n\t\t\t}\n\t\t}\n\n\tif (!video_success)\n\t\t{\n\t\tMessageBox(MainWindow, TEXT_VIDEO_ERROR, TEXT_SHORT_TITLE, MB_ICONEXCLAMATION|MB_OK);\n\n\t\tif (WindowsTimer)\n\t\t\tdelete WindowsTimer;\n\n\t\treturn false;\n\t\t}\n\n\tif (ScreenWidth == 320)\n\t\t{\n\t\tVisiblePage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)0);\n\t\tModeXBuff.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)(GBC_VISIBLE|GBC_VIDEOMEM));\n\t\t}\n\telse\n\t\t{\n\t\tVisiblePage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)(GBC_VISIBLE|GBC_VIDEOMEM));\n\n\t\t/* Check that we really got a video memory page. Failure is fatal. */\n\t\tmemset(&surface_capabilities, 0, sizeof(surface_capabilities));\n\t\tVisiblePage.Get_DD_Surface()->GetCaps(&surface_capabilities);\n\n\t\tif (surface_capabilities.dwCaps & DDSCAPS_SYSTEMMEMORY)\n\t\t\t{\n\t\t\t/* Aaaarrgghh! */\n\t\t\tWWDebugString(TEXT_DDRAW_ERROR);WWDebugString(\"\\n\");\n\t\t\tMessageBox(MainWindow, TEXT_DDRAW_ERROR, TEXT_SHORT_TITLE, MB_ICONEXCLAMATION|MB_OK);\n\n\t\t\tif (WindowsTimer)\n\t\t\t\tdelete WindowsTimer;\n\t\t\t\t\n\t\t\treturn false;\n\t\t\t}\n\n\t\t/* If we have enough left then put the hidpage in video memory unless...\n\t\t *\n\t\t * If there is no blitter then we will get better performance with a system\n\t\t * memory hidpage\n\t\t *\n\t\t * Use a system memory page if the user has specified it via the ccsetup program.\n\t\t */\n\t\tunsigned video_memory = Get_Free_Video_Memory();\n\t\tunsigned video_capabilities = Get_Video_Hardware_Capabilities();\n\n\t\tif (video_memory < ScreenWidth * ScreenHeight\n\t\t\t\t|| (!(video_capabilities & VIDEO_BLITTER))\n\t\t\t\t|| (video_capabilities & VIDEO_NO_HARDWARE_ASSIST)\n\t\t\t\t|| !VideoBackBufferAllowed)\n\t\t\t{\n\t\t\tHiddenPage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)0);\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tHiddenPage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)GBC_VIDEOMEM);\n\n\t\t\t/* Make sure we really got a video memory hid page. If we didnt then things\n\t\t\t * will run very slowly.\n\t\t\t */\n\t\t\tmemset(&surface_capabilities, 0, sizeof(surface_capabilities));\n\t\t\tHiddenPage.Get_DD_Surface()->GetCaps(&surface_capabilities);\n\t\t\t\n\t\t\tif (surface_capabilities.dwCaps & DDSCAPS_SYSTEMMEMORY)\n\t\t\t\t{\n\t\t\t\t/* Oh dear, big trub. This must be an IBM crAptiva or something similarly cruddy.\n\t\t\t\t * We must redo the Hidden Page as system memory.\n\t\t\t\t */\n\t\t\t\tAllSurfaces.Remove_DD_Surface(HiddenPage.Get_DD_Surface());  // Remove the old surface from the AllSurfaces list\n\t\t\t\tHiddenPage.Get_DD_Surface()->Release();\n\t\t\t\tHiddenPage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)0);\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tVisiblePage.Attach_DD_Surface(&HiddenPage);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\tScreenHeight = 400;\n\n\tif (VisiblePage.Get_Height() == 480)\n\t\t{\n\t\tSeenBuff.Attach(&VisiblePage, 0, 40, 640, 400);\n\t\tHidPage.Attach(&HiddenPage, 0, 40, 640, 400);\n\t\t}\n\telse\n\t\t{\n\t\tSeenBuff.Attach(&VisiblePage, 0, 0, 640, 400);\n\t\tHidPage.Attach(&HiddenPage, 0, 0, 640, 400);\n\t\t}\n\n\treturn true;\n\t}\n\n\n/***********************************************************************************************\n * Prog_End -- Cleans up library systems in prep for game exit.                                *\n *                                                                                             *\n *    This routine should be called before the game terminates. It handles cleaning up         *\n *    library systems so that a graceful return to the host operating system is achieved.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef WIN32\nvoid __cdecl Prog_End(void)\n{\n\tSound_End();\n\tif (WWMouse) {\n\t\tdelete WWMouse;\n\t\tWWMouse = NULL;\n\t}\n\tif (WindowsTimer) {\n\t\t delete WindowsTimer;\n\t\t WindowsTimer = NULL;\n\t}\n}\n#else\t//WIN32\n\nvoid Prog_End(void)\n{\n\tif (Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) {\n\t\tNullModem.Change_IRQ_Priority(0);\n\t}\n\n\tSet_Video_Mode(RESET_MODE);\n\tRemove_Keyboard_Interrupt();\n\tRemove_Mouse();\n\tSound_End();\n\tRemove_Timer_System();\n}\n#endif\t//WIN32\n\n\nvoid Print_Error_End_Exit(char * string)\n{\n\tProg_End();\n\tprintf( \"%s\\n\", string );\n\texit(1);\n}\n\n\nvoid Print_Error_Exit(char * string)\n{\n\tprintf( \"%s\\n\", string );\n\texit(1);\n}\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Emergency_Exit -- Function to call when we want to exit unexpectedly.                       *\n *                   Use this function instead of exit(n) so everything is properly cleaned up.*\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Code to return to the OS                                                          *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/13/97 1:32AM ST : Created                                                              *\n *=============================================================================================*/\nvoid Emergency_Exit ( int code )\n{\n\n#ifdef WIN32\n\n\t/*\n\t** Clear out the video buffers so we dont glitch when we lose focus\n\t*/\n\tVisiblePage.Clear();\n\tHiddenPage.Clear();\n\tBlackPalette.Set();\n\tMemory_Error_Exit = Print_Error_Exit;\n\n\t/*\n\t** Flag that this is an emergency shut down - not a clean shutdown but\n\t** not killed with Ctrl-Alt-Del either.\n\t*/\n\tReadyToQuit = 3;\n\n\t/*\n\t** Post a message to our message handler to tell it to clean up.\n\t*/\n\tPostMessage(MainWindow, WM_DESTROY, 0, 0);\n\n\t/*\n\t** Wait until the message handler has dealt with the message\n\t*/\n\tdo\n\t{\n\t\tKeyboard->Check();\n\t}while (ReadyToQuit == 3);\n\n\n#else\t//WIN32\n\t/*\n\t** Do the DOS end\n\t*/\n\tProg_End();\n\n#endif\t//WIN32\n\n\texit ( code );\n}\n\n\n\n\n\n\n\n\n\n\n\n#ifdef WIN32\n\n/***********************************************************************************************\n * Read_Setup_Options -- Read stuff in from the INI file that we need to know sooner           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Ptr to config file class                                                          *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/7/96 4:09PM ST : Created                                                               *\n *   09/30/1996 JLB : Uses INI class.                                                          *\n *=============================================================================================*/\nvoid Read_Setup_Options( RawFileClass *config_file )\n{\n\tif (config_file->Is_Available()) {\n\n\t\tINIClass ini;\n\n\t\tini.Load(*config_file);\n\n\t\t/*\n\t\t** Read in the boolean options\n\t\t*/\n\t\tVideoBackBufferAllowed = ini.Get_Bool(\"Options\", \"VideoBackBuffer\", true);\n\t\tAllowHardwareBlitFills = ini.Get_Bool(\"Options\", \"HardwareFills\", true);\n\t\tScreenHeight = ini.Get_Bool(\"Options\", \"Resolution\", false) ? 480 : 400;\n\n\t\t/*\n\t\t** See if an alternative socket number has been specified\n\t\t*/\n\t\tint socket = ini.Get_Int(\"Options\", \"Socket\", 0);\n\t\tif (socket >0 ) {\n\t\t\tsocket += 0x4000;\n\t\t\tif (socket >= 0x4000 && socket < 0x8000) {\n\t\t\t\tIpx.Set_Socket (socket);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** See if a destination network has been specified\n\t\t*/\n\t\tchar netbuf [512];\n\t\tmemset(netbuf, 0, sizeof(netbuf));\n\t\tchar * netptr = netbuf;\n\t\tbool found = ini.Get_String(\"Options\", \"DestNet\", NULL, netbuf, sizeof(netbuf));\n\n\t\tif (found && netptr != NULL && strlen(netbuf)) {\n\t\t\tNetNumType net;\n\t\t\tNetNodeType node;\n\n\t\t\t/*\n\t\t\t** Scan the string, pulling off each address piece\n\t\t\t*/\n\t\t\tint i = 0;\n\t\t\tchar * p = strtok(netbuf,\".\");\n\t\t\tint x;\n\t\t\twhile (p != NULL) {\n\t\t\t\tsscanf(p,\"%x\",&x);\t\t\t// convert from hex string to int\n\t\t\t\tif (i < 4) {\n\t\t\t\t\tnet[i] = (char)x;\t\t\t// fill NetNum\n\t\t\t\t} else {\n\t\t\t\t\tnode[i-4] = (char)x;\t\t// fill NetNode\n\t\t\t\t}\n\t\t\t\ti++;\n\t\t\t\tp = strtok(NULL,\".\");\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If all the address components were successfully read, fill in the\n\t\t\t** BridgeNet with a broadcast address to the network across the bridge.\n\t\t\t*/\n\t\t\tif (i >= 4) {\n\t\t\t\tSession.IsBridge = 1;\n\t\t\t\tmemset(node, 0xff, 6);\n\t\t\t\tSession.BridgeNet = IPXAddressClass(net, node);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid Get_OS_Version (void)\n{\n\n\tWindowsNT = ((GetVersion() & 0x80000000) == 0) ? true : false;\n\n#if (0)\n\tOSVERSIONINFO\tosversion;\n\tif ( GetVersionEx (&osversion) ){\n\t\tWindowsNT = (osversion.dwPlatformId == VER_PLATFORM_WIN32_NT) ? true : false;\n\t\tOutputDebugString (\"RA95 - Got OS version\\n\");\n\t}else{\n\t\tOutputDebugString (\"RA95 - Failed to get OS version\\n\");\n\t\tchar fuck [128];\n\t\tsprintf (fuck,\"RA95 - Error code is %d\\n\", GetLastError());\n\t\tOutputDebugString (fuck);\n\n\t}\n#endif\t//(0)\n\n}\n\n\n#endif\t//WIN32\n\n\n"
  },
  {
    "path": "CODE/STATBTN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/STATBTN.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TEXTBTN.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 19, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   StaticButtonClass::Draw_Background -- Draws the background to the text button.            *\n *   StaticButtonClass::Draw_Me -- Draws the text buttons as indicated.                        *\n *   StaticButtonClass::Draw_Text -- This draws the text for the text button.                  *\n *   StaticButtonClass::Set_Text -- Assigns a new text string to this button.                  *\n *   StaticButtonClass::StaticButtonClass -- Normal constructor for a text button.             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n#include \"statbtn.h\"\n\n\n/***********************************************************************************************\n * StaticButtonClass::StaticButtonClass -- Normal constructor for a text button.               *\n *                                                                                             *\n *    This is the constructor for text buttons if the text is provided as a string pointer.    *\n *                                                                                             *\n * INPUT:   id    -- The ID number to assign to this button.                                   *\n *                                                                                             *\n *          text  -- Pointer to the text string to display on top of the button.               *\n *                                                                                             *\n *          x,y   -- Pixel coordinate of button's upper left corner.                           *\n *                                                                                             *\n *          w,h   -- Dimensions of the button. If these are not filled in (or with -1), then   *\n *                   the dimensions are adapted to fit the text assigned to the button.        *\n *                                                                                             *\n *          style -- The print style for the text in the button. These are the TPF_ flags      *\n *                   used by Fancy_Text_Print().                                               *\n *                                                                                             *\n * OUTPUT:   none                                                                              *\n *                                                                                             *\n * WARNINGS: Call Set_Text & Set_Style, & init X,Y,Width,Height,ID before using this button.\t  *\n *                                                                                             *\n * HISTORY:  01/15/1995 JLB : Created.                                                         *\n *=============================================================================================*/\nStaticButtonClass::StaticButtonClass(unsigned , char const * text, TextPrintType style, int x, int y, int w, int h) :\n\tGadgetClass(x, y, w, h, FlagEnum(0)),\n\tString(NULL),\n\tPrintFlags(style)\n{\n\t/*\n\t**\tMake a duplicate of the string to display.\n\t*/\n\tSet_Text(text, false);\n\n\tif (w == -1 || h == -1) {\n\t\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, PrintFlags);\n\t\tif (w == -1) {\n\t\t\tWidth = String_Pixel_Width(String);\n\t\t}\n\t\tif (h == -1) {\n\t\t\tHeight = FontHeight;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * StaticButtonClass::StaticButtonClass -- Default constructor for a text button.              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:   none                                                                              *\n *                                                                                             *\n * WARNINGS: none                                                                              *\n *                                                                                             *\n * HISTORY:  01/15/1995 JLB : Created.                                                         *\n *=============================================================================================*/\nStaticButtonClass::StaticButtonClass(void) :\n\tGadgetClass(0, 0, 0, 0, FlagEnum(0)),\n\tString(NULL),\n\tPrintFlags(TPF_8POINT)\n{\n}\n\n\n/***********************************************************************************************\n * StaticButtonClass::Draw_Me -- Draws the text buttons as indicated.                          *\n *                                                                                             *\n *    This routine will draw the text button.                                                  *\n *                                                                                             *\n * INPUT:   forced   -- If the button is to be redrawn regardless of the state of the redraw   *\n *                      flag, then this parameter will be true.                                *\n *                                                                                             *\n * OUTPUT:  bool; Was the button redrawn?                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/03/1995 MML : Created.                                                                 *\n *   01/16/1995 JLB : Modified                                                                 *\n *=============================================================================================*/\nint StaticButtonClass::Draw_Me(int forced)\n{\n\tif (GadgetClass::Draw_Me(forced)) {\n\t\t/*\n\t\t**\tHide the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Hide_Mouse(X, Y, X+Width-1, Y+Height-1);\n\t\t}\n\n\t\t/*\n\t\t**\tDraw the background and overlaying text. These are virtual function\n\t\t**\tcalls so that they may be overridden.\n\t\t*/\n\t\tDraw_Background();\n\t\tDraw_Text(String);\n\n\t\t/*\n\t\t**\tDisplay the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Show_Mouse();\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * StaticButtonClass::Set_Text -- Assigns a new text string to this button.                    *\n *                                                                                             *\n *    Use this routine to assign a new text string to this button. By using this function it   *\n *    is possible to dynamically change the button's text. An example of this would be an      *\n *    on/off button that every time it is clicked, the text toggles between \"on\" and \"off\".    *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text string to assign to this button.                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The text is NOT copied to this button. You must make sure that the text         *\n *             remains valid throughout the lifetime of this text button.                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid StaticButtonClass::Set_Text(char const * text, bool resize)\n{\n\tif (String != NULL) {\n\t\tdelete [] String;\n\t\tString = NULL;\n\t}\n\n\tif (text != NULL) {\n\t\tString = new char[strlen(text)+1];\n\t\tif (String != NULL) {\n\t\t\tstrcpy(String, text);\n\t\t}\n\t}\n\n\tFlag_To_Redraw();\n\tif (resize && String != NULL) {\n\t\tDraw_Background();\n\t\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, PrintFlags);\n\t\tWidth = String_Pixel_Width(String);\n\t\tHeight = FontHeight + FontYSpacing;\n\t\tBackground = Buffer();\n\t}\n}\n\n\n/***********************************************************************************************\n * StaticButtonClass::Draw_Background -- Draws the background to the text button.              *\n *                                                                                             *\n *    This localizes the drawing of the background for the text button. By overriding this     *\n *    function you can give a different background to the button. The text is drawn using      *\n *    a different routine. The mouse is hidden, if necessary, before this routine is called.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid StaticButtonClass::Draw_Background(void)\n{\n\t/*\n\t**\tIf the background hasn't been recorded from the buffer, then\n\t**\tallocate and record the background image now.\n\t*/\n\tif (Background.Get_Buffer() == NULL && Width > 0 && Height > 0) {\n\t\tnew(&Background) Buffer(Width*Height);\n\t\tif (Background.Get_Buffer() != NULL) {\n\t\t\tLogicPage->To_Buffer(X, Y, Width, Height, Background, Background.Get_Size());\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is a background image present, then restore it to the buffer now.\n\t*/\n\tif (Background.Get_Buffer() != NULL && LogicPage->Lock()) {\n\t\tBuffer_To_Page(X, Y, Width, Height, Background, *LogicPage);\n\t\tLogicPage->Unlock();\n\t}\n}\n\n\n/***********************************************************************************************\n * StaticButtonClass::Draw_Text -- This draws the text for the text button.                    *\n *                                                                                             *\n *    This routine draws the text for the text button. You can override this routine if you    *\n *    wish different text rendering styles or colors. The background has already been drawn    *\n *    by the time this function is called. The mouse is hidden, if necessary, as well.         *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text string to print over the button.                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid StaticButtonClass::Draw_Text(char const * text)\n{\n\t/*\n\t**\tDisplay the text.\n\t*/\n\tif (String != NULL) {\n\t\tint x = X;\n\n\t\tif (PrintFlags & TPF_CENTER) {\n\t\t\tx += Width/2;\n\t\t}\n\t\tif (PrintFlags & TPF_RIGHT) {\n\t\t\tx += Width-1;\n\t\t}\n\n\t\tFancy_Text_Print(text, x, Y, GadgetClass::Get_Color_Scheme(), TBLACK, PrintFlags);\n\t}\n}\n"
  },
  {
    "path": "CODE/STATBTN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/STATBTN.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : STATBTN.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef STATBTN_H\n#define STATBTN_H\n\n#include\t\"gadget.h\"\n#include\t\"buff.h\"\n\nclass StaticButtonClass : public GadgetClass\n{\n\tpublic:\n\t\tStaticButtonClass(void);\n\t\tStaticButtonClass(unsigned id, char const * text, TextPrintType style, int x, int y, int w=-1, int h=-1);\n\t\tvirtual int Draw_Me(int forced=false);\n\t\tvirtual void Set_Text(char const * text, bool resize = false);\n\n\tprotected:\n\n\t\tvirtual void Draw_Background(void);\n\t\tvirtual void Draw_Text(char const * text);\n\n\t\t/*\n\t\t**\tIf a background is to be preserved for this button, then this will point to\n\t\t**\ta buffer that holds a pristine background image.\n\t\t*/\n\t\tBuffer Background;\n\n\t\t/*\n\t\t**\tThis points to a copy of the string that is used for the button's text.\n\t\t*/\n\t\tchar * String;\n\n\t\t/*\n\t\t**\tThis is the print flags to use when rendering this button's text.\n\t\t*/\n\t\tTextPrintType PrintFlags;\n};\n\n#endif\n\n"
  },
  {
    "path": "CODE/STATS.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : WINSTUB.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 05/29/1996                                                   *\n *                                                                                             *\n *                  Last Update : May 29th 1996 [ST]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *  Internet game statistics to collect and upload to the server                               *\n *                                                                                             *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifdef WIN32\n\n#include\t\"function.h\"\n#include \"tcpip.h\"\n#include \"packet.h\"\n#include \"ccdde.h\"\n\n#define FIELD_PACKET_TYPE\t\t\t\t\t\t\"TYPE\"\n#define FIELD_GAME_ID\t\t\t\t\t\t\t\"IDNO\"\n#define FIELD_START_CREDITS\t\t\t\t\t\t\"CRED\"\n#define FIELD_BASES\t\t\t\t\t\t\t\t\"BASE\"\n#define FIELD_TIBERIUM\t\t\t\t\t\t\t\"TIBR\"\n#define FIELD_CRATES\t\t\t\t\t\t\t\"CRAT\"\n#define FIELD_AI_PLAYERS\t\t\t\t\t\t\"AIPL\"\n#define FIELD_CAPTURE_THE_FLAG\t\t\t\t\t\"FLAG\"\n#define FIELD_START_UNIT_COUNT\t\t\t\t\t\"UNIT\"\n#define FIELD_TECH_LEVEL\t\t\t\t\t\t\"TECH\"\n#define FIELD_SCENARIO\t\t\t\t\t\t\t\"SCEN\"\n#define FIELD_COMPLETION\t\t\t\t\t\t\"CMPL\"\n#define FIELD_START_TIME\t\t\t\t\t\t\"TIME\"\n#define FIELD_GAME_DURATION\t\t\t\t\t\t\"DURA\"\n#define FIELD_FRAME_RATE\t\t\t\t\t\t\"AFPS\"\n#define FIELD_SPEED_SETTING\t\t\t\t\t\t\"SPED\"\n#define FIELD_GAME_VERSION\t\t\t\t\t\t\"VERS\"\n#define FIELD_GAME_BUILD_DATE\t\t\t\t\t\"DATE\"\n#define FIELD_COVERT_PRESENT\t\t\t\t\t\"COVT\"\n#define FIELD_CPU_TYPE\t\t\t\t\t\t\t\"PROC\"\n#define FIELD_MEMORY\t\t\t\t\t\t\t\"MEMO\"\n#define FIELD_VIDEO_MEMORY\t\t\t\t\t\t\"VIDM\"\n#define FIELD_SHADOW_REGROWS\t\t\t\t\t\"SHAD\"\n\n#ifdef WOLAPI_INTEGRATION\n#define FIELD_HOSTORNOT\t\t\t\t\t\t\t\"SDFX\"\n#define FIELD_TOURNAMENT\t\t\t\t\t\t\"TRNY\"\n#define FIELD_NUM_INITIAL_PLAYERS\t\t\t\t\"NUMP\"\n#define FIELD_NUM_REMAINING_PLAYERS\t\t\t\t\"REMN\"\n#define FIELD_DISCONNECT_PINGS\t\t\t\t\t\"PING\"\n#define FIELD_COMPUTERTOOKOVER\t\t\t\t\t\"QUIT\"\n//#define FIELD_HARDWARE_GUID\t\t\t\t\t\"GUID\"\n#define FIELD_PLAYER1_IP\t\t\t\t\t\t\"ADR1\"\n#define FIELD_PLAYER2_IP\t\t\t\t\t\t\"ADR2\"\n#endif\n\n//\tajw The following were never used (thank god).\n#define FIELD_PLAYER1_HANDLE\t\t\t\t\t\"NAM1\"\n#define FIELD_PLAYER2_HANDLE\t\t\t\t\t\"NAM2\"\n#define FIELD_PLAYER1_TEAM\t\t\t\t\t\t\"SID1\"\n#define FIELD_PLAYER2_TEAM\t\t\t\t\t\t\"SID2\"\n#define FIELD_PLAYER1_COLOR\t\t\t\t\t\t\"COL1\"\n#define FIELD_PLAYER2_COLOR\t\t\t\t\t\t\"COL2\"\n#define FIELD_PLAYER1_CREDITS\t\t\t\t\t\"CRD1\"\n#define FIELD_PLAYER2_CREDITS\t\t\t\t\t\"CRD2\"\n\n#define FIELD_PLAYER1_UNITS_LEFT\t\t\t\t\"UNL1\"\n#define FIELD_PLAYER2_UNITS_LEFT\t\t\t\t\"UNL2\"\n#define FIELD_PLAYER1_INFANTRY_LEFT\t\t\t\t\"INL1\"\n#define FIELD_PLAYER2_INFANTRY_LEFT\t\t\t\t\"INL2\"\n#define FIELD_PLAYER1_PLANES_LEFT\t\t\t\t\"PLL1\"\n#define FIELD_PLAYER2_PLANES_LEFT\t\t\t\t\"PLL2\"\n#define FIELD_PLAYER1_BUILDINGS_LEFT\t\t\t\"BLL1\"\n#define FIELD_PLAYER2_BUILDINGS_LEFT\t\t\t\"BLL2\"\n#define FIELD_PLAYER1_VESSELS_LEFT\t\t\t\t\"VSL1\"\n#define FIELD_PLAYER2_VESSELS_LEFT\t\t\t\t\"VSL2\"\n\n#define FIELD_PLAYER1_UNITS_BOUGHT\t\t\t\t\"UNB1\"\n#define FIELD_PLAYER2_UNITS_BOUGHT\t\t\t\t\"UNB2\"\n#define FIELD_PLAYER1_INFANTRY_BOUGHT\t\t\t\"INB1\"\n#define FIELD_PLAYER2_INFANTRY_BOUGHT\t\t\t\"INB2\"\n#define FIELD_PLAYER1_PLANES_BOUGHT\t\t\t\t\"PLB1\"\n#define FIELD_PLAYER2_PLANES_BOUGHT\t\t\t\t\"PLB2\"\n#define FIELD_PLAYER1_BUILDINGS_BOUGHT\t\t\t\"BLB1\"\n#define FIELD_PLAYER2_BUILDINGS_BOUGHT\t\t\t\"BLB2\"\n#define FIELD_PLAYER1_VESSELS_BOUGHT\t\t\t\"VSB1\"\n#define FIELD_PLAYER2_VESSELS_BOUGHT\t\t\t\"VSB2\"\n\n#define FIELD_PLAYER1_UNITS_KILLED\t\t\t\t\"UNK1\"\n#define FIELD_PLAYER2_UNITS_KILLED\t\t\t\t\"UNK2\"\n#define FIELD_PLAYER1_INFANTRY_KILLED\t\t\t\"INK1\"\n#define FIELD_PLAYER2_INFANTRY_KILLED\t\t\t\"INK2\"\n#define FIELD_PLAYER1_PLANES_KILLED\t\t\t\t\"PLK1\"\n#define FIELD_PLAYER2_PLANES_KILLED\t\t\t\t\"PLK2\"\n#define FIELD_PLAYER1_BUILDINGS_KILLED\t\t\t\"BLK1\"\n#define FIELD_PLAYER2_BUILDINGS_KILLED\t\t\t\"BLK2\"\n#define FIELD_PLAYER1_VESSELS_KILLED\t\t\t\"VSK1\"\n#define FIELD_PLAYER2_VESSELS_KILLED\t\t\t\"VSK2\"\n\n#define FIELD_PLAYER1_BUILDINGS_CAPTURED\t\t\"BLC1\"\n#define FIELD_PLAYER2_BUILDINGS_CAPTURED\t\t\"BLC2\"\n\n#define FIELD_PLAYER1_CRATES_FOUND\t\t\t\t\"CRA1\"\n#define FIELD_PLAYER2_CRATES_FOUND\t\t\t\t\"CRA2\"\n#define FIELD_PLAYER1_HARVESTED\t\t\t\t\t\"HRV1\"\n#define FIELD_PLAYER2_HARVESTED\t\t\t\t\t\"HRV2\"\n\n\n#define\tPACKET_TYPE_HOST_GAME_INFO\t\t(unsigned char) 50\n#define\tPACKET_TYPE_GUEST_GAME_INFO\t\t(unsigned char) 51\n\n//\tNote: These enums match those in the game results server code.\nenum {\n\tCOMPLETION_CONNECTION_LOST,\n\tCOMPLETION_PLAYER_1_WON,\n\tCOMPLETION_PLAYER_1_WON_BY_RESIGNATION,\n\tCOMPLETION_PLAYER_1_WON_BY_DISCONNECTION,\n\tCOMPLETION_PLAYER_2_WON,\n\tCOMPLETION_PLAYER_2_WON_BY_RESIGNATION,\n\tCOMPLETION_PLAYER_2_WON_BY_DISCONNECTION,\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\tCOMPLETION_WASH = 64,\n#endif\n};\n\n\nextern unsigned long \tPlanetWestwoodGameID;\nextern HINSTANCE\t\tProgramInstance;\nextern unsigned long \tPlanetWestwoodStartTime;\n\nextern \"C\" char\tCPUType;\n\n\nbool\t\t\tGameTimerInUse = false;\nTimerClass\tGameTimer;\nlong\t\t\tGameEndTime;\nvoid\t\t\t*PacketLater = NULL;\n\n#include \"WolDebug.h\"\n\n#ifdef WOLAPI_INTEGRATION\n#include \"WolapiOb.h\"\nextern WolapiObject* pWolapi;\n\nextern bool bReconnectDialogCancelled;\n#endif\n\n/***********************************************************************************************\n * Send_Statistics_To_Server -- sends internet game statistics to the Westeood server          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/29/96 12:38PM ST : Created                                                             *\n *=============================================================================================*/\n\nvoid Send_Statistics_Packet(void)\n{\n//\tdebugprint( \"Stats: Send_Statistics_Packet() called.\\n\" );\n#ifndef INTERNET_OFF // Denzil 5/4/98\n\n#ifdef WOLAPI_INTEGRATION\n\tif( !pWolapi )\t\t\t//\tShould no longer ever happen.\n\t\treturn;\n#endif\n\n\tPacketClass\tstats;\n\tHouseClass\t*player;\n\tstatic int\tpacket_size;\n\tint\t\t\tindex;\n\tbool\t\t\tpacket_later = false;\t// Should the packet be sent later\n\tvoid\t\t\t*packet;\n\n\tstatic char\tfield_player_handle[5] \t\t\t\t= { \"NAM?\" };\n\tstatic char\tfield_player_team[5] \t\t\t\t= { \"SID?\" };\n\tstatic char\tfield_player_color[5]\t\t\t\t= { \"COL?\" };\n\tstatic char field_player_credits[5]\t\t\t\t= { \"CRD?\" };\n\tstatic char field_player_units_left[5]\t\t\t= { \"UNL?\" };\n\tstatic char field_player_infantry_left[5]\t\t= { \"INL?\" };\n\tstatic char field_player_planes_left[5]\t\t= { \"PLL?\" };\n\tstatic char field_player_buildings_left[5]\t= { \"BLL?\" };\n\tstatic char field_player_vessels_left[5]\t\t= { \"VSL?\" };\n\tstatic char field_player_units_bought[5] \t\t= { \"UNB?\" };\n\tstatic char field_player_infantry_bought[5] \t= { \"INB?\" };\n\tstatic char field_player_planes_bought[5]\t\t= { \"PLB?\" };\n\tstatic char field_player_buildings_bought[5]\t= { \"BLB?\" };\n\tstatic char field_player_vessels_bought[5]\t= { \"VSB?\" };\n\tstatic char field_player_units_killed[5] \t\t= { \"UNK?\" };\n\tstatic char field_player_infantry_killed[5] \t= { \"INK?\" };\n\tstatic char field_player_planes_killed[5]\t\t= { \"PLK?\" };\n\tstatic char field_player_buildings_killed[5]\t= { \"BLK?\" };\n\tstatic char field_player_vessels_killed[5]\t= { \"VSK?\" };\n\tstatic char field_player_buildings_captured[5] = { \"BLC?\" };\n\tstatic char field_player_crates_found[5]\t\t= { \"CRA?\" };\n\tstatic char field_player_harvested[5]\t\t\t= { \"HRV?\" };\n\n\tstatic char *houses[] = {\n\t\t\"SPA\",\n\t\t\"GRE\",\n\t\t\"USS\",\n\t\t\"ENG\",\n\t\t\"ITA\",\n\t\t\"GER\",\n\t\t\"FRA\",\n\t\t\"TKY\",\n\t\t\"GUD\",\n\t\t\"BAD\",\n\t\t\"CIV\",\n\t\t\"JP \",\n\t\t\"M01\",\n\t\t\"M02\",\n\t\t\"M03\",\n\t\t\"M04\",\n\t\t\"M05\",\n\t\t\"M06\",\n\t\t\"M07\",\n\t\t\"M08\"\n\t};\n\n\tif (!PacketLater){\n\n\t\t/*\n\t\t** Field to identify this as C&C 95 internet game statistics packet\n\t\t*/\n#ifdef WOLAPI_INTEGRATION\n\t\tif( pWolapi->bGameServer )\n\t\t{\n\t\t\tstats.Add_Field( FIELD_HOSTORNOT, (unsigned char)0 );\t\t//\tReversed meaning of this for Neal.\n\t\t}else{\n\t\t\tstats.Add_Field( FIELD_HOSTORNOT, (unsigned char)1 );\n\t\t}\n#else\n\t\tif (Server){\n\t\t\tstats.Add_Field(FIELD_PACKET_TYPE, PACKET_TYPE_HOST_GAME_INFO);\n\t\t}else{\n\t\t\tstats.Add_Field(FIELD_PACKET_TYPE, PACKET_TYPE_GUEST_GAME_INFO);\n\t\t}\n#endif\n\n\t\t/*\n\t\t** Game ID. A unique game identifier assigned by WChat.\n\t\t*/\n\t\tstats.Add_Field(FIELD_GAME_ID, PlanetWestwoodGameID);\n\n#ifdef WOLAPI_INTEGRATION\n\n\t\t//\tNumber of players initially in game.\n\t\tstats.Add_Field( FIELD_NUM_INITIAL_PLAYERS, (unsigned long)pWolapi->GameInfoCurrent.iPlayerCount );\n//debugprint( \"Stats: number of initial players is %i\\n\", pWolapi->GameInfoCurrent.iPlayerCount );\n\n\t\t//\tNumber of players remaining in game. Not sure of what use this will be statistically...\n\t\tstats.Add_Field( FIELD_NUM_REMAINING_PLAYERS, (unsigned long)Session.Players.Count() );\n//debugprint( \"Stats: number of remaining players is %i\\n\", Session.Players.Count() );\n\n\t\t//\tWhether or not this was a tournament game.\n\t\tstats.Add_Field( FIELD_TOURNAMENT, (unsigned char)( pWolapi->GameInfoCurrent.bTournament ? 1 : 0 ) );\n\n//\tajw This is now in WOLAPI...\n//\t\t//\tA unique value that identifies the machine that the game was played on.\n//\t\tHW_PROFILE_INFO hwinfo;\n//\t\t::GetCurrentHwProfile( &hwinfo );\n//\t\tstats.Add_Field( FIELD_HARDWARE_GUID, hwinfo.szHwProfileGuid );\n#endif\n\n\t\t/*\n\t\t** Start credits.\n\t\t*/\n\t\tstats.Add_Field(FIELD_START_CREDITS, (unsigned long)Session.Options.Credits);\n\n\t\t/*\n\t\t** Bases (On/Off)\n\t\t*/\n\t\tstats.Add_Field(FIELD_BASES, Session.Options.Bases ? \"ON\" : \"OFF\");\n\n\t\t/*\n\t\t** Tiberium (On/Off)\n\t\t*/\n\t\tstats.Add_Field(FIELD_TIBERIUM, Session.Options.Tiberium ? \"ON\" : \"OFF\");\n\n\t\t/*\n\t\t** Crates (On/Off)\n\t\t*/\n\t\tstats.Add_Field(FIELD_CRATES, Session.Options.Goodies ? \"ON\" : \"OFF\");\n\n\t\t/*\n\t\t** AI Players (On/Off)\n\t\t*/\n\t\tstats.Add_Field(FIELD_AI_PLAYERS, (unsigned long) Session.Options.AIPlayers);\n\n\t\t/*\n\t\t** Shadow regrowth enabled\n\t\t*/\n\t\tstats.Add_Field(FIELD_SHADOW_REGROWS, Special.IsShadowGrow ? \"ON\" : \"OFF\" );\n\n\t\t/*\n\t\t** Capture the flag mode (On/Off)\n\t\t*/\n\t\tstats.Add_Field(FIELD_CAPTURE_THE_FLAG, Special.IsCaptureTheFlag ? \"ON\" : \"OFF\");\n\n\t\t/*\n\t\t** Start unit count\n\t\t*/\n\t\tstats.Add_Field(FIELD_START_UNIT_COUNT, (unsigned long)Session.Options.UnitCount);\n\n\t\t/*\n\t\t** Tech level.\n\t\t*/\n\t\tstats.Add_Field(FIELD_TECH_LEVEL, (unsigned long)BuildLevel);\n\n\t\t/*\n\t\t** Scenario\n\t\t*/\n#if (1)\n\n\t\tstats.Add_Field(FIELD_SCENARIO, Session.Options.ScenarioDescription);\n\n#else //(1)\n\t\tchar fname[128];\n\t\tchar namebuffer[40];\n\t\tchar *abuffer = (char *)_ShapeBuffer;\n\t\tmemset(abuffer, '\\0', _ShapeBufferSize);\n\t\tsprintf(fname,\"%s.INI\",Scen.ScenarioName);\n\t\tCCFileClass fileo;\n\t\tfileo.Set_Name (fname);\n\t\tfileo.Read(abuffer, _ShapeBufferSize-1);\n\t\tfileo.Close();\n\t\tWWGetPrivateProfileString(\"Basic\", \"Name\", \"Nulls-Ville\", namebuffer, 40, abuffer);\n\t\tstats.Add_Field(FIELD_SCENARIO, namebuffer);\n\t\t//stats.Add_Field(FIELD_SCENARIO, MPlayerScenarios[ScenarioIdx]);\n#endif\t//(1)\n\n#ifdef WOLAPI_INTEGRATION\n\t\t//\tCompletion status is set for Tournament games only - ajw.\n\t\tif( pWolapi->GameInfoCurrent.bTournament )\n\t\t{\n#endif\n\n\t\t\t/*\n\t\t\t** Game completion status.\t\t\n\t\t\t**\n\t\t\t**  Connection lost.\n\t\t\t**  Player 1 won\n\t\t\t**  Player 2 won\n\t\t\t**  Player 1 won by resignation\n\t\t\t**  Player 2 won by resignation\n\t\t\t**  Player 1 aborted\n\t\t\t**  Player 2 aborted\n\t\t\t**\n\t\t\t**\tGame was a draw\n\t\t\t*/\n\t\t\tHouseClass *player1 = NULL;\n\t\t\tHouseClass *player2 = NULL;\n\t\t\tfor (int h=0 ; h<Session.Players.Count(); h++){\n\t\t\t\tHouseClass *ptr = HouseClass::As_Pointer ((HousesType)(h + HOUSE_MULTI1));\n\t\t\t\tif (ptr->IsHuman){\n\t\t\t\t\tif (player1){\n\t\t\t\t\t\tplayer2 = ptr;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}else{\n\t\t\t\t\t\tplayer1 = ptr;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tint completion = -1;\n\n\t\t\tif (player1 && player2){\t\t\t//\tCan this ever fail?\t\tajw\n#ifdef FIXIT_VERSION_3\n\t\t\t\t//\tSend IP addresses of both players.\n\t\t\t\tNetNumType net;\n\t\t\t\tNetNodeType node;\n\t\t\t\tchar szIPAddress[ 30 ];\n\t\t\t\tSession.Players[ 0 ]->Address.Get_Address( net, node );\n\t\t\t\tsprintf( szIPAddress, \"%i.%i.%i.%i\", node[0], node[1], node[2], node[3] );\n\t\t\t\tif( strcmp( szIPAddress, \"255.255.255.255\" ) == 0 )\n\t\t\t\t{\n\n\t\t\t\t\t//\tOk. It's not set. Let's try to get it ourselves...\n\t\t\t\t\tchar szHostName[ 512 ];\n\t\t\t\t\tint iRes = gethostname( szHostName, 512 );\n\t\t\t\t\tif( iRes != SOCKET_ERROR )\t//\telse forget about trying\n\t\t\t\t\t{\n//\t\t\t\t\t\tdebugprint( \"gethostname got me %s\\n\", szHostName );\n\t\t\t\t\t\tstruct hostent* pHostent = gethostbyname( szHostName );\n\t\t\t\t\t\tif( pHostent )\t//\telse forget about trying\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint i = 0;\n\t\t\t\t\t\t\tint* piAddress = (int*)pHostent->h_addr_list[ i ];\n\t\t\t\t\t\t\twhile( piAddress )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t//\tThere is a non-null value for this h_addr_list entry.\n\t\t\t\t\t\t\t\tchar szAsciiIP[ 30 ];\n\t\t\t\t\t\t\t\tstrcpy( szAsciiIP, inet_ntoa( *( (struct in_addr*)piAddress ) ) );\n\t\t\t\t\t\t\t\t//\tWe have an address in the right form.\n\t\t\t\t\t\t\t\t//\tNow, is it an address in a private network? If so we should ignore it.\n\t\t\t\t\t\t\t\tunsigned char q1 = ( (char*)piAddress )[ 0 ];\t//\tFirst digit.\n\t\t\t\t\t\t\t\tunsigned char q2 = ( (char*)piAddress )[ 1 ];\t//\tSecond digit.\n//\t\t\t\t\t\t\t\tdebugprint( \"ip: %s\\n\", szAsciiIP );\n\t\t\t\t\t\t\t\tif( q1 == 10 || ( q1 == 172 && ( q2 >= 16 && q2 <= 31 ) ) || ( q1 == 192 && q2 == 168 ) )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t//\tThis is a private network address - ignore it and go on to next.\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tstrcpy( szIPAddress, szAsciiIP );\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tpiAddress = (int*)pHostent->h_addr_list[ ++i ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n//\t\t\t\t\t\telse\n//\t\t\t\t\t\t\tdebugprint( \"gethostbyname failed. Error %i\\n\", WSAGetLastError() );\n\t\t\t\t\t}\n//\t\t\t\t\telse\n//\t\t\t\t\t\tdebugprint( \"gethostname failed with %i, error %i\\n\", iRes, WSAGetLastError() );\n\t\t\t\t}\n\t\t\t\tstats.Add_Field( FIELD_PLAYER1_IP, (char*)szIPAddress );\n\t\t\t\tSession.Players[ 1 ]->Address.Get_Address( net, node );\n\t\t\t\tsprintf( szIPAddress, \"%i.%i.%i.%i\", node[0], node[1], node[2], node[3] );\n\t\t\t\tstats.Add_Field( FIELD_PLAYER2_IP, (char*)szIPAddress );\n#endif\t\t\t\t\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t\t\tif( Scen.bLocalProposesDraw && Scen.bOtherProposesDraw )\n\t\t\t\t{\n\t\t\t\t\tcompletion = COMPLETION_WASH;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n#endif\n\t\t\t\tif (ConnectionLost){\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\t\tif( bReconnectDialogCancelled )\n\t\t\t\t\t{\n\t\t\t\t\t\tif( Session.Players[ 0 ]->Player.ID == HOUSE_MULTI1 )\n\t\t\t\t\t\t\t//\tI am player1.\n\t\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_2_WON_BY_DISCONNECTION;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_1_WON_BY_DISCONNECTION;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tcompletion = COMPLETION_CONNECTION_LOST;\n\t\t\t\t\t\tif( pWolapi->bDisconnectPingingCompleted )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tchar szPingResult[ 8 ];\t\t//\tFormat is \"x/y a/b\", e.g., \"3/5 4/5\"\n\t\t\t\t\t\t\tpWolapi->DisconnectPingResultsString( szPingResult );\n\t\t\t\t\t\t\tstats.Add_Field( FIELD_DISCONNECT_PINGS, (char*)szPingResult );\n\t\t\t\t\t\t}\n//\t\t\t\t\t\telse\n//\t\t\t\t\t\t\tdebugprint( \"Stats: bDisconnectPingingCompleted is false! Should be finished!!!!!!!!!!!!!!!\\n\" );\n\t\t\t\t\t}\n#else\n\t\t\t\t\tcompletion = COMPLETION_CONNECTION_LOST;\n#endif\n\t\t\t\t}else{\n\n\t\t\t\t\tif (player1->IsGiverUpper){\n\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_2_WON_BY_DISCONNECTION;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (player2->IsGiverUpper){\n\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_1_WON_BY_DISCONNECTION;\n\t\t\t\t\t}\n\n\n\t\t\t\t\tif (player2->IsDefeated){\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Player 1 won. Find out how.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_1_WON;\n\t\t\t\t\t\tif (player2->IsResigner){\n\t\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_1_WON_BY_RESIGNATION;\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tif (player2->IsGiverUpper){\n\t\t\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_1_WON_BY_DISCONNECTION;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t}else{\n\n\t\t\t\t\t\tif (player1->IsDefeated){\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Player 2 won. Find out how.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_2_WON;\n\t\t\t\t\t\t\tif (player1->IsResigner){\n\t\t\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_2_WON_BY_RESIGNATION;\n\t\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t\tif (player1->IsGiverUpper){\n\t\t\t\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_2_WON_BY_DISCONNECTION;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t\t\t}\n#endif\n\t\t\t}\n\n\t\t\tstats.Add_Field (FIELD_COMPLETION, (char) completion);\n//debugprint( \"Stats: Tournament game completion value: %i\\n\", completion );\n\n#ifdef WOLAPI_INTEGRATION\n\t\t}\n#endif\n\n\n\t\t/*\n\t\t** Game start time (GMT or Pacific?)\n\t\t**\n\t\t** Passed from WChat\n\t\t*/\n\t\tstats.Add_Field (FIELD_START_TIME, (long) PlanetWestwoodStartTime);\n\n\t\t/*\n\t\t** Game duration (seconds).\n\t\t*/\n\t\tstats.Add_Field (FIELD_GAME_DURATION, (long) GameEndTime/60);\n\n\t\t/*\n\t\t** Avg. frame rate.\n\t\t*/\n#ifdef FIXIT_IP_CRASH\n\t\tlong divisor = GameEndTime / 60;\n\t\tif (divisor != 0) {\n\t\t\tstats.Add_Field (FIELD_FRAME_RATE, (long) Frame / (GameEndTime/60) );\n\t\t} else {\n\t\t\tstats.Add_Field (FIELD_FRAME_RATE, 0l);\n\t\t}\n#else\n\t\tstats.Add_Field (FIELD_FRAME_RATE, (long) Frame / (GameEndTime/60) );\n#endif\n\n\n\t\t/*\n\t\t** CPU type\n\t\t*/\n\t\tstats.Add_Field (FIELD_CPU_TYPE, (char)CPUType);\n\n\t\t/*\n\t\t** Memory\n\t\t*/\n\t\tMEMORYSTATUS\tmem_info;\n\t\tmem_info.dwLength=sizeof(mem_info);\n\t\tGlobalMemoryStatus(&mem_info);\n\t\tstats.Add_Field (FIELD_MEMORY, (long)mem_info.dwTotalPhys);\n\n\t\t/*\n\t\t** Video memory\n\t\t*/\n\t\tDDCAPS\tvideo_capabilities;\n\t\tlong\t\tvideo_memory;\n\n\t\tif (DirectDrawObject){\n\t\t\tvideo_capabilities.dwSize = sizeof (video_capabilities);\n\t\t\tif (DD_OK == DirectDrawObject->GetCaps (&video_capabilities , NULL)){\n\t\t\t\tvideo_memory = video_capabilities.dwVidMemTotal;\n\t\t\t\tvideo_memory += 1024*1024 -1;\n\t\t\t\tvideo_memory &= 0xfff00000;\n\t\t\t\tstats.Add_Field (FIELD_VIDEO_MEMORY, (long) video_memory);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Game speed setting.\n\t\t*/\n\t\tstats.Add_Field (FIELD_SPEED_SETTING, (char)Options.GameSpeed);\n\n\t\t/*\n\t\t** Red Alert version/build date\n\t\t*/\n\t\tchar\tversion[128];\n\t\tsprintf (version, \"V%s\", VerNum.Version_Name() );\n\t\tstats.Add_Field (FIELD_GAME_VERSION, (char*)version);\n\n\t\tchar path_to_exe[280];\n\t\tFILETIME write_time;\t\t//File time is 64 bits\n\n\t\tGetModuleFileName (ProgramInstance, path_to_exe, 280);\n\t\tRawFileClass file;\n\t\tfile.Set_Name(path_to_exe);\n\t\tfile.Open();\n\t\tHANDLE handle = file.Get_File_Handle();\n\n\t\tif (handle != INVALID_HANDLE_VALUE){\n\t\t\tif (GetFileTime (handle, NULL, NULL, &write_time)){\n\t\t\t\twrite_time.dwLowDateTime = htonl (write_time.dwLowDateTime);\n\t\t\t\twrite_time.dwHighDateTime = htonl (write_time.dwHighDateTime);\n\t\t\t\tstats.Add_Field (FIELD_GAME_BUILD_DATE, (void*)&write_time, sizeof (write_time));\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Covert installed? (Yes/No)\n\t\t*/\n\t\t//stats.Add_Field(FIELD_COVERT_PRESENT, (char) Expansion_Present());\n\n\t\t/*\n\t\t** Build the player specific statistics\n\t\t**\n\t\t*/\n#ifdef WOLAPI_INTEGRATION\n\t\tfor (int house = 0 ; house < 8 ; house++){\n#else\n\t\tfor (int house = 0 ; house < 2 ; house++){\n#endif\n\t\t\tplayer = HouseClass::As_Pointer((HousesType) (house + HOUSE_MULTI1));\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\tif( !player )\n\t\t\t\tcontinue;\n#endif\n\n\t\t\t/*\n\t\t\t** Player handle.\n\t\t\t*/\n\t\t\tfield_player_handle[3] = '1' + (char)house;\n#ifdef WOLAPI_INTEGRATION\n\t\t\tstats.Add_Field (field_player_handle, (char*) player->InitialName);\n//debugprint( \"Stats: Player %i name %s\\n\", house, (char*) player->InitialName );\n//debugprint( \"Stats: Player %i ending name %s\\n\", house, (char*) player->IniName );\n#else\n\t\t\tstats.Add_Field (field_player_handle, (char*) player->IniName);\n#endif\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\t//\tWhether or not this player was taken over by the computer, due to his quitting the game.\n\t\t\tif( strcmp( player->IniName, player->InitialName ) )\n\t\t\t\tstats.Add_Field( FIELD_COMPUTERTOOKOVER, (unsigned char)1 );\n\t\t\telse\n\t\t\t\tstats.Add_Field( FIELD_COMPUTERTOOKOVER, (unsigned char)0 );\n#endif\n\t\t\t/*\n\t\t\t** Player team. (NOD or GDI)\n\t\t\t*/\n\t\t\tfield_player_team[3] = '1' + (char)house;\n\t\t\tstats.Add_Field (field_player_team, houses[player->ActLike]);\n\n\t\t\t/*\n\t\t\t** Player color\n\t\t\t*/\n\t\t\tfield_player_color[3] = '1' + (char)house;\n\t\t\tstats.Add_Field (field_player_color, (unsigned char) (player->Class->House - HOUSE_MULTI1));\n\n\t\t\t/*\n\t\t\t** Player end credits.\n\t\t\t*/\n\t\t\tfield_player_credits[3] = '1' + (char)house;\n\t\t\tstats.Add_Field (field_player_credits, player->Credits + player->Tiberium);\n\n\t\t\t/*\n\t\t\t** Number of each unit/building type built\n\t\t\t*/\n\t\t\tfield_player_infantry_bought[3] = '1' + (char)house;\n\t\t\tfield_player_units_bought[3] = '1' + (char)house;\n\t\t\tfield_player_planes_bought[3] = '1' + (char)house;\n\t\t\tfield_player_buildings_bought[3] = '1' + (char)house;\n\t\t\tfield_player_vessels_bought[3] = '1' + (char)house;\n\n\t\t\tplayer->InfantryTotals->To_Network_Format();\n\t\t\tplayer->UnitTotals->To_Network_Format();\n\t\t\tplayer->AircraftTotals->To_Network_Format();\n\t\t\tplayer->BuildingTotals->To_Network_Format();\n\t\t\tplayer->VesselTotals->To_Network_Format();\n\n\t\t\tstats.Add_Field (field_player_infantry_bought, (void*) player->InfantryTotals->Get_All_Totals(), player->InfantryTotals->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_units_bought, (void*) player->UnitTotals->Get_All_Totals(), player->UnitTotals->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_planes_bought, (void*) player->AircraftTotals->Get_All_Totals(), player->AircraftTotals->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_buildings_bought, (void*) player->BuildingTotals->Get_All_Totals(), player->BuildingTotals->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_vessels_bought, (void*) player->VesselTotals->Get_All_Totals(), player->VesselTotals->Get_Unit_Count()*4);\n\n\t\t\tplayer->InfantryTotals->To_PC_Format();\n\t\t\tplayer->UnitTotals->To_PC_Format();\n\t\t\tplayer->AircraftTotals->To_PC_Format();\n\t\t\tplayer->BuildingTotals->To_PC_Format();\n\n\t\t\t/*\n\t\t\t** Clear out the counts and use the space to count up the current number of units/buildings\n\t\t\t*/\n\t\t\tplayer->InfantryTotals->Clear_Unit_Total();\n\t\t\tplayer->AircraftTotals->Clear_Unit_Total();\n\t\t\tplayer->UnitTotals->Clear_Unit_Total();\n\t\t\tplayer->BuildingTotals->Clear_Unit_Total();\n\t\t\tplayer->VesselTotals->Clear_Unit_Total();\n\n\t\t\t/*\n\t\t\t** Number of units remaining to player\n\t\t\t*/\n\t\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass const * unit = Units.Ptr(index);\n\t\t\t\tif (player == unit->House){\n\t\t\t\t\tplayer->UnitTotals->Increment_Unit_Total (unit->Class->Type);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\tInfantryClass const * infantry = Infantry.Ptr(index);\n\t\t\t\tif (player == infantry->House && !infantry->Class->IsCivilian){\n\t\t\t\t\tplayer->InfantryTotals->Increment_Unit_Total (infantry->Class->Type);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\t\tAircraftClass const * aircraft = Aircraft.Ptr(index);\n\t\t\t\tif (player == aircraft->House){\t// &&\taircraft->Class->Type != AIRCRAFT_CARGO){\n\t\t\t\t\tplayer->AircraftTotals->Increment_Unit_Total (aircraft->Class->Type);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass const * building = Buildings.Ptr(index);\n\t\t\t\tif (player == building->House){\n\t\t\t\t\tplayer->BuildingTotals->Increment_Unit_Total (building->Class->Type);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass const * vessel = Vessels.Ptr(index);\n\t\t\t\tif (player == vessel->House){\n\t\t\t\t\tplayer->VesselTotals->Increment_Unit_Total (vessel->Class->Type);\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\tplayer->InfantryTotals->To_Network_Format();\n\t\t\tplayer->UnitTotals->To_Network_Format();\n\t\t\tplayer->AircraftTotals->To_Network_Format();\n\t\t\tplayer->BuildingTotals->To_Network_Format();\n\t\t\tplayer->VesselTotals->To_Network_Format();\n\n\t\t\tfield_player_infantry_left[3] = '1' + (char)house;\n\t\t\tfield_player_units_left[3] = '1' + (char)house;\n\t\t\tfield_player_planes_left[3] = '1' + (char)house;\n\t\t\tfield_player_buildings_left[3] = '1' + (char)house;\n#ifdef FIXIT_IP_STATS\n\t\t\tfield_player_vessels_left[3] = '1' + (char)house;\n#endif\n\t\t\tstats.Add_Field (field_player_infantry_left, (void*) player->InfantryTotals->Get_All_Totals(), player->InfantryTotals->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_units_left, (void*) player->UnitTotals->Get_All_Totals(), player->UnitTotals->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_planes_left, (void*) player->AircraftTotals->Get_All_Totals(), player->AircraftTotals->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_buildings_left, (void*) player->BuildingTotals->Get_All_Totals(), player->BuildingTotals->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_vessels_left, (void*) player->VesselTotals->Get_All_Totals(), player->VesselTotals->Get_Unit_Count()*4);\n\n\n\t\t\t/*\n\t\t\t** Number of enemy units/buildings of each type destroyed.\n\t\t\t*/\n\n\t\t\tplayer->DestroyedInfantry->To_Network_Format();\n\t\t\tplayer->DestroyedUnits->To_Network_Format();\n\t\t\tplayer->DestroyedAircraft->To_Network_Format();\n\t\t\tplayer->DestroyedBuildings->To_Network_Format();\n\t\t\tplayer->DestroyedVessels->To_Network_Format();\n\n\t\t\tfield_player_infantry_killed[3] = '1' + (char)house;\n\t\t\tfield_player_units_killed[3] = '1' + (char)house;\n\t\t\tfield_player_planes_killed[3] = '1' + (char)house;\n\t\t\tfield_player_buildings_killed[3] = '1' + (char)house;\n\t\t\tfield_player_vessels_killed[3] = '1' + (char)house;\n\n\t\t\tstats.Add_Field (field_player_infantry_killed, (void*) player->DestroyedInfantry->Get_All_Totals(), player->DestroyedInfantry->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_units_killed, (void*) player->DestroyedUnits->Get_All_Totals(), player->DestroyedUnits->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_planes_killed, (void*) player->DestroyedAircraft->Get_All_Totals(), player->DestroyedAircraft->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_buildings_killed, (void*) player->DestroyedBuildings->Get_All_Totals(), player->DestroyedBuildings->Get_Unit_Count()*4);\n#ifdef FIXIT_VERSION_3\n\t\t\tstats.Add_Field (field_player_vessels_killed, (void*) player->DestroyedVessels->Get_All_Totals(), player->DestroyedVessels->Get_Unit_Count()*4);\n#else\n\t\t\tstats.Add_Field (field_player_vessels_killed, (void*) player->DestroyedVessels->Get_All_Totals(), player->DestroyedBuildings->Get_Unit_Count()*4);\n#endif\n\n\n\t\t\t/*\n\t\t\t** Number and type of enemy buildings captured\n\t\t\t*/\n\t\t\tfield_player_buildings_captured[3] = '1' + (char)house;\n\t\t\tplayer->CapturedBuildings->To_Network_Format();\n\t\t\tstats.Add_Field (field_player_buildings_captured, (void*) player->CapturedBuildings->Get_All_Totals(), player->CapturedBuildings->Get_Unit_Count()*4);\n\n\t\t\t/*\n\t\t\t** Number of crates discovered and their contents\n\t\t\t*/\n\t\t\tfield_player_crates_found[3] = '1' + (char)house;\n\t\t\tplayer->TotalCrates->To_Network_Format();\n\t\t\tstats.Add_Field (field_player_crates_found, (void*) player->TotalCrates->Get_All_Totals(), player->TotalCrates->Get_Unit_Count()*4);\n\n\t\t\t/*\n\t\t\t** Amount of tiberium turned into credits\n\t\t\t*/\n\t\t\tfield_player_harvested[3] = '1' + (char)house;\n\t\t\tstats.Add_Field (field_player_harvested, (unsigned long) player->HarvestedCredits);\n\n\t\t}\n\n\t\t/*\n\t\t** Create the comms packet to be sent\n\t\t*/\n\t\tpacket = stats.Create_Comms_Packet(packet_size);\n\n#ifndef WOLAPI_INTEGRATION\t//\tajw - 'PacketLater' is no longer ever used.\n\t\t/*\n\t\t** If a player disconnected then dont send the packet at this time - save it for later\n\t\t*/\n\t\tif (completion == COMPLETION_PLAYER_1_WON_BY_DISCONNECTION\n\t\t\t|| completion == COMPLETION_PLAYER_2_WON_BY_DISCONNECTION){\n\t\t\tPacketLater = packet;\n\t\t\treturn;\n\t\t}\n#endif\n\n\t}else{\t\t//else for if (!PacketLater)\n\n\t\t/*\n\t\t** Send the packet we calculated earlier when the disconnect occurred\n\t\t*/\n\t\tpacket = PacketLater;\n\t\tPacketLater = NULL;\n\t}\n\n\t/*\n\t** Send it.....\n\t*/\n\tconst char* szGameResServer;\n\tint iPort;\n\tif( pWolapi->GameInfoCurrent.GameKind == CREATEGAMEINFO::AMGAME )\n\t{\n\t\tszGameResServer = pWolapi->szGameResServerHost2;\n\t\tiPort = pWolapi->iGameResServerPort2;\n\t}\n\telse\n\t{\n\t\tszGameResServer = pWolapi->szGameResServerHost1;\n\t\tiPort = pWolapi->iGameResServerPort1;\n\t}\n\n\tif( *szGameResServer )\n\t{\n\t\tif( pWolapi->pNetUtil->RequestGameresSend( szGameResServer, iPort, (unsigned char*)packet, packet_size ) != S_OK )\n\t\t\t//debugprint( \"RequestGameresSend( %s, %i ) failed!!!\\n\", szGameResServer, iPort );\n\t\t\t;\n\t}\n\n\t/*\n\t** Save it to disk as well so I can see it\n\t*/\n//\tRawFileClass anotherfile (\"packet.net\");\n//\tanotherfile.Write(packet, packet_size);\n//debugprint( \"Wrote out packet.net\\n\" );\n\n\t/*\n\t** Tidy up\n\t*/\n\tdelete [] packet;\n\n\tGameStatisticsPacketSent = true;\n#endif // INTERNET_OFF\n}\n\n\n\nvoid Register_Game_Start_Time(void)\n{\n\n\tGameTimer.Set (0, true);\n\tGameTimerInUse = true;\n}\n\nextern void Register_Game_End_Time(void)\n{\n\tGameEndTime = GameTimer.Time();\n\tGameTimerInUse = false;\n}\n\n\n#endif\t//WIN32\n"
  },
  {
    "path": "CODE/STD.LNT",
    "content": "//  Watcom C, C++ (32 bit), -si4 -sp4,\n//  Standard lint options\n\n//    Compiler Options for Watcom C, C++ 32 bit\n\n-cwc\n\n//    This file contains options to allow PC-lint to process source\n//    files for your compiler.  It is used as follows:\n//\n//    lint  co-wc32.lnt  source-file(s)\n//\n-d_M_IX86=200   // assume Intel 80286 architecture -- modify to suit\n-d__declspec()= // ignore this construct\n\n  // additional reserve words needed\n+rw(_loadds,_export)\n+rw(__interrupt,__near,__far,__huge,__fortran,__pascal,__cdecl)\n+rw(__export,__loadds,__saveregs,__asm,__fastcall,__stdcall)\n+rw(_export)\n\n+fcd            // makes cdecl significant -- used for proto generation\n+fcu            // chars are by default unsigned\n+fsu            // so are strings\n-d__386__       // pre-defined macro for 386 version, not set by -cwc\n-d__FLAT__      // not set by -cwc\n-si4            // sizeof(int)         is 4\n-spN4           // sizeof(near pointer) is 4\n-spF6           // sizeof( far pointer) is 6\n-sld10          // sizeof(long double) is 10.\n-function(exit,_exit)   // _exit() is like exit()\n-emacro(734,putc)   // don't complain about items being too large.\n-emacro(506,putc)   // don't complain about constant Boolean\n-emacro(???,va_arg)     // the va_arg() macro can yield 415, 416, 661, 662\n\t\t\t// 796 and 797 (out-of-bounds errors).\n\n   // While processing compiler (library) header files ...\n-elib(46)       // an unsigned short bit field is used as __FILLER__\n-elib(522)      // function return value ignored\n-elib(537)      // repeated include file (ios.h)\n-elib(641)      // converting enum to int\n-elib(652)      // suppress message about #define of earlier declared symbols\n-elib(655)      // ORing enum's\n-elib(726)      // extraneous comma in enumeration\n-elib(760)      // suppress message about multiple identical macro defs\n-elib(762)      // suppress message about multiple identical declarations and\n-elib(806)      // small bit field is signed\n-elib(1053)     // prototypes cannot be distinguished\n-elib(1511)     // member (rdbuf) hides nonvirtual member\n-elib(1704)     // private copy constructor\n-elib(1712)     // default constructor missing\n-elib(1717)     // empty prototypes\n-elib(1720)     // strange argument to assignment operator\n-elib(1721)     // unusual operator =() declaration\n-elib(1722)     // assignment operator does not return ref to class\n-elib(1724)     // strange argument to copy constructor\n\n-esym(1702,operator<<,operator>>)\n\n//  The following functions exhibit variable return modes.\n//  That is, they may equally-usefully be called for a value\n//  as called just for their effects.  Accordingly we inhibit\n//  Warning 534 for these functions.\n//  Feel free to add to or subtract from this list.\n\n-esym(534,close,creat,fclose,fflush,fprintf,fputc)\n-esym(534,fputs,fscanf,fseek,fwrite,lseek,memcpy,memmove,memset)\n-esym(534,printf,puts,scanf,sprintf,sscanf,strcat,strcpy)\n-esym(534,strncat,strncpy,unlink,write)\n\n//------------------------------------------------------------------\n\n// Please note -- this is a representative set of error suppression\n//                options.  Please adjust to suit your own policies\n//                See PC-lint for C/C++ manual (chapter LIVING WITH LINT)\n//                for further details.\n\n-e502 -e713 -e737 -eau  // don't report on signed/unsigned mismatches\n-e734                   // allow sub-integer loss of information\n-e701 -e703             // shifting int left is OK\n-e537                   // don't care about repeated include file\n-e641                   // converting enum to int is ok\n-e1042                  // operator ++/-- don't need class parameters\n-e963 -e763             // redundant declarations are ok\n-e1712                  // no default constructor defined is ok\n-e1704                  // private constructors are ok\n-e534                   // ignoring return value is ok\n-e732                   // going from signed to unsigned parameter is ok\n-e1411                  // functions hiding base functions is ok\n-e788                   // switch with default doesn't need all values specified\n-e655 -e656             // compatable enum bit and arithmetic operations are ok\n-e1542                  // members possibly not initialized isn't a valid warning\n-e522                   // calling 'new' without assignment isn't always an error\n\n-e1401 // uninitialized by constructor warning disabled.\n\n\n// 32 bit integer and pointer size is four bytes.\n-si4 -sp4\n\n// Include directories\n-ic:\\projects\\c&czero\\code\\watcom\\h;..\\vq\\include;..\\gcl510\\h\n"
  },
  {
    "path": "CODE/STRAW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/STRAW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : STRAW.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Straw::Get_From -- Connect one straw segment to another.                                  *\n *   Straw::Get -- Fetch some data from the straw chain.                                       *\n *   Straw::~Straw -- Destructor for a straw segment.                                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"straw.h\"\n#include\t<stddef.h>\n#include\t<string.h>\n\n\n/***********************************************************************************************\n * Straw::~Straw -- Destructor for a straw segment.                                            *\n *                                                                                             *\n *    This destructor will remove this segment from the straw chain. If there were any         *\n *    connected segments to either side, they will be joined so that the straw chain will      *\n *    still remain linked.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nStraw::~Straw(void)\n{\n\tif (ChainTo != NULL) {\n\t\tChainTo->ChainFrom = ChainFrom;\n\t}\n\tif (ChainFrom != NULL) {\n\t\tChainFrom->Get_From(ChainTo);\n\t}\n\n\tChainFrom = NULL;\n\tChainTo = NULL;\n}\n\n\n/***********************************************************************************************\n * Straw::Get_From -- Connect one straw segment to another.                                    *\n *                                                                                             *\n *    Use this routine to connect straw segments together. The straw segment specified as the  *\n *    parameter will be linked to the chain such that when data is requested, it will be       *\n *    fetched from the specified link before being processed by this link.                     *\n *                                                                                             *\n * INPUT:   straw -- Pointer to the straw segment that data will be fetched from.              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Straw::Get_From(Straw * straw)\n{\n\tif (ChainTo != straw) {\n\t\tif (straw != NULL && straw->ChainFrom != NULL) {\n\t\t\tstraw->ChainFrom->Get_From(NULL);\n\t\t\tstraw->ChainFrom = NULL;\n\t\t}\n\n\t\tif (ChainTo != NULL) {\n\t\t\tChainTo->ChainFrom = NULL;\n\t\t}\n\n\t\tChainTo = straw;\n\t\tif (ChainTo != NULL) {\n\t\t\tChainTo->ChainFrom = this;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Straw::Get -- Fetch some data from the straw chain.                                         *\n *                                                                                             *\n *    Use this routine to fetch some data from the straw. It is presumed that this routine     *\n *    will be overridden to provide some useful functionality. At this level, the straw chain  *\n *    merely passes the request on to the next straw in the chain.                             *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer to hold the requested data.                      *\n *                                                                                             *\n *          length   -- The number of bytes requested.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes stored into the buffer. If the number returned    *\n *          is less than the number requested, then this indicates that the straw data has     *\n *          been exhausted.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Straw::Get(void * source, int slen)\n{\n\tif (ChainTo != NULL) {\n\t\treturn(ChainTo->Get(source, slen));\n\t}\n\treturn(0);\n}\n\n\n"
  },
  {
    "path": "CODE/STRAW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/STRAW.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : STRAW.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef STRAW_H\n#define STRAW_H\n\n#include <stdlib.h>\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\n/*\n**\tThis is a demand driven data carrier. It will retrieve the byte request by passing\n**\tthe request down the chain (possibly processing on the way) in order to fulfill the\n**\tdata request. Without being derived, this class merely passes the data through. Derived\n**\tversions are presumed to modify the data in some useful way or monitor the data\n**\tflow.\n*/\nclass Straw\n{\n\tpublic:\n\t\tStraw(void) : ChainTo(0), ChainFrom(0) {}\n\t\tvirtual ~Straw(void);\n\n\t\tvirtual void Get_From(Straw * pipe);\n\t\tvoid Get_From(Straw & pipe) {Get_From(&pipe);}\n\t\tvirtual int Get(void * buffer, int slen);\n\n\t\t/*\n\t\t**\tPointer to the next pipe segment in the chain.\n\t\t*/\n\t\tStraw * ChainTo;\n\t\tStraw * ChainFrom;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tDisable the copy constructor and assignment operator.\n\t\t*/\n\t\tStraw(Straw & rvalue);\n\t\tStraw & operator = (Straw const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/STUB.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include\t<stdlib.h>\n#include\t<stdio.h>\n\nvoid main(void)\n{\n\tprintf(\"Run C&C.COM.\\n\");\n}\n"
  },
  {
    "path": "CODE/STUFF.TXT",
    "content": "\n\n52\tMission Editor (52)*\n36\tVariable difficulty settings (36)*\n35\tImprove manual (more detailed information) (35)*\n26\tSVGA graphics (or at least the option) (26) \n22\tImprove AI (smarter/harder/no traffic jams) (22)* \n21\tRandom map/mission generator (21)*\n21\tAbility to review missions and cut scenes independent of the game(21)* \n18\tTerrain Editor (18)*\n12\tLarger map (12)*\n9\tFog of war (9)\n8\tMore than 2 sides/combatants (8)\n6\tC&C-type games based on other genres (such as Tolwkien, Lands of Lore, Civil War, American old west, etc.) (6)\n6\tCaptions for hearing impaired customers (6)*\n6\tNew Mission Add-ins (6)\n4\tRemove linear missions (winning and losing paths) (4) \n4\t(units and money kept in next mission) (4)\n3\tVariable weather which affects play (3)* \n3\tNo more maze-like levels (3)\n3\tAbility to play multi-player maps in single-player mode (3)\n2\tWindows 95 version (2)\n2\tOptional auto-save feature (2)\n2\tMore varried terrain types (2)\n2\tAllow player option to remain in mission after goal is met (2) \n1\tTerrain affects movement/combat ability (1) \n1\tOption screen to chose which messages are actually heard (1)\n1\tMultiple resources (1)\n1\tMore continuity between scenarios\n1\tCivilian riots (1)\n1\tAdd an option key to move to any occuring battle (1) \n\nMULTI-PLAYER:\n\n42\tSave option for modem/net play (42)*\n27\tAI players should build bases and be more aggressive (27)* \n17\tUser variable setting for Tiberium regeneration (15) Increase chat message space (17)*\n6\tAbility to specifically select which units and structures can be used in a game (not according to tech level) (6)\n4\tHigher setting for credits in modem/net play (4)* \n4\tAbility to connect to more than 4 players (4)*\n3\tAbility to pause in modem/network game (3)\n2\tHandicapping option (2)\n1\tAbility to connect through a BBS or online service (1) \n1\tAllow players to build bases before the game starts (1) \n1\tAllow allys to transfer units (1)\n\nUNITS:\n31\tMore land units (31)*\n22\tMore air units (22)*\n18\tMore water units (18)*\n16\tAir units reveal terrain as they fly over, not just when they land (16)\n16\tIncrease intelligence of Harvester (so it can recognize and avoid enemy threats) (16)*\n12\tGroup loading of APCs (12)*\n7\tPut the XO armor and Stealth fighters in the game (7) \n6\tBridge-laying/amphibious units (6)*\n6\tSabotage and espionage teams/infantry (6)\n6\tParatroopers that can jump from planes or transport copters (6) \n6\tOfficer infantry that make your troops more effective (hit better, stay in formation) (6)\n4\tAbility to control hovercraft, gunships, and A-10s (4)*\n4\tAbility to assign a unit to more than one Hot Key grouping (4)* \n4\tEngineers should have multiple purposes  (mine laying/clearing, bridge building/blowing) (4)*\n4\tMobile SAM (4)*\n4\tCarry-alls (like in dune 2) for Harvesters and damaged units (4) \n4\tMANY different harvester types, including flying and armed (4) \n4\tUnits should have capability to move and fire at the same time (4) \n3\tThe capability of squad/formation movement (3)\n3\tMultiple weapons on certain units (machine guns on tanks) (3) \n3\tAllow infantry to scale cliffs and ford rivers (3)\n3\tThe ability to set down patrol points (2 or more) for a unit or group of units (3)\n2\tScout (in conjunction with Fog of War) (2) \n2\tMake the commando a buildable unit in single-play (2)\n2\tAbility to put weapons on harvesters (2) \n2\tAbility to assign multiple targets (2)\n1\tMammoth Tanks can crush light vehicles (1)\n1\tAllow Construction Yard to revert to MCV (1) \n1\tSniper Units (1)\n1\tMedical Vehicals (Ambulances) to heal infantry (1) \n1\tMobile Chemical mortar tank (1)\n1\tCargo ships and vehicals able to carry more than 5 troopers and vehicles (1)\n1\tMobile Anti-aircraft artillery (1)\n1\tMobile Laser artillery (1)\n1\tIncrease range of artillery (1)\n1\tLiquid Nitrogen troopers (like chem troops) (1) \n1\tSome type of air-to-air fighter craft (1)\n1\tAutomatic scatter (X-key) of infantry units (and no scattering into threats) (1)\n1\tWhen a harvester is destroyed, the tiberium should stay on the ground (1)\n1\tSound effects for each unit (such as engine whine for Chinooks) (1) \n1\tSuicide Units (Humm Vees filled with C4) (1)\n\n\nSTRUCTURES:\n22\tAutomatic gates for the walls/fences (22)*\n21\tAbility to lay down mines (21)*\n16\tMore balance to Ion Cannon / Nukes (Ion Cannon should be stronger or faster) (16)\n11\tAbility to build structures anywhere rather than next to existing structures (11)*\n6\tAbility to dig trenches (6)*\n6\tBridges that can be destroyed (6)*\n4\tMake SAM sites respond faster (4)\n3\tFix the sandbag bug (3)\n3\tAdd a hospital to heal infantry (3)\n2\tMake capturing buildings more difficult (2)\n1\tRadar Jamming Center (1)\n1\tNon-mobile artillery emplacements (1)\n1\tGenerators as backup power to specific buildings (1) \n1\tListening Posts (in conjunction with Fog of War) (1) \n1\tForce fields as a barrier/wall type (1)\n1\tA defense shield generator to protect buildings from Nuke and Ion cannon (1)\n1\tBetter walls than concrete (Steel?) (1) \n"
  },
  {
    "path": "CODE/STYLE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*\n       STYLE GUIDE FOR COMMAND & CONQUER : TIBERIAN SUN\n\nIn addition to the standard Westwood programmer's style guide, the following\nguidelines apply.\n\n> Use every feature the compiler has that will help catch bugs and encourage\nsolid portable coding practices. i.e., turn on all warnings and treat all warnings\nas errors. Use helper programs such as Lint, BoundsChecker, or CodeGuard whenever\npossible.\n\n> Keep related items together. Examples: Declare variables right before they are\nused. Keep functions that work on the same subsystem, within the same module.\n\n> Use consistent commenting and spacing style. Examples: see existing Red Alert\ncode. Creative freedom does not extend to formatting.\n\n> Use descriptive variable names. Examples: Use \"index\" rather than \"i\". Use\n\"unit_index\" rather than \"index\".\n\n> Use a consistent variable and function naming convention. Examples; boolean\nvariables should begin with \"Is\" (e.g., \"IsActive\", \"IsFiring\"). Functions that\nexist solely to return a similar boolean query should begin with \"Is_\".\n\n> If you have a variable that only serves a boolean function, then declare it\nas \"bool\" rather than as \"int\" and assign it \"true\" or \"false\" rather than \"1\"\nor \"0\".\n\n> Choose function and variable names that are precise, descriptive, and concise (in that\norder).\n\n> Hide data where possible: Examples: If a global is only used in one module, make\nit static to that module. If a helper function is only used in one module, make it\nstatic as well. Hide class members in the private section if they aren't needed\npublic. Most variables aren't needed as public.\n\n> Keep function bodies short. It is often times, more easy to understand and maintain\nif a very long function is broken up into helper functions with descriptive names.\nA clue if a function is too long is if you can page down 5 times and still be somewhere\nin the middle of the function. If you can page down 10 times and still be in the\nfunction, you've got a serious function size problem.\n\n> Compare pointers to NULL and integer types to zero (NULL) instead of using the\n\"if (x)\" or \"if (!x)\" format. This short format should only be used for boolean\nvalues and expressions. It is just as efficient and it makes it more clear to the\nreader that the variable is a pointer and not a simple boolean value.\n\n> Use \"const\" when declaring any member functions that do not modify data. Corollary --\nmake sure any function that appears like it will not modify data will, in fact, NOT\nmodify any data. Example; A function called Is_Able_To_Move() shouldn't modify the\nobject nor should it actually cause something to start moving! The use of \"const\" is a\nvariation on style guide rule #1 (use the compiler to help ensure proper code).\n\n> Shun using assembly language except in extreme cases. Such would be if a\nfunction can only be performed by using assembly (requires special opcodes), or\nif performance would be PROVEABLY dramatically improved. Don't code in assembly for\nperformance reasons if there isn't benchmarking code in place to analyze the results.\nAs a corollary, design a better algorithm as the first recourse.\n\n> Keep class interfaces small and simple.\n\n> Organize algorithms to use as few special case \"if\" statements as possible. Data\ntables or data files are preferred. This follows the generally good guideline of offloading\nas much processing as possible to compile-time rather than run-time.\n\n*/\n"
  },
  {
    "path": "CODE/SUPER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SUPER.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SUPER.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/28/95                                                     *\n *                                                                                             *\n *                  Last Update : October 11, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SuperClass::AI -- Process the super weapon AI.                                            *\n *   SuperClass::Anim_Stage -- Fetches the animation stage for this super weapon.              *\n *   SuperClass::Discharged -- Handles discharged action for special super weapon.             *\n *   SuperClass::Enable -- Enable this super special weapon.                                   *\n *   SuperClass::Forced_Charge -- Force the super weapon to full charge state.                 *\n *   SuperClass::Impatient_Click -- Called when player clicks on unfinished super weapon.      *\n *   SuperClass::Recharge -- Starts the special super weapon recharging.                       *\n *   SuperClass::Remove -- Removes super weapon availability.                                  *\n *   SuperClass::SuperClass -- Constructor for special super weapon objects.                   *\n *   SuperClass::Suspend -- Suspend the charging of the super weapon.                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * SuperClass::SuperClass -- Constructor for special super weapon objects.                     *\n *                                                                                             *\n *    This is the constructor for the super weapons.                                           *\n *                                                                                             *\n * INPUT:   recharge    -- The recharge delay time (in game frames).                           *\n *                                                                                             *\n *          charging    -- Voice to announce that the weapon is charging.                      *\n *                                                                                             *\n *          ready       -- Voice to announce that the weapon is fully charged.                 *\n *                                                                                             *\n *          impatient   -- Voice to announce current charging state.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nSuperClass::SuperClass(int recharge, bool powered, VoxType charging, VoxType ready, VoxType impatient, VoxType suspend) :\n\tIsPowered(powered),\n\tIsPresent(false),\n\tIsOneTime(false),\n\tIsReady(false),\n\tControl(0),\n\tOldStage(-1),\n\tVoxRecharge(ready),\n\tVoxCharging(charging),\n\tVoxImpatient(impatient),\n\tVoxSuspend(suspend),\n\tRechargeTime(recharge)\n{\n}\n\n\n/***********************************************************************************************\n * SuperClass::Suspend -- Suspend the charging of the super weapon.                            *\n *                                                                                             *\n *    This will temporarily put on hold the charging of the special weapon. This might be the  *\n *    result of insufficient power.                                                            *\n *                                                                                             *\n * INPUT:   on -- Should the weapon charging be suspended? Else, it will unsuspend.            *\n *                                                                                             *\n * OUTPUT:  Was the weapon suspend state changed?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SuperClass::Suspend(bool on)\n{\n\tif (IsPresent && !IsReady && !IsOneTime && on == Control.Is_Active()) {\n\t\tif (!on) {\n\t\t\tControl.Start();\n\t\t} else {\n\t\t\tControl.Stop();\n\t\t}\n//\t\tif (on != IsSuspended) {\n//\t\t\tif (on) {\n//\t\t\t\tSuspendTime = Control;\n//\t\t\t} else {\n//\t\t\t\tControl = SuspendTime;\n//\t\t\t}\n//\t\t\tIsSuspended = on;\n\t\t\treturn(true);\n//\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SuperClass::Enable -- Enable this super special weapon.                                     *\n *                                                                                             *\n *    This routine is called when the special weapon needs to be activated. This is used for   *\n *    both the normal super weapons and the special one-time super weapons (from crates).      *\n *                                                                                             *\n * INPUT:   onetime  -- Is this a special one time super weapon?                               *\n *                                                                                             *\n *          player   -- Is this weapon for the player? If true, then there might be a voice    *\n *                      announcement of this weapon's availability.                            *\n *                                                                                             *\n *          quiet    -- Request that the weapon start in suspended state (quiet mode).         *\n *                                                                                             *\n * OUTPUT:  Was the special super weapon enabled? Failure might indicate that the weapon was   *\n *          already available.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SuperClass::Enable(bool onetime, bool player, bool quiet)\n{\n\tif (!IsPresent) {\n\t\tIsPresent = true;\n\t\tIsOneTime = onetime;\n\t\tbool retval = Recharge(player && !quiet);\n\t\tif (quiet) Suspend(true);\n\t\treturn(retval);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SuperClass::Remove -- Removes super weapon availability.                                    *\n *                                                                                             *\n *    Call this routine when the super weapon should be removed because of some outside        *\n *    force. For one time special super weapons, they can never be removed except as the       *\n *    result of discharging them.                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the special weapon removed and disabled?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SuperClass::Remove(void)\n{\n\tif (IsPresent && !IsOneTime) {\n\t\tIsReady = false;\n\t\tIsPresent = false;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SuperClass::Recharge -- Starts the special super weapon recharging.                         *\n *                                                                                             *\n *    This routine is called when the special weapon is allowed to recharge. Suspension will   *\n *    be disabled and the animation process will begin.                                        *\n *                                                                                             *\n * INPUT:   player   -- Is this for a player owned super weapon? If so, then a voice           *\n *                      announcement might be in order.                                        *\n *                                                                                             *\n * OUTPUT:  Was the super weapon begun charging up?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SuperClass::Recharge(bool player)\n{\n\tif (IsPresent && !IsReady) {\n//\t\tIsSuspended = false;\n\t\tOldStage = -1;\n\t\tControl.Start();\n\t\tControl = RechargeTime;\n\n#ifdef CHEAT_KEYS\n\t\tif (Special.IsSpeedBuild) {\n\t\t\tControl = 1;\n\t\t}\n#endif\n\n\t\tif (player) {\n\t\t\tSpeak(VoxCharging);\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * Superclass::Discharged -- Handles discharged action for special super weapon.               *\n *                                                                                             *\n *    This routine should be called when the special super weapon has been discharged. The     *\n *    weapon will either begin charging anew or will be removed entirely -- depends on the     *\n *    one time flag for the weapon.                                                            *\n *                                                                                             *\n * INPUT:   player   -- Is this special weapon for the player? If so, then there might be a    *\n *                      voice announcement.                                                    *\n *                                                                                             *\n * OUTPUT:  Should the sidebar be reprocessed because the special weapon has been eliminated?  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SuperClass::Discharged(bool player)\n{\n\tif (Control.Is_Active() && IsPresent && IsReady) {\n\t\tIsReady = false;\n\t\tif (IsOneTime) {\n\t\t\tIsOneTime = false;\n\t\t\treturn(Remove());\n\t\t} else {\n\t\t\tRecharge(player);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SuperClass::AI -- Process the super weapon AI.                                              *\n *                                                                                             *\n *    This routine will process the charge up AI for this super weapon object. If the weapon   *\n *    has advanced far enough to change any sidebar graphic that might represent it, then      *\n *    \"true\" will be returned. Use this return value to intelligently update the sidebar.      *\n *                                                                                             *\n * INPUT:   player   -- Is this for the player? If it is and the weapon is now fully charged,  *\n *                      then this fully charged state will be announced to the player.         *\n *                                                                                             *\n * OUTPUT:  Was the weapon's state changed such that a sidebar graphic update will be          *\n *          necessary?                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SuperClass::AI(bool player)\n{\n\tif (IsPresent && !IsReady) {\n\t\tif (!Control.Is_Active()) {\n\t\t\tif (OldStage != -1) {\n\t\t\t\tOldStage = -1;\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t} else {\n\t\t\tif (Control == 0) {\n\t\t\t\tIsReady = true;\n\t\t\t\tif (player) {\n\t\t\t\t\tSpeak(VoxRecharge);\n\t\t\t\t}\n\t\t\t\treturn(true);\n\t\t\t} else {\n\t\t\t\tif (Anim_Stage() != OldStage) {\n\t\t\t\t\tOldStage = Anim_Stage();\n\t\t\t\t\treturn(true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SuperClass::Anim_Stage -- Fetches the animation stage for this super weapon.                *\n *                                                                                             *\n *    This will return the current animation stage for this super weapon. The value will be    *\n *    between zero (uncharged) to ANIMATION_STAGES (fully charged). Use this value to render   *\n *    the appropriate graphic on the sidebar.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current animation stage for this special super weapon powerup.    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *   10/11/1996 JLB : Doesn't show complete until really complete.                             *\n *=============================================================================================*/\nint SuperClass::Anim_Stage(void) const\n{\n\tif (IsPresent) {\n\t\tif (IsReady) {\n\t\t\treturn(ANIMATION_STAGES);\n\t\t}\n//\t\tint time = Control;\n//\t\tif (IsSuspended) {\n//\t\t\ttime = SuspendTime;\n//\t\t}\n\n\t\tint stage = ANIMATION_STAGES * fixed(RechargeTime-Control.Value(), RechargeTime);\n\t\tstage = min(stage, ANIMATION_STAGES-1);\n\t\treturn(stage);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * SuperClass::Impatient_Click -- Called when player clicks on unfinished super weapon.        *\n *                                                                                             *\n *    This routine is called when the player clicks on the super weapon icon on the sidebar    *\n *    when the super weapon is not ready yet. This results in a voice message feedback to the  *\n *    player.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SuperClass::Impatient_Click(void) const\n{\n\tif (!Control.Is_Active()) {\n\t\tSpeak(VoxSuspend);\n\t} else {\n\t\tSpeak(VoxImpatient);\n\t}\n}\n\n\n/***********************************************************************************************\n * SuperClass::Forced_Charge -- Force the super weapon to full charge state.                   *\n *                                                                                             *\n *    This routine will force the special weapon to full charge state. Call it when the weapon *\n *    needs to be instantly charged. The airstrike (when it first becomes available) is a      *\n *    good example.                                                                            *\n *                                                                                             *\n * INPUT:   player   -- Is this for the player? If true, then the full charge state will be    *\n *                      announced.                                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SuperClass::Forced_Charge(bool player)\n{\n\tif (IsPresent) {\n\t\tIsReady = true;\n\t\tControl.Start();\n\t\tControl = 0;\n//\t\tIsSuspended = false;\n\t\tif (player) {\n\t\t\tSpeak(VoxRecharge);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "CODE/SUPER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SUPER.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SUPER.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/28/95                                                     *\n *                                                                                             *\n *                  Last Update : July 28, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SUPER_H\n#define SUPER_H\n\n#include\t\"ftimer.h\"\n\nclass SuperClass {\n\tpublic:\n\t\tSuperClass(NoInitClass const & x) : Control(x) {};\n\t\tSuperClass(void) : Control(NoInitClass()) {};\n\t\tSuperClass(int recharge, bool powered, VoxType charging=VOX_NONE, VoxType ready=VOX_NONE, VoxType impatient=VOX_NONE, VoxType suspend=VOX_NONE);\n\n\t\tbool Suspend(bool on);\n\t\tbool Enable(bool onetime = false, bool player=false, bool quiet=false);\n\t\tvoid Forced_Charge(bool player=false);\n\t\tbool AI(bool player=false);\n\t\tbool Remove(void);\n\t\tvoid Impatient_Click(void) const;\n\t\tint Anim_Stage(void) const;\n\t\tbool Discharged(bool player);\n\t\tbool Is_Ready(void) const {return(IsReady);}\n\t\tbool Is_Present(void) const {return(IsPresent);}\n\t\tbool Is_One_Time(void) const {return(IsOneTime && IsPresent);}\n\t\tbool Is_Powered(void) const {return(IsPowered);}\n\n\tprivate:\n\t\tbool Recharge(bool player=false);\n\n\t\tunsigned IsPowered:1;\n\t\tunsigned IsPresent:1;\n\t\tunsigned IsOneTime:1;\n\t\tunsigned IsReady:1;\n\n\t\tCDTimerClass<FrameTimerClass> Control;\n\t\tint OldStage;\n\n\t\tVoxType VoxRecharge;\n\t\tVoxType VoxCharging;\n\t\tVoxType VoxImpatient;\n\t\tVoxType VoxSuspend;\n\t\tint RechargeTime;\n\n\t\tenum {\n\t\t\tANIMATION_STAGES=54\n\t\t};\n};\n\n\n\n#endif\n"
  },
  {
    "path": "CODE/SUPPORT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header:   F:\\projects\\c&c0\\vcs\\code\\support.asv   5.0   11 Nov 1996 09:40:30   JOE_BOSTIC  $\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : SUPPORT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : September 23, 1993                       *\n;*                                                                         *\n;*                  Last Update : May 10, 1994   [JLB]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   strtrim -- Remove the trailing white space from a string.             *\n;*   Fat_Put_Pixel -- Draws a fat pixel.                                   *\n;*   Conquer_Build_Fading_Table -- Builds custom shadow/light fading table.*\n;*   Remove_From_List -- Removes a pointer from a list of pointers.        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"gbuffer.inc\"\n\tDISPLAY\t\"Command & Conquer assembly support routines.\"\n\n\tCODESEG\n\n\n;***************************************************************************\n;* Fat_Put_Pixel -- Draws a fat pixel.                                     *\n;*                                                                         *\n;*    Use this routine to draw a \"pixel\" that is bigger than 1 pixel       *\n;*    across.  This routine is faster than drawing a similar small shape   *\n;*    and faster than calling Fill_Rect.                                   *\n;*                                                                         *\n;* INPUT:   x,y       -- Screen coordinates to draw the pixel's upper      *\n;*                       left corner.                                      *\n;*                                                                         *\n;*          color     -- The color to render the pixel in.                 *\n;*                                                                         *\n;*          size      -- The number of pixels width of the big \"pixel\".    *\n;*                                                                         *\n;*          page      -- The pointer to a GraphicBuffer class or something *\n;*                                                                         *\n;* OUTPUT:  none                                                           *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/17/1994 JLB : Created.                                             *\n;*=========================================================================*\n; VOID cdecl Fat_Put_Pixel(long x, long y, long color, long size, void *page)\n\tGLOBAL\tC Fat_Put_Pixel:NEAR\n\tPROC\tFat_Put_Pixel C near\n\tUSES\teax, ebx, ecx, edx, edi, esi\n\n\tARG\tx:DWORD\t\t; X coordinate of upper left pixel corner.\n\tARG\ty:DWORD\t\t; Y coordinate of upper left pixel corner.\n\tARG\tcolor:DWORD\t; Color to use for the \"pixel\".\n\tARG\tsiz:DWORD\t; Size of \"pixel\" to plot (square).\n\tARG\tgpage:DWORD\t; graphic page address to plot onto\n\n\tcmp\t[siz],0\n\tje\tshort ??exit\n\n\t; Set EDI to point to start of logical page memory.\n\t;*===================================================================\n\t; Get the viewport information and put bytes per row in ecx\n\t;*===================================================================\n\tmov\tebx,[gpage]\t\t\t\t; get a pointer to viewport\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get the correct offset\n\n\t; Verify the the Y pixel offset is legal.\n\tmov\teax,[y]\n\tcmp\teax,[(GraphicViewPort ebx).GVPHeight]\t;YPIXEL_MAX\n\tjae\tshort ??exit\n\tmul\t[(GraphicViewPort ebx).GVPWidth]\n\tadd\tedi,eax\n\n\t; Verify the the X pixel offset is legal.\n\tmov\tedx,[(GraphicViewPort ebx).GVPWidth]\n\tcmp\tedx,[x]\n\tjbe\tshort ??exit\n\tadd\tedi,[x]\n\n\t; Write the pixel to the screen.\n\tmov\tebx,[siz]\t\t; Copy of pixel size.\n\tsub\tedx,ebx\t\t\t; Modulo to reach start of next row.\n\tmov\teax,[color]\n??again:\n\tmov\tecx,ebx\n\trep stosb\n\tadd\tedi,edx\t\t\t; EDI points to start of next row.\n\tdec\t[siz]\n\tjnz\tshort ??again\n\n??exit:\n\tret\n\n\tENDP\tFat_Put_Pixel\n\n\nif 0\n\n;***************************************************************************\n;* strtrim -- Remove the trailing white space from a string.               *\n;*                                                                         *\n;*    Use this routine to remove white space characters from the beginning *\n;*    and end of the string.        The string is modified in place by     *\n;*    this routine.                                                        *\n;*                                                                         *\n;* INPUT:   buffer   -- Pointer to the string to modify.                   *\n;*                                                                         *\n;* OUTPUT:     none                                                        *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/07/1992 JLB : Created.                                             *\n;*=========================================================================*\n; VOID cdecl strtrim(BYTE *buffer);\n\tGLOBAL\tC strtrim :NEAR\n\tPROC\tstrtrim C near\n\tUSES\tax, edi, esi\n\n\tARG\tbuffer:DWORD\t\t; Pointer to string to modify.\n\n\tcmp\t[buffer],0\n\tje\tshort ??fini\n\n\t; Prepare for string scanning by loading pointers.\n\tcld\n\tmov\tesi,[buffer]\n\tmov\tedi,esi\n\n\t; Strip white space from the start of the string.\n??looper:\n\tlodsb\n\tcmp\tal,20h\t\t\t; Space\n\tje\tshort ??looper\n\tcmp\tal,9\t\t\t; TAB\n\tje\tshort ??looper\n\tstosb\n\n\t; Copy the rest of the string.\n??gruntloop:\n\tlodsb\n\tstosb\n\tor\tal,al\n\tjnz\tshort ??gruntloop\n\tdec\tedi\n\t; Strip the white space from the end of the string.\n??looper2:\n\tmov\t[edi],al\n\tdec\tedi\n\tmov\tah,[edi]\n\tcmp\tah,20h\n\tje\tshort ??looper2\n\tcmp\tah,9\n\tje\tshort ??looper2\n\n??fini:\n\tret\n\n\tENDP\tstrtrim\n\n\n;***************************************************************************\n;* Conquer_Build_Fading_Table -- Builds custom shadow/light fading table.  *\n;*                                                                         *\n;*    This routine is used to build a special fading table for C&C.  There *\n;*    are certain colors that get faded to and cannot be faded again.      *\n;*    With this rule, it is possible to draw a shadow multiple times and   *\n;*    not have it get any lighter or darker.                               *\n;*                                                                         *\n;* INPUT:   palette  -- Pointer to the 768 byte IBM palette to build from. *\n;*                                                                         *\n;*          dest     -- Pointer to the 256 byte remap table.               *\n;*                                                                         *\n;*          color    -- Color index of the color to \"fade to\".             *\n;*                                                                         *\n;*          frac     -- The fraction to fade to the specified color        *\n;*                                                                         *\n;* OUTPUT:  Returns with pointer to the remap table.                       *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/07/1992 JLB : Created.                                             *\n;*=========================================================================*/\n;VOID * cdecl Conquer_Build_Fading_Table(VOID *palette, VOID *dest, long color, long frac);\n\tGLOBAL\tC Conquer_Build_Fading_Table : NEAR\n\tPROC\tConquer_Build_Fading_Table C near\n\tUSES\tebx, ecx, edi, esi\n\n\tARG\tpalette:DWORD\n\tARG\tdest:DWORD\n\tARG\tcolor:DWORD\n\tARG\tfrac:DWORD\n\n\tLOCAL\tmatchvalue:DWORD\t; Last recorded match value.\n\tLOCAL\ttargetred:BYTE\t\t; Target gun red.\n\tLOCAL\ttargetgreen:BYTE\t; Target gun green.\n\tLOCAL\ttargetblue:BYTE\t\t; Target gun blue.\n\tLOCAL\tidealred:BYTE\n\tLOCAL\tidealgreen:BYTE\n\tLOCAL\tidealblue:BYTE\n\tLOCAL\tmatchcolor:BYTE\t\t; Tentative match color.\n\nALLOWED_COUNT\tEQU\t16\nALLOWED_START\tEQU\t256-ALLOWED_COUNT\n\n\tcld\n\n\t; If the source palette is NULL, then just return with current fading table pointer.\n\tcmp\t[palette],0\n\tje\t??fini1\n\tcmp\t[dest],0\n\tje\t??fini1\n\n\t; Fractions above 255 become 255.\n\tmov\teax,[frac]\n\tcmp\teax,0100h\n\tjb\tshort ??ok\n\tmov\t[frac],0FFh\n??ok:\n\n\t; Record the target gun values.\n\tmov\tesi,[palette]\n\tmov\tebx,[color]\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tlodsb\n\tmov\t[targetred],al\n\tlodsb\n\tmov\t[targetgreen],al\n\tlodsb\n\tmov\t[targetblue],al\n\n\t; Main loop.\n\txor\tebx,ebx\t\t\t; Remap table index.\n\n\t; Transparent black never gets remapped.\n\tmov\tedi,[dest]\n\tmov\t[edi],bl\n\tinc\tedi\n\n\t; EBX = source palette logical number (1..255).\n\t; EDI = running pointer into dest remap table.\n??mainloop:\n\tinc\tebx\n\tmov\tesi,[palette]\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\n\tmov\tedx,[frac]\n\tshr\tedx,1\n\t; new = orig - ((orig-target) * fraction);\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetred]\t\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\teax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealred],dh\t\t; preserve ideal color gun value.\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetgreen]\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\teax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealgreen],dh\t\t; preserve ideal color gun value.\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetblue]\t\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\teax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealblue],dh\t\t; preserve ideal color gun value.\n\n\t; Sweep through a limited set of existing colors to find the closest\n\t; matching color.\n\n\tmov\teax,[color]\n\tmov\t[matchcolor],al\t\t; Default color (self).\n\tmov\t[matchvalue],-1\t\t; Ridiculous match value init.\n\tmov\tecx,ALLOWED_COUNT\n\n\tmov\tesi,[palette]\t\t; Pointer to original palette.\n\tadd\tesi,(ALLOWED_START)*3\n\n\t; BH = color index.\n\tmov\tbh,ALLOWED_START\n??innerloop:\n\n\txor\tedx,edx\t\t\t; Comparison value starts null.\n\n\t; Build the comparison value based on the sum of the differences of the color\n\t; guns squared.\n\tlodsb\n\tsub\tal,[idealred]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\n\tlodsb\n\tsub\tal,[idealgreen]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\n\tlodsb\n\tsub\tal,[idealblue]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\tjz\tshort ??perfect\t\t; If perfect match found then quit early.\n\n\tcmp\tedx,[matchvalue]\n\tjae\tshort ??notclose\n\tmov\t[matchvalue],edx\t; Record new possible color.\n\tmov\t[matchcolor],bh\n??notclose:\n\tinc\tbh\t\t\t; Checking color index.\n\tloop\t??innerloop\n\tmov\tbh,[matchcolor]\n??perfect:\n\tmov\t[matchcolor],bh\n\txor\tbh,bh\t\t\t; Make BX valid main index again.\n\n\t; When the loop exits, we have found the closest match.\n\tmov\tal,[matchcolor]\n\tstosb\n\tcmp\tebx,ALLOWED_START-1\n\tjne\t??mainloop\n\n\t; Fill the remainder of the remap table with values\n\t; that will remap the color to itself.\n\tmov\tecx,ALLOWED_COUNT\n??fillerloop:\n\tinc\tbl\n\tmov\tal,bl\n\tstosb\n\tloop\t??fillerloop\n\n??fini1:\n\tmov\tesi,[dest]\n\tmov\teax,esi\n\tret\n\n\tENDP\tConquer_Build_Fading_Table\n\n\n;***************************************************************************\n;* Remove_From_List -- Removes a pointer from a list of pointers.          *\n;*                                                                         *\n;*    This low level routine is used to remove a pointer from a list of    *\n;*    pointers.  The trailing pointers are moved downward to fill the      *\n;*    hole.                                                                *\n;*                                                                         *\n;* INPUT:   list     -- Pointer to list of pointer.                        *\n;*                                                                         *\n;*          index    -- Pointer to length of pointer list.                 *\n;*                                                                         *\n;*          ptr      -- The pointer value to search for and remove.        *\n;*                                                                         *\n;* OUTPUT:  none                                                           *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/11/1994 JLB : Created.                                             *\n;*   04/22/1994 JLB : Convert to assembly language.                        *\n;*   05/10/1994 JLB : Short pointers now.                                  *\n;*=========================================================================*/\n;VOID cdecl Remove_From_List(VOID **list, long *index, long ptr);\n\tGLOBAL\tC Remove_From_List:NEAR\n\tPROC\tRemove_From_List C near\n\tUSES\tedi, esi, ecx, eax\n\tARG\tlist:DWORD\t\t; Pointer to list.\n\tARG\tindex:DWORD\t\t; Pointer to count.\n\tARG\telement:DWORD\t\t; Element to remove.\n\n\t; Fetch the number of elements in the list.  If there are no\n\t; elements, then just exit quickly.\n\tmov\tedi,[index]\n\tmov\tecx,[edi]\n\tjcxz\tshort ??fini2\n\n\t; Fetch pointer to list.\n\tcmp\t[list],0\n\tje\tshort ??fini2\n\tmov\tedi,[list]\n\n\t; Loop through all elements searching for a match.\n\tmov\teax,[element]\n\trepne scasd\n\tjne\tshort ??fini2\t\t; No match found.\n\n\t; Copy all remaining elements down.  If this is the\n\t; last element in the list then nothing needs to be\n\t; copied -- just decrement the list size.\n\tjcxz\tshort ??nocopy\t\t; No copy necessary.\n\tmov\tesi,edi\n\tsub\tedi,4\n\trep movsd\n\n\t; Reduce the list count by one.\n??nocopy:\n\tmov\tedi,[index]\n\tdec\t[DWORD PTR edi]\n\n??fini2:\n\tret\n\n\tENDP\tRemove_From_List\n\n\n; long cdecl Get_EAX();\n\tGLOBAL\tC Get_EAX :NEAR\n\tPROC\tGet_EAX C near\n\tret\n\n\tENDP\tGet_EAX\nendif\n\n\n\tDATASEG\n\nTabA\tDD 6949350\n\tDD 4913933\n\tDD 3474675\n\tDD 2456966\n\tDD 1737338\n\tDD 1228483\n\tDD 868669\n\tDD 614242\n\tDD 434334\n\tDD 307121\n\tDD 217167\n\tDD 153560\n\tDD 108584\n\tDD 76780\n\tDD 54292\n\tDD 38390\n\tDD 27146\n\tDD 19195\n\tDD 13573\n\tDD 9598\n\tDD 6786\n\tDD 4799\n\tDD 3393\n\tDD 2399\n\tDD 1697\n\tDD 1200\n\tDD 848\n\tDD 600\n\tDD 424\n\tDD 300\n\tDD 212\n\tDD 150\n\tDD 106\n\nTabB\tDD 154\n\tDD 218\n\tDD 309\n\tDD 437\n\tDD 618\n\tDD 874\n\tDD 1236\n\tDD 1748\n\tDD 2472\n\tDD 3496\n\tDD 4944\n\tDD 6992\n\tDD 9888\n\tDD 13983\n\tDD 19775\n\tDD 27967\n\tDD 39551\n\tDD 55933\n\tDD 79101\n\tDD 111866\n\tDD 158203\n\tDD 223732\n\tDD 316405\n\tDD 447465\n\tDD 632811\n\tDD 894929\n\tDD 1265621\n\tDD 1789859\n\tDD 2531243\n\tDD 3579718\n\tDD 5062486\n\tDD 7159436\n\tDD 10124971\n\n\tCODESEG\n\n;***********************************************************************************************\n;* Square_Root -- Finds the square root of the fixed pointer parameter.                        *\n;*                                                                                             *\n;* INPUT:   val   -- The fixed point (16:16) value to find the square root of.                 *\n;*                                                                                             *\n;* OUTPUT:  Returns with the square root of the fixed pointer parameter.                       *\n;*                                                                                             *\n;* WARNINGS:   none                                                                            *\n;*                                                                                             *\n;* HISTORY:                                                                                    *\n;*   10/04/1995 JLB : Adapted.                                                                 *\n;*=============================================================================================*/\n;unsigned Square_Root(unsigned val);\n\tGLOBAL\tC Square_Root :NEAR\n\tPROC\tSquare_Root C near\n\tUSES\tebx,edx\n\n\tbsr ebx,eax\n\tjz ??zero\n\n\tmul [DWORD 4*ebx + OFFSET TabA]\n\tshrd eax,edx,10h\n\tadd eax, [4*ebx + OFFSET TabB]\n??zero:\n\tret\n\n\tENDP\tSquare_Root\n\n;----------------------------------------------------------------------------\n\n\tEND\n\n"
  },
  {
    "path": "CODE/SURFACE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SURFACE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SURFACE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 09/08/96                                                     *\n *                                                                                             *\n *                  Last Update : September 8, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"surface.h\"\n\n\nSurface::Surface(int w, int h, Buffer const * buffer, int pitch) :\n\tWidth(w),\n\tHeight(h),\n\tPitch(pitch)\n{\n\t/*\n\t**\tIf a buffer was specified, then this means that the surface will use the buffer memory\n\t**\tand thus not allocate and manage its own memory.\n\t*/\n\tif (buffer != NULL) {\n\t\tSurfaceData = *buffer;\n\n\t\t/*\n\t\t**\tReduce the dimensions if the buffer is not big enough. This size bounding is only\n\t\t**\tpossible if the buffer size is known. Otherwise, presume that it is big enough.\n\t\t*/\n\t\tif (buffer->Get_Size() > 0 && Get_Size() > buffer->Get_Size()) {\n\n\t\t\tHeight = buffer->Get_Size() / (Width+Pitch);\n\t\t\tif (Height == 0) {\n\t\t\t\tHeight = 1;\n\t\t\t\tWidth = buffer->Get_Size();\n\t\t\t}\n\t\t}\n\t} else {\n\t\t/*\n\t\t**\tA new buffer without existing memory specified, will allocate and manage its\n\t\t**\town memory for the surface.\n\t\t*/\n\t\tnew(&SurfaceData) Buffer(Logical_Size());\n\t}\n}\n\n\nSurface::Surface(Surface const & surface, int x, int y, int w, int h) :\n\tWidth(w),\n\tHeight(h),\n\tPitch(surface.Bytes_Per_Line() % w)\n{\n\tnew(&SurfaceData) Buffer((char*)surface.Get_Buffer() + y*surface.Bytes_Per_Line() + x);\n}\n\n\nvoid Surface::Copy_To(Buffer & buffer, int x, int y, int w, int h) const\n{\n\tassert(buffer.Is_Valid());\n\n\t/*\n\t**\tDetermine the width of the region to copy from this surface.\n\t*/\n\tint width = w;\n\tif (width == -1) {\n\t\twidth = Width;\n\t}\n\n\t/*\n\t**\tDetermine the height of the region to copy from this surface.\n\t*/\n\tint height = h;\n\tif (height == -1) {\n\t\theight = Height;\n\t}\n\n\tCopy_To(Rect(x, y, width, height), buffer);\n}\n\n\nvoid Surface::Copy_To(Rect const & fromrect, Buffer & tobuffer) const\n{\n\tassert(fromrect.Is_Valid());\n\tassert(tobuffer.Is_Valid());\n\n\t/*\n\t**\tDetermine the copy-from rectangle. The size is bounded to the source\n\t**\tsize of the surface, regardless of what was specified as the source\n\t**\trectangle.\n\t*/\n\tRect rect = fromrect.Intersect(Rect(0, 0, Width, Height));\n\n\t/*\n\t**\tDetermine the number of bytes to copy. If this number would be\n\t**\tlarger than the size of the destination buffer (presuming the size\n\t**\tof the destination buffer is known), then limit the copy size\n\t**\tto the buffer size.\n\t*/\n\tint tocopy = rect.Size();\n\tif (tobuffer.Get_Size() > 0 && tobuffer.Get_Size() > tocopy) {\n\t\ttocopy = tobuffer.Get_Size();\n\t}\n\n\t/*\n\t**\tDetermine the source starting byte pointer.\n\t*/\n\tchar * source = Get_Buffer() + rect.Y*Bytes_Per_Line() + rect.X;\n\n\t/*\n\t**\tDetermine the destination buffer pointer. This will always be the\n\t**\tstart of the destination buffer object specified.\n\t*/\n\tchar * dest = tobuffer;\n\n\t/*\n\t**\tDetermine the working pitch value to use. For full width surface\n\t**\tcopies on surfaces that have no inherent pitch, then a very fast\n\t**\tcopy-in-one-fast-step operation can be performed.\n\t*/\n\tint pitch = Bytes_Per_Line() % rect.Width;\n\tif (pitch == 0) {\n\t\tmemmove(dest, source, tocopy);\n\t} else {\n\n\t\t/*\n\t\t**\tCopy the source to the destination in line segments.\n\t\t*/\n\t\tfor (int y = 0; y < rect.Height; y++) {\n\t\t\tmemmove(dest, source, width);\n\t\t\tdest += rect.Width;\n\t\t\tsource += rect.Width + pitch;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "CODE/SURFACE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/SURFACE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SURFACE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 09/08/96                                                     *\n *                                                                                             *\n *                  Last Update : September 8, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef SURFACE_H\n#define SURFACE_H\n\n#include\t\"buff.h\"\n#include\t\"rect.h\"\n\n/*\n**\tThis class is used to represent an arbitrary rectangle in a graphic memory space. Typically,\n**\tthis represents what could be called a graphic buffer or even a portion of a graphic buffer.\n**\tIt can also represent a piece of artwork (such as a shape image) to be used to construct a\n**\tdisplay image. This wide range of use is possible, because this class is a very minimal\n**\trepresentation of the graphic data. It holds only the information is absolutely needs and\n**\thas the minimum member functions possible.\n*/\nclass Surface\n{\n\tpublic:\n\t\tSurface(void) : Width(0), Height(0), Pitch(0) {}\n\t\tSurface(int w, int h, Buffer const * buffer=NULL, int pitch=0);\n\t\tSurface(Surface const & surface, int x, int y, int w, int h);\n\t\tvirtual ~Surface(void) {}\n\n\t\t/*\n\t\t**\tBasic manipulation routines for copying entire surfaces or\n\t\t**\ta sub-region.\n\t\t*/\n\t\tvoid Copy_To(Rect const & fromrect, Surface & tosurface, Rect const & torect) const;\n\t\tvoid Copy_To(Rect const & fromrect, Buffer & tobuffer) const;\n\n\t\t/*\n\t\t**\tConvenience routines that make presumptions on what is desired so that a\n\t\t**\tminimum of parameters can be specified. These routine ultimately map to the\n\t\t**\tbasic copy routines.\n\t\t*/\n\t\tvoid Copy_To(Buffer & buffer, int x=0, int y=0, int w=-1, int h=-1) const;\n\t\tvoid Copy_From(Buffer const & buffer, int x=0, int y=0, int w=-1, int h=-1);\n\n\t\t/*\n\t\t**\tBasic query functions. Support routines that will manipulate the underlying\n\t\t**\timage data will require access to this information.\n\t\t*/\n\t\tvoid * Get_Buffer(void) const {return(SurfaceData.Get_Buffer());}\n\t\tint Get_Size(void) const {return(Bytes_Per_Line() * Height);}\n\t\tint Get_Width(void) const {return(Width);}\n\t\tint Get_Height(void) const {return(Height);}\n\t\tint Get_Pitch(void) const {return(Pitch);}\n\n\tprotected:\n\t\tint Bytes_Per_Line(void) const {return(Width+Pitch);}\n\n\t\t/*\n\t\t**\tThis is the pointer to the surface memory. Sometimes this could be allocated memory\n\t\t**\tmanaged by this class but more likely, it is memory that is merely referred to by\n\t\t**\tthis class.\n\t\t*/\n\t\tBuffer SurfaceData;\n\n\t\t/*\n\t\t**\tThis is the width (columns) of the surface (in pixels).\n\t\t*/\n\t\tint Width;\n\n\t\t/*\n\t\t**\tThis ithe height (rows) of the surface (in pixels).\n\t\t*/\n\t\tint Height;\n\n\t\t/*\n\t\t**\tThis is the modulus of the surface underlying memory 'display surface' width\n\t\t**\tdivided by this surface's width. For a surface that is full width, this value\n\t\t**\twill be 0. This value will be non-zero if this surface is referring to a\n\t\t**\tsub-region within another surface.\n\t\t*/\n\t\tint Pitch;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/TAB.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TAB.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TAB.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : September 20, 1995 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   TabClass::AI -- Handles player I/O with the tab buttons.                                  *\n *   TabClass::Draw_It -- Displays the tab buttons as necessary.                               *\n *   TabClass::One_Time -- Performs one time initialization of tab handler class.              *\n *   TabClass::Set_Active -- Activates a \"filefolder tab\" button.                              *\n *   TabClass::TabClass -- Default construct for the tab button class.                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\nvoid const * TabClass::TabShape = NULL;\n\n\n/***********************************************************************************************\n * TabClass::TabClass -- Default construct for the tab button class.                           *\n *                                                                                             *\n *    The default constructor merely sets the tab buttons to default non-selected state.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTabClass::TabClass(void) :\n\tFlasherTimer(0),\n\tIsToRedraw(false),\n\tMoneyFlashTimer(0)\n{\n}\n\n\n/***********************************************************************************************\n * TabClass::Draw_It -- Displays the tab buttons as necessary.                                 *\n *                                                                                             *\n *    This routine is called whenever the display is being redrawn (in some fashion). The      *\n *    parameter can be used to force the tab buttons to redraw completely. The default action  *\n *    is to only redraw if the tab buttons have been explicitly flagged to be redraw. The      *\n *    result of this is the elimination of unnecessary redraws.                                *\n *                                                                                             *\n * INPUT:   complete -- bool; Force redraw of the entire tab button graphics?                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/15/1994 JLB : Created.                                                                 *\n *   05/19/1995 JLB : New EVA style.                                                           *\n *=============================================================================================*/\n#define\tEVA_WIDTH\t\t80\n#define\tTAB_HEIGHT\t\t8\nvoid TabClass::Draw_It(bool complete)\n{\n\tSidebarClass::Draw_It(complete);\n\n\tif (Debug_Map) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tRedraw the top bar imagery if flagged to do so or if the entire display needs\n\t**\tto be redrawn.\n\t*/\n\tif ((complete || IsToRedraw) && LogicPage->Lock()) {\n\n\t\tint width  = SeenBuff.Get_Width();\n\t\tint rightx = width - 1;\n\t\tint tab_height = TAB_HEIGHT * RESFACTOR;\n\n\t\tLogicPage->Fill_Rect(0, 0, rightx, tab_height-1, BLACK);\n//\t\tLogicPage->Fill_Rect(0, 0, rightx, tab_height-(2 * RESFACTOR), BLACK);\n\n#ifdef WIN32\n\t\t/*\n\t\t** Use the new sidebar art for 640x400\n\t\t*/\n\t\tCC_Draw_Shape(TabShape, 0, 0, 0, WINDOW_MAIN, SHAPE_NORMAL);\n#else\n\t\tCC_Draw_Shape(TabShape, 2, 0, 0, WINDOW_MAIN, SHAPE_NORMAL);\n#endif\n\t\tDraw_Credits_Tab();\n\t\tLogicPage->Draw_Line(0, tab_height-(1* RESFACTOR), rightx, tab_height-(1 * RESFACTOR), BLACK);\n#ifdef WIN32\n\t\tFancy_Text_Print(TXT_TAB_BUTTON_CONTROLS, (EVA_WIDTH/2) * RESFACTOR, 0, &MetalScheme, TBLACK, TPF_METAL12 | TPF_CENTER | TPF_USE_GRAD_PAL);\n#else\n//\t\t\tFancy_Text_Print(TXT_TAB_BUTTON_CONTROLS, (EVA_WIDTH/2) * RESFACTOR, 0, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW|TPF_CENTER|TPF_BRIGHT_COLOR);\n\t\tFancy_Text_Print(TXT_TAB_BUTTON_CONTROLS, (EVA_WIDTH/2) * RESFACTOR, 0, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_METAL12|TPF_NOSHADOW|TPF_CENTER|TPF_BRIGHT_COLOR);\n#endif\t//WIN32\n\t\tif (IsSidebarActive) {\n#ifndef WIN32\n\t\t\tTabClass::Hilite_Tab(1);\n#endif\t//WIN32\n\t\t} else {\n\t\t\tCC_Draw_Shape(TabShape, 0, width-(EVA_WIDTH * RESFACTOR), 0, WINDOW_MAIN, SHAPE_NORMAL);\n\t\t\tFancy_Text_Print(TXT_TAB_SIDEBAR, width-((EVA_WIDTH/2) * RESFACTOR), 0, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_METAL12|TPF_NOSHADOW|TPF_CENTER|TPF_BRIGHT_COLOR);\n\t\t}\n\n\t\tLogicPage->Unlock();\n\t}\n\tCredits.Graphic_Logic(complete || IsToRedraw);\n\tIsToRedraw = false;\n}\n\n\nvoid TabClass::Draw_Credits_Tab(void)\n{\n#ifdef WIN32\n\t/*\n\t** Use the new sidebar art for 640x400\n\t*/\n\tCC_Draw_Shape(TabShape, Map.MoneyFlashTimer > 1 ? 8 : 6, (320-EVA_WIDTH) * RESFACTOR, 0, WINDOW_MAIN, SHAPE_NORMAL);\n#else\n\tCC_Draw_Shape(TabShape, 4, (320-(EVA_WIDTH*2)) * RESFACTOR, 0, WINDOW_MAIN, SHAPE_NORMAL);\n#endif\n\n\tif (Scen.MissionTimer.Is_Active()) {\n\t\tbool light = (Scen.MissionTimer < TICKS_PER_MINUTE * Rule.TimerWarning) || Map.FlasherTimer > 0;\n#ifdef WIN32\n\t\tCC_Draw_Shape(TabShape, light ? 4 : 2, 320, 0, WINDOW_MAIN, SHAPE_NORMAL);\n#else\n\t\tCC_Draw_Shape(TabShape, light ? 6 : 5, EVA_WIDTH * RESFACTOR, 0, WINDOW_MAIN, SHAPE_NORMAL);\n#endif\n\t}\n}\n\n\nvoid TabClass::Hilite_Tab(int tab)\n{\n\tint xpos = 0;\n\tint text = TXT_TAB_BUTTON_CONTROLS;\n\tint textx = (EVA_WIDTH/2) * RESFACTOR;\n\n\tif (tab) {\n\t\txpos = (320-EVA_WIDTH) * RESFACTOR;\n\t\ttext = TXT_TAB_SIDEBAR;\n\t\ttextx = (320-(EVA_WIDTH/2)) * RESFACTOR;\n\t}\n\n#ifdef WIN32\n\t/*\n\t** Use the new sidebar art for 640x400\n\t*/\n\tCC_Draw_Shape(TabShape, 1, xpos, 0, WINDOW_MAIN, SHAPE_NORMAL);\n\tMetalScheme.Color = 128+6;\n\tFancy_Text_Print(TXT_TAB_BUTTON_CONTROLS, (EVA_WIDTH/2) * RESFACTOR, 0, &MetalScheme, TBLACK, TPF_METAL12 | TPF_CENTER | TPF_USE_GRAD_PAL);\n\tMetalScheme.Color = 128;\n#else\n\tCC_Draw_Shape(TabShape, 1 + (tab ? 0 : 2), xpos, 0, WINDOW_MAIN, SHAPE_NORMAL);\n\tFancy_Text_Print(text, textx, 0, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_METAL12|TPF_NOSHADOW|TPF_CENTER|TPF_BRIGHT_COLOR);\n//\tFancy_Text_Print(text, textx, 0, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW|TPF_CENTER|TPF_BRIGHT_COLOR);\n#endif\n}\n\n\n/***********************************************************************************************\n * TabClass::AI -- Handles player I/O with the tab buttons.                                    *\n *                                                                                             *\n *    This routine is called every game tick and passed whatever key the player has supplied.  *\n *    If the input selects a tab button, then the graphic gets updated accordingly.            *\n *                                                                                             *\n * INPUT:   input -- The player's input character (might be mouse click).                      *\n *                                                                                             *\n *          x,y   -- Mouse coordinates at time of input.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/15/1994 JLB : Created.                                                                 *\n *   12/31/1994 JLB : Uses mouse coordinate parameters.                                        *\n *   05/31/1995 JLB : Fixed to handle mouse shape properly.                                    *\n *   08/25/1995 JLB : Handles new scrolling option.                                            *\n *=============================================================================================*/\nvoid TabClass::AI(KeyNumType &input, int x, int y)\n{\n\tif (y >= 0 && y < (TAB_HEIGHT * RESFACTOR) && x < (SeenBuff.Get_Width() - 1) && x > 0) {\n\n\t\tbool \tok = false;\n\t\tint\twidth = SeenBuff.Get_Width();\n\n\t\t/*\n\t\t**\tIf the mouse is at the top of the screen, then the tab bars only work\n\t\t**\tin certain areas. If the special scroll modification is not active, then\n\t\t**\tthe tabs never work when the mouse is at the top of the screen.\n\t\t*/\n\t\tif (y > 0) {\n\t\t\tok = true;\n\t\t}\n\n\t\tif (ok) {\n\t\t\tif (input == KN_LMOUSE) {\n\t\t\t\tint sel = -1;\n\t\t\t\tif (x < EVA_WIDTH * RESFACTOR) sel = 0;\n#ifndef WIN32\t// No Sidebar tab in hires - sidebar is always active.\n\t\t\t\tif (x > (320-80) * RESFACTOR) sel = 1;\n#endif\t//WIN32\n\t\t\t\tif (sel >= 0) {\n\t\t\t\t\tSet_Active(sel);\n\t\t\t\t\tinput = KN_NONE;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tOverride_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t}\n\t}\n\n\tif (MoneyFlashTimer == 1) {\n\t\tIsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\t}\n\n\tCredits.AI();\n\n\tSidebarClass::AI(input, x, y);\n}\n\n\n/***********************************************************************************************\n * TabClass::Set_Active -- Activates a \"filefolder tab\" button.                                *\n *                                                                                             *\n *    This function is used to activate one of the file folder tab buttons that appear at the  *\n *    top edge of the screen.                                                                  *\n *                                                                                             *\n * INPUT:   select   -- The button to activate. 0 = left button, 1=next button, etc.           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TabClass::Set_Active(int select)\n{\n\tswitch (select) {\n\t\tcase 0:\n\t\t\tQueue_Options();\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tMap.SidebarClass::Activate(-1);\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * TabClass::One_Time -- Performs one time initialization of tab handler class.                *\n *                                                                                             *\n *    This routine will perform any one time initializations of the tab handler class. This    *\n *    typically includes the loading of the shapes that appear on it.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TabClass::One_Time(void)\n{\n\tSidebarClass::One_Time();\n\tRawFileClass file(\"tabs.shp\");\n\tTabShape = MFCD::Retrieve(\"TABS.SHP\");\n}\n\n\nvoid TabClass::Flash_Money(void)\n{\n\tIsToRedraw = true;\n\tFlag_To_Redraw(false);\n\tMoneyFlashTimer = 7;\n}\n"
  },
  {
    "path": "CODE/TAB.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TAB.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TAB.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : December 15, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TAB_H\n#define TAB_H\n\n#include\t\"sidebar.h\"\n#include\t\"credits.h\"\n\nclass TabClass: public SidebarClass\n{\n\tpublic:\n\t\tTabClass(void);\n\t\tTabClass(NoInitClass const & x) : SidebarClass(x), Credits(x), FlasherTimer(x), MoneyFlashTimer(x) {};\n\n\t\tvirtual void AI(KeyNumType &input, int x, int y);\n\t\tvirtual void Draw_It(bool complete=false);\n\t\tstatic void Draw_Credits_Tab(void);\n\t\tstatic void Hilite_Tab(int tab);\n\t\tvoid Flash_Money(void);\n\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t\t// One-time inits\n\t\tvoid Redraw_Tab(void) {IsToRedraw = true;Flag_To_Redraw(false);};\n\n\t\tCreditClass Credits;\n\n\t\tCDTimerClass<FrameTimerClass> FlasherTimer;\n\n\tprotected:\n\n\t\t/*\n\t\t**\tIf the tab graphic is to be redrawn, then this flag is true.\n\t\t*/\n\t\tunsigned IsToRedraw:1;\n\n\tprivate:\n\t\tvoid Set_Active(int select);\n\n\t\tCDTimerClass<FrameTimerClass> MoneyFlashTimer;\n\n\t\tstatic void const * TabShape;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/TACTION.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TACTION.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ACTION.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/28/95                                                     *\n *                                                                                             *\n *                  Last Update : July 17, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Action_From_Name -- retrieves ActionType for given name                                   *\n *   Action_Needs -- Figures out what data an action object needs.                             *\n *   Name_From_Action -- retrieves name for ActionType                                         *\n *   TActionClass::Build_INI_Entry -- Builds an INI entry for this trigger action.             *\n *   TActionClass::Code_Pointers -- Convert embedded pointers into a transportable format.     *\n *   TActionClass::Decode_Pointers -- Converts coded pointers into usable format.              *\n *   TActionClass::Detach -- Removes any attachment from associated action.                    *\n *   TActionClass::Read_INI -- Converts INI text into appropriate action data.                 *\n *   TActionClass::operator -- Performs the action that this object does.                      *\n *   ActionChoiceClass::Draw_It -- Display the action choice as part of a list box.            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n/*\n**\tThese are the text names for the various actions. If the action name ends with \"...\" then\n**\tthis means that additional data is probably required.\n*/\nstatic const char * ActionText[TACTION_COUNT] = {\n\t\"-No Action-\",\n\t\"Winner is...\",\n\t\"Loser is...\",\n\t\"Production Begins\",\n\t\"Create Team...\",\n\t\"Destroy All Teams\",\n\t\"All to Hunt...\",\n\t\"Reinforcement (team)...\",\n\t\"Drop Zone Flare (waypoint)...\",\n\t\"Fire Sale...\",\n\t\"Play Movie...\",\n\t\"Text Trigger (ID num)...\",\n\t\"Destroy Trigger...\",\n\t\"Autocreate Begins...\",\n\t\"~don't use~\",\n\t\"Allow Win\",\n\t\"Reveal all map\",\n\t\"Reveal around waypoint...\",\n\t\"Reveal zone of waypoint...\",\n\t\"Play sound effect...\",\n\t\"Play music theme...\",\n\t\"Play speech...\",\n\t\"Force Trigger...\",\n\t\"Timer Start\",\n\t\"Timer Stop\",\n\t\"Timer Extend (1/10th min)...\",\n\t\"Timer Shorten (1/10th min)...\",\n\t\"Timer Set (1/10th min)...\",\n\t\"Global Set...\",\n\t\"Global Clear...\",\n\t\"Auto Base Building...\",\n\t\"Grow shroud one 'step'\",\n\t\"Destroy attached building\",\n\t\"Add 1-time special weapon...\",\n\t\"Add repeating special weapon...\",\n\t\"Preferred target...\",\n\t\"Launch Nukes\"\n};\n\n\nActionChoiceClass ActionChoices[TACTION_COUNT] = {\n\t{TACTION_NONE},\n\t{TACTION_WIN},\n\t{TACTION_LOSE},\n\t{TACTION_BEGIN_PRODUCTION},\n\t{TACTION_CREATE_TEAM},\n\t{TACTION_DESTROY_TEAM},\n\t{TACTION_ALL_HUNT},\n\t{TACTION_REINFORCEMENTS},\n\t{TACTION_DZ},\n\t{TACTION_FIRE_SALE},\n\t{TACTION_PLAY_MOVIE},\n\t{TACTION_TEXT_TRIGGER},\n\t{TACTION_DESTROY_TRIGGER},\n\t{TACTION_AUTOCREATE},\n\t{TACTION_WINLOSE},\n\t{TACTION_ALLOWWIN},\n\t{TACTION_REVEAL_ALL},\n\t{TACTION_REVEAL_SOME},\n\t{TACTION_REVEAL_ZONE},\n\t{TACTION_PLAY_SOUND},\n\t{TACTION_PLAY_MUSIC},\n\t{TACTION_PLAY_SPEECH},\n\t{TACTION_FORCE_TRIGGER},\n\t{TACTION_START_TIMER},\n\t{TACTION_STOP_TIMER},\n\t{TACTION_ADD_TIMER},\n\t{TACTION_SUB_TIMER},\n\t{TACTION_SET_TIMER},\n\t{TACTION_SET_GLOBAL},\n\t{TACTION_CLEAR_GLOBAL},\n\t{TACTION_BASE_BUILDING},\n\t{TACTION_CREEP_SHADOW},\n\t{TACTION_DESTROY_OBJECT},\n\t{TACTION_1_SPECIAL},\n\t{TACTION_FULL_SPECIAL},\n\t{TACTION_PREFERRED_TARGET},\n\t{TACTION_LAUNCH_NUKES}\n};\n\n\n/***********************************************************************************************\n * ActionChoiceClass::Draw_It -- Display the action choice as part of a list box.              *\n *                                                                                             *\n *    This is a support routine only used to display this object when it is part of a list     *\n *    box.                                                                                     *\n *                                                                                             *\n * INPUT:   x,y   -- The coordinate (upper left) to display the description.                   *\n *                                                                                             *\n *          width,height   -- Dimensions of the area to display the description.               *\n *                                                                                             *\n *          selected -- Is this item highlighted?                                              *\n *                                                                                             *\n *          flags -- The text print flags to use.                                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ActionChoiceClass::Draw_It(int , int x, int y, int width, int height, bool selected, TextPrintType flags) const\n{\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\tstatic int _tabs[] = {13,40};\n\tif ((flags & 0x0F) == TPF_6PT_GRAD || (flags & 0x0F) == TPF_EFNT) {\n\n\t\tif (selected) {\n\t\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\t\tLogicPage->Fill_Rect(x, y, x + width - 1, y + height - 1, scheme->Shadow);\n\t\t} else {\n\t\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t\t}\n\t\t}\n\n\t\tConquer_Clip_Text_Print(Description(), x, y, scheme, TBLACK, flags, width, _tabs);\n\t} else {\n\t\tConquer_Clip_Text_Print(Description(), x, y, (selected ? &ColorRemaps[PCOLOR_DIALOG_BLUE] : &ColorRemaps[PCOLOR_GREY]), TBLACK, flags, width, _tabs);\n\t}\n}\n\n\n/***********************************************************************************************\n * TActionClass::Detach -- Removes any attachment from associated action.                      *\n *                                                                                             *\n *    This routine will remove any action reference to the team type specified. This routine   *\n *    is called when the team type is being destroyed. All references to that team type must   *\n *    also be severed. This routine does that with respect to trigger actions.                 *\n *                                                                                             *\n * INPUT:   target-- The target object or type to remove from this taction object.             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/22/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TActionClass::Detach(TARGET target)\n{\n\tif (Is_Target_TeamType(target) && Team == As_TeamType(target)) {\n\t\tTeam = NULL;\n\t}\n\tif (Is_Target_TriggerType(target) && Trigger == As_TriggerType(target)) {\n\t\tTrigger = NULL;\n\t}\n}\n\n\n/***********************************************************************************************\n * TActionClass::Build_INI_Entry -- Builds an INI entry for this trigger action.               *\n *                                                                                             *\n *    This routine will build the text (INI entry) format for the data of this trigger         *\n *    action object. Typical use of this is when the INI file is being written.                *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the location to build the INI text to. The buffer is presumed  *\n *                   to be big enough.                                                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The buffer passed to this routine must be big enough to hold the largest        *\n *             text that will be created into it.                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/22/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TActionClass::Build_INI_Entry(char * ptr) const\n{\n\tsprintf(ptr, \"%d,%d,%d,%d\", Action, TeamTypes.Logical_ID(Team), TriggerTypes.Logical_ID(Trigger), Data.Value);\n}\n\n\n/***********************************************************************************************\n * TActionClass::Read_INI -- Converts INI text into appropriate action data.                   *\n *                                                                                             *\n *    This routine will convert INI data into the right values within this trigger action      *\n *    object. Typical use of this routine is when the INI file is being read. It is the        *\n *    counterpart to the Build_INI_Entry function.                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/22/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TActionClass::Read_INI(void)\n{\n\tswitch (NewINIFormat) {\n\t\tdefault:\n\t\t\tAction = TActionType(atoi(strtok(NULL, \",\")));\n\t\t\tTeam.Set_Raw(atoi(strtok(NULL, \",\")));\n\t\t\tTrigger.Set_Raw(atoi(strtok(NULL, \",\")));\n\t\t\tData.Value = atoi(strtok(NULL, \",\"));\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\tcase 0:\n\t\t\tAction = TActionType(atoi(strtok(NULL, \",\")));\n\n\t\t\tchar const * ptr = strtok(NULL, \",\");\n\t\t\tTeam = TeamTypeClass::From_Name(ptr);\n\t\t\tassert(Action_Needs(Action) != NEED_TEAM || Team.Is_Valid());\n\n\t\t\t/*\n\t\t\t**\tSince triggers refer to other triggers, only record a copy of the trigger text\n\t\t\t**\tname. This will be fixed up later.\n\t\t\t*/\n\t\t\tTrigger.Set_Raw((long)strdup(strtok(NULL, \",\")));\n\n\t\t\tData.Value = atoi(strtok(NULL, \",\"));\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * TActionClass::Code_Pointers -- Convert embedded pointers into a transportable format.       *\n *                                                                                             *\n *    This routine is called prior to saving the game. It will convert any pointers into a     *\n *    format that is safe for persistent storage.                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine makes the object unfit for use. The Decode_Pointers() routine      *\n *             must be called prior to using this object.                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/22/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TActionClass::Code_Pointers(void)\n{\n}\n\n\n/***********************************************************************************************\n * TActionClass::Decode_Pointers -- Converts coded pointers into usable format.                *\n *                                                                                             *\n *    This routine is called after a game has been loaded. The encoded pointers will be        *\n *    converted back into usable format by this routine.                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine will NOT work unless the pointer are, in fact, coded. There is     *\n *             no prevention check to protect against calling this routine twice.              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/22/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TActionClass::Decode_Pointers(void)\n{\n}\n\n\n/***********************************************************************************************\n * TActionClass::operator -- Performs the action that this object does.                        *\n *                                                                                             *\n *    This routine is called when the action associated with this action object must be        *\n *    performed. Typically, this occurs when a trigger has \"sprung\" and now it must take       *\n *    effect. The action object is what carries out this effect.                               *\n *                                                                                             *\n * INPUT:   house -- The owner of this action. This information is necessary since some        *\n *                   actions depend on who the trigger was owned by.                           *\n *                                                                                             *\n *          object-- Pointer to the object that the springing trigger was attached to. If      *\n *                   this parameter is null, then the trigger wasn't attached to any object.   *\n *                                                                                             *\n *          id    -- Trigger ID (only if forced) otherwise -1.                                 *\n *                                                                                             *\n *          cell  -- The cell this trigger is attached to (if any).                            *\n *                                                                                             *\n * OUTPUT:  bool; Was this action able to perform what it needed to do? Failure could be       *\n *                because a reinforcement couldn't be generated, for example.                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/22/1996 JLB : Created.                                                                 *\n *   04/10/1996 JLB : Added the ID parameter.                                                  *\n *=============================================================================================*/\nbool TActionClass::operator() (HousesType house, ObjectClass * object, int id, CELL cell)\n{\n\t/*\n\t**\tOtherwise, take an appropriate action.\n\t*/\n\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\tTriggerClass * trig = NULL;\n\tif (id != -1) {\n\t\ttrig = Triggers.Raw_Ptr(id);\n\t}\n\tbool success = true;\n//\tTeamTypeClass * ttype = Team;\n\n\t/*\n\t**\tEnsure that the specified object is not actually dead. A dead object could\n\t**\tbe passed to this routine in the case of a multiple event trigger that\n\t**\thad the first event kill the object.\n\t*/\n\tif (object && !object->IsActive) {\n\t\tobject = 0;\n\t}\n\n\tswitch (Action) {\n\t\t/*\n\t\t**\tDisplay a text message overlayed onto the tactical map.\n\t\t*/\n\t\tcase TACTION_TEXT_TRIGGER:\n\t\t\tSession.Messages.Add_Message(NULL, 0, (char *)TutorialText[Data.Value], PCOLOR_GREEN, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\t\tbreak;\n\n\t\t/*\n\t\t** Launch nuclear missiles (duds) from all mslo's\n\t\t*/\n\t\tcase TACTION_LAUNCH_NUKES:\n\t\t\t{\n\t\t\t\tfor(int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\tBuildingClass *bldg = Buildings.Ptr(index);\n\t\t\t\t\tif (*bldg == STRUCT_MSLO) {\n\t\t\t\t\t\tbldg->Assign_Mission(MISSION_MISSILE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t/*\n\t\t**\tSet the preferred target for the house.\n\t\t*/\n\t\tcase TACTION_PREFERRED_TARGET:\n\t\t\tif (hptr) {\n\t\t\t\thptr->PreferredTarget = Data.Quarry;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tInitiate (or disable) the computer AI. When active, the computer will\n\t\t**\tbuild bases and units.\n\t\t*/\n\t\tcase TACTION_BASE_BUILDING:\n\t\t\tif (Data.Bool) {\n\t\t\t\thptr->IsBaseBuilding = true;\n\t\t\t} else {\n\t\t\t\thptr->IsBaseBuilding = false;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tCause the shadow to creep back one step.\n\t\t*/\n\t\tcase TACTION_CREEP_SHADOW:\n\t\t\tMap.Encroach_Shadow();\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tSet a scenario global.\n\t\t*/\n\t\tcase TACTION_SET_GLOBAL:\n\t\t\tScen.Set_Global_To(Data.Value, true);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tClear a scenario global.\n\t\t*/\n\t\tcase TACTION_CLEAR_GLOBAL:\n\t\t\tScen.Set_Global_To(Data.Value, false);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tReveal the map around the area specified.\n\t\t*/\n\t\tcase TACTION_REVEAL_SOME:\n\t\t\tif (!PlayerPtr->IsVisionary) {\n\t\t\t\tMap.Sight_From(Scen.Waypoint[Data.Value], Rule.GapShroudRadius, PlayerPtr, false);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tReveal all cells of the zone that the specified waypoint is located\n\t\t**\tin. This can be used to reveal whole islands or bodies of water\n\t\t*/\n\t\tcase TACTION_REVEAL_ZONE:\n\t\t\tif (!PlayerPtr->IsVisionary) {\n\t\t\t\tint zone = Map[Scen.Waypoint[Data.Value]].Zones[MZONE_CRUSHER];\n\n\t\t\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\t\tif (Map[cell].Zones[MZONE_CRUSHER] == zone) {\n\t\t\t\t\t\tMap.Map_Cell(cell, PlayerPtr);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tReveal the entire map.\n\t\t*/\n\t\tcase TACTION_REVEAL_ALL:\n\t\t\tif (!PlayerPtr->IsVisionary) {\n\t\t\t\tPlayerPtr->IsVisionary = true;\n\t\t\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\t\tMap.Map_Cell(cell, PlayerPtr);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tStar the mission timer.\n\t\t*/\n\t\tcase TACTION_START_TIMER:\n\t\t\tif (!Scen.MissionTimer.Is_Active()) {\n\t\t\t\tScen.MissionTimer.Start();\n\t\t\t\tMap.Redraw_Tab();\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tStop the mission timer. This will really just\n\t\t**\tsuspend the timer.\n\t\t*/\n\t\tcase TACTION_STOP_TIMER:\n\t\t\tif (Scen.MissionTimer.Is_Active()) {\n\t\t\t\tScen.MissionTimer.Stop();\n\t\t\t\tMap.Redraw_Tab();\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tAdd time to the mission timer.\n\t\t*/\n\t\tcase TACTION_ADD_TIMER:\n\t\t\tScen.MissionTimer = Scen.MissionTimer + (Data.Value * (TICKS_PER_MINUTE/10));\n\t\t\tMap.Redraw_Tab();\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tRemove time from the mission timer.\n\t\t*/\n\t\tcase TACTION_SUB_TIMER:\n\t\t\tif (Scen.MissionTimer <= Data.Value * (TICKS_PER_MINUTE/10)) {\n\t\t\t\tScen.MissionTimer = 0;\n\t\t\t} else {\n\t\t\t\tScen.MissionTimer = Scen.MissionTimer - (Data.Value * (TICKS_PER_MINUTE/10));\n\t\t\t}\n\t\t\tMap.Redraw_Tab();\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tSet the mission timer to the value specified.\n\t\t*/\n\t\tcase TACTION_SET_TIMER:\n\t\t\tScen.MissionTimer = Data.Value * (TICKS_PER_MINUTE/10);\n\t\t\tScen.MissionTimer.Start();\n\t\t\tMap.Redraw_Tab();\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tPlay a movie immediately. The game is temporarily\n\t\t**\tsuspended while the movie plays.\n\t\t*/\n\t\tcase TACTION_PLAY_MOVIE:\n\t\t\tHide_Mouse();\n\t\t\tSeenPage.Clear();\n\t\t\tPlay_Movie(Data.Movie, THEME_NONE, true);\n\t\t\tGamePalette.Set();\n\t\t\tMap.Flag_To_Redraw(true);\n\t\t\tShow_Mouse();\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tPlay a sound effect.\n\t\t*/\n\t\tcase TACTION_PLAY_SOUND:\n\t\t\tSound_Effect(Data.Sound);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tPlay a musical theme.\n\t\t*/\n\t\tcase TACTION_PLAY_MUSIC:\n\t\t\tTheme.Queue_Song(Data.Theme);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tPlay the speech data specified.\n\t\t*/\n\t\tcase TACTION_PLAY_SPEECH:\n\t\t\tSpeak(Data.Speech);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tGive the special weapon to the house.\n\t\t*/\n\t\tcase TACTION_1_SPECIAL:\n\t\tcase TACTION_FULL_SPECIAL:\n\t\t\thptr->SuperWeapon[Data.Special].Enable(Action==TACTION_1_SPECIAL, false);\n//\t\t\thptr->SuperWeapon[Data.Special].Forced_Charge(PlayerPtr == hptr);\n\n\t\t\tif (PlayerPtr == hptr) {\n\t\t\t\tMap.Add(RTTI_SPECIAL, Data.Special);\n\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tDestroying a trigger means that all triggers of that type will be destroyed.\n\t\t*/\n\t\tcase TACTION_DESTROY_TRIGGER:\n\t\t\tif (Trigger.Is_Valid()) {\n\t\t\t\tfor (int index = 0; index < Triggers.Count(); index++) {\n\t\t\t\t\tif (Triggers.Ptr(index)->Class == Trigger) {\n\t\t\t\t\t\tDetach_This_From_All(Triggers.Ptr(index)->As_Target());\n\t\t\t\t\t\tdelete Triggers.Ptr(index);\n\t\t\t\t\t\tindex--;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tA forced trigger will force an existing trigger of that type or\n\t\t**\twill create a trigger of that type and then force it to be sprung.\n\t\t*/\n\t\tcase TACTION_FORCE_TRIGGER:\n\t\t\tif (Trigger.Is_Valid()) {\n\t\t\t\tFind_Or_Make(Trigger)->Spring(TEVENT_ANY, 0, 0, true);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tPlace a smoke marker at the waypoint specified.\n\t\t*/\n\t\tcase TACTION_DZ:\n\t\t\tnew AnimClass(ANIM_LZ_SMOKE, Cell_Coord(Scen.Waypoint[Data.Value]));\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tFlag the house specified as the winner. Really the house value\n\t\t**\tis only used to determine if it is the player or the computer.\n\t\t*/\n\t\tcase TACTION_WIN:\n\t\t\tif (Data.House == PlayerPtr->Class->House) {\n\t\t\t\tPlayerPtr->Flag_To_Win();\n\t\t\t} else {\n\t\t\t\tPlayerPtr->Flag_To_Lose();\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tFlag the house specified as the loser. The house parameter is only\n\t\t**\tused to determine if it refers to the player or the computer.\n\t\t*/\n\t\tcase TACTION_LOSE:\n\t\t\tif (Data.House != PlayerPtr->Class->House) {\n\t\t\t\tPlayerPtr->Flag_To_Win();\n\t\t\t} else {\n\t\t\t\tPlayerPtr->Flag_To_Lose();\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThis will enable production to begin for the house specified.\n\t\t*/\n\t\tcase TACTION_BEGIN_PRODUCTION:\n\t\t\tif (Data.House != HOUSE_NONE) {\n\t\t\t\tHouseClass * specified_house = HouseClass::As_Pointer(Data.House);\n\t\t\t\tspecified_house->Begin_Production();\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tCause all buildings to be sold and all units to go into\n\t\t**\thunt mode.\n\t\t*/\n\t\tcase TACTION_FIRE_SALE:\n\t\t\tif (Data.House != HOUSE_NONE) {\n\t\t\t\tHouseClass * specified_house = HouseClass::As_Pointer(Data.House);\n\t\t\t\tspecified_house->State = STATE_ENDGAME;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tBegin the team autocreate logic for the house specified.\n\t\t*/\n\t\tcase TACTION_AUTOCREATE:\n\t\t\tif (Data.House != HOUSE_NONE) {\n\t\t\t\tHouseClass * specified_house = HouseClass::As_Pointer(Data.House);\n\t\t\t\tspecified_house->IsAlerted = true;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tManually create the team specified.\n\t\t*/\n\t\tcase TACTION_CREATE_TEAM:\n\t\t\tScenarioInit++;\n\t\t\tTeam->Create_One_Of();\n\t\t\tScenarioInit--;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tDestroy all teams of the type specified.\n\t\t*/\n\t\tcase TACTION_DESTROY_TEAM:\n\t\t\tTeam->Destroy_All_Of();\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tCreate a reinforcement of the team specified.\n\t\t*/\n\t\tcase TACTION_REINFORCEMENTS:\n\t\t\tsuccess = Do_Reinforcements(&*Team);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tForce all units of the house specified to go into\n\t\t**\thunt mode.\n\t\t*/\n\t\tcase TACTION_ALL_HUNT:\n\t\t\tHouseClass::As_Pointer(Data.House)->Do_All_To_Hunt();\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThis will destroy all objects that this trigger is\n\t\t**\tattached to.\n\t\t*/\n\t\tcase TACTION_DESTROY_OBJECT:\n\t\t\tif (object) {\n\t\t\t\tint damage = object->Strength;\n\t\t\t\tobject->Take_Damage(damage, 0, WARHEAD_AP, 0, true);\n\t\t\t} else {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the trigger is attached to a bridge, then the bridge\n\t\t\t**\tgets destroyed regardless of whether the trigger was a\n\t\t\t**\tforced or natural spring event.\n\t\t\t*/\n\t\t\tif (cell != 0) {\n\t\t\t\tMap.Destroy_Bridge_At(cell);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tLoop through and destroy all objects that have this trigger\n\t\t\t**\tattached to them.\n\t\t\t*/\n\t\t\tif (trig) {\n\t\t\t\tfor (int u_index = 0; u_index < Units.Count(); u_index++) {\n\t\t\t\t\tUnitClass * unit = Units.Ptr(u_index);\n\n\t\t\t\t\tif (unit && unit->Trigger == trig) {\n\t\t\t\t\t\tunit->Trigger = NULL;\n\t\t\t\t\t\tint damage = unit->Strength;\n\t\t\t\t\t\tunit->Take_Damage(damage, 0, WARHEAD_AP, 0, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (int i_index = 0; i_index < Infantry.Count(); i_index++) {\n\t\t\t\t\tInfantryClass * infantry = Infantry.Ptr(i_index);\n\n\t\t\t\t\tif (infantry && infantry->Trigger == trig) {\n\t\t\t\t\t\tinfantry->Trigger = NULL;\n\t\t\t\t\t\tint damage = infantry->Strength;\n\t\t\t\t\t\tinfantry->Take_Damage(damage, 0, WARHEAD_AP, 0, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (int a_index = 0; a_index < Aircraft.Count(); a_index++) {\n\t\t\t\t\tAircraftClass * aircraft = Aircraft.Ptr(a_index);\n\n\t\t\t\t\tif (aircraft && aircraft->Trigger == trig) {\n\t\t\t\t\t\taircraft->Trigger = NULL;\n\t\t\t\t\t\tint damage = aircraft->Strength;\n\t\t\t\t\t\taircraft->Take_Damage(damage, 0, WARHEAD_AP, 0, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (int b_index = 0; b_index < Buildings.Count(); b_index++) {\n\t\t\t\t\tBuildingClass * building = Buildings.Ptr(b_index);\n\n\t\t\t\t\tif (building && building->Trigger == trig) {\n\t\t\t\t\t\tbuilding->Trigger = NULL;\n\t\t\t\t\t\tint damage = building->Strength;\n\t\t\t\t\t\tbuilding->Take_Damage(damage, 0, WARHEAD_AP, 0, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tDo no action at all.\n\t\t*/\n\t\tcase TACTION_NONE:\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(success);\n}\n\n\n/***********************************************************************************************\n * Action_From_Name -- retrieves ActionType for given name                                     *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      name         name to get ActionType for                                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      ActionType for given name                                                              *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/29/1994 BR : Created.                                                                  *\n *=============================================================================================*/\nTActionType Action_From_Name (char const * name)\n{\n\tif (name == NULL) {\n\t\treturn(TACTION_NONE);\n\t}\n\n\tfor (TActionType i = TACTION_NONE; i < TACTION_COUNT; i++) {\n\t\tif (!stricmp(name, ActionText[i])) {\n\t\t\treturn(i);\n\t\t}\n\t}\n\n\treturn(TACTION_NONE);\n}\n\n\n/***********************************************************************************************\n * Name_From_Action -- retrieves name for ActionType                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      action      ActionType to get name for                                                 *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      name of ActionType                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/29/1994 BR : Created.                                                                  *\n *=============================================================================================*/\nchar const * Name_From_Action(TActionType action)\n{\n\treturn(ActionText[action]);\n}\n\n\n/***********************************************************************************************\n * Action_Needs -- Figures out what data an action object needs.                               *\n *                                                                                             *\n *    Use this routine to determine what extra data is needed for the specified action. This   *\n *    data will be prompted for in the scenario editor.                                        *\n *                                                                                             *\n * INPUT:   action   -- The action that is to be queried.                                      *\n *                                                                                             *\n * OUTPUT:  Returns with the data type (enumeration) needed for this action type.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/22/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nNeedType Action_Needs(TActionType action)\n{\n\tswitch (action) {\n\t\tcase TACTION_1_SPECIAL:\n\t\tcase TACTION_FULL_SPECIAL:\n\t\t\treturn(NEED_SPECIAL);\n\n\t\tcase TACTION_FIRE_SALE:\n\t\tcase TACTION_WIN:\n\t\tcase TACTION_LOSE:\n\t\tcase TACTION_ALL_HUNT:\n\t\tcase TACTION_BEGIN_PRODUCTION:\n\t\tcase TACTION_AUTOCREATE:\n\t\t\treturn(NEED_HOUSE);\n\n\t\tcase TACTION_BASE_BUILDING:\n\t\t\treturn(NEED_BOOL);\n\n\t\tcase TACTION_CREATE_TEAM:\n\t\tcase TACTION_DESTROY_TEAM:\n\t\tcase TACTION_REINFORCEMENTS:\n\t\t\treturn(NEED_TEAM);\n\n\t\tcase TACTION_FORCE_TRIGGER:\n\t\tcase TACTION_DESTROY_TRIGGER:\n\t\t\treturn(NEED_TRIGGER);\n\n\t\tcase TACTION_DZ:\n\t\t\treturn(NEED_WAYPOINT);\n\n\t\tcase TACTION_REVEAL_SOME:\n\t\tcase TACTION_REVEAL_ZONE:\n\t\t\treturn(NEED_WAYPOINT);\n\n\t\tcase TACTION_PLAY_MUSIC:\n\t\t\treturn(NEED_THEME);\n\n\t\tcase TACTION_PLAY_MOVIE:\n\t\t\treturn(NEED_MOVIE);\n\n\t\tcase TACTION_PLAY_SOUND:\n\t\t\treturn(NEED_SOUND);\n\n\t\tcase TACTION_PLAY_SPEECH:\n\t\t\treturn(NEED_SPEECH);\n\n\t\tcase TACTION_TEXT_TRIGGER:\n\t\tcase TACTION_ADD_TIMER:\n\t\tcase TACTION_SUB_TIMER:\n\t\tcase TACTION_SET_TIMER:\n\t\tcase TACTION_SET_GLOBAL:\n\t\tcase TACTION_CLEAR_GLOBAL:\n\t\t\treturn(NEED_NUMBER);\n\n\t\tcase TACTION_PREFERRED_TARGET:\n\t\t\treturn(NEED_QUARRY);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(NEED_NONE);\n}\n\n\n"
  },
  {
    "path": "CODE/TACTION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TACTION.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ACTION.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/28/95                                                     *\n *                                                                                             *\n *                  Last Update : November 28, 1995 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef ACTION_H\n#define ACTION_H\n\ntypedef enum TActionType {\n\tTACTION_NONE,\n\n\tTACTION_WIN,\t\t\t\t\t\t\t\t// player wins!\n\tTACTION_LOSE,\t\t\t\t\t\t\t\t// player loses.\n\tTACTION_BEGIN_PRODUCTION,\t\t\t\t// computer begins factory production.\n\tTACTION_CREATE_TEAM,\t\t\t\t\t\t// computer creates a certain type of team\n\tTACTION_DESTROY_TEAM,\n\tTACTION_ALL_HUNT,\t\t\t\t\t\t\t// all enemy units go into hunt mode (teams destroyed).\n\tTACTION_REINFORCEMENTS,\t\t\t\t\t// player gets reinforcements\n\t\t\t\t\t\t\t\t\t\t\t\t\t// (house that gets them is determined by\n\t\t\t\t\t\t\t\t\t\t\t\t\t// the Reinforcement instance)\n\tTACTION_DZ,\t\t\t\t\t\t\t\t\t// Deploy drop zone smoke.\n\tTACTION_FIRE_SALE,\t\t\t\t\t\t// Sell all buildings and go on rampage.\n\tTACTION_PLAY_MOVIE,\t\t\t\t\t\t//\tPlay movie (temporarily suspend game).\n\tTACTION_TEXT_TRIGGER,\t\t\t\t\t// Triggers a text message display.\n\tTACTION_DESTROY_TRIGGER,\t\t\t\t// Destroy specified trigger.\n\tTACTION_AUTOCREATE,\t\t\t\t\t\t// Computer to autocreate teams.\n\tTACTION_WINLOSE,\t\t\t\t\t\t\t// Win if captured, lose if destroyed.\n\tTACTION_ALLOWWIN,\t\t\t\t\t\t\t// Allows winning if triggered.\n\n\tTACTION_REVEAL_ALL,\t\t\t\t\t\t// Reveal the entire map.\n\tTACTION_REVEAL_SOME,\t\t\t\t\t\t// Reveal map around cell #.\n\tTACTION_REVEAL_ZONE,\t\t\t\t\t\t// Reveal all of specified zone.\n\tTACTION_PLAY_SOUND,\t\t\t\t\t\t// Play sound effect.\n\tTACTION_PLAY_MUSIC,\t\t\t\t\t\t// Play musical score.\n\tTACTION_PLAY_SPEECH,\t\t\t\t\t\t// Play EVA speech.\n\tTACTION_FORCE_TRIGGER,\t\t\t\t\t// Force trigger to activate.\n\tTACTION_START_TIMER,\t\t\t\t\t\t// Start mission timer.\n\tTACTION_STOP_TIMER,\t\t\t\t\t\t// Stop mission timer.\n\tTACTION_ADD_TIMER,\t\t\t\t\t\t// Increase mission timer time.\n\tTACTION_SUB_TIMER,\t\t\t\t\t\t// Decrease mission timer time.\n\tTACTION_SET_TIMER,\t\t\t\t\t\t// Set and start the mission timer.\n\tTACTION_SET_GLOBAL,\t\t\t\t\t\t// Set global variable.\n\tTACTION_CLEAR_GLOBAL,\t\t\t\t\t// Clear global variable.\n\tTACTION_BASE_BUILDING,\t\t\t\t\t// Automated base building.\n\tTACTION_CREEP_SHADOW,\t\t\t\t\t// Shadow grows back one 'step'.\n\n\tTACTION_DESTROY_OBJECT,\t\t\t\t\t// Destroys the building this trigger is attached to.\n\tTACTION_1_SPECIAL,\t\t\t\t\t\t// Add a one-time special weapon ability to house.\n\tTACTION_FULL_SPECIAL,\t\t\t\t\t// Add a repeating special weapon ability to house.\n\n\tTACTION_PREFERRED_TARGET,\t\t\t\t// Designates preferred target for house.\n\tTACTION_LAUNCH_NUKES,\t\t\t\t\t// Launch fake nuclear missiles from all silos\n\n\tTACTION_COUNT,\n\tTACTION_FIRST=0\n} TActionType;\n\nTActionType Action_From_Name(char const * name);\nchar const * Name_From_Action(TActionType action);\nNeedType Action_Needs(TActionType action);\n\nclass TriggerTypeClass;\nclass TeamTypeClass;\n\n/*\n**\tThis elaborates the information necessary to carry out\n**\ta trigger's action.\n*/\nstruct TActionClass {\n\tTActionType\t\tAction;\t// Action to perform.\n\n\tCCPtr<TeamTypeClass> Team;\t// Team type pointer for this action (if needed).\n\n\tCCPtr<TriggerTypeClass> Trigger;\t// Trigger type pointer for this action (if needed).\n\n\tunion {\n\t\tThemeType\t\t\tTheme;\t\t// Musical theme.\n\t\tVocType\t\t\t\tSound;\t\t// Sound effect.\n\t\tVoxType\t\t\t\tSpeech;\t\t// Speech identifier.\n\t\tHousesType\t\t\tHouse;\t\t// House to be affected.\n\t\tSpecialWeaponType Special;\t\t// Special weapon ability.\n\t\tQuarryType\t\t\tQuarry;\t\t// Preferred target for attack.\n\t\tVQType\t\t\t\tMovie;\t\t// The movie to play.\n\t\tbool\t\t\t\t\tBool;\t\t\t// Boolean value.\n\t\tlong\t\t\t\t\tValue;\n\t} Data;\n\n\tTActionClass(void) : Action(TACTION_NONE) {\n\t\tData.Theme = THEME_NONE;\n\t\tData.Value = -1;\n\t};\n\tTActionClass(NoInitClass const & x) : Team(x), Trigger(x) {};\n\n\tvoid Detach(TARGET target);\n\tvoid Code_Pointers(void);\n\tvoid Decode_Pointers(void);\n\tvoid Read_INI(void);\n\tvoid Build_INI_Entry(char * buffer) const;\n\n\tbool operator() (HousesType house, ObjectClass * object, int id, CELL cell);\n};\n\n\nclass ActionChoiceClass {\n\tpublic:\n\t\tActionChoiceClass(TActionType event=TACTION_NONE) : Action(event) {}\n\n\t\toperator TActionType (void) const {return(Action);}\n\t\tbool operator == (ActionChoiceClass const & rvalue) const {return(Action == rvalue.Action);}\n\t\tbool operator != (ActionChoiceClass const & rvalue) const {return(Action != rvalue.Action);}\n\t\tbool operator > (ActionChoiceClass const & rvalue) const {return(stricmp(Description(), rvalue.Description()) > 0);}\n\t\tbool operator < (ActionChoiceClass const & rvalue) const {return(stricmp(Description(), rvalue.Description()) < 0);}\n\t\tbool operator <= (ActionChoiceClass const & rvalue) const {return(Action == rvalue.Action || stricmp(Description(), rvalue.Description()) < 0);}\n\t\tbool operator >= (ActionChoiceClass const & rvalue) const {return(Action == rvalue.Action || stricmp(Description(), rvalue.Description()) > 0);}\n\t\tchar const * Description(void) const {return(Name_From_Action(Action));}\n\t\tvoid Draw_It(int index, int x, int y, int width, int height, bool selected, TextPrintType flags) const;\n\n\t\tTActionType Action;\n};\n\n\nextern ActionChoiceClass ActionChoices[TACTION_COUNT];\n\n#endif\n"
  },
  {
    "path": "CODE/TARCOM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TARCOM.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TARCOM.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 16, 1994                                               *\n *                                                                                             *\n *                  Last Update : July 19, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   TarComClass::AI -- Handles the logical AI for the tarcom class.                           *\n *   TarComClass::Debug_Dump -- Displays the status of the tarcom class to the mono screen.    *\n *   TarComClass::~TarComClass -- Destructor for turret object.                                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * TarComClass::~TarComClass -- Destructor for turret object.                                  *\n *                                                                                             *\n *    This is the destructor for turret objects.                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTarComClass::~TarComClass(void)\n{\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * TarComClass::Debug_Dump -- Displays the status of the tarcom class to the mono screen.      *\n *                                                                                             *\n *    This routine is used to display the tarcom class status to the monochrome monitor.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TarComClass::Debug_Dump(MonoClass *mono) const\n{\n\tTurretClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * TarComClass::AI -- Handles the logical AI for the tarcom class.                             *\n *                                                                                             *\n *    This handles the AI logic for the targeting computer.                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TarComClass::AI(void)\n{\n\tassert(IsActive);\n\n\tTurretClass::AI();\n\n\tif (!IsActive) return;\n\n\tif (Class->Primary != WEAPON_NONE) {\n\n\t\t/*\n\t\t**\tDetermine which weapon can fire. First check for the primary weapon. If that weapon\n\t\t**\tcannot fire, then check any secondary weapon. If neither weapon can fire, then the\n\t\t**\tfailure code returned is that from the primary weapon.\n\t\t*/\n\t\tWeaponTypeClass const * weapon = &Weapons[Class->Primary];\n\t\tint primary = 0;\n\t\tFireErrorType ok = Can_Fire(TarCom, 0);\n\t\tif (ok != FIRE_OK) {\n\t\t\tif (Can_Fire(TarCom, 1) == FIRE_OK) {\n\t\t\t\tok = FIRE_OK;\n\t\t\t\tprimary = 1;\n\t\t\t\tweapon = &Weapons[Class->Secondary];\n\t\t\t}\n\t\t}\n\n\t\tswitch (ok) {\n\t\t\tcase FIRE_OK:\n//\t\t\t\tif (What_Am_I() != RTTI_UNIT) {\n//\t\t\t\t\tIsFiring = false;\n//\t\t\t\t} else {\n\t\t\t\t\tif (!((UnitClass *)this)->Class->IsFireAnim) {\n\t\t\t\t\t\tMark(MARK_OVERLAP_UP);\n\t\t\t\t\t\tIsFiring = false;\n\t\t\t\t\t\tMark(MARK_OVERLAP_DOWN);\n\t\t\t\t\t}\n//\t\t\t\t}\n\n\t\t\t\tif (TurretClass::Fire_At(TarCom, primary)) {\n//\t\t\t\t\tSound_Effect(weapon->Sound, Coord);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase FIRE_FACING:\n\t\t\t\tif (Class->IsLockTurret) {\n\t\t\t\t\tif (!Target_Legal(NavCom) && !IsDriving) {\n\t\t\t\t\t\tPrimaryFacing.Set_Desired(Direction(TarCom));\n\t\t\t\t\t\tSecondaryFacing.Set_Desired(PrimaryFacing.Desired());\n\t\t\t\t\t}\n\t\t\t\t} else {\n#ifdef OLD\n\t\t\t\t\tif (*this == UNIT_FTANK) {\n\t\t\t\t\t\tSecondaryFacing.Set_Desired(Facing_Dir(Dir_Facing(Direction(TarCom))));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSecondaryFacing.Set_Desired(Direction(TarCom));\n\t\t\t\t\t}\n#else\n\t\t\t\t\tSecondaryFacing.Set_Desired(Direction(TarCom));\n#endif\n//\t\t\t\t\tSecondaryFacing.Set_Desired(Direction256(Center_Coord(), As_Coord(TarCom)));\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase FIRE_CLOAKED:\n\t\t\t\tMark(MARK_OVERLAP_UP);\n\t\t\t\tIsFiring = false;\n\t\t\t\tMark(MARK_OVERLAP_DOWN);\n\t\t\t\tDo_Uncloak();\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (Target_Legal(TarCom) && !IsRotating) {\n\t\tDirType dir = Direction(TarCom);\n\n\t\tif (Class->IsTurretEquipped) {\n\t\t\tSecondaryFacing.Set_Desired(dir);\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tNon turret equipped vehicles will rotate their body to face the target only\n\t\t\t**\tif the vehicle isn't currently moving or facing the correct direction. This\n\t\t\t**\tapplies only to tracked vehicles. Wheeled vehicles never rotate to face the\n\t\t\t**\ttarget, since they aren't maneuverable enough.\n\t\t\t*/\n\t\t\tif ((Class->Speed == SPEED_TRACK /* || *this == UNIT_BIKE */ ) && !Target_Legal(NavCom) && !IsDriving && PrimaryFacing.Difference(dir)) {\n#ifdef OLD\n\t\t\t\tif (*this == UNIT_FTANK) {\n\t\t\t\t\tPrimaryFacing.Set_Desired(Facing_Dir(Dir_Facing(dir)));\n\t\t\t\t} else {\n\t\t\t\t\tPrimaryFacing.Set_Desired(dir);\n\t\t\t\t}\n#else\n\t\t\t\tPrimaryFacing.Set_Desired(dir);\n#endif\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n"
  },
  {
    "path": "CODE/TARCOM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\tarcom.h_v   2.17   01 Mar 1996 17:27:24   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               *** \n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TARCOM.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 23, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TARCOM_H\n#define TARCOM_H\n\n#include\t\"turret.h\"\n#include\t\"bullet.h\"\n\n/****************************************************************************\n**\tUnits that can perform combat are handled by this class. It performs\n**\tsuch operations as determining threat value down to actually launching the\n**\tprojectile.\n*/\nclass TarComClass : public TurretClass\n{\n\tpublic:\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tTarComClass(void) {};\n\t\tTarComClass(UnitType classid, HousesType house) : TurretClass(classid, house) {};\n\t\tvirtual ~TarComClass(void);\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\t\tvirtual void AI(void);\n//\t\tvirtual bool Target_Something_Nearby(ThreatType rangmatters=THREAT_NORMAL);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n\n};\n\n#endif\n\n\n"
  },
  {
    "path": "CODE/TARGET.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TARGET.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TARGET.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : July 16, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   As_Aircraft -- Converts the target value into an aircraft pointer.                        *\n *   As_Animation -- Converts target value into animation pointer.                             *\n *   As_Building -- Converts a target value into a building object pointer.                    *\n *   As_Bullet -- Converts the target into a bullet pointer.                                   *\n *   As_Cell -- Converts a target value into a cell number.                                    *\n *   As_Coord -- Converts a target value into a coordinate value.                              *\n *   As_Infantry -- If the target is infantry, return a pointer to it.                         *\n *   As_Movement_Coord -- Fetches coordinate if trying to move to this target.                 *\n *   As_Object -- Converts a target value into an object pointer.                              *\n *   As_Target -- Converts a cell into a target value.                                         *\n *   As_Target -- Converts a coordinate into a target value.                                   *\n *   As_Team -- Converts a target number into a team pointer.                                  *\n *   As_TeamType -- Converts a target into a team type pointer.                                *\n *   As_Techno -- Converts a target value into a TechnoClass pointer.                          *\n *   As_TechnoType -- Convert the target number into a techno type class pointer.              *\n *   As_Trigger -- Converts specified target into a trigger pointer.                           *\n *   As_TriggerType -- Convert the specified target into a trigger type.                       *\n *   As_Unit -- Converts a target value into a unit pointer.                                   *\n *   As_Vessel -- Converts a target number into a vessel pointer.                              *\n *   TClass::TClass -- Constructor for target from object pointer.                             *\n *   TargetClass::As_Object -- Converts a target into an object pointer.                       *\n *   TargetClass::As_Techno -- Converts a target into a techno object pointer.                 *\n *   Target_Legal -- Determines if the specified target is legal.                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"target.h\"\n\n\nTargetClass::TargetClass(TARGET target)\n{\n\tTarget.Target = target;\n}\n\n\nTargetClass::TargetClass(AbstractClass const * ptr) {\n\tif (ptr != NULL) {\n\t\tTarget.Sub.Exponent = ptr->RTTI;\n\t\tTarget.Sub.Mantissa = ptr->ID;\n\t} else {\n\t\tTarget.Sub.Exponent = RTTI_NONE;\n\t}\n}\n\nTargetClass::TargetClass(AbstractTypeClass const * ptr) {\n\tif (ptr != NULL) {\n\t\tTarget.Sub.Exponent = ptr->RTTI;\n\t\tTarget.Sub.Mantissa = ptr->ID;\n\t} else {\n\t\tTarget.Sub.Exponent = RTTI_NONE;\n\t}\n}\n\nTargetClass::TargetClass(CellClass const * ptr) {\n\tif (ptr != NULL) {\n\t\tTarget.Sub.Exponent = RTTI_CELL;\n\t\tTarget.Sub.Mantissa = ptr->ID;\n\t} else {\n\t\tTarget.Sub.Exponent = RTTI_NONE;\n\t}\n}\n\nCellClass * xTargetClass::As_Cell(void) const\n{\n\tif (Target.Sub.Exponent == RTTI_CELL) {\n\t\treturn(&Map[(CELL)Target.Sub.Mantissa]);\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * As_Trigger -- Converts specified target into a trigger pointer.                             *\n *                                                                                             *\n *    This routine will convert the specified target number into a trigger pointer.            *\n *                                                                                             *\n * INPUT:   target   -- The target number to convert.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the trigger pointer that the specified target number represents. If   *\n *          it doesn't represent a legal trigger object, then NULL is returned.                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTriggerClass * As_Trigger(TARGET target)\n{\n\treturn(Is_Target_Trigger(target) ? Triggers.Raw_Ptr(Target_Value(target)) : NULL);\n}\n\n\n/***********************************************************************************************\n * As_Team -- Converts a target number into a team pointer.                                    *\n *                                                                                             *\n *    This routine will convert the specified target number into a team pointer.               *\n *                                                                                             *\n * INPUT:   target   -- The target number to convert.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the team object that the specified target number represents. If it    *\n *          doesn't represent a legal team then NULL is returned.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTeamClass * As_Team(TARGET target)\n{\n\treturn(Is_Target_Team(target) ? Teams.Raw_Ptr(Target_Value(target)) : NULL);\n}\n\n\n/***********************************************************************************************\n * As_TeamType -- Converts a target into a team type pointer.                                  *\n *                                                                                             *\n *    This routine will convert the specified target number into a team type pointer.          *\n *                                                                                             *\n * INPUT:   target   -- The target number to convert.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the team type represented by the target number. If the   *\n *          target number doesn't represent a legal team type, then NULL is returned.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTeamTypeClass * As_TeamType(TARGET target)\n{\n\treturn(Is_Target_TeamType(target) ? TeamTypes.Raw_Ptr(Target_Value(target)) : NULL);\n}\n\n\n/***********************************************************************************************\n * As_Animation -- Converts target value into animation pointer.                               *\n *                                                                                             *\n *    This routine will convert the specified target number into an animation pointer.         *\n *                                                                                             *\n * INPUT:   target   -- The target number to convert into an animation pointer.                *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the legal animation that this target represents. If it   *\n *          doesn't represent a legal animation, then NULL is returned.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nAnimClass * As_Animation(TARGET target)\n{\n\treturn(Is_Target_Animation(target) ? Anims.Raw_Ptr(Target_Value(target)) : NULL);\n}\n\n\n/***********************************************************************************************\n * As_Bullet -- Converts the target into a bullet pointer.                                     *\n *                                                                                             *\n *    This routine will convert the specified target number into a bullet pointer.             *\n *                                                                                             *\n * INPUT:   target   -- The target number to convert.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the bullet it specifies. If the target doesn't refer to  *\n *          a legal bullet, then NULL is returned.                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nBulletClass * As_Bullet(TARGET target)\n{\n\treturn(Is_Target_Bullet(target) ? Bullets.Raw_Ptr(Target_Value(target)) : NULL);\n}\n\n\n/***********************************************************************************************\n * As_Aircraft -- Converts the target value into an aircraft pointer.                          *\n *                                                                                             *\n *    This routine will convert the specified target value into an aircraft object pointer.    *\n *                                                                                             *\n * INPUT:   target   -- The target value to convert.                                           *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the aircraft that this target value represents. If the   *\n *          specified target value doesn't represent an aircraft, then NULL is returned.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nAircraftClass * As_Aircraft(TARGET target)\n{\n\treturn(Is_Target_Aircraft(target) ? Aircraft.Raw_Ptr(Target_Value(target)) : NULL);\n}\n\n\n/***********************************************************************************************\n * As_Techno -- Converts a target value into a TechnoClass pointer.                            *\n *                                                                                             *\n *    This routine will take the target value specified and convert it into a TechnoClass      *\n *    pointer if the target represents an object that has a TechnoClass.                       *\n *                                                                                             *\n * INPUT:   target   -- The target value to convert into a TechnoClass pointer.                *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the associated object's TechnoClass. If the target       *\n *          cannot be converted into a TechnoClass pointer, then NULL is returned.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTechnoClass * As_Techno(TARGET target)\n{\n\tObjectClass * obj = As_Object(target);\n\n\tif (obj && obj->Is_Techno()) {\n\t\treturn(TechnoClass *)obj;\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * As_Object -- Converts a target value into an object pointer.                                *\n *                                                                                             *\n *    This routine is used to convert the target value specified into an object pointer. If    *\n *    the target doesn't represent an object or the target value is illegal, then NULL is      *\n *    returned.                                                                                *\n *                                                                                             *\n * INPUT:   target   -- The target value to convert from.                                      *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the object it represent, or NULL if not an object.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * As_Object(TARGET target)\n{\n\tint val = Target_Value(target);\n\tObjectClass * object = NULL;\n\tswitch (Target_Kind(target)) {\n\t\tcase RTTI_INFANTRY:\n\t\t\tobject = Infantry.Raw_Ptr(val);\n\t\t\tbreak;\n\n\t\tcase RTTI_UNIT:\n\t\t\tobject = Units.Raw_Ptr(val);\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\t\tobject = Vessels.Raw_Ptr(val);\n\t\t\tbreak;\n\n\t\tcase RTTI_BUILDING:\n\t\t\tobject = Buildings.Raw_Ptr(val);\n\t\t\tbreak;\n\n\t\tcase RTTI_AIRCRAFT:\n\t\t\tobject = Aircraft.Raw_Ptr(val);\n\t\t\tbreak;\n\n\t\tcase RTTI_TERRAIN:\n\t\t\tobject = Terrains.Raw_Ptr(val);\n\t\t\tbreak;\n\n\t\tcase RTTI_BULLET:\n\t\t\tobject = Bullets.Raw_Ptr(val);\n\t\t\tbreak;\n\n\t\tcase RTTI_ANIM:\n\t\t\tobject = Anims.Raw_Ptr(val);\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tSpecial check to ensure that a target value that references an\n\t**\tinvalid object will not be converted back into an object pointer.\n\t**\tThis condition is rare, but could occur in a network game if the\n\t**\tobject it refers to is destroyed between the time an event message\n\t**\tis sent and when it is received.\n\t*/\n\tif (object != NULL && !object->IsActive) {\n\t\tobject = NULL;\n\t}\n\n\treturn(object);\n}\n\n\n/***********************************************************************************************\n * As_Unit -- Converts a target value into a unit pointer.                                     *\n *                                                                                             *\n *    This routine is used to convert the target value specified into a pointer to a unit      *\n *    object.                                                                                  *\n *                                                                                             *\n * INPUT:   target   -- The target value to convert into a unit pointer.                       *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the unit the target value represents or NULL if not      *\n *          a unit.                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nUnitClass * As_Unit(TARGET target)\n{\n\treturn(Is_Target_Unit(target) ? Units.Raw_Ptr(Target_Value(target)) : NULL);\n}\n\n\n/***********************************************************************************************\n * As_Vessel -- Converts a target number into a vessel pointer.                                *\n *                                                                                             *\n *    Use this routine to conver the specified target number into a pointer to a vessel object *\n *    that it represents.                                                                      *\n *                                                                                             *\n * INPUT:   target   -- The target number to convert to a vessel pointer.                      *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the vessel object that this target value represents. If  *\n *          the target number does not represent a vessel, then null is returned.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nVesselClass * As_Vessel(TARGET target)\n{\n\treturn(Is_Target_Vessel(target) ? Vessels.Raw_Ptr(Target_Value(target)) : NULL);\n}\n\n\n/***********************************************************************************************\n * As_Infantry -- If the target is infantry, return a pointer to it.                           *\n *                                                                                             *\n *    This routine will translate the specified target value into an infantry pointer if the   *\n *    target actually represents an infantry object.                                           *\n *                                                                                             *\n * INPUT:   target   -- The target to convert to a pointer.                                    *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to the infantry object that this target value represents. If     *\n *          the target doesn't represent an infantry object, then return NULL.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nInfantryClass * As_Infantry(TARGET target)\n{\n\treturn(Is_Target_Infantry(target) ? Infantry.Raw_Ptr(Target_Value(target)) : NULL);\n}\n\n\n/***********************************************************************************************\n * As_Building -- Converts a target value into a building object pointer.                      *\n *                                                                                             *\n *    This routine is used to convert the target value specified into a building pointer.      *\n *                                                                                             *\n * INPUT:   target   -- The target value to convert from.                                      *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the building object that the target value represents.    *\n *          If it doesn't represent a building, then return NULL.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuildingClass * As_Building(TARGET target)\n{\n\treturn(Is_Target_Building(target) ? Buildings.Raw_Ptr(Target_Value(target)) : NULL);\n}\n\n\n#ifdef NEVER\n/***********************************************************************************************\n * Target_Legal -- Determines if the specified target is legal.                                *\n *                                                                                             *\n *    This routine is used to check for the legality of the target value specified. It is      *\n *    necessary to call this routine if there is doubt about the the legality of the target.   *\n *    It is possible for the unit that a target value represents to be eliminated and thus     *\n *    rendering the target value invalid.                                                      *\n *                                                                                             *\n * INPUT:   target   -- The target value to check.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Is the target value legal?                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool Target_Legal(TARGET target)\n{\n\tif (!Target_Legal(target)) return(false);\n\n\tObjectClass * obj = As_Object(target);\n\tif (obj) {\n\t\treturn(obj->Get_Strength() > 0 && obj->IsActive && !obj->IsInLimbo && obj->Class_Of().IsLegalTarget);\n\t}\n\treturn(true);\n}\n#endif\n\n\n/***********************************************************************************************\n * As_Cell -- Converts a target value into a cell number.                                      *\n *                                                                                             *\n *    This routine is used to convert the target value specified, into a cell value. This is   *\n *    necessary for find path and other procedures that need a cell value.                     *\n *                                                                                             *\n * INPUT:   target   -- The target value to convert to a cell value.                           *\n *                                                                                             *\n * OUTPUT:  Returns with the target value expressed as a cell location.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL As_Cell(TARGET target)\n{\n\treturn(Coord_Cell(As_Coord(target)));\n}\n\n\n/***********************************************************************************************\n * As_Coord -- Converts a target value into a coordinate value.                                *\n *                                                                                             *\n *    This routine is used to convert the target value specified into a coordinate value. It   *\n *    is necessary for those procedures that require a coordinate value.                       *\n *                                                                                             *\n * INPUT:   target   -- The target value to convert.                                           *\n *                                                                                             *\n * OUTPUT:  Returns with the target expressed as a COORDINATE value.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *   11/16/1994 JLB : Simplified.                                                              *\n *=============================================================================================*/\nCOORDINATE As_Coord(TARGET target)\n{\n\tif (Target_Legal(target)) {\n\t\t/*\n\t\t**\tCell target values are handled as a special case. The value of the target number is\n\t\t**\tactually the cell index number.\n\t\t*/\n\t\tif (Is_Target_Cell(target)) {\n\t\t\tint v = Target_Value(target);\n\n\t\t\tint x = ((v & 0x0FFF) << 4) + 0x0008;\n\t\t\tint y = (((v>>12) & 0x0FFF) << 4) + 0x0008;\n\t\t\treturn(XY_Coord(x, y));\n\n//\t\t\treturn(Cell_Coord((CELL)Target_Value(target)));\n\t\t}\n\n\t\t/*\n\t\t**\tNormal targets correspond to game objects. Fetch the object pointer and then ask it\n\t\t**\tfor the center coordinate. Return the center coordinate as the target's coordinate.\n\t\t*/\n\t\tObjectClass * obj = As_Object(target);\n\t\tif (obj != NULL) {\n\t\t\tassert(obj->IsActive);\n\t\t\treturn(obj->Target_Coord());\n\t\t}\n\t}\n\n\t/*\n\t**\tAn unrecognized target value results in a null coordinate value.\n\t*/\n\treturn(0x00000000L);\n}\n\n\n/***********************************************************************************************\n * As_Movement_Coord -- Fetches coordinate if trying to move to this target.                   *\n *                                                                                             *\n *    This routine will convert the specified target into a coordinate location. This location *\n *    is used when moving to the target specified. For cells, this is the center of the cell.  *\n *    For special buildings that allow docking, it is the center location of the docking       *\n *    bay.                                                                                     *\n *                                                                                             *\n * INPUT:   target   -- The target to convert into a coordinate value.                         *\n *                                                                                             *\n * OUTPUT:  Returns with the docking coordinate of the target value specified.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE As_Movement_Coord(TARGET target)\n{\n\tif (Target_Legal(target)) {\n\t\t/*\n\t\t**\tCell target values are handled as a special case. The value of the target number is\n\t\t**\tactually the cell index number.\n\t\t*/\n\t\tif (Is_Target_Cell(target)) {\n\t\t\treturn(Cell_Coord((CELL)Target_Value(target)));\n\t\t}\n\n\t\t/*\n\t\t**\tNormal targets correspond to game objects. Fetch the object pointer and then ask it\n\t\t**\tfor the center coordinate. Return the center coordinate as the target's coordinate.\n\t\t*/\n\t\tObjectClass * obj = As_Object(target);\n\t\tif (obj) {\n\t\t\treturn(obj->Docking_Coord());\n\t\t}\n\t}\n\n\t/*\n\t**\tAn unrecognized target value results in a null coordinate value.\n\t*/\n\treturn(0x00000000L);\n}\n\n\n/***********************************************************************************************\n * TargetClass::As_Object -- Converts a target into an object pointer.                         *\n *                                                                                             *\n *    If the target represents an object of some type, then this routine will return a         *\n *    pointer to the object. Otherwise it will return NULL.                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the object that this target represents or NULL if it     *\n *          doesn't represent a target.                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nAbstractClass * xTargetClass::As_Abstract(void) const\n{\n\tswitch ((RTTIType)*this) {\n\t\tcase RTTI_TEAM:\n\t\t\treturn(Teams.Raw_Ptr(Value()));\n\n\t\tcase RTTI_BULLET:\n\t\t\treturn(Bullets.Raw_Ptr(Value()));\n\n\t\tcase RTTI_OVERLAY:\n\t\t\treturn(Overlays.Raw_Ptr(Value()));\n\n\t\tcase RTTI_SMUDGE:\n\t\t\treturn(Smudges.Raw_Ptr(Value()));\n\n\t\tcase RTTI_UNIT:\n\t\t\treturn(Units.Raw_Ptr(Value()));\n\n\t\tcase RTTI_VESSEL:\n\t\t\treturn(Vessels.Raw_Ptr(Value()));\n\n\t\tcase RTTI_BUILDING:\n\t\t\treturn(Buildings.Raw_Ptr(Value()));\n\n\t\tcase RTTI_INFANTRY:\n\t\t\treturn(Infantry.Raw_Ptr(Value()));\n\n\t\tcase RTTI_AIRCRAFT:\n\t\t\treturn(Aircraft.Raw_Ptr(Value()));\n\n\t\tcase RTTI_TERRAIN:\n\t\t\treturn(Terrains.Raw_Ptr(Value()));\n\n\t\tcase RTTI_ANIM:\n\t\t\treturn(Anims.Raw_Ptr(Value()));\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(0);\n}\n\n\nAbstractTypeClass * xTargetClass::As_TypeClass(void) const\n{\n\tswitch ((RTTIType)*this) {\n\t\tcase RTTI_TEAMTYPE:\n\t\t\treturn(TeamTypes.Raw_Ptr(Value()));\n\n\t\tcase RTTI_TRIGGERTYPE:\n\t\t\treturn(TriggerTypes.Raw_Ptr(Value()));\n\n\t\tcase RTTI_BULLETTYPE:\n\t\t\treturn((BulletTypeClass *)&BulletTypeClass::As_Reference(BulletType(Value())));\n\n\t\tcase RTTI_OVERLAY:\n\t\t\treturn((OverlayTypeClass *)&OverlayTypeClass::As_Reference(OverlayType(Value())));\n\n\t\tcase RTTI_SMUDGE:\n\t\t\treturn((SmudgeTypeClass *)&SmudgeTypeClass::As_Reference(SmudgeType(Value())));\n\n\t\tcase RTTI_UNIT:\n\t\t\treturn((UnitTypeClass *)&UnitTypeClass::As_Reference(UnitType(Value())));\n\n\t\tcase RTTI_VESSEL:\n\t\t\treturn((VesselTypeClass *)&VesselTypeClass::As_Reference(VesselType(Value())));\n\n\t\tcase RTTI_BUILDING:\n\t\t\treturn((BuildingTypeClass *)&BuildingTypeClass::As_Reference(StructType(Value())));\n\n\t\tcase RTTI_INFANTRY:\n\t\t\treturn((InfantryTypeClass *)&InfantryTypeClass::As_Reference(InfantryType(Value())));\n\n\t\tcase RTTI_AIRCRAFT:\n\t\t\treturn((AircraftTypeClass *)&AircraftTypeClass::As_Reference(AircraftType(Value())));\n\n\t\tcase RTTI_TERRAIN:\n\t\t\treturn((TerrainTypeClass *)&TerrainTypeClass::As_Reference(TerrainType(Value())));\n\n\t\tcase RTTI_ANIM:\n\t\t\treturn((AnimTypeClass *)&AnimTypeClass::As_Reference(AnimType(Value())));\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * TargetClass::As_Techno -- Converts a target into a techno object pointer.                   *\n *                                                                                             *\n *    This routine is used to convert the target object into a pointer to a techno class       *\n *    object. If the target doesn't specify a techno class object, then NULL is returned.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the techno class object that this target represents or   *\n *          else it returns NULL.                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTechnoClass * xTargetClass::As_Techno(void) const\n{\n\tswitch ((RTTIType)*this) {\n\t\tcase RTTI_UNIT:\n\t\t\treturn(Units.Raw_Ptr(Value()));\n\n\t\tcase RTTI_VESSEL:\n\t\t\treturn(Vessels.Raw_Ptr(Value()));\n\n\t\tcase RTTI_BUILDING:\n\t\t\treturn(Buildings.Raw_Ptr(Value()));\n\n\t\tcase RTTI_INFANTRY:\n\t\t\treturn(Infantry.Raw_Ptr(Value()));\n\n\t\tcase RTTI_AIRCRAFT:\n\t\t\treturn(Aircraft.Raw_Ptr(Value()));\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(0);\n}\n\n\nObjectClass * xTargetClass::As_Object(void) const\n{\n\tswitch ((RTTIType)*this) {\n\t\tcase RTTI_TERRAIN:\n\t\t\treturn(Terrains.Raw_Ptr(Value()));\n\n\t\tcase RTTI_SMUDGE:\n\t\t\treturn(Smudges.Raw_Ptr(Value()));\n\n\t\tcase RTTI_OVERLAY:\n\t\t\treturn(Overlays.Raw_Ptr(Value()));\n\n\t\tcase RTTI_BULLET:\n\t\t\treturn(Bullets.Raw_Ptr(Value()));\n\n\t\tcase RTTI_ANIM:\n\t\t\treturn(Anims.Raw_Ptr(Value()));\n\n\t\tcase RTTI_UNIT:\n\t\t\treturn(Units.Raw_Ptr(Value()));\n\n\t\tcase RTTI_VESSEL:\n\t\t\treturn(Vessels.Raw_Ptr(Value()));\n\n\t\tcase RTTI_BUILDING:\n\t\t\treturn(Buildings.Raw_Ptr(Value()));\n\n\t\tcase RTTI_INFANTRY:\n\t\t\treturn(Infantry.Raw_Ptr(Value()));\n\n\t\tcase RTTI_AIRCRAFT:\n\t\t\treturn(Aircraft.Raw_Ptr(Value()));\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(0);\n}\n\n\n\n\n/***********************************************************************************************\n * As_Target -- Converts a cell into a target value.                                           *\n *                                                                                             *\n *    This routine will convert a cell into a target value.                                    *\n *                                                                                             *\n * INPUT:   cell  -- The cell number that will be coerced into a target value.                 *\n *                                                                                             *\n * OUTPUT:  Returns with the target value that this cell represents.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTARGET As_Target(CELL cell)\n{\n\tint x = Cell_X(cell);\n\tint y = Cell_Y(cell);\n\n\tx <<= 4;\n\ty <<= 4;\n\n\tx += 0x0008;\n\ty += 0x0008;\n\n\treturn(Build_Target(RTTI_CELL, ((y << 12) | x) ));\n}\n\n\n/***********************************************************************************************\n * As_Target -- Converts a coordinate into a target value.                                     *\n *                                                                                             *\n *    This routine is used to convert the specified coordinate into a target value.            *\n *                                                                                             *\n * INPUT:   coord -- The coordinate that is to be converted into a target value.               *\n *                                                                                             *\n * OUTPUT:  Returns with the target value that represents the coordinate.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTARGET As_Target(COORDINATE coord)\n{\n\tint x = Coord_X(coord);\n\tint y = Coord_Y(coord);\n\n\tx >>= 4;\n\ty >>= 4;\n\n\treturn(Build_Target(RTTI_CELL, ((y << 12) | x) ));\n}\n\n\n/***********************************************************************************************\n * As_TechnoType -- Convert the target number into a techno type class pointer.                *\n *                                                                                             *\n *    This routine will conver the specified target number into a pointer to the techno        *\n *    type class that it represents.                                                           *\n *                                                                                             *\n * INPUT:   target   -- The target number to convert.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the TechnoTypeClass object that the target number        *\n *          represents. If it doesn't represent that kind of object, then NULL is returned.    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTechnoTypeClass const * As_TechnoType(TARGET target)\n{\n\tint val = Target_Value(target);\n\tswitch (Target_Kind(target)) {\n\t\tcase RTTI_INFANTRYTYPE:\n\t\t\treturn(&InfantryTypeClass::As_Reference(InfantryType(val)));\n\n\t\tcase RTTI_UNITTYPE:\n\t\t\treturn(&UnitTypeClass::As_Reference(UnitType(val)));\n\n\t\tcase RTTI_VESSELTYPE:\n\t\t\treturn(&VesselTypeClass::As_Reference(VesselType(val)));\n\n\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\treturn(&AircraftTypeClass::As_Reference(AircraftType(val)));\n\n\t\tcase RTTI_BUILDINGTYPE:\n\t\t\treturn(&BuildingTypeClass::As_Reference(StructType(val)));\n\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * As_TriggerType -- Convert the specified target into a trigger type.                         *\n *                                                                                             *\n *    This routine will conver the target number into a pointer to the trigger type it         *\n *    represents.                                                                              *\n *                                                                                             *\n * INPUT:   target   -- The target value to convert into a trigger type pointer.               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the trigger type object that the specified target value  *\n *          represents. If it doesn't represent a trigger type, then NULL is returned.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTriggerTypeClass * As_TriggerType(TARGET target)\n{\n\tif (Target_Kind(target) == RTTI_TRIGGERTYPE) {\n\t\treturn(TriggerTypes.Raw_Ptr(Target_Value(target)));\n\t}\n\treturn(NULL);\n}"
  },
  {
    "path": "CODE/TARGET.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TARGET.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TARGET.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 25, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 25, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TARGET_H\n#define TARGET_H\n\n\ninline RTTIType Target_Kind(TARGET a)\n{\n\treturn(RTTIType(((TARGET_COMPOSITE &)a).Sub.Exponent));\n}\n\ninline unsigned Target_Value(TARGET a)\n{\n\treturn(((TARGET_COMPOSITE &)a).Sub.Mantissa);\n}\n\ninline bool Is_Target_Team(TARGET a) {return (Target_Kind(a) == RTTI_TEAM);}\ninline bool Is_Target_TeamType(TARGET a) {return (Target_Kind(a) == RTTI_TEAMTYPE);}\ninline bool Is_Target_Trigger(TARGET a) {return (Target_Kind(a) == RTTI_TRIGGER);}\ninline bool Is_Target_TriggerType(TARGET a) {return (Target_Kind(a) == RTTI_TRIGGERTYPE);}\ninline bool Is_Target_Infantry(TARGET a) {return (Target_Kind(a) == RTTI_INFANTRY);}\ninline bool Is_Target_Bullet(TARGET a) {return (Target_Kind(a) == RTTI_BULLET);}\ninline bool Is_Target_Terrain(TARGET a) {return (Target_Kind(a) == RTTI_TERRAIN);}\ninline bool Is_Target_Cell(TARGET a) {return (Target_Kind(a) == RTTI_CELL);}\ninline bool Is_Target_Unit(TARGET a) {return (Target_Kind(a) == RTTI_UNIT);}\ninline bool Is_Target_Vessel(TARGET a) {return (Target_Kind(a) == RTTI_VESSEL);}\ninline bool Is_Target_Building(TARGET a) {return (Target_Kind(a) == RTTI_BUILDING);}\ninline bool Is_Target_Template(TARGET a) {return (Target_Kind(a) == RTTI_TEMPLATE);}\ninline bool Is_Target_Aircraft(TARGET a) {return (Target_Kind(a) == RTTI_AIRCRAFT);}\ninline bool Is_Target_Animation(TARGET a) {return (Target_Kind(a) == RTTI_ANIM);}\ninline bool Is_Target_Object(TARGET a)\n{\n\treturn (Target_Kind(a) == RTTI_TERRAIN ||\n\t\t\tTarget_Kind(a) == RTTI_UNIT ||\n\t\t\tTarget_Kind(a) == RTTI_VESSEL ||\n\t\t\tTarget_Kind(a) == RTTI_INFANTRY ||\n\t\t\tTarget_Kind(a) == RTTI_BUILDING ||\n\t\t\tTarget_Kind(a) == RTTI_AIRCRAFT);\n}\n\n\nTARGET As_Target(CELL cell);\nTARGET As_Target(COORDINATE coord);\n//inline TARGET As_Target(CELL cell) {return (TARGET)(((unsigned)RTTI_CELL << TARGET_MANTISSA) | cell);}\n\nclass UnitClass;\nclass BuildingClass;\nclass TechnoClass;\nclass TerrainClass;\nclass ObjectClass;\nclass InfantryClass;\nclass BulletClass;\nclass TriggerClass;\nclass TeamClass;\nclass TeamTypeClass;\nclass AnimClass;\nclass AircraftClass;\nclass VesselClass;\nclass CellClass;\nclass TriggerTypeClass;\n\n/*\n** Must not have a constructor since Watcom cannot handle a class that has a constructor if\n** that class object is in a union. Don't use this class for normal purposes. Use the TargetClass\n**\tinstead. The xTargetClass is only used in one module for a special reason -- keep it that way.\n*/\nclass xTargetClass\n{\n\tprotected:\n\n\t\tTARGET_COMPOSITE Target;\n\n\tpublic:\n\n\t\t// conversion operator to RTTIType\n\t\toperator RTTIType (void) const {return(RTTIType(Target.Sub.Exponent));}\n\n\t\t// comparison operator\n\t\tint operator == (xTargetClass & tgt) {return (tgt.Target.Target==Target.Target ? 1 : 0);}\n\n\t\t// conversion operator to regular TARGET type\n\t\tTARGET As_TARGET(void) const {return(Target.Target);}\n\n\t\tunsigned Value(void) const {return(Target.Sub.Mantissa);};\n\n\t\tvoid Invalidate(void) {Target.Sub.Exponent = RTTI_NONE;Target.Sub.Mantissa = -1;}\n\t\tbool Is_Valid(void) const {return (Target.Sub.Exponent != RTTI_NONE);}\n\n\t\tTARGET As_Target(void) const {return(Target.Target);}\n\t\tAbstractTypeClass * As_TypeClass(void) const;\n\t\tAbstractClass * As_Abstract(void) const;\n\t\tTechnoClass * As_Techno(void) const;\n\t\tObjectClass * As_Object(void) const;\n\t\tCellClass * As_Cell(void) const;\n\n\t\t/*\n\t\t**\tHelper routines to combine testing for, and fetching a pointer to, the\n\t\t**\ttype of object indicated.\n\t\t*/\n\t\tTriggerTypeClass * As_TriggerType(void) const {if (*this == RTTI_TRIGGERTYPE) return((TriggerTypeClass *)As_TypeClass());return(0);}\n\t\tTeamTypeClass * As_TeamType(void) const {if (*this == RTTI_TEAMTYPE) return((TeamTypeClass *)As_TypeClass());return(0);}\n\t\tTerrainClass * As_Terrain(void) const {if (*this == RTTI_TERRAIN) return((TerrainClass *)As_Abstract());return(0);}\n\t\tBulletClass * As_Bullet(void) const {if (*this == RTTI_BULLET) return((BulletClass *)As_Abstract());return(0);}\n\t\tAnimClass * As_Anim(void) const {if (*this == RTTI_ANIM) return((AnimClass *)As_Abstract());return(0);}\n\t\tTeamClass * As_Team(void) const {if (*this == RTTI_TEAM) return((TeamClass *)As_Abstract());return(0);}\n\t\tInfantryClass * As_Infantry(void) const {if (*this == RTTI_INFANTRY) return((InfantryClass *)As_Techno());return(0);}\n\t\tUnitClass * As_Unit(void) const {if (*this == RTTI_UNIT) return((UnitClass *)As_Techno());return(0);}\n\t\tBuildingClass * As_Building(void) const {if (*this == RTTI_BUILDING) return((BuildingClass *)As_Techno());return(0);}\n\t\tAircraftClass * As_Aircraft(void) const {if (*this == RTTI_AIRCRAFT) return((AircraftClass *)As_Techno());return(0);}\n\t\tVesselClass * As_Vessel(void) const {if (*this == RTTI_VESSEL) return((VesselClass *)As_Techno());return(0);}\n};\n\n/*\n**\tThis class only serves as a wrapper to the xTargetClass. This class must not define any members except\n**\tfor the constructors. This is because the xTargetClass is used in a union and this target object is\n**\tused as its initializer. If this class had any extra members they would not be properly copied and\n**\tcommunicated to the other machines in a network/modem game. Combining this class with xTargetClass would\n**\tbe more efficient, but Watcom doesn't allow class objects that have a constructor to be part of a union [even\n**\tif the class object has a default constructor!].\n*/\nclass TargetClass : public xTargetClass\n{\n\tpublic:\n\n\t\tTargetClass(void) {Invalidate();}\n\t\tTargetClass(NoInitClass const &) {}\n\t\tTargetClass(RTTIType rtti, int id) {\n\t\t\tTarget.Sub.Exponent = rtti;\n\t\t\tTarget.Sub.Mantissa = id;\n\t\t}\n\t\tTargetClass(CELL cell) {\n\t\t\tTarget.Sub.Exponent = RTTI_CELL;\n\t\t\tTarget.Sub.Mantissa = cell;\n\t\t}\n\t\tTargetClass(TARGET target);\n\t\tTargetClass(AbstractClass const * ptr);\n\t\tTargetClass(AbstractTypeClass const * ptr);\n\t\tTargetClass(CellClass const * ptr);\n};\n\n#endif\n"
  },
  {
    "path": "CODE/TASM.CFG",
    "content": ""
  },
  {
    "path": "CODE/TCPIP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer - Red Alert            *\n *                                                                         *\n *                    File Name : TCPIP.CPP                                *\n *                                                                         *\n *                   Programmer : Steve Tall                               *\n *                                                                         *\n *                   Start Date : March 11th, 1996                         *\n *                                                                         *\n *                  Last Update : March 20th, 1996 [ST]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Overview:                                                               *\n *                                                                         *\n *  Member functions of the TcpipManagerClass which provides the Winsock   *\n * interface for C&C                                                       *\n *                                                                         *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *                                                                         *\n * TMC::TcpipManagerClass -- constructor for the TcpipManagerClass         *\n * TMC::~TcpipManagerClass -- destructor for the TcpipManagerClass         *\n * TMC::Close -- restores any currently in use Winsock resources           *\n * TMC::Init -- Initialised Winsock for use.                               *\n * TMC::Start_Server -- Initialise connection and start listening.         *\n * TMC::Read -- read any pending input from the stream socket              *\n * TMC::Write -- Send data via the Winsock streaming socket                *\n * TMC::Add_Client -- A client has requested to connect.                   *\n * TMC::Message_Handler -- Message handler for Winsock.                    *\n * TMC::Set_Host_Address -- Set the address of the host                    *\n * TMC::Start_Client -- Start trying to connect to a game host             *\n * TMC::Close_Socket -- Close an opened Winsock socket.                    *\n * TMC::Copy_To_In_Buffer -- copy data from our winsock buffer             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifdef WIN32\n\n#include \"function.h\"\n#include \"tcpip.h\"\n\n\n/*\n** Nasty globals\n*/\n#ifndef WOLAPI_INTEGRATION\nBOOL\t\t\t\t\tServer;\t\t\t//Is this player acting as client or server\n#endif\nTcpipManagerClass\tWinsock;\t\t\t//The object for interfacing with Winsock\n\n\n\n/***********************************************************************************************\n * TMC::TcpipManagerClass -- constructor for the TcpipManagerClass                             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 2:51PM ST : Created                                                              *\n *=============================================================================================*/\nTcpipManagerClass::TcpipManagerClass(void)\n{\n\tWinsockInitialised = FALSE;\n\tConnected = FALSE;\n\tUseUDP = TRUE;\n\tSocketReceiveBuffer = 4096;\n\tSocketSendBuffer = 4096;\n}\n\n\n/***********************************************************************************************\n * TMC::~TcpipManagerClass -- destructor for the TcpipManagerClass                             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 2:52PM ST : Created                                                              *\n *=============================================================================================*/\n\nTcpipManagerClass::~TcpipManagerClass(void)\n{\n\tClose();\n}\n\n\n/***********************************************************************************************\n * TMC::Close -- restores any currently in use Winsock resources                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 2:52PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid TcpipManagerClass::Close(void)\n{\n\t/*\n\t** If we never initialised the class in the first place then just return\n\t*/\n\tif (!WinsockInitialised) return;\n\n\t/*\n\t** Cancel any outstaning asyncronous events\n\t*/\n\tif (Async){\n\t\tWSACancelAsyncRequest(Async);\n\t}\n\n\t/*\n\t** Close any open sockets\n\t*/\n\tif (ConnectSocket != INVALID_SOCKET){\n\t\tClose_Socket(ConnectSocket);\n\t\tConnectSocket = INVALID_SOCKET;\n\t}\n\n\tif (ListenSocket != INVALID_SOCKET){\n\t\tClose_Socket(ListenSocket);\n\t\tListenSocket = INVALID_SOCKET;\n\t}\n\n\tif (UDPSocket != INVALID_SOCKET){\n\t\tClose_Socket(ListenSocket);\n\t\tUDPSocket = INVALID_SOCKET;\n\t}\n\n\t/*\n\t** Call the Winsock cleanup function to say we are finished using Winsock\n\t*/\n\tWSACleanup();\n\n\tWinsockInitialised = FALSE;\n\tConnected = FALSE;\n}\n\n\n\n/***********************************************************************************************\n * TMC::Init -- Initialised Winsock for use.                                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   TRUE if Winsock is available and was initialised                                  *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 2:54PM ST : Created                                                              *\n *=============================================================================================*/\n\nBOOL TcpipManagerClass::Init(void)\n{\n\tshort version;\n\tint \trc;\n\n\t/*\n\t** Just return true if we are already set up\n\t*/\n\tif (WinsockInitialised) return (TRUE);\n\n\t/*\n\t** Initialise sockets to null\n\t*/\n\tListenSocket = INVALID_SOCKET;\n\tConnectSocket =INVALID_SOCKET;\n\tUDPSocket = INVALID_SOCKET;\n\n\t/*\n\t** Start WinSock, and fill in our WinSockData\n\t*/\n\tversion = (WINSOCK_MINOR_VER << 8) | WINSOCK_MAJOR_VER;\n\trc = WSAStartup(version, &WinsockInfo);\n\tif (rc != 0) {\n\t\treturn (FALSE);\n\t}\n\n\t/*\n\t** Check the Winsock version number\n\t*/\n\tif ((WinsockInfo.wVersion & 0x00ff) != (version & 0x00ff) ||\n\t\t(WinsockInfo.wVersion >> 8) != (version >> 8)) {\n\t\treturn (FALSE);\n\t}\n\n\t/*\n\t** Everything is OK so return success\n\t*/\n\tWinsockInitialised = TRUE;\n\treturn (TRUE);\n\n}\n\n\n\n\n/***********************************************************************************************\n * TMC::Start_Server -- initialise out connection as the server. Start listening for clients.  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 2:56PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid TcpipManagerClass::Start_Server(void)\n{\n\tint i;\n\t//struct sockaddr_in addr;\n\n\tStart_Client();\n\n\t/*\n\t** Set up the incoming and outgoing data buffers head and tail pointers\n\t*/\n\tTXBufferHead = 0;\n\tTXBufferTail = 0;\n\tRXBufferHead = 0;\n\tRXBufferTail = 0;\n\n\tfor (i=0 ; i<WS_NUM_TX_BUFFERS ; i++){\n\t\tTransmitBuffers[i].InUse = false;\n\t}\n\n\tfor (i=0 ; i<WS_NUM_RX_BUFFERS ; i++){\n\t\tReceiveBuffers[i].InUse = false;\n\t}\n\n\t/*\n\t** Flag that we are the server side not the client\n\t*/\n\tIsServer = TRUE;\n\tUseUDP = TRUE;\n\tConnectStatus = CONNECTING;\n\n}\n\n\n\n\n/***********************************************************************************************\n * TMC::Read -- read any pending input from the stream socket                                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to buffer to receive input                                                    *\n *           length of buffer                                                                  *\n *                                                                                             *\n * OUTPUT:   number of bytes transfered to buffer                                              *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 2:58PM ST : Created                                                              *\n *=============================================================================================*/\n\nint TcpipManagerClass::Read(void *buffer, int buffer_len)\n{\n\tint \tbytes_copied = 0;\n\tchar \t*dest_buf = (char*) buffer;\n\n\t/*\n\t** Make sure the message loop gets called because all the Winsock notifications\n\t** are done via messages.\n\t*/\n\tKeyboard->Check();\n\n\t/*\n\t** Copy any outstanding incoming data to the buffer provided\n\t*/\n\tif (ReceiveBuffers[RXBufferTail].InUse){\n\t\tmemcpy (buffer, ReceiveBuffers[RXBufferTail].Buffer,\n\t\t\t\t\tMIN(ReceiveBuffers[RXBufferTail].DataLength, buffer_len));\n\t\tReceiveBuffers[RXBufferTail].InUse = false;\n\n\t\tbytes_copied = MIN(ReceiveBuffers[RXBufferTail++].DataLength, buffer_len);\n\n\t\tRXBufferTail &= WS_NUM_RX_BUFFERS-1;\n\t}\n\n\treturn (bytes_copied);\n}\n\n\n\n/***********************************************************************************************\n * TMC::Write -- Send data via the Winsock UDP socket                                          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to buffer containing data to send                                             *\n *           length of data to send                                                            *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 3:00PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid TcpipManagerClass::Write(void *buffer, int buffer_len)\n{\n\tchar \t*source_buf = (char*) buffer;\n\n\t/*\n\t** Copy the data to one of the classes internal buffers\n\t*/\n\tif (!TransmitBuffers[TXBufferHead].InUse){\n\t\tmemcpy (TransmitBuffers[TXBufferHead].Buffer,\n\t\t\t\t\tbuffer,\n\t\t\t\t\tMIN (buffer_len, WS_INTERNET_BUFFER_LEN));\n\t\tTransmitBuffers[TXBufferHead].InUse = true;\n\t\tTransmitBuffers[TXBufferHead++].DataLength = MIN(buffer_len, WS_INTERNET_BUFFER_LEN);\n\t\tTXBufferHead &= WS_NUM_TX_BUFFERS-1;\n\t}\n\n\t/*\n\t** Send a message to ourselves to start off the event\n\t*/\n\tif (UseUDP){\n\t\tSendMessage(MainWindow, WM_UDPASYNCEVENT, 0, (LONG)FD_WRITE);\n\t}else{\n\t\tSendMessage(MainWindow, WM_ASYNCEVENT, 0, (LONG)FD_WRITE);\n\t}\n\t/*\n\t** Make sure the message loop gets called because all the Winsock notifications\n\t** are done via messages.\n\t*/\n\tKeyboard->Check();\n}\n\n\n\n\n\n\n/***********************************************************************************************\n * TMC::Add_Client -- a client has requested to connect. Make the connection                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   TRUE if client was successfully connected                                         *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 3:02PM ST : Created                                                              *\n *=============================================================================================*/\n\nBOOL TcpipManagerClass::Add_Client(void)\n{\n\tstruct \tsockaddr_in addr;\n\tint \t\taddrsize;\n\tbool \t\tdelay = TRUE;\n\n\t/*\n\t** Accept the connection. If there is an error then dont do anything else\n\t*/\n\taddrsize = sizeof(addr);\n\tConnectSocket = accept (ListenSocket, (LPSOCKADDR)&addr, &addrsize);\n\tif (ConnectSocket == INVALID_SOCKET) {\n\t\t//Show_Error(\"accept\", WSAGetLastError());\n\t\treturn(FALSE);\n\t}\n\n\t/*\n\t** Set options for this socket\n\t*/\n\tsetsockopt (ConnectSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&delay, 4);\n\tsetsockopt (ConnectSocket, SOL_SOCKET, SO_RCVBUF, (char*)&SocketReceiveBuffer, 4);\n\tsetsockopt (ConnectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&SocketSendBuffer, 4);\n\n\t/*\n\t** Save the clients address\n\t*/\n\tmemcpy(&ClientIPAddress, &addr.sin_addr.s_addr,4);\n\tmemcpy(&UDPIPAddress, &addr.sin_addr.s_addr,4);\n\n\t/*\n\t** Initiate an asynchronous host lookup by address. Our window will receive notification\n\t** when this is complete or when it times out.\n\t*/\n\tAsync = WSAAsyncGetHostByAddr (MainWindow, WM_HOSTBYADDRESS,\n\t\t(char const *)&addr.sin_addr, 4, PF_INET, &HostBuff[0],\n\t\tMAXGETHOSTSTRUCT);\n\n\t/*\n\t** Enable asynchronous events on this socket\n\t*/\n\tif (WSAAsyncSelect (ConnectSocket, MainWindow, WM_ASYNCEVENT,\n\t\tFD_READ | FD_WRITE | FD_CLOSE) == SOCKET_ERROR){\n\t\tWSACancelAsyncRequest(Async);\n\t\tClose_Socket (ConnectSocket);\n\t\treturn(FALSE);\n\t}\n\n\t/*\n\t** Create our UDP socket\n\t*/\n\tUDPSocket = socket(AF_INET, SOCK_DGRAM, 0);\n\tif (UDPSocket == INVALID_SOCKET) {\n\t\treturn (FALSE);\n\t}\n\n\t/*\n\t** Bind our UDP socket to our UDP port number\n\t*/\n\taddr.sin_family = AF_INET;\n\taddr.sin_port = htons(PlanetWestwoodPortNumber);\n\taddr.sin_addr.s_addr = htonl(INADDR_ANY);\n\n\tif (bind(UDPSocket, (LPSOCKADDR)&addr, sizeof(addr)) ==\n\t\tSOCKET_ERROR) {\n\t\tClose_Socket(UDPSocket);\n\t\tConnectStatus = NOT_CONNECTING;\n\t\treturn(FALSE);\n\t}\n\n\t/*\n\t** Set options for the UDP socket\n\t*/\n\tsetsockopt (UDPSocket, SOL_SOCKET, SO_RCVBUF, (char*)&SocketReceiveBuffer, 4);\n\tsetsockopt (UDPSocket, SOL_SOCKET, SO_SNDBUF, (char*)&SocketSendBuffer, 4);\n\n\t/*\n\t** Enable asynchronous events on this socket\n\t*/\n\tif (WSAAsyncSelect (UDPSocket, MainWindow, WM_UDPASYNCEVENT,\n\t\tFD_READ | FD_WRITE) == SOCKET_ERROR){\n\t\tWSACancelAsyncRequest(Async);\n\t\tClose_Socket (UDPSocket);\n\t\tClose_Socket (ConnectSocket);\n\t\treturn(FALSE);\n\t}\n\n\treturn (TRUE);\n\n}\n\n\n\n\n/***********************************************************************************************\n * TMC::Message_Handler -- Message handler function for Winsock related messages               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Windows message handler stuff                                                     *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 3:05PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid TcpipManagerClass::Message_Handler(HWND, UINT message, UINT , LONG lParam)\n{\n\tstruct \thostent *hentry;\n\tstruct \tsockaddr_in addr;\n\tint\t \tevent;\n\tint\t \trc;\n\tint\t\taddr_len;\n\n\tswitch (message){\n\n\t\t/*\n\t\t** Handle the GetHostByAddress result\n\t\t*/\n\t\tcase WM_HOSTBYADDRESS:\n\n\t\t\tif (IsServer){\n\t\t\t\t/*\n\t\t\t\t** We are the server\n\t\t\t\t*/\n\t\t\t\tConnectStatus = CONNECTING;\n\t\t\t\tif (WSAGETASYNCERROR(lParam)==0) {\n\t\t\t\t\thentry = (struct hostent *)&HostBuff[0];\n\t\t\t\t\tstrcpy (&ClientName[0], hentry->h_name);\n\t\t\t\t}\n\t\t\t\tAsync = 0;\n\t\t\t\treturn;\n\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t** We are the client\n\t\t\t\t*/\n\t\t\t\tConnectStatus = CONTACTING_SERVER;\n\t\t\t\tif (WSAGETASYNCERROR(lParam)==0) {\n\t\t\t\t\thentry = (struct hostent *)&HostBuff[0];\n\t\t\t\t\tstrcpy (Server.Name, hentry->h_name);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tServer.Name[0] = 0;\n\t\t\t\t}\n\t\t\t\tAsync = 0;\n\t\t\t\treturn;\n\t\t\t}\n\n\n\t\t/*\n\t\t** Retrieve host by name: Start connecting now that we have the\n\t\t** address.\n\t\t*/\n\t\tcase WM_HOSTBYNAME:\n\t\t\tif (WSAGETASYNCERROR(lParam)==0) {\n\t\t\t\thentry = (struct hostent *)&HostBuff[0];\n\t\t\t\tmemcpy (&(Server.Addr.s_addr), hentry->h_addr, 4);\n\t\t\t\tmemcpy(&UDPIPAddress, hentry->h_addr, 4);\n\t\t\t\tstrcpy (Server.DotAddr, inet_ntoa(Server.Addr));\n\t\t\t\tConnectStatus = CONNECTED_OK;\n\t\t\t\tConnected = TRUE;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tServer.Name[0] = 0;\n\t\t\t\tstrcpy (Server.DotAddr, \"????\");\n\t\t\t\tConnectStatus = SERVER_ADDRESS_LOOKUP_FAILED;\n\t\t\t}\n\t\t\tAsync = 0;\n\t\t\treturn;\n\n\n\t\t/*\n\t\t** Connection is ready - accept the client\n\t\t*/\n\t\tcase WM_ACCEPT:\n\t\t\trc = WSAGETSELECTERROR(lParam);\n\t\t\tif (rc != 0) {\n\t\t\t\tConnectStatus = UNABLE_TO_ACCEPT_CLIENT;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (Add_Client()) {\n\t\t\t\tConnectStatus = CONNECTED_OK;\n\t\t\t\tConnected = TRUE;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tConnectStatus = UNABLE_TO_ACCEPT_CLIENT;\n\t\t\t}\n\t\t\treturn;\n\n\n\n\t\t/*\n\t\t** Handle UDP packet events\n\t\t*/\n\t\tcase WM_UDPASYNCEVENT:\n\t\t\tevent = WSAGETSELECTEVENT(lParam);\n\t\t\tswitch (event) {\n\n\t\t\t\tcase FD_READ:\n\t\t\t\t\trc = WSAGETSELECTERROR(lParam);\n\t\t\t\t\tif (rc != 0) {\n\t\t\t\t\t\tClear_Socket_Error(UDPSocket);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\taddr_len = sizeof(addr);\n\t\t\t\t\trc = recvfrom(UDPSocket, ReceiveBuffer, WS_RECEIVE_BUFFER_LEN, 0,\n\t\t\t\t\t(LPSOCKADDR)&addr, &addr_len);\n\t\t\t\t\tif (rc == SOCKET_ERROR) {\n\t\t\t\t\t\tClear_Socket_Error(UDPSocket);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tmemcpy(&UDPIPAddress, &addr.sin_addr.s_addr, 4);\n\t\t\t\t\tCopy_To_In_Buffer(rc);\n\t\t\t\t\treturn;\n\n\n\t\t\t\tcase FD_WRITE:\n\t\t\t\t\tif (UseUDP){\n\t\t\t\t\t\trc = WSAGETSELECTERROR(lParam);\n\t\t\t\t\t\tif (rc != 0) {\n\t\t\t\t\t\t\tClear_Socket_Error(UDPSocket);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\taddr.sin_family = AF_INET;\n\t\t\t\t\t\taddr.sin_port = htons(PlanetWestwoodPortNumber);\n\t\t\t\t\t\tmemcpy (&addr.sin_addr.s_addr, &UDPIPAddress, 4);\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**  Send as many bytes as there are in the buffer; if there's\n\t\t\t\t\t\t**  an error, just bail out.  If we get a WOULDBLOCK error,\n\t\t\t\t\t\t**  WinSock will send us another message when the socket is\n\t\t\t\t\t\t**  available for another write.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\twhile (TransmitBuffers[TXBufferTail].InUse){\n\t\t\t\t\t\t\trc = sendto(UDPSocket,\n\t\t\t\t\t\t\t\t\t\t\tTransmitBuffers[TXBufferTail].Buffer,\n\t\t\t\t\t\t\t\t\t\t\tTransmitBuffers[TXBufferTail].DataLength,\n\t\t\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t\t\t(LPSOCKADDR)&addr,\n\t\t\t\t\t\t\t\t\t\t\tsizeof (addr));\n\n\t\t\t\t\t\t\tif (rc == SOCKET_ERROR){\n\t\t\t\t\t\t\t\tif (WSAGetLastError() != WSAEWOULDBLOCK) {\n\t\t\t\t\t\t\t\t\tClear_Socket_Error(UDPSocket);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tTransmitBuffers[TXBufferTail++].InUse = false;\n\t\t\t\t\t\t\tTXBufferTail &= WS_NUM_TX_BUFFERS-1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t}\n\n\n\n\t\t/*\n\t\t** Handle the asynchronous event callbacks\n\t\t*/\n\t\tcase WM_ASYNCEVENT:\n\t\t\tevent = WSAGETSELECTEVENT(lParam);\n\t\t\tswitch (event) {\n\t\t\t\t/*\n\t\t\t\t** FD_CLOSE: the client has gone away. Remove the client from our system.\n\t\t\t\t*/\n\t\t\t\tcase FD_CLOSE:\n\t\t\t\t\trc = WSAGETSELECTERROR(lParam);\n\t\t\t\t\tif (rc != 0 && rc != WSAECONNRESET) {\n\t\t\t\t\t\tConnectStatus = CONNECTION_LOST;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (Async != 0) {\n\t\t\t\t\t\tWSACancelAsyncRequest(Async);\n\t\t\t\t\t}\n\t\t\t\t\tWSAAsyncSelect (ConnectSocket, MainWindow, WM_ASYNCEVENT, 0);\n\t\t\t\t\tClose_Socket (ConnectSocket);\n\t\t\t\t\tConnectSocket = INVALID_SOCKET;\n\t\t\t\t\t//Connected = FALSE;\n\t\t\t\t\tConnectStatus = CONNECTION_LOST;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t** FD_CONNECT: A connection was made, or an error occurred.\n\t\t\t\t*/\n\t\t\t\tcase FD_CONNECT:\n\t\t\t\t\trc = WSAGETSELECTERROR(lParam);\n\t\t\t\t\tif (rc != 0) {\n\t\t\t\t\t\tConnectStatus = UNABLE_TO_CONNECT;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tConnectStatus = CONNECTED_OK;\n\t\t\t\t\tConnected = TRUE;\n\t\t\t\t\treturn;\n\n\t\t\t}\n\t}\n}\n\n\n\n/***********************************************************************************************\n * TMC::Copy_To_In_Buffer -- copy data from our winsock buffer to our internal buffer          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    bytes to copy                                                                     *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 3:17PM ST : Created                                                              *\n *=============================================================================================*/\nvoid TcpipManagerClass::Copy_To_In_Buffer(int bytes)\n{\n\tif (!ReceiveBuffers[RXBufferHead].InUse){\n\t\tmemcpy (ReceiveBuffers[RXBufferHead].Buffer, ReceiveBuffer, MIN(bytes, WS_INTERNET_BUFFER_LEN));\n\t\tReceiveBuffers[RXBufferHead].InUse = true;\n\t\tReceiveBuffers[RXBufferHead++].DataLength = MIN(bytes, WS_INTERNET_BUFFER_LEN);\n\t\tRXBufferHead &= WS_NUM_RX_BUFFERS-1;\n\t}\n}\n\n\n\n/***********************************************************************************************\n * TMC::Set_Host_Address -- Set the address of the host game we want to connect to             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to address string                                                             *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 3:19PM ST : Created                                                              *\n *=============================================================================================*/\nvoid TcpipManagerClass::Set_Host_Address(char *address)\n{\n\tstrcpy(HostAddress, address);\n}\n\n\n\n/***********************************************************************************************\n * TMC::Start_Client -- Start trying to connect to a game host                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 3:19PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid TcpipManagerClass::Start_Client(void)\n{\n\tstruct \tsockaddr_in addr;\n\tbool\t\tdelay = true;\n\tint \t\ti;\n\n\taddr.sin_family = AF_INET;\n\taddr.sin_port = 0;\n\taddr.sin_addr.s_addr = htonl(INADDR_ANY);\n\n\t/*\n\t** Set up the incoming and outgoing data buffers head and tail pointers\n\t*/\n\tTXBufferHead = 0;\n\tTXBufferTail = 0;\n\tRXBufferHead = 0;\n\tRXBufferTail = 0;\n\n\tfor (i=0 ; i<WS_NUM_TX_BUFFERS ; i++){\n\t\tTransmitBuffers[i].InUse = false;\n\t}\n\n\tfor (i=0 ; i<WS_NUM_RX_BUFFERS ; i++){\n\t\tReceiveBuffers[i].InUse = false;\n\t}\n\n\tConnected = FALSE;\n\t/*\n\t** Flag that we are the client side not the server\n\t*/\n\tIsServer = FALSE;\n\tUseUDP = TRUE;\n\n\t/*\n\t** Create our UDP socket\n\t*/\n\tUDPSocket = socket(AF_INET, SOCK_DGRAM, 0);\n\tif (UDPSocket == INVALID_SOCKET) {\n\t\tClose_Socket(ConnectSocket);\n\t\tConnectStatus = NOT_CONNECTING;\n\t\treturn;\n\t}\n\t/*\n\t** Bind our UDP socket to our UDP port number\n\t*/\n\taddr.sin_family = AF_INET;\n\taddr.sin_port = htons(PlanetWestwoodPortNumber);\n\taddr.sin_addr.s_addr = htonl(INADDR_ANY);\n\n\tif (bind(UDPSocket, (LPSOCKADDR)&addr, sizeof(addr)) ==\n\t\tSOCKET_ERROR) {\n\t\tClose_Socket(UDPSocket);\n\t\tClose_Socket(ConnectSocket);\n\t\tConnectStatus = NOT_CONNECTING;\n\t\treturn;\n\t}\n\n\t/*\n\t** Set options for the UDP socket\n\t*/\n\tsetsockopt (UDPSocket, SOL_SOCKET, SO_RCVBUF, (char*)&SocketReceiveBuffer, 4);\n\tsetsockopt (UDPSocket, SOL_SOCKET, SO_SNDBUF, (char*)&SocketSendBuffer, 4);\n\n\t/*\n\t** Enable asynchronous events on the UDP socket\n\t*/\n\tif (WSAAsyncSelect (UDPSocket, MainWindow, WM_UDPASYNCEVENT,\n\t\tFD_READ | FD_WRITE) == SOCKET_ERROR){\n\t\tWSACancelAsyncRequest(Async);\n\t\tClose_Socket (UDPSocket);\n\t\tClose_Socket (ConnectSocket);\n\t\tConnectStatus = NOT_CONNECTING;\n\t\treturn;\n\t}\n\n\t/*\n\t** If the name is not a dot-decimal ip address then do a nameserver lookup\n\t*/\n\n\n\tServer.Addr.s_addr = inet_addr(PlanetWestwoodIPAddress);\n\tmemcpy(&UDPIPAddress, &Server.Addr.s_addr, 4);\n\tif (Server.Addr.s_addr == INADDR_NONE){\n\t\tstrcpy (Server.Name, PlanetWestwoodIPAddress);\n\t\tAsync = WSAAsyncGetHostByName(MainWindow, WM_HOSTBYNAME,\n\t\t\tServer.Name, HostBuff, MAXGETHOSTSTRUCT);\n\t\tConnectStatus = RESOLVING_HOST_ADDRESS;\n\t}else{\n\t\tConnectStatus = CONNECTED_OK;\n\t\tConnected = TRUE;\n\t}\n\n}\n\n\n\n/***********************************************************************************************\n * TMC::Close_Socket -- Close an opened Winsock socket.                                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Socket to close                                                                   *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 3:24PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid TcpipManagerClass::Close_Socket(SOCKET s)\n{\n\tLINGER ling;\n\n\tling.l_onoff = 0;\t\t// linger off\n\tling.l_linger = 0;\t// timeout in seconds (ie close now)\n\tsetsockopt(s, SOL_SOCKET, SO_LINGER, (LPSTR)&ling, sizeof(ling));\n\tclosesocket (s);\n}\n\n\nvoid TcpipManagerClass::Set_Protocol_UDP(BOOL state)\n{\n\tUseUDP = state;\n}\n\n\n\nvoid TcpipManagerClass::Clear_Socket_Error(SOCKET socket)\n{\n\tunsigned long error_code;\n\tint length = 4;\n\n\tgetsockopt (socket, SOL_SOCKET, SO_ERROR, (char*)&error_code, &length);\n\terror_code = 0;\n\tsetsockopt (socket, SOL_SOCKET, SO_ERROR, (char*)&error_code, length);\n}\n\n\n\n\n#endif\t//WIN32\n"
  },
  {
    "path": "CODE/TCPIP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TCPIP.H 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : TCPIP.CPP                                *\n *                                                                         *\n *                   Programmer : Steve Tall                               *\n *                                                                         *\n *                   Start Date : March 11th, 1996                         *\n *                                                                         *\n *                  Last Update : March 11th, 1996 [ST]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifdef WIN32\n\n#ifndef WOLAPI_INTEGRATION\nextern bool Server;\n#endif\n\n#define FORCE_WINSOCK\t\t\t\t1\n\n#define WINSOCK_MINOR_VER\t\t1\n#define WINSOCK_MAJOR_VER\t\t1\n#define PORTNUM\t\t\t\t\t\t0x1000\n#define UDP_PORT\t\t\t\t\t0x1001\n#define WS_INTERNET_BUFFER_LEN  1024\n#define WS_NUM_TX_BUFFERS\t\t16\t\t//Must be a power of 2\n#define WS_NUM_RX_BUFFERS\t\t16\t\t//MUst be a power of 2\n#define WS_RECEIVE_BUFFER_LEN\t1024\n//#define WS_IN_BUFFER_LEN\t\t\t8192\n//#define WS_OUT_BUFFER_LEN\t\t8192\n\n#define PLANET_WESTWOOD_HANDLE_MAX 20\n#define PLANET_WESTWOOD_PASSWORD_MAX 20\n#define IP_ADDRESS_MAX 40\n#define PORT_NUMBER_MAX 6\n\n//...........................................................................\n// Custom messages: WM_USER + 1 to WM_USER + 100\n// These will be sent to the dialog procedure, for display only.\n//...........................................................................\n#define\tWM_UPDATE_STATUS\t\t(WM_USER + 1)\t// update status text\n#define\tWM_UPDATE_CLIENTS\t\t(WM_USER + 2)\t// update client list box\n#define\tWM_UPDATE_MESSAGE\t\t(WM_USER + 3)\t// update received message list\n\n//...........................................................................\n// Messages for Async processing.\n//...........................................................................\n#define\tWM_ACCEPT\t\t\t\t(WM_USER + 101)\t// client wants to connect\n#define\tWM_HOSTBYADDRESS\t\t(WM_USER + 102)\t// async get host by address\n#define\tWM_HOSTBYNAME\t\t\t(WM_USER + 103)\t// async get host by name\n#define\tWM_ASYNCEVENT\t\t\t(WM_USER + 104)\t// other Async event\n#define\tWM_UDPASYNCEVENT\t\t(WM_USER + 105)\t// UDP socket Async event\n\n\nclass TcpipManagerClass {\n\n\tpublic:\n\n\t\tTcpipManagerClass(void);\n\t\t~TcpipManagerClass(void);\n\n\t\tBOOL Init(void);\n\t\tvoid Start_Server(void);\n\t\tvoid Start_Client(void);\n\t\tvoid Close_Socket(SOCKET s);\n\t \tvoid Message_Handler(HWND window, UINT message, UINT wParam, LONG lParam);\n\t\tvoid Copy_To_In_Buffer(int bytes);\n\t\tint  Read(void *buffer, int buffer_len);\n\t\tvoid Write(void *buffer, int buffer_len);\n\t\tBOOL Add_Client(void);\n\t\tvoid Close(void);\n\t\tvoid Set_Host_Address(char *address);\n\t\tvoid Set_Protocol_UDP(BOOL state);\n\t\tvoid Clear_Socket_Error(SOCKET socket);\n\n\t\tinline BOOL Get_Connected(void) {return (Connected);}\n\n\t\ttypedef enum ConnectStatusEnum {\n\t\t\tCONNECTED_OK = 0,\n\t\t\tNOT_CONNECTING,\n\t\t\tCONNECTING,\n\t\t\tUNABLE_TO_CONNECT_TO_SERVER,\n\t\t\tCONTACTING_SERVER,\n\t\t\tSERVER_ADDRESS_LOOKUP_FAILED,\n\t\t\tRESOLVING_HOST_ADDRESS,\n\t\t\tUNABLE_TO_ACCEPT_CLIENT,\n\t\t\tUNABLE_TO_CONNECT,\n\t\t\tCONNECTION_LOST\n\t\t} ConnectStatusEnum;\n\n\t\tinline ConnectStatusEnum Get_Connection_Status(void) {return (ConnectStatus);}\n\n\tprivate:\n\n\t\t//...........................................................................\n\t\t// This structure defines all the info we need about a host\n\t\t//...........................................................................\n\t\ttypedef struct {\n\t\t\tstruct in_addr Addr;\t\t\t\t\t// address\n\t\t\tchar DotAddr[16];\t\t\t\t\t\t// decimal-dot address string\n\t\t\tchar Name[255];\t\t\t\t\t\t// character-string name\n\t\t} HostType;\n\n\t\ttypedef struct {\n\t\t\tchar\tBuffer[WS_INTERNET_BUFFER_LEN];\n\t\t\tint\tDataLength;\n\t\t\tbool\tInUse:1;\n\t\t} InternetBufferType;\n\n\n\t\tBOOL \t\t\t\t\tWinsockInitialised;\n\t\tWSADATA\t\t\t\tWinsockInfo;\n\t\tSOCKET\t\t\t\tListenSocket;\n\t\tSOCKET\t\t\t\tConnectSocket;\n\t\tSOCKET\t\t\t\tUDPSocket;\n\t\tIN_ADDR\t\t\t\tClientIPAddress;\n\t\tHANDLE\t\t\t\tAsync;\n\t\tchar\t\t\t\t\tHostBuff[MAXGETHOSTSTRUCT];\n\t\tchar\t\t\t\t\tClientName[128];\n\t\tchar\t\t\t\t\tReceiveBuffer[WS_RECEIVE_BUFFER_LEN];\n\t\t//char\t\t\t\t\tInBuffer[WS_IN_BUFFER_LEN];\n\t\t//int\t\t\t\t\tInBufferHead;\n\t\t//int\t\t\t\t\tInBufferTail;\n\t\t//char\t\t\t\t\tOutBuffer[WS_OUT_BUFFER_LEN];\n\t\t//int\t\t\t\t\tOutBufferHead;\n\t\t//int\t\t\t\t\tOutBufferTail;\n\t\tBOOL\t\t\t\t\tIsServer;\n\t\tBOOL\t\t\t\t\tConnected;\n\t\tHostType\t\t\t\tServer;\n\t\tchar\t\t\t\t\tHostAddress[IP_ADDRESS_MAX];\n\t\tConnectStatusEnum ConnectStatus;\n\t\tBOOL\t\t\t\t\tUseUDP;\n\t\tIN_ADDR\t\t\t\tUDPIPAddress;\n\t\tint\t\t\t\t\tSocketReceiveBuffer;\n\t\tint\t\t\t\t\tSocketSendBuffer;\n\t\tInternetBufferType ReceiveBuffers[WS_NUM_TX_BUFFERS];\n\t\tInternetBufferType TransmitBuffers[WS_NUM_RX_BUFFERS];\n\t\tint\t\t\t\t\tTXBufferHead;\n\t\tint\t\t\t\t\tTXBufferTail;\n\t\tint\t\t\t\t\tRXBufferHead;\n\t\tint\t\t\t\t\tRXBufferTail;\n\n};\n\n\nextern TcpipManagerClass Winsock;\n\nextern char PlanetWestwoodIPAddress[IP_ADDRESS_MAX];\nextern long PlanetWestwoodPortNumber;\nextern bool PlanetWestwoodIsHost;\nextern int Read_Game_Options(char *);\n\n\n#define TXT_WINSOCK_CONNECTING\t\t\t\t\t\t\t4567+13\n#define TXT_WINSOCK_NOT_CONNECTING\t\t\t\t\t4567+14\n#define TXT_WINSOCK_UNABLE_TO_CONNECT_TO_SERVER\t4567+15\n#define TXT_WINSOCK_CONTACTING_SERVER\t\t\t\t4567+16\n#define TXT_WINSOCK_SERVER_ADDRESS_LOOKUP_FAILED\t4567+17\n#define TXT_WINSOCK_UNABLE_TO_ACCEPT_CLIENT\t\t4567+18\n#define TXT_WINSOCK_UNABLE_TO_CONNECT\t\t\t\t4567+19\n#define TXT_WINSOCK_CONNECTION_LOST\t\t\t\t\t4567+20\n#define TXT_WINSOCK_RESOLVING_HOST_ADDRESS\t\t\t4567+21\n\n\n\n#endif\t//WIN32\n"
  },
  {
    "path": "CODE/TDATA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TDATA.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TDATA.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 2, 1994                                                  *\n *                                                                                             *\n *                  Last Update : July 19, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   TerrainTypeClass::As_Reference -- Fetches a reference to the terrain type object specified*\n *   TerrainTypeClass::Create_And_Place -- Creates and places terrain object on map.           *\n *   TerrainTypeClass::Create_On_Of -- Creates a terrain object from type.                     *\n *   TerrainTypeClass::Display -- Display a generic terrain object.                            *\n *   TerrainTypeClass::From_Name -- Convert name to terrain type.                              *\n *   TerrainTypeClass::Init -- Loads terrain object shape files.                               *\n *   TerrainTypeClass::Init_Heap -- Initialize the terrain object heap.                        *\n *   TerrainTypeClass::Occupy_List -- Returns with the occupy list for the terrain object type.*\n *   TerrainTypeClass::One_Time -- Performs any special one time processing for terrain types. *\n *   TerrainTypeClass::Overlap_List -- Fetches the overlap list for the terrain type.          *\n *   TerrainTypeClass::Prep_For_Add -- Prepares to add terrain object.                         *\n *   TerrainTypeClass::TerrainTypeClass -- The general constructor for the terrain type objects*\n *   TerrainTypeClass::operator delete -- Returns a terrain type object back to the mem pool.  *\n *   TerrainTypeClass::operator new -- Allocates a terrain type object from special pool.      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"terrain.h\"\n#include\t\"type.h\"\n\n\nstatic short const _List000011101000[] = {MAP_CELL_W, MAP_CELL_W+1, MAP_CELL_W+2, MAP_CELL_W*2, REFRESH_EOL};\nstatic short const _List000110[] = {MAP_CELL_W, MAP_CELL_W+1, REFRESH_EOL};\nstatic short const _List001011100110[] = {2, MAP_CELL_W, MAP_CELL_W+1, MAP_CELL_W+2, MAP_CELL_W*2+1, MAP_CELL_W*2+2, REFRESH_EOL};\nstatic short const _List0010[] = {MAP_CELL_W, REFRESH_EOL};\nstatic short const _List0011[] = {MAP_CELL_W, MAP_CELL_W+1, REFRESH_EOL};\nstatic short const _List001[] = {2, REFRESH_EOL};\nstatic short const _List010110[] = {1, MAP_CELL_W, MAP_CELL_W+1, REFRESH_EOL};\nstatic short const _List01[] = {1, REFRESH_EOL};\nstatic short const _List11[] = {0, 1, REFRESH_EOL};\nstatic short const _List1001[] = {0, MAP_CELL_W+1, REFRESH_EOL};\nstatic short const _List1010[] = {0, MAP_CELL_W, REFRESH_EOL};\nstatic short const _List101001[] = {0, 2, MAP_CELL_W+2, REFRESH_EOL};\nstatic short const _List10[] = {0, REFRESH_EOL};\nstatic short const _List110000011001[] = {0, 1, MAP_CELL_W+3, MAP_CELL_W*2, MAP_CELL_W*2+3, REFRESH_EOL};\nstatic short const _List110001[] = {0, 1, MAP_CELL_W+2, REFRESH_EOL};\nstatic short const _List1100[] = {0, 1, REFRESH_EOL};\nstatic short const _List110110[] = {0, 1, MAP_CELL_W, MAP_CELL_W+1, REFRESH_EOL};\nstatic short const _List1101[] = {0, 1, MAP_CELL_W+1, REFRESH_EOL};\nstatic short const _List1111[] = {0, 1, MAP_CELL_W, MAP_CELL_W+1, REFRESH_EOL};\nstatic short const _List111000010110[] = {0, 1, 2, MAP_CELL_W+3, MAP_CELL_W*2+1, MAP_CELL_W*2+2, REFRESH_EOL};\n\n\nstatic TerrainTypeClass const Mine(\n\tTERRAIN_MINE,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(12,24),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"MINE\",\n\tTXT_ORE_MINE,\n\t(short const *)_List10,\n\tNULL\n);\nstatic TerrainTypeClass const Boxes01(\n\tTERRAIN_BOXES01,\n\tTHEATERF_INTERIOR,\n\tXYP_COORD(12,24),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"BOXES01\",\n\tTXT_CRATES,\n\t(short const *)_List10,\n\tNULL\n);\nstatic TerrainTypeClass const Boxes02(\n\tTERRAIN_BOXES02,\n\tTHEATERF_INTERIOR,\n\tXYP_COORD(12,24),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"BOXES02\",\n\tTXT_CRATES,\n\t(short const *)_List10,\n\tNULL\n);\nstatic TerrainTypeClass const Boxes03(\n\tTERRAIN_BOXES03,\n\tTHEATERF_INTERIOR,\n\tXYP_COORD(12,24),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"BOXES03\",\n\tTXT_CRATES,\n\t(short const *)_List10,\n\tNULL\n);\nstatic TerrainTypeClass const Boxes04(\n\tTERRAIN_BOXES04,\n\tTHEATERF_INTERIOR,\n\tXYP_COORD(12,24),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"BOXES04\",\n\tTXT_CRATES,\n\t(short const *)_List10,\n\tNULL\n);\nstatic TerrainTypeClass const Boxes05(\n\tTERRAIN_BOXES05,\n\tTHEATERF_INTERIOR,\n\tXYP_COORD(12,24),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"BOXES05\",\n\tTXT_CRATES,\n\t(short const *)_List10,\n\tNULL\n);\nstatic TerrainTypeClass const Boxes06(\n\tTERRAIN_BOXES06,\n\tTHEATERF_INTERIOR,\n\tXYP_COORD(12,24),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"BOXES06\",\n\tTXT_CRATES,\n\t(short const *)_List10,\n\tNULL\n);\nstatic TerrainTypeClass const Boxes07(\n\tTERRAIN_BOXES07,\n\tTHEATERF_INTERIOR,\n\tXYP_COORD(12,24),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"BOXES07\",\n\tTXT_CRATES,\n\t(short const *)_List10,\n\tNULL\n);\nstatic TerrainTypeClass const Boxes08(\n\tTERRAIN_BOXES08,\n\tTHEATERF_INTERIOR,\n\tXYP_COORD(12,24),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"BOXES08\",\n\tTXT_CRATES,\n\t(short const *)_List10,\n\tNULL\n);\nstatic TerrainTypeClass const Boxes09(\n\tTERRAIN_BOXES09,\n\tTHEATERF_INTERIOR,\n\tXYP_COORD(12,24),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"BOXES09\",\n\tTXT_CRATES,\n\t(short const *)_List10,\n\tNULL\n);\n\nstatic TerrainTypeClass const Ice01(\n\tTERRAIN_ICE01,\n\tTHEATERF_SNOW,\n\tXYP_COORD(24,24),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\ttrue,\t\t\t\t\t// Is based on the water?\n\t\"ICE01\",\n\tTXT_ICE,\n\t(short const *)_List1111,\n\tNULL\n);\nstatic TerrainTypeClass const Ice02(\n\tTERRAIN_ICE02,\n\tTHEATERF_SNOW,\n\tXYP_COORD(12,24),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\ttrue,\t\t\t\t\t// Is based on the water?\n\t\"ICE02\",\n\tTXT_ICE,\n\t(short const *)_List1010,\n\tNULL\n);\nstatic TerrainTypeClass const Ice03(\n\tTERRAIN_ICE03,\n\tTHEATERF_SNOW,\n\tXYP_COORD(24,12),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\ttrue,\t\t\t\t\t// Is based on the water?\n\t\"ICE03\",\n\tTXT_ICE,\n\t(short const *)_List11,\n\tNULL\n);\nstatic TerrainTypeClass const Ice04(\n\tTERRAIN_ICE04,\n\tTHEATERF_SNOW,\n\tXYP_COORD(12,12),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\ttrue,\t\t\t\t\t// Is based on the water?\n\t\"ICE04\",\n\tTXT_ICE,\n\t(short const *)_List10,\n\tNULL\n);\nstatic TerrainTypeClass const Ice05(\n\tTERRAIN_ICE05,\n\tTHEATERF_SNOW,\n\tXYP_COORD(12,12),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\ttrue,\t\t\t\t\t// Is based on the water?\n\t\"ICE05\",\n\tTXT_ICE,\n\t(short const *)_List10,\n\tNULL\n);\n\nstatic TerrainTypeClass const Tree1Class(\n\tTERRAIN_TREE1,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(11,41),\t\t// Center base coordinate offset.\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"T01\",\n\tTXT_TREE,\n\t(short const *)_List0010,\n\t(short const *)_List1001\n);\n\nstatic TerrainTypeClass const Tree2Class(\n\tTERRAIN_TREE2,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(11,44),\t\t// Center base coordinate offset.\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"T02\",\n\tTXT_TREE,\n\t(short const *)_List0010,\n\t(short const *)_List1001\n);\n\nstatic TerrainTypeClass const Tree3Class(\n\tTERRAIN_TREE3,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(12,45),\t\t// Center base coordinate offset.\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"T03\",\n\tTXT_TREE,\n\t(short const *)_List0010,\n\t(short const *)_List1001\n);\n\nstatic TerrainTypeClass const Tree5Class(\n\tTERRAIN_TREE5,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(15,41),\t\t// Center base coordinate offset.\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"T05\",\n\tTXT_TREE,\n\t(short const *)_List0010,\n\t(short const *)_List1001\n);\n\nstatic TerrainTypeClass const Tree6Class(\n\tTERRAIN_TREE6,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(16,37),\t\t// Center base coordinate offset.\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"T06\",\n\tTXT_TREE,\n\t(short const *)_List0010,\n\t(short const *)_List1001\n);\n\nstatic TerrainTypeClass const Tree7Class(\n\tTERRAIN_TREE7,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(15,41),\t\t// Center base coordinate offset.\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"T07\",\n\tTXT_TREE,\n\t(short const *)_List0010,\n\t(short const *)_List1001\n);\n\nstatic TerrainTypeClass const Tree8Class(\n\tTERRAIN_TREE8,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(14,22),\t\t// Center base coordinate offset.\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"T08\",\n\tTXT_TREE,\n\t(short const *)_List10,\n\t(short const *)_List01\n);\n\nstatic TerrainTypeClass const Tree10Class(\n\tTERRAIN_TREE10,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(25,43),\t\t// Center base coordinate offset.\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"T10\",\n\tTXT_TREE,\n\t(short const *)_List0011,\n\t(short const *)_List1100\n);\n\nstatic TerrainTypeClass const Tree11Class(\n\tTERRAIN_TREE11,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(23,44),\t\t// Center base coordinate offset.\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"T11\",\n\tTXT_TREE,\n\t(short const *)_List0011,\n\t(short const *)_List1100\n);\n\nstatic TerrainTypeClass const Tree12Class(\n\tTERRAIN_TREE12,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(14,36),\t\t// Center base coordinate offset.\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"T12\",\n\tTXT_TREE,\n\t(short const *)_List0010,\n\t(short const *)_List1001\n);\n\nstatic TerrainTypeClass const Tree13Class(\n\tTERRAIN_TREE13,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(19,40),\t\t// Center base coordinate offset.\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"T13\",\n\tTXT_TREE,\n\t(short const *)_List0010,\n\t(short const *)_List1101\n);\n\nstatic TerrainTypeClass const Tree14Class(\n\tTERRAIN_TREE14,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(19,40),\t\t// Center base coordinate offset.\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"T14\",\n\tTXT_TREE,\n\t(short const *)_List0011,\n\t(short const *)_List1100\n);\n\nstatic TerrainTypeClass const Tree15Class(\n\tTERRAIN_TREE15,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(19,40),\t\t// Center base coordinate offset.\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"T15\",\n\tTXT_TREE,\n\t(short const *)_List0011,\n\t(short const *)_List1100\n);\n\nstatic TerrainTypeClass const Tree16Class(\n\tTERRAIN_TREE16,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(13,36),\t\t// Center base coordinate offset.\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"T16\",\n\tTXT_TREE,\n\t(short const *)_List0010,\n\t(short const *)_List1001\n);\n\nstatic TerrainTypeClass const Tree17Class(\n\tTERRAIN_TREE17,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(18,44),\t\t// Center base coordinate offset.\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"T17\",\n\tTXT_TREE,\n\t(short const *)_List0010,\n\t(short const *)_List1001\n);\n\nstatic TerrainTypeClass const Clump1Class(\n\tTERRAIN_CLUMP1,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(28,41),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"TC01\",\n\tTXT_TREE,\n\t(short const *)_List000110,\n\t(short const *)_List110001\n);\n\nstatic TerrainTypeClass const Clump2Class(\n\tTERRAIN_CLUMP2,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(38,41),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"TC02\",\n\tTXT_TREE,\n\t(short const *)_List010110,\n\t(short const *)_List101001\n);\n\nstatic TerrainTypeClass const Clump3Class(\n\tTERRAIN_CLUMP3,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(33,35),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"TC03\",\n\tTXT_TREE,\n\t(short const *)_List110110,\n\t(short const *)_List001\n);\n\nstatic TerrainTypeClass const Clump4Class(\n\tTERRAIN_CLUMP4,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(44,49),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"TC04\",\n\tTXT_TREE,\n\t(short const *)_List000011101000,\n\t(short const *)_List111000010110\n);\n\nstatic TerrainTypeClass const Clump5Class(\n\tTERRAIN_CLUMP5,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\tXYP_COORD(49,58),\t\t// Center base coordinate offset.\n\t\ttrue,\t\t\t\t\t// Is it immune to normal combat damage?\n\t\tfalse,\t\t\t\t// Is based on the water?\n\t\"TC05\",\n\tTXT_TREE,\n\t(short const *)_List001011100110,\n\t(short const *)_List110000011001\n);\n\n\n/***********************************************************************************************\n * TerrainTypeClass::TerrainTypeClass -- The general constructor for the terrain type objects. *\n *                                                                                             *\n *    This is the constructor for terrain type objects. It is only used to construct the       *\n *    static (constant) terrain type objects.                                                  *\n *                                                                                             *\n * INPUT:   see below..                                                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTerrainTypeClass::TerrainTypeClass(\n\tTerrainType terrain,\n\tint theater,\n\tCOORDINATE centerbase,\n\tbool is_immune,\n\tbool is_water,\n\tchar const * ininame,\n\tint fullname,\n\tshort const * occupy,\n\tshort const * overlap) :\n\t\tObjectTypeClass(RTTI_TERRAINTYPE,\n\t\t\t\t\t\t\tint(terrain),\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\tis_immune,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\tfullname,\n\t\t\t\t\t\t\tininame),\n\tType(terrain),\n\tCenterBase(centerbase),\n\tTheater(theater),\n\tIsWaterBased(is_water),\n\tOccupy(occupy),\n\tOverlap(overlap)\n{\n\tMaxStrength = 800;\n\tArmor = ARMOR_WOOD;\n}\n\n\n/***********************************************************************************************\n * TerrainTypeClass::operator new -- Allocates a terrain type object from special pool.        *\n *                                                                                             *\n *    This routine will allocated a terrain type class object from the memory pool set up      *\n *    for that purpose.                                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the freshly allocated terrain type object block. If      *\n *          there was insufficient memory, then NULL is returned.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * TerrainTypeClass::operator new(size_t)\n{\n\treturn(TerrainTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * TerrainTypeClass::operator delete -- Returns a terrain type object back to the mem pool.    *\n *                                                                                             *\n *    This routine will return the supplied terrain type object back to the special memory     *\n *    pool for whence it was originally allocated.                                             *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to the terrain type object to return to the memory pool.       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TerrainTypeClass::operator delete(void * pointer)\n{\n\tTerrainTypes.Free((TerrainTypeClass *)pointer);\n}\n\n\n/***********************************************************************************************\n * TerrainTypeClass::Init_Heap -- Initialize the terrain object heap.                          *\n *                                                                                             *\n *    This routine preallocates the terrain type objects in the memory pool. It must be called *\n *    before the terrain type object data can be filled in.                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This must be called only once and before the rules.ini file is processed.       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TerrainTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese terrain type class objects must be allocated in the exact order that they\n\t**\tare specified in the TerrainType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew TerrainTypeClass(Tree1Class);\t\t//\tTERRAIN_TREE1\n\tnew TerrainTypeClass(Tree2Class);\t\t//\tTERRAIN_TREE2\n\tnew TerrainTypeClass(Tree3Class);\t\t//\tTERRAIN_TREE3\n\tnew TerrainTypeClass(Tree5Class);\t\t//\tTERRAIN_TREE5\n\tnew TerrainTypeClass(Tree6Class);\t\t//\tTERRAIN_TREE6\n\tnew TerrainTypeClass(Tree7Class);\t\t//\tTERRAIN_TREE7\n\tnew TerrainTypeClass(Tree8Class);\t\t//\tTERRAIN_TREE8\n\tnew TerrainTypeClass(Tree10Class);\t\t//\tTERRAIN_TREE10\n\tnew TerrainTypeClass(Tree11Class);\t\t//\tTERRAIN_TREE11\n\tnew TerrainTypeClass(Tree12Class);\t\t//\tTERRAIN_TREE12\n\tnew TerrainTypeClass(Tree13Class);\t\t//\tTERRAIN_TREE13\n\tnew TerrainTypeClass(Tree14Class);\t\t//\tTERRAIN_TREE14\n\tnew TerrainTypeClass(Tree15Class);\t\t//\tTERRAIN_TREE15\n\tnew TerrainTypeClass(Tree16Class);\t\t//\tTERRAIN_TREE16\n\tnew TerrainTypeClass(Tree17Class);\t\t//\tTERRAIN_TREE17\n\tnew TerrainTypeClass(Clump1Class);\t\t//\tTERRAIN_CLUMP1\n\tnew TerrainTypeClass(Clump2Class);\t\t//\tTERRAIN_CLUMP2\n\tnew TerrainTypeClass(Clump3Class);\t\t//\tTERRAIN_CLUMP3\n\tnew TerrainTypeClass(Clump4Class);\t\t//\tTERRAIN_CLUMP4\n\tnew TerrainTypeClass(Clump5Class);\t\t//\tTERRAIN_CLUMP5\n\tnew TerrainTypeClass(Ice01);\t\t\t\t//\tTERRAIN_ICE01\n\tnew TerrainTypeClass(Ice02);\t\t\t\t//\tTERRAIN_ICE02\n\tnew TerrainTypeClass(Ice03);\t\t\t\t//\tTERRAIN_ICE03\n\tnew TerrainTypeClass(Ice04);\t\t\t\t//\tTERRAIN_ICE04\n\tnew TerrainTypeClass(Ice05);\t\t\t\t//\tTERRAIN_ICE05\n\tnew TerrainTypeClass(Boxes01);\t\t\t//\tTERRAIN_BOXES01\n\tnew TerrainTypeClass(Boxes02);\t\t\t//\tTERRAIN_BOXES02\n\tnew TerrainTypeClass(Boxes03);\t\t\t//\tTERRAIN_BOXES03\n\tnew TerrainTypeClass(Boxes04);\t\t\t//\tTERRAIN_BOXES04\n\tnew TerrainTypeClass(Boxes05);\t\t\t//\tTERRAIN_BOXES05\n\tnew TerrainTypeClass(Boxes06);\t\t\t//\tTERRAIN_BOXES06\n\tnew TerrainTypeClass(Boxes07);\t\t\t//\tTERRAIN_BOXES07\n\tnew TerrainTypeClass(Boxes08);\t\t\t//\tTERRAIN_BOXES08\n\tnew TerrainTypeClass(Boxes09);\t\t\t//\tTERRAIN_BOXES09\n\tnew TerrainTypeClass(Mine);\t\t\t\t// TERRAIN_MINE\n}\n\n\n/***********************************************************************************************\n * TerrainTypeClass::One_Time -- Performs any special one time processing for terrain types.   *\n *                                                                                             *\n *    This routine will perform any special one time processing needed for the terrain         *\n *    object types. Typically, this would load up artwork for terrain objects that have        *\n *    artwork independant of the theater they appear in.                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TerrainTypeClass::One_Time(void)\n{\n}\n\n/***********************************************************************************************\n * TerrainTypeClass::Init -- Loads terrain object shape files.                                 *\n *                                                                                             *\n *    This routine is used to load up the terrain object shape files.                          *\n *    The shape files loaded depends on theater.                                               *\n *                                                                                             *\n * INPUT:   theater  -- The theater to load the terrain shape data for.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/16/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TerrainTypeClass::Init(TheaterType theater)\n{\n\tif (theater != LastTheater) {\n\n\t\tfor (TerrainType index = TERRAIN_FIRST; index < TERRAIN_COUNT; index++) {\n\t\t\tTerrainTypeClass const & terrain = As_Reference(index);\n\t\t\tchar\tfullname[_MAX_FNAME+_MAX_EXT];\n\n\t\t\t/*\n\t\t\t**\tClear any existing shape pointer. All terrain is theater specific, thus if\n\t\t\t**\tit isn't loaded in this routine, it shouldn't exist at all.\n\t\t\t*/\n\t\t\t((void const *&)terrain.ImageData) = NULL;\n\n\t\t\tif (terrain.Theater & (1 << theater)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tLoad in the appropriate object shape data.\n\t\t\t\t*/\n\t\t\t\t_makepath(fullname, NULL, NULL, terrain.IniName, Theaters[theater].Suffix);\n\t\t\t\t((void const *&)terrain.ImageData) = MFCD::Retrieve(fullname);\n\n\t\t\t\tIsTheaterShape = true;\t//Let Build_Frame know that this is a theater specific shape\n\t\t\t\tif (terrain.RadarIcon != NULL) delete[] (char *)terrain.RadarIcon;\n\t\t\t\t((void const *&)terrain.RadarIcon) = Get_Radar_Icon(terrain.Get_Image_Data(), 0, 1, 3);\n\t\t\t\tIsTheaterShape = false;\n\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TerrainTypeClass::From_Name -- Convert name to terrain type.                                *\n *                                                                                             *\n *    This routine is used to convert a text name into the matching                            *\n *    terrain type number. This is used during scenario initialization.                        *\n *                                                                                             *\n * INPUT:   name  -- The name to convert.                                                      *\n *                                                                                             *\n * OUTPUT:  Returns the TerrainType that matches the name specified. If                        *\n *          no match was found, then TERRAIN_NONE is returned.                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/16/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTerrainType TerrainTypeClass::From_Name(char const * name)\n{\n\tTerrainType\tindex;\n\n\tif (name != NULL) {\n\t\tfor (index = TERRAIN_FIRST; index < TERRAIN_COUNT; index++) {\n\t\t\tif (stricmp(name, As_Reference(index).IniName) == 0) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t}\n\t}\n\treturn(TERRAIN_NONE);\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***********************************************************************************************\n * TerrainTypeClass::Display -- Display a generic terrain object.                              *\n *                                                                                             *\n *    This routine is used to display a generic terrain object. Typical                        *\n *    use is during scenario editing.                                                          *\n *                                                                                             *\n * INPUT:   x,y   -- Pixel coordinates to display object at (centered).                        *\n *                                                                                             *\n *          window-- The window to display the object within.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/16/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TerrainTypeClass::Display(int x, int y, WindowNumberType window, HousesType) const\n{\n\tIsTheaterShape = true;\n\tCC_Draw_Shape(Get_Image_Data(), 0, x, y, window, SHAPE_NORMAL|SHAPE_CENTER|SHAPE_WIN_REL);\n\tIsTheaterShape = false;\n}\n\n\n/***********************************************************************************************\n * TerrainTypeClass::Prep_For_Add -- Prepares to add terrain object.                           *\n *                                                                                             *\n *    Submits all of the valid terrain objects to the scenario editor for possible selection   *\n *    and subsequent placement on the map. All terrain objects, that have a valid shape        *\n *    file available, are added.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TerrainTypeClass::Prep_For_Add(void)\n{\n\tfor (TerrainType index = TERRAIN_FIRST; index < TERRAIN_COUNT; index++) {\n\t\tif (As_Reference(index).Get_Image_Data()) {\n\t\t\tMap.Add_To_List(&As_Reference(index));\n\t\t}\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * TerrainTypeClass::Create_And_Place -- Creates and places terrain object on map.             *\n *                                                                                             *\n *    This support routine is used by the scenario editor to add a terrain object to the map.  *\n *                                                                                             *\n * INPUT:   cell  -- The cell to place the terrain object in.                                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the placement successful?                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TerrainTypeClass::Create_And_Place(CELL cell, HousesType ) const\n{\n\tif (new TerrainClass(Type, cell)) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TerrainTypeClass::Create_On_Of -- Creates a terrain object from type.                       *\n *                                                                                             *\n *    This is used to create a terrain object by using the terrain type as a guide. This       *\n *    routine is typically used by the scenario editor in order to place a terrain object      *\n *    onto the map.                                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the created terrain object or NULL if one couldn't be    *\n *          created.                                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * TerrainTypeClass::Create_One_Of(HouseClass *) const\n{\n\treturn(new TerrainClass(Type, -1));\n}\n\n\n/***********************************************************************************************\n * TerrainTypeClass::Occupy_List -- Returns with the occupy list for the terrain object type.  *\n *                                                                                             *\n *    This routine will return with the occupy list for the terrain object type. If there is   *\n *    no occupy list for this terrain object type, then a special zero length occupy list      *\n *    pointer is returned.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the terrain object's occupy list. A zero length list is  *\n *          returned in the case of no occupy list.                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * TerrainTypeClass::Occupy_List(bool ) const\n{\n\tif (Occupy != NULL) return(Occupy);\n\n\tstatic short const _simple[1] = {\n\t\tREFRESH_EOL\n\t};\n\treturn(&_simple[0]);\n}\n\n\n/***********************************************************************************************\n * TerrainTypeClass::Overlap_List -- Fetches the overlap list for the terrain type.            *\n *                                                                                             *\n *    This routine will return with the overlap list for the terrain object type. If there     *\n *    is no overlap list for the terrain object, then a null length list is returned in order  *\n *    to ensure that a non-null pointer is returned.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the overlap list for this object type. A special zero    *\n *          length list pointer is returned if there is no overlap list associated with the    *\n *          object type.                                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * TerrainTypeClass::Overlap_List(void) const\n{\n\tif (Overlap != NULL) return(Overlap);\n\n\tstatic short const _simple[1] = {\n\t\tREFRESH_EOL\n\t};\n\treturn(&_simple[0]);\n}\n\n\n/***********************************************************************************************\n * TerrainTypeClass::As_Reference -- Fetches a reference to the terrain type object specified. *\n *                                                                                             *\n *    Use this routine to convert the terrain type number into a reference to a terrain        *\n *    type class object.                                                                       *\n *                                                                                             *\n * INPUT:   type  -- The terrain type number to convert.                                       *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the terrain type class object that is referred to by   *\n *          the terrain type number.                                                           *\n *                                                                                             *\n * WARNINGS:   Be sure that the terrain type number is valid. Using an invalid value causes    *\n *             undefined behavior.                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTerrainTypeClass & TerrainTypeClass::As_Reference(TerrainType type)\n{\n\treturn(*TerrainTypes.Ptr(type));\n}\n\n\nCOORDINATE TerrainTypeClass::Coord_Fixup(COORDINATE coord) const\n{\n\treturn Coord_Whole(coord);\n}\n"
  },
  {
    "path": "CODE/TEAM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TEAM.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TEAM.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/11/94                                                     *\n *                                                                                             *\n *                  Last Update : August 27, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   TeamClass::AI -- Process team logic.                                                      *\n *   TeamClass::Add -- Adds specified object to team.                                          *\n *   TeamClass::Assign_Mission_Target -- Sets teams mission target and clears old target       *\n *   TeamClass::Calc_Center -- Determines average location of team members.                    *\n *   TeamClass::Can_Add -- Determines if the specified object can be added to team.            *\n *   TeamClass::Control -- Updates control on a member unit.                                   *\n *   TeamClass::Coordinate_Attack -- Handles coordinating a team attack.                       *\n *   TeamClass::Coordinate_Conscript -- Gives orders to new recruit.                           *\n *   TeamClass::Coordinate_Do -- Handles the team performing specified mission.                *\n *   TeamClass::Coordinate_Move -- Handles team movement coordination.                         *\n *   TeamClass::Coordinate_Regroup -- Handles team idling (regrouping).                        *\n *   TeamClass::Debug_Dump -- Displays debug information about the team.                       *\n *   TeamClass::Detach -- Removes specified target from team tracking.                         *\n *   TeamClass::Fetch_A_Leader -- Looks for a suitable leader member of the team.              *\n *   TeamClass::Has_Entered_Map -- Determines if the entire team has entered the map.          *\n *   TeamClass::Init -- Initializes the team objects for scenario preparation.                 *\n *   TeamClass::Is_A_Member -- Tests if a unit is a member of a team                           *\n *   TeamClass::Is_Leaving_Map -- Checks if team is in process of leaving the map              *\n *   TeamClass::Lagging_Units -- Finds and orders any lagging units to catch up.               *\n *   TeamClass::Recruit -- Attempts to recruit members to the team for the given index ID.     *\n *   TeamClass::Remove -- Removes the specified object from the team.                          *\n *   TeamClass::Scan_Limit -- Force all members of the team to have limited scan range.        *\n *   TeamClass::Suspend_Teams -- Suspends activity for low priority teams                      *\n *   TeamClass::TMision_Patrol -- Handles patrolling from one location to another.             *\n *   TeamClass::TMission_Attack -- Perform the team attack mission command.                    *\n *   TeamClass::TMission_Follow -- Perform the \"follow friendlies\" team command.               *\n *   TeamClass::TMission_Formation -- Process team formation change command.                   *\n *   TeamClass::TMission_Invulnerable -- Makes the entire team invulnerable for a period of tim*\n *   TeamClass::TMission_Load -- Tells the team to load onto the transport now.                *\n *   TeamClass::TMission_Loop -- Causes the team mission processor to jump to new location.    *\n *   TeamClass::TMission_Set_Global -- Performs a set global flag operation.                   *\n *   TeamClass::TMission_Spy -- Perform the team spy mission.                                  *\n *   TeamClass::TMission_Unload -- Tells the team to unload passengers now.                    *\n *   TeamClass::TeamClass -- Constructor for the team object type.                             *\n *   TeamClass::Took_Damage -- Informs the team when the team member takes damage.             *\n *   TeamClass::operator delete -- Deallocates a team object.                                  *\n *   TeamClass::operator new -- Allocates a team object.                                       *\n *   TeamClass::~TeamClass -- Team object destructor.                                          *\n *   _Is_It_Breathing -- Checks to see if unit is an active team member.                       *\n *   _Is_It_Playing -- Determines if unit is active and an initiated team member.              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include \"mission.h\"\n\n\n/***********************************************************************************************\n * _Is_It_Breathing -- Checks to see if unit is an active team member.                         *\n *                                                                                             *\n *    A unit could be a team member, but not be active. Such a case would occur when a         *\n *    reinforcement team is inside a transport. It could also occur if a unit is in the        *\n *    process of dying. Call this routine to ensure that the specified unit is a will and      *\n *    able participant in the team.                                                            *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the unit/infantry/aircraft that is to be checked.           *\n *                                                                                             *\n * OUTPUT:  bool; Is the specified unit active and able to be given commands by the team?      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic inline bool _Is_It_Breathing(FootClass const * object)\n{\n\t/*\n\t**\tIf the object is not present or appears to be dead, then it\n\t**\tcertainly isn't an active member of the team.\n\t*/\n\tif (object == NULL || !object->IsActive || object->Strength == 0) return(false);\n\n\t/*\n\t**\tIf the object is in limbo, then it isn't an active team member either. However, if the\n\t**\tscenario init flag is on, then it is probably a reinforcement issue or scenario\n\t**\tcreation situation. In such a case, the members are considered active because they need to\n\t**\tbe given special orders and treatment.\n\t*/\n\tif (!ScenarioInit && object->IsInLimbo) return(false);\n\n\t/*\n\t**\tNothing eliminated this object from being considered an active member of the team (i.e.,\n\t**\t\"breathing\"), then return that it is ok.\n\t*/\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * _Is_It_Playing -- Determines if unit is active and an initiated team member.                *\n *                                                                                             *\n *    Use this routine to determine if the specified unit is an active participant of the      *\n *    team. When a unit is first recruited to the team, it must travel to the team's location  *\n *    before it can become an active player. Call this routine to determine if the specified   *\n *    unit can be considered an active player.                                                 *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that is to be checked to see if it is an         *\n *                      active player.                                                         *\n *                                                                                             *\n * OUTPUT:  bool; Is the specified unit an active, living, initiated member of the team?       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic inline bool _Is_It_Playing(FootClass const * object)\n{\n\t/*\n\t**\tIf the object is not active, then it certainly can be a participating member of the\n\t**\tteam.\n\t*/\n\tif (!_Is_It_Breathing(object)) return(false);\n\n\t/*\n\t**\tOnly members that have been \"Initiated\" are considered \"playing\" participants of the\n\t**\tteam. This results in the team members that are racing to regroup with the team (i.e.,\n\t**\tnot initiated), will continue to catch up to the team even while the initiated team members\n\t**\tcarry out their team specific orders.\n\t*/\n\tif (!object->IsInitiated && object->What_Am_I() != RTTI_AIRCRAFT) return(false);\n\n\t/*\n\t**\tIf it reaches this point, then nothing appears to disqualify the specified object from\n\t**\tbeing considered an active playing member of the team. In this case, return that\n\t**\tinformation.\n\t*/\n\treturn(true);\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * TeamClass::Debug_Dump -- Displays debug information about the team.                         *\n *                                                                                             *\n *    This routine will display information about the team. This is useful for debugging       *\n *    purposes.                                                                                *\n *                                                                                             *\n * INPUT:   mono  -- Pointer to the monochrome screen that the debugging information will      *\n *                   be displayed on.                                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TeamClass::Debug_Dump(MonoClass * mono) const\n{\n\tmono->Set_Cursor(1, 20);mono->Printf(\"%8.8s\", Class->IniName);\n\tmono->Set_Cursor(10, 20);mono->Printf(\"%3d\", Total);\n\tmono->Set_Cursor(17, 20);mono->Printf(\"%3d\", Quantity[Class->ID]);\n\tif (CurrentMission != -1) {\n\t\tmono->Set_Cursor(1, 22);\n\t\tmono->Printf(\"%-29s\", Class->MissionList[CurrentMission].Description(CurrentMission));\n\t}\n\tmono->Set_Cursor(40, 20);mono->Printf(\"%-10s\", FormationName[Formation]);\n\tmono->Set_Cursor(22, 20);mono->Printf(\"%08X\", Zone);\n\tmono->Set_Cursor(31, 20);mono->Printf(\"%08X\", Target);\n\n\tmono->Fill_Attrib(53, 20, 12, 1, IsUnderStrength ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(53, 21, 12, 1, IsFullStrength ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(53, 22, 12, 1, IsHasBeen ? MonoClass::INVERSE : MonoClass::NORMAL);\n\n\tmono->Fill_Attrib(66, 20, 12, 1, IsMoving ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 21, 12, 1, IsForcedActive ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 22, 12, 1, IsReforming ? MonoClass::INVERSE : MonoClass::NORMAL);\n}\n#endif\n\n\n/***********************************************************************************************\n * TeamClass::Init -- Initializes the team objects for scenario preparation.                   *\n *                                                                                             *\n *    This routine clears out the team object array in preparation for starting a new          *\n *    scenario.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/29/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TeamClass::Init(void)\n{\n\tTeams.Free_All();\n}\n\n\n/***********************************************************************************************\n * TeamClass::operator new -- Allocates a team object.                                         *\n *                                                                                             *\n *    This routine will allocate a team object from the team object pool.                      *\n *                                                                                             *\n * INPUT:   size  -- The size of the requested allocation.                                     *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the freshly allocated team object. If an allocation      *\n *          could not be made, then NULL is returned.                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * TeamClass::operator new(size_t)\n{\n\tvoid * ptr = Teams.Allocate();\n\tif (ptr != NULL) {\n\t\t((TeamClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * TeamClass::operator delete -- Deallocates a team object.                                    *\n *                                                                                             *\n *    This routine will return a team object to the team object pool.                          *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the team object to deallocate.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TeamClass::operator delete(void * ptr)\n{\n\tif (ptr != NULL) {\n\t\t((TeamClass *)ptr)->IsActive = false;\n\t}\n\tTeams.Free((TeamClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * TeamClass::~TeamClass -- Team object destructor.                                            *\n *                                                                                             *\n *    This routine is called when a team object is destroyed. It handles updating the total    *\n *    number count for this team object type.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *   07/04/1996 JLB : Keeps trigger if trigger still attached to objects.                      *\n *=============================================================================================*/\nTeamClass::~TeamClass(void)\n{\n\tif (GameActive && Class.Is_Valid()) {\n\t\twhile (Member != NULL) {\n\t\t\tRemove(Member);\n\t\t}\n\t\tClass->Number--;\n\n\t\t/*\n\t\t**\tWhen the team dies, any trigger associated with it, dies as well. This will only occur\n\t\t**\tif there are no other objects linked to this trigger. Only player reinforcement\n\t\t**\tmembers that broke off of the team earlier will have this occur.\n\t\t*/\n\t\tif (Trigger.Is_Valid()) {\n\t\t\tif (Trigger->AttachCount == 0) {\n\t\t\t\tdelete (TriggerClass *)Trigger;\n\t\t\t}\n\t\t\tTrigger = NULL;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamClass::TeamClass -- Constructor for the team object type.                               *\n *                                                                                             *\n *    This routine is called when the team object is created.                                  *\n *                                                                                             *\n * INPUT:   type  -- Pointer to the team type to make this team object from.                   *\n *                                                                                             *\n *          owner -- The owner of this team.                                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTeamClass::TeamClass(TeamTypeClass const * type, HouseClass * owner) :\n\tAbstractClass(RTTI_TEAM, Teams.ID(this)),\n\tClass((TeamTypeClass *)type),\n\tHouse(owner),\n\tIsForcedActive(false),\n\tIsHasBeen(false),\n\tIsFullStrength(false),\n\tIsUnderStrength(true),\n\tIsReforming(false),\n\tIsLagging(false),\n\tIsAltered(true),\n\tJustAltered(false),\n\tIsMoving(false),\n\tIsNextMission(true),\n\tIsLeaveMap(false),\n\tSuspended(false),\n\tTrigger(NULL),\n\tZone(TARGET_NONE),\n\tClosestMember(TARGET_NONE),\n\tMissionTarget(TARGET_NONE),\n\tTarget(TARGET_NONE),\n\tTotal(0),\n\tRisk(0),\n\tFormation(FORMATION_NONE),\n\tSuspendTimer(0),\n\tCurrentMission(-1),\n\tTimeOut(0),\n\tMember(0)\n{\n\tassert(Class);\n\tassert(Class->IsActive);\n\tassert(Class->ClassCount > 0);\n\n\tif (owner == NULL) {\n\t\tHouse = HouseClass::As_Pointer(Class->House);\n\t}\n\n\tmemset(Quantity, 0, sizeof(Quantity));\n\tif (Class->Origin != -1) {\n\t\tZone = ::As_Target(Scen.Waypoint[Class->Origin]);\n\t}\n\tClass->Number++;\n\n\t/*\n\t**\tIf there is a trigger tightly associated with this team, then\n\t**\tcreate an instance of that trigger and attach it to the team.\n\t*/\n\tif (Class->Trigger.Is_Valid()) {\n\t\tTrigger = new TriggerClass(Class->Trigger);\n\t}\n}\n\n\n/***************************************************************************\n * TeamClass::Assign_Mission_Target -- Sets mission target and clears old  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid TeamClass::Assign_Mission_Target(TARGET new_target)\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\t/*\n\t** First go through and find anyone who is currently targeting\n\t** the old mission target and clear their Tarcom.\n\t*/\n\tFootClass * unit = Member;\n\tif (MissionTarget != TARGET_NONE) {\n\t\twhile (unit != NULL) {\n\t\t\tbool tar = (unit->TarCom == MissionTarget);\n\t\t\tbool nav = (unit->NavCom == MissionTarget);\n\t\t\tif (tar || nav) {\n\n\t\t\t\t/*\n\t\t\t\t** If the unit was doing something related to the team mission\n\t\t\t\t** then we kick him into guard mode so that he is easy to change\n\t\t\t\t** missions for.\n\t\t\t\t*/\n\t\t\t\tunit->Assign_Mission(MISSION_GUARD);\n\n\t\t\t\t/*\n\t\t\t\t** If the unit's tarcom is set to the old mission target, then\n\t\t\t\t** clear it, so that it will be reset by whatever happens next.\n\t\t\t\t*/\n\t\t\t\tif (nav) {\n\t\t\t\t\tunit->Assign_Destination(TARGET_NONE);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** If the unit's navcom is set to the old mission target, then\n\t\t\t\t** clear it, so that it will be reset by whatever happens next.\n\t\t\t\t*/\n\t\t\t\tif (tar) {\n\t\t\t\t\tunit->Assign_Target(TARGET_NONE);\n\t\t\t\t}\n\t\t\t}\n\t\t\tunit = unit->Member;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is not currently an override on the current mission target\n\t** then assign both MissionTarget and Target to the new target.  If\n\t** there is an override, allow the team to keep fighting the override but\n\t** make sure they pick up on the new mission when they are ready.\n\t*/\n\tif (Target == MissionTarget || !Target_Legal(Target)) {\n\t\tMissionTarget = Target = new_target;\n\t} else {\n\t\tMissionTarget = new_target;\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamClass::AI -- Process team logic.                                                        *\n *                                                                                             *\n *    General purpose team logic is handled by this routine. It should be called once per      *\n *    active team per game tick. This routine handles recruitment and assigning orders to      *\n *    member units.                                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/29/1994 JLB : Created.                                                                 *\n *   01/06/1995 JLB : Choreographed gesture.                                                   *\n *=============================================================================================*/\nvoid TeamClass::AI(void)\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\tint\tdesired\t\t= 0;\n\tint\told_under\t= IsUnderStrength;\n\tint\told_full\t\t= IsFullStrength;\n\n\t/*\n\t** If the team has been suspended then we need to check if it's time for\n\t** us to reactivate the team.  If not, no team logic will be processed\n\t** for this team.\n\t*/\n\tif (Suspended) {\n\t\tif (SuspendTimer != 0) {\n\t\t\treturn;\n\t\t}\n\t\tSuspended = false;\n\t}\n\n\t/*\n\t**\tIf this team senses that its composition has been altered, then it should\n\t**\trecalculate the under strength and full strength flags.\n\t*/\n\tif (IsAltered) {\n\n\t\t/*\n\t\t**\tFigure out the total number of objects that this team type requires.\n\t\t*/\n\t\tfor (int index = 0; index < Class->ClassCount; index++) {\n\t\t\tdesired += Class->Members[index].Quantity;\n\t\t}\n\t\tassert(desired != 0);\n\n\t\tif (Total) {\n\t\t\tIsFullStrength = (Total == desired);\n\t\t\tif (IsFullStrength) {\n\t\t\t\tIsHasBeen = true;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tReinforceable teams will revert (or snap out of) the under strength\n\t\t\t**\tmode when the members transition the magic 1/3 strength threshold.\n\t\t\t*/\n\t\t\tif (Class->IsReinforcable) {\n\t\t\t\tif (desired > 2) {\n\t\t\t\t\tIsUnderStrength = (Total <= desired / 3);\n\t\t\t\t} else {\n\t\t\t\t\tIsUnderStrength = (Total < desired);\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tTeams that are not flagged as reinforceable are never considered under\n\t\t\t\t**\tstrength if the team has already started its main mission. This\n\t\t\t\t**\tensures that once the team has started, it won't dally to pick up\n\t\t\t\t**\tnew members.\n\t\t\t\t*/\n\t\t\t\tIsUnderStrength = !IsHasBeen;\n\t\t\t}\n\n\t\t\tIsAltered = JustAltered = false;\n\t\t} else {\n\t\t\tIsUnderStrength = true;\n\t\t\tIsFullStrength = false;\n\t\t\tZone = TARGET_NONE;\n\n\t\t\t/*\n\t\t\t**\tA team that exists on the player's side is automatically destroyed\n\t\t\t**\twhen there are no team members left. This team was created as a\n\t\t\t**\tresult of reinforcement logic and no longer needs to exist when there\n\t\t\t**\tare no more team members.\n\t\t\t*/\n\t\t\tif (IsHasBeen || Session.Type != GAME_NORMAL) {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this team had no members (i.e., the team object wasn't terminated by some\n\t\t\t\t**\toutside means), then pass through the logic triggers to see if one that\n\t\t\t\t**\tdepends on this team leaving the map should be sprung.\n\t\t\t\t*/\n\t\t\t\tif (IsLeaveMap) {\n\t\t\t\t\tfor (int index = 0; index < LogicTriggers.Count(); index++) {\n\t\t\t\t\t\tTriggerClass * trig = LogicTriggers[index];\n\t\t\t\t\t\tif (trig->Spring(TEVENT_LEAVES_MAP)) {\n\t\t\t\t\t\t\tindex--;\n\t\t\t\t\t\t\tif (LogicTriggers.Count() == 0) break;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete this;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** If the team has gone from under strength to no longer under\n\t\t** strength than the team needs to reform.\n\t\t*/\n\t\tif (old_under != IsUnderStrength) {\n\t\t\tIsReforming = true;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the team is under strength, then flag it to regroup.\n\t*/\n\tif (IsMoving && IsUnderStrength) {\n\t\tIsMoving\t\t\t= false;\n\t\tCurrentMission\t= -1;\n\t\tif (Total) {\n\t\t\tCalc_Center(Zone, ClosestMember);\n\n\t\t\t/*\n\t\t\t** When a team is badly damaged and needs to regroup it should\n\t\t\t** pick a friendly building to go and regroup at.  Its first preference\n\t\t\t** should be somewhere near repair factory.  If it cannot find a repair\n\t\t\t** factory then it should pick another structure that is friendly to\n\t\t\t** its side.\n\t\t\t*/\n\t\t\tCELL \tdest\t= As_Cell(Zone);\n\t\t\tint \tmax\t= 0x7FFFFFFF;\n\n\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\tBuildingClass * b = Buildings.Ptr(index);\n\n\t\t\t\tif (b != NULL && !b->IsInLimbo && b->House == House && b->Class->PrimaryWeapon == NULL) {\n\t\t\t\t\tCELL cell = Coord_Cell(b->Center_Coord());\n\t\t\t\t\tint dist = ::Distance(b->Center_Coord(), As_Coord(Zone)) * (Map.Cell_Threat(cell, House->Class->House) + 1);\n\n\t\t\t\t\tif (*b == STRUCT_REPAIR) {\n\t\t\t\t\t\tdist /= 2;\n\t\t\t\t\t}\n\t\t\t\t\tif (dist < max) {\n\t\t\t\t\t\tcell = Fetch_A_Leader()->Safety_Point(As_Cell(Zone), cell, 2, 4);\n//\t\t\t\t\t\tcell = Member->Safety_Point(As_Cell(Zone), cell, 2, 4);\n\t\t\t\t\t\tif (cell != -1) {\n\t\t\t\t\t\t\tmax = dist;\n\t\t\t\t\t\t\tdest = cell;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Should calculate a regroup location.\n\t\t\tTarget = ::As_Target(dest);\n\t\t\tCoordinate_Move();\n\t\t\treturn;\n\t\t} else {\n\t\t\tZone = TARGET_NONE;\n\t\t}\n\t}\n\n\t/*\n\t**\tFlag this team into action when it gets to full strength. Human owned teams are only\n\t**\tused for reinforcement purposes -- always consider them at full strength.\n\t*/\n\tif (!IsMoving && (IsFullStrength || IsForcedActive)) {\n\t\tIsMoving = true;\n\t\tIsHasBeen = true;\n\t\tIsUnderStrength = false;\n\n\t\t/*\n\t\t**\tInfantry can do a gesture when they start their mission. Pick\n\t\t**\ta gesture at random.\n\t\t*/\n\t\tFootClass * techno = Member;\n\t\tDoType doaction = Percent_Chance(50) ? DO_GESTURE1 : DO_GESTURE2;\n\t\twhile (techno) {\n\t\t\tif (_Is_It_Breathing(techno) && techno->What_Am_I() == RTTI_INFANTRY) {\n\t\t\t\t((InfantryClass *)techno)->Do_Action(doaction);\n\t\t\t}\n\n\t\t\tif (IsReforming || IsForcedActive) {\n\t\t\t\ttechno->IsInitiated = true;\n\t\t\t}\n\n\t\t\ttechno = techno->Member;\n\t\t}\n\t\tCurrentMission\t= -1;\n\t\tIsNextMission\t= true;\n//\t\tIsForcedActive = false;\n\t}\n\n\t/*\n\t**\tIf the team is moving or if there is no center position for\n\t**\tthe team, then the center position must be recalculated.\n\t*/\n\tif (IsReforming || IsMoving || Zone == TARGET_NONE || ClosestMember == TARGET_NONE) {\n\t\tCalc_Center(Zone, ClosestMember);\n\t}\n\n\t/*\n\t**\tTry to recruit members if there is room to do so for this team.\n\t**\tOnly try to recruit members for a non player controlled team.\n\t*/\n\tif ((!IsMoving || (!IsFullStrength && Class->IsReinforcable)) && ((!House->IsHuman || !IsHasBeen) && Session.Type == GAME_NORMAL)) {\n//\tif ((!IsMoving || (!IsFullStrength && Class->IsReinforcable)) && ((/*!House->IsHuman ||*/ !IsHasBeen) && Session.Type == GAME_NORMAL)) {\n\t\tfor (int index = 0; index < Class->ClassCount; index++) {\n\t\t\tif (Quantity[index] < Class->Members[index].Quantity) {\n\t\t\t\tRecruit(index);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there are no members of the team and the team has reached\n\t**\tfull strength at one time, then delete the team.\n\t*/\n\tif (Member == NULL && IsHasBeen) {\n\n\t\t/*\n\t\t**\tIf this team had no members (i.e., the team object wasn't terminated by some\n\t\t**\toutside means), then pass through the logic triggers to see if one that\n\t\t**\tdepends on this team leaving the map should be sprung.\n\t\t*/\n\t\tif (IsLeaveMap) {\n\t\t\tfor (int index = 0; index < LogicTriggers.Count(); index++) {\n\t\t\t\tTriggerClass * trig = LogicTriggers[index];\n\t\t\t\tif (trig->Spring(TEVENT_LEAVES_MAP)) {\n\t\t\t\t\tindex--;\n\t\t\t\t\tif (LogicTriggers.Count() == 0) break;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdelete this;\n\t\treturn;\n\t}\n\n\t/*\n\t**\tIf the mission should be advanced to the next entry, then do so at\n\t**\tthis time. Various events may cause the mission to advance, but it\n\t**\tall boils down to the following change-mission code.\n\t*/\n\tif (IsMoving && !IsReforming && IsNextMission) {\n\t\tIsNextMission = false;\n\t\tCurrentMission++;\n\t\tif (CurrentMission < Class->MissionCount) {\n\t\t\tTeamMissionClass const * mission = &Class->MissionList[CurrentMission];\n\n\t\t\tTimeOut = mission->Data.Value * (TICKS_PER_MINUTE/10);\n\t\t\tTarget = TARGET_NONE;\n\t\t\tswitch (mission->Mission) {\n\n\t\t\t\tcase TMISSION_MOVECELL:\n\t\t\t\t\tAssign_Mission_Target(::As_Target((CELL)(mission->Data.Value)));\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TMISSION_MOVE:\n\t\t\t\t\tif ((unsigned)mission->Data.Value < WAYPT_COUNT && Member != NULL) {\n\t\t\t\t\t\tFootClass * leader = Fetch_A_Leader();\n\t\t\t\t\t\tCELL movecell = Scen.Waypoint[mission->Data.Value];\n\t\t\t\t\t\tif (!Is_Leaving_Map()) {\n\t\t\t\t\t\t\tif (leader->Can_Enter_Cell(movecell) != MOVE_OK) {\n\t\t\t\t\t\t\t\tmovecell = Map.Nearby_Location(movecell, leader->Techno_Type_Class()->Speed);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tAssign_Mission_Target(::As_Target(movecell));\n\t\t\t\t\t\tTarget = ::As_Target(movecell);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TMISSION_ATT_WAYPT:\n\t\t\t\tcase TMISSION_PATROL:\n\t\t\t\tcase TMISSION_SPY:\n\t\t\t\t\tif ((unsigned)mission->Data.Value < WAYPT_COUNT) {\n\t\t\t\t\t\tAssign_Mission_Target(::As_Target(Scen.Waypoint[mission->Data.Value]));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TMISSION_ATTACKTARCOM:\n\t\t\t\t\tAssign_Mission_Target(mission->Data.Value);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TMISSION_UNLOAD:\n\t\t\t\tdefault:\n\t\t\t\t\tAssign_Mission_Target(TARGET_NONE);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\tdelete this;\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/*\n\t**\tPerform mission of the team. This depends on the mission list.\n\t*/\n\tif (Member != NULL && IsMoving && !IsReforming && !IsUnderStrength) {\n\n\t\t/*\n\t\t** If the current Target has been dealt with but the mission target\n\t\t** has not, then the current target needs to be reset to the mission\n\t\t** target.\n\t\t*/\n\t\tif (!Target_Legal(Target)) {\n\t\t\tTarget = MissionTarget;\n\t\t}\n\n\t\t/*\n\t\t**\tIf the current mission is one that times out, then check for\n\t\t**\tthis case. If it has timed out then advance to the next\n\t\t**\tmission in the list or disband the team.\n\t\t*/\n\t\tTeamMissionClass const * mission = &Class->MissionList[CurrentMission];\n//\t\tFootClass\t* member = Member;\n\n\t\tswitch (mission->Mission) {\n\t\t\tcase TMISSION_PATROL:\n\t\t\t\tTMission_Patrol();\n\t\t\t\tbreak;\n\n\t\t\tcase TMISSION_FORMATION:\n\t\t\t\tTMission_Formation();\n\t\t\t\tbreak;\n\n\t\t\tcase TMISSION_ATTACKTARCOM:\n\t\t\tcase TMISSION_ATTACK:\n\t\t\t\tTMission_Attack();\n\t\t\t\tbreak;\n\n\t\t\tcase TMISSION_LOAD:\n\t\t\t\tTMission_Load();\n\t\t\t\tbreak;\n\n\t\t\tcase TMISSION_DEPLOY:\n\t\t\t\tTMission_Deploy();\n\t\t\t\tbreak;\n\n\t\t\tcase TMISSION_UNLOAD:\n\t\t\t\tTMission_Unload();\n\t\t\t\tbreak;\n\n\t\t\tcase TMISSION_MOVE:\n\t\t\tcase TMISSION_MOVECELL:\n\t\t\t\tCoordinate_Move();\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tAll members of this team become invulnerable as if by magic.\n\t\t\t*/\n\t\t\tcase TMISSION_INVULNERABLE:\n\t\t\t\tTMission_Invulnerable();\n\t\t\t\tbreak;\n\n\t\t\tcase TMISSION_GUARD:\n\t\t\t\tCoordinate_Regroup();\n\t\t\t\tbreak;\n\n\t\t\tcase TMISSION_DO:\n\t\t\t\tCoordinate_Do();\n\t\t\t\tbreak;\n\n\t\t\tcase TMISSION_SET_GLOBAL:\n\t\t\t\tTMission_Set_Global();\n\t\t\t\tbreak;\n\n\t\t\tcase TMISSION_ATT_WAYPT:\n\t\t\t\tif (!Target_Legal(MissionTarget)) {\n\t\t\t\t\tAssign_Mission_Target(TARGET_NONE);\n\t\t\t\t\tIsNextMission = true;\n\t\t\t\t} else {\n\t\t\t\t\tCoordinate_Attack();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase TMISSION_SPY:\n\t\t\t\tTMission_Spy();\n\t\t\t\tbreak;\n\n\t\t\tcase TMISSION_HOUND_DOG:\n\t\t\t\tTMission_Follow();\n\t\t\t\tbreak;\n\n\t\t\tcase TMISSION_LOOP:\n\t\t\t\tTMission_Loop();\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tCheck for mission time out condition. If the mission does in fact time out, then\n\t\t**\tflag it so that the team mission list will advance.\n\t\t*/\n\t\tswitch (mission->Mission) {\n//\t\t\tcase TMISSION_UNLOAD:\n\t\t\tcase TMISSION_GUARD:\n\t\t\t\tif (TimeOut == 0) {\n\t\t\t\t\tIsNextMission = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t} else {\n\n\t\tif (IsMoving) {\n\t\t\tIsReforming = !Coordinate_Regroup();\n\t\t} else {\n\t\t\tCoordinate_Move();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamClass::Add -- Adds specified object to team.                                            *\n *                                                                                             *\n *    Use this routine to add the specified object to the team. The object is checked to make  *\n *    sure that it can be assigned to the team. If it can't, then the object will be left      *\n *    alone and false will be returned.                                                        *\n *                                                                                             *\n * INPUT:   obj      -- Pointer to the object that is to be assigned to this team.             *\n *                                                                                             *\n * OUTPUT:  bool; Was the unit added to the team?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/29/1994 JLB : Created.                                                                 *\n *   01/02/1995 JLB : Initiation flag setup.                                                   *\n *   08/06/1995 JLB : Allows member stealing from lesser priority teams.                       *\n *=============================================================================================*/\nbool TeamClass::Add(FootClass * obj)\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\tif (!obj) return(false);\n\n\tint typeindex;\n\tif (!Can_Add(obj, typeindex)) return(false);\n\n\t/*\n\t**\tAll is ok to add the object to the team, but if the object is already part of\n\t**\tanother team, then it must be removed from that team first.\n\t*/\n\tif (obj->Team.Is_Valid()) {\n\t\tobj->Team->Remove(obj);\n\t}\n\n\t/*\n\t**\tActually add the object to the team.\n\t*/\n\tQuantity[typeindex]++;\n\tobj->IsInitiated = (Member == NULL);\n\tobj->Member = Member;\n\tMember = obj;\n\tobj->Team = this;\n\n\t/*\n\t**\tIf a common trigger is designated for this team type, then attach the\n\t**\ttrigger to this team member.\n\t*/\n\tif (Trigger.Is_Valid()) {\n\t\tobj->Attach_Trigger(Trigger);\n\t}\n\n\tTotal++;\n\tRisk += obj->Risk();\n\tif (Zone == TARGET_NONE) {\n\t\tCalc_Center(Zone, ClosestMember);\n\t}\n\n\t/*\n\t**\tReturn with success, since the object was added to the team.\n\t*/\n\tIsAltered = JustAltered = true;\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * TeamClass::Can_Add -- Determines if the specified object can be added to team.              *\n *                                                                                             *\n *    This routine will examine the team and determine if the specified object can be          *\n *    properly added to this team. This is a security check to filter out those objects that   *\n *    should not be added because of conflicting priorities or other restrictions.             *\n *                                                                                             *\n * INPUT:   obj      -- Pointer to the candidate object that is being checked for legal        *\n *                      adding to this team.                                                   *\n *                                                                                             *\n *          typeindex-- The class index number (according to the team type's class array) that *\n *                      the candidate object is classified as. The routine processes much      *\n *                      faster if you can provide this information, but if you don't, the      *\n *                      routine will figure it out.                                            *\n *                                                                                             *\n * OUTPUT:  bool; Can the specified object be added to this team?                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/27/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TeamClass::Can_Add(FootClass * obj, int & typeindex) const\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\t/*\n\t**\tTrying to add the team member to itself is an error condition.\n\t*/\n\tif (obj->Team == this) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tThe object must be active, a member of this house. A special dispensation is given to\n\t**\tunits that are in radio contact. It is presumed that they are very busy and should\n\t**\tnot be disturbed.\n\t*/\n\tif (!_Is_It_Breathing(obj) || obj->In_Radio_Contact() || obj->House != House) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the object is doing some mission that precludes it from joining\n\t**\ta team then don't add it.\n\t*/\n\tif (obj->Mission != MISSION_NONE && !MissionClass::Is_Recruitable_Mission(obj->Mission)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf this object is part of another team, then check to make sure that it\n\t**\tis permitted to leave the other team in order to join this one. If not,\n\t**\tthen no further processing is allowed -- bail.\n\t*/\n\tif (obj->Team.Is_Valid() && (obj->Team->Class->RecruitPriority >= Class->RecruitPriority)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tAircraft that have no ammo for their weapons cannot be recruited into a team.\n\t*/\n\tif (obj->What_Am_I() == RTTI_AIRCRAFT && obj->Techno_Type_Class()->PrimaryWeapon != NULL && !obj->Ammo) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tSearch for the exact member index that the candidate object matches.\n\t**\tIf no match could be found, then adding the object to the team cannot\n\t**\toccur.\n\t*/\n\tfor (typeindex = 0; typeindex < Class->ClassCount; typeindex++) {\n\t\tif (Class->Members[typeindex].Class == &obj->Class_Of()) {\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (typeindex == Class->ClassCount) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the team is already full of this type, then adding the object is not allowed.\n\t**\tReturn with a failure flag in this case.\n\t*/\n\tif (Quantity[typeindex] >= Class->Members[typeindex].Quantity) {\n\t\treturn(false);\n\t}\n\n\treturn(true);\n}\n\n\n\n/***********************************************************************************************\n * TeamClass::Remove -- Removes the specified object from the team.                            *\n *                                                                                             *\n *    Use this routine to remove an object from a team. Objects removed from the team are      *\n *    then available to be recruited by other teams, or even by the same team at a later time. *\n *                                                                                             *\n * INPUT:   obj      -- Pointer to the object that is to be removed from this team.            *\n *                                                                                             *\n *          typeindex-- Optional index of where this object type is specified in the type      *\n *                      type class. This parameter can be omitted. It only serves to make      *\n *                      the removal process faster.                                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the object removed from this team?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/29/1994 JLB : Created.                                                                 *\n *   01/02/1995 JLB : Initiation tracking and team captain selection.                          *\n *=============================================================================================*/\nbool TeamClass::Remove(FootClass * obj, int typeindex)\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\t/*\n\t**\tMake sure that the object is in fact a member of this team. If not, then it can't\n\t**\tbe removed. Return success because the end result is the same.\n\t*/\n\tif (this != obj->Team) {\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tDetach the common trigger for this team type. Only current and active members of the\n\t**\tteam have that trigger attached. The exception is for player team members that\n\t**\tget removed from a reinforcement team.\n\t*/\n\tif (obj->Trigger == Trigger && !obj->House->IsPlayerControl) {\n\t\tobj->Attach_Trigger(NULL);\n\t}\n\n\t/*\n\t**\tIf the proper team index was not provided, then find it in the type type class. The\n\t**\tteam type class will not be set if the appropriate type could not be found\n\t**\tfor this object. This indicates that the object was illegally added. Continue to\n\t**\tprocess however, since removing this object from the team is a good idea.\n\t*/\n\tif (typeindex == -1) {\n\t\tfor (typeindex = 0; typeindex < Class->ClassCount; typeindex++) {\n\t\t\tif (Class->Members[typeindex].Class == &obj->Class_Of()) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tDecrement the counter for the team class. There is now one less of this object type.\n\t*/\n\tif ((unsigned)typeindex < Class->ClassCount) {\n\t\tQuantity[typeindex]--;\n\t}\n\n\t/*\n\t**\tActually remove the object from the team. Scan through the team members\n\t**\tlooking for the one that matches the one specified. If it is found, it\n\t**\tis unlinked from the member chain. During this scan, a check is made to\n\t**\tensure that at least one remaining member is still initiated. If not, then\n\t**\ta new team captain must be chosen.\n\t*/\n\tbool initiated = false;\n\tFootClass * prev = 0;\n\tFootClass * curr = Member;\n\tbool found = false;\n\twhile (curr != NULL && (!found || !initiated)) {\n\t\tif (curr == obj) {\n\t\t\tif (prev != NULL) {\n\t\t\t\tprev->Member = curr->Member;\n\t\t\t} else {\n\t\t\t\tMember = curr->Member;\n\t\t\t}\n\t\t\tFootClass * temp = curr->Member;\n\t\t\tcurr->Member = 0;\n\t\t\tcurr->Team = 0;\n\t\t\tcurr->SuspendedMission = MISSION_NONE;\n\t\t\tcurr->SuspendedNavCom = TARGET_NONE;\n\t\t\tcurr->SuspendedTarCom = TARGET_NONE;\n\t\t\tcurr = temp;\n\t\t\tTotal--;\n\t\t\tfound = true;\n\t\t\tRisk -= obj->Risk();\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tIf this (remaining) member is initiated, then keep a record of this.\n\t\t*/\n\t\tinitiated |= curr->IsInitiated;\n\n\t\tprev = curr;\n\t\tcurr = curr->Member;\n\t}\n\n\t/*\n\t**\tA unit that breaks off of a team will enter idle mode.\n\t*/\n\tobj->Enter_Idle_Mode();\n\n\t/*\n\t**\tIf, after removing the team member, there are no initiated members left\n\t**\tin the team, then just make the first remaining member of the team the\n\t**\tteam captain. Mark the center location of the team as invalid so that\n\t**\tit will be centered around the captain.\n\t*/\n\tif (!initiated && Member != NULL) {\n\t\tMember->IsInitiated = true;\n\t\tZone = TARGET_NONE;\n\t}\n\n\t/*\n\t**\tMust record that the team composition has changed. At the next opportunity,\n\t**\tthe team members will be counted and appropriate AI adjustments made.\n\t*/\n\tIsAltered = JustAltered = true;\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * TeamClass::Recruit -- Attempts to recruit members to the team for the given index ID.       *\n *                                                                                             *\n *    This routine will take the given index ID and scan for available objects of that type    *\n *    to recruit to the team. Recruiting will continue until that object type has either       *\n *    been exhausted or if the team's requirement for that type has been filled.               *\n *                                                                                             *\n * INPUT:   typeindex   -- The index for the object type to recruit. The index is used to      *\n *                         look into the type type's array of object types that make up this   *\n *                         team.                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of objects added to this team.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/29/1994 JLB : Created.                                                                 *\n *   04/10/1995 JLB : Scans for units too.                                                     *\n *=============================================================================================*/\nint TeamClass::Recruit(int typeindex)\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\tCOORDINATE center = As_Coord(Zone);\n\n\tif (Class->Origin != -1) {\n\t\tcenter = Cell_Coord(Scen.Waypoint[Class->Origin]);\n\t}\n\n\tint added = 0;\t\t\t\t// Total number added to team.\n\n\t/*\n\t**\tQuick check to see if recruiting is really allowed for this index or not.\n\t*/\n\tif (Class->Members[typeindex].Quantity > Quantity[typeindex]) {\n\t\tswitch (Class->Members[typeindex].Class->What_Am_I()) {\n\n\t\t\t/*\n\t\t\t**\tFor infantry objects, sweep through the infantry in the game looking for\n\t\t\t**\tones owned by the house that owns the team. When found, try to add.\n\t\t\t*/\n\t\t\tcase RTTI_INFANTRYTYPE:\n\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t{\n\t\t\t\t\tInfantryClass * best = 0;\n\t\t\t\t\tint bestdist = -1;\n\n\t\t\t\t\tfor (int index = 0; index < Infantry.Count(); index++) {\n\t\t\t\t\t\tInfantryClass * infantry = Infantry.Ptr(index);\n\t\t\t\t\t\tint d = infantry->Distance(center);\n\n\t\t\t\t\t\tif ((d < bestdist || bestdist == -1) && Can_Add(infantry, typeindex)) {\n\t\t\t\t\t\t\tbest = infantry;\n\t\t\t\t\t\t\tbestdist = d;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (best) {\n\t\t\t\t\t\tbest->Assign_Target(TARGET_NONE);\n\t\t\t\t\t\tAdd(best);\n\t\t\t\t\t\tadded++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\t{\n\t\t\t\t\tAircraftClass * best = 0;\n\t\t\t\t\tint bestdist = -1;\n\n\t\t\t\t\tfor (int index = 0; index < Aircraft.Count(); index++) {\n\t\t\t\t\t\tAircraftClass * aircraft = Aircraft.Ptr(index);\n\t\t\t\t\t\tint d = aircraft->Distance(center);\n\n\t\t\t\t\t\tif ((d < bestdist || bestdist == -1) && Can_Add(aircraft, typeindex)) {\n\t\t\t\t\t\t\tbest = aircraft;\n\t\t\t\t\t\t\tbestdist = d;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (best) {\n\t\t\t\t\t\tbest->Assign_Target(TARGET_NONE);\n\t\t\t\t\t\tAdd(best);\n\t\t\t\t\t\tadded++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_UNITTYPE:\n\t\t\tcase RTTI_UNIT:\n\t\t\t\t{\n\t\t\t\t\tUnitClass * best = 0;\n\t\t\t\t\tint bestdist = -1;\n\n\t\t\t\t\tfor (int index = 0; index < Units.Count(); index++) {\n\t\t\t\t\t\tUnitClass * unit = Units.Ptr(index);\n\t\t\t\t\t\tint d = unit->Distance(center);\n\n\t\t\t\t\t\tif (unit->House == House && unit->Class == Class->Members[typeindex].Class) {\n\n\t\t\t\t\t\t\tif ((d < bestdist || bestdist == -1) && Can_Add(unit, typeindex)) {\n\t\t\t\t\t\t\t\tbest = unit;\n\t\t\t\t\t\t\t\tbestdist = d;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (best) {\n\t\t\t\t\t\t\tbest->Assign_Target(TARGET_NONE);\n\t\t\t\t\t\t\tAdd(best);\n\t\t\t\t\t\t\tadded++;\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf a transport is added to the team, the occupants\n\t\t\t\t\t\t\t**\tare added by default.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tFootClass * f = best->Attached_Object();\n\t\t\t\t\t\t\twhile (f) {\n\t\t\t\t\t\t\t\tAdd(f);\n\t\t\t\t\t\t\t\tf = (FootClass *)(ObjectClass *)f->Next;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_VESSELTYPE:\n\t\t\tcase RTTI_VESSEL:\n\t\t\t\t{\n\t\t\t\t\tVesselClass * best = 0;\n\t\t\t\t\tint bestdist = -1;\n\n\t\t\t\t\tfor (int index = 0; index < Vessels.Count(); index++) {\n\t\t\t\t\t\tVesselClass * vessel = Vessels.Ptr(index);\n\t\t\t\t\t\tint d = vessel->Distance(center);\n\n\t\t\t\t\t\tif (vessel->House == House && vessel->Class == Class->Members[typeindex].Class) {\n\n\t\t\t\t\t\t\tif ((d < bestdist || bestdist == -1) && Can_Add(vessel, typeindex)) {\n\t\t\t\t\t\t\t\tbest = vessel;\n\t\t\t\t\t\t\t\tbestdist = d;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (best) {\n\t\t\t\t\t\t\tbest->Assign_Target(TARGET_NONE);\n\t\t\t\t\t\t\tAdd(best);\n\t\t\t\t\t\t\tadded++;\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf a transport is added to the team, the occupants\n\t\t\t\t\t\t\t**\tare added by default.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tFootClass * f = best->Attached_Object();\n\t\t\t\t\t\t\twhile (f) {\n\t\t\t\t\t\t\t\tAdd(f);\n\t\t\t\t\t\t\t\tf = (FootClass *)(ObjectClass *)f->Next;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn(added);\n}\n\n\n/***********************************************************************************************\n * TeamClass::Detach -- Removes specified target from team tracking.                           *\n *                                                                                             *\n *    When a target object is about to be removed from the game (e.g., it was killed), then    *\n *    any team that is looking at that target must abort from that target.                     *\n *                                                                                             *\n * INPUT:   target   -- The target object that is going to be removed from the game.           *\n *                                                                                             *\n *          all      -- Is the target going away for good as opposed to just cloaking/hiding?  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/29/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TeamClass::Detach(TARGET target, bool )\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\t/*\n\t**\tIf the target to detach matches the target of this team, then remove\n\t**\tthe target from this team's Tar/Nav com and let the chips fall\n\t**\twhere they may.\n\t*/\n\tif (Target == target) {\n\t\tTarget = TARGET_NONE;\n\t}\n\tif (MissionTarget == target) {\n\t\tMissionTarget = TARGET_NONE;\n\t}\n\tif (Trigger.Is_Valid() && Trigger->As_Target() == target) {\n\t\tTrigger = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamClass::Calc_Center -- Determines average location of team members.                      *\n *                                                                                             *\n *    Use this routine to calculate the \"center\" location of the team. This is the average     *\n *    position of all members of the team. Using this center value it is possible to tell      *\n *    if a team member is too far away and where to head to in order to group up.              *\n *                                                                                             *\n * INPUT:   center   -- Average center target location of the team. Only initiated members     *\n *                      will be considered.                                                    *\n *                                                                                             *\n *          close_member--Location (as target) of the unit that is closest to the team's       *\n *                      target.                                                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/29/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TeamClass::Calc_Center(TARGET & center, TARGET & close_member) const\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\t/*\n\t**\tPresume there is no center. This will be confirmed in the following scanning\n\t**\toperation.\n\t*/\n\tclose_member = TARGET_NONE;\n\tcenter = TARGET_NONE;\n\n\tFootClass const * team_member = Member;\t\t// Working team member pointer.\n\n\t/*\n\t**\tIf there are no members of the team, then there can be no center point of the team.\n\t*/\n\tif (team_member == NULL) return;\n\n\t/*\n\t**\tIf the team is supposed to follow a nearby friendly unit, then the\n\t**\tteam's \"center\" will actually be that unit. Otherwise, calculated the\n\t**\taverage center location for the team.\n\t*/\n\tif (Class->MissionList[CurrentMission].Mission == TMISSION_HOUND_DOG) {\n\n\t\t/*\n\t\t**\tFirst pick a member of the team. The closest friendly object to that member\n\t\t**\twill be picked.\n\t\t*/\n\t\tif (!team_member) return;\n\n\t\tFootClass const * closest = NULL;\t// Current closest friendly object.\n\t\tint distance = -1;\t\t\t\t\t// Record of last closest distance calc.\n\n\t\t/*\n\t\t**\tScan through all vehicles.\n\t\t*/\n\t\tfor (int unit_index = 0; unit_index < Units.Count(); unit_index++) {\n\t\t\tFootClass const * trial_unit = Units.Ptr(unit_index);\n\n\t\t\tif (_Is_It_Breathing(trial_unit) && trial_unit->House->Is_Ally(House) && trial_unit->Team != this) {\n\t\t\t\tint trial_distance = team_member->Distance(trial_unit);\n\n\t\t\t\tif (distance == -1 || trial_distance < distance) {\n\t\t\t\t\tdistance = trial_distance;\n\t\t\t\t\tclosest = trial_unit;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tScan through all infantry.\n\t\t*/\n\t\tfor (int infantry_index = 0; infantry_index < Infantry.Count(); infantry_index++) {\n\t\t\tFootClass const * trial_infantry = Infantry.Ptr(infantry_index);\n\n\t\t\tif (_Is_It_Breathing(trial_infantry) && trial_infantry->House->Is_Ally(House) && trial_infantry->Team != this) {\n\t\t\t\tint trial_distance = team_member->Distance(trial_infantry);\n\n\t\t\t\tif (distance == -1 || trial_distance < distance) {\n\t\t\t\t\tdistance = trial_distance;\n\t\t\t\t\tclosest = trial_infantry;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tScan through all vessels.\n\t\t*/\n\t\tfor (int vessel_index = 0; vessel_index < Vessels.Count(); vessel_index++) {\n\t\t\tFootClass const * trial_vessel = Vessels.Ptr(vessel_index);\n\n\t\t\tif (_Is_It_Breathing(trial_vessel) && trial_vessel->House->Is_Ally(House) && trial_vessel->Team != this) {\n\t\t\t\tint trial_distance = team_member->Distance(trial_vessel);\n\n\t\t\t\tif (distance == -1 || trial_distance < distance) {\n\t\t\t\t\tdistance = trial_distance;\n\t\t\t\t\tclosest = trial_vessel;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tSet the center location as actually the friendly object that is closest. If there\n\t\t**\tis no friendly object, then don't set any center location at all.\n\t\t*/\n\t\tif (closest) {\n\t\t\tcenter = closest->As_Target();\n\t\t\tclose_member = Member->As_Target();\n\t\t}\n\n\t} else {\n\n\t\tlong\tx = 0;\t\t\t\t\t\t\t\t// Accumulated X coordinate.\n\t\tlong\ty = 0;\t\t\t\t\t\t\t\t// Accumulated Y coordinate.\n\t\tint   dist = 0;\t\t\t\t\t\t\t// Closest recorded distance to team target.\n\t\tint\tquantity = 0;\t\t\t\t\t\t// Number of team members counted.\n\t\tFootClass const * closest = 0;\t\t// Closest member to target.\n\n\t\t/*\n\t\t**\tScan through all team members and accumulate the X and Y component of their\n\t\t**\tlocation. Only team members that are active will be considered. Also keep\n\t\t**\ttrack of the team member that is closest to the team's target.\n\t\t*/\n\t\twhile (team_member != NULL) {\n\t\t\tif (_Is_It_Playing(team_member)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tAccumulate X and Y components of qualified team members.\n\t\t\t\t*/\n\t\t\t\tx += Coord_X(team_member->Coord);\n\t\t\t\ty += Coord_Y(team_member->Coord);\n\t\t\t\tquantity++;\n\n\t\t\t\t/*\n\t\t\t\t**\tKeep a record of the team member that is nearest to the team's\n\t\t\t\t**\ttarget.\n\t\t\t\t*/\n\t\t\t\tint try_dist = team_member->Distance(Target);\n\t\t\t\tif (!dist || try_dist < dist) {\n\t\t\t\t\tdist = try_dist;\n\t\t\t\t\tclosest = team_member;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tteam_member = team_member->Member;\n\t\t}\n\n\t\t/*\n\t\t**\tIf there were any qualifying members, then the team's center point can be\n\t\t**\tdetermined.\n\t\t*/\n\t\tif (quantity) {\n\t\t\tx /= quantity;\n\t\t\ty /= quantity;\n\t\t\tCOORDINATE coord = XY_Coord((int)x, (int)y);\n\t\t\tcenter = ::As_Target(coord);\n\n\n\t\t\t/*\n\t\t\t**\tIf the center location is impassable, then just pick the location of\n\t\t\t** one of the team members.\n\t\t\t*/\n\t\t\tif (!closest->Can_Enter_Cell(As_Cell(center))) {\n//\t\t\t\tif (Class->Origin != -1) {\n//\t\t\t\t\tcenter = ::As_Target(Scen.Waypoint[Class->Origin]);\n//\t\t\t\t} else {\n\t\t\t\t\tcenter = ::As_Target(Coord_Cell(closest->Center_Coord()));\n//\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tRecord the position of the closest member to the team's target and\n\t\t**\tthat will be used as the regroup point.\n\t\t*/\n\t\tif (closest != NULL) {\n\t\t\tclose_member = ::As_Target(Coord_Cell(closest->Center_Coord()));\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamClass::Took_Damage -- Informs the team when the team member takes damage.               *\n *                                                                                             *\n *    This routine is used when a team member takes damage. Usually the team will react in     *\n *    some fashion to the attack. This reaction can range from running away to assigning this  *\n *    new target as the team's target.                                                         *\n *                                                                                             *\n * INPUT:   obj      -- The team member that was damaged.                                      *\n *                                                                                             *\n *          result   -- The severity of the damage taken.                                      *\n *                                                                                             *\n *          source   -- The perpetrator of the damage.                                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/29/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TeamClass::Took_Damage(FootClass * , ResultType result, TechnoClass * source)\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\tif ((result != RESULT_NONE) && (!Class->IsSuicide)) {\n\t\tif (!IsMoving) {\n\n\t\t\t// TCTCTC\n\t\t\t// Should run to a better hiding place or disband into a group of hunting units.\n\n\t\t} else {\n\t\t\t/*\n\t\t\t** Respond to the attack, but not if we're an aircraft or a LST.\n\t\t\t*/\n\t\t\tif (source && !Is_A_Member(source) && Member && Member->What_Am_I() != RTTI_AIRCRAFT && (Member->What_Am_I() != RTTI_VESSEL || *(VesselClass *)((FootClass *)Member) != VESSEL_TRANSPORT)) {\n\t\t\t\tif (Target != source->As_Target()) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDon't change target if the team's target is one that can fire as well. There is\n\t\t\t\t\t**\tno point in endlessly shuffling between targets that have firepower.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Target_Legal(Target)) {\n\t\t\t\t\t\tTechnoClass * techno = As_Techno(Target);\n\n\t\t\t\t\t\tif (techno && ((TechnoTypeClass const &)techno->Class_Of()).PrimaryWeapon != NULL) {\n\t\t\t\t\t\t\tif (techno->In_Range(As_Coord(Zone), 0)) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDon't change target to aggressor if the aggressor cannot normally be attacked.\n\t\t\t\t\t*/\n\t\t\t\t\tif (source->What_Am_I() == RTTI_AIRCRAFT || (source->What_Am_I() == RTTI_VESSEL && (Member->What_Am_I() == RTTI_UNIT || Member->What_Am_I() == RTTI_INFANTRY))) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tTarget = source->As_Target();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamClass::Coordinate_Attack -- Handles coordinating a team attack.                         *\n *                                                                                             *\n *    This function is called when the team knows what it should attack. This routine will     *\n *    give the necessary orders to the members of the team.                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/06/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TeamClass::Coordinate_Attack(void)\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\tif (!Target_Legal(Target)) {\n\t\tTarget = MissionTarget;\n\t}\n\n\t/*\n\t** Check if they're attacking a cell.  If the contents of the cell are\n\t** a bridge or a building/unit/techno, then it's a valid target.  Otherwise,\n\t** the target is invalid. This only applies to non-aircraft teams. An aircraft team\n\t**\tcan \"attack\" an empty cell and this is perfectly ok (paratrooper drop and parabombs\n\t**\tare prime examples).\n\t*/\n\tif (Is_Target_Cell(Target) && Member != NULL && Fetch_A_Leader()->What_Am_I() != RTTI_AIRCRAFT) {\n\t\tCellClass *cellptr = &Map[As_Cell(Target)];\n\t\tTemplateType tt = cellptr->TType;\n\t\tif (cellptr->Cell_Object()) {\n\t\t\tTarget = cellptr->Cell_Object()->As_Target();\n\t\t} else {\n\t\t\tif (tt != TEMPLATE_BRIDGE1   && tt != TEMPLATE_BRIDGE2   &&\n\t\t\t\t tt != TEMPLATE_BRIDGE1H  && tt != TEMPLATE_BRIDGE2H  &&\n\t\t\t\t tt != TEMPLATE_BRIDGE_1A && tt != TEMPLATE_BRIDGE_1B &&\n\t\t\t\t tt != TEMPLATE_BRIDGE_2A && tt != TEMPLATE_BRIDGE_2B &&\n\t\t\t\t tt != TEMPLATE_BRIDGE_3A && tt != TEMPLATE_BRIDGE_3B ) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tFootClass *unit = Member;\n\tTeamMissionClass const * mission = &Class->MissionList[CurrentMission];\n\tif(unit->What_Am_I() != RTTI_UNIT || \n\t\t*(UnitClass *)unit != UNIT_CHRONOTANK || \n\t\tmission->Mission != TMISSION_SPY)\n#endif\n\t\t\t\tTarget = 0;\t\t// invalidize the target so it'll go to next mission.\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!Target_Legal(Target)) {\n\t\tIsNextMission = true;\n\n\t} else {\n\n\t\tTeamMissionClass const * mission = &Class->MissionList[CurrentMission];\n\n\t\tFootClass * unit = Member;\n\t\twhile (unit != NULL) {\n\n\t\t\tCoordinate_Conscript(unit);\n\n\t\t\tif (_Is_It_Playing(unit)) {\n\t\t\t\tif (mission->Mission == TMISSION_SPY && unit->What_Am_I() == RTTI_INFANTRY && *(InfantryClass *)unit == INFANTRY_SPY) {\n\t\t\t\t\tunit->Assign_Mission(MISSION_CAPTURE);\n\t\t\t\t\tunit->Assign_Target(Target);\n\t\t\t\t} else {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif (mission->Mission == TMISSION_SPY && unit->What_Am_I() == RTTI_UNIT && *(UnitClass *)unit == UNIT_CHRONOTANK) {\n\t\t\t\t\tUnitClass *tank = (UnitClass *)unit;\n\t\t\t\t\ttank->Teleport_To(::As_Cell(Target));\n\t\t\t\t\ttank->MoebiusCountDown = ChronoTankDuration * TICKS_PER_MINUTE;\n\t\t\t\t\tScen.Do_BW_Fade();\n\t\t\t\t\tSound_Effect(VOC_CHRONOTANK1, unit->Coord);\n\t\t\t\t\ttank->Assign_Target(TARGET_NONE);\n\t\t\t\t\ttank->Assign_Mission(MISSION_GUARD);\n\t\t\t\t} else {\n#endif\n\t\t\t\t\tif (unit->Mission != MISSION_ATTACK && unit->Mission != MISSION_ENTER && unit->Mission != MISSION_CAPTURE) {\n\t\t\t\t\t\tunit->Transmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t\tunit->Assign_Mission(MISSION_ATTACK);\n\t\t\t\t\t\tunit->Assign_Target(TARGET_NONE);\n\t\t\t\t\t\tunit->Assign_Destination(TARGET_NONE);\n\t\t\t\t\t}\n\t\t\t\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t}\n#endif\n\t\t\t\tif (unit->TarCom != Target) {\n\t\t\t\t\tunit->Assign_Target(Target);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tunit = unit->Member;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamClass::Coordinate_Regroup -- Handles team idling (regrouping).                          *\n *                                                                                             *\n *    This routine is called when the team must delay at its current location. Team members    *\n *    are grouped together by this function. It is called when the team needs to sit and       *\n *    wait.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Has the team completely regrouped?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/06/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TeamClass::Coordinate_Regroup(void)\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\tFootClass * unit   = Member;\n\tbool retval = true;\n\n\t/*\n\t**\tRegroup default logic.\n\t*/\n\twhile (unit != NULL) {\n\n\t\tCoordinate_Conscript(unit);\n\n\t\tif (_Is_It_Playing(unit)) {\n\n\t\t\tif (unit->Distance(Zone) > Rule.StrayDistance && (unit->Mission != MISSION_GUARD_AREA || !Target_Legal(unit->TarCom))) {\n\t\t\t\tif (!Target_Legal(unit->NavCom)) {\n// TCTCTC\n//\t\t\t\tif (!Target_Legal(unit->NavCom) || ::Distance(unit->NavCom, Zone) > Rule.StrayDistance) {\n\t\t\t\t\tunit->Assign_Mission(MISSION_MOVE);\n\t\t\t\t\tunit->Assign_Destination(Zone);\n\n\t\t\t\t\tretval = false;\n\t\t\t\t\tif (!unit->IsFormationMove) {\n\t\t\t\t\t\tunit->Assign_Mission(MISSION_MOVE);\n\t\t\t\t\t\tCELL dest = unit->Adjust_Dest(As_Cell(Zone));\n\t\t\t\t\t\tunit->Assign_Destination(::As_Target(dest));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tretval = true;\t// formations are always considered regrouped.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tThe team is regrouping, so just sit here and wait.\n\t\t\t\t*/\n\t\t\t\tif (unit->Mission != MISSION_GUARD_AREA) {\n\t\t\t\t\tunit->Assign_Mission(MISSION_GUARD);\n\t\t\t\t\tunit->Assign_Destination(TARGET_NONE);\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\tunit = unit->Member;\n\t}\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * TeamClass::Coordinate_Do -- Handles the team performing specified mission.                  *\n *                                                                                             *\n *    This will assign the specified mission to the team. If there are team members that are   *\n *    too far away from the center of the team, then they will be told to move to the team's   *\n *    location.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This only works if the special mission the team members are to perform does not *\n *             require extra parameters. The ATTACK and MOVE missions are particularly bad.    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TeamClass::Coordinate_Do(void)\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\tFootClass * unit = Member;\n\tMissionType do_mission = Class->MissionList[CurrentMission].Data.Mission;\n\n\t/*\n\t**\tFor each unit either head it back to the team center or give it the main\n\t**\tteam mission order as appropriate.\n\t*/\n\twhile (unit != NULL) {\n\n\t\tCoordinate_Conscript(unit);\n\n\t\tif (_Is_It_Playing(unit)) {\n\n\t\t\tif (!Target_Legal(unit->TarCom) && !Target_Legal(unit->NavCom) && unit->Distance(Zone) > Rule.StrayDistance * 2) {\n\n\t\t\t\t/*\n\t\t\t\t**\tOnly if the unit isn't already heading to regroup with the team, will it\n\t\t\t\t**\tbe given orders to do so.\n\t\t\t\t*/\n\t\t\t\tunit->Assign_Mission(MISSION_MOVE);\n\t\t\t\tunit->Assign_Destination(Zone);\n\t\t\t\tunit->Assign_Mission(MISSION_MOVE);\n\t\t\t\tCELL dest = unit->Adjust_Dest(As_Cell(Zone));\n\t\t\t\tunit->Assign_Destination(::As_Target(dest));\n\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tThe team is regrouping, so just sit here and wait.\n\t\t\t\t*/\n\t\t\t\tif (!Target_Legal(unit->TarCom) && !Target_Legal(unit->NavCom) && unit->Mission != do_mission) {\n\t\t\t\t\tunit->ArchiveTarget = TARGET_NONE;\n\t\t\t\t\tunit->Assign_Mission(do_mission);\n\t\t\t\t\tunit->Assign_Target(TARGET_NONE);\n\t\t\t\t\tunit->Assign_Destination(TARGET_NONE);\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\tunit = unit->Member;\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamClass::Coordinate_Move -- Handles team movement coordination.                           *\n *                                                                                             *\n *    This routine is called when the team must move to a new location. Movement and grouping  *\n *    commands associated with this task are initiated here.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/06/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TeamClass::Coordinate_Move(void)\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\tFootClass * unit = Member;\n\tbool finished = true;\n\tbool found = false;\n\n\tif (!Target_Legal(Target)) {\n\t\tTarget = MissionTarget;\n\t}\n\n\tif (Target_Legal(Target)) {\n\n\t\tif (!Lagging_Units()) {\n\n\t\t\twhile (unit != NULL) {\n\n\t\t\t\t/*\n\t\t\t\t**\tTell the unit, if necessary, that it should regroup\n\t\t\t\t**\twith the main team location. If the unit is regrouping, then\n\t\t\t\t**\tthe team should continue NOT qualify as fully reaching the desired\n\t\t\t\t**\tlocation.\n\t\t\t\t*/\n\t\t\t\tif (Coordinate_Conscript(unit)) {\n\t\t\t\t\tfinished = false;\n\t\t\t\t}\n\n\t\t\t\tif (unit->Mission == MISSION_UNLOAD || unit->MissionQueue == MISSION_UNLOAD) {\n\t\t\t\t\tfinished = false;\n\t\t\t\t}\n\n\t\t\t\tif (_Is_It_Playing(unit) && unit->Mission != MISSION_UNLOAD && unit->MissionQueue != MISSION_UNLOAD) {\n\t\t\t\t\tint stray = Rule.StrayDistance;\n\t\t\t\t\tif (unit->What_Am_I() == RTTI_AIRCRAFT) {\n\t\t\t\t\t\tstray *= 3;\n\t\t\t\t\t}\n\t\t\t\t\tif (unit->What_Am_I() == RTTI_INFANTRY && ((InfantryClass const *)unit)->Class->IsDog) {\n\t\t\t\t\t\tif (Target_Legal(unit->TarCom)) stray = unit->Techno_Type_Class()->ThreatRange;\n\t\t\t\t\t\tif (Target_Legal(unit->TarCom) && unit->Distance(unit->TarCom) > stray) {\n\t\t\t\t\t\t\tunit->Assign_Target(TARGET_NONE);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfound = true;\n\n\t\t\t\t\tint dist = unit->Distance(Target);\n\t\t\t\t\tif (unit->IsFormationMove) {\n\t\t\t\t\t\tif (::As_Target(Coord_Cell(unit->Coord)) != unit->NavCom) {\n\t\t\t\t\t\t\tdist = Rule.StrayDistance + 1;\t// formation moves must be exact.\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (dist > stray ||\n\t\t\t\t\t\t(unit->What_Am_I() == RTTI_AIRCRAFT &&\n//\t\t\t\t\t\t(unit->In_Which_Layer() == LAYER_TOP &&\n\t\t\t\t\t\t((AircraftClass *)unit)->Height > 0 &&\n\t\t\t\t\t\tCoord_Cell(unit->Center_Coord()) != As_Cell(Target) &&\n\t\t\t\t\t\t!((AircraftClass *)unit)->Class->IsFixedWing &&\n\t\t\t\t\t\tClass->MissionList[CurrentMission+1].Mission != TMISSION_MOVE)) {\n\n\t\t\t\t\t\tbool wasform = false;\n\n\n\t\t\t\t\t\tif (unit->Mission != MISSION_MOVE) {\n\t\t\t\t\t\t\tunit->Assign_Mission(MISSION_MOVE);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (unit->NavCom != Target) {\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Check if this destination should be adjusted for\n\t\t\t\t\t\t\t** a formation move\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Is_Target_Cell(Target) && unit->IsFormationMove) {\n\t\t\t\t\t\t\t\tCELL newcell = unit->Adjust_Dest(As_Cell(Target));\n\t\t\t\t\t\t\t\tif (Coord_Cell(unit->Coord) != newcell) {\n\t\t\t\t\t\t\t\t\tunit->Assign_Destination(::As_Target(newcell));\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tunit->Assign_Mission(MISSION_GUARD);\n\t\t\t\t\t\t\t\t\tunit->Assign_Destination(TARGET_NONE);\n\t\t\t\t\t\t\t\t\twasform = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tunit->Assign_Destination(Target);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!wasform) {\n\t\t\t\t\t\t\tfinished = false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (unit->Mission == MISSION_MOVE && (!Target_Legal(unit->NavCom) || Distance(unit->NavCom) < CELL_LEPTON_W)) {\n\t\t\t\t\t\t\tunit->Assign_Destination(TARGET_NONE);\n\t\t\t\t\t\t\tunit->Enter_Idle_Mode();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf any member still has a valid NavCom then consider this\n\t\t\t\t\t**\tmovement mission to still be in progress. This will ensure\n\t\t\t\t\t**\tthat the members come to a complete stop before the next\n\t\t\t\t\t**\tmission commences. Without this, the team will prematurely\n\t\t\t\t\t**\tstart on the next mission even when all members aren't yet\n\t\t\t\t\t**\tin their proper spot.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Target_Legal(unit->NavCom)) {\n\t\t\t\t\t\tfinished = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tunit = unit->Member;\n\t\t\t}\n\t\t} else {\n\t\t\tfinished = false;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there are no initiated members to this team, then it certainly\n\t**\tcould not have managed to move to the target destination.\n\t*/\n\tif (!found) {\n\t\tfinished = false;\n\t}\n\n\t/*\n\t**\tIf all the team members are close enough to the desired destination, then\n\t**\tmove to the next mission.\n\t*/\n\tif (finished && IsMoving) {\n\t\tIsNextMission = true;\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamClass::Lagging_Units -- Finds and orders any lagging units to catch up.                 *\n *                                                                                             *\n *    This routine will examine the team and find any lagging units. The units are then        *\n *    ordered to catch up to the team member that is closest to the team's destination. This   *\n *    routine will not do anything unless lagging members are suspected. This fact is          *\n *    indicated by setting the IsLagging flag. The flag is set by some outside agent.          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure to set IsLagging for the team if a lagging member is suspected.         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/01/1995 PWG : Created.                                                                 *\n *   04/11/1996 JLB : Modified.                                                                *\n *=============================================================================================*/\nbool TeamClass::Lagging_Units(void)\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\tFootClass * unit = Member;\n\tbool lag = false;\n\n\t//BG: HACK - if it's in a formation move, then disable the check for\n\t// VG added NULL check \t laggers, 'cause they're all moving simultaneously.\n\tif (unit != NULL && unit->IsFormationMove) IsLagging = false;\n\n\t/*\n\t** If the IsLagging bit is not set, then obviously there are no lagging\n\t** units.\n\t*/\n\tif (!IsLagging) return(false);\n\n\t/*\n\t**\tScan through all of the units, searching for units who are having\n\t** trouble keeping up with the pack.\n\t*/\n\twhile (unit != NULL) {\n\n\t\tif (_Is_It_Playing(unit)) {\n\t\t\tint stray = Rule.StrayDistance;\n\t\t\tif (unit->What_Am_I() ==  RTTI_AIRCRAFT) {\n\t\t\t\tstray *= 3;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If we find a unit who has fallen too far away from the center of\n\t\t\t** the pack, then we need to order that unit to catch up with the\n\t\t\t** first unit.\n\t\t\t*/\n\t\t\tif (unit->Distance(ClosestMember) > stray) {\n// TCTCTC\n\t\t\t\tif (!Target_Legal(unit->NavCom)) {\n//\t\t\t\tif (!Target_Legal(unit->NavCom) || ::Distance(unit->NavCom, ClosestMember) > Rule.StrayDistance) {\n\t\t\t\t\tunit->Assign_Mission(MISSION_MOVE);\n\t\t\t\t\tunit->Assign_Destination(ClosestMember);\n\t\t\t\t}\n\t\t\t\tlag = true;\n\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t** We need to order all of the other units to hold their\n\t\t\t\t** position until all lagging units catch up.\n\t\t\t\t*/\n\t\t\t\tif (unit->Mission != MISSION_GUARD) {\n\t\t\t\t\tunit->Assign_Mission(MISSION_GUARD);\n\t\t\t\t\tunit->Assign_Destination(TARGET_NONE);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tunit = unit->Member;\n\t}\n\n\t/*\n\t** Once we have handled the loop we know whether there are any lagging\n\t** units or not.\n\t*/\n\tIsLagging = lag;\n\treturn(lag);\n}\n\n\n/***********************************************************************************************\n * TeamClass::TMission_Unload -- Tells the team to unload passengers now.                      *\n *                                                                                             *\n *    This routine tells all transport vehicles to unload passengers now.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/14/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TeamClass::TMission_Unload(void)\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\tFootClass * unit = Member;\n\tbool finished = true;\n\n\twhile (unit != NULL) {\n\n\t\tCoordinate_Conscript(unit);\n\n\t\tif (_Is_It_Playing(unit)) {\n\t\t\t/*\n\t\t\t** Only assign the mission if the unit is carrying a passenger, OR\n\t\t\t** if the unit is a minelayer, with mines in it, and the cell it's\n\t\t\t** on doesn't have a building (read: mine) in it already.\n\t\t\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t/* Also, allow unload if it's a MAD Tank. */\n\t\t\tif (unit->Is_Something_Attached() || (unit->What_Am_I() == RTTI_UNIT && *(UnitClass *)unit == UNIT_MINELAYER && unit->Ammo) || (unit->What_Am_I() == RTTI_UNIT && *(UnitClass *)unit == UNIT_MAD )) {\n#else\n\t\t\tif (unit->Is_Something_Attached() || (unit->What_Am_I() == RTTI_UNIT && *(UnitClass *)unit == UNIT_MINELAYER && unit->Ammo) ) {\n#endif\n\t\t\t\tif (unit->Is_Something_Attached()) {\n\t\t\t\t\t/*\n\t\t\t\t\t** Passenger-carrying vehicles will always return false until\n\t\t\t\t\t** they've unloaded all passengers.\n\t\t\t\t\t*/\n\t\t\t\t\tfinished = false;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tThe check for a building is located here because the mine layer may have\n\t\t\t\t**\talready unloaded the mine but is still in the process of retracting\n\t\t\t\t**\tthe mine layer. During this time, it should not be considered to have\n\t\t\t\t**\tfinished its unload mission.\n\t\t\t\t*/\n\t\t\t\tif (Map[unit->Center_Coord()].Cell_Building() == NULL && unit->Mission != MISSION_UNLOAD) {\n\t\t\t\t\tunit->Assign_Destination(TARGET_NONE);\n\t\t\t\t\tunit->Assign_Target(TARGET_NONE);\n\t\t\t\t\tunit->Assign_Mission(MISSION_UNLOAD);\n\t\t\t\t\tfinished = false;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tA loaner transport should vacate the map when all transported objects\n\t\t\t\t**\thave been offloaded.\n\t\t\t\t*/\n\t\t\t\tif (unit->IsALoaner) {\n\t\t\t\t\tRemove(unit);\n\t\t\t\t\tunit->Assign_Mission(MISSION_RETREAT);\n\t\t\t\t\tunit->Commence();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tunit = unit->Member;\n\t}\n\n\tif (finished) {\n\t\tIsNextMission = true;\n\t}\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * TeamClass::TMission_Load -- Tells the team to load onto the transport now.                  *\n *                                                                                             *\n *    This routine tells all non-transport units in the team to climb onto the transport in the*\n *    team.  Note the transport must be a member of this team.                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/28/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nint TeamClass::TMission_Load(void)\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\tFootClass * unit = Member;\n\tFootClass * trans = 0;\n\n\t/*\n\t** First locate the transport in the team, if there is one.  There should\n\t** only be one transport in the team.\n\t*/\n\twhile(unit != NULL && trans == NULL) {\n\t\tif (unit->Techno_Type_Class()->Max_Passengers() > 0) {\n\t\t\ttrans = unit;\n\t\t\tbreak;\n\t\t}\n\t\tunit = unit->Member;\n\t}\n\n\t/*\n\t**\tIn the case of no transport available, then consider the mission complete\n\t**\tsince it can never complete otherwise.\n\t*/\n\tif (trans == NULL) {\n\t\tIsNextMission = true;\n\t\treturn(1);\n\t}\n\n\t/*\n\t**\tIf the transport is already in radio contact, then this means that\n\t**\tit is in the process of loading. During this time, don't bother to assign\n\t**\tthe enter mission to the other team members.\n\t*/\n\tif (trans->In_Radio_Contact()) {\n\t\treturn(1);\n\t}\n\n\t/*\n\t**\tFind a member to assign the entry logic for.\n\t*/\n\tbool finished = true;\n\tunit = Member;\t// re-point at the first member of the team again.\n\twhile (unit != NULL && Total > 1) {\n\t\tCoordinate_Conscript(unit);\n\n\t\t/*\n\t\t** Only assign the mission if the unit is not the transport.\n\t\t*/\n\t\tif (_Is_It_Playing(unit) && unit != trans) {\n\t\t\tif (unit->Mission != MISSION_ENTER) {\n\t\t\t\tunit->Assign_Mission(MISSION_ENTER);\n\t\t\t\tunit->Assign_Target(TARGET_NONE);\n\t\t\t\tunit->Assign_Destination(trans->As_Target());\n\t\t\t\tfinished = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfinished = false;\n\t\t}\n\n\t\tunit = unit->Member;\n\t}\n\n\tif (finished) {\n\t\tIsNextMission = true;\n\t}\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * TeamClass::Coordinate_Conscript -- Gives orders to new recruit.                             *\n *                                                                                             *\n *    This routine will give the movement orders to the conscript so that it will group        *\n *    with the other members of the team.                                                      *\n *                                                                                             *\n * INPUT:   unit  -- Pointer to the conscript unit.                                            *\n *                                                                                             *\n * OUTPUT:  bool; Is the unit still scurrying to reach the team's current location?            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/06/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TeamClass::Coordinate_Conscript(FootClass * unit)\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\tif (_Is_It_Breathing(unit) && !unit->IsInitiated) {\n\t\tif (unit->Distance(Zone) > Rule.StrayDistance) {\n\t\t\tif (!Target_Legal(unit->NavCom)) {\n\t\t\t\tunit->Assign_Mission(MISSION_MOVE);\n\t\t\t\tunit->Assign_Target(TARGET_NONE);\n\t\t\t\tunit->IsFormationMove = false;\n\t\t\t\tunit->Assign_Destination(Zone);\n\t\t\t}\n\t\t\treturn(true);\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tThis unit has gotten close enough to the team center so that it is\n\t\t\t**\tnow considered initiated. An initiated unit is considered when calculating\n\t\t\t**\tthe center of the team.\n\t\t\t*/\n\t\t\tunit->IsInitiated = true;\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***************************************************************************\n * TeamClass::Is_A_Member -- Tests if a unit is a member of a team         *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1995 PWG : Created.                                             *\n *=========================================================================*/\nbool TeamClass::Is_A_Member(void const * who) const\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\tFootClass * unit = Member;\n\twhile (unit != NULL) {\n\t\tif (unit == who) {\n\t\t\treturn(true);\n\t\t}\n\t\tunit = unit->Member;\n\t}\n\treturn(false);\n}\n\n\n/***************************************************************************\n * TeamClass::Suspend_Teams -- Suspends activity for low priority teams    *\n *                                                                         *\n * INPUT:\tint priority - determines what is considered low priority.     *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/19/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid TeamClass::Suspend_Teams(int priority, HouseClass const * house)\n{\n\tfor (int index = 0; index < Teams.Count(); index++) {\n\t\tTeamClass * team = Teams.Ptr(index);\n\n\t\t/*\n\t\t**\tIf a team is below the \"survival priority level\", then it gets\n\t\t**\tdestroyed. The team members are then free to be reassigned.\n\t\t*/\n\t\tif (team != NULL && team->House == house && team->Class->RecruitPriority < priority) {\n\t\t\tFootClass * unit = team->Member;\n\t\t\twhile (team->Member) {\n\t\t\t\tteam->Remove(team->Member);\n\t\t\t}\n\t\t\tteam->IsAltered = team->JustAltered = true;\n\t\t\tteam->SuspendTimer = Rule.SuspendDelay * TICKS_PER_MINUTE;\n\t\t\tteam->Suspended = true;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamClass::Is_Leaving_Map -- Checks if team is in process of leaving the map                *\n *                                                                                             *\n *    This routine is used to see if the team is leaving the map. A team that is leaving the   *\n *    map gives implicit permission for its members to leave the map.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is this team trying to leave the map?                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TeamClass::Is_Leaving_Map(void) const\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\tif (IsMoving && CurrentMission >= 0) {\n\t\tTeamMissionClass const * mission = &Class->MissionList[CurrentMission];\n\n\t\tif (mission->Mission == TMISSION_MOVE && !Map.In_Radar(Scen.Waypoint[mission->Data.Value])) {\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TeamClass::Has_Entered_Map -- Determines if the entire team has entered the map.            *\n *                                                                                             *\n *    This will examine all team members and only if all of them have entered the map, will    *\n *    it return true. This routine is used to recognize the case of a team that has been       *\n *    generated off map and one that has already entered game play. This knowledge can lead    *\n *    to more intelligent behavior regarding team and member disposition.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Have all members of this team entered the map?                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TeamClass::Has_Entered_Map(void) const\n{\n\tbool ok = true;\n\tFootClass * foot = Member;\n\twhile (foot != NULL) {\n\t\tif (!foot->IsLocked) {\n\t\t\tok = false;\n\t\t\tbreak;\n\t\t}\n\t\tfoot = (FootClass *)(ObjectClass *)(foot->Next);\n\t}\n\treturn(ok);\n}\n\n\n/***********************************************************************************************\n * TeamClass::Scan_Limit -- Force all members of the team to have limited scan range.          *\n *                                                                                             *\n *    This routine is used when one of the team members cannot get within range of the team's  *\n *    target. In such a case, the team must be assigned a new target and all members of that   *\n *    team must recognize that a restricted target scan is required. This is done by clearing  *\n *    out the team's target so that it will be forced to search for a new one. Also, since the *\n *    members are flagged for short scanning, whichever team member is picked to scan for a    *\n *    target will scan for one that is within range.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The team will reassign its target as a result of this routine.                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TeamClass::Scan_Limit(void)\n{\n\tAssign_Mission_Target(TARGET_NONE);\n\tFootClass * foot = Member;\n\twhile (foot != NULL) {\n\t\tfoot->Assign_Target(TARGET_NONE);\n\t\tfoot->IsScanLimited = true;\n\t\tfoot = foot->Member;\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamClass::TMission_Formation -- Process team formation change command.                     *\n *                                                                                             *\n *    This routine will change the team's formation to that specified in the team command      *\n *    parameter. It is presumed that the team will have further movement orders so that the    *\n *    formation can serve some purpose. Merely changing the formation doesn't alter the        *\n *    member's location. The team must be given a movement order before team member            *\n *    repositioning will occur.                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the time to delay before further team actions should occur.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TeamClass::TMission_Formation(void)\n{\n\tFootClass * member = Member;\n\tTeamMissionClass const * mission = &Class->MissionList[CurrentMission];\n\tFormation = mission->Data.Formation;\n\tint group = ID + 10;\n\tint xdir = 0;\n\tint ydir = 0;\n\tbool evenodd = 1;\n\n\t/*\n\t**\tAssign appropriate formation offsets for each of the members\n\t**\tof this team.\n\t*/\n\tswitch (Formation) {\n\t\tcase FORMATION_NONE:\n\t\t\twhile (member != NULL) {\n\t\t\t\tmember->Group = 0xFF;\n\t\t\t\tmember->XFormOffset = 0x80000000;\n\t\t\t\tmember->YFormOffset = 0x80000000;\n\t\t\t\tmember->IsFormationMove = false;\n\t\t\t\tmember = member->Member;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FORMATION_TIGHT:\n\t\t\twhile (member != NULL) {\n\t\t\t\tmember->Group = group;\n\t\t\t\tmember->XFormOffset = 0;\n\t\t\t\tmember->YFormOffset = 0;\n\t\t\t\tmember->IsFormationMove = true;\n\t\t\t\tmember = member->Member;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FORMATION_LOOSE:\n\t\t\tbreak;\n\t\tcase FORMATION_WEDGE_N:\n\t\t\tydir = -(Total / 2);\n\t\t\txdir = 0;\n\t\t\twhile (member != NULL) {\n\t\t\t\tmember->Group = group;\n\t\t\t\tmember->XFormOffset = xdir;\n\t\t\t\tmember->YFormOffset = ydir;\n\t\t\t\tmember->IsFormationMove = true;\n\t\t\t\txdir = -xdir;\n\t\t\t\tevenodd ^= 1;\n\t\t\t\tif (!evenodd) {\n\t\t\t\t\txdir -= 2;\n\t\t\t\t\tydir += 2;\n\t\t\t\t}\n\t\t\t\tmember = member->Member;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FORMATION_WEDGE_E:\n\t\t\txdir = (Total / 2);\n\t\t\tydir = 0;\n\t\t\twhile (member != NULL) {\n\t\t\t\tmember->Group = group;\n\t\t\t\tmember->XFormOffset = xdir;\n\t\t\t\tmember->YFormOffset = ydir;\n\t\t\t\tmember->IsFormationMove = true;\n\t\t\t\tydir = -ydir;\n\t\t\t\tevenodd ^= 1;\n\t\t\t\tif (!evenodd) {\n\t\t\t\t\txdir -= 2;\n\t\t\t\t\tydir -= 2;\n\t\t\t\t}\n\t\t\t\tmember = member->Member;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FORMATION_WEDGE_S:\n\t\t\tydir = (Total / 2);\n\t\t\txdir = 0;\n\t\t\twhile (member != NULL) {\n\t\t\t\tmember->Group = group;\n\t\t\t\tmember->XFormOffset = xdir;\n\t\t\t\tmember->YFormOffset = ydir;\n\t\t\t\tmember->IsFormationMove = true;\n\t\t\t\txdir = -xdir;\n\t\t\t\tevenodd ^= 1;\n\t\t\t\tif (!evenodd) {\n\t\t\t\t\txdir -= 2;\n\t\t\t\t\tydir -= 2;\n\t\t\t\t}\n\t\t\t\tmember = member->Member;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FORMATION_WEDGE_W:\n\t\t\txdir = -(Total / 2);\n\t\t\tydir = 0;\n\t\t\twhile (member != NULL) {\n\t\t\t\tmember->Group = group;\n\t\t\t\tmember->XFormOffset = xdir;\n\t\t\t\tmember->YFormOffset = ydir;\n\t\t\t\tmember->IsFormationMove = true;\n\t\t\t\tydir = -ydir;\n\t\t\t\tevenodd ^= 1;\n\t\t\t\tif (!evenodd) {\n\t\t\t\t\txdir += 2;\n\t\t\t\t\tydir -= 2;\n\t\t\t\t}\n\t\t\t\tmember = member->Member;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FORMATION_LINE_NS:\n\t\t\tydir = -(Total/2);\n\t\t\twhile (member != NULL) {\n\t\t\t\tmember->Group = group;\n\t\t\t\tmember->XFormOffset = 0;\n\t\t\t\tmember->YFormOffset = ydir;\n\t\t\t\tmember->IsFormationMove = true;\n\t\t\t\tmember = member->Member;\n\t\t\t\tydir += 2;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FORMATION_LINE_EW:\n\t\t\txdir = -(Total/2);\n\t\t\twhile (member != NULL) {\n\t\t\t\tmember->Group = group;\n\t\t\t\tmember->XFormOffset = xdir;\n\t\t\t\tmember->YFormOffset = 0;\n\t\t\t\tmember->IsFormationMove = true;\n\t\t\t\tmember = member->Member;\n\t\t\t\txdir += 2;\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n\t/*\n\t** Now calculate the group's movement type and speed\n\t*/\n\tif (Formation != FORMATION_NONE) {\n\t\tTeamSpeed[group] = SPEED_WHEEL;\n\t\tTeamMaxSpeed[group] = MPH_LIGHT_SPEED;\n\t\tmember = Member;\n\t\twhile (member != NULL) {\n\t\t\tRTTIType mytype = member->What_Am_I();\n\t\t\tSpeedType\tmemspeed;\n\t\t\tMPHType\t\tmemmax;\n\t\t\tbool\t\t\tspeedcheck = false;\n\n\t\t\tif (mytype == RTTI_INFANTRY) {\n\t\t\t\tmemspeed = SPEED_FOOT;\n\t\t\t\tmemmax = ((InfantryClass *)member)->Class->MaxSpeed;\n\t\t\t\tspeedcheck = true;\n\t\t\t}\n\t\t\tif (mytype == RTTI_UNIT) {\n\t\t\t\tmemspeed = ((UnitClass *)member)->Class->Speed;\n\t\t\t\tmemmax = ((UnitClass *)member)->Class->MaxSpeed;\n\t\t\t\tspeedcheck = true;\n\t\t\t}\n\n\t\t\tif (mytype == RTTI_VESSEL) {\n\t\t\t\tmemspeed = ((VesselClass *)member)->Class->Speed;\n\t\t\t\tmemmax = ((VesselClass *)member)->Class->MaxSpeed;\n\t\t\t\tspeedcheck = true;\n\t\t\t}\n\n\t\t\tif (speedcheck) {\n\t\t\t\tif (memmax < TeamMaxSpeed[group]) {\n\t\t\t\t\tTeamMaxSpeed[group] = memmax;\n\t\t\t\t\tTeamSpeed[group] = memspeed;\n\t\t\t\t}\n\t\t\t}\n\t\t\tmember = member->Member;\n\t\t}\n\n\t\t/*\n\t\t** Now that it's all calculated, assign the movement type and\n\t\t** speed to every member of the team.\n\t\t*/\n\t\tmember = Member;\n\t\twhile (member != NULL) {\n\t\t\tmember->FormationSpeed = TeamSpeed[group];\n\t\t\tmember->FormationMaxSpeed = TeamMaxSpeed[group];\n\t\t\tif (member->What_Am_I() == RTTI_INFANTRY) {\n\t\t\t\tmember->FormationSpeed = SPEED_FOOT;\n\t\t\t\tmember->FormationMaxSpeed = MPH_SLOW_ISH;\n\t\t\t}\n\t\t\tmember = member->Member;\n\t\t}\n\t}\n\n\t// Advance past the formation-setting command.\n\tIsNextMission = true;\n\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * TeamClass::TMission_Attack -- Perform the team attack mission command.                      *\n *                                                                                             *\n *    This will tell the team to attack the quarry specified in the team command. If the team  *\n *    already has a target, this it is presumed that this target take precidence and it won't  *\n *    be changed.                                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before the next team logic operation should occur.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TeamClass::TMission_Attack(void)\n{\n\tif (!Target_Legal(MissionTarget) && Member != NULL) {\n\t\tTeamMissionClass const * mission = &Class->MissionList[CurrentMission];\n\n\t\t/*\n\t\t**\tPick a team leader that has a weapon. Only in the case of no\n\t\t**\tteam members having any weapons, will a member without a weapon\n\t\t**\tbe chosen.\n\t\t*/\n\t\tFootClass const * candidate = Fetch_A_Leader();\n\n\t\t/*\n\t\t**\tHave the team leader pick what the next team target will be.\n\t\t*/\n\t\tswitch (mission->Data.Quarry) {\n\t\t\tcase QUARRY_ANYTHING:\n\t\t\t\tAssign_Mission_Target(candidate->Greatest_Threat(THREAT_NORMAL));\n\t\t\t\tbreak;\n\n\t\t\tcase QUARRY_BUILDINGS:\n\t\t\t\tAssign_Mission_Target(candidate->Greatest_Threat(THREAT_BUILDINGS));\n\t\t\t\tbreak;\n\n\t\t\tcase QUARRY_HARVESTERS:\n\t\t\t\tAssign_Mission_Target(candidate->Greatest_Threat(THREAT_TIBERIUM));\n\t\t\t\tbreak;\n\n\t\t\tcase QUARRY_INFANTRY:\n\t\t\t\tAssign_Mission_Target(candidate->Greatest_Threat(THREAT_INFANTRY));\n\t\t\t\tbreak;\n\n\t\t\tcase QUARRY_VEHICLES:\n\t\t\t\tAssign_Mission_Target(candidate->Greatest_Threat(THREAT_VEHICLES));\n\t\t\t\tbreak;\n\n\t\t\tcase QUARRY_FACTORIES:\n\t\t\t\tAssign_Mission_Target(candidate->Greatest_Threat(THREAT_FACTORIES));\n\t\t\t\tbreak;\n\n\t\t\tcase QUARRY_DEFENSE:\n\t\t\t\tAssign_Mission_Target(candidate->Greatest_Threat(THREAT_BASE_DEFENSE));\n\t\t\t\tbreak;\n\n\t\t\tcase QUARRY_THREAT:\n\t\t\t\tAssign_Mission_Target(candidate->Greatest_Threat(THREAT_NORMAL));\n\t\t\t\tbreak;\n\n\t\t\tcase QUARRY_POWER:\n\t\t\t\tAssign_Mission_Target(candidate->Greatest_Threat(THREAT_POWER));\n\t\t\t\tbreak;\n\n\t\t\tcase QUARRY_FAKES:\n\t\t\t\tAssign_Mission_Target(candidate->Greatest_Threat(THREAT_FAKES));\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\tif (!Target_Legal(MissionTarget)) IsNextMission = true;\n\t}\n\tCoordinate_Attack();\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * TeamClass::TMission_Spy -- Perform the team spy mission.                                    *\n *                                                                                             *\n *    This will give the team a spy mission to the location specified. It is presumed that     *\n *    the location of the team mission actually resides under the building to be spied. If     *\n *    no building exists at the location, then the spy operation is presumed to be a mere      *\n *    move operation.                                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before the next team logic operation should occur.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TeamClass::TMission_Spy(void)\n{\n\tif (Is_Target_Cell(MissionTarget))\n\t\t{\n\t\tCELL cell = ::As_Cell(MissionTarget);\n\t\tCellClass * cellptr = &Map[cell];\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tObjectClass * bldg = cellptr->Cell_Building();\n#else\n\t\tObjectClass * bldg = cellptr->Cell_Object();\n#endif\n\t\tif (bldg != NULL)\n\t\t\t{\n\t\t\tAssign_Mission_Target(bldg->As_Target());\n\t\t\tCoordinate_Attack();\n\t\t\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\telse\n\t\t\t{\n\t\t\tFootClass *member = Member;\n\t\t\tif(member->What_Am_I() == RTTI_UNIT && *(UnitClass *)member == UNIT_CHRONOTANK)\n\t\t\t\t{\n\t\t\t\tbool finished = true;\n\t\t\t\twhile (member)\n\t\t\t\t\t{\n\t\t\t\t\tif ( !((UnitClass *)member)->MoebiusCountDown) finished = false;\n\t\t\t\t\tmember = member->Member;\n\t\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (!finished)\n\t\t\t\t\t{\n\t\t\t\t\tCoordinate_Attack();\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tAssign_Mission_Target(TARGET_NONE);\n\t\t\t\t\tIsNextMission = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n#endif\n\t\t}\n\telse\n\t\t{\n\t\tif (!Target_Legal(MissionTarget))\n\t\t\t{\n\t\t\tAssign_Mission_Target(TARGET_NONE);\n\t\t\tIsNextMission = true;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tCoordinate_Attack();\n\t\t\t}\n\t\t}\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * TeamClass::TMission_Follow -- Perform the \"follow friendlies\" team command.                 *\n *                                                                                             *\n *    This will cause the team members to search out and follow the nearest friendly object.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before the next team logic operation should be performed.   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TeamClass::TMission_Follow(void)\n{\n\tCalc_Center(Zone, ClosestMember);\n\tTarget = Zone;\n\tCoordinate_Move();\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * TeamClass::TMission_Loop -- Causes the team mission processor to jump to new location.      *\n *                                                                                             *\n *    This is equivalent to a jump or goto command. It will alter the team command processing  *\n *    such that it will continue processing at the command number specified.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before the next team logic operation should be performed.   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TeamClass::TMission_Loop(void)\n{\n\tTeamMissionClass const * mission = &Class->MissionList[CurrentMission];\n\tCurrentMission = mission->Data.Value-1;\n\tIsNextMission = true;\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * TeamClass::TMission_Invulnerable -- Makes the entire team invulnerable for a period of time *\n *                                                                                             *\n *    This is a team mission that simulates the Iron Curtain device. It will make all team     *\n *    members invlunerable for a temporary period of time.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the time delay before the next team logic operation should occur.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TeamClass::TMission_Invulnerable(void)\n{\n\tFootClass * foot = Member;\n\twhile (foot != NULL) {\n\t\tfoot->IronCurtainCountDown = Rule.IronCurtainDuration * TICKS_PER_MINUTE;\n\t\tfoot->Mark(MARK_CHANGE);\n\t\tfoot = foot->Member;\n\t}\n\tIsNextMission = true;\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * TeamClass::TMission_Set_Global -- Performs a set global flag operation.                     *\n *                                                                                             *\n *    This routine is used by the team to set a global variable but otherwise perform no       *\n *    visible effect on the team. By using this routine, sophisticated trigger dependencies    *\n *    can be implemented.                                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before the next team logic operation should occur.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TeamClass::TMission_Set_Global(void)\n{\n\tTeamMissionClass const * mission = &Class->MissionList[CurrentMission];\n\tScen.Set_Global_To(mission->Data.Value, true);\n\tIsNextMission = true;\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * TeamClass::TMision_Patrol -- Handles patrolling from one location to another.               *\n *                                                                                             *\n *    A patrolling team will move to the designated waypoint, but along the way it will        *\n *    periodically scan for nearby enemies. If an enemy is found, the patrol mission turns     *\n *    into an attack mission until the target is destroyed -- after which it resumes its       *\n *    patrol duties.                                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before the next call to this routine is needed.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TeamClass::TMission_Patrol(void)\n{\n\t/*\n\t**\tReassign the movement destination if the target has been prematurely\n\t**\tcleared (probably because the object has been destroyed).\n\t*/\n\tif (!Target_Legal(Target)) {\n\t\tTeamMissionClass const * mission = &Class->MissionList[CurrentMission];\n\t\tif ((unsigned)mission->Data.Value < WAYPT_COUNT) {\n\t\t\tAssign_Mission_Target(::As_Target(Scen.Waypoint[mission->Data.Value]));\n\t\t}\n\t}\n\n\t/*\n\t**\tEvery so often, scan for a nearby enemy.\n\t*/\n\tif (Frame % (Rule.PatrolTime * TICKS_PER_MINUTE) == 0) {\n\t\tFootClass * leader = Fetch_A_Leader();\n\t\tif (leader != NULL) {\n\t\t\tTARGET target = leader->Greatest_Threat(THREAT_NORMAL|THREAT_RANGE);\n\n\t\t\tif (Target_Legal(target)) {\n\t\t\t\tAssign_Mission_Target(target);\n\t\t\t} else {\n\t\t\t\tAssign_Mission_Target(TARGET_NONE);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the mission target looks like it should be attacked, then do so, otherwise\n\t**\ttreat it as a movement destination.\n\t*/\n\tif (Is_Target_Object(Target)) {\n\t\tCoordinate_Attack();\n\t} else {\n\t\tCoordinate_Move();\n\t}\n\treturn(1);\n}\n\n\nint TeamClass::TMission_Deploy(void)\n{\n\tassert(IsActive);\n\tassert(Teams.ID(this) == ID);\n\n\tFootClass * unit = Member;\n\tbool finished = true;\n\n\twhile (unit != NULL) {\n\n\t\tCoordinate_Conscript(unit);\n\n\t\tif (_Is_It_Playing(unit)) {\n\n\t\t\tif (unit->What_Am_I() == RTTI_UNIT && *(UnitClass *)unit == UNIT_MCV) {\n\t\t\t\tif (unit->Mission != MISSION_UNLOAD) {\n\t\t\t\t\tunit->Assign_Destination(TARGET_NONE);\n\t\t\t\t\tunit->Assign_Target(TARGET_NONE);\n\t\t\t\t\tunit->Assign_Mission(MISSION_UNLOAD);\n\t\t\t\t\tfinished = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (unit->What_Am_I() == RTTI_UNIT && *(UnitClass *)unit == UNIT_MINELAYER && unit->Ammo != 0) {\n\t\t\t\t/*\n\t\t\t\t**\tThe check for a building is located here because the mine layer may have\n\t\t\t\t**\talready unloaded the mine but is still in the process of retracting\n\t\t\t\t**\tthe mine layer. During this time, it should not be considered to have\n\t\t\t\t**\tfinished its unload mission.\n\t\t\t\t*/\n\t\t\t\tif (!Map[unit->Center_Coord()].Cell_Building() && unit->Mission != MISSION_UNLOAD) {\n\t\t\t\t\tunit->Assign_Destination(TARGET_NONE);\n\t\t\t\t\tunit->Assign_Target(TARGET_NONE);\n\t\t\t\t\tunit->Assign_Mission(MISSION_UNLOAD);\n\t\t\t\t\tfinished = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\tunit = unit->Member;\n\t}\n\n\tif (finished) {\n\t\tIsNextMission = true;\n\t}\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * TeamClass::Fetch_A_Leader -- Looks for a suitable leader member of the team.                *\n *                                                                                             *\n *    This will scan through the team members looking for one that is suitable as a leader     *\n *    type. A team can sometimes contain limboed or unarmed members. These members are not     *\n *    suitable for leadership roles.                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a suitable leader type unit.                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/27/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nFootClass * TeamClass::Fetch_A_Leader(void) const\n{\n\tFootClass * leader = Member;\n\n\t/*\n\t**\tScan through the team members trying to find one that is an active member and\n\t**\tis equipped with a weapon.\n\t*/\n\twhile (leader != NULL) {\n\t\tif (_Is_It_Playing(leader) && leader->Is_Weapon_Equipped()) break;\n\t\tleader = leader->Member;\n\t}\n\n\t/*\n\t**\tIf no suitable leader was found, then just return with the first conveniently\n\t**\taccessable team member. This presumes that some member is better than no member\n\t**\tat all.\n\t*/\n\tif (leader == NULL) {\n\t\tleader = Member;\n\t}\n\n\treturn(leader);\n}\n"
  },
  {
    "path": "CODE/TEAM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TEAM.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TEAM.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/11/94                                                     *\n *                                                                                             *\n *                  Last Update : December 11, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TEAM_H\n#define TEAM_H\n\n\n#include\t\"wwfile.h\"\n#include\t\"teamtype.h\"\n#include\t\"abstract.h\"\n\n/*\n** Units are only allowed to stray a certain distance away from their\n** team.  When they exceed this distance, some sort of fixup must be\n** done.\n*/\n#define STRAY_DISTANCE\t\t2\n\nclass TeamClass : public AbstractClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis specifies the type of team this is.\n\t\t*/\n\t\tCCPtr<TeamTypeClass> Class;\n\n\t\t/*\n\t\t**\tThis specifies the owner of this team.\n\t\t*/\n\t\tCCPtr<HouseClass> House;\n\n\t\t/*\n\t\t**\tThis flag forces the team into active state regardless of whether it\n\t\t**\tis understrength or not.\n\t\t*/\n\t\tunsigned IsForcedActive:1;\n\n\t\t/*\n\t\t**\tThis flag is set to true when the team initiates into active mode. The\n\t\t**\tflag is never cleared. By examining this flag, it is possible to determine\n\t\t**\tif the team has ever launched into active mode.\n\t\t*/\n\t\tunsigned IsHasBeen:1;\n\n\t\t/*\n\t\t**\tIf the team is full strength, then this flag is true. A full strength\n\t\t**\tteam will not try to recruit members.\n\t\t*/\n\t\tunsigned IsFullStrength:1;\n\n\t\t/*\n\t\t**\tA team that is below half strength has this flag true. It means that the\n\t\t**\tthe team should hide back at the owner's base and try to recruit\n\t\t**\tmembers.\n\t\t*/\n\t\tunsigned IsUnderStrength:1;\n\n\t\t/*\n\t\t**\tIf a team is not understrength but is not yet full strength, then\n\t\t**\tthe team is regrouping.  If this flag is set and the team becomes\n\t\t**\tfull strength, the all members of the team will become initiated\n\t\t** and this flag will be reset.\n\t\t*/\n\t\tunsigned IsReforming:1;\n\n\t\t/*\n\t\t** This bit should be set if a team is determined to have lagging\n\t\t** units in its formation.\n\t\t*/\n\t\tunsigned IsLagging:1;\n\n\t\t/*\n\t\t**\tIf a team member was removed or added, then this flag will be set to true. The\n\t\t**\tteam system uses this flag to tell whether it should recalculate the team\n\t\t**\tunder strength or full strength flags. This process does not need to occur\n\t\t**\tEVERY time a unit added or deleted from a team, just every so often if the\n\t\t**\tteam has been changed.\n\t\t*/\n\t\tunsigned IsAltered:1;\n\t\tunsigned JustAltered:1;\n\n\t\t/*\n\t\t**\tIf the team is working on it's primary mission (it is past the build up stage)\n\t\t**\tthen this flag will be true. The transition between \"moving\" and \"stationary\"\n\t\t**\tstages usually requires some action on the team's part.\n\t\t*/\n\t\tunsigned IsMoving:1;\n\n\t\t/*\n\t\t**\tWhen the team determines that the next mission should be advanced to, it will\n\t\t**\tset this flag to true. Mission advance will either change the behavior of the\n\t\t**\tteam or cause it to disband.\n\t\t*/\n\t\tunsigned IsNextMission:1;\n\n\t\t/*\n\t\t**\tIf at least one member of this team successfully left the map, then this\n\t\t**\tflag will be set. At the time the team is terminated, if this flag is true, then\n\t\t**\tif there are any triggers that depend upon this team leaving, they will be\n\t\t**\tsprung.\n\t\t*/\n\t\tunsigned IsLeaveMap:1;\n\n\t\t/*\n\t\t** Records whether the team is suspended from production.\n\t\t*/\n\t\tunsigned Suspended:1;\n\n\t\t/*\n\t\t**\tA team will have a center point. This is the point used to determine if\n\t\t**\tany member of the team is \"too far\" from the team and must return. This\n\t\t**\tcenter point is usually calculated as the average position of all the\n\t\t**\tteam members.\n\t\t*/\n\t\tTARGET Zone;\n\n\t\t/*\n\t\t**\tThis is the target value of the team member that is closest to the\n\t\t**\tdestination of the team. The implied location serves as the\n\t\t**\tregroup point for the unit as it is moving.\n\t\t*/\n\t\tTARGET ClosestMember;\n\n\t\t/*\n\t\t**\tThis is the target of the team. Typically, it is a unit or structure, but\n\t\t**\tfor the case of teams with a movement mission, it might represent a\n\t\t**\tdestination cell.\n\t\t*/\n\t\tTARGET MissionTarget;\n\t\tTARGET Target;\n\n\t\t/*\n\t\t**\tThis is the total number of members in this team.\n\t\t*/\n\t\tint Total;\n\n\t\t/*\n\t\t**\tThis is the teams combined risk value\n\t\t*/\n\t\tint Risk;\n\n\t\t/*\n\t\t**\tIf this team is assigned a formation, then the formation type\n\t\t**\twill be stored here. If the formation type is FORMATION_NONE, then\n\t\t**\tthe team is a loose grouping -- just like C&C.\n\t\t*/\n\t\tFormationType Formation;\n\n\t\t/*\n\t\t** This is the amount of time the team is suspended for.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> SuspendTimer;\n\n\t\t/*\n\t\t**\tIf there is a trigger that should be attached to every member of this team, then\n\t\t**\tit is pointed to by this.\n\t\t*/\n\t\tCCPtr<TriggerClass> Trigger;\n\n\t\t//------------------------------------------------------------\n\t\tTeamClass(TeamTypeClass const * team=0, HouseClass * owner=0);\n\t\tTeamClass(NoInitClass const & x) : AbstractClass(x), Class(x), House(x), SuspendTimer(x), Trigger(x), TimeOut(x), Member(x) {};\n\t\tvirtual ~TeamClass(void);\n\t\tstatic void operator delete(void *ptr);\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t, void * ptr) {return(ptr);};\n\t\tstatic void Init(void);\n\t\tstatic void Suspend_Teams(int priority, HouseClass const * house);\n\t\tvoid Debug_Dump(MonoClass * mono) const;\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\t\tvoid Code_Pointers(void);\n\t\tvoid Decode_Pointers(void);\n\n\t\tbool Is_Empty(void) const {return(Member == (void*)NULL);}\n\t\tbool Has_Entered_Map(void) const;\n\t\tvoid Force_Active(void) {IsForcedActive = true;IsUnderStrength=false;};\n\t\tbool Remove(FootClass *, int typeindex=-1);\n\t\tvoid Detach(TARGET target, bool all);\n\t\tvoid AI(void);\n\t\tvoid Took_Damage(FootClass * obj, ResultType result, TechnoClass * source);\n\t\tbool Add(FootClass *);\n\t\tbool Can_Add(FootClass * obj, int & typeindex) const;\n\t\tvoid Assign_Mission_Target(TARGET new_target);\n\t\tbool Is_Leaving_Map(void) const;\n\t\tvoid Scan_Limit(void);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThe current mission index into the mission list is recorded here.\n\t\t*/\n\t\tint CurrentMission;\n\n\t\t/*\n\t\t**\tSome missions will time out. This is the timer that keeps track of the\n\t\t**\ttime to transition between missions.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> TimeOut;\n\n\t\tint TMission_Formation(void);\n\t\tint TMission_Attack(void);\n\t\tint TMission_Spy(void);\n\t\tint TMission_Follow(void);\n\t\tint TMission_Loop(void);\n\t\tint TMission_Load(void);\n\t\tint TMission_Unload(void);\n\t\tint TMission_Invulnerable(void);\n\t\tint TMission_Set_Global(void);\n\t\tint TMission_Patrol(void);\n\t\tint TMission_Deploy(void);\n\t\tbool Coordinate_Regroup(void);\n\t\tvoid Coordinate_Attack(void);\n\t\tvoid Coordinate_Move(void);\n\t\tbool Coordinate_Conscript(FootClass * unit);\n\t\tvoid Coordinate_Do(void);\n\t\tvoid Calc_Center(TARGET &center, TARGET &obj_center) const;\n\t\tint Recruit(int typeindex);\n\t\tbool Is_A_Member(void const * who) const;\n\t\tbool Lagging_Units(void);\n\t\tFootClass * Fetch_A_Leader(void) const;\n\n\t\t/*\n\t\t**\tPoints to the first member in the list of members for this team.\n\t\t*/\n\t\tSmartPtr<FootClass> Member;\n\n\t\tunsigned char Quantity[TeamTypeClass::MAX_TEAM_CLASSCOUNT];\n};\n\n#endif\n"
  },
  {
    "path": "CODE/TEAMTYPE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TEAMTYPE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TEAMTYPE.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/28/96                                                     *\n *                                                                                             *\n *                  Last Update : July 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   TeamMissionClass::Description -- Compose a text description of team mi                    *\n *   TeamMissionClass::Draw_It -- Draws a team mission list box entry.                         *\n *   TeamMission_Needs -- Determines what extra data is needed by team miss                    *\n *   TeamTypeClass::As_Pointer -- gets ptr for team type with given name                       *\n *   TeamTypeClass::Build_INI_Entry -- Builds the INI entry for this team type.                *\n *   TeamTypeClass::Create_One_Of -- Creates a team of this type.                              *\n *   TeamTypeClass::Description -- Builds a description of the team.                           *\n *   TeamTypeClass::Destroy_All_Of -- Destroy all teams of this type.                          *\n *   TeamTypeClass::Detach -- Detach the specified target from this team type.                 *\n *   TeamTypeClass::Draw_It -- Display the team type in a list box.                            *\n *   TeamTypeClass::Edit -- Edit the team type.                                                *\n *   TeamTypeClass::Fill_In -- fills in trigger from the given INI entry                       *\n *   TeamTypeClass::From_Name -- Converts a name into a team type pointer.                     *\n *   TeamTypeClass::Init -- pre-scenario initialization                                        *\n *   TeamTypeClass::Member_Description -- Builds a member description string                   *\n *   TeamTypeClass::Mission_From_Name -- returns mission for given name                        *\n *   TeamTypeClass::Name_From_Mission -- returns name for given mission                        *\n *   TeamTypeClass::Read_INI -- reads INI data                                                 *\n *   TeamTypeClass::Suggested_New_Team -- Suggests a new team to create.                       *\n *   TeamTypeClass::TeamTypeClass -- class constructor                                         *\n *   TeamTypeClass::Write_INI -- Write out the team types to the INI database.                 *\n *   TeamTypeClass::operator delete -- 'delete' operator                                       *\n *   TeamTypeClass::operator new -- 'new' operator                                             *\n *   TeamTypeClass::~TeamTypeClass -- class destructor                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\nTeamMissionClass TeamMissions[TMISSION_COUNT] = {\n\t{TMISSION_ATTACK},\n\t{TMISSION_ATT_WAYPT},\n\t{TMISSION_FORMATION},\n\t{TMISSION_MOVE},\n\t{TMISSION_MOVECELL},\n\t{TMISSION_GUARD},\n\t{TMISSION_LOOP},\n\t{TMISSION_ATTACKTARCOM},\n\t{TMISSION_UNLOAD},\n\t{TMISSION_DEPLOY},\n\t{TMISSION_HOUND_DOG},\n\t{TMISSION_DO},\n\t{TMISSION_SET_GLOBAL},\n\t{TMISSION_LOAD},\n\t{TMISSION_SPY},\n\t{TMISSION_PATROL},\n};\n\n\n\nint atoh(char * str);\n\n\n#if defined(CHEAT_KEYS) || defined(SCENARIO_EDITOR)\n/***********************************************************************************************\n * TeamTypeClass::Draw_It -- Display the team type in a list box.                              *\n *                                                                                             *\n *    This is a helper routine that is used when this team type is stored into a list box      *\n *    and must be displayed. It will display the team type as a single line of text.           *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TeamTypeClass::Draw_It(int , int x, int y, int width, int height, bool selected, TextPrintType flags) const\n{\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\tstatic int _tabs[] = {35, 60, 80, 100};\n\tif ((flags & 0x0F) == TPF_6PT_GRAD || (flags & 0x0F) == TPF_EFNT) {\n\n\t\tif (selected) {\n\t\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\t\tLogicPage->Fill_Rect(x, y, x + width - 1, y + height - 1, scheme->Shadow);\n\t\t} else {\n\t\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t\t}\n\t\t}\n\n\t\tConquer_Clip_Text_Print(Description(), x, y, scheme, TBLACK, flags, width, _tabs);\n\t} else {\n\t\tConquer_Clip_Text_Print(Description(), x, y, (selected ? &ColorRemaps[PCOLOR_DIALOG_BLUE] : &ColorRemaps[PCOLOR_GREY]), TBLACK, flags, width, _tabs);\n\t}\n}\n#endif\n\n\n/*\n********************************** Globals **********************************\n*/\nchar const * TeamTypeClass::TMissions[TMISSION_COUNT] = {\n\t\"Attack...\",\n\t\"Attack Waypoint...\",\n\t\"Change Formation to...\",\n\t\"Move to waypoint...\",\n\t\"Move to Cell...\",\n\t\"Guard area (1/10th min)...\",\n\t\"Jump to line #...\",\n\t\"Attack Tarcom\",\n\t\"Unload\",\n\t\"Deploy\",\n\t\"Follow friendlies\",\n\t\"Do this...\",\n\t\"Set global...\",\n\t\"Invulnerable\",\n\t\"Load onto Transport\",\n\t\"Spy on bldg @ waypt...\",\n\t\"Patrol to waypoint...\"\n};\n\n\n/***************************************************************************\n * TeamTypeClass::TeamTypeClass -- class constructor                       *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/07/1994 BR : Created.                                              *\n *   11/22/1995 JLB : Uses initializer constructor method.                 *\n *=========================================================================*/\nTeamTypeClass::TeamTypeClass(void) :\n\tAbstractTypeClass(RTTI_TEAMTYPE, TeamTypes.ID(this), TXT_NONE, \"\"),\n\tIsRoundAbout(false),\n\tIsSuicide(false),\n\tIsAutocreate(false),\n\tIsPrebuilt(true),\n\tIsReinforcable(true),\n\tIsTransient(false),\n\tRecruitPriority(7),\n\tInitNum(0),\n\tMaxAllowed(0),\n\tFear(0),\n\tHouse(HOUSE_NONE),\n\tTrigger(0),\n\tOrigin(-1),\n\tNumber(0),\n\tMissionCount(0),\n\tClassCount(0)\n{\n\tfor (int i = 0; i < MAX_TEAM_CLASSCOUNT; i++) {\n\t\tMembers[i].Class = NULL;\n\t\tMembers[i].Quantity = 0;\n\t}\n}\n\n\n/***************************************************************************\n * TeamTypeClass::Init -- pre-scenario initialization                      *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/07/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid TeamTypeClass::Init(void)\n{\n\tTeamTypes.Free_All();\n}\n\n\n/***************************************************************************\n * TeamTypeClass::As_Pointer -- gets ptr for team type with given name     *\n *                                                                         *\n * INPUT:                                                                  *\n *      name      name of teamtype                                         *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      ptr to TeamType with that name                                     *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/07/1994 BR : Created.                                              *\n *=========================================================================*/\nTeamTypeClass * TeamTypeClass::As_Pointer(char const * name)\n{\n\tif (name) {\n\t\tfor (int index = 0; index < TeamTypes.Count(); index++) {\n\t\t\tif (!stricmp(name, TeamTypes.Ptr(index)->IniName)) {\n\t\t\t\treturn(TeamTypes.Ptr(index));\n\t\t\t}\n\t\t}\n\t}\n\treturn(NULL);\n}\n\n\n/***************************************************************************\n * TeamTypeClass::Mission_From_Name -- returns team mission for given name *\n *                                                                         *\n * INPUT:                                                                  *\n *      name         name to compare                                       *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      mission for that name                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/13/1994 BR : Created.                                              *\n *=========================================================================*/\nTeamMissionType TeamTypeClass::Mission_From_Name(char const * name)\n{\n\tif (name) {\n\t\tfor (TeamMissionType order = TMISSION_FIRST; order < TMISSION_COUNT; order++) {\n\t\t\tif (stricmp(TMissions[order], name) == 0) {\n\t\t\t\treturn(order);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(TMISSION_NONE);\n}\n\n\n/***************************************************************************\n * TeamTypeClass::Name_From_Mission -- returns name for given mission      *\n *                                                                         *\n * INPUT:                                                                  *\n *      order      mission to get name for                                 *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      name of mission                                                    *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/13/1994 BR : Created.                                              *\n *=========================================================================*/\nchar const * TeamTypeClass::Name_From_Mission(TeamMissionType order)\n{\n\tassert((unsigned)order < TMISSION_COUNT);\n\n\treturn(TMissions[order]);\n}\n\n\n/***************************************************************************\n * TeamTypeClass::operator new -- 'new' operator                           *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      pointer to new TeamType                                            *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/28/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid * TeamTypeClass::operator new(size_t )\n{\n\tvoid * ptr = TeamTypes.Allocate();\n\tif (ptr) {\n\t\t((TeamTypeClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***************************************************************************\n * TeamTypeClass::operator delete -- 'delete' operator                     *\n *                                                                         *\n * INPUT:                                                                  *\n *      ptr      pointer to delete                                         *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/28/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid TeamTypeClass::operator delete(void * ptr)\n{\n\tif (ptr) {\n\t\t((TeamTypeClass *)ptr)->IsActive = false;\n\t}\n\tTeamTypes.Free((TeamTypeClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * TeamTypeClass::Create_One_Of -- Creates a team of this type.                                *\n *                                                                                             *\n *    Use this routine to create a team object from this team type.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the newly created team object. If one could not be       *\n *          created, then NULL is returned.                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTeamClass * TeamTypeClass::Create_One_Of(void) const\n{\n\tif (ScenarioInit || Number < MaxAllowed) {\n//\tif (ScenarioInit || TeamClass::Number[ID] < MaxAllowed) {\n\t\treturn(new TeamClass(this, HouseClass::As_Pointer(House)));\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * TeamTypeClass::Destroy_All_Of -- Destroy all teams of this type.                            *\n *                                                                                             *\n *    This routine will destroy all teams of this type. Typical use of this is from a trigger  *\n *    event.                                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TeamTypeClass::Destroy_All_Of(void) const\n{\n\tfor (int index = 0; index < Teams.Count(); index++) {\n\t\tTeamClass * team = Teams.Ptr(index);\n\n\t\tif (team->Class == this) {\n\t\t\tdelete team;\n\t\t\tindex--;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamTypeClass::Suggested_New_Team -- Suggests a new team to create.                         *\n *                                                                                             *\n *    This routine will scan through the team types available and create teams of the          *\n *    type that can best utilize the existing unit mix.                                        *\n *                                                                                             *\n * INPUT:   house    -- Pointer to the house that this team is to be created for.              *\n *                                                                                             *\n *          atypes   -- A bit mask of the aircraft types available for this house.             *\n *                                                                                             *\n *          utypes   -- A bit mask of the unit types available for this house.                 *\n *                                                                                             *\n *          itypes   -- A bit mask of the infantry types available for this house.             *\n *                                                                                             *\n *          vtypes   -- A bit mask of the vessel types available for this house.               *\n *                                                                                             *\n *          alerted  -- Is this house alerted? If true, then the Autocreate teams will be      *\n *                      considered in the selection process.                                   *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the team type that should be created. If no team should  *\n *          be created, then it returns NULL.                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/13/1995 JLB : Created.                                                                 *\n *   07/21/1995 JLB : Will autocreate team even if no members in field.                        *\n *=============================================================================================*/\nTeamTypeClass const * TeamTypeClass::Suggested_New_Team(HouseClass * house, long , long , long , long , bool alerted)\n//TeamTypeClass const * TeamTypeClass::Suggested_New_Team(HouseClass * house, long atypes, long utypes, long itypes, long vtypes, bool alerted)\n{\n//\tTeamTypeClass const * best = NULL;\n//\tint bestvalue = 0;\n\n\tTeamTypeClass const * choices[20];\n\tint choicecount = 0;\n\n\tfor (int index = 0; index < TeamTypes.Count(); index++) {\n\t\tTeamTypeClass const * ttype = TeamTypes.Ptr(index);\n\n\t\tassert(ttype != NULL);\n\n\t\tint maxnum = ttype->MaxAllowed;\n\t\tif ((alerted && !ttype->IsAutocreate) || (!alerted && ttype->IsAutocreate)) {\n\t\t\tmaxnum = 0;\n\t\t}\n\n\t\tif (choicecount >= ARRAY_SIZE(choices)) break;\n\n\t\tif (ttype != NULL && ttype->House == house->Class->House && ttype->Number < maxnum) {\n\n\t\t\tchoices[choicecount++] = ttype;\n\n#ifdef OBSOLETE\n\t\t\t/*\n\t\t\t**\tDetermine what kind of units this team requires.\n\t\t\t*/\n\t\t\tlong uneeded = 0;\n\t\t\tlong ineeded = 0;\n\t\t\tlong vneeded = 0;\n\t\t\tlong aneeded = 0;\n\t\t\tfor (int ctype = 0; ctype < ttype->ClassCount; ctype++) {\n\t\t\t\tswitch (ttype->Members[ctype].Class->What_Am_I()) {\n\t\t\t\t\tcase RTTI_INFANTRYTYPE:\n\t\t\t\t\t\tineeded |= (1 << ((InfantryTypeClass *)ttype->Members[ctype].Class)->Type);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase RTTI_UNITTYPE:\n\t\t\t\t\t\tuneeded |= (1 << ((UnitTypeClass *)ttype->Members[ctype].Class)->Type);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase RTTI_VESSELTYPE:\n\t\t\t\t\t\tvneeded |= (1 << ((VesselTypeClass *)ttype->Members[ctype].Class)->Type);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\t\t\t\taneeded |= (1 << ((AircraftTypeClass *)ttype->Members[ctype].Class)->Type);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf this team can use the types required, then consider it a possible\n\t\t\t**\tteam type to create.\n\t\t\t*/\n\t\t\tint value = 0;\n\t\t\tif ((aneeded & atypes) != 0 || (ineeded & itypes) != 0 || (uneeded & utypes) != 0 || (vneeded & vtypes) != 0) {\n\t\t\t\tvalue = ttype->RecruitPriority;\n\t\t\t} else {\n\t\t\t\tvalue = ttype->RecruitPriority/2;\n\t\t\t}\n\n\t\t\tif (best == NULL || bestvalue < value) {\n\t\t\t\tbestvalue = value;\n\t\t\t\tbest = ttype;\n\t\t\t}\n#endif\n\t\t}\n\t}\n\n\tif (choicecount > 0) {\n\t\treturn(choices[Random_Pick(0, choicecount-1)]);\n\t}\n\treturn(NULL);\n\n//\treturn(best);\n}\n\n\n/***********************************************************************************************\n * TeamTypeClass::From_Name -- Converts a name into a team type pointer.                       *\n *                                                                                             *\n *    This routine is used to convert an ASCII name of a team type into the corresponding      *\n *    team type pointer.                                                                       *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the ASCII name of the team type.                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the team type that this ASCII name represents. If there  *\n *          is no match, the NULL is returned.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTeamTypeClass * TeamTypeClass::From_Name(char const * name)\n{\n\tif (name) {\n\t\tfor (int index = 0; index < TeamTypes.Count(); index++) {\n\t\t\tif (stricmp(name, TeamTypes.Ptr(index)->IniName) == 0) {\n\t\t\t\treturn(TeamTypes.Ptr(index));\n\t\t\t}\n\t\t}\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * TeamMission_Needs -- Determines what extra data is needed by team mission.                  *\n *                                                                                             *\n *    This routine will return the required extra data that the specified team mission will    *\n *    need.                                                                                    *\n *                                                                                             *\n * INPUT:   tmtype   -- The team mission type to check.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with the data type needed for this team mission.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nNeedType TeamMission_Needs(TeamMissionType tmtype)\n{\n\tswitch (tmtype) {\n\t\t/*\n\t\t**\tRequires a formation type.\n\t\t*/\n\t\tcase TMISSION_FORMATION:\n\t\t\treturn(NEED_FORMATION);\n\n\t\t/*\n\t\t**\tTeam mission requires a target quarry value.\n\t\t*/\n\t\tcase TMISSION_ATTACK:\n\t\t\treturn(NEED_QUARRY);\n\n\t\t/*\n\t\t**\tTeam mission requires a data value.\n\t\t*/\n\t\tcase TMISSION_MOVECELL:\n\t\t\treturn(NEED_HEX_NUMBER);\n\n\t\tcase TMISSION_SET_GLOBAL:\n\t\tcase TMISSION_GUARD:\n\t\tcase TMISSION_LOOP:\n\t\t\treturn(NEED_NUMBER);\n\n\t\t/*\n\t\t**\tTeam mission requires a waypoint.\n\t\t*/\n\t\tcase TMISSION_PATROL:\n\t\tcase TMISSION_MOVE:\n\t\tcase TMISSION_ATT_WAYPT:\n\t\tcase TMISSION_SPY:\n\t\t\treturn(NEED_WAYPOINT);\n\n\t\t/*\n\t\t**\tTeam mission requires a general mission type.\n\t\t*/\n\t\tcase TMISSION_DO:\n\t\t\treturn(NEED_MISSION);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(NEED_NONE);\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***********************************************************************************************\n * TeamMissionClass::Draw_It -- Draws a team mission list box entry.                           *\n *                                                                                             *\n *    This routine will display a team mission list box entry. It converts the index number    *\n *    into the appropriate text string and then displays the text at the coordinates           *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   index    -- The index number to use when rendering the team mission.               *\n *                                                                                             *\n *          x,y      -- The X,Y coordinate to use when drawing the team mission entry.         *\n *                                                                                             *\n *          width, height  -- The dimensions of the area that the description can be           *\n *                            rendered into.                                                   *\n *                                                                                             *\n *          selected -- Is this entry currently selected? If so, then it should be rendered    *\n *                      differently.                                                           *\n *                                                                                             *\n *          flags    -- Text print control flags used for when the text is printed.            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TeamMissionClass::Draw_It(int index, int x, int y, int width, int height, bool selected, TextPrintType flags)\n{\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\tstatic int _tabs[] = {13,40};\n\tif ((flags & 0x0F) == TPF_6PT_GRAD || (flags & 0x0F) == TPF_EFNT) {\n\n\t\tif (selected) {\n\t\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\t\tLogicPage->Fill_Rect(x, y, x + width - 1, y + height - 1,\n\t\t\t\tscheme->Shadow);\n\t\t} else {\n\t\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t\t}\n\t\t}\n\n\t\tConquer_Clip_Text_Print(Description(index), x, y, scheme, TBLACK, flags, width, _tabs);\n\t} else {\n\t\tConquer_Clip_Text_Print(Description(index), x, y,\n\t\t\t(selected ? &ColorRemaps[PCOLOR_DIALOG_BLUE] : &ColorRemaps[PCOLOR_GREY]), TBLACK, flags, width, _tabs);\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamTypeClass::Edit -- Edit the team type.                                                  *\n *                                                                                             *\n *    This routine handles the editing dialog box for the team type.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the team type edited? A FALSE indicates that the dialog was canceled.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TeamTypeClass::Edit(void)\n{\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tenum {\n\t\tD_DIALOG_W = 400,\n\t\tD_DIALOG_H = 250,\n\t\tD_DIALOG_X = 0,\n\t\tD_DIALOG_Y = 0,\n\n\t\tD_NAME_X=D_DIALOG_X+35,\n\t\tD_NAME_Y=D_DIALOG_Y+27,\n\t\tED_WIDTH=40,\n\n\t\tD_CHECK_X=D_DIALOG_X+35,\t\t\t\t\t\t\t// Start of check box attribute list.\n\t\tD_CHECK_Y=D_NAME_Y+25,\n\n\t\tCB_SPACING_Y=9,\t\t\t\t\t\t\t\t\t\t// Vertical spacing between check box lines.\n\t\tCB_SPACING_X=8,\t\t\t\t\t\t\t\t\t\t// Horizontal spacing for check box description text.\n\t\tD_SPACING_X=9,\t\t\t\t\t\t\t\t\t\t\t// Horizontal spacing between data entry fields.\n\n\t\tD_CANCEL_W = 50,\n\t\tD_CANCEL_H = 9,\n\t\tD_CANCEL_X = D_DIALOG_X + D_DIALOG_W - (D_CANCEL_W+35),\n\t\tD_CANCEL_Y = D_DIALOG_Y + D_DIALOG_H - (D_CANCEL_H+20),\n\n\t\tD_OK_W = 50,\n\t\tD_OK_H = 9,\n\t\tD_OK_X = D_DIALOG_X + D_DIALOG_W - (D_OK_W+18)*2,\n\t\tD_OK_Y = D_CANCEL_Y\n\t};\n\n\t/*\n\t**\tButton enumerations:\n\t*/\n\tenum {\n\t\tBUTTON_NAME=100,\n\t\tBUTTON_RECRUIT,\n\t\tBUTTON_MAXNUM,\n\t\tBUTTON_INITNUM,\n\t\tBUTTON_HOUSE,\n\t\tBUTTON_ROUNDABOUT,\n\t\tBUTTON_LEARNING,\n\t\tBUTTON_SUICIDE,\n\t\tBUTTON_AUTO,\n\t\tBUTTON_PREBUILT,\n\t\tBUTTON_REINFORCE,\n\t\tBUTTON_MISSION1,\n\t\tBUTTON_MISSION2,\n\t\tBUTTON_ADD,\n\t\tBUTTON_INSERT,\n\t\tBUTTON_DELETE,\n\t\tBUTTON_REPLACE,\n\t\tBUTTON_ARG,\n\t\tBUTTON_FORMATION,\n\t\tBUTTON_MEMBERS,\n\t\tBUTTON_MISSION,\n\t\tBUTTON_TRIGGER,\n\t\tBUTTON_ORIGIN,\n\t\tBUTTON_OK,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_QUARRY,\n\t};\n\n\t/*\n\t**\tDialog variables:\n\t*/\n\tControlClass * commands = 0;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t**\tTeam name edit field.\n\t*/\n\tchar name_buf[10];\n\tEditClass name_edt(BUTTON_NAME, name_buf, sizeof(name_buf),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tD_NAME_X, D_NAME_Y, ED_WIDTH, 9, EditClass::ALPHANUMERIC);\n\tstrcpy(name_buf, IniName);\n\tcommands = &name_edt;\n\n\t/*\n\t**\tHouse ownership of this team.\n\t*/\n\tchar housetext[25] = \"\";\n\tDropListClass housebtn(BUTTON_HOUSE, housetext, sizeof(housetext),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tname_edt.X+name_edt.Width+D_SPACING_X, name_edt.Y, 55, 8*5,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\thousebtn.Add_Item(HouseTypeClass::As_Reference(house).IniName);\n\t}\n\tif (House == HOUSE_NONE) House = HOUSE_GOOD;\n\thousebtn.Set_Selected_Index(House);\n\thousebtn.Add(*commands);\n\n\t/*\n\t**\tRecruit priority for this team.\n\t*/\n\tchar recr_buf[4];\n\tEditClass recr_edt(BUTTON_RECRUIT, recr_buf, sizeof(recr_buf),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\thousebtn.X+housebtn.Width+5+D_SPACING_X, housebtn.Y, ED_WIDTH, 9, EditClass::NUMERIC);\n\tsprintf(recr_buf, \"%d\", RecruitPriority);\n\trecr_edt.Add(*commands);\n\n\t/*\n\t**\tMaximum allowed for this team type.\n\t*/\n\tchar maxnum_buf[4];\n\tEditClass maxnum_edt(BUTTON_MAXNUM, maxnum_buf, sizeof(maxnum_buf),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\trecr_edt.X+recr_edt.Width+D_SPACING_X, recr_edt.Y, ED_WIDTH, 9, EditClass::NUMERIC);\n\tsprintf(maxnum_buf, \"%d\", MaxAllowed);\n\tmaxnum_edt.Add(*commands);\n\n\t/*\n\t**\tInitial number for this team type.\n\t*/\n\tchar initnum_buf[4];\n\tEditClass initnum_edt(BUTTON_INITNUM, initnum_buf, sizeof(initnum_buf),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tmaxnum_edt.X+maxnum_edt.Width+D_SPACING_X, maxnum_edt.Y, ED_WIDTH, 9, EditClass::NUMERIC);\n\tsprintf(initnum_buf, \"%d\", InitNum);\n\tinitnum_edt.Add(*commands);\n\n\t/*\n\t**\tWaypoint preference to create/reinforce this team.\n\t*/\n\tchar origin[4];\n\tEditClass originbtn(BUTTON_ORIGIN, origin, sizeof(origin),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tinitnum_edt.X+initnum_edt.Width+D_SPACING_X, initnum_edt.Y, 20, 9, EditClass::ALPHA);\n\t*originbtn.Get_Text() = '\\0';\n\tif (Origin != -1) {\n\t\tif (Origin < 26) {\n\t\t\tsprintf(originbtn.Get_Text(), \"%c\", Origin + 'A');\n\t\t} else {\n\t\t\tsprintf(originbtn.Get_Text(), \"%c%c\", (Origin/26) + 'A'-1, Origin % 26 + 'A');\n\t\t}\n\t}\n\toriginbtn.Add(*commands);\n\n\t/*\n\t**\tMembers of this team control button.\n\t*/\n\tTextButtonClass membersbtn(BUTTON_MEMBERS, \"Members\", TPF_EBUTTON, name_edt.X, name_edt.Y+12, 50);\n\tmembersbtn.Add(*commands);\n\n\t/*\n\t**\tTrigger to assign to each member of this team (when object joins team).\n\t*/\n\tchar trigtext[25] = \"\";\n\tDropListClass triggerbtn(BUTTON_TRIGGER, trigtext, sizeof(trigtext),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tD_DIALOG_X+D_DIALOG_W-95, membersbtn.Y, 60, 8*5,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\ttriggerbtn.Add_Item(\"<NONE>\");\n\tfor (int index = 0; index < TriggerTypes.Count(); index++) {\n\t\ttriggerbtn.Add_Item(TriggerTypes.Ptr(index)->IniName);\n\t}\n\tif (Trigger.Is_Valid()) {\n\t\ttriggerbtn.Set_Selected_Index(Trigger->Name());\n\t} else {\n\t\ttriggerbtn.Set_Selected_Index(0);\n\t}\n\ttriggerbtn.Add(*commands);\n\n\t/*\n\t**\tRoundabout travel logic attribute for this team.\n\t*/\n\tCheckBoxClass roundbtn(BUTTON_ROUNDABOUT, D_CHECK_X, D_CHECK_Y);\n\tif (IsRoundAbout) {\n\t\troundbtn.Turn_On();\n\t} else {\n\t\troundbtn.Turn_Off();\n\t}\n\troundbtn.Add(*commands);\n\n\t/*\n\t**\tSuicide travel to target attribute.\n\t*/\n\tCheckBoxClass suicidebtn(BUTTON_SUICIDE, D_CHECK_X, roundbtn.Y+CB_SPACING_Y);\n\tif (IsSuicide) {\n\t\tsuicidebtn.Turn_On();\n\t} else {\n\t\tsuicidebtn.Turn_Off();\n\t}\n\tsuicidebtn.Add(*commands);\n\n\t/*\n\t**\tAutocreate attribute for this team.\n\t*/\n\tCheckBoxClass autocreatebtn(BUTTON_AUTO, D_CHECK_X, suicidebtn.Y+CB_SPACING_Y);\n\tif (IsAutocreate) {\n\t\tautocreatebtn.Turn_On();\n\t} else {\n\t\tautocreatebtn.Turn_Off();\n\t}\n\tautocreatebtn.Add(*commands);\n\n\t/*\n\t**\tPrebuild team members attribute for this team.\n\t*/\n\tCheckBoxClass prebuildbtn(BUTTON_PREBUILT, D_CHECK_X, autocreatebtn.Y+CB_SPACING_Y);\n\tif (IsPrebuilt) {\n\t\tprebuildbtn.Turn_On();\n\t} else {\n\t\tprebuildbtn.Turn_Off();\n\t}\n\tprebuildbtn.Add(*commands);\n\n\t/*\n\t**\tReinforce this team in progress attribute.\n\t*/\n\tCheckBoxClass reinforcebtn(BUTTON_REINFORCE, D_CHECK_X, prebuildbtn.Y+CB_SPACING_Y);\n\tif (IsReinforcable) {\n\t\treinforcebtn.Turn_On();\n\t} else {\n\t\treinforcebtn.Turn_Off();\n\t}\n\treinforcebtn.Add(*commands);\n\n\t/*\n\t**\tCreate drop box of possible team missions. This is used when building/editing the\n\t**\tteam mission list.\n\t*/\n\tchar droptext[45];\n\tDropListClass missionlist1(BUTTON_MISSION1, droptext, sizeof(droptext),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\treinforcebtn.X, reinforcebtn.Y+15, 170, 8*8,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (TeamMissionType tm = TMISSION_FIRST; tm < TMISSION_COUNT; tm++) {\n\t\tmissionlist1.Add_Item(TeamTypeClass::Name_From_Mission(tm));\n\t}\n\tmissionlist1.Set_Selected_Index(0);\n\tmissionlist1.Add_Tail(*commands);\n\n\t/*\n\t**\tOptional mission argument entry field.\n\t*/\n\tchar arg_buf[6] = {0};\n\tEditClass arg_edt(BUTTON_ARG, arg_buf, sizeof(arg_buf),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tmissionlist1.X + missionlist1.Width + 15, missionlist1.Y, 60, -1, EditClass::ALPHANUMERIC);\n//\targ_edt.Add(*commands);\n\n\tchar qtext[55];\n\tDropListClass qlist(BUTTON_QUARRY, qtext, sizeof(qtext),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tmissionlist1.X + missionlist1.Width + 15, missionlist1.Y, 100, 5*8,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (QuarryType q = QUARRY_FIRST; q < QUARRY_COUNT; q++) {\n\t\tqlist.Add_Item(QuarryName[q]);\n\t}\n\tqlist.Set_Selected_Index(0);\n\tqlist.Add_Tail(*commands);\n\n\tchar ftext[55];\n\tDropListClass flist(BUTTON_FORMATION, ftext, sizeof(ftext),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tmissionlist1.X + missionlist1.Width + 15, missionlist1.Y, 100, 5*8,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (FormationType f = FORMATION_FIRST; f < FORMATION_COUNT; f++) {\n\t\tflist.Add_Item(FormationName[f]);\n\t}\n\tflist.Set_Selected_Index(0);\n\tflist.Add_Tail(*commands);\n\n\tchar mtext[55];\n\tDropListClass mlist(BUTTON_MISSION, mtext, sizeof(mtext),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tmissionlist1.X + missionlist1.Width + 15, missionlist1.Y, 100, 5*8,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (MissionType m = MISSION_FIRST; m < MISSION_COUNT; m++) {\n\t\tmlist.Add_Item(MissionClass::Mission_Name(m));\n\t}\n\tmlist.Set_Selected_Index(0);\n\tmlist.Add_Tail(*commands);\n\n\tTListClass<TeamMissionClass *> missionlist2(BUTTON_MISSION2, missionlist1.X+60, missionlist1.Y+22, 240, 8*7,\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (index = 0; index < MissionCount; index++) {\n\t\tmissionlist2.Add_Item(new TeamMissionClass(MissionList[index]));\n//\t\tmissionlist2.Add_Item(&TeamMissions[MissionList[index].Mission]);\n\t}\n\tstatic int tabs[] = {13, 40};\t\t// list box tab stops\n\tmissionlist2.Set_Tabs(tabs);\n\tmissionlist2.Add_Tail(*commands);\n\n\t/*\n\t**\tMission editing command buttons.\n\t*/\n\tTextButtonClass addbtn(BUTTON_ADD, \"Append\", TPF_EBUTTON, D_NAME_X, missionlist1.Y+missionlist1.Height+1, 50);\n\taddbtn.Add(*commands);\n\n\tTextButtonClass insertbtn(BUTTON_INSERT, \"Insert\", TPF_EBUTTON, addbtn.X, addbtn.Y+10, 50);\n\tinsertbtn.Add(*commands);\n\n\tTextButtonClass delbtn(BUTTON_DELETE, \"Delete\", TPF_EBUTTON, insertbtn.X, insertbtn.Y+10, 50);\n\tdelbtn.Add(*commands);\n\n\tTextButtonClass repbtn(BUTTON_REPLACE, \"Replace\", TPF_EBUTTON, delbtn.X, delbtn.Y+10, 50);\n\trepbtn.Add(*commands);\n\n\n\tTextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_EBUTTON, D_OK_X, D_OK_Y, D_OK_W, D_OK_H);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_EBUTTON, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W, D_CANCEL_H);\n\n\t/*\n\t**\tInitialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tCreate the list\n\t*/\n\tokbtn.Add(*commands);\n\tcancelbtn.Add_Tail(*commands);\n\n\t/*\n\t**\tMain Processing Loop\n\t*/\n\tint lastindex = -1;\n\tint lastcount = -1;\n\tint lastbutton = -1;\n\tbool cancel = false;\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if needed\n\t\t*/\n\t\tif (display) {\n\n\t\t\t/*\n\t\t\t**\tAdd the optional data entry field as necessary.\n\t\t\t*/\n\t\t\targ_edt.Remove();\n\t\t\tqlist.Remove();\n\t\t\tflist.Remove();\n\t\t\tmlist.Remove();\n\t\t\tswitch (TeamMission_Needs(TeamMissionType(missionlist1.Current_Index()))) {\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_MISSION:\n\t\t\t\t\tmlist.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_FORMATION:\n\t\t\t\t\tflist.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_WAYPOINT:\n\t\t\t\tcase NEED_NUMBER:\n\t\t\t\tcase NEED_HEX_NUMBER:\n\t\t\t\t\targ_edt.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_QUARRY:\n\t\t\t\t\tqlist.Add(*commands);\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDisplay the dialog box\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\n\t\t\tDraw_Caption(TXT_TEAM_EDIT, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\n\t\t\t/*\n\t\t\t**\tDraw the captions\n\t\t\t*/\n\t\t\tFancy_Text_Print(\"Name:\", name_edt.X, name_edt.Y-7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"House:\", housebtn.X, housebtn.Y-7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Pri:\", recr_edt.X, recr_edt.Y-7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Max:\", maxnum_edt.X, maxnum_edt.Y-7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Num:\", initnum_edt.X, initnum_edt.Y-7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Loc:\", originbtn.X, originbtn.Y-7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"#  Team Mission\", missionlist2.X, missionlist2.Y-7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Trigger:\", triggerbtn.X-4, triggerbtn.Y+1, scheme, TBLACK, TPF_RIGHT | TPF_EFNT | TPF_NOSHADOW);\n\n\t\t\tFancy_Text_Print(Member_Description(), membersbtn.X + membersbtn.Width + 3, membersbtn.Y+1, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\n\t\t\tFancy_Text_Print(\"Use safest, possibly longer, route to target?\", roundbtn.X+CB_SPACING_X, roundbtn.Y, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Charge toward target ignoring distractions?\", suicidebtn.X+CB_SPACING_X, suicidebtn.Y, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Only 'Autocreate A.I.' uses this team type?\", autocreatebtn.X+CB_SPACING_X, autocreatebtn.Y, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Prebuild team members before team is created?\", prebuildbtn.X+CB_SPACING_X, prebuildbtn.Y, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Automatically reinforce team whenever possible?\", reinforcebtn.X+CB_SPACING_X, reinforcebtn.Y, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\n\t\t\t/*\n\t\t\t**\tRedraw the buttons\n\t\t\t*/\n\t\t\tcommands->Draw_All();\n\t\t\tShow_Mouse();\n\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t**\tProcess input\n\t\t*/\n\t\tswitch (input) {\n\n\t\t\t/*\n\t\t\t**\tSelect a Mission on the right-hand mission list; update the Argument\n\t\t\t**\tfield to reflect the current value. This only serves as an aide to editing\n\t\t\t**\tthe team mission list.\n\t\t\t*/\n\t\t\tcase BUTTON_MISSION2 | KN_BUTTON:\n\t\t\t\tif (missionlist2.Count() && lastcount == missionlist2.Count() && lastbutton == BUTTON_MISSION2 && lastindex == missionlist2.Current_Index()) {\n\t\t\t\t\tmissionlist1.Set_Selected_Index(missionlist2.Current_Item()->Mission);\n\n\t\t\t\t\tswitch (TeamMission_Needs(missionlist2.Current_Item()->Mission)) {\n\t\t\t\t\t\tcase NEED_MISSION:\n\t\t\t\t\t\t\tmlist.Set_Selected_Index(missionlist2.Current_Item()->Data.Mission);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_FORMATION:\n\t\t\t\t\t\t\tflist.Set_Selected_Index(missionlist2.Current_Item()->Data.Formation);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_NUMBER:\n\t\t\t\t\t\t\tsprintf(arg_edt.Get_Text(), \"%d\", missionlist2.Current_Item()->Data.Value);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_HEX_NUMBER:\n\t\t\t\t\t\t\tsprintf(arg_edt.Get_Text(), \"%x\", missionlist2.Current_Item()->Data.Value);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_QUARRY:\n\t\t\t\t\t\t\tstrcpy(qlist.Get_Text(), QuarryName[missionlist2.Current_Item()->Data.Quarry]);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_WAYPOINT:\n\t\t\t\t\t\t\tif (missionlist2.Current_Item()->Data.Value < 26) {\n\t\t\t\t\t\t\t\tsprintf(arg_edt.Get_Text(), \"%c\", missionlist2.Current_Item()->Data.Value + 'A');\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tsprintf(arg_edt.Get_Text(), \"%c%c\", (missionlist2.Current_Item()->Data.Value)/26 + 'A'-1, (missionlist2.Current_Item()->Data.Value % 26) + 'A');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlastindex = missionlist2.Current_Index();\n\t\t\t\tlastcount = missionlist2.Count();\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tAdd current mission data to current position of team mission list. Any\n\t\t\t**\tsubsequent missions get moved downward.\n\t\t\t*/\n\t\t\tcase BUTTON_INSERT | KN_BUTTON:\n\t\t\t\tif (missionlist2.Count() < MAX_TEAM_MISSIONS) {\n\t\t\t\t\tTeamMissionClass * tm = new TeamMissionClass;\n\t\t\t\t\ttm->Mission = TeamMissionType(missionlist1.Current_Index());\n\t\t\t\t\ttm->Data.Value = 0;\n\t\t\t\t\tswitch (TeamMission_Needs(tm->Mission)) {\n\t\t\t\t\t\tcase NEED_MISSION:\n\t\t\t\t\t\t\ttm->Data.Mission = MissionType(mlist.Current_Index());\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_FORMATION:\n\t\t\t\t\t\t\ttm->Data.Formation = FormationType(flist.Current_Index());\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_QUARRY:\n\t\t\t\t\t\t\ttm->Data.Quarry = QuarryType(qlist.Current_Index());\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_NUMBER:\n\t\t\t\t\t\t\ttm->Data.Value = atoi(arg_edt.Get_Text());\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_HEX_NUMBER:\n\t\t\t\t\t\t\ttm->Data.Value = atoh(arg_edt.Get_Text());\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_WAYPOINT:\n\t\t\t\t\t\t\ttm->Data.Value = toupper(*arg_edt.Get_Text()) - 'A';\n\t\t\t\t\t\t\tif ( *((arg_edt.Get_Text())+1)) {\n\t\t\t\t\t\t\t\ttm->Data.Value = (tm->Data.Value+1)*26;\n\t\t\t\t\t\t\t\ttm->Data.Value += toupper(*((arg_edt.Get_Text())+1)) - 'A';;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ((unsigned)tm->Data.Value >= WAYPT_HOME) {\n\t\t\t\t\t\t\t\ttm->Data.Value = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\ttm->Data.Value = 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tmissionlist2.Insert_Item(tm);\n\t\t\t\t}\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tAdd mission data to the end of the mission list.\n\t\t\t*/\n\t\t\tcase BUTTON_ADD | KN_BUTTON:\n\t\t\t\tif (missionlist2.Count() < MAX_TEAM_MISSIONS) {\n\t\t\t\t\tTeamMissionClass * tm = new TeamMissionClass;\n\t\t\t\t\ttm->Mission = TeamMissionType(missionlist1.Current_Index());\n\t\t\t\t\ttm->Data.Value = 0;\n\t\t\t\t\tswitch (TeamMission_Needs(tm->Mission)) {\n\t\t\t\t\t\tcase NEED_MISSION:\n\t\t\t\t\t\t\ttm->Data.Mission = MissionType(mlist.Current_Index());\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_FORMATION:\n\t\t\t\t\t\t\ttm->Data.Formation = FormationType(flist.Current_Index());\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_QUARRY:\n\t\t\t\t\t\t\ttm->Data.Quarry = QuarryType(qlist.Current_Index());\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_NUMBER:\n\t\t\t\t\t\t\ttm->Data.Value = atoi(arg_edt.Get_Text());\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_HEX_NUMBER:\n\t\t\t\t\t\t\ttm->Data.Value = atoh(arg_edt.Get_Text());\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_WAYPOINT:\n\t\t\t\t\t\t\ttm->Data.Value = toupper(*arg_edt.Get_Text()) - 'A';;\n\t\t\t\t\t\t\tif ( *((arg_edt.Get_Text())+1)) {\n\t\t\t\t\t\t\t\ttm->Data.Value = (tm->Data.Value+1)*26;\n\t\t\t\t\t\t\t\ttm->Data.Value += toupper(*((arg_edt.Get_Text())+1)) - 'A';;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ((unsigned)tm->Data.Value >= WAYPT_HOME) {\n\t\t\t\t\t\t\t\ttm->Data.Value = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\ttm->Data.Value = 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tmissionlist2.Add_Item(tm);\n\t\t\t\t\tdisplay = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tReplace the currently selected mission with the work mission data.\n\t\t\t*/\n\t\t\tcase BUTTON_REPLACE | KN_BUTTON:\n\t\t\t\tif (missionlist2.Count()) {\n\t\t\t\t\tTeamMissionClass * tm = missionlist2.Current_Item();\n\t\t\t\t\ttm->Mission = TeamMissionType(missionlist1.Current_Index());\n\t\t\t\t\ttm->Data.Value = 0;\n\t\t\t\t\tswitch (TeamMission_Needs(tm->Mission)) {\n\t\t\t\t\t\tcase NEED_MISSION:\n\t\t\t\t\t\t\ttm->Data.Mission = MissionType(mlist.Current_Index());\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_FORMATION:\n\t\t\t\t\t\t\ttm->Data.Formation = FormationType(flist.Current_Index());\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_QUARRY:\n\t\t\t\t\t\t\ttm->Data.Quarry = QuarryType(qlist.Current_Index());\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_NUMBER:\n\t\t\t\t\t\t\ttm->Data.Value = atoi(arg_edt.Get_Text());\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_HEX_NUMBER:\n\t\t\t\t\t\t\ttm->Data.Value = atoh(arg_edt.Get_Text());\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase NEED_WAYPOINT:\n\t\t\t\t\t\t\ttm->Data.Value = toupper(*arg_edt.Get_Text()) - 'A';\n\t\t\t\t\t\t\tif ( *((arg_edt.Get_Text())+1)) {\n\t\t\t\t\t\t\t\ttm->Data.Value = (tm->Data.Value+1)*26;\n\t\t\t\t\t\t\t\ttm->Data.Value += toupper(*((arg_edt.Get_Text())+1)) - 'A';\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ((unsigned)tm->Data.Value >= WAYPT_HOME) {\n\t\t\t\t\t\t\t\ttm->Data.Value = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\ttm->Data.Value = 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tmissionlist2[missionlist2.Current_Index()] = tm;\n\t\t\t\t}\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tDelete the currently selected mission.\n\t\t\t*/\n\t\t\tcase BUTTON_DELETE | KN_BUTTON:\n\t\t\t\tif (missionlist2.Count()) {\n\t\t\t\t\tTeamMissionClass * tm = missionlist2.Current_Item();\n\t\t\t\t\tmissionlist2.Remove_Index(missionlist2.Current_Index());\n\t\t\t\t\tdelete tm;\n\t\t\t\t}\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tInvoke the members dialog\n\t\t\t*/\n\t\t\tcase BUTTON_MEMBERS | KN_BUTTON:\n\n\t\t\t\t/*\n\t\t\t\t**\tTake editor focus away\n\t\t\t\t*/\n\t\t\t\tmembersbtn.Turn_Off();\n\n\t\t\t\t/*\n\t\t\t\t**\tInvoke the dialog\n\t\t\t\t*/\n\t\t\t\tMap.Team_Members(HousesType(housebtn.Current_Index()));\n\n\t\t\t\t/*\n\t\t\t\t**\tRedraw\n\t\t\t\t*/\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tWhen the OK button is selected, lift the values from the dialog box\n\t\t\t**\tand place them into the team type object.\n\t\t\t*/\n\t\t\tcase BUTTON_OK | KN_BUTTON:\n\t\t\t\tstrtrim(name_edt.Get_Text());\n\t\t\t\tif (strlen(name_edt.Get_Text()) != 0) {\n\t\t\t\t\tstrcpy(IniName, name_edt.Get_Text());\n\t\t\t\t} else {\n\t\t\t\t\tstrcpy(IniName, \"----\");\n\t\t\t\t}\n\n\t\t\t\tIsRoundAbout = roundbtn.IsOn;\n\t\t\t\tIsSuicide = suicidebtn.IsOn;\n\t\t\t\tIsAutocreate = autocreatebtn.IsOn;\n\t\t\t\tIsPrebuilt = prebuildbtn.IsOn;\n\t\t\t\tIsReinforcable = reinforcebtn.IsOn;\n\n\t\t\t\tRecruitPriority = atoi(recr_edt.Get_Text());\n\t\t\t\tInitNum = atoi(initnum_edt.Get_Text());\n\t\t\t\tMaxAllowed = atoi(maxnum_edt.Get_Text());\n\t\t\t\tHouse = HousesType(housebtn.Current_Index());\n\t\t\t\tTrigger = NULL;\n\t\t\t\tif (triggerbtn.Current_Index() > 0) {\n\t\t\t\t\tTrigger = TriggerTypes.Ptr(triggerbtn.Current_Index()-1);\n\t\t\t\t}\n\n\t\t\t\tMissionCount = missionlist2.Count();\n\t\t\t\tfor (index = 0; index < MissionCount; index++) {\n\t\t\t\t\tMissionList[index].Data.Value = 0;\t\t\t\t// Clears extra bits.\n\t\t\t\t\tMissionList[index] = *missionlist2[index];\n\t\t\t\t}\n\n#ifdef TOFIX\n// the mission class objects pointed to in the list should be deleted?\n#endif\n\n\t\t\t\tif (strlen(originbtn.Get_Text())) {\n\t\t\t\t\tif (strlen(originbtn.Get_Text()) == 1) {\n\t\t\t\t\t\tOrigin = toupper(*originbtn.Get_Text()) - 'A';\n\t\t\t\t\t} else {\n\t\t\t\t\t\tOrigin = (toupper(*originbtn.Get_Text())+1 - 'A' ) * 26;\n\t\t\t\t\t\tOrigin += toupper(*(originbtn.Get_Text()+1)) - 'A';\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tOrigin = -1;\n\t\t\t\t}\n\t\t\t\tcancel = false;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tCancel: return\n\t\t\t*/\n\t\t\tcase BUTTON_CANCEL | KN_BUTTON:\n\t\t\t\tcancel = true;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tUnrecognized events are ignored. If any button related event is\n\t\t\t**\tdetected, then collapse any drop down list boxes. This keeps the\n\t\t\t**\tdialog box clean.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\tif (input & KN_BUTTON) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tmissionlist1.Collapse();\n\t\t\t\t\ttriggerbtn.Collapse();\n\t\t\t\t\tdisplay = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tRecord the last dialog control touched so that a double click\n\t\t**\tcan be detected.\n\t\t*/\n\t\tif (input & KN_BUTTON) {\n\t\t\tlastbutton = (input & ~KN_BUTTON);\n\t\t}\n\t}\n\n\treturn(!cancel);\n}\n\n\nint atoh(char * str)\n{\n\tint retval = 0;\n\twhile (*str) {\n\t\tretval *= 16;\n\t\tif (*str >= '0' && *str <= '9') {\n\t\t\tretval += *str-'0';\n\t\t} else {\n\t\t\tif (*str >= 'a' && *str <= 'f') {\n\t\t\t\tretval += 10 + (*str - 'a');\n\t\t\t} else {\n\t\t\t\tif (*str >= 'A' && *str <= 'F') {\n\t\t\t\t\tretval += 10 + (*str - 'A');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tstr++;\n\t}\n\treturn(retval);\n}\n\n#endif\n\n\n#if defined(CHEAT_KEYS) || defined(SCENARIO_EDITOR)\n/***********************************************************************************************\n * TeamTypeClass::Member_Description -- Builds a member description string.                    *\n *                                                                                             *\n *    This routine will build a team member description string. The string will be composed    *\n *    of the team member type and quantity. As many team member types will be listed that      *\n *    can fit within a reasonable size.                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the text string that contains a description of the team  *\n *          type members.                                                                      *\n *                                                                                             *\n * WARNINGS:   The return string may be truncated if necessary to fit within reasonable size   *\n *             limits.                                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * TeamTypeClass::Member_Description(void) const\n{\n\tstatic char buffer[128];\n\n\tbuffer[0] = '\\0';\n\n\t/*\n\t**\tFill in class & count for all classes\n\t*/\n\tfor (int index = 0; index < ClassCount; index++) {\n\t\tchar txt[10];\n\n\t\tstrcat(buffer, Members[index].Class->IniName);\n\t\tstrcat(buffer, \":\");\n\n\t\tsprintf(txt, \"%d\", Members[index].Quantity);\n\t\tstrcat(buffer, txt);\n\n\t\tif (index < ClassCount-1) {\n\t\t\tstrcat(buffer, \",\");\n\t\t}\n\t}\n\n\tif (strlen(buffer) > 25) {\n\t\tstrcpy(&buffer[25-3], \"...\");\n\t}\n\n\treturn(buffer);\n}\n\n\n/***********************************************************************************************\n * TeamTypeClass::Description -- Builds a description of the team.                             *\n *                                                                                             *\n *    This routine will build a brief description of the team type. This description is used   *\n *    in the team type list.                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the composed text string that represents the team type.               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * TeamTypeClass::Description(void) const\n{\n\tstatic char _buffer[128];\n\tchar extra = ' ';\n\tchar loc[3];\n\n\tloc[0] = loc[1] = loc[2] = 0;\n\tif (IsAutocreate) extra = '*';\n\tif (Origin > -1) {\n//\tif (Origin != -1) {\n\t\tif (Origin < 26) {\n\t\t\tloc[0] = 'A' + Origin;\n\t\t} else {\n\t\t\tloc[0] = Origin / 26 + 'A'-1;\n\t\t\tloc[1] = Origin % 26 + 'A';\n\t\t}\n\t}\n\n\tsprintf(_buffer, \"%s\\t%s\\t%c%s\\t%d\\t%s\", IniName, HouseTypeClass::As_Reference(House).Suffix, extra, loc, MissionCount, Member_Description());\n\treturn(_buffer);\n}\n\n\n/***********************************************************************************************\n * TeamMissionClass::Description -- Compose a text description of team mission.                *\n *                                                                                             *\n *    This routine will create a text representation of a team mission. This description will  *\n *    be used in the list of team missions for display purposes.                               *\n *                                                                                             *\n * INPUT:   index -- The index to assign to this team. The index is used since some team       *\n *                   missions refer to the another team mission by index number.               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the team mission text.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * TeamMissionClass::Description(int index) const\n{\n\tstatic char buffer[64];\n\n\tsprintf(buffer, \"%d\\t%s\", index, TeamTypeClass::Name_From_Mission(Mission));\n\n\tswitch (TeamMission_Needs(Mission)) {\n\t\tcase NEED_MISSION:\n\t\t\tstrcat(buffer, MissionClass::Mission_Name(Data.Mission));\n\t\t\tbreak;\n\n\t\tcase NEED_FORMATION:\n\t\t\tstrcat(buffer, FormationName[Data.Quarry]);\n\t\t\tbreak;\n\n\t\tcase NEED_NUMBER:\n\t\t\tsprintf(&buffer[strlen(buffer)], \"%d\", Data.Value);\n\t\t\tbreak;\n\n\t\tcase NEED_HEX_NUMBER:\n\t\t\tsprintf(&buffer[strlen(buffer)], \"%x\", Data.Value);\n\t\t\tbreak;\n\n\t\tcase NEED_QUARRY:\n\t\t\tstrcat(buffer, QuarryName[Data.Quarry]);\n\t\t\tbreak;\n\n\t\tcase NEED_WAYPOINT:\n\t\t\tif (Data.Value < 26) {\n\t\t\t\tsprintf(&buffer[strlen(buffer)], \"%c\", Data.Value + 'A');\n\t\t\t} else {\n\t\t\t\tsprintf(&buffer[strlen(buffer)], \"%c%c\", (Data.Value/26) + 'A'-1, (Data.Value % 26) + 'A');\n\t\t\t}\n\t\t\tbreak;\n\n\t}\n\n\treturn(buffer);\n}\n#endif\n\n\n/***********************************************************************************************\n * TeamTypeClass::Detach -- Detach the specified target from this team type.                   *\n *                                                                                             *\n *    This routine is called when some object is about to be removed from the game system and  *\n *    all references to it must be severed. This will check to see if the specified object     *\n *    is a trigger that this team refers to. If so, then the reference will be cleared.        *\n *                                                                                             *\n * INPUT:   target   -- The target object to remove references to.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TeamTypeClass::Detach(TARGET target, bool)\n{\n\tif (Is_Target_TriggerType(target) && Trigger.Is_Valid() && Trigger == As_TriggerType(target)) {\n\t\tTrigger = NULL;\n\t}\n}\n\n\n/***************************************************************************\n * TeamTypeClass::Read_INI -- reads INI data                               *\n *                                                                         *\n * INI entry format:                                                       *\n *      TeamName = Housename,Roundabout,Learning,Suicide,Spy,Mercenary,    *\n *       RecruitPriority,MaxAllowed,InitNum,Fear,                          *\n *       ClassCount,Class:Num,Class:Num,...,                               *\n *       MissionCount,Mission:Arg,Mission:Arg,Mission:Arg,...              *\n *                                                                         *\n * INPUT:                                                                  *\n *      buffer      buffer to hold the INI data                            *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/07/1994 BR : Created.                                              *\n *   02/01/1995 BR : No del team if no classes (editor needs empty teams!) *\n *=========================================================================*/\nvoid TeamTypeClass::Read_INI(CCINIClass & ini)\n{\n\tTeamTypeClass * team;\t\t\t\t\t// Working team pointer.\n\tchar buf[500];\t\t\t\t\t\t\t\t// INI entry buffer\n\n\tint len = ini.Entry_Count(INI_Name());\n\n\t/*\n\t**\tLoop for all team entries, create and fill in.\n\t*/\n\tfor (int index = 0; index < len; index++) {\n\t\tteam = new TeamTypeClass();\n\t\tif (team != NULL) {\n\t\t\tchar const * entry = ini.Get_Entry(INI_Name(), index);\n\t\t\tini.Get_String(INI_Name(), entry, NULL, buf, sizeof(buf));\n\t\t\tteam->Fill_In((char *)entry, buf);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamTypeClass::Fill_In -- fills in trigger from the given INI entry                         *\n *                                                                                             *\n * This routine fills in the given teamtype with the given name, and values from               *\n * the given INI entry.                                                                        *\n *                                                                                             *\n * (This routine is used by the scenario editor, to import teams from the MASTER.INI file.)    *\n *                                                                                             *\n *    INI entry format:                                                                        *\n *      TeamName = Housename,Roundabout,Learning,Suicide,Spy,Mercenary,                        *\n *       RecruitPriority,MaxAllowed,InitNum,Fear,                                              *\n *       ClassCount,Class:Num,Class:Num,...,                                                   *\n *       MissionCount,Mission:Arg,Mission:Arg,Mission:Arg,...                                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      name      mnemonic for the desired trigger                                             *\n *      entry      INI entry to parse                                                          *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/28/1994 BR : Created.                                                                  *\n *   11/29/1995 JLB : Revamped to use new team class.                                          *\n *=============================================================================================*/\nvoid TeamTypeClass::Fill_In(char * name, char * entry)\n{\n\tassert(TeamTypes.ID(this) == ID);\n\n\t/*\n\t**\tSet its name\n\t*/\n\tSet_Name(name);\n\n\tHouse = HousesType(atoi(strtok(entry, \",\")));\n\n\tint code;\n\tswitch (NewINIFormat) {\n\t\tdefault:\n\t\t\tcode = atoi(strtok(NULL, \",\"));\n\t\t\tIsRoundAbout = ((code & 0x0001) != 0);\n\t\t\tIsSuicide = ((code & 0x0002) != 0);\n\t\t\tIsAutocreate = ((code & 0x0004) != 0);\n\t\t\tIsPrebuilt = ((code & 0x0008) != 0);\n\t\t\tIsReinforcable = ((code & 0x0010) != 0);\n\t\t\tbreak;\n\n\t\tcase 0:\n\t\tcase 1:\n\t\t\tIsRoundAbout = atoi(strtok(NULL, \",\"));\n\t\t\tIsSuicide = atoi(strtok(NULL, \",\"));\n\t\t\tIsAutocreate = atoi(strtok(NULL, \",\"));\n\t\t\tIsPrebuilt = atoi(strtok(NULL, \",\"));\n\t\t\tIsReinforcable = atoi(strtok(NULL, \",\"));\n\t\t\tbreak;\n\t}\n\n\tRecruitPriority = atoi(strtok(NULL, \",\"));\n\tInitNum = atoi(strtok(NULL, \",\"));\n\tMaxAllowed = atoi(strtok(NULL, \",\"));\n\tOrigin = atoi(strtok(NULL, \",\"));\n\n\tswitch (NewINIFormat) {\n\t\tdefault:\n\t\t\tTrigger.Set_Raw(atoi(strtok(NULL, \",\")));\n\t\t\tbreak;\n\n\t\tcase 0:\n\t\tcase 1:\n\t\t\t// Throw this token away -- it isn't used.\n\t\t\tstrtok(NULL, \",\");\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tFetch the team member types and quantity values.\n\t*/\n\tClassCount = atoi(strtok(NULL, \",\"));\n\tfor (int index = 0; index < ClassCount; index++) {\n\t\tchar * p1 = strtok(NULL, \",:\");\n\t\tchar * p2 = strtok(NULL, \",:\");\n\t\tTechnoTypeClass const * otype = NULL;\n\n\t\t/*\n\t\t**\tSee if this is an infantry name\n\t\t*/\n\t\tInfantryType i_id = InfantryTypeClass::From_Name(p1);\n\t\tif (i_id != INFANTRY_NONE) {\n\t\t\totype = &InfantryTypeClass::As_Reference(i_id);\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tSee if this is a unit name\n\t\t\t*/\n\t\t\tUnitType u_id = UnitTypeClass::From_Name(p1);\n\t\t\tif (u_id != UNIT_NONE) {\n\t\t\t\totype = &UnitTypeClass::As_Reference(u_id);\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tSee if this is an aircraft name\n\t\t\t\t*/\n\t\t\t\tAircraftType a_id = AircraftTypeClass::From_Name(p1);\n\t\t\t\tif (a_id != AIRCRAFT_NONE) {\n\t\t\t\t\totype = &AircraftTypeClass::As_Reference(a_id);\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSee if this is a vessel name.\n\t\t\t\t\t*/\n\t\t\t\t\tVesselType v_id = VesselTypeClass::From_Name(p1);\n\t\t\t\t\tif (v_id != VESSEL_NONE) {\n\t\t\t\t\t\totype = &VesselTypeClass::As_Reference(v_id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf the name was resolved, add this class\n\t\t*/\n\t\tif (otype) {\n\t\t\tMembers[index].Class = otype;\n\t\t\tMembers[index].Quantity = atoi(p2);\n\t\t} else {\n\t\t\tClassCount--;\n\t\t\tif (index == 0) break;\n\t\t\tindex--;\n\t\t}\n\t}\n\n\t/*\n\t**\tFetch the missions assigned to this team type.\n\t*/\n\tMissionCount = atoi(strtok(NULL, \",\"));\n\tfor (index = 0; index < MissionCount; index++) {\n\t\tMissionList[index].Mission = TeamMissionType(atoi(strtok(NULL, \",:\")));\n\t\tMissionList[index].Data.Value = atoi(strtok(NULL, \",:\"));\n\t}\n\n\tif (NewINIFormat < 2) {\n\t\t/*\n\t\t**\tFetch the trigger ID.\n\t\t*/\n\t\tTrigger.Set_Raw(atoi(strtok(NULL, \",\")));\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamTypeClass::Write_INI -- Write out the team types to the INI database.                   *\n *                                                                                             *\n *    This routine will take all team types and write them out to the INI database specified.  *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database that will hold al the teams.                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   All preexisting team data in the database will be erased by this routine.       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TeamTypeClass::Write_INI(CCINIClass & ini)\n{\n\tini.Clear(\"TeamTypes\");\n\tini.Clear(INI_Name());\n\n\t/*\n\t**\tNow write all the team data out\n\t*/\n\tfor (int index = 0; index < TeamTypes.Count(); index++) {\n//\tfor (int index = TeamTypes.Count()-1; index >= 0; index--) {\n\t\tTeamTypeClass * team = TeamTypes.Ptr(index);\n\t\tchar buf[256];\n\n\t\tbuf[0] = 0;\n\t\tteam->Build_INI_Entry(buf);\n\t\tini.Put_String(INI_Name(), team->IniName, buf);\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamTypeClass::Build_INI_Entry -- Builds the INI entry for this team type.                  *\n *                                                                                             *\n *    This routine is used to build the text string that will go into the INI database for     *\n *    a team of this type. This text string will be parsed back into a team object when the    *\n *    scenario INI is read in.                                                                 *\n *                                                                                             *\n * INPUT:   buf   -- Pointer to a buffer that will hold the team text entry.                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure that the buffer can hold the string build. A size of 80 or so is        *\n *             usually sufficient.                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TeamTypeClass::Build_INI_Entry(char * buf)\n{\n\tint code = 0;\n\tcode |= IsRoundAbout ? 0x0001 : 0;\n\tcode |= IsSuicide ? 0x0002 : 0;\n\tcode |= IsAutocreate ? 0x0004 : 0;\n\tcode |= IsPrebuilt ? 0x0008 : 0;\n\tcode |= IsReinforcable ? 0x0010 : 0;\n\n\t/*\n\t**\tOutput the general data for this team type.\n\t*/\n\tsprintf(buf, \"%d,%d,%d,%d,%d,%d,%d\",\n\t\tHouse,\n\t\tcode,\n\t\tRecruitPriority,\n\t\tInitNum,\n\t\tMaxAllowed,\n\t\tOrigin,\n\t\tTriggerTypes.Logical_ID(Trigger)\n\t\t);\n\tbuf += strlen(buf);\n\n\t/*\n\t**\tFor every class in the team, record the class's name & desired count\n\t*/\n\tsprintf (buf, \",%d\", ClassCount);\n\tbuf += strlen(buf);\n\tfor (int i = 0; i < ClassCount; i++) {\n\t\tsprintf (buf, \",%s:%d\", Members[i].Class->IniName, Members[i].Quantity);\n\t\tbuf += strlen(buf);\n\t}\n\n\t/*\n\t**\tRecord the # of missions, and each mission name & argument value.\n\t*/\n\tsprintf(buf, \",%d\", MissionCount);\n\tbuf += strlen(buf);\n\tfor (i = 0; i < MissionCount; i++) {\n\t\tsprintf (buf, \",%d:%d\", MissionList[i].Mission, MissionList[i].Data.Value);\n\t\tbuf += strlen(buf);\n\t}\n}\n\n\n"
  },
  {
    "path": "CODE/TEAMTYPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TEAMTYPE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TEAMTYPE.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TEAMTYPE_H\n#define TEAMTYPE_H\n\n/*\n**\tTeamMissionType: the various missions that a team can have.\n*/\ntypedef enum TeamMissionType {\n\tTMISSION_NONE=-1,\n\tTMISSION_ATTACK,\t\t\t\t\t// Attack specified quarry type.\n\tTMISSION_ATT_WAYPT,\t\t\t\t// Attack specified waypoint\n\tTMISSION_FORMATION,\t\t\t\t// Change formation of team.\n\tTMISSION_MOVE,\t\t\t\t\t\t// moves to waypoint specified.\n\tTMISSION_MOVECELL,\t\t\t\t// moves to cell # specified.\n\tTMISSION_GUARD,\t\t\t\t\t// works like an infantry's guard mission\n\tTMISSION_LOOP,\t\t\t\t\t\t// loop back to start of mission list\n\tTMISSION_ATTACKTARCOM,\t\t\t// attack tarcom\n\tTMISSION_UNLOAD,\t\t\t\t\t// Unload at current location.\n\tTMISSION_DEPLOY,\t\t\t\t\t// Deploy mobile building type.\n\tTMISSION_HOUND_DOG,\t\t\t\t// Follow nearest friendly unit.\n\tTMISSION_DO,\t\t\t\t\t\t// Do guard, sticky, area guard (mission sticks on this).\n\tTMISSION_SET_GLOBAL,\t\t\t\t// Set global variable.\n\tTMISSION_INVULNERABLE,\t\t\t// Magical invulnerability.\n\tTMISSION_LOAD,\t\t\t\t\t\t// Load onto transport member of team.\n\tTMISSION_SPY,\t\t\t\t\t\t// Spy enter the building at specified waypoint\n\tTMISSION_PATROL,\t\t\t\t\t// Move but look for enemies as well.\n\n\tTMISSION_COUNT,\n\tTMISSION_FIRST=0\n} TeamMissionType;\n\n\n/*\n** Forward declarations.\n*/\nclass TechnoTypeClass;\n\n\n/*\n**\tThis structure contains one team mission value & its argument.\n*/\nclass TeamMissionClass\n{\n\tpublic:\n#if defined(CHEAT_KEYS) || defined(SCENARIO_EDITOR)\n\t\tchar const * Description(int index) const;\n\t\toperator const char * () const {return(Description(0));};\n#endif\n\t\tvoid Draw_It(int index, int x, int y, int width, int height, bool selected, TextPrintType flags);\n\n\t\tTeamMissionType Mission;\t\t// Mission type.\n\t\tunion {\n\t\t\tFormationType Formation;\t// Formation to use.\n\t\t\tQuarryType Quarry;\t\t\t// Combat quarry type.\n\t\t\tMissionType Mission;\t\t\t// General mission orders.\n\t\t\tint Value;\t\t\t\t\t\t// Usually a waypoint number.\n\t\t} Data;\n};\n\n\n/*\n**\tThis class specifies the quantity and type of members desired for the\n**\tteam.\n*/\nclass TeamMemberClass\n{\n\tpublic:\n\t\tint Quantity;\t\t\t\t\t\t\t// Number of objects desired for this type.\n\t\tTechnoTypeClass const * Class;\t// The type of object desired.\n};\n\n\n/*\n**\tTeamTypeClass declaration\n*/\nclass TeamTypeClass : public AbstractTypeClass\n{\n\tpublic:\n\t\tenum TeamTypeClassEnums {\n\t\t\tMAX_TEAM_CLASSCOUNT=5,\n\t\t\tMAX_TEAM_MISSIONS=20\n\t\t};\n\n\t\t/*\n\t\t**\tConstructor/Destructor\n\t\t*/\n\t\tTeamTypeClass(void);\n\t\tTeamTypeClass(NoInitClass const & x) : AbstractTypeClass(x), Trigger(x) {};\n\t\tvirtual ~TeamTypeClass(void) {};\n\n\t\tstatic void * operator new(size_t );\n\t\tstatic void * operator new(size_t, void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\n\t\t/*\n\t\t**\tInitialization: clears all team types in preparation for new scenario\n\t\t*/\n\t\tstatic void Init(void);\n\n\t\t/*\n\t\t**\tFile I/O routines\n\t\t*/\n\t\tvoid Build_INI_Entry(char * buffer);\n\t\tstatic void Read_INI(CCINIClass & ini);\n\t\tvoid Fill_In(char *name, char *entry);\n\t\tstatic void Write_INI(CCINIClass & ini);\n\t\tstatic char * INI_Name(void) {return \"TeamTypes\";};\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\t\tvoid Code_Pointers(void);\n\t\tvoid Decode_Pointers(void);\n\n\t\t/*\n\t\t**\tAs_Pointer gets a pointer to the trigger object give its name\n\t\t*/\n\t\tstatic TeamTypeClass *As_Pointer(char const * name);\n\n\t\t/*\n\t\t**\tProcessing routines\n\t\t*/\n\t\tTeamClass * Create_One_Of(void) const;\n\t\tvoid Destroy_All_Of(void) const;\n\t\tvoid Detach(TARGET target, bool all=true);\n\n\t\t/*\n\t\t**\tUtility routines\n\t\t*/\n\t\tvoid Draw_It(int index, int x, int y, int width, int height, bool selected, TextPrintType flags) const;\n\t\tstatic char const * Name_From_Mission(TeamMissionType order);\n\t\tstatic TeamMissionType Mission_From_Name(char const *name);\n\t\tstatic TeamTypeClass const * Suggested_New_Team(HouseClass * house, long atypes, long utypes, long itypes, long vtypes, bool alerted);\n\t\tstatic TeamTypeClass * From_Name(char const * name);\n\t\tbool Edit(void);\n#if defined(CHEAT_KEYS) || defined(SCENARIO_EDITOR)\n\t\tchar const * Member_Description(void) const;\n\t\tchar const * Description(void) const;\n\t\toperator const char * (void) const {return(Description());};\n#endif\n\n\t\t/*\n\t\t**\tIf this teamtype object is active, then this flag will be true.\n\t\t**\tTeamType objects that are not active are either not yet created or have\n\t\t**\tbeen deleted after fulfilling their action.\n\t\t*/\n\t\tunsigned IsActive:1;\n\n\t\t/*\n\t\t**\tIf RoundAbout, the team avoids high-threat areas\n\t\t*/\n\t\tunsigned IsRoundAbout:1;\n\n\t\t/*\n\t\t**\tIf Suicide, the team won't stop until it achieves its mission or it's\n\t\t**\tdead\n\t\t*/\n\t\tunsigned IsSuicide:1;\n\n\t\t/*\n\t\t**\tIs this team type allowed to be created automatically by the computer\n\t\t**\twhen the appropriate trigger indicates?\n\t\t*/\n\t\tunsigned IsAutocreate:1;\n\n\t\t/*\n\t\t**\tThis flag tells the computer that it should build members to fill\n\t\t**\ta team of this type regardless of whether there actually is a team\n\t\t**\tof this type active.\n\t\t*/\n\t\tunsigned IsPrebuilt:1;\n\n\t\t/*\n\t\t**\tIf this team should allow recruitment of new members, then this flag\n\t\t**\twill be true. A false value results in a team that fights until it\n\t\t**\tis dead. This is similar to IsSuicide, but they will defend themselves.\n\t\t*/\n\t\tunsigned IsReinforcable:1;\n\n\t\t/*\n\t\t**\tA transient team type was created exclusively to bring on reinforcements\n\t\t**\tas a result of some special event. As soon as there are no teams\n\t\t**\texisting of this type, then this team type should be deleted.\n\t\t*/\n\t\tunsigned IsTransient:1;\n\n\t\t/*\n\t\t**\tPriority given the team for recruiting purposes; higher priority means\n\t\t**\tit can steal members from other teams (scale: 0 - 15)\n\t\t*/\n\t\tint RecruitPriority;\n\n\t\t/*\n\t\t**\tInitial # of this type of team\n\t\t*/\n\t\tunsigned char InitNum;\n\n\t\t/*\n\t\t**\tMax # of this type of team allowed at one time\n\t\t*/\n\t\tunsigned char MaxAllowed;\n\n\t\t/*\n\t\t**\tFear level of this team\n\t\t*/\n\t\tunsigned char Fear;\n\n\t\t/*\n\t\t**\tHouse the team belongs to\n\t\t*/\n\t\tHousesType House;\n\n\t\t/*\n\t\t**\tTrigger to assign to each object as it joins this team.\n\t\t*/\n\t\tCCPtr<TriggerTypeClass> Trigger;\n\n\t\t/*\n\t\t**\tThis is the waypoint origin to use when creating this team or\n\t\t**\twhen bringing the team on as a reinforcement.\n\t\t*/\n\t\tWAYPOINT Origin;\n\n\t\t/*\n\t\t**\tThis records the number of teams of this type that are currently\n\t\t**\tactive.\n\t\t*/\n\t\tint Number;\n\n\t\t/*\n\t\t**\tNumber and list of missions that this team will follow.\n\t\t*/\n\t\tint MissionCount;\n\t\tTeamMissionClass MissionList[MAX_TEAM_MISSIONS];\n\n\t\t/*\n\t\t**\tNumber and type of members desired for this team.\n\t\t*/\n\t\tint ClassCount;\n\t\tTeamMemberClass Members[MAX_TEAM_CLASSCOUNT];\n\n\t\tstatic char const * TMissions[TMISSION_COUNT];\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/TECHNO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TECHNO.CPP 5     3/17/97 1:28a Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BASE.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 8, 1994                                                  *\n *                                                                                             *\n *                  Last Update : November 1, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   TechnoClass::AI -- Handles AI processing for techno object.                               *\n *   TechnoClass::Anti_Air -- Determines the anti-aircraft strength of the object.             *\n *   TechnoClass::Anti_Armor -- Determines the anti-armor strength of the object.              *\n *   TechnoClass::Anti_Infantry -- Calculates the anti-infantry strength of this object.       *\n *   TechnoClass::Area_Modify -- Determine the area scan modifier for the cell.                *\n *   TechnoClass::Assign_Destination -- Assigns movement destination to the object.            *\n *   TechnoClass::Assign_Target -- Assigns the targeting computer with specified target.       *\n *   TechnoClass::Base_Is_Attacked -- Handle panic response to base being attacked.            *\n *   TechnoClass::Can_Fire -- Determines if this techno object can fire.                       *\n *   TechnoClass::Can_Player_Fire -- Determines if the player can give this object a fire order*\n *   TechnoClass::Can_Player_Move -- Determines if the object can move be moved by player.     *\n *   TechnoClass::Can_Repair -- Determines if the object can and should be repaired.           *\n *   TechnoClass::Can_Teleport_Here -- Checks cell to see if a valid teleport destination.     *\n *   TechnoClass::Captured -- Handles capturing this object.                                   *\n *   TechnoClass::Clicked_As_Target -- Sets the flash count for this techno object.            *\n *   TechnoClass::Cloaking_AI -- Perform the AI maintenance for a cloaking device.             *\n *   TechnoClass::Combat_Damage -- Fetch the amount of damage infliced by the specified weapon.*\n *   TechnoClass::Crew_Type -- Fetches the kind of crew this object contains.                  *\n *   TechnoClass::Debug_Dump -- Displays the base class data to the monochrome screen.         *\n *   TechnoClass::Desired_Load_Dir -- Fetches loading parameters for this object.              *\n *   TechnoClass::Detach -- Handles removal of target from tracking system.                    *\n *   TechnoClass::Do_Cloak -- Start the object into cloaking stage.                            *\n *   TechnoClass::Do_Shimmer -- Causes this object to shimmer if it is cloaked.                *\n *   TechnoClass::Do_Uncloak -- Cause the stealth tank to uncloak.                             *\n *   TechnoClass::Draw_It -- Draws the health bar (if necessary).                              *\n *   TechnoClass::Draw_Pips -- Draws the transport pips and other techno graphics.             *\n *   TechnoClass::Electric_Zap -- Fires electric zap at the target specified.                  *\n *   TechnoClass::Enter_Idle_Mode -- Object enters its default idle condition.                 *\n *   TechnoClass::Evaluate_Cell -- Determine the value and object of specified cell.           *\n *   TechnoClass::Evaluate_Just_Cell -- Evaluate a cell as a target by itself.                 *\n *   TechnoClass::Evaluate_Object -- Determines score value of specified object.               *\n *   TechnoClass::Exit_Object -- Causes specified object to leave this object.                 *\n *   TechnoClass::Find_Docking_Bay -- Searches for a close docking bay.                        *\n *   TechnoClass::Find_Exit_Cell -- Finds an appropriate exit cell for this object.            *\n *   TechnoClass::Fire_At -- Fires projectile at target specified.                             *\n *   TechnoClass::Fire_Coord -- Determine the coordinate where bullets appear.                 *\n *   TechnoClass::Fire_Direction -- Fetches the direction projectile fire will take.           *\n *   TechnoClass::Get_Ownable -- Fetches the ownable bits for this object.                     *\n *   TechnoClass::Greatest_Threat -- Determines best target given search criteria.             *\n *   TechnoClass::Hidden -- Returns the object back into the hidden state.                     *\n *   TechnoClass::How_Many_Survivors -- Determine the number of survivors to escape.           *\n *   TechnoClass::In_Range -- Determines if specified target is within weapon range.           *\n *   TechnoClass::In_Range -- Determines if specified target is within weapon range.           *\n *   TechnoClass::In_Range -- Determines if the specified coordinate is within range.          *\n *   TechnoClass::Is_Allowed_To_Recloak -- Can this object recloak?                            *\n *   TechnoClass::Is_Allowed_To_Retaliate -- Checks object to see if it can retaliate.         *\n *   TechnoClass::Is_In_Same_Zone -- Determine if specified cell is in same zone as object.    *\n *   TechnoClass::Is_Players_Army -- Determines if this object is part of the player's army.   *\n *   TechnoClass::Is_Ready_To_Cloak -- Determines if this object is ready to begin cloaking.   *\n *   TechnoClass::Is_Ready_To_Random_Animate -- Determines if the object should random animate.*\n *   TechnoClass::Is_Visible_On_Radar -- Is this object visible on player's radar screen?      *\n *   TechnoClass::Is_Weapon_Equipped -- Determines if this object has a combat weapon.         *\n *   TechnoClass::Kill_Cargo -- Destroys any cargo attached to this object.                    *\n *   TechnoClass::Look -- Performs a look around (map reveal) action.                          *\n *   TechnoClass::Mark -- Handles marking of techno objects.                                   *\n *   TechnoClass::Nearby_Location -- Radiates outward looking for clear cell nearby.           *\n *   TechnoClass::Owner -- Who is the owner of this object?                                    *\n *   TechnoClass::Per_Cell_Process -- Handles once-per-cell operations for techno type objects.*\n *   TechnoClass::Pip_Count -- Fetches the number of pips to display on this object.           *\n *   TechnoClass::Player_Assign_Mission -- Assigns a mission as result of player input.        *\n *   TechnoClass::Rearm_Delay -- Calculates the delay before firing can occur.                 *\n *   TechnoClass::Receive_Message -- Handles inbound message as appropriate.                   *\n *   TechnoClass::Record_The_Kill -- Records the death of this object.                         *\n *   TechnoClass::Refund_Amount -- Returns with the money to refund if this object is sold.    *\n *   TechnoClass::Remap_Table -- Fetches the appropriate remap table to use.                   *\n *   TechnoClass::Renovate -- Heal a building to maximum                                       *\n *   TechnoClass::Response_Attack -- Handles the voice response when given attack order.       *\n *   TechnoClass::Response_Move -- Handles the voice response to a movement request.           *\n *   TechnoClass::Response_Select -- Handles the voice response when selected.                 *\n *   TechnoClass::Revealed -- Handles revealing an object to the house specified.              *\n *   TechnoClass::Risk -- Fetches the risk associated with this object.                        *\n *   TechnoClass::Select -- Selects object and checks to see if can be selected.               *\n *   TechnoClass::Set_Mission -- Forced mission set (used by editor).                          *\n *   TechnoClass::Stun -- Prepares the object for removal from the game.                       *\n *   TechnoClass::Take_Damage -- Records damage assessed to this object.                       *\n *   TechnoClass::Target_Something_Nearby -- Handles finding and assigning a nearby target.    *\n *   TechnoClass::TechnoClass -- Constructor for techno type objects.                          *\n *   TechnoClass::Techno_Draw_Object -- General purpose draw object routine.                   *\n *   TechnoClass::Threat_Range -- Returns the range to scan based on threat control.           *\n *   TechnoClass::Tiberium_Load -- Fetches the current tiberium load percentage.               *\n *   TechnoClass::Time_To_Build -- Determines the time it would take to build this.            *\n *   TechnoClass::Unlimbo -- Performs unlimbo process for all techno type objects.             *\n *   TechnoClass::Value -- Fetches the target value for this object.                           *\n *   TechnoClass::Visual_Character -- Determine the visual character of the object.            *\n *   TechnoClass::Weapon_Range -- Determines the maximum range for the weapon.                 *\n *   TechnoClass::What_Action -- Determines action to perform if cell is clicked on.           *\n *   TechnoClass::What_Action -- Determines what action to perform if object is selected.      *\n *   TechnoClass::What_Weapon_Should_I_Use -- Determines what is the best weapon to use.       *\n *   TechnoTypeClass::Cost_Of -- Fetches the cost of this object type.                         *\n *   TechnoTypeClass::Get_Cameo_Data -- Fetches the cameo image for this object type.          *\n *   TechnoTypeClass::Get_Ownable -- Fetches the ownable bits for this object type.            *\n *   TechnoTypeClass::Is_Two_Shooter -- Determines if this object is a double shooter.         *\n *   TechnoTypeClass::Raw_Cost -- Fetches the raw (base) cost of the object.                   *\n *   TechnoTypeClass::Read_INI -- Reads the techno type data from the INI database.            *\n *   TechnoTypeClass::Repair_Cost -- Fetches the cost to repair one step.                      *\n *   TechnoTypeClass::Repair_Step -- Fetches the health to repair one step.                    *\n *   TechnoTypeClass::TechnoTypeClass -- Constructor for techno type objects.                  *\n *   TechnoTypeClass::Time_To_Build -- Fetches the time to build this object.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***************************************************************************\n**\tCloaking control values.\n*/\n#define\tMAX_UNCLOAK_STAGE\t\t38\n\n\n/***************************************************************************\n**\tThese are the pointers to the special shape data that the units may need.\n*/\nvoid const * TechnoTypeClass::WakeShapes = 0;\nvoid const * TechnoTypeClass::TurretShapes = 0;\nvoid const * TechnoTypeClass::SamShapes = 0;\nvoid const * TechnoTypeClass::MGunShapes = 0;\n\n//Xlat Tables for French and German\n// For name overriding\n//#define NEWNAMES  22\n#ifdef GERMAN\nconst char* NewName[] = {\n\t\"Scout Ant\",\t  \t\t\t\"Kundschafter-Ameise\",\n\t\"Warrior Ant\",    \t\t\"Krieger-Ameise\",\n\t\"Fire Ant\",\t  \t\t\t\t\"Feuer-Ameise\",\n\t\"Queen Ant\",\t  \t\t\t\"Ameisenknigin\",\n\t\"ATS\",\t\t\t\t\t\t\"Angriffs-U-Boot\",\n\t\"Tesla Tank\",\t  \t\t\t\"Telsapanzer\",\n\t\"Volkov\",  \t\t\t\t\t\"Modell Volkov\",\n\t\"Chitzkoi\", \t\t\t\t\"Roboterhund\",\n\t\"Stavros\",\t\t\t\t\t\"Stavros\",\n\t\"F-A Longbow\",\t\t\t\t\"Jagdhubschrauber Longbow\",\n\t\"Civilian Specialist\",\t\"Wissenschaftler\",\n\t\"Alloy Facility\",\t\t\t\"Legierungswerk\",\n\tNULL,\n\t};\n\n#endif\n#ifdef FRENCH\nconst char* NewName[] = {\n\t\"Scout Ant\",\t  \t\t\t\"Fourmi de Reconnaissance\",\n\t\"Warrior Ant\",    \t\t\"Fourmi Guerrire\",\n\t\"Fire Ant\",\t  \t\t\t\t\"Fourmi Lance-Flammes\",\n\t\"Queen Ant\",\t  \t\t\t\"Reine des Fourmis\",\n\t\"ATS\", \t\t\t\t\t\t\"SMTA\",\n\t\"Tesla Tank\",\t  \t\t\t\"Tank Tesla\",\n\t\"Volkov\",  \t\t\t\t\t\"Volkov\",\n\t\"Chitzkoi\", \t\t\t\t\"Cyber-Chien\",\n\t\"Stavros\",\t\t\t\t\t\"Stavros\",\n\t\"F-A Longbow\",\t\t\t\t\"HAA (Hlicoptre d'Assaut Avanc)\",\n\t\"Civilian Specialist\",\t\"Spcialiste Civil\",\n\t\"Alloy Facility\",\t\t\t\"Usine Mtallurgique\",\n\tNULL,\n\t};\n\n#endif\n\n\n/***************************************************************************\n**\tWhich shape to use depending on which facing is controlled by these arrays.\n*/\nint const TechnoClass::BodyShape[32] = {0,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1};\n\n\n/***********************************************************************************************\n * TechnoClass::Is_Players_Army -- Determines if this object is part of the player's army.     *\n *                                                                                             *\n *    The player's army is considered to be all those mobile units that can be selected        *\n *    and controlled by the player (they may or may not have weapons in the traditional        *\n *    sense).                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is this object part of the player's selectable controllable army?            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::Is_Players_Army(void) const\n{\n\t/*\n\t**\tAn object that is dead (or about to be) is not considered part of\n\t**\tthe player's army.\n\t*/\n\tif (Strength <= 0) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the object is not yet on the map or is otherwise indisposed, then\n\t**\tdon't consider it.\n\t*/\n\tif (IsInLimbo || !IsLocked) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tBuildings, although sometimes serving a combat purpose, are not part\n\t**\tof the player's army.\n\t*/\n\tif (What_Am_I() == RTTI_BUILDING) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf not discoverd by the player, then don't consider it part of the\n\t**\tplayer's army (yet).\n\t*/\n\tif (!IsDiscoveredByPlayer) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf not selectable, then not really part of the player's active army.\n\t*/\n\tif (!Techno_Type_Class()->IsSelectable) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf not under player control, then it isn't part of the player's army.\n\t*/\n\tif (!House->IsPlayerControl) {\n\t\treturn(false);\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Can_Teleport_Here -- Checks cell to see if a valid teleport destination.       *\n *                                                                                             *\n *    Use this routine to examine the cell specified and if the cell could be a valid          *\n *    destination for a teleport, then return true.                                            *\n *                                                                                             *\n * INPUT:   cell  -- The cell to examine as a possible legal teleport destination.             *\n *                                                                                             *\n * OUTPUT:  bool; Is the specified cell a legal teleport destination?                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::Can_Teleport_Here(CELL cell) const\n{\n\t/*\n\t**\tInfantry are never allowed to teleport.\n\t*/\n\tif (What_Am_I() == RTTI_INFANTRY) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tThe destination cell must be on the playfield.\n\t*/\n\tif (!Map.In_Radar(cell)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tTeleporting directly onto the flag spot is not allowed. This is due to the\n\t**\trequirement that entering that location must proceed under normal channels.\n\t*/\n\tif (Map[cell].Overlay == OVERLAY_FLAG_SPOT) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tDetermine if the object could enter the cell by normal means. If the\n\t**\tcell is impassable, then it can't be teleported there.\n\t*/\n\tTechnoTypeClass const * ttype = Techno_Type_Class();\n\tif (!Map[cell].Is_Clear_To_Move(ttype->Speed, true, true, -1, ttype->Speed == SPEED_FLOAT ? MZONE_WATER : MZONE_NORMAL)) {\n\t\treturn(false);\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::What_Weapon_Should_I_Use -- Determines what is the best weapon to use.         *\n *                                                                                             *\n *    This routine will compare the weapons this object is equipped with verses the            *\n *    candidate target object. The best weapon to use against the target will be returned.     *\n *    Special emphasis is given to weapons that can fire on the target without requiring       *\n *    this object to move within range.                                                        *\n *                                                                                             *\n * INPUT:   target   -- The candidate target to determine which weapon is best against.        *\n *                                                                                             *\n * OUTPUT:  Returns with an identifier the specifies what weapon to use against the target.    *\n *          The return value will be \"0\" for the primary weapon and \"1\" for the secondary.     *\n *                                                                                             *\n * WARNINGS:   This routine is called very frequently. It should be as efficient as possible.  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoClass::What_Weapon_Should_I_Use(TARGET target) const\n{\n\tif (!Target_Legal(target)) return(0);\n\n\t/*\n\t**\tFetch the armor of the candidate target object. Presume that if the target\n\t**\tis not an object, then its armor is equivalent to wood. Who knows why?\n\t*/\n\tArmorType armor = ARMOR_WOOD;\n\tif (Is_Target_Object(target)) {\n\t\tarmor = As_Object(target)->Class_Of().Armor;\n\t}\n\n\tTechnoTypeClass const * ttype = Techno_Type_Class();\n\n\t/*\n\t**\tGet the value of the primary weapon verses the candidate target. Increase the\n\t**\tvalue of the weapon if it happens to be in range.\n\t*/\n\tint w1 = 0;\n\tWeaponTypeClass const * wptr = ttype->PrimaryWeapon;\n\tif (wptr != NULL && wptr->WarheadPtr != NULL) w1 = wptr->WarheadPtr->Modifier[armor] * 1000;\n\tif (In_Range(target, 0)) w1 *= 2;\n\tFireErrorType ok = Can_Fire(target, 0);\n\tif (ok == FIRE_CANT || ok == FIRE_ILLEGAL) w1 = 0;\n\n\t/*\n\t**\tCalculate a similar value for the secondary weapon.\n\t*/\n\tint w2 = 0;\n\twptr = ttype->SecondaryWeapon;\n\tif (wptr != NULL && wptr->WarheadPtr != NULL) w2 = wptr->WarheadPtr->Modifier[armor] * 1000;\n\tif (In_Range(target, 1)) w2 *= 2;\n\tok = Can_Fire(target, 1);\n\tif (ok == FIRE_CANT || ok == FIRE_ILLEGAL) w2 = 0;\n\n\t/*\n\t**\tReturn with the weapon identifier that should be used to fire upon the\n\t**\tcandidate target.\n\t*/\n\tif (w2 > w1) return(1);\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::How_Many_Survivors -- Determine the number of survivors to escape.             *\n *                                                                                             *\n *    This routine will determine the number of survivors that should run from this object     *\n *    when it is destroyed.                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the maximum number of survivors that should run from this object      *\n *          when the object gets destroyed.                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoClass::How_Many_Survivors(void) const\n{\n\tif (Techno_Type_Class()->IsCrew) {\n\t\treturn(1);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Combat_Damage -- Fetch the amount of damage infliced by the specified weapon.  *\n *                                                                                             *\n *    This routine will examine the specified weapon of this object and determine how much     *\n *    damage it could inflict -- best case.                                                    *\n *                                                                                             *\n * INPUT:   which -- Which weapon to consider. If -1 is specified, then the average of both    *\n *                   weapon types (if present) is returned.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the combat damage that could be inflicted by the specified weapon.    *\n *                                                                                             *\n * WARNINGS:   This routine could return a negative number if a medic is scanned.              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoClass::Combat_Damage(int which) const\n{\n\tTechnoTypeClass const * ttype = Techno_Type_Class();\n\n\tint divisor = 0;\n\tint value = 0;\n\n\tif (which == 0 || which == -1) {\n\t\tif (ttype->PrimaryWeapon != NULL) {\n\t\t\tvalue += ttype->PrimaryWeapon->Attack;\n\t\t\tdivisor += 1;\n\t\t}\n\t}\n\n\tif (which == 1 || which == -1) {\n\t\tif (ttype->SecondaryWeapon != NULL) {\n\t\t\tvalue += ttype->SecondaryWeapon->Attack;\n\t\t\tdivisor += 1;\n\t\t}\n\t}\n\n\tif (divisor > 1) {\n\t\treturn(value / divisor);\n\t}\n\treturn(value);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Is_Allowed_To_Recloak -- Can this object recloak?                              *\n *                                                                                             *\n *    Determine is this object can recloak now and returns that info. Usually the answer is    *\n *    yes, but it can be overridden be derived classes.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Can this object recloak now? (presumes it has the ability to cloak)          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::Is_Allowed_To_Recloak(void) const\n{\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Fire_Coord -- Determine the coordinate where bullets appear.                   *\n *                                                                                             *\n *    This routine will determine the coordinate to use when this object fires. The coordinate *\n *    is the location where bullets appear (or fire effects appear) when the object fires      *\n *    its weapon.                                                                              *\n *                                                                                             *\n * INPUT:   which -- Which weapon is the coordinate to be calculated for? 0 means primary      *\n *                   weapon, 1 means secondary weapon.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate that any bullets fired from the specified weapon       *\n *          should appear.                                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE TechnoClass::Fire_Coord(int which) const\n{\n\tassert(IsActive);\n\n\tDirType dir = Turret_Facing();\n\tTechnoTypeClass const * tclass = Techno_Type_Class();\n\n\tint dist = 0;\n\tint lateral = 0;\n\tif (which == 0) {\n\t\tdist = tclass->PrimaryOffset;\n\t\tlateral = tclass->PrimaryLateral;\n\t} else {\n\t\tdist = tclass->SecondaryOffset;\n\t\tlateral = tclass->SecondaryLateral;\n\t}\n\n\tCOORDINATE coord = Coord_Move(Center_Coord(), DIR_N, tclass->VerticalOffset + Height);\n\tif (IsSecondShot) {\n\t\tcoord = Coord_Move(coord, (DirType)(dir+DIR_E), lateral);\n\t} else {\n\t\tcoord = Coord_Move(coord, (DirType)(dir+DIR_W), lateral);\n\t}\n\tcoord = Coord_Move(coord, dir, dist);\n\n\treturn(coord);\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * TechnoClass::Debug_Dump -- Displays the base class data to the monochrome screen.           *\n *                                                                                             *\n *    This routine is used to dump the status of the object class to the monochrome screen.    *\n *    This display can be used to track down or prevent bugs.                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(IsActive);\n\tmono->Set_Cursor(10, 7);mono->Printf(\"%2d\", Fetch_Rate());\n\tmono->Set_Cursor(14, 7);mono->Printf(\"%2d\", Fetch_Stage());\n\tmono->Set_Cursor(49, 1);mono->Printf(\"%3d\", Ammo);\n\tmono->Set_Cursor(71, 1);mono->Printf(\"$%4d\", PurchasePrice);\n\tmono->Set_Cursor(54, 1);mono->Printf(\"%3d\", (long)Arm);\n\tif (Is_Something_Attached()) {\n\t\tmono->Set_Cursor(1, 5);mono->Printf(\"%08X\", Attached_Object());\n\t}\n\tif (Target_Legal(TarCom)) {\n\t\tmono->Set_Cursor(29, 3);mono->Printf(\"%08X\", TarCom);\n\t}\n\tif (Target_Legal(SuspendedTarCom)) {\n\t\tmono->Set_Cursor(38, 3);mono->Printf(\"%08X\", SuspendedTarCom);\n\t}\n\tif (Target_Legal(ArchiveTarget)) {\n\t\tmono->Set_Cursor(69, 5);mono->Printf(\"%08X\", ArchiveTarget);\n\t}\n\tmono->Set_Cursor(47, 3);mono->Printf(\"%02X:%02X\", PrimaryFacing.Current(), PrimaryFacing.Desired());\n\tmono->Set_Cursor(64, 1);mono->Printf(\"%d(%d)\", Cloak, CloakingDevice);\n\n\tmono->Fill_Attrib(14, 15, 12, 1, IsUseless ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(14, 16, 12, 1, IsTickedOff ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(14, 17, 12, 1, IsCloakable ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(27, 13, 12, 1, IsLeader ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(27, 14, 12, 1, IsALoaner ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(27, 15, 12, 1, IsLocked ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(27, 16, 12, 1, IsInRecoilState ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(27, 17, 12, 1, IsTethered ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(40, 13, 12, 1, IsOwnedByPlayer ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(40, 14, 12, 1, IsDiscoveredByPlayer ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(40, 15, 12, 1, IsDiscoveredByComputer ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(40, 16, 12, 1, IsALemon ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Set_Cursor(47, 17);mono->Printf(\"%3d\", (long)IronCurtainCountDown);\n\tmono->Fill_Attrib(40, 17, 12, 1, IronCurtainCountDown > 0 ? MonoClass::INVERSE : MonoClass::NORMAL);\n\n\tRadioClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * TechnoClass::TechnoClass -- Default constructor for techno objects.                         *\n *                                                                                             *\n *    This default constructor for techno objects is used to reset all internal variables to   *\n *    their default state.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTechnoClass::TechnoClass(RTTIType rtti, int id, HousesType house) :\n\tRadioClass(rtti, id),\n\tIsUseless(false),\n\tIsTickedOff(false),\n\tIsCloakable(false),\n\tIsLeader(false),\n\tIsALoaner(false),\n\tIsLocked(false),\n\tIsInRecoilState(false),\n\tIsTethered(false),\n\tIsOwnedByPlayer(false),\n\tIsDiscoveredByPlayer(false),\n\tIsDiscoveredByComputer(false),\n\tIsALemon(false),\n\tIsSecondShot(true),\n\tArmorBias(1),\n\tFirepowerBias(1),\n\tIdleTimer(0),\n\tIronCurtainCountDown(0),\n\tSpiedBy(0),\n\tArchiveTarget(TARGET_NONE),\n\tHouse(HouseClass::As_Pointer(house)),\n\tCloak(UNCLOAKED),\n\tTarCom(TARGET_NONE),\n\tSuspendedTarCom(TARGET_NONE),\n\tPrimaryFacing(DIR_N),\n\tArm(0),\n\tAmmo(-1),\n\tPurchasePrice(0)\n{\n\tIsOwnedByPlayer = (PlayerPtr == House);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Time_To_Build -- Determines the time it would take to build this.              *\n *                                                                                             *\n *    Use this routine to determine the amount of time it would take to build an object of     *\n *    this type.                                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the time it should take (unmodified by outside factors) to build      *\n *          this object. The time is expressed in game frames.                                 *\n *                                                                                             *\n * WARNINGS:   The time will usually be modified by power status and handicap rating for the   *\n *             owning house. The value returned is merely the raw unmodified time to build.    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *   09/27/1996 JLB : Takes into account the power availability.                               *\n *=============================================================================================*/\n//#define UNIT_BUILD_BIAS fixed(5,4)\n//#define UNIT_BUILD_BIAS fixed(6,4)\n#define UNIT_BUILD_BIAS fixed(1,1)\n//#define UNIT_BUILD_BIAS fixed(5,1)\n\nextern int UnitBuildPenalty;\n\nint TechnoClass::Time_To_Build(void) const\n{\n\tint val = Class_Of().Time_To_Build();\n\n#ifdef FIXIT_VERSION_3\n\tif (Session.Type == GAME_NORMAL ) {\n#else\n\tif (Session.Type == GAME_NORMAL ||\n\t\t\t\t\tPlayingAgainstVersion == VERSION_RED_ALERT_104 ||\n\t\t \t\t\tPlayingAgainstVersion == VERSION_RED_ALERT_107){\n#endif\n\t\tval *= House->BuildSpeedBias;\n\t}else{\n\t\tif (What_Am_I() == RTTI_BUILDING || What_Am_I() == RTTI_INFANTRY) {\n\t\t\tval *= House->BuildSpeedBias;\n\t\t} else {\n\t\t\tval *= House->BuildSpeedBias * fixed (UnitBuildPenalty, 100);\t//UNIT_BUILD_BIAS;\n\t\t}\n\t}\n\n\n\t/*\n\t**\tAdjust the time to build based on the power output of the owning house.\n\t*/\n\tfixed power = House->Power_Fraction();\n\tif (power > 1) power = 1;\n\tif (power < 1 && power > fixed::_3_4) power = fixed::_3_4;\n\tif (power < fixed::_1_2) power = fixed::_1_2;\n\tpower.Inverse();\n\tval *= power;\n\n\tint divisor = House->Factory_Count(What_Am_I());\n\tif (divisor != 0) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// Hack: allow the multiple-factory bonus, but only up to two factories if\n//\t\t\tthis is an AM<->AM game.\n\t\tif(NewUnitsEnabled) {\n\t\t\tval /= min(divisor,2);\n\t\t} else {\n\t\t\tval /= divisor;\n\t\t}\n#else\n\t\tval /= divisor;\n#endif\n\t}\n\treturn(val);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Is_Visible_On_Radar -- Is this object visible on player's radar screen?        *\n *                                                                                             *\n *    Use this routine to determine if this object should be visible on the player's radar     *\n *    screen. This routine doesn't take into consideration mapped terrain or whether the       *\n *    radar is active. It merely checks to see that if all else is functioning correctly,      *\n *    is this unit invisible or visible on the radar map. Typically, cloaked vehicles will     *\n *    not be visible.                                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is this object nominally visible on the player's radar screen?               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::Is_Visible_On_Radar(void) const\n{\n\t/*\n\t** Hack: MRJ is invisible to radar, unless it's allied with the player.\n\t*/\n\tif (What_Am_I() == RTTI_UNIT) {\n\t\tif(*((UnitClass *)this) == UNIT_MRJ) {\n\t\t\tif(!House->Is_Ally(PlayerPtr)) {\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t}\n\t}\n\tif (!Techno_Type_Class()->IsInvisible && (Cloak != CLOAKED || House->Is_Ally(PlayerPtr))) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Revealed -- Handles revealing an object to the house specified.                *\n *                                                                                             *\n *    When a unit moves out from under the shroud or when it gets delivered into already       *\n *    explored terrain, then it must be \"revealed\". Objects that are revealed may be           *\n *    announced to the player. The discovered bit updated accordingly.                         *\n *                                                                                             *\n * INPUT:   house -- The house that this object is revealed to.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *   12/27/1994 JLB : Discovered trigger event processing.                                     *\n *=============================================================================================*/\nbool TechnoClass::Revealed(HouseClass * house)\n{\n\tassert(IsActive);\n\n\tif (house == PlayerPtr && IsDiscoveredByPlayer) return(false);\n\tif (house != PlayerPtr) {\n\t\tif (IsDiscoveredByComputer) return(false);\n\t\tIsDiscoveredByComputer = true;\n\t}\n\n\tif (RadioClass::Revealed(house)) {\n\n\t\t/*\n\t\t**\tAn enemy object that is discovered will go into hunt mode if\n\t\t**\tits current mission is to ambush.\n\t\t*/\n\t\tif (!house->IsHuman && Mission == MISSION_AMBUSH) {\n\t\t\tAssign_Mission(MISSION_HUNT);\n\t\t}\n\n\t\tif (house == PlayerPtr) {\n\t\t\tIsDiscoveredByPlayer = true;\n\n\t\t\tif (!IsOwnedByPlayer) {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf there is a trigger event associated with this object, then process\n\t\t\t\t**\tit for discovery purposes.\n\t\t\t\t*/\n\t\t\t\tif (!ScenarioInit && Trigger.Is_Valid()) {\n\t\t\t\t\tTrigger->Spring(TEVENT_DISCOVERED, this);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAlert the enemy house to presence of the friendly side.\n\t\t\t\t*/\n\t\t\t\tHouse->IsDiscovered = true;\n\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tA newly revealed object will always perform a look operation.\n\t\t\t\t*/\n\t\t\t\tLook();\n\t\t\t}\n\t\t} else {\n\t\t\tIsDiscoveredByComputer = true;\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Hidden -- Returns the object back into the hidden state.                       *\n *                                                                                             *\n *    This routine is called for every object that returns to the darkness shroud or when      *\n *    it gets destroyed. This also occurs when an object enters another (such as infantry      *\n *    entering a transport helicopter).                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Hidden(void)\n{\n\tassert(IsActive);\n\n\tif (!IsDiscoveredByPlayer) return;\n\tif (!House->IsHuman) {\n\t\tIsDiscoveredByPlayer = false;\n\t}\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Mark -- Handles marking of techno objects.                                     *\n *                                                                                             *\n *    On the Techno-level, marking handles transmission of the redraw command to any object    *\n *    that it is 'connected' with. This only occurs during loading and unloading.              *\n *                                                                                             *\n * INPUT:   mark  -- The marking method. This routine just passes this on to base classes.     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::Mark(MarkType mark)\n{\n\tassert(IsActive);\n\n\tif (RadioClass::Mark(mark)) {\n\n\t\t/*\n\t\t**\tWhen redrawing an object, if there is another object tethered to this one,\n\t\t**\tredraw it as well.\n\t\t*/\n\t\tif (IsTethered) {\n\t\t\tTransmit_Message(RADIO_REDRAW);\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Receive_Message -- Handles inbound message as appropriate.                     *\n *                                                                                             *\n *    This routine is used to handle inbound radio messages. It only handles those messages    *\n *    that deal with techno objects. Typically, these include loading and unloading.           *\n *                                                                                             *\n * INPUT:   from     -- Pointer to the originator of the radio message.                        *\n *                                                                                             *\n *          message  -- The inbound radio message.                                             *\n *                                                                                             *\n *          param    -- Reference to optional parameter that might be used to transfer         *\n *                      more information than is possible with the simple radio message        *\n *                      type.                                                                  *\n *                                                                                             *\n * OUTPUT:  Returns with the radio response.                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *   06/17/1995 JLB : Handles tether contact messages.                                         *\n *=============================================================================================*/\nRadioMessageType TechnoClass::Receive_Message(RadioClass * from, RadioMessageType message, long & param)\n{\n\tassert(IsActive);\n\n\tswitch (message) {\n\n\t\t/*\n\t\t**\tJust received instructions to attack the specified target.\n\t\t*/\n\t\tcase RADIO_ATTACK_THIS:\n\t\t\tif (Techno_Type_Class()->PrimaryWeapon != NULL) {\n\t\t\t\tAssign_Target(param);\n\t\t\t\tAssign_Mission(MISSION_ATTACK);\n\t\t\t\treturn(RADIO_ROGER);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tEstablish a tethered connection to the object in radio contact.\n\t\t*/\n\t\tcase RADIO_TETHER:\n\t\t\tif (!IsTethered) {\n\t\t\t\tIsTethered = true;\n\t\t\t\tTransmit_Message(RADIO_TETHER, from);\n\t\t\t\treturn(RADIO_ROGER);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tBreak the tethered connection to the object in radio contact.\n\t\t*/\n\t\tcase RADIO_UNTETHER:\n\t\t\tif (IsTethered) {\n\t\t\t\tIsTethered = false;\n\t\t\t\tTransmit_Message(RADIO_UNTETHER, from);\n\t\t\t\treturn(RADIO_ROGER);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tA tethered unit has reached it's destination. All is\n\t\t**\tclear, so radio contact can be broken.\n\t\t*/\n\t\tcase RADIO_UNLOADED:\n\t\t\tTransmit_Message(RADIO_UNTETHER, from);\n\t\t\treturn(Transmit_Message(RADIO_OVER_OUT, from));\n\n\t\t/*\n\t\t**\tWhen this message is received, it means that the other object\n\t\t**\thas already turned its radio off. Turn this radio off as well.\n\t\t*/\n\t\tcase RADIO_OVER_OUT:\n\t\t\tTransmit_Message(RADIO_UNTETHER, from);\n\t\t\tRadioClass::Receive_Message(from, message, param);\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t**\tRequest to be informed when unloaded. This message is transmitted\n\t\t**\tby the transport unit to the transported unit as it is about to be\n\t\t**\tunloaded. It is saying, \"All is clear. Drive off now.\"\n\t\t*/\n\t\tcase RADIO_UNLOAD:\n\t\tcase RADIO_BACKUP_NOW:\n\t\tcase RADIO_HOLD_STILL:\n\t\t\tTransmit_Message(RADIO_TETHER, from);\n\t\t\tRadioClass::Receive_Message(from, message, param);\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t**\tHandle reloading one ammo point for this unit.\n\t\t*/\n\t\tcase RADIO_RELOAD:\n\t\t\tif (Ammo == Techno_Type_Class()->MaxAmmo) return(RADIO_NEGATIVE);\n/*BG*/\tMark(MARK_CHANGE_REDRAW);\n\t\t\tAmmo++;\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t**\tHandle repair of this unit.\n\t\t*/\n\t\tcase RADIO_REPAIR:\n\t\t\t/*\n\t\t\t** If it's a mine layer, re-arm him if he's empty. This always takes precedence\n\t\t\t**\tover repair, since this operation is free.\n\t\t\t*/\n\t\t\tif (What_Am_I() == RTTI_UNIT && *((UnitClass *)this) == UNIT_MINELAYER && ((UnitClass *)this)->Ammo < ((UnitClass *)this)->Class->MaxAmmo) {\n\t\t\t\t((UnitClass *)this)->Ammo = ((UnitClass *)this)->Class->MaxAmmo;\n\t\t\t\treturn(RADIO_NEGATIVE);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDetermine if this unit can be repaired becaause it is under strength. If so, then\n\t\t\t**\tproceed with the repair process.\n\t\t\t*/\n\t\t\tif (Health_Ratio() < Rule.ConditionGreen) {\n\t\t\t\tint cost = Techno_Type_Class()->Repair_Cost();\n\t\t\t\tcost = max(cost, 1);\n\t\t\t\tint step = Techno_Type_Class()->Repair_Step();\n\t\t\t\tstep = max(step, 1);\n\n\t\t\t\t/*\n\t\t\t\t**\tIf there is sufficient money to repair the unit one step, then do so.\n\t\t\t\t**\tOtherwise return with a \"can't complete\" radio response.\n\t\t\t\t*/\n\t\t\t\tif (House->Available_Money() >= cost) {\n\t\t\t\t\tHouse->Spend_Money(cost);\n\t\t\t\t\tStrength += step;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tReturn with either an all ok or mission accomplished radio message. This\n\t\t\t\t\t**\tlets the repairing object know if it should abort the repair control process\n\t\t\t\t\t**\tor continue it.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Health_Ratio() < Rule.ConditionGreen) {\n\t\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tStrength = Techno_Type_Class()->MaxStrength;\n\t\t\t\t\t\treturn(RADIO_ALL_DONE);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn(RADIO_CANT);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn(RADIO_NEGATIVE);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(RadioClass::Receive_Message(from, message, param));\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Per_Cell_Process -- Handles once-per-cell operations for techno type objects.  *\n *                                                                                             *\n *    This routine handles marking a game object as not a loaner. It is set only if the unit   *\n *    is not player owned and is on the regular map. This is necessary so that enemy objects   *\n *    can exist off-map but as soon as they move onto the map, are flagged so that can never   *\n *    leave it again.                                                                          *\n *                                                                                             *\n * INPUT:   why   -- Specifies the circumstances under which this routine was called.          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *   10/26/94   JLB : Handles scanner units.                                                   *\n *   12/27/1994 JLB : Checks for an processes any trigger in cell.                             *\n *=============================================================================================*/\nvoid TechnoClass::Per_Cell_Process(PCPType why)\n{\n\tassert(IsActive);\n\n\tif (why == PCP_END) {\n\t\tCELL cell = Coord_Cell(Center_Coord());\n\n\t\t/*\n\t\t**\tWhen enemy units enter the proper map area from off map, they are\n\t\t**\tflagged so that they won't travel back off the map again.\n\t\t*/\n\t\tif (!IsLocked && Map.In_Radar(cell)) {\n\t  \t\tIsLocked = true;\n\t\t}\n\n\t\t/*\n\t\t**\tIf this object somehow moves into mapped terrain, but is not yet\n\t\t**\tdiscovered, then flag it to be discovered.\n\t\t*/\n\t\tif (!IsDiscoveredByPlayer && Map[cell].IsVisible) {\n\t\t\tRevealed(PlayerPtr);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Draw_It -- Draws the health bar (if necessary).                                *\n *                                                                                             *\n *    This routine will draw the common elements for techno type objects. This element is      *\n *    the health bar. The main game object has already been rendered by the time this          *\n *    routine is called.                                                                       *\n *                                                                                             *\n * INPUT:   x,y   -- The coordinate of the center of the unit.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *   10/26/94   JLB : Knows about radar scanned cells.                                         *\n *   12/13/1994 JLB : Clips health bar against map edge.                                       *\n *   01/23/1995 JLB : Dynamic selected object rectangle.                                       *\n *=============================================================================================*/\nvoid TechnoClass::Draw_It(int x, int y, WindowNumberType window) const\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tTells the door logic that it has been drawn.\n\t*/\n\t((TechnoClass *)this)->Clear_Redraw_Flag();\n\n\tif (IsSelected) {\n\t\tGraphicViewPortClass draw_window(\tLogicPage->Get_Graphic_Buffer(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWX] + LogicPage->Get_XPos(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWY] + LogicPage->Get_YPos(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWWIDTH],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWHEIGHT]);\n\n\n\t\t/*\n\t\t**\tThe infantry select box should be a bit higher than normal.\n\t\t*/\n\t\tif (What_Am_I() == RTTI_INFANTRY) {\n\t\t\ty -= 6;\n\t\t}\n\n\t\tif (What_Am_I() == RTTI_BUILDING && ((BuildingTypeClass const &)Class_Of()).Type == STRUCT_BARRACKS) {\n\t\t\ty -= 5;\n\t\t}\n\n\t\t/*\n\t\t**\tFetch the dimensions of the object. These dimensions will be used to draw\n\t\t**\tthe selection box and the health bar.\n\t\t*/\n\t\tint width,height;\n\t\tClass_Of().Dimensions(width, height);\n\n\t\tif (Strength && (House->Is_Ally(PlayerPtr) || Rule.IsHealthBar)) {\n\t\t\tfixed\tratio = Health_Ratio();\n\t\t\tint\tpwidth;\t\t// Pixel width of bar interior.\n\t\t\tint\tcolor;\t\t// The color to give the interior of the bargraph.\n\n\t\t\tint xx = x-width/2;\n\t\t\tint yy = y-(height/2);\n\n\t\t\t/*\n\t\t\t**\tDraw the outline of the bargraph.\n\t\t\t*/\n\t\t\tdraw_window.Remap(xx+1, yy+1, width-1, 3-1, Map.FadingShade);\n\t\t\tdraw_window.Draw_Rect(xx, yy, xx+width-1, yy+3, BLACK);\n\n\t\t\t/*\n\t\t\t**\tDetermine the width of the interior strength\n\t\t\t**\tgraph.\n\t\t\t*/\n\t\t\tpwidth = (width-2) * ratio;\n\n\t\t\tpwidth = Bound(pwidth, 1, width-2);\n\n\t\t\tcolor = LTGREEN;\n\t\t\tif (ratio <= Rule.ConditionYellow) {\n\t\t\t\tcolor = YELLOW;\n\t\t\t}\n\t\t\tif (ratio <= Rule.ConditionRed) {\n\t\t\t\tcolor = RED;\n\t\t\t}\n\t\t\tdraw_window.Fill_Rect(xx+1, yy+1, xx+pwidth, yy+(3-1), color);\n\t\t}\n\n\t\t/*\n\t\t**\tDraw the selected object graphic.\n\t\t*/\n\t\tif (IsSelected) {\n\t\t\tint lx = width/2;\n\t\t\tint ly = height/2;\n\t\t\tint dx = width/5;\n\t\t\tint dy = height/5;\n\t\t\tint fudge = (House->Is_Ally(PlayerPtr) || Rule.IsHealthBar) ? 4 : 0;\n\t\t\tif (What_Am_I() == RTTI_VESSEL) {\n\t\t\t\tlx = width / 2;\n\t\t\t}\n\n\t\t\t// Upper left corner.\n\t\t\tdraw_window.Draw_Line(x-lx, fudge+y-ly, x-lx+dx, fudge+y-ly, WHITE);\n\t\t\tdraw_window.Draw_Line(x-lx, fudge+y-ly, x-lx, fudge+y-ly+dy, WHITE);\n\n\t\t\t// Upper right corner.\n\t\t\tdraw_window.Draw_Line(x+lx, fudge+y-ly, x+lx-dx, fudge+y-ly, WHITE);\n\t\t\tdraw_window.Draw_Line(x+lx, fudge+y-ly, x+lx, fudge+y-ly+dy, WHITE);\n\n\t\t\t// Lower right corner.\n\t\t\tdraw_window.Draw_Line(x+lx, y+ly, x+lx-dx, y+ly, WHITE);\n\t\t\tdraw_window.Draw_Line(x+lx, y+ly, x+lx, y+ly-dy, WHITE);\n\n\t\t\t// Lower left corner.\n\t\t\tdraw_window.Draw_Line(x-lx, y+ly, x-lx+dx, y+ly, WHITE);\n\t\t\tdraw_window.Draw_Line(x-lx, y+ly, x-lx, y+ly-dy, WHITE);\n\t\t\tif (House->Is_Ally(PlayerPtr) || (SpiedBy & (1<<(PlayerPtr->Class->House)))) {\n\t\t\t\tDraw_Pips((x-lx)+5, y+ly-3, window);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Unlimbo -- Performs unlimbo process for all techno type objects.               *\n *                                                                                             *\n *    This routine handles the common operation between techno objects when they are           *\n *    unlimboed. This includes revealing the map.                                              *\n *                                                                                             *\n * INPUT:   coord    -- The coordinate to unlimbo object at.                                   *\n *                                                                                             *\n *          dir (optional) -- initial facing direction for this object                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the unlimbo successful?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::Unlimbo(COORDINATE coord, DirType dir)\n{\n\tassert(IsActive);\n\n\tif (RadioClass::Unlimbo(coord, dir)) {\n\t\tPrimaryFacing = dir;\n\t\tEnter_Idle_Mode(true);\n\t\tCommence();\n\n\t\tIsLocked = Map.In_Radar(Coord_Cell(coord));\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::In_Range -- Determines if specified target is within weapon range.             *\n *                                                                                             *\n *    This routine is used to compare the distance to the specified target with the range      *\n *    of the weapon. If the target is outside of weapon range, then false is returned.         *\n *                                                                                             *\n * INPUT:   target   -- The target to check if it is within weapon range.                      *\n *                                                                                             *\n *          which    -- Which weapon to use in determining range. 0=primary, 1=secondary.      *\n *                                                                                             *\n * OUTPUT:  bool; Is the specified target within weapon range?                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::In_Range(TARGET target, int which) const\n{\n\tassert(IsActive);\n\n\tif (IsLocked && Target_Legal(target)) {\n\t\tint range = Weapon_Range(which);\n\t\tBuildingClass const * building = As_Building(target);\n\t\tif (building != NULL) {\n\t\t\trange += ((building->Class->Width() + building->Class->Height()) * (ICON_LEPTON_W / 4));\n\t\t}\n\n\t\tif (::Distance(Fire_Coord(which), As_Coord(target)) <= range) {\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::In_Range -- Determines if specified target is within weapon range.             *\n *                                                                                             *\n *    This routine will determine if the pointer to the target object passed into this         *\n *    routine is within weapon range.                                                          *\n *                                                                                             *\n * INPUT:   target   -- Pointer to the target object to check if within weapon range.          *\n *                                                                                             *\n *          which    -- Which weapon to use in determining range. 0=primary, 1=secondary.      *\n *                                                                                             *\n * OUTPUT:  bool; Is the target within weapon range?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::In_Range(ObjectClass const * target, int which) const\n{\n\tassert(IsActive);\n\n\tif (IsLocked && target) {\n\t\tint range = Weapon_Range(which);\n\t\tif (target->What_Am_I() == RTTI_BUILDING) {\n\t\t\tBuildingClass const * building = (BuildingClass const *)target;\n\t\t\trange += ((building->Class->Width() + building->Class->Height()) * (ICON_LEPTON_W / 4));\n\t\t}\n\n\t\tif (::Distance(Fire_Coord(which), target->Center_Coord()) <= range) {\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::In_Range -- Determines if the specified coordinate is within range.            *\n *                                                                                             *\n *    Use this routine to determine if the specified coordinate is within weapon range.        *\n *                                                                                             *\n * INPUT:   coord    -- The coordinate to examine against the object to determine range.       *\n *                                                                                             *\n *          which    -- The weapon to consider when determining range. 0=primary, 1=secondary. *\n *                                                                                             *\n * OUTPUT:  bool; Is the weapon within range?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::In_Range(COORDINATE coord, int which) const\n{\n\tassert(IsActive);\n\n\treturn(IsLocked && ::Distance(Fire_Coord(which), coord) <= Weapon_Range(which));\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Area_Modify -- Determine the area scan modifier for the cell.                  *\n *                                                                                             *\n *    This routine scans around the cell specified and if there are any friendly buildings     *\n *    nearby, the multiplier return value will be reduced. If there are no friendly buildings  *\n *    nearby, then the return value will be 1. It checks to see if the primary weapon is       *\n *    supposed to perform this scan and if so, the scan will be performed. Otherwise the       *\n *    default value is quickly returned.                                                       *\n *                                                                                             *\n * INPUT:   cell  -- The cell where the potential target lies. An area around this cell will   *\n *                   be scanned for friendly buildings.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with the multiplier to be multiplied by the potential target score value.  *\n *          For less opportune targets, the multiplier fraction will be less than one. For     *\n *          all other cases, it will return the default value of 1.                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed TechnoClass::Area_Modify(CELL cell) const\n{\n//\tassert(Techno_Type_Class()->PrimaryWeapon != NULL);\n\tif (Techno_Type_Class()->PrimaryWeapon == NULL || !Techno_Type_Class()->PrimaryWeapon->IsSupressed) return(1);\n\n\tint crange = Lepton_To_Cell(Rule.SupressRadius);\n\tfixed odds = 1;\n\n\tfor (int radius = 1; radius < crange; radius++) {\n\n\t\t/*\n\t\t**\tScan the top and bottom rows of the \"box\".\n\t\t*/\n\t\tfor (int x = -radius; x <= radius; x++) {\n\t\t\tCELL newcell;\n\n\t\t\tif ((Cell_X(cell) + x) < Map.MapCellX) continue;\n\t\t\tif ((Cell_X(cell) + x) >= (Map.MapCellX+Map.MapCellWidth)) continue;\n\n\t\t\tif ((Cell_Y(cell) - radius) >= Map.MapCellY) {\n\t\t\t\tnewcell = XY_Cell(Cell_X(cell) + x, Cell_Y(cell)-radius);\n\t\t\t\tBuildingClass const * building = Map[newcell].Cell_Building();\n\t\t\t\tif (building != NULL && House->Is_Ally(building)) {\n\t\t\t\t\todds /= 2;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ((Cell_Y(cell) + radius) < (Map.MapCellY+Map.MapCellHeight)) {\n\t\t\t\tnewcell = XY_Cell(Cell_X(cell)+x, Cell_Y(cell)+radius);\n\t\t\t\tBuildingClass const * building = Map[newcell].Cell_Building();\n\t\t\t\tif (building != NULL && House->Is_Ally(building)) {\n\t\t\t\t\todds /= 2;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tScan the left and right columns of the \"box\".\n\t\t*/\n\t\tfor (int y = -(radius-1); y < radius; y++) {\n\t\t\tCELL newcell;\n\n\t\t\tif ((Cell_Y(cell) + y) < Map.MapCellY) continue;\n\t\t\tif ((Cell_Y(cell) + y) >= (Map.MapCellY+Map.MapCellHeight)) continue;\n\n\t\t\tif ((Cell_X(cell) - radius) >= Map.MapCellX) {\n\t\t\t\tnewcell = XY_Cell(Cell_X(cell)-radius, Cell_Y(cell)+y);\n\t\t\t\tBuildingClass const * building = Map[newcell].Cell_Building();\n\t\t\t\tif (building != NULL && House->Is_Ally(building)) {\n\t\t\t\t\todds /= 2;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ((Cell_X(cell) + radius) < (Map.MapCellX+Map.MapCellWidth)) {\n\t\t\t\tnewcell = XY_Cell(Cell_X(cell)+radius, Cell_Y(cell)+y);\n\t\t\t\tBuildingClass const * building = Map[newcell].Cell_Building();\n\t\t\t\tif (building != NULL && House->Is_Ally(building)) {\n\t\t\t\t\todds /= 2;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(odds);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Evaluate_Object -- Determines score value of specified object.                 *\n *                                                                                             *\n *    This routine is used to determine the score value (value as a potential target) of the   *\n *    object specified. This routine will check the specified object for all the various       *\n *    legality checks that threat scanning requires. This is the main workhorse routine for    *\n *    target searching.                                                                        *\n *                                                                                             *\n * INPUT:   method   -- The threat method requested. This is a combined bitflag value that     *\n *                      not only specifies the kind of targets to consider, but how far away   *\n *                      they are allowed to be.                                                *\n *                                                                                             *\n *          mask     -- This is an RTTI mask to use for quickly eliminating object types.      *\n *                      The mask is created outside of this routine because this routine is    *\n *                      usually called from within a loop and this value is constant in that   *\n *                      context.                                                               *\n *                                                                                             *\n *          range    -- The range at which potential target objects are rejected.              *\n *                      0  = must be within weapon range.                                      *\n *                      >0 = must be within this lepton distance.                              *\n *                      <0 = range doesn't matter.                                             *\n *                                                                                             *\n *          object   -- Pointer to the object itself.                                          *\n *                                                                                             *\n *          value    -- Reference to the value variable that this routine will fill in. The    *\n *                      higher the value the more likely this object will be selected as best. *\n *                                                                                             *\n *          zone     -- The zone restriction if any. A -1 means no zone check required.        *\n *                                                                                             *\n * OUTPUT:  Did the target pass all legality checks? If this value is returned true, then the  *\n *          value parameter will be filled in correctly.                                       *\n *                                                                                             *\n * WARNINGS:   This routine is time consuming. Don't call unless necessary.                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/30/1995 JLB : Created.                                                                 *\n *   07/14/1995 JLB : Forces SAM site to not fire on landed aircraft.                          *\n *   09/22/1995 JLB : Zone checking enabled.                                                   *\n *   10/05/1995 JLB : Gives greater weight to designated enemy house targets.                  *\n *   02/16/1996 JLB : Added additional threat checks.                                          *\n *=============================================================================================*/\nbool TechnoClass::Evaluate_Object(ThreatType method, int mask, int range, TechnoClass const * object, int & value, int zone) const\n{\n\tassert(IsActive);\n\tassert(object != NULL);\n\n\tBStart(BENCH_EVAL_OBJECT);\n\n\t/*\n\t**\tAn object in limbo can never be a valid target.\n\t*/\n\tif (object == NULL || object->IsInLimbo) {\n\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the object is cloaked, then it isn't a legal target.\n\t*/\n\tif (object->Cloak == CLOAKED) {\n\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the object is in a \"harmless\" state, then don't bother to consider it\n\t**\ta threat.\n\t*/\n\tif (MissionControl[object->Mission].IsNoThreat) {\n\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the object is not within the desired zone, then ignore it, but only if\n\t**\tzone checking is desired.\n\t*/\n\tCOORDINATE objectcoord = object->Center_Coord();\n\tif (zone != -1 && Map[objectcoord].Zones[Techno_Type_Class()->MZone] != zone) {\n\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tFriendly units are never considered a good target. Bail if this\n\t**\tobject is a friend.  Unless we're a medic, of course.  But then,\n\t** only consider it a target if it's injured.\n\t*/\n\tif (House->Is_Ally(object)) {\n\t\tif (Combat_Damage() < 0) {\n\t\t\tif (object->Health_Ratio() == Rule.ConditionGreen) {\n\t\t\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t} else {\n\t\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the object is further away than allowed, bail.\n\t*/\n\tint dist = Distance(object);\n\tif (range > 0 && dist > range) {\n\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\treturn(false);\n\t}\n\n\tif (range == 0) {\n\t\tint primary = What_Weapon_Should_I_Use(object->As_Target());\n\t\tif (!In_Range(object, primary)) {\n\t\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the object is not visible, then bail. Human controlled units\n\t**\tare always considered to be visible.\n\t*/\n\tif (!object->IsOwnedByPlayer && !object->IsDiscoveredByPlayer && Session.Type == GAME_NORMAL && object->What_Am_I() != RTTI_AIRCRAFT) {\n\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tQuickly eliminate all unit types that are not allowed according to the mask\n\t**\tvalue.\n\t*/\n\tRTTIType otype = object->What_Am_I();\n\tif (!((1 << otype) & mask)) {\n\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\treturn(false);\t\t// Mask failure.\n\t}\n\n\t/*\n\t**\tDetermine if the target is theoretically allowed to be a target. If\n\t**\tnot, then bail.\n\t*/\n\tTechnoTypeClass const * tclass = object->Techno_Type_Class();\n\tif (!tclass->IsLegalTarget) {\n\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\treturn(false);\t\t// Legality failure.\n\t}\n\n\t/*\n\t**\tNever consider a spy to be a valid target, unless you're a dog\n\t*/\n\tif (otype == RTTI_INFANTRY && ((InfantryTypeClass const *)tclass)->Type == INFANTRY_SPY) {\n\t\tif (What_Am_I() == RTTI_INFANTRY && ((InfantryClass *)this)->Class->IsDog) {\n\t\t// continue executing...\n\t\t} else {\n\t\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tSpecial case so that SAM site doesn't fire on aircraft that are landed.\n\t*/\n\tif (otype == RTTI_AIRCRAFT && What_Am_I() == RTTI_BUILDING && *((BuildingClass *)this) == STRUCT_SAM) {\n\t\tif (((AircraftClass *)object)->Height == 0) {\n\t\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tIf only allowed to attack civilians, then eliminate all other types.\n\t*/\n\tif ((method & THREAT_CIVILIANS) && object->Owner() != HOUSE_NEUTRAL) {\n\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the scan is limited to capturable buildings only, then bail if the examined\n\t**\tobject isn't a capturable building.\n\t*/\n\tif ((method & THREAT_CAPTURE) && (otype != RTTI_BUILDING || !((BuildingTypeClass const *)tclass)->IsCaptureable)) {\n\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\treturn(false);\n\t}\n\n\t/*\n\t** If we're a sub and the subject is a structure, bail if the structure\n\t** is other than a sub pen or shipyard.\n\t*/\n\tif (otype == RTTI_BUILDING && What_Am_I() == RTTI_VESSEL && *(VesselClass *)this == VESSEL_SS) {\n\t\tStructType ostruc = *(BuildingClass *)object;\n\t\tif (ostruc != STRUCT_SUB_PEN && ostruc != STRUCT_SHIP_YARD) {\n\t\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tSPECIAL CASE: Friendly units won't automatically fire on buildings\n\t**\tif the building is not aggressive. That is, unless it is part of a team. A team\n\t**\tis allowed to pick any target it so chooses.\n\t*/\n\tif ((!Is_Foot() || !((FootClass *)this)->Team.Is_Valid()) &&\n\t\t\t(House->IsHuman || (House->IsPlayerControl && Session.Type == GAME_NORMAL)) &&\n\t\t\totype == RTTI_BUILDING && tclass->PrimaryWeapon == NULL) {\n#ifdef OBSOLETE\n\tif ((!Is_Foot() || ((FootClass *)this)->Team.Is_Valid()) && House->IsHuman && otype == RTTI_BUILDING && tclass->PrimaryWeapon == NULL) {\n#endif\n\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the search is restricted to Tiberium processing objects, then\n\t**\tperform the special qualification check now.\n\t*/\n\tif (method & THREAT_TIBERIUM) {\n\t\tswitch (otype) {\n\t\t\tcase RTTI_UNIT:\n\t\t\t\tif (!((UnitTypeClass const *)tclass)->IsToHarvest) {\n\t\t\t\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\t\t\t\treturn(false);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_BUILDING:\n\t\t\t\tif (!((BuildingTypeClass const *)tclass)->Capacity && Session.Type != GAME_NORMAL) {\n\t\t\t\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\t\t\t\treturn(false);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tIf this target value is better than the previously recorded best\n\t**\ttarget value then record this target for possible return as the\n\t**\tbest.\n\t*/\n\tint rawval = object->Value();\n\tvalue = rawval + object->Crew.Kills;\n\n\t/*\n\t**\tIf the candidate object is owned by the designated enemy of this house, then\n\t**\tgive it a higher value. This will tend to gravitate attacks toward the main\n\t**\tantagonist of this house.\n\t*/\n\tif (House->Enemy != HOUSE_NONE && House->Enemy == object->House->Class->House) {\n\t\tvalue += 500;\n\t\tvalue *= 3;\n\t}\n\n\t/*\n\t**\tIf the object is outside of the protective umbrella of the enemy base, then give it\n\t**\ta target boost value.\n\t*/\n\tif (object->House->Which_Zone(object) == ZONE_NONE) {\n\t\tvalue *= 2;\n\t}\n\n\t/*\n\t**\tIf fake buildings are considered to be a greater target option, then boost\n\t**\tthe fake building's value.\n\t*/\n\tif ((method & THREAT_FAKES) && otype == RTTI_BUILDING) {\n\t\tswitch (!((BuildingTypeClass const *)tclass)->Type) {\n\t\t\tcase STRUCT_FAKECONST:\n\t\t\tcase STRUCT_FAKEWEAP:\n\t\t\tcase STRUCT_FAKE_YARD:\n\t\t\tcase STRUCT_FAKE_PEN:\n\t\t\tcase STRUCT_FAKE_RADAR:\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tIgnore all non-fake buildings.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\tvalue = 0;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf power plants are to be considered a greater threat, then increase\n\t**\ttheir value here. Buildings that produce no power are not considered\n\t**\ta threat.\n\t*/\n\tif ((method & THREAT_POWER) && otype == RTTI_BUILDING) {\n\t\tif (((BuildingTypeClass const *)tclass)->Power > 0) {\n\t\t\tvalue += ((BuildingTypeClass const *)tclass)->Power * 1000;\n\t\t} else {\n\t\t\tvalue = 0;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf factories are to be considered a greater threat, then don't\n\t**\tconsider any non-factory building.\n\t*/\n\tif ((method & THREAT_FACTORIES) && otype == RTTI_BUILDING) {\n\t\tif (((BuildingTypeClass const *)tclass)->ToBuild == RTTI_NONE) {\n\t\t\tvalue = 0;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf base defensive structures are to be considered a greater threat, then\n\t**\tdon't consider an unarmed building to be a threat.\n\t*/\n\tif ((method & THREAT_BASE_DEFENSE) /*&& otype == RTTI_BUILDING*/) {\n\t\tif (tclass->PrimaryWeapon == NULL) {\n\t\t\tvalue = 0;\n\t\t}\n\t}\n\n\t/*\n\t**\tPossibly cause a reduction of the target's value if it is nearby friendly\n\t**\tstructures and the primary weapon of this object is flagged for\n\t**\tfriendly fire supression special check logic.\n\t*/\n\tfixed areamod = Area_Modify(Coord_Cell(object->Center_Coord()));\n\tif (areamod != 1) {\n\t\tvalue = areamod * value;\n\t}\n\n\t/*\n\t**\tAdjust the target value upward if it is in the 'nervous zone' of the\n\t**\towning base. This will tend to protect the base more thoroughly than\n\t**\tan unmodified scan would.\n\t*/\n\tif (House->Which_Zone(object) != ZONE_NONE) {\n\t\tvalue *= Rule.NervousBias;\n\t}\n\n\t/*\n\t**\tLessen threat as a factor of distance.\n\t*/\n\tif (value) {\n//\tif (rawval) {\n\n\t\tvalue = (value * 32000) / ((dist/ICON_LEPTON_W)+1);\n//\t\tvalue = (value * 32000) / (((dist/ICON_LEPTON_W)*(dist/ICON_LEPTON_W))+1);\n\n//\t\tif (value < MAP_CELL_W*2) value = dist/ICON_LEPTON_W;\n\t\tvalue = max(value, 1);\n\t\tBEnd(BENCH_EVAL_OBJECT);\n\t\treturn(true);\n\t}\n\tvalue = 0;\n\tBEnd(BENCH_EVAL_OBJECT);\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Evaluate_Cell -- Determine the value and object of specified cell.             *\n *                                                                                             *\n *    This routine will examine the specified cell and return with the potential target        *\n *    object it contains and the value of it. Use this routine when searching for threats.     *\n *                                                                                             *\n * INPUT:   method   -- The scan method to use for target searching.                           *\n *                                                                                             *\n *          mask     -- Prebuilt mask of object RTTI types acceptable for scanning.            *\n *                                                                                             *\n *          range    -- Scan range limit to use for elimination purposes. This ensures that    *\n *                      objects in the \"corner\" of a square scan get properly discarded.       *\n *                                                                                             *\n *          object   -- Pointer to object pointer to be filled in with the object at this      *\n *                      cell as a valid target.                                                *\n *                                                                                             *\n *          value    -- Reference to the value of the object in this cell. It will be set      *\n *                      according to the object's value.                                       *\n *                                                                                             *\n *          zone     -- The zone restriction if any. A -1 means no zone check required.        *\n *                                                                                             *\n * OUTPUT:  Was a valid potential target found in this cell?                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *   09/22/1995 JLB : Zone checking enabled.                                                   *\n *=============================================================================================*/\nbool TechnoClass::Evaluate_Cell(ThreatType method, int mask, CELL cell, int range, TechnoClass const * * object, int & value, int zone) const\n{\n\tassert(IsActive);\n\n\tBStart(BENCH_EVAL_CELL);\n\n\t*object = NULL;\n\tvalue = 0;\n\n\t/*\n\t**\tIf the cell is not on the legal map, then always ignore it.\n\t*/\n\tif ((unsigned)cell > MAP_CELL_TOTAL) {\n\t\tBEnd(BENCH_EVAL_CELL);\n\t\treturn(false);\n\t}\n\tif (!Map.In_Radar(cell)) {\n\t\tBEnd(BENCH_EVAL_CELL);\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tFetch the techno object from the cell. If there is no\n\t**\ttechno object there, then bail.\n\t*/\n\tCellClass * cellptr = &Map[cell];\n\n\t/*\n\t**\tDon't consider for evaluation a cell that is not within the same zone. Only\n\t**\tperform this check if zone checking is required.\n\t*/\n\tif (zone != -1 && cellptr->Zones[Techno_Type_Class()->MZone] != zone) {\n\t\tBEnd(BENCH_EVAL_CELL);\n\t\treturn(false);\n\t}\n\n\tTechnoClass const * tentative = (TechnoClass const *)cellptr->Cell_Occupier();\n\twhile (tentative != NULL) {\n\t\tif (tentative != this) {\n\t\t\tif (tentative->Is_Techno()) {\n\t\t\t\tif (Combat_Damage() < 0) {\n\t\t\t\t\tif (tentative->Health_Ratio() < Rule.ConditionGreen && House->Is_Ally(tentative)) break;\n\t\t\t\t} else {\n\t\t\t\t\tif (!House->Is_Ally(tentative)) break;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\ttentative = (TechnoClass const *)(ObjectClass *)tentative->Next;\n\t}\n\n\tif (tentative == NULL) {\n\t\tBEnd(BENCH_EVAL_CELL);\n\t\treturn(false);\n\t}\n\t*object = tentative;\n\n\tbool result = Evaluate_Object(method, mask, range, tentative, value);\n\n\tBEnd(BENCH_EVAL_CELL);\n\treturn(result);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Evaluate_Just_Cell -- Evaluate a cell as a target by itself.                   *\n *                                                                                             *\n *    This will examine the cell (as if it contained no sentient objects) and determine a      *\n *    target value to assign to it. Typically, this is only useful for wall destroyable        *\n *    weapons when dealing with enemy walls.                                                   *\n *                                                                                             *\n * INPUT:   cell  -- The cell to examine and evaluate.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the target value to assign to this cell.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoClass::Evaluate_Just_Cell(CELL cell) const\n{\n\tBStart(BENCH_EVAL_WALL);\n\n\t/*\n\t**\tShips don't scan for walls.\n\t*/\n\tif (What_Am_I() == RTTI_VESSEL) {\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tFirst, only computer objects are allowed to automatically scan for walls.\n\t*/\n\tif (House->IsHuman) {\n\t\tBEnd(BENCH_EVAL_WALL);\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tEven then, if the difficulty indicates that it shouldn't search for wall\n\t**\ttargets, then don't allow it to do so.\n\t*/\n\tif (!Rule.Diff[House->Difficulty].IsWallDestroyer) {\n\t\tBEnd(BENCH_EVAL_WALL);\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tDetermine if, in fact, a wall is located at this cell location.\n\t*/\n\tCellClass const * cellptr = &Map[cell];\n\tif (cellptr->Overlay == OVERLAY_NONE || !OverlayTypeClass::As_Reference(cellptr->Overlay).IsWall) {\n\t\tBEnd(BENCH_EVAL_WALL);\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tAs a convenience to the target scanning logic, don't consider any wall to be\n\t**\ta target if it isn't in range of the primary weapon.\n\t*/\n\tint primary = What_Weapon_Should_I_Use(::As_Target(cell));\n\tif (!In_Range(Cell_Coord(cell), primary)) {\n\t\tBEnd(BENCH_EVAL_WALL);\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tSee if the object has a weapon that can damage walls.\n\t*/\n\tTechnoTypeClass const * ttype = (TechnoTypeClass const *)Techno_Type_Class();\n\tif (ttype->PrimaryWeapon == NULL || ttype->PrimaryWeapon->WarheadPtr == NULL) {\n\t\tBEnd(BENCH_EVAL_WALL);\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tIf the weapon cannot deal with ground based targets, then don't consider\n\t**\tthis a valid cell target.\n\t*/\n\tif (ttype->PrimaryWeapon->Bullet != NULL && !ttype->PrimaryWeapon->Bullet->IsAntiGround) {\n\t\tBEnd(BENCH_EVAL_WALL);\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tIf the primary weapon cannot destroy a wall, then don't give the cell any\n\t**\tvalue as a target.\n\t*/\n\tif (!ttype->PrimaryWeapon->WarheadPtr->IsWallDestroyer) {\n\t\tBEnd(BENCH_EVAL_WALL);\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tIf this is a friendly wall, then don't attack it.\n\t*/\n\tif (House->Is_Ally(cellptr->Owner)) {\n\t\tBEnd(BENCH_EVAL_WALL);\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tSince a wall was found, then return a value adjusted according to the range the wall\n\t**\tis from the object. The greater the range, the lesser the value returned.\n\t*/\n\tBEnd(BENCH_EVAL_WALL);\n\treturn(Weapon_Range(0) - Distance(Cell_Coord(cell)));\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Greatest_Threat -- Determines best target given search criteria.               *\n *                                                                                             *\n *    This routine will scan game objects looking for the best target. It is used by the       *\n *    general target searching processes. The type of target scan to perform is controlled     *\n *    by the method control parameter.                                                         *\n *                                                                                             *\n * INPUT:   method   -- The method control parameter is used to control the type of target     *\n *                      scan performed. It consists of a series of bit flags (see ThreatType)  *\n *                      that are combined to form the target scan desired.                     *\n *                                                                                             *\n * OUTPUT:  Returns the target value of a suitable target. If no target was found then the     *\n *          value TARGET_NONE is returned.                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1994 JLB : Created.                                                                 *\n *   06/20/1995 JLB : Greatly optimized scan method.                                           *\n *   09/22/1995 JLB : Takes into account the zone (if necessary).                              *\n *   05/30/1996 JLB : Tighter elimination mask checking.                                       *\n *=============================================================================================*/\nTARGET TechnoClass::Greatest_Threat(ThreatType method) const\n{\n\tassert(IsActive);\n\n\tBStart(BENCH_GREATEST_THREAT);\n\n\tObjectClass const * bestobject = NULL;\n\tint bestval = -1;\n\tint zone = -1;\n\n\tTargetScan++;\n\n\t/*\n\t**\tDetermine the zone that the target must be in. For aircraft and gunboats, they\n\t**\tignore zones since they either can fly over any zone or are designed to fire into\n\t**\tother zones. If scanning for targets that are within range, then zone checking need\n\t**\tnot be performed -- range checking is much more thorough and effective.\n\t*/\n\tif (!(method & THREAT_RANGE) &&\n\t\tWhat_Am_I() != RTTI_VESSEL &&\n\t\tWhat_Am_I() != RTTI_BUILDING &&\n\t\tWhat_Am_I() != RTTI_AIRCRAFT) {\n\n\t\tzone = Map[Center_Coord()].Zones[Techno_Type_Class()->MZone];\n\t}\n\n\t/*\n\t** Hack for dogs, 'cause they can only consider infantrymen to be a\n\t** threat.  Medics also.\n\t*/\n\tif (What_Am_I() == RTTI_INFANTRY) {\n\t\tif (((InfantryClass *)this)->Class->IsDog || Combat_Damage() < 0) {\n\t\t\tmethod = THREAT_INFANTRY | (method & (THREAT_RANGE | THREAT_AREA));\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif(*(InfantryClass *)this == INFANTRY_MECHANIC) {\n\t\t\t\tmethod = (THREAT_VEHICLES | THREAT_AIR) | (method & (THREAT_RANGE | THREAT_AREA));\n\t\t\t}\n#endif\n\t\t}\n\t}\n\n\t/*\n\t**\tBuild a quick elimination mask. If the RTTI of the object doesn't\n\t**\tqualify with this mask, then we KNOW that it shouldn't be considered.\n\t*/\n\tint mask = 0;\n\tif (method & THREAT_CIVILIANS) mask |= ((1 << RTTI_BUILDING) | (1 << RTTI_INFANTRY) | (1 << RTTI_UNIT));\n\tif (method & THREAT_AIR) mask |= (1 << RTTI_AIRCRAFT);\n\tif (method & THREAT_CAPTURE) mask |= (1 << RTTI_BUILDING);\n\tif (method & (THREAT_CIVILIANS|THREAT_BUILDINGS|THREAT_FACTORIES|THREAT_POWER|THREAT_FAKES|THREAT_BASE_DEFENSE|THREAT_TIBERIUM)) mask |= (1 << RTTI_BUILDING);\n\tif (method & (THREAT_CIVILIANS|THREAT_INFANTRY|THREAT_BASE_DEFENSE)) mask |= (1 << RTTI_INFANTRY);\n\tif (method & THREAT_VEHICLES) mask |= (1 << RTTI_UNIT);\n\tif (method & THREAT_BASE_DEFENSE) mask |= (1 << RTTI_BUILDING);\n\tif (method & THREAT_BOATS) mask |= (1 << RTTI_VESSEL);\n\n\t/*\n\t**\tLimit area target scans use a method where the actual map cells are\n\t**\texamined for occupants. The occupant is then examined in turn. The\n\t**\tbest target within the area is returned as a target.\n\t*/\n\tif (method & (THREAT_AREA|THREAT_RANGE)) {\n\t\tint range = Threat_Range((method & THREAT_RANGE) ? 0 : 1);\n\n\t\tint crange = range / ICON_LEPTON_W;\n\t\tif (range == 0) {\n\t\t\tcrange = max(Weapon_Range(0), Weapon_Range(1)) / ICON_LEPTON_W;\n\t\t\tcrange++;\n\t\t}\n\t\tCELL cell = Coord_Cell(Fire_Coord(0));\n\n\t\t/*\n\t\t** BG: Miserable hack to get the stupid doctor to actually do area\n\t\t** \t guarding.\n\t\t*/\n\t\tif (Combat_Damage() < 0) {\n\t\t\t/*if (method & THREAT_AREA)*/ crange++;\n\t\t}\n\n\t\t/*\n\t\t**\tIf aircraft are a legal target, then scan through all of them at this time.\n\t\t**\tScanning by cell is not possible for aircraft since they are not recorded\n\t\t**\tat the cell level.\n\t\t*/\n\t\tif (method & THREAT_AIR) {\n\t\t\tfor (int index = 0; index < Aircraft.Count(); index++) {\n\t\t\t\tTechnoClass * object = Aircraft.Ptr(index);\n\n\t\t\t\tint value = 0;\n\t\t\t\tif (object->In_Which_Layer() != LAYER_GROUND && Evaluate_Object(method, mask, range, object, value)) {\n\t\t\t\t\tif (value > bestval) {\n\t\t\t\t\t\tbestobject = object;\n\t\t\t\t\t\tbestval = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tWhen scanning the ground, always consider landed aircraft as a valid\n\t\t**\tpotential target. This is only true if vehicles are considered a\n\t\t**\tvalid target. A landed aircraft is considered a vehicle.\n\t\t*/\n\t\tif (method & THREAT_VEHICLES) {\n\t\t\tmask |= (1 << RTTI_AIRCRAFT);\n\t\t}\n\n\t\t/*\n\t\t**\tRadiate outward from the object's location, looking for the best\n\t\t**\ttarget.\n\t\t*/\n\t\tCELL bestcell = -1;\n\t\tint bestcellvalue = 0;\n\t\tTechnoClass const * object;\n\t\tint value;\n//\t\tint rad = 1;\n\n\t\t// BG: Medics need to be able to look in their own cell too.\n//\t\tif (Combat_Damage() < 0 || (What_Am_I() == RTTI_INFANTRY && ((InfantryClass*)this)->Class->IsDog)) {\n//\t\t\trad = 0;\n//\t\t}\n\n\t\tfor (int radius = 0; radius < crange; radius++) {\n\n\t\t\t/*\n\t\t\t**\tScan the top and bottom rows of the \"box\".\n\t\t\t*/\n\t\t\tfor (int x = -radius; x <= radius; x++) {\n\t\t\t\tCELL newcell;\n\n\t\t\t\tif ((Cell_X(cell) + x) < Map.MapCellX) continue;\n\t\t\t\tif ((Cell_X(cell) + x) >= (Map.MapCellX+Map.MapCellWidth)) continue;\n\n\t\t\t\tif ((Cell_Y(cell) - radius) >= Map.MapCellY) {\n\t\t\t\t\tnewcell = XY_Cell(Cell_X(cell) + x, Cell_Y(cell)-radius);\n\t\t\t\t\tif (Evaluate_Cell(method, mask, newcell, range, &object, value, zone)) {\n\t\t\t\t\t\tif (bestval < value) {\n\t\t\t\t\t\t\tbestobject = object;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (bestobject == NULL) {\n\t\t\t\t\t\tvalue = Evaluate_Just_Cell(newcell);\n\t\t\t\t\t\tif (bestcellvalue < value) {\n\t\t\t\t\t\t\tbestcellvalue = value;\n\t\t\t\t\t\t\tbestcell = newcell;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ((Cell_Y(cell) + radius) < (Map.MapCellY+Map.MapCellHeight)) {\n\t\t\t\t\tnewcell = XY_Cell(Cell_X(cell)+x, Cell_Y(cell)+radius);\n\t\t\t\t\tif (Evaluate_Cell(method, mask, newcell, range, &object, value, zone)) {\n\t\t\t\t\t\tif (bestval < value) {\n\t\t\t\t\t\t\tbestobject = object;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (bestobject == NULL) {\n\t\t\t\t\t\tvalue = Evaluate_Just_Cell(newcell);\n\t\t\t\t\t\tif (bestcellvalue < value) {\n\t\t\t\t\t\t\tbestcellvalue = value;\n\t\t\t\t\t\t\tbestcell = newcell;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tScan the left and right columns of the \"box\".\n\t\t\t*/\n\t\t\tfor (int y = -(radius-1); y < radius; y++) {\n\t\t\t\tCELL newcell;\n\n\t\t\t\tif ((Cell_Y(cell) + y) < Map.MapCellY) continue;\n\t\t\t\tif ((Cell_Y(cell) + y) >= (Map.MapCellY+Map.MapCellHeight)) continue;\n\n\t\t\t\tif ((Cell_X(cell) - radius) >= Map.MapCellX) {\n\t\t\t\t\tnewcell = XY_Cell(Cell_X(cell)-radius, Cell_Y(cell)+y);\n\t\t\t\t\tif (Evaluate_Cell(method, mask, newcell, range, &object, value, zone)) {\n\t\t\t\t\t\tif (bestval < value) {\n\t\t\t\t\t\t\tbestobject = object;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (bestobject == NULL) {\n\t\t\t\t\t\tvalue = Evaluate_Just_Cell(newcell);\n\t\t\t\t\t\tif (bestcellvalue < value) {\n\t\t\t\t\t\t\tbestcellvalue = value;\n\t\t\t\t\t\t\tbestcell = newcell;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ((Cell_X(cell) + radius) < (Map.MapCellX+Map.MapCellWidth)) {\n\t\t\t\t\tnewcell = XY_Cell(Cell_X(cell)+radius, Cell_Y(cell)+y);\n\t\t\t\t\tif (Evaluate_Cell(method, mask, newcell, range, &object, value, zone)) {\n\t\t\t\t\t\tif (bestval < value) {\n\t\t\t\t\t\t\tbestobject = object;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (bestobject == NULL) {\n\t\t\t\t\t\tvalue = Evaluate_Just_Cell(newcell);\n\t\t\t\t\t\tif (bestcellvalue < value) {\n\t\t\t\t\t\t\tbestcellvalue = value;\n\t\t\t\t\t\t\tbestcell = newcell;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tBail early if a target has already been found and the range is at\n\t\t\t**\tone of the breaking points (i.e., normal range or range * 2).\n\t\t\t*/\n\t\t\tif (bestobject != NULL) {\n\t\t\t\tif (radius == crange/4) {\n\t\t\t\t\treturn(bestobject->As_Target());\n\t\t\t\t}\n\t\t\t\tif (radius == crange/2) {\n\t\t\t\t\treturn(bestobject->As_Target());\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (bestcell != -1) {\n\t\t\t\treturn(::As_Target(bestcell));\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t/*\n\t\t**\tA full map scan was requested. First scan through aircraft. The top map layer\n\t\t**\tis NOT scanned since that layer will probably contain more bullets and animations\n\t\t**\tthan aircraft.\n\t\t*/\n\t\tif (mask & (1L << RTTI_AIRCRAFT)) {\n\t\t\tfor (int index = 0; index < Aircraft.Count(); index++) {\n\t\t\t\tTechnoClass * object = Aircraft.Ptr(index);\n\n\t\t\t\tint value = 0;\n\t\t\t\tif (Evaluate_Object(method, mask, -1, object, value)) {\n\t\t\t\t\tif (value > bestval) {\n\t\t\t\t\t\tbestobject = object;\n\t\t\t\t\t\tbestval = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tWhen scanning the ground, always consider landed aircraft as a valid\n\t\t**\tpotential target. This is only true if vehicles are considered a\n\t\t**\tvalid target. A landed aircraft is considered a vehicle.\n\t\t*/\n\t\tif (method & THREAT_VEHICLES) {\n\t\t\tmask |= (1 << RTTI_AIRCRAFT);\n\t\t}\n\n\t\t/*\n\t\t**\tNow scan through the entire ground layer. This is painful, but what other\n\t\t**\tchoice is there?\n\t\t*/\n\t\tfor (int index = 0; index < Map.Layer[LAYER_GROUND].Count(); index++) {\n\t\t\tObjectClass const * object = Map.Layer[LAYER_GROUND][index];\n\n\t\t\tint value = 0;\n\t\t\tif (object->Is_Techno() && Evaluate_Object(method, mask, -1, (TechnoClass const *)object, value, zone)) {\n\t\t\t\tif (value > bestval) {\n\t\t\t\t\tbestobject = object;\n\t\t\t\t\tbestval = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tBEnd(BENCH_GREATEST_THREAT);\n\n\t/*\n\t**\tIf a good target object was found, then return with the target value\n\t**\tof it.\n\t*/\n\tif (bestobject != NULL) {\n\t\treturn(bestobject->As_Target());\n\t}\n\treturn(TARGET_NONE);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Owner -- Who is the owner of this object?                                      *\n *                                                                                             *\n *    Use this routine to examine this object and return who the owner is.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the house number of the owner of this object.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nHousesType TechnoClass::Owner(void) const\n{\n\tassert(IsActive);\n\n\treturn(House->Class->House);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Clicked_As_Target -- Sets the flash count for this techno object.              *\n *                                                                                             *\n *    Use this routine to set the flash count for the object. This flash count is the number   *\n *    of times the object will \"flash\". Typically it is called as a result of the player       *\n *    clicking on this object in order to make it the target of a move or attack.              *\n *                                                                                             *\n * INPUT:   count -- The number of times the object should flash.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Clicked_As_Target(int count)\n{\n\tassert(IsActive);\n\n\tFlashCount = count;\n}\n\n\n/***********************************************************************************************\n * TechnoClass::AI -- Handles AI processing for techno object.                                 *\n *                                                                                             *\n *    This routine handles AI processing for techno objects. Typically, this merely dispatches *\n *    to the appropriate AI routines for the base classes.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Make sure that this routine is only called ONCE per game tick.                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::AI(void)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tHandle recoil recovery here.\n\t*/\n\tif (IsInRecoilState) {\n\t\tIsInRecoilState = false;\n\t\tMark(MARK_CHANGE_REDRAW);\n\t}\n\n\tCargoClass::AI();\n\tRadioClass::AI();\n\n\tif (!IsActive || (Height > 0 && What_Am_I() != RTTI_AIRCRAFT)) return;\n\n\tDoorClass::AI();\n\n\t/*\n\t**\tIf this is a vehicle that heals itself (e.g., Mammoth Tank), then it will perform\n\t**\tthe heal logic here.\n\t*/\n\tif (Techno_Type_Class()->IsSelfHealing && (Frame % (Rule.RepairRate * TICKS_PER_MINUTE)) == 0 && Health_Ratio() <= Rule.ConditionYellow) {\n\t\tStrength++;\n\t\tMark(MARK_CHANGE);\n\t}\n\n\t/*\n\t**\tCloaking device processing.\n\t*/\n\tCloaking_AI();\n\n\t/*\n\t**\tIf for some strange reason, the computer is firing upon itself, then\n\t**\ttell it not to.\n\t*/\n\tif (!House->IsHuman && As_Techno(TarCom) && As_Techno(TarCom)->House->Is_Ally(this)) {\n//#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98 (commented out)\n//if(What_Am_I() == RTTI_INFANTRY && *(InfantryClass *)this==INFANTRY_GENERAL && Session.Type==GAME_NORMAL && House->Class->House==HOUSE_UKRAINE) {\n//} else\n//#endif\n\t\tAssign_Target(TARGET_NONE);\n\t}\n\n\t/*\n\t**\tPerform a maintenance check to see that if somehow this object is trying to fire\n\t**\tupon an object it can never hit (because it can't reach it), then abort the tarcom\n\t*/\n\tif (What_Am_I() != RTTI_AIRCRAFT && Target_Legal(TarCom) && (!Is_Foot() || !((FootClass *)this)->Team.Is_Valid()) && (!Is_Foot() || !Is_In_Same_Zone(As_Cell(TarCom)))) {\n\t\tint primary = What_Weapon_Should_I_Use(TarCom);\n\t\tif (!In_Range(TarCom, primary)) {\n\t\t\tAssign_Target(TARGET_NONE);\n\t\t}\n\t}\n\n\t/*\n\t**\tUpdate the animation timer system. If the animation stage\n\t**\tchanges, then flag the object to be redrawn as well as determine\n\t**\tif the current animation process needs to change.\n\t*/\n\tif (What_Am_I() != RTTI_BUILDING) {\n\t\tif (StageClass::About_To_Change()) {\n\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t}\n\t\tif (StageClass::Graphic_Logic() || Time_To_Redraw()) {\n\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the object is flashing and a change of flash state has occurred, then mark the\n\t**\tobject to be redrawn.\n\t*/\n\tif (FlasherClass::Process()) {\n\t\tMark(MARK_CHANGE);\n\t}\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Cloaking_AI -- Perform the AI maintenance for a cloaking device.               *\n *                                                                                             *\n *    This routine handles the cloaking device logic for this object. It will handle the       *\n *    transition effects as the object cloaks or decloaks. It will also try to start an        *\n *    object to cloak if possible.                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Cloaking_AI(void)\n{\n\t/*\n\t** Handle decision to re-cloak here. Process the cloaking/decloaking operation.\n\t*/\n\tif (IsCloakable) {\n\n\t\t/*\n\t\t**\tIf this object is uncloaked, but it can be cloaked and it thinks that it\n\t\t**\tis a good time do so, then begin cloaking.\n\t\t*/\n\t\tif (Cloak == UNCLOAKED) {\n#ifdef PREDATOR\n\t\t\tif (IsOwnedByPlayer) Mark(MARK_CHANGE);\n#endif\n\t\t\tCloakingDevice.Graphic_Logic();\n\t\t\tif (Is_Ready_To_Cloak()) {\n\t\t\t\tif (Health_Ratio() > Rule.ConditionRed) {\n\t\t\t\t\tDo_Cloak();\n\t\t\t\t} else {\n\t\t\t\t\tif (Percent_Chance(4)) {\n\t\t\t\t\t\tDo_Cloak();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\n\t\t\tCloakingDevice.Graphic_Logic();\n\t\t\tswitch (Cloak) {\n\n\t\t\t\t/*\n\t\t\t\t**\tHandle the uncloaking process. Always mark to redraw\n\t\t\t\t**\tthe object and when cloaking is complete, stabilize into\n\t\t\t\t**\tthe normal uncloaked state.\n\t\t\t\t*/\n\t\t\t\tcase UNCLOAKING:\n\t\t\t\t\tMark(MARK_CHANGE);\n\t\t\t\t\tif (Visual_Character(true) == VISUAL_NORMAL) {\n\t\t\t\t\t\tCloakingDevice.Set_Rate(0);\n\t\t\t\t\t\tCloakingDevice.Set_Stage(0);\t// re-start the stage counter\n\t\t\t\t\t\tCloak = UNCLOAKED;\n\t\t\t\t\t\tCloakDelay = Rule.CloakDelay * TICKS_PER_MINUTE;\n\t\t\t\t\t\tMark(MARK_CHANGE);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tHandle the cloaking process. Always mark to redraw the object\n\t\t\t\t**\tand when the cloaking process is complete, stabilize into the\n\t\t\t\t**\tnormal cloaked state.\n\t\t\t\t*/\n\t\t\t\tcase CLOAKING:\n\t\t\t\t\tMark(MARK_CHANGE);\n\t\t\t\t\tif(!CloakingDevice.Fetch_Rate()) {\n\t\t\t\t\t\tCloakingDevice.Set_Rate(1);\n\t\t\t\t\t}\n\t\t\t\t\tswitch (Visual_Character(true)) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf badly damaged, then it can never fully cloak.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase VISUAL_DARKEN:\n\t\t\t\t\t\t\tif (Health_Ratio() <= Rule.ConditionRed && Percent_Chance(25)) {\n\t\t\t\t\t\t\t\tCloak = UNCLOAKING;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase VISUAL_HIDDEN:\n\t\t\t\t\t\t\tCloak = CLOAKED;\n\t\t\t\t\t\t\tCloakingDevice.Set_Rate(0);\n\t\t\t\t\t\t\tCloakingDevice.Set_Stage(0);\n\t\t\t\t\t\t\tMark(MARK_CHANGE);\n\n\t\t\t\t\t\t\tMap[Center_Coord()].Redraw_Objects(true);\n\t\t\t\t\t\t\tMap.RadarClass::Flag_To_Redraw(true);\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tSpecial check to ensure that if the unit is carrying a captured\n\t\t\t\t\t\t\t**\tflag, it will never fully cloak.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (What_Am_I() == RTTI_UNIT && ((UnitClass *)this)->Flagged != HOUSE_NONE) {\n\t\t\t\t\t\t\t\tDo_Shimmer();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tDetach_All(false);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tA computer controlled unit will try to scatter if possible so\n\t\t\t\t\t\t\t**\tthat it will be much harder to locate.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (What_Am_I() == RTTI_UNIT && !House->IsHuman) {\n\t\t\t\t\t\t\t\tScatter(0, true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tA cloaked object will always be redrawn if it is owned by the\n\t\t\t\t**\tplayer. This ensures that the shimmering effect will animate.\n\t\t\t\t*/\n\t\t\t\tcase CLOAKED:\n#ifdef PREDATOR\n\t\t\t\t\tif (IsOwnedByPlayer) {\n\t\t\t\t\t\tMark(MARK_CHANGE);\n\t\t\t\t\t}\n#endif\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Is_Ready_To_Cloak -- Determines if this object is ready to begin cloaking.     *\n *                                                                                             *\n *    This routine will examine this object and determine if it can and is ready and able      *\n *    to begin cloaking. It will also check to make sure it appears to be a good time to cloak *\n *    as well.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is this unit ready and able to start cloaking?                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::Is_Ready_To_Cloak(void) const\n{\n\t/*\n\t**\tIf it is already cloaked or in the process of cloaking, then it can't start cloaking.\n\t*/\n\tif (Cloak == CLOAKED || (Cloak == CLOAKING && CloakingDevice.Fetch_Rate())) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the object cannot recloak, then it certainly is not allowed to start.\n\t*/\n\tif (!IsCloakable || !Is_Allowed_To_Recloak()) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the object is currently rearming, then don't begin to recloak.\n\t*/\n\tif (Arm != 0) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf it seems like this object is about to fire on a target, then don't begin\n\t**\tcloaking either.\n\t*/\n\tif (Target_Legal(TarCom) && In_Range(TarCom)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tRecloaking can only begin if the cloaking device is not already operating.\n\t*/\n\tif (CloakingDevice.Fetch_Stage() != 0) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the arbitrary cloak delay value is still counting down, then don't\n\t**\tallow recloaking just yet.\n\t*/\n\tif (CloakDelay != 0) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tAll tests passed, so this object is allowed to begin cloaking.\n\t*/\n\treturn(true);\n}\n\n\n\n/***********************************************************************************************\n * TechnoClass::Select -- Selects object and checks to see if can be selected.                 *\n *                                                                                             *\n *    This function checks to see if this techno object can be selected. If it can, then it    *\n *    is selected.                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/11/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::Select(void)\n{\n\tassert(IsActive);\n\n\tif (!IsDiscoveredByPlayer && !House->IsPlayerControl && !Debug_Unshroud) {\n\t\treturn(false);\n\t}\n\n\tif (RadioClass::Select()) {\n\n\t\t/*\n\t\t**\tSpeak a confirmation of selection.\n\t\t*/\n\t\tif (House->IsPlayerControl && AllowVoice) {\n\t\t\tResponse_Select();\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Can_Fire -- Determines if this techno object can fire.                         *\n *                                                                                             *\n *    This performs a simple check to make sure that this techno object can fire. At this      *\n *    level, the only thing checked for is the rearming delay.                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the fire legality control code.                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nFireErrorType TechnoClass::Can_Fire(TARGET target, int which) const\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tDon't allow firing if the target is illegal.\n\t*/\n\tif (!Target_Legal(target)) {\n\t\treturn(FIRE_ILLEGAL);\n\t}\n\n\tObjectClass * object = As_Object(target);\n\n\t/*\n\t**\tIf the object is completely cloaked, then you can't fire on it.\n\t*/\n\tif (object != NULL && object->Is_Techno() && ((TechnoClass *)object)->Cloak == CLOAKED) {\n\t\treturn(FIRE_CANT);\n\t}\n\n\t/*\n\t**\tA falling object is too busy falling to fire.\n\t*/\n\tif (IsFalling) {\n\t\treturn(FIRE_CANT);\n\t}\n\n\t/*\n\t**\tIf there is no weapon, then firing is not allowed.\n\t*/\n\tWeaponTypeClass const * weapon = ((which == 0) ? Techno_Type_Class()->PrimaryWeapon : Techno_Type_Class()->SecondaryWeapon);\n\tif (weapon == NULL) {\n\t\treturn(FIRE_CANT);\n\t}\n\n\t/*\n\t**\tCan only fire anti-aircraft weapons against aircraft unless the aircraft is\n\t**\tsitting on the ground.\n\t*/\n\tif (object != NULL && object->What_Am_I() == RTTI_AIRCRAFT &&\n\t\t\t!weapon->Bullet->IsAntiAircraft &&\n\t\t\t((AircraftClass *)object)->Height > 0) {\n\n\t\treturn(FIRE_CANT);\n\t}\n\n\t/*\n\t**\tIf the object is on the ground, then don't allow firing if it can't fire upon ground objects.\n\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (object != NULL && object->Height == 0 && (object->What_Am_I() != RTTI_VESSEL || (*((VesselClass*)object) != VESSEL_SS && *((VesselClass*)object) != VESSEL_MISSILESUB )) &&\n#else\n\tif (object != NULL && object->Height == 0 && (object->What_Am_I() != RTTI_VESSEL || *((VesselClass*)object) != VESSEL_SS) &&\n#endif\n\t\t!weapon->Bullet->IsAntiGround) {\n\n\t\treturn(FIRE_CANT);\n\t}\n\tif (Is_Target_Cell(target) && !weapon->Bullet->IsAntiGround) {\n\t\treturn(FIRE_CANT);\n\t}\n\n\t/*\n\t**\tDon't allow firing if still rearming.\n\t*/\n\tif (Arm != 0) return(FIRE_REARM);\n\n\t/*\n\t**\tThe target must be within range in order to allow firing.\n\t*/\n\tif (!In_Range(target, which)) {\n\t\treturn(FIRE_RANGE);\n\t}\n\n\t/*\n\t**\tIf there is no ammo left, then it can't fire.\n\t*/\n\tif (!Ammo) {\n\t\treturn(FIRE_AMMO);\n\t}\n\n\t/*\n\t**\tIf cloaked, then firing is disabled.\n\t*/\n\tif (Cloak != UNCLOAKED) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// Special hack for John Archer's Hunt-The-Wumpus multiplayer mission... if\n// the object firing is a cloaked civilian, don't require uncloaking before\n// allowing firing.\n\t\tif (What_Am_I()==RTTI_INFANTRY && ((InfantryClass *)this)->Class->IsCivilian ) {\n\t\t\treturn(FIRE_OK);\n\t\t}\n#endif\n\t\treturn(FIRE_CLOAKED);\n\t}\n\n\treturn(FIRE_OK);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Stun -- Prepares the object for removal from the game.                         *\n *                                                                                             *\n *    This routine handles cleaning up this techno object from the game system so that when    *\n *    it is subsequently removed, it doesn't leave any loose ends.                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Stun(void)\n{\n\tassert(IsActive);\n\n\tAssign_Target(TARGET_NONE);\n\tAssign_Destination(TARGET_NONE);\n\tTransmit_Message(RADIO_OVER_OUT);\n\tDetach_All();\n\tUnselect();\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Assign_Target -- Assigns the targeting computer with specified target.         *\n *                                                                                             *\n *    Use this routine to set the targeting computer for this object. It checks to make sure   *\n *    that targeting of itself is prohibited.                                                  *\n *                                                                                             *\n * INPUT:   target   -- The target for this object to attack.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Assign_Target(TARGET target)\n{\n\tassert(IsActive);\n\n\tif (target == TarCom) return;\n\n\tif (!Target_Legal(target)) {\n\t\ttarget = TARGET_NONE;\n\t} else {\n\n\t\t/*\n\t\t**\tPrevent targeting of self.\n\t\t*/\n\t\tif (target == As_Target()) {\n\t\t\ttarget = ::As_Target(Coord_Cell(Coord));\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tMake sure that the target is not already dead.\n\t\t\t*/\n\t\t\tObjectClass * object = As_Object(target);\n\t\t\tif (object != NULL && (object->IsActive == false || object->Strength == 0)) {\n\t\t\t\ttarget = TARGET_NONE;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tSet the unit's targeting computer.\n\t*/\n\tTarCom = target;\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Rearm_Delay -- Calculates the delay before firing can occur.                   *\n *                                                                                             *\n *    This function calculates the delay between shots. It determines this from the standard   *\n *    rate of fire (ROF) of the base class and modifies it according to game speed and         *\n *    whether this is the first or second shot. All single shot attackers consider their       *\n *    shots to be \"second\" since the second shot is the one handled normally. The first shot   *\n *    usually gets assigned a much shorter delay time before the next shot can fire.           *\n *                                                                                             *\n * INPUT:   second   -- bool; Is this the second of a two shot salvo?                          *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before the next shot may fire.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoClass::Rearm_Delay(bool second, int which) const\n{\n\tassert(IsActive);\n\n\tif (What_Am_I() == RTTI_BUILDING && Ammo > 1) {\n\t\treturn(1);\n\t}\n\n\tWeaponTypeClass const * weapon = (which == 0) ? Techno_Type_Class()->PrimaryWeapon : Techno_Type_Class()->SecondaryWeapon;\n\tif (second && weapon != NULL) {\n\t\treturn(weapon->ROF * House->ROFBias);\n\t}\n\treturn(3);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Electric_Zap -- Fires electric zap at the target specified.                    *\n *                                                                                             *\n *    This routine is used to fire an electric zap at the target specified.                    *\n *                                                                                             *\n * INPUT:   target   -- The target to fire the zap at.                                         *\n *                                                                                             *\n *          which    -- Which weapon is this zap associated with (0=primary, 1=secondary).     *\n *                                                                                             *\n *          source_coord   -- The coordinate that the zap is to originate from. This is an     *\n *                            override value and if not specifide, the normal fire coordinate  *\n *                            is used.                                                         *\n *                                                                                             *\n *          remap    -- Pointer to the zap animation remap override table. If not specified    *\n *                      then the zap remains the normal blue white color.                      *\n *                                                                                             *\n * OUTPUT:  bool; Does this object need to redraw?                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 BWG : Created.                                                                 *\n *   09/30/1996 JLB : Uses standard facing conversion and distance routines.                   *\n *=============================================================================================*/\nbool TechnoClass::Electric_Zap(TARGET target, int which, COORDINATE source_coord, unsigned char * remap)\n{\n\tint x,y,x1,y1;\n\tCOORDINATE source;\n\n\tif (source_coord != 0) {\n\t\tsource = source_coord;\n\t} else {\n\t\tsource = Fire_Coord(which);\n\t}\n\tCOORDINATE dest = As_Coord(target);\n\tif (What_Am_I() == RTTI_BUILDING) {\n\t\t((BuildingClass *)this)->IsCharging = false;\n\t}\n\tbool gonnadraw = false;\n\n\tif (Map.Push_Onto_TacMap(source, dest) && SpecialDialog == SDLG_NONE) {\n\t\tMap.Coord_To_Pixel(source, x, y);\n\t\tMap.Coord_To_Pixel(dest, x1, y1);\n\t\tx += Map.TacPixelX;\n\t\tx1 += Map.TacPixelX;\n\t\ty += Map.TacPixelY;\n\t\ty1 += Map.TacPixelY;\n\t\tSet_Logic_Page(SeenBuff);\n\t\tgonnadraw = true;\n\t}\n\n\tstatic int _shape[]={ 2, 3, 1, 0, 2, 3, 1, 0};\n\tstatic int  _xadd[8][8]={\n\t\t{ 0, 8, 8, 8, 0, 0, 0, 0},\n\t\t{ 0, 8, 8, 8, 0, 0, 0, 0},\n\t\t{ 0, 8, 8, 8, 0, 0, 0, 0},\n\t\t{ 0, 8, 8, 8, 0, 0, 0, 0},\n\t\t{ 0, 8, 8, 8, 0, 0, 0, 0},\n\t\t{-8, 0, 0, 0,-8,-8,-8,-8},\n\t\t{-8, 0, 0, 0,-8,-8,-8,-8},\n\t\t{-8, 0, 0, 0,-8,-8,-8,-8}\n\t};\n\tstatic int  _yadd[8][8]={\n\t\t{-8,-8,-8, 0, 0, 0,-8,-8},\n\t\t{-8,-8,-8, 0, 0, 0,-8,-8},\n\t\t{ 0, 0, 0, 8, 8, 8, 0, 0},\n\t\t{ 0, 0, 0, 8, 8, 8, 0, 0},\n\t\t{ 0, 0, 0, 8, 8, 8, 0, 0},\n\t\t{ 0, 0, 0, 8, 8, 8, 0, 0},\n\t\t{ 0, 0, 0, 8, 8, 8, 0, 0},\n\t\t{-8,-8,-8, 0, 0, 0,-8,-8}\n\t};\n\n\tint savex = x, savey = y;\n\tif (gonnadraw) {\n\t\tfor (int shots = 0; shots < 3; shots++) {\n\t\t\tx = savex;\n\t\t\ty = savey;\n\t\t\tint lastfacing = 0;\n\t\t\twhile (::Distance(x, y, x1, y1) > 8) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDetermine true (0..7) facing from current position to\n\t\t\t\t**\tdestination (actually the source coordinate of the zap).\n\t\t\t\t*/\n\t\t\t\tint facing = Dir_Facing(Desired_Facing8(x, y, x1, y1));\n\n\t\t\t\t/*\n\t\t\t\t** If there's quite a bit of distance to go,\n\t\t\t\t** we may vary the desired facing to give the\n\t\t\t\t** bolt some randomness.\n\t\t\t\t*/\n\t\t\t\tif (::Distance(x, y, x1, y1) > 40) {\n\t\t\t\t\tswitch (Sim_Random_Pick(1, 3 + ((shots==0) ? 3 : 0))) {\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tfacing++;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tfacing--;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tfacing &= 7;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Now that we have the direction of the bolt,\n\t\t\t\t** draw it and move the x & y coords in the right\n\t\t\t\t** direction for the next piece.\n\t\t\t\t*/\n\t\t\t\tx += _xadd[facing][lastfacing];\n\t\t\t\ty += _yadd[facing][lastfacing];\n\t\t\t\tif (remap != NULL) {\n\t\t\t\t\tCC_Draw_Shape(LightningShapes, _shape[facing]+(shots ? 4 : 0), x, y, WINDOW_TACTICAL, SHAPE_FADING|SHAPE_CENTER|SHAPE_WIN_REL, remap);\n\t\t\t\t} else {\n\t\t\t\t\tCC_Draw_Shape(LightningShapes, _shape[facing]+(shots ? 4 : 0), x, y, WINDOW_TACTICAL, SHAPE_CENTER|SHAPE_WIN_REL);\n\t\t\t\t}\n\t\t\t\tlastfacing = facing;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn (gonnadraw);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Fire_At -- Fires projectile at target specified.                               *\n *                                                                                             *\n *    This is the main projectile firing code. Buildings, units, and infantry route fire       *\n *    requests through this function.                                                          *\n *                                                                                             *\n * INPUT:   target   -- The target that the projectile is to be fired at.                      *\n *                                                                                             *\n *          which    -- Which weapon to fire.                                                  *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the projectile object that was fired. If no projectile   *\n *          could be created or there was some other illegality detected, the return value     *\n *          will be NULL.                                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *   07/03/1995 JLB : Moving platforms fire inaccurate projectiles.                            *\n *   02/22/1996 JLB : Handles camera \"weapon\" case.                                            *\n *=============================================================================================*/\nBulletClass * TechnoClass::Fire_At(TARGET target, int which)\n{\n\tassert(IsActive);\n\n\tBulletClass * bullet;\t\t\t\t// Projectile.\n\tDirType dir;\t\t\t\t\t// The facing to impart upon the projectile.\n\tCOORDINATE target_coord;\t\t// Coordinate of the target.\n\tCOORDINATE fire_coord;\t\t\t// Coordinate of firing position.\n\tTechnoTypeClass const & tclass = *Techno_Type_Class();\n\tObjectClass * object;\n\tWeaponTypeClass const * weapon = (which == 0) ? tclass.PrimaryWeapon : tclass.SecondaryWeapon;\n\n\t/*\n\t**\tIf this object doesn't have a weapon, then it is obvious that firing\n\t**\tcannot ever succeed. Return with failure flag.\n\t*/\n\tif (weapon == NULL) return(NULL);\n\n\tBulletTypeClass const & btype = *weapon->Bullet;\n\n\t/*\n\t**\tPerform a quick legality check to see if firing can occur.\n\t*/\n\tif (Debug_Map || !Target_Legal(target)) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tFetch the target coordinate for the target specified.\n\t*/\n\tobject = As_Object(target);\n\tif (object != NULL) {\n\t\ttarget_coord = object->Target_Coord();\n\t} else {\n\t\ttarget_coord = As_Coord(target);\n\t}\n\n\t/*\n\t**\tGet the location where the projectile should appear.\n\t*/\n\tfire_coord = Fire_Coord(which);\n\n\t/*\n\t**\tIf the projectile is a homing type (such as a missile), then it will\n\t**\tlaunch in the direction the turret is facing, NOT necessarily the same\n\t**\tdirection as the target.\n\t*/\n\tif (btype.ROT != 0 || btype.IsDropping) {\n\t\tdir = Fire_Direction();\n\t\tif (btype.IsDropping) {\n\t\t\tfire_coord = Center_Coord();\n\t\t}\n\t} else {\n\t\tdir = ::Direction(fire_coord, target_coord);\n\t}\n\n\t/*\n\t**\tCreate the projectile. Then process any special operations that\n\t**\tneed to be performed according to the style of projectile\n\t**\tcreated.\n\t*/\n\tint firepower = weapon->Attack;\n\tif (firepower > 0) {\n\t\tfirepower = weapon->Attack * FirepowerBias * House->FirepowerBias;\n\t}\n\n\n\t/*\n\t**\tGive the bullet a boost of speed if the weapon indicates that this is required. Only\n\t**\tneed to perform this check if the target is an aircraft.\n\t*/\n\tint firespeed = weapon->MaxSpeed;\n\tif (weapon->IsTurboBoosted && Is_Target_Aircraft(target)) {\n\t\tfirespeed *= Rule.TurboBoost;\n\t}\n\n \tbullet = new BulletClass(weapon->Bullet->Type, target, this, firepower, WarheadType(weapon->WarheadPtr->ID), firespeed);\n\n\tif (bullet != NULL) {\n\n\t\t/*\n\t\t**\tIf this is firing from a moving platform, then the projectile is inaccurate.\n\t\t*/\n\t\tif (Is_Foot() && ((FootClass const *)this)->IsDriving) {\n\t\t\tbullet->IsInaccurate = true;\n\t\t}\n\n\t\tif (bullet->Unlimbo(fire_coord, dir)) {\n\t\t} else {\n\t\t\tdelete bullet;\n\t\t}\n\t\tif (tclass.IsTurretEquipped) {\n\t\t\tIsInRecoilState = true;\n\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t}\n\n\t\tArm = Rearm_Delay(IsSecondShot, which);\n\t\tif (tclass.Is_Two_Shooter()) {\n\t\t\tIsSecondShot = (IsSecondShot == false);\n\t\t}\n\n\t\t/*\n\t\t**\tPerform any animation effect for this weapon.\n\t\t*/\n\t\tAnimType a = weapon->Anim;\n\t\tswitch (a) {\n\t\t\tcase ANIM_GUN_N:\n\t\t\t\ta = AnimType(a + Dir_Facing(Fire_Direction()));\n\t\t\t\tbreak;\n\n\t\t\tcase ANIM_SAM_N:\n\t\t\t\ta = AnimType(ANIM_SAM_N + Dir_Facing(PrimaryFacing.Current()));\n\t\t\t\tbreak;\n\t\t}\n\n  \t\t/*\n\t\t**\tPlay any sound effect tied to this weapon type.\n\t\t*/\n\t\tSound_Effect(weapon->Sound, Fire_Coord(which));\n\n\t\t/*\n\t\t**\tIf there is a special firing animation, then create and attach it\n\t\t**\tnow.\n\t\t*/\n\t\tif (a != ANIM_NONE) {\n\t\t\tAnimClass * anim = new AnimClass(a, Fire_Coord(which));\n\t\t\tif (anim != NULL) {\n\t\t\t\tanim->Attach_To(this);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tElectric zap animation.\n\t\t*/\n\t\tif (weapon->IsElectric) {\n\t\t\tbool gonnadraw = Electric_Zap(target, which);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif(What_Am_I() != RTTI_INFANTRY) {\n\t\t\t\tSet_Stage(0);\n\t\t\t\tSet_Rate(0);\n\t\t\t}\n#else\n\t\t\tSet_Stage(0);\n\t\t\tSet_Rate(0);\n#endif\n\t\t\tif (Ammo <= 1 && What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t((BuildingClass *)this)->IsCharged = false;\n\t\t\t}\n\n\t\t\tTechnoClass * tech = As_Techno(target);\n\t\t\tif (tech != NULL)  {\n\t\t\t\ttech->Clicked_As_Target(4);\n\t\t\t}\n\n\t\t\tDelay(1);\t// Make sure line is visible briefly\n\t\t\tif (gonnadraw) {\n\t\t\t\tMap.Flag_To_Redraw(true);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tReduce ammunition for this object.\n\t\t*/\n\t\tif (Ammo > 0) {\n\t\t\tAmmo--;\n\t\t}\n\n\t\t/*\n\t\t**\tFiring will in all likelihood, require the unit to be redrawn. Flag it to be\n\t\t**\tredrawn here.\n\t\t*/\n\t\tMark(MARK_CHANGE);\n\n\t\t/*\n\t\t**\tIf a projectile was fired from a unit that is hidden in the darkness,\n\t\t**\treveal that unit and a little area around it.\n\t\t** For multiplayer games, only reveal the unit if the target is the\n\t\t** local player.\n\t\t*/\n\t\tif ((!IsOwnedByPlayer && !IsDiscoveredByPlayer) || (!Map[Center_Coord()].IsMapped && (What_Am_I()!=RTTI_AIRCRAFT || !IsOwnedByPlayer)) ) {\n\t\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\t\tMap.Sight_From(Coord_Cell(Center_Coord()), 2, PlayerPtr, false);\n\t\t\t} else {\n\t\t\t\tObjectClass * obj = As_Object(target);\n\t\t\t\tif (obj != NULL) {\n\t\t\t\t\tHousesType tgt_owner = obj->Owner();\n\n\t\t\t\t\tif (PlayerPtr->Class->House == tgt_owner) {\n\t\t\t\t\t\tMap.Sight_From(Coord_Cell(Center_Coord()), 2, PlayerPtr, false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(bullet);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Player_Assign_Mission -- Assigns a mission as result of player input.          *\n *                                                                                             *\n *    This routine is called when the mission for an object needs to change as a result of     *\n *    player input. The basic operation would be to queue the event and let the action         *\n *    occur at the frame dictated by the queuing system. However, if a voice response is       *\n *    indicated, then perform it at this time. This will give a greater illusion of            *\n *    immediate response.                                                                      *\n *                                                                                             *\n * INPUT:   mission     -- The mission order to assign to this object.                         *\n *                                                                                             *\n *          target      -- The target of this object. This will be used for combat and attack. *\n *                                                                                             *\n *          destination -- The movement destination for this object.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Player_Assign_Mission(MissionType mission, TARGET target, TARGET destination)\n{\n\tassert(IsActive);\n\n\tif (AllowVoice) {\n\t\tif (mission == MISSION_ATTACK) {\n\t\t\tResponse_Attack();\n\t\t} else {\n\t\t\tResponse_Move();\n\t\t}\n\t}\n\n\tif (FormMove) {\n\t\tQueue_Mission(TargetClass(this), mission, target, destination, FormSpeed, FormMaxSpeed);\n\t} else {\n\n\t\t/*\n\t\t**\tCooerce the movement mission into a queued movement mission if the ALT key was\n\t\t**\theld down.\n\t\t*/\n\t\tif (mission == MISSION_MOVE && (Keyboard->Down(Options.KeyQueueMove1) || Keyboard->Down(Options.KeyQueueMove2))) {\n\t\t\tmission = MISSION_QMOVE;\n\t\t}\n\n\t\tQueue_Mission(TargetClass(this), mission, target, destination);\n\t}\n}\n\n\n/***********************************************************************************************\n * TechnoClass::What_Action -- Determines what action to perform if object is selected.        *\n *                                                                                             *\n *    This routine will examine the object specified and return with the action that will      *\n *    be performed if the mouse button were clicked over the object.                           *\n *                                                                                             *\n * INPUT:   object   -- The object that the mouse button might be clicked on.                  *\n *                                                                                             *\n * OUTPUT:  Returns with the action that will be performed if the object was clicked on.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *   03/21/1995 JLB : Special target control for trees.                                        *\n *=============================================================================================*/\nActionType TechnoClass::What_Action(ObjectClass const * object) const\n{\n\tassert(IsActive);\n\n\tif (object != NULL) {\n\n\t\t/*\n\t\t**\tReturn the ACTION_SELF flag if clicking on itself. However, if this\n\t\t**\tobject cannot do anything special with itself, then just return with\n\t\t**\tthe no action flag.\n\t\t*/\n\t\tif (object == this && CurrentObject.Count() == 1 && House->IsPlayerControl) {\n\t\t\treturn(ACTION_SELF);\n\t\t}\n\n\t\tbool altdown = (Keyboard->Down(Options.KeyForceMove1) || Keyboard->Down(Options.KeyForceMove2));\n\t\tbool ctrldown = (Keyboard->Down(Options.KeyForceAttack1) || Keyboard->Down(Options.KeyForceAttack2));\n\t\tbool shiftdown = (Keyboard->Down(Options.KeySelect1) || Keyboard->Down(Options.KeySelect2));\n\n\t\t/*\n\t\t**\tSpecial guard area mission is possible if both the control and the\n\t\t**\talt keys are held down.\n\t\t*/\n\t\tif (House->IsPlayerControl && ctrldown && altdown && Can_Player_Move() /*KO && Can_Player_Fire()*/) {\n//\t\tif (House->IsPlayerControl && ctrldown && altdown && Can_Player_Move() && Can_Player_Fire()) {\n\t\t\treturn(ACTION_GUARD_AREA);\n\t\t}\n\n\t\t/*\n\t\t**\tSpecial override to force a move regardless of what is occupying the location.\n\t\t*/\n\t\tif (altdown) {\n\t\t\tif (House->IsPlayerControl && Can_Player_Move()) {\n\t\t\t\treturn(ACTION_MOVE);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tOverride so that toggled select state can be performed while the <SHIFT> key\n\t\t**\tis held down.\n\t\t*/\n\t\tif (shiftdown) {\n\t\t\tif (House->IsPlayerControl && !IsALoaner) {\n\t\t\t\treturn(ACTION_TOGGLE_SELECT);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf the weapon is blatantly disallowed from firing on the object specified, then\n\t\t**\tdon't allow the attach check logic to proceed.\n\t\t*/\n\t\tTechnoTypeClass const * ttype = Techno_Type_Class();\n\t\tif (Is_Weapon_Equipped() &&\n\t\t\t\tttype->PrimaryWeapon->Bullet != NULL &&\n\t\t\t\tttype->PrimaryWeapon->Bullet->IsSubSurface &&\n\t\t\t\tMap[object->Target_Coord()].Land_Type() != LAND_WATER) {\n\n\t\t\t// Do nothing.\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf firing is possible and legal, then return this action potential.\n\t\t\t*/\n\t\t\tif (House->IsPlayerControl && (ctrldown || !House->Is_Ally(object)) && (ctrldown || object->Class_Of().IsLegalTarget || (Rule.IsTreeTarget && object->What_Am_I() == RTTI_TERRAIN))) {\n\n\t\t\t\tif (Is_Weapon_Equipped() ||\n\t\t\t\t\t\t(What_Am_I() == RTTI_INFANTRY &&\n\t\t\t\t\t\t(((InfantryTypeClass const *)ttype)->IsBomber ||\n\t\t\t\t\t\t((InfantryTypeClass const *)ttype)->IsCapture)\n\t\t\t\t\t\t)) {\n\n\t\t\t\t\tint primary = What_Weapon_Should_I_Use(object->As_Target());\n\t\t\t\t\tif (Can_Player_Move() || In_Range(object, primary)) {\n\t\t\t\t\t\tif (In_Range(object, primary) || (What_Am_I() == RTTI_INFANTRY && ((InfantryClass *)this)->Class->IsCapture && object->What_Am_I() == RTTI_BUILDING && ((BuildingClass *)object)->Class->IsCaptureable)) {\n\t\t\t\t\t\t\treturn(ACTION_ATTACK);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (!Can_Player_Move()) {\n\t\t\t\t\t\t\t\treturn(ACTION_NONE);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\treturn(ACTION_ATTACK);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tPossibly try to select the specified object, if that is warranted.\n\t\t*/\n\t\tif (!Is_Weapon_Equipped() || !House->IsPlayerControl || object->Owner() == Owner()) {\n\t\t\tif ((!IsALoaner || !IsOwnedByPlayer) && object->Class_Of().IsSelectable && !object->IsSelected) {\n\t\t\t\treturn(ACTION_SELECT);\n\t\t\t}\n\t\t\treturn(ACTION_NONE);\n\t\t}\n\t}\n\treturn(ACTION_NONE);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::What_Action -- Determines action to perform if cell is clicked on.             *\n *                                                                                             *\n *    Use this routine to determine what action will be performed if the specified cell        *\n *    is clicked on. Usually this action is either a ACTION_MOVE or ACTION_NOMOVE. The action  *\n *    nomove is used to perform special case checking for nearby cells if in fact the mouse    *\n *    is clicked over the cell.                                                                *\n *                                                                                             *\n * INPUT:   cell  -- The cell to check for being clicked over.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the action that will occur if the cell is clicked on.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *   07/10/1995 JLB : Force fire for buildings is explicitly disabled.                         *\n *=============================================================================================*/\nActionType TechnoClass::What_Action(CELL cell) const\n{\n\tassert(IsActive);\n\n\tCellClass const * cellptr = &Map[cell];\n\tOverlayTypeClass const * optr = NULL;\n\n\tbool ctrldown = Keyboard->Down(Options.KeyForceAttack1) || Keyboard->Down(Options.KeyForceAttack2);\n\tbool shiftdown = Keyboard->Down(Options.KeySelect1) || Keyboard->Down(Options.KeySelect2);\n\tbool altdown = (Keyboard->Down(Options.KeyForceMove1) || Keyboard->Down(Options.KeyForceMove2));\n\n\t/*\n\t**\tDisable recognizing the <CTRL> key forced fire option when dealing with buildings.\n\t*/\n\tif (What_Am_I() == RTTI_BUILDING) ctrldown = false;\n\n\t/*\n\t**\tDisable recognizing the <CTRL> key forced fire option when dealing with submarines.\n\t*/\n\tif(What_Am_I() == RTTI_VESSEL) {\n\t\tWeaponTypeClass const * weapon = ((VesselClass *)this)->Class->PrimaryWeapon;\n\t\tif (weapon && weapon->Bullet->IsSubSurface) ctrldown = false;\n\t}\n\n\n\tif (cellptr->Overlay != OVERLAY_NONE) {\n\t\toptr = &OverlayTypeClass::As_Reference(cellptr->Overlay);\n\t}\n\n\t/*\n\t**\tSpecial guard area mission is possible if both the control and the\n\t**\talt keys are held down.\n\t*/\n\tif (House->IsPlayerControl && ctrldown && altdown && Can_Player_Move() && Can_Player_Fire()) {\n\t\treturn(ACTION_GUARD_AREA);\n\t}\n\n\tif (House->IsPlayerControl && Techno_Type_Class()->PrimaryWeapon != NULL && (ctrldown || (optr && optr->IsLegalTarget))) {\n\t\tWarheadTypeClass const * whead = Techno_Type_Class()->PrimaryWeapon->WarheadPtr;\n\n// To be fixed for firing on ore by accounting for ore and ignoring the overlay in that case.\n\n\t\tif (optr == NULL || (optr->IsWall && (whead->IsWallDestroyer || (whead->IsWoodDestroyer && optr->IsWooden)))) {\n\t\t\tint primary = What_Weapon_Should_I_Use(::As_Target(cell));\n\t\t\tif (Can_Player_Move() || In_Range(::As_Target(cell), primary)) {\n\t\t\t\treturn(ACTION_ATTACK);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (House->IsPlayerControl && Can_Player_Move()) {\n\n\t\t/*\n\t\t**\tSpecial override to force a move regardless of what is occupying the location.\n\t\t*/\n\t\tif (shiftdown) {\n\t\t\treturn(ACTION_MOVE);\n\t\t}\n\n\t\t/*\n\t\t**\tIf the object can enter the cell specified, then allow\n\t\t**\tmovement to it.\n\t\t*/\n\t\tif (Can_Enter_Cell(cell) <= MOVE_CLOAK) {\n\t\t\treturn(ACTION_MOVE);\n\t\t}\n\t\treturn(ACTION_NOMOVE);\n\t}\n\n\treturn(ACTION_NONE);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Can_Player_Move -- Determines if the object can move be moved by player.       *\n *                                                                                             *\n *    Use this routine to determine whether a movement order can be given to this object.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Can this object be given a movement order by the player?                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::Can_Player_Move(void) const\n{\n\tassert(IsActive);\n\n\treturn(House->IsPlayerControl);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Can_Player_Fire -- Determines if the player can give this object a fire order. *\n *                                                                                             *\n *    Call this routine to determine if this object can be given a fire order by the player.   *\n *    Such objects will affect the mouse cursor accordingly -- usually causes the targeting    *\n *    cursor to appear.                                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Can this object be given firing orders by the player?                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::Can_Player_Fire(void) const\n{\n\tassert(IsActive);\n\n\tif (House->IsPlayerControl && Is_Techno() && Techno_Type_Class()->PrimaryWeapon != NULL) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Is_Weapon_Equipped -- Determines if this object has a combat weapon.           *\n *                                                                                             *\n *    Use this routine to determine if this object is equipped with a combat weapon. Such      *\n *    determination is used by the AI system to gauge the threat potential of the object.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is this object equipped with a combat weapon?                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::Is_Weapon_Equipped(void) const\n{\n\tassert(IsActive);\n\n\treturn(Techno_Type_Class()->PrimaryWeapon != NULL);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Can_Repair -- Determines if the object can and should be repaired.             *\n *                                                                                             *\n *    Use this routine to determine if the specified object is a candidate for repair. In      *\n *    order to qualify, the object must be allowed to be repaired (in theory) and it must      *\n *    be below full strength. If these conditions are met, then it can be repaired.            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; May this unit be repaired? A return value of false may mean that the object  *\n *                is not allowed to be repaired, or it might be full strength already.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::Can_Repair(void) const\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tTemporary hack to disable repair cursor over non-buildings.\n\t*/\n\tif (What_Am_I() != RTTI_BUILDING) {\n\t\treturn(false);\n\t}\n\treturn(Techno_Type_Class()->IsRepairable && Strength != Class_Of().MaxStrength);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Weapon_Range -- Determines the maximum range for the weapon.                   *\n *                                                                                             *\n *    Use this routine to determine the maximum range for the weapon indicated.                *\n *                                                                                             *\n * INPUT:   which -- Which weapon to use when determining the range. 0=primary, 1=secondary.   *\n *                                                                                             *\n * OUTPUT:  Returns with the range of the weapon (in leptons).                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoClass::Weapon_Range(int which) const\n{\n\tassert(IsActive);\n\tassert((unsigned)which < 2);\n\n\tWeaponTypeClass const * weapon = NULL;\n\tTechnoTypeClass const & ttype = *Techno_Type_Class();\n\n\tswitch (which) {\n\t\tcase 0:\n\t\t\tweapon = ttype.PrimaryWeapon;\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tweapon = ttype.SecondaryWeapon;\n\t\t\tbreak;\n\t}\n\tif (weapon != NULL) {\n\t\treturn(weapon->Range);\n\t}\n\treturn(0);\n}\n\n\n/***************************************************************************\n * TechnoClass::Override_Mission -- temporarily overrides a units mission  *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:      MissionType mission - the mission we want to override       *\n *               TARGET      tarcom  - the new target we want to override  *\n *               TARGET      navcom  - the new navigation point to override*\n *                                                                         *\n * OUTPUT:      none                                                       *\n *                                                                         *\n * WARNINGS:   If a mission is already overridden, the current mission is  *\n *               just re-assigned.                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/28/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid TechnoClass::Override_Mission(MissionType mission, TARGET tarcom, TARGET navcom)\n{\n\tassert(IsActive);\n\n\tSuspendedTarCom = TarCom;\n\tRadioClass::Override_Mission(mission, tarcom, navcom);\n\tAssign_Target(tarcom);\n}\n\n\n/***************************************************************************\n * TechnoClass::Restore_Mission -- Restores an overridden mission          *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/28/1995 PWG : Created.                                             *\n *=========================================================================*/\nbool TechnoClass::Restore_Mission(void)\n{\n\tassert(IsActive);\n\n\tif (RadioClass::Restore_Mission()) {\n\t\tAssign_Target(SuspendedTarCom);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Renovate -- Heal a building to maximum                                         *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/15/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Renovate(void)\n{\n\tassert(IsActive);\n\n\tMark(MARK_CHANGE);\n\tStrength = Techno_Type_Class()->MaxStrength;\n\tif (What_Am_I() == RTTI_BUILDING) {\n\t\t((BuildingClass *)this)->Repair(0);\n\t}\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Captured -- Handles capturing this object.                                     *\n *                                                                                             *\n *    This routine is called when this object gets captured by the house specified. It handles *\n *    removing this object from any targeting computers and then changes the ownership of      *\n *    the object to the new house.                                                             *\n *                                                                                             *\n * INPUT:   newowner -- Pointer to the house that is now the new owner.                        *\n *                                                                                             *\n * OUTPUT:  Was the object captured? Failure would mean that it is already under control of    *\n *          the house specified.                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *   09/29/1995 JLB : Keeps track of quantity records.                                         *\n *=============================================================================================*/\nbool TechnoClass::Captured(HouseClass * newowner)\n{\n\tassert(IsActive);\n\n\tif (newowner != House) {\n\n\t\t/*\n\t\t**\tCapture attempt springs any \"entered\" trigger. The entered trigger\n\t\t**\toccurs first since there may be a special trigger attached to this\n\t\t**\tobject that flags a capture as a win and a destroy as a loss. This\n\t\t**\torder is necessary because the object is recorded as a kill as well.\n\t\t*/\n\t\tif (Trigger.Is_Valid()) {\n\t\t\tTrigger->Spring(TEVENT_PLAYER_ENTERED, this);\n\t\t}\n\n\t\t/*\n\t\t**\tRecord this as a kill.\n\t\t*/\n\t\tRecord_The_Kill(NULL);\n\n\t\t/*\n\t\t**\tSpecial kill record logic for capture process.\n\t\t*/\n\t\tHouse->Tracking_Remove(this);\n\t\tnewowner->Tracking_Add(this);\n\t\tswitch (What_Am_I()) {\n\t\t\tcase RTTI_BUILDING:\n\t\t\t\tnewowner->BuildingsKilled[Owner()]++;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_AIRCRAFT:\n\t\t\tcase RTTI_INFANTRY:\n\t\t\tcase RTTI_UNIT:\n\t\t\tcase RTTI_VESSEL:\n\t\t\t\tnewowner->UnitsKilled[Owner()]++;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\tHouse->WhoLastHurtMe = newowner->Class->House;\n\n\t\t/*\n\t\t**\tRemove from targeting computers.\n\t\t*/\n\t\tDetach_All(false);\n\n\t\t/*\n\t\t**\tChange ownership now.\n\t\t*/\n\t\tHouse = newowner;\n\t\tIsOwnedByPlayer = (House == PlayerPtr);\n\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Take_Damage -- Records damage assessed to this object.                         *\n *                                                                                             *\n *    This routine is called when this object has taken damage. It handles recording whether   *\n *    this object has been destroyed. If it has, then mark the appropriate kill records as     *\n *    necessary.                                                                               *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nResultType TechnoClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, int forced)\n{\n\tassert(IsActive);\n\n\tResultType result = RESULT_NONE;\n\n\t/*\n\t**\tIf not a forced damage condition, adjust damage according to house override armor\n\t**\tvalue.\n\t*/\n\tif (!forced && damage > 0) {\n\t\tdamage = damage * ArmorBias * House->ArmorBias;\n\t}\n\n\tif (IronCurtainCountDown == 0) {\n\t\tresult = ObjectClass::Take_Damage(damage, distance, warhead, source, forced);\n\t}\n\n\tswitch (result) {\n\t\tcase RESULT_DESTROYED:\n\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\tStun();\n\n\t\t\t/*\n\t\t\t**\tIf this object explodes with violent damage, then perform the explosion\n\t\t\t**\tnow and use the warhead type and full strength as the explosion values.\n\t\t\t*/\n\t\t\tif (Techno_Type_Class()->IsExploding) {\n\n\t\t\t\t/*\n\t\t\t\t**\tThe warhead to use is based on the weapon this object is equipped with.\n\t\t\t\t*/\n\t\t\t\tWarheadType wh = WARHEAD_HE;\n\t\t\t\tif (Techno_Type_Class()->PrimaryWeapon != NULL) {\n\t\t\t\t\twh = WarheadType(Techno_Type_Class()->PrimaryWeapon->WarheadPtr->ID);\n\t\t\t\t}\n\n\t\t\t\tint damage = Techno_Type_Class()->MaxStrength;\n\t\t\t\tnew AnimClass(Combat_Anim(damage, wh, Map[Center_Coord()].Land_Type()), Center_Coord());\n\t\t\t\tint radius = damage * Rule.ExplosionSpread;\n//\t\t\t\tint radius = damage/2;\n\t\t\t\tWide_Area_Damage(Center_Coord(), radius, damage, source, wh);\n\t\t\t}\n\n\t\t\tif (this == (TechnoClass *)::As_Object(House->UnitToTeleport)) {\n\t\t\t\tHouse->UnitToTeleport = 0;\n\t\t\t\tif (!Scen.IsFadingColor) {\n\t\t\t\t\tScen.IsFadingBW = false;\n\t\t\t\t\tScen.IsFadingColor = true;\n\t\t\t\t\tScen.FadeTimer = GRAYFADETIME;\n\t\t\t\t}\n\t\t\t\tif (Map.IsTargettingMode == SPC_CHRONO2) {\n\t\t\t\t\tKeyNumType input = KN_RMOUSE;\n\t\t\t\t\tMap.AI(input, 0, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tIf some damage was received and this object is cloaked, shimmer\n\t\t**\tthe cloak a bit.\n\t\t*/\n\t\tdefault:\n\t\t\tif (source != NULL && !House->Is_Ally(source)) {\n\t\t\t\tIsTickedOff = true;\n\t\t\t}\n\t\t\tDo_Shimmer();\n\t\t\tbreak;\n\n\t\tcase RESULT_NONE:\n\t\t\tbreak;\n\t}\n\treturn(result);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Record_The_Kill -- Records the death of this object.                           *\n *                                                                                             *\n *    This routine is used to record the death of this object. It will handle updating the     *\n *    owner house with the kill record as well as springing any trigger events associated with *\n *    this object's death.                                                                     *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the source of this object's death (if there is a source).   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *   08/23/1995 JLB : Building loss is only counted if it received damage.                     *\n *=============================================================================================*/\nvoid TechnoClass::Record_The_Kill(TechnoClass * source)\n{\n\tassert(IsActive);\n\n\tint total_recorded = 0;\n\n\tint points = Techno_Type_Class()->Points;\n\n\t/*\n\t**\tHandle any trigger event associated with this object.\n\t*/\n\tif (Trigger.Is_Valid() && source) Trigger->Spring(TEVENT_ATTACKED, this);\n\n\tif (Trigger.Is_Valid() && source) Trigger->Spring(TEVENT_DISCOVERED, this);\n\n\tif (Trigger.Is_Valid()) Trigger->Spring(TEVENT_DESTROYED, this);\n\n\tif (source != NULL) {\n\t\tCrew.Made_A_Kill();\n\n\t\tHouse->WhoLastHurtMe = source->Owner();\n\n\t\t/*\n\t\t** Add up the score for killing this unit\n\t\t*/\n\t\tsource->House->PointTotal += points;\n\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// Hack check: if they were trying to teleport this unit when it died, take\n//\tthe map mode out of teleportation mode.\n\tif(IsOwnedByPlayer && Map.IsTargettingMode == SPC_CHRONO2 && House->UnitToTeleport == As_Target()) {\n\t\tMap.IsTargettingMode = SPC_NONE;\n\t}\n#endif\n\tswitch (What_Am_I()) {\n\t\tcase RTTI_BUILDING:\n\t\t\t{\n\t\t\t\tStructType bldg = *(BuildingClass *)this;\n\t\t\t\tif (bldg != STRUCT_BARREL && bldg != STRUCT_BARREL3 &&\n\t\t\t\t\t bldg != STRUCT_APMINE && bldg != STRUCT_AVMINE) {\n\t\t\t\t\tif (((BuildingClass *)this)->WhoLastHurtMe != HOUSE_NONE) {\n\t\t\t\t\t\tHouse->BuildingsLost++;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (source != NULL) {\n\t\t\t\t\t\tif (Session.Type == GAME_INTERNET) {\n\t\t\t\t\t\t\tsource->House->DestroyedBuildings->Increment_Unit_Total( ((BuildingClass*)this)->Class->Type );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsource->House->BuildingsKilled[Owner()]++;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If the map is displaying the multiplayer player names & their\n\t\t\t\t\t** # of kills, tell it to redraw.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Map.Is_Player_Names()) {\n\t\t\t\t\t\tMap.Player_Names(true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_AIRCRAFT:\n\t\t\tif (source != NULL && Session.Type == GAME_INTERNET) {\n\t\t\t\tsource->House->DestroyedAircraft->Increment_Unit_Total( ((AircraftClass*)this)->Class->Type );\n\t\t\t\ttotal_recorded++;\n\t\t\t}\n\t\t\t//Fall through.....\n\t\tcase RTTI_INFANTRY:\n\t\t\tif (source != NULL && !total_recorded && Session.Type == GAME_INTERNET) {\n\t\t\t\tsource->House->DestroyedInfantry->Increment_Unit_Total( ((InfantryClass*)this)->Class->Type );\n\t\t\t\ttotal_recorded++;\n\t\t\t}\n\t\t\t//Fall through.....\n\t\tcase RTTI_UNIT:\n\t\t\tif (source != NULL && !total_recorded && Session.Type == GAME_INTERNET) {\n\t\t\t\tsource->House->DestroyedUnits->Increment_Unit_Total( ((UnitClass*)this)->Class->Type );\n\t\t\t\ttotal_recorded++;\n\t\t\t}\n\t\t\t//Fall through.....\n\t\tcase RTTI_VESSEL:\n\t\t\tif (source != NULL && !total_recorded && Session.Type == GAME_INTERNET) {\n\t\t\t\tsource->House->DestroyedUnits->Increment_Unit_Total( ((VesselClass*)this)->Class->Type );\n\t\t\t}\n\n\t\t\tHouse->UnitsLost++;\n\t\t\tif (source != NULL) source->House->UnitsKilled[Owner()]++;\n\n\t\t\t/*\n\t\t\t** If the map is displaying the multiplayer player names & their\n\t\t\t** # of kills, tell it to redraw.\n\t\t\t*/\n\t\t\tif (Map.Is_Player_Names()) {\n\t\t\t\tMap.Player_Names(true);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t** Since we lost an object, we lose the associated points as well.\n\t*/\n\tHouse->PointTotal -= points;\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Nearby_Location -- Radiates outward looking for clear cell nearby.             *\n *                                                                                             *\n *    This routine is used to find a nearby location from center of this object. It can lean   *\n *    toward finding a location closest to an optional object.                                 *\n *                                                                                             *\n * INPUT:   object   -- Optional object that the finding algorithm will try to find a close    *\n *                      spot to.                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the cell that is closest to this object.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1995 JLB : Created.                                                                 *\n *   09/28/1995 JLB : Uses map scan function.                                                  *\n *=============================================================================================*/\nCELL TechnoClass::Nearby_Location(TechnoClass const * techno) const\n{\n\tassert(IsActive);\n\n\tSpeedType speed = Techno_Type_Class()->Speed;\n\tif (speed == SPEED_WINGED) {\n\t\tspeed = SPEED_TRACK;\n\t}\n\n\tCELL cell = 0;\n\tif (techno != NULL) {\n\t\tcell = Coord_Cell(techno->Center_Coord());\n\t} else {\n\t\tcell = Coord_Cell(Center_Coord());\n\t}\n\n\treturn(Map.Nearby_Location(cell, speed, Map[cell].Zones[Techno_Type_Class()->MZone], Techno_Type_Class()->MZone));\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Do_Uncloak -- Cause the stealth tank to uncloak.                               *\n *                                                                                             *\n *    This routine will start the stealth tank to uncloak.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Do_Uncloak(void)\n{\n\tassert(IsActive);\n\n\tif (IsCloakable && (Cloak == CLOAKED || Cloak == CLOAKING)) {\n\t\tif (Cloak == CLOAKED) {\n\t\t\tMap.RadarClass::Flag_To_Redraw(true);\n\t\t}\n\t\tCloak = UNCLOAKING;\n\t\tCloakingDevice.Set_Stage(0);\n\t\tCloakingDevice.Set_Rate(1);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tif(What_Am_I() == RTTI_VESSEL) {\n\t\t\tSound_Effect(VOC_SUBSHOW, Coord);\n\t\t} else {\n\t\t\tSound_Effect(VOC_IRON1, Coord);\n\t\t}\n#else\n\t\tSound_Effect(VOC_SUBSHOW, Coord);\n#endif\n\t}\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Do_Cloak -- Start the object into cloaking stage.                              *\n *                                                                                             *\n *    This routine will start the object into its cloaking state.                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Do_Cloak(void)\n{\n\tassert(IsActive);\n\n\tif (IsCloakable && (Cloak == UNCLOAKED || Cloak == UNCLOAKING)) {\n\t\tDetach_All(false);\n\n\t\tif (Cloak == UNCLOAKED) {\n\t\t\tMap.RadarClass::Flag_To_Redraw(true);\n\t\t}\n\n\t\tCloak = CLOAKING;\n\t\tCloakingDevice.Set_Stage(0);\n\t\tCloakingDevice.Set_Rate(1);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tif(What_Am_I() == RTTI_VESSEL) {\n\t\t\tSound_Effect(VOC_SUBSHOW, Coord);\n\t\t} else {\n\t\t\tSound_Effect(VOC_IRON1, Coord);\n\t\t}\n#else\n\t\tSound_Effect(VOC_SUBSHOW, Coord);\n#endif\n\t}\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Do_Shimmer -- Causes this object to shimmer if it is cloaked.                  *\n *                                                                                             *\n *    This routine is called when this object should shimmer. If the object is cloaked, then   *\n *    a shimmering effect (partial decloak) occurs. For objects that are not cloaked, no       *\n *    effect occurs.                                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Do_Shimmer(void)\n{\n\tassert(IsActive);\n#if(0)\n\tif (IsCloakable && Cloak == CLOAKED) {\n\t\tCloak = CLOAKING;\n\t\tCloakingDevice.Set_Stage(MAX_UNCLOAK_STAGE/2);\n\t\tCloakingDevice.Set_Rate(1);\n\t}\n#else\n\tDo_Uncloak();\n#endif\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Visual_Character -- Determine the visual character of the object.              *\n *                                                                                             *\n *    This routine will determine how this object should be drawn. Typically, this is the      *\n *    unmodified visible state, but cloaked objects have a different character.                *\n *                                                                                             *\n * INPUT:   raw   -- Should the check be based on the unmodified cloak condition of the        *\n *                   object? If false, then an object owned by the player will never become    *\n *                   completely invisible.                                                     *\n *                                                                                             *\n * OUTPUT:  Returns with the visual character to use when displaying this object.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/07/1995 JLB : Created.                                                                 *\n *   05/27/1996 JLB : Knows about invisible objects.                                           *\n *=============================================================================================*/\nVisualType TechnoClass::Visual_Character(bool raw) const\n{\n\tassert(IsActive);\n\n\tif (Techno_Type_Class()->IsInvisible && IsOwnedByPlayer) return(VISUAL_NORMAL);\n\tif (Techno_Type_Class()->IsInvisible && !IsOwnedByPlayer && !Debug_Map) return(VISUAL_HIDDEN);\n\n\t/*\n\t**\tWhen uncloaked or in map editor mode, always draw the object normally.\n\t*/\n\tif (Cloak == UNCLOAKED || Debug_Map) return(VISUAL_NORMAL);\n\n\t/*\n\t**\tA cloaked unit will not be visible at all unless it is owned\n\t**\tby the player.\n\t*/\n\tif (Cloak == CLOAKED) {\n\t\tif (!raw && IsOwnedByPlayer) return(VISUAL_SHADOWY);\n\t\treturn(VISUAL_HIDDEN);\n\t}\n\n\tint stage = CloakingDevice.Fetch_Stage();\n\tif (Cloak == UNCLOAKING) stage = MAX_UNCLOAK_STAGE - stage;\n\tif (stage <= 0) {\n\t\treturn(VISUAL_NORMAL);\n\t}\n\n\tstage = fixed(stage, MAX_UNCLOAK_STAGE) * 256;\n\n\tif (stage < 0x0040) return(VISUAL_INDISTINCT);\n\tif (stage < 0x0080) return(VISUAL_DARKEN);\n\tif (stage < 0x00C0) return(VISUAL_SHADOWY);\n\tif (!raw && IsOwnedByPlayer) return(VISUAL_SHADOWY);\n\tif (stage < 0x00FF) return(VISUAL_RIPPLE);\n\treturn(VISUAL_HIDDEN);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Techno_Draw_Object -- General purpose draw object routine.                     *\n *                                                                                             *\n *    This routine is used to draw the object. It will handle any remapping or cloaking        *\n *    effects required. This logic is isolated here since all techno object share the same     *\n *    render logic when it comes to remapping and cloaking.                                    *\n *                                                                                             *\n * INPUT:   shapefile   -- Pointer to the shape file that the shape will be drawn from.        *\n *                                                                                             *\n *          shapenum    -- The shape number of the object in the file to use.                  *\n *                                                                                             *\n *          x,y         -- Center pixel coordinate to use for rendering this object.           *\n *                                                                                             *\n *          window      -- The clipping window to use when rendering.                          *\n *                                                                                             *\n *          rotation    -- The rotation of the object.                                         *\n *                                                                                             *\n *          scale       -- The scaling factor to use (24.8 fixed point).                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *   01/11/1996 JLB : Added rotation and scaling.                                              *\n *=============================================================================================*/\nvoid TechnoClass::Techno_Draw_Object(void const * shapefile, int shapenum, int x, int y, WindowNumberType window, DirType rotation, int scale) const\n{\n\tassert(IsActive);\n\n\tif (shapefile != NULL) {\n\t\tVisualType visual = Visual_Character();\n\t\tvoid const * remap = Remap_Table();\n\t\tvoid const * shadow = Map.UnitShadow;\n\n\t\t/*\n\t\t**\tCreate a minimum shape rectangle if one hasn't already been\n\t\t**\tcalculated and the shape file matches the one that the\n\t\t**\tclass thinks it should be using. This check is necessary because\n\t\t**\tthe dimension rectangle pointer is referenced from the type class\n\t\t**\tobject on the presumption that the shapefile pointer passed to this\n\t\t**\troutine matches. If it doesn't match, then the wrong rectangle information\n\t\t**\twill be stored into the type class object.\n\t\t*/\n\t\tTechnoTypeClass * ttype = Techno_Type_Class();\n\t\tif (shapefile == ttype->Get_Image_Data() && shapenum < Get_Build_Frame_Count(shapefile)-1) {\n\t\t\tif (ttype->DimensionData == NULL) {\n\t\t\t\tttype->DimensionData = new Rect [Get_Build_Frame_Count(shapefile)];\n\t\t\t}\n\t\t\tif (ttype->DimensionData != NULL && !ttype->DimensionData[shapenum].Is_Valid()) {\n\t\t\t\tttype->DimensionData[shapenum] = Shape_Dimensions(shapefile, shapenum);\n\t\t\t}\n\t\t}\n\n\t\tif (Height > 0) {\n\t\t\tshadow = Map.UnitShadowAir;\n\t\t}\n\n\t\ty -= Lepton_To_Pixel(Height);\n\n\t\t/*\n\t\t** If they're viewing a spy, and the spy belongs to some other house,\n\t\t** make it look like an infantryman from our house\n\t\t*/\n\t\tif (What_Am_I() == RTTI_INFANTRY) {\n\t\t\tif (!IsOwnedByPlayer) {\n\t\t\t\tif (*(InfantryClass *)this == INFANTRY_SPY) remap = PlayerPtr->Remap_Table();\n\t\t\t}\n\t\t\tif (((InfantryClass *)this)->Class->IsRemapOverride) {\n\t\t\t\tremap = ((InfantryClass *)this)->Class->OverrideRemap;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Check for the special visual effect for the iron curtain\n\t\t*/\n\t\tif (IronCurtainCountDown > 0) {\n//\t\t\tremap = RemapEmber;\n\t\t\tremap = DisplayClass::FadingRed;\n\t\t}\n\n#ifdef PREDATOR\n\t\tif (visual != VISUAL_HIDDEN && visual != VISUAL_RIPPLE) {\n\t\t\tif (visual == VISUAL_SHADOWY) {\n\t\t\t\tCC_Draw_Shape(shapefile, shapenum, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_FADING|SHAPE_PREDATOR, NULL, Map.FadingShade, rotation, scale);\n\t\t\t} else {\n\t\t\t\tCC_Draw_Shape(shapefile, shapenum, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_FADING|SHAPE_GHOST, remap, shadow, rotation, scale);\n\t\t\t}\n\t\t\tif (visual == VISUAL_DARKEN) {\n\t\t\t\tCC_Draw_Shape(shapefile, shapenum, x, y, window, SHAPE_PREDATOR|SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_FADING, remap, Map.FadingShade, rotation, scale);\n\t\t\t}\n\t\t}\n\t\tif (visual != VISUAL_NORMAL && visual != VISUAL_HIDDEN) {\n\t\t\tCC_Draw_Shape(shapefile, shapenum, x, y, window, SHAPE_PREDATOR|SHAPE_CENTER|SHAPE_WIN_REL, NULL, NULL, rotation, scale);\n\t\t}\n#else\n\t\tswitch (visual) {\n\t\t\tcase VISUAL_NORMAL:\n\t\t\t\tCC_Draw_Shape(shapefile, shapenum, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_FADING|SHAPE_GHOST, remap, shadow, rotation, scale);\n\t\t\t\tbreak;\n\n\t\t\tcase VISUAL_INDISTINCT:\n\t\t\tcase VISUAL_DARKEN:\n\t\t\t\tCC_Draw_Shape(shapefile, shapenum, x, y, window, SHAPE_FADING|SHAPE_CENTER|SHAPE_WIN_REL, remap, Map.FadingShade, rotation, scale);\n\t\t\t\tbreak;\n\n\t\t\tcase VISUAL_SHADOWY:\n\t\t\tcase VISUAL_RIPPLE:\n\t\t\t\tCC_Draw_Shape(shapefile, shapenum, x, y, window, SHAPE_PREDATOR|SHAPE_FADING|SHAPE_CENTER|SHAPE_WIN_REL, NULL, Map.FadingShade, rotation, scale);\n\t\t\t\tbreak;\n\n\t\t\tcase VISUAL_HIDDEN:\n\t\t\t\tbreak;\n\t\t}\n#endif\n\t}\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Remap_Table -- Fetches the appropriate remap table to use.                     *\n *                                                                                             *\n *    This routine is used to fetch the appropriate remap table to use for this object.        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the remap table to use for this object.                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid const * TechnoClass::Remap_Table(void) const\n{\n\tassert(IsActive);\n\n\tif (Techno_Type_Class()->IsRemappable) {\n\t\treturn(House->Remap_Table(IsBlushing, Techno_Type_Class()->Remap));\n\t}\n\treturn(ColorRemaps[PCOLOR_GOLD].RemapTable);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Detach -- Handles removal of target from tracking system.                      *\n *                                                                                             *\n *    This routine is called when the specified object is about to be removed from the game    *\n *    system. The target object is removed from any tracking computers that this object may    *\n *    have.                                                                                    *\n *                                                                                             *\n * INPUT:   target   -- The target object (as a target value) that is being removed from the   *\n *                      game.                                                                  *\n *                                                                                             *\n *          all      -- Is the target about to die? A false value might indicate that the      *\n *                      object is merely cloaking. In such a case, radio contact will not      *\n *                      be affected.                                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Detach(TARGET target, bool all)\n{\n\tassert(IsActive);\n\tRadioClass::Detach(target, all);\n\n\tif (SuspendedMission != MISSION_NONE && SuspendedTarCom == target) {\n\t\tSuspendedMission = MISSION_NONE;\n\t\tSuspendedTarCom = TARGET_NONE;\n\t}\n\n\t/*\n\t**\tIf the targeting computer is assigned to the target, then the targeting\n\t**\tcomputer must be cleared.\n\t*/\n\tif (TarCom == target) {\n\t\tAssign_Target(TARGET_NONE);\n\t\tRestore_Mission();\n\t}\n\n\t/*\n\t**\tIf it is in radio contact with another object, then that radio contact\n\t**\tmust be broken.\n\t*/\n\tif (all && In_Radio_Contact() && Contact_With_Whom()->As_Target() == target) {\n\t\tTransmit_Message(RADIO_OVER_OUT);\n\t}\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Kill_Cargo -- Destroys any cargo attached to this object.                      *\n *                                                                                             *\n *    This routine handles the destruction of any cargo this object may contain. Typical of    *\n *    this would be when a transport helicopter gets destroyed.                                *\n *                                                                                             *\n * INPUT:   source   -- The source of the destruction of the cargo.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Kill_Cargo(TechnoClass * source)\n{\n\tassert(IsActive);\n\n\twhile (Is_Something_Attached()) {\n\t\tFootClass * foot = Detach_Object();\n\t\tif (foot != NULL) {\n\t\t\tfoot->Record_The_Kill(source);\n\t\t\tdelete foot;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Crew_Type -- Fetches the kind of crew this object contains.                    *\n *                                                                                             *\n *    This routine is called when generating survivors to this object. This routine returns    *\n *    the type of survivor to generate.                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the infantry type of a survivor.                                           *\n *                                                                                             *\n * WARNINGS:   This routine is designed to be called repeatedly. Once for each survivor to     *\n *             generate.                                                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nInfantryType TechnoClass::Crew_Type(void) const\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tIf this object contains no crew, then there can be no\n\t**\tcrew inside, duh... return this news.\n\t*/\n\tif (!Techno_Type_Class()->IsCrew) {\n\t\treturn(INFANTRY_NONE);\n\t}\n\n\t/*\n\t**\tThe normal infantry survivor is the standard issue\n\t**\tminigunner. Certain buildings, especially neutral ones, tend to have\n\t**\tcivilians exit them instead.\n\t*/\n\tInfantryType infantry = INFANTRY_E1;\n\tif (House->ActLike == HOUSE_NEUTRAL) {\n\t\tinfantry = Random_Pick(INFANTRY_C1, INFANTRY_C9);\n\t} else {\n\t\tif (Techno_Type_Class()->PrimaryWeapon == NULL && Percent_Chance(15)) {\n\t\t\tif (Percent_Chance(50)) {\n\t\t\t\tinfantry = INFANTRY_C1;\n\t\t\t} else {\n\t\t\t\tinfantry = INFANTRY_C7;\n\t\t\t}\n\t\t}\n\t}\n\treturn(infantry);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Value -- Fetches the target value for this object.                             *\n *                                                                                             *\n *    This routine is used to fetch the target value for this object. The greater the value    *\n *    returned, the better this object is as a target.                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the target value for this object.                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *   08/16/1995 JLB : Adjusted for early mission lame-out.                                     *\n *=============================================================================================*/\nint TechnoClass::Value(void) const\n{\n\tassert(IsActive);\n\n\tint value = 0;\n\n\t/*\n\t**\tIn early missions, contents of transports are not figured\n\t**\tinto the total value.\n\t*/\n\tif (Rule.Diff[House->Difficulty].IsContentScan || House->IQ >= Rule.IQContentScan) {\n\t\tif (Is_Something_Attached()) {\n\t\t\tFootClass * object = Attached_Object();\n\n\t\t\twhile (object != NULL) {\n\t\t\t\tvalue += object->Value();\n\t\t\t\tobject = (FootClass *)(ObjectClass *)object->Next;\n\t\t\t}\n\t\t}\n\t}\n\n#ifdef TOFIX\n\t/*\n\t**\tIncrease the value of power producing object when there is power critical\n\t**\tdefensive structures.\n\t*/\n\tif (What_Am_I() == RTTI_BUILDING && ((BuildingClass *)this)->Class->Power) {\n\t\tif (House->BScan & (STRUCTF_ATOWER|STRUCTF_OBELISK)) {\n\t\t\tvalue += Techno_Type_Class()->Reward;\n\t\t}\n\t}\n#endif\n\n\treturn Risk() + Techno_Type_Class()->Reward + value;\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Threat_Range -- Returns the range to scan based on threat control.             *\n *                                                                                             *\n *    This routine will return the range to scan based on the control value specified. The     *\n *    value returned by this routine is typically used when scanning for enemies.              *\n *                                                                                             *\n * INPUT:   control  -- The range control parameter.                                           *\n *                      0  = Use weapon range (zero is returned in this special case).         *\n *                      -1 = Scan without range restrictions (-1 is returned in this case).    *\n *                      1  = Scan up to twice weapon range.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with a range (or special value) that can be used in the threat scan        *\n *          process. If zero is returned, then always check threat against In_Range(). If      *\n *          -1 is returned, then no range limitation restriction exists.                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoClass::Threat_Range(int control) const\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tThreat range means nothing if scanning the whole map. In such a case, just\n\t**\treturn with the same control flag specified.\n\t*/\n\tif (control == -1) return(-1);\n\n\t/*\n\t**\tIf simple guard range is requested, then return \"0\" since\n\t**\tthis is a special control value that is calculated as the object's\n\t**\tweapon range.\n\t*/\n\tif (control == 0) {\n\t\t/*\n\t\t**\tFor normal guard mode or for area guard mode, use the override\n\t\t**\tthreat range value as specified by the object's type class.\n\t\t*/\n\t\tif (Techno_Type_Class()->ThreatRange != 0) {\n\t\t\treturn(Techno_Type_Class()->ThreatRange);\n\t\t}\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tArea guard range is specified, so figure twice the weapon range of the\n\t**\tlongest range weapon this object is equipped with.\n\t*/\n\tint range = Techno_Type_Class()->ThreatRange;\n\tif (range == 0) {\n\t\trange = max(Weapon_Range(0), Weapon_Range(1));\n\t}\n\n\trange *= 2;\n\trange = Bound(range, 0x0000, 0x0A00);\n\n\treturn(range);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Is_In_Same_Zone -- Determine if specified cell is in same zone as object.      *\n *                                                                                             *\n *    This will examine the specified cell to determine if it is in the same zone as this      *\n *    object's location.                                                                       *\n *                                                                                             *\n * INPUT:   cell  -- The cell that is to be checked against this object's current location.    *\n *                                                                                             *\n * OUTPUT:  bool; Is the specified cell in the same zone as this object is?                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::Is_In_Same_Zone(CELL cell) const\n{\n\tMZoneType zone = Techno_Type_Class()->MZone;\n\treturn(Map[cell].Zones[zone] == Map[Center_Coord()].Zones[zone]);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Base_Is_Attacked -- Handle panic response to base being attacked.              *\n *                                                                                             *\n *    This routine is called when the base is being attacked. It will pull units off of the    *\n *    field and send them back to defend the base. This routine will make taking an enemy      *\n *    base much more difficult.                                                                *\n *                                                                                             *\n * INPUT:   enemy -- Pointer to the enemy object that did the damage on the base.              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine can drastically affect the game play. The computer will probably   *\n *             call off its attacks as a result.                                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Commented.                                                               *\n *   10/15/1996 JLB : Alternates between guard area and attack.                                *\n *   11/01/1996 JLB : Allow recruit of guard area units in multiplay.                          *\n *=============================================================================================*/\nvoid TechnoClass::Base_Is_Attacked(TechnoClass const * enemy)\n{\n\tassert(IsActive);\n\n\tFootClass * defender[6];\n\tmemset(defender, '\\0', sizeof(defender));\n\n\tint value[ARRAY_SIZE(defender)];\n\tmemset(value, '\\0', sizeof(value));\n\n\tint count = 0;\n\tint weakest = 0;\n\tint desired = enemy->Risk() * House->Control.TechLevel;\n\tint risktotal = 0;\n\tint zone = Map[Center_Coord()].Zones[Techno_Type_Class()->MZone];\n\n\t/*\n\t** Humans have to deal with their own base is attacked problems.\n\t*/\n\tif (enemy == NULL || House->Is_Ally(enemy) || House->IsHuman) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tDon't overreact if this building can defend itself.\n\t*/\n\tif (Session.Type == GAME_NORMAL && Techno_Type_Class()->PrimaryWeapon != NULL) return;\n\n\t/*\n\t** If the enemy is not an infantry or a unit there is not much we can\n\t** do about it.\n\t*/\n\tif (enemy->What_Am_I() != RTTI_INFANTRY && enemy->What_Am_I() != RTTI_UNIT) {\n\t\treturn;\n\t}\n\n\t/*\n\t** If we are a certain type of building, such as a barrel or land mine,\n\t** ignore the attack.\n\t*/\n\tif (Techno_Type_Class()->IsInsignificant) {\n\t\treturn;\n\t}\n\n\t/*\n\t** If the threat has already been dealt with then we don't need to do\n\t** any work. Check for that here.\n\t*/\n\tif (enemy->Is_Foot() && ((FootClass *)enemy)->BaseAttackTimer != 0) {\n\t\treturn;\n\t}\n\n\t/*\n\t** We will need units to defend our base.  We need to suspend teams until\n\t** the situation has been dealt with.\n\t*/\n\tTeamClass::Suspend_Teams(Rule.SuspendPriority, House);\n\n\t/*\n\t** Loop through the infantry looking for those who are capable of going\n\t** on a rescue mission.\n\t*/\n\tfor (int index = 0; index < Infantry.Count() && desired > 0; index++) {\n\t \tInfantryClass * infantry = Infantry.Ptr(index);\n\t\tif (infantry != NULL && infantry->Owner() == Owner()) {\n\n\t\t\t/*\n\t\t\t**\tNever recruit sticky guard units to defend a base.\n\t\t\t*/\n\t\t\tif (!infantry->Is_Weapon_Equipped() ||\n\t\t\t\t\t(!MissionControl[infantry->Mission].IsRecruitable && Session.Type == GAME_NORMAL)) continue;\n//\t\t\t\t\t(Mission != MISSION_GUARD_AREA || Session.Type == GAME_NORMAL)) continue;\n\n\t\t\t/*\n\t\t\t**\tDon't allow a response if it doesn't have a weapon that will affect the\n\t\t\t**\tenemy object.\n\t\t\t*/\n\t\t\tif (infantry->Class->PrimaryWeapon->WarheadPtr->Modifier[enemy->Techno_Type_Class()->Armor] == 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDon't try to help if the building is on another planet.\n\t\t\t*/\n\t\t\tif (Map[infantry->Center_Coord()].Zones[infantry->Class->MZone] != Map[Center_Coord()].Zones[infantry->Class->MZone]) continue;\n\n\t\t\t/*\n\t\t\t** Find the amount of threat that this unit can apply to the\n\t\t\t** enemy.\n\t\t\t*/\n\t\t\tint threat = infantry->Rescue_Mission(enemy->As_Target());\n\n\t\t\t/*\n\t\t\t** If it can't apply any threat then do just skip it and do not\n\t\t\t** add it to the list.\n\t\t\t*/\n\t\t\tif (!threat) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tGreatly increase the threat value if this unit is already assigned to protect\n\t\t\t**\tthe target.\n\t\t\t*/\n\t\t\tif (ArchiveTarget == As_Target()) {\n\t\t\t\tthreat *= 100;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If the value returned is negative then this unit is already\n\t\t\t** assigned to fighting the enemy, so subtract its value from\n\t\t\t** the enemy's desired value.\n\t\t\t*/\n\t\t\tif (threat < 0) {\n\t\t\t\tdesired += threat;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (count < ARRAY_SIZE(defender)) {\n\t\t\t\tdefender[count] = infantry;\n\t\t\t\tvalue[count] = threat;\n\t\t\t\tcount++;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (threat > weakest) {\n\t\t\t\tint newweakest = threat;\n\n\t\t\t\tfor (int lp = 0; lp < count; lp++) {\n\t\t\t\t\tif (value[lp] == weakest) {\n\t\t\t\t\t\tvalue[lp] = threat;\n\t\t\t\t\t\tdefender[lp] = (FootClass *) infantry;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (value[lp] < newweakest) {\n\t\t\t\t\t\tnewweakest = value[lp];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tweakest = newweakest;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Loop through the units looking for those who are capable of going\n\t** on a rescue mission.\n\t*/\n\tfor (index = 0; index < Units.Count() && desired > 0; index++) {\n\t \tUnitClass * unit = Units.Ptr(index);\n\t\tif (unit != NULL && unit->Owner() == Owner()) {\n\n\t\t\t/*\n\t\t\t**\tNever recruit sticky guard units to defend a base.\n\t\t\t*/\n\t\t\tif (!unit->Is_Weapon_Equipped() ||\n\t\t\t\t(!MissionControl[unit->Mission].IsRecruitable && Session.Type == GAME_NORMAL)) continue;\n\n\t\t\t/*\n\t\t\t**\tDon't allow a response if it doesn't have a weapon that will affect the\n\t\t\t**\tenemy object.\n\t\t\t*/\n\t\t\tif (unit->Class->PrimaryWeapon->WarheadPtr->Modifier[enemy->Techno_Type_Class()->Armor] == 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDon't try to help if the building is on another planet.\n\t\t\t*/\n\t\t\tif (Map[unit->Center_Coord()].Zones[unit->Class->MZone] != Map[Center_Coord()].Zones[unit->Class->MZone]) continue;\n\n\t\t\t/*\n\t\t\t** Find the amount of threat that this unit can apply to the\n\t\t\t** enemy.\n\t\t\t*/\n\t\t\tint threat = unit->Rescue_Mission(enemy->As_Target());\n\n\t\t\t/*\n\t\t\t** If it can't apply any threat then do just skip it and do not\n\t\t\t** add it to the list.\n\t\t\t*/\n\t\t\tif (!threat) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tGreatly increase the threat value if this unit is already assigned to protect\n\t\t\t**\tthe target.\n\t\t\t*/\n\t\t\tif (threat > 0 && ArchiveTarget == As_Target()) {\n\t\t\t\tthreat *= 10;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If the value returned is negative then this unit is already\n\t\t\t** assigned to fighting the enemy, so subtract its value from\n\t\t\t** the enemy's desired value.\n\t\t\t*/\n\t\t\tif (threat < 0) {\n\t\t\t\tdesired += threat;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (count < ARRAY_SIZE(defender)) {\n\t\t\t\tdefender[count] = unit;\n\t\t\t\tvalue[count] = threat;\n\t\t\t\tcount++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (threat > weakest) {\n\t\t\t\tint newweakest = threat;\n\n\t\t\t\tfor (int lp = 0; lp < count; lp ++) {\n\t\t\t\t\tif (value[lp] == weakest) {\n\t\t\t\t\t\tvalue[lp] = threat;\n\t\t\t\t\t\tdefender[lp] = (FootClass *) unit;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (value[lp] < newweakest) {\n//\t\t\t\t\tif (value[count] < newweakest) {\n\t\t\t\t\t\tnewweakest = value[lp];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tweakest = newweakest;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (desired > 0) {\n\n\t\t/*\n\t\t** Sort the defenders by value, this doesn't take very long and will\n\t\t** help the closest defenders to respond.\n\t\t*/\n\t\tfor (int lp = 0; lp < count - 1; lp ++) {\n\t\t\tfor (int lp2 = lp + 1; lp2 < count; lp2++) {\n\t\t\t\tif (value[lp] < value[lp2]) {\n\n\t\t\t\t\tvalue[lp] \t^= value[lp2];\n\t\t\t\t\tvalue[lp2]\t^= value[lp];\n\t\t\t\t\tvalue[lp]\t^= value[lp2];\n\n\t\t\t\t\tFootClass *temp;\n\t\t\t\t\ttemp\t\t\t\t= defender[lp];\n\t\t\t\t\tdefender[lp]\t= defender[lp2];\n\t\t\t\t\tdefender[lp2]  = temp;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (lp = 0; lp < count; lp ++) {\n\t\t\tif (Percent_Chance(50)) {\n\t\t\t\tdefender[lp]->Assign_Mission(MISSION_RESCUE);\n\t\t\t} else {\n\t\t\t\tdefender[lp]->Assign_Mission(MISSION_GUARD_AREA);\n\t\t\t\tdefender[lp]->ArchiveTarget = As_Target();\n\t\t\t}\n\t\t\tdefender[lp]->Assign_Target(enemy->As_Target());\n\t\t\trisktotal += defender[lp]->Risk();\n\t\t\tif (risktotal > desired) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (risktotal > desired && enemy->Is_Foot()) {\n\t\t((FootClass *)enemy)->BaseAttackTimer = TICKS_PER_MINUTE * Rule.BaseDefenseDelay;\n\t}\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Is_Allowed_To_Retaliate -- Checks object to see if it can retaliate.           *\n *                                                                                             *\n *    This routine is called when this object has suffered some damage and it needs to know    *\n *    if it should fight back. The object that caused the damage is specifed as a parameter.   *\n *                                                                                             *\n * INPUT:   source   -- The points to the object that was the source of the damage applied     *\n *                      to this object.                                                        *\n *                                                                                             *\n * OUTPUT:  bool; Should retaliation occur?                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::Is_Allowed_To_Retaliate(TechnoClass const * source) const\n{\n\t/*\n\t**\tIf there is no source of the damage, then retaliation cannot occur.\n\t*/\n\tif (source == NULL) return(false);\n\n\t/*\n\t**\tIf the mission precludes retaliation, then don't retaliate.\n\t*/\n\tif (!MissionControl[Mission].IsRetaliate) return(false);\n\n\t/*\n\t**\tFixed wing aircraft are not responsive enough to retaliate to damage recieved.\n\t*/\n\tif (What_Am_I() == RTTI_AIRCRAFT && ((AircraftClass *)this)->Class->IsFixedWing) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the source of the damage is an ally, then retaliation shouldn't\n\t**\toccur either.\n\t*/\n\tif (House->Is_Ally(source)) return(false);\n\n\t/*\n\t**\tOnly objects that have a damaging weapon are allowed to retaliate.\n\t*/\n\tif (Combat_Damage() <= 0 || !Is_Weapon_Equipped()) return(false);\n\n\t/*\n\t**\tIf this is not equipped with a weapon that can attack the molester, then\n\t**\tdon't allow retaliation.\n\t*/\n\tTechnoTypeClass const * ttype = Techno_Type_Class();\n\tif (ttype->PrimaryWeapon->WarheadPtr != NULL &&\n\t\tttype->PrimaryWeapon->WarheadPtr->Modifier[source->Techno_Type_Class()->Armor] == 0) {\n\t\t\treturn(false);\n\t}\n\n\t/*\n\t**\tOne can never retaliate against a dog because of their peculiar nature of attacking.\n\t**\tDogs must be attacked using normal target processing.\n\t*/\n\tif (source->What_Am_I() == RTTI_INFANTRY && ((InfantryClass *)source)->Class->IsDog) return(false);\n\n\t/*\n\t**\tDon't allow retaliation if it isn't equipped with a weapon that can deal with the threat.\n\t*/\n\tif (source->What_Am_I() == RTTI_AIRCRAFT && !ttype->PrimaryWeapon->Bullet->IsAntiAircraft) return(false);\n\n\t/*\n\t**\tTanya is not allowed to retaliate against buildings in the normal sense while in guard mode. That\n\t**\tis, unless it is owned by the computer. Normally, Tanya can't do anything substantial to a building\n\t**\texcept to blow it up.\n\t*/\n\tif ((House->IsHuman || (Session.Type == GAME_NORMAL && House->IsPlayerControl))\n\t\t\t&& source->What_Am_I() == RTTI_BUILDING && What_Am_I() == RTTI_INFANTRY && ((InfantryTypeClass const *)ttype)->IsBomber) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf a human house is not allowed to retaliate automatically, then don't\n\t*/\n\tif (House->IsHuman && !Rule.IsSmartDefense && (What_Am_I() != RTTI_INFANTRY || *((InfantryClass*)this) != INFANTRY_TANYA || source->What_Am_I() != RTTI_INFANTRY)) return(false);\n\n\t/*\n\t**\tIf this object is part of a team that prevents retaliation then don't allow retaliation.\n\t*/\n\tif (Is_Foot() && ((FootClass *)this)->Team.Is_Valid() && ((FootClass *)this)->Team->Class->IsSuicide) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tCompare potential threat of the current target and the potential new target. Don't retaliate\n\t**\tif it is currently attacking the greater threat.\n\t*/\n\tif (!House->IsHuman && Percent_Chance(50)) {\n\t\tfixed source_val = 0;\n\t\tint primary = What_Weapon_Should_I_Use(source->As_Target());\n\t\tWeaponTypeClass const * weapon = (primary == 0) ? source->Techno_Type_Class()->PrimaryWeapon : source->Techno_Type_Class()->SecondaryWeapon;\n\t\tif (weapon != NULL && weapon->WarheadPtr != NULL && In_Range(source, primary)) {\n\t\t\tsource_val = weapon->WarheadPtr->Modifier[Techno_Type_Class()->Armor];\n\t\t}\n\n\t\tfixed current_val = 0;\n\t\tTechnoClass const * tech = As_Techno(TarCom);\n\t\tif (tech != NULL) {\n\t\t\tprimary = What_Weapon_Should_I_Use(tech->As_Target());\n\t\t\tweapon = (primary == 0) ? source->Techno_Type_Class()->PrimaryWeapon : source->Techno_Type_Class()->SecondaryWeapon;\n\t\t\tif (weapon != NULL && weapon->WarheadPtr != NULL && In_Range(tech, primary)) {\n\t\t\t\tcurrent_val = weapon->WarheadPtr->Modifier[Techno_Type_Class()->Armor];\n\t\t\t}\n\t\t}\n\t\tif (source_val <= current_val) return(false);\n\t}\n\n\t/*\n\t**\tIf it is already busy attacking another target, then don't retaliate.\n\t*/\n//\tif (In_Range(TarCom)) return(false);\n\n\t/*\n\t**\tAll checks passed, so return that retaliation is allowed.\n\t*/\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Get_Ownable -- Fetches the ownable bits for this object.                       *\n *                                                                                             *\n *    This routine will return the ownable bits for this object. The ownable bits represent    *\n *    the houses that are allowed to own this object.                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the ownable bits for this object.                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoClass::Get_Ownable(void) const\n{\n\tassert(IsActive);\n\n\treturn ((TechnoTypeClass const &)Class_Of()).Get_Ownable();\n//\treturn ((TechnoTypeClass const &)Class_Of()).Ownable;\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Risk -- Fetches the risk associated with this object.                          *\n *                                                                                             *\n *    This routine is called when the risk value for this object needs to be determined.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the risk value for this object.                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoClass::Risk(void) const\n{\n\tassert(IsActive);\n\n\treturn(Techno_Type_Class()->Risk);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Tiberium_Load -- Fetches the current tiberium load percentage.                 *\n *                                                                                             *\n *    This routine will return the current Tiberium load (expressed as a fixed point fraction) *\n *    that this object currently contains. Typical implementor of this function would be       *\n *    the harvester. Any object that can return a non-zero value should derive from this       *\n *    function in order to return the appropriate value.                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current Tiberium load expressed as a fixed point number.          *\n *          0x0000   = empty                                                                   *\n *          0x0080   = half full                                                               *\n *          0x0100   = full                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed TechnoClass::Tiberium_Load(void) const\n{\n\tassert(IsActive);\n\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Desired_Load_Dir -- Fetches loading parameters for this object.                *\n *                                                                                             *\n *    This routine is called when an object desires to load up on this object. The object      *\n *    desiring to load is specified. The cell that the loading object should move to is        *\n *    determined. The direction that this object should face is also calculated. This routine  *\n *    will be overridden by those objects that can actually load up passengers.                *\n *                                                                                             *\n * INPUT:   object   -- The object that is desiring to load up.                                *\n *                                                                                             *\n *          moveto   -- Reference to the cell that the loading object should move to before    *\n *                      the final load process occurs (this value will be filled in).          *\n *                                                                                             *\n * OUTPUT:  Returns with the direction that the transport object should face.                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nDirType TechnoClass::Desired_Load_Dir(ObjectClass * , CELL & moveto) const\n{\n\tassert(IsActive);\n\n\tmoveto = 0;\n\treturn(DIR_N);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Pip_Count -- Fetches the number of pips to display on this object.             *\n *                                                                                             *\n *    This routine will return the number of pips to display on this object when the object    *\n *    is selected. The default condition is to return no pips at all. This routine is          *\n *    derived for those objects that can have pips.                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of pips to display on this object when selected.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoClass::Pip_Count(void) const\n{\n\tassert(IsActive);\n\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Fire_Direction -- Fetches the direction projectile fire will take.             *\n *                                                                                             *\n *    This routine will fetch the direction that a fired projectile will take. This is         *\n *    usually the facing of the object's weapon. This routine will be derived for the objects  *\n *    that have their weapon barrel facing a different direction than the body.                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the direction a fired projectile will take.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nDirType TechnoClass::Fire_Direction(void) const\n{\n\tassert(IsActive);\n\n\treturn(Turret_Facing());\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Response_Select -- Handles the voice response when selected.                   *\n *                                                                                             *\n *    This routine is called when a voice response to a select action is desired. This routine *\n *    should be overridden for any object that actually has a voice response.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine can generate an audio response.                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Response_Select(void)\n{\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Response_Move -- Handles the voice response to a movement request.             *\n *                                                                                             *\n *    This routine is called when a voice response to a movement order is desired. This        *\n *    routine should be overridden for any object that actually has a voice response.          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This can generate an audio response.                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Response_Move(void)\n{\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Response_Attack -- Handles the voice response when given attack order.         *\n *                                                                                             *\n *    This routine is called when a voice response to an attack order is desired. This routine *\n *    should be overridden for any object that actually have a voice response.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This can generate an audio response.                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Response_Attack(void)\n{\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Target_Something_Nearby -- Handles finding and assigning a nearby target.      *\n *                                                                                             *\n *    This routine will search for a nearby target and assign it to this object's TarCom.      *\n *    The method to use when scanning for a target is controlled by the parameter passed.      *\n *                                                                                             *\n * INPUT:   threat   -- The threat control parameter used to control the range searched. The   *\n *                      only values recognized are THREAT_RANGE and THREAT_AREA.               *\n *                                                                                             *\n * OUTPUT:  Was a suitable target acquired and assigned to the TarCom?                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::Target_Something_Nearby(ThreatType threat)\n{\n\tassert(IsActive);\n\tthreat = threat & (THREAT_RANGE|THREAT_AREA);\n\n\t/*\n\t**\tDetermine that if there is an existing target it is still legal\n\t**\tand within range.\n\t*/\n\tif (Target_Legal(TarCom)) {\n\t\tif ((threat & THREAT_RANGE)) {\n\t\t\tint primary = What_Weapon_Should_I_Use(TarCom);\n\t\t\tif (!In_Range(TarCom, primary)) {\n\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is no target, then try to find one and assign it as\n\t**\tthe target for this unit.\n\t*/\n\tif (!Target_Legal(TarCom)) {\n\t\tAssign_Target(Greatest_Threat(threat));\n\t}\n\n\t/*\n\t**\tReturn with answer to question: Does this unit now have a target?\n\t*/\n\treturn(Target_Legal(TarCom));\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Exit_Object -- Causes specified object to leave this object.                   *\n *                                                                                             *\n *    This routine is called when there is an attached object that should detach and leave     *\n *    this object. Typical of this would be the refinery and APC.                              *\n *                                                                                             *\n * INPUT:   object   -- The object that is trying to leave this object.                        *\n *                                                                                             *\n * OUTPUT:  Was the object successfully launched from this object? Failure might indicate that *\n *          there is insufficient room to detach the specified object.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoClass::Exit_Object(TechnoClass *)\n{\n\tassert(IsActive);\n\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Is_Ready_To_Random_Animate -- Determines if the object should random animate.  *\n *                                                                                             *\n *    This will examine this object to determine if it is time and ready to perform some       *\n *    kind of random animation.                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is it time to perform an random animation?                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoClass::Is_Ready_To_Random_Animate(void) const\n{\n\tassert(IsActive);\n\treturn(IdleTimer == 0);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Assign_Destination -- Assigns movement destination to the object.              *\n *                                                                                             *\n *    This routine is called when the object needs to have a new movement destination          *\n *    assigned. This routine must be overridden since at this level, movement is not allowed.  *\n *                                                                                             *\n * INPUT:   destination -- The destination to assign to this object.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Assign_Destination(TARGET )\n{\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Enter_Idle_Mode -- Object enters its default idle condition.                   *\n *                                                                                             *\n *    This routine is called when the object should intelligently revert to an idle state.     *\n *    Typically this routine is called after some mission has completed. This routine must     *\n *    be overridden by the various object types. It is located at this level merely to provide *\n *    a virtual function entry point.                                                          *\n *                                                                                             *\n * INPUT:   initial  -- Is this called when the unit just leaves a factory or is initially     *\n *                      or is initially placed on the map?                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Enter_Idle_Mode(bool )\n{\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Draw_Pips -- Draws the transport pips and other techno graphics.               *\n *                                                                                             *\n *    This routine is used to render the small transportation pip (occupant feedback graphic)  *\n *    used for transporter object. It will also display if the techno object is \"primary\"      *\n *    if necessary.                                                                            *\n *                                                                                             *\n * INPUT:   x,y   -- The pixel coordinate for the center of the first pip. Subsequent pips     *\n *                   are drawn rightward.                                                      *\n *                                                                                             *\n *          window-- The window that pip clipping is relative to.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1995 JLB : Created.                                                                 *\n *   10/06/1995 JLB : Displays the team group number.                                          *\n *   09/10/1996 JLB : Medic hack for red pip.                                                  *\n *=============================================================================================*/\nvoid TechnoClass::Draw_Pips(int x, int y, WindowNumberType window) const\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tTransporter type objects have a different graphic representation for the pips. The\n\t**\tpip color represents the type of occupant.\n\t*/\n\tif (Techno_Type_Class()->Max_Passengers() > 0) {\n\t\tObjectClass const * object = Attached_Object();\n\t\tfor (int index = 0; index < Class_Of().Max_Pips(); index++) {\n\t\t\tPipEnum pip = PIP_EMPTY;\n\n\t\t\tif (object != NULL) {\n\t\t\t\tpip = PIP_FULL;\n\t\t\t\tif (object->What_Am_I() == RTTI_INFANTRY) {\n\t\t\t\t\tpip = ((InfantryClass *)object)->Class->Pip;\n\t\t\t\t}\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\t\t\tif (What_Am_I() == RTTI_VESSEL && *(VesselClass *)this == VESSEL_CARRIER) {\n\t\t\t\t\tif (object->What_Am_I() == RTTI_AIRCRAFT) {\n\t\t\t\t\t\tAircraftClass *heli = (AircraftClass *)object;\n\t\t\t\t\t\tif (heli->Ammo != heli->Techno_Type_Class()->MaxAmmo) {\n\t\t\t\t\t\t\tpip = PIP_ENGINEER;\n\t\t\t\t\t\t\tif (!heli->Ammo) {\n\t\t\t\t\t\t\t\tpip = PIP_COMMANDO;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n#endif\n\t\t\t\tobject = object->Next;\n\t\t\t}\n\t\t\tCC_Draw_Shape(Class_Of().PipShapes, pip, x+index*3, y, window, SHAPE_CENTER|SHAPE_WIN_REL);\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tDisplay number of how many attached objects there are. This is also used\n\t\t**\tto display the fullness rating for a harvester.\n\t\t*/\n\t\tint pips = Pip_Count();\n\n\t\t/*\n\t\t** Check if it's a harvester, to show the right type of pips for the\n\t\t** various minerals it could have harvested.\n\t\t*/\n\t\tif (What_Am_I() == RTTI_UNIT && *(UnitClass *)this == UNIT_HARVESTER) {\n\t\t\tUnitClass * harv = (UnitClass *)this;\n\n\t\t\tint iron = harv->Gems;\n\t\t\tint nickel = harv->Gold;\n\t\t\tint graypips   = pips * fixed(iron, Rule.BailCount);\n\t\t\tint greenpips  = pips * fixed(nickel, Rule.BailCount);\n\n\t\t\twhile (greenpips + graypips < pips) {\n\t\t\t\tint ironnickelmax = max(iron, nickel);\n\t\t\t\tif (iron > nickel) {\n\t\t\t\t\tgraypips++;\n\t\t\t\t} else {\n\t\t\t\t\tgreenpips++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (int index = 0; index < Class_Of().Max_Pips(); index++) {\n\t\t\t\tint shape = PIP_EMPTY;\n\t\t\t\tif (index < pips) {\n\t\t\t\t\tif (greenpips) {\n\t\t\t\t\t\tshape = PIP_FULL;\n\t\t\t\t\t\tgreenpips--;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tshape = PIP_COMMANDO;\n\t\t\t\t\t\tgraypips--;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tCC_Draw_Shape(Class_Of().PipShapes, shape, x+index*3, y, window, SHAPE_CENTER|SHAPE_WIN_REL);\n\t\t\t}\n\t\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t/*\n\t\t** Check if it's a Chrono tank, to show the recharge gauge.\n\t\t*/\n\t\telse if (What_Am_I() == RTTI_UNIT && *(UnitClass *)this == UNIT_CHRONOTANK) {\n\t\t\tfor (int index = 0; index < 5; index++) {\n\t\t\t\tint shape = PIP_EMPTY;\n\t\t\t\tif (index < pips) {\n\t\t\t\t\tswitch(index) {\n\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tshape = PIP_COMMANDO;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tshape = PIP_ENGINEER;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\tshape = PIP_FULL;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tCC_Draw_Shape(Class_Of().PipShapes, shape, x+index*3, y, window, SHAPE_CENTER|SHAPE_WIN_REL);\n\t\t\t}\n#endif\n\t\t} else {\n\t\t\tbool building = false;\n\t\t\tint pip = PIP_FULL;\t// green\n\t\t\tif(!IsOwnedByPlayer && What_Am_I() == RTTI_BUILDING) {\n\t\t\t\tif(*(BuildingClass *)this==STRUCT_POWER || *(BuildingClass *)this==STRUCT_ADVANCED_POWER) {\n\t\t\t\t\tbuilding = true;\n\t\t\t\t\tif (House->Power_Fraction() < 1) {\n\t\t\t\t\t\tpip = PIP_ENGINEER;\t// gold\n\t\t\t\t\t\tif (House->Drain > (House->Power * 2) ) {\n\t\t\t\t\t\t\tpip = PIP_COMMANDO;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (int index = 0; index < (building ? 5 : Class_Of().Max_Pips()); index++) {\n\t\t\t\tif (building) {\n\t\t\t\t\tCC_Draw_Shape(Class_Of().PipShapes, pip, x, y-index*3, window, SHAPE_CENTER|SHAPE_WIN_REL);\n\t\t\t\t} else {\n\t\t\t\t\tCC_Draw_Shape(Class_Of().PipShapes, (index < pips) ? PIP_FULL : PIP_EMPTY, x+index*3, y, window, SHAPE_CENTER|SHAPE_WIN_REL);\n\t\t\t\t}\n\t\t\t}\n\n//BG\t\t\tfor (int index = 0; index < Class_Of().Max_Pips(); index++) {\n//BG\t\t\t\tCC_Draw_Shape(Class_Of().PipShapes, (index < pips) ? PIP_FULL : PIP_EMPTY, x+index*3, y, window, SHAPE_CENTER|SHAPE_WIN_REL);\n//BG\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tSpecial hack to display a red pip on the medic.\n\t*/\n\tif (What_Am_I() == RTTI_INFANTRY && Combat_Damage() < 0) {\n\t\tCC_Draw_Shape(Class_Of().PipShapes, PIP_MEDIC, x+8, y, window, SHAPE_CENTER|SHAPE_WIN_REL);\n\t}\n\n\t/*\n\t**\tDisplay whether this unit is a leader unit or not.\n\t*/\n\tif (IsLeader) {\n\t\tPipEnum prishape = PIP_PRIMARY;\n\n\t\tif(What_Am_I() == RTTI_BUILDING) {\n\t\t\tif(*((BuildingClass *)this) == STRUCT_KENNEL) {\n\t\t\t\tprishape = PIP_PRI;\n\t\t\t}\n\t\t}\n\t\tCC_Draw_Shape(Class_Of().PipShapes, prishape, x-2, y-3, window, /*SHAPE_CENTER|*/SHAPE_WIN_REL);\n\t}\n\n\t/*\n\t**\tDisplay what group this unit belongs to. This corresponds to the team\n\t**\tnumber assigned with the <CTRL> key.\n\t*/\n\tif (Is_Foot() && ((FootClass *)this)->Group != 0xFF && ((FootClass *)this)->Group < 10) {\n\t\tint yval = -1;\n\t\tint group = ((FootClass *)this)->Group+1;\n\n\t\tif (Class_Of().Max_Pips()) yval -= 4;\n\t\tif (group == 10) group = 0;\n\n\t\tCC_Draw_Shape(Class_Of().PipShapes, PIP_NUMBERS+group, x+2, y+yval, window, SHAPE_CENTER|SHAPE_WIN_REL);\n\n\t\t/*\n\t\t** If this unit is part of a formation, draw an 'F' after the group\n\t\t** number.\n\t\t*/\n\t\tif ( ((FootClass *)this)->XFormOffset != 0x80000000UL) {\n\t\t\tCC_Draw_Shape(Class_Of().PipShapes, PIP_LETTERF, x+8, y+yval, window, SHAPE_CENTER|SHAPE_WIN_REL);\n\t\t}\n\t}\n\n\t/*\n\t** If this building is being spied on by the player, draw the money or\n\t** factory-producing item or whatever.\n\t*/\n\tif (What_Am_I() == RTTI_BUILDING) {\n\t\tint spiedby = SpiedBy & (1<<(PlayerPtr->Class->House));\n\n\t\t/*\n\t\t** If it's an ore refinery or other such storage-capable building,\n\t\t** loop thru all of their buildings to see if ANY of them are spied\n\t\t** upon, 'cause once you spy any money, you've spied all of it.\n\t\t*/\n\t\tif (((BuildingClass *)this)->Class->Capacity) {\n\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\tBuildingClass * building = Buildings.Ptr(index);\n\t\t\t\tif (building->House == House && building->Class->Capacity) {\n\t\t\t\t\tspiedby |= (building->SpiedBy) & (1<<(PlayerPtr->Class->House));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Print word \"Decoy\" above buildings that are spied upon or fake\n\t\t*/\n\t\tif (((BuildingClass *)this)->Class->IsFake) {\n\t\t\tif (spiedby || IsOwnedByPlayer) {\n\t\t\t\tCC_Draw_Shape(Class_Of().PipShapes, PIP_DECOY, x, y-16, window, SHAPE_WIN_REL);\n\t\t\t}\n\t\t}\n\t\t/*\n\t\t** See if we should print the credits for a spied refinery\n\t\t*/\n\t\tif (spiedby) {\n\t\t\t// If it's a refinery/silo, print the enemy's money\n\t\t\tif (((BuildingClass *)this)->Class->Capacity) {\n\t\t\t\tlong money = House->Available_Money();\n\n\t\t\t\t/*\n\t\t\t\t**\tDetermine how many digits will be printed.\n\t\t\t\t*/\n\t\t\t\tint digits;\n\t\t\t\tint factor = 10;\n\t\t\t\tfor (digits = 1; digits < 9; digits++) {\n\t\t\t\t\tif (money < factor) break;\n\t\t\t\t\tfactor *= 10;\n\t\t\t\t}\n\n\t\t\t\tint startx = x + 6 * digits - 3;// + 6 * 8;\n\t\t\t\twhile (money) {\n\t\t\t\t\tint xdigit = money % 10;\n\t\t\t\t\tmoney /= 10;\n\t\t\t\t\tCC_Draw_Shape(Class_Of().PipShapes, PIP_NUMBERS + xdigit, startx, y-6, window, SHAPE_CENTER|SHAPE_WIN_REL);\n\t\t\t\t\tstartx -= 6;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Find_Docking_Bay -- Searches for a close docking bay.                          *\n *                                                                                             *\n *    This routine will be used to find a building that can serve as a docking bay. The        *\n *    closest building that qualifies will be returned. If no building could be found then     *\n *    return with NULL.                                                                        *\n *                                                                                             *\n * INPUT:   b  -- The structure type to look for.                                              *\n *                                                                                             *\n *          friendly -- Allow searching for allied buildings as well.                          *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the building that can serve as the best docking bay.     *\n *                                                                                             *\n * WARNINGS:   This routine might return NULL even if there are buildings of the specified     *\n *             type available. This is the case when the building(s) are currently busy and    *\n *             cannot serve as a docking bay at the moment.                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1995 JLB : Created.                                                                 *\n *   08/13/1995 JLB : Recognizes the \"IsLeader\" method of building preference.                 *\n *=============================================================================================*/\nBuildingClass * TechnoClass::Find_Docking_Bay(StructType b, bool friendly) const\n{\n\tassert(IsActive);\n\n\tBuildingClass * best = 0;\n\n\t/*\n\t**\tFirst check to see if there are ANY buildings of the specified\n\t**\ttype in this house's inventory. If not, then don't bother to scan\n\t**\tfor one.\n\t*/\n\tif (House->Get_Quantity(b) != 0) {\n\t\tint bestval = -1;\n\n\t\t/*\n\t\t**\tLoop through all the buildings and find the one that matches the specification\n\t\t**\tand is willing to dock with this object.\n\t\t*/\n\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass * building = Buildings.Ptr(index);\n\n\t\t\t/*\n\t\t\t**\tCheck to see if the building qualifies (preliminary scan).\n\t\t\t*/\n\t\t\tif (building != NULL &&\n\t\t\t\t(friendly ? building->House->Is_Ally(this) : building->House == House) &&\n\t\t\t\t!building->IsInLimbo &&\n\t\t\t\t*building == b &&\n\t\t\t\t(What_Am_I() == RTTI_AIRCRAFT || Map[building->Center_Coord()].Zones[Techno_Type_Class()->MZone] == Map[Center_Coord()].Zones[Techno_Type_Class()->MZone]) &&\n\t\t\t\t((TechnoClass *)this)->Transmit_Message(RADIO_CAN_LOAD, building) == RADIO_ROGER) {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the building qualifies and this building is better than the\n\t\t\t\t**\tlast qualifying building (as rated by distance), then record\n\t\t\t\t**\tthis building and keep scanning.\n\t\t\t\t*/\n\t\t\t\tif (bestval == -1 || Distance(building) < bestval || building->IsLeader) {\n\t\t\t\t\tbest = building;\n\t\t\t\t\tbestval = Distance(building);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(best);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Find_Exit_Cell -- Finds an appropriate exit cell for this object.              *\n *                                                                                             *\n *    This routine is called when an object would like to exit from this (presumed) transport. *\n *    A suitable cell should be returned by this routine. The specified object will probably   *\n *    be unloaded at that cell.                                                                *\n *                                                                                             *\n * INPUT:   techno   -- Pointer to the object that would like to unload. This is used to       *\n *                      determine suitability for placement.                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the cell that is recommended for object exit.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL TechnoClass::Find_Exit_Cell(TechnoClass const * ) const\n{\n\tassert(IsActive);\n\n\treturn(Coord_Cell(Docking_Coord()));\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Refund_Amount -- Returns with the money to refund if this object is sold.      *\n *                                                                                             *\n *    This routine is used by the selling back mechanism in order to credit the owning house   *\n *    with some refund credits. The value returned is the credits to refund to the owner.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the credits to refund to the owner.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoClass::Refund_Amount(void) const\n{\n\tassert(IsActive);\n\n\tint cost = Techno_Type_Class()->Raw_Cost() * House->CostBias;\n\n#ifdef TOFIX\n\t/*\n\t**\tIf the object is carrying Tiberium directly (i.e., the harvester), then\n\t**\taccount for the credits of the load.\n\t*/\n//\tcost += Fixed_To_Cardinal(UnitTypeClass::FULL_LOAD_CREDITS, Tiberium_Load())/2;\n#endif\n\n\tif (House->IsHuman) {\n\t\tcost = cost * Rule.RefundPercent;\n//\t\tcost /= 2;\n\t}\n\treturn(cost);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Anti_Air -- Determines the anti-aircraft strength of the object.               *\n *                                                                                             *\n *    This routine will calculate and return the anti-aircraft strength of this object.        *\n *    Typical users of this strength value is the base defense expert system AI.               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the anti-aircraft defense value of this object. The value returned    *\n *          is an abstract number to be used for relative comparisons only.                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoClass::Anti_Air(void) const\n{\n\tassert(IsActive);\n\n\tif (Is_Weapon_Equipped()) {\n\t\tWeaponTypeClass const * weapon = Techno_Type_Class()->PrimaryWeapon;\n\t\tBulletTypeClass const * bullet = weapon->Bullet;\n\t\tWarheadTypeClass const * warhead = weapon->WarheadPtr;\n\n\t\tif (bullet->IsAntiAircraft) {\n\t\t\tint value = ((weapon->Attack * warhead->Modifier[ARMOR_ALUMINUM]) * weapon->Range) / weapon->ROF;\n\n\t\t\tif (Techno_Type_Class()->Is_Two_Shooter()) {\n\t\t\t\tvalue *= 2;\n\t\t\t}\n\t\t\treturn(value/50);\n\t\t}\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Anti_Armor -- Determines the anti-armor strength of the object.                *\n *                                                                                             *\n *    This routine is used to examine and calculate the anti-armor strength of this object.    *\n *    Typical user user of this would be the expert system base defense AI.                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the relative anti-armor combat value for this object. The value       *\n *          is abstract and is only to be used in relative comparisons.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoClass::Anti_Armor(void) const\n{\n\tassert(IsActive);\n\n\tif (Is_Weapon_Equipped()) {\n\t\tif (!Techno_Type_Class()->PrimaryWeapon->Bullet->IsAntiGround) return(0);\n\n\t\tWeaponTypeClass const * weapon = Techno_Type_Class()->PrimaryWeapon;\n\t\tBulletTypeClass const * bullet = weapon->Bullet;\n\t\tWarheadTypeClass const * warhead = weapon->WarheadPtr;\n\t\tint mrange = min(weapon->Range, 0x0400);\n\n\t\tint value = ((weapon->Attack * warhead->Modifier[ARMOR_STEEL]) * mrange * warhead->SpreadFactor) / weapon->ROF;\n\t\tif (Techno_Type_Class()->Is_Two_Shooter()) {\n\t\t\tvalue *= 2;\n\t\t}\n\t\tif (bullet->IsInaccurate) {\n\t\t\tvalue /= 2;\n\t\t}\n\t\treturn(value/50);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Anti_Infantry -- Calculates the anti-infantry strength of this object.         *\n *                                                                                             *\n *    This routine is used to determine the anti-infantry strength of this object. The         *\n *    typical user of this routine is the expert system base defense AI.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the anti-infantry strength of this object. The value returned is      *\n *          abstract and should only be used for relative comparisons.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoClass::Anti_Infantry(void) const\n{\n\tassert(IsActive);\n\n\tif (Is_Weapon_Equipped()) {\n\t\tif (!Techno_Type_Class()->PrimaryWeapon->Bullet->IsAntiGround) return(0);\n\n\t\tWeaponTypeClass const * weapon = Techno_Type_Class()->PrimaryWeapon;\n\t\tBulletTypeClass const * bullet = weapon->Bullet;\n\t\tWarheadTypeClass const * warhead = weapon->WarheadPtr;\n\t\tint mrange = min(weapon->Range, 0x0400);\n\n\t\tint value = ((weapon->Attack * warhead->Modifier[ARMOR_NONE]) * mrange * warhead->SpreadFactor) / weapon->ROF;\n\t\tif (Techno_Type_Class()->Is_Two_Shooter()) {\n\t\t\tvalue *= 2;\n\t\t}\n\t\tif (bullet->IsInaccurate) {\n\t\t\tvalue /= 2;\n\t\t}\n\t\treturn(value/50);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Look -- Performs a look around (map reveal) action.                            *\n *                                                                                             *\n *    This routine will reveal the map around this object.                                     *\n *                                                                                             *\n * INPUT:   incremental -- This parameter can enable a more efficient map reveal logic.        *\n *                         If it is absolutely known that the object has only moved one        *\n *                         cell from its previous location that it performed a Look() at,      *\n *                         then set this parameter to TRUE. It will only perform the look      *\n *                         check on the perimeter cells.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine is slow, try to call it only when necessary.                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TechnoClass::Look(bool incremental)\n{\n\tassert(IsActive);\n\tassert(!IsInLimbo);\n\n\tint sight_range = Techno_Type_Class()->SightRange;\n\n\tif (sight_range) {\n\t\tMap.Sight_From(Coord_Cell(Coord), sight_range, House, incremental);\n\t}\n}\n\n\n//**********************************************************************************************\n// MODULE SEPARATION -- TechnoTypeClass member functions follow.\n//**********************************************************************************************\n\n\n/***********************************************************************************************\n * TechnoTypeClass::TechnoTypeClass -- Constructor for techno type objects.                    *\n *                                                                                             *\n *    This is the normal constructor for techno type objects. It is called in the process of   *\n *    constructing all the object type (constant) data for the various techno type objects.    *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/19/1995 JLB : Created.                                                                 *\n *   05/11/1996 JLB : Moderated risk calc so range doesn't dominate.                           *\n *=============================================================================================*/\nTechnoTypeClass::TechnoTypeClass(\n\t\tRTTIType rtti,\n\t\tint id,\n\t\tint name,\n\t\tchar const * ininame,\n\t\tRemapType remap,\n\t\tint verticaloffset,\n\t\tint primaryoffset,\n\t\tint primarylateral,\n\t\tint secondaryoffset,\n\t\tint secondarylateral,\n\t\tbool is_nominal,\n\t\tbool is_stealthy,\n\t\tbool is_selectable,\n\t\tbool is_legal_target,\n\t\tbool is_insignificant,\n\t\tbool is_immune,\n\t\tbool is_theater,\n\t\tbool is_turret_equipped,\n\t\tbool is_remappable,\n\t\tbool is_footprint,\n\t\tint rotation,\n\t\tSpeedType speed) :\n\tObjectTypeClass(\trtti,\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\tis_stealthy,\n\t\t\t\t\t\t\tis_selectable,\n\t\t\t\t\t\t\tis_legal_target,\n\t\t\t\t\t\t\tis_insignificant,\n\t\t\t\t\t\t\tis_immune,\n\t\t\t\t\t\t\tis_footprint,\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tininame),\n\tRemap(remap),\n\tIsDoubleOwned(false),\n\tIsInvisible(false),\n\tIsLeader(false),\n\tIsScanner(false),\n\tIsNominal(is_nominal),\n\tIsTheater(is_theater),\n\tIsTurretEquipped(is_turret_equipped),\n\tIsCrew(false),\n\tIsRepairable(true),\n\tIsRemappable(is_remappable),\n\tIsCloakable(false),\n\tIsSelfHealing(false),\n\tIsExploding(false),\n\tMZone(MZONE_NORMAL),\n\tThreatRange(0),\n\tMaxPassengers(0),\n\tSightRange(0),\n\tCost(0),\n\tLevel(-1),\n\tPrerequisite(STRUCTF_NONE),\n\tRisk(0),Reward(0),\n\tMaxSpeed(MPH_IMMOBILE),\n\tSpeed(speed),\n\tMaxAmmo(-1),\n\tOwnable(0),\n\tCameoData(NULL),\n\tRotation(rotation),\n\tROT(0),\n\tPrimaryWeapon(NULL),\n\tSecondaryWeapon(NULL),\n\tVerticalOffset(verticaloffset),\n\tPrimaryOffset(primaryoffset),\n\tPrimaryLateral(primarylateral),\n\tSecondaryOffset(secondaryoffset),\n\tSecondaryLateral(secondarylateral),\n\tPoints(0)\n{\n}\n\n\n/***********************************************************************************************\n * TechnoTypeClass::Raw_Cost -- Fetches the raw (base) cost of the object.                     *\n *                                                                                             *\n *    This routine is used to find the underlying cost for this object. The underlying cost    *\n *    does not include any free items that normally come with the object when purchased        *\n *    directly. Example: The raw cost of a refinery is the normal cost minus the cost of a     *\n *    harvester.                                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the credit cost of the base object type.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoTypeClass::Raw_Cost(void) const\n{\n\treturn(Cost);\n}\n\n\n/***********************************************************************************************\n * TechnoTypeClass::Get_Ownable -- Fetches the ownable bits for this object type.              *\n *                                                                                             *\n *    This routine will return the ownable bits for this object type. The ownable bits are     *\n *    a bitflag composite of the houses that can own (build) this object type.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the ownable bits for this object type.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoTypeClass::Get_Ownable(void) const\n{\n\tif (IsDoubleOwned && Session.Type != GAME_NORMAL) {\n\t\treturn(Ownable | HOUSEF_SOVIET | HOUSEF_ALLIES);\n\t}\n\treturn(Ownable);\n}\n\n\n/***********************************************************************************************\n * TechnoTypeClass::Time_To_Build -- Fetches the time to build this object.                    *\n *                                                                                             *\n *    This routine will return the time it takes to construct this object. Usually the time    *\n *    to produce is directly related to cost.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the time to produce this object type. The time is expressed in the    *\n *          form of game ticks.                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoTypeClass::Time_To_Build(void) const\n{\n\treturn(Cost * Rule.BuildSpeedBias * fixed(TICKS_PER_MINUTE, 1000));\n}\n\n\n/***********************************************************************************************\n * TechnoTypeClass::Cost_Of -- Fetches the cost of this object type.                           *\n *                                                                                             *\n *    This routine will return the cost to produce an object of this type.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the cost to produce one object of this type.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoTypeClass::Cost_Of(void) const\n{\n\treturn(Cost);\n}\n\n\n/***********************************************************************************************\n * TechnoTypeClass::Get_Cameo_Data -- Fetches the cameo image for this object type.            *\n *                                                                                             *\n *    This routine will fetch the cameo (sidebar small image) shape of this object type.       *\n *    If there is no cameo data available (typical for non-produceable units), then NULL will  *\n *    be returned.                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the cameo data for this object type if present.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid const * TechnoTypeClass::Get_Cameo_Data(void) const\n{\n\treturn(CameoData);\n}\n\n\n/***********************************************************************************************\n * TechnoTypeClass::Repair_Cost -- Fetches the cost to repair one step.                        *\n *                                                                                             *\n *    This routine will return the cost to repair one step. At the TechnoTypeClass level,      *\n *    this merely serves as a placeholder function. The derived classes will provide a         *\n *    functional version of this routine.                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the cost to repair one step.                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoTypeClass::Repair_Cost(void) const\n{\n\tif (Is_Foot()) {\n\t\treturn((Raw_Cost()/(MaxStrength/Rule.URepairStep)) * Rule.URepairPercent);\n\t}\n\treturn((Raw_Cost()/(MaxStrength/Rule.RepairStep)) * Rule.RepairPercent);\n}\n\n\n/***********************************************************************************************\n * TechnoTypeClass::Repair_Step -- Fetches the health to repair one step.                      *\n *                                                                                             *\n *    This routine merely serves as placeholder virtual function. The various type classes     *\n *    will override this routine to return the number of health points to repair in one        *\n *    \"step\".                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of health points to repair in one step.                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint TechnoTypeClass::Repair_Step(void) const\n{\n\tif (Is_Foot()) {\n\t\treturn(Rule.URepairStep);\n\t}\n\treturn(Rule.RepairStep);\n}\n\n\n/***********************************************************************************************\n * TechnoTypeClass::Is_Two_Shooter -- Determines if this object is a double shooter.           *\n *                                                                                             *\n *    Some objects fire two shots in quick succession. If this is true for this object, then   *\n *    a 'true' value will be returned from this routine.                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is this object a two shooter?                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoTypeClass::Is_Two_Shooter(void) const\n{\n\tif (PrimaryWeapon != NULL && (PrimaryWeapon == SecondaryWeapon || PrimaryWeapon->Burst > 1)) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * _Scale_To_256 -- Scales a 1..100 number into a 1..255 number.                               *\n *                                                                                             *\n *    This is a helper routine that will take a decimal percentage number and convert it       *\n *    into a game based fixed point number.                                                    *\n *                                                                                             *\n * INPUT:   val   -- Decimal percent number to convert.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with the decimal percent number converted to a game fixed point number.    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic inline int _Scale_To_256(int val)\n{\n\tval = min(val, 100);\n\tval = max(val, 0);\n\tval = ((val * 256) / 100);\n\tval = min(val, 255);\n\treturn(val);\n}\n\n\n/***********************************************************************************************\n * TechnoTypeClass::Read_INI -- Reads the techno type data from the INI database.              *\n *                                                                                             *\n *    Use this routine to fill in the data for this techno type class object from the          *\n *    database specified. Typical use of this is for the rules parsing.                        *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database that the information will be lifted from.   *\n *                                                                                             *\n * OUTPUT:  bool; Was the database used to extract information? A failure (false) response     *\n *                would mean that the database didn't contain a section that applies to this   *\n *                techno class object.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TechnoTypeClass::Read_INI(CCINIClass & ini)\n{\n\tif (ini.Is_Present(Name())) {\n#ifdef FIXIT_NAME_OVERRIDE\n\t\tchar buffer[256];\n\t\tint id = ((RTTI+1) * 100) + ID;\n\n\t\tini.Get_String(Name(), \"Name\", \"\", buffer, sizeof(buffer));\n\t\tif (strlen(buffer) > 0)  {\n\n#if defined (GERMAN)||(FRENCH)\n\n\t\tfor(int xx=0; NewName[xx] != NULL; xx++){\n\t\t    if(!strcmp(NewName[xx], buffer)){\n\t\t\tmemcpy(buffer, \"\", sizeof(buffer));\n\t\t\tmemcpy(buffer, NewName[xx+1], sizeof(buffer));\n\t\t\tbreak;\n\t\t   }\n\t\t}\n#endif\n\n\t\t\t/*\n\t\t\t**\tInsert the new name text into the buffer list.\n\t\t\t*/\n\t\t\tfor (int index = 0; index < ARRAY_SIZE(NameOverride); index++) {\n\t\t\t\tif (NameIDOverride[index] == 0)  {\n\t\t\t\t\tNameOverride[index] = strdup(buffer);\n\t\t\t\t\tNameIDOverride[index] = id;\n//\t\t\t\t\tFullName = -(index+1);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#endif\n\n\t\tIsDoubleOwned = ini.Get_Bool(Name(), \"DoubleOwned\", IsDoubleOwned);\n\t\tThreatRange = ini.Get_Lepton(Name(), \"GuardRange\", ThreatRange);\n\t\tIsExploding = ini.Get_Bool(Name(), \"Explodes\", IsExploding);\n\t\tPrimaryWeapon = WeaponTypeClass::As_Pointer(ini.Get_WeaponType(Name(), \"Primary\", PrimaryWeapon != NULL ? (WeaponType)(PrimaryWeapon->ID) : WEAPON_NONE));\n\t\tSecondaryWeapon = WeaponTypeClass::As_Pointer(ini.Get_WeaponType(Name(), \"Secondary\", SecondaryWeapon != NULL ? (WeaponType)(SecondaryWeapon->ID) : WEAPON_NONE));\n\t\tIsCloakable = ini.Get_Bool(Name(), \"Cloakable\", IsCloakable);\n\t\tIsCrushable = ini.Get_Bool(Name(), \"Crushable\", IsCrushable);\n\t\tIsScanner = ini.Get_Bool(Name(), \"Sensors\", IsScanner);\n\t\tArmor = ini.Get_ArmorType(Name(), \"Armor\", Armor);\n\t\tPrerequisite = ini.Get_Buildings(Name(), \"Prerequisite\", Prerequisite);\n\t\tMaxStrength = ini.Get_Int(Name(), \"Strength\", MaxStrength);\n\t\tSightRange = ini.Get_Int(Name(), \"Sight\", SightRange);\n\t\tLevel = ini.Get_Int(Name(), \"TechLevel\", Level);\n\t\tMaxSpeed = MPHType(_Scale_To_256(ini.Get_Int(Name(), \"Speed\", fixed(MaxSpeed, 256) * 100)));\n\t\tCost = ini.Get_Int(Name(), \"Cost\", Cost);\n\t\tMaxAmmo = ini.Get_Int(Name(), \"Ammo\", MaxAmmo);\n\t\tRisk = Reward = Points = ini.Get_Int(Name(), \"Points\", Points);\n\t\tOwnable = ini.Get_Owners(Name(), \"Owner\", Ownable);\n\t\tIsCrew = ini.Get_Bool(Name(), \"Crewed\", IsCrew);\n\t\tIsRepairable = ini.Get_Bool(Name(), \"Repairable\", IsRepairable);\n\t\tIsInvisible = ini.Get_Bool(Name(), \"Invisible\", IsInvisible);\n\t\tIsSelfHealing = ini.Get_Bool(Name(), \"SelfHealing\", IsSelfHealing);\n\t\tROT = ini.Get_Int(Name(), \"ROT\", ROT);\n\t\tMaxPassengers = ini.Get_Int(Name(), \"Passengers\", MaxPassengers);\n//Mono_Printf(\"before image=: %s\\n\",GraphicName);\n\t\tini.Get_String(Name(), \"Image\", GraphicName, GraphicName, sizeof(GraphicName));\n//Mono_Printf(\"after image=: %s\\n\",GraphicName);if(Random_Pick(0,4)) Keyboard->Get();\n\n\t\tIsLeader = false;\n\t\tif (PrimaryWeapon != NULL && PrimaryWeapon->Attack > 0) {\n\t\t\tIsLeader = true;\n\t\t}\n\n\t\t/*\n\t\t**\tCheck to see what zone this object should recognize.\n\t\t*/\n\t\tif (PrimaryWeapon != NULL && PrimaryWeapon->WarheadPtr != NULL && PrimaryWeapon->WarheadPtr->IsWallDestroyer) {\n\t\t\tMZone = MZONE_DESTROYER;\n\t\t}\n\t\tif (Speed == SPEED_FLOAT) {\n\t\t\tMZone = MZONE_WATER;\n\t\t}\n\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\nint TechnoTypeClass::Legal_Placement(CELL pos) const\n{\n\tif (pos == -1) return(0);\n\n\t/*\n\t**\tNormal buildings must check to see that every foundation square is free of\n\t**\tobstacles. If this check passes for all foundation squares, only then does the\n\t**\troutine return that it is legal to place.\n\t*/\n\tshort const * offset = Occupy_List(true);\n\tbool build = (What_Am_I() == RTTI_BUILDINGTYPE);\n\n\twhile (offset != NULL && *offset != REFRESH_EOL) {\n\t\tCELL cell = pos + *offset++;\n\t\tif (!Map.In_Radar(cell)) return(false);\n\t\tif (build) {\n\t\t\tif (!Map[cell].Is_Clear_To_Build(Speed)) {\n\t\t\t\treturn(0);\n\t\t\t}\n\t\t} else {\n\t\t\tif (!Map[cell].Is_Clear_To_Move(Speed, false, false)) {\n\t\t\t\treturn(0);\n\t\t\t}\n\t\t}\n\t}\n\treturn(1);\n}\n"
  },
  {
    "path": "CODE/TECHNO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TECHNO.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TECHNO.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 14, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 14, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TECHNO_H\n#define TECHNO_H\n\n#include\t\"radio.h\"\n#include\t\"stage.h\"\n#include\t\"cargo.h\"\n#include\t\"flasher.h\"\n#include\t\"house.h\"\n#include\t\"target.h\"\n#include\t\"bullet.h\"\n#include\t\"door.h\"\n#include\t\"crew.h\"\n\n/****************************************************************************\n**\tThis is the common data between building and units.\n*/\nclass TechnoClass :\tpublic RadioClass,\n\t\t\t\t\t\t\tpublic FlasherClass,\n\t\t\t\t\t\t\tpublic StageClass,\n\t\t\t\t\t\t\tpublic CargoClass,\n\t\t\t\t\t\t\tpublic DoorClass\n{\n\tpublic:\n\t\tCrewClass Crew;\n\n\t\t/*\n\t\t**\tIf this techno object has detected that it has outlived its\n\t\t**\tpurpose, then this flag will be true. Such object will either\n\t\t**\tbe sold or sacrificed at the first opportunity.\n\t\t*/\n\t\tunsigned IsUseless:1;\n\n\t\t/*\n\t\t**\tThis flag will be true if the object has been damaged with malice.\n\t\t**\tDamage received due to friendly fire or wear and tear does not count.\n\t\t**\tThe computer is not allowed to sell a building unless it has been\n\t\t**\tdamaged with malice.\n\t\t*/\n\t\tunsigned IsTickedOff:1;\n\n\t\t/*\n\t\t**\tIf this object has inherited the ability to cloak, then this bit will\n\t\t**\tbe set to true.\n\t\t*/\n\t\tunsigned IsCloakable:1;\n\n\t\t/*\n\t\t**\tIf this object is designated as special then this flag will be true. For\n\t\t**\tbuildings, this means that it is the primary factory. For units, it means\n\t\t**\tthat the unit is the team leader.\n\t\t*/\n\t\tunsigned IsLeader:1;\n\n\t\t/*\n\t\t**\tCertain units are flagged as \"loaners\".  These units are typically transports that\n\t\t**\tare created solely for the purpose of delivering reinforcements.  Such \"loaner\"\n\t\t**\tunits are not owned by the player and thus cannot be directly controlled.  These\n\t\t**\tunits will leave the game as soon as they have fulfilled their purpose.\n\t\t*/\n\t\tunsigned IsALoaner:1;\n\n\t\t/*\n\t\t**\tOnce a unit enters the map, then this flag is set. This flag is used to make\n\t\t**\tsure that a unit doesn't leave the map once it enters the map.\n\t\t*/\n\t\tunsigned IsLocked:1;\n\n\t\t/*\n\t\t**\tBuildings and units with turrets usually have a recoil animation when they\n\t\t**\tfire. If this flag is true, then the next rendering of the object will be\n\t\t**\tin the \"recoil state\". The flag will then be cleared pending the next\n\t\t**\tfiring event.\n\t\t*/\n\t\tunsigned IsInRecoilState:1;\n\n\t\t/*\n\t\t**\tIf this unit is \"loosely attached\" to another unit it is given special\n\t\t**\tprocessing. A unit is in such a condition when it is in the process of\n\t\t**\tunloading from a transport type object. During the unloading process\n\t\t**\tthe transport object must stay still until the unit is free and clear.\n\t\t**\tAt that time it radios the transport object and the \"tether\" is broken -\n\t\t**\tfreeing both the unit and the transport object.\n\t\t*/\n\t\tunsigned IsTethered:1;\n\n\t\t/*\n\t\t**\tIs this object owned by the player?  If not, then it is owned by the computer\n\t\t**\tor remote opponent. This flag facilitates the many logic differences when dealing\n\t\t**\twith player's or computer's units or buildings.\n\t\t*/\n\t\tunsigned IsOwnedByPlayer:1;\n\n\t\t/*\n\t\t**\tThe more sophisticated game objects must keep track of whether they are discovered\n\t\t**\tor not. This is because the state of discovery can often control how the object\n\t\t**\tbehaves. In addition, this fact is used in radar and user I/O processing.\n\t\t*/\n\t\tunsigned IsDiscoveredByPlayer:1;\n\n\t\t/*\n\t\t**\tThis is used to control the computer recognizing this object.\n\t\t*/\n\t\tunsigned IsDiscoveredByComputer:1;\n\n\t\t/*\n\t\t**\tSome game objects can be of the \"lemon\" variety. This means that they take damage\n\t\t**\teven when everything is ok. This adds a little variety to the game.\n\t\t*/\n\t\tunsigned IsALemon:1;\n\n\t\t/*\n\t\t**\tThis flag is used to control second shot processing for those units or buildings\n\t\t**\tthat fire two shots in quick succession. When this flag is true, it indicates that\n\t\t**\tthe second shot is ready to fire. After this shot is fired, regular rearm timing\n\t\t**\tis used rather than the short rearm time.\n\t\t*/\n\t\tunsigned IsSecondShot:1;\n\n\t\t/*\n\t\t**\tThis is the firepower and armor modifiers for this techno object. Normally,\n\t\t**\tthese values are fixed at 0x0100, but they can be modified by certain\n\t\t**\tcrate powerups.\n\t\t*/\n\t\tfixed ArmorBias;\n\t\tfixed FirepowerBias;\n\n\t\t/*\n\t\t**\tIdle animations (if any are supported by the object type) are regulated by\n\t\t**\tthis timer. When the timer expires an idle animation occurs. Then the\n\t\t**\ttimer is reinitialized to some random (bounded) setting.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> IdleTimer;\n\n\t\t/*\n\t\t** This timer keeps track of how long the unit is under the influence\n\t\t** of the iron curtain.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> IronCurtainCountDown;\n\n\n\t\t/*\n\t\t** This is a list of bits of which houses are spying on this building,\n\t\t** if in fact this is a building.\n\t\t*/\n\t\tunsigned SpiedBy;\n\n\t\t/*\n\t\t**\tFor units in area guard mode, this is the recorded home position. The guarding\n\t\t**\tunit will try to stay near this location in the course of it's maneuvers. This is\n\t\t**\talso used to record a pending transport for those passengers that are waiting for\n\t\t**\tthe transport to become available. It is also used by harvesters so that they know\n\t\t**\twhere to head back to after unloading.\n\t\t*/\n\t\tTARGET ArchiveTarget;\n\n\t\t/*\n\t\t**\tThis is the house that the unit belongs to.\n\t\t*/\n\t\tCCPtr<HouseClass> House;\n\n\t\t/*\n\t\t**\tThis records the current cloak state for this vehicle.\n\t\t*/\n\t\tCloakType Cloak;\n\t\tStageClass CloakingDevice;\n\t\tCDTimerClass<FrameTimerClass> CloakDelay;\n\n\t\t/* (Targeting Computer)\n\t\t**\tThis is the target value for the item that this vehicle should ATTACK. If this\n\t\t**\tis a vehicle with a turret, then it may differ from its movement destination.\n\t\t*/\n\t\tTARGET TarCom;\n\t\tTARGET SuspendedTarCom;\n\n\t\t/*\n\t\t**\tThis is the visible facing for the unit or building.\n\t\t*/\n\t\tFacingClass PrimaryFacing;\n\n\t\t/*\n\t\t**\tThis is the arming countdown. It represents the time necessary\n\t\t**\tto reload the weapon.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> Arm;\n\n\t\t/*\n\t\t**\tThe number of shot this object can fire before running out of ammo. If this\n\t\t**\tvalue is zero, then firing is not allowed. If -1, then there is no ammunition\n\t\t**\tlimit.\n\t\t*/\n\t\tint Ammo;\n\n\t\t/*\n\t\t**\tThis is the amount of money spent to produce this object. This value really\n\t\t**\tonly comes into play for the case of buildings that have special \"free\"\n\t\t**\tobjects available when purchased at the more expensive rate.\n\t\t*/\n\t\tint PurchasePrice;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tTechnoClass(RTTIType rtti, int id, HousesType house=HOUSE_NONE);\n#ifdef FIXIT_MULTI_SAVE\n\t\tTechnoClass(NoInitClass const & x) : RadioClass(x), FlasherClass(x), StageClass(x), CargoClass(x), DoorClass(x), IdleTimer(x), IronCurtainCountDown(x), House(x), Crew(x), CloakDelay(x), PrimaryFacing(x), Arm(x) {};\n#else\n\t\tTechnoClass(NoInitClass const & x) : RadioClass(x), FlasherClass(x), StageClass(x), CargoClass(x), DoorClass(x), IronCurtainCountDown(x), House(x), Crew(x), CloakDelay(x), PrimaryFacing(x), Arm(x) {};\n#endif\n\t\tvirtual ~TechnoClass(void) {House=0;};\n\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tbool Is_Allowed_To_Retaliate(TechnoClass const * source) const;\n\t\tbool Can_Teleport_Here(CELL cell) const;\n\t\tbool Is_In_Same_Zone(CELL cell) const;\n\t\tvirtual bool Is_Players_Army(void) const;\n\t\tint Combat_Damage(int which=-1) const;\n\t\tbool Is_Ready_To_Cloak(void) const;\n\t\tvirtual int How_Many_Survivors(void) const;\n\t\tvirtual DirType Turret_Facing(void) const {return(PrimaryFacing.Current());}\n\t\tCELL Nearby_Location(TechnoClass const * from=NULL) const;\n\t\tTechnoTypeClass * Techno_Type_Class(void) const {return((TechnoTypeClass *)&Class_Of());};\n\t\tbool Is_Visible_On_Radar(void) const;\n\t\tint Anti_Air(void) const;\n\t\tint Anti_Armor(void) const;\n\t\tint Anti_Infantry(void) const;\n\t\tint Time_To_Build(void) const;\n\t\tint What_Weapon_Should_I_Use(TARGET target) const;\n\t\tvirtual ActionType What_Action(CELL cell) const;\n\t\tvirtual ActionType What_Action(ObjectClass const * target) const;\n\t\tvirtual BuildingClass * Find_Docking_Bay(StructType b, bool friendly) const;\n\t\tvirtual CELL Find_Exit_Cell(TechnoClass const * techno) const;\n\t\tvirtual COORDINATE Fire_Coord(int which) const;\n\t\tvirtual DirType Desired_Load_Dir(ObjectClass * , CELL & moveto) const;\n\t\tvirtual DirType Fire_Direction(void) const;\n\t\tvirtual HousesType Owner(void) const;\n\t\tvirtual InfantryType Crew_Type(void) const;\n\t\tvirtual bool Can_Player_Fire(void) const;\n\t\tvirtual bool Can_Player_Move(void) const;\n\t\tvirtual bool Is_Allowed_To_Recloak(void) const;\n\t\tvirtual bool Can_Repair(void) const;\n\t\tvirtual bool Is_Weapon_Equipped(void) const;\n\t\tvirtual fixed Tiberium_Load(void) const;\n\t\tvirtual int Pip_Count(void) const;\n\t\tvirtual int Rearm_Delay(bool second=true, int which=0) const;\n\t\tvirtual int Refund_Amount(void) const;\n\t\tvirtual int Risk(void) const;\n\t\tvirtual int Threat_Range(int control) const;\n\t\tvirtual int Value(void) const;\n\t\tvirtual int Get_Ownable(void) const;\n\n\t\t/*\n\t\t**\tUser I/O.\n\t\t*/\n\t\tvirtual void Clicked_As_Target(int count=7);\n\t\tvirtual bool Select(void);\n\t\tvirtual void Response_Select(void);\n\t\tvirtual void Response_Move(void);\n\t\tvirtual void Response_Attack(void);\n\t\tvirtual void Player_Assign_Mission(MissionType order, TARGET target=TARGET_NONE, TARGET destination=TARGET_NONE);\n\n\t\t/*\n\t\t**\tCombat related.\n\t\t*/\n\t\tfixed Area_Modify(CELL cell) const;\n\t\tvirtual int Made_A_Kill(void) {return(Crew.Made_A_Kill());}\n\t\tvoid Base_Is_Attacked(TechnoClass const *enemy);\n\t\tvoid Kill_Cargo(TechnoClass * source);\n\t\tvirtual void Record_The_Kill(TechnoClass * source);\n\t\tvirtual bool Target_Something_Nearby(ThreatType threat=THREAT_NORMAL);\n\t\tvirtual void Stun(void);\n\t\tvirtual bool In_Range(COORDINATE coord, int which=0) const;\n\t\tvirtual bool In_Range(TARGET target, int which=0) const;\n\t\tvirtual bool In_Range(ObjectClass const * target, int which=0) const;\n\t\tvirtual void Death_Announcement(TechnoClass const * source=0) const = 0;\n\t\tvirtual FireErrorType Can_Fire(TARGET target, int which=0) const;\n\t\tvirtual TARGET Greatest_Threat(ThreatType threat) const;\n\t\tvirtual void Assign_Target(TARGET target);\n\t\tvirtual void Override_Mission(MissionType mission, TARGET tarcom, TARGET navcom);\n\t\tvirtual bool Restore_Mission(void);\n\t\tvirtual BulletClass * Fire_At(TARGET target, int which=0);\n\t\tvirtual int Weapon_Range(int which) const;\n\t\tvirtual bool Captured(HouseClass * newowner);\n\t\tvirtual ResultType Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source=0, bool forced=false);\n\t\tbool Evaluate_Cell(ThreatType method, int mask, CELL cell, int range, TechnoClass const ** object, int & value, int zone=0) const;\n\t\tbool Evaluate_Object(ThreatType method, int mask, int range, TechnoClass const * object, int & value, int zone=-1) const;\n\t\tint Evaluate_Just_Cell(CELL cell) const;\n\t\tvirtual bool Electric_Zap (TARGET target, int which, COORDINATE target_coord=0L, unsigned char * remap=NULL);\n\n\t\t/*\n\t\t**\tAI.\n\t\t*/\n\t\tvirtual void Renovate(void);\n\t\tvirtual void AI(void);\n\t\tvirtual bool Revealed(HouseClass * house);\n\t\tvirtual RadioMessageType Receive_Message(RadioClass * from, RadioMessageType message, long & param);\n\t\tvoid Cloaking_AI(void);\n\n\t\t/*\n\t\t**\tScenario and debug support.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n\n\t\t/*\n\t\t**\tDisplay and rendering support functionality. Supports imagery and how\n\t\t**\tobject interacts with the map and thus indirectly controls rendering.\n\t\t*/\n\t\tvirtual void const * Remap_Table(void) const;\n\t\tVisualType Visual_Character(bool raw = false) const;\n\t\tvoid Techno_Draw_Object(void const * shapefile, int shapenum, int x, int y, WindowNumberType window, DirType rotation=DIR_N, int scale=0x0100) const;\n\t\tvirtual void Draw_It(int x, int y, WindowNumberType window) const;\n\t\tvirtual void Draw_Pips(int x, int y, WindowNumberType window) const;\n\t\tvirtual void Hidden(void);\n\t\tvirtual bool Mark(MarkType mark=MARK_CHANGE);\n\t\tvirtual int Exit_Object(TechnoClass *);\n\t\tvirtual void Do_Uncloak(void);\n\t\tvirtual void Do_Cloak(void);\n\t\tvirtual void Do_Shimmer(void);\n\n\t\t/*\n\t\t**\tMovement and animation.\n\t\t*/\n\t\tvirtual bool Is_Ready_To_Random_Animate(void) const;\n\t\tvirtual bool Random_Animate(void) {return(false);}\n\t\tvirtual void Assign_Destination(TARGET target);\n\t\tvirtual void Per_Cell_Process(PCPType why);\n\t\tvirtual void Enter_Idle_Mode(bool initial=false);\n\t\tvirtual void Look(bool incremental=false);\n\n\t\t/*\n\t\t**\tMap entry and exit logic.\n\t\t*/\n\t\tvirtual bool Unlimbo(COORDINATE , DirType facing=DIR_N);\n\t\tvirtual void Detach(TARGET target, bool all);\n\n\t\t/*\n\t\t**\tFacing translation tables that fix the flaw with 3D studio when\n\t\t**\tit renders 45 degree angles.\n\t\t*/\n\t\tstatic int const BodyShape[32];\n};\n\n#endif\n"
  },
  {
    "path": "CODE/TEMP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\nTHIS IS FROM SCORE.CPP\n\nline 79\n#ifdef FIXIT_SCORE_CRASH\nvoid Disable_Uncompressed_Shapes (void);\nvoid Enable_Uncompressed_Shapes (void);\n#endif\t//FIXIT\n\n\nline 361\n#ifdef FIXIT_SCORE_CRASH\n\t/*\n\t** Fix for the score screen crash due to uncompressed shape buffer overflow.\n\t*/\n\tDisable_Uncompressed_Shapes();\n#endif\t//FIXIT\n\n\n\nLINE 844\n#ifdef FIXIT_SCORE_CRASH\n\t/*\n\t** Fix for the score screen crash due to uncompressed shape buffer overflow.\n\t*/\n\tEnable_Uncompressed_Shapes();\n#endif\t//FIXIT\n\n\nend of score\n\n**********************\n\n\nkeyframe.cpp\n\nline 116\n#ifdef FIXIT_SCORE_CRASH\n\tchar * ptr;\n\tunsigned long offcurr, offdiff;\n#else\n\tchar * ptr, * lockptr;\n\tunsigned long offcurr, off16, offdiff;\n#endif\n\n\nline 184\n#ifndef FIXIT_SCORE_CRASH\n\t\toff16 = (unsigned long)lockptr & 0x00003FFFL;\n#endif\n\n\nline 194\n#ifndef FIXIT_SCORE_CRASH\n\t\tif ( ((offset[2] & 0x00FFFFFFL) - offcurr) >= (0x00010000L - off16) ) {\n\n\t\t\tptr = (char *)Add_Long_To_Pointer( ptr, offdiff );\n\t\t\toff16 = (unsigned long)ptr & 0x00003FFFL;\n\n\t\t\toffcurr += offdiff;\n\t\t\toffdiff = 0;\n\t\t}\n#endif\n\n\nline 228\n#ifndef FIXIT_SCORE_CRASH\n\t\t\t\tif ( ((offset[subframe+2] & 0x00FFFFFFL) - offcurr) >= (0x00010000L - off16) ) {\n\n\t\t\t\t\tptr = (char *)Add_Long_To_Pointer( ptr, offdiff );\n\t\t\t\t\toff16 = (unsigned long)lockptr & 0x00003FFFL;\n\n\t\t\t\t\toffcurr += offdiff;\n\t\t\t\t\toffdiff = 0;\n\t\t\t\t}\n#endif\n\n\nend keyframe\n**********************\n\n\n2keyframe.cpp\n\nline 53\n#ifdef FIXIT_SCORE_CRASH\n/*\n** Global required to fix the score screen crash bug by allowing disabling of uncompressed shapes.\n*/\nbool\t\tOriginalUseBigShapeBuffer = false;\n#endif\t//FIXIT\n\nend 2keyframe.cpp\n\n\n\n\n"
  },
  {
    "path": "CODE/TEMPLATE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TEMPLATE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TEMPLATE.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 17, 1994                                                 *\n *                                                                                             *\n *                  Last Update : January 23, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   TemplateClass::Init -- Resets the template object system.                                 *\n *   TemplateClass::Mark -- Lifts or drops a template object.                                  *\n *   TemplateClass::Select -- Select the template object.                                      *\n *   TemplateClass::TemplateClass -- Template object constructor.                              *\n *   TemplateClass::Unlimbo -- Places a template object into the game/map system.              *\n *   TemplateClass::delete -- Returns a template object to the pool.                           *\n *   TemplateClass::new -- Allocates a template object from pool                               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"template.h\"\n\n\n/***********************************************************************************************\n * TemplateClass::Init -- Resets the template object system.                                   *\n *                                                                                             *\n *    This routine resets the template object system. It is called                             *\n *    prior to loading a new scenario.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TemplateClass::Init(void)\n{\n\tTemplates.Free_All();\n}\n\n\n/***********************************************************************************************\n * TemplateClass::Mark -- Lifts or drops a template object.                                    *\n *                                                                                             *\n *    This routine handles placing or removing a template object. This                         *\n *    entails marking the map as appropriate and redisplaying affected                         *\n *    cells.                                                                                   *\n *                                                                                             *\n * INPUT:   mark  -- The marking operation to perform.                                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the template successfully marked?                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/17/1994 JLB : Created.                                                                 *\n *   12/23/1994 JLB : Examines low level legality before processing.                           *\n *=============================================================================================*/\nbool TemplateClass::Mark(MarkType mark)\n{\n\tassert(Templates.ID(this) == ID);\n\tassert(IsActive);\n\n\tstatic bool noup = false;\n\tvoid const * iset = Get_Image_Data();\n\tif (iset && ObjectClass::Mark(mark)) {\n\n\t\tvoid * map = Get_Icon_Set_Map(iset);\n\n\t\tfor (int y = 0; y < Class->Height; y++) {\n\t\t\tfor (int x = 0; x < Class->Width; x++) {\n\t\t\t\tCELL cell = Coord_Cell(Coord) + y*MAP_CELL_W + x;\n\t\t\t\tif (Map.In_Radar(cell)) {\n\t\t\t\t\tCellClass * cellptr = &Map[cell];\n\t\t\t\t\tint number = y*Class->Width + x;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDetermine if this logical icon actually maps to a real icon. If no real\n\t\t\t\t\t**\ticon is associated with this logical position, then don't do any action\n\t\t\t\t\t**\tsince none is required.\n\t\t\t\t\t*/\n\t\t\t\t\tchar * mapptr = (char*)map;\n\t\t\t\t\tbool real = (mapptr[number] != -1);\n\n\t\t\t\t\tif (real) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tLift the terrain object from the map.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (mark == MARK_UP && !noup) {\n\t\t\t\t\t\t\tif (cellptr->TType == Class->Type && cellptr->TIcon == number) {\n\t\t\t\t\t\t\t\tcellptr->TType = TEMPLATE_NONE;\n\t\t\t\t\t\t\t\tcellptr->TIcon = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tPlace the terrain object down.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (mark == MARK_DOWN) {\n\t\t\t\t\t\t\tif (*this == TEMPLATE_CLEAR1) {\n\t\t\t\t\t\t\t\tcellptr->TType = TEMPLATE_NONE;\n\t\t\t\t\t\t\t\tcellptr->TIcon = 0;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcellptr->TType = Class->Type;\n\t\t\t\t\t\t\t\tcellptr->TIcon = number;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tMake sure that no overlays or smudges exist after\n\t\t\t\t\t\t\t**\tplacing the template down.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tcellptr->Smudge = SMUDGE_NONE;\n\t\t\t\t\t\t\tcellptr->SmudgeData = 0;\n\t\t\t\t\t\t\tcellptr->Overlay = OVERLAY_NONE;\n\t\t\t\t\t\t\tcellptr->OverlayData = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcellptr->Redraw_Objects();\n\t\t\t\t\t\tcellptr->Recalc_Attributes();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tWhen marking this template down onto the map, the map template numbers are update\n\t\t**\tbut the template is removed from existence. Make sure that the deletion of the\n\t\t**\ttemplate object doesn't also lift the template numbers up from the map.\n\t\t*/\n\t\tif (mark == MARK_DOWN) {\n\t\t\tnoup = true;\n\t\t\tdelete this;\n\t\t\tnoup = false;\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TemplateClass::new -- Allocates a template object from pool                                 *\n *                                                                                             *\n *    This routine is used to allocate a template object from the                              *\n *    template object pool.                                                                    *\n *                                                                                             *\n * INPUT:   size  -- The size of a template object (not used).                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to an available template object.                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * TemplateClass::operator new(size_t )\n{\n\tvoid * ptr = Templates.Allocate();\n\tif (ptr) {\n\t\t((TemplateClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * TemplateClass::delete -- Returns a template object to the pool.                             *\n *                                                                                             *\n *    This routine will return a template object to the template object                        *\n *    pool. A template so returned is available for allocation again.                          *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the object to be returned.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TemplateClass::operator delete(void * ptr)\n{\n\tif (ptr) {\n\t\t((TemplateClass *)ptr)->IsActive = false;\n\t}\n\tTemplates.Free((TemplateClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * TemplateClass::TemplateClass -- Template object constructor.                                *\n *                                                                                             *\n *    This is the constructor for a template object.                                           *\n *                                                                                             *\n * INPUT:   type  -- The template object this is to become.                                    *\n *                                                                                             *\n *          pos   -- The position on the map to place the object.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTemplateClass::TemplateClass(TemplateType type, CELL pos) :\n\tObjectClass(RTTI_TEMPLATE, Templates.ID(this)),\n\tClass(TemplateTypes.Ptr((int)type))\n{\n\tif (pos != -1) {\n\t\tUnlimbo(Cell_Coord(pos));\n\t}\n}\n"
  },
  {
    "path": "CODE/TEMPLATE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TEMPLATE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TEMPLATE.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 17, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 17, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TEMPLATE_H\n#define TEMPLATE_H\n\n#include\t\"object.h\"\n#include\t\"type.h\"\n\n\n/******************************************************************************\n**\tThis class controls the template object. Template objects function congruously\n**\tto carpet on a floor. They have no depth, but merely control the icon to be rendered\n**\tas the cell's bottom most layer.\n*/\nclass TemplateClass : public ObjectClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis is a pointer to the template object's class.\n\t\t*/\n\t\tCCPtr<TemplateTypeClass> Class;\n\n\t\t/*-------------------------------------------------------------------\n\t\t**\tConstructors and destructors.\n\t\t*/\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\t\tTemplateClass(TemplateType type, CELL pos=-1);\n\t\tTemplateClass(NoInitClass const & x) : ObjectClass(x), Class(x) {};\n\t\tvirtual ~TemplateClass(void) {if (GameActive) TemplateClass::Limbo();Class=0;};\n\t\toperator TemplateType(void) const {return Class->Type;};\n\n\t\tstatic void Init(void);\n\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const {return *Class;};\n\t\tint Icon_Number(CELL cell);\n\n\t\t/*\n\t\t**\tDisplay and rendering support functionality. Supports imagery and how\n\t\t**\tobject interacts with the map and thus indirectly controls rendering.\n\t\t*/\n\t\tvirtual void Draw_It(int , int , WindowNumberType ) const {};\n\t\tvirtual bool Mark(MarkType mark);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/TENMGR.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*************************************************************************** \n *                                                                         * \n *                 Project Name : Command & Conquer                        * \n *                                                                         * \n *                    File Name : TENMGR.CPP                               * \n *                                                                         * \n *                   Programmer : Bill R. Randolph                         * \n *                                                                         * \n *                   Start Date : 06/26/96                                 * \n *                                                                         * \n *                  Last Update : July 22, 1996 [BRR]                      * \n *                                                                         * \n *-------------------------------------------------------------------------* \n * Functions:                                                              * \n *   TenConnManClass::TenConnManClass -- Class constructor                 * \n *   TenConnManClass::~TenConnManClass -- Class destructor                 * \n *   TenConnManClass::Init -- Inits TEN                                    * \n *   TenConnManClass::Service -- Service routine                           * \n *   TenConnManClass::Send_Private_Message -- Sends a \"private\" message    * \n *   TenConnManClass::Get_Private_Message -- Gets the next private message\t*\n *   TenConnManClass::Send_Global_Message -- Sends a \"global\" message      * \n *   TenConnManClass::Get_Global_Message -- Gets next global message\t\t\t*\n *   TenConnManClass::Num_Connections -- Reports # connections             * \n *   TenConnManClass::Connection_ID -- Reports a connection's ID           * \n *   TenConnManClass::Connection_Index -- Gets a connection's index        * \n *   TenConnManClass::Create_Connection -- Creates a new connection        * \n *   TenConnManClass::Delete_Connection -- Deletes a connection            * \n *   TenConnManClass::Connection_Name -- Reports a connection's name       * \n *   TenConnManClass::Connection_Address -- Gets a connection's \"address\"  * \n *   TenConnManClass::Global_Num_Send -- Reports # outgoing packets        * \n *   TenConnManClass::Global_Num_Receive -- Reports # incoming packets     * \n *   TenConnManClass::Private_Num_Send -- Reports # outgoing packets       * \n *   TenConnManClass::Private_Num_Receive -- Reports # incoming packets    * \n *   TenConnManClass::Flush_All -- Flushes all packets                     * \n *   TenConnManClass::Reset_Response_Time -- Does nothing                  * \n *   TenConnManClass::Response_Time -- Reports response time               * \n *   TenConnManClass::Set_Timing -- Does nothing                           * \n *   TenConnManClass::Configure_Debug -- Does nothing                      * \n *   TenConnManClass::Mono_Debug_Print -- Does nothing                     * \n *   terminateApp -- Callback: app terminates on error                     * \n *   debugMessage -- outputs debug message                                 * \n *   doAlert -- Outputs debug message                                      * \n *   doPregameHook -- Callback: game is starting                           * \n *   doIncomingPacket -- Callback: packet has arrived                      * \n *   doPlayerJoins -- Callback: player joins                               * \n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include \"function.h\"\n\n#ifdef WIN32\n#define WINDOWS\n#endif\n\n#if(TEN)\n#include \"ten.h\"\n\n//**************************************************************************\n// Constants\n//\nconst unsigned char kGlobalChannelFlag\t= 0x80;\nconst int kMaxPlayers = 8;\n\n//**************************************************************************\n// Functions\n//\nstatic void terminateApp(void);\nstatic void debugMessage(int msgLevel, char *msg);\nstatic void doAlert(int, int, char *);\nstatic void doPregameHook(char * joinType,  char *,  char *, \n\tchar *,  char *,  char *);\nvoid doIncomingPacket(int addr, void *buf, size_t size);\nvoid doPlayerEntered(int pid, int isYou, char *, char *, char *, long , char *);\n\n\n//**************************************************************************\n// Globals\n//\nstatic int IgnoreIncoming = 0;\n\n/*************************************************************************** \n * TenConnManClass::TenConnManClass -- Class constructor                   * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nTenConnManClass::TenConnManClass(void)\n{\n\tint i;\n\n\tIsHost = 0;\n\n\tGlobalQueue = new CommBufferClass(1, 50, sizeof(GlobalPacketType), 4);\n\tPrivateQueue = new CommBufferClass(1, 50, Session.TenSize, 4);\n\n\tNumConnections = 0;\n\tfor (i = 0; i < MAX_PLAYERS; i++) {\n\t\tConnections[i] = 0;\n\t\tID[i] = 0;\n\t\tNames[i][0] = 0;\n\t}\n\n}\t// end of TenConnManClass\n\n\n/*************************************************************************** \n * TenConnManClass::~TenConnManClass -- Class destructor                   * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nTenConnManClass::~TenConnManClass()\n{\n\ttenArExitArena();\n\n\tdelete GlobalQueue;\n\tdelete PrivateQueue;\n\n}\t// end of ~TenConnManClass\n\n\n/*************************************************************************** \n * TenConnManClass::Init -- Inits TEN                                      * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\t1.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nint TenConnManClass::Init(void)\n{\n\t//\n\t// set the debugging functions\n\t//\n\tsetExitRoutine(terminateApp);\n\tsetDebugMsgRoutine(debugMessage);\n\n\t//\n\t// callback function addresses\n\t//\n\ttenArSetAlertMessageRoutine(doAlert);\n\n\ttenArSetPregameHookRoutine(doPregameHook);\n\n\ttenArSetIncomingPacketRoutine(doIncomingPacket);\n\n\ttenArSetPlayerEnteredRoutine(doPlayerEntered);\n\n\tverifyNoErr(tenArInitArena(\"redalt\"));\t\n\n\treturn (1);\n\n}\t// end of Init\n\n\n/*************************************************************************** \n * TenConnManClass::Service -- Service routine                             * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\t1.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nint TenConnManClass::Service(void)\n{\n\ttenArIdleArena();\n\n\treturn (1);\n\n}\t// Service\n\n\n/*************************************************************************** \n * TenConnManClass::Send_Private_Message -- Sends a \"private\" message      * \n *                                                                         * \n * If Connection ID is -1, the packet is multicast; otherwise, it's sent\t*\n * to only the specified connection.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * Private & Global messages are sent via the same mechanism.  The only\t\t*\n * way to tell the difference between them is that the Global Channel\t\t*\n * packets have the 'kGlobalChannelFlag' bit set in the 1st byte (the\t\t*\n * \"Type\" field for EventClass's, and the NetCommand field for Global\t\t*\n * packets).\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * INPUT:                                                                  * \n *\t\tbuf\t\t\tpacket to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tsize of packet\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\treliable\t\t1 = must be delivered reliably\t\t\t\t\t\t\t\t\t*\n *\t\tconn_id\t\tconnection ID to send to, -1 = all\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nint TenConnManClass::Send_Private_Message(void *buf, int buflen, \n\tint reliable, int conn_id)\n{\n\tint doBroadcast = conn_id == -1;\n\tunsigned char *ucbuf = (unsigned char *)buf;\n\n\t//\n\t// Ensure the global channel flag isn't set on this outgoing packet\n\t//\n\t(void)verify(!(ucbuf[0] & kGlobalChannelFlag));\t\n\n\tif (doBroadcast)\n\t{\n\t\tif (reliable)\n\t\t{\n\t\t\tverifyNoErr(tenArSendToOtherPlayers(buf, buflen));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tverifyNoErr(tenArUnreliableSendToOtherPlayers(buf, buflen));\n\t\t}\n\t}\n\telse\n\t{\n\t\tint pid = Connection_Address(conn_id);\n\n\t\t(void)verify(pid >= 0 && pid < kMaxPlayers);\n\t\tif (reliable)\n\t\t{\n\t\t\tverifyNoErr(tenArSendToPlayer(pid, buf, buflen));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tverifyNoErr(tenArUnreliableSendToPlayer(pid, buf, buflen));\n\t\t}\n\t}\n\treturn (1);\n\t\n}\t// end of Send_Private_Message\n\n\n/*************************************************************************** \n * TenConnManClass::Get_Private_Message -- Gets the next private message\t*\n *                                                                         * \n * Retrieves the next-available \"private\" message, if there is one.\t\t\t*\n *                                                                         * \n * INPUT:                                                                  * \n *\t\tbuf\t\t\tpacket retrieved\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of packet\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tconn_id\t\tptr to store sender's connection ID\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nint TenConnManClass::Get_Private_Message(void *buf, int *buflen, \n\tint *conn_id)\n{\n\tint addr;\n\tint addrlen;\n\tint i;\n\n\tif (PrivateQueue->Num_Receive() > 0) {\n\t\tPrivateQueue->UnQueue_Receive(buf, buflen, 0, &addr, &addrlen);\n\t\t(void)verify(addrlen == 4);\n\t\t(*conn_id) = CONNECTION_NONE;\n\t\tfor (i = 0; i < NumConnections; i++) {\n\t\t\tif (addr == Connections[i]) {\n\t\t\t\t(*conn_id) = ID[i]; \n\t\t\t\treturn (1);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn (0);\n\n}\t// end of Get_Private_Message\n\n\n/*************************************************************************** \n * TenConnManClass::Send_Global_Message -- Sends a \"global\" message        * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tbuf\t\t\tpacket to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of packet\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\treliable\t\t1 = send reliably\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\taddress\t\taddress to send to; -1 = broadcast it (for TEN, this\t\t*\n *\t\t\t\t\t\tmeans send to all connected players).\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nint TenConnManClass::Send_Global_Message(void *buf, int buflen, \n\tint reliable, int address)\n{\n\tint doBroadcast = address == -1;\n\tunsigned char *ucbuf = (unsigned char *)buf;\n\n\t//\n\t// Ensure the global channel flag isn't set on this outgoing packet\n\t//\n\t(void)verify(!(ucbuf[0] & kGlobalChannelFlag));\t\n\n\t//\n\t// Set the global channel flag for this packet\n\t//\n\tucbuf[0] |= kGlobalChannelFlag;\n\n\tif (doBroadcast)\n\t{\n\t\tif (reliable)\n\t\t{\n\t\t\tverifyNoErr(tenArSendToOtherPlayers(buf, buflen));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tverifyNoErr(tenArUnreliableSendToOtherPlayers(buf, buflen));\n\t\t}\n\t}\n\telse\n\t{\n\t\tint pid = address;\n\n\t\t(void)verify(pid >= 0 && pid < kMaxPlayers);\n\t\tif (reliable)\n\t\t{\n\t\t\tverifyNoErr(tenArSendToPlayer(pid, buf, buflen));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tverifyNoErr(tenArUnreliableSendToPlayer(pid, buf, buflen));\n\t\t}\n\t}\n\n\t//\n\t// The caller may re-use this buffer, so clear the global channel flag.\n\t//\n\tucbuf[0] &= ~kGlobalChannelFlag;\n\n\treturn (1);\n\n}\t// end of Send_Global_Message\n\n\n/*************************************************************************** \n * TenConnManClass::Get_Global_Message -- Gets next global message\t\t\t*\n *                                                                         * \n * INPUT:                                                                  * \n *\t\tbuf\t\t\tbuffer to store packet in\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tptr filled in with packet length\t\t\t\t\t\t\t\t\t*\n *\t\taddress\t\tptr filled in with address (Player ID) of sender\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nint TenConnManClass::Get_Global_Message(void *buf, int *buflen, \n\tint *address)\n{\n\tint addrlen;\n\n\tif (GlobalQueue->Num_Receive() > 0) {\n\t\tGlobalQueue->UnQueue_Receive(buf, buflen, 0, address, &addrlen);\n\t\t(void)verify(addrlen == 4);\n\t\treturn (1);\n\t}\n\n\treturn (0);\n\n}\t// end of Get_Global_Message\n\n\n/*************************************************************************** \n * TenConnManClass::Num_Connections -- Reports # connections               * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\t# connections\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *                                                                         * \n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nint TenConnManClass::Num_Connections(void)\n{\n\treturn (NumConnections);\n\n}\t// end of Num_Connections\n\n\n/*************************************************************************** \n * TenConnManClass::Connection_ID -- Reports a connection's ID             * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tindex\t\t\tindex of connection to report\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tconnection ID for this connection\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nint TenConnManClass::Connection_ID(int index)\n{\n\tif (index >= 0 && index < NumConnections) {\n\t\treturn(ID[index]);\n\t} else {\n\t\treturn(CONNECTION_NONE);\n\t}\n\n}\t// end of Connection_ID\n\n\n/*************************************************************************** \n * TenConnManClass::Connection_Index -- Gets a connection's index          * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tid\t\t\tConnection ID to find index for\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tindex for that connection\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nint TenConnManClass::Connection_Index(int id)\n{\n\tint i;\n\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tif (ID[i] == id) {\n\t\t\treturn (i);\n\t\t}\n\t}\n\n\treturn(CONNECTION_NONE);\n\n}\t// end of Connection_Index\n\n\n/*************************************************************************** \n * TenConnManClass::Create_Connection -- Creates a new connection          * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tid\t\t\t\tID of connection\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tname\t\t\tname of connection\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\taddress\t\tTEN address (player ID) to give this connection\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\t1 = OK, 0 = error\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nint TenConnManClass::Create_Connection(int id, char *name, int address)\n{\n   Connections[NumConnections] = address;\n\tID[NumConnections] = id;\n   strcpy(Names[NumConnections], name);\n   NumConnections++;\n\n   return (1);\n\n}\t// end of Create_Connection\n\n\n/*************************************************************************** \n * TenConnManClass::Delete_Connection -- Deletes a connection              * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tid\t\tID for connection to delete\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\t1 = OK, 0 = error\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nint TenConnManClass::Delete_Connection(int id)\n{\n\tint i;\n\tint idx = Connection_Index(id);\n\tif (idx == CONNECTION_NONE) {\n\t\treturn 0;\n\t}\n\n\tfor (i = idx; i < NumConnections - 1; i++) {\n\t\tConnections[i] = Connections[i+1];\n\t\tID[i] = ID[i + 1];\n\t\tstrcpy (Names[i], Names[i + 1]);\n\t}\n\n   NumConnections--;\n\n   return (1);\n\n}\t// end of Delete_Connection\n\n\n/*************************************************************************** \n * TenConnManClass::Connection_Name -- Reports a connection's name         * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tid\t\tID of connection to report\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tconnection name\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nchar * TenConnManClass::Connection_Name(int id)\n{\n\tint i;\n\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tif (ID[i]==id) {\n\t\t\treturn(Names[i]);\n\t\t}\n\t}\n\n\treturn(NULL);\n\n}\t// end of Connection_Name\n\n\n/*************************************************************************** \n * TenConnManClass::Connection_Address -- Gets a connection's \"address\"    * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tid\t\tID of connection to report\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tconnection \"address\" (TEN player ID)\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nint TenConnManClass::Connection_Address(int id)\n{\n\tint i;\n\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tif (ID[i]==id) {\n\t\t\treturn(Connections[i]);\n\t\t}\n\t}\n\n\treturn(NULL);\n\n}\t// end of Connection_Address\n\n\n/*************************************************************************** \n * TenConnManClass::Global_Num_Send -- Reports # outgoing packets          * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\t0.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nint TenConnManClass::Global_Num_Send(void)\n{\n\treturn(0);\n\n}\t// end of Global_Num_Send\n\n/*************************************************************************** \n * TenConnManClass::Global_Num_Receive -- Reports # incoming packets       * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\t# packets waiting to be read\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nint TenConnManClass::Global_Num_Receive(void)\n{\n\treturn (GlobalQueue->Num_Receive());\n\n}\t// end of Global_Num_Receive\n\n/*************************************************************************** \n * TenConnManClass::Private_Num_Send -- Reports # outgoing packets         * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\t0.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nint TenConnManClass::Private_Num_Send(int /*id*/)\n{\n\treturn(0);\n\n}\t// end of Private_Num_Send\n\n/*************************************************************************** \n * TenConnManClass::Private_Num_Receive -- Reports # incoming packets      * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\t# packets waiting to be read\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nint TenConnManClass::Private_Num_Receive(int /*id*/)\n{\n\treturn (PrivateQueue->Num_Receive());\n\n}\t// end of Private_Num_Receive\n\n\n/*************************************************************************** \n * TenConnManClass::Flush_All -- Flushes all packets                       * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nvoid TenConnManClass::Flush_All(void)\n{\n\tint i;\n\tint maxqueuesize;\n\tint rc;\n\n\t//\n\t// Set the max # of packets that Ten will send me during any given\n\t// call to tenArIdleArena() to slightly smaller than my max queue\n\t// size.\n\t//\n\tmaxqueuesize = 45;\n\trc = tenArSetOption(kTenArOptReadQueueSize, &maxqueuesize, \n\t\tsizeof(maxqueuesize));\n\n\tverifyNoErr(rc);\n\n\n\t//\n\t// Set the flag to tell the doIncomingPacket routine to ignore packets.\n\t// (doIncomingPacket() is called by tenArIdleArena().)\n\t//\n\tIgnoreIncoming = 1;\n\n\twhile (i++ < 1000) {\n\t\ttenArIdleArena();\n\t\tif (GlobalQueue->Num_Receive() == 0 && \n\t\t\tPrivateQueue->Num_Receive() == 0) {\n\t\t\tbreak;\n\t\t}\n\t\tGlobalQueue->Init();\n\t\tPrivateQueue->Init();\n\t}\n\n\tIgnoreIncoming = 0;\n\n}\t// end of Flush_All\n\n\n/*************************************************************************** \n * TenConnManClass::Reset_Response_Time -- Does nothing                    * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nvoid TenConnManClass::Reset_Response_Time(void)\n{\n\t//\n\t// (This function intentionally left blank.)\n\t//\n\n}\t// end of Reset_Response_Time\n\n\n/*************************************************************************** \n * TenConnManClass::Response_Time -- Reports response time                 * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tworst-case connection response time (round-trip)\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nunsigned long TenConnManClass::Response_Time(void)\n{\n   return((Session.NetResponseTime * 60) / 1000);   // 300 milliseconds one way\n\n}\t// end of Response_Time\n\n\n/*************************************************************************** \n * TenConnManClass::Set_Timing -- Does nothing                             * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nvoid TenConnManClass::Set_Timing(unsigned long /*retrydelta*/, \n\tunsigned long /*maxretries*/, unsigned long /*timeout*/)\n{\n\t//\n\t// (This function intentionally left blank.)\n\t//\n\n}\t// end of Set_Timing\n\n\n/*************************************************************************** \n * TenConnManClass::Configure_Debug -- Does nothing                        * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nvoid TenConnManClass::Configure_Debug(int /*index*/, int /*type_offset*/, \n\tint /*type_size*/, char **/*names*/, int /*namestart*/, int /*namecount*/)\n{\n\t//\n\t// (This function intentionally left blank.)\n\t//\n\n}\t// end of Configure_Debug\n\n/*************************************************************************** \n * TenConnManClass::Mono_Debug_Print -- Does nothing                       * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nvoid TenConnManClass::Mono_Debug_Print(int /*index*/, int /*refresh*/)\n{\n\t//\n\t// (This function intentionally left blank.)\n\t//\n\n}\t// end of Mono_Debug_Print\n\n/*************************************************************************** \n * terminateApp -- Callback: app terminates on error                       * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nstatic void terminateApp(void)\n{\n\tProg_End();\n\tdprintf(\"Exiting due to a fatal error.\\n\");\n\texit(0);\n\n}\t// end of terminateApp\n\n\n/*************************************************************************** \n * debugMessage -- outputs debug message                                   * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tmsgLevel\t\t\tnot used\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tmsg\t\t\t\tmessage to print\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nstatic void debugMessage(int /*msgLevel*/, char *msg)\n{\n\tstatic int recurse = 0;\n\n\tif (recurse) {\n\t\treturn;\n\t}\n\n\trecurse = 1;\n\n\tif (MonoClass::Is_Enabled()) {\n\t\tMono_Printf(\"%s\\n\",msg);\n\t} else {\n\t\t//printf(\"%s\\n\",msg);\n\t\tFILE *fp;\n\t\tfp = fopen(\"tendebug.log\",\"at\");\n\t\tif (fp) {\n\t\t\tfprintf(fp,\"%s\\n\",msg);\n\t\t\tfclose(fp);\n\t\t}\n\t}\n\n\tif (GameActive) {\n\t\tWWMessageBox().Process(msg);\n\t}\n\n\trecurse = 0;\n\n}\t// end of debugMessage\n\n\n/*************************************************************************** \n * doAlert -- Outputs debug message                                        * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tmsg\t\t\tmessage to print\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nstatic void doAlert(int, int, char * msg)\n{\n\tstatic int recurse = 0;\n\n\tif (recurse) {\n\t\treturn;\n\t}\n\n\trecurse = 1;\n\n\tif (MonoClass::Is_Enabled()) {\n\t\tMono_Printf(\"%s\\n\",msg);\n\t} else {\n\t\t//printf(\"%s\\n\",msg);\n\t\tFILE *fp;\n\t\tfp = fopen(\"tenalert.log\",\"at\");\n\t\tif (fp) {\n\t\t\tfprintf(fp,\"%s\\n\",msg);\n\t\t\tfclose(fp);\n\t\t}\n\t}\n\n\tif (GameActive) {\n\t\tWWMessageBox().Process(msg);\n\t}\n\t\n\trecurse = 0;\n\n}\t// end of doAlert\n\n\n/*************************************************************************** \n * doPregameHook -- Callback: game is starting                             * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tjoinType\t\tif \"create\", we're the game host\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nstatic void doPregameHook(char * joinType,  char *,  char *, \n\tchar *,  char *,  char *)\n{\n\tchar typeToken[16];\n\n\tsscanf(joinType, \"%s\", typeToken);\n\tif (!strcmp(typeToken, \"create\")) {\n\t\tTen->IsHost = 1;\n\t}\n\n\tif (Ten->IsHost) {\n\t\tverifyNoErr(tenArReturnGameOptions(\"\"));\n\t}\n\n\tverifyNoErr(tenArReturnPlayerOptions(\"\"));\n\n}\t// end of doPregameHook\n\n\n/*************************************************************************** \n * doIncomingPacket -- Callback: packet has arrived                        * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\taddr\t\t\tplayer ID of sender\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuf\t\t\tbuffer containing incoming packet\t\t\t\t\t\t\t\t*\n *\t\tsize\t\t\tsize of incoming packet\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *                                                                         * \n * WARNINGS:                                                               * \n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nvoid doIncomingPacket(int addr, void *buf, size_t size)\n{\n\tint rc;\n\tunsigned char *byte;\n\n\t//\n\t// Check to see if this packet belongs to the Global Channel or not\n\t//\n\tbyte = (unsigned char *)buf;\n\n\t//\n\t// If the global channel flag is set in this packet, queue it onto the \n\t// Global Channel queue.  Ignore any errors if \"IgnoreIncoming\" is set,\n\t// which means we're in the process of flushing the queues.\n\t//\n\tif (byte[0] & kGlobalChannelFlag) {\n\t\tbyte[0] &= (~kGlobalChannelFlag);\n\t\trc = Ten->GlobalQueue->Queue_Receive(buf, size, &addr, 4);\n\t\tif (!IgnoreIncoming) {\n\t\t\t(void)verify(rc==1);\n\t\t}\n\t} else {\n\t\trc = Ten->PrivateQueue->Queue_Receive(buf, size, &addr, 4);\n\t\tif (!IgnoreIncoming) {\n\t\t\t(void)verify(rc==1);\n\t\t}\n\t}\n\n}\t// end of doIncomingPacket\n\n\n/*************************************************************************** \n * doPlayerJoins -- Callback: player joins                                 * \n *                                                                         * \n * INPUT:                                                                  * \n *\t\tpid\t\tplayer ID of the player joining\t\t\t\t\t\t\t\t\t\t*\n *\t\tisYou\t\ttrue = this is you\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   07/22/1996 BRR : Created.                                             * \n *=========================================================================*/\nvoid doPlayerEntered(int pid, int isYou, char * /*options*/, \n\tchar */*termOptions*/, char */*address*/, long /*uniqueId*/, \n\tchar */*joinType*/)\n{\n\tif (isYou) {\n\t\tSession.TenPlayerID = pid;\n\t}\n\n}\t// end of doPlayerJoins\n\n\n#endif\t//TEN\n/************************** end of tenmgr.cpp ******************************/\n"
  },
  {
    "path": "CODE/TENMGR.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*************************************************************************** \n *                                                                         * \n *                 Project Name : Command & Conquer                        * \n *                                                                         * \n *                    File Name : TENMGR.H                                 * \n *                                                                         * \n *                   Programmer : Bill R. Randolph                         * \n *                                                                         * \n *                   Start Date : 06/26/96                                 * \n *                                                                         * \n *                  Last Update : June 26, 1996 [BRR]                      * \n *                                                                         * \n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nclass TenConnManClass : public ConnManClass\n{\n\tpublic:\n\t\t//\n\t\t// Constructor / Destructor\n\t\t//\n\t\tTenConnManClass(void);\n\t\tvirtual ~TenConnManClass();\n\n\t\t//\n\t\t// Initialization\n\t\t//\n\t   int Init(void);\n\n\t\t//\n\t\t// Service routine\n\t\t//\n\t\tvirtual int Service(void);\n\n\t\t//\n\t\t// Sending & receiving data\n\t\t//\n\t\tvirtual int Send_Private_Message (void *buf, int buflen, \n\t\t\tint ack_req = 1, int conn_id = CONNECTION_NONE);\n\t\tvirtual int Get_Private_Message (void *buf, int *buflen, \n\t\t\tint *conn_id);\n\n\t   int Send_Global_Message(void *buf, int buflen, \n\t   \tint ack_req = 0, int address = 0);\n\t   int Get_Global_Message(void *buf, int *buflen, \n\t   \tint *address = 0);\n\n\t\t//\n\t\t// Connection management\n\t\t//\n\t\tvirtual int Num_Connections(void);\n\t\tvirtual int Connection_ID(int index);\n\t\tvirtual int Connection_Index(int id);\n\n\t   int Create_Connection(int id, char *name, int address);\n\t   int Delete_Connection(int id);\n\t   char *Connection_Name(int id);\n\t   int Connection_Address(int id);\n\n\t\t//\n\t\t// Queue utility routines\n\t\t//\n\t\tvirtual int Global_Num_Send(void);\n\t\tvirtual int Global_Num_Receive(void);\n\t\tvirtual int Private_Num_Send(int id = CONNECTION_NONE);\n\t\tvirtual int Private_Num_Receive(int id = CONNECTION_NONE);\n\n\t\tvoid Flush_All(void);\n\n\t\t//\n\t\t// Timing management\n\t\t//\n\t\tvirtual void Reset_Response_Time(void);\n\t\tvirtual unsigned long Response_Time(void);\n\t\tvirtual void Set_Timing (unsigned long retrydelta, \n\t\t\tunsigned long maxretries, unsigned long timeout);\n\n\t\t//\n\t\t// Debugging\n\t\t//\n\t\tvirtual void Configure_Debug(int index, int type_offset, int type_size, \n\t\t\tchar **names, int namestart, int namecount);\n\t\tvirtual void Mono_Debug_Print(int index, int refresh);\n\n\t\tCommBufferClass *GlobalQueue;\n\t\tCommBufferClass *PrivateQueue;\n\n\t\t//\n\t\t// This flag will be set if I'm the game host.\n\t\t//\n\t\tint IsHost;\n\n\tprivate:\n\t   int Connections[MAX_PLAYERS];\n\t\tint ID[MAX_PLAYERS];\n\t   char Names[MAX_PLAYERS][128];\n\t   int NumConnections;\n\n};\n\n/***************************** end of tenmgr.h *****************************/\n"
  },
  {
    "path": "CODE/TERRAIN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TERRAIN.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TERRAIN.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 29, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 4, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   TerrainClass::AI -- Process the terrain object AI.                                        *\n *   TerrainClass::Can_Enter_Cell -- Determines if the terrain object can exist in the cell.   *\n *   TerrainClass::Catch_Fire -- Catches the terrain object on fire.                           *\n *   TerrainClass::Center_Coord -- Fetches the center point coordinate for terrain object.     *\n *   TerrainClass::Debug_Dump -- Displays the status of the terrain object.                    *\n *   TerrainClass::Draw_It -- Renders the terrain object at the location specified.            *\n *   TerrainClass::Fire_Out -- Handles when fire has gone out.                                 *\n *   TerrainClass::Heath_Ratio -- Determines the health ratio for the terrain object.          *\n *   TerrainClass::Init -- Initialize the terrain object tracking system.                      *\n *   TerrainClass::Limbo -- Handles terrain specific limbo action.                             *\n *   TerrainClass::Mark -- Marks the terrain object on the map.                                *\n *   TerrainClass::Radar_Icon -- Fetches pointer to radar icon to use.                         *\n *   TerrainClass::Read_INI -- Reads terrain objects from INI file.                            *\n *   TerrainClass::Start_To_Crumble -- Initiates crumbling of terrain (tree) object.           *\n *   TerrainClass::Take_Damage -- Damages the terrain object as specified.                     *\n *   TerrainClass::Target_Coord -- Returns with the target coordinate.                         *\n *   TerrainClass::TerrainClass -- This is the constructor for a terrain object.               *\n *   TerrainClass::Unlimbo -- Unlimbo terrain object onto the map.                             *\n *   TerrainClass::Write_INI -- Write all terrain objects to the INI database specified.       *\n *   TerrainClass::delete -- Deletes a terrain object.                                         *\n *   TerrainClass::new -- Creates a new terrain object.                                        *\n *   TerrainClass::~TerrainClass -- Default destructor for terrain class objects.              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"terrain.h\"\n\n\n/***********************************************************************************************\n * TerrainClass::~TerrainClass -- Default destructor for terrain class objects.                *\n *                                                                                             *\n *    This is the default destructor for terrain objects. It will remove the object from the   *\n *    map and tracking systems, but only if the game is running. Otherwise, it does nothing.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTerrainClass::~TerrainClass(void)\n{\n\tif (GameActive && Class) {\n\t\tTerrainClass::Limbo();\n\t}\n}\n\n\n/***********************************************************************************************\n * TerrainClass::Take_Damage -- Damages the terrain object as specified.                       *\n *                                                                                             *\n *    This routine is called when damage is to be inflicted upon the terrain object. It is     *\n *    through this routine that terrain objects are attacked and thereby destroyed. Not all    *\n *    terrain objects can be damaged by this routine however.                                  *\n *                                                                                             *\n * INPUT:   damage      -- The damage points to inflict (raw).                                 *\n *                                                                                             *\n *          warhead     -- The warhead type the indicates the kind of damage. This is used to  *\n *                         determine if the terrain object is damaged and if so, by how much.  *\n *                                                                                             *\n * OUTPUT:  bool; Was the terrain object destroyed by this damage?                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *   11/22/1994 JLB : Shares base damage handler for techno objects.                           *\n *   12/11/1994 JLB : Shortens attached burning animations.                                    *\n *=============================================================================================*/\nResultType TerrainClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, bool forced)\n{\n\tassert(Terrains.ID(this) == ID);\n\tassert(IsActive);\n\n\tResultType res = RESULT_NONE;\n\n\t/*\n\t**\tSmall arms can never destroy a terrain element.\n\t*/\n\tif ((!IsOnFire || warhead == WARHEAD_FIRE) && warhead != WARHEAD_SA && !Class->IsImmune) {\n\n\t\tres = ObjectClass::Take_Damage(damage, distance, warhead, source, forced);\n\n\t\tif (damage && warhead == WARHEAD_FIRE) {\n\t\t\tCatch_Fire();\n\t\t}\n\n\t\t/*\n\t\t**\tIf the terrain object is destroyed by this damage, then only remove it if it\n\t\t**\tcurrently isn't on fire and isn't in the process of crumbling.\n\t\t*/\n\t\tif (res == RESULT_DESTROYED) {\n\n\t\t\t/*\n\t\t\t**\tRemove this terrain object from the targeting computers of all other\n\t\t\t**\tgame objects. No use beating a dead horse.\n\t\t\t*/\n\t\t\tDetach_All();\n\n\t\t\tif (IsOnFire) {\n\n\t\t\t\t/*\n\t\t\t\t**\tAttached flame animation should be shortened as much as possible so that\n\t\t\t\t**\tcrumbling can begin soon.\n\t\t\t\t*/\n\t\t\t\tShorten_Attached_Anims(this);\n\t\t\t} else {\n\t\t\t\tStart_To_Crumble();\n\t\t\t}\n\t\t}\n\t}\n\treturn(res);\n}\n\n\n/***********************************************************************************************\n * TerrainClass::new -- Creates a new terrain object.                                          *\n *                                                                                             *\n *    This routine creates a new terrain object by grabbing a free slot                        *\n *    out of the terrain object pool.                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the terrain object allocated.                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/14/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * TerrainClass::operator new(size_t)\n{\n\tvoid * ptr = Terrains.Allocate();\n\tif (ptr) {\n\t\t((TerrainClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * TerrainClass::delete -- Deletes a terrain object.                                           *\n *                                                                                             *\n *    This routine deletes a terrain object by returning it to the                             *\n *    terrain object pool.                                                                     *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the terrain object to delete.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/14/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TerrainClass::operator delete(void * ptr)\n{\n\tif (ptr) {\n\t\t((TerrainClass *)ptr)->IsActive = false;\n\t}\n\tTerrains.Free((TerrainClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * TerrainClass::TerrainClass -- This is the constructor for a terrain object                  *\n *                                                                                             *\n *    This constructor for a terrain object will initialize the terrain                        *\n *    object with it's proper type and insert it into the access                               *\n *    tracking system.                                                                         *\n *                                                                                             *\n * INPUT:   type  -- The terrain object type.                                                  *\n *                                                                                             *\n *          cell  -- The location of the terrain object.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTerrainClass::TerrainClass(TerrainType type, CELL cell) :\n\tObjectClass(RTTI_TERRAIN, Terrains.ID(this)),\n\tClass(TerrainTypes.Ptr((int)type)),\n\tIsOnFire(false),\n\tIsCrumbling(false)\n{\n\tStrength = Class->MaxStrength;\n\tif (cell != -1) {\n\t\tif (!Unlimbo(Cell_Coord(cell))) {\n\t\t\tdelete this;\n\t\t}\n\t}\n\tSet_Rate(0);\t// turn off animation\n}\n\n\n/***********************************************************************************************\n * TerrainClass::Mark -- Marks the terrain object on the map.                                  *\n *                                                                                             *\n *    This routine will mark or remove the terrain object from the map                         *\n *    tracking system. This is typically called when the terrain object                        *\n *    is first created, when it is destroyed, and whenever it needs to be                      *\n *    redrawn.                                                                                 *\n *                                                                                             *\n * INPUT:   mark  -- The marking operation to perform.                                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the terrain object successfully marked?                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/02/1994 JLB : Created.                                                                 *\n *   12/23/1994 JLB : Performs low level legality check before proceeding.                     *\n *=============================================================================================*/\nbool TerrainClass::Mark(MarkType mark)\n{\n\tassert(Terrains.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (ObjectClass::Mark(mark)) {\n\t\tCELL cell = Coord_Cell(Coord);\n\n\t\tswitch (mark) {\n\t\t\tcase MARK_UP:\n\t\t\t\tMap.Pick_Up(cell, this);\n\t\t\t\tbreak;\n\n\t\t\tcase MARK_DOWN:\n\t\t\t\tMap.Place_Down(cell, this);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tMap.Refresh_Cells(cell, Overlap_List(true));\n\t\t\t\tMap.Refresh_Cells(cell, Occupy_List());\n\t\t\t\tbreak;\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TerrainClass::Draw_It -- Renders the terrain object at the location specified.              *\n *                                                                                             *\n *    This routine is used to render the terrain object at the location specified and          *\n *    clipped to the window specified. This is the gruntwork drawing routine for the           *\n *    terrain objects as they are displayed on the map.                                        *\n *                                                                                             *\n * INPUT:   x,y      -- The coordinate to draw the terrain object at (centered).               *\n *                                                                                             *\n *          window   -- The clipping window to draw to.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/27/1994 JLB : Created.                                                                 *\n *   11/09/1994 JLB : Changed selected terrain highlight method.                               *\n *=============================================================================================*/\nvoid TerrainClass::Draw_It(int x, int y, WindowNumberType window) const\n{\n\tassert(Terrains.ID(this) == ID);\n\tassert(IsActive);\n\n\tvoid const * shapedata;\n\n\tshapedata = Get_Image_Data();\n\tif (shapedata) {\n\t\tint\tshapenum = 0;\n\n\t\t/*\n\t\t**\tDetermine the animation stage to render the terrain object. If it is crumbling, then\n\t\t**\tit will display the crumbling animation.\n\t\t*/\n\t\tif (IsCrumbling) {\n\t\t\tshapenum = Fetch_Stage()+IsCrumbling;\n\t\t} else {\n\t\t\tif (Strength < 2) {\n\t\t\t\tshapenum++;\n\t\t\t}\n\t\t}\n\n\t\tShapeFlags_Type flags = SHAPE_NORMAL;\n\t\tif (IsSelected && Debug_Map) flags = flags | SHAPE_FADING;\n\n\t\t/*\n\t\t**Terrain is always theater specific so flag it as such for Build_Frame\n\t\t*/\n\t\tIsTheaterShape = true;\n\t\tCC_Draw_Shape(shapedata, shapenum, x, y, window, flags|SHAPE_WIN_REL|SHAPE_GHOST, Map.FadingLight, Map.UnitShadow);\n\t\tIsTheaterShape = false;\n\t}\n}\n\n\n/***********************************************************************************************\n * TerrainClass::Init -- Initialize the terrain object tracking system.                        *\n *                                                                                             *\n *    This routine will clear out the terrain object system so that no terrain objects will    *\n *    exists. It is called prior to loading or starting a scenario.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TerrainClass::Init(void)\n{\n\tTerrains.Free_All();\n}\n\n\n/***********************************************************************************************\n * TerrainClass::Can_Enter_Cell -- Determines if the terrain object can exist in the cell.     *\n *                                                                                             *\n *    This routine will examine the cell specified and determine if the the terrain object     *\n *    can legally exist there.                                                                 *\n *                                                                                             *\n * INPUT:   cell  -- The cell to examine.                                                      *\n *                                                                                             *\n * OUTPUT:  If the terrain object can be placed in the cell specified, then a value less than  *\n *          256 will be returned.                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *   01/01/1995 JLB : Actually works now.                                                      *\n *=============================================================================================*/\nMoveType TerrainClass::Can_Enter_Cell(CELL cell, FacingType) const\n{\n\tassert(Terrains.ID(this) == ID);\n\tassert(IsActive);\n\n\tshort const\t* offset;\t\t// Pointer to cell offset list.\n\n\tif ((unsigned)cell >= MAP_CELL_TOTAL) return(MOVE_NO);\n\n\toffset = Occupy_List();\n\twhile (*offset != REFRESH_EOL) {\n\t\tif (Class->IsWaterBased) {\n\t\t\tif (!Map[(CELL)(cell + *offset++)].Is_Clear_To_Build(SPEED_FLOAT)) {\n\t\t\t\treturn(MOVE_NO);\n\t\t\t}\n\t\t} else {\n\t\t\tif (!Map[(CELL)(cell + *offset++)].Is_Clear_To_Build()) {\n\t\t\t\treturn(MOVE_NO);\n\t\t\t}\n\t\t}\n\t}\n\treturn(MOVE_OK);\n}\n\n\n/***********************************************************************************************\n * TerrainClass::Catch_Fire -- Catches the terrain object on fire.                             *\n *                                                                                             *\n *    This routine is called if the terrain object is supposed to catch on fire. The routine   *\n *    performs checking to make sure that only flammable terrain objects that aren't already   *\n *    on fire get caught on fire.                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the terrain object caught on fire by this routine?                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/27/1994 JLB : Created.                                                                 *\n *   12/11/1994 JLB : Don't catch fire if already on fire or crumbling.                        *\n *=============================================================================================*/\nbool TerrainClass::Catch_Fire(void)\n{\n\tassert(Terrains.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!IsCrumbling && !IsOnFire && Class->Armor == ARMOR_WOOD) {\n\t\tAnimClass * anim = new AnimClass(ANIM_BURN_BIG, Coord_Add(Sort_Y(), 0xFFB00000L));\n\t\tif (anim) {\n\t\t\tanim->Attach_To(this);\n\t\t}\n\t\tanim = new AnimClass(ANIM_BURN_MED, Coord_Add(Sort_Y(), 0xFF200000L), 15);\n\t\tif (anim) {\n\t\t\tanim->Attach_To(this);\n\t\t}\n\t\tIsOnFire = true;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TerrainClass::Fire_Out -- Handles when fire has gone out.                                   *\n *                                                                                             *\n *    When the fire has gone out on a burning terrain object, this routine is called. The      *\n *    animation has already been terminated prior to calling this routine. All this routine    *\n *    needs to perform is any necessary local flag updating.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TerrainClass::Fire_Out(void)\n{\n\tassert(Terrains.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (IsOnFire) {\n\t\tIsOnFire = false;\n\t\tif (!IsCrumbling && !Strength) {\n\t\t\tDetach_All();\n\t\t\tMark();\n\t\t\tStart_To_Crumble();\n\t\t\tnew AnimClass(ANIM_SMOKE_M, Coord_Add(Coord, Class->CenterBase));\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TerrainClass::AI -- Process the terrain object AI.                                          *\n *                                                                                             *\n *    This is used to handle any AI processing necessary for terrain objects. This might       *\n *    include animation effects.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/27/1994 JLB : Created.                                                                 *\n *   09/28/1994 JLB : Crumbling animation.                                                     *\n *   08/12/1996 JLB : Reset map zone when terrain object destroyed.                            *\n *   10/04/1996 JLB : Growth speed regulated by rules.                                         *\n *=============================================================================================*/\nvoid TerrainClass::AI(void)\n{\n\tassert(Terrains.ID(this) == ID);\n\tassert(IsActive);\n\n\tObjectClass::AI();\n\n\tif ((*this == TERRAIN_MINE) && (Frame % (Rule.GrowthRate * TICKS_PER_MINUTE)) == 0) {\n\t\tMap[::As_Cell(As_Target())].Spread_Tiberium(true);\n\t}\n\tif (StageClass::Graphic_Logic()) {\n\t\tMark();\n\n\t\t/*\n\t\t**\tIf the terrain object is in the process of crumbling, then when at the\n\t\t**\tlast stage of the crumbling animation, delete the terrain object.\n\t\t*/\n\t\tif (IsCrumbling && Fetch_Stage() == Get_Build_Frame_Count(Class->Get_Image_Data())-1) {\n\t\t\tdelete this;\n\n\t\t\tMap.Zone_Reset(MZONEF_NORMAL|MZONEF_CRUSHER|MZONEF_DESTROYER);\n\t\t}\n\t}\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * TerrainClass::Debug_Dump -- Displays the status of the terrain object.                      *\n *                                                                                             *\n *    This debugging support routine is used to display the status of the terrain object to    *\n *    the debug screen.                                                                        *\n *                                                                                             *\n * INPUT:   mono  -- The mono screen to display the status to.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TerrainClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(Terrains.ID(this) == ID);\n\tassert(IsActive);\n\n\tObjectClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * TerrainClass::Unlimbo -- Unlimbo terrain object onto the map.                               *\n *                                                                                             *\n *    This routine is used to unlimbo the terrain object onto a location on the map. Normal    *\n *    unlimbo procedures are sufficient except that the coordinate location of a terrain       *\n *    object is based on the upper left corner of a cell rather than the center. Mask the      *\n *    coordinate value so that it snaps to the upper left corner and then proceed with a       *\n *    normal unlimbo process.                                                                  *\n *                                                                                             *\n * INPUT:   coord    -- The coordinate to mark as the terrain's location.                      *\n *                                                                                             *\n *          dir      -- unused                                                                 *\n *                                                                                             *\n * OUTPUT:  bool; Was the terrain object successful in the unlimbo process? Failure could be   *\n *                the result of illegal positioning.                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1994 JLB : Created.                                                                 *\n *   11/16/1994 JLB : Checks for theater legality.                                             *\n *=============================================================================================*/\nbool TerrainClass::Unlimbo(COORDINATE coord, DirType dir)\n{\n\tassert(Terrains.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->Theater & (1 << Scen.Theater)) {\n\t\treturn(ObjectClass::Unlimbo(coord, dir));\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TerrainClass::Start_To_Crumble -- Initiates crumbling of terrain (tree) object.             *\n *                                                                                             *\n *    This routine is used to start the crumbling process for terrain object. This only        *\n *    applies to trees.                                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TerrainClass::Start_To_Crumble(void)\n{\n\tassert(Terrains.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!IsCrumbling) {\n\t\tIsCrumbling = true;\n\t\tSet_Rate(2);\n\t\tSet_Stage(0);\n\t}\n}\n\n\n/***********************************************************************************************\n * TerrainClass::Limbo -- Handles terrain specific limbo action.                               *\n *                                                                                             *\n *    This routine (called as a part of the limbo process) will remove the terrain occupation  *\n *    flag in the cell it occupies.                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the terrain object unlimboed?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TerrainClass::Limbo(void)\n{\n\tassert(Terrains.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!IsInLimbo) {\n\t\tCELL cell = Coord_Cell(Coord);\n\t\tMap[cell].Flag.Occupy.Monolith = false;\n\t}\n\treturn(ObjectClass::Limbo());\n}\n\n\n/***********************************************************************************************\n * TerrainClass::Center_Coord -- Fetches the center point coordinate for terrain object.       *\n *                                                                                             *\n *    Use this routine to fetch the center point terrain                                       *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE TerrainClass::Center_Coord(void) const\n{\n\tassert(Terrains.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(Coord_Add(Coord, Class->CenterBase));\n}\n\n\n/***********************************************************************************************\n * TerrainClass::Radar_Icon -- Fetches pointer to radar icon to use.                           *\n *                                                                                             *\n *    This routine will return with a pointer to the radar icon to use for the cell number     *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   cell  -- The cell number to use when determine what icon pointer to return.        *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the 9 pixel values that make up the icon of this         *\n *          terrain object located at the cell specified.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned char * TerrainClass::Radar_Icon(CELL cell)\n{\n\tassert(Terrains.ID(this) == ID);\n\tassert(IsActive);\n\n\tunsigned char * icon = (unsigned char *)Class->Get_Radar_Data();\t// get a pointer to radar icons\n\tint  width = *icon++;\t\t\t\t\t\t\t// extract the width from data\n\tint  height = *icon++;\t\t\t\t\t\t\t// extract the width from data\n\n\t/*\n\t** Icon number that we need can be found by converting the cell and base\n\t** cell to and x and y offset from the upper left of the cell, and then\n\t** multiplying it by the width of the terrain in icons, which we\n\t** conveniently stored out as the first byte of every icon we made.\n\t*/\n\tint basecell = Coord_Cell(Coord);\t\t\t\t// find the base cell of terrain\n\tint ydiff = Cell_Y(cell) - Cell_Y(basecell);\n\tint xdiff = Cell_X(cell) - Cell_X(basecell);\n\tif (xdiff < width && ydiff < height) {\n\t\tint iconnum = (ydiff * width) + xdiff;\n\t\treturn(icon + (iconnum * 9));\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * TerrainClass::Target_Coord -- Returns with the target coordinate.                           *\n *                                                                                             *\n *    This routine will return with the coordinate to use if this terrain object were to be    *\n *    fired upon and the coordinate where the bullets should hit is needed. Usually, this      *\n *    location is the base of the object (e.g., the trunk of a tree).                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate to use when firing at this object.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/07/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE TerrainClass::Target_Coord(void) const\n{\n\treturn(Coord_Add(XY_Coord(0, -Height), Sort_Y()));\n}\n\n\n/***********************************************************************************************\n * TerrainClass::Read_INI -- Reads terrain objects from INI file.                              *\n *                                                                                             *\n *    This routine reads a scenario control INI file and creates all                           *\n *    terrain objects specified therein. Objects so created are placed                         *\n *    upon the map.                                                                            *\n *                                                                                             *\n *      INI entry format:                                                                      *\n *      cellnum = TypeName, Triggername                                                        *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the loaded scenario INI file data.                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TerrainClass::Read_INI(CCINIClass & ini)\n{\n\tTerrainClass * tptr;\n\n\tint len = ini.Entry_Count(INI_Name());\n\n\tfor (int index = 0; index < len; index++) {\n\t\tchar const * entry = ini.Get_Entry(INI_Name(), index);\n\t\tTerrainType terrain = ini.Get_TerrainType(INI_Name(), entry, TERRAIN_NONE);\n\t\tCELL cell = atoi(entry);\n\n\t\tif (terrain != TERRAIN_NONE) {\n\t\t\ttptr = new TerrainClass(terrain, cell);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TerrainClass::Write_INI -- Write all terrain objects to the INI database specified.         *\n *                                                                                             *\n *    This routine will clear out any old terrain data from the INI database and then          *\n *    fill it in with all the data from the terrain objects that currently exists.             *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to store the terrain objects in.            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TerrainClass::Write_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tFirst, clear out all existing terrain data from the ini file.\n\t*/\n\tini.Clear(INI_Name());\n\n\t/*\n\t**\tWrite the terrain data out.\n\t*/\n\tfor (int index = 0; index < Terrains.Count(); index++) {\n\t\tTerrainClass * terrain;\n\n\t\tterrain = Terrains.Ptr(index);\n\t\tif (terrain != NULL && !terrain->IsInLimbo && terrain->IsActive) {\n\t\t\tchar\tuname[10];\n\t\t\tsprintf(uname, \"%d\", Coord_Cell(terrain->Coord));\n\t\t\tini.Put_TerrainType(INI_Name(), uname, *terrain);\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "CODE/TERRAIN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TERRAIN.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TERRAIN.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 29, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 29, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TERRAIN_H\n#define TERRAIN_H\n\n#include\t\"object.h\"\n#include\t\"type.h\"\n\n\n/****************************************************************************\n**\tEach type of terrain has certain pieces of static information associated\n**\twith it. This class elaborates this data.\n*/\nclass TerrainClass : public ObjectClass, public StageClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis points to the constant terrain data (for this type) that gives this\n\t\t**\tterrain object its character.\n\t\t*/\n\t\tCCPtr<TerrainTypeClass> Class;\n\n  \t\t/*\n\t\t**\tConstructor for terrain object class.\n\t\t*/\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\t\tTerrainClass(TerrainType id, CELL cell);\n\t\tTerrainClass(NoInitClass const & x) : ObjectClass(x), Class(x), StageClass(x) {};\n\t\tvirtual ~TerrainClass(void);\n\t\toperator TerrainType(void) const {return Class->Type;};\n\n\t\tstatic void Init(void);\n\n\t\t/*\n\t\t**\tTerrain specific support functions.\n\t\t*/\n\t\tvoid Start_To_Crumble(void);\n\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const {return *Class;};\n\n\t\t/*\n\t\t**\tCoordinate inquiry functions. These are used for both display and\n\t\t**\tcombat purposes.\n\t\t*/\n\t\tvirtual COORDINATE Center_Coord(void) const;\n\t\tvirtual COORDINATE Render_Coord(void) const {return Coord;};\n\t\tvirtual COORDINATE Sort_Y(void) const {return Coord_Add(Coord, Class->CenterBase);};\n\t\tvirtual COORDINATE Target_Coord(void) const;\n\n\t\t/*\n\t\t**\tObject entry and exit from the game system.\n\t\t*/\n\t\tvirtual bool Unlimbo(COORDINATE coord, DirType dir=DIR_N);\n\t\tvirtual bool Limbo(void);\n\t\tvirtual MoveType Can_Enter_Cell(CELL cell, FacingType facing = FACING_NONE) const;\n\n\t\t/*\n\t\t**\tDisplay and rendering support functionality. Supports imagery and how\n\t\t**\tobject interacts with the map and thus indirectly controls rendering.\n\t\t*/\n\t\tvirtual void Draw_It(int x, int y, WindowNumberType window) const;\n\t\tvirtual bool Mark(MarkType mark=MARK_CHANGE);\n\t\tunsigned char *Radar_Icon(CELL cell);\n\n\t\t/*\n\t\t**\tUser I/O.\n\t\t*/\n\t\tvirtual void Clicked_As_Target(int) {};\n\n\t\t/*\n\t\t**\tCombat related.\n\t\t*/\n\t\tvirtual void Fire_Out(void);\n\t\tvirtual bool Catch_Fire(void);\n\t\tvirtual ResultType Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, bool forced=false);\n\n\t\t/*\n\t\t**\tAI.\n\t\t*/\n\t\tvirtual void AI(void);\n\n\t\t/*\n\t\t**\tScenario and debug support.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tstatic void Read_INI(CCINIClass & ini);\n\t\tstatic void Write_INI(CCINIClass & ini);\n\t\tstatic char *INI_Name(void) {return \"TERRAIN\";};\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tIf this terrain object is on fire, then this flag will be true.\n\t\t*/\n\t\tunsigned IsOnFire:1;\n\n\t\t/*\n\t\t**\tIs this a terrain object that undergoes crumbling animation and it is\n\t\t**\tin fact crumbling at this time?\n\t\t*/\n\t\tunsigned IsCrumbling:1;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/TEVENT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TEVENT.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TEVENT.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/28/95                                                     *\n *                                                                                             *\n *                  Last Update : July 29, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Attaches_To -- Determines what event can be attached to.                                  *\n *   EventChoiceClass::Draw_It -- Displays the event choice class as a text string.            *\n *   Event_From_Name -- retrieves EventType for given name                                     *\n *   Event_Needs -- Returns with what this event type needs for data.                          *\n *   Name_From_Event -- retrieves name for EventType                                           *\n *   TEventClass::Build_INI_Entry -- Builds the ini text for this event.                       *\n *   TEventClass::Read_INI -- Parses the INI text for this event's data.                       *\n *   TEventClass::Reset -- Reset the trigger for a subsequent \"spring\".                        *\n *   TEventClass::operator () -- Action operator to see if event is satisfied.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n\n/*\n**\tThis is the text name for all of the trigger events. These are used by the scenario editor\n*/\nconst char * EventText[TEVENT_COUNT] = {\n\t\"-No Event-\",\n\t\"Entered by...\",\n\t\"Spied by...\",\n\t\"Thieved by...\",\n\t\"Discovered by player\",\n\t\"House Discovered...\",\n\t\"Attacked by anybody\",\n\t\"Destroyed by anybody\",\n\t\"Any Event\",\n\t\"Destroyed, Units, All...\",\n\t\"Destroyed, Buildings, All...\",\n\t\"Destroyed, All...\",\n\t\"Credits exceed (x100)...\",\n\t\"Elapsed Time (1/10th min)...\",\n\t\"Mission Timer Expired\",\n\t\"Destroyed, Buildings, #...\",\n\t\"Destroyed, Units, #...\",\n\t\"No Factories left\",\n\t\"Civilians Evacuated\",\n\t\"Build Building Type...\",\n\t\"Build Unit Type...\",\n\t\"Build Infantry Type...\",\n\t\"Build Aircraft Type...\",\n\t\"Leaves map (team)...\",\n\t\"Zone Entry by...\",\n\t\"Crosses Horizontal Line...\",\n\t\"Crosses Vertical Line...\",\n\t\"Global is set...\",\n\t\"Global is clear...\",\n\t\"Destroyed, Fakes, All...\",\n\t\"Low Power...\",\n\t\"All bridges destroyed\",\n\t\"Building exists...\"\n};\n\n\n/*\n**\tThis is an ordinal list of trigger events. This list\n**\tis used when generating the trigger dialog box.\n*/\nEventChoiceClass EventChoices[TEVENT_COUNT] = {\n\t{TEVENT_NONE},\n\t{TEVENT_PLAYER_ENTERED},\n\t{TEVENT_SPIED},\n\t{TEVENT_THIEVED},\n\t{TEVENT_DISCOVERED},\n\t{TEVENT_HOUSE_DISCOVERED},\n\t{TEVENT_ATTACKED},\n\t{TEVENT_DESTROYED},\n\t{TEVENT_ANY},\n\t{TEVENT_UNITS_DESTROYED},\n\t{TEVENT_BUILDINGS_DESTROYED},\n\t{TEVENT_ALL_DESTROYED},\n\t{TEVENT_CREDITS},\n\t{TEVENT_TIME},\n\t{TEVENT_MISSION_TIMER_EXPIRED},\n\t{TEVENT_NBUILDINGS_DESTROYED},\n\t{TEVENT_NUNITS_DESTROYED},\n\t{TEVENT_NOFACTORIES},\n\t{TEVENT_EVAC_CIVILIAN},\n\t{TEVENT_BUILD},\n\t{TEVENT_BUILD_UNIT},\n\t{TEVENT_BUILD_INFANTRY},\n\t{TEVENT_BUILD_AIRCRAFT},\n\t{TEVENT_LEAVES_MAP},\n\t{TEVENT_ENTERS_ZONE},\n\t{TEVENT_CROSS_HORIZONTAL},\n\t{TEVENT_CROSS_VERTICAL},\n\t{TEVENT_GLOBAL_SET},\n\t{TEVENT_GLOBAL_CLEAR},\n\t{TEVENT_FAKES_DESTROYED},\n\t{TEVENT_LOW_POWER},\n\t{TEVENT_ALL_BRIDGES_DESTROYED},\n\t{TEVENT_BUILDING_EXISTS},\n};\n\n\n/***********************************************************************************************\n * EventChoiceClass::Draw_It -- Displays the event choice class as a text string.              *\n *                                                                                             *\n *    This utility routine is used by the list box display code to print the text line that    *\n *    describes the event choice action.                                                       *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid EventChoiceClass::Draw_It(int , int x, int y, int width, int height, bool selected, TextPrintType flags) const\n{\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\tstatic int _tabs[] = {13,40};\n\tif ((flags & 0x0F) == TPF_6PT_GRAD || (flags & 0x0F) == TPF_EFNT) {\n\n\t\tif (selected) {\n\t\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\t\tLogicPage->Fill_Rect(x, y, x + width - 1, y + height - 1, scheme->Shadow);\n\t\t} else {\n\t\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t\t}\n\t\t}\n\n\t\tConquer_Clip_Text_Print(Description(), x, y, scheme, TBLACK, flags, width, _tabs);\n\t} else {\n\t\tConquer_Clip_Text_Print(Description(), x, y, (selected ? &ColorRemaps[PCOLOR_DIALOG_BLUE] : &ColorRemaps[PCOLOR_GREY]), TBLACK, flags, width, _tabs);\n\t}\n}\n\n\n/***********************************************************************************************\n * TEventClass::Reset -- Reset the trigger for a subsequent \"spring\".                          *\n *                                                                                             *\n *    This will reset the trigger event so that it may be \"sprung\" again. Typically, this      *\n *    occurs for persistent triggers.                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TEventClass::Reset(TDEventClass & td) const\n{\n\ttd.IsTripped = false;\n\tif (Event == TEVENT_TIME) {\n\t\ttd.Timer = Data.Value * (TICKS_PER_MINUTE/10);\n\t}\n}\n\n\n/***********************************************************************************************\n * TEventClass::operator () -- Action operator to see if event is satisfied.                   *\n *                                                                                             *\n *    This routine is called to see if the event has been satisfied. Typically, when the       *\n *    necessary trigger events have been satisfied, then the trigger is sprung. For some       *\n *    events, the act of calling this routine is tacit proof enough that the event has         *\n *    occurred. For most other events, the success condition must be explicitly checked.       *\n *                                                                                             *\n * INPUT:   event -- The event that has occurred according to the context from which this      *\n *                   routine was called. In the case of no specific event having occurred,     *\n *                   then TEVENT_ANY will be passed in.                                        *\n *                                                                                             *\n *          house -- The house that this event is tied to.                                     *\n *                                                                                             *\n *          object-- The object that this event might apply to. For object triggering          *\n *                   events, this will point to the perpetrator object.                        *\n *                                                                                             *\n *          forced-- If this event is forced by some outside action, this flag will be true.   *\n *                   Forcing only occurs as an explicit action from another trigger.           *\n *                                                                                             *\n * OUTPUT:  Was this event satisfied? A satisfied event will probably spring the trigger       *\n *          it is attached to.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TEventClass::operator () (TDEventClass & td, TEventType event, HousesType house, ObjectClass const * object, bool forced)\n{\n\t/*\n\t**\tIf this trigger event has been forced, then no further checks are required.\n\t**\tForce the trigger to be tripped.\n\t*/\n\tif (forced) {\n\t\ttd.IsTripped = true;\n\t}\n\n\tif (td.IsTripped) return(true);\n\n\t/*\n\t**\tTriggers based on the game's global environment such as time or\n\t**\tglobal flags are triggered only when the appropriate condition\n\t**\tis true.\n\t*/\n\tswitch (Event) {\n\t\tcase TEVENT_GLOBAL_SET:\n\t\t\tif (!Scen.GlobalFlags[Data.Value]) return(false);\n\t\t\treturn(true);\n\n\t\tcase TEVENT_GLOBAL_CLEAR:\n\t\t\tif (Scen.GlobalFlags[Data.Value]) return(false);\n\t\t\treturn(true);\n\n\t\tcase TEVENT_MISSION_TIMER_EXPIRED:\n//\t\t\tif (MissionSuspend == -1 || MissionTimer != 0) return(false);\n\t\t\tif (!Scen.MissionTimer.Is_Active() || Scen.MissionTimer != 0) return(false);\n\t\t\treturn(true);\n\n\t\tcase TEVENT_TIME:\n\t\t\tif (td.Timer != 0) return(false);\n\t\t\treturn(true);\n\t}\n\n\t/*\n\t**\tDon't trigger this event if the parameters mean nothing. Typical of\n\t**\tthis would be for events related to time or other outside influences.\n\t*/\n\tif (Event == TEVENT_NONE) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf this is not the event for this trigger, just return. This is only\n\t**\tnecessary to check for those trigger events that are presumed to be\n\t**\ttrue just by the fact that this routine is called with the appropriate\n\t**\tevent identifier.\n\t*/\n\tif (Event == TEVENT_ATTACKED ||\n\t\tEvent == TEVENT_DESTROYED ||\n\t\tEvent == TEVENT_DISCOVERED ||\n\t\tEvent == TEVENT_SPIED ||\n\t\tEvent == TEVENT_NONE ||\n\t\tEvent == TEVENT_CROSS_HORIZONTAL ||\n\t\tEvent == TEVENT_CROSS_VERTICAL ||\n\t\tEvent == TEVENT_ENTERS_ZONE ||\n\t\tEvent == TEVENT_PLAYER_ENTERED) {\n\n\t\tif (event != Event && event != TEVENT_ANY) {\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tThe cell entry trigger event is only tripped when an object of the\n\t**\tmatching ownership has entered the cell in question. All other\n\t**\tconditions will not trigger the event.\n\t*/\n\tif (Event == TEVENT_PLAYER_ENTERED || Event == TEVENT_CROSS_HORIZONTAL || Event == TEVENT_CROSS_VERTICAL || Event == TEVENT_ENTERS_ZONE) {\n\t\tif (!object || object->Owner() != Data.House) return(false);\n\t\ttd.IsTripped = true;\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tCheck for all bridges destroyed condition.\n\t*/\n\tif (Event == TEVENT_ALL_BRIDGES_DESTROYED) {\n\t\tif (Scen.BridgeCount) return(false);\n\t\ttd.IsTripped = true;\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tThe following trigger events are not considered to have sprung\n\t**\tmerely by fact that this routine has been called. These trigger\n\t**\tevents must be verified manually by examining the house that\n\t**\tthey are assigned to.\n\t*/\n\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\tint index;\n\tif (hptr != NULL) {\n\t\tswitch (Event) {\n\t\t\t/*\n\t\t\t**\tCheck to see if a team of the appropriate type has left the map.\n\t\t\t*/\n\t\t\tcase TEVENT_LEAVES_MAP:\n\t\t\t\tfor (index = 0; index < Teams.Count(); index++) {\n\t\t\t\t\tTeamClass * ptr = Teams.Ptr(index);\n\t\t\t\t\tif (ptr->Class == Team && ptr->Is_Empty() && ptr->IsLeaveMap) {\n//\t\t\t\t\tif (ptr->Class == Team && ptr->House == hptr && ptr->Is_Empty() && ptr->IsLeaveMap) {\n\t\t\t\t\t\ttd.IsTripped = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (index == Teams.Count()) return(false);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tCredits must be equal or greater to the value specified.\n\t\t\t*/\n\t\t\tcase TEVENT_CREDITS:\n\t\t\t\tif (hptr->Available_Money() < Data.Value) return(false);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tEnsure that there are no more factories left.\n\t\t\t*/\n\t\t\tcase TEVENT_NOFACTORIES:\n\t\t\t\tif (hptr->BScan & (STRUCTF_AIRSTRIP|STRUCTF_TENT|STRUCTF_WEAP|STRUCTF_BARRACKS|STRUCTF_CONST)) return(false);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tEnsure that there are no fake structures left.\n\t\t\t*/\n\t\t\tcase TEVENT_FAKES_DESTROYED:\n\t\t\t\tif (hptr->BScan & (STRUCTF_FAKECONST|STRUCTF_FAKEWEAP)) return(false);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tA civilian must have been evacuated.\n\t\t\t*/\n\t\t\tcase TEVENT_EVAC_CIVILIAN:\n\t\t\t\tif (!hptr->IsCivEvacuated) return(false);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tVerify that the structure has been built.\n\t\t\t*/\n\t\t\tcase TEVENT_BUILDING_EXISTS:\n\t\t\t\tif ((hptr->ActiveBScan & (1 << Data.Structure)) == 0) return(false);\n//\t\t\t\tif (hptr->Get_Quantity(Data.Structure) == 0) return(false);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tVerify that the structure has been built.\n\t\t\t*/\n\t\t\tcase TEVENT_BUILD:\n\t\t\t\tif (hptr->JustBuiltStructure != Data.Structure) return(false);\n\t\t\t\ttd.IsTripped = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tVerify that the unit has been built.\n\t\t\t*/\n\t\t\tcase TEVENT_BUILD_UNIT:\n\t\t\t\tif (hptr->JustBuiltUnit != Data.Unit) return(false);\n\t\t\t\ttd.IsTripped = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tVerify that the infantry has been built.\n\t\t\t*/\n\t\t\tcase TEVENT_BUILD_INFANTRY:\n\t\t\t\tif (hptr->JustBuiltInfantry != Data.Infantry) return(false);\n\t\t\t\ttd.IsTripped = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tVerify that the aircraft has been built.\n\t\t\t*/\n\t\t\tcase TEVENT_BUILD_AIRCRAFT:\n\t\t\t\tif (hptr->JustBuiltAircraft != Data.Aircraft) return(false);\n\t\t\t\ttd.IsTripped = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tVerify that the specified number of buildings have been destroyed.\n\t\t\t*/\n\t\t\tcase TEVENT_NBUILDINGS_DESTROYED:\n\t\t\t\tif (hptr->BuildingsLost < Data.Value) return(false);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tVerify that the specified number of units have been destroyed.\n\t\t\t*/\n\t\t\tcase TEVENT_NUNITS_DESTROYED:\n\t\t\t\tif (hptr->UnitsLost < Data.Value) return(false);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\thptr = HouseClass::As_Pointer(Data.House);\n\tif (hptr) {\n\t\tswitch (Event) {\n\t\t\tcase TEVENT_LOW_POWER:\n\t\t\t\tif (hptr->Power_Fraction() >= 1) return(false);\n\t\t\t\tbreak;\n\n//\t\t\tcase TEVENT_SPIED:\n//\t\t\t\tif (!hptr->IsSpied) return(false);\n//\t\t\t\tbreak;\n\n\t\t\tcase TEVENT_THIEVED:\n\t\t\t\tif (!hptr->IsThieved) return(false);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tVerify that the house has been discovered.\n\t\t\t*/\n\t\t\tcase TEVENT_HOUSE_DISCOVERED:\n\t\t\t\tif (!hptr->IsDiscovered) return(false);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tVerify that all buildings have been destroyed.\n\t\t\t*/\n\t\t\tcase TEVENT_BUILDINGS_DESTROYED:\n\t\t\t\tif (hptr->ActiveBScan) return(false);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tVerify that all units have been destroyed -- with some\n\t\t\t**\texceptions.\n\t\t\t*/\n\t\t\tcase TEVENT_UNITS_DESTROYED:\n\t\t\t\tif (hptr->ActiveUScan | hptr->ActiveIScan) return(false);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tVerify that all buildings and units have been destroyed.\n\t\t\t*/\n\t\t\tcase TEVENT_ALL_DESTROYED:\n\t\t\t\tif (hptr->ActiveBScan | hptr->ActiveUScan | hptr->ActiveIScan | hptr->ActiveVScan) return(false);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * TEventClass::Build_INI_Entry -- Builds the ini text for this event.                         *\n *                                                                                             *\n *    This routine will build the ini text for this trigger event. The ini text is appended    *\n *    to the string buffer specified. This routine is used to build the complete trigger       *\n *    ini text for writing out to the INI scenario file.                                       *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the string buffer that will hold the event INI data.           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TEventClass::Build_INI_Entry(char * ptr) const\n{\n\tsprintf(ptr, \"%d,%d,%d\", Event, TeamTypes.Logical_ID(Team), Data.Value);\n}\n\n\n/***********************************************************************************************\n * TEventClass::Read_INI -- Parses the INI text for this event's data.                         *\n *                                                                                             *\n *    This routine is used to parse the INI data line to fetch the event's data from it.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TEventClass::Read_INI(void)\n{\n\tchar const * token;\n\tswitch (NewINIFormat) {\n\t\tdefault:\n\t\t\tEvent = TEventType(atoi(strtok(NULL, \",\")));\n\t\t\tTeam.Set_Raw(atoi(strtok(NULL, \",\")));\n\t\t\tData.Value = atoi(strtok(NULL, \",\"));\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\ttoken = strtok(NULL, \",\");\n\t\t\tEvent = TEVENT_NONE;\n\t\t\tif (token) Event = TEventType(atoi(token));\n\n\t\t\ttoken = strtok(NULL, \",\");\n\t\t\tTeam = NULL;\n\t\t\tData.Value = -1;\n\t\t\tif (token) {\n\t\t\t\tif (Event_Needs(Event) == NEED_TEAM) {\n\t\t\t\t\tTeam = TeamTypes.Raw_Ptr(atoi(token));\n\t\t\t\t} else {\n\t\t\t\t\tData.Value = atoi(token);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 0:\n\t\t\tEvent = TEventType(atoi(strtok(NULL, \",\")));\n\n\t\t\tstrtok(NULL, \",\");\n\t\t\tstrtok(NULL, \",\");\n\n\t\t\tTeam = TeamTypeClass::From_Name(strtok(NULL, \",\"));\n\t\t\tData.Value = atoi(strtok(NULL, \",\"));\n\t\t\tstrtok(NULL, \",\");\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * Event_Needs -- Returns with what this event type needs for data.                            *\n *                                                                                             *\n *    This routine will examine the specified event type and return a code that indicates      *\n *    the type of data that must be supplied to this event. Some events require no data and    *\n *    these will return NEED_NONE.                                                             *\n *                                                                                             *\n * INPUT:   event -- The event type to examine.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the type of additional data that is needed by this event.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nNeedType Event_Needs(TEventType event)\n{\n\tswitch (event) {\n\t\tcase TEVENT_THIEVED:\n\t\tcase TEVENT_PLAYER_ENTERED:\n\t\tcase TEVENT_CROSS_HORIZONTAL:\n\t\tcase TEVENT_CROSS_VERTICAL:\n\t\tcase TEVENT_ENTERS_ZONE:\n\t\tcase TEVENT_HOUSE_DISCOVERED:\n\t\tcase TEVENT_BUILDINGS_DESTROYED:\n\t\tcase TEVENT_UNITS_DESTROYED:\n\t\tcase TEVENT_ALL_DESTROYED:\n\t\tcase TEVENT_LOW_POWER:\n\t\t\treturn(NEED_HOUSE);\n\n\t\tcase TEVENT_NUNITS_DESTROYED:\n\t\tcase TEVENT_NBUILDINGS_DESTROYED:\n\t\tcase TEVENT_CREDITS:\n\t\tcase TEVENT_TIME:\n\t\tcase TEVENT_GLOBAL_SET:\n\t\tcase TEVENT_GLOBAL_CLEAR:\n\t\t\treturn(NEED_NUMBER);\n\n\t\tcase TEVENT_BUILDING_EXISTS:\n\t\tcase TEVENT_BUILD:\n\t\t\treturn(NEED_STRUCTURE);\n\n\t\tcase TEVENT_BUILD_UNIT:\n\t\t\treturn(NEED_UNIT);\n\n\t\tcase TEVENT_BUILD_INFANTRY:\n\t\t\treturn(NEED_INFANTRY);\n\n\t\tcase TEVENT_BUILD_AIRCRAFT:\n\t\t\treturn(NEED_AIRCRAFT);\n\n\t\tcase TEVENT_LEAVES_MAP:\n\t\t\treturn(NEED_TEAM);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(NEED_NONE);\n}\n\n\n/***********************************************************************************************\n * Event_From_Name -- retrieves EventType for given name                                       *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      name      name to get event for                                                        *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      EventType for given name                                                               *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/29/1994 BR : Created.                                                                  *\n *=============================================================================================*/\nTEventType Event_From_Name (char const * name)\n{\n\tif (name) {\n\t\tfor (TEventType i = TEVENT_NONE; i < TEVENT_COUNT; i++) {\n\t\t\tif (!stricmp(name, EventText[i])) {\n\t\t\t\treturn(i);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(TEVENT_NONE);\n}\n\n\n/***********************************************************************************************\n * Name_From_Event -- retrieves name for EventType                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      event      EventType to get name for                                                   *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      name for EventType                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/29/1994 BR : Created.                                                                  *\n *=============================================================================================*/\nchar const * Name_From_Event(TEventType event)\n{\n\treturn(EventText[event]);\n}\n\n\n/***********************************************************************************************\n * Attaches_To -- Determines what event can be attached to.                                    *\n *                                                                                             *\n *    This routine is used to determine what this event type can be attached to in the game.   *\n *    Some events are specifically tied to cells or game object. This routine will indicate    *\n *    this requirement.                                                                        *\n *                                                                                             *\n * INPUT:   event -- The event type to examine.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the attachable characteristics for this event type. These             *\n *          characteristics are represented by a composite bit field. Some events can be       *\n *          attached to multiple objects.                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nAttachType Attaches_To(TEventType event)\n{\n\tAttachType attach = ATTACH_NONE;\n\n\tswitch (event) {\n\t\tcase TEVENT_CROSS_HORIZONTAL:\n\t\tcase TEVENT_CROSS_VERTICAL:\n\t\tcase TEVENT_ENTERS_ZONE:\n\t\tcase TEVENT_PLAYER_ENTERED:\n\t\tcase TEVENT_ANY:\n\t\tcase TEVENT_DISCOVERED:\n\t\tcase TEVENT_NONE:\n\t\t\tattach = attach | ATTACH_CELL;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tswitch (event) {\n\t\tcase TEVENT_SPIED:\n\t\tcase TEVENT_PLAYER_ENTERED:\n\t\tcase TEVENT_DISCOVERED:\n\t\tcase TEVENT_DESTROYED:\n\t\tcase TEVENT_ATTACKED:\n\t\tcase TEVENT_ANY:\n\t\tcase TEVENT_NONE:\n\t\t\tattach = attach | ATTACH_OBJECT;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tswitch (event) {\n//\t\tcase TEVENT_CROSS_HORIZONTAL:\n//\t\tcase TEVENT_CROSS_VERTICAL:\n\t\tcase TEVENT_ENTERS_ZONE:\n\t\tcase TEVENT_ANY:\n\t\t\tattach = attach | ATTACH_MAP;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tswitch (event) {\n\t\tcase TEVENT_LOW_POWER:\n\t\tcase TEVENT_EVAC_CIVILIAN:\n\t\tcase TEVENT_BUILDING_EXISTS:\n\t\tcase TEVENT_BUILD:\n\t\tcase TEVENT_BUILD_UNIT:\n\t\tcase TEVENT_BUILD_INFANTRY:\n\t\tcase TEVENT_BUILD_AIRCRAFT:\n\t\tcase TEVENT_NOFACTORIES:\n\t\tcase TEVENT_BUILDINGS_DESTROYED:\n\t\tcase TEVENT_NBUILDINGS_DESTROYED:\n\t\tcase TEVENT_UNITS_DESTROYED:\n\t\tcase TEVENT_NUNITS_DESTROYED:\n\t\tcase TEVENT_ALL_DESTROYED:\n\t\tcase TEVENT_HOUSE_DISCOVERED:\n\t\tcase TEVENT_CREDITS:\n//\t\tcase TEVENT_ATTACKED:\n\t\tcase TEVENT_THIEVED:\n\t\tcase TEVENT_ANY:\n\t\tcase TEVENT_FAKES_DESTROYED:\n\t\t\tattach = attach | ATTACH_HOUSE;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tswitch (event) {\n\t\tcase TEVENT_TIME:\n\t\tcase TEVENT_GLOBAL_SET:\n\t\tcase TEVENT_GLOBAL_CLEAR:\n\t\tcase TEVENT_MISSION_TIMER_EXPIRED:\n\t\tcase TEVENT_ANY:\n\t\tcase TEVENT_ALL_BRIDGES_DESTROYED:\n\t\tcase TEVENT_LEAVES_MAP:\n\t\t\tattach = attach | ATTACH_GENERAL;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\treturn(attach);\n}\n"
  },
  {
    "path": "CODE/TEVENT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TEVENT.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TEVENT.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/28/95                                                     *\n *                                                                                             *\n *                  Last Update : November 28, 1995 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef TEVENT_H\n#define TEVENT_H\n\n/*\n**\tThese are the trigger events that are checked for and if qualified, they will signal\n**\ta successful trigger event. This might result in the trigger action being performed.\n*/\ntypedef enum TEventType {\n\tTEVENT_NONE,\n\tTEVENT_PLAYER_ENTERED,\t\t\t\t\t// player enters this square\n\tTEVENT_SPIED,\t\t\t\t\t\t\t\t// Spied by.\n\tTEVENT_THIEVED,\t\t\t\t\t\t\t// Thieved by (raided or stolen vehicle).\n\tTEVENT_DISCOVERED,\t\t\t\t\t\t// player discovers this object\n\tTEVENT_HOUSE_DISCOVERED,\t\t\t\t// House has been discovered.\n\tTEVENT_ATTACKED,\t\t\t\t\t\t\t// player attacks this object\n\tTEVENT_DESTROYED,\t\t\t\t\t\t\t// player destroys this object\n\tTEVENT_ANY,\t\t\t\t\t\t\t\t\t// Any object event will cause the trigger.\n\tTEVENT_UNITS_DESTROYED,\t\t\t\t\t// all house's units destroyed\n\tTEVENT_BUILDINGS_DESTROYED,\t\t\t// all house's buildings destroyed\n\tTEVENT_ALL_DESTROYED,\t\t\t\t\t// all house's units & buildings destroyed\n\tTEVENT_CREDITS,\t\t\t\t\t\t\t// house reaches this many credits\n\tTEVENT_TIME,\t\t\t\t\t\t\t\t// Scenario elapsed time from start.\n\tTEVENT_MISSION_TIMER_EXPIRED,\t\t\t// Pre expired mission timer.\n\tTEVENT_NBUILDINGS_DESTROYED,\t\t\t// Number of buildings destroyed.\n\tTEVENT_NUNITS_DESTROYED,\t\t\t\t// Number of units destroyed.\n\tTEVENT_NOFACTORIES,\t\t\t\t\t\t// No factories left.\n\tTEVENT_EVAC_CIVILIAN,\t\t\t\t\t// Civilian has been evacuated.\n\tTEVENT_BUILD,\t\t\t\t\t\t\t\t// Specified building has been built.\n\tTEVENT_BUILD_UNIT,\t\t\t\t\t\t// Specified unit has been built.\n\tTEVENT_BUILD_INFANTRY,\t\t\t\t\t// Specified infantry has been built.\n\tTEVENT_BUILD_AIRCRAFT,\t\t\t\t\t// Specified aircraft has been built.\n\tTEVENT_LEAVES_MAP,\t\t\t\t\t\t// Specified team member leaves map.\n\tTEVENT_ENTERS_ZONE,\t\t\t\t\t\t// Enters same zone as waypoint 'x'.\n\tTEVENT_CROSS_HORIZONTAL,\t\t\t\t// Crosses horizontal trigger line.\n\tTEVENT_CROSS_VERTICAL,\t\t\t\t\t// Crosses vertical trigger line.\n\tTEVENT_GLOBAL_SET,\t\t\t\t\t\t// If specified global has been set.\n\tTEVENT_GLOBAL_CLEAR,\t\t\t\t\t\t// If specified global has been cleared.\n\tTEVENT_FAKES_DESTROYED,\t\t\t\t\t// If all fake structures are gone.\n\tTEVENT_LOW_POWER,\t\t\t\t\t\t\t// When power drops below 100%.\n\tTEVENT_ALL_BRIDGES_DESTROYED,\t\t\t// All bridges destroyed.\n\tTEVENT_BUILDING_EXISTS,\t\t\t\t\t// Check for building existing.\n\n\tTEVENT_COUNT,\n\tTEVENT_FIRST=0\n} TEventType;\n\nTEventType Event_From_Name(char const * name);\nNeedType Event_Needs(TEventType event);\nchar const * Name_From_Event(TEventType event);\n\n/*\n**\tThis holds the changable data that is associated with an event as\n**\tit relates to a trigger.\n*/\nstruct TDEventClass {\n\t/*\n\t**\tIf this event has been triggered by something that is temporal, then\n\t**\tthis flag will be set to true so that subsequent trigger examination\n\t**\twill return a successful event trigger flag. Typical use of this is\n\t**\tfor when objects of a specific type are built.\n\t*/\n\tunsigned IsTripped:1;\n\n\t/*\n\t**\tTimer based events require a special timer control handler.\n\t*/\n\tCDTimerClass<FrameTimerClass> Timer;\n\n\tTDEventClass(void) : IsTripped(false), Timer(0) {};\n\tTDEventClass(NoInitClass const & x) : Timer(x) {};\n};\n\n\n/*\n**\tThis elaborates the information necessary to trigger\n**\tan event.\n*/\nclass TeamTypeClass;\nstruct TEventClass {\n\n\t/*\n\t**\tThis is the event that will controls how this event gets triggered.\n\t*/\n\tTEventType Event;\n\n\t/*\n\t**\tIf this event needs to reference a team type, then this is the pointer\n\t**\tto the team type object. This must be separated from the following\n\t**\tunion because Watcom compiler won't allow a class that has a\n\t**\tconstructor to be declared in a union.\n\t*/\n\tCCPtr<TeamTypeClass> Team;\n\n\tunion {\n\t\tStructType\t\t\t\tStructure;\t// Used for structure type checking.\n\t\tUnitType\t\t\t\t\tUnit;\t\t\t// Used for unit type checking.\n\t\tInfantryType\t\t\tInfantry;\t//\tUsed for infantry type checking.\n\t\tAircraftType\t\t\tAircraft;\t// Used for aircraft type checking.\n\t\tHousesType\t\t\t\tHouse;\t\t// Used for house specific events.\n\t\tlong\tValue;\t\t\t\t\t\t\t// Used for other events that need data.\n\t} Data;\n\n\tTEventClass(void) : Event(TEVENT_NONE) {Data.Value = 0;};\n\tTEventClass(TEventType event) : Event(event) {Data.Value = 0;};\n\tTEventClass(NoInitClass const & x) : Team(x) {};\n\n\tvoid Code_Pointers(void);\n\tvoid Decode_Pointers(void);\n\tvoid Reset(TDEventClass & td) const;\n\tbool operator () (TDEventClass & td, TEventType event, HousesType house, ObjectClass const * object, bool forced);\n\tvoid Read_INI(void);\n\tvoid Build_INI_Entry(char * buffer) const;\n};\n\n\ntypedef enum AttachType {\n\tATTACH_NONE=0x00,\t\t\t\t// Trigger doesn't attach to anything (orphan trigger types).\n\tATTACH_CELL=0x01,\t\t\t\t// Trigger can only attach to a cell.\n\tATTACH_OBJECT=0x02,\t\t\t// Trigger can attach only to object (usually building or vehicle).\n\tATTACH_MAP=0x04,\t\t\t\t// Trigger applies to the general map (usually zone or parallel triggers).\n\tATTACH_HOUSE=0x08,\t\t\t// Trigger applies only to a house.\n\tATTACH_GENERAL=0x10,\t\t\t// General purpose trigger attached to game state.\n\tATTACH_TEAM=0x20\t\t\t\t// Trigger applies to team object.\n} AttachType;\n\nAttachType Attaches_To(TEventType event);\n\n\n\nclass EventChoiceClass {\n\tpublic:\n\t\tEventChoiceClass(TEventType event=TEVENT_NONE) : Event(event) {}\n\n\t\toperator TEventType (void) const {return(Event);}\n\t\tbool operator == (EventChoiceClass const & rvalue) const {return(Event == rvalue.Event);}\n\t\tbool operator != (EventChoiceClass const & rvalue) const {return(Event != rvalue.Event);}\n\t\tbool operator > (EventChoiceClass const & rvalue) const {return(stricmp(Description(), rvalue.Description()) > 0);}\n\t\tbool operator < (EventChoiceClass const & rvalue) const {return(stricmp(Description(), rvalue.Description()) < 0);}\n\t\tbool operator <= (EventChoiceClass const & rvalue) const {return(Event == rvalue.Event || stricmp(Description(), rvalue.Description()) < 0);}\n\t\tbool operator >= (EventChoiceClass const & rvalue) const {return(Event == rvalue.Event || stricmp(Description(), rvalue.Description()) > 0);}\n\t\tchar const * Description(void) const {return(Name_From_Event(Event));}\n\t\tvoid Draw_It(int index, int x, int y, int width, int height, bool selected, TextPrintType flags) const;\n\n\t\tTEventType Event;\n};\n\nextern EventChoiceClass EventChoices[TEVENT_COUNT];\n\n\n#endif\n"
  },
  {
    "path": "CODE/TEXTBTN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TEXTBTN.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TEXTBTN.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 19, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   TextButtonClass::Draw_Background -- Draws the background to the text button.              *\n *   TextButtonClass::Draw_Me -- Draws the text buttons as indicated.                          *\n *   TextButtonClass::Draw_Text -- This draws the text for the text button.                    *\n *   TextButtonClass::Set_Text -- Assigns a new text string to this button.                    *\n *   TextButtonClass::Set_Text -- Sets the text for this text button.                          *\n *   TextButtonClass::TextButtonClass -- Normal constructor for a text button.                 *\n *   TextButtonClass::TextButtonClass -- Normal constructor for a text button.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include \"textbtn.h\"\n\n\n/***********************************************************************************************\n * TextButtonClass::TextButtonClass -- Normal constructor for a text button.                   *\n *                                                                                             *\n *    This is the constructor for text buttons if the text is provided as a string pointer.    *\n *                                                                                             *\n * INPUT:   id    -- The ID number to assign to this button.                                   *\n *                                                                                             *\n *          text  -- Pointer to the text string to display on top of the button.               *\n *                                                                                             *\n *          x,y   -- Pixel coordinate of button's upper left corner.                           *\n *                                                                                             *\n *          w,h   -- Dimensions of the button. If these are not filled in (or with -1), then   *\n *                   the dimensions are adapted to fit the text assigned to the button.        *\n *                                                                                             *\n *          style -- The print style for the text in the button. These are the TPF_ flags      *\n *                   used by Fancy_Text_Print().                                               *\n *                                                                                             *\n *          border-- If the button is to be surrounded by a black border, then this flag       *\n *                   should be set to true.                                                    *\n *                                                                                             *\n * OUTPUT:   none                                                                              *\n *                                                                                             *\n * WARNINGS: Call Set_Text & Set_Style, & init X,Y,Width,Height,ID before using this button.\t  *\n *                                                                                             *\n * HISTORY:  01/15/1995 JLB : Created.                                                         *\n *=============================================================================================*/\nTextButtonClass::TextButtonClass(unsigned id, char const * text, TextPrintType style, int x, int y, int w, int h, int blackborder) :\n\tToggleClass(id, x, y, w, h),\n\tString(text)\n{\n\tPrintFlags = style;\n\tIsBlackBorder = blackborder;\n\n\tif (w == -1 || h == -1) {\n\t\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, PrintFlags);\n\t\tif (w == -1) {\n\t\t\tWidth = String_Pixel_Width(String)+8;\n\t\t}\n\t\tif (h == -1) {\n\t\t\tHeight = FontHeight + FontYSpacing + 2;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TextButtonClass::TextButtonClass -- Default constructor for a text button.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:   none                                                                              *\n *                                                                                             *\n * WARNINGS: none                                                                              *\n *                                                                                             *\n * HISTORY:  01/15/1995 JLB : Created.                                                         *\n *=============================================================================================*/\nTextButtonClass::TextButtonClass(void) :\n\tToggleClass(0, 0, 0, 0, 0)\n{\n\tIsBlackBorder = false;\n\tString = NULL;\n\tPrintFlags = TPF_8POINT;\n}\n\n\n/***********************************************************************************************\n * TextButtonClass::TextButtonClass -- Normal constructor for a text button.                   *\n *                                                                                             *\n *    This is the constructor for text buttons if the text is provided as a string pointer.    *\n *                                                                                             *\n * INPUT:   id    -- The ID number to assign to this button.                                   *\n *                                                                                             *\n *          text  -- The text number to use for displaying on top of the button.               *\n *                                                                                             *\n *          x,y   -- Pixel coordinate of button's upper left corner.                           *\n *                                                                                             *\n *          w,h   -- Dimensions of the button. If these are not filled in (or with -1), then   *\n *                   the dimensions are adapted to fit the text assigned to the button.        *\n *                                                                                             *\n *                                                                                             *\n *          style -- The print style for the text in the button. These are the TPF_ flags      *\n *                   used by Fancy_Text_Print().                                               *\n *                                                                                             *\n *          border-- If the button is to be surrounded by a black border, then this flag       *\n *                   should be set to true.                                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTextButtonClass::TextButtonClass (unsigned id, int text, TextPrintType style, int x, int y, int w, int h, int blackborder) :\n\tToggleClass (id, x, y, w, h),\n\tString(0)\n{\n\tPrintFlags = style;\n\tIsBlackBorder = blackborder;\n\tSet_Text(text);\n\n\tif (w == -1 || h == -1) {\n\t\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, PrintFlags);\n\t\tif (w == -1) {\n\t\t\tWidth = String_Pixel_Width(String)+8;\n\t\t}\n\t\tif (h == -1) {\n\t\t\tHeight = FontHeight + FontYSpacing + 2;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TextButtonClass::Draw_Me -- Draws the text buttons as indicated.                            *\n *                                                                                             *\n *    This routine will draw the text button.                                                  *\n *                                                                                             *\n * INPUT:   forced   -- If the button is to be redrawn regardless of the state of the redraw   *\n *                      flag, then this parameter will be true.                                *\n *                                                                                             *\n * OUTPUT:  bool; Was the button redrawn?                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/03/1995 MML : Created.                                                                 *\n *   01/16/1995 JLB : Modified                                                                 *\n *=============================================================================================*/\nint TextButtonClass::Draw_Me(int forced)\n{\n\tif (ControlClass::Draw_Me(forced)) {\n\t\t/*\n\t\t**\tHide the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Hide_Mouse(X, Y, X+Width-1, Y+Height-1);\n\t\t}\n\n\t\t/*\n\t\t**\tDraw the background and overlaying text. These are virtual function\n\t\t**\tcalls so that they may be overridden.\n\t\t*/\n\t\tDraw_Background();\n\t\tDraw_Text(String);\n\n\t\t/*\n\t\t**\tDisplay the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Show_Mouse();\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TextButtonClass::Set_Text -- Assigns a new text string to this button.                      *\n *                                                                                             *\n *    Use this routine to assign a new text string to this button. By using this function it   *\n *    is possible to dynamically change the button's text. An example of this would be an      *\n *    on/off button that every time it is clicked, the text toggles between \"on\" and \"off\".    *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text string to assign to this button.                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The text is NOT copied to this button. You must make sure that the text         *\n *             remains valid throughout the lifetime of this text button.                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TextButtonClass::Set_Text(char const * text, bool resize)\n{\n\tString = text;\n\tFlag_To_Redraw();\n\tif (resize && String) {\n\t\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, PrintFlags);\n\t\tWidth = String_Pixel_Width(String)+8;\n\t\tHeight = FontHeight + FontYSpacing + 2;\n\t}\n}\n\n\n/***********************************************************************************************\n * TextButtonClass::Set_Text -- Sets the text for this text button.                            *\n *                                                                                             *\n *    This will set the text for this button. The text is provided as a text number. This      *\n *    number is automatically converted to the appropriate text string before being stored     *\n *    in the button's structure.                                                               *\n *                                                                                             *\n * INPUT:   text  -- The text number to assign to this button.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The text number information is lost when it is assigned to the button. Once     *\n *             the assignment takes place, the text number is NOT remembered by the button.    *\n *             Only the associated text string is.                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TextButtonClass::Set_Text(int text, bool resize)\n{\n\tif (text != TXT_NONE) {\n\t\tSet_Text(Text_String(text), resize);\n\t}\n}\n\n\n/***********************************************************************************************\n * TextButtonClass::Draw_Background -- Draws the background to the text button.                *\n *                                                                                             *\n *    This localizes the drawing of the background for the text button. By overriding this     *\n *    function you can give a different background to the button. The text is drawn using      *\n *    a different routine. The mouse is hidden, if necessary, before this routine is called.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TextButtonClass::Draw_Background(void)\n{\n\t/*\n\t**\tDraw a border if selected style.\n\t*/\n\tif (IsBlackBorder) {\n\t\tLogicPage->Draw_Rect (X-1, Y-1, X+Width+2, Y+Height+2, BLACK);\n\t}\n\n\t/*\n\t**\tDraw the body & set text color.\n\t*/\n\tBoxStyleEnum style;\n\n\tif (IsDisabled) {\n#ifdef WOLAPI_INTEGRATION\n\t\tstyle = BOXSTYLE_BOX;\n#else\n\t\tstyle = BOXSTYLE_DIS_RAISED;\n#endif\n\t} else {\n\t\tif (IsPressed) {\n\t\t\tstyle = BOXSTYLE_DOWN;\n\t\t} else {\n\t\t\tstyle = BOXSTYLE_RAISED;\n\t\t}\n\t}\n\n\tDraw_Box(X, Y, Width, Height, style, true);\n}\n\n\n/***********************************************************************************************\n * TextButtonClass::Draw_Text -- This draws the text for the text button.                      *\n *                                                                                             *\n *    This routine draws the text for the text button. You can override this routine if you    *\n *    wish different text rendering styles or colors. The background has already been drawn    *\n *    by the time this function is called. The mouse is hidden, if necessary, as well.         *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text string to print over the button.                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TextButtonClass::Draw_Text(char const * text)\n{\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t**\tDisplay the text.\n\t*/\n\tif (String) {\n\t\tTextPrintType flags;\n\n\t\tif (IsDisabled) {\n\t\t\tflags = (TextPrintType)0;\n\t\t} else {\n\t\t\tif (IsPressed || IsOn) {\n\t\t\t\tflags = TPF_USE_GRAD_PAL|TPF_BRIGHT_COLOR;\n\t\t\t} else {\n\t\t\t\tflags = TPF_USE_GRAD_PAL|TPF_MEDIUM_COLOR;\n\t\t\t}\n\t\t}\n\n\t\tFancy_Text_Print(text, X+(Width>>1)-1, Y+1, scheme, TBLACK, PrintFlags|flags|TPF_CENTER);\n\t}\n}\n"
  },
  {
    "path": "CODE/TEXTBTN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TEXTBTN.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TEXTBTN.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TEXTBTN_H\n#define TEXTBTN_H\n\n#include\t\"toggle.h\"\n\n\nclass TextButtonClass : public ToggleClass\n{\n\tpublic:\n\t\tTextButtonClass(void);\n\t\tTextButtonClass(unsigned id, char const * text, TextPrintType style, int x, int y, int w=-1, int h=-1, int blackborder=false);\n\t\tTextButtonClass(unsigned id, int text, TextPrintType style, int x, int y, int w=-1, int h=-1, int blackborder=false);\n\t\tvirtual int Draw_Me(int forced=false);\n\t\tvirtual void Set_Text(char const *text, bool resize = false);\n\t\tvirtual void Set_Text(int text, bool resize = false);\n\t\tvirtual void Set_Style (TextPrintType style) {PrintFlags = style;}\n\n\tprotected:\n\n\t\tvirtual void Draw_Background(void);\n\t\tvirtual void Draw_Text(char const * text);\n\n\t\tunsigned IsBlackBorder:1;\n\n\t\t/*\n\t\t**\tThis points to a constant string that is used for the button's text.\n\t\t*/\n\t\tchar const * String;\n\n\t\t/*\n\t\t**\tThis is the print flags to use when rendering this button's text.\n\t\t*/\n\t\tTextPrintType PrintFlags;\n};\n\n#endif\n\n"
  },
  {
    "path": "CODE/THEME.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/THEME.CPP 3     3/11/97 4:03p Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : THEME.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 14, 1994                                              *\n *                                                                                             *\n *                  Last Update : August 12, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ThemeClass::AI -- Process the theme engine and restart songs.                             *\n *   ThemeClass::Base_Name -- Fetches the base filename for the theme specified.               *\n *   ThemeClass::From_Name -- Determines theme number from specified name.                     *\n *   ThemeClass::Full_Name -- Retrieves the full score name.                                   *\n *   ThemeClass::Is_Allowed -- Checks to see if the specified theme is legal.                  *\n *   ThemeClass::Next_Song -- Calculates the next song number to play.                         *\n *   ThemeClass::Play_Song -- Starts the specified song play NOW.                              *\n *   ThemeClass::Queue_Song -- Queues the song to the play queue.                              *\n *   ThemeClass::Scan -- Scans all scores for availability.                                    *\n *   ThemeClass::Set_Theme_Data -- Set the theme data for scenario and owner.                  *\n *   ThemeClass::Still_Playing -- Determines if music is still playing.                        *\n *   ThemeClass::Stop -- Stops the current theme from playing.                                 *\n *   ThemeClass::ThemeClass -- Default constructor for the theme manager class.                *\n *   ThemeClass::Theme_File_Name -- Constructs a filename for the specified theme.             *\n *   ThemeClass::Track_Length -- Calculates the length of the song (in seconds).               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"theme.h\"\n\n#ifndef WIN32\nextern short StreamLowImpact;\n#endif  //WIN32\n\n/*\n**\tThese are the actual filename list for the theme sample files.\n*/\nThemeClass::ThemeControl ThemeClass::_themes[THEME_COUNT] = {\n\t{\"BIGF226M\",\tTXT_THEME_BIGF,\t\t0,\t\t307,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES},\n\t{\"CRUS226M\",\tTXT_THEME_CRUS,\t\t0,\t\t222,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_SOVIET},\n\t{\"FAC1226M\",\tTXT_THEME_FAC1,\t\t0,\t\t271,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES},\n\t{\"FAC2226M\",\tTXT_THEME_FAC2,\t\t0,\t\t328,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_SOVIET},\n\t{\"HELL226M\",\tTXT_THEME_HELL,\t\t0,\t\t375,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES},\n\t{\"RUN1226M\",\tTXT_THEME_RUN1,\t\t0,\t\t312,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_SOVIET},\n\t{\"SMSH226M\",\tTXT_THEME_SMSH,\t\t0,\t\t272,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES},\n\t{\"TREN226M\",\tTXT_THEME_TREN,\t\t0,\t\t312,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_SOVIET},\n\t{\"WORK226M\",\tTXT_THEME_WORK,\t\t0,\t\t277,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES},\n\t{\"AWAIT\",\t\tTXT_THEME_AWAIT,\t\t0,\t\t259,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES},\n\t{\"DENSE_R\",\t\tTXT_THEME_DENSE_R,\t0,\t\t294,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES},\n\t{\"FOGGER1A\",\tTXT_THEME_FOGGER1A,\t0,\t\t297,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES},\n\t{\"MUD1A\",\t\tTXT_THEME_MUD1A,\t\t0,\t\t280,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES},\n\t{\"RADIO2\",\t\tTXT_THEME_RADIO2,\t\t0,\t\t237,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES},\n\t{\"ROLLOUT\",\t\tTXT_THEME_ROLLOUT,\t0,\t\t227,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES},\n\t{\"SNAKE\",\t\tTXT_THEME_SNAKE,\t\t0,\t\t277,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES},\n\t{\"TERMINAT\",\tTXT_THEME_TERMINAT,\t0,\t\t310,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES},\n\t{\"TWIN\",\t\t\tTXT_THEME_TWIN,\t\t0,\t\t229,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES},\n\t{\"VECTOR1A\",\tTXT_THEME_VECTOR1A,\t0,\t\t252,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES},\n  \t{\"MAP\",\t\t\tTXT_THEME_MAP,\t\t\t0,\t\t63,\tfalse,\ttrue,\t\ttrue,\tHOUSEF_NONE},\n\t{\"SCORE\",\t\tTXT_THEME_SCORE,\t\t0,\t\t106,\tfalse,\ttrue,\t\ttrue,\tHOUSEF_NONE},\n\t{\"INTRO\",\t\tTXT_THEME_INTRO,\t\t0,\t\t205,\tfalse,\ttrue,\t\ttrue,\tHOUSEF_NONE},\n\t{\"CREDITS\",\t\tTXT_THEME_CREDITS,\t0,\t\t163,\tfalse,\ttrue,\t\ttrue,\tHOUSEF_NONE},\n\n\t{\"2ND_HAND\",\tTXT_THEME_2ND_HAND,\t0,\t\t268,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES|HOUSEF_SPAIN},\n\t{\"ARAZOID\",\t\tTXT_THEME_ARAZOID,\t0,\t\t257,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_SOVIET|HOUSEF_SPAIN},\n\t{\"BACKSTAB\",\tTXT_THEME_BACKSTAB,\t0,\t\t278,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES|HOUSEF_SPAIN},\n\t{\"CHAOS2\",\t\tTXT_THEME_CHAOS2,\t\t0,\t\t250,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_SOVIET|HOUSEF_SPAIN},\n\t{\"SHUT_IT\",\t\tTXT_THEME_SHUT_IT,\t0,\t\t261,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES|HOUSEF_SPAIN},\n\t{\"TWINMIX1\",\tTXT_THEME_TWINMIX1,\t0,\t\t222,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_SOVIET|HOUSEF_SPAIN},\n\t{\"UNDER3\",\t\tTXT_THEME_UNDER3,\t\t0,\t\t246,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES|HOUSEF_SPAIN},\n\t{\"VR2\",\t\t\tTXT_THEME_VR2,\t\t\t0,\t\t255,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_SOVIET|HOUSEF_SPAIN},\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t{\"BOG\",\t\t\tTXT_THEME_BOG,\t\t\t0,\t\t212,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES|HOUSEF_SPAIN},\n\t{\"FLOAT_V2\",\tTXT_THEME_FLOAT_V2,\t0,\t\t274,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_SOVIET|HOUSEF_SPAIN},\n\t{\"GLOOM\",\t\tTXT_THEME_GLOOM,\t\t0,\t\t236,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES|HOUSEF_SPAIN},\n\t{\"GRNDWIRE\",\tTXT_THEME_GRNDWIRE,\t0,\t\t228,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_SOVIET|HOUSEF_SPAIN},\n\t{\"RPT\",\t\t\tTXT_THEME_RPT,\t\t\t0,\t\t275,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES|HOUSEF_SPAIN},\n\t{\"SEARCH\",\t\tTXT_THEME_SEARCH,\t\t0,\t\t276,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_SOVIET|HOUSEF_SPAIN},\n\t{\"TRACTION\",\tTXT_THEME_TRACTION,\t0,\t\t237,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_ALLIES|HOUSEF_SPAIN},\n\t{\"WASTELND\",\tTXT_THEME_WASTELND,\t0,\t\t242,\ttrue,\t\tfalse,\ttrue,\tHOUSEF_SOVIET|HOUSEF_SPAIN},\n#endif\n};\n\n\n/***********************************************************************************************\n * ThemeClass::Base_Name -- Fetches the base filename for the theme specified.                 *\n *                                                                                             *\n *    This routine is used to retrieve a pointer to the base filename for the theme            *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   theme -- The theme number to convert into a base filename.                         *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the base filename for the theme specified. If the        *\n *          theme number is invalid, then a pointer to \"No Theme\" is returned instead.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * ThemeClass::Base_Name(ThemeType theme) const\n{\n\tif (theme != THEME_NONE) {\n\t\treturn(_themes[theme].Name);\n\t}\n\treturn(\"No theme\");\n}\n\n\n/***********************************************************************************************\n * ThemeClass::ThemeClass -- Default constructor for the theme manager class.                  *\n *                                                                                             *\n *    This is the default constructor for the theme class object.                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nThemeClass::ThemeClass(void) :\n\tCurrent(-1),\n\tScore(THEME_NONE),\n\tPending(THEME_NONE)\n{\n}\n\n\n/***********************************************************************************************\n * ThemeClass::Full_Name -- Retrieves the full score name.                                     *\n *                                                                                             *\n *    This routine will fetch and return with a pointer to the full name of the theme          *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   theme -- The theme to fetch the full name for.                                     *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the full name for this score. This pointer may point to  *\n *          EMS memory.                                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * ThemeClass::Full_Name(ThemeType theme) const\n{\n\tif (theme >= THEME_FIRST && theme < THEME_COUNT) {\n\t\treturn(Text_String(_themes[theme].Fullname));\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * ThemeClass::AI -- Process the theme engine and restart songs.                               *\n *                                                                                             *\n *    This is a maintenance function that will restart an appropriate theme if the current one *\n *    has finished. This routine should be called frequently.                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *   01/23/1995 JLB : Picks new song just as it is about to play it.                           *\n *=============================================================================================*/\nvoid ThemeClass::AI(void)\n{\n\tif (SampleType && !Debug_Quiet) {\n\t\tif (ScoresPresent && Options.ScoreVolume != 0 && !Still_Playing() && Pending != THEME_NONE) {\n\n\t\t\t/*\n\t\t\t**\tIf the pending song needs to be picked, then pick it now.\n\t\t\t*/\n\t\t\tif (Pending == THEME_PICK_ANOTHER) {\n\t\t\t\tPending = Next_Song(Score);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tStart the song playing and then flag it so that a new song will\n\t\t\t**\tbe picked when this one ends.\n\t\t\t*/\n\t\t\tPlay_Song(Pending);\n\t\t\tPending = THEME_PICK_ANOTHER;\n\t\t}\n\t\tSound_Callback();\n\t}\n}\n\n\n/***********************************************************************************************\n * ThemeClass::Next_Song -- Calculates the next song number to play.                           *\n *                                                                                             *\n *    use this routine to figure out what song number to play. It examines the option settings *\n *    for repeat and shuffle so that it can return the correct value.                          *\n *                                                                                             *\n * INPUT:   theme -- The origin (last) index. The new value is related to this for all but     *\n *                   the shuffling method of play.                                             *\n *                                                                                             *\n * OUTPUT:  Returns with the song number for the next song to play.                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *   01/19/1995 JLB : Will not play the same song twice when in shuffle mode.                  *\n *=============================================================================================*/\nThemeType ThemeClass::Next_Song(ThemeType theme) const\n{\n\tif (theme == THEME_NONE || theme == THEME_PICK_ANOTHER || (theme != THEME_QUIET && !_themes[theme].Repeat && !Options.IsScoreRepeat)) {\n\t\tif (Options.IsScoreShuffle) {\n\n\t\t\t/*\n\t\t\t**\tShuffle the theme, but never pick the same theme that was just\n\t\t\t**\tplaying.\n\t\t\t*/\n\t\t\tThemeType newtheme;\n\t\t\tdo {\n\t\t\t\tnewtheme = Sim_Random_Pick(THEME_FIRST, THEME_LAST);\n\t\t\t} while (newtheme == theme || !Is_Allowed(newtheme));\n\t\t\ttheme = newtheme;\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tSequential score playing.\n\t\t\t*/\n\t\t\tdo {\n\t\t\t\ttheme++;\n\t\t\t\tif (theme > THEME_LAST) {\n\t\t\t\t\ttheme = THEME_FIRST;\n\t\t\t\t}\n\t\t\t} while (!Is_Allowed(theme));\n\t\t}\n\t}\n\treturn(theme);\n}\n\n\n/***********************************************************************************************\n * ThemeClass::Queue_Song -- Queues the song to the play queue.                                *\n *                                                                                             *\n *    This routine will cause the current song to fade and the specified song to start. This   *\n *    is the normal and friendly method of changing the current song.                          *\n *                                                                                             *\n * INPUT:   theme -- The song to start playing. If -1 is passed in, then just the current song.*\n *                   is faded.                                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ThemeClass::Queue_Song(ThemeType theme)\n{\n\t/*\n\t**\tIf there is no score file present, then abort.\n\t*/\n\tif (!ScoresPresent) return;\n\n\t/*\n\t**\tIf there is no sound driver or sounds have been specifically\n\t**\tturned off, then abort.\n\t*/\n\tif (SampleType == 0 || Debug_Quiet) return;\n\n\t/*\n\t**\tIf the current score volumne is set to silent, then there is no need to play the\n\t**\tspecified theme.\n\t*/\n\tif (Options.ScoreVolume == 0) return;\n\n\t/*\n\t**\tIf the pending theme is available to be set and the specified theme is valid, then\n\t**\tset the queued theme accordingly.\n\t*/\n\tif (Pending == THEME_NONE || Pending == THEME_PICK_ANOTHER || theme == THEME_NONE || theme == THEME_QUIET) {\n\t\tPending = theme;\n\t\tif (Still_Playing()) {\n\t\t\tFade_Sample(Current, THEME_DELAY);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * ThemeClass::Play_Song -- Starts the specified song play NOW.                                *\n *                                                                                             *\n *    This routine is used to start the specified theme playing right now. If there is already *\n *    a theme playing, it is cut short so that this one may start.                             *\n *                                                                                             *\n * INPUT:   theme -- The theme number to start playing.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with the sample play handle.                                               *\n *                                                                                             *\n * WARNINGS:   This cuts off any current song in a abrupt manner. Only use this routine when   *\n *             necessary.                                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ThemeClass::Play_Song(ThemeType theme)\n{\n\tif (ScoresPresent && SampleType && !Debug_Quiet && Options.ScoreVolume != 0) {\n\t\tStop();\n\t\tScore = theme;\n\t\tif (theme != THEME_NONE && theme != THEME_QUIET) {\n\t\t\tStreamLowImpact = true;\n\t\t\tCurrent = File_Stream_Sample_Vol(Theme_File_Name(theme), 0xFF, true);\n\t\t\tStreamLowImpact = false;\n\t\t}\n\t}\n\treturn(Current);\n}\n\n\n/***********************************************************************************************\n * ThemeClass::Theme_File_Name -- Constructs a filename for the specified theme.               *\n *                                                                                             *\n *    This routine will construct (into a static buffer) a filename that matches the theme     *\n *    number specified. This constructed filename is returned as a pointer. The filename will  *\n *    remain valid until the next call to this routine.                                        *\n *                                                                                             *\n * INPUT:   theme -- The theme number to convert to a filename.                                *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the constructed filename for the specified theme number. *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *   05/09/1995 JLB : Theme variation support.                                                 *\n *=============================================================================================*/\nchar const * ThemeClass::Theme_File_Name(ThemeType theme)\n{\n\tstatic char name[_MAX_FNAME+_MAX_EXT];\n\n\tif (theme >= THEME_FIRST && theme < THEME_COUNT) {\n\t\t_makepath(name, NULL, NULL, _themes[theme].Name, \".AUD\");\n\t\treturn((char const *)(&name[0]));\n\t}\n\n\treturn(\"\");\n}\n\n\n/***********************************************************************************************\n * ThemeClass::Track_Length -- Calculates the length of the song (in seconds).                 *\n *                                                                                             *\n *    Use this routine to calculate the length of the song. The length is determined by        *\n *    reading the header of the song and dividing the sample rate into the sample length.      *\n *                                                                                             *\n * INPUT:   theme -- The song number to examine to find its length.                            *\n *                                                                                             *\n * OUTPUT:  Returns with the length of the specified theme. This length is in the form of      *\n *          seconds.                                                                           *\n *                                                                                             *\n * WARNINGS:   This routine goes to disk to fetch this information. Don't call frivolously.    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ThemeClass::Track_Length(ThemeType theme) const\n{\n\tif ((unsigned)theme < THEME_COUNT) {\n\t\treturn(_themes[theme].Duration);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * ThemeClass::Stop -- Stops the current theme from playing.                                   *\n *                                                                                             *\n *    Use this routine to stop the current theme. After this routine is called, no more music  *\n *    will play until the Start() function is called.                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ThemeClass::Stop(void)\n{\n\tif (ScoresPresent && SampleType && !Debug_Quiet && Current != -1) {\n\t\tStop_Sample(Current);\n\t\tCurrent = -1;\n\t\tScore = THEME_NONE;\n\t\tPending = THEME_NONE;\n\t}\n}\n\n\nvoid ThemeClass::Suspend(void)\n{\n\tif (ScoresPresent && SampleType && !Debug_Quiet && Current != -1) {\n\t\tStop_Sample(Current);\n\t\tCurrent = -1;\n\t\tPending = Score;\n\t\tScore = THEME_NONE;\n\t}\n}\n\n\n/***********************************************************************************************\n * ThemeClass::Still_Playing -- Determines if music is still playing.                          *\n *                                                                                             *\n *    Use this routine to determine if music is still playing.                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the music still audible?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/20/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ThemeClass::Still_Playing(void) const\n{\n\tif (ScoresPresent && SampleType && Current != -1 && !Debug_Quiet) {\n\t\treturn(Sample_Status(Current));\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ThemeClass::Is_Allowed -- Checks to see if the specified theme is legal.                    *\n *                                                                                             *\n *    Use this routine to determine if a theme is allowed to be played. A theme is not allowed *\n *    if the scenario is too early for that score, or the score only is allowed in special     *\n *    cases.                                                                                   *\n *                                                                                             *\n * INPUT:   index -- The score the check to see if it is allowed to play.                      *\n *                                                                                             *\n * OUTPUT:  Is the specified score allowed to play in the normal score playlist?               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/09/1995 JLB : Created.                                                                 *\n *   07/04/1996 JLB : Handles alternate playlist checking.                                     *\n *=============================================================================================*/\nbool ThemeClass::Is_Allowed(ThemeType index) const\n{\n\tif ((unsigned)index >= THEME_COUNT) return(true);\n\n\t/*\n\t**\tIf the theme is not present, then it certainly isn't allowed.\n\t*/\n\tif (!_themes[index].Available) return(false);\n\n\t/*\n\t**\tOnly normal themes (playable during battle) are considered allowed.\n\t*/\n\tif (!_themes[index].Normal) return(false);\n\n\t/*\n\t**\tIf the theme is not allowed to be played by the player's house, then don't allow\n\t**\tit. If the player's house hasn't yet been determined, then presume this test\n\t**\tpasses.\n\t*/\n\tif (PlayerPtr != NULL && ((1 << PlayerPtr->ActLike) & _themes[index].Owner) == 0) return(false);\n\n\t/*\n\t**\tIf the scenario doesn't allow this theme yet, then return the failure flag. The\n\t**\tscenario check only makes sense for solo play.\n\t*/\n\tif (Session.Type == GAME_NORMAL && Scen.Scenario < _themes[index].Scenario) return(false);\n\n\t/*\n\t**\tSince all tests passed, return with the \"is allowed\" flag.\n\t*/\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * ThemeClass::From_Name -- Determines theme number from specified name.                       *\n *                                                                                             *\n *    Use this routine to convert a name (either the base filename of the theme, or a partial  *\n *    substring of the full name) into the matching ThemeType value. Typical use of this is    *\n *    when parsing the INI file for theme control values.                                      *\n *                                                                                             *\n * INPUT:   name  -- Pointer to base filename of theme or a partial substring of the full      *\n *                   theme name.                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the matching theme number. If no match could be found, then           *\n *          THEME_NONE is returned.                                                            *\n *                                                                                             *\n * WARNINGS:   If a filename is specified the comparison is case insensitive. When scanning    *\n *             the full theme name, the comparison is case sensitive.                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nThemeType ThemeClass::From_Name(char const * name) const\n{\n\tif (name && strlen(name) > 0) {\n\t\t/*\n\t\t**\tFirst search for an exact name match with the filename\n\t\t**\tof the theme. This is guaranteed to be unique.\n\t\t*/\n\t\tfor (ThemeType theme = THEME_FIRST; theme < THEME_COUNT; theme++) {\n\t\t\tif (stricmp(_themes[theme].Name, name) == 0) {\n\t\t\t\treturn(theme);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf the filename scan failed to find a match, then scan for\n\t\t**\ta substring within the full name of the score. This might\n\t\t**\tyield a match, but is not guaranteed to be unique.\n\t\t*/\n\t\tfor (theme = THEME_FIRST; theme < THEME_COUNT; theme++) {\n\t\t\tif (strstr(Text_String(_themes[theme].Fullname), name) != NULL) {\n\t\t\t\treturn(theme);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(THEME_NONE);\n}\n\n\n/***********************************************************************************************\n * ThemeClass::Scan -- Scans all scores for availability.                                      *\n *                                                                                             *\n *    This routine should be called whenever a score mixfile is registered. It will scan       *\n *    to see if any score is unavailable. If this is the case, then the score will be so       *\n *    flagged in order not to appear on the play list. This condition is likely to occur       *\n *    when expansion mission disks contain a different score mix than the release version.     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ThemeClass::Scan(void)\n{\n\tfor (ThemeType theme = THEME_FIRST; theme < THEME_COUNT; theme++) {\n\t\t_themes[theme].Available = CCFileClass(Theme_File_Name(theme)).Is_Available();\n\t}\n}\n\n\n\n/***********************************************************************************************\n * ThemeClass::Set_Theme_Data -- Set the theme data for scenario and owner.                    *\n *                                                                                             *\n *    This is an override function used to set a particular theme's initial scenario and       *\n *    owner values. Typically, the rules control file will be the source of calling this       *\n *    routine.                                                                                 *\n *                                                                                             *\n * INPUT:   theme    -- The theme to set these override values for.                            *\n *                                                                                             *\n *          scenario -- The first scenario when this theme becomes available on the play list. *\n *                                                                                             *\n *          owners   -- A bitfield representing the owners allowed to play this song.          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ThemeClass::Set_Theme_Data(ThemeType theme, int scenario, int owners)\n{\n\tif (theme != THEME_NONE) {\n\t\t_themes[theme].Normal = true;\n\t\t_themes[theme].Scenario = scenario;\n\t\t_themes[theme].Owner = owners;\n\t}\n}\n\n"
  },
  {
    "path": "CODE/THEME.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/THEME.H 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : THEME.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 14, 1994                                              *\n *                                                                                             *\n *                  Last Update : August 14, 1994   [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef THEME_H\n#define THEME_H\n\nclass ThemeClass\n{\n\tprivate:\n\t\tstatic char const * Theme_File_Name(ThemeType theme);\n\n\t\tint Current;\t\t\t// Handle to current score.\n\t\tThemeType Score;\t\t// Score number currently being played.\n\t\tThemeType Pending;\t// Score to play next.\n\n\t\ttypedef struct {\n\t\t\tchar const * Name;\t// Filename of score.\n\t\t\tint Fullname;\t\t\t// Text number for full score name.\n\t\t\tint Scenario;\t\t\t// Scenario when it first becomes available.\n\t\t\tint Duration;\t\t\t// Duration of theme in seconds.\n\t\t\tbool Normal;\t\t\t// Allowed in normal game play?\n\t\t\tbool Repeat;\t\t\t// Always repeat this score?\n\t\t\tbool Available;\t\t// Is the score available?\n\t\t\tint Owner;\t\t\t\t// What houses are allowed to play this theme (bit field)?\n\t\t} ThemeControl;\n\n\t\tstatic ThemeControl _themes[THEME_COUNT];\n\n\t\tenum {\n\t\t\tTHEME_DELAY=TIMER_SECOND\n\t\t};\n\n\tpublic:\n\t\tThemeClass(void);\n\n\t\tThemeType From_Name(char const * name) const;\n\t\tThemeType Next_Song(ThemeType index) const;\n\t\tThemeType What_Is_Playing(void) const {return Score;}\n\t\tbool Is_Allowed(ThemeType index) const;\n\t\tbool Is_Regular(ThemeType theme) const {return(theme != THEME_NONE && _themes[theme].Normal);}\n\t\tchar const * Base_Name(ThemeType index) const;\n\t\tchar const * Full_Name(ThemeType index) const;\n\t\tint Max_Themes(void) const {return THEME_COUNT;}\n\t\tint Play_Song(ThemeType index);\n\t\tint Still_Playing(void) const;\n\t\tint Track_Length(ThemeType index) const;\n\t\tstatic void Scan(void);\n\t\tvoid AI(void);\n\t\tvoid Fade_Out(void) {Queue_Song(THEME_QUIET);}\n\t\tvoid Queue_Song(ThemeType index);\n\t\tvoid Set_Theme_Data(ThemeType theme, int scenario, int owners);\n\t\tvoid Stop(void);\n\t\tvoid Suspend(void);\n};\n\n#endif\n"
  },
  {
    "path": "CODE/TLINK.CFG",
    "content": " /Lbc402\\lib;d:\\library;d:\\bc4\\lib;d:\\rtlink\n /c \n /E\n /Tde \n"
  },
  {
    "path": "CODE/TODO.TXT",
    "content": "MASTER 11/7/96\n\n*Skirmish and cap flag carry over bug.\n\n*Speed boots to anti-aircraft flag.\n\n*allies reveal fakes\n\nBadguy -vs- soviet repair glitch\n\nBuilding one too many harvester.\n\nforce music on the title page and credit scroll\n\nAdd mouse dead zone around key buttons\n\n*Harvester getting stuck against a unit that is perpetually trying to scatter (stutter rotating).\n\nAI base is unit heavy. Should concentrate more on air defenses and selling off old buildings.\n\nAttack buildings to discourage from attacking base defenses.\n\n*Longbow not going onto pad even if empty.\n\nTanya should laugh when exiting barracks.\n\n*If dog drops onto impassable terrain, then fake it into a passable cell instead.\n\n*Keep record of previously existing building to use for computer prerequisite checks.\n\n*Bias the base center away from the edge of the map.\n\n*Add \"delay before beginning the first attack\" to the rules for ai players.\n\nAdd difficulty slider to the skirmish mode.\n\nDriving over weapons factory door.\n\nGive rules control to some of the house check and ai function pairs.\n\nControl engineer repair of bridge by rules file.\n\nCombine chrono effects into a single event.\n\nIf near capacity, then build a silo.\n\nHouseClass::Attacked is not multiplay friendly\n\nUse the return value from the house AI function to regulate the interval between their processing.\n\nBuild MCV (and go into hunt) when no construction yard left.\n\nCredit scroll scraggs title page.\n\nRetreat mode with LST\n\n*AI units sometimes drive to upper left corner\n\nSneak peek after intro replay.\n\nDon't allow more than two allies together (if humans only).\n\nFix the Where_To_Go() function so that it prefers under protected zones and zones that are\nclosest to the enemy.\n\nComputer should cause blocking units to move before giving up placing a building.\n\nComputer should avoid building against the map edge.\n\nSpecial build emphasis on the zone that gets attacked.\n\n\nTournament rules:\n> Countdown timer -- game ends with winner who has higher score. If not\ncounting down, it should count upward.\n> Display score instead of kills on map display.\n> Handicap assigned to each player?\n> Invulnerable harvester option. Will not be automatically fired\nupon until all refineries destroyed. Also, it cannot overrun\ninfantry until then either.\n> Allow disabling of ally option.\n> Ally should be limited to only one other player. Say \"Changes allegience to ???\" or\n\"Turncoats from ??? to ???\"\n\nClicks on unit production (especially infantry) should be\nqueued up (with a number).\n\nC&C2: Ideas\n> Some advantage to the civilian or mutant villages so that they\nwon't likely be destroyed in a multiplayer game. Maybe they plant\nTiberium.\n> Tiberium should spill from a destroyed harvester.\n> Multiplayer maps should have more than one entrance into the\nlikely starting areas for the players. This is needed to make\ncomplete blocking of access to the base very difficult.\n\nAudio control slider should have a step rate\n\nCan harvester detect a stealth tank on the radar map as long as the\nstealth tank is not over tiberium?\n\nCivilians should run from civilian buildings.\n\nWhen ordering to move to a tree, the units don't move at all.\n\nTransport should not scatter.\n\nHarvesters should return to refinery instead of scattering. If they are already\nunloading or heading back to refinery, then they shouldn't scatter at all.\n\nOfficial maps should be brighter color.\n\nDetect counterfiet maps.\n\nAdd KN bits for Num, Scroll, and Caps lock toggle keys. This will give more\ninformation to the ToASCII function for proper keyboard conversion.\n\nFire coord for AA guns are off.\n\nDraw parachute before drawing attached object.\n\nPatrol to waypoint should clear out any prexisting target so the team members wont\nstart to run back to their old target.\n\nforce bases on if cap flag checked and visa versa.\n\nBoats are not giving out-of-range cursor when selecting a target? Make this controllable\nthrough the rules.ini file.\n\nBuildings are all scanned during every foot::percellprocess as well as any\ntime a building is drawn that is spied.\n\nForce attack for mine layer could be \"lay mine\".\n\nNeed scenario.Start(), Restart(), Reset() functions to control the campaign start,\nnext mission start, and restart current mission over functions.\nBreak scenario data into two groups. The group that needs to be preserved between scenarios\nand that which is set by the scenario INI file. Both groups should be saved in the saved game.\nThe IsTanyaDead and SaveTanya should be in there. There should be two copies of the section\nthat is preserved between scenarios. This will allow restarting the scenario.\n\nEncrypt the message digest for scenario files. Detect whether scenario is custom or\noriginal version when loading?\n\nThe overlap list could be implemented as a sparse array. Each cell would have a pointer\nto the overlap list handler. when no overlaps exist, the handler gets deleted.\n\nOptimize INI scanning code. Store only CRC if never going to be written back out? Store\nentry/section CRC values as a sorted array to allow binary search? Use strcmp instead of\nstricmp?\n\nThief in hunt mode should go after structures.\n\nChoose computer to attack based on force comparison? If stronger by certain\namount, then attack. If weaker than certain amount, then build.\n\nProgress bargraph on game save/load.\n\nLongbow shows up for airstrip production?\n\nSuggest that these get added to the westwood library: _rotl(), ARRAY_SIZE, min(), max(), abs(), Bound()\n\nPut saving/load of Special and Options into save_misc_values and remove from\nsave/load mplayer_values function.\n\nWhy does SessionClass::Save seem to save the same values that save_mplayer_values\nand save_misc_values does.\n\nFlying debris from an exploding building or vehicle.\n\nThe UnitToTeleport and TimeQuake variables might need to be save/loaded with the game.\n\nEach class should have an equivalent Build_INI_Entry routine. A generic (save all objects) routine\ncould then be written.\n...or... Need a INI-Put_String with variable parameters.\n\nAdd random animation logic for buildings, vessels, and vehicles.\n\nIf directed to move to the immediately adjacent behind cell, then just back up into it. Anything\nmore distant, rotate to normal orientation.\n\nThe MPHType seems obsolete. Just a simple \"leptons per game frame\" speed value seems\nmore appropriate.\n\nCrosses line triggers may need special handling in some kind of list. They need to have a cell\nattached so that when a unit moves, it can quickly determine if it causes one of these\ntrigger types to spring. This is the only trigger type that requires a cell data.\n\nNeed a more efficient way of detecting when a unit crosses line or enters zone trigger event.\n\nCrack the radio messages into separate handler functions e.g., Radio_Run_Away(), Radio_Over_Out()\n\nTake close look at findpath logic. Incorporate;\n> Settle for simple path calc when first starting and distant from destination.\n> Escilate path searching when blockage occurs.\n> Reset search aggressiveness when new navcom is assigned.\n> Use common routine when path is block and \"What now?\" needs to be answered.\n\nComputer ships SHOULD fire on non-combat buildings when in area guard mode.\n\nTeam AI should have a delay between calls.\n\nHires_Load may be obsolete?\n\nCrosses line trigger is causing problems.\n\nCheck for out of disk space during save. Delete partial save file.\n\nV04, V05, V07 have more anim frames.\n\nPut INI reading code within the warhead class object. The warhead object will be\ncreated by the weapon INI info. It will be named but otherwise undefined. The warhead\nreading code will look up the warhead info based on the name and then fill in the\nvalues.\n\nAdd override flag so unit name can always be printed over unit? Possibly have\nfull name override for pop up help text as well.\n\n\nAdjust_Threat should only make an adjustment if the unit moves to a new\ncell, is unlimboed, or limboed.\n\nNew to Borland 5.0!\n\tnamespaces\n\tmutable\n\tbool\n\tstandard template library\n\n\n\nkevin_aguilar\n\nTOFIX -- fix for Red Alert\nOLD -- obsolete for Red Alert, but applicable for Tiberiun Sun\n\n\nWhile moving, scan for targets within range (turret vehicles only) so that\nfiring may occur while moving.\n\nKeep track of the amount of damage (rate) received by a building. This\nis used to determine if the building should be sold if it is taking\ntoo much damage.\n\nSend attack helicopter to harrass the enemy.\n\nDon't consider SAM sites to be weapon equipped when determining retaliation\nlogic.\n\nAbort existing production in emergency situations. e.g., when power is low, base\nis under attack, or no refineries left.\n\nBreak down AI into request and priority. Then after building list, try to perform\nall actions that are highest priority without being mutually exclusive.\n\nRecord the current state of the house. Possible states could be \"buildup\", \"under attack\",\n\"idle\". The AI will adjust itself depending on the state of the base.\n\n\nWhen damaged and previous target is outside of range but antagonist is much closer,\nthen attack antagonist. Recuit assistance from any nearby friendly units that\nare also far from their designated target or are otherwise unoccupied.\n\nHall of fame data to record more information. Histogram of progress? Records\nthe number of wins/losses/reloads/saves, etc. Time they play.\n\nColors on team selection brackets.\n\nBuild base defense toward last enemy, but as a ring from the center of the base.\n\nBuild infrastructure away from enemy threat.\n\nIf low on money also sell of some base defense if there is just too much of it.\n\n\nSetup program crashes in windows 95. Error is \"stack overflow on interrupt\".\n\nMCV not deploying if it starts in correct rotated position.\n\nScore timer needs fixing.\n\n33. SCG03EA: Won by capturing his Hand of Nod, and then\nbuilding engineers from it to capture the rest of the  base.\nWhen something like that happens, the AI should  recall most or all of its forces for defense.\n\nDistribute damage applied to refinery to any attached harvester as well.\n\nIf no more tiberium or no more refinery, then rampage harvester.\n\nFix tree crumbling.\n\nAdd a hover command to the mission list so that the helicopter can hover (forever).\n\nPrevent using the placement cursor to find stealth tanks.\n\nAirstrip should animation flashing lights when an aircraft is approaching only.\n\nApply low power damage only when the \"need more power\" message is played.\n\nClick and drag on the radar map?\n\nIf engineer has its target snatched out from under him, then assign a hunt\nmission so that it will pick another target (applied to computer non-team only).\n\nIf hit, then respond even if on hunt.\n\nOptimize the update threat function to occur ever cell rather than every time the object\nis marked up or down.\n\nIf a building is captured, cause a defend base action.\n\nWhen full of storage, stop the harvester. Don't enter refinery if there is\nno storage available. If less than 350 credit storage available, pause.\n\nDarken \"repair\" and \"sell\" if there are no buildings available.\n\nIf a computer controlled unit enters a transport square, then load it up.\n\nTake advantage of archive target for aircraft. Returns to location after\nattacking.\n\nAircraft dying on ground should have crew survivor.\n\nHelicopters puff smoke before crashing. Handles the transport helicopter.\n\nAfter evac, send the helicopter back to the game? Keep track of number\nof civilians evacutated? Tie a trigger event to this number?\n\nDon't reload the SCUD while it is moving. Suspend the reload delay\nby incrementing the countdown timer.\n\nNeed accurate mouse tracking so that it is possible to move infantry into the same square\nas other infantry.\n\nTighter individual infantry AI. Self defence priority.\n\nBringing a wall to its last damage level should be much easier\nthan completely destroying it. This will allow infantry to\nenter through the holes in a wall more easily than the vehicles\nwould.\n\nNeed a function that will return the cell number that either the unit is\ncurrently at (if it isn't moving) or the one that it will be at the\nmoment is needs to pull more values off of the path list. This function\nwill be used in the findpath draw routine. This is necessary because\ninfantry and vehicles use a different method of movement and path list\nprocessing.\n\nAdd flag so that bullet (or warhead) knows whether to do explosion area\neffect damage or whether to just damage the target. SAM missiles would\njust damage the target (maybe APDS as well).\n\nAdd some function to the facing class that automatically convert the\nreturn value to 1/32 or 1/8 values.\n\nMisc. strange Watcom errors/quirks\n> Internal compiler error 57\n> Abnormal program termination: Array bounds exception CS:EIP = 2BCDh:000009A6h\n> Created a 100 meg precompiled header file.\n> read error on work file: error code = 1\n> \"const\" bitfields show up as 32bit numbers in debugger.\n> couldn't add a specifier (foobar::) to a friend class declaration\n> Inline assembly can generate wrong code for parameter setup.\n> casting doesn't follow precidence rules.\n> CTRL-C to break out of compile sometimes crashes. Here is an error.\n Invalid date \"\"\n run-time error R6000\n - stack overflow\n> Unable to find carve memory block.\n> Can't overload inline assembly routines?!?! #pragma doesn't specify parameter\n type information so that it can resolve properly?\n> Access Violation abort and register dump when compiling display.cpp\n\tWPP386 caused an invalid page fault in\n\tmodule <unknown> at 0000:4f435c4f.\n\tRegisters:\n\tEAX=8161e314 CS=014f EIP=4f435c4f EFLGS=00010246\n\tEBX=0059f798 SS=0157 ESP=005900f0 EBP=00590110\n\tECX=00590198 DS=0157 ESI=005901dc FS=0d97\n\tEDX=bff76648 ES=0157 EDI=005901c0 GS=0000\n\tBytes at CS:EIP:\n\n\nPass range to bullet constructor. It will use this value to limit the\nfuel and scatter calculations.\n\nLibrary allocation and input system should route through a global\nbase class pointer. This allows changing some aspect of these system\nby using simple derived classes. Example: The memory system could keep\ntrack of what and why allocations take place. The input system could be\nintercepted to playback a recorded demo. Etc.\n\nCreate a standard format for dissemenating technology from a project. This form\nwould have a concise technology synopsis at the begining. This would be\nfollowed by greater detail explanations.\n\nCreate inline versions of Swap_LONG, Reverse_WORD, and Reverse_LONG.\n\nStraighten out the ScrollGadget / SliderGadgets. It shouldn't \"new\"\nthe arrow gadgets, but rather either have them as integral objects\nor separate them completely and create a special combination class\nin a similar fashion to the list class.\n\nCreate a number<->string handler for the library. String data files (blocks) are registered\nwith the handler. All library routines that can take const strings could then also take\nstring numbers. They would use the handler to extract the correct string pointer.\n\nCreate a utility that loads the palette source pictures and then generates all the morph\npalette tables.  This is a C&C custom utility.\n\nNeed a smarter team movement logic for the computer so that infantry do not clump into\none cell unless absolutely necessary.\n\nCreate a function that submits a \"pending object\" to the map I/O handler. This handles\nsetting up the Zone cell, pseudocursor sizes, as well as all the pending pointers.\n\nIf fire shard lands in the exact sub-cell position of an infantry unit, then it will automatically\ncatch fire.\n\nIf cell targets were simple object types, then they can exists in a sort of virtual cell existence\nwhen specific targeting of a cell is desired. This will allow all target values to be converted\ninto short object  pointers. There would be a limit to the number of cells that could be targeted\nsimultaneously. Multiple  units targeting the same cell would be allowed. Each pseudo-cell would\nkeep a record of the number of  simultaneous targets upon itself.\n\nAdd a \"new\" and \"delete\" function for cells. It would merely return pointer to appropriate spot in\nthe cell array, but does allow the constructor/destructor logic to function as well as allow the\npossibility of arbitrary sized maps. These cell objects would not be the same as the virtual cell\nobjects used for targeting purposes, although each targeting cell object has a real cell object it\ncorresponds to.\n\nNeed a utility that will calculate fading and translucent tables from a specified palette.\nIt will create a data file of the created table(s). This utility should be passed a\nsource LBM (for palette file) and a destination filename and the operation to perform.\nIt could also be passed a text file that elaborated the process to perform.\n\nExample:\n[All]\t\t; Options that perform to all colors unless overridden.\nPercent=70\t; Percent to fade from original color to destination color.\n[1]\t\t; Process for color table entry #1 in original palette.\nFadeTo=13\t; Fades to color #13.\nPercent=70\t; Fades 70% of the way from color 1 to color 13.\nUses=240-255\t; Only allowed to pick from these colors as final color.\n\nObjects should move into and out of the logic processing list according to what state they are in.\nA unit that is just sitting and waiting for its timer to count down shouldn't be processed in the\nregular list like the other units would be. Example:  A unit is sitting there with no order so it\nis out of the normal logic loop. If it gets selected as a target then it must flash. The\n\"isflashing\" flag gets set and the object gets placed into the logic list. When the flashing\nexpires, a simple (union?) check of the logic activation bits is performed. If any of the bits are\nstill on, then the object remains in the logic list, otherwise it is removed. A simple countdown\ntimer processor is needed for those cases where the only reason the unit is out of the logic loop\nis if it is waiting for the next AI command to occur.\n\nsearch for \",[^ \\t$]\" and \" (\" and \"}\\n[ \\t]else {\" and \"for(\" and \"switch(\" and \"\\*.\" and \"\\t\\*-\" and \"return(\"\n){ and }else{\n\nSeparate arming value for each weapon. This will allow weapons to fire at will according to\ntheir fire rates. This will also require a What_Weapon_Should_I_Fire_Now() function to\nhelp resolve the ambiguous situations.\n\nCreate a project format style guide for C&C Tiberian Sun. Put summary into some header file.\n\nNeed very specific question functions for the objects. Wrapper functions (radio messages) coordinate\nthese sub functions to perform tasks."
  },
  {
    "path": "CODE/TOGGLE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TOGGLE.CPP 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TOGGLE.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : February 2, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ToggleClass::ToggleClass -- Normal constructor for toggle button gadgets.                 *\n *   ToggleClass::Turn_Off -- Turns the toggle button to the \"OFF\" state.                      *\n *   ToggleClass::Turn_On -- Turns the toggle button to the \"ON\" state.                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"toggle.h\"\n\n\n/***********************************************************************************************\n * ToggleClass::ToggleClass -- Normal constructor for toggle button gadgets.                   *\n *                                                                                             *\n *    This is the normal constructor for toggle buttons. A toggle button is one that most      *\n *    closely resembles the Windows style. It has an up and down state as well as an on        *\n *    and off state.                                                                           *\n *                                                                                             *\n * INPUT:   id    -- ID number for this button.                                                *\n *                                                                                             *\n *          x,y   -- Pixel coordinate of upper left corner of this button.                     *\n *                                                                                             *\n *          w,h   -- Width and height of the button.                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nToggleClass::ToggleClass(unsigned id, int x, int y, int w, int h) :\n\tControlClass(id, x, y, w, h, LEFTPRESS|LEFTRELEASE, true),\n\tIsPressed(false),\n\tIsOn(false),\n\tIsToggleType(false)\n{\n}\n\n\n/***********************************************************************************************\n * ToggleClass::Turn_On -- Turns the toggle button to the \"ON\" state.                          *\n *                                                                                             *\n *    This routine will turn the button on. The button will also be flagged to be redrawn      *\n *    at the next opportunity.                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ToggleClass::Turn_On(void)\n{\n\tIsOn = true;\n\tFlag_To_Redraw();\n}\n\n\n/***********************************************************************************************\n * ToggleClass::Turn_Off -- Turns the toggle button to the \"OFF\" state.                        *\n *                                                                                             *\n *    This routine will turn the toggle button \"off\". It will also be flagged to be redrawn    *\n *    at the next opportunity.                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ToggleClass::Turn_Off(void)\n{\n\tIsOn = false;\n\tFlag_To_Redraw();\n}\n\n\n/***********************************************************************************************\n * ToggleClass::Action -- Handles mouse clicks on a text button.                               *\n *                                                                                             *\n *    This routine will process any mouse or keyboard event that is associated with this       *\n *    button object. It detects and flags the text button so that it will properly be drawn    *\n *    in a pressed or raised state. It also handles any toggle state for the button.           *\n *                                                                                             *\n * INPUT:   flags -- The event flags that triggered this button.                               *\n *                                                                                             *\n *          key   -- The keyboard code associated with this event. Usually this is KN_LMOUSE   *\n *                   or similar, but it could be a regular key if this text button is given    *\n *                   a hotkey.                                                                 *\n *                                                                                             *\n * OUTPUT:  Returns whatever the lower level processing for buttons decides. This is usually   *\n *          true.                                                                              *\n *                                                                                             *\n * WARNINGS:   The button is flagged to be redrawn by this routine.                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/14/1995 JLB : Created.                                                                 *\n *   02/02/1995 JLB : Left press doesn't get passed to other buttons now                       *\n *=============================================================================================*/\nint ToggleClass::Action(unsigned flags, KeyNumType &key)\n{\n\t/*\n\t**\tIf there are no action flag bits set, then this must be a forced call. A forced call\n\t**\tmust never actually function like a real call, but rather only performs any necessary\n\t**\tgraphic updating.\n\t*/\n\tbool overbutton = ((unsigned)(Get_Mouse_X() - X) < Width && (unsigned)(Get_Mouse_Y() - Y) < Height );\n\tif (!flags) {\n\t\tif (overbutton) {\n\t\t\tif (!IsPressed) {\n\t\t\t\tIsPressed = true;\n\t\t\t\tFlag_To_Redraw();\n\t\t\t}\n\t\t} else {\n\t\t\tif (IsPressed) {\n\t\t\t\tIsPressed = false;\n\t\t\t\tFlag_To_Redraw();\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tHandle the sticky state for this gadget. It must be processed here\n\t**\tbecause the event flags might be cleared before the action function\n\t**\tis called.\n\t*/\n\tSticky_Process(flags);\n\n\t/*\n\t**\tFlag the button to show the pressed down imagery if this mouse button\n\t**\twas pressed over this gadget.\n\t*/\n\tif (flags & LEFTPRESS) {\n\t\tIsPressed = true;\n\t\tFlag_To_Redraw();\n\t\tflags &= ~LEFTPRESS;\n\t\tControlClass::Action(flags, key);\n\t\tkey = KN_NONE;\t\t\t\t// erase the event\n\t\treturn(true);\t\t// stop processing other buttons now\n\t}\n\n\tif (flags & LEFTRELEASE) {\n\t\tif (IsPressed) {\n\t\t\tif (IsToggleType && overbutton) {\n\t\t\t\tIsOn = (IsOn == false);\n\t\t\t}\n\t\t\tIsPressed = false;\n\t\t\tFlag_To_Redraw();\n\t\t} else {\n\t\t\tflags &= ~LEFTRELEASE;\n\t\t}\n\t}\n\n\t/*\n\t**\tDo normal button processing. This ends up causing the button's ID number to\n\t**\tbe returned from the controlling Input() function.\n\t*/\n\treturn(ControlClass::Action(flags, key));\n}\n\n\n"
  },
  {
    "path": "CODE/TOGGLE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TOGGLE.H 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TOGGLE.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TOGGLE_H\n#define TOGGLE_H\n\n#include \"control.h\"\n\n/*\n**\tThis class handles gadgets that behave like the Windows buttons. That is, once the mouse\n**\tbutton is clicked over them, they capture the focus until the mouse button is released.\n**\tThey have a different imagery for the pressed and released states. They only recognize\n**\ta valid selection when the mouse button is release while over the button.\n*/\nclass ToggleClass : public ControlClass\n{\n\tpublic:\n\t\tToggleClass(unsigned id, int x, int y, int w, int h);\n\t\tvoid Turn_On(void);\n\t\tvoid Turn_Off(void);\n\n\t\t/*\n\t\t**\tIs this button in a pressed down state? This occurs when the mouse is clicked on the\n\t\t**\tbutton and the mouse is still being held down.\n\t\t*/\n\t\tunsigned IsPressed:1;\n\n\t\t/*\n\t\t**\tThis is the button on/off state. Sometimes a button that is \"on\" has a different\n\t\t**\timagery than one that is \"off\". If the on/off state is not necessary, then just\n\t\t**\tignore this flag.\n\t\t*/\n\t\tunsigned IsOn:1;\n\n\t\t/*\n\t\t**\tIf this button can be turned \"on\" or \"off\", then this flag should be set to\n\t\t**\ttrue. Sometimes a button needs to display its on/off state. In the render routine,\n\t\t**\texamine the IsOn flag and display accordingly. If this flag is false, then the\n\t\t**\tIsOn flag will not be changed, regardless of button clicking.\n\t\t*/\n\t\tunsigned IsToggleType:1;\n\n\tprotected:\n\n\t\tvirtual int Action(unsigned flags, KeyNumType &key);\n};\n\n#endif\n"
  },
  {
    "path": "CODE/TOOLTIP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n//\tToolTip.cpp\n\n#include \"function.h\"\n#include \"ToolTip.h\"\n#include \"IconList.h\"\n\n//#include \"WolDebug.h\"\n\nbool SaveSurfaceRect( int xRect, int yRect, int wRect, int hRect, char* pBits, WindowNumberType window );\nbool RestoreSurfaceRect( int xRect, int yRect, int wRect, int hRect, const char* pBits, WindowNumberType window );\n\n//***********************************************************************************************\nToolTipClass::ToolTipClass( GadgetClass* pGadget, const char* szText, int xShow, int yShow, \n\t\t\t\t\t\t\t\tbool bRightAlign /* = false */, bool bIconList /*= false */ )\n\t: pGadget( pGadget ), xShow( xShow ), yShow( yShow ), next( NULL ), bShowing( false ), bIconList( bIconList ),\n\t\tbRightAlign( bRightAlign )\n\n{\n\tif( szText )\n\t{\n\t\tif( strlen( szText ) > TOOLTIPTEXT_MAX_LEN )\n\t\t\tstrcpy( szTip, \"Tooltip too long!\" );\n\t\telse\n\t\t\tstrcpy( szTip, szText );\n\t}\n\telse\n\t\t*szTip = 0;\n\n\tSet_Font( TypeFontPtr );\n\tFancy_Text_Print( TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TYPE );\t//\tRequired before String_Pixel_Width() call, for god's sake.\n\twShow = String_Pixel_Width( szTip ) + 2;\n\thShow = 11;\n\n\tif( !bIconList )\n\t{\n\t\tpSaveRect = new char[ wShow * hShow ];\t\t//\tElse it is reallocated on every draw.\n\t\tif( bRightAlign )\n\t\t\tthis->xShow -= wShow;\n\t}\n\telse\n\t\tpSaveRect = NULL;\n\n\t//\tbIconList is true if tooltips appear for individual line items in an iconlist.\n\t//\tszText in this case is ignored.\n\t//\tyShow is the y position of the top row's tooltip - other rows will be offset from here.\n}\n\n//***********************************************************************************************\nToolTipClass* ToolTipClass::GetToolTipHit()\n{\n\t//\tReturns 'this' if the mouse is over gadget bound to tooltip.\n\t//\tOtherwise calls the same function in the next tooltip in the list of which *this is a part.\n\tif( bGadgetHit() )\n\t\treturn this;\n\telse if( next )\n\t\treturn next->GetToolTipHit();\n\telse\n\t\treturn NULL;\n}\n\n//***********************************************************************************************\nbool ToolTipClass::bGadgetHit() const\n{\n\t//\tReturns true if the mouse is currently over the gadget to which *this is bound.\n\tint x = Get_Mouse_X();\n\tint y = Get_Mouse_Y();\n\treturn ( x > pGadget->X && x < pGadget->X + pGadget->Width && y > pGadget->Y && y < pGadget->Y + pGadget->Height );\n}\n\n//***********************************************************************************************\nvoid ToolTipClass::Move( int xShow, int yShow )\n{\n\tbool bRestoreShow = false;\n\tif( bShowing )\n\t{\n\t\tbRestoreShow = true;\n\t\tUnshow();\n\t}\n\tthis->xShow = xShow;\n\tif( !bIconList )\n\t{\n\t\tif( bRightAlign )\n\t\t\tthis->xShow -= wShow;\n\t}\n\tthis->yShow = yShow;\n\tif( bRestoreShow )\n\t\tShow();\n}\n\n//***********************************************************************************************\nvoid ToolTipClass::Show()\n{\n\tif( !bShowing )\n\t{\n\t\tSet_Font( TypeFontPtr );\n\t\tint xShowUse = xShow, yShowUse, wShowUse;\n\t\tconst char* szTipUse;\n\t\tif( !bIconList )\n\t\t{\n\t\t\tyShowUse = yShow;\n\t\t\twShowUse = wShow;\n\t\t\tszTipUse = szTip;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tIconListClass* pIconList = (IconListClass*)pGadget;\n\t\t\tiLastIconListIndex = pIconList->IndexUnderMouse();\n\t\t\tif( iLastIconListIndex < 0 )\n\t\t\t{\n\t\t\t\t//\tNothing to show.\n\t\t\t\tbShowing = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tyShowUse = pIconList->OffsetToIndex( iLastIconListIndex, yShow );\n\t\t\tszTipUse = pIconList->Get_Item_Help( iLastIconListIndex );\n\t\t\tif( !szTipUse || *szTipUse == 0 )\n\t\t\t{\n\t\t\t\t//\tNothing to show.\n\t\t\t\tbShowing = true;\n\t\t\t\tbLastShowNoText = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tFancy_Text_Print( TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TYPE );\t//\tRequired before String_Pixel_Width() call, for god's sake.\n\t\t\twShowUse = String_Pixel_Width( szTipUse ) + 2;\n\t\t\tif( bRightAlign )\n\t\t\t\txShowUse -= wShowUse;\n\t\t\tdelete [] pSaveRect;\n\t\t\tpSaveRect = new char[ wShowUse * hShow ];\n\t\t\tbLastShowNoText = false;\n\t\t\txLastShow = xShowUse;\n\t\t\tyLastShow = yShowUse;\n\t\t\twLastShow = wShowUse;\n\t\t}\n\n\t\t//\tSave rect about to be corrupted.\n\t\tHide_Mouse();\n\t\tSaveSurfaceRect( xShowUse, yShowUse, wShowUse, hShow, pSaveRect, WINDOW_MAIN );\n\t\t//\tDraw text.\n\t\t//Simple_Text_Print( szTipUse, xShowUse, yShowUse, GadgetClass::Get_Color_Scheme(), ColorRemaps[ PCOLOR_BROWN ].Color, TPF_TYPE ); //TPF_DROPSHADOW );\n\t\tSimple_Text_Print( szTipUse, xShowUse, yShowUse, GadgetClass::Get_Color_Scheme(), BLACK, TPF_TYPE ); //TPF_DROPSHADOW );\n\t\t//\tDraw bounding rect.\n//\t\tLogicPage->Draw_Rect( xShowUse, yShowUse, xShowUse + wShowUse - 1, yShowUse + hShow - 1, ColorRemaps[ PCOLOR_GOLD ].Color );\n\t\tDraw_Box( xShowUse, yShowUse, wShowUse, hShow, BOXSTYLE_BOX, false );\n\t\tShow_Mouse();\n\t\tbShowing = true;\n\t}\n}\n\n//***********************************************************************************************\nvoid ToolTipClass::Unshow()\n{\n\tif( bShowing )\n\t{\n\t\tint xShowUse, yShowUse, wShowUse;\n\t\tif( !bIconList )\n\t\t{\n\t\t\txShowUse = xShow;\n\t\t\twShowUse = wShow;\n\t\t\tyShowUse = yShow;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif( iLastIconListIndex == -1 || bLastShowNoText )\n\t\t\t{\n\t\t\t\t//\tNothing to restore.\n\t\t\t\tbShowing = false;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t//\t(Can't rely on iconlist being the same as when Show() occurred.)\n//\t\t\tIconListClass* pIconList = (IconListClass*)pGadget;\n//\t\t\tyShowUse = pIconList->OffsetToIndex( iLastIconListIndex, yShow );\n//\t\t\tconst char* szTipUsed = pIconList->Get_Item_Help( iLastIconListIndex );\n//\t\t\tif( !szTipUsed || *szTipUsed == 0 )\n//\t\t\t{\n//\t\t\t\t//\tNothing to restore.\n//\t\t\t\tbShowing = false;\n//\t\t\t\treturn;\n//\t\t\t}\n//\t\t\tFancy_Text_Print( TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TYPE );\t//\tRequired before String_Pixel_Width() call, for god's sake.\n//\t\t\twShowUse = String_Pixel_Width( szTipUsed ) + 2;\n//\t\t\tif( bRightAlign )\n//\t\t\t\txShowUse -= wShowUse;\n\t\t\txShowUse = xLastShow;\n\t\t\tyShowUse = yLastShow;\n\t\t\twShowUse = wLastShow;\n\t\t}\n\t\tHide_Mouse();\n\t\tRestoreSurfaceRect( xShowUse, yShowUse, wShowUse, hShow, pSaveRect, WINDOW_MAIN );\n\t\tShow_Mouse();\n\t\tbShowing = false;\n\t}\n}\n\n//***********************************************************************************************\nbool ToolTipClass::bOverDifferentLine() const\n{\n\t//\tbIconList must be true if this is being used.\n\t//\tReturns true if the iconlist line that the mouse is over is different than the last time Show() was called.\n\treturn ( ((IconListClass*)pGadget)->IndexUnderMouse() != iLastIconListIndex );\n}\n\n//***********************************************************************************************\nbool SaveSurfaceRect( int xRect, int yRect, int wRect, int hRect, char* pBits, WindowNumberType window )\n{\n\t//\tSaves a rect of the LogicPage DirectDraw surface to pBits.\n//\tif( wRect * hRect > iBufferSize )\n//\t{\n//\t\tdebugprint( \"SaveSurfaceRect failed.\\n\" );\n//\t\treturn false;\n//\t}\n\n\tGraphicViewPortClass draw_window(\tLogicPage->Get_Graphic_Buffer(),\n\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWX] + LogicPage->Get_XPos(),\n\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWY] + LogicPage->Get_YPos(),\n\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWWIDTH],\n\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWHEIGHT] );\n\tif( draw_window.Lock() )\n\t{\n\t\tint iPitchSurf = draw_window.Get_Pitch() + draw_window.Get_Width();\t//\tMeaning of \"Pitch\" in this class seems to mean the eol skip.\n\t\tconst char* pLineSurf = (char*)draw_window.Get_Offset() + xRect + yRect * iPitchSurf;\n\t\tchar* pLineSave = pBits;\n\n\t\t//\tajw - Should copy DWORDs here instead for speed.\n\t\tfor( int y = 0; y != hRect; y++ )\n\t\t{\n\t\t\tconst char* pSurf = pLineSurf;\n\t\t\tchar* pSave = pLineSave;\n\t\t\tfor( int x = 0; x != wRect; x++ )\n\t\t\t\t*pSave++ = *pSurf++;\n\n\t\t\tpLineSurf += iPitchSurf;\n\t\t\tpLineSave += wRect;\n\t\t}\n\t\tdraw_window.Unlock();\n\t\treturn true;\n\t}\n\telse\n\t{\n//\t\tdebugprint( \"SaveSurfaceRect Could not lock surface.\\n\" );\n\t\treturn false;\n\t}\n}\n\n//***********************************************************************************************\nbool RestoreSurfaceRect( int xRect, int yRect, int wRect, int hRect, const char* pBits, WindowNumberType window )\n{\n\t//\tCopies a saved rect of bits back to the LogicPage DD surface.\n\tGraphicViewPortClass draw_window(\tLogicPage->Get_Graphic_Buffer(),\n\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWX] + LogicPage->Get_XPos(),\n\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWY] + LogicPage->Get_YPos(),\n\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWWIDTH],\n\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWHEIGHT] );\n\tif( draw_window.Lock() )\n\t{\n\t\tint iPitchSurf = draw_window.Get_Pitch() + draw_window.Get_Width();\t//\tMeaning of \"Pitch\" in this class seems to mean the eol skip.\n\t\tchar* pLineSurf = (char*)draw_window.Get_Offset() + xRect + yRect * iPitchSurf;\n\t\tconst char* pLineSave = pBits;\n\n\t\t//\tajw - Should copy DWORDs here instead for speed.\n\t\tfor( int y = 0; y != hRect; y++ )\n\t\t{\n\t\t\tchar* pSurf = pLineSurf;\n\t\t\tconst char* pSave = pLineSave;\n\t\t\tfor( int x = 0; x != wRect; x++ )\n\t\t\t\t*pSurf++ = *pSave++;\n\n\t\t\tpLineSurf += iPitchSurf;\n\t\t\tpLineSave += wRect;\n\t\t}\n\t\tdraw_window.Unlock();\n\t\treturn true;\n\t}\n\telse\n\t{\n//\t\tdebugprint( \"RestoreSurfaceRect Could not lock surface.\\n\" );\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "CODE/TOOLTIP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n//\tToolTip.h\n\n#ifdef WOLAPI_INTEGRATION\n\n#ifndef TOOLTIP_H\n#define TOOLTIP_H\n\n#include \"Gadget.h\"\n\n#define TOOLTIPTEXT_MAX_LEN\t\t100\n\n#define TOOLTIPDELAY\t\t\t400\t\t//\tMilliseconds\n\nclass ToolTipClass\n{\npublic:\n\tToolTipClass( GadgetClass* pGadget, const char* szText, int xShow, int yShow, bool bRightAlign = false, bool bIconList = false );\n\t~ToolTipClass()\n\t{\n\t\tdelete [] pSaveRect;\n\t}\n\n\tToolTipClass*\tGetToolTipHit();\n\tvoid\t\t\tShow();\n\tvoid\t\t\tUnshow();\n\tvoid\t\t\tMove( int xShow, int yShow );\n\tbool\t\t\tbOverDifferentLine() const;\n\n\tToolTipClass*\tnext;\t\t\t\t\t//\tNext tooltip in list of which *this is a part.\n\n\tGadgetClass*\tpGadget;\t\t\t\t\t\t\t//\tGadget to which this tooltip is bound.\n\n\tbool\t\t\tbRightAlign;\n\n\tbool\t\t\tbShowing;\n\tbool\t\t\tbIconList;\t\t\t//\tTrue if gadget is iconlist and line-specific tooltips are to be used.\n\nprotected:\n\tbool\t\t\tbGadgetHit() const;\n\n\tint\t\t\t\txShow;\n\tint\t\t\t\tyShow;\n\tint\t\t\t\twShow;\n\tint\t\t\t\thShow;\n\tchar\t\t\tszTip[ TOOLTIPTEXT_MAX_LEN + 1 ];\t//\tText to show as tip.\n\n\tchar*\t\t\tpSaveRect;\n\n\t//\tUsed only if bIconList.\n\tint\t\t\t\tiLastIconListIndex;\n\tbool\t\t\tbLastShowNoText;\n\tint\t\t\t\txLastShow;\n\tint\t\t\t\tyLastShow;\n\tint\t\t\t\twLastShow;\n};\n\n#endif\n\n#endif\n"
  },
  {
    "path": "CODE/TRACKER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TRACKER.CPP 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TRACKER.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/14/96                                                     *\n *                                                                                             *\n *                  Last Update : June 14, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Detach_This_From_All -- Detaches this object from all others.                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * Detach_This_From_All -- Detaches this object from all others.                               *\n *                                                                                             *\n *    This routine sweeps through all game objects and makes sure that it is no longer         *\n *    referenced by them. Typically, this is called in preparation for the object's death      *\n *    or limbo state.                                                                          *\n *                                                                                             *\n * INPUT:   target   -- This object expressed as a target number.                              *\n *                                                                                             *\n *          all      -- Is this object really in truly being removed from the game? The        *\n *                      answer would be false if the target was actually a stealth             *\n *                      tank that is cloaking. In such a case, the object should be removed    *\n *                      from all non-friendly tracking systems, but otherwise left alone.      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Detach_This_From_All(TARGET target, bool all)\n{\n\tint index;\n\tif (Target_Legal(target)) {\n\n\t\tfor (index = 0; index < Houses.Count(); index++) {\n\t\t\tHouses.Ptr(index)->Detach(target, all);\n\t\t}\n\t\tfor (index = 0; index < Teams.Count(); index++) {\n\t\t\tTeams.Ptr(index)->Detach(target, all);\n\t\t}\n\t\tfor (index = 0; index < TeamTypes.Count(); index++) {\n\t\t\tTeamTypes.Ptr(index)->Detach(target, all);\n\t\t}\n\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\tUnits.Ptr(index)->Detach(target, all);\n\t\t}\n\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\tVessels.Ptr(index)->Detach(target, all);\n\t\t}\n\t\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\t\tAircraft.Ptr(index)->Detach(target, all);\n\t\t}\n\t\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildings.Ptr(index)->Detach(target, all);\n\t\t}\n\t\tfor (index = 0; index < Bullets.Count(); index++) {\n\t\t\tBullets.Ptr(index)->Detach(target, all);\n\t\t}\n\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\tInfantry.Ptr(index)->Detach(target, all);\n\t\t}\n\t\tfor (index = 0; index < Anims.Count(); index++) {\n\t\t\tAnims.Ptr(index)->Detach(target, all);\n\t\t}\n\n\t\tMap.Detach(target, all);\n\n\t\tLogic.Detach(target, all);\n\n\t\tChronalVortex.Detach(target);\n\n\t\t/*\n\t\t**\tRemoving a trigger type must also remove all triggers that are dependant\n\t\t**\tupon that type.\n\t\t*/\n\t\tif (As_TriggerType(target) != NULL) {\n\t\t\tfor (int index = 0; index < Triggers.Count(); index++) {\n\t\t\t\tTriggerClass * tp = Triggers.Ptr(index);\n\n\t\t\t\tif (tp->Class->As_Target() == target) {\n\t\t\t\t\tDetach_This_From_All(tp->As_Target());\n\t\t\t\t\tdelete tp;\n\t\t\t\t\tindex--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (index = 0; index < Triggers.Count(); index++) {\n\t\t\tTriggers.Ptr(index)->Detach(target, all);\n\t\t}\n\t\tfor (index = 0; index < TriggerTypes.Count(); index++) {\n\t\t\tTriggerTypes.Ptr(index)->Detach(target, all);\n\t\t}\n\t}\n}\n\n\n\n\n\n"
  },
  {
    "path": "CODE/TRIGGER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TRIGGER.CPP 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TRIGGER.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/12/94                                                     *\n *                                                                                             *\n *                  Last Update : August 13, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Find_Or_Make -- Find or create a trigger of the type specified.                           *\n *   TriggerClass::As_Target -- Converts trigger to a target value                             *\n *   TriggerClass::Attaches_To -- Determines what trigger can attach to.                       *\n *   TriggerClass::Description -- Fetch a one line ASCII description of the trigger.           *\n *   TriggerClass::Detach -- Detach specified target from this trigger.                        *\n *   TriggerClass::Draw_It -- Draws this trigger as if it were part of a list box.             *\n *   TriggerClass::Init -- clears triggers for new scenario                                    *\n *   TriggerClass::Spring -- Spring the trigger (possibly).                                    *\n *   TriggerClass::TriggerClass -- constructor                                                 *\n *   TriggerClass::operator delete -- Returns a trigger to the special memory pool.            *\n *   TriggerClass::operator new -- 'new' operator                                              *\n *   TriggerClass::~TriggerClass -- Destructor for trigger objects.                            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n#if defined(CHEAT_KEYS) || defined(SCENARIO_EDITOR)\n/***********************************************************************************************\n * TriggerClass::Description -- Fetch a one line ASCII description of the trigger.             *\n *                                                                                             *\n *    In the rare (possibly never?) case of requiring a description for this trigger, then     *\n *    just have the model class generate a description and return that.                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with an ASCII description of this trigger.                                 *\n *                                                                                             *\n * WARNINGS:   see TriggerTypeClass::Description()                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * TriggerClass::Description(void) const\n{\n\treturn(Class->Description());\n}\n\n\n/***********************************************************************************************\n * TriggerClass::Draw_It -- Draws this trigger as if it were part of a list box.               *\n *                                                                                             *\n *    This routine is called when the trigger has been assigned to a list box. It will         *\n *    display a description of the trigger.                                                    *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TriggerClass::Draw_It(int , int x, int y, int width, int height, bool selected, TextPrintType flags) const\n{\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\tstatic int _tabs[] = {13,40};\n\tif ((flags & 0x0F) == TPF_6PT_GRAD || (flags & 0x0F) == TPF_EFNT) {\n\n\t\tif (selected) {\n\t\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\t\tLogicPage->Fill_Rect(x, y, x + width - 1, y + height - 1, scheme->Shadow);\n\t\t} else {\n\t\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t\t}\n\t\t}\n\n\t\tConquer_Clip_Text_Print(Description(), x, y, scheme, TBLACK, flags, width, _tabs);\n\t} else {\n\t\tConquer_Clip_Text_Print(Description(), x, y, (selected ? &ColorRemaps[PCOLOR_DIALOG_BLUE] : &ColorRemaps[PCOLOR_GREY]), TBLACK, flags, width, _tabs);\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * TriggerClass::TriggerClass -- constructor                                                   *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/28/1994 BR : Created.                                                                  *\n *=============================================================================================*/\nTriggerClass::TriggerClass(TriggerTypeClass * trigtype) :\n\tRTTI(RTTI_TRIGGER),\n\tID(Triggers.ID(this)),\n\tClass(trigtype),\n\tAttachCount(0),\n\tCell(0)\n{\n\tClass->Event1.Reset(Event1);\n\tClass->Event2.Reset(Event2);\n}\n\n\n/***********************************************************************************************\n * TriggerClass::~TriggerClass -- Destructor for trigger objects.                              *\n *                                                                                             *\n *    This destructor will update the house blockage value if necessary. No other action need  *\n *    be performed on trigger destruction.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTriggerClass::~TriggerClass(void)\n{\n\tif (GameActive && Class.Is_Valid() && (Class->Attaches_To() & ATTACH_GENERAL) != 0) {\n\t\tif (LogicTriggerID >= LogicTriggers.ID(this)) {\n\t\t\tLogicTriggerID--;\n\t\t\tif (LogicTriggerID < 0 && LogicTriggers.Count() == 0) {\n\t\t\t\tLogicTriggerID = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (GameActive && Class.Is_Valid() && (Class->Attaches_To() & ATTACH_MAP) != 0) {\n\t\tif (MapTriggerID >= MapTriggers.ID(this)) {\n\t\t\tMapTriggerID--;\n\t\t\tif (MapTriggerID < 0 && MapTriggers.Count() == 0) {\n\t\t\t\tMapTriggerID = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (GameActive && Class->House != HOUSE_NONE && Class->Action1.Action == TACTION_ALLOWWIN) {\n\t\tif (Houses.Ptr(Class->House)->Blockage) Houses.Ptr(Class->House)->Blockage--;\n\t\tHouses.Ptr(Class->House)->BorrowedTime = TICKS_PER_SECOND*4;\n\t}\n\tID = -1;\n}\n\n\n/***********************************************************************************************\n * TriggerClass::Init -- clears triggers for new scenario                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/29/1994 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid TriggerClass::Init(void)\n{\n\tTriggers.Free_All();\n}\n\n\n/***********************************************************************************************\n * TriggerClass::Spring -- Spring the trigger (possibly).                                      *\n *                                                                                             *\n *    This routine is called when a potential trigger even has occurred. The event is matched  *\n *    with the trigger event needed by this trigger. If the condition warrants, the trigger    *\n *    action is performed.                                                                     *\n *                                                                                             *\n * INPUT:   event    -- The event that is occurring.                                           *\n *                                                                                             *\n *          obj      -- If the trigger is attached to an object, this points to the object.    *\n *                                                                                             *\n *          cell     -- If the trigger is attached to a cell, this is the cell number.         *\n *                                                                                             *\n *          forced   -- Should the trigger be forced to execute regardless of the event?       *\n *                                                                                             *\n * OUTPUT:  bool; Was the trigger sprung?                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1996 JLB : Created.                                                                 *\n *   08/13/1996 JLB : Linked triggers supported.                                               *\n *=============================================================================================*/\nbool TriggerClass::Spring(TEventType event, ObjectClass * obj, CELL cell, bool forced)\n{\n\tassert(Triggers.ID(this) == ID);\n\n\tbool e1 = Class->Event1(Event1, event, Class->House, obj, forced);\n\tbool e2 = false;\n\tbool execute = false;\n\n\t/*\n\t**\tForced triggers must presume that the cell parameter is invalid. It then\n\t**\tuses the embedded cell value in the trigger as the official location where\n\t**\tthe trigger will detonate at.\n\t*/\n\tif (forced) {\n\t\tcell = Cell;\n\t} else {\n\n\t\t/*\n\t\t**\tDetermine if the trigger event is considered to have been sprung according to the\n\t\t**\tevent control value. This might require that both events be triggered, one event\n\t\t**\ttriggered, or either event triggered to activate the trigger action.\n\t\t*/\n\t\tswitch (Class->EventControl) {\n\t\t\tcase MULTI_ONLY:\n\t\t\t\texecute = e1;\n\t\t\t\tbreak;\n\n\t\t\tcase MULTI_AND:\n\t\t\t\te2 = Class->Event2(Event2, event, Class->House, obj, forced);\n\t\t\t\texecute = (e1 && e2);\n\t\t\t\tbreak;\n\n\t\t\tcase MULTI_LINKED:\n\t\t\tcase MULTI_OR:\n\t\t\t\te2 = Class->Event2(Event2, event, Class->House, obj, forced);\n\t\t\t\texecute = (e1 || e2);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tSee if the trigger is sprung with a qualifying event.\n\t*/\n\tif (execute || forced) {\n\n\t\t/*\n\t\t**\tVerify that the trigger event should really be sprung. Exceptions\n\t\t**\twould include semi-persistent triggers that don't actually\n\t\t**\tspring until all triggers have sprung.\n\t\t*/\n\t\tif (Class->IsPersistant == TriggerTypeClass::SEMIPERSISTANT) {\n\n\t\t\t/*\n\t\t\t** Detach ourselves from the object and record that there\n\t\t\t**\tis one less attachment to keep track of.\n\t\t\t*/\n\t\t\tif (obj) {\n\t\t\t\tobj->Trigger = NULL;\n\t\t\t}\n\t\t\tif (cell) {\n\t\t\t\tMap[cell].Trigger = NULL;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If we're attached to more objects, don't spring; otherwise, spring.\n\t\t\t** And, mark ourselves as volatile so we'll completely remove ourselves\n\t\t\t** from the game after we go off.\n\t\t\t*/\n\t\t\tAttachCount--;\n\t\t\tif (AttachCount > 0) {\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tFor linked trigger events, perform the action associated with the matching\n\t\t**\ttrigger event. Otherwise perform the action for both events.\n\t\t*/\n\t\tbool ok = false;\n\t\tHousesType hh = Class->House;\n\t\tif (Class->EventControl == MULTI_LINKED) {\n\t\t\tif (e1 || forced) ok |= Class->Action1(hh, obj, ID, cell);\n\t\t\tif (e2 && !forced) ok |= Class->Action2(hh, obj, ID, cell);\n\t\t} else {\n\n\t\t\tswitch (Class->ActionControl) {\n\t\t\t\tcase MULTI_ONLY:\n\t\t\t\t\tok |= Class->Action1(hh, obj, ID, cell);\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\tcase MULTI_AND:\n\t\t\t\t\tok |= Class->Action1(hh, obj, ID, cell);\n\t\t\t\t\tok |= Class->Action2(hh, obj, ID, cell);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!IsActive) return(true);\n\n\t\t/*\n\t\t**\tIf at least one action was performed, then consider this\n\t\t**\ttrigger to have completed and thus will be deleted if\n\t\t**\tnecessary.\n\t\t*/\n\t\tif (ok) {\n\t\t\t#ifdef CHEAT_KEYS\n\t\t\tMonoArray[DMONO_STRESS].Sub_Window(61, 1, 17, 11);\n\t\t\tMonoArray[DMONO_STRESS].Scroll();\n\t\t\tMonoArray[DMONO_STRESS].Sub_Window(61, 1, 18, 11);\n\t\t\tMonoArray[DMONO_STRESS].Set_Cursor(0, 10);\n\t\t\tMonoArray[DMONO_STRESS].Printf(\"%02d:%02d:%02d-%s\", Scen.Timer / TICKS_PER_HOUR, (Scen.Timer % TICKS_PER_HOUR)/TICKS_PER_MINUTE, (Scen.Timer % TICKS_PER_MINUTE)/TICKS_PER_SECOND, Class->IniName);\n\t\t\tMonoArray[DMONO_STRESS].Sub_Window();\n\t\t\t#endif\n\n\t\t\tif (Class->IsPersistant == TriggerTypeClass::VOLATILE || (Class->IsPersistant == TriggerTypeClass::SEMIPERSISTANT && AttachCount <= 1)) {\n\t\t\t\tDetach_This_From_All(As_Target(), true);\n\t\t\t\tdelete this;\n\t\t\t\treturn(true);\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tReset event data so that the event will\n\t\t\t\t**\trepeat as necessary.\n\t\t\t\t*/\n\t\t\t\tClass->Event1.Reset(Event1);\n\t\t\t\tClass->Event2.Reset(Event2);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TriggerClass::operator new -- 'new' operator                                                *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      pointer to new trigger                                                                 *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/28/1994 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid * TriggerClass::operator new(size_t )\n{\n\tvoid * ptr = Triggers.Allocate();\n\tif (ptr) {\n\t\t((TriggerClass *)ptr)->IsActive = true;\n\t}\n\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * TriggerClass::operator delete -- Returns a trigger to the special memory pool.              *\n *                                                                                             *\n *    This routine will return a previously allocated trigger object back to the memory        *\n *    pool from which it came.                                                                 *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to the trigger to return to the memory pool.                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TriggerClass::operator delete(void * pointer)\n{\n\tif (pointer) {\n\t\t((TriggerClass *)pointer)->IsActive = false;\n\t}\n\tTriggers.Free((TriggerClass *)pointer);\n}\n\n\n/***********************************************************************************************\n * TriggerClass::As_Target -- Converts trigger to a target value                               *\n *                                                                                             *\n *    Converts the trigger object into a target identifier.                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  TARGET value                                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTARGET TriggerClass::As_Target(void) const\n{\n\tassert(Triggers.ID(this) == ID);\n\n\treturn(Build_Target(RTTI_TRIGGER, ID));\n}\n\n\n/***********************************************************************************************\n * Find_Or_Make -- Find or create a trigger of the type specified.                             *\n *                                                                                             *\n *    This routine is used when, given a trigger type, an actual trigger object is needed.     *\n *    In this case, an existing trigger of the correct type must be located, or a trigger      *\n *    object must be created. In either case, this routine will return a trigger object that   *\n *    corresponds to the trigger type class specified.                                         *\n *                                                                                             *\n * INPUT:   trigtype -- Pointer to the trigger type to find (or create) a matching trigger     *\n *                      object.                                                                *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to a matching trigger object. If no more triggers could be       *\n *          allocated and no matching trigger could be found, then this routine will return    *\n *          NULL (a very rare case).                                                           *\n *                                                                                             *\n * WARNINGS:   This routine could return NULL.                                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTriggerClass * Find_Or_Make(TriggerTypeClass * trigtype)\n{\n\tif (!trigtype) return(NULL);\n\n\tfor (int index = 0; index < Triggers.Count(); index++) {\n\t\tif (trigtype == Triggers.Ptr(index)->Class) {\n\t\t\treturn(Triggers.Ptr(index));\n\t\t}\n\t}\n\n\t/*\n\t**\tNo trigger was found, so make one.\n\t*/\n\tTriggerClass * trig = new TriggerClass(trigtype);\n\treturn(trig);\n}\n\n\n/***********************************************************************************************\n * TriggerClass::Detach -- Detach specified target from this trigger.                          *\n *                                                                                             *\n *    This routine is called when the specified trigger MUST be detached from all references   *\n *    to it. The only reference maintained by a trigger is the reference to the trigger        *\n *    type class it is modeled after.                                                          *\n *                                                                                             *\n * INPUT:   target   -- The target identifier to remove all attachments to.                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   You must never detach the trigger type class from a trigger. Such a process     *\n *             will leave the trigger orphan and in a 'crash the game immediately if used'     *\n *             state. As such, this routine will throw an assertion if this is tried.          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TriggerClass::Detach(TARGET target, bool )\n{\n\tif (Is_Target_TriggerType(target)) {\n\t\tassert((TriggerTypeClass*)Class != As_TriggerType(target));\n//\t\tif (Class == As_TriggerType(target)) {\n//\t\t\tClass = NULL;\n//\t\t}\n\t}\n}\n"
  },
  {
    "path": "CODE/TRIGGER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TRIGGER.H 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TRIGGER.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/12/94                                                     *\n *                                                                                             *\n *                  Last Update : November 12, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TRIGGER_H\n#define TRIGGER_H\n\nclass TriggerClass {\n\tpublic:\n\t\tRTTIType RTTI;\n\t\tint ID;\n\n\t\tCCPtr<TriggerTypeClass> Class;\n\n\t\t/*\n\t\t**\tRecord of the \"already sprung\" flag for the events.\n\t\t*/\n\t\tTDEventClass Event1;\n\t\tTDEventClass Event2;\n\n\t\t/*\n\t\t**\tConstructor/Destructor\n\t\t*/\n\t\tTriggerClass(TriggerTypeClass * trigtype=NULL);\n\t\tTriggerClass(NoInitClass const & x) : Class(x), Event1(x), Event2(x) {};\n\t\t~TriggerClass(void);\n\n\t\t/*\n\t\t**\tInitialization: clears all triggers in preparation for new scenario\n\t\t*/\n\t\tstatic void Init(void);\n\n\t\t/*\n\t\t**\tProcessing routines\n\t\t*/\n\t\tbool  Spring(TEventType event=TEVENT_ANY, ObjectClass * object=0, CELL cell=0, bool forced=false);\n\t\tvoid Detach(TARGET target, bool all=true);\n\n\t\t/*\n\t\t**\tFile I/O routines\n\t\t*/\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\t\tvoid Code_Pointers(void) {};\n\t\tvoid Decode_Pointers(void) {};\n\n\t\t/*\n\t\t**\tUtility routines\n\t\t*/\n\t\tTARGET As_Target(void) const;\n\t\tchar const * Description(void) const;\n\t\tvoid Draw_It(int , int x, int y, int width, int height, bool selected, TextPrintType flags) const;\n\t\tchar const * Name(void) const {return(Class->Name());}\n\n\t\t/*\n\t\t**\tOverloaded operators\n\t\t*/\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t, void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void * ptr);\n\n\t\t/*\n\t\t**\tIf this trigger object is active, then this flag will be true. Trigger\n\t\t**\tobjects that are not active are either not yet created or have been\n\t\t**\tdeleted after fulfilling their action.\n\t\t*/\n\t\tunsigned IsActive:1;\n\n\t\t/*\n\t\t**\tThis value tells how many objects or cells this trigger is attached\n\t\t**\tto.  The Read_INI routine for all classes that point to a trigger must\n\t\t**\tincrement this value!\n\t\t*/\n\t\tint AttachCount;\n\n\t\t/*\n\t\t**\tThis value is used for triggers that can only exist in one cell. It is\n\t\t**\tneeded for such triggers that the exact location of the trigger is needed\n\t\t**\tduring processing but its location cannot be inferred from other data.\n\t\t**\tFor all other triggers, this value is ignored.\n\t\t*/\n\t\tCELL Cell;\n};\n\n\n\n\n#endif\n"
  },
  {
    "path": "CODE/TRIGTYPE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TRIGTYPE.CPP 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TRIGTYPE.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/05/96                                                     *\n *                                                                                             *\n *                  Last Update : July 9, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   TriggerTypeClass::As_Target -- Convert this trigger type object into a target value.      *\n *   TriggerTypeClass::Attaches_To -- Determines what trigger can attach to.                   *\n *   TriggerTypeClass::Build_INI_Entry -- Construct the INI entry into the buffer specified.   *\n *   TriggerTypeClass::Description -- Build a text description of the trigger type.            *\n *   TriggerTypeClass::Detach -- Removes attachments to the target object specified.           *\n *   TriggerTypeClass::Draw_It -- Draws this trigger as if it were a line in a list box.       *\n *   TriggerTypeClass::Edit -- Edit the trigger type through the scenario editor.              *\n *   TriggerTypeClass::Fill_In -- fills in trigger from the given INI entry                    *\n *   TriggerTypeClass::From_Name -- Convert an ASCII name into a trigger type pointer.         *\n *   TriggerTypeClass::Init -- Initialize the trigger type object management system.           *\n *   TriggerTypeClass::Read_INI -- reads triggers from the INI file                            *\n *   TriggerTypeClass::TriggerTypeClass -- Constructor for trigger class object.               *\n *   TriggerTypeClass::Write_INI -- Stores all trigger types to the INI database specified.    *\n *   TriggerTypeClass::operator delete -- Returns a trigger type class object back to the pool *\n *   TriggerTypeClass::operator new -- Allocates a trigger type class object.                  *\n *   TriggerTypeClass::~TriggerTypeClass -- Deleting a trigger type deletes associated triggers*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n#include\t\"trigtype.h\"\n\n\n/***********************************************************************************************\n * TriggerTypeClass::TriggerTypeClass -- Constructor for trigger class object.                 *\n *                                                                                             *\n *    This is the normal constructor for a trigger object. The trigger starts with no team     *\n *    members, no mission, and default values for all settings.                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTriggerTypeClass::TriggerTypeClass(void) :\n\tAbstractTypeClass(RTTI_TRIGGERTYPE, TriggerTypes.ID(this), TXT_NONE, \"x\"),\n\tIsPersistant(VOLATILE),\n\tEventControl(MULTI_ONLY),\n\tActionControl(MULTI_ONLY),\n\tHouse(HOUSE_SPAIN)\n{\n}\n\n\n/***********************************************************************************************\n * TriggerTypeClass::~TriggerTypeClass -- Deleting a trigger type deletes associated triggers. *\n *                                                                                             *\n *    When a trigger type is deleted, then all triggers that refer to that type must also      *\n *    be deleted as well. There can be no 'orphan' triggers in existence.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTriggerTypeClass::~TriggerTypeClass(void)\n{\n}\n\n\n/***********************************************************************************************\n * TriggerTypeClass::operator new -- Allocates a trigger type class object.                    *\n *                                                                                             *\n *    This routine will allocate a block of memory from the special trigger type object        *\n *    pool.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocated trigger type memory block. If there is     *\n *          no more block available in the pool, then NULL is returned.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * TriggerTypeClass::operator new(size_t )\n{\n\tvoid * ptr = TriggerTypes.Allocate();\n\tif (ptr) {\n\t\t((TriggerTypeClass *)ptr)->IsActive = true;\n\t}\n\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * TriggerTypeClass::operator delete -- Returns a trigger type class object back to the pool   *\n *                                                                                             *\n *    This routine will return a previously allocated trigger type object to the private       *\n *    memory pool from which it was allocated.                                                 *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the trigger type class to return to the pool.                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TriggerTypeClass::operator delete(void * ptr)\n{\n\tif (ptr) {\n\t\t((TriggerTypeClass *)ptr)->IsActive = false;\n\t}\n\tTriggerTypes.Free((TriggerTypeClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * TriggerTypeClass::As_Target -- Convert this trigger type object into a target value.        *\n *                                                                                             *\n *    Use this routine to take this trigger type class object and convert it into a            *\n *    target number.                                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the target number that represents this trigger type class object.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTARGET TriggerTypeClass::As_Target(void) const\n{\n\treturn(Build_Target(RTTI_TRIGGERTYPE, ID));\n}\n\n\n/***********************************************************************************************\n * TriggerTypeClass::Detach -- Removes attachments to the target object specified.             *\n *                                                                                             *\n *    When an object disappears from the game, it must be detached from all other objects that *\n *    may be referring to it. This routine will detach the specified target object from any    *\n *    references to it in this trigger type class.                                             *\n *                                                                                             *\n * INPUT:   target   -- The target object to be detached from this trigger type.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TriggerTypeClass::Detach(TARGET target, bool)\n{\n\tAction1.Detach(target);\n\tAction2.Detach(target);\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***********************************************************************************************\n * TriggerTypeClass::Edit -- Edit the trigger type through the scenario editor.                *\n *                                                                                             *\n *    This is the scenario editor interface to a trigger type class object. It brings up a     *\n *    fancy schmancy dialog to allow full edit control of the trigger type.                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the \"OK\" button pressed? A false return value indicates that the edits   *\n *                to this trigger type class object should be rejected.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TriggerTypeClass::Edit(void)\n{\n\tenum {\n\t\t/*\n\t\t**\tDialog position and dimensions.\n\t\t*/\n\t\tD_DIALOG_W = 320 + 100,\n\t\tD_DIALOG_H = 200 + 20,\n\t\tD_DIALOG_X = 0,\n\t\tD_DIALOG_Y = 0,\n\n\t\t/*\n\t\t**\tEvent entry list box coordinates and dimensions.\n\t\t*/\n\t\tE1_X=D_DIALOG_X+45,\n\t\tE1_Y=D_DIALOG_Y+65,\n\t\tE2_X=E1_X,\n\t\tE2_Y=E1_Y+22,\n\t\tE_WIDTH=160,\n\t\tE_HEIGHT=8*5,\n\n\t\t/*\n\t\t**\tEvent optional data entry coordinates and dimensions.\n\t\t*/\n\t\tED1_X=E1_X+E_WIDTH+20,\n\t\tED1_Y=E1_Y,\n\t\tED2_X=ED1_X,\n\t\tED2_Y=E2_Y,\n\n\t\tED_WIDTH=95,\n\t\tED_HEIGHT=8*5,\n\n\t\t/*\n\t\t**\tAction entry list box coordinates.\n\t\t*/\n\t\tA1_X=E1_X,\n\t\tA1_Y=D_DIALOG_Y+120,\n\t\tA2_X=E1_X,\n\t\tA2_Y=A1_Y+22,\n\n\t\t/*\n\t\t**\tAction optional data entry coordinates.\n\t\t*/\n\t\tAD1_X=A1_X+E_WIDTH+20,\n\t\tAD1_Y=A1_Y,\n\t\tAD2_X=AD1_X,\n\t\tAD2_Y=A2_Y,\n\n\t\t/*\n\t\t**\tMisc control values.\n\t\t*/\n\t\tGENERAL_SIZE=10,\t\t\t\t// Text length for general data entry fields.\n\t\tENTRY_SIZE=35,\t\t\t\t\t// Maximum size of event or action description text.\n\t\tWAYPOINT_SIZE=3,\t\t\t\t// Text length maximum for waypoint entry.\n\t\tTEAM_SIZE=10,\t\t\t\t\t// Team name text entry field length.\n\t\tDESC_SIZE=35\t\t\t\t\t// Maximum length of object full name description.\n\t};\n\n\t/*\n\t**\tButton enumerations:\n\t*/\n\tenum {\n\t\tEVENT_LIST=100,\t\t\t\t// Primary event list.\n\t\tEVENT_LIST2,\t\t\t\t\t// Secondary event list.\n\t\tACTION_LIST,\t\t\t\t\t// Primary action list.\n\t\tACTION_LIST2,\t\t\t\t\t// Secondary action list.\n\t\tNAME_EDIT,\t\t\t\t\t\t// Trigger name edit field.\n\t\tDATA_SPEECH1,\t\t\t\t\t// Primary action speech.\n\t\tDATA_SPEECH2,\t\t\t\t\t// Secondary action speech.\n\t\tDATA_THEME1,\t\t\t\t\t// Primary action theme.\n\t\tDATA_THEME2,\t\t\t\t\t// Secondary action theme.\n\t\tDATA_MOVIE1,\t\t\t\t\t// Primary action movie.\n\t\tDATA_MOVIE2,\t\t\t\t\t// Secondary action movie.\n\t\tDATA_SOUND1,\t\t\t\t\t// Primary action sound effect.\n\t\tDATA_SOUND2,\t\t\t\t\t// Secondary action sound effect.\n\t\tDATA_SPECIAL1,\t\t\t\t\t// Primary action special weapon.\n\t\tDATA_SPECIAL2,\t\t\t\t\t// Secondary action special weapon.\n\t\tDATA_EDIT,\t\t\t\t\t\t// Primary event waypoint data field.\n\t\tDATA_EDIT2,\t\t\t\t\t\t// Secondary event waypoint data field.\n\t\tDATA_EDIT3,\t\t\t\t\t\t// Primary action waypoint data field.\n\t\tDATA_EDIT4,\t\t\t\t\t\t// Secondary action waypoint data field.\n\t\tDATA_HTYPE1,\t\t\t\t\t// Primary event house choice list.\n\t\tDATA_HTYPE2,\t\t\t\t\t// Secondary event house choice list.\n\t\tDATA_HTYPE3,\t\t\t\t\t// Primary action house choice list.\n\t\tDATA_HTYPE4,\t\t\t\t\t// Secondary action house choice list.\n\t\tDATA_BOOLTYPE1,\t\t\t\t// Primary action boolean data list.\n\t\tDATA_BOOLTYPE2,\t\t\t\t// Secondary action boolean data list.\n\t\tDATA_GENERAL1,\t\t\t\t\t// Primary event general data field.\n\t\tDATA_GENERAL2,\t\t\t\t\t// Secondary event general data field.\n\t\tDATA_GENERAL3,\t\t\t\t\t// Primary action general data field.\n\t\tDATA_GENERAL4,\t\t\t\t\t// Secondary action general data field.\n\t\tDATA_BTYPE1,\t\t\t\t\t// Primary event building type list.\n\t\tDATA_BTYPE2,\t\t\t\t\t// Secondary event building type list.\n\t\tDATA_ITYPE1,\t\t\t\t\t// Primary event infantry type list.\n\t\tDATA_ITYPE2,\t\t\t\t\t// Secondary event infantry type list.\n\t\tDATA_ATYPE1,\t\t\t\t\t// Primary event aircraft type list.\n\t\tDATA_ATYPE2,\t\t\t\t\t// Secondary event aircraft type list.\n\t\tDATA_UTYPE1,\t\t\t\t\t// Primary event unit type list.\n\t\tDATA_UTYPE2,\t\t\t\t\t// Secondary event unit type list.\n\t\tDATA_TTYPE1,\t\t\t\t\t// Primary event team type entry list.\n\t\tDATA_TTYPE2,\t\t\t\t\t// Secondary event team type entry list.\n\t\tDATA_TTYPE3,\t\t\t\t\t// Primary action team type entry list.\n\t\tDATA_TTYPE4,\t\t\t\t\t// Secondary action team type entry list.\n\t\tDATA_TRTYPE1,\t\t\t\t\t// Primary action trigger list.\n\t\tDATA_TRTYPE2,\t\t\t\t\t// Secondary action trigger list.\n\t\tBUTTON_HOUSE,\t\t\t\t\t// House ownership for this trigger.\n\t\tBUTTON_PERSISTANCE,\t\t\t// Persistence of this trigger.\n\t\tBUTTON_OK,\t\t\t\t\t\t// Ok button - save and exit.\n\t\tBUTTON_CANCEL,\t\t\t\t\t// Cancel button - just exit.\n\t\tBUTTON_ACTION,\t\t\t\t\t// Multiple action control button.\n\t\tBUTTON_EVENT,\t\t\t\t\t// Multiple event control button.\n\t};\n\n\t/*\n\t**\tDialog variables:\n\t*/\n\tbool cancel = false;\t\t\t\t\t\t\t\t// true = user cancels\n\tint i;\t\t\t\t\t\t\t\t\t\t\t\t// loop counter\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass * commands = NULL;\t\t\t\t// the button list\n\n\t/*\n\t**\tList of events allowed.\n\t*/\n\tchar eventtext[ENTRY_SIZE] = \"\";\n\tTDropListClass<EventChoiceClass *> event1list(EVENT_LIST, eventtext, sizeof(eventtext),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tE1_X, E1_Y, E_WIDTH, E_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar event2text[ENTRY_SIZE] = \"\";\n\tTDropListClass<EventChoiceClass *> event2list(EVENT_LIST2, event2text, sizeof(event2text),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tE2_X, E2_Y, E_WIDTH, E_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (TEventType event = TEVENT_FIRST; event < TEVENT_COUNT; event++) {\n\t\tevent1list.Add_Item(&EventChoices[event]);\n\t\tevent2list.Add_Item(&EventChoices[event]);\n\t}\n\n\tPBubble_Sort(&event1list[0], event1list.Count());\n\tPBubble_Sort(&event2list[0], event2list.Count());\n\n\tif (Event1.Event == TEVENT_NONE) Event1.Event = TEVENT_FIRST;\n\tevent1list.Set_Selected_Index(&EventChoices[Event1.Event]);\n\tif (Event2.Event == TEVENT_NONE) Event2.Event = TEVENT_FIRST;\n\tevent2list.Set_Selected_Index(&EventChoices[Event2.Event]);\n\n\t/*\n\t**\tList of actions allowed.\n\t*/\n\tchar actiontext[ENTRY_SIZE] = \"\";\n\tTDropListClass<ActionChoiceClass *> action1list(ACTION_LIST, actiontext, sizeof(actiontext),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tA1_X, A1_Y, E_WIDTH, E_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar action2text[ENTRY_SIZE] = \"\";\n\tTDropListClass<ActionChoiceClass *> action2list(ACTION_LIST2, action2text, sizeof(action2text),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tA2_X, A2_Y, E_WIDTH, E_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (TActionType action = TACTION_FIRST; action < TACTION_COUNT; action++) {\n\t\taction1list.Add_Item(&ActionChoices[action]);\n\t\taction2list.Add_Item(&ActionChoices[action]);\n\t}\n\n\tPBubble_Sort(&action1list[0], action1list.Count());\n\tPBubble_Sort(&action2list[0], action2list.Count());\n\n\tif (Action1.Action == ACTION_NONE) Action1.Action = TACTION_FIRST;\n\taction1list.Set_Selected_Index(&ActionChoices[Action1.Action]);\n\tif (Action2.Action == ACTION_NONE) Action2.Action = TACTION_FIRST;\n\taction2list.Set_Selected_Index(&ActionChoices[Action2.Action]);\n\n\t/*\n\t**\tOptional waypoint entry field.\n\t*/\n\tchar way1[WAYPOINT_SIZE] = \"A\";\n\tEditClass way1data(DATA_EDIT, way1, sizeof(way1), TPF_EFNT | TPF_NOSHADOW,\n\t\tED1_X, ED1_Y, ED_WIDTH, 9, EditClass::ALPHA);\n\tif (Event_Needs(Event1.Event) == NEED_WAYPOINT) {\n\t\tif (Event1.Data.Value < 26) {\n\t\t\tsprintf(way1data.Get_Text(), \"%c\", Event1.Data.Value + 'A');\n\t\t} else {\n\t\t\tsprintf(way1data.Get_Text(), \"%c%c\", (Event1.Data.Value / 26) + 'A'-1, (Event1.Data.Value % 26) + 'A');\n\t\t}\n\t}\n\n\tchar way2[WAYPOINT_SIZE] = \"A\";\n\tEditClass way2data(DATA_EDIT2, way2, sizeof(way2), TPF_EFNT | TPF_NOSHADOW,\n\t\tED2_X, ED2_Y, ED_WIDTH, 9, EditClass::ALPHA);\n\tif (Event_Needs(Event2.Event) == NEED_WAYPOINT) {\n\t\tif (Event2.Data.Value < 26) {\n\t\t\tsprintf(way2data.Get_Text(), \"%c\", Event2.Data.Value + 'A');\n\t\t} else {\n\t\t\tsprintf(way2data.Get_Text(), \"%c%c\", (Event2.Data.Value / 26) + 'A'-1, (Event2.Data.Value % 26) + 'A');\n\t\t}\n\t}\n\n\tchar way3[WAYPOINT_SIZE] = \"A\";\n\tEditClass way3data(DATA_EDIT3, way3, sizeof(way3), TPF_EFNT | TPF_NOSHADOW,\n\t\tAD1_X, AD1_Y, ED_WIDTH, 9, EditClass::ALPHA);\n\tif (Action_Needs(Action1.Action) == NEED_WAYPOINT) {\n\t\tif (Action1.Data.Value < 26) {\n\t\t\tsprintf(way3data.Get_Text(), \"%c\", Action1.Data.Value + 'A');\n\t\t} else {\n\t\t\tsprintf(way3data.Get_Text(), \"%c%c\", (Action1.Data.Value / 26) + 'A'-1, (Action1.Data.Value % 26) + 'A');\n\t\t}\n\t}\n\n\tchar way4[WAYPOINT_SIZE] = \"A\";\n\tEditClass way4data(DATA_EDIT4, way4, sizeof(way4), TPF_EFNT | TPF_NOSHADOW,\n\t\tAD2_X, AD2_Y, ED_WIDTH, 9, EditClass::ALPHA);\n\tif (Action_Needs(Action2.Action) == NEED_WAYPOINT) {\n\t\tif (Action2.Data.Value < 26) {\n\t\t\tsprintf(way4data.Get_Text(), \"%c\", Action2.Data.Value + 'A');\n\t\t} else {\n\t\t\tsprintf(way4data.Get_Text(), \"%c%c\", (Action2.Data.Value / 26) + 'A'-1, (Action2.Data.Value % 26) + 'A');\n\t\t}\n\t}\n\n\t/*\n\t**\tOptional event data entry field.\n\t*/\n\tchar databuf1[GENERAL_SIZE] = \"\";\n\tEditClass event1data(DATA_GENERAL1, databuf1, sizeof(databuf1),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tED1_X, ED1_Y, ED_WIDTH, 9, EditClass::NUMERIC);\n\tswitch (Event_Needs(Event1.Event)) {\n\t\tcase NEED_TIME:\n\t\tcase NEED_NUMBER:\n\t\t\tsprintf(event1data.Get_Text(), \"%d\", Event1.Data.Value);\n\t\t\tbreak;\n\t}\n\n\tchar databuf2[GENERAL_SIZE] = \"\";\n\tEditClass event2data(DATA_GENERAL2, databuf2, sizeof(databuf2),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tED2_X, ED2_Y, ED_WIDTH, 9, EditClass::NUMERIC);\n\tswitch (Event_Needs(Event2.Event)) {\n\t\tcase NEED_TIME:\n\t\tcase NEED_NUMBER:\n\t\t\tsprintf(event2data.Get_Text(), \"%d\", Event2.Data.Value);\n\t\t\tbreak;\n\t}\n\n\tchar actionbuf1[GENERAL_SIZE] = \"\";\n\tEditClass action1data(DATA_GENERAL3, actionbuf1, sizeof(actionbuf1),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD1_X, AD1_Y, ED_WIDTH, 9, EditClass::NUMERIC);\n\tswitch (Action_Needs(Action1.Action)) {\n\t\tcase NEED_NUMBER:\n\t\t\tsprintf(action1data.Get_Text(), \"%d\", Action1.Data.Value);\n\t\t\tbreak;\n\t}\n\n\tchar actionbuf2[GENERAL_SIZE] = \"\";\n\tEditClass action2data(DATA_GENERAL4, actionbuf2, sizeof(actionbuf2),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD2_X, AD2_Y, ED_WIDTH, 9, EditClass::NUMERIC);\n\tswitch (Action_Needs(Action2.Action)) {\n\t\tcase NEED_NUMBER:\n\t\t\tsprintf(action2data.Get_Text(), \"%d\", Action2.Data.Value);\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tOptional team entry list.\n\t*/\n\tchar tbuf1[TEAM_SIZE] = \"\";\n\tDropListClass ttype1list(DATA_TTYPE1, tbuf1, sizeof(tbuf1),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tED1_X, ED1_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar tbuf2[TEAM_SIZE] = \"\";\n\tDropListClass ttype2list(DATA_TTYPE2, tbuf2, sizeof(tbuf2),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tED2_X, ED2_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar tbuf3[TEAM_SIZE] = \"\";\n\tDropListClass ttype3list(DATA_TTYPE3, tbuf3, sizeof(tbuf3),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD1_X, AD1_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar tbuf4[TEAM_SIZE] = \"\";\n\tDropListClass ttype4list(DATA_TTYPE4, tbuf4, sizeof(tbuf4),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD2_X, AD2_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tfor (int index = 0; index < TeamTypes.Count(); index++) {\n\t\tttype1list.Add_Item(TeamTypes.Ptr(index)->IniName);\n\t\tttype2list.Add_Item(TeamTypes.Ptr(index)->IniName);\n\t\tttype3list.Add_Item(TeamTypes.Ptr(index)->IniName);\n\t\tttype4list.Add_Item(TeamTypes.Ptr(index)->IniName);\n\t}\n\n\tif (Event1.Team.Is_Valid()) {\n\t\tttype1list.Set_Selected_Index(Event1.Team->IniName);\n\t} else {\n\t\tttype1list.Set_Selected_Index(0);\n\t}\n\tif (Event2.Team.Is_Valid()) {\n\t\tttype2list.Set_Selected_Index(Event2.Team->IniName);\n\t} else {\n\t\tttype2list.Set_Selected_Index(0);\n\t}\n\tif (Action1.Team.Is_Valid()) {\n\t\tttype3list.Set_Selected_Index(Action1.Team->IniName);\n\t} else {\n\t\tttype3list.Set_Selected_Index(0);\n\t}\n\tif (Action2.Team.Is_Valid()) {\n\t\tttype4list.Set_Selected_Index(Action2.Team->IniName);\n\t} else {\n\t\tttype4list.Set_Selected_Index(0);\n\t}\n\n\t/*\n\t**\tOptional trigger entry list.\n\t*/\n\tchar trbuf1[TEAM_SIZE] = \"\";\n\tDropListClass trtype1list(DATA_TRTYPE1, trbuf1, sizeof(trbuf1),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD1_X, AD1_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar trbuf2[TEAM_SIZE] = \"\";\n\tDropListClass trtype2list(DATA_TRTYPE2, trbuf2, sizeof(trbuf2),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD2_X, AD2_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tfor (index = 0; index < TriggerTypes.Count(); index++) {\n\t\ttrtype1list.Add_Item(TriggerTypes.Ptr(index)->IniName);\n\t\ttrtype2list.Add_Item(TriggerTypes.Ptr(index)->IniName);\n\t}\n\n\tif (Action1.Trigger.Is_Valid()) {\n\t\ttrtype1list.Set_Selected_Index(Action1.Trigger->IniName);\n\t} else {\n\t\ttrtype1list.Set_Selected_Index(0);\n\t}\n\tif (Action2.Trigger.Is_Valid()) {\n\t\ttrtype2list.Set_Selected_Index(Action2.Trigger->IniName);\n\t} else {\n\t\ttrtype2list.Set_Selected_Index(0);\n\t}\n\n\t/*\n\t**\tOptional boolean value list.\n\t*/\n\tchar boolbuf1[TEAM_SIZE] = \"\";\n\tDropListClass booltype1list(DATA_BOOLTYPE1, boolbuf1, sizeof(boolbuf1),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD1_X, AD1_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar boolbuf2[TEAM_SIZE] = \"\";\n\tDropListClass booltype2list(DATA_BOOLTYPE2, boolbuf2, sizeof(boolbuf2),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD2_X, AD2_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tbooltype1list.Add_Item(\"OFF\");\n\tbooltype1list.Add_Item(\"ON\");\n\tbooltype2list.Add_Item(\"OFF\");\n\tbooltype2list.Add_Item(\"ON\");\n\n\tbooltype1list.Set_Selected_Index(Action1.Data.Bool);\n\tbooltype2list.Set_Selected_Index(Action2.Data.Bool);\n\n\t/*\n\t**\tOptional musical theme choice list.\n\t*/\n\tchar themebuf1[DESC_SIZE] = \"\";\n\tDropListClass themetype1list(DATA_THEME1, themebuf1, sizeof(themebuf1),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD1_X, AD1_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar themebuf2[DESC_SIZE] = \"\";\n\tDropListClass themetype2list(DATA_THEME2, themebuf2, sizeof(themebuf2),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD2_X, AD2_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tfor (ThemeType theme = THEME_FIRST; theme < THEME_COUNT; theme++) {\n\t\tthemetype1list.Add_Item(Theme.Full_Name(theme));\n\t\tthemetype2list.Add_Item(Theme.Full_Name(theme));\n\t}\n\n\tif (Action_Needs(Action1.Action) == NEED_THEME) {\n\t\tthemetype1list.Set_Selected_Index(Action1.Data.Theme);\n\t} else {\n\t\tthemetype1list.Set_Selected_Index(0);\n\t}\n\tif (Action_Needs(Action2.Action) == NEED_THEME) {\n\t\tthemetype2list.Set_Selected_Index(Action2.Data.Theme);\n\t} else {\n\t\tthemetype2list.Set_Selected_Index(0);\n\t}\n\n\t/*\n\t**\tOptional movie list.\n\t*/\n\tchar moviebuf1[DESC_SIZE] = \"\";\n\tDropListClass movietype1list(DATA_MOVIE1, moviebuf1, sizeof(moviebuf1),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD1_X, AD1_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar moviebuf2[DESC_SIZE] = \"\";\n\tDropListClass movietype2list(DATA_MOVIE2, moviebuf2, sizeof(moviebuf2),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD2_X, AD2_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tfor (VQType movie = VQ_FIRST; movie < VQ_COUNT; movie++) {\n\t\tmovietype1list.Add_Item(VQName[movie]);\n\t\tmovietype2list.Add_Item(VQName[movie]);\n\t}\n\n\tif (Action_Needs(Action1.Action) == NEED_MOVIE) {\n\t\tmovietype1list.Set_Selected_Index(Action1.Data.Movie);\n\t} else {\n\t\tmovietype1list.Set_Selected_Index(0);\n\t}\n\tif (Action_Needs(Action2.Action) == NEED_MOVIE) {\n\t\tmovietype2list.Set_Selected_Index(Action2.Data.Movie);\n\t} else {\n\t\tmovietype2list.Set_Selected_Index(0);\n\t}\n\n\t/*\n\t**\tOptional sound effect list.\n\t*/\n\tchar soundbuf1[DESC_SIZE] = \"\";\n\tDropListClass soundtype1list(DATA_SOUND1, soundbuf1, sizeof(soundbuf1),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD1_X, AD1_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar soundbuf2[DESC_SIZE] = \"\";\n\tDropListClass soundtype2list(DATA_SOUND2, soundbuf2, sizeof(soundbuf2),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD2_X, AD2_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tfor (VocType sound = VOC_FIRST; sound < VOC_COUNT; sound++) {\n\t\tsoundtype1list.Add_Item(Voc_Name(sound));\n\t\tsoundtype2list.Add_Item(Voc_Name(sound));\n\t}\n\n\tif (Action_Needs(Action1.Action) == NEED_SOUND) {\n\t\tsoundtype1list.Set_Selected_Index(Action1.Data.Sound);\n\t} else {\n\t\tsoundtype1list.Set_Selected_Index(0);\n\t}\n\tif (Action_Needs(Action2.Action) == NEED_SOUND) {\n\t\tsoundtype2list.Set_Selected_Index(Action2.Data.Sound);\n\t} else {\n\t\tsoundtype2list.Set_Selected_Index(0);\n\t}\n\n\t/*\n\t**\tOptional speech effect list.\n\t*/\n\tchar speechbuf1[DESC_SIZE] = \"\";\n\tDropListClass speechtype1list(DATA_SPEECH1, speechbuf1, sizeof(speechbuf1),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD1_X, AD1_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar speechbuf2[DESC_SIZE] = \"\";\n\tDropListClass speechtype2list(DATA_SPEECH2, speechbuf2, sizeof(speechbuf2),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD2_X, AD2_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tfor (VoxType speech = VOX_FIRST; speech < VOX_COUNT; speech++) {\n\t\tspeechtype1list.Add_Item(Speech_Name(speech));\n\t\tspeechtype2list.Add_Item(Speech_Name(speech));\n\t}\n\n\tif (Action_Needs(Action1.Action) == NEED_SPEECH) {\n\t\tspeechtype1list.Set_Selected_Index(Action1.Data.Speech);\n\t} else {\n\t\tspeechtype1list.Set_Selected_Index(0);\n\t}\n\tif (Action_Needs(Action2.Action) == NEED_SPEECH) {\n\t\tspeechtype2list.Set_Selected_Index(Action2.Data.Speech);\n\t} else {\n\t\tspeechtype2list.Set_Selected_Index(0);\n\t}\n\n\t/*\n\t**\tOptional building type entry list.\n\t*/\n\tchar bbuf1[DESC_SIZE] = \"\";\n\tDropListClass btype1list(DATA_BTYPE1, bbuf1, sizeof(bbuf1),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tED1_X, ED1_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar bbuf2[DESC_SIZE] = \"\";\n\tDropListClass btype2list(DATA_BTYPE2, bbuf2, sizeof(bbuf2),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tED2_X, ED2_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tfor (StructType ss = STRUCT_FIRST; ss < STRUCT_COUNT; ss++) {\n\t\tbtype1list.Add_Item(Text_String(BuildingTypeClass::As_Reference(ss).Full_Name()));\n\t\tbtype2list.Add_Item(Text_String(BuildingTypeClass::As_Reference(ss).Full_Name()));\n\t}\n\n\tif (Event_Needs(Event1.Event) == NEED_STRUCTURE) {\n\t\tbtype1list.Set_Selected_Index(Event1.Data.Structure);\n\t} else {\n\t\tbtype1list.Set_Selected_Index(0);\n\t}\n\tif (Event_Needs(Event2.Event) == NEED_STRUCTURE) {\n\t\tbtype2list.Set_Selected_Index(Event2.Data.Structure);\n\t} else {\n\t\tbtype2list.Set_Selected_Index(0);\n\t}\n\n\t/*\n\t**\tOptional infantry type entry list.\n\t*/\n\tchar ibuf1[DESC_SIZE] = \"\";\n\tDropListClass itype1list(DATA_ITYPE1, ibuf1, sizeof(ibuf1),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tED1_X, ED1_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar ibuf2[DESC_SIZE] = \"\";\n\tDropListClass itype2list(DATA_ITYPE2, ibuf2, sizeof(ibuf2),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tED2_X, ED2_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tfor (InfantryType ii = INFANTRY_FIRST; ii < INFANTRY_COUNT; ii++) {\n\t\titype1list.Add_Item(Text_String(InfantryTypeClass::As_Reference(ii).Full_Name()));\n\t\titype2list.Add_Item(Text_String(InfantryTypeClass::As_Reference(ii).Full_Name()));\n\t}\n\n\tif (Event_Needs(Event1.Event) == NEED_INFANTRY) {\n\t\titype1list.Set_Selected_Index(Event1.Data.Infantry);\n\t} else {\n\t\titype1list.Set_Selected_Index(0);\n\t}\n\tif (Event_Needs(Event2.Event) == NEED_INFANTRY) {\n\t\titype2list.Set_Selected_Index(Event2.Data.Infantry);\n\t} else {\n\t\titype2list.Set_Selected_Index(0);\n\t}\n\n\t/*\n\t**\tOptional aircraft type entry list.\n\t*/\n\tchar abuf1[DESC_SIZE] = \"\";\n\tDropListClass atype1list(DATA_ATYPE1, abuf1, sizeof(abuf1),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tED1_X, ED1_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar abuf2[DESC_SIZE] = \"\";\n\tDropListClass atype2list(DATA_ATYPE2, abuf2, sizeof(abuf2),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tED2_X, ED2_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tfor (AircraftType aa = AIRCRAFT_FIRST; aa < AIRCRAFT_COUNT; aa++) {\n\t\tatype1list.Add_Item(Text_String(AircraftTypeClass::As_Reference(aa).Full_Name()));\n\t\tatype2list.Add_Item(Text_String(AircraftTypeClass::As_Reference(aa).Full_Name()));\n\t}\n\n\tif (Event_Needs(Event1.Event) == NEED_AIRCRAFT) {\n\t\tatype1list.Set_Selected_Index(Event1.Data.Aircraft);\n\t} else {\n\t\tatype1list.Set_Selected_Index(0);\n\t}\n\tif (Event_Needs(Event2.Event) == NEED_AIRCRAFT) {\n\t\tatype2list.Set_Selected_Index(Event2.Data.Aircraft);\n\t} else {\n\t\tatype2list.Set_Selected_Index(0);\n\t}\n\n\t/*\n\t**\tOptional unit type entry list.\n\t*/\n\tchar ubuf1[DESC_SIZE] = \"\";\n\tDropListClass utype1list(DATA_UTYPE1, ubuf1, sizeof(ubuf1),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tED1_X, ED1_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar ubuf2[DESC_SIZE] = \"\";\n\tDropListClass utype2list(DATA_UTYPE2, ubuf2, sizeof(ubuf2),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tED2_X, ED2_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tfor (UnitType uu = UNIT_FIRST; uu < UNIT_COUNT; uu++) {\n\t\tutype1list.Add_Item(Text_String(UnitTypeClass::As_Reference(uu).Full_Name()));\n\t\tutype2list.Add_Item(Text_String(UnitTypeClass::As_Reference(uu).Full_Name()));\n\t}\n\n\tif (Event_Needs(Event1.Event) == NEED_UNIT) {\n\t\tutype1list.Set_Selected_Index(Event1.Data.Unit);\n\t} else {\n\t\tutype1list.Set_Selected_Index(0);\n\t}\n\tif (Event_Needs(Event2.Event) == NEED_UNIT) {\n\t\tutype2list.Set_Selected_Index(Event2.Data.Unit);\n\t} else {\n\t\tutype2list.Set_Selected_Index(0);\n\t}\n\n\t/*\n\t**\tOptional house type entry list.\n\t*/\n\tchar housebuf1[DESC_SIZE] = \"\";\n\tDropListClass htype1list(DATA_HTYPE1, housebuf1, sizeof(housebuf1),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tED1_X, ED1_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar housebuf2[DESC_SIZE] = \"\";\n\tDropListClass htype2list(DATA_HTYPE2, housebuf2, sizeof(housebuf2),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tED2_X, ED2_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar housebuf3[DESC_SIZE] = \"\";\n\tDropListClass htype3list(DATA_HTYPE3, housebuf3, sizeof(housebuf3),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD1_X, AD1_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar housebuf4[DESC_SIZE] = \"\";\n\tDropListClass htype4list(DATA_HTYPE4, housebuf4, sizeof(housebuf4),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD2_X, AD2_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tfor (HousesType hh = HOUSE_FIRST; hh < HOUSE_COUNT; hh++) {\n\t\thtype1list.Add_Item(HouseTypeClass::As_Reference(hh).IniName);\n\t\thtype2list.Add_Item(HouseTypeClass::As_Reference(hh).IniName);\n\t\thtype3list.Add_Item(HouseTypeClass::As_Reference(hh).IniName);\n\t\thtype4list.Add_Item(HouseTypeClass::As_Reference(hh).IniName);\n\t}\n\n\tif (Event_Needs(Event1.Event) == NEED_HOUSE) {\n\t\thtype1list.Set_Selected_Index(Event1.Data.House);\n\t} else {\n\t\thtype1list.Set_Selected_Index(0);\n\t}\n\tif (Event_Needs(Event2.Event) == NEED_HOUSE) {\n\t\thtype2list.Set_Selected_Index(Event2.Data.House);\n\t} else {\n\t\thtype2list.Set_Selected_Index(0);\n\t}\n\tif (Action_Needs(Action1.Action) == NEED_HOUSE) {\n\t\thtype3list.Set_Selected_Index(Action1.Data.House);\n\t} else {\n\t\thtype3list.Set_Selected_Index(0);\n\t}\n\tif (Action_Needs(Action2.Action) == NEED_HOUSE) {\n\t\thtype4list.Set_Selected_Index(Action2.Data.House);\n\t} else {\n\t\thtype4list.Set_Selected_Index(0);\n\t}\n\n\t/*\n\t**\tOptional special weapon list.\n\t*/\n\tchar special1[DESC_SIZE] = \"\";\n\tDropListClass spc1(DATA_SPECIAL1, special1, sizeof(special1),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD1_X, AD1_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar special2[DESC_SIZE] = \"\";\n\tDropListClass spc2(DATA_SPECIAL2, special2, sizeof(special2),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD2_X, AD2_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (SpecialWeaponType spec = SPC_FIRST; spec < SPC_COUNT; spec++) {\n\t\tspc1.Add_Item(SpecialWeaponName[spec]);\n\t\tspc2.Add_Item(SpecialWeaponName[spec]);\n\t}\n\tif ((unsigned)Action1.Data.Special < SPC_COUNT) {\n\t\tspc1.Set_Selected_Index(Action1.Data.Special);\n\t} else {\n\t\tspc1.Set_Selected_Index(0);\n\t}\n\tif ((unsigned)Action2.Data.Special < SPC_COUNT) {\n\t\tspc2.Set_Selected_Index(Action2.Data.Special);\n\t} else {\n\t\tspc2.Set_Selected_Index(0);\n\t}\n\n\t/*\n\t**\tOptional quarry type.\n\t*/\n\tchar quarry1[DESC_SIZE] = \"\";\n\tDropListClass qlist1(DATA_SPECIAL1, quarry1, sizeof(quarry1),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD1_X, AD1_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tchar quarry2[DESC_SIZE] = \"\";\n\tDropListClass qlist2(DATA_SPECIAL2, quarry2, sizeof(quarry2),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tAD2_X, AD2_Y, ED_WIDTH, ED_HEIGHT,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (QuarryType q = QUARRY_FIRST; q < QUARRY_COUNT; q++) {\n\t\tqlist1.Add_Item(QuarryName[q]);\n\t\tqlist2.Add_Item(QuarryName[q]);\n\t}\n\tif ((unsigned)Action1.Data.Quarry < QUARRY_COUNT) {\n\t\tqlist1.Set_Selected_Index(Action1.Data.Quarry);\n\t} else {\n\t\tqlist1.Set_Selected_Index(0);\n\t}\n\tif ((unsigned)Action2.Data.Quarry < QUARRY_COUNT) {\n\t\tqlist2.Set_Selected_Index(Action2.Data.Quarry);\n\t} else {\n\t\tqlist2.Set_Selected_Index(0);\n\t}\n\n\t/*\n\t**\tName of this trigger text edit field.\n\t*/\n\tchar namebuf[5] = \"\";\n\tEditClass name_edt(NAME_EDIT, namebuf, sizeof(namebuf), TPF_EFNT | TPF_NOSHADOW, D_DIALOG_X+40, D_DIALOG_Y+30, 40, 9, EditClass::ALPHANUMERIC);\n\tstrcpy(namebuf, IniName);\t\t\t\t// Name\n\n\t/*\n\t**\tCreate the list of house's allowed for trigger.\n\t*/\n\tchar housetext[DESC_SIZE] = \"\";\n\tDropListClass housebtn(BUTTON_HOUSE, housetext, sizeof(housetext),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tname_edt.X+name_edt.Width+20, name_edt.Y, 95, 8*5,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\thousebtn.Add_Item(HouseTypeClass::As_Reference(house).IniName);\n\t}\n\tif (House == HOUSE_NONE) House = HOUSE_GOOD;\n\thousebtn.Set_Selected_Index(House);\n\n\t/*\n\t** Must match order and number of PersistantType specified in\n\t**\tTriggerTypeClass definition.\n\t*/\n\tchar perstext[DESC_SIZE] = \"\";\n\tstatic char * _perstext[3] = {\n\t\t\"Volatile\",\n\t\t\"Semi-persistent\",\n\t\t\"Persistent\"\n\t};\n\tDropListClass persbtn(BUTTON_PERSISTANCE, perstext, sizeof(perstext),\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\thousebtn.X+housebtn.Width+20, housebtn.Y, 105, 8*5,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (i = 0; i < sizeof(_perstext)/sizeof(_perstext[0]); i++) {\n\t\tpersbtn.Add_Item(_perstext[i]);\n\t}\n\tpersbtn.Set_Selected_Index(IsPersistant);\n\n\t/*\n\t**\tThis button controls the existence and relationship of a second trigger\n\t**\tevent.\n\t*/\n\tint eventflag = EventControl;\n\tTextButtonClass eventbtn(BUTTON_EVENT, TXT_TRIGGER_JUST_EVENT, TPF_EBUTTON, event1list.X, event1list.Y+11, 100, 9);\n\n\t/*\n\t**\tThis button controls the existence of a secondary action.\n\t*/\n\tbool actionflag = ActionControl;\n\tTextButtonClass actionbtn(BUTTON_ACTION, TXT_TRIGGER_JUST_ACTION, TPF_EBUTTON, action1list.X, action1list.Y+11, 100, 9);\n\n\t/*\n\t**\tCreate the ubiquitous OK and Cancel buttons.\n\t*/\n\tTextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_EBUTTON, D_DIALOG_X+35, D_DIALOG_Y+D_DIALOG_H-30, 45, 9);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_EBUTTON, D_DIALOG_X+D_DIALOG_W-80, D_DIALOG_Y+D_DIALOG_H-30, 45, 9);\n\n\t/*\n\t**\tInitialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tBuild the button list\n\t*/\n\tcommands = &okbtn;\n\tcancelbtn.Add_Tail(*commands);\n\tevent1list.Add_Tail(*commands);\n\taction1list.Add_Tail(*commands);\n\teventbtn.Add_Tail(*commands);\n\tactionbtn.Add_Tail(*commands);\n\tname_edt.Add_Tail(*commands);\n\tpersbtn.Add_Tail(*commands);\n\thousebtn.Add_Tail(*commands);\n\n\t/*\n\t**\tMain Processing Loop\n\t*/\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if needed\n\t\t*/\n\t\tif (display /*&& LogicPage->Lock()*/) {\n\n\t\t\t/*\n\t\t\t**\tDisplay the dialog box\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\t\t\tDraw_Caption(TXT_TRIGGER_EDITOR, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\n\t\t\t/*\n\t\t\t**\tDraw the captions\n\t\t\t*/\n\t\t\tFancy_Text_Print(\"Trigger Event:\", event1list.X, event1list.Y - 7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Action to Perform:\", action1list.X, action1list.Y - 7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"House:\", housebtn.X, housebtn.Y - 7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Name:\", name_edt.X, name_edt.Y - 7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Persistence:\", persbtn.X, persbtn.Y - 7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);\n\n\t\t\tif (eventflag == 3) {\n\t\t\t\tLogicPage->Draw_Line(event1list.X-1, event1list.Y+3, event1list.X-2*RESFACTOR, event1list.Y+3, WHITE);\n\t\t\t\tLogicPage->Draw_Line(event1list.X-2*RESFACTOR, event1list.Y+3, action1list.X-2*RESFACTOR, action1list.Y+3, WHITE);\n\t\t\t\tLogicPage->Draw_Line(action1list.X-1, action1list.Y+3, action1list.X-2*RESFACTOR, action1list.Y+3, WHITE);\n\n\t\t\t\tLogicPage->Draw_Line(event2list.X-1, event2list.Y+3, event2list.X-5*RESFACTOR, event2list.Y+3, WHITE);\n\t\t\t\tLogicPage->Draw_Line(event2list.X-5*RESFACTOR, event2list.Y+3, action2list.X-5*RESFACTOR, action2list.Y+3, WHITE);\n\t\t\t\tLogicPage->Draw_Line(action2list.X-1, action2list.Y+3, action2list.X-5*RESFACTOR, action2list.Y+3, WHITE);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAdjust the button list to match current control settings.\n\t\t\t*/\n\t\t\tevent2list.Remove();\n\t\t\tswitch (eventflag) {\n\t\t\t\tcase 0:\n\t\t\t\t\teventbtn.Set_Text(TXT_TRIGGER_JUST_EVENT);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 1:\n\t\t\t\t\teventbtn.Set_Text(TXT_TRIGGER_AND);\n\t\t\t\t\tevent2list.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 2:\n\t\t\t\t\teventbtn.Set_Text(TXT_TRIGGER_OR);\n\t\t\t\t\tevent2list.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 3:\n\t\t\t\t\teventbtn.Set_Text(TXT_TRIGGER_LINKED);\n\t\t\t\t\tevent2list.Add(*commands);\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tPrepare the primary event data field.\n\t\t\t*/\n\t\t\thtype1list.Remove();\n\t\t\tway1data.Remove();\n\t\t\tevent1data.Remove();\n\t\t\tbtype1list.Remove();\n\t\t\titype1list.Remove();\n\t\t\tatype1list.Remove();\n\t\t\tutype1list.Remove();\n\t\t\tttype1list.Remove();\n\t\t\tswitch (Event_Needs(*event1list.Current_Item())) {\n\t\t\t\tcase NEED_HOUSE:\n\t\t\t\t\thtype1list.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_TEAM:\n\t\t\t\t\tttype1list.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_WAYPOINT:\n\t\t\t\t\tway1data.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_TIME:\n\t\t\t\tcase NEED_NUMBER:\n\t\t\t\t\tevent1data.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_STRUCTURE:\n\t\t\t\t\tbtype1list.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_INFANTRY:\n\t\t\t\t\titype1list.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_AIRCRAFT:\n\t\t\t\t\tatype1list.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_UNIT:\n\t\t\t\t\tutype1list.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tPrepare the secondary event data field.\n\t\t\t*/\n\t\t\thtype2list.Remove();\n\t\t\tway2data.Remove();\n\t\t\tevent2data.Remove();\n\t\t\tbtype2list.Remove();\n\t\t\titype2list.Remove();\n\t\t\tatype2list.Remove();\n\t\t\tutype2list.Remove();\n\t\t\tttype2list.Remove();\n\t\t\tif (commands->Extract_Gadget(EVENT_LIST2)) {\n\t\t\t\tswitch (Event_Needs(*event2list.Current_Item())) {\n\t\t\t\t\tcase NEED_HOUSE:\n\t\t\t\t\t\thtype2list.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_TEAM:\n\t\t\t\t\t\tttype2list.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_WAYPOINT:\n\t\t\t\t\t\tway2data.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_TIME:\n\t\t\t\t\tcase NEED_NUMBER:\n\t\t\t\t\t\tevent2data.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_STRUCTURE:\n\t\t\t\t\t\tbtype2list.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_INFANTRY:\n\t\t\t\t\t\titype2list.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_AIRCRAFT:\n\t\t\t\t\t\tatype2list.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_UNIT:\n\t\t\t\t\t\tutype2list.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSetup the action buttons and associated data entry fields.\n\t\t\t*/\n\t\t\tactionbtn.Remove();\n\t\t\taction2list.Remove();\n\t\t\tif (eventflag == 3) {\n\t\t\t\taction2list.Add(*commands);\n\t\t\t} else {\n\t\t\t\tactionbtn.Add(*commands);\n\t\t\t\tif (actionflag) {\n\t\t\t\t\tactionbtn.Set_Text(TXT_TRIGGER_AND);\n\t\t\t\t\taction2list.Add(*commands);\n\t\t\t\t} else {\n\t\t\t\t\tactionbtn.Set_Text(TXT_TRIGGER_JUST_ACTION);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tqlist1.Remove();\n\t\t\tspc1.Remove();\n\t\t\thtype3list.Remove();\n\t\t\tbooltype1list.Remove();\n\t\t\ttrtype1list.Remove();\n\t\t\tway3data.Remove();\n\t\t\taction1data.Remove();\n\t\t\tttype3list.Remove();\n\t\t\tthemetype1list.Remove();\n\t\t\tsoundtype1list.Remove();\n\t\t\tmovietype1list.Remove();\n\t\t\tspeechtype1list.Remove();\n\t\t\tswitch (Action_Needs(*action1list.Current_Item())) {\n\t\t\t\tcase NEED_MOVIE:\n\t\t\t\t\tmovietype1list.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_SPECIAL:\n\t\t\t\t\tspc1.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_HOUSE:\n\t\t\t\t\thtype3list.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_BOOL:\n\t\t\t\t\tbooltype1list.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_TRIGGER:\n\t\t\t\t\ttrtype1list.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_TEAM:\n\t\t\t\t\tttype3list.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_NUMBER:\n\t\t\t\t\taction1data.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_WAYPOINT:\n\t\t\t\t\tway3data.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_THEME:\n\t\t\t\t\tthemetype1list.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_SOUND:\n\t\t\t\t\tsoundtype1list.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_SPEECH:\n\t\t\t\t\tspeechtype1list.Add(*commands);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_QUARRY:\n\t\t\t\t\tqlist1.Add(*commands);\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tqlist2.Remove();\n\t\t\tspc2.Remove();\n\t\t\thtype4list.Remove();\n\t\t\tbooltype2list.Remove();\n\t\t\ttrtype2list.Remove();\n\t\t\tway4data.Remove();\n\t\t\taction2data.Remove();\n\t\t\tttype4list.Remove();\n\t\t\tthemetype2list.Remove();\n\t\t\tsoundtype2list.Remove();\n\t\t\tmovietype2list.Remove();\n\t\t\tspeechtype2list.Remove();\n\t\t\tif (commands->Extract_Gadget(ACTION_LIST2)) {\n\t\t\t\tswitch (Action_Needs(*action2list.Current_Item())) {\n\t\t\t\t\tcase NEED_MOVIE:\n\t\t\t\t\t\tmovietype2list.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_SPECIAL:\n\t\t\t\t\t\tspc2.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_HOUSE:\n\t\t\t\t\t\thtype4list.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_BOOL:\n\t\t\t\t\t\tbooltype2list.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_TRIGGER:\n\t\t\t\t\t\ttrtype2list.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_TEAM:\n\t\t\t\t\t\tttype4list.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_NUMBER:\n\t\t\t\t\t\taction2data.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_WAYPOINT:\n\t\t\t\t\t\tway4data.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_THEME:\n\t\t\t\t\t\tthemetype2list.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_SOUND:\n\t\t\t\t\t\tsoundtype2list.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_SPEECH:\n\t\t\t\t\t\tspeechtype2list.Add(*commands);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_QUARRY:\n\t\t\t\t\t\tqlist2.Add(*commands);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCollapse any dropped down list boxes.\n\t\t\t*/\n\t\t\tspc1.Collapse();\n\t\t\tspc2.Collapse();\n\t\t\tqlist1.Collapse();\n\t\t\tqlist2.Collapse();\n\t\t\thtype1list.Collapse();\n\t\t\thtype2list.Collapse();\n\t\t\thtype3list.Collapse();\n\t\t\thtype4list.Collapse();\n\t\t\tttype1list.Collapse();\n\t\t\tttype2list.Collapse();\n\t\t\tttype3list.Collapse();\n\t\t\tttype4list.Collapse();\n\t\t\tbtype1list.Collapse();\n\t\t\tbtype2list.Collapse();\n\t\t\tutype1list.Collapse();\n\t\t\tutype2list.Collapse();\n\t\t\titype1list.Collapse();\n\t\t\titype2list.Collapse();\n\t\t\tatype1list.Collapse();\n\t\t\tatype2list.Collapse();\n\t\t\ttrtype1list.Collapse();\n\t\t\ttrtype2list.Collapse();\n\t\t\taction1list.Collapse();\n\t\t\taction2list.Collapse();\n\t\t\tevent1list.Collapse();\n\t\t\tevent2list.Collapse();\n\t\t\thousebtn.Collapse();\n\t\t\tpersbtn.Collapse();\n\t\t\tbooltype1list.Collapse();\n\t\t\tbooltype2list.Collapse();\n\t\t\tthemetype1list.Collapse();\n\t\t\tthemetype2list.Collapse();\n\t\t\tsoundtype1list.Collapse();\n\t\t\tsoundtype2list.Collapse();\n\t\t\tmovietype1list.Collapse();\n\t\t\tmovietype2list.Collapse();\n\t\t\tspeechtype1list.Collapse();\n\t\t\tspeechtype2list.Collapse();\n\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n//\t\t\tLogicPage->Unlock();\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t**\tProcess input\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase BUTTON_EVENT | KN_BUTTON:\n\t\t\t\teventflag = (eventflag+1) % 4;\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\tcase BUTTON_ACTION | KN_BUTTON:\n\t\t\t\tactionflag = (actionflag == false);\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\tcase DATA_SPEECH1 | KN_BUTTON:\n\t\t\t\tSpeak(VoxType(speechtype1list.Current_Index()));\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\tcase DATA_SPEECH2 | KN_BUTTON:\n\t\t\t\tSpeak(VoxType(speechtype2list.Current_Index()));\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\tcase DATA_SOUND1 | KN_BUTTON:\n\t\t\t\tSound_Effect(VocType(soundtype1list.Current_Index()));\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\tcase DATA_SOUND2 | KN_BUTTON:\n\t\t\t\tSound_Effect(VocType(soundtype2list.Current_Index()));\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tTransfer all the necessary values from the edit fields into their\n\t\t\t**\trespective positions within the trigger object.\n\t\t\t*/\n\t\t\tcase KN_RETURN:\n\t\t\tcase BUTTON_OK | KN_BUTTON:\n\t\t\t\tHouse = HousesType(housebtn.Current_Index());\n\t\t\t\tIsPersistant = PersistantType(persbtn.Current_Index());\n\t\t\t\tif (strlen(namebuf)==0) {\n\t\t\t\t\tSet_Name(\"____\");\n\t\t\t\t} else {\n\t\t\t\t\tSet_Name(namebuf);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tPrimary event specific data retrieval.\n\t\t\t\t*/\n\t\t\t\tEventControl = MultiStyleType(eventflag);\n\t\t\t\tEvent1.Event = *event1list.Current_Item();\n\t\t\t\tswitch (Event_Needs(Event1.Event)) {\n\t\t\t\t\tcase NEED_HOUSE:\n\t\t\t\t\t\tEvent1.Data.House = HousesType(htype1list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_TIME:\n\t\t\t\t\t\tEvent1.Data.Value = atoi(event1data.Get_Text());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_NUMBER:\n\t\t\t\t\t\tEvent1.Data.Value = atoi(event1data.Get_Text());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_STRUCTURE:\n\t\t\t\t\t\tEvent1.Data.Structure = StructType(btype1list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_UNIT:\n\t\t\t\t\t\tEvent1.Data.Unit = UnitType(utype1list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_INFANTRY:\n\t\t\t\t\t\tEvent1.Data.Infantry = InfantryType(itype1list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_AIRCRAFT:\n\t\t\t\t\t\tEvent1.Data.Aircraft = AircraftType(atype1list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_WAYPOINT:\n\t\t\t\t\t\tEvent1.Data.Value = toupper(way1[0]) - 'A';\n\t\t\t\t\t\tif (way1[1] != '\\0') {\n\t\t\t\t\t\t\tEvent1.Data.Value = (Event1.Data.Value+1)*26;\n\t\t\t\t\t\t\tEvent1.Data.Value += toupper(way1[1]) - 'A';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_TEAM:\n\t\t\t\t\t\tEvent1.Team = TeamTypeClass::From_Name(ttype1list.Current_Item());\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tSecondary event specific data retrieval.\n\t\t\t\t*/\n\t\t\t\tEvent2.Event = *event2list.Current_Item();\n\t\t\t\tswitch (Event_Needs(Event2.Event)) {\n\t\t\t\t\tcase NEED_HOUSE:\n\t\t\t\t\t\tEvent2.Data.House = HousesType(htype2list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_TIME:\n\t\t\t\t\t\tEvent2.Data.Value = atoi(event2data.Get_Text());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_NUMBER:\n\t\t\t\t\t\tEvent2.Data.Value = atoi(event2data.Get_Text());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_STRUCTURE:\n\t\t\t\t\t\tEvent2.Data.Structure = StructType(btype2list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_UNIT:\n\t\t\t\t\t\tEvent2.Data.Unit = UnitType(utype2list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_INFANTRY:\n\t\t\t\t\t\tEvent2.Data.Infantry = InfantryType(itype2list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_AIRCRAFT:\n\t\t\t\t\t\tEvent2.Data.Aircraft = AircraftType(atype2list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_WAYPOINT:\n\t\t\t\t\t\tEvent2.Data.Value = toupper(way2[0]) - 'A';\n\t\t\t\t\t\tif (way2[1] != '\\0') {\n\t\t\t\t\t\t\tEvent2.Data.Value = (Event2.Data.Value+1)*26;\n\t\t\t\t\t\t\tEvent2.Data.Value += toupper(way2[1]) - 'A';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_TEAM:\n\t\t\t\t\t\tEvent2.Team = TeamTypeClass::As_Pointer(ttype2list.Current_Item());\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tPrimary action data retrieval.\n\t\t\t\t*/\n\t\t\t\tActionControl = MultiStyleType(actionflag);\n\t\t\t\tAction1.Action = *action1list.Current_Item();\n\t\t\t\tswitch (Action_Needs(Action1.Action)) {\n\t\t\t\t\tcase NEED_SPECIAL:\n\t\t\t\t\t\tAction1.Data.Special = SpecialWeaponType(spc1.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_HOUSE:\n\t\t\t\t\t\tAction1.Data.House = HousesType(htype3list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_TRIGGER:\n\t\t\t\t\t\tAction1.Trigger = TriggerTypeClass::From_Name(trtype1list.Current_Item());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_TEAM:\n\t\t\t\t\t\tAction1.Team = TeamTypeClass::From_Name(ttype3list.Current_Item());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_NUMBER:\n\t\t\t\t\t\tAction1.Data.Value = atoi(action1data.Get_Text());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_WAYPOINT:\n\t\t\t\t\t\tAction1.Data.Value = toupper(way3[0]) - 'A';\n\t\t\t\t\t\tif (way3[1] != '\\0') {\n\t\t\t\t\t\t\tAction1.Data.Value = (Action1.Data.Value+1)*26;\n\t\t\t\t\t\t\tAction1.Data.Value += toupper(way3[1]) - 'A';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_BOOL:\n\t\t\t\t\t\tAction1.Data.Bool = booltype1list.Current_Index();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_THEME:\n\t\t\t\t\t\tAction1.Data.Theme = ThemeType(themetype1list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_SOUND:\n\t\t\t\t\t\tAction1.Data.Sound = VocType(soundtype1list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_MOVIE:\n\t\t\t\t\t\tAction1.Data.Movie = VQType(movietype1list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_SPEECH:\n\t\t\t\t\t\tAction1.Data.Speech = VoxType(speechtype1list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_QUARRY:\n\t\t\t\t\t\tAction1.Data.Quarry = QuarryType(qlist1.Current_Index());\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tSecondary action data retrieval.\n\t\t\t\t*/\n\t\t\t\tAction2.Action = *action2list.Current_Item();\n\t\t\t\tswitch (Action_Needs(Action2.Action)) {\n\t\t\t\t\tcase NEED_SPECIAL:\n\t\t\t\t\t\tAction2.Data.Special = SpecialWeaponType(spc2.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_HOUSE:\n\t\t\t\t\t\tAction2.Data.House = HousesType(htype4list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_TRIGGER:\n\t\t\t\t\t\tAction2.Trigger = TriggerTypeClass::From_Name(trtype2list.Current_Item());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_TEAM:\n\t\t\t\t\t\tAction2.Team = TeamTypeClass::From_Name(ttype4list.Current_Item());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_NUMBER:\n\t\t\t\t\t\tAction2.Data.Value = atoi(action2data.Get_Text());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_WAYPOINT:\n\t\t\t\t\t\tAction2.Data.Value = toupper(way4[0]) - 'A';\n\t\t\t\t\t\tif (way4[1] != '\\0') {\n\t\t\t\t\t\t\tAction2.Data.Value = (Action2.Data.Value+1)*26;\n\t\t\t\t\t\t\tAction2.Data.Value += toupper(way4[1]) - 'A';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_BOOL:\n\t\t\t\t\t\tAction2.Data.Bool = booltype2list.Current_Index();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_THEME:\n\t\t\t\t\t\tAction2.Data.Theme = ThemeType(themetype2list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_MOVIE:\n\t\t\t\t\t\tAction2.Data.Movie = VQType(movietype2list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_SOUND:\n\t\t\t\t\t\tAction2.Data.Sound = VocType(soundtype2list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_SPEECH:\n\t\t\t\t\t\tAction2.Data.Speech = VoxType(speechtype2list.Current_Index());\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase NEED_QUARRY:\n\t\t\t\t\t\tAction2.Data.Quarry = QuarryType(qlist1.Current_Index());\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn(true);\n\n\t\t\tcase KN_ESC:\n\t\t\tcase BUTTON_CANCEL | KN_BUTTON:\n\t\t\t\tprocess = false;\n\n\t\t\t/*\n\t\t\t**\tAlways signal a redraw if any of the buttons were touched. This\n\t\t\t**\tcan be determined by examining the button bit flag in the input\n\t\t\t**\treturn value.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\tif (input & KN_BUTTON) {\n\t\t\t\t\tdisplay = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn(false);\n}\n#endif\n\n\n#if defined(CHEAT_KEYS) || defined(SCENARIO_EDITOR)\n/***********************************************************************************************\n * TriggerTypeClass::Description -- Build a text description of the trigger type.              *\n *                                                                                             *\n *    This will build a (static) text description of the trigger type. Use this description    *\n *    when displaying this trigger in a list box.                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a one line text description of this trigger.             *\n *                                                                                             *\n * WARNINGS:   The pointer returned actually points to a static buffer. The pointer is only    *\n *             valid until this routine is called again.                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * TriggerTypeClass::Description(void) const\n{\n\tstatic char _buffer[128];\n\n\tchar special;\n\tswitch (EventControl) {\n\t\tcase MULTI_AND:\n\t\t\tspecial = '&';\n\t\t\tbreak;\n\n\t\tcase MULTI_OR:\n\t\t\tspecial = '|';\n\t\t\tbreak;\n\n\t\tcase MULTI_LINKED:\n\t\t\tspecial = '=';\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tspecial = '.';\n\t\t\tbreak;\n\t}\n\n\tchar special2 = '.';\n\tif (ActionControl == MULTI_AND) {\n\t\tspecial2 = '&';\n\t}\n\n\tchar tbuf[32];\n\tchar const * added = \"\";\n\tswitch (Event_Needs(Event1.Event)) {\n\t\tcase NEED_NUMBER:\n\t\t\tsprintf(tbuf, \"%d\", Event1.Data.Value);\n\t\t\tadded = tbuf;\n\t\t\tbreak;\n\n\t\tcase NEED_UNIT:\n\t\t\tadded = Text_String(UnitTypeClass::As_Reference(Event1.Data.Unit).Full_Name());;\n\t\t\tbreak;\n\n\t\tcase NEED_AIRCRAFT:\n\t\t\tadded = Text_String(AircraftTypeClass::As_Reference(Event1.Data.Aircraft).Full_Name());;\n\t\t\tbreak;\n\n\t\tcase NEED_STRUCTURE:\n\t\t\tadded = Text_String(BuildingTypeClass::As_Reference(Event1.Data.Structure).Full_Name());\n\t\t\tbreak;\n\n\t\tcase NEED_INFANTRY:\n\t\t\tadded = Text_String(InfantryTypeClass::As_Reference(Event1.Data.Infantry).Full_Name());\n\t\t\tbreak;\n\n\t\tcase NEED_WAYPOINT:\n\t\t\tif (Event1.Data.Value < 26) {\n\t\t\t\tsprintf(tbuf, \"'%c'\", Event1.Data.Value + 'A');\n\t\t\t} else {\n\t\t\t\tsprintf(tbuf, \"'%c%c'\", (Event1.Data.Value / 26) + 'A'-1, (Event1.Data.Value % 26) + 'A');\n\t\t\t}\n\t\t\tadded = tbuf;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tPersistence indicator value.\n\t*/\n\tchar pers = 'V';\n\tif (IsPersistant == SEMIPERSISTANT) pers = 'S';\n\tif (IsPersistant == PERSISTANT) pers = 'P';\n\n\tsprintf(_buffer, \"%4.4s\\t %s %c%c%c  %s%s\",\n\t\tIniName,\n\t\tHouseTypeClass::As_Reference(House).Suffix,\n\t\tpers,\n\t\tspecial,\n\t\tspecial2,\n\t\tName_From_Event(Event1.Event),\n\t\tadded);\n\treturn(_buffer);\n}\n\n#endif\n\n\n/***********************************************************************************************\n * TriggerTypeClass::Attaches_To -- Determines what trigger can attach to.                     *\n *                                                                                             *\n *    This routine will examine the trigger events and return with a composit bitfield that    *\n *    indicates what this trigger can be attached to. This is used for trigger placement       *\n *    and logic processing.                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with AttachType bitfield representing what this trigger can be attached    *\n *          to.                                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/30/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nAttachType TriggerTypeClass::Attaches_To(void) const\n{\n\tAttachType attach = ::Attaches_To(Event1.Event);\n\n\tif (EventControl != MULTI_ONLY) {\n\t\tattach = attach | ::Attaches_To(Event2.Event);\n\t}\n\treturn(attach);\n}\n\n\n/***********************************************************************************************\n * TriggerTypeClass::Read_INI -- reads triggers from the INI file                              *\n *                                                                                             *\n *    INI entry format:                                                                        *\n *      Triggername = Eventname, Actionname, Data, Housename, TeamName, IsPersistant           *\n *                                                                                             *\n * This routine reads in the triggers & creates them. Then, other classes can                  *\n * get pointers to the triggers they're linked to.                                             *\n *                                                                                             *\n * The routine relies on the TeamTypeClasses already being loaded so it can resolve            *\n * references to teams in this function.                                                       *\n *                                                                                             *\n * Cell Trigger pointers & IsTrigger flags are set in DisplayClass::Read_INI(),                *\n * and cleared in the Map::Init() routine (which clears all cell objects to 0's).              *\n *                                                                                             *\n * Object's pointers are set in:                                                               *\n *      InfantryClass::Read_INI()                                                              *\n *      BuildingClass::Read_INI()                                                              *\n *      UnitClass::Read_INI()                                                                  *\n *      TerrainClass::Read_INI()                                                               *\n * The object trigger pointers are cleared in the ObjectClass constructor.                     *\n *                                                                                             *\n * The House's EMSListOf triggers is set in this routine, and cleared in the                   *\n * HouseClass::Init() routine.                                                                 *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      buffer      buffer to hold the INI data                                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      This function must be called before any other class's Read_INI.                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/28/1994 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid TriggerTypeClass::Read_INI(CCINIClass & ini)\n{\n\tTriggerTypeClass *trigger;\t\t\t\t// Working trigger pointer.\n\tchar buf[128];\n\n\tint len = ini.Entry_Count(INI_Name());\n\tfor (int index = 0; index < len; index++) {\n\t\tchar const * entry = ini.Get_Entry(INI_Name(), index);\n\n\t\t/*\n\t\t**\tCreate a new trigger.\n\t\t*/\n\t\ttrigger = new TriggerTypeClass();\n\n\t\t/*\n\t\t**\tGet the trigger entry.\n\t\t*/\n\t\tini.Get_String(INI_Name(), entry, NULL, buf, sizeof(buf));\n\n\t\t/*\n\t\t**\tFill in the trigger.\n\t\t*/\n\t\ttrigger->Fill_In((char *)entry, buf);\n\t}\n\n\tif (NewINIFormat < 2) {\n\t\t/*\n\t\t**\tFix up the self-referential trigger pointers.\n\t\t*/\n\t\tfor (int trig_index = 0; trig_index < TriggerTypes.Count(); trig_index++) {\n\t\t\tTriggerTypeClass * trigger = TriggerTypes.Ptr(trig_index);\n\n\t\t\tchar * ptr = (char *)trigger->Action1.Trigger.Raw();\n\t\t\tif (ptr /*&& trigger->Action1.Trigger.Raw() != -1*/) {\n\t\t\t\ttrigger->Action1.Trigger = TriggerTypeClass::From_Name(ptr);\n\t\t\t\tfree(ptr);\n\t\t\t}\n\n\t\t\tptr = (char *)trigger->Action2.Trigger.Raw();\n\t\t\tif (ptr /*&& trigger->Action2.Trigger.Raw() != -1*/) {\n\t\t\t\ttrigger->Action2.Trigger = TriggerTypeClass::From_Name(ptr);\n\t\t\t\tfree(ptr);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TriggerTypeClass::Fill_In -- fills in trigger from the given INI entry                      *\n *                                                                                             *\n * This routine fills in the given trigger with the given name, and values from                *\n * the given INI entry.                                                                        *\n *                                                                                             *\n * (This routine is used by the scenario editor, to import teams from the MASTER.INI file.)    *\n *                                                                                             *\n *    INI entry format:                                                                        *\n *      Triggername = Eventname, Actionname, Data, Housename, TeamName, IsPersistant           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      name      mnemonic for the desired trigger                                             *\n *      entry      INI entry to parse                                                          *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/28/1994 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid TriggerTypeClass::Fill_In(char * name, char * entry)\n{\n\tassert(TriggerTypes.ID(this) == ID);\n\n\t/*\n\t**\tSet its name.\n\t*/\n\tSet_Name(name);\n\n\tIsPersistant = PersistantType(atoi(strtok(entry, \",\")));\n\tHouse = HousesType(atoi(strtok(NULL, \",\")));\n\tEventControl = MultiStyleType(atoi(strtok(NULL, \",\")));\n\tActionControl = MultiStyleType(atoi(strtok(NULL, \",\")));\n\n\tEvent1.Read_INI();\n\tEvent2.Read_INI();\n\tAction1.Read_INI();\n\tAction2.Read_INI();\n}\n\n\n/***********************************************************************************************\n * TriggerTypeClass::Write_INI -- Stores all trigger types to the INI database specified.      *\n *                                                                                             *\n *    This routine will write out all trigger type objects to the INI database. Any existing   *\n *    trigger types in the database will be cleared out.                                       *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to have the trigger types added.            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TriggerTypeClass::Write_INI(CCINIClass & ini)\n{\n\tini.Clear(\"Triggers\");\n\tini.Clear(INI_Name());\n\n\t/*\n\t**\tNow write all the trigger data out\n\t*/\n\tfor (int index = 0; index < TriggerTypes.Count(); index++) {\n//\tfor (int index = TriggerTypes.Count()-1; index >= 0; index--) {\n\t\tchar buf[256];\n\t\tTriggerTypeClass * trigger = TriggerTypes.Ptr(index);\n\n\t\ttrigger->Build_INI_Entry(buf);\n\t\tini.Put_String(INI_Name(), trigger->IniName, buf);\n\t}\n}\n\n\n/***********************************************************************************************\n * TriggerTypeClass::Build_INI_Entry -- Construct the INI entry into the buffer specified.     *\n *                                                                                             *\n *    This low level routine will take the information in this trigger type and store it       *\n *    into a buffer such that the resultant string can be stored into an INI database for      *\n *    later retrieval.                                                                         *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer to store the INI entry string.                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure the buffer is big enough. Usually 128 bytes is more than sufficient.    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TriggerTypeClass::Build_INI_Entry(char * buffer) const\n{\n\t/*\n\t**\tBuild the root portion of the trigger event.\n\t*/\n\tsprintf(buffer, \"%d,%d,%d,%d,\", IsPersistant, House, EventControl, ActionControl);\n\n\t/*\n\t**\tAppend the event and action values.\n\t*/\n\tbuffer += strlen(buffer);\n\tEvent1.Build_INI_Entry(buffer);\n\n\tstrcat(buffer, \",\");\n\tbuffer += strlen(buffer);\n\tEvent2.Build_INI_Entry(buffer);\n\n\tstrcat(buffer, \",\");\n\tbuffer += strlen(buffer);\n\tAction1.Build_INI_Entry(buffer);\n\n\tstrcat(buffer, \",\");\n\tbuffer += strlen(buffer);\n\tAction2.Build_INI_Entry(buffer);\n}\n\n\n#if defined(CHEAT_KEYS) || defined(SCENARIO_EDITOR)\n/***********************************************************************************************\n * TriggerTypeClass::Draw_It -- Draws this trigger as if it were a line in a list box.         *\n *                                                                                             *\n *    This routine is called when triggers are assigned to a list box and then must be drawn.  *\n *    It will display an identifying text string with as much information as is useful.        *\n *                                                                                             *\n * INPUT:   index    -- The index number of this line in the list box.                         *\n *                                                                                             *\n *          x,y      -- The pixel coordinate of the upper left corner of the text box.         *\n *                                                                                             *\n *          width,height   -- The dimensions of the text box to display the description in.    *\n *                                                                                             *\n *          selected -- Is this a selected line? If so, then it should be highlighted.         *\n *                                                                                             *\n *          flags    -- The text print flags to use to display this text string.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TriggerTypeClass::Draw_It(int , int x, int y, int width, int height, bool selected, TextPrintType flags) const\n{\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\tstatic int _tabs[] = {13,40};\n\tif ((flags & 0x0F) == TPF_6PT_GRAD || (flags & 0x0F) == TPF_EFNT) {\n\n\t\tif (selected) {\n\t\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\t\tLogicPage->Fill_Rect(x, y, x + width - 1, y + height - 1, scheme->Shadow);\n\t\t} else {\n\t\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t\t}\n\t\t}\n\n\t\tConquer_Clip_Text_Print(Description(), x, y, scheme, TBLACK, flags, width, _tabs);\n\t} else {\n\t\tConquer_Clip_Text_Print(Description(), x, y, (selected ? &ColorRemaps[PCOLOR_DIALOG_BLUE] : &ColorRemaps[PCOLOR_GREY]), TBLACK, flags, width, _tabs);\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * TriggerTypeClass::Init -- Initialize the trigger type object management system.             *\n *                                                                                             *\n *    This routine should be called to initialize the trigger type object system. It should    *\n *    be called when clearing out a scenario.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   All trigger types will be destroyed by this routine.                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TriggerTypeClass::Init(void)\n{\n\tTriggerTypes.Free_All();\n}\n\n\n/***********************************************************************************************\n * TriggerTypeClass::From_Name -- Convert an ASCII name into a trigger type pointer.           *\n *                                                                                             *\n *    Given just an ASCII representation of the trigger type, this routine will return with    *\n *    a pointer to the trigger type it refers to. Typical use of this is when parsing          *\n *    scenario INI files.                                                                      *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the name to use to identify the trigger type class object to   *\n *                   be looked up.                                                             *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the trigger type class object that matches the name      *\n *          specified. If no match could be found, then NULL is returned.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTriggerTypeClass * TriggerTypeClass::From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (int index = 0; index < TriggerTypes.Count(); index++) {\n\t\t\tif (stricmp(TriggerTypes.Ptr(index)->Name(), name) == 0) {\n\t\t\t\treturn(TriggerTypes.Ptr(index));\n\t\t\t}\n\t\t}\n\t}\n\treturn(NULL);\n}\n"
  },
  {
    "path": "CODE/TRIGTYPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TRIGTYPE.H 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TRIGTYPE.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/05/96                                                     *\n *                                                                                             *\n *                  Last Update : June 5, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef TRIGTYPE_H\n#define TRIGTYPE_H\n\n#include\t\"tevent.h\"\n#include\t\"taction.h\"\n\nclass TriggerClass;\n\n/*\n**\tThere can be multiple trigger events and trigger actions. This enumeration is used to\n**\tindicate if there are multiple events/actions and what their relationship is.\n*/\ntypedef enum MultiStyleType {\n\tMULTI_ONLY,\t\t\t\t\t// \"Only\" main trigger action/event?\n\tMULTI_AND,\t\t\t\t\t// \"And\" secondary trigger action/event?\n\tMULTI_OR,\t\t\t\t\t// \"Or\" secondary event?\n\tMULTI_LINKED\t\t\t\t// Cause and effect pairs are linked?\n} MultiStyleType;\n\n\nclass TriggerTypeClass : public AbstractTypeClass\n{\n\tpublic:\n\t\tunsigned IsActive:1;\n\n\t\ttypedef enum PersistantType {\n\t\t\tVOLATILE = 0,\n\t\t\tSEMIPERSISTANT = 1,\n\t\t\tPERSISTANT = 2\n\t\t} PersistantType;\n\n\t\t/*\n\t\t**\tThis flag controls whether the trigger destroys itself after it goes\n\t\t**\toff.\n\t\t**\t0 = trigger destroys itself immediately after going off, and removes\n\t\t**\t    itself from all objects it's attached to\n\t\t**\t1 = trigger is \"Semi-Persistent\"; it maintains a count of all objects\n\t\t**\t    it's attached to, and only actually \"springs\" after its been\n\t\t**\t\t triggered from all the objects; then, it removes itself.\n\t\t**\t2 = trigger is Fully Persistent; it just won't go away.\n\t\t*/\n\t\tPersistantType IsPersistant;\n\n\t\t/*\n\t\t**\tFor house-specific events, this is the house for that event.\n\t\t*/\n\t\tHousesType House;\n\n\t\t/*\n\t\t**\tEach trigger must have an event which activates it. This is the event that is\n\t\t**\tused to activate this trigger.\n\t\t*/\n\t\tTEventClass Event1;\n\t\tTEventClass Event2;\n\t\tMultiStyleType EventControl;\n\n\t\t/*\n\t\t**\tThis is the action to perform when the trigger event occurs.\n\t\t*/\n\t\tTActionClass Action1;\n\t\tTActionClass Action2;\n\t\tMultiStyleType ActionControl;\n\n\n\t\tTriggerTypeClass(void);\n\t\tTriggerTypeClass(NoInitClass const & x) : AbstractTypeClass(x), Event1(x), Event2(x), Action1(x), Action2(x) {};\n\t\tvirtual ~TriggerTypeClass(void);\n\n\t\tstatic void * operator new(size_t );\n\t\tstatic void * operator new(size_t, void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\n\t\t/*\n\t\t**\tInitialization: clears all trigger types in preparation for new scenario\n\t\t*/\n\t\tstatic void Init(void);\n\n\t\t/*\n\t\t**\tFile I/O routines\n\t\t*/\n\t\tstatic void Read_INI(CCINIClass & ini);\n\t\tstatic void Write_INI(CCINIClass & ini);\n\t\tvoid Fill_In(char * name, char * entry);\n\t\tvoid Build_INI_Entry(char * buf) const;\n\n\t\tstatic char * INI_Name(void) {return \"Trigs\";};\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\t\tvoid Code_Pointers(void);\n\t\tvoid Decode_Pointers(void);\n\n\t\t/*\n\t\t**\tProcessing routines\n\t\t*/\n\t\tTriggerClass * Create_One_Of(void) const;\n\t\tvoid Destroy_All_Of(void) const;\n\n\t\t/*\n\t\t**\tUtility routines\n\t\t*/\n\t\tvoid Detach(TARGET target, bool all=true);\n\t\tAttachType Attaches_To(void) const;\n\t\tTARGET As_Target(void) const;\n\t\tstatic TriggerTypeClass * From_Name(char const * name);\n\t\tbool Edit(void);\n#if defined(CHEAT_KEYS) || defined(SCENARIO_EDITOR)\n\t\tchar const * Description(void) const;\n\t\toperator const char * (void) const {return(Description());};\n#endif\n\t\tvoid Draw_It(int index, int x, int y, int width, int height, bool selected, TextPrintType flags) const;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/TURBOC.CFG",
    "content": " -Vt\n -Vb-\n -a-\n -b-\n -3\n -ml\n -nobj\\.\n -C-\n -c\n -Jg\n -DIBM=1\n -H=conquer.sym\n -Ibc402\\include;d:\\WATCOM\\H;d:\\WATCOM\\H\\win;player\n -Id:\\library;d:\\library\\source\\hmi\\midi\\inc;d:\\library\\source\\hmi\\digi\\inc\n -P-\n -w\n -w!\n -X-\n -RT\n -x\n -k-\n -vi\n -Z\n -Oi\n -Op\n -Og\n -Oc\n -Ol\n -d\n -r\n -V\n -dc\n -K2-\n -R-\n -Oe\n -Ob\n -Om\n"
  },
  {
    "path": "CODE/TURRET.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\turret.cpv   3.1   13 Mar 1996 09:49:34   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***             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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TURRET.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 25, 1994                                               *\n *                                                                                             *\n *                  Last Update : August 13, 1995 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   TurretClass::AI -- Handles the reloading of the turret weapon.                            *\n *   TurretClass::Can_Fire -- Determines if turret can fire upon target.                       *\n *   TurretClass::Debug_Dump -- Debug printing of turret values.                               *\n *   TurretClass::Fire_At -- Try to fire upon the target specified.                            *\n *   TurretClass::Fire_Coord -- Determines the coorindate that projectile would appear.        *\n *   TurretClass::Fire_Direction -- Determines the directinon of firing.                       *\n *   TurretClass::Ok_To_Move -- Queries whether the vehicle can move.                          *\n *   TurretClass::TurretClass -- Normal constructor for the turret class.                      *\n *   TurretClass::TurretClass -- The default constructor for turret class objects.             *\n *   TurretClass::Unlimbo -- Unlimboes turret object.                                          *\n *   TurretClass::~TurretClass -- Default destructor for turret class objects.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"turret.h\"\n\n\n/***********************************************************************************************\n * TurretClass::~TurretClass -- Default destructor for turret class objects.                   *\n *                                                                                             *\n *    This is the default destructor for turret class objects. It does nothing.                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTurretClass::~TurretClass(void)\n{\n}\n\n\n/***********************************************************************************************\n * TurretClass::TurretClass -- The default constructor for turret class objects.               *\n *                                                                                             *\n *    This is the default constructor for turret class objects. It does nothing.               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTurretClass::TurretClass(void)\n{\n}\n\n\n/***********************************************************************************************\n * TurretClass::TurretClass -- Normal constructor for the turret class.                        *\n *                                                                                             *\n *    This is the normal constructor for the turret class. It merely sets the turret up to     *\n *    face north.                                                                              *\n *                                                                                             *\n * INPUT:   classid  -- The type id for this particular unit.                                  *\n *                                                                                             *\n *          house    -- The house that this unit will belong to.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTurretClass::TurretClass(UnitType classid, HousesType house) :\n\tDriveClass(classid, house)\n{\n}\n\n\n\n"
  },
  {
    "path": "CODE/TURRET.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\turret.h_v   3.1   13 Mar 1996 09:43:14   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TURRET.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 25, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 25, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TURRET_H\n#define TURRET_H\n\n#include \"drive.h\"\n\nclass TurretClass : public DriveClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n\n\tprotected:\n\t\tTurretClass(UnitType classid, HousesType house);\n\t\tTurretClass(void);\n\t\tvirtual ~TurretClass(void);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/TXTLABEL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TXTLABEL.CPP 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TXTLABEL.H                                                   *\n *                                                                                             *\n *                   Programmer : Bill Randolph                                                *\n *                                                                                             *\n *                   Start Date : 02/06/95                                                     *\n *                                                                                             *\n *                  Last Update : February 6, 1995 [BR]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   TextLableClass::Draw_Me -- Graphical update routine                                       *\n *   TextLableClass::TextLabelClass -- Constructor                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/***********************************************************************************************\n * TextLableClass::TextLabelClass -- Constructor                                               *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      txt         pointer to text buffer to print from                                       *\n *      x            x-coord for text printing                                                 *\n *      y            y-coord for text printing                                                 *\n *      color         color to print in                                                        *\n *      style         style to print (determines the meaning of x & y)                         *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nTextLabelClass::TextLabelClass(char *txt, int x, int y, RemapControlType * color,\n TextPrintType style) : GadgetClass(x, y, 1, 1, 0, 0)\n{\n\tText = txt;\n\tColor = color;\n\tStyle = style;\n\tUserData1 = 0;\n\tUserData2 = 0;\n\tPixWidth = -1;\n}\n\n\n/***********************************************************************************************\n * TextLableClass::Draw_Me -- Graphical update routine                                         *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      forced      true = draw regardless of the current redraw flag state                    *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = gadget was redrawn, false = wasn't                                              *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvirtual int TextLabelClass::Draw_Me(int forced)\n{\n\tif (GadgetClass::Draw_Me(forced)) {\n\t\tif (PixWidth == -1) {\n\t\t\tSimple_Text_Print(Text, X, Y, Color, TBLACK, Style);\n//\t\t\tFancy_Text_Print(Text, X, Y, Color, TBLACK, Style);\n\t\t} else {\n\t\t\tConquer_Clip_Text_Print(Text, X, Y, Color, TBLACK, Style, PixWidth);\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "CODE/TXTLABEL.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TXTLABEL.H 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TXTLABEL.H                                                   *\n *                                                                                             *\n *                   Programmer : Bill Randolph\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *                   Start Date : 02/06/95                                                     *\n *                                                                                             *\n *                  Last Update : February 6, 1995 [BR]\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TXTLABEL_H\n#define TXTLABEL_H\n\nclass TextLabelClass : public GadgetClass\n{\n\tpublic:\n\t\t/*\n\t\t** Constructor/Destructor\n\t\t*/\n\t\tTextLabelClass(char *txt, int x, int y, RemapControlType * color,\n\t\t\tTextPrintType style);\n\n\t\t/*\n\t\t** Overloaded draw routine\n\t\t*/\n\t\tvirtual int Draw_Me(int forced = false);\n\n\t\t/*\n\t\t** Sets the displayed text of the label\n\t\t*/\n\t\tvirtual void Set_Text(char *txt) {Text = txt;};\n\n\t\t/*\n\t\t** General-purpose data fields\n\t\t*/\n\t\tunsigned long UserData1;\n\t\tunsigned long UserData2;\n\t\tTextPrintType Style;\n\t\tchar *Text;\n\t\tRemapControlType * Color;\n\t\tint PixWidth;\n};\n\n#endif\n\n"
  },
  {
    "path": "CODE/TXTPRNT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TXTPRNT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 17, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 17, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   MCGA_Print -- Assembly MCGA text print routine                        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n;INCLUDE \"mcgaprim.inc\"\n;INCLUDE \".\\gbuffer.inc\"\n\nGLOBAL MCGA_Print : NEAR\n\nSTRUC GraphicViewPort\nGVPOffset\t\tDD\t\t?\t\t; offset to virtual viewport\nGVPWidth\t\tDD\t\t?\t\t; width of virtual viewport\nGVPHeight\t\tDD\t\t?\t\t; height of virtual viewport\nGVPXAdd\t\t\tDD\t\t?\t\t; x mod to get to next line\nGVPXPos\t\t\tDD\t\t?\t\t; x pos relative to Graphic Buff\nGVPYPos\t\t\tDD\t\t?\t\t; y pos relative to Graphic Buff\nGVPBuffPtr\t\tDD\t\t?\t\t; ptr to associated Graphic Buff\nENDS\n\n\n;*=========================================================================*\n;* Extern the font pointer which is defined by the font class\t\t   *\n;*=========================================================================*\nGLOBAL\tFontPtr:DWORD\nGLOBAL\tFontXSpacing:DWORD\nGLOBAL\tFontYSpacing:DWORD\nGLOBAL\tColorXlat:BYTE\n\n;*=========================================================================*\n;* Define the necessary equates for structures and bounds checking\t   *\n;*=========================================================================*\n; The header of the font file looks like this:\n; \tUWORD\tFontLength;\t\t0\n; \tBYTE\tFontCompress;\t\t2\n;\tBYTE\tFontDataBlocks;\t\t3\n;\tUWORD\tInfoBlockOffset;\t4\n;\tUWORD\tOffsetBlockOffset;\t6\n;\tUWORD\tWidthBlockOffset;\t8\n;\tUWORD\tDataBlockOffset;\t10\n;\tUWORD\tHeightOffset;\t\t12\n; For this reason the following equates have these values:\nFONTINFOBLOCK\t\tEQU\t4\nFONTOFFSETBLOCK\t\tEQU\t6\nFONTWIDTHBLOCK\t\tEQU\t8\nFONTDATABLOCK\t\tEQU\t10\nFONTHEIGHTBLOCK\t\tEQU\t12\n\nFONTINFOMAXHEIGHT\tEQU\t4\nFONTINFOMAXWIDTH\tEQU\t5\n\n\nLOCALS ??\n;*=========================================================================*\n;* Define the color xlate table in the data segment\t\t\t   *\n;*=========================================================================*\n\tDATASEG\n\nColorXlat\tDB\t000H,001H,002H,003H,004H,005H,006H,007H\n\t\tDB\t008H,009H,00AH,00BH,00CH,00DH,00EH,00FH\n\n\t\tDB\t001H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t002H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t003H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t004H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t005H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t006H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t007H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t008H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t009H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00AH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00BH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00CH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00DH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00EH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00FH\n\n\tCODESEG\n\n\n;***************************************************************************\n;* MCGA_PRINT -- Assembly MCGA text print routine                          *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/17/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tMCGA_Print C near\n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\tthis:DWORD\n\tARG\tstring:DWORD\n\tARG\tx_pixel:DWORD\n\tARG\ty_pixel:DWORD\n\tARG\tfcolor:DWORD\n\tARG\tbcolor:DWORD\n\n\tLOCAL\tinfoblock:DWORD\t\t; pointer to info block\n\tLOCAL\toffsetblock:DWORD\t; pointer to offset block  (UWORD *)\n\tLOCAL\twidthblock:DWORD\t; pointer to width block   (BYTE  *)\n\tLOCAL\theightblock:DWORD\t; pointer to height block  (UWORD *)\n\n\tLOCAL\tcurline:DWORD\t\t; pointer to first column of current row.\n\tLOCAL\tbufferwidth:DWORD    \t; width of buffer (vpwidth + Xadd)\n\tLOCAL\tnextdraw:DWORD\t\t; bufferwidth - width of cur character.\n\tLOCAL\tstartdraw:DWORD\t\t; where next character will start being drawn.\n\n\tLOCAL\tchar:DWORD\t\t; current character value.\n\n\tLOCAL\tmaxheight:BYTE\t\t; max height of characters in font.\n\tLOCAL\tbottomblank:BYTE\t; amount of empty space below current character.\n\tLOCAL\tcharheight:BYTE\t\t; true height of current character.\n\tLOCAL\tvpwidth:DWORD\n\tLOCAL\tvpheight:DWORD\n\tLOCAL\toriginal_x:DWORD\t; Starting X position.\n\n\n;-------------------------------- Where to draw -----------------------------------------------\n\t; Set up memory location to start drawing.\n\tmov  \tebx,[this]\t\t\t\t; get a pointer to dest\n\tmov\teax,[(GraphicViewPort ebx).GVPHeight]\t; get height of viewport\n\tmov\t[vpheight],eax\t\t\t\t; save off height of viewport\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\t; get width of viewport\n\tmov\t[vpwidth],eax\t\t\t\t; save it off for later\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\t; add in xadd for bytes_per_line\n\tmov\t[bufferwidth],eax     \t\t\t; save it off for later use.\n\n\tmul\t[y_pixel]\t\t\t\t; multiply rowsize * y_pixel start.\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get start of the viewport\n\tadd\tedi,eax\t\t\t\t\t; add y position to start of vp\n\tmov\t[curline],edi\t\t\t\t; save 0,y address for line feed stuff.\n\tadd\tedi,[x_pixel]\t\t\t\t; add to get starting column in starting row.\n\tmov\t[startdraw],edi\t\t\t\t; save it off.\n\n\tmov\teax,[x_pixel]\n\tmov\t[original_x],eax\n\n;-------------------------------- Create block pointers ----------------------------------------\n\t; Get the pointer to the font.\n\t; We could check for NULL but why waste the time.\n\t; It is up to programmer to make sure it is set.\n\tmov\tesi,[FontPtr]\t\t; Get the font pointer\n\tor\tesi,esi\n\tjz\t??overflow\n\n\t; Set up some pointers to the different memory blocks.\n\t; esi (FontPtr) is added to each to get the true address of each block.\n\t; Many registers are used for P5 optimizations.\n\t; ebx is used for InfoBlock which is then used in the next section.\n\tmovzx\teax,[WORD PTR esi+FONTOFFSETBLOCK]\t; get offset to offset block\n\tmovzx\tebx,[WORD PTR esi+FONTINFOBLOCK]      \t; get offset to info block (must be ebx for height test)\n\tmovzx\tecx,[WORD PTR esi+FONTWIDTHBLOCK] \t; get offset to width block\n\tmovzx\tedx,[WORD PTR esi+FONTHEIGHTBLOCK]\t; get offset to height block\n\n\tadd\teax,esi\t\t\t\t; add offset of FontPtr to offset block\n\tadd\tebx,esi\t\t\t\t; add offset of FontPtr to info block\n\tadd\tecx,esi\t\t\t\t; add offset of FontPtr to width block\n\tadd\tedx,esi\t\t\t\t; add offset of FontPtr to height block\n\n\tmov\t[offsetblock],eax\t\t; save offset to offset block\n\tmov\t[infoblock],ebx\t\t\t; save offset to info block\n\tmov\t[widthblock],ecx   \t\t; save offset to width block\n\tmov\t[heightblock],edx\t\t; save offset to height block\n\n;------------------------------------------ Test for fit ----------------------------------------------\n\t; Test to make sure the height of the max character will fit on this line\n\t; and and not fall out of the viewport.\n\t; remember we set ebx to FONTINFOBLOCK above.\n\tmovzx\teax,[BYTE PTR ebx + FONTINFOMAXHEIGHT]; get the max height in font.\n\tmov\t[maxheight],al\t\t\t; save it for later use.\n\tadd\teax,[y_pixel]\t\t\t; add current y_value.\n\tcmp\teax,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we're outa here.\n\n\tmov\t[y_pixel],eax\t\t\t; save for next line feed. y value for next line.\n\n\tcld\t\t\t\t\t; Make sure we are always forward copying.\n\n;------------------------ Set palette foreground and background ----------------------------------\n\tmov\teax,[fcolor]\t\t; foreground color\n\tmov\t[ColorXlat+1],al\n\tmov\t[ColorXlat+16],al\n\n\tmov\teax,[bcolor]\t\t; background color\n\tmov\t[ColorXlat],al\n\n;-------------------------------------------------------------------------------------------------\n;----------------------------------------- Main loop ----------------------------------------------\n\t; Now we go into the main loop of reading each character in the string and doing\n\t; something with it.\n??next_char:\n\t; while (*string++)\n\txor\teax,eax\t\t\t\t; zero out since we will just load al.\n\tmov\tesi,[string]\t\t\t; get address on next character.\n\tlodsb\t\t\t\t\t; load the character into al.\n\ttest\teax,0FFH\t\t\t; test to see if character is a NULL\n\tjz\t??done\t\t\t\t; character is NULL, get outa here.\n\n\tmov\tedi,[startdraw]\t\t\t; Load the starting address.\n\n\tmov\t[string],esi\t\t\t; save index into string. (incremented by lodsb)\n\n\tcmp\tal,10\t\t\t\t; is the character a line feed?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\n\tcmp\tal,13\t\t\t\t; is the character a line feed?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\n\tmov\t[char],eax\t\t\t; save the character off for later reference.\n\tmov\tebx,eax\t\t\t\t; save it in ebx for later use also.\n\n\tadd\teax,[widthblock]\t\t; figure address of width of character.\n\tmov\tecx,[x_pixel]\t\t\t; get current x_pixel.\n\tmovzx\tedx,[BYTE PTR eax]\t \t; get the width of the character in dl.\n\tadd\tecx,edx\t\t\t\t; add width of char to current x_pixel.\n\tmov\teax,[FontXSpacing]\n\tadd\tecx,eax\n\tadd\t[startdraw],edx\t\t\t; save start draw for next character.\n\tadd\t[startdraw],eax\t\t\t; adjust for the font spacing value\n\n\tcmp\tecx,[vpwidth]\t\t\t; is the pixel greater then the vp width?\n\tjg\t??force_line_feed\t\t; if so, force a line feed.\n\n\tmov\t[x_pixel],ecx\t\t\t; save value of start of next character.\n\tmov\tecx,[bufferwidth]\t\t; get amount to next y same x (one row down)\n\tsub\tecx,edx\t\t\t\t; take the current width off.\n\tmov\t[nextdraw],ecx\t\t\t; save it to add to edi when done with a row.\n\n\t; At this point we got the character. It is now time to find out specifics\n\t; about drawing the darn thing.\n\t; ebx = char so they can be used as an indexes.\n\t; edx = width of character for loop later.\n\n\t; get offset of data for character into esi.\n\tshl\tebx,1\t\t\t\t; mult by 2 to later use as a WORD index.\n\tmov\tesi,[offsetblock]\t\t; get pointer to begining of offset block.\n\tadd\tesi,ebx\t\t\t\t; index into offset block.\n\tmovzx\tesi,[WORD PTR esi]\t\t; get true offset into data block from FontPtr.\n\tadd\tesi,[FontPtr]\t\t\t; Now add FontPtr address to get true address.\n\n\t; Get top and bottom blank sizes and the true height of the character.\n\tadd\tebx,[heightblock]\t\t; point ebx to element in height array.\n\tmov\tal,[ebx+1]\t\t\t; load the data height into dl.\n\tmov\tcl,[ebx]\t\t\t; load the first data row into cl.\n\tmov\tbl,[maxheight]\t\t\t; get the max height of characters.\n\tmov\t[charheight],al\t\t\t; get number of rows with data.\n\tadd\tal,cl\t\t\t\t; add the two heights.\n\tsub\tbl,al\t\t\t\t; subract topblank + char height from maxheight.\n\tmov\t[bottomblank],bl\t\t; save off the number of blank rows on the bottom.\n\t; leaving this section:\n\t; dl is still the width of the character.\n\t; cl is the height of the top blank area.\n\n\tmov\tebx,OFFSET ColorXlat\t\t; setup ebx for xlat commands.\n\tmov\tdh,dl\t\t\t\t; save the width of the character to restore each loop.\n\n\tcmp\tcl,0\t\t\t\t; is there any blank rows on top?\n\tjz\t??draw_char\t\t\t; if not go and draw the real character.\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjnz\t??loop_top\t\t\t; if not go and write the color\n\n;----------------------------------------- skip Top blank area ----------------------------------------\n\t; this case, the top is transparrent, but we need to increase our dest pointer to correct row.\n\tmovzx\teax,cl\t\t\t\t; get number of rows into eax;\n\tmov\tecx,edx\t\t\t\t; save width since edx will be destroyed by mul.\n\tmul\t[bufferwidth]\t\t\t; multiply that by the width of the buffer.\n\tmov\tedx,ecx\t\t\t\t; restore the width\n\tadd\tedi,eax\t\t\t\t; update the pointer.\n\tjmp\tshort ??draw_char\t\t; now go draw the character.\n\n;----------------------------------------- fill Top blank area ----------------------------------------\n\t; edi was set a long time ago.\n\t; al is the translated color\n??loop_top:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_top\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tdec\tcl\t\t\t\t; decrement or row count\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tjz\t??draw_char\t\t\t; we are done here, go draw the character.\n\tjmp\tshort ??loop_top\t\t; go back to top of loop.\n\n\n;----------------------------------------- Draw character ----------------------------------------------\n??draw_char:\n\tmovzx\tecx,[charheight]\t\t; get the height of character to count down rows.\n\ttest\tecx,ecx\t\t\t\t; is there any data? (blank would not have any)\n\tjz\t??next_char\t\t\t; if no data, go on to next character.\n\n??while_data:\n\tlodsb\t\t\t\t\t; get byte value from font data\n\tmov\tah,al\t\t\t\t; save hinibble\n\tand\teax,0F00FH\t       \t\t; mask of low nibble in al hi nibble in ah.\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiplo\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiplo:\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjz\tshort ??nextrow\t\t\t; check if done with width of char\n\n\tmov\tal,ah\t\t\t\t; restore to get\n\t; test the time difference between looking up in a large table when shr al,4 is not done as\n\t; compared to using only a 16 byte table when using the shr al,4\n\t;shr\tal,4\t\t\t\t; shift the hi nibble down to low nibble\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiphi\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiphi:\n\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\tshort ??while_data\t\t; check if done with width of char\n\n??nextrow:\n\tadd\tedi,[nextdraw]\t\t\t; go to next line.\n\tdec\tecx\t\t\t\t; decrement the number of rows to go\n\tmov\tdh,dl\t\t\t\t; restore our column count for row.\n\tjnz\t??while_data\t\t\t; more data for character.\n\n\t; Now it is time to setup for clearing out the bottom of the character.\n\tmovzx\tecx,[bottomblank]\t\t; get amount on bottom that is blank\n\tcmp\tecx,0\t\t\t\t; if there is no blank bottom...\n\tjz\t??next_char\t\t\t; then skip to go to next character\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjz\t??next_char\t\t\t; skip the top black section to let the background through\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\n;----------------------------------------- Blank below character -----------------------------------\n??loop_bottom:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_bottom\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tdec\tcl\t\t\t\t; decrement or row count\n\tjz\t??next_char\t\t\t; we are done here, go to the next character.\n\tjmp\tshort ??loop_bottom\t\t; go back to top of loop.\n\n;----------------------------------- end of next_char (main) loop ------------------------------------\n;-------------------------------------------------------------------------------------------------\n\n\n;----------------------------------- special case line feeds ----------------------------------------\n\n??force_line_feed:\n\t; decrement pointer *string so that it will be back at same character\n\t; when it goes through the loop.\n\tmov\teax,[string]\t\t\t; get string pointer.\n\tdec\teax\t\t\t\t; decrement it to point to previos char\n\tmov\t[string],eax\t\t\t; save it back off.\n\txor\teax,eax\n\t; Now go into the line feed code.....\n\n??line_feed:\n\tmov\tbl,al\n\tmov\tedx,[y_pixel]\t\t\t; get the current y pixel value.\n\tmovzx\tecx,[maxheight]\t\t\t; get max height for later use.\n\tadd\tecx,[FontYSpacing]\n\tadd\tedx,ecx\t\t\t\t; add max height to y_pixel\n\tcmp\tedx,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we are outa here.\n\n\tmov\teax,[bufferwidth]      \t\t; get bytes to next line.\n\tmov\tedi,[curline]\t\t\t; get start of current line.\n\tmul\tecx\t\t\t\t; mult max height * next line.\n\n\tadd\tedi,eax\t\t\t\t; add adjustment to current line.\n\tadd\t[y_pixel],ecx\t\t\t; increment to our next y position.\n;;; DRD\n\tmov\t[curline],edi\t\t\t; save it off for next line_feed.\n\n\t; Move the cursor to either the left edge of the screen\n\t; or the left margin of the print position depending\n\t; on whether <CR> or <LF> was specified. <CR> = left margin\n\t; <LF> = left edge of screen\n\txor\teax,eax\n\tcmp\tbl,10\n\tje\t??lfeed\n\tmov\teax,[original_x]\n??lfeed:\n\tmov\t[x_pixel],eax\t\t\t; zero out x_pixel\n\n\tadd\tedi,eax\n;;; DRD\tmov\t[curline],edi\t\t\t; save it off for next line_feed.\n\tmov\t[startdraw],edi\t\t\t; save it off so we know where to draw next char.w\n\n\tjmp\t??next_char\n\n??overflow:\n\tmov\t[startdraw],0\t\t\t; Indicate that there is no valid next pos.\n??done:\n\tmov\teax,[startdraw]\t\t\t; return this so calling routine\n\tret\t\t\t\t\t; can figure out where to draw next.\n\n\tENDP\tMCGA_Print\n;***************************************************************************\n;* GET_FONT_PALETTE_PTR -- Returns a pointer to the 256 byte font palette  *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tvoid *Get_Font_Palette_Ptr(void);                          *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   08/18/1995 PWG : Created.                                             *\n;*=========================================================================*\n\n\tGLOBAL\tGet_Font_Palette_Ptr:NEAR\n\tPROC\tGet_Font_Palette_Ptr C near\n\tmov\teax, OFFSET ColorXlat\n\tret\n\tENDP\tGet_Font_Palette_Ptr\n\n\nEND\n"
  },
  {
    "path": "CODE/TYPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/TYPE.H 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TYPE.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 14, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 14, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TYPE_H\n#define TYPE_H\n\n#include\t\"mission.h\"\n#include\t\"target.h\"\n\nclass MapEditClass;\nclass HouseClass;\nclass WeaponTypeClass;\n\n\n/***************************************************************************\n**\tThis is the abstract type class. It holds information common to all\n**\tobjects that might exist. This contains the name of the object type.\n*/\nclass AbstractTypeClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tThis serves to identify the object class. The ID corresponds to the\n\t\t**\tvariation number (e.g., UNIT_TANK1, UNIT_TANK2, etc.).\n\t\t*/\n\t\tRTTIType RTTI;\n\t\tint ID;\n\n\t\t/*\n\t\t**\tThis is the internal control name of the object. This name does\n\t\t**\tnot change regardless of language specified. This is the name\n\t\t**\tused in scenario control files and for other text based unique\n\t\t**\tidentification purposes.\n\t\t*/\n\t\tchar IniName[24];\n\n\t\t/*\n\t\t**\tThe translated (language specific) text name number of this object.\n\t\t**\tThis number is used to fetch the object's name from the language\n\t\t**\ttext file. Whenever the name of the object needs to be displayed,\n\t\t**\tthis is used to determine the text string.\n\t\t*/\n\t\tint FullName;\n\n\t\tAbstractTypeClass(RTTIType rtti, int id, int name, char const * ini);\n\t\tAbstractTypeClass(NoInitClass const & ) {};\n\t\t~AbstractTypeClass(void) {};\n\n\t\tRTTIType What_Am_I(void) const {return(RTTI);};\n\t\tTARGET As_Target(void) const {return(Build_Target(RTTI, ID));};\n\n\t\tvirtual COORDINATE Coord_Fixup(COORDINATE coord) const;\n\t\tvirtual int Full_Name(void) const;\n\t\tchar const * Name(void) const {return(IniName);}\n\t\tvoid Set_Name(char const * buf) const {\n\t\t\tstrncpy((char *)IniName, buf, sizeof(IniName));\n\t\t\t((char &)IniName[sizeof(IniName)-1]) = '\\0';\n\t\t};\n\t\tvirtual int Get_Ownable(void) const;\n\n\t\tvoid Code_Pointers(void) {}\n\t\tvoid Decode_Pointers(void) {}\n};\n\n\n/**********************************************************************\n**\tEach house has certain unalienable characteristics. This structure\n**\telaborates these.\n*/\nclass HouseTypeClass : public AbstractTypeClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis is the house number (enum). This is a unique identification\n\t\t**\tnumber for the house.\n\t\t*/\n\t\tHousesType House;\n\n\t\t/*\n\t\t**\tThis is the filename suffix to use when creating a house specific\n\t\t**\tfile name. It is three characters long.\n\t\t*/\n\t\tchar Suffix[_MAX_EXT];\n\n\t\t/*\n\t\t**\tThis is the \"lemon percentage\" to use when determining if a particular\n\t\t**\tobject owned by this house is to be flagged as a \"lemon\". Objects so\n\t\t**\tflagged have a greater break-down chance. The percentage is expressed\n\t\t**\tas a fixed point number with 0x000 meaning 0% and 0x100 meaning 100%.\n\t\t*/\n\t\tunsigned Lemon;\n\n\t\t/*\n\t\t**\tThis points to the default remap table for this house.\n\t\t*/\n\t\tPlayerColorType RemapColor;\n\n\t\t/*\n\t\t**\tThis is a unique ASCII character used when constructing filenames. It\n\t\t**\tserves a similar purpose as the \"Suffix\" element, but is only one\n\t\t**\tcharacter long.\n\t\t*/\n\t\tchar Prefix;\n\n\t\t/*\n\t\t**\tThis controls the various general adjustments to the house owned\n\t\t**\tunit and building ratings. The default value for these ratings is\n\t\t**\ta fixed point number of 1.0.\n\t\t*/\n\t\tfixed FirepowerBias;\n\t\tfixed GroundspeedBias;\n\t\tfixed AirspeedBias;\n\t\tfixed ArmorBias;\n\t\tfixed ROFBias;\n\t\tfixed CostBias;\n\t\tfixed BuildSpeedBias;\n\n\t\t//------------------------------------------------------------------------\n\t\tHouseTypeClass(NoInitClass const & x) : AbstractTypeClass(x) {}\n\t\tHouseTypeClass(HousesType house,\n\t\t\t\t\t\t\tchar const * ini,\n\t\t\t\t\t\t\tint fullname,\n\t\t\t\t\t\t\tchar const * ext,\n\t\t\t\t\t\t\tint lemon,\n\t\t\t\t\t\t\tPlayerColorType remapcolor,\n\t\t\t\t\t\t\tchar prefix);\n\n\t\tunsigned char const * Remap_Table(void) const;\n\n\t\tstatic void * operator new(size_t);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void * ptr);\n\n\t\tstatic HousesType From_Name(char const * name);\n\t\tstatic HouseTypeClass & As_Reference(HousesType house);\n\t\tstatic void One_Time(void);\n\t\tstatic void Init_Heap(void);\n\n\t\tvirtual bool Read_INI(CCINIClass & ini);\n};\n\n\n/***************************************************************************\n**\tThis the the common base class of game objects. Since these values\n**\trepresent the unchanging object TYPES, this data is initialized at game\n**\tstart and not changed during play. It is \"const\" data.\n*/\nclass ObjectTypeClass : public AbstractTypeClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis is the base name of the graphic data associated with this object\n\t\t**\ttype. If the graphic name is a null string, then there is no graphic\n\t\t**\tassociated with this object type.\n\t\t*/\n\t\tchar GraphicName[_MAX_FNAME];\n\n\t\t/*\n\t\t**\tIs this object squashable by heavy vehicles?  If it is, then the vehicle\n\t\t**\tcan travel over this object and destroy it in the process.\n\t\t*/\n\t\tunsigned IsCrushable:1;\n\n\t\t/*\n\t\t**\tDoes this object type NOT show up on radar scans?  If true, then in any\n\t\t**\tradar display, only the underlying ground will be show, not this object.\n\t\t**\tMost terrain falls into this category, but only a few special real units/buildings\n\t\t**\tdo.\n\t\t*/\n\t\tunsigned IsStealthy:1;\n\n\t\t/*\n\t\t**\tIt is legal to \"select\" some objects in the game. If it is legal to select this\n\t\t**\tobject type then this flag will be true. Selected game objects typically display\n\t\t**\ta floating health bar and allows special user I/O control.\n\t\t*/\n\t\tunsigned IsSelectable:1;\n\n\t\t/*\n\t\t**\tCan this object be the target of an attack or move command?  Typically, only objects\n\t\t**\tthat take damage or can be destroyed are allowed to be a target.\n\t\t*/\n\t\tunsigned IsLegalTarget:1;\n\n\t\t/*\n\t\t**\t\"Insignificant\" objects will not be announced when they are destroyed or when they\n\t\t**\tappear. Terrain elements and some lesser vehicles have this characteristic.\n\t\t*/\n\t\tunsigned IsInsignificant:1;\n\n\t\t/*\n\t\t**\tIs this object immune to normal combat damage?  Rocks and other inert type terrain\n\t\t**\tobject are typically of this type.\n\t\t*/\n\t\tunsigned IsImmune:1;\n\n\t\t/*\n\t\t**\t\"Sentient\" objects are ones that have logic AI processing performed on them. All\n\t\t**\tvehicles, buildings, infantry, and aircraft are so flagged. Terrain elements also\n\t\t**\tfall under this category, but only because certain animation effects require this.\n\t\t*/\n\t\tunsigned IsSentient:1;\n\n\t\t/*\n\t\t**\tIf this object type affects the occupation and collision logic associated with\n\t\t**\tcells, then this flag will be true. Typically, this characteristic is limited\n\t\t**\tto buildings, units, terrain objects, and landed aircraft.\n\t\t*/\n\t\tunsigned IsFootprint:1;\n\n\t\t/*\n\t\t**\tThe defense of this object is greatly affected by the type of armor\n\t\t**\tit possesses. This value specifies the type of armor.\n\t\t*/\n\t\tArmorType Armor;\n\n\t\t/*\n\t\t**\tThis is the maximum strength of this object type.\n\t\t*/\n\t\tunsigned short MaxStrength;\n\n\t\t/*\n\t\t**\tThese point to the shape imagery for this object type. Since the shape imagery\n\t\t**\texists in a separate file, the data is filled in after this object is constructed.\n\t\t**\tThe \"mutable\" keyword allows easy modification to this otherwise const object.\n\t\t*/\n\t\tvoid const * ImageData;\n\n\t\t/*\n\t\t**\tPoints to the dimension data for each shape in the image list. By using this\n\t\t**\tdata, the minimum number of cells will be redrawn when the object changes shape.\n\t\t*/\n\t\tRect * DimensionData;\n\n\t\t/*\n\t\t**\tThis points to the radar imagery for this object.\n\t\t*/\n\t\tvoid const * RadarIcon;\n\n\t\t//--------------------------------------------------------------------\n\t\tObjectTypeClass(NoInitClass const & x) : AbstractTypeClass(x) {}\n\t\tObjectTypeClass(\tRTTIType rtti,\n\t\t\t\t\t\t\t\tint id,\n\t\t\t\t\t\t\t\tbool is_sentient,\n\t\t\t\t\t\t\t\tbool is_stealthy,\n\t\t\t\t\t\t\t\tbool is_selectable,\n\t\t\t\t\t\t\t\tbool is_legal_target,\n\t\t\t\t\t\t\t\tbool is_insignificant,\n\t\t\t\t\t\t\t\tbool is_immune,\n\t\t\t\t\t\t\t\tbool is_footprint,\n\t\t\t\t\t\t\t\tint fullname,\n\t\t\t\t\t\t\t\tchar const * name\n\t\t\t\t\t\t\t\t);\n\n\t\tstatic void One_Time(void);\n\n\t\tbool Is_Foot(void) const {return(RTTI == RTTI_INFANTRYTYPE || RTTI == RTTI_UNITTYPE || RTTI == RTTI_VESSELTYPE || RTTI == RTTI_AIRCRAFTTYPE);};\n\t\tchar const * Graphic_Name(void) const {if (GraphicName[0] != '\\0') return(GraphicName); return(Name());}\n\t\tvirtual int Max_Pips(void) const;\n\t\tvirtual void Dimensions(int &width, int &height) const;\n\t\tvirtual bool Create_And_Place(CELL , HousesType =HOUSE_NONE) const = 0;\n\t\tvirtual int Cost_Of(void) const;\n\t\tvirtual int Time_To_Build(void) const;\n\t\tvirtual ObjectClass * Create_One_Of(HouseClass *) const = 0;\n\t\tvirtual short const * Occupy_List(bool placement=false) const;\n\t\tvirtual short const * Overlap_List(void) const;\n\t\tvirtual BuildingClass * Who_Can_Build_Me(bool intheory, bool legal, HousesType house) const;\n\t\tvirtual void const * Get_Cameo_Data(void) const;\n\t\tvoid const * Get_Image_Data(void) const {return ImageData;};\n\t\tvoid const * Get_Radar_Data(void) const {return RadarIcon;};\n\n\t\t#ifdef SCENARIO_EDITOR\n\t\tvirtual void Display(int, int, WindowNumberType, HousesType) const {};\n\t\t#endif\n\n\t\tstatic void const * SelectShapes;\n\t\tstatic void const * PipShapes;\n};\n\n\n/***************************************************************************\n**\tThis class is the common data for all objects that can be owned, produced,\n** or delivered as reinforcements. These are objects that typically contain\n**\tcrews and weapons -- the fighting objects of the game.\n*/\nclass TechnoTypeClass : public ObjectTypeClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tThis controls how this object type is remapped when it is displayed\n\t\t**\tin the sidebar.\n\t\t*/\n\t\tRemapType Remap;\n\n\t\t/*\n\t\t**\tIs this object ownable by all sides in a multiplayer game? There are some\n\t\t**\tspecial case objects that need this override ability.\n\t\t*/\n\t\tunsigned IsDoubleOwned:1;\n\n\t\t/*\n\t\t**\tIf this object should be completely and always invisible to the enemy, then\n\t\t**\tthis flag will be true.\n\t\t*/\n\t\tunsigned IsInvisible:1;\n\n\t\t/*\n\t\t**\tIf this object can serve as a good leader for a group selected\n\t\t**\tseries of objects, then this flag will be true. Unarmed or\n\t\t**\tability challenged units do not make good leaders. This flag is\n\t\t**\talso used to indicate the primary factory when dealing with\n\t\t**\tbuildings.\n\t\t*/\n\t\tunsigned IsLeader:1;\n\n\t\t/*\n\t\t**\tDoes this object have the ability to detect the presence of a nearby\n\t\t**\tcloaked object?\n\t\t*/\n\t\tunsigned IsScanner:1;\n\n\t\t/*\n\t\t**\tIf this object is always given its proper name rather than a generic\n\t\t**\tname, then this flag will be true. Typically, civilians and Dr. Moebius\n\t\t**\tfall under this category.\n\t\t*/\n\t\tunsigned IsNominal:1;\n\n\t\t/*\n\t\t**\tIf the artwork for this object (only for generics) is theater specific, then\n\t\t**\tthis flag will be true. Civilian buildings are a good example of this.\n\t\t*/\n\t\tunsigned IsTheater:1;\n\n\t\t/*\n\t\t**\tDoes this object type contain a rotating turret?  Gun emplacements, SAM launchers,\n\t\t**\tand many vehicles contain a turret. If a turret is present, special rendering and\n\t\t**\tcombat logic must be performed.\n\t\t*/\n\t\tunsigned IsTurretEquipped:1;\n\n\t\t/*\n\t\t**\tCertain objects can be repaired. For buildings, they repair \"in place\". For units,\n\t\t**\tthey must travel to a repair center to be repaired. If this flag is true, then\n\t\t**\tallow the player or computer AI to repair the object.\n\t\t*/\n\t\tunsigned IsRepairable:1;\n\n\t\t/*\n\t\t**\tDoes this object contain a crew?  If it does, then when the object is destroyed, there\n\t\t**\tis a distinct possibility that infantry will \"pop out\". Only units with crews can\n\t\t**\tbecome \"heros\".\n\t\t*/\n\t\tunsigned IsCrew:1;\n\n\t\t/*\n\t\t**\tThis tells whether this unit should EVER be remapped when it is displayed\n\t\t**\ton the tactical map. Normally, the unit is remapped, but for certain civilian\n\t\t**\tobject, remapping is not to be performed, regardless of owner.\n\t\t*/\n\t\tunsigned IsRemappable:1;\n\n\t\t/*\n\t\t** Is the unit capable of cloaking?  Only Stealth Tank can do so now.\n\t\t*/\n\t\tunsigned IsCloakable:1;\n\n\t\t/*\n\t\t**\tCan this object self heal up to half strength? Mammoth tanks from C&C had this\n\t\t**\tfeature.\n\t\t*/\n\t\tunsigned IsSelfHealing:1;\n\n\t\t/*\n\t\t**\tIf this object explodes violently when destroyed, then this flag will be true.\n\t\t**\tThe type of explosion is based on the warhead type and the damage generated\n\t\t**\tcorresponds to the full strength of the object.\n\t\t*/\n\t\tunsigned IsExploding:1;\n\n\t\t/*\n\t\t**\tThis specifies the zone that an object of this type should recognize. Zones\n\t\t**\tof this type or lower will be considered \"possible to travel to\".\n\t\t*/\n\t\tMZoneType MZone;\n\n\t\t/*\n\t\t**\tWhen determining threat, the range can be overridden to be the value\n\t\t**\tspecified here. Otherwise, the range for enemy scan is equal to the\n\t\t**\tlongest weapon range the object has. If the value is zero, then the\n\t\t**\tweapon range is used.\n\t\t*/\n\t\tLEPTON ThreatRange;\n\n\t\t/*\n\t\t**\tIf this is a transporter object (e.g., hovercraft, chinook, APC), then this\n\t\t**\tvalue specifies the maximum number of passengers it may carry.\n\t\t*/\n\t\tint MaxPassengers;\n\n\t\t/*\n\t\t**\tMost objects have the ability to reveal the terrain around themselves.\n\t\t**\tThis sight range (expressed in cell distance) is specified here. If\n\t\t**\tthis value is 0, then this unit never reveals terrain. Bullets are\n\t\t**\ttypically of this nature.\n\t\t*/\n\t\tint SightRange;\n\n\t\t/*\n\t\t**\tThis is the credit cost to produce this object (presuming production is\n\t\t**\tallowed).\n\t\t*/\n\t\tint Cost;\n\n\t\t/*\n\t\t**\tThe tech level that this object can be produced at.\n\t\t*/\n\t\tunsigned Level;\n\n\t\t/*\n\t\t**\tThis specifies the building prerequisites required before an object\n\t\t**\tof this type can be produced.\n\t\t*/\n\t\tlong Prerequisite;\n\n\t\t/*\n\t\t**\tThe risk and reward values are used to determine targets and paths\n\t\t**\ttoward targets. When heading toward a target, a path of least\n\t\t**\trisk will be followed. When picking a target, the object of\n\t\t**\tgreatest reward will be selected. The values assigned are\n\t\t** arbitrary.\n\t\t*/\n\t\tint Risk,Reward;\n\n\t\t/*\n\t\t**\tThis value indicates the maximum speed that this object can achieve.\n\t\t*/\n\t\tMPHType MaxSpeed;\n\n\t\t/*\n\t\t**\tThis indicates the speed (locomotion) type for this unit. Through this\n\t\t**\tvalue the movement capabilities are deduced.\n\t\t*/\n\t\tSpeedType Speed;\n\n\t\t/*\n\t\t**\tThis is the maximum number of ammo shots this object can hold. If\n\t\t**\tthis number is -1, then this indicates unlimited ammo.\n\t\t*/\n\t\tint MaxAmmo;\n\n\t\t/*\n\t\t**\tThis is a bit field representing the houses that are allowed to\n\t\t**\town (by normal means) this particular object type. This value is\n\t\t**\ttypically used in production contexts. It is possible for a side\n\t\t**\tto take possession of an object type otherwise not normally allowed.\n\t\t**\tThis event usually occurs as a result of capture.\n\t\t*/\n\t\tlong Ownable;\n\n\t\t/*\n\t\t**\tThis is the small icon image that is used to display the object in\n\t\t**\tthe sidebar for construction selection purposes.\n\t\t*/\n\t\tvoid const * CameoData;\n\n\t\t/*\n\t\t**\tThe number of animation frames allotted to rotation is specified here.\n\t\t**\tFor an object that has no rotation, this value will be 1. For normal\n\t\t**\tvehicles this value will be 32. There are some special case units that\n\t\t**\thave intermediate rotation frames.\n\t\t*/\n\t\tint Rotation;\n\n\t\t/*\n\t\t**\tThis is the rotational speed of the object. This value represents the\n\t\t**\tturret or body rotation speed expresses as 360/256ths rotation steps per\n\t\t**\tgame tick.\n\t\t*/\n\t\tint ROT;\n\n\t\t/*\n\t\t**\tThese are the weapons that this techno object is armed with.\n\t\t*/\n\t\tWeaponTypeClass const * PrimaryWeapon;\n\t\tWeaponTypeClass const * SecondaryWeapon;\n\n\t\t/*\n\t\t**\tThese specify the lepton offsets to locate the exact coordinate of the\n\t\t**\t'tip of the barrel' for the weapon. This is used for generating the bullet\n\t\t**\tat the proper location.\n\t\t*/\n\t\tint VerticalOffset;\t\t\t// Distance to move north (compensates for perspective).\n\t\tint PrimaryOffset;\t\t\t// Offset along turret centerline and facing.\n\t\tint PrimaryLateral;\t\t\t// Sideways offset from turret centerline and facing.\n\t\tint SecondaryOffset;\n\t\tint SecondaryLateral;\n\n\t\t/*\n\t\t** Points you're awarded for destroying an object of this type, and\n\t\t** points you lose if you lose an object of this type.\n\t\t*/\n\t\tint Points;\n\n\t\t//--------------------------------------------------------------------\n\t\tTechnoTypeClass(NoInitClass const & x) : ObjectTypeClass(x) {}\n\t\tTechnoTypeClass(\n\t\t\t\tRTTIType rtti,\n\t\t\t\tint id,\n\t\t\t\tint name,\n\t\t\t\tchar const * ininame,\n\t\t\t\tRemapType remap,\n\t\t\t\tint verticaloffset,\n\t\t\t\tint primaryoffset,\n\t\t\t\tint primarylateral,\n\t\t\t\tint secondaryoffset,\n\t\t\t\tint secondarylateral,\n\t\t\t\tbool is_nominal,\n\t\t\t\tbool is_stealthy,\n\t\t\t\tbool is_selectable,\n\t\t\t\tbool is_legal_target,\n\t\t\t\tbool is_insignificant,\n\t\t\t\tbool is_immune,\n\t\t\t\tbool is_theater,\n\t\t\t\tbool is_turret_equipped,\n\t\t\t\tbool is_remappable,\n\t\t\t\tbool is_footprint,\n\t\t\t\tint rotation,\n\t\t\t\tSpeedType speed\n\t\t\t\t);\n\n\t\tbool Is_Two_Shooter(void) const;\n\t\tint Legal_Placement(CELL pos) const;\n\t\tvirtual int Raw_Cost(void) const;\n\t\tvirtual int Max_Passengers(void) const {return(MaxPassengers);}\n\t\tvirtual int Repair_Cost(void) const;\n\t\tvirtual int Repair_Step(void) const;\n\t\tvirtual void const * Get_Cameo_Data(void) const;\n\t\tvirtual int Cost_Of(void) const;\n\t\tvirtual int Time_To_Build(void) const;\n\t\tvirtual int Get_Ownable(void) const;\n\t\tvirtual bool Read_INI(CCINIClass & ini);\n\n\t\t/*\n\t\t**\tThis is a pointer to the wake shape (as needed by the gunboat).\n\t\t*/\n\t\tstatic void const * WakeShapes;\n\t\tstatic void const * TurretShapes;\n\t\tstatic void const * SamShapes;\n\t\tstatic void const * MGunShapes;\n};\n\n\n/***************************************************************************\n**\tBuilding types need some special information custom to buildings. This\n**\tis a derived class that elaborates these additional data elements.\n*/\nclass BuildingTypeClass : public TechnoTypeClass {\n\tpublic:\n\t\t/*\n\t\t**\tIs this building allowed to be considered for building adjacency\n\t\t**\tchecking? If false, then building off of (or adjacent to) this building\n\t\t**\tis not considered.\n\t\t*/\n\t\tunsigned IsBase:1;\n\n\t\t/*\n\t\t** If this building is a fake, this flag will be set.\n\t\t*/\n\t\tunsigned IsFake:1;\n\n\t\t/*\n\t\t**\tThis flag controls whether the building is equiped with a dirt\n\t\t**\tbib or not. A building with a bib has a dirt patch automatically\n\t\t**\tattached to the structure when it is placed.\n\t\t*/\n\t\tunsigned IsBibbed:1;\n\n\t\t/*\n\t\t**\tIf this building is a special wall type, such that it exists as a building\n\t\t**\tfor purposes of construction but transforms into an overlay wall object when\n\t\t**\tit is placed on the map, then this flag will be true.\n\t\t*/\n\t\tunsigned IsWall:1;\n\n\t\t/*\n\t\t**\tBuildings can have either simple or complex damage stages. If simple,\n\t\t**\tthen the second to the last frame is the half damage stage, and the last\n\t\t**\tframe is the complete damage stage. For non-simple damage, buildings\n\t\t**\thave a complete animation set for damaged as well as undamaged condition.\n\t\t**\tTurrets, oil pumps, and repair facilities are a few examples.\n\t\t*/\n\t\tunsigned IsSimpleDamage:1;\n\n\t\t/*\n\t\t**\tCertain building types can be captures by enemy infantry. For those\n\t\t**\tbuilding types, this flag will be true. Typically, military or hardened\n\t\t**\tstructures such as turrets cannot be captured.\n\t\t*/\n\t\tunsigned IsCaptureable:1;\n\n\t\t/*\n\t\t**\tIf this building really only has cosmetic idle animation, then this flag will be\n\t\t**\ttrue if this animation should run at a relatively constant rate regardless of game\n\t\t**\tspeed setting.\n\t\t*/\n\t\tunsigned IsRegulated:1;\n\n\t\t/*\n\t\t**\tDoes this building require power to function? Usually, this isn't the case. The building\n\t\t**\tnormally either has no effect by power level or is gradually reduced in effectiveness. This\n\t\t**\tflag is for those buildings that completely cease to function when the power drops below\n\t\t**\tfull.\n\t\t*/\n\t\tunsigned IsPowered:1;\n\n\t\t/*\n\t\t**\tIf this flag is true, then the building cannot be sold even if it could have been built. This\n\t\t**\tis especially useful for mines which can be built but cannot be sold.\n\t\t*/\n\t\tunsigned IsUnsellable:1;\n\n\t\t/*\n\t\t**\tThis is the direction (from the center cell) of the building in order to find a\n\t\t**\tlegitimate foundation square. This location will be used for targeting and capture\n\t\t**\tmove destination purposes.\n\t\t*/\n\t\tFacingType FoundationFace;\n\n\t\t/*\n\t\t**\tAdjacent distance for building next to.\n\t\t*/\n\t\tint Adjacent;\n\n\t\t/*\n\t\t**\tThis flag specifies the type of object this factory building can \"produce\". For non\n\t\t**\tfactory buildings, this value will be RTTI_NONE.\n\t\t*/\n\t\tRTTIType ToBuild;\n\n\t\t/*\n\t\t**\tFor building that produce ground units (infantry and vehicles), there is a default\n\t\t**\texit point defined. This point is where the object is first placed on the map.\n\t\t**\tTypically, this is located next to a door. The unit will then travel on to a clear\n\t\t**\tterrain area and enter normal game processing.\n\t\t*/\n\t\tCOORDINATE ExitCoordinate;\n\n\t\t/*\n\t\t**\tWhen determine which cell to head toward when exiting a building, use the\n\t\t**\tlist elaborated by this variable. There are directions of exit that are\n\t\t**\tmore suitable than others. This list is here to inform the system which\n\t\t**\tdirections those are.\n\t\t*/\n\t\tshort const * ExitList;\n\n\t\t/*\n\t\t**\tThis is the structure type identifier. It can serve as a unique\n\t\t**\tidentification number for building types.\n\t\t*/\n\t\tStructType Type;\n\n\t\t/*\n\t\t**\tThis is the starting facing to give this building when it first\n\t\t**\tgets constructed. The facing matches the final stage of the\n\t\t**\tconstruction animation.\n\t\t*/\n\t\tDirType StartFace;\n\n\t\t/*\n\t\t**\tThis is the Tiberium storage capacity of the building. The sum of all\n\t\t**\tbuilding's storage capacity is used to determine how much Tiberium can\n\t\t**\tbe accumulated.\n\t\t*/\n\t\tint Capacity;\n\n\t\t/*\n\t\t**\tEach building type produces and consumes power. These values tell how\n\t\t**\tmuch.\n\t\t*/\n\t\tint Power;\n\t\tint Drain;\n\n\t\t/*\n\t\t**\tThis is the size of the building. This size value is a rough indication\n\t\t**\tof the building's \"footprint\".\n\t\t*/\n\t\tBSizeType Size;\n\n\t\t/**********************************************************************\n\t\t**\tFor each stage that a building may be in, its animation is controlled\n\t\t**\tby this structure. It dictates the starting and length of the animation\n\t\t**\tframes needed for the specified state. In addition it specifies how long\n\t\t**\tto delay between changes in animation. With this data it is possible to\n\t\t**\tcontrol the appearance of all normal buildings. Turrets and SAM sites are\n\t\t**\tan exception since their animation is not merely cosmetic.\n\t\t*/\n\t\ttypedef struct {\n\t\t\tint\tStart;\t\t\t// Starting frame of animation.\n\t\t\tint\tCount;\t\t\t// Number of frames in this animation.\n\t\t\tint\tRate;\t\t\t\t// Number of ticks to delay between each frame.\n\t\t} AnimControlType;\n\t\tAnimControlType Anims[BSTATE_COUNT];\n\n\t\t/*---------------------------------------------------------------------------\n\t\t**\tThis is the building type explicit constructor.\n\t\t*/\n\t\tBuildingTypeClass(NoInitClass const & x) : TechnoTypeClass(x) {}\n\t\tBuildingTypeClass\t(\n\t\t\t\t\t\tStructType type,\n\t\t\t\t\t\tint name,\n\t\t\t\t\t\tchar const * ininame,\n\t\t\t\t\t\tFacingType foundation,\n\t\t\t\t\t\tCOORDINATE exitpoint,\n\t\t\t\t\t\tRemapType remap,\n\t\t\t\t\t\tint verticaloffset,\n\t\t\t\t\t\tint primaryoffset,\n\t\t\t\t\t\tint primarylateral,\n\t\t\t\t\t\tbool is_fake,\n\t\t\t\t\t\tbool is_regulated,\n\t\t\t\t\t\tbool is_nominal,\n\t\t\t\t\t\tbool is_wall,\n\t\t\t\t\t\tbool is_simpledamage,\n\t\t\t\t\t\tbool is_stealthy,\n\t\t\t\t\t\tbool is_selectable,\n\t\t\t\t\t\tbool is_legal_target,\n\t\t\t\t\t\tbool is_insignificant,\n\t\t\t\t\t\tbool is_theater,\n\t\t\t\t\t\tbool is_turret_equipped,\n\t\t\t\t\t\tbool is_remappable,\n\t\t\t\t\t\tRTTIType tobuild,\n\t\t\t\t\t\tDirType sframe,\n\t\t\t\t\t\tBSizeType size,\n\t\t\t\t\t\tshort const * exitlist,\n\t\t\t\t\t\tshort const * sizelist,\n\t\t\t\t\t\tshort const * overlap\n\t\t\t\t\t\t);\n\t\toperator StructType(void) const {return(Type);};\n\n\t\tstatic void * operator new(size_t);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void * ptr);\n\n\t\tstatic void Init_Heap(void);\n\t\tstatic BuildingTypeClass & As_Reference(StructType type);\n\t\tstatic StructType From_Name(char const * name);\n\t\tstatic void Init(TheaterType theater);\n\t\tstatic void One_Time(void);\n\t\tstatic void Prep_For_Add(void);\n\n\t\tint Width(void) const;\n\t\tint Height(bool bib=false) const;\n\n\t\tvirtual int Full_Name(void) const;\n\t\tvirtual bool Read_INI(CCINIClass & ini);\n\t\tbool Flush_For_Placement(CELL cell, HouseClass * house) const;\n\t\tvirtual int Cost_Of(void) const;\n\t\tvirtual COORDINATE Coord_Fixup(COORDINATE coord) const;\n\t\tvirtual int Max_Pips(void) const;\n\t\tvirtual void Dimensions(int &width, int &height) const;\n\t\tvirtual bool Create_And_Place(CELL cell, HousesType house) const;\n\t\tvirtual ObjectClass * Create_One_Of(HouseClass * house) const;\n\t\tvirtual short const * Occupy_List(bool placement=false) const;\n\t\tvirtual short const * Overlap_List(void) const;\n\t\tvirtual void const * Get_Buildup_Data(void) const {return(BuildupData);};\n\n\t\tbool Is_Factory(void) const {return(ToBuild != RTTI_NONE);}\n\t\tvirtual int Raw_Cost(void) const;\n\t\tbool Bib_And_Offset(SmudgeType & bib, CELL & cell) const;\n\n\t\t#ifdef SCENARIO_EDITOR\n\t\tvirtual void Display(int x, int y, WindowNumberType window, HousesType house) const;\n\t\t#endif\n\n\t\t/*\n\t\t**\tSpecial overlay for the weapons factory.\n\t\t*/\n\t\tstatic void const * WarFactoryOverlay;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is a pointer to a list of offsets (from the upper left corner) that\n\t\t**\tare used to indicate the building's \"footprint\". This footprint is used\n\t\t**\tto determine building placement legality and terrain passibility.\n\t\t*/\n\t\tshort const * OccupyList;\n\n\t\t/*\n\t\t**\tBuildings can often times overlap a cell but not actually \"occupy\" it for\n\t\t**\tpurposes of movement. This points to a list of offsets that indicate which\n\t\t**\tcells the building has visual overlap but does not occupy.\n\t\t*/\n\t\tshort const * OverlapList;\n\n\t\t/*\n\t\t**\tThe construction animation graphic data pointer is\n\t\t**\tpointed to by this element.\n\t\t*/\n\t\tvoid const * BuildupData;\n\n\t\tvoid Init_Anim(BStateType state, int start, int count, int rate) const;\n};\n\n\n/***************************************************************************\n**\tThe various unit types need specific data that is unique to units as\n**\topposed to buildings. This derived class elaborates these additional\n**\tdata types.\n*/\nclass UnitTypeClass : public TechnoTypeClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tIf this unit can appear out of a crate, then this flag will be true.\n\t\t*/\n\t\tunsigned IsCrateGoodie:1;\n\n\t\t/*\n\t\t**\tCan this unit squash infantry?  If it can then if the player selects\n\t\t**\tan (enemy) infantry unit as the movement target, it will ride over and\n\t\t**\tsquish the infantry unit.\n\t\t*/\n\t\tunsigned IsCrusher:1;\n\n\t\t/*\n\t\t**\tDoes this unit go into harvesting mode when it stops on a tiberium\n\t\t**\tfield?  Typically, only one unit does this and that is the harvester.\n\t\t*/\n\t\tunsigned IsToHarvest:1;\n\n\t\t/*\n\t\t**\tSome units are equipped with a rotating radar dish. These units have special\n\t\t**\tanimation processing. The rotating radar dish is similar to a turret, but\n\t\t**\talways rotates and does not affect combat.\n\t\t*/\n\t\tunsigned IsRadarEquipped:1;\n\n\t\t/*\n\t\t**\tIf this unit has a firing animation, this flag is true. Infantry and some special\n\t\t**\tvehicles are the ones with firing animations.\n\t\t*/\n\t\tunsigned IsFireAnim:1;\n\n\t\t/*\n\t\t**\tMany vehicles have a turret with restricted motion. These vehicles must move the\n\t\t**\tturret into a locked down position while travelling. Rocket launchers and artillery\n\t\t**\tare good examples of this kind of unit.\n\t\t*/\n\t\tunsigned IsLockTurret:1;\n\n\t\t/*\n\t\t**\tIs this unit of the humongous size?  Harvesters and mobile construction vehicles are\n\t\t**\tof this size. If the vehicle is greater than 24 x 24 but less than 48 x 48, it is\n\t\t**\tconsidered \"Gigundo\".\n\t\t*/\n\t\tunsigned IsGigundo:1;\n\n\t\t/*\n\t\t** Does this unit have a constant animation (like Visceroid?)\n\t\t*/\n\t\tunsigned IsAnimating:1;\n\n\t\t/*\n\t\t** Does this unit have the ability to jam radar facilities?\n\t\t*/\n\t\tunsigned IsJammer:1;\n\n\t\t/*\n\t\t** Is this unit a mobile gap generator?\n\t\t*/\n\t\tunsigned IsGapper:1;\n\n\t\t/*\n\t\t**\tIf this unit cannot fire while moving, then this flag will be\n\t\t**\ttrue. Such a unit must stop and stabilize for a bit before it\n\t\t**\tcan fire.\n\t\t*/\n\t\tunsigned IsNoFireWhileMoving:1;\n\n\t\t/*\n\t\t**\tThis value represents the unit class. It can serve as a unique\n\t\t**\tidentification number for this unit class.\n\t\t*/\n\t\tUnitType Type;\n\n\t\t/*\n\t\t**\tThis is the distance along the centerline heading in the direction the body\n\t\t**\tis facing used to reach the center point of the turret. This distance is\n\t\t**\tin leptons.\n\t\t*/\n\t\tsigned char TurretOffset;\n\n\t\t/*\n\t\t**\tThis value is used to provide the unit with a default mission order when\n\t\t**\tfirst created. Usually, this is a resting or idle type of order.\n\t\t*/\n\t\tMissionType Mission;\n\n\t\t/*\n\t\t**\tThis is the default explosion to use when this vehicle is destroyed.\n\t\t*/\n\t\tAnimType Explosion;\n\n\t\t/*\n\t\t**\tThe width or height of the largest dimension for this unit.\n\t\t*/\n\t\tint MaxSize;\n\n\t\t/*\n\t\t**\tThis is the explicit unit class constructor.\n\t\t*/\n\t\tUnitTypeClass(NoInitClass const & x) : TechnoTypeClass(x) {}\n\t\tUnitTypeClass\t(\n\t\t\t\t\t\tUnitType type,\n\t\t\t\t\t\tint name,\n\t\t\t\t\t\tchar const * ininame,\n\t\t\t\t\t\tAnimType exp,\n\t\t\t\t\t\tRemapType remap,\n\t\t\t\t\t\tint verticaloffset,\n\t\t\t\t\t\tint primaryoffset,\n\t\t\t\t\t\tint primarylateral,\n\t\t\t\t\t\tint secondaryoffset,\n\t\t\t\t\t\tint secondarylateral,\n\t\t\t\t\t\tbool is_goodie,\n\t\t\t\t\t\tbool is_nominal,\n\t\t\t\t\t\tbool is_crusher,\n\t\t\t\t\t\tbool is_harvest,\n\t\t\t\t\t\tbool is_stealthy,\n\t\t\t\t\t\tbool is_insignificant,\n\t\t\t\t\t\tbool is_turret_equipped,\n\t\t\t\t\t\tbool is_radar_equipped,\n\t\t\t\t\t\tbool is_fire_anim,\n\t\t\t\t\t\tbool is_lock_turret,\n\t\t\t\t\t\tbool is_gigundo,\n\t\t\t\t\t\tbool is_animating,\n\t\t\t\t\t\tbool is_jammer,\n\t\t\t\t\t\tbool is_gapper,\n\t\t\t\t\t\tint rotation,\n\t\t\t\t\t\tint toffset,\n\t\t\t\t\t\tMissionType order\n\t\t\t\t\t\t);\n\n\t\tstatic void * operator new(size_t);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void * ptr);\n\n\t\tstatic void Init_Heap(void);\n\t\tstatic UnitType From_Name(char const * name);\n\t\tstatic UnitTypeClass & As_Reference(UnitType type);\n\t\tstatic void Init(TheaterType ) {};\n\t\tstatic void One_Time(void);\n\t\tstatic void Prep_For_Add(void);\n\n\t\tvirtual bool Read_INI(CCINIClass & ini);\n\t\tvirtual void Dimensions(int &width, int &height) const;\n\t\tvirtual bool Create_And_Place(CELL cell, HousesType house) const;\n\t\tvirtual ObjectClass * Create_One_Of(HouseClass * house) const;\n\t\tvirtual int Max_Pips(void) const;\n\n\t\tvoid Turret_Adjust(DirType dir, int & x, int & y) const;\n\n\t\t#ifdef SCENARIO_EDITOR\n\t\tvirtual void Display(int x, int y, WindowNumberType window, HousesType house) const;\n\t\t#endif\n\n\t\t/*\n\t\t**\tThe animation stage list for harvester dumping into the refinery.\n\t\t*/\n\t\tstatic const int Harvester_Dump_List[22];\n\n\t\t/*\n\t\t**\tThe animatino stage list for harvester loading up on ore.\n\t\t*/\n\t\tstatic const int Harvester_Load_List[9];\n\n\t\t/*\n\t\t**\tThe number of animation stages when the harvester is loading\n\t\t**\tup on ore in the field.\n\t\t*/\n\t\tstatic const int Harvester_Load_Count;\n};\n\n\n/***************************************************************************\n**\tThis specifies the constant attribute data associated with naval\n**\tvessels.\n*/\nclass VesselTypeClass : public TechnoTypeClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tDoes this unit have only 8 facings? Special test units have limited\n\t\t**\tfacings.\n\t\t*/\n\t\tunsigned IsPieceOfEight:1;\n\n\t\t/*\n\t\t**\tThis value represents the unit class. It can serve as a unique\n\t\t**\tidentification number for this unit class.\n\t\t*/\n\t\tVesselType Type;\n\n\t\t/*\n\t\t**\tThis is the distance along the centerline heading in the direction the body\n\t\t**\tis facing used to reach the center point of the turret. This distance is\n\t\t**\tin leptons.\n\t\t*/\n\t\tsigned char TurretOffset;\n\n\t\t/*\n\t\t**\tThis value is used to provide the unit with a default mission order when\n\t\t**\tfirst created. Usually, this is a resting or idle type of order.\n\t\t*/\n\t\tMissionType Mission;\n\n\t\t/*\n\t\t**\tThis is the default explosion to use when this vehicle is destroyed.\n\t\t*/\n\t\tAnimType Explosion;\n\n\t\t/*\n\t\t**\tThe width or height of the largest dimension for this unit.\n\t\t*/\n\t\tint MaxSize;\n\n\t\t/*\n\t\t**\tThis is the explicit unit class constructor.\n\t\t*/\n\t\tVesselTypeClass(NoInitClass const & x) : TechnoTypeClass(x) {}\n\t\tVesselTypeClass\t(\n\t\t\t\t\t\tVesselType type,\n\t\t\t\t\t\tint name,\n\t\t\t\t\t\tchar const * ininame,\n\t\t\t\t\t\tAnimType exp,\n\t\t\t\t\t\tint verticaloffset,\n\t\t\t\t\t\tint primaryoffset,\n\t\t\t\t\t\tint primarylateral,\n\t\t\t\t\t\tint secondaryoffset,\n\t\t\t\t\t\tint secondarylateral,\n\t\t\t\t\t\tbool is_eight,\n\t\t\t\t\t\tbool is_nominal,\n\t\t\t\t\t\tbool is_turret_equipped,\n\t\t\t\t\t\tint rotation,\n\t\t\t\t\t\tint toffset\n\t\t\t\t\t\t);\n\n\t\tstatic void * operator new(size_t);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void * ptr);\n\n\t\tstatic void Init_Heap(void);\n\t\tstatic VesselType From_Name(char const * name);\n\t\tstatic VesselTypeClass & As_Reference(VesselType type);\n\t\tstatic void Init(TheaterType ) {};\n\t\tstatic void One_Time(void);\n\t\tstatic void Prep_For_Add(void);\n\n\t\tvirtual void Dimensions(int &width, int &height) const;\n\t\tvirtual bool Create_And_Place(CELL cell, HousesType house) const;\n\t\tvirtual ObjectClass * Create_One_Of(HouseClass * house) const;\n\t\tvirtual int Max_Pips(void) const;\n\t\tvirtual short const * Overlap_List(void) const;\n\n\t\tvoid Turret_Adjust(DirType dir, int & x, int & y) const;\n\n\t\t#ifdef SCENARIO_EDITOR\n\t\tvirtual void Display(int x, int y, WindowNumberType window, HousesType house) const;\n\t\t#endif\n};\n\n\n/***************************************************************************\n**\tThe various unit types need specific data that is unique to units as\n**\topposed to buildings. This derived class elaborates these additional\n**\tdata types.\n*/\nclass InfantryTypeClass : public TechnoTypeClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tIf this civilian infantry type is female, then this flag\n\t\t**\twill be true. This information is used to get the correct\n\t\t**\tvoice response.\n\t\t*/\n\t\tunsigned IsFemale:1;\n\n\t\t/*\n\t\t**\tDoes this infantry unit have crawling animation? If not, then this\n\t\t**\tmeans that the \"crawling\" frames are actually running animation frames.\n\t\t*/\n\t\tunsigned IsCrawling:1;\n\n\t\t/*\n\t\t**\tFor those infantry types that can capture buildings, this flag\n\t\t**\twill be set to true. Typically, this is the engineer.\n\t\t*/\n\t\tunsigned IsCapture:1;\n\n\t\t/*\n\t\t**\tFor infantry types that will run away from any damage causing\n\t\t**\tevents, this flag will be true. Typically, this is so for all\n\t\t**\tcivilians as well as the flame thrower guys.\n\t\t*/\n\t\tunsigned IsFraidyCat:1;\n\n\t\t/*\n\t\t**\tThis flags whether this infantry is actually a civilian. A\n\t\t**\tcivilian uses different voice responses, has less ammunition,\n\t\t**\tand runs from danger more often.\n\t\t*/\n\t\tunsigned IsCivilian:1;\n\n\t\t/*\n\t\t**\tIf the infantry unit is equipped with C4 explosives, then this\n\t\t**\tflag will be true. Such infantry can enter and destroy enemy\n\t\t**\tbuildings.\n\t\t*/\n\t\tunsigned IsBomber:1;\n\n\t\t/*\n\t\t** This flags whether this infantry is actually a dog.  A dog\n\t\t** uses different voice responses, has no ammo, and runs instead\n\t\t** of walks to attack.\n\t\t*/\n\t\tunsigned IsDog:1;\n\n\t\t/*\n\t\t** This flag specifies whether this infantry type should use the\n\t\t** override remap table, instead of the house remap table.  This is\n\t\t** used to turn the two civilian animations into a veritable smorgasbord\n\t\t** of civilian types, for example.\n\t\t*/\n\t\tunsigned IsRemapOverride:1;\n\n\t\t/*\n\t\t**\tThis value represents the unit class. It can serve as a unique\n\t\t**\tidentification number for this unit class.\n\t\t*/\n\t\tInfantryType Type;\n\n\t\t/*\n\t\t**\tWhen this infantry unit is loaded onto a transport, then this\n\t\t**\tis the pip shape to use. Primarily, this is a color control.\n\t\t*/\n\t\tPipEnum Pip;\n\n\t\t/*\n\t\t**\tThis is an array of the various animation frame data for the actions that\n\t\t**\tthe infantry may perform.\n\t\t*/\n\t\tDoInfoStruct const * DoControls;\n\n\t\t/*\n\t\t**\tThere are certain units with special animation sequences built into the\n\t\t**\tshape file. These values tell how many frames are used for the firing animation.\n\t\t*/\n\t\tchar FireLaunch;\n\t\tchar ProneLaunch;\n\n\t\t/*\n\t\t** This is a pointer to the special override remap table, which is\n\t\t** used only in conjunction with the IsRemapOverride flag, and is\n\t\t** primarily used for the civilians.\n\t\t*/\n\t\tunsigned char const * OverrideRemap;\n\n\t\t/*\n\t\t**\tThis is the explicit unit class constructor.\n\t\t*/\n\t\tInfantryTypeClass(NoInitClass const & x) : TechnoTypeClass(x) {}\n\t\tInfantryTypeClass\t(\n\t\t\t\t\t\tInfantryType type,\n\t\t\t\t\t\tint name,\n\t\t\t\t\t\tchar const * ininame,\n\t\t\t\t\t\tint verticaloffset,\n\t\t\t\t\t\tint primaryoffset,\n\t\t\t\t\t\tbool is_female,\n\t\t\t\t\t\tbool is_crawling,\n\t\t\t\t\t\tbool is_civilian,\n\t\t\t\t\t\tbool is_remap_override,\n\t\t\t\t\t\tbool is_nominal,\n\t\t\t\t\t\tbool is_theater,\n\t\t\t\t\t\tPipEnum pip,\n\t\t\t\t\t\tDoInfoStruct const * controls,\n\t\t\t\t\t\tint firelaunch,\n\t\t\t\t\t\tint pronelaunch,\n\t\t\t\t\t\tunsigned char const * override_remap);\n\n\t\tstatic void * operator new(size_t);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void * ptr);\n\n\t\tstatic void Init_Heap(void);\n\t\tstatic InfantryType From_Name(char const * name);\n\t\tstatic InfantryTypeClass & As_Reference(InfantryType type);\n\t\tstatic void Init(TheaterType ) {};\n\t\tstatic void One_Time(void);\n\t\tstatic void Prep_For_Add(void);\n\n\t\tvirtual bool Read_INI(CCINIClass & ini);\n\t\tvirtual void Dimensions(int & width, int & height) const;\n\t\tvirtual bool Create_And_Place(CELL cell, HousesType house) const;\n\t\tvirtual ObjectClass * Create_One_Of(HouseClass * house) const;\n\t\tvirtual short const * Occupy_List(bool placement=false) const;\n\t\tvirtual int Full_Name(void) const;\n\n\t\t#ifdef SCENARIO_EDITOR\n\t\tvirtual void Display(int x, int y, WindowNumberType window, HousesType house) const;\n\t\t#endif\n};\n\n\n/****************************************************************************\n**\tThe various aircraft types are controlled by object types of\n**\tthis class.\n*/\nclass AircraftTypeClass : public TechnoTypeClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tFixed wing aircraft (ones that cannot hover) have this flag set to true.\n\t\t**\tSuch aircraft will not vary speed while it is flying.\n\t\t*/\n\t\tunsigned IsFixedWing:1;\n\n\t\t/*\n\t\t**\tCan this aircraft land?  If it can land it is presumed to be controllable by the player.\n\t\t*/\n\t\tunsigned IsLandable:1;\n\n\t\t/*\n\t\t**\tDoes this aircraft have a rotor blade (helicopter) type propulsion?\n\t\t*/\n\t\tunsigned IsRotorEquipped:1;\t// Is a rotor attached?\n\n\t\t/*\n\t\t**\tIs there a custom rotor animation stage set for each facing of the aircraft?\n\t\t*/\n\t\tunsigned IsRotorCustom:1;\t// Custom rotor sets for each facing?\n\n\t\t/*\n\t\t**\tThis is the kind of aircraft identifier number.\n\t\t*/\n\t\tAircraftType Type;\n\n\t\t/*\n\t\t**\tThis specifies the default mission order for this aircraft. Some aircraft default\n\t\t**\tto guard mode (e.g., helicopters) while some default to attack mode (e.g., bombers).\n\t\t*/\n\t\tMissionType Mission;\n\n\t\t/*\n\t\t**\tThis is the preferred landing building. The aircraft will try to land at the\n\t\t**\tbuilding of this type.\n\t\t*/\n\t\tStructType Building;\n\n\t\t/*\n\t\t** This is the final approach speed of this aircraft type for landing\n\t\t** at an airfield.  Most aircraft hit it at full speed, but the MIG is\n\t\t** an example of a plane that needs a slower approach speed to hit the\n\t\t** airfield.\n\t\t*/\n\t\tint LandingSpeed;\n\n\t\tAircraftTypeClass(NoInitClass const & x) : TechnoTypeClass(x) {}\n\t\tAircraftTypeClass(\n\t\t\t\tAircraftType airtype,\n\t\t\t\tint name,\n\t\t\t\tchar const * ininame,\n\t\t\t\tint verticaloffset,\n\t\t\t\tint primaryoffset,\n\t\t\t\tint primarylateral,\n\t\t\t\tbool is_fixedwing,\n\t\t\t\tbool is_rotorequipped,\n\t\t\t\tbool is_rotorcustom,\n\t\t\t\tbool is_landable,\n\t\t\t\tbool is_stealthy,\n\t\t\t\tbool is_selectable,\n\t\t\t\tbool is_legal_target,\n\t\t\t\tbool is_insignificant,\n\t\t\t\tbool is_immune,\n\t\t\t\tStructType building,\n\t\t\t\tint landingspeed,\n\t\t\t\tint rotation,\n\t\t\t\tMissionType deforder);\n\n\t\tstatic void * operator new(size_t);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void * ptr);\n\n\t\tstatic void Init_Heap(void);\n\t\tstatic AircraftType From_Name(char const * name);\n\t\tstatic AircraftTypeClass & As_Reference(AircraftType a);\n\t\tstatic void Init(TheaterType ) {};\n\t\tstatic void One_Time(void);\n\t\tstatic void Prep_For_Add(void);\n\n\t\tvirtual void Dimensions(int &width, int &height) const;\n\t\tvirtual bool Create_And_Place(CELL, HousesType) const;\n\t\tvirtual ObjectClass * Create_One_Of(HouseClass * house) const;\n\t\tvirtual short const * Occupy_List(bool placement=false) const;\n\t\tvirtual short const * Overlap_List(void) const;\n\t\tvirtual int Max_Pips(void) const;\n\n\t\t#ifdef SCENARIO_EDITOR\n\t\tvirtual void Display(int x, int y, WindowNumberType window, HousesType house) const;\n\t\t#endif\n\n\t\tstatic void const * LRotorData;\n\t\tstatic void const * RRotorData;\n};\n\n\n/***************************************************************************\n** Bullets and other projectiles need some specific information according\n**\tto their type.\n*/\nclass BulletTypeClass : public ObjectTypeClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tDoes this bullet type fly over walls?\n\t\t*/\n\t\tunsigned IsHigh:1;\n\n\t\t/*\n\t\t** Does this bullet need a shadow drawn under it?  Shadowed bullets\n\t\t** use the Height value to offset their Y position.\n\t\t*/\n\t\tunsigned IsShadow:1;\n\n\t\t/*\n\t\t**\tIf this projectile is one that ballistically arcs from ground level, up into the air and\n\t\t**\tthen back to the ground, where it explodes. Typical uses of this are for grenades and\n\t\t**\tartillery shells.\n\t\t*/\n\t\tunsigned IsArcing:1;\n\n\t\t/*\n\t\t**\tCertain projectiles do not travel horizontally, but rather, vertically -- they drop\n\t\t**\tfrom a height. Bombs fall into this category and will have this value set to\n\t\t**\ttrue. Dropping projectiles do not calculate collision with terrain (such as walls).\n\t\t*/\n\t\tunsigned IsDropping:1;\n\n\t\t/*\n\t\t**\tIs this projectile invisible?  Some bullets and weapon effects are not directly\n\t\t**\trendered. Small caliber bullets and flame thrower flames are treated like\n\t\t**\tnormal projectiles for damage purposes, but are displayed using custom\n\t\t**\trules.\n\t\t*/\n\t\tunsigned IsInvisible:1;\n\n\t\t/*\n\t\t**\tDoes this bullet explode when near the target?  Some bullets only explode if\n\t\t**\tit actually hits the target. Some explode even if nearby.\n\t\t*/\n\t\tunsigned IsProximityArmed:1;\n\n\t\t/*\n\t\t**\tDoes this projectile spew puffs of smoke out its tail while it\n\t\t**\ttravels? Missiles are prime examples of this projectile type.\n\t\t*/\n\t\tunsigned IsFlameEquipped:1;\n\n\t\t/*\n\t\t**\tShould fuel consumption be tracked for this projectile?  Rockets are the primary\n\t\t**\tprojectile with this characteristic, but even for bullets it should be checked so that\n\t\t**\tbullets don't travel too far.\n\t\t*/\n\t\tunsigned IsFueled:1;\n\n\t\t/*\n\t\t**\tIs this projectile without different facing visuals?  Most plain bullets do not change\n\t\t**\tvisual imagery if their facing changes. Rockets, on the other hand, are equipped with\n\t\t**\tthe full 32 facing imagery.\n\t\t*/\n\t\tunsigned IsFaceless:1;\n\n\t\t/*\n\t\t**\tIf this is a typically inaccurate projectile, then this flag will be true. Artillery\n\t\t**\tis a prime example of this type.\n\t\t*/\n\t\tunsigned IsInaccurate:1;\n\n\t\t/*\n\t\t**\tIf the bullet contains translucent pixels, then this flag will be true. These\n\t\t**\ttranslucent pixels really are \"shadow\" pixels in the same style as the shadow\n\t\t**\tcast by regular ground units.\n\t\t*/\n\t\tunsigned IsTranslucent:1;\n\n\t\t/*\n\t\t**\tIf this bullet can be fired on aircraft, then this flag will be true.\n\t\t*/\n\t\tunsigned IsAntiAircraft:1;\n\n\t\t/*\n\t\t**\tIf this bullet can fire upon ground targets, then this flag will be true.\n\t\t*/\n\t\tunsigned IsAntiGround:1;\n\n\t\t/*\n\t\t**\tIf this bullet can be fired upon submarines (that are submerged), then\n\t\t**\tthis flag will be true.\n\t\t*/\n\t\tunsigned IsAntiSub:1;\n\n\t\t/*\n\t\t**\tIf this bullet should lose strength as it travels toward the target, then\n\t\t**\tthis flag will be true.\n\t\t*/\n\t\tunsigned IsDegenerate:1;\n\n\t\t/*\n\t\t**\tDoes this projectile travel under the water? If so, then its imagery will be modified\n\t\t**\tto look like it is doing so.\n\t\t*/\n\t\tunsigned IsSubSurface:1;\n\n\t\t/*\n\t\t**\tIf this projectile is equipped with a parachute, then this flag will be set. Parachute\n\t\t**\tbombs are usually the only one with this flag set.\n\t\t*/\n\t\tunsigned IsParachuted:1;\n\n\t\t/*\n\t\t**\tIs this unit of the humongous size?  Certain very large projectiles have\n\t\t**\tthis flag set. Typically, they require a special offset list so that the cells\n\t\t**\tthey overlap will be properly redrawn.\n\t\t*/\n\t\tunsigned IsGigundo:1;\n\n\t\t/*\n\t\t**\tThis element is a unique identification number for the bullet\n\t\t**\ttype.\n\t\t*/\n\t\tBulletType Type;\n\n\t\t/*\n\t\t**\tThis is the rotation speed of the bullet. It only has practical value\n\t\t**\tfor those projectiles that performing homing action during flight -- such\n\t\t**\tas with rockets. If the ROT is zero, then no homing is performed. Otherwise\n\t\t**\tthe projectile is considered to be a homing type.\n\t\t*/\n\t\tunsigned char ROT;\n\n\t\t/*\n\t\t**\tSome projectiles have a built in arming distance that must elapse before the\n\t\t**\tprojectile may explode. If this value is non-zero, then this override is\n\t\t**\tapplied.\n\t\t*/\n\t\tint Arming;\n\n\t\t/*\n\t\t**\tIf this bullet is of the tumbling type, then this is the modulo to factor\n\t\t**\tinto the game frame when determining what shape number to use for the\n\t\t**\timagery.\n\t\t*/\n\t\tint Tumble;\n\n\t\t//---------------------------------------------------------------------\n\t\tBulletTypeClass(NoInitClass const & x) : ObjectTypeClass(x) {}\n\t\tBulletTypeClass(char const * name);\n\n\t\tstatic void * operator new(size_t);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void * ptr);\n\n\t\tstatic void Init_Heap(void);\n\t\tstatic BulletTypeClass & As_Reference(BulletType type);\n\t\tstatic void Init(TheaterType ) {};\n\t\tstatic void One_Time(void);\n\n\t\tvirtual bool Read_INI(CCINIClass & ini);\n\t\tvirtual bool Create_And_Place(CELL , HousesType =HOUSE_NONE) const {return false;};\n\t\tvirtual ObjectClass * Create_One_Of(HouseClass *) const {return 0;};\n};\n\n\n/****************************************************************************\n**\tThese are the different TYPES of terrain objects. Every terrain object must\n**\tbe one of these types.\n*/\nclass TerrainTypeClass : public ObjectTypeClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tWhich terrain object does this class type represent.\n\t\t*/\n\t\tTerrainType Type;\n\n\t\t/*\n\t\t**\tThis is the coordinate offset (from upper left) of where the center base\n\t\t**\tposition of the terrain object lies. For trees, this would be the base of\n\t\t**\tthe trunk. This is used for sorting purposes.\n\t\t*/\n\t\tCOORDINATE CenterBase;\n\n\t\t/*\n\t\t**\tThis is the bitfield control that tells which theater this terrain object is\n\t\t**\tvalid for. If the bit (1 << TheaterType) is true, then this terrain object\n\t\t**\tis allowed.\n\t\t*/\n\t\tint Theater;\n\n\t\t/*\n\t\t**\tDoes this terrain object get placed on the water instead of the ground?\n\t\t*/\n\t\tunsigned IsWaterBased:1;\n\n\t\t//----------------------------------------------------------------\n\t\tTerrainTypeClass(NoInitClass const & x) : ObjectTypeClass(x) {}\n\t\tTerrainTypeClass(\n\t\t\t\tTerrainType terrain,\n\t\t\t\tint theater,\n\t\t\t\tCOORDINATE centerbase,\n\t\t\t\tbool is_immune,\n\t\t\t\tbool is_water,\n\t\t\t\tchar const * ininame,\n\t\t\t\tint fullname,\n\t\t\t\tshort const * occupy,\n\t\t\t\tshort const * overlap);\n\n\t\tstatic void * operator new(size_t);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void * ptr);\n\n\t\tstatic void Init_Heap(void);\n\t\tstatic TerrainType From_Name(char const * name);\n\t\tstatic TerrainTypeClass & As_Reference(TerrainType type);\n\t\tstatic void Init(TheaterType theater = THEATER_TEMPERATE);\n\t\tstatic void One_Time(void);\n\t\tstatic void Prep_For_Add(void);\n\n\t\tvirtual COORDINATE Coord_Fixup(COORDINATE coord) const;\n\t\tvirtual bool Create_And_Place(CELL cell, HousesType house) const;\n\t\tvirtual ObjectClass * Create_One_Of(HouseClass *) const;\n\t\tvirtual short const * Occupy_List(bool placement=false) const;\n\t\tvirtual short const * Overlap_List(void) const;\n\n\t\t#ifdef SCENARIO_EDITOR\n\t\tvirtual void Display(int x, int y, WindowNumberType window, HousesType house=HOUSE_NONE) const;\n\t\t#endif\n\n\tprivate:\n\t\tshort const * Occupy;\n\t\tshort const * Overlap;\n};\n\n\n/****************************************************************************\n**\tThe tile type objects are controlled by this class. It specifies the form\n**\tof the tile set for the specified object as well as other related datum.\n**\tIt is derived from the ObjectTypeClass solely for the purpose of scenario\n**\tediting and creation.\n*/\nclass TemplateTypeClass: public ObjectTypeClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tWhat template is this.\n\t\t*/\n\t\tTemplateType Type;\n\n\t\t/*\n\t\t**\tA bitfield container that indicates which theaters this template is allowed\n\t\t**\tin. A bit set in the (1<<TheaterType) position indicates the template is legal\n\t\t**\tin that particular theater.\n\t\t*/\n\t\tunsigned char Theater;\n\n\t\t/*\n\t\t**\tRaw dimensions of this template (in icons).\n\t\t*/\n\t\tunsigned char Width,Height;\n\n\t\t//----------------------------------------------------------\n\t\tTemplateTypeClass(NoInitClass const & x) : ObjectTypeClass(x) {};\n\t\tTemplateTypeClass(\n\t\t\tTemplateType iconset,\n\t\t\tint theater,\n\t\t\tchar const * ininame,\n\t\t\tint fullname);\n\n\t\tstatic void * operator new(size_t);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void * ptr);\n\n\t\tstatic void Init_Heap(void);\n\t\tstatic TemplateType From_Name(char const * name);\n\t\tstatic TemplateTypeClass & As_Reference(TemplateType type);\n\t\tstatic void Init(TheaterType theater);\n\t\tstatic void One_Time(void);\n\t\tstatic void Prep_For_Add(void);\n\n\t\tvirtual COORDINATE Coord_Fixup(COORDINATE coord) const;\n\t\tvirtual bool Create_And_Place(CELL cell, HousesType house=HOUSE_NONE) const;\n\t\tvirtual ObjectClass * Create_One_Of(HouseClass *) const;\n\t\tvirtual short const * Occupy_List(bool placement=false) const;\n\t\tLandType Land_Type(int icon) const;\n\n\t\t#ifdef SCENARIO_EDITOR\n\t\tvirtual void Display(int x, int y, WindowNumberType window, HousesType house=HOUSE_NONE) const;\n\t\t#endif\n};\n\n\n/****************************************************************************\n**\tAll the animation objects are controlled by this class. It holds the static\n**\tdata associated with each animation type.\n*/\nclass AnimTypeClass : public ObjectTypeClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tIf this animation should run at a constant apparent rate regardless\n\t\t**\tof game speed setting, then this flag will be set to true.\n\t\t*/\n\t\tunsigned IsNormalized:1;\n\n\t\t/*\n\t\t**\tIf this animation should be rendered and sorted with the other ground\n\t\t**\tunits, then this flag is true. Typical of this would be fire and other\n\t\t**\tlow altitude animation effects.\n\t\t*/\n\t\tunsigned IsGroundLayer:1;\n\n\t\t/*\n\t\t**\tIf this animation should be rendered in a translucent fashion, this flag\n\t\t**\twill be true. Translucent colors are some of the reds and some of the\n\t\t**\tgreys. Typically, smoke and some fire effects have this flag set.\n\t\t*/\n\t\tunsigned IsTranslucent:1;\n\n\t\t/*\n\t\t**\tIf this animation uses the white translucent table, then this flag\n\t\t**\twill be true.\n\t\t*/\n\t\tunsigned IsWhiteTrans:1;\n\n\t\t/*\n\t\t**\tIf this is the special flame thrower animation, then custom affects\n\t\t**\toccur as it is playing. Specifically, scorch marks and little fire\n\t\t**\tpieces appear as the flame jets forth.\n\t\t*/\n\t\tunsigned IsFlameThrower:1;\n\n\t\t/*\n\t\t**\tSome animations leave a scorch mark behind. Napalm and other flame\n\t\t**\ttype explosions are typical of this type.\n\t\t*/\n\t\tunsigned IsScorcher:1;\n\n\t\t/*\n\t\t**\tSome explosions are of such violence that they leave craters behind.\n\t\t**\tThis flag will be true for those types.\n\t\t*/\n\t\tunsigned IsCraterForming:1;\n\n\t\t/*\n\t\t**\tIf this animation should attach itself to any unit that is in the same\n\t\t**\tlocation as itself, then this flag will be true. Most vehicle impact\n\t\t**\texplosions are of this type.\n\t\t*/\n\t\tunsigned IsSticky:1;\n\n\t\t/*\n\t\t**\tIf this animation is theater specific, then this flag will be\n\t\t**\tset to true. Most animations are not theater specific.\n\t\t*/\n\t\tunsigned IsTheater:1;\n\n\t\t/*\n\t\t**\tThis is the type number for this animation kind. It can be used as\n\t\t**\ta unique identifier for animation types.\n\t\t*/\n\t\tAnimType Type;\n\n\t\t/*\n\t\t**\tThis specified the maximum dimension of the shape (edge to edge). This dimension\n\t\t**\tis used to build the appropriate cell refresh list. Keep this value as small\n\t\t**\tas possible to ensure maximum performance. This is especially critical, since\n\t\t**\tanimations always cause the cells under them to be redrawn every frame.\n\t\t*/\n\t\tint Size;\n\n\t\t/*\n\t\t**\tThis is the frame that the animation is biggest. The biggest frame of animation\n\t\t**\twill hide any changes to underlying ground (e.g., craters) that the animation\n\t\t**\tcauses, so these effects are delayed until this frame is reached. The end result\n\t\t**\tis to prevent the player from seeing craters \"pop\" into existence.\n\t\t*/\n\t\tint Biggest;\n\n\t\t/*\n\t\t**\tSome animations (when attached to another object) damage the object it\n\t\t**\tis in contact with. Fire is a good example of this. This value is a\n\t\t**\tfixed point number of the damage that is applied to the attached object\n\t\t**\tevery game tick. The damage is expressed as damage points per game frame.\n\t\t**\tBecause it is a fixed point fraction, the damage can be very slight.\n\t\t*/\n\t\tfixed Damage;\n\n\t\t/*\n\t\t**\tSimple animation delay value between advancing of frames. This can\n\t\t**\tbe overridden by the control list.\n\t\t*/\n\t\tint Delay;\n\n\t\t/*\n\t\t**\tThe starting frame number for each animation sequence. Usually this is\n\t\t**\tzero, but can sometimes be different if this animation is a sub sequence\n\t\t**\tof a larger animation file.\n\t\t*/\n\t\tint Start;\n\n\t\t/*\n\t\t**\tLooping animations might start at a different frame than the initial one.\n\t\t**\tThis is true for smoke effects that have a startup sequence followed by a\n\t\t**\tcontinuous looping sequence.\n\t\t*/\n\t\tint LoopStart;\n\n\t\t/*\n\t\t**\tFor looping animations, this is the frame that will end all the middle loops\n\t\t**\tof the animation. The last loop of the animation will proceed until the Stages\n\t\t**\thas been fully completed.\n\t\t*/\n\t\tint LoopEnd;\n\n\t\t/*\n\t\t**\tThe number of stages that this animation sequence will progress through\n\t\t**\tbefore it loops or ends.\n\t\t*/\n\t\tint Stages;\n\n\t\t/*\n\t\t**\tThis is the normal loop count for this animation. Usually this is one, but\n\t\t**\tfor some animations, it may be larger.\n\t\t*/\n\t\tunsigned Loops;\n\n\t\t/*\n\t\t**\tThis is the sound effect to play when this animation starts. Usually, this\n\t\t**\tapplies to explosion animations.\n\t\t*/\n\t\tVocType Sound;\n\n\t\t/*\n\t\t**\tIf the animation is to launch into another animation, then\n\t\t**\tthe secondary animation will be defined here.\n\t\t*/\n\t\tAnimType ChainTo;\n\n\t\t//---------------------------------------------------------------------------\n\t\tAnimTypeClass(NoInitClass const & x) : ObjectTypeClass(x) {}\n\t\tAnimTypeClass(AnimType anim,\n\t\t\t\t\t\t\tchar const * name,\n\t\t\t\t\t\t\tint size,\n\t\t\t\t\t\t\tint biggest,\n\t\t\t\t\t\t\tbool istheater,\n\t\t\t\t\t\t\tbool isnormal,\n\t\t\t\t\t\t\tbool iswhite,\n\t\t\t\t\t\t\tbool isscorcher,\n\t\t\t\t\t\t\tbool iscrater,\n\t\t\t\t\t\t\tbool issticky,\n\t\t\t\t\t\t\tbool ground,\n\t\t\t\t\t\t\tbool istrans,\n\t\t\t\t\t\t\tbool isflame,\n\t\t\t\t\t\t\tfixed damage,\n\t\t\t\t\t\t\tint delaytime,\n\t\t\t\t\t\t\tint start,\n\t\t\t\t\t\t\tint loopstart,\n\t\t\t\t\t\t\tint loopend,\n\t\t\t\t\t\t\tint stages,\n\t\t\t\t\t\t\tint loops,\n\t\t\t\t\t\t\tVocType sound,\n\t\t\t\t\t\t\tAnimType chainto);\n\n\t\tstatic void Init_Heap(void);\n\t\tstatic void * operator new(size_t);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void * ptr);\n\n\t\tstatic AnimTypeClass & As_Reference(AnimType type);\n\t\tstatic void Init(TheaterType theater);\n\t\tstatic void One_Time(void);\n\n\t\tvirtual bool Create_And_Place(CELL , HousesType =HOUSE_NONE) const {return false;};\n\t\tvirtual ObjectClass * Create_One_Of(HouseClass *) const {return 0;};\n};\n\n\n/****************************************************************************\n**\tThis controls the overlay object types. These object types include walls\n**\tand concrete. They are always considered to be one icon in size and\n**\tare processed on an icon by icon basis. This is different from normal\n**\ttemplates which can be an arbitrary size. Other than this they are\n**\tmostly similar to normal templates but with some characteristics of\n**\tstructures (they can be destroyed).\n*/\nclass OverlayTypeClass: public ObjectTypeClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tWhat overlay is this.\n\t\t*/\n\t\tOverlayType Type;\n\n\t\t/*\n\t\t**\tWhat type of ground does this make the cell it occupies?\n\t\t*/\n\t\tLandType Land;\n\n\t\t/*\n\t\t** If this overlay is a wall, how many stages of destruction are there\n\t\t** for this wall type? i.e. sandbags = 2, concrete = 4, etc.\n\t\t*/\n\t\tint DamageLevels;\n\n\t\t/*\n\t\t** If this overlay is a wall, what amount of damage is necessary\n\t\t** before the wall takes damage?\n\t\t*/\n\t\tint DamagePoints;\n\n\t\t/*\n\t\t**\tIs this overlay graphic theater specific. This means that if there is\n\t\t**\tcustom art for this overlay that varies between different theaters, then\n\t\t**\tthis flag will be true.\n\t\t*/\n\t\tunsigned IsTheater:1;\n\n\t\t/*\n\t\t**\tIs this a wall type overlay?  Wall types change their shape\n\t\t**\tdepending on the existence of adjacent walls of the same type.\n\t\t*/\n\t\tunsigned IsWall:1;\n\n\t\t/*\n\t\t**\tIf this overlay is actually a wall and this wall type is tall enough that\n\t\t**\tnormal ground based straight line weapons will be blocked by it, then this\n\t\t**\tflag will be true. Brick fences are typical of this type.\n\t\t*/\n\t\tunsigned IsHigh:1;\n\n\t\t/*\n\t\t**\tIf this overlay represents harvestable tiberium, then this flag\n\t\t**\twill be true.\n\t\t*/\n\t\tunsigned IsTiberium:1;\n\n\t\t/*\n\t\t**\tIf this is a wall that is made of wood, then this flag will be\n\t\t**\ttrue. Such walls are affected by fire damage.\n\t\t*/\n\t\tunsigned IsWooden:1;\n\n\t\t/*\n\t\t**\tIs this a crate? If it is, then goodies may come out of it.\n\t\t*/\n\t\tunsigned IsCrate:1;\n\n\t\t/*\n\t\t**\tIf this is true, then the overlay will not show up on the radar map.\n\t\t*/\n\t\tunsigned IsRadarVisible:1;\n\n\t\t//----------------------------------------------------------\n\t\tOverlayTypeClass(NoInitClass const & x) : ObjectTypeClass(x) {}\n\t\tOverlayTypeClass(\n\t\t\tOverlayType iconset,\n\t\t\tchar const * ininame,\n\t\t\tint  fullname,\n\t\t\tLandType ground,\n\t\t\tint  damagelevels,\n\t\t\tint  damagepoints,\n\t\t\tbool isradarinvisible,\n\t\t\tbool iswooden,\n\t\t\tbool istarget,\n\t\t\tbool iscrushable,\n\t\t\tbool istiberium,\n\t\t\tbool high,\n\t\t\tbool theater,\n\t\t\tbool iswall,\n\t\t\tbool iscrate);\n\n\t\tstatic void * operator new(size_t);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void * ptr);\n\n\t\tstatic void Init_Heap(void);\n\t\tstatic OverlayType From_Name(char const * name);\n\t\tstatic OverlayTypeClass & As_Reference(OverlayType type);\n\t\tstatic void Init(TheaterType);\n\t\tstatic void One_Time(void);\n\t\tstatic void Prep_For_Add(void);\n\n\t\tvirtual COORDINATE Coord_Fixup(COORDINATE coord) const;\n\t\tvirtual bool Create_And_Place(CELL cell, HousesType house=HOUSE_NONE) const;\n\t\tvirtual ObjectClass * Create_One_Of(HouseClass *) const;\n\t\tvirtual short const * Occupy_List(bool placement=false) const;\n\t\tvirtual void Draw_It(int x, int y, int data) const;\n\t\tvirtual unsigned char * Radar_Icon(int data) const;\n\n\t\t#ifdef SCENARIO_EDITOR\n\t\tvirtual void Display(int x, int y, WindowNumberType window, HousesType house=HOUSE_NONE) const;\n\t\t#endif\n};\n\n\n/****************************************************************************\n**\tThis type elaborates the various \"smudge\" effects that can occur. Smudges are\n**\tthose elements which are on top off all the ground icons, but below anything\n**\tthat is \"above\" it. This includes scorch marks, craters, and infantry bodies.\n**\tSmudges, be definition, contain transparency. The are modifiers to underlying\n**\tterrain imagery.\n*/\nclass SmudgeTypeClass : public ObjectTypeClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tWhat overlay is this.\n\t\t*/\n\t\tSmudgeType Type;\n\n\t\t/*\n\t\t**\tSome smudges are larger than one cell. If this is the case, then\n\t\t**\tthese dimensions specify the number of cells wide and tall the\n\t\t**\tsmudge is.\n\t\t*/\n\t\tint Width;\n\t\tint Height;\n\n\t\t/*\n\t\t**\tIs this smudge a crater type? If so, then a second crater can be added to\n\t\t**\tthis smudge so that a more cratered landscape results.\n\t\t*/\n\t\tunsigned IsCrater:1;\n\n\t\t/*\n\t\t**\tIs this overlay used as the attached road piece for buildings (bib)?\n\t\t*/\n\t\tunsigned IsBib:1;\n\n\t\t//----------------------------------------------------------\n\t\tSmudgeTypeClass(NoInitClass const & x) : ObjectTypeClass(x) {}\n\t\tSmudgeTypeClass(\n\t\t\tSmudgeType smudge,\n\t\t\tchar const * ininame,\n\t\t\tint fullname,\n\t\t\tint width,\n\t\t\tint height,\n\t\t\tbool isbib,\n\t\t\tbool iscrater\n\t\t\t);\n\n\t\tstatic void * operator new(size_t);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void * ptr);\n\n\t\tstatic void Init_Heap(void);\n\t\tstatic SmudgeType From_Name(char const * name);\n\t\tstatic SmudgeTypeClass & As_Reference(SmudgeType type);\n\t\tstatic void Init(TheaterType);\n\t\tstatic void One_Time(void);\n\t\tstatic void Prep_For_Add(void);\n\n\t\tvirtual bool Create_And_Place(CELL cell, HousesType house=HOUSE_NONE) const;\n\t\tvirtual ObjectClass * Create_One_Of(HouseClass *) const;\n\t\tvirtual short const * Occupy_List(bool placement=false) const;\n\t\tvirtual short const * Overlap_List(void) const {return Occupy_List();};\n\t\tvirtual void Draw_It(int x, int y, int data) const ;\n\n\t\t#ifdef SCENARIO_EDITOR\n\t\tvirtual void Display(int x, int y, WindowNumberType window, HousesType house=HOUSE_NONE) const;\n\t\t#endif\n};\n\n#endif\n\n"
  },
  {
    "path": "CODE/UDATA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/UDATA.CPP 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : UDATA.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : July 19, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   UnitTypeClass::As_Reference -- Fetches a reference to the unit type class specified.      *\n *   UnitTypeClass::Create_And_Place -- Creates and places a unit object onto the map.         *\n *   UnitTypeClass::Create_One_Of -- Creates a unit in limbo.                                  *\n *   UnitTypeClass::Dimensions -- Determines the unit's pixel dimensions.                      *\n *   UnitTypeClass::Display -- Displays a generic unit shape.                                  *\n *   UnitTypeClass::From_Name -- Fetch class pointer from specified name.                      *\n *   UnitTypeClass::Init_Heap -- Initialize the unit type class heap.                          *\n *   UnitTypeClass::Max_Pips -- Fetches the maximum pips allowed for this unit.                *\n *   UnitTypeClass::One_Time -- Performs one time processing for unit type class objects.      *\n *   UnitTypeClass::Prep_For_Add -- Prepares scenario editor to add unit.                      *\n *   UnitTypeClass::Read_INI -- Fetch the unit type data from the INI database.                *\n *   UnitTypeClass::Turret_Adjust -- Turret adjustment routine for MLRS and MSAM units.        *\n *   UnitTypeClass::UnitTypeClass -- Constructor for unit types.                               *\n *   UnitTypeClass::operator delete -- Return a unit type class object back to the pool.       *\n *   UnitTypeClass::operator new -- Allocates an object from the unit type class heap.         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n/*\n**\tThis is the list of animation stages to use when the harvester\n**\tis to dump its load into the refinery. The offsets are based from the\n**\tstart of the dump animation.\n*/\nconst int UnitTypeClass::Harvester_Dump_List[22] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,6,5,4,3,2,1,0};\nconst int UnitTypeClass::Harvester_Load_List[9] = {0, 1, 2, 3, 4, 5, 6, 7, 0};\nconst int UnitTypeClass::Harvester_Load_Count = 8;\n\n\n// V2 rocket launcher\nstatic UnitTypeClass const UnitV2Launcher(\n\tUNIT_V2_LAUNCHER,\n\tTXT_V2_LAUNCHER,\t\t// NAME:\t\t\tText name of this unit type.\n\t\"V2RL\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FRAG1,\t\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\ttrue,\t\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\ttrue,\t\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n// Light tank\nstatic UnitTypeClass const UnitLTank(\n\tUNIT_LTANK,\n\tTXT_LTANK,\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"1TNK\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FRAG1,\t\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0020,\t\t\t\t\t//\tVertical offset.\n\t0x00C0,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\ttrue,\t\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\ttrue,\t\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\tfalse,\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n// Heavy tank\nstatic UnitTypeClass const UnitMTank(\n\tUNIT_MTANK,\n\tTXT_MTANK,\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"3TNK\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FRAG1,\t\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0040,\t\t\t\t\t//\tVertical offset.\n\t0x0080,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0018,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0080,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0018,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\ttrue,\t\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\ttrue,\t\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\ttrue,\t\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n// Medium tank\nstatic UnitTypeClass const UnitMTank2(\n\tUNIT_MTANK2,\n\tTXT_MTANK2,\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"2TNK\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FRAG1,\t\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0030,\t\t\t\t\t//\tVertical offset.\n\t0x00C0,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x00C0,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\ttrue,\t\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\ttrue,\t\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\ttrue,\t\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n// Mastadon tank\nstatic UnitTypeClass const UnitHTank(\n\tUNIT_HTANK,\n\tTXT_HTANK,\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"4TNK\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_ART_EXP1,\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0020,\t\t\t\t\t//\tVertical offset.\n\t0x00C0,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0028,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0008,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0040,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\ttrue,\t\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\ttrue,\t\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\ttrue,\t\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n// Mobile Radar Jammer\nstatic UnitTypeClass const UnitMRJammer(\n\tUNIT_MRJ,\n\tTXT_MRJ,\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"MRJ\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FRAG1,\t\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\ttrue,\t\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t\ttrue,\t\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\tfalse,\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\ttrue,\t\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n// Mobile Gap Generator\nstatic UnitTypeClass const UnitMGG(\n\tUNIT_MGG,\n\tTXT_MGG,\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"MGG\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FRAG1,\t\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t\ttrue,\t\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\ttrue,\t\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\ttrue,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n// Artillery\nstatic UnitTypeClass const UnitArty(\n\tUNIT_ARTY,\n\tTXT_ARTY,\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"ARTY\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_ART_EXP1,\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0040,\t\t\t\t\t//\tVertical offset.\n\t0x0060,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\ttrue,\t\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\tfalse,\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\tfalse,\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n// Harvester\nstatic UnitTypeClass const UnitHarvester(\n\tUNIT_HARVESTER,\n\tTXT_HARVESTER,\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"HARV\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FBALL1,\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_ALTERNATE,\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\ttrue,\t\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\ttrue,\t\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Can this unit squash infantry?\n\t\ttrue,\t\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\ttrue,\t\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HARVEST\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n// Mobile construction vehicle\nstatic UnitTypeClass const UnitMCV(\n\tUNIT_MCV,\n\tTXT_MCV,\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"MCV\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FBALL1,\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_ALTERNATE,\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\ttrue,\t\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\ttrue,\t\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n// Jeep (hummer)\nstatic UnitTypeClass const UnitJeep(\n\tUNIT_JEEP,\n\tTXT_JEEP,\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"JEEP\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FRAG1,\t\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0030,\t\t\t\t\t//\tVertical offset.\n\t0x0030,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0030,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\ttrue,\t\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\tfalse,\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\ttrue,\t\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\tfalse,\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n// Armored personnel carrier\nstatic UnitTypeClass const UnitAPC(\n\tUNIT_APC,\n\tTXT_APC,\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"APC\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FRAG1,\t\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0030,\t\t\t\t\t//\tVertical offset.\n\t0x0030,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0030,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\ttrue,\t\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\tfalse,\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n// Mine laying truck\nstatic UnitTypeClass const UnitMineLayer(\n\tUNIT_MINELAYER,\n\tTXT_MINE_LAYER,\t\t// NAME:\t\t\tText name of this unit type.\n\t\"MNLY\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FRAG1,\t\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\ttrue,\t\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\tfalse,\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n// Convoy Truck\nstatic UnitTypeClass const UnitConvoyTruck(\n\tUNIT_TRUCK,\n\tTXT_TRUCK,\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"TRUK\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FRAG1,\t\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\tfalse,\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\tfalse,\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_GUARD\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n#ifdef FIXIT_ANTS\n/*\n[ANT]\nName=Warrior Ant\nPrimary=Mandible\nStrength=150\nArmor=light\nTechLevel=-1\nSight=2\nSpeed=5\nCost=700\nPoints=40\nROT=5\nTracked=yes\nCrewed=no\nNoMovingFire=yes\n\n; Ant mandible\n[Mandible]\nDamage=50\nROF=5\nRange=1.5\nProjectile=Invisible\nSpeed=100\nWarhead=HollowPoint\nReport=none\n\n\n*/\n\n// Warrior ant\nstatic UnitTypeClass const UnitAnt1(\n\tUNIT_ANT1,\n\tTXT_NONE,\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"ANT1\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_ANT_DEATH,\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\ttrue,\t\t\t\t\t// Always use the given name for the vehicle?\n\t\tfalse,\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\ttrue,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\ttrue,\t\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t8,\t\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\nstatic UnitTypeClass const UnitAnt2(\n\tUNIT_ANT2,\n\tTXT_NONE,\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"ANT2\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_ANT_DEATH,\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\ttrue,\t\t\t\t\t// Always use the given name for the vehicle?\n\t\tfalse,\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\ttrue,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\ttrue,\t\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t8,\t\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\nstatic UnitTypeClass const UnitAnt3(\n\tUNIT_ANT3,\n\tTXT_NONE,\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"ANT3\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_ANT_DEATH,\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\ttrue,\t\t\t\t\t// Always use the given name for the vehicle?\n\t\tfalse,\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\ttrue,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\ttrue,\t\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t8,\t\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// Chrono Tank\nstatic UnitTypeClass const UnitChrono(\n\tUNIT_CHRONOTANK,\n\tTXT_CHRONOTANK,\t\t// NAME:\t\t\tText name of this unit type.\n\t\"CTNK\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FRAG1,\t\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\ttrue,\t\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n// Tesla Tank\nstatic UnitTypeClass const UnitTesla(\n\tUNIT_TESLATANK,\n\tTXT_TESLATANK,\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"TTNK\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FRAG1,\t\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\ttrue,\t\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t\ttrue,\t\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\ttrue,\t\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\ttrue,\t\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n// M.A.D. Tank\nstatic UnitTypeClass const UnitMAD(\n\tUNIT_MAD,\n\tTXT_MAD,\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"QTNK\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FRAG1,\t\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\ttrue,\t\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n\n// Demolition Truck\nstatic UnitTypeClass const UnitDemoTruck(\n\tUNIT_DEMOTRUCK,\n\tTXT_DEMOTRUCK,\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"DTRK\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FRAG1,\t\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\tfalse,\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\n\t\tfalse,\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_GUARD\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n#ifdef FIXIT_PHASETRANSPORT\t//\tchecked - ajw 9/28/98\nstatic UnitTypeClass const UnitPhase(\n\tUNIT_PHASE,\n\tTXT_PHASETRANSPORT,\t// NAME:\t\t\tText name of this unit type.\n\t\"STNK\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FRAG1,\t\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\tREMAP_NORMAL,\t\t\t// Sidebar remap logic.\n\t0x0030,\t\t\t\t\t//\tVertical offset.\n\t0x0030,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0030,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Can this be a goodie surprise from a crate?\n\t\tfalse,\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Can this unit squash infantry?\n\t\tfalse,\t\t\t\t// Does this unit harvest Tiberium?\n\t\tfalse,\t\t\t\t// Is invisible to radar?\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\ttrue,\t\t\t\t\t// Is it equipped with a combat turret?\n\t\tfalse,\t\t\t\t// Does it have a rotating radar dish?\n\t\tfalse,\t\t\t\t// Is there an associated firing animation?\n\t\tfalse,\t\t\t\t// Must the turret be in a locked down position while moving?\ntrue,//\t\tfalse,\t\t\t\t// Is this a gigundo-rotund-enormous unit?\n\t\tfalse,\t\t\t\t// Does the unit have a constant animation?\n\t\tfalse,\t\t\t\t// Is the unit capable of jamming radar?\n\t\tfalse,\t\t\t\t// Is the unit a mobile gap generator?\n\t32,\t\t\t\t\t\t// Rotation stages.\n\t0,\t\t\t\t\t\t\t// Turret center offset along body centerline.\n\tMISSION_HUNT\t\t\t// ORDERS:\t\tDefault order to give new unit.\n);\n\n#endif\n#endif\n\n/***********************************************************************************************\n * UnitTypeClass::UnitTypeClass -- Constructor for unit types.                                 *\n *                                                                                             *\n *    This is the constructor for the unit types. It is used to initialize the unit type class *\n *    structure. The unit type class is used to control the behavior of the various types      *\n *    of units in the game. This constructor is called for every unique unit type as it        *\n *    exists in the array of unit types.                                                       *\n *                                                                                             *\n * INPUT:   bla bla bla... see below                                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nUnitTypeClass::UnitTypeClass(\n\t\t\t\tUnitType type,\n\t\t\t\tint name,\n\t\t\t\tchar const * ininame,\n\t\t\t\tAnimType exp,\n\t\t\t\tRemapType remap,\n\t\t\t\tint verticaloffset,\n\t\t\t\tint primaryoffset,\n\t\t\t\tint primarylateral,\n\t\t\t\tint secondaryoffset,\n\t\t\t\tint secondarylateral,\n\t\t\t\tbool is_goodie,\n\t\t\t\tbool is_nominal,\n\t\t\t\tbool is_crusher,\n\t\t\t\tbool is_harvest,\n\t\t\t\tbool is_stealthy,\n\t\t\t\tbool is_insignificant,\n\t\t\t\tbool is_turret_equipped,\n\t\t\t\tbool is_radar_equipped,\n\t\t\t\tbool is_fire_anim,\n\t\t\t\tbool is_lock_turret,\n\t\t\t\tbool is_gigundo,\n\t\t\t\tbool is_animating,\n\t\t\t\tbool is_jammer,\n\t\t\t\tbool is_gapper,\n\t\t\t\tint rotation,\n\t\t\t\tint toffset,\n\t\t\t\tMissionType order) :\n\t\t\t\t\tTechnoTypeClass(RTTI_UNITTYPE,\n\t\t\t\t\t\t\t\t\t\tint(type),\n\t\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\t\tininame,\n\t\t\t\t\t\t\t\t\t\tremap,\n\t\t\t\t\t\t\t\t\t\tverticaloffset,\n\t\t\t\t\t\t\t\t\t\tprimaryoffset,\n\t\t\t\t\t\t\t\t\t\tprimarylateral,\n\t\t\t\t\t\t\t\t\t\tsecondaryoffset,\n\t\t\t\t\t\t\t\t\t\tsecondarylateral,\n\t\t\t\t\t\t\t\t\t\tis_nominal,\n\t\t\t\t\t\t\t\t\t\tis_stealthy,\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\tis_insignificant,\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\tis_turret_equipped,\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\trotation,\n\t\t\t\t\t\t\t\t\t\tSPEED_TRACK),\n\tIsCrateGoodie(is_goodie),\n\tIsCrusher(is_crusher),\n\tIsToHarvest(is_harvest),\n\tIsRadarEquipped(is_radar_equipped),\n\tIsFireAnim(is_fire_anim),\n\tIsLockTurret(is_lock_turret),\n\tIsGigundo(is_gigundo),\n\tIsAnimating(is_animating),\n\tIsJammer(is_jammer),\n\tIsGapper(is_gapper),\n\tIsNoFireWhileMoving(false),\n\tType(type),\n\tTurretOffset(toffset),\n\tMission(order),\n\tExplosion(exp),\n\tMaxSize(0)\n{\n\t/*\n\t**\tForced unit overrides form the default.\n\t*/\n\tSpeed = SPEED_WHEEL;\n}\n\n\n/***********************************************************************************************\n * UnitTypeClass::operator new -- Allocates an object from the unit type class heap.           *\n *                                                                                             *\n *    Use this routine to allocate a unit type class object from the special heap that is      *\n *    maintained for this purpose.                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the newly allocated unit type class object. If there is  *\n *          no more room to allocate another unit type class object, then NULL will be         *\n *          returned.                                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * UnitTypeClass::operator new(size_t)\n{\n\treturn(UnitTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * UnitTypeClass::operator delete -- Return a unit type class object back to the pool.         *\n *                                                                                             *\n *    This will return a previously allocated unit to the memory pool from whence it came.     *\n *                                                                                             *\n * INPUT:   pointer  -- A Pointer to the unit type class object to return to the memory pool.  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitTypeClass::operator delete(void * pointer)\n{\n\tUnitTypes.Free((UnitTypeClass *)pointer);\n}\n\n\n/***********************************************************************************************\n * UnitTypeClass::Init_Heap -- Initialize the unit type class heap.                            *\n *                                                                                             *\n *    This initializes the unit type class heap by pre-allocated all the known unit types.     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this once and call it before processing the rules.ini file.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese unit type class objects must be allocated in the exact order that they\n\t**\tare specified in the UnitType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew UnitTypeClass(UnitHTank);\t\t\t//\tUNIT_HTANK\n\tnew UnitTypeClass(UnitMTank);\t\t\t//\tUNIT_MTANK\n\tnew UnitTypeClass(UnitMTank2);\t\t//\tUNIT_MTANK2\n\tnew UnitTypeClass(UnitLTank);\t\t\t//\tUNIT_LTANK\n\tnew UnitTypeClass(UnitAPC);\t\t\t//\tUNIT_APC\n\tnew UnitTypeClass(UnitMineLayer);\t// UNIT_MINELAYER\n\tnew UnitTypeClass(UnitJeep);\t\t\t//\tUNIT_JEEP\n\tnew UnitTypeClass(UnitHarvester);\t//\tUNIT_HARVESTER\n\tnew UnitTypeClass(UnitArty);\t\t\t//\tUNIT_ARTY\n\tnew UnitTypeClass(UnitMRJammer);\t\t//\tUNIT_MRJ\n\tnew UnitTypeClass(UnitMGG);\t\t\t//\tUNIT_MGG\n\tnew UnitTypeClass(UnitMCV);\t\t\t// UNIT_MCV\n\tnew UnitTypeClass(UnitV2Launcher);\t//\tUNIT_V2_LAUNCHER\n\tnew UnitTypeClass(UnitConvoyTruck);\t// UNIT_TRUCK\n#ifdef FIXIT_ANTS\n\tnew UnitTypeClass(UnitAnt1);\t\t\t// UNIT_ANT1\n\tnew UnitTypeClass(UnitAnt2);\t\t\t// UNIT_ANT2\n\tnew UnitTypeClass(UnitAnt3);\t\t\t// UNIT_ANT3\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tnew UnitTypeClass(UnitChrono);\t\t// UNIT_CHRONOTANK\n\tnew UnitTypeClass(UnitTesla);\t\t\t// UNIT_TESLATANK\n\tnew UnitTypeClass(UnitMAD);\t\t\t// UNIT_MAD\n\tnew UnitTypeClass(UnitDemoTruck);\t// UNIT_DEMOTRUCK\n#ifdef FIXIT_PHASETRANSPORT\t//\tchecked - ajw 9/28/98\n\tnew UnitTypeClass(UnitPhase);\t\t\t//\tUNIT_PHASETRANSPORT\n#endif\n#endif\n\n}\n\n\n/***********************************************************************************************\n * UnitTypeClass::From_Name -- Fetch class pointer from specified name.                        *\n *                                                                                             *\n *    This routine converts an ASCII representation of a unit class and                        *\n *    converts it into a real unit class number.                                               *\n *                                                                                             *\n * INPUT:   name  -- ASCII name representing a unit class.                                     *\n *                                                                                             *\n * OUTPUT:  Returns with the actual unit class number that the string                          *\n *          represents.                                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *   05/02/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nUnitType UnitTypeClass::From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (UnitType classid = UNIT_FIRST; classid < UNIT_COUNT; classid++) {\n\t\t\tif (stricmp(As_Reference(classid).IniName, name) == 0) {\n\t\t\t\treturn(classid);\n\t\t\t}\n\t\t}\n\t}\n\treturn(UNIT_NONE);\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***********************************************************************************************\n * UnitTypeClass::Display -- Displays a generic unit shape.                                    *\n *                                                                                             *\n *    This routine displays a generic representation of a unit of this                         *\n *    type. Typically, it is used when adding objects to the game map.                         *\n *                                                                                             *\n * INPUT:   x,y   -- Coordinate to render the unit shape.                                      *\n *                                                                                             *\n *          window-- Window to render within.                                                  *\n *                                                                                             *\n *          house -- House to render the unit colors.                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/14/1994 JLB : Created.                                                                 *\n *   11/08/1994 JLB : Handles chunky type vehicles now.                                        *\n *=============================================================================================*/\nvoid UnitTypeClass::Display(int x, int y, WindowNumberType window, HousesType ) const\n{\n\tint shape = 0;\n\tvoid const * ptr = Get_Cameo_Data();\n\tif (ptr == NULL) {\n\t\tptr = Get_Image_Data();\n\t\tshape = Rotation/6;\n\t}\n\tCC_Draw_Shape(ptr, shape, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL);\n}\n\n\n/***********************************************************************************************\n * UnitTypeClass::Prep_For_Add -- Prepares scenario editor to add unit.                        *\n *                                                                                             *\n *    This routine is used to prepare the generic object adder dialog                          *\n *    box so that it will be able to add a unit object.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *   06/04/1994 JLB : Uses map editing interface functions.                                    *\n *=============================================================================================*/\nvoid UnitTypeClass::Prep_For_Add(void)\n{\n\tfor (UnitType index = UNIT_FIRST; index < UNIT_COUNT; index++) {\n\t\tif (As_Reference(index).Get_Image_Data() != NULL) {\n\t\t\tMap.Add_To_List(&As_Reference(index));\n\t\t}\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * UnitTypeClass::One_Time -- Performs one time processing for unit type class objects.        *\n *                                                                                             *\n *    This routine is used to perform the action necessary only once for the unit type class.  *\n *    It loads unit shapes and brain files.   This routine should only be called once.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once.                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitTypeClass::One_Time(void)\n{\n\tfor (UnitType index = UNIT_FIRST; index < UNIT_COUNT; index++) {\n\t\tchar\tfullname[_MAX_FNAME+_MAX_EXT];\n\t\tchar\tbuffer[_MAX_FNAME];\n\t\tUnitTypeClass const & uclass = As_Reference(index);\n\t\tCCFileClass\tfile;\n\n\t\tvoid const * ptr;\t\t// Shape pointer and set pointer.\n\n\t\tint largest = 0;\n//\t\tif (uclass.Level != -1) {\n//\t\tif (uclass.IsBuildable) {\n\n\t\t\t/*\n\t\t\t**\tFetch the supporting data files for the unit.\n\t\t\t*/\n\t\t\tsprintf(buffer, \"%sICON\", uclass.Graphic_Name());\n\t\t\t_makepath(fullname, NULL, NULL, buffer, \".SHP\");\n\t\t\t#ifndef NDEBUG\n\t\t\t\tRawFileClass datafile(fullname);\n\t\t\t\tif (datafile.Is_Available()) {\n\t\t\t\t\t((void const *&)uclass.CameoData) = Load_Alloc_Data(datafile);\n\t\t\t\t} else {\n\t\t\t\t\t((void const *&)uclass.CameoData) = MFCD::Retrieve(fullname);\n\t\t\t\t}\n\t\t\t#else\n\t\t\t\t((void const *&)uclass.CameoData) = MFCD::Retrieve(fullname);\n\t\t\t#endif\n//\t\t}\n\n\t\t/*\n\t\t**\tFetch a pointer to the unit's shape data.\n\t\t*/\n\t\t_makepath(fullname, NULL, NULL, uclass.Graphic_Name(), \".SHP\");\n\t\t#ifndef NDEBUG\n\t\t\tRawFileClass shpfile(fullname);\n\t\t\tif (shpfile.Is_Available()) {\n\t\t\t\tptr = Load_Alloc_Data(shpfile);\n\t\t\t} else {\n\t\t\t\tptr = MFCD::Retrieve(fullname);\n\t\t\t}\n\t\t#else\n\t\t\tptr = MFCD::Retrieve(fullname);\n\t\t#endif\n\n\t\t((void const *&)uclass.ImageData) = ptr;\n\t\tif (ptr != NULL) {\n\n\t\t\tlargest = max(largest, (int)Get_Build_Frame_Width(ptr));\n\t\t\tlargest = max(largest, (int)Get_Build_Frame_Height(ptr));\n\t\t}\n\n\t\t((int &)uclass.MaxSize) = max(largest, 8);\n\t}\n\n\t/*\n\t**\tLoad any custom shapes at this time.\n\t*/\n\tif (WakeShapes == NULL) {\n\t\tWakeShapes = MFCD::Retrieve(\"WAKE.SHP\");\n\t}\n\tif (TurretShapes == NULL) {\n\t\tTurretShapes = MFCD::Retrieve(\"TURR.SHP\");\n\t}\n\tif (SamShapes == NULL) {\n\t\tSamShapes = MFCD::Retrieve(\"SSAM.SHP\");\n\t}\n\tif (MGunShapes == NULL) {\n\t\tMGunShapes = MFCD::Retrieve(\"MGUN.SHP\");\n\t}\n}\n\n\n/***********************************************************************************************\n * UnitTypeClass::Create_And_Place -- Creates and places a unit object onto the map.           *\n *                                                                                             *\n *    This routine is used by the scenario editor to create and place a unit object of this    *\n *    type onto the map.                                                                       *\n *                                                                                             *\n * INPUT:   cell     -- The cell that the unit is to be placed into.                           *\n *                                                                                             *\n *          house    -- The house that the unit belongs to.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the unit created and placed successfully?                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool UnitTypeClass::Create_And_Place(CELL cell, HousesType house) const\n{\n\tUnitClass * unit = new UnitClass(Type, house);\n\tif (unit != NULL) {\n\t\treturn(unit->Unlimbo(Cell_Coord(cell), Random_Pick(DIR_N, DIR_MAX)));\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * UnitTypeClass::Create_One_Of -- Creates a unit in limbo.                                    *\n *                                                                                             *\n *    This function creates a unit of this type and keeps it in limbo. A pointer to the        *\n *    created unit object is returned. It is presumed that this object will later be           *\n *    unlimboed at the correct time and place.                                                 *\n *                                                                                             *\n * INPUT:   house -- Pointer to the house that is to own the unit.                             *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the created unit object. If the unit object              *\n *          could not be created, then NULL is returned.                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/07/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * UnitTypeClass::Create_One_Of(HouseClass * house) const\n{\n\treturn(new UnitClass(Type, house->Class->House));\n}\n\n\n/***********************************************************************************************\n * UnitTypeClass::As_Reference -- Fetches a reference to the unit type class specified.        *\n *                                                                                             *\n *    Use this routine to return a reference to the UnitTypeClass object as indicated by       *\n *    the unit type number specified.                                                          *\n *                                                                                             *\n * INPUT:   type  -- The unit type number to convert into a UnitTypeClass object reference.    *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the unit type class object specified.                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nUnitTypeClass & UnitTypeClass::As_Reference(UnitType type)\n{\n\treturn(*UnitTypes.Ptr(type));\n}\n\n\n/***********************************************************************************************\n * UnitTypeClass::Dimensions -- Determines the unit's pixel dimensions.                        *\n *                                                                                             *\n *    This routine will fill in the width and height for this unit type. This width and        *\n *    height are used to render the selection rectangle and the positioning of the health      *\n *    bargraph.                                                                                *\n *                                                                                             *\n * INPUT:   width    -- Reference to the width of the unit (to be filled in).                  *\n *                                                                                             *\n *          height   -- Reference to the height of the unit (to be filled in).                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitTypeClass::Dimensions(int &width, int &height) const\n{\n\twidth = MaxSize-(MaxSize/4);\n\twidth = min(width, 48);\n\theight = MaxSize-(MaxSize/4);\n\theight = min(height, 48);\n}\n\n\n/***********************************************************************************************\n * UnitTypeClass::Max_Pips -- Fetches the maximum pips allowed for this unit.                  *\n *                                                                                             *\n *    This routine will determine the number of pips (maximum) allowed for this unit type.     *\n *    Typically, this is the number of passengers allowed, but for harvesters, it is the       *\n *    number of credits it holds divided by 100.                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the maximum number of pips allowed for this unit type.                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/26/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint UnitTypeClass::Max_Pips(void) const\n{\n\tif (Type == UNIT_HARVESTER) {\n\t\treturn(7);\n\t}\n\n\tif (Type == UNIT_MINELAYER) {\n\t\treturn(MaxAmmo);\n\t}\n\treturn(Max_Passengers());\n}\n\n\n/***********************************************************************************************\n * UnitTypeClass::Turret_Adjust -- Turret adjustment routine for MLRS and MSAM units.          *\n *                                                                                             *\n *    This routine adjusts the pixel coordinates specified to account for the displacement of  *\n *    the turret on the MLRS and MSAM vehicles.                                                *\n *                                                                                             *\n * INPUT:   dir   -- The direction of the body of the vehicle.                                 *\n *                                                                                             *\n *          x,y   -- References to the turret center pixel position. These will be modified as *\n *                   necessary.                                                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitTypeClass::Turret_Adjust(DirType dir, int &x, int &y) const\n{\n\tstatic struct {\n\t\tsigned char X,Y;\n\t} _adjust[32] = {\n\t  \t{1,2},\t// N\n\t  \t{-1,1},\n\t  \t{-2,0},\n\t  \t{-3,0},\n\t  \t{-3,1},\t// NW\n\t  \t{-4,-1},\n\t  \t{-4,-1},\n\t  \t{-5,-2},\n\t  \t{-5,-3},\t// W\n\t  \t{-5,-3},\n\t  \t{-3,-3},\n\t  \t{-3,-4},\n\t  \t{-3,-4},\t// SW\n\t  \t{-3,-5},\n\t  \t{-2,-5},\n\t  \t{-1,-5},\n\t  \t{0,-5},\t// S\n\t  \t{1,-6},\n\t  \t{2,-5},\n\t  \t{3,-5},\n\t  \t{4,-5},\t// SE\n\t  \t{6,-4},\n\t  \t{6,-3},\n\t  \t{6,-3},\n\t  \t{6,-3},\t// E\n\t  \t{5,-1},\n\t  \t{5,-1},\n\t  \t{4,0},\n\t  \t{3,0},\t// NE\n\t  \t{2,0},\n\t  \t{2,1},\n\t  \t{1,2}\n\t};\n\n\tint index = 0;\n\tswitch (Type) {\n\t\tcase UNIT_JEEP:\n\t\t\ty -= 4;\n\t\t\tbreak;\n\n\t\tcase UNIT_MGG:\n\t\t\tindex = Dir_To_32(dir);\n\t\t\tx += _adjust[index].X;\n\t\t\ty += _adjust[index].Y;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * UnitTypeClass::Read_INI -- Fetch the unit type data from the INI database.                  *\n *                                                                                             *\n *    This routine will find the section in the INI database for this unit type object and     *\n *    then fill in the override values specified.                                              *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database that will be examined.                      *\n *                                                                                             *\n * OUTPUT:  bool; Was the section for this unit found in the database and the data extracted?  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool UnitTypeClass::Read_INI(CCINIClass & ini)\n{\n\tif (TechnoTypeClass::Read_INI(ini)) {\n\t\tIsNoFireWhileMoving = ini.Get_Bool(IniName, \"NoMovingFire\", IsNoFireWhileMoving);\n\t\tSpeed = ini.Get_Bool(IniName, \"Tracked\", (Speed == SPEED_TRACK)) ? SPEED_TRACK : SPEED_WHEEL;\n\n\t\t/*\n\t\t**\tIf this unit can drive over walls, then mark it as recognizing the crusher zone.\n\t\t*/\n\t\tif (MZone < MZONE_CRUSHER && IsCrusher) {\n\t\t\tMZone = MZONE_CRUSHER;\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "CODE/UDPADDR.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n\n#include \"function.h\"\n//#include \"_WSProto.h\"\n#include \"WSPUDP.h\"\n\n\nbool Get_Broadcast_Addresses (void)\n{\n\tint d_dialog_w = 320 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 160 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320*RESFACTOR - d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\tint d_dialog_y = ((200*RESFACTOR - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_txt6_h = 6 *RESFACTOR+1;\t\t\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_margin1 = 5 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// large margin\n\tint d_margin2 = 7 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// small margin\n\n\tint d_ip_address_list_w = 300 *RESFACTOR;\n\tint d_ip_address_list_h = ((20 * 6) + 3) *RESFACTOR;\t\t// 6 rows high\n\tint d_ip_address_list_x = d_dialog_cx - d_ip_address_list_w / 2;\n\tint d_ip_address_list_y = d_margin2 + d_dialog_y;\n\n\n\tint d_ok_w = 40*RESFACTOR;\n\tint d_ok_h = 9*RESFACTOR;\n\tint d_ok_x = d_dialog_cx + d_dialog_w / 4;\n\tint d_ok_y = d_dialog_y + d_dialog_h - 20*RESFACTOR;\n\n#if (GERMAN | FRENCH)\n\tint d_cancel_w = 50*RESFACTOR;\n#else\n\tint d_cancel_w = 40*RESFACTOR;\n#endif\n\tint d_cancel_h = 9*RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - d_dialog_w / 4;\n\tint d_cancel_y = d_dialog_y + d_dialog_h - 20*RESFACTOR;\n\n\t//------------------------------------------------------------------------\n\t//\tButton Enumerations\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tBUTTON_IPLIST=100,\n\t\tBUTTON_OK,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t//------------------------------------------------------------------------\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PARMS,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t//------------------------------------------------------------------------\n\t//\tDialog variables\n\t//------------------------------------------------------------------------\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\n\tint\twidth;\n\tint\theight;\n\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\tFancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);\n\tFormat_Window_String(\"IP Addresses\", SeenBuff.Get_Height(), width, height);\n\n\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\tColorListClass ip_address_list(BUTTON_IPLIST, d_ip_address_list_x, d_ip_address_list_y, d_ip_address_list_w, d_ip_address_list_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\n\tTextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_BUTTON, d_ok_x, d_ok_y, d_ok_w, d_ok_h);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n\n\tip_address_list.Set_Selected_Style(ColorListClass::SELECT_NORMAL);\n\n\tFancy_Text_Print(\"\", 0, 0, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\n\tLoad_Title_Page(true);\n\tCCPalette.Set();\t//GamePalette.Set();\n\n\n\n\t/*\n\t** Add all the ip addresses from the ini file to the list box.\n\t*/\n\tCCINIClass ip_ini;\n\tint res=0;\n\n\tif (ip_ini.Load(CCFileClass(\"IP.INI\"), false)) {\n\t\tint entry=0;\n\t\tchar entry_name[16];\n\t\tdo {\n\t\t\tentry++;\n\t\t\tchar *temp = new char [128];\n\t\t\tsprintf (entry_name, \"%d\", entry);\n\t\t\tres = ip_ini.Get_String(\"IP_ADDRESSES\", entry_name, \"\", temp, 128);\n\t\t\tif ( res ) {\n\t\t\t\tip_address_list.Add_Item (temp);\nchar debug[128];\nsprintf (debug, \"RA95 - Adding address %s\\n\", temp);\nWWDebugString (debug);\n\t\t\t}\n\t\t}while (res);\n\t}\n\tip_address_list.Flag_To_Redraw();\n\n\n\t//------------------------------------------------------------------------\n\t//\tProcessing loop\n\t//------------------------------------------------------------------------\n\twhile (process) {\n\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\t//.....................................................................\n\t\t//\tRefresh display if needed\n\t\t//.....................................................................\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw backgound & dialog box\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tCCPalette.Set();\t//GamePalette.Set();\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tDialog & Field labels\n\t\t\t\t//...............................................................\n\t\t\t\tFancy_Text_Print(\"IP Addresses\", d_dialog_cx-width/2, d_dialog_y + 25*RESFACTOR, scheme, TBLACK, TPF_TEXT);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tRebuild the button list\n\t\t\t\t//...............................................................\n\t\t\t\tokbtn.Zap();\n\t\t\t\tcancelbtn.Zap();\n\t\t\t\tip_address_list.Zap();\n\n\t\t\t\tcommands = &okbtn;\n\t\t\t\tcancelbtn.Add_Tail(*commands);\n\t\t\t\tip_address_list.Add_Tail(*commands);\n\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw buttons\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcommands->Draw_All();\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tGet user input\n\t\t//.....................................................................\n\t\tinput = commands->Input();\n\n\t\t//.....................................................................\n\t\t//\tProcess input\n\t\t//.....................................................................\n\t\tswitch (input) {\n\n\t\t\t//..................................................................\n\t\t\t// ESC / CANCEL: send a SIGN_OFF\n\t\t\t// - If we're part of a game, stay in this dialog; otherwise, exit\n\t\t\t//..................................................................\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\treturn (false);\n\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\n\t//------------------------------------------------------------------------\n\t//\tRestore screen\n\t//------------------------------------------------------------------------\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n\tCCPalette.Set();\t//GamePalette.Set();\n\tShow_Mouse();\n\n\tfor ( int i=0 ; i<ip_address_list.Count() ; i++ ) {\n\t\tchar const *temp = ip_address_list.Get_Item(i);\n\t\tchar *cut = strchr (temp, '#');\n\t\tif ( cut ) *cut = 0;\n\t\tPacketTransport->Set_Broadcast_Address ((char*)temp);\n\t}\n\n\treturn (true);\n}"
  },
  {
    "path": "CODE/UNIT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/UNIT.CPP 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : UNIT.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : November 3, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Recoil_Adjust -- Adjust pixel values in direction specified.                              *\n *   UnitClass::AI -- AI processing for the unit.                                              *\n *   UnitClass::APC_Close_Door -- Closes an APC door.                                          *\n *   UnitClass::APC_Open_Door -- Opens an APC door.                                            *\n *   UnitClass::Active_Click_With -- Intercepts the active click to see if deployment is possib*\n *   UnitClass::Active_Click_With -- Performs specified action on specified cell.              *\n *   UnitClass::Approach_Target -- Handles approaching the target in order to attack it.       *\n *   UnitClass::Assign_Destination -- Assign a destination to a unit.                          *\n *   UnitClass::Blocking_Object -- Determines how a object blocks a unit                       *\n *   UnitClass::Can_Enter_Cell -- Determines cell entry legality.                              *\n *   UnitClass::Can_Fire -- Determines if turret can fire upon target.                         *\n *   UnitClass::Click_With -- Handles player map clicking while this unit is selected.         *\n *   UnitClass::Credit_Load -- Fetch the full credit value of cargo carried.                   *\n *   UnitClass::Crew_Type -- Fetches the kind of crew that this object produces.               *\n *   UnitClass::Debug_Dump -- Displays the status of the unit to the mono monitor.             *\n *   UnitClass::Desired_Load_Dir -- Determines the best cell and facing for loading.           *\n *   UnitClass::Draw_It -- Draws a unit object.                                                *\n *   UnitClass::Edge_Of_World_AI -- Check for falling off the edge of the world.               *\n *   UnitClass::Enter_Idle_Mode -- Unit enters idle mode state.                                *\n *   UnitClass::Fire_Direction -- Determines the direction of firing.                          *\n *   UnitClass::Firing_AI -- Handle firing logic for this unit.                                *\n *   UnitClass::Flag_Attach -- Attaches a house flag to this unit.                             *\n *   UnitClass::Flag_Remove -- Removes the house flag from this unit.                          *\n *   UnitClass::Goto_Clear_Spot -- Finds a clear spot to deploy.                               *\n *   UnitClass::Goto_Tiberium -- Search for and head toward nearest available Tiberium patch.  *\n *   UnitClass::Greatest_Threat -- Fetches the greatest threat for this unit.                  *\n *   UnitClass::Harvesting -- Harvests tiberium at the current location.                       *\n *   UnitClass::Init -- Clears all units for scenario preparation.                             *\n *   UnitClass::Limbo -- Limbo this unit.                                                      *\n *   UnitClass::Mission_Guard -- Special guard mission override processor.                     *\n *   UnitClass::Mission_Guard_Area -- Guard area logic for units.                              *\n *   UnitClass::Mission_Harvest -- Handles the harvesting process used by harvesters.          *\n *   UnitClass::Mission_Hunt -- This is the AI process for aggressive enemy units.             *\n *   UnitClass::Mission_Move -- Handles special move mission overrides.                        *\n *   UnitClass::Mission_Repair -- Handles finding and proceeding on a repair mission.          *\n *   UnitClass::Mission_Unload -- Handles unloading cargo.                                     *\n *   UnitClass::Offload_Tiberium_Bail -- Offloads one Tiberium quantum from the object.        *\n *   UnitClass::Ok_To_Move -- Queries whether the vehicle can move.                            *\n *   UnitClass::Overlap_List -- Determines overlap list for units.                             *\n *   UnitClass::Overrun_Square -- Handles vehicle overrun of a cell.                           *\n *   UnitClass::Per_Cell_Process -- Performs operations necessary on a per cell basis.         *\n *   UnitClass::Pip_Count -- Fetches the number of pips to display on unit.                    *\n *   UnitClass::Random_Animate -- Handles random idle animation for the unit.                  *\n *   UnitClass::Read_INI -- Reads units from scenario INI file.                                *\n *   UnitClass::Receive_Message -- Handles receiving a radio message.                          *\n *   UnitClass::Reload_AI -- Perform reload logic for this unit.                               *\n *   UnitClass::Rotation_AI -- Process any turret or body rotation.                            *\n *   UnitClass::Scatter -- Causes the unit to scatter to a nearby location.                    *\n *   UnitClass::Set_Speed -- Initiate unit movement physics.                                   *\n *   UnitClass::Shape_Number -- Fetch the shape number to use for this unit.                   *\n *   UnitClass::Should_Crush_It -- Determines if this unit should crush an object.             *\n *   UnitClass::Sort_Y -- Give Y coordinate sort value for unit.                               *\n *   UnitClass::Start_Driver -- Starts driving and reserves destination cell.                  *\n *   UnitClass::Take_Damage -- Inflicts damage points on a unit.                               *\n *   UnitClass::Tiberium_Check -- Search for and head toward nearest available Tiberium patch. *\n *   UnitClass::Tiberium_Load -- Determine the Tiberium load as a percentage.                  *\n *   UnitClass::Try_To_Deploy -- The unit attempts to \"deploy\" at current location.            *\n *   UnitClass::UnitClass -- Constructor for units.                                            *\n *   UnitClass::Unlimbo -- Removes unit from stasis.                                           *\n *   UnitClass::What_Action -- Determines action to perform on specified cell.                 *\n *   UnitClass::What_Action -- Determines what action would occur if clicked on object.        *\n *   UnitClass::Write_INI -- Store the units to the INI database.                              *\n *   UnitClass::delete -- Deletion operator for units.                                         *\n *   UnitClass::new -- Allocate a unit slot and adjust access arrays.                          *\n *   UnitClass::~UnitClass -- Destructor for unit objects.                                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * Recoil_Adjust -- Adjust pixel values in direction specified.                                *\n *                                                                                             *\n *    This is a helper routine that modifies the pixel coordinates provided according to the   *\n *    direction specified. The effect is the simulate recoil effects by moving an object 'back'*\n *    one pixel. Since the pixels moved depend on facing, this routine handles the pixel       *\n *    adjustment quickly.                                                                      *\n *                                                                                             *\n * INPUT:   dir   -- The direction to base the recoil on.                                      *\n *                                                                                             *\n *          x,y   -- References to the pixel coordinates that will be adjusted.                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Recoil_Adjust(DirType dir, int &x, int &y)\n{\n\tstatic struct {\n\t\tsigned char X,Y;\n\t} _adjust[32] = {\n\t\t{0,\t1},\t// N\n\t\t{0,\t1},\n\t\t{0,\t1},\n\t\t{-1,\t1},\n\t\t{-1,\t1},\t// NE\n\t\t{-1,\t1},\n\t\t{-1,\t0},\n\t\t{-1,\t0},\n\t\t{-1,\t0},\t// E\n\t\t{-1,\t0},\n\t\t{-1,\t-1},\n\t\t{-1,\t-1},\n\t\t{-1,\t-1},\t// SE\n\t\t{-1,\t-1},\n\t\t{-1,\t-1},\n\t\t{0,\t-1},\n\t\t{0,\t-1},\t// S\n\t\t{0,\t-1},\n\t\t{0,\t-1},\n\t\t{1,\t-1},\n\t\t{1,\t-1},\t// SW\n\t\t{1,\t-1},\n\t\t{1,\t0},\n\t\t{1,\t0},\n\t\t{1,\t0},\t// W\n\t\t{1,\t0},\n\t\t{1,\t1},\n\t\t{1,\t1},\n\t\t{1,\t1},\t// NW\n\t\t{1,\t1},\n\t\t{0,\t1},\n\t\t{0,\t1}\n\t};\n\n\tint index = Dir_To_32(dir);\n\tx += _adjust[index].X;\n\ty += _adjust[index].Y;\n}\n\n\n/***********************************************************************************************\n * UnitClass::new -- Allocate a unit slot and adjust access arrays.                            *\n *                                                                                             *\n *    This routine will allocate a unit from the available unit pool and                       *\n *    fixup all the access lists to match. It will allocate a unit slot                        *\n *    from within the range allowed for the specified unit type. If no                         *\n *    slot was found, then it will fail.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocated unit.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/11/1994 JLB : Created.                                                                 *\n *   04/21/1994 JLB : Converted to operator new.                                               *\n *=============================================================================================*/\nvoid * UnitClass::operator new(size_t)\n{\n\tvoid * ptr = Units.Alloc();\n\tif (ptr != NULL) {\n\t\t((UnitClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * UnitClass::delete -- Deletion operator for units.                                           *\n *                                                                                             *\n *    This removes the unit from the local allocation system. Since this                       *\n *    is a fixed block of memory, not much has to be done to delete the                        *\n *    unit. Merely marking it as inactive is enough.                                           *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the unit to delete.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/21/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitClass::operator delete(void * ptr)\n{\n\tif (ptr != NULL) {\n\t\t((UnitClass *)ptr)->IsActive = false;\n\t}\n\tUnits.Free((UnitClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * UnitClass::~UnitClass -- Destructor for unit objects.                                       *\n *                                                                                             *\n *    This destructor will lower the unit count for the owning house as well as inform any     *\n *    other units in communication, that this unit is about to leave reality.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nUnitClass::~UnitClass(void)\n{\n\tif (GameActive && Class.Is_Valid()) {\n\n\t\t/*\n\t\t**\tRemove this member from any team it may be associated with. This must occur at the\n\t\t**\ttop most level of the inheritance hierarchy because it may call virtual functions.\n\t\t*/\n\t\tif (Team.Is_Valid()) {\n\t\t\tTeam->Remove(this);\n\t\t\tTeam = NULL;\n\t\t}\n\n\t\tHouse->Tracking_Remove(this);\n\n\t\t/*\n\t\t**\tIf there are any cargo members, delete them.\n\t\t*/\n\t\twhile (Is_Something_Attached()) {\n\t\t\tdelete Detach_Object();\n\t\t}\n\n\t\tLimbo();\n\t}\n\tID = -1;\n}\n\n\n/***********************************************************************************************\n * UnitClass::UnitClass -- Constructor for units.                                              *\n *                                                                                             *\n *    This constructor for units will initialize the unit into the game                        *\n *    system. It will be placed in all necessary tracking lists. The initial condition will    *\n *    be in a state of limbo.                                                                  *\n *                                                                                             *\n * INPUT:   classid  -- The type of unit to create.                                            *\n *                                                                                             *\n *          house -- The house owner of this unit.                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/21/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nUnitClass::UnitClass(UnitType classid, HousesType house) :\n\tDriveClass(RTTI_UNIT, Units.ID(this), house),\n\tClass(UnitTypes.Ptr((int)classid)),\n\tFlagged(HOUSE_NONE),\n\tIsDumping(false),\n\tGems(0),\n\tGold(0),\n\tTiberium(0),\n\tIsToScatter(false),\n\tShroudBits(0xFFFFFFFFUL),\n\tShroudCenter(0),\n\tReload(0),\n\tSecondaryFacing(PrimaryFacing)\n{\n\tReload = 0;\n\tHouse->Tracking_Add(this);\n\tAmmo = Class->MaxAmmo;\n\tIsCloakable = Class->IsCloakable;\n\tif (Class->IsAnimating) Set_Rate(Options.Normalize_Delay(3));\n\n\t/*\n\t**\tFor two shooters, clear out the second shot flag -- it will be set the first time\n\t**\tthe object fires. For non two shooters, set the flag since it will never be cleared\n\t**\tand the second shot flag tells the system that normal rearm times apply -- this is\n\t**\twhat is desired for non two shooters.\n\t*/\n\tIsSecondShot = !Class->Is_Two_Shooter();\n\tStrength = Class->MaxStrength;\n\n\t/*\n\t** Keep count of the number of units created.\n\t*/\n//\tif (Session.Type == GAME_INTERNET) {\n//\t\tHouse->UnitTotals->Increment_Unit_Total((int)classid);\n//\t}\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * UnitClass::Debug_Dump -- Displays the status of the unit to the mono monitor.               *\n *                                                                                             *\n *    This displays the current status of the unit class to the mono monitor. By this display  *\n *    bugs may be tracked down or prevented.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tmono->Set_Cursor(0, 0);\n\tmono->Print(Text_String(TXT_DEBUG_VEHICLE));\n\tmono->Set_Cursor(47, 5);mono->Printf(\"%02X:%02X\", SecondaryFacing.Current(), SecondaryFacing.Desired());\n\n\tmono->Set_Cursor(1, 11);mono->Printf(\"%03\", Gems);\n\tmono->Set_Cursor(7, 11);mono->Printf(\"%03\", Gold);\n\n\tmono->Fill_Attrib(66, 13, 12, 1, IsDumping ? MonoClass::INVERSE : MonoClass::NORMAL);\n\n\tDriveClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * UnitClass::Sort_Y -- Give Y coordinate sort value for unit.                                 *\n *                                                                                             *\n *    This routine is used by the rendering system in order to sort the                        *\n *    game objects in a back to front order. This is now the correct                           *\n *    overlap effect is achieved.                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a coordinate value that can be used for sorting.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE UnitClass::Sort_Y(void) const\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(Coord_Add(Coord, 0x00800000L));\n}\n\n\n/***********************************************************************************************\n * UnitClass::AI -- AI processing for the unit.                                                *\n *                                                                                             *\n *    This routine will perform the AI processing necessary for the unit. These are non-       *\n *    graphic related operations.                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitClass::AI(void)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\t/*\n\t**\tAct on new orders if the unit is at a good position to do so.\n\t*/\n\tif (Height == 0 && !IsDumping && !IsDriving && Is_Door_Closed() /*&& Mission != MISSION_UNLOAD*/) {\n//\t\tif (MissionQueue == MISSION_NONE) Enter_Idle_Mode();\n\t\tCommence();\n\t}\n\tDriveClass::AI();\n\tif (!IsActive || Height > 0) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tHack check to ensure that a harvester won't harvest if it is not harvesting.\n\t*/\n\tif (Mission != MISSION_HARVEST) {\n\t\tIsHarvesting = false;\n\t}\n\n\t/*\n\t**\tHandle combat logic for this unit. It will determine if it has a target and\n\t**\tif so, if conditions are favorable for firing. When conditions permit, the\n\t**\tunit will fire upon its target.\n\t*/\n\tFiring_AI();\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (!IsActive) {\n\t\treturn;\n\t}\n#endif\n\t/*\n\t**\tTurret rotation processing. Handles rotating radar dish\n\t**\tas well as conventional turrets if present. If no turret present, but\n\t**\tit decides that the body should face its target, then body rotation\n\t**\twould occur by this process as well.\n\t*/\n\tRotation_AI();\n\n\t/*\n\t**\tDelete this unit if it finds itself off the edge of the map and it is in\n\t**\tguard or other static mission mode.\n\t*/\n\tif (Edge_Of_World_AI()) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tUnits will reload every so often if they are under the burden of\n\t**\tbeing required to reload between shots.\n\t*/\n\tReload_AI();\n\n\t/*\n\t**\tTransporters require special logic handled here since there isn't a MISSION_WAIT_FOR_PASSENGERS\n\t**\tmission that they can follow. Passenger loading is merely a part of their normal operation.\n\t*/\n\tif (Class->Max_Passengers() > 0) {\n\n\t\t/*\n\t\t**\tDouble check that there is a passenger that is trying to load or unload.\n\t\t**\tIf not, then close the door.\n\t\t*/\n\t\tif (!Is_Door_Closed() && Mission != MISSION_UNLOAD && Transmit_Message(RADIO_TRYING_TO_LOAD) != RADIO_ROGER) {\n\t\t\tAPC_Close_Door();\n\t\t}\n\t}\n\n\t/*\n\t**\tDon't start a new mission unless the vehicle is in the center of\n\t**\ta cell (not driving) and the door (if any) is closed.\n\t*/\n\tif (!IsDumping && !IsDriving && Is_Door_Closed()/*&& Mission != MISSION_UNLOAD*/) {\n\t\tCommence();\n\t}\n\n\t/*\n\t**\tA cloaked object that is carrying the flag will always shimmer.\n\t*/\n\tif (Cloak == CLOAKED && Flagged != HOUSE_NONE) {\n\t\tDo_Shimmer();\n\t}\n\n\t/*\n\t**\tMobile gap generators regenerate their gap every so often (just in case).\n\t*/\n\tif (Class->IsGapper && !IsDriving && (Frame % TICKS_PER_SECOND) == 0) {\n\t\tShroud_Regen();\n\t}\n}\n\n\n/***********************************************************************************************\n * UnitClass::Rotation_AI -- Process any turret or body rotation.                              *\n *                                                                                             *\n *    This routine will handle the rotation logic for the unit's turret (if it has one) as     *\n *    well as its normal body shape.                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitClass::Rotation_AI(void)\n{\n\tif (Target_Legal(TarCom) && !IsRotating) {\n\t\tDirType dir = Direction(TarCom);\n\n\t\tif (Class->IsTurretEquipped) {\n\t\t\tSecondaryFacing.Set_Desired(dir);\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tNon turret equipped vehicles will rotate their body to face the target only\n\t\t\t**\tif the vehicle isn't currently moving or facing the correct direction. This\n\t\t\t**\tapplies only to tracked vehicles. Wheeled vehicles never rotate to face the\n\t\t\t**\ttarget, since they aren't maneuverable enough.\n\t\t\t*/\n\t\t\tif ((Class->Speed == SPEED_TRACK /* || *this == UNIT_BIKE */ ) && !Target_Legal(NavCom) && !IsDriving && PrimaryFacing.Difference(dir)) {\n\t\t\t\tPrimaryFacing.Set_Desired(dir);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (Class->IsRadarEquipped) {\n\t\tMark(MARK_CHANGE_REDRAW);\n\t\tSecondaryFacing.Set((DirType)(SecondaryFacing.Current() + 8));\n\t\tMark(MARK_CHANGE_REDRAW);\n\t} else {\n\n\t\tIsRotating = false;\n\t\tif (Class->IsTurretEquipped) {\n\t\t\tif (IsTurretLockedDown) {\n\t\t\t\tSecondaryFacing.Set_Desired(PrimaryFacing.Current());\n\t\t\t}\n\n\t\t\tif (SecondaryFacing.Is_Rotating()) {\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t\tif (SecondaryFacing.Rotation_Adjust(Class->ROT+1)) {\n\t\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf no further rotation is necessary, flag that the rotation\n\t\t\t\t**\thas stopped.\n\t\t\t\t*/\n\t\t\t\tif (!Class->IsRadarEquipped) {\n\t\t\t\t\tIsRotating = SecondaryFacing.Is_Rotating();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!IsTurretLockedDown && !Target_Legal(TarCom)) {\n\t\t\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\t\t\tSecondaryFacing.Set_Desired(PrimaryFacing.Current());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSecondaryFacing.Set_Desired(Direction(NavCom));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * UnitClass::Edge_Of_World_AI -- Check for falling off the edge of the world.                 *\n *                                                                                             *\n *    When a unit leaves the map it will be eliminated. This routine checks for this case      *\n *    and eliminates the unit accordingly.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the unit eliminated by this routine?                                     *\n *                                                                                             *\n * WARNINGS:   Be sure to check for the return value and if 'true' abort any further processing*\n *             of the unit since it is dead. Only call this routine once per unit per          *\n *             game logic loop.                                                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool UnitClass::Edge_Of_World_AI(void)\n{\n\tif (Mission == MISSION_GUARD && !Map.In_Radar(Coord_Cell(Coord)) && IsLocked) {\n\t\tif (Team.Is_Valid()) Team->IsLeaveMap = true;\n\t\tStun();\n\t\tdelete this;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Reload_AI -- Perform reload logic for this unit.                                 *\n *                                                                                             *\n *    Some units require special reload logic. The V2 rocket launcher in particular. Perform   *\n *    this reload logic with this routine.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per unit per game logic loop.                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitClass::Reload_AI(void)\n{\n\tif (*this == UNIT_V2_LAUNCHER && Ammo < Class->MaxAmmo) {\n\t\tif (IsDriving) {\n\t\t\tReload = Reload + 1;\n\t\t} else {\n\t\t\tif (Reload == 0) {\n\t\t\t\tAmmo++;\n\t\t\t\tif (Ammo < Class->MaxAmmo) {\n\t\t\t\t\tReload = TICKS_PER_SECOND*30;\n\t\t\t\t}\n\t\t\t\tMark(MARK_CHANGE);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * UnitClass::Firing_AI -- Handle firing logic for this unit.                                  *\n *                                                                                             *\n *    This routine wil check for and perform any firing logic required of this unit.           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This should be called only once per unit per game logic loop.                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitClass::Firing_AI(void)\n{\n\tif (Target_Legal(TarCom) && Class->PrimaryWeapon != NULL) {\n\n\t\t/*\n\t\t**\tDetermine which weapon can fire. First check for the primary weapon. If that weapon\n\t\t**\tcannot fire, then check any secondary weapon. If neither weapon can fire, then the\n\t\t**\tfailure code returned is that from the primary weapon.\n\t\t*/\n\t\tint primary = What_Weapon_Should_I_Use(TarCom);\n\t\tFireErrorType ok = Can_Fire(TarCom, primary);\n\t\tswitch (ok) {\n\t\t\tcase FIRE_OK:\n\t\t\t\tif (!((UnitClass *)this)->Class->IsFireAnim) {\n\t\t\t\t\tMark(MARK_OVERLAP_UP);\n\t\t\t\t\tIsFiring = false;\n\t\t\t\t\tMark(MARK_OVERLAP_DOWN);\n\t\t\t\t}\n\n\t\t\t\tFire_At(TarCom, primary);\n\t\t\t\tbreak;\n\n\t\t\tcase FIRE_FACING:\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif (Class->IsLockTurret || Class->Type == UNIT_DEMOTRUCK) {\n#else\n\t\t\t\tif (Class->IsLockTurret) {\n#endif\n\t\t\t\t\tif (!Target_Legal(NavCom) && !IsDriving) {\n\t\t\t\t\t\tPrimaryFacing.Set_Desired(Direction(TarCom));\n\t\t\t\t\t\tSecondaryFacing.Set_Desired(PrimaryFacing.Desired());\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tSecondaryFacing.Set_Desired(Direction(TarCom));\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase FIRE_CLOAKED:\n\t\t\t\tMark(MARK_OVERLAP_UP);\n\t\t\t\tIsFiring = false;\n\t\t\t\tMark(MARK_OVERLAP_DOWN);\n\t\t\t\tDo_Uncloak();\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * UnitClass::Receive_Message -- Handles receiving a radio message.                            *\n *                                                                                             *\n *    This is the handler function for when a unit receives a radio                            *\n *    message. Typical use of this is when a unit unloads from a hover                         *\n *    class so that clearing of the transport is successful.                                   *\n *                                                                                             *\n * INPUT:   from     -- Pointer to the originator of the message.                              *\n *                                                                                             *\n *          message  -- The radio message received.                                            *\n *                                                                                             *\n *          param    -- Reference to an optional parameter the might be needed to return       *\n *                      information back to the originator of the message.                     *\n *                                                                                             *\n * OUTPUT:  Returns with the radio message response.                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nRadioMessageType UnitClass::Receive_Message(RadioClass * from, RadioMessageType message, long & param)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tswitch (message) {\n\t\t/*\n\t\t**\tChecks to see if this object is in need of service depot processing.\n\t\t*/\n\t\tcase RADIO_NEED_REPAIR:\n\t\t\tif (!IsDriving && !Target_Legal(NavCom) && (Health_Ratio() >= 1 && (*this != UNIT_MINELAYER || Ammo >= Class->MaxAmmo))) return(RADIO_NEGATIVE);\n\t\t\tbreak;\n//\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t**\tAsks if the passenger can load on this transport.\n\t\t*/\n\t\tcase RADIO_CAN_LOAD:\n\t\t\tif (Class->Max_Passengers() == 0 || from == NULL || !House->Is_Ally(from->Owner())) return(RADIO_STATIC);\n\t\t\tif (How_Many() < Class->Max_Passengers()) {\n\t\t\t\treturn(RADIO_ROGER);\n\t\t\t}\n\t\t\treturn(RADIO_NEGATIVE);\n\n\t\t/*\n\t\t**\tThe refinery has told this harvester that it should begin the backup procedure\n\t\t**\tso that proper unloading may take place.\n\t\t*/\n\t\tcase RADIO_BACKUP_NOW:\n\t\t\tDriveClass::Receive_Message(from, message, param);\n\t\t\tif (!IsRotating && PrimaryFacing != DIR_W) {\n\t\t\t\tDo_Turn(DIR_W);\n\t\t\t} else {\n\t\t\t\tif (!IsDriving) {\n\t\t\t\t\tTechnoClass\t* whom = Contact_With_Whom();\n\t\t\t\t\tif (IsTethered && whom != NULL) {\n\t\t\t\t\t\tif (whom->What_Am_I() == RTTI_BUILDING && Mission == MISSION_ENTER) {\n\t\t\t\t\t\t\tif (Transmit_Message(RADIO_IM_IN, whom) == RADIO_ROGER) {\n\t\t\t\t\t\t\t\tTransmit_Message(RADIO_UNLOADED, whom);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t**\tThis message is sent by the passenger when it determines that it has\n\t\t**\tentered the transport.\n\t\t*/\n\t\tcase RADIO_IM_IN:\n\t\t\tif (How_Many() == Class->Max_Passengers()) {\n\t\t\t\tAPC_Close_Door();\n\t\t\t}\n\t\t\treturn(RADIO_ATTACH);\n\n\t\t/*\n\t\t**\tDocking maintenance message received. Check to see if new orders should be given\n\t\t**\tto the impatient unit.\n\t\t*/\n\t\tcase RADIO_DOCKING:\n\n\t\t\t/*\n\t\t\t**\tIf this transport is moving, then always abort the docking request.\n\t\t\t*/\n\t\t\tif (IsDriving || Target_Legal(NavCom)) {\n\t\t\t\treturn(RADIO_NEGATIVE);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCheck for the case of a docking message arriving from a unit that does not\n\t\t\t**\thave formal radio contact established. This might be a unit that is standing\n\t\t\t**\tby. If this transport is free to proceed with normal docking operation, then\n\t\t\t**\testablish formal contact now. If the transport is completely full, then break\n\t\t\t**\toff contact. In all other cases, just tell the pending unit to stand by.\n\t\t\t*/\n\t\t\tif (Contact_With_Whom() != from) {\n\n\t\t\t\t/*\n\t\t\t\t**\tCan't ever load up so tell the passenger to bug off.\n\t\t\t\t*/\n\t\t\t\tif (How_Many() >= Class->Max_Passengers()) {\n\t\t\t\t\treturn(RADIO_NEGATIVE);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tEstablish contact and let the loading process proceed normally.\n\t\t\t\t*/\n\t\t\t\tif (!In_Radio_Contact()) {\n\t\t\t\t\tTransmit_Message(RADIO_HELLO, from);\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThis causes the potential passenger to think that all is ok and to\n\t\t\t\t\t**\thold on for a bit.\n\t\t\t\t\t*/\n\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (Class->Max_Passengers() > 0 && How_Many() < Class->Max_Passengers()) {\n\t\t\t\tDriveClass::Receive_Message(from, message, param);\n\n\t\t\t\tif (!IsDriving && !IsRotating && !IsTethered) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the potential passenger needs someplace to go, then figure out a good\n\t\t\t\t\t**\tspot and tell it to go.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Transmit_Message(RADIO_NEED_TO_MOVE, from) == RADIO_ROGER) {\n\n\t\t\t\t\t\tCELL cell;\n\t\t\t\t\t\tDirType dir = Desired_Load_Dir(from, cell);\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf no adjacent free cells are detected, then passenger loading\n\t\t\t\t\t\t**\tcannot occur. Break radio contact.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (cell == 0) {\n\t\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT, from);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tparam = (long)::As_Target(cell);\n\t\t\t\t\t\t\tDo_Turn(dir);\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf it is now facing the correct direction, then open the\n\t\t\t\t\t\t\t**\ttransport doors. Close the doors if the transport is or needs\n\t\t\t\t\t\t\t**\tto rotate.\n\t\t\t\t\t\t\t*/\n#ifdef FIXIT_PHASETRANSPORT\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\t\tif (*this == UNIT_APC || *this == UNIT_PHASE) {\n#else\n\t\t\t\t\t\t\tif (*this == UNIT_APC) {\n#endif\n\t\t\t\t\t\t\t\tif (IsRotating) {\n\t\t\t\t\t\t\t\t\tif (!Is_Door_Closed()) {\n\t\t\t\t\t\t\t\t\t\tAPC_Close_Door();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tif (!Is_Door_Open()) {\n\t\t\t\t\t\t\t\t\t\tAPC_Open_Door();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tTell the potential passenger where it should go. If the passenger is\n\t\t\t\t\t\t\t**\talready at the staging location, then tell it to move onto the transport\n\t\t\t\t\t\t\t**\tdirectly.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Transmit_Message(RADIO_MOVE_HERE, param, from) == RADIO_YEA_NOW_WHAT) {\n#ifdef FIXIT_PHASETRANSPORT\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\t\t\tif ( (*this != UNIT_APC && *this != UNIT_PHASE) || Is_Door_Open()) {\n#else\n\t\t\t\t\t\t\t\tif (*this != UNIT_APC || Is_Door_Open()) {\n#endif\n\t\t\t\t\t\t\t\t\tparam = (long)As_Target();\n\t\t\t\t\t\t\t\t\tTransmit_Message(RADIO_TETHER);\n\t\t\t\t\t\t\t\t\tif (Transmit_Message(RADIO_MOVE_HERE, param, from) != RADIO_ROGER) {\n\t\t\t\t\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT, from);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tContact_With_Whom()->Unselect();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(RADIO_ROGER);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tWhen this message is received, it means that the other object\n\t\t**\thas already turned its radio off. Turn this radio off as well.\n\t\t*/\n\t\tcase RADIO_OVER_OUT:\n\t\t\tif (Mission == MISSION_RETURN) {\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t}\n\t\t\tDriveClass::Receive_Message(from, message, param);\n\t\t\treturn(RADIO_ROGER);\n\n\t}\n\treturn(DriveClass::Receive_Message(from, message, param));\n}\n\n\n/***********************************************************************************************\n * UnitClass::Unlimbo -- Removes unit from stasis.                                             *\n *                                                                                             *\n *    This routine will place a unit into the game and out of its limbo                        *\n *    state. This occurs whenever a unit is unloaded from a transport.                         *\n *                                                                                             *\n * INPUT:   coord    -- The coordinate to make the unit appear.                                *\n *                                                                                             *\n *          dir      -- The initial facing to impart upon the unit.                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the unit unlimboed successfully?  If the desired                         *\n *                coordinate is illegal, then this might very well return                      *\n *                false.                                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool UnitClass::Unlimbo(COORDINATE coord, DirType dir)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tAll units must start out facing one of the 8 major directions.\n\t*/\n\tdir = Facing_Dir(Dir_Facing(dir));\n\tif (DriveClass::Unlimbo(coord, dir)) {\n\n\t\tSecondaryFacing = dir;\n\t\t/*\n\t\t**\tEnsure that the owning house knows about the\n\t\t**\tnew object.\n\t\t*/\n\t\tHouse->UScan |= (1L << Class->Type);\n\t\tHouse->ActiveUScan |= (1L << Class->Type);\n\n\t\t/*\n\t\t**\tIf it starts off the edge of the map, then it already starts cloaked.\n\t\t*/\n\t\tif (IsCloakable && !IsLocked) Cloak = CLOAKED;\n\n\t\t/*\n\t\t**\tUnits default to no special animation.\n\t\t*/\n\t\tSet_Rate(0);\n\t\tSet_Stage(0);\n\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Take_Damage -- Inflicts damage points on a unit.                                 *\n *                                                                                             *\n *    This routine will inflict the specified number of damage points on                       *\n *    the given unit. If the unit is destroyed, then this routine will                         *\n *    remove the unit cleanly from the game. The return value indicates                        *\n *    whether the unit was destroyed. This will allow appropriate death                        *\n *    animation or whatever.                                                                   *\n *                                                                                             *\n * INPUT:   damage-- The number of damage points to inflict.                                   *\n *                                                                                             *\n *          distance -- The distance from the damage center point to the object's center point.*\n *                                                                                             *\n *          warhead--The type of damage to inflict.                                            *\n *                                                                                             *\n *          source   -- Who is responsible for this damage?                                    *\n *                                                                                             *\n * OUTPUT:  Returns the result of the damage process. This can range from RESULT_NONE up to    *\n *          RESULT_DESTROYED.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/30/1991 JLB : Created.                                                                 *\n *   07/12/1991 JLB : Script initiated by unit destruction.                                    *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *   04/16/1994 JLB : Warhead modifier.                                                        *\n *   06/03/1994 JLB : Added the source of the damage target value.                             *\n *   06/20/1994 JLB : Source is a base class pointer.                                          *\n *   11/22/1994 JLB : Shares base damage handler for techno objects.                           *\n *   06/30/1995 JLB : Lasers do maximum damage against gunboat.                                *\n *   08/16/1995 JLB : Harvester crushing doesn't occur on early missions.                      *\n *=============================================================================================*/\nResultType UnitClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, int forced)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tResultType res = RESULT_NONE;\n\n\t/*\n\t**\tRemember if this object was selected. If it was and it gets destroyed and it has\n\t**\tpassengers that pop out, then the passengers will inherit the select state.\n\t*/\n\tbool select = (IsSelected && House->IsPlayerControl);\n\n\t/*\n\t**\tIn order for a this to be damaged, it must either be a unit\n\t**\twith a crew or a sandworm.\n\t*/\n\tres = DriveClass::Take_Damage(damage, distance, warhead, source, forced);\n\n\tif (res == RESULT_DESTROYED) {\n\t\tDeath_Announcement(source);\n\t\tShroud_Regen();\t// remove the shroud if it's a gap generator\n\t\tif (Class->Explosion != ANIM_NONE) {\n\t\t\tAnimType anim = Class->Explosion;\n\n\t\t\t/*\n\t\t\t**\tSSM launchers will really explode big if they are carrying\n\t\t\t**\tmissiles at the time of the explosion.\n\t\t\t*/\n\t\t\tif (*this == UNIT_V2_LAUNCHER && Ammo) {\n\t\t\t\tanim = ANIM_NAPALM3;\n\t\t\t}\n\n\t\t\tnew AnimClass(anim, Coord);\n\n\t\t\t/*\n\t\t\t**\tHarvesters explode with a force equal to the amount of\n\t\t\t**\tTiberium they are carrying.\n\t\t\t*/\n\t\t\tif (Tiberium > 0 && Rule.IsExplosiveHarvester) {\n\t\t\t\tWide_Area_Damage(Coord, CELL_LEPTON_W + CELL_LEPTON_W/2, Credit_Load()+Class->MaxStrength, this, WARHEAD_HE);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tVery strong units that have an explosion will also rock the\n\t\t\t**\tscreen when they are destroyed.\n\t\t\t*/\n\t\t\tif (Class->MaxStrength > 400) {\n\t\t\t\tShake_The_Screen(3);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tPossibly have the crew member run away.\n\t\t*/\n\t\tCELL cell = Coord_Cell(Center_Coord());\n\t\tMark(MARK_UP);\n\n\t\tif (Class->IsCrew && Class->Max_Passengers() == 0) {\n\t\t\tif (Percent_Chance(50)) {\n\t\t\t\tInfantryClass * i = 0;\n\n\t\t\t\tif (Class->PrimaryWeapon == NULL) {\n\t\t\t\t\ti = new InfantryClass(INFANTRY_C1, House->Class->House);\n\t\t\t\t\tif (i != NULL) i->IsTechnician = true;\n\t\t\t\t} else {\n\t\t\t\t\ti = new InfantryClass(INFANTRY_E1, House->Class->House);\n\t\t\t\t}\n\t\t\t\tif (i != NULL) {\n\t\t\t\t\tif (i->Unlimbo(Coord, DIR_N)) {\n\t\t\t\t\t\ti->Strength = Random_Pick(5, (int)i->Class->MaxStrength/2);\n\t\t\t\t\t\ti->Scatter(0, true);\n\t\t\t\t\t\tif (!House->IsHuman) {\n\t\t\t\t\t\t\ti->Assign_Mission(MISSION_HUNT);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ti->Assign_Mission(MISSION_GUARD);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (select) i->Select();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdelete i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\twhile (Is_Something_Attached()) {\n\t\t\t\tFootClass * object = Detach_Object();\n\n\t\t\t\tif (object == NULL) break;\t\t// How can this happen?\n\n\t\t\t\t/*\n\t\t\t\t**\tOnly infantry can run from a destroyed vehicle. Even then, it is not a sure\n\t\t\t\t**\tthing.\n\t\t\t\t*/\n\t\t\t\tif (object->Is_Infantry() && object->Unlimbo(Coord, DIR_N)) {\n\t\t\t\t\tobject->Scatter(0, true);\n\t\t\t\t\tif (select) object->Select();\n\t\t\t\t} else {\n\t\t\t\t\tobject->Record_The_Kill(source);\n\t\t\t\t\tdelete object;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf this is a truck, there is a possibility that a crate will drop out\n\t\t**\tif the scenario so indicates and there is room.\n\t\t*/\n\t\tif (Scen.IsTruckCrate && *this == UNIT_TRUCK) {\n\t\t\tcell = Nearby_Location();\n\t\t\tif (cell != 0) {\n\t\t\t\tnew OverlayClass(OVERLAY_WOOD_CRATE, cell);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tFinally, delete the vehicle.\n\t\t*/\n\t\tdelete this;\n\n\t} else {\n\n\t\t/*\n\t\t**\tWhen damaged and below half strength, start smoking if\n\t\t**\tit isn't already smoking.\n\t\t*/\n\t\tif (Health_Ratio() <= Rule.ConditionYellow && !IsAnimAttached) {\n#ifdef FIXIT_ANTS\n\t\t\tif (*this != UNIT_ANT1 && *this != UNIT_ANT2 && *this != UNIT_ANT3)  {\n#endif\n\t\t\t\tAnimClass * anim = new AnimClass(ANIM_SMOKE_M, Coord_Add(Coord, XYP_Coord(0, -8)));\n\t\t\t\tif (anim) anim->Attach_To(this);\n#ifdef FIXIT_ANTS\n\t\t\t}\n#endif\n\t\t   }\n\n\t\t/*\n\t\t**\tTry to crush anyone that fires on this unit if possible. The harvester\n\t\t**\ttypically is the only one that will qualify here.\n\t\t*/\n\t\tif (!Team.Is_Valid() && source != NULL && !IsTethered && !House->Is_Ally(source) && (!House->IsHuman || Rule.IsAutoCrush)) {\n\n\t\t\t/*\n\t\t\t**\tTry to crush the attacker if it can be crushed by this unit and this unit is\n\t\t\t**\tnot equipped with a flame type weapon. If this unit has a weapon and the target\n\t\t\t**\tis not very close, then fire on it instead. In easy mode, they never run over the\n\t\t\t**\tplayer. In hard mode, they always do. In normal mode, they only overrun past\n\t\t\t**\tmission #8.\n\t\t\t*/\n\t\t\tif (Should_Crush_It(source)) {\n\t\t\t\tAssign_Destination(source->As_Target());\n\t\t\t\tAssign_Mission(MISSION_MOVE);\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tTry to return to base if possible.\n\t\t\t\t*/\n\t\t\t\tif (*this == UNIT_HARVESTER && Pip_Count() && Health_Ratio() <= Rule.ConditionYellow) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tFind nearby refinery and head to it?\n\t\t\t\t\t*/\n\t\t\t\t\tBuildingClass * building = Find_Docking_Bay(STRUCT_REFINERY, false);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSince the refinery said it was ok to load, establish radio\n\t\t\t\t\t**\tcontact with the refinery and then await docking orders.\n\t\t\t\t\t*/\n\t\t\t\t\tif (building != NULL && Transmit_Message(RADIO_HELLO, building) == RADIO_ROGER) {\n\t\t\t\t\t\tAssign_Mission(MISSION_ENTER);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tComputer controlled harvester will radio for help if they are attacked.\n\t\t*/\n\t\tif (*this == UNIT_HARVESTER && !House->IsHuman && source) {\n\t\t\tBase_Is_Attacked(source);\n\t\t}\n\t}\n\treturn(res);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Active_Click_With -- Intercepts the active click to see if deployment is possible*\n *                                                                                             *\n *    This routine intercepts the active click operation. It check to see if this is a self    *\n *    deployment request (MCV's have this ability). If it is, then the object is initiated     *\n *    to self deploy. In the other cases, it passes the operation down to the lower            *\n *    classes for processing.                                                                  *\n *                                                                                             *\n * INPUT:   action   -- The action requested of the unit.                                      *\n *                                                                                             *\n *          object   -- The object that the mouse pointer is over.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitClass::Active_Click_With(ActionType action, ObjectClass * object)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (action != What_Action(object)) {\n\t\taction = What_Action(object);\n\t\tswitch (action) {\n\t\t\tcase ACTION_SABOTAGE:\n\t\t\tcase ACTION_CAPTURE:\n\t\t\t\taction = ACTION_ATTACK;\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_ENTER:\n\t\t\t\taction = ACTION_MOVE;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tShort circuit out if trying to tell a unit to \"nomove\" to itself. This bypass of the\n\t**\tnormal active click with logic prevents any disturbance to the vehicle's state. Without\n\t**\tthis bypass, a unit on a repair bay would stop repairing because it would break radio\n\t**\tcontact.\n\t*/\n\tif (object == this && action == ACTION_NOMOVE) {\n\t\treturn;\n\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (*this == UNIT_MAD && (IsDumping || Gold)) {\n\t} else {\n\t\tDriveClass::Active_Click_With(action, object);\n\t}\n#else\n\tDriveClass::Active_Click_With(action, object);\n#endif\n}\n\n\n/***********************************************************************************************\n * UnitClass::Active_Click_With -- Performs specified action on specified cell.                *\n *                                                                                             *\n *    This routine is called when the mouse has been clicked over a cell and this unit must    *\n *    now respond. Notice that this is merely a placeholder function that exists because there *\n *    is another function of the same name that needs to be overloaded. C++ has scoping        *\n *    restrictions when there are two identically named functions that are overridden in       *\n *    different classes -- it handles it badly, hence the existence of this routine.           *\n *                                                                                             *\n * INPUT:   action   -- The action to perform on the cell specified.                           *\n *                                                                                             *\n *          cell     -- The cell that the action is to be performed on.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitClass::Active_Click_With(ActionType action, CELL cell)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (*this == UNIT_MAD && (IsDumping || Gold)) {\n\t} else {\n\t\tDriveClass::Active_Click_With(action, cell);\n\t}\n#else\n\tDriveClass::Active_Click_With(action, cell);\n#endif\n}\n\n\n/***********************************************************************************************\n * UnitClass::Enter_Idle_Mode -- Unit enters idle mode state.                                  *\n *                                                                                             *\n *    This routine is called when the unit completes one mission but does not have a clear     *\n *    follow up mission to perform. In such a case, the unit should enter a default idle       *\n *    state. This idle state varies depending on what the current internal computer            *\n *    settings of the unit is as well as what kind of unit it is.                              *\n *                                                                                             *\n * INPUT:   initial  -- Is this called when the unit just leaves a factory or is initially     *\n *                      or is initially placed on the map?                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   06/03/1994 JLB : Fixed to handle non-combat vehicles.                                     *\n *   06/18/1995 JLB : Allows a harvester to stop harvesting.                                   *\n *=============================================================================================*/\nvoid UnitClass::Enter_Idle_Mode(bool initial)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tMissionType\torder = MISSION_GUARD;\n\n\tif (IsToScatter) {\n\t\tIsToScatter = false;\n\t\tScatter(0, true);\n\t}\n\n\t/*\n\t**\tA movement mission without a NavCom would be pointless to have a radio contact since\n\t**\tno radio coordination occurs on a just a simple movement mission.\n\t*/\n\tif (Mission == MISSION_MOVE && !Target_Legal(NavCom)) {\n\t\tTransmit_Message(RADIO_OVER_OUT);\n\t}\n\n\tHandle_Navigation_List();\n\tif (Target_Legal(NavCom)) {\n\t\torder = MISSION_MOVE;\n\t} else {\n\n\t\tif (!Is_Weapon_Equipped()) {\n\t\t\tif (Class->IsToHarvest) {\n\t\t\t\tif (!In_Radio_Contact() && Mission != MISSION_HARVEST && MissionQueue != MISSION_HARVEST) {\n\t\t\t\t\tif (initial || !House->IsHuman || Map[Coord].Land_Type() == LAND_TIBERIUM) {\n\t\t\t\t\t\torder = MISSION_HARVEST;\n\t\t\t\t\t} else {\n\t\t\t\t\t\torder = MISSION_GUARD;\n\t\t\t\t\t}\n\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t} else {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (IsALoaner && Class->Max_Passengers() > 0 && Is_Something_Attached() && !Team.Is_Valid()) {\n\t\t\t\t\torder = MISSION_UNLOAD;\n\t\t\t\t} else {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif(*this == UNIT_MAD && Mission == MISSION_UNLOAD) {\n\t\torder = MISSION_UNLOAD;\n\t} else {\n#endif\n\t\t\t\t\torder = MISSION_GUARD;\n\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t}\n\t\t\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t}\n#endif\n\t\t} else {\n\n\t\t\tif (Mission == MISSION_GUARD || Mission == MISSION_GUARD_AREA || MissionControl[Mission].IsParalyzed || MissionControl[Mission].IsZombie) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (House->IQ < Rule.IQGuardArea || Team.Is_Valid()) {\n\t\t\t\torder = MISSION_GUARD;\n\t\t\t} else {\n\t\t\t\torder = MISSION_GUARD_AREA;\n\t\t\t}\n\t\t}\n\t}\n\tAssign_Mission(order);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Goto_Clear_Spot -- Finds a clear spot to deploy.                                 *\n *                                                                                             *\n *    This routine is used by the MCV to find a clear spot to deploy. If a clear spot          *\n *    is found, then the MCV will assign that location to its navigation computer. This only   *\n *    occurs if the MCV isn't already heading toward a spot.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool;  Is the located at a spot where it can deploy?                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool UnitClass::Goto_Clear_Spot(void)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tMark(MARK_UP);\n\tif (!Target_Legal(NavCom) && BuildingTypeClass::As_Reference(STRUCT_CONST).Legal_Placement(Adjacent_Cell(Coord_Cell(Center_Coord()), FACING_NW))) {\n\t\tMark(MARK_DOWN);\n\t\treturn(true);\n\t}\n\n\tif (!Target_Legal(NavCom)) {\n\t\t/*\n\t\t**\tThis scan table is skewed to north scanning only. This should\n\t\t**\tprobably be converted to a more flexible method.\n\t\t*/\n\t\tstatic int _offsets[] = {\n\t\t\t-MAP_CELL_W*1,\n\t\t\t-MAP_CELL_W*2,\n\t\t\t-(MAP_CELL_W*2)+1,\n\t\t\t-(MAP_CELL_W*2)-1,\n\t\t\t-MAP_CELL_W*3,\n\t\t\t-(MAP_CELL_W*3)+1,\n\t\t\t-(MAP_CELL_W*3)-1,\n\t\t\t-(MAP_CELL_W*3)+2,\n\t\t\t-(MAP_CELL_W*3)-2,\n\t\t\t-MAP_CELL_W*4,\n\t\t\t-(MAP_CELL_W*4)+1,\n\t\t\t-(MAP_CELL_W*4)-1,\n\t\t\t-(MAP_CELL_W*4)+2,\n\t\t\t-(MAP_CELL_W*4)-2,\n//BG: Added south scanning\n\t\t\tMAP_CELL_W*1,\n\t\t\tMAP_CELL_W*2,\n\t\t\t(MAP_CELL_W*2)+1,\n\t\t\t(MAP_CELL_W*2)-1,\n\t\t\tMAP_CELL_W*3,\n\t\t\t(MAP_CELL_W*3)+1,\n\t\t\t(MAP_CELL_W*3)-1,\n\t\t\t(MAP_CELL_W*3)+2,\n\t\t\t(MAP_CELL_W*3)-2,\n\t\t\tMAP_CELL_W*4,\n\t\t\t(MAP_CELL_W*4)+1,\n\t\t\t(MAP_CELL_W*4)-1,\n\t\t\t(MAP_CELL_W*4)+2,\n\t\t\t(MAP_CELL_W*4)-2,\n\n//BG: Added some token east/west scanning\n\t\t\t-1,-2,-3,-4,\n\n\t\t\t 1, 2, 3, 4,\n\t\t\t0\n\t\t};\n\t\tint * ptr;\n\n\t\tptr = &_offsets[0];\n\t\twhile (*ptr) {\n\t\t\tCELL\tcell = Coord_Cell(Coord)+*ptr++;\n\t\t\tCELL\tcheck_cell = Adjacent_Cell(cell, FACING_NW);\n\t\t\tif (BuildingTypeClass::As_Reference(STRUCT_CONST).Legal_Placement(check_cell)) {\n\t\t\t\tAssign_Destination(::As_Target(cell));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tMark(MARK_DOWN);\n\n\t/*\n\t** If we couldn't find a destination to go to, let's try random movement\n\t** to see if that brings us to a better spot.\n\t*/\n\tif(!Target_Legal(NavCom) && !House->IsHuman) {\n\t\tScatter(0);\n\t}\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Try_To_Deploy -- The unit attempts to \"deploy\" at current location.              *\n *                                                                                             *\n *    Certain units have the ability to deploy into a building. When this routine is called    *\n *    for one of those units, it will attempt to deploy at its current location. If the unit   *\n *    is in motion to a destination or it isn't one of the special units that can deploy or    *\n *    it isn't allowed to deploy at this location for some reason it won't deploy. In all      *\n *    other cases, it will begin to deploy and once it begins only a player abort action will  *\n *    stop it.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was deployment begun?                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool UnitClass::Try_To_Deploy(void)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!Target_Legal(NavCom) && !IsRotating) {\n\t\tif (*this == UNIT_MCV) {\n\n\t\t\t/*\n\t\t\t**\tDetermine if it is legal to deploy at this location. If not, tell the\n\t\t\t**\tplayer.\n\t\t\t*/\n\t\t\tMark(MARK_UP);\n\t\t\tCELL cell = Coord_Cell(Adjacent_Cell(Center_Coord(), FACING_NW));\n\t\t\tif (!BuildingTypeClass::As_Reference(STRUCT_CONST).Legal_Placement(cell)) {\n\t\t\t\tif (PlayerPtr == House) {\n\t\t\t\t\tSpeak(VOX_DEPLOY);\n\t\t\t\t}\n\t\t\t\tif (!House->IsHuman) {\n\t\t\t\t\tBuildingTypeClass::As_Reference(STRUCT_CONST).Flush_For_Placement(cell, House);\n\t\t\t\t}\n\t\t\t\tMark(MARK_DOWN);\n\t\t\t\tIsDeploying = false;\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t\tMark(MARK_DOWN);\n\n\t\t\t/*\n\t\t\t**\tIf the unit is not facing the correct direction, then start it rotating\n\t\t\t**\ttoward the right facing, but still flag it as if it had deployed. This is\n\t\t\t**\tbecause it will deploy as soon as it reaches the correct facing.\n\t\t\t*/\n\t\t\tif (PrimaryFacing.Current() != DIR_SW) {\n\t\t\t\tDo_Turn(DIR_SW);\n//\t\t\t\tPrimaryFacing.Set_Desired(DIR_SW);\n\t\t\t\tIsDeploying = true;\n\t\t\t\treturn(true);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSince the unit is already facing the correct direction, actually do the\n\t\t\t**\tdeploy logic. If for some reason this cannot occur, then don't delete the\n\t\t\t**\tunit, just mark it as not deploying.\n\t\t\t*/\n\t\t\tMark(MARK_UP);\n\t\t\tBuildingClass * building = new BuildingClass(STRUCT_CONST, House->Class->House);\n\t\t\tif (building != NULL) {\n\t\t\t\tif (building->Unlimbo(Adjacent_Cell(Coord, FACING_NW))) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tPlay the buildup sound for the player if this is the players\n\t\t\t\t\t**\tMCV.\n\t\t\t\t\t*/\n\t\t\t\t\tif (building->House == PlayerPtr) {\n\t\t\t\t\t\tSound_Effect(VOC_PLACE_BUILDING_DOWN, Center_Coord());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbuilding->IsToRebuild = true;\n\t\t\t\t\t\tbuilding->IsToRepair = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tAlways reveal the construction yard to the player that owned the\n\t\t\t\t\t**\tmobile construction vehicle.\n\t\t\t\t\t*/\n\t\t\t\t\tbuilding->Revealed(House);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tWhen the MCV deploys, always consider production to have started\n\t\t\t\t\t**\tfor the owning house. This ensures that in multiplay, computer\n\t\t\t\t\t**\topponents will begin construction as soon as they start their\n\t\t\t\t\t**\tbase.\n\t\t\t\t\t*/\n\t\t\t\t\tHouse->IsStarted = true;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tForce the newly placed construction yard to be in the same strength\n\t\t\t\t\t**\tratio as the MCV that deployed into it.\n\t\t\t\t\t*/\n\t\t\t\t\tbuilding->Strength = Health_Ratio() * building->Class->MaxStrength;\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Force the MCV to drop any flag it was carrying.  This will also set\n\t\t\t\t\t** the owner house's flag home cell (since the house's FlagHome is\n\t\t\t\t\t** presumably 0 at this point).\n\t\t\t\t\t*/\n\t\t\t\t\tStun();\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If this MCV was teleported here, clear the gray flag so\n\t\t\t\t\t** the screen will go back to color.\n\t\t\t\t\t*/\n\t\t\t\t\tif (IsMoebius && !Scen.IsFadingColor) {\n\t\t\t\t\t\tScen.IsFadingBW = false;\n\t\t\t\t\t\tScen.IsFadingColor = true;\n\t\t\t\t\t\tScen.FadeTimer = GRAYFADETIME;\n\t\t\t\t\t}\n\t\t\t\t\tdelete this;\n\t\t\t\t\treturn(true);\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCould not deploy the construction yard at this location! Just revert\n\t\t\t\t\t**\tback to normal \"just sitting there\" mode and await further instructions.\n\t\t\t\t\t*/\n\t\t\t\t\tdelete building;\n\t\t\t\t}\n\t\t\t}\n\t\t\tMark(MARK_DOWN);\n\t\t\tIsDeploying = false;\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Per_Cell_Process -- Performs operations necessary on a per cell basis.           *\n *                                                                                             *\n *    This routine will perform the operations necessary that occur when a unit is at the      *\n *    center of a cell. These operations could entail deploying into a construction yard,      *\n *    radioing a transport unit, and looking around for the enemy.                             *\n *                                                                                             *\n * INPUT:   why   -- Specifies the circumstances under which this routine was called.          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/18/1994 JLB : Created.                                                                 *\n *   06/17/1995 JLB : Handles case when building says \"NO!\"                                    *\n *   06/30/1995 JLB : Gunboats head back and forth now.                                        *\n *=============================================================================================*/\nvoid UnitClass::Per_Cell_Process(PCPType why)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tCELL\tcell = Coord_Cell(Coord);\n\tHousesType house;\n\n\tif (why == PCP_END || why == PCP_ROTATION) {\n\t\t/*\n\t\t**\tCheck to see if this is merely the end of a rotation for the MCV as it is\n\t\t**\tpreparing to deploy. In this case, it should begin its deploy process.\n\t\t*/\n\t\tif (IsDeploying) {\n\t\t\tTry_To_Deploy();\n\t\t\tif (!IsActive) return;\t\t\t// Unit no longer exists -- bail.\n\t\t}\n\t}\n\n\tBStart(BENCH_PCP);\n\tif (why == PCP_END) {\n\t\t/*\n\t\t**\tIf this is a unit that is driving onto a building then the unit must enter\n\t\t**\tthe building as the final step.\n\t\t*/\n\t\tTechnoClass\t* whom = Contact_With_Whom();\n\t\tif (IsTethered && whom != NULL) {\n\t\t\tif (whom->What_Am_I() == RTTI_BUILDING && Mission == MISSION_ENTER) {\n\t\t\t\tif (whom == Map[CELL(cell-MAP_CELL_W)].Cell_Building()) {\n\t\t\t\t\tswitch (Transmit_Message(RADIO_IM_IN, whom)) {\n\t\t\t\t\t\tcase RADIO_ROGER:\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase RADIO_ATTACH:\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tScatter(0, true);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tUnit entering a transport vehicle will break radio contact\n\t\t**\tand attach itself to the transporter.\n\t\t*/\n\t\tTechnoClass * techno = Contact_With_Whom();\n\t\tif (Mission == MISSION_ENTER && techno && Coord_Cell(Coord) == Coord_Cell(techno->Coord) && techno == As_Techno(NavCom)) {\n\t\t\tif (Transmit_Message(RADIO_IM_IN) == RADIO_ATTACH) {\n\t\t\t\tLimbo();\n\t\t\t\ttechno->Attach(this);\n\t\t\t}\n\t\t\tBEnd(BENCH_PCP);\n\t\t\treturn;\n\t\t}\n\n\t\t/*\n\t\t**\tWhen breaking away from a transport object or building, possibly\n\t\t**\tscatter or otherwise begin normal unit operations.\n\t\t*/\n\t\tif (IsTethered && (Mission != MISSION_ENTER ||\n\t\t\t\t(As_Techno(NavCom) != NULL && Contact_With_Whom() != As_Techno(NavCom))\n\t\t\t\t) &&\n\t\t\t\tMission != MISSION_UNLOAD) {\n\n\t\t\t/*\n\t\t\t**\tSpecial hack check to make sure that even though it has moved one\n\t\t\t**\tcell, if it is still on the building (e.g., service depot), have\n\t\t\t**\tit scatter again.\n\t\t\t*/\n\t\t\tif\t(Map[Coord].Cell_Building() != NULL && !Target_Legal(NavCom)) {\n\t\t\t\tScatter(0, true, true);\n\t\t\t} else {\n\t\t\t\tif (Transmit_Message(RADIO_UNLOADED) == RADIO_RUN_AWAY) {\n\t\t\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\t\t\tScatter(0, true);\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tSpecial case hack to allow automatic transition to loading\n\t\t\t\t\t\t**\tonto a transport (or other situation) if the destination\n\t\t\t\t\t\t**\tso indicates.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tTechnoClass * techno = As_Techno(NavCom);\n\t\t\t\t\t\tif (techno != NULL) {\n\t\t\t\t\t\t\tTransmit_Message(RADIO_DOCKING, techno);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (*this == UNIT_HARVESTER) {\n\t\t\t\t\t\tif (Target_Legal(ArchiveTarget)) {\n\t\t\t\t\t\t\tAssign_Mission(MISSION_HARVEST);\n\t\t\t\t\t\t\tAssign_Destination(ArchiveTarget);\n\t\t\t\t\t\t\tArchiveTarget = TARGET_NONE;\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tSince there is no place to go, move away to clear\n\t\t\t\t\t\t\t**\tthe pad for another harvester.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\t\t\t\t\tScatter(0, true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf this is a loaner unit and is is off the edge of the\n\t\t**\tmap, then it gets eliminated. That is, unless it is carrying cargo. This means that\n\t\t**\tit is probably carrying an incoming reinforcement and it should not be eliminated.\n\t\t*/\n\t\tif (Edge_Of_World_AI()) {\n\t\t\tBEnd(BENCH_PCP);\n\t\t\treturn;\n\t\t}\n\n\t\t/*\n\t\t**\tThe unit performs looking around at this time. If the\n\t\t**\tunit moved further than one square during the last track\n\t\t**\tmove, don't do an incremental look. Do a full look around\n\t\t**\tinstead.\n\t\t*/\n\t\tif (IsPlanningToLook) {\n\t\t\tIsPlanningToLook = false;\n\t\t\tLook(false);\n\t\t} else {\n\t\t\tLook(true);\n\t\t}\n\n\t\t/*\n\t\t** If this is a mobile gap generator, restore the shroud where appropriate\n\t\t** and re-shroud around us.\n\t\t*/\n\t\tif (Class->IsGapper && !House->IsPlayerControl) {\n\t\t\tShroud_Regen();\n\t\t}\n\n\t\t/*\n\t\t**\tAct on new orders if the unit is at a good position to do so.\n\t\t*/\n\t\tif (!IsDumping) {\n\t\t\tCommence();\n\t\t}\n\n\t\t/*\n\t\t**\tCertain units require some setup time after they come to a halt.\n\t\t*/\n\t\tif (!Target_Legal(NavCom) && Path[0] == FACING_NONE) {\n\t\t\tif (Class->IsNoFireWhileMoving) {\n\t\t\t\tArm = Rearm_Delay(true)/4;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is a house flag here, then this unit just might pick it up.\n\t\t*/\n\t\tif (Flagged == HOUSE_NONE) {\n\n\t\t\tif (Map[cell].IsFlagged && Map[cell].Owner != House->Class->House) {\n\t\t\t\tHouseClass::As_Pointer(Map[cell].Owner)->Flag_Attach(this);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf this is the unit's own flag-home-cell and the unit is carrying\n\t\t** a flag, destroy the house of the flag the unit is carrying.\n\t\t*/\n\t\tif (Flagged != HOUSE_NONE) {\n\n\t\t\t/*\n\t\t\t**\tIf this vehicle is carrying your flag, then it will reveal the\n\t\t\t**\tmap for you as well as itself. This gives you and opportunity to\n\t\t\t**\tattack the unit.\n\t\t\t*/\n\t\t\tif (!IsOwnedByPlayer && Flagged == PlayerPtr->Class->House) {\n\t\t\t\tMap.Sight_From(Coord_Cell(Coord), Class->SightRange, House, true);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the flag reaches the home cell for the player, then the flag's\n\t\t\t**\towner will be destroyed.\n\t\t\t*/\n\t\t\tif (cell == HouseClass::As_Pointer(Owner())->FlagHome) {\n\t\t\t\thouse = Flagged; // Flag_Remove will clear 'Flagged', so save it\n\t\t\t\tHouseClass::As_Pointer(house)->Flag_Remove(As_Target(), true);\n\t\t\t\tHouseClass::As_Pointer(house)->Flag_To_Die();\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** If entering a cell with a land mine in it, blow up the mine.\n\t\t*/\n\t\tBuildingClass * bldng = Map[cell].Cell_Building();\n\t\tif (bldng != NULL && (*bldng == STRUCT_AVMINE || *bldng == STRUCT_APMINE) && !bldng->House->Is_Ally(this)) {\n\n\t\t\t/*\n\t\t\t** Special case: if it's a land mine deployer, and it ran over the\n\t\t\t** type of mine it deploys (only possible if it just dropped it\n\t\t\t** down) then ignore the mine.\n\t\t\t*/\n\t\t\tif (*this != UNIT_MINELAYER || bldng->House != House) {\n\n\t\t\t\tCOORDINATE blcoord = bldng->Center_Coord();\n\n\t\t\t\tnew AnimClass(ANIM_MINE_EXP1, blcoord);\n//\t\t\t\tnew AnimClass(Combat_Anim(Rule.AVMineDamage, WARHEAD_HE, Map[cell].Land_Type()), blcoord);\n\n\t\t\t\t/*\n\t\t\t\t** Vehicles blow up both mines, but they only take significant damage from AV mines.\n\t\t\t\t*/\n\t\t\t\tif (*bldng == STRUCT_AVMINE) {\n\t\t\t\t\tint damage = Rule.AVMineDamage;\n\t\t\t\t\tTake_Damage(damage, 0, WARHEAD_HE);\n\t\t\t\t} else {\n\t\t\t\t\tint damage = 10;\n\t\t\t\t\tTake_Damage(damage, 0, WARHEAD_HE);\n\t\t\t\t}\n\t\t\t\tdelete bldng;\n\t\t\t\tif (!IsActive) {\n\t\t\t\t\tBEnd(BENCH_PCP);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf after all is said and done, the unit finishes its move on an impassable cell, then\n\t\t**\tit must presume that it is in the case of a unit driving onto a bridge that blows up\n\t\t**\tbefore the unit completes it's move. In such a case the unit should have been destroyed\n\t\t**\tanyway, so blow it up now.\n\t\t*/\n\t\tLandType land = Map[Coord].Land_Type();\n\t\tif (!IsDriving && (land == LAND_ROCK || land == LAND_WATER || land == LAND_RIVER)) {\n\t\t\tnew AnimClass(Combat_Anim(Strength, WARHEAD_AP, land), Coord);\n\t\t\tint damage = Strength;\n\t\t\tTake_Damage(damage, 0, WARHEAD_AP, NULL, true);\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/*\n\t**\tDestroy any crushable wall that is driven over by a tracked vehicle.\n\t*/\n\tCellClass * cellptr = &Map[cell];\n\tif (Class->IsCrusher && cellptr->Overlay != OVERLAY_NONE) {\n//\tif (Class->Speed == SPEED_TRACK && cellptr->Overlay != OVERLAY_NONE) {\n\t\tOverlayTypeClass const * optr = &OverlayTypeClass::As_Reference(cellptr->Overlay);\n\n\t\tif (optr->IsCrushable) {\n\t\t\tif (optr->Type == OVERLAY_SANDBAG_WALL) {\n\t\t\t\tSound_Effect(VOC_SANDBAG, Center_Coord());\n\t\t\t} else {\n\t\t\t\tSound_Effect(VOC_WALLKILL2, Center_Coord());\n\t\t\t}\n\t\t\tcellptr->Reduce_Wall(-1);\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck to see if crushing of any unfortunate infantry is warranted.\n\t*/\n\tOverrun_Square(Coord_Cell(Coord), false);\n\n\tif (!IsActive) {\n\t\tBEnd(BENCH_PCP);\n\t\treturn;\n\t}\n\tDriveClass::Per_Cell_Process(why);\n\tBEnd(BENCH_PCP);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Shape_Number -- Fetch the shape number to use for this unit.                     *\n *                                                                                             *\n *    This routine will calculate the shape number for this unit. The shape number is used     *\n *    for the body of the unit.                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the shape number to be used for this unit.                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint UnitClass::Shape_Number(void) const\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tint\t\t\tshapenum;\t\t// Working shape number.\n\tint\t\t\tfacing = Dir_To_32(PrimaryFacing);\n\tint\t\t\ttfacing = Dir_To_32(SecondaryFacing);\n\tDirType\t\trotation = DIR_N;\n\n#ifdef FIXIT_ANTS\n\t/*\n\t**\tThis handles the ant case.\n\t*/\n\tif (Class->Rotation == 8)  {\n\n\t\t/*\n\t\t**\tThe starting frame is based on the facing of the unit.\n\t\t*/\n\t\tshapenum = ((UnitClass::BodyShape[facing]+2)/4) & 0x07;\n\n\t\t/*\n\t\t**\tIf the unit is driving, then it has an animation adjustment to the frame number.\n\t\t*/\n\t\tif (IsDriving)  {\n\t\t\tshapenum = 8 + (shapenum * 8) + ((::Frame+ID)/2) % 8;\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf in combat, then do combat anims.\n\t\t\t*/\n\t\t\tif (Arm > 0)  {\n\t\t\t\tshapenum = 8 + 64 + (shapenum * 4) + ((::Frame+ID)/2) % 4;\n\t\t\t}\n\t\t}\n\t} else {\n#endif\n\n\t/*\n\t**\tFetch the harvesting animation stage as appropriate.\n\t*/\n\tif (IsHarvesting && !PrimaryFacing.Is_Rotating() && !NavCom && !IsDriving) {\n//\t\t\tstatic char _hstage[] = {0, 1, 2, 3, 4, 5, 6, 7, 0};\n\t\tunsigned stage = Fetch_Stage();\n\t\tif (stage >= ARRAY_SIZE(Class->Harvester_Load_List)) stage = ARRAY_SIZE(Class->Harvester_Load_List)-1;\n\t\tshapenum = 32 + (((UnitClass::BodyShape[facing]+2)/4)*Class->Harvester_Load_Count)+Class->Harvester_Load_List[stage];\n\t} else {\n\t\t/*\n\t\t** If the harvester's dumping a load of ore, show that animation\n\t\t*/\n\t\tif (IsDumping) {\n\t\t\tunsigned stage = Fetch_Stage();\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif (*this == UNIT_MAD) {\n\t\t\t\tif (stage >= 8) {\n\t\t\t\t\tstage = 7;\n\t\t\t\t}\n\t\t\t\tshapenum = 32 + stage + (UnitClass::BodyShape[facing]/4)*8;\n\t\t\t} else {\n\t\t\t\tif (stage >= ARRAY_SIZE(Class->Harvester_Dump_List)) stage = ARRAY_SIZE(Class->Harvester_Dump_List)-1;\n\t\t\t\tshapenum = Class->Harvester_Dump_List[stage]+96;\n\t\t\t}\n#else\n\t\t\tif (stage >= ARRAY_SIZE(Class->Harvester_Dump_List)) stage = ARRAY_SIZE(Class->Harvester_Dump_List)-1;\n\t\t\tshapenum = Class->Harvester_Dump_List[stage]+96;\n#endif\n\t\t} else {\n\t\t\tshapenum = UnitClass::BodyShape[facing];\n\n\t\t\tif (Class->IsAnimating) {\n\t\t\t\tshapenum = Fetch_Stage();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDoor opening and closing animation must be handled carefully. There are only\n\t\t\t**\tcertain directions where this door animation will work.\n\t\t\t*/\n\t\t\tif (!Is_Door_Closed() && (PrimaryFacing == DIR_NW || PrimaryFacing == DIR_NE)) {\n\t\t\t\tif (PrimaryFacing == DIR_NE) {\n\t\t\t\t\tshapenum = 32;\n\t\t\t\t} else {\n\t\t\t\t\tif (PrimaryFacing == DIR_NW) {\n\t\t\t\t\t\tshapenum = 35;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tshapenum += Door_Stage();\n\t\t\t}\n\t\t}\n\t}\n\n#ifdef FIXIT_ANTS\n\t}\n#endif\n\n\t/*\n\t**\tThe body of the V2 launcher indicates whether it is loaded with a missile\n\t**\tor not.\n\t*/\n\tif (*this == UNIT_V2_LAUNCHER) {\n\t\tif (Ammo == 0) shapenum += 32;\n\t}\n\n\treturn(shapenum);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Draw_It -- Draws a unit object.                                                  *\n *                                                                                             *\n *    This routine is the one that actually draws a unit object. It displays the unit          *\n *    according to its current state flags and centered at the location specified.             *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y coordinate of where to draw the unit.                         *\n *                                                                                             *\n *          window   -- The clipping window to use.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1994 JLB : Created.                                                                 *\n *   06/27/1994 JLB : Takes a window parameter.                                                *\n *   08/15/1994 JLB : Removed infantry support.                                                *\n *   01/07/1995 JLB : Harvester animation support.                                             *\n *   07/08/1995 JLB : Uses general purpose draw routine.                                       *\n *=============================================================================================*/\nvoid UnitClass::Draw_It(int x, int y, WindowNumberType window) const\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tint\t\t\tshapenum;\t\t// Working shape number.\n\tvoid const\t* shapefile;\t\t// Working shape file pointer.\n\tint\t\t\tfacing = Dir_To_32(PrimaryFacing);\n\tint\t\t\ttfacing = Dir_To_32(SecondaryFacing);\n\tDirType\t\trotation = DIR_N;\n\tint\t\t\tscale = 0x0100;\n\n\t/*\n\t**\tVerify the legality of the unit class.\n\t*/\n\tshapefile = Get_Image_Data();\n\tif (shapefile == NULL) return;\n\n\t/*\n\t**\tIf drawing of this unit is not explicitly prohibited, then proceed\n\t**\twith the render process.\n\t*/\n\tif (Visual_Character() != VISUAL_HIDDEN) {\n\t\tshapenum = Shape_Number();\n\n\t\t/*\n\t\t**\tThe artillery unit should have its entire body recoil when it fires.\n\t\t*/\n\t\tif (*this == UNIT_ARTY && IsInRecoilState) {\n\t\t\tRecoil_Adjust(PrimaryFacing.Current(), x, y);\n\t\t}\n\n\t\t/*\n\t\t**\tActually perform the draw. Overlay an optional shimmer effect as necessary.\n\t\t*/\n\t\tTechno_Draw_Object(shapefile, shapenum, x, y, window, rotation, scale);\n\n\t\t/*\n\t\t**\tIf there is a rotating radar dish, draw it now.\n\t\t*/\n\t\tif (Class->IsRadarEquipped) {\n\t\t\tif (*this == UNIT_MGG) {\n\t\t\t\tint x2 = x, y2 = y;\n\t\t\t\tshapenum = 32 + (Frame & 7);\n\t\t\t\tClass->Turret_Adjust(PrimaryFacing, x2, y2);\n\t\t\t\tTechno_Draw_Object(shapefile, shapenum, x2, y2, window);\n\t\t\t} else {\n//#ifdef FIXIT_PHASETRANSPORT\t//\tchecked - ajw 9/28/98\n//\t\t\t\tif (*this == UNIT_PHASE) {\n//\t\t\t\t\tshapenum = 38 + (Frame & 7);\n//\t\t\t\t} else {\n//\t\t\t\t\tshapenum = 32 + (Frame % 32);\n//\t\t\t\t}\n//#else\n\t\t\t\tshapenum = 32 + (Frame % 32);\n//#endif\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif (*this == UNIT_TESLATANK) {\n\t\t\t\t\tTechno_Draw_Object(shapefile, shapenum, x, y, window);\n\t\t\t\t} else {\n\t\t\t\t\tTechno_Draw_Object(shapefile, shapenum, x, y-5, window);\n\t\t\t\t}\n#else\n\t\t\t\tTechno_Draw_Object(shapefile, shapenum, x, y-5, window);\n#endif\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is a turret, then it must be rendered as well. This may include\n\t\t**\tfiring animation if required.\n\t\t*/\n\t\tif (/*!Class->IsChunkyShape &&*/ Class->IsTurretEquipped) {\n\t\t\tint xx = x;\n\t\t\tint yy = y;\n\n\t\t\t/*\n\t\t\t**\tDetermine which turret shape to use. This depends on if there\n\t\t\t**\tis any firing animation in progress.\n\t\t\t*/\n\t\t\tshapenum = TechnoClass::BodyShape[tfacing]+32;\n#ifdef FIXIT_PHASETRANSPORT\t//\tchecked - ajw 9/28/98\n\t\t\tif (*this == UNIT_PHASE) {\n\t\t\t\tshapenum += 6;\n\t\t\t}\n#endif\n\t\t\t/*\n\t\t\t**\tA recoiling turret moves \"backward\" one pixel.\n\t\t\t*/\n\t\t\tif (IsInRecoilState) {\n\t\t\t\tRecoil_Adjust(SecondaryFacing, xx, yy);\n\t\t\t}\n\n\t\t\tClass->Turret_Adjust(PrimaryFacing, xx, yy);\n\n\t\t\t/*\n\t\t\t**\tActually perform the draw. Overlay an optional shimmer effect as necessary.\n\t\t\t*/\n\t\t\tTechno_Draw_Object(shapefile, shapenum, xx, yy, window);\n\t\t}\n\t}\n\n\t/*\n\t**\tIf this unit is carrying the flag, then draw that on top of everything else.\n\t*/\n\tif (Flagged != HOUSE_NONE) {\n\t\tCC_Draw_Shape(MFCD::Retrieve(\"FLAGFLY.SHP\"), Frame % 14, x, y, window, SHAPE_CENTER|SHAPE_FADING|SHAPE_GHOST, HouseClass::As_Pointer(Flagged)->Remap_Table(false, Class->Remap), Map.UnitShadow);\n\t}\n\n\tDriveClass::Draw_It(x, y, window);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Tiberium_Check -- Search for and head toward nearest available Tiberium patch.   *\n *                                                                                             *\n *    This routine is used to move a harvester to a place where it can load up with            *\n *    Tiberium. It will return true only if it can start harvesting. Otherwise, it sets        *\n *    the navigation computer toward the nearest Tiberium and lets the unit head there         *\n *    automatically.                                                                           *\n *                                                                                             *\n * INPUT:   center   -- Reference to the center of the radius scan.                            *\n *                                                                                             *\n *          x,y      -- Relative offset from the center cell to perform the check upon.        *\n *                                                                                             *\n * OUTPUT:  bool; Is it located directly over a Tiberium patch?                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool UnitClass::Tiberium_Check(CELL & center, int x, int y)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tIf the specified offset from the origin will cause it\n\t**\tto spill past the map edge, then abort this cell check.\n\t*/\n\tif (Cell_X(center)+x < Map.MapCellX) return(false);\n\tif (Cell_X(center)+x >= Map.MapCellX+Map.MapCellWidth) return(false);\n\tif (Cell_Y(center)+y < Map.MapCellY) return(false);\n\tif (Cell_Y(center)+y >= Map.MapCellY+Map.MapCellHeight) return(false);\n\n\tcenter = XY_Cell(Cell_X(center)+x, Cell_Y(center)+y);\n\n\tif ((Session.Type != GAME_NORMAL || (!IsOwnedByPlayer || Map[center].IsMapped))) {\n\t\tif (Map[Coord].Zones[Class->MZone] != Map[center].Zones[Class->MZone]) return(false);\n\t\tif (!Map[center].Cell_Techno() && Map[center].Land_Type() == LAND_TIBERIUM) {\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Goto_Tiberium -- Searches for and heads toward tiberium.                         *\n *                                                                                             *\n *    This routine will cause the unit to search for and head toward nearby Tiberium. When     *\n *    the Tiberium is reached, then this routine should not be called again until such time    *\n *    as additional harvesting is required. When this routine returns false, then it should    *\n *    be called again until such time as it returns true.                                      *\n *                                                                                             *\n * INPUT:   rad = size of ring to search                                                       *\n *                                                                                             *\n * OUTPUT:  Has the unit reached Tiberium and harvesting should begin?                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool UnitClass::Goto_Tiberium(int rad)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!Target_Legal(NavCom)) {\n\t\tCELL center = Coord_Cell(Center_Coord());\n\t\tif (Map[center].Land_Type() == LAND_TIBERIUM) {\n\t\t\treturn(true);\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tPerform a ring search outward from the center.\n\t\t\t*/\n\t\t\tfor (int radius = 1; radius < rad; radius++) {\n\t\t\t\tfor (int x = -radius; x <= radius; x++) {\n\t\t\t\t\tCELL cell = center;\n\t\t\t\t\tif (Tiberium_Check(cell, x, -radius)) {\n\t\t\t\t\t\tAssign_Destination(::As_Target(cell));\n\t\t\t\t\t\treturn(false);\n\t\t\t\t\t}\n\n\t\t\t\t\tcell = center;\n\t\t\t\t\tif (Tiberium_Check(cell, x, +radius)) {\n\t\t\t\t\t\tAssign_Destination(::As_Target(cell));\n\t\t\t\t\t\treturn(false);\n\t\t\t\t\t}\n\n\t\t\t\t\tcell = center;\n\t\t\t\t\tif (Tiberium_Check(cell, -radius, x)) {\n\t\t\t\t\t\tAssign_Destination(::As_Target(cell));\n\t\t\t\t\t\treturn(false);\n\t\t\t\t\t}\n\n\t\t\t\t\tcell = center;\n\t\t\t\t\tif (Tiberium_Check(cell, +radius, x)) {\n\t\t\t\t\t\tAssign_Destination(::As_Target(cell));\n\t\t\t\t\t\treturn(false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Harvesting -- Harvests tiberium at the current location.                         *\n *                                                                                             *\n *    This routine is used to by the harvester to harvest Tiberium at the current location.    *\n *    When harvesting is complete, this routine will return true.                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is harvesting complete?                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool UnitClass::Harvesting(void)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tCELL\tcell = Coord_Cell(Coord);\n\tCellClass * ptr = &Map[cell];\n\n\t/*\n\t**\tKeep waiting if still heading toward a spot to harvest.\n\t*/\n\tif (Target_Legal(NavCom)) return(true);\n\n\tif (Tiberium_Load() < 1 && ptr->Land_Type() == LAND_TIBERIUM) {\n\n\t\t/*\n\t\t**\tLift some Tiberium from the ground. Try to lift a complete\n\t\t**\t\"level\" of Tiberium. A level happens to be 6 steps. If there\n\t\t**\tis a partial level, then lift that instead. Never lift more\n\t\t**\tthan the harvester can carry.\n\t\t*/\n//\t\tint reducer = (ptr->OverlayData % 6) + 1;\n\t\tint reducer = 1;\n\t\tOverlayType overlay = ptr->Overlay;\n\t\treducer = ptr->Reduce_Tiberium(min(reducer, Rule.BailCount-Tiberium));\n\t\tTiberium += reducer;\n\t\tswitch (overlay) {\n\t\t\tcase OVERLAY_GOLD1:\n\t\t\tcase OVERLAY_GOLD2:\n\t\t\tcase OVERLAY_GOLD3:\n\t\t\tcase OVERLAY_GOLD4:\n\t\t\t\tGold += reducer;\n\t\t\t\tbreak;\n\n\t\t\tcase OVERLAY_GEMS1:\n\t\t\tcase OVERLAY_GEMS2:\n\t\t\tcase OVERLAY_GEMS3:\n\t\t\tcase OVERLAY_GEMS4:\n\t\t\t\tGems += reducer;\n\t\t\t\tif (Rule.BailCount > Tiberium) {Gems++;Tiberium++;}\n\t\t\t\tif (Rule.BailCount > Tiberium) {Gems++;Tiberium++;}\n\t\t\t\tif (Rule.BailCount > Tiberium) {Gems++;Tiberium++;}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\tSet_Stage(0);\n\t\tSet_Rate(Rule.OreDumpRate);\n\n\t} else {\n\n\t\t/*\n\t\t**\tIf the harvester is stopped on a non Tiberium field and the harvester\n\t\t**\tisn't loaded with Tiberium, then no further action can be performed\n\t\t**\tby this logic routine. Bail with a failure and thus cause a branch to\n\t\t**\ta better suited logic processor.\n\t\t*/\n\t\tSet_Stage(0);\n\t\tSet_Rate(0);\n\t\treturn(false);\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Mission_Unload -- Handles unloading cargo.                                       *\n *                                                                                             *\n *    This is the AI control sequence for when a transport desires to unload its cargo and     *\n *    then exit the map.                                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before calling this routine again.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint UnitClass::Mission_Unload(void)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tenum {\n\t\tINITIAL_CHECK,\n\t\tMANEUVERING,\n\t\tOPENING_DOOR,\n\t\tUNLOADING,\n\t\tCLOSING_DOOR\n\t};\n\tDirType\tdir;\n\tCELL\t\tcell;\n\n\tswitch (Class->Type) {\n\t\tcase UNIT_HARVESTER:\n\t\t\tif (PrimaryFacing != DIR_W) {\n\t\t\t\tif (!IsRotating) {\n\t\t\t\t\tDo_Turn(DIR_W);\n\t\t\t\t}\n\t\t\t\treturn(5);\n\t\t\t}\n\n\t\t\tif (!IsDumping) {\n\t\t\t\tIsDumping = true;\n\t\t\t\tSet_Stage(0);\n\t\t\t\tSet_Rate(Rule.OreDumpRate);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (Fetch_Stage() < ARRAY_SIZE(Class->Harvester_Dump_List)-1) break;\n\n\t\t\tIsDumping = false;\n\t\t\tif (Tiberium) {\n\t\t\t\tTiberium = 0;\n\t\t\t\tint credits = Credit_Load();\n\t\t\t\tHouse->Harvested(credits);\n\t\t\t\tTiberium = Gold = Gems = 0;\n\t\t\t}\n\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\n\t\t\tAssign_Mission(MISSION_HARVEST);\n\t\t\tbreak;\n\n\t\tcase UNIT_TRUCK:\n\t\t\tswitch (Status) {\n\t\t\t\tcase INITIAL_CHECK:\n\t\t\t\t\tdir = Desired_Load_Dir(NULL, cell);\n\t\t\t\t\tif (How_Many() && cell != 0) {\n\t\t\t\t\t\tDo_Turn(dir);\n\t\t\t\t\t\tStatus = MANEUVERING;\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase MANEUVERING:\n\t\t\t\t\tif (!IsRotating) {\n\t\t\t\t\t\tStatus = UNLOADING;\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase UNLOADING:\n\t\t\t\t\tif (How_Many()) {\n\t\t\t\t\t\tFootClass * passenger = Detach_Object();\n\n\t\t\t\t\t\tif (passenger != NULL) {\n\t\t\t\t\t\t\tDirType toface = DIR_S + PrimaryFacing;\n\t\t\t\t\t\t\tbool placed = false;\n\n\t\t\t\t\t\t\tfor (FacingType face = FACING_N; face < FACING_COUNT; face++) {\n\t\t\t\t\t\t\t\tDirType newface = toface + Facing_Dir(face);\n\t\t\t\t\t\t\t\tCELL newcell = Adjacent_Cell(Coord_Cell(Coord), newface);\n\n\t\t\t\t\t\t\t\tif (passenger->Can_Enter_Cell(newcell) == MOVE_OK) {\n\t\t\t\t\t\t\t\t\tScenarioInit++;\n\t\t\t\t\t\t\t\t\tpassenger->Unlimbo(Coord_Move(Coord, newface, 0x0080), newface);\n\t\t\t\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t\t\t\t\tpassenger->Assign_Mission(MISSION_MOVE);\n\t\t\t\t\t\t\t\t\tpassenger->Assign_Destination(::As_Target(newcell));\n\t\t\t\t\t\t\t\t\tplaced = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** If the attached unit could NOT be deployed, then re-attach\n\t\t\t\t\t\t\t**\tit and then bail out of this deploy process.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (!placed) {\n\t\t\t\t\t\t\t\tAttach(passenger);\n\t\t\t\t\t\t\t\tStatus = CLOSING_DOOR;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tStatus = CLOSING_DOOR;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tClose APC door in preparation for normal operation.\n\t\t\t\t*/\n\t\t\t\tcase CLOSING_DOOR:\n\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase UNIT_APC:\n#ifdef FIXIT_PHASETRANSPORT\t//\tchecked - ajw 9/28/98\n\t\tcase UNIT_PHASE:\n#endif\n\t\t\tswitch (Status) {\n\t\t\t\tcase INITIAL_CHECK:\n\t\t\t\t\tdir = Desired_Load_Dir(NULL, cell);\n\t\t\t\t\tif (How_Many() && cell != 0) {\n\t\t\t\t\t\tDo_Turn(dir);\n\t\t\t\t\t\tStatus = MANEUVERING;\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase MANEUVERING:\n\t\t\t\t\tif (!IsRotating) {\n\t\t\t\t\t\tAPC_Open_Door();\n\t\t\t\t\t\tif (Is_Door_Opening()) {\n\t\t\t\t\t\t\tStatus = OPENING_DOOR;\n\t\t\t\t\t\t\treturn(1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OPENING_DOOR:\n\t\t\t\t\tif (Is_Door_Open()) {\n\t\t\t\t\t\tStatus = UNLOADING;\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!Is_Door_Opening()) {\n\t\t\t\t\t\t\tStatus = INITIAL_CHECK;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase UNLOADING:\n\t\t\t\t\tif (How_Many()) {\n\t\t\t\t\t\tFootClass * passenger = Detach_Object();\n\n\t\t\t\t\t\tif (passenger != NULL) {\n\t\t\t\t\t\t\tDirType toface = DIR_S + PrimaryFacing;\n\t\t\t\t\t\t\tbool placed = false;\n\n\t\t\t\t\t\t\tfor (FacingType face = FACING_N; face < FACING_COUNT; face++) {\n\t\t\t\t\t\t\t\tDirType newface = toface + Facing_Dir(face);\n\t\t\t\t\t\t\t\tCELL newcell = Adjacent_Cell(Coord_Cell(Coord), newface);\n\n\t\t\t\t\t\t\t\tif (passenger->Can_Enter_Cell(newcell) == MOVE_OK) {\n\t\t\t\t\t\t\t\t\tScenarioInit++;\n\t\t\t\t\t\t\t\t\tpassenger->Unlimbo(Coord_Move(Coord, newface, 0x0080), newface);\n\t\t\t\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t\t\t\t\tpassenger->Assign_Mission(MISSION_MOVE);\n\t\t\t\t\t\t\t\t\tpassenger->Assign_Destination(::As_Target(newcell));\n\t\t\t\t\t\t\t\t\tplaced = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** If the attached unit could NOT be deployed, then re-attach\n\t\t\t\t\t\t\t**\tit and then bail out of this deploy process.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (!placed) {\n\t\t\t\t\t\t\t\tAttach(passenger);\n\t\t\t\t\t\t\t\tStatus = CLOSING_DOOR;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tStatus = CLOSING_DOOR;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tClose APC door in preparation for normal operation.\n\t\t\t\t*/\n\t\t\t\tcase CLOSING_DOOR:\n\t\t\t\t\tif (Is_Door_Open()) {\n\t\t\t\t\t\tAPC_Close_Door();\n\t\t\t\t\t}\n\t\t\t\t\tif (Is_Door_Closed()) {\n\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase UNIT_MCV:\n\t\t\tswitch (Status) {\n\t\t\t\tcase 0:\n\t\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t\t\tStatus = 1;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 1:\n\t\t\t\t\tif (!IsDriving) {\n\t\t\t\t\t\tTry_To_Deploy();\n\t\t\t\t\t\tif (IsActive) {\n\t\t\t\t\t\t\tif (IsDeploying) {\n\t\t\t\t\t\t\t\tStatus = 2;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (!House->IsHuman && Session.Type != GAME_NORMAL) {\n\t\t\t\t\t\t\t\t\tAssign_Mission(MISSION_HUNT);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 2:\n\t\t\t\t\tif (!IsDeploying) {\n\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\treturn(1);\n\n\t\tcase UNIT_MINELAYER:\n\t\t\tswitch (Status) {\n\t\t\t\tcase INITIAL_CHECK:\n\t\t\t\t\tdir = DIR_NE;\n\t\t\t\t\tif (Ammo > 0) {\n\t\t\t\t\t\tDo_Turn(dir);\n\t\t\t\t\t\tStatus = MANEUVERING;\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase MANEUVERING:\n\t\t\t\t\tif (!IsRotating) {\n\t\t\t\t\t\tAPC_Open_Door();\n\t\t\t\t\t\tif (Is_Door_Opening()) {\n\t\t\t\t\t\t\tStatus = OPENING_DOOR;\n\t\t\t\t\t\t\treturn(1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OPENING_DOOR:\n\t\t\t\t\tif (Is_Door_Open()) {\n\t\t\t\t\t\tStatus = UNLOADING;\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!Is_Door_Opening()) {\n\t\t\t\t\t\t\tStatus = INITIAL_CHECK;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase UNLOADING:\n\t\t\t\t\tif (Ammo > 0) {\n\t\t\t\t\t\tif (!Map[Center_Coord()].Cell_Building()) {\n\t\t\t\t\t\t\tMark(MARK_UP);\n\t\t\t\t\t\t\tBuildingClass * building = new BuildingClass((House->ActLike == HOUSE_USSR || House->ActLike == HOUSE_UKRAINE || House->ActLike == HOUSE_BAD) ? STRUCT_APMINE : STRUCT_AVMINE, House->Class->House);\n\t\t\t\t\t\t\tif (building != NULL) {\n\t\t\t\t\t\t\t\tScenarioInit = true;\n\t\t\t\t\t\t\t\tif (building->Unlimbo(Coord)) {\n\t\t\t\t\t\t\t\t\tSound_Effect(VOC_MINELAY1, Coord);\n\t\t\t\t\t\t\t\t\tScenarioInit = false;\n\t\t\t\t\t\t\t\t\tbuilding->Revealed(House);\n\t\t\t\t\t\t\t\t\tAmmo--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tScenarioInit = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tStatus = CLOSING_DOOR;\n\t\t\t\t\t\t\tMark(MARK_DOWN);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tStatus = CLOSING_DOOR;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tStatus = CLOSING_DOOR;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tClose APC door in preparation for normal operation.\n\t\t\t\t*/\n\t\t\t\tcase CLOSING_DOOR:\n\t\t\t\t\tif (Is_Door_Open()) {\n\t\t\t\t\t\tAPC_Close_Door();\n\t\t\t\t\t}\n\t\t\t\t\tif (Is_Door_Closed()) {\n\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tcase UNIT_MAD:\n\t\t\tif (!Gems && !IsDumping) {\n\t\t\t\tGems = 1;\n\t\t\t\tGold = 0;\n\t\t\t\tArm = QuakeDelay * House->ROFBias;\n#ifdef ENGLISH\n\t\t\t\tSpeak(VOX_MADTANK_DEPLOYED);\t// this voice only exists in English\n#else\n\t\t\t\tSound_Effect(VOC_BUZZY1,Center_Coord());\n#endif\n\t\t\t\tSet_Stage(0);\n\t\t\t\tSet_Rate(Rule.OreDumpRate*2);\n\t\t\t\tIsDumping = true;\n\n#if 1\n\t\t\t\tInfantryClass *crew = new InfantryClass(INFANTRY_C1, House->Class->House);\n\t\t\t\tif (crew != NULL) crew->IsTechnician = true;\n\n\t\t\t\tif (crew != NULL) {\n\t\t\t\t\tDirType toface = DIR_S + PrimaryFacing;\n\n\t\t\t\t\tfor (FacingType face = FACING_N; face < FACING_COUNT; face++) {\n\t\t\t\t\t\tDirType newface = toface + Facing_Dir(face);\n\t\t\t\t\t\tCELL newcell = Adjacent_Cell(Coord_Cell(Coord), newface);\n\t\t\t\t\t\tif (crew->Can_Enter_Cell(newcell) == MOVE_OK) {\n\t\t\t\t\t\t\tScenarioInit++;\n\t\t\t\t\t\t\tcrew->Unlimbo(Coord_Move(Coord, newface, 0x0080), newface);\n\t\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t\t\tcrew->Assign_Mission(MISSION_MOVE);\n\t\t\t\t\t\t\tcrew->Assign_Destination(::As_Target(newcell));\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n#endif\n\t\t\t}\n\n\t\t\tif ( (Arm && !Gold) || IronCurtainCountDown) {\n\t\t\t\tSet_Stage(Fetch_Stage() & 1);\n\t\t\t\treturn(1);\n\t\t\t}\n\n\t\t\tif (!Gold) {\n\t\t\t\tSound_Effect(VOC_MAD_CHARGE, Center_Coord());\n\t\t\t\tSet_Stage(0);\n\t\t\t\tGold = 1;\n\t\t\t\treturn(1);\n\t\t\t}\n\n\t\t\tif (Fetch_Stage() < 7) {\n\t\t\t\treturn(1);\n\t\t\t}\n\n\t\t\tIsDumping = false;\n\n\t\t\tSound_Effect(VOC_MAD_EXPLODE, Center_Coord());\n\n\t\t\tStrength = 1;\t\t\t// assure destruction\n\t\t\tPendingTimeQuake = true;\t\t// trigger a time quake\n\t\t\tTimeQuakeCenter = ::As_Target(Center_Coord());\n\t\t\tbreak;\n\n\t\tcase UNIT_CHRONOTANK:\n\t\t\tif (IsOwnedByPlayer) {\n\t\t\t\tMap.IsTargettingMode = SPC_CHRONO2;\n\t\t\t\tUnselect_All();\n\t\t\t}\n\t\t\tHouse->UnitToTeleport = As_Target();\n\n\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\tbreak;\n#endif\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * UnitClass::Mission_Harvest -- Handles the harvesting process used by harvesters.            *\n *                                                                                             *\n *    This is the AI process used by harvesters when they are doing their harvesting action.   *\n *    This entails searching for nearby Tiberium, heading there, harvesting, and then          *\n *    returning to a refinery for unloading.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before calling this routine again.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *   06/21/1995 JLB : Force guard mode if no Tiberium found.                                   *\n *   09/28/1995 JLB : Aborts harvesting if there are no more refineries.                       *\n *=============================================================================================*/\nint UnitClass::Mission_Harvest(void)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tenum {\n\t\tLOOKING,\n\t\tHARVESTING,\n\t\tFINDHOME,\n\t\tHEADINGHOME,\n\t\tGOINGTOIDLE,\n\t};\n\n\t/*\n\t**\tA non-harvesting type unit will just sit still if it is given the harvest mission. This\n\t**\tallows combat units to act \"brain dead\".\n\t*/\n\tif (!Class->IsToHarvest) return(TICKS_PER_SECOND*30);\n\n\t/*\n\t**\tIf there are no more refineries, then drop into guard mode.\n\t*/\n\tif (!(House->ActiveBScan & STRUCTF_REFINERY)) {\n\t\tAssign_Mission(MISSION_GUARD);\n\t\treturn(1);\n\t}\n\n\tswitch (Status) {\n\n\t\t/*\n\t\t**\tGo and find a Tiberium field to harvest.\n\t\t*/\n\t\tcase LOOKING:\n\t\t\t/*\n\t\t\t**\tWhen full of tiberium, just skip to finding a free refinery\n\t\t\t**\tto unload at.\n\t\t\t*/\n\t\t\tif (Tiberium_Load() == 1) {\n\t\t\t\tStatus = FINDHOME;\n\t\t\t\treturn(1);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Look for ore where we last found some - mine the same patch\n\t\t\t*/\n\t\t\tif (Target_Legal(ArchiveTarget)) {\n\t\t\t\tAssign_Destination(ArchiveTarget);\n\t\t\t\tArchiveTarget = 0;\n\t\t\t}\n\t\t\tIsHarvesting = false;\n\t\t\tif (Goto_Tiberium(Rule.TiberiumLongScan / CELL_LEPTON_W)) {\n\t\t\t\tIsHarvesting = true;\n\t\t\t\tSet_Rate(2);\n\t\t\t\tSet_Stage(0);\n\t\t\t\tStatus = HARVESTING;\n\t\t\t\treturn(1);\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the harvester isn't on Tiberium and it is not heading toward Tiberium, then\n\t\t\t\t**\tforce it to go into guard mode. This will prevent the harvester from repeatedly\n\t\t\t\t**\tsearching for Tiberium.\n\t\t\t\t*/\n\t\t\t\tif (!Target_Legal(NavCom)) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the archive target is legal, then head there since it is presumed\n\t\t\t\t\t**\tthat the archive target points to the last place it harvested at. This might\n\t\t\t\t\t**\tsolve the case where the harvester gets stuck and can't find Tiberium just because\n\t\t\t\t\t**\tit is greater than 32 squares away.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Target_Legal(ArchiveTarget)) {\n\t\t\t\t\t\tAssign_Destination(ArchiveTarget);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tStatus = GOINGTOIDLE;\n\t\t\t\t\t\tIsUseless = true;\n\t\t\t\t\t\tHouse->IsTiberiumShort = true;\n\t\t\t\t\t\treturn(TICKS_PER_SECOND*7);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tIsUseless = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tHarvest at current location until full or Tiberium exhausted.\n\t\t*/\n\t\tcase HARVESTING:\n//\t\t\tif (Fetch_Stage() > ARRAY_SIZE(Class->Harvester_Load_List)) {\n//\t\t\t\tSet_Stage(0);\n//\t\t\t}\n\t\t\tif (Fetch_Rate() == 0) {\n\t\t\t\tSet_Stage(0);\n\t\t\t\tSet_Rate(Rule.OreDumpRate);\n\t\t\t}\n\n\t\t\tif (Fetch_Stage() < ARRAY_SIZE(Class->Harvester_Load_List)) return(1);\n\t\t\tif (!Harvesting()) {\n\t\t\t\tIsHarvesting = false;\n\t\t\t\tif (Tiberium_Load() == 1) {\n\t\t\t\t\tStatus = FINDHOME;\n\t\t\t\t  \tArchiveTarget = ::As_Target(Coord_Cell(Coord));\n\t\t\t\t} else {\n\t\t\t\t\tif (!Goto_Tiberium(Rule.TiberiumShortScan / CELL_LEPTON_W) && !Target_Legal(NavCom))\t{\n\t\t\t\t\t  \tArchiveTarget = TARGET_NONE;\n\t\t\t\t\t\tStatus = FINDHOME;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tStatus = HARVESTING;\n\t\t\t\t\t\tIsHarvesting = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(1);\n\t\t\t}\n\t\t\treturn(1);\n//\t\t\treturn(TICKS_PER_SECOND*Rule.OreDumpRate);\n\n\t\t/*\n\t\t**\tFind and head to refinery.\n\t\t*/\n\t\tcase FINDHOME:\n\t\t\tif (!Target_Legal(NavCom)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tFind nearby refinery and head to it?\n\t\t\t\t*/\n\t\t\t\tBuildingClass * nearest = Find_Docking_Bay(STRUCT_REFINERY, false);\n\n\t\t\t\t/*\n\t\t\t\t**\tSince the refinery said it was ok to load, establish radio\n\t\t\t\t**\tcontact with the refinery and then await docking orders.\n\t\t\t\t*/\n\t\t\t\tif (nearest != NULL && Transmit_Message(RADIO_HELLO, nearest) == RADIO_ROGER) {\n\t\t\t\t\tStatus = HEADINGHOME;\n\t\t\t\t\tif (nearest->House == PlayerPtr && (PlayerPtr->Capacity - PlayerPtr->Tiberium) < 300 && PlayerPtr->Capacity > 500 && (PlayerPtr->ActiveBScan & (STRUCTF_REFINERY | STRUCTF_CONST))) {\n\t\t\t\t\t\tSpeak(VOX_NEED_MO_CAPACITY);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tScenarioInit++;\n\t\t\t\t\tnearest = Find_Docking_Bay(STRUCT_REFINERY, false);\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t\tif (nearest != NULL) {\n\t\t\t\t\t\tAssign_Destination(::As_Target(Nearby_Location(nearest)));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tIn communication with refinery so that it will successfully dock and\n\t\t**\tunload. If, for some reason, radio contact was lost, then hunt for\n\t\t**\tanother refinery to unload at.\n\t\t*/\n\t\tcase HEADINGHOME:\n\t\t\tAssign_Mission(MISSION_ENTER);\n\t\t\treturn(1);\n\n\t\t/*\n\t\t**\tThe harvester has nothing to do. There is no Tiberium nearby and\n\t\t**\tno where to go.\n\t\t*/\n\t\tcase GOINGTOIDLE:\n\t\t\tif (IsUseless) {\n\t\t\t\tif (House->ActiveBScan & STRUCTF_REPAIR) {\n\t\t\t\t\tAssign_Mission(MISSION_REPAIR);\n\t\t\t\t} else {\n\t\t\t\t\tAssign_Mission(MISSION_HUNT);\n\t\t\t\t}\n\t\t\t}\n\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\tbreak;\n\n\t}\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * UnitClass::Mission_Hunt -- This is the AI process for aggressive enemy units.               *\n *                                                                                             *\n *    Computer controlled units must be intelligent enough to find enemies as well as to       *\n *    attack them. This AI process will handle both the simple attack process as well as the   *\n *    scanning for enemy units to attack.                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before calling this routine again.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint UnitClass::Mission_Hunt(void)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == UNIT_MCV) {\n\t\tenum {\n\t\t\tFIND_SPOT,\n\t\t\tWAITING\n\t\t};\n\n\t\tswitch (Status) {\n\n\t\t\t/*\n\t\t\t**\tThis stage handles locating a convenient spot, rotating to face the correct\n\t\t\t**\tdirection and then commencing the deployment operation.\n\t\t\t*/\n\t\t\tcase FIND_SPOT:\n\t\t\t\tif (Goto_Clear_Spot()) {\n\t\t\t\t\tif (Try_To_Deploy()) {\n\t\t\t\t\t\tStatus = WAITING;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tThis stage watchdogs the deployment operation and if for some reason, the deployment\n\t\t\t**\tis aborted (the IsDeploying flag becomes false), then it reverts back to hunting for\n\t\t\t**\ta convenient spot to deploy.\n\t\t\t*/\n\t\t\tcase WAITING:\n\t\t\t\tif (!IsDeploying) {\n\t\t\t\t\tStatus = FIND_SPOT;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t} else {\n\n\t\treturn(DriveClass::Mission_Hunt());\n\t}\n\treturn(MissionControl[Mission].Normal_Delay()+Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * UnitClass::Overlap_List -- Determines overlap list for units.                               *\n *                                                                                             *\n *    The unit overlap list is used to keep track of which cells are to                        *\n *    be marked for redraw. This is critical in order to keep the units                        *\n *    displayed correctly.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the overlap list pointer for the unit at its                          *\n *          present position.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/26/1994 JLB : Created.                                                                 *\n *   06/19/1994 JLB : Uses Coord_Spillable_List function.                                      *\n *=============================================================================================*/\nshort const * UnitClass::Overlap_List(bool redraw) const\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n#ifdef PARTIAL\n\tif (Height == 0 && redraw && Class->DimensionData != NULL) {\n\t\tRect rect;\n\t\tint shapenum = Shape_Number();\n\t\tif (Class->DimensionData[shapenum].Is_Valid()) {\n\t\t\trect = Class->DimensionData[shapenum];\n\t\t} else {\n\t\t\trect = Class->DimensionData[shapenum] = Shape_Dimensions(Get_Image_Data(), shapenum);\n\t\t}\n\n\t\tif (IsSelected) {\n\t\t\trect = Union(rect, Rect(-15, -15, 30, 30));\n\t\t}\n\n\t\tif (Class->IsTurretEquipped || Class->IsRadarEquipped) {\n\t\t\trect = Union(rect, Rect(-15, -15, 30, 30));\n\t\t}\n\n\t\treturn(Coord_Spillage_List(Coord, rect, true));\n\t}\n#else\n\tredraw = redraw;\n#endif\n\n\tint size = ICON_PIXEL_W;\n\n\tif (redraw && (IsSelected || IsFiring)) {\n\t\tsize += 24;\n\t}\n\tif (Class->IsGigundo || IsAnimAttached) {\n\t\tsize = ICON_PIXEL_W*2;\n\t}\n\n\treturn(Coord_Spillage_List(Coord, size)+1);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Can_Enter_Cell -- Determines cell entry legality.                                *\n *                                                                                             *\n *    Use this routine to determine if the unit can enter the cell                             *\n *    specified and given the direction of entry specified. Typically,                         *\n *    this is used when determining unit travel path.                                          *\n *                                                                                             *\n * INPUT:   cell     -- The cell to examine.                                                   *\n *                                                                                             *\n *          facing   -- The facing that the unit would enter the specified                     *\n *                      cell. If this value is -1, then don't consider                         *\n *                      facing when performing the check.                                      *\n *                                                                                             *\n * OUTPUT:  Returns the reason why it couldn't enter the cell or MOVE_OK if movement is        *\n *          allowed.                                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/07/1992 JLB : Created.                                                                 *\n *   04/16/1994 JLB : Converted to member function.                                            *\n *   07/04/1995 JLB : Allowed to drive on building trying to enter it.                         *\n *=============================================================================================*/\nMoveType UnitClass::Can_Enter_Cell(CELL cell, FacingType ) const\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tbool cancrush = false;\n\n\tCellClass const * cellptr = &Map[cell];\n\n\tif ((unsigned)cell >= MAP_CELL_TOTAL) return(MOVE_NO);\n\n\t/*\n\t**\tMoving off the edge of the map is not allowed unless\n\t**\tthis is a loaner vehicle.\n\t*/\n\tif (!ScenarioInit && !Map.In_Radar(cell) && !Is_Allowed_To_Leave_Map() && IsLocked) {\n\t\treturn(MOVE_NO);\n\t}\n\n\tMoveType retval = MOVE_OK;\n\n\t/*\n\t**\tCertain vehicles can drive over walls. Check for this case and\n\t**\tand return the appropriate flag. Other units treat walls as impassable.\n\t*/\n\tif (cellptr->Overlay != OVERLAY_NONE) {\n\t\tOverlayTypeClass const * optr = &OverlayTypeClass::As_Reference(cellptr->Overlay);\n\n\t\tif (optr->IsCrate && !((Session.Type == GAME_NORMAL) ? House->IsPlayerControl : House->IsHuman) && Session.Type == GAME_NORMAL) {\n\t\t\treturn(MOVE_NO);\n\t\t}\n\n\t\tif (optr->IsWall) {\n\n\t\t\t/*\n\t\t\t**\tIf the blocking wall is crushable (and not owned by this player or one of this players\n\t\t\t**\tallies, then record that it is crushable and let the normal logic take over. The end\n\t\t\t**\tresult should cause this unit to consider the cell passable.\n\t\t\t*/\n\t\t\tif (optr->IsCrushable && Class->IsCrusher) {\n\t\t\t\tcancrush = !House->Is_Ally(cellptr->Owner);\n\t\t\t}\n\n\t\t\tif (!cancrush && Is_Weapon_Equipped()) {\n\t\t\t\tWarheadTypeClass const * whead = Class->PrimaryWeapon->WarheadPtr;\n\n\t\t\t\tif (whead->IsWallDestroyer || (whead->IsWoodDestroyer && optr->IsWooden)) {\n//\t\t\t\t\tif (!House->IsHuman && !House->Is_Ally(cellptr->Owner)) {\n\t\t\t\t\t\tif (retval < MOVE_DESTROYABLE) retval = MOVE_DESTROYABLE;\n//\t\t\t\t\t} else {\n//\t\t\t\t\t\treturn(MOVE_NO);\n//\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn(MOVE_NO);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Loop through all of the objects in the square setting a bit\n\t** for how they affect movement.\n\t*/\n\tbool crushable = false;\n\tObjectClass * obj = cellptr->Cell_Occupier();\n\twhile (obj != NULL) {\n\n\t\tif (obj != this) {\n\n\t\t\t/*\n\t\t\t** If object is a land mine, allow movement if possible.\n\t\t\t*/\n\t\t\tif (obj->What_Am_I() == RTTI_BUILDING && (!Rule.IsMineAware || !((BuildingClass *)obj)->House->Is_Ally(House))) {\n\t\t\t\tif ((*(BuildingClass *)obj) == STRUCT_APMINE) return(MOVE_OK);\n\t\t\t\tif ((*(BuildingClass *)obj) == STRUCT_AVMINE) return(MOVE_OK);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAlways allow entry if trying to move on a cell with\n\t\t\t**\tauthorization from the occupier.\n\t\t\t*/\n\t\t\tif (obj == Contact_With_Whom() && (IsTethered || (obj->What_Am_I() ==  RTTI_BUILDING && *((BuildingClass *)obj) == STRUCT_REPAIR))) {\n\t\t\t\treturn(MOVE_OK);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSpecial check to allow entry into the sea transport this vehicle\n\t\t\t**\tis trying to enter.\n\t\t\t*/\n\t\t\tif (Mission == MISSION_ENTER && obj->As_Target() == NavCom && IsTethered) {\n\t\t\t\treturn(MOVE_OK);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tGuard area should not allow the guarding unit to enter the cell with the\n\t\t\t**\tguarded unit.\n\t\t\t*/\n\t\t\tif (Mission == MISSION_GUARD_AREA && ArchiveTarget == obj->As_Target()) {\n\t\t\t\treturn(MOVE_NO);\n\t\t\t}\n\n\t\t\tbool is_moving = obj->Is_Foot() &&\n\t\t\t\t\t\t(Target_Legal(((FootClass *)obj)->NavCom) || ((FootClass *)obj)->PrimaryFacing.Is_Rotating() || ((FootClass *)obj)->IsDriving);\n//\t\t\t\t\t\t(((FootClass *)obj)->PrimaryFacing.Is_Rotating() || ((FootClass *)obj)->IsDriving);\n//\t\t\t\t\t\t(((FootClass *)obj)->IsRotating || ((FootClass *)obj)->IsDriving);\n//\t\t\t\t\t\t(Target_Legal(((FootClass *)obj)->NavCom) || ((FootClass *)obj)->IsDriving);\n\n\t\t\tif (House->Is_Ally(obj)) {\n\t\t\t\tif (is_moving) {\n\t\t\t\t\tint face \t\t= Dir_Facing(PrimaryFacing);\n\t\t\t\t\tint techface\t= Dir_Facing(((FootClass const *)obj)->PrimaryFacing) ^4;\n\t\t\t\t\tif (face == techface && Distance((AbstractClass const *)obj) <= 0x1FF) {\n\t\t\t\t\t\treturn(MOVE_NO);\n\t\t\t\t\t}\n\t\t\t\t\tif (retval < MOVE_MOVING_BLOCK) retval = MOVE_MOVING_BLOCK;\n\t\t\t\t} else {\n\t\t\t\t\tif (obj->What_Am_I() == RTTI_BUILDING) return(MOVE_NO);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the blocking object is not in the same zone, then it certainly\n\t\t\t\t\t**\tisn't a temporary block, it is a permanent one.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Map[Coord].Zones[Class->MZone] != cellptr->Zones[Class->MZone]) return(MOVE_NO);\n\n\t\t\t\t\tif (retval < MOVE_TEMP) retval = MOVE_TEMP;\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tCloaked enemy objects are not considered if this is a Find_Path()\n\t\t\t\t**\tcall.\n\t\t\t\t*/\n\t\t\t\tif (!obj->Is_Techno() || ((TechnoClass *)obj)->Cloak != CLOAKED) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf this unit can crush infantry, and there is an enemy infantry in the\n\t\t\t\t\t**\tcell, don't consider the cell impassible. This is true even if the unit\n\t\t\t\t\t**\tdoesn't contain a legitimate weapon.\n\t\t\t\t\t*/\n\t\t\t\t\tbool crusher = Class->IsCrusher;\n\t\t\t\t\tif (!crusher || !obj->Class_Of().IsCrushable) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tAny non-allied blockage is considered impassable if the unit\n\t\t\t\t\t\t**\tis not equipped with a weapon.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (Class->PrimaryWeapon == NULL) return(MOVE_NO);\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tSome kinds of terrain are considered destroyable if the unit is equipped\n\t\t\t\t\t\t**\twith the weapon that can destroy it. Otherwise, the terrain is considered\n\t\t\t\t\t\t**\timpassable.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tswitch (obj->What_Am_I()) {\n\t\t\t\t\t\t\tcase RTTI_TERRAIN:\n\n#ifdef TOFIX\n\t\t\t\t\t\t\t\tif (((TerrainClass *)obj)->Class->Armor == ARMOR_WOOD &&\n\t\t\t\t\t\t\t\t\t\tClass->PrimaryWeapon->WarheadPtr->IsWoodDestroyer) {\n\n\t\t\t\t\t\t\t\t\tif (retval < MOVE_DESTROYABLE) retval = MOVE_DESTROYABLE;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\treturn(MOVE_NO);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n#else\n\t\t\t\t\t\t\t\treturn(MOVE_NO);\n#endif\n\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tif (retval < MOVE_DESTROYABLE) retval = MOVE_DESTROYABLE;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcrushable = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (retval < MOVE_CLOAK) retval = MOVE_CLOAK;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tMove to next object in chain.\n\t\t*/\n\t\tobj = obj->Next;\n\t}\n\n\t/*\n\t**\tIf the cell is out and out impassable because of underlying terrain, then\n\t**\treturn this immutable fact.\n\t*/\n\tif (!cancrush && retval != MOVE_DESTROYABLE && Ground[cellptr->Land_Type()].Cost[Class->Speed] == 0) {\n\t\treturn(MOVE_NO);\n\t}\n\n\t/*\n\t**\tIf some allied object has reserved the cell, then consider the cell\n\t**\tas blocked by a moving object.\n\t*/\n\tif (retval == MOVE_OK && !crushable && (cellptr->Flag.Composite & 0x3F) != 0) {\n\n\t\t/*\n\t\t**\tIf reserved by a vehicle, then consider this blocked terrain.\n\t\t*/\n\t\tif (cellptr->Flag.Occupy.Vehicle) {\n\t\t\tretval = MOVE_MOVING_BLOCK;\n\t\t} else {\n\t\t\tif (cellptr->InfType != HOUSE_NONE && House->Is_Ally(cellptr->InfType)) {\n\t\t\t\tretval = MOVE_MOVING_BLOCK;\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tEnemy infantry have reserved the cell. If this unit can crush\n\t\t\t\t**\tinfantry, consider the cell passable. If not, then consider the\n\t\t\t\t**\tcell destroyable if it has a weapon. If neither case applies, then\n\t\t\t\t**\tthis vehicle should avoid the cell altogether.\n\t\t\t\t*/\n\t\t\t\tif (!Class->IsCrusher) {\n\t\t\t\t\tif (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->Bullet->IsAntiGround) {\n\t\t\t\t\t\tretval = MOVE_DESTROYABLE;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn(MOVE_NO);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** If its ok to move into the cell because we can crush whats in the cell, then\n\t** make sure no one else is already moving into the cell to crush something.\n\t*/\n\tif (retval == MOVE_OK && crushable && cellptr->Flag.Occupy.Vehicle) {\n\n\t\t/*\n\t\t**\tHowever, if the cell is occupied by a crushable vehicle, then we can\n\t\t**\tnever be sure if some other friendly vehicle is also trying to crush\n\t\t**\tthe cell at the same time. In the case of a crushable vehicle in the\n\t\t**\tcell, then allow entry.\n\t\t*/\n\t\tif (!cellptr->Cell_Unit() || !cellptr->Cell_Unit()->Class->IsCrushable) {\n\t\t\treturn(MOVE_MOVING_BLOCK);\n\t\t}\n\t}\n\n\t/*\n\t**\tReturn with the most severe reason why this cell would be impassable.\n\t*/\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Init -- Clears all units for scenario preparation.                               *\n *                                                                                             *\n *    This routine will zero out the unit list and unit objects. This routine is typically     *\n *    used in preparation for a new scenario load. All units are guaranteed to be eliminated   *\n *    by this routine.                                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitClass::Init(void)\n{\n\tUnits.Free_All();\n}\n\n\n/***********************************************************************************************\n * UnitClass::Start_Driver -- Starts driving and reserves destination cell.                    *\n *                                                                                             *\n *    This routine will start the vehicle moving by marking the destination cell as            *\n *    reserved. Cells must be reserved in this fashion or else they might become occupied as   *\n *    the vehicle is proceeding toward it.                                                     *\n *                                                                                             *\n * INPUT:   headto   -- The location where the vehicle will be heading.                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the vehicle started to move? Failure could be the result of the cell     *\n *                being occupied.                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool UnitClass::Start_Driver(COORDINATE & headto)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (DriveClass::Start_Driver(headto) && IsActive) {//BG IsActive can be cleared by Start_Driver\n\t\tMark_Track(headto, MARK_DOWN);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * UnitClass::What_Action -- Determines what action would occur if clicked on object.          *\n *                                                                                             *\n *    Use this function to determine what action would likely occur if the specified object    *\n *    were clicked on while this unit was selected as current. This function controls, not     *\n *    only the action to perform, but indirectly controls the cursor shape to use as well.     *\n *                                                                                             *\n * INPUT:   object   -- The object that to check for against \"this\" object.                    *\n *                                                                                             *\n * OUTPUT:  Returns with the default action to perform. If no clear action can be determined,  *\n *          then ACTION_NONE is returned.                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/11/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType UnitClass::What_Action(ObjectClass const * object) const\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tActionType action = DriveClass::What_Action(object);\n\n\t/*\n\t** Allow units to move onto land mines.\n\t*/\n\tif (action == ACTION_NONE && object->What_Am_I() == RTTI_BUILDING) {\n\t\tStructType blah = *((BuildingClass *)object);\n\t\tif (blah == STRUCT_AVMINE || blah == STRUCT_APMINE) return(ACTION_MOVE);\n\t}\n\n\t/*\n\t**\tIf the unit doesn't have a weapon, but can crush the object, then consider\n\t**\tthe object as a movable location.\n\t*/\n\tif (action == ACTION_ATTACK && !Can_Player_Fire()) {\n\t\tif (Class->IsCrusher && object->Class_Of().IsCrushable) {\n\t\t\taction = ACTION_MOVE;\n\t\t} else {\n\t\t\taction = ACTION_SELECT;\n\t\t}\n\t}\n\n\t/*\n\t**\tDon't allow special deploy action unless there is something to deploy.\n\t*/\n\tif (action == ACTION_SELF) {\n\t\tif (*this == UNIT_MCV) {\n\n\t\t\t/*\n\t\t\t**\tThe MCV will get the no-deploy cursor if it couldn't\n\t\t\t**\tdeploy at its current location.\n\t\t\t*/\n\t\t\t((ObjectClass &)(*this)).Mark(MARK_UP);\n\t\t\tif (!BuildingTypeClass::As_Reference(STRUCT_CONST).Legal_Placement(Coord_Cell(Adjacent_Cell(Center_Coord(), FACING_NW)))) {\n\t\t\t\taction = ACTION_NO_DEPLOY;\n\t\t\t}\n\t\t\t((ObjectClass &)(*this)).Mark(MARK_DOWN);\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tThe mine layer can \"deploy\" its mines if it currently isn't\n\t\t\t**\tsitting on top of a mine and it still has mines available.\n\t\t\t*/\n\t\t\tif (*this == UNIT_MINELAYER) {\n\t\t\t\tif (!Ammo || Map[Center_Coord()].Cell_Building() || (Map[Center_Coord()].Smudge != SMUDGE_NONE && SmudgeTypeClass::As_Reference(Map[Center_Coord()].Smudge).IsBib)) {\n\t\t\t\t\taction = ACTION_NO_DEPLOY;\n\t\t\t\t}\n\t\t\t} else {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif (*this == UNIT_CHRONOTANK || *this == UNIT_MAD) {\n\t\t\t\t\tif (*this == UNIT_CHRONOTANK) {\n// If the chrono tank's counter is still charging up, don't allow deploy.  Or,\n// if it's a player-controlled chrono tank, and the player's currently trying\n// to teleport a different unit, don't allow teleporting this unit.\n\t\t\t\t\t\tif(MoebiusCountDown || (IsOwnedByPlayer && House->UnitToTeleport && Map.IsTargettingMode == SPC_CHRONO2)) {\n\t\t\t\t\t\t\taction = ACTION_NO_DEPLOY;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n#endif\n\t\t\t\t/*\n\t\t\t\t**\tAll other units can \"deploy\" their passengers if they in-fact have\n\t\t\t\t**\tpassengers and are a transport vehicle. Otherwise, they cannot\n\t\t\t\t**\tperform any self action.\n\t\t\t\t*/\n\t\t\t\tif (Class->Max_Passengers() > 0) {\n\t\t\t\t\tif (How_Many() == 0) {\n\t\t\t\t\t\taction = ACTION_NO_DEPLOY;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\taction = ACTION_NONE;\n\t\t\t\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t}\n#endif\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tSpecial return to friendly refinery action.\n\t*/\n\tif (House->IsPlayerControl && object->Is_Techno() && ((TechnoClass const *)object)->House->Is_Ally(this)) {\n\t\tif (object->What_Am_I() == RTTI_BUILDING && ((UnitClass *)this)->Transmit_Message(RADIO_CAN_LOAD, (TechnoClass*)object) == RADIO_ROGER) {\n\t\t\taction = ACTION_ENTER;\n\t\t}\n\t}\n\n\t/*\n\t**\tSpecial return to friendly repair factory action.\n\t*/\n\tif (House->IsPlayerControl && action == ACTION_SELECT && object->What_Am_I() == RTTI_BUILDING) {\n\t\tBuildingClass * building = (BuildingClass *)object;\n\t\tif (building->Class->Type == STRUCT_REPAIR && ((UnitClass *)this)->Transmit_Message(RADIO_CAN_LOAD, building) == RADIO_ROGER && !building->In_Radio_Contact() && !building->Is_Something_Attached()) {\n\t\t\taction = ACTION_MOVE;\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck to see if it can enter a transporter.\n\t*/\n\tif (\n\t\tHouse->Is_Ally(object) &&\n\t\tHouse->IsPlayerControl && object->Is_Techno() && object->What_Am_I() == RTTI_VESSEL) {\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n if( *(VesselClass *)object != VESSEL_CARRIER) {\n#endif\n\t\tswitch (((UnitClass *)this)->Transmit_Message(RADIO_CAN_LOAD, (TechnoClass*)object)) {\n\t\t\tcase RADIO_ROGER:\n\t\t\t\taction = ACTION_ENTER;\n\t\t\t\tbreak;\n\n\t\t\tcase RADIO_NEGATIVE:\n\t\t\t\taction = ACTION_NO_ENTER;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\taction = ACTION_NONE;\n\t\t\t\tbreak;\n\t\t}\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n }\n#endif\n\t}\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (*this == UNIT_MAD && (IsDumping || Gold)) {\n\t\taction = ACTION_NONE;\n\t}\n#endif\n\t/*\n\t**\tIf it doesn't know what to do with the object, then just\n\t**\tsay it can't move there.\n\t*/\n\tif (action == ACTION_NONE) action = ACTION_NOMOVE;\n\n\treturn(action);\n}\n\n\n/***********************************************************************************************\n * UnitClass::What_Action -- Determines action to perform on specified cell.                   *\n *                                                                                             *\n *    This routine will determine what action to perform if the mouse were clicked over the    *\n *    cell specified. At the unit level, only the harvester is checked for. The lower          *\n *    classes determine the regular action response.                                           *\n *                                                                                             *\n * INPUT:   cell  -- The cell that the mouse might be clicked on.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the action type that this unit will perform if the mouse were         *\n *          clicked of the cell specified.                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType UnitClass::What_Action(CELL cell) const\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tActionType action = DriveClass::What_Action(cell);\n\tif (action == ACTION_MOVE && Map[cell].Land_Type() == LAND_TIBERIUM && Class->IsToHarvest) {\n\t\treturn(ACTION_HARVEST);\n\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (*this == UNIT_MAD && (IsDumping || Gold)) {\n\t\taction = ACTION_NOMOVE;\n\t}\n#endif\n\treturn(action);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Exit_Repair -- Drive the unit off the repair facility.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/03/1995 BWG : Created.                                                                 *\n *=============================================================================================*/\n#define XYCELL(x, y)\t(y*MAP_CELL_W+x)\nvoid UnitClass::Exit_Repair(void)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tint\ti;\n\tCELL\tcell;\n\tbool\tfound = false;\n\tstatic short const ExitRepair[] = {\n\t\tXYCELL(0,\t-2),\n\t\tXYCELL(1,\t-1),\n\t\tXYCELL(2,\t0),\n\t\tXYCELL(1,\t1),\n\t\tXYCELL(0,\t2),\n\t\tXYCELL(-1,\t1),\n\t\tXYCELL(-2,\t0),\n\t\tXYCELL(-1,\t-1)\n\t};\n\n\tcell = Coord_Cell(Coord) + ExitRepair[Dir_Facing(PrimaryFacing.Current())];\n\tif (Can_Enter_Cell(cell) == MOVE_OK) found = true;\n\n\tif (!found) for (i=0; i<8; i++) {\n\t\tcell = Coord_Cell(Coord) + ExitRepair[i];\n\t\tif (Can_Enter_Cell(cell) == MOVE_OK) {\n\t\t\tfound = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (found) {\n//\t\tDirType\tdir = Direction(cell);\n\n\t\tAssign_Mission(MISSION_MOVE);\n\t\tAssign_Destination(::As_Target(cell));\n\t}\n}\n\n\n/***********************************************************************************************\n * UnitClass::Mission_Guard -- Special guard mission override processor.                       *\n *                                                                                             *\n *    Handles the guard mission for the unit. If the IQ is high enough and the unit is         *\n *    a harvester, it will begin to harvest automatically. An MCV might autodeploy.            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the time delay before this command is executed again.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *   05/08/1995 JLB : Fixes gunboat problems.                                                  *\n *=============================================================================================*/\nint UnitClass::Mission_Guard(void)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\tif (/*House->IsBaseBuilding &&*/ !House->IsHuman && Class->IsToHarvest && House->Get_Quantity(STRUCT_REFINERY) > 0 && !House->IsTiberiumShort) {\n\t\tAssign_Mission(MISSION_HARVEST);\n\t\treturn(1);\n//\t\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n\t}\n\n\tif (*this == UNIT_MCV && House->IsBaseBuilding) {\n\t\tAssign_Mission(MISSION_UNLOAD);\n\t\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n\t}\n\treturn(DriveClass::Mission_Guard());\n}\n\n\n/***********************************************************************************************\n * UnitClass::Mission_Move -- Handles special move mission overrides.                          *\n *                                                                                             *\n *    This routine intercepts the normal move mission and if a gunboat is being processed,     *\n *    changes its mission to hunt. This is an attempt to keep the gunboat on the hunt mission  *\n *    regardless of what the player did.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the number of ticks before this routine should be called again.            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/09/1995 JLB : Created.                                                                 *\n *   09/28/1995 JLB : Harvester stick in guard mode if no more refineries.                     *\n *=============================================================================================*/\nint UnitClass::Mission_Move(void)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tIsHarvesting = false;\n\n\t/*\n\t**\tAlways make sure that that transport door is closed if the vehicle is moving.\n\t*/\n\tif (!Is_Door_Closed()) {\n\t\tAPC_Close_Door();\n\t}\n\n\treturn(DriveClass::Mission_Move());\n}\n\n\n/***********************************************************************************************\n * UnitClass::Desired_Load_Dir -- Determines the best cell and facing for loading.             *\n *                                                                                             *\n *    This routine examines the unit and adjacent cells in order to find the best facing       *\n *    for the transport and best staging cell for the potential passengers. This location is   *\n *    modified by adjacent cell passability and direction of the potential passenger.          *\n *                                                                                             *\n * INPUT:   passenger   -- Pointer to the potential passenger.                                 *\n *                                                                                             *\n *          moveto      -- Reference to the cell number that specifies where the potential     *\n *                         passenger should move to first.                                     *\n *                                                                                             *\n * OUTPUT:  Returns with the direction the transport should face before opening the transport  *\n *          door.                                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nDirType UnitClass::Desired_Load_Dir(ObjectClass * passenger, CELL & moveto) const\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tDetermine the ideal facing that provides the least resistance. This would be the direction\n\t**\tof the potential passenger or the current transport facing if it is going to unload.\n\t*/\n\tDirType faceto;\n\tif (passenger != NULL) {\n\t\tfaceto = Direction(passenger);\n\t} else {\n\t\tfaceto = PrimaryFacing.Current() + DIR_S;\n\t}\n\n\t/*\n\t**\tSweep through the adjacent cells in order to find the best candidate.\n\t*/\n\tFacingType bestdir = FACING_N;\n\tint bestval = -1;\n\tfor (FacingType face = FACING_N; face < FACING_COUNT; face++) {\n\t\tint value = 0;\n\t\tCELL cellnum = Adjacent_Cell(Coord_Cell(Coord), face);\n\n\t\t/*\n\t\t**\tBase the initial value of the potential cell according to whether the passenger is\n\t\t**\tallowed to enter the cell. If it can't, then give such a negative value to the\n\t\t**\tcell so that it is prevented from ever choosing that cell for load/unload.\n\t\t*/\n\t\tif (passenger != NULL) {\n\t\t\tvalue = (passenger->Can_Enter_Cell(cellnum) == MOVE_OK || Coord_Cell(passenger->Coord) == cellnum) ? 128 : -128;\n\t\t} else {\n\t\t\tCellClass * cell = &Map[cellnum];\n\t\t\tif (Ground[cell->Land_Type()].Cost[SPEED_FOOT] == 0 || cell->Flag.Occupy.Building || cell->Flag.Occupy.Vehicle || cell->Flag.Occupy.Monolith || (cell->Flag.Composite & 0x01F) == 0x01F) {\n\t\t\t\tvalue = -128;\n\t\t\t} else {\n\t\t\t\tif (cell->Cell_Techno() && !House->Is_Ally(cell->Cell_Techno())) {\n\t\t\t\t\tvalue = -128;\n\t\t\t\t} else {\n\t\t\t\t\tvalue = 128;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tGive more weight to the cells that require the least rotation of the transport or the\n\t\t**\tleast roundabout movement for the potential passenger.\n\t\t*/\n\t\tvalue -= (int)ABS((int)(signed char)Facing_Dir(face) - (int)(signed char)faceto);\n\t\tif (face == FACING_S) {\n\t\t\tvalue -= 100;\n\t\t}\n\t\tif (face == FACING_SW || face == FACING_SE) value += 64;\n\n\t\t/*\n\t\t**\tIf the value for the potential cell is greater than the last recorded potential\n\t\t**\tvalue, then record this cell as the best candidate.\n\t\t*/\n\t\tif (bestval == -1 || value > bestval) {\n\t\t\tbestval = value;\n\t\t\tbestdir = face;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf a suitable direction was found, then return with the direction value.\n\t*/\n\tmoveto = 0;\n\tif (bestval > 0) {\n\t\tstatic DirType _desired_to_actual[FACING_COUNT] = {DIR_S, DIR_SW, DIR_NW, DIR_NW, DIR_NE, DIR_NE, DIR_NE, DIR_SE};\n\n\t\tmoveto = Adjacent_Cell(Coord_Cell(Coord), bestdir);\n\t\treturn(_desired_to_actual[bestdir]);\n\t}\n\treturn(DIR_S);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Flag_Attach -- Attaches a house flag to this unit.                               *\n *                                                                                             *\n *    This routine will attach a house flag to this unit.                                      *\n *                                                                                             *\n * INPUT:   house -- The house that is having its flag attached to it.                         *\n *                                                                                             *\n * OUTPUT:  Was the house flag successfully attached to this unit?                             *\n *                                                                                             *\n * WARNINGS:   A unit can only carry one flag at a time. This might be a reason for failure    *\n *             of this routine.                                                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool UnitClass::Flag_Attach(HousesType house)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (house != HOUSE_NONE && Flagged == HOUSE_NONE)\t{\n\t\tFlagged = house;\n\t\tMark(MARK_CHANGE);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Flag_Remove -- Removes the house flag from this unit.                            *\n *                                                                                             *\n *    This routine will remove the house flag that is attached to this unit.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the flag successfully removed?                                                 *\n *                                                                                             *\n * WARNINGS:   This routine doesn't put the flag into a new location. That operation must      *\n *             be performed or else the house flag will cease to exist.                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool UnitClass::Flag_Remove(void)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Flagged != HOUSE_NONE) {\n\t\tFlagged = HOUSE_NONE;\n\t\tMark(MARK_CHANGE);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Pip_Count -- Fetches the number of pips to display on unit.                      *\n *                                                                                             *\n *    This routine is used to fetch the number of \"fullness\" pips to display on the unit.      *\n *    This will either be the number of passengers or the percentage full (in 1/5ths) of       *\n *    a harvester.                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of pips to draw on this unit.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint UnitClass::Pip_Count(void) const\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->Max_Passengers() > 0) {\n\t\treturn(How_Many());\n\t}\n\n\tif (*this == UNIT_MINELAYER) {\n\t\tint retval = 0;\n\t\tif (Ammo > 0) {\n\t\t\tretval = Class->Max_Pips() * fixed(Ammo, Class->MaxAmmo);\n\t\t\tif (!retval) retval = 1;\n\t\t}\n\t\treturn(retval);\n\t}\n\n\tif (*this == UNIT_HARVESTER) {\n\t\treturn((Gold + Gems) / 4);\n\t}\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (*this == UNIT_CHRONOTANK) {\n\t\tint fulldur = ChronoTankDuration * TICKS_PER_MINUTE;\n\t\treturn( (fulldur - MoebiusCountDown) / (fulldur / 5));\n\t}\n#endif\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * UnitClass::APC_Close_Door -- Closes an APC door.                                            *\n *                                                                                             *\n *    This routine will initiate closing of the APC door.                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitClass::APC_Close_Door(void)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tClose_Door(10, 2);\n}\n\n\n/***********************************************************************************************\n * UnitClass::APC_Open_Door -- Opens an APC door.                                              *\n *                                                                                             *\n *    This routine will initiate opening of the APC door.                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitClass::APC_Open_Door(void)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!IsDriving && !IsRotating) {\n\t\tif (PrimaryFacing == DIR_NW || PrimaryFacing == DIR_NE) {\n\t\t\tOpen_Door(10, 2);\n\t\t} else {\n\t\t\tOpen_Door(1, 2);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * UnitClass::Crew_Type -- Fetches the kind of crew that this object produces.                 *\n *                                                                                             *\n *    When a unit is destroyed, a crew member might be generated. This routine will return     *\n *    with the infantry type to produce for this unit. This routine will be called for every   *\n *    survivor that is generated.                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a suggested infantry type to generate as a survivor from this unit.   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nInfantryType UnitClass::Crew_Type(void) const\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->PrimaryWeapon == NULL) {\n\t\tif (Percent_Chance(50)) {\n\t\t\treturn(INFANTRY_C1);\n\t\t} else {\n\t\t\treturn(INFANTRY_C7);\n\t\t}\n\t}\n\treturn(DriveClass::Crew_Type());\n}\n\n\n/***********************************************************************************************\n * UnitClass::Mission_Repair -- Handles finding and proceeding on a repair mission.            *\n *                                                                                             *\n *    This mission handler will look for a repair facility. If one is found then contact       *\n *    is established and then the normal Mission_Enter logic is performed. The repair facility *\n *    will take over the actual repair coordination process.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the number of game frames to delay before calling this routine again.      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint UnitClass::Mission_Repair(void)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tBuildingClass * nearest = Find_Docking_Bay(STRUCT_REFINERY, true);\n\n\tIsHarvesting = false;\n\n\t/*\n\t**\tIf there is no available repair facility, then check to see if there\n\t**\tare any repair facilities at all. If not, then enter this unit\n\t**\tinto idle state.\n\t*/\n\tif (nearest == NULL) {\n\t\tif (!(House->ActiveBScan & STRUCTF_REFINERY)) {\n\t\t\tEnter_Idle_Mode();\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tTry to establish radio contact with the repair facility. If contact\n\t\t**\twas established, then proceed with normal enter mission, which handles\n\t\t**\tthe repair process.\n\t\t*/\n\t\tif (Transmit_Message(RADIO_HELLO, nearest) == RADIO_ROGER) {\n\t\t\tAssign_Mission(MISSION_ENTER);\n\t\t\treturn(1);\n\t\t}\n\t}\n\n\t/*\n\t**\tIf no action could be performed at this time, then wait\n\t**\taround for a bit before trying again.\n\t*/\n\treturn(MissionControl[Mission].Normal_Delay());\n}\n\n\n/***********************************************************************************************\n * UnitClass::Fire_Direction -- Determines the direction of firing.                            *\n *                                                                                             *\n *    This routine will return with the facing that a projectile will travel if it was         *\n *    fired at this instant. The facing should match the turret facing for those units         *\n *    equipped with a turret. If the unit doesn't have a turret, then it will be the facing    *\n *    of the body.                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the default firing direction for a projectile.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nDirType UnitClass::Fire_Direction(void) const\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsTurretEquipped) {\n\t\tif (*this == UNIT_V2_LAUNCHER) {\n\t\t\tint diff1 = SecondaryFacing.Difference(DIR_E);\n\t\t\tint diff2 = SecondaryFacing.Difference(DIR_W);\n\t\t\tdiff1 = ABS(diff1);\n\t\t\tdiff2 = ABS(diff2);\n\t\t\tint diff = min(diff1, diff2);\n\t\t\tint adj = Fixed_To_Cardinal(ABS(SecondaryFacing.Difference(DIR_N)), 64-diff);\n\t\t\tif (SecondaryFacing.Difference(DIR_N) < 0) {\n\t\t\t\treturn(DirType)(SecondaryFacing - (DirType)adj);\n\t\t\t} else {\n\t\t\t\treturn(DirType)(SecondaryFacing + (DirType)adj);\n\t\t\t}\n\t\t}\n\t\treturn(SecondaryFacing.Current());\n\t}\n\n\treturn(DriveClass::Fire_Direction());\n}\n\n\n/***********************************************************************************************\n * UnitClass::Ok_To_Move -- Queries whether the vehicle can move.                              *\n *                                                                                             *\n *    This virtual routine is used to determine if the vehicle is allowed                      *\n *    to start moving. It is typically called when the vehicle desires                         *\n *    to move but needs confirmation from the turret logic before                              *\n *    proceeding. This happens when dealing with a vehicle that must have                      *\n *    its turret face the same direction as the body before the vehicle                        *\n *    may begin movement.                                                                      *\n *                                                                                             *\n * INPUT:   dir      -- The facing the unit wants to travel in.                                *\n *                                                                                             *\n * OUTPUT:  bool; Can the unit begin forward movement now?                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool UnitClass::Ok_To_Move(DirType dir) const\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsLockTurret) {\n\t\tif (IsRotating) {\n\t\t\treturn(false);\n\t\t} else {\n\t\t\tif (SecondaryFacing.Difference(dir)) {\n\t\t\t\t((UnitClass *)this)->SecondaryFacing.Set_Desired(dir);\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t}\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Can_Fire -- Determines if turret can fire upon target.                           *\n *                                                                                             *\n *    This routine determines if the turret can fire upon the target                           *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   target   -- The target to fire upon.                                               *\n *                                                                                             *\n *          which    -- Which weapon to use to determine legality to fire. 0=primary,          *\n *                      1=secondary.                                                           *\n *                                                                                             *\n * OUTPUT:  Returns the fire status type that indicates if firing is allowed and if not, why.  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/26/1994 JLB : Created.                                                                 *\n *   06/01/1994 JLB : Returns reason why it can't fire.                                        *\n *=============================================================================================*/\nFireErrorType UnitClass::Can_Fire(TARGET target, int which) const\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tDirType\t\t\tdir;\t\t\t\t\t// The facing to impart upon the projectile.\n\tint\t\t\t\tdiff;\n\tFireErrorType\tfire = DriveClass::Can_Fire(target, which);\n\n\tif (fire == FIRE_OK) {\n\t\tWeaponTypeClass const * weapon = (which == 0) ? Class->PrimaryWeapon : Class->SecondaryWeapon;\n\n\t\t/*\n\t\t**\tIf this unit cannot fire while moving, then bail.\n\t\t*/\n\t\tif ((Class->IsNoFireWhileMoving /*!Class->IsTurretEquipped || Class->IsLockTurret*/) && Target_Legal(NavCom)) {\n\t\t\treturn(FIRE_MOVING);\n\t\t}\n\n\t\t/*\n\t\t**\tIf the turret is rotating and the projectile isn't a homing type, then\n\t\t**\tfiring must be delayed until the rotation stops.\n\t\t*/\n\t\tif (!IsFiring && IsRotating && weapon->Bullet->ROT == 0) {\n\t\t\treturn(FIRE_ROTATING);\n\t\t}\n\n\t\tdir = Direction(target);\n\n\t\t/*\n\t\t**\tDetermine if the turret facing isn't too far off of facing the target.\n\t\t*/\n\t\tif (Class->IsTurretEquipped) {\n\t\t\tdiff = SecondaryFacing.Difference(dir);\n\t\t} else {\n\t\t\tdiff = PrimaryFacing.Difference(dir);\n\t\t}\n\t\tdiff = ABS(diff);\n\n\t\tif (weapon->Bullet->ROT != 0) {\n\t\t\tdiff >>= 2;\n\t\t}\n\t\tif (diff < 8) {\n\t\t\treturn(DriveClass::Can_Fire(target, which));\n\t\t}\n\t\treturn(FIRE_FACING);\n\t}\n\treturn(fire);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Fire_At -- Try to fire upon the target specified.                                *\n *                                                                                             *\n *    This routine is the auto-fire logic for the turret. It will check                        *\n *    to see if firing is technically legal given the specified target.                        *\n *    If it is legal to fire, it does so. It is safe to call this routine                      *\n *    every game tick.                                                                         *\n *                                                                                             *\n * INPUT:   target   -- The target to fire upon.                                               *\n *                                                                                             *\n *          which    -- Which weapon to use when firing. 0=primary, 1=secondary.               *\n *                                                                                             *\n * OUTPUT:  bool; Did firing occur?                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nBulletClass * UnitClass::Fire_At(TARGET target, int which)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tBulletClass * bullet = NULL;\n\tWeaponTypeClass const * weap = (which == 0) ? Class->PrimaryWeapon : Class->SecondaryWeapon;\n\tif (weap == NULL) return(NULL);\n\n\tif (Can_Fire(target, which) == FIRE_OK) {\n\t\tbullet = DriveClass::Fire_At(target, which);\n\n\t\tif (bullet != NULL) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nif(Class->Type == UNIT_DEMOTRUCK && IsActive) delete this;\n#endif\n\t\t\t/*\n\t\t\t**\tPossible reload timer set.\n\t\t\t*/\n\t\t\tif ((*this == UNIT_V2_LAUNCHER) && Reload == 0) {\n\t\t\t\tReload = TICKS_PER_SECOND * 30;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(bullet);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Class_Of -- Fetches a reference to the class type for this object.               *\n *                                                                                             *\n *    This routine will fetch a reference to the TypeClass of this object.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with reference to the type class of this object.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectTypeClass const & UnitClass::Class_Of(void) const\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(*Class);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Tiberium_Load -- Determine the Tiberium load as a percentage.                    *\n *                                                                                             *\n *    Use this routine to determine what the Tiberium load is (as a fixed point percentage).   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current \"fullness\" rating for the object.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed UnitClass::Tiberium_Load(void) const\n{\n\tassert(IsActive);\n\n\tif (*this == UNIT_HARVESTER) {\n\t\treturn(fixed(Tiberium, Rule.BailCount));\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Offload_Tiberium_Bail -- Offloads one Tiberium quantum from the object.          *\n *                                                                                             *\n *    This routine will offload one Tiberium packet/quantum/bail from the object. Multiple     *\n *    calls to this routine are needed in order to fully offload all Tiberium.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of credits offloaded for the one call. If zero is returned,*\n *          then this indicates that all Tiberium has been offloaded.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint UnitClass::Offload_Tiberium_Bail(void)\n{\n\tassert(IsActive);\n\n\tif (Tiberium) {\n\t\tTiberium--;\n#ifdef TOFIX\n\t\tif (House->IsHuman) {\n\t\t\treturn(UnitTypeClass::FULL_LOAD_CREDITS/UnitTypeClass::STEP_COUNT);\n\t\t}\n\t\treturn(UnitTypeClass::FULL_LOAD_CREDITS+(UnitTypeClass::FULL_LOAD_CREDITS/3)/UnitTypeClass::STEP_COUNT);\n#endif\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Approach_Target -- Handles approaching the target in order to attack it.         *\n *                                                                                             *\n *    This routine will check to see if the target is infantry and it can be overrun. It will  *\n *    try to overrun the infantry rather than attack it. This only applies to computer         *\n *    controlled vehicles. If it isn't the infantry overrun case, then it falls into the       *\n *    base class for normal (complex) approach algorithm.                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 JLB : Created.                                                                 *\n *   07/12/1995 JLB : Flamethrower tanks don't overrun -- their weapon is better.              *\n *=============================================================================================*/\nvoid UnitClass::Approach_Target(void)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tOnly if there is a legal target should the approach check occur.\n\t*/\n\tif (!House->IsHuman && Target_Legal(TarCom) && !Target_Legal(NavCom)) {\n\n\t\t/*\n\t\t**\tSpecial case:\n\t\t**\tIf this is for a unit that can crush infantry, and the target is\n\t\t**\tinfantry, AND the infantry is pretty darn close, then just try\n\t\t**\tto drive over the infantry instead of firing on it.\n\t\t*/\n\t\tTechnoClass * target = As_Techno(TarCom);\n\t\tif (Class->IsCrusher && Distance(TarCom) < Rule.CrushDistance && target && ((TechnoTypeClass const &)(target->Class_Of())).IsCrushable) {\n\t\t\tAssign_Destination(TarCom);\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/*\n\t**\tIn the other cases, uses the more complex \"get to just within weapon range\"\n\t**\talgorithm.\n\t*/\n\tDriveClass::Approach_Target();\n}\n\n\n/***********************************************************************************************\n * DriveClass::Overrun_Square -- Handles vehicle overrun of a cell.                            *\n *                                                                                             *\n *    This routine is called when a vehicle enters a square or when it is about to enter a     *\n *    square (controlled by parameter). When a vehicle that can crush infantry enters a        *\n *    cell that contains infantry, then the infantry will be destroyed (regardless of          *\n *    affiliation). When a vehicle threatens to overrun a square, all occupying infantry       *\n *    will attempt to get out of the way.                                                      *\n *                                                                                             *\n * INPUT:   cell     -- The cell that is, or soon will be, entered by a vehicle.               *\n *                                                                                             *\n *          threaten -- Don't kill, but just threaten to enter the cell.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitClass::Overrun_Square(CELL cell, bool threaten)\n{\n\tassert(IsActive);\n\n\tCellClass * cellptr = &Map[cell];\n\n\tif (Class->IsCrusher) {\n\t\tif (threaten) {\n\n\t\t\t/*\n\t\t\t**\tIf the cell contains infantry, then they will panic when a vehicle tries\n\t\t\t**\tdrive over them. Have the infantry run away instead.\n\t\t\t*/\n\t\t\tif (cellptr->Flag.Composite & 0x1F) {\n\n\t\t\t\t/*\n\t\t\t\t**\tScattering is controlled by the game difficulty level.\n\t\t\t\t*/\n\t\t\t\tcellptr->Incoming(0, true);\n\t\t\t}\n\t\t} else {\n\t\t\tObjectClass * object = cellptr->Cell_Occupier();\n\t\t\tint crushed = false;\n\t\t\twhile (object != NULL) {\n\t\t\t\tif (object->Class_Of().IsCrushable && !House->Is_Ally(object) && Distance(object->Center_Coord()) < CELL_LEPTON_W/2) {\n\n#ifdef OBSOLETE\n\t\t\t\t\t/*\n\t\t\t\t\t** If we're running over infantry, let's see if the infantry we're\n\t\t\t\t\t** squashing is a thief trying to capture us.  If so, let him succeed.\n\t\t\t\t\t*/\n\t\t\t\t\tif (object->What_Am_I() == RTTI_INFANTRY && *((InfantryClass *)object) == INFANTRY_THIEF && ((InfantryClass *)object)->NavCom == As_Target()) {\n\t\t\t\t\t\tObjectClass * next = object->Next;\n\t\t\t\t\t\tIsOwnedByPlayer = ((InfantryClass *)object)->IsOwnedByPlayer;\n\t\t\t\t\t\tHouse = ((InfantryClass *)object)->House;\n\t\t\t\t\t\tdelete object;\n\t\t\t\t\t\tobject = next;\n\t\t\t\t\t} else {\n#endif\n\t\t\t\t\t\tObjectClass * next = object->Next;\n\t\t\t\t\t\tcrushed = true;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Record credit for the kill(s)\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tSound_Effect(VOC_SQUISH, Coord);\n\t\t\t\t\t\tif (object->Height == 0) {\n\t\t\t\t\t\t\tnew AnimClass(ANIM_CORPSE1, object->Center_Coord());\n\t\t\t\t\t\t}\n\t\t\t\t\t\tobject->Record_The_Kill(this);\n\t\t\t\t\t\tobject->Mark(MARK_UP);\n\t\t\t\t\t\tobject->Limbo();\n\t\t\t\t\t\tdelete object;\n\t\t\t\t\t\t//new OverlayClass(OVERLAY_SQUISH, Coord_Cell(Coord));\n\n\t\t\t\t\t\tobject = next;\n#ifdef OBSOLETE\n\t\t\t\t\t}\n#endif\n\t\t\t\t} else {\n\t\t\t\t\tobject = object->Next;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (crushed) Do_Uncloak();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * UnitClass::Assign_Destination -- Assign a destination to a unit.                            *\n *                                                                                             *\n *    This will assign the specified destination to the unit. It is presumed that doing is     *\n *    is all that is needed in order to cause the unit to move to the specified destination.   *\n *                                                                                             *\n * INPUT:   target   -- The target (location) to move to.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitClass::Assign_Destination(TARGET target)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tAbort early if there is anything wrong with the parameters\n\t**\tor the unit already is assigned the specified destination.\n\t*/\n\tif (target == NavCom) return;\n\n\t/*\n\t**\tTransport vehicles must tell all passengers that are about to load, that they\n\t**\tcannot proceed. This is accomplished with a radio message to this effect.\n\t*/\n\tif (In_Radio_Contact() && Class->Max_Passengers() > 0 && Contact_With_Whom()->Is_Infantry()) {\n\t\tTransmit_Message(RADIO_OVER_OUT);\n\t}\n\n\tBuildingClass * b = As_Building(target);\n\n\t/*\n\t**\tHandle entry logic here.\n\t*/\n\tif (Mission == MISSION_ENTER || MissionQueue == MISSION_ENTER) {\n\n\t\t/*\n\t\t**\tIf not already in radio contact (presumed with the transport), then\n\t\t**\teither try to establish contact if allowed, or just move close and\n\t\t**\twait until radio contact can be established.\n\t\t*/\n\t\tif (!In_Radio_Contact()) {\n\t\t\tif (b != NULL) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDetermine if the transport is already in radio contact. If so, then just move\n\t\t\t\t**\ttoward the transport and try to establish contact at a later time.\n\t\t\t\t*/\n\t\t\t\tif (b->In_Radio_Contact()) {\n// TCTCTC -- call for an update from the transport to get a good rendezvous position.\n\t\t\t\t\tArchiveTarget = target;\n\n/*\n**\tHACK ALERT: The repair bay is counting on the assignment of the NavCom by this routine.\n**\tThe refinery must NOT have the navcom assigned by this routine.\n*/\nif (*b != STRUCT_REPAIR) {\n\ttarget = TARGET_NONE;\n}\n\t\t\t\t} else {\n\t\t\t\t\tif (Transmit_Message(RADIO_DOCKING, b) != RADIO_ROGER) {\n\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t\tif (*b == STRUCT_REPAIR) {\n\t\t\t\t\t\t\tArchiveTarget = target;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\nif (*b != STRUCT_REPAIR) {\n\tArchiveTarget = target;\n//\ttarget = TARGET_NONE;\n}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tTechnoClass * techno = As_Techno(target);\n\t\t\t\tif (techno != NULL) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDetermine if the transport is already in radio contact. If so, then just move\n\t\t\t\t\t**\ttoward the transport and try to establish contact at a later time.\n\t\t\t\t\t*/\n\t\t\t\t\tif (techno->In_Radio_Contact()) {\n\t// TCTCTC -- call for an update from the transport to get a good rendezvous position.\n\n\t\t\t\t\t\tArchiveTarget = target;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (Transmit_Message(RADIO_HELLO, techno) == RADIO_ROGER) {\n\t\t\t\t\t\t\tif (Transmit_Message(RADIO_DOCKING) != RADIO_ROGER) {\n\t\t\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t//BG: keep retransmitted navcom from radio-move-here.\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\t\t} else {\n\t\t\tPath[0] = FACING_NONE;\n\t\t}\n\t} else {\n\t\tPath[0] = FACING_NONE;\n\t}\n\n\t/*\n\t**\tIf the player clicked on a friendly repair facility and the repair\n\t**\tfacility is currently not involved with some other unit (radio or unloading).\n\t*/\n\tif (b != NULL && *b == STRUCT_REPAIR) {\n\t\tif (b->In_Radio_Contact() && (b->Contact_With_Whom() != this) ) {\n//\t\t\tif (target != NULL) {\n\t\t\t\tArchiveTarget = target;\n//\t\t\t}\n//\t\t\ttarget = TARGET_NONE;\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tEstablish radio contact protocol. If the facility responds correctly,\n\t\t\t**\tthen remain in radio contact and proceed toward the desired destination.\n\t\t\t*/\n\t\t\tif (Transmit_Message(RADIO_HELLO, b) == RADIO_ROGER) {\n\n\t\t\t\t/*\n\t\t\t\t**\tLast check to make sure that the loading square is free from permanent\n\t\t\t\t**\toccupation (such as a building).\n\t\t\t\t*/\n\t\t\t\tCELL cell = (CELL)(Coord_Cell(b->Center_Coord()) + (MAP_CELL_W-1));\n\t\t\t\tif (Ground[Map[cell].Land_Type()].Cost[Techno_Type_Class()->Speed] > 0) {\n\t\t\t\t\tif (Transmit_Message(RADIO_DOCKING) == RADIO_ROGER) {\n\t\t\t\t\t\tFootClass::Assign_Destination(target);\n\t\t\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tFailure to establish a docking relationship with the refinery.\n\t\t\t\t\t**\tBail & await further instructions.\n\t\t\t\t\t*/\n\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tDriveClass::Assign_Destination(target);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Greatest_Threat -- Fetches the greatest threat for this unit.                    *\n *                                                                                             *\n *    This routine will search the map looking for a good target to attack. It takes into      *\n *    consideration the type of weapon it is equipped with.                                    *\n *                                                                                             *\n * INPUT:   threat   -- The threat type to search for.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with a target value of the target that this unit should pursue. If there   *\n *          is no suitable target, then TARGET_NONE is returned.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTARGET UnitClass::Greatest_Threat(ThreatType threat) const\n{\n\tassert(IsActive);\n\tif (Class->PrimaryWeapon != NULL) {\n\t\tthreat = threat | Class->PrimaryWeapon->Allowed_Threats();\n\t}\n\tif (Class->SecondaryWeapon != NULL) {\n\t\tthreat = threat | Class->SecondaryWeapon->Allowed_Threats();\n\t}\n\n#ifdef OBSOLETE\n\tif (House->IsHuman) {\n\t\tthreat = threat & ~THREAT_BUILDINGS;\n\t}\n#endif\n\n\treturn(FootClass::Greatest_Threat(threat));\n}\n\n\n/***********************************************************************************************\n * UnitClass::Read_INI -- Reads units from scenario INI file.                                  *\n *                                                                                             *\n *    This routine is used to read all the starting units from the                             *\n *    scenario control INI file. The units are created and placed on the                       *\n *    map by this routine.                                                                     *\n *                                                                                             *\n *    INI entry format:                                                                        *\n *      Housename, Typename, Strength, Coord, Facingnum, Missionname, Triggername              *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the loaded scenario INI file.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitClass::Read_INI(CCINIClass & ini)\n{\n\tUnitClass\t* unit;\t\t\t// Working unit pointer.\n\tHousesType\tinhouse;\t\t\t// Unit house.\n\tUnitType\t\tclassid;\t\t\t// Unit class.\n\tchar\t\t\tbuf[128];\n\n\tint len = ini.Entry_Count(INI_Name());\n\n\tfor (int index = 0; index < len; index++) {\n\t\tchar const * entry = ini.Get_Entry(INI_Name(), index);\n\n\t\tini.Get_String(INI_Name(), entry, NULL, buf, sizeof(buf));\n\n\t\tinhouse = HouseTypeClass::From_Name(strtok(buf, \",\"));\n\t\tif (inhouse != HOUSE_NONE) {\n\t\t\tclassid = UnitTypeClass::From_Name(strtok(NULL, \",\"));\n\n\t\t\tif (classid != UNIT_NONE) {\n\n\t\t\t\tunit = new UnitClass(classid, inhouse);\n\t\t\t\tif (unit != NULL) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tRead the raw data.\n\t\t\t\t\t*/\n\t\t\t\t\tint strength = atoi(strtok(NULL, \",\\r\\n\"));\n\n\t\t\t\t\tCELL cell = atoi(strtok(NULL, \",\\r\\n\"));\n\n\t\t\t\t\tCOORDINATE coord = Cell_Coord(cell);\n\n\t\t\t\t\tDirType dir = (DirType)atoi(strtok(NULL, \",\\r\\n\"));\n\t\t\t\t\tMissionType mission = MissionClass::Mission_From_Name(strtok(NULL, \",\\n\\r\"));\n\n\t\t\t\t\tunit->Trigger = NULL;\n\t\t\t\t\tTriggerTypeClass * tp = TriggerTypeClass::From_Name(strtok(NULL,\",\\r\\n\"));\n\t\t\t\t\tif (tp != NULL) {\n\t\t\t\t\t\tTriggerClass * tt = Find_Or_Make(tp);\n\t\t\t\t\t\tif (tt != NULL) {\n\t\t\t\t\t\t\ttt->AttachCount++;\n\t\t\t\t\t\t\tunit->Trigger = tt;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (unit->Unlimbo(coord, dir)) {\n\t\t\t\t\t\tunit->Strength = unit->Class->MaxStrength * fixed(strength, 256);\n\t\t\t\t\t\tif (unit->Strength > unit->Class->MaxStrength-3) unit->Strength = unit->Class->MaxStrength;\n\t\t\t\t\t\tif (Session.Type == GAME_NORMAL || unit->House->IsHuman) {\n\t\t\t\t\t\t\tunit->Assign_Mission(mission);\n\t\t\t\t\t\t\tunit->Commence();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tunit->Enter_Idle_Mode();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf the unit could not be unlimboed, then this is a catastrophic error\n\t\t\t\t\t\t**\tcondition. Delete the unit.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tdelete unit;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * UnitClass::Write_INI -- Store the units to the INI database.                                *\n *                                                                                             *\n *    This routine will store all the unit data to the INI database.                           *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database object to store to.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitClass::Write_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tFirst, clear out all existing unit data from the ini file.\n\t*/\n\tini.Clear(INI_Name());\n\n\t/*\n\t**\tWrite the unit data out.\n\t*/\n\tfor (int index = 0; index < Units.Count(); index++) {\n\t\tUnitClass * unit = Units.Ptr(index);\n\t\tif (unit != NULL && !unit->IsInLimbo && unit->IsActive) {\n\t\t\tchar\tuname[10];\n\t\t\tchar\tbuf[128];\n\n\t\t\tsprintf(uname, \"%d\", index);\n\t\t\tsprintf(buf, \"%s,%s,%d,%u,%d,%s,%s\",\n\t\t\t\tunit->House->Class->IniName,\n\t\t\t\tunit->Class->IniName,\n\t\t\t\tunit->Health_Ratio()*256,\n\t\t\t\tCoord_Cell(unit->Coord),\n\t\t\t\tunit->PrimaryFacing.Current(),\n\t\t\t\tMissionClass::Mission_Name(unit->Mission),\n\t\t\t\tunit->Trigger.Is_Valid() ? unit->Trigger->Class->IniName : \"None\"\n\t\t\t\t);\n\t\t\tini.Put_String(INI_Name(), uname, buf);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * UnitClass::Credit_Load -- Fetch the full credit value of cargo carried.                     *\n *                                                                                             *\n *    This will determine the value of the cargo carried (limited to considering only gold     *\n *    and gems) and return that value. Use this to determine how 'valuable' a harvester is.    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the credit value of the cargo load of this unit (harvester).          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint UnitClass::Credit_Load(void) const\n{\n\treturn((Gold * Rule.GoldValue) + (Gems * Rule.GemValue));\n}\n\n\n/***********************************************************************************************\n * UnitClass::Should_Crush_It -- Determines if this unit should crush an object.               *\n *                                                                                             *\n *    Call this routine to determine if this unit should crush the object specified. The       *\n *    test for crushable action depends on proximity and ability of the unit. If a unit        *\n *    should crush the object, then it should be given a movement order to enter the cell      *\n *    where the object is located.                                                             *\n *                                                                                             *\n * INPUT:   it -- The object to see if it should be crushed.                                   *\n *                                                                                             *\n * OUTPUT:  bool; Should \"it\" be crushed by this unit?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool UnitClass::Should_Crush_It(TechnoClass const * it) const\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tIf this unit cannot crush anything or the candidate object cannot be crushed,\n\t**\tthen it obviously should not try to crush it -- return negative answer.\n\t*/\n\tif (!Class->IsCrusher || it == NULL || !it->Techno_Type_Class()->IsCrushable) return(false);\n\n\t/*\n\t**\tObjects that are far away should really be fired upon rather than crushed.\n\t*/\n\tif (Distance(it) > Rule.CrushDistance) return(false);\n\n\t/*\n\t**\tHuman controlled units don't automatically crush. Neither do computer controlled ones\n\t**\tif they are at difficult setting.\n\t*/\n\tif (House->IsHuman || House->Difficulty == DIFF_HARD) return(false);\n\n\t/*\n\t**\tIf the weapon this unit is equipped with is very good against crushable objects then\n\t**\tfire the weapon instead. It is presumed that a wood destroying weapon is good against\n\t**\tmost crushable object types (infantry).\n\t*/\n\tif (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->WarheadPtr->IsWoodDestroyer) return(false);\n\n\t/*\n\t**\tIf the house IQ indicates that crushing should not be allowed, then don't\n\t**\tsuggest that crushing be done.\n\t*/\n\tif (House->IQ < Rule.IQCrush) return(false);\n\n\t/*\n\t** Don't allow crushing of spies by computer-controlled vehicles.\n\t*/\n\tif (it->What_Am_I() == RTTI_INFANTRY && *(InfantryClass *)it == INFANTRY_SPY) {\n\t\treturn(false);\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * UnitClass::Scatter -- Causes the unit to scatter to a nearby location.                      *\n *                                                                                             *\n *    This scatter logic will actually look for a nearby location rather than an adjacent      *\n *    free location. This is necessary because sometimes a unit is required to scatter more    *\n *    than one cell. A vehicle on a service depot is a prime example.                          *\n *                                                                                             *\n * INPUT:   threat   -- The coordinate that a potential threat resides. If this is a non       *\n *                      threat related scatter, then this parameter will be zero.              *\n *                                                                                             *\n *          forced   -- Should the scatter be performed even if it would be otherwise          *\n *                      inconvenient?                                                          *\n *                                                                                             *\n *          nokidding-- Should the scatter be performed even if it would otherwise be          *\n *                      illegal?                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid UnitClass::Scatter(COORDINATE threat, bool forced, bool nokidding)\n{\n\tassert(IsActive);\n\n\tif (Mission == MISSION_SLEEP || Mission == MISSION_STICKY || Mission == MISSION_UNLOAD) return;\n\n\t/*\n\t**\tCertain missions prevent scattering regardless of whether it would be\n\t**\ta good idea or not.\n\t*/\n\tif (!MissionControl[Mission].IsScatter && !forced) return;\n\n\tif (PrimaryFacing.Is_Rotating()) return;\n//\tif (IsRotating) return;\n\n\tif (Target_Legal(NavCom) && !nokidding) return;\n\n\tif (threat == 0) {\n\t\tAssign_Destination(::As_Target(Map.Nearby_Location(Coord_Cell(Coord), Class->Speed)));\n\t} else {\n\t\tDriveClass::Scatter(threat, forced, nokidding);\n\t}\n}\n\n\n/***********************************************************************************************\n * UnitClass::Limbo -- Limbo this unit.                                                        *\n *                                                                                             *\n *    This will cause the unit to go into a limbo state. If it was carrying a flag, then       *\n *    the flag will be dropped where the unit is at.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was this unit limboed?                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool UnitClass::Limbo(void)\n{\n\tif (DriveClass::Limbo()) {\n\t\tif (Flagged != HOUSE_NONE) {\n\t\t\tHouseClass::As_Pointer(Flagged)->Flag_Attach(Coord_Cell(Coord));\n\t\t\tFlagged = HOUSE_NONE;\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\nvoid UnitClass::Shroud_Regen(void)\n{\n\tif (Class->IsGapper/*KO && !House->IsPlayerControl*/) {\n\t\tstatic int _xtab[]={\n\t\t\t   -1, 0, 1,\n\t\t\t-2,-1, 0, 1, 2,\n\t\t\t-2,-1, 0, 1, 2,\n\t\t\t-2,-1, 0, 1, 2,\n\t\t\t-2,-1, 0, 1, 2,\n\t\t\t-2,-1, 0, 1, 2,\n\t\t\t   -1, 0, 1\n\t\t};\n\t\tstatic int _ytab[]={\n\t\t\t   -3,-3,-3,\n\t\t\t-2,-2,-2,-2,-2,\n\t\t\t-1,-1,-1,-1,-1,\n\t\t\t 0, 0, 0, 0, 0,\n\t\t\t 1, 1, 1, 1, 1,\n\t\t\t 2, 2, 2, 2, 2,\n\t\t\t    3, 3, 3\n\t\t};\n\t\tint index;\n\t\tint centerx, centery;\n\t\tCELL trycell;\n\n\t\t// Only restore under the shroud if it's a valid field.\n\t\tif (ShroudBits != (unsigned)-1L) {\n\t\t\tcenterx = Cell_X(ShroudCenter);\n\t\t\tcentery = Cell_Y(ShroudCenter);\n\t\t\tfor (index = 30; index >= 0 && ShroudBits; index--) {\n\t\t\t\tif (ShroudBits & 1) {\n\t\t\t\t\ttrycell = XY_Cell(centerx + _xtab[index], centery + _ytab[index]);\n#if(0)\n\t\t\t\t\tMap.Map_Cell(trycell, PlayerPtr);\n#else\n\t\t\t\tMap.UnJam_Cell(trycell, House);\n\t\t\t\tMap.Map_Cell(trycell, PlayerPtr);\n#endif\n\t\t\t\t}\n\t\t\t\tShroudBits >>= 1;\n\t\t\t}\n\t\t}\n\n\t\tif(IsActive && Strength) {\n\t\t\t// Now shroud around the new center\n\t\t\tShroudBits = 0L;\n\t\t\tShroudCenter = Coord_Cell(Center_Coord());\n\t\t\tcenterx = Cell_X(ShroudCenter);\n\t\t\tcentery = Cell_Y(ShroudCenter);\n\t\t\tfor (index = 0; index < 31; index++) {\n\t\t\t\tShroudBits <<= 1;\n\t\t\t\ttrycell = XY_Cell(centerx + _xtab[index], centery + _ytab[index]);\n\t\t\t\tif (Map[trycell].IsMapped) {\n#if(0)\n\t\t\t\t\tMap.Shroud_Cell(trycell);\n#else\n\t\t\t\tMap.Jam_Cell(trycell, House);\n#endif\n\t\t\t\t\tShroudBits |= 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!House->IsPlayerControl) {\n\t\t\tMap.Constrained_Look(Coord, 5 * CELL_LEPTON_W);\n//\t\t\tPlayerPtr->IsToLook = true;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * UnitClass::Mission_Guard_Area -- Guard area logic for units.                                *\n *                                                                                             *\n *    This logic is similar to normal guard area except that APCs owned by the computer will   *\n *    try to load up with nearby infantry. This will give the computer some fake intelligence  *\n *    when playing in skirmish mode.                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay to use before calling this routine again.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint UnitClass::Mission_Guard_Area(void)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tCheck to see if this is an APC that is largely empty and not otherwise doing anything.\n\t**\tSuch an APC should load up with infantry.\n\t*/\n\tif (Session.Type != GAME_NORMAL &&\n#ifdef FIXIT_PHASETRANSPORT\t//\tchecked - ajw 9/28/98\n\t\t\t(*this == UNIT_APC || *this == UNIT_PHASE ) &&\n#else\n\t\t\t*this == UNIT_APC &&\n#endif\n\t\t\t!Target_Legal(TarCom) &&\n\t\t\t!In_Radio_Contact() &&\n\t\t\tHouse->Which_Zone(this) != ZONE_NONE &&\n\t\t\t!House->IsHuman) {\n\n\n\t\tint needed = Class->Max_Passengers() - How_Many();\n\t\tfor (int index = 0; index < Infantry.Count(); index++) {\n\t\t\tif (needed == 0) break;\n\n\t\t\tInfantryClass * infantry = Infantry.Ptr(index);\n\n\t\t\tif (infantry != NULL &&\n\t\t\t\t\tinfantry->IsActive &&\n\t\t\t\t\t!infantry->IsInLimbo &&\n\t\t\t\t\tinfantry->Strength > 0 &&\n\t\t\t\t\tinfantry->House == House &&\n\t\t\t\t\t!Target_Legal(infantry->TarCom) &&\n\t\t\t\t\t!Target_Legal(infantry->NavCom) &&\n\t\t\t\t\tDistance(infantry) < 7 * CELL_LEPTON_W &&\n\t\t\t\t\t(infantry->Mission == MISSION_GUARD || infantry->Mission == MISSION_GUARD_AREA)) {\n\n\t\t\t\tinfantry->Assign_Mission(MISSION_ENTER);\n\t\t\t\tinfantry->ArchiveTarget = As_Target();\n\t\t\t\tneeded--;\n\t\t\t}\n\t\t}\n\t}\n\treturn(DriveClass::Mission_Guard_Area());\n}\n"
  },
  {
    "path": "CODE/UNIT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/UNIT.H 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : UNIT.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 14, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 14, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef UNIT_H\n#define UNIT_H\n\n#include \"drive.h\"\n#include \"radio.h\"\n#include \"cargo.h\"\n#include \"mission.h\"\n#include\t\"target.h\"\n\n\n/****************************************************************************\n**\tFor each instance of a unit (vehicle) in the game, there is one of\n**\tthese structures. This structure holds information that is specific\n**\tand dynamic for a particular unit.\n*/\nclass UnitClass :\tpublic DriveClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tThis points to the static control data that gives 'this' unit its characteristics.\n\t\t*/\n\t\tCCPtr<UnitTypeClass> Class;\n\n\t\t/*\n\t\t**\tThis records the house flag that this object is currently carrying.\n\t\t*/\n\t\tHousesType Flagged;\n\n\t\t/*\n\t\t** This flag is used for when the harvester dumps ore, to track its\n\t\t** special animation.\n\t\t*/\n\t\tunsigned IsDumping:1;\n\n\t\t/*\n\t\t** This is a count of the # of loads of the various minerals that the\n\t\t** unit has harvested.\n\t\t*/\n\t\tunsigned Gold:5;\n\t\tunsigned Gems:5;\n\n\t\t/*\n\t\t** This flag tells a unit that, if after reaching its destination, it\n\t\t** should scatter away.  It's meant to help a LST unload its units by\n\t\t** having its previous passengers get out of the way.\n\t\t*/\n\t\tunsigned IsToScatter:1;\n\n\t\t/*\n\t\t**\tThis records the number of \"loads\" of Tiberium the unit is carrying. Only\n\t\t**\tharvesters use this field.\n\t\t*/\n\t\tint Tiberium;\n\n\t\t/*\n\t\t** This is the area where a mobile gap generator stores the previously-held\n\t\t** shroud values for the cells surrounding itself.\n\t\t*/\n\t\tunsigned long ShroudBits;\n\n\t\t/*\n\t\t** This is the center coordinate for the mobile gap generator, as to\n\t\t** what cells should be revealed (according to ShroudBits)\n\t\t*/\n\t\tCELL ShroudCenter;\n\n\t\t/*\n\t\t**\tThis is the timer that controls the reload rate. The MSAM rocket\n\t\t**\tlauncher is the primary user of this.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> Reload;\n\n\t\t/*\n\t\t**\tThis is the facing of the turret. It can be, and usually is,\n\t\t**\trotated independently of the body it is attached to.\n\t\t*/\n\t\tFacingClass SecondaryFacing;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\t\tUnitClass(UnitType classid, HousesType house);\n\t\tUnitClass(NoInitClass const & x) : DriveClass(x), Class(x), Reload(x), SecondaryFacing(x) {};\n\t\toperator UnitType(void) const {return Class->Type;};\n\t\tvirtual ~UnitClass(void);\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const;\n\t\tstatic void Init(void);\n\n\t\tbool Goto_Clear_Spot(void);\n\t\tbool Try_To_Deploy(void);\n\t\tvirtual void Scatter(COORDINATE threat, bool forced=false, bool nokidding=false);\n\n\t\tbool Tiberium_Check(CELL &center, int x, int y);\n\t\tbool Flag_Attach(HousesType house);\n\t\tbool Flag_Remove(void);\n\t\tbool Goto_Tiberium(int radius);\n\t\tbool Harvesting(void);\n\t\tvoid APC_Close_Door(void);\n\t\tvoid APC_Open_Door(void);\n\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tbool Should_Crush_It(TechnoClass const * it) const;\n\t\tint Credit_Load(void) const;\n\t\tvirtual DirType Turret_Facing(void) const {if (Class->IsTurretEquipped) return(SecondaryFacing.Current());return(PrimaryFacing.Current());}\n\t\tint Shape_Number(void) const;\n\t\tvirtual int Pip_Count(void) const;\n\t\tvirtual InfantryType Crew_Type(void) const;\n\t\tvirtual DirType Fire_Direction(void) const;\n\t\tvirtual bool Ok_To_Move(DirType facing) const;\n\t\tvirtual FireErrorType Can_Fire(TARGET target, int which) const;\n\t\tvirtual fixed Tiberium_Load(void) const;\n\n\t\t/*\n\t\t**\tCoordinate inquiry functions. These are used for both display and\n\t\t**\tcombat purposes.\n\t\t*/\n\t\tvirtual COORDINATE Sort_Y(void) const;\n\n\t\t/*\n\t\t**\tObject entry and exit from the game system.\n\t\t*/\n\t\tvirtual bool Limbo(void);\n\t\tvirtual bool Unlimbo(COORDINATE , DirType facing=DIR_N);\n\n\t\t/*\n\t\t**\tDisplay and rendering support functionality. Supports imagery and how\n\t\t**\tobject interacts with the map and thus indirectly controls rendering.\n\t\t*/\n\t\tvirtual short const * Overlap_List(bool redraw=false) const;\n\t\tvirtual void Draw_It(int x, int y, WindowNumberType window) const;\n\n\t\t/*\n\t\t**\tUser I/O.\n\t\t*/\n\t\tvirtual ActionType What_Action(CELL cell) const;\n\t\tvirtual ActionType What_Action(ObjectClass const * object) const;\n\t\tvirtual void Active_Click_With(ActionType action, ObjectClass * object);\n\t\tvirtual void Active_Click_With(ActionType action, CELL cell);\n\n\t\t/*\n\t\t**\tCombat related.\n\t\t*/\n\t\tvirtual ResultType Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source=0, bool forced=false);\n\t\tvirtual BulletClass * Fire_At(TARGET target, int which=0);\n\n\t\t/*\n\t\t**\tDriver control support functions. These are used to control cell\n\t\t**\toccupation flags and driver instructions.\n\t\t*/\n\t\tvirtual bool Start_Driver(COORDINATE & coord);\n\n\t\t/*\n\t\t**\tAI.\n\t\t*/\n\t\tvirtual TARGET Greatest_Threat(ThreatType threat) const;\n\t\tvirtual DirType Desired_Load_Dir(ObjectClass * passenger, CELL & moveto) const;\n\t\tvirtual RadioMessageType Receive_Message(RadioClass * from, RadioMessageType message, long & param);\n\t\tvirtual void AI(void);\n\t\tvirtual int Mission_Guard_Area(void);\n\t\tvirtual int Mission_Unload(void);\n\t\tvirtual int Mission_Guard(void);\n\t\tvirtual int Mission_Harvest(void);\n\t\tvirtual int Mission_Hunt(void);\n\t\tvirtual int Mission_Repair(void);\n\t\tvirtual int Mission_Move(void);\n\t\tvoid Rotation_AI(void);\n\t\tvoid Firing_AI(void);\n\t\tvoid Reload_AI(void);\n\t\tbool Edge_Of_World_AI(void);\n\n\t\t/*\n\t\t**\tScenario and debug support.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\n\t\t/*\n\t\t**\tMovement and animation.\n\t\t*/\n\t\tvirtual void Assign_Destination(TARGET target);\n\t\tvirtual void Overrun_Square(CELL cell, bool threaten=true);\n\t\tvirtual void Approach_Target(void);\n\t\tvirtual int Offload_Tiberium_Bail(void);\n\t\tvirtual void Enter_Idle_Mode(bool initial=false);\n\t\tvirtual MoveType Can_Enter_Cell(CELL cell, FacingType facing=FACING_NONE) const;\n\t\tvirtual void Per_Cell_Process(PCPType why);\n\t\tvoid Exit_Repair(void);\n\t\tvoid Shroud_Regen(void);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tstatic void Read_INI(CCINIClass & ini);\n\t\tstatic void Write_INI(CCINIClass & ini);\n\t\tstatic char *INI_Name(void) {return \"UNITS\";};\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/UTRACKER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : UTRACKER.CPP                             *\n *                                                                         *\n *                   Programmer : Steve Tall                               *\n *                                                                         *\n *                   Start Date : June 3rd, 1996                           *\n *                                                                         *\n *                  Last Update : June 7th, 1996 [ST]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *  The UnitTracker class exists to track the various statistics           *\n *   required for internet games.                                          *\n *                                                                         *\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n *                                                                         *\n *  Functions:                                                             *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\n#include \"function.h\"\n\n/*\n** Define host to network to host functions for DOS\n*/\n#ifndef WIN32\n\n#define htonl(val) 0\n#define ntohl(val) 0\n\n#endif\t//WIN32\n\n\n/***********************************************************************************************\n * UTC::UnitTrackerClass -- Class constructor                                                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Number of unit types to reserve space for                                         *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/7/96 0:10AM ST : Created                                                               *\n *=============================================================================================*/\nUnitTrackerClass::UnitTrackerClass (int unit_count)\n{\n\tUnitTotals = new long [unit_count];\t\t// Allocate memory for the unit totals\n\tUnitCount = unit_count;\t\t\t\t\t\t// Keep a record of how many unit entries there are\n\tInNetworkFormat = 0;\t\t\t\t\t\t\t// The unit entries are in host format\n\tClear_Unit_Total();\t\t\t\t\t\t\t// Clear each entry\n}\n\n\n/***********************************************************************************************\n * UTC::~UnitTrackerClass -- Class destructor                                                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/7/96 0:10AM ST : Created                                                               *\n *=============================================================================================*/\nUnitTrackerClass::~UnitTrackerClass (void)\n{\n\tdelete UnitTotals;\n}\n\n\n\n/***********************************************************************************************\n * UTC::Increment_Unit_Total -- Increment the total for the specefied unit                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Unit number                                                                       *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/7/96 0:12AM ST : Created                                                               *\n *=============================================================================================*/\nvoid UnitTrackerClass::Increment_Unit_Total(int unit_type)\n{\n\tUnitTotals[unit_type]++;\n}\n\n\n/***********************************************************************************************\n * UTC::Decrement_Unit_Total -- Decrement the total for the specefied unit                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Unit number                                                                       *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/7/96 0:13AM ST : Created                                                               *\n *=============================================================================================*/\nvoid UnitTrackerClass::Decrement_Unit_Total(int unit_type)\n{\n\tUnitTotals[unit_type]--;\n}\n\n\n/***********************************************************************************************\n * UTC::Get_All_Totals -- Returns a pointer to the start of the unit totals list               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Ptr to unit totals list                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/7/96 0:13AM ST : Created                                                               *\n *=============================================================================================*/\nlong *UnitTrackerClass::Get_All_Totals (void)\n{\n\treturn (UnitTotals);\n}\n\n\n/***********************************************************************************************\n * UTC::Clear_Unit_Total -- Clear out all the unit totals                                      *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/7/96 0:14AM ST : Created                                                               *\n *=============================================================================================*/\nvoid UnitTrackerClass::Clear_Unit_Total (void)\n{\n\tmemset (UnitTotals, 0, UnitCount * sizeof(long) );\n}\n\n\n\n/***********************************************************************************************\n * UTC::To_Network_Format -- Changes all unit totals to network format for the internet        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/7/96 0:15AM ST : Created                                                               *\n *=============================================================================================*/\nvoid UnitTrackerClass::To_Network_Format (void)\n{\n\tif (!InNetworkFormat){\n\t\tfor (int i=0 ; i<UnitCount ; i++){\n\t\t\tUnitTotals[i] = htonl (UnitTotals[i]);\n\t\t}\n\t}\n\tInNetworkFormat = 1;\t\t// Flag that data is now in network format\n}\n\n\n/***********************************************************************************************\n * UTC::To_PC_Format -- Changes all unit totals to PC format from network format               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/7/96 0:15AM ST : Created                                                               *\n *=============================================================================================*/\nvoid UnitTrackerClass::To_PC_Format (void)\n{\n\tif (InNetworkFormat){\n\t\tfor (int i=0 ; i<UnitCount ; i++){\n\t\t\tUnitTotals[i] = ntohl (UnitTotals[i]);\n\t\t}\n\t}\n\tInNetworkFormat = 0;\t\t// Flag that data is now in PC format\n}\n\n\n"
  },
  {
    "path": "CODE/UTRACKER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : UTRACKER.H                               *\n *                                                                         *\n *                   Programmer : Steve Tall                               *\n *                                                                         *\n *                   Start Date : June 3rd, 1996                           *\n *                                                                         *\n *                  Last Update : June 7th, 1996 [ST]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *  The UnitTracker class exists to track the various statistics           *\n *   required for internet games.                                          *\n *                                                                         *\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\n/*\n** UnitTracker Class\n*/\n\nclass\tUnitTrackerClass {\n\n\tpublic:\n\n\t\tUnitTrackerClass(int unit_count);\n\t\t~UnitTrackerClass(void);\n\n\t\tvoid \tIncrement_Unit_Total (int unit_type);\n\t\tvoid \tDecrement_Unit_Total (int unit_type);\n\t\tvoid\tClear_Unit_Total(void);\n\n\t\tint \tGet_Unit_Total (int unit_type);\n\t\tlong *Get_All_Totals (void);\n\t\tint\tGet_Unit_Count (void){return (UnitCount);};\n\n\t\tvoid\tTo_Network_Format(void);\n\t\tvoid\tTo_PC_Format(void);\n\n\tprivate:\n\n\t\tlong\t*UnitTotals;\n\t\tint\tUnitCount;\n\t\tint\tInNetworkFormat;\n\n};\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "CODE/VDATA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/VDATA.CPP 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : VDATA.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/13/96                                                     *\n *                                                                                             *\n *                  Last Update : July 9, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   VesselTypeClass::As_Reference -- Converts a vessel type into a VesselTypeClass reference. *\n *   VesselTypeClass::Create_And_Place -- Creates a vessel and places it at location.          *\n *   VesselTypeClass::Create_One_Of -- Creates a vessel object that matches this vessel type.  *\n *   VesselTypeClass::Dimensions -- Fetches the pixel width and height of this vessel type.    *\n *   VesselTypeClass::Display -- Displays a generic representation of this vessel type.        *\n *   VesselTypeClass::From_Name -- Converts a name into a vessel type.                         *\n *   VesselTypeClass::Init_Heap -- Initialize the vessel heap.                                 *\n *   VesselTypeClass::One_Time -- Performs one time initialization for vessel types.           *\n *   VesselTypeClass::Overlap_List -- Figures the overlap list for the vessel type.            *\n *   VesselTypeClass::Prep_For_Add -- Adds vessel types to the scenario editor object list.    *\n *   VesselTypeClass::Turret_Adjust -- Adjust turret offset according to facing specified.     *\n *   VesselTypeClass::VesselTypeClass -- Constructor for naval vessel types.                   *\n *   VesselTypeClass::Who_Can_Build_Me -- Fetches pointer to available factory for this vessel.*\n *   VesselTypeClass::operator delete -- Returns a vessel type object back to the memory pool. *\n *   VesselTypeClass::operator new -- Allocate a vessel type object from the special memory poo*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"function.h\"\n\n\n// Submarine\nstatic VesselTypeClass const VesselSubmarine(\n\tVESSEL_SS,\n\tTXT_SS,\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"SS\",\t\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FBALL1,\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Only has eight facings?\n\t\ttrue,\t\t\t\t\t// Always use the given name for the vehicle?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t8,\t\t\t\t\t\t\t// Rotation stages.\n\t14\t\t\t\t\t\t\t// Turret center offset along body centerline.\n);\n\n// Destroyer\nstatic VesselTypeClass const VesselDestroyer(\n\tVESSEL_DD,\n\tTXT_DD,\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"DD\",\t\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FBALL1,\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Only has eight facings?\n\t\ttrue,\t\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Is it equipped with a combat turret?\n\t8,\t\t\t\t\t\t\t// Rotation stages.\n\t14\t\t\t\t\t\t\t// Turret center offset along body centerline.\n);\n\n// Cruiser\nstatic VesselTypeClass const VesselCruiser(\n\tVESSEL_CA,\n\tTXT_CA,\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"CA\",\t\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FBALL1,\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Only has eight facings?\n\t\ttrue,\t\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Is it equipped with a combat turret?\n\t8,\t\t\t\t\t\t\t// Rotation stages.\n\t14\t\t\t\t\t\t\t// Turret center offset along body centerline.\n);\n\n// Transport\nstatic VesselTypeClass const VesselTransport(\n\tVESSEL_TRANSPORT,\n\tTXT_TRANSPORT,\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"LST\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FBALL1,\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Only has eight facings?\n\t\ttrue,\t\t\t\t\t// Always use the given name for the vehicle?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t0,\t\t\t\t\t\t\t// Rotation stages.\n\t0\t\t\t\t\t\t\t// Turret center offset along body centerline.\n);\n\n// Gun Boat\nstatic VesselTypeClass const VesselPTBoat(\n\tVESSEL_PT,\n\tTXT_PT,\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"PT\",\t\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FBALL1,\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Only has eight facings?\n\t\ttrue,\t\t\t\t\t// Always use the given name for the vehicle?\n\t\ttrue,\t\t\t\t\t// Is it equipped with a combat turret?\n\t8,\t\t\t\t\t\t\t// Rotation stages.\n\t14\t\t\t\t\t\t\t// Turret center offset along body centerline.\n);\n\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// Missile Submarine\nstatic VesselTypeClass const VesselMissileSubmarine(\n\tVESSEL_MISSILESUB,\n\tTXT_MISSILESUB,\t\t// NAME:\t\t\tText name of this unit type.\n\t\"MSUB\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FBALL1,\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Only has eight facings?\n\t\ttrue,\t\t\t\t\t// Always use the given name for the vehicle?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t8,\t\t\t\t\t\t\t// Rotation stages.\n\t14\t\t\t\t\t\t\t// Turret center offset along body centerline.\n);\n#endif\n\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n// Transport\nstatic VesselTypeClass const VesselCarrier(\n\tVESSEL_CARRIER,\n\tTXT_CARRIER,\t\t\t// NAME:\t\t\tText name of this unit type.\n\t\"CARR\",\t\t\t\t\t// NAME:\t\t\tText name of this unit type.\n\tANIM_FBALL1,\t\t\t// EXPLOSION:\tType of explosion when destroyed.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Secondary weapon lateral offset along turret centerling.\n\t\tfalse,\t\t\t\t// Only has eight facings?\n\t\ttrue,\t\t\t\t\t// Always use the given name for the vehicle?\n\t\tfalse,\t\t\t\t// Is it equipped with a combat turret?\n\t0,\t\t\t\t\t\t\t// Rotation stages.\n\t0\t\t\t\t\t\t\t// Turret center offset along body centerline.\n);\n#endif\n\n/***********************************************************************************************\n * VesselTypeClass::VesselTypeClass -- Constructor for unit types.                             *\n *                                                                                             *\n *    This is the constructor for the vessel static data. Each vessels is assign a specific    *\n *    variation. This class elaborates what the variation actually is.                         *\n *                                                                                             *\n * INPUT:   bla bla bla... see below                                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/14/1996 JLB : Created                                                                  *\n *=============================================================================================*/\nVesselTypeClass::VesselTypeClass(\n\t\t\t\tVesselType type,\n\t\t\t\tint name,\n\t\t\t\tchar const * ininame,\n\t\t\t\tAnimType exp,\n\t\t\t\tint verticaloffset,\n\t\t\t\tint primaryoffset,\n\t\t\t\tint primarylateral,\n\t\t\t\tint secondaryoffset,\n\t\t\t\tint secondarylateral,\n\t\t\t\tbool is_eight,\n\t\t\t\tbool is_nominal,\n\t\t\t\tbool is_turret_equipped,\n\t\t\t\tint rotation,\n\t\t\t\tint toffset\n\t\t\t\t) :\n\t\t\t\t\tTechnoTypeClass(\n\t\t\t\t\t\t\t\t\t\tRTTI_VESSELTYPE,\n\t\t\t\t\t\t\t\t\t\tint(type),\n\t\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\t\tininame,\n\t\t\t\t\t\t\t\t\t\tREMAP_NORMAL,\n\t\t\t\t\t\t\t\t\t\tverticaloffset,\n\t\t\t\t\t\t\t\t\t\tprimaryoffset,\n\t\t\t\t\t\t\t\t\t\tprimarylateral,\n\t\t\t\t\t\t\t\t\t\tsecondaryoffset,\n\t\t\t\t\t\t\t\t\t\tsecondarylateral,\n\t\t\t\t\t\t\t\t\t\tis_nominal,\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\tis_turret_equipped,\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\trotation,\n\t\t\t\t\t\t\t\t\t\tSPEED_FLOAT\n\t\t\t\t\t\t\t\t\t\t),\n\tIsPieceOfEight(is_eight),\n\tType(type),\n\tTurretOffset(toffset),\n\tMission(MISSION_GUARD),\n\tExplosion(exp),\n\tMaxSize(0)\n{\n\t/*\n\t**\tForced vessel overrides from the default.\n\t*/\n\tIsCrew = false;\n\tSpeed = SPEED_FLOAT;\n\tIsScanner = true;\n}\n\n\n/***********************************************************************************************\n * VesselTypeClass::operator new -- Allocate a vessel type object from the special memory pool *\n *                                                                                             *\n *    This will allocate a vessel type class object from the memory pool.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocated vessel type class object. If memory in the *\n *          special heap has been exhaused, then NULL will be returned.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * VesselTypeClass::operator new(size_t)\n{\n\treturn(VesselTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * VesselTypeClass::operator delete -- Returns a vessel type object back to the memory pool.   *\n *                                                                                             *\n *    This will return a previously allocated vessel object back to the special pool from      *\n *    whence it was originally allocated.                                                      *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to the vessel type object to return to the pool.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselTypeClass::operator delete(void * pointer)\n{\n\tVesselTypes.Free((VesselTypeClass *)pointer);\n}\n\n\n/***********************************************************************************************\n * VesselTypeClass::Init_Heap -- Initialize the vessel heap.                                   *\n *                                                                                             *\n *    This will pre-allocate all the vessel types required.                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once and do so before processing the rules.ini file.     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese vessel type class objects must be allocated in the exact order that they\n\t**\tare specified in the VesselType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew VesselTypeClass(VesselSubmarine);\t\t\t\t//\tVESSEL_SS\n\tnew VesselTypeClass(VesselDestroyer);\t\t\t\t//\tVESSEL_DD\n\tnew VesselTypeClass(VesselCruiser);\t\t\t\t\t// VESSEL_CA\n\tnew VesselTypeClass(VesselTransport);\t\t\t\t// VESSEL_TRANSPORT\n\tnew VesselTypeClass(VesselPTBoat);\t\t\t\t\t// VESSEL_PT\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tnew VesselTypeClass(VesselMissileSubmarine);\t\t// VESSEL_MISSILESUB\n#endif\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tnew VesselTypeClass(VesselCarrier);\t\t\t\t\t// VESSEL_CARRIER\n#endif\n}\n\n\n/***********************************************************************************************\n * VesselTypeClass::As_Reference -- Converts a vessel type into a VesselTypeClass reference.   *\n *                                                                                             *\n *    This routine will fetch a reference to the vessel type that corresponds to the vessel    *\n *    type specified.                                                                          *\n *                                                                                             *\n * INPUT:   type  -- The vessel type number to convert.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the vessel type class that corresponds to the vessel   *\n *          type specified.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nVesselTypeClass & VesselTypeClass::As_Reference(VesselType type)\n{\n\treturn(*VesselTypes.Ptr(type));\n}\n\n\n#ifdef NEVER\n/***********************************************************************************************\n * VesselTypeClass::Who_Can_Build_Me -- Fetches pointer to available factory for this vessel.  *\n *                                                                                             *\n *    Use this routine to fetch a pointer to the vessel factory that can build this vessel     *\n *    type.                                                                                    *\n *                                                                                             *\n * INPUT:   intheory -- If true, then this indicates that if the factory is currently          *\n *                      busy doing other things, this won't make in ineligible for searching. *\n *                      Typical use of this is by the sidebar logic which needs only to know   *\n *                      if theoretical production is allowed.                                  *\n *                                                                                             *\n *          legal    -- If true, then the buildings are checked for specific legality when     *\n *                      being scanned. For building placement, this is usually false, for      *\n *                      sidebar button adding, this is usually true.                           *\n *                                                                                             *\n *          house    -- The owner of the unit to be produced. This has an effect of legality.  *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the factory (building) that can produce this vessel type.*\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuildingClass * VesselTypeClass::Who_Can_Build_Me(bool intheory, bool legal, HousesType house) const\n{\n\tBuildingClass * anybuilding = NULL;\n\n\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\tBuildingClass * building = Buildings.Ptr(index);\n\t\tassert(building != NULL);\n\n\t\tif (\t!building->IsInLimbo &&\n\t\t\t\tbuilding->House->Class->House == house &&\n\t\t\t\tbuilding->Class->ToBuild == RTTI_VESSELTYPE &&\n\t\t\t\tbuilding->Mission != MISSION_DECONSTRUCTION &&\n\t\t\t\t((1L << building->ActLike) & Ownable) &&\n\t\t\t\t(!legal || building->House->Can_Build(Type, building->ActLike)) &&\n\t\t\t\t(intheory || !building->In_Radio_Contact())) {\n\n\t\t\tif (building->IsLeader) return(building);\n\t\t\tanybuilding = building;\n\t\t}\n\t}\n\treturn(anybuilding);\n}\n#endif\n\n\n/***********************************************************************************************\n * VesselTypeClass::Display -- Displays a generic representation of this vessel type.          *\n *                                                                                             *\n *    This routine is used by the scenario editor to display a representation of this          *\n *    vessel type in the object placement dialog.                                              *\n *                                                                                             *\n * INPUT:   x,y      -- Pixel coordinate to render the center of this vessel type to.          *\n *                                                                                             *\n *          window   -- The window to clip the shape to. The pixel coordinates are relative    *\n *                      to this window.                                                        *\n *                                                                                             *\n *          house    -- The owner of the vessel. This is used to give the vessel its color.    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef SCENARIO_EDITOR\nvoid VesselTypeClass::Display(int x, int y, WindowNumberType window, HousesType ) const\n{\n\tint shape = 0;\n\tvoid const * ptr = Get_Cameo_Data();\n\tif (ptr == NULL) {\n\t\tptr = Get_Image_Data();\n\t\tshape = Rotation/6;\n\t}\n\tCC_Draw_Shape(ptr, shape, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL);\n}\n\n\n/***********************************************************************************************\n * VesselTypeClass::Prep_For_Add -- Adds vessel types to the scenario editor object list.      *\n *                                                                                             *\n *    This routine is called when the scenario editor needs to obtain a list of the            *\n *    vessel object that can be placed down. It will submit all the vessel types that can      *\n *    be placed down.                                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselTypeClass::Prep_For_Add(void)\n{\n\tfor (VesselType index = VESSEL_FIRST; index < VESSEL_COUNT; index++) {\n\t\tif (As_Reference(index).Get_Image_Data() != NULL) {\n\t\t\tMap.Add_To_List(&As_Reference(index));\n\t\t}\n\t}\n}\n#endif\t//SCENARIO_EDITOR\n\n\n/***********************************************************************************************\n * VesselTypeClass::Create_One_Of -- Creates a vessel object that matches this vessel type.    *\n *                                                                                             *\n *    This routine is called when the type of vessel is known (by way of a VesselTypeClass)    *\n *    and a corresponding vessel object needs to be created.                                   *\n *                                                                                             *\n * INPUT:   house -- Pointer to the owner that this vessel will be assigned to.                *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the vessel object created. If no vessel could be         *\n *          created, then NULL is returned.                                                    *\n *                                                                                             *\n * WARNINGS:   The vessel is created in a limbo state. It must first be placed down upon       *\n *             the map before it starts to function.                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * VesselTypeClass::Create_One_Of(HouseClass * house) const\n{\n\treturn(new VesselClass(Type, house->Class->House));\n}\n\n\n/***********************************************************************************************\n * VesselTypeClass::Create_And_Place -- Creates a vessel and places it at location.            *\n *                                                                                             *\n *    This routine is used to create a vessel and then place it down upon the                  *\n *    map.                                                                                     *\n *                                                                                             *\n * INPUT:   cell  -- The location to place this vessel down upon.                              *\n *                                                                                             *\n *          house -- The house to assign this vessel's ownership to.                           *\n *                                                                                             *\n * OUTPUT:  bool; Was the vessel successfully created and placed down upon the map?            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool VesselTypeClass::Create_And_Place(CELL cell, HousesType house) const\n{\n\tVesselClass * unit = new VesselClass(Type, house);\n\tif (unit != NULL) {\n\t\treturn(unit->Unlimbo(Cell_Coord(cell), Random_Pick(DIR_N, DIR_MAX)));\n\t}\n\tdelete unit;\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * VesselTypeClass::Dimensions -- Fetches the pixel width and height of this vessel type.      *\n *                                                                                             *\n *    This routine is used to fetch the width and height of this vessel type. These dimensions *\n *    are not specific to any particular facing. Rather, they are only for the generic vessel  *\n *    size.                                                                                    *\n *                                                                                             *\n * INPUT:   width, height  -- Reference to the integers that are to be initialized with the    *\n *                            pixel width and height of this vessel type.                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselTypeClass::Dimensions(int & width, int & height) const\n{\n\twidth = 48;\n\theight = 48;\n}\n\n\n/***********************************************************************************************\n * VesselTypeClass::One_Time -- Performs one time initialization for vessel types.             *\n *                                                                                             *\n *    This routine will load in the vessel shape data. It should be called only once at the    *\n *    beginning of the game.                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this once.                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselTypeClass::One_Time(void)\n{\n\tfor (VesselType index = VESSEL_FIRST; index < VESSEL_COUNT; index++) {\n\t\tchar\tfullname[_MAX_FNAME+_MAX_EXT];\n\t\tchar\tbuffer[_MAX_FNAME];\n\t\tVesselTypeClass const & uclass = As_Reference(index);\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\tif (uclass.Level != -1 || index==VESSEL_CARRIER) {\n#else\n\t\tif (uclass.Level != -1) {\n#endif\n//\t\tif (uclass.IsBuildable) {\n\n\t\t\t/*\n\t\t\t**\tFetch the supporting data files for the unit.\n\t\t\t*/\n\t\t\tsprintf(buffer, \"%sICON\", uclass.Graphic_Name());\n\t\t\t_makepath(fullname, NULL, NULL, buffer, \".SHP\");\n\t\t\t((void const *&)uclass.CameoData) = MFCD::Retrieve(fullname);\n\t\t}\n\n\t\t/*\n\t\t**\tFetch a pointer to the unit's shape data.\n\t\t*/\n\t\t_makepath(fullname, NULL, NULL, uclass.Graphic_Name(), \".SHP\");\n\t\t((void const *&)uclass.ImageData) = MFCD::Retrieve(fullname);\n\n\t\t((int &)uclass.MaxSize) = 26;\n\t}\n}\n\n\n/***********************************************************************************************\n * VesselTypeClass::Turret_Adjust -- Adjust turret offset according to facing specified.       *\n *                                                                                             *\n *    This routine will determine the pixel adjustment necessary for a turret. The direction   *\n *    specified is what the vessel body is facing.                                             *\n *                                                                                             *\n * INPUT:   dir   -- The presumed direction of the body facing for the vessel.                 *\n *                                                                                             *\n *          x,y   -- The center pixel position for the vessel. These values should be          *\n *                   adjusted (they are references) to match the adjusted offset for the       *\n *                   turret.                                                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselTypeClass::Turret_Adjust(DirType dir, int & x, int & y) const\n{\n\tshort xx = x;\n\tshort yy = y;\n\n\tswitch (Type) {\n\t\tcase VESSEL_CA:\n\t\t\tNormal_Move_Point(xx, yy, dir, 22);\n\t\t\tx = xx;\n\t\t\ty = yy-4;\n\t\t\tbreak;\n\n\t\tcase VESSEL_PT:\n\t\t\tNormal_Move_Point(xx, yy, dir, 14);\n\t\t\tx = xx;\n\t\t\ty = yy+1;\n\t\t\tbreak;\n\n\t\tcase VESSEL_DD:\n\t\t\tNormal_Move_Point(xx, yy, dir+DIR_S, 8);\n\t\t\tx = xx;\n\t\t\ty = yy-4;\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * VesselTypeClass::Overlap_List -- Figures the overlap list for the vessel type.              *\n *                                                                                             *\n *    This routine will return the overlap list for a vessel that is sitting still in the      *\n *    center of a cell.                                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the overlap list that this vessel would use.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * VesselTypeClass::Overlap_List(void) const\n{\n\tstatic short const _ship[] = {-3, -2, -1, 1, 2, 3,\n\t\t-MAP_CELL_W, -(MAP_CELL_W+1), -(MAP_CELL_W-1), -(MAP_CELL_W+2), -(MAP_CELL_W-2),\n\t\t+MAP_CELL_W, +(MAP_CELL_W+1), +(MAP_CELL_W-1), +(MAP_CELL_W+2), +(MAP_CELL_W-2),\n\t\tREFRESH_EOL};\n//\tstatic short const _ship[] = {-1, 1,\n//\t\t-MAP_CELL_W, -(MAP_CELL_W+1), -(MAP_CELL_W-1),\n//\t\t+MAP_CELL_W, +(MAP_CELL_W+1), +(MAP_CELL_W-1),\n//\t\tREFRESH_EOL};\n\n\treturn(&_ship[0]);\n}\n\n\n/***********************************************************************************************\n * VesselTypeClass::From_Name -- Converts a name into a vessel type.                           *\n *                                                                                             *\n *    Use this routine to convert an ASCII version of a vessel type into the corresponding     *\n *    VesselType id value. Typical use of this would be to parse the INI file.                 *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the ASCII name to be converted into a vessel type.             *\n *                                                                                             *\n * OUTPUT:  Returns with the vessel type number that matches the string specified.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nVesselType VesselTypeClass::From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (VesselType classid = VESSEL_FIRST; classid < VESSEL_COUNT; classid++) {\n\t\t\tif (stricmp(As_Reference(classid).IniName, name) == 0) {\n\t\t\t\treturn(classid);\n\t\t\t}\n\t\t}\n\t}\n\treturn(VESSEL_NONE);\n}\n\n\n/***********************************************************************************************\n * VesselTypeClass::Max_Pips -- Fetches the maximum pips allowed for this vessel.              *\n *                                                                                             *\n *    This routine will determine the number of pips (maximum) allowed for this unit type.     *\n *    Typically, this is the number of passengers allowed.\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the maximum number of pips allowed for this vessel type.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/01/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nint VesselTypeClass::Max_Pips(void) const\n{\n\treturn(Max_Passengers());\n}\n"
  },
  {
    "path": "CODE/VECTOR.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/VECTOR.CPP 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : VECTOR.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/19/95                                                     *\n *                                                                                             *\n *                  Last Update : September 21, 1995 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BooleanVectorClass::BooleanVectorClass -- Copy constructor for boolean array.             *\n *   BooleanVectorClass::BooleanVectorClass -- Explicit data buffer constructor.               *\n *   BooleanVectorClass::Clear -- Resets boolean vector to empty state.                        *\n *   BooleanVectorClass::Fixup -- Updates the boolean vector to a known state.                 *\n *   BooleanVectorClass::Reset -- Clear all boolean values in array.                           *\n *   BooleanVectorClass::Resize -- Resizes a boolean vector object.                            *\n *   BooleanVectorClass::Set -- Forces all boolean elements to true.                           *\n *   BooleanVectorClass::operator = -- Assignment operator.                                    *\n *   BooleanVectorClass::operator == -- Comparison operator for boolean vector.                *\n *   VectorClass<T>::Clear -- Frees and clears the vector.                                     *\n *   VectorClass<T>::ID -- Finds object ID based on value.                                     *\n *   VectorClass<T>::ID -- Pointer based conversion to index number.                           *\n *   VectorClass<T>::Resize -- Changes the size of the vector.                                 *\n *   VectorClass<T>::VectorClass -- Constructor for vector class.                              *\n *   VectorClass<T>::VectorClass -- Copy constructor for vector object.                        *\n *   VectorClass<T>::operator = -- The assignment operator.                                    *\n *   VectorClass<T>::operator == -- Equality operator for vector objects.                      *\n *   VectorClass<T>::~VectorClass -- Default destructor for vector class.                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#ifdef WINSOCK_IPX\n#include\t\"WSProto.h\"\n#include\t\"WSPUDP.h\"\n#endif\t//WINSOCK_IPX\n#include \"vector.h\"\n#include\t<mem.h>\n#include\t<stdio.h>\n\n/*\n**\tThe following template function can be located here ONLY if all the instantiations are\n**\tdeclared in a header file this module includes. By placing the template functions here,\n**\tit speeds up compiler operation and reduces object module size.\n*/\n\n/***********************************************************************************************\n * VectorClass<T>::VectorClass -- Constructor for vector class.                                *\n *                                                                                             *\n *    This constructor for the vector class is passed the initial size of the vector and an    *\n *    optional pointer to a preallocated block of memory that the vector will be placed in.    *\n *    If this optional pointer is NULL (or not provided), then the vector is allocated out     *\n *    of free store (with the \"new\" operator).                                                 *\n *                                                                                             *\n * INPUT:   size  -- The number of elements to initialize this vector to.                      *\n *                                                                                             *\n *          array -- Optional pointer to a previously allocated memory block to hold the       *\n *                   vector.                                                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nVectorClass<T>::VectorClass(unsigned size, T const * array) :\n\tVector(0),\n\tVectorMax(size),\n\tIsAllocated(false)\n{\n\t/*\n\t**\tAllocate the vector. The default constructor will be called for every\n\t**\tobject in this vector.\n\t*/\n\tif (size) {\n\t\tif (array) {\n\t\t\tVector = new((void*)array) T[size];\n\t\t} else {\n\t\t\tVector = new T[size];\n\t\t\tIsAllocated = true;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * VectorClass<T>::~VectorClass -- Default destructor for vector class.                        *\n *                                                                                             *\n *    This is the default destructor for the vector class. It will deallocate any memory       *\n *    that it may have allocated.                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nVectorClass<T>::~VectorClass(void)\n{\n\tVectorClass<T>::Clear();\n}\n\n\n/***********************************************************************************************\n * VectorClass<T>::VectorClass -- Copy constructor for vector object.                          *\n *                                                                                             *\n *    This is the copy constructor for the vector class. It will duplicate the provided        *\n *    vector into the new vector being created.                                                *\n *                                                                                             *\n * INPUT:   vector   -- Reference to the vector to use as a copy.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nVectorClass<T>::VectorClass(VectorClass<T> const & vector) :\n\tVector(0),\n\tVectorMax(0),\n\tIsAllocated(false)\n{\n\t*this = vector;\n}\n\n\n/***********************************************************************************************\n * VectorClass<T>::operator = -- The assignment operator.                                      *\n *                                                                                             *\n *    This the the assignment operator for vector objects. It will alter the existing lvalue   *\n *    vector to duplicate the rvalue one.                                                      *\n *                                                                                             *\n * INPUT:   vector   -- The rvalue vector to copy into the lvalue one.                         *\n *                                                                                             *\n * OUTPUT:  Returns with reference to the newly copied vector.                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nVectorClass<T> & VectorClass<T>::operator =(VectorClass<T> const & vector)\n{\n\tif (this != &vector) {\n\t\tClear();\n\t\tVectorMax = vector.Length();\n\t\tif (VectorMax) {\n\t\t\tVector = new T[VectorMax];\n\t\t\tif (Vector) {\n\t\t\t\tIsAllocated = true;\n\t\t\t\tfor (int index = 0; index < VectorMax; index++) {\n\t\t\t\t\tVector[index] = vector[index];\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tVector = 0;\n\t\t\tIsAllocated = false;\n\t\t}\n\t}\n\treturn(*this);\n}\n\n\n/***********************************************************************************************\n * VectorClass<T>::operator == -- Equality operator for vector objects.                        *\n *                                                                                             *\n *    This operator compares two vectors for equality. It does this by performing an object    *\n *    by object comparison between the two vectors.                                            *\n *                                                                                             *\n * INPUT:   vector   -- The right vector expression.                                           *\n *                                                                                             *\n * OUTPUT:  bool; Are the two vectors essentially equal? (do they contain comparable elements  *\n *                in the same order?)                                                          *\n *                                                                                             *\n * WARNINGS:   The equality operator must exist for the objects that this vector contains.     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint VectorClass<T>::operator == (VectorClass<T> const & vector) const\n{\n\tif (VectorMax == vector.Length()) {\n\t\tfor (int index = 0; index < VectorMax; index++) {\n\t\t\tif (Vector[index] != vector[index]) {\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * VectorClass<T>::ID -- Pointer based conversion to index number.                             *\n *                                                                                             *\n *    Use this routine to convert a pointer to an element in the vector back into the index    *\n *    number of that object. This routine ONLY works with actual pointers to object within     *\n *    the vector. For \"equivalent\" object index number (such as with similar integral values)  *\n *    then use the \"by value\" index number ID function.                                        *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to an actual object in the vector.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the index number for the object pointed to by the parameter.          *\n *                                                                                             *\n * WARNINGS:   This routine is only valid for actual pointers to object that exist within      *\n *             the vector. All other object pointers will yield undefined results.             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline int VectorClass<T>::ID(T const * ptr)\n{\n\treturn(((unsigned long)ptr - (unsigned long)&(*this)[0]) / sizeof(T));\n}\n\n\n/***********************************************************************************************\n * VectorClass<T>::ID -- Finds object ID based on value.                                       *\n *                                                                                             *\n *    Use this routine to find the index value of an object with equivalent value in the       *\n *    vector. Typical use of this would be for integral types.                                 *\n *                                                                                             *\n * INPUT:   object   -- Reference to the object that is to be looked up in the vector.         *\n *                                                                                             *\n * OUTPUT:  Returns with the index number of the object that is equivalent to the one          *\n *          specified. If no matching value could be found then -1 is returned.                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint VectorClass<T>::ID(T const & object)\n{\n\tfor (int index = 0; index < VectorMax; index++) {\n\t\tif ((*this)[index] == object) {\n\t\t\treturn(index);\n\t\t}\n\t}\n\treturn(-1);\n}\n\n\n/***********************************************************************************************\n * VectorClass<T>::Clear -- Frees and clears the vector.                                       *\n *                                                                                             *\n *    Use this routine to reset the vector to an empty (non-allocated) state. A vector will    *\n *    free all allocated memory when this routine is called. In order for the vector to be     *\n *    useful after this point, the Resize function must be called to give it element space.    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid VectorClass<T>::Clear(void)\n{\n\tif (Vector && IsAllocated) {\n\t\tdelete[] Vector;\n\t\tVector = 0;\n\t}\n\tIsAllocated = false;\n\tVectorMax = 0;\n}\n\n\n/***********************************************************************************************\n * VectorClass<T>::Resize -- Changes the size of the vector.                                   *\n *                                                                                             *\n *    This routine is used to change the size (usually to increase) the size of a vector. This *\n *    is the only way to increase the vector's working room (number of elements).              *\n *                                                                                             *\n * INPUT:   newsize  -- The desired size of the vector.                                        *\n *                                                                                             *\n *          array    -- Optional pointer to a previously allocated memory block that the       *\n *                      array will be located in. If this parameter is not supplied, then      *\n *                      the array will be allocated from free store.                           *\n *                                                                                             *\n * OUTPUT:  bool; Was the array resized successfully?                                          *\n *                                                                                             *\n * WARNINGS:   Failure to succeed could be the result of running out of memory.                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint VectorClass<T>::Resize(unsigned newsize, T const * array)\n{\n\tif (newsize) {\n\n\t\t/*\n\t\t**\tAllocate a new vector of the size specified. The default constructor\n\t\t**\twill be called for every object in this vector.\n\t\t*/\n\t\tT * newptr;\n\t\tif (!array) {\n\t\t\tnewptr = new T[newsize];\n\t\t} else {\n\t\t\tnewptr = new((void*)array) T[newsize];\n\t\t}\n\t\tif (!newptr) {\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is an old vector, then it must be copied (as much as is feasible)\n\t\t**\tto the new vector.\n\t\t*/\n\t\tif (Vector) {\n\n\t\t\t/*\n\t\t\t**\tCopy as much of the old vector into the new vector as possible. This\n\t\t\t**\tpresumes that there is a functional assignment operator for each\n\t\t\t**\tof the objects in the vector.\n\t\t\t*/\n\t\t\tint copycount = (newsize < VectorMax) ? newsize : VectorMax;\n\t\t\tfor (int index = 0; index < copycount; index++) {\n\t\t\t\tnewptr[index] = Vector[index];\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDelete the old vector. This might cause the destructors to be called\n\t\t\t**\tfor all of the old elements. This makes the implementation of suitable\n\t\t\t**\tassignment operator very important. The default assignment operator will\n\t\t\t**\tonly work for the simplest of objects.\n\t\t\t*/\n\t\t\tif (IsAllocated) {\n\t\t\t\tdelete[] Vector;\n\t\t\t\tVector = 0;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tAssign the new vector data to this class.\n\t\t*/\n\t\tVector = newptr;\n\t\tVectorMax = newsize;\n\t\tIsAllocated = (Vector && !array);\n\n\t} else {\n\n\t\t/*\n\t\t**\tResizing to zero is the same as clearing the vector.\n\t\t*/\n\t\tClear();\n\t}\n\treturn(true);\n}\n\n//----------------------------------------------------------------------------------------------\n\n/***********************************************************************************************\n * BooleanVectorClass::BooleanVectorClass -- Explicit data buffer constructor.                 *\n *                                                                                             *\n *    This is the constructor for a boolean array. This constructor takes the memory pointer   *\n *    provided as assigns that as the array data pointer.                                      *\n *                                                                                             *\n * INPUT:   size  -- The size of the array (in bits).                                          *\n *                                                                                             *\n *          array -- Pointer to the memory that the array is to use.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   You must make sure that the memory specified is large enough to contain the     *\n *             bits specified.                                                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nBooleanVectorClass::BooleanVectorClass(unsigned size, unsigned char * array)\n{\n\tBitArray.Resize(((size + (8-1)) / 8), array);\n\tLastIndex = -1;\n\tBitCount = size;\n}\n\n\n/***********************************************************************************************\n * BooleanVectorClass::BooleanVectorClass -- Copy constructor of boolean array.                *\n *                                                                                             *\n *    This is the copy constructor for a boolean array. It is used to make a duplicate of the  *\n *    boolean array.                                                                           *\n *                                                                                             *\n * INPUT:   vector   -- Reference to the vector to be duplicated.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nBooleanVectorClass::BooleanVectorClass(BooleanVectorClass const & vector)\n{\n\tLastIndex = -1;\n\t*this = vector;\n}\n\n\n/***********************************************************************************************\n * BooleanVectorClass::operator = -- Assignment operator.                                      *\n *                                                                                             *\n *    This routine will make a copy of the specified boolean vector array. The vector is        *\n *    copied into an already constructed existing vector. The values from the existing vector  *\n *    are destroyed by this copy.                                                              *\n *                                                                                             *\n * INPUT:   vector   -- Reference to the vector to make a copy of.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nBooleanVectorClass & BooleanVectorClass::operator =(BooleanVectorClass const & vector)\n{\n\tFixup();\n\tCopy = vector.Copy;\n\tLastIndex = vector.LastIndex;\n\tBitArray = vector.BitArray;\n\tBitCount = vector.BitCount;\n\treturn(*this);\n}\n\n\n/***********************************************************************************************\n * BooleanVectorClass::operator == -- Comparison operator for boolean vector.                  *\n *                                                                                             *\n *    This is the comparison operator for a boolean vector class. Boolean vectors are equal    *\n *    if the bit count and bit values are identical.                                           *\n *                                                                                             *\n * INPUT:   vector   -- Reference to the vector to compare to.                                 *\n *                                                                                             *\n * OUTPUT:  Are the boolean vectors identical?                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BooleanVectorClass::operator == (const BooleanVectorClass & vector)\n{\n\tFixup(LastIndex);\n\treturn(BitCount == vector.BitCount && BitArray == vector.BitArray);\n}\n\n\n/***********************************************************************************************\n * BooleanVectorClass::Resize -- Resizes a boolean vector object.                              *\n *                                                                                             *\n *    This routine will resize the boolean vector object. An index value used with a boolean   *\n *    vector must be less than the value specified in as the new size.                         *\n *                                                                                             *\n * INPUT:   size  -- The new maximum size of this boolean vector.                              *\n *                                                                                             *\n * OUTPUT:  Was the boolean vector sized successfully?                                         *\n *                                                                                             *\n * WARNINGS:   The boolean array might be reallocated or even deleted by this routine.         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BooleanVectorClass::Resize(unsigned size)\n{\n\tFixup();\n\n\tif (size) {\n\n\t\t/*\n\t\t**\tRecord the previous bit count of the boolean vector. This is used\n\t\t**\tto determine if the array has grown in size and thus clearing is\n\t\t**\tnecessary.\n\t\t*/\n\t\tint oldsize = BitCount;\n\n\t\t/*\n\t\t**\tActually resize the bit array. Since this is a bit packed array,\n\t\t**\tthere are 8 elements per byte (rounded up).\n\t\t*/\n\t\tint success = BitArray.Resize(((size + (8-1)) / 8));\n\n\t\t/*\n\t\t**\tSince there is no default constructor for bit packed integers, a manual\n\t\t**\tclearing of the bits is required.\n\t\t*/\n\t\tBitCount = size;\n\t\tif (success && oldsize < size) {\n\t\t\tfor (int index = oldsize; index < size; index++) {\n\t\t\t\t(*this)[index] = 0;\n\t\t\t}\n\t\t}\n\n\t\treturn(success);\n\t}\n\n\t/*\n\t**\tResizing to zero is the same as clearing and deallocating the array.\n\t**\tThis is always successful.\n\t*/\n\tClear();\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * BooleanVectorClass::Clear -- Resets boolean vector to empty state.                          *\n *                                                                                             *\n *    This routine will clear out the boolean array. This will free any allocated memory and   *\n *    result in the boolean vector being unusable until the Resize function is subsequently    *\n *    called.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The boolean vector cannot be used until it is resized to a non null condition.  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BooleanVectorClass::Clear(void)\n{\n\tFixup();\n\tBitCount = 0;\n\tBitArray.Clear();\n}\n\n\n/***********************************************************************************************\n * BooleanVectorClass::Reset -- Clear all boolean values in array.                             *\n *                                                                                             *\n *    This is the preferred (and quick) method to clear the boolean array to a false condition.*\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BooleanVectorClass::Reset(void)\n{\n\tLastIndex = -1;\n\tif (BitArray.Length()) {\n\t\tmemset(&BitArray[0], '\\0', BitArray.Length());\n\t}\n}\n\n\n/***********************************************************************************************\n * BooleanVectorClass::Set -- Forces all boolean elements to true.                             *\n *                                                                                             *\n *    This is the preferred (and fast) way to set all boolean elements to true.                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BooleanVectorClass::Set(void)\n{\n\tLastIndex = -1;\n\tif (BitArray.Length()) {\n\t\tmemset(&BitArray[0], '\\xFF', BitArray.Length());\n\t}\n}\n\n\n/***********************************************************************************************\n * BooleanVectorClass::Fixup -- Updates the boolean vector to a known state.                   *\n *                                                                                             *\n *    Use this routine to set the boolean value copy to match the appropriate bit in the       *\n *    boolean array. The boolean array will be updated with any changes from the last time     *\n *    a value was fetched from the boolean vector. By using this update method, the boolean    *\n *    array can be treated as a normal array even though the elements are composed of          *\n *    otherwise inaccessible bits.                                                             *\n *                                                                                             *\n * INPUT:   index -- The index to set the new copy value to. If the index is -1, then the      *\n *                   previous value will be updated into the vector array, but no new value    *\n *                   will be fetched from it.                                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Always call this routine with \"-1\" if any direct manipulation of the bit        *\n *             array is to occur. This ensures that the bit array is accurate.                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BooleanVectorClass::Fixup(int index) const\n{\n\t/*\n\t**\tIf the requested index value is illegal, then force the index\n\t**\tto be -1. This is the default non-index value.\n\t*/\n\tif ((unsigned)index >= BitCount) {\n\t\tindex = -1;\n\t}\n\n\t/*\n\t**\tIf the new index is different than the previous index, there might\n\t**\tbe some fixing up required.\n\t*/\n\tif (index != LastIndex) {\n\n\t\t/*\n\t\t**\tIf the previously fetched boolean value was changed, then update\n\t\t**\tthe boolean array accordingly.\n\t\t*/\n\t\tif (LastIndex != -1) {\n\t\t\tSet_Bit((void*)&BitArray[0], LastIndex, Copy);\n\t\t}\n\n\t\t/*\n\t\t**\tIf this new current index is valid, then fill in the reference boolean\n\t\t**\tvalue with the appropriate data from the bit array.\n\t\t*/\n\t\tif (index != -1) {\n\t\t\t((unsigned char&)Copy) = Get_Bit(&BitArray[0], index);\n\t\t}\n\n\t\t((int &)LastIndex) = index;\n\t}\n}\n\n\n"
  },
  {
    "path": "CODE/VECTOR.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/VECTOR.H 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : VECTOR.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/19/95                                                     *\n *                                                                                             *\n *                  Last Update : March 13, 1995 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   VectorClass<T>::VectorClass -- Constructor for vector class.                              *\n *   VectorClass<T>::~VectorClass -- Default destructor for vector class.                      *\n *   VectorClass<T>::VectorClass -- Copy constructor for vector object.                        *\n *   VectorClass<T>::operator = -- The assignment operator.                                    *\n *   VectorClass<T>::operator == -- Equality operator for vector objects.                      *\n *   VectorClass<T>::Clear -- Frees and clears the vector.                                     *\n *   VectorClass<T>::Resize -- Changes the size of the vector.                                 *\n *   DynamicVectorClass<T>::DynamicVectorClass -- Constructor for dynamic vector.              *\n *   DynamicVectorClass<T>::Resize -- Changes the size of a dynamic vector.                    *\n *   DynamicVectorClass<T>::Add -- Add an element to the vector.                               *\n *   DynamicVectorClass<T>::Delete -- Remove the specified object from the vector.             *\n *   DynamicVectorClass<T>::Delete -- Deletes the specified index from the vector.             *\n *   VectorClass<T>::ID -- Pointer based conversion to index number.                           *\n *   VectorClass<T>::ID -- Finds object ID based on value.                                     *\n *   DynamicVectorClass<T>::ID -- Find matching value in the dynamic vector.                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef VECTOR_H\n#define VECTOR_H\n\n#ifdef NEVER\n#ifndef false\n#define false 0\n#endif\n#ifndef true\n#define true 1\n#endif\n#endif\n\n#include\t<stdlib.h>\n#include\t<stddef.h>\n\ninline void * operator new(size_t , void * pointer) {return(pointer);}\ninline void * operator new[](size_t , void * pointer) {return(pointer);}\n\n\n/**************************************************************************\n**\tThis is a general purpose vector class. A vector is defined by this\n**\tclass, as an array of arbitrary objects where the array can be dynamically\n**\tsized. Because is deals with arbitrary object types, it can handle everything.\n**\tAs a result of this, it is not terribly efficient for integral objects (such\n**\tas char or int). It will function correctly, but the copy constructor and\n**\tequality operator could be highly optimized if the integral type were known.\n**\tThis efficiency can be implemented by deriving an integral vector template\n**\tfrom this one in order to supply more efficient routines.\n*/\ntemplate<class T>\nclass VectorClass\n{\n\tpublic:\n\t\tVectorClass(NoInitClass const & ) {};\n\t\tVectorClass(unsigned size=0, T const * array=0);\n\t\tVectorClass(VectorClass<T> const &);\t\t// Copy constructor.\n\t\tvirtual ~VectorClass(void);\n\n\t\tT & operator[](unsigned index) {return(Vector[index]);};\n\t\tT const & operator[](unsigned index) const {return(Vector[index]);};\n\t\tvirtual VectorClass<T> & operator =(VectorClass<T> const &); // Assignment operator.\n\t\tvirtual int operator == (VectorClass<T> const &) const;\t// Equality operator.\n\t\tvirtual int Resize(unsigned newsize, T const * array=0);\n\t\tvirtual void Clear(void);\n\t\tunsigned Length(void) const {return VectorMax;};\n\t\tvirtual int ID(T const * ptr);\t// Pointer based identification.\n\t\tvirtual int ID(T const & ptr);\t// Value based identification.\n\n\tprotected:\n\n\t\t/*\n\t\t**\tThis is a pointer to the allocated vector array of elements.\n\t\t*/\n\t\tT * Vector;\n\n\t\t/*\n\t\t**\tThis is the maximum number of elements allowed in this vector.\n\t\t*/\n\t\tunsigned VectorMax;\n\n\t\t/*\n\t\t**\tDoes the vector data pointer refer to memory that this class has manually\n\t\t**\tallocated? If so, then this class is responsible for deleting it.\n\t\t*/\n\t\tunsigned IsAllocated:1;\n};\n\n\n/**************************************************************************\n**\tThis derivative vector class adds the concept of adding and deleting\n**\tobjects. The objects are packed to the beginning of the vector array.\n**\tIf this is instantiated for a class object, then the assignment operator\n**\tand the equality operator must be supported. If the vector allocates its\n**\town memory, then the vector can grow if it runs out of room adding items.\n**\tThe growth rate is controlled by setting the growth step rate. A growth\n**\tstep rate of zero disallows growing.\n*/\ntemplate<class T>\nclass DynamicVectorClass : public VectorClass<T>\n{\n\tpublic:\n\t\tDynamicVectorClass(unsigned size=0, T const * array=0);\n\n\t\t// Change maximum size of vector.\n\t\tvirtual int Resize(unsigned newsize, T const * array=0);\n\n\t\t// Resets and frees the vector array.\n\t\tvirtual void Clear(void) {ActiveCount = 0;VectorClass<T>::Clear();};\n\n\t\t// Fetch number of \"allocated\" vector objects.\n\t\tint Count(void) const {return(ActiveCount);};\n\n\t\t// Add object to vector (growing as necessary).\n\t\tint Add(T const & object);\n\t\tint Add_Head(T const & object);\n\n\t\t// Delete object just like this from vector.\n\t\tint Delete(T const & object);\n\n\t\t// Delete object at this vector index.\n\t\tint Delete(int index);\n\n\t\t// Deletes all objects in the vector.\n\t\tvoid Delete_All(void) {ActiveCount = 0;};\n\n\t\t// Set amount that vector grows by.\n\t\tint Set_Growth_Step(int step) {return(GrowthStep = step);};\n\n\t\t// Fetch current growth step rate.\n\t\tint Growth_Step(void) {return GrowthStep;};\n\n\t\tvirtual int ID(T const * ptr) {return(VectorClass<T>::ID(ptr));};\n\t\tvirtual int ID(T const & ptr);\n\n\tprotected:\n\n\t\t/*\n\t\t**\tThis is a count of the number of active objects in this\n\t\t**\tvector. The memory array often times is bigger than this\n\t\t**\tvalue.\n\t\t*/\n\t\tint ActiveCount;\n\n\t\t/*\n\t\t**\tIf there is insufficient room in the vector array for a new\n\t\t**\tobject to be added, then the vector will grow by the number\n\t\t**\tof objects specified by this value. This is controlled by\n\t\t**\tthe Set_Growth_Step() function.\n\t\t*/\n\t\tint GrowthStep;\n};\n\n\n/**************************************************************************\n**\tThis is a derivative of a vector class that supports boolean flags. Since\n**\ta boolean flag can be represented by a single bit, this class packs the\n**\tarray of boolean flags into an array of bytes containing 8 boolean values\n**\teach. For large boolean arrays, this results in an 87.5% savings. Although\n**\tthe indexing \"[]\" operator is supported, DO NOT pass pointers to sub elements\n**\tof this bit vector class. A pointer derived from the indexing operator is\n**\tonly valid until the next call. Because of this, only simple\n**\tdirect use of the \"[]\" operator is allowed.\n*/\nclass BooleanVectorClass\n{\n\tpublic:\n\t\tBooleanVectorClass(unsigned size=0, unsigned char * array=0);\n\t\tBooleanVectorClass(BooleanVectorClass const & vector);\n\n\t\t// Assignment operator.\n\t\tBooleanVectorClass & operator =(BooleanVectorClass const & vector);\n\n\t\t// Equivalency operator.\n\t\tint operator == (BooleanVectorClass const & vector);\n\n\t\t// Fetch number of boolean objects in vector.\n\t\tint Length(void) {return BitCount;};\n\n\t\t// Set all boolean values to false;\n\t\tvoid Reset(void);\n\n\t\t// Set all boolean values to true.\n\t\tvoid Set(void);\n\n\t\t// Resets vector to zero length (frees memory).\n\t\tvoid Clear(void);\n\n\t\t// Change size of this boolean vector.\n\t\tint Resize(unsigned size);\n\n\t\t// Fetch reference to specified index.\n\t\tbool const & operator[](int index) const {\n\t\t\tif (LastIndex != index) Fixup(index);\n\t\t\treturn(Copy);\n\t\t};\n\t\tbool & operator[](int index) {\n\t\t\tif (LastIndex != index) Fixup(index);\n\t\t\treturn(Copy);\n\t\t};\n\n\t\t// Quick check on boolean state.\n\t\tbool Is_True(int index) const {\n\t\t\tif (index == LastIndex) return(Copy);\n\t\t\treturn(Get_Bit(&BitArray[0], index));\n\t\t};\n\n\t\t// Find first index that is false.\n\t\tint First_False(void) const {\n\t\t\tif (LastIndex != -1) Fixup(-1);\n\n\t\t\tint retval = First_False_Bit(&BitArray[0]);\n\t\t\tif (retval < BitCount) return(retval);\n\n\t\t\t/*\n\t\t\t**\tFailure to find a false boolean value in the vector. Return this\n\t\t\t**\tfact in the form of an invalid index number.\n\t\t\t*/\n\t\t\treturn(-1);\n\t\t}\n\n\t\t// Find first index that is true.\n\t\tint First_True(void) const {\n\t\t\tif (LastIndex != -1) Fixup(-1);\n\n\t\t\tint retval = First_True_Bit(&BitArray[0]);\n\t\t\tif (retval < BitCount) return(retval);\n\n\t\t\t/*\n\t\t\t**\tFailure to find a true boolean value in the vector. Return this\n\t\t\t**\tfact in the form of an invalid index number.\n\t\t\t*/\n\t\t\treturn(-1);\n\t\t}\n\n\tprivate:\n\t\tvoid Fixup(int index=-1) const;\n\n\t\t/*\n\t\t**\tThis is the number of boolean values in the vector. This value is\n\t\t**\tnot necessarily a multiple of 8, even though the underlying character\n\t\t**\tvector contains a multiple of 8 bits.\n\t\t*/\n\t\tint BitCount;\n\n\t\t/*\n\t\t**\tThis is a referential copy of an element in the bit vector. The\n\t\t**\tpurpose of this copy is to allow normal reference access to this\n\t\t**\tobject (for speed reasons). This hides the bit packing scheme from\n\t\t**\tthe user of this class.\n\t\t*/\n\t\tbool Copy;\n\n\t\t/*\n\t\t**\tThis records the index of the value last fetched into the reference\n\t\t**\tboolean variable. This index is used to properly restore the value\n\t\t**\twhen the reference copy needs updating.\n\t\t*/\n\t\tint LastIndex;\n\n\t\t/*\n\t\t**\tThis points to the allocated bitfield array.\n\t\t*/\n\t\tVectorClass<unsigned char> BitArray;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/VERSION.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/VERSION.CPP 14    3/16/97 10:16p Joe_b $ */\n/***************************************************************************\n ***              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               ***\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : VERSION.CPP                              *\n *                                                                         *\n *                   Programmer : Bill R. Randolph                         *\n *                                                                         *\n *                   Start Date : 10/26/95                                 *\n *                                                                         *\n *                  Last Update : September 17, 1996 [JLB]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   VersionClass::VersionClass -- Class constructor                       *\n *   VersionClass::Version_Number -- Returns program version number        *\n *   VersionClass::Major_Version -- returns major version #                *\n *   VersionClass::Minor_Version -- returns minor version (revision) number*\n *   VersionClass::Version_Name -- returns version # as char string        *\n *   VersionClass::Read_Text_String -- reads version text string from disk *\n *   VersionClass::Version_Protocol -- returns default protocol for version*\n *   VersionClass::Init_Clipping -- Initializes version clipping           *\n *   VersionClass::Clip_Version -- \"clips\" the given version range         *\n *   VersionClass::Min_Version -- returns lowest version # to connect to   *\n *   VersionClass::Max_Version -- returns highest version # to connect to  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n#ifdef FIXIT_VERSION_3\n#include \"rawolapi.h\"\t\t//\tFor version number.\n#endif\n\n/****************************** Globals ************************************/\n//---------------------------------------------------------------------------\n// This is a table of version numbers # the communications protocol used for\n// that version number.  It's used by the game owner to determine the\n// protocol to be used for a given session.\n//\n// This table needs to be updated every time a new communications protocol\n// is implemented, not every time a new version is created.\n//\n// A given protocol is used from its corresponding version #, up to (but not\n// including) the next version number in the table.  The last protocol in\n// the table is the default protocol for this version.\n//---------------------------------------------------------------------------\nstatic VersionProtocolType VersionProtocol[] = {\n\t{0x00001000,COMM_PROTOCOL_SINGLE_NO_COMP},\t// (obsolete)\n\t{0x00002000,COMM_PROTOCOL_SINGLE_E_COMP},\t\t// (obsolete)\n\t{0x00010000,COMM_PROTOCOL_MULTI_E_COMP},\n};\n\n\n/***************************************************************************\n * VersionClass::VersionClass -- Class constructor                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/26/1995 BRR : Created.                                             *\n *   09/17/1996 JLB : Converted to used initializer list.                  *\n *=========================================================================*/\nVersionClass::VersionClass(void) :\n\tVersion(0),\n\tMajorVer(0),\n\tMinorVer(0),\n\tMinClipVer(0),\n\tMaxClipVer(0),\n\tVersionInit(false),\n\tMajorInit(false),\n\tMinorInit(false),\n\tTextInit(false)\n{\n\tVersionText[0] = '\\0';\n\tVersionName[0] = '\\0';\n}\n\n\n/***************************************************************************\n * VersionClass::Version_Number -- Returns program version number          *\n *                                                                         *\n * Version Number Format:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Non-CHEAT format:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Byte 3,2: major version (printed to the left of a decimal)\t\t\t\t*\n *   Byte 1,0: minor version (printed to the right of a decimal)\t\t\t\t*\n *   Thus, version 1.07 would appear as 0x0001 0700\t\t\t\t\t\t\t\t*\n *                                                                         *\n *   This format guarantees that a greater-than or less-than comparison\t\t*\n *   will work on version numbers.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * CHEAT format:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Byte 3: Month #\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Byte 2: Day #\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Byte 1: Hour #\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Byte 0: Minute #\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * This format guarantees a unique version number for each compile (as\t\t*\n * long as they're a minute or more apart), with increasing version #'s\t\t*\n * for later times.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * Either format should be printed in hex.                                 *\n *                                                                         *\n * This routine also fills in a text string (retrieved with Version_Text), *\n * which may contain a custom string (such as \"Beta\"); this string is\t\t*\n * read from the file VERSION.TXT.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tVersion number\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tDon't call this function until the file system has been init'd!\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/26/1995 BRR : Created.                                             *\n *=========================================================================*/\n\n//ajw Note: This function is no longer called. MIN_VERSION is now incorrect, but I don't have time\n//\tfor a full rebuild (3 hrs!), and as MIN_VERSION is no longer referred to, I'm going to leave it.\n//\tReally, it should be deleted or commented out.\n//\tVersion number used is now GAME_VERSION.\n//\tNote also that VERSION_RA_300 is wrong, but not used.\n\nunsigned long VersionClass::Version_Number(void)\n{\n\t//------------------------------------------------------------------------\n\t// Read the text description, if there is one\n\t//------------------------------------------------------------------------\n\tif (!TextInit) {\n\t\tRead_Text_String();\n\t\tTextInit = 1;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// If the version has already been set, just return it.\n\t//------------------------------------------------------------------------\n\tif (VersionInit) {\n\t\treturn (Version);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Generate the version #\n\t//------------------------------------------------------------------------\n\tVersion = ((Major_Version() << 16) | Minor_Version());\n\tVersionInit = 1;\n\n\treturn (Version);\n\n}\t/* end of Version_Number */\n\n\n/***************************************************************************\n * VersionClass::Major_Version -- returns major version #                  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tMajor Version number\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tDon't call this function until the file system has been init'd!\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/26/1995 BRR : Created.                                             *\n *=========================================================================*/\nunsigned short VersionClass::Major_Version(void)\n{\n#ifdef DEV_VERSION\n\tstatic char * date = __DATE__;\t\t// format: Mmm dd yyyy\n\tstatic char const * months = \"JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC\";\n\tchar buf[10];\n\tchar * ptr;\n\tchar * tok;\n\tint monthnum;\n\tint daynum;\n#endif\n\n\t//------------------------------------------------------------------------\n\t// Read the text description, if there is one\n\t//------------------------------------------------------------------------\n\tif (!TextInit) {\n\t\tRead_Text_String();\n\t\tTextInit = 1;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// If the major version # is already set, just return it.\n\t//------------------------------------------------------------------------\n\tif (MajorInit) {\n\t\treturn (MajorVer);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// For a development version, use the date (month & day) as the major\n\t// version number.\n\t//------------------------------------------------------------------------\n#ifdef DEV_VERSION\n\t//........................................................................\n\t//\tFetch the month and place in the high byte.\n\t//........................................................................\n\tstrupr(date);\n\ttok = strtok(date, \" \");\n\tptr = strstr(months, tok);\n\tif (ptr) {\n\t\tmonthnum = (((ptr - months) / 3) + 1);\n\t} else {\n\t\tmonthnum = 0;\n\t}\n\n\t//........................................................................\n\t// Convert the month number to a hex counterpart (so, when it's printed\n\t// in hex, it will read correctly.)\n\t//........................................................................\n\tsprintf(buf,\"%d\",monthnum);\n\tsscanf(buf,\"%x\",&monthnum);\n\n\t//........................................................................\n\t//\tFetch the date and place that in the low byte.\n\t//........................................................................\n\ttok = strtok(NULL, \" \");\n\tif (tok) {\n\t\tdaynum = atoi(tok);\n\t} else {\n\t\tdaynum = 0;\n\t}\n\n\t//........................................................................\n\t// Convert the day number to a hex counterpart\n\t//........................................................................\n\tsprintf(buf,\"%d\",daynum);\n\tsscanf(buf,\"%x\",&daynum);\n\n\tMajorVer = ((monthnum << 8) | daynum);\n\n\t//------------------------------------------------------------------------\n\t// For a non-development version, use the hard-coded minor version number.\n\t//------------------------------------------------------------------------\n#else\n\tMajorVer = MAJOR_VERSION;\n#endif\n\n\tMajorInit = 1;\n\n\treturn (MajorVer);\n\n}\t/* end of Major_Version */\n\n\n/***************************************************************************\n * VersionClass::Minor_Version -- returns minor version (revision) number  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tMinor Version number\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tDon't call this function until the file system has been init'd!\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/26/1995 BRR : Created.                                             *\n *=========================================================================*/\nunsigned short VersionClass::Minor_Version(void)\n{\n#ifdef DEV_VERSION\n\tstatic char * time = __TIME__;\t\t// format: hh:mm:ss\n\tchar * tok;\n\tchar buf[10];\n\tint hournum;\n\tint minnum;\n#endif\n\n\t//------------------------------------------------------------------------\n\t// Read the text description, if there is one\n\t//------------------------------------------------------------------------\n\tif (!TextInit) {\n\t\tRead_Text_String();\n\t\tTextInit = 1;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// If the minor version # is already set, just return it.\n\t//------------------------------------------------------------------------\n\tif (MinorInit) {\n\t\treturn (MinorVer);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// For in-development versions, use the time (hour & min) as the minor\n\t// version\n\t//------------------------------------------------------------------------\n#ifdef DEV_VERSION\n\t//........................................................................\n\t//\tFetch the hour and place that in the last two digit positions.\n\t//........................................................................\n\ttok = strtok(time, \": \");\n\tif (tok) {\n\t\thournum = atoi(tok);\n\t} else {\n\t\thournum = 0;\n\t}\n\n\t//........................................................................\n\t// Convert the hour number to a hex counterpart (so, when it's printed\n\t// in hex, it will read correctly.)\n\t//........................................................................\n\tsprintf(buf,\"%d\",hournum);\n\tsscanf(buf,\"%x\",&hournum);\n\n\t//........................................................................\n\t//\tFetch the minute and place that in the last two digit positions.\n\t//........................................................................\n\ttok = strtok(NULL, \": \");\n\tif (tok) {\n\t\tminnum = atoi(tok);\n\t} else {\n\t\tminnum = 0;\n\t}\n\n\t//........................................................................\n\t// Convert the minute number to a hex counterpart\n\t//........................................................................\n\tsprintf(buf,\"%d\",minnum);\n\tsscanf(buf,\"%x\",&minnum);\n\n\tMinorVer = ((hournum << 8) | minnum);\n\n\t//------------------------------------------------------------------------\n\t// For a non-development version, use the hard-coded minor revision number.\n\t//------------------------------------------------------------------------\n#else\n\n#ifdef FIXIT_VERSION_3\t\t\t//\tInsanity. CS installation should not have affected version number. ajw\n\n\tMinorVer = MINOR_VERSION;\n\n#else\t//\tFIXIT_VERSION_3\n\n#ifdef FIXIT_CSII\n\tMinorVer = MINOR_VERSION;\n\tif (Is_Counterstrike_Installed()) {\n\t\tMinorVer = MINOR_VERSION - 1;\n\t}\n#else\n\t#ifdef FIXIT_VERSION\n\t/* If counterstrike is not installed then we report version 1.06\n\t * otherwise we report ourselves as 1.08\n\t */\n\tif (Is_Counterstrike_Installed() == false) {\n\t\tMinorVer = (MINOR_VERSION - CS_MINOR_VERSION_MODIFIER);\n\t} else {\n\t\tMinorVer = MINOR_VERSION;\n\t}\n\t#else\n\tMinorVer = MINOR_VERSION;\n\t#endif\n#endif\n\n#endif\t//\tFIXIT_VERSION_3\n\n#endif\n\n\tMinorInit = 1;\n\n\treturn (MinorVer);\n\n}\t/* end of Minor_Version */\n\n\n/***************************************************************************\n * VersionClass::Version_Name -- returns version # as char string          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to name\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/30/1995 BRR : Created.                                             *\n *=========================================================================*/\nchar * VersionClass::Version_Name(void)\n{\n\t//------------------------------------------------------------------------\n\t// For developmental versions, just use the major & minor version #'s\n\t//------------------------------------------------------------------------\n#ifdef DEV_VERSION\n\tsprintf(VersionName, \"%x.%x\", VerNum.Major_Version(), VerNum.Minor_Version());\n\n\t//------------------------------------------------------------------------\n\t// For final versions, trim 0's off the minor version\n\t//------------------------------------------------------------------------\n#else\n\tunsigned short adjusted_minor;\n\tint i;\n\n\tadjusted_minor = Minor_Version();\n\tfor (i = 0; i < 4; i++) {\n\t\tif ( (adjusted_minor & 0x000f) != 0) {\n\t\t\tbreak;\n\t\t}\n\t\tadjusted_minor >>= 4;\n\t}\n\n\tsprintf(VersionName, \"%x.%x\", VerNum.Major_Version(), adjusted_minor);\n#endif\n\n\treturn (VersionName);\n\n}\t/* end of Version_Name */\n\n\n/***************************************************************************\n * VersionClass::Read_Text_String -- reads version # text string from disk *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tDon't call this function until the file system has been init'd!\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/26/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid VersionClass::Read_Text_String(void)\n{\n\tRawFileClass file(\"VERSION.TXT\");\n\n\tif (file.Is_Available()) {\n\t\tfile.Read(VersionText, sizeof(VersionText));\n\t\tVersionText[sizeof(VersionText)-1] = '\\0';\n\t\twhile (VersionText[strlen(VersionText)-1] == '\\r') {\n\t\t\tVersionText[strlen(VersionText)-1] = '\\0';\n\t\t}\n\t} else {\n\t\tVersionText[0] = '\\0';\n\t}\n\n}\t/* end of Read_Text_String */\n\n\n/***************************************************************************\n * VersionClass::Version_Protocol -- returns default protocol for version  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tversion\t\tversion # to look up\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tprotocol value to use for that version #\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/26/1995 BRR : Created.                                             *\n *=========================================================================*/\nCommProtocolType VersionClass::Version_Protocol(unsigned long version)\n{\n\tint i,j;\n\n\t//------------------------------------------------------------------------\n\t// Compute # entries in the VersionProtocol table\n\t//------------------------------------------------------------------------\n\tj = sizeof (VersionProtocol) / sizeof(VersionProtocolType);\n\n\t//------------------------------------------------------------------------\n\t// Search backwards through the table, finding the first entry for which\n\t// the given version # is >= the table's; this is the range containing\n\t// the given version number.\n\t//------------------------------------------------------------------------\n\tfor (i = j - 1; i >= 0; i--) {\n\t\tif (version >= VersionProtocol[i].Version) {\n\t\t\treturn (VersionProtocol[i].Protocol);\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t// If no range was found for the given version, return the highest\n\t// possible protocol.  (If version clipping is being done properly, this\n\t// case should never happen, but never say never.)\n\t//------------------------------------------------------------------------\n\treturn (VersionProtocol[j-1].Protocol);\n\n}\t/* end of Version_Protocol */\n\n\n/***************************************************************************\n * VersionClass::Init_Clipping -- Initializes version clipping             *\n *                                                                         *\n * Initializes the Min & Max clip version #'s to the min & max values\t\t*\n * defined for this program.  This sets the initial range for use by\t\t\t*\n * the Clip_Version routine.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tThe DEV_VERSION version of this routine calls Version_Number(), so \t*\n *\t\tdon't\tcall this routine until the file system has been initialized!\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/26/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid VersionClass::Init_Clipping(void)\n{\n\tMinClipVer = Min_Version();\n\tMaxClipVer = Max_Version();\n\n}\t/* end of Init_Clipping */\n\n\n/***************************************************************************\n * VersionClass::Clip_Version -- \"clips\" the given version range           *\n *                                                                         *\n * This routine compares another program's supported min/max version \t\t*\n * range with the range currently defined by 'MinClipVer' and 'MaxClipVer'.*\n * If there is overlap in the two ranges, Min & MaxClipVer are adjusted\t\t*\n * to the bounds of the overlap. The routine returns the largest version\t*\n * number shared by the ranges (MaxClipVer).\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Thus, by calling Init_Clipping(), then a series of Clip_Version() calls,*\n * a mutually-acceptable range of version #'s may be negotiated between\t\t*\n * different versions of this program.  The max shared version may then\t\t*\n * be used to decide upon a communications protocol that all programs\t\t*\n * support.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tminver\t\tmin version to clip to\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tmaxver\t\tmax version to clip to\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\thighest clipped version #\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t0 = given range is below our current range\t\t\t\t\t\t\t\t\t*\n *\t\t0xFFFFFFFF = given range is above our current range\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tBe sure Init_Clipping() was called before performing a clipping\t\t*\n *\t\tsession.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/26/1995 BRR : Created.                                             *\n *=========================================================================*/\nunsigned long VersionClass::Clip_Version(unsigned long minver,\n\tunsigned long maxver)\n{\n\t//------------------------------------------------------------------------\n\t// If the given range is outside & above our own, return an error.\n\t//------------------------------------------------------------------------\n\tif (minver > MaxClipVer)\n\t\treturn (0xffffffff);\n\n\t//------------------------------------------------------------------------\n\t// If the given range is outside & below our own, return an error.\n\t//------------------------------------------------------------------------\n\tif (maxver < MinClipVer)\n\t\treturn (0);\n\n\t//------------------------------------------------------------------------\n\t// Clip the lower range value\n\t//------------------------------------------------------------------------\n\tif (minver > MinClipVer)\n\t\tMinClipVer = minver;\n\n\t//------------------------------------------------------------------------\n\t// Clip the upper range value\n\t//------------------------------------------------------------------------\n\tif (maxver < MaxClipVer)\n\t\tMaxClipVer = maxver;\n\n\t//------------------------------------------------------------------------\n\t// Return the highest version supported by the newly-adjusted range.\n\t//------------------------------------------------------------------------\n\treturn (MaxClipVer);\n\n}\t/* end of Clip_Version */\n\n\n/***************************************************************************\n * VersionClass::Min_Version -- returns lowest version # to connect to     *\n *                                                                         *\n * Returns the minimum version # this program will connect to.\t\t\t\t\t*\n *                                                                         *\n * If DEV_VERSION is defined, this routine returns the current version, so *\n * this program will only connect to an exact copy of itself.\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tmin version #\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tThe DEV_VERSION version of this routine calls Version_Number(), so \t*\n *\t\tdon't\tcall this routine until the file system has been initialized!\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/26/1995 BRR : Created.                                             *\n *=========================================================================*/\nunsigned long VersionClass::Min_Version(void)\n{\n#ifdef DEV_VERSION\n\treturn (Version_Number());\n#else\n\n#ifdef FIXIT_VERSION_3\n\n\t//\tNote! I'm no longer using MIN_VERSION, MAX_VERSION, or VERSION_RA_300!\n\t//\tBut no time to do three full rebuilds right now, so I'm not deleting them from the header file...   ajw\n\treturn GAME_VERSION;\n\n#else\t//\tFIXIT_VERSION_3\n\n#ifdef FIXIT_VERSION\n\tif ( Is_Counterstrike_Installed() ) {\n\t\treturn (MIN_VERSION - 1);\n\t}\n\treturn (MIN_VERSION);\n#else\n\tif ( Is_Counterstrike_Installed() ){\n\t\treturn (MIN_VERSION - CS_MINOR_VERSION_MODIFIER);\n\t}else{\n\t\treturn (MIN_VERSION);\n\t}\n#endif\n\n#endif\t//\tFIXIT_VERSION_3\n\n#endif\n\n}\t/* end of Min_Version */\n\n\n/***************************************************************************\n * VersionClass::Max_Version -- returns highest version # to connect to    *\n *                                                                         *\n * Returns the maximum version # this program will connect to.\t\t\t\t\t*\n *                                                                         *\n * If DEV_VERSION is defined, this routine returns the current version, so *\n * this program will only connect to an exact copy of itself.\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tmax version #\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tThe DEV_VERSION version of this routine calls Version_Number(), so \t*\n *\t\tdon't\tcall this routine until the file system has been initialized!\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/26/1995 BRR : Created.                                             *\n *=========================================================================*/\nunsigned long VersionClass::Max_Version(void)\n{\n#ifdef DEV_VERSION\n\treturn (Version_Number());\n#else\n\n#ifdef FIXIT_VERSION_3\n\n\t//\tNote! I'm no longer using MIN_VERSION, MAX_VERSION, or VERSION_RA_300!\n\t//\tBut no time to do three full rebuilds right now, so I'm not deleting them from the header file...   ajw\n\treturn GAME_VERSION;\n\n#else\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw\n\treturn (MAX_VERSION);\n#else\n #ifdef FIXIT_VERSION\n\tif (Is_Counterstrike_Installed() == false) {\n\t\treturn (MAX_VERSION - CS_MINOR_VERSION_MODIFIER);\n\t} else {\n\t\treturn (MAX_VERSION);\n\t}\n #else\n\tif ( Is_Counterstrike_Installed() ){\n\t\treturn (MAX_VERSION + CS_MINOR_VERSION_MODIFIER);\n\t}else{\n\t\treturn (MAX_VERSION);\n\t}\n #endif\n#endif\n#endif\n\n#endif\t//\tFIXIT_VERSION_3\n\n}\t/* end of Max_Version */\n\n\nchar const * Version_Name(void)\n{\n#ifdef NEVER\n\tstatic char buffer[32];\n\n\t/*\n\t**\tFetch the day and month components from the current\n\t**\tbuild date.\n\t*/\n\tstatic char * date = __DATE__;\t\t// format: Mmm dd yyyy\n\tstrupr(date);\n\tchar const * tok = strtok(date, \" \");\n\tstatic char const * months = \"JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC\";\n\tchar const * ptr = strstr(months, tok);\n\tint monthnum = 0;\n\tif (ptr != NULL) {\n\t\tmonthnum = (((ptr - months) / 3) + 1);\n\t}\n\n\ttok = strtok(NULL, \" \");\n\tint daynum = 0;\n\tif (tok != NULL) {\n\t\tdaynum = atoi(tok);\n\t}\n\n\t/*\n\t**\tFetch the time components from the current build time.\n\t*/\n\tstatic char * time = __TIME__;\t\t// format: hh:mm:ss\n\ttok = strtok(time, \": \");\n\tint hournum = 0;\n\tif (tok != NULL) {\n\t\thournum = atoi(tok);\n\t}\n\n\ttok = strtok(NULL, \": \");\n\tint minnum = 0;\n\tif (tok != NULL) {\n\t\tminnum = atoi(tok);\n\t}\n\n\tsprintf(buffer, \"%02d%02d%02d\", monthnum, daynum, (hournum*4) + (minnum / 15));\n\treturn(buffer);\n#else\n\n\tstatic char buffer[128];\n\n\tmemset(buffer, '\\0', sizeof(buffer));\n\n#ifdef FIXIT_VERSION_3\n\tstrcpy( buffer, \"3.03\" );\n\n\t#ifdef ENGLISH\n\tstrcat(buffer, \"E\");\n\t#else\n\t\t#ifdef GERMAN\n\t\tstrcat(buffer, \"G\");\n\t\t#else\n\t\t\t#ifdef FRENCH\n\t\t\tstrcat(buffer, \"F\");\n\t\t\t#endif\n\t\t#endif\n\t#endif\n\n#else\t//\tFIXIT_VERSION_3\n\n#ifdef FIXIT_PATCH_108\n\t//strcpy(buffer, \"1.08PE\");\n    strcpy(buffer, \"1.08P\");\n\n#ifdef FIXIT_CSII\n\tstrcpy(buffer,\"2.00\");\n#ifdef DEV_VERSION\n\tstrcpy(buffer,VerNum.Version_Name());\n#endif\n#ifdef DEV_VER_NAME\n\tstrcpy(buffer,__DATE__);\t\t// format: Mmm dd yyyy\n#endif\n#endif\n\n\t#ifdef ENGLISH\n\tstrcat(buffer, \"E\");\n\t#else\n\t\t#ifdef GERMAN\n\t\tstrcat(buffer, \"G\");\n\t\t#else\n\t\t\t#ifdef FRENCH\n\t\t\tstrcat(buffer, \"F\");\n\t\t\t#endif\n\t\t#endif\n\t#endif\n\n#else\n\tstrcpy(buffer, \"1.07E\");\n#endif\n\n#endif //\tFIXIT_VERSION_3\n\n\tif (Is_Counterstrike_Installed ()){\n\t\tstrcat (buffer, \"CS\");\n\t}\n\tif (Is_Aftermath_Installed()) {\n\t\tstrcat (buffer, \"AM\");\n\t}\n\n#if(TEN)\n\tstrcat(buffer, \"Ten\");\t\t// Ten version\n#endif\n\n#if(MPATH)\n\tstrcat(buffer, \"MPath\");\t// MPath version\n#endif\n\n\tRawFileClass file(\"VERSION.TXT\");\n\tif (file.Is_Available()) {\n\t\tstrcat(buffer, \"\\r\");\n\t\tfile.Read(&buffer[strlen(buffer)], 25);\n\t}\n\treturn(buffer);\n#endif\n}\n"
  },
  {
    "path": "CODE/VERSION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /counterstrike/VERSION.H 2     3/10/97 6:22p Steve_tall $ */\n/***************************************************************************\n ***              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               ***\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : VERSION.H                                *\n *                                                                         *\n *                   Programmer : Bill R. Randolph                         *\n *                                                                         *\n *                   Start Date : 10/26/95                                 *\n *                                                                         *\n *                  Last Update : October 26, 1995 [BRR]                   *\n *                                                                         *\n * This class maintains version information, and communications protocol\t*\n * information.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef VERSION_H\n#define VERSION_H\n\n#define\tVERSION_RED_ALERT_104\t\t0x00010000\t//Shipped US version number\n#define\tVERSION_RED_ALERT_107\t\t0x00011000\t//Shipped Counterstrike number\n#define\tVERSION_RED_ALERT_106\t\t0x00010500\t//Patch without CS installed\n#define\tVERSION_RED_ALERT_108\t\t0x00011500\t//Patch with CS installed\n#define\tVERSION_AFTERMATH_CS\t\t\t0x00011FFF\t//Aftermath with CS installed\n#define\tVERSION_AFTERMATH\t\t\t\t0x00012000\t//Aftermath\n\n//\tAftermath has, in a sense, used version 2.00. (Because of the text on title screen.) Call ourselves version 3.\n#define VERSION_RA_300\t\t\t\t0x00030000\t//\tRA, CS, AM executables unified into one. All are now the same version. -ajw\n//\tIt seems that extra information, that didn't belong there, was being stuffed into version number. Namely, whether or not\n//\tCounterstrike is installed. I'm going to change things back to the way they should be, as I see it. Version will describe\n//\tthe version of the executable only. When it comes to communicating whether or not a player has expansions present, separate\n//\tdata will be transmitted.\n\n//\tHowever, having said that, a caveat. I'm going to have to use the same communication method that was used previously, because\n//\tI need to have prior versions of the game recognize that they can't play against this version. What I'll do is encode\n//\t\"does player have aftermath\" (which is actually the only fact that matters, in multiplayer) in the communicated version\n//\tnumber, as a high bit set/unset. This version of the game will receive this communicated value and pull out the Aftermath\n//\tbit. Older version will reject us as a possible opponent, because, whether or not AM is installed, our version number will\n//\tbe too high for them.\n\n//\tThese horrible things are no longer used. ajw\n#define\tCS_MAJOR_VERSION_MODIFIER\t0x0000\n#define\tCS_MINOR_VERSION_MODIFIER\t0x1000\n\n//---------------------------------------------------------------------------\n//\n//---------------------------------------------------------------------------\ntypedef enum CommProtocolEnum {\n\tCOMM_PROTOCOL_SINGLE_NO_COMP = 0,\t// single frame with no compression\n\tCOMM_PROTOCOL_SINGLE_E_COMP,\t\t\t// single frame with event compression\n\tCOMM_PROTOCOL_MULTI_E_COMP,\t\t\t// multiple frame with event compression\n\tCOMM_PROTOCOL_COUNT,\n\tDEFAULT_COMM_PROTOCOL = COMM_PROTOCOL_MULTI_E_COMP\n} CommProtocolType;\n\ntypedef struct {\n\tunsigned long Version;\n\tCommProtocolType Protocol;\n} VersionProtocolType;\n\nclass VersionClass {\n\tpublic:\n\t\t//.....................................................................\n\t\t// Constructor/Destructor\n\t\t//.....................................................................\n\t\tVersionClass(void);\n\t\tvirtual ~VersionClass() {};\n\n\t\t//.....................................................................\n\t\t// These routines return the current version number.  The long version\n\t\t// number contains the major version in the high word, and the minor\n\t\t// version in the low word.  They should be interpreted in hex.\n\t\t//.....................................................................\n\t\tunsigned long Version_Number(void);\n\t\tunsigned short Major_Version(void);\n\t\tunsigned short Minor_Version(void);\n\n\t\t//.....................................................................\n\t\t// Retrieves a pointer to the version # as a text string (#.#), with\n\t\t// the trailing 0's trimmed off.\n\t\t//.....................................................................\n\t\tchar *Version_Name(void);\n\n\t\t//.....................................................................\n\t\t// Retrieves a pointer to the current version text.\n\t\t//.....................................................................\n\t\tchar *Version_Text() {return (VersionText);}\n\n\t\t//.....................................................................\n\t\t// Returns the default comm protocol for a given version number.\n\t\t//.....................................................................\n\t\tCommProtocolType Version_Protocol(unsigned long version);\n\n\t\t//.....................................................................\n\t\t// These routines support \"version clipping\".\n\t\t//.....................................................................\n\t\tvoid Init_Clipping(void);\n\t\tunsigned long Clip_Version(unsigned long minver, unsigned long maxver);\n\t\tunsigned long Get_Clipped_Version(void) {return (MaxClipVer);}\n\n\t\t//.....................................................................\n\t\t// These routines return the theoretical lowest & highest version #'s\n\t\t// that this program will connect to; this does not take any previous\n\t\t// version clipping into account.\n\t\t//.....................................................................\n\t\tunsigned long Min_Version(void);\n\t\tunsigned long Max_Version(void);\n\n\tprivate:\n\t\t//.....................................................................\n\t\t// Fills in a 'VersionText' with a descriptive version name.\n\t\t//.....................................................................\n\t\tvoid Read_Text_String(void);\n\n\t\t//.....................................................................\n\t\t// These values define the major & minor version #'s for the current\n\t\t// version.  Change these values to change the game's version #!\n\t\t//.....................................................................\n\t\tenum VersionEnum {\n#ifdef FIXIT_VERSION_3\n\t\t\tMAJOR_VERSION = 0x0003,\n\t\t\tMINOR_VERSION = 0x0000\n#else\n\t\t\tMAJOR_VERSION = 0x0001,\n\t\t\tMINOR_VERSION = 0x2000\n#endif\n\t\t};\n\n\t\t//.....................................................................\n\t\t// These values control which other versions this program will connect\n\t\t// to.  Keep them current!\n\t\t// If CHEAT is defined, the program will only connect to itself; these\n\t\t// values aren't used.\n\t\t//.....................................................................\n\t\tenum VersionRangeEnum {\n#ifdef FIXIT_VERSION_3\n\t\t\t//\tajw - We can only play against same version.\n\t\t\tMIN_VERSION = VERSION_RA_300,\n\t\t\tMAX_VERSION = VERSION_RA_300\n#else\n\t\t\tMIN_VERSION = VERSION_RED_ALERT_104, //0x00010000,\t// Version: 1.0\n\t\t\tMAX_VERSION = VERSION_AFTERMATH\t\t //0x00012000\t// Version: 1.2\n#endif\n\t\t};\n\n\t\t//.....................................................................\n\t\t// This is the program's version number, stored internally.\n\t\t//.....................................................................\n\t\tunsigned long Version;\n\t\tunsigned short MajorVer;\n\t\tunsigned short MinorVer;\n\n\t\t//.....................................................................\n\t\t// This array is used for formatting the version # as a string\n\t\t//.....................................................................\n\t\tchar VersionName[30];\n\n\t\t//.....................................................................\n\t\t// This array contains special version labels (such as \"Beta\"), stored\n\t\t// in the file VERSION.TXT.  If the file isn't present, no label is\n\t\t// shown.\n\t\t//.....................................................................\n\t\tchar VersionText[16];\n\n\t\t//.....................................................................\n\t\t// Values used for \"Version Clipping\"\n\t\t//.....................................................................\n\t\tunsigned long MinClipVer;\n\t\tunsigned long MaxClipVer;\n\n\t\t//.....................................................................\n\t\t// Bitfield Flags\n\t\t// IsInitialized: is set if the VERSION.TXT file has been read\n\t\t//.....................................................................\n\t\tunsigned VersionInit :\t\t1;\n\t\tunsigned MajorInit :\t\t1;\n\t\tunsigned MinorInit :\t\t1;\n\t\tunsigned TextInit :\t\t\t1;\n};\n#endif\n/************************** end of version.h *******************************/\n\n"
  },
  {
    "path": "CODE/VER_FUNC.TXT",
    "content": "/***********************************************************************************************\n * Version_Number -- Determines the version number.                                            *\n *                                                                                             *\n *    This routine will determine the version number by analyzing the date and teim that the   *\n *    program was compiled and then generating a unique version number based on it. The        *\n *    version numbers are guaranteed to be larger for later dates.                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the version number.                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Version_Number(void)\n{\n#ifdef OBSOLETE\n\tstatic bool initialized = false;\n\tstatic int version;\n\tstatic char * date = __DATE__;\n\tstatic char * time = __TIME__;\n\tstatic char const * months = \"JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC\";\n\n\tif (!initialized) {\n\t\tchar * ptr;\n\t\tchar * tok;\n\n\t\t/*\n\t\t**\tFetch the month and place in the first two digit positions.\n\t\t*/\n\t\tstrupr(date);\n\t\ttok = strtok(date, \" \");\n\t\tptr = strstr(months, tok);\n\t\tif (ptr) {\n\t\t\tversion = (((ptr - months) / 3)+1) * 10000;\n\t\t}\n\n\t\t/*\n\t\t**\tFetch the date and place that in the next two digit positions.\n\t\t*/\n\t\ttok = strtok(NULL, \" \");\n\t\tif (tok) {\n\t\t\tversion += atoi(tok) * 100;\n\t\t}\n\n\t\t/*\n\t\t**\tFetch the time and place that in the last two digit positions.\n\t\t*/\n\t\ttok = strtok(time, \": \");\n\t\tif (tok) {\n\t\t\tversion += atoi(tok);\n\t\t}\n\n\n\t\t/*\n\t\t**\tFetch the virgin text file (if present).\n\t\t*/\n\t\tRawFileClass file(\"VERSION.TXT\");\n\t\tif (file.Is_Available()) {\n\t\t\tfile.Read(VersionText, sizeof(VersionText));\n\t\t\tVersionText[sizeof(VersionText)-1] = '\\0';\n\t\t\twhile (VersionText[sizeof(VersionText)-1] == '\\r') {\n\t\t\t\tVersionText[sizeof(VersionText)-1] = '\\0';\n\t\t\t}\n\t\t} else {\n\t\t\tVersionText[0] = '\\0';\n\t\t}\n\n\t\tinitialized = true;\n\t}\n\treturn(version);\n#endif\n\n#ifdef PATCH\n\n\t#ifdef DEMO\n\t\tsprintf(VersionText, \" 1.1a\");\t\t// Demo version.\n\t#else\n\t\tstrcpy(VersionText, \".19a \");\n//\t\tstrcpy(VersionText, \".34 \");\n\t#endif\n\treturn(1);\n\n#else\n\n\t#ifdef DEMO\n\t\tsprintf(VersionText, \" 1.0a\");\t\t// Demo version.\n\t#else\n\t//\tsprintf(VersionText, \".%02dp\", 13);\t\t\t// Patch version.\n\t\tsprintf(VersionText, \".%02d\", 14);\t\t\t// Master version.\n\t#endif\n\treturn(1);\n#endif\n}\n\n\n"
  },
  {
    "path": "CODE/VESSEL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/VESSEL.CPP 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : VESSEL.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/13/96                                                     *\n *                                                                                             *\n *                  Last Update : July 31, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   VesselClass::AI -- Handles the AI processing for vessel objects.                          *\n *   VesselClass::Assign_Destination -- Assign a destination for this vessel.                  *\n *   VesselClass::Can_Enter_Cell -- Determines if the vessel can enter the cell specified.     *\n *   VesselClass::Can_Fire -- Determines if this vessel can fire its weapon.                   *\n *   VesselClass::Is_Allowed_To_Recloak -- Can the vessel recloak now?                         *\n *   VesselClass::Class_Of -- Fetches a reference to the vessel's class data.                  *\n *   VesselClass::Combat_AI -- Handles firing and target selection for the vessel.             *\n *   VesselClass::Debug_Dump -- Dumps the vessel status information to the mono monitor.       *\n *   VesselClass::Draw_It -- Draws the vessel.                                                 *\n *   VesselClass::Edge_Of_World_AI -- Determine if vessel is off the edge of the world.        *\n *   VesselClass::Enter_Idle_Mode -- Causes the vessel to enter its default idle mode.         *\n *   VesselClass::Fire_Coord -- Fetches the coordinate the firing originates from.             *\n *   VesselClass::Greatest_Threat -- Determines the greatest threat (best target) for the vesse*\n *   VesselClass::Init -- Initialize the vessel heap system.                                   *\n *   VesselClass::Mission_Retreat -- Perform the retreat mission.                              *\n *   VesselClass::Overlap_List -- Fetches the overlap list for this vessel object.             *\n *   VesselClass::Per_Cell_Process -- Performs once-per-cell action.                           *\n *   VesselClass::Read_INI -- Read the vessel data from the INI database.                      *\n *   VesselClass::Repair_AI -- Process any self-repair required of this vessel.                *\n *   VesselClass::Rotation_AI -- Handles turret and body rotation for this vessel.             *\n *   VesselClass::Shape_Number -- Calculates the shape number for the ship body.               *\n *   VesselClass::Start_Driver -- Starts the vessel by reserving the location it is moving to. *\n *   VesselClass::Take_Damage -- Assign damage to the vessel.                                  *\n *   VesselClass::VesselClass -- Constructor for vessel class objects.                         *\n *   VesselClass::What_Action -- Determines action to perform on specified cell.               *\n *   VesselClass::Write_INI -- Write all vessel scenario data to the INI database.             *\n *   VesselClass::~VesselClass -- Destructor for vessel objects.                               *\n *   operator delete -- Deletes a vessel's memory block.                                       *\n *   operator new -- Allocates a vessel object memory block.                                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"function.h\"\n\n\n/***********************************************************************************************\n * VesselClass::VesselClass -- Constructor for vessel class objects.                           *\n *                                                                                             *\n *    This is the normal constructor for vessel class objects. It will set up a vessel that    *\n *    is valid excepting that it won't be placed on the map.                                   *\n *                                                                                             *\n * INPUT:   classid  -- The type of vessel this will be.                                       *\n *                                                                                             *\n *          house    -- The owner of this vessel.                                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nVesselClass::VesselClass(VesselType classid, HousesType house) :\n\tDriveClass(RTTI_VESSEL, Vessels.ID(this), house),\n\tClass(VesselTypes.Ptr((int)classid)),\n\tIsToSelfRepair(false),\n\tIsSelfRepairing(false),\n\tDoorShutCountDown(0),\n\tPulseCountDown(0),\n\tSecondaryFacing(PrimaryFacing)\n{\n\tHouse->Tracking_Add(this);\n\n\t/*\n\t**\tThe ammo member is actually part of the techno class, but must be initialized\n\t**\tmanually here because this is where we first have access to the class pointer.\n\t*/\n\tAmmo = Class->MaxAmmo;\n\n\t/*\n\t**\tFor two shooters, clear out the second shot flag -- it will be set the first time\n\t**\tthe object fires. For non two shooters, set the flag since it will never be cleared\n\t**\tand the second shot flag tells the system that normal rearm times apply -- this is\n\t**\twhat is desired for non two shooters.\n\t*/\n\tIsSecondShot = !Class->Is_Two_Shooter();\n\tStrength = Class->MaxStrength;\n\n\t/*\n\t**\tThe techno class cloakabilty flag is set according to the type\n\t**\tclass cloakability flag.\n\t*/\n\tIsCloakable = Class->IsCloakable;\n\n\t/*\n\t** Keep count of the number of units created.\n\t*/\n//\tif (Session.Type == GAME_INTERNET) {\n//\t\tHouse->UnitTotals->Increment_Unit_Total((int)classid);\n//\t}\n}\n\n\n/***********************************************************************************************\n * VesselClass::~VesselClass -- Destructor for vessel objects.                                 *\n *                                                                                             *\n *    The destructor will destroy the vessel and ensure that it is properly removed from the   *\n *    game engine.                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nVesselClass::~VesselClass(void)\n{\n\tif (GameActive && Class.Is_Valid()) {\n\n\t\t/*\n\t\t**\tRemove this member from any team it may be associated with. This must occur at the\n\t\t**\ttop most level of the inheritance hierarchy because it may call virtual functions.\n\t\t*/\n\t\tif (Team.Is_Valid()) {\n\t\t\tTeam->Remove(this);\n\t\t\tTeam = NULL;\n\t\t}\n\n\t\tHouse->Tracking_Remove(this);\n\n\t\t/*\n\t\t**\tIf there are any cargo members, delete them.\n\t\t*/\n\t\twhile (Is_Something_Attached()) {\n\t\t\tdelete Detach_Object();\n\t\t}\n\n\t\tLimbo();\n\t}\n\tID = -1;\n}\n\n\n/***********************************************************************************************\n * operator new -- Allocates a vessel object memory block.                                     *\n *                                                                                             *\n *    This routine is used to allocate a block of memory from the vessel heap. If there is     *\n *    no more space in the heap, then this routine will return NULL.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the pointer to the allocated block of memory.                         *\n *                                                                                             *\n * WARNINGS:   This routine could return NULL.                                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * VesselClass::operator new(size_t)\n{\n\tvoid * ptr = Vessels.Alloc();\n\tif (ptr != NULL) {\n\t\t((VesselClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * operator delete -- Deletes a vessel's memory block.                                         *\n *                                                                                             *\n *    This overloaded delete operator will return the vessel's memory back to the pool of      *\n *    memory used for vessel allocation.                                                       *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the vessel's memory block.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselClass::operator delete(void * ptr)\n{\n\tif (ptr != NULL) {\n\t\tassert(((VesselClass *)ptr)->IsActive);\n\t\t((VesselClass *)ptr)->IsActive = false;\n\t}\n\tVessels.Free((VesselClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * VesselClass::Class_Of -- Fetches a reference to the vessel's class data.                    *\n *                                                                                             *\n *    This routine will return with a reference to the static class data for this vessel.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the class data structure associated with this vessel.  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectTypeClass const & VesselClass::Class_Of(void) const\n{\n\tassert(IsActive);\n\n\treturn(*Class);\n}\n\n\n/***********************************************************************************************\n * VesselClass::Can_Enter_Cell -- Determines if the vessel can enter the cell specified.       *\n *                                                                                             *\n *    This routine is used by find path and other movement logic to determine if this          *\n *    vessel can enter the cell specified.                                                     *\n *                                                                                             *\n * INPUT:   cell  -- The cell to check this vessel against.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the movement restriction associated with movement into this object.   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nMoveType VesselClass::Can_Enter_Cell(CELL cell, FacingType ) const\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\tif ((unsigned)cell >= MAP_CELL_TOTAL) return(MOVE_NO);\n\n\tCellClass const * cellptr = &Map[cell];\n\n\t/*\n\t**\tMoving off the edge of the map is not allowed unless\n\t**\tthis is a loaner vehicle.\n\t*/\n\tif (!ScenarioInit && !Map.In_Radar(cell) && !Is_Allowed_To_Leave_Map()) {\n\t\treturn(MOVE_NO);\n\t}\n\n\tMoveType retval = MOVE_OK;\n\n\t/*\n\t**\tIf there is blocking terrain (such as ice), then the vessel\n\t**\tcan't move there.\n\t*/\n\tif (cellptr->Cell_Terrain() != NULL) {\n\t\treturn(MOVE_NO);\n\t}\n\n\t/*\n\t**\tIf the cell is out and out impassable because of underlying terrain, then\n\t**\treturn this immutable fact.\n\t*/\n\tif (Ground[cellptr->Land_Type()].Cost[Class->Speed] == 0) {\n\t\treturn(MOVE_NO);\n\t}\n\n\t/*\n\t**\tIf some allied object has reserved the cell, then consider the cell\n\t**\tas blocked by a moving object.\n\t*/\n\tif (cellptr->Flag.Composite) {\n\n\t\tif (cellptr->Flag.Occupy.Building) {\n\t\t\treturn(MOVE_NO);\n\t\t}\n\n\t\tTechnoClass * techno = cellptr->Cell_Techno();\n\t\tif (techno != NULL && techno->Cloak == CLOAKED && !House->Is_Ally(techno)) {\n\t\t\treturn(MOVE_CLOAK);\n\t\t}\n\n\t\t/*\n\t\t**\tIf reserved by a vehicle, then consider this blocked terrain.\n\t\t*/\n\t\tif (cellptr->Flag.Occupy.Vehicle) {\n\t\t\tretval = MOVE_MOVING_BLOCK;\n\t\t}\n\t}\n\n\t/*\n\t**\tReturn with the most severe reason why this cell would be impassable.\n\t*/\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * VesselClass::Shape_Number -- Calculates the shape number for the ship body.                 *\n *                                                                                             *\n *    This routine will return with the shape number to use for the ship's body.               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the shape number to use for the ship's body when drawing.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/31/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint VesselClass::Shape_Number(void) const\n{\n\t/*\n\t**\tFor eight facing units, adjust the facing number accordingly.\n\t*/\n\tFacingType facing = Dir_Facing(PrimaryFacing.Current());\n\n\tint shapenum = UnitClass::BodyShape[Dir_To_16(PrimaryFacing)*2]>>1;\n\n\t/*\n\t**\tSpecial case code for transport. The north/south facing is in frame\n\t**\t0. The east/west facing is in frame 3.\n\t*/\n\tif (*this == VESSEL_TRANSPORT) {\n\t\tshapenum = 0;\n\t}\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tif (*this == VESSEL_CARRIER) {\n\t\tshapenum = 0;\n\t}\n#endif\n\t/*\n\t**\tDoor opening and closing animation stage check.\n\t*/\n\tif (!Is_Door_Closed()) {\n\t\tshapenum = Door_Stage();\n\t}\n\n\treturn(shapenum);\n}\n\n\n/***********************************************************************************************\n * VesselClass::Draw_It -- Draws the vessel.                                                   *\n *                                                                                             *\n *    Draws the vessel on the tactical display. This routine is called by the map rendering    *\n *    process to display the vessel.                                                           *\n *                                                                                             *\n * INPUT:   x,y   -- The pixel coordinate to draw this vessel at.                              *\n *                                                                                             *\n *          window-- The window to base clipping and coordinates upon when drawing.            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselClass::Draw_It(int x, int y, WindowNumberType window) const\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tVerify the legality of the unit class.\n\t*/\n\tvoid const * shapefile = Get_Image_Data();\n\tif (shapefile == NULL) return;\n\n\t/*\n\t**\tIf drawing of this unit is not explicitly prohibited, then proceed\n\t**\twith the render process.\n\t*/\n\tif (Visual_Character() != VISUAL_HIDDEN) {\n\t\tint\t\t\tfacing = Dir_To_32(PrimaryFacing);\n\t\tint\t\t\ttfacing = Dir_To_32(SecondaryFacing);\n\t\tDirType\t\trotation = DIR_N;\n\t\tint\t\t\tscale = 0x0100;\n\n\t\t/*\n\t\t**\tActually perform the draw. Overlay an optional shimmer effect as necessary.\n\t\t*/\n\t\tTechno_Draw_Object(shapefile, Shape_Number(), x, y, window, rotation, scale);\n\n\t\t/*\n\t\t**\tIf there is a turret, then it must be rendered as well. This may include\n\t\t**\tfiring animation if required.\n\t\t*/\n\t\tif (Class->IsTurretEquipped) {\n\t\t\tint xx = x;\n\t\t\tint yy = y;\n\n\t\t\t/*\n\t\t\t**\tDetermine which turret shape to use. This depends on if there\n\t\t\t**\tis any firing animation in progress.\n\t\t\t*/\n\t\t\tint shapenum = TechnoClass::BodyShape[tfacing]+32;\n\t\t\tDirType turdir = DirType(Dir_To_16(PrimaryFacing)*16);\n\n\t\t\tswitch (Class->Type) {\n\t\t\t\tcase VESSEL_CA:\n\t\t\t\t\tshapefile = Class->TurretShapes;\n\t\t\t\t\tshapenum = TechnoClass::BodyShape[Dir_To_32(SecondaryFacing)];\n\t\t\t\t\tClass->Turret_Adjust(turdir, xx, yy);\n\t\t\t\t\tTechno_Draw_Object(shapefile, shapenum, xx, yy, window);\n\t\t\t\t\txx = x;\n\t\t\t\t\tyy = y;\n\t\t\t\t\tturdir = DirType(Dir_To_16(PrimaryFacing+DIR_S)*16);\n\t\t\t\t\tClass->Turret_Adjust(turdir, xx, yy);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase VESSEL_DD:\n\t\t\t\t\tshapefile = Class->SamShapes;\n\t\t\t\t\tshapenum = TechnoClass::BodyShape[Dir_To_32(SecondaryFacing)];\n\t\t\t\t\tClass->Turret_Adjust(turdir, xx, yy);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase VESSEL_PT:\n\t\t\t\t\tshapefile = Class->MGunShapes;\n\t\t\t\t\tshapenum = TechnoClass::BodyShape[Dir_To_32(SecondaryFacing)];\n\t\t\t\t\tClass->Turret_Adjust(turdir, xx, yy);\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tshapenum = TechnoClass::BodyShape[Dir_To_32(SecondaryFacing)];\n\t\t\t\t\tClass->Turret_Adjust(turdir, xx, yy);\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tActually perform the draw. Overlay an optional shimmer effect as necessary.\n\t\t\t*/\n\t\t\tTechno_Draw_Object(shapefile, shapenum, xx, yy, window);\n\t\t}\n\t}\n\n\tDriveClass::Draw_It(x, y, window);\n\n\t/*\n\t** Patch so the transport will draw its passengers on top of itself.\n\t*/\n\tif (!Is_Door_Closed() && IsTethered && In_Radio_Contact() && !Contact_With_Whom()->IsInLimbo) {\n\t\tassert(Contact_With_Whom()->IsActive);\n\t\tContact_With_Whom()->Render(true);\n\t}\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * VesselClass::Debug_Dump -- Dumps the vessel status information to the mono monitor.         *\n *                                                                                             *\n *    This routine will display the vessel's status information. The information is dumped to  *\n *    the monochrome monitor.                                                                  *\n *                                                                                             *\n * INPUT:   mono  -- Pointer to the monochrome screen that the information will be displayed   *\n *                   to.                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\tmono->Set_Cursor(0, 0);\n\tmono->Print(Text_String(TXT_DEBUG_SHIP));\n\tmono->Set_Cursor(47, 5);mono->Printf(\"%02X:%02X\", SecondaryFacing.Current(), SecondaryFacing.Desired());\n\n\tmono->Fill_Attrib(66, 13, 12, 1, IsSelfRepairing ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 14, 12, 1, IsToSelfRepair ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tDriveClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * VesselClass::Overlap_List -- Fetches the overlap list for this vessel object.               *\n *                                                                                             *\n *    This routine will fetch the overlap list for this vessel type. It takes into             *\n *    consideration any movement the vessel may be doing.                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the overlap list for this vessel.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * VesselClass::Overlap_List(bool redraw) const\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n#ifdef PARTIAL\n\tif (Height == 0 && redraw && Class->DimensionData != NULL) {\n\t\tRect rect;\n\t\tint shapenum = Shape_Number();\n\t\tif (Class->DimensionData[shapenum].Is_Valid()) {\n\t\t\trect = Class->DimensionData[shapenum];\n\t\t} else {\n\t\t\trect = Class->DimensionData[shapenum] = Shape_Dimensions(Get_Image_Data(), shapenum);\n\t\t}\n\n\t\tif (IsSelected) {\n\t\t\trect = Union(rect, Rect(-32, 32, 64, 64));\n\t\t}\n\n\t\treturn(Coord_Spillage_List(Coord, rect, true));\n\t}\n#else\n\tredraw = redraw;\n#endif\n\n\treturn(Coord_Spillage_List(Coord, 56)+1);\n}\n\n\n/***********************************************************************************************\n * VesselClass::AI -- Handles the AI processing for vessel objects.                            *\n *                                                                                             *\n *    This routine is called once for each vessel object during each main game loop. All       *\n *    normal AI processing is handled here. This includes dispatching and maintaining any      *\n *    processing that is specific to vessel objects.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 JLB : Created.                                                                 *\n *   07/16/1996 JLB : Prefers anti-sub weapons if firing on subs.                              *\n *=============================================================================================*/\nvoid VesselClass::AI(void)\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Mission == MISSION_NONE && MissionQueue == MISSION_NONE) {\n\t\tEnter_Idle_Mode();\n\t}\n\n\t/*\n\t**\tHACK ALERT:\n\t**\tIf the ship finds itself in a hunt order but it has no weapons, then tell it\n\t**\tto sail off the map instead.\n\t*/\n\tif (Mission == MISSION_HUNT && !Is_Weapon_Equipped()) {\n\t\tAssign_Mission(MISSION_RETREAT);\n\t}\n\n\t/*\n\t**\tAct on new orders if the unit is at a good position to do so.\n\t*/\n\tif (!IsDriving && Is_Door_Closed() /*Mission != MISSION_UNLOAD*/) {\n\t\tCommence();\n\t}\n\n#ifndef CLIPDRAW\n\tif (Map.In_View(Coord_Cell(Center_Coord())) && Visual_Character() != VISUAL_HIDDEN && Visual_Character() != VISUAL_NORMAL) {\n\t\tMark(MARK_CHANGE);\n\t}\n#endif\n\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n// Re-stock the ammo of any on-board helicopters on an aircraft carrier.\n\tif (*this == VESSEL_CARRIER && How_Many()) {\n\t\tif (!MoebiusCountDown) {\n\t\t\tMoebiusCountDown = Rule.ReloadRate * TICKS_PER_MINUTE;\n\t\t\tObjectClass *obj = Attached_Object();\n\t\t\twhile (obj) {\n\t\t\t\tlong bogus;\n\t\t\t\t((AircraftClass *)obj)->Receive_Message(this,RADIO_RELOAD,bogus);\n\t\t\t\tobj = (obj->Next);\n\t\t\t}\n\t\t}\n\t}\n#endif\n\t/*\n\t**\tProcess base class AI routine. If as a result of this, the vessel gets\n\t**\tdestroyed, then detect this fact and bail early.\n\t*/\n\tDriveClass::AI();\n\tif (!IsActive) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tHandle body and turret rotation.\n\t*/\n\tRotation_AI();\n\n\t/*\n\t**\tHandle any combat processing required.\n\t*/\n\tCombat_AI();\n\n\t/*\n\t**\tDelete this unit if it finds itself off the edge of the map and it is in\n\t**\tguard or other static mission mode.\n\t*/\n\tif (Edge_Of_World_AI()) {\n\t\treturn;\n\t}\n\n\tif (Class->Max_Passengers() > 0) {\n\n\t\t/*\n\t\t**\tDouble check that there is a passenger that is trying to load or unload.\n\t\t**\tIf not, then close the door.\n\t\t*/\n\t\tif (!Is_Door_Closed() && Mission != MISSION_UNLOAD && Transmit_Message(RADIO_TRYING_TO_LOAD) != RADIO_ROGER && !(long)DoorShutCountDown) {\n\t\t\tLST_Close_Door();\n\t\t}\n\t}\n\n\t/*\n\t**\tDon't start a new mission unless the vehicle is in the center of\n\t**\ta cell (not driving) and the door (if any) is closed.\n\t*/\n\tif (!IsDriving && Is_Door_Closed()/*&& Mission != MISSION_UNLOAD*/) {\n\t\tCommence();\n\t}\n\n\t/*\n\t** Do a step of repair here, if appropriate.\n\t*/\n\tRepair_AI();\n}\n\n\n/***********************************************************************************************\n * VesselClass::Per_Cell_Process -- Performs once-per-cell action.                             *\n *                                                                                             *\n *    This routine is called when the vessel travels one cell. It handles any processes that   *\n *    must occur on a per-cell basis.                                                          *\n *                                                                                             *\n * INPUT:   why   -- Specifies the circumstances under which this routine was called.          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselClass::Per_Cell_Process(PCPType why)\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\tBStart(BENCH_PCP);\n\n\tif (why == PCP_END) {\n\t\tCELL cell = Coord_Cell(Coord);\n\n\t\t/*\n\t\t**\tThe unit performs looking around at this time. If the\n\t\t**\tunit moved further than one square during the last track\n\t\t**\tmove, don't do an incremental look. Do a full look around\n\t\t**\tinstead.\n\t\t*/\n\t\tLook(!IsPlanningToLook);\n\t\tIsPlanningToLook = false;\n\n\t\tif (IsToSelfRepair) {\n\t\t\tfor (FacingType face = FACING_N; face < FACING_COUNT; face++) {\n\t\t\t\tCELL cell = Coord_Cell(Adjacent_Cell(Center_Coord(), face));\n\t\t\t\tSmartPtr<BuildingClass> whom;\n\t\t\t\twhom = Map[cell].Cell_Building();\n\t\t\t\tif (whom != NULL && ((*whom == STRUCT_SHIP_YARD) || (*whom == STRUCT_SUB_PEN)) ) {\n\t\t\t\t\tif (IsOwnedByPlayer) Speak(VOX_REPAIRING);\n\t\t\t\t\tIsSelfRepairing = true;\n\t\t\t\t\tIsToSelfRepair = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf this is a loaner unit and is is off the edge of the\n\t\t**\tmap, then it gets eliminated.\n\t\t*/\n\t\tif (Edge_Of_World_AI()) {\n\t\t\tBEnd(BENCH_PCP);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (IsActive) {\n\t\tDriveClass::Per_Cell_Process(why);\n\t}\n\tBEnd(BENCH_PCP);\n}\n\n\n/***********************************************************************************************\n * VesselClass::What_Action -- Determines what action would occur if clicked on object.        *\n *                                                                                             *\n *    Use this function to determine what action would likely occur if the specified object    *\n *    were clicked on while this unit was selected as current. This function controls, not     *\n *    only the action to perform, but indirectly controls the cursor shape to use as well.     *\n *                                                                                             *\n * INPUT:   object   -- The object that to check for against \"this\" object.                    *\n *                                                                                             *\n * OUTPUT:  Returns with the default action to perform. If no clear action can be determined,  *\n *          then ACTION_NONE is returned.                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/16/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nActionType VesselClass::What_Action(ObjectClass const * object) const\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\tActionType action = DriveClass::What_Action(object);\n\n\tif (action == ACTION_SELF) {\n\t\tif (Class->Max_Passengers() == 0 || !How_Many() ) {\n\t\t\taction = ACTION_NONE;\n\t\t} else {\n// check to see if the transporter can unload.\n\t\t\tbool found = 0;\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\tif (*this != VESSEL_CARRIER)\n#endif\n\t\t\tfor (FacingType face = FACING_N; face < FACING_COUNT && !found; face++) {\n\t\t\t\tCELL cellnum = Adjacent_Cell(Coord_Cell(Coord), face);\n\t\t\t\tCellClass * cell = &Map[cellnum];\n\t\t\t\tif (Map.In_Radar(cellnum) && Ground[cell->Land_Type()].Cost[SPEED_FOOT] == 0 || cell->Flag.Occupy.Building || cell->Flag.Occupy.Vehicle || cell->Flag.Occupy.Monolith || (cell->Flag.Composite & 0x01F) == 0x01F) {\n\t\t\t\t\tcontinue;\n\t\t\t\t} else {\n\t\t\t\t\tfound = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!found) {\n\t\t\t\taction = ACTION_NONE;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tSpecial return to friendly repair factory action.\n\t*/\n\tif (House->IsPlayerControl && action == ACTION_SELECT && object->What_Am_I() == RTTI_BUILDING) {\n\t\tBuildingClass * building = (BuildingClass *)object;\n\n\t\tif (building->Class->ToBuild == RTTI_VESSELTYPE && building->House->Is_Ally(this)) {\n\t\t\taction = ACTION_ENTER;\n\t\t}\n\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (action == ACTION_ATTACK && object->What_Am_I() == RTTI_VESSEL &&\n\t\t (*this == VESSEL_MISSILESUB || *this == VESSEL_CA) ) {\n\t\t \taction = ACTION_NOMOVE;\n\t}\n#endif\n\t/*\n\t**\tIf it doesn't know what to do with the object, then just\n\t**\tsay it can't move there.\n\t*/\n\tif (action == ACTION_NONE) action = ACTION_NOMOVE;\n\n\treturn(action);\n}\n\n\n/***********************************************************************************************\n * VesselClass::Active_Click_With -- Intercepts the active click to see if deployment is possib*\n *                                                                                             *\n *    This routine intercepts the active click operation. It check to see if this is a self    *\n *    deployment request (MCV's have this ability). If it is, then the object is initiated     *\n *    to self deploy. In the other cases, it passes the operation down to the lower            *\n *    classes for processing.                                                                  *\n *                                                                                             *\n * INPUT:   action   -- The action requested of the unit.                                      *\n *                                                                                             *\n *          object   -- The object that the mouse pointer is over.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/16/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselClass::Active_Click_With(ActionType action, ObjectClass * object)\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n//\tif (action != What_Action(object)) {\n\t\taction = What_Action(object);\n\t\tswitch (action) {\n\t\t\tcase ACTION_ENTER:\n\t\t\t\taction = ACTION_MOVE;\n\t\t\t\t// BRR 10/18/96 IsToSelfRepair = true;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n//\t\t\t\taction = ACTION_NONE;\n\t\t\t\tbreak;\n\t\t}\n//\t}\n//\tif (action == ACTION_ENTER) {\n\t\t// BRR 10/18/96 IsToSelfRepair = true;\n//\t\taction = ACTION_MOVE;\n//\t} else {\n//\t\tif (action != ACTION_NONE) {\n\t\t\t// BRR 10/18/96 IsSelfRepairing = IsToSelfRepair = false;\n//\t\t}\n//\t}\n\n\tDriveClass::Active_Click_With(action, object);\n}\n\n\n/***********************************************************************************************\n * VesselClass::Active_Click_With -- Performs specified action on specified cell.              *\n *                                                                                             *\n *    This routine is called when the mouse has been clicked over a cell and this unit must    *\n *    now respond. Notice that this is merely a placeholder function that exists because there *\n *    is another function of the same name that needs to be overloaded. C++ has scoping        *\n *    restrictions when there are two identically named functions that are overridden in       *\n *    different classes -- it handles it badly, hence the existence of this routine.           *\n *                                                                                             *\n * INPUT:   action   -- The action to perform on the cell specified.                           *\n *                                                                                             *\n *          cell     -- The cell that the action is to be performed on.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/16/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselClass::Active_Click_With(ActionType action, CELL cell)\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\t// BRR 10/18/96 IsToSelfRepair = false;\n//\tif (action != ACTION_NONE) {\n\t\t// BRR 10/18/96 IsSelfRepairing = false;\n//\t}\n\tDriveClass::Active_Click_With(action, cell);\n}\n\n\n/***********************************************************************************************\n * VesselClass::Take_Damage -- Assign damage to the vessel.                                    *\n *                                                                                             *\n *    This routine is called to apply damage to this vessel. The amount and type of damage     *\n *    to apply is passed as parameters. This routine could end up destroying the vessel.       *\n *                                                                                             *\n * INPUT:   damage   -- Reference to the amount of damage to apply to this vessel. The damage  *\n *                      value will be adjusted so that the actual damage applied will be       *\n *                      stored into this variable for possible subsequent examination.         *\n *                                                                                             *\n *          distance -- The distance from the center of the damage to the vessel itself.       *\n *                                                                                             *\n *          warhead  -- The warhead type of damage to apply.                                   *\n *                                                                                             *\n *          source   -- The perpetrator of this damage. Knowing who was responsible allows     *\n *                      retaliation logic.                                                     *\n *                                                                                             *\n *          forced   -- Is this damage forced upon the vessel by some supernatural means?      *\n *                                                                                             *\n * OUTPUT:  Returns with the result of the damage applied. This enumeration indicates the      *\n *          general effect of the damage. Examine this return value to see if the vessel       *\n *          has been destroyed.                                                                *\n *                                                                                             *\n * WARNINGS:   The vessel could be destroyed by the call to this routine!                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/13/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nResultType VesselClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, int forced)\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\tResultType res = RESULT_NONE;\n\n\t/*\n\t**\tIn order for a this to be damaged, it must either be a unit\n\t**\twith a crew or a sandworm.\n\t*/\n\tres = FootClass::Take_Damage(damage, distance, warhead, source, forced);\n\n\tif (res == RESULT_DESTROYED) {\n\t\tDeath_Announcement(source);\n\t\tif (Class->Explosion != ANIM_NONE) {\n\t\t\tAnimType anim = Class->Explosion;\n\n\t\t\tnew AnimClass(anim, Coord);\n\n\t\t\t/*\n\t\t\t**\tVery strong units that have an explosion will also rock the\n\t\t\t**\tscreen when they are destroyed.\n\t\t\t*/\n\t\t\tif (Class->MaxStrength > 400) {\n\t\t\t\tShake_The_Screen(Class->MaxStrength / 150);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tPossibly have the crew member run away.\n\t\t*/\n\t\tMark(MARK_UP);\n\t\twhile (Is_Something_Attached()) {\n\t\t\tFootClass * object = Detach_Object();\n\n\t\t\t/*\n\t\t\t**\tOnly infantry can run from a destroyed vehicle. Even then, it is not a sure\n\t\t\t**\tthing.\n\t\t\t*/\n\t\t\tobject->Record_The_Kill(source);\n\t\t\tdelete object;\n\t\t}\n\n\t\t/*\n\t\t**\tFinally, delete the vehicle.\n\t\t*/\n\t\tdelete this;\n\n\t} else {\n\n\t\t/*\n\t\t**\tWhen damaged and below half strength, start smoking if\n\t\t**\tit isn't already smoking (and it's not a submarine).\n\t\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tif (Health_Ratio() <= Rule.ConditionYellow && !IsAnimAttached && (*this != VESSEL_SS && *this != VESSEL_MISSILESUB) ) {\n#else\n\t\tif (Health_Ratio() <= Rule.ConditionYellow && !IsAnimAttached && (*this != VESSEL_SS) ) {\n#endif\n\t\t\tAnimClass * anim = new AnimClass(ANIM_SMOKE_M, Coord_Add(Coord, XYP_Coord(0, -8)));\n\t\t\tif (anim != NULL) anim->Attach_To(this);\n\t\t}\n\t}\n\treturn(res);\n}\n\n\n/***********************************************************************************************\n * VesselClass::Can_Fire -- Determines if this vessel can fire its weapon.                     *\n *                                                                                             *\n *    This routine is used to determine if this vessel can fire its weapon at the target       *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   target   -- The target candidate to determine if firing upon is valid.             *\n *                                                                                             *\n *          which    -- Which weapon to use when considering the candidate as a potential      *\n *                      target.                                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the fire error type. This enum indicates if the vessel and fire. If   *\n *          it can't fire, then the enum indicates why.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/13/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nFireErrorType VesselClass::Can_Fire(TARGET target, int which) const\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\tDirType\t\t\tdir;\t\t\t\t\t// The facing to impart upon the projectile.\n\tint\t\t\t\tdiff;\n\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tif (*this == VESSEL_CARRIER) {\n\t\tif(!How_Many() || Arm) {\n\t\t\treturn(FIRE_REARM);\n\t\t} else {\n\t\t\treturn(FIRE_OK);\n\t\t}\n\t}\n#endif\n\tFireErrorType\tfire = DriveClass::Can_Fire(target, which);\nif(*this==VESSEL_DD) {\nMono_Set_Cursor(0,0);\n}\n\tif (fire == FIRE_OK || fire == FIRE_CLOAKED) {\n\t\tWeaponTypeClass const * weapon = (which == 0) ? Class->PrimaryWeapon : Class->SecondaryWeapon;\n\n\t\t/*\n\t\t**\tEnsure that a torpedo will never be fired upon a non naval target.\n\t\t** Unless that non-naval target is a naval building (sub pen/ship yard)\n\t\t*/\n\t\tbool isseatarget = Is_Target_Vessel(target);\n\t\tbool isbridgetarget = false;\n\t\tif (weapon->Bullet->IsSubSurface) {\n\t\t\tisbridgetarget = Is_Target_Cell(target);\t// enable shooting at bridges\n\t\t\tisseatarget |= isbridgetarget;\n\t\t}\n\t\tBuildingClass * bldg = ::As_Building(target);\n\t\tif (bldg != NULL && bldg->Class->Speed == SPEED_FLOAT) {\n\t\t\tisseatarget = true;\n\t\t}\n\n\t\tdir = Direction(target);\n\n\t\tif (weapon->Bullet->IsSubSurface) {\n\t\t\tif (!isseatarget && Is_Target_Object(target)) {\n\t\t\t\treturn(FIRE_CANT);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If it's a torpedo, let's check line-of-sight to make sure that\n\t\t\t** there's only water squares between us and the target.\n\t\t\t*/\n\t\t\tObjectClass * obj = As_Object(target);\n\t\t\tCOORDINATE coord = Center_Coord();\n\t\t\tif (obj != NULL) {\n\t\t\t\tint totaldist = ::Distance(coord, obj->Center_Coord());\n\t\t\t\twhile (totaldist > CELL_LEPTON_W) {\n\t\t\t\t\tcoord = Coord_Move(coord, dir, CELL_LEPTON_W);\n\t\t\t\t\tif (Map[coord].Land_Type() != LAND_WATER) {\n\t\t\t\t\t\tif (!isbridgetarget) {\n\t\t\t\t\t\t\treturn(FIRE_RANGE);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Check for friendly boats in the way.\n\t\t\t\t\t*/\n\t\t\t\t\tTechnoClass * tech = Map[coord].Cell_Techno();\n\t\t\t\t\tif (tech != NULL && tech != this && House->Is_Ally(tech)) {\n\t\t\t\t\t\treturn(FIRE_RANGE);\n\t\t\t\t\t}\n\t\t\t\t\ttotaldist -= CELL_LEPTON_W;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tDepth charges are only good against submarines.\n\t\t*/\n\t\tif (weapon->Bullet->IsAntiSub) {\n\t\t\tif (!isseatarget) {\n\t\t\t\treturn(FIRE_CANT);\n\t\t\t} else {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif (Is_Target_Vessel(target) && (*As_Vessel(target) != VESSEL_SS && *As_Vessel(target) != VESSEL_MISSILESUB) ) {\n#else\n\t\t\t\tif (Is_Target_Vessel(target) && *As_Vessel(target) != VESSEL_SS) {\n#endif\n\t\t\t\t\tif (!Is_Target_Vessel(target) || !weapon->Bullet->IsSubSurface) {\n\t\t\t\t\t\treturn(FIRE_CANT);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif (Is_Target_Vessel(target) && (*As_Vessel(target) == VESSEL_SS || *As_Vessel(target) == VESSEL_MISSILESUB)) {\n#else\n\t\t\tif (Is_Target_Vessel(target) && *As_Vessel(target) == VESSEL_SS) {\n#endif\n\t\t\t\treturn(FIRE_CANT);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf this unit cannot fire while moving, then bail.\n\t\t*/\n\t\tif (!Class->IsTurretEquipped && Target_Legal(NavCom)) {\n\t\t\treturn(FIRE_MOVING);\n\t\t}\n\n\t\t/*\n\t\t**\tIf the turret is rotating and the projectile isn't a homing type, then\n\t\t**\tfiring must be delayed until the rotation stops.\n\t\t*/\n\t\tif (!IsFiring && IsRotating && weapon->Bullet->ROT == 0) {\n\t\t\treturn(FIRE_ROTATING);\n\t\t}\n\n\t\t/*\n\t\t**\tDetermine if the turret facing isn't too far off of facing the target.\n\t\t*/\n\t\tif (Class->IsTurretEquipped) {\n\t\t\tdiff = SecondaryFacing.Difference(dir);\n\t\t} else {\n\t\t\tdiff = PrimaryFacing.Difference(dir);\n\t\t}\n\t\tdiff = ABS(diff);\n\n\t\tif (weapon->Bullet->ROT != 0) {\n\t\t\tdiff >>= 2;\n\t\t}\n\t\tif (diff > 8) {\n\t\t\treturn(FIRE_FACING);\n\t\t}\n\t}\n\treturn(fire);\n}\n\n\n/***********************************************************************************************\n * VesselClass::Fire_Coord -- Fetches the coordinate the firing originates from.               *\n *                                                                                             *\n *    This routine is called to determine the coordinate that a fired projectile will          *\n *    originate from.                                                                          *\n *                                                                                             *\n * INPUT:   which -- Which weapon is this query directed at?                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate where a projectile would appear if it were fired.      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/13/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE VesselClass::Fire_Coord(int which) const\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\tCOORDINATE coord = Center_Coord();\n\n\tif (*this == VESSEL_CA) {\n\t\tif (IsSecondShot) {\n\t\t\tcoord = Coord_Move(coord, PrimaryFacing + DIR_S, 0x0100);\n\t\t} else {\n\t\t\tcoord = Coord_Move(coord, PrimaryFacing, 0x0100);\n\t\t}\n\t\tcoord = Coord_Move(coord, DIR_N, 0x0030);\n\t\tcoord = Coord_Move(coord, Turret_Facing(), 0x0040);\n\t\treturn(coord);\n\t}\n\n\tif (*this == VESSEL_PT) {\n\t\tcoord = Coord_Move(coord, PrimaryFacing, 0x0080);\n\t\tcoord = Coord_Move(coord, DIR_N, 0x0020);\n\t\tcoord = Coord_Move(coord, Turret_Facing(), 0x0010);\n\t\treturn(coord);\n\t}\n\n\treturn(DriveClass::Fire_Coord(which));\n}\n\n\n/***********************************************************************************************\n * VesselClass::Init -- Initialize the vessel heap system.                                     *\n *                                                                                             *\n *    This routine is used to clear out the vessel heap. It is called whenever a scenario is   *\n *    being initialized prior to scenario or saved game loading.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   All vessel objects are invalid after this routine is called.                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/13/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselClass::Init(void)\n{\n\tVessels.Free_All();\n}\n\n\n/***********************************************************************************************\n * VesselClass::Greatest_Threat -- Determines the greatest threat (best target) for the vessel *\n *                                                                                             *\n *    This routine is used by ships to determine what target they should go after.             *\n *                                                                                             *\n * INPUT:   threat   -- The threat type that this ship should go after (as determined by the   *\n *                      team mission or general self defense principles).                      *\n *                                                                                             *\n * OUTPUT:  Returns with the target that this ship should attack.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/13/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTARGET VesselClass::Greatest_Threat(ThreatType threat) const\n{\n\tif (*this == VESSEL_SS) {\n\t\tthreat = threat & ThreatType(THREAT_RANGE|THREAT_AREA);\n\t\tthreat = threat | THREAT_BOATS;\n\n\t\t//BG: get subs to attack buildings also.\n\t\tthreat = threat | THREAT_BUILDINGS;\n\t\tthreat = threat | THREAT_FACTORIES;\n\t} else {\n\t\tif ((threat & (THREAT_GROUND|THREAT_POWER|THREAT_FACTORIES|THREAT_TIBERIUM|THREAT_BASE_DEFENSE|THREAT_BOATS)) == 0) {\n\t\t\tif (Class->PrimaryWeapon != NULL) {\n\t\t\t\tthreat = threat | Class->PrimaryWeapon->Allowed_Threats();\n\t\t\t}\n\n\t\t\tif (Class->SecondaryWeapon != NULL) {\n\t\t\t\tthreat = threat | Class->SecondaryWeapon->Allowed_Threats();\n\t\t\t}\n\n//\t\t\tthreat = threat | THREAT_GROUND | THREAT_BOATS;\n\t\t}\n\n\t\t// Cruisers can never hit infantry anyway, so take 'em out of the list\n\t\t// of possible targets.\n\t\tif (*this == VESSEL_CA) {\n\t\t\tthreat = (ThreatType) (threat & (~THREAT_INFANTRY));\n\t\t}\n\t}\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tif (*this == VESSEL_CARRIER) {\n\t\treturn(TARGET_NONE);\n\t}\n#endif\n\treturn(FootClass::Greatest_Threat(threat));\n}\n\n\n/***********************************************************************************************\n * VesselClass::Enter_Idle_Mode -- Causes the vessel to enter its default idle mode.           *\n *                                                                                             *\n *    This routine is called when the vessel is finished with what it is doing, but the next   *\n *    action is not known. This routine will determine what is the appropriate course of       *\n *    action for this vessel and then start it doing that.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselClass::Enter_Idle_Mode(bool )\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\tMissionType\torder = MISSION_GUARD;\n\n\t/*\n\t**\tA movement mission without a NavCom would be pointless to have a radio contact since\n\t**\tno radio coordination occurs on a just a simple movement mission.\n\t*/\n\tif (Mission == MISSION_MOVE && !Target_Legal(NavCom)) {\n\t\tTransmit_Message(RADIO_OVER_OUT);\n\t}\n\n\tHandle_Navigation_List();\n\tif (Target_Legal(NavCom)) {\n\t\torder = MISSION_MOVE;\n\t} else {\n\n\t\tif (Class->PrimaryWeapon == NULL) {\n\t\t\tif (IsALoaner && Class->Max_Passengers() > 0 && Is_Something_Attached() && !Team) {\n\t\t\t\torder = MISSION_UNLOAD;\n\t\t\t} else {\n\t\t\t\torder = MISSION_GUARD;\n\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif (Mission == MISSION_GUARD || Mission == MISSION_GUARD_AREA || MissionControl[Mission].IsParalyzed || MissionControl[Mission].IsZombie) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (House->IsHuman || Team.Is_Valid()) {\n\t\t\t\torder = MISSION_GUARD;\n\t\t\t} else {\n\t\t\t\tif (House->IQ < Rule.IQGuardArea) {\n\t\t\t\t\torder = MISSION_GUARD;\n\t\t\t\t} else {\n\t\t\t\t\torder = MISSION_GUARD_AREA;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tAssign_Mission(order);\n}\n\n\n/***********************************************************************************************\n * VesselClass::Receive_Message -- Handles receiving a radio message.                          *\n *                                                                                             *\n *    This is the handler function for when a vessel receives a radio                          *\n *    message. Typical use of this is when a unit unloads from a lst                           *\n *    class so that clearing of the transport is successful.                                   *\n *                                                                                             *\n * INPUT:   from     -- Pointer to the originator of the message.                              *\n *                                                                                             *\n *          message  -- The radio message received.                                            *\n *                                                                                             *\n *          param    -- Reference to an optional parameter the might be needed to return       *\n *                      information back to the originator of the message.                     *\n *                                                                                             *\n * OUTPUT:  Returns with the radio message response.                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nRadioMessageType VesselClass::Receive_Message(RadioClass * from, RadioMessageType message, long & param)\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\tswitch (message) {\n\n\t\t/*\n\t\t**\tAsks if the passenger can load on this transport.\n\t\t*/\n\t\tcase RADIO_CAN_LOAD:\n\t\t\tif (Class->Max_Passengers() == 0 || from == NULL || !House->Is_Ally(from->Owner())) return(RADIO_STATIC);\n\t\t\tif (How_Many() < Class->Max_Passengers()) {\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tif(*this == VESSEL_CARRIER && from->What_Am_I() == RTTI_AIRCRAFT) {\n\t\treturn(RADIO_ROGER);\n\t}\n#endif\n\t\t\t/*\n\t\t\t** Before saying \"Sure, come on board\", make sure we're adjacent to\n\t\t\t** the shore.\n\t\t\t*/\n\t\t\t\tCELL cell;\n\t\t\t\tDesired_Load_Dir(from, cell);\n\t\t\t\tif(cell) {\n\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn(RADIO_NEGATIVE);\n\n\t\t/*\n\t\t**\tThis message is sent by the passenger when it determines that it has\n\t\t**\tentered the transport.\n\t\t*/\n\t\tcase RADIO_IM_IN:\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tif(*this != VESSEL_CARRIER) {\n#endif\n\t\t\tif (How_Many() == Class->Max_Passengers()) {\n\t\t\t\tLST_Close_Door();\n\t\t\t} else {\n\t\t\t\tDoorShutCountDown = TICKS_PER_SECOND;\n\t\t\t}\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t}\n#endif\n\t\t\treturn(RADIO_ATTACH);\n\n\t\t/*\n\t\t**\tDocking maintenance message received. Check to see if new orders should be given\n\t\t**\tto the impatient unit.\n\t\t*/\n\t\tcase RADIO_DOCKING:\n\n\t\t\t/*\n\t\t\t**\tIf this transport is moving, then always abort the docking request.\n\t\t\t*/\n\t\t\tif (IsDriving || Target_Legal(NavCom)) {\n\t\t\t\treturn(RADIO_NEGATIVE);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCheck for the case of a docking message arriving from a unit that does not\n\t\t\t**\thave formal radio contact established. This might be a unit that is standing\n\t\t\t**\tby. If this transport is free to proceed with normal docking operation, then\n\t\t\t**\testablish formal contact now. If the transport is completely full, then break\n\t\t\t**\toff contact. In all other cases, just tell the pending unit to stand by.\n\t\t\t*/\n\t\t\tif (Contact_With_Whom() != from) {\n\n\t\t\t\t/*\n\t\t\t\t**\tCan't ever load up so tell the passenger to bug off.\n\t\t\t\t*/\n\t\t\t\tif (How_Many() >= Class->Max_Passengers()) {\n\t\t\t\t\treturn(RADIO_NEGATIVE);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tEstablish contact and let the loading process proceed normally.\n\t\t\t\t*/\n\t\t\t\tif (!In_Radio_Contact()) {\n\t\t\t\t\tparam = TARGET_NONE;\n\t\t\t\t\tTransmit_Message(RADIO_HELLO, from);\n\t\t\t\t\tTransmit_Message(RADIO_MOVE_HERE, param);\n\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThis causes the potential passenger to think that all is ok and to\n\t\t\t\t\t**\thold on for a bit.\n\t\t\t\t\t*/\n\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\n\t\t\t*/\n\t\t\tif (Class->Max_Passengers() > 0 && *this == VESSEL_TRANSPORT && How_Many() < Class->Max_Passengers()) {\n\t\t\t\tDriveClass::Receive_Message(from, message, param);\n\n\t\t\t\tif (!IsDriving && !IsRotating) {\n//\t\t\t\tif (!IsDriving && !IsRotating && !IsTethered) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the potential passenger needs someplace to go, then figure out a good\n\t\t\t\t\t**\tspot and tell it to go.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Transmit_Message(RADIO_NEED_TO_MOVE, from) == RADIO_ROGER) {\n\n\t\t\t\t\t\tCELL cell;\n\t\t\t\t\t\tDirType dir = Desired_Load_Dir(from, cell);\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf no adjacent free cells are detected, then passenger loading\n\t\t\t\t\t\t**\tcannot occur. Break radio contact.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (cell == 0) {\n\t\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT, from);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tparam = (long)::As_Target(cell);\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf it is now facing the correct direction, then open the\n\t\t\t\t\t\t\t**\ttransport doors. Close the doors if the transport is full or needs\n\t\t\t\t\t\t\t**\tto rotate.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (!Is_Door_Open()) {\n\t\t\t\t\t\t\t\tLST_Open_Door();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tTell the potential passenger where it should go. If the passenger is\n\t\t\t\t\t\t\t**\talready at the staging location, then tell it to move onto the transport\n\t\t\t\t\t\t\t**\tdirectly.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Transmit_Message(RADIO_MOVE_HERE, param, from) == RADIO_YEA_NOW_WHAT) {\n\t\t\t\t\t\t\t\tif (Is_Door_Open()) {\n\t\t\t\t\t\t\t\t\tparam = (long)As_Target();\n\t\t\t\t\t\t\t\t\tTransmit_Message(RADIO_TETHER);\n\t\t\t\t\t\t\t\t\tif (Transmit_Message(RADIO_MOVE_HERE, param, from) != RADIO_ROGER) {\n\t\t\t\t\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT, from);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tContact_With_Whom()->Unselect();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(RADIO_ROGER);\n\t\t\t}\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\t\tif (Class->Max_Passengers() > 0 && *this == VESSEL_CARRIER && How_Many() < Class->Max_Passengers()) {\n\t\t\t\tTechnoClass::Receive_Message(from, message, param);\n\t\t\t\t/*\n\t\t\t\t**\tEstablish contact with the object if this building isn't already in contact\n\t\t\t\t**\twith another.\n\t\t\t\t*/\n\t\t\t\tif (!In_Radio_Contact()) {\n\t\t\t\t\tTransmit_Message(RADIO_HELLO, from);\n\t\t\t\t}\n\t\t\t\tif (Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {\n\t\t\t\t\tparam = As_Target();\n\t\t\t\t\tif (Transmit_Message(RADIO_MOVE_HERE, param) == RADIO_YEA_NOW_WHAT) {\n\t\t\t\t\t\tTransmit_Message(RADIO_TETHER);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(RADIO_ROGER);\n\t\t\t}\n#endif\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tWhen this message is received, it means that the other object\n\t\t**\thas already turned its radio off. Turn this radio off as well.\n\t\t*/\n\t\tcase RADIO_OVER_OUT:\n\t\t\tif (Mission == MISSION_RETURN) {\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t}\n\t\t\tDriveClass::Receive_Message(from, message, param);\n\t\t\treturn(RADIO_ROGER);\n\n\t}\n\treturn(DriveClass::Receive_Message(from, message, param));\n}\n\n\n/***********************************************************************************************\n * VesselClass::Desired_Load_Dir -- Determines the best cell and facing for loading.           *\n *                                                                                             *\n *    This routine examines the unit and adjacent cells in order to find the best facing       *\n *    for the transport and best staging cell for the potential passengers. This location is   *\n *    modified by adjacent cell passability and direction of the potential passenger.          *\n *                                                                                             *\n * INPUT:   passenger   -- Pointer to the potential passenger.                                 *\n *                                                                                             *\n *          moveto      -- Reference to the cell number that specifies where the potential     *\n *                         passenger should move to first.                                     *\n *                                                                                             *\n * OUTPUT:  Returns with the direction the transport should face before opening the transport  *\n *          door.                                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/01/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nDirType VesselClass::Desired_Load_Dir(ObjectClass * passenger, CELL & moveto) const\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tDetermine the ideal facing that provides the least resistance. This would be the direction\n\t**\tof the potential passenger or the current transport facing if it is going to unload.\n\t*/\n\tDirType faceto;\n\tif (passenger != NULL) {\n\t\tfaceto = Direction(passenger);\n\t} else {\n\t\tfaceto = PrimaryFacing.Current() + DIR_S;\n\t}\n\n\t/*\n\t**\tSweep through the adjacent cells in order to find the best candidate.\n\t*/\n\tFacingType bestdir = FACING_N;\n\tint bestval = -1;\n\tfor (FacingType face = FACING_N; face < FACING_COUNT; face++) {\n\t\tint value = 0;\n\t\tCELL cellnum = Adjacent_Cell(Coord_Cell(Coord), face);\n\n\t\t/*\n\t\t**\tBase the initial value of the potential cell according to whether the passenger is\n\t\t**\tallowed to enter the cell. If it can't, then give such a negative value to the\n\t\t**\tcell so that it is prevented from ever choosing that cell for load/unload.\n\t\t*/\n\t\tif (passenger != NULL) {\n\t\t\tvalue = (passenger->Can_Enter_Cell(cellnum) == MOVE_OK || Coord_Cell(passenger->Coord) == cellnum) ? 128 : -128;\n\t\t} else {\n\t\t\tCellClass * cell = &Map[cellnum];\n\t\t\tif (Ground[cell->Land_Type()].Cost[SPEED_FOOT] == 0 || cell->Flag.Occupy.Building || cell->Flag.Occupy.Vehicle || cell->Flag.Occupy.Monolith || (cell->Flag.Composite & 0x01F) == 0x01F) {\n\t\t\t\tvalue = -128;\n\t\t\t} else {\n\t\t\t\tif (cell->Cell_Techno() && !House->Is_Ally(cell->Cell_Techno())) {\n\t\t\t\t\tvalue = -128;\n\t\t\t\t} else {\n\t\t\t\t\tvalue = 128;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n#if(0)\n\t\t/*\n\t\t**\tGive more weight to the cells that require the least rotation of the transport or the\n\t\t**\tleast roundabout movement for the potential passenger.\n\t\t*/\n\t\tvalue -= (int)ABS((int)(signed char)Facing_Dir(face) - (int)(signed char)faceto);\n\t\tif (face == FACING_S) {\n\t\t\tvalue -= 100;\n\t\t}\n\t\tif (face == FACING_SW || face == FACING_SE) value += 64;\n#endif\n\t\t/*\n\t\t**\tIf the value for the potential cell is greater than the last recorded potential\n\t\t**\tvalue, then record this cell as the best candidate.\n\t\t*/\n\t\tif (bestval == -1 || value > bestval) {\n\t\t\tbestval = value;\n\t\t\tbestdir = face;\n//\t\t} else {\n//\t\t\tObjectClass * obj = Map[cellnum].Cell_Occupier();\n//\t\t\tif (obj) obj->Scatter(Coord, true);\n\t\t}\n\t}\n\n\t/*\n\t**\tIf a suitable direction was found, then return with the direction value.\n\t*/\n\tmoveto = 0;\n\tif (bestval > 0) {\n\t\tstatic DirType _desired_to_actual[FACING_COUNT] = {DIR_S, DIR_SW, DIR_NW, DIR_NW, DIR_NE, DIR_NE, DIR_NE, DIR_SE};\n\n\t\tmoveto = Adjacent_Cell(Coord_Cell(Coord), bestdir);\n\t\treturn(_desired_to_actual[bestdir]);\n\t}\n\treturn(DIR_N);\n}\n\n\n/***********************************************************************************************\n * VesselClass::LST_Open_Door -- Opens a LST door.                                             *\n *                                                                                             *\n *    This routine will initiate opening of the doors on the LST.                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/01/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselClass::LST_Open_Door(void)\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!IsDriving && !IsRotating) {\n\t\tOpen_Door(5, 6);\n\t}\n}\n\n\n/***********************************************************************************************\n * VesselClass::LST_Close_Door -- Closes a LST door.                                           *\n *                                                                                             *\n *    This routine will initiate closing of the LST door.                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/01/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselClass::LST_Close_Door(void)\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\tClose_Door(5, 6);\n}\n\n\n/***********************************************************************************************\n * VesselClass::Mission_Unload -- Handles unloading cargo.                                     *\n *                                                                                             *\n *    This is the AI control sequence for when a transport desires to unload its cargo.\t     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before calling this routine again.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/01/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nint VesselClass::Mission_Unload(void)\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\tenum {\n\t\tINITIAL_CHECK,\n\t\tMANEUVERING,\n\t\tOPENING_DOOR,\n\t\tUNLOADING,\n\t\tCLOSING_DOOR\n\t};\n\tDirType\tdir;\n\tCELL\t\tcell;\n\n\tswitch (Class->Type) {\n\t\tcase VESSEL_TRANSPORT:\n\t\t\tswitch (Status) {\n\t\t\t\tcase INITIAL_CHECK:\n\t\t\t\t\tdir = Desired_Load_Dir(NULL, cell);\n\t\t\t\t\tif (How_Many() > 0 && cell != 0) {\n\t\t\t\t\t\tDo_Turn(dir);\n\t\t\t\t\t\tStatus = MANEUVERING;\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!How_Many()) {\t// don't break out if still carrying passengers\n\t\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase MANEUVERING:\n\t\t\t\t\tif (!IsRotating) {\n\t\t\t\t\t\tLST_Open_Door();\n\t\t\t\t\t\tif (Is_Door_Opening()) {\n\t\t\t\t\t\t\tStatus = OPENING_DOOR;\n\t\t\t\t\t\t\treturn(1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OPENING_DOOR:\n\t\t\t\t\tif (Is_Door_Open()) {\n\t\t\t\t\t\tStatus = UNLOADING;\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!Is_Door_Opening()) {\n\t\t\t\t\t\t\tStatus = INITIAL_CHECK;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase UNLOADING:\n\t\t\t\t\tif (How_Many()) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDon't do anything if still in radio contact.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (In_Radio_Contact()) return(TICKS_PER_SECOND);\n\n\t\t\t\t\t\tFootClass * passenger = Detach_Object();\n\n\t\t\t\t\t\tif (passenger != NULL) {\n\t\t\t\t\t\t\tDirType toface = DIR_S + PrimaryFacing;\n\t\t\t\t\t\t\tbool placed = false;\n\n\t\t\t\t\t\t\tfor (FacingType face = FACING_N; face < FACING_COUNT; face++) {\n\t\t\t\t\t\t\t\tDirType newface = toface + Facing_Dir(face);\n\t\t\t\t\t\t\t\tCELL newcell = Adjacent_Cell(Coord_Cell(Coord), newface);\n\n\t\t\t\t\t\t\t\tif (passenger->Can_Enter_Cell(newcell) == MOVE_OK) {\n\t\t\t\t\t\t\t\t\tScenarioInit++;\n\t\t\t\t\t\t\t\t\tpassenger->Unlimbo(Coord_Move(Coord, newface, CELL_LEPTON_W/2), newface);\n\t\t\t\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t\t\t\t\tpassenger->Assign_Mission(MISSION_MOVE);\n\t\t\t\t\t\t\t\t\tpassenger->Assign_Destination(::As_Target(newcell));\n\t\t\t\t\t\t\t\t\tpassenger->Commence();\n\t\t\t\t\t\t\t\t\tTransmit_Message(RADIO_HELLO, passenger);\n\t\t\t\t\t\t\t\t\tTransmit_Message(RADIO_TETHER, passenger);\n\t\t\t\t\t\t\t\t\tif (passenger->What_Am_I() == RTTI_UNIT) {\n\t\t\t\t\t\t\t\t\t\t((UnitClass *)passenger)->IsToScatter = true;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tplaced = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** If the attached unit could NOT be deployed, then re-attach\n\t\t\t\t\t\t\t**\tit and then bail out of this deploy process.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (!placed) {\n\t\t\t\t\t\t\t\tAttach(passenger);\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t**\tTell everyone around the transport to scatter.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tfor (FacingType face = FACING_N; face < FACING_COUNT; face++) {\n\t\t\t\t\t\t\t\t\tCellClass * cellptr = &Map[Coord].Adjacent_Cell(face);\n\t\t\t\t\t\t\t\t\tif (cellptr->Is_Clear_To_Move(SPEED_TRACK, true, true)) {\n\t\t\t\t\t\t\t\t\t\tcellptr->Incoming(0, true);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n//\t\t\t\t\t\t\t\tStatus = CLOSING_DOOR;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tStatus = CLOSING_DOOR;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tClose LST door in preparation for normal operation.\n\t\t\t\t*/\n\t\t\t\tcase CLOSING_DOOR:\n\t\t\t\t\tif (Is_Door_Open()) {\n\t\t\t\t\t\tLST_Close_Door();\n\t\t\t\t\t}\n\t\t\t\t\tif (Is_Door_Closed()) {\n\t\t\t\t\t\tif (IsALoaner) {\n\t\t\t\t\t\t\tAssign_Mission(MISSION_RETREAT);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(MissionControl[Mission].Normal_Delay());\n}\n\n\n/***********************************************************************************************\n * VesselClass::Assign_Destination -- Assign a destination for this vessel.                    *\n *                                                                                             *\n *    This routine is called when a destination is to be assigned to this vessel.              *\n *                                                                                             *\n * INPUT:   target   -- The destination to assign to this vessel.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselClass::Assign_Destination(TARGET target)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tAbort early if there is anything wrong with the parameters\n\t**\tor the unit already is assigned the specified destination.\n\t*/\n\tif (target == NavCom) return;\n\n\t/*\n\t**\tTransport vehicles must tell all passengers that are about to load, that they\n\t**\tcannot proceed. This is accomplished with a radio message to this effect.\n\t*/\n\tif (In_Radio_Contact() && Class->Max_Passengers() > 0 && (Contact_With_Whom()->Is_Infantry() || Contact_With_Whom()->What_Am_I() == RTTI_UNIT)) {\n\t\tlong param = TARGET_NONE;\n\t\tTransmit_Message(RADIO_MOVE_HERE, param);\t\t// should stop objects heading toward this transport.\n\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\tif (!Is_Door_Closed()) {\n\t\t\tLST_Close_Door();\n\t\t}\n\t}\n\n\tif (!Is_Door_Closed()) {\n\t\tLST_Close_Door();\n\t}\n\n\tDriveClass::Assign_Destination(target);\n}\n\n\n/***********************************************************************************************\n * VesselClass::Mission_Retreat -- Perform the retreat mission.                                *\n *                                                                                             *\n *    This will cause the vessel to run away from the battlefield. It searches for an escape   *\n *    map edge according to the reinforcement edge specified in the house.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before this routine is called      *\n *          again.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint VesselClass::Mission_Retreat(void)\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\tenum {\n\t\tPICK_RETREAT_POINT,\n\t\tTRAVEL\n\t};\n\tswitch (Status) {\n\t\tcase PICK_RETREAT_POINT:\n\t\t\tIsALoaner = true;\n\t\t\tif (!Target_Legal(NavCom)) {\n//\t\t\t\tCELL cell = Map.Calculated_Cell(House->Control.Edge, (Team.Is_Valid()) ? Team->Class->Origin : -1, -1, Class->Speed);\n\t\t\t\tCELL cell = Map.Calculated_Cell(House->Control.Edge, (Team.Is_Valid()) ? Team->Class->Origin : -1, Coord_Cell(Center_Coord()), Class->Speed);\n\t\t\t\tif (Team.Is_Valid()) {\n\t\t\t\t\tTeam->Remove(this);\n\t\t\t\t}\n\t\t\t\tAssign_Destination(::As_Target(cell));\n\t\t\t}\n\t\t\tStatus = TRAVEL;\n\t\t\treturn(1);\n\n\t\tcase TRAVEL:\n\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\tStatus = PICK_RETREAT_POINT;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(MissionControl[Mission].Normal_Delay());\n}\n\n\n/***********************************************************************************************\n * VesselClass::Is_Allowed_To_Recloak -- Can the vessel recloak now?                           *\n *                                                                                             *\n *    Asking this question is part of the recloak process. If the answer is no, then           *\n *    recloaking is postponed. This facilitates keeping submarines visible for longer than     *\n *    they otherwise would be.                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Can this vessel recloak now?                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nbool VesselClass::Is_Allowed_To_Recloak(void) const\n{\n\treturn(PulseCountDown == 0);\n}\n\n\n/***********************************************************************************************\n * VesselClass::Read_INI -- Read the vessel data from the INI database.                        *\n *                                                                                             *\n *    This will read and create all vessels specified in the INI database. This routine is     *\n *    called when the scenario starts.                                                         *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to read the vessel data from.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Vessels will be created and placed on the map by this function.                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselClass::Read_INI(CCINIClass & ini)\n{\n\tVesselClass\t* vessel;\t\t\t// Working vessel pointer.\n\tHousesType\tinhouse;\t\t\t// Vessel house.\n\tVesselType\tclassid;\t\t\t// Vessel class.\n\tchar\t\t\tbuf[128];\n\n\tint len = ini.Entry_Count(INI_Name());\n\tfor (int index = 0; index < len; index++) {\n\t\tchar const * entry = ini.Get_Entry(INI_Name(), index);\n\n\t\tini.Get_String(INI_Name(), entry, NULL, buf, sizeof(buf));\n\t\tinhouse = HouseTypeClass::From_Name(strtok(buf, \",\"));\n\t\tif (inhouse != HOUSE_NONE) {\n\t\t\tclassid = VesselTypeClass::From_Name(strtok(NULL, \",\"));\n\n\t\t\tif (classid != VESSEL_NONE) {\n\n\t\t\t\tvessel = new VesselClass(classid, inhouse);\n\t\t\t\tif (vessel != NULL) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tRead the raw data.\n\t\t\t\t\t*/\n\t\t\t\t\tint strength = atoi(strtok(NULL, \",\\r\\n\"));\n\n\t\t\t\t\tCELL cell = atoi(strtok(NULL, \",\\r\\n\"));\n\n\t\t\t\t\tCOORDINATE coord = Cell_Coord(cell);\n\n\t\t\t\t\tDirType dir = (DirType)atoi(strtok(NULL, \",\\r\\n\"));\n\t\t\t\t\tMissionType mission = MissionClass::Mission_From_Name(strtok(NULL, \",\\n\\r\"));\n\n\t\t\t\t\tvessel->Trigger = NULL;\n\t\t\t\t\tTriggerTypeClass * tp = TriggerTypeClass::From_Name(strtok(NULL, \",\\r\\n\"));\n\t\t\t\t\tif (tp != NULL) {\n\t\t\t\t\t\tTriggerClass * tt = Find_Or_Make(tp);\n\t\t\t\t\t\tif (tt != NULL) {\n\t\t\t\t\t\t\ttt->AttachCount++;\n\t\t\t\t\t\t\tvessel->Trigger = tt;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (vessel->Unlimbo(coord, dir)) {\n\t\t\t\t\t\tvessel->Strength = vessel->Class->MaxStrength * fixed(strength, 256);\n\t\t\t\t\t\tif (vessel->Strength > vessel->Class->MaxStrength-3) vessel->Strength = vessel->Class->MaxStrength;\n//\t\t\t\t\t\tvessel->Strength = Fixed_To_Cardinal(vessel->Class->MaxStrength, strength);\n\t\t\t\t\t\tif (Session.Type == GAME_NORMAL || vessel->House->IsHuman) {\n\t\t\t\t\t\t\tvessel->Assign_Mission(mission);\n\t\t\t\t\t\t\tvessel->Commence();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvessel->Enter_Idle_Mode();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf the vessel could not be unlimboed, then this is a catastrophic error\n\t\t\t\t\t\t**\tcondition. Delete the vessel.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tdelete vessel;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * VesselClass::Write_INI -- Write all vessel scenario data to the INI database.               *\n *                                                                                             *\n *    This routine is used to add the vessel data (needed for scenario start) to the INI       *\n *    database specified. If there was any preexisting vessel data in the database, it will    *\n *    be cleared                                                                               *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the ini database to store the vessel data into.              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselClass::Write_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tFirst, clear out all existing vessel data from the ini file.\n\t*/\n\tini.Clear(INI_Name());\n\n\t/*\n\t**\tWrite the vessel data out.\n\t*/\n\tfor (int index = 0; index < Vessels.Count(); index++) {\n\t\tVesselClass * vessel = Vessels.Ptr(index);\n\t\tif (vessel != NULL && !vessel->IsInLimbo && vessel->IsActive) {\n\t\t\tchar\tuname[10];\n\t\t\tchar\tbuf[128];\n\n\t\t\tsprintf(uname, \"%d\", index);\n\t\t\tsprintf(buf, \"%s,%s,%d,%u,%d,%s,%s\",\n\t\t\t\tvessel->House->Class->IniName,\n\t\t\t\tvessel->Class->IniName,\n\t\t\t\tvessel->Health_Ratio()*256,\n\t\t\t\tCoord_Cell(vessel->Coord),\n\t\t\t\tvessel->PrimaryFacing.Current(),\n\t\t\t\tMissionClass::Mission_Name(vessel->Mission),\n\t\t\t\tvessel->Trigger.Is_Valid() ? vessel->Trigger->Class->IniName : \"None\"\n\t\t\t\t);\n\t\t\tini.Put_String(INI_Name(), uname, buf);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * VesselClass::Start_Driver -- Starts the vessel by reserving the location it is moving to.   *\n *                                                                                             *\n *    This routine is called when the vessel starts moving. It will reserve the destination    *\n *    cell so that it won't be occupied by another vessel as this one is travelling.           *\n *                                                                                             *\n * INPUT:   headto   -- The coordinate that will be headed to.                                 *\n *                                                                                             *\n * OUTPUT:  bool; Was the destination location successfully marked?                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool VesselClass::Start_Driver(COORDINATE & headto)\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (DriveClass::Start_Driver(headto) && IsActive) { //BG IsActive can be cleared by Start_Driver\n\t\tMark_Track(headto, MARK_DOWN);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * VesselClass::What_Action -- Determines action to perform on specified cell.                 *\n *                                                                                             *\n *    This routine will determine what action to perform if the mouse were clicked over the    *\n *    cell specified.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:   cell  -- The cell that the mouse might be clicked on.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the action type that this unit will perform if the mouse were         *\n *          clicked of the cell specified.                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nActionType VesselClass::What_Action(CELL cell) const\n{\n\tassert(Vessels.ID(this) == ID);\n\tassert(IsActive);\n\n\tActionType action = DriveClass::What_Action(cell);\n\tif (action == ACTION_NOMOVE && Map[cell].Land_Type() == LAND_BEACH) {\n\t\treturn(ACTION_MOVE);\n\t}\n\n\tif (action == ACTION_NOMOVE && Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->Bullet->IsSubSurface && Map[cell].Is_Bridge_Here()) {\n\t\treturn(ACTION_ATTACK);\n\t}\n\treturn(action);\n}\n\n\n/***********************************************************************************************\n * VesselClass::Rotation_AI -- Handles turret and body rotation for this vessel.               *\n *                                                                                             *\n *    Any turret or body rotation for this vessel will be handled by this routine.             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per vessel per game logic loop.                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselClass::Rotation_AI(void)\n{\n\tif (Target_Legal(TarCom) && !IsRotating) {\n\t\tDirType dir = Direction(TarCom);\n\n\t\tif (Class->IsTurretEquipped) {\n\t\t\tSecondaryFacing.Set_Desired(dir);\n\t\t}\n\t}\n\n\tIsRotating = false;\n\tif (Class->IsTurretEquipped) {\n\n\t\tif (SecondaryFacing.Is_Rotating()) {\n\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\tif (SecondaryFacing.Rotation_Adjust((Class->ROT * House->GroundspeedBias)+1)) {\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf no further rotation is necessary, flag that the rotation\n\t\t\t**\thas stopped.\n\t\t\t*/\n\t\t\tIsRotating = SecondaryFacing.Is_Rotating();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * VesselClass::Combat_AI -- Handles firing and target selection for the vessel.               *\n *                                                                                             *\n *    This routine will process firing logic for the vessel. It includes searching for targets *\n *    and performing any adjustments necessary to bring the target to bear.                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per vessel per game logic loop.                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselClass::Combat_AI(void)\n{\n\tif (Target_Legal(TarCom) && Is_Weapon_Equipped()) {\n\n\t\t/*\n\t\t**\tDetermine which weapon can fire. First check for the primary weapon. If that weapon\n\t\t**\tcannot fire, then check any secondary weapon. If neither weapon can fire, then the\n\t\t**\tfailure code returned is that from the primary weapon.\n\t\t*/\n\t\tint primary = What_Weapon_Should_I_Use(TarCom);\n\t\tFireErrorType ok = Can_Fire(TarCom, primary);\n\n\t\tswitch (ok) {\n\t\t\tcase FIRE_OK:\n\t\t\t\tFire_At(TarCom, primary);\n\t\t\t\tbreak;\n\n\t\t\tcase FIRE_FACING:\n\t\t\t\tif (Class->IsTurretEquipped) {\n\t\t\t\t\tSecondaryFacing.Set_Desired(Direction(TarCom));\n\t\t\t\t} else {\n\t\t\t\t\tif (!PrimaryFacing.Is_Rotating()) {\n\t\t\t\t\t\tPrimaryFacing.Set_Desired(Direction(TarCom));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase FIRE_CLOAKED:\n\t\t\t\tMark(MARK_OVERLAP_UP);\n\t\t\t\tIsFiring = false;\n\t\t\t\tMark(MARK_OVERLAP_DOWN);\n\t\t\t\tDo_Uncloak();\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * VesselClass::Edge_Of_World_AI -- Determine if vessel is off the edge of the world.          *\n *                                                                                             *\n *    In addition to detecting the edge of world case, this routine will delete the vessel     *\n *    if it occurs.                                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the vessel deleted by this routine?                                      *\n *                                                                                             *\n * WARNINGS:   Be sure to examine the return value and if true, abort any further processing   *\n *             for this vessel since it has been deleted. This routine should be called once   *\n *             per vessel per game logic loop.                                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool VesselClass::Edge_Of_World_AI(void)\n{\n\tif (!IsDriving && !Map.In_Radar(Coord_Cell(Coord)) && IsLocked) {\n\t\tif (Team.Is_Valid()) Team->IsLeaveMap = true;\n\t\tStun();\n\t\tdelete this;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * VesselClass::Repair_AI -- Process any self-repair required of this vessel.                  *\n *                                                                                             *\n *    When a vessel repairs, it does so 'by itself' and not under direct control of another    *\n *    object. This self repair logic is processed here. Upon repair completion of money        *\n *    exhuastion, the repair process will terminate.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine only once per vessel per game logic loop.                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid VesselClass::Repair_AI(void)\n{\n\tif (IsSelfRepairing) {\n\t\tif ((Frame % (TICKS_PER_MINUTE * Rule.RepairRate)) == 0) {\n\t\t\tMark(MARK_CHANGE);\n\t\t\tint cost = Class->Repair_Cost();\n\t\t\tint step = Class->Repair_Step();\n\n\t\t\tif (House->Available_Money() >= cost) {\n\t\t\t\tHouse->Spend_Money(cost);\n\t\t\t\tStrength += step;\n\t\t\t\tif (Strength >= Class->MaxStrength) {\n\t\t\t\t\tStrength = Class->MaxStrength;\n\t\t\t\t\tIsSelfRepairing = IsToSelfRepair = false;\n\t\t\t\t\tif (IsOwnedByPlayer) Speak(VOX_UNIT_REPAIRED);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n/***********************************************************************************************\n * VesselClass::Fire_At -- Try to fire upon the target specified.                              *\n *                                                                                             *\n *    This routine is the auto-fire logic for the ship. It will check                          *\n *    to see if we're an aircraft carrier, and if so, launch one of our                        *\n *    aircraft.  If we're not an aircraft carrier, it lets the higher-level                    *\n *    Fire_At logic take over.                                                                 *\n *                                                                                             *\n * INPUT:   target   -- The target to fire upon.                                               *\n *                                                                                             *\n *          which    -- Which weapon to use when firing. 0=primary, 1=secondary.               *\n *                                                                                             *\n * OUTPUT:  bool; Did firing occur?                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nBulletClass * VesselClass::Fire_At(TARGET target, int which)\n{\n\tassert(Units.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == VESSEL_CARRIER) {\n\t\tArm = CarrierLaunchDelay;\n\t\tFootClass * passenger = Detach_Object();\n\t\tif (passenger != NULL) {\n\t\t\tScenarioInit++;\n\t\t\tpassenger->Unlimbo(Center_Coord());\n\t\t\tScenarioInit--;\n\t\t\tpassenger->Assign_Mission(MISSION_ATTACK);\n\t\t\tpassenger->Assign_Target(TarCom);\n\t\t\tpassenger->Commence();\n// If we've launched our last aircraft, discontinue attacking.\n\t\t\tif (!How_Many()) Assign_Target(TARGET_NONE);\n\t\t}\n\t} else {\n\t\treturn DriveClass::Fire_At(target, which);\n\t}\n\treturn (NULL);\n}\n\n#endif\n"
  },
  {
    "path": "CODE/VESSEL.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/VESSEL.H 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : VESSEL.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/13/96                                                     *\n *                                                                                             *\n *                  Last Update : March 13, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef VESSEL_H\n#define VESSEL_H\n\n#include \"drive.h\"\n#include \"radio.h\"\n#include \"cargo.h\"\n#include \"mission.h\"\n#include\t\"target.h\"\n\nclass VesselClass : public DriveClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis points to the controling static characteristic data associated with\n\t\t**\tthis vessel.\n\t\t*/\n\t\tCCPtr<VesselTypeClass> Class;\n\n\t\t/*\n\t\t** Has this sea vessel been told to move to a shipyard?  If so, then\n\t\t** when we get there, start the repair process.\n\t\t*/\n\t\tunsigned IsToSelfRepair:1;\n\n\t\t/*\n\t\t** Is this sea vessel parked next to a shipyard/subpen, and therefore\n\t\t** in the special self-repair mode?\n\t\t*/\n\t\tunsigned IsSelfRepairing:1;\n\n\t\t/*\n\t\t** If this is an LST, is it time to shut the door?\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> DoorShutCountDown;\n\n\t\t/*\n\t\t** If this is a sub, has the sonar pulse worn off, such that we can\n\t\t** re-submerge?\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> PulseCountDown;\n\n\t\tVesselClass(VesselType classid, HousesType house);\n\t\tVesselClass(NoInitClass const & x) : DriveClass(x), Class(x), SecondaryFacing(x) {};\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\t\toperator VesselType(void) const {return Class->Type;};\n\n\t\tstatic void Init(void);\n\n\t\tvirtual ~VesselClass(void);\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const;\n\n\t\tvirtual MZoneType Zone_Check_Type(void) const {return(MZONE_WATER);}\n\t\tint Shape_Number(void) const;\n\t\tvoid Rotation_AI(void);\n\t\tvoid Combat_AI(void);\n\t\tbool Edge_Of_World_AI(void);\n\t\tvoid Repair_AI(void);\n\t\tvirtual DirType Turret_Facing(void) const {if (Class->IsTurretEquipped) return(SecondaryFacing.Current());return(PrimaryFacing.Current());}\n\t\tvirtual bool Start_Driver(COORDINATE & headto);\n\t\tvirtual int Mission_Retreat(void);\n\t\tvirtual int Mission_Unload(void);\n\t\tvoid LST_Open_Door(void);\n\t\tvoid LST_Close_Door(void);\n\t\tvirtual COORDINATE Fire_Coord(int which) const;\n\t\tvirtual MoveType Can_Enter_Cell(CELL cell, FacingType from=FACING_NONE) const;\n\t\tvirtual void Draw_It(int x, int y, WindowNumberType window) const;\n\t\tvirtual short const * Overlap_List(bool redraw=false) const;\n\t\tvirtual DirType Desired_Load_Dir(ObjectClass * passenger, CELL & moveto) const;\n\t\tvirtual RadioMessageType Receive_Message(RadioClass * from, RadioMessageType message, long & param);\n\t\tvirtual void AI(void);\n\t\tvirtual void Per_Cell_Process(PCPType why);\n\t\tvirtual void Assign_Destination(TARGET target);\n\n\t\tvirtual ResultType Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source=0, int forced=false);\n\t\tvirtual FireErrorType Can_Fire(TARGET target, int which) const;\n\n\t\tvirtual void Enter_Idle_Mode(bool initial=false);\n\t\tvirtual ActionType What_Action(ObjectClass const * object) const;\n\t\tvirtual ActionType What_Action(CELL cell) const;\n\t\tvirtual void Active_Click_With(ActionType action, CELL cell);\n\t\tvirtual void Active_Click_With(ActionType action, ObjectClass * object);\n\t\tvirtual TARGET Greatest_Threat(ThreatType threat) const;\n\t\tvirtual bool Is_Allowed_To_Recloak(void) const;\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\tvirtual BulletClass * Fire_At(TARGET target, int which=0);\n#endif\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tstatic void Read_INI(CCINIClass & ini);\n\t\tstatic void Write_INI(CCINIClass & ini);\n\t\tstatic char * INI_Name(void) {return \"SHIPS\";};\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\n\t\t/*\n\t\t**\tScenario and debug support.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\n\tprotected:\n\t\t/*\n\t\t**\tThis is the facing of the turret. It can be, and usually is,\n\t\t**\trotated independently of the body it is attached to.\n\t\t*/\n\t\tFacingClass SecondaryFacing;\n};\n\n#endif\n"
  },
  {
    "path": "CODE/VISUDLG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/VISUDLG.CPP 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : VISUDLG.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg                                  *\n *                                  Joe L. Bostic                                              *\n *                                                                                             *\n *                   Start Date : Jan 8, 1995                                                  *\n *                                                                                             *\n *                  Last Update : June 18, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   VisualControlsClass::Process -- Process the visual control dialog box.                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"visudlg.h\"\n\n\n/***********************************************************************************************\n * VisualControlsClass::Process -- Process the visual control dialog box.                      *\n *                                                                                             *\n *    This routine displays and processes the visual controls dialog box.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid VisualControlsClass::Process(void)\n{\n\tstatic int _titles[4] = {\n\t\tTXT_BRIGHTNESS,\n\t\tTXT_COLOR,\n\t\tTXT_CONTRAST,\n\t\tTXT_TINT\n\t};\n\n\tenum {\n\t\tNUM_OF_BUTTONS = 6,\n\t};\n\n\t/*\n\t** Make em resolution independent\n\t*/\n\tint option_width = OPTION_WIDTH * RESFACTOR;\t\t\t\t// Width of dialog box.\n\tint option_height = OPTION_HEIGHT * RESFACTOR;\t\t\t// Height of dialog box.\n\tint option_x = OPTION_X * RESFACTOR;\n\tint option_y = OPTION_Y * RESFACTOR;\n\tint text_x = TEXT_X * RESFACTOR;\n\tint text_y = TEXT_Y * RESFACTOR;\n\tint slider_x = SLIDER_X * RESFACTOR;\n\tint slider_y = SLIDER_Y * RESFACTOR;\n\tint slider_width = SLIDER_WIDTH * RESFACTOR;\t\t\t\t// Width of each control slider.\n\tint slider_height = SLIDER_HEIGHT * RESFACTOR;\t\t\t// Height of each control slider.\n\tint slider_y_spacing = SLIDER_Y_SPACING * RESFACTOR;\t// Vertical spacing between sliders.\n\tint button_x = BUTTON_X * RESFACTOR;\t \t\t\t\t\t\t// Options button x pos\n\tint button_y = BUTTON_Y * RESFACTOR; \t\t\t\t\t\t// Options button y pos\n\n\n\t/*\n\t**\tVariables.\n\t*/\n\tint selection;\n\tbool pressed;\n\tint curbutton;\n\tTextButtonClass * buttons[NUM_OF_BUTTONS];\n\tSliderClass * buttonsliders[NUM_OF_BUTTONS];\n\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tCreate Buttons.  Button coords are in pixels, but are window-relative.\n\t*/\n\tTextButtonClass optionsbtn(BUTTON_OPTIONS, TXT_OK, TPF_BUTTON, 0, button_y, 60*RESFACTOR);\n//\tTextButtonClass optionsbtn(BUTTON_OPTIONS, TXT_OPTIONS_MENU, TPF_BUTTON, 0, button_y);\n\tTextButtonClass resetbtn(BUTTON_RESET, TXT_RESET_MENU, TPF_BUTTON, 0, button_y, 80*RESFACTOR);\n\n\t/*\n\t**\tCenters options button.\n\t*/\n\toptionsbtn.X = option_x + (option_width - optionsbtn.Width - (17 * RESFACTOR));\n\tresetbtn.X   = option_x + (17 * RESFACTOR);\n\n\tresetbtn.Add_Tail(optionsbtn);\n\n\t/*\n\t**\tBrightness (value) control.\n\t*/\n\tSliderClass brightness(BUTTON_BRIGHTNESS, slider_x, slider_y + (slider_y_spacing*0), slider_width, slider_height, true);\n\tbrightness.Set_Thumb_Size(20 * RESFACTOR);\n\tbrightness.Set_Value(Options.Get_Brightness() * 256);\n\tbrightness.Add_Tail(optionsbtn);\n\n\t/*\n\t**\tColor (saturation) control.\n\t*/\n\tSliderClass color(BUTTON_COLOR, slider_x, slider_y + (slider_y_spacing*1), slider_width, slider_height, true);\n\tcolor.Set_Thumb_Size(20 * RESFACTOR);\n\tcolor.Set_Value(Options.Get_Saturation() * 256);\n\tcolor.Add_Tail(optionsbtn);\n\n\t/*\n\t**\tContrast control.\n\t*/\n\tSliderClass contrast(BUTTON_CONTRAST, slider_x, slider_y + (slider_y_spacing*2), slider_width, slider_height, true);\n\tcontrast.Set_Thumb_Size(20 * RESFACTOR);\n\tcontrast.Set_Value(Options.Get_Contrast() * 256);\n\tcontrast.Add_Tail(optionsbtn);\n\n\t/*\n\t**\tTint (hue) control.\n\t*/\n\tSliderClass tint(BUTTON_TINT, slider_x, slider_y + (slider_y_spacing*3), slider_width, slider_height, true);\n\ttint.Set_Thumb_Size(20 * RESFACTOR);\n\ttint.Set_Value(Options.Get_Tint() * 256);\n\ttint.Add_Tail(optionsbtn);\n\n\t/*\n\t**\tThis causes left mouse button clicking within the confines of the dialog to\n\t**\tbe ignored if it wasn't recognized by any other button or slider.\n\t*/\n\tGadgetClass dialog(option_x, option_y, option_width, option_height, GadgetClass::LEFTPRESS);\n\tdialog.Add_Tail(optionsbtn);\n\n\t/*\n\t**\tThis causes a right click anywhere or a left click outside the dialog region\n\t**\tto be equivalent to clicking on the return to options dialog.\n\t*/\n\tControlClass background(BUTTON_OPTIONS, 0, 0, SeenBuff.Get_Width(), SeenBuff.Get_Height(),\n\t\t\t\t\t\t\t\t\tGadgetClass::LEFTPRESS|GadgetClass::RIGHTPRESS);\n\tbackground.Add_Tail(optionsbtn);\n\n\tcurbutton = 0;\n\tbuttons[0] = NULL;\n\tbuttons[1] = NULL;\n\tbuttons[2] = NULL;\n\tbuttons[3] = NULL;\n\tbuttons[4] = &resetbtn;\n\tbuttons[5] = &optionsbtn;\n\n\tbuttonsliders[0] = &brightness;\n\tbuttonsliders[1] = &color;\n\tbuttonsliders[2] = &contrast;\n\tbuttonsliders[3] = &tint;\n\tbuttonsliders[4] = NULL;\n\tbuttonsliders[5] = NULL;\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tbool display = true;\n\tbool process = true;\n\tbool partial = true;\n\tpressed = false;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tif (Session.Type == GAME_NORMAL || Session.Type == GAME_SKIRMISH) {\n\t\t\tCall_Back();\n\t\t} else {\n\t\t\tif (Main_Loop()) {\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = true;\n\t\t}\n\t\t#endif\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(option_x, option_y, option_width, option_height);\n\t\t\tDraw_Caption(TXT_VISUAL_CONTROLS, option_x, option_y, option_width);\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t\tpartial = true;\n\t\t}\n\n\t\t/*\n\t\t**\tIf just the buttons and captions need to be redrawn, then do so now.\n\t\t*/\n\t\tif (partial) {\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t**\tDraw the titles.\n\t\t\t*/\n\t\t\tfor (int i = 0; i < (sizeof(_titles)/sizeof(_titles[0])); i++) {\n\t\t\t\tFancy_Text_Print(_titles[i], slider_x - (8 * RESFACTOR), text_y + (i*slider_y_spacing),\n\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT|TPF_RIGHT| ((curbutton == i) ? TPF_BRIGHT_COLOR : TPF_TEXT));\n\t\t\t}\n\t\t\toptionsbtn.Draw_All();\n\t\t\tShow_Mouse();\n\t\t\tpartial = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet and process player input.\n\t\t*/\n\t\tKeyNumType input = optionsbtn.Input();\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_BRIGHTNESS | KN_BUTTON):\n\t\t\t\tOptions.Set_Brightness(fixed(brightness.Get_Value(), 256));\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_COLOR | KN_BUTTON):\n\t\t\t\tOptions.Set_Saturation(fixed(color.Get_Value(), 256));\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_CONTRAST | KN_BUTTON):\n\t\t\t\tOptions.Set_Contrast(fixed(contrast.Get_Value(), 256));\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_TINT | KN_BUTTON):\n\t\t\t\tOptions.Set_Tint(fixed(tint.Get_Value(), 256));\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_RESET | KN_BUTTON):\n\t\t\t\tselection = BUTTON_RESET;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase KN_ESC:\n\t\t\tcase BUTTON_OPTIONS|KN_BUTTON:\n\t\t\t\tselection = BUTTON_OPTIONS;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_LEFT):\n\t\t\t\tif (curbutton <= (BUTTON_TINT - BUTTON_BRIGHTNESS)) {\n\t\t\t\t\tbuttonsliders[curbutton]->Bump(1);\n\t\t\t\t\tswitch (curbutton) {\n\t\t\t\t\t\tcase (BUTTON_BRIGHTNESS - BUTTON_BRIGHTNESS):\n\t\t\t\t\t\t\tOptions.Set_Brightness(fixed(brightness.Get_Value(), 256));\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase (BUTTON_COLOR - BUTTON_BRIGHTNESS):\n\t\t\t\t\t\t\tOptions.Set_Saturation(fixed(color.Get_Value(), 256));\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase (BUTTON_CONTRAST - BUTTON_BRIGHTNESS):\n\t\t\t\t\t\t\tOptions.Set_Contrast(fixed(contrast.Get_Value(), 256));\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase (BUTTON_TINT - BUTTON_BRIGHTNESS):\n\t\t\t\t\t\t\tOptions.Set_Tint(fixed(tint.Get_Value(), 256));\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\t\t\tcurbutton--;\n\t\t\t\t\tif (curbutton < (BUTTON_RESET - BUTTON_BRIGHTNESS) ) {\n\t\t\t\t\t\tcurbutton = (BUTTON_OPTIONS - BUTTON_BRIGHTNESS);\n\t\t\t\t\t}\n\n\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RIGHT):\n\t\t\t\tif (curbutton <= (BUTTON_TINT - BUTTON_BRIGHTNESS)) {\n\t\t\t\t\tbuttonsliders[curbutton]->Bump(0);\n\t\t\t\t\tswitch (curbutton) {\n\t\t\t\t\t\tcase (BUTTON_BRIGHTNESS - BUTTON_BRIGHTNESS):\n\t\t\t\t\t\t\tOptions.Set_Brightness(fixed(brightness.Get_Value(), 256));\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase (BUTTON_COLOR - BUTTON_BRIGHTNESS):\n\t\t\t\t\t\t\tOptions.Set_Saturation(fixed(color.Get_Value(), 256));\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase (BUTTON_CONTRAST - BUTTON_BRIGHTNESS):\n\t\t\t\t\t\t\tOptions.Set_Contrast(fixed(contrast.Get_Value(), 256));\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase (BUTTON_TINT - BUTTON_BRIGHTNESS):\n\t\t\t\t\t\t\tOptions.Set_Tint(fixed(tint.Get_Value(), 256));\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\t\t\tcurbutton++;\n\t\t\t\t\tif (curbutton > (BUTTON_OPTIONS - BUTTON_BRIGHTNESS) ) {\n\t\t\t\t\t\tcurbutton = (BUTTON_RESET - BUTTON_BRIGHTNESS);\n\t\t\t\t\t}\n\n\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_UP):\n\t\t\t\tif (curbutton <= (BUTTON_TINT - BUTTON_BRIGHTNESS) ) {\n\t\t\t\t\tpartial = true;\n\t\t\t\t} else {\n\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t}\n\n\t\t\t\tcurbutton--;\n\t\t\t\tif (curbutton == (BUTTON_RESET - BUTTON_BRIGHTNESS) ) {\n\t\t\t\t\tcurbutton--;\n\t\t\t\t}\n\n\t\t\t\tif (curbutton < 0) {\n\t\t\t\t\tcurbutton = (BUTTON_RESET - BUTTON_BRIGHTNESS);\n\t\t\t\t}\n\n\t\t\t\tif (curbutton <= (BUTTON_TINT - BUTTON_BRIGHTNESS) ) {\n\t\t\t\t\tpartial = true;\n\t\t\t\t} else {\n\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_DOWN):\n\t\t\t\tif (curbutton <= (BUTTON_TINT - BUTTON_BRIGHTNESS) ) {\n\t\t\t\t\tpartial = true;\n\t\t\t\t} else {\n\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t}\n\n\t\t\t\tcurbutton++;\n\t\t\t\tif (curbutton > (BUTTON_RESET - BUTTON_BRIGHTNESS) ) {\n\t\t\t\t\tcurbutton = 0;\n\t\t\t\t}\n\n\t\t\t\tif (curbutton <= (BUTTON_TINT - BUTTON_BRIGHTNESS) ) {\n\t\t\t\t\tpartial = true;\n\t\t\t\t} else {\n\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\t\tselection = curbutton + BUTTON_BRIGHTNESS;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\n\t\tif (pressed) {\n\t\t\tswitch (selection) {\n\t\t\t\tcase (BUTTON_RESET):\n\t\t\t\t\tbrightness.Set_Value(128);\n\t\t\t\t\tcontrast.Set_Value(128);\n\t\t\t\t\tcolor.Set_Value(128);\n\t\t\t\t\ttint.Set_Value(128);\n\n\t\t\t\t\tOptions.Set_Brightness(fixed::_1_2);\n\t\t\t\t\tOptions.Set_Contrast(fixed::_1_2);\n\t\t\t\t\tOptions.Set_Saturation(fixed::_1_2);\n\t\t\t\t\tOptions.Set_Tint(fixed::_1_2);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_OPTIONS):\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tpressed = false;\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "CODE/VISUDLG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/VISUDLG.H 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               *** \n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : VISUDLG.H                                                    *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\t\t\t\t\t Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : Jan 8, 1995                                                  *\n *                                                                                             *\n *                  Last Update : Jan 18, 1995   [MML]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *---------------------------------------------------------------------------------------------*/\n\n#ifndef VISUDLG_H\n#define VISUDLG_H\n\n#include \"gadget.h\"\n\nclass VisualControlsClass \n{\n\tprivate:\n\n\t\tenum VisualControlEnums {\n\t\t\tBUTTON_BRIGHTNESS=1,\n\t\t\tBUTTON_COLOR,\n\t\t\tBUTTON_CONTRAST,\n\t\t\tBUTTON_TINT,\n\t\t\tBUTTON_RESET,\n\t\t\tBUTTON_OPTIONS,\t\t\t\t\t\t\t// Button number for \"Options menu\"\n\t\t\tOPTION_WIDTH=216,\t\t\t\t\t\t\t// Width of dialog box.\n\t\t\tOPTION_HEIGHT=122,\t\t\t\t\t\t// Height of dialog box.\n\t\t\tOPTION_X=(((320 - OPTION_WIDTH) / 2)),\n\t\t\tOPTION_Y=((200 - OPTION_HEIGHT) / 2),\n\t\t\tTEXT_X=OPTION_X+28,\t\t\t \t\t\t// Title's x pos\n\t\t\tTEXT_Y=OPTION_Y+30,  \t\t\t\t\t// Add 11 for each following line\n\t\t\tSLIDER_X=OPTION_X+105, \t\t\t\t\t// Slider's x pos\n\t\t\tSLIDER_Y=OPTION_Y+30,  \t\t\t\t\t// Add 11 for each following line\n\t\t\tSLIDER_WIDTH=70,\t\t\t\t\t\t\t// Width of each control slider.\n\t\t\tSLIDER_HEIGHT=5,\t\t\t\t\t\t\t// Height of each control slider.\n\t\t\tSLIDER_Y_SPACING=11,\t\t\t\t\t\t// Vertical spacing between sliders.\n\t\t\tBUTTON_X=OPTION_X+63,\t \t\t\t\t// Options button x pos\n\t\t\tBUTTON_Y=OPTION_Y+102, \t\t\t\t\t// Options button y pos\n\t\t};\n\n\tpublic:\n\n\t\tVisualControlsClass(void) {};\n\t\tvoid Process(void);\n};\n\n#endif\n"
  },
  {
    "path": "CODE/VORTEX.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*************************************************************************************\n **   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                  **\n *************************************************************************************\n *                                                                                   *\n *                 Project Name : Command & Conquer - Red Alert                      *\n *                                                                                   *\n *                    File Name : VORTEX.CPP                                         *\n *                                                                                   *\n *                   Programmer : Steve Tall                                         *\n *                                                                                   *\n *                   Start Date : August 12th, 1996                                  *\n *                                                                                   *\n *                  Last Update : September 6th, 1996 [ST]                           *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Overview:                                                                         *\n *                                                                                   *\n *  Circley vortexy swirly type thing. (Really just a pixel & color remap).          *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Functions:                                                                        *\n *                                                                                   *\n * CVC::ChronalVortexClass -- vortex class constructor                               *\n * CVC::~ChronalVortexClass -- vortex class destructor                               *\n * CVC::Appear -- Makes a chronal vortex appear at the given coordinate.             *\n * CVC::Disappear -- Makes the chronal vortex go away.                               *\n * CVC::Hide -- Makes the vortex hide. It might come back later.                     *\n * CVC::Show -- Makes a hidden vortex visible again.                                 *\n * CVC::Stop -- Stops the vortex without going through the hide animation            *\n * CVC::Load -- Loads the chronal vortex from a savegame file.                       *\n * CVC::Save -- Saves the vortex class data to a savegame file                       *\n * CVC::AI -- AI for the vortex. Includes movement and firing.                       *\n * CVC::Movement -- Movement AI for the vortex.                                      *\n * CVC::Set_Target -- Make the vortex zap a particular object.                       *\n * CVC::Attack -- look for objects to attack                                         *\n * CVC::Zap_Target -- If the vortex has a target object then zap it with lightning.  *\n * CVC::Coordinate_Remap -- Draws the vortex                                         *\n * CVC::Render -- Renders the vortex at its current position.                        *\n * CVC::Set_Redraw -- Flags the cells under to vortex to redraw.                     *\n * CVC::Setup_Remap_Tables -- Initialises the color remap tables based on theater.   *\n * CVC::Build_Fading_Table -- Builds a fading color lookup table.                    *\n *                                                                                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include \"vortex.h\"\n\n\n/*\n** Instance of chronal vortex class. This must be the only instance.\n*/\nChronalVortexClass\tChronalVortex;\n\n\n\n/***********************************************************************************************\n * CVC::ChronalVortexClass -- vortex class constructor                                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:25PM ST : Created                                                              *\n *=============================================================================================*/\nChronalVortexClass::ChronalVortexClass (void)\n{\n\tActive \t= 0;\n\tTheater \t= THEATER_NONE;\n\tSpeed\t\t= 10;\n\tRange\t\t= 10;\n\tDamage\t= 200;\n\tRenderBuffer = NULL;\t\t//We havn't allocated it yet. It will be allocated as needed.\n}\n\n\n\n/***********************************************************************************************\n * CVC::~ChronalVortexClass -- vortex class destructor                                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:25PM ST : Created                                                              *\n *=============================================================================================*/\nChronalVortexClass::~ChronalVortexClass (void)\n{\n\tif (RenderBuffer) delete RenderBuffer;\n\tActive = 0;\n}\n\n\n\n/***********************************************************************************************\n * CVC::Appear -- Makes a chronal vortex appear at the given coordinate.                       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Coordinate that vortex should appear at.                                          *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: This member does nothing if the vortex is already active                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:27PM ST : Created                                                              *\n *=============================================================================================*/\nvoid ChronalVortexClass::Appear (COORDINATE coordinate)\n{\n\tif (Active) return;\n\n\t/*\n\t** Adjust the given coordinate so the vortex appears in a central position\n\t*/\n\tint x = Lepton_To_Pixel(Coord_X(coordinate));\n\tint y = Lepton_To_Pixel(Coord_Y(coordinate));\n\n\tx -= 32;\n\ty -= 32;\n\n\tLEPTON lx = Pixel_To_Lepton (x);\n\tLEPTON ly = Pixel_To_Lepton (y);\n\n\tPosition = XY_Coord (lx, ly);\n\n\t/*\n\t** Initialise the vortex variables.\n\t*/\n\tAnimateDir \t\t= 1;\n\tAnimateFrame \t= 0;\n\tState\t\t\t\t= STATE_GROW;\n\tActive\t\t\t= true;\n\tAnimate\t\t\t= 0;\n\tStartShutdown\t= false;\n\tLastAttackFrame= Frame;\n\tTargetObject\t= TARGET_NONE;\n\tZapFrame\t\t\t= 0;\n\tHidden\t\t\t= false;\n\tStartHiding\t\t= false;\n\tXDir\t\t\t\t= 0;\n\tYDir\t\t\t\t= 0;\n\n\t/*\n\t** Vortex starts off in a random direction.\n\t*/\n\tDesiredXDir\t\t= Random_Pick (-Speed, Speed);\n\tDesiredYDir\t\t= Random_Pick (-Speed, Speed);\n\n}\n\n\n/***********************************************************************************************\n * CVC::Disappear -- Makes the chronal vortex go away.                                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:30PM ST : Created                                                              *\n *=============================================================================================*/\nvoid ChronalVortexClass::Disappear (void)\n{\n\tif (Hidden) {\n\t\tActive = false;\n\t} else {\n\t\tStartShutdown = true;\n\t}\n}\n\n\n\n/***********************************************************************************************\n * CVC::Hide -- Makes the vortex hide. It might come back later.                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: This doesnt deactivate the vortex. Use Disappear to get rid of it permanently.    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:30PM ST : Created                                                              *\n *=============================================================================================*/\nvoid ChronalVortexClass::Hide (void)\n{\n\tif (!StartShutdown) {\n\t\tStartHiding = true;\n\t}\n}\n\n\n/***********************************************************************************************\n * CVC::Show -- Makes a hidden vortex visible again.                                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:31PM ST : Created                                                              *\n *=============================================================================================*/\nvoid ChronalVortexClass::Show (void)\n{\n\t/*\n\t** Dont do anything if vortx is dying.\n\t*/\n\tif (!StartShutdown) {\n\n\t\t/*\n\t\t** If the vortex is hidden then show it again.\n\t\t*/\n\t\tif (Hidden) {\n\t\t\tHidden = false;\n\t\t\tStartHiding = false;\n\t\t\tAnimateFrame = 0;\n\t\t\tState = STATE_GROW;\n\t\t\tXDir = 0;\n\t\t\tYDir = 0;\n\t\t} else {\n\t\t\t/*\n\t\t\t** If the vortex is in the process of hiding then reverse it.\n\t\t\t*/\n\t\t\tStartHiding = false;\n\t\t\tif (State == STATE_SHRINK) {\n\t\t\t\tState = STATE_GROW;\n\t\t\t\tAnimateFrame = VORTEX_FRAMES - AnimateFrame;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n/***********************************************************************************************\n * CVC::Stop -- Stops the vortex without going through the hide animation                      *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:32PM ST : Created                                                              *\n *=============================================================================================*/\nvoid ChronalVortexClass::Stop(void)\n{\n\tif (Active) Active = false;\n}\n\n\n\n\n/***********************************************************************************************\n * CVC::Load -- Loads the chronal vortex from a savegame file.                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to file                                                                       *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:32PM ST : Created                                                              *\n *=============================================================================================*/\nvoid ChronalVortexClass::Load(Straw &file)\n{\n\t/*\n\t** Delete the render buffer as we are going to lose the pointer anyway.\n\t** It will be re-allocated when needed.\n\t*/\n\tif (RenderBuffer) delete RenderBuffer;\n\n\tfile.Get (this, sizeof (ChronalVortexClass));\n}\n\n\n\n/***********************************************************************************************\n * CVC::Save -- Saves the vortex class data to a savegame file                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    file                                                                              *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:33PM ST : Created                                                              *\n *=============================================================================================*/\nvoid ChronalVortexClass::Save(Pipe &file)\n{\n\tGraphicBufferClass *save_ptr = NULL;\n\n\tif (RenderBuffer){\n\t\t/*\n\t\t** Save the ptr to the render buffer so we can null it for the save\n\t\t*/\n\t\tsave_ptr = RenderBuffer;\n\t\tRenderBuffer = NULL;\n\t}\n\n\tfile.Put (this, sizeof (ChronalVortexClass));\n\n\t/*\n\t** Restore the render buffer ptr\n\t*/\n\tif (save_ptr){\n\t\tRenderBuffer = save_ptr;\n\t}\n}\n\n\n\n/***********************************************************************************************\n * CVC::AI -- AI for the vortex. Includes movement and firing.                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:34PM ST : Created                                                              *\n *=============================================================================================*/\nvoid ChronalVortexClass::AI(void)\n{\n\n\tint chance;\n\n\t/*\n\t** No AI if vortex isnt active\n\t*/\n\tif (Active) {\n\n\t\t/*\n\t\t** Do the movement AI\n\t\t*/\n\t\tMovement();\n\n\t\t/*\n\t\t** Do the attack AI\n\t\t*/\n\t\tZap_Target();\n\n\n\t\tif (Hidden && (Frame - HiddenFrame > 50) ) {\n\t\t\t/*\n\t\t\t** Vortex is hidden. Chance of it showing itself increases the longer its stays hidden.\n\t\t\t*/\n\t\t\tchance = Random_Pick(0,2000);\n\t\t\tif (chance <= Frame - HiddenFrame) {\n\t\t\t\tShow();\n\t\t\t}\n\t\t} else {\n\n\t\t\tif (Animate == 0) {\n\n\t\t\t\t/*\n\t\t\t\t** Its time to animate the vortex.\n\t\t\t\t*/\n\t\t\t\tAnimateFrame += AnimateDir;\n\n\t\t\t\tif (AnimateFrame > VORTEX_FRAMES) {\n\t\t\t\t\t/*\n\t\t\t\t\t** State changes can only occur on final animation frames.\n\t\t\t\t\t*/\n\t\t\t\t\tAnimateFrame = 1;\n\n\t\t\t\t\tif (StartShutdown) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Vortex is in the process of dying.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (State == STATE_SHRINK) {\n\t\t\t\t\t\t\tSet_Redraw();\n\t\t\t\t\t\t\tActive = false;\n\t\t\t\t\t\t\tAnimateFrame = 0;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tAttack();\n\t\t\t\t\t\t\tState = STATE_SHRINK;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tif (StartHiding) {\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Vortex wants to hide.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (State == STATE_SHRINK) {\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** Hide the vortex now.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tSet_Redraw();\n\t\t\t\t\t\t\t\tStartHiding = false;\n\t\t\t\t\t\t\t\tHidden = true;\n\t\t\t\t\t\t\t\tHiddenFrame = Frame;\n\t\t\t\t\t\t\t\tif (Random_Pick(0,4) == 4) {\n\t\t\t\t\t\t\t\t\tDisappear();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** Start hiding the vortex.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tAttack();\n\t\t\t\t\t\t\t\tState = STATE_SHRINK;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tAttack();\n\t\t\t\t\t\t\tif (State == STATE_GROW) {\n\t\t\t\t\t\t\t\tState = STATE_ROTATE;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t//Attack();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (AnimateFrame == VORTEX_FRAMES / 2) Attack();\n\t\t\t\t}\n\t\t\t}\n\t\t\tAnimate++;\n\t\t\tAnimate &= 1;\n\t\t}\n\t}\n}\n\n\n\n\n\n/***********************************************************************************************\n * CVC::Movement -- Movement AI for the vortex.                                                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:39PM ST : Created                                                              *\n *=============================================================================================*/\nvoid ChronalVortexClass::Movement (void)\n{\n\tbool newpick = true;\n\n\t/*\n\t** Update the vortex position by applying the x and y direction variables\n\t*/\n\tLEPTON x = Coord_X(Position);\n\tLEPTON y = Coord_Y(Position);\n\n\tx += XDir;\n\ty += YDir;\n\n\tPosition = XY_Coord (x,y);\n\n\t/*\n\t** Reverse the direction of the vortex if its drifting off the map.\n\t*/\n\tif (x > CELL_LEPTON_W *(Map.MapCellX + Map.MapCellWidth -4)) {\n\t\tnewpick = false;\n\t\tif (DesiredXDir >0 ) DesiredXDir = -DesiredXDir;\n\t}\n\n\tif (y > CELL_LEPTON_H *(Map.MapCellY + Map.MapCellHeight -4)) {\n\t\tnewpick = false;\n\t\tif (DesiredYDir >0 ) DesiredYDir = -DesiredYDir;\n\t}\n\n\tif (x < CELL_LEPTON_W *Map.MapCellX + 2*CELL_LEPTON_W) {\n\t\tnewpick = false;\n\t\tif (DesiredXDir <0 ) DesiredXDir = -DesiredXDir;\n\t}\n\n\tif (y < CELL_LEPTON_H *Map.MapCellY + 2*CELL_LEPTON_W) {\n\t\tnewpick = false;\n\t\tif (DesiredYDir <0 ) DesiredYDir = -DesiredYDir;\n\t}\n\n\t/*\n\t** Vortex direction tends towards the desired direction unless the vortex is shutting down or\n\t**\tappearing in which case the direction tends towards 0.\n\t*/\n\tif (State == STATE_ROTATE || Hidden) {\n\t\tif (XDir < DesiredXDir) XDir ++;\n\t\tif (XDir > DesiredXDir) XDir --;\n\t\tif (YDir < DesiredYDir) YDir ++;\n\t\tif (YDir > DesiredYDir) YDir --;\n\t} else {\n\t\tif (XDir > 0) XDir -= Speed/8;\n\t\tif (XDir < 0) XDir += Speed/8;\n\t\tif (YDir > 0) YDir -= Speed/8;\n\t\tif (YDir < 0) YDir += Speed/8;\n\t}\n\n\t/*\n\t** Occasionally change the direction of the vortex.\n\t*/\n\tif (newpick && Random_Pick (0, 100) == 100) {\n\t\tDesiredXDir\t\t= Random_Pick (-Speed, Speed);\n\t\tDesiredYDir\t\t= Random_Pick (-Speed, Speed);\n\t}\n}\n\n\n\n/***********************************************************************************************\n * CVC::Set_Target -- Make the vortex zap a particular object.                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to object to zap                                                              *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:42PM ST : Created                                                              *\n *=============================================================================================*/\nvoid ChronalVortexClass::Set_Target (ObjectClass *target)\n{\n\tif (Active){\n\t\tZapFrame = 0;\n\t\tTargetObject = TARGET_NONE;\n\t\tif (target != NULL) TargetObject = target->As_Target();\n\t\tLastAttackFrame = Frame;\n\t\tTargetDistance = (target != NULL) ? Distance (target->Center_Coord(), Position) : 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * CVC::Attack -- look for objects to attack                                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:42PM ST : Created                                                              *\n *=============================================================================================*/\nvoid ChronalVortexClass::Attack(void)\n{\n\tint distance;\n// if(TargetObject) return;\n// if(!TargetObject) return;\n\t/*\n\t** Calculate the position of the center of the vortex.\n\t*/\n\tint x = Lepton_To_Pixel(Coord_X(Position));\n\tint y = Lepton_To_Pixel(Coord_Y(Position));\n\n\tx += 32;\n\ty += 12;\n\n\tLEPTON lx = Pixel_To_Lepton (x);\n\tLEPTON ly = Pixel_To_Lepton (y);\n\n\tCOORDINATE here = XY_Coord (lx, ly);\n\n\t/*\n\t** Scan through the ground layer objects and see who we should attack\n\t*/\n\n\t/*\n\t** First scan - find any object directly above the vortex.\n\t*/\n\tfor (unsigned i= 0; i < Map.Layer[LAYER_GROUND].Count(); i++) {\n\t\tObjectClass * obj = Map.Layer[LAYER_GROUND][i];\n\n\t\tif ( obj->Is_Techno() && obj->Strength > 0 ) {\n\n\t\t\tdistance = Distance (obj->Center_Coord(), here);\n\n\t\t\tif (distance <= CELL_LEPTON_W*2) {\n\t\t\t\tSet_Target (obj);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** If we found something to attack then just return\n\t*/\n\tif (!Target_Legal(TargetObject)) return;\n\n\n\t/*\n\t** Scan through all ground level objects.\n\t**\n\t** Objects within range have a chance of being selected based on their distance from the vortex.\n\t*/\n\n\tint chance = Random_Pick (0, 1000);\n\tif (chance > Frame - LastAttackFrame) return;\n\n\tfor (i= 0; i < Map.Layer[LAYER_GROUND].Count(); i++) {\n\t\tObjectClass * obj = Map.Layer[LAYER_GROUND][i];\n\n\t\tif ( obj && obj->Is_Techno() ) {\n\n\t\t\tdistance = Distance (obj->Center_Coord(), Position);\n\n\t\t\tif (distance < CELL_LEPTON_W * Range) {\n\t\t\t\tchance = Random_Pick (0, distance);\n\t\t\t\tif (chance < CELL_LEPTON_W) {\n\t\t\t\t\tSet_Target (obj);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n\n/***********************************************************************************************\n * CVC::Zap_Target -- If the vortex has a target object then zap it with lightning.            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:45PM ST : Created                                                              *\n *=============================================================================================*/\n#define\tZAP_COUNT\t1\nvoid ChronalVortexClass::Zap_Target (void)\n{\n\tif (!Hidden && Target_Legal(TargetObject) && ZapFrame < ZAP_COUNT) {\n\n\t\t/*\n\t\t** Get the center of the vortex.\n\t\t*/\n\t\tint x = Lepton_To_Pixel(Coord_X(Position));\n\t\tint y = Lepton_To_Pixel(Coord_Y(Position));\n\n\t\tx += 32;\n\t\ty += 12;\n\n\t\tLEPTON lx = Pixel_To_Lepton (x);\n\t\tLEPTON ly = Pixel_To_Lepton (y);\n\n\t\tCOORDINATE here = XY_Coord (lx, ly);\n\n\t\t/*\n\t\t** Create a temporary techno object se we can access the lightning ability of the tesla.\n\t\t*/\n\t\tTechnoClass *temptech = new BuildingClass (STRUCT_TESLA, HOUSE_GOOD);\n\t\tif (temptech != NULL) {\n\t\t\ttemptech->Coord = here;\n\t\t\tObjectClass * obj = As_Object(TargetObject);\n\t\t\tTARGET target = As_Target (obj->Center_Coord());\n\t\t\tSound_Effect(VOC_TESLA_ZAP, obj->Center_Coord());\n\t\t\ttemptech->Electric_Zap (target, 0, here, LightningRemap);\n\t\t\tdelete temptech;\n\n\t\t\t/*\n\t\t\t** Flag the whole map to redraw to cover the lightning.\n\t\t\t*/\n\t\t\tMap.Flag_To_Redraw(true);\n\n\t\t\t/*\n\t\t\t** Zap the target 3 times but only do damage on the last frame.\n\t\t\t*/\n\t\t\tZapFrame++;\n\n\t\t\tif (ZapFrame == ZAP_COUNT) {\n\t\t\t\tZapFrame = 0;\n\t\t\t\tint damage = Damage;\n\t\t\t\tobj->Take_Damage(damage, TargetDistance, WARHEAD_TESLA, NULL, 1);\n\t\t\t\tTargetObject = TARGET_NONE;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Vortex might pretend to go away after zapping the target.\n\t\t*/\n\t\tif (Random_Pick (0,2) == 2) Hide();\n\t}\n}\n\n\n\n\n\n/***********************************************************************************************\n * CVC::Coordinate_Remap -- Draws the vortex                                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to view port to draw the vortex into                                          *\n *           x offset                                                                          *\n *           y offset                                                                          *\n *           width of vortex                                                                   *\n *           height of vortex                                                                  *\n *           ptr to shading remap tables                                                       *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:48PM ST : Created                                                              *\n *=============================================================================================*/\nvoid ChronalVortexClass::Coordinate_Remap ( GraphicViewPortClass *inbuffer, int x, int y, int width, int height, unsigned char *remap_table)\n{\n\tunsigned char\tgetx,gety, remap_color, pixel_color;\n\n\n\tBufferClass destbuf (width * height);\n\n\tunsigned char *destptr = (unsigned char*) destbuf.Get_Buffer();\n\n\tint destx = x;\n\tint desty = y;\n\n\tint dest_width = width;\n\tint dest_height = height;\n\n\tif (inbuffer->Lock()) {\n\n\t\t/*\n\t\t** Get a pointer to the section of buffer we are going to work on.\n\t\t*/\n\t\tunsigned char *bufptr = (unsigned char *) inbuffer->Get_Offset()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t + destx\n#ifdef WIN32\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t + desty* (inbuffer->Get_Width() + inbuffer->Get_XAdd() + inbuffer->Get_Pitch());\n#else\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t + desty* (inbuffer->Get_Width() + inbuffer->Get_XAdd());\n#endif\n\n\n#ifdef WIN32\n\t\tint modulo = inbuffer->Get_Pitch() + inbuffer->Get_XAdd() + inbuffer->Get_Width();\n#else\n\t\tint modulo = inbuffer->Get_XAdd() + inbuffer->Get_Width();\n#endif\n\n\n\t\tfor (int yy = desty ; yy < desty+dest_height ; yy++) {\n\t\t\tfor (int xx = destx ; xx < destx+dest_width ; xx++) {\n\t\t\t\t/*\n\t\t\t\t** Get the coordinates of the pixel to draw\n\t\t\t\t*/\n\t\t\t\tgetx = *(remap_table++);\n\t\t\t\tgety = *(remap_table++);\n\t\t\t\tremap_color = *(remap_table++);\n\n\t\t\t\tpixel_color = * (bufptr + getx + (gety * modulo) );\n\n\t\t\t\t*(destptr++) = VortexRemapTables [remap_color] [pixel_color];\n\t\t\t}\n\n\t\t\tremap_table += 3*(width - dest_width);\n\t\t\tdestptr += width - dest_width;\n\n\t\t}\n\n\t\tdestbuf.To_Page(destx, desty, dest_width, dest_height, *inbuffer);\n\n\n\t\tinbuffer->Unlock();\n\t}\n}\n\n\n\n/***********************************************************************************************\n * CVC::Render -- Renders the vortex at its current position.                                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:49PM ST : Created                                                              *\n *=============================================================================================*/\nvoid ChronalVortexClass::Render (void)\n{\n\tif (Active && !Hidden) {\n\t\tchar fname [80];\n\n\t\tint frame;\n\n\t\t/*\n\t\t** Calculate which coordinate lookup table we should be using for this frame.\n\t\t*/\n\t\tswitch (State) {\n\t\t\tcase STATE_GROW:\n\t\t\t\tframe = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase STATE_ROTATE:\n\t\t\t\tframe = VORTEX_FRAMES;\n\t\t\t\tbreak;\n\n\t\t\tcase STATE_SHRINK:\n\t\t\t\tframe = VORTEX_FRAMES*2;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tframe += AnimateFrame;\n\n\t\tsprintf (fname, \"HOLE%04d.lut\", frame);\n\n\t\tvoid const *lut_ptr = MFCD::Retrieve(fname);\n\t\tif (lut_ptr) {\n\n\t\t\t/*\n\t\t\t** Build a representation of the area of the screen where the vortex will be\n\t\t\t** in an off-screen buffer.\n\t\t\t** This is necessary for clipping as we cant remap pixels from off screen if we build\n\t\t\t** the image from the hidpage.\n\t\t\t*/\n\t\t\tif (!RenderBuffer) {\n\t\t\t\tRenderBuffer = new GraphicBufferClass(CELL_PIXEL_W * 4, CELL_PIXEL_H * 4, (void*)NULL);\n\t\t\t}\n\t\t\tCELL xc = Coord_XCell (Position);\n\t\t\tCELL yc = Coord_YCell (Position);\n\t\t\tCellClass *cellptr;\n\t\t\tCELL cell;\n\t\t\tTemplateTypeClass const * ttype = 0;\n\t\t\tint\ticon;\t\t// The icon number to use from the template set.\n\n\n#ifdef WIN32\n\t\t\tGraphicViewPortClass * oldpage = Set_Logic_Page(RenderBuffer);\n#else\n\t\t\tGraphicBufferClass * oldpage = Set_Logic_Page(RenderBuffer);\n#endif\n\n\t\t\t/*\n\t\t\t** Temporarily modify the tactical window so it works with our offscreen buffer\n\t\t\t*/\n\t\t\tint wx = WindowList[WINDOW_TACTICAL][WINDOWX];\n\t\t\tint wy = WindowList[WINDOW_TACTICAL][WINDOWY];\n\t\t\tint ww = WindowList[WINDOW_TACTICAL][WINDOWWIDTH];\n\t\t\tint wh = WindowList[WINDOW_TACTICAL][WINDOWHEIGHT];\n\n\t\t\tWindowList[WINDOW_TACTICAL][WINDOWX] = 0;\n\t\t\tWindowList[WINDOW_TACTICAL][WINDOWY] = 0;\n\t\t\tWindowList[WINDOW_TACTICAL][WINDOWWIDTH] = RenderBuffer->Get_Width();\n\t\t\tWindowList[WINDOW_TACTICAL][WINDOWHEIGHT] = RenderBuffer->Get_Height();\n\n\n\t\t\t/*\n\t\t\t** Loop through all the cells that the vortex overlaps and render the template, smudge\n\t\t\t** and overlay for each cell.\n\t\t\t*/\n\t\t\tfor (int y = 0 ; y<4 ; y++) {\n\t\t\t\tfor (int x = 0 ; x<4 ; x++) {\n\n\t\t\t\t\tcell = XY_Cell (xc+x,yc+y);\n\t\t\t\t\tif (cell != -1) {\n\n\t\t\t\t\t\t//cellptr = &Map[ Coord_Whole (Cell_Coord(cell)) ];\n\t\t\t\t\t\tcellptr = &Map [cell];\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tFetch a pointer to the template type associated with this cell.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (cellptr->TType != TEMPLATE_NONE && cellptr->TType != TEMPLATE_CLEAR1 && cellptr->TType != 255) {\n\t\t\t\t\t\t\tttype = &TemplateTypeClass::As_Reference(cellptr->TType);\n\t\t\t\t\t\t\ticon = cellptr->TIcon;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tttype = &TemplateTypeClass::As_Reference(TEMPLATE_CLEAR1);\n\t\t\t\t\t\t\ticon = cellptr->Clear_Icon();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Draw the template\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (ttype->Get_Image_Data()) {\n\t\t\t\t\t\t\tRenderBuffer->Draw_Stamp(ttype->Get_Image_Data(), icon, x*CELL_PIXEL_W, y*CELL_PIXEL_H, NULL, WINDOW_MAIN);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDraw any smudge.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (cellptr->Smudge != SMUDGE_NONE) {\n\t\t\t\t\t\t\tSmudgeTypeClass::As_Reference(cellptr->Smudge).Draw_It(x*CELL_PIXEL_W, y*CELL_PIXEL_H, cellptr->SmudgeData);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDraw the overlay object.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (cellptr->Overlay != OVERLAY_NONE) {\n\t\t\t\t\t\t\tOverlayTypeClass const & otype = OverlayTypeClass::As_Reference(cellptr->Overlay);\n\t\t\t\t\t\t\tIsTheaterShape = (bool)otype.IsTheater;\t//Tell Build_Frame if this overlay is theater specific\n\t\t\t\t\t\t\tCC_Draw_Shape(otype.Get_Image_Data(),\n\t\t\t\t\t\t\t\t\t\t\t\tcellptr->OverlayData,\n\t\t\t\t\t\t\t\t\t\t\t\tx*CELL_PIXEL_W + (CELL_PIXEL_W >> 1),\n\t\t\t\t\t\t\t\t\t\t\t\ty*CELL_PIXEL_H + (CELL_PIXEL_H >> 1),\n\t\t\t\t\t\t\t\t\t\t\t\tWINDOW_TACTICAL,\n\t\t\t\t\t\t\t\t\t\t\t\tSHAPE_CENTER|SHAPE_WIN_REL|SHAPE_GHOST,\n\t\t\t\t\t\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t\t\t\t\t\tDisplayClass::UnitShadow);\n\n\t\t\t\t\t\t\tIsTheaterShape = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\tSet_Logic_Page(oldpage);\n\n\t\t\t/*\n\t\t\t** Restore the tactical window to its correct value\n\t\t\t*/\n\t\t\tWindowList[WINDOW_TACTICAL][WINDOWX] = wx;\n\t\t\tWindowList[WINDOW_TACTICAL][WINDOWY] = wy;\n\t\t\tWindowList[WINDOW_TACTICAL][WINDOWWIDTH] = ww;\n\t\t\tWindowList[WINDOW_TACTICAL][WINDOWHEIGHT] = wh;\n\n\t\t\t/*\n\t\t\t** Render the vortex over the cells we just rendered to our buffer\n\t\t\t*/\n\t\t\tCoordinate_Remap (RenderBuffer, Lepton_To_Pixel(Coord_X(Coord_Fraction(Position))),\n\t\t\t\t\t\t\t\t\t\t\tLepton_To_Pixel(Coord_Y(Coord_Fraction(Position))),\n\t\t\t\t\t\t\t\t\t\t\t64,\n\t\t\t\t\t\t\t\t\t\t\t64,\n\t\t\t\t\t\t\t\t\t\t\t(unsigned char*) lut_ptr);\n\n\n\t\t\t/*\n\t\t\t** Calculate the pixel position of our fresh block of cells on the tactical map so\n\t\t\t**\twe can blit it to the hid page.\n\t\t\t*/\n\t\t\tCOORDINATE render_pos = XY_Coord(xc * CELL_LEPTON_W, yc * CELL_LEPTON_H);\t//Coord_Whole(Position);\n\n\t\t\tint xtac = Pixel_To_Lepton(Lepton_To_Pixel(Coord_X(Map.TacticalCoord)));\n\t\t\tint xoff = Pixel_To_Lepton(Lepton_To_Pixel(Coord_X(render_pos)));\n\t\t\txoff -= xtac;\n\n\t\t\tint ytac = Pixel_To_Lepton(Lepton_To_Pixel(Coord_Y(Map.TacticalCoord)));\n\t\t\tint yoff = Pixel_To_Lepton(Lepton_To_Pixel(Coord_Y(render_pos)));\n\t\t\tyoff -= ytac;\n\n\n\t\t\t/*\n\t\t\t** Create a view port to blit to\n\t\t\t*/\n\t\t\tGraphicViewPortClass target (LogicPage->Get_Graphic_Buffer(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t\t\t\t\t8*RESFACTOR + LogicPage->Get_YPos(),\n\t\t\t\t\t\t\t\t\t\t\t\t\tLepton_To_Pixel (Map.TacLeptonWidth),\n\t\t\t\t\t\t\t\t\t\t\t\t\tLepton_To_Pixel (Map.TacLeptonHeight));\n\n\n\t\t\t/*\n\t\t\t** Do some clipping since the library clipping gets it wrong.\n\t\t\t*/\n\t\t\tint diff;\n\n\t\t\tint source_x = 0;\n\t\t\tint source_y = 0;\n\t\t\tint source_width = CELL_PIXEL_W*4;\n\t\t\tint source_height = CELL_PIXEL_H*4;\n\n\t\t\tint dest_x = Lepton_To_Pixel (xoff);\n\t\t\tint dest_y = Lepton_To_Pixel (yoff);\n\t\t\tint dest_width = source_width;\n\t\t\tint dest_height = source_height;\n\n\t\t\tif (dest_x < 0) {\n\t\t\t\tsource_width += dest_x;\n\t\t\t\tdest_width += dest_x;\n\t\t\t\tsource_x -= dest_x;\n\t\t\t\tdest_x = 0;\n\t\t\t}\n\n\t\t\tif (dest_y <0) {\n\t\t\t\tsource_height += dest_y;\n\t\t\t\tdest_height += dest_y;\n\t\t\t\tsource_y -= dest_y;\n\t\t\t\tdest_y = 0;\n\t\t\t}\n\n\t\t\tif (dest_x + dest_width > target.Get_Width() ) {\n\t\t\t\tdiff = dest_x + dest_width - target.Get_Width();\n\t\t\t\tdest_width -= diff;\n\t\t\t\tsource_width -= diff;\n\t\t\t}\n\n\t\t\tif (dest_y + dest_height > target.Get_Height() ) {\n\t\t\t\tdiff = dest_y + dest_height - target.Get_Height();\n\t\t\t\tdest_height -= diff;\n\t\t\t\tsource_height -= diff;\n\t\t\t}\n\n\n\t\t\t/*\n\t\t\t** Blit our freshly draw cells and vortex into their correct position on the hidpage\n\t\t\t*/\n\t\t\tif (dest_width > 0 && dest_height > 0) {\n\t\t\t\tRenderBuffer->Blit (target, source_x, source_y, dest_x, dest_y, dest_width, dest_height, false);\n\t\t\t}\n\n\t\t}\n\t}\n}\n\n\n\n/***********************************************************************************************\n * CVC::Set_Redraw -- Flags the cells under to vortex to redraw.                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:50PM ST : Created                                                              *\n *=============================================================================================*/\nvoid ChronalVortexClass::Set_Redraw(void)\n{\n\n\tif (Active) {\n\n\t\tCELL xc = Coord_XCell (Position);\n\t\tCELL yc = Coord_YCell (Position);\n\n\t\tCELL cell;\n\n\t\tfor (int y = MAX(0,yc - 1) ; y< yc+4 ; y++) {\n\t\t\tfor (int x = MAX(0, xc-1) ; x< xc + 4 ; x++) {\n\t\t\t\tcell = XY_Cell (x,y);\n\t\t\t\tif (cell != -1) {\n\t\t\t\t\tMap[cell].Redraw_Objects();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n\n/***********************************************************************************************\n * CVC::Setup_Remap_Tables -- Initialises the color remap tables based on theater.             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Theater                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:51PM ST : Created                                                              *\n *=============================================================================================*/\nvoid ChronalVortexClass::Setup_Remap_Tables (TheaterType theater)\n{\n\t/*\n\t** The names of the remap files for each theater\n\t*/\n\tstatic char _remaps[3][13] ={\n\t\t\"TEMP_VTX.PAL\",\n\t\t\"SNOW_VTX.PAL\",\n\t\t\"INTR_VTX.PAL\"\n\t};\n\n\tint i;\n\n\t/*\n\t** If the theater has changed then load the remap tables from disk if they exist or create\n\t** them if they dont.\n\t*/\n\tif (theater != Theater) {\n\n\t\tTheater = theater;\n\n\t\tCCFileClass file (_remaps[(int)Theater]);\n\n\t\tif (file.Is_Available()) {\n\t\t\tfile.Read (VortexRemapTables, MAX_REMAP_SHADES*256);\n\t\t} else {\n\n\t\t\tfor (i=0 ; i<MAX_REMAP_SHADES ; i++) {\n\t\t\t\tBuild_Fading_Table ( GamePalette, &VortexRemapTables[i][0], 0, 240- ((i*256)/MAX_REMAP_SHADES) );\n\t\t\t}\n\n\t\t\tfile.Write (VortexRemapTables, MAX_REMAP_SHADES*256);\n\t\t}\n\t}\n\n\t/*\n\t** Set up the remap table for the lightning\n\t*/\n\tfor (i=0 ; i<256 ; i++) {\n\t\tLightningRemap[i] = i;\n\t}\n\tLightningRemap[192] = 208;\n\tLightningRemap[193] = 209;\n\tLightningRemap[194] = 210;\n\tLightningRemap[195] = 211;\n\tLightningRemap[196] = 212;\n\tLightningRemap[197] = 213;\n\tLightningRemap[198] = 214;\n\tLightningRemap[199] = 215;\n}\n\n\n\n\n/***********************************************************************************************\n * CVC::Build_Fading_Table -- Builds a fading color lookup table.                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to palette to base tables on                                                  *\n *           ptr to buffer to put clut in.                                                     *\n *           color to bias colors to                                                           *\n *           percentage of bias                                                                *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: Based on Conquer_Build_Fading_Table                                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/29/96 4:53PM ST : Created                                                              *\n *=============================================================================================*/\nvoid ChronalVortexClass::Build_Fading_Table(PaletteClass const & palette, void * dest, int color, int frac)\n{\n\tif (dest) {\n\t\tunsigned char * ptr = (unsigned char *)dest;\n\n\t\t/*\n\t\t**\tFind an appropriate remap color index for every color in the palette.\n\t\t**\tThere are certain exceptions to this, but they are trapped within the\n\t\t**\tloop.\n\t\t*/\n\t\tfor (int index = 0; index < PaletteClass::COLOR_COUNT; index++) {\n\n\t\t\t/*\n\t\t\t**\tIf this color should not be remapped, then it will be stored as a remap\n\t\t\t**\tto itself. This is effectively no remap.\n\t\t\t*/\n\t\t\tif (index == 0 ||\n\t\t\t\t (index >= CYCLE_COLOR_START && index < (CYCLE_COLOR_START + CYCLE_COLOR_COUNT)) ||\n\t\t\t\t index == CC_PULSE_COLOR ||\n\t\t\t\t index == CC_EMBER_COLOR) {\n\t\t\t\t*ptr++ = index;\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tFind the color that, ideally, the working color should be remapped\n\t\t\t\t**\tto in the special remap range.\n\t\t\t\t*/\n\t\t\t\tRGBClass trycolor = palette[index];\n\t\t\t\ttrycolor.Adjust(frac, palette[color]);\t\t\t// Try to match this color.\n\n\t\t\t\t/*\n\t\t\t\t**\tSearch through the remap range to find the color that should be remapped\n\t\t\t\t**\tto.\n\t\t\t\t*/\n\t\t\t\tint best = -1;\n\t\t\t\tint bvalue = 0;\n\t\t\t\tfor (int id = 0; id < PaletteClass::COLOR_COUNT; id++) {\n\n\t\t\t\t\tif (id != 0 &&\n\t\t\t\t\t\t(id < CYCLE_COLOR_START || id >= (CYCLE_COLOR_START + CYCLE_COLOR_COUNT)) &&\n\t\t\t\t\t\t id != CC_PULSE_COLOR &&\n\t\t\t\t\t\t id != CC_EMBER_COLOR) {\n\n\t\t\t\t\t\tint diff = palette[id].Difference(trycolor);\n\t\t\t\t\t\tif (best == -1 || diff < bvalue) {\n\t\t\t\t\t\t\tbest = id;\n\t\t\t\t\t\t\tbvalue = diff;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t*ptr++ = best;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nvoid ChronalVortexClass::Detach(TARGET target)\n{\n\tif (Target_Legal(target) && target == TargetObject) {\n\t\tSet_Target(NULL);\n\t}\n}\n"
  },
  {
    "path": "CODE/VORTEX.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer - Red Alert                                *\n *                                                                                             *\n *                    File Name : VORTEX.H                                                     *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 8/12/96                                                      *\n *                                                                                             *\n *                  Last Update : August 29th, 1996 [ST]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *  Overview:                                                                                  *\n *    Definition of ChronalVortexClass. The Chronal vortex sometimes appears when the          *\n *  chronosphere is used.                                                                      *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef VORTEX_H\n#define VORTEX_H\n\n\n#define MAX_REMAP_SHADES 16\t\t//Number of lookup tables required for vortex shading.\n#define VORTEX_FRAMES\t\t16\t\t//Number of frames in one complete rotation of the vortex.\n\n\n\nclass ChronalVortexClass {\n\n\tpublic:\n\n\t\t/*\n\t\t** Constructor and destructor.\n\t\t*/\n\t\tChronalVortexClass(void);\n\t\t~ChronalVortexClass(void);\n\n\t\tvoid Detach(TARGET target);\n\n\t\t/*\n\t\t** Makes the vortex appear at the specified coordinate.\n\t\t*/\n\t\tvoid Appear (COORDINATE coordinate);\n\n\t\t/*\n\t\t** Makes the vortex go away.\n\t\t*/\n\t\tvoid Disappear (void);\n\n\t\t/*\n\t\t** Call this every frame.\n\t\t*/\n\t\tvoid AI (void);\n\n\t\t/*\n\t\t** Render the vortex\n\t\t*/\n\t\tvoid Render (void);\n\n\t\t/*\n\t\t** Flags cells under the vortex to be redrawn\n\t\t*/\n\t\tvoid Set_Redraw (void);\n\n\t\t/*\n\t\t** Call whenever the theater changes to recalculate the shading lookup tables\n\t\t*/\n\t\tvoid Setup_Remap_Tables (TheaterType theater);\n\n\t\t/*\n\t\t** Functions to load and save the vortex.\n\t\t*/\n\t\tvoid Load(Straw &file);\n\t\tvoid Save(Pipe  &file);\n\n\t\t/*\n\t\t** Returns true of vortex is currently active.\n\t\t*/\n\t\tbool Is_Active(void) {return (Active);};\n\n\t\t/*\n\t\t** Makes the vortex attack the specified target. Target must be in range of the vortex.\n\t\t*/\n\t\tvoid Set_Target (ObjectClass *target);\n\n\t\t/*\n\t\t** Disables the vortex.\n\t\t*/\n\t\tvoid Stop(void);\n\n\t\t/*\n\t\t** Members to allow read access to private data\n\t\t*/\n\t\tint Get_Range  (void) {return (Range);};\n\t\tint Get_Speed  (void) {return (Speed);};\n\t\tint Get_Damage (void) {return (Damage);};\n\n\t\t/*\n\t\t** Members to allow write access to private data.\n\t\t*/\n\t\tvoid Set_Range  (int range) {Range = range;};\n\t\tvoid Set_Speed  (int speed) {Speed = speed;};\n\t\tvoid Set_Damage (int damage) {Damage = damage;};\n\n\t\t/*\n\t\t** Possible states the vortex can be in.\n\t\t*/\n\t\ttypedef enum AnimStateType{\n\t\t\tSTATE_GROW,\t\t\t//Vortex has just appeared and is growing larger\n\t\t\tSTATE_ROTATE,\t\t//Vortex is rotating\n\t\t\tSTATE_SHRINK\t\t//Vortex is shrinking and about to disappear\n\t\t}AnimStateType;\n\n\tprivate:\n\n\t\t/*\n\t\t** Members for setting up the lookup tables.\n\t\t*/\n\t\tvoid Build_Fading_Table (PaletteClass const & palette, void * dest, int color, int frac);\n\t\tvoid Coordinate_Remap ( GraphicViewPortClass *inbuffer, int x, int y, int width, int height, unsigned char *remap_table);\n\n\t\t/*\n\t\t** Misc internal functions\n\t\t*/\n\t\tvoid Attack(void);\n\t\tvoid Zap_Target(void);\n\t\tvoid Movement(void);\n\t\tvoid Hide(void);\n\t\tvoid Show(void);\n\n\t\t/*\n\t\t** Position of the top left of the vortex\n\t\t*/\n\t\tCOORDINATE\t\tPosition;\n\n\t\t/*\n\t\t** Direction of rotation\n\t\t*/\n\t\tint         \tAnimateDir;\n\n\t\t/*\n\t\t** Current frame of animation\n\t\t*/\n\t\tint\t\t\t\tAnimateFrame;\n\n\t\t/*\n\t\t** Animation flag. When 0 vortex will animate 1 frame.\n\t\t*/\n\t\tint\t\t\t\tAnimate;\n\n\t\t/*\n\t\t** State of vortex. See ENUM for info.\n\t\t*/\n\t\tAnimStateType\tState;\n\n\t\t/*\n\t\t** Color lookup tables for shading on vortex.\n\t\t*/\n\t\tunsigned char \tVortexRemapTables [MAX_REMAP_SHADES][256];\n\n\t\t/*\n\t\t** Color lookup table to make the blue lightning orange.\n\t\t*/\n\t\tunsigned char\tLightningRemap[256];\n\n\t\t/*\n\t\t** Is vortex currently active?\n\t\t*/\n\t\tint\t\t\t\tActive \t\t\t: 1;\n\n\t\t/*\n\t\t** Is the vortex winding down?\n\t\t*/\n\t\tint\t\t\t\tStartShutdown \t: 1;\n\n\t\t/*\n\t\t** Is the vortex about to hide from view?\n\t\t*/\n\t\tint\t\t\t\tStartHiding\t\t: 1;\n\n\t\t/*\n\t\t** Is the vortex active but hidden?\n\t\t*/\n\t\tint\t\t\t\tHidden\t\t\t: 1;\n\n\t\t/*\n\t\t** Theater that lookup table is good for.\n\t\t*/\n\t\tTheaterType\t\tTheater;\n\n\t\t/*\n\t\t** Last frame that vortex attacked on\n\t\t*/\n\t\tint\t\t\t\tLastAttackFrame;\n\n\t\t/*\n\t\t** How many times lightning has zapped on this attack\n\t\t*/\n\t\tint\t\t\t\tZapFrame;\n\n\t\t/*\n\t\t** Ptr to object that the vortex is zapping\n\t\t*/\n\t\tTARGET\tTargetObject;\n//\t\tObjectClass\t\t*TargetObject;\n\n\t\t/*\n\t\t** Distance to the target object\n\t\t*/\n\t\tint\t\t\t\tTargetDistance;\n\n\t\t/*\n\t\t** Game frame that vortex hid on.\n\t\t*/\n\t\tint\t\t\t\tHiddenFrame;\n\n\t\t/*\n\t\t** Direction vortex is going in.\n\t\t*/\n\t\tint\t\t\t\tXDir;\n\t\tint\t\t\t\tYDir;\n\n\t\t/*\n\t\t** Direction vortex should be going in\n\t\t*/\n\t\tint\t\t\t\tDesiredXDir;\n\t\tint\t\t\t\tDesiredYDir;\n\n\t\t/*\n\t\t** Range in cells of the vortex lightning\n\t\t*/\n\t\tint\t\t\t\tRange;\n\n\t\t/*\n\t\t** Max speed in leptons per frame of the vortex.\n\t\t*/\n\t\tint\t\t\t\tSpeed;\n\n\t\t/*\n\t\t** Damge of vortex lightning zap.\n\t\t*/\n\t\tint\t\t\t\tDamage;\n\n\t\t/*\n\t\t** Offscreen buffer to render vortex into. This is needed so we can handle clipping.\n\t\t*/\n\t\tGraphicBufferClass *RenderBuffer;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/W95TRACE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/*\n    Implementation of Win95 tracing facility to mimic that of NT\n*/\n\n#include <windows.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <process.h>\n#include \"w95trace.h\"\n\n\nvoid OutputDebugStringW95( LPCTSTR /*lpOutputString*/, ...)\n{\n#if 0\n\n    HANDLE heventDBWIN;  /* DBWIN32 synchronization object */\n    HANDLE heventData;   /* data passing synch object */\n    HANDLE hSharedFile;  /* memory mapped file shared data */\n    LPSTR lpszSharedMem;\n    char achBuffer[500];\n\n    /* create the output buffer */\n    va_list args;\n    va_start(args, lpOutputString);\n    vsprintf(achBuffer, lpOutputString, args);\n    va_end(args);\n\n\tachBuffer[499] = 0;\t//\tNull-terminate here, just in case vsprintf didn't do it because lpOutputString was too long.\n\n    /* \n        Do a regular OutputDebugString so that the output is \n        still seen in the debugger window if it exists.\n\n        This ifdef is necessary to avoid infinite recursion \n        from the inclusion of W95TRACE.H\n    */\n#ifdef _UNICODE\n    ::OutputDebugStringW(achBuffer);\n#else\n    ::OutputDebugStringA(achBuffer);\n#endif\n\n\t//\tadded by ajw\n\t//FILE* pFile = fopen( \"debugout.wri\", \"a\" );\n\tFILE* pFile = fopen( \"wolapi.out\", \"a\" );\n\tfprintf( pFile, achBuffer );\n\tfclose( pFile );\n\n//    /* bail if it's not Win95 */\n//    {\n//        OSVERSIONINFO VerInfo;\n//        VerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\n//        GetVersionEx(&VerInfo);\n//        if ( VerInfo.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS )\n//            return;\n//    }\n\n    /* make sure DBWIN is open and waiting */\n    heventDBWIN = OpenEvent(EVENT_MODIFY_STATE, FALSE, \"DBWIN_BUFFER_READY\");\n    if ( !heventDBWIN )\n    {\n        //MessageBox(NULL, \"DBWIN_BUFFER_READY nonexistent\", NULL, MB_OK);\n        return;            \n    }\n\n    /* get a handle to the data synch object */\n    heventData = OpenEvent(EVENT_MODIFY_STATE, FALSE, \"DBWIN_DATA_READY\");\n    if ( !heventData )\n    {\n        // MessageBox(NULL, \"DBWIN_DATA_READY nonexistent\", NULL, MB_OK);\n        CloseHandle(heventDBWIN);\n        return;            \n    }\n    \n    hSharedFile = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, 0, 4096, \"DBWIN_BUFFER\");\n    if (!hSharedFile) \n    {\n        //MessageBox(NULL, \"DebugTrace: Unable to create file mapping object DBWIN_BUFFER\", \"Error\", MB_OK);\n        CloseHandle(heventDBWIN);\n        CloseHandle(heventData);\n        return;\n    }\n\n    lpszSharedMem = (LPSTR)MapViewOfFile(hSharedFile, FILE_MAP_WRITE, 0, 0, 512);\n    if (!lpszSharedMem) \n    {\n        //MessageBox(NULL, \"DebugTrace: Unable to map shared memory\", \"Error\", MB_OK);\n        CloseHandle(heventDBWIN);\n        CloseHandle(heventData);\n        return;\n    }\n\n    /* wait for buffer event */\n    WaitForSingleObject(heventDBWIN, INFINITE);\n\n    /* write it to the shared memory */\n    *((LPDWORD)lpszSharedMem) = getpid();\n    wsprintf(lpszSharedMem + sizeof(DWORD), \"%s\", achBuffer);\n\n    /* signal data ready event */\n    SetEvent(heventData);\n\n    /* clean up handles */\n    CloseHandle(hSharedFile);\n    CloseHandle(heventData);\n    CloseHandle(heventDBWIN);\n\n    return;\n#endif\n}\n"
  },
  {
    "path": "CODE/W95TRACE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*\n    declarations for Win95 tracing facility\n*/\n\n#ifdef _DEBUG\n\n#ifndef __TRACEW95__\n#define __TRACEW95__\n\n#include <windows.h>\n\n// redefine all the MFC macros to point to us\n\n#undef  TRACE\n#define TRACE   OutputDebugStringW95\n\n#undef  TRACE0\n#define TRACE0   OutputDebugStringW95\n\n#undef  TRACE1\n#define TRACE1   OutputDebugStringW95\n\n#undef  TRACE2\n#define TRACE2   OutputDebugStringW95\n\n#undef  TRACE3\n#define TRACE3   OutputDebugStringW95\n\n// redefine OutputDebugString so that it works with \n// API calls\n#undef OutputDebugString\n#define OutputDebugString   OutputDebugStringW95\n\n\n// function declarations\nvoid OutputDebugStringW95( LPCTSTR lpOutputString, ... );\n\n#endif  //__TRACEW95__\n\n#endif  // _DEBUG\n"
  },
  {
    "path": "CODE/WARHEAD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/WARHEAD.CPP 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : WARHEAD.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/20/96                                                     *\n *                                                                                             *\n *                  Last Update : July 19, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   WarheadTypeClass::As_Pointer -- Convert a warhead type number into a pointer.             *\n *   WarheadTypeClass::Read_INI -- Fetches the warhead data from the INI database.             *\n *   WarheadTypeClass::WarheadTypeClass -- Default constructor for warhead objects.            *\n *   WarheadTypeClass::operator delete -- Returns warhead object back to special memory pool.  *\n *   WarheadTypeClass::operator new -- Allocate a warhead object from the special heap.        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n\n\n/***************************************************************************\n**\tThis is the warhead data object array.\n*/\nTFixedIHeapClass<WarheadTypeClass> Warheads;\n\n\n/***********************************************************************************************\n * WarheadTypeClass::WarheadTypeClass -- Default constructor for warhead objects.              *\n *                                                                                             *\n *    This default constructor for a warhead object will fill in all the default values        *\n *    for a warhead. It is presumed that these values will be normal unless specifically       *\n *    overridden by the INI database.                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nWarheadTypeClass::WarheadTypeClass(char const * name) :\n\tID(Warheads.ID(this)),\n\tIniName(name),\n\tSpreadFactor(1),\n\tIsWallDestroyer(false),\n\tIsWoodDestroyer(false),\n\tIsTiberiumDestroyer(false),\n\tIsOrganic(false),\n\tExplosionSet(0),\n\tInfantryDeath(0)\n{\n\tfor (ArmorType armor = ARMOR_FIRST; armor < ARMOR_COUNT; armor++) {\n\t\tModifier[armor] = 1;\n\t}\n}\n\n\n/***********************************************************************************************\n * WarheadTypeClass::operator new -- Allocate a warhead object from the special heap.          *\n *                                                                                             *\n *    This will allocate a warhead object from the special heap that is maintained for         *\n *    this purpose.                                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the newly allocated warhead type object. If there is     *\n *          insufficient memory for the allocation, then NULL is returned.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * WarheadTypeClass::operator new(size_t)\n{\n\treturn(Warheads.Alloc());\n}\n\n\n/***********************************************************************************************\n * WarheadTypeClass::operator delete -- Returns warhead object back to special memory pool.    *\n *                                                                                             *\n *    This routine will return the warhead object to the memory pool from whence it came.      *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to the warhead object to return to the memory pool.            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid WarheadTypeClass::operator delete(void * pointer)\n{\n\tWarheads.Free((WarheadTypeClass *)pointer);\n}\n\n\n/***********************************************************************************************\n * WarheadTypeClass::As_Pointer -- Convert a warhead type number into a pointer.               *\n *                                                                                             *\n *    This will locate the warhead type specified and return a pointer to it.                  *\n *                                                                                             *\n * INPUT:   warhead  -- The warhead to convert into a pointer.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the warhead type object that is represented by the       *\n *          warhead type number specified.                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nWarheadTypeClass * WarheadTypeClass::As_Pointer(WarheadType warhead)\n{\n\tif (warhead != WARHEAD_NONE) {\n\t\treturn(Warheads.Ptr(warhead));\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * WarheadTypeClass::Read_INI -- Fetches the warhead data from the INI database.               *\n *                                                                                             *\n *    Use this routine to retrieve the data specific to this warhead type class object from    *\n *    the INI database specified. Typical use of this is when processing the rules.ini         *\n *    file.                                                                                    *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to fetch the values from.                   *\n *                                                                                             *\n * OUTPUT:  bool; Was the warhead entry found and the data retrieved?                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WarheadTypeClass::Read_INI(CCINIClass & ini)\n{\n\tif (ini.Is_Present(Name())) {\n\t\tSpreadFactor = ini.Get_Int(Name(), \"Spread\", SpreadFactor);\n\t\tIsWallDestroyer = ini.Get_Bool(Name(), \"Wall\", IsWallDestroyer);\n\t\tIsWoodDestroyer = ini.Get_Bool(Name(), \"Wood\", IsWoodDestroyer);\n\t\tIsTiberiumDestroyer = ini.Get_Bool(Name(), \"Ore\", IsTiberiumDestroyer);\n\t\tExplosionSet = ini.Get_Int(Name(), \"Explosion\", ExplosionSet);\n\t\tInfantryDeath = ini.Get_Int(Name(), \"InfDeath\", InfantryDeath);\n\n\t\tchar buffer[128];\n\t\tif (ini.Get_String(Name(), \"Verses\", \"100%%,100%%,100%%,100%%,100%%\", buffer, sizeof(buffer))) {\n\t\t\tchar * aval = strtok(buffer, \",\");\n\t\t\tfor (ArmorType armor = ARMOR_FIRST; armor < ARMOR_COUNT; armor++) {\n\t\t\t\tModifier[armor] = fixed(aval);\n\t\t\t\taval = strtok(NULL, \",\");\n\t\t\t}\n\t\t}\n\n\t\tIsOrganic = (Modifier[ARMOR_STEEL] == 0);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n"
  },
  {
    "path": "CODE/WARHEAD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/WARHEAD.H 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : WARHEAD.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/17/96                                                     *\n *                                                                                             *\n *                  Last Update : May 17, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WARHEAD_H\n#define WARHEAD_H\n\n\n/**********************************************************************\n**\tEach of the warhead types has specific characteristics. This structure\n**\tholds these characteristics.\n*/\nclass WarheadTypeClass\n{\n\tpublic:\n\t\tWarheadTypeClass(char const * name);\n\t\tWarheadTypeClass(NoInitClass const &) {}\n\n\t\tvoid * operator new(size_t);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tvoid operator delete(void * pointer);\n\n\t\tvoid Code_Pointers(void) {}\n\t\tvoid Decode_Pointers(void) {}\n\t\tchar const * Name(void) const {return(IniName);}\n\t\tbool Read_INI(CCINIClass & ini);\n\t\tstatic WarheadTypeClass * As_Pointer(WarheadType weapon);\n\n\t\t/*\n\t\t**\tThis is the ID number of the weapon type. It is the weapon\n\t\t**\ttype ID enum as well as the index number into the weapon\n\t\t**\theap.\n\t\t*/\n\t\tint ID;\n\n\t\t/*\n\t\t**\tThis is the identifying name of this warhead type.\n\t\t*/\n\t\tchar const * IniName;\n\n\t\t/*\n\t\t**\tThis value control how damage from this warhead type will reduce\n\t\t**\tover distance. The larger the number, the less the damage is reduced\n\t\t**\tthe further the distance from the source of the damage.\n\t\t*/\n\t\tint SpreadFactor;\n\n\t\t/*\n\t\t**\tIf this warhead type can destroy walls, then this flag will be true.\n\t\t*/\n\t\tbool IsWallDestroyer:1;\n\n\t\t/*\n\t\t**\tIf this warhead can destroy wooden walls, then this flag will be true.\n\t\t*/\n\t\tbool IsWoodDestroyer:1;\n\n\t\t/*\n\t\t**\tDoes this warhead damage tiberium?\n\t\t*/\n\t\tbool IsTiberiumDestroyer:1;\n\n\t\t/*\n\t\t**\tOnly effective against infantry?\n\t\t*/\n\t\tbool IsOrganic:1;\n\n\t\t/*\n\t\t**\tThe warhead damage is reduced depending on the the type of armor the\n\t\t**\tdefender has. This table is what gives weapons their \"character\".\n\t\t*/\n\t\tfixed Modifier[ARMOR_COUNT];\n\n\t\t/*\n\t\t**\tWhich explosion set to use for warhead impact.\n\t\t*/\n\t\tint ExplosionSet;\n\n\t\t/*\n\t\t**\tThis specifies the infantry death animation to use if the infantry dies as\n\t\t**\ta result of a warhead of this type.\n\t\t*/\n\t\tint InfantryDeath;\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/WATCOM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/WATCOM.H 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : WATCOM.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/12/95                                                     *\n *                                                                                             *\n *                  Last Update : March 12, 1995 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WATCOM_H\n#define WATCOM_H\n\n// Turn all warnings into errors.\n#pragma warning * 0\n\n// Disables warning when \"sizeof\" is used on an object with virtual functions.\n#pragma warning 549 9\n\n// Disable the \"Integral value may be truncated during assignment or initialization\".\n#pragma warning 389 9\n\n// Allow constructing a temporary to be used as a parameter.\n#pragma warning 604 9\n\n// Disable the construct resolved as an expression warning.\n#pragma warning 595 9\n\n// Disable the strange \"construct resolved as a declaration/type\" warning.\n#pragma warning 594 9\n\n// Disable the \"pre-compiled header file cannot be used\" warning.\n#pragma warning 698 9\n\n// Disable the \"temporary object used to initialize a non-constant reference\" warning.\n#pragma warning 665 9\n\n// Disable the \"pointer or reference truncated by cast. Cast is supposed to REMOVE warnings, not create them.\n#pragma warning 579 9\n\n// Disable the warning that suggests a null destructor be placed in class definition.\n#pragma warning 656 9\n\n// Disable the warning about moving empty constructors/destructors to the class declaration.\n#pragma warning 657 9\n\n// No virtual destructor is not an error in C&C.\n#pragma warning 004 9\n\n// Turns off unreferenced function parameter warning.\n//#pragma off(unreferenced)\n\n\n// Fix deficiency in Watcom so that true/false will be defined.\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n#endif\n"
  },
  {
    "path": "CODE/WEAPON.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/WEAPON.CPP 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : WEAPON.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/20/96                                                     *\n *                                                                                             *\n *                  Last Update : September 9, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Armor_From_Name -- Convert ASCII name into armor type number.                             *\n *   WeaponTypeClass::As_Pointer -- Give a weapon type ID, fetch pointer to weapon type object.*\n *   WeaponTypeClass::Read_INI -- Fetch the weapon data from the INI database.                 *\n *   WeaponTypeClass::WeaponTypeClass -- Default constructor for weapon type objects.          *\n *   WeaponTypeClass::operator delete -- Returns weapon type object back to special heap.      *\n *   WeaponTypeClass::operator new -- Allocates a weapon type object form the special heap.    *\n *   WeaponTypeClass::~WeaponTypeClass -- Destructor for weapon type class objects.            *\n *   Weapon_From_Name -- Conver ASCII name to weapon type ID number.                           *\n *   WeaponTypeClass::Allowed_Threats -- Determine what threats this weapon can address.       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***************************************************************************\n**\tThese are the various weapons and their characteristics.\n*/\nTFixedIHeapClass<WeaponTypeClass> Weapons;\n\n\n/***********************************************************************************************\n * WeaponTypeClass::WeaponTypeClass -- Default constructor for weapon type objects.            *\n *                                                                                             *\n *    This default constructor will initialize all the values of the weapon to the default     *\n *    state. Thus, if any of these settings are not specifically overridden by the rules.ini   *\n *    file, they will remain this value in the game.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nWeaponTypeClass::WeaponTypeClass(char const * name) :\n\tID(Weapons.ID(this)),\n\tIniName(name),\n\tIsSupressed(false),\n\tIsCamera(false),\n\tIsElectric(false),\n\tBurst(1),\n\tBullet(NULL),\n\tAttack(0),\n\tMaxSpeed(MPH_IMMOBILE),\n\tWarheadPtr(NULL),\n\tROF(0),\n\tRange(0),\n\tSound(VOC_NONE),\n\tAnim(ANIM_NONE)\n{\n}\n\n\n/***********************************************************************************************\n * WeaponTypeClass::~WeaponTypeClass -- Destructor for weapon type class objects.              *\n *                                                                                             *\n *    This destructor really doesn't do anything but set the pointers to NULL. This is a       *\n *    general purposes safety tactic but is otherwise useless.                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nWeaponTypeClass::~WeaponTypeClass(void)\n{\n\tIniName = NULL;\n\tBullet = NULL;\n\tWarheadPtr = NULL;\n}\n\n\n/***********************************************************************************************\n * WeaponTypeClass::operator new -- Allocates a weapon type object form the special heap.      *\n *                                                                                             *\n *    This will allocate a weapon type object from a special heap that has been set up for     *\n *    that purpose.                                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the weapon type object allocated. If there was           *\n *          insufficient memory available, NULL is returned.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * WeaponTypeClass::operator new(size_t)\n{\n\treturn(Weapons.Alloc());\n}\n\n\n/***********************************************************************************************\n * WeaponTypeClass::operator delete -- Returns weapon type object back to special heap.        *\n *                                                                                             *\n *    This routine will return the weapon type object back to the heap so that the memory      *\n *    can be reused for subsiquent allocations of weapon type objects.                         *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to the weapon type object to return to the special heap.       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid WeaponTypeClass::operator delete(void * pointer)\n{\n\tWeapons.Free((WeaponTypeClass *)pointer);\n}\n\n\n/***********************************************************************************************\n * WeaponTypeClass::As_Pointer -- Give a weapon type ID, fetch pointer to weapon type object.  *\n *                                                                                             *\n *    This routine will conver the weapon type ID specified into a pointer to the weapon type  *\n *    object it represents.                                                                    *\n *                                                                                             *\n * INPUT:   weapon   -- The weapon type object ID to convert to a pointer.                     *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the weapon type class object that is represented by the  *\n *          weapon ID number specified. If no match could be found, then NULL is returned.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nWeaponTypeClass * WeaponTypeClass::As_Pointer(WeaponType weapon)\n{\n\tif (weapon != WEAPON_NONE) {\n\t\treturn(Weapons.Ptr(weapon));\n//\t\tfor (int index = 0; index < Weapons.Count(); index++) {\n//\t\t\tWeaponTypeClass * ptr = Weapons.Ptr(index);\n//\t\t\tif (ptr->ID == weapon) {\n//\t\t\t\treturn(ptr);\n//\t\t\t}\n//\t\t}\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * WeaponTypeClass::Read_INI -- Fetch the weapon data from the INI database.                   *\n *                                                                                             *\n *    This routine will fetch the weapon data for this weapon type object from the INI         *\n *    database specified.                                                                      *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database that the weapon data will be fetched        *\n *                   from.                                                                     *\n *                                                                                             *\n * OUTPUT:  bool; Was this weapon type described in the database and the values retrieved?     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WeaponTypeClass::Read_INI(CCINIClass & ini)\n{\n\tif (ini.Is_Present(Name())) {\n\t\tIsSupressed = ini.Get_Bool(Name(), \"Supress\", IsSupressed);\n\t\tBurst = ini.Get_Int(Name(), \"Burst\", Burst);\n\t\tAttack = ini.Get_Int(Name(), \"Damage\", Attack);\n\t\tMaxSpeed = ini.Get_MPHType(Name(), \"Speed\", MaxSpeed);\n\t\tROF = ini.Get_Int(Name(), \"ROF\", ROF);\n\t\tRange = ini.Get_Lepton(Name(), \"Range\", Range);\n\t\tSound = ini.Get_VocType(Name(), \"Report\", Sound);\n\t\tAnim = ini.Get_AnimType(Name(), \"Anim\", Anim);\n\t\tIsCamera = ini.Get_Bool(Name(), \"Camera\", IsCamera);\n\t\tIsElectric = ini.Get_Bool(Name(), \"Charges\", IsElectric);\n\t\tIsTurboBoosted = ini.Get_Bool(Name(), \"TurboBoost\", IsTurboBoosted);\n\n\t\tWarheadType wtype = (WarheadPtr != NULL) ? WarheadType(WarheadPtr->ID) : WARHEAD_NONE;\n\t\twtype = ini.Get_WarheadType(Name(), \"Warhead\", wtype);\n\t\tif (wtype != WARHEAD_NONE) {\n\t\t\tWarheadPtr = WarheadTypeClass::As_Pointer(wtype);\n//\t\t\tWarheadPtr = &Warheads[wtype];\n\t\t} else {\n\t\t\tWarheadPtr = NULL;\n\t\t}\n\n\t\tBulletType btype = (Bullet != NULL) ? BulletType(Bullet->ID) : BULLET_NONE;\n\t\tbtype = ini.Get_BulletType(Name(), \"Projectile\", btype);\n\t\tif (btype != BULLET_NONE) {\n\t\t\tBullet = &BulletTypeClass::As_Reference(btype);\n\t\t} else {\n\t\t\tBullet = NULL;\n\t\t}\n\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * Weapon_From_Name -- Conver ASCII name to weapon type ID number.                             *\n *                                                                                             *\n *    This will find the weapon whos name matches that specified and then it will return the   *\n *    weapon ID number associated with it.                                                     *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the ASCII name of the weapon type.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the weapon type ID number that matches the name specified. If no      *\n *          match could be found, then WEAPON_NONE is returned.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nWeaponType Weapon_From_Name(char const * name)\n{\n\tif (!name) return(WEAPON_NONE);\n\n\tfor (int index = 0; index < Weapons.Count(); index++) {\n\t\tif (stricmp(Weapons.Ptr(index)->Name(), name) == 0) {\n\t\t\treturn(WeaponType(Weapons.Ptr(index)->ID));\n\t\t}\n\t}\n\n\treturn(WEAPON_NONE);\n}\n\n\n/***********************************************************************************************\n * Armor_From_Name -- Convert ASCII name into armor type number.                               *\n *                                                                                             *\n *    This will find the armor type that matches the ASCII name specified and then will return *\n *    the armor ID number of it.                                                               *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the ASCII name of the armor to find.                           *\n *                                                                                             *\n * OUTPUT:  Returns with the armor ID number of the armor that matches the name specified. If  *\n *          no match could be found, then ARMOR_NONE is returned.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nArmorType Armor_From_Name(char const * name)\n{\n\tif (!name) return(ARMOR_NONE);\n\n\tfor (ArmorType index = ARMOR_FIRST; index < ARMOR_COUNT; index++) {\n\t\tif (stricmp(ArmorName[index], name) == 0) {\n\t\t\treturn(index);\n\t\t}\n\t}\n\n\treturn(ARMOR_NONE);\n}\n\n\n/***********************************************************************************************\n * WeaponTypeClass::Allowed_Threats -- Determine what threats this weapon can address.         *\n *                                                                                             *\n *    This routine will examine the capabilities of this weapon and return with the threat     *\n *    types that it can address.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the threat types that this weapon can address.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nThreatType WeaponTypeClass::Allowed_Threats(void) const\n{\n\tThreatType threat = THREAT_NORMAL;\n\tif (Bullet->IsAntiAircraft) {\n\t\tthreat = threat | THREAT_AIR;\n\t}\n\tif (Bullet->IsAntiGround) {\n\t\tthreat = threat | THREAT_INFANTRY|THREAT_VEHICLES|THREAT_BOATS|THREAT_BUILDINGS;\n\t}\n\treturn(threat);\n}\n\n\nbool WeaponTypeClass::Is_Wall_Destroyer(void) const\n{\n\tif (WarheadPtr != NULL && WarheadPtr->IsWallDestroyer) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "CODE/WEAPON.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/WEAPON.H 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : WEAPON.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/17/96                                                     *\n *                                                                                             *\n *                  Last Update : May 17, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef WEAPON_H\n#define WEAPON_H\n\n\n/**********************************************************************\n**\tThis is the constant data associated with a weapon. Some objects\n**\tcan have multiple weapons and this class is used to isolate and\n**\tspecify this data in a convenient and selfcontained way.\n*/\nclass WeaponTypeClass\n{\n\tpublic:\n\t\tWeaponTypeClass(char const * name);\n\t\tWeaponTypeClass(NoInitClass const &) {}\n\t\t~WeaponTypeClass(void);\n\n\t\tvoid * operator new(size_t);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tvoid operator delete(void * pointer);\n\n\t\tchar const * Name(void) const {return(IniName);}\n\t\tbool Read_INI(CCINIClass & ini);\n\t\tstatic WeaponTypeClass * As_Pointer(WeaponType weapon);\n\t\tvoid Code_Pointers(void) {}\n\t\tvoid Decode_Pointers(void) {}\n\t\tThreatType Allowed_Threats(void) const;\n\t\tbool Is_Wall_Destroyer(void) const;\n\n\t\t/*\n\t\t**\tThis is both the weapon type number and the index number into\n\t\t**\tthe weapon array.\n\t\t*/\n\t\tint ID;\n\n\t\t/*\n\t\t**\tThis is the identifying name of this weapon.\n\t\t*/\n\t\tchar const * IniName;\n\n\t\t/*\n\t\t**\tIncrease the weapon speed if the target is flying.\n\t\t*/\n\t\tunsigned IsTurboBoosted:1;\n\n\t\t/*\n\t\t**\tIf potential targets of this weapon should be scanned for\n\t\t**\tnearby friendly structures and if found, firing upon the target\n\t\t**\twould be discouraged, then this flag will be true.\n\t\t*/\n\t\tunsigned IsSupressed:1;\n\n\t\t/*\n\t\t**\tIf this weapon is equipped with a camera that reveals the\n\t\t**\tarea around the firer, then this flag will be true.\n\t\t*/\n\t\tunsigned IsCamera:1;\n\n\t\t/*\n\t\t**\tIf this weapon requires charging before it can fire, then this\n\t\t**\tflag is true. In actuality, this only applies to the Tesla coil\n\t\t**\twhich has specific charging animation. The normal rate of fire\n\t\t**\tvalue suffices for all other cases.\n\t\t*/\n\t\tunsigned IsElectric:1;\n\n\t\t/*\n\t\t**\tThis is the number of shots this weapon first (in rapid succession).\n\t\t**\tThe normal value is 1, but for the case of two shooter weapons such as\n\t\t**\tthe double barreled gun turrets of the Mammoth tank, this value will be\n\t\t**\tset to 2.\n\t\t*/\n\t\tint Burst;\n\n\t\t/*\n\t\t**\tThis is the unit class of the projectile fired. A subset of the unit types\n\t\t**\trepresent projectiles. It is one of these classes that is specified here.\n\t\t**\tIf this object does not fire anything, then this value will be BULLET_NONE.\n\t\t*/\n\t\tBulletTypeClass const * Bullet;\n\n\t\t/*\n\t\t**\tThis is the damage (explosive load) to be assigned to the projectile that\n\t\t**\tthis object fires. For the rare healing weapon, this value is negative.\n\t\t*/\n\t\tint Attack;\n\n\t\t/*\n\t\t**\tSpeed of the projectile launched.\n\t\t*/\n\t\tMPHType MaxSpeed;\n\n\t\t/*\n\t\t**\tWarhead to attach to the projectile.\n\t\t*/\n\t\tWarheadTypeClass const * WarheadPtr;\n\n\t\t/*\n\t\t**\tObjects that fire (which can be buildings as well) will fire at a\n\t\t**\tfrequency controlled by this value. This value serves as a count\n\t\t**\tdown timer between shots. The smaller the value, the faster the\n\t\t**\trate of fire.\n\t\t*/\n\t\tint ROF;\n\n\t\t/*\n\t\t**\tWhen this object fires, the range at which it's projectiles travel is\n\t\t**\tcontrolled by this value. The value represents the number of cells the\n\t\t**\tprojectile will travel. Objects outside of this range will not be fired\n\t\t**\tupon (in normal circumstances).\n\t\t*/\n\t\tLEPTON Range;\n\n\t\t/*\n\t\t**\tThis is the typical sound generated when firing.\n\t\t*/\n\t\tVocType Sound;\n\n\t\t/*\n\t\t**\tThis is the animation to display at the firing coordinate.\n\t\t*/\n\t\tAnimType Anim;\n};\n\n\n#endif\n\n\n"
  },
  {
    "path": "CODE/WIDEFUNC.MAC",
    "content": "<End><Left><Down><Alt-1>y<Up><Right>#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138<Alt-J>1<Enter><F5>#4138#4143<Enter><Up><Alt-C><Alt-J>1<Enter><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Alt-C><F5>#4138#4143<Enter><Left><Right>#4157#4157#4157#4157#4157#4157#4157#4157#4157#4157#4157#4157#4157#4157#4157#4157#4157#4157#4157#4157<Alt-J>1<Enter><Home><F5>#4143<Backspace><Esc><Ctrl-F6><F5>#4190#4143#4138<Enter><F5>#4190#4188#4143#4188#4138<Enter><Ctrl-T><Ctrl-F6><F7>"
  },
  {
    "path": "CODE/WIDEHDR.MAC",
    "content": "<Down><End><Left><Left>#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138<Home><Down><Ctrl-Right><Ctrl-Right><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><End><Left><Left><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Down><End>#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138#4138<Down><End><Left><Alt-1>y<F5>#4138#4143<Enter><Up><Alt-C><Alt-J>1<Enter><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Space><Alt-C><F5>#4138#4143<Enter><Left><Right>#4141<Space>#4141<Space>#4141<Space>#4141<Space>#4141<Space>#4141<Space>#4141<Space>#4141<Space>#4141<Space>#4141<Space><Alt-J>1<Enter><F5>#4141#4141#4141#4141#4141#4141<Space><Enter><Right><Right><Right><Right><Right><Right>#4141#4141#4141#4141#4141#4141#4141#4141#4141#4141#4141#4141#4141#4141#4141#4141#4141#4141#4141#4141<Del><Del><Del><Del><Del><Del><Del><Del><Del><Del><Del><Del><Del><Del><Del><Del><Del><Del><Del><Del><Alt-J>1<Enter><Up><Up><Up><Home><F7>"
  },
  {
    "path": "CODE/WINASM.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\n;***************************************************************************\n;**   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  I N C  **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : WINSAM.ASM                               *\n;*                                                                         *\n;*                   Programmer : Steve Tall                               *\n;*                                                                         *\n;*                   Start Date : October 26th, 1995                       *\n;*                                                                         *\n;*                  Last Update : October 26th, 1995  [ST]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nglobal\tC _AbortModemFunctionPtr:dword\nglobal\tC Memory_Error_Exit\t:dword\nglobal\tC MouseQX\t\t:dword\nglobal\tC MouseQY\t\t:dword\n\nglobal\tFastGetPortHardware_\t:near\nglobal\tFastSetPortHardware_\t:near\nglobal\tPortOpenGreenleafFast_\t:near\nglobal\tHMWaitForOK_\t\t:near\nglobal\tHMSetDialingMethod_\t:near\nglobal\tHMDial_\t\t\t:near\nglobal\tHMInputLine_\t\t:near\nglobal\tHMAnswer_\t\t:near\nglobal\tPortKillTime_\t\t:near\nglobal\tHMSendStringNoWait_\t:near\nglobal\tHMSetUpEchoRoutine_\t:near\nglobal\tHMSetUpAbortKey_\t:near\nglobal\tSetAbortModemFunctionPtr_:near\nglobal\tChange8259Priority_\t:near\nglobal\tHMSendString_\t\t:near\nglobal\tC Stop_Execution\t:near\n\n\nglobal\t_IPX_Initialise:near\nglobal\t_ASM_IPX_Initialise:near\n\n\n\t\tcodeseg\n\n;proc _ASM_IPX_Initialise near\n;\n;\t\tint\t3\n;\t\tjmp\t_IPX_Initialise\n;\n;endp\n\n\n\n\nglobal _Int3:near\nproc _Int3 near\n\t;int\t3\n\tret\nendp\n\n\nproc Stop_Execution C near\n\n\tnop\n\tret\n\nendp\n\n\n\n;\n; Stuff needed from the shape library\n;\n;\n;\n\n\nINCLUDE \"shape.inc\"\n\n\n\n\n;***************************************************************************\n;* ModeX_Blit -- Copy a 320x200 graphic view port to a modex screen        *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\teax - graphic view port                                    *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       extern \"C\" void ModeX_Blit (GraphicBufferClass *source);   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/26/1994 PWG : Created.                                             *\n;*=========================================================================*\n\nSEQUENCER\t=3c4h\t; sequencer port\nMAP_MASK\t=2\t; map mask register\n\n\t\tINCLUDE \"gbuffer.inc\"\n\t\tglobal\tModeX_Blit_:near\n\n\nproc        \tModeX_Blit_ NEAR\n\n\t\tpushad\n\t\tmov\tebx,eax\n\n\t\tmov\tesi,[(GraphicViewPort ebx).GVPOffset]\n\t\tmov\teax,[(GraphicViewPort ebx).GVPXAdd]\n\t\tadd\teax,[(GraphicViewPort ebx).GVPPitch]\n\t\tmov\tedi,0a0000h\n\t\tmov\tebx,eax\n\n\t\tmov\tal,MAP_MASK\n\n\t\tmov\tebp,200\n\n??each_line_lp:\tmov\tah,1\t\t;1st plane\n\t\tpush\tebx\n\t\tpush\tesi\n\n??each_plane_lp:mov\tedx,SEQUENCER\n\t\tout\tdx,ax\n\n\t\tpush\tesi\n\t\tpush\tedi\n\t\tpush\teax\n\n\t\trept\t10\n\t\tmov\tal,[esi]\n\t\tmov\tbl,[esi+8]\n\t\tmov\tcl,[esi+16]\n\t\tmov\tdl,[esi+24]\n\t\tmov\tah,[esi+4]\n\t\tmov\tbh,[esi+12]\n\t\tmov\tch,[esi+20]\n\t\tmov\tdh,[esi+28]\n\t\tshl\tebx,16\n\t\tshl\tedx,16\n\t\tor\tebx,eax\n\t\tor\tedx,ecx\n\t\tmov\t[edi],ebx\n\t\tmov\t[edi+4],edx\n\t\tadd\tesi,32\n\t\tadd\tedi,8\n\t\tendm\n\n\t\tpop\teax\n\t\tpop\tedi\n\t\tpop\tesi\n\t\tinc\tesi\n\t\tshl\tah,1\n\t\tcmp\tah,16\n\t\tjl\t??each_plane_lp\n\n\n\t\tpop\tesi\n\t\tpop\tebx\n\t\tlea\tesi,[esi+ebx+320]\n\t\tadd\tedi,80\n\t\tdec\tebp\n\t\tjnz\t??each_line_lp\n\n\t\tpopad\n\n\t\tret\n\nendp\t\tModeX_Blit_\n\n\n\n\n\n\nifdef cuts\n\t\tpushad\n\t\tmov\tebx,eax\n\n\t\tmov\tesi,[(GraphicViewPort ebx).GVPOffset]\n\t\tmov\teax,[(GraphicViewPort ebx).GVPXAdd]\n\t\tadd\teax,[(GraphicViewPort ebx).GVPPitch]\n\t\tmov\tedi,0a0000h\n\t\tmov\tebx,eax\n\n\t\tmov\tal,MAP_MASK\n\t\tmov\tah,1\t\t;1st plane\n\n??each_plane_lp:mov\tedx,SEQUENCER\n\t\tout\tdx,ax\n\t\tmov\tebp,200\t\t;do 200 lines\n\t\tpush\tesi\n\t\tpush\tedi\n\n??each_line_lp:\tmov\tecx,320/4\n\n??each_pixel_lp:mov\tdl,[esi]\n\t\tmov\t[edi],dl\n\t\tadd\tesi,4\n\t\tinc\tedi\n\t\tdec\tecx\n\t\tjnz\t??each_pixel_lp\n\n\t\tadd\tesi,ebx\n\t\tdec\tebp\n\t\tjnz\t??each_line_lp\n\n\t\tpop\tedi\n\t\tpop\tesi\n\t\tinc\tesi\n\t\tshl\tah,1\n\n\t\tcmp\tah,16\n\t\tjl\t??each_plane_lp\nendif\n\n\n\n\n\n\n\n\n\n\nproc FastGetPortHardware_ NEAR\nendp\n\nproc FastSetPortHardware_ NEAR\nendp\n\nproc PortOpenGreenleafFast_ NEAR\nendp\n\nproc HMWaitForOK_ NEAR\nendp\n\nproc HMSetDialingMethod_ NEAR\nendp\n\nproc HMDial_ NEAR\nendp\n\nproc HMInputLine_ NEAR\nendp\n\nproc HMAnswer_ NEAR\nendp\n\nproc PortKillTime_ NEAR\nendp\n\nproc HMSendStringNoWait_ NEAR\nendp\n\nproc HMSetUpEchoRoutine_ NEAR\nendp\n\nproc HMSetUpAbortKey_ NEAR\nendp\n\nproc SetAbortModemFunctionPtr_ NEAR\nendp\n\nproc Change8259Priority_ NEAR\nendp\n\nproc HMSendString_ NEAR\nendp\n\n\t\tret\n\n\n\n\n\n\n\n\tmasm\n;\n; Change a DAC colour register directly\n;\n; register number in al\n;\n; bh=red bl=green cl=blue\n;\n\nset_dac_col proc near\n\t\tpushad\n\t\tcli\n\t\tpush\teax\n\t\tmov\tdx,03dah\n\t\tin\tal,dx\n\t\tjmp\t@@1\n@@1:\t\tmov\tdx,03c8h\n\t\tpop\teax\n\t\tout\tdx,al\n\t\tjmp\t@@2\n@@2:\t\tinc\tdl\n\t\tmov\tal,bh\n\t\tout\tdx,al\n\t\tjmp\t@@3\n@@3:\t\tmov\tal,bl\n\t\tout\tdx,al\n\t\tjmp\t@@4\n@@4:\t\tmov\tal,cl\n\t\tout\tdx,al\n\t\tjmp\t@@5\n@@5:\t\tsti\n\t\tpopad\n\t\tret\nset_dac_col endp\n\n\tideal\n\n\nglobal\tSet_Palette_Register_:near\n\n\nproc Set_Palette_Register_ near\n\n\t\tpushad\n\t\tand\tcl,63\n\t\tmov\tbh,dl\n\t\tand\tbh,63\n\t\tand\tbl,63\n\t\tcall\tset_dac_col\n\t\tpopad\n\t\tret\n\nendp Set_Palette_Register_\n\n\n\n\n\t\tlocals\t??\n\n\n\n\t\tends\n\n\t\tdataseg\n\nLineBuffer\t\tdd\t640 dup (?)\n\t\tends\n\n\n\n\t\tsegment mycode page public use32 'code'\t; Need stricter segment alignment\n\nglobal\t\tC\tAsm_Interpolate:near\nglobal\t\tC\tAsm_Interpolate_Line_Double:near\nglobal\t\tC\tAsm_Interpolate_Line_Interpolate:near\nglobal\t\tC\tPaletteInterpolationTable:byte\n\n\n;*********************************************************************************************\n;* Asm_Interpolate -- interpolate a 320x200 buffer to a 640x400 screen                       *\n;*                                                                                           *\n;* INPUT:\tptr to source buffer (320x200 image)                                         *\n;*              ptr to dest buffer (640x400)                                                 *\n;*              height of source buffer                                                      *\n;*              width of source buffer                                                        *\n;*              width of dest buffer                                                         *\n;*                                                                                           *\n;*                                                                                           *\n;* OUTPUT:      none                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   12/15/95 ST : Created.                                                                  *\n;*===========================================================================================*\n\nPROC\t\tAsm_Interpolate C near\n\n\t\tARG\tsrc_ptr:dword\n\t\tARG\tdest_ptr:dword\n\t\tARG\tsource_height:dword\n\t\tARG\tsource_width:dword\n\t\tARG\tdest_width:dword\n\n\t\tLOCAL\told_dest:dword\n\n\t\tpushad\n\n\t\tmov\teax,[dest_ptr]\n\t\tmov\t[old_dest],eax\n\n\t\tmov\tesi,[src_ptr]\n\n??each_line_loop:\n\t\tmov\tecx,[source_width]\n\t\tsub\tecx,2\n\t\tshr\tecx,1\n\t\tmov\tedi,[old_dest]\n\t\tjmp\t??interpolate_loop\n\n\t\talign\t32\n;\n; convert 2 pixels of source into 4 pixels of destination\n; so we can write to video memory with dwords\n;\n??interpolate_loop:\n\t\tmov\teax,[esi]\n\t\tlea\tesi,[esi+2]\n\t\tmov\tedx,eax\n\t\tmov\tebx,eax\n\t\tand\tedx,65535\n\t\tror\tebx,8\n\t\tmov\tbl,[edx+PaletteInterpolationTable]\n\t\tmov\tbh,ah\n\t\tand\teax,000ffff00h\n\t\tror\tebx,8\n\n;1st 3 pixels now in ebx\n\n\t\tshr\teax,8\n\t\tmov\tbh,[eax+PaletteInterpolationTable]\n\t\tror\tebx,16\n\t\tmov\t[edi],ebx\n\t\tadd\tedi,4\n\n\t\tdec\tecx\n\t\tjnz\t??interpolate_loop\n\n; do the last three pixels and a blank on the end of a row\n\t\txor\teax,eax\n\t\tmov\tax,[esi]\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\t\tlea\tesi,[esi+2]\n\t\tmov\tal,[eax+PaletteInterpolationTable]\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\t\tmov\t[edi],ah\n\t\tinc\tedi\n\t\tmov\t[byte edi],0\n\n\t\tmov\tedi,[dest_width]\n\t\tadd\t[old_dest],edi\n\n\t\tdec\t[source_height]\n\t\tjnz\t??each_line_loop\n\n\t\tpopad\n\t\tret\n\nendp\t\tAsm_Interpolate\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nPROC\t\tAsm_Interpolate_Line_Double C near\n\t\tARG\tsrc_ptr:dword\n\t\tARG\tdest_ptr:dword\n\t\tARG\tsource_height:dword\n\t\tARG\tsource_width:dword\n\t\tARG\tdest_width:dword\n\n\t\tLOCAL\told_dest:dword\n\t\tLOCAL\twidth_counter:dword\n\t\tLOCAL\tpixel_count:dword\n\n\t\tpushad\n\n\t\tmov\teax,[dest_ptr]\n\t\tmov\t[old_dest],eax\n\n\t\tmov\tesi,[src_ptr]\n\t\tmov\tedi,[dest_ptr]\n\n??each_line_loop:\n\t\tmov\t[width_counter],0\n\t\tmov\tecx,[source_width]\n\t\tsub\tecx,2\n\t\tshr\tecx,1\n\t\tmov\t[pixel_count],ecx\n\t\tmov\tecx,offset LineBuffer\n\t\tmov\tedi,[old_dest]\n\t\tjmp\t??interpolate_loop\n\t\talign\t16\n\n; convert 2 pixels of source into 4 pixels of destination\n??interpolate_loop:\n\t\tmov\teax,[esi]\n\t\tlea\tesi,[esi+2]\n\t\tmov\tedx,eax\n\t\tmov\tebx,eax\n\t\tand\tedx,65535\n\t\tror\tebx,8\n\t\tmov\tbl,[edx+PaletteInterpolationTable]\n\t\tmov\tbh,ah\n\t\tand\teax,000ffff00h\n\t\tror\tebx,8\n\n\t\t;1st 3 pixels now in ebx\n\t\tshr\teax,8\n\t\tmov\tbh,[eax+PaletteInterpolationTable]\n\t\tror\tebx,16\n\t\tmov\t[edi],ebx\n\t\tmov\t[ecx],ebx\n\t\tadd\tedi,4\n\t\tadd\tecx,4\n\n\t\tdec\t[pixel_count]\n\t\tjnz\t??interpolate_loop\n\n; do the last three pixels and a blank\n\n\t\txor\teax,eax\n\t\tmov\tax,[esi]\n\t\tmov\t[edi],al\n\t\tmov\t[ecx],al\n\t\tinc\tedi\n\t\tinc\tecx\n\t\tlea\tesi,[esi+2]\n\t\tmov\tal,[eax+PaletteInterpolationTable]\n\t\tmov\t[edi],al\n\t\tmov\t[ecx],al\n\t\tinc\tedi\n\t\tinc\tecx\n\t\tmov\t[edi],ah\n\t\tmov\t[ecx],ah\n\t\tinc\tedi\n\t\tinc\tecx\n\t\tmov\t[byte edi],0\n\t\tmov\t[byte ecx],0\n\n\t\tmov\tedi,[dest_width]\n\t\tshr\tedi,1\n\t\tadd\t[old_dest],edi\n\t\tpush\tesi\n\t\tpush\tedi\n\t\tmov\tesi,offset LineBuffer\n\t\tmov\tedi,[old_dest]\n\t\tmov\tecx,[source_width]\n\t\tshr\tecx,1\n\t\trep\tmovsd\n\t\tpop\tedi\n\t\tpop\tesi\n\t\tadd\t[old_dest],edi\n\t\tmov\tedi,[old_dest]\n\n\t\tdec\t[source_height]\n\t\tjnz\t??each_line_loop\n\n\t\tpopad\n\t\tret\n\nendp\t\tAsm_Interpolate_Line_Double\n\n\n\n\n\n\n\n\n\n\t\tends\n\n\t\tdataseg\n\nTopLine\t\tdd\t640 dup (?)\nBottomLine\tdd\t640 dup (?)\n\n\n\t\tsegment mycode page public use32 'code'\t; Need stricter segment alignment\n\n\nproc\t\tInterpolate_Single_Line C near\n\n\t\tARG\tsource_ptr:dword\n\t\tARG\tdest_ptr:dword\n\t\tARG\tsource_width:dword\n\n\t\tpushad\n\n\t\tmov\tecx,[source_width]\n\t\tsub\tecx,2\n\t\tshr\tecx,1\n\n\t\tmov\tesi,[source_ptr]\n\t\tmov\tedi,[dest_ptr]\n\n??interpolate_loop:\n\t\tmov\teax,[esi]\n\t\tlea\tesi,[esi+2]\n\t\tmov\tedx,eax\n\t\tmov\tebx,eax\n\t\tand\tedx,65535\n\t\tror\tebx,8\n\t\tmov\tbl,[edx+PaletteInterpolationTable]\n\t\tmov\tbh,ah\n\t\tand\teax,000ffff00h\n\t\tror\tebx,8\n\n\t\t;1st 3 pixels now in ebx\n\t\tshr\teax,8\n\t\tmov\tbh,[eax+PaletteInterpolationTable]\n\t\tror\tebx,16\n\t\tmov\t[edi],ebx\n\t\tadd\tedi,4\n\n\t\tdec\tecx\n\t\tjnz\t??interpolate_loop\n\n; do the last three pixels and a blank\n\n\t\txor\teax,eax\n\t\tmov\tax,[esi]\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\t\tmov\tal,[eax+PaletteInterpolationTable]\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\t\tmov\t[edi],ah\n\t\tinc\tedi\n\t\tmov\t[byte edi],0\n\n\t\tpopad\n\t\tret\n\n\nendp\t\tInterpolate_Single_Line\n\n\nproc\t\tInterpolate_Between_Lines C near\n\n\t\tARG\tsource1:dword\n\t\tARG\tsource2:dword\n\t\tARG\tdestination:dword\n\t\tARG\tsource_width:dword\n\n\t\tpushad\n\t\tmov\tesi,[source1]\n\t\tmov\tedi,[destination]\n\t\tmov\tebx,[source2]\n\t\txor\teax,eax\n\t\tmov\tecx,[source_width]\n\t\tadd\tecx,ecx\n\n??interpolate_each_pixel_loop:\n\t\tmov\tal,[esi]\n\t\tmov\tah,[ebx]\n\t\tinc\tesi\n\t\tinc\tebx\n\t\tmov\tdl,[eax+PaletteInterpolationTable]\n\t\tmov\t[edi],dl\n\t\tinc\tedi\n\t\tdec\tecx\n\t\tjnz\t??interpolate_each_pixel_loop\n\n\t\tpopad\n\t\tret\n\nendp\t\tInterpolate_Between_Lines\n\n\n\n\nmacro\t\tLineswp\n\t\tpush\t[next_line]\n\t\tpush\t[last_line]\n\t\tpop\t[next_line]\n\t\tpop\t[last_line]\nendm\n\n\nPROC\t\tAsm_Interpolate_Line_Interpolate C near\n\n\n\t\tARG\tsrc_ptr:dword\n\t\tARG\tdest_ptr:dword\n\t\tARG\tsource_lines:dword\n\t\tARG\tsource_width:dword\n\t\tARG\tdest_width:dword\n\n\t\tLOCAL\told_dest:dword\n\t\tLOCAL\tpixel_count:dword\n\t\tLOCAL\tnext_line:dword\n\t\tLOCAL\tlast_line:dword\n\n\t\tpushad\n\n\t\tmov\teax,[dest_ptr]\n\t\tmov\t[old_dest],eax\n\n\t\tmov\t[next_line],offset TopLine\n\t\tmov\t[last_line],offset BottomLine\n\t\tmov\tecx,[source_width]\n\t\tshr\tecx,1\n\t\tmov\t[pixel_count],ecx\n\t\tshr\t[dest_width],1\n\n\t\tcall\tInterpolate_Single_Line C,[src_ptr],[next_line],[source_width]\n\t\tmov\tesi,[source_width]\n\t\tLineswp\n\t\tadd\t[src_ptr],esi\n\t\tdec\t[source_lines]\n\n\n??each_line_pair_loop:\n\t\tcall\tInterpolate_Single_Line C,[src_ptr],[next_line],[source_width]\n\t\tcall\tInterpolate_Between_Lines C,[last_line],[next_line],offset LineBuffer,[source_width]\n\n\t\tmov\tesi,[last_line]\n\t\tmov\tedi,[old_dest]\n\t\tmov\tecx,[pixel_count]\n\t\trep\tmovsd\n\n\t\tmov\tedi,[old_dest]\n\t\tmov\tesi,offset LineBuffer\n\t\tadd\tedi,[dest_width]\n\t\tmov\tecx,[pixel_count]\n\t\tmov\t[old_dest],edi\n\t\trep\tmovsd\n\n\t\tmov\tedi,[old_dest]\n\t\tmov\tesi,[source_width]\n\t\tadd\tedi,[dest_width]\n\t\tadd\t[src_ptr],esi\n\t\tmov\t[old_dest],edi\n\n\t\tLineswp\n\t\tdec\t[source_lines]\n\t\tjnz\t??each_line_pair_loop\n\n\t\tcall\tInterpolate_Single_Line C,[src_ptr],[next_line],[source_width]\n\t\tmov\tesi,[next_line]\n\t\tmov\tedi,[old_dest]\n\t\tmov\tecx,[pixel_count]\n\t\trep\tmovsd\n\n\t\tpopad\n\t\tret\n\n\nendp\t\tAsm_Interpolate_Line_Interpolate\n\n\t\tends\tmycode\n\n\n\n\nglobal\t\tC Asm_Create_Palette_Interpolation_Table:near\nglobal\t\tC InterpolationPalette:dword\n\n\t\tcodeseg\n\n\nproc\t\tAsm_Create_Palette_Interpolation_Table C near\n\n\t\tLOCAL\tpalette_counter:dword\n\t\tLOCAL\tfirst_palette:dword\n\t\tLOCAL\tsecond_palette:dword\n\t\tLOCAL\tdest_ptr:dword\n\t\tLOCAL\tcount:dword\n\t\tLOCAL\tclosest_colour:dword\n\t\tLOCAL\tdistance_of_closest:dword\n\n\t\tpushad\n\n\t\tmov\t[dest_ptr],0\n\t\tmov\t[palette_counter],256\n\t\tmov\tesi,[InterpolationPalette]\n\n??palette_outer_loop:\n\t\tmov\tedi,[InterpolationPalette]\n\t\tmov\tecx,256\n\n??palette_inner_loop:\n\t\tmov\tbl,[esi]\n\t\tadd\tbl,[edi]\n\t\tshr\tbl,1\n\n\t\tmov\tbh,[esi+1]\n\t\tadd\tbh,[edi+1]\n\t\tshr\tbh,1\n\n\t\tmov\tdl,[esi+2]\n\t\tadd\tdl,[edi+2]\n\t\tshr\tdl,1\n\n\t\tmov\t[closest_colour],0\n\t\tmov\t[distance_of_closest],-1\n\n\t\tpush\tedi\n\t\tpush\tecx\n\t\tmov\tedi,[InterpolationPalette]\n\t\tmov\t[count],0\n\n??cmp_pal_lp:\txor\teax,eax\n\t\txor\tecx,ecx\n\t\tmov\tal,[edi]\n\t\tsub\tal,bl\n\t\timul\tal\n\t\tmov\tecx,eax\n\t\tmov\tal,[edi+1]\n\t\tsub\tal,bh\n\t\timul\tal\n\t\tadd\tecx,eax\n\t\tmov\tal,[edi+2]\n\t\tsub\tal,dl\n\t\timul\tal\n\t\tadd\tecx,eax\n\n\t\tcmp\tecx,[distance_of_closest]\n\t\tja\t??end_cmp_lp\n\t\tmov\t[distance_of_closest],ecx\n\t\tmov\teax,[count]\n\t\tmov\t[closest_colour],eax\n\t\ttest\tecx,ecx\n\t\tjz\t??got_perfect\n\n??end_cmp_lp:\tlea\tedi,[edi+3]\n\t\tinc\t[count]\n\t\tcmp\t[count],256\n\t\tjb\t??cmp_pal_lp\n\n\n??got_perfect:\tmov\tedi,[dest_ptr]\n\t\tmov\teax,[closest_colour]\n\t\tmov\t[edi+PaletteInterpolationTable],al\n\t\tinc\t[dest_ptr]\n\n\t\tpop\tecx\n\t\tpop\tedi\n\t\tlea\tedi,[edi+3]\n\t\tdec\tecx\n\t\tjnz\t??palette_inner_loop\n\n\t\tlea\tesi,[esi+3]\n\t\tdec\t[palette_counter]\n\t\tjnz\t??palette_outer_loop\n\n\t\tpopad\n\t\tret\n\nendp\t\tAsm_Create_Palette_Interpolation_Table\n\n\n\n\n\tDATASEG\n\n_AbortModemFunctionPtr\tdd\t0\nMemory_Error_Exit\tdd\t0\nMouseQX\t\t\tdd\t0\nMouseQY\t\t\tdd\t0\n\nend\n"
  },
  {
    "path": "CODE/WINSTUB.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/WINSTUB.CPP 3     3/13/97 2:06p Steve_tall $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : WINSTUB.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 10/04/95                                                     *\n *                                                                                             *\n *                  Last Update : October 4th 1995 [ST]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *   This file contains stubs for undefined externals when linked under Watcom for Win 95      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *   Assert_Failure -- display the line and source file where a failed assert occurred         *\n *   Check_For_Focus_Loss -- check for the end of the focus loss                               *\n *   Create_Main_Window -- opens the MainWindow for C&C                                        *\n *   Focus_Loss -- this function is called when a library function detects focus loss          *\n *   Memory_Error_Handler -- Handle a possibly fatal failure to allocate memory                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n#ifdef WINSOCK_IPX\n#include \"WSProto.h\"\n#else\t//WINSOCK_IPX\n#include \"tcpip.h\"\n#include \"ipx95.h\"\n#endif\t//WINSOCK_IPX\n\nvoid output(short,short)\n{}\n\n\nunsigned long CCFocusMessage = WM_USER+50;\t//Private message for receiving application focus\nextern\tvoid VQA_PauseAudio(void);\nextern\tvoid VQA_ResumeAudio(void);\n\n//#include \"WolDebug.h\"\n\n\n/***********************************************************************************************\n * Focus_Loss -- this function is called when a library function detects focus loss            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    2/1/96 2:10PM ST : Created                                                               *\n *=============================================================================================*/\n\nvoid Focus_Loss(void)\n{\n\tTheme.Suspend();\n\tStop_Primary_Sound_Buffer();\n\tif (WWMouse) WWMouse->Clear_Cursor_Clip();\n}\n\nvoid Focus_Restore(void)\n{\n\tRestore_Cached_Icons();\n\tMap.Flag_To_Redraw(true);\n\tStart_Primary_Sound_Buffer(TRUE);\n\tif (WWMouse) WWMouse->Set_Cursor_Clip();\n\tVisiblePage.Clear();\n\tHiddenPage.Clear();\n}\n\n\n\n/***********************************************************************************************\n * Check_For_Focus_Loss -- check for the end of the focus loss                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    2/2/96 10:49AM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Check_For_Focus_Loss(void)\n{\n\tstatic BOOL\tfocus_last_time = 1;\n\t\t\t MSG\tmsg;\n\n\n\tif ( !GameInFocus ) {\n\t\tFocus_Loss();\n\t\twhile ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE | PM_NOYIELD ) ) {\n\t  \t\tif (!GetMessage( &msg, NULL, 0, 0 ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tTranslateMessage(&msg);\n\t\t\tDispatchMessage(&msg);\n\t\t}\n\t}\n\n\tif (!focus_last_time && GameInFocus) {\n\n\t\tVQA_PauseAudio();\n\t\tCountDownTimerClass cd;\n\t\tcd.Set(60*1);\n\n\t\tdo {\n\t\t\twhile (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE )) {\n\t  \t\t\tif (!GetMessage( &msg, NULL, 0, 0 ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tTranslateMessage(&msg);\n\t\t\t\tDispatchMessage(&msg);\n\t\t\t}\n\n\t\t} while (cd.Time());\n\t\tVQA_ResumeAudio();\n\t\tPostMessage (MainWindow, CCFocusMessage, 0, 0);\n//\t\tAllSurfaces.Restore_Surfaces();\n//\t\tVisiblePage.Clear();\n//\t\tHiddenPage.Clear();\n//\t\tMap.Flag_To_Redraw(true);\n\t}\n\n\tfocus_last_time = GameInFocus;\n\n}\n\n\n\nextern BOOL InMovie;\n\nlong FAR PASCAL _export Windows_Procedure(HWND hwnd, UINT message, UINT wParam, LONG lParam)\n{\n\n\tint\tlow_param = LOWORD(wParam);\n\n\tif (message == CCFocusMessage) {\n\t\tStart_Primary_Sound_Buffer(TRUE);\n\t\tif (!InMovie) {\n\t\t\tTheme.Stop();\n\t\t\tTheme.Queue_Song(THEME_PICK_ANOTHER);\n\t\t}\n\t\treturn(0);\n\t}\n\n#ifdef WINSOCK_IPX\n\t/*\n\t** Pass on any messages intended for the winsock message handler.\n\t*/\n\tif ( PacketTransport ) {\n\t\tif ( message == (UINT) PacketTransport->Protocol_Event_Message() ) {\n\t\t\tif ( PacketTransport->Message_Handler (hwnd, message, wParam, lParam) ){\n\t\t\t\treturn ( DefWindowProc (hwnd, message, wParam, lParam) );\n\t\t\t}else{\n\t\t\t\treturn (0);\n\t\t\t}\n\t\t}\n\t}\n#endif\t//WINSOCK_IPX\n\n\t\n\t/*\n\t**\tPass this message through to the keyboard handler. If the message\n\t**\twas processed and requires no further action, then return with\n\t**\tthis information.\n\t*/\n\tif (Keyboard->Message_Handler(hwnd, message, wParam, lParam)) {\n\t\treturn(1);\n\t}\n\n\tswitch ( message ) {\n//\t\tcase WM_SYSKEYDOWN:\n//\t\t\tMono_Printf(\"wparam=%08X lparam=%08X\\n\", (long)wParam, (long)lParam);\n\t\t\t// fall through\n\n//\t\tcase WM_MOUSEMOVE:\n//\t\tcase WM_KEYDOWN:\n//\t\tcase WM_SYSKEYUP:\n//\t\tcase WM_KEYUP:\n//\t\tcase WM_LBUTTONDOWN:\n//\t\tcase WM_LBUTTONUP:\n//\t\tcase WM_LBUTTONDBLCLK:\n//\t\tcase WM_MBUTTONDOWN:\n//\t\tcase WM_MBUTTONUP:\n//\t\tcase WM_MBUTTONDBLCLK:\n//\t\tcase WM_RBUTTONDOWN:\n//\t\tcase WM_RBUTTONUP:\n//\t\tcase WM_RBUTTONDBLCLK:\n//\t \t\tKeyboard->Message_Handler(hwnd, message, wParam, lParam);\n//\t\t\treturn(0);\n\n\t\t\t/*\n\t\t\t** Windoze message says we have to shut down. Try and do it cleanly.\n\t\t\t*/\n\t\tcase WM_DESTROY:\n\t\t\tProg_End();\n\t\t\tInvalidate_Cached_Icons();\n\t\t\tVisiblePage.Un_Init();\n\t\t\tHiddenPage.Un_Init();\n\t\t\tAllSurfaces.Release();\n\t\t\tif (!InDebugger) Reset_Video_Mode();\n\t\t\tStop_Profiler();\n\t\t\tPostQuitMessage( 0 );\n\n\t\t\t/*\n\t\t\t** If we are shutting down gracefully than flag that the message loop has finished.\n\t\t\t** If this is a forced shutdown (ReadyToQuit == 0) then try and close down everything\n\t\t\t** before we exit.\n\t\t\t*/\n\t\t\tswitch (ReadyToQuit) {\n\t\t\t\tcase 1:\n\t\t\t\t\tReadyToQuit = 2;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 0:\n\t\t\t\t\tShutdown_Network();\n#ifndef WINSOCK_IPX\n\t\t\t\t\tif (Winsock.Get_Connected()) Winsock.Close();\n\t\t\t\t\t/*\n\t\t\t\t\t** Free the THIPX32 dll\n\t\t\t\t\t*/\n\t\t\t\t\tUnload_IPX_Dll();\n#endif\t//WINSOCK_IPX\n\t\t\t\t\tExitProcess(0);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tShutdown_Network();\n#ifndef WINSOCK_IPX\n\t\t\t\t\t/*\n\t\t\t\t\t** Call the function to disable the IPX callback as horrible things can\n\t\t\t\t\t** happen if we get a callback after the process has exited!\n\t\t\t\t\t*/\n\t\t\t\t\tif (Session.Type == GAME_IPX){\n\t\t\t\t\t\tIPX_Shut_Down95();\n\t\t\t\t\t}\n\t\t\t\t\t/*\n\t\t\t\t\t** Free the THIPX32 dll\n\t\t\t\t\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n#else\n\t\t\t\t\tUnload_IPX_Dll();\n#endif\n\n\t\t\t\t\tif (Winsock.Get_Connected()) Winsock.Close();\n#endif\t//WINSOCK_IPX\n\t\t\t\t\tReadyToQuit = 2;\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\t\t\treturn(0);\n\n\t\tcase WM_ACTIVATEAPP:\n\t\t\tGameInFocus=(BOOL)wParam;\n\t\t\tif (!GameInFocus) Focus_Loss();\n\t\t\tAllSurfaces.Set_Surface_Focus (GameInFocus);\n\t\t\tAllSurfaces.Restore_Surfaces();\n//\t\t\tif (GameInFocus) {\n//\t\t\t\tRestore_Cached_Icons();\n//\t\t\t\tMap.Flag_To_Redraw(true);\n//\t\t\t\tStart_Primary_Sound_Buffer(TRUE);\n//\t\t\t\tif (WWMouse) WWMouse->Set_Cursor_Clip();\n//\t\t\t}\n\t\t\treturn(0);\n#ifdef NEVER\n\t\tcase WM_ACTIVATE:\n\t\t\tif (low_param == WA_INACTIVE) {\n\t\t\t\tGameInFocus = FALSE;\n\t\t\t\tFocus_Loss();\n\t\t\t}\n\t\t\treturn(0);\n#endif\t//NEVER\n\n\n\t\tcase WM_SYSCOMMAND:\n\t\t\tswitch ( wParam ) {\n\n\t\t\t\tcase SC_CLOSE:\n\t\t\t\t\t/*\n\t\t\t\t\t** Windows sent us a close message. Probably in response to Alt-F4. Ignore it by\n\t\t\t\t\t** pretending to handle the message and returning true;\n\t\t\t\t\t*/\n\t\t\t\t\treturn (0);\n\n\t\t\t\tcase SC_SCREENSAVE:\n\t\t\t\t\t/*\n\t\t\t\t\t** Windoze is about to start the screen saver. If we just return without passing\n\t\t\t\t\t** this message to DefWindowProc then the screen saver will not be allowed to start.\n\t\t\t\t\t*/\n\t\t\t\t\treturn (0);\n\t\t\t}\n\t\t\tbreak;\n\n\n#ifndef WINSOCK_IPX\n\t\tcase WM_ACCEPT:\n\t\tcase WM_HOSTBYADDRESS:\n\t\tcase WM_HOSTBYNAME:\n\t\tcase WM_ASYNCEVENT:\n\t\tcase WM_UDPASYNCEVENT:\n\t \t\tWinsock.Message_Handler(hwnd, message, wParam, lParam);\n\t\t\treturn (0);\n#endif\t//WINSOCK_IPX\n\t}\n\n\n\n\treturn DefWindowProc (hwnd, message, wParam, lParam);\n}\n\n\n\n\n\n\nHANDLE DebugFile = INVALID_HANDLE_VALUE;\n\n/***********************************************************************************************\n * WWDebugString -- sends a string to the debugger and echos it to disk                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    string                                                                            *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/28/96 12:48PM ST : Created                                                              *\n *=============================================================================================*/\nvoid WWDebugString (char *string)\n{\n#if (0)\n\tchar outstr[256];\n\n\tsprintf (outstr, \"%s\", string);\n\n\tDWORD\tactual;\n\tif (DebugFile == INVALID_HANDLE_VALUE){\n\t\tDebugFile = CreateFile(\"debug.txt\", GENERIC_WRITE, 0,\n\t\t\t\t\t\t\t\t\t\t\t\tNULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);\n\t}else{\n\t\tDebugFile = CreateFile(\"debug.txt\", GENERIC_WRITE, 0,\n\t\t\t\t\t\t\t\t\t\t\t\tNULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n\t}\n\n\tif (DebugFile != INVALID_HANDLE_VALUE){\n\t\tSetFilePointer (DebugFile, 0, NULL, FILE_END);\n\t\tWriteFile(DebugFile, outstr, strlen(outstr)+1, &actual, NULL);\n\t\tCloseHandle (DebugFile);\n\t}\n\n\tOutputDebugString (string);\n#else\t//(0)\n\n\tstring = string;\n//\tdebugprint( string );\n\n#endif\t//(0)\n\n}\n\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Create_Main_Window -- opens the MainWindow for C&C                                          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    instance -- handle to program instance                                            *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/10/95 4:08PM ST : Created                                                             *\n *=============================================================================================*/\n\n#define CC_ICON 1\n\n#if (ENGLISH)\n#define WINDOW_NAME\t\t\"Red Alert\"\n#endif\n\n#if (FRENCH)\n#define WINDOW_NAME\t\t\"Alerte Rouge\"\n#endif\n\n#if (GERMAN)\n#define WINDOW_NAME\t\t\"Alarmstufe Rot\"\n#endif\n\n\nvoid Create_Main_Window ( HANDLE instance , int command_show , int width , int height )\n\n{\n\tHWND        \thwnd ;\n\tWNDCLASS    \twndclass ;\n\t//\n\t// Register the window class\n\t//\n\n\twndclass.style         = CS_HREDRAW | CS_VREDRAW ;\n\twndclass.lpfnWndProc   = Windows_Procedure ;\n\twndclass.cbClsExtra    = 0 ;\n\twndclass.cbWndExtra    = 0 ;\n\twndclass.hInstance     = instance ;\n\twndclass.hIcon         = LoadIcon (instance, MAKEINTRESOURCE(CC_ICON)) ;\n\twndclass.hCursor       = NULL;\n\twndclass.hbrBackground = NULL;\n\twndclass.lpszMenuName  = WINDOW_NAME;\t//NULL\n\twndclass.lpszClassName = WINDOW_NAME;\n\n\tRegisterClass (&wndclass) ;\n\n\n\t//\n\t// Create our main window\n\t//\n\thwnd = CreateWindowEx (\n\t\t\t\t\t\t\tWS_EX_TOPMOST,\n\t\t\t\t\t\t\tWINDOW_NAME,\n\t\t\t\t\t\t\tWINDOW_NAME,\n\t\t\t\t\t\t\tWS_POPUP, // Denzil | WS_MAXIMIZE,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t// Denzil 5/18/98 - Making window fullscreen prevents other apps\n\t\t\t\t\t\t\t// from getting WM_PAINT messages\n\t\t\t\t\t\t\tGetSystemMetrics(SM_CXSCREEN), //width,\n\t\t\t\t\t\t\tGetSystemMetrics(SM_CYSCREEN), //height,\n\t\t\t\t\t\t\t// End Denzil\n\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\tinstance,\n\t\t\t\t\t\t\tNULL );\n// Denzil\nwidth = width; height = height;\n// End\n\n\tShowWindow (hwnd, command_show );\n\tShowCommand = command_show;\n\tUpdateWindow (hwnd);\n\tSetFocus (hwnd);\n\tMainWindow=hwnd;\t\t\t//Save the handle to our main window\n\thInstance = instance;\n\n\tCCFocusMessage = RegisterWindowMessage (\"CC_GOT_FOCUS\");\n\n\tAudio_Focus_Loss_Function = &Focus_Loss;\n\tMisc_Focus_Loss_Function = &Focus_Loss;\n\tMisc_Focus_Restore_Function = &Focus_Restore;\n\tGbuffer_Focus_Loss_Function = &Focus_Loss;\n}\n\n\nvoid Window_Dialog_Box(HANDLE  hinst, LPCTSTR  lpszTemplate, HWND  hwndOwner, DLGPROC  dlgprc)\n{\n\tMSG\t\t\t\t\tmsg;\n\t/*\n\t** Get rid of the Westwood mouse cursor because we are showing a\n\t** dialog box and we want to have the right windows cursor showing\n\t** for it.\n\t*/\n\tHide_Mouse();\n\tShowCursor(TRUE);\n\n\t/*\n\t** Pop up the dialog box and then run a standard message handler\n\t** until the dialog box is closed.\n\t*/\n\n\tDialogBox(hinst, lpszTemplate, hwndOwner, dlgprc);\n\twhile (GetMessage(&msg, NULL, 0, 0) && !AllDone) {\n\t\tTranslateMessage(&msg);\n\t\tDispatchMessage(&msg);\n\t}\n\n\t/*\n\t** Restore the westwood mouse cursor and get rid of the windows one\n\t** because it is now time to restore back to the westwood way of\n\t** doing things.\n\t*/\n\tShowCursor(FALSE);\n\tShow_Mouse();\n}\n\n\n\ntypedef struct tColourList {\n\n\tchar\tRed;\n\tchar\tGreen;\n\tchar\tBlue;\n} ColourList;\n\nColourList\tColourLookup[9]={\n\t0,0,0,\n\t63,0,0,\n\t0,63,0,\n\t0,0,63,\n\t63,0,63,\n\t63,63,0,\n\t0,63,63,\n\t32,32,32,\n\t63,63,63\n};\n\n\n\n\nint\tDebugColour=1;\n\n\nextern \"C\" void Set_Palette_Register(int number, int red, int green, int blue);\n#pragma off (unreferenced)\nvoid Colour_Debug (int call_number)\n{\n\t//#if 0\n\t//if (DebugColour==call_number || !call_number) {\n\n\t\t//if (call_number) {\n\t\t//\tWait_Vert_Blank();\n\t\t//}\n\n\t\tSet_Palette_Register (0,ColourLookup[call_number].Red ,\n\t\t\t\t\t\t\t\t\t\tColourLookup[call_number].Green,\n\t\t\t\t\t\t\t\t\t\tColourLookup[call_number].Blue);\n\t//}\n\t//#endif\n}\n\n#pragma on (unreferenced)\n\n\n\n\n\nBOOL Any_Locked (void)\n{\n\tif (SeenBuff.Get_LockCount() ||\n\t\tHidPage.Get_LockCount()) {\n\t\treturn (TRUE);\n\t} else {\n\t\treturn(FALSE);\n\t}\n}\n\n\n\n\n\n\n\n\n//\n// Miscellaneous stubs. Mainly for multi player stuff\n//\n//\n//\n\n//IPXAddressClass::IPXAddressClass(void) {\n//\tint i;\n//\ti++;\n//}\n//int IPXManagerClass::Num_Connections(void) { return (0); }\n//int IPXManagerClass::Connection_ID( int ) { return (0); }\n//IPXAddressClass * IPXManagerClass::Connection_Address( int ) { return ((IPXAddressClass*)0); }\n//char * IPXManagerClass::Connection_Name( int ) { return ((char*)0); }\n//int IPXAddressClass::Is_Broadcast() { return (0); }\n//int IPXManagerClass::Send_Global_Message( void *, int, int, IPXAddressClass * ) { return (0); }\n//int IPXManagerClass::Service() { return (0); }\n//int IPXManagerClass::Get_Global_Message( void  *, int  *, IPXAddressClass  *, short unsigned  * ) { return (0); }\n//int IPXAddressClass::operator ==( IPXAddressClass  & ) { return (0); }\n//IPXManagerClass::IPXManagerClass( int, int, int, int, short unsigned, short unsigned ) {}\n//IPXManagerClass::~IPXManagerClass() {\n//\tint i;\n//\ti++;\n//\t}\n//int  IPXManagerClass::Delete_Connection( int ) { return (0); }\n//IPXAddressClass::IPXAddressClass( char unsigned  *, char unsigned  * ) {}\n//void  IPXManagerClass::Set_Socket( short unsigned ) {}\n//int  IPXManagerClass::Is_IPX() { return (0); }\n//int  IPXManagerClass::Init() { return (0); }\n//void  IPXAddressClass::Get_Address( char unsigned  *, char unsigned  * ) {}\n//void  IPXManagerClass::Set_Bridge( char unsigned  * ) {}\n//int  IPXManagerClass::Global_Num_Send() { return (0); }\n//void  IPXManagerClass::Set_Timing( long unsigned, long unsigned, long unsigned ) {}\n//unsigned long IPXManagerClass::Global_Response_Time() { return (0); }\n//int  IPXManagerClass::Create_Connection( int, char  *, IPXAddressClass  * ) { return (0); }\n//int  IPXAddressClass::operator !=( IPXAddressClass  & ) { return (0); }\n//int  IPXManagerClass::Send_Private_Message( void  *, int, int, int ) { return (0); }\n//int  IPXManagerClass::Get_Private_Message( void  *, int  *, int  * ) { return (0); }\n//int  IPXManagerClass::Connection_Index( int ) { return (0); }\n//void  IPXManagerClass::Reset_Response_Time() {}\n//long unsigned  IPXManagerClass::Response_Time() { return (0); }\n//int  IPXManagerClass::Private_Num_Send( int ) { return (0); }\n\n//_VQAHandle  *  VQA_Alloc(void) { return ((_VQAHandle *)0); }\n//void  VQA_Init( _VQAHandle  *, long ( *)()) {}\n//long  VQA_Open( _VQAHandle  *, char const  *, _VQAConfig  * ) { return (0); }\n//void  VQA_Free( _VQAHandle  * ) {}\n//void  VQA_Close( _VQAHandle  * ) {}\n//long  VQA_Play( _VQAHandle  *, long ) { return (0); }\n\n//void VQA_Init(VQAHandle *, long(*)(VQAHandle *vqa, long action,\tvoid *buffer, long nbytes)) {}\n\n//long VQA_Open(VQAHandle *, char const *, VQAConfig *)\n//{\n//\treturn (0);\n//}\n\n//void VQA_Close(VQAHandle *) {}\n\n//long VQA_Play(VQAHandle *, long)\n//{\n//\treturn (0);\n//}\n\n\nunsigned char\t*VQPalette;\nlong\t\t\t\tVQNumBytes;\nunsigned long\tVQSlowpal;\nbool\t\t\t\tVQPaletteChange = false;\n\n\nextern \"C\"{\n\tvoid __cdecl SetPalette(unsigned char *palette, long numbytes, unsigned long slowpal);\n}\n\n\n\nvoid Flag_To_Set_Palette(unsigned char *palette, long numbytes, unsigned long slowpal)\n{\n\tVQPalette = palette;\n\tVQNumBytes = numbytes;\n\tVQSlowpal = slowpal;\n\tVQPaletteChange = true;\n}\n\n\n\nvoid Check_VQ_Palette_Set(void)\n{\n\tif (VQPaletteChange) {\n\t\tSetPalette(VQPalette, VQNumBytes, VQSlowpal);\n\t\tVQPaletteChange = false;\n\t}\n}\n\n\n\n\n\nvoid __cdecl SetPalette(unsigned char *palette, long, unsigned long)\n{\n\tfor (int i=0 ; i<256*3 ; i++) {\n\t\t*(palette+i)&=63;\n\t}\n\tIncrease_Palette_Luminance(palette , 15 , 15 , 15 ,63);\n\n\tif (PalettesRead) {\n\t\tmemcpy (&PaletteInterpolationTable[0][0] , InterpolatedPalettes[PaletteCounter++] , 65536);\n\t}\n\tSet_Palette(palette);\n}\n\n\n#ifndef NDEBUG\n/***********************************************************************************************\n * Assert_Failure -- display the line and source file where a failed assert occurred           *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    line number in source file                                                        *\n *           name of source file                                                               *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    4/17/96 9:58AM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Assert_Failure (char *expression, int line, char *file)\n{\n\tchar\tassertbuf[256];\n\tchar   timebuff[512];\n\tSYSTEMTIME\ttime;\n\n\tsprintf (assertbuf, \"assert '%s' failed at line %d in module %s.\\n\", expression, line, file);\n\n\tif (!MonoClass::Is_Enabled()) MonoClass::Enable();\n\n\tMono_Clear_Screen();\n\tMono_Printf(\"%s\", assertbuf);\n\n\tWWDebugString(assertbuf);\n\n\tGetLocalTime(&time);\n\n\tsprintf (timebuff, \"%02d/%02d/%04d %02d:%02d:%02d - %s\", time.wMonth, time.wDay, time.wYear,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttime.wHour, time.wMinute, time.wSecond,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tassertbuf);\n\n\n\tHMMIO handle = mmioOpen(\"ASSERT.TXT\", NULL, MMIO_WRITE);\n\tif (!handle) {\n\t\thandle = mmioOpen(\"ASSERT.TXT\", NULL, MMIO_CREATE | MMIO_WRITE);\n\t\t//mmioClose(handle, 0);\n\t\t//handle = mmioOpen(\"ASSERT.TXT\", NULL, MMIO_WRITE);\n\t}\n\n\tif (handle) {\n\n\t\tmmioWrite(handle, timebuff, strlen(timebuff));\n\t\tmmioClose(handle, 0);\n\t}\n\n\tWWMessageBox().Process(assertbuf);\n//\tWWMessageBox().Process(\"Red Alert demo timed out - Aborting\");\n\t//Get_Key();\n\n\tProg_End();\n\tInvalidate_Cached_Icons();\n\tPostQuitMessage( 0 );\n\tExitProcess(0);\n}\n#endif\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Memory_Error_Handler -- Handle a possibly fatal failure to allocate memory                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/22/96 3:57PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Memory_Error_Handler(void)\n{\n\tVisiblePage.Clear();\n\tCCPalette.Set();\n\twhile (Get_Mouse_State()) {Show_Mouse();};\n\tWWMessageBox().Process(TEXT_MEMORY_ERROR, TEXT_ABORT, false);\n\n\tReadyToQuit = 1;\n\n\tPostMessage(MainWindow, WM_DESTROY, 0, 0);\n\tdo\n\t{\n\t\tKeyboard->Check();\n\t}while (ReadyToQuit == 1);\n\n\tExitProcess(0);\n}\n\n\n\n\n\n\n\n\nGraphicBufferClass* Read_PCX_File(char* name, char* Palette, void *Buff, long Size);\nvoid Load_Title_Screen(char *name, GraphicViewPortClass *video_page, unsigned char *palette)\n{\n\n\tGraphicBufferClass *load_buffer;\n\n\n\tload_buffer = Read_PCX_File (name, (char*)palette, NULL, 0);\n\n\tif (load_buffer) {\n\t\tload_buffer->Blit(*video_page);\n\t\tdelete load_buffer;\n\t}\n}\n\n\n\n#include \"filepcx.h\"\n\n/***************************************************************************\n * READ_PCX_FILE -- read a pcx file into a Graphic Buffer                  *\n *                                                                         *\n *\tGraphicBufferClass* Read_PCX_File (char* name, char* palette ,void *Buff, long size );\t*\n *  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT: name is a NULL terminated string of the format [xxxx.pcx]        *\n *        palette is optional, if palette != NULL the the color palette of *\n *\t\t\t\t\t the pcx file will be place in the memory block pointed\t   *\n *               by palette.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t Buff is optional, if Buff == NULL a new memory Buffer\t\t \t\t*\n *\t\t\t\t\t will be allocated, otherwise the file will be placed \t\t*\n *\t\t\t\t\t at location pointed by Buffer;\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tSize is the size in bytes of the memory block pointed by Buff\t\t*\n *\t\t\t\t  is also optional;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*                                                                         *\n * OUTPUT: on success a pointer to a GraphicBufferClass containing the     *\n *         pcx file, NULL otherwise.                                       *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *         Appears to be a comment-free zone                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1995 JRJ : Created.                                             *\n *   04/30/1996 ST : Tidied up and modified to use CCFileClass             *\n *=========================================================================*/\n\n#define\tPOOL_SIZE 2048\n#define\tREAD_CHAR()  *file_ptr++ ; \\\n\t\t\t\t\t\t\t if ( file_ptr\t>= & pool [ POOL_SIZE ]\t) { \\\n\t\t\t\t\t\t\t\t file_handle.Read (pool , POOL_SIZE ); \\\n\t\t\t\t\t\t\t\t file_ptr = pool ; \\\n\t\t\t\t\t\t\t }\n\n\nGraphicBufferClass* Read_PCX_File(char* name, char* palette, void *Buff, long Size)\n{\n\tunsigned\t\t\t\t\ti, j;\n\tunsigned\t\t\t\t\trle;\n\tunsigned\t\t\t\t\tcolor;\n\tunsigned\t\t\t\t\tscan_pos;\n\tchar\t\t\t\t\t\t*file_ptr;\n\tint\t\t\t\t\t\twidth;\n\tint\t\t\t\t\t\theight;\n\tchar\t\t\t\t\t\t*buffer;\n\tPCX_HEADER\t\t\t\theader;\n\tRGB\t\t\t\t\t\t*pal;\n\tchar\t\t\t\t\t\tpool [POOL_SIZE];\n\tGraphicBufferClass\t*pic;\n\n\tCCFileClass file_handle(name);\n\n\tif (!file_handle.Is_Available()) return (NULL);\n\n\tfile_handle.Open(READ);\n\n\tfile_handle.Read (&header, sizeof (PCX_HEADER));\n\n\tif (header.id != 10 &&  header.version != 5 && header.pixelsize != 8 ) return NULL ;\n\n\twidth = header.width - header.x + 1;\n\theight = header.height - header.y + 1;\n\n\tif (Buff) {\n    \tbuffer = (char *)Buff;\n    \ti = Size / width;\n    \theight = MIN (i - 1, height);\n    \tpic = new GraphicBufferClass(width, height, buffer, Size);\n    \tif ( !(pic && pic->Get_Buffer()) ) return NULL ;\n\t} else {\n    \tpic = new GraphicBufferClass(width, height, NULL, width*(height+4));\n    \tif ( !(pic && pic->Get_Buffer()) ) return NULL ;\n\t}\n\n\tbuffer = (char *) pic->Get_Buffer();\n\tfile_ptr = pool ;\n\tfile_handle.Read (pool , POOL_SIZE);\n\n\tif ( header.byte_per_line != width ) {\n\n\t\tfor ( scan_pos = j = 0 ; j < height ; j ++, scan_pos += width ) {\n\t\t\tfor ( i = 0 ; i < width ; ) {\n\t\t\t\trle = READ_CHAR ();\n\t\t\t\tif ( rle > 192 ) {\n\t\t\t\t\trle -= 192 ;\n\t\t\t\t\tcolor =\tREAD_CHAR (); ;\n\t\t\t\t\tmemset ( buffer + scan_pos + i , color , rle );\n\t\t\t\t\ti += rle;\n\t\t\t\t} else {\n\t\t\t\t\t*(buffer+scan_pos + i++ ) = (char)rle;\n\t\t\t\t}\n\t\t\t}\n      \t}\n\n\t\tif ( i == width ) rle = READ_CHAR ();\n\t\tif ( rle > 192 )  rle = READ_CHAR ();\n\n\t} else {\n\n\t\tfor ( i = 0 ; i < width * height ; ) {\n  \t\t\trle = READ_CHAR ();\n  \t\t\trle &= 0xff;\n  \t\t\tif ( rle > 192 ) {\n        \t\trle -= 192 ;\n        \t\tcolor = READ_CHAR ();\n  \t\t\t\tmemset ( buffer + i , color , rle );\n        \t\ti += rle ;\n     \t\t} else {\n\t\t\t\t*(buffer + i++) = (char)rle;\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( palette ) {\n\t\tfile_handle.Seek (- (256 * sizeof ( RGB )) , SEEK_END );\n\t\tfile_handle.Read (palette , 256L * sizeof ( RGB ));\n\n\t\tpal = ( RGB * ) palette;\n\t\tfor (i = 0 ; i < 256 ; i ++) {\n\t\t\tpal ->red\t>>= 2;\n\t\t\tpal ->green\t>>= 2;\n\t\t\tpal ->blue\t>>= 2;\n\t\t\tpal ++ ;\n\t\t}\n\t}\n\n\tfile_handle.Close();\n\treturn pic;\n}\n"
  },
  {
    "path": "CODE/WOLAPI/CHATDEFS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef CHATDEFS_HEADER\n#define CHATDEFS_HEADER\n\n//\n// Response errors (Sent as arguments to the OnFoo calls)\n//\n\n// Your nick is still logged into chat\n#define CHAT_E_NICKINUSE       MAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 100)\n// Your password is incorrect during login\n#define CHAT_E_BADPASS         MAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 101)\n// Reference made to non-existant user or channel\n#define CHAT_E_NONESUCH\t\t   MAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 102)\n// The network layer is down or cannot be initialized for some reason\n#define CHAT_E_CON_NETDOWN        MAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 103)\n// Name lookup (e.g DNS) failed for some reason\n#define CHAT_E_CON_LOOKUP_FAILED  MAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 104)\n// Some fatal error occured with the net connection\n#define CHAT_E_CON_ERROR          MAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 105)\n// General request timeout for a request\n#define CHAT_E_TIMEOUT            MAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 106)\n// Must patch before continuing\n#define CHAT_E_MUSTPATCH        MAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 107)\n// Miscellaneous internal status error\n#define CHAT_E_STATUSERROR\t\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 108)\n// Server has returned something we don't recognise\n#define CHAT_E_UNKNOWNRESPONSE\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 109)\n// Tried to join a channel that has enough players already\n#define CHAT_E_CHANNELFULL\t\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 110)\n// Tried to create a channel that already exists\n#define CHAT_E_CHANNELEXISTS\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 111)\n// Tried to join a channel that does not exist\n#define CHAT_E_CHANNELDOESNOTEXIST\t\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 112)\n// Tried to join a channel with the wrong password\n#define CHAT_E_BADCHANNELPASSWORD\t\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 113)\n// You've been banned from the server / channel\n#define CHAT_E_BANNED            MAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 114)\n// You tried to do something that required operator status\n#define CHAT_E_NOT_OPER           MAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 115)\n\n\n//\n// Response success codes (non-error arguments passed to the OnFoo callbacks)\n// Note: S_OK is the usual success code\n\n// A network connection is underway\n#define CHAT_S_CON_CONNECTING     MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_ITF, 300)\n// A network connection is complete\n#define CHAT_S_CON_CONNECTED      MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_ITF, 301)\n// A network connection is going down\n#define CHAT_S_CON_DISCONNECTING  MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_ITF, 302)\n// A network connection is closed\n#define CHAT_S_CON_DISCONNECTED   MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_ITF, 303)\n\n\n// Find - Nick not in system\n#define CHAT_S_FIND_NOTHERE   MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_ITF, 304)\n// Find - Not in any channels\n#define CHAT_S_FIND_NOCHAN   MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_ITF, 305)\n// Find - user has find turned off\n#define CHAT_S_FIND_OFF   MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_ITF, 306)\n\n\n// Page - Nick not in system\n#define CHAT_S_PAGE_NOTHERE   MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_ITF, 307)\n// Page - user has page turned off\n#define CHAT_S_PAGE_OFF   MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_ITF, 308)\n\n// This channel list is only a ping update\n#define CHAT_S_PINGLIST  MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_ITF, 315)\n\n\n\n\n\n\n\n//\n// Request errors (returned from the RequestFoo calls)\n// \n\n// You are not connected to the chat server\n#define CHAT_E_NOTCONNECTED    MAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 500)\n// You are not in a channel\n#define CHAT_E_NOCHANNEL       MAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 501)\n// Feature is not implemented\n#define CHAT_E_NOTIMPLEMENTED  MAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 502)\n// The request was made while while a conflicting request was still pending\n#define CHAT_E_PENDINGREQUEST  MAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 503)\n// Invalid parameter passed - usually a NULL pointer\n#define CHAT_E_PARAMERROR\t   MAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 504)\n// Tried to create or join a channel before leaving the previous one\n#define CHAT_E_LEAVECHANNEL\t\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 508)\n// Tried to send something to a channel when not a member of any channel\n#define CHAT_E_JOINCHANNEL\t\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 509)\n// Tried to join a non-existant channel\n#define CHAT_E_UNKNOWNCHANNEL\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 510)\n\n\n//\n// Request success codes\n// Notes: S_OK is the usual success code\n\n//\n// Channel list filter values\n//\n\n#define CHAT_CHANNEL_LIST_ALL\t\t-99999\n\n//\n// User flags (bit field)\n//\n// The owner of the current channel\n#define CHAT_USER_CHANNELOWNER                 0x0001\n// The person with voice (conch shell...)\n#define CHAT_USER_VOICE                        0x0002\n// The local user\n#define CHAT_USER_MYSELF                       0x8000\n\n//\n// Channel flags (bit field)\n//\n#define CHAN_MODE_PRIVATE     0x0004\n#define CHAN_MODE_SECRET      0x0008\n#define CHAN_MODE_MODERATED   0x0010\n#define CHAN_MODE_TOPICLIMIT  0x0020\n#define CHAN_MODE_INVITEONLY  0x0040\n#define CHAN_MODE_NOPRIVMSGS  0x0080\n#define CHAN_MODE_KEY         0x0100\n#define CHAN_MODE_BAN         0x0200\n#define CHAN_MODE_LIMIT       0x0400\n\n\n#endif\n"
  },
  {
    "path": "CODE/WOLAPI/DOWNLOADDEFS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef _DOWNLOADDEFS_H\n#define _DOWNLOADDEFS_H\n\n// CDownload statuses\n\n#define DOWNLOADSTATUS_NONE\t\t\t\t0\n#define DOWNLOADSTATUS_GO\t\t\t\t1\n#define DOWNLOADSTATUS_CONNECTING\t\t2\n#define DOWNLOADSTATUS_LOGGINGIN\t\t3\n#define DOWNLOADSTATUS_FINDINGFILE\t\t4\n#define DOWNLOADSTATUS_QUERYINGRESUME\t5\n#define DOWNLOADSTATUS_DOWNLOADING\t\t6\n#define DOWNLOADSTATUS_DISCONNECTING\t7\n#define\tDOWNLOADSTATUS_DONE\t\t\t\t0\n\n// CDownload return codes\n\n#define DOWNLOAD_SUCCEEDED\t\tS_OK\n#define\tDOWNLOAD_PARAMERROR\t\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 1 )\n#define DOWNLOAD_STATUSERROR\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 2 )\n#define DOWNLOAD_NETWORKERROR\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 3 )\n#define DOWNLOAD_FILEERROR\t\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 4 )\n#define DOWNLOAD_REENTERERROR\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 4 )\n\n// CDownloadEvent return codes.\n\n#define DOWNLOADEVENT_SUCCEEDED\t\tS_OK\n#define\tDOWNLOADEVENT_FAILED\t\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 5 )\n#define\tDOWNLOADEVENT_RESUME\t\tS_OK\n#define\tDOWNLOADEVENT_DONOTRESUME\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 6 )\n\n// CDownloadEvent error codes for OnError()\n\n#define DOWNLOADEVENT_NOSUCHSERVER\t\t\t1\n#define DOWNLOADEVENT_COULDNOTCONNECT\t\t2\n#define DOWNLOADEVENT_LOGINFAILED\t\t\t3\n#define DOWNLOADEVENT_NOSUCHFILE\t\t\t4\n#define DOWNLOADEVENT_LOCALFILEOPENFAILED\t5\n#define DOWNLOADEVENT_TCPERROR\t\t\t\t6\n#define DOWNLOADEVENT_DISCONNECTERROR\t\t7\n\n#endif\n"
  },
  {
    "path": "CODE/WOLAPI/FTPDEFS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef __FTPDEFS_H_INCLUDED__\n#define __FTPDEFS_H_INCLUDED__\n\n\n// CFtp return codes.\n\n#define FTP_SUCCEEDED\t\tS_OK\n#define\tFTP_FAILED\t\t\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 1 )\n#define FTP_TRYING\t\t\tMAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 2 )\n\n\n#endif"
  },
  {
    "path": "CODE/WOLAPI/NETUTILDEFS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef NETUTILDEFS_HEADER\n#define NETUTILDEFS_HEADER\n\n\n#define NETUTIL_E_ERROR       MAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 100)\n#define NETUTIL_E_BUSY        MAKE_HRESULT( SEVERITY_ERROR, FACILITY_ITF, 101)\n\n#define NETUTIL_S_FINISHED    MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_ITF, 500)\n\n#endif"
  },
  {
    "path": "CODE/WOLAPI/WOLAPI.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* this ALWAYS GENERATED file contains the definitions for the interfaces */\n\n\n/* File created by MIDL compiler version 3.01.75 */\n/* at Wed Jul 29 16:25:34 1998\n */\n/* Compiler settings for WOLAPI.idl:\n    Oicf (OptLev=i2), W1, Zp8, env=Win32, ms_ext, c_ext\n    error checks: none\n*/\n//@@MIDL_FILE_HEADING(  )\n#include \"rpc.h\"\n#include \"rpcndr.h\"\n#ifndef COM_NO_WINDOWS_H\n#include \"windows.h\"\n#include \"ole2.h\"\n#endif /*COM_NO_WINDOWS_H*/\n\n#ifndef __WOLAPI_h__\n#define __WOLAPI_h__\n\n#ifdef __cplusplus\nextern \"C\"{\n#endif \n\n/* Forward Declarations */ \n\n#ifndef __IRTPatcher_FWD_DEFINED__\n#define __IRTPatcher_FWD_DEFINED__\ntypedef interface IRTPatcher IRTPatcher;\n#endif \t/* __IRTPatcher_FWD_DEFINED__ */\n\n\n#ifndef __IRTPatcherEvent_FWD_DEFINED__\n#define __IRTPatcherEvent_FWD_DEFINED__\ntypedef interface IRTPatcherEvent IRTPatcherEvent;\n#endif \t/* __IRTPatcherEvent_FWD_DEFINED__ */\n\n\n#ifndef __IChat_FWD_DEFINED__\n#define __IChat_FWD_DEFINED__\ntypedef interface IChat IChat;\n#endif \t/* __IChat_FWD_DEFINED__ */\n\n\n#ifndef __IChatEvent_FWD_DEFINED__\n#define __IChatEvent_FWD_DEFINED__\ntypedef interface IChatEvent IChatEvent;\n#endif \t/* __IChatEvent_FWD_DEFINED__ */\n\n\n#ifndef __IDownload_FWD_DEFINED__\n#define __IDownload_FWD_DEFINED__\ntypedef interface IDownload IDownload;\n#endif \t/* __IDownload_FWD_DEFINED__ */\n\n\n#ifndef __IDownloadEvent_FWD_DEFINED__\n#define __IDownloadEvent_FWD_DEFINED__\ntypedef interface IDownloadEvent IDownloadEvent;\n#endif \t/* __IDownloadEvent_FWD_DEFINED__ */\n\n\n#ifndef __INetUtil_FWD_DEFINED__\n#define __INetUtil_FWD_DEFINED__\ntypedef interface INetUtil INetUtil;\n#endif \t/* __INetUtil_FWD_DEFINED__ */\n\n\n#ifndef __INetUtilEvent_FWD_DEFINED__\n#define __INetUtilEvent_FWD_DEFINED__\ntypedef interface INetUtilEvent INetUtilEvent;\n#endif \t/* __INetUtilEvent_FWD_DEFINED__ */\n\n\n#ifndef __IChat2_FWD_DEFINED__\n#define __IChat2_FWD_DEFINED__\ntypedef interface IChat2 IChat2;\n#endif \t/* __IChat2_FWD_DEFINED__ */\n\n\n#ifndef __IChat2Event_FWD_DEFINED__\n#define __IChat2Event_FWD_DEFINED__\ntypedef interface IChat2Event IChat2Event;\n#endif \t/* __IChat2Event_FWD_DEFINED__ */\n\n\n#ifndef __RTPatcher_FWD_DEFINED__\n#define __RTPatcher_FWD_DEFINED__\n\n#ifdef __cplusplus\ntypedef class RTPatcher RTPatcher;\n#else\ntypedef struct RTPatcher RTPatcher;\n#endif /* __cplusplus */\n\n#endif \t/* __RTPatcher_FWD_DEFINED__ */\n\n\n#ifndef __Chat_FWD_DEFINED__\n#define __Chat_FWD_DEFINED__\n\n#ifdef __cplusplus\ntypedef class Chat Chat;\n#else\ntypedef struct Chat Chat;\n#endif /* __cplusplus */\n\n#endif \t/* __Chat_FWD_DEFINED__ */\n\n\n#ifndef __Download_FWD_DEFINED__\n#define __Download_FWD_DEFINED__\n\n#ifdef __cplusplus\ntypedef class Download Download;\n#else\ntypedef struct Download Download;\n#endif /* __cplusplus */\n\n#endif \t/* __Download_FWD_DEFINED__ */\n\n\n#ifndef __NetUtil_FWD_DEFINED__\n#define __NetUtil_FWD_DEFINED__\n\n#ifdef __cplusplus\ntypedef class NetUtil NetUtil;\n#else\ntypedef struct NetUtil NetUtil;\n#endif /* __cplusplus */\n\n#endif \t/* __NetUtil_FWD_DEFINED__ */\n\n\n#ifndef __Chat2_FWD_DEFINED__\n#define __Chat2_FWD_DEFINED__\n\n#ifdef __cplusplus\ntypedef class Chat2 Chat2;\n#else\ntypedef struct Chat2 Chat2;\n#endif /* __cplusplus */\n\n#endif \t/* __Chat2_FWD_DEFINED__ */\n\n\n/* header files for imported files */\n#include \"oaidl.h\"\n//#include \"ocidl.h\"\n\nvoid __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);\nvoid __RPC_USER MIDL_user_free( void __RPC_FAR * ); \n\n#ifndef __IRTPatcher_INTERFACE_DEFINED__\n#define __IRTPatcher_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IRTPatcher\n * at Wed Jul 29 16:25:34 1998\n * using MIDL 3.01.75\n ****************************************/\n/* [object][unique][helpstring][uuid] */ \n\n\n\nEXTERN_C const IID IID_IRTPatcher;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface DECLSPEC_UUID(\"925CDEDE-71B9-11D1-B1C5-006097176556\")\n    IRTPatcher : public IUnknown\n    {\n    public:\n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ApplyPatch( \n            /* [string][in] */ LPCSTR destpath,\n            /* [string][in] */ LPCSTR filename) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PumpMessages( void) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IRTPatcherVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IRTPatcher __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IRTPatcher __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IRTPatcher __RPC_FAR * This);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ApplyPatch )( \n            IRTPatcher __RPC_FAR * This,\n            /* [string][in] */ LPCSTR destpath,\n            /* [string][in] */ LPCSTR filename);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *PumpMessages )( \n            IRTPatcher __RPC_FAR * This);\n        \n        END_INTERFACE\n    } IRTPatcherVtbl;\n\n    interface IRTPatcher\n    {\n        CONST_VTBL struct IRTPatcherVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IRTPatcher_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IRTPatcher_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IRTPatcher_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IRTPatcher_ApplyPatch(This,destpath,filename)\t\\\n    (This)->lpVtbl -> ApplyPatch(This,destpath,filename)\n\n#define IRTPatcher_PumpMessages(This)\t\\\n    (This)->lpVtbl -> PumpMessages(This)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IRTPatcher_ApplyPatch_Proxy( \n    IRTPatcher __RPC_FAR * This,\n    /* [string][in] */ LPCSTR destpath,\n    /* [string][in] */ LPCSTR filename);\n\n\nvoid __RPC_STUB IRTPatcher_ApplyPatch_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IRTPatcher_PumpMessages_Proxy( \n    IRTPatcher __RPC_FAR * This);\n\n\nvoid __RPC_STUB IRTPatcher_PumpMessages_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IRTPatcher_INTERFACE_DEFINED__ */\n\n\n#ifndef __IRTPatcherEvent_INTERFACE_DEFINED__\n#define __IRTPatcherEvent_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IRTPatcherEvent\n * at Wed Jul 29 16:25:34 1998\n * using MIDL 3.01.75\n ****************************************/\n/* [object][unique][helpstring][uuid] */ \n\n\n\nEXTERN_C const IID IID_IRTPatcherEvent;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface DECLSPEC_UUID(\"925CDEE3-71B9-11D1-B1C5-006097176556\")\n    IRTPatcherEvent : public IUnknown\n    {\n    public:\n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnProgress( \n            /* [in] */ LPCSTR filename,\n            /* [in] */ int progress) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnTermination( \n            /* [in] */ BOOL success) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IRTPatcherEventVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IRTPatcherEvent __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IRTPatcherEvent __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IRTPatcherEvent __RPC_FAR * This);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnProgress )( \n            IRTPatcherEvent __RPC_FAR * This,\n            /* [in] */ LPCSTR filename,\n            /* [in] */ int progress);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnTermination )( \n            IRTPatcherEvent __RPC_FAR * This,\n            /* [in] */ BOOL success);\n        \n        END_INTERFACE\n    } IRTPatcherEventVtbl;\n\n    interface IRTPatcherEvent\n    {\n        CONST_VTBL struct IRTPatcherEventVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IRTPatcherEvent_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IRTPatcherEvent_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IRTPatcherEvent_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IRTPatcherEvent_OnProgress(This,filename,progress)\t\\\n    (This)->lpVtbl -> OnProgress(This,filename,progress)\n\n#define IRTPatcherEvent_OnTermination(This,success)\t\\\n    (This)->lpVtbl -> OnTermination(This,success)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IRTPatcherEvent_OnProgress_Proxy( \n    IRTPatcherEvent __RPC_FAR * This,\n    /* [in] */ LPCSTR filename,\n    /* [in] */ int progress);\n\n\nvoid __RPC_STUB IRTPatcherEvent_OnProgress_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IRTPatcherEvent_OnTermination_Proxy( \n    IRTPatcherEvent __RPC_FAR * This,\n    /* [in] */ BOOL success);\n\n\nvoid __RPC_STUB IRTPatcherEvent_OnTermination_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IRTPatcherEvent_INTERFACE_DEFINED__ */\n\n\n#ifndef __IChat_INTERFACE_DEFINED__\n#define __IChat_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IChat\n * at Wed Jul 29 16:25:34 1998\n * using MIDL 3.01.75\n ****************************************/\n/* [object][unique][helpstring][uuid] */ \n\n\n//typedef long time_t;\n#include <sys\\types.h>\n\nstruct  Ladder\n    {\n    unsigned int sku;\n    unsigned int team_no;\n    unsigned int wins;\n    unsigned int losses;\n    unsigned int points;\n    unsigned int kills;\n    unsigned int rank;\n    unsigned int rung;\n    unsigned int disconnects;\n    unsigned int team_rung;\n    unsigned int provisional;\n    unsigned int last_game_date;\n    unsigned int win_streak;\n    unsigned int reserved1;\n    unsigned int reserved2;\n    struct Ladder __RPC_FAR *next;\n    unsigned char login_name[ 40 ];\n    };\ntypedef int GroupID;\n\nstruct  Server\n    {\n    int gametype;\n    int chattype;\n    int timezone;\n    float longitude;\n    float lattitude;\n    struct Server __RPC_FAR *next;\n    unsigned char name[ 71 ];\n    unsigned char connlabel[ 5 ];\n    unsigned char conndata[ 128 ];\n    unsigned char login[ 10 ];\n    unsigned char password[ 10 ];\n    };\nstruct  Channel\n    {\n    int type;\n    unsigned int minUsers;\n    unsigned int maxUsers;\n    unsigned int currentUsers;\n    unsigned int official;\n    unsigned int tournament;\n    unsigned int ingame;\n    unsigned int flags;\n    unsigned long reserved;\n    unsigned long ipaddr;\n    int latency;\n    int hidden;\n    struct Channel __RPC_FAR *next;\n    unsigned char name[ 17 ];\n    unsigned char topic[ 81 ];\n    unsigned char location[ 65 ];\n    unsigned char key[ 9 ];\n    unsigned char exInfo[ 41 ];\n    };\nstruct  User\n    {\n    unsigned int flags;\n    GroupID group;\n    unsigned long reserved;\n    unsigned long reserved2;\n    unsigned long reserved3;\n    unsigned long reserved4;\n    unsigned long ipaddr;\n    unsigned long squad_icon;\n    struct User __RPC_FAR *next;\n    unsigned char name[ 10 ];\n    unsigned char squadname[ 41 ];\n    };\nstruct  Group\n    {\n    GroupID ident;\n    int type;\n    unsigned int members;\n    struct Group __RPC_FAR *next;\n    unsigned char name[ 65 ];\n    };\nstruct  Update\n    {\n    unsigned long SKU;\n    unsigned long version;\n    int required;\n    struct Update __RPC_FAR *next;\n    unsigned char server[ 65 ];\n    unsigned char patchpath[ 256 ];\n    unsigned char patchfile[ 33 ];\n    unsigned char login[ 33 ];\n    unsigned char password[ 65 ];\n    unsigned char localpath[ 256 ];\n    };\ntypedef struct Server Server;\n\ntypedef struct Channel Channel;\n\ntypedef struct User User;\n\ntypedef struct Group Group;\n\ntypedef struct Update Update;\n\ntypedef struct Ladder Ladder;\n\n\nEXTERN_C const IID IID_IChat;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface DECLSPEC_UUID(\"4DD3BAF4-7579-11D1-B1C6-006097176556\")\n    IChat : public IUnknown\n    {\n    public:\n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PumpMessages( void) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestServerList( \n            /* [in] */ unsigned long SKU,\n            /* [in] */ unsigned long current_version,\n            /* [in] */ LPCSTR loginname,\n            /* [in] */ LPCSTR password,\n            /* [in] */ int timeout) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestConnection( \n            /* [in] */ Server __RPC_FAR *server,\n            /* [in] */ int timeout,\n            int domangle) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestChannelList( \n            /* [in] */ int channelType,\n            /* [in] */ int autoping) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestChannelCreate( \n            /* [in] */ Channel __RPC_FAR *channel) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestChannelJoin( \n            /* [in] */ Channel __RPC_FAR *channel) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestChannelLeave( void) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestUserList( void) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestPublicMessage( \n            /* [in] */ LPCSTR message) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestPrivateMessage( \n            /* [in] */ User __RPC_FAR *users,\n            /* [in] */ LPCSTR message) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestLogout( void) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestPrivateGameOptions( \n            /* [in] */ User __RPC_FAR *users,\n            /* [in] */ LPCSTR options) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestPublicGameOptions( \n            /* [in] */ LPCSTR options) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestPublicAction( \n            /* [in] */ LPCSTR action) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestPrivateAction( \n            /* [in] */ User __RPC_FAR *users,\n            /* [in] */ LPCSTR action) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestGameStart( \n            /* [in] */ User __RPC_FAR *users) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestChannelTopic( \n            /* [in] */ LPCSTR topic) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetVersion( \n            /* [in] */ unsigned long __RPC_FAR *version) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestUserKick( \n            /* [in] */ User __RPC_FAR *user) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestUserIP( \n            /* [in] */ User __RPC_FAR *user) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetGametypeInfo( \n            unsigned int gtype,\n            int icon_size,\n            unsigned char __RPC_FAR *__RPC_FAR *bitmap,\n            int __RPC_FAR *bmp_bytes,\n            LPCSTR __RPC_FAR *name,\n            LPCSTR __RPC_FAR *URL) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestFind( \n            User __RPC_FAR *user) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestPage( \n            User __RPC_FAR *user,\n            LPCSTR message) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetFindPage( \n            int findOn,\n            int pageOn) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetSquelch( \n            User __RPC_FAR *user,\n            int squelch) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetSquelch( \n            User __RPC_FAR *user) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetChannelFilter( \n            int channelType) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestGameEnd( void) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetLangFilter( \n            int onoff) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestChannelBan( \n            LPCSTR name,\n            int ban) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetGametypeList( \n            LPCSTR __RPC_FAR *list) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetHelpURL( \n            LPCSTR __RPC_FAR *url) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetProductSKU( \n            unsigned long SKU) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetNick( \n            int num,\n            LPCSTR __RPC_FAR *nick,\n            LPCSTR __RPC_FAR *pass) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetNick( \n            int num,\n            LPCSTR nick,\n            LPCSTR pass,\n            int domangle) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetLobbyCount( \n            int __RPC_FAR *count) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestRawMessage( \n            LPCSTR ircmsg) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetAttributeValue( \n            LPCSTR attrib,\n            LPCSTR __RPC_FAR *value) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetAttributeValue( \n            LPCSTR attrib,\n            LPCSTR value) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetChannelExInfo( \n            LPCSTR info) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE StopAutoping( void) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IChatVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IChat __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IChat __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IChat __RPC_FAR * This);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *PumpMessages )( \n            IChat __RPC_FAR * This);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestServerList )( \n            IChat __RPC_FAR * This,\n            /* [in] */ unsigned long SKU,\n            /* [in] */ unsigned long current_version,\n            /* [in] */ LPCSTR loginname,\n            /* [in] */ LPCSTR password,\n            /* [in] */ int timeout);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestConnection )( \n            IChat __RPC_FAR * This,\n            /* [in] */ Server __RPC_FAR *server,\n            /* [in] */ int timeout,\n            int domangle);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestChannelList )( \n            IChat __RPC_FAR * This,\n            /* [in] */ int channelType,\n            /* [in] */ int autoping);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestChannelCreate )( \n            IChat __RPC_FAR * This,\n            /* [in] */ Channel __RPC_FAR *channel);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestChannelJoin )( \n            IChat __RPC_FAR * This,\n            /* [in] */ Channel __RPC_FAR *channel);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestChannelLeave )( \n            IChat __RPC_FAR * This);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestUserList )( \n            IChat __RPC_FAR * This);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestPublicMessage )( \n            IChat __RPC_FAR * This,\n            /* [in] */ LPCSTR message);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestPrivateMessage )( \n            IChat __RPC_FAR * This,\n            /* [in] */ User __RPC_FAR *users,\n            /* [in] */ LPCSTR message);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestLogout )( \n            IChat __RPC_FAR * This);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestPrivateGameOptions )( \n            IChat __RPC_FAR * This,\n            /* [in] */ User __RPC_FAR *users,\n            /* [in] */ LPCSTR options);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestPublicGameOptions )( \n            IChat __RPC_FAR * This,\n            /* [in] */ LPCSTR options);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestPublicAction )( \n            IChat __RPC_FAR * This,\n            /* [in] */ LPCSTR action);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestPrivateAction )( \n            IChat __RPC_FAR * This,\n            /* [in] */ User __RPC_FAR *users,\n            /* [in] */ LPCSTR action);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestGameStart )( \n            IChat __RPC_FAR * This,\n            /* [in] */ User __RPC_FAR *users);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestChannelTopic )( \n            IChat __RPC_FAR * This,\n            /* [in] */ LPCSTR topic);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetVersion )( \n            IChat __RPC_FAR * This,\n            /* [in] */ unsigned long __RPC_FAR *version);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestUserKick )( \n            IChat __RPC_FAR * This,\n            /* [in] */ User __RPC_FAR *user);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestUserIP )( \n            IChat __RPC_FAR * This,\n            /* [in] */ User __RPC_FAR *user);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetGametypeInfo )( \n            IChat __RPC_FAR * This,\n            unsigned int gtype,\n            int icon_size,\n            unsigned char __RPC_FAR *__RPC_FAR *bitmap,\n            int __RPC_FAR *bmp_bytes,\n            LPCSTR __RPC_FAR *name,\n            LPCSTR __RPC_FAR *URL);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestFind )( \n            IChat __RPC_FAR * This,\n            User __RPC_FAR *user);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestPage )( \n            IChat __RPC_FAR * This,\n            User __RPC_FAR *user,\n            LPCSTR message);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetFindPage )( \n            IChat __RPC_FAR * This,\n            int findOn,\n            int pageOn);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetSquelch )( \n            IChat __RPC_FAR * This,\n            User __RPC_FAR *user,\n            int squelch);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetSquelch )( \n            IChat __RPC_FAR * This,\n            User __RPC_FAR *user);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetChannelFilter )( \n            IChat __RPC_FAR * This,\n            int channelType);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestGameEnd )( \n            IChat __RPC_FAR * This);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetLangFilter )( \n            IChat __RPC_FAR * This,\n            int onoff);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestChannelBan )( \n            IChat __RPC_FAR * This,\n            LPCSTR name,\n            int ban);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetGametypeList )( \n            IChat __RPC_FAR * This,\n            LPCSTR __RPC_FAR *list);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetHelpURL )( \n            IChat __RPC_FAR * This,\n            LPCSTR __RPC_FAR *url);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetProductSKU )( \n            IChat __RPC_FAR * This,\n            unsigned long SKU);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetNick )( \n            IChat __RPC_FAR * This,\n            int num,\n            LPCSTR __RPC_FAR *nick,\n            LPCSTR __RPC_FAR *pass);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetNick )( \n            IChat __RPC_FAR * This,\n            int num,\n            LPCSTR nick,\n            LPCSTR pass,\n            int domangle);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetLobbyCount )( \n            IChat __RPC_FAR * This,\n            int __RPC_FAR *count);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestRawMessage )( \n            IChat __RPC_FAR * This,\n            LPCSTR ircmsg);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetAttributeValue )( \n            IChat __RPC_FAR * This,\n            LPCSTR attrib,\n            LPCSTR __RPC_FAR *value);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetAttributeValue )( \n            IChat __RPC_FAR * This,\n            LPCSTR attrib,\n            LPCSTR value);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetChannelExInfo )( \n            IChat __RPC_FAR * This,\n            LPCSTR info);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *StopAutoping )( \n            IChat __RPC_FAR * This);\n        \n        END_INTERFACE\n    } IChatVtbl;\n\n    interface IChat\n    {\n        CONST_VTBL struct IChatVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IChat_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IChat_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IChat_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IChat_PumpMessages(This)\t\\\n    (This)->lpVtbl -> PumpMessages(This)\n\n#define IChat_RequestServerList(This,SKU,current_version,loginname,password,timeout)\t\\\n    (This)->lpVtbl -> RequestServerList(This,SKU,current_version,loginname,password,timeout)\n\n#define IChat_RequestConnection(This,server,timeout,domangle)\t\\\n    (This)->lpVtbl -> RequestConnection(This,server,timeout,domangle)\n\n#define IChat_RequestChannelList(This,channelType,autoping)\t\\\n    (This)->lpVtbl -> RequestChannelList(This,channelType,autoping)\n\n#define IChat_RequestChannelCreate(This,channel)\t\\\n    (This)->lpVtbl -> RequestChannelCreate(This,channel)\n\n#define IChat_RequestChannelJoin(This,channel)\t\\\n    (This)->lpVtbl -> RequestChannelJoin(This,channel)\n\n#define IChat_RequestChannelLeave(This)\t\\\n    (This)->lpVtbl -> RequestChannelLeave(This)\n\n#define IChat_RequestUserList(This)\t\\\n    (This)->lpVtbl -> RequestUserList(This)\n\n#define IChat_RequestPublicMessage(This,message)\t\\\n    (This)->lpVtbl -> RequestPublicMessage(This,message)\n\n#define IChat_RequestPrivateMessage(This,users,message)\t\\\n    (This)->lpVtbl -> RequestPrivateMessage(This,users,message)\n\n#define IChat_RequestLogout(This)\t\\\n    (This)->lpVtbl -> RequestLogout(This)\n\n#define IChat_RequestPrivateGameOptions(This,users,options)\t\\\n    (This)->lpVtbl -> RequestPrivateGameOptions(This,users,options)\n\n#define IChat_RequestPublicGameOptions(This,options)\t\\\n    (This)->lpVtbl -> RequestPublicGameOptions(This,options)\n\n#define IChat_RequestPublicAction(This,action)\t\\\n    (This)->lpVtbl -> RequestPublicAction(This,action)\n\n#define IChat_RequestPrivateAction(This,users,action)\t\\\n    (This)->lpVtbl -> RequestPrivateAction(This,users,action)\n\n#define IChat_RequestGameStart(This,users)\t\\\n    (This)->lpVtbl -> RequestGameStart(This,users)\n\n#define IChat_RequestChannelTopic(This,topic)\t\\\n    (This)->lpVtbl -> RequestChannelTopic(This,topic)\n\n#define IChat_GetVersion(This,version)\t\\\n    (This)->lpVtbl -> GetVersion(This,version)\n\n#define IChat_RequestUserKick(This,user)\t\\\n    (This)->lpVtbl -> RequestUserKick(This,user)\n\n#define IChat_RequestUserIP(This,user)\t\\\n    (This)->lpVtbl -> RequestUserIP(This,user)\n\n#define IChat_GetGametypeInfo(This,gtype,icon_size,bitmap,bmp_bytes,name,URL)\t\\\n    (This)->lpVtbl -> GetGametypeInfo(This,gtype,icon_size,bitmap,bmp_bytes,name,URL)\n\n#define IChat_RequestFind(This,user)\t\\\n    (This)->lpVtbl -> RequestFind(This,user)\n\n#define IChat_RequestPage(This,user,message)\t\\\n    (This)->lpVtbl -> RequestPage(This,user,message)\n\n#define IChat_SetFindPage(This,findOn,pageOn)\t\\\n    (This)->lpVtbl -> SetFindPage(This,findOn,pageOn)\n\n#define IChat_SetSquelch(This,user,squelch)\t\\\n    (This)->lpVtbl -> SetSquelch(This,user,squelch)\n\n#define IChat_GetSquelch(This,user)\t\\\n    (This)->lpVtbl -> GetSquelch(This,user)\n\n#define IChat_SetChannelFilter(This,channelType)\t\\\n    (This)->lpVtbl -> SetChannelFilter(This,channelType)\n\n#define IChat_RequestGameEnd(This)\t\\\n    (This)->lpVtbl -> RequestGameEnd(This)\n\n#define IChat_SetLangFilter(This,onoff)\t\\\n    (This)->lpVtbl -> SetLangFilter(This,onoff)\n\n#define IChat_RequestChannelBan(This,name,ban)\t\\\n    (This)->lpVtbl -> RequestChannelBan(This,name,ban)\n\n#define IChat_GetGametypeList(This,list)\t\\\n    (This)->lpVtbl -> GetGametypeList(This,list)\n\n#define IChat_GetHelpURL(This,url)\t\\\n    (This)->lpVtbl -> GetHelpURL(This,url)\n\n#define IChat_SetProductSKU(This,SKU)\t\\\n    (This)->lpVtbl -> SetProductSKU(This,SKU)\n\n#define IChat_GetNick(This,num,nick,pass)\t\\\n    (This)->lpVtbl -> GetNick(This,num,nick,pass)\n\n#define IChat_SetNick(This,num,nick,pass,domangle)\t\\\n    (This)->lpVtbl -> SetNick(This,num,nick,pass,domangle)\n\n#define IChat_GetLobbyCount(This,count)\t\\\n    (This)->lpVtbl -> GetLobbyCount(This,count)\n\n#define IChat_RequestRawMessage(This,ircmsg)\t\\\n    (This)->lpVtbl -> RequestRawMessage(This,ircmsg)\n\n#define IChat_GetAttributeValue(This,attrib,value)\t\\\n    (This)->lpVtbl -> GetAttributeValue(This,attrib,value)\n\n#define IChat_SetAttributeValue(This,attrib,value)\t\\\n    (This)->lpVtbl -> SetAttributeValue(This,attrib,value)\n\n#define IChat_SetChannelExInfo(This,info)\t\\\n    (This)->lpVtbl -> SetChannelExInfo(This,info)\n\n#define IChat_StopAutoping(This)\t\\\n    (This)->lpVtbl -> StopAutoping(This)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_PumpMessages_Proxy( \n    IChat __RPC_FAR * This);\n\n\nvoid __RPC_STUB IChat_PumpMessages_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestServerList_Proxy( \n    IChat __RPC_FAR * This,\n    /* [in] */ unsigned long SKU,\n    /* [in] */ unsigned long current_version,\n    /* [in] */ LPCSTR loginname,\n    /* [in] */ LPCSTR password,\n    /* [in] */ int timeout);\n\n\nvoid __RPC_STUB IChat_RequestServerList_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestConnection_Proxy( \n    IChat __RPC_FAR * This,\n    /* [in] */ Server __RPC_FAR *server,\n    /* [in] */ int timeout,\n    int domangle);\n\n\nvoid __RPC_STUB IChat_RequestConnection_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestChannelList_Proxy( \n    IChat __RPC_FAR * This,\n    /* [in] */ int channelType,\n    /* [in] */ int autoping);\n\n\nvoid __RPC_STUB IChat_RequestChannelList_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestChannelCreate_Proxy( \n    IChat __RPC_FAR * This,\n    /* [in] */ Channel __RPC_FAR *channel);\n\n\nvoid __RPC_STUB IChat_RequestChannelCreate_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestChannelJoin_Proxy( \n    IChat __RPC_FAR * This,\n    /* [in] */ Channel __RPC_FAR *channel);\n\n\nvoid __RPC_STUB IChat_RequestChannelJoin_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestChannelLeave_Proxy( \n    IChat __RPC_FAR * This);\n\n\nvoid __RPC_STUB IChat_RequestChannelLeave_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestUserList_Proxy( \n    IChat __RPC_FAR * This);\n\n\nvoid __RPC_STUB IChat_RequestUserList_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestPublicMessage_Proxy( \n    IChat __RPC_FAR * This,\n    /* [in] */ LPCSTR message);\n\n\nvoid __RPC_STUB IChat_RequestPublicMessage_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestPrivateMessage_Proxy( \n    IChat __RPC_FAR * This,\n    /* [in] */ User __RPC_FAR *users,\n    /* [in] */ LPCSTR message);\n\n\nvoid __RPC_STUB IChat_RequestPrivateMessage_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestLogout_Proxy( \n    IChat __RPC_FAR * This);\n\n\nvoid __RPC_STUB IChat_RequestLogout_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestPrivateGameOptions_Proxy( \n    IChat __RPC_FAR * This,\n    /* [in] */ User __RPC_FAR *users,\n    /* [in] */ LPCSTR options);\n\n\nvoid __RPC_STUB IChat_RequestPrivateGameOptions_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestPublicGameOptions_Proxy( \n    IChat __RPC_FAR * This,\n    /* [in] */ LPCSTR options);\n\n\nvoid __RPC_STUB IChat_RequestPublicGameOptions_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestPublicAction_Proxy( \n    IChat __RPC_FAR * This,\n    /* [in] */ LPCSTR action);\n\n\nvoid __RPC_STUB IChat_RequestPublicAction_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestPrivateAction_Proxy( \n    IChat __RPC_FAR * This,\n    /* [in] */ User __RPC_FAR *users,\n    /* [in] */ LPCSTR action);\n\n\nvoid __RPC_STUB IChat_RequestPrivateAction_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestGameStart_Proxy( \n    IChat __RPC_FAR * This,\n    /* [in] */ User __RPC_FAR *users);\n\n\nvoid __RPC_STUB IChat_RequestGameStart_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestChannelTopic_Proxy( \n    IChat __RPC_FAR * This,\n    /* [in] */ LPCSTR topic);\n\n\nvoid __RPC_STUB IChat_RequestChannelTopic_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_GetVersion_Proxy( \n    IChat __RPC_FAR * This,\n    /* [in] */ unsigned long __RPC_FAR *version);\n\n\nvoid __RPC_STUB IChat_GetVersion_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestUserKick_Proxy( \n    IChat __RPC_FAR * This,\n    /* [in] */ User __RPC_FAR *user);\n\n\nvoid __RPC_STUB IChat_RequestUserKick_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestUserIP_Proxy( \n    IChat __RPC_FAR * This,\n    /* [in] */ User __RPC_FAR *user);\n\n\nvoid __RPC_STUB IChat_RequestUserIP_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_GetGametypeInfo_Proxy( \n    IChat __RPC_FAR * This,\n    unsigned int gtype,\n    int icon_size,\n    unsigned char __RPC_FAR *__RPC_FAR *bitmap,\n    int __RPC_FAR *bmp_bytes,\n    LPCSTR __RPC_FAR *name,\n    LPCSTR __RPC_FAR *URL);\n\n\nvoid __RPC_STUB IChat_GetGametypeInfo_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestFind_Proxy( \n    IChat __RPC_FAR * This,\n    User __RPC_FAR *user);\n\n\nvoid __RPC_STUB IChat_RequestFind_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestPage_Proxy( \n    IChat __RPC_FAR * This,\n    User __RPC_FAR *user,\n    LPCSTR message);\n\n\nvoid __RPC_STUB IChat_RequestPage_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_SetFindPage_Proxy( \n    IChat __RPC_FAR * This,\n    int findOn,\n    int pageOn);\n\n\nvoid __RPC_STUB IChat_SetFindPage_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_SetSquelch_Proxy( \n    IChat __RPC_FAR * This,\n    User __RPC_FAR *user,\n    int squelch);\n\n\nvoid __RPC_STUB IChat_SetSquelch_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_GetSquelch_Proxy( \n    IChat __RPC_FAR * This,\n    User __RPC_FAR *user);\n\n\nvoid __RPC_STUB IChat_GetSquelch_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_SetChannelFilter_Proxy( \n    IChat __RPC_FAR * This,\n    int channelType);\n\n\nvoid __RPC_STUB IChat_SetChannelFilter_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestGameEnd_Proxy( \n    IChat __RPC_FAR * This);\n\n\nvoid __RPC_STUB IChat_RequestGameEnd_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_SetLangFilter_Proxy( \n    IChat __RPC_FAR * This,\n    int onoff);\n\n\nvoid __RPC_STUB IChat_SetLangFilter_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestChannelBan_Proxy( \n    IChat __RPC_FAR * This,\n    LPCSTR name,\n    int ban);\n\n\nvoid __RPC_STUB IChat_RequestChannelBan_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_GetGametypeList_Proxy( \n    IChat __RPC_FAR * This,\n    LPCSTR __RPC_FAR *list);\n\n\nvoid __RPC_STUB IChat_GetGametypeList_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_GetHelpURL_Proxy( \n    IChat __RPC_FAR * This,\n    LPCSTR __RPC_FAR *url);\n\n\nvoid __RPC_STUB IChat_GetHelpURL_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_SetProductSKU_Proxy( \n    IChat __RPC_FAR * This,\n    unsigned long SKU);\n\n\nvoid __RPC_STUB IChat_SetProductSKU_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_GetNick_Proxy( \n    IChat __RPC_FAR * This,\n    int num,\n    LPCSTR __RPC_FAR *nick,\n    LPCSTR __RPC_FAR *pass);\n\n\nvoid __RPC_STUB IChat_GetNick_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_SetNick_Proxy( \n    IChat __RPC_FAR * This,\n    int num,\n    LPCSTR nick,\n    LPCSTR pass,\n    int domangle);\n\n\nvoid __RPC_STUB IChat_SetNick_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_GetLobbyCount_Proxy( \n    IChat __RPC_FAR * This,\n    int __RPC_FAR *count);\n\n\nvoid __RPC_STUB IChat_GetLobbyCount_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_RequestRawMessage_Proxy( \n    IChat __RPC_FAR * This,\n    LPCSTR ircmsg);\n\n\nvoid __RPC_STUB IChat_RequestRawMessage_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_GetAttributeValue_Proxy( \n    IChat __RPC_FAR * This,\n    LPCSTR attrib,\n    LPCSTR __RPC_FAR *value);\n\n\nvoid __RPC_STUB IChat_GetAttributeValue_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_SetAttributeValue_Proxy( \n    IChat __RPC_FAR * This,\n    LPCSTR attrib,\n    LPCSTR value);\n\n\nvoid __RPC_STUB IChat_SetAttributeValue_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_SetChannelExInfo_Proxy( \n    IChat __RPC_FAR * This,\n    LPCSTR info);\n\n\nvoid __RPC_STUB IChat_SetChannelExInfo_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat_StopAutoping_Proxy( \n    IChat __RPC_FAR * This);\n\n\nvoid __RPC_STUB IChat_StopAutoping_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IChat_INTERFACE_DEFINED__ */\n\n\n#ifndef __IChatEvent_INTERFACE_DEFINED__\n#define __IChatEvent_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IChatEvent\n * at Wed Jul 29 16:25:34 1998\n * using MIDL 3.01.75\n ****************************************/\n/* [object][unique][helpstring][uuid] */ \n\n\n\nEXTERN_C const IID IID_IChatEvent;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface DECLSPEC_UUID(\"4DD3BAF6-7579-11D1-B1C6-006097176556\")\n    IChatEvent : public IUnknown\n    {\n    public:\n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnServerList( \n            /* [in] */ HRESULT res,\n            /* [in] */ Server __RPC_FAR *servers) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnUpdateList( \n            /* [in] */ HRESULT res,\n            /* [in] */ Update __RPC_FAR *updates) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnServerError( \n            /* [in] */ HRESULT res,\n            /* [in] */ LPCSTR ircmsg) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnConnection( \n            /* [in] */ HRESULT res,\n            /* [in] */ LPCSTR motd) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnMessageOfTheDay( \n            /* [in] */ HRESULT res,\n            /* [in] */ LPCSTR motd) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnChannelList( \n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channels) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnChannelCreate( \n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnChannelJoin( \n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            /* [in] */ User __RPC_FAR *user) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnChannelLeave( \n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            /* [in] */ User __RPC_FAR *user) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnChannelTopic( \n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            /* [in] */ LPCSTR topic) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnPrivateAction( \n            /* [in] */ HRESULT res,\n            /* [in] */ User __RPC_FAR *user,\n            /* [in] */ LPCSTR action) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnPublicAction( \n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            User __RPC_FAR *user,\n            /* [in] */ LPCSTR action) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnUserList( \n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            /* [in] */ User __RPC_FAR *users) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnPublicMessage( \n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            /* [in] */ User __RPC_FAR *user,\n            /* [in] */ LPCSTR message) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnPrivateMessage( \n            /* [in] */ HRESULT res,\n            /* [in] */ User __RPC_FAR *user,\n            /* [in] */ LPCSTR message) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnSystemMessage( \n            /* [in] */ HRESULT res,\n            /* [in] */ LPCSTR message) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnNetStatus( \n            /* [in] */ HRESULT res) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnLogout( \n            /* [in] */ HRESULT status,\n            /* [in] */ User __RPC_FAR *user) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnPrivateGameOptions( \n            /* [in] */ HRESULT res,\n            /* [in] */ User __RPC_FAR *user,\n            /* [in] */ LPCSTR options) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnPublicGameOptions( \n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            /* [in] */ User __RPC_FAR *user,\n            /* [in] */ LPCSTR options) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnGameStart( \n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            /* [in] */ User __RPC_FAR *users,\n            /* [in] */ int gameid) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnUserKick( \n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            /* [in] */ User __RPC_FAR *kicked,\n            /* [in] */ User __RPC_FAR *kicker) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnUserIP( \n            /* [in] */ HRESULT res,\n            /* [in] */ User __RPC_FAR *user) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnFind( \n            HRESULT res,\n            Channel __RPC_FAR *chan) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnPageSend( \n            HRESULT res) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnPaged( \n            HRESULT res,\n            User __RPC_FAR *user,\n            LPCSTR message) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnServerBannedYou( \n            HRESULT res,\n            time_t bannedTill) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnUserFlags( \n            HRESULT res,\n            LPCSTR name,\n            unsigned int flags,\n            unsigned int mask) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnChannelBan( \n            HRESULT res,\n            LPCSTR name,\n            int banned) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IChatEventVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IChatEvent __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IChatEvent __RPC_FAR * This);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnServerList )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ Server __RPC_FAR *servers);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnUpdateList )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ Update __RPC_FAR *updates);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnServerError )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ LPCSTR ircmsg);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnConnection )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ LPCSTR motd);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnMessageOfTheDay )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ LPCSTR motd);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnChannelList )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channels);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnChannelCreate )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnChannelJoin )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            /* [in] */ User __RPC_FAR *user);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnChannelLeave )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            /* [in] */ User __RPC_FAR *user);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnChannelTopic )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            /* [in] */ LPCSTR topic);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnPrivateAction )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ User __RPC_FAR *user,\n            /* [in] */ LPCSTR action);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnPublicAction )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            User __RPC_FAR *user,\n            /* [in] */ LPCSTR action);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnUserList )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            /* [in] */ User __RPC_FAR *users);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnPublicMessage )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            /* [in] */ User __RPC_FAR *user,\n            /* [in] */ LPCSTR message);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnPrivateMessage )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ User __RPC_FAR *user,\n            /* [in] */ LPCSTR message);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnSystemMessage )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ LPCSTR message);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnNetStatus )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnLogout )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT status,\n            /* [in] */ User __RPC_FAR *user);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnPrivateGameOptions )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ User __RPC_FAR *user,\n            /* [in] */ LPCSTR options);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnPublicGameOptions )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            /* [in] */ User __RPC_FAR *user,\n            /* [in] */ LPCSTR options);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnGameStart )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            /* [in] */ User __RPC_FAR *users,\n            /* [in] */ int gameid);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnUserKick )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ Channel __RPC_FAR *channel,\n            /* [in] */ User __RPC_FAR *kicked,\n            /* [in] */ User __RPC_FAR *kicker);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnUserIP )( \n            IChatEvent __RPC_FAR * This,\n            /* [in] */ HRESULT res,\n            /* [in] */ User __RPC_FAR *user);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnFind )( \n            IChatEvent __RPC_FAR * This,\n            HRESULT res,\n            Channel __RPC_FAR *chan);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnPageSend )( \n            IChatEvent __RPC_FAR * This,\n            HRESULT res);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnPaged )( \n            IChatEvent __RPC_FAR * This,\n            HRESULT res,\n            User __RPC_FAR *user,\n            LPCSTR message);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnServerBannedYou )( \n            IChatEvent __RPC_FAR * This,\n            HRESULT res,\n            time_t bannedTill);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnUserFlags )( \n            IChatEvent __RPC_FAR * This,\n            HRESULT res,\n            LPCSTR name,\n            unsigned int flags,\n            unsigned int mask);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnChannelBan )( \n            IChatEvent __RPC_FAR * This,\n            HRESULT res,\n            LPCSTR name,\n            int banned);\n        \n        END_INTERFACE\n    } IChatEventVtbl;\n\n    interface IChatEvent\n    {\n        CONST_VTBL struct IChatEventVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IChatEvent_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IChatEvent_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IChatEvent_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IChatEvent_OnServerList(This,res,servers)\t\\\n    (This)->lpVtbl -> OnServerList(This,res,servers)\n\n#define IChatEvent_OnUpdateList(This,res,updates)\t\\\n    (This)->lpVtbl -> OnUpdateList(This,res,updates)\n\n#define IChatEvent_OnServerError(This,res,ircmsg)\t\\\n    (This)->lpVtbl -> OnServerError(This,res,ircmsg)\n\n#define IChatEvent_OnConnection(This,res,motd)\t\\\n    (This)->lpVtbl -> OnConnection(This,res,motd)\n\n#define IChatEvent_OnMessageOfTheDay(This,res,motd)\t\\\n    (This)->lpVtbl -> OnMessageOfTheDay(This,res,motd)\n\n#define IChatEvent_OnChannelList(This,res,channels)\t\\\n    (This)->lpVtbl -> OnChannelList(This,res,channels)\n\n#define IChatEvent_OnChannelCreate(This,res,channel)\t\\\n    (This)->lpVtbl -> OnChannelCreate(This,res,channel)\n\n#define IChatEvent_OnChannelJoin(This,res,channel,user)\t\\\n    (This)->lpVtbl -> OnChannelJoin(This,res,channel,user)\n\n#define IChatEvent_OnChannelLeave(This,res,channel,user)\t\\\n    (This)->lpVtbl -> OnChannelLeave(This,res,channel,user)\n\n#define IChatEvent_OnChannelTopic(This,res,channel,topic)\t\\\n    (This)->lpVtbl -> OnChannelTopic(This,res,channel,topic)\n\n#define IChatEvent_OnPrivateAction(This,res,user,action)\t\\\n    (This)->lpVtbl -> OnPrivateAction(This,res,user,action)\n\n#define IChatEvent_OnPublicAction(This,res,channel,user,action)\t\\\n    (This)->lpVtbl -> OnPublicAction(This,res,channel,user,action)\n\n#define IChatEvent_OnUserList(This,res,channel,users)\t\\\n    (This)->lpVtbl -> OnUserList(This,res,channel,users)\n\n#define IChatEvent_OnPublicMessage(This,res,channel,user,message)\t\\\n    (This)->lpVtbl -> OnPublicMessage(This,res,channel,user,message)\n\n#define IChatEvent_OnPrivateMessage(This,res,user,message)\t\\\n    (This)->lpVtbl -> OnPrivateMessage(This,res,user,message)\n\n#define IChatEvent_OnSystemMessage(This,res,message)\t\\\n    (This)->lpVtbl -> OnSystemMessage(This,res,message)\n\n#define IChatEvent_OnNetStatus(This,res)\t\\\n    (This)->lpVtbl -> OnNetStatus(This,res)\n\n#define IChatEvent_OnLogout(This,status,user)\t\\\n    (This)->lpVtbl -> OnLogout(This,status,user)\n\n#define IChatEvent_OnPrivateGameOptions(This,res,user,options)\t\\\n    (This)->lpVtbl -> OnPrivateGameOptions(This,res,user,options)\n\n#define IChatEvent_OnPublicGameOptions(This,res,channel,user,options)\t\\\n    (This)->lpVtbl -> OnPublicGameOptions(This,res,channel,user,options)\n\n#define IChatEvent_OnGameStart(This,res,channel,users,gameid)\t\\\n    (This)->lpVtbl -> OnGameStart(This,res,channel,users,gameid)\n\n#define IChatEvent_OnUserKick(This,res,channel,kicked,kicker)\t\\\n    (This)->lpVtbl -> OnUserKick(This,res,channel,kicked,kicker)\n\n#define IChatEvent_OnUserIP(This,res,user)\t\\\n    (This)->lpVtbl -> OnUserIP(This,res,user)\n\n#define IChatEvent_OnFind(This,res,chan)\t\\\n    (This)->lpVtbl -> OnFind(This,res,chan)\n\n#define IChatEvent_OnPageSend(This,res)\t\\\n    (This)->lpVtbl -> OnPageSend(This,res)\n\n#define IChatEvent_OnPaged(This,res,user,message)\t\\\n    (This)->lpVtbl -> OnPaged(This,res,user,message)\n\n#define IChatEvent_OnServerBannedYou(This,res,bannedTill)\t\\\n    (This)->lpVtbl -> OnServerBannedYou(This,res,bannedTill)\n\n#define IChatEvent_OnUserFlags(This,res,name,flags,mask)\t\\\n    (This)->lpVtbl -> OnUserFlags(This,res,name,flags,mask)\n\n#define IChatEvent_OnChannelBan(This,res,name,banned)\t\\\n    (This)->lpVtbl -> OnChannelBan(This,res,name,banned)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnServerList_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ Server __RPC_FAR *servers);\n\n\nvoid __RPC_STUB IChatEvent_OnServerList_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnUpdateList_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ Update __RPC_FAR *updates);\n\n\nvoid __RPC_STUB IChatEvent_OnUpdateList_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnServerError_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ LPCSTR ircmsg);\n\n\nvoid __RPC_STUB IChatEvent_OnServerError_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnConnection_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ LPCSTR motd);\n\n\nvoid __RPC_STUB IChatEvent_OnConnection_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnMessageOfTheDay_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ LPCSTR motd);\n\n\nvoid __RPC_STUB IChatEvent_OnMessageOfTheDay_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnChannelList_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ Channel __RPC_FAR *channels);\n\n\nvoid __RPC_STUB IChatEvent_OnChannelList_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnChannelCreate_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ Channel __RPC_FAR *channel);\n\n\nvoid __RPC_STUB IChatEvent_OnChannelCreate_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnChannelJoin_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ Channel __RPC_FAR *channel,\n    /* [in] */ User __RPC_FAR *user);\n\n\nvoid __RPC_STUB IChatEvent_OnChannelJoin_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnChannelLeave_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ Channel __RPC_FAR *channel,\n    /* [in] */ User __RPC_FAR *user);\n\n\nvoid __RPC_STUB IChatEvent_OnChannelLeave_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnChannelTopic_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ Channel __RPC_FAR *channel,\n    /* [in] */ LPCSTR topic);\n\n\nvoid __RPC_STUB IChatEvent_OnChannelTopic_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnPrivateAction_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ User __RPC_FAR *user,\n    /* [in] */ LPCSTR action);\n\n\nvoid __RPC_STUB IChatEvent_OnPrivateAction_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnPublicAction_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ Channel __RPC_FAR *channel,\n    User __RPC_FAR *user,\n    /* [in] */ LPCSTR action);\n\n\nvoid __RPC_STUB IChatEvent_OnPublicAction_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnUserList_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ Channel __RPC_FAR *channel,\n    /* [in] */ User __RPC_FAR *users);\n\n\nvoid __RPC_STUB IChatEvent_OnUserList_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnPublicMessage_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ Channel __RPC_FAR *channel,\n    /* [in] */ User __RPC_FAR *user,\n    /* [in] */ LPCSTR message);\n\n\nvoid __RPC_STUB IChatEvent_OnPublicMessage_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnPrivateMessage_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ User __RPC_FAR *user,\n    /* [in] */ LPCSTR message);\n\n\nvoid __RPC_STUB IChatEvent_OnPrivateMessage_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnSystemMessage_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ LPCSTR message);\n\n\nvoid __RPC_STUB IChatEvent_OnSystemMessage_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnNetStatus_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res);\n\n\nvoid __RPC_STUB IChatEvent_OnNetStatus_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnLogout_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT status,\n    /* [in] */ User __RPC_FAR *user);\n\n\nvoid __RPC_STUB IChatEvent_OnLogout_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnPrivateGameOptions_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ User __RPC_FAR *user,\n    /* [in] */ LPCSTR options);\n\n\nvoid __RPC_STUB IChatEvent_OnPrivateGameOptions_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnPublicGameOptions_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ Channel __RPC_FAR *channel,\n    /* [in] */ User __RPC_FAR *user,\n    /* [in] */ LPCSTR options);\n\n\nvoid __RPC_STUB IChatEvent_OnPublicGameOptions_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnGameStart_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ Channel __RPC_FAR *channel,\n    /* [in] */ User __RPC_FAR *users,\n    /* [in] */ int gameid);\n\n\nvoid __RPC_STUB IChatEvent_OnGameStart_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnUserKick_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ Channel __RPC_FAR *channel,\n    /* [in] */ User __RPC_FAR *kicked,\n    /* [in] */ User __RPC_FAR *kicker);\n\n\nvoid __RPC_STUB IChatEvent_OnUserKick_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnUserIP_Proxy( \n    IChatEvent __RPC_FAR * This,\n    /* [in] */ HRESULT res,\n    /* [in] */ User __RPC_FAR *user);\n\n\nvoid __RPC_STUB IChatEvent_OnUserIP_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnFind_Proxy( \n    IChatEvent __RPC_FAR * This,\n    HRESULT res,\n    Channel __RPC_FAR *chan);\n\n\nvoid __RPC_STUB IChatEvent_OnFind_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnPageSend_Proxy( \n    IChatEvent __RPC_FAR * This,\n    HRESULT res);\n\n\nvoid __RPC_STUB IChatEvent_OnPageSend_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnPaged_Proxy( \n    IChatEvent __RPC_FAR * This,\n    HRESULT res,\n    User __RPC_FAR *user,\n    LPCSTR message);\n\n\nvoid __RPC_STUB IChatEvent_OnPaged_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnServerBannedYou_Proxy( \n    IChatEvent __RPC_FAR * This,\n    HRESULT res,\n    time_t bannedTill);\n\n\nvoid __RPC_STUB IChatEvent_OnServerBannedYou_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnUserFlags_Proxy( \n    IChatEvent __RPC_FAR * This,\n    HRESULT res,\n    LPCSTR name,\n    unsigned int flags,\n    unsigned int mask);\n\n\nvoid __RPC_STUB IChatEvent_OnUserFlags_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChatEvent_OnChannelBan_Proxy( \n    IChatEvent __RPC_FAR * This,\n    HRESULT res,\n    LPCSTR name,\n    int banned);\n\n\nvoid __RPC_STUB IChatEvent_OnChannelBan_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IChatEvent_INTERFACE_DEFINED__ */\n\n\n#ifndef __IDownload_INTERFACE_DEFINED__\n#define __IDownload_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IDownload\n * at Wed Jul 29 16:25:34 1998\n * using MIDL 3.01.75\n ****************************************/\n/* [unique][helpstring][dual][uuid][object] */ \n\n\n\nEXTERN_C const IID IID_IDownload;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface DECLSPEC_UUID(\"0BF5FCEB-9F03-11D1-9DC7-006097C54321\")\n    IDownload : public IUnknown\n    {\n    public:\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE DownloadFile( \n            LPCSTR server,\n            LPCSTR login,\n            LPCSTR password,\n            LPCSTR file,\n            LPCSTR localfile,\n            LPCSTR regkey) = 0;\n        \n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Abort( void) = 0;\n        \n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE PumpMessages( void) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IDownloadVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IDownload __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IDownload __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IDownload __RPC_FAR * This);\n        \n        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DownloadFile )( \n            IDownload __RPC_FAR * This,\n            LPCSTR server,\n            LPCSTR login,\n            LPCSTR password,\n            LPCSTR file,\n            LPCSTR localfile,\n            LPCSTR regkey);\n        \n        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Abort )( \n            IDownload __RPC_FAR * This);\n        \n        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *PumpMessages )( \n            IDownload __RPC_FAR * This);\n        \n        END_INTERFACE\n    } IDownloadVtbl;\n\n    interface IDownload\n    {\n        CONST_VTBL struct IDownloadVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IDownload_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IDownload_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IDownload_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IDownload_DownloadFile(This,server,login,password,file,localfile,regkey)\t\\\n    (This)->lpVtbl -> DownloadFile(This,server,login,password,file,localfile,regkey)\n\n#define IDownload_Abort(This)\t\\\n    (This)->lpVtbl -> Abort(This)\n\n#define IDownload_PumpMessages(This)\t\\\n    (This)->lpVtbl -> PumpMessages(This)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\n/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IDownload_DownloadFile_Proxy( \n    IDownload __RPC_FAR * This,\n    LPCSTR server,\n    LPCSTR login,\n    LPCSTR password,\n    LPCSTR file,\n    LPCSTR localfile,\n    LPCSTR regkey);\n\n\nvoid __RPC_STUB IDownload_DownloadFile_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IDownload_Abort_Proxy( \n    IDownload __RPC_FAR * This);\n\n\nvoid __RPC_STUB IDownload_Abort_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IDownload_PumpMessages_Proxy( \n    IDownload __RPC_FAR * This);\n\n\nvoid __RPC_STUB IDownload_PumpMessages_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IDownload_INTERFACE_DEFINED__ */\n\n\n#ifndef __IDownloadEvent_INTERFACE_DEFINED__\n#define __IDownloadEvent_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IDownloadEvent\n * at Wed Jul 29 16:25:34 1998\n * using MIDL 3.01.75\n ****************************************/\n/* [object][unique][helpstring][uuid] */ \n\n\n\nEXTERN_C const IID IID_IDownloadEvent;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface DECLSPEC_UUID(\"6869E99D-9FB4-11D1-9DC8-006097C54321\")\n    IDownloadEvent : public IUnknown\n    {\n    public:\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE OnEnd( void) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnError( \n            int error) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnProgressUpdate( \n            int bytesread,\n            int totalsize,\n            int timetaken,\n            int timeleft) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnQueryResume( void) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnStatusUpdate( \n            int status) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IDownloadEventVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IDownloadEvent __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IDownloadEvent __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IDownloadEvent __RPC_FAR * This);\n        \n        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnEnd )( \n            IDownloadEvent __RPC_FAR * This);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnError )( \n            IDownloadEvent __RPC_FAR * This,\n            int error);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnProgressUpdate )( \n            IDownloadEvent __RPC_FAR * This,\n            int bytesread,\n            int totalsize,\n            int timetaken,\n            int timeleft);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnQueryResume )( \n            IDownloadEvent __RPC_FAR * This);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnStatusUpdate )( \n            IDownloadEvent __RPC_FAR * This,\n            int status);\n        \n        END_INTERFACE\n    } IDownloadEventVtbl;\n\n    interface IDownloadEvent\n    {\n        CONST_VTBL struct IDownloadEventVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IDownloadEvent_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IDownloadEvent_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IDownloadEvent_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IDownloadEvent_OnEnd(This)\t\\\n    (This)->lpVtbl -> OnEnd(This)\n\n#define IDownloadEvent_OnError(This,error)\t\\\n    (This)->lpVtbl -> OnError(This,error)\n\n#define IDownloadEvent_OnProgressUpdate(This,bytesread,totalsize,timetaken,timeleft)\t\\\n    (This)->lpVtbl -> OnProgressUpdate(This,bytesread,totalsize,timetaken,timeleft)\n\n#define IDownloadEvent_OnQueryResume(This)\t\\\n    (This)->lpVtbl -> OnQueryResume(This)\n\n#define IDownloadEvent_OnStatusUpdate(This,status)\t\\\n    (This)->lpVtbl -> OnStatusUpdate(This,status)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\n/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IDownloadEvent_OnEnd_Proxy( \n    IDownloadEvent __RPC_FAR * This);\n\n\nvoid __RPC_STUB IDownloadEvent_OnEnd_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IDownloadEvent_OnError_Proxy( \n    IDownloadEvent __RPC_FAR * This,\n    int error);\n\n\nvoid __RPC_STUB IDownloadEvent_OnError_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IDownloadEvent_OnProgressUpdate_Proxy( \n    IDownloadEvent __RPC_FAR * This,\n    int bytesread,\n    int totalsize,\n    int timetaken,\n    int timeleft);\n\n\nvoid __RPC_STUB IDownloadEvent_OnProgressUpdate_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IDownloadEvent_OnQueryResume_Proxy( \n    IDownloadEvent __RPC_FAR * This);\n\n\nvoid __RPC_STUB IDownloadEvent_OnQueryResume_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IDownloadEvent_OnStatusUpdate_Proxy( \n    IDownloadEvent __RPC_FAR * This,\n    int status);\n\n\nvoid __RPC_STUB IDownloadEvent_OnStatusUpdate_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IDownloadEvent_INTERFACE_DEFINED__ */\n\n\n#ifndef __INetUtil_INTERFACE_DEFINED__\n#define __INetUtil_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: INetUtil\n * at Wed Jul 29 16:25:34 1998\n * using MIDL 3.01.75\n ****************************************/\n/* [object][unique][helpstring][uuid] */ \n\n\n\nEXTERN_C const IID IID_INetUtil;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface DECLSPEC_UUID(\"B832B0AA-A7D3-11D1-97C3-00609706FA0C\")\n    INetUtil : public IUnknown\n    {\n    public:\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE RequestGameresSend( \n            LPCSTR host,\n            int port,\n            unsigned char __RPC_FAR *data,\n            int length) = 0;\n        \n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE RequestLadderSearch( \n            LPCSTR host,\n            int port,\n            LPCSTR key,\n            unsigned long SKU,\n            int team,\n            int cond,\n            int sort,\n            int number,\n            int leading) = 0;\n        \n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE RequestLadderList( \n            LPCSTR host,\n            int port,\n            LPCSTR keys,\n            unsigned long SKU,\n            int team,\n            int cond,\n            int sort) = 0;\n        \n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE RequestPing( \n            LPCSTR host,\n            int timeout,\n            int __RPC_FAR *handle) = 0;\n        \n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE PumpMessages( void) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetAvgPing( \n            unsigned long ip,\n            int __RPC_FAR *avg) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct INetUtilVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            INetUtil __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            INetUtil __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            INetUtil __RPC_FAR * This);\n        \n        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestGameresSend )( \n            INetUtil __RPC_FAR * This,\n            LPCSTR host,\n            int port,\n            unsigned char __RPC_FAR *data,\n            int length);\n        \n        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestLadderSearch )( \n            INetUtil __RPC_FAR * This,\n            LPCSTR host,\n            int port,\n            LPCSTR key,\n            unsigned long SKU,\n            int team,\n            int cond,\n            int sort,\n            int number,\n            int leading);\n        \n        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestLadderList )( \n            INetUtil __RPC_FAR * This,\n            LPCSTR host,\n            int port,\n            LPCSTR keys,\n            unsigned long SKU,\n            int team,\n            int cond,\n            int sort);\n        \n        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestPing )( \n            INetUtil __RPC_FAR * This,\n            LPCSTR host,\n            int timeout,\n            int __RPC_FAR *handle);\n        \n        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *PumpMessages )( \n            INetUtil __RPC_FAR * This);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetAvgPing )( \n            INetUtil __RPC_FAR * This,\n            unsigned long ip,\n            int __RPC_FAR *avg);\n        \n        END_INTERFACE\n    } INetUtilVtbl;\n\n    interface INetUtil\n    {\n        CONST_VTBL struct INetUtilVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define INetUtil_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define INetUtil_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define INetUtil_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define INetUtil_RequestGameresSend(This,host,port,data,length)\t\\\n    (This)->lpVtbl -> RequestGameresSend(This,host,port,data,length)\n\n#define INetUtil_RequestLadderSearch(This,host,port,key,SKU,team,cond,sort,number,leading)\t\\\n    (This)->lpVtbl -> RequestLadderSearch(This,host,port,key,SKU,team,cond,sort,number,leading)\n\n#define INetUtil_RequestLadderList(This,host,port,keys,SKU,team,cond,sort)\t\\\n    (This)->lpVtbl -> RequestLadderList(This,host,port,keys,SKU,team,cond,sort)\n\n#define INetUtil_RequestPing(This,host,timeout,handle)\t\\\n    (This)->lpVtbl -> RequestPing(This,host,timeout,handle)\n\n#define INetUtil_PumpMessages(This)\t\\\n    (This)->lpVtbl -> PumpMessages(This)\n\n#define INetUtil_GetAvgPing(This,ip,avg)\t\\\n    (This)->lpVtbl -> GetAvgPing(This,ip,avg)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\n/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE INetUtil_RequestGameresSend_Proxy( \n    INetUtil __RPC_FAR * This,\n    LPCSTR host,\n    int port,\n    unsigned char __RPC_FAR *data,\n    int length);\n\n\nvoid __RPC_STUB INetUtil_RequestGameresSend_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE INetUtil_RequestLadderSearch_Proxy( \n    INetUtil __RPC_FAR * This,\n    LPCSTR host,\n    int port,\n    LPCSTR key,\n    unsigned long SKU,\n    int team,\n    int cond,\n    int sort,\n    int number,\n    int leading);\n\n\nvoid __RPC_STUB INetUtil_RequestLadderSearch_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE INetUtil_RequestLadderList_Proxy( \n    INetUtil __RPC_FAR * This,\n    LPCSTR host,\n    int port,\n    LPCSTR keys,\n    unsigned long SKU,\n    int team,\n    int cond,\n    int sort);\n\n\nvoid __RPC_STUB INetUtil_RequestLadderList_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE INetUtil_RequestPing_Proxy( \n    INetUtil __RPC_FAR * This,\n    LPCSTR host,\n    int timeout,\n    int __RPC_FAR *handle);\n\n\nvoid __RPC_STUB INetUtil_RequestPing_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE INetUtil_PumpMessages_Proxy( \n    INetUtil __RPC_FAR * This);\n\n\nvoid __RPC_STUB INetUtil_PumpMessages_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE INetUtil_GetAvgPing_Proxy( \n    INetUtil __RPC_FAR * This,\n    unsigned long ip,\n    int __RPC_FAR *avg);\n\n\nvoid __RPC_STUB INetUtil_GetAvgPing_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __INetUtil_INTERFACE_DEFINED__ */\n\n\n#ifndef __INetUtilEvent_INTERFACE_DEFINED__\n#define __INetUtilEvent_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: INetUtilEvent\n * at Wed Jul 29 16:25:34 1998\n * using MIDL 3.01.75\n ****************************************/\n/* [object][unique][helpstring][uuid] */ \n\n\n\nEXTERN_C const IID IID_INetUtilEvent;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface DECLSPEC_UUID(\"B832B0AC-A7D3-11D1-97C3-00609706FA0C\")\n    INetUtilEvent : public IUnknown\n    {\n    public:\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE OnPing( \n            HRESULT res,\n            int time,\n            unsigned long ip,\n            int handle) = 0;\n        \n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE OnLadderList( \n            HRESULT res,\n            /* [in] */ Ladder __RPC_FAR *list,\n            int totalCount,\n            long timeStamp,\n            int keyRung) = 0;\n        \n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE OnGameresSent( \n            HRESULT res) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct INetUtilEventVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            INetUtilEvent __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            INetUtilEvent __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            INetUtilEvent __RPC_FAR * This);\n        \n        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnPing )( \n            INetUtilEvent __RPC_FAR * This,\n            HRESULT res,\n            int time,\n            unsigned long ip,\n            int handle);\n        \n        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnLadderList )( \n            INetUtilEvent __RPC_FAR * This,\n            HRESULT res,\n            /* [in] */ Ladder __RPC_FAR *list,\n            int totalCount,\n            long timeStamp,\n            int keyRung);\n        \n        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnGameresSent )( \n            INetUtilEvent __RPC_FAR * This,\n            HRESULT res);\n        \n        END_INTERFACE\n    } INetUtilEventVtbl;\n\n    interface INetUtilEvent\n    {\n        CONST_VTBL struct INetUtilEventVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define INetUtilEvent_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define INetUtilEvent_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define INetUtilEvent_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define INetUtilEvent_OnPing(This,res,time,ip,handle)\t\\\n    (This)->lpVtbl -> OnPing(This,res,time,ip,handle)\n\n#define INetUtilEvent_OnLadderList(This,res,list,totalCount,timeStamp,keyRung)\t\\\n    (This)->lpVtbl -> OnLadderList(This,res,list,totalCount,timeStamp,keyRung)\n\n#define INetUtilEvent_OnGameresSent(This,res)\t\\\n    (This)->lpVtbl -> OnGameresSent(This,res)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\n/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE INetUtilEvent_OnPing_Proxy( \n    INetUtilEvent __RPC_FAR * This,\n    HRESULT res,\n    int time,\n    unsigned long ip,\n    int handle);\n\n\nvoid __RPC_STUB INetUtilEvent_OnPing_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE INetUtilEvent_OnLadderList_Proxy( \n    INetUtilEvent __RPC_FAR * This,\n    HRESULT res,\n    /* [in] */ Ladder __RPC_FAR *list,\n    int totalCount,\n    long timeStamp,\n    int keyRung);\n\n\nvoid __RPC_STUB INetUtilEvent_OnLadderList_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE INetUtilEvent_OnGameresSent_Proxy( \n    INetUtilEvent __RPC_FAR * This,\n    HRESULT res);\n\n\nvoid __RPC_STUB INetUtilEvent_OnGameresSent_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __INetUtilEvent_INTERFACE_DEFINED__ */\n\n\n#ifndef __IChat2_INTERFACE_DEFINED__\n#define __IChat2_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IChat2\n * at Wed Jul 29 16:25:34 1998\n * using MIDL 3.01.75\n ****************************************/\n/* [object][unique][helpstring][uuid] */ \n\n\ntypedef unsigned long GID;\n\n\nenum GTYPE_\n    {\tSERVER\t= 0,\n\tCHANNEL\t= 1,\n\tCLIENT\t= 2\n    };\ntypedef enum GTYPE_ GTYPE;\n\n\nenum CHAN_CTYPE_\n    {\tALLEXIT\t= 0,\n\tCREATOREXIT\t= 1,\n\tCLOSEC\t= 2\n    };\ntypedef enum CHAN_CTYPE_ CHAN_CTYPE;\n\n\nEXTERN_C const IID IID_IChat2;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface DECLSPEC_UUID(\"8B938190-EF3F-11D1-9808-00609706FA0C\")\n    IChat2 : public IUnknown\n    {\n    public:\n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PumpMessages( void) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestConnection( \n            Server __RPC_FAR *server,\n            int timeout) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestMessage( \n            GID who,\n            LPCSTR message) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetTypeFromGID( \n            GID id,\n            GTYPE __RPC_FAR *type) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestChannelList( void) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestChannelJoin( \n            LPCSTR name) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestChannelLeave( \n            Channel __RPC_FAR *chan) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestUserList( \n            Channel __RPC_FAR *chan) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestLogout( void) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestChannelCreate( \n            Channel __RPC_FAR *chan) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RequestRawCmd( \n            LPCSTR cmd) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IChat2Vtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IChat2 __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IChat2 __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IChat2 __RPC_FAR * This);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *PumpMessages )( \n            IChat2 __RPC_FAR * This);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestConnection )( \n            IChat2 __RPC_FAR * This,\n            Server __RPC_FAR *server,\n            int timeout);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestMessage )( \n            IChat2 __RPC_FAR * This,\n            GID who,\n            LPCSTR message);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeFromGID )( \n            IChat2 __RPC_FAR * This,\n            GID id,\n            GTYPE __RPC_FAR *type);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestChannelList )( \n            IChat2 __RPC_FAR * This);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestChannelJoin )( \n            IChat2 __RPC_FAR * This,\n            LPCSTR name);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestChannelLeave )( \n            IChat2 __RPC_FAR * This,\n            Channel __RPC_FAR *chan);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestUserList )( \n            IChat2 __RPC_FAR * This,\n            Channel __RPC_FAR *chan);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestLogout )( \n            IChat2 __RPC_FAR * This);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestChannelCreate )( \n            IChat2 __RPC_FAR * This,\n            Channel __RPC_FAR *chan);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestRawCmd )( \n            IChat2 __RPC_FAR * This,\n            LPCSTR cmd);\n        \n        END_INTERFACE\n    } IChat2Vtbl;\n\n    interface IChat2\n    {\n        CONST_VTBL struct IChat2Vtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IChat2_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IChat2_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IChat2_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IChat2_PumpMessages(This)\t\\\n    (This)->lpVtbl -> PumpMessages(This)\n\n#define IChat2_RequestConnection(This,server,timeout)\t\\\n    (This)->lpVtbl -> RequestConnection(This,server,timeout)\n\n#define IChat2_RequestMessage(This,who,message)\t\\\n    (This)->lpVtbl -> RequestMessage(This,who,message)\n\n#define IChat2_GetTypeFromGID(This,id,type)\t\\\n    (This)->lpVtbl -> GetTypeFromGID(This,id,type)\n\n#define IChat2_RequestChannelList(This)\t\\\n    (This)->lpVtbl -> RequestChannelList(This)\n\n#define IChat2_RequestChannelJoin(This,name)\t\\\n    (This)->lpVtbl -> RequestChannelJoin(This,name)\n\n#define IChat2_RequestChannelLeave(This,chan)\t\\\n    (This)->lpVtbl -> RequestChannelLeave(This,chan)\n\n#define IChat2_RequestUserList(This,chan)\t\\\n    (This)->lpVtbl -> RequestUserList(This,chan)\n\n#define IChat2_RequestLogout(This)\t\\\n    (This)->lpVtbl -> RequestLogout(This)\n\n#define IChat2_RequestChannelCreate(This,chan)\t\\\n    (This)->lpVtbl -> RequestChannelCreate(This,chan)\n\n#define IChat2_RequestRawCmd(This,cmd)\t\\\n    (This)->lpVtbl -> RequestRawCmd(This,cmd)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2_PumpMessages_Proxy( \n    IChat2 __RPC_FAR * This);\n\n\nvoid __RPC_STUB IChat2_PumpMessages_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2_RequestConnection_Proxy( \n    IChat2 __RPC_FAR * This,\n    Server __RPC_FAR *server,\n    int timeout);\n\n\nvoid __RPC_STUB IChat2_RequestConnection_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2_RequestMessage_Proxy( \n    IChat2 __RPC_FAR * This,\n    GID who,\n    LPCSTR message);\n\n\nvoid __RPC_STUB IChat2_RequestMessage_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2_GetTypeFromGID_Proxy( \n    IChat2 __RPC_FAR * This,\n    GID id,\n    GTYPE __RPC_FAR *type);\n\n\nvoid __RPC_STUB IChat2_GetTypeFromGID_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2_RequestChannelList_Proxy( \n    IChat2 __RPC_FAR * This);\n\n\nvoid __RPC_STUB IChat2_RequestChannelList_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2_RequestChannelJoin_Proxy( \n    IChat2 __RPC_FAR * This,\n    LPCSTR name);\n\n\nvoid __RPC_STUB IChat2_RequestChannelJoin_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2_RequestChannelLeave_Proxy( \n    IChat2 __RPC_FAR * This,\n    Channel __RPC_FAR *chan);\n\n\nvoid __RPC_STUB IChat2_RequestChannelLeave_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2_RequestUserList_Proxy( \n    IChat2 __RPC_FAR * This,\n    Channel __RPC_FAR *chan);\n\n\nvoid __RPC_STUB IChat2_RequestUserList_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2_RequestLogout_Proxy( \n    IChat2 __RPC_FAR * This);\n\n\nvoid __RPC_STUB IChat2_RequestLogout_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2_RequestChannelCreate_Proxy( \n    IChat2 __RPC_FAR * This,\n    Channel __RPC_FAR *chan);\n\n\nvoid __RPC_STUB IChat2_RequestChannelCreate_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2_RequestRawCmd_Proxy( \n    IChat2 __RPC_FAR * This,\n    LPCSTR cmd);\n\n\nvoid __RPC_STUB IChat2_RequestRawCmd_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IChat2_INTERFACE_DEFINED__ */\n\n\n#ifndef __IChat2Event_INTERFACE_DEFINED__\n#define __IChat2Event_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IChat2Event\n * at Wed Jul 29 16:25:34 1998\n * using MIDL 3.01.75\n ****************************************/\n/* [object][unique][helpstring][uuid] */ \n\n\n\nEXTERN_C const IID IID_IChat2Event;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface DECLSPEC_UUID(\"8B938192-EF3F-11D1-9808-00609706FA0C\")\n    IChat2Event : public IUnknown\n    {\n    public:\n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnNetStatus( \n            HRESULT res) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnMessage( \n            HRESULT res,\n            User __RPC_FAR *user,\n            LPCSTR message) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnChannelList( \n            HRESULT res,\n            Channel __RPC_FAR *list) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnChannelJoin( \n            HRESULT res,\n            Channel __RPC_FAR *chan,\n            User __RPC_FAR *user) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnLogin( \n            HRESULT res) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnUserList( \n            HRESULT res,\n            Channel __RPC_FAR *chan,\n            User __RPC_FAR *users) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnChannelLeave( \n            HRESULT res,\n            Channel __RPC_FAR *chan,\n            User __RPC_FAR *user) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnChannelCreate( \n            HRESULT res,\n            Channel __RPC_FAR *chan) = 0;\n        \n        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OnUnknownLine( \n            HRESULT res,\n            LPCSTR line) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IChat2EventVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IChat2Event __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IChat2Event __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IChat2Event __RPC_FAR * This);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnNetStatus )( \n            IChat2Event __RPC_FAR * This,\n            HRESULT res);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnMessage )( \n            IChat2Event __RPC_FAR * This,\n            HRESULT res,\n            User __RPC_FAR *user,\n            LPCSTR message);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnChannelList )( \n            IChat2Event __RPC_FAR * This,\n            HRESULT res,\n            Channel __RPC_FAR *list);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnChannelJoin )( \n            IChat2Event __RPC_FAR * This,\n            HRESULT res,\n            Channel __RPC_FAR *chan,\n            User __RPC_FAR *user);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnLogin )( \n            IChat2Event __RPC_FAR * This,\n            HRESULT res);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnUserList )( \n            IChat2Event __RPC_FAR * This,\n            HRESULT res,\n            Channel __RPC_FAR *chan,\n            User __RPC_FAR *users);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnChannelLeave )( \n            IChat2Event __RPC_FAR * This,\n            HRESULT res,\n            Channel __RPC_FAR *chan,\n            User __RPC_FAR *user);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnChannelCreate )( \n            IChat2Event __RPC_FAR * This,\n            HRESULT res,\n            Channel __RPC_FAR *chan);\n        \n        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnUnknownLine )( \n            IChat2Event __RPC_FAR * This,\n            HRESULT res,\n            LPCSTR line);\n        \n        END_INTERFACE\n    } IChat2EventVtbl;\n\n    interface IChat2Event\n    {\n        CONST_VTBL struct IChat2EventVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IChat2Event_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IChat2Event_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IChat2Event_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IChat2Event_OnNetStatus(This,res)\t\\\n    (This)->lpVtbl -> OnNetStatus(This,res)\n\n#define IChat2Event_OnMessage(This,res,user,message)\t\\\n    (This)->lpVtbl -> OnMessage(This,res,user,message)\n\n#define IChat2Event_OnChannelList(This,res,list)\t\\\n    (This)->lpVtbl -> OnChannelList(This,res,list)\n\n#define IChat2Event_OnChannelJoin(This,res,chan,user)\t\\\n    (This)->lpVtbl -> OnChannelJoin(This,res,chan,user)\n\n#define IChat2Event_OnLogin(This,res)\t\\\n    (This)->lpVtbl -> OnLogin(This,res)\n\n#define IChat2Event_OnUserList(This,res,chan,users)\t\\\n    (This)->lpVtbl -> OnUserList(This,res,chan,users)\n\n#define IChat2Event_OnChannelLeave(This,res,chan,user)\t\\\n    (This)->lpVtbl -> OnChannelLeave(This,res,chan,user)\n\n#define IChat2Event_OnChannelCreate(This,res,chan)\t\\\n    (This)->lpVtbl -> OnChannelCreate(This,res,chan)\n\n#define IChat2Event_OnUnknownLine(This,res,line)\t\\\n    (This)->lpVtbl -> OnUnknownLine(This,res,line)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2Event_OnNetStatus_Proxy( \n    IChat2Event __RPC_FAR * This,\n    HRESULT res);\n\n\nvoid __RPC_STUB IChat2Event_OnNetStatus_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2Event_OnMessage_Proxy( \n    IChat2Event __RPC_FAR * This,\n    HRESULT res,\n    User __RPC_FAR *user,\n    LPCSTR message);\n\n\nvoid __RPC_STUB IChat2Event_OnMessage_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2Event_OnChannelList_Proxy( \n    IChat2Event __RPC_FAR * This,\n    HRESULT res,\n    Channel __RPC_FAR *list);\n\n\nvoid __RPC_STUB IChat2Event_OnChannelList_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2Event_OnChannelJoin_Proxy( \n    IChat2Event __RPC_FAR * This,\n    HRESULT res,\n    Channel __RPC_FAR *chan,\n    User __RPC_FAR *user);\n\n\nvoid __RPC_STUB IChat2Event_OnChannelJoin_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2Event_OnLogin_Proxy( \n    IChat2Event __RPC_FAR * This,\n    HRESULT res);\n\n\nvoid __RPC_STUB IChat2Event_OnLogin_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2Event_OnUserList_Proxy( \n    IChat2Event __RPC_FAR * This,\n    HRESULT res,\n    Channel __RPC_FAR *chan,\n    User __RPC_FAR *users);\n\n\nvoid __RPC_STUB IChat2Event_OnUserList_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2Event_OnChannelLeave_Proxy( \n    IChat2Event __RPC_FAR * This,\n    HRESULT res,\n    Channel __RPC_FAR *chan,\n    User __RPC_FAR *user);\n\n\nvoid __RPC_STUB IChat2Event_OnChannelLeave_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2Event_OnChannelCreate_Proxy( \n    IChat2Event __RPC_FAR * This,\n    HRESULT res,\n    Channel __RPC_FAR *chan);\n\n\nvoid __RPC_STUB IChat2Event_OnChannelCreate_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [helpstring] */ HRESULT STDMETHODCALLTYPE IChat2Event_OnUnknownLine_Proxy( \n    IChat2Event __RPC_FAR * This,\n    HRESULT res,\n    LPCSTR line);\n\n\nvoid __RPC_STUB IChat2Event_OnUnknownLine_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IChat2Event_INTERFACE_DEFINED__ */\n\n\n\n#ifndef __WOLAPILib_LIBRARY_DEFINED__\n#define __WOLAPILib_LIBRARY_DEFINED__\n\n/****************************************\n * Generated header for library: WOLAPILib\n * at Wed Jul 29 16:25:34 1998\n * using MIDL 3.01.75\n ****************************************/\n/* [helpstring][version][uuid] */ \n\n\n\nEXTERN_C const IID LIBID_WOLAPILib;\n\n#ifdef __cplusplus\nEXTERN_C const CLSID CLSID_RTPatcher;\n\nclass DECLSPEC_UUID(\"925CDEDF-71B9-11D1-B1C5-006097176556\")\nRTPatcher;\n#endif\n\n#ifdef __cplusplus\nEXTERN_C const CLSID CLSID_Chat;\n\nclass DECLSPEC_UUID(\"4DD3BAF5-7579-11D1-B1C6-006097176556\")\nChat;\n#endif\n\n#ifdef __cplusplus\nEXTERN_C const CLSID CLSID_Download;\n\nclass DECLSPEC_UUID(\"BF6EA206-9E55-11D1-9DC6-006097C54321\")\nDownload;\n#endif\n\n#ifdef __cplusplus\nEXTERN_C const CLSID CLSID_NetUtil;\n\nclass DECLSPEC_UUID(\"B832B0AB-A7D3-11D1-97C3-00609706FA0C\")\nNetUtil;\n#endif\n\n#ifdef __cplusplus\nEXTERN_C const CLSID CLSID_Chat2;\n\nclass DECLSPEC_UUID(\"8B938191-EF3F-11D1-9808-00609706FA0C\")\nChat2;\n#endif\n#endif /* __WOLAPILib_LIBRARY_DEFINED__ */\n\n/* Additional Prototypes for ALL interfaces */\n\n/* end of Additional Prototypes */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "CODE/WOLAPI/WOLAPI_I.C",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* this file contains the actual definitions of */\n/* the IIDs and CLSIDs */\n\n/* link this file in with the server and any clients */\n\n\n/* File created by MIDL compiler version 3.01.75 */\n/* at Wed Jul 29 16:25:34 1998\n */\n/* Compiler settings for WOLAPI.idl:\n    Oicf (OptLev=i2), W1, Zp8, env=Win32, ms_ext, c_ext\n    error checks: none\n*/\n//@@MIDL_FILE_HEADING(  )\n#ifdef __cplusplus\nextern \"C\"{\n#endif \n\n\n#ifndef __IID_DEFINED__\n#define __IID_DEFINED__\n\ntypedef struct _IID\n{\n    unsigned long x;\n    unsigned short s1;\n    unsigned short s2;\n    unsigned char  c[8];\n} IID;\n\n#endif // __IID_DEFINED__\n\n#ifndef CLSID_DEFINED\n#define CLSID_DEFINED\ntypedef IID CLSID;\n#endif // CLSID_DEFINED\n\nconst IID IID_IRTPatcher = {0x925CDEDE,0x71B9,0x11D1,{0xB1,0xC5,0x00,0x60,0x97,0x17,0x65,0x56}};\n\n\nconst IID IID_IRTPatcherEvent = {0x925CDEE3,0x71B9,0x11D1,{0xB1,0xC5,0x00,0x60,0x97,0x17,0x65,0x56}};\n\n\nconst IID IID_IChat = {0x4DD3BAF4,0x7579,0x11D1,{0xB1,0xC6,0x00,0x60,0x97,0x17,0x65,0x56}};\n\n\nconst IID IID_IChatEvent = {0x4DD3BAF6,0x7579,0x11D1,{0xB1,0xC6,0x00,0x60,0x97,0x17,0x65,0x56}};\n\n\nconst IID IID_IDownload = {0x0BF5FCEB,0x9F03,0x11D1,{0x9D,0xC7,0x00,0x60,0x97,0xC5,0x43,0x21}};\n\n\nconst IID IID_IDownloadEvent = {0x6869E99D,0x9FB4,0x11D1,{0x9D,0xC8,0x00,0x60,0x97,0xC5,0x43,0x21}};\n\n\nconst IID IID_INetUtil = {0xB832B0AA,0xA7D3,0x11D1,{0x97,0xC3,0x00,0x60,0x97,0x06,0xFA,0x0C}};\n\n\nconst IID IID_INetUtilEvent = {0xB832B0AC,0xA7D3,0x11D1,{0x97,0xC3,0x00,0x60,0x97,0x06,0xFA,0x0C}};\n\n\nconst IID IID_IChat2 = {0x8B938190,0xEF3F,0x11D1,{0x98,0x08,0x00,0x60,0x97,0x06,0xFA,0x0C}};\n\n\nconst IID IID_IChat2Event = {0x8B938192,0xEF3F,0x11D1,{0x98,0x08,0x00,0x60,0x97,0x06,0xFA,0x0C}};\n\n\nconst IID LIBID_WOLAPILib = {0x925CDED1,0x71B9,0x11D1,{0xB1,0xC5,0x00,0x60,0x97,0x17,0x65,0x56}};\n\n\nconst CLSID CLSID_RTPatcher = {0x925CDEDF,0x71B9,0x11D1,{0xB1,0xC5,0x00,0x60,0x97,0x17,0x65,0x56}};\n\n\nconst CLSID CLSID_Chat = {0x4DD3BAF5,0x7579,0x11D1,{0xB1,0xC6,0x00,0x60,0x97,0x17,0x65,0x56}};\n\n\nconst CLSID CLSID_Download = {0xBF6EA206,0x9E55,0x11D1,{0x9D,0xC6,0x00,0x60,0x97,0xC5,0x43,0x21}};\n\n\nconst CLSID CLSID_NetUtil = {0xB832B0AB,0xA7D3,0x11D1,{0x97,0xC3,0x00,0x60,0x97,0x06,0xFA,0x0C}};\n\n\nconst CLSID CLSID_Chat2 = {0x8B938191,0xEF3F,0x11D1,{0x98,0x08,0x00,0x60,0x97,0x06,0xFA,0x0C}};\n\n\n#ifdef __cplusplus\n}\n#endif\n\n"
  },
  {
    "path": "CODE/WOLAPIOB.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifdef WOLAPI_INTEGRATION\n\n//\tWolapiOb.cpp - Implementation of class WolapiObject.\n//\tajw 07/10/98\n\n#include \"WolapiOb.h\"\n#include \"RAWolapi.h\"\n#include \"WolStrng.h\"\n#include \"SEditDlg.h\"\n#include \"ToolTip.h\"\n#include \"Wol_GSup.h\"\n\n#include \"WolDebug.h\"\n\nextern void WOL_PrintMessage( IconListClass& ILTarget, const char* szText, PlayerColorType iColorRemap = PCOLOR_NONE );\nextern void WOL_PrintMessage( IconListClass& ILTarget, const char* szText, RemapControlType* pColorRemap );\nvoid HostNameFromGameChannelName( char* szNameToSet, const char* szChannelName );\n\nbool WOL_Options_Dialog( WolapiObject* pWO, bool bCalledFromGame );\n\nextern bool cancel_current_msgbox;\n\nconst char* Game_Registry_Key();\n\n//***********************************************************************************************\nWolapiObject::WolapiObject() : pChat( NULL ), pDownload( NULL ), pChatSink( NULL ), pDownloadSink( NULL ),\n\t\t\t\t\t\t\t\tdwChatAdvise( 0 ), dwDownloadAdvise( 0 ), pILChat( NULL ), pILUsers( NULL ),\n\t\t\t\t\t\t\t\tCurrentLevel( WOL_LEVEL_TOP ), bChannelOwner( false ), GameTypeInfos( NULL ),\n\t\t\t\t\t\t\t\tnGameTypeInfos( 0 ), bChatShownBefore( false ),\n\t\t\t\t\t\t\t\tpILPlayers( NULL ), pChatSaveList( NULL ), iLobbyReturnAfterGame( -1 ), iLobbyLast( -1 ),\n\t\t\t\t\t\t\t\tbFindEnabled( true ),\n\t\t\t\t\t\t\t\tbPageEnabled( true ),\n\t\t\t\t\t\t\t\tbLangFilter( true ),\n\t\t\t\t\t\t\t\tbAllGamesShown( true ),\n\t\t\t\t\t\t\t\tpGSupDlg( NULL ),\n\t\t\t\t\t\t\t\tpShpDiscon( NULL ),\n\t\t\t\t\t\t\t\tpShpLeave( NULL ),\n\t\t\t\t\t\t\t\tpShpRefresh( NULL ),\n\t\t\t\t\t\t\t\tpShpSquelch( NULL ),\n\t\t\t\t\t\t\t\tpShpBan( NULL ),\n\t\t\t\t\t\t\t\tpShpKick( NULL ),\n\t\t\t\t\t\t\t\tpShpFindpage( NULL ),\n\t\t\t\t\t\t\t\tpShpOptions( NULL ),\n\t\t\t\t\t\t\t\tpShpLadder( NULL ),\n\t\t\t\t\t\t\t\tpShpHelp( NULL ),\n\t\t\t\t\t\t\t\tpShpBtnDiscon( NULL ),\n\t\t\t\t\t\t\t\tpShpBtnLeave( NULL ),\n\t\t\t\t\t\t\t\tpShpBtnRefresh( NULL ),\n\t\t\t\t\t\t\t\tpShpBtnSquelch( NULL ),\n\t\t\t\t\t\t\t\tpShpBtnBan( NULL ),\n\t\t\t\t\t\t\t\tpShpBtnKick( NULL ),\n\t\t\t\t\t\t\t\tpShpBtnFindpage( NULL ),\n\t\t\t\t\t\t\t\tpShpBtnOptions( NULL ),\n\t\t\t\t\t\t\t\tpShpBtnLadder( NULL ),\n\t\t\t\t\t\t\t\tpShpBtnHelp( NULL ),\n\t\t\t\t\t\t\t\tbReturningAfterGame( false ),\n\t\t\t\t\t\t\t\tpTTipDiscon( NULL ),\n\t\t\t\t\t\t\t\tpTTipLeave( NULL ),\n\t\t\t\t\t\t\t\tpTTipRefresh( NULL ),\n\t\t\t\t\t\t\t\tpTTipSquelch( NULL ),\n\t\t\t\t\t\t\t\tpTTipBan( NULL ),\n\t\t\t\t\t\t\t\tpTTipKick( NULL ),\n\t\t\t\t\t\t\t\tpTTipFindpage( NULL ),\n\t\t\t\t\t\t\t\tpTTipOptions( NULL ),\n\t\t\t\t\t\t\t\tpTTipLadder( NULL ),\n\t\t\t\t\t\t\t\tpTTipHelp( NULL ),\n\t\t\t\t\t\t\t\tbMyRecordUpdated( false ),\n\t\t\t\t\t\t\t\tbChannelListTitleUpdated( false ),\n\t\t\t\t\t\t\t\tbInGame( false ),\n\t\t\t\t\t\t\t\tpStaticUsers( NULL ),\n\t\t\t\t\t\t\t\tbPump_In_Call_Back( false ),\n\t\t\t\t\t\t\t\tbFreezeExternalPager( false ),\n\t\t\t\t\t\t\t\tbDoingDisconnectPinging( false ),\n\t\t\t\t\t\t\t\tbSelfDestruct( false ),\n\t\t\t\t\t\t\t\tbEggSounds( true ),\n\t\t\t\t\t\t\t\tbEgg8Player( false ),\n\t\t\t\t\t\t\t\tbShowRankRA( true ),\n\t\t\t\t\t\t\t\tbShowRankUpdated( false )\n{\n\t*szMyName = 0;\n\t*szMyRecord = 0;\n\t*szMyRecordAM = 0;\n\t*szChannelListTitle = 0;\n\t*szChannelNameCurrent = 0;\n\t*szChannelReturnOnGameEnterFail = 0;\n\tdwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT;\n\tdwTimeNextChannelUpdate = 0;\n\t*szLadderServerHost = 0;\n\t*szGameResServerHost1 = 0;\n\t*szGameResServerHost2 = 0;\n\n\tstrcpy( DibIconInfos[ DIBICON_OWNER ].szFile, \"dib_own.bmp\" );\n\tstrcpy( DibIconInfos[ DIBICON_SQUELCH ].szFile, \"dib_sqel.bmp\" );\n\tstrcpy( DibIconInfos[ DIBICON_LATENCY ].szFile, \"latency.bmp\" );\n\tstrcpy( DibIconInfos[ DIBICON_ACCEPT ].szFile, \"dib_acpt.bmp\" );\n\tstrcpy( DibIconInfos[ DIBICON_NOTACCEPT ].szFile, \"dib_acp2.bmp\" );\n\tstrcpy( DibIconInfos[ DIBICON_USER ].szFile, \"dib_user.bmp\" );\n\tstrcpy( DibIconInfos[ DIBICON_PRIVATE ].szFile, \"privgame.bmp\" );\n\tstrcpy( DibIconInfos[ DIBICON_TOURNAMENT ].szFile, \"tourgame.bmp\" );\n\tstrcpy( DibIconInfos[ DIBICON_VOICE ].szFile, \"voice.bmp\" );\n\tfor( int i = 0; i != NUMDIBICONS; i++ )\n\t{\n\t\tDibIconInfos[ i ].hDIB = 0;\n\t\tDibIconInfos[ i ].pDIB = NULL;\n\t}\n\n\t//\tDetermine name of executable of user's web browser.\n\t//\tThis seems to be the \"correct\" way to do this, but it's bloody stupid.\n\t*szWebBrowser = 0;\n\tchar szFile[] = \"\\\\name_unlikely_to_conflict_77.html\";\t//\"\\\\it is really dumb for me to have to create this file.html\";\n\tHANDLE hFile = ::CreateFile( szFile, GENERIC_WRITE, NULL, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );\n\tif( hFile != INVALID_HANDLE_VALUE )\n\t{\n\t\t::CloseHandle( hFile );\n\t\tHINSTANCE hExecutable = ::FindExecutable( szFile, \"\", szWebBrowser );\n//\t\tif( (int)hExecutable <= 32 )\n//\t\t{\n//\t\t\tdebugprint( \"error %i getting browser\\n\", hExecutable );\n//\t\t}\n//\t\telse\n//\t\t\tdebugprint( \"szWebBrowser is %s\\n\", szWebBrowser );\n\t\t::DeleteFile( szFile );\n\t}\n}\n\n//***********************************************************************************************\nWolapiObject::~WolapiObject()\n{\n\tDeleteSavedChat();\n\n\tif( nGameTypeInfos )\n\t{\n\t\t//\tDelete DIBs that were created, and the wol_gametypeinfos themselves\n\t\tfor( unsigned int n = 0; n != nGameTypeInfos; n++ )\n\t\t{\n\t\t\tif( GameTypeInfos[ n ].hDIB )\n\t\t\t{\n\t\t\t\tGlobalUnlock( GameTypeInfos[ n ].hDIB );\t\t//\tRelease pDIB.\n\t\t\t\tDestroyDIB( GameTypeInfos[ n ].hDIB );\t\t\t//\tDestroy mem alloc'ed for dib bits data.\n\t\t\t}\n\t\t}\n\t\tdelete [] GameTypeInfos;\n\t\tGameTypeInfos = NULL;\n\t}\n\n\tfor( int i = 0; i != NUMDIBICONS; i++ )\n\t{\n\t\tif( DibIconInfos[ i ].pDIB )\n\t\t{\n\t\t\tGlobalUnlock( DibIconInfos[ i ].hDIB );\n\t\t\tDestroyDIB( DibIconInfos[ i ].hDIB );\n\t\t}\n\t}\n\n\tif( pChatSink )\n\t\tUnsetupCOMStuff();\n\n\t//\tDelete buttons, etc., shared by dialogs.\n\tdelete pShpBtnDiscon;\n\tdelete pShpBtnLeave;\n\tdelete pShpBtnRefresh;\n\tdelete pShpBtnSquelch;\n\tdelete pShpBtnBan;\n\tdelete pShpBtnKick;\n\tdelete pShpBtnFindpage;\n\tdelete pShpBtnOptions;\n\tdelete pShpBtnLadder;\n\tdelete pShpBtnHelp;\n\t//\tDelete shared tooltips.\n\tdelete pTTipDiscon;\n\tdelete pTTipLeave;\n\tdelete pTTipRefresh;\n\tdelete pTTipSquelch;\n\tdelete pTTipBan;\n\tdelete pTTipKick;\n\tdelete pTTipFindpage;\n\tdelete pTTipOptions;\n\tdelete pTTipLadder;\n\tdelete pTTipHelp;\n}\n\n//***********************************************************************************************\nbool WolapiObject::bSetupCOMStuff()\n{\n//\tdebugprint( \"++++Begin WolapiObject::bSetupCOMStuff\\n\" );\n\n\tHRESULT\thRes;\n\n\t//\tGrab IChat, INetUtil, set up \"sinks\".\n//\tdebugprint( \"CoCreateInstance\\n\" );\n\tCoCreateInstance( CLSID_Chat, NULL, CLSCTX_INPROC_SERVER, IID_IChat, (void**)&pChat );\n\tif( !pChat )\n\t\treturn false;\t\t//\tSevere, essentially fatal.\n\tCoCreateInstance( CLSID_NetUtil, NULL, CLSCTX_INPROC_SERVER, IID_INetUtil, (void**)&pNetUtil );\n\tif( !pNetUtil )\n\t\treturn false;\t\t//\tSevere, essentially fatal.\n\n\t//\tSet up RAChatEventSink.\n\tpChatSink = new RAChatEventSink( this );\n\tpChatSink->AddRef();\n\t//\tSet up RANetUtilEventSink.\n\tpNetUtilSink = new RANetUtilEventSink( this );\n\tpNetUtilSink->AddRef();\n\n\t//\tIf we could use ATL stuff, this would be different. (We'd use AtlAdvise.)\n\n\tIConnectionPoint*\t\t\tpConnectionPoint = NULL;\n\tIConnectionPointContainer*\tpContainer = NULL;\n\t\n\t// Get a connection point from the chat class for the chatsink.\n//\tdebugprint( \"QueryInterface\\n\" );\n\thRes = pChat->QueryInterface( IID_IConnectionPointContainer, (void**)&pContainer );\n\tif( !SUCCEEDED(hRes) )\n\t\treturn false;\t\t//\tSevere, essentially fatal.\n//\tdebugprint( \"FindConnectionPoint\\n\" );\n\thRes = pContainer->FindConnectionPoint( IID_IChatEvent, &pConnectionPoint );\n\tif( !SUCCEEDED(hRes) )\n\t\treturn false;\t\t//\tSevere, essentially fatal.\n\t//\tConnect chat to chatsink.\n//\tdebugprint( \"Advise. pChatSink = %i, pConnectionPoint = %i\\n\", pChatSink, pConnectionPoint );\n\thRes = pConnectionPoint->Advise( (IChatEvent*)pChatSink, &dwChatAdvise );\n\tif( !SUCCEEDED(hRes) )\n\t\treturn false;\t\t//\tSevere, essentially fatal.\n\t\n\tpContainer->Release();\n\tpConnectionPoint->Release();\n\n\tpConnectionPoint = NULL;\n\tpContainer = NULL;\n\t// Get a connection point from the netutil class for the netutilsink.\n//\tdebugprint( \"QueryInterface\\n\" );\n\thRes = pNetUtil->QueryInterface( IID_IConnectionPointContainer, (void**)&pContainer );\n\tif( !SUCCEEDED(hRes) )\n\t\treturn false;\t\t//\tSevere, essentially fatal.\n//\tdebugprint( \"FindConnectionPoint\\n\" );\n\thRes = pContainer->FindConnectionPoint( IID_INetUtilEvent, &pConnectionPoint );\n\tif( !SUCCEEDED(hRes) )\n\t\treturn false;\t\t//\tSevere, essentially fatal.\n\t//\tConnect netutil to netutilsink.\n//\tdebugprint( \"Advise. pChatSink = %i, pConnectionPoint = %i\\n\", pChatSink, pConnectionPoint );\n\thRes = pConnectionPoint->Advise( (INetUtilEvent*)pNetUtilSink, &dwNetUtilAdvise );\n\tif( !SUCCEEDED(hRes) )\n\t\treturn false;\t\t//\tSevere, essentially fatal.\n\n\tpContainer->Release();\n\tpConnectionPoint->Release();\n\n//\tdebugprint( \"++++End WolapiObject::bSetupCOMStuff\\n\" );\n\treturn true;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::UnsetupCOMStuff()\n{\n//\tdebugprint( \"----Begin WolapiObject::UnsetupCOMStuff\\n\" );\n\n\tHRESULT\thRes;\n\n\t//\tIf we could use ATL stuff, this would be different. (We'd use AtlUnadvise.)\n\n\t//\tUnsetup RAChatEventSink and RANetUtilEventSink, release IChat.\n\tIConnectionPoint*\t\t\tpConnectionPoint = NULL;\n\tIConnectionPointContainer*\tpContainer = NULL;\n\n//\tdebugprint( \"QueryInterface\\n\" );\n\thRes = pChat->QueryInterface( IID_IConnectionPointContainer, (void**)&pContainer );\n\t_ASSERTE(SUCCEEDED(hRes));\n//\tdebugprint( \"FindConnectionPoint\\n\" );\n\thRes = pContainer->FindConnectionPoint( IID_IChatEvent, &pConnectionPoint );\n\t_ASSERTE(SUCCEEDED(hRes));\n//\tdebugprint( \"Unadvise: %i\\n\", dwChatAdvise );\n\tpConnectionPoint->Unadvise( dwChatAdvise );\n\n\tpContainer->Release();\n\tpConnectionPoint->Release();\n\n\tpConnectionPoint = NULL;\n\tpContainer = NULL;\n//\tdebugprint( \"QueryInterface\\n\" );\n\thRes = pNetUtil->QueryInterface( IID_IConnectionPointContainer, (void**)&pContainer );\n\t_ASSERTE(SUCCEEDED(hRes));\n//\tdebugprint( \"FindConnectionPoint\\n\" );\n\thRes = pContainer->FindConnectionPoint( IID_INetUtilEvent, &pConnectionPoint );\n\t_ASSERTE(SUCCEEDED(hRes));\n//\tdebugprint( \"Unadvise: %i\\n\", dwNetUtilAdvise );\n\tpConnectionPoint->Unadvise( dwNetUtilAdvise );\n\n\tpContainer->Release();\n\tpConnectionPoint->Release();\n\n//\tdebugprint( \"pChat->Release\\n\" );\n\tpChat->Release();\n\n//\tdebugprint( \"pChatSink->Release\\n\" );\n\tpChatSink->Release();\t//\tThis results in pChatSink deleting itself for us.\n\tpChatSink = NULL;\n\n//\tdebugprint( \"pNetUtil->Release\\n\" );\n\tpNetUtil->Release();\n\n//\tdebugprint( \"pNetUtilSink->Release\\n\" );\n\tpNetUtilSink->Release();\t//\tThis results in pChatSink deleting itself for us.\n\tpNetUtilSink = NULL;\n\n//\tdebugprint( \"----End WolapiObject::UnsetupCOMStuff\\n\" );\n}\n\n//***********************************************************************************************\nvoid WolapiObject::LinkToChatDlg( IconListClass* pILChat, IconListClass* pILChannels, IconListClass* pILUsers, StaticButtonClass* pStaticUsers )\n{\n\t//\tCalled to initialize this before the chat dialog is shown.\n\n\t//\tSet pointers to lists in dialog.\n\tthis->pILChat = pILChat;\n\tthis->pILChannels = pILChannels;\n\tthis->pILUsers = pILUsers;\n\n\tthis->pStaticUsers = pStaticUsers;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::ClearListPtrs()\n{\n\t//\tCalled to clear list pointers when chat or gamesetup dialog goes away, for safety.\n\tpILChat = NULL;\n\tpILChannels = NULL;\n\tpILUsers = NULL;\n\t\n\tpILPlayers = NULL;\n\n\tpStaticUsers = NULL;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::LinkToGameDlg( IconListClass* pILDisc, IconListClass* pILPlayers )\n{\n\t//\tCalled to initialize this before the gamesetup dialog is shown.\n\n\t//\tSet pointers to lists in dialog.\n\tpILChat = pILDisc;\n\tthis->pILPlayers = pILPlayers;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::PrepareButtonsAndIcons()\n{\n\t//\tLoad shapes for buttons. Store images in this order: up, down, disabled.\n\t//pShpDiscon = LoadShpFile( \"discon.shp\" ); etc\n\tpShpDiscon = (char*)MFCD::Retrieve( \"discon.shp\" );\n\tpShpLeave = (char*)MFCD::Retrieve( \"leave.shp\" );\n\tpShpRefresh = (char*)MFCD::Retrieve( \"refresh.shp\" );\n\tpShpSquelch = (char*)MFCD::Retrieve( \"squelch.shp\" );\n\tpShpBan = (char*)MFCD::Retrieve( \"ban.shp\" );\n\tpShpKick = (char*)MFCD::Retrieve( \"kick.shp\" );\n\tpShpFindpage = (char*)MFCD::Retrieve( \"findpage.shp\" );\n\tpShpOptions = (char*)MFCD::Retrieve( \"ops.shp\" );\n\tpShpLadder = (char*)MFCD::Retrieve( \"ladder.shp\" );\n\tpShpHelp = (char*)MFCD::Retrieve( \"help.shp\" );\n\n\t//\tSet up standard wol buttons, used by both main dialogs. Note hardcoded ID values: must match values in dialog.\n\tint iWolButtons_x = 34;\n\tint iWolButtons_y = 20;\n\tint iWolButtons_dx = 53;\n\tint xWolButton = iWolButtons_x;\n\tint xTTip = 10;\t\t\t//\tOffset for tooltip.\n\tint yTTip = - 5;\t\t//\tOffset for tooltip.\n\tpShpBtnDiscon = new ShapeButtonClass( 100, pShpDiscon, xWolButton, iWolButtons_y );\n\tpTTipDiscon = new ToolTipClass( pShpBtnDiscon, TXT_WOL_TTIP_DISCON, xWolButton + xTTip, iWolButtons_y + yTTip );\n\txWolButton += iWolButtons_dx;\n\tpShpBtnLeave = new ShapeButtonClass( 101, pShpLeave, xWolButton, iWolButtons_y );\n\tpTTipLeave = new ToolTipClass( pShpBtnLeave, TXT_WOL_TTIP_LEAVE, xWolButton + xTTip, iWolButtons_y + yTTip );\n\txWolButton += iWolButtons_dx;\n\tpShpBtnRefresh = new ShapeButtonClass( 102, pShpRefresh, xWolButton, iWolButtons_y );\n\tpTTipRefresh = new ToolTipClass( pShpBtnRefresh, TXT_WOL_TTIP_REFRESH, xWolButton + xTTip, iWolButtons_y + yTTip );\n\txWolButton += iWolButtons_dx;\n\tpShpBtnSquelch = new ShapeButtonClass( 103, pShpSquelch, xWolButton, iWolButtons_y );\n\tpTTipSquelch = new ToolTipClass( pShpBtnSquelch, TXT_WOL_TTIP_SQUELCH, xWolButton + xTTip, iWolButtons_y + yTTip );\n\txWolButton += iWolButtons_dx;\n\tpShpBtnBan = new ShapeButtonClass( 104, pShpBan, xWolButton, iWolButtons_y );\n\tpTTipBan = new ToolTipClass( pShpBtnBan, TXT_WOL_TTIP_BAN, xWolButton + xTTip, iWolButtons_y + yTTip );\n\txWolButton += iWolButtons_dx;\n\tpShpBtnKick = new ShapeButtonClass( 105, pShpKick, xWolButton, iWolButtons_y );\n\tpTTipKick = new ToolTipClass( pShpBtnKick, TXT_WOL_TTIP_KICK, xWolButton + xTTip, iWolButtons_y + yTTip );\n\txWolButton += iWolButtons_dx;\n\tpShpBtnFindpage = new ShapeButtonClass( 106, pShpFindpage, xWolButton, iWolButtons_y );\n\tpTTipFindpage = new ToolTipClass( pShpBtnFindpage, TXT_WOL_TTIP_FINDPAGE, xWolButton + xTTip, iWolButtons_y + yTTip );\n\txWolButton = 452;\n\tpShpBtnOptions = new ShapeButtonClass( 107, pShpOptions, xWolButton, iWolButtons_y );\n\tpTTipOptions = new ToolTipClass( pShpBtnOptions, TXT_WOL_TTIP_OPTIONS, xWolButton + xTTip, iWolButtons_y + yTTip, true );\n\txWolButton += iWolButtons_dx;\n\tpShpBtnLadder = new ShapeButtonClass( 108, pShpLadder, xWolButton, iWolButtons_y );\n\tpTTipLadder = new ToolTipClass( pShpBtnLadder, TXT_WOL_TTIP_LADDER, xWolButton + xTTip, iWolButtons_y + yTTip, true );\n\txWolButton += iWolButtons_dx;\n\tpShpBtnHelp = new ShapeButtonClass( 109, pShpHelp, xWolButton, iWolButtons_y );\n\tpTTipHelp = new ToolTipClass( pShpBtnHelp, TXT_WOL_TTIP_HELP, xWolButton + xTTip, iWolButtons_y + yTTip, true );\n\n\t//\tLoad standard hard-coded icons.\n\tHPALETTE hPal = GetCurrentScreenPalette();\n\n\tint iFileLength;\n\tconst char* pFileData;\n\tfor( int iDibIcon = 0; iDibIcon != NUMDIBICONS; iDibIcon++ )\n\t{\n\t\t//pFileData = LoadFileIntoMemory( DibIconInfos[ iDibIcon ].szFile, iFileLength );\n\t\tpFileData = (char*)MFCD::Retrieve( DibIconInfos[ iDibIcon ].szFile );\n\t\tif( pFileData )\n\t\t{\n\t\t\tCCFileClass ccfileDib( DibIconInfos[ iDibIcon ].szFile );\n\t\t\tiFileLength = ccfileDib.Size();\n\t\t\t//debugprint( \"Loaded %s, size is %i.\\n\", DibIconInfos[ iDibIcon ].szFile, iFileLength );\n\t\t\tDibIconInfos[ iDibIcon ].hDIB = LoadDIB_FromMemory( (unsigned char*)pFileData, iFileLength );\n\t\t\tif( DibIconInfos[ iDibIcon ].hDIB )\n\t\t\t{\n\t\t\t\tDibIconInfos[ iDibIcon ].pDIB = (char*)GlobalLock( DibIconInfos[ iDibIcon ].hDIB );\n\t\t\t\tRemapDIBToPalette( hPal, DibIconInfos[ iDibIcon ].pDIB );\n\t\t\t}\n//\t\t\telse\n//\t\t\t\tdebugprint( \"LoadDIB_FromMemory failed!\\n\" );\n\t\t}\n//\t\telse\n//\t\t\tdebugprint( \"Couldn't find %s in mix.\\n\", DibIconInfos[ iDibIcon ].szFile );\n\t}\n\n\tif( DibIconInfos[ DIBICON_LATENCY ].pDIB )\n\t\tfLatencyToIconWidth = (float)DIBWidth( DibIconInfos[ DIBICON_LATENCY ].pDIB ) / 1000;\n\telse\n\t\tfLatencyToIconWidth = 0;\n\n\t//\tAll of the following is for the list of game icons...\n\n\t//\tLoad game icons from the wol api.\n\tLPCSTR szSkus;\n\tif( pChat->GetGametypeList( &szSkus ) == S_OK )\n\t{\n\t\t//\tMake two copies of szSkus because strtok insists on messing with them.\n\t\tchar* szSkus1 = new char[ strlen( szSkus ) + 1 ];\n\t\tchar* szSkus2 = new char[ strlen( szSkus ) + 1 ];\n\t\tstrcpy( szSkus1, szSkus );\n\t\tstrcpy( szSkus2, szSkus );\n\t\t//\tCount commas.\n\t\tchar seps[] = \",\";\n\t\tchar* token;\n\t\tnGameTypeInfos = 0;\n\t\ttoken = strtok( szSkus1, seps );\n\t\twhile( token != NULL )\n\t\t{\n\t\t\tnGameTypeInfos++;\n\t\t\ttoken = strtok( NULL, seps );\n\t\t}\n\t\t//\tThere are actually 2 additional game types available in wolapi - 0 (ws icon) and -1 (wwonline icon).\n\t\tnGameTypeInfos += 2;\n\t\t//\tCreate structs to hold infos.\n//\t\tdebugprint( \"Creating %i gametypeinfos\\n\", nGameTypeInfos );\n\t\tGameTypeInfos = new WOL_GAMETYPEINFO[ nGameTypeInfos ];\n\t\tint iMyIndex = 0;\n\t\ttoken = strtok( szSkus2, seps );\n\t\twhile( token != NULL )\n\t\t{\n\t\t\tGetGameTypeInfo( atoi( token ), GameTypeInfos[ iMyIndex ], hPal );\n\t\t\ttoken = strtok( NULL, seps );\n\t\t\tiMyIndex++;\n\t\t}\n\t\t//\tGet the two extra game type infos...\n\t\tGetGameTypeInfo( -1, GameTypeInfos[ iMyIndex++ ], hPal );\n\t\tGetGameTypeInfo( 0, GameTypeInfos[ iMyIndex++ ], hPal );\n\t}\n//\telse\n//\t\tdebugprint( \"GetGametypeList() failed.\\n\" );\n\n\t//\tLoad icons that we'll need to represent Red Alert GameKinds.\n\t//\tThese are available in wolapi at their old sku number locations.\n\tGetGameTypeInfo( 2, OldRAGameTypeInfos[ 0 ], hPal );\t//\tRA\n\tGetGameTypeInfo( 3, OldRAGameTypeInfos[ 1 ], hPal );\t//\tCS\n\tGetGameTypeInfo( 4, OldRAGameTypeInfos[ 2 ], hPal );\t//\tAM\n\n\tif( hPal )\n\t\tDeleteObject( hPal );\n}\n\n//***********************************************************************************************\nvoid WolapiObject::GetGameTypeInfo( int iGameType, WOL_GAMETYPEINFO& GameTypeInfo, HPALETTE hPal )\n{\n\tunsigned char* pVirtualFile;\n\tint\tiFileLength;\n//\tdebugprint( \"GetGametypeInfo, type %i\\n\", iGameType );\n\tLPCSTR szName;\n\tLPCSTR szURL;\n\tpChat->GetGametypeInfo( iGameType, 12, &pVirtualFile, &iFileLength, &szName, &szURL );\n\tGameTypeInfo.iGameType = iGameType;\n\tif( szName )\n\t\tstrcpy( GameTypeInfo.szName, szName );\n\telse\n\t\t*GameTypeInfo.szName = 0;\n\tif( szURL )\n\t\tstrcpy( GameTypeInfo.szURL, szURL );\n\telse\n\t\t*GameTypeInfo.szURL = 0;\n\n//\tdebugprint( \"LoadDIB_FromMemory( %i, %i )\\n\", pVirtualFile, iFileLength );\n\t//\tCreate a DIB by \"loading\" (as if it was a file) the bitmap data.\n\tGameTypeInfo.hDIB = LoadDIB_FromMemory( pVirtualFile, iFileLength );\n//\tdebugprint( \"hDIB is %i\\n\", GameTypeInfo.hDIB );\n\tif( !GameTypeInfo.hDIB )\n\t{\n\t\tGameTypeInfo.pDIB = NULL;\n\t\treturn;\t\t\t//\tLoad failed. Should not ever happen.\n\t}\n\tGameTypeInfo.pDIB = (const char*)GlobalLock( GameTypeInfo.hDIB );\n\n//\tdebugprint( \"@@@@@ Created gametypeinfo #%i: name %s, pDIB = %i\\n\", iIndex, GameTypeInfo.szName, GameTypeInfo.pDIB );\n\n\tLPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)GameTypeInfo.pDIB;\n\tif( lpbi->biBitCount != 8 )\n\t{\n\t\t//\tDo not use this loaded bmp, as it's not 256 color.\n\t\tGlobalUnlock( GameTypeInfo.hDIB );\t\t//\tRelease pDIB.\n\t\tGameTypeInfo.pDIB = NULL;\n\t\tDestroyDIB( GameTypeInfo.hDIB );\t\t//\tDestroy mem alloc'ed for dib bits data.\n\t\tGameTypeInfo.hDIB = 0;\n\t\treturn;\n\t}\n\n\t//\tRemap colors...\n\tRemapDIBToPalette( hPal, GameTypeInfo.pDIB );\n\n}\n\n//***********************************************************************************************\nvoid* WolapiObject::IconForGameType( int iGameType )\n{\n\t//\tReturns a GameTypeInfos entry by gametype, instead of our (potentially arbitrary) index.\n\t//\tReturns NULL if type not found in list, which will of course never happen...\n\tfor( int i = 0; i != nGameTypeInfos; i++ )\n\t{\n\t\tif( GameTypeInfos[i].iGameType == iGameType )\n\t\t\treturn (void*)GameTypeInfos[i].pDIB;\n\t}\n\treturn NULL;\n}\n\n//***********************************************************************************************\nconst char* WolapiObject::NameOfGameType( int iGameType ) const\n{\n\t//\tReturns the name of a sku by gametype, instead of our (potentially arbitrary) index.\n\t//\tReturns NULL if type not found in list, which will of course never happen...\n\tfor( int i = 0; i != nGameTypeInfos; i++ )\n\t{\n\t\tif( GameTypeInfos[i].iGameType == iGameType )\n\t\t\treturn GameTypeInfos[i].szName;\n\t}\n\treturn NULL;\n}\n\n//***********************************************************************************************\nconst char* WolapiObject::URLForGameType( int iGameType ) const\n{\n\t//\tReturns NULL if type not found in list, which will of course never happen...\n\tfor( int i = 0; i != nGameTypeInfos; i++ )\n\t{\n\t\tif( GameTypeInfos[i].iGameType == iGameType )\n\t\t\treturn GameTypeInfos[i].szURL;\n\t}\n\treturn NULL;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::PrintMessage( const char* szText, PlayerColorType iColorRemap /* = PCOLOR_NONE */ )\n{\n\tif( pILChat )\n\t\tWOL_PrintMessage( *pILChat, szText, iColorRemap );\n}\n\n//***********************************************************************************************\nvoid WolapiObject::PrintMessage( const char* szText, RemapControlType* pColorRemap )\n{\n\tif( pILChat )\n\t\tWOL_PrintMessage( *pILChat, szText, pColorRemap );\n}\n\n//***********************************************************************************************\nHRESULT WolapiObject::GetChatServer()\n{\n\t//\tCalls RequestServerList() to get a chat server ready for us to login to.\n\t//\tReturns S_OK and sets pChatSink->pServer if successful.\n\tWWMessageBox().Process( TXT_WOL_CONNECTING, TXT_NONE );\n\n//if( !( ::GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) )\t\t\t//\tajw - allow use of test servers\n//{\n\n\t//\tRequest chat server address from server server.\n\tpChatSink->bRequestServerListWait = true;\n//\tdebugprint( \"Calling RequestServerList...\\n\" );\n\tif( !SUCCEEDED( pChat->RequestServerList( GAME_SKU, GAME_VERSION, \"unused\", \"unused\", 5 ) ) )\n\t{\n//\t\tdebugprint( \"RequestServerList call failed\\n\" );\n\t\treturn E_FAIL;\n\t}\n\tDWORD dwTimeLimit = timeGetTime();\t\t//\tajw My own extra timeout at one minute, in case wolapi chokes.\n//\tdebugprint( \"Called RequestServerList...\\n\" );\n\tDWORD dwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\t::GetAsyncKeyState( VK_ESCAPE );\t//\tSet up for escape key checking.\n\tbool bCancel = false;\n\thresPatchResults = 0;\n\twhile( pChatSink->bRequestServerListWait && timeGetTime() - dwTimeLimit < 60000 )\n\t{\n\t\twhile( timeGetTime() < dwTimeNextPump )\n\t\t{\n\t\t\tCall_Back();\n\t\t\tif( ::GetAsyncKeyState( VK_ESCAPE ) & 1 )\n\t\t\t{\n\t\t\t\tbCancel = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n//\t\tdebugprint( \"PumpMessages after RequestServerList...\\n\" );\n\t\tpChat->PumpMessages();\n\t\tdwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n//        Sleep( PUMPSLEEPDURATION );\t//\tCan't do because we want to Call_Back()\n\t\t//\tIf an \"update list\" of patches has been received, instead of a server list, this flag will have been set\n\t\t//\tfor us describing the results. We'll either cancel log in or trigger game exit.\n\t\tif( hresPatchResults )\n\t\t{\n\t\t\tpChatSink->bRequestServerListWait = false;\n\t\t\treturn hresPatchResults;\n\t\t}\n\t}\n//\tdebugprint( \"RequestServerList wait finished\\n\" );\n\tif( bCancel )\n\t{\n\t\tKeyboard->Clear();\n\t\treturn USERCANCELLED;\n\t}\n\tif( pChatSink->pServer )\n\t\treturn S_OK;\n\telse\n\t\treturn E_FAIL;\n\n/*\n}\nelse\n{\n\t//\tTest using local server on LAN.\n\n\t//\tBypass RequestServerList, as it is unnecessary and may not be possible if serverserver can't be reached.\n\t//\tSet SKU manually because normally RequestServerList does this for you.\n\tpChat->SetProductSKU( GAME_SKU );\n\tif( pChatSink->pServer )\n\t\tdelete pChatSink->pServer;\n\tpChatSink->pServer = new Server;\n\tif( !( ::GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) )\n\t\tstrcpy( (char*)pChatSink->pServer->conndata, \"TCP;irc.westwood.com;9000\" );\n\telse\n\t\t//\tControl key down as well.\n\t\tstrcpy( (char*)pChatSink->pServer->conndata, \"TCP;10.2.20.28;4000\" );\n\tstrcpy( (char*)pChatSink->pServer->connlabel, \"IRC\" );\n\tstrcpy( (char*)pChatSink->pServer->name, \"Chat\");\n\treturn S_OK;\n}\n*/\n\n}\n\n//***********************************************************************************************\nHRESULT WolapiObject::AttemptLogin( const char* szName, const char* szPass, bool bPassIsMangled )\n{\n\t//\tIf RequestConnection() succeeds, sets pChatSink->bConnected true and returns S_OK.\n\t//\tElse returns RequestConnection() error result.\n\tWWMessageBox().Process( TXT_WOL_ATTEMPTLOGIN, TXT_NONE );\n\n//\tdebugprint( \"~1\\n\" );\n\tstrcpy( (char*)pChatSink->pServer->login, szName );\n\tstrcpy( (char*)pChatSink->pServer->password, szPass );\n\n/*\n//\tdebugprint( \"RequestConnection with:\\n%s,%s,%s,%s,%s - %s\\n\",\n\t\t\t\t\tpChatSink->pServer->name,\n\t\t\t\t\tpChatSink->pServer->connlabel,\n\t\t\t\t\tpChatSink->pServer->conndata,\n\t\t\t\t\tpChatSink->pServer->login,\n\t\t\t\t\tpChatSink->pServer->password,\n\t\t\t\t\tbPassIsMangled ? \"(mangled)\" : \"(unmangled)\" );\n*/\n\tpChatSink->bRequestConnectionWait = true;\n\tpChatSink->hresRequestConnectionError = 0;\n\n\tif( !SUCCEEDED( pChat->RequestConnection( pChatSink->pServer, 15, !bPassIsMangled ) ) )\n\t{\n//\t\tdebugprint( \"RequestConnection call failed\\n\" );\n\t\treturn CHAT_E_CON_ERROR;\n\t}\n\n\tDWORD dwTimeStart = timeGetTime();\n\tDWORD dwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\t::GetAsyncKeyState( VK_ESCAPE );\t//\tSet up for escape key checking.\n\tbool bCancel = false;\n\twhile( pChatSink->bRequestConnectionWait && timeGetTime() - dwTimeStart < EMERGENCY_TIMEOUT )\n\t{\n\t\twhile( timeGetTime() < dwTimeNextPump )\n\t\t{\n\t\t\tCall_Back();\n\t\t\tif( ::GetAsyncKeyState( VK_ESCAPE ) & 1 )\n\t\t\t{\n\t\t\t\tbCancel = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif( bCancel )\n\t\t\tbreak;\n\t\tpChat->PumpMessages();\n\t\tdwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n//        Sleep( PUMPSLEEPDURATION );\t//\tCan't do because we want to Call_Back()\n\t}\n\tif( bCancel )\n\t{\n\t\tKeyboard->Clear();\n\t\treturn USERCANCELLED;\n\t}\n\tif( pChatSink->bRequestConnectionWait )\n\t\treturn CHAT_E_CON_ERROR;\n\n\tif( pChatSink->bConnected )\n\t{\n\t\tstrcpy( szMyName, szName );\n\t\tstrcpy( szMyRecord, szName );\n\t\tstrcpy( szMyRecordAM, szName );\n\t\treturn S_OK;\n\t}\n\telse\n\t\treturn pChatSink->hresRequestConnectionError;\n}\n\n//***********************************************************************************************\nbool WolapiObject::bLoggedIn()\n{\n\treturn pChatSink->bConnected;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::Logout()\n{\n\t//\tRequests logout from wolapi. Doesn't return any error values, as what we would do if it\n\t//\tfailed - force the user to stay connected?\n\n\tif( bSelfDestruct )\n\t\tWWMessageBox().Process( TXT_WOL_ERRORLOGOUT, TXT_NONE );\n\telse\n\t\tWWMessageBox().Process( TXT_WOL_ATTEMPTLOGOUT, TXT_NONE );\n\n//\tdebugprint( \"RequestLogout()\\n\" );\n\n\tpChatSink->bRequestLogoutWait = true;\n\n\tif( !SUCCEEDED( pChat->RequestLogout() ) )\n\t{\n//\t\tdebugprint( \"RequestLogout() call failed\\n\" );\n\t}\n\n\tDWORD dwTimePatience = timeGetTime();\t\t//\tAfter 5 seconds we run out of patience and bail.\n\tDWORD dwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\twhile( pChatSink->bRequestLogoutWait && timeGetTime() - dwTimePatience < 5000 )\n\t{\n\t\twhile( timeGetTime() < dwTimeNextPump )\n\t\t\tCall_Back();\n\t\tpChat->PumpMessages();\n\t\tdwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\t}\n\n\tpChatSink->bConnected = false;\n\t*szMyName = 0;\n\n\tSound_Effect( WOLSOUND_LOGOUT );\n}\n\n//***********************************************************************************************\nbool WolapiObject::UpdateChannels( int iChannelType, CHANNELFILTER ChannelFilter, bool bAutoping )\n{\n\t//\tThis is now non-modal.\n\t//\tSends off a request for a new channels list.\n\n//\t//\tReturns false upon total failure.\n//\tWWMessageBox().Process( TXT_WOL_WAIT, TXT_NONE );\n\n//\tpChatSink->bRequestChannelListWait = true;\n\tpChatSink->ChannelFilter = ChannelFilter;\n\n//\tdebugprint( \"RequestChannelList(), iChannelType = %i, filter = %i\\n\", iChannelType, ChannelFilter );\n\tif( !SUCCEEDED( pChat->RequestChannelList( iChannelType, bAutoping ) ) )\n\t{\n//\t\tdebugprint( \"RequestChannelList() call failed\\n\" );\n\t\treturn false;\n\t}\n/*\n\tDWORD dwTimeStart = timeGetTime();\n\tDWORD dwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\twhile( pChatSink->bRequestChannelListWait && timeGetTime() - dwTimeStart < EMERGENCY_TIMEOUT )\n\t{\n\t\twhile( timeGetTime() < dwTimeNextPump )\n\t\t\tCall_Back();\n\t\tpChat->PumpMessages();\n\t\tdwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\t}\n\n\tif( pChatSink->bRequestChannelListWait )\n\t\treturn false;\n*/\n\tLastUpdateChannelCallLevel = CurrentLevel;\n\n\treturn true;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::OnChannelList()\n{\n\t//\tThe chatsink calls this when its OnChannelList() is called, and it has remade its internal channel list.\n\t//\tThe question here is: should we display the values now in the chatsink?\n\t//\tAs UpdateChannels() is now non-modal, there is the danger that we have moved away from the place in\n\t//\tthe channel heirarchy where we originally called RequestChannelList().\n\t//\tTo help ensure we're getting this where we expect to get it, we check the value of CurrentLevel against\n\t//\twhat it was when we called UpdateChannels().\n\tif( CurrentLevel == LastUpdateChannelCallLevel )\n\t\tListChannels();\n}\n\n//***********************************************************************************************\nvoid WolapiObject::ListChannels()\n{\n\t//\tShow pChatSink's pChannelList in pILChannels.\n\t//\tThe extra data ptr hidden in each list item will hold a void pointer to the channel described.\n//\tdebugprint( \"ListChannels(), pChannelList = %i\\n\", pChatSink->pChannelList );\n\n\tstatic WOL_LEVEL\tLevelLastListed = WOL_LEVEL_INVALID;\n\n\tint iListViewIndex = 0;\n\n\t//\tIf redrawing the same list as before, preserve the view position.\n\tif( LevelLastListed == CurrentLevel )\n\t\tiListViewIndex = pILChannels->Get_View_Index();\n\telse\n\t\tLevelLastListed = CurrentLevel;\n\n\tpILChannels->Clear();\n\tswitch( CurrentLevel )\n\t{\n\tcase WOL_LEVEL_GAMESOFTYPE:\n\t\tpILChannels->Add_Item( TXT_WOL_CHANNEL_BACK, CHANNELTYPE_GAMES, NULL, ICON_SHAPE, CHANNELTYPE_GAMES );\n\t\tbreak;\n\tcase WOL_LEVEL_LOBBIES:\n\t\tpILChannels->Add_Item( TXT_WOL_CHANNEL_BACK, CHANNELTYPE_GAMES, NULL, ICON_SHAPE, CHANNELTYPE_GAMES );\n\t\tbreak;\n\tcase WOL_LEVEL_INLOBBY:\n\t\tpILChannels->Add_Item( TXT_WOL_CHANNEL_BACK, CHANNELTYPE_LOBBIES, NULL, ICON_SHAPE, CHANNELTYPE_LOBBIES );\n\t\tbreak;\n\tdefault:\n\t\tpILChannels->Add_Item( TXT_WOL_CHANNEL_TOP, CHANNELTYPE_TOP, NULL, ICON_SHAPE, CHANNELTYPE_TOP );\n\t\tbreak;\n\t}\n\n\tChannel* pChannel = pChatSink->pChannelList;\n\twhile( pChannel )\n\t{\n\t\tif( pChannel->type == 0 )\n\t\t{\n\t\t\t//\tShow chat channel.\n\t\t\tchar* pShow;\n\t\t\tint iLobby = iChannelLobbyNumber( pChannel->name );\n\t\t\tif( iLobby == - 1 )\n\t\t\t{\n\t\t\t\t//\tRegular chat channel.\n\t\t\t\tpShow = new char[ strlen( (char*)pChannel->name ) + 10 ];\n\t\t\t\tsprintf( pShow, \"%s\\t%-3u\", (char*)pChannel->name, pChannel->currentUsers );\n\t\t\t\tchar szHelp[ 200 ];\n\t\t\t\tsprintf( szHelp, TXT_WOL_TTIP_CHANLIST_CHAT, (char*)pChannel->name, pChannel->currentUsers );\n\t\t\t\tpILChannels->Add_Item( pShow, szHelp, (void*)DibIconInfos[ DIBICON_USER ].pDIB, ICON_DIB, CHANNELTYPE_CHATCHANNEL, (void*)pChannel );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//\tChannel is a lobby.\n\t\t\t\tchar szLobbyName[ REASONABLELOBBYINTERPRETEDNAMELEN ];\n\t\t\t\tInterpretLobbyNumber( szLobbyName, iLobby );\n\t\t\t\tpShow = new char[ REASONABLELOBBYINTERPRETEDNAMELEN + 10 ];\n\t\t\t\tsprintf( pShow, \"%s\\t%-3u\", szLobbyName, pChannel->currentUsers );\n\t\t\t\tchar szHelp[ 200 ];\n\t\t\t\tsprintf( szHelp, TXT_WOL_TTIP_CHANLIST_LOBBY, szLobbyName, pChannel->currentUsers );\n\t\t\t\tpILChannels->Add_Item( pShow, szHelp, IconForGameType( -1 ), ICON_DIB, CHANNELTYPE_LOBBYCHANNEL, (void*)pChannel );\n//\t\t\t\tdebugprint( \":::::added pChannel %i, name %s, as %s\\n\", pChannel, pChannel->name, pShow );\n\t\t\t}\n\t\t\tdelete [] pShow;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//\tShow game channel.\n\t\t\tchar* pShow = new char[ strlen( (char*)pChannel->name ) + 10 ];\n\t\t\tchar szHelp[ 200 ];\n\t\t\tvoid* pGameKindIcon;\n\t\t\tif( pChannel->type == GAME_TYPE )\n\t\t\t{\n\t\t\t\t//\tGet RedAlert GameKind.\n\t\t\t\tCREATEGAMEINFO::GAMEKIND GameKind = (CREATEGAMEINFO::GAMEKIND)( pChannel->reserved & 0xFF000000 );\n\t\t\t\tswitch( GameKind )\n\t\t\t\t{\n\t\t\t\tcase CREATEGAMEINFO::RAGAME:\n\t\t\t\t\tpGameKindIcon = (void*)OldRAGameTypeInfos[ 0 ].pDIB;\t\t//\tRed Alert icon\n\t\t\t\t\tsprintf( szHelp, TXT_WOL_TTIP_CHANLIST_RAGAME, TXT_WOL_TTIP_REDALERT, \n\t\t\t\t\t\t\t\tpChannel->currentUsers, pChannel->maxUsers );\n\t\t\t\t\tbreak;\n\t\t\t\tcase CREATEGAMEINFO::CSGAME:\n\t\t\t\t\tpGameKindIcon = (void*)OldRAGameTypeInfos[ 1 ].pDIB;\t\t//\tCS icon\n\t\t\t\t\tsprintf( szHelp, TXT_WOL_TTIP_CHANLIST_RAGAME, TXT_WOL_TTIP_COUNTERSTRIKE, \n\t\t\t\t\t\t\t\tpChannel->currentUsers, pChannel->maxUsers );\n\t\t\t\t\tbreak;\n\t\t\t\tcase CREATEGAMEINFO::AMGAME:\n\t\t\t\t\tpGameKindIcon = (void*)OldRAGameTypeInfos[ 2 ].pDIB;\t\t//\tAM icon\n\t\t\t\t\tsprintf( szHelp, TXT_WOL_TTIP_CHANLIST_RAGAME, TXT_WOL_TTIP_AFTERMATH, \n\t\t\t\t\t\t\t\tpChannel->currentUsers, pChannel->maxUsers );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n//\t\t\t\t\tdebugprint( \"Illegal value for GameKind channel reserved field: %s\\n\", (char*)pChannel->name );\n\t\t\t\t\tpGameKindIcon = NULL;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tsprintf( pShow, \"%s\\t%u/%u\", (char*)pChannel->name, pChannel->currentUsers, pChannel->maxUsers );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tpGameKindIcon = IconForGameType( pChannel->type );\n\t\t\t\tsprintf( pShow, \"%s\\t%-2u\", (char*)pChannel->name, pChannel->currentUsers );\n\t\t\t\tsprintf( szHelp, TXT_WOL_TTIP_CHANLIST_GAME, NameOfGameType( pChannel->type ), \n\t\t\t\t\t\t\tpChannel->currentUsers );\n\t\t\t}\n\t\t\tvoid* pPrivateIcon = NULL;\n\t\t\tif( pChannel->flags & CHAN_MODE_KEY )\n\t\t\t{\n\t\t\t\t//\tGame is private.\n\t\t\t\tpPrivateIcon = (void*)DibIconInfos[ DIBICON_PRIVATE ].pDIB;\n\t\t\t\tstrcat( szHelp, TXT_WOL_TTIP_PRIVATEGAME );\n\t\t\t}\n\n\t\t\tvoid* pTournamentIcon = NULL;\n\t\t\tif( pChannel->tournament )\n\t\t\t{\n\t\t\t\t//\tGame is tournament.\n\t\t\t\tpTournamentIcon = (void*)DibIconInfos[ DIBICON_TOURNAMENT ].pDIB;\n\t\t\t\tstrcat( szHelp, TXT_WOL_TTIP_TOURNAMENTGAME );\n\t\t\t}\n\n\t\t\tint iLatencyUse = pChannel->latency;\n\t\t\tif( iLatencyUse == -1 )\n\t\t\t\tiLatencyUse = 0;\n\n\t\t\tstatic int iLatencyBarX = 227 - DIBWidth( DibIconInfos[ DIBICON_LATENCY ].pDIB ) - 19;\n\n\t\t\tpILChannels->Add_Item( pShow, szHelp, pGameKindIcon, ICON_DIB,\n\t\t\t\t\t\t\t\t\tCHANNELTYPE_GAMECHANNEL, (void*)pChannel, NULL,\n\t\t\t\t\t\t\t\t\tpPrivateIcon, ICON_DIB, pTournamentIcon, ICON_DIB,\n\t\t\t\t\t\t\t\t\t(void*)DibIconInfos[ DIBICON_LATENCY ].pDIB, ICON_DIB, \n\t\t\t\t\t\t\t\t\tiLatencyBarX, 0, iLatencyUse * fLatencyToIconWidth );\n\t\t\tdelete [] pShow;\n\t\t}\n\t\tpChannel = pChannel->next;\n\t}\n\tif( iListViewIndex )\n\t\tpILChannels->Set_View_Index( iListViewIndex );\t//\tNot perfect but should keep list pretty stable on updates.\n}\n\n//***********************************************************************************************\nHRESULT WolapiObject::ChannelJoin( const char* szChannelName, const char* szKey )\n{\n\t//\tUsed for CHAT channels (or lobbies) only. Channel type is set to 0.\n\tChannel ChannelTemp;\n\tmemset( &ChannelTemp, 0, sizeof( ChannelTemp ) );\n\tstrcpy( (char*)ChannelTemp.name, szChannelName );\n\tstrcpy( (char*)ChannelTemp.key, szKey );\n\treturn ChannelJoin( &ChannelTemp );\n}\n\n//***********************************************************************************************\nHRESULT WolapiObject::ChannelJoin( Channel* pChannelToJoin )\n{\n\t//\tReturns an HRESULT, the meaning of which is totally customized for my own uses.\n\n\tWWMessageBox().Process( TXT_WOL_WAIT, TXT_NONE );\n\n\tpChatSink->bRequestChannelJoinWait = true;\n\tpChatSink->hresRequestJoinResult = 0;\n\n//\tdebugprint( \"RequestChannelJoin(), %s\\n\", pChannelToJoin->name );\n\tHRESULT hRes = pChat->RequestChannelJoin( pChannelToJoin );\n\tif( !SUCCEEDED( hRes ) )\n\t{\n//\t\tdebugprint( \"RequestChannelJoin() call failed, result %i \", hRes );\n\t\tDebugChatDef( hRes );\n\t\treturn E_FAIL;\n\t}\n\tpChatSink->bIgnoreChannelLists = true;\t\t//\tTurn off response to channel lists.\n\tDWORD dwTimeStart = timeGetTime();\n\tDWORD dwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\twhile( pChatSink->bRequestChannelJoinWait && timeGetTime() - dwTimeStart < EMERGENCY_TIMEOUT )\n\t{\n\t\twhile( timeGetTime() < dwTimeNextPump )\n\t\t\tCall_Back();\n\t\tpChat->PumpMessages();\n\t\tdwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\t}\n\tpChatSink->bIgnoreChannelLists = false;\t\t//\tTurn on response to channel lists.\n\n\tif( pChatSink->bRequestChannelJoinWait )\n\t\treturn CHAT_E_TIMEOUT;\n\n\tswitch( pChatSink->hresRequestJoinResult )\n\t{\n\tcase CHAT_E_CHANNELDOESNOTEXIST:\n\tcase CHAT_E_BADCHANNELPASSWORD:\n\tcase CHAT_E_BANNED:\n\tcase CHAT_E_CHANNELFULL:\n\t\treturn pChatSink->hresRequestJoinResult;\n\t}\n\n\tif( !pChatSink->bJoined )\n\t\treturn E_FAIL;\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nbool WolapiObject::ChannelLeave()\n{\n\t//\tReturns false upon total failure.\n\tWWMessageBox().Process( TXT_WOL_WAIT, TXT_NONE );\n\n\tpChatSink->bRequestChannelLeaveWait = true;\n\tpChatSink->DeleteUserList();\n\t\n//\tdebugprint( \"RequestChannelLeave()\\n\" );\n\tif( !SUCCEEDED( pChat->RequestChannelLeave() ) )\n\t{\n//\t\tdebugprint( \"RequestChannelLeave() call failed\\n\" );\n\t\treturn false;\n\t}\n\tpChatSink->bIgnoreChannelLists = true;\t\t//\tTurn off response to channel lists.\n\tDWORD dwTimeStart = timeGetTime();\n\tDWORD dwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\twhile( pChatSink->bRequestChannelLeaveWait && timeGetTime() - dwTimeStart < EMERGENCY_TIMEOUT )\n\t{\n\t\twhile( timeGetTime() < dwTimeNextPump )\n\t\t\tCall_Back();\n\t\tpChat->PumpMessages();\n\t\tdwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\t}\n\tpChatSink->bIgnoreChannelLists = false;\n\n\tif( pChatSink->bRequestChannelLeaveWait || pChatSink->bJoined )\n\t\treturn false;\n\n\treturn true;\n}\n\n/*\n//***********************************************************************************************\nbool WolapiObject::UserList()\n{\n\t//\tReturns false upon total failure.\n\tWWMessageBox().Process( TXT_WOL_WAIT, TXT_NONE );\n\n\tpChatSink->bRequestUserListWait = true;\n\n\t//\tI no longer request a user list, as this was being done only when entering a channel, and it turns out wolapi gives\n\t//\tus a user list automatically when joining. This function is used as a blocker that waits until the user list has\n\t//\tdefinitely arrived.\n//\tdebugprint( \"RequestUserList()\\n\" );\n//\tif( !SUCCEEDED( pChat->RequestUserList() ) )\n//\t{\n//\t\tdebugprint( \"RequestUserList() call failed\\n\" );\n//\t\treturn false;\n//\t}\n\n\tDWORD dwTimeStart = timeGetTime();\n\tDWORD dwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\twhile( pChatSink->bRequestUserListWait && timeGetTime() - dwTimeStart < EMERGENCY_TIMEOUT )\n\t{\n\t\twhile( timeGetTime() < dwTimeNextPump )\n\t\t\tCall_Back();\n\t\tpChat->PumpMessages();\n\t\tdwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\t}\n\n\tif( pChatSink->bRequestUserListWait )\n\t{\n\t\tpChatSink->bRequestUserListWait = false;\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n*/\n\n//***********************************************************************************************\n//typedef char CHANNELUSERNAME[ WOL_NAME_LEN_MAX ];\nstruct CHANNELUSERINFO\n{\n\tchar\t\t\t\tszName[ WOL_NAME_LEN_MAX ];\n\tbool\t\t\t\tbFlagged;\n\tRemapControlType*\tpColorRemap;\n\tHousesType\t\t\tHouse;\t\t\t//\tOnly used if game channel.\n\tbool\t\t\t\tbAccept;\t\t//\tOnly used if game channel.\n\tchar\t\t\t\tszExtra[ 50 ];\t//\tOnly used if game channel.\n};\n\n//***********************************************************************************************\nbool WolapiObject::ListChannelUsers()\n{\n\t//\tShow pChatSink's pUserList in pILUsers or pILPlayers (depending on CurrentLevel), after clearing it.\n\t//\tThe extra data ptr hidden in each list item will hold a void pointer to the user described.\n\t//\tFor simplicity, I destroy the old list and write a new one, even though possibly only one item\n\t//\tmay have changed.\n\t//\tIn order for the multiselect flags in the list to persist, I record the names that are flagged\n\t//\tbefore clearing the list, then reset them (if found) in the new list.\n\t//\tThis is inefficient, but should be fine in this non-time-critical situation.\n\t//\t(I also save item color here, and save all items. Now it's really inefficient.)\n\t//\t(Oh, boy. Now I've added the persistence of house info when this is a game channel...)\n\t//\tThe idea was to avoid duplication of player data, and not have any dependence on the integrity of the chatsink's\n\t//\tplayers list. Now it is a case of it working \"well enough\" to not require time to elegantize it.\n\n\t//\tExtra bonus, if useful: returns true if an operator (channel owner) is found in the channel, false otherwise.\n\n\tbool bChannelOwnerFound = false;\n\n\tbool bInLobby;\n\tIconListClass* pListToUse;\n\tif( CurrentLevel == WOL_LEVEL_INGAMECHANNEL )\n\t{\n\t\tbInLobby = false;\n\t\tpListToUse = pILPlayers;\n\t}\n\telse\n\t{\n\t\tbInLobby = ( iChannelLobbyNumber( (unsigned char*)szChannelNameCurrent ) != -1 );\n\t\tpListToUse = pILUsers;\n\t}\n\n\tif( pListToUse &&\t\t\t\t//\tFails in rare cases when list draw is triggered before it is fully set up.\n\t\t*szChannelNameCurrent )\t\t//\tNo users to list if not in a channel.\n\t{\n\t\t//\tIf redrawing the same list as before, preserve the view position.\n\t\tstatic char szChannelLastListed[ WOL_CHANNAME_LEN_MAX ] = { 0 };\n//debugprint( \"szChannelLastListed '%s', szChannelNameCurrent '%s'\\n\", szChannelLastListed, szChannelNameCurrent );\n\t\tint iListViewIndex = 0;\n\t\tif( strcmp( szChannelLastListed, szChannelNameCurrent ) == 0 )\n\t\t\tiListViewIndex = pListToUse->Get_View_Index();\n\t\telse\n\t\t\tstrcpy( szChannelLastListed, szChannelNameCurrent );\n\n//debugprint( \"ListChannelUsers(), pUserList = %i\\n\", pChatSink->pUserList );\n\t\t//\tSave users in current list.\n\t\tint iCount = pListToUse->Count();\n\t\tCHANNELUSERINFO* pUsersSaved = NULL;\n\t\tint iUsersSaved = 0;\n\t\tif( iCount )\n\t\t{\n\t\t\tpUsersSaved = new CHANNELUSERINFO[ iCount ];\n\t\t\tfor( int i = 0; i != iCount; i++ )\n\t\t\t{\n\t\t\t\tPullPlayerName_Into_From( pUsersSaved[ iUsersSaved ].szName, pListToUse->Get_Item( i ) );\n\t\t\t\tpUsersSaved[ iUsersSaved ].bFlagged = pListToUse->bItemIsMultiSelected( i );\n\t\t\t\tpUsersSaved[ iUsersSaved ].pColorRemap = pListToUse->Get_Item_Color( i );\n//\t\t\t\tdebugprint( \"  Saving color of %s as %i.\\n\", pUsersSaved[ iUsersSaved ].szName, pUsersSaved[ iUsersSaved ].pColorRemap );\n\t\t\t\tif( CurrentLevel == WOL_LEVEL_INGAMECHANNEL )\n\t\t\t\t{\n\t\t\t\t\tpUsersSaved[ iUsersSaved ].House = PullPlayerHouse_From( pListToUse->Get_Item( i ) );\n\t\t\t\t\tpUsersSaved[ iUsersSaved ].bAccept = bItemMarkedAccepted( i );\n\t\t\t\t\tconst char* szExtra = pListToUse->Get_Item_ExtraDataString( i );\n\t\t\t\t\tif( szExtra )\n\t\t\t\t\t\tstrcpy( pUsersSaved[ iUsersSaved ].szExtra, szExtra );\n\t\t\t\t\telse\n\t\t\t\t\t\t*pUsersSaved[ iUsersSaved ].szExtra = 0;\n\t\t\t\t}\n\t\t\t\tiUsersSaved++;\n\t\t\t}\n\t\t}\n\t\t//\tClear list and recreate with new users list.\n\t\tpListToUse->Clear();\n\t\tUser* pUser = pChatSink->pUserList;\n\t\tint iUserCount = 0;\n\t\twhile( pUser )\n\t\t{\n\t\t\t++iUserCount;\n\t\t\tvoid* pIcon1 = NULL;\n\t\t\tvoid* pIcon2 = NULL;\n\t\t\tif( pUser->flags & CHAT_USER_CHANNELOWNER )\n\t\t\t{\n\t\t\t\tpIcon1 = (void*)DibIconInfos[ DIBICON_OWNER ].pDIB;\n\t\t\t\tbChannelOwnerFound = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif( CurrentLevel == WOL_LEVEL_INGAMECHANNEL )\t\t\t\t\n\t\t\t\t\tpIcon1 = (void*)DibIconInfos[ DIBICON_NOTACCEPT ].pDIB;\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif( pUser->flags & CHAT_USER_VOICE )\n\t\t\t\t\t\tpIcon1 = (void*)DibIconInfos[ DIBICON_VOICE ].pDIB;\n\t\t\t\t\telse\n\t\t\t\t\t\tpIcon1 = (void*)DibIconInfos[ DIBICON_USER ].pDIB;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif( pUser->flags & CHAT_USER_SQUELCHED )\n\t\t\t\tpIcon2 = (void*)DibIconInfos[ DIBICON_SQUELCH ].pDIB;\n\n\t\t\tif( CurrentLevel == WOL_LEVEL_INGAMECHANNEL || bInLobby )\n\t\t\t{\t\t\t\t\n\t\t\t\tint iRank = pNetUtilSink->GetUserRank( (char*)pUser->name, bShowRankRA );\n\t\t\t\tchar szNameToShow[ WOL_NAME_LEN_MAX + 40 ];\n\t\t\t\tif( iRank )\n\t\t\t\t{\n//\t\t\t\t\tdebugprint(\"  Found %s has rank %u\\n\", (char*)pUser->name, iRank );\n\t\t\t\t\tsprintf( szNameToShow, TXT_WOL_USERRANK, (char*)pUser->name, iRank );\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tstrcpy( szNameToShow, (char*)pUser->name );\n\n\t\t\t\tstatic int iLatencyBarX = 124*RESFACTOR - DIBWidth( DibIconInfos[ DIBICON_LATENCY ].pDIB ) - 5 - 16;\n\n\t\t\t\t//\tIf we have had a chance to request pings to the player, there'll be some avg. results waiting for us.\n\t\t\t\tint iLatencyBarWidth = 0;\n\t\t\t\tint iLatency;\n\t\t\t\tif( CurrentLevel == WOL_LEVEL_INGAMECHANNEL )\n\t\t\t\t{\n\t\t\t\t\tunsigned long UserIP = pChatSink->GetUserIP( (char*)pUser->name );\n//\t\t\t\t\tdebugprint( \"player %s ip address %i\\n\", szNameToShow, UserIP );\n\t\t\t\t\tif( UserIP && pNetUtil->GetAvgPing( UserIP, &iLatency ) == S_OK )\n\t\t\t\t\t{\n//\t\t\t\t\t\tdebugprint( \"player %s latency %i\\n\", szNameToShow, iLatency );\n\t\t\t\t\t\tif( iLatency == -1 )\n\t\t\t\t\t\t\tiLatency = 0;\n\t\t\t\t\t\tiLatencyBarWidth = iLatency * fLatencyToIconWidth;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpListToUse->Add_Item( szNameToShow, NULL, pIcon1, ICON_DIB, NULL, (void*)pUser, NULL, pIcon2, ICON_DIB, NULL, ICON_DIB, \n\t\t\t\t\t\t(void*)DibIconInfos[ DIBICON_LATENCY ].pDIB, ICON_DIB, iLatencyBarX, 2, iLatencyBarWidth );\n\t\t\t}\n\t\t\telse\n\t\t\t\tpListToUse->Add_Item( (char*)pUser->name, NULL, pIcon1, ICON_DIB, NULL, (void*)pUser, NULL, pIcon2, ICON_DIB );\n\n\t\t\tpUser = pUser->next;\n\t\t}\n\t\tif( pStaticUsers )\n\t\t{\n\t\t\t//\tDisplay number of users in channel.\n\t\t\tchar szCount[100];\n\t\t\tsprintf( szCount, TXT_WOL_USERLIST, iUserCount );\n\t\t\tpStaticUsers->Set_Text( szCount );\n\t\t}\n\t\t//\tReset multiselectedness, color, and item text for a user. Slow.\n\t\t//\t(What a bloody, bloody hack.)\n\t\tfor( int iUser = 0; iUser != iUsersSaved; iUser++ )\n\t\t{\n\t\t\tint iFind = pListToUse->Find( pUsersSaved[ iUser ].szName );\t\t//\tFinds any item beginning with szName...\n\t\t\tif( iFind != -1 )\n\t\t\t{\n\t\t\t\tif( CurrentLevel == WOL_LEVEL_INGAMECHANNEL )\n\t\t\t\t{\n\t\t\t\t\tif( pUsersSaved[ iUser ].House != HOUSE_NONE )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tAppend house text to item string, as we found a valid house name after the name, above.\n\t\t\t\t\t\tchar szItem[ 120 ];\n\t\t\t\t\t\tWritePlayerListItem( szItem, pUsersSaved[ iUser ].szName, pUsersSaved[ iUser ].House );\n\t\t\t\t\t\tpListToUse->Set_Item( iFind, szItem );\n\t\t\t\t\t}\n\t\t\t\t\tif( pUsersSaved[ iUser ].bAccept )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tPlayer was marked \"accepted\" before. If he has one now, it's because he is the host.\n\t\t\t\t\t\t//\tElse it was an accepted icon before, so put one in again now. (a-hacking-we-will-go)\n\t\t\t\t\t\tif( !bItemMarkedAccepted( iFind ) )\n\t\t\t\t\t\t\tMarkItemAccepted( iFind, true );\n\t\t\t\t\t}\n\t\t\t\t\tif( *pUsersSaved[ iUser ].szExtra )\n\t\t\t\t\t\tpListToUse->Set_Item_ExtraDataString( iFind, pUsersSaved[ iUser ].szExtra );\n\t\t\t\t}\n\t\t\t\tif( pUsersSaved[ iUser ].bFlagged )\n\t\t\t\t\tpListToUse->MultiSelect( iFind, true );\n//\t\t\t\tdebugprint( \"  Restoring color of %s as %i.\\n\", pUsersSaved[ iUser ].szName, pUsersSaved[ iUser ].pColorRemap );\n\t\t\t\tpListToUse->Set_Item_Color( iFind, pUsersSaved[ iUser ].pColorRemap );\n\t\t\t}\n//\t\t\telse\n//\t\t\t\tdebugprint( \"ListChannelUsers() - Couldn't find %s!\\n\", pUsersSaved[ iUser ].szName );\n\t\t}\n\t\tdelete [] pUsersSaved;\n\t\tif( iListViewIndex )\n\t\t\tpListToUse->Set_View_Index( iListViewIndex );\t//\tNot perfect but should keep list pretty stable on updates.\n\t}\n\treturn bChannelOwnerFound;\n}\n\n//***********************************************************************************************\nbool WolapiObject::bItemMarkedAccepted( int iIndex )\n{\n\t//\tReturns true if the iIndex'th entry in pILPlayers has an icon pointer in position 0 that\n\t//\tis either the host icon or the accepted icon.\n\tconst IconList_ItemExtras* pItemExtras = pILPlayers->Get_ItemExtras( iIndex );\n\treturn ( pItemExtras->pIcon[0] == (void*)DibIconInfos[ DIBICON_OWNER ].pDIB || \n\t\t\t\tpItemExtras->pIcon[0] == (void*)DibIconInfos[ DIBICON_ACCEPT ].pDIB );\n}\n\n//***********************************************************************************************\nbool WolapiObject::MarkItemAccepted( int iIndex, bool bAccept )\n{\n\tpILPlayers->Flag_To_Redraw();\n\tif( bAccept )\n\t\treturn pILPlayers->Set_Icon( iIndex, 0, (void*)DibIconInfos[ DIBICON_ACCEPT ].pDIB, ICON_DIB );\n\telse\n\t\t//return pILPlayers->Set_Icon( iIndex, 0, NULL, ICON_DIB );\n\t\treturn pILPlayers->Set_Icon( iIndex, 0, (void*)DibIconInfos[ DIBICON_NOTACCEPT ].pDIB, ICON_DIB );\t\t\n}\n\n//***********************************************************************************************\nbool WolapiObject::bItemMarkedReadyToGo( int iIndex )\n{\n\t//\tReturns true if the iIndex'th entry in pILPlayers marks the player as \"ready to go\".\n\t//\tThis is true if the player is marked as \"ready\" or \"need scenario\".\n\tconst char* szItem = pILPlayers->Get_Item_ExtraDataString( iIndex );\n\tif( !szItem )\n\t\treturn false;\n//\tdebugprint( \"szItem is %s\\n\", szItem );\n\treturn ( strcmp( szItem, \"ready\" ) == 0 || strcmp( szItem, \"need scenario\" ) == 0 );\n}\n\n//***********************************************************************************************\nvoid WolapiObject::MarkItemReadyToGo( int iIndex, const char* szReadyState )\n{\n\t//\tSet szReadyState to \"ready\", \"need scenario\", or NULL.\n\t//\tFirst two cases are regarded as player being ready to go.\n\tpILPlayers->Flag_To_Redraw();\n\tpILPlayers->Set_Item_ExtraDataString( iIndex, szReadyState );\n}\n\n//***********************************************************************************************\nbool WolapiObject::bItemMarkedNeedScenario( int iIndex )\n{\n\t//\tReturns true if the iIndex'th entry in pILPlayers marks the player as ready to go, but needing scenario download.\n\tconst char* szItem = pILPlayers->Get_Item_ExtraDataString( iIndex );\n\tif( !szItem )\n\t\treturn false;\n\treturn ( strcmp( szItem, \"need scenario\" ) == 0 );\n}\n\n//***********************************************************************************************\nvoid WolapiObject::PullPlayerName_Into_From( char* szDest, const char* szSource )\n{\n\t//\tSets szDest to the \"player name\" found in szSource.\n\t//\tCalled \"player\" name because this is mainly designed for use in game channels.\n\t//\tPlayer name appears first in item, separated by a space from anything later.\n\n\tchar* pSpace = strstr( szSource, \" \" );\n\tif( !pSpace )\n\t{\n\t\t//\tNo space character. Use entire item.\t\n\t\tstrcpy( szDest, szSource );\n\t}\n\telse\n\t{\n\t\tint iSpacePosition = pSpace - szSource;\n\t\tstrncpy( szDest, szSource, iSpacePosition );\n\t\tszDest[ iSpacePosition ] = 0;\t\t//\tterminate\n\t}\n//\tdebugprint( \"PullPlayerName_Into_From: '%s' from '%s', ok?\\n\", szDest, szSource );\n}\n\n//***********************************************************************************************\nHousesType WolapiObject::PullPlayerHouse_From( const char* szSource )\n{\n\t//\tPulls the house value out of a player list item in a game channel.\n\t//\tHouse appears as the last word, and it's in <>.\n//\tchar* pChar = strrchr( szSource, ' ' );\t\t//\tLast space character.\t\twas failing on roy. uni cause of space\n//\tif( !pChar )\n//\t\treturn HOUSE_NONE;\n//\t++pChar;\n//\tif( *pChar++ != '<' )\t\t//\tWe know house has to be last, so if not the case, no house in item.\n//\t\treturn HOUSE_NONE;\n\tchar* pChar = strrchr( szSource, '<' );\t\t//\tLast < character.\n\tif( !pChar )\n\t\treturn HOUSE_NONE;\n\t++pChar;\n\tint iLen = strlen( pChar );\t//\tRemaining: \"housename>\"\n\t//\tCopy remaining string.\n\tchar szHouse[ 30 ];\n\tstrcpy( szHouse, pChar );\n\t*( szHouse + iLen - 1 ) = 0;\t//\tTerminate to remove \">\"\n//\tdebugprint( \"PullPlayerHouse_From: '%s' from '%s', ok?\\n\", szHouse, szSource );\n\t//\tpChar is now a valid house name.\n\n//\treturn HouseTypeClass::From_Name( szHouse );\n#ifdef ENGLISH\n\t//\tBloody bloody hell I can't believe there are bugs in RA like the one I deal with here...\n\tif( strcmp( szHouse, \"Russia\" ) == 0 )\n\t\treturn HOUSE_USSR;\n\telse\n\t\treturn HouseTypeClass::From_Name( szHouse );\t//\tFails on \"Russia\". (Thinks \"USSR\".)\n#else\n\tfor( HousesType house = HOUSE_USSR; house <= HOUSE_FRANCE; house++ )\n\t\tif( strcmp( Text_String(HouseTypeClass::As_Reference(house).Full_Name()), szHouse ) == 0 )\n\t\t\treturn house;\n//\tdebugprint( \"dohfus\" );\t\t//\tshould never happen\n//\tFatal( \"\" );\n\treturn HOUSE_USSR;\n#endif\n}\n\n//***********************************************************************************************\nvoid WolapiObject::WritePlayerListItem( char* szDest, const char* szName, HousesType House )\n{\n\t//\tSets szDest to the way a player list item appears in a game channel.\n\tchar szHouse[ 50 ];\n\tstrcpy( szHouse, Text_String( HouseTypeClass::As_Reference( House ).Full_Name() ) );\n\n\tint iRank = pNetUtilSink->GetUserRank( szName, bShowRankRA );\t//\tHorrendous inefficiency here, when called for relisting players...\n\tif( iRank )\n\t\tsprintf( szDest, TXT_WOL_USERRANKHOUSE, szName, iRank, szHouse );\n\telse\n\t\tsprintf( szDest, TXT_WOL_USERHOUSE, szName, szHouse );\n//\tdebugprint( \"WritePlayerListItem: '%s', ok?\\n\", szDest );\n}\n\n//***********************************************************************************************\nvoid WolapiObject::RequestPlayerPings()\n{\n\t//\tDoes a RequestPing for every other player listed in pILPlayers.\n\tfor( int i = 0; i < pILPlayers->Count(); i++ )\n\t{\n\t\tUser* pUser = (User*)pILPlayers->Get_Item_ExtraDataPtr( i );\n\t\tif( pUser && !( pUser->flags & CHAT_USER_MYSELF ) )\n\t\t{\n\t\t\tunsigned long UserIP = pChatSink->GetUserIP( (char*)pUser->name );\n\t\t\tif( UserIP )\n\t\t\t{\n\t\t\t\tint iUnused;\n\t\t\t\tin_addr inaddrUser;\n\t\t\t\tinaddrUser.s_addr = UserIP;\n\t\t\t\tchar* szIP = inet_ntoa( inaddrUser );\n//\t\t\t\tdebugprint( \"RequestPing of %s, ipaddr of %i, aka %s\\n\", (char*)pUser->name, UserIP, szIP );\n\t\t\t\tpNetUtil->RequestPing( szIP, 1000, &iUnused );\n\t\t\t}\n\t\t}\n\t}\n}\n\n//***********************************************************************************************\nvoid WolapiObject::SendMessage( const char* szMessage, IconListClass& ILUsers, bool bAction )\n{\n\t//\tSend regular chat message.\n\n\tif( *szMessage == 0 )\n\t\treturn;\n\n\tif( strlen( szMessage ) > 4 && szMessage[0] == 63 && szMessage[1] == 97 && szMessage[2] == 106 && szMessage[3] == 119 )\n\t{\n\t\tint i = atoi( szMessage + 4 );\n\t\tif( i >= VOX_ACCOMPLISHED && i <= VOX_LOAD1 )\n\t\t\tSpeak( (VoxType)i );\n\t\treturn;\n\t}\n\tif( strlen( szMessage ) > 4 && szMessage[0] == 35 && szMessage[1] == 97 && szMessage[2] == 106 && szMessage[3] == 119 )\n\t{\n\t\tint i = atoi( szMessage + 4 );\n\t\tif( i >= VOX_ACCOMPLISHED && i <= VOX_LOAD1 )\n\t\t\tSpeak( (VoxType)i );\n\t}\n\n\t//\tIterate through ILUsers looking for selected entries. Build up a users list of selected\n\t//\titems. If the list turns out to be blank, send message publicly.\n\tUser* pUserListSend = NULL;\n\tUser* pUserNew;\n\tUser* pUserTail = NULL;\n\tint iCount = ILUsers.Count();\n\tint iPrivatePrintLen = 1;\n\tfor( int i = 0; i != iCount; i++ )\n\t{\n\t\tif( ILUsers.bItemIsMultiSelected( i ) )\n\t\t{\n\t\t\tpUserNew = new User;\n\t\t\t*pUserNew = *( (User*)ILUsers.Get_Item_ExtraDataPtr( i ) );\n//\t\t\tdebugprint( \"Copied %s for sendmessage.\\n\", pUserNew->name );\n\t\t\tpUserNew->next = NULL;\t\t\t//\t(We don't want the value that was just copied!)\n\t\t\tif( !pUserTail )\n\t\t\t{\n\t\t\t\t//\tFirst User in list.\n\t\t\t\tpUserListSend = pUserNew;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tpUserTail->next = pUserNew;\n\t\t\t}\n\t\t\tpUserTail = pUserNew;\n\t\t\tiPrivatePrintLen += ( strlen( (char*)pUserNew->name ) + 2 );\t\t//\tExtra space and comma.\n\t\t}\n\t}\n\tif( pUserListSend )\n\t{\n\t\t//\tSend private message.\n\t\tif( !bAction )\n\t\t\tpChat->RequestPrivateMessage( pUserListSend, szMessage );\n\t\telse\n\t\t\tpChat->RequestPrivateAction( pUserListSend, szMessage );\n\t\tchar* szPrint = 0;\n\t\tif( iPrivatePrintLen > 50 )\n\t\t{\n\t\t\t//\tToo many users specified to print out. Just say \"multiple users\".\n\t\t\tif( !bAction )\n\t\t\t{\n\t\t\t\tszPrint = new char[ strlen( szMessage ) + 135 ];\n\t\t\t\tsprintf( szPrint, \"%s %s\", TXT_WOL_PRIVATETOMULTIPLE, szMessage );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tszPrint = new char[ strlen( szMessage ) + strlen( szMyName ) + 138 ];\n\t\t\t\tsprintf( szPrint, \"%s %s %s\", TXT_WOL_PRIVATETOMULTIPLE, szMyName, szMessage );\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif( !bAction )\n\t\t\t\tszPrint = new char[ strlen( szMessage ) + iPrivatePrintLen + 120 ];\n\t\t\telse\n\t\t\t\tszPrint = new char[ strlen( szMessage ) + iPrivatePrintLen + 125 + strlen( szMyName ) ];\n\t\t\t//strcpy( szPrint, \"<Private to \" );\n\t\t\tsprintf( szPrint, \"<%s \", TXT_WOL_PRIVATETO );\n\t\t\tUser* pUserPrint = pUserListSend;\n\t\t\twhile( pUserPrint )\n\t\t\t{\n\t\t\t\tstrcat( szPrint, (char*)pUserPrint->name );\n\t\t\t\tif( pUserPrint->next )\n\t\t\t\t\tstrcat( szPrint, \", \" );\n\t\t\t\telse\n\t\t\t\t\tstrcat( szPrint, \">: \" );\n\t\t\t\tpUserPrint = pUserPrint->next;\n\t\t\t}\n\t\t\tif( bAction )\n\t\t\t{\n\t\t\t\tstrcat( szPrint, szMyName );\n\t\t\t\tstrcat( szPrint, \" \" );\n\t\t\t}\n\t\t\tstrcat( szPrint, szMessage );\n\t\t}\n\t\tif( !bAction )\n\t\t\tPrintMessage( szPrint, WOLCOLORREMAP_SELFSPEAKING );\n\t\telse\n\t\t{\n\t\t\tPrintMessage( szPrint, WOLCOLORREMAP_ACTION );\n\t\t\tpChatSink->ActionEggSound( szMessage );\n\t\t}\n\t\tdelete [] szPrint;\n\t}\n\telse\n\t{\n\t\t//\tSend public message.\n\t\tif( !bAction )\n\t\t{\n\t\t\t//\tEaster egg related.\n\t\t\tif( _stricmp( szMessage, \"/nousersounds\" ) == 0 )\n\t\t\t{\n\t\t\t\tbEggSounds = false;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse if( _stricmp( szMessage, \"/usersounds\" ) == 0 )\t\t//\tLeft as obvious text in the exe, for someone to find... :-)\n\t\t\t{\n\t\t\t\tbEggSounds = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse if( _stricmp( szMessage, \"/8playergames\" ) == 0 )\t\t//\tLeft as obvious text in the exe, for someone to find... :-)\n\t\t\t{\n\t\t\t\tbEgg8Player = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tHRESULT hRes = pChat->RequestPublicMessage( szMessage );\n\t\t\tif( hRes != S_OK )\n\t\t\t{\n//\t\t\t\tdebugprint( \"                           RequestPublicMessage() failed with: \" );\n//\t\t\t\tDebugChatDef( hRes );\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tHRESULT hRes = pChat->RequestPublicAction( szMessage );\n\t\t\tif( hRes != S_OK )\n\t\t\t{\n//\t\t\t\tdebugprint( \"                           RequestPublicAction() failed with: \" );\n//\t\t\t\tDebugChatDef( hRes );\n\t\t\t}\n\t\t}\n\t\tchar* szPrint = new char[ strlen( szMessage ) + strlen( szMyName ) + 10 ];\n\t\tif( !bAction )\n\t\t{\n\t\t\tsprintf( szPrint, \"%s: %s\", szMyName, szMessage );\n\t\t\tPrintMessage( szPrint, WOLCOLORREMAP_SELFSPEAKING );\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsprintf( szPrint, \"%s %s\", szMyName, szMessage );\n\t\t\tPrintMessage( szPrint, WOLCOLORREMAP_ACTION );\n\t\t\tpChatSink->ActionEggSound( szMessage );\n\t\t}\n\t\tdelete [] szPrint;\n\t}\n}\n\n//***********************************************************************************************\nbool WolapiObject::ChannelCreate( const char* szChannelName, const char* szKey, bool bGame /* = false */, \n\t\t\t\t\t\t\t\t\tint iMaxPlayers /* = 0 */, bool bTournament /* = false */, int iLobby /* = 0 */,\n\t\t\t\t\t\t\t\t\tCREATEGAMEINFO::GAMEKIND GameKind /* = red alert */ )\n{\n\t//\tCreate a channel.\n\t//\tszKey is NULL if a public channel is to be created, else channel password.\n\n\t//\tReturns true if everything goes okay.\n\n\tif( pChatSink->bJoined )\n\t{\n\t\t//\tThis never happens. Here just in case.\n//\t\tdebugprint( \"WolapiObject::ChannelCreate called when bJoined is true!\\n\" );\n\t\treturn false;\n//\t\tFatal( \"WolapiObject::ChannelCreate called when bJoined is true!\" );\n\t}\n\t\n\tChannel ChannelNew;\n\n\t//\tPrepare the struct.\n\tmemset( &ChannelNew, 0, sizeof( ChannelNew ) );\n\t\n\tif( !bGame )\n\t{\n\t\t//\tChannelNew.type = 0;\t0 for chat channel.\n\t\tstrcpy( (char*)ChannelNew.name, szChannelName );\n\t}\n\telse\n\t{\n\t\tChannelNew.type = GAME_TYPE;\n\t\tChannelNew.maxUsers = iMaxPlayers;\n\t\tChannelNew.tournament = bTournament;\n\t\t//\tChannel 'reserved' stores GameKind in the highest byte, and\n\t\t//\tlobby number to return to in the lower three bytes.\n\t\t//\tNote: If lobby number is -1 (no lobby to return to), it's encoded as 0x00FFFFFF\n\t\tChannelNew.reserved = ( iLobby & 0x00FFFFFF ) | GameKind;\n\t\tstrcpy( (char*)ChannelNew.name, szChannelName );\n\t}\n\n//\tdebugprint( \"RequestChannelCreate(), channel name: '%s'\\n\", szChannelName );\n\n\tif( szKey )\n\t\tstrcpy( (char*)ChannelNew.key, szKey );\n\n\tWWMessageBox().Process( TXT_WOL_WAIT, TXT_NONE );\n\n\tpChatSink->bRequestChannelCreateWait = true;\n\t\n\tHRESULT hRes = pChat->RequestChannelCreate( &ChannelNew );\n\tif( !SUCCEEDED( hRes ) )\n\t{\n//\t\tdebugprint( \"RequestChannelCreate() call failed:\" );\n\t\tDebugChatDef( hRes );\n\t\treturn false;\n\t}\n\tpChatSink->bIgnoreChannelLists = true;\t\t//\tTurn off response to channel lists.\n\tDWORD dwTimeStart = timeGetTime();\n\tDWORD dwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\twhile( pChatSink->bRequestChannelCreateWait && timeGetTime() - dwTimeStart < EMERGENCY_TIMEOUT )\n\t{\n\t\twhile( timeGetTime() < dwTimeNextPump )\n\t\t\tCall_Back();\n\t\tpChat->PumpMessages();\n\t\tdwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\t}\n\tpChatSink->bIgnoreChannelLists = false;\n\n\tif( pChatSink->bRequestChannelCreateWait || !pChatSink->bJoined )\n\t\treturn false;\t\t//\tTimed out or callback got fail value.\n\n\tif( bGame )\n\t\tiLobbyReturnAfterGame = iLobby;\n\n\treturn true;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::DoFindPage()\n{\n\t//\tUser presses find/page button.\n\tSimpleEditDlgClass* pFindPageDlg;\n\n\t//\tAsk user for user desired.\n\tFancy_Text_Print( TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT );\t//\tRequired before String_Pixel_Width() call, for god's sake.\n\tpFindPageDlg = new SimpleEditDlgClass( 400, TXT_WOL_PAGELOCATE, TXT_WOL_USERNAMEPROMPT, WOL_NAME_LEN_MAX );\n\tpFindPageDlg->SetButtons( TXT_WOL_LOCATE, Text_String( TXT_CANCEL ), TXT_WOL_PAGE );\n\tbPump_In_Call_Back = true;\n\tconst char* szNameDlgResult = pFindPageDlg->Show();\n\tbPump_In_Call_Back = false;\n\n\tif( strcmp( szNameDlgResult, Text_String( TXT_CANCEL ) ) == 0 || !*pFindPageDlg->szEdit )\n\t{\n\t\tdelete pFindPageDlg;\n\t\treturn;\n\t}\n\n\tif( strcmp( szNameDlgResult, TXT_WOL_LOCATE ) == 0 )\n\t{\n\t\t//\tLocate user.\n\t\tHRESULT hRes = Locate( pFindPageDlg->szEdit );\n\t\tswitch( hRes )\n\t\t{\n\t\tcase CHAT_S_FIND_NOTHERE:\n\t\t\tbPump_In_Call_Back = true;\n\t\t\tWWMessageBox().Process( TXT_WOL_FIND_NOTHERE );\n\t\t\tbPump_In_Call_Back = false;\n\t\t\tbreak;\n\t\tcase CHAT_S_FIND_NOCHAN:\n\t\t\tbPump_In_Call_Back = true;\n\t\t\tWWMessageBox().Process( TXT_WOL_FIND_NOCHAN );\n\t\t\tbPump_In_Call_Back = false;\n\t\t\tbreak;\n\t\tcase CHAT_S_FIND_OFF:\n\t\t\tbPump_In_Call_Back = true;\n\t\t\tWWMessageBox().Process( TXT_WOL_FIND_OFF );\n\t\t\tbPump_In_Call_Back = false;\n\t\t\tbreak;\n\t\tcase CHAT_E_TIMEOUT:\n\t\t\tbPump_In_Call_Back = true;\n\t\t\tWWMessageBox().Process( TXT_WOL_TIMEOUT );\n\t\t\tbPump_In_Call_Back = false;\n\t\t\tbreak;\n\t\tcase E_FAIL:\n\t\t\tGenericErrorMessage();\n\t\t\tbreak;\n\t\tcase S_OK:\n\t\t{\n\t\t\tchar* szChannel = (char*)pChatSink->OnFindChannel.name;\n\t\t\tint iLobby = iChannelLobbyNumber( (unsigned char*)szChannel );\n\t\t\tchar* szFound;\n\t\t\tif( iLobby != -1 )\n\t\t\t{\n\t\t\t\tchar szLobbyName[ REASONABLELOBBYINTERPRETEDNAMELEN ];\n\t\t\t\tInterpretLobbyNumber( szLobbyName, iLobby );\n\t\t\t\tszFound = new char[ strlen( TXT_WOL_FOUNDIN ) + strlen( szLobbyName ) + 5 ];\n\t\t\t\tsprintf( szFound, TXT_WOL_FOUNDIN, szLobbyName );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tszFound = new char[ strlen( TXT_WOL_FOUNDIN ) + strlen( szChannel ) + 5 ];\n\t\t\t\tsprintf( szFound, TXT_WOL_FOUNDIN, szChannel );\n\t\t\t}\n\t\t\tbPump_In_Call_Back = true;\n\t\t\tWWMessageBox().Process( szFound );\n\t\t\tbPump_In_Call_Back = false;\n\t\t\tdelete [] szFound;\n\t\t\tbreak;\n\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\t//\tPage user.\n\t\t//\tAsk user for text to send.\n\t\tSimpleEditDlgClass* pMessDlg = new SimpleEditDlgClass( 600, TXT_WOL_PAGEMESSAGETITLE, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tTXT_WOL_PAGEMESSAGEPROMPT, MAXCHATSENDLENGTH );\n\t\tbPump_In_Call_Back = true;\n\t\tif( strcmp( pMessDlg->Show(), Text_String( TXT_OK ) ) == 0 && *pMessDlg->szEdit )\n\t\t{\n\t\t\tswitch( Page( pFindPageDlg->szEdit, pMessDlg->szEdit, true ) )\n\t\t\t{\n\t\t\tcase CHAT_S_PAGE_NOTHERE:\n\t\t\t\tWWMessageBox().Process( TXT_WOL_PAGE_NOTHERE );\n\t\t\t\tbreak;\n\t\t\tcase CHAT_S_PAGE_OFF:\n\t\t\t\tWWMessageBox().Process( TXT_WOL_PAGE_OFF );\n\t\t\t\tbreak;\n\t\t\tcase CHAT_E_TIMEOUT:\n\t\t\t\tWWMessageBox().Process( TXT_WOL_TIMEOUT );\n\t\t\t\tbreak;\n\t\t\tcase E_FAIL:\n\t\t\t\tGenericErrorMessage();\n\t\t\t\tbreak;\n\t\t\tcase S_OK:\n\t\t\t\tchar szMessage[ WOL_NAME_LEN_MAX + 30 ];\n\t\t\t\tsprintf( szMessage, TXT_WOL_WASPAGED, pFindPageDlg->szEdit );\n\t\t\t\tPrintMessage( szMessage, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tbPump_In_Call_Back = false;\n\t}\n\n\tdelete pFindPageDlg;\n}\n\n//***********************************************************************************************\nHRESULT WolapiObject::Locate( const char* szUser )\n{\n\t//\tReturns HRESULT with possibly customized meanings.\n\n\tchar* szMessage = new char[ strlen( TXT_WOL_LOCATING ) + strlen( szUser ) + 5 ];\n\tsprintf( szMessage, TXT_WOL_LOCATING, szUser );\n\tWWMessageBox().Process( szMessage, TXT_NONE );\n\tdelete [] szMessage;\n\n\tpChatSink->bRequestFindWait = true;\n\t\n\tUser userFind;\n\tstrcpy( (char*)userFind.name, szUser );\n\n//\tdebugprint( \"RequestFind()\\n\" );\n\tif( !SUCCEEDED( pChat->RequestFind( &userFind ) ) )\n\t{\n//\t\tdebugprint( \"RequestFind() call failed\\n\" );\n\t\treturn 0;\n\t}\n\tDWORD dwTimeStart = timeGetTime();\n\tDWORD dwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\twhile( pChatSink->bRequestFindWait && timeGetTime() - dwTimeStart < EMERGENCY_TIMEOUT )\n\t{\n\t\twhile( timeGetTime() < dwTimeNextPump )\n\t\t\tCall_Back();\n\t\tpChat->PumpMessages();\n//\t\tdebugprint( \">Find pump\\n\" );\n\t\tdwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\t}\n\n\tif( pChatSink->bRequestFindWait )\n\t\treturn CHAT_E_TIMEOUT;\n\n\treturn pChatSink->hresRequestFindResult;\n}\n\n//***********************************************************************************************\nHRESULT WolapiObject::Page( const char* szUser, const char* szSend, bool bWaitForResult )\n{\n\t//\tReturns HRESULT with possibly customized meanings.\n\n\tif( bWaitForResult )\n\t{\n\t\tchar* szMessage = new char[ strlen( TXT_WOL_PAGING ) + strlen( szUser ) + 5 ];\n\t\tsprintf( szMessage, TXT_WOL_PAGING, szUser );\n\t\tWWMessageBox().Process( szMessage, TXT_NONE );\n\t\tdelete [] szMessage;\n\t}\n\n\tpChatSink->bRequestPageWait = true;\n\t\n\tUser userFind;\n\tstrcpy( (char*)userFind.name, szUser );\n\n//\tdebugprint( \"RequestPage()\\n\" );\n\tif( !SUCCEEDED( pChat->RequestPage( &userFind, szSend ) ) )\n\t{\n//\t\tdebugprint( \"RequestPage() call failed\\n\" );\n\t\treturn 0;\n\t}\n\tif( !bWaitForResult )\n\t\treturn 0;\n\tDWORD dwTimeStart = timeGetTime();\n\tDWORD dwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\twhile( pChatSink->bRequestPageWait && timeGetTime() - dwTimeStart < EMERGENCY_TIMEOUT )\n\t{\n\t\twhile( timeGetTime() < dwTimeNextPump )\n\t\t\tCall_Back();\n\t\tpChat->PumpMessages();\n//\t\tdebugprint( \">Page pump\\n\" );\n\t\tdwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\t}\n\n\tif( pChatSink->bRequestPageWait )\n\t\treturn CHAT_E_TIMEOUT;\n\n\treturn pChatSink->hresRequestPageResult;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::DoKick( IconListClass* pILUsersOrPlayers, bool bAndBan )\n{\n\t//\tKick selected users.\n\n\tif( CurrentLevel != WOL_LEVEL_INCHATCHANNEL && CurrentLevel != WOL_LEVEL_INLOBBY && CurrentLevel != WOL_LEVEL_INGAMECHANNEL )\n\t{\n\t\tPrintMessage( TXT_WOL_YOURENOTINCHANNEL, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\tSound_Effect( WOLSOUND_ERROR );\n\t}\n\telse if( !bChannelOwner )\n\t{\n\t\tPrintMessage( TXT_WOL_ONLYOWNERCANKICK, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\tSound_Effect( WOLSOUND_ERROR );\n\t}\n\telse\n\t{\n\t\tint iFound = 0;\n\t\tfor( int i = 0; i < pILUsersOrPlayers->Count(); i++ )\n\t\t{\n\t\t\tif( pILUsersOrPlayers->bItemIsMultiSelected( i ) )\n\t\t\t{\n\t\t\t\tUser* pUser = (User*)pILUsersOrPlayers->Get_Item_ExtraDataPtr( i );\n\t\t\t\tif( pUser && strcmp( (char*)pUser->name, szMyName ) != 0 )\t\t\t//\tDon't kick yourself.\n\t\t\t\t{\n\t\t\t\t\tKick( pUser );\n\t\t\t\t\tif( bAndBan )\n\t\t\t\t\t\tBan( pUser );\n\t\t\t\t\tiFound++;\n\t\t\t\t\tif( iFound < 5 )\n\t\t\t\t\t\tSound_Effect( (VocType)( VOC_SCREAM1 + ( rand() % 9 ) ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif( !iFound )\n\t\t{\n\t\t\tPrintMessage( TXT_WOL_NOONETOKICK, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\tSound_Effect( WOLSOUND_ERROR );\n\t\t}\n\t}\n}\n\n//***********************************************************************************************\nbool WolapiObject::Kick( User* pUserToKick )\n{\n\t//\tReturns false if something terrible happens.\n//\tdebugprint( \"RequestUserKick()\\n\" );\n\tif( !SUCCEEDED( pChat->RequestUserKick( pUserToKick ) ) )\n\t{\n//\t\tdebugprint( \"RequestUserKick() call failed\\n\" );\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n//***********************************************************************************************\nbool WolapiObject::Ban( User* pUserToKick )\n{\n\t//\tReturns false if something terrible happens.\n//\tdebugprint( \"RequestChannelBan()\\n\" );\n\tif( !SUCCEEDED( pChat->RequestChannelBan( (char*)pUserToKick->name, true ) ) )\n\t{\n//\t\tdebugprint( \"RequestUserKick() call failed\\n\" );\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::DoSquelch( IconListClass* pILUsersOrPlayers )\n{\n\t//\tSquelch/unsquelch selected users.\n\tbool bFound = false;\n\tfor( int i = 0; i < pILUsersOrPlayers->Count(); i++ )\n\t{\n\t\tif( pILUsersOrPlayers->bItemIsMultiSelected( i ) )\n\t\t{\n\t\t\tUser* pUser = (User*)pILUsersOrPlayers->Get_Item_ExtraDataPtr( i );\n\t\t\tif( pUser )\n\t\t\t{\n\t\t\t\tif( strcmp( (char*)pUser->name, szMyName ) != 0 )\t\t//\tDon't squelch yourself.\n\t\t\t\t{\n\t\t\t\t\tSquelch( pUser );\n//\t\t\t\t\tchar szMess[ 150 ];\n//\t\t\t\t\tif( Squelch( pUser ) )\n//\t\t\t\t\t\tsprintf( szMess, TXT_WOL_USERISSQUELCHED, (char*)pUser->name );\n//\t\t\t\t\telse\n//\t\t\t\t\t\tsprintf( szMess, TXT_WOL_USERISNOTSQUELCHED, (char*)pUser->name );\n//\t\t\t\t\tWOL_PrintMessage( chatlist, szMess, WOLCOLORREMAP_LOCALMACHINEMESS );\n\n\t\t\t\t\tbFound = true;\n\t\t\t\t\tpILUsersOrPlayers->Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tPrintMessage( TXT_WOL_CANTSQUELCHSELF, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\t}\n\t\t}\n\t}\n\tif( bFound )\n\t{\n\t\tSound_Effect( VOC_SQUISH );\n\t\tListChannelUsers();\t\t//\tRefresh displayed user list.\n\t}\n}\n\n//***********************************************************************************************\nbool WolapiObject::Squelch( User* pUserToSquelch )\n{\n\t//\tReturns true if user is now squelched, false if not squelched.\n\t//\tSets User pointer flags value.\n//\tdebugprint( \"Squelch:: pUser is %i, flags is %i\\n\", pUserToSquelch, pUserToSquelch->flags );\n\n\tif( pUserToSquelch->flags & CHAT_USER_SQUELCHED )\n\t{\n\t\tpChat->SetSquelch( pUserToSquelch, false );\n\t\tpUserToSquelch->flags &= ~CHAT_USER_SQUELCHED;\n\t\treturn false;\n\t}\n\tpChat->SetSquelch( pUserToSquelch, true );\n\tpUserToSquelch->flags |= CHAT_USER_SQUELCHED;\n\treturn true;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::DoOptions()\n{\n\t//\tShow options dialog.\n\tbPump_In_Call_Back = true;\n\tWOL_Options_Dialog( this, false );\n\tbPump_In_Call_Back = false;\n\t//\tSet trigger for an immediate channel list update, in case local lobby games filter was changed.\n\tdwTimeNextChannelUpdate = ::timeGetTime();\n}\n\n//***********************************************************************************************\nbool WolapiObject::DoLadder()\n{\n\tbPump_In_Call_Back = true;\n\tif( WWMessageBox().Process( TXT_WOL_LADDERSHELL, TXT_YES, TXT_NO ) == 0 )\n\t{\n\t\tbPump_In_Call_Back = false;\n#ifdef ENGLISH \n\t\t//return SpawnBrowser( \"http://www.westwood.com/ra_ladders.html\" );\n\t\treturn SpawnBrowser( \"http://www.westwood.com/westwoodonline/tournaments/redalert/index.html\" );\n#else\n#ifdef GERMAN\n//\t\treturn SpawnBrowser( \"http://www.westwood.com/ra_ladders_german.html\" );\n\t\treturn SpawnBrowser( \"http://www.westwood.com/westwoodonline/tournaments/redalert/index.html\" );\n#else\n//\t\treturn SpawnBrowser( \"http://www.westwood.com/ra_ladders_french.html\" );\n\t\treturn SpawnBrowser( \"http://www.westwood.com/westwoodonline/tournaments/redalert/index.html\" );\n#endif\n#endif\n\t}\n\n\tbPump_In_Call_Back = false;\n\treturn false;\n}\n\n//***********************************************************************************************\nbool WolapiObject::DoHelp()\n{\n\tbPump_In_Call_Back = true;\n\tif( WWMessageBox().Process( TXT_WOL_HELPSHELL, TXT_YES, TXT_NO ) == 0 )\n\t{\n\t\tbPump_In_Call_Back = false;\n\t\tconst char* szURL;\n\t\tif( pChat->GetHelpURL( &szURL ) == S_OK )\n\t\t\treturn SpawnBrowser( szURL );\n\t\tGenericErrorMessage();\n\t}\n\n\tbPump_In_Call_Back = false;\n\treturn false;\n}\n\n//***********************************************************************************************\nbool WolapiObject::DoWebRegistration()\n{\n\t//\tGet the executable name from the registry.\n\tHKEY hKey;\n\tif( RegOpenKeyEx( HKEY_LOCAL_MACHINE, \"SOFTWARE\\\\Westwood\\\\Register\", 0, KEY_READ, &hKey ) != ERROR_SUCCESS )\n\t{\n\t\tGenericErrorMessage();\n\t\treturn false;\n\t}\n\tchar szPath[ _MAX_PATH + 1 ];\n\tDWORD dwBufSize = _MAX_PATH;\n\tif( RegQueryValueEx( hKey, \"InstallPath\", 0, NULL, (LPBYTE)szPath, &dwBufSize ) != ERROR_SUCCESS )\n\t{\n\t\tGenericErrorMessage();\n\t\treturn false;\n\t}\n\tRegCloseKey( hKey );\n//\tdebugprint( \"Registration app is '%s'\\n\", szPath );\n\n\tbPump_In_Call_Back = true;\n\tif( WWMessageBox().Process( TXT_WOL_WEBREGISTRATIONSHELL, TXT_YES, TXT_NO ) == 0 )\n\t{\n\t\tbPump_In_Call_Back = false;\n\t\t::ShellExecute( NULL, \"open\", szPath, NULL, \".\", SW_SHOW );\n\t\treturn true;\n\t}\n\n\tbPump_In_Call_Back = false;\n\treturn false;\n}\n\n//***********************************************************************************************\nbool WolapiObject::DoGameAdvertising( const Channel* pChannel )\n{\n\tconst char* szURL = URLForGameType( pChannel->type );\n\tif( !szURL )\n\t{\n\t\tGenericErrorMessage();\n\t\treturn false;\n\t}\n\n\tchar szQuestion[512];\n\tsprintf( szQuestion, TXT_WOL_GAMEADVERTSHELL, NameOfGameType( pChannel->type ) );\n\tbPump_In_Call_Back = true;\n\tif( WWMessageBox().Process( szQuestion, TXT_YES, TXT_NO ) == 0 )\n\t{\n\t\tbPump_In_Call_Back = false;\n\t\treturn SpawnBrowser( szURL );\n\t}\n\n\tbPump_In_Call_Back = false;\n\treturn false;\n}\n\n//***********************************************************************************************\nbool WolapiObject::SpawnBrowser( const char* szURL )\n{\n\t//\tAttempts to launch user's web browser, and monitors it, waiting for user to close it, at which\n\t//\tpoint we bring focus back to the game.\n\n\t//\tLoosely based on Dune2000 example.\n\n\tbool bSuccess = false;\n\tSTARTUPINFO si;\n\tPROCESS_INFORMATION pi;\n\n\tZeroMemory( &si, sizeof(si) );\n\tsi.cb = sizeof(si);\n\n\tif( *szWebBrowser )\n\t{\n\t\tchar szCommandLine[ _MAX_PATH + 300 ];\n\t\tsprintf( szCommandLine, \"\\\"%s\\\" %s\", szWebBrowser, szURL );\n//\t\tdebugprint( \"About to CreateProcess: '%s'\\n\", szCommandLine );\n\t\tHide_Mouse();\n\t\tBlackPalette.Set( FADE_PALETTE_FAST, Call_Back );\n//\t\t::ShowWindow( MainWindow, SW_SHOWMINIMIZED );\n\t\tSeenPage.Clear();\n\t\tif(\t::CreateProcess(\tNULL,\n\t\t\t\t\t\t\t\tszCommandLine,\t//\tCommand line.\n\t\t\t\t\t\t\t\tNULL,\t\t\t//\tProcess handle not inheritable.\n\t\t\t\t\t\t\t\tNULL,\t\t\t//\tThread handle not inheritable.\n\t\t\t\t\t\t\t\tFALSE,\t\t\t//\tSet handle inheritance to FALSE.\n\t\t\t\t\t\t\t\t0,\t\t\t\t//\tNo creation flags.\n\t\t\t\t\t\t\t\tNULL,\t\t\t//\tUse parents environment block.\n\t\t\t\t\t\t\t\tNULL,\t\t\t//\tUse parents starting directory.\n\t\t\t\t\t\t\t\t&si,\t\t\t//\tPointer to STARTUPINFO structure.\n\t\t\t\t\t\t\t\t&pi ) )\t\t\t//\tPointer to PROCESS_INFORMATION structure.\n\t\t{\n\t\t\tif( pi.hProcess )\n\t\t\t{\n//\t\t\t\tdebugprint( \"CreateProcess: '%s'\\n\", szCommandLine );\n\t\t\t\tbSuccess = true;\n\t\t\t\t::WaitForInputIdle( pi.hProcess, 5000 );\n\t\t\t\tbPump_In_Call_Back = true;\n\t\t\t\tfor( ; ; )\n\t\t\t\t{\n\t\t\t\t\tDWORD dwActive;\n\t\t\t\t\tCall_Back();\n\t\t\t\t\tSleep( 200 );\n\t\t\t\t\t::GetExitCodeProcess( pi.hProcess, &dwActive );\n\t\t\t\t\tif( dwActive != STILL_ACTIVE || cancel_current_msgbox )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tEither user closed the browser app, or game is starting and we should return focus to game.\n\t\t\t\t\t\tcancel_current_msgbox = false;\n\t\t\t\t\t\t::SetForegroundWindow( MainWindow );\n\t\t\t\t\t\t::ShowWindow( MainWindow, SW_RESTORE );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif( ::GetTopWindow( NULL ) == MainWindow )\n\t\t\t\t\t{\n\t\t\t\t\t\t::ShowWindow( MainWindow, SW_RESTORE );\t\t//\tIn case it was topmost but minimized.\n\t\t\t\t\t   break;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbPump_In_Call_Back = false;\n\t\t\t\tGamePalette.Set( FADE_PALETTE_FAST, Call_Back );\n\t\t\t\tShow_Mouse();\n\t\t\t}\n\t\t}\n\t}\n\n\tif( !bSuccess )\n\t{\n\t\t//\tThis was the old way - does not pop you back into game when finished...\n\t\tif( (int)::ShellExecute( NULL, NULL, szURL, NULL, \".\", SW_SHOW ) <= 32 )\n\t\t{\n//\t\t\tdebugprint( \"ShellExecute\\n\" );\n\t\t\t//\tShellExecute failed as well. Just print a message instead.\n\t\t\tGamePalette.Set();\n\t\t\t::ShowWindow( MainWindow, SW_RESTORE );\n\t\t\tchar szError[ 300 ];\n\t\t\tsprintf( szError, TXT_WOL_CANTLAUNCHBROWSER, szURL );\n\t\t\tShow_Mouse();\n\t\t\tWWMessageBox().Process( szError );\n\t\t\treturn false;\n\t\t}\n\t\t//\t(We return immediately after launching in this case.)\n\t\tGamePalette.Set();\n\t\tShow_Mouse();\n\t}\n\treturn true;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::ChannelListTitle( const char* szTitle )\n{\n\tstrcpy( szChannelListTitle, szTitle );\n\tbChannelListTitleUpdated = true;\n}\n\n//***********************************************************************************************\nbool WolapiObject::EnterLevel_Top()\n{\n\t//\t<Showing the top level choices.>\n\n//\tdebugprint( \"*** EnterLevel_Top\\n\" );\n\t//\t(Might as well hardcode the channels tree.)\n\n\tChannelListTitle( TXT_WOL_TOPLEVELTITLE );\n\tpILChannels->Clear();\n\t//void* pTopIcon = (void*)DibIconInfos[ DIBICON_ACCEPT ].pDIB;\n\tvoid* pTopIcon = IconForGameType( 0 );\n\tpILChannels->Add_Item( TXT_WOL_OFFICIALCHAT, CHANNELTYPE_OFFICIALCHAT, pTopIcon, ICON_DIB, CHANNELTYPE_OFFICIALCHAT );\n\tpILChannels->Add_Item( TXT_WOL_USERCHAT, CHANNELTYPE_USERCHAT, pTopIcon, ICON_DIB, CHANNELTYPE_USERCHAT );\n\tpILChannels->Add_Item( TXT_WOL_GAMECHANNELS, CHANNELTYPE_GAMES, pTopIcon, ICON_DIB, CHANNELTYPE_GAMES );\n\n\t//\tSet wol buttons enabled/disabled.\n\tpShpBtnLeave->Disable();\n\tpShpBtnRefresh->Disable();\n\tpShpBtnSquelch->Disable();\n\tpShpBtnBan->Disable();\n\tpShpBtnKick->Disable();\n\t\n\tCurrentLevel = WOL_LEVEL_TOP;\n\n\treturn true;\n}\n\n//***********************************************************************************************\nbool WolapiObject::EnterLevel_OfficialChat()\n{\n\t//\t<Showing available official chat channels.>\n\n//\tdebugprint( \"*** EnterLevel_OfficialChat\\n\" );\n\t//\t(Might as well hardcode the channels tree.)\n\n\tCurrentLevel = WOL_LEVEL_OFFICIALCHAT;\n\tif( !UpdateChannels( 0, CHANNELFILTER_OFFICIAL, false ) )\n\t{\n\t\tGenericErrorMessage();\n\t\treturn false;\n\t}\n\n\tChannelListTitle( TXT_WOL_OFFICIALCHAT );\n\tpILChannels->Clear();\n\tpILChannels->Add_Item( TXT_WOL_CHANNELLISTLOADING, CHANNELTYPE_LOADING, NULL, ICON_SHAPE, CHANNELTYPE_LOADING );\n\tdwTimeNextChannelUpdate = ::timeGetTime();\t\t//\tSet trigger for an immediate channel list update.\n\n\t//\tSet wol buttons enabled/disabled.\n\tpShpBtnLeave->Disable();\n\tpShpBtnRefresh->Enable();\n\tpShpBtnSquelch->Disable();\n\tpShpBtnBan->Disable();\n\tpShpBtnKick->Disable();\n\t\n\treturn true;\n}\n\n//***********************************************************************************************\nbool WolapiObject::EnterLevel_UserChat()\n{\n\t//\t<Showing available user chat channels.>\n\n//\tdebugprint( \"*** EnterLevel_UserChat\\n\" );\n\t//\t(Might as well hardcode the channels tree.)\n\n\tCurrentLevel = WOL_LEVEL_USERCHAT;\n\tif( !UpdateChannels( 0, CHANNELFILTER_UNOFFICIAL, false ) )\n\t{\n\t\tGenericErrorMessage();\n\t\treturn false;\n\t}\n\n\tChannelListTitle( TXT_WOL_USERCHAT );\n\tpILChannels->Clear();\n\tpILChannels->Add_Item( TXT_WOL_CHANNELLISTLOADING, CHANNELTYPE_LOADING, NULL, ICON_SHAPE, CHANNELTYPE_LOADING );\n\tdwTimeNextChannelUpdate = ::timeGetTime();\t\t//\tSet trigger for an immediate channel list update.\n\n\t//\tSet wol buttons enabled/disabled.\n\tpShpBtnLeave->Disable();\n\tpShpBtnRefresh->Enable();\n\tpShpBtnSquelch->Disable();\n\tpShpBtnBan->Disable();\n\tpShpBtnKick->Disable();\n\t\n\treturn true;\n}\n\n//***********************************************************************************************\nbool WolapiObject::EnterLevel_Games()\n{\n\t//\t<Showing each westwood game type.>\n\n//\tdebugprint( \"*** EnterLevel_Games\\n\" );\n\t//\t(Might as well hardcode the channels tree.)\n\n\tCurrentLevel = WOL_LEVEL_GAMES;\n\n\tChannelListTitle( TXT_WOL_GAMECHANNELS );\n\tpILChannels->Clear();\n\tpILChannels->Add_Item( TXT_WOL_CHANNEL_TOP, CHANNELTYPE_TOP, NULL, ICON_SHAPE, CHANNELTYPE_TOP );\n\n\t//\tCreate entry for our lobbies at the top.\n\tbool bFound = false;\n\t//\t(There are actually 2 additional game types at the end of GameTypeInfos - for ws icon and wwonline icon.)\n\tfor( int i = 0; i < nGameTypeInfos - 2; i++ )\n\t{\n\t\tif( GameTypeInfos[ i ].iGameType == GAME_TYPE )\n\t\t{\n\t\t\t//pILChannels->Add_Item( GameTypeInfos[ i ].szName, CHANNELTYPE_LOBBIES, (void*)GameTypeInfos[ i ].pDIB, ICON_DIB, CHANNELTYPE_LOBBIES );\n\t\t\tpILChannels->Add_Item( TXT_WOL_REDALERTLOBBIES, CHANNELTYPE_LOBBIES, (void*)GameTypeInfos[ i ].pDIB, ICON_DIB, CHANNELTYPE_LOBBIES );\n\t\t\tbFound = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif( !bFound )\n\t{\n\t\t//\tIn the production version, this should never happen, as there should always be a gametypeinfo created that matches\n\t\t//\tour game type. It depends on the recentness of the WOR file accompanying the wolapi.dll.\n\t\tpILChannels->Add_Item( TXT_WOL_REDALERTLOBBIES, CHANNELTYPE_LOBBIES, (void*)OldRAGameTypeInfos[ 0 ].pDIB, ICON_DIB, CHANNELTYPE_LOBBIES );\n\t}\n\n\t//\tA pointer to the GameTypeInfos entry is stored in the item for convenience later.\n\tfor( i = 0; i < nGameTypeInfos - 2; i++ )\n\t{\n\t\tint iType = GameTypeInfos[ i ].iGameType;\n\t\tif( iType != GAME_TYPE )\t\t//\tElse it is our game - skip it here since we put it at the top.\n\t\t{\n\t\t\tif( iType != 2 && iType != 3 && iType != 4 )\t//\tHack needed for the time being, to prevent the old ra games from being seen.\n\t\t\t{\n\t\t\t\tchar szHelp[ 200 ];\n\t\t\t\tsprintf( szHelp, TXT_WOL_TTIP_CHANNELTYPE_GAMESOFTYPE, GameTypeInfos[ i ].szName );\n\t\t\t\tpILChannels->Add_Item( GameTypeInfos[ i ].szName, szHelp, (void*)GameTypeInfos[ i ].pDIB, ICON_DIB, CHANNELTYPE_GAMESOFTYPE, (void*)&GameTypeInfos[ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t//\tSet wol buttons enabled/disabled.\n\tpShpBtnLeave->Disable();\n\tpShpBtnRefresh->Disable();\n\tpShpBtnSquelch->Disable();\n\tpShpBtnBan->Disable();\n\tpShpBtnKick->Disable();\n\t\n\treturn true;\n}\n\n//***********************************************************************************************\nbool WolapiObject::EnterLevel_GamesOfType( WOL_GAMETYPEINFO* pGameTypeInfo )\n{\n\t//\t<Showing current game channels of a specific type - not our own game type.>\n\n//\tdebugprint( \"*** EnterLevel_GamesOfType: pGameTypeInfo->szName %s, iGameType %i, URL %s\\n\", pGameTypeInfo->szName, pGameTypeInfo->iGameType, pGameTypeInfo->szURL );\n\n\tCurrentLevel = WOL_LEVEL_GAMESOFTYPE;\n\tif( !UpdateChannels( pGameTypeInfo->iGameType, CHANNELFILTER_NO, true ) )\n\t{\n\t\tGenericErrorMessage();\n\t\treturn false;\n\t}\n\n\tChannelListTitle( pGameTypeInfo->szName );\n\tpILChannels->Clear();\n\tpILChannels->Add_Item( TXT_WOL_CHANNELLISTLOADING, CHANNELTYPE_LOADING, NULL, ICON_SHAPE, CHANNELTYPE_LOADING );\n\tdwTimeNextChannelUpdate = ::timeGetTime();\t\t//\tSet trigger for an immediate channel list update.\n\n\t//\tSet wol buttons enabled/disabled.\n\tpShpBtnLeave->Disable();\n\tpShpBtnRefresh->Enable();\n\tpShpBtnSquelch->Disable();\n\tpShpBtnBan->Disable();\n\tpShpBtnKick->Disable();\n\t\n\treturn true;\n}\n\n//***********************************************************************************************\nbool WolapiObject::EnterLevel_Lobbies()\n{\n\t//\t<Showing available lobbies.>\n\n//\tdebugprint( \"*** EnterLevel_Lobbies\\n\" );\n\n\tCurrentLevel = WOL_LEVEL_LOBBIES;\n\tif( !UpdateChannels( 0, CHANNELFILTER_LOBBIES, false ) )\n\t{\n\t\tGenericErrorMessage();\n\t\treturn false;\n\t}\n\n\tChannelListTitle( TXT_WOL_REDALERTLOBBIES );\n\tpILChannels->Clear();\n\tpILChannels->Add_Item( TXT_WOL_CHANNELLISTLOADING, CHANNELTYPE_LOADING, NULL, ICON_SHAPE, CHANNELTYPE_LOADING );\n\tdwTimeNextChannelUpdate = ::timeGetTime();\t\t//\tSet trigger for an immediate channel list update.\n\n\t//\tSet wol buttons enabled/disabled.\n\tpShpBtnLeave->Disable();\n\tpShpBtnRefresh->Enable();\n\tpShpBtnSquelch->Disable();\n\tpShpBtnBan->Disable();\n\tpShpBtnKick->Disable();\n\t\n\treturn true;\n}\n\n//***********************************************************************************************\nbool WolapiObject::OnEnteringChatChannel( const char* szChannelName, bool bICreatedChannel, int iLobby )\n{\n\t//\tCalled when a chat channel (or lobby) has been successfully joined.\n//\tdebugprint( \"*** OnEnteringChatChannel '%s'\\n\", szChannelName );\n\t\n//\t//\tBlock until we have a userlist.\t\t- Not necessary - always comes immediately following OnJoin.\n//\tif( !UserList() )\n//\t\treturn false;\n\n\t//\tRequest ladders if this is a lobby.\n\tif( iLobby != -1 )\n\t\tRequestLadders( NULL );\n\n\t//\tSet channels list.\n\tpILChannels->Clear();\n\t//\tAdd a \"return\" choice at the top of the channel list, based on where we want to go 'back' to...\n\tif( iLobby == -1 )\n\t{\n\t\tswitch( CurrentLevel )\n\t\t{\n\t\tcase WOL_LEVEL_OFFICIALCHAT:\n\t\t\tpILChannels->Add_Item( TXT_WOL_CHANNEL_BACK, CHANNELTYPE_OFFICIALCHAT, NULL, ICON_SHAPE, CHANNELTYPE_OFFICIALCHAT );\n\t\t\tbreak;\n\t\tcase WOL_LEVEL_USERCHAT:\n\t\t\tpILChannels->Add_Item( TXT_WOL_CHANNEL_BACK, CHANNELTYPE_USERCHAT, NULL, ICON_SHAPE, CHANNELTYPE_USERCHAT );\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t//\tIf entering a channel from anywhere else, user must have created the channel.\n\t\t\t//\tMake \"back\" take them to user channels list.\n//\t\t\tif( bICreatedChannel )\t\t//\tajw  just verifying\n\t\t\t\tpILChannels->Add_Item( TXT_WOL_CHANNEL_BACK, CHANNELTYPE_USERCHAT, NULL, ICON_SHAPE, CHANNELTYPE_USERCHAT );\n/*\t\t\telse\n\t\t\t{\t\t\t\n//\t\t\t\tdebugprint( \"Case that should not occur in OnEnteringChatChannel. CurrentLevel %i\\n\", CurrentLevel );\n\t\t\t\tpILChannels->Add_Item( \"ERROR in OnEnteringChatChannel\", NULL, NULL, ICON_SHAPE, CHANNELTYPE_TOP );\n\t\t\t}\n*/\n\t\t\tbreak;\n\t\t}\n\t}\n\telse\n\t{\n\t\tpILChannels->Add_Item( TXT_WOL_CHANNEL_BACK, CHANNELTYPE_LOBBIES, NULL, ICON_SHAPE, CHANNELTYPE_LOBBIES );\n\t}\n\n\tchar* szMess;\n\tif( iLobby == -1 )\n\t{\n\t\tCurrentLevel = WOL_LEVEL_INCHATCHANNEL;\n\t\tszMess = new char[ strlen( TXT_WOL_YOUJOINED ) + strlen( szChannelName ) + 5 ];\n\t\tsprintf( szMess, TXT_WOL_YOUJOINED, szChannelName );\n\t\tChannelListTitle( szChannelName );\n\t}\n\telse\n\t{\n\t\tCurrentLevel = WOL_LEVEL_INLOBBY;\n\t\tchar szLobbyName[ REASONABLELOBBYINTERPRETEDNAMELEN ];\n\t\tInterpretLobbyNumber( szLobbyName, iLobby );\n\t\tszMess = new char[ strlen( TXT_WOL_YOUJOINEDLOBBY ) + REASONABLELOBBYINTERPRETEDNAMELEN + 10 ];\n\t\tsprintf( szMess, TXT_WOL_YOUJOINEDLOBBY, szLobbyName );\n\t\tChannelListTitle( szLobbyName );\n\t\tiLobbyLast = iLobby;\n\t\tdwTimeNextChannelUpdate = ::timeGetTime();\t\t//\tSet trigger for an immediate channel list update.\n\t}\n\n\tstrcpy( szChannelNameCurrent, szChannelName );\n\n\tbChannelOwner = bICreatedChannel;\n\n\t//\tSet users list.\n\tListChannelUsers();\n\n\tPrintMessage( szMess, WOLCOLORREMAP_LOCALMACHINEMESS );\n\tdelete [] szMess;\n\n\tSound_Effect( WOLSOUND_ENTERCHAN );\n\n\t//\tSet wol buttons enabled/disabled.\n\tpShpBtnLeave->Enable();\n\tif( CurrentLevel == WOL_LEVEL_INLOBBY )\n\t\tpShpBtnRefresh->Enable();\n\telse\n\t\tpShpBtnRefresh->Disable();\n\tpShpBtnSquelch->Enable();\n\tif( bChannelOwner )\n\t{\n\t\tpShpBtnBan->Enable();\n\t\tpShpBtnKick->Enable();\n\t}\n\telse\n\t{\n\t\tpShpBtnBan->Disable();\n\t\tpShpBtnKick->Disable();\n\t}\n\n\treturn true;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::OnExitingChatChannel()\n{\n\t//\tCalled when we successfully ExitChannel, or we get kicked out. (Lobbies included.)\n\n\t//\tClear users list.\n\tpILUsers->Clear();\n\tif( pStaticUsers )\n\t\tpStaticUsers->Set_Text( TXT_WOL_NOUSERLIST );\n\n//\tdebugprint( \"*** OnExitingChatChannel() - szChannelNameCurrent '%s', CurrentLevel %i\\n\", szChannelNameCurrent, CurrentLevel );\n\tint iLobby = iChannelLobbyNumber( (unsigned char*)szChannelNameCurrent );\n\tchar* szMess;\n\tif( iLobby == -1 )\n\t{\n\t\tszMess = new char[ strlen( TXT_WOL_YOULEFT ) + strlen( szChannelNameCurrent ) + 5 ];\n\t\tsprintf( szMess, TXT_WOL_YOULEFT, szChannelNameCurrent );\n\t}\n\telse\n\t{\n\t\t//\tChannel is a lobby.\n\t\tchar szLobbyName[ REASONABLELOBBYINTERPRETEDNAMELEN ];\n\t\tInterpretLobbyNumber( szLobbyName, iLobby );\n\t\tszMess = new char[ strlen( TXT_WOL_YOULEFTLOBBY ) + REASONABLELOBBYINTERPRETEDNAMELEN + 10 ];\n\t\tsprintf( szMess, TXT_WOL_YOULEFTLOBBY, szLobbyName );\n\t}\n\tPrintMessage( szMess, WOLCOLORREMAP_LOCALMACHINEMESS );\n\tdelete [] szMess;\n\n\t*szChannelNameCurrent = 0;\n\tCurrentLevel = WOL_LEVEL_INVALID;\n\n\tSound_Effect( WOLSOUND_EXITCHAN );\n}\n\n//***********************************************************************************************\nbool WolapiObject::ExitChatChannelForGameChannel()\n{\n\t//\tWe are about to try and join/create a game channel, and are currently in a chat channel.\n\n\t//\tSave this channel name, so we can come back to it if game channel join/create fails.\n\tstrcpy( szChannelReturnOnGameEnterFail, szChannelNameCurrent );\n\n\tif( !ChannelLeave() )\n\t{\n\t\tGenericErrorMessage();\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n//***********************************************************************************************\nbool WolapiObject::OnEnteringGameChannel( const char* szChannelName, bool bICreatedChannel, \n\t\t\t\t\t\t\t\t\t\t\tconst CREATEGAMEINFO& CreateGameInfo )\n{\n\t//\tCalled when a game channel has been successfully joined, while still in chat dialog,\n\t//\tbefore game dialog has been created.\n\t//\tCreateGameInfo is copied to GameInfoCurrent, so that we know what kind of a game we're in during setup.\n\n//\tdebugprint( \"*** OnEnteringGameChannel() - %s\\n\", szChannelName );\n\n\tCurrentLevel = WOL_LEVEL_INGAMECHANNEL;\n\tstrcpy( szChannelNameCurrent, szChannelName );\n\n\tbChannelOwner = bICreatedChannel;\n//\tGameKindCurrent = GameKind;\n\tGameInfoCurrent = CreateGameInfo;\n\tstrcpy( GameInfoCurrent.szPassword, CreateGameInfo.szPassword );\n\n\t//\tRemove shared buttons from wolchat's command list.\n\tpShpBtnDiscon->Zap();\n\tpShpBtnLeave->Zap();\n\tpShpBtnRefresh->Zap();\n\tpShpBtnSquelch->Zap();\n\tpShpBtnBan->Zap();\n\tpShpBtnKick->Zap();\n\tpShpBtnFindpage->Zap();\n\tpShpBtnOptions->Zap();\n\tpShpBtnLadder->Zap();\n\tpShpBtnHelp->Zap();\n\n\t//\tSet wol buttons enabled/disabled.\n\tpShpBtnLeave->Enable();\n\tpShpBtnRefresh->Disable();\n\tpShpBtnSquelch->Enable();\n\tif( bChannelOwner )\n\t{\n\t\tpShpBtnBan->Enable();\n\t\tpShpBtnKick->Enable();\n\t}\n\telse\n\t{\n\t\tpShpBtnBan->Disable();\n\t\tpShpBtnKick->Disable();\n\t}\n\n\tif( CreateGameInfo.GameKind == CREATEGAMEINFO::AMGAME )\n\t{\n\t\tif( bShowRankRA )\n\t\t{\n\t\t\t//\tSwitch to \"show AM rankings\" mode.\n\t\t\tbShowRankRA = false;\n\t\t\tbMyRecordUpdated = true;\n\t\t\tbShowRankUpdated = true;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif( !bShowRankRA )\n\t\t{\n\t\t\t//\tSwitch to \"show RA rankings\" mode.\n\t\t\tbShowRankRA = true;\n\t\t\tbMyRecordUpdated = true;\n\t\t\tbShowRankUpdated = true;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n//***********************************************************************************************\nbool WolapiObject::OnEnteringGameSetup()\n{\n\t//\tCalled when entering the game setup screen. Controls are initialized. OnEnteringGameChannel\n\t//\thas just been called earlier.\n\n\t//\tReturns false only if we find there is not host - he must have simultaneously left.\n\n//\t//\tBlock until we have a userlist.\t\t- Not necessary - always comes immediately following OnJoin.\n//\tif( !UserList() )\n//\t\treturn false;\n\n\t//\tRequest ladders.\n\tRequestLadders( NULL );\n\n\t//\tRequest IP addresses.\n\tRequestIPs( NULL );\n\n\t//\tSet users list.\n\tif( !ListChannelUsers() )\n\t{\n\t\t//\tNo host was found currently in channel!\n\t\treturn false;\n\t}\n\n\tif( !pGSupDlg->bHost )\n\t{\n\t\tchar* szMess = new char[ strlen( TXT_WOL_YOUJOINEDGAME ) + WOL_NAME_LEN_MAX + 5 ];\n\t\tchar szHostName[ WOL_NAME_LEN_MAX ];\n\t\tHostNameFromGameChannelName( szHostName, szChannelNameCurrent );\n\t\tsprintf( szMess, TXT_WOL_YOUJOINEDGAME, szHostName );\n\t\tPrintMessage( szMess, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\tdelete [] szMess;\n\t}\n\telse\n\t\tPrintMessage( TXT_WOL_YOUCREATEDGAME, WOLCOLORREMAP_LOCALMACHINEMESS );\n\n\treturn true;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::OnFailedToEnterGameChannel()\n{\n\tif( *szChannelReturnOnGameEnterFail == 0 )\n\t\treturn;\n\n\t//\tThis is called when we fail to join/create a game channel.\n\t*szChannelNameCurrent = 0;\n\n\t//\tBecause we don't save the channel key as well, assume the usual lobby password. If we fail, we'll return to top level.\n\tHRESULT hRes = ChannelJoin( szChannelReturnOnGameEnterFail, LOBBYPASSWORD );\n\tswitch( hRes )\n\t{\n\tcase S_OK:\n\t\tOnEnteringChatChannel( szChannelReturnOnGameEnterFail, false, iChannelLobbyNumber( (unsigned char*)szChannelReturnOnGameEnterFail ) );\n\t\tbreak;\n\tdefault:\n\t\t//\tChannelJoin returned fail value.\n\t\t//\t(Now only applies if you could ever enter a game channel from a non-lobby.)\n\t\t//\tThere is the possibility that the channel we were in disappeared in the instant between leaving it and\n\t\t//\tfailing to join the game channel. <sigh> Or, the channel has a password, that we didn't record. In either\n\t\t//\tcase, go back to the top level.\n\t\tGenericErrorMessage();\n\t\tEnterLevel_Top();\n\t}\n}\n\n//***********************************************************************************************\nvoid WolapiObject::OnExitingGameChannel()\n{\n\t//\tThis is called after we leave a game channel, while still in the game setup dialog.\n\n\t//\tRemove shared buttons from wolgsup's command list.\n\tpShpBtnDiscon->Zap();\n\tpShpBtnLeave->Zap();\n\tpShpBtnRefresh->Zap();\n\tpShpBtnSquelch->Zap();\n\tpShpBtnBan->Zap();\n\tpShpBtnKick->Zap();\n\tpShpBtnFindpage->Zap();\n\tpShpBtnOptions->Zap();\n\tpShpBtnLadder->Zap();\n\tpShpBtnHelp->Zap();\n\n\tCurrentLevel = WOL_LEVEL_INVALID;\n\t*szChannelNameCurrent = 0;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::RejoinLobbyAfterGame()\n{\n\t//\tCalled to rejoin lobby after EITHER a game, or the game setup dialog.\n//debugprint( \"RejoinLobbyAfterGame, iLobbyReturnAfterGame is %i\\n\", iLobbyReturnAfterGame );\n\n\tif( iLobbyReturnAfterGame == -1 )\n\t{\n\t\t//\tWill never happen presumably, if games are always entered via a lobby chat channel.\n\t\t//\tWe will naturally reenter the top level.\n\t}\n\telse\n\t{\n\t\tchar szChannelToJoin[ WOL_CHANNAME_LEN_MAX ];\n\t\t//sprintf( szChannelToJoin, \"Lob_%i_%i\", GAME_TYPE, iLobbyReturnAfterGame );\n\t\tsprintf( szChannelToJoin, \"%s%i\", LOB_PREFIX, iLobbyReturnAfterGame );\n//debugprint( \"RejoinLobbyAfterGame, channel is %s\\n\", szChannelToJoin );\n\n\t\tHRESULT hRes = ChannelJoin( szChannelToJoin, LOBBYPASSWORD );\n\t\tswitch( hRes )\n\t\t{\n\t\tcase S_OK:\n\t\t\t//OnEnteringChatChannel( szChannelToJoin, false );\t\tDone automatically now in wol_chat.\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t//\tSomething went wrong when trying to rejoin the lobby we were in.\n\t\t\t//\tWe'll go back to the top level instead, which happens automatically if we do this...\n\t\t\tiLobbyReturnAfterGame = -1;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n//***********************************************************************************************\nbool WolapiObject::RequestLadders( const char* szName )\n{\n\t//\tIf szName is NULL, calls RequestLadderList() until all ladder structs for all users in pChatSink's current \n\t//\tlist have been asked for. Does not wait for results - these come in asynchronously. The previous list is\n\t//\terased before new results come in.\n\t//\tIf szName is valid, asks for specific name only. Result is appended to current ladder list.\n\t//\tThis function does not block.\n\n\tif( szName && *szName )\n\t{\n//\t\tdebugprint( \"RequestLadderList( %s )\\n\", szName );\n\t\tif( !SUCCEEDED( pNetUtil->RequestLadderList( szLadderServerHost, iLadderServerPort, szName, LADDER_CODE_RA, -1, 0, 0 ) ) )\n\t\t{\n//\t\t\tdebugprint( \"RequestLadderList() call failed\\n\" );\n\t\t\treturn false;\n\t\t}\n\t\tif( !SUCCEEDED( pNetUtil->RequestLadderList( szLadderServerHost, iLadderServerPort, szName, LADDER_CODE_AM, -1, 0, 0 ) ) )\n\t\t{\n//\t\t\tdebugprint( \"RequestLadderList() call failed\\n\" );\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\tchar szNames[ ( WOL_NAME_LEN_MAX + 1 ) * 30 ];\t\t\t//\tNeal says max is actually 25 names requested at once. Do 24...\n\n\tpNetUtilSink->DeleteLadderList();\n\n\t//\tDo not request more than this number of times, to prevent overloads to ladder server.\n\t//\tIf we have that many people in the channel, forget about doing ladders for all of them.\n\t//\tProbably this will never come into play (except while testing), because lobbies will be limited in # of users.\n\tint iCallLimit = 4;\n\n\tUser* pUser = pChatSink->pUserList;\n\twhile( pUser )\n\t{\n\t\t//\tReset names string.\n\t\t*szNames = 0;\n\t\t//\tGet 24 users from list and add names to string.\n\t\tfor( int i = 0; i != 24; ++i )\n\t\t{\n\t\t\tstrcat( szNames, (char*)pUser->name );\n\t\t\tstrcat( szNames, \":\" );\n\t\t\tpUser = pUser->next;\n\t\t\tif( !pUser )\n\t\t\t\tbreak;\n\t\t}\n\t\t//\tRemove last colon.\n\t\tszNames[ strlen( szNames ) - 1 ] = 0;\n\n//\t\tdebugprint( \"RequestLadderList( %s )\\n\", szNames );\n\t\tif( !SUCCEEDED( pNetUtil->RequestLadderList( szLadderServerHost, iLadderServerPort, szNames, LADDER_CODE_RA, -1, 0, 0 ) ) )\n\t\t{\n//\t\t\tdebugprint( \"RequestLadderList() call failed\\n\" );\n\t\t\treturn false;\n\t\t}\n\t\tif( !SUCCEEDED( pNetUtil->RequestLadderList( szLadderServerHost, iLadderServerPort, szNames, LADDER_CODE_AM, -1, 0, 0 ) ) )\n\t\t{\n//\t\t\tdebugprint( \"RequestLadderList() call failed\\n\" );\n\t\t\treturn false;\n\t\t}\n\t\tif( --iCallLimit == 0 )\n\t\t\treturn false;\n\t}\n\treturn true;\n}\n\n//***********************************************************************************************\nbool WolapiObject::RequestIPs( const char* szName )\n{\n\t//\tIf szName is NULL, calls RequestUserIP() until IPs for all users in pChatSink's current \n\t//\tlist have been asked for. Does not wait for results - these come in asynchronously. The previous list is\n\t//\terased before new results come in.\n\t//\tIf szName is valid, asks for specific name only. Result is appended to current IP list.\n\t//\tThis function does not block.\n\n\tif( szName && *szName )\n\t{\n\t\tUser user;\n\t\tstrcpy( (char*)user.name, szName );\n//\t\tdebugprint( \"RequestUserIP( %s )\\n\", szName );\n\t\tif( !SUCCEEDED( pChat->RequestUserIP( &user ) ) )\n\t\t{\n//\t\t\tdebugprint( \"RequestUserIP() call failed\\n\" );\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t//\tDo all users in current chatsink list.\n\n\tpChatSink->DeleteUserIPList();\t//\tClear old user IPs. (To keep searches fast, if we go in and out of game channels a lot.)\n\n\tUser* pUser = pChatSink->pUserList;\n\twhile( pUser )\n\t{\n\t\tif( !( pUser->flags & CHAT_USER_MYSELF ) )\n\t\t{\n\t\t\tif( !SUCCEEDED( pChat->RequestUserIP( pUser ) ) )\n\t\t\t{\n//\t\t\t\tdebugprint( \"RequestUserIP() call failed\\n\" );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\tpUser = pUser->next;\n\t}\n\treturn true;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::SaveChat()\n{\n\t//\tBasically, a big hack to avoiding restructuring things so that the dialogs are persistent\n\t//\tobjects. Save the contents of the chat list in the chat dialog so that we can refresh it\n\t//\tafter returning from the game setup dialog (if necessary).\n\t//\tThis turns out to be the easiest and most straightforward way to implement this.\n\tpChatSaveLast = pChatSaveList = NULL;\n\tCHATSAVE* pChatSaveNew;\n\n\tfor( int i = 0; i != pILChat->Count(); i++ )\n\t{\n\t\tpChatSaveNew = new CHATSAVE;\n\t\tconst char* szItem = pILChat->Get_Item( i );\n\t\tif( strlen( szItem ) < SAVECHATWIDTH )\n\t\t\tstrcpy( pChatSaveNew->szText, szItem );\n\t\tconst IconList_ItemExtras* pItemExtras = pILChat->Get_ItemExtras( i );\n\t\tpChatSaveNew->ItemExtras.pColorRemap = pItemExtras->pColorRemap;\t\t\t\n\t\tpChatSaveNew->next = NULL;\n\n\t\tif( pChatSaveLast )\n\t\t\tpChatSaveLast->next = pChatSaveNew;\n\t\telse\n\t\t\tpChatSaveList = pChatSaveNew;\n\t\tpChatSaveLast = pChatSaveNew;\n\t}\n}\n\n//***********************************************************************************************\nvoid WolapiObject::RestoreChat()\n{\n\t//\tSee SaveChat()...\n\tCHATSAVE* pChatSave = pChatSaveList;\n\twhile( pChatSave )\n\t{\n\t\tPrintMessage( pChatSave->szText, pChatSave->ItemExtras.pColorRemap );\n\t\tpChatSave = pChatSave->next;\n\t}\n}\n\n//***********************************************************************************************\nvoid WolapiObject::AddHostLeftMessageToSavedChat( const char* szName )\n{\n\tCHATSAVE* pChatSaveNew;\n\tpChatSaveNew = new CHATSAVE;\n\tsprintf( pChatSaveNew->szText, TXT_WOL_HOSTLEFTGAME, szName );\n\tpChatSaveNew->ItemExtras.pColorRemap = &ColorRemaps[ WOLCOLORREMAP_LOCALMACHINEMESS ];\n\tpChatSaveNew->next = NULL;\n\tif( pChatSaveLast )\n\t\tpChatSaveLast->next = pChatSaveNew;\n\telse\n\t\tpChatSaveList = pChatSaveNew;\n\tpChatSaveLast = pChatSaveNew;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::AddMessageToSavedChat( const char* szMessage )\n{\n\tCHATSAVE* pChatSaveNew;\n\tpChatSaveNew = new CHATSAVE;\n\tstrcpy( pChatSaveNew->szText, szMessage );\n\tpChatSaveNew->ItemExtras.pColorRemap = &ColorRemaps[ WOLCOLORREMAP_LOCALMACHINEMESS ];\n\tpChatSaveNew->next = NULL;\n\tif( pChatSaveLast )\n\t\tpChatSaveLast->next = pChatSaveNew;\n\telse\n\t\tpChatSaveList = pChatSaveNew;\n\tpChatSaveLast = pChatSaveNew;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::DeleteSavedChat()\n{\n\t//\tSee SaveChat()...\n\tCHATSAVE* pChatSaveNext;\n\twhile( pChatSaveList )\n\t{\n\t\tpChatSaveNext = pChatSaveList->next;\n\t\tdelete pChatSaveList;\n\t\tpChatSaveList = pChatSaveNext;\n\t}\n}\n\n//***********************************************************************************************\nvoid WolapiObject::GenericErrorMessage()\n{\n\t//\tDisplays generic \"something bad happened\" error message.\n\tbPump_In_Call_Back = true;\n\tWWMessageBox().Process( TXT_WOL_ERRORMESSAGE );\n\tbPump_In_Call_Back = false;\n}\n\n//***********************************************************************************************\nbool WolapiObject::GetNameOfBeginningLobby( char* szNameToSet )\n{\n\t//\tChecks for game lobbies, sets szNameToSet to the channel name that the new user should enter and returns true if succeeds.\n\tif( !GetLobbyChannels() )\n\t\treturn false;\n\n\t//\tChatsink should now have a list of lobbies.\n\tint iCount = 0;\n\tChannel* pChannel = pChatSink->pChannelList;\n\tif( !pChannel )\n\t\t//\tList is empty.\n\t\treturn false;\n\n\t//\tReturn the name of the first lobby with less than 50 users.\n\twhile( pChannel )\n\t{\n\t\tif( pChannel->currentUsers < 50 )\n\t\t{\n\t\t\tstrcpy( szNameToSet, (char*)pChannel->name );\n\t\t\treturn true;\n\t\t}\n\t\t++iCount;\n\t\tpChannel = pChannel->next;\n\t}\n\n\t//\tAll lobbies have 50 or more users. So just choose a random one.\n\tint iChoice = ( rand() % iCount );\n\tpChannel = pChatSink->pChannelList;\n\tfor( int i = 0; i != iChoice; i++ )\n\t\tpChannel = pChannel->next;\n\n\tstrcpy( szNameToSet, (char*)pChannel->name );\n\n\treturn true;\n}\n\n//***********************************************************************************************\nbool WolapiObject::GetLobbyChannels()\n{\n\t//\tModal version of UpdateChannels, for fetching lobby names.\n\n//\t//\tReturns false upon total failure.\tajxxx do same for other calls\n//\tWWMessageBox().Process( TXT_WOL_WAIT, TXT_NONE );\n\n\tpChatSink->bRequestChannelListForLobbiesWait = true;\n\tpChatSink->ChannelFilter = CHANNELFILTER_LOBBIES;\n\n//\tdebugprint( \"RequestChannelList() for lobbies\\n\" );\n\tif( !SUCCEEDED( pChat->RequestChannelList( 0, false ) ) )\n\t{\n//\t\tdebugprint( \"RequestChannelList() call failed\\n\" );\n\t\treturn false;\n\t}\n\n\tDWORD dwTimeStart = timeGetTime();\n\tDWORD dwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\twhile( pChatSink->bRequestChannelListForLobbiesWait && timeGetTime() - dwTimeStart < EMERGENCY_TIMEOUT )\n\t{\n\t\twhile( timeGetTime() < dwTimeNextPump )\n\t\t\tCall_Back();\n\t\tpChat->PumpMessages();\n\t\tdwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\t}\n\n\tif( pChatSink->bRequestChannelListForLobbiesWait )\n\t\treturn false;\n\n\treturn true;\n}\n\n//***********************************************************************************************\nconst char* WolapiObject::pGameHostName()\n{\n\t//\tReturns a POINTER (careful - temporary!) to the name of the creator of the game channel we're in, or null.\n\t//\tUses players' list as its means of reference.\n\tif( pILPlayers )\n\t{\n\t\tfor( int i = 0; i != pILPlayers->Count(); i++ )\n\t\t{\n\t\t\tUser* pUser = (User*)pILPlayers->Get_Item_ExtraDataPtr( i );\n\t\t\tif( pUser && pUser->flags & CHAT_USER_CHANNELOWNER )\n\t\t\t\treturn (char*)pUser->name;\n\t\t}\n\t}\n\treturn NULL;\n}\n\n//***********************************************************************************************\nUser* WolapiObject::pGameHost()\n{\n\t//\tReturns a POINTER (careful - temporary!) to the creator of the game channel we're in, or null.\n\t//\tUses players' list as its means of reference.\n\tif( pILPlayers )\n\t{\n\t\tfor( int i = 0; i != pILPlayers->Count(); i++ )\n\t\t{\n\t\t\tUser* pUser = (User*)pILPlayers->Get_Item_ExtraDataPtr( i );\n\t\t\tif( pUser && pUser->flags & CHAT_USER_CHANNELOWNER )\n\t\t\t\treturn pUser;\n\t\t}\n\t}\n\treturn NULL;\n}\n\n//***********************************************************************************************\nbool WolapiObject::SendGameOpt( const char* szSend, User* pUserPriv )\n{\n\t//\tUsed during game setup to send public or private game options string.\n\t//\tIf pUserPriv is NULL, message is public, else private to pUserPriv.\n\tif( !pUserPriv )\n\t{\n//\t\tdebugprint( \"Send public game opt: '%s'\\n\", szSend );\n\t\tif( !SUCCEEDED( pChat->RequestPublicGameOptions( szSend ) ) )\n\t\t{\n//\t\t\tdebugprint( \"RequestPublicGameOptions() call failed\\n\" );\n\t\t\treturn false;\n\t\t}\n\t}\n\telse\n\t{\n//\t\tdebugprint( \"Send private game opt to %s: '%s'\\n\", (char*)pUserPriv->name, szSend );\n\t\tif( !SUCCEEDED( pChat->RequestPrivateGameOptions( pUserPriv, szSend ) ) )\n\t\t{\n//\t\t\tdebugprint( \"RequestPrivateGameOptions() call failed\\n\" );\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n//***********************************************************************************************\nbool WolapiObject::RequestGameStart()\n{\n\t//\tHost is starting a game.\n\n/*\n\t//\tBlock any users that join the channel in the next microsecond from becoming involved, and\n\t//\tblock any users that leave from being recognized as having left.\n\t//what if someone leaves?\n\t//\tThis is done to preserve the integrity of the ChatSink's user list\n\tpWO->pChatSink->bIgnoreJoin = true;\n*/\n\tpChatSink->bRequestGameStartWait = true;\n\n//\tdebugprint( \"RequestGameStart()\\n\" );\n\tif( !SUCCEEDED( pChat->RequestGameStart( pChatSink->pUserList ) ) )\n\t{\n//\t\tdebugprint( \"RequestGameStart() call failed\\n\" );\n\t\treturn false;\n\t}\n\n\tDWORD dwTimeStart = timeGetTime();\n\tDWORD dwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\twhile( pChatSink->bRequestGameStartWait && timeGetTime() - dwTimeStart < EMERGENCY_TIMEOUT )\n\t{\n\t\twhile( timeGetTime() < dwTimeNextPump )\n\t\t\tCall_Back();\n\t\tpChat->PumpMessages();\n\t\tdwTimeNextPump = timeGetTime() + PUMPSLEEPDURATION;\n\t}\n\n\tif( pChatSink->bRequestGameStartWait )\n\t{\n//\t\tdebugprint( \"WolapiObject::RequestGameStart returning false\\n\" );\n\t\tpChatSink->bRequestGameStartWait = false;\n\t\treturn false;\n\t}\n\n//\tdebugprint( \"WolapiObject::RequestGameStart returning true\\n\" );\n\treturn true;\n}\n\n//***********************************************************************************************\nbool WolapiObject::SendGo( const char* szSend )\n{\n\t//\tSend a \"GO\" message to all players included in the list that came back from OnGameStart.\n\t//\t(Don't just broadcast it. We don't want to include any users that may have joined the channel\n\t//\tin the last microsecond.)\n//\tdebugprint( \"SendGo()\\n\" );\n\n\tUser* pUser = pChatSink->pGameUserList;\n\n\twhile( pUser )\n\t{\n//\t\tif( !( pUser->flags & CHAT_USER_MYSELF ) )\t\t\tMethod changed. I now wait for go message to bounce back to me.\n//\t\t{\n//\t\t\tdebugprint( \"Send private game opt to %s: '%s'\\n\", (char*)pUser->name, szSend );\n\t\t\tif( !SUCCEEDED( pChat->RequestPrivateGameOptions( pUser, szSend ) ) )\n\t\t\t{\n//\t\t\t\tdebugprint( \"RequestPrivateGameOptions() call failed\\n\" );\n\t\t\t\treturn false;\n\t\t\t}\n//\t\t}\n\t\tpUser = pUser->next;\n\t}\n\treturn true;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::Init_DisconnectPinging()\n{\n\t//\tSets us up to begin \"disconnect pinging\" - the pinging that occurs when connection is broken\n\t//\tduring a tournament game. The idea is to try and figure out who is responsible for the connection\n\t//\tgoing down. We do this by repeatedly pinging the opponent and the game results server. The number\n\t//\tof successful pings is sent in the game results package.\n\tiDisconnectPingCurrent = 0;\n\tfor( int i = 0; i != DISCONNECT_PING_COUNT; ++i )\n\t{\n\t\tDisconnectPingResult_Server[ i ] = PING_UNSTARTED;\n\t\tDisconnectPingResult_Opponent[ i ] = PING_UNSTARTED;\n\t}\n\tbDisconnectPingingCompleted = false;\n\tbDoingDisconnectPinging = true;\n}\n\n//***********************************************************************************************\nbool WolapiObject::Pump_DisconnectPinging()\n{\n\t//\tCalled repeatedly and continuously when it seems a tournament game connection with the opponent\n\t//\thas been broken. Does PumpMessages() and requests new pings when previous results have been received.\n\t//\tReturns true when the required number of pings have been completed.\n\n\tif( ::timeGetTime() > dwTimeNextWolapiPump )\n\t{\n\t\tpChat->PumpMessages();\n\t\tpNetUtil->PumpMessages();\n\t\tdwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT;\n\t}\n\n\tswitch( DisconnectPingResult_Server[ iDisconnectPingCurrent ] )\n\t{\n\tcase PING_UNSTARTED:\n\t\t//\tPings have yet to be requested.\n\t\t//\tPing game results server.\n\t\tint iUnused;\n\t\tif( *szGameResServerHost1 )\n\t\t{\n//\t\t\tdebugprint( \"RequestPing ( gameres server )\\n\" );\n\t\t\tif( pNetUtil->RequestPing( szGameResServerHost1, 1000, &iUnused ) != S_OK )\n\t\t\t{\n//\t\t\t\tdebugprint( \"RequestPing() ( gameres server ) failed\\n\" );\n\t\t\t\tDisconnectPingResult_Server[ iDisconnectPingCurrent ] = PING_BAD;\n\t\t\t}\n\t\t\tDisconnectPingResult_Server[ iDisconnectPingCurrent ] = PING_WAITING;\n\t\t}\n\t\telse\n\t\t\t//\tWe never got an address for the gameresults server. Fake fail result.\n\t\t\tDisconnectPingResult_Server[ iDisconnectPingCurrent ] = PING_BAD;\n\n\t\t//\tPing opponent.\n\t\tin_addr inaddr;\n\t\tchar* szIP;\n\t\tinaddr.s_addr = TournamentOpponentIP;\n\t\tszIP = inet_ntoa( inaddr );\n//\t\tdebugprint( \"RequestPing ( opponent )\\n\" );\n\t\tif( pNetUtil->RequestPing( szIP, 1000, &iUnused ) != S_OK )\n\t\t{\n//\t\t\tdebugprint( \"RequestPing() ( opponent ) failed\\n\" );\n\t\t\tDisconnectPingResult_Opponent[ iDisconnectPingCurrent ] = PING_BAD;\n\t\t}\n\t\telse\n\t\t\tDisconnectPingResult_Opponent[ iDisconnectPingCurrent ] = PING_WAITING;\n\t\tbreak;\n\tcase PING_WAITING:\n\t\t//\tPing results still pending. (Callback will set vars when results arrive.)\n\t\tbreak;\n\tdefault:\n\t\t//\tPing result for server is in.\n\t\tif( DisconnectPingResult_Opponent[ iDisconnectPingCurrent ] == PING_WAITING )\n\t\t\tbreak;\n\t\t//\tBoth results are in. Begin new ping, or end disconnect pinging.\n\t\tiDisconnectPingCurrent++;\n\t\tif( iDisconnectPingCurrent == DISCONNECT_PING_COUNT )\n\t\t{\n\t\t\tbDisconnectPingingCompleted = true;\n\t\t\tbDoingDisconnectPinging = false;\n\t\t\treturn true;\n\t\t}\n\t\tbreak;\n\t}\n\treturn false;\n}\n\n//***********************************************************************************************\nvoid WolapiObject::DisconnectPingResultsString( char* szStringToSet )\n{\n\tint iGoodServerPings = 0;\n\tint iGoodPlayerPings = 0;\n\tfor( int i = 0; i < DISCONNECT_PING_COUNT; ++i )\n\t{\n\t\tif( DisconnectPingResult_Server[ i ] == PING_GOOD )\t\t\t++iGoodServerPings;\n\t\tif( DisconnectPingResult_Opponent[ i ] == PING_GOOD )\t\t++iGoodPlayerPings;\n\t}\n\n\tsprintf( szStringToSet, \"%1u/%1u %1u/%1u\", iGoodServerPings, DISCONNECT_PING_COUNT, iGoodPlayerPings, DISCONNECT_PING_COUNT );\n}\n\n//***********************************************************************************************\nvoid WolapiObject::SetOptionDefaults()\n{\n\t//\tGet stored defaults for options.\n\tHKEY hKey;\n\tif( RegOpenKeyEx( HKEY_LOCAL_MACHINE, Game_Registry_Key(), 0, KEY_READ, &hKey ) == ERROR_SUCCESS )\n\t{\n\t\tDWORD dwValue;\n\t\tDWORD dwBufSize = sizeof( DWORD );\n\t\tif( RegQueryValueEx( hKey, \"WOLAPI Find Enabled\", 0, NULL, (LPBYTE)&dwValue, &dwBufSize ) != ERROR_SUCCESS )\n\t\t\tbFindEnabled = true;\n\t\telse\n\t\t\tbFindEnabled = (bool)dwValue;\n\t\tif( RegQueryValueEx( hKey, \"WOLAPI Page Enabled\", 0, NULL, (LPBYTE)&dwValue, &dwBufSize ) != ERROR_SUCCESS )\n\t\t\tbPageEnabled = true;\n\t\telse\n\t\t\tbPageEnabled = (bool)dwValue;\n\t\tif( RegQueryValueEx( hKey, \"WOLAPI Lang Filter\", 0, NULL, (LPBYTE)&dwValue, &dwBufSize ) != ERROR_SUCCESS )\n\t\t\tbLangFilter = true;\n\t\telse\n\t\t\tbLangFilter = (bool)dwValue;\n\t\tif( RegQueryValueEx( hKey, \"WOLAPI Show All Games\", 0, NULL, (LPBYTE)&dwValue, &dwBufSize ) != ERROR_SUCCESS )\n\t\t\tbAllGamesShown = true;\n\t\telse\n\t\t\tbAllGamesShown = (bool)dwValue;\n\n\t\tRegCloseKey( hKey );\n\t}\n\tpChat->SetFindPage( bFindEnabled, bPageEnabled );\n\tpChat->SetLangFilter( bLangFilter );\n}\n\n//***********************************************************************************************\nvoid WolapiObject::SetOptions( bool bEnableFind, bool bEnablePage, bool bLangFilterOn, bool bShowAllGames )\n{\n\t//\tSet options and remember them in registry.\n\n\tbFindEnabled = bEnableFind;\n\tbPageEnabled = bEnablePage;\n\tbLangFilter = bLangFilterOn;\n\tbAllGamesShown = bShowAllGames;\n\n\tHKEY hKey;\n\tif( RegOpenKeyEx( HKEY_LOCAL_MACHINE, Game_Registry_Key(), 0, KEY_WRITE, &hKey ) == ERROR_SUCCESS )\n\t{\n\t\tDWORD dwValue = bFindEnabled ? 1 : 0;\n\t\tRegSetValueEx( hKey, \"WOLAPI Find Enabled\", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof( dwValue ) );\n\t\tdwValue = bPageEnabled ? 1 : 0;\n\t\tRegSetValueEx( hKey, \"WOLAPI Page Enabled\", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof( dwValue ) );\n\t\tdwValue = bLangFilter ? 1 : 0;\n\t\tRegSetValueEx( hKey, \"WOLAPI Lang Filter\", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof( dwValue ) );\n\t\tdwValue = bAllGamesShown ? 1 : 0;\n\t\tRegSetValueEx( hKey, \"WOLAPI Show All Games\", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof( dwValue ) );\n\n\t\tRegCloseKey( hKey );\n\t}\n\tpChat->SetFindPage( bFindEnabled, bPageEnabled );\n\tpChat->SetLangFilter( bLangFilter );\n}\n\n//***********************************************************************************************\nHPALETTE GetCurrentScreenPalette()\n{\n\t//\tGet the palette of the current screen.\n\t//\tReturns 0 if can't get palette.\n\t//\tRemember to DeleteObject the HPALETTE if non-zero.\n\tGraphicViewPortClass draw_window(\tLogicPage->Get_Graphic_Buffer(),\n\t\t\t\t\t\t\t\t\t\tWindowList[WINDOW_MAIN][WINDOWX] + LogicPage->Get_XPos(),\n\t\t\t\t\t\t\t\t\t\tWindowList[WINDOW_MAIN][WINDOWY] + LogicPage->Get_YPos(),\n\t\t\t\t\t\t\t\t\t\tWindowList[WINDOW_MAIN][WINDOWWIDTH],\n\t\t\t\t\t\t\t\t\t\tWindowList[WINDOW_MAIN][WINDOWHEIGHT] );\n\tLPDIRECTDRAWSURFACE lpDDS = draw_window.Get_Graphic_Buffer()->Get_DD_Surface();\n\tLPDIRECTDRAWPALETTE lpDDP;\n\tHPALETTE hPal = 0;\n\tif( lpDDS->GetPalette( &lpDDP ) == DD_OK )\n\t{\n\t\tPALETTEENTRY pe[256];\n\t\tif( lpDDP->GetEntries( 0, 0, 256, pe ) == DD_OK )\n\t\t{\n\t\t\tLOGPALETTE* pLogPal = (LOGPALETTE*)new char[ sizeof( LOGPALETTE ) + sizeof( PALETTEENTRY ) * 255 ];\n\t\t\tpLogPal->palVersion = 0x300;\n\t\t\tpLogPal->palNumEntries = 256;\n\t\t\tfor( int i = 0; i != 256; i++ )\n\t\t\t{\n\t\t\t\tpLogPal->palPalEntry[i].peRed = pe[i].peRed;\n\t\t\t\tpLogPal->palPalEntry[i].peGreen = pe[i].peGreen;\n\t\t\t\tpLogPal->palPalEntry[i].peBlue = pe[i].peBlue;\n\t\t\t\tpLogPal->palPalEntry[i].peFlags = 0;\n//\t\t\t\tdebugprint( \"DD Palette %03u: %03u, %03u, %03u\\n\", i, pe[i].peRed, pe[i].peGreen, pe[i].peBlue );\n\t\t\t}\n\t\t\thPal = CreatePalette( pLogPal );\n\t\t\tdelete [] pLogPal;\n\t\t}\n//\t\telse\n//\t\t\tdebugprint( \"DD GetEntries failed.\\n\" );\n\t}\n//\telse\n//\t\tdebugprint( \"DD GetPalette failed.\\n\" );\n\t\n\treturn hPal;\n}\n\n//***********************************************************************************************\nvoid RemapDIBToPalette( HPALETTE hPal, const char* pDIB )\t\t//\tNote: pDIB is treated as non-const.\n{\n\t//\tConverts pDIB's actual pixel data to proper values for a different palette (hPal).\n\t//\tObeys convention that index 0 in the DIB's palette should map to transparent. For our purposes, make it black.\n\t\n\t//\tSet the values of the qNewPalette array to hold the new destination palette index we want \n\t//\ta bmp palette entry to map to.\n\tunsigned char qNewPalette[ 256 ];\n\n\tLPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)pDIB;\n\n\tRGBQUAD* pRGBEntry = (RGBQUAD*)( (char*)lpbi + lpbi->biSize );\t\t//\tThis now points to the first entry in the bmp's palette table.\n\n//\tdebugprint( \"Starting rgbquads at %i\\n\", pRGBEntry );\n\n\t//\tIndex zero is supposed to be transparent. In our case, that means make it black.\n\tqNewPalette[0] = GetNearestPaletteIndex( hPal, RGB( 0, 0, 0 ) );\n\tpRGBEntry++;\n\n\tfor( int i = 1; i != 256; i++ )\n\t{\n\t\tqNewPalette[i] = GetNearestPaletteIndex( hPal, RGB( pRGBEntry->rgbRed, pRGBEntry->rgbGreen, pRGBEntry->rgbBlue ) );\n//\t\tif( iIndex == 1 )\n//\t\t\tdebugprint( \"Remapping bmp %03u to new %03u\\n\", i, qNewPalette[i] );\n\t\tpRGBEntry++;\n\t}\n\n\t//\tConvert the data to values that match game palette.\n\tint iWidth = DIBWidth( pDIB );\n\tint iHeight = DIBHeight( pDIB );\n\tint iSrcPitch = ( iWidth + 3 ) & ~3;\n\tint iLength = iSrcPitch * iHeight;\n\tunsigned char* pBits = (unsigned char*)FindDIBBits( pDIB );\n//\tdebugprint( \"First Byte value %03u will become %03u\\n\", *pBits, qNewPalette[ *pBits ] );\n\tfor( i = 0; i != iLength; i++ )\n\t{\n\t\t*pBits++ = qNewPalette[ *pBits ];\n\t}\n}\n\n/*\n//***********************************************************************************************\nchar* LoadFileIntoMemory( const char* szFileName, int& iLength )\n{\n\t//\tLoads a file into a buffer.\n\t//\tDelete[] the pointer when you're done with the buffer.\n\tHANDLE hFile;\n\thFile = CreateFile( szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\n\tif( hFile == INVALID_HANDLE_VALUE )\n\t\treturn NULL;\n\tiLength = GetFileSize( hFile, NULL );\n\tchar* pData = new char[ iLength ];\n\tDWORD dwBytesRead;\n\tReadFile( hFile, pData, iLength, &dwBytesRead, NULL );\n\tif( dwBytesRead != iLength )\n//\t\tdebugprint( \"######LoadFileIntoMemory expected %i bytes and got %i\\n\", iLength, dwBytesRead );\n\tCloseHandle( hFile );\n\treturn pData;\n}\n*/\n\n//***********************************************************************************************\nvoid HostNameFromGameChannelName( char* szNameToSet, const char* szChannelName )\n{\n\tint iApostrophe = strcspn( szChannelName, \"'\" );\n\tmemcpy( szNameToSet, szChannelName, iApostrophe );\n\tszNameToSet[ iApostrophe ] = 0;\n}\n\n#endif\n"
  },
  {
    "path": "CODE/WOLAPIOB.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifdef WOLAPI_INTEGRATION\n\n//\tWolapiOb.h\n//\tajw 07/10/98\n\n//\tClass WolapiObject is mainly a container so I can avoid globals and keep things clean.\n//\tAll WOLAPI interfacing will be done through this object. It's lifetime will begin when\n//\tAPI functions are first needed and end when we are finished with the API - this will\n//\tpresumably parallel the duration of the user's connection to WOL.\n\n#ifndef WOLAPI_H\n#define WOLAPI_H\n\n#include \"RAWolapi.h\"\n#include \"dibapi.h\"\n#include \"IconList.h\"\n\n//***********************************************************************************************\nclass IconListClass;\nclass WOL_GameSetupDialog;\nclass ToolTipClass;\n\n#define PUMPSLEEPDURATION\t300\t\t\t//\tMilliseconds between PumpMessages() calls.\n#define EMERGENCY_TIMEOUT\t40000\t\t//\tLongest we wait for a wolapi response before terminating everything.\n\n//\tMilliseconds between automatic behaviors.\n#define WOLAPIPUMPWAIT\t\t\t\t300\n#define CHANNELUPDATEWAIT\t\t\t45000\n\n#define WOL_NAME_LEN_MAX\t\t10\t\t\t//\tIncludes null-terminator.\n#define WOL_PASSWORD_LEN\t\t9\t\t\t//\tIncludes null-terminator.\n#define WOL_CHANNAME_LEN_MAX\t17\t\t\t//\tIncludes null-terminator.\n#define WOL_CHANKEY_LEN_MAX\t\t9\t\t\t//\tIncludes null-terminator.\n\n#define CHAT_USER_SQUELCHED\t\t0x0004\t\t//\tWill theoretically be added to the api and implemented.\n\n#define LOBBYPASSWORD \"not_a_valid_password\" // Password removed per Security review - LFeenanEA, 26th February 2025\n\n#define USERCANCELLED\t1\n#define PATCHDOWNLOADED\t2\n#define PATCHAVOIDED\t3\n\n//\tSpecial hidden descriptors added to channel list items.\n//\tThese serve double-duty as tooltip help text.\n#define CHANNELTYPE_TOP\t\t\t\tTXT_WOL_CHANNELTYPE_TOP\n#define CHANNELTYPE_OFFICIALCHAT\tTXT_WOL_CHANNELTYPE_OFFICIALCHAT\n#define CHANNELTYPE_USERCHAT\t\tTXT_WOL_CHANNELTYPE_USERCHAT\n#define CHANNELTYPE_GAMES\t\t\tTXT_WOL_CHANNELTYPE_GAMES\n#define CHANNELTYPE_GAMESOFTYPE     \"GamesOfType\"\t//\tNot seen.\n#define CHANNELTYPE_CHATCHANNEL\t\t\"ChatChannel\"\t//\tNot seen.\n#define CHANNELTYPE_GAMECHANNEL\t\t\"GameChannel\"\t//\tNot seen.\n#define CHANNELTYPE_LOADING\t\t\tTXT_WOL_CHANNELTYPE_LOADING\n#define CHANNELTYPE_LOBBIES\t\t\tTXT_WOL_CHANNELTYPE_LOBBIES\n#define CHANNELTYPE_LOBBYCHANNEL\t\"LobbyChannel\"\t//\tNot seen.\n\nenum WOL_LEVEL\n{\n\tWOL_LEVEL_TOP,\t\t\t\t\t//\tViewing top level menu choices.\n\tWOL_LEVEL_OFFICIALCHAT,\t\t\t//\tViewing official chat channels.\n\tWOL_LEVEL_USERCHAT,\t\t\t\t//\tViewing user chat channels.\n\tWOL_LEVEL_INCHATCHANNEL,\t\t//\tIn a chat channel.\n\tWOL_LEVEL_GAMES,\t\t\t\t//\tViewing types (skus) of games.\n\tWOL_LEVEL_GAMESOFTYPE,\t\t\t//\tViewing game channels of a type.\n\tWOL_LEVEL_INGAMECHANNEL,\t\t//\tIn a game channel.\n\tWOL_LEVEL_LOBBIES,\t\t\t\t//\tViewing the game lobbies.\n\tWOL_LEVEL_INLOBBY,\t\t\t\t//\tIn a \"lobby\" chat channel.\n\tWOL_LEVEL_INVALID\n};\n\nstruct WOL_GAMETYPEINFO\n{\n\tint\t\tiGameType;\n\tchar\tszName[128];\n\tchar\tszURL[256];\n\tHDIB\thDIB;\t\t\t\t//\tDIB handle.\n\tconst char*\tpDIB;\t\t\t\t//\tWhat you get when you GlobalLock hDIB.\n};\n\n//\tHeader values for game options messages. Note that 0 is not used!\nenum WOL_GAMEOPT\n{\n\tWOL_GAMEOPT_REQCOLOR = 1,\t//\tREQuest = guest asks game host for a color\n\tWOL_GAMEOPT_INFCOLOR,\t\t//\tINForm = game host tells guests color of a single player (not \"accept-canceling\")\n\tWOL_GAMEOPT_INFPARAMS,\t\t//\thost tells guests all common game params\n\tWOL_GAMEOPT_REQHOUSE,\t\t//\tguest tells host he's changed house (REQ because it's guest->host)\n\tWOL_GAMEOPT_INFHOUSE,\t\t//\thost tells guests about new house of a single player\n\tWOL_GAMEOPT_REQACCEPT,\t\t//\tguest tells host he accepts current params\n\tWOL_GAMEOPT_INFACCEPT,\t\t//\thost tells guests that a player accepted\n\tWOL_GAMEOPT_INFSTART,\t\t//\thost tell guests to go into wait for start mode\n\tWOL_GAMEOPT_REQSTART,\t\t//\tguest acknowledges WOL_GAMEOPT_INFSTART\n\tWOL_GAMEOPT_REQSTART_BUTNEEDSCENARIO,\t//\tguests acks WOL_GAMEOPT_INFSTART and asks for scenario download\n\tWOL_GAMEOPT_INFCANCELSTART,\t//\thost tells guests to cancel game start, as a change arrived or player joined/left\n\tWOL_GAMEOPT_INFGO,\t\t\t//\thost tells everyone to start\n\tWOL_GAMEOPT_INFNEWGUESTPLAYERINFO,\t//\thost tells new guest a lot of stuff about everyone that's in the game\n};\nenum DIBICON\n{\n\tDIBICON_OWNER,\n\tDIBICON_SQUELCH,\n\tDIBICON_LATENCY,\n\tDIBICON_ACCEPT,\n\tDIBICON_NOTACCEPT,\n\tDIBICON_USER,\n\tDIBICON_PRIVATE,\n\tDIBICON_TOURNAMENT,\n\tDIBICON_VOICE,\n};\n#define NUMDIBICONS\t\t9\n\nstruct DIBICONINFO\n{\n\tchar\t\tszFile[50];\n\tHDIB\t\thDIB;\n\tconst char*\tpDIB;\n};\n\n//\tSee SaveChat()...\n#define SAVECHATWIDTH\t150\t\t\t//\tWider than text that will fit in the chat list window.\nstruct CHATSAVE\t\t\t//\tWhat we save about each individual list item.\n{\n\tchar\t\t\t\t\tszText[ SAVECHATWIDTH + 1 ];\n\tIconList_ItemExtras\t\tItemExtras;\t\t\t//\tOnly color is used.\n\tCHATSAVE*\t\t\t\tnext;\n};\n\nstruct CREATEGAMEINFO\n{\n\tenum GAMEKIND\t\t//\tGets or'ed with lobby number in channel 'reserved' field.\n\t{\n\t\tRAGAME = 0x01000000,\n\t\tCSGAME = 0x02000000,\n\t\tAMGAME = 0x04000000,\n\t};\n\n\tbool\tbCreateGame;\t//\tTrue if user confirms game creation.\n\tint\t\tiPlayerMax;\t\t//\tNOT number of players, but maximum number allowed into game channel.\n\tint\t\tiPlayerCount;\t//\tNumber of initial human players in game. Set at game launch, used for stats.\n\tbool\tbTournament;\n\tbool\tbPrivate;\n\tGAMEKIND GameKind;\n\tchar\tszPassword[ WOL_CHANKEY_LEN_MAX ];\t\t//\tIf not blank, key for private game.\n};\n\n//***********************************************************************************************\nHPALETTE\tGetCurrentScreenPalette();\nvoid\t\tRemapDIBToPalette( HPALETTE hPal, const char* pDIB );\t\t//\tNote: pDIB is treated as non-const.\n//char*\t\tLoadFileIntoMemory( const char* szFileName, int& iLength );\n\n//***********************************************************************************************\nclass WolapiObject\n{\npublic:\n\tWolapiObject();\n\tvirtual ~WolapiObject();\n\n\tIChat*\t\t\t\t\tpChat;\n\tIDownload*\t\t\t\tpDownload;\n\tINetUtil*\t\t\t\tpNetUtil;\n\tDWORD\t\t\t\t\tdwChatAdvise;\t\t\t//\tValue that identifies the \"connection\" from chat to chatsink.\n\tDWORD\t\t\t\t\tdwDownloadAdvise;\n\tDWORD\t\t\t\t\tdwNetUtilAdvise;\n\n\tRAChatEventSink*\t\tpChatSink;\n\tRADownloadEventSink*\tpDownloadSink;\n\tRANetUtilEventSink*\t\tpNetUtilSink;\n\n\tbool\t\t\t\t\tbChatShownBefore;\n\n\tchar\t\t\t\t\tszLadderServerHost[ 150 ];\n\tint\t\t\t\t\t\tiLadderServerPort;\n\tchar\t\t\t\t\tszGameResServerHost1[ 150 ];\n\tint\t\t\t\t\t\tiGameResServerPort1;\n\tchar\t\t\t\t\tszGameResServerHost2[ 150 ];\n\tint\t\t\t\t\t\tiGameResServerPort2;\n\n\tbool\t\tbFindEnabled;\t\t//\tI have to maintain these, though wolapi should do it for me...\n\tbool\t\tbPageEnabled;\t\t//\tNote they are initialized true, as is currently the case in wol.\n\tbool\t\tbLangFilter;\t\t//\n\tbool\t\tbAllGamesShown;\n\n\tbool\t\tbEggSounds;\t\t\t//\tEaster egg related. True = user actions trigger sounds.\n\tbool\t\tbEgg8Player;\t\t//\tTrue = 8 player games can be created. This is hidden so that we don't really have to support the feature...\n\n\tWOL_LEVEL\tCurrentLevel;\n\tWOL_LEVEL\tLastUpdateChannelCallLevel;\n\tchar\t\tszMyName[WOL_NAME_LEN_MAX];\t\t//\tLocal user's name, valid while connected.\n\tchar\t\tszMyRecord[ WOL_NAME_LEN_MAX + 80 ];\n\tchar\t\tszMyRecordAM[ WOL_NAME_LEN_MAX + 80 ];\n\tbool\t\tbMyRecordUpdated;\t\t\t\t//\tTrue when szMyRecord has changed and not yet recognized by chat dialog.\n\tchar\t\tszChannelListTitle[ 100 ];\n\tbool\t\tbChannelListTitleUpdated;\n\tchar\t\tszChannelNameCurrent[WOL_CHANNAME_LEN_MAX];\n\tbool\t\tbChannelOwner;\n\tchar\t\tszChannelReturnOnGameEnterFail[WOL_CHANNAME_LEN_MAX];\n\n\tint\t\t\tiLobbyReturnAfterGame;\t\t\t//\tWhen in game channel, part of the value of the channel's 'reserved' field.\n\t\n\tbool\t\tbReturningAfterGame;\n\n\tint\t\t\tiLobbyLast;\t\t\t\t\t\t//\tNumber of last lobby we personally were in.\n\n//\tCREATEGAMEINFO::GAMEKIND GameKindCurrent;\t//\tKind of game (Red Alert, CS, AM) we are in game setup for.\n\tCREATEGAMEINFO GameInfoCurrent;\t\t\t\t//\tKind of game (Red Alert, CS, AM, tournament, private) we are in game setup for.\n\tbool\t\tbEnableNewAftermathUnits;\t\t//\tUsed to pass game parameter back to init only.\n\n\tDWORD\t\tdwTimeNextWolapiPump;\n\tDWORD\t\tdwTimeNextChannelUpdate;\n\n\tDIBICONINFO DibIconInfos[ NUMDIBICONS ];\n\n\tHRESULT\t\thresPatchResults;\t\t\t\t//\tUsed when a patch has been downloaded or cancelled.\n\n\tWOL_GameSetupDialog*\tpGSupDlg;\t\t\t//\tWhen in a game channel, setting up a game; ptr to the dialog.\n\n\tbool\t\tbInGame;\t\t\t\t//\tTrue while playing a game.\n\tbool\t\tbConnectionDown;\t\t//\tFlag used while in a game, set to true if connection goes down.\n\tbool\t\tbGameServer;\t\t\t//\tFlag used while in a game, true if game server (host).\n\t\n\tunsigned long\tTournamentOpponentIP;\t//\tValid while playing a tournament game. IP address of opponent.\n\n\tbool\t\tbPump_In_Call_Back;\t\t//\tUsed to enable PumpMessages during Call_Back(), for when we're in a modal dialog.\n\n\tbool\t\tbSelfDestruct;\t\t\t//\tIf set true, causes logout and deletion of wolapi object.\n\n\tchar\t\tszWebBrowser[ _MAX_PATH + 1 ];\n\n\t//\tFor \"disconnect pinging\".\n\tbool\t\tbDoingDisconnectPinging;\n\tbool\t\tbDisconnectPingingCompleted;\n\tint\t\t\tiDisconnectPingCurrent;\n\tDISCONNECT_PING_STATUS\tDisconnectPingResult_Server[ DISCONNECT_PING_COUNT ];\n\tDISCONNECT_PING_STATUS\tDisconnectPingResult_Opponent[ DISCONNECT_PING_COUNT ];\n\n\t//\tUsed for in-game paging and responding.\n\tchar\t\tszExternalPager[ WOL_NAME_LEN_MAX ];\t//\tLast person to page me from outside the game, or blank for none.\n\tbool\t\tbFreezeExternalPager;\n\n\tbool\t\tbShowRankRA;\t\t//\ttrue = view RA rankings, false = view AM rankings\n\tbool\t\tbShowRankUpdated;\t//\tset true when bShowRankRA value changes\n\n\t//\tStandard wol buttons.\n\tchar*\t\tpShpDiscon;\n\tchar*\t\tpShpLeave;\n\tchar*\t\tpShpRefresh;\n\tchar*\t\tpShpSquelch;\n\tchar*\t\tpShpBan;\n\tchar*\t\tpShpKick;\n\tchar*\t\tpShpFindpage;\n\tchar*\t\tpShpOptions;\n\tchar*\t\tpShpLadder;\n\tchar*\t\tpShpHelp;\n\tShapeButtonClass*\tpShpBtnDiscon;\n\tShapeButtonClass*\tpShpBtnLeave;\n\tShapeButtonClass*\tpShpBtnRefresh;\n\tShapeButtonClass*\tpShpBtnSquelch;\n\tShapeButtonClass*\tpShpBtnBan;\n\tShapeButtonClass*\tpShpBtnKick;\n\tShapeButtonClass*\tpShpBtnFindpage;\n\tShapeButtonClass*\tpShpBtnOptions;\n\tShapeButtonClass*\tpShpBtnLadder;\n\tShapeButtonClass*\tpShpBtnHelp;\n\tToolTipClass*\t\tpTTipDiscon;\n\tToolTipClass*\t\tpTTipLeave;\n\tToolTipClass*\t\tpTTipRefresh;\n\tToolTipClass*\t\tpTTipSquelch;\n\tToolTipClass*\t\tpTTipBan;\n\tToolTipClass*\t\tpTTipKick;\n\tToolTipClass*\t\tpTTipFindpage;\n\tToolTipClass*\t\tpTTipOptions;\n\tToolTipClass*\t\tpTTipLadder;\n\tToolTipClass*\t\tpTTipHelp;\n\n\tWOL_GAMETYPEINFO\t\tOldRAGameTypeInfos[ 3 ];\t//\tUsed for storing old red alert icons only.\n\npublic:\n\tbool\t\tbLoggedIn();\n\n\tvoid\t\tLinkToChatDlg( IconListClass* pILChat, IconListClass* pILChannels, IconListClass* pILUsers, StaticButtonClass* pStaticUsers );\n\tvoid\t\tClearListPtrs();\n\tvoid\t\tLinkToGameDlg( IconListClass* pILDisc, IconListClass* pILPlayers );\n\n\tvoid\t\tPrepareButtonsAndIcons();\n\n\tbool\t\tbSetupCOMStuff();\n\tvoid\t\tUnsetupCOMStuff();\n\n\tvoid\t\tPrintMessage( const char* szText, PlayerColorType iColorRemap = PCOLOR_NONE );\n\tvoid\t\tPrintMessage( const char* szText, RemapControlType* pColorRemap );\n\n\tHRESULT\t\tGetChatServer();\n\tHRESULT \tAttemptLogin( const char* szName, const char* szPass, bool bPassIsMangled );\n\tvoid\t\tLogout();\n\tbool\t\tUpdateChannels( int iChannelType, CHANNELFILTER ChannelFilter, bool bAutoping );\n\tvoid\t\tOnChannelList();\n\tvoid\t\tListChannels();\n\tHRESULT\t\tChannelJoin( const char* szChannelName, const char* szKey );\n\tHRESULT\t\tChannelJoin( Channel* pChannelToJoin );\n\tbool\t\tChannelLeave();\n//\tbool\t\tUserList();\n\tbool\t\tListChannelUsers();\n\n\tbool\t\tbItemMarkedAccepted( int iIndex );\n\tbool\t\tMarkItemAccepted( int iIndex, bool bAccept );\n\tbool\t\tbItemMarkedReadyToGo( int iIndex );\n\tvoid\t\tMarkItemReadyToGo( int iIndex, const char* szReadyState );\n\tbool\t\tbItemMarkedNeedScenario( int iIndex );\n\tvoid\t\tPullPlayerName_Into_From( char* szDest, const char* szSource );\n\tHousesType\tPullPlayerHouse_From( const char* szSource );\n\tvoid\t\tWritePlayerListItem( char* szDest, const char* szName, HousesType House );\n\n\tvoid\t\tRequestPlayerPings();\n\t\n\tvoid\t\tSendMessage( const char* szMessage, IconListClass& ILUsers, bool bAction );\n\tbool\t\tChannelCreate( const char* szChannelName, const char* szKey, bool bGame = false, int iMaxPlayers = 0, \n\t\t\t\t\t\t\t\tbool bTournament = false, int iLobby = 0, CREATEGAMEINFO::GAMEKIND GameKind = CREATEGAMEINFO::RAGAME );\n\tvoid\t\tDoFindPage();\n\tHRESULT\t\tLocate( const char* szUser );\n\tHRESULT\t\tPage( const char* szUser, const char* szSend, bool bWaitForResult );\n\tvoid\t\tDoKick( IconListClass* pILUsersOrPlayers, bool bAndBan );\n\tbool\t\tKick( User* pUserToKick );\n\tbool\t\tBan( User* pUserToKick );\n\tvoid\t\tDoSquelch( IconListClass* pILUsersOrPlayers );\n\tbool\t\tSquelch( User* pUserToSquelch );\n\tvoid\t\tDoOptions();\n\tbool\t\tDoLadder();\n\tbool\t\tDoHelp();\n\tbool\t\tDoWebRegistration();\n\tbool\t\tDoGameAdvertising( const Channel* pChannel );\n\tbool\t\tSpawnBrowser( const char* szURL );\n\t\n\tvoid\t\tChannelListTitle( const char* szTitle );\n\tbool\t\tEnterLevel_Top();\n\tbool\t\tEnterLevel_OfficialChat();\n\tbool\t\tEnterLevel_UserChat();\n\tbool\t\tEnterLevel_Games();\n\tbool\t\tEnterLevel_GamesOfType( WOL_GAMETYPEINFO* pGameTypeInfo );\n\tbool\t\tEnterLevel_Lobbies();\n\tbool\t\tOnEnteringChatChannel( const char* szChannelName, bool bICreatedChannel, int iLobby );\n\tvoid\t\tOnExitingChatChannel();\n\tbool\t\tExitChatChannelForGameChannel();\n\tbool\t\tOnEnteringGameChannel( const char* szChannelName, bool bICreatedChannel, const CREATEGAMEINFO& CreateGameInfo );\n\tbool\t\tOnEnteringGameSetup();\n\tvoid\t\tOnFailedToEnterGameChannel();\n\tvoid\t\tOnExitingGameChannel();\n\tvoid\t\tRejoinLobbyAfterGame();\n\t\n\tbool\t\tRequestLadders( const char* szName );\n\tbool\t\tRequestIPs( const char* szName );\n\n\tvoid\t\tSaveChat();\n\tvoid\t\tRestoreChat();\n\tvoid\t\tAddHostLeftMessageToSavedChat( const char* szName );\n\tvoid\t\tAddMessageToSavedChat( const char* szMessage );\n\tvoid\t\tDeleteSavedChat();\n\tvoid\t\tGenericErrorMessage();\n\n\tbool\t\tGetNameOfBeginningLobby( char* szNameToSet );\n\tbool\t\tGetLobbyChannels();\n\n\tconst char* pGameHostName();\n\tUser*\t\tpGameHost();\n\tbool\t\tSendGameOpt( const char* szSend, User* pUserPriv );\n\tbool\t\tRequestGameStart();\n\tbool\t\tSendGo( const char* szSend );\n\n\tvoid\t\tInit_DisconnectPinging();\n\tbool\t\tPump_DisconnectPinging();\n\tvoid\t\tDisconnectPingResultsString( char* szStringToSet );\n\n\tvoid\t\tSetOptionDefaults();\n\tvoid\t\tSetOptions( bool bEnableFind, bool bEnablePage, bool bLangFilterOn, bool bShowAllGames );\n\nprotected:\n\tvoid\t\tGetGameTypeInfo( int iGameType, WOL_GAMETYPEINFO& GameTypeInfo, HPALETTE hPal );\n\tvoid*\t\tIconForGameType( int iGameType );\n\tconst char* NameOfGameType( int iGameType ) const;\n\tconst char* URLForGameType( int iGameType ) const;\n\nprotected:\n\t//\tUsed by the general chat dialog.\n\tIconListClass*\t\t\tpILChat;\t\t\t//\tMain messages list.\n\tIconListClass*\t\t\tpILChannels;\t\t//\tChannels list.\n\tIconListClass*\t\t\tpILUsers;\t\t\t//\tUsers list.\n\n//\tIconListClass*\t\t\tpILDisc;\t\t\t//\tMain messages list.\t\t(pILChat is used.)\n\tIconListClass*\t\t\tpILPlayers;\t\t\t//\tPlayers list.\n\n\tStaticButtonClass*\t\tpStaticUsers;\t\t//\tTitle for a users list. Used by main chat dialog only, not by game setup.\n\n\tWOL_GAMETYPEINFO*\t\tGameTypeInfos;\n\tunsigned int\t\t\tnGameTypeInfos;\n\n\tfloat\t\t\t\t\tfLatencyToIconWidth;\n\n\tCHATSAVE*\t\t\t\tpChatSaveList;\n\tCHATSAVE*\t\t\t\tpChatSaveLast;\n};\n\n#endif\n\n#endif\n"
  },
  {
    "path": "CODE/WOLDEBUG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#if 0\n\n#define debugprogress\n#define _ASSERTE( x )\n\n#else\n\n#define debugprint\t\t\tOutputDebugString\n\n#define _DEBUG\n#include \"w95trace.h\"\n\n#define debugprogress debugprint( \"...%s: %i\\n\", __FILE__, __LINE__ )\n#define _ASSERTE( x )\t\tif( !(x) )\tdebugprint( \"ASSERT FALSE!\\n\" );\n\n#endif\n"
  },
  {
    "path": "CODE/WOLEDIT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifdef WOLAPI_INTEGRATION\n\n/***************************************************************************\n * WOLEditClass -- Derived from EditClass, includes changes I wanted for\n *                 wolapi integration stuff.\n *\t\t\t\t\tNote: An editbox of this class cannot be made read-only. See comment below.\n * HISTORY:    07/17/1998 ajw : Created.\n *=========================================================================*/\n\n#include \"WOLEdit.h\"\n\n//#include \"WolDebug.h\"\n\nbool bTabKeyPressedHack = false;\n\n//***********************************************************************************************\nvoid WOLEditClass::Draw_Text( char const * text )\n{\n\t//\tOnly difference between this and EditClass: cursor shows up when\n\t//\tstring is at MaxLength.\n\n\tTextPrintType flags;\n\n\tif (Has_Focus()) {\n\t\tflags = TPF_BRIGHT_COLOR;\n\t} else {\n\t\tflags = (TextPrintType)0;\n\t}\n\n\tConquer_Clip_Text_Print(text, X+1, Y+1, Color, TBLACK, TextFlags | flags, Width-2);\n\n\tif (Has_Focus() &&\t\t//\tstrlen(text) < MaxLength &&\n\t\t(String_Pixel_Width(text) + String_Pixel_Width (\"_\") < Width-2) ) {\n\t\tConquer_Clip_Text_Print( \"_\", X+1+String_Pixel_Width(text), Y+1, Color, TBLACK, TextFlags | flags);\n\t}\n}\n\n//***********************************************************************************************\n//\tOverride of EditClass::Action, because the base class does not behave correctly in certain circumstances.\n//\t(Escape key is being processed as enter key.)\n//\tAgain, I'm not about to change the base class directly, as I'm trying to have as minimal an affect as possible on\n//\tthe current game code. -ajw\nint WOLEditClass::Action(unsigned flags, KeyNumType & key)\n{\n\t//\t(Mostly duplicated from base class ::Action)\n/*\tFor some painful reason, IsReadOnly is private in the base class, so I can't do the following.\n\tFor this reason, don't make a WOLEditClass edit box read-only.\n\n\t//\n\t// If this is a read-only edit box, it's a display-only device\n\t//\n\tif (IsReadOnly) {\n\t\treturn(false);\n\t}\n*/\n\n\t//debugprint( \"WOLEditClass::Action this=%i, flags=0x%x, key=0x%x\\n\", this, flags, key );\n\t//\n\t//\tIf the left mouse button is pressed over this gadget, then set the focus to\n\t//\tthis gadget. The event flag is cleared so that no button ID number is returned.\n\t//\n\tif ((flags & LEFTPRESS)) {\n\t\tflags &= ~LEFTPRESS;\n\t\tSet_Focus();\n\t\tFlag_To_Redraw();\t\t// force to draw cursor\n\t}\n\n\t//\n\t//\tHandle keyboard events here. Normally, the key is added to the string, but if the\n\t//\tRETURN key is pressed, then the button ID number is returned from the Input()\n\t//\tfunction.\n\t//\n\tif ((flags & KEYBOARD) && Has_Focus()) {\n\n\t\t//\n\t\t//\tProcess the keyboard character. If indicated, consume this keyboard event\n\t\t//\tso that the edit gadget ID number is not returned.\n\t\t//\n\t\tif (key == KN_ESC) {\n\n\t\t\tClear_Focus();\n\t\t\tflags = 0;\n\n\t\t} else {\n#ifdef WIN32\n\n\t\t\tKeyASCIIType ascii = (KeyASCIIType)(Keyboard->To_ASCII(key) & 0xff);\n\n\t\t\t//\n\t\t\t// Allow numeric keypad presses to map to ascii numbers\n\t\t\t//\n\t\t\tif ((key & WWKEY_VK_BIT) && ascii >='0' && ascii <= '9') {\n\n\t\t\t\tkey = (KeyNumType)(key & ~WWKEY_VK_BIT);\n\t\t\t\tif ( (!(flags & LEFTRELEASE)) && (!(flags & RIGHTRELEASE))) {\n\t\t\t\t\tif (Handle_Key (ascii) ) {\n\t\t\t\t\t\tflags &= ~KEYBOARD;\n\t\t\t\t\t\tkey = KN_NONE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t//\n\t\t\t\t// Filter out all special keys except return and backspace\n\t\t\t\t//  \t\n\t\t\t\tif ((!(key & WWKEY_VK_BIT) && ascii >= ' ' && ascii <= 255)\n\t\t\t\t\t|| key == KN_RETURN || key == KN_BACKSPACE) {\n\n\n\n\t\t\t\t\tif ((!(flags & LEFTRELEASE)) && (!(flags & RIGHTRELEASE))) {\n\t\t\t\t\t\tif (Handle_Key(Keyboard->To_ASCII(key))) {\n\t\t\t\t\t\t\tflags &= ~KEYBOARD;\n\t\t\t\t\t\t\tkey = KN_NONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif( key == KN_TAB )\n\t\t\t\t\t{\n\t\t\t\t\t\tbTabKeyPressedHack = true;\n\t\t\t\t\t}\n\t\t\t\t\tflags &= ~KEYBOARD;\n\t\t\t\t\tkey = KN_NONE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n#else\t//WIN32\n\t\t\tif (Handle_Key(Keyboard->To_ASCII(key))) {\n\t\t\t\tflags &= ~KEYBOARD;\n\t\t\t\tkey = KN_NONE;\n\t\t\t}\n\t\t}\n#endif\t//WIN32\n\t}\n\telse\n\t{\n\t\t//\tajw added\n//\t\tif( key == ( KN_ESC | WWKEY_RLS_BIT ) && ( key & WWKEY_ALT_BIT ) )\n//\t\t{\n\t\t\t//Clear_Focus();\n\t\t\tflags = 0;\n\t\t\tkey = KN_NONE;\n//\t\t}\n\t}\n\n\treturn(ControlClass::Action(flags, key));\n}\n\n#endif\n"
  },
  {
    "path": "CODE/WOLEDIT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifdef WOLAPI_INTEGRATION\n\n/***************************************************************************\n * WOLEditClass -- Derived from EditClass, includes changes I wanted for\n *                 wolapi integration stuff.\n *\n * HISTORY:    07/17/1998 ajw : Created.\n *=========================================================================*/\n\n#include \"Function.h\"\n\nclass WOLEditClass : public EditClass\n{\npublic:\n\tWOLEditClass(int id, char * text, int max_len, TextPrintType flags, int x, int y, int w, int h, EditStyle style) :\n\t\tEditClass( id, text, max_len, flags, x, y, w, h, style )\t{}\n\t\t\n\tvirtual int Action (unsigned flags, KeyNumType &key);\t\t//\tOverride of base\n\nprotected:\n\tvirtual void Draw_Text( char const * text );\t\t\t\t//\tOverride of base\n\n};\n\n#endif\n"
  },
  {
    "path": "CODE/WOLSTRNG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n//\tNew character strings for wolapi integration.\n\n#ifdef WOLAPI_INTEGRATION\n#include \"function.h\"\n#include \"WolStrng.h\"\n\n//#undef ENGLISH\n//#define GERMAN\n\n#ifdef ENGLISH\n#pragma message( \"...Building English version...\" )\n\n//\tMenu choice for Internet game.\nconst char TXT_WOL_INTERNETBUTTON[]\t\t\t= \"Internet\";\n//\tGeneric error message, though implies that blame lies with Westwood Online.\nconst char TXT_WOL_ERRORMESSAGE[]\t\t\t= \"Unexpected error occurred communicating with Westwood Online.\";\n//\tConnect button on login dialog.\nconst char TXT_WOL_CONNECT[]\t\t\t\t= \"Connect\";\n//\tTitle for login dialog.\nconst char TXT_WOL_LOGINDIALOG[]\t\t\t= \"Westwood Online Login\";\n//\tAppears on login dialog - user login name field.\nconst char TXT_WOL_NAME[]\t\t\t\t\t= \"Nickname\";\n//\tAppears on login dialog - user password field.\nconst char TXT_WOL_PASSWORD[]\t\t\t\t= \"Password\";\n//\tAppears on login dialog - checkbox specifying whether nickname/password should be saved to disk.\nconst char TXT_WOL_SAVELOGIN[]\t\t\t\t= \"Save\";\n//\tUser hit the Escape button to cancel the logging in process.\nconst char TXT_WOL_LOGINCANCEL[]\t\t\t= \"Login cancelled.\";\n\nconst char TXT_WOL_MISSINGNAME[]\t\t\t= \"Please enter your login nickname.\";\n\nconst char TXT_WOL_MISSINGPASSWORD[]\t\t= \"Please enter your login password.\";\n\nconst char TXT_WOL_CANTSAVENICK[]\t\t\t= \"Error saving nickname/password.\";\n\nconst char TXT_WOL_NICKINUSE[]\t\t\t\t= \"That nickname is in use. Please select another.\";\n\nconst char TXT_WOL_BADPASS[]\t\t\t\t= \"Invalid password for this nickname.\";\n\nconst char TXT_WOL_TIMEOUT[]\t\t\t\t= \"Connection to Westwood Online timed out.\";\n\nconst char TXT_WOL_CONNECTING[]\t\t\t\t= \"Connecting to Westwood Online...\";\n\nconst char TXT_WOL_CANTCONNECT[]\t\t\t= \"Could not establish connection to Westwood Online.\";\n//\tAppears while connecting and logging in to Westwood Online.\nconst char TXT_WOL_ATTEMPTLOGIN[]\t\t\t= \"Logging in...\";\n//\tAppears while logging out and disconnecting from Westwood Online.\nconst char TXT_WOL_ATTEMPTLOGOUT[]\t\t\t= \"Logging out...\";\n//\tAppears while logging out and disconnecting from Westwood Online after an error has occurred.\nconst char TXT_WOL_ERRORLOGOUT[]\t\t\t= \"Terminating connection with Westwood Online...\";\n//\tCommon \"please wait\" message.\nconst char TXT_WOL_WAIT[]\t\t\t\t\t= \"Please wait... communicating with Westwood Online...\";\n//\tTitle for the top WW Online level.\nconst char TXT_WOL_TOPLEVELTITLE[]\t\t\t= \"Westwood Online\";\n//\tTitle for the WW Online level where \"official\" chat channels are listed.\nconst char TXT_WOL_OFFICIALCHAT[]\t\t\t= \"Official Chat\";\n//\tTitle for the WW Online level where \"user\" (in other words, unofficial) chat channels are listed.\nconst char TXT_WOL_USERCHAT[]\t\t\t\t= \"User Chat\";\n//\tTitle for the WW Online level where game channels are listed.\nconst char TXT_WOL_GAMECHANNELS[]\t\t\t= \"Game Channels\";\n//\tTitle for the WW Online level where Red Alert game lobbies are listed.\nconst char TXT_WOL_REDALERTLOBBIES[]\t\t= \"Red Alert Lobbies\";\n//\tAppears briefly while a list of channels is being downloaded.\nconst char TXT_WOL_CHANNELLISTLOADING[]\t\t= \"...downloading...\";\n\nconst char TXT_WOL_YOURENOTINCHANNEL[]\t\t= \"You are not currently in a chat channel.\";\n//\t\"Action\" button. Causes text entered by user to show up as if they were performing an action, as opposed to speaking.\nconst char TXT_WOL_ACTION[]\t\t\t\t\t= \"Action\";\n//\t\"Join\" button. Allows user to join a channel, game, or WW Online level.\nconst char TXT_WOL_JOIN[]\t\t\t\t\t= \"Join\";\n\nconst char TXT_WOL_CANTCREATEINCHANNEL[]\t= \"You can't create a new channel until you exit this channel.\";\n//\t\"New\" button. Allows user to create a new chat channel or game.\nconst char TXT_WOL_NEWSOMETHING[]\t\t\t= \"New\";\n//\tTitle for chat channel creation dialog.\nconst char TXT_WOL_CREATECHANNELTITLE[]\t\t= \"Create Channel\";\n\nconst char TXT_WOL_CREATECHANNELPROMPT[]\t= \"Channel Name: \";\n//\tPrompt for fields where the user must enter a password.\nconst char TXT_WOL_PASSPROMPT[]\t\t\t\t= \"Password: \";\n//\tPrompt for fields where the user may enter a password, but it is not required.\nconst char TXT_WOL_OPTIONALPASSPROMPT[]\t\t= \"Password (optional): \";\n//\tAppears in channel list, as top choice, which the user can use to go back to the top WW Online level.\nconst char TXT_WOL_CHANNEL_TOP[]\t\t\t= \".. <back to top>\";\n//\tAppears in channel list, as top choice, which the user can use to go back up one WW Online level.\nconst char TXT_WOL_CHANNEL_BACK[]\t\t\t= \".. <back>\";\n//\t%s is replaced by the name of a channel.\nconst char TXT_WOL_YOUJOINED[]\t\t\t\t= \"You have joined the %s channel.\";\n//\t%s is replaced by the name of a user.\nconst char TXT_WOL_YOUJOINEDGAME[]\t\t\t= \"You have joined %s's game.\";\n//\tMessage confirming that user created a new game.\nconst char TXT_WOL_YOUCREATEDGAME[]\t\t\t= \"New game created.\";\n//\t%s is replaced by the name of a lobby.\nconst char TXT_WOL_YOUJOINEDLOBBY[]\t\t\t= \"You have entered the %s lobby.\";\n//\t%s is replaced by the name of a channel.\nconst char TXT_WOL_YOULEFT[]\t\t\t\t= \"You have left the %s channel.\";\n//\t%s is replaced by the name of a lobby.\nconst char TXT_WOL_YOULEFTLOBBY[]\t\t\t= \"You have left the %s lobby.\";\n//\tTitle for dialog that prompts user for the password needed to enter a private channel.\nconst char TXT_WOL_JOINPRIVATETITLE[]\t\t= \"Join Private Channel\";\n\nconst char TXT_WOL_JOINPRIVATEPROMPT[]\t\t= \"Enter Channel Password: \";\n\nconst char TXT_WOL_BADCHANKEY[]\t\t\t\t= \"Incorrect channel password.\";\n//\tTitle for the Page/Locate dialog. Page = send a user a message. Locate = find out where a user is.\nconst char TXT_WOL_PAGELOCATE[]\t\t\t\t= \"Page/Locate\";\n//\tAppears on Page/Locate dialog.\nconst char TXT_WOL_USERNAMEPROMPT[]\t\t\t= \"User Name: \";\n//\tText for Page button on dialog.\nconst char TXT_WOL_PAGE[]\t\t\t\t\t= \"Page\";\n//\tText for Locate button on dialog.\nconst char TXT_WOL_LOCATE[]\t\t\t\t\t= \"Locate\";\n//\t%s is replaced with name of user being located.\nconst char TXT_WOL_LOCATING[]\t\t\t\t= \"Locating %s...\";\n\nconst char TXT_WOL_FIND_NOTHERE[]\t\t\t= \"The specified user name does not exist.\";\n\nconst char TXT_WOL_FIND_NOCHAN[]\t\t\t= \"The specified user is currently not in a channel.\";\n\nconst char TXT_WOL_FIND_OFF[]\t\t\t\t= \"The specified user has disabled find capability.\";\n//\t%s is replaced with name of user being located.\nconst char TXT_WOL_FOUNDIN[]\t\t\t\t= \"User found in the %s channel.\";\n//\tTitle for Page dialog.\nconst char TXT_WOL_PAGEMESSAGETITLE[]\t\t= \"Page User\";\n//\tPrompt for field in which user enters the message that is to be sent to user.\nconst char TXT_WOL_PAGEMESSAGEPROMPT[]\t\t= \"Message to Send: \";\n//\t%s is replaced with name of user being paged.\nconst char TXT_WOL_PAGING[]\t\t\t\t\t= \"Paging %s...\";\n\nconst char TXT_WOL_PAGE_NOTHERE[]\t\t\t= \"The specified user is not logged in.\";\n\nconst char TXT_WOL_PAGE_OFF[]\t\t\t\t= \"The specified user has disabled page capability.\";\n//\tFirst %s is replaced with user name, second %s with a text message.\nconst char TXT_WOL_ONPAGE[]\t\t\t\t\t= \"Page from %s: %s\";\n//\t%s is replaced with name of user being paged.\nconst char TXT_WOL_WASPAGED[]\t\t\t\t= \"%s was successfully paged.\";\n//\t%s is replaced with the name of a user that has just been squelched. (Currently unused.)\n//const char TXT_WOL_USERISSQUELCHED[]\t\t= \"%s has been squelched.\";\n//\t%s is replaced with the name of a user that has had squelch removed. (Currently unused.)\n//const char TXT_WOL_USERISNOTSQUELCHED[]\t\t= \"%s is no longer squelched.\";\n\nconst char TXT_WOL_ONLYOWNERCANKICK[]\t\t= \"Only the channel owner can kick users out.\";\n//\tBoth %s replaced with user names.\nconst char TXT_WOL_USERKICKEDUSER[]\t\t\t= \"%s kicked %s out of the channel.\";\n//\t%s replaced with user name.\nconst char TXT_WOL_USERKICKEDYOU[]\t\t\t= \"You were kicked out of the channel by %s.\";\n\nconst char TXT_WOL_NOONETOKICK[]\t\t\t= \"Select the user(s) you wish to kick out.\";\n//\t%s replaced with user name.\nconst char TXT_WOL_USERWASBANNED[]\t\t\t= \"%s has been banned from the channel.\";\n//\tTitle for dialog in which user enters password for new game they are creating.\nconst char TXT_WOL_CREATEPRIVGAMETITLE[]\t= \"Create Private Game\";\n\nconst char TXT_WOL_YOUREBANNED[]\t\t\t= \"You've been banned from entering this channel.\";\n//\t%s replaced with user name.\nconst char TXT_WOL_PLAYERLEFTGAME[]\t\t\t= \"%s has left the game.\";\n//\t%s replaced with user name.\nconst char TXT_WOL_PLAYERJOINEDGAME[]\t\t= \"%s has joined the game.\";\n\nconst char TXT_WOL_YOUWEREKICKEDFROMGAME[]\t= \"You've been kicked out of the game.\";\n//\tShows user's ladder ranking and win/loss record. Appears above main chat area.\nconst char TXT_WOL_PERSONALWINLOSSRECORD[]\t= \"%s. Red Alert: Ranked %u. Won %u. Lost %u. Points %u.\";\n//\tShows user's ladder ranking and win/loss record. Appears above main chat area. Appended Aftermath ranking.\nconst char TXT_WOL_PERSONALWINLOSSRECORDAM[]= \"%s. Aftermath: Ranked %u. Won %u. Lost %u. Points %u.\";\n//\tUsed to show brief user ladder ranking in user lists. Example: FredX (Rank 134)\nconst char TXT_WOL_USERRANK[]\t\t\t\t= \"%s (Rank %u)\";\n//\tNo need to translate.\nconst char TXT_WOL_USERHOUSE[]\t\t\t\t= \"%s <%s>\";\n//\t\"Rank\" translates the same here as above.\nconst char TXT_WOL_USERRANKHOUSE[]\t\t\t= \"%s (Rank %u) <%s>\";\n//\tButton host user presses to start a game they have created.\nconst char TXT_WOL_STARTBUTTON[]\t\t\t= \"Start\";\n//\tButton that guests joining a game press to indicate that they agree to the game rules set up by the host.\nconst char TXT_WOL_ACCEPTBUTTON[]\t\t\t= \"Accept\";\n//\t%s replaced with user name.\nconst char TXT_WOL_HOSTLEFTGAME[]\t\t\t= \"%s has cancelled the game.\";\n//\tAppears when game is actually being started.\nconst char TXT_WOL_WAITINGTOSTART[]\t\t\t= \"Launching game...\";\n//\tTooltip help for WW Online button: disconnect.\nconst char TXT_WOL_TTIP_DISCON[]\t\t\t= \" Leave Westwood Online \";\n//\tTooltip help for WW Online button: leave current channel.\nconst char TXT_WOL_TTIP_LEAVE[]\t\t\t\t= \" Leave the channel you are in \";\n//\tTooltip help for WW Online button: refresh current list.\nconst char TXT_WOL_TTIP_REFRESH[]\t\t\t= \" Refresh current channel list \";\n//\tTooltip help for WW Online button: squelch user(s).\nconst char TXT_WOL_TTIP_SQUELCH[]\t\t\t= \" Enable/disable incoming message from user(s) \";\n//\tTooltip help for WW Online button: ban (and kick) user(s).\nconst char TXT_WOL_TTIP_BAN[]\t\t\t\t= \" Ban user(s) from channel \";\n//\tTooltip help for WW Online button: kick user(s).\nconst char TXT_WOL_TTIP_KICK[]\t\t\t\t= \" Kick user(s) out of channel \";\n//\tTooltip help for WW Online button: find/page.\nconst char TXT_WOL_TTIP_FINDPAGE[]\t\t\t= \" Find or page a user \";\n//\tTooltip help for WW Online button: show options dialog.\nconst char TXT_WOL_TTIP_OPTIONS[]\t\t\t= \" Set Westwood Online options \";\n//\tTooltip help for WW Online button: browse game ladder.\nconst char TXT_WOL_TTIP_LADDER[]\t\t\t= \" Browse Red Alert ladders \";\n//\tTooltip help for WW Online button: show help.\nconst char TXT_WOL_TTIP_HELP[]\t\t\t\t= \" Show Westwood Online help \";\n//\tTooltip help. Appears for button host presses to start a game.\nconst char TXT_WOL_TTIP_START[]\t\t\t\t= \" Start the game \";\n//\tTooltip help. Appears for button guests press in order to agree to (accept) game rules set up by the host.\nconst char TXT_WOL_TTIP_ACCEPT[]\t\t\t= \" Accept the current game settings \";\n//\tTooltip help. Appears for the small buttons that allow users to enlarge or diminish the size of channel/user lists.\nconst char TXT_WOL_TTIP_EXPANDLIST[]\t\t= \" Expand/contract list \";\n//\tTooltip for Cancel button during game setup.\nconst char TXT_WOL_TTIP_CANCELGAME[]\t\t= \" Go back a level \";\n//\tTooltip for Join button during chat.\nconst char TXT_WOL_TTIP_JOIN[]\t\t\t\t= \" Join a chat or game channel \";\n//\tTooltip for Back button during chat.\nconst char TXT_WOL_TTIP_BACK[]\t\t\t\t= \" Go back a level \";\n//\tTooltip for New button during chat.\nconst char TXT_WOL_TTIP_CREATE[]\t\t\t= \" Create a new chat/game channel \";\n//\tTooltip for Action button.\nconst char TXT_WOL_TTIP_ACTION[]\t\t\t= \" Action message \";\n\nconst char TXT_WOL_OPTFIND[]\t\t\t\t= \"Let others FIND you.\";\n\nconst char TXT_WOL_OPTPAGE[]\t\t\t\t= \"Let others PAGE you.\";\n\nconst char TXT_WOL_OPTLANGUAGE[]\t\t\t= \"Filter out bad language.\";\n//\t\"Display just the games that were created by someone in the lobby you are currently in.\"\nconst char TXT_WOL_OPTGAMESCOPE[]\t\t\t= \"Show local lobby games only.\";\n\nconst char TXT_WOL_CHANNELGONE[]\t\t\t= \"Channel no longer exists.\";\n//\tTitle for create new game dialog.\nconst char TXT_WOL_CG_TITLE[]\t\t\t\t= \"Create Game\";\n//\t%i replaced by number of players allowed into game channel.\nconst char TXT_WOL_CG_PLAYERS[]\t\t\t\t= \"Players:  %i\";\n//\tMarks field indicating whether or not this is a tournament game.\nconst char TXT_WOL_CG_TOURNAMENT[]\t\t\t= \"Tournament\";\n//\tMarks field indicating whether or not this is a private game.\nconst char TXT_WOL_CG_PRIVACY[]\t\t\t\t= \"Private\";\n\nconst char TXT_WOL_CG_RAGAME[]\t\t\t\t= \"Red Alert game\";\n\nconst char TXT_WOL_CG_CSGAME[]\t\t\t\t= \"Counterstrike game\";\n\nconst char TXT_WOL_CG_AMGAME[]\t\t\t\t= \"Aftermath game\";\n\nconst char TXT_WOL_NEEDCOUNTERSTRIKE[]\t\t= \"Sorry, you must have Counterstrike installed to play this game.\";\n\nconst char TXT_WOL_NEEDAFTERMATH[]\t\t\t= \"Sorry, you must have Aftermath installed to play this game.\";\n//\t%s = name of channel, %i = number of people in channel.\nconst char TXT_WOL_TTIP_CHANLIST_CHAT[]\t\t= \" Doubleclick to join the '%s' channel (%i current users). \";\n//\t%s = name of lobby, %i = number of people in channel.\nconst char TXT_WOL_TTIP_CHANLIST_LOBBY[]\t= \" Doubleclick to join the '%s' lobby (%i current users). \";\n//\tAppears in tooltip help for a channel list item.\nconst char TXT_WOL_TTIP_REDALERT[]\t\t\t= \"Red Alert\";\n//\tAppears in tooltip help for a channel list item.\nconst char TXT_WOL_TTIP_COUNTERSTRIKE[]\t\t= \"Counterstrike\";\n//\tAppears in tooltip help for a channel list item.\nconst char TXT_WOL_TTIP_AFTERMATH[]\t\t\t= \"Aftermath\";\n//\t%s = name of user, first %i = number of players in channel, second %i = maximum number of players allowed.\nconst char TXT_WOL_TTIP_CHANLIST_RAGAME[]\t= \" %s game (%i players of a maximum %i). \";\n//\t%s = name of user, %i = number of players in channel.\nconst char TXT_WOL_TTIP_CHANLIST_GAME[]\t\t= \" %s game (%i players). \";\n//\tAppears in tooltip help for a channel list item.\nconst char TXT_WOL_TTIP_PRIVATEGAME[]\t\t= \"(Private) \";\n//\tAppears in tooltip help for a channel list item.\nconst char TXT_WOL_TTIP_TOURNAMENTGAME[]\t= \"(Tournament) \";\n//\t%s is a kind of game, for example, \"Dune 2000\".\nconst char TXT_WOL_TTIP_CHANNELTYPE_GAMESOFTYPE[]\t= \" Doubleclick to view %s games. \";\n\nconst char TXT_WOL_TOURNAMENTPLAYERLIMIT[]\t= \"Tournament games must be two player games.\";\n//\tShows on game setup screen for private games. %s = password for game.\nconst char TXT_WOL_PRIVATEPASSWORD[]\t\t= \"Password: %s\";\n//\tUser cannot join game because either he or the game host has hacked the game.\nconst char TXT_WOL_RULESMISMATCH[]\t\t\t= \"Your game is incompatible with the host's!\";\n//\tMessage appears when game host presses start button but slow responses cause an automatic cancellation of game start.\nconst char TXT_WOL_STARTTIMEOUT[]\t\t\t= \"Timed out waiting for guest responses! Game start cancelled.\";\n//\tMessage appears for guests when automatic cancellation occurs.\nconst char TXT_WOL_STARTCANCELLED[]\t\t\t= \"Game start cancelled.\";\n//\tText of button on game setup screen that takes user out of the game channel.\nconst char TXT_WOL_CANCELGAME[]\t\t\t\t= \"Back\";\n\nconst char TXT_WOL_PATCHQUESTION[]\t\t\t= \"An update patch is required for Internet play. Do you want to download it now?\";\n//\tTitle of patch download dialog. First %i = current file being downloaded, second %i = total # of files to download.\nconst char TXT_WOL_DOWNLOADING[]\t\t\t= \"Download file %i of %i\";\n\nconst char TXT_WOL_DOWNLOADERROR[]\t\t\t= \"An error occurred during file download.\";\n//\tAppears on patch download dialog. First %i = current # of bytes downloaded, second %i = total # of bytes to download.\nconst char TXT_WOL_DOWNLOADBYTES[]\t\t\t= \"Received %i bytes out of %i. (%i%%%%)\";\n//\tAppears on patch download dialog. First %i = number of minutes left, second %i = number of seconds left.\nconst char TXT_WOL_DOWNLOADTIME[]\t\t\t= \"Time Remaining: %i min. %i secs.\";\n//\tAppended to title of patch download dialog when resuming an interrupted download. %s is the regular title, as above.\nconst char TXT_WOL_DOWNLOADRESUMED[]\t\t= \"%s (Resumed after interruption.)\";\n\nconst char TXT_WOL_DOWNLOADCONNECTING[]\t\t= \"Status: Connecting...\";\n\nconst char TXT_WOL_DOWNLOADLOCATING[]\t\t= \"Status: Locating file...\";\n\nconst char TXT_WOL_DOWNLOADDOWNLOADING[]\t= \"Status: Downloading...\";\n\nconst char TXT_WOL_DOWNLOADEXITWARNING[]\t= \"Download complete! Red Alert will now restart in order to apply the update patch.\";\n\nconst char TXT_WOL_HELPSHELL[]\t\t\t\t= \"Are you sure you want to launch the Internet browser for Westwood Online help?\";\n\nconst char TXT_WOL_LADDERSHELL[]\t\t\t= \"Are you sure you want to launch the Internet browser for the Red Alert ladders?\";\n\nconst char TXT_WOL_WEBREGISTRATIONSHELL[]\t= \"No saved usernames found. Would you like to register a new username for Westwood Online?\";\n\nconst char TXT_WOL_GAMEADVERTSHELL[]\t\t= \"Are you sure you want to launch the Internet browser for information about %s?\";\n//\tAppears above user list. %i = number of users in the current channel.\nconst char TXT_WOL_USERLIST[]\t\t\t\t= \"Users   %i\";\n//\tAppears above user list to explain why no users are being listed: because the user is not currently in a chat channel.\nconst char TXT_WOL_NOUSERLIST[]\t\t\t\t= \"(not in a channel)\";\n\nconst char TXT_WOL_CANTCREATEHERE[]\t\t\t= \"To start a game, you have to be in a Red Alert lobby.\";\n//\tAppears inside game, when connection to WW Online is lost.\nconst char TXT_WOL_WOLAPIGONE[]\t\t\t\t= \"Connection to Westwood Online has been lost!\";\n//\tAppears after game, when attempting to get back into WW Online.\nconst char TXT_WOL_WOLAPIREINIT[]\t\t\t= \"Connection to Westwood Online was lost. Reinitializing...\";\n\nconst char TXT_WOL_NOTPAGED[]\t\t\t\t= \"Can't respond to page; no one has paged you.\";\n//\tAppears briefly in the space for scenario name, in game setup dialog.\nconst char TXT_WOL_SCENARIONAMEWAIT[]\t\t= \"waiting for scenario...\";\n//\tText of button on chat screen that takes user out of a chat channel, or up one WW Online level.\nconst char TXT_WOL_BACK[]\t\t\t\t\t= \"Back\";\n\nconst char TXT_WOL_AMDISCNEEDED[]\t\t\t= \"The Aftermath disk will be required for this game; please insert it now.\";\n\nconst char TXT_WOL_CONFIRMLOGOUT[]\t\t\t= \"Are you sure you want to leave Westwood Online?\";\n//\t\"Propose a stalemate\" button.\nconst char TXT_WOL_PROPOSE_DRAW[]\t\t\t= \"Propose a Draw\";\n//\tWithdraw proposed stalemate button.\nconst char TXT_WOL_RETRACT_DRAW[]\t\t\t= \"Retract Draw Proposal\";\n//\tAccept offered stalemate button.\nconst char TXT_WOL_ACCEPT_DRAW[]\t\t\t= \"Accept Proposed Draw\";\n//\tUser proposes that the game be declared a stalemate.\nconst char TXT_WOL_PROPOSE_DRAW_CONFIRM[]\t= \"Are you sure you want to propose a draw?\";\n//\tUser accepts the other's offer that the game be a tie.\nconst char TXT_WOL_ACCEPT_DRAW_CONFIRM[]\t= \"Are you sure you want to accept a draw?\";\n\nconst char TXT_WOL_DRAW_PROPOSED_LOCAL[]\t= \"You have proposed that the game be declared a draw.\";\n\nconst char TXT_WOL_DRAW_PROPOSED_OTHER[]\t= \"%s has proposed that the game be declared a draw.\";\n\nconst char TXT_WOL_DRAW_RETRACTED_LOCAL[]\t= \"You have retracted your offer of a draw.\";\n\nconst char TXT_WOL_DRAW_RETRACTED_OTHER[]\t= \"%s has retracted the offer of a draw.\";\n//\tMessage that appears in place of \"Mission Accomplished\" or \"Mission Failed\", when game is a draw.\nconst char TXT_WOL_DRAW[]\t\t\t\t\t= \"The Game is a Draw\";\n//\tError message that appears when user's web browser can't be automatically launched. %s is a web site URL.\nconst char TXT_WOL_CANTLAUNCHBROWSER[]\t\t= \"Can't launch web browser to open %s!\";\n\nconst char TXT_WOL_CHANNELFULL[]\t\t\t= \"That chat/game channel is full.\";\n\nconst char TXT_WOL_CHANNELTYPE_TOP[]\t\t\t= \" Doubleclick to go to the top level. \";\n\nconst char TXT_WOL_CHANNELTYPE_OFFICIALCHAT[]\t= \" Doubleclick to go to the official chat channels level. \";\n\nconst char TXT_WOL_CHANNELTYPE_USERCHAT[]\t\t= \" Doubleclick to go to the user chat channels level. \";\n\nconst char TXT_WOL_CHANNELTYPE_GAMES[]\t\t\t= \" Doubleclick to go to the game channels level. \";\n\nconst char TXT_WOL_CHANNELTYPE_LOADING[]\t\t= \" Loading list from Westwood Online, please wait... \";\n\nconst char TXT_WOL_CHANNELTYPE_LOBBIES[]\t\t= \" Doubleclick to go to the lobbies level. \";\n\nconst char TXT_WOL_FINDINGLOBBY[]\t\t\t\t= \"Connected - finding available lobby to enter...\";\n\nconst char TXT_WOL_PRIVATETOMULTIPLE[]\t\t\t= \"<Private to multiple users>:\";\n\nconst char TXT_WOL_PRIVATETO[]\t\t\t\t\t= \"Private to\";\n\nconst char TXT_WOL_CS_MISSIONS[]\t\t\t\t= \"Counterstrike Missions\";\n\nconst char TXT_WOL_AM_MISSIONS[]\t\t\t\t= \"Aftermath Missions\";\n\nconst char TXT_WOL_CANTSQUELCHSELF[]\t\t\t= \"You cannot disable viewing of your own messages!\";\n//\tTitle of the WW Online options dialog.\nconst char TXT_WOL_OPTTITLE[]\t\t\t\t\t= \"Westwood Online Options\";\n\nconst char TXT_WOL_SLOWUNITBUILD[]\t\t\t\t= \"Slow Unit Build\";\n\nconst char TXT_WOL_THEGAMEHOST[]\t\t\t\t= \"The game host\";\n\nconst char TXT_WOL_TTIP_RANKRA[]\t\t\t\t= \" Show Red Alert ladder rankings \";\n\nconst char TXT_WOL_TTIP_RANKAM[]\t\t\t\t= \" Show Aftermath ladder rankings \";\n\nconst char TXT_WOL_OPTRANKAM[]\t\t\t\t\t= \"Show Aftermath rankings (instead of Red Alert)\";\n\nconst char TXT_WOL_CANCELMEANSFORFEIT[]\t\t\t= \" (AND FORFEIT THE GAME)\";\n\nconst char TXT_WOL_DLLERROR_GETIE3[]\t\t\t= \"Your version of Windows is out of date. Please upgrade to Windows SP1, or install Internet Explorer 3.0 or higher.\";\n\nconst char TXT_WOL_DLLERROR_CALLUS[]\t\t\t= \"An unexpected error has occurred. Please contact Westwood technical support.\";\n\nconst char TXT_WOL_PRIVATE[]\t\t\t\t\t= \"<private>\";\n\n#else\n\n#ifdef GERMAN\n#pragma message( \"...Building German version...\" )\n\n//\tReplaced \"\" with ascii 169 (in octal, 251) in cases where 8 point font is used (see 8point.lbm for why).\nconst char TXT_WOL_INTERNETBUTTON[]\t\t\t= \"Internet\";\nconst char TXT_WOL_ERRORMESSAGE[]\t\t\t= \"Unerwarteter Fehler trat bei der Kommunikation mit Westwood Online auf.\";\nconst char TXT_WOL_CONNECT[]\t\t\t\t= \"Verbinden\";\nconst char TXT_WOL_LOGINDIALOG[]\t\t\t= \"Westwood-Online-Login\";\nconst char TXT_WOL_NAME[]\t\t\t\t\t= \"Spitzname\";\nconst char TXT_WOL_PASSWORD[]\t\t\t\t= \"Pa\\251wort\";\nconst char TXT_WOL_SAVELOGIN[]\t\t\t\t= \"Speichern\";\nconst char TXT_WOL_LOGINCANCEL[]\t\t\t= \"Login abgebrochen.\";\nconst char TXT_WOL_MISSINGNAME[]\t\t\t= \"Bitte geben Sie Ihren Login-Spitznamen ein.\";\nconst char TXT_WOL_MISSINGPASSWORD[]\t\t= \"Bitte geben Sie Ihr Login-Pa\\251wort ein.\";\nconst char TXT_WOL_CANTSAVENICK[]\t\t\t= \"Fehler beim Speichern des Spitznamens/Pa\\251worts\";\nconst char TXT_WOL_NICKINUSE[]\t\t\t\t= \"Dieser Spitzname wird bereits verwendet. Bitte whlen Sie einen anderen.\";\nconst char TXT_WOL_BADPASS[]\t\t\t\t= \"Ungltiges Pa\\251wort fr diesen Spitznamen\";\nconst char TXT_WOL_TIMEOUT[]\t\t\t\t= \"Verbindung zu Westwood Online unterbrochen\";\nconst char TXT_WOL_CONNECTING[]\t\t\t\t= \"Verbinde zu Westwood Online...\";\nconst char TXT_WOL_CANTCONNECT[]\t\t\t= \"Verbindung zu Westwood Online konnte nicht hergestellt werden.\";\nconst char TXT_WOL_ATTEMPTLOGIN[]\t\t\t= \"Einloggen ... \";\nconst char TXT_WOL_ATTEMPTLOGOUT[]\t\t\t= \"Ausloggen ...\";\nconst char TXT_WOL_ERRORLOGOUT[]\t\t\t= \"Verbindung zu Westwood Online beenden ...\";\nconst char TXT_WOL_WAIT[]\t\t\t\t\t= \"Bitte warten ... Verbindung zu Westwood Online wird hergestellt ...\";\nconst char TXT_WOL_TOPLEVELTITLE[]\t\t\t= \"Westwood Online\";\nconst char TXT_WOL_OFFICIALCHAT[]\t\t\t= \"Offizieller Chat\";\nconst char TXT_WOL_USERCHAT[]\t\t\t\t= \"User-Chat\";\nconst char TXT_WOL_GAMECHANNELS[]\t\t\t= \"Game-Channels\";\nconst char TXT_WOL_REDALERTLOBBIES[]\t\t= \"Alarmstufe-Rot-Lobbies\";\nconst char TXT_WOL_CHANNELLISTLOADING[]\t\t= \"... Daten werden heruntergeladen ...\";\nconst char TXT_WOL_YOURENOTINCHANNEL[]\t\t= \"Sie befinden sich zur Zeit nicht in einem Chat-Channel.\";\nconst char TXT_WOL_ACTION[]\t\t\t\t\t= \"Action\";\nconst char TXT_WOL_JOIN[]\t\t\t\t\t= \"Teilnehmen\";\nconst char TXT_WOL_CANTCREATEINCHANNEL[]\t= \"Sie knnen keinen neuen Channel erstellen, bevor Sie diesen Channel verlassen.\";\nconst char TXT_WOL_NEWSOMETHING[]\t\t\t= \"Neu\";\nconst char TXT_WOL_CREATECHANNELTITLE[]\t\t= \"Channel erstellen\";\nconst char TXT_WOL_CREATECHANNELPROMPT[]\t= \"Channel-Name: \";\nconst char TXT_WOL_PASSPROMPT[]\t\t\t\t= \"Pa\\251wort: \";\nconst char TXT_WOL_OPTIONALPASSPROMPT[]\t\t= \"Pa\\251wort (optional): \";\nconst char TXT_WOL_CHANNEL_TOP[]\t\t\t= \".. <zurck zum Anfang>\";\nconst char TXT_WOL_CHANNEL_BACK[]\t\t\t= \".. <zurck>\";\nconst char TXT_WOL_YOUJOINED[]\t\t\t\t= \"Sie nehmen am %s-Channel teil.\";\nconst char TXT_WOL_YOUJOINEDGAME[]\t\t\t= \"Sie nehmen an %ss Spiel teil.\";\nconst char TXT_WOL_YOUCREATEDGAME[]\t\t\t= \"Neues Spiel erstellt.\";\nconst char TXT_WOL_YOUJOINEDLOBBY[]\t\t\t= \"Sie haben die %s-Lobby betreten.\";\nconst char TXT_WOL_YOULEFT[]\t\t\t\t= \"Sie haben den %s-Channel verlassen.\";\nconst char TXT_WOL_YOULEFTLOBBY[]\t\t\t= \"Sie haben die %s-Lobby verlassen.\";\nconst char TXT_WOL_JOINPRIVATETITLE[]\t\t= \"An privatem Channel teilnehmen\";\nconst char TXT_WOL_JOINPRIVATEPROMPT[]\t\t= \"Channel-Pa\\251wort eingeben: \";\nconst char TXT_WOL_BADCHANKEY[]\t\t\t\t= \"Falsches Channel-Pa\\251wort.\";\nconst char TXT_WOL_PAGELOCATE[]\t\t\t\t= \"Senden/Suchen\";\nconst char TXT_WOL_USERNAMEPROMPT[]\t\t\t= \"User-Name: \";\nconst char TXT_WOL_PAGE[]\t\t\t\t\t= \"Senden\";\nconst char TXT_WOL_LOCATE[]\t\t\t\t\t= \"Suchen\";\nconst char TXT_WOL_LOCATING[]\t\t\t\t= \"Suche %s...\";\nconst char TXT_WOL_FIND_NOTHERE[]\t\t\t= \"Der gesuchte User-Name existiert nicht.\";\nconst char TXT_WOL_FIND_NOCHAN[]\t\t\t= \"Der genannte User befindet sich zur Zeit nicht in einem Channel.\";\nconst char TXT_WOL_FIND_OFF[]\t\t\t\t= \"Der genannte User hat die Suchfunktion ausgeschaltet.\";\nconst char TXT_WOL_FOUNDIN[]\t\t\t\t= \"User wurde im %s-Channel gefunden.\";\nconst char TXT_WOL_PAGEMESSAGETITLE[]\t\t= \"Sender\";\nconst char TXT_WOL_PAGEMESSAGEPROMPT[]\t\t= \"Zu sendende Nachricht: \";\nconst char TXT_WOL_PAGING[]\t\t\t\t\t= \"Sende an %s ...\";\nconst char TXT_WOL_PAGE_NOTHERE[]\t\t\t= \"Der genannte User ist nicht eingeloggt.\";\nconst char TXT_WOL_PAGE_OFF[]\t\t\t\t= \"Der genannte User hat die Empfangsfunktion ausgeschaltet.\";\nconst char TXT_WOL_ONPAGE[]\t\t\t\t\t= \"Sende von %s: %s\";\nconst char TXT_WOL_WASPAGED[]\t\t\t\t= \"Die Nachricht wurde %s erfolgreich zugestellt.\";\n//const char TXT_WOL_USERISSQUELCHED[]\t\t= \"%s ist zur Zeit nicht erreichbar.\";\n//const char TXT_WOL_USERISNOTSQUELCHED[]\t\t= \"%s ist jetzt wieder erreichbar.\";\nconst char TXT_WOL_ONLYOWNERCANKICK[]\t\t= \"Nur der Channel-Besitzer kann andere User hinauswerfen.\";\nconst char TXT_WOL_USERKICKEDUSER[]\t\t\t= \"%s hat %s aus dem Channel geworfen.\";\nconst char TXT_WOL_USERKICKEDYOU[]\t\t\t= \"Sie wurden von %s aus dem Channel geworfen.\";\nconst char TXT_WOL_NOONETOKICK[]\t\t\t= \"Whlen Sie den/die User, die Sie hinauswerfen mchten.\";\nconst char TXT_WOL_USERWASBANNED[]\t\t\t= \"%s hat keinen Zutritt mehr zu diesem Channel.\";\nconst char TXT_WOL_CREATEPRIVGAMETITLE[]\t= \"Privates Spiel erstellen\";\nconst char TXT_WOL_YOUREBANNED[]\t\t\t= \"Sie haben keinen Zutritt mehr zu diesem Channel.\";\nconst char TXT_WOL_PLAYERLEFTGAME[]\t\t\t= \"%s hat das Spiel verlassen.\";\nconst char TXT_WOL_PLAYERJOINEDGAME[]\t\t= \"%s hat an dem Spiel teilgenommen.\";\nconst char TXT_WOL_YOUWEREKICKEDFROMGAME[]\t= \"Sie wurden aus dem Spiel geworfen.\";\nconst char TXT_WOL_PERSONALWINLOSSRECORD[]\t= \"%s. Alarmstufe Rot: Pl %u. Siege %u. Niederl %u. Pkte %u.\";\nconst char TXT_WOL_PERSONALWINLOSSRECORDAM[]= \"%s. Vergeltungsschlag: Pl %u. Siege %u. Niederl %u. Pkte %u.\";\nconst char TXT_WOL_USERRANK[]\t\t\t\t= \"%s (Platz %u)\";\nconst char TXT_WOL_USERHOUSE[]\t\t\t\t= \"%s <%s>\";\nconst char TXT_WOL_USERRANKHOUSE[]\t\t\t= \"%s (Platz %u) <%s>\";\nconst char TXT_WOL_STARTBUTTON[]\t\t\t= \"Start\";\nconst char TXT_WOL_ACCEPTBUTTON[]\t\t\t= \"Besttigen\";\nconst char TXT_WOL_HOSTLEFTGAME[]\t\t\t= \"%s hat das Spiel abgebrochen.\";\nconst char TXT_WOL_WAITINGTOSTART[]\t\t\t= \"Spiel wird gestartet ...\";\nconst char TXT_WOL_TTIP_DISCON[]\t\t\t= \" Westwood Online verlassen\";\nconst char TXT_WOL_TTIP_LEAVE[]\t\t\t\t= \" Derzeitigen Channel verlassen \";\nconst char TXT_WOL_TTIP_REFRESH[]\t\t\t= \" Channel-Liste aktualisieren \";\nconst char TXT_WOL_TTIP_SQUELCH[]\t\t\t= \" Nachrichteneingang von User(n) ein/ausschalten\";\nconst char TXT_WOL_TTIP_BAN[]\t\t\t\t= \" User(n) Zutritt zum Channel verwehren \";\nconst char TXT_WOL_TTIP_KICK[]\t\t\t\t= \" User aus dem Channel werfen \";\nconst char TXT_WOL_TTIP_FINDPAGE[]\t\t\t= \" User suchen oder an User senden \";\nconst char TXT_WOL_TTIP_OPTIONS[]\t\t\t= \" Westwood-Online-Optionen einstellen \";\nconst char TXT_WOL_TTIP_LADDER[]\t\t\t= \" Alarmstufe-Rot-Tabelle durchsuchen \";\nconst char TXT_WOL_TTIP_HELP[]\t\t\t\t= \" Westwood-Online-Hilfe anzeigen \";\nconst char TXT_WOL_TTIP_START[]\t\t\t\t= \" Spiel starten \";\nconst char TXT_WOL_TTIP_ACCEPT[]\t\t\t= \" Aktuelle Spieleinstellungen besttigen \";\nconst char TXT_WOL_TTIP_EXPANDLIST[]\t\t= \" Listen erweitern/verkleinern \";\nconst char TXT_WOL_TTIP_CANCELGAME[]\t\t= \" Einen Level zurck \";\nconst char TXT_WOL_TTIP_JOIN[]\t\t\t\t= \" An Chat- oder Game-Channel teilnehmen \";\nconst char TXT_WOL_TTIP_BACK[]\t\t\t\t= \" Einen Level zurck \";\nconst char TXT_WOL_TTIP_CREATE[]\t\t\t= \" Neuen Chat- oder Game-Level erstellen \";\nconst char TXT_WOL_TTIP_ACTION[]\t\t\t= \" Action-Nachricht \";\nconst char TXT_WOL_OPTFIND[]\t\t\t\t= \"Lassen Sie zu, da\\251 andere Sie FINDEN.\";\nconst char TXT_WOL_OPTPAGE[]\t\t\t\t= \"Lassen Sie zu, da\\251 andere Ihnen Nachrichten SENDEN.\";\nconst char TXT_WOL_OPTLANGUAGE[]\t\t\t= \"Unangemessene Sprache herausfiltern.\";\nconst char TXT_WOL_OPTGAMESCOPE[]\t\t\t= \"Nur lokale Spiel-Lobby anzeigen.\";\n//const char TXT_WOL_OPTTITLE[]\t\t\t\t= \"Optionen\";\nconst char TXT_WOL_CHANNELGONE[]\t\t\t= \"Channel existiert nicht mehr.\";\nconst char TXT_WOL_CG_TITLE[]\t\t\t\t= \"Spiel erstellen\";\nconst char TXT_WOL_CG_PLAYERS[]\t\t\t\t= \"Spieler:  %i\";\nconst char TXT_WOL_CG_TOURNAMENT[]\t\t\t= \"Turnier\";\nconst char TXT_WOL_CG_PRIVACY[]\t\t\t\t= \"Privat\";\nconst char TXT_WOL_CG_RAGAME[]\t\t\t\t= \"Alarmstufe-Rot-Spiel\";\nconst char TXT_WOL_CG_CSGAME[]\t\t\t\t= \"Gegenangriff-Spiel\";\nconst char TXT_WOL_CG_AMGAME[]\t\t\t\t= \"Vergeltungsschlag-Spiel\";\nconst char TXT_WOL_NEEDCOUNTERSTRIKE[]\t\t= \"Sie mssen 'Gegenangriff' installiert haben, um dieses Spiel spielen zu knnen.\";\nconst char TXT_WOL_NEEDAFTERMATH[]\t\t\t= \"Sie mssen 'Vergeltungsschlag' installiert haben, um dieses Spiel spielen zu knnen.\";\nconst char TXT_WOL_TTIP_CHANLIST_CHAT[]\t\t= \" Doppelklick zur Teilnahme am '%s'-Channel (z.Z. %i User). \";\nconst char TXT_WOL_TTIP_CHANLIST_LOBBY[]\t= \" Doppelklick zur Teilnahme an der '%s'-Lobby (z.Z. %i User). \";\nconst char TXT_WOL_TTIP_REDALERT[]\t\t\t= \"Alarmstufe Rot\";\nconst char TXT_WOL_TTIP_COUNTERSTRIKE[]\t\t= \"Gegenangriff\";\nconst char TXT_WOL_TTIP_AFTERMATH[]\t\t\t= \"Vergeltungsschlag\";\nconst char TXT_WOL_TTIP_CHANLIST_RAGAME[]\t= \" %s-Spiel (%i Spieler von maximal %i). \";\nconst char TXT_WOL_TTIP_CHANLIST_GAME[]\t\t= \" %s-Spiel (%i Spieler). \";\nconst char TXT_WOL_TTIP_PRIVATEGAME[]\t\t= \"(Privat) \";\nconst char TXT_WOL_TTIP_TOURNAMENTGAME[]\t= \"(Turnier) \";\nconst char TXT_WOL_TTIP_CHANNELTYPE_GAMESOFTYPE[]\t= \" Doppelklicken Sie, um %s-Spiele anzusehen. \";\nconst char TXT_WOL_TOURNAMENTPLAYERLIMIT[]\t= \"Turnierspiele mssen von zwei Spieler gespielt werden.\";\nconst char TXT_WOL_PRIVATEPASSWORD[]\t\t= \"Pa\\251wort: %s\";\nconst char TXT_WOL_RULESMISMATCH[]\t\t\t= \"Ihr Spiel ist mit dem des Host nicht kompatibel!\";\nconst char TXT_WOL_STARTTIMEOUT[]\t\t\t= \"Keine Antworten von Gsten! Spielstart abgebrochen.\";\nconst char TXT_WOL_STARTCANCELLED[]\t\t\t= \"Spielstart abgebrochen.\";\nconst char TXT_WOL_CANCELGAME[]\t\t\t\t= \"Zurck\";\nconst char TXT_WOL_PATCHQUESTION[]\t\t\t= \"Ein Update-Patch wird fr Internet-Spiele bentigt. Mchten Sie es jetzt herunterladen?\";\nconst char TXT_WOL_DOWNLOADING[]\t\t\t= \"Datei %i von %i herunterladen\";\nconst char TXT_WOL_DOWNLOADERROR[]\t\t\t= \"Ein Fehler trat beim Herunterladen der Dateien auf.\";\nconst char TXT_WOL_DOWNLOADBYTES[]\t\t\t= \"%i Bytes von %i erhalten. (%i%%%%)\";\nconst char TXT_WOL_DOWNLOADTIME[]\t\t\t= \"Verbleibende Zeit: %i Min. %i Sek.\";\nconst char TXT_WOL_DOWNLOADRESUMED[]\t\t= \"%s (Nach Unterbrechung wiederaufgenommen.)\";\nconst char TXT_WOL_DOWNLOADCONNECTING[]\t\t= \"Status: Verbinde ...\";\nconst char TXT_WOL_DOWNLOADLOCATING[]\t\t= \"Status: Suche Datei ...\";\nconst char TXT_WOL_DOWNLOADDOWNLOADING[]\t= \"Status: Lade herunter ...\";\nconst char TXT_WOL_DOWNLOADEXITWARNING[]\t= \"Herunterladen abgeschlossen! Alarmstufe Rot wird jetzt neugestartet, damit das Update-Patch angewendet werden kann.\";\nconst char TXT_WOL_HELPSHELL[]\t\t\t\t= \"Sind Sie sicher, da\\251 Sie den Internet-Browser fr die Westwood-Online-Hilfe starten mchten?\";\nconst char TXT_WOL_LADDERSHELL[]\t\t\t= \"Sind Sie sicher, da\\251 Sie den Internet-Browser fr die Alarmstufe-Rot-Tabellen starten mchten?\";\nconst char TXT_WOL_WEBREGISTRATIONSHELL[]\t= \"Keine gespeicherten User-Namen gefunden. Mchten Sie einen neuen User-Namen fr Westwood Online eintragen?\";\nconst char TXT_WOL_GAMEADVERTSHELL[]\t\t= \"Sind Sie sicher, da\\251 Sie den Internet-Browser fr Informationen ber %s starten mchten?\";\nconst char TXT_WOL_USERLIST[]\t\t\t\t= \"User: %i\";\nconst char TXT_WOL_NOUSERLIST[]\t\t\t\t= \"(nicht in einem Channel)\";\nconst char TXT_WOL_CANTCREATEHERE[]\t\t\t= \"Um ein Spiel zu starten, mssen Sie in der Lobby Alarmstufe Rot sein.\";\nconst char TXT_WOL_WOLAPIGONE[]\t\t\t\t= \"Verbindung zu Westwood Online verloren!\";\nconst char TXT_WOL_WOLAPIREINIT[]\t\t\t= \"Verbindung zu Westwood Online verloren. Verbinde erneut ...\";\nconst char TXT_WOL_NOTPAGED[]\t\t\t\t= \"Kann keine Antwort senden, niemand hat Ihnen geschrieben.\";\nconst char TXT_WOL_SCENARIONAMEWAIT[]\t\t= \"Warte auf Szenario ...\";\nconst char TXT_WOL_BACK[]\t\t\t\t\t= \"Zurck\";\nconst char TXT_WOL_AMDISCNEEDED[]\t\t\t= \"Die CD 'Vergeltungsschlag' wird fr dieses Spiel bentigt, bitte legen Sie sie jetzt ein.\";\nconst char TXT_WOL_CONFIRMLOGOUT[]\t\t\t= \"Sind Sie sicher, da\\251 Sie Westwood Online verlassen mchten?\";\nconst char TXT_WOL_PROPOSE_DRAW[]\t\t\t= \"Unentschieden vorschlagen\";\nconst char TXT_WOL_RETRACT_DRAW[]\t\t\t= \"Unentschieden-Vorschlag zurckziehen\";\nconst char TXT_WOL_ACCEPT_DRAW[]\t\t\t= \"Unentschieden-Vorschlag akzeptieren\";\nconst char TXT_WOL_PROPOSE_DRAW_CONFIRM[]\t= \"Sind Sie sicher, da\\251 Sie ein Unentschieden vorschlagen mchten?\";\nconst char TXT_WOL_ACCEPT_DRAW_CONFIRM[]\t= \"Sind Sie sicher, da\\251 Sie ein Unentschieden akzeptieren mchten?\";\nconst char TXT_WOL_DRAW_PROPOSED_LOCAL[]\t= \"Sie haben vorgeschlagen, da\\251 das Spiel fr unentschieden erklrt wird.\";\nconst char TXT_WOL_DRAW_PROPOSED_OTHER[]\t= \"%s hat vorgeschlagen, da\\251 das Spiel fr unentschieden erklrt wird.\";\nconst char TXT_WOL_DRAW_RETRACTED_LOCAL[]\t= \"Sie haben Ihr Unentschieden-Angebot zurckgezogen.\";\nconst char TXT_WOL_DRAW_RETRACTED_OTHER[]\t= \"%s hat das Unentschieden-Angebot zurckgezogen.\";\nconst char TXT_WOL_DRAW[]\t\t\t\t\t= \"Das Spiel ist unentschieden\";\nconst char TXT_WOL_CANTLAUNCHBROWSER[]\t\t= \"Web-Browser kann %s nicht ffnen!\";\nconst char TXT_WOL_CHANNELFULL[]\t\t\t= \"Dieser Chat-/Game-Channel ist voll.\";\nconst char TXT_WOL_CHANNELTYPE_TOP[]\t\t\t= \" Doppelklicken Sie, um zum obersten Level zu gelangen. \";\nconst char TXT_WOL_CHANNELTYPE_OFFICIALCHAT[]\t= \" Doppelklicken Sie, um zum offiziellen Chat-Channel-Level zu gelangen. \";\nconst char TXT_WOL_CHANNELTYPE_USERCHAT[]\t\t= \" Doppelklicken Sie, um zum User-Chat-Channel-Level zu gelangen. \";\nconst char TXT_WOL_CHANNELTYPE_GAMES[]\t\t\t= \" Doppelklicken Sie, um zum Game-Channel-Level zu gelangen. \";\nconst char TXT_WOL_CHANNELTYPE_LOADING[]\t\t= \" Liste von Westwood Online wird geladen, bitte warten... \";\nconst char TXT_WOL_CHANNELTYPE_LOBBIES[]\t\t= \" Doppelklicken Sie, um zum Lobby-Level zu gelangen. \";\nconst char TXT_WOL_FINDINGLOBBY[]\t\t\t\t= \"Verbunden - suche verfgbare Lobby...\";\nconst char TXT_WOL_PRIVATETOMULTIPLE[]\t\t\t= \"<Privat an mehrere User>:\";\nconst char TXT_WOL_PRIVATETO[]\t\t\t\t\t= \"Privat an\";\nconst char TXT_WOL_CS_MISSIONS[]\t\t\t\t= \"Gegenangriff-Missionen\";\nconst char TXT_WOL_AM_MISSIONS[]\t\t\t\t= \"Vergeltungsschlag-Missionen\";\nconst char TXT_WOL_CANTSQUELCHSELF[]\t\t\t= \"Sie knnen die Option zum Lesen Ihrer eigenen Nachrichten nicht ausschalten!\";\nconst char TXT_WOL_OPTTITLE[]\t\t\t\t\t= \"Westwood Online-Optionen\";\nconst char TXT_WOL_SLOWUNITBUILD[]\t\t\t\t= \"Einheitenbau verlangsamen\";\nconst char TXT_WOL_THEGAMEHOST[]\t\t\t\t= \"Der Spiel-Host\";\nconst char TXT_WOL_TTIP_RANKRA[]\t\t\t\t= \" Alarmstufe-Rot-Platz anzeigen \";\nconst char TXT_WOL_TTIP_RANKAM[]\t\t\t\t= \" Vergeltungsschlag-Platz anzeigen \";\nconst char TXT_WOL_OPTRANKAM[]\t\t\t\t\t= \"Vergeltungsschlag-Platz anzeigen.\";\nconst char TXT_WOL_CANCELMEANSFORFEIT[]\t\t\t= \" (UND BSSEN SIE DAS SPIEL EIN)\";\nconst char TXT_WOL_DLLERROR_GETIE3[]\t\t\t= \"Ihre Version der Windows ist veraltet. Bauen Sie bitte zu den Windows SP1, aus oder installieren Sie Internet Explorer 3,0 oder hheres.\";\nconst char TXT_WOL_DLLERROR_CALLUS[]\t\t\t= \"Ein unerwarteter Fehler ist aufgetreten. Bitte wenden Sie sich an den Technischen Kundendienst.\";\nconst char TXT_WOL_PRIVATE[]\t\t\t\t\t= \"<privat>\";\n\n#else\t//\tFRENCH\n\n#pragma message( \"...Building French version...\" )\n\nconst char TXT_WOL_INTERNETBUTTON[]\t\t\t= \"Internet\";\nconst char TXT_WOL_ERRORMESSAGE[]\t\t\t= \"Erreur inattendue lors de la connexion  Westwood Online.\";\nconst char TXT_WOL_CONNECT[]\t\t\t\t= \"Se connecter\";\nconst char TXT_WOL_LOGINDIALOG[]\t\t\t= \"Identifiant  Westwood Online\";\nconst char TXT_WOL_NAME[]\t\t\t\t\t= \"Pseudo\";\nconst char TXT_WOL_PASSWORD[]\t\t\t\t= \"Mot de passe\";\nconst char TXT_WOL_SAVELOGIN[]\t\t\t\t= \"Sauvegarder\";\nconst char TXT_WOL_LOGINCANCEL[]\t\t\t= \"Ouverture de session annule.\";\nconst char TXT_WOL_MISSINGNAME[]\t\t\t= \"Veuillez entrer l'identifiant pour votre pseudo.\";\nconst char TXT_WOL_MISSINGPASSWORD[]\t\t= \"Veuillez entrer l'identifiant pour votre mot de passe.\";\nconst char TXT_WOL_CANTSAVENICK[]\t\t\t= \"Erreur lors de la sauvegarde du pseudo/mot de passe.\";\nconst char TXT_WOL_NICKINUSE[]\t\t\t\t= \"Ce pseudo est dj utilis. Slectionnez-en un autre.\";\nconst char TXT_WOL_BADPASS[]\t\t\t\t= \"Mot de passe invalide pour ce pseudo.\";\nconst char TXT_WOL_TIMEOUT[]\t\t\t\t= \"Expiration du temps de connexion  Westwood Online.\";\nconst char TXT_WOL_CONNECTING[]\t\t\t\t= \"Connexion  Westwood Online...\";\nconst char TXT_WOL_CANTCONNECT[]\t\t\t= \"Impossible d'tablir la connexion  Westwood Online.\";\nconst char TXT_WOL_ATTEMPTLOGIN[]\t\t\t= \"Ouverture de la session en cours...\";\nconst char TXT_WOL_ATTEMPTLOGOUT[]\t\t\t= \"Fermeture de la session en cours...\";\nconst char TXT_WOL_ERRORLOGOUT[]\t\t\t= \"Fin de connexion avec Westwood Online...\";\nconst char TXT_WOL_WAIT[]\t\t\t\t\t= \"Attendez svp, en communication  Westwood Online...\";\nconst char TXT_WOL_TOPLEVELTITLE[]\t\t\t= \"Westwood Online\";\nconst char TXT_WOL_OFFICIALCHAT[]\t\t\t= \"Conversation officielle\";\nconst char TXT_WOL_USERCHAT[]\t\t\t\t= \"Conversation utilisateur\";\nconst char TXT_WOL_GAMECHANNELS[]\t\t\t= \"Canaux de jeu\";\nconst char TXT_WOL_REDALERTLOBBIES[]\t\t= \"Salons d'Alerte Rouge\";\nconst char TXT_WOL_CHANNELLISTLOADING[]\t\t= \"...En cours de tlchargement...\";\nconst char TXT_WOL_YOURENOTINCHANNEL[]\t\t= \"Vous n'tes pas dans un canal de conversation.\";\nconst char TXT_WOL_ACTION[]\t\t\t\t\t= \"Action\";\nconst char TXT_WOL_JOIN[]\t\t\t\t\t= \"Rejoindre\";\nconst char TXT_WOL_CANTCREATEINCHANNEL[]\t= \"Cration d'un nouveau canal impossible tant que vous ne quittez pas ce canal.\";\nconst char TXT_WOL_NEWSOMETHING[]\t\t\t= \"Nouveau\";\nconst char TXT_WOL_CREATECHANNELTITLE[]\t\t= \"Crer un canal\";\nconst char TXT_WOL_CREATECHANNELPROMPT[]\t= \"Nom du canal : \";\nconst char TXT_WOL_PASSPROMPT[]\t\t\t\t= \"Mot de passe : \";\nconst char TXT_WOL_OPTIONALPASSPROMPT[]\t\t= \"Mot de passe (en option): \";\nconst char TXT_WOL_CHANNEL_TOP[]\t\t\t= \".. <retour  la page d'accueil>\";\nconst char TXT_WOL_CHANNEL_BACK[]\t\t\t= \".. <retour>\";\nconst char TXT_WOL_YOUJOINED[]\t\t\t\t= \"Vous avez rejoint le canal %s.\";\nconst char TXT_WOL_YOUJOINEDGAME[]\t\t\t= \"Vous rejoignez la partie de %s.\";\nconst char TXT_WOL_YOUCREATEDGAME[]\t\t\t= \"Cration d'une nouvelle partie.\";\nconst char TXT_WOL_YOUJOINEDLOBBY[]\t\t\t= \"Vous tes entr dans le salon %s.\";\nconst char TXT_WOL_YOULEFT[]\t\t\t\t= \"Vous avez quitt le canal %s.\";\nconst char TXT_WOL_YOULEFTLOBBY[]\t\t\t= \"Vous avez quitt le salon %s.\";\nconst char TXT_WOL_JOINPRIVATETITLE[]\t\t= \"Rejoindre un canal priv\";\nconst char TXT_WOL_JOINPRIVATEPROMPT[]\t\t= \"Entrer le mot de passe du canal : \";\nconst char TXT_WOL_BADCHANKEY[]\t\t\t\t= \"Mot de passe du canal incorrect.\";\nconst char TXT_WOL_PAGELOCATE[]\t\t\t\t= \"Envoyer/Rechercher\";\nconst char TXT_WOL_USERNAMEPROMPT[]\t\t\t= \"Nom de l'utilisateur : \";\nconst char TXT_WOL_PAGE[]\t\t\t\t\t= \"Envoyer\";\nconst char TXT_WOL_LOCATE[]\t\t\t\t\t= \"Rechercher\";\nconst char TXT_WOL_LOCATING[]\t\t\t\t= \"Recherche de %s en cours ...\";\nconst char TXT_WOL_FIND_NOTHERE[]\t\t\t= \"Le nom de l'utilisateur spcifi n'existe pas.\";\nconst char TXT_WOL_FIND_NOCHAN[]\t\t\t= \"L'utilisateur spcifi n'est pas sur le canal pour le moment.\";\nconst char TXT_WOL_FIND_OFF[]\t\t\t\t= \"L'utilisateur spcifi a dsactiv la fonction de recherche.\";\nconst char TXT_WOL_FOUNDIN[]\t\t\t\t= \"Utilisateur trouv dans le canal %s.\";\nconst char TXT_WOL_PAGEMESSAGETITLE[]\t\t= \"Envoyer  l'utilisateur\";\nconst char TXT_WOL_PAGEMESSAGEPROMPT[]\t\t= \"Message  envoyer : \";\nconst char TXT_WOL_PAGING[]\t\t\t\t\t= \"Envoi  %s en cours...\";\nconst char TXT_WOL_PAGE_NOTHERE[]\t\t\t= \"L'utilisateur spcifi n'a pas ouvert la session.\";\nconst char TXT_WOL_PAGE_OFF[]\t\t\t\t= \"L'utilisateur spcifi a dsactiv la fonction d'envoi de messages.\";\nconst char TXT_WOL_ONPAGE[]\t\t\t\t\t= \"Envoi de %s : %s\";\nconst char TXT_WOL_WASPAGED[]\t\t\t\t= \"Envoi  %s russi.\";\n//const char TXT_WOL_USERISSQUELCHED[]\t\t= \"%s a t rejet.\";\t\t\t\t//\tajw rejete really means squelched?\n//const char TXT_WOL_USERISNOTSQUELCHED[]\t\t= \"%s n'est plus rejet.\";\nconst char TXT_WOL_ONLYOWNERCANKICK[]\t\t= \"Seul le responsable du canal peut expulser des utilisateurs.\";\nconst char TXT_WOL_USERKICKEDUSER[]\t\t\t= \"%s expulse %s du canal.\";\nconst char TXT_WOL_USERKICKEDYOU[]\t\t\t= \"Vous tes expuls du canal par %s.\";\nconst char TXT_WOL_NOONETOKICK[]\t\t\t= \"Slectionnez l'(les) utilisateur(s) que vous voulez expulser.\";\nconst char TXT_WOL_USERWASBANNED[]\t\t\t= \"%s est exclu du canal.\";\nconst char TXT_WOL_CREATEPRIVGAMETITLE[]\t= \"Crer une partie prive\";\nconst char TXT_WOL_YOUREBANNED[]\t\t\t= \"Vous n'tes pas autoris  entrer dans ce canal.\";\nconst char TXT_WOL_PLAYERLEFTGAME[]\t\t\t= \"%s a quitt la partie.\";\nconst char TXT_WOL_PLAYERJOINEDGAME[]\t\t= \"%s a rejoint la partie.\";\nconst char TXT_WOL_YOUWEREKICKEDFROMGAME[]\t= \"Vous avez t expuls de la partie.\";\nconst char TXT_WOL_PERSONALWINLOSSRECORD[]\t= \"%s. Alerte Rouge: position %u. Vict. %u. Df. %u. Pts. %u.\";\nconst char TXT_WOL_PERSONALWINLOSSRECORDAM[]= \"%s. Missions M.A.D.: position %u. Vict. %u. Df. %u. Pts. %u.\";\nconst char TXT_WOL_USERRANK[]\t\t\t\t= \"%s (Position %u)\";\nconst char TXT_WOL_USERHOUSE[]\t\t\t\t= \"%s <%s>\";\nconst char TXT_WOL_USERRANKHOUSE[]\t\t\t= \"%s (Position %u) <%s>\";\nconst char TXT_WOL_STARTBUTTON[]\t\t\t= \"Dmarrer\";\nconst char TXT_WOL_ACCEPTBUTTON[]\t\t\t= \"Accepter\";\nconst char TXT_WOL_HOSTLEFTGAME[]\t\t\t= \"%s a annul la partie.\";\nconst char TXT_WOL_WAITINGTOSTART[]\t\t\t= \"Lancement de la partie...\";\nconst char TXT_WOL_TTIP_DISCON[]\t\t\t= \" Quitter Westwood Online \";\nconst char TXT_WOL_TTIP_LEAVE[]\t\t\t\t= \" Quitter le canal o vous vous trouvez \";\nconst char TXT_WOL_TTIP_REFRESH[]\t\t\t= \" Rafrachir la liste du canal \";\nconst char TXT_WOL_TTIP_SQUELCH[]\t\t\t= \" Activer/dsactiver les messages en provenance de(s) l'utilisateur(s) \";\nconst char TXT_WOL_TTIP_BAN[]\t\t\t\t= \" Exclure l'/les utilisateur(s)du canal \";\nconst char TXT_WOL_TTIP_KICK[]\t\t\t\t= \" Expulser l'/les utilisateurs du canal \";\nconst char TXT_WOL_TTIP_FINDPAGE[]\t\t\t= \" Rechercher ou envoyer un message  un utilisateur \";\nconst char TXT_WOL_TTIP_OPTIONS[]\t\t\t= \" Rgler les options de Westwood Online \";\nconst char TXT_WOL_TTIP_LADDER[]\t\t\t= \" Parcourir les hirarchies d'Alerte Rouge \";\nconst char TXT_WOL_TTIP_HELP[]\t\t\t\t= \" Afficher l'aide de Westwood Online \";\nconst char TXT_WOL_TTIP_START[]\t\t\t\t= \" Dmarrer le jeu \";\nconst char TXT_WOL_TTIP_ACCEPT[]\t\t\t= \" Valider les paramtres actuels du jeu \";\nconst char TXT_WOL_TTIP_EXPANDLIST[]\t\t= \" Complter/rduire la liste \";\nconst char TXT_WOL_TTIP_CANCELGAME[]\t\t= \" Retour au niveau prcdent \";\nconst char TXT_WOL_TTIP_JOIN[]\t\t\t\t= \" Rejoindre un canal de conversation/jeu \";\nconst char TXT_WOL_TTIP_BACK[]\t\t\t\t= \" Retour au niveau prcdent \";\nconst char TXT_WOL_TTIP_CREATE[]\t\t\t= \" Crer un nouveau canal de conversation/jeu \";\nconst char TXT_WOL_TTIP_ACTION[]\t\t\t= \" Message d'action \";\nconst char TXT_WOL_OPTFIND[]\t\t\t\t= \"Laisser les autres vous RECHERCHER.\";\nconst char TXT_WOL_OPTPAGE[]\t\t\t\t= \"Laisser les autres vous ENVOYER des messages.\";\nconst char TXT_WOL_OPTLANGUAGE[]\t\t\t= \"Filtrer les vulgarits.\";\nconst char TXT_WOL_OPTGAMESCOPE[]\t\t\t= \"Afficher seulement les parties en salons locaux.\";\n//const char TXT_WOL_OPTTITLE[]\t\t\t\t= \"Options\";\nconst char TXT_WOL_CHANNELGONE[]\t\t\t= \"Ce canal n'existe plus.\";\nconst char TXT_WOL_CG_TITLE[]\t\t\t\t= \"Crer une partie\";\nconst char TXT_WOL_CG_PLAYERS[]\t\t\t\t= \"Joueurs :  %i\";\nconst char TXT_WOL_CG_TOURNAMENT[]\t\t\t= \"Tournoi\";\nconst char TXT_WOL_CG_PRIVACY[]\t\t\t\t= \"Prive\";\nconst char TXT_WOL_CG_RAGAME[]\t\t\t\t= \"Partie Alerte Rouge\";\nconst char TXT_WOL_CG_CSGAME[]\t\t\t\t= \"Partie Missions Taga\";\nconst char TXT_WOL_CG_AMGAME[]\t\t\t\t= \"Partie Missions M.A.D.\";\nconst char TXT_WOL_NEEDCOUNTERSTRIKE[]\t\t= \"Dsol, vous devez installer Missions Taga pour jouer cette partie.\";\nconst char TXT_WOL_NEEDAFTERMATH[]\t\t\t= \"Dsol, vous devez installer Missions M.A.D. pour jouer cette partie.\";\nconst char TXT_WOL_TTIP_CHANLIST_CHAT[]\t\t= \" Double-clic pour rejoindre canal %s (%i utilisateurs). \";\nconst char TXT_WOL_TTIP_CHANLIST_LOBBY[]\t= \" Double-clic pour rejoindre salon %s (%i utilisateurs). \";\nconst char TXT_WOL_TTIP_REDALERT[]\t\t\t= \"Alerte Rouge\";\nconst char TXT_WOL_TTIP_COUNTERSTRIKE[]\t\t= \"Missions Taga\";\nconst char TXT_WOL_TTIP_AFTERMATH[]\t\t\t= \"Missions M.A.D.\";\nconst char TXT_WOL_TTIP_CHANLIST_RAGAME[]\t= \" Partie de %s (%i joueurs pour un max. de %i). \";\nconst char TXT_WOL_TTIP_CHANLIST_GAME[]\t\t= \" Partie de %s (%i joueurs). \";\nconst char TXT_WOL_TTIP_PRIVATEGAME[]\t\t= \"(Prive) \";\nconst char TXT_WOL_TTIP_TOURNAMENTGAME[]\t= \"(Tournoi) \";\nconst char TXT_WOL_TTIP_CHANNELTYPE_GAMESOFTYPE[]\t= \" Double-clic pour afficher les parties %s. \";\nconst char TXT_WOL_TOURNAMENTPLAYERLIMIT[]\t= \"Les parties en tournoi doivent rassembler deux joueurs.\";\nconst char TXT_WOL_PRIVATEPASSWORD[]\t\t= \"Mot de passe : %s\";\nconst char TXT_WOL_RULESMISMATCH[]\t\t\t= \"Votre partie n'est pas compatible avec celle du serveur !\";\nconst char TXT_WOL_STARTTIMEOUT[]\t\t\t= \"Expiration du temps de rponse des clients ! Dmarrage du jeu annul.\";\nconst char TXT_WOL_STARTCANCELLED[]\t\t\t= \"Dmarrage du jeu annul.\";\nconst char TXT_WOL_CANCELGAME[]\t\t\t\t= \"Retour\";\nconst char TXT_WOL_PATCHQUESTION[]\t\t\t= \"Un patch mis  jour est ncessaire pour le jeu sur Internet. Voulez-vous le tlcharger maintenant ?\";\nconst char TXT_WOL_DOWNLOADING[]\t\t\t= \"Tlcharger %i fichier(s) sur %i.\";\nconst char TXT_WOL_DOWNLOADERROR[]\t\t\t= \"Erreur lors du tlchargement du fichier.\";\nconst char TXT_WOL_DOWNLOADBYTES[]\t\t\t= \"Rception de %i octets sur %i. (%i%%%%).\";\nconst char TXT_WOL_DOWNLOADTIME[]\t\t\t= \"Temps restant : %i min. %i secs.\";\nconst char TXT_WOL_DOWNLOADRESUMED[]\t\t= \"%s (reprise aprs interruption.)\";\nconst char TXT_WOL_DOWNLOADCONNECTING[]\t\t= \"Etat : en cours de connexion...\";\nconst char TXT_WOL_DOWNLOADLOCATING[]\t\t= \"Etat : recherche du fichier...\";\nconst char TXT_WOL_DOWNLOADDOWNLOADING[]\t= \"Etat : en cours de tlchargement...\";\nconst char TXT_WOL_DOWNLOADEXITWARNING[]\t= \"Tlchargement termin ! Alerte Rouge est relanc pour que le nouveau patch soit pris en compte.\";\nconst char TXT_WOL_HELPSHELL[]\t\t\t\t= \"Voulez-vous vraiment lancer le navigateur Internet pour obtenir l'aide Westwood Online ?\";\nconst char TXT_WOL_LADDERSHELL[]\t\t\t= \"Voulez-vous vraiment lancer le navigateur Internet pour les hirarchies d'Alerte Rouge ?\";\nconst char TXT_WOL_WEBREGISTRATIONSHELL[]\t= \"Aucun nom d'utilisateur sauvegard. Voulez-vous enregistrer un nouveau nom d'utilisateur pour Westwood Online ?\";\nconst char TXT_WOL_GAMEADVERTSHELL[]\t\t= \"Voulez-vous vraiment lancer le navigateur Internet pour obtenir des informations sur %s ?\";\nconst char TXT_WOL_USERLIST[]\t\t\t\t= \"Utilisateurs %i\";\nconst char TXT_WOL_NOUSERLIST[]\t\t\t\t= \"(absent du canal)\";\nconst char TXT_WOL_CANTCREATEHERE[]\t\t\t= \"Pour commencer une partie, vous devez tre dans un salon d'Alerte Rouge.\";\nconst char TXT_WOL_WOLAPIGONE[]\t\t\t\t= \"Perte de connexion avec Westwood Online !\";\nconst char TXT_WOL_WOLAPIREINIT[]\t\t\t= \"Perte de connexion avec Westwood Online. Rinitialisation en cours...\";\nconst char TXT_WOL_NOTPAGED[]\t\t\t\t= \"Impossible de rpondre au message ; personne ne vous en a envoy.\";\nconst char TXT_WOL_SCENARIONAMEWAIT[]\t\t= \"En attente du scnario...\";\nconst char TXT_WOL_BACK[]\t\t\t\t\t= \"Retour\";\nconst char TXT_WOL_AMDISCNEEDED[]\t\t\t= \"Le CD de Missions M.A.D. est ncessaire pour cette partie ; insrez-le maintenant.\";\nconst char TXT_WOL_CONFIRMLOGOUT[]\t\t\t= \"Voulez-vous vraiment quitter Westwood Online ?\";\nconst char TXT_WOL_PROPOSE_DRAW[]\t\t\t= \"Proposer une fin avec galit\";\nconst char TXT_WOL_RETRACT_DRAW[]\t\t\t= \"Annuler la proposition de fin avec galit\";\nconst char TXT_WOL_ACCEPT_DRAW[]\t\t\t= \"Accepter la proposition de fin avec galit\";\nconst char TXT_WOL_PROPOSE_DRAW_CONFIRM[]\t= \"Voulez-vous vraiment proposer une fin avec galit ?\";\nconst char TXT_WOL_ACCEPT_DRAW_CONFIRM[]\t= \"Voulez-vous vraiment accepter une fin avec galit ?\" ;\nconst char TXT_WOL_DRAW_PROPOSED_LOCAL[]\t= \"Vous proposez de terminer la partie sans vainqueur ni perdant.\";\nconst char TXT_WOL_DRAW_PROPOSED_OTHER[]\t= \"%s a propos de terminer la partie sans vainqueur ni perdant.\";\nconst char TXT_WOL_DRAW_RETRACTED_LOCAL[]\t= \"Vous avez annul votre proposition de terminer la partie sans vainqueur ni perdant.\";\nconst char TXT_WOL_DRAW_RETRACTED_OTHER[]\t= \"%s a annul sa proposition de terminer la partie sans vainqueur ni perdant.\";\nconst char TXT_WOL_DRAW[]\t\t\t\t\t= \"Match nul\";\nconst char TXT_WOL_CANTLAUNCHBROWSER[]\t\t= \"Impossible de lancer le navigateur web pour ouvrir %s !\";\nconst char TXT_WOL_CHANNELFULL[]\t\t\t= \"Ce canal de jeu/conversation est satur.\";\nconst char TXT_WOL_CHANNELTYPE_TOP[]\t\t\t= \" Double-clic pour retourner au premier niveau. \";\nconst char TXT_WOL_CHANNELTYPE_OFFICIALCHAT[]\t= \" Double-clic pour les canaux de conversation officiels. \";\nconst char TXT_WOL_CHANNELTYPE_USERCHAT[]\t\t= \" Double-clic pour les canaux d' utilisateur. \";\nconst char TXT_WOL_CHANNELTYPE_GAMES[]\t\t\t= \" Double-clic pour accder au niveau des canaux de jeu. \";\nconst char TXT_WOL_CHANNELTYPE_LOADING[]\t\t= \" Chargement de la liste depuis Westwood Online, veuillez patienter...\";\nconst char TXT_WOL_CHANNELTYPE_LOBBIES[]\t\t= \" Double-clic pour accder au niveau des salons. \";\nconst char TXT_WOL_FINDINGLOBBY[]\t\t\t\t= \"Connection : recherche de salons disponibles...\";\nconst char TXT_WOL_PRIVATETOMULTIPLE[]\t\t\t= \"<Message personnel adress  divers utilisateurs> :\";\nconst char TXT_WOL_PRIVATETO[]\t\t\t\t\t= \"Message personnel \";\nconst char TXT_WOL_CS_MISSIONS[]\t\t\t\t= \"Missions extraites de Missions Taga\";\nconst char TXT_WOL_AM_MISSIONS[]\t\t\t\t= \"Missions extraites de Missions M.A.D.\";\nconst char TXT_WOL_CANTSQUELCHSELF[]\t\t\t= \"Vous ne pouvez pas dsactiver vos propres messages!\";\nconst char TXT_WOL_OPTTITLE[]\t\t\t\t\t= \"Options de Westwood Online\";\nconst char TXT_WOL_SLOWUNITBUILD[]\t\t\t\t= \"Ralentir la Construction\";\nconst char TXT_WOL_THEGAMEHOST[]\t\t\t\t= \"Le serveur\";\nconst char TXT_WOL_TTIP_RANKRA[]\t\t\t\t= \" Afficher les positions d'Alerte Rouge \";\nconst char TXT_WOL_TTIP_RANKAM[]\t\t\t\t= \" Afficher les positions de Missions M.A.D. \";\nconst char TXT_WOL_OPTRANKAM[]\t\t\t\t\t= \"Afficher les positions de Missions M.A.D.\";\nconst char TXT_WOL_CANCELMEANSFORFEIT[]\t\t\t= \" (ET RENONCER AU JEU)\";\nconst char TXT_WOL_DLLERROR_GETIE3[]\t\t\t= \"Votre version des Windows est dmode. Amliorez s'il vous plait aux Windows SP1, ou installez l'Internet Explorer 3,0 ou plus haut.\";\nconst char TXT_WOL_DLLERROR_CALLUS[]\t\t\t= \"Une erreur inattendue s'est produite. Veuillez contacter l'assistance technique de Electronic Arts.\";\nconst char TXT_WOL_PRIVATE[]\t\t\t\t\t= \"<personnel>\";\n\n#endif\n\n#endif\n\n\n#endif\n"
  },
  {
    "path": "CODE/WOLSTRNG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n//\tWolstrng.h - this will presumably go away eventually.\n\n//\tNew character strings.\n\nextern const char TXT_WOL_INTERNETBUTTON[];\nextern const char TXT_WOL_ERRORMESSAGE[];\nextern const char TXT_WOL_CONNECT[];\nextern const char TXT_WOL_LOGINDIALOG[];\nextern const char TXT_WOL_NAME[];\nextern const char TXT_WOL_PASSWORD[];\nextern const char TXT_WOL_SAVELOGIN[];\nextern const char TXT_WOL_LOGINCANCEL[];\nextern const char TXT_WOL_MISSINGNAME[];\nextern const char TXT_WOL_MISSINGPASSWORD[];\nextern const char TXT_WOL_CANTSAVENICK[];\nextern const char TXT_WOL_NICKINUSE[];\nextern const char TXT_WOL_BADPASS[];\nextern const char TXT_WOL_TIMEOUT[];\nextern const char TXT_WOL_CONNECTING[];\nextern const char TXT_WOL_CANTCONNECT[];\nextern const char TXT_WOL_ATTEMPTLOGIN[];\nextern const char TXT_WOL_ATTEMPTLOGOUT[];\nextern const char TXT_WOL_ERRORLOGOUT[];\nextern const char TXT_WOL_WAIT[];\nextern const char TXT_WOL_OFFICIALCHAT[];\nextern const char TXT_WOL_USERCHAT[];\nextern const char TXT_WOL_YOURENOTINCHANNEL[];\nextern const char TXT_WOL_ACTION[];\nextern const char TXT_WOL_JOIN[];\nextern const char TXT_WOL_CANTCREATEINCHANNEL[];\nextern const char TXT_WOL_NEWSOMETHING[];\nextern const char TXT_WOL_CREATECHANNELTITLE[];\nextern const char TXT_WOL_CREATECHANNELPROMPT[];\nextern const char TXT_WOL_PASSPROMPT[];\nextern const char TXT_WOL_OPTIONALPASSPROMPT[];\nextern const char TXT_WOL_CHANNEL_TOP[];\nextern const char TXT_WOL_CHANNEL_BACK[];\nextern const char TXT_WOL_YOUJOINED[];\nextern const char TXT_WOL_YOUJOINEDGAME[];\nextern const char TXT_WOL_YOUCREATEDGAME[];\nextern const char TXT_WOL_YOUJOINEDLOBBY[];\nextern const char TXT_WOL_YOULEFT[];\nextern const char TXT_WOL_YOULEFTLOBBY[];\nextern const char TXT_WOL_JOINPRIVATETITLE[];\nextern const char TXT_WOL_JOINPRIVATEPROMPT[];\nextern const char TXT_WOL_BADCHANKEY[];\nextern const char TXT_WOL_PAGELOCATE[];\nextern const char TXT_WOL_USERNAMEPROMPT[];\nextern const char TXT_WOL_PAGE[];\nextern const char TXT_WOL_LOCATE[];\nextern const char TXT_WOL_LOCATING[];\nextern const char TXT_WOL_FIND_NOTHERE[];\nextern const char TXT_WOL_FIND_NOCHAN[];\nextern const char TXT_WOL_FIND_OFF[];\nextern const char TXT_WOL_FOUNDIN[];\nextern const char TXT_WOL_PAGEMESSAGETITLE[];\nextern const char TXT_WOL_PAGEMESSAGEPROMPT[];\nextern const char TXT_WOL_PAGING[];\nextern const char TXT_WOL_PAGE_NOTHERE[];\nextern const char TXT_WOL_PAGE_OFF[];\nextern const char TXT_WOL_ONPAGE[];\nextern const char TXT_WOL_WASPAGED[];\n//extern const char TXT_WOL_USERISSQUELCHED[];\n//extern const char TXT_WOL_USERISNOTSQUELCHED[];\nextern const char TXT_WOL_ONLYOWNERCANKICK[];\nextern const char TXT_WOL_USERKICKEDUSER[];\nextern const char TXT_WOL_USERKICKEDYOU[];\nextern const char TXT_WOL_NOONETOKICK[];\nextern const char TXT_WOL_USERWASBANNED[];\nextern const char TXT_WOL_GAMECHANNELS[];\nextern const char TXT_WOL_CHANNELLISTLOADING[];\nextern const char TXT_WOL_CREATEPRIVGAMETITLE[];\nextern const char TXT_WOL_YOUREBANNED[];\nextern const char TXT_WOL_PLAYERLEFTGAME[];\nextern const char TXT_WOL_PLAYERJOINEDGAME[];\nextern const char TXT_WOL_YOUWEREKICKEDFROMGAME[];\nextern const char TXT_WOL_PERSONALWINLOSSRECORD[];\nextern const char TXT_WOL_PERSONALWINLOSSRECORDAM[];\nextern const char TXT_WOL_USERRANK[];\nextern const char TXT_WOL_USERHOUSE[];\nextern const char TXT_WOL_USERRANKHOUSE[];\nextern const char TXT_WOL_STARTBUTTON[];\nextern const char TXT_WOL_ACCEPTBUTTON[];\nextern const char TXT_WOL_HOSTLEFTGAME[];\nextern const char TXT_WOL_WAITINGTOSTART[];\nextern const char TXT_WOL_TTIP_DISCON[];\nextern const char TXT_WOL_TTIP_LEAVE[];\nextern const char TXT_WOL_TTIP_REFRESH[];\nextern const char TXT_WOL_TTIP_SQUELCH[];\nextern const char TXT_WOL_TTIP_BAN[];\nextern const char TXT_WOL_TTIP_KICK[];\nextern const char TXT_WOL_TTIP_FINDPAGE[];\nextern const char TXT_WOL_TTIP_OPTIONS[];\nextern const char TXT_WOL_TTIP_LADDER[];\nextern const char TXT_WOL_TTIP_HELP[];\nextern const char TXT_WOL_TTIP_START[];\nextern const char TXT_WOL_TTIP_ACCEPT[];\nextern const char TXT_WOL_TTIP_EXPANDLIST[];\nextern const char TXT_WOL_TTIP_CANCELGAME[];\nextern const char TXT_WOL_TTIP_JOIN[];\nextern const char TXT_WOL_TTIP_BACK[];\nextern const char TXT_WOL_TTIP_CREATE[];\nextern const char TXT_WOL_TTIP_ACTION[];\nextern const char TXT_WOL_OPTFIND[];\nextern const char TXT_WOL_OPTPAGE[];\nextern const char TXT_WOL_OPTLANGUAGE[];\nextern const char TXT_WOL_OPTGAMESCOPE[];\nextern const char TXT_WOL_OPTTITLE[];\nextern const char TXT_WOL_REDALERTLOBBIES[];\nextern const char TXT_WOL_TOPLEVELTITLE[];\nextern const char TXT_WOL_CHANNELGONE[];\nextern const char TXT_WOL_CG_TITLE[];\nextern const char TXT_WOL_CG_PLAYERS[];\nextern const char TXT_WOL_CG_TOURNAMENT[];\nextern const char TXT_WOL_CG_PRIVACY[];\nextern const char TXT_WOL_CG_RAGAME[];\nextern const char TXT_WOL_CG_CSGAME[];\nextern const char TXT_WOL_CG_AMGAME[];\nextern const char TXT_WOL_NEEDCOUNTERSTRIKE[];\nextern const char TXT_WOL_NEEDAFTERMATH[];\nextern const char TXT_WOL_TTIP_CHANLIST_CHAT[];\nextern const char TXT_WOL_TTIP_CHANLIST_LOBBY[];\nextern const char TXT_WOL_TTIP_REDALERT[];\nextern const char TXT_WOL_TTIP_COUNTERSTRIKE[];\nextern const char TXT_WOL_TTIP_AFTERMATH[];\nextern const char TXT_WOL_TTIP_CHANLIST_RAGAME[];\nextern const char TXT_WOL_TTIP_CHANLIST_GAME[];\nextern const char TXT_WOL_TTIP_PRIVATEGAME[];\nextern const char TXT_WOL_TTIP_TOURNAMENTGAME[];\nextern const char TXT_WOL_TTIP_CHANNELTYPE_GAMESOFTYPE[];\nextern const char TXT_WOL_TOURNAMENTPLAYERLIMIT[];\nextern const char TXT_WOL_PRIVATEPASSWORD[];\nextern const char TXT_WOL_RULESMISMATCH[];\nextern const char TXT_WOL_STARTTIMEOUT[];\nextern const char TXT_WOL_CANCELGAME[];\nextern const char TXT_WOL_PATCHQUESTION[];\nextern const char TXT_WOL_DOWNLOADING[];\nextern const char TXT_WOL_DOWNLOADERROR[];\nextern const char TXT_WOL_DOWNLOADBYTES[];\nextern const char TXT_WOL_DOWNLOADTIME[];\nextern const char TXT_WOL_DOWNLOADRESUMED[];\nextern const char TXT_WOL_DOWNLOADCONNECTING[];\nextern const char TXT_WOL_DOWNLOADLOCATING[];\nextern const char TXT_WOL_DOWNLOADDOWNLOADING[];\nextern const char TXT_WOL_DOWNLOADEXITWARNING[];\nextern const char TXT_WOL_HELPSHELL[];\nextern const char TXT_WOL_LADDERSHELL[];\nextern const char TXT_WOL_WEBREGISTRATIONSHELL[];\nextern const char TXT_WOL_GAMEADVERTSHELL[];\nextern const char TXT_WOL_USERLIST[];\nextern const char TXT_WOL_NOUSERLIST[];\nextern const char TXT_WOL_STARTCANCELLED[];\nextern const char TXT_WOL_CANTCREATEHERE[];\nextern const char TXT_WOL_WOLAPIGONE[];\nextern const char TXT_WOL_WOLAPIREINIT[];\nextern const char TXT_WOL_NOTPAGED[];\nextern const char TXT_WOL_SCENARIONAMEWAIT[];\nextern const char TXT_WOL_BACK[];\nextern const char TXT_WOL_AMDISCNEEDED[];\nextern const char TXT_WOL_CONFIRMLOGOUT[];\nextern const char TXT_WOL_PROPOSE_DRAW[];\nextern const char TXT_WOL_RETRACT_DRAW[];\nextern const char TXT_WOL_ACCEPT_DRAW[];\nextern const char TXT_WOL_PROPOSE_DRAW_CONFIRM[];\nextern const char TXT_WOL_ACCEPT_DRAW_CONFIRM[];\nextern const char TXT_WOL_DRAW_PROPOSED_LOCAL[];\nextern const char TXT_WOL_DRAW_PROPOSED_OTHER[];\nextern const char TXT_WOL_DRAW_RETRACTED_LOCAL[];\nextern const char TXT_WOL_DRAW_RETRACTED_OTHER[];\nextern const char TXT_WOL_DRAW[];\nextern const char TXT_WOL_CANTLAUNCHBROWSER[];\nextern const char TXT_WOL_CHANNELFULL[];\nextern const char TXT_WOL_CHANNELTYPE_TOP[];\nextern const char TXT_WOL_CHANNELTYPE_OFFICIALCHAT[];\nextern const char TXT_WOL_CHANNELTYPE_USERCHAT[];\nextern const char TXT_WOL_CHANNELTYPE_GAMES[];\nextern const char TXT_WOL_CHANNELTYPE_LOADING[];\nextern const char TXT_WOL_CHANNELTYPE_LOBBIES[];\nextern const char TXT_WOL_FINDINGLOBBY[];\nextern const char TXT_WOL_PRIVATETOMULTIPLE[];\nextern const char TXT_WOL_PRIVATETO[];\nextern const char TXT_WOL_CS_MISSIONS[];\nextern const char TXT_WOL_AM_MISSIONS[];\nextern const char TXT_WOL_CANTSQUELCHSELF[];\nextern const char TXT_WOL_SLOWUNITBUILD[];\nextern const char TXT_WOL_THEGAMEHOST[];\nextern const char TXT_WOL_TTIP_RANKRA[];\nextern const char TXT_WOL_TTIP_RANKAM[];\nextern const char TXT_WOL_OPTRANKAM[];\nextern const char TXT_WOL_CANCELMEANSFORFEIT[];\nextern const char TXT_WOL_DLLERROR_GETIE3[];\nextern const char TXT_WOL_DLLERROR_CALLUS[];\nextern const char TXT_WOL_PRIVATE[];\n\n"
  },
  {
    "path": "CODE/WOL_CGAM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifdef WOLAPI_INTEGRATION\t\t\t//\tImplies FIXIT_CSII.\n\n//\tWol_CGam.cpp - Create game dialog.\n//\tajw 09/9/98\n\n#include \"function.h\"\n\n#ifndef FIXIT_CSII\n#error FIXIT_CSII must be defined.\n#endif\n\n#include \"IconList.h\"\n#include \"WolapiOb.h\"\n#include \"WolStrng.h\"\n#include \"SEditDlg.h\"\n#include \"BigCheck.h\"\n\n//extern char* LoadShpFile( const char* szShpFile );\nvoid SetPlayerCountList( IconListClass& PlayerCountList, int iPlayerMax, char* pShpBoxCheck, char* pShpBoxEmpty );\n\n//***********************************************************************************************\nCREATEGAMEINFO WOL_CreateGame_Dialog( WolapiObject* pWO )\n{\n\tCREATEGAMEINFO cgiReturn;\n\tcgiReturn.bCreateGame = false;\n\tcgiReturn.iPlayerMax = 2;\n\tcgiReturn.bTournament = false;\n\tcgiReturn.bPrivate = false;\n\tcgiReturn.GameKind = CREATEGAMEINFO::RAGAME;\n\t*cgiReturn.szPassword = 0;\n\n\tbool bEscapeDown = false;\n\tbool bReturnDown = false;\n\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tint d_dialog_w = 150 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 135 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = (((320 * RESFACTOR) - d_dialog_w) / 2);\n\tint d_dialog_y = (((200 * RESFACTOR) - d_dialog_h) / 2);\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// coord of x-center\n\n\tint d_txt8_h = 11 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// ht of 8-pt text\n\tint d_margin = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\tint x_margin = 16 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint top_margin = 0;\n\n\tint d_gaugeplayers_w = 70 * RESFACTOR;\n\tint d_gaugeplayers_h = 9 * RESFACTOR;\n\tint d_gaugeplayers_x = d_dialog_cx - d_gaugeplayers_w / 2;\n\tint d_gaugeplayers_y = d_dialog_y + d_margin + 42;\n\n\tint d_checktourn_w = 75 * RESFACTOR;\n\tint d_checktourn_h = 9 * RESFACTOR;\n\tint d_checktourn_x = d_dialog_cx - d_checktourn_w / 2;\n\tint d_checktourn_y = d_gaugeplayers_y + d_gaugeplayers_h + 10;\n\n\tint d_checkpriv_w = d_checktourn_w;\n\tint d_checkpriv_h = 9 * RESFACTOR;\n\tint d_checkpriv_x = d_checktourn_x;\n\tint d_checkpriv_y = d_checktourn_y + d_checktourn_h + 10;\n\n\tint d_checkra_w = d_checktourn_w;\n\tint d_checkra_h = 9 * RESFACTOR;\n\tint d_checkra_x = d_checktourn_x;\n\tint d_checkra_y = d_checkpriv_y + d_checkpriv_h + 20;\n\n\tint d_checkcs_w = d_checktourn_w;\n\tint d_checkcs_h = 9 * RESFACTOR;\n\tint d_checkcs_x = d_checktourn_x;\n\tint d_checkcs_y = d_checkra_y + d_checkra_h + 5;\n\n\tint d_checkam_w = d_checktourn_w;\n\tint d_checkam_h = 9 * RESFACTOR;\n\tint d_checkam_x = d_checktourn_x;\n\tint d_checkam_y = d_checkcs_y + d_checkcs_h + 5;\n\n#if (GERMAN | FRENCH)\n\tint d_ok_w = 30 * RESFACTOR;\n#else\n\tint d_ok_w = 30 * RESFACTOR;\n#endif\n\tint d_ok_h = 13 * RESFACTOR;\n\tint d_ok_x = d_dialog_x + ( d_dialog_w / 3 ) - ( d_ok_w / 2 );\n\tint d_ok_y = d_dialog_y + d_dialog_h - d_ok_h - d_margin;\n\n\tint d_cancel_w = 40 * RESFACTOR;\n\tint d_cancel_h = 9 * RESFACTOR;\n\tint d_cancel_x = d_dialog_x + ( ( d_dialog_w * 2 ) / 3 ) - ( d_cancel_w / 2 );\n\tint d_cancel_y = d_ok_y;\n\n\t/*\n\t**\tButton enumerations\n\t*/\n\tenum {\n\t\tBUTTON_OK = 100,\n\t\tBUTTON_CANCEL,\n\t\tGAUGE_PLAYERCOUNT,\n\t\tCHECK_TOURNAMENT,\n\t\tCHECK_PRIVACY,\n\t\tCHECK_RA,\n\t\tCHECK_CS,\n\t\tCHECK_AM,\n\t};\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass* commands = NULL;\t\t// the button list\n\n\tTextButtonClass OkBtn( BUTTON_OK, TXT_OK, TPF_BUTTON, d_ok_x, d_ok_y, d_ok_w );\n\tTextButtonClass CancelBtn( BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w );\n\n\tStaticButtonClass PlayerCountStatic( 0, \"               \", TPF_TEXT, d_gaugeplayers_x, d_gaugeplayers_y - 16 );\n\tGaugeClass PlayerCountGauge( GAUGE_PLAYERCOUNT, d_gaugeplayers_x, d_gaugeplayers_y, d_gaugeplayers_w, d_gaugeplayers_h );\n\n\tif( pWO->bEgg8Player )\n\t\tPlayerCountGauge.Set_Maximum( 6 );\n\telse\n\t\tPlayerCountGauge.Set_Maximum( 2 );\n\tPlayerCountGauge.Set_Value( cgiReturn.iPlayerMax - 2 );\n\n\tBigCheckBoxClass TournamentCheck( CHECK_TOURNAMENT, d_checktourn_x, d_checktourn_y, d_checktourn_w, d_checktourn_h,\n\t\t\t\t\t\t\t\t\t\tTXT_WOL_CG_TOURNAMENT, TPF_6PT_GRAD | TPF_NOSHADOW, cgiReturn.bTournament );\n\n\tBigCheckBoxClass PrivacyCheck( CHECK_PRIVACY, d_checkpriv_x, d_checkpriv_y, d_checkpriv_w, d_checkpriv_h,\n\t\t\t\t\t\t\t\t\t\tTXT_WOL_CG_PRIVACY, TPF_6PT_GRAD | TPF_NOSHADOW, cgiReturn.bPrivate );\n\n\tBigCheckBoxClass RA_Check( CHECK_RA, d_checkra_x, d_checkra_y, d_checkra_w, d_checkra_h,\n\t\t\t\t\t\t\t\t\t\tTXT_WOL_CG_RAGAME, TPF_6PT_GRAD | TPF_NOSHADOW, cgiReturn.GameKind == CREATEGAMEINFO::RAGAME );\n\tBigCheckBoxClass CS_Check( CHECK_CS, d_checkcs_x, d_checkcs_y, d_checkcs_w, d_checkcs_h,\n\t\t\t\t\t\t\t\t\t\tTXT_WOL_CG_CSGAME, TPF_6PT_GRAD | TPF_NOSHADOW, cgiReturn.GameKind == CREATEGAMEINFO::CSGAME );\n\tBigCheckBoxClass AM_Check( CHECK_AM, d_checkam_x, d_checkam_y, d_checkam_w, d_checkam_h,\n\t\t\t\t\t\t\t\t\t\tTXT_WOL_CG_AMGAME, TPF_6PT_GRAD | TPF_NOSHADOW, cgiReturn.GameKind == CREATEGAMEINFO::AMGAME );\n\n\tif( !Is_Counterstrike_Installed() )\n\t\tCS_Check.Disable();\n\n\tif( !Is_Aftermath_Installed() )\n\t\tAM_Check.Disable();\n\n\t/*\n\t**\tInitialize.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tCreate the button list.\n\t*/\n\tcommands = &OkBtn;\n\tCancelBtn.Add_Tail(*commands);\n\tPlayerCountStatic.Add_Tail(*commands);\n\tPlayerCountGauge.Add_Tail(*commands);\n\tTournamentCheck.Add_Tail(*commands);\n\tPrivacyCheck.Add_Tail(*commands);\n\tRA_Check.Add_Tail(*commands);\n\tCS_Check.Add_Tail(*commands);\n\tAM_Check.Add_Tail(*commands);\n\n\tchar szPlayerCount[ 100 ];\n\tsprintf( szPlayerCount, TXT_WOL_CG_PLAYERS, cgiReturn.iPlayerMax );\n\tPlayerCountStatic.Set_Text( szPlayerCount );\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tKeyboard->Clear();\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tCall_Back();\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = true;\n\t\t}\n\t\t#endif\n\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\n\t\t\t/*\n\t\t\t**\tDisplay the dialog box.\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\t\t\tDraw_Caption( TXT_WOL_CG_TITLE, d_dialog_x, d_dialog_y, d_dialog_w );\n//\t\t\tFancy_Text_Print( TXT_WOL_CG_PLAYERS, d_gaugeplayers_x - 2*RESFACTOR, d_gaugeplayers_y, \n//\t\t\t\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT | TPF_RIGHT );\n\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t//\tForce mouse visible, as some beta testers report unexplicable disappearing cursors.\n\t\twhile( Get_Mouse_State() )\n\t\t\tShow_Mouse();\n\t\t//\tBe nice to other apps.\n\t\tSleep( 50 );\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t//\tMy hack for triggering escape and return on key up instead of down...\n\t\t//\tThe problem that was occurring was that the calling dialog would act on the key up,\n\t\t//\tthough this dialog handled the key down. ajw\n\t\tif( ( ::GetAsyncKeyState( VK_ESCAPE ) & 0x8000 ) )\n\t\t{\n\t\t\tbEscapeDown = true;\n\t\t}\n\t\telse if( bEscapeDown )\n\t\t{\n\t\t\tinput = (KeyNumType)( BUTTON_CANCEL | KN_BUTTON );\n\t\t\tbEscapeDown = false;\n\t\t}\n\t\tif( ( ::GetAsyncKeyState( VK_RETURN ) & 0x8000 ) )\n\t\t{\n\t\t\tbReturnDown = true;\n\t\t}\n\t\telse if( bReturnDown )\n\t\t{\n\t\t\tinput = (KeyNumType)( BUTTON_OK | KN_BUTTON );\n\t\t\tbReturnDown = false;\n\t\t}\n\n\t\t/*\n\t\t**\tProcess input.\n\t\t*/\n\n\t\tswitch( input )\n\t\t{\n\t\t\tcase ( BUTTON_OK | KN_BUTTON ):\n\t\t\t\tcgiReturn.bCreateGame = true;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_CANCEL | KN_BUTTON ):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase ( GAUGE_PLAYERCOUNT | KN_BUTTON ):\n\t\t\t\tif( PlayerCountGauge.Get_Value() != 0 && cgiReturn.bTournament )\n\t\t\t\t{\n\t\t\t\t\tWWMessageBox().Process( TXT_WOL_TOURNAMENTPLAYERLIMIT );\n\t\t\t\t\tPlayerCountGauge.Set_Value( 0 );\n\t\t\t\t\tdisplay = true;\n\t\t\t\t}\n\t\t\t\tcgiReturn.iPlayerMax = PlayerCountGauge.Get_Value() + 2;\n\t\t\t\tsprintf( szPlayerCount, TXT_WOL_CG_PLAYERS, cgiReturn.iPlayerMax );\n\t\t\t\tPlayerCountStatic.Set_Text( szPlayerCount );\n\t\t\t\tPlayerCountStatic.Draw_Me();\n\t\t\t\tbreak;\n\n\t\t\tcase ( CHECK_TOURNAMENT | KN_BUTTON ):\n\t\t\t\tcgiReturn.bTournament = TournamentCheck.IsOn;\n\t\t\t\tif( cgiReturn.bTournament )\n\t\t\t\t{\n\t\t\t\t\tPlayerCountGauge.Set_Value( 0 );\n//\t\t\t\t\tPlayerCountGauge.Disable();\n\t\t\t\t\tcgiReturn.iPlayerMax = 2;\n\t\t\t\t\tsprintf( szPlayerCount, TXT_WOL_CG_PLAYERS, cgiReturn.iPlayerMax );\n\t\t\t\t\tPlayerCountStatic.Set_Text( szPlayerCount );\n\t\t\t\t\tPlayerCountStatic.Draw_Me();\n\t\t\t\t}\n//\t\t\t\telse\n//\t\t\t\t\tPlayerCountGauge.Enable();\n\t\t\t\tbreak;\n\n\t\t\tcase ( CHECK_PRIVACY | KN_BUTTON ):\n\t\t\t\tcgiReturn.bPrivate = PrivacyCheck.IsOn;\n\t\t\t\tbreak;\n\n\t\t\tcase ( CHECK_RA | KN_BUTTON ):\n\t\t\t\tif( RA_Check.IsOn )\n\t\t\t\t{\n\t\t\t\t\t//\tBox was checked.\n\t\t\t\t\tCS_Check.Turn_Off();\n\t\t\t\t\tAM_Check.Turn_Off();\n\t\t\t\t\tcgiReturn.GameKind = CREATEGAMEINFO::RAGAME;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t//\tBox was unchecked. Has no effect.\n\t\t\t\t\tRA_Check.Turn_On();\n\t\t\t\tbreak;\n\t\t\tcase ( CHECK_CS | KN_BUTTON ):\n\t\t\t\tif( CS_Check.IsOn )\n\t\t\t\t{\n\t\t\t\t\t//\tBox was checked.\n\t\t\t\t\tRA_Check.Turn_Off();\n\t\t\t\t\tAM_Check.Turn_Off();\n\t\t\t\t\tcgiReturn.GameKind = CREATEGAMEINFO::CSGAME;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t//\tBox was unchecked. Has no effect.\n\t\t\t\t\tCS_Check.Turn_On();\n\t\t\t\tbreak;\n\t\t\tcase ( CHECK_AM | KN_BUTTON ):\n\t\t\t\tif( AM_Check.IsOn )\n\t\t\t\t{\n\t\t\t\t\t//\tBox was checked.\n\t\t\t\t\tRA_Check.Turn_Off();\n\t\t\t\t\tCS_Check.Turn_Off();\n\t\t\t\t\tcgiReturn.GameKind = CREATEGAMEINFO::AMGAME;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t//\tBox was unchecked. Has no effect.\n\t\t\t\t\tAM_Check.Turn_On();\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif( cgiReturn.bCreateGame && cgiReturn.bPrivate )\n\t{\n\t\t//\tGet a password for the channel.\n\t\tFancy_Text_Print( TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT );\t//\tRequired before String_Pixel_Width() call, for god's sake.\n\t\tSimpleEditDlgClass* pEditDlg = new SimpleEditDlgClass( 300, TXT_WOL_CREATEPRIVGAMETITLE, \n\t\t\t\t\t\t\t\t\t\t\t\tTXT_WOL_PASSPROMPT, WOL_CHANKEY_LEN_MAX );\n\t\tpWO->bPump_In_Call_Back = true;\n\t\tif( strcmp( pEditDlg->Show(), Text_String( TXT_OK ) ) == 0 && *pEditDlg->szEdit )\n\t\t\tstrcpy( cgiReturn.szPassword, pEditDlg->szEdit );\n\t\telse\n\t\t\tcgiReturn.bCreateGame = false;\t\t//\tCancel creation.\n\t\tpWO->bPump_In_Call_Back = false;\n\t}\n\n\treturn cgiReturn;\n}\n\n//***********************************************************************************************\nvoid SetPlayerCountList( IconListClass& PlayerCountList, int iPlayerMax, char* pShpBoxCheck, char* pShpBoxEmpty )\n{\n\t//\tChecks appropriate list item based on iPlayerMax.\n\tswitch( iPlayerMax )\n\t{\n\tcase 2:\n\t\tPlayerCountList.Set_Icon( 0, 0, (void*)pShpBoxCheck, ICON_SHAPE );\n\t\tPlayerCountList.Set_Icon( 1, 0, (void*)pShpBoxEmpty, ICON_SHAPE );\n\t\tPlayerCountList.Set_Icon( 2, 0, (void*)pShpBoxEmpty, ICON_SHAPE );\n\t\tbreak;\n\tcase 3:\n\t\tPlayerCountList.Set_Icon( 0, 0, (void*)pShpBoxEmpty, ICON_SHAPE );\n\t\tPlayerCountList.Set_Icon( 1, 0, (void*)pShpBoxCheck, ICON_SHAPE );\n\t\tPlayerCountList.Set_Icon( 2, 0, (void*)pShpBoxEmpty, ICON_SHAPE );\n\t\tbreak;\n\tcase 4:\n\t\tPlayerCountList.Set_Icon( 0, 0, (void*)pShpBoxEmpty, ICON_SHAPE );\n\t\tPlayerCountList.Set_Icon( 1, 0, (void*)pShpBoxEmpty, ICON_SHAPE );\n\t\tPlayerCountList.Set_Icon( 2, 0, (void*)pShpBoxCheck, ICON_SHAPE );\n\t\tbreak;\n\t}\n}\n\n#endif\n"
  },
  {
    "path": "CODE/WOL_CHAT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifdef WOLAPI_INTEGRATION\n\n//\twol_chat.cpp\n//\tajw 7/8/98\n\n#include \"function.h\"\n#include \"iconlist.h\"\n#include \"WolapiOb.h\"\n#include \"SEditDlg.h\"\n#include \"WolStrng.h\"\n#include \"ToolTip.h\"\n\n//#include \"WolDebug.h\"\n\nvoid WOL_PrintMessage( IconListClass& ILTarget, const char* szText, PlayerColorType iColorRemap = PCOLOR_NONE );\nvoid WOL_PrintMessage( IconListClass& ILTarget, const char* szText, RemapControlType* pColorRemap );\nbool EnterChannel( WolapiObject* pWO, IconListClass& chatlist, Channel* pChannel, char* szChannelName, bool bGame );\nbool EnterChannel( WolapiObject* pWO, IconListClass& chatlist, IconListClass& chanlist, int iIndex, bool bGame );\nbool ExitChatChannel( WolapiObject* pWO );\nvoid CreateChatChannel( WolapiObject* pWO );\nbool CreateGameChannel( WolapiObject* pWO, const CREATEGAMEINFO& cgi );\nbool ProcessChannelListSelection( WolapiObject* pWO, IconListClass& chatlist, IconListClass& chanlist, int iIndex );\n\nenum LIST_EXPAND_STATE\n{\n\tLES_NORMAL,\n\tLES_CHANNELS_EXPANDED,\n\tLES_USERS_EXPANDED,\n};\nstatic LIST_EXPAND_STATE\tlesCurrent = LES_NORMAL;\n\nbool OnExpandChannelList( IconListClass& chanlist, IconListClass& userlist );\nbool OnExpandUserList( IconListClass& chanlist, IconListClass& userlist );\nvoid ResizeChannelList( IconListClass& chanlist, bool bExpand );\nvoid ResizeUserList( IconListClass& userlist, bool bExpand );\n\nbool bLinkInList( const LinkClass* pListHead, const LinkClass* pLinkToFind );\n\nextern CREATEGAMEINFO WOL_CreateGame_Dialog( WolapiObject* pWO );\n\nstatic int d_chanlist_w;\nstatic int d_chanlist_h;\nstatic int d_chanlist_x;\nstatic int d_chanlist_y;\n\nstatic int d_userlist_w;\nstatic int d_userlist_h;\nstatic int d_userlist_x;\nstatic int d_userlist_y;\n\n#define DRAWTOGDOWN\t\tTurn_Off()\n#define DRAWTOGUP\t\tTurn_On()\n\n//***********************************************************************************************\nint WOL_Chat_Dialog( WolapiObject* pWO )\n{\n\tint rc;\n\tbool bFirsttime = true;\n\tbool bHackFocus = true;\n\n\t//------------------------------------------------------------------------\n\t//\tDialog & button dimensions\n\t//------------------------------------------------------------------------\n\tint d_dialog_w = 320 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 200 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320*RESFACTOR - d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\tint d_dialog_y = ((200*RESFACTOR - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_text_h = 12;\n\tint d_margin1 = 34;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// large margin\n\tint d_margin2 = 14;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// small margin\n\n\tint d_chatlist_w = 340;\n\tint d_chatlist_x = d_dialog_x + d_margin1;\n\tint d_chatlist_y = d_dialog_y + d_margin2 + d_margin1 + 27;\n\tint d_chatlist_h = 337 - d_chatlist_y;\n\n\td_chanlist_w = 227;\n\td_chanlist_h = 50 * RESFACTOR;\n\td_chanlist_x = d_dialog_x + d_dialog_w - (d_margin1 + d_chanlist_w);\n\td_chanlist_y = d_chatlist_y;\n\n\td_userlist_w = d_chanlist_w;\n//\t\tint d_userlist_h = ((10 * 6) + 3) *RESFACTOR;\n\td_userlist_x = d_chanlist_x;\n\td_userlist_y = d_chanlist_y + d_chanlist_h + 14 + 5;\n\n\td_userlist_h = d_chatlist_y + d_chatlist_h - d_userlist_y;\n\n\tint d_action_w = 100;\n\tint d_action_h = 9 *RESFACTOR;\n\tint d_action_x = d_dialog_x + 500;\n\tint d_action_y = 365;\n\n//\tint d_chanpriv_w = 60;\n//\tint d_chanpriv_h = 9 *RESFACTOR;\n//\tint d_chanpriv_x = d_dialog_x + 150;\n//\tint d_chanpriv_y = d_action_y;\n\n//\tint d_cgame_w = 60;\n//\tint d_cgame_h = 9 *RESFACTOR;\n//\tint d_cgame_x = d_dialog_x + 390; //d_dialog_cx - d_cgame_w / 2;\n//\tint d_cgame_y = d_action_y;\n\n\tint d_back_w = 100;\n\tint d_back_h = 9 *RESFACTOR;\n\tint d_back_x = d_dialog_x + 100;\n\tint d_back_y = d_action_y;\n\n\tint d_join_w = 100;\n\tint d_join_h = 9 *RESFACTOR;\n\tint d_join_x = d_dialog_x + 210;\n\tint d_join_y = d_action_y;\n\n\tint d_create_w = 100;\n\tint d_create_h = 9 *RESFACTOR;\n\tint d_create_x = d_dialog_x + 320;\t//((d_dialog_w * 5) / 6) - (d_create_w / 2);\n\tint d_create_y = d_action_y;\n\n\tint d_send_w = d_chanlist_x + d_chanlist_w - d_chatlist_x;\n\tint d_send_h = 9 *RESFACTOR;\n\tint d_send_x = d_chatlist_x;\n\tint d_send_y = d_chatlist_y + d_chatlist_h + 5;\n\n\t//------------------------------------------------------------------------\n\t//\tButton Enumerations\n\t//------------------------------------------------------------------------\n\tenum \n\t{\n\t\tBUTTON_DISCONNECT = 100,\t//\tNote: standard WOL button IDs must match values in WolapiObject::PrepareButtonsAndIcons().\n\t\tBUTTON_LEAVE,\n\t\tBUTTON_REFRESH,\n\t\tBUTTON_SQUELCH,\n\t\tBUTTON_BAN,\n\t\tBUTTON_KICK,\n\t\tBUTTON_FINDPAGE,\n\t\tBUTTON_OPTIONS,\n\t\tBUTTON_LADDER,\n\t\tBUTTON_HELP,\n\n\t\tBUTTON_CHATLIST,\n\t\tBUTTON_CHANLIST,\n\t\tBUTTON_USERLIST,\n\t\tBUTTON_SENDEDIT,\n\t\tBUTTON_ACTION,\n//\t\tBUTTON_CGAME,\n\t\tBUTTON_CREATE,\n\t\tBUTTON_JOIN,\n\t\tBUTTON_BACK,\n\t\tBUTTON_EXPANDCHANNELS,\n\t\tBUTTON_EXPANDUSERS,\n\t\tBUTTON_RANKRA,\n\t\tBUTTON_RANKAM\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t//------------------------------------------------------------------------\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t//------------------------------------------------------------------------\n\t//\tDialog variables\n\t//------------------------------------------------------------------------\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\n\tTTimerClass<SystemTimerClass> lastclick_timer;\n\tint lastclick_idx = 0;\t\t\t\t\t// index of item last clicked on\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t//------------------------------------------------------------------------\n\t//\tButtons\n\t//------------------------------------------------------------------------\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tchar* pShpExpand = (char*)MFCD::Retrieve( \"exp.shp\" );\n\tchar* pShpUnexpand = (char*)MFCD::Retrieve( \"unexp.shp\" );\n\n\tIconListClass chatlist( BUTTON_CHATLIST, d_chatlist_x, d_chatlist_y, d_chatlist_w, d_chatlist_h, TPF_TYPE, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"), true, 0, 500 );\n\tShapeButtonClass ExpandChanBtn( BUTTON_EXPANDCHANNELS, pShpExpand, d_chanlist_x + d_chanlist_w - 17, d_chanlist_y - 14 );\n\tIconListClass chanlist( BUTTON_CHANLIST, d_chanlist_x, d_chanlist_y, d_chanlist_w, d_chanlist_h, TPF_TYPE, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"), true, 1 );\n\tShapeButtonClass ExpandUserBtn( BUTTON_EXPANDUSERS, pShpExpand, d_userlist_x + d_userlist_w - 17, d_userlist_y - 14 );\n\tIconListClass userlist( BUTTON_USERLIST, d_userlist_x, d_userlist_y, d_userlist_w, d_userlist_h, TPF_TYPE, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"), true, 2 );\n\tTextButtonClass ActionBtn( BUTTON_ACTION, TXT_WOL_ACTION, TPF_BUTTON, d_action_x, d_action_y, d_action_w );\n\tTextButtonClass CreateBtn( BUTTON_CREATE, TXT_WOL_NEWSOMETHING, TPF_BUTTON, d_create_x, d_create_y, d_create_w );\n\tTextButtonClass JoinBtn( BUTTON_JOIN, TXT_WOL_JOIN, TPF_BUTTON, d_join_x, d_join_y, d_join_w );\n\tTextButtonClass BackBtn( BUTTON_BACK, TXT_WOL_BACK, TPF_BUTTON, d_back_x, d_back_y, d_back_w );\n\tchar* szRecordToStartWith;\n\tif( pWO->bShowRankRA )\n\t\tszRecordToStartWith = pWO->szMyRecord;\n\telse\n\t\tszRecordToStartWith = pWO->szMyRecordAM;\n\tStaticButtonClass chatlistTitle( 0, szRecordToStartWith, TPF_TYPE, d_chatlist_x + 2, d_chatlist_y - 13, d_chatlist_w - 4, 12 );\n\tStaticButtonClass chanlistTitle( 0, \"\", TPF_TYPE, d_chanlist_x + 2, d_chanlist_y - 16 + 4, d_chanlist_w - 4 - 16, 12 );\n\tStaticButtonClass userlistTitle( 0, TXT_WOL_NOUSERLIST, TPF_TYPE, d_userlist_x + 2, d_userlist_y - 16 + 4, d_userlist_w - 4 - 16 * 4, 12 );\n\n\tchar szSendBuffer[MAXCHATSENDLENGTH] = \"\";\n\tEditClass sendedit( BUTTON_SENDEDIT, szSendBuffer, MAXCHATSENDLENGTH, TPF_TEXT, d_send_x, d_send_y, d_send_w, d_send_h );\n\n\tchar* pShpRankRA = (char*)MFCD::Retrieve( \"rank_ra.shp\" );\n\tchar* pShpRankAM = (char*)MFCD::Retrieve( \"rank_am.shp\" );\n\tShapeButtonClass RankRABtn( BUTTON_RANKRA, pShpRankRA, d_userlist_x + d_userlist_w - ( 16 * 4 + 1 ), d_userlist_y - 14 );\n\tShapeButtonClass RankAMBtn( BUTTON_RANKAM, pShpRankAM, d_userlist_x + d_userlist_w - ( 16 * 3 + 1 ), d_userlist_y - 14 );\n\t//\tChange draw behavior of toggle buttons.\n\tRankRABtn.ReflectButtonState = true;\n\tRankAMBtn.ReflectButtonState = true;\n\n\t//\tBuild the button list.\n\tcommands = pWO->pShpBtnDiscon;\n\tpWO->pShpBtnLeave->Add_Tail(*commands);\n\tpWO->pShpBtnRefresh->Add_Tail(*commands);\n\tpWO->pShpBtnSquelch->Add_Tail(*commands);\n\tpWO->pShpBtnBan->Add_Tail(*commands);\n\tpWO->pShpBtnKick->Add_Tail(*commands);\n\tpWO->pShpBtnFindpage->Add_Tail(*commands);\n\tpWO->pShpBtnOptions->Add_Tail(*commands);\n\tpWO->pShpBtnLadder->Add_Tail(*commands);\n\tpWO->pShpBtnHelp->Add_Tail(*commands);\n\tchatlist.Add_Tail(*commands);\n\tExpandChanBtn.Add_Tail(*commands);\n\tchanlist.Add_Tail(*commands);\n\tExpandUserBtn.Add_Tail(*commands);\n\tuserlist.Add_Tail(*commands);\n\tActionBtn.Add_Tail(*commands);\n\tCreateBtn.Add_Tail(*commands);\n//\tCreatePrivBtn.Add_Tail(*commands);\n\tJoinBtn.Add_Tail(*commands);\n\tBackBtn.Add_Tail(*commands);\n//\tCGameBtn.Add_Tail(*commands);\n\tchatlistTitle.Add_Tail(*commands);\n\tchanlistTitle.Add_Tail(*commands);\n\tuserlistTitle.Add_Tail(*commands);\n\tsendedit.Add_Tail(*commands);\n\n\t//\tTooltips...\n\tDWORD\t\t\t\ttimeToolTipAppear;\n\tToolTipClass*\t\tpToolTipHead = NULL;\t\t//\tHead of list of ToolTips that parallels gadget list.\n\tToolTipClass*\t\tpToolTipHitLast = NULL;\t\t//\tToolTip the mouse was last over, or null.\n\n\tToolTipClass* pToolTip = pToolTipHead = pWO->pTTipDiscon;\n\tpToolTip->next = pWO->pTTipLeave;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pWO->pTTipRefresh;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pWO->pTTipSquelch;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pWO->pTTipBan;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pWO->pTTipKick;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pWO->pTTipFindpage;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pWO->pTTipOptions;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pWO->pTTipLadder;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pWO->pTTipHelp;\n\tpToolTip = pToolTip->next;\n\tToolTipClass TTipChanExpand( &ExpandChanBtn, TXT_WOL_TTIP_EXPANDLIST, ExpandChanBtn.X + 8, ExpandChanBtn.Y - 9, true );\n\tpToolTip->next = &TTipChanExpand;\n\tpToolTip = pToolTip->next;\n\tToolTipClass TTipUserExpand( &ExpandUserBtn, TXT_WOL_TTIP_EXPANDLIST, ExpandUserBtn.X + 8, ExpandUserBtn.Y - 9, true );\n\tpToolTip->next = &TTipUserExpand;\n\tpToolTip = pToolTip->next;\n\tToolTipClass TTipChanList( &chanlist, 0, chanlist.X + 1, chanlist.Y + 1, true, true );\n\tpToolTip->next = &TTipChanList;\n\tpToolTip = pToolTip->next;\n\tToolTipClass TTipJoin( &JoinBtn, TXT_WOL_TTIP_JOIN, d_join_x + d_join_w/2, d_join_y - 6 );\n\tpToolTip->next = &TTipJoin;\n\tpToolTip = pToolTip->next;\n\tToolTipClass TTipBack( &BackBtn, TXT_WOL_TTIP_BACK, d_back_x + d_back_w/2, d_back_y - 6 );\n\tpToolTip->next = &TTipBack;\n\tpToolTip = pToolTip->next;\n\tToolTipClass TTipCreate( &CreateBtn, TXT_WOL_TTIP_CREATE, d_create_x + d_create_w/2, d_create_y - 6 );\n\tpToolTip->next = &TTipCreate;\n\tpToolTip = pToolTip->next;\n\tToolTipClass TTipAction( &ActionBtn, TXT_WOL_TTIP_ACTION, d_action_x + d_action_w/2, d_action_y - 6, true );\n\tpToolTip->next = &TTipAction;\n\tpToolTip = pToolTip->next;\n\tToolTipClass TTipRankRA( &RankRABtn, TXT_WOL_TTIP_RANKRA, RankRABtn.X + 8, RankRABtn.Y - 9, true );\n\tpToolTip->next = &TTipRankRA;\n\tpToolTip = pToolTip->next;\n\tToolTipClass TTipRankAM( &RankAMBtn, TXT_WOL_TTIP_RANKAM, RankAMBtn.X + 8, RankAMBtn.Y - 9, true );\n\tpToolTip->next = &TTipRankAM;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = NULL;\n\n\t//........................................................................\n\t// List boxes\n\t//........................................................................\n\tint tabs[] = { 150 };\t\t\t//\ttabs for channel list\n\tchanlist.Set_Tabs( tabs );\n\n//\tFancy_Text_Print(\"\", 0, 0, scheme, TBLACK, TPF_TEXT);\n\n\tlastclick_timer = 0;\n\n\t//\tTell WolapiObject about lists to use for output.\n\t//\t(Sure wish I'd gone against the grain and made this dialog a class...)\n\tpWO->LinkToChatDlg( &chatlist, &chanlist, &userlist, &userlistTitle );\n\n\tif( !pWO->bChatShownBefore )\n\t{\n\t\t//\tPrint message of the day.\n\t\tchatlist.Add_Item( pWO->pChatSink->szMotd, NULL, NULL, ICON_SHAPE );\n\t}\n\telse\n\t{\n\t\t//\tWe have returned to the chat dialog after being in either game setup or an actual game.\n\t\tpWO->RestoreChat();\n\t\tpWO->DeleteSavedChat();\n\n\t\tif( pWO->bReturningAfterGame )\n\t\t\tpWO->RejoinLobbyAfterGame();\n\t\telse\n\t\t{\n\t\t\tif( pWO->pChatSink->bGotKickedTrigger )\n\t\t\t{\n\t\t\t\t//\tWe got kicked out of a game setup.\n\t\t\t\tWOL_PrintMessage( chatlist, TXT_WOL_YOUWEREKICKEDFROMGAME, WOLCOLORREMAP_KICKORBAN );\n\t\t\t\tpWO->pChatSink->bGotKickedTrigger = false;\n\t\t\t}\n\t\t}\n\n\t\tif( pWO->iLobbyReturnAfterGame != -1 )\n\t\t{\n\t\t\tchar szChannelToJoin[ WOL_CHANNAME_LEN_MAX ];\n\t\t\t//sprintf( szChannelToJoin, \"Lob_%i_%i\", GAME_TYPE, pWO->iLobbyReturnAfterGame );\n\t\t\tsprintf( szChannelToJoin, \"%s%i\", LOB_PREFIX, pWO->iLobbyReturnAfterGame );\n\t\t\tpWO->OnEnteringChatChannel( szChannelToJoin, false, iChannelLobbyNumber( (unsigned char*)szChannelToJoin ) );\n\t\t}\n\t\telse\n\t\t\t//\tWill never happen presumably, if games are always entered via a lobby chat channel.\n\t\t\tpWO->EnterLevel_Top();\n\n\t\tpWO->iLobbyReturnAfterGame = -1;\n\n\t\tif( pWO->bReturningAfterGame )\n\t\t{\n\t\t\tSound_Effect( WOLSOUND_LOGIN );\n\t\t\tpWO->bReturningAfterGame = false;\n\t\t}\n\t\telse\n\t\t\tSound_Effect( WOLSOUND_EXITGAME );\n\t}\n\n\t//\tCause a refresh of szMyRecord, the string showing my win/loss record.\n\tpWO->RequestLadders( pWO->szMyName );\n\n\t//------------------------------------------------------------------------\n\t//\tInit Mono Output\n\t//------------------------------------------------------------------------\n\t#if(SHOW_MONO)\n \tIpx.Configure_Debug(-1, sizeof (GlobalHeaderType), sizeof(NetCommandType), GlobalPacketNames, 0, 13);\n\tIpx.Mono_Debug_Print(-1,1);\n\t#endif\n\n\t//------------------------------------------------------------------------\n\t//\tProcessing loop\n\t//------------------------------------------------------------------------\n\twhile (process) \n\t{\n\t\t#if(SHOW_MONO)\n\t\tIpx.Mono_Debug_Print(-1,0);\n\t\t#endif\n\n\t\t//\tRegularly check for incoming messages from wolapi.\n\t\tif( ::timeGetTime() > pWO->dwTimeNextWolapiPump )\n\t\t{\n/*\n\t\t\tif( pToolTipHitLast && pToolTipHitLast->bShowing )\t//\tLame hack. Problem is draws that occur in callbacks.\n\t\t\t{\n\t\t\t\tpToolTipHitLast->Unshow();\n\t\t\t\tpWO->pChat->PumpMessages();\n\t\t\t\tpWO->pNetUtil->PumpMessages();\n\t\t\t\tpToolTipHitLast->Show();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tpWO->pChat->PumpMessages();\n\t\t\t\tpWO->pNetUtil->PumpMessages();\n\t\t\t}\n*/\n\t\t\tpWO->pChat->PumpMessages();\n\t\t\tpWO->pNetUtil->PumpMessages();\n\n\t\t\t//\tSpecial post-callback processing...\n\t\t\tif( pWO->bSelfDestruct )\n\t\t\t{\n\t\t\t\tif( pWO->pChatSink->bConnected )\n\t\t\t\t\tpWO->Logout();\n\t\t\t\trc = -1;\t\t//\tAs if the user logged himself out.\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif( pWO->pChatSink->bGotKickedTrigger )\n\t\t\t{\n\t\t\t\tif( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )\n\t\t\t\t{\n\t\t\t\t\tpWO->OnExitingChatChannel();\n\t\t\t\t\tpWO->EnterLevel_UserChat();\n\t\t\t\t}\n\t\t\t\telse if( pWO->CurrentLevel == WOL_LEVEL_INLOBBY )\n\t\t\t\t{\n\t\t\t\t\tpWO->OnExitingChatChannel();\n\t\t\t\t\tpWO->EnterLevel_Lobbies();\n\t\t\t\t}\n\t\t\t\telse\t\t//\tMust be WOL_LEVEL_INOFFICIALCHATCHANNEL.\n\t\t\t\t{\n\t\t\t\t\tpWO->OnExitingChatChannel();\n\t\t\t\t\tpWO->EnterLevel_OfficialChat();\n\t\t\t\t}\n\t\t\t\tpWO->pChatSink->bGotKickedTrigger = false;\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t}\n\t\t\tif( pWO->bMyRecordUpdated )\n\t\t\t{\n\t\t\t\tif( pWO->bShowRankRA )\n\t\t\t\t\tchatlistTitle.Set_Text( pWO->szMyRecord );\n\t\t\t\telse\n\t\t\t\t\tchatlistTitle.Set_Text( pWO->szMyRecordAM );\n\t\t\t\tpWO->bMyRecordUpdated = false;\n\t\t\t}\n\t\t\tif( pWO->bChannelListTitleUpdated )\n\t\t\t{\n\t\t\t\tchanlistTitle.Set_Text( pWO->szChannelListTitle );\n\t\t\t\tpWO->bChannelListTitleUpdated = false;\n\t\t\t}\n\t\t\tpWO->dwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT;\n\t\t}\n\n\t\t//\tSynch rank toggle buttons state.\n\t\tif( BackBtn.Get_Prev() == &RankAMBtn )\n\t\t{\n\t\t\tif( pWO->CurrentLevel != WOL_LEVEL_INLOBBY )\n\t\t\t{\n\t\t\t\t//\tRank buttons are there and shouldn't be.\n\t\t\t\tRankRABtn.Remove();\n\t\t\t\tRankAMBtn.Remove();\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif( pWO->bShowRankUpdated )\n\t\t\t\t{\n\t\t\t\t\tif( pWO->bShowRankRA )\n\t\t\t\t\t{\n\t\t\t\t\t\tRankRABtn.DRAWTOGDOWN;\n\t\t\t\t\t\tRankAMBtn.DRAWTOGUP;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tRankRABtn.DRAWTOGUP;\n\t\t\t\t\t\tRankAMBtn.DRAWTOGDOWN;\n\t\t\t\t\t}\n\t\t\t\t\t//\tButtons have been refreshed.\n\t\t\t\t\tpWO->bShowRankUpdated = false;\n\t\t\t\t\t//\tCause my own record to get refreshed.\n\t\t\t\t\tpWO->bMyRecordUpdated = true;\n\t\t\t\t\t//\tRefresh list to show different rankings type.\n\t\t\t\t\tpWO->ListChannelUsers();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif( pWO->CurrentLevel == WOL_LEVEL_INLOBBY )\n\t\t\t{\n\t\t\t\t//\tRank buttons aren't there and should be.\n\t\t\t\tRankRABtn.Add( JoinBtn );\n\t\t\t\tRankAMBtn.Add( RankRABtn );\n\t\t\t\tRankRABtn.Flag_To_Redraw();\n\t\t\t\tRankAMBtn.Flag_To_Redraw();\n\t\t\t\tif( pWO->bShowRankRA )\n\t\t\t\t{\n\t\t\t\t\tRankRABtn.DRAWTOGDOWN;\n\t\t\t\t\tRankAMBtn.DRAWTOGUP;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tRankRABtn.DRAWTOGUP;\n\t\t\t\t\tRankAMBtn.DRAWTOGDOWN;\n\t\t\t\t}\n\t\t\t\t//\tButtons have been refreshed.\n\t\t\t\tpWO->bShowRankUpdated = false;\n\t\t\t}\n\t\t}\n\n\t\t//\tRegularly update the channels list in certain cases.\n\t\tif( ( pWO->CurrentLevel == WOL_LEVEL_OFFICIALCHAT || pWO->CurrentLevel == WOL_LEVEL_USERCHAT || \n\t\t\t\tpWO->CurrentLevel == WOL_LEVEL_LOBBIES || pWO->CurrentLevel == WOL_LEVEL_INLOBBY ) && \n\t\t\t\t::timeGetTime() > pWO->dwTimeNextChannelUpdate )\n\t\t{\n\t\t\tswitch( pWO->CurrentLevel )\n\t\t\t{\n\t\t\tcase WOL_LEVEL_OFFICIALCHAT:\n\t\t\t\tpWO->UpdateChannels( 0, CHANNELFILTER_OFFICIAL, false );\n\t\t\t\tbreak;\n\t\t\tcase WOL_LEVEL_USERCHAT:\n\t\t\t\tpWO->UpdateChannels( 0, CHANNELFILTER_UNOFFICIAL, false );\n\t\t\t\tbreak;\n\t\t\tcase WOL_LEVEL_LOBBIES:\t\t//\tOverkill in this case to update so often...\n\t\t\t\tpWO->UpdateChannels( 0, CHANNELFILTER_LOBBIES, false );\n\t\t\t\tbreak;\n\t\t\tcase WOL_LEVEL_INLOBBY:\n\t\t\t\tpWO->UpdateChannels( GAME_TYPE, CHANNELFILTER_LOCALLOBBYGAMES, true );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tpWO->dwTimeNextChannelUpdate = ::timeGetTime() + CHANNELUPDATEWAIT;\n\t\t}\n\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n#endif\n\n\t\tif( bFirsttime && !pWO->bChatShownBefore )\n\t\t{\n\t\t\tWWMessageBox().Process( TXT_WOL_FINDINGLOBBY, TXT_NONE );\n\t\t\tchar szLobbyName[ WOL_CHANNAME_LEN_MAX ];\n\t\t\tif( pWO->GetNameOfBeginningLobby( szLobbyName ) )\n\t\t\t{\n//\t\t\t\tdebugprint( \"Found lobby to go into: '%s'\\n\", szLobbyName );\n\t\t\t\tif( !EnterChannel( pWO, chatlist, NULL, szLobbyName, false ) )\n\t\t\t\t{\n\t\t\t\t\t//\tCould not enter channel for some reason. Go to top instead.\n\t\t\t\t\tpWO->EnterLevel_Top();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//\tCould not find name of a lobby for some reason. Go to top instead.\n\t\t\t\tpWO->EnterLevel_Top();\n\t\t\t}\n\t\t\tpWO->bChatShownBefore = true;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t\t//\tPlay login sound.\n\t\t\tSound_Effect( WOLSOUND_LOGIN );\n\t\t}\n\t\tbFirsttime = false;\n\n\t\t//.....................................................................\n\t\t//\tRefresh display if needed\n\t\t//.....................................................................\n\t\tif (display) \n\t\t{\n\t\t\tHide_Mouse();\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw backgound & dialog box\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BACKGROUND) \n\t\t\t{\n\t\t\t\tif( pToolTipHitLast && pToolTipHitLast->bShowing )\n\t\t\t\t{\n\t\t\t\t\tpToolTipHitLast->Unshow();\n\t\t\t\t}\n\n\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tDialog & Field labels\n\t\t\t\t//...............................................................\n\n\t\t\t\tcommands->Draw_All();\n\n\t\t\t\t//\tDraw title bar above channel list.\n\t\t\t\tDraw_Box( d_chanlist_x, d_chanlist_y - 15, d_chanlist_w, 16, BOXSTYLE_BOX, false );\n\t\t\t\tswitch( lesCurrent )\n\t\t\t\t{\n\t\t\t\tcase LES_CHANNELS_EXPANDED:\n\t\t\t\t\t//\tDraw users title bar at bottom.\n\t\t\t\t\tDraw_Box( d_userlist_x, d_userlist_y + d_userlist_h - 16, d_userlist_w, 16, BOXSTYLE_BOX, false );\n\t\t\t\t\tbreak;\n\t\t\t\tcase LES_USERS_EXPANDED:\n\t\t\t\t\t//\tDraw users title bar at top.\n\t\t\t\t\tDraw_Box( d_chanlist_x, d_chanlist_y, d_chanlist_w, 16, BOXSTYLE_BOX, false );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t//\tDraw users title bar in middle.\n\t\t\t\t\tDraw_Box( d_userlist_x, d_userlist_y - 15, d_userlist_w, 16, BOXSTYLE_BOX, false );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t//\tForce mouse visible, as some beta testers report unexplicable disappearing cursors.\n\t\twhile( Get_Mouse_State() )\n\t\t\tShow_Mouse();\n\t\t//\tBe nice to other apps.\n\t\tSleep( 50 );\n\n\t\t//.....................................................................\n\t\t//\tGet user input\n\t\t//.....................................................................\n\t\tif( ( ::GetAsyncKeyState( KN_LMOUSE ) & 0x8000 ) || ( ::GetAsyncKeyState( KN_RMOUSE ) & 0x8000 ) )\n\t\t{\n\t\t\t//\tMouse button is down.\n\t\t\ttimeToolTipAppear = ::timeGetTime() + TOOLTIPDELAY;\n\t\t\tif( pToolTipHitLast && pToolTipHitLast->bShowing )\n\t\t\t{\n\t\t\t\tpToolTipHitLast->Unshow();\n\t\t\t}\n\t\t}\n\n\t\t//\tIf anything currently on the controls list is set to redraw, hide tooltip.\n\t\tif( pToolTipHitLast && pToolTipHitLast->bShowing && commands->Is_List_To_Redraw() )\n\t\t{\n\t\t\tpToolTipHitLast->Unshow();\n\t\t}\n\n\t\tinput = commands->Input();\n\n\t\t//\tThis hack, used elsewhere in this form, appears to be the standard dodge around GadgetClass::Input's \n\t\t//\ttendency to remove any focus the first time it runs for a 'commands' list.\n\n\t\t//\tajw - Perhaps I could try doing this every cycle regardless - would avoid stupid non-focused editbox key reactions bug.\n\t\tif( bHackFocus )\n\t\t{\n\t\t\tsendedit.Set_Focus();\n\t\t\tsendedit.Flag_To_Redraw();\n\t\t\tinput = commands->Input();\n\t\t\tbHackFocus = false;\n\t\t}\n\n\t\t//\tTooltips...\n\t\tif( pToolTipHead )\n\t\t{\n\t\t\tToolTipClass* pToolTipHit = pToolTipHead->GetToolTipHit();\n\t\t\tif( pToolTipHit == pToolTipHitLast )\n\t\t\t{\n\t\t\t\tif( pToolTipHit && bLinkInList( commands, pToolTipHit->pGadget ) )\t//\t(Gadget must be in controls list.)\n\t\t\t\t{\n\t\t\t\t\tif( !pToolTipHit->bShowing && ::timeGetTime() > timeToolTipAppear && \n\t\t\t\t\t\t!( ( ::GetAsyncKeyState( KN_LMOUSE ) & 0x8000 ) || ( ::GetAsyncKeyState( KN_RMOUSE ) & 0x8000 ) ) )\n\t\t\t\t\t{\n\t\t\t\t\t\tpToolTipHit->Show();\n\t\t\t\t\t}\n\t\t\t\t\telse if( pToolTipHit->bIconList && pToolTipHit->bOverDifferentLine() )\n\t\t\t\t\t{\n\t\t\t\t\t\tpToolTipHit->Unshow();\n\t\t\t\t\t\tpToolTipHit->Show();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif( pToolTipHitLast && pToolTipHitLast->bShowing )\n\t\t\t\t\tpToolTipHitLast->Unshow();\n\t\t\t\tpToolTipHitLast = pToolTipHit;\n\t\t\t\ttimeToolTipAppear = ::timeGetTime() + TOOLTIPDELAY;\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tProcess input\n\t\t//.....................................................................\n\t\tswitch (input) \n\t\t{\n\t\t\tcase ( BUTTON_SENDEDIT | KN_BUTTON ):\n\t\t\t\t//\tEnter has been pressed - was caught by sendedit control.\n\t\t\t\tif( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL || pWO->CurrentLevel == WOL_LEVEL_INLOBBY )\n\t\t\t\t{\n\t\t\t\t\tpWO->SendMessage( sendedit.Get_Text(), userlist, false );\n\t\t\t\t\t//\tClear sendedit, reset focus.\n\t\t\t\t\tszSendBuffer[0] = 0;\n\t\t\t\t\tsendedit.Set_Focus();\n\t\t\t\t\t//\tMark for redraw.\n\t\t\t\t\tsendedit.Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tWOL_PrintMessage( chatlist, TXT_WOL_YOURENOTINCHANNEL, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\t\t\tSound_Effect( WOLSOUND_ERROR );\n\t\t\t\t\tsendedit.Set_Focus();\n\t\t\t\t\t//\tMark for redraw.\n\t\t\t\t\tsendedit.Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase KN_LMOUSE:\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_EXPANDCHANNELS | KN_BUTTON ):\n\t\t\t\tif( OnExpandChannelList( chanlist, userlist ) )\n\t\t\t\t{\n\t\t\t\t\t//\tHide userlist.\n\t\t\t\t\tif( ExpandUserBtn.Get_Next() == &userlist )\n\t\t\t\t\t\tuserlist.Remove();\n\t\t\t\t\t//\tEnsure chanlist is visible.\n\t\t\t\t\tif( ExpandChanBtn.Get_Next() != &chanlist )\n\t\t\t\t\t\tchanlist.Add( ExpandChanBtn );\n\t\t\t\t\t//\tMove userlist expand button.\n\t\t\t\t\tExpandUserBtn.Set_Position( ExpandUserBtn.X, chanlist.Y + chanlist.Height );\n\t\t\t\t\tTTipUserExpand.Move( ExpandUserBtn.X + 8, ExpandUserBtn.Y - 16 );\n\t\t\t\t\tuserlistTitle.Set_Position( userlistTitle.X, chanlist.Y + chanlist.Height + 2 );\n\t\t\t\t\t//\tSet buttons.\n\t\t\t\t\tExpandChanBtn.Set_Shape( pShpUnexpand );\n\t\t\t\t\tExpandUserBtn.Set_Shape( pShpExpand );\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t//\tShow userlist.\n\t\t\t\t\tif( ExpandUserBtn.Get_Next() != &userlist )\n\t\t\t\t\t\tuserlist.Add( ExpandUserBtn );\n\t\t\t\t\t//\tMove userlist expand button.\n\t\t\t\t\tExpandUserBtn.Set_Position( ExpandUserBtn.X, userlist.Y - 14 );\n\t\t\t\t\tTTipUserExpand.Move( ExpandUserBtn.X + 8, ExpandUserBtn.Y - 16 );\n\t\t\t\t\tuserlistTitle.Set_Position( userlistTitle.X, userlist.Y - 16 + 4 );\n\t\t\t\t\t//\tSet buttons.\n\t\t\t\t\tExpandChanBtn.Set_Shape( pShpExpand );\n\t\t\t\t\tExpandUserBtn.Set_Shape( pShpExpand );\n\t\t\t\t}\n\t\t\t\t//\tMove rank buttons.\n\t\t\t\tRankRABtn.Set_Position( RankRABtn.X, ExpandUserBtn.Y );\n\t\t\t\tRankAMBtn.Set_Position( RankAMBtn.X, ExpandUserBtn.Y );\n\t\t\t\tTTipRankRA.Move( RankRABtn.X + 8, RankRABtn.Y - 16 );\n\t\t\t\tTTipRankAM.Move( RankAMBtn.X + 8, RankAMBtn.Y - 16 );\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_EXPANDUSERS | KN_BUTTON ):\n\t\t\t\tif( OnExpandUserList( chanlist, userlist ) )\n\t\t\t\t{\n\t\t\t\t\t//\tHide chanlist controls.\n\t\t\t\t\tif( ExpandChanBtn.Get_Next() == &chanlist )\n\t\t\t\t\t\tchanlist.Remove();\n\t\t\t\t\t//\tEnsure userlist is visible.\n\t\t\t\t\tif( ExpandUserBtn.Get_Next() != &userlist )\n\t\t\t\t\t\tuserlist.Add( ExpandUserBtn );\n\t\t\t\t\t//\tSet buttons.\n\t\t\t\t\tExpandChanBtn.Set_Shape( pShpExpand );\n\t\t\t\t\tExpandUserBtn.Set_Shape( pShpUnexpand );\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t//\tShow chanlist.\n\t\t\t\t\tif( ExpandChanBtn.Get_Next() != &chanlist )\n\t\t\t\t\t\tchanlist.Add( ExpandChanBtn );\n\t\t\t\t\t//\tSet buttons.\n\t\t\t\t\tExpandChanBtn.Set_Shape( pShpExpand );\n\t\t\t\t\tExpandUserBtn.Set_Shape( pShpExpand );\n\t\t\t\t}\n\t\t\t\t//\tMove userlist expand button.\n\t\t\t\tExpandUserBtn.Set_Position( ExpandUserBtn.X, userlist.Y - 14 );\n\t\t\t\tTTipUserExpand.Move( ExpandUserBtn.X + 8, ExpandUserBtn.Y - 16 );\n\t\t\t\tuserlistTitle.Set_Position( userlistTitle.X, userlist.Y - 16 + 4 );\n\t\t\t\t//\tMove rank buttons.\n\t\t\t\tRankRABtn.Set_Position( RankRABtn.X, ExpandUserBtn.Y );\n\t\t\t\tRankAMBtn.Set_Position( RankAMBtn.X, ExpandUserBtn.Y );\n\t\t\t\tTTipRankRA.Move( RankRABtn.X + 8, RankRABtn.Y - 16 );\n\t\t\t\tTTipRankAM.Move( RankAMBtn.X + 8, RankAMBtn.Y - 16 );\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_CHANLIST | KN_BUTTON ):\n\t\t\t\t//\tUser clicks on the game list.\n\t\t\t\t//...............................................................\n\t\t\t\t// Handle a double-click\n\t\t\t\t//...............................................................\n\t\t\t\tif( lastclick_timer < 30 && chanlist.Current_Index() == lastclick_idx )\n\t\t\t\t{\n\t\t\t\t\t//\tDoubleclick on channel list.\n\t\t\t\t\tif( ProcessChannelListSelection( pWO, chatlist, chanlist, lastclick_idx ) )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tExit the chat dialog, go to game dialog.\n\t\t\t\t\t\trc = 2;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t}\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\tbHackFocus = true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t//...............................................................\n\t\t\t\t\t// Handle a single-click\n\t\t\t\t\t//...............................................................\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// If no double-click occurred, set the last-clicked index\n\t\t\t\t\t// & double-click timer.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tlastclick_timer = 0;\n\t\t\t\t\tlastclick_idx = chanlist.Current_Index();\n\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_JOIN | KN_BUTTON ):\n\t\t\t\t//\tPressing the join button is exactly like doubleclicking on the selected index in chanlist, except:\n\t\t\t\t//\t\tif the first item is selected, ignore, unless we are at the top level\n\t\t\t\tif( pWO->CurrentLevel == WOL_LEVEL_TOP || chanlist.Current_Index() != 0 )\n\t\t\t\t{\n\t\t\t\t\tif( ProcessChannelListSelection( pWO, chatlist, chanlist, chanlist.Current_Index() ) )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tExit the chat dialog, go to game dialog.\n\t\t\t\t\t\trc = 2;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t}\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\tbHackFocus = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_USERLIST | KN_BUTTON ):\n\t\t\t\t//\tUser clicks on user list.\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tcase ( BUTTON_CREATE | KN_BUTTON ):\n\t\t\t\tswitch( pWO->CurrentLevel )\n\t\t\t\t{\n\t\t\t\tcase WOL_LEVEL_INCHATCHANNEL:\n//\t\t\t\t\tdebugprint( \"%s\\n\", TXT_WOL_CANTCREATEINCHANNEL );\n\t\t\t\t\tWOL_PrintMessage( chatlist, TXT_WOL_CANTCREATEINCHANNEL, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\t\t\tSound_Effect( WOLSOUND_ERROR );\n\t\t\t\t\tbreak;\n\t\t\t\tcase WOL_LEVEL_INLOBBY:\n\t\t\t\t{\n\t\t\t\t\tpWO->bPump_In_Call_Back = true;\n\t\t\t\t\tCREATEGAMEINFO CreateGameInfo = WOL_CreateGame_Dialog( pWO );\n\t\t\t\t\tpWO->bPump_In_Call_Back = false;\n\t\t\t\t\tif( CreateGameInfo.bCreateGame )\n\t\t\t\t\t{\n\t\t\t\t\t\tif( CreateGameChannel( pWO, CreateGameInfo ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trc = 1;\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase WOL_LEVEL_GAMES:\n\t\t\t\tcase WOL_LEVEL_GAMESOFTYPE:\n\t\t\t\tcase WOL_LEVEL_LOBBIES:\n\t\t\t\t\tWOL_PrintMessage( chatlist, TXT_WOL_CANTCREATEHERE, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\t\t\tSound_Effect( WOLSOUND_ERROR );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tCreateChatChannel( pWO );\n\t\t\t\t}\n\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbHackFocus = true;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_LEAVE | KN_BUTTON ):\n\t\t\t\t//\tBecause of the way things are set up, this is exactly like selecting the first item in chanlist.\n\t\t\t\t//\t(Button is disabled when this is not appropriate.)\n\t\t\t\tProcessChannelListSelection( pWO, chatlist, chanlist, 0 );\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_REFRESH | KN_BUTTON ):\n\t\t\t\tpWO->dwTimeNextChannelUpdate = ::timeGetTime();\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_SQUELCH | KN_BUTTON ):\n\t\t\t\tpWO->DoSquelch( &userlist );\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_BAN | KN_BUTTON ):\n\t\t\t\tpWO->DoKick( &userlist, true );\n//\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_KICK | KN_BUTTON ):\n\t\t\t\tpWO->DoKick( &userlist, false );\n//\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_FINDPAGE | KN_BUTTON ):\n\t\t\t\tpWO->DoFindPage();\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbHackFocus = true;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_OPTIONS | KN_BUTTON ):\n\t\t\t\tpWO->DoOptions();\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbHackFocus = true;\n\t\t\t\tbreak;\n\n\t\t\tcase ( KN_ESC ):\n//\t\t\t\tbreak;\t\t\tajw\t\tPut back in?\n\n\t\t\tcase ( BUTTON_BACK | KN_BUTTON ):\n\t\t\t\t//\tPressing the back button is exactly like doubleclicking on the top item in chanlist, except\n\t\t\t\t//\twhen we're at the top level.\n\t\t\t\tif( pWO->CurrentLevel != WOL_LEVEL_TOP )\n\t\t\t\t{\n\t\t\t\t\tProcessChannelListSelection( pWO, chatlist, chanlist, 0 );\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t//\tNote no break; here. Fall through if at top level.\n\t\t\tcase ( BUTTON_DISCONNECT | KN_BUTTON ):\n\t\t\t\tif( WWMessageBox().Process( TXT_WOL_CONFIRMLOGOUT, TXT_YES, TXT_NO ) == 0 )\n\t\t\t\t{\n\t\t\t\t\tif( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL || pWO->CurrentLevel == WOL_LEVEL_INLOBBY )\n\t\t\t\t\t\tExitChatChannel( pWO );\n\t\t\t\t\tpWO->Logout();\n\t\t\t\t\trc = -1;\n\t\t\t\t\tprocess = false;\n\t\t\t\t}\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbHackFocus = true;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_ACTION | KN_BUTTON ):\n\t\t\t\tif( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL || pWO->CurrentLevel == WOL_LEVEL_INLOBBY )\n\t\t\t\t{\n\t\t\t\t\tpWO->SendMessage( sendedit.Get_Text(), userlist, true );\n\t\t\t\t\t//\tClear sendedit, reset focus.\n\t\t\t\t\tszSendBuffer[0] = 0;\n\t\t\t\t\tsendedit.Set_Focus();\n\t\t\t\t\t//\tMark for redraw.\n\t\t\t\t\t//chatlist.Flag_To_Redraw();\n\t\t\t\t\tsendedit.Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tWOL_PrintMessage( chatlist, TXT_WOL_YOURENOTINCHANNEL, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\t\t\tSound_Effect( WOLSOUND_ERROR );\n\t\t\t\t\tsendedit.Set_Focus();\n\t\t\t\t\t//\tMark for redraw.\n\t\t\t\t\tsendedit.Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_LADDER | KN_BUTTON ):\n\t\t\t\tpWO->DoLadder();\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbHackFocus = true;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_HELP | KN_BUTTON ):\n\t\t\t\tpWO->DoHelp();\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbHackFocus = true;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_RANKRA | KN_BUTTON ):\n\t\t\t\tpWO->bShowRankRA = true;\n\t\t\t\tpWO->bShowRankUpdated = true;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase ( BUTTON_RANKAM | KN_BUTTON ):\n\t\t\t\tpWO->bShowRankRA = false;\n\t\t\t\tpWO->bShowRankUpdated = true;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tbreak;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tService the sounds & score; GameActive must be false at this point,\n\t\t//\tso Call_Back() doesn't intercept global messages from me!\n\t\t//.....................................................................\n\t\tCall_Back();\n\n\t}\t// end of while\n\n\tif( pToolTipHitLast && pToolTipHitLast->bShowing )\n\t\tpToolTipHitLast->Unshow();\n\n/*\n\t//------------------------------------------------------------------------\n\t//\tRestore screen\n\t//------------------------------------------------------------------------\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n\tShow_Mouse();\n*/\n\n\tpWO->SaveChat();\n\n\tpWO->ClearListPtrs();\n\n\treturn rc;\n}\n\n//***********************************************************************************************\nvoid WOL_PrintMessage( IconListClass& ILTarget, const char* szText, PlayerColorType iColorRemap /* = PCOLOR_NONE */ )\n{\n\tRemapControlType* pColorRemap = ( iColorRemap == PCOLOR_NONE ? NULL : &ColorRemaps[ iColorRemap ] );\n\tWOL_PrintMessage( ILTarget, szText, pColorRemap );\n}\n\n//***********************************************************************************************\nvoid WOL_PrintMessage( IconListClass& ILTarget, const char* szText, RemapControlType* pColorRemap )\n{\n\tILTarget.Add_Item( szText, NULL, NULL, ICON_SHAPE, NULL, NULL, pColorRemap );\n\tif( !ILTarget.bScrollBeingDragged() )\n\t\tILTarget.Show_Last_Item();\n}\n\n//***********************************************************************************************\nbool OnExpandChannelList( IconListClass& chanlist, IconListClass& userlist )\n{\n\t//\tExpand channel list button was pressed.\n\t//\tReturns true if userlist controls are to be hidden, false if they are to be shown.\n\tswitch( lesCurrent )\n\t{\n\tcase LES_NORMAL:\n\t\tResizeChannelList( chanlist, true );\n\t\tlesCurrent = LES_CHANNELS_EXPANDED;\n\t\tbreak;\n\tcase LES_USERS_EXPANDED:\n\t\tResizeUserList( userlist, false );\n\t\tResizeChannelList( chanlist, true );\n\t\tlesCurrent = LES_CHANNELS_EXPANDED;\n\t\tbreak;\n\tcase LES_CHANNELS_EXPANDED:\n\t\tResizeChannelList( chanlist, false );\n\t\tlesCurrent = LES_NORMAL;\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n//***********************************************************************************************\nbool OnExpandUserList( IconListClass& chanlist, IconListClass& userlist )\n{\n\t//\tExpand user list button was pressed.\n\t//\tReturns true if chanlist controls are to be hidden, false if they are to be shown.\n\tswitch( lesCurrent )\n\t{\n\tcase LES_NORMAL:\n\t\tResizeUserList( userlist, true );\n\t\tlesCurrent = LES_USERS_EXPANDED;\n\t\tbreak;\n\tcase LES_CHANNELS_EXPANDED:\n\t\tResizeChannelList( chanlist, false );\n\t\tResizeUserList( userlist, true );\n\t\tlesCurrent = LES_USERS_EXPANDED;\n\t\tbreak;\n\tcase LES_USERS_EXPANDED:\n\t\tResizeUserList( userlist, false );\n\t\tlesCurrent = LES_NORMAL;\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n//***********************************************************************************************\nvoid ResizeChannelList( IconListClass& chanlist, bool bExpand )\n{\n\t//\tIf bExpand, makes list big, else normal size.\n\tif( bExpand )\n\t\tchanlist.Resize( d_chanlist_x, d_chanlist_y, d_chanlist_w, d_userlist_y + d_userlist_h - 15 - d_chanlist_y );\n\telse\n\t\tchanlist.Resize( d_chanlist_x, d_chanlist_y, d_chanlist_w, d_chanlist_h );\n}\n\n//***********************************************************************************************\nvoid ResizeUserList( IconListClass& userlist, bool bExpand )\n{\n\t//\tIf bExpand, makes list big, else normal size.\n\tif( bExpand )\n\t\tuserlist.Resize( d_userlist_x, d_chanlist_y + 15, d_userlist_w, d_userlist_y + d_userlist_h - ( d_chanlist_y + 15 ) );\n\telse\n\t\tuserlist.Resize( d_userlist_x, d_userlist_y, d_userlist_w, d_userlist_h );\n}\n\n//***********************************************************************************************\nbool EnterChannel( WolapiObject* pWO, IconListClass& chatlist, IconListClass& chanlist, int iIndex, bool bGame )\n{\n\t//\tEnter the channel specified in chanlist at iIndex.\n\t//\tCalled to enter chat channels, \"lobbies\", and game channels.\n\n\t//\tWe've stored the channel pointer in the hidden extra data field.\n\t//\t( Be careful about calling RAChatEventSink::DeleteChannelList()! )\n\tChannel* pChannel = (Channel*)chanlist.Get_Item_ExtraDataPtr( iIndex );\n\treturn EnterChannel( pWO, chatlist, pChannel, NULL, bGame );\n}\n\n//***********************************************************************************************\nbool EnterChannel( WolapiObject* pWO, IconListClass& chatlist, Channel* pChannel, char* szChannelName, bool bGame )\n{\n\t//\tCalled to cause the user to enter a channel (chat, lobby, or game).\n\t//\tIf pChannel is NULL, szChannelName will be used.\n\n\tChannel ChannelWhenNameOnly;\n\tif( !pChannel )\n\t{\n\t\tif( !szChannelName )\n\t\t{\n//\t\t\tdebugprint( \"pChannel and szChannelName null in EnterChannel\" );\n\t\t\tpWO->bSelfDestruct = true;\n\t\t\treturn false;\n\t\t}\n\t\tpChannel = &ChannelWhenNameOnly;\n\t\tstrcpy( (char*)pChannel->name, szChannelName );\n\t}\n\n\tif( bGame && pChannel->currentUsers >= pChannel->maxUsers )\t\t\t//\tPre-emptive fullness check.\n\t{\n\t\tWOL_PrintMessage( chatlist, TXT_WOL_CHANNELFULL, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\tSound_Effect( WOLSOUND_ERROR );\n\t\treturn false;\n\t}\n\n\tif( bGame )\n\t{\n\t\t//\tIt is possible to enter a game channel while currently in a chat channel. (A lobby, presumably.)\n\t\tif( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL || pWO->CurrentLevel == WOL_LEVEL_INLOBBY )\n\t\t\tif( !pWO->ExitChatChannelForGameChannel() )\n\t\t\t{\n\t\t\t\t*pWO->szChannelReturnOnGameEnterFail = 0;\n//\t\t\t\tdebugprint( \"ExitChatChannelForGameChannel on join failed\" );\n\t\t\t\tpWO->bSelfDestruct = true;\n\t\t\t\treturn false;\n\t\t\t}\n\t}\n\n/*\tThe following doesn't work because the needpw field is not currently being set in wolapi for chat channels.\n\tInstead, we wait for a fail on join, then present this dialog and try again.\n\tif( pChannel->needpw )\n\t{\n\t\tSimpleEditDlgClass* pEditDlg = new SimpleEditDlgClass( 300, TXT_WOL_JOINPRIVATETITLE, TXT_WOL_JOINPRIVATEPROMPT,\n\t\t\t\t\t\t\t\t\t\t\tWOL_CHANKEY_LEN_MAX );\n\t\tif( !pEditDlg->Show() || !*pEditDlg->szEdit )\n\t\t\treturn false;\n\n\t\tstrcpy( (char*)pChannel->key, pEditDlg->szEdit );\n\t}\n*/\n\tbool bKeepTrying = true;\n\n\t//\tSet password automatically for our lobbies, if trying to join one.\n\tint iLobby = iChannelLobbyNumber( pChannel->name );\n\tif( iLobby != -1 )\n\t\tstrcpy( (char*)pChannel->key, LOBBYPASSWORD );\n\n\tchar szSuccessfulPassword[ WOL_PASSWORD_LEN + 5 ];\n\t*szSuccessfulPassword = 0;\n\n\tHRESULT hRes;\n\twhile( bKeepTrying )\n\t{\n\t\thRes = pWO->ChannelJoin( pChannel );\n\t\tswitch( hRes )\n\t\t{\n\t\tcase CHAT_E_BADCHANNELPASSWORD:\n\t\t{\n\t\t\tFancy_Text_Print( TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT );\t//\tRequired before String_Pixel_Width() call, for god's sake.\n#ifdef ENGLISH\n\t\t\tSimpleEditDlgClass* pEditDlg = new SimpleEditDlgClass( 300, TXT_WOL_JOINPRIVATETITLE, TXT_WOL_JOINPRIVATEPROMPT,\n\t\t\t\t\t\t\t\t\t\t\t\tWOL_CHANKEY_LEN_MAX );\n#else\n#ifdef GERMAN\n\t\t\tSimpleEditDlgClass* pEditDlg = new SimpleEditDlgClass( 400, TXT_WOL_JOINPRIVATETITLE, TXT_WOL_JOINPRIVATEPROMPT,\n\t\t\t\t\t\t\t\t\t\t\t\tWOL_CHANKEY_LEN_MAX );\n#else\n\t\t\tSimpleEditDlgClass* pEditDlg = new SimpleEditDlgClass( 500, TXT_WOL_JOINPRIVATETITLE, TXT_WOL_JOINPRIVATEPROMPT,\n\t\t\t\t\t\t\t\t\t\t\t\tWOL_CHANKEY_LEN_MAX );\n#endif\n#endif\n\t\t\tpWO->bPump_In_Call_Back = true;\n\t\t\tif( strcmp( pEditDlg->Show(), Text_String( TXT_OK ) ) != 0 || !*pEditDlg->szEdit )\n\t\t\t{\n\t\t\t\tpWO->bPump_In_Call_Back = false;\n\t\t\t\tdelete pEditDlg;\n\t\t\t\tbKeepTrying = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tpWO->bPump_In_Call_Back = false;\n\t\t\tstrcpy( (char*)pChannel->key, pEditDlg->szEdit );\n\t\t\tstrcpy( szSuccessfulPassword, pEditDlg->szEdit );\n\t\t\tdelete pEditDlg;\n\t\t\tbreak;\n\t\t}\n\t\tcase CHAT_E_TIMEOUT:\n\t\t\tpWO->bPump_In_Call_Back = true;\n\t\t\tWWMessageBox().Process( TXT_WOL_TIMEOUT );\n\t\t\tpWO->bPump_In_Call_Back = false;\n\t\t\tbKeepTrying = false;\n\t\t\tbreak;\n\t\tcase CHAT_E_CHANNELDOESNOTEXIST:\n\t\t\tpWO->bPump_In_Call_Back = true;\n\t\t\tWWMessageBox().Process( TXT_WOL_CHANNELGONE );\n\t\t\tpWO->bPump_In_Call_Back = false;\n\t\t\tbKeepTrying = false;\n\t\t\tbreak;\n\t\tcase CHAT_E_BANNED:\n\t\t\tWOL_PrintMessage( chatlist, TXT_WOL_YOUREBANNED, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\tSound_Effect( WOLSOUND_ERROR );\n\t\t\tbKeepTrying = false;\n\t\t\tbreak;\n\t\tcase CHAT_E_CHANNELFULL:\n\t\t\tWOL_PrintMessage( chatlist, TXT_WOL_CHANNELFULL, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\tSound_Effect( WOLSOUND_ERROR );\n\t\t\tbKeepTrying = false;\n\t\t\tbreak;\n\t\tcase E_FAIL:\n\t\t\tpWO->GenericErrorMessage();\n\t\t\tbKeepTrying = false;\n\t\t\tbreak;\n\t\tcase S_OK:\n\t\t\tbKeepTrying = false;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif( !bGame )\n\t{\n\t\tif( hRes == S_OK )\n\t\t\treturn pWO->OnEnteringChatChannel( (char*)pChannel->name, false, iLobby );\n\t\telse\n\t\t\treturn false;\n\t}\n\telse\n\t{\n\t\tif( hRes == S_OK )\n\t\t{\n\t\t\t*pWO->szChannelReturnOnGameEnterFail = 0;\n\t\t\t//\tReturn later to the lobby of the channel creator - which was saved in the channel itself.\n\t\t\tpWO->iLobbyReturnAfterGame = pChannel->reserved & 0x00FFFFFF;\n\t\t\tif( pWO->iLobbyReturnAfterGame == 0x00FFFFFF )\n\t\t\t\tpWO->iLobbyReturnAfterGame = -1;\n\t\t\tCREATEGAMEINFO CreateGameInfo;\n\t\t\t//\tNot all of these values are currently used during setup.\n\t\t\tCreateGameInfo.bCreateGame = false;\n\t\t\tCreateGameInfo.iPlayerMax = pChannel->maxUsers;\n\t\t\tCreateGameInfo.bTournament = pChannel->tournament;\n\t\t\tif( *szSuccessfulPassword )\n\t\t\t{\n\t\t\t\tCreateGameInfo.bPrivate = true;\n\t\t\t\tstrcpy( CreateGameInfo.szPassword, szSuccessfulPassword );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tCreateGameInfo.bPrivate = false;\n\t\t\t\t*CreateGameInfo.szPassword = 0;\n\t\t\t}\n\t\t\tCreateGameInfo.GameKind = (CREATEGAMEINFO::GAMEKIND)( pChannel->reserved & 0xFF000000 );\n\t\t\treturn pWO->OnEnteringGameChannel( (char*)pChannel->name, false, CreateGameInfo );\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpWO->OnFailedToEnterGameChannel();\n\t\t\t*pWO->szChannelReturnOnGameEnterFail = 0;\n\t\t\treturn false;\n\t\t}\n\t}\n}\n\n//***********************************************************************************************\nbool ExitChatChannel( WolapiObject* pWO )\n{\n\t//\tCalled to cause user to leave current chat or lobby channel.\n\n//\tdebugprint( \"ExitChatChannel\\n\" );\n\tif( !pWO->ChannelLeave() )\n\t{\n\t\tpWO->GenericErrorMessage();\n\t\treturn false;\n\t}\n\n\tpWO->OnExitingChatChannel();\n\n\treturn true;\n}\n\n//***********************************************************************************************\n//void CreateChatChannel( WolapiObject* pWO, bool bPrivate )\nvoid CreateChatChannel( WolapiObject* pWO )\n{\n\tSimpleEditDlgClass* pEditDlg;\n/*\tif( !bPrivate )\n\t{\n\t\tpEditDlg = new SimpleEditDlgClass( 300, TXT_WOL_CREATECHANNELTITLE, TXT_WOL_CREATECHANNELPROMPT,\n\t\t\t\t\t\t\t\t\t\t\tWOL_CHANNAME_LEN_MAX );\n\t\tif( strcmp( pEditDlg->Show(), Text_String( TXT_OK ) ) == 0 && *pEditDlg->szEdit )\n\t\t{\n\t\t\tif( pWO->ChannelCreate( pEditDlg->szEdit, NULL ) )\n\t\t\t\tpWO->OnEnteringChatChannel( pEditDlg->szEdit, true, -1 );\n\t\t}\n\t}\n\telse\n*/\t{\n\t\tFancy_Text_Print( TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT );\t//\tRequired before String_Pixel_Width() call, for god's sake.\n\t\tpEditDlg = new SimpleEditDlgClass( 350, TXT_WOL_CREATECHANNELTITLE, TXT_WOL_CREATECHANNELPROMPT,\n\t\t\t\t\t\t\t\t\t\t\tWOL_CHANNAME_LEN_MAX, TXT_WOL_OPTIONALPASSPROMPT, WOL_CHANKEY_LEN_MAX );\n\t\tpWO->bPump_In_Call_Back = true;\n\t\tif( strcmp( pEditDlg->Show(), Text_String( TXT_OK ) ) == 0 && *pEditDlg->szEdit )\n\t\t{\n\t\t\tpWO->bPump_In_Call_Back = false;\n\t\t\tif( *pEditDlg->szEdit2 )\n\t\t\t{\n\t\t\t\tif( pWO->ChannelCreate( pEditDlg->szEdit, pEditDlg->szEdit2 ) )\n\t\t\t\t\tpWO->OnEnteringChatChannel( pEditDlg->szEdit, true, -1 );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//\tCreate public channel.\n\t\t\t\tif( pWO->ChannelCreate( pEditDlg->szEdit, NULL ) )\n\t\t\t\t\tpWO->OnEnteringChatChannel( pEditDlg->szEdit, true, -1 );\n\t\t\t}\n\t\t}\n\t\tpWO->bPump_In_Call_Back = false;\n\t}\n\n\tdelete pEditDlg;\n}\n\n//***********************************************************************************************\nbool CreateGameChannel( WolapiObject* pWO, const CREATEGAMEINFO& cgi )\n{\n\tchar szNewChannelName[ WOL_CHANNAME_LEN_MAX ];\n\tsprintf( szNewChannelName, \"%s's_game\", pWO->szMyName );\n\n\tif( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL || pWO->CurrentLevel == WOL_LEVEL_INLOBBY )\n\t\tif( !pWO->ExitChatChannelForGameChannel() )\n\t\t{\n\t\t\t*pWO->szChannelReturnOnGameEnterFail = 0;\n//\t\t\tdebugprint( \"ExitChatChannelForGameChannel in CreateGameChannel() error\" );\n\t\t\tpWO->bSelfDestruct = true;\n\t\t\treturn false;\n\t\t}\n\n\tconst char* szKey;\n\tif( *cgi.szPassword )\n\t\tszKey = cgi.szPassword;\n\telse\n\t\tszKey = NULL;\n\n\tif( pWO->ChannelCreate( szNewChannelName, szKey, true, cgi.iPlayerMax, cgi.bTournament, pWO->iLobbyLast, cgi.GameKind ) )\n\t\tpWO->OnEnteringGameChannel( szNewChannelName, true, cgi );\n\telse\n\t{\n\t\tpWO->OnFailedToEnterGameChannel();\n//\t\tdebugprint( \"CreateGameChannel fail\" );\n\t\treturn false;\n\t}\n\t*pWO->szChannelReturnOnGameEnterFail = 0;\n\n\treturn true;\n}\n\n//***********************************************************************************************\nbool ProcessChannelListSelection( WolapiObject* pWO, IconListClass& chatlist, IconListClass& chanlist, int iIndex )\n{\n\t//\tTakes whatever action necessary due to user selecting iIndex from chanlist.\n\t//\tReturns true if user selected to enter a game channel, else false.\n\tif( iIndex < 0 )\n\t\treturn false;\n\n//\tdebugprint( \"iIndex %i\\n\", iIndex );\n\n\tconst char* szChannelType = chanlist.Get_Item_ExtraDataString( iIndex );\n\tif( szChannelType )\n\t{\n//debugprint( \"szChannelType %s\\n\", szChannelType );\n\t\tif( strcmp( szChannelType, CHANNELTYPE_OFFICIALCHAT ) == 0 )\n\t\t{\n\t\t\tif( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )\n\t\t\t{\n\t\t\t\tif( !ExitChatChannel( pWO ) )\n\t\t\t\t{\n\t\t\t\t\tpWO->bSelfDestruct = true;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tpWO->EnterLevel_OfficialChat();\n\t\t}\n\t\telse if( strcmp( szChannelType, CHANNELTYPE_USERCHAT ) == 0 )\n\t\t{\n\t\t\tif( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )\n\t\t\t{\n\t\t\t\tif( !ExitChatChannel( pWO ) )\n\t\t\t\t{\n\t\t\t\t\tpWO->bSelfDestruct = true;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tpWO->EnterLevel_UserChat();\n\t\t}\n\t\telse if( strcmp( szChannelType, CHANNELTYPE_TOP ) == 0 )\n\t\t{\n\t\t\tif( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )\n\t\t\t{\n\t\t\t\t//\tNow not possible.\n\t\t\t\tif( !ExitChatChannel( pWO ) )\n\t\t\t\t{\n\t\t\t\t\tpWO->bSelfDestruct = true;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tpWO->EnterLevel_Top();\n\t\t}\n\t\telse if( strcmp( szChannelType, CHANNELTYPE_GAMES ) == 0 )\n\t\t{\n\t\t\tif( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )\n\t\t\t{\n\t\t\t\t//\tNow not possible.\n\t\t\t\tif( !ExitChatChannel( pWO ) )\n\t\t\t\t{\n\t\t\t\t\tpWO->bSelfDestruct = true;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tpWO->EnterLevel_Games();\n\t\t}\n\t\telse if( strcmp( szChannelType, CHANNELTYPE_GAMESOFTYPE ) == 0 )\n\t\t{\n\t\t\tif( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )\n\t\t\t{\n\t\t\t\t//\tNow not possible.\n\t\t\t\tif( !ExitChatChannel( pWO ) )\n\t\t\t\t{\n\t\t\t\t\tpWO->bSelfDestruct = true;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvoid* pExtraData = chanlist.Get_Item_ExtraDataPtr( iIndex );\n\t\t\tpWO->EnterLevel_GamesOfType( (WOL_GAMETYPEINFO*)pExtraData );\n\t\t}\n\t\telse if( strcmp( szChannelType, CHANNELTYPE_CHATCHANNEL ) == 0 )\n\t\t{\n\t\t\tif( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )\n\t\t\t{\n\t\t\t\t//\tNot currently possible.\n//\t\t\t\tdebugprint( \"Trying to jump from channel to channel?!\\n\" );\n\t\t\t\tpWO->bSelfDestruct = true;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t//\tJoin the chat channel.\n\t\t\tEnterChannel( pWO, chatlist, chanlist, iIndex, false );\t\t//\tCan fail.\n\t\t}\n\t\telse if( strcmp( szChannelType, CHANNELTYPE_GAMECHANNEL ) == 0 )\n\t\t{\n\t\t\t//\tUser attempting to join game channel.\n\t\t\tif( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )\n\t\t\t{\n\t\t\t\t//\tNot currently possible.\n//\t\t\t\tdebugprint( \"Trying to jump from channel to channel?!\\n\" );\n\t\t\t\tpWO->bSelfDestruct = true;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t//\tCheck if local user is allowed to join GameKind.\n\t\t\tChannel* pChannel = (Channel*)chanlist.Get_Item_ExtraDataPtr( iIndex );\n\t\t\tif( pChannel->type == GAME_TYPE )\n\t\t\t{\n\t\t\t\t//\tIt is a game of our type, at least.\n\t\t\t\tCREATEGAMEINFO::GAMEKIND GameKind = (CREATEGAMEINFO::GAMEKIND)( pChannel->reserved & 0xFF000000 );\n\t\t\t\tswitch( GameKind )\n\t\t\t\t{\n\t\t\t\tcase CREATEGAMEINFO::RAGAME:\n\t\t\t\t\tbreak;\n\t\t\t\tcase CREATEGAMEINFO::CSGAME:\n\t\t\t\t\tif( !Is_Counterstrike_Installed() )\n\t\t\t\t\t{\n\t\t\t\t\t\tWOL_PrintMessage( chatlist, TXT_WOL_NEEDCOUNTERSTRIKE, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\t\t\t\tSound_Effect( WOLSOUND_ERROR );\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase CREATEGAMEINFO::AMGAME:\n\t\t\t\t\tif( !Is_Aftermath_Installed() )\n\t\t\t\t\t{\n\t\t\t\t\t\tWOL_PrintMessage( chatlist, TXT_WOL_NEEDAFTERMATH, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\t\t\t\tSound_Effect( WOLSOUND_ERROR );\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n//\t\t\t\t\tdebugprint( \"Illegal value for GameKind channel reserved field: %s\\n\", (char*)pChannel->name );\n\t\t\t\t\tSound_Effect( WOLSOUND_ERROR );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t//\tJoin the game channel.\n\t\t\t\tif( EnterChannel( pWO, chatlist, chanlist, iIndex, true ) )\n\t\t\t\t{\n\t\t\t\t\t//\tExit the chat dialog, go to game dialog.\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//\tUser doubleclicked on a game that is of a different type.\n\t\t\t\t//\tOffer to take them to a web page regarding the game type.\n\t\t\t\tpWO->DoGameAdvertising( pChannel );\n\t\t\t}\n\t\t}\n\t\telse if( strcmp( szChannelType, CHANNELTYPE_LOBBIES ) == 0 )\n\t\t{\n\t\t\tif( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )\n\t\t\t{\n\t\t\t\t//\tNot currently possible.\n//\t\t\t\tdebugprint( \"Chat channel to lobbies level?!\\n\" );\n\t\t\t\tpWO->bSelfDestruct = true;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif( pWO->CurrentLevel == WOL_LEVEL_INLOBBY )\n\t\t\t{\n\t\t\t\tif( !ExitChatChannel( pWO ) )\n\t\t\t\t{\n\t\t\t\t\tpWO->bSelfDestruct = true;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tpWO->EnterLevel_Lobbies();\n\t\t}\n\t\telse if( strcmp( szChannelType, CHANNELTYPE_LOBBYCHANNEL ) == 0 )\n\t\t{\n\t\t\tif( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL ||\n\t\t\t\tpWO->CurrentLevel == WOL_LEVEL_INLOBBY )\n\t\t\t{\n\t\t\t\t//\tNot currently possible.\n//\t\t\t\tdebugprint( \"Chat or lobby channel to lobby channel?!\\n\" );\n\t\t\t\tpWO->bSelfDestruct = true;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t//\tJoin the lobby chat channel.\n\t\t\tEnterChannel( pWO, chatlist, chanlist, iIndex, false );\t\t//\tCan fail.\n\t\t}\n\t\telse if( strcmp( szChannelType, CHANNELTYPE_LOADING ) == 0 )\n\t\t{\n\t\t\t//\tUser clicked on the channel list loading notification - do nothing.\n\t\t}\n\t\telse\n\t\t{\n//\t\t\tdebugprint( \"Item selected in channel list unidentifiable from extradata field\\n\" );\n\t\t\tpWO->bSelfDestruct = true;\n\t\t\treturn false;\n\t\t}\n\n\t}\n\treturn false;\n}\n\t\n//***********************************************************************************************\nbool bLinkInList( const LinkClass* pListHead, const LinkClass* pLinkToFind )\n{\n\tconst LinkClass* pLink = pListHead;\n\twhile( pLink )\n\t{\n\t\tif( pLink == pLinkToFind )\n\t\t\treturn true;\n\t\tpLink = pLink->Get_Next();\n\t}\n\treturn false;\n}\n\n#endif\n"
  },
  {
    "path": "CODE/WOL_DNLD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifdef WOLAPI_INTEGRATION\n\n//\tWol_Dnld.cpp - WW online patch download dialog.\n//\tajw 10/12/98\n\n#include \"function.h\"\n#include \"WolapiOb.h\"\n#include \"WolStrng.h\"\n\n//***********************************************************************************************\nbool WOL_Download_Dialog( IDownload* pDownload, RADownloadEventSink* pDownloadSink, const char* szTitle )\n{\n\t//\tThis dialog is presented for each file that is to be downloaded during a WOLAPI patch.\n\n\tbool bReturn = true;\n\tDWORD dwTimeNextPump = ::timeGetTime() + WOLAPIPUMPWAIT;\n\n\t/*\n\t** Dialog & button dimensions\n\t*/\n\tint d_dialog_w = 200*RESFACTOR;\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 90*RESFACTOR;\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320*RESFACTOR - d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\tint d_dialog_y = ((200*RESFACTOR - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_margin = 34;\n\tint d_txt6_h = 15;\n\n#if (GERMAN | FRENCH)\n\tint d_cancel_w = 50*RESFACTOR;\n#else\n\tint d_cancel_w = 40*RESFACTOR;\n#endif\n\tint d_cancel_h = 9*RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - d_cancel_w / 2;\n\tint d_cancel_y = d_dialog_y + d_dialog_h - 20*RESFACTOR;\n\n\tint d_progress_w = 100*RESFACTOR;\n\tint d_progress_h = 10*RESFACTOR;\n\tint d_progress_x = (SeenBuff.Get_Width()/2) - d_progress_w/2;\n\tint d_progress_y = d_dialog_y + 45*RESFACTOR;\n\n//\tint\twidth;\n//\tint\theight;\n//\tchar* info_string = (char*)szTitle;\n\n\tFancy_Text_Print( TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\t\t\t\t\tTBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW );\n\n//\tFormat_Window_String( info_string, SeenBuff.Get_Height(), width, height );\n\n\n\t/*\n\t** Button Enumerations\n\t*/\n\tenum {\n\t\tBUTTON_CANCEL = 100,\n\t\tBUTTON_PROGRESS\n\t};\n\n\t/*\n\t** Buttons\n\t*/\n\tTextButtonClass cancelbtn( BUTTON_CANCEL, TXT_CANCEL, TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n#if (GERMAN | FRENCH)\n\t\t\t\t\t\t\t\t\td_cancel_x, d_cancel_y );\n#else\n\t\t\t\t\t\t\t\t\td_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h );\n#endif\n\n\tGaugeClass progress_meter( BUTTON_PROGRESS, d_progress_x, d_progress_y, d_progress_w, d_progress_h );\n\tprogress_meter.Use_Thumb( 0 );\n\n\tStaticButtonClass StatTitle( 0, szTitle, TPF_CENTER|TPF_TEXT, d_dialog_x + d_margin, d_dialog_y + 28, d_dialog_w - 2 * d_margin, d_txt6_h );\n\tStaticButtonClass StatStatus( 0, \"\", TPF_CENTER|TPF_TEXT, d_dialog_x + d_margin, d_dialog_y + 49, d_dialog_w - 2 * d_margin, d_txt6_h );\n\tStaticButtonClass StatBytes( 0, \"\", TPF_CENTER|TPF_TEXT, d_dialog_x + d_margin, d_dialog_y + 71, d_dialog_w - 2 * d_margin, d_txt6_h );\n\tStaticButtonClass StatTime( 0, \"\", TPF_CENTER|TPF_TEXT, d_dialog_x + d_margin, d_dialog_y + 117, d_dialog_w - 2 * d_margin, d_txt6_h );\n\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PROGRESS,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\n\tbool \t\tprocess = true;\n\tRedrawType \tdisplay = REDRAW_ALL;\t\t// redraw level\n\tKeyNumType \tinput;\n\tGadgetClass* commands;\t\t\t\t\t// button list\n\n\tcommands = &cancelbtn;\n\tprogress_meter.Add_Tail(*commands);\n\tStatTitle.Add_Tail(*commands);\n\tStatBytes.Add_Tail(*commands);\n\tStatTime.Add_Tail(*commands);\n\tStatStatus.Add_Tail(*commands);\n\n\tprogress_meter.Set_Maximum(100);\t\t// Max is 100%\n\tprogress_meter.Set_Value(0);\t\t\t// Current is 0%\n\n\tdo\t{\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n#endif\n\n\t\tif (display){\n\n\t\t\tif (display >= REDRAW_BACKGROUND){\n\n\t\t\t\tHide_Mouse();\n\t\t\t\t/*\n\t\t\t\t** Redraw backgound & dialog box\n\t\t\t\t*/\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tSet_Palette(CCPalette);\n\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t/*\n\t\t\t\t** Dialog & Field labels\n\t\t\t\t*/\n\t\t\t\tDraw_Caption (TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);\n\n//\t\t\t\tFancy_Text_Print(info_string, d_dialog_cx-width/2, d_dialog_y + 25*RESFACTOR,\n//\t\t\t\t\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK,\n//\t\t\t\t\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);\n\n\t\t\t\tShow_Mouse();\n\n\t\t\t}\n\n\t\t\tif (display >= REDRAW_BUTTONS){\n\n\t\t\t\tcommands->Draw_All();\n\n\t\t\t}\n\n\t\t\tif (display >= REDRAW_PROGRESS){\n\t\t\t\tprogress_meter.Draw_Me(true);\n\t\t\t}\n\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\tif (process){\n\t\t\tinput = cancelbtn.Input();\n\t\t\tswitch (input) {\n\n\t\t\t\t/*\n\t\t\t\t** Cancel. Just return to the main menu\n\t\t\t\t*/\n\t\t\t\tcase (KN_ESC):\n\t\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\t\tpDownload->Abort();\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbReturn = false;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif( ::timeGetTime() > dwTimeNextPump )\n\t\t{\n\t\t\tpDownload->PumpMessages();\n\t\t\tif( pDownloadSink->bFlagEnd )\n\t\t\t{\n\t\t\t\tpDownloadSink->bFlagEnd = false;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif( pDownloadSink->bFlagError )\n\t\t\t{\n\t\t\t\tWWMessageBox().Process( TXT_WOL_DOWNLOADERROR );\n\t\t\t\tpDownloadSink->bFlagError = false;\n\t\t\t\tprocess = false;\n\t\t\t\tbReturn = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif( pDownloadSink->bFlagProgressUpdate )\n\t\t\t{\n\t\t\t\tpDownloadSink->bFlagProgressUpdate = false;\n\t\t\t\tprogress_meter.Set_Value( ( pDownloadSink->iBytesRead * 100 ) / pDownloadSink->iTotalSize );\n\t\t\t\tchar szText[200];\n\t\t\t\tsprintf( szText, TXT_WOL_DOWNLOADBYTES, pDownloadSink->iBytesRead, pDownloadSink->iTotalSize,\n\t\t\t\t\t\t\t( pDownloadSink->iBytesRead * 100 ) / pDownloadSink->iTotalSize );\n\t\t\t\tStatBytes.Set_Text( szText );\n\t\t\t\tsprintf( szText, TXT_WOL_DOWNLOADTIME, pDownloadSink->iTimeLeft / 60, pDownloadSink->iTimeLeft % 60 );\n\t\t\t\tStatTime.Set_Text( szText );\n\t\t\t\tif( display < REDRAW_BUTTONS ) display = REDRAW_BUTTONS;\n\t\t\t}\n\t\t\tif( pDownloadSink->bFlagStatusUpdate )\n\t\t\t{\n\t\t\t\tpDownloadSink->bFlagStatusUpdate = false;\n\t\t\t\tswitch( pDownloadSink->iStatus )\n\t\t\t\t{\n\t\t\t\tcase DOWNLOADSTATUS_CONNECTING:\n\t\t\t\t\tStatStatus.Set_Text( TXT_WOL_DOWNLOADCONNECTING );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase DOWNLOADSTATUS_FINDINGFILE:\n\t\t\t\t\tStatStatus.Set_Text( TXT_WOL_DOWNLOADLOCATING );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase DOWNLOADSTATUS_DOWNLOADING:\n\t\t\t\t\tStatStatus.Set_Text( TXT_WOL_DOWNLOADDOWNLOADING );\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n//\t\t\t\t\tdebugprint( \"Unknown status update!\\n\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif( display < REDRAW_BUTTONS ) display = REDRAW_BUTTONS;\n\t\t\t}\n\t\t\tif( pDownloadSink->bFlagQueryResume )\n\t\t\t{\n\t\t\t\tif( pDownloadSink->bResumed )\n\t\t\t\t{\n\t\t\t\t\tchar szTitleNew[200];\n\t\t\t\t\tsprintf( szTitleNew, TXT_WOL_DOWNLOADRESUMED, szTitle );\n\t\t\t\t\tStatTitle.Set_Text( szTitleNew );\n\t\t\t\t\tif( display < REDRAW_BUTTONS ) display = REDRAW_BUTTONS;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdwTimeNextPump = ::timeGetTime() + WOLAPIPUMPWAIT;\n\t\t}\n\n\t\t//\tInvoke game callback\n\t\tCall_Back();\n\n\t} while ( process );\n\n\treturn bReturn;\n}\n\n#endif\n"
  },
  {
    "path": "CODE/WOL_GSUP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#ifdef WOLAPI_INTEGRATION\t\t\t//\tNow implies also WINSOCK_IPX, WIN32, and FIXIT_CSII must be true\n\n#include \"wol_gsup.h\"\n#include \"function.h\"\n#include \"IconList.h\"\n#include <time.h>\n#include \"WolStrng.h\"\n#include \"wsproto.h\"\n#include \"BigCheck.h\"\n#include \"ToolTip.h\"\n\nextern char const* EngMisStr[];\n\nbool Is_Mission_126x126 (char *file_name);\nbool Is_Mission_Aftermath (char *file_name);\nbool Is_Mission_Counterstrike (char *file_name);\n\nbool Force_Scenario_Available( const char* szName );\n\nint ScenarioIndex_From_Filename( const char* szScenarioFilename );\n\nbool bSpecialAftermathScenario( const char* szScenarioDescription );\n\n#include \"WolDebug.h\"\n\n#define PARAMREFRESHWAIT\t2000\n\n#define PING_AND_DISPLAY_WAIT\t\t5000\n\nvoid WOL_PrintMessage( IconListClass& ILTarget, const char* szText, PlayerColorType iColorRemap = PCOLOR_NONE );\nvoid WOL_PrintMessage( IconListClass& ILTarget, const char* szText, RemapControlType* pColorRemap );\nvoid CC_Draw_DIB( const char* pDIB, int xDest, int yDest, int iWidth, WindowNumberType window );\n\nbool operator==( const GAMEPARAMS& gp1, const GAMEPARAMS& gp2 );\nbool operator==( const GlobalPacketType& gp1, const GlobalPacketType& gp2 );\nPlayerColorType PlayerColorTypeOf( RemapControlType* pColorRemap );\n\nextern unsigned long PlanetWestwoodStartTime;\t\t\t\t\t//Time that game was started\n\nextern bool cancel_current_msgbox;\nextern bool disable_current_msgbox;\n\nvoid Debug_GlobalPacketType( const GlobalPacketType& gp1 );\n\n//***********************************************************************************************\n/*\tGame startup logic:\nWhen a guest joins the channel, the host sends all current setup info.\nWhen a guest changes house, he tells the host, who informs everyone. A house change can't be denied.\nWhen a guest changes color, he asks the host for the new color, and assumes the request will go through. If it doesn't, the\nhost sends the guest a messages setting him back to the old color, otherwise, everyone gets the new color for the guest.\nWhen the host changes a game param, the change will be noticed within PARAMREFRESHWAIT milliseconds and then transmitted to\nall guests.\nAll player specific information is stored within the players list (IconListClass), and nowhere else. Though this storage\nmethod got a bit inelegant, it gets the job done.\nAll \"informs\" (messages sent from host to guest) except color changes (WOL_GAMEOPT_INFCOLOR) and player \"accept\" status\nchanges (WOL_GAMEOPT_INFACCEPT) are assigned a ID, which\nincrements on each send. Color informs are: a) not a condition for removing a guest's \"accept\" status, and b) sent out to\nindividual guests in certain cases, and would thus complicate the ID tracking scheme.\nWhen a guest \"accepts\" the game setup (with a WOL_GAMEOPT_REQACCEPT), the latest received ID is included in the message.\nIf the host receives a WOL_GAMEOPT_REQACCEPT with an out-of-date ID, the accept is ignored. Though the guest sets himself to\n\"accepted\" when he sends the WOL_GAMEOPT_REQACCEPT, if it gets ignored by the host it is because a new inform is already on its\nway, which will reset the guest's own status to \"not accepted\" when it arrives.\nHost clears all accepteds when params are changed, player joins or leaves, or house change message arrives. Though a\nWOL_GAMEOPT_INFACCEPT is sent out when a guest accepts, there is no corresponding \"unaccept all\" message sent out at this point,\nas all guests will naturally clear their recorded accept status for everyone when the change arrives there.\nGuest clears own accepted when an inform from the server other than color change arrives, player joins or leaves, or own\nhouse is directly changed.\nWhen all players are \"accepted\", and the host says \"start\", a WOL_GAMEOPT_INFSTART is sent to all guests and the host goes into\n\"waiting to start\" mode. If a house change or other arrives in this phase, host clears waiting mode and (naturally) marks guests\nunaccepted and sends out the house change to the guests. (The same applies to player joins/leaves.)\nWhile in this mode, the host user is locked out of making any changes to game params.\nIf a change does come in during this phase, a WOL_GAMEOPT_INFCANCELSTART is sent to the guests, and the waiting mode cancelled.\nWhen a guest receives WOL_GAMEOPT_INFSTART: If he does not see himself as accepted, it is because a change has just been sent\nto the host, or some other event occurred that the host will learn about, so the guest can simply ignore the WOL_GAMEOPT_INFSTART.\nIf the guest does see himself as accepted when WOL_GAMEOPT_INFSTART arrives, he responds with WOL_GAMEOPT_REQSTART and goes into\n\"waiting to start\" mode. When in this mode, the user is locked out of making any changes.\nNote that the host is not really asking for any sort of \"confirmation that it's ok\" to start from the guest here. (Hence no\n\"cancel\" response is possible.) It's really just a way of telling the guests not to make any more changes to the setup; it's\nlike we're making sure we've \"flushed the queue\" of game changes.\nIf a guest receives a WOL_GAMEOPT_INFCANCELSTART, he cancels out of \"waiting to start\" mode. Note that while in the waiting\nmode, normal processing of messages is allowed to take place - the user is simply blocked from doing anything.\nPresumably (hopefully) this phase will last less than a second.\nWhen the host receives a WOL_GAMEOPT_REQSTART from everyone, he tells everyone to start with a WOL_GAMEOPT_INFGO.\nBecause there is a chance of color changes being out of sync, all player colors are sent to all guests at this point.\nThere is no chance of other data being out of sync.\n*/\n\n//--------------------------------------------------------------------------\n//\tPieced together from Net_New_Dialog() and Net_Join_Dialog().\n//--------------------------------------------------------------------------\n//***********************************************************************************************\nWOL_GameSetupDialog::WOL_GameSetupDialog( WolapiObject* pWO, bool bHost ) : pWO( pWO ), bHost( bHost ),\n\t\tHousePrevious( HOUSE_NONE ),\n\t\tpILPlayers( NULL ),\n\t\tpILScens( NULL ),\n\t\tpILDisc( NULL ),\n\t\tpEditSend( NULL ),\n\t\tpGaugeCount( NULL ),\n\t\tpGaugeLevel( NULL ),\n\t\tpGaugeCredits( NULL ),\n\t\tpGaugeAIPlayers( NULL ),\n\t\tpCheckListOptions( NULL ),\n//\t\tpTextBtnOk( NULL ),\n\t\tpTextBtnCancel( NULL ),\n\t\tpTextBtnAcceptStart( NULL ),\n\t\tpTextBtnAction( NULL ),\n\t\tpStaticDescrip( NULL ),\n\t\tpStaticUnit( NULL ),\n\t\tpStaticLevel( NULL ),\n\t\tpStaticCredits( NULL ),\n\t\tpStaticAIPlayers( NULL ),\n\t\tpDropListHouse( NULL ),\n\t\tpCheckAftermathUnits( NULL ),\n\t\tnHostLastParamID( 0 ),\n\t\tnGuestLastParamID( 0 ),\n\t\tbWaitingToStart( false ),\n\t\tbParamsReceived( false ),\n\t\tbHostSayGo( false ),\n\t\tbExitForGameTrigger( false ),\n\t\tpToolTipHead( NULL ),\n\t\tpToolTipHitLast( NULL ),\n\t\tpTTipAcceptStart( NULL ),\n\t\tpTTipCancel( NULL ),\n\t\tpTTipAction( NULL ),\n\t\tScenKindCurrent( SCENARIO_UNINITIALIZED ),\n\t\tpShpBtnScenarioRA( NULL ),\n\t\tpShpBtnScenarioCS( NULL ),\n\t\tpShpBtnScenarioAM( NULL ),\n\t\tpShpBtnScenarioUser( NULL ),\n\t\tbLeaveDueToRulesMismatchTrigger( false ),\n\t\tbHostWaitingForGoTrigger( false )\n{\n\t*szSendBuffer = 0;\n\t*szHouseBuffer = 0;\n\tmemset( &GParamsLastSent, 0, sizeof( GAMEPARAMS ) );\n\t*szNameOfHostWhoJustBailedOnUs = 0;\n\t*szTriggerGameStartInfo = 0;\n}\n\n//***********************************************************************************************\nWOL_GameSetupDialog::~WOL_GameSetupDialog()\n{\n\tdelete pILPlayers;\n\tdelete pILScens;\n\tdelete pILDisc;\n\tdelete pEditSend;\n\tdelete pGaugeCount;\n\tdelete pGaugeLevel;\n\tdelete pGaugeCredits;\n\tdelete pGaugeAIPlayers;\n\tdelete pCheckListOptions;\n//\tdelete pTextBtnOk;\n\tdelete pTextBtnCancel;\n\tdelete pTextBtnAcceptStart;\n\tdelete pTextBtnAction;\n//\tdelete pStaticDescrip;\n\tdelete pStaticUnit;\n\tdelete pStaticLevel;\n\tdelete pStaticCredits;\n\tdelete pStaticAIPlayers;\n\tdelete pDropListHouse;\n\tdelete pCheckAftermathUnits;\n\tdelete pTTipAcceptStart;\n\tdelete pTTipCancel;\n\tdelete pTTipAction;\n\tdelete pShpBtnScenarioRA;\n\tdelete pShpBtnScenarioCS;\n\tdelete pShpBtnScenarioAM;\n\tdelete pShpBtnScenarioUser;\n}\n\n//***********************************************************************************************\nRESULT_WOLGSUP WOL_GameSetupDialog::Run()\n{\n\tInitialize();\n\treturn Show();\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::Initialize()\n{\n\t//------------------------------------------------------------------------\n\t//\tDialog & button dimensions\n\t//------------------------------------------------------------------------\n\td_dialog_w = 640;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\td_dialog_h = 400;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\td_dialog_x = 0;\n\td_dialog_y = 0;\n\td_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\td_txt6_h = 6*RESFACTOR+1;\t\t\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_text_h = 12;\n\td_margin1 = 34;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// large margin\n\n\td_color_w = 10 *RESFACTOR;\n\td_color_h = 9 *RESFACTOR;\n\td_color_x = 294;\t//54;\t\t//d_dialog_x + ((d_dialog_w / 4) * 3) - (d_color_w * 3);\n\td_color_y = 89;\t\t//142;\t//d_house_y;\n\n\td_house_w = 60 *RESFACTOR;\n\td_house_h = (8 * 5 *RESFACTOR);\n\td_house_x = 466;\t//65;\t//d_color_x;\t//d_dialog_cx - (d_house_w / 2);\n\td_house_y = d_color_y;\t// + 36;\t//d_dialog_y + ( 7 * RESFACTOR ) + d_txt6_h + (2*RESFACTOR);\n\n\tif( bHost )\n\t\td_disc_w = 365;\t//d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR;\n\telse\n\t\td_disc_w = d_dialog_w - ( d_margin1 * 2 );\n\td_disc_x = d_dialog_x + d_margin1;\n\td_disc_y = 205;\t//d_dialog_y + d_dialog_h - ( 65 + d_disc_h );\n\td_disc_h = 337 - d_disc_y;\n\n\td_playerlist_w = 124*RESFACTOR;\n\td_playerlist_h = d_text_h * 4 + 4;\n\td_playerlist_x = d_dialog_x + d_margin1;\n\td_playerlist_y = 75;\t//d_dialog_y + d_margin1 + d_txt6_h + 3*RESFACTOR + 18 * RESFACTOR;\n\n\tint d_tab_h = 19;\n\n\td_scenariolist_w = 200;\n//\td_scenariolist_h = (4 * d_txt6_h) + 3*RESFACTOR;\t\t// 4 rows high\n\td_scenariolist_x = d_dialog_x + d_dialog_w - d_margin1 - d_scenariolist_w;\n\td_scenariolist_y = d_disc_y + d_tab_h;\n\td_scenariolist_h = d_disc_y + d_disc_h - d_scenariolist_y;\n\n\td_gamekind_w = 182;\n\td_gamekind_h = 30;\n\td_gamekind_x = 52;\t\t//\t370;\n\td_gamekind_y = 153;\t\t//\td_playerlist_y + d_text_h + 3;\t// + d_playerlist_h - d_text_h;\n\n\td_count_w = 25*RESFACTOR;\n\td_count_h = d_txt6_h;\n\td_count_x = 310;\n\td_count_y = 138;\t//d_playerlist_y + d_playerlist_h + d_margin2 + 9*RESFACTOR;\n\n\td_level_w = 25*RESFACTOR;\n\td_level_h = d_txt6_h;\n\td_level_x = d_count_x;\n\td_level_y = d_count_y + d_count_h;\n\n\td_credits_w = 25*RESFACTOR;\n\td_credits_h = d_txt6_h;\n\td_credits_x = d_count_x;\n\td_credits_y = d_level_y + d_level_h;\n\n\td_aiplayers_w = 25*RESFACTOR;\n\td_aiplayers_h = d_txt6_h;\n\td_aiplayers_x = d_count_x;\n\td_aiplayers_y = d_credits_y + d_credits_h;\n\n#ifdef GERMAN\n\td_options_w = 186;\n#else\n\td_options_w = 180;\n#endif\n\td_options_h = ((6 * 6) + 4)*RESFACTOR + 1;\n\td_options_x = d_dialog_x + d_dialog_w - d_options_w - d_margin1;\n\td_options_y = 127 - d_txt6_h + 2;\n\n\td_send_w = d_dialog_w - ( d_margin1 * 2 );\n\td_send_h = 9*RESFACTOR;\n\td_send_x = d_dialog_x + d_margin1;\n\td_send_y = d_disc_y + d_disc_h + 5;\n\n//\td_ok_w = 50*RESFACTOR;\n//\td_ok_h = 9*RESFACTOR;\n//\td_ok_x = d_dialog_x + (d_dialog_w / 6) - (d_ok_w / 2);\n//\td_ok_y = d_dialog_y + d_dialog_h - d_ok_h - d_margin1 - 3*RESFACTOR;\n\n\td_cancel_w = 100;\n\td_cancel_h = 9*RESFACTOR;\n\td_cancel_x = d_dialog_x + 100; //d_dialog_cx - (d_cancel_w / 2);\n\td_cancel_y = 365;\t//d_dialog_y + d_dialog_h - d_cancel_h - d_margin1 - 3*RESFACTOR;\n\n\td_accept_w = 100;\n\td_accept_h = 9 *RESFACTOR;\n\td_accept_x = d_dialog_x + 210;\n\td_accept_y = d_cancel_y;\t//d_dialog_y + d_dialog_h - 17*RESFACTOR;\n\n\td_action_w = 100;\n\td_action_h = 9 *RESFACTOR;\n\td_action_x = d_dialog_x + 500;\n\td_action_y = d_cancel_y;\n\n/*\tint d_load_w = 50*RESFACTOR;\n\tint d_load_h = 9*RESFACTOR;\n\tint d_load_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_load_w / 2);\n\tint d_load_y = d_dialog_y + d_dialog_h - d_load_h - d_margin1 - 3*RESFACTOR;\n*/\n\td_amunits_w = 160;\n\td_amunits_h = 18;\n\td_amunits_x = d_dialog_x + (d_dialog_w / 6) - (d_amunits_w / 2);\n\td_amunits_y = 365;\n\n\tToolTipClass* pToolTip = pToolTipHead = pWO->pTTipDiscon;\n\tpToolTip->next = pWO->pTTipLeave;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pWO->pTTipRefresh;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pWO->pTTipSquelch;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pWO->pTTipBan;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pWO->pTTipKick;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pWO->pTTipFindpage;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pWO->pTTipOptions;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pWO->pTTipLadder;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pWO->pTTipHelp;\n\n\tpILPlayers = new IconListClass( BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, TPF_TYPE, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"), true, 2 );\n//\tListClass scenariolist(BUTTON_SCENARIOLIST, d_scenariolist_x, d_scenariolist_y, d_scenariolist_w, d_scenariolist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tpILScens = new IconListClass( BUTTON_SCENARIOLIST, d_scenariolist_x, d_scenariolist_y, d_scenariolist_w, d_scenariolist_h, TPF_TYPE, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"), true, 1 );\n\tpILDisc = new IconListClass( BUTTON_DISCLIST, d_disc_x, d_disc_y, d_disc_w, d_disc_h, TPF_TYPE, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"), true, 0, 300 );\n\n\tpEditSend = new EditClass( BUTTON_SENDEDIT, szSendBuffer, MAXCHATSENDLENGTH, TPF_TEXT, d_send_x, d_send_y, d_send_w, d_send_h );\n\n//\tTextButtonClass rejectbtn( BUTTON_REJECT, TXT_REJECT, TPF_BUTTON, d_reject_x, d_reject_y );\n\tpGaugeCount = new GaugeClass( BUTTON_COUNT, d_count_x, d_count_y, d_count_w, d_count_h );\n\tpGaugeLevel = new GaugeClass( BUTTON_LEVEL, d_level_x, d_level_y, d_level_w, d_level_h );\n\tpGaugeCredits = new GaugeClass( BUTTON_CREDITS, d_credits_x, d_credits_y, d_credits_w, d_credits_h );\n\tpGaugeAIPlayers = new GaugeClass( BUTTON_AIPLAYERS, d_aiplayers_x, d_aiplayers_y, d_aiplayers_w, d_aiplayers_h );\n\tpCheckListOptions = new CheckListClass( BUTTON_PARAMS, d_options_x, d_options_y, d_options_w, d_options_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\") );\n//\tpTextBtnOk = new TextButtonClass( BUTTON_OK, TXT_OK, TPF_BUTTON, d_ok_x, d_ok_y, 60*RESFACTOR );\n//\tTextButtonClass loadbtn(BUTTON_LOAD, TXT_LOAD_BUTTON, TPF_BUTTON, d_load_x, d_load_y, 60*RESFACTOR);\n\tpTextBtnCancel = new TextButtonClass( BUTTON_CANCEL, TXT_WOL_CANCELGAME, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w );\n\tpTTipCancel = new ToolTipClass( pTextBtnCancel, TXT_WOL_TTIP_CANCELGAME, d_cancel_x + d_cancel_w/2, d_cancel_y - 6 );\n\n\tif( bHost )\n\t{\n\t\tpTextBtnAcceptStart = new TextButtonClass( BUTTON_ACCEPTSTART, TXT_WOL_STARTBUTTON, TPF_BUTTON, d_accept_x, d_accept_y,  d_accept_w );\n\t\tpTTipAcceptStart = new ToolTipClass( pTextBtnAcceptStart, TXT_WOL_TTIP_START, d_accept_x + d_accept_w/2, d_accept_y - 6 );\n\t}\n\telse\n\t{\n\t\tpTextBtnAcceptStart = new TextButtonClass( BUTTON_ACCEPTSTART, TXT_WOL_ACCEPTBUTTON, TPF_BUTTON, d_accept_x, d_accept_y, d_accept_w );\n\t\tpTTipAcceptStart = new ToolTipClass( pTextBtnAcceptStart, TXT_WOL_TTIP_ACCEPT, d_accept_x + d_accept_w/2, d_accept_y - 6 );\n\t}\n\n\tpTextBtnAction = new TextButtonClass( BUTTON_ACTION, TXT_WOL_ACTION, TPF_BUTTON, d_action_x, d_action_y, d_action_w );\n\tpTTipAction = new ToolTipClass( pTextBtnAction, TXT_WOL_TTIP_ACTION, d_action_x + d_action_w/2, d_action_y - 6, true );\n\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pTTipCancel;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pTTipAcceptStart;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = pTTipAction;\n\tpToolTip = pToolTip->next;\n\tpToolTip->next = NULL;\n\n\tif( bHost )\n\t\tpTextBtnAcceptStart->Disable();\n\n\t//\tpStaticDescrip is no longer used - can't get the bloody thing to clip text. You'd think a StaticButton control would.\n//\tpStaticDescrip = new StaticButtonClass( 0, \"\", TPF_TYPE, d_gamekind_x, d_gamekind_y, d_gamekind_w, d_gamekind_h );\n\tpStaticUnit = new StaticButtonClass( 0, \"    \", TPF_TEXT, d_count_x + d_count_w + 2*RESFACTOR, d_count_y );\n\tpStaticLevel = new StaticButtonClass( 0, \"    \", TPF_TEXT, d_level_x + d_level_w + 2*RESFACTOR, d_level_y );\n\tpStaticCredits = new StaticButtonClass( 0, \"         \", TPF_TEXT, d_credits_x + d_credits_w + 2*RESFACTOR, d_credits_y );\n\tpStaticAIPlayers = new StaticButtonClass( 0, \"   \", TPF_TEXT, d_aiplayers_x + d_aiplayers_w + 2*RESFACTOR, d_aiplayers_y );\n\n\tFancy_Text_Print(\"\", 0, 0, 0, 0, TPF_TEXT);\n\tpDropListHouse = new DropListClass( BUTTON_HOUSE, szHouseBuffer, sizeof( szHouseBuffer ),\n\t\tTPF_TEXT,\n\t\td_house_x, d_house_y, d_house_w, d_house_h,\n\t\tMFCD::Retrieve(\"BTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"BTN-DN.SHP\") );\n\n\t//\tajw - This checkbox is not used. Could be turned on, though.\n\tpCheckAftermathUnits = new BigCheckBoxClass( BUTTON_AFTERMATHUNITS, d_amunits_x, d_amunits_y, d_amunits_w, d_amunits_h,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Aftermath units enabled\", TPF_TEXT, false );\n\n\tif( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::AMGAME )\n\t{\n\t\tbAftermathUnits = true;\n\t\tint current_drive = CCFileClass::Get_CD_Drive();\n\t\tint cd_index = Get_CD_Index(current_drive, 1*60);\n\t\tif( cd_index != 3 && cd_index != 5 )\n\t\t{\n\t\t\tWOL_PrintMessage( *pILDisc, TXT_WOL_AMDISCNEEDED, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t}\n\t}\n\telse\n\t{\n\t\tbAftermathUnits = false;\n\t\tpCheckAftermathUnits->Disable();\n\t}\n\n\tbSlowUnitBuildRate = true;\n\n#define TABSPACING 38\n\tpShpBtnScenarioRA = new ShapeButtonClass( BUTTON_SCENARIO_RA, MFCD::Retrieve( \"tabra.shp\" ), d_scenariolist_x, d_scenariolist_y - d_tab_h );\n\tpShpBtnScenarioCS = new ShapeButtonClass( BUTTON_SCENARIO_CS, MFCD::Retrieve( \"tabcs.shp\" ), d_scenariolist_x + TABSPACING, d_scenariolist_y - d_tab_h );\n\tpShpBtnScenarioAM = new ShapeButtonClass( BUTTON_SCENARIO_AM, MFCD::Retrieve( \"tabam.shp\" ), d_scenariolist_x + TABSPACING, d_scenariolist_y - d_tab_h );\n\n\tint iScenarioUserTabPos;\n\tif( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::CSGAME || pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::AMGAME ||\n\t\t( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::RAGAME && Is_Aftermath_Installed() && !pWO->GameInfoCurrent.bTournament ) )\n\t\t//\tPlace user tab in the third tab position. (It may still not be present.)\n\t\tiScenarioUserTabPos = d_scenariolist_x + TABSPACING * 2;\n\telse\n\t\tiScenarioUserTabPos = d_scenariolist_x + TABSPACING;\n\n\tpShpBtnScenarioUser = new ShapeButtonClass( BUTTON_SCENARIO_USER, MFCD::Retrieve( \"tabus.shp\" ), iScenarioUserTabPos, d_scenariolist_y - d_tab_h );\n\n\t//\tChange draw behavior of tab buttons.\n\tpShpBtnScenarioRA->ReflectButtonState = true;\n\tpShpBtnScenarioCS->ReflectButtonState = true;\n\tpShpBtnScenarioAM->ReflectButtonState = true;\n\tpShpBtnScenarioUser->ReflectButtonState = true;\n\n\tif( !bHost )\n\t{\n\t\tpILScens->Disable();\n\t\tpGaugeCount->Disable();\n\t\tpGaugeLevel->Disable();\n\t\tpGaugeCredits->Disable();\n\t\tpGaugeAIPlayers->Disable();\n\t\tpCheckListOptions->Disable();\n\t\tpCheckAftermathUnits->Disable();\n\t}\n\n\tpWO->LinkToGameDlg( pILDisc, pILPlayers );\n\tpWO->pGSupDlg = this;\n\n\tdwTimeNextParamRefresh = ::timeGetTime();\n}\n\n//***********************************************************************************************\nRESULT_WOLGSUP WOL_GameSetupDialog::Show()\n{\n\t//\tReturns: -1 == return to chat dialog.\n\n\t//------------------------------------------------------------------------\n\t//\tDialog variables\n\t//------------------------------------------------------------------------\n\tbool bHackFocus = true;\n\n\tdisplay = REDRAW_ALL;\t\t// redraw level\n\tbProcess = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\n\tDWORD timeWaitingToStartTimeout;\n\n\tchar szScenarioNameDisplay[ 300 ];\n\n\tbool\tbInformParamChange;\n\n\tlong ok_timer = 0;\t\t\t\t\t\t// for timing OK button\n\tint i;\n\tint tabs[] = {77*RESFACTOR};\t\t\t// tabs for player list box\n\tint optiontabs[] = {8*RESFACTOR};\t\t// tabs for option list box\n\n\tCCFileClass loadfile (\"SAVEGAME.NET\");\n\tint load_game = 0;\t\t\t\t\t\t// 1 = load a saved game\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\tint cbox_x[] = {\n\t\t\t\t\t\t\td_color_x,\n\t\t\t\t\t\t\td_color_x + d_color_w,\n\t\t\t\t\t\t\td_color_x + (d_color_w * 2),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 3),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 4),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 5),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 6),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 7),\n\t\t\t\t\t};\n\n\tbool bRetractHouseDropDown = false;\n\n\tif( !pWO->OnEnteringGameSetup() )\t\t//\tGets a userlist setup, among other things.\n\t\tstrcpy( szNameOfHostWhoJustBailedOnUs, TXT_WOL_THEGAMEHOST );\t\t//\tWill cause immediate exit.\n\n\t//\tIf I'm not already listed with a color, give myself a color.\n\t//\t(I may have already received my assigned color from the game host.)\n\tint iItem = pILPlayers->Find( pWO->szMyName );\t\t//\t(I must be in the list I just got.)\n\t_ASSERTE( iItem != -1 );\n\tRemapControlType* pColorRemap = pILPlayers->Get_Item_Color( iItem );\n\tPlayerColorType Color = PlayerColorTypeOf( pColorRemap );\n\n//\tdebugprint( \"Starting up, I see myself as color %i\\n\", Color );\n\tif( Color == PCOLOR_NONE )\n\t\tSetPlayerColor( pWO->szMyName, ColorNextAvailable() );\t//\tUnless I'm host, this will be changed quite immediately,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\tbut nice to have it be a valid value until then.\n\n\tDWORD dwTimeNextPlayerPing = ::timeGetTime() + PING_AND_DISPLAY_WAIT;\n\tDWORD dwTimeNextPingDisplay = dwTimeNextPlayerPing + 1500;\t\t//\tStagger ping and ping display periods.\n\n\t//------------------------------------------------------------------------\n\t//\tBuild the button list\n\t//------------------------------------------------------------------------\n\tBindControls( true );\n\n\tpILPlayers->Set_Tabs(tabs);\n\n\t//\tIf we have not already received a param update from a host, set default param values.\n\tif( !bParamsReceived )\n\t{\n\t\tif( !bHost )\n\t\t\t//\tAccept button disabled until first params arrive.\n\t\t\tpTextBtnAcceptStart->Disable();\n\n\t\tSpecial.IsCaptureTheFlag = Rule.IsMPCaptureTheFlag;\t\t//\tUgh. Use of \"Special\" global.\n\t\tif( bHost ) {\n\t\t\tSession.Options.Credits = Rule.MPDefaultMoney;\t\t\t// init credits & credit buffer\n\t\t\tSession.Options.Bases = Rule.IsMPBasesOn;\t\t\t\t\t// init scenario parameters\n\t\t\tSession.Options.Tiberium = Rule.IsMPTiberiumGrow;\n\t\t\tSession.Options.Goodies = Rule.IsMPCrates;\n\t\t\tSession.Options.AIPlayers = 0;\n\t\t\tSession.Options.UnitCount = (SessionClass::CountMax[Session.Options.Bases] + SessionClass::CountMin[Session.Options.Bases]) / 2;\n\t\t\t//first_time = 0;\n\t\t}\n\t\t//------------------------------------------------------------------------\n\t\t//\tInit other scenario parameters\n\t\t//------------------------------------------------------------------------\n\t\tSpecial.IsTGrowth = Session.Options.Tiberium;\t\t//\tUgh. Use of \"Special\" global.\n\t\tRule.IsTGrowth = Session.Options.Tiberium;\n\t\tSpecial.IsTSpread = Session.Options.Tiberium;\t\t//\tUgh. Use of \"Special\" global.\n\t\tRule.IsTSpread = Session.Options.Tiberium;\n\n\t\tif( bHost )\n\t\t{\n\t\t\t//------------------------------------------------------------------------\n\t\t\t//\tSet up array of lists of available scenarios.\n\t\t\t//------------------------------------------------------------------------\n\t\t\tfor( i = 0; i < Session.Scenarios.Count(); i++ )\n\t\t\t{\n\t\t\t\t//\tReworking of the loop previously used for language translation. (What a hack I have inherited...)\n\t\t\t\tMultiMission* pMMission = Session.Scenarios[ i ];\n\t\t\t\tconst char* szScenarioNameShow = pMMission->Description();\n\t#if defined( GERMAN ) || defined( FRENCH )\n\t\t\t\tfor( int j = 0; EngMisStr[j] != NULL; j++ )\n\t\t\t\t{\n\t\t\t\t\tif( !strcmp( szScenarioNameShow, EngMisStr[j] ) )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tFound description in translation array that matches mission.\n\t\t\t\t\t\tszScenarioNameShow = EngMisStr[ j + 1 ];\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t//\t(If no match found, defaults to English description.)\n\t#endif\n\t\t\t\t//\tPlace scenario name in a specific scenario list.\n\t\t\t\tif( pMMission->Get_Official() )\n\t\t\t\t{\n\t\t\t\t\tif( Is_Mission_Counterstrike( (char*)( Session.Scenarios[i]->Get_Filename() ) ) )\n\t\t\t\t\t{\n\t//\t\t\t\t\tdebugprint( \" ---------------- Adding scenario %s as CS\\n\", szScenarioNameShow );\n\t\t\t\t\t\tar_szScenarios[ SCENARIO_CS ].Add( szScenarioNameShow );\n\t\t\t\t\t\tar_szScenIndexes[ SCENARIO_CS ].Add( (void*)i );\n\t\t\t\t\t}\n\t\t\t\t\telse if( Is_Mission_Aftermath( (char*)( Session.Scenarios[i]->Get_Filename() ) ) )\n\t\t\t\t\t{\n\t//\t\t\t\t\tdebugprint( \" ---------------- Adding scenario %s as AM\\n\", szScenarioNameShow );\n\t\t\t\t\t\t//\tIf this is not an Aftermath game channel, we must filter out any AM maps that have\n\t\t\t\t\t\t//\tspecial AM units on them.\n\t\t\t\t\t\tif( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::AMGAME ||\n\t\t\t\t\t\t\t!bSpecialAftermathScenario( pMMission->Description() ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tar_szScenarios[ SCENARIO_AM ].Add( szScenarioNameShow );\n\t\t\t\t\t\t\tar_szScenIndexes[ SCENARIO_AM ].Add( (void*)i );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t//\t\t\t\t\tdebugprint( \" ---------------- Adding scenario %s as RA\\n\", szScenarioNameShow );\n\t\t\t\t\t\tar_szScenarios[ SCENARIO_RA ].Add( szScenarioNameShow );\n\t\t\t\t\t\tar_szScenIndexes[ SCENARIO_RA ].Add( (void*)i );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t//\t\t\t\tdebugprint( \" ---------------- Adding scenario %s as User\\n\", szScenarioNameShow );\n\t\t\t\t\tar_szScenarios[ SCENARIO_USER ].Add( szScenarioNameShow );\n\t\t\t\t\tar_szScenIndexes[ SCENARIO_USER ].Add( (void*)i );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//\tSet default scenario list viewing mode and prepare tab buttons.\n\t/*\t\tswitch( pWO->GameInfoCurrent.GameKind )\n\t\t\t{\n\t\t\tcase CREATEGAMEINFO::RAGAME:\n\t\t\t\tScenarioDisplayMode( SCENARIO_RA );\n\t\t\t\tbreak;\n\t\t\tcase CREATEGAMEINFO::CSGAME:\n\t\t\t\tScenarioDisplayMode( SCENARIO_CS );\n\t\t\t\tbreak;\n\t\t\tcase CREATEGAMEINFO::AMGAME:\n\t\t\t\tScenarioDisplayMode( SCENARIO_AM );\n\t\t\t\tbreak;\n\t\t\tdefault:\n//\t\t\t\tdebugprint( \"Illegal GameInfoCurrent value.\" );\n\t\t\t\tFatal( \"Illegal GameInfoCurrent value.\" );\n\t\t\t}\n\t*/\n\t\t\tSession.Options.ScenarioIndex = 0;\t\t// 1st scenario is selected\n\n\t\t\tScenarioDisplayMode( SCENARIO_RA );\t\t//\tAlways start on RedAlert tab. Next line depends on selected item in\n\t\t\t\t\t\t\t\t\t\t\t\t\t//\tlist matching selected scenario.\n//\t\t\tpStaticDescrip->Set_Text( pILScens->Get_Item( pILScens->Current_Index() ), false );\n\t\t\tstrcpy( szScenarioNameDisplay, pILScens->Get_Item( pILScens->Current_Index() ) );\n\t\t}\n\n\t\tSeed = rand();\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tInit button states\n\t//------------------------------------------------------------------------\n\tpCheckListOptions->Set_Tabs(optiontabs);\n\tpCheckListOptions->Set_Read_Only(0);\n\n\tpCheckListOptions->Add_Item(Text_String(TXT_BASES));\n\tpCheckListOptions->Add_Item(Text_String(TXT_ORE_SPREADS));\n\tpCheckListOptions->Add_Item(Text_String(TXT_CRATES));\n\tpCheckListOptions->Add_Item(Text_String(TXT_CAPTURE_THE_FLAG));\n\tpCheckListOptions->Add_Item(Text_String(TXT_SHADOW_REGROWS));\n\tpCheckListOptions->Add_Item(TXT_WOL_SLOWUNITBUILD);\n\n\tSetSpecialControlStates();\n\n\t//........................................................................\n\t// House buttons\n\t//........................................................................\n\tfor (HousesType house = HOUSE_USSR; house <= HOUSE_FRANCE; house++) {\n\t\tpDropListHouse->Add_Item(Text_String(HouseTypeClass::As_Reference(house).Full_Name()));\n\t}\n\tpDropListHouse->Set_Selected_Index(Session.House - HOUSE_USSR);\n\tpDropListHouse->Set_Read_Only (true);\n\n\n\tbInformParamChange = false;\n\n//\tPlayingAgainstVersion = VerNum.Version_Number();\n\n\t//------------------------------------------------------------------------\n\t//\tInit random-number generator, & create a seed to be used for all random\n\t//\tnumbers from here on out\n\t//------------------------------------------------------------------------\n\tsrand(time(NULL));\n\n\t//------------------------------------------------------------------------\n\t//\tInit the version-clipping system\n\t//------------------------------------------------------------------------\n\tVerNum.Init_Clipping();\n\n\n//\tLoad_Title_Page(true);\n//\tCCPalette.Set();\t//GamePalette.Set();\n\n\t//\n\t// Now init the max range of the AI players slider.\n\t//\n//\tpGaugeAIPlayers->Set_Maximum(Rule.MaxPlayers-Session.Players.Count());\n//\tpGaugeAIPlayers->Set_Value(Session.Options.AIPlayers);\n\n\tSound_Effect( WOLSOUND_ENTERGAME );\n\n\t//------------------------------------------------------------------------\n\t//\tProcessing loop\n\t//------------------------------------------------------------------------\n\twhile (bProcess) {\n\t\t#if(SHOW_MONO)\n\t\tIpx.Mono_Debug_Print(-1,0);\n\t\t#endif\n\n\t\t//\tCheck for change of house. Occurs on first loop and when user changes house.\n\t\tif( HousePrevious != Session.House )\n\t\t{\n\t\t\tif( bHost )\n\t\t\t{\n\t\t\t\t//\tHost changed house.\n\t\t\t\t//\tDo processing as if we'd received a message from a guest.\n\n\t\t\t\t//\tSet house in our own list.\n\t\t\t\tSetPlayerHouse( pWO->szMyName, Session.House );\n\t\t\t\t//\tTell guests.\n\t\t\t\tnHostLastParamID++;\n\t\t\t\tInformAboutPlayerHouse( pWO->szMyName, Session.House, NULL );\n\t\t\t\tHousePrevious = Session.House;\n\t\t\t\tClearAllAccepts();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tUser* pUserHost = pWO->pGameHost();\n\t\t\t\tif( pUserHost )\t\t//\tElse we have not received the user list yet and don't know who the host is.\n\t\t\t\t\t\t\t\t\t//\tWe'll keep trying this until we get a host - HousePrevious keeps us triggering until then.\n\t\t\t\t{\n//\t\t\t\t\tdebugprint( \"Session.House changed.\\n\" );\n\t\t\t\t\t//\tTell host we changed our house.\n\t\t\t\t\tchar szSend[ 20 ];\n\t\t\t\t\tsprintf( szSend, \"%02u %02u\", WOL_GAMEOPT_REQHOUSE, Session.House );\n\t\t\t\t\tpWO->SendGameOpt( szSend, pUserHost );\n\t\t\t\t\t//\tSet house in our own list. This is fine because we know that the change must be affirmed by the host.\n\t\t\t\t\tSetPlayerHouse( pWO->szMyName, Session.House );\n\t\t\t\t\tHousePrevious = Session.House;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//\tRegularly ping other players to assess latencies.\n\t\t//\tDisplay of ping results is on a parallel timer, slightly behind the ping so that we'll be likely to have\n\t\t//\ta fresh average to show. Not too big a deal if OnPings haven't arrived by then (though they should have).\n\t\tif( ::timeGetTime() > dwTimeNextPlayerPing )\n\t\t{\n\t\t\tpWO->RequestPlayerPings();\n\t\t\tdwTimeNextPlayerPing = ::timeGetTime() + PING_AND_DISPLAY_WAIT;\n\t\t}\n\t\tif( ::timeGetTime() > dwTimeNextPingDisplay )\n\t\t{\n\t\t\tpWO->ListChannelUsers();\n\t\t\tdwTimeNextPingDisplay = ::timeGetTime() + PING_AND_DISPLAY_WAIT;\n\t\t}\n\n\t\tif( pWO->bShowRankUpdated )\n\t\t{\n\t\t\tpWO->bShowRankUpdated = false;\n\t\t\tpWO->ListChannelUsers();\n\t\t}\n\n\t\t//\tRegularly check for incoming messages from wolapi.\n\t\tif( ::timeGetTime() > pWO->dwTimeNextWolapiPump )\n\t\t{\n\t\t\tpWO->pChat->PumpMessages();\n\t\t\tpWO->pNetUtil->PumpMessages();\n\t\t\t//\tSpecial post-callback processing...\n\t\t\tif( pWO->pChatSink->bGotKickedTrigger )\n\t\t\t{\n\t\t\t\t//\tWe got kicked out of the channel.\n\t\t\t\tpWO->OnExitingGameChannel();\n\t\t\t\tpWO->RejoinLobbyAfterGame();\n\t\t\t\tbProcess = false;\n\t\t\t\tResultReturn = RESULT_WOLGSUP_BACKTOCHAT;\t//\tReturn to chat.\n\t\t\t\t//\tLeave the bGotKickedTrigger flag so we can react to it upon reentering the chat dialog.\n\t\t\t\t//pWO->pChatSink->bGotKickedTrigger = false;\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t}\n\t\t\tpWO->dwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT;\n\t\t}\n\n\t\tif( bHostSayGo )\n\t\t{\n//\t\t\tdebugprint( \"bHostSayGo trigger\\n\" );\n\t\t\t//\tWe are the host, now ready to tell everyone to GO and start our game.\n\t\t\tHostSaysGo();\n/*\tPart of old method of game start.\n\t\t\tbProcess = false;\n\t\t\tResultReturn = RESULT_WOLGSUP_STARTGAMEHOST;\n//\t\t\tdebugprint( \"Host about to exit game setup dialog for game.\\n\" );\n\t\t\tif( !ExitGameChannel() )\n\t\t\t\tResultReturn = RESULT_WOLGSUP_FATALERROR;\t//\tReturn with an error value.\n\t\t\tbreak;\n*/\n\t\t}\n\t\telse if( *szNameOfHostWhoJustBailedOnUs )\t\t//\tHost left channel - cancel setup.\n\t\t{\n//\t\t\tdebugprint( \"Guest about to exit game setup dialog because host bailed on us.\\n\" );\n\t\t\tif( ExitGameChannel() )\n\t\t\t{\n\t\t\t\tpWO->RejoinLobbyAfterGame();\n\t\t\t\tbProcess = false;\n\t\t\t\tResultReturn = RESULT_WOLGSUP_HOSTLEFT;\t//\tReturn to chat.\n\t\t\t\t//\tAdd a message explaining what happened to the saved chat that will be restored in the chat dialog.\n\t\t\t\tpWO->AddHostLeftMessageToSavedChat( szNameOfHostWhoJustBailedOnUs );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tbProcess = false;\n\t\t\t\tResultReturn = RESULT_WOLGSUP_FATALERROR;\t//\tReturn with an error value.\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\telse if( bLeaveDueToRulesMismatchTrigger )\n\t\t{\n//\t\t\tdebugprint( \"Guest about to exit game setup dialog because of rules.ini mismatch.\\n\" );\n\t\t\tif( ExitGameChannel() )\n\t\t\t{\n\t\t\t\tpWO->RejoinLobbyAfterGame();\n\t\t\t\tbProcess = false;\n\t\t\t\tResultReturn = RESULT_WOLGSUP_RULESMISMATCH;\t//\tReturn to chat.\n\t\t\t\t//\tAdd a message explaining what happened to the saved chat that will be restored in the chat dialog.\n\t\t\t\tpWO->AddMessageToSavedChat( TXT_WOL_RULESMISMATCH );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tbProcess = false;\n\t\t\t\tResultReturn = RESULT_WOLGSUP_FATALERROR;\t//\tReturn with an error value.\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\telse if( *szTriggerGameStartInfo )\n\t\t{\n//\t\t\tdebugprint( \"About to trigger game start.\\n\" );\n\t\t\tTriggerGameStart( szTriggerGameStartInfo );\n\t\t}\n\t\telse if( pWO->bSelfDestruct )\n\t\t{\n\t\t\tif( pWO->pChatSink->bConnected )\n\t\t\t\tpWO->Logout();\n\t\t\tbProcess = false;\n\t\t\tResultReturn = RESULT_WOLGSUP_LOGOUT;\t\t//\tAs if the user logged himself out.\n\t\t}\n\n\t\tif( bExitForGameTrigger )\n\t\t{\n\t\t\t//\tWe are now exiting to go into a game.\n\t\t\tbProcess = false;\n\t\t\tif( bHost )\n\t\t\t\tResultReturn = RESULT_WOLGSUP_STARTGAMEHOST;\n\t\t\telse\n\t\t\t\tResultReturn = RESULT_WOLGSUP_STARTGAME;\n//\t\t\tdebugprint( \"About to exit game setup dialog for game.\\n\" );\n\t\t\tif( !ExitGameChannel() )\n\t\t\t\tResultReturn = RESULT_WOLGSUP_FATALERROR;\t//\tReturn with an error value.\n\t\t\tbreak;\n\t\t}\n\n\t\tif( bHost && bWaitingToStart && !bExitForGameTrigger && timeGetTime() > timeWaitingToStartTimeout )\n\t\t{\n\t\t\tClearAllAccepts();\t\t//\tResults in all required steps to cancel game start.\n\t\t\tWOL_PrintMessage( *pILDisc, TXT_WOL_STARTTIMEOUT, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\tSound_Effect( WOLSOUND_ERROR );\n\t\t}\n\n\t\t//\tRegularly send game param changes if I'm the host.\n\t\tif( bHost && !bHostSayGo && !bExitForGameTrigger && ::timeGetTime() > dwTimeNextParamRefresh )\n\t\t{\n\t\t\tif( bParamsUnfresh() )\n\t\t\t{\n\t\t\t\tnHostLastParamID++;\n\t\t\t\tSendParams();\n\t\t\t\tClearAllAccepts();\n\t\t\t}\n\t\t\tdwTimeNextParamRefresh = ::timeGetTime() + PARAMREFRESHWAIT;\n\t\t}\n\n\t\tif( !bProcess )\t\t\t//\tAvoid redrawing if we're about to bail.\n\t\t\tbreak;\n\n\t\t//\n\t\t// If we have just received input focus again after running in the background then\n\t\t// we need to redraw.\n\t\t//\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tRefresh display if needed\n\t\t//.....................................................................\n\n\t\tif( bRetractHouseDropDown )\t//|| pCheckListOptions->Is_To_Redraw() )\n\t\t{\n\t\t\tbRetractHouseDropDown = false;\n\t\t\tif( pDropListHouse->IsDropped )\n\t\t\t{\n\t\t\t\tpDropListHouse->Collapse();\n\t\t\t\tif (display < REDRAW_BACKGROUND) display = REDRAW_BACKGROUND;\n\t\t\t}\n\t\t}\n//\t\tif( pILDisc->Is_To_Redraw() )\n//\t\t{\n//\t\t\tpDropListHouse->Flag_To_Redraw();\n//\t\t}\n\n\t\tif( display )\n\t\t{\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t** Collapse the country list if we are going to redraw the game list\n\t\t\t*/\n//\t\t\tif (pILScens->Is_To_Redraw() && pDropListHouse->IsDropped) {\n//\t\t\t\tpDropListHouse->Collapse();\n//\t\t\t\tif (display < REDRAW_BACKGROUND) display = REDRAW_BACKGROUND;\n//\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw backgound & dialog box\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tif( pToolTipHitLast && pToolTipHitLast->bShowing )\n\t\t\t\t\tpToolTipHitLast->Unshow();\n\n\t\t\t\tif( pDropListHouse->IsDropped )\n\t\t\t\t\tpDropListHouse->Collapse();\n\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tDialog & Field labels\n\t\t\t\t//...............................................................\n\t\t\t\tFancy_Text_Print(TXT_PLAYERS, d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h, scheme, TBLACK, TPF_TEXT | TPF_CENTER);\n\t\t\t\tif( bHost )\n\t\t\t\t\tFancy_Text_Print( TXT_SCENARIOS, d_scenariolist_x + d_scenariolist_w, d_scenariolist_y - 12, scheme, TBLACK, TPF_TYPE | TPF_RIGHT );\n//\t\t\t\telse\n//\t\t\t\t\tFancy_Text_Print( TXT_SCENARIO_COLON, d_scenariolist_x + (d_scenariolist_w / 2), d_scenariolist_y - d_txt6_h, scheme, TBLACK, TPF_TEXT | TPF_CENTER);\n\t\t\t\tFancy_Text_Print(TXT_COUNT, d_count_x - 2*RESFACTOR, d_count_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print(TXT_LEVEL, d_level_x - 2*RESFACTOR, d_level_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print(TXT_CREDITS_COLON, d_credits_x - 2*RESFACTOR, d_credits_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print(TXT_AI_PLAYERS_COLON, d_aiplayers_x - 2*RESFACTOR, d_aiplayers_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print(TXT_SIDE_COLON,\n//\t\t\t\t\td_house_x + (d_house_w / 2),\n\t\t\t\t\td_house_x + ( ( d_house_w + 16 ) / 2 ),\n\t\t\t\t\td_house_y - d_txt6_h,\n\t\t\t\t\tscheme, TBLACK,\n\t\t\t\t\tTPF_CENTER | TPF_TEXT);\n\t\t\t\tFancy_Text_Print(TXT_COLOR_COLON,\n\t\t\t\t\td_color_x + d_color_w * 4,\n\t\t\t\t\td_color_y - d_txt6_h,\n\t\t\t\t\tscheme, TBLACK,\n\t\t\t\t\tTPF_CENTER | TPF_TEXT);\n\n\t\t\t\tconst char* szGameKind;\n\t\t\t\tconst char* pDIB;\n\t\t\t\tswitch( pWO->GameInfoCurrent.GameKind )\n\t\t\t\t{\n\t\t\t\tcase CREATEGAMEINFO::RAGAME:\n\t\t\t\t\tszGameKind = TXT_WOL_CG_RAGAME;\n\t\t\t\t\tpDIB = pWO->OldRAGameTypeInfos[ 0 ].pDIB;\n\t\t\t\t\tbreak;\n\t\t\t\tcase CREATEGAMEINFO::CSGAME:\n\t\t\t\t\tszGameKind = TXT_WOL_CG_CSGAME;\n\t\t\t\t\tpDIB = pWO->OldRAGameTypeInfos[ 1 ].pDIB;\n\t\t\t\t\tbreak;\n\t\t\t\tcase CREATEGAMEINFO::AMGAME:\n\t\t\t\t\tszGameKind = TXT_WOL_CG_AMGAME;\n\t\t\t\t\tpDIB = pWO->OldRAGameTypeInfos[ 2 ].pDIB;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n//\t\t\t\t\tdebugprint( \"Illegal GameInfoCurrent value.\" );\n\t\t\t\t\t//Fatal( \"Illegal GameInfoCurrent value.\" );\n\t\t\t\t\tszGameKind = TXT_WOL_CG_AMGAME;\n\t\t\t\t\tpDIB = NULL;\n\t\t\t\t\tpWO->bSelfDestruct = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tint iGameInfoSpacingY = 14;\n\t\t\t\tint iGameInfoSecondColumnX = 0;\t//170;\n\t\t\t\t//\tGame kind.\n\t\t\t\tFancy_Text_Print( szGameKind, d_gamekind_x, d_gamekind_y - iGameInfoSpacingY * 1, scheme, TBLACK, TPF_TYPE );\n\t\t\t\t//\tGame kind icon.\n\t\t\t\tCC_Draw_DIB( pDIB, d_gamekind_x - 16, d_gamekind_y - iGameInfoSpacingY * 1 - 2, 100, WINDOW_MAIN );\n\t\t\t\t//\t\"Tournament.\"\n\t\t\t\tif( pWO->GameInfoCurrent.bTournament )\n\t\t\t\t{\n\t\t\t\t\tFancy_Text_Print( TXT_WOL_CG_TOURNAMENT, d_gamekind_x + iGameInfoSecondColumnX,\n\t\t\t\t\t\t\t\t\t\td_gamekind_y + iGameInfoSpacingY * 1, scheme, TBLACK, TPF_TYPE );\n\t\t\t\t\tCC_Draw_DIB( pWO->DibIconInfos[ DIBICON_TOURNAMENT ].pDIB, d_gamekind_x + iGameInfoSecondColumnX - 16,\n\t\t\t\t\t\t\t\t\t\td_gamekind_y + iGameInfoSpacingY * 1 - 2, 100, WINDOW_MAIN );\n\t\t\t\t}\n\t\t\t\t//\t\"Password: ...\"\n\t\t\t\tif( pWO->GameInfoCurrent.bPrivate )\n\t\t\t\t{\n\t\t\t\t\tchar szPrivatePassword[ 100 ];\n\t\t\t\t\tsprintf( szPrivatePassword, TXT_WOL_PRIVATEPASSWORD, pWO->GameInfoCurrent.szPassword );\n\t\t\t\t\tFancy_Text_Print( szPrivatePassword, d_gamekind_x + iGameInfoSecondColumnX,\n\t\t\t\t\t\t\t\t\t\td_gamekind_y + iGameInfoSpacingY * 2, scheme, TBLACK, TPF_TYPE );\n\t\t\t\t\tCC_Draw_DIB( pWO->DibIconInfos[ DIBICON_PRIVATE ].pDIB, d_gamekind_x + iGameInfoSecondColumnX - 16,\n\t\t\t\t\t\t\t\t\t\td_gamekind_y + iGameInfoSpacingY * 2 - 2, 100, WINDOW_MAIN );\n\t\t\t\t}\n\t\t\t\t//\t\"Scenario:\" - scenario name is drawn separately.\n\t\t\t\t//Fancy_Text_Print( TXT_SCENARIO_COLON, d_gamekind_x, d_gamekind_y - iGameInfoSpacingY, scheme, TBLACK, TPF_TYPE );\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw buttons\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\n\t\t\t\tcommands->Draw_All();\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tDraw the color boxes\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_COLORS ) {\n\t\t\t\tfor (i = 0; i < MAX_MPLAYER_COLORS; i++) {\n\t\t\t\t\tLogicPage->Fill_Rect (cbox_x[i] + 1, d_color_y + 1,\n\t\t\t\t\t\tcbox_x[i] + 1 + d_color_w - 2 *RESFACTOR, d_color_y + 1 + d_color_h - 2,\n\t\t\t\t\t\tColorRemaps[i].Box);\n\n\t\t\t\t\tif (i == Session.ColorIdx) {\n\t\t\t\t\t\tDraw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_DOWN, false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tDraw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_RAISED, false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tDraw the messages:\n\t\t\t//\t- Erase an old message first\n\t\t\t//\t- If we're in a game, print the game options (if they've been\n\t\t\t//\t  received)\n\t\t\t//\t- If we've been rejected from a game, print that message\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_MESSAGE) {\n//\t\t\t\tDraw_Box(d_disc_x, d_disc_y, d_disc_w, d_disc_h, BOXSTYLE_BOX, true);\n//\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true);\n//\t\t\t\tSession.Messages.Draw();\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// Update game parameter labels\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_PARMS)\n\t\t\t{\n\t\t\t\tchar txt[80];\n\n\t\t\t\tchar* szScenarioDesc;\n\t\t\t\tbool bOfficial;\n\t\t\t\tchar* szScenarioFileName;\n\t\t\t\tif( !bHost )\n\t\t\t\t{\n\t\t\t\t\tszScenarioDesc = Session.Options.ScenarioDescription;\n\t\t\t\t\tbOfficial = Session.ScenarioIsOfficial;\n\t\t\t\t\tszScenarioFileName = Session.ScenarioFileName;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tszScenarioDesc = (char*)Session.Scenarios[ Session.Options.ScenarioIndex ]->Description();\n\t\t\t\t\tbOfficial = Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Official();\n\t\t\t\t\tszScenarioFileName = (char*)Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Filename();\n\t\t\t\t}\n\n\t\t\t\tif( *szScenarioDesc )\n\t\t\t\t{\n\t\t\t\t\t//\tLanguage translation.\n\t\t\t\t\tfor (int ii = 0; EngMisStr[ii] != NULL;  ii++) {\n\t\t\t\t\t\tif (!strcmp( szScenarioDesc, EngMisStr[ii]) ) {\n\t\t\t\t\t\t\t#if defined(GERMAN) || defined(FRENCH)\n\t\t\t\t\t\t\t\t//sprintf(txt, \"%s %s\", Text_String(TXT_SCENARIO_COLON), EngMisStr[ii+1]);\n\t\t\t\t\t\t\t\tsprintf(txt, \"%s\", EngMisStr[ii+1]);\n\t\t\t\t\t\t\t#else\n\t\t\t\t\t\t\t\t//sprintf(txt, \"%s %s\", Text_String(TXT_SCENARIO_COLON), Session.Options.ScenarioDescription);\n\t\t\t\t\t\t\t\tsprintf(txt, \"%s\", szScenarioDesc);\n\t\t\t\t\t\t\t#endif\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (EngMisStr[ii] == NULL) {\n\t\t\t\t\t\tsprintf(txt, \"%s\", szScenarioDesc);\n\t\t\t\t\t}\n//\t\t\t\t\tpStaticDescrip->Set_Text( txt, false );\n\t\t\t\t\tstrcpy( szScenarioNameDisplay, txt );\n\n\t\t\t\t\t//\tShow icon for gamekind of scenario.\n\t\t\t\t\tconst char* pDIB;\n\n\t\t\t\t\tif( bOfficial )\n\t\t\t\t\t{\n\t\t\t\t\t\tif( Is_Mission_Counterstrike( szScenarioFileName ) )\n\t\t\t\t\t\t\tpDIB = pWO->OldRAGameTypeInfos[ 1 ].pDIB;\n\t\t\t\t\t\telse if( Is_Mission_Aftermath( szScenarioFileName ) )\n\t\t\t\t\t\t\tpDIB = pWO->OldRAGameTypeInfos[ 2 ].pDIB;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tpDIB = pWO->OldRAGameTypeInfos[ 0 ].pDIB;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tpDIB = pWO->DibIconInfos[ DIBICON_USER ].pDIB;\n\n\t\t\t\t\tDrawScenarioDescripIcon( pDIB );\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t//sprintf(txt, \"%s %s\", Text_String(TXT_SCENARIO_COLON), Text_String(TXT_NOT_FOUND));\n\t\t\t\t\tsprintf(txt, \"%s\", TXT_WOL_SCENARIONAMEWAIT );\n//\t\t\t\t\tpStaticDescrip->Set_Text( txt, false );\n\t\t\t\t\tstrcpy( szScenarioNameDisplay, txt );\n\t\t\t\t}\n\n\t\t\t\t//\tPrint scenario name.\n\t\t\t\tConquer_Clip_Text_Print( szScenarioNameDisplay, d_gamekind_x, d_gamekind_y, scheme, TBLACK, TPF_TYPE, d_gamekind_w );\n//\t\t\t\tpStaticDescrip->Draw_Me();\n\n\t\t\t\tsprintf(txt,\"%d\",Session.Options.UnitCount);\n\t\t\t\tpStaticUnit->Set_Text(txt);\n\t\t\t\tpStaticUnit->Draw_Me();\n\n\t\t\t\tif (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {\n\t\t\t\t\tsprintf(txt,\"%d\",BuildLevel);\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(txt, \"**\");\n\t\t\t\t}\n\t\t\t\tpStaticLevel->Set_Text(txt);\n\t\t\t\tpStaticLevel->Draw_Me();\n\n\t\t\t\tsprintf(txt,\"%d\",Session.Options.Credits);\n\t\t\t\tpStaticCredits->Set_Text(txt);\n\t\t\t\tpStaticCredits->Draw_Me();\n\n\t\t\t\tsprintf(txt,\"%d\",Session.Options.AIPlayers);\n\t\t\t\tpStaticAIPlayers->Set_Text(txt);\n\t\t\t\tpStaticAIPlayers->Draw_Me();\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t//\tForce mouse visible, as some beta testers report unexplicable disappearing cursors.\n\t\twhile( Get_Mouse_State() )\n\t\t\tShow_Mouse();\n\t\t//\tBe nice to other apps.\n\t\tSleep( 50 );\n\n\t\t//.....................................................................\n\t\t//\tGet user input\n\t\t//.....................................................................\n\t\tif( ( ::GetAsyncKeyState( KN_LMOUSE ) & 0x8000 ) || ( ::GetAsyncKeyState( KN_RMOUSE ) & 0x8000 ) )\n\t\t{\n\t\t\ttimeToolTipAppear = ::timeGetTime() + TOOLTIPDELAY;\n\t\t\tif( pToolTipHitLast && pToolTipHitLast->bShowing )\n\t\t\t\tpToolTipHitLast->Unshow();\n\t\t}\n\n\t\tinput = commands->Input();\n\n\t\tif( bHackFocus )\n\t\t{\n\t\t\tpEditSend->Set_Focus();\n\t\t\tpEditSend->Flag_To_Redraw();\n\t\t\tinput = commands->Input();\n\t\t\tbHackFocus = false;\n\t\t}\n\n\t\t//\tTooltips...\n\t\tif( pToolTipHead )\n\t\t{\n\t\t\tToolTipClass* pToolTipHit = pToolTipHead->GetToolTipHit();\n\t\t\tif( pToolTipHit == pToolTipHitLast )\n\t\t\t{\n\t\t\t\tif( pToolTipHit && !pToolTipHit->bShowing && ::timeGetTime() > timeToolTipAppear && !( ( ::GetAsyncKeyState( KN_LMOUSE ) & 0x8000 ) || ( ::GetAsyncKeyState( KN_RMOUSE ) & 0x8000 ) ) )\n\t\t\t\t{\n\t\t\t\t\tpToolTipHit->Show();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif( pToolTipHitLast && pToolTipHitLast->bShowing )\n\t\t\t\t\tpToolTipHitLast->Unshow();\n\t\t\t\tpToolTipHitLast = pToolTipHit;\n\t\t\t\ttimeToolTipAppear = ::timeGetTime() + TOOLTIPDELAY;\n\t\t\t}\n\t\t}\n\n\t\t//\tYummy special hack. Luv' that UI system.\n\t\tif( input == 2049 )\t\t//\tLeft mouse released, not on control that captured it.\n\t\t{\n\t\t\t//\tRedraw the tabs in case they were what were pressed down on.\n\t\t\tpShpBtnScenarioRA->Flag_To_Redraw();\n\t\t\tpShpBtnScenarioCS->Flag_To_Redraw();\n\t\t\tpShpBtnScenarioAM->Flag_To_Redraw();\n\t\t\tpShpBtnScenarioUser->Flag_To_Redraw();\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tProcess input\n\t\t//.....................................................................\n\t\tswitch( input )\n\t\t{\n\t\t\tcase KN_LMOUSE:\n\t\t\t\tif( !bWaitingToStart )\n\t\t\t\t{\n\t\t\t\t\t//\tCheck for mouse down on a control when player is not host.\n\t\t\t\t\tif( !bHost )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( (\n\t\t\t\t\t\t\t\tGet_Mouse_X() >= d_count_x &&\n\t\t\t\t\t\t\t\tGet_Mouse_X() <= d_count_x + d_count_w &&\n\t\t\t\t\t\t\t\tGet_Mouse_Y() >= d_count_y &&\n\t\t\t\t\t\t\t\tGet_Mouse_Y() <= d_aiplayers_y + d_aiplayers_h\n\t\t\t\t\t\t\t) || (\n\t\t\t\t\t\t\t\tGet_Mouse_X() >= d_options_x &&\n\t\t\t\t\t\t\t\tGet_Mouse_X() <= d_options_x + d_options_w &&\n\t\t\t\t\t\t\t\tGet_Mouse_Y() >= d_options_y &&\n\t\t\t\t\t\t\t\tGet_Mouse_Y() <= d_options_y + d_options_h\n\t\t\t\t\t\t\t) || (\n\t\t\t\t\t\t\t\tGet_Mouse_X() >= d_scenariolist_x &&\n\t\t\t\t\t\t\t\tGet_Mouse_X() <= d_scenariolist_x + d_scenariolist_w &&\n\t\t\t\t\t\t\t\tGet_Mouse_Y() >= d_scenariolist_y &&\n\t\t\t\t\t\t\t\tGet_Mouse_Y() <= d_scenariolist_y + d_scenariolist_h\n\t\t\t\t\t\t\t) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_ONLY_HOST_CAN_MODIFY), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\t\t\tWOL_PrintMessage( *pILDisc, Text_String( TXT_ONLY_HOST_CAN_MODIFY ), WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\t\t\t\t\tSound_Effect( WOLSOUND_ERROR );\n\t\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (Keyboard->MouseQX > cbox_x[0] &&\n\t\t\t\t\t\tKeyboard->MouseQX < (cbox_x[MAX_MPLAYER_COLORS - 1] + d_color_w) &&\n\t\t\t\t\t\tKeyboard->MouseQY > d_color_y &&\n\t\t\t\t\t\tKeyboard->MouseQY < (d_color_y + d_color_h))\n\t\t\t\t\t{\n\t\t\t\t\t\tSession.PrefColor = (PlayerColorType)\n\t\t\t\t\t\t\t((Keyboard->MouseQX - cbox_x[0]) / d_color_w);\n\n\t\t\t\t\t\t//\tEnsure that no one is using this color (to our knowledge).\n\t\t\t\t\t\tif( pILPlayers->FindColor( &ColorRemaps[ Session.PrefColor == PCOLOR_DIALOG_BLUE ? PCOLOR_REALLY_BLUE : Session.PrefColor ] ) == -1 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//\tShow me as the new color.\n//\t\t\t\t\t\t\tdebugprint( \"Color box pressed - \" );\n\t\t\t\t\t\t\tSetPlayerColor( pWO->szMyName, Session.PrefColor );\n\t\t\t\t\t\t\tif( bHost )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t//\tTell all guests about the color change.\n\t\t\t\t\t\t\t\tInformAboutPlayerColor( pWO->szMyName, Session.PrefColor, NULL );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tRequestPlayerColor( Session.PrefColor );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_DISCONNECT | KN_BUTTON ):\n\t\t\t\tif( WWMessageBox().Process( TXT_WOL_CONFIRMLOGOUT, TXT_YES, TXT_NO ) == 0 )\n\t\t\t\t{\n//\t\t\t\t\tdebugprint( \"Logging out from gsup.\\n\" );\n\t\t\t\t\tExitGameChannel();\n\t\t\t\t\tpWO->Logout();\n\t\t\t\t\tbProcess = false;\n\t\t\t\t\tResultReturn = RESULT_WOLGSUP_LOGOUT;\n\t\t\t\t}\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbHackFocus = true;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_REFRESH | KN_BUTTON ):\t\t//\tAlways disabled.\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_SQUELCH | KN_BUTTON ):\n\t\t\t\tpWO->DoSquelch( pILPlayers );\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_BAN | KN_BUTTON ):\n\t\t\t\tpWO->DoKick( pILPlayers, true );\n//\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_KICK | KN_BUTTON ):\n\t\t\t\tpWO->DoKick( pILPlayers, false );\n//\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_FINDPAGE | KN_BUTTON ):\n\t\t\t\tpWO->DoFindPage();\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbHackFocus = true;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_OPTIONS | KN_BUTTON ):\n\t\t\t\tpWO->DoOptions();\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbHackFocus = true;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_LADDER | KN_BUTTON ):\n\t\t\t\tpWO->DoLadder();\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbHackFocus = true;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_HELP | KN_BUTTON ):\n\t\t\t\tpWO->DoHelp();\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbHackFocus = true;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_HOUSE | KN_BUTTON ):\n\t\t\t\tSession.House = (HousesType)( pDropListHouse->Current_Index() + HOUSE_USSR );\n/*\n\t\t\t\t//\tBloody bloody hell I can't believe there are bugs in RA like the one I deal with here...\n\t\t\t\tif( strcmp( pDropListHouse->Current_Item(), \"Russia\" ) == 0 )\n\t\t\t\t\tSession.House = HOUSE_USSR;\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tSession.House = HouseTypeClass::From_Name( pDropListHouse->Current_Item() );\t//\tFails on \"Russia\". (Thinks \"USSR\".)\n\t\t\t\t\tif( Session.House == HOUSE_NONE )\n\t\t\t\t\t{\n//\t\t\t\t\t\tdebugprint( \"Couldn't find house from selected '%s'.\\n\", pDropListHouse->Current_Item() );\n\t\t\t\t\t}\n\t\t\t\t}\n*/\n\t\t\t\tif( pDropListHouse->IsDropped )\n\t\t\t\t\tbRetractHouseDropDown = true;\n\t\t\t\telse\n\t\t\t\t\tif (display < REDRAW_BACKGROUND) display = REDRAW_BACKGROUND;\t\t//\tDroplist already got contracted.\n\n\t\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_AFTERMATHUNITS | KN_BUTTON ):\n\t\t\t\tbAftermathUnits = pCheckAftermathUnits->IsOn;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_SENDEDIT | KN_BUTTON ):\n\t\t\t\t//\tEnter has been pressed - was caught by pEditSend control.\n\t\t\t\tpWO->SendMessage( pEditSend->Get_Text(), *pILPlayers, false );\n\t\t\t\t//\tClear pEditSend, reset focus.\n\t\t\t\tszSendBuffer[0] = 0;\n\t\t\t\tpEditSend->Set_Focus();\n\t\t\t\t//\tMark for redraw.\n\t\t\t\tpEditSend->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_ACTION | KN_BUTTON ):\n\t\t\t\t//\tEnter has been pressed - was caught by pEditSend control.\n\t\t\t\tpWO->SendMessage( pEditSend->Get_Text(), *pILPlayers, true );\n\t\t\t\t//\tClear pEditSend, reset focus.\n\t\t\t\tszSendBuffer[0] = 0;\n\t\t\t\tpEditSend->Set_Focus();\n\t\t\t\t//\tMark for redraw.\n\t\t\t\tpEditSend->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tNew Scenario selected.\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_SCENARIOLIST | KN_BUTTON):\n\t\t\t{\n\t\t\t\tif( pILScens->Count() )\n\t\t\t\t{\n\t\t\t\t\tint iSelectedScenIndex = (int)pILScens->Get_Item_ExtraDataPtr( pILScens->Current_Index() );\n\t\t\t\t\tif( iSelectedScenIndex != Session.Options.ScenarioIndex )\n\t\t\t\t\t{\n\t\t\t\t\t\tSession.Options.ScenarioIndex = iSelectedScenIndex;\n\t\t\t\t\t\tbInformParamChange = true;\n\t\t\t\t\t\tif( !pILScens->SetSelectType( 1 ) )\t//\tHack to deal with ListClass \"highlighting nothing\" problem.\n\t\t\t\t\t\t\t//\tSelectType was 0 before call.\n\t\t\t\t\t\t\tpILScens->Flag_To_Redraw();\n//\t\t\t\t\t\tpStaticDescrip->Set_Text( pILScens->Get_Item( pILScens->Current_Index() ), false );\n\t\t\t\t\t\tstrcpy( szScenarioNameDisplay, pILScens->Get_Item( pILScens->Current_Index() ) );\n\t\t\t\t\t\t//if (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t//..................................................................\n\t\t\t//\tUser adjusts max # units\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_COUNT | KN_BUTTON):\n\t\t\t\tSession.Options.UnitCount = pGaugeCount->Get_Value() +\n\t\t\t\t\tSessionClass::CountMin[Session.Options.Bases];\n\t\t\t\tbInformParamChange = true;\n\t\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\t\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tUser adjusts build level\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_LEVEL | KN_BUTTON):\n\t\t\t\tBuildLevel = pGaugeLevel->Get_Value() + 1;\n\t\t\t\tif (BuildLevel > MPLAYER_BUILD_LEVEL_MAX)\t// if it's pegged, max it out\n\t\t\t\t\tBuildLevel = MPLAYER_BUILD_LEVEL_MAX;\n\t\t\t\tbInformParamChange = true;\n\t\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\t\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tUser edits the credits value; retransmit new game options\n\t\t\t// Round the credits to the nearest 500.\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_CREDITS | KN_BUTTON):\n\t\t\t\tSession.Options.Credits = pGaugeCredits->Get_Value();\n\t\t\t\tSession.Options.Credits =\n\t\t\t\t\t((Session.Options.Credits + 250) / 500) * 500;\n\t\t\t\tbInformParamChange = true;\n\t\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\t\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tUser adjusts # of AI players\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_AIPLAYERS | KN_BUTTON):\n\t\t\t\tSession.Options.AIPlayers = pGaugeAIPlayers->Get_Value();\n//\t\t\t\tif (Session.Options.AIPlayers+Session.Players.Count() > Rule.MaxPlayers) {\t// if it's pegged, max it out\n\t\t\t\tif (Session.Options.AIPlayers + pWO->GameInfoCurrent.iPlayerMax > Rule.MaxPlayers) {\t// if it's pegged, max it out\n\t\t\t\t\tSession.Options.AIPlayers = Rule.MaxPlayers - pWO->GameInfoCurrent.iPlayerMax;\n\t\t\t\t\tpGaugeAIPlayers->Set_Value(Session.Options.AIPlayers);\n\t\t\t\t}\n\t\t\t\tbInformParamChange = true;\n\t\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\t\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t// Toggle-able options:\n\t\t\t// If 'Bases' gets toggled, we have to change the range of the\n\t\t\t// UnitCount slider.\n\t\t\t// Also, if Tiberium gets toggled, we have to set the flags\n\t\t\t// in SpecialClass.\n\t\t\t//..................................................................\n\t\t\tcase ( BUTTON_PARAMS | KN_BUTTON ):\n\t\t\t\tbRetractHouseDropDown = true;\n\t\t\t\tif (Special.IsCaptureTheFlag != pCheckListOptions->Is_Checked(3) && !Special.IsCaptureTheFlag) {\n\t\t\t\t\tpCheckListOptions->Check_Item(0, true);\n\t\t\t\t}\n\t\t\t\tif (Session.Options.Bases != pCheckListOptions->Is_Checked(0)) {\n\t\t\t\t\tSession.Options.Bases = pCheckListOptions->Is_Checked(0);\n\t\t\t\t\tif (Session.Options.Bases) {\n\t\t\t\t\t\tSession.Options.UnitCount = Fixed_To_Cardinal (\n\t\t\t\t\t\t\tSessionClass::CountMax[1] -\n\t\t\t\t\t\t\tSessionClass::CountMin[1],\n\t\t\t\t\t\t\tCardinal_To_Fixed(\n\t\t\t\t\t\t\t\tSessionClass::CountMax[0]-SessionClass::CountMin[0],\n\t\t\t\t\t\t\t\tSession.Options.UnitCount-SessionClass::CountMin[0])) +\n\t\t\t\t\t\t\tSessionClass::CountMin[1];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpCheckListOptions->Check_Item(3, false);\n\t\t\t\t\t\tSession.Options.UnitCount = Fixed_To_Cardinal (\n\t\t\t\t\t\t\tSessionClass::CountMax[0] -\n\t\t\t\t\t\t\tSessionClass::CountMin[0],\n\t\t\t\t\t\t\tCardinal_To_Fixed(\n\t\t\t\t\t\t\t\tSessionClass::CountMax[1]-SessionClass::CountMin[1],\n\t\t\t\t\t\t\t\tSession.Options.UnitCount - SessionClass::CountMin[1])) +\n\t\t\t\t\t\t\tSessionClass::CountMin[0];\n\t\t\t\t\t}\n\t\t\t\t\tpGaugeCount->Set_Maximum(\n\t\t\t\t\t\tSessionClass::CountMax[Session.Options.Bases] -\n\t\t\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\t\t\tpGaugeCount->Set_Value(Session.Options.UnitCount -\n\t\t\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\t\t}\n\t\t\t\tSession.Options.Tiberium = pCheckListOptions->Is_Checked(1);\n\t\t\t\tSpecial.IsTGrowth = Session.Options.Tiberium;\t\t\t//\tUgh. Use of \"Special\" global.\n\t\t\t\tRule.IsTGrowth = Session.Options.Tiberium;\n\t\t\t\tSpecial.IsTSpread = Session.Options.Tiberium;\t\t\t//\tUgh. Use of \"Special\" global.\n\t\t\t\tRule.IsTSpread = Session.Options.Tiberium;\n\n\t\t\t\tSession.Options.Goodies = pCheckListOptions->Is_Checked(2);\n\t\t\t\tSpecial.IsCaptureTheFlag = pCheckListOptions->Is_Checked(3);\t//\tUgh. Use of \"Special\" global.\n\t\t\t\tSpecial.IsShadowGrow = pCheckListOptions->Is_Checked(4);\t\t//\tUgh. Use of \"Special\" global.\n\n\t\t\t\tbSlowUnitBuildRate = pCheckListOptions->Is_Checked(5);\n\n\t\t\t\tbInformParamChange = true;\n\t\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\t\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_ACCEPTSTART | KN_BUTTON ):\t\t//\t'Accept' or 'Start Game' button.\n\t\t\t\tif( !bHost )\n\t\t\t\t{\n\t\t\t\t\t//\tGuest wishes to accept game params.\n\t\t\t\t\tUser* pUserHost = pWO->pGameHost();\n\t\t\t\t\tif( pUserHost )\t\t\t//\tElse it's too early to even be thinking about accepting, anyway.\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tSet ourself as accepted. We want to do this immediately so the user has feedback for pressing button.\n\t\t\t\t\t\t//\tBesides, the host is guaranteed to allow this and set us to \"accepted\", unless it is simultaneously\n\t\t\t\t\t\t//\tsending us a new update we haven't received yet. If this is the case, we will get that update in a\n\t\t\t\t\t\t//\tsecond and will set ourselves to unaccepted, which will match the unaccepted state on the server.\n\t\t\t\t\t\t//\tUpshot - We can ignore messages from the server telling us that we, ourself, accepted.\n\t\t\t\t\t\tif( pToolTipHitLast && pToolTipHitLast->bShowing )\n\t\t\t\t\t\t\tpToolTipHitLast->Unshow();\n\t\t\t\t\t\tpTextBtnAcceptStart->Disable();\n\t\t\t\t\t\tif( SetPlayerAccepted( pWO->szMyName, true ) )\t//\tElse we didn't find ourself in list!\n\t\t\t\t\t\t{\n//\t\t\t\t\t\t\tdebugprint( \"Sending accept.\\n\" );\n\t\t\t\t\t\t\t//\tTell host we accept.\n\t\t\t\t\t\t\tchar szSend[ 20 ];\n\t\t\t\t\t\t\tsprintf( szSend, \"%02u %06u\", WOL_GAMEOPT_REQACCEPT, nGuestLastParamID );\n\t\t\t\t\t\t\tpWO->SendGameOpt( szSend, pUserHost );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t//\tHost says start the game.\n\t\t\t\t\t//\tIf we have changes just made and not yet sent, don't say start, because we're about to send changes\n\t\t\t\t\t//\tthat will unaccept everyone.\n\t\t\t\t\tif( !bParamsUnfresh() )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tForce user to put the correct disk in before proceeding. (Not crucial, but can lead to ugly\n\t\t\t\t\t\t//\ttimeouts if the scenario has to be downloaded before game start.)\n\t\t\t\t\t\tif( !Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Official() ||\n\t\t\t\t\t\t\tForce_Scenario_Available( Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Filename() ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//\tGo into \"waiting to start\" mode, tell guests to, and wait for responses.\n\t\t\t\t\t\t\tbWaitingToStart = true;\n\t\t\t\t\t\t\ttimeWaitingToStartTimeout = ::timeGetTime() + 30000;\n\t\t\t\t\t\t\tnHostLastParamID++;\n\t\t\t\t\t\t\tInformAboutStart();\n\t\t\t\t\t\t\tWWMessageBox().Process( TXT_WOL_WAITINGTOSTART, TXT_NONE );\n\t\t\t\t\t\t\tBindControls( false );\n\t\t\t\t\t\t\tSetPlayerReadyToGo( pWO->szMyName, \"ready\" );\n\t\t\t\t\t\t\tSound_Effect( VOC_GAME_CLOSED );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_SCENARIO_RA | KN_BUTTON ):\n\t\t\t\tScenarioDisplayMode( SCENARIO_RA );\n\t\t\t\tbreak;\n\t\t\tcase ( BUTTON_SCENARIO_CS | KN_BUTTON ):\n\t\t\t\tScenarioDisplayMode( SCENARIO_CS );\n\t\t\t\tbreak;\n\t\t\tcase ( BUTTON_SCENARIO_AM | KN_BUTTON ):\n\t\t\t\tScenarioDisplayMode( SCENARIO_AM );\n\t\t\t\tbreak;\n\t\t\tcase ( BUTTON_SCENARIO_USER | KN_BUTTON ):\n\t\t\t\tScenarioDisplayMode( SCENARIO_USER );\n\t\t\t\tbreak;\n\n//\t\t\tcase (BUTTON_LOAD | KN_BUTTON):\n//\t\t\tcase (BUTTON_OK | KN_BUTTON):\n//\t\t\t\tbreak;\n\n\t\t\tcase (KN_ESC):\n\t\t\t\tif( pDropListHouse->IsDropped )\n\t\t\t\t\tbRetractHouseDropDown = true;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_LEAVE | KN_BUTTON ):\n\t\t\tcase ( BUTTON_CANCEL | KN_BUTTON ):\n\t\t\t\tif( ExitGameChannel() )\n\t\t\t\t{\n\t\t\t\t\tpWO->RejoinLobbyAfterGame();\n\t\t\t\t\tbProcess = false;\n\t\t\t\t\tResultReturn = RESULT_WOLGSUP_BACKTOCHAT;\t//\tReturn to chat.\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbProcess = false;\n\t\t\t\t\tResultReturn = RESULT_WOLGSUP_FATALERROR;\t//\tReturn with an error value.\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\tCall_Back();\n\t}\n\n\tif( pToolTipHitLast && pToolTipHitLast->bShowing )\n\t\tpToolTipHitLast->Unshow();\n\n\tpWO->ClearListPtrs();\n\tpWO->pGSupDlg = NULL;\n\n\treturn ResultReturn;\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::SetSpecialControlStates()\n{\n\t//\tSet gauges and checklist.\n\n\tpCheckListOptions->Check_Item(0, Session.Options.Bases);\n\tpCheckListOptions->Check_Item(1, Session.Options.Tiberium);\n\tpCheckListOptions->Check_Item(2, Session.Options.Goodies);\n\tpCheckListOptions->Check_Item(3, Special.IsCaptureTheFlag);\t\t//\tUgh. Use of \"Special\" global.\n\tpCheckListOptions->Check_Item(4, Special.IsShadowGrow);\t\t\t//\tUgh. Use of \"Special\" global.\n\n\tpCheckListOptions->Check_Item(5, bSlowUnitBuildRate);\t\t\t//\tUgh. Use of \"Special\" global.\n\n\tpGaugeCount->Set_Maximum(SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]);\n\tpGaugeCount->Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]);\n\n\tpGaugeLevel->Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1);\n\tpGaugeLevel->Set_Value(BuildLevel - 1);\n\n\tpGaugeCredits->Set_Maximum(Rule.MPMaxMoney);\n\tpGaugeCredits->Set_Value(Session.Options.Credits);\n\n\tif( pWO->GameInfoCurrent.bTournament )\n\t{\n\t\tpGaugeAIPlayers->Set_Maximum( 0 );\n\t}\n\telse\n\t{\n\t\t//\tNote dependency of AIPlayers on number of human players.\n\t//\tpGaugeAIPlayers->Set_Maximum(Rule.MaxPlayers-Session.Players.Count());\n\t\tpGaugeAIPlayers->Set_Maximum( Rule.MaxPlayers - pWO->GameInfoCurrent.iPlayerMax );\n\t}\n\tpGaugeAIPlayers->Set_Value(Session.Options.AIPlayers);\n\n\tif( bAftermathUnits )\n\t\tpCheckAftermathUnits->Turn_On();\n\telse\n\t\tpCheckAftermathUnits->Turn_Off();\n}\n\n#define DRAWTABDOWN\t\tTurn_On()\n#define DRAWTABUP\t\tTurn_Off()\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::BindControls( bool bBind )\n{\n\tif( bBind )\n\t{\n\t\tcommands = pWO->pShpBtnDiscon;\n\t\tpWO->pShpBtnLeave->Add_Tail(*commands);\n\t\tpWO->pShpBtnRefresh->Add_Tail(*commands);\n\t\tpWO->pShpBtnSquelch->Add_Tail(*commands);\n\t\tpWO->pShpBtnBan->Add_Tail(*commands);\n\t\tpWO->pShpBtnKick->Add_Tail(*commands);\n\t\tpWO->pShpBtnFindpage->Add_Tail(*commands);\n\t\tpWO->pShpBtnOptions->Add_Tail(*commands);\n\t\tpWO->pShpBtnLadder->Add_Tail(*commands);\n\t\tpWO->pShpBtnHelp->Add_Tail(*commands);\n\t\tpILPlayers->Add_Tail(*commands);\n\t\tif( bHost )\n\t\t{\n\t\t\t//\tDraw order of tabs depends on which one is selected, as we want them to overlap appropriately.\n\t\t\t//\tAlso, the selected tab must appear over the scenario list, while the unselected tabs are below it.\n\t\t\t//\tThis assures that that bottom of the tab overlaps the scenario list border, making it look connected.\n\n\t\t\t//\tajw I could make all maps always available now that they're downloadable. Playing CS map with AM rules\n\t\t\t//\twould mean switching CDs, though.\n\t\t\t//\tWould mean no difference between RA and CS games.\n\n\t\t\tswitch( ScenKindCurrent )\n\t\t\t{\n\t\t\tcase SCENARIO_RA:\n\t\t\t\tif( !pWO->GameInfoCurrent.bTournament )\n\t\t\t\t{\n\t\t\t\t\tpShpBtnScenarioUser->Add_Tail(*commands);\n\t\t\t\t\tpShpBtnScenarioUser->DRAWTABDOWN;\n\t\t\t\t}\n\t\t\t\tif( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::CSGAME )\n\t\t\t\t{\n\t\t\t\t\tpShpBtnScenarioCS->Add_Tail(*commands);\n\t\t\t\t\tpShpBtnScenarioCS->DRAWTABDOWN;\n\t\t\t\t}\n\t\t\t\telse if( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::AMGAME ||\n\t\t\t\t\t\t( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::RAGAME && Is_Aftermath_Installed() && !pWO->GameInfoCurrent.bTournament )\t)\n\t\t\t\t{\n\t\t\t\t\tpShpBtnScenarioAM->Add_Tail(*commands);\n\t\t\t\t\tpShpBtnScenarioAM->DRAWTABDOWN;\n\t\t\t\t}\n\t\t\t\tpILScens->Add_Tail(*commands);\n\t\t\t\tpShpBtnScenarioRA->Add_Tail(*commands);\n\t\t\t\tpShpBtnScenarioRA->DRAWTABUP;\n\t\t\t\tbreak;\n\t\t\tcase SCENARIO_CS:\t\t//\tpWO->GameInfoCurrent.GameKind must be CREATEGAMEINFO::CSGAME.\n\t\t\t\tif( !pWO->GameInfoCurrent.bTournament )\n\t\t\t\t{\n\t\t\t\t\tpShpBtnScenarioUser->Add_Tail(*commands);\n\t\t\t\t\tpShpBtnScenarioUser->DRAWTABDOWN;\n\t\t\t\t}\n\t\t\t\tpShpBtnScenarioRA->Add_Tail(*commands);\n\t\t\t\tpShpBtnScenarioRA->DRAWTABDOWN;\n\t\t\t\tpILScens->Add_Tail(*commands);\n\t\t\t\tpShpBtnScenarioCS->Add_Tail(*commands);\n\t\t\t\tpShpBtnScenarioCS->DRAWTABUP;\n\t\t\t\tbreak;\n\t\t\tcase SCENARIO_AM:\t\t//\tpWO->GameInfoCurrent.GameKind must be CREATEGAMEINFO::AMGAME, or RAGAME with AM installed.\n\t\t\t\tif( !pWO->GameInfoCurrent.bTournament )\n\t\t\t\t{\n\t\t\t\t\tpShpBtnScenarioUser->Add_Tail(*commands);\n\t\t\t\t\tpShpBtnScenarioUser->DRAWTABDOWN;\n\t\t\t\t}\n\t\t\t\tpShpBtnScenarioRA->Add_Tail(*commands);\n\t\t\t\tpShpBtnScenarioRA->DRAWTABDOWN;\n\t\t\t\tpILScens->Add_Tail(*commands);\n\t\t\t\tpShpBtnScenarioAM->Add_Tail(*commands);\n\t\t\t\tpShpBtnScenarioAM->DRAWTABUP;\n\t\t\t\tbreak;\n\t\t\tcase SCENARIO_USER:\t\t//\tpWO->GameInfoCurrent.bTournament must be false.\n\t\t\t\tpShpBtnScenarioRA->Add_Tail(*commands);\n\t\t\t\tpShpBtnScenarioRA->DRAWTABDOWN;\n\t\t\t\tif( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::CSGAME )\n\t\t\t\t{\n\t\t\t\t\tpShpBtnScenarioCS->Add_Tail(*commands);\n\t\t\t\t\tpShpBtnScenarioCS->DRAWTABDOWN;\n\t\t\t\t}\n\t\t\t\telse if( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::AMGAME ||\n\t\t\t\t\t\t( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::RAGAME && Is_Aftermath_Installed() && !pWO->GameInfoCurrent.bTournament ) )\n\t\t\t\t{\n\t\t\t\t\tpShpBtnScenarioAM->Add_Tail(*commands);\n\t\t\t\t\tpShpBtnScenarioAM->DRAWTABDOWN;\n\t\t\t\t}\n\t\t\t\tpILScens->Add_Tail(*commands);\n\t\t\t\tpShpBtnScenarioUser->Add_Tail(*commands);\n\t\t\t\tpShpBtnScenarioUser->DRAWTABUP;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n//\t\tpStaticDescrip->Add_Tail(*commands);\n\t\tpEditSend->Add_Tail(*commands);\n\t\tpStaticUnit->Add_Tail(*commands);\n\t\tpStaticLevel->Add_Tail(*commands);\n\t\tpStaticCredits->Add_Tail(*commands);\n\t\tpStaticAIPlayers->Add_Tail(*commands);\n\t\tpGaugeCount->Add_Tail(*commands);\n\t\tpGaugeCredits->Add_Tail(*commands);\n\t\tpGaugeAIPlayers->Add_Tail(*commands);\n\t\tpGaugeLevel->Add_Tail(*commands);\n\t\tpCheckListOptions->Add_Tail(*commands);\n\t\tpTextBtnCancel->Add_Tail(*commands);\n\t\tpTextBtnAcceptStart->Add_Tail(*commands);\n\t\tpTextBtnAction->Add_Tail(*commands);\n\t\tpILDisc->Add_Tail(*commands);\n\t\tpDropListHouse->Add_Tail(*commands);\n//\t\tpCheckAftermathUnits->Add_Tail(*commands);\n\t}\n\telse\n\t{\n\t\tpWO->pShpBtnDiscon->Zap();\n\t\tpWO->pShpBtnLeave->Zap();\n\t\tpWO->pShpBtnRefresh->Zap();\n\t\tpWO->pShpBtnSquelch->Zap();\n\t\tpWO->pShpBtnBan->Zap();\n\t\tpWO->pShpBtnKick->Zap();\n\t\tpWO->pShpBtnFindpage->Zap();\n\t\tpWO->pShpBtnOptions->Zap();\n\t\tpWO->pShpBtnLadder->Zap();\n\t\tpWO->pShpBtnHelp->Zap();\n\t\tpILPlayers->Zap();\n\t\tif( bHost )\n\t\t{\n\t\t\tpShpBtnScenarioRA->Zap();\n\t\t\tif( !pWO->GameInfoCurrent.bTournament )\n\t\t\t{\n\t\t\t\tpShpBtnScenarioUser->Zap();\n\t\t\t}\n\t\t\tif( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::CSGAME )\n\t\t\t\tpShpBtnScenarioCS->Zap();\n\t\t\telse if( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::AMGAME ||\n\t\t\t\t\t( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::RAGAME && Is_Aftermath_Installed() && !pWO->GameInfoCurrent.bTournament ) )\n\t\t\t\tpShpBtnScenarioAM->Zap();\n\t\t\tpILScens->Zap();\n\t\t}\n//\t\tpStaticDescrip->Zap();\n\t\tpEditSend->Zap();\n\t\tpStaticUnit->Zap();\n\t\tpStaticLevel->Zap();\n\t\tpStaticCredits->Zap();\n\t\tpStaticAIPlayers->Zap();\n\t\tpGaugeCount->Zap();\n\t\tpGaugeCredits->Zap();\n\t\tpGaugeAIPlayers->Zap();\n\t\tpGaugeLevel->Zap();\n\t\tpCheckListOptions->Zap();\n\t\tpTextBtnCancel->Zap();\n\t\tpTextBtnAcceptStart->Zap();\n\t\tpTextBtnAction->Zap();\n\t\tpILDisc->Zap();\n\t\tpDropListHouse->Zap();\n//\t\tpCheckAftermathUnits->Zap();\n\t}\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::ScenarioDisplayMode( SCENARIO_GAMEKIND ScenKind )\n{\n//\tdebugprint( \"ScenarioDisplayMode, from %i going into %i mode.\\n\", ScenKindCurrent, ScenKind );\n\n\t//\tPuts us into mode where we are viewing a particular gamekind of scenario list.\n\tif( ScenKindCurrent == ScenKind )\n\t\treturn;\n\n\t//\tReorder tab buttons.\n\tBindControls( false );\n\tScenKindCurrent = ScenKind;\n\tBindControls( true );\n\n\t//\tReset list items.\n\tpILScens->Clear();\n//\tdebugprint( \"  *  *  *  *  *  *  ScenKind %i has %i items.\\n\", ScenKind, ar_szScenarios[ ScenKind ].Count() );\n\t//\tCheck for the currently selected scenario.\n\tbool bFoundCurrentSelection = false;\n\tint iSelect;\n\tfor( int i = 0; i != ar_szScenarios[ ScenKind ].Count(); i++ )\n\t{\n\t\t//\tPut ScenarioIndex in as extradata to list item.\n\t\tint iScenIndex = (int)ar_szScenIndexes[ ScenKind ][ i ];\n\t\tint iIndexNew = pILScens->Add_Item( ar_szScenarios[ ScenKind ][ i ], NULL, NULL, ICON_DIB, NULL, (void*)iScenIndex );\n\t\tif( iScenIndex == Session.Options.ScenarioIndex && !bFoundCurrentSelection )\n\t\t{\n\t\t\t//\t(Choose first line of what can be multiline description of currently selected scenario.)\n\t\t\tbFoundCurrentSelection = true;\n\t\t\tiSelect = i;\n\t\t}\n\t}\n\t//\tIf the current scenario selection is in this list, enable the list to show the selection, otherwise,\n\t//\tmake the listclass selection invisible, because it doesn't indicate the real scenario selection.\n\t//\tBasically, problem is that I can't have no selection in ListClass, and I don't want to risk changing\n\t//\tit as I'll affect the rest of the code. So I do this horrible hack.\n\tif( bFoundCurrentSelection )\n\t{\n\t\tpILScens->SetSelectType( 1 );\t\t//\tRegular selection.\n\t\tpILScens->Set_Selected_Index( iSelect );\n\t}\n\telse\n\t\tpILScens->SetSelectType( 0 );\t\t//\tInvisible selection.\n\n//\tdisplay = REDRAW_ALL;\n\tpILScens->Flag_To_Redraw();\n\tpShpBtnScenarioRA->Flag_To_Redraw();\n\tpShpBtnScenarioCS->Flag_To_Redraw();\n\tpShpBtnScenarioAM->Flag_To_Redraw();\n\tpShpBtnScenarioUser->Flag_To_Redraw();\n}\n\n//***********************************************************************************************\nbool WOL_GameSetupDialog::ExitGameChannel()\n{\n//\tdebugprint( \"ExitGameChannel \\n\" );\n\tif( pDropListHouse->IsDropped )\n\t{\n\t\tpDropListHouse->Collapse();\n\t\tif (display < REDRAW_BACKGROUND) display = REDRAW_BACKGROUND;\n\t}\n\tif( !pWO->ChannelLeave() )\n\t{\n\t\tpWO->GenericErrorMessage();\n\t\treturn false;\n\t}\n\n\tpWO->OnExitingGameChannel();\n\n\treturn true;\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::DrawScenarioDescripIcon( const char* pDIB ) const\n{\n\tCC_Draw_DIB( pDIB, d_gamekind_x - 16, d_gamekind_y - 2, 100, WINDOW_MAIN );\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::SetPlayerColor( const char* szName, PlayerColorType Color )\n{\n\t//\tSets player color - does not verify if it is \"okay\" to do so.\n//\tdebugprint( \"SetPlayerColor %s to %i\\n\", szName, Color );\n\n\tint iItem = pILPlayers->Find( szName );\n\tif( iItem == -1 )\n\t{\n\t\t//\tPlayer name was not found in list.\n\t\t//\tThis can happen when player color Informs arrive from the host before I have gotten a userlist.\n\t\t//\tInsert an entry for user - color will be maintained when the userlist arrives.\n\t\t//\t\"early insertion\"\n//\t\tdebugprint( \"SetPlayerColor could not find name '%s'! Inserting...\\n\", szName );\n\t\tiItem = pILPlayers->Add_Item( szName );\n\t}\n\n\tif( strcmp( pWO->szMyName, szName ) == 0 )\n\t{\n\t\t//\tI am the player involved.\n\t\tSession.ColorIdx = Color;\n\t\tif( display < REDRAW_COLORS ) display = REDRAW_COLORS;\n\t}\n\tpILPlayers->Set_Item_Color( iItem, &ColorRemaps[ Color == PCOLOR_DIALOG_BLUE ? PCOLOR_REALLY_BLUE : Color ] );\n\tpILPlayers->Flag_To_Redraw();\n\n}\n\n//***********************************************************************************************\nPlayerColorType WOL_GameSetupDialog::GetPlayerColor( const char* szName )\n{\n\t//\tReturns player color, if player is found in list, else PCOLOR_NONE.\n\tint iItem = pILPlayers->Find( szName );\n\tif( iItem == -1 )\n\t{\n\t\t//\tPlayer name was not found in list.\n\t\treturn PCOLOR_NONE;\n\t}\n\tRemapControlType* pRemap = pILPlayers->Get_Item_Color( iItem );\n\treturn PlayerColorTypeOf( pRemap );\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::SetPlayerHouse( const char* szName, HousesType House )\n{\n\t//\tSets player house - does not verify if it is \"okay\" to do so.\n//\tdebugprint( \"SetPlayerHouse %s to %i\\n\", szName, House );\n\n\tint iItem = pILPlayers->Find( szName );\n\tif( iItem == -1 )\n\t{\n\t\t//\tPlayer name was not found in list.\n\t\t//\tThis can happen when player house Informs arrive from the host before I have gotten a userlist.\n\t\t//\tInsert an entry for user - house will be maintained when the userlist arrives.\n\t\t//\t\"early insertion\"\n//\t\tdebugprint( \"SetPlayerHouse could not find name '%s'! Inserting...\\n\", szName );\n\t\tiItem = pILPlayers->Add_Item( szName );\n\t}\n\n\t//\tReset item text.\n\tchar szItem[ 100 ];\n\tpWO->WritePlayerListItem( szItem, szName, House );\n//\tdebugprint ( \"%i, %s\\n\", iItem, szItem );\n\tpILPlayers->Set_Item( iItem, szItem );\n\tpILPlayers->Flag_To_Redraw();\n}\n\n//***********************************************************************************************\nHousesType WOL_GameSetupDialog::GetPlayerHouse( const char* szName )\n{\n\t//\tReturns player house for user if found in list, else HOUSE_NONE.\n\tint iItem = pILPlayers->Find( szName );\n\tif( iItem == -1 )\n\t{\n\t\t//\tPlayer name was not found in list.\n\t\treturn HOUSE_NONE;\n\t}\n\n\treturn pWO->PullPlayerHouse_From( pILPlayers->Get_Item( iItem ) );\n}\n\n//***********************************************************************************************\nbool WOL_GameSetupDialog::SetPlayerAccepted( const char* szName, bool bAccepted )\n{\n\t//\tSets player's 'accepted' state to true or false.\n\t//\tValue is stored in the player list: if there is an accepted icon, player has accepted.\n\tint iItem = pILPlayers->Find( szName );\n\tif( iItem == -1 )\n\t{\n\t\t//\tPlayer name was not found in list.\n//\t\tdebugprint( \"SetPlayerAccepted() - could not find '%s'.\\n\", szName );\n\t\treturn false;\n\t}\n//\tdebugprint( \"SetPlayerAccepted() - set '%s' to %s.\\n\", szName, bAccepted ? \"accepted\" : \"NOT accepted\" );\n\treturn pWO->MarkItemAccepted( iItem, bAccepted );\n}\n\n//***********************************************************************************************\nbool WOL_GameSetupDialog::IveAccepted()\n{\n\t//\tReturns true if I am marked as \"accepted\".\n\tint iItem = pILPlayers->Find( pWO->szMyName );\n\tif( iItem == -1 )\n\t\treturn false;\n\treturn pWO->bItemMarkedAccepted( iItem );\n}\n\n//***********************************************************************************************\nbool WOL_GameSetupDialog::SetPlayerReadyToGo( const char* szName, const char* szReadyState )\n{\n\t//\tSets player's 'ready to go' state.\n\t//\tSet szReadyState to \"ready\", \"need scenario\", or NULL.\n\t//\tFirst two cases are regarded as player being ready to go.\n\t//\tValue is stored in the player list in the hidden string field.\n\tint iItem = pILPlayers->Find( szName );\n\tif( iItem == -1 )\n\t{\n\t\t//\tPlayer name was not found in list.\n//\t\tdebugprint( \"SetPlayerReadyToGo() - could not find '%s'.\\n\", szName );\n\t\treturn false;\n\t}\n//\tdebugprint( \"SetPlayerReadyToGo() - set '%s' to %s.\\n\", szName, szReadyState );\n\tpWO->MarkItemReadyToGo( iItem, szReadyState );\n\n\treturn true;\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::ResetReadyToGo()\n{\n\t//\tResets all users to \"not ready to go\".\n\tfor( int i = 0; i < pILPlayers->Count(); i++ )\n\t{\n\t\tpWO->MarkItemReadyToGo( i, NULL );\n\t}\n}\n\n//***********************************************************************************************\nbool WOL_GameSetupDialog::bPlayerReadyToGo( const char* szName )\n{\n\t//\tReturns true if player is marked as \"ready to go\".\n\tint iItem = pILPlayers->Find( szName );\n\tif( iItem == -1 )\n\t\treturn false;\n\treturn pWO->bItemMarkedReadyToGo( iItem );\n}\n\n//***********************************************************************************************\nbool WOL_GameSetupDialog::bAllPlayersReadyToGo()\n{\n\t//\tReturns true if all players are marked as \"ready to go\".\n//\tdebugprint( \"Checking for all players ready - there are %i\\n\", pILPlayers->Count() );\n\tfor( int i = 0; i < pILPlayers->Count(); i++ )\n\t{\n\t\tif( !pWO->bItemMarkedReadyToGo( i ) )\n\t\t{\n//\t\t\tdebugprint( \"Item %i NOT ready\\n\", i );\n\t\t\treturn false;\n\t\t}\n//\t\tdebugprint( \"Item %i is ready\\n\", i );\n\t}\n//\tdebugprint( \"Return true\\n\" );\n\treturn true;\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::ProcessGuestRequest( User* pUser, const char* szRequest )\n{\n\t//\tGame host processes a request that arrived as a privategameopt from one of the guests.\n\t//\tWOL_GAMEOPT_REQCOLOR format:\n\t//\t2\t\tWOL_GAMEOPT\n\t//\t1\t\tspace\n\t//\t2\t\tcolor\n\t//\t1\t\tnull-terminator\n//\tdebugprint( \"ProcessGuestRequest. szRequest is '%s', len %i.\\n\", szRequest, strlen( szRequest ) );\n\tWOL_GAMEOPT opt = (WOL_GAMEOPT)atoi( szRequest );\n\tszRequest += 3;\n\n\tswitch( opt )\n\t{\n\tcase WOL_GAMEOPT_REQCOLOR:\n\t{\n\t\tPlayerColorType ColorDesired = (PlayerColorType)( atoi( szRequest ) );\n\t\tif( pILPlayers->FindColor( &ColorRemaps[ ColorDesired == PCOLOR_DIALOG_BLUE ? PCOLOR_REALLY_BLUE : ColorDesired ] ) == -1 )\n\t\t{\n\t\t\t//\tColor is available.\n\t\t\tSetPlayerColor( (char*)pUser->name, ColorDesired );\n\t\t\t//\tTell all guests about the color change.\n\t\t\tInformAboutPlayerColor( (char*)pUser->name, ColorDesired, NULL );\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//\tColor is not available.\n//\t\t\tdebugprint( \"Color %i denied to %s\\n\", ColorDesired, (char*)pUser->name );\n\t\t\t//\tTell requestor that his color is still the same.\n\t\t\tRemapControlType* pColorRemapCurrent = pILPlayers->Get_Item_Color( pILPlayers->Find( (char*)pUser->name ) );\n\t\t\tInformAboutPlayerColor( (char*)pUser->name, PlayerColorTypeOf( pColorRemapCurrent ), pUser );\n\t\t}\n\t\tbreak;\n\t}\n\tcase WOL_GAMEOPT_REQHOUSE:\n\t{\n\t\tHousesType HouseChoice = (HousesType)( atoi( szRequest ) );\n//\t\tdebugprint( \"Host received: '%s' changed house to %u.\\n\", (char*)pUser->name, HouseChoice );\n\t\tSetPlayerHouse( (char*)pUser->name, HouseChoice );\n\t\tnHostLastParamID++;\n\t\tInformAboutPlayerHouse( (char*)pUser->name, HouseChoice, NULL );\n\t\tClearAllAccepts();\n\t\tbreak;\n\t}\n\tcase WOL_GAMEOPT_REQACCEPT:\n\t\t//\tDoes Param ID of accept request match the last param change ID sent? See notes at top.\n\t\tif( atoi( szRequest ) == nHostLastParamID )\n\t\t{\n//\t\t\tdebugprint( \"Host received valid accept from '%s'.\\n\", (char*)pUser->name );\n\t\t\tSetPlayerAccepted( (char*)pUser->name, true );\n\t\t\tInformAboutPlayerAccept( (char*)pUser->name, NULL );\n\t\t\t//\tWe may be ready to start a game now.\n\t\t\tif( bAllGuestsAccept() )\n\t\t\t{\n\t\t\t\tif( pToolTipHitLast && pToolTipHitLast->bShowing )\n\t\t\t\t\tpToolTipHitLast->Unshow();\n\t\t\t\tpTextBtnAcceptStart->Enable();\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n//\t\t\tdebugprint( \"______________Host received invalid accept from '%s'. ID = %i when it should be %i.\\n\", (char*)pUser->name,\n//\t\t\t\tatoi( szRequest ), nHostLastParamID );\n\t\t}\n\t\tbreak;\n\tcase WOL_GAMEOPT_REQSTART:\n\t\t//\tDoes Param ID of accept request match the last param change ID sent? See notes at top.\n\t\tif( atoi( szRequest ) == nHostLastParamID )\t\t//\tOtherwise ignore - it's old and we don't care. (Incredibly unlikely to happen, actually.)\n\t\t{\n//\t\t\tdebugprint( \"Host received valid WOL_GAMEOPT_REQSTART from '%s'.\\n\", (char*)pUser->name );\n//\t\t\tWOL_PrintMessage( *pILDisc, \"WOL_GAMEOPT_REQSTART response\", WOLCOLORREMAP_LOCALMACHINEMESS );\n//\t\t\tWOL_PrintMessage( *pILDisc, (char*)pUser->name, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\tif( bWaitingToStart )\n\t\t\t\t//\tIf all responses are in, start the game!\n\t\t\t\tGuestIsReadyToPlay( (char*)pUser->name, \"ready\" );\n//\t\t\telse\n//\t\t\t\tdebugprint( \"Ignoring - I am no longer waiting to start a game.\\n\" );\n\t\t}\n\t\tbreak;\n\tcase WOL_GAMEOPT_REQSTART_BUTNEEDSCENARIO:\n\t\t//\tDoes Param ID of accept request match the last param change ID sent? See notes at top.\n\t\tif( atoi( szRequest ) == nHostLastParamID )\t\t//\tOtherwise ignore - it's old and we don't care. (Incredibly unlikely to happen, actually.)\n\t\t{\n//\t\t\tdebugprint( \"Host received valid WOL_GAMEOPT_REQSTART_BUTNEEDSCENARIO from '%s'.\\n\", (char*)pUser->name );\n\t\t\tif( bWaitingToStart )\n\t\t\t\t//\tIf all responses are in, start the game!\n\t\t\t\tGuestIsReadyToPlay( (char*)pUser->name, \"need scenario\" );\n//\t\t\telse\n//\t\t\t\tdebugprint( \"Ignoring - I am no longer waiting to start a game.\\n\" );\n\t\t}\n\t\tbreak;\n\tcase WOL_GAMEOPT_INFGO:\n\t\t//\tI have told myself to start game right now.\n\t\t//\tThis is the new method. Avoids apparent \"private messages/gameopts are getting delayed\" problem in chatserver...\n\t\t//\t(I don't want to end up leaving the channel before guests get my go message.)\n\t\tstrcpy( szTriggerGameStartInfo, szRequest );\n\t\tbreak;\n\tdefault:\n//\t\tdebugprint( \"Unhandled value of %i in ProcessGuestRequest!!!\\n\", opt );\n\t\tbreak;\n\t}\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::ProcessInform( char* szInform )\n{\n\t//\tProcess inform message arriving from game host.\n//\tdebugprint( \"ProcessInform: '%s'\\n\", szInform );\n\tif( !bHost )\n\t{\n\t\tWOL_GAMEOPT opt = (WOL_GAMEOPT)atoi( szInform );\n\t\tszInform += 3;\n\t\tswitch( opt )\n\t\t{\n\t\tcase WOL_GAMEOPT_INFCOLOR:\n\t\t{\n\t\t\t//\tWOL_GAMEOPT_INFCOLOR format:\n\t\t\t//\t2\t\tWOL_GAMEOPT\n\t\t\t//\t1\t\tspace\n\t\t\t//\t2\t\tcolor\n\t\t\t//\t1\t\tspace\n\t\t\t//\tstring\tname of player\n\t\t\tPlayerColorType Color = (PlayerColorType)( atoi( szInform ) );\n\t\t\tszInform += 3;\n\t\t\tSetPlayerColor( szInform, Color );\t\t//\t(szInform is now sitting at the start of the name string.)\n\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t\tbreak;\n\t\t}\n\t\tcase WOL_GAMEOPT_INFHOUSE:\t\t//\tNote: In theory, I could ignore this if it refers to me. I've already set my own house.\n\t\t{\n\t\t\tnGuestLastParamID = atoi( szInform );\n\t\t\tszInform += 7;\n\t\t\tHousesType House = (HousesType)( atoi( szInform ) );\n\t\t\tszInform += 3;\n\t\t\tSetPlayerHouse( szInform, House );\t\t//\t(szInform is now sitting at the start of the name string.)\n\t\t\tClearAllAccepts();\n\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t\tbreak;\n\t\t}\n\t\tcase WOL_GAMEOPT_INFACCEPT:\t\t//\tNote: In theory, I could ignore this if it refers to me.\n\t\t\t//\tA guest has accepted.\n\t\t\tSetPlayerAccepted( szInform, true );\t\t//\t(szInform is now sitting at the start of the name string.)\n\t\t\tbreak;\n\t\tcase WOL_GAMEOPT_INFPARAMS:\n\t\t\t//\tGame params have changed.\n\t\t\tbParamsReceived = true;\n\t\t\tif( !AcceptParams( szInform ) )\n\t\t\t\tbLeaveDueToRulesMismatchTrigger = true;\n\t\t\tSetSpecialControlStates();\n\t\t\t//pILScens->Set_Selected_Index( Session.Options.ScenarioIndex );\n\t\t\tdisplay = REDRAW_ALL;\n\t\t\tClearAllAccepts();\n\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t\tbreak;\n\t\tcase WOL_GAMEOPT_INFNEWGUESTPLAYERINFO:\n\t\t\t//\tI have just joined and have received a message with info on all players in game.\n\t\t\tAcceptNewGuestPlayerInfo( szInform );\n\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t\tbreak;\n\t\tcase WOL_GAMEOPT_INFSTART:\n\t\t{\n\t\t\t//\tHost tells us to wait for start of game.\n//\t\t\tdebugprint( \"Guest received WOL_GAMEOPT_INFSTART.\\n\" );\n\t\t\tnGuestLastParamID = atoi( szInform );\n//\tThe following check is not necessary. Rules.ini, if manually replaced by a cheater, is not reloaded.\n//\tSo prior checks (that occur on game params receives) are sufficient.\n//\t\t\tszInform += 7;\n//\t\t\t//\tCheck rules.ini compatibility.\n//\t\t\tint iRulesID = atoi( szInform );\n//\t\t\tif( RuleINI.Get_Unique_ID() != iRulesID )\n//\t\t\t{\n//\t\t\t\t//\tRules.ini incompatible. Don't respond to call for start.\n//\t\t\t\tbLeaveDueToRulesMismatchTrigger = true;\n//\t\t\t\tbreak;\n//\t\t\t}\n\t\t\tUser* pUserHost = pWO->pGameHost();\n\t\t\tif( pUserHost )\t\t//\tThis better'd be true.\n\t\t\t{\n\t\t\t\t//\tSend ack back to host.\n\t\t\t\tchar szSend[ 20 ];\n\t\t\t\t//\tMake sure we have the scenario.\n\t\t\t\tif( !bNeedScenarioDownload() )\n\t\t\t\t\tsprintf( szSend, \"%02u %06u\", WOL_GAMEOPT_REQSTART, nGuestLastParamID );\n\t\t\t\telse\n\t\t\t\t\tsprintf( szSend, \"%02u %06u\", WOL_GAMEOPT_REQSTART_BUTNEEDSCENARIO, nGuestLastParamID );\n\t\t\t\tpWO->SendGameOpt( szSend, pUserHost );\n\t\t\t\t//\tEnter waiting mode.\n\t\t\t\tbWaitingToStart = true;\n\t\t\t\tWWMessageBox().Process( TXT_WOL_WAITINGTOSTART, TXT_NONE );\n\t\t\t\tBindControls( false );\n\t\t\t\t//\tIf we are in a modal dialog, we must have arrived here through Call_Back()'s PumpMessages.\n\t\t\t\t//\tSet global that will force edit dialogs to stop accepting characters.\n\t\t\t\t//\tThis is to fix a minor glitch: guests can keep typing into a \"page\" dialog editbox after the\n\t\t\t\t//\t\"Launching game...\" message has appeared on top of it.\n\t\t\t\tif( pWO->bPump_In_Call_Back )\n\t\t\t\t\tdisable_current_msgbox = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n//\t\t\t\tdebugprint( \"Impossible arose on WOL_GAMEOPT_INFSTART.\\n\" );\n\t\t\t\tFatal( \"Impossible arose on WOL_GAMEOPT_INFSTART.\\n\" );\n\t\t\t}\n\t\t\tSound_Effect( VOC_GAME_CLOSED );\n\t\t\tbreak;\n\t\t}\n\t\tcase WOL_GAMEOPT_INFCANCELSTART:\n\t\t\t//\tHost tells us to cancel waiting for start of game.\n\t\t\tbWaitingToStart = false;\n\t\t\tClearAllAccepts();\n\t\t\tBindControls( true );\n\t\t\tWOL_PrintMessage( *pILDisc, TXT_WOL_STARTCANCELLED, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\tSound_Effect( VOC_SYS_ERROR );\n\t\t\tdisplay = REDRAW_ALL;\n\t\t\t//\tIf we are in a modal dialog, we must have arrived here through Call_Back()'s PumpMessages. Set global that will\n\t\t\t//\tforce a cancel out of the dialog.\n\t\t\tif( pWO->bPump_In_Call_Back )\n\t\t\t\tcancel_current_msgbox = true;\n\t\t\tbreak;\n\t\tcase WOL_GAMEOPT_INFGO:\n\t\t\t//\tHost says start game right now.\n\t\t\tstrcpy( szTriggerGameStartInfo, szInform );\n\t\t\t//\tIf we are in a modal dialog, we must have arrived here through Call_Back()'s PumpMessages. Set global that will\n\t\t\t//\tforce a cancel out of the dialog.\n\t\t\tif( pWO->bPump_In_Call_Back )\n\t\t\t\tcancel_current_msgbox = true;\n\t\t\tbreak;\n\t\tdefault:\n//\t\t\tdebugprint( \"Unhandled value of %i in ProcessInform!!!\\n\", opt );\n\t\t\t//WOL_PrintMessage( *pILDisc, \"Error - Unhandled value in ProcessInform!!!\", WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\tFatal( \"Error - Unhandled value in ProcessInform!\" );\n\t\t\tbreak;\n\t\t}\n\t}\n//\tdebugprint( \"* END of ProcessInform: '%s'\\n\", szInform );\n}\n\n//***********************************************************************************************\nbool WOL_GameSetupDialog::bParamsUnfresh()\n{\n\t//\tReturns true if game setup parameters do not match what they were last time they were sent.\n\tGAMEPARAMS GParamsNow;\n\tSetGParamsToCurrent( GParamsNow );\n\n//\tif( !( GParamsNow == GParamsLastSent ) )\n//\t{\n//\t\tdebugprint( \"---- Params Unfresh: OLD...\\n\" );\n//\t\tDebug_GlobalPacketType( GParamsLastSent.GPacket );\n//\t\tdebugprint( \"-------------------  NEW...\\n\" );\n//\t\tDebug_GlobalPacketType( GParamsNow.GPacket );\n//\t\tdebugprint( \"old bAftermathUnits = %i\\n\", GParamsLastSent.bAftermathUnits );\n//\t\tdebugprint( \"new bAftermathUnits = %i\\n\", GParamsNow.bAftermathUnits );\n//\t}\n\n\treturn !( GParamsNow == GParamsLastSent );\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::SendParams()\n{\n\t//\tHost only.\n\n\tSetGParamsToCurrent( GParamsLastSent );\n\n\tchar szSend[ 130 + DESCRIP_MAX + 12 + 32 + 100 ];\n\tsprintf( szSend,\n\t\t\"%01u \"\n\t\t\"%06u \"\n\t\t\"%03u \"\n\t\t\"%s \"\n\t\t\"%u \"\n\t\t\"%s \"\n\t\t\"%01u \"\n\t\t\"%.32s \"\t//\tNo null-terminator on digest. There may be nothing at all inserted here.\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t\"%u \"\n\t\t,\n\t\tWOL_GAMEOPT_INFPARAMS,\n\t\tnHostLastParamID,\n\t\tstrlen( GParamsLastSent.GPacket.ScenarioInfo.Scenario ),\n\t\tGParamsLastSent.GPacket.ScenarioInfo.Scenario,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.FileLength,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.ShortFileName,\n//\t\tstrlen( (char*)GParamsLastSent.GPacket.ScenarioInfo.FileDigest ),\t\tnot null-terminated!\n\t\tGParamsLastSent.GPacket.ScenarioInfo.FileDigest[0] ? 1 : 0,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.FileDigest,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.OfficialScenario,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.Credits,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.IsBases,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.IsTiberium,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.IsGoodies,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.BuildLevel,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.UnitCount,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.AIPlayers,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.Seed,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.Special.IsShadowGrow,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.Special.IsSpeedBuild,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.Special.IsFromInstall,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.Special.IsCaptureTheFlag,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.Special.IsInert,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.Special.IsThreePoint,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.Special.IsTGrowth,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.Special.IsTSpread,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.GameSpeed,\n\t\tGParamsLastSent.GPacket.ScenarioInfo.Version,\n\t\tGParamsLastSent.bAftermathUnits,\t\t\t//\tNot currently used.\n\t\tGParamsLastSent.bSlowUnitBuildRate,\n\t\tRuleINI.Get_Unique_ID()\t\t//\tUsed to verify rules.ini files match.\n\t\t);\n\n\tpWO->SendGameOpt( szSend, NULL );\n}\n\n//***********************************************************************************************\nbool WOL_GameSetupDialog::AcceptParams( char* szParams )\n{\n\t//\tReverse of SendParams() process. szParams has already been stripped of 2 bytes header. Guest only.\n\n\t//\tReturns false if rules.ini doesn't match that of the host.\n\t//\t(Or if an error occurs due to the packet being incorrect - which happened once in test...)\n\n\tchar szDelimiter[] = \" \";\n\tchar* szToken;\n\tchar* szRemaining;\n\n\tszToken = strtok( szParams, szDelimiter );\n\tnGuestLastParamID = atoi( szToken );\n\n\t//\tRead in length of following string.\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tint iLen = atoi( szToken );\n\t//\tSet string pointer to start of string (length is 3 digits).\n\tszRemaining = szToken + 4;\n\t//\tRead in string.\n\tmemcpy( Session.Options.ScenarioDescription, szRemaining, iLen );\n\t//\tNull-terminate.\n\tSession.Options.ScenarioDescription[ iLen ] = 0;\n\t//\tAdvance string pointer to next param.\n\tszRemaining += iLen + 1;\n\n//debugprint( \"scenario description is '%s'\\n\", Session.Options.ScenarioDescription );\n//debugprint( \"remaining: '%s'\\n\", szRemaining );\n\n\tszToken = strtok( szRemaining, szDelimiter );\n\tif( !szToken )\treturn false;\n\tSession.ScenarioFileLength = atoi( szToken );\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tstrcpy( Session.ScenarioFileName, szToken );\n\n//\t//\tRead in length of following string.\n//\tszToken = strtok( NULL, szDelimiter );\n//\tiLen = atoi( szToken );\n//\t//\tSet string pointer to start of string (length is 3 digits).\n//\tszRemaining = szToken + 4;\n\t//\tMethod changed.\n\t//\tCheck if there is a digest.\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tiLen = atoi( szToken );\t\t//\t1 or 0, indicating if there is a digest following.\n\tif( iLen )\n\t{\n//\t\t//\tSet string pointer to start of string (previous field is 1 digit).\n//\t\tszRemaining = szToken + 2;\n//\t\tiLen = sizeof( Session.ScenarioDigest );\n//\t\t//\tRead in string.\n//\t\tmemcpy( Session.ScenarioDigest, szRemaining, iLen );\n//\t\t//\t//\tNull-terminate.\n//\t\t//\tSession.ScenarioDigest[ iLen ] = 0;\t\t\tDigest has no null-terminator!\n//\t\t//\tAdvance string pointer to next param.\n//\t\tszRemaining += iLen + 1;\n\t\t//\tThere is a digest.\n\t\tszToken = strtok( NULL, szDelimiter );\t\t\t//\t(Digests can't have spaces in the them.)\n//debugprint( \"digest: '%s'\\n\", szToken );\n\t\tif( !szToken )\treturn false;\n\t\tstrncpy( Session.ScenarioDigest, szToken, sizeof( Session.ScenarioDigest ) );\n\t}\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tSession.ScenarioIsOfficial = (bool)atoi( szToken );\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tSession.Options.Credits = atoi( szToken );\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tSession.Options.Bases = atoi( szToken );\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tSession.Options.Tiberium = atoi( szToken );\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tSession.Options.Goodies = atoi( szToken );\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tBuildLevel = atoi( szToken );\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tSession.Options.UnitCount = atoi( szToken );\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tSession.Options.AIPlayers = atoi( szToken );\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tSeed = atoi( szToken );\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tSpecial.IsShadowGrow = ( atoi( szToken ) == 0 ) ? 0 : 1;\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tSpecial.IsSpeedBuild = ( atoi( szToken ) == 0 ) ? 0 : 1;\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tSpecial.IsFromInstall = ( atoi( szToken ) == 0 ) ? 0 : 1;\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tSpecial.IsCaptureTheFlag = ( atoi( szToken ) == 0 ) ? 0 : 1;\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tSpecial.IsInert = ( atoi( szToken ) == 0 ) ? 0 : 1;\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tSpecial.IsThreePoint = ( atoi( szToken ) == 0 ) ? 0 : 1;\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tSpecial.IsTGrowth = ( atoi( szToken ) == 0 ) ? 0 : 1;\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tSpecial.IsTSpread = ( atoi( szToken ) == 0 ) ? 0 : 1;\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tOptions.GameSpeed = atoi( szToken );\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n//\t\"Version\"\t= atoi( szToken );\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tbAftermathUnits = (bool)atoi( szToken );\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tbSlowUnitBuildRate = (bool)atoi( szToken );\n\n\tszToken = strtok( NULL, szDelimiter );\n\tif( !szToken )\treturn false;\n\tint iRulesID = atoi( szToken );\n\n\tszToken = strtok( NULL, szDelimiter );\n//\tif( szToken )\n//\t\tdebugprint( \"szToken should be NULL!!!!!!!!\\n\" );\n\n\treturn ( RuleINI.Get_Unique_ID() == iRulesID );\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::SetGParamsToCurrent( GAMEPARAMS& GParams )\n{\n\t//\tSets values in a GAMEPARAMS to the current game settings.\n\n\tstrcpy( GParams.GPacket.ScenarioInfo.Scenario, Session.Scenarios[ Session.Options.ScenarioIndex ]->Description() );\n\tCCFileClass file( Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Filename() );\n\tGParams.GPacket.ScenarioInfo.FileLength = file.Size();\n\tstrcpy( GParams.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Filename() );\n\t//\tDigest is not null-terminated.\n\tstrncpy( (char*)GParams.GPacket.ScenarioInfo.FileDigest, Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Digest(), sizeof( GParams.GPacket.ScenarioInfo.FileDigest ) );\n\tGParams.GPacket.ScenarioInfo.OfficialScenario = Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Official();\n\tGParams.GPacket.ScenarioInfo.Credits = Session.Options.Credits;\n\tGParams.GPacket.ScenarioInfo.IsBases = Session.Options.Bases;\n\tGParams.GPacket.ScenarioInfo.IsTiberium = Session.Options.Tiberium;\n\tGParams.GPacket.ScenarioInfo.IsGoodies = Session.Options.Goodies;\n\tGParams.GPacket.ScenarioInfo.BuildLevel = BuildLevel;\n\tGParams.GPacket.ScenarioInfo.UnitCount = Session.Options.UnitCount;\n\tGParams.GPacket.ScenarioInfo.AIPlayers = Session.Options.AIPlayers;\n\tGParams.GPacket.ScenarioInfo.Seed = Seed;\n\tGParams.GPacket.ScenarioInfo.Special = Special;\n\tGParams.GPacket.ScenarioInfo.GameSpeed = Options.GameSpeed;\n\tGParams.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version();\n\n\tGParams.bAftermathUnits = bAftermathUnits;\n\tGParams.bSlowUnitBuildRate = bSlowUnitBuildRate;\n}\n\n//***********************************************************************************************\nbool operator==( const GAMEPARAMS& gp1, const GAMEPARAMS& gp2 )\n{\n\treturn\tgp1.GPacket == gp2.GPacket &&\n\t\t\tgp1.bAftermathUnits == gp2.bAftermathUnits && gp1.bSlowUnitBuildRate == gp2.bSlowUnitBuildRate;\n}\n\n//***********************************************************************************************\nbool operator==( const GlobalPacketType& gp1, const GlobalPacketType& gp2 )\n{\n\tif( strcmp( gp1.ScenarioInfo.Scenario, gp2.ScenarioInfo.Scenario ) != 0\t)\t\treturn false;\n\tif( strcmp( gp1.ScenarioInfo.ShortFileName, gp2.ScenarioInfo.ShortFileName ) != 0 )\t\treturn false;\n\t//\tDigest is not null-terminated...\n\tif( strncmp( (const char*)gp1.ScenarioInfo.FileDigest, (const char*)gp2.ScenarioInfo.FileDigest, sizeof( gp1.ScenarioInfo.FileDigest ) ) != 0 )\t\treturn false;\n\n\tif(\tgp1.ScenarioInfo.FileLength == gp2.ScenarioInfo.FileLength &&\n\t\tgp1.ScenarioInfo.OfficialScenario == gp2.ScenarioInfo.OfficialScenario &&\n\t\tgp1.ScenarioInfo.Credits == gp2.ScenarioInfo.Credits &&\n\t\tgp1.ScenarioInfo.IsBases == gp2.ScenarioInfo.IsBases &&\n\t\tgp1.ScenarioInfo.IsTiberium == gp2.ScenarioInfo.IsTiberium &&\n\t\tgp1.ScenarioInfo.IsGoodies == gp2.ScenarioInfo.IsGoodies &&\n\t\tgp1.ScenarioInfo.BuildLevel == gp2.ScenarioInfo.BuildLevel &&\n\t\tgp1.ScenarioInfo.UnitCount == gp2.ScenarioInfo.UnitCount &&\n\t\tgp1.ScenarioInfo.AIPlayers == gp2.ScenarioInfo.AIPlayers &&\n\t\tgp1.ScenarioInfo.Seed == gp2.ScenarioInfo.Seed &&\n\t\tgp1.ScenarioInfo.Special.IsShadowGrow == gp2.ScenarioInfo.Special.IsShadowGrow &&\n\t\tgp1.ScenarioInfo.Special.IsSpeedBuild == gp2.ScenarioInfo.Special.IsSpeedBuild &&\n\t\tgp1.ScenarioInfo.Special.IsFromInstall == gp2.ScenarioInfo.Special.IsFromInstall &&\n\t\tgp1.ScenarioInfo.Special.IsCaptureTheFlag == gp2.ScenarioInfo.Special.IsCaptureTheFlag &&\n\t\tgp1.ScenarioInfo.Special.IsInert == gp2.ScenarioInfo.Special.IsInert &&\n\t\tgp1.ScenarioInfo.Special.IsThreePoint == gp2.ScenarioInfo.Special.IsThreePoint &&\n\t\tgp1.ScenarioInfo.Special.IsTGrowth == gp2.ScenarioInfo.Special.IsTGrowth &&\n\t\tgp1.ScenarioInfo.Special.IsTSpread == gp2.ScenarioInfo.Special.IsTSpread &&\n\t\tgp1.ScenarioInfo.GameSpeed == gp2.ScenarioInfo.GameSpeed &&\n\t\tgp1.ScenarioInfo.Version == gp2.ScenarioInfo.Version )\n\t\treturn true;\n\n\treturn false;\n}\n\n//***********************************************************************************************\n/*\nvoid Debug_GlobalPacketType( const GlobalPacketType& gp1 )\t\t\t//\tajw  debugging\n{\n\tif( *gp1.ScenarioInfo.Scenario )\n//\t\tdebugprint( \"Scenario = %s\\n\", (char*)gp1.ScenarioInfo.Scenario );\n\telse\n//\t\tdebugprint( \"!Scenario string is null\\n\" );\n\tif( *gp1.ScenarioInfo.ShortFileName )\n//\t\tdebugprint( \"ShortFileName = %s\\n\", (char*)gp1.ScenarioInfo.ShortFileName );\n\telse\n//\t\tdebugprint( \"!ShortFileName string is null\\n\" );\n\t//\tRemember ShortFileName is not null-terminated...\n\tif( *gp1.ScenarioInfo.FileDigest )\n//\t\tdebugprint( \"FileDigest = %.32s\\n\", (char*)gp1.ScenarioInfo.FileDigest );\n\telse\n//\t\tdebugprint( \"!FileDigest string is null\\n\" );\n\n//\tdebugprint(\t\"FileLength = %i\\n\"\n\t\t\t\t\"OfficialScenario = %i\\n\"\n\t\t\t\t\"Credits = %i\\n\"\n\t\t\t\t\"IsBases = %i\\n\"\n\t\t\t\t\"IsTiberium = %i\\n\"\n\t\t\t\t\"IsGoodies = %i\\n\"\n\t\t\t\t\"BuildLevel = %i\\n\"\n\t\t\t\t\"UnitCount = %i\\n\"\n\t\t\t\t\"AIPlayers = %i\\n\"\n\t\t\t\t\"Seed = %i\\n\"\n\t\t\t\t\"Special.IsShadowGrow = %i\\n\"\n\t\t\t\t\"Special.IsSpeedBuild = %i\\n\"\n\t\t\t\t\"Special.IsFromInstall = %i\\n\"\n\t\t\t\t\"Special.IsCaptureTheFlag = %i\\n\"\n\t\t\t\t\"Special.IsInert = %i\\n\"\n\t\t\t\t\"Special.IsThreePoint = %i\\n\"\n\t\t\t\t\"Special.IsTGrowth = %i\\n\"\n\t\t\t\t\"Special.IsTSpread = %i\\n\"\n\t\t\t\t\"GameSpeed = %i\\n\"\n\t\t\t\t\"Version = %i\\n\",\n\t\t\t\tgp1.ScenarioInfo.FileLength,\n\t\t\t\tgp1.ScenarioInfo.OfficialScenario,\n\t\t\t\tgp1.ScenarioInfo.Credits,\n\t\t\t\tgp1.ScenarioInfo.IsBases,\n\t\t\t\tgp1.ScenarioInfo.IsTiberium,\n\t\t\t\tgp1.ScenarioInfo.IsGoodies,\n\t\t\t\tgp1.ScenarioInfo.BuildLevel,\n\t\t\t\tgp1.ScenarioInfo.UnitCount,\n\t\t\t\tgp1.ScenarioInfo.AIPlayers,\n\t\t\t\tgp1.ScenarioInfo.Seed,\n\t\t\t\tgp1.ScenarioInfo.Special.IsShadowGrow,\n\t\t\t\tgp1.ScenarioInfo.Special.IsSpeedBuild,\n\t\t\t\tgp1.ScenarioInfo.Special.IsFromInstall,\n\t\t\t\tgp1.ScenarioInfo.Special.IsCaptureTheFlag,\n\t\t\t\tgp1.ScenarioInfo.Special.IsInert,\n\t\t\t\tgp1.ScenarioInfo.Special.IsThreePoint,\n\t\t\t\tgp1.ScenarioInfo.Special.IsTGrowth,\n\t\t\t\tgp1.ScenarioInfo.Special.IsTSpread,\n\t\t\t\tgp1.ScenarioInfo.GameSpeed,\n\t\t\t\tgp1.ScenarioInfo.Version );\n}\n*/\n\n//***********************************************************************************************\nPlayerColorType PlayerColorTypeOf( RemapControlType* pColorRemap )\n{\n\tfor( PlayerColorType pcolor = PCOLOR_FIRST; pcolor < PCOLOR_COUNT; pcolor++ )\n\t{\n\t\tif( &ColorRemaps[ pcolor ] == pColorRemap )\n\t\t\treturn pcolor;\n\t}\n\treturn PCOLOR_NONE;\n}\n\n//***********************************************************************************************\nbool WOL_GameSetupDialog::RequestPlayerColor( PlayerColorType Color )\n{\n\t//\tLocal player sends a request to the game host asking for a particular color.\n\tchar szSend[ 20 ];\n\n\t//\tWOL_GAMEOPT_REQCOLOR format:\n\t//\t2\tWOL_GAMEOPT\n\t//\t1\tspace\n\t//\t2\tcolor\n\tsprintf( szSend, \"%02u %02u\", WOL_GAMEOPT_REQCOLOR, Color );\n\n\t_ASSERTE( pWO->pGameHost() );\n\n\treturn pWO->SendGameOpt( szSend, pWO->pGameHost() );\n}\n\n//***********************************************************************************************\nbool WOL_GameSetupDialog::InformAboutPlayerColor( const char* szName, PlayerColorType Color, User* pUserPriv )\n{\n\t//\tGame host tells guests about a player color assignment.\n\t//\tIf pUserPriv is not null, indicates user to send message as private to.\n\tchar szSend[ 20 + WOL_NAME_LEN_MAX ];\n\n\t//\tWOL_GAMEOPT_INFCOLOR format:\n\t//\t2\t\tWOL_GAMEOPT\n\t//\t1\t\tspace\n\t//\t2\t\tcolor\n\t//\t1\t\tspace\n\t//\tstring\tname of player\n\n\tif( Color == PCOLOR_NONE )\n\t{\n//\t\tdebugprint( \"Bad Color for %s in InformAboutPlayerColor.\\n\", szName );\n\t\t*szSend = 0;\n\t}\n\telse\n\t\tsprintf( szSend, \"%02u %02u %s\", WOL_GAMEOPT_INFCOLOR, Color, szName );\n\n\treturn pWO->SendGameOpt( szSend, pUserPriv );\n}\n\n//***********************************************************************************************\nbool WOL_GameSetupDialog::InformAboutPlayerHouse( const char* szName, HousesType House, User* pUserPriv )\n{\n\t//\tGame host tells guests about a player house assignment.\n\t//\tIf pUserPriv is not null, indicates user to send message as private to.\n\tchar szSend[ 28 + WOL_NAME_LEN_MAX ];\n\t//\tWOL_GAMEOPT_INFHOUSE format:\n\t//\t2\t\tWOL_GAMEOPT\n\t//\t1\t\tspace\n\t//\t6\t\tparam ID\n\t//\t1\t\tspace\n\t//\t2\t\thouse\n\t//\t1\t\tspace\n\t//\tstring\tname of player\n\n\tif( House == HOUSE_NONE )\n\t{\n//\t\tdebugprint( \"Bad House for %s in InformAboutPlayerHouse.\\n\", szName );\n\t\t*szSend = 0;\n\t}\n\telse\n\t\tsprintf( szSend, \"%02u %06u %02u %s\", WOL_GAMEOPT_INFHOUSE, nHostLastParamID, (short)House, szName );\n\n\treturn pWO->SendGameOpt( szSend, pUserPriv );\n}\n\n//***********************************************************************************************\nbool WOL_GameSetupDialog::InformAboutPlayerAccept( const char* szName, User* pUserPriv )\n{\n\t//\tGame host tells guests about player accepting game params.\n\t//\tIf pUserPriv is not null, indicates user to send message as private to.\n\tchar szSend[ 6 + WOL_NAME_LEN_MAX ];\n\tsprintf( szSend, \"%02u %s\", WOL_GAMEOPT_INFACCEPT, szName );\n\n\treturn pWO->SendGameOpt( szSend, pUserPriv );\n}\n\n//***********************************************************************************************\nbool WOL_GameSetupDialog::InformAboutStart()\n{\n\t//\tGame host tells all guests that he wants to start the game.\n\t//\tNote that nHostLastParamID is involved here. We want to make sure that guest responses apply\n\t//\tto the latest WOL_GAMEOPT_INFSTART, and not to an earlier one we canceled out of.\n\tchar szSend[ 10 ];\n\n\tsprintf( szSend, \"%02u %06u\", WOL_GAMEOPT_INFSTART, nHostLastParamID );\n\n\treturn pWO->SendGameOpt( szSend, NULL );\n}\n\n//***********************************************************************************************\nbool WOL_GameSetupDialog::InformAboutCancelStart()\n{\n\t//\tGame host tells all guests that he wants to start the game.\n\t//\tNote that nHostLastParamID is involved here. We want to make sure that guest responses apply\n\t//\tto the latest WOL_GAMEOPT_INFSTART, and not to an earlier one we canceled out of.\n//\tdebugprint( \"InformAboutCancelStart!\\n\" );\n\n\tchar szSend[ 10 ];\n\n\tsprintf( szSend, \"%02u\", WOL_GAMEOPT_INFCANCELSTART );\n\n\treturn pWO->SendGameOpt( szSend, NULL );\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::OnGuestJoin( User* pUser )\n{\n\t//\tA guest (not myself) has entered the game channel.\n//\tdebugprint( \"OnGuestJoin()\\n\" );\n\tchar* szPrint = new char[ strlen( TXT_WOL_PLAYERJOINEDGAME ) + strlen( (char*)pUser->name ) + 5 ];\n\tsprintf( szPrint, TXT_WOL_PLAYERJOINEDGAME, (char*)pUser->name );\n\tWOL_PrintMessage( *pILDisc, szPrint, WOLCOLORREMAP_LOCALMACHINEMESS );\n\tdelete [] szPrint;\n\n\tClearAllAccepts();\n\n\tif( bHost )\n\t{\n\t\t//\tSend the new guest the current setup.\tNote that nHostLastParamID doesn't change here.\n\n\t\t//\tAssign color to new guest.\n\t\tPlayerColorType Color = ColorNextAvailable();\n\t\tSetPlayerColor( (char*)pUser->name, Color );\n\n\t\t//\tPreviously, I was sending an individual color, house, and acceptedstate message for each other guest.\n\t\t//\tThough convenient code-wise, this causes the initial info to arrive at the new guest in a very slow\n\t\t//\tmanner. This is because of the wonderful \"anti-flood\" feature of the chat server, which prevents a\n\t\t//\tseries of messages from a client from being passed on faster than a certain rate.\n\t\t//\tFor this reason, a new message that contains all of the info about all of the other guests has been\n\t\t//\tcreated (WOL_GAMEOPT_INFNEWGUESTPLAYERINFO).\n\n\t\t//\tWOL_GAMEOPT_INFNEWGUESTPLAYERINFO format (items separated by spaces):\n\t\t//\t\tWOL_GAMEOPT\n\t\t//\t\tnumber of players\n\t\t//\t\tfor each player {\n\t\t//\t\t\tlength of player name string\n\t\t//\t\t\tplayer name\n\t\t//\t\t\tcolor\n\t\t//\t\t\tbool - is there a house field following?\n\t\t//\t\t\t(house)\n\t\t//\t\t\t// (removed) acceptedness - true for set player accepted, false for do nothing\n\t\t//\t\t}\n\n\t\t//\tBuild up a big WOL_GAMEOPT_INFNEWGUESTPLAYERINFO message.\n\t\tchar szSend[ 500 ];\n\t\tsprintf( szSend, \"%02u %02u\", WOL_GAMEOPT_INFNEWGUESTPLAYERINFO, pILPlayers->Count() );\n\t\t//\tSend color and house of all players (including himself) to the new guest.\n\t\tfor( int i = 0; i < pILPlayers->Count(); i++ )\n\t\t{\n\t\t\tchar szSendPiece[ 100 ];\n\t\t\tchar szPlayerName[ WOL_NAME_LEN_MAX ];\n\t\t\tpWO->PullPlayerName_Into_From( szPlayerName, pILPlayers->Get_Item( i ) );\n//\t\t\tInformAboutPlayerColor( szPlayerName, PlayerColorTypeOf( pILPlayers->Get_Item_Color( i ) ), pUser );\n\t\t\tsprintf( szSendPiece, \" %02u %s %02u\", strlen( szPlayerName ), szPlayerName,\n\t\t\t\t\t\t\tPlayerColorTypeOf( pILPlayers->Get_Item_Color( i ) ) );\n\n\t\t\tif( strcmp( szPlayerName, (char*)pUser->name ) != 0 )\n\t\t\t{\n\t\t\t\tHousesType House = pWO->PullPlayerHouse_From( pILPlayers->Get_Item( i ) );\n\t\t\t\tif( House != HOUSE_NONE )\n\t\t\t\t{\n\t//\t\t\t\tInformAboutPlayerHouse( szPlayerName, House, pUser );\n\t\t\t\t\tchar szSendHouse[ 50 ];\n\t\t\t\t\tsprintf( szSendHouse, \" 1 %02u\", (short)House );\n\t\t\t\t\tstrcat( szSendPiece, szSendHouse );\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t//\tPlayer must not have told me what house he is yet. Don't send house value.\n\t\t\t\t\tstrcat( szSendPiece, \" 0\" );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//\tPlayer is the new guest himself. Don't send house value.\n\t\t\t\t\tstrcat( szSendPiece, \" 0\" );\n\t\t\t}\n\n//\tAcceptedness must be false! No need to send.\n//\t\t\t//\tSend \"accepted\" status of player. Ignore myself, as I'm the host.\n//\t\t\tif( strcmp( szPlayerName, pWO->szMyName ) != 0 && pWO->bItemMarkedAccepted( i ) )\n//\t\t\t\tstrcat( szSendPiece, \" 1\" );\n//\t\t\telse\n//\t\t\t\tstrcat( szSendPiece, \" 0\" );\n\n\t\t\tstrcat( szSend, szSendPiece );\n\t\t}\n\t\tpWO->SendGameOpt( szSend, pUser );\n\n\t\t//\tSend everyone the color of the new guest.\n\t\tInformAboutPlayerColor( (char*)pUser->name, Color, NULL );\n\n\t\t//\tSend game params.\n\t\t//\tThis is done last because it contains a param ID value, and we need to ensure that the new guest has\n\t\t//\treceived everything we are sending him here before he tries to send me an accept.\n\t\t//\tIf game params were sent first, he could theoretically receive them, then send an accept, even though he\n\t\t//\thas not received the WOL_GAMEOPT_INFNEWGUESTPLAYERINFO.\n\t\t//\tBy doing this I avoid having to have a param ID in WOL_GAMEOPT_INFNEWGUESTPLAYERINFO, which would be hard,\n\t\t//\tsince it is a private message.\n\t\t//\tFor simplicity, send public.\n\t\tSendParams();\n\t}\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::AcceptNewGuestPlayerInfo( char* szMsg )\n{\n\t//\tProcess a received WOL_GAMEOPT_INFNEWGUESTPLAYERINFO message.\n\t//\tszMsg has already been stripped of 2 bytes header.\n\tchar szDelimiter[] = \" \";\n\tchar* szToken;\n\tchar* szRemaining;\n\n\tszToken = strtok( szMsg, szDelimiter );\n\tunsigned int nPlayers = atoi( szToken );\n\n\t//\tWe have to assist strtok a bit because of calls below that may also call strtok()...\n\tszRemaining = szMsg + 3;\n\n\tfor( unsigned int nPlayer = 0; nPlayer != nPlayers; ++nPlayer )\n\t{\n\t\t//\tRead in length of following string.\n\t\tszToken = strtok( szRemaining, szDelimiter );\n\t\tint iLen = atoi( szToken );\n\n\t\t//\tSet string pointer to start of string (length is 2 digits).\n\t\tszRemaining = szToken + 3;\n\t\t//\tRead in string.\n\t\tchar szPlayerName[ 50 ];\n\t\tmemcpy( szPlayerName, szRemaining, iLen );\n\t\t//\tNull-terminate.\n\t\tszPlayerName[ iLen ] = 0;\n\n\t\t//\tAdvance string pointer to next param.\n\t\tszRemaining += iLen + 1;\n\n\t\t//\tRead color.\n\t\tszToken = strtok( szRemaining, szDelimiter );\n\t\tPlayerColorType Color = (PlayerColorType)atoi( szToken );\n\t\tSetPlayerColor( szPlayerName, Color );\n\n\t\t//\tSetPlayerColor may call strtok, so we can't use the strtok( NULL, option... in the next call.\n\t\tszRemaining += 3;\n\n\t\t//\tRead whether there is a house field.\n\t\tszToken = strtok( szRemaining, szDelimiter );\n\t\tbool bHouseField = (bool)atoi( szToken );\n\n\t\tif( bHouseField )\n\t\t{\n\t\t\t//\tRead house.\n\t\t\tszToken = strtok( NULL, szDelimiter );\n\t\t\tHousesType House = (HousesType)atoi( szToken );\n\t\t\tSetPlayerHouse( szPlayerName, House );\n\t\t\t//\tSetPlayerHouse may call strtok, so we can't use the strtok( NULL, option... in the next call.\n\t\t\tszRemaining += 5;\n\t\t}\n\t\telse\n\t\t\tszRemaining += 2;\t\t//\tAdvance past \"0 \".\n\n//\tAcceptedness must be false. No need for it in message.\n//\t\t//\tRead acceptedness.\n//\t\tszToken = strtok( NULL, szDelimiter );\n//\t\tbool bAccepted = (bool)atoi( szToken );\n//\t\tif( bAccepted )\n//\t\t\tSetPlayerAccepted( szPlayerName, true );\n\t}\n\n\tszToken = strtok( NULL, szDelimiter );\n//\tif( szToken )\n//\t\tdebugprint( \"szToken should be NULL!!!!!!!!\\n\" );\n\n\tClearAllAccepts();\t\t//\tMost likely a pointless precaution.\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::OnGuestLeave( User* pUser )\n{\n\t//\tpUser is about to leave but is still in our player list.\n\tif( pUser->flags & CHAT_USER_CHANNELOWNER  )\n\t{\n\t\t//\tHost is leaving the channel. We must be a guest, and so must leave also. This will trigger exit.\n\t\tstrcpy( szNameOfHostWhoJustBailedOnUs, (char*)pUser->name );\n\t}\n\telse\n\t{\n\t\tClearAllAccepts();\n\t}\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::ClearAllAccepts()\n{\n\t//\tClears all \"player has accepted\" marks.\n//debugprint( \"ClearAllAccepts()\\n\" );\n\tfor( int i = 0; i < pILPlayers->Count(); i++ )\n\t{\n\t\tUser* pUser = (User*)pILPlayers->Get_Item_ExtraDataPtr( i );\n\t\tif( pUser && !( pUser->flags & CHAT_USER_CHANNELOWNER ) )\t//\tpUser null if this is an \"early insertion\" entry on startup\n\t\t\tpWO->MarkItemAccepted( i, false );\n\t}\n\n\tif( pToolTipHitLast && pToolTipHitLast->bShowing )\n\t\tpToolTipHitLast->Unshow();\n\n\tif( bHost )\n\t{\n\t\tpTextBtnAcceptStart->Disable();\n\t\tif( bWaitingToStart )\n\t\t{\n\t\t\t//\tSomething has happened that makes starting a game not possible now.\n\t\t\t//\tCancel out of waiting mode and tell guests to do the same.\n\t\t\tbWaitingToStart = false;\n\t\t\tInformAboutCancelStart();\n\t\t\tBindControls( true );\n\t\t\tResetReadyToGo();\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\telse\n\t\t\tpTextBtnAcceptStart->Flag_To_Redraw();\n\t}\n\telse\n\t{\n\t\tpTextBtnAcceptStart->Enable();\n\t\tpTextBtnAcceptStart->Flag_To_Redraw();\n\t}\n}\n\n//***********************************************************************************************\nbool WOL_GameSetupDialog::bAllGuestsAccept()\n{\n\tfor( int i = 0; i < pILPlayers->Count(); i++ )\n\t{\n\t\tif( !pWO->bItemMarkedAccepted( i ) )\n\t\t\treturn false;\n\t}\n\treturn true;\n}\n\n//***********************************************************************************************\nPlayerColorType WOL_GameSetupDialog::ColorNextAvailable()\n{\n\t//\tReturns the first free player color available.\n\n\t//\t(Totally unoptimized, but hardly ever called.)\n\n\tfor( int i = 0; i < MAX_MPLAYER_COLORS; i++ )\n\t{\n\t\tif( pILPlayers->FindColor( &ColorRemaps[ i ] ) == -1 )\n\t\t{\n\t\t\treturn (PlayerColorType)i;\n\t\t}\n\t}\n//\tdebugprint( \"ColorNextAvailable is NONE!\\n\" );\n\treturn PCOLOR_NONE;\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::GuestIsReadyToPlay( const char* szName, const char* szReadyState )\n{\n\t//\tA guest has responded to a game start request.\n\tSetPlayerReadyToGo( szName, szReadyState );\n\n\tif( bAllPlayersReadyToGo() )\n\t{\n//\t\tdebugprint( \"All players ready to go.\\n\" );\n\t\t//\tWe can start the game.\n\t\tbHostSayGo = true;\t\t\t\t//\tSet trigger to fire function after we're out of callback.\n\t}\n}\n\n//***********************************************************************************************\nbool WOL_GameSetupDialog::bNeedScenarioDownload()\n{\n\t//\tReturns true if we don't have the scenario and it is allowable as a download.\n\tif( !bHost )\n\t{\n\t\tif( Find_Local_Scenario(\tSession.Options.ScenarioDescription,\n\t\t\t\t\t\t\t\t\tSession.ScenarioFileName,\n\t\t\t\t\t\t\t\t\tSession.ScenarioFileLength,\n\t\t\t\t\t\t\t\t\tSession.ScenarioDigest,\n\t\t\t\t\t \t\t\t\tSession.ScenarioIsOfficial ) )\n\t\t{\n//\t\t\tdebugprint( \"bNeedScenarioDownload() returning false.\\n\" );\n\t\t\tbRequestedScenarioDownload = false;\n\t\t\treturn false;\n\t\t}\n\t\telse\n\t\t{\n/*\t\t\tif( !Session.ScenarioIsOfficial )\n\t\t\t{\n\t\t\t\tbRequestedScenarioDownload = true;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n//\t\t\t\tdebugprint( \"bNeedScenarioDownload fatal\\n\" );\n\t\t\t\tFatal( \"\" );\n\t\t\t}\n*/\n//\t\t\tdebugprint( \"Requesting download\\n\" );\t\t//\tajw  Shouldn't be happening with am maps when i have am...?\n\t\t\tbRequestedScenarioDownload = true;\t\t\t//\tAll maps are downloadable.\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tbRequestedScenarioDownload = false;\n\treturn false;\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::HostSaysGo()\n{\n\tbHostSayGo = false;\n\tbHostWaitingForGoTrigger = true;\n\n//\tdebugprint( \"HostSaysGo()\\n\" );\n\n\tif( !pWO->RequestGameStart() )\n\t{\n//\t\tdebugprint( \"Call to RequestGameStart() failed.\\n\" );\n\t\t//Fatal( \"Call to RequestGameStart() failed.\\n\" );\n\t\tpWO->bSelfDestruct = true;\n\t\treturn;\n\t}\n\n\t//\tTell guests to start game.\n//\tdebugprint( \"Telling guests to start game.\\n\" );\n\n\t//\tCreate WOL_GAMEOPT_INFGO message.\n\t//\tThis contains the color for each player, which can change about haphazardly at the end of setup,\n\t//\twithout causing \"unacceptedness\". This means that the colors everyone thinks everyone else is might not\n\t//\tbe sync'ed. Host sets everyone straight here.\n\tchar szSend[ ( WOL_NAME_LEN_MAX + 10 ) * 4 + 50 ] = \"\";\n\tsprintf( szSend, \"%02u\", WOL_GAMEOPT_INFGO );\n\n\tUser* pUser = pWO->pChatSink->pGameUserList;\n\twhile( pUser )\n\t{\n\t\tchar szUser[ WOL_NAME_LEN_MAX + 10 ];\n\t\tPlayerColorType Color = GetPlayerColor( (char*)pUser->name );\n\t\tsprintf( szUser, \" %s %02u\", (char*)pUser->name, Color );\t//\tWhat if player left just now, and got removed from list. Ok to continue and fail on game start?\n\t\tstrcat( szSend, szUser );\n\t\tpUser = pUser->next;\n\t}\n\tif( !pWO->SendGo( szSend ) )\n\t{\n//\t\tdebugprint( \"Call to SendGo() failed.\\n\" );\n\t\t//Fatal( \"Call to SendGo() failed.\\n\" );\n\t\tpWO->bSelfDestruct = true;\n\t\treturn;\n\t}\n\n/*\t...Method changed. It appears that my channelleave may appear to guests before the \"go\" privategameopt.\n\tFor this reason, I'll wait until I receive a copy of the \"go\" message sent to myself, before proceeding.\n\n\tpWO->pChat->PumpMessages();\t\t//\tFlush the send out.\n\t//\t(ajw - Note: An apparent bug in wolapi means that this pump does not necessarily flush the go gameopts.\n\t//\tThis is ok in practice, because the host hits pumps later that will flush them.)\n\n\t//\tPretend we just received szSend, and processed it like a guest would.\n\tchar* szFakeGoMessage = szSend + 3;\n\n\tTriggerGameStart( szFakeGoMessage );\n*/\n}\n\n//***********************************************************************************************\nvoid WOL_GameSetupDialog::TriggerGameStart( char* szGoMessage )\n{\n\t//\tLast function before dialog is exited for game start. (Which must occur now.)\n\t//\tHost or guest is about to start a game using final data in szGoMessage.\n\n//\tdebugprint( \"TriggerGameStart( %s )\\n\", szGoMessage );\n\n\t//\tIf we are in a modal dialog, we must have arrived here through Call_Back()'s PumpMessages. Set global that will\n\t//\tforce a cancel out of the dialog.\n\tif( pWO->bPump_In_Call_Back )\n\t\tcancel_current_msgbox = true;\n\n\tbHostWaitingForGoTrigger = false;\n\tbExitForGameTrigger = true;\n\n\t//\tThe following is based on Read_Game_Options()...\n\n//\tWWGetPrivateProfileString(\"Options\", \"Handle\", \"Noname\", Session.Handle, sizeof(Session.Handle), buffer);\n\n\tstrcpy( Session.Handle, pWO->szMyName );\n\n\t//\tGameName will be the host's name...\n\tstrcpy( Session.GameName, pWO->pGameHostName() );\n//\tdebugprint( \"Session.GameName is %s\\n\", Session.GameName );\n\n//\tgotit\tSession.ColorIdx = (PlayerColorType) WWGetPrivateProfileInt(\"Options\", \"Color\", 0, buffer);\n//\tgotit\tSession.PrefColor = Session.ColorIdx;\n//\tgotit\tint temp = WWGetPrivateProfileInt(\"Options\", \"Side\", 0, buffer);\n//\tgotit\tSession.House = (HousesType) ((int)HOUSE_USSR + temp);\n\n//\tgotit\tSession.Options.Credits = WWGetPrivateProfileInt(\"Options\", \"Credits\", 0, buffer);\n//\tgotit\tSession.Options.Bases = WWGetPrivateProfileInt(\"Options\", \"Bases\", 0, buffer);\n//\tgotit\tSession.Options.Tiberium = WWGetPrivateProfileInt(\"Options\", \"Tiberium\", 0, buffer);\n//\tgotit\tSession.Options.Goodies = WWGetPrivateProfileInt(\"Options\", \"Crates\", 0, buffer);\n//\tgotit\tSpecial.IsShadowGrow = WWGetPrivateProfileInt (\"Options\", \"Shadow\", 0, buffer);\n//\tgotit\tBuildLevel = WWGetPrivateProfileInt(\"Options\", \"BuildLevel\", 0, buffer);\n//\tgotit\tSession.Options.UnitCount = WWGetPrivateProfileInt(\"Options\", \"UnitCount\", 0, buffer);\n//\tgotit\tSeed = WWGetPrivateProfileInt(\"Options\", \"Seed\", 0, buffer);\n//\tgotit\tSpecial.IsCaptureTheFlag = WWGetPrivateProfileInt(\"Options\", \"CapFlag\", 0, buffer);\n\n//\tUnitBuildPenalty = WWGetPrivateProfileInt (\"Options\", \"BuildRate\", 100, buffer);\n\tif( bSlowUnitBuildRate )\n\t\tUnitBuildPenalty = 250;\n\telse\n\t\tUnitBuildPenalty = 100;\n\n\t//PlanetWestwoodGameID = WWGetPrivateProfileInt(\"Internet\", \"GameID\", 0, buffer);\n\tPlanetWestwoodGameID = pWO->pChatSink->iGameID;\n\n\t//\tReset ChatSink's iGameID.\n\tpWO->pChatSink->iGameID = 0;\n\n\t//PlanetWestwoodStartTime = WWGetPrivateProfileInt (\"Internet\", \"StartTime\", 0, buffer);\n\tPlanetWestwoodStartTime = time( NULL );\n\t//WChatHWND = (HWND) WWGetPrivateProfileInt(\"Internet\", \"HWND\", (int)FindWindow(\"OWL_Window\", \"Westwood Chat\"), buffer);\n\n//\tgotit\tSession.Options.AIPlayers = WWGetPrivateProfileInt(\"Options\", \"AI\", 0, buffer);\t\t//Number of AI players\n\tif (Session.Options.AIPlayers){\n\t\tSession.Options.Ghosts = 1;\n\t}\n\n\tif (Session.Options.Tiberium) {\n\t\tSpecial.IsTGrowth = 1;\n\t\tSpecial.IsTSpread = 1;\n\t} else {\n\t\tSpecial.IsTGrowth = 0;\n\t\tSpecial.IsTSpread = 0;\n\t}\n\n\t//\tThe preceding was based on Read_Game_Options()...\n\n\n\t//\tNow do whatever we've left out that the horrific Net_Fake_New_Dialog() and Net_Fake_Join_Dialog() used to do for us...\n\n\t//\tSet up the Session.Players list.\n\t//\tI think there is dependence on the local player being first, so put him there.\n\t//\tElse put them in order listed in the szGoMessage.\n\t//\tI will set \"ID\" based on a player's color, though it seems unclear if this is even used in the game, or what it should be.\n\n\tClear_Vector( &Session.Players );\n\n\t//\tMake the pILPlayers a valid list of players in the game.\n\t//\tPlayers might (incredibly rarely) have joined in the last split-second, and we only want the players listed in\n\t//\tthe szGoMessage. To test for whether they're in this list, first wipe the colors from all list items.\n\t//\tThen we fill them in from info in szGoMessage.\n\t//\tWe can ignore any list items then that have no color assigned.\n\t//\tAlso, we'll know that the colors assigned to valid players indeed match up with what every other client has.\n\t//\tRemember, all other data should already be sync'ed because it has been implemented in such a way that changes would\n\t//\tcause \"unacceptedness\" of guests to occur.\n\n\t//\tClear colors in list.\n\tfor( int iItem = 0; iItem < pILPlayers->Count(); iItem++ )\n\t\tpILPlayers->Set_Item_Color( iItem, &ColorRemaps[ PCOLOR_NONE ] );\n\n\t//\tParse szGoMessage to iterate through players.\n\tchar szDelimiter[] = \" \";\n\tchar* szToken;\n\tchar szPlayerName[ WOL_NAME_LEN_MAX ];\n\n\tszToken = strtok( szGoMessage, szDelimiter );\n\n\twhile( szToken )\n\t{\n\t\tstrcpy( szPlayerName, szToken );\n\t\tszToken = strtok( NULL, szDelimiter );\n\n\t\tPlayerColorType Color = (PlayerColorType)atoi( szToken );\n\t\tSetPlayerColor( szPlayerName, Color );\t\t//\tajw note: inserts if not found.\n\t\tszToken = strtok( NULL, szDelimiter );\n\t}\n\n\t//\tAdd myself to Session.Players list.\n\t_ASSERTE( pILPlayers->Find( pWO->szMyName ) != -1 );\n\n\tNodeNameType* pPlayerNew = new NodeNameType;\n\tstrcpy( pPlayerNew->Name, pWO->szMyName );\t\t\t//\t\"Name\" is 12 chars max.\n\t//pPlayerNew->Address = Session.GAddress;\n\tpPlayerNew->Player.House = GetPlayerHouse( pWO->szMyName );\n//debugprint( \"ME: pPlayerNew->Player.House = %i\\n\", pPlayerNew->Player.House );\n\tpPlayerNew->Player.Color = GetPlayerColor( pWO->szMyName );\n//\tThis gets done later.\n//\tpPlayerNew->Player.ID = (HousesType)( pPlayerNew->Player.Color + HOUSE_MULTI1 );\n\n\tSession.Players.Add( pPlayerNew );\n\n\tchar szHostName[ WOL_NAME_LEN_MAX ] = \"Game host\";\n\n\t//\tAdd all other players to Session.Players list (if they have a valid color - see just above).\n\t//\tAlso in this step - build the scenario download requests array (used by hosts only).\n\tmemset( Session.ScenarioRequests, 0, sizeof( Session.ScenarioRequests ) );\n\tSession.RequestCount = 0;\n\tfor( iItem = 0; iItem < pILPlayers->Count(); iItem++ )\n\t{\n\t\t//\tThe following is not very efficient, but doesn't have to be. Better in this case to keep it clear and simple.\n\t\tpWO->PullPlayerName_Into_From( szPlayerName, pILPlayers->Get_Item( iItem ) );\n\t\tif( strcmp( szPlayerName, pWO->szMyName ) != 0 && GetPlayerColor( szPlayerName ) != PCOLOR_NONE )\n\t\t{\n//\t\t\tdebugprint( \"Creating player node '%s'\\n\", szPlayerName );\n\t\t\tpPlayerNew = new NodeNameType;\n\t\t\tstrcpy( pPlayerNew->Name, szPlayerName );\n\t\t\t//\tGet player's IP address from pChatSink...\n\t\t\tunsigned long lAddress = ( pWO->pChatSink->GetPlayerGameIP( szPlayerName ) );\t//ntohl(\n//\t\t\tdebugprint( \"IP address is %i, or 0x%x\\n\", lAddress, lAddress );\n\t\t\tif( pWO->GameInfoCurrent.bTournament )\n\t\t\t{\n\t\t\t\t//\tThis is a tournament game, and I therefore have only one opponent: this one.\n\t\t\t\t//\tfor convenience, save a copy of his IP address in case I need it later for disconnect pinging.\n\t\t\t\tpWO->TournamentOpponentIP = lAddress;\n\t\t\t\tpWO->bDisconnectPingingCompleted = false;\n\t\t\t}\n\t\t\tNetNumType net;\n\t\t\tNetNodeType node;\n\t\t\tmemset( net, 0, 4 );\n\t\t\tmemset( node, 0, 6 );\n\t\t\tmemcpy( node, &lAddress, 4 );\n\t\t\t//memcpy( node + 2, &lAddress, 4 );\n\t\t\tpPlayerNew->Address.Set_Address( net, node );\n\t\t\t//pPlayerNew->Address = Session.GAddress;\n\t\t\tpPlayerNew->Player.House = GetPlayerHouse( szPlayerName );\n//debugprint( \"Player %i: pPlayerNew->Player.House = %i\\n\", iItem, pPlayerNew->Player.House );\n\t\t\tpPlayerNew->Player.Color = GetPlayerColor( szPlayerName );\n\t\t\t//\tThis gets done later.\n\t\t\t//pPlayerNew->Player.ID = (HousesType)( pPlayerNew->Player.Color + HOUSE_MULTI1 );\n\n\t\t\tSession.Players.Add( pPlayerNew );\n\n\t\t\t//\tIf player is the game host, set HostAddress. This global is used when downloading scenarios; who knows where else.\n\t\t\tUser* pUser = (User*)pILPlayers->Get_Item_ExtraDataPtr( iItem );\n\t\t\tif( pUser && pUser->flags & CHAT_USER_CHANNELOWNER )\n\t\t\t{\n\t\t\t\tSession.HostAddress = pPlayerNew->Address;\n\t\t\t\tstrcpy( szHostName, (char*)pUser->name );\n/*\n\t\t\t\t//\tdebugging\n\t\t\t\tNetNumType netxxx;\n\t\t\t\tNetNodeType nodexxx;\n\t\t\t\tSession.HostAddress.Get_Address( netxxx, nodexxx );\n//\t\t\t\tdebugprint( \"Host, ip %i.%i.%i.%i.%i.%i\\n\", nodexxx[0], nodexxx[1], nodexxx[2], nodexxx[3], nodexxx[4], nodexxx[5] );\n*/\n\t\t\t}\n/*\n\t\t\telse\n\t\t\t{\n\t\t\t\tNetNumType netxxx;\n\t\t\t\tNetNodeType nodexxx;\n\t\t\t\tpPlayerNew->Address.Get_Address( netxxx, nodexxx );\n//\t\t\t\tdebugprint( \"Player ip %i.%i.%i.%i.%i.%i\\n\", nodexxx[0], nodexxx[1], nodexxx[2], nodexxx[3], nodexxx[4], nodexxx[5] );\n\t\t\t}\n*/\n\n\t\t\tif( bHost && pWO->bItemMarkedNeedScenario( iItem ) )\n\t\t\t{\n//\t\t\t\tdebugprint( \"%s has requested scenario download.\\n\", szPlayerName );\n\t\t\t\tSession.ScenarioRequests[ Session.RequestCount++ ] = Session.Players.Count() - 1;\n\t\t\t}\n\t\t}\n//\t\telse\n//\t\t\tdebugprint( \"%s excluded from Session.Players\\n\", szPlayerName );\n\t}\n\n\n\t//\tFrom Init...\n//\tdebugprint( \"About to call Open_Socket().\\n\");\n\tPacketTransport->Open_Socket( 0 );\n\n//\tdebugprint( \"RA95 - About to call Start_Listening.\\n\" );\n\tPacketTransport->Start_Listening();\n\n\t/*\n\t** Flush out any pending packets from a previous game.\n\t*/\n\tPacketTransport->Discard_In_Buffers();\n\tPacketTransport->Discard_Out_Buffers();\n\n\tWWDebugString (\"RA95 - About to call Init_Network.\\n\");\n\tInit_Network();\n\n\tIpx.Set_Timing (\t30, \t\t// retry 2 times per second\n\t\t\t\t\t\t-1, \t\t// ignore max retries\n\t\t\t\t\t\t600);\t\t// give up after 10 seconds\n\n//\tdebugprint( \"Session.ScenarioFileName is %s.\\n\", Session.ScenarioFileName );\n\n\n\t/*\n\t** Read the scenario name from the .INI and try to match it with a scenario file in our list.\n\t*/\n//\tgotit\t\tWWGetPrivateProfileString(\"Options\", \"Scenario\", \"SCM01EA.INI\",\n//\t\t\t\t\t\t\t\t\t\tSession.Options.ScenarioDescription,\n//\t\t\t\t\t\t\t\t\t\tsizeof (Session.Options.ScenarioDescription),\n//\t\t\t\t\t\t\t\t\t\tbuffer);\n\t//WWDebugString (\"RA95I - Scenario is \");\n\t//WWDebugString (Session.Options.ScenarioDescription);\n\t//WWDebugString (\"\\n\");\n\n\tif( !bHost )\t\t//\tElse ScenarioIndex is already set.\n\t{\n\t\tif( bRequestedScenarioDownload )\n\t\t{\n\t\t\tSession.Options.ScenarioIndex = 1;\n\t\t\tif( bSpecialAftermathScenario( Session.Options.ScenarioDescription ) )\n\t\t\t{\n\t\t\t\t//\tShouldn't ever happen. We should never have the opportunity to ask for one of these maps to be downloaded.\n\t\t\t\tbExitForGameTrigger = false;\n\t\t\t\t*szTriggerGameStartInfo = 0;\n\t\t\t\t//\tTrigger the \"our host just left the channel\" code...\n\t\t\t\tstrcpy( szNameOfHostWhoJustBailedOnUs, szHostName );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t//\tWait for download from game host.\n//debugprint( \"Wait for download from game host.\\n\" );\n\t\t\tif( !Get_Scenario_File_From_Host( Session.ScenarioFileName, 1 ) )\n\t\t\t{\n//\t\t\t\tdebugprint( \"Get_Scenario_File_From_Host failed!\\n\" );\n\t\t\t\tbExitForGameTrigger = false;\n\t\t\t\t*szTriggerGameStartInfo = 0;\n\t\t\t\t//\tTrigger the \"our host just left the channel\" code...\n\t\t\t\tstrcpy( szNameOfHostWhoJustBailedOnUs, szHostName );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tScen.Scenario = Session.Options.ScenarioIndex;\n//\t\t\tdebugprint( \"Scen.Scenario = %i\\n\", Scen.Scenario );\n\t\t\tstrcpy( Scen.ScenarioName, Session.ScenarioFileName );\n//\t\t\tdebugprint( \"Scen.ScenarioName = %s\\n\", Scen.ScenarioName );\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//\tMatch ScenarioDescription to a ScenarioIndex.\n/*\tThis is how the same code existed previously. Insufficient because Description may match on many scenarios.\n\t\t\tSession.Options.ScenarioIndex = -1;\n\t\t\tfor (int i = 0; i < Session.Scenarios.Count(); i++) {\n\t\t\t\tif (!strcmp (Session.Scenarios[i]->Description(), Session.Options.ScenarioDescription) ){\n\t\t\t\t\tSession.Options.ScenarioIndex = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n*/\n\t\t\t//\t(We have already done the lookup, in Find_Local_Scenario, above.)\n\t\t\tSession.Options.ScenarioIndex = ScenarioIndex_From_Filename( Session.ScenarioFileName );\n\t\t\t_ASSERTE( Session.Options.ScenarioIndex != -1 );\n\t\t\tScen.Scenario = Session.Options.ScenarioIndex;\n//\t\t\tdebugprint( \"Scen.Scenario = %i\\n\", Scen.Scenario );\n\t\t\tstrcpy( Scen.ScenarioName, Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Filename() );\n//\t\t\tdebugprint( \"Scen.ScenarioName = %s\\n\", Scen.ScenarioName );\n\t\t}\n\t}\n\telse\t\t//\tbHost\n\t{\n\t\tScen.Scenario = Session.Options.ScenarioIndex;\n//\t\tdebugprint( \"Scen.Scenario = %i\\n\", Scen.Scenario );\n\t\tstrcpy( Scen.ScenarioName, Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Filename() );\n//\t\tdebugprint( \"Scen.ScenarioName = %s\\n\", Scen.ScenarioName );\n\t\tstrcpy( Session.Options.ScenarioDescription, (char*)Session.Scenarios[ Session.Options.ScenarioIndex ]->Description() );\n\t}\n\n\tOptions.GameSpeed = 0;\n\n\t//Session.MaxAhead = WChatMaxAhead = WWGetPrivateProfileInt(\"Timing\", \"MaxAhead\", 9, buffer);\n\t//Session.FrameSendRate = WChatSendRate = WWGetPrivateProfileInt(\"Timing\", \"SendRate\", 3, buffer);\n\tSession.MaxAhead = 15;\t//9;\n\t//Session.FrameSendRate = 5;\t//3;\n\tSession.FrameSendRate = 3;\t//3;\n\n\t//\tThis is from NETDLG processing...\n\tSession.NumPlayers = Session.Players.Count();\n\n\tpWO->GameInfoCurrent.iPlayerCount = Session.Players.Count();\n\n\tIpx.Set_Timing (25, (unsigned long) -1, 1000);\n\n\n\tif( bHost )\n\t{\n\t\tif( Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Official() )\n\t\t{\n\t\t\tif( !Force_Scenario_Available( Scen.ScenarioName ) )\n\t\t\t{\n\t\t\t\tbExitForGameTrigger = false;\n\t\t\t\t*szTriggerGameStartInfo = 0;\n\t\t\t\tpWO->bSelfDestruct = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif( Session.RequestCount )\n\t\t{\n\t\t\t//\tSend the scenario to any guests that requested a download.\n//debugprint( \"Send the scenario to any guests that requested a download.\\n\" );\n\t\t\tSend_Remote_File( Scen.ScenarioName, 1 );\n\t\t}\n\t}\n\n\tSession.CommProtocol = COMM_PROTOCOL_MULTI_E_COMP;\n\tIpx.Set_Timing (30, (unsigned long) -1, 600);\n\n\tpWO->bEnableNewAftermathUnits = bAftermathUnits;\n\tbAftermathMultiplayer = bAftermathUnits;\n\n\t*pWO->szExternalPager = 0;\n\n\tpWO->bDoingDisconnectPinging = false;\t//\tPointlessly making sure.\n\n\t*szTriggerGameStartInfo = 0;\t//\tThis was set in order to trigger my coming here.\n}\n\n#endif\n\n//***********************************************************************************************\nbool bSpecialAftermathScenario( const char* szScenarioDescription )\n{\n\t//\tReturns true if szScenarioDescription matches one of the descriptions for Aftermath multiplayer\n\t//\tscenarios that have special Aftermath-only units *embedded* within them.\n\tif( strcmp( szScenarioDescription, \"Booby Traps (Mega 8 players)\" ) == 0 ||\n\t\tstrcmp( szScenarioDescription, \"Central Conflict Extreme (Mega 8 players)\" ) == 0 ||\n\t\tstrcmp( szScenarioDescription, \"Circles of Death (Mega 8 players)\" ) == 0 ||\n\t\tstrcmp( szScenarioDescription, \"Holy Grounds (Mega 8 players)\" ) == 0 ||\n\t\tstrcmp( szScenarioDescription, \"Island Wars Extreme (Mega 8 players)\" ) == 0 ||\n\t\tstrcmp( szScenarioDescription, \"King of the Hills Extreme (Mega 8 players)\" ) == 0 ||\n\t\tstrcmp( szScenarioDescription, \"The Hills Have Eyes (Mega 8 players)\" ) == 0 )\n\t\treturn true;\n\treturn false;\n}\n\n//***********************************************************************************************\nint ScenarioIndex_From_Filename( const char* szScenarioFilename )\n{\n\t//\tReturns the scenario index that matches the scenario filename, or -1 if no match found.\n\tfor( int index = 0; index < Session.Scenarios.Count(); index++ )\n\t{\n\t\tif( _stricmp( szScenarioFilename, Session.Scenarios[index]->Get_Filename() ) == 0 )\n\t\t\treturn index;\n\t}\n\treturn -1;\n}\n"
  },
  {
    "path": "CODE/WOL_GSUP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifdef WOLAPI_INTEGRATION\n\n//\twol_gsup.h\t\t\t\"WOL Game Setup Dialog\"\n//\tajw 08/06/98\n\n//\tClass WOL_GameSetupDialog is a move away from doing dialogs purely in C, a format that I've maintained in the login and\n//\tchat dialogs, mimicking how dialogs are done elsewhere in the code, but became frustrated with.\n//\tThough I'll follow the same pattern as before, things will be centralized a little cleaner through the use of this object.\n//\tWhy a standard dialog class that would handle common input behavior and so forth (one that this class could derive from)\n//\twasn't written 5 years ago, I don't know...\n\n#include \"WolapiOb.h\"\n//class WolapiObject;\nclass IconListClass;\nclass EditClass;\nclass GaugeClass;\nclass CheckListClass;\nclass TextButtonClass;\nclass StaticButtonClass;\nclass DropListClass;\nclass ShapeButtonClass;\nclass BigCheckBoxClass;\nclass ToolTipClass;\n\n//***********************************************************************************************\nenum RESULT_WOLGSUP\n{\n\tRESULT_WOLGSUP_BACKTOCHAT,\n\tRESULT_WOLGSUP_FATALERROR,\n\tRESULT_WOLGSUP_HOSTLEFT,\n\tRESULT_WOLGSUP_STARTGAMEHOST,\n\tRESULT_WOLGSUP_STARTGAME,\n\tRESULT_WOLGSUP_RULESMISMATCH,\n\tRESULT_WOLGSUP_LOGOUT,\n};\n\nstruct GAMEPARAMS\n{\n\tGlobalPacketType\tGPacket;\n\t//\tMy additions to game params. - ajw\n\tbool\t\t\t\tbAftermathUnits;\n\tbool\t\t\t\tbSlowUnitBuildRate;\n};\n\n//***********************************************************************************************\nclass WOL_GameSetupDialog\n{\npublic:\n\tWOL_GameSetupDialog( WolapiObject* pWO, bool bHost );\n\t~WOL_GameSetupDialog();\n\n\tRESULT_WOLGSUP\tRun();\n\npublic:\n\tbool\tbHost;\t\t\t\t//\tTrue when I created the game channel and am the host.\n\n\tbool\tbHostSayGo;\t\t\t\t\t//\tTrigger host instructing all to start game immediately.\n\tbool\tbHostWaitingForGoTrigger;\t//\tTrue while host is waiting for go message to bounce back to him and trigger start.\n\tbool\tbExitForGameTrigger;\t\t//\tTrigger exiting dialog for game.\n\n\n\tvoid\tProcessGuestRequest( User* pUser, const char* szRequest );\n\tvoid\tProcessInform( char* szRequest );\n\tvoid\tOnGuestJoin( User* pUser );\n\tvoid\tOnGuestLeave( User* pUser );\n\nprotected:\n\tvoid\tInitialize();\n\tRESULT_WOLGSUP\tShow();\n\tvoid\tSetSpecialControlStates();\n\tvoid\tBindControls( bool bBind );\n\tbool\tExitGameChannel();\n\tvoid\tDrawScenarioDescripIcon( const char* pDIB ) const;\n\tvoid\tSetPlayerColor( const char* szName, PlayerColorType Color );\n\tPlayerColorType\t\tGetPlayerColor( const char* szName );\n\tvoid\tSetPlayerHouse( const char* szName, HousesType House );\n\tHousesType\tGetPlayerHouse( const char* szName );\n\tbool\tSetPlayerAccepted( const char* szName, bool bAccepted );\n\tbool\tIveAccepted();\n\tbool\tSetPlayerReadyToGo( const char* szName, const char* szReadyState );\n\tvoid\tResetReadyToGo();\n\tbool\tbPlayerReadyToGo( const char* szName );\n\tbool\tbAllPlayersReadyToGo();\n\n\tbool\tbParamsUnfresh();\n\tvoid\tSendParams();\n\tbool\tAcceptParams( char* szParams );\n\tvoid\tSetGParamsToCurrent( GAMEPARAMS& GParams );\n\n\tvoid\tAcceptNewGuestPlayerInfo( char* szMsg );\n\n\tbool\tRequestPlayerColor( PlayerColorType Color );\n\tbool\tInformAboutPlayerColor( const char* szName, PlayerColorType Color, User* pUserPriv );\n\tbool\tInformAboutPlayerHouse( const char* szName, HousesType House, User* pUserPriv );\n\tbool\tInformAboutPlayerAccept( const char* szName, User* pUserPriv );\n\tbool\tInformAboutStart();\n\tbool\tInformAboutCancelStart();\n\n\tvoid\tClearAllAccepts();\n\tbool\tbAllGuestsAccept();\n\n\tPlayerColorType ColorNextAvailable();\n\n\tvoid\tGuestIsReadyToPlay( const char* szName, const char* szReadyState );\n\tbool\tbNeedScenarioDownload();\n\tvoid\tHostSaysGo();\n\tvoid\tTriggerGameStart( char* szGoMessage );\n\n\tenum SCENARIO_GAMEKIND\n\t{\n\t\tSCENARIO_RA = 0,\n\t\tSCENARIO_CS,\n\t\tSCENARIO_AM,\n\t\tSCENARIO_USER,\n\t\tSCENARIO_UNINITIALIZED,\n\t};\n\tvoid\tScenarioDisplayMode( SCENARIO_GAMEKIND ScenKind );\n\n//\tbool\tbSpecialAftermathScenario( const char* szScenarioDescription );\n\npublic:\n\tint d_dialog_w;\n\tint d_dialog_h;\n\tint d_dialog_x;\n\tint d_dialog_y;\n\tint d_dialog_cx;\n\n\tint d_txt6_h;\n\tint d_margin1;\n\n\tint d_house_w;\n\tint d_house_h;\n\tint d_house_x;\n\tint d_house_y;\n\n\tint d_color_w;\n\tint d_color_h;\n\tint d_color_x;\n\tint d_color_y;\n\n\tint d_playerlist_w;\n\tint d_playerlist_h;\n\tint d_playerlist_x;\n\tint d_playerlist_y;\n\n\tint d_scenariolist_w;\n\tint d_scenariolist_h;\n\tint d_scenariolist_x;\n\tint d_scenariolist_y;\n\n\tint d_gamekind_w;\n\tint d_gamekind_h;\n\tint d_gamekind_x;\n\tint d_gamekind_y;\n\n\tint d_count_w;\n\tint d_count_h;\n\tint d_count_x;\n\tint d_count_y;\n\n\tint d_level_w;\n\tint d_level_h;\n\tint d_level_x;\n\tint d_level_y;\n\n\tint d_credits_w;\n\tint d_credits_h;\n\tint d_credits_x;\n\tint d_credits_y;\n\n\tint d_aiplayers_w;\n\tint d_aiplayers_h;\n\tint d_aiplayers_x;\n\tint d_aiplayers_y;\n\n\tint d_options_w;\n\tint d_options_h;\n\tint d_options_x;\n\tint d_options_y;\n\n\tint d_disc_w;\n\tint d_disc_h;\n\tint d_disc_x;\n\tint d_disc_y;\n\n\tint d_send_w;\n\tint d_send_h;\n\tint d_send_x;\n\tint d_send_y;\n\n\tint d_ok_w;\n\tint d_ok_h;\n\tint d_ok_x;\n\tint d_ok_y;\n\n\tint d_cancel_w;\n\tint d_cancel_h;\n\tint d_cancel_x;\n\tint d_cancel_y;\n\n\tint\td_accept_w;\n\tint\td_accept_h;\n\tint\td_accept_x;\n\tint\td_accept_y;\n\n\tint\td_amunits_w;\n\tint\td_amunits_h;\n\tint\td_amunits_x;\n\tint\td_amunits_y;\n\n\tint\td_action_w;\n\tint\td_action_h;\n\tint\td_action_x;\n\tint\td_action_y;\n\nprotected:\n\tGadgetClass*\t\tcommands;\t\t\t\t//\tThe controls list.\n\n\tIconListClass*\t\tpILPlayers;\n\tIconListClass*\t\tpILScens;\n\tIconListClass*\t\tpILDisc;\n\tchar szSendBuffer[ MAXCHATSENDLENGTH ];\n\tEditClass*\t\t\tpEditSend;\n\tGaugeClass*\t\t\tpGaugeCount;\n\tGaugeClass*\t\t\tpGaugeLevel;\n\tGaugeClass*\t\t\tpGaugeCredits;\n\tGaugeClass*\t\t\tpGaugeAIPlayers;\n\tCheckListClass*\t\tpCheckListOptions;\n\tTextButtonClass*\tpTextBtnOk;\n\tTextButtonClass*\tpTextBtnCancel;\n\tTextButtonClass*\tpTextBtnAcceptStart;\n\tTextButtonClass*\tpTextBtnAction;\n\tStaticButtonClass*\tpStaticDescrip;\n\tStaticButtonClass*\tpStaticUnit;\n\tStaticButtonClass*\tpStaticLevel;\n\tStaticButtonClass*\tpStaticCredits;\n\tStaticButtonClass*\tpStaticAIPlayers;\n\tchar szHouseBuffer[25];\t\t\t\t\t\t// buffer for house droplist\n\tDropListClass*\t\tpDropListHouse;\n\tBigCheckBoxClass*\tpCheckAftermathUnits;\n\tShapeButtonClass*\tpShpBtnScenarioRA;\n\tShapeButtonClass*\tpShpBtnScenarioCS;\n\tShapeButtonClass*\tpShpBtnScenarioAM;\n\tShapeButtonClass*\tpShpBtnScenarioUser;\n\n\tToolTipClass*\t\tpTTipAcceptStart;\n\tToolTipClass*\t\tpTTipCancel;\n\tToolTipClass*\t\tpTTipAction;\n\n\tWolapiObject*\t\tpWO;\n\n\n\tGAMEPARAMS\t\t\tGParamsLastSent;\t\t//\tUsed merely as a handy container for the vars I need to set.\n\n\tDWORD\t\t\t\tdwTimeNextParamRefresh;\t\t//\tParam changes are sent by host at certain interval.\n\n\tHousesType\t\t\tHousePrevious;\n\n\tunsigned int\t\tnHostLastParamID;\t\t//\tHost's send update tracking packet ID.\n\tunsigned int\t\tnGuestLastParamID;\t\t//\tGuest's record of last ID received from host.\n\n\tbool\t\t\t\tbWaitingToStart;\n\n\tbool\t\t\t\tbProcess;\t\t\t\t//\tTrue means continue doing input loop.\n\tRESULT_WOLGSUP\t\tResultReturn;\t\t\t//\tValue that will be returned from Show().\n\tchar\t\t\t\tszNameOfHostWhoJustBailedOnUs[ WOL_NAME_LEN_MAX ];\t//\tIf set, triggers setup cancellation.\n\n\tbool\t\t\t\tbParamsReceived;\t\t//\tTrue after any WOL_GAMEOPT_INFPARAMS messages have been received from a host.\n\n\tbool\t\t\t\tbLeaveDueToRulesMismatchTrigger;\n\n\tbool\t\t\t\tbRequestedScenarioDownload;\n\n\tchar\t\t\t\tszTriggerGameStartInfo[ ( WOL_NAME_LEN_MAX + 10 ) * 4 + 60 ];\n\n\t//\tTooltips...\n\tDWORD\t\t\t\ttimeToolTipAppear;\n\tToolTipClass*\t\tpToolTipHead;\t\t\t//\tHead of list of ToolTips that parallels gadget list.\n\tToolTipClass*\t\tpToolTipHitLast;\t\t//\tToolTip the mouse was last over, or null.\n\n\t//\tExtra game params...\n\tbool\t\t\t\tbAftermathUnits;\t\t//\tTrue if aftermath units are to be used in the game.\n\tbool\t\t\t\tbSlowUnitBuildRate;\n\n\tSCENARIO_GAMEKIND\tScenKindCurrent;\t\t//\tDescribes what gamekind of scenarios we are viewing, if host.\n\tDynamicVectorClass< const char* >\tar_szScenarios[ 4 ];\t//\tLists of scenarios, by SCENARIO_GAMEKIND.\n\t//\tar_szScenIndexes parallels ar_szScenarios, holds ScenarioIndex. It's actually an int, but I'm using void* to avoid\n\t//\ttemplate instantiation problems and the need to change defines.h.\n\tDynamicVectorClass< void* >\t\t\tar_szScenIndexes[ 4 ];\n\n\t//------------------------------------------------------------------------\n\t//\tButton Enumerations\n\t//------------------------------------------------------------------------\n\tenum\n\t{\n\t\tBUTTON_DISCONNECT = 100,\t//\tNote: standard WOL button IDs must match values in WolapiObject::PrepareButtonsAndIcons().\n\t\tBUTTON_LEAVE,\n\t\tBUTTON_REFRESH,\n\t\tBUTTON_SQUELCH,\n\t\tBUTTON_BAN,\n\t\tBUTTON_KICK,\n\t\tBUTTON_FINDPAGE,\n\t\tBUTTON_OPTIONS,\n\t\tBUTTON_LADDER,\n\t\tBUTTON_HELP,\n\n\t\tBUTTON_PLAYERLIST,\n\t\tBUTTON_HOUSE,\n\t\tBUTTON_SCENARIOLIST,\n\t\tBUTTON_DISCLIST,\n\t\tBUTTON_SENDEDIT,\n\t\tBUTTON_COUNT,\n\t\tBUTTON_LEVEL,\n\t\tBUTTON_CREDITS,\n\t\tBUTTON_AIPLAYERS,\n\t\tBUTTON_PARAMS,\n//\t\tBUTTON_OK,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_ACCEPTSTART,\n\t\tBUTTON_ACTION,\n\t\tBUTTON_AFTERMATHUNITS,\n\t\tBUTTON_SCENARIO_RA,\n\t\tBUTTON_SCENARIO_CS,\n\t\tBUTTON_SCENARIO_AM,\n\t\tBUTTON_SCENARIO_USER,\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t//------------------------------------------------------------------------\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PARMS,\n\t\tREDRAW_MESSAGE,\n\t\tREDRAW_COLORS,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\tRedrawType\t\t\tdisplay;\n\n};\n\n#endif\n\n"
  },
  {
    "path": "CODE/WOL_LOGN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifdef WOLAPI_INTEGRATION\n\n//\tWol_Logn.cpp - WW online name/password dialog.\n//\tajw 07/16/98\n\n#include \"function.h\"\n\n#include \"IconList.h\"\n#include \"WolapiOb.h\"\n#include \"PassEdit.h\"\n#include \"WolStrng.h\"\n#include \"BigCheck.h\"\n\nbool ReadSavedNicks( WolapiObject* pWO, IconListClass& NickList, char* szNameBuffer, char* szPassBuffer );\nbool bSaveNick( WolapiObject* pWO, const char* szNickToSave, const char* szPassToSave, bool bPassIsMangled );\nvoid DeleteNick( WolapiObject* pWO, int iOneBasedEntryToDelete );\n//char* LoadShpFile( const char* szShpFile );\n\nvoid DebugChatDef( HRESULT hRes );\n\nextern bool bTabKeyPressedHack;\n\n//#include \"WolDebug.h\"\n\n//***********************************************************************************************\nint WOL_Login_Dialog( WolapiObject* pWO )\n{\n\t//\tReturn values: 0 = user cancels, 1 = success, -1 = force game exit\n\n\tif( pWO->bLoggedIn() )\n\t{\n\t\tpWO->bReturningAfterGame = true;\t//\tSet trigger for chat dialog.\n\t\treturn 1;\t\t//\tWe are already logged in, and have just come back from a game.\n\t}\n\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n#ifdef FRENCH\n\tint d_dialog_w = 160 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n#else\n\tint d_dialog_w = 150 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n#endif\n\tint d_dialog_h = 85 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = (((320 * RESFACTOR) - d_dialog_w) / 2);\n\tint d_dialog_y = (((255 * RESFACTOR) - d_dialog_h) / 2);\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// coord of x-center\n\n\tint d_txt8_h = 11 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// ht of 8-pt text\n\tint d_margin = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\tint x_margin = 16 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint top_margin = 0;\n\n\tint d_name_w = 66 * RESFACTOR;\n\tint d_name_h = 10 * RESFACTOR;\n#ifdef FRENCH\n\tint d_name_x = d_dialog_x + 25 * RESFACTOR;\n#else\n\tint d_name_x = d_dialog_x + 20 * RESFACTOR;\n#endif\n\tint d_name_y = d_dialog_y + top_margin + 25 * RESFACTOR;\n\n\tint d_pass_w = 36 * RESFACTOR;\n\tint d_pass_h = d_name_h;\n\tint d_pass_x = d_name_x + d_name_w + 6 * RESFACTOR;\n\tint d_pass_y = d_name_y;\n\n\tint d_list_w = d_name_w;\n\tint d_list_h = 20 * RESFACTOR;\n\tint d_list_x = d_name_x;\n\tint d_list_y = d_dialog_y + top_margin + 40 * RESFACTOR;\n\n//\tint d_save_w = d_pass_w;\n\tint d_save_h = 9 * RESFACTOR;\n\tint d_save_x = d_pass_x + ( d_pass_w / 2 ) - ( d_pass_w / 2 );\n\tint d_save_y = d_list_y;\t// + ( d_list_h / 2 ) - ( d_save_h / 2 );\n\n\tint d_delete_w = d_pass_w;\n\tint d_delete_h = 10 * RESFACTOR;\n\tint d_delete_x = d_save_x;\n\tint d_delete_y = d_list_y + d_list_h - d_delete_h;\n\n#ifdef FRENCH\n\tint d_connect_w = 45 * RESFACTOR;\n#else\n\tint d_connect_w = 40 * RESFACTOR;\n#endif\n\tint d_connect_h = 13 * RESFACTOR;\n\tint d_connect_x = d_name_x + d_name_w/2 - d_connect_w/2;\n\tint d_connect_y = d_dialog_y + top_margin + 65 * RESFACTOR;\t//d_dialog_y + d_dialog_h - d_connect_h - d_margin;\n\n#if defined(GERMAN) || defined(FRENCH)\n\tint d_cancel_w = 40 * RESFACTOR;//BG:40\n#else\n\tint d_cancel_w = 40 * RESFACTOR;\n#endif\n\tint d_cancel_h = 13 * RESFACTOR;\n\tint d_cancel_x = d_pass_x + d_pass_w/2 - d_cancel_w/2;\t//d_dialog_cx + d_margin;\n\tint d_cancel_y = d_connect_y;\n\n\t/*\n\t**\tButton enumerations\n\t*/\n\tenum {\n\t\tBUTTON_CONNECT = 100,\n\t\tBUTTON_CANCEL,\n\t\tLISTBOX_NICKS,\n\t\tEDITBOX_NAME,\n\t\tEDITBOX_PASS,\n\t\tBUTTON_SAVECHECK,\n\t\tBUTTON_DELETE,\n\t};\n\n\t/*\n\t**\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*\n\t**\tDialog variables\n\t*/\n\tint iReturn = 1;\t\t//\t0 = user cancels, 1 = success, -1 = force game exit\n\n\t/*\n\t**\tOther Variables\n\t*/\n\tchar szNameBuffer[ WOL_NAME_LEN_MAX ] = {0};\t\t\t\t//\tUser name.\n\tchar szPassBuffer[ WOL_PASSWORD_LEN ] = {0};\t\t\t\t//\tUser password.\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass* commands = NULL;\t\t// the button list\n\n\tTextButtonClass ConnectBtn( BUTTON_CONNECT, TXT_WOL_CONNECT, TPF_BUTTON, d_connect_x, d_connect_y, d_connect_w );\n\tTextButtonClass CancelBtn( BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w );\n\n\tIconListClass NickList( LISTBOX_NICKS, d_list_x, d_list_y, d_list_w, d_list_h, TPF_6PT_GRAD | TPF_NOSHADOW,\n\t\t\t\t\t\t\t\tMFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"), true, 1, 0 );\n\n\tWOLEditClass NameEdit( EDITBOX_NAME, szNameBuffer, sizeof(szNameBuffer), TPF_6PT_GRAD|TPF_NOSHADOW, \n\t\t\t\t\t\t\td_name_x, d_name_y, d_name_w, -1, EditClass::ALPHANUMERIC );\n\n\tPassEditClass PassEdit( EDITBOX_PASS, szPassBuffer, sizeof(szPassBuffer), TPF_6PT_GRAD|TPF_NOSHADOW, \n\t\t\t\t\t\t\td_pass_x, d_pass_y, d_pass_w, -1, EditClass::ALPHANUMERIC );\n\n\t//\tJust making sure globals are set right before String_Pixel_Width() call... sigh\n\tFancy_Text_Print( TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD | TPF_NOSHADOW );\n\tint iSaveTextWidth = String_Pixel_Width( TXT_WOL_SAVELOGIN ) + BIGCHECK_OFFSETX;\n\tBigCheckBoxClass SaveCheckBox( BUTTON_SAVECHECK, d_save_x, d_save_y, iSaveTextWidth, d_save_h, \n\t\t\t\t\t\t\t\t\t\tTXT_WOL_SAVELOGIN, TPF_6PT_GRAD | TPF_NOSHADOW, true );\n\n\tTextButtonClass DeleteBtn( BUTTON_DELETE, TXT_DELETE_BUTTON, TPF_BUTTON, d_delete_x, d_delete_y, d_delete_w );\n\n\t/*\n\t**\tInitialize.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t//\tGet saved nickname/passwords from the registry.\n\tif( ReadSavedNicks( pWO, NickList, szNameBuffer, szPassBuffer ) )\n\t{\n\t\tPassEdit.bClearOnNextSetFocus = true;\n\t}\n\telse\n\t{\n\t\t//\tOffer user the chance to go to web site now to get a nick.\n\t\tif( pWO->DoWebRegistration() )\n\t\t{\n\t\t\t//\tUser chose to go to web page. Leave function so that we'll re-read nicks when they return.\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\t/*\n\t**\tCreate the button list.\n\t*/\n\tcommands = &ConnectBtn;\n\tCancelBtn.Add_Tail(*commands);\n\tNickList.Add_Tail(*commands);\n\tNameEdit.Add_Tail(*commands);\n\tPassEdit.Add_Tail(*commands);\n\tSaveCheckBox.Add_Tail(*commands);\n\tDeleteBtn.Add_Tail(*commands);\n\tNameEdit.Set_Focus();\n\n\tif( NickList.Count() == 0 )\n\t\tDeleteBtn.Disable();\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tKeyboard->Clear();\n\tbool firsttime = true;\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tCall_Back();\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = true;\n\t\t}\n\t\t#endif\n\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\n\t\t\t//------------------------------------------------------------------------\n\t\t\t//\tClear screen\n\t\t\t//------------------------------------------------------------------------\n\t\t\tHide_Mouse();\n\t\t\tLoad_Title_Page(true);\n//\t\t\tShow_Mouse();\n\n\t\t\t/*\n\t\t\t**\tDisplay the dialog box.\n\t\t\t*/\n//\t\t\tHide_Mouse();\n\t\t\tif (display) {\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\t\t\t\tDraw_Caption(TXT_WOL_LOGINDIALOG, d_dialog_x, d_dialog_y, d_dialog_w);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRedraw the buttons.\n\t\t\t*/\n\t\t\tif (display) {\n\t\t\t\tFancy_Text_Print( TXT_WOL_NAME, d_name_x + ( d_name_w / 2 ), d_name_y - 14,\n\t\t\t\t\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT | TPF_CENTER );\n\t\t\t\tFancy_Text_Print( TXT_WOL_PASSWORD, d_pass_x + ( d_pass_w / 2 ), d_pass_y - 14,\n\t\t\t\t\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT | TPF_CENTER );\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t//\tForce mouse visible, as some beta testers report unexplicable disappearing cursors.\n\t\twhile( Get_Mouse_State() )\n\t\t\tShow_Mouse();\n\t\t//\tBe nice to other apps.\n\t\tSleep( 50 );\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tbTabKeyPressedHack = false;\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t**\tThe first time through the processing loop, set the edit\n\t\t**\tgadget to have the focus. The\n\t\t**\tfocus must be set here since the gadget list has changed\n\t\t**\tand this change will cause any previous focus setting to be\n\t\t**\tcleared by the input processing routine.\n\t\t*/\n\t\tif (firsttime ) {\n\t\t\tfirsttime = false;\n\t\t\tNameEdit.Set_Focus();\n\t\t\tNameEdit.Flag_To_Redraw();\n\t\t}\n\n//\t\t/*\n//\t\t**\tIf the <RETURN> key was pressed, then default to the appropriate\n//\t\t**\taction button according to the style of this dialog box.\n//\t\t*/\n/*\t\tif (input == KN_RETURN || input == (BUTTON_CONNECT|KN_BUTTON)) {\n\t\t\tToggleClass * toggle = NULL;\n\t\t\tinput = (KeyNumType)(BUTTON_CONNECT|KN_BUTTON);\n\t\t\tCancelBtn.Turn_Off();\n\t\t\ttoggle = (ToggleClass*)commands->Extract_Gadget(BUTTON_CONNECT);\n\t\t\tif (toggle != NULL) {\n\t\t\t\ttoggle->Turn_On();\n\t\t\t\ttoggle->IsPressed = true;\n\t\t\t}\n\n\t\t\tHide_Mouse();\n\t\t\tcommands->Draw_All(true);\n\t\t\tShow_Mouse();\n\t\t}\n*/\n\t\t/*\n\t\t**\tProcess input.\n\t\t*/\n//\t\tif( input )\n//\t\t\tdebugprint( \"input: %i\\n\", input );\n\n\t\tif( bTabKeyPressedHack )\n\t\t{\n\t\t\tif( NameEdit.Has_Focus() )\n\t\t\t\tPassEdit.Set_Focus();\n\t\t\telse\n\t\t\t\tNameEdit.Set_Focus();\n\t\t\tNameEdit.Flag_To_Redraw();\n\t\t\tPassEdit.Flag_To_Redraw();\n\t\t}\n\n\t\tswitch( input )\n\t\t{\n\t\t\t/*\n\t\t\t** ESC/Cancel: break\n\t\t\t*/\n\t\t\tcase ( KN_ESC ):\n\t\t\tcase ( BUTTON_CANCEL | KN_BUTTON ):\n\t\t\t\tiReturn = 0;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase KN_RETURN:\n\t\t\tcase ( EDITBOX_NAME | KN_BUTTON ):\n\t\t\tcase ( EDITBOX_PASS | KN_BUTTON ):\n\t\t\tcase ( BUTTON_CONNECT | KN_BUTTON ):\n\t\t\t{\n\t\t\t\tif( !strlen( szNameBuffer ) )\n\t\t\t\t{\n\t\t\t\t\tWWMessageBox().Process( TXT_WOL_MISSINGNAME );\n\t\t\t\t\tfirsttime = true;\t\t//\tBloody hack.\n\t\t\t\t\tNameEdit.Set_Focus();\n\t\t\t\t\tKeyboard->Clear();\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif( !strlen( szPassBuffer ) )\n\t\t\t\t{\n\t\t\t\t\tWWMessageBox().Process( TXT_WOL_MISSINGPASSWORD );\n\t\t\t\t\tfirsttime = true;\t\t//\tBloody hack.\n\t\t\t\t\tPassEdit.Set_Focus();\n\t\t\t\t\tKeyboard->Clear();\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//\tIf we have not done RequestServerList() yet, do it now.\n\t\t\t\tif( !pWO->pChatSink->pServer )\n\t\t\t\t{\n\t\t\t\t\tbool bBreak = false;\n\t\t\t\t\tHRESULT hRes = pWO->GetChatServer();\n\t\t\t\t\tswitch( hRes )\n\t\t\t\t\t{\n\t\t\t\t\tcase E_FAIL:\n\t\t\t\t\t\tbBreak = true;\n\t\t\t\t\t\tWWMessageBox().Process( TXT_WOL_CANTCONNECT );\n\t\t\t\t\t\tfirsttime = true;\t\t//\tBloody hack.\n\t\t\t\t\t\tNameEdit.Set_Focus();\n\t\t\t\t\t\tKeyboard->Clear();\n\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase USERCANCELLED:\n\t\t\t\t\t\tbBreak = true;\n\t\t\t\t\t\tWWMessageBox().Process( TXT_WOL_LOGINCANCEL );\n\t\t\t\t\t\tfirsttime = true;\t\t//\tBloody hack.\n\t\t\t\t\t\tNameEdit.Set_Focus();\n\t\t\t\t\t\tKeyboard->Clear();\n\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PATCHAVOIDED:\n\t\t\t\t\t\tbBreak = true;\n\t\t\t\t\t\tfirsttime = true;\t\t//\tBloody hack.\n\t\t\t\t\t\tNameEdit.Set_Focus();\n\t\t\t\t\t\tKeyboard->Clear();\n\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PATCHDOWNLOADED:\n\t\t\t\t\t\tbBreak = true;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tiReturn = -1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif( bBreak )\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//\tRequestConnection()...\n\t\t\t\tHRESULT hRes = pWO->AttemptLogin( szNameBuffer, szPassBuffer, PassEdit.bClearOnNextSetFocus );\n\t\t\t\tif( hRes == S_OK )\n\t\t\t\t{\n\t\t\t\t\tif( SaveCheckBox.IsOn && !bSaveNick( pWO, szNameBuffer, szPassBuffer, PassEdit.bClearOnNextSetFocus ) )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tNick/pass save failed.\n\t\t\t\t\t\tWWMessageBox().Process( TXT_WOL_CANTSAVENICK );\n\t\t\t\t\t}\n\t\t\t\t\tprocess = false;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tswitch( hRes )\n\t\t\t\t\t{\n\t\t\t\t\tcase USERCANCELLED:\n\t\t\t\t\t\tWWMessageBox().Process( TXT_WOL_LOGINCANCEL );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CHAT_E_TIMEOUT:\n\t\t\t\t\t\tWWMessageBox().Process( TXT_WOL_TIMEOUT );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CHAT_E_BADPASS:\n\t\t\t\t\t\tWWMessageBox().Process( TXT_WOL_BADPASS );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CHAT_E_NICKINUSE:\n\t\t\t\t\t\tWWMessageBox().Process( TXT_WOL_NICKINUSE );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CHAT_E_CON_ERROR:\n\t\t\t\t\t\t//\tThis error value I pass back myself, when the emergency timeout is hit.\n\t\t\t\t\t\tWWMessageBox().Process( TXT_WOL_TIMEOUT );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tfirsttime = true;\t\t//\tBloody hack.\n\t\t\t\t\tNameEdit.Set_Focus();\n\t\t\t\t\tKeyboard->Clear();\n\t\t\t\t\tdisplay = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n/*\n\t\t\tcase( EDITBOX_PASS | KN_BUTTON ):\n\t\t\t{\n\t\t\t\t//\tMessage with delay so that user has time to read it...\n\t\t\t\tCDTimerClass<SystemTimerClass> timer;\n\t\t\t\ttimer = TICKS_PER_SECOND*4;\n\t\t\t\tWWMessageBox().Process(TXT_WOL_DEBUG2, TXT_NONE);\n\t\t\t\twhile (timer > 0) {\n\t\t\t\t\tCall_Back();\n\t\t\t\t}\n\t\t\t\tKeyboard->Clear();\n\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\t\t\t}\n*/\n\t\t\tcase ( LISTBOX_NICKS | KN_BUTTON ):\n\t\t\t\tstrcpy( szNameBuffer, NickList.Get_Item( NickList.Current_Index() ) );\n\t\t\t\tstrcpy( szPassBuffer, NickList.Get_Item_ExtraDataString( NickList.Current_Index() ) );\n\t\t\t\tNameEdit.Flag_To_Redraw();\n\t\t\t\tPassEdit.Flag_To_Redraw();\n\t\t\t\t//\tBecause the password is mangled, if the user begins to edit it now, we clear it.\n\t\t\t\t//\tOtherwise we could get a half-mangled, half-unmangled password field.\n\t\t\t\t//\tPassEdit.bClearOnNextSetFocus also acts as a flag telling us whether or not the\n\t\t\t\t//\tpassword field is mangled or not.\n\t\t\t\tPassEdit.bClearOnNextSetFocus = true;\n//\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_SAVECHECK | KN_BUTTON ):\n\t\t\t\tbreak;\n\n\t\t\tcase ( BUTTON_DELETE | KN_BUTTON ):\n\t\t\t\tif( NickList.Count() > 0 )\n\t\t\t\t{\n\t\t\t\t\tDeleteNick( pWO, NickList.Current_Index() + 1 );\n\t\t\t\t\tNickList.Remove_Item( NickList.Current_Index() );\n\t\t\t\t\tNickList.Flag_To_Redraw();\n\t\t\t\t\tif( NickList.Count() == 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\tDeleteBtn.Disable();\n\t\t\t\t\t\tDeleteBtn.Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn iReturn;\n}\n\n//***********************************************************************************************\nbool ReadSavedNicks( WolapiObject* pWO, IconListClass& NickList, char* szNameBuffer, char* szPassBuffer )\n{\n\t//\tRead saved nickname/passwords from the registry.\n\t//\tSet up the list of nick/passwords.\n\t//\tCopy the first nick into the nick/password edits.\n\n\t//\tReturns true if edits are set with a default nick/pass because a nick was found.\n\n\tLPCSTR szNick;\n\tLPCSTR szPass;\n\tbool bReturn = false;\n\n\tfor( int i = 1; i != 3; i++ )\n\t{\n\t\tif( pWO->pChat->GetNick( i, &szNick, &szPass ) == S_OK )\n\t\t{\n\t\t\tif( *szNick )\n\t\t\t{\n\t\t\t\tNickList.Add_Item( szNick, NULL, NULL, ICON_SHAPE, szPass );\n\t\t\t\tif( i == 1 )\n\t\t\t\t{\n\t\t\t\t\tstrcpy( szNameBuffer, szNick );\n\t\t\t\t\tstrcpy( szPassBuffer, szPass );\n\t\t\t\t\tbReturn = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn bReturn;\n}\n\n//***********************************************************************************************\nbool bSaveNick( WolapiObject* pWO, const char* szNickToSave, const char* szPassToSave, bool bPassIsMangled )\n{\n\t//\tSaves specified nick and password in the registry, using SetNick.\n\t//\tReturns false if nick can't be saved.\n\t\n\t//\tIf slot 1 empty, use slot 1.\n\t//\tElse push nick 1 down to second slot and save new nick in slot 1, unless\n\t//\tnick 1 name matches new entry.\n\n\tLPCSTR szNick;\n\tLPCSTR szPass;\n\tbool bPushSlot1 = true;\n\n\tswitch( pWO->pChat->GetNick( 1, &szNick, &szPass ) )\n\t{\n\tcase E_FAIL:\n\t\t//\tAssume that this is because there is no registry entry. We can use this slot.\n\t\tbPushSlot1 = false;\n\t\tbreak;\n\tcase S_OK:\n\t\tif( *szNick == 0 )\n\t\t\tbPushSlot1 = false;\t\t\t//\tWe can use this blank slot.\n\t\telse\n\t\t\tif( strcmp( szNick, szNickToSave ) == 0 )\n\t\t\t\tbPushSlot1 = false;\t\t//\tWe can use this slot as the name is the same.\n\t\tbreak;\n\t}\n\n\tif( bPushSlot1 )\n\t{\n\t\t//\tMove nick in slot 1 to slot 2.\n\t\tpWO->pChat->SetNick( 2, szNick, szPass, false );\t//\t(Already mangled.)\n\t}\n\n\t//\tSave new nick in slot 1.\n\treturn ( pWO->pChat->SetNick( 1, szNickToSave, szPassToSave, !bPassIsMangled ) == S_OK );\n\n/*\n\tint iSlot;\n\tbool bStop = false;\n\tfor( iSlot = 1; iSlot != 3; iSlot++ )\n\t{\n\t\tswitch( pWO->pChat->GetNick( iSlot, &szNick, &szPass ) )\n\t\t{\n\t\tcase E_FAIL:\n\t\t\t//\tAssume that this is because there is no registry entry. We can use this slot.\n\t\t\tbStop = true;\n\t\t\tbreak;\n\t\tcase S_OK:\n\t\t\tif( *szNick == 0 )\n\t\t\t\tbStop = true;\t\t//\tWe can use this blank slot.\n\t\t\telse\n\t\t\t\tif( strcmp( szNick, szNickToSave ) == 0 )\n\t\t\t\t\tbStop = true;\t//\tWe can use this slot as the name is the same.\n\t\t\tbreak;\n\t\t}\n\t\tif( bStop )\n\t\t\tbreak;\n\t}\n\tif( iSlot == 3 )\n\t{\n\t\t//\tNo open slots were found.\n\t\t//\tGet nick 1.\n\t\tpWO->pChat->GetNick( 1, &szNick, &szPass );\n\t\t//\tSave as nick 2.\n\t\tpWO->pChat->SetNick( 2, szNick, szPass, false );\t//\t(Already mangled.)\n\t\t//\tSave new nick 1.\n\t\treturn ( pWO->pChat->SetNick( 1, szNickToSave, szPassToSave, !bPassIsMangled ) == S_OK );\n\t}\n\telse\n\t{\n\t\t//\tiSlot points to an open slot.\n\t\treturn ( pWO->pChat->SetNick( iSlot, szNickToSave, szPassToSave, !bPassIsMangled ) == S_OK );\n\t}\n*/\n}\n\n//***********************************************************************************************\nvoid DeleteNick( WolapiObject* pWO, int iOneBasedEntryToDelete )\n{\n\t//\tDelete a nick from the registry via wolapi SetNick.\n\t//\tIf nick to delete is in position one, and there is a second nick, move the second nick into position one.\n\tif( iOneBasedEntryToDelete == 1 )\n\t{\n\t\t//\tCheck for nick 2.\n\t\tLPCSTR szNick;\n\t\tLPCSTR szPass;\n\t\tif( pWO->pChat->GetNick( 2, &szNick, &szPass ) == S_OK && *szNick != 0 )\n\t\t{\n\t\t\t//\tCopy nick in slot 2 to slot 1.\n\t\t\tpWO->pChat->SetNick( 1, szNick, szPass, false );\t//\t(Already mangled.)\n\t\t\t//\tDelete slot 2.\n\t\t\tHRESULT hRes = pWO->pChat->SetNick( 2, \"\", \"\", false );\n\t\t\tDebugChatDef( hRes );\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//\tNo second nick.\n\t\t\tHRESULT hRes = pWO->pChat->SetNick( 1, \"\", \"\", false );\n\t\t\tDebugChatDef( hRes );\n\t\t}\n\t}\n\telse\n\t{\n\t\tHRESULT hRes = pWO->pChat->SetNick( 2, \"\", \"\", false );\n\t\tDebugChatDef( hRes );\n\t}\n}\n\n/*\n//***********************************************************************************************\nchar* LoadShpFile( const char* szShpFile )\n{\n\t//\tReturns pointer to shp data that has been new'ed (and must be delete[]d), or NULL if failure.\n\t//\tajw: No longer needed - I used this before putting new resources into a mix file.\n\tHANDLE hFile;\n\thFile = CreateFile( szShpFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\n\tif( hFile == INVALID_HANDLE_VALUE )\n\t\treturn NULL;\n\tDWORD dwFileSize = GetFileSize( hFile, NULL );\n\tchar* pShp = new char[ dwFileSize ];\n\tDWORD dwBytesRead;\n\tReadFile( hFile, pShp, dwFileSize, &dwBytesRead, NULL );\n//\tdebugprint( \"~~ LoadShpFile() - Read %i bytes out of %i from shp file.\\n\", dwBytesRead, dwFileSize );\n\tCloseHandle( hFile );\n\treturn pShp;\n}\n*/\n\n#endif\n"
  },
  {
    "path": "CODE/WOL_MAIN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifdef WOLAPI_INTEGRATION\n\n//\tWol_Main.cpp - Bottom level wolapi-stuff function.\n//\tajw 07/16/98\n\n#include \"function.h\"\n#include \"WolapiOb.h\"\n#include \"wol_gsup.h\"\n#include \"WolStrng.h\"\n\nint WOL_Login_Dialog( WolapiObject* pWolapi );\nint WOL_Chat_Dialog( WolapiObject* pWolapi );\nconst char* Game_Registry_Key();\n\nbool ReregisterWolapiDLL();\nvoid HandleDLLFail();\n\nWolapiObject* pWolapi = NULL;\n\n#include \"WolDebug.h\"\n\n//***********************************************************************************************\n//\tThe first time through, pWolapi is NULL thus wolapi gets set up. WOL_Login_Dialog presents the user\n//\twith the login dialog and attempts to log us on to the server. If the user continues on all the\n//\tway to a game start, we will drop out of here with pWolapi still pointing to a valid WolapiObject,\n//\tand with pWolapi's iLobbyReturnAfterGame set to the number of the lobby to return to automatically \n//\tafter the game ends.\n//\tInit() automatically brings us here if pWolapi is non-null.\n//***********************************************************************************************\nint WOL_Main()\n{\n\t//\tReturn values:\n\t//\t\t0 = cancel\n\t//\t\t1 = start game\n\t//\t\t-1 = patch downloaded, shut down app\n\tint iReturn = 0;\n\n\tif( pWolapi )\n\t{\n\t\t//\tWe have returned from a game started through ww online.\n\t\t\n\t\t//\tStart theme up again.\n\t\tTheme.Play_Song( THEME_INTRO );\n\n\t\t//\tVerify that we are still connected. If we aren't, kill WolapiObject and start over.\n\t\t//\t(This will likely occur during the game, if connection is lost. Ensure that it is done here.)\n\t\tpWolapi->pChat->PumpMessages();\t\t\t//\tCauses OnNetStatus() call if no longer connected.\n\t\tif( pWolapi->bConnectionDown )\n\t\t{\n//debugprint( \"Re-entering WOL_Main(), pWolapi->bConnectionDown is true. Deleting old WolapiObject...\\n\" );\n\t\t\tWWMessageBox().Process( TXT_WOL_WOLAPIREINIT );\n\t\t\t//\tKill wolapi.\n\t\t\tpWolapi->UnsetupCOMStuff();\n\t\t\tdelete pWolapi;\n\t\t\tpWolapi = NULL;\n\t\t}\n\t}\n\n\tif( !pWolapi )\n\t{\n\t\t//\tStart up wolapi.\n\t\tpWolapi = new WolapiObject;\n\t\tif( !pWolapi->bSetupCOMStuff() )\n\t\t{\n\t\t\t//\tThings are really bad if this happens. A COM call failed.\n\t\t\t\n\t\t\t//\tWe first assume that their wolapi.dll failed to register during wolsetup.exe, part of the patch process.\n\t\t\t//\tThis happens if they have an outdated oleaut32.dll, such as the one that comes with original\n\t\t\t//\tversion of Windows 95.\n\n//\t\t\tdebugprint( \"bSetupCOMStuff failed. Attemping to reregister wolapi.dll...\\n\" );\n\t\t\t//\tAttempt to re-register wolapi.dll...\n\t\t\tif( ReregisterWolapiDLL() )\n\t\t\t{\n\t\t\t\tif( !pWolapi->bSetupCOMStuff() )\n\t\t\t\t{\n\t\t\t\t\t//\tStill failed after reregistering seemed to work.\n\t\t\t\t\tHandleDLLFail();\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tHandleDLLFail();\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t\tpWolapi->PrepareButtonsAndIcons();\n\t\t//\tUndocumented hack needed for patch downloading, per Neal.\n\t\tpWolapi->pChat->SetAttributeValue( \"RegPath\", Game_Registry_Key() );\n\t\t//\t(Not that anything's really \"documented\".)\n\t}\n\n\tpWolapi->bInGame = false;\n\n\tint iLoginResult = WOL_Login_Dialog( pWolapi );\n\tif( iLoginResult == 1 )\n\t{\n\t\tpWolapi->SetOptionDefaults();\n\t\tbool bKeepGoing = true;\n\t\twhile( bKeepGoing )\n\t\t{\n\t\t\tbool bCreator;\n\t\t\tswitch( WOL_Chat_Dialog( pWolapi ) )\n\t\t\t{\n\t\t\tcase -1:\n\t\t\t\tbKeepGoing = false;\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\t//\tUser created game channel.\n\t\t\t\tbCreator = true;\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\t//\tUser joined game channel.\n\t\t\t\tbCreator = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif( bKeepGoing )\n\t\t\t{\n\t\t\t\tWOL_GameSetupDialog GSupDlg( pWolapi, bCreator );\n\t\t\t\tswitch( GSupDlg.Run() )\n\t\t\t\t{\n\t\t\t\tcase RESULT_WOLGSUP_LOGOUT:\n\t\t\t\t\t//\tUser logged out.\n\t\t\t\t\tbKeepGoing = false;\n\t\t\t\t\tbreak;\n\t\t\t\tcase RESULT_WOLGSUP_BACKTOCHAT:\n\t\t\t\tcase RESULT_WOLGSUP_HOSTLEFT:\n\t\t\t\tcase RESULT_WOLGSUP_RULESMISMATCH:\n\t\t\t\t\t//\tReturn to chat.\n\t\t\t\t\tbreak;\n\t\t\t\tcase RESULT_WOLGSUP_STARTGAMEHOST:\n\t\t\t\t\t//\tProceed with game.\n\t\t\t\t\tbKeepGoing = false;\n\t\t\t\t\tiReturn = 1;\n\t\t\t\t\tpWolapi->bGameServer = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase RESULT_WOLGSUP_STARTGAME:\n\t\t\t\t\t//\tProceed with game.\n\t\t\t\t\tbKeepGoing = false;\n\t\t\t\t\tiReturn = 1;\n\t\t\t\t\tpWolapi->bGameServer = false;\n\t\t\t\t\tbreak;\n\t\t\t\tcase RESULT_WOLGSUP_FATALERROR:\n//\t\t\t\t\tdebugprint( \"RESULT_WOLGSUP_FATALERROR from game setup dialog.\\n\" );\n//\t\t\t\t\tFatal( \"RESULT_WOLGSUP_FATALERROR from game setup dialog.\\n\" );\n\t\t\t\t\tif( pWolapi->pChatSink->bConnected )\n\t\t\t\t\t\tpWolapi->Logout();\n\t\t\t\t\tbKeepGoing = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif( iReturn != 1 )\n\t{\n\t\t//\tKill wolapi.\n\t\tpWolapi->UnsetupCOMStuff();\n\t\tdelete pWolapi;\n\t\tpWolapi = NULL;\n\t}\n\telse\n\t{\n\t\tpWolapi->bInGame = true;\n\t\tpWolapi->bConnectionDown = false;\n\t}\n\n\tif( iLoginResult == -1 )\n\t{\n\t\tWWMessageBox().Process( TXT_WOL_DOWNLOADEXITWARNING );\n\t\tiReturn = -1;\n\t}\n\n\treturn iReturn;\n}\n\n//***********************************************************************************************\nbool ReregisterWolapiDLL()\n{\n\t//\tAttempt to reregister wolapi.dll.\n\t//\tReturns true if we think we succeeded.\n\tHKEY hKey;\n\tchar szInstallPath[ _MAX_PATH ];\n\tif( ::RegOpenKeyEx( HKEY_LOCAL_MACHINE, \"Software\\\\Westwood\\\\WOLAPI\", 0, KEY_READ, &hKey ) == ERROR_SUCCESS )\n\t{\n\t\tDWORD dwBufSize = _MAX_PATH;\n\t\tif( ::RegQueryValueEx( hKey, \"InstallPath\", 0, NULL, (LPBYTE)szInstallPath, &dwBufSize ) == ERROR_SUCCESS )\n\t\t{\n\t\t\tWIN32_FIND_DATA wfd;\n\t\t\tHANDLE handle = FindFirstFile( szInstallPath, &wfd );\n\t\t\tif( handle == INVALID_HANDLE_VALUE )\n\t\t\t{\n\t\t\t\t//\tFile is not there.\n\t\t\t\tFindClose( handle );\n\t\t\t\t::RegCloseKey( hKey );\n\t\t\t\treturn false;\n\t\t\t}\n//\t\t\tdebugprint( \"Found dll -> %s\\n\", szInstallPath );\n\t\t\t//\tGet the DLL to register itself.\n\t\t\tHINSTANCE hLib = LoadLibrary( szInstallPath );\n\t\t\tif( !hLib )\n\t\t\t{\n//\t\t\t\tdebugprint( \"LoadLibrary failed, GetLastError is %i\\n\", GetLastError() );\n\t\t\t\t::RegCloseKey( hKey );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tFARPROC lpDllRegisterFunction = GetProcAddress( hLib, \"DllRegisterServer\" );\n\t\t\tif( !lpDllRegisterFunction )\n\t\t\t{\n\t\t\t\t::RegCloseKey( hKey );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif( lpDllRegisterFunction() != S_OK )\n\t\t\t{\n\t\t\t\t::RegCloseKey( hKey );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t//\tThere is a bug in wolapi.dll that makes the following delay necessary.\n\t\t\t//\tSomething about Neal's extra threads only getting half-way set up before they get deleted.\n\t\t\t//\t(The extra threads shouldn't really be created in this case, anyway...)\n\t\t\t::Sleep( 1000 );\n\t\t\tFreeLibrary( hLib );\n\t\t\tFindClose( handle );\n\t\t}\n\t\telse\n\t\t{\n\t\t\t::RegCloseKey( hKey );\n\t\t\treturn false;\n\t\t}\n\t\t::RegCloseKey( hKey );\n\t}\n\telse\n\t{\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n//***********************************************************************************************\nvoid HandleDLLFail()\n{\n\t//\tThe DLL failed to load. Either we failed to reregister it, or we think we succeeded at this but it\n\t//\tstill is not working. Show an error message and delete pWolapi.\n\t//\tWe show either \"call tech support\" or \"download IE3\", depending on whether oleaut32.dll looks out of date.\n\n\tchar szPath[ _MAX_PATH + 1 ];\n\t::GetSystemDirectory( szPath, _MAX_PATH );\n\tif( *szPath && szPath[ strlen( szPath ) - 1 ] != '\\\\' )\n\t\tstrcat( szPath, \"\\\\\" );\n\n\tstrcat( szPath, \"oleaut32.dll\" );\n\n\tWIN32_FIND_DATA wfd;\n\tHANDLE handle = FindFirstFile( szPath, &wfd );\n\n//\tdebugprint( \"HandleDLLFail(): filesize of oleaut32 is %i\\n\", wfd.nFileSizeLow );\n\tif( handle != INVALID_HANDLE_VALUE && wfd.nFileSizeLow <= 232720 )\n\t\tWWMessageBox().Process( TXT_WOL_DLLERROR_GETIE3 );\n\telse\n\t\tWWMessageBox().Process( TXT_WOL_DLLERROR_CALLUS );\n\n\tFindClose( handle );\n\n\tdelete pWolapi;\n\tpWolapi = NULL;\n}\n\n#endif\n"
  },
  {
    "path": "CODE/WOL_OPT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifdef WOLAPI_INTEGRATION\n\n//\tWol_Opt.cpp - WW online options dialog.\n//\tajw 09/1/98\n\n#include \"function.h\"\n\n#include \"IconList.h\"\n#include \"WolapiOb.h\"\n#include \"WolStrng.h\"\n#include \"BigCheck.h\"\n//#include \"WolDebug.h\"\n\nextern bool cancel_current_msgbox;\n\n//***********************************************************************************************\nbool WOL_Options_Dialog( WolapiObject* pWO, bool bCalledFromGame )\n{\n\t//\tReturns true only if called from inside game, and the game ended on us unexpectedly.\n\tbool bReturn = false;\n\n\tbool bEscapeDown = false;\n\tbool bReturnDown = false;\n\n\tbool bIgnoreReturnDown = false;\n\tif( ( ::GetAsyncKeyState( VK_RETURN ) & 0x8000 ) )\n\t{\n\t\t//\tThe return key is already down, as we enter the dialog.\n\t\t//\tUntil it comes up again, ignore this fact, so that we don't act on a return press that's not valid.\n\t\tbIgnoreReturnDown = true;\n\t}\n\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n#ifdef GERMAN\n\tint d_list_w = 180 * RESFACTOR;\n#else\n#ifdef FRENCH\n\tint d_list_w = 165 * RESFACTOR;\n#else\n\tint d_list_w = 165 * RESFACTOR;\n#endif\n#endif\n\n\tint d_dialog_w = d_list_w + 40 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 90 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = (((320 * RESFACTOR) - d_dialog_w) / 2);\n\tint d_dialog_y = (((200 * RESFACTOR) - d_dialog_h) / 2);\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// coord of x-center\n\n\tint d_txt8_h = 11 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// ht of 8-pt text\n\tint d_margin = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\tint x_margin = 16 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint top_margin = 0;\n\n//\tint d_list_w = 100 * RESFACTOR;\n\tint d_list_h = 7 * RESFACTOR;\n\tint d_list_x = d_dialog_cx - d_list_w / 2;\n\tint d_list_y = d_dialog_y + d_margin + 24;\n\n#if (GERMAN | FRENCH)\n\tint d_ok_w = 40 * RESFACTOR;\n#else\n\tint d_ok_w = 40 * RESFACTOR;\n#endif\n\tint d_ok_h = 13 * RESFACTOR;\n\tint d_ok_x = d_dialog_cx - d_ok_w / 2;\n\tint d_ok_y = d_dialog_y + d_dialog_h - d_ok_h - d_margin;\n\n\t/*\n\t**\tButton enumerations\n\t*/\n\tenum {\n\t\tBUTTON_OK = 100,\n\t\tCHECK_FIND,\n\t\tCHECK_PAGE,\n\t\tCHECK_LANGUAGE,\n\t\tCHECK_ALLGAMES,\n\t\tCHECK_RANKAM,\n\t};\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass* commands = NULL;\t\t// the button list\n\n\tTextButtonClass OkBtn( BUTTON_OK, TXT_OK, TPF_BUTTON, d_ok_x, d_ok_y, d_ok_w );\n\n\tBigCheckBoxClass FindCheck( CHECK_FIND, d_list_x, d_list_y, d_list_w, d_list_h, \n\t\t\t\t\t\t\t\tTXT_WOL_OPTFIND, TPF_6PT_GRAD | TPF_NOSHADOW, pWO->bFindEnabled );\n\tBigCheckBoxClass PageCheck( CHECK_PAGE, d_list_x, d_list_y + d_list_h + 2, d_list_w, d_list_h, \n\t\t\t\t\t\t\t\tTXT_WOL_OPTPAGE, TPF_6PT_GRAD | TPF_NOSHADOW, pWO->bPageEnabled );\n\tBigCheckBoxClass LanguageCheck( CHECK_LANGUAGE, d_list_x, d_list_y + 2 * ( d_list_h + 2 ), d_list_w, d_list_h, \n\t\t\t\t\t\t\t\t\tTXT_WOL_OPTLANGUAGE, TPF_6PT_GRAD | TPF_NOSHADOW, pWO->bLangFilter );\n\tBigCheckBoxClass GamescopeCheck( CHECK_ALLGAMES, d_list_x, d_list_y + 3 * ( d_list_h + 2 ), d_list_w, d_list_h, \n\t\t\t\t\t\t\t\t\tTXT_WOL_OPTGAMESCOPE, TPF_6PT_GRAD | TPF_NOSHADOW, !pWO->bAllGamesShown );\n\tBigCheckBoxClass RankAMCheck( CHECK_RANKAM, d_list_x, d_list_y + 4 * ( d_list_h + 2 ), d_list_w, d_list_h, \n\t\t\t\t\t\t\t\t\tTXT_WOL_OPTRANKAM, TPF_6PT_GRAD | TPF_NOSHADOW, !pWO->bShowRankRA );\n\n\t/*\n\t**\tInitialize.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tCreate the button list.\n\t*/\n\tcommands = &OkBtn;\n\tFindCheck.Add_Tail(*commands);\n\tPageCheck.Add_Tail(*commands);\n\tLanguageCheck.Add_Tail(*commands);\n\tGamescopeCheck.Add_Tail(*commands);\n\tRankAMCheck.Add_Tail(*commands);\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tKeyboard->Clear();\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tif( !bCalledFromGame )\n\t\t\tCall_Back();\n\t\telse\n\t\t{\n\t\t\tif( Main_Loop() )\t//\tGame ended on us in the background.\n\t\t\t{\n\t\t\t\tprocess = false;\n\t\t\t\tbReturn = true;\n\t\t\t}\n\t\t}\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = true;\n\t\t}\n\t\t#endif\n\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\n\t\t\t/*\n\t\t\t**\tDisplay the dialog box.\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\t\t\tDraw_Caption( TXT_WOL_OPTTITLE, d_dialog_x, d_dialog_y, d_dialog_w );\n\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t//\tForce mouse visible, as some beta testers report unexplicable disappearing cursors.\n\t\twhile( Get_Mouse_State() )\n\t\t\tShow_Mouse();\n\t\t//\tBe nice to other apps.\n\t\tSleep( 50 );\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t//\tMy hack for triggering escape and return on key up instead of down...\n\t\t//\tThe problem that was occurring was that the calling dialog would act on the key up,\n\t\t//\tthough this dialog handled the key down. ajw\n\t\tif( ( ::GetAsyncKeyState( VK_ESCAPE ) & 0x8000 ) )\n\t\t{\n\t\t\tbEscapeDown = true;\n\t\t}\n\t\telse if( bEscapeDown )\n\t\t{\n\t\t\tinput = (KeyNumType)( BUTTON_OK | KN_BUTTON );\n\t\t\tbEscapeDown = false;\n\t\t}\n\t\tif( ( ::GetAsyncKeyState( VK_RETURN ) & 0x8000 ) )\n\t\t{\n\t\t\tif( !bIgnoreReturnDown )\n\t\t\t\tbReturnDown = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbIgnoreReturnDown = false;\n\t\t\tif( bReturnDown )\n\t\t\t{\n\t\t\t\tinput = (KeyNumType)( BUTTON_OK | KN_BUTTON );\n\t\t\t\tbReturnDown = false;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tProcess input.\n\t\t*/\n\n\t\tif( cancel_current_msgbox )\n\t\t{\n\t\t\tcancel_current_msgbox = false;\n\t\t\tinput = (KeyNumType)( BUTTON_OK | KN_BUTTON );\n\t\t}\n\t\tswitch( input )\n\t\t{\n\t\t\tcase ( BUTTON_OK | KN_BUTTON ):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase ( CHECK_FIND | KN_BUTTON ):\n\t\t\tcase ( CHECK_PAGE | KN_BUTTON ):\n\t\t\tcase ( CHECK_LANGUAGE | KN_BUTTON ):\n\t\t\tcase ( CHECK_ALLGAMES | KN_BUTTON ):\n\t\t\t\tpWO->SetOptions( FindCheck.IsOn, PageCheck.IsOn, LanguageCheck.IsOn, !GamescopeCheck.IsOn );\n\t\t\t\tbreak;\n\n\t\t\tcase ( CHECK_RANKAM | KN_BUTTON ):\n\t\t\t\tpWO->bShowRankRA = !RankAMCheck.IsOn;\n\t\t\t\tpWO->bMyRecordUpdated = true;\n\t\t\t\tpWO->bShowRankUpdated = true;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn bReturn;\n}\n\n#endif\n"
  },
  {
    "path": "CODE/WRITEPCX.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/WRITEPCX.CPP 1     3/03/97 10:26a Joe_bostic $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : iff                                      *\n *                                                                         *\n *                    File Name : WRITEPCX.CPP                             *\n *                                                                         *\n *                   Programmer : Julio R. Jerez                           *\n *                                                                         *\n *                   Start Date : May 2, 1995                              *\n *                                                                         *\n *                  Last Update : May 2, 1995   [JRJ]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * int Save_PCX_File (char* name, GraphicViewPortClass& pic, char* palette)*\n *= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n#include\t\"function.h\"\n#include \"pcx.h\"\n\n\nstatic void Write_Pcx_ScanLine(FileClass & file, int scansize, char * ptr);\n\n\n/***************************************************************************\n * WRITE_PCX_FILE -- Write the data in ViewPort to a pcx file              *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:  name is a NULL terminated string of the format [xxxx.pcx]\t\t\t*\n *\t\t\t  pic\t is a pointer to a GraphicViewPortClass or to a \t\t\t\t*\n *\t\t\t\t\t GraphicBufferClass holding the picture. \t\t\t\t\t\t\t*\n *        palette is a pointer the the memory block holding the color \t\t*\n *              palette of the picture.                                    *\n *                                                                         *\n * OUTPUT: FALSE  if the function fails zero otherwise             \t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/04/1995 JRJ : Created.                                             *\n *   08/01/1995 SKB : Copy the palette so it is not modified.              *\n *   06/03/1996 JLB : Converted to C++ and file class I/O.                 *\n *=========================================================================*/\n\nstatic const unsigned char rle_code = 0xC0;\t\t\t\t\t// Run code.\nstatic const unsigned char rle_max_run = 0x2F;\t\t\t\t// Maximum run allowed.\nstatic const unsigned char rle_full_run = (rle_max_run|rle_code);\t// Full character run.\n\n\n/***********************************************************************************************\n * Write_PCX_File -- Write a PCX file from specified buffer.                                   *\n *                                                                                             *\n *    This routine will take the specified buffer and write out the data as a PCX file to the  *\n *    the file object specified.                                                               *\n *                                                                                             *\n * INPUT:   file     -- Reference to the file object to write the buffer as a PCX file.        *\n *                                                                                             *\n *          pic      -- Reference to a graphic buffer that contains the data to be written.    *\n *                                                                                             *\n *          palette  -- Reference to the palette to be attached to the PCX file as well.       *\n *                                                                                             *\n * OUTPUT:  bool; Was there an error?                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Write_PCX_File(FileClass & file, GraphicBufferClass & pic, PaletteClass * palette)\n{\n \tunsigned char palcopy[256 * sizeof(RGB)];\n\tint\tVP_Scan_Line;\n\tchar\t* ptr;\n\tRGB\t* pal;\n\tPCX_HEADER header = {\n\t\t10,\n\t\t5,\n\t\t1,\n\t\t8,\n\t\t0,\n\t\t0,\n\t\t(short)(pic.Get_Width()-1),\n\t\t(short)(pic.Get_Height()-1),\n\t\t(short)(pic.Get_Width()),\n\t\t(short)(pic.Get_Height()),\n\t\t{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},\n\t\t0,\n\t\t1,\n\t\t(short)pic.Get_Width(),\n\t\t1,\n\t\t{0}\n\t};\n\n\t/*\n\t**\tOpen the output file and write out the header information. If the file\n\t**\tis already open, then just presume that it is positioned correctly and is\n\t**\topen for write.\n\t*/\n\tbool open = false;\n\tif (!file.Is_Open()) {\n\t\tfile.Open(WRITE);\n\t\topen = true;\n\t}\n\tfile.Write(&header, sizeof(header));\n\n\t/*\n\t**\tWrite out the picture, line by line.\n\t*/\n\tVP_Scan_Line = pic.Get_Width() + pic.Get_XAdd();\n\tptr = (char *)pic.Get_Buffer() ;\n\tptr += ((pic.Get_YPos() * VP_Scan_Line) + pic.Get_XPos());\n\tfor (int line = 0; line < header.height + 1; line++) {\n   \tWrite_Pcx_ScanLine(file, header.byte_per_line, ptr + line * VP_Scan_Line ) ;\n\t}\n\n\t/*\n\t**\tSpecial marker for end of RLE data.\n\t*/\n\tunsigned char ender = 0x0C;\n\tfile.Write(&ender, sizeof(ender));\n\n\t/*\n\t**\tConvert the palette from 6 bit to 8 bit format.\n\t*/\n\tmemmove(palcopy, palette, sizeof(PaletteClass));\n\tpal = (RGB *)palcopy ;\n\tfor (int palindex = 0; palindex < 256; palindex++) {\n\t\tpal->red = (unsigned char)((pal->red<<2)); // | (pal->red>>6));\n\t\tpal->green = (unsigned char)((pal->green<<2)); // | (pal->green>>6));\n\t\tpal->blue = (unsigned char)((pal->blue<<2)); // | (pal->blue>>6));\n\t\tpal++;\n\t}\n\n\t/*\n\t**\tWrite the palette out.\n\t*/\n\tfile.Write(palcopy, sizeof(palcopy));\n\n\t/*\n\t**\tClose the file (if necessary) and exit with no error flag.\n\t*/\n\tif (open) {\n\t\tfile.Close();\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * Write_Pcx_ScanLine -- Writes a PCX scanline.                                                *\n *                                                                                             *\n *    Writes out a PCX scanline using RLE compression.                                         *\n *                                                                                             *\n * INPUT:   file     -- Reference to the file to write the scan line to.                       *\n *                                                                                             *\n *          scansize -- The number of bytes to compress (write).                               *\n *                                                                                             *\n *          ptr      -- Pointer to the data to compress (write).                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/04/1995 JRJ : Created.                                                                 *\n *   06/03/1996 JLB : Converted to C++ and file class I/O.                                     *\n *=============================================================================================*/\nstatic void Write_Pcx_ScanLine(FileClass & file, int scansize, char * ptr)\n{\n\tunsigned char last = *ptr;\n\tunsigned char rle=1;\n\tunsigned char c;\n\tfor (int i = 1; i < scansize; i++) {\n   \tunsigned char color = (unsigned char)(0xff & * ++ptr);\n\t\tif (color == last) {\n\t\t\trle++;\n\t\t\tif (rle == rle_max_run) {\n\t\t\t\tfile.Write(&rle_full_run, sizeof(rle_full_run));\n\t\t\t\tfile.Write(&color, sizeof(color));\n\t\t\t\trle = 0 ;\n\t\t\t}\n\t\t} else {\n\t  \t\tif (rle) {\n\t\t \t\tif (rle == 1 && (rle_code != (rle_code & last))) {\n\t\t\t   \tfile.Write(&last, sizeof(last));\n\t\t     \t} else {\n\t\t\t\t\tc = (unsigned char)(rle | rle_code);\n\t\t      \tfile.Write(&c, sizeof(c));\n\t     \t   \tfile.Write(&last, sizeof(last));\n\t\t\t\t}\n\t\t\t}\n\t\t\tlast = color ;\n\t\t\trle = 1 ;\n\t\t}\n\t}\n\tif (rle) {\n\t\tif (rle == 1 && ( rle_code != (rle_code & last))) {\n\t\t\tfile.Write(&last, sizeof(last));\n\t\t} else {\n\t\t\tc = (unsigned char)(rle | rle_code);\n\t\t\tfile.Write(&c, sizeof(c));\n\t   \tfile.Write(&last, sizeof(last));\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "CODE/WSPIPX.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                     $Archive:: /Sun/WSPIPX.cpp                                             $*\n *                                                                                             *\n *                      $Author:: Joe_b                                                       $*\n *                                                                                             *\n *                     $Modtime:: 8/20/97 10:54a                                              $*\n *                                                                                             *\n *                    $Revision:: 6                                                           $*\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *                                                                                             *\n * IPXInterfaceClass::IPXInterfaceClass -- Class constructor                                   *\n * IPXInterfaceClass::Get_Network_Card_Address -- Get the ID of the installed net card         *\n * IPXInterfaceClass::Open_Socket -- Opens an IPX socket for reading & writing                 *\n * IPXInterfaceClass::Message_Handler -- Handler for windows messages relating to IPX          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"wspipx.h\"\n#include\t\"ipxaddr.h\"\n\n#include\t<assert.h>\n#include\t<stdio.h>\n\n\n/***********************************************************************************************\n * IPXInterfaceClass::IPXInterfaceClass -- Class constructor                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/4/97 11:41AM ST : Created                                                              *\n *=============================================================================================*/\nIPXInterfaceClass::IPXInterfaceClass (void) : WinsockInterfaceClass()\n{\n\t/*\n\t** Set the net and node addressed to their default values.\n\t*/\n\tmemset ( BroadcastNet, 0xff, sizeof (BroadcastNet) );\n\tmemset ( BroadcastNode, 0xff, sizeof (BroadcastNode) );\n\tmemset ( MyNode, 0xff, sizeof (MyNode) );\n}\n\n\n/***********************************************************************************************\n * IPXInterfaceClass::Get_Network_Card_Address -- Get the ID of the installed net card         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    card number to retrieve ID for                                                    *\n *           ptr to addr to return ID in                                                       *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/1/97 3:04PM ST : Created                                                               *\n *=============================================================================================*/\nbool IPXInterfaceClass::Get_Network_Card_Address (int card_number, SOCKADDR_IPX *addr)\n{\n\tint            \tcbOpt;\n\tint\t\t\t\t\tcbAddr = sizeof( SOCKADDR_IPX );\n    SOCKET         \ts;\n    SOCKADDR_IPX   \tAddr;\n    IPX_ADDRESS_DATA  IpxData;\n\n    /*\n\t** Create a temporary IPX socket.\n\t*/\n    s = socket( AF_IPX, SOCK_DGRAM, NSPROTO_IPX );\n\tif ( s == SOCKET_ERROR ) {\n\t\tassert ( s != SOCKET_ERROR );\n\t\treturn (false);\n\t}\n\n\t/*\n\t** Socket must be bound prior to calling IPX_MAX_ADAPTER_NUM\n\t*/\n    memset( &Addr, 0, sizeof( Addr ));\n    Addr.sa_family = AF_IPX;\n    int err = bind( s, (SOCKADDR*) &Addr, cbAddr);\n\tif ( err == SOCKET_ERROR ) {\n\t\tassert ( err != SOCKET_ERROR );\n\t\tclosesocket (s);\n\t\treturn (false);\n\t}\n\n    memset( &IpxData, 0, sizeof(IpxData));\n\n\t/*\n\t** Specify which adapter to check.\n\t*/\n    IpxData.adapternum = card_number;\n    cbOpt = sizeof( IpxData );\n\n\t/*\n\t** Get information for the current adapter.\n\t*/\n    err = getsockopt( s, NSPROTO_IPX, IPX_ADDRESS, (char*) &IpxData, &cbOpt );\n\tif ( err == SOCKET_ERROR ) {\n\t\tassert ( err != SOCKET_ERROR );\n\t\tclosesocket (s);\n\t\treturn (false);\n\t}\n\n\t/*\n\t** IpxData contains the address for the current adapter.\n\t** The network number will be needed later for broadcasts as the net number ff,ff,ff,ff\n\t** doesn't work under NT.\n\t**\n\t** Note: Due to a bug in Win95s implementation of Winsock, only the netnum & nodenum\n\t** values are correctly returned. NT returns all expected values. ST - 7/31/97 0:57AM\n\t*/\n\tmemcpy (addr->sa_netnum, IpxData.netnum, sizeof (addr->sa_netnum));\n\tmemcpy (BroadcastNet, IpxData.netnum, sizeof (addr->sa_netnum));\n\tmemcpy (addr->sa_nodenum, IpxData.nodenum, sizeof (addr->sa_nodenum));\n\n\tclosesocket (s);\n\treturn (true);\n}\n\n\n\n\n\n\n/***********************************************************************************************\n * IPXInterfaceClass::Open_Socket -- Opens an IPX socket for reading & writing                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    SOCKET number to open. This is usually VIRGIN_SOCKET                              *\n *                                                                                             *\n * OUTPUT:   true if socket was opened without error                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/4/97 5:54PM ST : Created                                                               *\n *=============================================================================================*/\nbool IPXInterfaceClass::Open_Socket( SOCKET socketnum )\n{\n\tSOCKADDR_IPX \taddr;\n\tbool\t\t\t\tdelay = true;\n\tint\t\t\t\terr;\n\n\t/*\n\t** If Winsock is not initialised then do it now.\n\t*/\n\tif ( !WinsockInitialised ) {\n\t\tif ( !Init()) return ( false );;\n\t}\n\n\tIPXSocketNumber = socketnum;\n\n\t/*\n\t** Set up the addr structure for the IPX socket\n\t*/\n\taddr.sa_family = AF_IPX;\n\tmemset (addr.sa_netnum, 0, sizeof (addr.sa_netnum));\n\tmemset (addr.sa_nodenum, -1, sizeof (addr.sa_nodenum));\n\taddr.sa_socket = htons ( socketnum );\n\n\t/*\n\t** Create the socket.\n\t*/\n\tSocket = socket (AF_NS, SOCK_DGRAM, NSPROTO_IPX);\n\tif (Socket == INVALID_SOCKET) {\n\t\tchar out[128];\n\t\tsprintf (out, \"TS: Failed to create IPX socket - error code %d.\\n\", GetLastError() );\n\t\tOutputDebugString (out);\n\t\tassert ( Socket != INVALID_SOCKET );\n\t\tclosesocket(Socket);\n\t\treturn ( false );\n\t}\n\n\t/*\n\t** Get the network card address. This is needed so we can bind the socket to the net card.\n\t*/\n\tif ( !Get_Network_Card_Address (0, &addr)){\n\t\tclosesocket ( Socket );\n\t\treturn ( false );\n\t}\n\n\t/*\n\t** Bind the IPX socket to the network card.\n\t*/\n\tif (bind ( Socket, (const struct sockaddr *) &addr, 16) == SOCKET_ERROR ){\n\t\tchar out[128];\n\t\tsprintf (out, \"TS: IPX socket bind failed with error code %d.\\n\", GetLastError() );\n\t\tOutputDebugString (out);\n\t\tassert ( false );\n\t\tclosesocket(Socket);\n\t\treturn ( false );;\n\t}\n\n\n\t/*\n\t** Set the various options for this IPX socket\n\t*/\n\tunsigned long \toptval = true;\n\tint \tpacket_type = 4;\n\n\t/*\n\t** The SO_BROADCAST option allows broadcasting on this socket. This shouldn't be needed\n\t** except for the bug in the Win95 implementation of Winsock which causes broadcasts to\n\t** fail if it isn't set.\n\t*/\n\tif ( setsockopt ( Socket, SOL_SOCKET, SO_BROADCAST, (char*)&optval,\tsizeof(optval) ) == SOCKET_ERROR ) {\n\t\tchar out[128];\n\t\tsprintf (out, \"TS: Failed to set IPX socket option SO_BROADCAST - error code %d.\\n\", GetLastError() );\n\t\tOutputDebugString (out);\n\t\tassert ( false );\n\t}\n\n\t/*\n\t** Set the value in the packet type field for outgoing packets.\n\t*/\n\terr = setsockopt ( Socket, NSPROTO_IPX, IPX_PTYPE, (char*)&packet_type,\tsizeof(packet_type));\n\tif ( err == INVALID_SOCKET ) {\n\t\tchar out[128];\n\t\tsprintf (out, \"TS: Failed to set IPX protocol option IPX_PTYPE - error code %d.\\n\", GetLastError() );\n\t\tOutputDebugString (out);\n\t\tassert ( err != INVALID_SOCKET );\n\t}\n\n\t/*\n\t** Ignore all incoming packets not of this type.\n\t*/\n\terr = setsockopt ( Socket, NSPROTO_IPX, IPX_FILTERPTYPE, (char*)&packet_type,\tsizeof(packet_type));\n\tif ( err == INVALID_SOCKET ) {\n\t\tchar out[128];\n\t\tsprintf (out, \"TS: Failed to set IPX protocol option IPX_FILTERTYPE - error code %d.\\n\", GetLastError() );\n\t\tOutputDebugString (out);\n\t\tassert ( err != INVALID_SOCKET );\n\t}\n\n\t/*\n\t** Set the the base class socket options for buffer sizes.\n\t*/\n\tWinsockInterfaceClass::Set_Socket_Options();\n\n\t/*\n\t** Woohoo!\n\t*/\n\treturn ( true );\n}\n\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * IPXInterfaceClass::Message_Handler -- Handler for windows messages relating to IPX          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Usual windoze message handler stuff                                               *\n *                                                                                             *\n * OUTPUT:   0 if message was handled                                                          *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/4/97 5:55PM ST : Created                                                               *\n *=============================================================================================*/\nlong IPXInterfaceClass::Message_Handler(HWND , UINT message, UINT , LONG lParam)\n{\n\n\tint\t\t\t\t\taddr_len;\t\t// Length of address structure\n\tint\t \t\t\t\trc;\t\t\t\t// Result code\n\tSOCKADDR_IPX \t\taddr;\t\t\t\t// Winsock IPX addressing structure\n\tWinsockBufferType *packet;\t\t\t// Ptr to packet\n\tNetNumType\t\t\tnetnum;\n\tNetNodeType\t\t\tnodenum;\n\n\n\t/*\n\t** We only handle IPX events.\n\t*/\n\tif ( message != WM_IPXASYNCEVENT ) return ( 1 );\n\n\n\tswitch ( WSAGETSELECTEVENT(lParam) ) {\n\n\t\t/*\n\t\t** Read event. Winsock has data it would like to give us.\n\t\t*/\n\t\tcase FD_READ:\n\t\t\t/*\n\t\t\t** Clear any outstanding errors on the socket.\n\t\t\t*/\n\t\t\trc = WSAGETSELECTERROR(lParam);\n\t\t\tif (rc != 0) {\n\t\t\t\tClear_Socket_Error (Socket);\n\t\t\t\treturn(0);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Call the Winsock recvfrom function to get the outstanding packet.\n\t\t\t*/\n\t\t\taddr_len = sizeof(addr);\n\t\t\trc = recvfrom ( Socket, (char*) ReceiveBuffer, sizeof (ReceiveBuffer), 0, (LPSOCKADDR)&addr, &addr_len );\n\t\t\tif (rc == SOCKET_ERROR) {\n\t\t\t\tif (WSAGetLastError() != WSAEWOULDBLOCK) {\n\t\t\t\t\tClear_Socket_Error (Socket);\n\t\t\t\t}\n\t\t\t\treturn(0);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** rc is the number of bytes received from Winsock\n\t\t\t*/\n\t\t\tif ( rc ) {\n\n\t\t\t\t/*\n\t\t\t\t** Make a copy of the address that this packet came from.\n\t\t\t\t*/\n\t\t\t\tmemcpy ( netnum, addr.sa_netnum, sizeof (netnum) );\n\t\t\t\tmemcpy ( nodenum, addr.sa_nodenum, sizeof (nodenum) );\n\n\t\t\t\t/*\n\t\t\t\t** If this packet was from me then ignore it.\n\t\t\t\t*/\n\t\t\t\tif ( !memcmp (netnum, BroadcastNet, sizeof (BroadcastNet)) && !memcmp(nodenum, MyNode, sizeof (MyNode)) ) {\n\t\t\t\t\treturn (0);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Create a new buffer and store this packet in it.\n\t\t\t\t*/\n\t\t\t\tpacket = new WinsockBufferType;\n\t\t\t\tpacket->BufferLen = rc;\n\t\t\t\tmemcpy ( packet->Buffer, ReceiveBuffer, rc );\n\t\t\t\tIPXAddressClass *paddress = (IPXAddressClass*) (&packet->Address[0]);\n\t\t\t\tpaddress->Set_Address ( netnum, nodenum );\n\t\t\t\tInBuffers.Add ( packet );\n\t\t\t}\n\t\t\treturn(0);\n\n\n\t\t/*\n\t\t** Write event. We send ourselves this event when we have more data to send. This\n\t\t** event will also occur automatically when a packet has finished being sent.\n\t\t*/\n\t\tcase FD_WRITE:\n\t\t\t/*\n\t\t\t** Clear any outstanding erros on the socket.\n\t\t\t*/\n\t\t\trc = WSAGETSELECTERROR(lParam);\n\t\t\tif (rc != 0) {\n\t\t\t\tClear_Socket_Error ( Socket );\n\t\t\t\treturn(0);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If there are no packets waiting to be sent then bail.\n\t\t\t*/\n\t\t\twhile ( OutBuffers.Count() != 0 ) {\n\t\t\t\tint packetnum = 0;\n\n\t\t\t\t/*\n\t\t\t\t** Get a pointer to the packet.\n\t\t\t\t*/\n\t\t\t\tpacket = OutBuffers [ packetnum ];\n\n\t\t\t\t/*\n\t\t\t\t** Set up the address structure of the outgoing packet\n\t\t\t\t*/\n\t\t\t\taddr.sa_family = AF_IPX;\n\t\t\t\taddr.sa_socket = htons ( IPXSocketNumber );\n\n\t\t\t\t/*\n\t\t\t\t** Set up the address as either a broadcast address or the given address\n\t\t\t\t*/\n\t\t\t\tif ( packet->IsBroadcast ) {\n\t\t\t\t\tmemcpy ( addr.sa_netnum, BroadcastNet, sizeof (BroadcastNet) );\n\t\t\t\t\tmemcpy ( addr.sa_nodenum, BroadcastNode, sizeof (BroadcastNode) );\n\t\t\t\t}else{\n\t\t\t\t\tIPXAddressClass *paddress = (IPXAddressClass*) (&packet->Address[0]);\n\t\t\t\t\tpaddress->Get_Address ( netnum, nodenum );\n\t\t\t\t\tmemcpy ( addr.sa_netnum, netnum, sizeof (netnum) );\n\t\t\t\t\tmemcpy ( addr.sa_nodenum, nodenum, sizeof (nodenum) );\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Send it.\n\t\t\t\t** If we get a WSAWOULDBLOCK error it means that Winsock is unable to accept the packet\n\t\t\t\t** at this time. In this case, we clear the socket error and just exit. Winsock will\n\t\t\t\t** send us another WRITE message when it is ready to receive more data.\n\t\t\t\t*/\n\t\t\t\trc = sendto ( Socket, (const char*) packet->Buffer, packet->BufferLen, 0, (LPSOCKADDR)&addr, sizeof (addr) );\n\n\t\t\t\tif (rc == SOCKET_ERROR){\n\t\t\t\t\tif (WSAGetLastError() != WSAEWOULDBLOCK) {\n\t\t\t\t\t\tClear_Socket_Error (Socket);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Delete the sent packet.\n\t\t\t\t*/\n\t\t\t\tOutBuffers.Delete ( packetnum );\n\t\t\t\tdelete packet;\n\t\t\t}\n\n\t\t\treturn(0);\n\t}\n\n\treturn (0);\n}\n\n\n"
  },
  {
    "path": "CODE/WSPIPX.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                     $Archive:: /Sun/WSPIPX.h                                               $*\n *                                                                                             *\n *                      $Author:: Joe_b                                                       $*\n *                                                                                             *\n *                     $Modtime:: 8/12/97 5:42p                                               $*\n *                                                                                             *\n *                    $Revision:: 3                                                           $*\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WSPIPX_H\n#define WSPIPX_H\n\n#include\t\"WSProto.h\"\n\n/*\n** Include Windows specific extensions for Winsock that allow IPX over winsock 1.1\n*/\n#include\t<wsipx.h>\n\n/*\n** This file normally resides with the SDK. However, since it needs fixing up before watcom will\n** compile it, it has been incorporated into the project.\n*/\n#include\t\"wsnwlink.h\"\n\n/*\n** IPX interface class. This handles access to the IPX specific portions of the\n** Winsock interface.\n**\n*/\nclass IPXInterfaceClass : public WinsockInterfaceClass {\n\n\tpublic:\n\n\t\tIPXInterfaceClass (void);\n\t\t//virtual ~IPXInterfaceClass(void){Close();};\n\t\tbool Get_Network_Card_Address (int card_number, SOCKADDR_IPX *addr);\n\t \tvirtual long Message_Handler(HWND window, UINT message, UINT wParam, LONG lParam);\n\t\tvirtual bool Open_Socket ( SOCKET socketnum );\n\n\t\tvirtual ProtocolEnum Get_Protocol (void) {\n\t\t\treturn (PROTOCOL_IPX);\n\t\t};\n\n\t\tvirtual int Protocol_Event_Message (void) {\n\t\t\treturn (WM_IPXASYNCEVENT);\n\t\t};\n\n\n\tprivate:\n\t\t/*\n\t\t** The address of the network we will send broadcasts to. Normally you would expect\n\t\t** this to be ff,ff,ff,ff but this fails under NT 4.0. Instead, we can use the network\n\t\t** number of the net that this PC is attached to. This limits broadcasts to the current\n\t\t** network.\n\t\t*/\n\t\tunsigned char\tBroadcastNet[4];\n\n\t\t/*\n\t\t** The node to use as a broadcast address. Normally ff,ff,ff,ff,ff,ff.\n\t\t*/\n\t\tunsigned char\tBroadcastNode[6];\n\n\t\t/*\n\t\t** The id of the network cars in this machine.\n\t\t*/\n\t\tunsigned char\tMyNode[6];\n\n\t\t/*\n\t\t** The socket number to connect with. Normally this will be virgins reserved socket\n\t\t** number - VIRGIN_SOCKET (0x8813).\n\t\t*/\n\t\tSOCKET\t\t\tIPXSocketNumber;\n\n};\n\n\n\n#endif"
  },
  {
    "path": "CODE/WSPROTO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                     $Archive:: /Sun/WSProto.cpp                                            $*\n *                                                                                             *\n *                      $Author:: Joe_b                                                       $*\n *                                                                                             *\n *                     $Modtime:: 8/20/97 10:54a                                              $*\n *                                                                                             *\n *                    $Revision:: 5                                                           $*\n *                                                                                             *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n *  WSProto.CPP WinsockInterfaceClass to provide an interface to Winsock protocols             *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *                                                                                             *\n * WIC::WinsockInterfaceClass -- constructor for the WinsockInterfaceClass                     *\n * WIC::~WinsockInterfaceClass -- destructor for the WinsockInterfaceClass                     *\n * WIC::Close -- Releases any currently in use Winsock resources.                              *\n * WIC::Close_Socket -- Close the communication socket if its open                             *\n * WIC::Start_Listening -- Enable callbacks for read/write events on our socket                *\n * WIC::Stop_Listening -- Disable the winsock event callback                                   *\n * WIC::Discard_In_Buffers -- Discard any packets in our incoming packet holding buffers       *\n * WIC::Discard_In_Buffers -- Discard any packets in our outgoing packet holding buffers       *\n * WIC::Init -- Initialised Winsock and this class for use.                                    *\n * WIC::Read -- read any pending input from the communications socket                          *\n * WIC::WriteTo -- Send data via the Winsock socket                                            *\n * WIC::Broadcast -- Send data via the Winsock socket                                          *\n * WIC::Clear_Socket_Error -- Clear any outstanding erros on the socket                        *\n * WIC::Set_Socket_Options -- Sets default socket options for Winsock buffer sizes             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"WSProto.h\"\n\n#include\t<stdio.h>\n\n\n/***********************************************************************************************\n * WIC::WinsockInterfaceClass -- constructor for the WinsockInterfaceClass                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 2:51PM ST : Created                                                              *\n *=============================================================================================*/\nWinsockInterfaceClass::WinsockInterfaceClass(void)\n{\n\tWinsockInitialised = false;\n\tASync = INVALID_HANDLE_VALUE;\n\tSocket = INVALID_SOCKET;\n}\n\n\n/***********************************************************************************************\n * WIC::~WinsockInterfaceClass -- destructor for the WinsockInterfaceClass                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 2:52PM ST : Created                                                              *\n *=============================================================================================*/\nWinsockInterfaceClass::~WinsockInterfaceClass(void)\n{\n\tClose();\n}\n\n\n/***********************************************************************************************\n * WIC::Close -- Releases any currently in use Winsock resources.                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 2:52PM ST : Created                                                              *\n *=============================================================================================*/\nvoid WinsockInterfaceClass::Close(void)\n{\n\t/*\n\t** If we never initialised the class in the first place then just return\n\t*/\n\tif (!WinsockInitialised) return;\n\n\t/*\n\t** Cancel any outstaning asyncronous events\n\t*/\n\tStop_Listening();\n\n\t/*\n\t** Close any open sockets\n\t*/\n\tClose_Socket();\n\n\t/*\n\t** Call the Winsock cleanup function to say we are finished using Winsock\n\t*/\n\tWSACleanup();\n\n\tWinsockInitialised = false;\n}\n\n\n\n/***********************************************************************************************\n * WIC::Close_Socket -- Close the communication socket if its open                             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/5/97 11:53AM ST : Created                                                              *\n *=============================================================================================*/\nvoid WinsockInterfaceClass::Close_Socket (void)\n{\n\tif ( Socket != INVALID_SOCKET ) {\n\t\tclosesocket (Socket);\n\t\tSocket = INVALID_SOCKET;\n\t}\n}\n\n\n\n/***********************************************************************************************\n * WIC::Start_Listening -- Enable callbacks for read/write events on our socket                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/5/97 11:54AM ST : Created                                                              *\n *=============================================================================================*/\nbool WinsockInterfaceClass::Start_Listening (void)\n{\n\t/*\n\t** Enable asynchronous events on the socket\n\t*/\n\tif ( WSAAsyncSelect ( Socket, MainWindow, Protocol_Event_Message(), FD_READ | FD_WRITE) == SOCKET_ERROR ){\n\t\tWWDebugString ( \"TS: Async select failed.\\n\" );\n\t\tassert (false);\n\t\tWSACancelAsyncRequest(ASync);\n\t\tASync = INVALID_HANDLE_VALUE;\n\t\treturn (false);\n\t}\n\treturn (true);\n}\n\n\n/***********************************************************************************************\n * WIC::Stop_Listening -- Disable the winsock event callback                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/5/97 12:06PM ST : Created                                                              *\n *=============================================================================================*/\nvoid WinsockInterfaceClass::Stop_Listening (void)\n{\n\tif ( ASync != INVALID_HANDLE_VALUE ) {\n\t\tWSACancelAsyncRequest ( ASync );\n\t\tASync = INVALID_HANDLE_VALUE;\n\t}\n}\n\n\n\n\n/***********************************************************************************************\n * WIC::Discard_In_Buffers -- Discard any packets in our incoming packet holding buffers       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/5/97 11:55AM ST : Created                                                              *\n *=============================================================================================*/\nvoid WinsockInterfaceClass::Discard_In_Buffers (void)\n{\n\tWinsockBufferType *packet;\n\n\twhile ( InBuffers.Count() ) {\n\t\tpacket = InBuffers [ 0 ];\n\t\tdelete packet;\n\t\tInBuffers.Delete (0);\n\t}\n}\n\n\n/***********************************************************************************************\n * WIC::Discard_In_Buffers -- Discard any packets in our outgoing packet holding buffers       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/5/97 11:55AM ST : Created                                                              *\n *=============================================================================================*/\nvoid WinsockInterfaceClass::Discard_Out_Buffers (void)\n{\n\tWinsockBufferType *packet;\n\n\twhile ( OutBuffers.Count() ) {\n\t\tpacket = OutBuffers [ 0 ];\n\t\tdelete packet;\n\t\tOutBuffers.Delete (0);\n\t}\n}\n\n\n/***********************************************************************************************\n * WIC::Init -- Initialised Winsock and this class for use.                                    *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   true if Winsock is available and was initialised                                  *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 2:54PM ST : Created                                                              *\n *=============================================================================================*/\nbool WinsockInterfaceClass::Init(void)\n{\n\tshort version;\n\tint \trc;\n\n\t/*\n\t** Just return true if we are already set up\n\t*/\n\tif (WinsockInitialised) return (true);\n\n\t/*\n\t** Create a buffer much larger than the sizeof (WSADATA) would indicate since Bounds Checker\n\t** says that a buffer of that size gets overrun.\n\t*/\n\tchar\t*buffer = new char [sizeof (WSADATA) + 1024];\n\tWSADATA *winsock_info = (WSADATA*) (&buffer[0]);\n\n\t/*\n\t** Initialise socket and event handle to null\n\t*/\n\tSocket =INVALID_SOCKET;\n\tASync = INVALID_HANDLE_VALUE;\n\tDiscard_In_Buffers();\n\tDiscard_Out_Buffers();\n\n\t/*\n\t** Start WinSock, and fill in our Winsock info structure\n\t*/\n\tversion = (WINSOCK_MINOR_VER << 8) | WINSOCK_MAJOR_VER;\n\trc = WSAStartup(version, winsock_info);\n\tif (rc != 0) {\n\t\tchar out[128];\n\t\tsprintf (out, \"TS: Winsock failed to initialise - error code %d.\\n\", GetLastError() );\n\t\tOutputDebugString (out);\n\t\tdelete [] buffer;\n\t\treturn (false);\n\t}\n\n\t/*\n\t** Check the Winsock version number\n\t*/\n\tif ((winsock_info->wVersion & 0x00ff) != (version & 0x00ff) ||\n\t\t(winsock_info->wVersion >> 8) != (version >> 8)) {\n\t\tOutputDebugString (\"TS: Winsock version is less than 1.1\\n\" );\n\t\tdelete [] buffer;\n\t\treturn (false);\n\t}\n\n\t/*\n\t** Everything is OK so return success\n\t*/\n\tWinsockInitialised = true;\n\n\tdelete [] buffer;\n\treturn (true);\n\n}\n\n\n\n\n/***********************************************************************************************\n * WIC::Read -- read any pending input from the communications socket                          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to buffer to receive input                                                    *\n *           length of buffer                                                                  *\n *           ptr to address to fill with address that packet was sent from                     *\n *           length of address buffer                                                          *\n *                                                                                             *\n * OUTPUT:   number of bytes transfered to buffer                                              *\n *                                                                                             *\n * WARNINGS: The format of the address is dependent on the protocol in use.                    *\n *                                                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 2:58PM ST : Created                                                              *\n *=============================================================================================*/\nint WinsockInterfaceClass::Read(void *buffer, int &buffer_len, void *address, int &address_len)\n{\n\taddress_len = address_len;\n\t/*\n\t** Call the message loop in case there are any outstanding winsock READ messages.\n\t*/\n\tKeyboard->Check();\n\n\t/*\n\t** If there are no available packets then return 0\n\t*/\n\tif ( InBuffers.Count() == 0 ) return (0);\n\n\t/*\n\t** Get the oldest packet for reading\n\t*/\n\tint packetnum = 0;\n\tWinsockBufferType *packet = InBuffers [packetnum];\n\n\tassert ( buffer_len >= packet->BufferLen );\n\tassert ( address_len >= sizeof (packet->Address) );\n\n\t/*\n\t** Copy the data and the address it came from into the supplied buffers.\n\t*/\n\tmemcpy ( buffer, packet->Buffer, packet->BufferLen );\n\tmemcpy ( address, packet->Address, sizeof (packet->Address) );\n\n\t/*\n\t** Return the length of the packet in buffer_len.\n\t*/\n\tbuffer_len = packet->BufferLen;\n\n\t/*\n\t** Delete the temporary storage for the packet now that it is being passed to the game.\n\t*/\n\tInBuffers.Delete ( packetnum );\n\tdelete packet;\n\n\treturn ( buffer_len );\n}\n\n\n\n\n/***********************************************************************************************\n * WIC::WriteTo -- Send data via the Winsock socket                                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to buffer containing data to send                                             *\n *           length of data to send                                                            *\n *           address to send data to.                                                          *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: The format of the address is dependent on the protocol in use.                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 3:00PM ST : Created                                                              *\n *=============================================================================================*/\nvoid WinsockInterfaceClass::WriteTo(void *buffer, int buffer_len, void *address)\n{\n\t/*\n\t** Create a temporary holding area for the packet.\n\t*/\n\tWinsockBufferType *packet = new WinsockBufferType;\n\n\t/*\n\t** Copy the packet into the holding buffer.\n\t*/\n\tmemcpy ( packet->Buffer, buffer, buffer_len );\n\tpacket->BufferLen = buffer_len;\n\tpacket->IsBroadcast = false;\n//\tmemcpy ( packet->Address, address, sizeof (packet->Address) );\n\tmemcpy ( packet->Address, address, sizeof( IPXAddressClass ) );\t\t// Steve Tall has revised WriteTo due to this bug.\n\n\t/*\n\t** Add it to our out list.\n\t*/\n\tOutBuffers.Add ( packet );\n\n\t/*\n\t** Send a message to ourselves so that we can initiate a write if Winsock is idle.\n\t*/\n\tSendMessage ( MainWindow, Protocol_Event_Message(), 0, (LONG)FD_WRITE );\n\n\t/*\n\t** Make sure the message loop gets called.\n\t*/\n\tKeyboard->Check();\n}\n\n\n\n\n/***********************************************************************************************\n * WIC::Broadcast -- Send data via the Winsock socket                                          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to buffer containing data to send                                             *\n *           length of data to send                                                            *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 3:00PM ST : Created                                                              *\n *=============================================================================================*/\nvoid WinsockInterfaceClass::Broadcast (void *buffer, int buffer_len)\n{\n\n\t/*\n\t** Create a temporary holding area for the packet.\n\t*/\n\tWinsockBufferType *packet = new WinsockBufferType;\n\n\t/*\n\t** Copy the packet into the holding buffer.\n\t*/\n\tmemcpy ( packet->Buffer, buffer, buffer_len );\n\tpacket->BufferLen = buffer_len;\n\n\t/*\n\t** Indicate that this packet should be broadcast.\n\t*/\n\tpacket->IsBroadcast = true;\n\n\t/*\n\t** Add it to our out list.\n\t*/\n\tOutBuffers.Add ( packet );\n\n\t/*\n\t** Send a message to ourselves so that we can initiate a write if Winsock is idle.\n\t*/\n\tSendMessage ( MainWindow, Protocol_Event_Message(), 0, (LONG)FD_WRITE );\n\n\t/*\n\t** Make sure the message loop gets called.\n\t*/\n\tKeyboard->Check();\n}\n\n\n\n\n/***********************************************************************************************\n * WIC::Clear_Socket_Error -- Clear any outstanding erros on the socket                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Socket                                                                            *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/5/97 12:05PM ST : Created                                                              *\n *=============================================================================================*/\nvoid WinsockInterfaceClass::Clear_Socket_Error(SOCKET socket)\n{\n\tunsigned long error_code;\n\tint length = 4;\n\n\tgetsockopt (socket, SOL_SOCKET, SO_ERROR, (char*)&error_code, &length);\n\terror_code = 0;\n\tsetsockopt (socket, SOL_SOCKET, SO_ERROR, (char*)&error_code, length);\n}\n\n\n\n\n\n\n\n/***********************************************************************************************\n * WIC::Set_Socket_Options -- Sets default socket options for Winsock buffer sizes             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/5/97 12:07PM ST : Created                                                              *\n *=============================================================================================*/\nbool WinsockInterfaceClass::Set_Socket_Options ( void )\n{\n\tstatic int\t\tsocket_transmit_buffer_size = SOCKET_BUFFER_SIZE;\n\tstatic int\t\tsocket_receive_buffer_size = SOCKET_BUFFER_SIZE;\n\n\t/*\n\t** Specify the size of the receive buffer.\n\t*/\n\tint err = setsockopt ( Socket, SOL_SOCKET, SO_RCVBUF, (char*)&socket_receive_buffer_size, 4);\n\tif ( err == INVALID_SOCKET ) {\n\t\tchar out[128];\n\t\tsprintf (out, \"TS: Failed to set IPX socket option SO_RCVBUF - error code %d.\\n\", GetLastError() );\n\t\tOutputDebugString (out);\n\t\tassert ( err != INVALID_SOCKET );\n\t}\n\n\t/*\n\t** Specify the size of the send buffer.\n\t*/\n\terr = setsockopt ( Socket, SOL_SOCKET, SO_SNDBUF, (char*)&socket_transmit_buffer_size, 4);\n\tif ( err == INVALID_SOCKET ) {\n\t\tchar out[128];\n\t\tsprintf (out, \"TS: Failed to set IPX socket option SO_SNDBUF - error code %d.\\n\", GetLastError() );\n\t\tOutputDebugString (out);\n\t\tassert ( err != INVALID_SOCKET );\n\t}\n\n\treturn ( true );\n}\n\n\n"
  },
  {
    "path": "CODE/WSPROTO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                     $Archive:: /Sun/WSProto.h                                              $*\n *                                                                                             *\n *                      $Author:: Joe_b                                                       $*\n *                                                                                             *\n *                     $Modtime:: 8/12/97 5:42p                                               $*\n *                                                                                             *\n *                    $Revision:: 4                                                          $*\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WSPROTO_H\n#define WSPROTO_H\n\n#include\t\"_WSProto.h\"\n\n/*\n** Include standard Winsock 1.0 header file.\n*/\n#include\t<winsock.h>\n\n/*\n** Misc defines\n*/\n#define WINSOCK_MINOR_VER\t\t1\t\t\t// Version of Winsock\n#define WINSOCK_MAJOR_VER\t\t1        // \tthat we require\n\n//#define WS_RECEIVE_BUFFER_LEN\t32768\t\t// Length of our temporary receive buffer. Needs to be more that the max packet size which is about 550 bytes.\n//#define SOCKET_BUFFER_SIZE\t\t32768\t\t// Length of winsocks internal buffer.\n#define WS_RECEIVE_BUFFER_LEN\t1024\t\t// Length of our temporary receive buffer.\n#define SOCKET_BUFFER_SIZE\t\t1024*128\t// Length of winsocks internal buffer.\n\n#define PLANET_WESTWOOD_HANDLE_MAX 20\t// Max length of a WChat handle\n\n/*\n** Define events for Winsock callbacks\n*/\n#define WM_IPXASYNCEVENT\t\t(WM_USER + 115)\t// IPX socket Async event\n#define WM_UDPASYNCEVENT\t\t(WM_USER + 116)\t// UDP socket Async event\n\n\n/*\n** Enum to identify the protocols supported by the Winsock interface.\n*/\ntypedef enum tProtocolEnum {\n\tPROTOCOL_NONE,\n\tPROTOCOL_IPX,\n\tPROTOCOL_UDP\n} ProtocolEnum;\n\n\n\n/*\n**\n** Class to interface with Winsock. This interface only supports connectionless packet protocols\n** like UDP & IPX. Connection orientated or streaming protocols like TCP are not supported by this\n** class.\n**\n*/\nclass WinsockInterfaceClass {\n\n\tpublic:\n\n\t\tWinsockInterfaceClass(void);\n\t\tvirtual ~WinsockInterfaceClass(void);\n\n\t\tbool Init(void);\n\t\tvoid Close(void);\n\n\n\t\tvirtual void Close_Socket(void);\n\t\tvirtual int  Read(void *buffer, int &buffer_len, void *address, int &address_len);\n\t\tvirtual void WriteTo (void *buffer, int buffer_len, void *address);\n\t\tvirtual void Broadcast (void *buffer, int buffer_len);\n\t\tvirtual void Discard_In_Buffers (void);\n\t\tvirtual void Discard_Out_Buffers (void);\n\t\tvirtual bool Start_Listening (void);\n\t\tvirtual void Stop_Listening (void);\n\t\tvirtual void Clear_Socket_Error(SOCKET socket);\n\t\tvirtual bool Set_Socket_Options ( void );\n\t\tvirtual void Set_Broadcast_Address ( void * ) {};\n\n\t\tvirtual ProtocolEnum Get_Protocol (void) {\n\t\t\treturn (PROTOCOL_NONE);\n\t\t};\n\n\t\tvirtual int Protocol_Event_Message (void) {\n\t\t\treturn (0);\n\t\t};\n\n\t\tvirtual bool Open_Socket ( SOCKET ) {\n\t\t\treturn (false);\n\t\t};\n\n\t \tvirtual long Message_Handler(HWND, UINT, UINT, LONG) {\n\t\t\treturn (1);\n\t\t}\n\n\n\t\ttypedef enum ConnectStatusEnum {\n\t\t\tCONNECTED_OK = 0,\n\t\t\tNOT_CONNECTING,\n\t\t\tCONNECTING,\n\t\t\tUNABLE_TO_CONNECT_TO_SERVER,\n\t\t\tCONTACTING_SERVER,\n\t\t\tSERVER_ADDRESS_LOOKUP_FAILED,\n\t\t\tRESOLVING_HOST_ADDRESS,\n\t\t\tUNABLE_TO_ACCEPT_CLIENT,\n\t\t\tUNABLE_TO_CONNECT,\n\t\t\tCONNECTION_LOST\n\t\t} ConnectStatusEnum;\n\n\t\tinline ConnectStatusEnum Get_Connection_Status(void) {return (ConnectStatus);}\n\n\tprotected:\n\n\t\t/*\n\t\t** This struct contains the information needed for each incoming and outgoing packet.\n\t\t** It acts as a temporary control for these packets.\n\t\t*/\n\t\ttypedef struct tWinsockBufferType {\n\t\t\tunsigned char\t\tAddress [64];\t// Address. IN_ADDR, IPXAddressClass etc.\n\t\t\tint\t\t\t\t\tBufferLen;\t\t// Length of data in buffer\n\t\t\tbool\t\t\t\t\tIsBroadcast;\t// Flag to broadcast this packet\n\t\t\tunsigned char\t\tBuffer[1024];\t// Buffer to store packet in.\n\t\t} WinsockBufferType;\n\n\t\t/*\n\t\t** Array of buffers to temporarily store incoming and outgoing packets.\n\t\t*/\n\t\tDynamicVectorClass <WinsockBufferType *> InBuffers;\n\t\tDynamicVectorClass <WinsockBufferType *> OutBuffers;\n\n\n\t\t/*\n\t\t** Is Winsock present and initialised?\n\t\t*/\n\t\tbool \t\t\t\t\tWinsockInitialised;\n\n\t\t/*\n\t\t** Socket that communications will take place over.\n\t\t*/\n\t\tSOCKET\t\t\t\tSocket;\n\n\t\t/*\n\t\t** Async object required for callbacks to our message handler.\n\t\t*/\n\t\tHANDLE\t\t\t\tASync;\n\n\t\t/*\n\t\t** Temporary receive buffer to use when querying Winsock for incoming packets.\n\t\t*/\n\t\tunsigned char\t\tReceiveBuffer[WS_RECEIVE_BUFFER_LEN];\n\n\t\t/*\n\t\t** Current connection status.\n\t\t*/\n\t\tConnectStatusEnum\tConnectStatus;\n};\n\n\n\n\n\n\n\n#endif\t//WSPROTO_H\n"
  },
  {
    "path": "CODE/WSPUDP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                     $Archive:: /Sun/WSPUDP.cpp                                             $*\n *                                                                                             *\n *                      $Author:: Joe_b                                                       $*\n *                                                                                             *\n *                     $Modtime:: 8/05/97 6:45p                                               $*\n *                                                                                             *\n *                    $Revision:: 3                                                           $*\n *                                                                                             *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n *  WSProto.CPP WinsockInterfaceClass to provide an interface to Winsock protocols             *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n * UDPInterfaceClass::UDPInterfaceClass -- Class constructor.                                  *\n * UDPInterfaceClass::Set_Broadcast_Address -- Sets the address to send broadcast packets to   *\n * UDPInterfaceClass::Open_Socket -- Opens a socket for communications via the UDP protocol    *\n * TMC::Message_Handler -- Message handler function for Winsock related messages               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"internet.h\"\n#include\t\"WSPUDP.h\"\n\n#include\t<assert.h>\n#include\t<stdio.h>\n#include\t<svcguid.h>\n\n\n/***********************************************************************************************\n * UDPInterfaceClass::UDPInterfaceClass -- Class constructor.                                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/5/97 12:11PM ST : Created                                                              *\n *=============================================================================================*/\nUDPInterfaceClass::UDPInterfaceClass (void) : WinsockInterfaceClass()\n{}\n\n\n\n/***********************************************************************************************\n * UDPIC::~UDPInterfaceClass -- UDPInterface class destructor                                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/9/97 12:17PM ST : Created                                                             *\n *=============================================================================================*/\nUDPInterfaceClass::~UDPInterfaceClass (void)\n{\n\twhile ( BroadcastAddresses.Count() ) {\n\t\tdelete BroadcastAddresses[0];\n\t\tBroadcastAddresses.Delete(0);\n\t}\n\n\twhile ( LocalAddresses.Count() ) {\n\t\tdelete LocalAddresses[0];\n\t\tLocalAddresses.Delete(0);\n\t}\n\n\tClose();\n}\n\n\n/***********************************************************************************************\n * UDPInterfaceClass::Set_Broadcast_Address -- Sets the address to send broadcast packets to   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to address in decimal dot format. i.e. xxx.xxx.xxx.xxx                        *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/5/97 12:12PM ST : Created                                                              *\n *=============================================================================================*/\nvoid UDPInterfaceClass::Set_Broadcast_Address (void *address)\n{\n\tchar* ip_addr = (char*) address;\n\tassert ( strlen (ip_addr) <= strlen ( \"xxx.xxx.xxx.xxx\" ) );\n\n\tunsigned char *baddr = new unsigned char[4];\n\n\tsscanf ( ip_addr, \"%d.%d.%d.%d\", &baddr[0], &baddr[1], &baddr[2], &baddr[3] );\n\tBroadcastAddresses.Add (baddr);\n}\n\n\n\n/***********************************************************************************************\n * UDPInterfaceClass::Open_Socket -- Opens a socket for communications via the UDP protocol    *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Socket number to use. Not required for this protocol.                             *\n *                                                                                             *\n * OUTPUT:   True if socket was opened OK                                                      *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/5/97 12:13PM ST : Created                                                              *\n *=============================================================================================*/\nbool UDPInterfaceClass::Open_Socket ( SOCKET )\n{\n\tLINGER ling;\n\tstruct \tsockaddr_in addr;\n\n\t/*\n\t** If Winsock is not initialised then do it now.\n\t*/\n\tif ( !WinsockInitialised ) {\n\t\tif ( !Init()) return ( false );;\n\t}\n\n\t/*\n\t** Create our UDP socket\n\t*/\n\tSocket = socket(AF_INET, SOCK_DGRAM, 0);\n\tif (Socket == INVALID_SOCKET) {\n\t\treturn (false);\n\t}\n\n\t/*\n\t** Bind our UDP socket to our UDP port number\n\t*/\n\taddr.sin_family = AF_INET;\n\taddr.sin_port = (unsigned short) htons ( (unsigned short) PlanetWestwoodPortNumber);\n\taddr.sin_addr.s_addr = htonl (INADDR_ANY);\n\n\tif ( bind (Socket, (LPSOCKADDR)&addr, sizeof(addr) ) == SOCKET_ERROR) {\n\t\tClose_Socket ();\n\t\treturn (false);\n\t}\n\n\t/*\n\t** Use gethostbyname to find the name of the local host. We will need this to look up\n\t** the local ip address.\n\t*/\n\tchar hostname[128];\n\tgethostname(hostname, 128);\n\tWWDebugString (hostname);\n\tstruct hostent *host_info = gethostbyname ( hostname );\n\n\t/*\n\t** Clear out any old local addresses from the local address list.\n\t*/\n\twhile ( LocalAddresses.Count() ) {\n\t\tdelete LocalAddresses[0];\n\t\tLocalAddresses.Delete(0);\n\t}\n\n\n\t/*\n\t** Add all local IP addresses to the list. This list will be used to discard any packets that\n\t** we send to ourselves.\n\t*/\n\tunsigned long **addresses = (unsigned long**) (host_info->h_addr_list);\n\n\tfor ( ;; ) {\n\t\tif ( !*addresses ) break;\n\n\t\tunsigned long address = **addresses++;\n\t\t//address = ntohl (address);\n\n\t\tchar temp[128];\n\t\tsprintf (temp, \"RA95: Found local address: %d.%d.%d.%d\\n\", address & 0xff, (address & 0xff00) >> 8, (address & 0xff0000) >> 16, (address & 0xff000000) >> 24);\n\t\tOutputDebugString (temp);\n\n\t\tunsigned char *a = new unsigned char [4];\n\t\t* ((unsigned long*) a) = address;\n\t\tLocalAddresses.Add (a);\n\t}\n\n\t/*\n\t** Set options for the UDP socket\n\t*/\n\tling.l_onoff = 0;\t\t// linger off\n\tling.l_linger = 0;\t// timeout in seconds (ie close now)\n\tsetsockopt (Socket, SOL_SOCKET, SO_LINGER, (LPSTR)&ling, sizeof(ling));\n\n\tWinsockInterfaceClass::Set_Socket_Options();\n\n\treturn (true);\n\n\n}\n\n\n\n\n/***********************************************************************************************\n * UDPIC::Broadcast -- Send data via the Winsock socket                                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to buffer containing data to send                                             *\n *           length of data to send                                                            *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 3:00PM ST : Created                                                              *\n *=============================================================================================*/\nvoid UDPInterfaceClass::Broadcast (void *buffer, int buffer_len)\n{\n\tfor ( int i=0 ; i<BroadcastAddresses.Count() ; i++ ) {\n\n\t\t/*\n\t\t** Create a temporary holding area for the packet.\n\t\t*/\n\t\tWinsockBufferType *packet = new WinsockBufferType;\n\n\t\t/*\n\t\t** Copy the packet into the holding buffer.\n\t\t*/\n\t\tmemcpy ( packet->Buffer, buffer, buffer_len );\n\t\tpacket->BufferLen = buffer_len;\n\n\t\t/*\n\t\t** Indicate that this packet should be broadcast.\n\t\t*/\n\t\tpacket->IsBroadcast = true;\n\n\t\t/*\n\t\t** Set up the send address for this packet.\n\t\t*/\n\t\tmemset (packet->Address, 0, sizeof (packet->Address));\n\t\tmemcpy (packet->Address+4, BroadcastAddresses[i], 4);\n\n\t\t/*\n\t\t** Add it to our out list.\n\t\t*/\n\t\tOutBuffers.Add ( packet );\n\n\t\t/*\n\t\t** Send a message to ourselves so that we can initiate a write if Winsock is idle.\n\t\t*/\n\t\tSendMessage ( MainWindow, Protocol_Event_Message(), 0, (LONG)FD_WRITE );\n\n\t\t/*\n\t\t** Make sure the message loop gets called.\n\t\t*/\n\t\tKeyboard->Check();\n\t}\n}\n\n\n\n\n\n/***********************************************************************************************\n * TMC::Message_Handler -- Message handler function for Winsock related messages               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Windows message handler stuff                                                     *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 3:05PM ST : Created                                                              *\n *=============================================================================================*/\nlong UDPInterfaceClass::Message_Handler(HWND, UINT message, UINT, LONG lParam)\n{\n\tstruct \tsockaddr_in addr;\n\tint\t \trc;\n\tint\t\taddr_len;\n\tWinsockBufferType *packet;\n\n\t/*\n\t** We only handle UDP events.\n\t*/\n\tif ( message != WM_UDPASYNCEVENT ) return (1);\n\n\t/*\n\t** Handle UDP packet events\n\t*/\n\tswitch ( WSAGETSELECTEVENT(lParam) ) {\n\n\t\t/*\n\t\t** Read event. Winsock has data it would like to give us.\n\t\t*/\n\t\tcase FD_READ:\n\t\t\t/*\n\t\t\t** Clear any outstanding errors on the socket.\n\t\t\t*/\n\t\t\trc = WSAGETSELECTERROR(lParam);\n\t\t\tif (rc != 0) {\n\t\t\t\tClear_Socket_Error (Socket);\n\t\t\t\treturn (0);;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Call the Winsock recvfrom function to get the outstanding packet.\n\t\t\t*/\n\t\t\taddr_len = sizeof(addr);\n\t\t\trc = recvfrom ( Socket, (char*)ReceiveBuffer, sizeof (ReceiveBuffer), 0, (LPSOCKADDR)&addr, &addr_len);\n\t\t\tif (rc == SOCKET_ERROR) {\n\t\t\t\tClear_Socket_Error (Socket);\n\t\t\t\treturn (0);;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** rc is the number of bytes received from Winsock\n\t\t\t*/\n\t\t\tif ( rc ) {\n\n\t\t\t\t/*\n\t\t\t\t** Make sure this packet didn't come from us. If it did then throw it away.\n\t\t\t\t*/\n\t\t\t\tfor ( int i=0 ; i<LocalAddresses.Count() ; i++ ) {\n\t\t\t\t\tif ( ! memcmp (LocalAddresses[i], &addr.sin_addr.s_addr, 4) ) return (0);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Create a new buffer and store this packet in it.\n\t\t\t\t*/\n\t\t\t\tpacket = new WinsockBufferType;\n\t\t\t\tpacket->BufferLen = rc;\n\t\t\t\tmemcpy ( packet->Buffer, ReceiveBuffer, rc );\n\t\t\t\tmemset ( packet->Address, 0, sizeof (packet->Address) );\n\t\t\t\tmemcpy ( packet->Address+4, &addr.sin_addr.s_addr, 4 );\n\t\t\t\tInBuffers.Add (packet);\n\t\t\t}\n\t\t\treturn (0);\n\n\n\t\t/*\n\t\t** Write event. We send ourselves this event when we have more data to send. This\n\t\t** event will also occur automatically when a packet has finished being sent.\n\t\t*/\n\t\tcase FD_WRITE:\n\t\t\t/*\n\t\t\t** Clear any outstanding erros on the socket.\n\t\t\t*/\n\t\t\trc = WSAGETSELECTERROR(lParam);\n\t\t\tif (rc != 0) {\n\t\t\t\tClear_Socket_Error (Socket);\n\t\t\t\treturn (0);;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If there are no packets waiting to be sent then bail.\n\t\t\t*/\n\t\t\tif ( OutBuffers.Count() == 0 ) return (0);\n\t\t\tint packetnum = 0;\n\n\t\t\t/*\n\t\t\t** Get a pointer to the packet.\n\t\t\t*/\n\t\t\tpacket = OutBuffers [ packetnum ];\n\n\t\t\t/*\n\t\t\t** Set up the address structure of the outgoing packet\n\t\t\t*/\n\t\t\taddr.sin_family = AF_INET;\n\t\t\taddr.sin_port = (unsigned short) htons ((unsigned short)PlanetWestwoodPortNumber);\n\t\t\tmemcpy (&addr.sin_addr.s_addr, packet->Address+4, 4);\n\n\t\t\t/*\n\t\t\t** Send it.\n\t\t\t** If we get a WSAWOULDBLOCK error it means that Winsock is unable to accept the packet\n\t\t\t** at this time. In this case, we clear the socket error and just exit. Winsock will\n\t\t\t** send us another WRITE message when it is ready to receive more data.\n\t\t\t*/\n\t\t\trc = sendto ( Socket, (const char*) packet->Buffer, packet->BufferLen, 0, (LPSOCKADDR)&addr, sizeof (addr) );\n\n\t\t\tif (rc == SOCKET_ERROR){\n\t\t\t\tif (WSAGetLastError() != WSAEWOULDBLOCK) {\n\t\t\t\t\tClear_Socket_Error (Socket);\n\t\t\t\t\treturn (0);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Delete the sent packet.\n\t\t\t*/\n\t\t\tOutBuffers.Delete ( packetnum );\n\t\t\tdelete packet;\n\t\t\treturn(0);\n\t}\n\n\treturn (0);\n}\n"
  },
  {
    "path": "CODE/WSPUDP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                     $Archive:: /Sun/WSPUDP.h                                               $*\n *                                                                                             *\n *                      $Author:: Joe_b                                                       $*\n *                                                                                             *\n *                     $Modtime:: 8/05/97 6:45p                                               $*\n *                                                                                             *\n *                    $Revision:: 3                                                           $*\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WSPUDP_H\n#define WSPUDP_H\n\n#include\t\"WSProto.h\"\n#include\t<nspapi.h>\n\n\n\n\n/*\n** Class to allow access to UDP specific portions of the Winsock interface.\n**\n*/\nclass UDPInterfaceClass : public WinsockInterfaceClass {\n\n\tpublic:\n\n\t\tUDPInterfaceClass (void);\n\t\tvirtual ~UDPInterfaceClass(void);\n\n\t \tvirtual long Message_Handler(HWND window, UINT message, UINT wParam, LONG lParam);\n\t\tvirtual bool Open_Socket ( SOCKET socketnum );\n\t\tvirtual void Set_Broadcast_Address ( void *address );\n\t\tvirtual void Broadcast (void *buffer, int buffer_len);\n\n\t\tvirtual ProtocolEnum Get_Protocol (void) {\n\t\t\treturn (PROTOCOL_UDP);\n\t\t};\n\n\t\tvirtual int Protocol_Event_Message (void) {\n\t\t\treturn (WM_UDPASYNCEVENT);\n\t\t};\n\n\n\tprivate:\n\n\t\t/*\n\t\t** Address to use when broadcasting a packet.\n\t\t*/\n\t\tDynamicVectorClass <unsigned char *> BroadcastAddresses;\n\n\t\t/*\n\t\t** List of local addresses.\n\t\t*/\n\t\tDynamicVectorClass <unsigned char *> LocalAddresses;\n};\n\n\n\n#endif"
  },
  {
    "path": "CODE/WWALLOC.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\wwalloc.h_v   4.9   07 May 1996 17:14:00   JOE_BOSTIC  $ */\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n/*\n**\tThis should be located in the wwlib32.h file, but is located here for\n**\ttest purposes.\n*/\n#ifdef __FLAT__\n#define\tPRIVATE\tstatic\n#endif\n\ntypedef enum MemoryFlagType {\n\tMEM_NORMAL = 0x0000,\t\t// Default memory (normal).\n\tMEM_PUBLIC = 0x0000,\t\t// Default memory (normal).\n\tMEM_CHIP   = 0x0000,\t\t// Graphic & sound buffer memory (Amiga).\n\tMEM_UNUSED = 0x0001,\t\t// <unused>\n\tMEM_SYSTEM = 0x0002,\t\t// Allocate out of system heap (XMS or EMS only).\n\tMEM_RELAXED= 0x0004,\t\t// Don't worry about page conservation in EMS.\n\tMEM_TEMP   = 0x0008,\t\t// Temporary allocation (used by library only).\n\tMEM_CLEAR  = 0x0010,\t\t// Fill memory with '\\0' characters.\n\tMEM_PARA   = 0x0020,\t\t// Paragraph aligned (IBM only).\n\tMEM_XMS    = 0x0040,\t\t// XMS memory.\n\tMEM_EMS    = 0x0080,\t\t// EMS memory (not implemented).\n\tMEM_X      = 0x8000\t\t// Here to force this enum to be unsigned sized.\n} MemoryFlagType;\nMemoryFlagType operator |(MemoryFlagType, MemoryFlagType);\nMemoryFlagType operator &(MemoryFlagType, MemoryFlagType);\nMemoryFlagType operator ~(MemoryFlagType);\n\n\n/* Prototypes for functions defined in this file */\nvoid *cdecl Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags);\nvoid cdecl Free(void const *pointer);\nvoid *cdecl Resize_Alloc(void const *original_ptr, unsigned long new_size_in_bytes);\nlong cdecl Ram_Free(MemoryFlagType flag);\nlong cdecl Total_Ram_Free(MemoryFlagType flag);\nlong cdecl Heap_Size(MemoryFlagType flag);\n\nextern unsigned long cdecl MinRam;\t\t// Record of least memory at worst case.\nextern unsigned long cdecl MaxRam;\t\t// Record of total allocated at worst case.\n\n#ifdef __cplusplus\n}\n#endif\n\n"
  },
  {
    "path": "CODE/WWFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/WWFILE.H 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Library                                             *\n *                                                                                             *\n *                    File Name : WWFILE.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : August 8, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWFILE_Hx\n#define WWFILE_Hx\n\n#define YEAR(dt)\t(((dt & 0xFE000000) >> (9 + 16)) + 1980)\n#define MONTH(dt)\t ((dt & 0x01E00000) >> (5 + 16))\n#define DAY(dt)\t ((dt & 0x001F0000) >> (0 + 16))\n#define HOUR(dt)\t ((dt & 0x0000F800) >> 11)\n#define MINUTE(dt) ((dt & 0x000007E0) >> 5)\n#define SECOND(dt) ((dt & 0x0000001F) << 1)\n\n#include\t<io.h>\n#include\t<stddef.h>\n\n#ifndef READ\n#define READ 1\n#endif\n#ifndef WRITE\n#define WRITE 2\n#endif\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\nclass FileClass\n{\n\tpublic:\n\t\tvirtual ~FileClass(void) {};\n\t\tvirtual char const * File_Name(void) const = 0;\n\t\tvirtual char const * Set_Name(char const *filename) = 0;\n\t\tvirtual int Create(void) = 0;\n\t\tvirtual int Delete(void) = 0;\n\t\tvirtual int Is_Available(int forced=false) = 0;\n\t\tvirtual int Is_Open(void) const = 0;\n\t\tvirtual int Open(char const *filename, int rights=READ) = 0;\n\t\tvirtual int Open(int rights=READ) = 0;\n\t\tvirtual long Read(void *buffer, long size) = 0;\n\t\tvirtual long Seek(long pos, int dir=SEEK_CUR) = 0;\n\t\tvirtual long Size(void) = 0;\n\t\tvirtual long Write(void const *buffer, long size) = 0;\n\t\tvirtual void Close(void) = 0;\n\t\tvirtual unsigned long Get_Date_Time(void) {return(0);}\n\t\tvirtual bool Set_Date_Time(unsigned long ) {return(false);}\n\t\tvirtual void Error(int error, int canretry = false, char const * filename=NULL) = 0;\n\n\t\toperator char const * () {return File_Name();};\n};\n\n#endif\n"
  },
  {
    "path": "CODE/XPIPE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/XPIPE.CPP 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : XPIPE.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/04/96                                                     *\n *                                                                                             *\n *                  Last Update : July 5, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BufferPipe::Put -- Submit data to the buffered pipe segment.                              *\n *   FilePipe::Put -- Submit a block of data to the pipe.                                      *\n *   FilePipe::End -- End the file pipe handler.                                               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"xpipe.h\"\n#include\t<stddef.h>\n#include\t<string.h>\n\n\n//---------------------------------------------------------------------------------------------------------\n// BufferPipe\n//---------------------------------------------------------------------------------------------------------\n\n\n/***********************************************************************************************\n * BufferPipe::Put -- Submit data to the buffered pipe segment.                                *\n *                                                                                             *\n *    The buffered pipe is a pipe terminator. That is, the data never flows onto subsequent    *\n *    pipe chains. The data is stored into the buffer previously submitted to the pipe.        *\n *    If the buffer is full, no more data is output to the buffer.                             *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the data to submit.                                         *\n *                                                                                             *\n *          length   -- The number of bytes to be submitted.                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes output to the destination buffer.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BufferPipe::Put(void const * source, int slen)\n{\n\tint total = 0;\n\n\tif (Is_Valid() && source != NULL && slen > 0) {\n\t\tint len = slen;\n\t\tif (BufferPtr.Get_Size() != 0) {\n\t\t\tint theoretical_max = BufferPtr.Get_Size() - Index;\n\t\t\tlen = (slen < theoretical_max) ? slen : theoretical_max;\n\t\t}\n\n\t\tif (len > 0) {\n\t\t\tmemmove(((char *)BufferPtr.Get_Buffer()) + Index, source, len);\n\t\t}\n\n\t\tIndex += len;\n//\t\tLength -= len;\n//\t\tBuffer = ((char *)Buffer) + len;\n\t\ttotal += len;\n\t}\n\treturn(total);\n}\n\n\n//---------------------------------------------------------------------------------------------------------\n// FilePipe\n//---------------------------------------------------------------------------------------------------------\n\nFilePipe::~FilePipe(void)\n{\n\tif (Valid_File() && HasOpened) {\n\t\tHasOpened = false;\n\t\tFile->Close();\n\t\tFile = NULL;\n\t}\n}\n\n\n/***********************************************************************************************\n * FilePipe::End -- End the file pipe handler.                                                 *\n *                                                                                             *\n *    This routine is called when there will be no more data sent through the pipe. It is      *\n *    responsible for cleaning up anything it needs to. This is not handled by the             *\n *    destructor, although it serves a similar purpose, because pipe are linked together and   *\n *    the destructor order is not easily controlled. If the destructors for a pipe chain were  *\n *    called out of order, the result might be less than pleasant.                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes flushed out the final end of the pipe as a        *\n *          consequence of this routine.                                                       *\n *                                                                                             *\n * WARNINGS:   Don't send any more data through the pipe after this routine is called.         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FilePipe::End(void)\n{\n\tint total = Pipe::End();\n\tif (Valid_File() && HasOpened) {\n\t\tHasOpened = false;\n\t\tFile->Close();\n\t}\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * FilePipe::Put -- Submit a block of data to the pipe.                                        *\n *                                                                                             *\n *    Takes the data block submitted and writes it to the file. If the file was not already    *\n *    open, this routine will open it for write.                                               *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the data to submit to the file.                             *\n *                                                                                             *\n *          length   -- The number of bytes to write to the file.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes written to the file.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FilePipe::Put(void const * source, int slen)\n{\n\tif (Valid_File() && source != NULL && slen > 0) {\n\t\tif (!File->Is_Open()) {\n\t\t\tHasOpened = true;\n\t\t\tFile->Open(WRITE);\n\t\t}\n\n\t\treturn(File->Write(source, slen));\n\t}\n\treturn(0);\n}\n"
  },
  {
    "path": "CODE/XPIPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/XPIPE.H 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : XPIPE.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/04/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef XPIPE_H\n#define XPIPE_H\n\n#include\t\"pipe.h\"\n#include\t\"wwfile.h\"\n#include\t\"buff.h\"\n\n/*\n**\tThis is a simple store-into-buffer pipe terminator. Use it as the final link in a pipe process\n**\tthat needs to store the data into a memory buffer. This can only serve as the final\n**\tlink in the chain of pipe segments.\n*/\nclass BufferPipe : public Pipe\n{\n\tpublic:\n\t\tBufferPipe(Buffer const & buffer) : BufferPtr(buffer), Index(0) {}\n\t\tBufferPipe(void * buffer, int length) : BufferPtr(buffer, length), Index(0) {}\n\t\tvirtual int Put(void const * source, int slen);\n\n\tprivate:\n\t\tBuffer BufferPtr;\n\t\tint Index;\n\n//\t\tvoid * Buffer;\n//\t\tint Length;\n\n\t\tbool Is_Valid(void) {return(BufferPtr.Is_Valid());}\n\t\tBufferPipe(BufferPipe & rvalue);\n\t\tBufferPipe & operator = (BufferPipe const & pipe);\n};\n\n\n/*\n**\tThis is a store-to-file pipe terminator. Use it as the final link in a pipe process that\n**\tneeds to store the data to a file. This can only serve as the last link in the chain\n**\tof pipe segments.\n*/\nclass FilePipe : public Pipe\n{\n\tpublic:\n\t\tFilePipe(FileClass * file) : File(file), HasOpened(false) {}\n\t\tFilePipe(FileClass & file) : File(&file), HasOpened(false) {}\n\t\tvirtual ~FilePipe(void);\n\n\t\tvirtual int Put(void const * source, int slen);\n\t\tvirtual int End(void);\n\n\tprivate:\n\t\tFileClass * File;\n\t\tbool HasOpened;\n\n\t\tbool Valid_File(void) {return(File != NULL);}\n\t\tFilePipe(FilePipe & rvalue);\n\t\tFilePipe & operator = (FilePipe const & pipe);\n\n};\n\n#endif\n"
  },
  {
    "path": "CODE/XSTRAW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/XSTRAW.CPP 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : XSTRAW.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/04/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BufferStraw::Get -- Fetch data from the straw's buffer holding tank.                      *\n *   FileStraw::Get -- Fetch data from the file.                                               *\n *   FileStraw::~FileStraw -- The destructor for the file straw.                               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"xstraw.h\"\n#include\t<stddef.h>\n#include\t<string.h>\n\n//---------------------------------------------------------------------------------------------------------\n// BufferStraw\n//---------------------------------------------------------------------------------------------------------\n\n\n/***********************************************************************************************\n * BufferStraw::Get -- Fetch data from the straw's buffer holding tank.                        *\n *                                                                                             *\n *    This routine will copy the requested number of bytes from the buffer holding tank (as    *\n *    set up by the straw's constructor) to the buffer specified.                              *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer to be filled with data.                          *\n *                                                                                             *\n *          length   -- The number of bytes requested.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes copied to the buffer. If this is less than        *\n *          requested, then it indicates that the data holding tank buffer is exhausted.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BufferStraw::Get(void * source, int slen)\n{\n\tint total = 0;\n\n\tif (Is_Valid() && source != NULL && slen > 0) {\n\t\tint len = slen;\n\t\tif (BufferPtr.Get_Size() != 0) {\n\t\t\tint theoretical_max = BufferPtr.Get_Size() - Index;\n\t\t\tlen = (slen < theoretical_max) ? slen : theoretical_max;\n\t\t}\n\n\t\tif (len > 0) {\n\t\t\tmemmove(source, ((char*)BufferPtr.Get_Buffer()) + Index, len);\n\t\t}\n\n\t\tIndex += len;\n//\t\tLength -= len;\n//\t\tBufferPtr = ((char *)BufferPtr) + len;\n\t\ttotal += len;\n\t}\n\treturn(total);\n}\n\n\n//---------------------------------------------------------------------------------------------------------\n// FileStraw\n//---------------------------------------------------------------------------------------------------------\n\n\n/***********************************************************************************************\n * FileStraw::Get -- Fetch data from the file.                                                 *\n *                                                                                             *\n *    This routine will read data from the file (as specified in the straw's constructor) into *\n *    the buffer indicated.                                                                    *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer to hold the data.                                *\n *                                                                                             *\n *          length   -- The number of bytes requested.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes stored into the buffer. If this number is less    *\n *          than the number requested, then this indicates that the file is exhausted.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FileStraw::Get(void * source, int slen)\n{\n\tif (Valid_File() && source != NULL && slen > 0) {\n\t\tif (!File->Is_Open()) {\n\t\t\tHasOpened = true;\n\t\t\tif (!File->Is_Available()) return(0);\n\t\t\tif (!File->Open(READ)) return(0);\n\t\t}\n\n\t\treturn(File->Read(source, slen));\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * FileStraw::~FileStraw -- The destructor for the file straw.                                 *\n *                                                                                             *\n *    This destructor only needs to close the file if it was the one to open it.               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nFileStraw::~FileStraw(void)\n{\n\tif (Valid_File() && HasOpened) {\n\t\tFile->Close();\n\t\tHasOpened = false;\n\t\tFile = NULL;\n\t}\n}\n"
  },
  {
    "path": "CODE/XSTRAW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: /CounterStrike/XSTRAW.H 1     3/03/97 10:26a Joe_bostic $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : XSTRAW.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/04/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef XSTRAW_H\n#define XSTRAW_H\n\n#include\t\"straw.h\"\n#include\t\"buff.h\"\n#include\t\"wwfile.h\"\n#include\t<stddef.h>\n\n/*\n**\tThis class is used to manage a buffer as a data source. Data requests will draw from the\n**\tbuffer supplied until the buffer is exhausted.\n*/\nclass BufferStraw : public Straw\n{\n\tpublic:\n\t\tBufferStraw(Buffer const & buffer) : BufferPtr(buffer), Index(0) {}\n\t\tBufferStraw(void const * buffer, int length) : BufferPtr((void*)buffer, length), Index(0) {}\n\t\tvirtual int Get(void * source, int slen);\n\n\tprivate:\n\t\tBuffer BufferPtr;\n\t\tint Index;\n//\t\tvoid const * BufferPtr;\n//\t\tint Length;\n\n\t\tbool Is_Valid(void) {return(BufferPtr.Is_Valid());}\n\t\tBufferStraw(BufferStraw & rvalue);\n\t\tBufferStraw & operator = (BufferStraw const & pipe);\n};\n\n/*\n**\tThis class is used to manage a file as a data source. Data requests will draw from the\n**\tfile until the file has been completely read.\n*/\nclass FileStraw : public Straw\n{\n\tpublic:\n\t\tFileStraw(FileClass * file) : File(file), HasOpened(false) {}\n\t\tFileStraw(FileClass & file) : File(&file), HasOpened(false) {}\n\t\tvirtual ~FileStraw(void);\n\t\tvirtual int Get(void * source, int slen);\n\n\tprivate:\n\t\tFileClass * File;\n\t\tbool HasOpened;\n\n\t\tbool Valid_File(void) {return(File != NULL);}\n\t\tFileStraw(FileStraw & rvalue);\n\t\tFileStraw & operator = (FileStraw const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "CODE/_WSPROTO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                     $Archive:: /Sun/_WSProto.cpp                                           $*\n *                                                                                             *\n *                      $Author:: Joe_b                                                       $*\n *                                                                                             *\n *                     $Modtime:: 8/06/97 12:47p                                              $*\n *                                                                                             *\n *                    $Revision:: 2                                                           $*\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"_WSProto.h\"\n\n\nWinsockInterfaceClass\t*PacketTransport = 0;\t\t\t//The object for interfacing with Winsock\n"
  },
  {
    "path": "CODE/_WSPROTO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                     $Archive:: /Sun/_WSProto.h                                             $*\n *                                                                                             *\n *                      $Author:: Joe_b                                                       $*\n *                                                                                             *\n *                     $Modtime:: 8/06/97 12:39p                                              $*\n *                                                                                             *\n *                    $Revision:: 3                                                           $*\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef _WSPROTO_H\n#define _WSPROTO_H\n\n\nclass WinsockInterfaceClass;\nextern WinsockInterfaceClass *PacketTransport;\t\t\t//The object for interfacing with Winsock\n\n#endif\t//_WSPROTO_H\n"
  },
  {
    "path": "IPX/FIXTHUNK.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#include <windows.h>\n#include <sys\\types.h>\n#include <sys\\stat.h>\n#include <fcntl.h>\n#include <io.h>\n#include <stdio.h>\n\n\nunsigned char thunk_file[1000000];\nunsigned char thunk_file_out[100050];\n\n\n/***********************************************************************************************\n * Search_For_String -- search for a string of chars within a buffer                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    string                                                                            *\n *           ptr to buffer to search in                                                        *\n *           length of buffer                                                                  *\n *                                                                                             *\n * OUTPUT:   ptr to string in buffer or NULL if not found                                      *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:42PM ST : Created                                                             *\n *=============================================================================================*/\n\nchar *Search_For_String (char *string , char *buffer_ptr , int buffer_length)\n{\n\tint\tj;\n\tint\tstring_length=strlen(string);\n\n\tfor (int i=0 ; i<buffer_length-string_length ; i++){\n\n\t\tfor (j=0 ; j<string_length ; j++){\n\t\t\tif ( *(string+j) != *(buffer_ptr+i+j)) break;\n\t\t}\n\t\tif (j==string_length) return buffer_ptr+i;\n\t}\n\n\treturn (NULL);\n\n}\n\n\n\n\nint main(int argc, char *argv[])\n{\n\tint\thandle;\n\tchar\tfind_string[]={\";************************ START OF THUNK BODIES************************\"};\n\tchar\tfind_other_string[]={\"public _IPX_Initialise@4\"};\n\n\tchar\tinsert_string1[]={\"\\n\\r;\\n\\r\"};\n\tchar\tinsert_string2[]={\";For some reason, inserting these lines makes it assemble correctly\\n\\r\"};\n\tchar\tinsert_string3[]={\";\\n\\r\"};\n\tchar\tinsert_string4[]={\"Externdef   IPX_Initialise:near\\n\\r\"};\n\tchar\tinsert_string5[]={\"IPX_Initialise label near\\n\\r\\n\\r\"};\n\n\tunsigned char *pointer;\n\tunsigned char *pointer2;\n\tint\tcopy_length;\n\tint\tfile_length;\n\n\thandle = open (\"thipx.asm\", O_RDONLY | O_BINARY);\n\n\tif (handle==-1)return (1);\n\n\tfile_length = filelength(handle);\n\n\tif (read (handle, thunk_file, file_length) != file_length){\n\t\tclose (handle);\n\t\treturn (1);\n\t}\n\n\tclose (handle);\n\n\tpointer = (unsigned char*)Search_For_String(find_string, (char*)thunk_file, file_length);\n\n\tif (pointer){\n\n\t\tpointer += strlen(find_string);\n\n\t\tcopy_length = (int)( (int)pointer - (int)&thunk_file[0]);\n\n\t\tmemcpy (thunk_file_out, thunk_file, copy_length);\n\n\t\tsprintf ((char*)&thunk_file_out[copy_length], \"%s%s%s%s%s\", \tinsert_string1,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tinsert_string2,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tinsert_string3,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tinsert_string4,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tinsert_string5);\n\n\n\t\tpointer2 = (unsigned char*)Search_For_String(find_other_string, (char*)pointer, file_length);\n\t\tif (!pointer2) return (1);\n\t\tpointer2 += strlen(find_other_string);\n\n\t\tmemcpy (&thunk_file_out [copy_length+ strlen(insert_string1)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ strlen(insert_string2)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ strlen(insert_string3)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ strlen(insert_string4)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ strlen(insert_string5)],\n\t\t\t\t\tpointer2,\n\t\t\t\t\tfile_length-((int)pointer2-(int)&thunk_file[0]));\n\n\n\t\thandle = open (\"thipx.asm\", O_WRONLY | O_BINARY | O_TRUNC);\n\n\t\tif (handle == -1) return (1);\n\n\t\twrite (handle, thunk_file_out, file_length+ strlen(insert_string1)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ strlen(insert_string2)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ strlen(insert_string3)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ strlen(insert_string4)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ strlen(insert_string5));\n\n\t\tclose (handle);\n\t}\n\n\treturn (0);\n}\n\n\n"
  },
  {
    "path": "IPX/IPX.RC",
    "content": "\n\n"
  },
  {
    "path": "IPX/IPX16.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\n\n\t\tIDEAL\n\t\tP386N\n\t\tLOCALS ??\n\n\n\n\t\tsegment realcode para public USE16 'code'\n\n\nglobal\t\tPASCAL ASM_IPX_INITIALISE:far\nglobal\t\tPASCAL ASM_IPX_UNINITIALISE:far\n\n\nproc\t\tASM_IPX_INITIALISE PASCAL FAR\n\n\t\tint\t3\n\t\tmov\tax,7a00h\n\t\tint\t2fh\n\t\tand\teax,0ffh\n\t\tcmp\tal,-1\n\t\tsetz\tal\n\t\tret\n\nendp\t\tASM_IPX_INITIALISE\n\n\n\n\nproc\t\tASM_IPX_UNINITIALISE PASCAL FAR\n\n\t\tret\n\nendp\t\tASM_IPX_UNINITIALISE\n\n\n\n\t\tends\n\n\t\tend\n\n\n\n"
  },
  {
    "path": "IPX/IPX16.BAK",
    "content": "system\twindows_dll\noption redefsok\noption quiet\noption map\noption eliminate\noption caseexact\noption one\n\ndebug all\nfile ipx16a.obj\nfile ipx16c.obj\n\nname wwipx16.dll\n"
  },
  {
    "path": "IPX/IPX16.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n\nextern \"C\"{\n\tBOOL FAR __cdecl IPX_Initialise(int);\n}\n\n\n"
  },
  {
    "path": "IPX/IPX16A.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\n;***************************************************************************\n;**   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  I N C  **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : IPX16a.asm                               *\n;*                                                                         *\n;*                   Programmer : Steve Tall                               *\n;*                                                                         *\n;*                   Start Date : January 26th, 1996                       *\n;*                                                                         *\n;*                  Last Update : January 26th, 1996  [ST]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Overview:                                                               *\n;*  16-bit protected mode windows code. This code sits in a 16 bit .DLL    *\n;* and provides access to IPX functions via the standard DOS interface.    *\n;*                                                                         *\n;*  Strangely enough, although you would expect to have to use segment     *\n;* addresses when passing data to and from the DOS IPX services, it only   *\n;* seems to work with selector addressing. This could be something to do   *\n;* with being in a windows .DLL.                                           *\n;*                                                                         *\n;*  It seems that in Win95, the DOS services are stubbed to just pass up   *\n;* to NWLINK which is the win95 32bit netware services layer. If we ever   *\n;* have direct access to that then all this code can go away.              *\n;*                                                                         *\n;*                                                                         *\n;*-----------------------------------------------------------------------------------------------*\n;* Functions:                                                                                    *\n;* _IPX_Initialise -- confirms the presence of IPX and gets the entry point for subsequent calls *\n;* _IPX_Open_Socket95 -- opens the given socket number                                           *\n;* IPX_Close_Socket95 -- closes the given socket number                                          *\n;* _IPX_Get_Connection_Number95 -- get the users local 'connection number'                       *\n;* _IPX_Send_Packet95 -- Send a packet via IPX                                                   *\n;* _IPX_Broadcast_Packet95 -- Broadcast a packet via IPX                                         *\n;* _IPX_Get_Local_Target95 -- Gets the node address of a destination or bridge                   *\n;* _IPX_Get_Outstanding_Buffer95 -- return contents of the next unread buffer in the buffer list *\n;* Receive_Callback -- IPX callback function. Called when a new packet arrives                   *\n;* Init_Receive_ECB -- initialises an ECB for receiving a packet                                 *\n;* _IPX_Start_Listening95 -- initialise DOS memory for receive buffers and start listening for   *\n;*                           IPX packets                                                         *\n;* _IPX_Shut_Down95 -- finish an IPX session. Releases any allocated resources except the socket *\n;* Listen_For_Packet -- Start IPX listening for an incoming packet                               *\n;* Call_IPX -- Make a call to the IPX entry point                                                *\n;* Call_DOS -- use DPMI to call a DOS interrupt service                                          *\n;*                                                                                               *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\n\t\t.8086\t\t\t;cant specify .386 until we are into the code segment\n\n\n\t\t.model\tlarge\n\t\toption\tsegment:USE16\t;16-bit segment\n\t\toption\treadonly\n\t\toption\toldstructs\n\n\n\t\tassume\tds:@data\t;ds is defauly segment register for our data segment\n\t\tassume\tes:nothing\n\n\n;#############################################################################\n;\n; Constants\n;\nRECEIVE_BUFFER_LENGTH\t=1024\t\t;length of each DOS memory receive buffer\nMAX_RECEIVE_BUFFERS\t=32\t\t;number of receive buffers allocated\n\nOFFS\t\t=0\t\t\t;offset of OFFSET part of a far ptr\nSEGM\t\t=2\t\t\t;offset of SEGMENT part of a far ptr\n\nSEND_ECB_OFFSET\t\t=0\t\t\t\t\t\t\t\t;offset of SEND ecb\nSEND_HEADER_OFFSET\t=(sizeof ECB +3) AND 0fffch\t\t\t\t\t;offset of our send header\nSEND_BUFFER_OFFSET\t=(SEND_HEADER_OFFSET + sizeof IPXHeaderType +3) AND 0fffch\t;offset of our send buffer\n\n;---------------------------------------------------------------------------\n;These defines are for the IPX functions.  The function number is specified\n;by placing it in BX when IPX is called.  There are two ways to invoke IPX:\n;use interrupt 0x7a, or use a function whose address is obtained by calling\n;interrupt 0x2f with AX=0x7a00; the function address is returned in ES:DI.\n;This is the preferred method, since other apps are known to use int 0x7a.\n;---------------------------------------------------------------------------\nIPX_OPEN_SOCKET\t\t\t= 0000h\nIPX_CLOSE_SOCKET\t\t= 0001h\nIPX_GET_LOCAL_TARGET\t\t= 0002h\nIPX_SEND_PACKET\t\t\t= 0003h\nIPX_LISTEN_FOR_PACKET\t\t= 0004h\nIPX_SCHEDULE_EVENT\t\t= 0005h\nIPX_CANCEL_EVENT\t\t= 0006h\nIPX_GET_INTERVAL_MARKER\t\t= 0008h\nIPX_GET_INTERNETWORK_ADDRESS\t= 0009h\nIPX_RELINQUISH_CONTROL\t\t= 000Ah\nIPX_DISCONNECT_FROM_TARGET\t= 000Bh\n\n;/*---------------------------------------------------------------------------\n;These defines are for various IPX error codes:\n;---------------------------------------------------------------------------*/\nIPXERR_CONNECTION_SEVERED\t= 00ech\nIPXERR_CONNECTION_FAILED\t= 00edh\nIPXERR_NO_CONNECTION\t\t= 00eeh\nIPXERR_CONNECTION_TABLE_FULL\t= 00efh\nIPXERR_NO_CANCEL_ECB\t\t= 00f9h\nIPXERR_NO_PATH\t\t\t= 00fah\nIPXERR_ECB_INACTIVE\t\t= 00fch\nIPXERR_INVALID_PACKET_LENGTH\t= 00fdh\nIPXERR_SOCKET_TABLE_FULL\t= 00feh\nIPXERR_SOCKET_ERROR\t\t= 00ffh\n\n;/*---------------------------------------------------------------------------\n;These defines are for various interrupt vectors and DPMI functions:\n;---------------------------------------------------------------------------*/\nIPX_INT\t\t\t= 007ah\nDPMI_INT\t\t= 0031h\nDPMI_ALLOC_DOS_MEM\t= 0100h\nDPMI_FREE_DOS_MEM\t= 0101h\nDPMI_CALL_REAL_INT\t= 0300h\nDPMI_CALL_REAL_PROC\t= 0301h\nDPMI_ALLOCATE_CALLBACK\t= 0303h\nDPMI_RELEASE_CALLBACK\t= 0304h\nDPMI_LOCK_MEM\t\t= 0600h\nDPMI_UNLOCK_MEM\t\t= 0601h\n\n\n\n;#############################################################################\n;\n; Windows API functions\n;\nexterndef GLOBALDOSALLOC:far\nexterndef GLOBALDOSFREE:far\n\n\n;#############################################################################\n;\n; Global initialised data\n;\n\t\t\t.data\n\nIPXCallOffset\t\tdw\t0\nIPXCallSegment\t\tdw\t0\n\nRegisterDump\t\tdb\t32h dup (0)\nNoReenter\t\tdb\t0\n\n\n;#############################################################################\n;\n; Global uninitialised data\n;\n\t\t\t.data?\n\nMySocket\t\tdw\t?\nReceiveBufferSegment\tdw\t?\nReceiveBufferSelector\tdw\t?\nReceiveECBOffset\tdw\t?\nCurrentReceiveBuffer\tdw\t?\nLastPassedReceiveBuffer\tdw\t?\n\nReceiveDescriptor\tdb\t8 dup (?)\nOriginalReceiveDescriptor db\t8 dup (?)\n\nListening\t\tdb\t?\nListeningFailed\t\tdb\t?\n\n\n;#############################################################################\n;\n; Structures\n;\n\n;---------------------------------------------------------------------------\n;This is the IPX Packet structure.  It's followed by the data itself, which\n;can be up to 546 bytes long.  Annotation of 'IPX' means IPX will set this\n;field; annotation of 'APP' means the application must set the field.\n;NOTE: All header fields are ordered high-byte,low-byte.\n;---------------------------------------------------------------------------*/\nIPXHeaderType\tstruct\n\n\t\tCheckSum\t\tdw\t?\t\t; IPX: Not used; always 0xffff\n\t\tIPXLength\t\tdw\t?               ; IPX: Total size, incl header & data\n\t\tTransportControl\tdb\t?               ; IPX: # bridges message crossed\n\t\tPacketType\t\tdb\t?               ; APP: Set to 4 for IPX (5 for SPX)\n\t\tDestNetworkNumber\tdb\t?,?,?,?         ; APP: destination Network Number\n\t\tDestNetworkNode\t\tdb\t?,?,?,?,?,?     ; APP: destination Node Address\n\t\tDestNetworkSocket\tdw\t?               ; APP: destination Socket Number\n\t\tSourceNetworkNumber\tdb\t?,?,?,?         ; IPX: source Network Number\n\t\tSourceNetworkNode\tdb\t?,?,?,?,?,?     ; IPX: source Node Address\n\t\tSourceNetworkSocket\tdw\t?               ; IPX: source Socket Number\n\nIPXHeaderType\tends\n\n\n;/*---------------------------------------------------------------------------\n;This is the IPX Event Control Block.  It serves as a communications area\n;between IPX and the application for a single IPX operation.  You should set\n;up a separate ECB for each IPX operation you perform.\n;---------------------------------------------------------------------------*/\n\nECB\t\tstruct\n\n\t\tLink_Address\t\tdd\t?\n\t\tEvent_Service_Routine\tdd\t?\t\t; APP: event handler (NULL=none)\n\t\tInUse\t\t\tdb\t?               ; IPX: 0 = event complete\n\t\tCompletionCode\t\tdb\t?               ; IPX: event's return code\n\t\tSocketNumber\t\tdw\t?               ; APP: socket to send data through\n\t\tConnectionID\t\tdw\t?               ; returned by Listen (???)\n\t\tRestOfWorkspace\t\tdw\t?\n\t\tDriverWorkspace\t\tdb\t12 dup (?)\n\t\tImmediateAddress\tdb\t6 dup (?)       ; returned by Get_Local_Target\n\t\tPacketCount\t\tdw\t?\n\t\tPacketAddress0\t\tdd\t?\n\t\tPacketLength0\t\tdw\t?\n\t\tPacketAddress1\t\tdd\t?\n\t\tPacketLength1\t\tdw\t?\n\nECB\t\tends\n\n\n\n;\n; Structures used for Get_Local_Target calls\n;\nrequest_local_target_buffer struct\n\t\tlt_network_number\tdb\t?,?,?,?\n\t\tlt_physical_node\tdb\t?,?,?,?,?,?\n\t\tlt_socket\t\tdw\t?\nrequest_local_target_buffer ends\n\n\nlocal_target_reply_buffer struct\n\t\tlt_local_target\t\tdb\t?,?,?,?,?,?\nlocal_target_reply_buffer ends\n\n\n\n\n\n\n;#############################################################################\n;\n; Start of code segment\n;\n;\n\t\t.code\n\n\t\t.386\t\t\t;now we can specify 386 instructions. Its still a 16 bit code segment though.\n\n\t\tinclude <pcmacro.16>\t;include 16 bit instruction macros\n\n\n\n;*************************************************************************************************\n;* _IPX_Initialise -- confirms the presence of IPX and gets the entry point for subsequent calls *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\teax - nothing                                                                    *\n;*                                                                                               *\n;* OUTPUT:      true if IPX was initialised                                                      *\n;*                                                                                               *\n;* 32bit PROTO:\textern BOOL __stdcall IPX_Initialise(void);                                      *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   01/29/96 ST: Created.                                                                       *\n;*===============================================================================================*\n\n_IPX_Initialise\tproc far pascal\n\n\t\tpush\tebx\n\t\tpush\tecx\n\t\tpush\tedx\n\t\tpush\tesi\n\t\tpush\tedi\n\t\tpush\tebp\n\t\tpush\tds\n\t\tpush\tes\n\t\tpush\tfs\n\t\tpush\tgs\n\n\t\t; Call the multiplex interrupt to confirm the presence of IPX\n\t\t; The real mode entry point is returned in es:di if present\n\t\t;\n\t\tmov\tax,7a00h\n\t\tint\t2fh\n\t\tand\teax,0ffh\n\t\tcmp\tal,-1\n\t\tsetz\tal\n\n\t\ttest\tal,al\n\t\tjz\t@f\n\n\t\t; Save the real mode entry point\n\t\t;\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\t[IPXCallSegment],es\n\t\tmov\t[IPXCallOffset],di\n\t\tmov\t[Listening],0\n\t\tmov\t[ListeningFailed],0\n\n@@:\t\tpop\tgs\n\t\tpop\tfs\n\t\tpop\tes\n\t\tpop\tds\n\t\tpop\tebp\n\t\tpop\tedi\n\t\tpop\tesi\n\t\tpop\tedx\n\t\tpop\tecx\n\t\tpop\tebx\n\t\tret\n\n_IPX_Initialise\tendp\n\n\n\n;*************************************************************************************************\n;* _IPX_Open_Socket95 -- opens the given socket number                                           *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tsocket - socket number to open                                                   *\n;*                                                                                               *\n;* OUTPUT:      0 if socket opened successfully                                                  *\n;*                                                                                               *\n;* 32bit PROTO:\textern int __stdcall IPX_Open_Socket95(int socket);                              *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   01/29/96 ST: Created.                                                                       *\n;*===============================================================================================*\n_IPX_Open_Socket95 proc far pascal uses bx cx dx si di ds es fs gs,\n\t\tsocket:word\n\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\tbx,IPX_OPEN_SOCKET\t;open socket\n\t\tmov_w\tdx,[socket]\t\t;socket number\n\t\tmov_w\t[MySocket],dx\t\t;save it for later\n\t\tmov\tax,0ffh\t\t\t;long lived\n\n\t\tcall\tCall_IPX\n\n\t\tret\n\n_IPX_Open_Socket95 endp\n\n\n\n\n;*************************************************************************************************\n;* IPX_Close_Socket95 -- closes the given socket number                                          *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tsocket - socket number to close                                                  *\n;*                                                                                               *\n;* OUTPUT:      nothing                                                                          *\n;*                                                                                               *\n;* 32bit PROTO:\textern void __stdcall IPX_Close_Socket95(int socket);                            *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   01/29/96 ST: Created.                                                                       *\n;*===============================================================================================*\n_IPX_Close_Socket95 proc far pascal uses ax bx cx dx si di ds es fs gs,\n\t\tsocket:word\n\n\t\tmov\tbx,1\n\t\tmov_w\tdx,[socket]\n\n\t\tcall\tCall_IPX\n\n\t\tret\n\n_IPX_Close_Socket95 endp\n\n\n\n\n\n\n\n;*************************************************************************************************\n;* _IPX_Get_Connection_Number95 -- get the users local 'connection number'                       *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tnothing                                                                          *\n;*                                                                                               *\n;* OUTPUT:      connection number. 0 if user isnt logged into novell                             *\n;*                                                                                               *\n;* 32bit PROTO:\textern int  __stdcall IPX_Get_Connection_Number95(void);                         *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   01/29/96 ST: Created.                                                                       *\n;*===============================================================================================*\n_IPX_Get_Connection_Number95 proc far pascal uses bx cx dx si di ds es fs gs\n\n\t\tmov\tax,0dc00h\n\t\tcall\tCall_DOS\n\t\tand\teax,255\n\t\tret\n\n_IPX_Get_Connection_Number95 endp\n\n\n\n\n\n\n\n\n\n;*************************************************************************************************\n;* _IPX_Send_Packet95 -- Send a packet via IPX                                                   *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tsend_address \t- ptr to address of destination for packet                       *\n;*              send_buffer  \t- ptr to data to be sent                                         *\n;*              send_buffer_len\t- length of data in send_buffer                                  *\n;*              network_num\t- network number                                                 *\n;*              node_address\t- node address                                                   *\n;*                                                                                               *\n;* OUTPUT:      true if successfully sent                                                        *\n;*                                                                                               *\n;* 32bit PROTO:\textern int  __stdcall IPX_Send_Packet95(unsigned char *, unsigned char *,        *\n;*\t\t\t\t\t\t\tint, unsigned char*, unsigned char*);    *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   01/29/96 ST: Created.                                                                       *\n;*===============================================================================================*\n_IPX_Send_Packet95 proc far pascal uses ebx ecx edx esi edi ds es fs gs,\n\t\tsend_address\t:far ptr byte,\n\t\tsend_buffer\t:far ptr byte,\n\t\tsend_buffer_len\t:word,\n\t\tnetwork_num\t:far ptr byte,\n\t\tnode_address\t:far ptr byte\n\n\t\tlocal\tselector\t:word\t\t\t;DOS memory selector\n\t\tlocal\tsegmento\t:word\t\t\t;DOS memory segment\n\t\tlocal\tdos_send_ecb\t:far ptr ECB\t\t;ptr to send ECB\n\t\tlocal\tdos_send_header\t:far ptr IPXHeaderType\t;ptr to IPX header for sending\n\t\tlocal\tdos_send_buffer\t:far ptr byte\t\t;ptr to copy of buffer to be sent\n\t\tlocal\tcompletion_code\t:word\t\t\t;IPX send packet completion code\n\n\t\t; Allocate required DOS memory\n\t\t; GlobalDosAlloc is a win3.1 API function for allocating and locking DOS memory\n\t\t; GlobalDosAlloc returns the segment in dx and a selector in ax\n\t\txor\tax,ax\n\t\tmov\tbx,(sizeof ECB + sizeof IPXHeaderType + 1024 +31)\n\t\tpush\tbp\n\t\tpush\tax\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSALLOC\n\t\tpop\tbp\n\t\ttest\tax,ax\n\t\tjz\t@@error\n\t\tmov\t[segmento],dx\t;save the segment pointer\n\t\tmov\t[selector],ax\t;save the selector pointer\n\n\t\t;\n\t\t; Set up the pointers to the dos memory\n\t\t;\n\t\tmov_w\t[dos_send_ecb+OFFS],SEND_ECB_OFFSET\n\t\tmov_w\t[dos_send_ecb+SEGM],ax\n\t\tmov_w\t[dos_send_header+OFFS],SEND_HEADER_OFFSET\n\t\tmov_w\t[dos_send_header+SEGM],ax\n\t\tmov_w\t[dos_send_buffer+OFFS],SEND_BUFFER_OFFSET\n\t\tmov_w\t[dos_send_buffer+SEGM],ax\n\n\t\t;\n\t\t; Clear out the send ECB\n\t\t;\n\t\txor\tal,al\n\t\tmov\tcx,sizeof ECB\n\t\tles\tdi,[dos_send_ecb]\n\t\trep\tstosb\n\n\t\t;\n\t\t; Clear out the send IPX header\n\t\t;\n\t\tmov\tcx,sizeof IPXHeaderType\n\t\tles\tdi,[dos_send_header]\n\t\trep\tstosb\n\n\t\t;\n\t\t; Copy the data to be sent into the DOS memory send buffer\n\t\t;\n\t\tmov\tcx,546\t\t;maximum size of IPX data packet\n\t\tcmp_w\tcx,[send_buffer_len]\n\t\tjle\t@@got_buffer_len\n\t\tmov_w\tcx,[send_buffer_len]\n@@got_buffer_len:\n\t\tles\tdi,[dos_send_buffer]\n\t\tlds\tsi,[send_buffer]\n\t\trep\tmovsb\n\n\t\t;\n\t\t; Fill in the send ECB\n\t\t;\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\tfs,ax\t\t\t;keep ptr to data seg in fs\n\t\tles\tdi,[dos_send_ecb]\n\n\t\tmov\tax,[MySocket]\n\t\tmov\tes:[di.SocketNumber],ax\n\t\tmov\tes:[di.PacketCount],2\n\t\tmov\tax,[selector]\n\t\tshl\teax,16\n\t\tmov_w\tax,[dos_send_header+OFFS]\n\t\tmov_d\tes:[di.PacketAddress0],eax\n\t\tmov_w\tes:[di.PacketLength0],sizeof IPXHeaderType\n\t\tmov_w\tax,[dos_send_buffer+OFFS]\n\t\tmov_d\tes:[di.PacketAddress1],eax\n\t\tmov_w\tax,[send_buffer_len]\n\t\tmov_w\tes:[di.PacketLength1],ax\n\n\t\t;\n\t\t; Fill in the address field\n\t\t;\n\t\tlds\tsi,[send_address]\n\t\tmov\teax,[si]\n\t\tmov_d\tes:[di.ImmediateAddress],eax\n\t\tmov\tax,[si+4]\n\t\tmov_w\tes:[di.ImmediateAddress+4],ax\n\n\t\t;\n\t\t; Fill in the outgoing header\n\t\t;\n\t\tles\tdi,[dos_send_header]\n\t\tmov\tes:[di.PacketType],4\n\t\tpush\tfs:[MySocket]\n\t\tpop\tes:[di.DestNetworkSocket]\n\n\t\t;\n\t\t; Fill in the network number and node address\n\t\t;\n\t\tlds\tsi,[network_num]\n\t\tmov_d\teax,[si]\n\t\tmov_d\tes:[di.DestNetworkNumber],eax\n\t\tlds\tsi,[node_address]\n\t\tmov_d\teax,[si]\n\t\tmov_d\tes:[di.DestNetworkNode],eax\n\t\tmov_w\tax,[si+4]\n\t\tmov_w\tes:[di.DestNetworkNode+4],ax\n\n\t\t;\n\t\t; Send that sucker!\n\t\t;\n\t\tmov\tes,[selector]\n\t\tmov\tsi,SEND_ECB_OFFSET\n\t\tmov\tbx,IPX_SEND_PACKET\n\t\tpusha\n\t\tcall\tCall_IPX\n\t\tpopa\n\n\t\t;\n\t\t; Wait for the send to finish by monitoring the 'in use' flag of the ECB\n\t\t;\n@@wait_send_loop:\n\t\tlds\tsi,[dos_send_ecb]\n\t\tcmp\t[si.InUse],0\n\t\tjz\t@@done\n\n\t\t;\n\t\t; Let IPX 'breath' if send isnt complete\n\t\t;\n\t\tmov\tbx,IPX_RELINQUISH_CONTROL\n\t\tpush\tbp\n\t\tcall\tCall_IPX\n\t\tpop\tbp\n\t\tjmp\t@@wait_send_loop\n\n\n\t\t;\n\t\t; Get the completion code and save it for posterity\n\t\t;\n@@done:\t\tlds\tsi,[dos_send_ecb]\n\t\tmov\tal,[si.CompletionCode]\n\t\txor\tah,ah\n\t\tmov\t[completion_code],ax\n\n\t\t;\n\t\t; Free the DOS memory\n\t\t;\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\tes,bx\n\t\tmov\tfs,bx\n\t\tmov\tgs,bx\n\t\tmov\tbx,[selector]\n\t\tpush\tbp\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSFREE\n\t\tpop\tbp\n\n\t\t;\n\t\t; Set up the return value\n\t\t;\n\t\tcmp\t[completion_code],0\n\t\tjnz\t@@error\n\n@@success:\tmov\tax,1\n\t\tret\n\n@@error:\txor\tax,ax\n\t\tret\n\n\n_IPX_Send_Packet95 endp\n\n\n\n\n\n;*************************************************************************************************\n;* _IPX_Broadcast_Packet95 -- Broadcast a packet via IPX                                         *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tsend_buffer  \t- ptr to data to be sent                                         *\n;*              send_buffer_len\t- length of data in send_buffer                                  *\n;*                                                                                               *\n;* OUTPUT:      true if successfully sent                                                        *\n;*                                                                                               *\n;* 32bit PROTO:\textern int  __stdcall IPX_Broadcast_Packet95(unsigned char *, int);              *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   01/29/96 ST: Created.                                                                       *\n;*===============================================================================================*\n_IPX_Broadcast_Packet95 proc far pascal uses ebx ecx edx esi edi ds es fs gs,\n\t\tsend_buffer\t:far ptr byte,\n\t\tsend_buffer_len\t:word\n\n\t\tlocal\tselector\t:word\t\t\t;DOS memory selector\n\t\tlocal\tsegmento\t:word                   ;DOS memory segment\n\t\tlocal\tdos_send_ecb\t:far ptr ECB            ;ptr to send ECB\n\t\tlocal\tdos_send_header\t:far ptr IPXHeaderType  ;ptr to IPX header for sending\n\t\tlocal\tdos_send_buffer\t:far ptr byte           ;ptr to copy of buffer to be sent\n\t\tlocal\tcompletion_code\t:word                   ;IPX send packet completion code\n\n\t\t; Allocate required DOS memory\n\t\t; GlobalDosAlloc is a win3.1 API function for allocating and locking DOS memory\n\t\t; GlobalDosAlloc returns the segment in dx and a selector in ax\n\t\txor\tax,ax\n\t\tmov\tbx,(sizeof ECB + sizeof IPXHeaderType + 1024 +31)\n\t\tpush\tbp\n\t\tpush\tax\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSALLOC\n\t\tpop\tbp\n\t\ttest\tax,ax\n\t\tjz\t@@error\n\t\tmov\t[segmento],dx\t;save the segment pointer\n\t\tmov\t[selector],ax   ;save the selector pointer\n\n\t\t;\n\t\t; Set up the pointers to the dos memory\n\t\t;\n\t\tmov_w\t[dos_send_ecb+OFFS],SEND_ECB_OFFSET\n\t\tmov_w\t[dos_send_ecb+SEGM],ax\n\t\tmov_w\t[dos_send_header+OFFS],SEND_HEADER_OFFSET\n\t\tmov_w\t[dos_send_header+SEGM],ax\n\t\tmov_w\t[dos_send_buffer+OFFS],SEND_BUFFER_OFFSET\n\t\tmov_w\t[dos_send_buffer+SEGM],ax\n\n\t\t;\n\t\t; Clear out the send ECB\n\t\t;\n\t\txor\tal,al\n\t\tmov\tcx,sizeof ECB\n\t\tles\tdi,[dos_send_ecb]\n\t\trep\tstosb\n\n\t\t;\n\t\t; Clear out the send header\n\t\t;\n\t\tmov\tcx,sizeof IPXHeaderType\n\t\tles\tdi,[dos_send_header]\n\t\trep\tstosb\n\n\t\t;\n\t\t; Copy the data to be sent into the send buffer\n\t\t;\n\t\tmov\tcx,546\t\t;maximum size of IPX data packet\n\t\tcmp_w\tcx,[send_buffer_len]\n\t\tjle\t@@got_buffer_len\n\t\tmov_w\tcx,[send_buffer_len]\n@@got_buffer_len:\n\t\tles\tdi,[dos_send_buffer]\n\t\tlds\tsi,[send_buffer]\n\t\trep\tmovsb\n\n\t\t;\n\t\t; Fill in the ECB\n\t\t;\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\tfs,ax\t\t\t;keep ptr to data seg in fs\n\t\tles\tdi,[dos_send_ecb]\n\n\t\tmov\tax,[MySocket]\n\t\tmov\tes:[di.SocketNumber],ax\n\t\tmov\tes:[di.PacketCount],2\n\t\tmov\tax,[selector]\n\t\tshl\teax,16\n\t\tmov_w\tax,[dos_send_header+OFFS]\n\t\tmov_d\tes:[di.PacketAddress0],eax\n\t\tmov_w\tes:[di.PacketLength0],sizeof IPXHeaderType\n\t\tmov_w\tax,[dos_send_buffer+OFFS]\n\t\tmov_d\tes:[di.PacketAddress1],eax\n\t\tmov_w\tax,[send_buffer_len]\n\t\tmov_w\tes:[di.PacketLength1],ax\n\n\t\t;\n\t\t; Fill in the address field\n\t\t;\n\t\tmov_d\tes:[di.ImmediateAddress],0ffffffffh\n\t\tmov_w\tes:[di.ImmediateAddress+4],0ffffh\n\n\t\t;\n\t\t; Fill in the outgoing header\n\t\t;\n\t\tles\tdi,[dos_send_header]\n\t\tmov\tes:[di.PacketType],4\n\t\tpush\tfs:[MySocket]\n\t\tpop\tes:[di.DestNetworkSocket]\n\n\t\t;\n\t\t; Fill in the network number and node address\n\t\t;\n\t\tmov_d\tes:[di.DestNetworkNumber],0ffffffffh\n\t\tmov_d\tes:[di.DestNetworkNode],0ffffffffh\n\t\tmov_w\tes:[di.DestNetworkNode+4],0ffffh\n\n\t\t;\n\t\t; Send that sucker!\n\t\t;\n\t\tmov\tes,[selector]\n\t\tmov\tsi,SEND_ECB_OFFSET\n\t\tmov\tbx,IPX_SEND_PACKET\n\t\tpusha\n\t\tpush\tfs\n\t\tcall\tCall_IPX\n\t\tpop\tfs\n\t\tpopa\n\n\t\t;\n\t\t; Wait for the send to finish by monitoring the 'in use' flag of the ECB\n\t\t;\n@@wait_send_loop:\n\t\tlds\tsi,[dos_send_ecb]\n\t\tcmp\t[si.InUse],0\n\t\tjz\t@@done\n\n\t\t;\n\t\t; Let IPX 'breath' if send isnt complete\n\t\t;\n\t\tmov\tbx,IPX_RELINQUISH_CONTROL\n\t\tpush\tbp\n\t\tcall\tCall_IPX\n\t\tpop\tbp\n\t\tjmp\t@@wait_send_loop\n\n\n\t\t;\n\t\t; Get the completion code and save it for posterity\n\t\t;\n@@done:\t\tlds\tsi,[dos_send_ecb]\n\t\tmov\tal,[si.CompletionCode]\n\t\txor\tah,ah\n\t\tmov\t[completion_code],ax\n\n\t\t;\n\t\t; Free the DOS memory\n\t\t;\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\tes,bx\n\t\tmov\tfs,bx\n\t\tmov\tgs,bx\n\t\tmov\tbx,[selector]\n\t\tpush\tbp\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSFREE\n\t\tpop\tbp\n\n\t\t;\n\t\t; Set up the return value\n\t\t;\n\t\tcmp\t[completion_code],0\n\t\tjnz\t@@error\n\n@@success:\tmov\tax,1\n\t\tret\n\n@@error:\txor\tax,ax\n\t\tret\n\n\n_IPX_Broadcast_Packet95 endp\n\n\n\n\n\n\n;*************************************************************************************************\n;* _IPX_Get_Local_Target95 -- Gets the node address of a destination or bridge                   *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tdest_network \t- ptr to network number of target                                *\n;*              dest_node\t- ptr to node number of target                                   *\n;*              socket\t\t- socket number                                                  *\n;*              bridge_address\t- ptr to buffer to store immediate address in                    *\n;*                                                                                               *\n;* OUTPUT:      IPX result code. -1 if error                                                     *\n;*                                                                                               *\n;* 32bit PROTO:\textern int  __stdcall IPX_Get_Local_Target95(unsigned char *, unsigned char*,    *\n;*\t\t\t\t\t\t\t unsigned short, unsigned char*);        *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   01/29/96 ST: Created.                                                                       *\n;*===============================================================================================*\n\n_IPX_Get_Local_Target95\tproc far pascal uses ebx ecx edx esi edi ds es fs gs,\n\t\tdest_network\t:far ptr byte,\n\t\tdest_node\t:far ptr byte,\n\t\tsocket\t\t:word,\n\t\tbridge_address\t:far ptr byte\n\n\t\tlocal\tsegmento\t:word\t; DOS memory segment\n\t\tlocal\tselector\t:word\t; DOS memory selector\n\t\tlocal\tresult_code\t:word\t; return code\n\n\t\t; Allocate required DOS memory for data passed to IPX\n\t\t; GlobalDosAlloc is a win3.1 API function for allocating and locking DOS memory\n\t\t; GlobalDosAlloc returns the segment in dx and a selector in ax\n\t\txor\tax,ax\n\t\tmov\tbx,(sizeof local_target_reply_buffer + \\\n\t\t\t    sizeof request_local_target_buffer + 15)\n\t\tpush\tbp\n\t\tpush\tax\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSALLOC\n\t\tpop\tbp\n\t\ttest\tax,ax\n\t\tjz\t@@return_error\n\n\t\tmov\t[segmento],dx\t; save the segment\n\t\tmov\t[selector],ax\t; save the selector\n\t\tmov\tfs,ax\n\t\txor\tdi,di\n\n\t\t;\n\t\t; Init the request structure\n\t\t;\n\t\tlds\tsi,[dest_network]\n\t\tmov_d\teax,[si]\n\t\tmov_d\tfs:[di.lt_network_number],eax\n\t\tlds\tsi,[dest_node]\n\t\tmov\teax,[si]\n\t\tmov_d\tfs:[di.lt_physical_node],eax\n\t\tmov_w\tax,[si+4]\n\t\tmov_w\tfs:[di.lt_physical_node+4],ax\n\t\tmov\tax,[socket]\n\t\tmov\tfs:[di.lt_socket],ax\n\n\t\t;\n\t\t; Set up the registers to call IPX\n\t\t;\n\t\tmov\tbx,IPX_GET_LOCAL_TARGET\n\t\tmov\tax,[selector]\n\t\tmov\tds,ax\n\t\txor\tsi,si\n\t\tmov\tes,ax\n\t\tmov\tdi,sizeof request_local_target_buffer\n\n\t\t;\n\t\t; Call IPX\n\t\t;\n\t\tpush\tbp\n\t\tcall\tCall_IPX\n\t\tpop\tbp\n\n\t\t;\n\t\t; Save the result code so we can return it\n\t\t;\n\t\tmov\t[result_code],ax\n\n\t\t;\n\t\t; Copy the bridge address into the return buffer\n\t\t;\n\t\tmov\tds,[selector]\n\t\tmov\tsi,sizeof request_local_target_buffer + lt_local_target\n\t\tles\tdi,[bridge_address]\n\t\tmovsd\n\t\tmovsw\n\n\t\t;\n\t\t; Free the DOS memory\n\t\t;\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\tes,bx\n\t\tmov\tfs,bx\n\t\tmov\tgs,bx\n\t\tmov\tbx,[selector]\n\t\tpush\tbp\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSFREE\n\t\tpop\tbp\n\n\t\t;\n\t\t; Return the IPX result code\n\t\t;\n\t\tmov\tax,[result_code]\n\t\tret\n\n@@return_error:\tmov\tax,-1\n\t\tret\n\n_IPX_Get_Local_Target95\tendp\n\n\n\n;*************************************************************************************************\n;* _IPX_Get_Outstanding_Buffer95 -- return contents of the next unread buffer in the buffer list *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tcopy_receive_buffer -- ptr to buffer that data will be copied to                 *\n;*                                                                                               *\n;* OUTPUT:      number of buffers returned (0 or 1)                                              *\n;*                                                                                               *\n;* 32bit PROTO:\textern BOOL __stdcall IPX_Get_Outstanding_Buffer95(unsigned char *buffer);       *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   01/29/96 ST: Created.                                                                       *\n;*===============================================================================================*\n\n_IPX_Get_Outstanding_Buffer95 proc far pascal uses ebx ecx edx esi edi ebp ds es fs gs,\n\t\tcopy_receive_buffer:far ptr byte\n\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\n\t\t;\n\t\t; If the receive buffer pointer is the same as the pointer to the last buffer\n\t\t; returned then there is no outstanding data to return so just exit\n\t\t;\n\t\txor\tax,ax\n\t\tmov\tsi,[LastPassedReceiveBuffer]\n\t\tcmp\tsi,[CurrentReceiveBuffer]\n\t\tjz\t@@done\n\n\t\t;\n\t\t; Copy the IPX receive data buffer into the buffer provided by the caller\n\t\t;\n\t\tpush\tds\n\t\tmov\tcx,RECEIVE_BUFFER_LENGTH/4\n\t\tmov\tds,[ReceiveBufferSelector]\n\t\tles\tdi,[copy_receive_buffer]\n\t\trep\tmovsd\n\t\tpop\tds\n\n\t\t;\n\t\t; Update the pointer to the last buffer we copied\n\t\t;\n\t\tcmp\tsi,RECEIVE_BUFFER_LENGTH*MAX_RECEIVE_BUFFERS\n\t\tjc\t@@no_wrap\n\t\txor\tsi,si\n@@no_wrap:\tmov\t[LastPassedReceiveBuffer],si\n\n\t\tmov\tax,1\n\n@@done:\t\tret\n\n_IPX_Get_Outstanding_Buffer95 endp\n\n\n\n\n;*************************************************************************************************\n;* Receive_Callback -- IPX callback function. Called when a new packet arrives                   *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tnothing                                                                          *\n;*                                                                                               *\n;* OUTPUT:      nothing                                                                          *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   01/29/96 ST: Created.                                                                       *\n;*===============================================================================================*\nReceive_Callback proc far\n\n\t\t;\n\t\t; Save everything\n\t\t;\n\t\tpushf\n\t\tcli\n\t\tcld\n\t\tpushad\n\t\tpush\tds\n\t\tpush\tes\n\t\tpush\tfs\n\t\tpush\tgs\n\n\t\t;\n\t\t; Dont reenter\n\t\t;\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tcmp\t[NoReenter],0\n\t\tjnz\t@@out\n\t\tmov\t[NoReenter],1\n\n\t\t;\n\t\t; Update the receive buffer pointer to point to the next buffer\n\t\t;\n\t\tmov\tax,[CurrentReceiveBuffer]\n\t\tadd\tax,RECEIVE_BUFFER_LENGTH\n\t\tcmp\tax,RECEIVE_BUFFER_LENGTH*MAX_RECEIVE_BUFFERS\n\t\tjc\t@@no_wrap\n\t\txor\tax,ax\n@@no_wrap:\tmov\t[CurrentReceiveBuffer],ax\n\n\t\t;\n\t\t; Listen for another packet\n\t\t;\n\t\tcall\tListen_For_Packet\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\t[NoReenter],0\n\n\t\t;\n\t\t; Restore everything and exit\n\t\t;\n@@out:\t\tpop\tgs\n\t\tpop\tfs\n\t\tpop\tes\n\t\tpop\tds\n\t\tpopad\n\t\tpopf\n\t\tret\n\nReceive_Callback endp\n\n\n\n\n;*************************************************************************************************\n;* Init_Receive_ECB -- initialises an ECB for receiving a packet                                 *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tnothing                                                                          *\n;*                                                                                               *\n;* OUTPUT:      nothing                                                                          *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   01/29/96 ST: Created.                                                                       *\n;*===============================================================================================*\n\nInit_Receive_ECB proc near uses eax ebx ecx edx esi edi ebp ds es\n\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\tes,[ReceiveBufferSelector]\n\n\t\t;\n\t\t; Clear out the ECB\n\t\t;\n\t\tmov\tdi,[ReceiveECBOffset]\n\t\tmov\tcx,sizeof ECB\n\t\txor\tal,al\n\t\trep\tstosb\n\n\n\t\t;\n\t\t; Set up the ECB\n\t\t;\n\n\t\t;\n\t\t;General ECB data\n\t\tmov\tdi,[ReceiveECBOffset]\n\t\tmov\tax,[MySocket]\n\t\tmov\tes:[di.SocketNumber],ax\n\t\tmov\tes:[di.PacketCount],2\n\n\t\t;\n\t\t; Packet address for IPX header\n\t\tmov\tax,[CurrentReceiveBuffer]\n\t\tmov\tbx,[ReceiveBufferSelector]\n\t\tmov_w\tes:[di.PacketAddress0+OFFS],ax\n\t\tmov_w\tes:[di.PacketAddress0+SEGM],bx\n\t\tmov\tes:[di.PacketLength0],sizeof IPXHeaderType\n\n\t\t;\n\t\t; Packet address for receive buffer\n\t\tmov\tax,[CurrentReceiveBuffer]\n\t\tadd\tax,sizeof IPXHeaderType\n\t\tmov_w\tes:[di.PacketAddress1+OFFS],ax\n\t\tmov_w\tes:[di.PacketAddress1+SEGM],bx\n\t\tmov\tes:[di.PacketLength1],546\n\n\t\t;\n\t\t; Set up the callback address\n\t\tmov_w\tes:[di.Event_Service_Routine+OFFS],offset Receive_Callback\n\t\tmov_w\tes:[di.Event_Service_Routine+SEGM],cs\n\n\t\tret\n\nInit_Receive_ECB endp\n\n\n\n;*************************************************************************************************\n;* _IPX_Start_Listening95 -- initialise DOS memory for receive buffers and start listening for   *\n;*                           IPX packets                                                         *\n;*                                                                                               *\n;* INPUT:\tnothing                                                                          *\n;*                                                                                               *\n;* OUTPUT:      true if we started listening                                                     *\n;*                                                                                               *\n;* 32bit PROTO:\textern BOOL __stdcall IPX_Start_Listening95(void);                               *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   01/29/96 ST: Created.                                                                       *\n;*===============================================================================================*\n_IPX_Start_Listening95 proc far pascal uses ebx ecx edx esi edi ebp ds es fs gs\n\n\t\t;\n\t\t; Check that we arent already listening\n\t\t;\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tcmp\t[ListeningFailed],0\n\t\tjnz\t@@restart\n\t\tcmp\t[Listening],0\n\t\tjnz\t@@out\t\t;already listening\n\n\t\t;\n\t\t; Allocate and lock DOS memory for listen ECB and receive buffers\n\t\t; GlobalDosAlloc is a win3.1 API function for allocating and locking DOS memory\n\t\t; GlobalDosAlloc returns the segment in dx and a selector in ax\n\t\tmov\tbx,(RECEIVE_BUFFER_LENGTH*MAX_RECEIVE_BUFFERS + sizeof ECB + 15)\n\t\txor\tax,ax\n\t\tsave\tbp,ds\n\t\tpush\tax\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSALLOC\n\t\trestore\tbp,ds\n\t\ttest\tax,ax\n\t\tjz\t@@error\n\n\t\tmov\t[ReceiveBufferSegment],dx\t;save the DOS memory segment in a global\n\t\tmov\t[ReceiveBufferSelector],ax      ;save the DOS memory selector in a global\n\n\tsaveall\n;\tint\t3\n\tmov\tax,@data\n\tmov\tes,ax\n\tmov\tax,0bh\n\tmov\tbx,es:[ReceiveBufferSelector]\n\tmov\tdi,offset OriginalReceiveDescriptor\n\tint\t31h\n\tbcc\t@f\n;\tint\t3\n@@:\trestall\n\n\n\t\t;\n\t\t; Set up pointers to the DOS memory\n\t\t;\n\t\tmov\t[ReceiveECBOffset],RECEIVE_BUFFER_LENGTH * MAX_RECEIVE_BUFFERS\n\t\tmov\t[CurrentReceiveBuffer],0\t;1st receive buffer\n\t\tmov\t[LastPassedReceiveBuffer],0\n\n\t\t;\n\t\t; Start listening\n\t\t;\n@@restart:\tmov\t[ListeningFailed],0\n\t\tpush\tds\n\t\tcall\tListen_For_Packet\n\t\tpop\tds\n\t\tmov\t[Listening],1\n\n@@out:\t\tmov\tax,1\n\t\tret\n\n@@error:\txor\tax,ax\n\t\tret\n\n_IPX_Start_Listening95 endp\n\n\n\n;*************************************************************************************************\n;* _IPX_Shut_Down95 -- finish an IPX session. Releases any allocated resources except the socket *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tnothing                                                                          *\n;*                                                                                               *\n;* OUTPUT:      nothing                                                                          *\n;*                                                                                               *\n;* 32bit PROTO:\textern void __stdcall IPX_Shut_Down95(void);                                     *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   01/29/96 ST: Created.                                                                       *\n;*===============================================================================================*\n\n_IPX_Shut_Down95 proc far pascal uses eax ebx ecx edx esi edi ebp ds es fs gs\n\n\t\t;\n\t\t; If we aren't listening then we cant stop\n\t\t;\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tcmp\t[Listening],0\n\t\tjz\t@@out\n\n\t\t;\n\t\t; Stop listening for a packet\n\t\t;\n\t\tmov\tes,[ReceiveBufferSelector]\n\t\tmov\tsi,[ReceiveECBOffset]\n\t\tmov\tbx,IPX_CANCEL_EVENT\n\t\tsave\tbp,ds\n\t\tcall\tCall_IPX\n\t\trestore\tbp,ds\n\n\t\t;\n\t\t; Free the DOS memory\n\t\t;\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\tes,ax\n\t\tmov\tax,[ReceiveBufferSelector]\n\t\tsave\tbp,ds\n\t\tpush\tax\n\t\tcall\tGLOBALDOSFREE\n\t\trestore\tbp,ds\n\n\t\tmov\t[Listening],0\n\n@@out:\t\tret\n\n_IPX_Shut_Down95 endp\n\n\n\n\n\nVerify_Selectors proc near uses eax ebx ecx edx esi edi ebp ds es fs gs\n\n;\t\tint \t3\n\t\tmov\tax,1686h\n\t\tint\t2fh\n\t\ttest\tax,ax\n\t\tjnz\t@@fail\n\n\t\tmov\tax,@data\n\t\tmov\tes,ax\n\t\tmov\tax,0bh\n\t\tmov\tbx,es:[ReceiveBufferSelector]\n\t\tmov\tdi,offset ReceiveDescriptor\n\t\tint\t31h\n\t\tbcs\t@@fail\n\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov_d\teax,[ReceiveDescriptor]\n\t\tcmp_d\teax,[OriginalReceiveDescriptor]\n\t\tjnz\t@@fail\n\t\tmov_d\teax,[ReceiveDescriptor+4]\n\t\tcmp_d\teax,[OriginalReceiveDescriptor+4]\n\t\tjnz\t@@fail\n\t\tclc\n\t\tret\n\n@@fail:\t\tstc\n\t\tret\n\nVerify_Selectors endp\n\n\n\n\n;*************************************************************************************************\n;* Listen_For_Packet -- Start IPX listening for an incoming packet                               *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tnothing                                                                          *\n;*                                                                                               *\n;* OUTPUT:      nothing                                                                          *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   01/29/96 ST: Created.                                                                       *\n;*===============================================================================================*\n\nListen_For_Packet proc near uses eax ebx ecx edx esi edi ebp ds es fs gs\n\n\t\tcall\tVerify_Selectors\n\t\tbcs\t@@fail\n\n\t\tcall\tInit_Receive_ECB\n\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\tes,[ReceiveBufferSelector]\n\t\tmov\tsi,[ReceiveECBOffset]\n\t\tmov\tbx,IPX_LISTEN_FOR_PACKET\n\t\tpush\tds\n\t\tcall\tCall_IPX\n\t\tpop\tds\n\t\tret\n\n@@fail:\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\t[ListeningFailed],1\n\t\tret\n\n\nListen_For_Packet endp\n\n\n\n\n\n;*************************************************************************************************\n;* Call_IPX -- Make a call to the IPX entry point                                                *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tregisters set up for the IPX call                                                *\n;*                                                                                               *\n;* OUTPUT:      registers returned by IPX                                                        *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   01/29/96 ST: Created.                                                                       *\n;*===============================================================================================*\nCall_IPX\tproc far\n\n\t\tpush\tgs\n\t\tpush\tax\n\t\tmov\tax,@data\n\t\tmov\tgs,ax\n\t\tpop\tax\n\n\t       \tpush\tbp\n\t\tmov\tbp,offset IPXCallOffset\n\t\tcall\tdword ptr gs:[bp]\n\t\tpop\tbp\n\n\t\tpop\tgs\n\t\tret\n\nCall_IPX\tendp\n\n\n\n\n\n\n\n;*************************************************************************************************\n;* Call_DOS -- use DPMI to call a DOS interrupt service                                          *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tregisters set up for the DOS call                                                *\n;*                                                                                               *\n;* OUTPUT:      registers returned by DOS                                                        *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   01/29/96 ST: Created.                                                                       *\n;*===============================================================================================*\n\nCall_DOS\tproc far\n\n\t\tpush\tgs\n\t\tpush\tax\n\t\tmov\tax,@data\n\t\tmov\tgs,ax\n\t\tpop\tax\n\n\t\t;\n\t\t; Dump the registers first so we can use them\n\t\t;\n\t\tmov_d\tgs:[RegisterDump],edi\n\t\tmov_d\tgs:[RegisterDump+4],esi\n\t\tmov_d\tgs:[RegisterDump+8],ebp\n\t\tmov_d\tgs:[RegisterDump+10h],ebx\n\t\tmov_d\tgs:[RegisterDump+14h],edx\n\t\tmov_d\tgs:[RegisterDump+18h],ecx\n\t\tmov_d\tgs:[RegisterDump+1ch],eax\n\n\t\t;\n\t\t; Dump the flags\n\t\t;\n\t\tpushf\n\t\tpop\tgs:[word ptr RegisterDump+20h]\n\n\t\t;\n\t\t; Save the segment registers\n\t\t;\n\t\tmov_w\tgs:[RegisterDump+22h],es\n\t\tmov_w\tgs:[RegisterDump+24h],ds\n\t\tmov_w\tgs:[RegisterDump+26h],fs\n\t\tmov_w\tgs:[RegisterDump+28h],gs\n\n\t\t;\n\t\t; Set up stack addr to zero - DPMI will supply a real mode stack\n\t\t;\n\t\txor\tax,ax\n\t\tmov_w\tgs:[RegisterDump+2eh],ax\t;sp\n\t\tmov_w\tgs:[RegisterDump+30h],ax\t;ss\n\n\t\tmov\tax,DPMI_CALL_REAL_INT\t; Simulate real mode interrupt\n\t\txor\tbh,bh\t\t\t; flags - should be zero\n\t\tmov\tbl,21h\t\t\t; interrupt number\n\t\tmov\tecx,0\t\t\t; number of words to copy from the protected mode stack\n\t\tmov\tdi,offset RegisterDump\n\t\tpush\tgs\n\t\tpop\tes\n\t\tpush\tgs\n\t\tint\t31h\t\t\t;DPMI interrupt\n\t\tpop\tgs\n\n\t\t;\n\t\t; Get the return registers\n\t\t;\n\t\tmov_d\tedi,gs:[RegisterDump]\n\t\tmov_d\tesi,gs:[RegisterDump+4]\n\t\tmov_d\tebp,gs:[RegisterDump+8]\n\t\tmov_d\tebx,gs:[RegisterDump+10h]\n\t\tmov_d\tedx,gs:[RegisterDump+14h]\n\t\tmov_d\tecx,gs:[RegisterDump+18h]\n\t\tmov_d\teax,gs:[RegisterDump+1ch]\n\t\tmov_w\tes,gs:[RegisterDump+22h]\n\t\tmov_w\tds,gs:[RegisterDump+24h]\n\t\tpop\tgs\n\n\t\tret\n\n\nCall_DOS\tendp\n\n\n\n\n\t\tend\n\n\n\n\n\n\n"
  },
  {
    "path": "IPX/IPX16C.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n\n\n#include <windows.h>\n\nextern \"C\"{\n\textern BOOL FAR __pascal ASM_IPX_Initialise(void);\n\textern BOOL FAR __pascal ASM_IPX_Uninitialise(void);\n}\n\n\nextern \"C\"{\n\tBOOL FAR __pascal _export IPX_Initialise(int);\n\tvoid FAR __pascal _export IPX_Uninitialise(void);\n}\n\n\n\nint CALLBACK LibMain (HANDLE, WORD, WORD, LPSTR)\n{\n\treturn (1);\n}\n\n\n\nBOOL FAR __pascal _export IPX_Initialise(int)\n{\n\n\treturn (ASM_IPX_Initialise());\n\n}\n\n\n\nvoid FAR __pascal _export IPX_Uninitialise(void)\n{\n\n\tASM_IPX_Uninitialise();\n\n}\n\n\n\n\n"
  },
  {
    "path": "IPX/IPXTEST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#define WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n\n#include <windows.h>\n\n\n\nint PASCAL WinMain ( HINSTANCE instance , HINSTANCE , char *, int)\n{\n\n\n\n\n}\n\n\n\n"
  },
  {
    "path": "IPX/MAKE.BAK",
    "content": "set include >temp.txt\nset include=c:\\wat\\h;c:\\wat\\h\\win\ncopy setinc.bat+temp.txt setinc2.bat\nwpp -ml -bd -zu -bt=windows -0 ipx16c.cpp\ntasm /ml ipx16a.asm\nwlink @ipx16.lnk\nwlib -c -n wwipx16.lib +wwipx16.dll\ncall setinc2.bat\n"
  },
  {
    "path": "IPX/MAKE.BAT",
    "content": "set include >temp.txt\nset include=c:\\wat\\h;c:\\wat\\h\\win\ncopy setinc.bat+temp.txt setinc2.bat\nwpp -s -ml -bd -zu -bt=windows -0 ipx16c.cpp\ntasm /ml ipx16a.asm\nwlink @ipx16.lnk\nwlib -c -n wwipx16.lib +wwipx16.dll\ncall setinc2.bat\n"
  },
  {
    "path": "IPX/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n.nocheck\n\nALL:\tthipx32.dll &\n\tthipx16.dll\n\nthipx32.dll: thipx.thk thipx32c.cpp thmap32.asm thipx32.lnk\n\tmaketh32\n\nthipx16.dll: thipx.thk thipx16a.asm thipx16c.cpp thmap16.asm thipx16.lnk\n\tmaketh16\n\n\n\n\n"
  },
  {
    "path": "IPX/MAKETH16.BAK",
    "content": "set include >temp.txt\nset include=c:\\wat\\h;c:\\wat\\h\\win\ncopy setinc.bat+temp.txt setinc2.bat\nthunk Thipx.thk\nwpp -ml -bd -zu -bt=windows -0 thipx16c.cpp\nml /c /W3 ipx16a.asm\nml /DIS_16 /c /W3 /Fothipx16a.obj thipx.asm\nml /c /W3 thmap16.asm\nml /c /W3 ipx16a.asm\nwlink @thipx16.lnk\nrc -40 thipx16.dll\ncall setinc2.bat\n"
  },
  {
    "path": "IPX/MAKETH16.BAT",
    "content": "set include >temp.txt\nset include=c:\\wat\\h;c:\\wat\\h\\win\ncopy setinc.bat+temp.txt setinc2.bat\nthunk Thipx.thk\nwpp -ml -bd -zu -bt=windows -0 thipx16c.cpp\nml /c /W3 ipx16a.asm\nml /DIS_16 /c /W3 /Fothipx16a.obj thipx.asm\nml /c /W3 thmap16.asm\nwlink @thipx16.lnk\nrc -40 thipx16.dll\ncall setinc2.bat\n"
  },
  {
    "path": "IPX/MAKETH32.BAK",
    "content": "rem thunk Thipx.thk\nrem fixthunk\nwpp386 -s -mf -3s -bt=nt -bd -zu -4 thipx32c.cpp\nml /DIS_32 /Zf /Fl /c /W3 /Fothipx32a.obj thipx.asm\nml /c /W3 thmap32.asm\nwlink @thipx32.lnk\nwlib -c -n wwipx32.lib +thipx32.dll\n"
  },
  {
    "path": "IPX/MAKETH32.BAT",
    "content": "thunk Thipx.thk\nrem fixthunk\nwpp386 -s -mf -3s -bt=nt -bd -zu -4 thipx32c.cpp\nml /DIS_32 /Zf /Fl /c /W3 /Fothipx32a.obj thipx.asm\nml /c /W3 thmap32.asm\nwlink @thipx32.lnk\nwlib -c -n wwipx32.lib +thipx32.dll\n"
  },
  {
    "path": "IPX/OK/FIXTHUNK.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#include <windows.h>\n#include <sys\\types.h>\n#include <sys\\stat.h>\n#include <fcntl.h>\n#include <io.h>\n#include <stdio.h>\n\n\nunsigned char thunk_file[1000000];\nunsigned char thunk_file_out[100050];\n\n\n/***********************************************************************************************\n * Search_For_String -- search for a string of chars within a buffer                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    string                                                                            *\n *           ptr to buffer to search in                                                        *\n *           length of buffer                                                                  *\n *                                                                                             *\n * OUTPUT:   ptr to string in buffer or NULL if not found                                      *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:42PM ST : Created                                                             *\n *=============================================================================================*/\n\nchar *Search_For_String (char *string , char *buffer_ptr , int buffer_length)\n{\n\tint\tj;\n\tint\tstring_length=strlen(string);\n\n\tfor (int i=0 ; i<buffer_length-string_length ; i++){\n\n\t\tfor (j=0 ; j<string_length ; j++){\n\t\t\tif ( *(string+j) != *(buffer_ptr+i+j)) break;\n\t\t}\n\t\tif (j==string_length) return buffer_ptr+i;\n\t}\n\n\treturn (NULL);\n\n}\n\n\n\n\nint main(int argc, char *argv[])\n{\n\tint\thandle;\n\tchar\tfind_string[]={\";************************ START OF THUNK BODIES************************\"};\n\tchar\tfind_other_string[]={\"public _IPX_Initialise@4\"};\n\n\tchar\tinsert_string1[]={\"\\n\\r;\\n\\r\"};\n\tchar\tinsert_string2[]={\";For some reason, inserting these lines makes it assemble correctly\\n\\r\"};\n\tchar\tinsert_string3[]={\";\\n\\r\"};\n\tchar\tinsert_string4[]={\"Externdef   IPX_Initialise:near\\n\\r\"};\n\tchar\tinsert_string5[]={\"IPX_Initialise label near\\n\\r\\n\\r\"};\n\n\tunsigned char *pointer;\n\tunsigned char *pointer2;\n\tint\tcopy_length;\n\tint\tfile_length;\n\n\thandle = open (\"thipx.asm\", O_RDONLY | O_BINARY);\n\n\tif (handle==-1)return (1);\n\n\tfile_length = filelength(handle);\n\n\tif (read (handle, thunk_file, file_length) != file_length){\n\t\tclose (handle);\n\t\treturn (1);\n\t}\n\n\tclose (handle);\n\n\tpointer = (unsigned char*)Search_For_String(find_string, (char*)thunk_file, file_length);\n\n\tif (pointer){\n\n\t\tpointer += strlen(find_string);\n\n\t\tcopy_length = (int)( (int)pointer - (int)&thunk_file[0]);\n\n\t\tmemcpy (thunk_file_out, thunk_file, copy_length);\n\n\t\tsprintf ((char*)&thunk_file_out[copy_length], \"%s%s%s%s%s\", \tinsert_string1,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tinsert_string2,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tinsert_string3,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tinsert_string4,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tinsert_string5);\n\n\n\t\tpointer2 = (unsigned char*)Search_For_String(find_other_string, (char*)pointer, file_length);\n\t\tif (!pointer2) return (1);\n\t\tpointer2 += strlen(find_other_string);\n\n\t\tmemcpy (&thunk_file_out [copy_length+ strlen(insert_string1)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ strlen(insert_string2)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ strlen(insert_string3)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ strlen(insert_string4)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ strlen(insert_string5)],\n\t\t\t\t\tpointer2,\n\t\t\t\t\tfile_length-((int)pointer2-(int)&thunk_file[0]));\n\n\n\t\thandle = open (\"thipx.asm\", O_WRONLY | O_BINARY | O_TRUNC);\n\n\t\tif (handle == -1) return (1);\n\n\t\twrite (handle, thunk_file_out, file_length+ strlen(insert_string1)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ strlen(insert_string2)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ strlen(insert_string3)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ strlen(insert_string4)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ strlen(insert_string5));\n\n\t\tclose (handle);\n\t}\n\n\treturn (0);\n}\n\n\n"
  },
  {
    "path": "IPX/OK/IPX.RC",
    "content": "\n\n"
  },
  {
    "path": "IPX/OK/IPX16.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\n\n\t\tIDEAL\n\t\tP386N\n\t\tLOCALS ??\n\n\n\n\t\tsegment realcode para public USE16 'code'\n\n\nglobal\t\tPASCAL ASM_IPX_INITIALISE:far\nglobal\t\tPASCAL ASM_IPX_UNINITIALISE:far\n\n\nproc\t\tASM_IPX_INITIALISE PASCAL FAR\n\n\t\tint\t3\n\t\tmov\tax,7a00h\n\t\tint\t2fh\n\t\tand\teax,0ffh\n\t\tcmp\tal,-1\n\t\tsetz\tal\n\t\tret\n\nendp\t\tASM_IPX_INITIALISE\n\n\n\n\nproc\t\tASM_IPX_UNINITIALISE PASCAL FAR\n\n\t\tret\n\nendp\t\tASM_IPX_UNINITIALISE\n\n\n\n\t\tends\n\n\t\tend\n\n\n\n"
  },
  {
    "path": "IPX/OK/IPX16.BAK",
    "content": "system\twindows_dll\noption redefsok\noption quiet\noption map\noption eliminate\noption caseexact\noption one\n\ndebug all\nfile ipx16a.obj\nfile ipx16c.obj\n\nname wwipx16.dll\n"
  },
  {
    "path": "IPX/OK/IPX16.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n\nextern \"C\"{\n\tBOOL FAR __cdecl IPX_Initialise(int);\n}\n\n\n"
  },
  {
    "path": "IPX/OK/IPX16A.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\n\n\t\t.8086\n\n\n\t\t.model\tlarge\n\t\toption\tsegment:USE16\n\t\toption\treadonly\n\t\toption\toldstructs\n\n\n\t\tassume\tds:@data\n\t\tassume\tes:nothing\n\n\nRECEIVE_BUFFER_LENGTH\t=1024\nMAX_RECEIVE_BUFFERS\t=32\n\n\nexterndef GLOBALDOSALLOC:far\nexterndef GLOBALDOSFREE:far\n\n\n\t\t.data\n\nIPXCallOffset\tdw\t0\nIPXCallSegment\tdw\t0\nRealSegment\tdw\t0\nPseudoES\tdw\t0\n\n\n\nRegisterDump\tdb\t32h dup (0)\n\nMyNetworkNumber\tdb\t4 dup (?)\nMyNodeAddress\tdb\t6 dup (?)\nMySocket\tdw\t?\n\nReceiveBufferSegment\tdw\t?\nReceiveBufferSelector\tdw\t?\nReceiveECBOffset\tdw\t?\nCurrentReceiveBuffer\tdw\t?\nLastPassedReceiveBuffer\tdw\t?\nRealModeCallbackSegment\tdw\t?\nRealModeCallbackOffset\tdw\t?\n\nCallbackRegisterDump\tdb\t32h dup (0)\n\nListening\t\tdb\t?\nNoReenter\t\tdb\t0\nIPXHold\t\t\tdb\t0\n\n\n\nOFFS\t\t=0\nSEGM\t\t=2\n\n\n;---------------------------------------------------------------------------\n;These defines are for the IPX functions.  The function number is specified\n;by placing it in BX when IPX is called.  There are two ways to invoke IPX:\n;use interrupt 0x7a, or use a function whose address is obtained by calling\n;interrupt 0x2f with AX=0x7a00; the function address is returned in ES:DI.\n;This is the preferred method, since other apps are known to use int 0x7a.\n;---------------------------------------------------------------------------\nIPX_OPEN_SOCKET\t\t\t= 0000h\nIPX_CLOSE_SOCKET\t\t= 0001h\nIPX_GET_LOCAL_TARGET\t\t= 0002h\nIPX_SEND_PACKET\t\t\t= 0003h\nIPX_LISTEN_FOR_PACKET\t\t= 0004h\nIPX_SCHEDULE_EVENT\t\t= 0005h\nIPX_CANCEL_EVENT\t\t= 0006h\nIPX_GET_INTERVAL_MARKER\t\t= 0008h\nIPX_GET_INTERNETWORK_ADDRESS\t= 0009h\nIPX_RELINQUISH_CONTROL\t\t= 000Ah\nIPX_DISCONNECT_FROM_TARGET\t= 000Bh\n\n;/*---------------------------------------------------------------------------\n;These defines are for various IPX error codes:\n;---------------------------------------------------------------------------*/\nIPXERR_CONNECTION_SEVERED\t= 00ech\nIPXERR_CONNECTION_FAILED\t= 00edh\nIPXERR_NO_CONNECTION\t\t= 00eeh\nIPXERR_CONNECTION_TABLE_FULL\t= 00efh\nIPXERR_NO_CANCEL_ECB\t\t= 00f9h\nIPXERR_NO_PATH\t\t\t= 00fah\nIPXERR_ECB_INACTIVE\t\t= 00fch\nIPXERR_INVALID_PACKET_LENGTH\t= 00fdh\nIPXERR_SOCKET_TABLE_FULL\t= 00feh\nIPXERR_SOCKET_ERROR\t\t= 00ffh\n\n;/*---------------------------------------------------------------------------\n;These defines are for various interrupt vectors and DPMI functions:\n;---------------------------------------------------------------------------*/\nIPX_INT\t\t\t= 007ah\nDPMI_INT\t\t= 0031h\nDPMI_ALLOC_DOS_MEM\t= 0100h\nDPMI_FREE_DOS_MEM\t= 0101h\nDPMI_CALL_REAL_INT\t= 0300h\nDPMI_CALL_REAL_PROC\t= 0301h\nDPMI_ALLOCATE_CALLBACK\t= 0303h\nDPMI_RELEASE_CALLBACK\t= 0304h\nDPMI_LOCK_MEM\t\t= 0600h\nDPMI_UNLOCK_MEM\t\t= 0601h\n\n\n\n\n\nrequest_buffer\tstruct\n\t\tlen\t\t\tword\t?\n\t\tbuffer_type\t\tbyte\t?\n\t\tconnect_number\t\tbyte\t?\nrequest_buffer\tends\n\n\n\nrequest_local_target_buffer struct\n\t\tlt_network_number\tdb\t?,?,?,?\n\t\tlt_physical_node\tdb\t?,?,?,?,?,?\n\t\tlt_socket\t\tdw\t?\nrequest_local_target_buffer ends\n\n\nlocal_target_reply_buffer struct\n\t\tlt_local_target\t\tdb\t?,?,?,?,?,?\nlocal_target_reply_buffer ends\n\n\n\nreply_buffer\tstruct\n\t\tlem\t\t\tword\t?\n\t\tnetwork_number\t\tbyte\t?,?,?,?\n\t\tphysical_node\t\tbyte\t?,?,?,?,?,?\n\t\tserver_socket\t\tword\t?\nreply_buffer\tends\n\n\n\n\n\nuserid_buffer \tstruct\n\t\tstruct_len\t\tword\t?\n\t\tobject_id\tbyte\t?,?,?,?\n\t\tobject_type\tbyte\t?,?\n\t\tobject_name\tbyte\t48 dup(?)\n\t\tlogin_time\tbyte\t7 dup (?)\n\t\treserved\tword\t?\nuserid_buffer\tends\n\n\t\t.code\n\n\t\t.386\n\n\t\tinclude <pcmacro.16>\n\nexterndef\tpascal _IPX_Initiialise:far16\nexterndef\tpascal _IPX_Uninitialise:far16\n\n\n_IPX_Initialise\tproc far pascal\n\n\t\tpush\tebx\n\t\tpush\tecx\n\t\tpush\tedx\n\t\tpush\tesi\n\t\tpush\tedi\n\t\tpush\tebp\n\t\tpush\tds\n\t\tpush\tes\n\t\tpush\tfs\n\t\tpush\tgs\n\n\t\tmov\tax,7a00h\n\t\tint\t2fh\n\t\tand\teax,0ffh\n\t\tcmp\tal,-1\n\t\tsetz\tal\n\n\t\ttest\tal,al\n\t\tjz\t@f\n\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\t[IPXCallSegment],es\n\t\tmov\t[IPXCallOffset],di\n\n@@:\t\tpop\tgs\n\t\tpop\tfs\n\t\tpop\tes\n\t\tpop\tds\n\t\tpop\tebp\n\t\tpop\tedi\n\t\tpop\tesi\n\t\tpop\tedx\n\t\tpop\tecx\n\t\tpop\tebx\n\t\tret\n\n_IPX_Initialise\tendp\n\n\n\n_IPX_Open_Socket95 proc far pascal uses bx cx dx si di ds es fs gs,\n\t\tsocket:word\n\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\tbx,IPX_OPEN_SOCKET\t;open socket\n\t\tmov_w\tdx,[socket]\t\t;socket number\n\t\tmov_w\t[MySocket],dx\t\t;save it for later\n\t\tmov\tax,0ffh\t\t\t;long lived\n\n\t\tcall\tCall_IPX\n\n\t\tret\n\n_IPX_Open_Socket95 endp\n\n\n\n\n_IPX_Close_Socket95 proc far pascal uses ax bx cx dx si di ds es fs gs,\n\t\tsocket:word\n\n\t\tmov\tbx,1\n\t\tmov_w\tdx,[socket]\n\n\t\tcall\tCall_IPX\n\n\t\tret\n\n_IPX_Close_Socket95 endp\n\n\n\n\n\n_IPX_Uninitialise proc far pascal\n\n\t\t;int\t3\n\t\tret\n\n_IPX_Uninitialise endp\n\n\n\n\n\n_IPX_Get_Connection_Number95 proc far pascal uses bx cx dx si di ds es fs gs\n\n\t\tmov\tax,0dc00h\n\t\tcall\tCall_DOS\n\t\tand\teax,255\n\t\tret\n\n_IPX_Get_Connection_Number95 endp\n\n\n\n\n\n\n_IPX_Get_Internet_Address95 proc far pascal uses bx cx dx si di ds es fs gs,\n\t\tconnection_number\t:dword,\n\t\tnetwork_number_off\t:word,\n\t\tnetwork_number_seg\t:word,\n\t\tphysical_node_off\t:word,\n\t\tphysical_node_seg\t:word\n\n\t\tlocal\tselector:word\n\t\tlocal\tsegmento:word\n\n\t\tret\nifdef cuts ;(unfinished)\n\t\t;\n\t\t; Allocate DOS memory for buffers passed to interrupt\n\t\t;\n\t\tint\t3\n\t\txor\tax,ax\n\t\tmov\tbx,(sizeof reply_buffer + sizeof request_buffer + 15)\n\t\tsave\tbp\n\t\tpush\tax\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSALLOC\n\t\trestore\tbp\n\t\ttest\tax,ax\n\t\tjz\t@@dpmi_error\n\n\t\tmov\t[segmento],dx\n\t\tmov\t[selector],ax\n\t\tmov\tfs,dx\n\t\txor\tdi,di\n\n\t\tmov_w\tfs:[di.len],2\n\t\tmov_b\tfs:[di.buffer_type],13h\n\t\tmov_b\tal,[connection_number]\n\t\tmov_b\tfs:[di.connect_number],al\n\n\t\tmov\tdi,sizeof request_buffer\n\t\tmov\tfs:[di.len],12\n\n\n\t\tmov\tax,0e300h\n\t\tmov\tds,[segmento]\n\t\tmov\tes,[segmento]\n\t\txor\tsi,si\n\n\t\tpusha\n\t\tcall\tCall_DOS\n\t\tpopa\n\n\t\tles\tdi,dword ptr [network_number_off]\n\t\tmov\tds,[selector]\n\t\tmov\tsi,sizeof request_buffer + network_number\n\t\tmovsd\n\n\t\tles\tdi,dword ptr [physical_node_off]\n\t\tmov\tsi,sizeof request_buffer + physical_node\n\t\tmovsd\n\t\tmovsw\n\n\t\t;\n\t\t; Save it here for posterity (or perhaps later use)\n\t\t;\n\t\tmov\tdi,offset MyNetworkNumber\n\t\tmov\tax,@data\n\t\tmov\tes,ax\n\t\tmov\tds,[selector]\n\t\tmov\tsi,sizeof request_buffer + network_number\n\t\tmovsd\n\n\t\tmov\tdi,offset MyNodeAddress\n\t\tmov\tsi,sizeof request_buffer + physical_node\n\t\tmovsd\n\t\tmovsw\n\n\n\t\t;\n\t\t; Free the DOS memory\n\t\t;\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\tes,bx\n\t\tmov\tfs,bx\n\t\tmov\tgs,bx\n\t\tmov\tbx,[selector]\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSFREE\n\n\t\txor\tax,ax\n\t\tret\n\n@@dpmi_error:\tmov\tax,-1\n\t\tret\nendif\n\n_IPX_Get_Internet_Address95 endp\n\n\n\n\n; Never called!!\n\n_IPX_Get_User_ID95 proc far pascal uses bx cx dx si di ds es fs gs,\n\t\tconnection_number:dword,\n\t\tuser_id_off:word,\n\t\tuser_id_seg:word\n\n\t\tlocal\tsegmento:word\n\t\tlocal\tselector:word\n\n\t\tcmp\t[connection_number],0\n\t\tjz\t@@return_error\n\n\t\t;\n\t\t; Allocate DOS memory for buffers passed to interrupt\n\t\t;\n\t\txor\tax,ax\n\t\tmov\tbx,(sizeof reply_buffer + sizeof request_buffer + 15)\n\t\tsave\tbp\n\t\tpush\tax\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSALLOC\n\t\trestore\tbp\n\t\ttest\tax,ax\n\t\tjz\t@@return_error\n\n\t\tmov\t[segmento],dx\n\t\tmov\t[selector],ax\n\t\tmov\tfs,dx\n\t\txor\tdi,di\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\n\t\tmov_w\tfs:[di.len],2\n\t\tmov_b\tfs:[di.buffer_type],16h\n\t\tmov_b\tal,[connection_number]\n\t\tmov_b\tfs:[di.connect_number],al\n\n\t\tmov\tdi,sizeof request_buffer\n\t\tmov\tfs:[di.struct_len],sizeof userid_buffer-2\n\n\t\tmov\tax,0e300h\n\t\tmov\tds,[segmento]\n\t\tmov\tes,[segmento]\n\t\txor\tsi,si\n\n\t\tpusha\n\t\tcall\tCall_DOS\n\t\tpopa\n\n\t\tles\tdi,dword ptr [user_id_off]\n\t\tmov\tds,[selector]\n\t\tmov\tsi,sizeof request_buffer + object_name\n\t\tmov\tcx,48/4\n\t\trep\tmovsd\n\n\t\t;\n\t\t; Free the DOS memory\n\t\t;\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\tes,bx\n\t\tmov\tfs,bx\n\t\tmov\tgs,bx\n\t\tmov\tbx,[selector]\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSFREE\n\n\t\txor\tax,ax\n\t\tret\n\n@@return_error:\tmov\tax,-1\n\t\tret\n\n_IPX_Get_User_ID95 endp\n\n\n\n\n;---------------------------------------------------------------------------\n;This is the IPX Packet structure.  It's followed by the data itself, which\n;can be up to 546 bytes long.  Annotation of 'IPX' means IPX will set this\n;field; annotation of 'APP' means the application must set the field.\n;NOTE: All header fields are ordered high-byte,low-byte.\n;---------------------------------------------------------------------------*/\nIPXHeaderType\tstruct\n\n\t\tCheckSum\t\tdw\t?\t\t; IPX: Not used; always 0xffff\n\t\tIPXLength\t\tdw\t?               ; IPX: Total size, incl header & data\n\t\tTransportControl\tdb\t?               ; IPX: # bridges message crossed\n\t\tPacketType\t\tdb\t?               ; APP: Set to 4 for IPX (5 for SPX)\n\t\tDestNetworkNumber\tdb\t?,?,?,?         ; APP: destination Network Number\n\t\tDestNetworkNode\t\tdb\t?,?,?,?,?,?     ; APP: destination Node Address\n\t\tDestNetworkSocket\tdw\t?               ; APP: destination Socket Number\n\t\tSourceNetworkNumber\tdb\t?,?,?,?         ; IPX: source Network Number\n\t\tSourceNetworkNode\tdb\t?,?,?,?,?,?     ; IPX: source Node Address\n\t\tSourceNetworkSocket\tdw\t?               ; IPX: source Socket Number\n\nIPXHeaderType\tends\n\n\n\n\n;/*---------------------------------------------------------------------------\n;This is the IPX Event Control Block.  It serves as a communications area\n;between IPX and the application for a single IPX operation.  You should set\n;up a separate ECB for each IPX operation you perform.\n;---------------------------------------------------------------------------*/\n\nECB\t\tstruct\n\n\t\tLink_Address\t\tdd\t?\n\t\tEvent_Service_Routine\tdd\t?\t\t; APP: event handler (NULL=none)\n\t\tInUse\t\t\tdb\t?               ; IPX: 0 = event complete\n\t\tCompletionCode\t\tdb\t?               ; IPX: event's return code\n\t\tSocketNumber\t\tdw\t?               ; APP: socket to send data through\n\t\tConnectionID\t\tdw\t?               ; returned by Listen (???)\n\t\tRestOfWorkspace\t\tdw\t?\n\t\tDriverWorkspace\t\tdb\t12 dup (?)\n\t\tImmediateAddress\tdb\t6 dup (?)       ; returned by Get_Local_Target\n\t\tPacketCount\t\tdw\t?\n\t\tPacketAddress0\t\tdd\t?\n\t\tPacketLength0\t\tdw\t?\n\t\tPacketAddress1\t\tdd\t?\n\t\tPacketLength1\t\tdw\t?\n\nECB\t\tends\n\n\nSEND_ECB_OFFSET\t\t=0\nSEND_HEADER_OFFSET\t=(sizeof ECB +3) AND 0fffch\nSEND_BUFFER_OFFSET\t=(SEND_HEADER_OFFSET + sizeof IPXHeaderType +3) AND 0fffch\n\n\n_IPX_Send_Packet95 proc far pascal uses ebx ecx edx esi edi ds es fs gs,\n\t\tsend_address\t:far ptr byte,\n\t\tsend_buffer\t:far ptr byte,\n\t\tsend_buffer_len\t:word\n\n\t\tlocal\tselector\t:word\n\t\tlocal\tsegmento\t:word\n\t\tlocal\tdos_send_ecb\t:far ptr ECB\n\t\tlocal\tdos_send_header\t:far ptr IPXHeaderType\n\t\tlocal\tdos_send_buffer\t:far ptr byte\n\t\tlocal\tcompletion_code\t:word\n\n\t\t;\n\t\t; Allocate required DOS memory\n\t\t;\n\t\txor\tax,ax\n\t\tmov\tbx,(sizeof ECB + sizeof IPXHeaderType + 1024 +31)\n\t\tsave\tbp\n\t\tpush\tax\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSALLOC\n\t\trestore\tbp\n\t\ttest\tax,ax\n\t\tjz\t@@error\n\t\tmov\t[segmento],dx\n\t\tmov\t[selector],ax\n\n\t\t;\n\t\t; Set up the pointers to the dos memory\n\t\t;\n\t\tmov_w\t[dos_send_ecb+OFFS],SEND_ECB_OFFSET\n\t\tmov_w\t[dos_send_ecb+SEGM],ax\n\t\tmov_w\t[dos_send_header+OFFS],SEND_HEADER_OFFSET\n\t\tmov_w\t[dos_send_header+SEGM],ax\n\t\tmov_w\t[dos_send_buffer+OFFS],SEND_BUFFER_OFFSET\n\t\tmov_w\t[dos_send_buffer+SEGM],ax\n\n\t\t;\n\t\t; Clear out the send ECB\n\t\t;\n\t\txor\tal,al\n\t\tmov\tcx,sizeof ECB\n\t\tles\tdi,[dos_send_ecb]\n\t\trep\tstosb\n\n\t\t;\n\t\t; Clear out the send header\n\t\t;\n\t\tmov\tcx,sizeof IPXHeaderType\n\t\tles\tdi,[dos_send_header]\n\t\trep\tstosb\n\n\t\t;\n\t\t; Copy the data to be sent into the send buffer\n\t\t;\n\t\tmov\tcx,546\n\t\tcmp_w\tcx,[send_buffer_len]\n\t\tjle\t@@got_buffer_len\n\t\tmov_w\tcx,[send_buffer_len]\n@@got_buffer_len:\n;\t\tmov_w\t[send_buffer_len],546\t;always send same size packets (nice and big for Kali hehe)\n\t\tles\tdi,[dos_send_buffer]\n\t\tlds\tsi,[send_buffer]\n\t\trep\tmovsb\n\n\t\t;\n\t\t; Fill in the ECB\n\t\t;\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\tfs,ax\t\t\t;keep ptr to data seg in fs\n\t\tles\tdi,[dos_send_ecb]\n\n\t\tmov\tax,[MySocket]\n\t\tmov\tes:[di.SocketNumber],ax\n\t\tmov\tes:[di.PacketCount],2\n\t\tmov\tax,[selector]\n\t\tshl\teax,16\n\t\tmov_w\tax,[dos_send_header+OFFS]\n\t\tmov_d\tes:[di.PacketAddress0],eax\n\t\tmov_w\tes:[di.PacketLength0],sizeof IPXHeaderType\n\t\tmov_w\tax,[dos_send_buffer+OFFS]\n\t\tmov_d\tes:[di.PacketAddress1],eax\n\t\tmov_w\tax,[send_buffer_len]\n\t\tmov_w\tes:[di.PacketLength1],ax\n\n\t\t;\n\t\t; Fill in the address field\n\t\t;\n\t\tlds\tsi,[send_address]\n\t\tmov\teax,[si]\n\t\tmov_d\tes:[di.ImmediateAddress],eax\n\t\tmov\tax,[si+4]\n\t\tmov_w\tes:[di.ImmediateAddress+4],ax\n\n\t\t;\n\t\t; Fill in the outgoing header\n\t\t;\n\t\tles\tdi,[dos_send_header]\n\t\tmov\tes:[di.PacketType],4\n\t\tpush\tfs:[MySocket]\n\t\tpop\tes:[di.DestNetworkSocket]\n\n\t\t;\n\t\t; Fill in the nwtowrk number and node address\n\t\t;\n\t\tmov_d\teax,fs:[MyNetworkNumber]\n\t\tmov_d\tes:[di.DestNetworkNumber],eax\n\t\tmov_d\teax,fs:[MyNodeAddress]\n\t\tmov_d\tes:[di.DestNetworkNode],eax\n\t\tmov_w\tax,fs:[MyNodeAddress+4]\n\t\tmov_w\tes:[di.DestNetworkNode+4],ax\n\n\t\t;\n\t\t; Send that sucker!\n\t\t;\n\t\tmov\tes,[selector]\n\t\tmov\tsi,SEND_ECB_OFFSET\n\t\tmov\tbx,IPX_SEND_PACKET\n\t\tpusha\n\t\tpush\tfs\n\t\tcall\tCall_IPX\n\t\tpop\tfs\n\t\tpopa\n\t\tmov\tfs:[PseudoES],0\n\n\n\t\t;\n\t\t; Wait for the send to finish\n\t\t;\n@@wait_send_loop:\n\t\tlds\tsi,[dos_send_ecb]\n\t\tcmp\t[si.InUse],0\n\t\tjz\t@@done\n\n\t\tmov\tbx,IPX_RELINQUISH_CONTROL\n\t\tsave\tbp\n\t\tcall\tCall_IPX\n\t\trestore\tbp\n\t\tjmp\t@@wait_send_loop\n\n\n\t\t;\n\t\t; Get the completion code\n\t\t;\n@@done:\t\tlds\tsi,[dos_send_ecb]\n\t\tmov\tal,[si.CompletionCode]\n\t\txor\tah,ah\n\t\tmov\t[completion_code],ax\n\n\t\t;\n\t\t; Free the DOS memory\n\t\t;\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\tes,bx\n\t\tmov\tfs,bx\n\t\tmov\tgs,bx\n\t\tmov\tbx,[selector]\n\t\tsave\tbp\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSFREE\n\t\trestore\tbp\n\n\t\tcmp\t[completion_code],0\n\t\tjnz\t@@error\n\n@@success:\tmov\tax,1\n\t\tret\n\n\n@@error:\txor\tax,ax\n\t\tret\n\n\n_IPX_Send_Packet95 endp\n\n\n\n\n\n\n_IPX_Broadcast_Packet95 proc far pascal uses ebx ecx edx esi edi ds es fs gs,\n\t\tsend_buffer\t:far ptr byte,\n\t\tsend_buffer_len\t:word\n\n\t\tlocal\tselector\t:word\n\t\tlocal\tsegmento\t:word\n\t\tlocal\tdos_send_ecb\t:far ptr ECB\n\t\tlocal\tdos_send_header\t:far ptr IPXHeaderType\n\t\tlocal\tdos_send_buffer\t:far ptr byte\n\t\tlocal\tcompletion_code\t:word\n\n\t\t;\n\t\t; Allocate required DOS memory\n\t\t;\n\t\txor\tax,ax\n\t\tmov\tbx,(sizeof ECB + sizeof IPXHeaderType + 1024 +31)\n\t\tsave\tbp\n\t\tpush\tax\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSALLOC\n\t\trestore\tbp\n\t\ttest\tax,ax\n\t\tjz\t@@error\n\t\tmov\t[segmento],dx\n\t\tmov\t[selector],ax\n\n\t\t;\n\t\t; Set up the pointers to the dos memory\n\t\t;\n\t\tmov_w\t[dos_send_ecb+OFFS],SEND_ECB_OFFSET\n\t\tmov_w\t[dos_send_ecb+SEGM],ax\n\t\tmov_w\t[dos_send_header+OFFS],SEND_HEADER_OFFSET\n\t\tmov_w\t[dos_send_header+SEGM],ax\n\t\tmov_w\t[dos_send_buffer+OFFS],SEND_BUFFER_OFFSET\n\t\tmov_w\t[dos_send_buffer+SEGM],ax\n\n\t\t;\n\t\t; Clear out the send ECB\n\t\t;\n\t\txor\tal,al\n\t\tmov\tcx,sizeof ECB\n\t\tles\tdi,[dos_send_ecb]\n\t\trep\tstosb\n\n\t\t;\n\t\t; Clear out the send header\n\t\t;\n\t\tmov\tcx,sizeof IPXHeaderType\n\t\tles\tdi,[dos_send_header]\n\t\trep\tstosb\n\n\t\t;\n\t\t; Copy the data to be sent into the send buffer\n\t\t;\n\t\tmov\tcx,546\n\t\tcmp_w\tcx,[send_buffer_len]\n\t\tjle\t@@got_buffer_len\n\t\tmov_w\tcx,[send_buffer_len]\n@@got_buffer_len:\n;\t\tmov_w\t[send_buffer_len],546\t;always send same size packets (nice and big for Kali hehe)\n\t\tles\tdi,[dos_send_buffer]\n\t\tlds\tsi,[send_buffer]\n\t\trep\tmovsb\n\n\t\t;\n\t\t; Fill in the ECB\n\t\t;\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\tfs,ax\t\t\t;keep ptr to data seg in fs\n\t\tles\tdi,[dos_send_ecb]\n\n\t\tmov\tax,[MySocket]\n\t\tmov\tes:[di.SocketNumber],ax\n\t\tmov\tes:[di.PacketCount],2\n\t\tmov\tax,[selector]\n\t\tshl\teax,16\n\t\tmov_w\tax,[dos_send_header+OFFS]\n\t\tmov_d\tes:[di.PacketAddress0],eax\n\t\tmov_w\tes:[di.PacketLength0],sizeof IPXHeaderType\n\t\tmov_w\tax,[dos_send_buffer+OFFS]\n\t\tmov_d\tes:[di.PacketAddress1],eax\n\t\tmov_w\tax,[send_buffer_len]\n\t\tmov_w\tes:[di.PacketLength1],ax\n\n\t\t;\n\t\t; Fill in the address field\n\t\t;\n\t\tmov_d\tes:[di.ImmediateAddress],0ffffffffh\n\t\tmov_w\tes:[di.ImmediateAddress+4],0ffffh\n\n\t\t;\n\t\t; Fill in the outgoing header\n\t\t;\n\t\tles\tdi,[dos_send_header]\n\t\tmov\tes:[di.PacketType],4\n\t\tpush\tfs:[MySocket]\n\t\tpop\tes:[di.DestNetworkSocket]\n\n\t\t;\n\t\t; Fill in the nwtowrk number and node address\n\t\t;\n\t\tmov_d\tes:[di.DestNetworkNumber],0ffffffffh\n\t\tmov_d\tes:[di.DestNetworkNode],0ffffffffh\n\t\tmov_w\tes:[di.DestNetworkNode+4],0ffffh\n\n\t\t;\n\t\t; Send that sucker!\n\t\t;\n\t\tmov\tes,[selector]\n\t\tmov\tsi,SEND_ECB_OFFSET\n\t\tmov\tbx,IPX_SEND_PACKET\n\t\tpusha\n\t\tpush\tfs\n\t\tcall\tCall_IPX\n\t\tpop\tfs\n\t\tpopa\n\t\tmov\tfs:[PseudoES],0\n\n\t\t;\n\t\t; Wait for the send to finish\n\t\t;\n@@wait_send_loop:\n\t\tlds\tsi,[dos_send_ecb]\n\t\tcmp\t[si.InUse],0\n\t\tjz\t@@done\n\n\t\tmov\tbx,IPX_RELINQUISH_CONTROL\n\t\tsave\tbp\n\t\tcall\tCall_IPX\n\t\trestore\tbp\n\t\tjmp\t@@wait_send_loop\n\n\n\n\t\t;\n\t\t; Get the completion code\n\t\t;\n@@done:\t\tlds\tsi,[dos_send_ecb]\n\t\tmov\tal,[si.CompletionCode]\n\t\txor\tah,ah\n\t\tmov\t[completion_code],ax\n\n\t\t;\n\t\t; Free the DOS memory\n\t\t;\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\tes,bx\n\t\tmov\tfs,bx\n\t\tmov\tgs,bx\n\t\tmov\tbx,[selector]\n\t\tsave\tbp\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSFREE\n\t\trestore\tbp\n\n\t\tcmp\t[completion_code],0\n\t\tjnz\t@@error\n\n\n@@success:\tmov\tax,1\n\t\tret\n\n\n@@error:\txor\tax,ax\n\t\tret\n\n\n_IPX_Broadcast_Packet95 endp\n\n\n\n\n\n\n\n_IPX_Get_Local_Target95\tproc far pascal uses ebx ecx edx esi edi ds es fs gs,\n\t\tdest_network\t:far ptr byte,\n\t\tdest_node\t:far ptr byte,\n\t\tsocket\t\t:word,\n\t\tbridge_address\t:far ptr byte\n\n\n\t\tlocal\tsegmento\t:word\n\t\tlocal\tselector\t:word\n\t\tlocal\tresult_code\t:word\n\n\t\t;\n\t\t; Allocate DOS memory for buffers passed to interrupt\n\t\t;\n\t\txor\tax,ax\n\t\tmov\tbx,(sizeof local_target_reply_buffer + \\\n\t\t\t    sizeof request_local_target_buffer + 15)\n\t\tsave\tbp\n\t\tpush\tax\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSALLOC\n\t\trestore\tbp\n\t\ttest\tax,ax\n\t\tjz\t@@return_error\n\n\t\tmov\t[segmento],dx\n\t\tmov\t[selector],ax\n\t\tmov\tfs,ax\n\t\txor\tdi,di\n\n\t\t;\n\t\t; Init the request structure\n\t\t;\n\t\tlds\tsi,[dest_network]\n\t\tmov_d\teax,[si]\n\t\tmov_d\tfs:[di.lt_network_number],eax\n\t\tlds\tsi,[dest_node]\n\t\tmov\teax,[si]\n\t\tmov_d\tfs:[di.lt_physical_node],eax\n\t\tmov_w\tax,[si+4]\n\t\tmov_w\tfs:[di.lt_physical_node+4],ax\n\t\tmov\tax,[socket]\n\t\tmov\tfs:[di.lt_socket],ax\n\n\t\tmov\tbx,IPX_GET_LOCAL_TARGET\n\t\tmov\tax,[selector]\n\t\tmov\tds,ax\n\t\txor\tsi,si\n\t\tmov\tes,ax\n\t\tmov\tdi,sizeof request_local_target_buffer\n\n\t\tpush\tbp\n\t\tcall\tCall_IPX\n\t\tpop\tbp\n\n\t\tmov\t[result_code],ax\n\n\t\tmov\tds,[selector]\n\t\tmov\tsi,sizeof request_local_target_buffer + lt_local_target\n\t\tles\tdi,[bridge_address]\n\t\tmovsd\n\t\tmovsw\n\n\t\t;\n\t\t; Free the DOS memory\n\t\t;\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\tes,bx\n\t\tmov\tfs,bx\n\t\tmov\tgs,bx\n\t\tmov\tbx,[selector]\n\t\tsave\tbp\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSFREE\n\t\trestore\tbp\n\n\t\t;\n\t\t; Return the IPX result code\n\t\t;\n\t\tmov\tax,[result_code]\n\t\tret\n\n@@return_error:\tmov\tax,-1\n\t\tret\n\n_IPX_Get_Local_Target95\tendp\n\n\n\n\n_IPX_Get_Outstanding_Buffer95 proc far pascal uses ebx ecx edx esi edi ebp ds es fs gs,\n\t\tcopy_receive_buffer:far ptr byte\n\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\n\t\txor\tax,ax\n\t\tmov\tsi,[LastPassedReceiveBuffer]\n\t\tcmp\tsi,[CurrentReceiveBuffer]\n\t\tjz\t@@done\n\n\t\tpush\tds\n\t\tmov\tcx,RECEIVE_BUFFER_LENGTH/4\n\t\tmov\tds,[ReceiveBufferSelector]\n\t\tles\tdi,[copy_receive_buffer]\n\t\trep\tmovsd\n\t\tpop\tds\n\n\t\tcmp\tsi,RECEIVE_BUFFER_LENGTH*MAX_RECEIVE_BUFFERS\n\t\tjc\t@@no_wrap\n\t\txor\tsi,si\n@@no_wrap:\tmov\t[LastPassedReceiveBuffer],si\n\n\t\tmov\tax,1\n\n@@done:\t\tret\n\n_IPX_Get_Outstanding_Buffer95 endp\n\n\n\n\nReceive_Callback proc far\n\n\t\tpushf\n\t\tcli\n\t\tcld\n\t\tpushad\n\t\tpush\tds\n\t\tpush\tes\n\t\tpush\tfs\n\t\tpush\tgs\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tcmp\t[NoReenter],0\n\t\tjnz\t@@out\n\t\tmov\t[NoReenter],1\n\t\tmov\tax,[CurrentReceiveBuffer]\n\n\t\tadd\tax,RECEIVE_BUFFER_LENGTH\n\t\tcmp\tax,RECEIVE_BUFFER_LENGTH*MAX_RECEIVE_BUFFERS\n\t\tjc\t@@no_wrap\n\t\txor\tax,ax\n@@no_wrap:\tmov\t[CurrentReceiveBuffer],ax\n\n\t\tcall\tListen_For_Packet\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\t[NoReenter],0\n\n@@out:\t\tpop\tgs\n\t\tpop\tfs\n\t\tpop\tes\n\t\tpop\tds\n\t\tpopad\n\t\tpopf\n\t\tret\n\nReceive_Callback endp\n\n\n\n\n\nInit_Receive_ECB proc near uses eax ebx ecx edx esi edi ebp ds es\n\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\tes,[ReceiveBufferSelector]\n\n\t\t;\n\t\t; Clear out the ECB\n\t\t;\n\t\tmov\tdi,[ReceiveECBOffset]\n\t\tmov\tcx,sizeof ECB\n\t\txor\tal,al\n\t\trep\tstosb\n\n\n;\n; Set up the ECB\n;\n\t\t;\n\t\t;General ECB data\n\t\tmov\tdi,[ReceiveECBOffset]\n\t\tmov\tax,[MySocket]\n\t\tmov\tes:[di.SocketNumber],ax\n\t\tmov\tes:[di.PacketCount],2\n\n\t\t;\n\t\t; Packet address for IPX header\n\t\tmov\tax,[CurrentReceiveBuffer]\n\t\tmov\tbx,[ReceiveBufferSelector]\n\t\tmov_w\tes:[di.PacketAddress0+OFFS],ax\n\t\tmov_w\tes:[di.PacketAddress0+SEGM],bx\n\t\tmov\tes:[di.PacketLength0],sizeof IPXHeaderType\n\n\t\t;\n\t\t; Packet address for receive buffer\n\t\tmov\tax,[CurrentReceiveBuffer]\n\t\tadd\tax,sizeof IPXHeaderType\n\t\tmov_w\tes:[di.PacketAddress1+OFFS],ax\n\t\tmov_w\tes:[di.PacketAddress1+SEGM],bx\n\t\tmov\tes:[di.PacketLength1],546\n\n\t\t;\n\t\t; Set up the callback address\n\t\tmov\tax,[RealModeCallbackOffset]\n\t\tmov_w\tes:[di.Event_Service_Routine+OFFS],offset Receive_Callback\t;ax\n\t\tmov\tax,[RealModeCallbackSegment]\n\t\tmov_w\tes:[di.Event_Service_Routine+SEGM],cs\t;ax\n\n\t\tret\n\nInit_Receive_ECB endp\n\n\n_IPX_Start_Listening95 proc far pascal uses ebx ecx edx esi edi ebp ds es fs gs\n\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tcmp\t[Listening],0\n\t\tjnz\t@@restart\t\t;already listening\n\n\t\t;\n\t\t; Allocate and lock DOS memory for listen\n\t\t;  ECB and receive buffers\n\t\t;\n\t\tmov\tbx,(RECEIVE_BUFFER_LENGTH*MAX_RECEIVE_BUFFERS + sizeof ECB + 15)\n\t\txor\tax,ax\n\t\tsave\tbp,ds\n\t\tpush\tax\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSALLOC\n\t\trestore\tbp,ds\n\t\ttest\tax,ax\n\t\tjz\t@@error\n\n\t\tmov\t[ReceiveBufferSegment],dx\n\t\tmov\t[ReceiveBufferSelector],ax\n\n\t\t;\n\t\t; Set up pointers to the DOS memory\n\t\t;\n\t\tmov\t[ReceiveECBOffset],RECEIVE_BUFFER_LENGTH * MAX_RECEIVE_BUFFERS\n\t\tmov\t[CurrentReceiveBuffer],0\t;1st receive buffer\n\t\tmov\t[LastPassedReceiveBuffer],0\n\n\t\t;\n\t\t; Set up a real mode callback function\n\t\t;\n\t\t;mov\tax,DPMI_ALLOCATE_CALLBACK\n\t\t;mov\tsi,offset Receive_Callback\n\t\t;mov\tdi,offset CallbackRegisterDump\n\t\t;push\tcs\n\t\t;pop\tds\n\t\t;mov\tbx,@data\n\t\t;mov\tes,bx\n\t\t;save\tbp\n\t\t;int\t31h\n\t\t;restore\tbp\n\t\t;bcs\t@@error\n\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\t[RealModeCallbackSegment],cx\n\t\tmov\t[RealModeCallbackOffset],dx\n\n@@restart:\tsave\tds\n\t\tcall\tListen_For_Packet\n\t\trestore\tds\n\t\tmov\t[Listening],1\n\n@@out:\t\tmov\tax,1\n\t\tret\n\n@@error:\txor\tax,ax\n\t\tret\n\n_IPX_Start_Listening95 endp\n\n\n\n\n_IPX_Shut_Down95 proc far pascal uses eax ebx ecx edx esi edi ebp ds es fs gs\n\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tcmp\t[Listening],0\n\t\tjz\t@@out\n\n\t\t;\n\t\t; Stop listening for a packet\n\t\t;\n\t\tmov\tes,[ReceiveBufferSelector]\n\t\tmov\tsi,[ReceiveECBOffset]\n\t\tmov\tbx,IPX_CANCEL_EVENT\n\t\tsave\tbp,ds\n\t\tcall\tCall_IPX\n\t\trestore\tbp,ds\n\n\t\t;\n\t\t; Remove the real mode callback function\n\t\t;\n\t\t;mov\tcx,[RealModeCallbackSegment]\n\t\t;mov\tdx,[RealModeCallbackOffset]\n\t\t;mov\tax,DPMI_RELEASE_CALLBACK\n\t\t;save\tbp,ds\n\t\t;int\t31h\n\t\t;restore\tbp,ds\n\n\t\t;\n\t\t; Free the DOS memory\n\t\t;\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\tes,ax\n\t\tmov\tax,[ReceiveBufferSelector]\n\t\tsave\tbp,ds\n\t\tpush\tax\n\t\tcall\tGLOBALDOSFREE\n\t\trestore\tbp,ds\n\n\t\tmov\t[Listening],0\n\n@@out:\t\tret\n\n_IPX_Shut_Down95 endp\n\n\n\n\nListen_For_Packet proc near uses ebx ecx edx esi edi ebp ds es fs gs\n\n\t\tcall\tInit_Receive_ECB\n\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\tes,[ReceiveBufferSelector]\n\t\tmov\tsi,[ReceiveECBOffset]\n\t\tmov\tbx,IPX_LISTEN_FOR_PACKET\n\t\tsave\tds\n\t\tcall\tCall_IPX\n\t\trestore\tds\n\t\tmov\t[PseudoES],0\n\n\t\tret\n\nListen_For_Packet endp\n\n\n\n\n\n\nCall_IPX\tproc far\n\n\t\tpush\tgs\n\t\tpush\tax\n\t\tmov\tax,@data\n\t\tmov\tgs,ax\n\t\tpop\tax\n\n\t       \tpush\tbp\n\t\tmov\tbp,offset IPXCallOffset\n\t\tcall\tdword ptr gs:[bp]\n\t\tpop\tbp\n\n\t\tpop\tgs\n\t\tret\n\n\n\n\n\n\n\t\tpush\tgs\n\t\tpush\tax\n\t\tmov\tax,@data\n\t\tmov\tgs,ax\n\t\tpop\tax\n\n\t\t;\n\t\t; Prevent reenterancy\n\t\t;\n@@hold:\t\t;cmp\tgs:[IPXHold],0\n\t\t;jnz\t@@hold\n\n\t\tmov\tgs:[IPXHold],1\n\n\t\t;\n\t\t; Dump the registers first so we can use them\n\t\t;\n\t\tmov_d\tgs:[RegisterDump+0ch],0\n\t\tmov_d\tgs:[RegisterDump],edi\n\t\tmov_d\tgs:[RegisterDump+4],esi\n\t\tmov_d\tgs:[RegisterDump+8],ebp\n\t\tmov_d\tgs:[RegisterDump+10h],ebx\n\t\tmov_d\tgs:[RegisterDump+14h],edx\n\t\tmov_d\tgs:[RegisterDump+18h],ecx\n\t\tmov_d\tgs:[RegisterDump+1ch],eax\n\n\t\tpush\tgs\n\t\txor\tax,ax\n\t\tpush\tax\n\t\tmov\tax,4096\t;4k real mode stack\n\t\tpush\tax\n\t\tcall\tGLOBALDOSALLOC\n\t\tpop\tgs\n\t\tmov\tbx,4094\t;stack ptr\n\t\ttest\tax,ax\n\t\tjnz\t@f\n\t\txor\tbx,bx\n\n\t\t;\n\t\t; Set up stack addr to zero - DPMI will supply a real mode stack\n\t\t;\n@@:\t\tmov_w\tgs:[RegisterDump+2eh],bx\t;sp\n\t\tmov_w\tgs:[RegisterDump+30h],dx\t;ss\n\t\tsave\tax\t;save selector so we can free the memory later\n\n\n\t\t;\n\t\t; Dump the flags\n\t\t;\n\t\tpushf\n\t\tpop\tgs:[word ptr RegisterDump+20h]\n\n\t\t;\n\t\t; Set up all segment register areas to point to our real mode segment\n\t\t;\n\t\tmov_w\tgs:[RegisterDump+22h],es\n\t\tmov_w\tgs:[RegisterDump+24h],ds\n\t\tmov_w\tgs:[RegisterDump+26h],fs\n\t\tmov_w\tgs:[RegisterDump+28h],gs\n\n\t\tcmp\tgs:[PseudoES],0\n\t\tjz\t@f\n\t\tmov\tax,gs:[PseudoES]\n\t\tmov_w\tgs:[RegisterDump+22h],ax\n@@:\n\n\n\t\t;\n\t\t; Set up the address to call\n\t\t;\n\t\tmov\tax,gs:[IPXCallSegment]\n\t\tmov_w\tgs:[RegisterDump+2ch],ax\n\t\tmov\tax,gs:[IPXCallOffset]\n\t\tmov_w\tgs:[RegisterDump+2ah],ax\n\n\t\tmov\tax,DPMI_CALL_REAL_INT\t; Call real mode procedure with far return frame\n\t\txor\tbh,bh\t\t\t; flags - should be zero\n\t\tmov\tbl,07ah\t\t\t; IPX interrupt\n\t\tmov\tecx,0 ;512\t\t\t; number of words to copy from the protected mode stack\n\t\tmov\tdi,offset RegisterDump\n\t\tpush\tgs\n\t\tpop\tes\n\t\tsave\tgs\n\t\t;push\tss\n\t\t;push\tsp\n\t\tint\t31h\t\t;DPMI interrupt\n\n\t\t;pop\tax\n\t\t;pop\tbx\n\t\t;pushf\n\t\t;pop\tcx\n\t\t;cli\n\t\t;mov\tsp,ax\n\t\t;mov\tss,bx\n\t\t;add\tsp,2\n\t\t;push\tcx\n\t\t;popf\n\n\t\trestore\tgs\n\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\tes,ax\n\t\tmov\tfs,ax\n\t\tmov\tgs,ax\n\t\tcall\tGLOBALDOSFREE\n\n\n\t\tmov_d\teax,gs:[RegisterDump+1ch]\n\t\tmov\tgs:[IPXHold],0\n\t\tpop\tgs\n\n\t\tret\n\n\nCall_IPX\tendp\n\n\n\n\n\n\n\n\nCall_DOS\tproc far\n\n\t\tpush\tgs\n\t\tpush\tax\n\t\tmov\tax,@data\n\t\tmov\tgs,ax\n\t\tpop\tax\n\t\t;\n\t\t; Dump the registers first so we can use them\n\t\t;\n\t\tmov_d\tgs:[RegisterDump],edi\n\t\tmov_d\tgs:[RegisterDump+4],esi\n\t\tmov_d\tgs:[RegisterDump+8],ebp\n\t\tmov_d\tgs:[RegisterDump+10h],ebx\n\t\tmov_d\tgs:[RegisterDump+14h],edx\n\t\tmov_d\tgs:[RegisterDump+18h],ecx\n\t\tmov_d\tgs:[RegisterDump+1ch],eax\n\n\t\t;\n\t\t; Dump the flags\n\t\t;\n\t\tpushf\n\t\tpop\tgs:[word ptr RegisterDump+20h]\n\n\t\t;\n\t\t; Set up all segment register areas to point to our real mode segment\n\t\t;\n\t\tmov_w\tgs:[RegisterDump+22h],es\n\t\tmov_w\tgs:[RegisterDump+24h],ds\n\t\tmov_w\tgs:[RegisterDump+26h],fs\n\t\tmov_w\tgs:[RegisterDump+28h],gs\n\n\t\t;\n\t\t; Set up stack addr to zero - DPMI will supply a real mode stack\n\t\t;\n\t\txor\tax,ax\n\t\tmov_w\tgs:[RegisterDump+2eh],ax\t;sp\n\t\tmov_w\tgs:[RegisterDump+30h],ax\t;ss\n\n\t\tmov\tax,DPMI_CALL_REAL_INT; Simulate real mode interrupt\n\t\txor\tbh,bh\t\t; flags - should be zero\n\t\tmov\tbl,21h\t\t; interrupt number\n\t\tmov\tecx,0 ;512\t\t; number of words to copy from the protected mode stack\n\t\tmov\tdi,offset RegisterDump\n\t\tpush\tgs\n\t\tpop\tes\n\t\tsave\tgs\n\t\tint\t31h\t\t;DPMI interrupt\n\t\trestore\tgs\n\n\t\tmov_d\tedi,gs:[RegisterDump]\n\t\tmov_d\tesi,gs:[RegisterDump+4]\n\t\tmov_d\tebp,gs:[RegisterDump+8]\n\t\tmov_d\tebx,gs:[RegisterDump+10h]\n\t\tmov_d\tedx,gs:[RegisterDump+14h]\n\t\tmov_d\tecx,gs:[RegisterDump+18h]\n\t\tmov_d\teax,gs:[RegisterDump+1ch]\n\t\tmov_w\tes,gs:[RegisterDump+22h]\n\t\tmov_w\tds,gs:[RegisterDump+24h]\n\t\tpop\tgs\n\n\t\tret\n\n\nCall_DOS\tendp\n\n\n\n\n\t\tend\n\n\n\n\n\n\n"
  },
  {
    "path": "IPX/OK/IPX16C.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n\n\n#include <windows.h>\n\nextern \"C\"{\n\textern BOOL FAR __pascal ASM_IPX_Initialise(void);\n\textern BOOL FAR __pascal ASM_IPX_Uninitialise(void);\n}\n\n\nextern \"C\"{\n\tBOOL FAR __pascal _export IPX_Initialise(int);\n\tvoid FAR __pascal _export IPX_Uninitialise(void);\n}\n\n\n\nint CALLBACK LibMain (HANDLE, WORD, WORD, LPSTR)\n{\n\treturn (1);\n}\n\n\n\nBOOL FAR __pascal _export IPX_Initialise(int)\n{\n\n\treturn (ASM_IPX_Initialise());\n\n}\n\n\n\nvoid FAR __pascal _export IPX_Uninitialise(void)\n{\n\n\tASM_IPX_Uninitialise();\n\n}\n\n\n\n\n"
  },
  {
    "path": "IPX/OK/IPXTEST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#define WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#include <windows.h>\n\n\n\nint PASCAL WinMain ( HINSTANCE instance , HINSTANCE , char *, int)\n{\n\n\n\n\n}\n\n\n\n"
  },
  {
    "path": "IPX/OK/MAKE.BAK",
    "content": "set include >temp.txt\nset include=c:\\wat\\h;c:\\wat\\h\\win\ncopy setinc.bat+temp.txt setinc2.bat\nwpp -ml -bd -zu -bt=windows -0 ipx16c.cpp\ntasm /ml ipx16a.asm\nwlink @ipx16.lnk\nwlib -c -n wwipx16.lib +wwipx16.dll\ncall setinc2.bat\n"
  },
  {
    "path": "IPX/OK/MAKE.BAT",
    "content": "set include >temp.txt\nset include=c:\\wat\\h;c:\\wat\\h\\win\ncopy setinc.bat+temp.txt setinc2.bat\nwpp -s -ml -bd -zu -bt=windows -0 ipx16c.cpp\ntasm /ml ipx16a.asm\nwlink @ipx16.lnk\nwlib -c -n wwipx16.lib +wwipx16.dll\ncall setinc2.bat\n"
  },
  {
    "path": "IPX/OK/MAKETH16.BAK",
    "content": "set include >temp.txt\nset include=c:\\wat\\h;c:\\wat\\h\\win\ncopy setinc.bat+temp.txt setinc2.bat\nthunk Thipx.thk\nwpp -ml -bd -zu -bt=windows -0 thipx16c.cpp\nml /c /W3 ipx16a.asm\nml /DIS_16 /c /W3 /Fothipx16a.obj thipx.asm\nml /c /W3 thmap16.asm\nml /c /W3 ipx16a.asm\nwlink @thipx16.lnk\nrc -40 thipx16.dll\ncall setinc2.bat\n"
  },
  {
    "path": "IPX/OK/MAKETH16.BAT",
    "content": "set include >temp.txt\nset include=c:\\wat\\h;c:\\wat\\h\\win\ncopy setinc.bat+temp.txt setinc2.bat\nthunk Thipx.thk\nwpp -ml -bd -zu -bt=windows -0 thipx16c.cpp\nml /c /W3 ipx16a.asm\nml /DIS_16 /c /W3 /Fothipx16a.obj thipx.asm\nml /c /W3 thmap16.asm\nwlink @thipx16.lnk\nrc -40 thipx16.dll\ncall setinc2.bat\n"
  },
  {
    "path": "IPX/OK/MAKETH32.BAK",
    "content": "rem thunk Thipx.thk\nrem fixthunk\nwpp386 -s -mf -3s -bt=nt -bd -zu -4 thipx32c.cpp\nml /DIS_32 /Zf /Fl /c /W3 /Fothipx32a.obj thipx.asm\nml /c /W3 thmap32.asm\nwlink @thipx32.lnk\nwlib -c -n wwipx32.lib +thipx32.dll\n"
  },
  {
    "path": "IPX/OK/MAKETH32.BAT",
    "content": "thunk Thipx.thk\nrem fixthunk\nwpp386 -s -mf -3s -bt=nt -bd -zu -4 thipx32c.cpp\nml /DIS_32 /Zf /Fl /c /W3 /Fothipx32a.obj thipx.asm\nml /c /W3 thmap32.asm\nwlink @thipx32.lnk\nwlib -c -n wwipx32.lib +thipx32.dll\n"
  },
  {
    "path": "IPX/OK/PCMACRO.16",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;$e:\\ifil\\pcmacro.inc\n;- 16-5-1991 at 10:55:13 by mike\n;- 16-5-1991 at 08:30:30 by mike\n;- 3-5-1991 at 15:39:52 by mike\n\n\n\tSUBTTL PCMACRO.INC\n\t.xlist\n\n\nfmulscan_size\t MACRO\te0,e1\n\tIFDEF\tTANDY\n\t.err\n\tENDIF\n\tIFDEF\tCGA\n\t.err\n\tENDIF\n\tIFDEF\tEGA\n\tm8\te0   \t\t\t\t;; scan size = 40 for vga & ega\n\tmov\te1,e0\n\tm4\te0\n\tadd\te0,e1\t\n\tENDIF\n\tENDM\n\n;.commo\tMACRO\n;\tENDM\n\n;.commf\tMACRO\n;\tENDM\n\nsetpal\tMACRO \te0\n\tpush\tsi\n\tmov\tsi,OFFSET e0\n\tcall\tset_pallette\n\tpop\tsi\n\tENDM\n\t\t\n\n\n\n\n\nwaitvbl\tMACRO\n\tcall\twait_vbl\n\tENDM\n\n\nswapscr\tMACRO\n\tcall\tswap_scr\n\tENDM\n\nsetscad\tMACRO\n\tIFDEF\tTANDY\n\tmov\tax,0b800h\t;;setup screen address \n\tENDIF\n\tIFDEF\tCGA\n\tmov\tax,0b800h\n\tENDIF\n\tIFDEF\tEGA\n\tpush\tds\n\tmov\tax,_DATA\n\tmov\tds,ax\n\tmov\tax,screen_seg\n\tpop\tds\n\tENDIF\n\tmov\tes,ax\n\tENDM\n\nreswordscr\tmacro\n\tstosw\t\t\t\t;;movsw\n\tendm\n\n;;\t\t      x\t y\ngetscreen\tMACRO e0,e1\n\tIFIDN <e1>,<ax>\n\t%out\t\"CANT USED AX AS SECOND ARGUMENT\"\n\t.err\n\tendif\n\n\tIFIDN <e1>,<di>\n\t%out\t\"CANT USED DI AS SECOND ARGUMENT\"\n\t.err\n\tendif\n\t\t       \n\tIFDIF <e1>,<di>\n\tmov\tdi,e1\n\tendif\n\tm2\tdi\n\tmov\tdi,screenvtb[di]\n\n\tIFDIF <e0>,<ax>\n\tmov\tax,e0\n\tendif\n\n\tIFDEF\tEGA\n\tdi8\tax\n\tENDIF\n\tIFDEF\tTANDY\n\tshr\tax,1\n\tENDIF\n\tIFDEF\tCGA\n\tshr\tax,1\n\tshr\tax,1\n\tshr\tax,1\n\tshr\tax,1\n\tENDIF\n\tadd\tdi,ax\n\tIFDEF\tTANDY\n\tand\tdi,1fffh\n\tENDIF\n\tENDM\n\ngetscreen_no MACRO\n\tmov\tax,d1\n\tsal\tax,1\n\tmov\tdi,ax\n\tmov\tax,screenvtb[di]\n\tmov\tdi,ax\n\tmov\tax,scadd\n\tadd\tdi,ax\n\tmov\tax,d0\n\tIFDEF\tEGA\n\tdi8\tax\n\tENDIF\n\tIFDEF\tTANDY\n\tshr\tax,1\n\tENDIF\n\tIFDEF\tCGA\n\tshr\tax,1\n\tshr\tax,1\n\tshr\tax,1\n\tshr\tax,1\n\tENDIF\n\tadd\tdi,ax\n\tENDM\n\n\n\n\n\n\nmult\tmacro\te0,e1\n\tif\t( e1 EQ 2 )\n\tm2\te0\n\texitm\n\tendif\n\n\tif\t( e1 EQ 4 )\n\tm4\te0\n\texitm\n\tendif\n\n\tif\t( e1 EQ 8 )\n\tm8\te0\n\texitm\n\tendif\n\n\tif\t( e1 EQ 16 )\n\tm16\te0\n\texitm\n\tendif\n\n\t%out\t\"CANT USE THIS MACRO WITH THIS VALUE\"\n\t.err\n\tendm\n\n\n\nm2\tmacro\te0\n\tshl\te0,1\n\tendm\n\nm4\tmacro\te0\n\tm2\te0\n\tm2\te0\n\tendm\n\nm8\tmacro\te0\n\tm4\te0\n\tm2\te0\n\tendm\n\nm16\tmacro\te0\n\tm8\te0\n\tm2\te0\n\tendm\n\nm32\tmacro\te0\n\tm16\te0\n\tm2\te0\n\tendm\n\nm64\tmacro\te0\n\tm32\te0\n\tm2\te0\n\tendm\n\nm128\tmacro\te0\n\tm64\te0\n\tm2\te0\n\tendm\n\ndi2\tmacro\te0\n\tshr\te0,1\n\tendm\n\ndi4\tmacro\te0\n\tdi2\te0\n\tdi2\te0\n\tendm\n\ndi8\tmacro\te0\n\tdi4\te0\n\tdi2\te0\n\tendm\n\ndi16\tmacro\te0\n\tdi8\te0\n\tdi2\te0\n\tendm\n\ndi32\tmacro\te0\n\tdi16\te0\n\tdi2\te0\n\tendm\n\ndeca\tmacro\te0\n\tmov\tax,e0\n\tdec\tax\n\tmov\te0,ax\n\tendm\n\ndecb\tmacro\te0\n\tmov\tal,e0\n\tdec\tal\n\tmov\te0,al\n\tendm\n\ninca\tmacro\te0\n\tmov\tax,e0\n\tinc\tax\n\tmov\te0,ax\n\tendm\n\nincb\tmacro\te0\n\tmov\tal,e0\n\tinc\tal\n\tmov\te0,al\n\tendm\n\nclrw\tmacro\te0\n\tmov\tWORD PTR e0,0\n\tendm\n\nclrb\tmacro\te0\n\tmov\tBYTE PTR e0,0\n\tendm\n\nclr\tmacro\te0\n\tmov\te0,0\n\tendm\n\n\n\t\n\nmova\tmacro\te1,e2\n\t.ERRIDN\t<e1>,<WORD>\n\t.ERRIDN <e1>,<BYTE>\n\t.ERRIDN <e1>,<OFFSET>\n\t.ERRIDN\t<e2>,<WORD>\n\t.ERRIDN <e2>,<BYTE>\n\t.ERRIDN <e2>,<OFFSET>\n\tmov\tax,e2\n\tmov\te1,ax\n\tendm\n\nmovb\tmacro\te1,e2\n\t.ERRIDN\t<e1>,<WORD>\n\t.ERRIDN <e1>,<BYTE>\n\t.ERRIDN <e1>,<OFFSET>\n\t.ERRIDN\t<e2>,<WORD>\n\t.ERRIDN <e2>,<BYTE>\n\t.ERRIDN <e2>,<OFFSET>\n\tmov\tal,e2\n\tmov\te1,al\n\tendm\n\nbtstb\tmacro\te1,e2\n\tIFIDN <e1>,<al>\n\ttest\te1,1 SHL e2\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<ah>\n\ttest\te1,1 SHL e2\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<bl>\n\ttest\te1,1 SHL e2\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<bh>\n\ttest\te1,1 SHL e2\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<cl>\n\ttest\te1,1 SHL e2\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<ch>\n\ttest\te1,1 SHL e2\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<dl>\n\ttest\te1,1 SHL e2\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<dh>\n\ttest\te1,1 SHL e2\n\tEXITM\n\tENDIF\n        test    BYTE PTR e1,1 SHL e2\n\tendm\n\n\n\nsaveall\tmacro\n\tsave\tax,bx,cx,dx,bp,si,di,es,ds\n\tendm\n\nrestall\tmacro\n\trestore\tax,bx,cx,dx,bp,si,di,es,ds\n\tendm\n\nsave\tmacro\tr0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14\n\tIFNB\t<r0>\n\tpush\tr0\n\tsave\tr1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14\n\tENDIF\n\tendm\n\nrestore\tmacro\tr0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14\n\tIFNB\t<r14>\n\tpop\tr14\n\tENDIF\n\tIFNB\t<r13>\n\tpop\tr13\n\tENDIF\n\tIFNB\t<r12>\n\tpop\tr12\n\tENDIF\n\tIFNB\t<r11>\n\tpop\tr11\n\tENDIF\n\tIFNB\t<r10>\n\tpop\tr10\n\tENDIF\n\tIFNB\t<r9>\n\tpop\tr9\n\tENDIF\n\tIFNB\t<r8>\n\tpop\tr8\n\tENDIF\n\tIFNB\t<r7>\n\tpop\tr7\n\tENDIF\n\tIFNB\t<r6>\n\tpop\tr6\n\tENDIF\n\tIFNB\t<r5>\n\tpop\tr5\n\tENDIF\n\tIFNB\t<r4>\n\tpop\tr4\n\tENDIF\n\tIFNB\t<r3>\n\tpop\tr3\n\tENDIF\n\tIFNB\t<r2>\n\tpop\tr2\n\tENDIF\n\tIFNB\t<r1>\n\tpop\tr1\n\tENDIF\n\tIFNB\t<r0>\n\tpop\tr0\n\tENDIF\n\tendm\n\nbhi\tmacro\tlab\n\tja\tlab\n\tendm\n\nbls\tmacro\tlab\n\tjbe\tlab\n\tendm\n\nbcc\tmacro\tlab\n\tjnc\tlab\n\tendm\n\nbcs\tmacro\tlab\n\tjc\tlab\n\tendm\t\n\nbhs\tmacro\tlab\n\tjnc\tlab\n\tendm\n\nblo\tmacro\tlab\n\tjc\tlab\n\tendm\n\nbne\tmacro\tlab\n\tjne\tlab\n\tendm\n\nbeq\tmacro\tlab\n\tje\tlab\n\tendm\n\nbpl\tmacro\tlab\n\tjns\tlab\n\tendm\n\nbmi\tmacro\tlab\n\tjs\tlab\n\tendm\n\nbge\tmacro\tlab\n\tjge\tlab\n\tendm\n\nblt\tmacro\tlab\n\tjl\tlab\n\tendm\n\nbgt\tmacro\tlab\n\tjg\tlab\n\tendm\n\nble\tmacro\tlab\n\tjle\tlab\n\tendm\n\nbra\tmacro\tlab\n\tjmp\tlab\n\tendm\n\n\nbhis\tmacro\tlab\n\tja\tlab\n\tendm\n\nblss\tmacro\tlab\n\tjbe\tlab\n\tendm\n\nbccs\tmacro\tlab\n\tjnc\tlab\n\tendm\n\nbcss\tmacro\tlab\n\tjc\tlab\n\tendm\t\n\nbnes\tmacro\tlab\n\tjne\tlab\n\tendm\n\nbeqs\tmacro\tlab\n\tje\tlab\n\tendm\n\nbpls\tmacro\tlab\n\tjns\tlab\n\tendm\n\nbmis\tmacro\tlab\n\tjs\tlab\n\tendm\n\nbges\tmacro\tlab\n\tjge\tlab\n\tendm\n\nblts\tmacro\tlab\n\tjl\tlab\n\tendm\n\nbgts\tmacro\tlab\n\tjg\tlab\n\tendm\n\nbles\tmacro\tlab\n\tjle\tlab\n\tendm\n\nbras\tmacro\tlab\n\tjmp\tlab\n\tendm\n\n\ntstb\tmacro\te1\n\n\tIFIDN <e1>,<al>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<bp>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<ah>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<bl>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<bh>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<cl>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<ch>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<dl>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<dh>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tcmp\tBYTE PTR e1,0\n\tendm\n\n\t\ntstw\tmacro\te1\n\tIFIDN\t<e1>,<ax>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<bx>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<cx>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<dx>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tIFIDN\t<e1>,<bp>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tIFIDN\t<e1>,<si>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tIFIDN\t<e1>,<di>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tcmp\tWORD PTR e1,0\n\tendm\n\n\n\ntst\tmacro\te1\n\tIFIDN\t<e1>,<ax>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<bx>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<cx>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<dx>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tIFIDN\t<e1>,<bp>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tIFIDN\t<e1>,<si>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tIFIDN\t<e1>,<di>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tIFIDN\t<e1>,<al>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<bl>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<cl>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<dl>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tIFIDN\t<e1>,<ah>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<bh>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<ch>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<dh>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tcmp\te1,0\n\tendm\n\n\nclear\tmacro\tfirst\n\txor\tfirst,first\n\tendm\n\nrts\tmacro\n\tret\n\tendm\n\n\nbclrb\tmacro\te1,e2\n\tbtstb\te1,e2\n\tpushf\n\n\tbclrb_sub\te1,e2\n\tpopf\n\tendm\n\nbclrb_sub macro e1,e2\n\tIFIDN <e1>,<al>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<bp>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<ah>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<bl>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<bh>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<cl>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<ch>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<dl>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<dh>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tand\tBYTE PTR e1,NOT ( 1 SHL e2 )\n\tendm\n\n\n\nbsetb\tmacro\te1,e2\n\tbtstb\te1,e2\n\tpushf\n\tor\tBYTE PTR e1,1 SHL e2\n\tpopf\n\tendm\n\n\nbchgb\tmacro\te1,e2\n\tbtstb\te1,e2\n\tpushf\n\txor\tBYTE PTR e1,1 SHL e2\n\tpopf\n\tendm\n\n\n\nmov_b\tmacro\tlabel,label2\n\tmov\tbyte ptr label,byte ptr label2\n\tendm\n\n\n\nmov_w\tmacro\tlabel,label2\n\tmov\tword ptr label,word ptr label2\n\tendm\n\n\n\nmov_d\tmacro\tlabel,label2\n\tmov\tdword ptr label,dword ptr label2\n\tendm\n\n\ncmp_b\tmacro\tlabel,label2\n\tcmp\tbyte ptr label,byte ptr label2\n\tendm\n\ncmp_w\tmacro\tlabel,label2\n\tcmp\tword ptr label,word ptr label2\n\tendm\n\ncmp_d\tmacro\tlabel,label2\n\tcmp\tdword ptr label,dword ptr label2\n\tendm\n\n\n\nadd_b\tmacro\tlabel,label2\n\tadd\tbyte ptr label,byte ptr label2\n\tendm\n\nadd_w\tmacro\tlabel,label2\n\tadd\tword ptr label,word ptr label2\n\tendm\n\nadd_d\tmacro\tlabel,label2\n\tadd\tdword ptr label,dword ptr label2\n\tendm\n\n\n\nsub_b\tmacro\tlabel,label2\n\tsub\tbyte ptr label,byte ptr label2\n\tendm\n\nsub_w\tmacro\tlabel,label2\n\tsub\tword ptr label,word ptr label2\n\tendm\n\nsub_d\tmacro\tlabel,label2\n\tsub\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\n\nor_b\tmacro\tlabel,label2\n\tor\tbyte ptr label,byte ptr label2\n\tendm\n\nor_w\tmacro\tlabel,label2\n\tor\tword ptr label,word ptr label2\n\tendm\n\nor_d\tmacro\tlabel,label2\n\tor\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\n\n\n\nxor_b\tmacro\tlabel,label2\n\txor\tbyte ptr label,byte ptr label2\n\tendm\n\nxor_w\tmacro\tlabel,label2\n\txor\tword ptr label,word ptr label2\n\tendm\n\nxor_d\tmacro\tlabel,label2\n\txor\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\n\n\n\n\neor_b\tmacro\tlabel,label2\n\txor\tbyte ptr label,byte ptr label2\n\tendm\n\neor_w\tmacro\tlabel,label2\n\txor\tword ptr label,word ptr label2\n\tendm\n\neor_d\tmacro\tlabel,label2\n\txor\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\nand_b\tmacro\tlabel,label2\n\tand\tbyte ptr label,byte ptr label2\n\tendm\n\nand_w\tmacro\tlabel,label2\n\tand\tword ptr label,word ptr label2\n\tendm\n\nand_d\tmacro\tlabel,label2\n\tand\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\n\ntest_b\tmacro\tlabel,label2\n\ttest\tbyte ptr label,byte ptr label2\n\tendm\n\ntest_w\tmacro\tlabel,label2\n\ttest\tword ptr label,word ptr label2\n\tendm\n\ntest_d\tmacro\tlabel,label2\n\ttest\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\n\n\n\nshr_b\tmacro\tlabel,label2\n\tshr\tbyte ptr label,label2\n\tendm\n\nshr_w\tmacro\tlabel,label2\n\tshr\tword ptr label,label2\n\tendm\n\nshr_d\tmacro\tlabel,label2\n\tshr\tdword ptr label,label2\n\tendm\n\n \n\nshl_b\tmacro\tlabel,label2\n\tshl\tbyte ptr label,label2\n\tendm\n\nshl_w\tmacro\tlabel,label2\n\tshl\tword ptr label,label2\n\tendm\n\nshl_d\tmacro\tlabel,label2\n\tshl\tdword ptr label,label2\n\tendm\n\n\n\n\nsar_b\tmacro\tlabel,label2\n\tsar\tbyte ptr label,label2\n\tendm\n\nsar_w\tmacro\tlabel,label2\n\tsar\tword ptr label,label2\n\tendm\n\nsar_d\tmacro\tlabel,label2\n\tsar\tdword ptr label,label2\n\tendm\n\n\n\n\n\nsal_b\tmacro\tlabel,label2\n\tsal\tbyte ptr label,label2\n\tendm\n\nsal_w\tmacro\tlabel,label2\n\tsal\tword ptr label,label2\n\tendm\n\nsal_d\tmacro\tlabel,label2\n\tsal\tdword ptr label,label2\n\tendm\n\n\n\ninc_b\tmacro\tlabel\n\tinc\tbyte ptr label\n\tendm\n\ninc_w\tmacro\tlabel\n\tinc\tword ptr label\n\tendm\n\ninc_d\tmacro\tlabel\n\tinc\tdword ptr label\n\tendm\n\n\n\n\ndec_b\tmacro\tlabel\n\tdec\tbyte ptr label\n\tendm\n\ndec_w\tmacro\tlabel\n\tdec\tword ptr label\n\tendm\n\ndec_d\tmacro\tlabel\n\tdec\tdword ptr label\n\tendm\n\n\n\n\n\nmovzx_b\tmacro\tlabel,label2\n\tmovzx\tlabel,byte ptr label2\n\tendm\n\n\nmovzx_w\tmacro\tlabel,label2\n\tmovzx\tlabel,word ptr label2\n\tendm\n   \n\nmovsx_b\tmacro\tlabel,label2\n\tmovsx\tlabel,byte ptr label2\n\tendm\n\n\nmovsx_w\tmacro\tlabel,label2\n\tmovsx\tlabel,word ptr label2\n\tendm\n   \n\n\n\nmul_b\tmacro\tlabel\n\tmul\tbyte ptr label\n\tendm\n\n\nmul_w\tmacro\tlabel\n\tmul\tword ptr label\n\tendm\n\n\ndiv_b\tmacro\tlabel\n\tdiv\tbyte ptr label\n\tendm\n\n\ndiv_w\tmacro\tlabel\n\tdiv\tword ptr label\n\tendm\n\n\nidiv_b\tmacro\tlabel\n\tidiv\tbyte ptr label\n\tendm\n\n\nidiv_w\tmacro\tlabel\n\tidiv\tword ptr label\n\tendm\n\n\n\n\ntst_b\tmacro\tlabel\n\tcmp\tbyte ptr label,0\n\tendm\n\ntst_w\tmacro\tlabel\n\tcmp\tword ptr label,0\n\tendm\n\ntst_d\tmacro\tlabel\n\tcmp\tdword ptr label,0\n\tendm\n\n\n\n\n\n\n\nnot_b\tmacro\tlabel\n\tnot\tbyte ptr label\n\tendm\n\nnot_w\tmacro\tlabel\n\tnot\tword ptr label\n\tendm\n\nnot_d\tmacro\tlabel\n\tnot\tdword ptr label\n\tendm\n\n\n\n\nneg_b\tmacro\tlabel\n\tneg\tbyte ptr label\n\tendm\n\nneg_w\tmacro\tlabel\n\tneg\tword ptr label\n\tendm\n\nneg_d\tmacro\tlabel\n\tneg\tdword ptr label\n\tendm\n\n\n\n\n\n  \t.list\n\n\n\u001a"
  },
  {
    "path": "IPX/OK/THIPX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\tpage\t,132\n\n;Thunk Compiler Version 1.8  May 11 1995 13:16:19\n;File Compiled Fri Jan 26 16:12:04 1996\n\n;Command Line: C:\\BIN\\THUNK.EXE Thipx.thk \n\n\tTITLE\t$Thipx.asm\n\n\t.386\n\tOPTION READONLY\n\tOPTION OLDSTRUCTS\n\nIFNDEF IS_16\nIFNDEF IS_32\n%out command line error: specify one of -DIS_16, -DIS_32\n.err\nENDIF  ;IS_32\nENDIF  ;IS_16\n\n\nIFDEF IS_32\nIFDEF IS_16\n%out command line error: you can't specify both -DIS_16 and -DIS_32\n.err\nENDIF ;IS_16\n;************************* START OF 32-BIT CODE *************************\n\n\n\t.model FLAT,STDCALL\n\n\n;-- Import common flat thunk routines (in k32)\n\nexternDef MapHInstLS\t:near32\nexternDef MapHInstLS_PN\t:near32\nexternDef MapHInstSL\t:near32\nexternDef MapHInstSL_PN\t:near32\nexternDef FT_Prolog\t:near32\nexternDef FT_Thunk\t:near32\nexternDef QT_Thunk\t:near32\nexternDef FT_Exit0\t:near32\nexternDef FT_Exit4\t:near32\nexternDef FT_Exit8\t:near32\nexternDef FT_Exit12\t:near32\nexternDef FT_Exit16\t:near32\nexternDef FT_Exit20\t:near32\nexternDef FT_Exit24\t:near32\nexternDef FT_Exit28\t:near32\nexternDef FT_Exit32\t:near32\nexternDef FT_Exit36\t:near32\nexternDef FT_Exit40\t:near32\nexternDef FT_Exit44\t:near32\nexternDef FT_Exit48\t:near32\nexternDef FT_Exit52\t:near32\nexternDef FT_Exit56\t:near32\nexternDef SMapLS\t:near32\nexternDef SUnMapLS\t:near32\nexternDef SMapLS_IP_EBP_8\t:near32\nexternDef SUnMapLS_IP_EBP_8\t:near32\nexternDef SMapLS_IP_EBP_12\t:near32\nexternDef SUnMapLS_IP_EBP_12\t:near32\nexternDef SMapLS_IP_EBP_16\t:near32\nexternDef SUnMapLS_IP_EBP_16\t:near32\nexternDef SMapLS_IP_EBP_20\t:near32\nexternDef SUnMapLS_IP_EBP_20\t:near32\nexternDef SMapLS_IP_EBP_24\t:near32\nexternDef SUnMapLS_IP_EBP_24\t:near32\nexternDef SMapLS_IP_EBP_28\t:near32\nexternDef SUnMapLS_IP_EBP_28\t:near32\nexternDef SMapLS_IP_EBP_32\t:near32\nexternDef SUnMapLS_IP_EBP_32\t:near32\nexternDef SMapLS_IP_EBP_36\t:near32\nexternDef SUnMapLS_IP_EBP_36\t:near32\nexternDef SMapLS_IP_EBP_40\t:near32\nexternDef SUnMapLS_IP_EBP_40\t:near32\n\nMapSL\tPROTO NEAR STDCALL p32:DWORD\n\n\n\n\t.code \n\n;************************* COMMON PER-MODULE ROUTINES *************************\n\n\t.data\n\npublic Thipx_ThunkData32\t;This symbol must be exported.\nThipx_ThunkData32 label dword\n\tdd\t3130534ch\t;Protocol 'LS01'\n\tdd\t0228d3h\t;Checksum\n\tdd\t0\t;Jump table address.\n\tdd\t3130424ch\t;'LB01'\n\tdd\t0\t;Flags\n\tdd\t0\t;Reserved (MUST BE 0)\n\tdd\t0\t;Reserved (MUST BE 0)\n\tdd\toffset QT_Thunk_Thipx - offset Thipx_ThunkData32\n\tdd\toffset FT_Prolog_Thipx - offset Thipx_ThunkData32\n\n\n\n\t.code \n\n\nexternDef ThunkConnect32@24:near32\n\npublic Thipx_ThunkConnect32@16\nThipx_ThunkConnect32@16:\n\tpop\tedx\n\tpush\toffset Thipx_ThkData16\n\tpush\toffset Thipx_ThunkData32\n\tpush\tedx\n\tjmp\tThunkConnect32@24\nThipx_ThkData16 label byte\n\tdb\t\"Thipx_ThunkData16\",0\n\n\n\t\t\n\n\npfnQT_Thunk_Thipx\tdd offset QT_Thunk_Thipx\npfnFT_Prolog_Thipx\tdd offset FT_Prolog_Thipx\n\t.data\nQT_Thunk_Thipx label byte\n\tdb\t32 dup(0cch)\t;Patch space.\n\nFT_Prolog_Thipx label byte\n\tdb\t32 dup(0cch)\t;Patch space.\n\n\n\t.code \n\n\n\n\n\n;************************ START OF THUNK BODIES************************\n\n\n\n\n;\npublic _IPX_Close_Socket95@4\n_IPX_Close_Socket95@4:\n\tmov\tcl,9\n\tjmp\tII_IPX_Close_Socket95@4\npublic _IPX_Initialise@4\n_IPX_Initialise@4:\n\tmov\tcl,12\n\tjmp\tII_IPX_Close_Socket95@4\npublic _IPX_Open_Socket95@4\n_IPX_Open_Socket95@4:\n\tmov\tcl,10\n; _IPX_Close_Socket95(16) = _IPX_Close_Socket95(32) {}\n;\n; dword ptr [ebp+8]:  param1\n;\npublic II_IPX_Close_Socket95@4\nII_IPX_Close_Socket95@4:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tpush\tword ptr [ebp+8]\t;param1: dword->word\n\tcall\tdword ptr [pfnQT_Thunk_Thipx]\n\tcwde\n\tleave\n\tretn\t4\n\n\n\n\n\n;\npublic _IPX_Get_Internet_Address95@12\n_IPX_Get_Internet_Address95@12:\n\tmov\tcl,7\n; _IPX_Get_Internet_Address95(16) = _IPX_Get_Internet_Address95(32) {}\n;\n; dword ptr [ebp+8]:  param1\n; dword ptr [ebp+12]:  netnum\n; dword ptr [ebp+16]:  node\n;\npublic II_IPX_Get_Internet_Address95@12\nII_IPX_Get_Internet_Address95@12:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tpush\tword ptr [ebp+8]\t;param1: dword->word\n\tcall\tSMapLS_IP_EBP_12\n\tpush\teax\n\tcall\tSMapLS_IP_EBP_16\n\tpush\teax\n\tcall\tdword ptr [pfnQT_Thunk_Thipx]\n\tcwde\n\tcall\tSUnMapLS_IP_EBP_12\n\tcall\tSUnMapLS_IP_EBP_16\n\tleave\n\tretn\t12\n\n\n\n\n\n;\npublic _IPX_Get_User_ID95@8\n_IPX_Get_User_ID95@8:\n\tmov\tcl,6\n; _IPX_Get_User_ID95(16) = _IPX_Get_User_ID95(32) {}\n;\n; dword ptr [ebp+8]:  param1\n; dword ptr [ebp+12]:  user_id\n;\npublic II_IPX_Get_User_ID95@8\nII_IPX_Get_User_ID95@8:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tpush\tword ptr [ebp+8]\t;param1: dword->word\n\tcall\tSMapLS_IP_EBP_12\n\tpush\teax\n\tcall\tdword ptr [pfnQT_Thunk_Thipx]\n\tcwde\n\tcall\tSUnMapLS_IP_EBP_12\n\tleave\n\tretn\t8\n\n\n\n\n\n;\npublic _IPX_Send_Packet95@12\n_IPX_Send_Packet95@12:\n\tmov\tcl,5\n; _IPX_Send_Packet95(16) = _IPX_Send_Packet95(32) {}\n;\n; dword ptr [ebp+8]:  address\n; dword ptr [ebp+12]:  buffer\n; dword ptr [ebp+16]:  param3\n;\npublic II_IPX_Send_Packet95@12\nII_IPX_Send_Packet95@12:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tcall\tSMapLS_IP_EBP_8\n\tpush\teax\n\tcall\tSMapLS_IP_EBP_12\n\tpush\teax\n\tpush\tword ptr [ebp+16]\t;param3: dword->word\n\tcall\tdword ptr [pfnQT_Thunk_Thipx]\n\tcwde\n\tcall\tSUnMapLS_IP_EBP_8\n\tcall\tSUnMapLS_IP_EBP_12\n\tleave\n\tretn\t12\n\n\n\n\n\n;\npublic _IPX_Broadcast_Packet95@8\n_IPX_Broadcast_Packet95@8:\n\tmov\tcl,4\n; _IPX_Broadcast_Packet95(16) = _IPX_Broadcast_Packet95(32) {}\n;\n; dword ptr [ebp+8]:  buffer\n; dword ptr [ebp+12]:  param2\n;\npublic II_IPX_Broadcast_Packet95@8\nII_IPX_Broadcast_Packet95@8:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tcall\tSMapLS_IP_EBP_8\n\tpush\teax\n\tpush\tword ptr [ebp+12]\t;param2: dword->word\n\tcall\tdword ptr [pfnQT_Thunk_Thipx]\n\tcwde\n\tcall\tSUnMapLS_IP_EBP_8\n\tleave\n\tretn\t8\n\n\n\n\n\n;\npublic _IPX_Get_Local_Target95@16\n_IPX_Get_Local_Target95@16:\n\tmov\tcl,3\n; _IPX_Get_Local_Target95(16) = _IPX_Get_Local_Target95(32) {}\n;\n; dword ptr [ebp+8]:  netnum\n; dword ptr [ebp+12]:  node\n; dword ptr [ebp+16]:  param3\n; dword ptr [ebp+20]:  address\n;\npublic II_IPX_Get_Local_Target95@16\nII_IPX_Get_Local_Target95@16:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tcall\tSMapLS_IP_EBP_8\n\tpush\teax\n\tcall\tSMapLS_IP_EBP_12\n\tpush\teax\n\tpush\tword ptr [ebp+16]\t;param3: dword->word\n\tcall\tSMapLS_IP_EBP_20\n\tpush\teax\n\tcall\tdword ptr [pfnQT_Thunk_Thipx]\n\tcwde\n\tcall\tSUnMapLS_IP_EBP_8\n\tcall\tSUnMapLS_IP_EBP_12\n\tcall\tSUnMapLS_IP_EBP_20\n\tleave\n\tretn\t16\n\n\n\n\n\n;\npublic _IPX_Shut_Down95@0\n_IPX_Shut_Down95@0:\n\tmov\tcl,1\n\tjmp\tII_IPX_Shut_Down95@0\npublic _IPX_Uninitialise@0\n_IPX_Uninitialise@0:\n\tmov\tcl,11\n\tjmp\tII_IPX_Shut_Down95@0\npublic _IPX_Get_Connection_Number95@0\n_IPX_Get_Connection_Number95@0:\n\tmov\tcl,8\n\tjmp\tII_IPX_Shut_Down95@0\npublic _IPX_Start_Listening95@0\n_IPX_Start_Listening95@0:\n\tmov\tcl,2\n; _IPX_Shut_Down95(16) = _IPX_Shut_Down95(32) {}\n;\n;\npublic II_IPX_Shut_Down95@0\nII_IPX_Shut_Down95@0:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tcall\tdword ptr [pfnQT_Thunk_Thipx]\n\tcwde\n\tleave\n\tretn\n\n\n\n\n\n;\npublic _IPX_Get_Outstanding_Buffer95@4\n_IPX_Get_Outstanding_Buffer95@4:\n\tmov\tcl,0\n; _IPX_Get_Outstanding_Buffer95(16) = _IPX_Get_Outstanding_Buffer95(32) {}\n;\n; dword ptr [ebp+8]:  buffer\n;\npublic II_IPX_Get_Outstanding_Buffer95@4\nII_IPX_Get_Outstanding_Buffer95@4:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tcall\tSMapLS_IP_EBP_8\n\tpush\teax\n\tcall\tdword ptr [pfnQT_Thunk_Thipx]\n\tcwde\n\tcall\tSUnMapLS_IP_EBP_8\n\tleave\n\tretn\t4\n\n\n\n\nELSE\n;************************* START OF 16-BIT CODE *************************\n\n\n\n\n\tOPTION SEGMENT:USE16\n\t.model LARGE,PASCAL\n\n\n\t.code\t\n\n\n\nexternDef _IPX_Get_Outstanding_Buffer95:far16\nexternDef _IPX_Shut_Down95:far16\nexternDef _IPX_Start_Listening95:far16\nexternDef _IPX_Get_Local_Target95:far16\nexternDef _IPX_Broadcast_Packet95:far16\nexternDef _IPX_Send_Packet95:far16\nexternDef _IPX_Get_User_ID95:far16\nexternDef _IPX_Get_Internet_Address95:far16\nexternDef _IPX_Get_Connection_Number95:far16\nexternDef _IPX_Close_Socket95:far16\nexternDef _IPX_Open_Socket95:far16\nexternDef _IPX_Uninitialise:far16\nexternDef _IPX_Initialise:far16\n\n\nFT_ThipxTargetTable label word\n\tdw\toffset _IPX_Get_Outstanding_Buffer95\n\tdw\t   seg _IPX_Get_Outstanding_Buffer95\n\tdw\toffset _IPX_Shut_Down95\n\tdw\t   seg _IPX_Shut_Down95\n\tdw\toffset _IPX_Start_Listening95\n\tdw\t   seg _IPX_Start_Listening95\n\tdw\toffset _IPX_Get_Local_Target95\n\tdw\t   seg _IPX_Get_Local_Target95\n\tdw\toffset _IPX_Broadcast_Packet95\n\tdw\t   seg _IPX_Broadcast_Packet95\n\tdw\toffset _IPX_Send_Packet95\n\tdw\t   seg _IPX_Send_Packet95\n\tdw\toffset _IPX_Get_User_ID95\n\tdw\t   seg _IPX_Get_User_ID95\n\tdw\toffset _IPX_Get_Internet_Address95\n\tdw\t   seg _IPX_Get_Internet_Address95\n\tdw\toffset _IPX_Get_Connection_Number95\n\tdw\t   seg _IPX_Get_Connection_Number95\n\tdw\toffset _IPX_Close_Socket95\n\tdw\t   seg _IPX_Close_Socket95\n\tdw\toffset _IPX_Open_Socket95\n\tdw\t   seg _IPX_Open_Socket95\n\tdw\toffset _IPX_Uninitialise\n\tdw\t   seg _IPX_Uninitialise\n\tdw\toffset _IPX_Initialise\n\tdw\t   seg _IPX_Initialise\n\n\n\n\n\t.data\n\npublic Thipx_ThunkData16\t;This symbol must be exported.\nThipx_ThunkData16\tdd\t3130534ch\t;Protocol 'LS01'\n\tdd\t0228d3h\t;Checksum\n\tdw\toffset FT_ThipxTargetTable\n\tdw\tseg    FT_ThipxTargetTable\n\tdd\t0\t;First-time flag.\n\n\n\n\t.code \n\n\nexternDef ThunkConnect16:far16\n\npublic Thipx_ThunkConnect16\nThipx_ThunkConnect16:\n\tpop\tax\n\tpop\tdx\n\tpush\tseg    Thipx_ThunkData16\n\tpush\toffset Thipx_ThunkData16\n\tpush\tseg    Thipx_ThkData32\n\tpush\toffset Thipx_ThkData32\n\tpush\tcs\n\tpush\tdx\n\tpush\tax\n\tjmp\tThunkConnect16\nThipx_ThkData32 label byte\n\tdb\t\"Thipx_ThunkData32\",0\n\n\n\n\n\nENDIF\nEND\n"
  },
  {
    "path": "IPX/OK/THIPX.BAK",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\tpage\t,132\n\n;Thunk Compiler Version 1.8  May 11 1995 13:16:19\n;File Compiled Tue Jan 23 15:12:09 1996\n\n;Command Line: C:\\BIN\\THUNK.EXE thipx.thk \n\n\tTITLE\t$thipx.asm\n\n\t.386\n\tOPTION READONLY\n\tOPTION OLDSTRUCTS\n\nIFNDEF IS_16\nIFNDEF IS_32\n%out command line error: specify one of -DIS_16, -DIS_32\n.err\nENDIF  ;IS_32\nENDIF  ;IS_16\n\n\nIFDEF IS_32\nIFDEF IS_16\n%out command line error: you can't specify both -DIS_16 and -DIS_32\n.err\nENDIF ;IS_16\n;************************* START OF 32-BIT CODE *************************\n\n\n\t.model FLAT,STDCALL\n\n\n;-- Import common flat thunk routines (in k32)\n\nexternDef MapHInstLS\t:near32\nexternDef MapHInstLS_PN\t:near32\nexternDef MapHInstSL\t:near32\nexternDef MapHInstSL_PN\t:near32\nexternDef FT_Prolog\t:near32\nexternDef FT_Thunk\t:near32\nexternDef QT_Thunk\t:near32\nexternDef FT_Exit0\t:near32\nexternDef FT_Exit4\t:near32\nexternDef FT_Exit8\t:near32\nexternDef FT_Exit12\t:near32\nexternDef FT_Exit16\t:near32\nexternDef FT_Exit20\t:near32\nexternDef FT_Exit24\t:near32\nexternDef FT_Exit28\t:near32\nexternDef FT_Exit32\t:near32\nexternDef FT_Exit36\t:near32\nexternDef FT_Exit40\t:near32\nexternDef FT_Exit44\t:near32\nexternDef FT_Exit48\t:near32\nexternDef FT_Exit52\t:near32\nexternDef FT_Exit56\t:near32\nexternDef SMapLS\t:near32\nexternDef SUnMapLS\t:near32\nexternDef SMapLS_IP_EBP_8\t:near32\nexternDef SUnMapLS_IP_EBP_8\t:near32\nexternDef SMapLS_IP_EBP_12\t:near32\nexternDef SUnMapLS_IP_EBP_12\t:near32\nexternDef SMapLS_IP_EBP_16\t:near32\nexternDef SUnMapLS_IP_EBP_16\t:near32\nexternDef SMapLS_IP_EBP_20\t:near32\nexternDef SUnMapLS_IP_EBP_20\t:near32\nexternDef SMapLS_IP_EBP_24\t:near32\nexternDef SUnMapLS_IP_EBP_24\t:near32\nexternDef SMapLS_IP_EBP_28\t:near32\nexternDef SUnMapLS_IP_EBP_28\t:near32\nexternDef SMapLS_IP_EBP_32\t:near32\nexternDef SUnMapLS_IP_EBP_32\t:near32\nexternDef SMapLS_IP_EBP_36\t:near32\nexternDef SUnMapLS_IP_EBP_36\t:near32\nexternDef SMapLS_IP_EBP_40\t:near32\nexternDef SUnMapLS_IP_EBP_40\t:near32\n\nMapSL\tPROTO NEAR STDCALL p32:DWORD\n\n\n\n\t.code \n\n;************************* COMMON PER-MODULE ROUTINES *************************\n\n\t.data\n\npublic thipx_ThunkData32\t;This symbol must be exported.\nthipx_ThunkData32 label dword\n\tdd\t3130534ch\t;Protocol 'LS01'\n\tdd\t0a179h\t;Checksum\n\tdd\t0\t;Jump table address.\n\tdd\t3130424ch\t;'LB01'\n\tdd\t0\t;Flags\n\tdd\t0\t;Reserved (MUST BE 0)\n\tdd\t0\t;Reserved (MUST BE 0)\n\tdd\toffset QT_Thunk_thipx - offset thipx_ThunkData32\n\tdd\toffset FT_Prolog_thipx - offset thipx_ThunkData32\n\n\n\n\t.code \n\n\nexternDef ThunkConnect32@24:near32\n\npublic thipx_ThunkConnect32@16\nthipx_ThunkConnect32@16:\n\tpop\tedx\n\tpush\toffset thipx_ThkData16\n\tpush\toffset thipx_ThunkData32\n\tpush\tedx\n\tjmp\tThunkConnect32@24\nthipx_ThkData16 label byte\n\tdb\t\"thipx_ThunkData16\",0\n\n\n\t\t\n\n\npfnQT_Thunk_thipx\tdd offset QT_Thunk_thipx\npfnFT_Prolog_thipx\tdd offset FT_Prolog_thipx\n\t.data\nQT_Thunk_thipx label byte\n\tdb\t32 dup(0cch)\t;Patch space.\n\nFT_Prolog_thipx label byte\n\tdb\t32 dup(0cch)\t;Patch space.\n\n\n\t.code \n\n\n\n\n\n;************************ START OF THUNK BODIES************************\n\n\n\n\n;\npublic _IPX_Close_Socket95@4\n_IPX_Close_Socket95@4:\n\tmov\tcl,3\n\tjmp\tII_IPX_Close_Socket95@4\npublic _IPX_Initialise@4\n_IPX_Initialise@4:\n\tmov\tcl,6\n\tjmp\tII_IPX_Close_Socket95@4\npublic _IPX_Open_Socket95@4\n_IPX_Open_Socket95@4:\n\tmov\tcl,4\n; _IPX_Close_Socket95(16) = _IPX_Close_Socket95(32) {}\n;\n; dword ptr [ebp+8]:  param1\n;\npublic II_IPX_Close_Socket95@4\nII_IPX_Close_Socket95@4:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tpush\tword ptr [ebp+8]\t;param1: dword->word\n\tcall\tdword ptr [pfnQT_Thunk_thipx]\n\tcwde\n\tleave\n\tretn\t4\n\n\n\n\n\n;\npublic _IPX_Get_Connection_Number95@0\n_IPX_Get_Connection_Number95@0:\n\tmov\tcl,2\n\tjmp\tII_IPX_Get_Connection_Number95@0\npublic _IPX_Uninitialise@0\n_IPX_Uninitialise@0:\n\tmov\tcl,5\n; _IPX_Get_Connection_Number95(16) = _IPX_Get_Connection_Number95(32) {}\n;\n;\npublic II_IPX_Get_Connection_Number95@0\nII_IPX_Get_Connection_Number95@0:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tcall\tdword ptr [pfnQT_Thunk_thipx]\n\tcwde\n\tleave\n\tretn\n\n\n\n\n\n;\npublic _IPX_Get_Internet_Address95@12\n_IPX_Get_Internet_Address95@12:\n\tmov\tcl,1\n; _IPX_Get_Internet_Address95(16) = _IPX_Get_Internet_Address95(32) {}\n;\n; dword ptr [ebp+8]:  param1\n; dword ptr [ebp+12]:  netnum\n; dword ptr [ebp+16]:  node\n;\npublic II_IPX_Get_Internet_Address95@12\nII_IPX_Get_Internet_Address95@12:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tpush\tword ptr [ebp+8]\t;param1: dword->word\n\tcall\tSMapLS_IP_EBP_12\n\tpush\teax\n\tcall\tSMapLS_IP_EBP_16\n\tpush\teax\n\tcall\tdword ptr [pfnQT_Thunk_thipx]\n\tcwde\n\tcall\tSUnMapLS_IP_EBP_12\n\tcall\tSUnMapLS_IP_EBP_16\n\tleave\n\tretn\t12\n\n\n\n\n\n;\npublic __IPX_Get_User_ID95@8\n__IPX_Get_User_ID95@8:\n\tmov\tcl,0\n; __IPX_Get_User_ID95(16) = __IPX_Get_User_ID95(32) {}\n;\n; dword ptr [ebp+8]:  param1\n; dword ptr [ebp+12]:  user_id\n;\npublic II__IPX_Get_User_ID95@8\nII__IPX_Get_User_ID95@8:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tpush\tword ptr [ebp+8]\t;param1: dword->word\n\tcall\tSMapLS_IP_EBP_12\n\tpush\teax\n\tcall\tdword ptr [pfnQT_Thunk_thipx]\n\tcwde\n\tcall\tSUnMapLS_IP_EBP_12\n\tleave\n\tretn\t8\n\n\n\n\nELSE\n;************************* START OF 16-BIT CODE *************************\n\n\n\n\n\tOPTION SEGMENT:USE16\n\t.model LARGE,PASCAL\n\n\n\t.code\t\n\n\n\nexternDef __IPX_Get_User_ID95:far16\nexternDef _IPX_Get_Internet_Address95:far16\nexternDef _IPX_Get_Connection_Number95:far16\nexternDef _IPX_Close_Socket95:far16\nexternDef _IPX_Open_Socket95:far16\nexternDef _IPX_Uninitialise:far16\nexternDef _IPX_Initialise:far16\n\n\nFT_thipxTargetTable label word\n\tdw\toffset __IPX_Get_User_ID95\n\tdw\t   seg __IPX_Get_User_ID95\n\tdw\toffset _IPX_Get_Internet_Address95\n\tdw\t   seg _IPX_Get_Internet_Address95\n\tdw\toffset _IPX_Get_Connection_Number95\n\tdw\t   seg _IPX_Get_Connection_Number95\n\tdw\toffset _IPX_Close_Socket95\n\tdw\t   seg _IPX_Close_Socket95\n\tdw\toffset _IPX_Open_Socket95\n\tdw\t   seg _IPX_Open_Socket95\n\tdw\toffset _IPX_Uninitialise\n\tdw\t   seg _IPX_Uninitialise\n\tdw\toffset _IPX_Initialise\n\tdw\t   seg _IPX_Initialise\n\n\n\n\n\t.data\n\npublic thipx_ThunkData16\t;This symbol must be exported.\nthipx_ThunkData16\tdd\t3130534ch\t;Protocol 'LS01'\n\tdd\t0a179h\t;Checksum\n\tdw\toffset FT_thipxTargetTable\n\tdw\tseg    FT_thipxTargetTable\n\tdd\t0\t;First-time flag.\n\n\n\n\t.code \n\n\nexternDef ThunkConnect16:far16\n\npublic thipx_ThunkConnect16\nthipx_ThunkConnect16:\n\tpop\tax\n\tpop\tdx\n\tpush\tseg    thipx_ThunkData16\n\tpush\toffset thipx_ThunkData16\n\tpush\tseg    thipx_ThkData32\n\tpush\toffset thipx_ThkData32\n\tpush\tcs\n\tpush\tdx\n\tpush\tax\n\tjmp\tThunkConnect16\nthipx_ThkData32 label byte\n\tdb\t\"thipx_ThunkData32\",0\n\n\n\n\n\nENDIF\nEND\n"
  },
  {
    "path": "IPX/OK/THIPX.THK",
    "content": "\nenablemapdirect3216 = true;\n\ntypedef\tint\tBOOL;\ntypedef\tint\tINT;\n\n\ntypedef\tstruct tag_network_number {\n\t\tunsigned char   bytes[4];\n}network_number;\n\ntypedef struct tag_physical_node {\n\t\tunsigned char   bytes[6];\n}physical_node;\n\n\n\n\nBOOL _IPX_Initialise(INT)\n{\n}\n\nBOOL _IPX_Uninitialise(void)\n{\n}\n\nINT  _IPX_Open_Socket95(INT)\n{\n}\n\nINT  _IPX_Close_Socket95(INT)\n{\n}\n\nINT  _IPX_Get_Connection_Number95(void)\n{\n}\n\nINT  _IPX_Get_Internet_Address95(INT, network_number* netnum, physical_node* node)\n{\n\tnetnum\t= output;\n\tnode\t= output;\n}\n\nINT  _IPX_Get_User_ID95(INT, char *user_id)\n{\n\tuser_id\t= output;\n}\n\n\ntypedef struct tag_send_address_struct{\n\tunsigned char\taddress[6];\n}send_address_struct;\n\ntypedef struct tag_send_buffer_struct{\n\tunsigned char\tbuffer[512];\n}send_buffer_struct;\n\n\nINT _IPX_Send_Packet95(send_address_struct *address, send_buffer_struct *buffer, INT)\n{\n\taddress\t= input;\n\tbuffer\t= input;\n}\n\nINT _IPX_Broadcast_Packet95(send_buffer_struct *buffer, INT)\n{\n\tbuffer\t= input;\n}\n\nINT _IPX_Get_Local_Target95(network_number *netnum, physical_node *node, short, send_address_struct *address)\n{\n\tnetnum\t= input;\n\tnode\t= input;\n\taddress\t= output;\n}\n\n\nINT _IPX_Start_Listening95(void)\n{\n}\n\nINT _IPX_Shut_Down95(void)\n{\n}\n\n\ntypedef struct tag_get_buffer_struct{\n\tunsigned char\tget_buffer[1024];\n}get_buffer_struct;\n\nINT _IPX_Get_Outstanding_Buffer95(get_buffer_struct *buffer)\n{\n\tbuffer\t= output;\n}\n\n\n\n"
  },
  {
    "path": "IPX/OK/THIPX16C.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n\n#include <windows.h>\n\nextern \"C\" {\n\tBOOL FAR PASCAL Thipx_ThunkConnect16_(LPSTR pszDll16, LPSTR pszDll32, WORD  hInst, DWORD dwReason);\n}\n\nint CALLBACK LibMain (HANDLE, WORD, WORD, LPSTR)\n{\n\treturn (1);\n}\n\n\nextern \"C\" {\n\tBOOL FAR PASCAL DllEntryPoint_ (DWORD dwReason, WORD hInst, WORD, WORD, DWORD, WORD);\n}\n\n\nBOOL FAR PASCAL DllEntryPoint_ (DWORD dwReason, WORD hInst, WORD, WORD, DWORD, WORD)\n{\n\tOutputDebugString(\"In 16bit DLL entry point. Calling Thipx_ThunkConnect16\\r\\n\");\n\n\tif (!Thipx_ThunkConnect16_(\"THIPX16.DLL\", \"THIPX32.DLL\", hInst, dwReason)){\n        OutputDebugString(\"In 16bit DllEntryPoint: thkThunkConnect16 ret FALSE\\r\\n\");\n        return FALSE;\n    }\n\n    OutputDebugString(\"In 16bit DllEntryPoint: thkThunkConnect16 ret TRUE\\r\\n\");\n    return TRUE;\n}\n\n\n"
  },
  {
    "path": "IPX/OK/THIPX32C.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n\n#define WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#include <windows.h>\n\n\n\nextern \"C\" {\nBOOL WINAPI Thipx_ThunkConnect32(LPSTR pszDll16, LPSTR pszDll32, DWORD hIinst, DWORD dwReason);\n};\n\n\n\n\nBOOL APIENTRY DllMain(DWORD hInst, DWORD dwReason, DWORD dwReserved)\n\n{\n\tOutputDebugString(\"In THIPX32.DLL : DllMain\\r\\n\");\n    if (! Thipx_ThunkConnect32(\"THIPX16.DLL\", \"THIPX32.DLL\", hInst, dwReason)) {\n        OutputDebugString(\"ERROR! 32Bit ThunkConnect32 failed!\\r\\n\");\n        return FALSE;\n    }\n\tOutputDebugString(\"32Bit ThunkConnect32 succeeded.\\r\\n\");\n\treturn (TRUE);\n}\n\n\nBOOL APIENTRY LibMain(DWORD hInst, DWORD dwReason, DWORD dwReserved)\n{\n\treturn (DllMain(hInst, dwReason, dwReserved));\n}\n"
  },
  {
    "path": "IPX/OK/THMAP16.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\n\n\n\t.8086\n\n\tOPTION READONLY\n\tOPTION OLDSTRUCTS\n\tOPTION SEGMENT:USE16\n\t.model LARGE,PASCAL\n\n\n\t.code\n\n\nexterndef\tpascal Thipx_ThunkConnect16_:far16\nextern\t\tpascal Thipx_ThunkConnect16:near16\n\nThipx_ThunkConnect16_ \tproc\tfar16 pascal\n\n\t\tjmp\tThipx_ThunkConnect16\n\nThipx_ThunkConnect16_\tendp\n\n\n\nexterndef\tDllEntryPoint:far16\nextern\t\tpascal DllEntryPoint_:far16\n\nDllEntryPoint \tproc\tfar16\n\n\t\tjmp\tDllEntryPoint_\n\nDllEntryPoint\tendp\n\n\n\n\n\tend\n\n\n\n\n"
  },
  {
    "path": "IPX/OK/THMAP32.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\t.386\n\tOPTION READONLY\n\tOPTION OLDSTRUCTS\n\n\t.model FLAT\n\n\n\n\t.code\n\n\n;externdef\t_DllMain@12:near\n;externdef\tDllMain@12:near\n;\n;DllMain\t\tproc near\n;\n;\t\tjmp\t_DllMain@12\n;\n;DllMain\t\tendp\n\n\n\nexterndef \t_IPX_Initialise:near\nexterndef \t__IPX_Initialise@4:near\n\n_IPX_Initialise\tproc near\n\n\t\tjmp\t__IPX_Initialise@4\n\n_IPX_Initialise endp\n\n\n\n\nexterndef \t_IPX_Uninitialise:near\nexterndef \t__IPX_Uninitialise@0:near\n\n_IPX_Uninitialise\tproc near\n\n\t\tjmp\t__IPX_Uninitialise@0\n\n_IPX_Uninitialise endp\n\n\n\n\nexterndef \t_IPX_Open_Socket95:near\nexterndef \t__IPX_Open_Socket95@4:near\n\n_IPX_Open_Socket95\tproc near\n\n\t\tjmp\t__IPX_Open_Socket95@4\n\n_IPX_Open_Socket95 endp\n\n\n\n\n\nexterndef \t_IPX_Close_Socket95:near\nexterndef \t__IPX_Close_Socket95@4:near\n\n_IPX_Close_Socket95\tproc near\n\n\t\tjmp\t__IPX_Close_Socket95@4\n\n_IPX_Close_Socket95 endp\n\n\n\nexterndef \t_IPX_Get_Connection_Number95:near\nexterndef \t__IPX_Get_Connection_Number95@0:near\n\n_IPX_Get_Connection_Number95\tproc near\n\n\t\tjmp\t__IPX_Get_Connection_Number95@0\n\n_IPX_Get_Connection_Number95 endp\n\n\n\nexterndef \t_IPX_Get_Internet_Address95:near\nexterndef \t__IPX_Get_Internet_Address95@12:near\n\n_IPX_Get_Internet_Address95\tproc near\n\n\t\tjmp\t__IPX_Get_Internet_Address95@12\n\n_IPX_Get_Internet_Address95 endp\n\n\n\nexterndef \t_IPX_Get_User_ID95:near\nexterndef \t__IPX_Get_User_ID95@8:near\n\n_IPX_Get_User_ID95\tproc near\n\n\t\tjmp\t__IPX_Get_User_ID95@8\n\n_IPX_Get_User_ID95 endp\n\n\n\n\nexterndef \t_IPX_Send_Packet95:near\nexterndef \t__IPX_Send_Packet95@12:near\n\n_IPX_Send_Packet95\tproc near\n\n\t\tjmp\t__IPX_Send_Packet95@12\n\n_IPX_Send_Packet95 endp\n\n\n\nexterndef \t_IPX_Broadcast_Packet95:near\nexterndef \t__IPX_Broadcast_Packet95@8:near\n\n_IPX_Broadcast_Packet95\tproc near\n\n\t\tjmp\t__IPX_Broadcast_Packet95@8\n\n_IPX_Broadcast_Packet95 endp\n\n\n\nexterndef \t_IPX_Get_Local_Target95:near\nexterndef \t__IPX_Get_Local_Target95@16:near\n\n_IPX_Get_Local_Target95\tproc near\n\n\t\tjmp\t__IPX_Get_Local_Target95@16\n\n_IPX_Get_Local_Target95 endp\n\n\n\nexterndef \t_IPX_Start_Listening95:near\nexterndef \t__IPX_Start_Listening95@0:near\n\n_IPX_Start_Listening95\tproc near\n\n\t\tjmp\t__IPX_Start_Listening95@0\n\n_IPX_Start_Listening95 endp\n\n\n\nexterndef \t_IPX_Shut_Down95:near\nexterndef \t__IPX_Shut_Down95@0:near\n\n_IPX_Shut_Down95\tproc near\n\n\t\tjmp\t__IPX_Shut_Down95@0\n\n_IPX_Shut_Down95 endp\n\n\n\nexterndef \t_IPX_Get_Outstanding_Buffer95:near\nexterndef \t__IPX_Get_Outstanding_Buffer95@4:near\n\n_IPX_Get_Outstanding_Buffer95\tproc near\n\n\t\tjmp\t__IPX_Get_Outstanding_Buffer95@4\n\n_IPX_Get_Outstanding_Buffer95 endp\n\n\n\tend\n"
  },
  {
    "path": "IPX/OK/WWIPX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\tpage\t,132\n\n;Thunk Compiler Version 1.8  May 11 1995 13:16:19\n;File Compiled Tue Jan 16 13:53:22 1996\n\n;Command Line: D:\\MSTOOLS\\BIN\\THUNK.EXE wwipx.thk \n\n\tTITLE\t$wwipx.asm\n\n\t.386\n\tOPTION READONLY\n\tOPTION OLDSTRUCTS\n\nIFNDEF IS_16\nIFNDEF IS_32\n%out command line error: specify one of -DIS_16, -DIS_32\n.err\nENDIF  ;IS_32\nENDIF  ;IS_16\n\n\nIFDEF IS_32\nIFDEF IS_16\n%out command line error: you can't specify both -DIS_16 and -DIS_32\n.err\nENDIF ;IS_16\n;************************* START OF 32-BIT CODE *************************\n\n\n\t.model FLAT,STDCALL\n\n\n;-- Import common flat thunk routines (in k32)\n\nexternDef MapHInstLS\t:near32\nexternDef MapHInstLS_PN\t:near32\nexternDef MapHInstSL\t:near32\nexternDef MapHInstSL_PN\t:near32\nexternDef FT_Prolog\t:near32\nexternDef FT_Thunk\t:near32\nexternDef QT_Thunk\t:near32\nexternDef FT_Exit0\t:near32\nexternDef FT_Exit4\t:near32\nexternDef FT_Exit8\t:near32\nexternDef FT_Exit12\t:near32\nexternDef FT_Exit16\t:near32\nexternDef FT_Exit20\t:near32\nexternDef FT_Exit24\t:near32\nexternDef FT_Exit28\t:near32\nexternDef FT_Exit32\t:near32\nexternDef FT_Exit36\t:near32\nexternDef FT_Exit40\t:near32\nexternDef FT_Exit44\t:near32\nexternDef FT_Exit48\t:near32\nexternDef FT_Exit52\t:near32\nexternDef FT_Exit56\t:near32\nexternDef SMapLS\t:near32\nexternDef SUnMapLS\t:near32\nexternDef SMapLS_IP_EBP_8\t:near32\nexternDef SUnMapLS_IP_EBP_8\t:near32\nexternDef SMapLS_IP_EBP_12\t:near32\nexternDef SUnMapLS_IP_EBP_12\t:near32\nexternDef SMapLS_IP_EBP_16\t:near32\nexternDef SUnMapLS_IP_EBP_16\t:near32\nexternDef SMapLS_IP_EBP_20\t:near32\nexternDef SUnMapLS_IP_EBP_20\t:near32\nexternDef SMapLS_IP_EBP_24\t:near32\nexternDef SUnMapLS_IP_EBP_24\t:near32\nexternDef SMapLS_IP_EBP_28\t:near32\nexternDef SUnMapLS_IP_EBP_28\t:near32\nexternDef SMapLS_IP_EBP_32\t:near32\nexternDef SUnMapLS_IP_EBP_32\t:near32\nexternDef SMapLS_IP_EBP_36\t:near32\nexternDef SUnMapLS_IP_EBP_36\t:near32\nexternDef SMapLS_IP_EBP_40\t:near32\nexternDef SUnMapLS_IP_EBP_40\t:near32\n\nMapSL\tPROTO NEAR STDCALL p32:DWORD\n\n\n\n\t.code \n\n;************************* COMMON PER-MODULE ROUTINES *************************\n\n\t.data\n\npublic wwipx_ThunkData32\t;This symbol must be exported.\nwwipx_ThunkData32 label dword\n\tdd\t3130534ch\t;Protocol 'LS01'\n\tdd\t043bh\t;Checksum\n\tdd\t0\t;Jump table address.\n\tdd\t3130424ch\t;'LB01'\n\tdd\t0\t;Flags\n\tdd\t0\t;Reserved (MUST BE 0)\n\tdd\t0\t;Reserved (MUST BE 0)\n\tdd\toffset QT_Thunk_wwipx - offset wwipx_ThunkData32\n\tdd\toffset FT_Prolog_wwipx - offset wwipx_ThunkData32\n\n\n\n\t.code \n\n\nexternDef ThunkConnect32@24:near32\n\npublic wwipx_ThunkConnect32@16\nwwipx_ThunkConnect32@16:\n\tpop\tedx\n\tpush\toffset wwipx_ThkData16\n\tpush\toffset wwipx_ThunkData32\n\tpush\tedx\n\tjmp\tThunkConnect32@24\nwwipx_ThkData16 label byte\n\tdb\t\"wwipx_ThunkData16\",0\n\n\n\t\t\n\n\npfnQT_Thunk_wwipx\tdd offset QT_Thunk_wwipx\npfnFT_Prolog_wwipx\tdd offset FT_Prolog_wwipx\n\t.data\nQT_Thunk_wwipx label byte\n\tdb\t32 dup(0cch)\t;Patch space.\n\nFT_Prolog_wwipx label byte\n\tdb\t32 dup(0cch)\t;Patch space.\n\n\n\t.code \n\n\n\n\n\n;************************ START OF THUNK BODIES************************\n\n\n\n\n;\npublic IPX_Initialise@4\nIPX_Initialise@4:\n\tmov\tcl,0\n; IPX_Initialise(16) = IPX_Initialise(32) {}\n;\n; dword ptr [ebp+8]:  param1\n;\npublic IIIPX_Initialise@4\nIIIPX_Initialise@4:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tpush\tword ptr [ebp+8]\t;param1: dword->word\n\tcall\tdword ptr [pfnQT_Thunk_wwipx]\n\tcwde\n\tleave\n\tretn\t4\n\n\n\n\nELSE\n;************************* START OF 16-BIT CODE *************************\n\n\n\n\n\tOPTION SEGMENT:USE16\n\t.model LARGE,PASCAL\n\n\n\t.code\t\n\n\n\nexternDef IPX_Initialise:far16\n\n\nFT_wwipxTargetTable label word\n\tdw\toffset IPX_Initialise\n\tdw\t   seg IPX_Initialise\n\n\n\n\n\t.data\n\npublic wwipx_ThunkData16\t;This symbol must be exported.\nwwipx_ThunkData16\tdd\t3130534ch\t;Protocol 'LS01'\n\tdd\t043bh\t;Checksum\n\tdw\toffset FT_wwipxTargetTable\n\tdw\tseg    FT_wwipxTargetTable\n\tdd\t0\t;First-time flag.\n\n\n\n\t.code \n\n\nexternDef ThunkConnect16:far16\n\npublic wwipx_ThunkConnect16\nwwipx_ThunkConnect16:\n\tpop\tax\n\tpop\tdx\n\tpush\tseg    wwipx_ThunkData16\n\tpush\toffset wwipx_ThunkData16\n\tpush\tseg    wwipx_ThkData32\n\tpush\toffset wwipx_ThkData32\n\tpush\tcs\n\tpush\tdx\n\tpush\tax\n\tjmp\tThunkConnect16\nwwipx_ThkData32 label byte\n\tdb\t\"wwipx_ThunkData32\",0\n\n\n\n\n\nENDIF\nEND\n"
  },
  {
    "path": "IPX/OK/WWIPX16.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\tpage\t,132\n\n;Thunk Compiler Version 1.8  May 11 1995 13:16:19\n;File Compiled Tue Jan 16 13:14:21 1996\n\n;Command Line: D:\\MSTOOLS\\BIN\\THUNK.EXE wwipx16.thk \n\n\tTITLE\t$wwipx16.asm\n\n\t.386\n\tOPTION READONLY\n\tOPTION OLDSTRUCTS\n\nIFNDEF IS_16\nIFNDEF IS_32\n%out command line error: specify one of -DIS_16, -DIS_32\n.err\nENDIF  ;IS_32\nENDIF  ;IS_16\n\n\nIFDEF IS_32\nIFDEF IS_16\n%out command line error: you can't specify both -DIS_16 and -DIS_32\n.err\nENDIF ;IS_16\n;************************* START OF 32-BIT CODE *************************\n\n\n\t.model FLAT,STDCALL\n\n\n;-- Import common flat thunk routines (in k32)\n\nexternDef MapHInstLS\t:near32\nexternDef MapHInstLS_PN\t:near32\nexternDef MapHInstSL\t:near32\nexternDef MapHInstSL_PN\t:near32\nexternDef FT_Prolog\t:near32\nexternDef FT_Thunk\t:near32\nexternDef QT_Thunk\t:near32\nexternDef FT_Exit0\t:near32\nexternDef FT_Exit4\t:near32\nexternDef FT_Exit8\t:near32\nexternDef FT_Exit12\t:near32\nexternDef FT_Exit16\t:near32\nexternDef FT_Exit20\t:near32\nexternDef FT_Exit24\t:near32\nexternDef FT_Exit28\t:near32\nexternDef FT_Exit32\t:near32\nexternDef FT_Exit36\t:near32\nexternDef FT_Exit40\t:near32\nexternDef FT_Exit44\t:near32\nexternDef FT_Exit48\t:near32\nexternDef FT_Exit52\t:near32\nexternDef FT_Exit56\t:near32\nexternDef SMapLS\t:near32\nexternDef SUnMapLS\t:near32\nexternDef SMapLS_IP_EBP_8\t:near32\nexternDef SUnMapLS_IP_EBP_8\t:near32\nexternDef SMapLS_IP_EBP_12\t:near32\nexternDef SUnMapLS_IP_EBP_12\t:near32\nexternDef SMapLS_IP_EBP_16\t:near32\nexternDef SUnMapLS_IP_EBP_16\t:near32\nexternDef SMapLS_IP_EBP_20\t:near32\nexternDef SUnMapLS_IP_EBP_20\t:near32\nexternDef SMapLS_IP_EBP_24\t:near32\nexternDef SUnMapLS_IP_EBP_24\t:near32\nexternDef SMapLS_IP_EBP_28\t:near32\nexternDef SUnMapLS_IP_EBP_28\t:near32\nexternDef SMapLS_IP_EBP_32\t:near32\nexternDef SUnMapLS_IP_EBP_32\t:near32\nexternDef SMapLS_IP_EBP_36\t:near32\nexternDef SUnMapLS_IP_EBP_36\t:near32\nexternDef SMapLS_IP_EBP_40\t:near32\nexternDef SUnMapLS_IP_EBP_40\t:near32\n\nMapSL\tPROTO NEAR STDCALL p32:DWORD\n\n\n\n\t.code \n\n;************************* COMMON PER-MODULE ROUTINES *************************\n\n\t.data\n\npublic wwipx16_ThunkData32\t;This symbol must be exported.\nwwipx16_ThunkData32 label dword\n\tdd\t3130534ch\t;Protocol 'LS01'\n\tdd\t043bh\t;Checksum\n\tdd\t0\t;Jump table address.\n\tdd\t3130424ch\t;'LB01'\n\tdd\t0\t;Flags\n\tdd\t0\t;Reserved (MUST BE 0)\n\tdd\t0\t;Reserved (MUST BE 0)\n\tdd\toffset QT_Thunk_wwipx16 - offset wwipx16_ThunkData32\n\tdd\toffset FT_Prolog_wwipx16 - offset wwipx16_ThunkData32\n\n\n\n\t.code \n\n\nexternDef ThunkConnect32@24:near32\n\npublic wwipx16_ThunkConnect32@16\nwwipx16_ThunkConnect32@16:\n\tpop\tedx\n\tpush\toffset wwipx16_ThkData16\n\tpush\toffset wwipx16_ThunkData32\n\tpush\tedx\n\tjmp\tThunkConnect32@24\nwwipx16_ThkData16 label byte\n\tdb\t\"wwipx16_ThunkData16\",0\n\n\n\t\t\n\n\npfnQT_Thunk_wwipx16\tdd offset QT_Thunk_wwipx16\npfnFT_Prolog_wwipx16\tdd offset FT_Prolog_wwipx16\n\t.data\nQT_Thunk_wwipx16 label byte\n\tdb\t32 dup(0cch)\t;Patch space.\n\nFT_Prolog_wwipx16 label byte\n\tdb\t32 dup(0cch)\t;Patch space.\n\n\n\t.code \n\n\n\n\n\n;************************ START OF THUNK BODIES************************\n\n\n\n\n;\npublic IPX_Initialise@4\nIPX_Initialise@4:\n\tmov\tcl,0\n; IPX_Initialise(16) = IPX_Initialise(32) {}\n;\n; dword ptr [ebp+8]:  param1\n;\npublic IIIPX_Initialise@4\nIIIPX_Initialise@4:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tpush\tword ptr [ebp+8]\t;param1: dword->word\n\tcall\tdword ptr [pfnQT_Thunk_wwipx16]\n\tcwde\n\tleave\n\tretn\t4\n\n\n\n\nELSE\n;************************* START OF 16-BIT CODE *************************\n\n\n\n\n\tOPTION SEGMENT:USE16\n\t.model LARGE,PASCAL\n\n\n\t.code\t\n\n\n\nexternDef IPX_Initialise:far16\n\n\nFT_wwipx16TargetTable label word\n\tdw\toffset IPX_Initialise\n\tdw\t   seg IPX_Initialise\n\n\n\n\n\t.data\n\npublic wwipx16_ThunkData16\t;This symbol must be exported.\nwwipx16_ThunkData16\tdd\t3130534ch\t;Protocol 'LS01'\n\tdd\t043bh\t;Checksum\n\tdw\toffset FT_wwipx16TargetTable\n\tdw\tseg    FT_wwipx16TargetTable\n\tdd\t0\t;First-time flag.\n\n\n\n\t.code \n\n\nexternDef ThunkConnect16:far16\n\npublic wwipx16_ThunkConnect16\nwwipx16_ThunkConnect16:\n\tpop\tax\n\tpop\tdx\n\tpush\tseg    wwipx16_ThunkData16\n\tpush\toffset wwipx16_ThunkData16\n\tpush\tseg    wwipx16_ThkData32\n\tpush\toffset wwipx16_ThkData32\n\tpush\tcs\n\tpush\tdx\n\tpush\tax\n\tjmp\tThunkConnect16\nwwipx16_ThkData32 label byte\n\tdb\t\"wwipx16_ThunkData32\",0\n\n\n\n\n\nENDIF\nEND\n"
  },
  {
    "path": "IPX/OLD/IPX16A.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\n\n\t\t.8086\n\n\n\t\t.model\tlarge\n\t\toption\tsegment:USE16\n\t\toption\treadonly\n\t\toption\toldstructs\n\n\n\t\tassume\tds:@data\n\t\tassume\tes:nothing\n\n\nRECEIVE_BUFFER_LENGTH\t=1024\nMAX_RECEIVE_BUFFERS\t=32\n\n\nexterndef GLOBALDOSALLOC:far\nexterndef GLOBALDOSFREE:far\n\n\n\t\t.data\n\nIPXCallOffset\tdw\t0\nIPXCallSegment\tdw\t0\nRealSegment\tdw\t0\nPseudoES\tdw\t0\n\n\n\nRegisterDump\tdb\t32h dup (0)\n\nMyNetworkNumber\tdb\t4 dup (?)\nMyNodeAddress\tdb\t6 dup (?)\nMySocket\tdw\t?\n\nReceiveBufferSegment\tdw\t?\nReceiveBufferSelector\tdw\t?\nReceiveECBOffset\tdw\t?\nCurrentReceiveBuffer\tdw\t?\nLastPassedReceiveBuffer\tdw\t?\nRealModeCallbackSegment\tdw\t?\nRealModeCallbackOffset\tdw\t?\n\nCallbackRegisterDump\tdb\t32h dup (0)\n\nListening\t\tdb\t?\nNoReenter\t\tdb\t0\nIPXHold\t\t\tdb\t0\n\n\n\nOFFS\t\t=0\nSEGM\t\t=2\n\n\n;---------------------------------------------------------------------------\n;These defines are for the IPX functions.  The function number is specified\n;by placing it in BX when IPX is called.  There are two ways to invoke IPX:\n;use interrupt 0x7a, or use a function whose address is obtained by calling\n;interrupt 0x2f with AX=0x7a00; the function address is returned in ES:DI.\n;This is the preferred method, since other apps are known to use int 0x7a.\n;---------------------------------------------------------------------------\nIPX_OPEN_SOCKET\t\t\t= 0000h\nIPX_CLOSE_SOCKET\t\t= 0001h\nIPX_GET_LOCAL_TARGET\t\t= 0002h\nIPX_SEND_PACKET\t\t\t= 0003h\nIPX_LISTEN_FOR_PACKET\t\t= 0004h\nIPX_SCHEDULE_EVENT\t\t= 0005h\nIPX_CANCEL_EVENT\t\t= 0006h\nIPX_GET_INTERVAL_MARKER\t\t= 0008h\nIPX_GET_INTERNETWORK_ADDRESS\t= 0009h\nIPX_RELINQUISH_CONTROL\t\t= 000Ah\nIPX_DISCONNECT_FROM_TARGET\t= 000Bh\n\n;/*---------------------------------------------------------------------------\n;These defines are for various IPX error codes:\n;---------------------------------------------------------------------------*/\nIPXERR_CONNECTION_SEVERED\t= 00ech\nIPXERR_CONNECTION_FAILED\t= 00edh\nIPXERR_NO_CONNECTION\t\t= 00eeh\nIPXERR_CONNECTION_TABLE_FULL\t= 00efh\nIPXERR_NO_CANCEL_ECB\t\t= 00f9h\nIPXERR_NO_PATH\t\t\t= 00fah\nIPXERR_ECB_INACTIVE\t\t= 00fch\nIPXERR_INVALID_PACKET_LENGTH\t= 00fdh\nIPXERR_SOCKET_TABLE_FULL\t= 00feh\nIPXERR_SOCKET_ERROR\t\t= 00ffh\n\n;/*---------------------------------------------------------------------------\n;These defines are for various interrupt vectors and DPMI functions:\n;---------------------------------------------------------------------------*/\nIPX_INT\t\t\t= 007ah\nDPMI_INT\t\t= 0031h\nDPMI_ALLOC_DOS_MEM\t= 0100h\nDPMI_FREE_DOS_MEM\t= 0101h\nDPMI_CALL_REAL_INT\t= 0300h\nDPMI_CALL_REAL_PROC\t= 0301h\nDPMI_ALLOCATE_CALLBACK\t= 0303h\nDPMI_RELEASE_CALLBACK\t= 0304h\nDPMI_LOCK_MEM\t\t= 0600h\nDPMI_UNLOCK_MEM\t\t= 0601h\n\n\n\n\n\nrequest_buffer\tstruct\n\t\tlen\t\t\tword\t?\n\t\tbuffer_type\t\tbyte\t?\n\t\tconnect_number\t\tbyte\t?\nrequest_buffer\tends\n\n\n\nrequest_local_target_buffer struct\n\t\tlt_network_number\tdb\t?,?,?,?\n\t\tlt_physical_node\tdb\t?,?,?,?,?,?\n\t\tlt_socket\t\tdw\t?\nrequest_local_target_buffer ends\n\n\nlocal_target_reply_buffer struct\n\t\tlt_local_target\t\tdb\t?,?,?,?,?,?\nlocal_target_reply_buffer ends\n\n\n\nreply_buffer\tstruct\n\t\tlem\t\t\tword\t?\n\t\tnetwork_number\t\tbyte\t?,?,?,?\n\t\tphysical_node\t\tbyte\t?,?,?,?,?,?\n\t\tserver_socket\t\tword\t?\nreply_buffer\tends\n\n\n\n\n\nuserid_buffer \tstruct\n\t\tstruct_len\t\tword\t?\n\t\tobject_id\tbyte\t?,?,?,?\n\t\tobject_type\tbyte\t?,?\n\t\tobject_name\tbyte\t48 dup(?)\n\t\tlogin_time\tbyte\t7 dup (?)\n\t\treserved\tword\t?\nuserid_buffer\tends\n\n\t\t.code\n\n\t\t.386\n\n\t\tinclude <pcmacro.16>\n\nexterndef\tpascal _IPX_Initiialise:far16\nexterndef\tpascal _IPX_Uninitialise:far16\n\n\n_IPX_Initialise\tproc far pascal\n\n\t\tpush\tebx\n\t\tpush\tecx\n\t\tpush\tedx\n\t\tpush\tesi\n\t\tpush\tedi\n\t\tpush\tebp\n\t\tpush\tds\n\t\tpush\tes\n\t\tpush\tfs\n\t\tpush\tgs\n\n\t\tmov\tax,7a00h\n\t\tint\t2fh\n\t\tand\teax,0ffh\n\t\tcmp\tal,-1\n\t\tsetz\tal\n\n\t\ttest\tal,al\n\t\tjz\t@f\n\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\t[IPXCallSegment],es\n\t\tmov\t[IPXCallOffset],di\n\n@@:\t\tpop\tgs\n\t\tpop\tfs\n\t\tpop\tes\n\t\tpop\tds\n\t\tpop\tebp\n\t\tpop\tedi\n\t\tpop\tesi\n\t\tpop\tedx\n\t\tpop\tecx\n\t\tpop\tebx\n\t\tret\n\n_IPX_Initialise\tendp\n\n\n\n_IPX_Open_Socket95 proc far pascal uses bx cx dx si di ds es fs gs,\n\t\tsocket:word\n\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\tbx,IPX_OPEN_SOCKET\t;open socket\n\t\tmov_w\tdx,[socket]\t\t;socket number\n\t\tmov_w\t[MySocket],dx\t\t;save it for later\n\t\tmov\tax,0ffh\t\t\t;long lived\n\n\t\tcall\tCall_IPX\n\n\t\tret\n\n_IPX_Open_Socket95 endp\n\n\n\n\n_IPX_Close_Socket95 proc far pascal uses ax bx cx dx si di ds es fs gs,\n\t\tsocket:word\n\n\t\tmov\tbx,1\n\t\tmov_w\tdx,[socket]\n\n\t\tcall\tCall_IPX\n\n\t\tret\n\n_IPX_Close_Socket95 endp\n\n\n\n\n\n_IPX_Uninitialise proc far pascal\n\n\t\tint\t3\n\t\tret\n\n_IPX_Uninitialise endp\n\n\n\n\n\n_IPX_Get_Connection_Number95 proc far pascal uses bx cx dx si di ds es fs gs\n\n\t\tmov\tax,0dc00h\n\t\tcall\tCall_DOS\n\t\tand\teax,255\n\t\tret\n\n_IPX_Get_Connection_Number95 endp\n\n\n\n\n\n\n_IPX_Get_Internet_Address95 proc far pascal uses bx cx dx si di ds es fs gs,\n\t\tconnection_number\t:dword,\n\t\tnetwork_number_off\t:word,\n\t\tnetwork_number_seg\t:word,\n\t\tphysical_node_off\t:word,\n\t\tphysical_node_seg\t:word\n\n\t\tlocal\tselector:word\n\t\tlocal\tsegmento:word\n\n\t\tret\nifdef cuts ;(unfinished)\n\t\t;\n\t\t; Allocate DOS memory for buffers passed to interrupt\n\t\t;\n\t\tint\t3\n\t\txor\tax,ax\n\t\tmov\tbx,(sizeof reply_buffer + sizeof request_buffer + 15)\n\t\tsave\tbp\n\t\tpush\tax\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSALLOC\n\t\trestore\tbp\n\t\ttest\tax,ax\n\t\tjz\t@@dpmi_error\n\n\t\tmov\t[segmento],dx\n\t\tmov\t[selector],ax\n\t\tmov\tfs,dx\n\t\txor\tdi,di\n\n\t\tmov_w\tfs:[di.len],2\n\t\tmov_b\tfs:[di.buffer_type],13h\n\t\tmov_b\tal,[connection_number]\n\t\tmov_b\tfs:[di.connect_number],al\n\n\t\tmov\tdi,sizeof request_buffer\n\t\tmov\tfs:[di.len],12\n\n\n\t\tmov\tax,0e300h\n\t\tmov\tds,[segmento]\n\t\tmov\tes,[segmento]\n\t\txor\tsi,si\n\n\t\tpusha\n\t\tcall\tCall_DOS\n\t\tpopa\n\n\t\tles\tdi,dword ptr [network_number_off]\n\t\tmov\tds,[selector]\n\t\tmov\tsi,sizeof request_buffer + network_number\n\t\tmovsd\n\n\t\tles\tdi,dword ptr [physical_node_off]\n\t\tmov\tsi,sizeof request_buffer + physical_node\n\t\tmovsd\n\t\tmovsw\n\n\t\t;\n\t\t; Save it here for posterity (or perhaps later use)\n\t\t;\n\t\tmov\tdi,offset MyNetworkNumber\n\t\tmov\tax,@data\n\t\tmov\tes,ax\n\t\tmov\tds,[selector]\n\t\tmov\tsi,sizeof request_buffer + network_number\n\t\tmovsd\n\n\t\tmov\tdi,offset MyNodeAddress\n\t\tmov\tsi,sizeof request_buffer + physical_node\n\t\tmovsd\n\t\tmovsw\n\n\n\t\t;\n\t\t; Free the DOS memory\n\t\t;\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\tes,bx\n\t\tmov\tfs,bx\n\t\tmov\tgs,bx\n\t\tmov\tbx,[selector]\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSFREE\n\n\t\txor\tax,ax\n\t\tret\n\n@@dpmi_error:\tmov\tax,-1\n\t\tret\nendif\n\n_IPX_Get_Internet_Address95 endp\n\n\n\n\n\n\n_IPX_Get_User_ID95 proc far pascal uses bx cx dx si di ds es fs gs,\n\t\tconnection_number:dword,\n\t\tuser_id_off:word,\n\t\tuser_id_seg:word\n\n\t\tlocal\tsegmento:word\n\t\tlocal\tselector:word\n\n\t\tint\t3\n\n\t\tcmp\t[connection_number],0\n\t\tjz\t@@return_error\n\n\t\t;\n\t\t; Allocate DOS memory for buffers passed to interrupt\n\t\t;\n\t\txor\tax,ax\n\t\tmov\tbx,(sizeof reply_buffer + sizeof request_buffer + 15)\n\t\tsave\tbp\n\t\tpush\tax\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSALLOC\n\t\trestore\tbp\n\t\ttest\tax,ax\n\t\tjz\t@@return_error\n\n\t\tmov\t[segmento],dx\n\t\tmov\t[selector],ax\n\t\tmov\tfs,dx\n\t\txor\tdi,di\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\n\t\tmov_w\tfs:[di.len],2\n\t\tmov_b\tfs:[di.buffer_type],16h\n\t\tmov_b\tal,[connection_number]\n\t\tmov_b\tfs:[di.connect_number],al\n\n\t\tmov\tdi,sizeof request_buffer\n\t\tmov\tfs:[di.struct_len],sizeof userid_buffer-2\n\n\t\tmov\tax,0e300h\n\t\tmov\tds,[segmento]\n\t\tmov\tes,[segmento]\n\t\txor\tsi,si\n\n\t\tpusha\n\t\tcall\tCall_DOS\n\t\tpopa\n\n\t\tles\tdi,dword ptr [user_id_off]\n\t\tmov\tds,[selector]\n\t\tmov\tsi,sizeof request_buffer + object_name\n\t\tmov\tcx,48/4\n\t\trep\tmovsd\n\n\t\t;\n\t\t; Free the DOS memory\n\t\t;\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\tes,bx\n\t\tmov\tfs,bx\n\t\tmov\tgs,bx\n\t\tmov\tbx,[selector]\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSFREE\n\n\t\txor\tax,ax\n\t\tret\n\n@@return_error:\tmov\tax,-1\n\t\tret\n\n_IPX_Get_User_ID95 endp\n\n\n\n\n;---------------------------------------------------------------------------\n;This is the IPX Packet structure.  It's followed by the data itself, which\n;can be up to 546 bytes long.  Annotation of 'IPX' means IPX will set this\n;field; annotation of 'APP' means the application must set the field.\n;NOTE: All header fields are ordered high-byte,low-byte.\n;---------------------------------------------------------------------------*/\nIPXHeaderType\tstruct\n\n\t\tCheckSum\t\tdw\t?\t\t; IPX: Not used; always 0xffff\n\t\tIPXLength\t\tdw\t?               ; IPX: Total size, incl header & data\n\t\tTransportControl\tdb\t?               ; IPX: # bridges message crossed\n\t\tPacketType\t\tdb\t?               ; APP: Set to 4 for IPX (5 for SPX)\n\t\tDestNetworkNumber\tdb\t?,?,?,?         ; APP: destination Network Number\n\t\tDestNetworkNode\t\tdb\t?,?,?,?,?,?     ; APP: destination Node Address\n\t\tDestNetworkSocket\tdw\t?               ; APP: destination Socket Number\n\t\tSourceNetworkNumber\tdb\t?,?,?,?         ; IPX: source Network Number\n\t\tSourceNetworkNode\tdb\t?,?,?,?,?,?     ; IPX: source Node Address\n\t\tSourceNetworkSocket\tdw\t?               ; IPX: source Socket Number\n\nIPXHeaderType\tends\n\n\n\n\n;/*---------------------------------------------------------------------------\n;This is the IPX Event Control Block.  It serves as a communications area\n;between IPX and the application for a single IPX operation.  You should set\n;up a separate ECB for each IPX operation you perform.\n;---------------------------------------------------------------------------*/\n\nECB\t\tstruct\n\n\t\tLink_Address\t\tdd\t?\n\t\tEvent_Service_Routine\tdd\t?\t\t; APP: event handler (NULL=none)\n\t\tInUse\t\t\tdb\t?               ; IPX: 0 = event complete\n\t\tCompletionCode\t\tdb\t?               ; IPX: event's return code\n\t\tSocketNumber\t\tdw\t?               ; APP: socket to send data through\n\t\tConnectionID\t\tdw\t?               ; returned by Listen (???)\n\t\tRestOfWorkspace\t\tdw\t?\n\t\tDriverWorkspace\t\tdb\t12 dup (?)\n\t\tImmediateAddress\tdb\t6 dup (?)       ; returned by Get_Local_Target\n\t\tPacketCount\t\tdw\t?\n\t\tPacketAddress0\t\tdd\t?\n\t\tPacketLength0\t\tdw\t?\n\t\tPacketAddress1\t\tdd\t?\n\t\tPacketLength1\t\tdw\t?\n\nECB\t\tends\n\n\nSEND_ECB_OFFSET\t\t=0\nSEND_HEADER_OFFSET\t=(sizeof ECB +3) AND 0fffch\nSEND_BUFFER_OFFSET\t=(SEND_HEADER_OFFSET + sizeof IPXHeaderType +3) AND 0fffch\n\n\n_IPX_Send_Packet95 proc far pascal uses ebx ecx edx esi edi ds es fs gs,\n\t\tsend_address\t:far ptr byte,\n\t\tsend_buffer\t:far ptr byte,\n\t\tsend_buffer_len\t:word\n\n\t\tlocal\tselector\t:word\n\t\tlocal\tsegmento\t:word\n\t\tlocal\tdos_send_ecb\t:far ptr ECB\n\t\tlocal\tdos_send_header\t:far ptr IPXHeaderType\n\t\tlocal\tdos_send_buffer\t:far ptr byte\n\t\tlocal\tcompletion_code\t:word\n\n\t\tint\t3\n\t\t;\n\t\t; Allocate required DOS memory\n\t\t;\n\t\txor\tax,ax\n\t\tmov\tbx,(sizeof ECB + sizeof IPXHeaderType + 1024 +31)\n\t\tsave\tbp\n\t\tpush\tax\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSALLOC\n\t\trestore\tbp\n\t\ttest\tax,ax\n\t\tjz\t@@error\n\t\tmov\t[segmento],dx\n\t\tmov\t[selector],ax\n\n\t\t;\n\t\t; Set up the pointers to the dos memory\n\t\t;\n\t\tmov_w\t[dos_send_ecb+OFFS],SEND_ECB_OFFSET\n\t\tmov_w\t[dos_send_ecb+SEGM],ax\n\t\tmov_w\t[dos_send_header+OFFS],SEND_HEADER_OFFSET\n\t\tmov_w\t[dos_send_header+SEGM],ax\n\t\tmov_w\t[dos_send_buffer+OFFS],SEND_BUFFER_OFFSET\n\t\tmov_w\t[dos_send_buffer+SEGM],ax\n\n\t\t;\n\t\t; Clear out the send ECB\n\t\t;\n\t\txor\tal,al\n\t\tmov\tcx,sizeof ECB\n\t\tles\tdi,[dos_send_ecb]\n\t\trep\tstosb\n\n\t\t;\n\t\t; Clear out the send header\n\t\t;\n\t\tmov\tcx,sizeof IPXHeaderType\n\t\tles\tdi,[dos_send_header]\n\t\trep\tstosb\n\n\t\t;\n\t\t; Copy the data to be sent into the send buffer\n\t\t;\n\t\tmov\tcx,546\n\t\tcmp_w\tcx,[send_buffer_len]\n\t\tjle\t@@got_buffer_len\n\t\tmov_w\tcx,[send_buffer_len]\n@@got_buffer_len:\n\t\tmov_w\t[send_buffer_len],546\t;always send same size packets (nice and big for Kali hehe)\n\t\tles\tdi,[dos_send_buffer]\n\t\tlds\tsi,[send_buffer]\n\t\trep\tmovsb\n\n\t\t;\n\t\t; Fill in the ECB\n\t\t;\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\tfs,ax\t\t\t;keep ptr to data seg in fs\n\t\tles\tdi,[dos_send_ecb]\n\n\t\tassume\tds:@data\n\t\tassume\tfs:@data\n\n\t\tmov\tax,[MySocket]\n\t\tmov\tes:[di.SocketNumber],ax\n\t\tmov\tes:[di.PacketCount],2\n\t\tmov\tax,[segmento]\n\t\tshl\teax,16\n\t\tmov_w\tax,[dos_send_header+OFFS]\n\t\tmov_d\tes:[di.PacketAddress0],eax\n\t\tmov_w\tes:[di.PacketLength0],sizeof IPXHeaderType\n\t\tmov_w\tax,[dos_send_buffer+OFFS]\n\t\tmov_d\tes:[di.PacketAddress1],eax\n\t\tmov_w\tax,[send_buffer_len]\n\t\tmov_w\tes:[di.PacketLength1],ax\n\n\t\t;assume\tds:nothing\n\t\t;\n\t\t; Fill in the address field\n\t\t;\n\t\tlds\tsi,[send_address]\n\t\tmov\teax,[si]\n\t\tmov_d\tes:[di.ImmediateAddress],eax\n\t\tmov\tax,[si+4]\n\t\tmov_w\tes:[di.ImmediateAddress+4],ax\n\n\t\t;\n\t\t; Fill in the outgoing header\n\t\t;\n\t\tles\tdi,[dos_send_header]\n\t\tmov\tes:[di.PacketType],4\n\t\tpush\tfs:[MySocket]\n\t\tpop\tes:[di.DestNetworkSocket]\n\n\t\t;\n\t\t; Fill in the nwtowrk number and node address\n\t\t;\n\t\tmov_d\teax,fs:[MyNetworkNumber]\n\t\tmov_d\tes:[di.DestNetworkNumber],eax\n\t\tmov_d\teax,fs:[MyNodeAddress]\n\t\tmov_d\tes:[di.DestNetworkNode],eax\n\t\tmov_w\tax,fs:[MyNodeAddress+4]\n\t\tmov_w\tes:[di.DestNetworkNode+4],ax\n\n\t\t;\n\t\t; Send that sucker!\n\t\t;\n\t\tmov\tsi,[segmento]\n\t\tmov\tfs:[PseudoES],si\n\t\tmov\tsi,SEND_ECB_OFFSET\n\t\tmov\tbx,IPX_SEND_PACKET\n\t\tpusha\n\t\tpush\tfs\n\t\tcall\tCall_IPX\n\t\tpop\tfs\n\t\tpopa\n\t\tmov\tfs:[PseudoES],0\n\n\n\t\tassume\tfs:nothing\n\t\t;\n\t\t; Wait for the send to finish\n\t\t;\n@@wait_send_loop:\n\t\tlds\tsi,[dos_send_ecb]\n\t\tcmp\t[si.InUse],0\n\t\tjz\t@@done\n\n\t\tmov\tbx,IPX_RELINQUISH_CONTROL\n\t\tsave\tbp\n\t\tcall\tCall_IPX\n\t\trestore\tbp\n\t\tjmp\t@@wait_send_loop\n\n\n\t\t;\n\t\t; Get the completion code\n\t\t;\n@@done:\t\tlds\tsi,[dos_send_ecb]\n\t\tmov\tal,[si.CompletionCode]\n\t\txor\tah,ah\n\t\tmov\t[completion_code],ax\n\n\t\t;\n\t\t; Free the DOS memory\n\t\t;\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\tes,bx\n\t\tmov\tfs,bx\n\t\tmov\tgs,bx\n\t\tmov\tbx,[selector]\n\t\tsave\tbp\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSFREE\n\t\trestore\tbp\n\n\t\tcmp\t[completion_code],0\n\t\tjz\t@@error\n\n@@success:\tmov\tax,1\n\t\tret\n\n\n@@error:\txor\tax,ax\n\t\tret\n\n\n_IPX_Send_Packet95 endp\n\n\n\n\n\n\n_IPX_Broadcast_Packet95 proc far pascal uses ebx ecx edx esi edi ds es fs gs,\n\t\tsend_buffer\t:far ptr byte,\n\t\tsend_buffer_len\t:word\n\n\t\tlocal\tselector\t:word\n\t\tlocal\tsegmento\t:word\n\t\tlocal\tdos_send_ecb\t:far ptr ECB\n\t\tlocal\tdos_send_header\t:far ptr IPXHeaderType\n\t\tlocal\tdos_send_buffer\t:far ptr byte\n\t\tlocal\tcompletion_code\t:word\n\n\t\tint\t3\n\t\t;\n\t\t; Allocate required DOS memory\n\t\t;\n\t\txor\tax,ax\n\t\tmov\tbx,(sizeof ECB + sizeof IPXHeaderType + 1024 +31)\n\t\tsave\tbp\n\t\tpush\tax\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSALLOC\n\t\trestore\tbp\n\t\ttest\tax,ax\n\t\tjz\t@@error\n\t\tmov\t[segmento],dx\n\t\tmov\t[selector],ax\n\n\t\t;\n\t\t; Set up the pointers to the dos memory\n\t\t;\n\t\tmov_w\t[dos_send_ecb+OFFS],SEND_ECB_OFFSET\n\t\tmov_w\t[dos_send_ecb+SEGM],ax\n\t\tmov_w\t[dos_send_header+OFFS],SEND_HEADER_OFFSET\n\t\tmov_w\t[dos_send_header+SEGM],ax\n\t\tmov_w\t[dos_send_buffer+OFFS],SEND_BUFFER_OFFSET\n\t\tmov_w\t[dos_send_buffer+SEGM],ax\n\n\t\t;\n\t\t; Clear out the send ECB\n\t\t;\n\t\txor\tal,al\n\t\tmov\tcx,sizeof ECB\n\t\tles\tdi,[dos_send_ecb]\n\t\trep\tstosb\n\n\t\t;\n\t\t; Clear out the send header\n\t\t;\n\t\tmov\tcx,sizeof IPXHeaderType\n\t\tles\tdi,[dos_send_header]\n\t\trep\tstosb\n\n\t\t;\n\t\t; Copy the data to be sent into the send buffer\n\t\t;\n\t\tmov\tcx,546\n\t\tcmp_w\tcx,[send_buffer_len]\n\t\tjle\t@@got_buffer_len\n\t\tmov_w\tcx,[send_buffer_len]\n@@got_buffer_len:\n\t\tmov_w\t[send_buffer_len],546\t;always send same size packets (nice and big for Kali hehe)\n\t\tles\tdi,[dos_send_buffer]\n\t\tlds\tsi,[send_buffer]\n\t\trep\tmovsb\n\n\t\t;\n\t\t; Fill in the ECB\n\t\t;\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\tfs,ax\t\t\t;keep ptr to data seg in fs\n\t\tles\tdi,[dos_send_ecb]\n\n\t\tassume\tfs:@data\n\t\tassume\tds:@data\n\n\t\tmov\tax,[MySocket]\n\t\tmov\tes:[di.SocketNumber],ax\n\t\tmov\tes:[di.PacketCount],2\n\t\tmov\tax,[segmento]\n\t\tshl\teax,16\n\t\tmov_w\tax,[dos_send_header+OFFS]\n\t\tmov_d\tes:[di.PacketAddress0],eax\n\t\tmov_w\tes:[di.PacketLength0],sizeof IPXHeaderType\n\t\tmov_w\tax,[dos_send_buffer+OFFS]\n\t\tmov_d\tes:[di.PacketAddress1],eax\n\t\tmov_w\tax,[send_buffer_len]\n\t\tmov_w\tes:[di.PacketLength1],ax\n\n\t\t;assume\tds:nothing\n\t\t;\n\t\t; Fill in the address field\n\t\t;\n\t\tmov_d\tes:[di.ImmediateAddress],0ffffffffh\n\t\tmov_w\tes:[di.ImmediateAddress+4],0ffffh\n\n\t\t;\n\t\t; Fill in the outgoing header\n\t\t;\n\t\tles\tdi,[dos_send_header]\n\t\tmov\tes:[di.PacketType],4\n\t\tpush\tfs:[MySocket]\n\t\tpop\tes:[di.DestNetworkSocket]\n\n\t\t;\n\t\t; Fill in the nwtowrk number and node address\n\t\t;\n\t\tmov_d\tes:[di.DestNetworkNumber],0ffffffffh\n\t\tmov_d\tes:[di.DestNetworkNode],0ffffffffh\n\t\tmov_w\tes:[di.DestNetworkNode+4],0ffffh\n\n\t\t;\n\t\t; Send that sucker!\n\t\t;\n\t\tmov\tsi,[segmento]\n\t\tmov\tfs:[PseudoES],si\n\t\tmov\tsi,SEND_ECB_OFFSET\n\t\tmov\tbx,IPX_SEND_PACKET\n\t\tpusha\n\t\tpush\tfs\n\t\tcall\tCall_IPX\n\t\tpop\tfs\n\t\tpopa\n\t\tmov\tfs:[PseudoES],0\n\n\t\tassume\tfs:nothing\n\t\t;\n\t\t; Wait for the send to finish\n\t\t;\n@@wait_send_loop:\n\t\tlds\tsi,[dos_send_ecb]\n\t\tcmp\t[si.InUse],0\n\t\tjz\t@@done\n\n\t\tmov\tbx,IPX_RELINQUISH_CONTROL\n\t\tsave\tbp\n\t\tcall\tCall_IPX\n\t\trestore\tbp\n\t\tjmp\t@@wait_send_loop\n\n\n\n\t\t;\n\t\t; Get the completion code\n\t\t;\n@@done:\t\tlds\tsi,[dos_send_ecb]\n\t\tmov\tal,[si.CompletionCode]\n\t\txor\tah,ah\n\t\tmov\t[completion_code],ax\n\n\t\t;\n\t\t; Free the DOS memory\n\t\t;\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\tes,bx\n\t\tmov\tfs,bx\n\t\tmov\tgs,bx\n\t\tmov\tbx,[selector]\n\t\tsave\tbp\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSFREE\n\t\trestore\tbp\n\n\t\tcmp\t[completion_code],0\n\t\tjz\t@@error\n\n\n@@success:\tmov\tax,1\n\t\tret\n\n\n@@error:\txor\tax,ax\n\t\tret\n\n\n_IPX_Broadcast_Packet95 endp\n\n\n\n\n\n\n\n_IPX_Get_Local_Target95\tproc far pascal uses ebx ecx edx esi edi ds es fs gs,\n\t\tdest_network\t:far ptr byte,\n\t\tdest_node\t:far ptr byte,\n\t\tsocket\t\t:word,\n\t\tbridge_address\t:far ptr byte\n\n\n\t\tlocal\tsegmento\t:word\n\t\tlocal\tselector\t:word\n\t\tlocal\tresult_code\t:word\n\n\t\tint\t3\n\t\t;\n\t\t; Allocate DOS memory for buffers passed to interrupt\n\t\t;\n\t\txor\tax,ax\n\t\tmov\tbx,(sizeof local_target_reply_buffer + \\\n\t\t\t    sizeof request_local_target_buffer + 15)\n\t\tsave\tbp\n\t\tpush\tax\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSALLOC\n\t\trestore\tbp\n\t\ttest\tax,ax\n\t\tjz\t@@return_error\n\n\t\tmov\t[segmento],dx\n\t\tmov\t[selector],ax\n\t\tmov\tfs,dx\n\t\txor\tdi,di\n\n\t\t;\n\t\t; Init the request structure\n\t\t;\n\t\tmov_d\teax,[dest_network]\n\t\tmov_d\tfs:[di.lt_network_number],eax\n\t\tmov_d\teax,[dest_node]\n\t\tmov_d\tfs:[di.lt_physical_node],eax\n\t\tmov_w\tax,[dest_node+4]\n\t\tmov_w\tfs:[di.lt_physical_node+4],ax\n\t\tmov\tax,[socket]\n\t\tmov\tfs:[di.lt_socket],ax\n\n\t\tmov\tbx,IPX_GET_LOCAL_TARGET\n\t\tmov\tax,[segmento]\n\t\tmov\tds,ax\n\t\txor\tsi,si\n\t\tmov\tes,ax\n\t\tmov\tdi,sizeof request_local_target_buffer\n\n\t\tpush\tbp\n\t\tcall\tCall_IPX\n\t\tpop\tbp\n\n\t\tmov\t[result_code],ax\n\n\t\tmov\tds,[selector]\n\t\tmov\tsi,sizeof request_local_target_buffer + lt_local_target\n\t\tles\tdi,bridge_address\n\t\tmovsd\n\t\tmovsw\n\n\t\t;\n\t\t; Free the DOS memory\n\t\t;\n\t\tmov\tbx,@data\n\t\tmov\tds,bx\n\t\tmov\tes,bx\n\t\tmov\tfs,bx\n\t\tmov\tgs,bx\n\t\tmov\tbx,[selector]\n\t\tsave\tbp\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSFREE\n\t\trestore\tbp\n\n\t\t;\n\t\t; Return the IPX result code\n\t\t;\n\t\tmov\tax,[result_code]\n\t\tret\n\n@@return_error:\tmov\tax,-1\n\t\tret\n\n_IPX_Get_Local_Target95\tendp\n\n\n\n\n_IPX_Get_Outstanding_Buffer95 proc far pascal uses ebx ecx edx esi edi ebp ds es fs gs,\n\t\tcopy_receive_buffer:far ptr byte\n\n\t\tint\t3\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\n\t\txor\tax,ax\n\t\tmov\tsi,[LastPassedReceiveBuffer]\n\t\tcmp\tsi,[CurrentReceiveBuffer]\n\t\tjz\t@@done\n\n\t\tpush\tds\n\t\tmov\tcx,RECEIVE_BUFFER_LENGTH/4\n\t\tmov\tds,[ReceiveBufferSelector]\n\t\tles\tdi,[copy_receive_buffer]\n\t\trep\tmovsd\n\t\tpop\tds\n\n\t\tcmp\tsi,RECEIVE_BUFFER_LENGTH*MAX_RECEIVE_BUFFERS\n\t\tjc\t@@no_wrap\n\t\txor\tsi,si\n@@no_wrap:\tmov\t[LastPassedReceiveBuffer],si\n\n\t\tmov\tax,1\n\n@@done:\t\tret\n\n_IPX_Get_Outstanding_Buffer95 endp\n\n\n\n\nReceive_Callback proc far\n\n\t\tpushf\n\t\tcli\n\t\tcld\n\t\tpushad\n\t\tpush\tds\n\t\tpush\tes\n\t\tpush\tfs\n\t\tpush\tgs\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tcmp\t[NoReenter],0\n\t\tjnz\t@@out\n\t\tmov\t[NoReenter],1\n\t\tmov\tax,[CurrentReceiveBuffer]\n\n\t\tadd\tax,RECEIVE_BUFFER_LENGTH\n\t\tcmp\tax,RECEIVE_BUFFER_LENGTH*MAX_RECEIVE_BUFFERS\n\t\tjc\t@@no_wrap\n\t\txor\tax,ax\n@@no_wrap:\tmov\t[CurrentReceiveBuffer],ax\n\n\t\tcall\tListen_For_Packet\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\t[NoReenter],0\n\n@@out:\t\tpop\tgs\n\t\tpop\tfs\n\t\tpop\tes\n\t\tpop\tds\n\t\tpopad\n\t\tpopf\n\t\tret\n\nReceive_Callback endp\n\n\n\n\n\nInit_Receive_ECB proc near uses eax ebx ecx edx esi edi ebp ds es\n\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\tes,[ReceiveBufferSelector]\n\n\t\t;\n\t\t; Clear out the ECB\n\t\t;\n\t\tmov\tdi,[ReceiveECBOffset]\n\t\tmov\tcx,sizeof ECB\n\t\txor\tal,al\n\t\trep\tstosb\n\n\n;\n; Set up the ECB\n;\n\t\t;\n\t\t;General ECB data\n\t\tmov\tdi,[ReceiveECBOffset]\n\t\tmov\tax,[MySocket]\n\t\tmov\tes:[di.SocketNumber],ax\n\t\tmov\tes:[di.PacketCount],2\n\n\t\t;\n\t\t; Packet address for IPX header\n\t\tmov\tax,[CurrentReceiveBuffer]\n\t\tmov\tbx,[ReceiveBufferSegment]\n\t\tmov_w\tes:[di.PacketAddress0+OFFS],ax\n\t\tmov_w\tes:[di.PacketAddress0+SEGM],bx\n\t\tmov\tes:[di.PacketLength0],sizeof IPXHeaderType\n\n\t\t;\n\t\t; Packet address for receive buffer\n\t\tmov\tax,[CurrentReceiveBuffer]\n\t\tadd\tax,sizeof IPXHeaderType\n\t\tmov_w\tes:[di.PacketAddress1+OFFS],ax\n\t\tmov_w\tes:[di.PacketAddress1+SEGM],bx\n\t\tmov\tes:[di.PacketLength1],546\n\n\t\t;\n\t\t; Set up the callback address\n\t\tmov\tax,[RealModeCallbackOffset]\n\t\tmov_w\tes:[di.Event_Service_Routine+OFFS],ax\n\t\tmov\tax,[RealModeCallbackSegment]\n\t\tmov_w\tes:[di.Event_Service_Routine+SEGM],ax\n\n\t\tret\n\nInit_Receive_ECB endp\n\n\n_IPX_Start_Listening95 proc far pascal uses ebx ecx edx esi edi ebp ds es fs gs\n\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tcmp\t[Listening],0\n\t\tjnz\t@@restart\t\t;already listening\n\n\t\t;\n\t\t; Allocate and lock DOS memory for listen\n\t\t;  ECB and receive buffers\n\t\t;\n\t\tmov\tbx,(RECEIVE_BUFFER_LENGTH*MAX_RECEIVE_BUFFERS + sizeof ECB + 15)\n\t\txor\tax,ax\n\t\tsave\tbp,ds\n\t\tpush\tax\n\t\tpush\tbx\n\t\tcall\tGLOBALDOSALLOC\n\t\trestore\tbp,ds\n\t\ttest\tax,ax\n\t\tjz\t@@error\n\n\t\tmov\t[ReceiveBufferSegment],dx\n\t\tmov\t[ReceiveBufferSelector],ax\n\n\t\t;\n\t\t; Set up pointers to the DOS memory\n\t\t;\n\t\tmov\t[ReceiveECBOffset],RECEIVE_BUFFER_LENGTH * MAX_RECEIVE_BUFFERS\n\t\tmov\t[CurrentReceiveBuffer],0\t;1st receive buffer\n\t\tmov\t[LastPassedReceiveBuffer],0\n\n\t\t;\n\t\t; Set up a real mode callback function\n\t\t;\n\t\tmov\tax,DPMI_ALLOCATE_CALLBACK\n\t\tmov\tsi,offset Receive_Callback\n\t\tmov\tdi,offset CallbackRegisterDump\n\t\tpush\tcs\n\t\tpop\tds\n\t\tmov\tbx,@data\n\t\tmov\tes,bx\n\t\tsave\tbp\n\t\tint\t31h\n\t\trestore\tbp\n\t\tbcs\t@@error\n\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\t[RealModeCallbackSegment],cx\n\t\tmov\t[RealModeCallbackOffset],dx\n\n@@restart:\tsave\tds\n\t\tcall\tListen_For_Packet\n\t\trestore\tds\n\t\tmov\t[Listening],1\n\n@@out:\t\tmov\tax,1\n\t\tret\n\n@@error:\txor\tax,ax\n\t\tret\n\n_IPX_Start_Listening95 endp\n\n\n\n\n_IPX_Shut_Down95 proc far pascal uses eax ebx ecx edx esi edi ebp ds es fs gs\n\n\t\tint\t3\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tcmp\t[Listening],0\n\t\tjz\t@@out\n\n\t\t;\n\t\t; Stop listening for a packet\n\t\t;\n\t\tmov\tes,[ReceiveBufferSegment]\n\t\tmov\tsi,[ReceiveECBOffset]\n\t\tmov\tbx,IPX_CANCEL_EVENT\n\t\tsave\tbp,ds\n\t\tcall\tCall_IPX\n\t\tsave\tbp,ds\n\n\t\t;\n\t\t; Remove the real mode callback function\n\t\t;\n\t\tmov\tcx,[RealModeCallbackSegment]\n\t\tmov\tdx,[RealModeCallbackOffset]\n\t\tmov\tax,DPMI_RELEASE_CALLBACK\n\t\tsave\tbp,ds\n\t\tint\t31h\n\t\trestore\tbp,ds\n\n\t\t;\n\t\t; Free the DOS memory\n\t\t;\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\tes,ax\n\t\tmov\tfs,ax\n\t\tmov\tgs,ax\n\t\tmov\tax,[ReceiveBufferSelector]\n\t\tsave\tbp,ds\n\t\tpush\tax\n\t\tcall\tGLOBALDOSFREE\n\t\trestore\tbp,ds\n\n\t\tmov\t[Listening],0\n\n@@out:\t\tret\n\n_IPX_Shut_Down95 endp\n\n\n\n\nListen_For_Packet proc near uses ebx ecx edx esi edi ebp ds es fs gs\n\n\t\tcall\tInit_Receive_ECB\n\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\tsi,[ReceiveBufferSegment]\n\t\tmov\t[PseudoES],si\n\t\tmov\tsi,[ReceiveECBOffset]\n\t\tmov\tbx,IPX_LISTEN_FOR_PACKET\n\t\tsave\tds\n\t\tcall\tCall_IPX\n\t\trestore\tds\n\t\tmov\t[PseudoES],0\n\n\t\tret\n\nListen_For_Packet endp\n\n\n\n\n\n\nCall_IPX\tproc far\n\n\t\tpush\tgs\n\t\tpush\tax\n\t\tmov\tax,@data\n\t\tmov\tgs,ax\n\t\tpop\tax\n\n\t       \tpush\tbp\n\t\tmov\tbp,offset IPXCallOffset\n\t\tcall\tdword ptr gs:[bp]\n\t\tpop\tbp\n\n\t\tpop\tgs\n\t\tret\n\n\n\n\n\n\n\t\tpush\tgs\n\t\tpush\tax\n\t\tmov\tax,@data\n\t\tmov\tgs,ax\n\t\tpop\tax\n\n\t\t;\n\t\t; Prevent reenterancy\n\t\t;\n@@hold:\t\t;cmp\tgs:[IPXHold],0\n\t\t;jnz\t@@hold\n\n\t\tmov\tgs:[IPXHold],1\n\n\t\t;\n\t\t; Dump the registers first so we can use them\n\t\t;\n\t\tmov_d\tgs:[RegisterDump+0ch],0\n\t\tmov_d\tgs:[RegisterDump],edi\n\t\tmov_d\tgs:[RegisterDump+4],esi\n\t\tmov_d\tgs:[RegisterDump+8],ebp\n\t\tmov_d\tgs:[RegisterDump+10h],ebx\n\t\tmov_d\tgs:[RegisterDump+14h],edx\n\t\tmov_d\tgs:[RegisterDump+18h],ecx\n\t\tmov_d\tgs:[RegisterDump+1ch],eax\n\n\t\tint\t3\n\n\t\tpush\tgs\n\t\txor\tax,ax\n\t\tpush\tax\n\t\tmov\tax,4096\t;4k real mode stack\n\t\tpush\tax\n\t\tcall\tGLOBALDOSALLOC\n\t\tpop\tgs\n\t\tmov\tbx,4094\t;stack ptr\n\t\ttest\tax,ax\n\t\tjnz\t@f\n\t\txor\tbx,bx\n\n\t\t;\n\t\t; Set up stack addr to zero - DPMI will supply a real mode stack\n\t\t;\n@@:\t\tmov_w\tgs:[RegisterDump+2eh],bx\t;sp\n\t\tmov_w\tgs:[RegisterDump+30h],dx\t;ss\n\t\tsave\tax\t;save selector so we can free the memory later\n\n\n\t\t;\n\t\t; Dump the flags\n\t\t;\n\t\tpushf\n\t\tpop\tgs:[word ptr RegisterDump+20h]\n\n\t\t;\n\t\t; Set up all segment register areas to point to our real mode segment\n\t\t;\n\t\tmov_w\tgs:[RegisterDump+22h],es\n\t\tmov_w\tgs:[RegisterDump+24h],ds\n\t\tmov_w\tgs:[RegisterDump+26h],fs\n\t\tmov_w\tgs:[RegisterDump+28h],gs\n\n\t\tcmp\tgs:[PseudoES],0\n\t\tjz\t@f\n\t\tmov\tax,gs:[PseudoES]\n\t\tmov_w\tgs:[RegisterDump+22h],ax\n@@:\n\n\n\t\t;\n\t\t; Set up the address to call\n\t\t;\n\t\tmov\tax,gs:[IPXCallSegment]\n\t\tmov_w\tgs:[RegisterDump+2ch],ax\n\t\tmov\tax,gs:[IPXCallOffset]\n\t\tmov_w\tgs:[RegisterDump+2ah],ax\n\n\t\tmov\tax,DPMI_CALL_REAL_INT\t; Call real mode procedure with far return frame\n\t\txor\tbh,bh\t\t\t; flags - should be zero\n\t\tmov\tbl,07ah\t\t\t; IPX interrupt\n\t\tmov\tecx,0 ;512\t\t\t; number of words to copy from the protected mode stack\n\t\tmov\tdi,offset RegisterDump\n\t\tpush\tgs\n\t\tpop\tes\n\t\tsave\tgs\n\t\t;push\tss\n\t\t;push\tsp\n\t\tint\t31h\t\t;DPMI interrupt\n\n\t\t;pop\tax\n\t\t;pop\tbx\n\t\t;pushf\n\t\t;pop\tcx\n\t\t;cli\n\t\t;mov\tsp,ax\n\t\t;mov\tss,bx\n\t\t;add\tsp,2\n\t\t;push\tcx\n\t\t;popf\n\n\t\trestore\tgs\n\n\t\tmov\tax,@data\n\t\tmov\tds,ax\n\t\tmov\tes,ax\n\t\tmov\tfs,ax\n\t\tmov\tgs,ax\n\t\tcall\tGLOBALDOSFREE\n\n\n\t\tmov_d\teax,gs:[RegisterDump+1ch]\n\t\tmov\tgs:[IPXHold],0\n\t\tpop\tgs\n\n\t\tret\n\n\nCall_IPX\tendp\n\n\n\n\n\n\n\n\nCall_DOS\tproc far\n\n\t\tpush\tgs\n\t\tpush\tax\n\t\tmov\tax,@data\n\t\tmov\tgs,ax\n\t\tpop\tax\n\t\t;\n\t\t; Dump the registers first so we can use them\n\t\t;\n\t\tmov_d\tgs:[RegisterDump],edi\n\t\tmov_d\tgs:[RegisterDump+4],esi\n\t\tmov_d\tgs:[RegisterDump+8],ebp\n\t\tmov_d\tgs:[RegisterDump+10h],ebx\n\t\tmov_d\tgs:[RegisterDump+14h],edx\n\t\tmov_d\tgs:[RegisterDump+18h],ecx\n\t\tmov_d\tgs:[RegisterDump+1ch],eax\n\n\t\t;\n\t\t; Dump the flags\n\t\t;\n\t\tpushf\n\t\tpop\tgs:[word ptr RegisterDump+20h]\n\n\t\t;\n\t\t; Set up all segment register areas to point to our real mode segment\n\t\t;\n\t\tmov_w\tgs:[RegisterDump+22h],es\n\t\tmov_w\tgs:[RegisterDump+24h],ds\n\t\tmov_w\tgs:[RegisterDump+26h],fs\n\t\tmov_w\tgs:[RegisterDump+28h],gs\n\n\t\t;\n\t\t; Set up stack addr to zero - DPMI will supply a real mode stack\n\t\t;\n\t\txor\tax,ax\n\t\tmov_w\tgs:[RegisterDump+2eh],ax\t;sp\n\t\tmov_w\tgs:[RegisterDump+30h],ax\t;ss\n\n\t\tmov\tax,DPMI_CALL_REAL_INT; Simulate real mode interrupt\n\t\txor\tbh,bh\t\t; flags - should be zero\n\t\tmov\tbl,21h\t\t; interrupt number\n\t\tmov\tecx,0 ;512\t\t; number of words to copy from the protected mode stack\n\t\tmov\tdi,offset RegisterDump\n\t\tpush\tgs\n\t\tpop\tes\n\t\tsave\tgs\n\t\tint\t31h\t\t;DPMI interrupt\n\t\trestore\tgs\n\n\t\tmov_d\tedi,gs:[RegisterDump]\n\t\tmov_d\tesi,gs:[RegisterDump+4]\n\t\tmov_d\tebp,gs:[RegisterDump+8]\n\t\tmov_d\tebx,gs:[RegisterDump+10h]\n\t\tmov_d\tedx,gs:[RegisterDump+14h]\n\t\tmov_d\tecx,gs:[RegisterDump+18h]\n\t\tmov_d\teax,gs:[RegisterDump+1ch]\n\t\tmov_w\tes,gs:[RegisterDump+22h]\n\t\tmov_w\tds,gs:[RegisterDump+24h]\n\t\tpop\tgs\n\n\t\tret\n\n\nCall_DOS\tendp\n\n\n\n\n\t\tend\n\n\n\n\n\n\n"
  },
  {
    "path": "IPX/PCMACRO.16",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : 16 bit ASM Macros                        *\n;*                                                                         *\n;*                    File Name : PCMACRO.16                               *\n;*                                                                         *\n;*                   Programmer : Steve Tall\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : November 17th, 1995\t\t\t   *\n;*                                                                         *\n;*                  Last Update : November 20th, 1995   [ST]               *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nsaveall\tmacro\n\tsave\tax,bx,cx,dx,bp,si,di,es,ds\n\tendm\n\nrestall\tmacro\n\trestore\tax,bx,cx,dx,bp,si,di,es,ds\n\tendm\n\nsave\tmacro\tr0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14\n\tIFNB\t<r0>\n\tpush\tr0\n\tsave\tr1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14\n\tENDIF\n\tendm\n\nrestore\tmacro\tr0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14\n\tIFNB\t<r14>\n\tpop\tr14\n\tENDIF\n\tIFNB\t<r13>\n\tpop\tr13\n\tENDIF\n\tIFNB\t<r12>\n\tpop\tr12\n\tENDIF\n\tIFNB\t<r11>\n\tpop\tr11\n\tENDIF\n\tIFNB\t<r10>\n\tpop\tr10\n\tENDIF\n\tIFNB\t<r9>\n\tpop\tr9\n\tENDIF\n\tIFNB\t<r8>\n\tpop\tr8\n\tENDIF\n\tIFNB\t<r7>\n\tpop\tr7\n\tENDIF\n\tIFNB\t<r6>\n\tpop\tr6\n\tENDIF\n\tIFNB\t<r5>\n\tpop\tr5\n\tENDIF\n\tIFNB\t<r4>\n\tpop\tr4\n\tENDIF\n\tIFNB\t<r3>\n\tpop\tr3\n\tENDIF\n\tIFNB\t<r2>\n\tpop\tr2\n\tENDIF\n\tIFNB\t<r1>\n\tpop\tr1\n\tENDIF\n\tIFNB\t<r0>\n\tpop\tr0\n\tENDIF\n\tendm\n\nbhi\tmacro\tlab\n\tja\tlab\n\tendm\n\nbls\tmacro\tlab\n\tjbe\tlab\n\tendm\n\nbcc\tmacro\tlab\n\tjnc\tlab\n\tendm\n\nbcs\tmacro\tlab\n\tjc\tlab\n\tendm\n\nbhs\tmacro\tlab\n\tjnc\tlab\n\tendm\n\nblo\tmacro\tlab\n\tjc\tlab\n\tendm\n\nbne\tmacro\tlab\n\tjne\tlab\n\tendm\n\nbeq\tmacro\tlab\n\tje\tlab\n\tendm\n\nbpl\tmacro\tlab\n\tjns\tlab\n\tendm\n\nbmi\tmacro\tlab\n\tjs\tlab\n\tendm\n\nbge\tmacro\tlab\n\tjge\tlab\n\tendm\n\nblt\tmacro\tlab\n\tjl\tlab\n\tendm\n\nbgt\tmacro\tlab\n\tjg\tlab\n\tendm\n\nble\tmacro\tlab\n\tjle\tlab\n\tendm\n\nbra\tmacro\tlab\n\tjmp\tlab\n\tendm\n\n\nbhis\tmacro\tlab\n\tja\tlab\n\tendm\n\nblss\tmacro\tlab\n\tjbe\tlab\n\tendm\n\nbccs\tmacro\tlab\n\tjnc\tlab\n\tendm\n\nbcss\tmacro\tlab\n\tjc\tlab\n\tendm\n\nbnes\tmacro\tlab\n\tjne\tlab\n\tendm\n\nbeqs\tmacro\tlab\n\tje\tlab\n\tendm\n\nbpls\tmacro\tlab\n\tjns\tlab\n\tendm\n\nbmis\tmacro\tlab\n\tjs\tlab\n\tendm\n\nbges\tmacro\tlab\n\tjge\tlab\n\tendm\n\nblts\tmacro\tlab\n\tjl\tlab\n\tendm\n\nbgts\tmacro\tlab\n\tjg\tlab\n\tendm\n\nbles\tmacro\tlab\n\tjle\tlab\n\tendm\n\nbras\tmacro\tlab\n\tjmp\tlab\n\tendm\n\n\nclear\tmacro\tfirst\n\txor\tfirst,first\n\tendm\n\nrts\tmacro\n\tret\n\tendm\n\n\n\nmov_b\tmacro\tlabel,label2\n\tmov\tbyte ptr label,byte ptr label2\n\tendm\n\n\n\nmov_w\tmacro\tlabel,label2\n\tmov\tword ptr label,word ptr label2\n\tendm\n\n\n\nmov_d\tmacro\tlabel,label2\n\tmov\tdword ptr label,dword ptr label2\n\tendm\n\n\ncmp_b\tmacro\tlabel,label2\n\tcmp\tbyte ptr label,byte ptr label2\n\tendm\n\ncmp_w\tmacro\tlabel,label2\n\tcmp\tword ptr label,word ptr label2\n\tendm\n\ncmp_d\tmacro\tlabel,label2\n\tcmp\tdword ptr label,dword ptr label2\n\tendm\n\n\n\nadd_b\tmacro\tlabel,label2\n\tadd\tbyte ptr label,byte ptr label2\n\tendm\n\nadd_w\tmacro\tlabel,label2\n\tadd\tword ptr label,word ptr label2\n\tendm\n\nadd_d\tmacro\tlabel,label2\n\tadd\tdword ptr label,dword ptr label2\n\tendm\n\n\n\nsub_b\tmacro\tlabel,label2\n\tsub\tbyte ptr label,byte ptr label2\n\tendm\n\nsub_w\tmacro\tlabel,label2\n\tsub\tword ptr label,word ptr label2\n\tendm\n\nsub_d\tmacro\tlabel,label2\n\tsub\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\n\nor_b\tmacro\tlabel,label2\n\tor\tbyte ptr label,byte ptr label2\n\tendm\n\nor_w\tmacro\tlabel,label2\n\tor\tword ptr label,word ptr label2\n\tendm\n\nor_d\tmacro\tlabel,label2\n\tor\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\n\n\n\nxor_b\tmacro\tlabel,label2\n\txor\tbyte ptr label,byte ptr label2\n\tendm\n\nxor_w\tmacro\tlabel,label2\n\txor\tword ptr label,word ptr label2\n\tendm\n\nxor_d\tmacro\tlabel,label2\n\txor\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\n\n\n\n\neor_b\tmacro\tlabel,label2\n\txor\tbyte ptr label,byte ptr label2\n\tendm\n\neor_w\tmacro\tlabel,label2\n\txor\tword ptr label,word ptr label2\n\tendm\n\neor_d\tmacro\tlabel,label2\n\txor\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\nand_b\tmacro\tlabel,label2\n\tand\tbyte ptr label,byte ptr label2\n\tendm\n\nand_w\tmacro\tlabel,label2\n\tand\tword ptr label,word ptr label2\n\tendm\n\nand_d\tmacro\tlabel,label2\n\tand\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\n\ntest_b\tmacro\tlabel,label2\n\ttest\tbyte ptr label,byte ptr label2\n\tendm\n\ntest_w\tmacro\tlabel,label2\n\ttest\tword ptr label,word ptr label2\n\tendm\n\ntest_d\tmacro\tlabel,label2\n\ttest\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\n\n\n\nshr_b\tmacro\tlabel,label2\n\tshr\tbyte ptr label,label2\n\tendm\n\nshr_w\tmacro\tlabel,label2\n\tshr\tword ptr label,label2\n\tendm\n\nshr_d\tmacro\tlabel,label2\n\tshr\tdword ptr label,label2\n\tendm\n\n\n\nshl_b\tmacro\tlabel,label2\n\tshl\tbyte ptr label,label2\n\tendm\n\nshl_w\tmacro\tlabel,label2\n\tshl\tword ptr label,label2\n\tendm\n\nshl_d\tmacro\tlabel,label2\n\tshl\tdword ptr label,label2\n\tendm\n\n\n\n\nsar_b\tmacro\tlabel,label2\n\tsar\tbyte ptr label,label2\n\tendm\n\nsar_w\tmacro\tlabel,label2\n\tsar\tword ptr label,label2\n\tendm\n\nsar_d\tmacro\tlabel,label2\n\tsar\tdword ptr label,label2\n\tendm\n\n\n\n\n\nsal_b\tmacro\tlabel,label2\n\tsal\tbyte ptr label,label2\n\tendm\n\nsal_w\tmacro\tlabel,label2\n\tsal\tword ptr label,label2\n\tendm\n\nsal_d\tmacro\tlabel,label2\n\tsal\tdword ptr label,label2\n\tendm\n\n\n\ninc_b\tmacro\tlabel\n\tinc\tbyte ptr label\n\tendm\n\ninc_w\tmacro\tlabel\n\tinc\tword ptr label\n\tendm\n\ninc_d\tmacro\tlabel\n\tinc\tdword ptr label\n\tendm\n\n\n\n\ndec_b\tmacro\tlabel\n\tdec\tbyte ptr label\n\tendm\n\ndec_w\tmacro\tlabel\n\tdec\tword ptr label\n\tendm\n\ndec_d\tmacro\tlabel\n\tdec\tdword ptr label\n\tendm\n\n\n\n\n\nmovzx_b\tmacro\tlabel,label2\n\tmovzx\tlabel,byte ptr label2\n\tendm\n\n\nmovzx_w\tmacro\tlabel,label2\n\tmovzx\tlabel,word ptr label2\n\tendm\n\n\nmovsx_b\tmacro\tlabel,label2\n\tmovsx\tlabel,byte ptr label2\n\tendm\n\n\nmovsx_w\tmacro\tlabel,label2\n\tmovsx\tlabel,word ptr label2\n\tendm\n\n\n\n\nmul_b\tmacro\tlabel\n\tmul\tbyte ptr label\n\tendm\n\n\nmul_w\tmacro\tlabel\n\tmul\tword ptr label\n\tendm\n\n\ndiv_b\tmacro\tlabel\n\tdiv\tbyte ptr label\n\tendm\n\n\ndiv_w\tmacro\tlabel\n\tdiv\tword ptr label\n\tendm\n\n\nidiv_b\tmacro\tlabel\n\tidiv\tbyte ptr label\n\tendm\n\n\nidiv_w\tmacro\tlabel\n\tidiv\tword ptr label\n\tendm\n\n\n\n\ntst_b\tmacro\tlabel\n\tcmp\tbyte ptr label,0\n\tendm\n\ntst_w\tmacro\tlabel\n\tcmp\tword ptr label,0\n\tendm\n\ntst_d\tmacro\tlabel\n\tcmp\tdword ptr label,0\n\tendm\n\n\n\n\n\n\n\nnot_b\tmacro\tlabel\n\tnot\tbyte ptr label\n\tendm\n\nnot_w\tmacro\tlabel\n\tnot\tword ptr label\n\tendm\n\nnot_d\tmacro\tlabel\n\tnot\tdword ptr label\n\tendm\n\n\n\n\nneg_b\tmacro\tlabel\n\tneg\tbyte ptr label\n\tendm\n\nneg_w\tmacro\tlabel\n\tneg\tword ptr label\n\tendm\n\nneg_d\tmacro\tlabel\n\tneg\tdword ptr label\n\tendm\n\n\n\n\n"
  },
  {
    "path": "IPX/THIPX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\tpage\t,132\n\n;Thunk Compiler Version 1.8  May 11 1995 13:16:19\n;File Compiled Tue Mar 12 13:23:57 1996\n\n;Command Line: C:\\BIN\\THUNK.EXE Thipx.thk \n\n\tTITLE\t$Thipx.asm\n\n\t.386\n\tOPTION READONLY\n\tOPTION OLDSTRUCTS\n\nIFNDEF IS_16\nIFNDEF IS_32\n%out command line error: specify one of -DIS_16, -DIS_32\n.err\nENDIF  ;IS_32\nENDIF  ;IS_16\n\n\nIFDEF IS_32\nIFDEF IS_16\n%out command line error: you can't specify both -DIS_16 and -DIS_32\n.err\nENDIF ;IS_16\n;************************* START OF 32-BIT CODE *************************\n\n\n\t.model FLAT,STDCALL\n\n\n;-- Import common flat thunk routines (in k32)\n\nexternDef MapHInstLS\t:near32\nexternDef MapHInstLS_PN\t:near32\nexternDef MapHInstSL\t:near32\nexternDef MapHInstSL_PN\t:near32\nexternDef FT_Prolog\t:near32\nexternDef FT_Thunk\t:near32\nexternDef QT_Thunk\t:near32\nexternDef FT_Exit0\t:near32\nexternDef FT_Exit4\t:near32\nexternDef FT_Exit8\t:near32\nexternDef FT_Exit12\t:near32\nexternDef FT_Exit16\t:near32\nexternDef FT_Exit20\t:near32\nexternDef FT_Exit24\t:near32\nexternDef FT_Exit28\t:near32\nexternDef FT_Exit32\t:near32\nexternDef FT_Exit36\t:near32\nexternDef FT_Exit40\t:near32\nexternDef FT_Exit44\t:near32\nexternDef FT_Exit48\t:near32\nexternDef FT_Exit52\t:near32\nexternDef FT_Exit56\t:near32\nexternDef SMapLS\t:near32\nexternDef SUnMapLS\t:near32\nexternDef SMapLS_IP_EBP_8\t:near32\nexternDef SUnMapLS_IP_EBP_8\t:near32\nexternDef SMapLS_IP_EBP_12\t:near32\nexternDef SUnMapLS_IP_EBP_12\t:near32\nexternDef SMapLS_IP_EBP_16\t:near32\nexternDef SUnMapLS_IP_EBP_16\t:near32\nexternDef SMapLS_IP_EBP_20\t:near32\nexternDef SUnMapLS_IP_EBP_20\t:near32\nexternDef SMapLS_IP_EBP_24\t:near32\nexternDef SUnMapLS_IP_EBP_24\t:near32\nexternDef SMapLS_IP_EBP_28\t:near32\nexternDef SUnMapLS_IP_EBP_28\t:near32\nexternDef SMapLS_IP_EBP_32\t:near32\nexternDef SUnMapLS_IP_EBP_32\t:near32\nexternDef SMapLS_IP_EBP_36\t:near32\nexternDef SUnMapLS_IP_EBP_36\t:near32\nexternDef SMapLS_IP_EBP_40\t:near32\nexternDef SUnMapLS_IP_EBP_40\t:near32\n\nMapSL\tPROTO NEAR STDCALL p32:DWORD\n\n\n\n\t.code \n\n;************************* COMMON PER-MODULE ROUTINES *************************\n\n\t.data\n\npublic Thipx_ThunkData32\t;This symbol must be exported.\nThipx_ThunkData32 label dword\n\tdd\t3130534ch\t;Protocol 'LS01'\n\tdd\t014cdch\t;Checksum\n\tdd\t0\t;Jump table address.\n\tdd\t3130424ch\t;'LB01'\n\tdd\t0\t;Flags\n\tdd\t0\t;Reserved (MUST BE 0)\n\tdd\t0\t;Reserved (MUST BE 0)\n\tdd\toffset QT_Thunk_Thipx - offset Thipx_ThunkData32\n\tdd\toffset FT_Prolog_Thipx - offset Thipx_ThunkData32\n\n\n\n\t.code \n\n\nexternDef ThunkConnect32@24:near32\n\npublic Thipx_ThunkConnect32@16\nThipx_ThunkConnect32@16:\n\tpop\tedx\n\tpush\toffset Thipx_ThkData16\n\tpush\toffset Thipx_ThunkData32\n\tpush\tedx\n\tjmp\tThunkConnect32@24\nThipx_ThkData16 label byte\n\tdb\t\"Thipx_ThunkData16\",0\n\n\n\t\t\n\n\npfnQT_Thunk_Thipx\tdd offset QT_Thunk_Thipx\npfnFT_Prolog_Thipx\tdd offset FT_Prolog_Thipx\n\t.data\nQT_Thunk_Thipx label byte\n\tdb\t32 dup(0cch)\t;Patch space.\n\nFT_Prolog_Thipx label byte\n\tdb\t32 dup(0cch)\t;Patch space.\n\n\n\t.code \n\n\n\n\n\n;************************ START OF THUNK BODIES************************\n\n\n\n\n;\npublic _IPX_Close_Socket95@4\n_IPX_Close_Socket95@4:\n\tmov\tcl,7\n\tjmp\tII_IPX_Close_Socket95@4\npublic _IPX_Open_Socket95@4\n_IPX_Open_Socket95@4:\n\tmov\tcl,8\n; _IPX_Close_Socket95(16) = _IPX_Close_Socket95(32) {}\n;\n; dword ptr [ebp+8]:  param1\n;\npublic II_IPX_Close_Socket95@4\nII_IPX_Close_Socket95@4:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tpush\tword ptr [ebp+8]\t;param1: dword->word\n\tcall\tdword ptr [pfnQT_Thunk_Thipx]\n\tcwde\n\tleave\n\tretn\t4\n\n\n\n\n\n;\npublic _IPX_Send_Packet95@20\n_IPX_Send_Packet95@20:\n\tmov\tcl,5\n; _IPX_Send_Packet95(16) = _IPX_Send_Packet95(32) {}\n;\n; dword ptr [ebp+8]:  address\n; dword ptr [ebp+12]:  buffer\n; dword ptr [ebp+16]:  param3\n; dword ptr [ebp+20]:  net\n; dword ptr [ebp+24]:  node\n;\npublic II_IPX_Send_Packet95@20\nII_IPX_Send_Packet95@20:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tcall\tSMapLS_IP_EBP_8\n\tpush\teax\n\tcall\tSMapLS_IP_EBP_12\n\tpush\teax\n\tpush\tword ptr [ebp+16]\t;param3: dword->word\n\tcall\tSMapLS_IP_EBP_20\n\tpush\teax\n\tcall\tSMapLS_IP_EBP_24\n\tpush\teax\n\tcall\tdword ptr [pfnQT_Thunk_Thipx]\n\tcwde\n\tcall\tSUnMapLS_IP_EBP_8\n\tcall\tSUnMapLS_IP_EBP_12\n\tcall\tSUnMapLS_IP_EBP_20\n\tcall\tSUnMapLS_IP_EBP_24\n\tleave\n\tretn\t20\n\n\n\n\n\n;\npublic _IPX_Broadcast_Packet95@8\n_IPX_Broadcast_Packet95@8:\n\tmov\tcl,4\n; _IPX_Broadcast_Packet95(16) = _IPX_Broadcast_Packet95(32) {}\n;\n; dword ptr [ebp+8]:  buffer\n; dword ptr [ebp+12]:  param2\n;\npublic II_IPX_Broadcast_Packet95@8\nII_IPX_Broadcast_Packet95@8:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tcall\tSMapLS_IP_EBP_8\n\tpush\teax\n\tpush\tword ptr [ebp+12]\t;param2: dword->word\n\tcall\tdword ptr [pfnQT_Thunk_Thipx]\n\tcwde\n\tcall\tSUnMapLS_IP_EBP_8\n\tleave\n\tretn\t8\n\n\n\n\n\n;\npublic _IPX_Get_Local_Target95@16\n_IPX_Get_Local_Target95@16:\n\tmov\tcl,3\n; _IPX_Get_Local_Target95(16) = _IPX_Get_Local_Target95(32) {}\n;\n; dword ptr [ebp+8]:  netnum\n; dword ptr [ebp+12]:  node\n; dword ptr [ebp+16]:  param3\n; dword ptr [ebp+20]:  address\n;\npublic II_IPX_Get_Local_Target95@16\nII_IPX_Get_Local_Target95@16:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tcall\tSMapLS_IP_EBP_8\n\tpush\teax\n\tcall\tSMapLS_IP_EBP_12\n\tpush\teax\n\tpush\tword ptr [ebp+16]\t;param3: dword->word\n\tcall\tSMapLS_IP_EBP_20\n\tpush\teax\n\tcall\tdword ptr [pfnQT_Thunk_Thipx]\n\tcwde\n\tcall\tSUnMapLS_IP_EBP_8\n\tcall\tSUnMapLS_IP_EBP_12\n\tcall\tSUnMapLS_IP_EBP_20\n\tleave\n\tretn\t16\n\n\n\n\n\n;\npublic _IPX_Shut_Down95@0\n_IPX_Shut_Down95@0:\n\tmov\tcl,1\n\tjmp\tII_IPX_Shut_Down95@0\npublic _IPX_Initialise@0\n_IPX_Initialise@0:\n\tmov\tcl,9\n\tjmp\tII_IPX_Shut_Down95@0\npublic _IPX_Get_Connection_Number95@0\n_IPX_Get_Connection_Number95@0:\n\tmov\tcl,6\n\tjmp\tII_IPX_Shut_Down95@0\npublic _IPX_Start_Listening95@0\n_IPX_Start_Listening95@0:\n\tmov\tcl,2\n; _IPX_Shut_Down95(16) = _IPX_Shut_Down95(32) {}\n;\n;\npublic II_IPX_Shut_Down95@0\nII_IPX_Shut_Down95@0:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tcall\tdword ptr [pfnQT_Thunk_Thipx]\n\tcwde\n\tleave\n\tretn\n\n\n\n\n\n;\npublic _IPX_Get_Outstanding_Buffer95@4\n_IPX_Get_Outstanding_Buffer95@4:\n\tmov\tcl,0\n; _IPX_Get_Outstanding_Buffer95(16) = _IPX_Get_Outstanding_Buffer95(32) {}\n;\n; dword ptr [ebp+8]:  buffer\n;\npublic II_IPX_Get_Outstanding_Buffer95@4\nII_IPX_Get_Outstanding_Buffer95@4:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tcall\tSMapLS_IP_EBP_8\n\tpush\teax\n\tcall\tdword ptr [pfnQT_Thunk_Thipx]\n\tcwde\n\tcall\tSUnMapLS_IP_EBP_8\n\tleave\n\tretn\t4\n\n\n\n\nELSE\n;************************* START OF 16-BIT CODE *************************\n\n\n\n\n\tOPTION SEGMENT:USE16\n\t.model LARGE,PASCAL\n\n\n\t.code\t\n\n\n\nexternDef _IPX_Get_Outstanding_Buffer95:far16\nexternDef _IPX_Shut_Down95:far16\nexternDef _IPX_Start_Listening95:far16\nexternDef _IPX_Get_Local_Target95:far16\nexternDef _IPX_Broadcast_Packet95:far16\nexternDef _IPX_Send_Packet95:far16\nexternDef _IPX_Get_Connection_Number95:far16\nexternDef _IPX_Close_Socket95:far16\nexternDef _IPX_Open_Socket95:far16\nexternDef _IPX_Initialise:far16\n\n\nFT_ThipxTargetTable label word\n\tdw\toffset _IPX_Get_Outstanding_Buffer95\n\tdw\t   seg _IPX_Get_Outstanding_Buffer95\n\tdw\toffset _IPX_Shut_Down95\n\tdw\t   seg _IPX_Shut_Down95\n\tdw\toffset _IPX_Start_Listening95\n\tdw\t   seg _IPX_Start_Listening95\n\tdw\toffset _IPX_Get_Local_Target95\n\tdw\t   seg _IPX_Get_Local_Target95\n\tdw\toffset _IPX_Broadcast_Packet95\n\tdw\t   seg _IPX_Broadcast_Packet95\n\tdw\toffset _IPX_Send_Packet95\n\tdw\t   seg _IPX_Send_Packet95\n\tdw\toffset _IPX_Get_Connection_Number95\n\tdw\t   seg _IPX_Get_Connection_Number95\n\tdw\toffset _IPX_Close_Socket95\n\tdw\t   seg _IPX_Close_Socket95\n\tdw\toffset _IPX_Open_Socket95\n\tdw\t   seg _IPX_Open_Socket95\n\tdw\toffset _IPX_Initialise\n\tdw\t   seg _IPX_Initialise\n\n\n\n\n\t.data\n\npublic Thipx_ThunkData16\t;This symbol must be exported.\nThipx_ThunkData16\tdd\t3130534ch\t;Protocol 'LS01'\n\tdd\t014cdch\t;Checksum\n\tdw\toffset FT_ThipxTargetTable\n\tdw\tseg    FT_ThipxTargetTable\n\tdd\t0\t;First-time flag.\n\n\n\n\t.code \n\n\nexternDef ThunkConnect16:far16\n\npublic Thipx_ThunkConnect16\nThipx_ThunkConnect16:\n\tpop\tax\n\tpop\tdx\n\tpush\tseg    Thipx_ThunkData16\n\tpush\toffset Thipx_ThunkData16\n\tpush\tseg    Thipx_ThkData32\n\tpush\toffset Thipx_ThkData32\n\tpush\tcs\n\tpush\tdx\n\tpush\tax\n\tjmp\tThunkConnect16\nThipx_ThkData32 label byte\n\tdb\t\"Thipx_ThunkData32\",0\n\n\n\n\n\nENDIF\nEND\n"
  },
  {
    "path": "IPX/THIPX.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\nenablemapdirect3216 = true;\n\ntypedef\tint\tBOOL;\ntypedef\tint\tINT;\n\n\ntypedef\tstruct tag_network_number {\n\t\tunsigned char   bytes[4];\n}network_number;\n\ntypedef struct tag_physical_node {\n\t\tunsigned char   bytes[6];\n}physical_node;\n\ntypedef struct tag_send_address_struct{\n\tunsigned char\taddress[6];\n}send_address_struct;\n\ntypedef struct tag_send_buffer_struct{\n\tunsigned char\tbuffer[512];\n}send_buffer_struct;\n\ntypedef struct tag_get_buffer_struct{\n\tunsigned char\tget_buffer[1024];\n}get_buffer_struct;\n\n\n\n\nBOOL _IPX_Initialise(INT)\n{\n}\n\n\nINT  _IPX_Open_Socket95(INT)\n{\n}\n\nINT  _IPX_Close_Socket95(INT)\n{\n}\n\nINT  _IPX_Get_Connection_Number95(void)\n{\n}\n\n\nINT _IPX_Send_Packet95(send_address_struct *address, send_buffer_struct *buffer, INT, network_number *net, physical_node* node)\n{\n\taddress\t= input;\n\tbuffer\t= input;\n\tnet\t= input;\n\tnode\t= input;\n}\n\nINT _IPX_Broadcast_Packet95(send_buffer_struct *buffer, INT)\n{\n\tbuffer\t= input;\n}\n\nINT _IPX_Get_Local_Target95(network_number *netnum, physical_node *node, short, send_address_struct *address)\n{\n\tnetnum\t= input;\n\tnode\t= input;\n\taddress\t= output;\n}\n\n\nINT _IPX_Start_Listening95(void)\n{\n}\n\nINT _IPX_Shut_Down95(void)\n{\n}\n\n\n\nINT _IPX_Get_Outstanding_Buffer95(get_buffer_struct *buffer)\n{\n\tbuffer\t= output;\n}\n\n\n\n"
  },
  {
    "path": "IPX/THIPX.THK",
    "content": "\nenablemapdirect3216 = true;\n\ntypedef\tint\tBOOL;\ntypedef\tint\tINT;\n\n\ntypedef\tstruct tag_network_number {\n\t\tunsigned char   bytes[4];\n}network_number;\n\ntypedef struct tag_physical_node {\n\t\tunsigned char   bytes[6];\n}physical_node;\n\ntypedef struct tag_send_address_struct{\n\tunsigned char\taddress[6];\n}send_address_struct;\n\ntypedef struct tag_send_buffer_struct{\n\tunsigned char\tbuffer[512];\n}send_buffer_struct;\n\ntypedef struct tag_get_buffer_struct{\n\tunsigned char\tget_buffer[1024];\n}get_buffer_struct;\n\n\n\n\nBOOL _IPX_Initialise(void)\n{\n}\n\n\nINT  _IPX_Open_Socket95(INT)\n{\n}\n\nINT  _IPX_Close_Socket95(INT)\n{\n}\n\nINT  _IPX_Get_Connection_Number95(void)\n{\n}\n\n\nINT _IPX_Send_Packet95(send_address_struct *address, send_buffer_struct *buffer, INT, network_number *net, physical_node* node)\n{\n\taddress\t= input;\n\tbuffer\t= input;\n\tnet\t= input;\n\tnode\t= input;\n}\n\nINT _IPX_Broadcast_Packet95(send_buffer_struct *buffer, INT)\n{\n\tbuffer\t= input;\n}\n\nINT _IPX_Get_Local_Target95(network_number *netnum, physical_node *node, short, send_address_struct *address)\n{\n\tnetnum\t= input;\n\tnode\t= input;\n\taddress\t= output;\n}\n\n\nINT _IPX_Start_Listening95(void)\n{\n}\n\nINT _IPX_Shut_Down95(void)\n{\n}\n\n\n\nINT _IPX_Get_Outstanding_Buffer95(get_buffer_struct *buffer)\n{\n\tbuffer\t= output;\n}\n\n\n\n"
  },
  {
    "path": "IPX/THIPX16C.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer 95                                         *\n *                                                                                             *\n *                    File Name : THIPX16C.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 1/15/96                                                      *\n *                                                                                             *\n *                  Last Update : January 29thth 1996 [ST]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *                                                                                             *\n *   'C' code for the 16 bit IPX library. This library is 'thunked' down to from a 32bit       *\n *  .dll.                                                                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *  LibMain -- library entry point                                                             *\n *  DllEntryPoint -- called each time a new app requests use of the .dll                       *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include <windows.h>\n\n\nextern \"C\" {\n\tBOOL FAR PASCAL Thipx_ThunkConnect16_(LPSTR pszDll16, LPSTR pszDll32, WORD  hInst, DWORD dwReason);\n\tBOOL FAR PASCAL DllEntryPoint_ (DWORD dwReason, WORD hInst, WORD, WORD, DWORD, WORD);\n}\n\n\n/***********************************************************************************************\n * LibMain -- library entry point                                                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    the usual windows rubbish                                                         *\n *                                                                                             *\n * OUTPUT:   true                                                                              *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/29/96 10:45AM ST : Created                                                             *\n *=============================================================================================*/\nint CALLBACK LibMain (HANDLE, WORD, WORD, LPSTR)\n{\n\treturn (1);\n}\n\n\n\n/***********************************************************************************************\n * DllEntryPoint -- called each time a new app requests use of the .dll                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    windows junk                                                                      *\n *                                                                                             *\n * OUTPUT:   true                                                                              *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/29/96 10:45AM ST : Created                                                             *\n *=============================================================================================*/\nBOOL FAR PASCAL DllEntryPoint_ (DWORD dwReason, WORD hInst, WORD, WORD, DWORD, WORD)\n{\n\tif (!Thipx_ThunkConnect16_(\"THIPX16.DLL\", \"THIPX32.DLL\", hInst, dwReason)){\n        return FALSE;\n    }\n    return TRUE;\n}\n\n\n"
  },
  {
    "path": "IPX/THIPX32C.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer 95                                         *\n *                                                                                             *\n *                    File Name : THIPX16C.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 1/15/96                                                      *\n *                                                                                             *\n *                  Last Update : January 29thth 1996 [ST]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *                                                                                             *\n *   'C' code for the 32 bit IPX library. This library 'thunks' down to a 16bit .dll           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *  DllMain -- called each time a new app requests use of the .dll                             *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#define WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#include <windows.h>\n\n\nextern \"C\" {\n\tBOOL WINAPI Thipx_ThunkConnect32(LPSTR pszDll16, LPSTR pszDll32, DWORD hIinst, DWORD dwReason);\n};\n\n\n\n/***********************************************************************************************\n * DllMain -- called every time a new app requests use of the .dll                             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    usual windoze junk                                                                *\n *                                                                                             *\n * OUTPUT:   true                                                                              *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/29/96 10:55AM ST : Created                                                             *\n *=============================================================================================*/\nBOOL APIENTRY DllMain(DWORD hInst, DWORD dwReason, DWORD dwReserved)\n\n{\n    if (! Thipx_ThunkConnect32(\"THIPX16.DLL\", \"THIPX32.DLL\", hInst, dwReason)) {\n        return FALSE;\n    }\n\treturn (TRUE);\n}\n\n\n/***********************************************************************************************\n * LibMain -- This just calls DllMain. Watcom erroneously links this in as the entry point!    *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/29/96 10:56AM ST : Created                                                             *\n *=============================================================================================*/\nBOOL APIENTRY LibMain(DWORD hInst, DWORD dwReason, DWORD dwReserved)\n{\n\treturn (DllMain(hInst, dwReason, dwReserved));\n}\n"
  },
  {
    "path": "IPX/THMAP16.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\n\n\n\t.8086\n\n\tOPTION READONLY\n\tOPTION OLDSTRUCTS\n\tOPTION SEGMENT:USE16\n\t.model LARGE,PASCAL\n\n\n\t.code\n\n\nexterndef\tpascal Thipx_ThunkConnect16_:far16\nextern\t\tpascal Thipx_ThunkConnect16:near16\n\nThipx_ThunkConnect16_ \tproc\tfar16 pascal\n\n\t\tjmp\tThipx_ThunkConnect16\n\nThipx_ThunkConnect16_\tendp\n\n\n\nexterndef\tDllEntryPoint:far16\nextern\t\tpascal DllEntryPoint_:far16\n\nDllEntryPoint \tproc\tfar16\n\n\t\tjmp\tDllEntryPoint_\n\nDllEntryPoint\tendp\n\n\n\n\n\tend\n\n\n\n\n"
  },
  {
    "path": "IPX/THMAP32.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : THMAP32.ASM                              *\n;*                                                                         *\n;*                   Programmer : Steve Tall\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : January 25th, 1996\t\t\t   *\n;*                                                                         *\n;*                  Last Update : January 29th, 1996   [ST]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Overview:                                                               *\n;*  These functions exist simply to map similar function names to each     *\n;* other.                                                                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\n\t\t.386\n\t\tOPTION READONLY\n\t\tOPTION OLDSTRUCTS\n\n\t\t.model FLAT\n\n\n\n\t\t.code\n\n\n\n\n\nexterndef \t_IPX_Initialise:near\nexterndef \t__IPX_Initialise@0:near\n_IPX_Initialise\tproc near\n\n\t\tjmp\t__IPX_Initialise@0\n\n_IPX_Initialise endp\n\nexterndef \t_IPX_Open_Socket95:near\nexterndef \t__IPX_Open_Socket95@4:near\n_IPX_Open_Socket95\tproc near\n\n\t\tjmp\t__IPX_Open_Socket95@4\n\n_IPX_Open_Socket95 endp\n\nexterndef \t_IPX_Close_Socket95:near\nexterndef \t__IPX_Close_Socket95@4:near\n_IPX_Close_Socket95\tproc near\n\n\t\tjmp\t__IPX_Close_Socket95@4\n\n_IPX_Close_Socket95 endp\n\nexterndef \t_IPX_Get_Connection_Number95:near\nexterndef \t__IPX_Get_Connection_Number95@0:near\n_IPX_Get_Connection_Number95\tproc near\n\n\t\tjmp\t__IPX_Get_Connection_Number95@0\n\n_IPX_Get_Connection_Number95 endp\n\nexterndef \t_IPX_Send_Packet95:near\nexterndef \t__IPX_Send_Packet95@20:near\n_IPX_Send_Packet95\tproc near\n\n\t\tjmp\t__IPX_Send_Packet95@20\n\n_IPX_Send_Packet95 endp\n\nexterndef \t_IPX_Broadcast_Packet95:near\nexterndef \t__IPX_Broadcast_Packet95@8:near\n_IPX_Broadcast_Packet95\tproc near\n\n\t\tjmp\t__IPX_Broadcast_Packet95@8\n\n_IPX_Broadcast_Packet95 endp\n\nexterndef \t_IPX_Get_Local_Target95:near\nexterndef \t__IPX_Get_Local_Target95@16:near\n_IPX_Get_Local_Target95\tproc near\n\n\t\tjmp\t__IPX_Get_Local_Target95@16\n\n_IPX_Get_Local_Target95 endp\n\nexterndef \t_IPX_Start_Listening95:near\nexterndef \t__IPX_Start_Listening95@0:near\n_IPX_Start_Listening95\tproc near\n\n\t\tjmp\t__IPX_Start_Listening95@0\n\n_IPX_Start_Listening95 endp\n\nexterndef \t_IPX_Shut_Down95:near\nexterndef \t__IPX_Shut_Down95@0:near\n_IPX_Shut_Down95\tproc near\n\n\t\tjmp\t__IPX_Shut_Down95@0\n\n_IPX_Shut_Down95 endp\n\n\n\nexterndef \t_IPX_Get_Outstanding_Buffer95:near\nexterndef \t__IPX_Get_Outstanding_Buffer95@4:near\n\n_IPX_Get_Outstanding_Buffer95\tproc near\n\n\t\tjmp\t__IPX_Get_Outstanding_Buffer95@4\n\n_IPX_Get_Outstanding_Buffer95 endp\n\n\n\tend\n"
  },
  {
    "path": "IPX/WWIPX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\tpage\t,132\n\n;Thunk Compiler Version 1.8  May 11 1995 13:16:19\n;File Compiled Tue Jan 16 13:53:22 1996\n\n;Command Line: D:\\MSTOOLS\\BIN\\THUNK.EXE wwipx.thk \n\n\tTITLE\t$wwipx.asm\n\n\t.386\n\tOPTION READONLY\n\tOPTION OLDSTRUCTS\n\nIFNDEF IS_16\nIFNDEF IS_32\n%out command line error: specify one of -DIS_16, -DIS_32\n.err\nENDIF  ;IS_32\nENDIF  ;IS_16\n\n\nIFDEF IS_32\nIFDEF IS_16\n%out command line error: you can't specify both -DIS_16 and -DIS_32\n.err\nENDIF ;IS_16\n;************************* START OF 32-BIT CODE *************************\n\n\n\t.model FLAT,STDCALL\n\n\n;-- Import common flat thunk routines (in k32)\n\nexternDef MapHInstLS\t:near32\nexternDef MapHInstLS_PN\t:near32\nexternDef MapHInstSL\t:near32\nexternDef MapHInstSL_PN\t:near32\nexternDef FT_Prolog\t:near32\nexternDef FT_Thunk\t:near32\nexternDef QT_Thunk\t:near32\nexternDef FT_Exit0\t:near32\nexternDef FT_Exit4\t:near32\nexternDef FT_Exit8\t:near32\nexternDef FT_Exit12\t:near32\nexternDef FT_Exit16\t:near32\nexternDef FT_Exit20\t:near32\nexternDef FT_Exit24\t:near32\nexternDef FT_Exit28\t:near32\nexternDef FT_Exit32\t:near32\nexternDef FT_Exit36\t:near32\nexternDef FT_Exit40\t:near32\nexternDef FT_Exit44\t:near32\nexternDef FT_Exit48\t:near32\nexternDef FT_Exit52\t:near32\nexternDef FT_Exit56\t:near32\nexternDef SMapLS\t:near32\nexternDef SUnMapLS\t:near32\nexternDef SMapLS_IP_EBP_8\t:near32\nexternDef SUnMapLS_IP_EBP_8\t:near32\nexternDef SMapLS_IP_EBP_12\t:near32\nexternDef SUnMapLS_IP_EBP_12\t:near32\nexternDef SMapLS_IP_EBP_16\t:near32\nexternDef SUnMapLS_IP_EBP_16\t:near32\nexternDef SMapLS_IP_EBP_20\t:near32\nexternDef SUnMapLS_IP_EBP_20\t:near32\nexternDef SMapLS_IP_EBP_24\t:near32\nexternDef SUnMapLS_IP_EBP_24\t:near32\nexternDef SMapLS_IP_EBP_28\t:near32\nexternDef SUnMapLS_IP_EBP_28\t:near32\nexternDef SMapLS_IP_EBP_32\t:near32\nexternDef SUnMapLS_IP_EBP_32\t:near32\nexternDef SMapLS_IP_EBP_36\t:near32\nexternDef SUnMapLS_IP_EBP_36\t:near32\nexternDef SMapLS_IP_EBP_40\t:near32\nexternDef SUnMapLS_IP_EBP_40\t:near32\n\nMapSL\tPROTO NEAR STDCALL p32:DWORD\n\n\n\n\t.code \n\n;************************* COMMON PER-MODULE ROUTINES *************************\n\n\t.data\n\npublic wwipx_ThunkData32\t;This symbol must be exported.\nwwipx_ThunkData32 label dword\n\tdd\t3130534ch\t;Protocol 'LS01'\n\tdd\t043bh\t;Checksum\n\tdd\t0\t;Jump table address.\n\tdd\t3130424ch\t;'LB01'\n\tdd\t0\t;Flags\n\tdd\t0\t;Reserved (MUST BE 0)\n\tdd\t0\t;Reserved (MUST BE 0)\n\tdd\toffset QT_Thunk_wwipx - offset wwipx_ThunkData32\n\tdd\toffset FT_Prolog_wwipx - offset wwipx_ThunkData32\n\n\n\n\t.code \n\n\nexternDef ThunkConnect32@24:near32\n\npublic wwipx_ThunkConnect32@16\nwwipx_ThunkConnect32@16:\n\tpop\tedx\n\tpush\toffset wwipx_ThkData16\n\tpush\toffset wwipx_ThunkData32\n\tpush\tedx\n\tjmp\tThunkConnect32@24\nwwipx_ThkData16 label byte\n\tdb\t\"wwipx_ThunkData16\",0\n\n\n\t\t\n\n\npfnQT_Thunk_wwipx\tdd offset QT_Thunk_wwipx\npfnFT_Prolog_wwipx\tdd offset FT_Prolog_wwipx\n\t.data\nQT_Thunk_wwipx label byte\n\tdb\t32 dup(0cch)\t;Patch space.\n\nFT_Prolog_wwipx label byte\n\tdb\t32 dup(0cch)\t;Patch space.\n\n\n\t.code \n\n\n\n\n\n;************************ START OF THUNK BODIES************************\n\n\n\n\n;\npublic IPX_Initialise@4\nIPX_Initialise@4:\n\tmov\tcl,0\n; IPX_Initialise(16) = IPX_Initialise(32) {}\n;\n; dword ptr [ebp+8]:  param1\n;\npublic IIIPX_Initialise@4\nIIIPX_Initialise@4:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tpush\tword ptr [ebp+8]\t;param1: dword->word\n\tcall\tdword ptr [pfnQT_Thunk_wwipx]\n\tcwde\n\tleave\n\tretn\t4\n\n\n\n\nELSE\n;************************* START OF 16-BIT CODE *************************\n\n\n\n\n\tOPTION SEGMENT:USE16\n\t.model LARGE,PASCAL\n\n\n\t.code\t\n\n\n\nexternDef IPX_Initialise:far16\n\n\nFT_wwipxTargetTable label word\n\tdw\toffset IPX_Initialise\n\tdw\t   seg IPX_Initialise\n\n\n\n\n\t.data\n\npublic wwipx_ThunkData16\t;This symbol must be exported.\nwwipx_ThunkData16\tdd\t3130534ch\t;Protocol 'LS01'\n\tdd\t043bh\t;Checksum\n\tdw\toffset FT_wwipxTargetTable\n\tdw\tseg    FT_wwipxTargetTable\n\tdd\t0\t;First-time flag.\n\n\n\n\t.code \n\n\nexternDef ThunkConnect16:far16\n\npublic wwipx_ThunkConnect16\nwwipx_ThunkConnect16:\n\tpop\tax\n\tpop\tdx\n\tpush\tseg    wwipx_ThunkData16\n\tpush\toffset wwipx_ThunkData16\n\tpush\tseg    wwipx_ThkData32\n\tpush\toffset wwipx_ThkData32\n\tpush\tcs\n\tpush\tdx\n\tpush\tax\n\tjmp\tThunkConnect16\nwwipx_ThkData32 label byte\n\tdb\t\"wwipx_ThunkData32\",0\n\n\n\n\n\nENDIF\nEND\n"
  },
  {
    "path": "IPX/WWIPX16.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\tpage\t,132\n\n;Thunk Compiler Version 1.8  May 11 1995 13:16:19\n;File Compiled Tue Jan 16 13:14:21 1996\n\n;Command Line: D:\\MSTOOLS\\BIN\\THUNK.EXE wwipx16.thk \n\n\tTITLE\t$wwipx16.asm\n\n\t.386\n\tOPTION READONLY\n\tOPTION OLDSTRUCTS\n\nIFNDEF IS_16\nIFNDEF IS_32\n%out command line error: specify one of -DIS_16, -DIS_32\n.err\nENDIF  ;IS_32\nENDIF  ;IS_16\n\n\nIFDEF IS_32\nIFDEF IS_16\n%out command line error: you can't specify both -DIS_16 and -DIS_32\n.err\nENDIF ;IS_16\n;************************* START OF 32-BIT CODE *************************\n\n\n\t.model FLAT,STDCALL\n\n\n;-- Import common flat thunk routines (in k32)\n\nexternDef MapHInstLS\t:near32\nexternDef MapHInstLS_PN\t:near32\nexternDef MapHInstSL\t:near32\nexternDef MapHInstSL_PN\t:near32\nexternDef FT_Prolog\t:near32\nexternDef FT_Thunk\t:near32\nexternDef QT_Thunk\t:near32\nexternDef FT_Exit0\t:near32\nexternDef FT_Exit4\t:near32\nexternDef FT_Exit8\t:near32\nexternDef FT_Exit12\t:near32\nexternDef FT_Exit16\t:near32\nexternDef FT_Exit20\t:near32\nexternDef FT_Exit24\t:near32\nexternDef FT_Exit28\t:near32\nexternDef FT_Exit32\t:near32\nexternDef FT_Exit36\t:near32\nexternDef FT_Exit40\t:near32\nexternDef FT_Exit44\t:near32\nexternDef FT_Exit48\t:near32\nexternDef FT_Exit52\t:near32\nexternDef FT_Exit56\t:near32\nexternDef SMapLS\t:near32\nexternDef SUnMapLS\t:near32\nexternDef SMapLS_IP_EBP_8\t:near32\nexternDef SUnMapLS_IP_EBP_8\t:near32\nexternDef SMapLS_IP_EBP_12\t:near32\nexternDef SUnMapLS_IP_EBP_12\t:near32\nexternDef SMapLS_IP_EBP_16\t:near32\nexternDef SUnMapLS_IP_EBP_16\t:near32\nexternDef SMapLS_IP_EBP_20\t:near32\nexternDef SUnMapLS_IP_EBP_20\t:near32\nexternDef SMapLS_IP_EBP_24\t:near32\nexternDef SUnMapLS_IP_EBP_24\t:near32\nexternDef SMapLS_IP_EBP_28\t:near32\nexternDef SUnMapLS_IP_EBP_28\t:near32\nexternDef SMapLS_IP_EBP_32\t:near32\nexternDef SUnMapLS_IP_EBP_32\t:near32\nexternDef SMapLS_IP_EBP_36\t:near32\nexternDef SUnMapLS_IP_EBP_36\t:near32\nexternDef SMapLS_IP_EBP_40\t:near32\nexternDef SUnMapLS_IP_EBP_40\t:near32\n\nMapSL\tPROTO NEAR STDCALL p32:DWORD\n\n\n\n\t.code \n\n;************************* COMMON PER-MODULE ROUTINES *************************\n\n\t.data\n\npublic wwipx16_ThunkData32\t;This symbol must be exported.\nwwipx16_ThunkData32 label dword\n\tdd\t3130534ch\t;Protocol 'LS01'\n\tdd\t043bh\t;Checksum\n\tdd\t0\t;Jump table address.\n\tdd\t3130424ch\t;'LB01'\n\tdd\t0\t;Flags\n\tdd\t0\t;Reserved (MUST BE 0)\n\tdd\t0\t;Reserved (MUST BE 0)\n\tdd\toffset QT_Thunk_wwipx16 - offset wwipx16_ThunkData32\n\tdd\toffset FT_Prolog_wwipx16 - offset wwipx16_ThunkData32\n\n\n\n\t.code \n\n\nexternDef ThunkConnect32@24:near32\n\npublic wwipx16_ThunkConnect32@16\nwwipx16_ThunkConnect32@16:\n\tpop\tedx\n\tpush\toffset wwipx16_ThkData16\n\tpush\toffset wwipx16_ThunkData32\n\tpush\tedx\n\tjmp\tThunkConnect32@24\nwwipx16_ThkData16 label byte\n\tdb\t\"wwipx16_ThunkData16\",0\n\n\n\t\t\n\n\npfnQT_Thunk_wwipx16\tdd offset QT_Thunk_wwipx16\npfnFT_Prolog_wwipx16\tdd offset FT_Prolog_wwipx16\n\t.data\nQT_Thunk_wwipx16 label byte\n\tdb\t32 dup(0cch)\t;Patch space.\n\nFT_Prolog_wwipx16 label byte\n\tdb\t32 dup(0cch)\t;Patch space.\n\n\n\t.code \n\n\n\n\n\n;************************ START OF THUNK BODIES************************\n\n\n\n\n;\npublic IPX_Initialise@4\nIPX_Initialise@4:\n\tmov\tcl,0\n; IPX_Initialise(16) = IPX_Initialise(32) {}\n;\n; dword ptr [ebp+8]:  param1\n;\npublic IIIPX_Initialise@4\nIIIPX_Initialise@4:\n\tpush\tebp\n\tmov\tebp,esp\n\tpush\tecx\n\tsub\tesp,60\n\tpush\tword ptr [ebp+8]\t;param1: dword->word\n\tcall\tdword ptr [pfnQT_Thunk_wwipx16]\n\tcwde\n\tleave\n\tretn\t4\n\n\n\n\nELSE\n;************************* START OF 16-BIT CODE *************************\n\n\n\n\n\tOPTION SEGMENT:USE16\n\t.model LARGE,PASCAL\n\n\n\t.code\t\n\n\n\nexternDef IPX_Initialise:far16\n\n\nFT_wwipx16TargetTable label word\n\tdw\toffset IPX_Initialise\n\tdw\t   seg IPX_Initialise\n\n\n\n\n\t.data\n\npublic wwipx16_ThunkData16\t;This symbol must be exported.\nwwipx16_ThunkData16\tdd\t3130534ch\t;Protocol 'LS01'\n\tdd\t043bh\t;Checksum\n\tdw\toffset FT_wwipx16TargetTable\n\tdw\tseg    FT_wwipx16TargetTable\n\tdd\t0\t;First-time flag.\n\n\n\n\t.code \n\n\nexternDef ThunkConnect16:far16\n\npublic wwipx16_ThunkConnect16\nwwipx16_ThunkConnect16:\n\tpop\tax\n\tpop\tdx\n\tpush\tseg    wwipx16_ThunkData16\n\tpush\toffset wwipx16_ThunkData16\n\tpush\tseg    wwipx16_ThkData32\n\tpush\toffset wwipx16_ThkData32\n\tpush\tcs\n\tpush\tdx\n\tpush\tax\n\tjmp\tThunkConnect16\nwwipx16_ThkData32 label byte\n\tdb\t\"wwipx16_ThunkData32\",0\n\n\n\n\n\nENDIF\nEND\n"
  },
  {
    "path": "LAUNCH/LAUNCH.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***********************************************************************************************\n;***             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               ***\n;***********************************************************************************************\n;*                                                                                             *\n;*                 Project Name : Command & Conquer -- launcher program                        *\n;*                                                                                             *\n;*                    File Name : launch.asm                                                   *\n;*                                                                                             *\n;*                   Programmer : Steve Tall                                                   *\n;*                                                                                             *\n;*                   Start Date : August 19, 1995                                              *\n;*                                                                                             *\n;*                  Last Update : Modified for RA, October 14th, 1996 [ST]                     *\n;*                                                                                             *\n;*                        Build : Compile and link with MASM 6                                 *\n;*                                Note that masm will complain there is no stack because       *\n;*                                we are not using a simplified segment model                  *\n;*                                                                                             *\n;*---------------------------------------------------------------------------------------------*\n;* Functions:                                                                                  *\n;*  Start -- Program entry point                                                               *\n;*  Mem_Error -- report an out of memory error (not a function)                                *\n;*  Disc_Error -- report an out of disk space error (not a function)                           *\n;*  Delete_Swaps -- Deletes old swap files from the game directory                             *\n;*  Setup_Environment -- Adds environment strings required for DOS4G professional              *\n;*                                                                                             *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\n\n\n\t\tTITLE\t\"Red Alert launcher\"\n\n\t\t.386\n\n\n;----------------------------------------------------------------------------------------------\n; Defines for DOS system functions.\n;\nDOS_LOAD_AND_EXEC\t=4B00H\nDOS_ALLOC\t\t=48H\nDOS_FREE\t\t=49h\nDOS_GET_FREE_DISC_SPACE\t=36H\nDOS_SET_DIRECTORY\t=3BH\nDOS\t\t\t=21H\nDOS_SET_DTA\t\t=1AH\nDOS_FIND_FIRST\t\t=4EH\nDOS_FIND_NEXT\t\t=4FH\nDOS_DELETE_FILE\t\t=41H\nDOS_SET_ATTRIBUTES\t=43H\nDOS_SET_DRIVE\t\t=0EH\nDOS_RESIZE_ALLOCATION\t=4Ah\nDOS_EXIT\t\t=4ch\nDOS_PRINT_STRING\t=9\n\n\n;----------------------------------------------------------------------------------------------\n; Defines for keyboard BIOS functions\n;\nKEYBOARD_BIOS\t\t=16h\nBIOS_CHECK_KEYBOARD\t=11h\nBIOS_GET_KEYSTROKE\t=10h\n\n\n;----------------------------------------------------------------------------------------------\n; Defines for video bios functions\n;\nVIDEO_BIOS\t\t=10h\nBIOS_SET_VIDEO_MODE_3\t=0003h\n\n\n;----------------------------------------------------------------------------------------------\n; Misc defines\n;\nMEM_REQUIRED\t\t=1024 * 400\t;Check for 400k low memory\nINIT_FREE_DISK_SPACE\t=15*1024*1024\t;C&C requirement for disc space\n\nMY_ALLOCATION\t\t=1536/16\t;only allow myself 1.5k to run in incl. psp and stack\n\t\t\t\t\t;you can find out how much space the program needs\n\t\t\t\t\t;by running WDISASM LAUNCH.OBJ\n\t\t\t\t\t;dont forget to add 256 bytes on for the psp\n\n\n\t\tinclude <pcmacro.16>\n\n\n;----------------------------------------------------------------------------------------------\n; Simplified segment models are for wimmin\n;\n; We want 32 bit instructions in a 16 bit segment\n;\n\n_code segment para public use16 'code'\n\n\t\tassume\tds:_data\n\t\tassume\tes:_data\n\t\tassume\tss:_data\n\t\tassume\tcs:_code\n\n\n\n;*************************************************************************************************\n;* Start -- Program entry point                                                                  *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tnothing                                                                          *\n;*                                                                                               *\n;* OUTPUT:      DOS return code from spawning the game                                           *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   08/19/95 ST: Created.                                                                       *\n;*===============================================================================================*\n\nStart:\t\t;\n\t\t; Set up the segments and the stack pointer\n\t\t;\n\t\tcli\n\t\tmov\tax,_data\n\t\tmov\tds,ax\n\t\tmov\t[Psp],es\n\t\tmov\tss,ax\n\t\tmov\tsp,offset MyStack\n\t\tsti\n\n\t\t;\n\t\t; Modify the starting memory allocation to free enough for the game proper\n\t\t;\n\t\tsave\tax\n\t\tmov\tbx,MY_ALLOCATION\n\t\tmov\tah,DOS_RESIZE_ALLOCATION\n\t\tint\tDOS\n\t\trestore\tax\n\t\tbcs\tMem_Error\n\n\t\t;\n\t\t; See if we have enough free memory to launch\n\t\t;\n\t\tmov\tah,DOS_ALLOC\n\t\tmov\tbx,-1\t\t;I want it all! hahaha\n\t\tint\tDOS\n\t\tjnc\tMem_Error\t;shouldnt ever succeed but...\n\t\tcmp\tax,8\n\t\tjnz\tMem_Error\n\t\tcmp\tbx,(MEM_REQUIRED/16)-MY_ALLOCATION\n\t\tbls\tMem_Error\t;oh dear\n\n\t\t;\n\t\t; See if there is enough free disc space to launch\n\t\t;\n\t\txor\tdl,dl\n\t\tmov\tah,DOS_GET_FREE_DISC_SPACE\n\t\tint\tDOS\n\n\t\t; dos get free disc space returns with the following\n\t\t; ax - sectors per cluster\n\t\t; bx - number of available clusters\n\t\t; cx - bytes per sector\n\t\t; dx - cluster on the drive\n\n\t\tmul\tbx\t;clusters avail*sectors per cluster\n\t\tshl\tedx,16\n\t\tmov\tdx,ax\n\t\tmov\teax,edx\n\t\tand\tecx,65535\n\t\tmul\tecx\t;*bytes per sector\n\t\tcmp\teax,INIT_FREE_DISK_SPACE\n\t\tblo\tDisc_Error\n\n\t\t;\n\t\t; Get the directory we were run from and cd to it\n\t\t;\n\t\tmov\tes,[Psp]\n\t\tmov\tbx,2ch\n\t\tmov\tes,es:[bx]\t;es points to env\n\t\txor\tdi,di\n\t\txor\tal,al\n\t\tmov\tcx,-1\n\n\t\t;\n\t\t; Search for 0,0 as that aways terminates the environment block\n\t\t;\n@@again:\trepnz\tscasb\n\t\tcmp_b\tes:[di],al\n\t\tjnz\t@@again\n\t\tlea\tsi,[di+3]\t;skip length word and second zero\n\n\t\t;\n\t\t; Copy the directory name to temporary workspace\n\t\t;\n\t\tmov\tdi,si\n\t\tmov\tcx,-1\n\t\trepnz\tscasb\n\t\tneg\tcx\n\t\tmov\tbx,cx\n\t\tmov\tcx,-1\n\t\tstd\n\t\tmov\tal,'\\'\n\t\trepnz\tscasb\n\t\tneg\tcx\n\t\tsub\tbx,cx\n\t\tmov\tcx,bx\n\t\tinc\tcx\n\t\tcld\n\n\t\tmov\tdi,offset Dta\n\t\tpush\tds\n\t\tmov\tax,es\n\t\tmov\tbx,ds\n\t\tmov\tes,bx\n\t\tmov\tds,ax\n\t\trep\tmovsb\n\t\txor\tal,al\n\t\tstosb\n\t\tpop\tds\n\n\t\t;\n\t\t; Actually set the drive and path\n\t\t;\n\t\tmov\tdl,[Dta]\n\t\tsub\tdl,'A'\n\t\tmov\tah,DOS_SET_DRIVE\n\t\tint\tDOS\n\n\t\tmov\tdx,offset Dta\n\t\tmov\tah,DOS_SET_DIRECTORY\n\t\tint\tDOS\n\n\t\t;\n\t\t; Delete all the old swap files\n\t\t;\n\t\tmov\tdx,offset Dta\n\t\tmov\tah,DOS_SET_DTA\n\t\tint\tDOS\n\t\tcall\tDelete_Swaps\n\n\t\t;\n\t\t; Add in the environment strings required for DOS4G professional\n\t\t;\n\t\tcall\tSetup_Environment\n\n\t\t;\n\t\t; Set up the parameters to launch c&c\n\t\t;\n\t\tmov\tes,[Psp]\n\t\tmov\tdx,offset GameName\n\t\tmov\tbx,offset GameParameterBlock\n\n\t\tmov\tax,[EnvironmentSegment]\t\t;Initialised by Setup_Environment\n\t\tmov_w\t[bx],ax\t\t;ptr to environment\n\n\t\t;\n\t\t; just pass the command tail we got straight through\n\t\t;\n\t\tmov\tax,80h\n\t\tmov\t[bx+2],ax\t;offset of command tail\n\t\tmov\tax,[Psp]\n\t\tmov\t[bx+4],ax\t;segment of command tail\n\n\t\tmov\tes,ax\n\t\tmov\tax,es:[2ch]\n\t\tmov\t[bx+8],ax\t;segment of first fcb\n\t\tmov\t[bx+12],ax\t;segment of second fcb\n\n\t\tmov\tax,_data\n\t\tmov\tes,ax\n\n\t\t;\n\t\t; Run the main game program\n\t\t;\n\t\tmov\tax,DOS_LOAD_AND_EXEC\t;load and execute program\n\t\tint\tDOS\n\n\n\t\t;\n\t\t; Restore teh environment memory\n\t\t;\n\t\tmov\tax,[EnvironmentSegment]\n\t\ttest\tax,ax\n\t\tjz\t@@no_free\n\t\tmov\tes,ax\n\t\tmov\tah,DOS_FREE\n\t\tint\tDOS\n\n\n@@no_free:\t;\n\t\t; Quit to DOS\n\t\t;\n\t\tmov\tah,DOS_EXIT\n\t\tint\tDOS\n\n\n\n\n;*************************************************************************************************\n;* Mem_Error -- Print a memory error message and quit                                            *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tnothing                                                                          *\n;*                                                                                               *\n;* OUTPUT:      undefined                                                                        *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   08/19/95 ST: Created.                                                                       *\n;*===============================================================================================*\nMem_Error:\tmov\tax,BIOS_SET_VIDEO_MODE_3\n\t\tint\tVIDEO_BIOS\n\t\tmov\tdx,offset MemErrorTxt\n\t\tmov\tah,DOS_PRINT_STRING\n\t\tint\tDOS\n\n\t\tmov\tdx,offset MoreInfoTxt\nError_In:\tmov\tah,DOS_PRINT_STRING\n\t\tint\tDOS\n\n\t\t;\n\t\t; wait for keypress\n\t\t;\n\nnochar:\t\tmov\tah,BIOS_CHECK_KEYBOARD\n\t\tint\tKEYBOARD_BIOS\n\t\tbeq\tnochar\n\n\t\t;\n\t\t; get the ket out of the buffer\n\t\t;\n\t\tmov\tah,BIOS_GET_KEYSTROKE\n\t\tint\tKEYBOARD_BIOS\n\n\t\t;\n\t\t; Quit to DOS\n\t\t;\n\t\tmov\tah,DOS_EXIT\n\t\tint\tDOS\n\n\n\n\n\n\n;*************************************************************************************************\n;* Disc_Error -- Prints a disk error message and exits                                           *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tnothing                                                                          *\n;*                                                                                               *\n;* OUTPUT:      DOS return code from spawning the game                                           *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   08/19/95 ST: Created.                                                                       *\n;*===============================================================================================*\nDisc_Error:\tmov\tax,BIOS_SET_VIDEO_MODE_3\n\t\tint\tVIDEO_BIOS\n\t\tmov\tdx,offset DiscErrorTxt\n\t\tjmp\tError_In\n\n\n\n\n\n\n\n;*************************************************************************************************\n;* Setup_Environment -- Create a new environment block with the set DOS4GVM= stuff               *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tnothing                                                                          *\n;*                                                                                               *\n;* OUTPUT:      nothing                                                                          *\n;*                                                                                               *\n;* Note: Modifies the global variable 'EnvironmentStrings' to point to the start of our new      *\n;*       environment block. This memory will need to be freed later.                             *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   10/14/96 ST: Created.                                                                       *\n;*===============================================================================================*\nSetup_Environment proc near\n\n\t\t;\n\t\t; Point to default environment.\n\t\t;\n\t\tmov\t[EnvironmentSegment],0\n\n\t\t;\n\t\t; Get the address of our environment block into es\n\t\t;\n\t\tmov\tes,[Psp]\n\t\tmov\tbx,2ch\n\t\tmov\tes,es:[bx]\t;es points to env\n\n\t\t;\n\t\t; Search for the end of the block to get its length\n\t\t;\n\t\txor\tdi,di\n\t\txor\tal,al\n\t\tmov\tcx,-1\n\n@@search:\trepnz\tscasb\n\t\tcmp_b\tes:[di],al\n\t\tjnz\t@@search\n\n\t\t;\n\t\t; di is length of environment block\n\t\t;\n\t\tlea\tbx,[di+256]\t; a little extra to be sure.\n\n\t\t;\n\t\t; Allocate memory for a copy of the environment.\n\t\t;\n\t\tpush\tdi\n\t\tmov\tah,DOS_ALLOC\n\t\tshr\tbx,4\t\t;needs to be number of paragraphs\n\t\tint\tDOS\n\t\tjnc\t@@ok\n\n\t\t;\n\t\t; Oops. Not enough memory. We are screwed so just exit.\n\t\t;\n\t\tpop\tdi\n\t\tjmp\t@@out\n\n@@ok:           ;\n\t\t; Save the pointer to our new environment\n\t\t; We can also use this to free the memory later\n\t\t;\n\t\tmov\t[EnvironmentSegment],ax\n\n\t\t;\n\t\t; Copy the original environment to the newly alloced memory\n\t\t;\n\t\tmov\tes,ax\n\t\tpop\tcx\t\t; size to copy\n\n\t\tpush\tds\n\t\tmov\tds,[Psp]\n\t\tmov\tbx,2ch\n\t\tmov\tds,ds:[bx]\t;ds points to original environment\n\n\t\txor\tsi,si\n\t\txor\tdi,di\n\t\trep\tmovsb\n\t\tpop\tds\n\n\t\tmov\tsi,offset Dos4gEnvironment\n\n@@copy_loop:\tlodsb\n\t\tstosb\n\t\ttest\tal,al\n\t\tjnz\t@@copy_loop\n\n\t\t;\n\t\t; Copy the final zero. The environment must be terminated by 2 zeros.\n\t\t;\n\t\tmovsb\n\n@@out:\t\tret\n\nSetup_Environment endp\n\n\n\n\n\n;*************************************************************************************************\n;* Delete_Swaps -- Delete any swap files left over from a previous game                          *\n;*                                                                                               *\n;*                                                                                               *\n;* INPUT:\tnothing                                                                          *\n;*                                                                                               *\n;* OUTPUT:      nothing                                                                          *\n;*                                                                                               *\n;* HISTORY:                                                                                      *\n;*   08/19/95 ST: Created.                                                                       *\n;*===============================================================================================*\nDelete_Swaps proc near\n\n\t\t;\n\t\t; Use 'Find first/next' to find the swap files\n\t\t;\n\t\tmov\tdx,offset SwapName\n\t\tmov\tcx,7\t;attributes\n\t\tmov\tah,DOS_FIND_FIRST\n\t\tint\tDOS\n\t\tbcs\t@@out\t\t;no matching files\n\n\t\t;\n\t\t; Make sure it isn't read only\n\t\t;\n@@loop:\t\tmov\tdx,offset Dta+1eh\n\t\tmov\tah,DOS_SET_ATTRIBUTES\n\t\tmov\tal,1\n\t\txor\tcx,cx\t\t;attributes\n\t\tint\tDOS\n\n\t\t;\n\t\t; Delete the file\n\t\t;\n\t\tmov\tdx,offset Dta+1eh\n\t\tmov\tah,DOS_DELETE_FILE\n\t\tint\tDOS\n\n\t\t;\n\t\t; Find the next one\n\t\t;\n\t\tmov\tah,DOS_FIND_NEXT\n\t\tint\tDOS\n\t\tbcc\t@@loop\n\n@@out:\t\tret\n\nDelete_Swaps endp\n\n\n\n\n\n_code ends\t;end of code segment\n\n\n\n\n\n\n\n\n\n;----------------------------------------------------------------------------------------------\n;\n; Complex data segment\n;\n;\n\n_data segment dword public use16 'data'\n\n\nEnvironmentSegment\tdw\t0\t\t;ptr to environment to pass to child process\nPsp\t\t\tdw\t0\t\t;segment addr of program segment prefix\nGameParameterBlock\tdb\t16h dup (0)\t;required parameters for DOS launch\n\nGameName\tdb\t\"GAME.DAT\",0\t;this is the name of the app to be spawned\nSwapName\tdb\t\"*.SWP\",0\t;swap files always have a .SWP extension\n\n;\n; Environment to be set for DOS4G professional\n;\nDos4gEnvironment db\t\"DOS4GVM=SwapMin:12M,SwapInc:0\",0,0\n\n;\n; Error and warning messages\n;\nMemErrorTxt\tdb\t\"Warning - There is very little free conventional DOS memory in the system.\",13,10,\"$\"\n\nDiscErrorTxt\tdb\t\"Error - insufficient disk space to run Red Alert.\"\n\t\tdb\t13,10,\"Red Alert requires 15,728,640 bytes of free disk space.\",13,10\t;this string will\n\t\t\t\t\t\t\t\t\t\t\t;run into the next because\n\t\t\t\t\t\t\t\t\t\t\t;there is no '$'\nMoreInfoTxt\tdb\t\"Please read the Red Alert manual for more information.\",13,10,13,10\n\t\tdb\t\"Press a key to continue.\",13,10,\"$\"\n\n\nDta\t\tdb\t128 dup (0)\t;enough for complete path\n\n\n;*************************************************************\n;\n; The stack\n;\n\nStackSpace\tdb\t256 dup (0)\t;256 byte stack!\nMyStack \tlabel \tbyte\t\t;The stack starts here and grows down.\n\nEndCode\t\tlabel\tbyte\t\t;The end of the data segment\n\n\n_data ends\n\nend Start\n"
  },
  {
    "path": "LAUNCH/PCMACRO.16",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;$e:\\ifil\\pcmacro.inc\n;- 16-5-1991 at 10:55:13 by mike\n;- 16-5-1991 at 08:30:30 by mike\n;- 3-5-1991 at 15:39:52 by mike\n\n\n\tSUBTTL PCMACRO.INC\n\t.xlist\n\n\n\n\n\n\nsaveall\tmacro\n\tsave\tax,bx,cx,dx,bp,si,di,es,ds\n\tendm\n\nrestall\tmacro\n\trestore\tax,bx,cx,dx,bp,si,di,es,ds\n\tendm\n\nsave\tmacro\tr0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14\n\tIFNB\t<r0>\n\tpush\tr0\n\tsave\tr1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14\n\tENDIF\n\tendm\n\nrestore\tmacro\tr0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14\n\tIFNB\t<r14>\n\tpop\tr14\n\tENDIF\n\tIFNB\t<r13>\n\tpop\tr13\n\tENDIF\n\tIFNB\t<r12>\n\tpop\tr12\n\tENDIF\n\tIFNB\t<r11>\n\tpop\tr11\n\tENDIF\n\tIFNB\t<r10>\n\tpop\tr10\n\tENDIF\n\tIFNB\t<r9>\n\tpop\tr9\n\tENDIF\n\tIFNB\t<r8>\n\tpop\tr8\n\tENDIF\n\tIFNB\t<r7>\n\tpop\tr7\n\tENDIF\n\tIFNB\t<r6>\n\tpop\tr6\n\tENDIF\n\tIFNB\t<r5>\n\tpop\tr5\n\tENDIF\n\tIFNB\t<r4>\n\tpop\tr4\n\tENDIF\n\tIFNB\t<r3>\n\tpop\tr3\n\tENDIF\n\tIFNB\t<r2>\n\tpop\tr2\n\tENDIF\n\tIFNB\t<r1>\n\tpop\tr1\n\tENDIF\n\tIFNB\t<r0>\n\tpop\tr0\n\tENDIF\n\tendm\n\nbhi\tmacro\tlab\n\tja\tlab\n\tendm\n\nbls\tmacro\tlab\n\tjbe\tlab\n\tendm\n\nbcc\tmacro\tlab\n\tjnc\tlab\n\tendm\n\nbcs\tmacro\tlab\n\tjc\tlab\n\tendm\n\nbhs\tmacro\tlab\n\tjnc\tlab\n\tendm\n\nblo\tmacro\tlab\n\tjc\tlab\n\tendm\n\nbne\tmacro\tlab\n\tjne\tlab\n\tendm\n\nbeq\tmacro\tlab\n\tje\tlab\n\tendm\n\nbpl\tmacro\tlab\n\tjns\tlab\n\tendm\n\nbmi\tmacro\tlab\n\tjs\tlab\n\tendm\n\nbge\tmacro\tlab\n\tjge\tlab\n\tendm\n\nblt\tmacro\tlab\n\tjl\tlab\n\tendm\n\nbgt\tmacro\tlab\n\tjg\tlab\n\tendm\n\nble\tmacro\tlab\n\tjle\tlab\n\tendm\n\nbra\tmacro\tlab\n\tjmp\tlab\n\tendm\n\n\nbhis\tmacro\tlab\n\tja\tlab\n\tendm\n\nblss\tmacro\tlab\n\tjbe\tlab\n\tendm\n\nbccs\tmacro\tlab\n\tjnc\tlab\n\tendm\n\nbcss\tmacro\tlab\n\tjc\tlab\n\tendm\n\nbnes\tmacro\tlab\n\tjne\tlab\n\tendm\n\nbeqs\tmacro\tlab\n\tje\tlab\n\tendm\n\nbpls\tmacro\tlab\n\tjns\tlab\n\tendm\n\nbmis\tmacro\tlab\n\tjs\tlab\n\tendm\n\nbges\tmacro\tlab\n\tjge\tlab\n\tendm\n\nblts\tmacro\tlab\n\tjl\tlab\n\tendm\n\nbgts\tmacro\tlab\n\tjg\tlab\n\tendm\n\nbles\tmacro\tlab\n\tjle\tlab\n\tendm\n\nbras\tmacro\tlab\n\tjmp\tlab\n\tendm\n\n\ntstb\tmacro\te1\n\n\tIFIDN <e1>,<al>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<bp>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<ah>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<bl>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<bh>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<cl>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<ch>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<dl>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<dh>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tcmp\tBYTE PTR e1,0\n\tendm\n\n\ntstw\tmacro\te1\n\tIFIDN\t<e1>,<ax>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<bx>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<cx>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<dx>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tIFIDN\t<e1>,<bp>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tIFIDN\t<e1>,<si>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tIFIDN\t<e1>,<di>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tcmp\tWORD PTR e1,0\n\tendm\n\n\n\ntst\tmacro\te1\n\tIFIDN\t<e1>,<ax>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<bx>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<cx>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<dx>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tIFIDN\t<e1>,<bp>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tIFIDN\t<e1>,<si>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tIFIDN\t<e1>,<di>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tIFIDN\t<e1>,<al>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<bl>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<cl>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<dl>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tIFIDN\t<e1>,<ah>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<bh>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<ch>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\tIFIDN\t<e1>,<dh>\n\tor\te1,e1\n\tEXITM\n\tENDIF\n\n\tcmp\te1,0\n\tendm\n\n\nclear\tmacro\tfirst\n\txor\tfirst,first\n\tendm\n\nrts\tmacro\n\tret\n\tendm\n\n\nbclrb\tmacro\te1,e2\n\tbtstb\te1,e2\n\tpushf\n\n\tbclrb_sub\te1,e2\n\tpopf\n\tendm\n\nbclrb_sub macro e1,e2\n\tIFIDN <e1>,<al>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<bp>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<ah>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<bl>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<bh>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<cl>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<ch>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<dl>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tIFIDN <e1>,<dh>\n\tand\te1,NOT ( 1 SHL e2 )\n\tEXITM\n\tENDIF\n\tand\tBYTE PTR e1,NOT ( 1 SHL e2 )\n\tendm\n\n\n\nbsetb\tmacro\te1,e2\n\tbtstb\te1,e2\n\tpushf\n\tor\tBYTE PTR e1,1 SHL e2\n\tpopf\n\tendm\n\n\nbchgb\tmacro\te1,e2\n\tbtstb\te1,e2\n\tpushf\n\txor\tBYTE PTR e1,1 SHL e2\n\tpopf\n\tendm\n\n\n\nmov_b\tmacro\tlabel,label2\n\tmov\tbyte ptr label,byte ptr label2\n\tendm\n\n\n\nmov_w\tmacro\tlabel,label2\n\tmov\tword ptr label,word ptr label2\n\tendm\n\n\n\nmov_d\tmacro\tlabel,label2\n\tmov\tdword ptr label,dword ptr label2\n\tendm\n\n\ncmp_b\tmacro\tlabel,label2\n\tcmp\tbyte ptr label,byte ptr label2\n\tendm\n\ncmp_w\tmacro\tlabel,label2\n\tcmp\tword ptr label,word ptr label2\n\tendm\n\ncmp_d\tmacro\tlabel,label2\n\tcmp\tdword ptr label,dword ptr label2\n\tendm\n\n\n\nadd_b\tmacro\tlabel,label2\n\tadd\tbyte ptr label,byte ptr label2\n\tendm\n\nadd_w\tmacro\tlabel,label2\n\tadd\tword ptr label,word ptr label2\n\tendm\n\nadd_d\tmacro\tlabel,label2\n\tadd\tdword ptr label,dword ptr label2\n\tendm\n\n\n\nsub_b\tmacro\tlabel,label2\n\tsub\tbyte ptr label,byte ptr label2\n\tendm\n\nsub_w\tmacro\tlabel,label2\n\tsub\tword ptr label,word ptr label2\n\tendm\n\nsub_d\tmacro\tlabel,label2\n\tsub\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\n\nor_b\tmacro\tlabel,label2\n\tor\tbyte ptr label,byte ptr label2\n\tendm\n\nor_w\tmacro\tlabel,label2\n\tor\tword ptr label,word ptr label2\n\tendm\n\nor_d\tmacro\tlabel,label2\n\tor\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\n\n\n\nxor_b\tmacro\tlabel,label2\n\txor\tbyte ptr label,byte ptr label2\n\tendm\n\nxor_w\tmacro\tlabel,label2\n\txor\tword ptr label,word ptr label2\n\tendm\n\nxor_d\tmacro\tlabel,label2\n\txor\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\n\n\n\n\neor_b\tmacro\tlabel,label2\n\txor\tbyte ptr label,byte ptr label2\n\tendm\n\neor_w\tmacro\tlabel,label2\n\txor\tword ptr label,word ptr label2\n\tendm\n\neor_d\tmacro\tlabel,label2\n\txor\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\nand_b\tmacro\tlabel,label2\n\tand\tbyte ptr label,byte ptr label2\n\tendm\n\nand_w\tmacro\tlabel,label2\n\tand\tword ptr label,word ptr label2\n\tendm\n\nand_d\tmacro\tlabel,label2\n\tand\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\n\ntest_b\tmacro\tlabel,label2\n\ttest\tbyte ptr label,byte ptr label2\n\tendm\n\ntest_w\tmacro\tlabel,label2\n\ttest\tword ptr label,word ptr label2\n\tendm\n\ntest_d\tmacro\tlabel,label2\n\ttest\tdword ptr label,dword ptr label2\n\tendm\n\n\n\n\n\n\n\nshr_b\tmacro\tlabel,label2\n\tshr\tbyte ptr label,label2\n\tendm\n\nshr_w\tmacro\tlabel,label2\n\tshr\tword ptr label,label2\n\tendm\n\nshr_d\tmacro\tlabel,label2\n\tshr\tdword ptr label,label2\n\tendm\n\n\n\nshl_b\tmacro\tlabel,label2\n\tshl\tbyte ptr label,label2\n\tendm\n\nshl_w\tmacro\tlabel,label2\n\tshl\tword ptr label,label2\n\tendm\n\nshl_d\tmacro\tlabel,label2\n\tshl\tdword ptr label,label2\n\tendm\n\n\n\n\nsar_b\tmacro\tlabel,label2\n\tsar\tbyte ptr label,label2\n\tendm\n\nsar_w\tmacro\tlabel,label2\n\tsar\tword ptr label,label2\n\tendm\n\nsar_d\tmacro\tlabel,label2\n\tsar\tdword ptr label,label2\n\tendm\n\n\n\n\n\nsal_b\tmacro\tlabel,label2\n\tsal\tbyte ptr label,label2\n\tendm\n\nsal_w\tmacro\tlabel,label2\n\tsal\tword ptr label,label2\n\tendm\n\nsal_d\tmacro\tlabel,label2\n\tsal\tdword ptr label,label2\n\tendm\n\n\n\ninc_b\tmacro\tlabel\n\tinc\tbyte ptr label\n\tendm\n\ninc_w\tmacro\tlabel\n\tinc\tword ptr label\n\tendm\n\ninc_d\tmacro\tlabel\n\tinc\tdword ptr label\n\tendm\n\n\n\n\ndec_b\tmacro\tlabel\n\tdec\tbyte ptr label\n\tendm\n\ndec_w\tmacro\tlabel\n\tdec\tword ptr label\n\tendm\n\ndec_d\tmacro\tlabel\n\tdec\tdword ptr label\n\tendm\n\n\n\n\n\nmovzx_b\tmacro\tlabel,label2\n\tmovzx\tlabel,byte ptr label2\n\tendm\n\n\nmovzx_w\tmacro\tlabel,label2\n\tmovzx\tlabel,word ptr label2\n\tendm\n\n\nmovsx_b\tmacro\tlabel,label2\n\tmovsx\tlabel,byte ptr label2\n\tendm\n\n\nmovsx_w\tmacro\tlabel,label2\n\tmovsx\tlabel,word ptr label2\n\tendm\n\n\n\n\nmul_b\tmacro\tlabel\n\tmul\tbyte ptr label\n\tendm\n\n\nmul_w\tmacro\tlabel\n\tmul\tword ptr label\n\tendm\n\n\ndiv_b\tmacro\tlabel\n\tdiv\tbyte ptr label\n\tendm\n\n\ndiv_w\tmacro\tlabel\n\tdiv\tword ptr label\n\tendm\n\n\nidiv_b\tmacro\tlabel\n\tidiv\tbyte ptr label\n\tendm\n\n\nidiv_w\tmacro\tlabel\n\tidiv\tword ptr label\n\tendm\n\n\n\n\ntst_b\tmacro\tlabel\n\tcmp\tbyte ptr label,0\n\tendm\n\ntst_w\tmacro\tlabel\n\tcmp\tword ptr label,0\n\tendm\n\ntst_d\tmacro\tlabel\n\tcmp\tdword ptr label,0\n\tendm\n\n\n\n\n\n\n\nnot_b\tmacro\tlabel\n\tnot\tbyte ptr label\n\tendm\n\nnot_w\tmacro\tlabel\n\tnot\tword ptr label\n\tendm\n\nnot_d\tmacro\tlabel\n\tnot\tdword ptr label\n\tendm\n\n\n\n\nneg_b\tmacro\tlabel\n\tneg\tbyte ptr label\n\tendm\n\nneg_w\tmacro\tlabel\n\tneg\tword ptr label\n\tendm\n\nneg_d\tmacro\tlabel\n\tneg\tdword ptr label\n\tendm\n\n\n\n\n\n  \t.list\n\n\n"
  },
  {
    "path": "LAUNCHER/256BMP.C",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include <windows.h>\n#include <windowsx.h>\n#include <alloc.h>\n\nDWORD GetDibInfoHeaderSize (BYTE huge *);\nWORD GetDibWidth (BYTE huge *);\nWORD GetDibHeight (BYTE huge *);\nBYTE huge * GetDibBitsAddr (BYTE huge *);\nBYTE huge * ReadDib(char *);\n\n//-------------------------------------------------------------//\n\nDWORD GetDibInfoHeaderSize (BYTE huge * lpDib)\n{\n\treturn ((BITMAPINFOHEADER huge *) lpDib)->biSize ;\n}\n\nWORD GetDibWidth (BYTE huge * lpDib)\n{\n\tif (GetDibInfoHeaderSize (lpDib) == sizeof (BITMAPCOREHEADER))\n\t\treturn (WORD) (((BITMAPCOREHEADER huge *) lpDib)->bcWidth) ;\n\telse\n\t\treturn (WORD) (((BITMAPINFOHEADER huge *) lpDib)->biWidth) ;\n}\n\nWORD GetDibHeight (BYTE huge * lpDib)\n{\n\tif (GetDibInfoHeaderSize (lpDib) == sizeof (BITMAPCOREHEADER))\n\t\treturn (WORD) (((BITMAPCOREHEADER huge *) lpDib)->bcHeight) ;\n\telse\n\t\treturn (WORD) (((BITMAPINFOHEADER huge *) lpDib)->biHeight) ;\n}\n\nBYTE huge * GetDibBitsAddr (BYTE huge * lpDib)\n{\n\tDWORD dwNumColors, dwColorTableSize ;\n\tWORD  wBitCount ;\n\n\tif (GetDibInfoHeaderSize (lpDib) == sizeof (BITMAPCOREHEADER))\n\t{\n\t\twBitCount = ((BITMAPCOREHEADER huge *) lpDib)->bcBitCount ;\n\n\t\tif (wBitCount != 24)\n\t\t\tdwNumColors = 1L << wBitCount ;\n\t\telse\n\t\t\tdwNumColors = 0 ;\n\n\t\tdwColorTableSize = dwNumColors * sizeof (RGBTRIPLE) ;\n\t}\n\telse\n\t{\n\t\twBitCount = ((BITMAPINFOHEADER huge *) lpDib)->biBitCount ;\n\n\t\tif (GetDibInfoHeaderSize (lpDib) >= 36)\n\t\t\tdwNumColors = ((BITMAPINFOHEADER huge *) lpDib)->biClrUsed ;\n\t\telse\n\t\t\tdwNumColors = 0 ;\n\n\t\tif (dwNumColors == 0)\n\t\t{\n\t\t\tif (wBitCount != 24)\n\t\t\t\tdwNumColors = 1L << wBitCount ;\n\t\t\telse\n\t\t\t\tdwNumColors = 0 ;\n\t\t}\n\n\t\tdwColorTableSize = dwNumColors * sizeof (RGBQUAD) ;\n\t}\n\n\treturn lpDib + GetDibInfoHeaderSize (lpDib) + dwColorTableSize ;\n}\n\n// Read a DIB from a file into memory\nBYTE huge * ReadDib (char * szFileName)\n{\n\tBITMAPFILEHEADER bmfh ;\n\tBYTE huge *      lpDib ;\n\tDWORD            dwDibSize, dwOffset, dwHeaderSize ;\n\tint              hFile ;\n\tWORD             wDibRead ;\n\n\tif (-1 == (hFile = _lopen (szFileName, OF_READ | OF_SHARE_DENY_WRITE)))\n\t\treturn NULL ;\n\n\tif (_lread (hFile, (LPSTR) &bmfh, sizeof (BITMAPFILEHEADER)) !=\n\t\t\t\t\t\t\t\t\t   sizeof (BITMAPFILEHEADER))\n\t{\n\t\t_lclose (hFile) ;\n\t\treturn NULL ;\n\t}\n\n\tif (bmfh.bfType != * (WORD *) \"BM\")\n\t{\n\t\t  _lclose (hFile) ;\n\t\t  return NULL ;\n\t}\n\n\tdwDibSize = bmfh.bfSize - sizeof (BITMAPFILEHEADER) ;\n\n\tlpDib = (BYTE huge * ) GlobalAllocPtr (GMEM_MOVEABLE, dwDibSize) ;\n\n\tif (lpDib == NULL)\n\t{\n\t\t_lclose (hFile) ;\n\t\treturn NULL ;\n\t}\n\n\tdwOffset = 0 ;\n\n\twhile (dwDibSize > 0)\n\t{\n\t\twDibRead = (WORD) min (32768ul, dwDibSize) ;\n\n\t\tif (wDibRead != _lread (hFile, (LPSTR) (lpDib + dwOffset), wDibRead))\n\t\t{\n\t\t\t_lclose (hFile) ;\n\t\t\treturn NULL ;\n\t\t}\n\n\t\tdwDibSize -= wDibRead ;\n\t\tdwOffset  += wDibRead ;\n\t}\n\n\t_lclose (hFile) ;\n\n\tdwHeaderSize = GetDibInfoHeaderSize (lpDib) ;\n\n\tif (dwHeaderSize < 12 || (dwHeaderSize > 12 && dwHeaderSize < 16))\n\t\treturn NULL ;\n\treturn lpDib ;\n}\n\nlong FAR PASCAL _export MainWndProc(HWND hWnd,UINT message,UINT wParam,LONG lParam)\n{\n\tPAINTSTRUCT\tps;\n\tHDC hdc;\n\tRECT rect;\n\tunsigned char r,g,b,x;\n\tFILE *fi;\n\tint i;\n\n\tstatic BYTE huge *lpDib;\n\tstatic BYTE huge *lpDibBits;\n\tstatic int cxDib, cyDib;\n\tstatic LPLOGPALETTE LogPal;\n\tstatic HPALETTE hLogPal;\n\n\tswitch(message)\n\t{\n\t\tcase WM_CREATE:\n\t\t\tfi=fopen(\"somefile.bmp\",\"r\");\n\t\t\tif(fi==NULL)\n\t\t\t\treturn 0;\n\n\t\t\tLogPal=(LPLOGPALETTE)farmalloc(sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*256);\n\t\t\tLogPal->palVersion=0x300;\n\t\t\tLogPal->palNumEntries=256;\n\n\t\t\tfseek(fi,54L,0);\n\t\t\tfor(i=0;i<256;i++)\n\t\t\t{\n\t\t\t\tfscanf(fi,\"%c%c%c%c\",&b,&g,&r,&x);\n\t\t\t\tLogPal->palPalEntry[i].peRed=r;\n\t\t\t\tLogPal->palPalEntry[i].peGreen=g;\n\t\t\t\tLogPal->palPalEntry[i].peBlue=b;\n\t\t\t\tLogPal->palPalEntry[i].peFlags=x;\n\t\t\t}\n\t\t\tfclose(fi);\n\t\t\thLogPal=CreatePalette(LogPal);\n\t\t\treturn 0;\n\t\tcase WM_PAINT:\n\t\t\thdc=BeginPaint(hWnd,&ps);\n\t\t\tGetClientRect(hWnd,&rect);\n\t\t\tSelectPalette(hdc,hLogPal,0);\n\t\t\tRealizePalette(hdc);\n\n\t\t\tSetStretchBltMode(hdc,COLORONCOLOR);\n\t\t\tlpDib=ReadDib(bmp_fname);\n\t\t\tlpDibBits=GetDibBitsAddr(lpDib);\n\t\t\tcxDib=GetDibWidth(lpDib);\n\t\t\tcyDib=GetDibHeight(lpDib);\n\t\t\tStretchDIBits(hdc,0,0,rect.right,rect.bottom,0,0,cxDib,cyDib,(LPSTR)lpDibBits,\n\t\t\t\t(LPBITMAPINFO)lpDib,DIB_RGB_COLORS,SRCCOPY);\n\t\t\tEndPaint(hWnd,&ps);\n\t\t\tbreak;\n\t\tcase WM_DESTROY:\n\t\t\tfarfree(LogPal);\n\t\t\tDeleteObject(hLogPal);\n\t\t\tPostQuitMessage(0);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn (DefWindowProc(hWnd,message,wParam,lParam));\n\t}\n\treturn (DefWindowProc(hWnd,message,wParam,lParam));\n}"
  },
  {
    "path": "LAUNCHER/BITMAP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n"
  },
  {
    "path": "LAUNCHER/CONFIGFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\\\n*        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         *\n******************************************************************************\nProject Name: Carpenter  (The RedAlert ladder creator)\nFile Name   : configfile.cpp\nAuthor      : Neal Kettler\nStart Date  : June 9, 1997\nLast Update : June 17, 1997  \n\n\nThis class will read in a config file and store the key value pairs for\nlater access.  This is a fairly simple class, the config file is assumed\nto be of the form:\n\n#comment\nkey = value\n\nThe value can then be retrieved as a string or an integer.  The key on\nthe left is used for retrieval and it must be specified in uppercase\nfor the 'get' functions. E.g. getString(\"KEY\",valWstring);\n\\***************************************************************************/\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <ctype.h>\n\n#include \"configfile.h\"\n\nstatic uint32 Wstring_Hash(Wstring &string);\nstatic char  *Eat_Spaces(char *string);\n\nConfigFile::ConfigFile() : dictionary(Wstring_Hash)\n{ }\n\nConfigFile::~ConfigFile()\n{ }\n\n// Read and parse the config file.  The key value pairs will be stored\n//   for later access by the getString/getInt functions.\nbit8 ConfigFile::readFile(FILE *in)\n{\n  char    string[256];\n  Wstring  key;\n  Wstring  value;\n  char   *cptr;\n\n  memset(string,0,256);\n  while (fgets(string,256,in))\n  {\n    cptr=Eat_Spaces(string);\n    if ((*cptr==0)||(*cptr=='#'))  // '#' signals a comment\n      continue;\n    if (strchr(cptr,'=')==NULL)   // All config entries must have a '='\n      continue;\n    key=cptr;\n    key.truncate('=');\n    key.removeSpaces();  // No spaces allowed in the key\n    key.toUpper();       // make key all caps \n    cptr=Eat_Spaces(strchr(cptr,'=')+1); // Jump to after the '='\n    value=cptr;\n    value.truncate('\\r');\n    value.truncate('\\n');\n    dictionary.add(key,value);\n  } \n  return(TRUE);\n}\n\n// Get a config entry as a string\nbit8 ConfigFile::getString(Wstring &key,Wstring &value)\n{\n  return(dictionary.getValue(key,value));\n} \n\n// Get a config entry as a string\nbit8 ConfigFile::getString(char *key,Wstring &value)\n{\n  Wstring sKey;\n  sKey.set(key);\n  return(getString(sKey,value));\n}   \n\n// Get a config entry as an integer\nbit8 ConfigFile::getInt(Wstring &key,sint32 &value)\n{\n  Wstring svalue;\n  bit8 retval=dictionary.getValue(key,svalue);\n  if (retval==FALSE)\n    return(FALSE);\n  value=atol(svalue.get());\n  return(TRUE);\n}\n\n// Get a config entry as an integer\nbit8 ConfigFile::getInt(char *key,sint32 &value)\n{\n  Wstring sKey;\n  sKey.set(key);\n  return(getInt(sKey,value));\n}    \n\n\n\n// Get a config entry as an integer\nbit8 ConfigFile::getInt(Wstring &key,sint16 &value)\n{\n  Wstring svalue;\n  bit8 retval=dictionary.getValue(key,svalue);\n  if (retval==FALSE)\n    return(FALSE);\n  value=atoi(svalue.get());\n  return(TRUE);\n}\n \n// Get a config entry as an integer\nbit8 ConfigFile::getInt(char *key,sint16 &value)\n{\n  Wstring sKey;\n  sKey.set(key);\n  return(getInt(sKey,value));\n}\n\n\n\n/************* Static functions below **************/\n\n// Given a Wstring, return a 32 bit integer that has a good numeric\n//   distributation for the purposes of indexing into a hash table.\nstatic uint32 Wstring_Hash(Wstring &string)\n{\n  uint32 retval=0;\n  retval=string.length();\n  for (uint32 i=0; i<string.length(); i++)\n  {\n    retval+=*(string.get()+i);\n    retval+=i;\n    retval=(retval<<8)^(retval>>24);  // ROL 8\n  }\n  return(retval);\n}         \n\nstatic char *Eat_Spaces(char *string)\n{\n  char *retval=string;\n  while (isspace(*retval))\n    retval++;\n  return(retval);\n}\n"
  },
  {
    "path": "LAUNCHER/CONFIGFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\\\n*        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         *\n******************************************************************************\nProject Name: Carpenter  (The RedAlert ladder creator)\nFile Name   : configfile.h \nAuthor      : Neal Kettler\nStart Date  : June 9, 1997\nLast Update : June 17, 1997  \n\\***************************************************************************/\n\n#ifndef CONFIGFILE_HEADER\n#define CONFIGFILE_HEADER\n\n#include \"dictionary.h\"\n#include \"wstring.h\"\n\nclass ConfigFile\n{\n public:\n             ConfigFile();\n            ~ConfigFile();\n bit8        readFile(IN FILE *config);\n bit8        getString(IN Wstring &key,OUT Wstring &value);\n bit8        getString(IN char *key,OUT Wstring &value);\n\n bit8        getInt(IN Wstring &key,OUT sint32 &value);\n bit8        getInt(IN char *key,OUT sint32 &value);\n\n bit8        getInt(IN Wstring &key,OUT sint16 &value);\n bit8        getInt(IN char *key,OUT sint16 &value);\n\n private:\n  Dictionary<Wstring,Wstring> dictionary; // stores the mappings from keys\n                                        //  to value strings\n};\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/DIALOG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n//\n// Create the dialog used during the patching process.\n//\n#include\"winblows.h\"\n#include\"resource.h\"\n#include\"loadbmp.h\"\n#include<commctrl.h>\n\nHWND PatchDialog;\nBOOL CALLBACK Patch_Window_Proc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);\n\nHWND Create_Patch_Dialog(void)\n{\n  PatchDialog=CreateDialog(Global_instance, MAKEINTRESOURCE(IDD_DIALOG1),\n    NULL, (DLGPROC)Patch_Window_Proc);\n\n  ShowWindow(PatchDialog, SW_NORMAL);\n  SetForegroundWindow(PatchDialog);\n  return(PatchDialog);\n}\n\nBOOL CALLBACK Patch_Window_Proc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)\n{\n\n  static LoadBmp bmpLoader;\n\n  switch(iMsg) {\n    case WM_INITDIALOG:\n      // progress bar\n      SendMessage(GetDlgItem(hwnd,IDC_PROGRESS2),PBM_SETRANGE,\n        0,MAKELPARAM(0,100));\n      SendMessage(GetDlgItem(hwnd,IDC_PROGRESS2),PBM_SETPOS,0,0);\n      SendMessage(GetDlgItem(hwnd,IDC_PROGRESS2),PBM_SETSTEP,10,0);\n\n      bmpLoader.init(\"launcher.bmp\",GetDlgItem(hwnd,IDC_SPLASH));\n      return(TRUE);   // True means windows handles focus issues\n    break;\n    case WM_PAINT:\n      bmpLoader.drawBmp();\n    break;\n    case WM_COMMAND:\n      /* May want to add cancel later\n      switch(wParam) {\n        case IDCANCEL:\n        {\n          // do some stuff\n          return(TRUE);\n        }\n        default:\n        break;\n      }\n      default:\n      *************/\n    break;\n    case WM_CLOSE:\n      DestroyWindow(hwnd);\n      PostQuitMessage(0);\n      exit(0);\n    break;\n  }\n  return(FALSE);\n}"
  },
  {
    "path": "LAUNCHER/DIALOG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef DIALOG_HEADER\n#define DIALOG_HEADER\n\n#include\"winblows.h\"\n#include<commctrl.h>\nHWND Create_Patch_Dialog(void);\n\nextern HWND PatchDialog;\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/DICTIONARY.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\\\n*        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         *\n******************************************************************************\nProject Name: Carpenter  (The RedAlert ladder creator)\nFile Name   : dictionary.h\nAuthor      : Neal Kettler\nStart Date  : June 1, 1997\nLast Update : June 17, 1997\n\nThis template file implements a hash dictionary.  A hash dictionary is\nused to quickly match a value with a key.  This works well for very\nlarge sets of data.  A table is constructed that has some power of two\nnumber of pointers in it.  Any value to be put in the table has a hashing\nfunction applied to the key.  That key/value pair is then put in the\nlinked list at the slot the hashing function specifies.  If everything\nis working well, this is much faster than a linked list, but only if\nyour hashing function is good.\n\\****************************************************************************/\n\n#ifndef DICTIONARY_HEADER\n#define DICTIONARY_HEADER    \n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"wstypes.h\"\n#include \"wdebug.h\"\n\n// Every entry in the hash dictionary must be an instance of the DNode\n// template.  'K' and 'V' denote Key and Value.\ntemplate <class K,class V>\nclass DNode\n{\n public:\n  K               key;\n  V               value;\n  DNode<K,V>     *hashNext;\n};        \n\ntemplate <class K,class V>\nclass Dictionary\n{\n public:\n                   Dictionary(uint32 (* hashFn)(K &key));\n                  ~Dictionary();\n\n  void             clear(void);\n  bit8             add(IN K &key,IN V &value);\n  bit8             getValue(IN K &key, OUT V &value);\n  void             print(IN FILE *out) const;\n  uint32           getSize(void) const;\n  uint32           getEntries(void) const;\n  bit8             contains(IN K &key);\n  bit8             updateValue(IN K &key,IN V &value);\n  bit8             remove(IN K &key,OUT V &value);\n  bit8             remove(IN K &key); \n  bit8             removeAny(OUT K &key,OUT V &value);\n  bit8             iterate(INOUT int &index,INOUT int &offset, OUT V &value) const;\n\n private:\n  void             shrink(void);  // halve the number of slots\n  void             expand(void);  // double the number of slots\n\n\n  DNode<K,V>     **table;      // This stores the lists at each slot\n\n  uint32           entries;    // number of entries\n  uint32           size;       // size of table\n  uint32           tableBits;  // table is 2^tableBits big\n  uint32           log2Size;   // Junk variable\n  bit8             keepSize;   // If true don't shrink or expand\n\n  uint32           (* hashFunc)(K &key);   // User provided hash function\n  uint32           keyHash(IN K &key);     // This will reduce to correct range\n\n\n  // See initilizer list of constructor for values\n  const double     SHRINK_THRESHOLD; // When table is this % full shrink it\n  const double     EXPAND_THRESHOLD; // When table is this % full grow it\n  const int        MIN_TABLE_SIZE;   // must be a power of 2               \n};\n\n\n//Create the empty hash dictionary\ntemplate <class K,class V>\nDictionary<K,V>::Dictionary(uint32 (* hashFn)(K &key)) :\n SHRINK_THRESHOLD(0.20), // When table is only 20% full shrink it\n EXPAND_THRESHOLD(0.80), // When table is 80% full grow it\n MIN_TABLE_SIZE(32)      // must be a power of 2\n{\n  log2Size=MIN_TABLE_SIZE;\n  size=MIN_TABLE_SIZE;\n  assert(size>=4);\n  tableBits=0;\n  while(log2Size) { tableBits++; log2Size>>=1; }\n  tableBits--;\n  size=1<<tableBits;  //Just in case MIN_TABLE_SIZE wasn't a power of 2\n  entries=0;\n  keepSize=FALSE;\n\n  //Table is a pointer to a list of pointers (the hash table)\n  table=(DNode<K,V> **)new DNode<K,V>* [size];\n  assert(table!=NULL);\n\n  memset((void *)table,0,size*sizeof(void *));        \n  hashFunc=hashFn;\n}\n\n//Free all the memory...\ntemplate <class K,class V>\nDictionary<K,V>::~Dictionary()\n{\n  clear();          // Remove the entries\n  delete[](table);  // And the table as well\n}\n\n// Remove all the entries and free the memory\ntemplate <class K,class V>\nvoid Dictionary<K,V>::clear()\n{\n  DNode<K,V> *temp,*del;\n  uint32 i;\n  //free all the data\n  for (i=0; i<size; i++)\n  {\n    temp=table[i];\n    while(temp!=NULL)\n    {\n      del=temp;\n      temp=temp->hashNext;\n      delete(del);\n    }\n    table[i]=NULL;\n  }\n  entries=0;\n\n  while ((getSize()>(uint32)MIN_TABLE_SIZE)&&(keepSize==FALSE))\n    shrink();\n}            \n\ntemplate <class K,class V>\nuint32 Dictionary<K,V>::keyHash(IN K &key)\n{\n  uint32 retval=hashFunc(key);\n  retval &= ((1<<tableBits)-1);\n  assert(retval<getSize());\n  return(retval);\n}   \n\n\ntemplate <class K,class V>\nvoid Dictionary<K,V>::print(IN FILE *out) const\n{\n  DNode<K,V> *temp;\n  uint32 i;\n\n  fprintf(out,\"--------------------\\n\");\n  for (i=0; i<getSize(); i++)\n  {\n    temp=table[i];\n\n    fprintf(out,\" |\\n\");\n    fprintf(out,\"[ ]\");\n\n    while (temp!=NULL)\n    {\n      fprintf(out,\"--[ ]\");\n      temp=temp->hashNext;\n    }\n    fprintf(out,\"\\n\");\n  }\n  fprintf(out,\"--------------------\\n\");\n}            \n\n\n//\n// Iterate through all the records. Index is for the table, offset specifies the\n//   element in the linked list.  Set both to 0 and continue calling till false\n//   is returned.\ntemplate <class K,class V>\nbit8 Dictionary<K,V>::iterate(INOUT int &index,INOUT int &offset,\n    OUT V &value) const\n{\n  DNode<K,V> *temp;\n\n  // index out of range\n  if ((index<0)||(index >= getSize()))\n    return(FALSE);\n\n  temp=table[index];\n  while ((temp==NULL)&&((++index) < getSize()))\n  {\n    temp=table[index];\n    offset=0;\n  }\n\n  if (temp==NULL)   // no more slots with data\n    return(FALSE);\n\n  uint32 i=0;\n  while ((temp!=NULL) && (i < offset))\n  {\n    temp=temp->hashNext;\n    i++;\n  }\n\n  if (temp==NULL)  // should never happen\n    return(FALSE);\n\n  value=temp->value;\n  if (temp->hashNext==NULL)\n  {\n    index++;\n    offset=0;\n  }\n  else\n    offset++;\n\n  return(TRUE);\n}            \n\n\n\n// Return the current size of the hash table\ntemplate <class K,class V>\nuint32 Dictionary<K,V>::getSize(void) const\n{ return(size); }    \n\n\n// Return the current number of entries in the table\ntemplate <class K,class V>\nuint32 Dictionary<K,V>::getEntries(void) const\n{ return(entries); }\n\n\n// Does the Dictionary contain the key?\ntemplate <class K,class V>\nbit8 Dictionary<K,V>::contains(IN K &key)\n{\n  int offset;\n  DNode<K,V> *node;\n\n  offset=keyHash(key);\n\n  node=table[offset];\n\n  if (node==NULL)\n  { return(FALSE); }  // can't find it\n\n  while(node!=NULL)\n  {\n    if ((node->key)==key)\n    { return(TRUE); }          \n    node=node->hashNext;\n  }\n  return(FALSE); \n}\n\n\n// Try and update the value of an already existing object\ntemplate <class K,class V>\nbit8 Dictionary<K,V>::updateValue(IN K &key,IN V &value)\n{\n  sint32 retval;\n\n  retval=remove(key);\n  if (retval==FALSE)\n    return(FALSE);\n\n  add(key,value);\n  return(TRUE);\n}           \n\n\n// Add to the dictionary (if key exists, value is updated with the new V)\ntemplate <class K, class V>\nbit8 Dictionary<K,V>::add(IN K &key,IN V &value)\n{\n  int offset;\n  DNode<K,V> *node,*item,*temp;\n  float percent;\n\n  item=(DNode<K,V> *)new DNode<K,V>;\n  assert(item!=NULL);\n\n  #ifdef KEY_MEM_OPS\n    memcpy(&(item->key),&key,sizeof(K));\n  #else\n    item->key=key;\n  #endif\n\n  #ifdef VALUE_MEM_OPS\n    memcpy(&(item->value),&value,sizeof(V));\n  #else\n    item->value=value;\n  #endif\n\n  item->hashNext=NULL;\n\n  //If key already exists, it will be overwritten\n  remove(key);\n\n  offset=keyHash(key);\n    \n  node=table[offset];\n\n  if (node==NULL)\n  { table[offset]=item; }\n  else\n  {\n    temp=table[offset];\n    table[offset]=item;\n    item->hashNext=temp;\n  } \n\n  entries++;\n  percent=(float)entries;\n  percent/=(float)getSize();\n  if (percent>= EXPAND_THRESHOLD ) expand();\n\n  return(TRUE);\n}\n\n// Remove an item from the dictionary\ntemplate <class K,class V>\nbit8 Dictionary<K,V>::remove(IN K &key,OUT V &value)\n{\n  int offset;\n  DNode<K,V> *node,*last,*temp;\n  float percent;\n\n  if (entries==0)\n    return(FALSE);\n\n  percent=(float)(entries-1);\n  percent/=(float)getSize();\n\n  offset=keyHash(key);\n  node=table[offset];\n\n  last=node;\n  if (node==NULL) return(FALSE);\n\n  //special case table points to thing to delete\n\n  #ifdef KEY_MEM_OPS\n  if (0==memcmp(&(node->key),&key,sizeof(K)))\n  #else\n  if ((node->key)==key)\n  #endif\n  {\n    #ifdef VALUE_MEM_OPS\n      memcpy(&value,&(node->value),sizeof(V));\n    #else\n      value=node->value;\n    #endif\n    temp=table[offset]->hashNext;\n    delete(table[offset]);\n    table[offset]=temp;\n    entries--;\n    if (percent <= SHRINK_THRESHOLD)\n      shrink();\n    return(TRUE);\n  }\n  node=node->hashNext;\n\n  //Now the case if the thing to delete is not the first\n  while (node!=NULL)\n  {\n    #ifdef KEY_MEM_OPS\n      if (0==memcmp(&(node->key),&key,sizeof(K)))\n    #else\n      if (node->key==key)\n    #endif\n    {\n      #ifdef VALUE_MEM_OPS\n        memcpy(&value,&(node->value),sizeof(V));\n      #else\n        value=node->value;\n      #endif \n      last->hashNext=node->hashNext;\n      entries--;\n      delete(node);\n      break;\n    }\n    last=node;\n    node=node->hashNext;\n  }\n\n  if (percent <= SHRINK_THRESHOLD)\n    shrink();\n  return(TRUE);\n}\n\n\ntemplate <class K,class V>\nbit8 Dictionary<K,V>::remove(IN K &key)\n{\n  V temp;\n  return(remove(key,temp));\n}\n\n\n// Remove some random K/V pair that's in the Dictionary\ntemplate <class K,class V>\nbit8 Dictionary<K,V>::removeAny(OUT K &key,OUT V &value)\n{\n  int offset;\n  DNode<K,V> *node,*last,*temp;\n  float percent;\n\n  if (entries==0)\n    return(FALSE);\n\n  percent=(entries-1);\n  percent/=(float)getSize();\n\n  int i;\n  offset=-1;\n  for (i=0; i<(int)getSize(); i++)\n    if (table[i]!=NULL)\n    {\n      offset=i;\n      break;\n    } \n\n  if (offset==-1)    // Nothing there\n    return(FALSE);\n\n  node=table[offset];\n  last=node;\n\n  #ifdef KEY_MEM_OPS\n    memcpy(&key,&(node->key),sizeof(K));\n  #else\n    key=node->key;\n  #endif\n  #ifdef VALUE_MEM_OPS\n    memcpy(&value,&(node->value),sizeof(V));     \n  #else\n    value=node->value;\n  #endif\n\n  temp=table[offset]->hashNext;\n  delete(table[offset]);\n  table[offset]=temp;\n  entries--;\n  if (percent <= SHRINK_THRESHOLD)\n    shrink();\n  return(TRUE);\n}\n\ntemplate <class K,class V>\nbit8 Dictionary<K,V>::getValue(IN K &key,OUT V &value)\n{\n  int offset;\n  DNode<K,V> *node;\n\n  offset=keyHash(key);\n\n  node=table[offset];\n\n  if (node==NULL) return(FALSE);\n\n  #ifdef KEY_MEM_OPS\n    while ((node!=NULL)&&(memcmp(&(node->key),&key,sizeof(K))))\n  #else\n    while ((node!=NULL)&&( ! ((node->key)==key)) )  // odd syntax so you don't\n  #endif                                            // have to do oper !=\n  { node=node->hashNext; }\n\n  if (node==NULL)\n  { return(FALSE); }\n\n  #ifdef VALUE_MEM_OPS\n    memcpy(&value,&(node->value),sizeof(V));\n  #else\n    value=(node->value);\n  #endif\n  return(TRUE);\n}\n\n\n//A note about Shrink and Expand: They are never necessary, they are\n//only here to improve performance of the hash table by reducing\n//the length of the linked list at each table entry.\n\n// Shrink the hash table by a factor of 2 (and relocate entries)   \ntemplate <class K,class V>\nvoid Dictionary<K,V>::shrink(void)\n{\n  int    i;\n  int    oldsize;\n  uint32 offset;\n  DNode<K,V> **oldtable,*temp,*first,*next;\n\n  if ((size<=(uint32)MIN_TABLE_SIZE)||(keepSize==TRUE))\n    return;\n\n  //fprintf(stderr,\"Shrinking....\\n\");\n\n  oldtable=table;\n  oldsize=size;\n  size/=2;\n  tableBits--;\n\n  table=(DNode<K,V> **)new DNode<K,V>*[size];\n  assert(table!=NULL);\n  memset((void *)table,0,size*sizeof(void *)); \n\n  for (i=0; i<oldsize; i++)\n  {\n    temp=oldtable[i];\n    while (temp!=NULL)\n    {\n      offset=keyHash(temp->key);\n      first=table[offset];\n      table[offset]=temp;\n      next=temp->hashNext;\n      temp->hashNext=first;\n      temp=next;\n    }\n  }\n  delete[](oldtable);\n}\n\n\ntemplate <class K,class V>\nvoid Dictionary<K,V>::expand(void)\n{\n  int    i;\n  int    oldsize;\n  uint32 offset;\n  DNode<K,V> **oldtable,*temp,*first,*next;\n\n  if (keepSize==TRUE)\n    return;\n\n  //fprintf(stderr,\"Expanding...\\n\");\n\n  oldtable=table;\n  oldsize=size;\n  size*=2;\n  tableBits++;\n\n  table=(DNode<K,V> **)new DNode<K,V>* [size];\n  assert(table!=NULL);\n  memset((void *)table,0,size*sizeof(void *));       \n\n  for (i=0; i<oldsize; i++)\n  {\n    temp=oldtable[i];\n    while (temp!=NULL)\n    {\n      offset=keyHash(temp->key);\n      first=table[offset];\n      table[offset]=temp;\n      next=temp->hashNext;\n      temp->hashNext=first;\n      temp=next;\n    }\n  }\n  delete[](oldtable);\n}\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/FILED.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef FILED_HEADER\n#define FILED_HEADER\n\n#include \"odevice.h\"\n\nclass FileD : public OutputDevice\n{\n public:\n   FileD(char *filename)\n   { \n     out=fopen(filename,\"w\");\n     if (out==NULL)\n       out=fopen(\"FileDev.out\",\"w\");\n   }\n\n   virtual ~FileD()\n   { fclose(out); }\n\n   virtual int print(const char *str,int len)\n   {\n     char *string=new char[len+1];\n     memset(string,0,len+1);\n     memcpy(string,str,len);\n     fprintf(out,\"%s\",string);\n     delete[](string);\n     fflush(out);\n     return(len);\n   }\n\n   FILE      *out;\n};\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/FINDPATCH.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"findpatch.h\"\n\n//\n// Locate a patch file\n//  If a patch can be found then TRUE is returned and the name is filled in,\n//  otherwise FALSE is returned.\n//\n// Patch Types:\n//   - *.rtp = RTPatch file that can be applied right now\n//   - *.exe = Executable that should be put in the RunOnce registry entry & reboot\n//   - *.exn = Executable that should be run right now\n//   - *.web = Link to a web page that will have the patch\n//   - else  = File is ignored, possibly a resource file for one of the other types\n//\nint Find_Patch(OUT char *filename,int maxlen, ConfigFile &config)\n{\n  WIN32_FIND_DATA     findData;\n  char                string[128];\n  HANDLE              hFile;\n  char               *extensions[]={\"web\",\"exe\",\"exn\",\"rtp\",NULL};\n  int                 i;\n  int                 skuIndex=0;\n  Wstring             key;\n  Wstring             path;\n  Wstring             sku;\n  char                gamePath[MAX_PATH];\n  bit8                ok;\n\n\n  while(1)\n  {\n    //\n    // Loop through the apps we're responsible for\n    //\n    skuIndex++;\n    ok=Get_App_Dir(gamePath,MAX_PATH,config,skuIndex);\n    if (ok==FALSE)\n      break;\n    \n    i=0;\n    while(extensions[i++])\n    {\n      _chdir(gamePath);  // goto the directory with the game\n\n      // should probably get the registry entry for the wchat install path\n      sprintf(string,\"patches\\\\*.%s\",extensions[i]);\n      hFile=FindFirstFile(string,&findData);\n      if (hFile!=INVALID_HANDLE_VALUE)\n      {\n        _getcwd(filename,MAX_PATH);\n        strcat(filename,\"\\\\patches\\\\\");\n        strcat(filename,findData.cFileName);\n        FindClose(hFile);\n        return(skuIndex);\n      }\n    }\n  }\n  return(FALSE);\n}\n\n\n//\n// Get the directory for the N'th application in the config file\n//\n// Returns FALSE if not in the config file or invalid for some reason.\n//\nbit8 Get_App_Dir(OUT char *filename,int maxlen, ConfigFile &config,int index)\n{\n  char                string[128];\n  Wstring             key;\n  Wstring             path;\n  Wstring             sku;\n  int                 temp;\n  char                gamePath[MAX_PATH];\n\n\n  sprintf(string,\"SKU%d\",index);\n\n  // Can't find this product\n  if (config.getString(string,key)==FALSE)\n    return(FALSE);\n\n \n  DBGMSG(\"KEY = \"<<key.get());\n  // Get the InstallPath from the specified registry key\n  temp=0;\n  temp=key.getToken(temp,\" \",sku);\n  path=key;\n  path.remove(0,temp);\n  while((*(path.get()))==' ')  // remove leading spaces\n    path.remove(0,1);\n\n\n  DBGMSG(\"CONFIG:   SKU = \"<<sku.get()<<\"  PATH = '\"<<path.get()<<\"'\");\n  HKEY   regKey;\n  LONG   regRetval;\n  /////////////DWORD  regPrevious;\n  regRetval=RegOpenKeyEx(HKEY_LOCAL_MACHINE,path.get(),0,KEY_READ,&regKey);\n  if (regRetval!=ERROR_SUCCESS)\n  {\n    DBGMSG(\"RegOpenKey failed\");\n    return(FALSE);\n  }\n  DWORD  type;\n  DWORD  length=MAX_PATH;\n  regRetval=RegQueryValueEx(regKey,\"InstallPath\",NULL,&type,(uint8 *)gamePath,\n      &length);\n  DBGMSG(\"GAME PATH = \"<<gamePath);\n  if ((regRetval!=ERROR_SUCCESS)||(type!=REG_SZ))\n  {\n    DBGMSG(\"Reg failure\");\n    return(FALSE);\n  }\n\n  // Find the last '\\\\' in a string and put a 0 after it\n  //  If you only put a directory in the InstallPath key instead of a full\n  //  path to a file, you better end the directory with a trailing '\\\\'!!!\n  char *cptr=gamePath;\n  char *tempPtr;\n  while( (tempPtr=strchr(cptr,'\\\\')) !=NULL)\n    cptr=tempPtr+1;\n  if (cptr)\n    *cptr=0;\n\n  DBGMSG(\"Game path = \"<<gamePath);\n  strncpy(filename,gamePath,maxlen);\n\n  return(TRUE);\n}\n\n\n\n\n\n//\n// Delete any patch files\n//\nvoid Delete_Patches(ConfigFile &config)\n{\n  char dir[MAX_PATH];\n  int  i=1;\n  WIN32_FIND_DATA     findData;\n  HANDLE              hFile;\n\n  DBGMSG(\"IN DELPATCH\");\n\n  //\n  // Loop through all the application directories in the config file\n  //\n  while (Get_App_Dir(dir,MAX_PATH,config,i++)==TRUE)\n  {\n    // Make sure path is at least 3 for \"c:\\\".  I really hope nobody's\n    //   dumb enough to install a game to the root directory. (It's OK though\n    //   since only the '\\patches' folder is cleared out.\n    if (strlen(dir)<3)\n      continue;\n\n    //\n    // Delete everything in case a .exe patch had some data files it used.\n    //\n    strcat(dir,\"patches\\\\*.*\");\n\n    DBGMSG(\"DELPATCH: \"<<dir);\n\n    hFile=FindFirstFile(dir,&findData);\n    if (hFile!=INVALID_HANDLE_VALUE)\n    {\n      if (findData.cFileName[0]!='.')\n      {\n        //_unlink(findData.cFileName);\n        DBGMSG(\"UNLINK: \"<<findData.cFileName);\n      }\n      while(FindNextFile(hFile,&findData))\n      {\n        if (findData.cFileName[0]!='.')\n        {\n          //_unlink(findData.cFileName);\n          DBGMSG(\"UNLINK: \"<<findData.cFileName);\n        }\n      }\n    }  // If there's at least one file\n    FindClose(hFile);\n  }  // while there's apps in config\n  return;\n} \n"
  },
  {
    "path": "LAUNCHER/FINDPATCH.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef FINDPATCH_HEADER\n#define FINDPATCH_HEADER\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <windows.h>\n#include <direct.h>\n#include \"wstypes.h\"\n#include \"configfile.h\"\n\nint Find_Patch(OUT char *file,int maxlen, ConfigFile &config);\nbit8 Get_App_Dir(OUT char *file,int maxlen, ConfigFile &config, int index);\nvoid Delete_Patches(ConfigFile &config);\n\n#endif"
  },
  {
    "path": "LAUNCHER/LAUNCHER.DSP",
    "content": "# Microsoft Developer Studio Project File - Name=\"launcher\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Application\" 0x0101\n\nCFG=launcher - Win32 Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"launcher.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"launcher.mak\" CFG=\"launcher - Win32 Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"launcher - Win32 Release\" (based on \"Win32 (x86) Application\")\n!MESSAGE \"launcher - Win32 Debug\" (based on \"Win32 (x86) Application\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nMTL=midl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"launcher - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"Release\"\n# PROP Intermediate_Dir \"Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /YX /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /map /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"launcher - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"Debug\"\n# PROP Intermediate_Dir \"Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /YX /FD /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"DEBUG\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib patchw32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:\".\"\n\n!ENDIF \n\n# Begin Target\n\n# Name \"launcher - Win32 Release\"\n# Name \"launcher - Win32 Debug\"\n# Begin Group \"dbglib\"\n\n# PROP Default_Filter \".cpp,.h\"\n# Begin Source File\n\nSOURCE=.\\configfile.cpp\n# End Source File\n# Begin Source File\n\nSOURCE=.\\configfile.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\dictionary.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\filed.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\monod.cpp\n# End Source File\n# Begin Source File\n\nSOURCE=.\\monod.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\odevice.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\streamer.cpp\n# End Source File\n# Begin Source File\n\nSOURCE=.\\streamer.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\wdebug.cpp\n# End Source File\n# Begin Source File\n\nSOURCE=.\\wdebug.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\wstring.cpp\n# End Source File\n# Begin Source File\n\nSOURCE=.\\wstring.h\n# End Source File\n# End Group\n# Begin Group \"util\"\n\n# PROP Default_Filter \"\"\n# End Group\n# Begin Source File\n\nSOURCE=.\\dialog.cpp\n# End Source File\n# Begin Source File\n\nSOURCE=.\\dialog.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\findpatch.cpp\n# End Source File\n# Begin Source File\n\nSOURCE=.\\findpatch.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\launcher1.rc\n# End Source File\n# Begin Source File\n\nSOURCE=.\\loadbmp.cpp\n# End Source File\n# Begin Source File\n\nSOURCE=.\\loadbmp.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\main.cpp\n# End Source File\n# Begin Source File\n\nSOURCE=.\\patch.cpp\n# End Source File\n# Begin Source File\n\nSOURCE=.\\patch.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\process.cpp\n# End Source File\n# Begin Source File\n\nSOURCE=.\\process.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\Redalert.ico\n# End Source File\n# Begin Source File\n\nSOURCE=.\\resource.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\winblows.cpp\n# End Source File\n# Begin Source File\n\nSOURCE=.\\winblows.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\wstypes.h\n# End Source File\n# End Target\n# End Project\n"
  },
  {
    "path": "LAUNCHER/LAUNCHER.DSW",
    "content": "Microsoft Developer Studio Workspace File, Format Version 6.00\n# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n###############################################################################\n\nProject: \"launcher\"=.\\launcher.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nGlobal:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n###############################################################################\n\n"
  },
  {
    "path": "LAUNCHER/LAUNCHER1.RC",
    "content": "//Microsoft Developer Studio generated resource script.\n//\n#include \"resource.h\"\n\n#define APSTUDIO_READONLY_SYMBOLS\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 2 resource.\n//\n#include \"afxres.h\"\n\n/////////////////////////////////////////////////////////////////////////////\n#undef APSTUDIO_READONLY_SYMBOLS\n\n/////////////////////////////////////////////////////////////////////////////\n// English (U.S.) resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\n#ifdef _WIN32\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\n#pragma code_page(1252)\n#endif //_WIN32\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Dialog\n//\n\nIDD_DIALOG1 DIALOG DISCARDABLE  0, 0, 243, 126\nSTYLE DS_MODALFRAME | DS_SETFOREGROUND | WS_MINIMIZEBOX | WS_POPUP | \n    WS_CAPTION | WS_SYSMENU\nCAPTION \"Patching\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    CONTROL         \"\",IDC_SPLASH,\"Static\",SS_GRAYRECT | SS_SUNKEN,7,7,229,\n                    70\n    GROUPBOX        \"File\",IDC_CAPTION,7,78,229,22\n    CONTROL         \"Progress1\",IDC_PROGRESS2,\"msctls_progress32\",WS_BORDER,\n                    7,105,229,13\n    CONTROL         \"\",IDC_FILENAME,\"Static\",SS_LEFTNOWORDWRAP | \n                    SS_CENTERIMAGE | WS_GROUP,13,85,217,13\nEND\n\nIDD_CHANGELOG DIALOG DISCARDABLE  0, 0, 332, 204\nSTYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU\nCAPTION \"Update Information\"\nFONT 10, \"Lucida Console\"\nBEGIN\n    EDITTEXT        IDC_TEXT,5,5,322,178,ES_MULTILINE | ES_AUTOHSCROLL | \n                    ES_READONLY | WS_VSCROLL | WS_HSCROLL\n    PUSHBUTTON      \"OK\",IDOK,128,185,76,14\nEND\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// DESIGNINFO\n//\n\n#ifdef APSTUDIO_INVOKED\nGUIDELINES DESIGNINFO DISCARDABLE \nBEGIN\n    IDD_DIALOG1, DIALOG\n    BEGIN\n        LEFTMARGIN, 7\n        RIGHTMARGIN, 236\n        TOPMARGIN, 7\n        BOTTOMMARGIN, 119\n    END\n\n    IDD_CHANGELOG, DIALOG\n    BEGIN\n        LEFTMARGIN, 5\n        RIGHTMARGIN, 327\n        TOPMARGIN, 5\n        BOTTOMMARGIN, 199\n    END\nEND\n#endif    // APSTUDIO_INVOKED\n\n\n#ifdef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// TEXTINCLUDE\n//\n\n1 TEXTINCLUDE DISCARDABLE \nBEGIN\n    \"resource.h\\0\"\nEND\n\n2 TEXTINCLUDE DISCARDABLE \nBEGIN\n    \"#include \"\"afxres.h\"\"\\r\\n\"\n    \"\\0\"\nEND\n\n3 TEXTINCLUDE DISCARDABLE \nBEGIN\n    \"\\r\\n\"\n    \"\\0\"\nEND\n\n#endif    // APSTUDIO_INVOKED\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Icon\n//\n\n// Icon with lowest ID value placed first to ensure application icon\n// remains consistent on all systems.\nIDI_ICON2               ICON    DISCARDABLE     \"redalert.ico\"\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// String Table\n//\n\nSTRINGTABLE DISCARDABLE \nBEGIN\n    IDS_SYS_RESTART         \"Your computer needs to be restarted to continue the patch. Press OK to continue.\"\n    IDS_SYS_RESTART_TITLE   \"About to restart\"\n    IDS_WEBPATCH            \"You need to download a patch from our website.\\rWhen you press OK, your browser will automatically open to the download page.\"\n    IDS_WEBPATCH_TITLE      \"Web Patch\"\n    IDS_FILE_X_OF_Y         \"File (%d of %d)\"\n    IDS_MUST_RESTART        \"You must restart your computer now.\"\n    IDS_RUNONCE_ERR         \"Could not set the patch to run on system reboot!\\rYou must exit the game and run %s to complete the patch.\"\n    IDS_ERROR               \"Error\"\n    IDS_ERR_MISSING_FILE    \"Error: Couldn't find file: %s\"\n    IDS_BAD_LIBRARY         \"A required DLL is corrupt.\"\nEND\n\n#endif    // English (U.S.) resources\n/////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 3 resource.\n//\n\n\n/////////////////////////////////////////////////////////////////////////////\n#endif    // not APSTUDIO_INVOKED\n\n"
  },
  {
    "path": "LAUNCHER/LOADBMP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include\"loadbmp.h\"\n\n\nLoadBmp::LoadBmp()\n{\n  BitmapHandle_=NULL;\n  PalHandle_=NULL;\n}\n\nLoadBmp::~LoadBmp()\n{\n  // free resources\n  DeleteObject(BitmapHandle_);\n  DeleteObject(PalHandle_);\n}\n\n//\n//  Load a specified bitmap for later display on a window\n//\nbit8 LoadBmp::init(char *filename,HWND hwnd)\n{\n  int                  i;\n  char                 string[128];\n  HANDLE               hBitmapFile;\n  DWORD                dwRead;\n  BITMAPFILEHEADER     bitmapHeader;\n  BITMAPINFOHEADER     bitmapInfoHeader;\n  LPLOGPALETTE         lpLogPalette;\n  char                *palData;\n  HGLOBAL              hmem2;\n  LPVOID               lpvBits;\n  PAINTSTRUCT          ps;\n  HDC                  hdc;\n  HPALETTE             select;\n  UINT                 realize;\n  RECT                 rect;\n\n\n  // Set the member for future reference\n  WindowHandle_=hwnd;\n\n  // Retrieve a handle identifying the file. \n  hBitmapFile = CreateFile(\n    filename,\n    GENERIC_READ, \n    FILE_SHARE_READ,\n    (LPSECURITY_ATTRIBUTES) NULL, \n    OPEN_EXISTING,\n    FILE_ATTRIBUTE_READONLY, \n    (HANDLE) NULL); \n\n  if (hBitmapFile==NULL)\n    return(FALSE);\n\n  // Retrieve the BITMAPFILEHEADER structure. \n  ReadFile(hBitmapFile, &bitmapHeader, sizeof(BITMAPFILEHEADER), &dwRead, \n    (LPOVERLAPPED)NULL); \n \n\n  // Retrieve the BITMAPFILEHEADER structure. \n  ReadFile(hBitmapFile, &bitmapInfoHeader, sizeof(BITMAPINFOHEADER), \n    &dwRead, (LPOVERLAPPED)NULL); \n\n \n  // Allocate memory for the BITMAPINFO structure. \n  HGLOBAL infoHeaderMem = GlobalAlloc(GHND, sizeof(BITMAPINFOHEADER) + \n    ((1<<bitmapInfoHeader.biBitCount) * sizeof(RGBQUAD))); \n \n  LPBITMAPINFO lpHeaderMem = (LPBITMAPINFO)GlobalLock(infoHeaderMem); \n \n  // Load BITMAPINFOHEADER into the BITMAPINFO structure. \n  lpHeaderMem->bmiHeader.biSize          = bitmapInfoHeader.biSize; \n  lpHeaderMem->bmiHeader.biWidth         = bitmapInfoHeader.biWidth; \n  lpHeaderMem->bmiHeader.biHeight        = bitmapInfoHeader.biHeight; \n  lpHeaderMem->bmiHeader.biPlanes        = bitmapInfoHeader.biPlanes; \n  lpHeaderMem->bmiHeader.biBitCount      = bitmapInfoHeader.biBitCount; \n  lpHeaderMem->bmiHeader.biCompression   = bitmapInfoHeader.biCompression; \n  lpHeaderMem->bmiHeader.biSizeImage     = bitmapInfoHeader.biSizeImage; \n  lpHeaderMem->bmiHeader.biXPelsPerMeter = bitmapInfoHeader.biXPelsPerMeter; \n  lpHeaderMem->bmiHeader.biYPelsPerMeter = bitmapInfoHeader.biYPelsPerMeter; \n  lpHeaderMem->bmiHeader.biClrUsed       = bitmapInfoHeader.biClrUsed; \n  lpHeaderMem->bmiHeader.biClrImportant  = bitmapInfoHeader.biClrImportant; \n \n\n  // Retrieve the color table. \n  // 1 << bitmapInfoHeader.biBitCount == 2 ^ bitmapInfoHeader.biBitCount \n  ReadFile(hBitmapFile, lpHeaderMem->bmiColors, \n    ((1<<bitmapInfoHeader.biBitCount) * sizeof(RGBQUAD)), \n    &dwRead, (LPOVERLAPPED) NULL); \n\n\n  lpLogPalette=(LPLOGPALETTE)new char[(sizeof(LOGPALETTE)+\n      sizeof(PALETTEENTRY)*256)];\n  lpLogPalette->palVersion=0x300;\n  lpLogPalette->palNumEntries=256;\n\n  palData=(char *)lpHeaderMem->bmiColors;\n\n  for (i=0; i<256; i++)\n  {\n    lpLogPalette->palPalEntry[i].peRed=*palData++;\n    lpLogPalette->palPalEntry[i].peGreen=*palData++;\n    lpLogPalette->palPalEntry[i].peBlue=*palData++;\n    lpLogPalette->palPalEntry[i].peFlags=*palData++;\n  }\n  PalHandle_=CreatePalette(lpLogPalette);\n  delete(lpLogPalette);\n\n \n  // Allocate memory for the required number of bytes. \n  hmem2 = GlobalAlloc(GHND, (bitmapHeader.bfSize - bitmapHeader.bfOffBits)); \n \n  lpvBits = GlobalLock(hmem2); \n \n  // Retrieve the bitmap data. \n  ReadFile(hBitmapFile, lpvBits, (bitmapHeader.bfSize - bitmapHeader.bfOffBits), \n    &dwRead, (LPOVERLAPPED) NULL); \n \n\n  // Create a bitmap from the data stored in the .BMP file. \n  hdc=GetDC(hwnd);\n  select=SelectPalette(hdc,PalHandle_,0);\n  if (select==NULL)\n    return(FALSE);\n  realize=RealizePalette(hdc);\n  if (realize==GDI_ERROR)\n    return(FALSE);\n  BitmapHandle_=CreateDIBitmap(hdc, &bitmapInfoHeader, CBM_INIT, lpvBits, lpHeaderMem, DIB_RGB_COLORS); \n  ReleaseDC(hwnd,hdc);\n\n\n  if (BitmapHandle_==NULL)\n    return(FALSE);\n \n  // Unlock the global memory objects and close the .BMP file.  \n  GlobalUnlock(infoHeaderMem); \n  GlobalUnlock(hmem2); \n  CloseHandle(hBitmapFile); \n \n  if (BitmapHandle_==NULL) \n    return(FALSE);\n \n  // Inform windows the window needs to be repainted\n  GetClientRect(hwnd, &rect); \n  InvalidateRect(hwnd, &rect, TRUE); \n  UpdateWindow(hwnd); \n\n  return(TRUE);\n}\n\n\nbit8 LoadBmp::drawBmp(void)\n{\n  // Paint the window (and draw the bitmap). \n \n  PAINTSTRUCT ps;\n  HDC         hdc;\n  char        string[128];\n\n  InvalidateRect(WindowHandle_,NULL,FALSE); // keep windows from screwing up the\n                                           //  redrawing (as much).\n  hdc=BeginPaint(WindowHandle_,&ps);\n\n  //Do palette stuff\n  HPALETTE select=SelectPalette(ps.hdc,PalHandle_,0);\n  if (select==NULL)\n  {\n    sprintf(string,\"Select Pal Fail: %d\",GetLastError());\n    MessageBox(NULL,string,\"OK\",MB_OK);\n  }\n  UINT realize=RealizePalette(ps.hdc);\n  if (realize==GDI_ERROR)\n  {\n    sprintf(string,\"Realize Pal Fail: %d\",GetLastError());\n    MessageBox(NULL,string,\"OK\",MB_OK);\n  }\n\n  HDC hdcMem = CreateCompatibleDC(ps.hdc); \n  SelectObject(hdcMem, BitmapHandle_); \n  BITMAP bm;\n  GetObject(BitmapHandle_, sizeof(BITMAP), (LPSTR) &bm);\n  \n  /// for non-stretching version\n  ///////BitBlt(ps.hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY); \n\n  RECT clientRect;\n  GetClientRect(WindowHandle_,&clientRect);\n  SetStretchBltMode(ps.hdc,COLORONCOLOR);\n  StretchBlt(ps.hdc,0,0,clientRect.right,clientRect.bottom,hdcMem,0,0,bm.bmWidth,\n    bm.bmHeight,SRCCOPY);\n\n\n  DeleteDC(hdcMem); \n  EndPaint(WindowHandle_,&ps);\n  return(TRUE);\n}\n"
  },
  {
    "path": "LAUNCHER/LOADBMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef LOADBMP_HEADER\n#define LOADBMP_HEADER\n\n#include<stdlib.h>\n#include<stdio.h>\n#include \"wstypes.h\"\n#include \"winblows.h\"\n\n\n//\n// Functions and data assocated with a loaded bitmap on a single window.\n//\nclass LoadBmp\n{\n public:\n                  LoadBmp();\n                 ~LoadBmp();\n   bit8           init(char *filename,HWND hwnd);  // must call before the drawBmp\n   bit8           drawBmp(void);  // call this from your WM_PAINT message\n\n private:\n   HBITMAP        BitmapHandle_;\n   HPALETTE       PalHandle_;\n   HWND           WindowHandle_;\n};\n\n\n#endif"
  },
  {
    "path": "LAUNCHER/MAIN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*****************************************************************************\\\n          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\n*******************************************************************************\n File:       main.cpp\n Programmer: Neal Kettler\n \n StartDate:  Feb  6, 1998\n LastUpdate: Feb 10, 1998\n-------------------------------------------------------------------------------\n\n Launcher application for games/apps using the chat API.  This should be\n run by the user and it will start the actual game executable.  If a patch\n file has been downloaded the patch will be applied before starting the game.\n\n This does not download patches or do version checks, the game/app is responsible\n for that.  This just applies patches that are in the correct location for the\n game.  All patches should be in the \"Patches\" folder of the app.\n\n The launcher should have a config file (launcher.cfg) so it knows which apps\n should be checked for patches. The file should look like this:\n\n # comment\n # RUN = the game to launch\n RUN = . notepad.exe        # directory and app name\n #\n # Sku's to check for patches\n #\n SKU1 = 1100 SOFTWARE\\Westwood\\WOnline      # skus and registry keys\n SKU2 = 1234 SOFTWARE\\Westwood\\FakeGame\n\n\\*****************************************************************************/\n\n\n#include \"dialog.h\"\n#include \"patch.h\"\n#include \"findpatch.h\"\n#include \"process.h\"\n\n#include \"wdebug.h\"\n#include \"monod.h\"\n#include \"filed.h\"\n#include \"configfile.h\"\n#include <windows.h>\n\n#define UPDATE_RETVAL 123456789  // if a program returns this it means it wants to check for patches\n\nvoid CreatePrimaryWin(char *prefix);\nvoid myChdir(char *path);\n\n\n//\n// Called by WinMain\n//\nint main(int argc, char *argv[])\n{\n  char      patchFile[MAX_PATH];\n  bit8      ok;\n  int       skuIndex=0;\n  char      cwd[MAX_PATH];  // save current directory before game start\n  _getcwd(cwd,MAX_PATH);\n\n  InitCommonControls();\n\n  #ifdef DEBUG\n    ///MonoD outputDevice;\n    FileD outputDevice(\"launcher.out\");\n    MsgManager::setAllStreams(&outputDevice);\n    DBGMSG(\"Launcher initialized\");\n  #endif\n\n  \n  // Goto the folder where launcher is installed\n  myChdir(argv[0]);\n\n  // extract the program name from argv[0].  Change the extension to\n  //   .lcf (Launcher ConFig).  This is the name of our config file.\n  char  configName[MAX_PATH+3];\n  strcpy(configName,argv[0]);\n  char *extension=configName;\n  char *tempptr;\n  while((tempptr=strchr(extension+1,'.')))\n    extension=tempptr;\n  if (*extension=='.')\n    *extension=0;\n  strcat(configName,\".lcf\");\n\n  DBGMSG(\"Config Name: \"<<configName);\n\n  ConfigFile config;\n  FILE *in=fopen(configName,\"r\");\n  if (in==NULL)\n  {\n    MessageBox(NULL,\"You must run the game from its install directory.\",\n      \"Launcher config file missing\",MB_OK);\n    exit(-1);\n  }\n  ok=config.readFile(in);\n  fclose(in);\n  if(ok==FALSE)\n  {\n     MessageBox(NULL,\"File 'launcher.cfg' is corrupt\",\"Error\",MB_OK);\n     exit(-1);\n  }\n\n\n  // Load process info\n  Process proc;\n  Read_Process_Info(config,proc);\n\n  DBGMSG(\"Read process info\");\n\n  // Create the main window\n  ///CreatePrimaryWin(proc.command);\n\n  while((skuIndex=Find_Patch(patchFile,MAX_PATH,config))!=0)\n    Apply_Patch(patchFile,config,skuIndex);\n\n  Delete_Patches(config);  // delete all patches\n\n  for (int i=1; i<argc; i++)\n  {\n    strcat(proc.args,\" \");\n    strcat(proc.args,argv[i]);\n  }\n  DBGMSG(\"ARGS: \"<<proc.args);\n\n  while(1)\n  {\n    myChdir(argv[0]);\n    Create_Process(proc);\n    Wait_Process(proc);\n\n    if((skuIndex=Find_Patch(patchFile,MAX_PATH,config))!=0)\n    {\n      do\n      {\n        Apply_Patch(patchFile,config,skuIndex);\n      } while((skuIndex=Find_Patch(patchFile,MAX_PATH,config))!=0);\n    }\n    else\n    {\n      break;\n    }\n  }\n  myChdir(cwd);\n\n  // Exit normally\n\n  return(0);\n}\n\n\n\n\n//\n// Create a primary window\n//\nvoid CreatePrimaryWin(char *prefix)\n{\n  HWND                hwnd;\n  WNDCLASS            wc;\n  char                name[256];\n\n  sprintf(name,\"launcher_%s\",prefix);\n\n  DBGMSG(\"CreatePrimary: \"<<name);\n\n  /*\n  ** set up and register window class\n  */\n  wc.style = CS_HREDRAW | CS_VREDRAW;\n  wc.lpfnWndProc = DefWindowProc;\n  wc.cbClsExtra = 0;            // Don't need any extra class data\n  wc.cbWndExtra = 0;            // No extra win data\n  wc.hInstance = Global_instance;\n  wc.hIcon=LoadIcon(Global_instance, MAKEINTRESOURCE(IDI_ICON));\n  wc.hCursor = NULL;  /////////LoadCursor( NULL, IDC_ARROW );\n  wc.hbrBackground = NULL;\n  wc.lpszMenuName = name;\n  wc.lpszClassName = name;\n  RegisterClass( &wc );\n    \n  /*\n  ** create a window\n  */\n  hwnd = CreateWindowEx(\n      WS_EX_TOPMOST,\n      name,\n      name,\n      WS_POPUP,\n      0, 0,\n      GetSystemMetrics( SM_CXSCREEN ),\n      GetSystemMetrics( SM_CYSCREEN ),\n      NULL,\n      NULL,\n      Global_instance,\n      NULL );\n\n  if( !hwnd )\n  {\n    DBGMSG(\"Couldn't make window!\");\n  }\n  else\n  {\n    DBGMSG(\"Window created!\");\n  }\n}\n\n\n//void DestroyPrimaryWin(void)\n//{\n//  DestroyWindow(PrimaryWin);\n//  UnregisterClass(classname);\n//}\n\n\n\n//\n// If given a file, it'll goto it's directory.  If on a diff drive,\n//   it'll go there.\n//\nvoid myChdir(char *path)\n{\n  char drive[10];\n  char dir[255];\n  char file[255];\n  char ext[64];\n  char filepath[513];\n  int  abc;\n\n  _splitpath( path, drive, dir, file, ext );\n  _makepath ( filepath,   drive, dir, NULL, NULL );\n\n  if ( filepath[ strlen( filepath ) - 1 ] == '\\\\' ) \n  {\n    filepath[ strlen( filepath ) - 1 ] = '\\0';\n  }\n  abc = (unsigned)( toupper( filepath[0] ) - 'A' + 1 ); \n  if ( !_chdrive( abc )) \n  {\n    abc = chdir( filepath );  // Will fail with ending '\\\\'\n  }\n  // should be in proper folder now....\n}\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "LAUNCHER/MONOD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"monod.h\"\n\nMonoD::MonoD(void)\n{\n#ifdef _WIN32\n  unsigned long retval;\n  handle = CreateFile(\"\\\\\\\\.\\\\MONO\", GENERIC_READ|GENERIC_WRITE, 0, NULL,\n                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n\n  if (handle != INVALID_HANDLE_VALUE)\n  {\n    DeviceIoControl(handle, (DWORD)IOCTL_MONO_CLEAR_SCREEN, NULL, 0, NULL, 0,\n                     &retval,0);\n  }\n#endif\n}\n\nMonoD::~MonoD()\n{\n  #ifdef _WIN32\n    CloseHandle(handle);\n    handle=NULL;\n  #endif\n}\n\nint MonoD::print(const char *str, int len)\n{\n  #ifdef _WIN32\n    unsigned long retval;\n    WriteFile(handle, str, len, &retval, NULL);\n    //DeviceIoControl(handle, (DWORD)IOCTL_MONO_PRINT_RAW, (void *)str, len, NULL, 0,\n    //                 &retval,0);\n    return(len);\n  #else\n    for (int i=0; i<len; i++)\n      fprintf(stderr,\"%c\",str[i]); \n    return(len);\n  #endif\n}\n"
  },
  {
    "path": "LAUNCHER/MONOD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef MONOD_HEADER\n#define MONOD_HEADER\n\n\n#include <stdlib.h>\n#include <stdio.h>\n#include \"odevice.h\"\n\n///////////////////////// WIN32 ONLY ///////////////////////////////////\n\n#ifdef _WIN32\n#include <windows.h>\n#include <winioctl.h>\n\n\n/*\n**  This is the identifier for the Monochrome Display Driver\n*/\n#define FILE_DEVICE_MONO 0x00008000\n\n/*\n**      These are the IOCTL commands supported by the Monochrome Display Driver.\n*/\n#define IOCTL_MONO_HELP_SCREEN  CTL_CODE(FILE_DEVICE_MONO, 0x800, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_CLEAR_SCREEN CTL_CODE(FILE_DEVICE_MONO, 0x801, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_PRINT_RAW            CTL_CODE(FILE_DEVICE_MONO, 0x802, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_SET_CURSOR           CTL_CODE(FILE_DEVICE_MONO, 0x803, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_SCROLL                       CTL_CODE(FILE_DEVICE_MONO, 0x804, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_BRING_TO_TOP CTL_CODE(FILE_DEVICE_MONO, 0x805, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_SET_ATTRIBUTE        CTL_CODE(FILE_DEVICE_MONO, 0x806, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_PAN                          CTL_CODE(FILE_DEVICE_MONO, 0x807, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_LOCK                         CTL_CODE(FILE_DEVICE_MONO, 0x808, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_UNLOCK                       CTL_CODE(FILE_DEVICE_MONO, 0x809, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_SET_WINDOW           CTL_CODE(FILE_DEVICE_MONO, 0x80A, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_RESET_WINDOW CTL_CODE(FILE_DEVICE_MONO, 0x80B, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_SET_FLAG             CTL_CODE(FILE_DEVICE_MONO, 0x80C, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_CLEAR_FLAG           CTL_CODE(FILE_DEVICE_MONO, 0x80D, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_FILL_ATTRIB  CTL_CODE(FILE_DEVICE_MONO, 0x80E, METHOD_BUFFERED, FILE_WRITE_DATA)\n\n#endif  // ifdef _WIN32\n\nclass MonoD : public OutputDevice\n{\n public:\n                   MonoD();\n                  ~MonoD();\n\n   virtual int    print(const char *str,int len);\n\n private:\n   #ifdef _WIN32\n     HANDLE handle;\n   #endif\n};\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/ODEVICE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef ODEVICE_HEADER\n#define ODEVICE_HEADER\n\n// This virtual base class provides an interface for output devices\n//  that can be used for the debugging package.\nclass OutputDevice\n{\n public:\n                 OutputDevice() {}\n    virtual     ~OutputDevice() {};\n    virtual int print(const char *s,int len)=0;\n};\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/PATCH.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*****************************************************************************\\\n          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\n*******************************************************************************\n File:       patch.cpp\n Programmer: Neal Kettler\n \n StartDate:  Feb  6, 1998\n LastUpdate: Feb 10, 1998\n-------------------------------------------------------------------------------\n\nThis is where all the code is for applying various types of patches.\n\n\\*****************************************************************************/\n\n\n#include \"patch.h\"\n#include <shellapi.h>\n#include <direct.h>\n\n\n//\n// For the text box showing patch info\n//\nBOOL CALLBACK Update_Info_Proc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)\n{\n\n  static int unselectText=0;\n\n  switch(iMsg) \n  {\n    case WM_INITDIALOG:\n    {\n      FILE *in = fopen(\"launcher.txt\",\"r\");\n      if (in==NULL)\n      {\n        EndDialog(hwnd,-1);\n        return(1);\n      }\n\n      char   line[270];\n      int    lastsel=0;\n      char  *cptr=NULL;\n      while(fgets(line,255,in))\n      {\n        //Get rid of any trailing junk\n        while(1)\n        {\n          if (strlen(line)<1)\n            break;\n          cptr=line+(strlen(line))-1;\n          if ((*cptr=='\\r')||(*cptr=='\\n'))\n            *cptr=0;\n          else\n            break;\n        }\n        // ...and add back the gunk that windows likes\n        strcat(line,\"\\r\\r\\n\");\n        \n\t     SendDlgItemMessage(hwnd, IDC_TEXT, EM_SETSEL, (WPARAM)lastsel, (LPARAM)lastsel );\n\t     SendDlgItemMessage(hwnd, IDC_TEXT, EM_REPLACESEL, 0, (LPARAM)(line) );\n\t     SendDlgItemMessage(hwnd, IDC_TEXT, EM_GETSEL, (WPARAM)NULL, (LPARAM)&lastsel );\n      }\n      unselectText=1;\n      fclose(in);\n\n      return(1);   // 1 means windows handles focus issues\n    }\n    break;\n\n    case WM_PAINT:\n      if (unselectText)\n        SendDlgItemMessage(hwnd, IDC_TEXT, EM_SETSEL, -1, 0);\n      unselectText=0;\n      return(0);\n    break;\n\n\n    case WM_COMMAND:\n      switch(wParam) {\n        case IDOK:\n        {\n          EndDialog(hwnd,0);\n          return(1);\n        }\n        default:\n        break;\n      }\n      default:\n    break;\n    case WM_CLOSE:\n      EndDialog(hwnd,0);\n      return(1);\n    break;\n  }\n  return(FALSE);\n}\n\n\n\n\n\n\n\n// Restart the computer for certain types of patches\nvoid Shutdown_Computer_Now(void);\n\n\nLPVOID CALLBACK __export PatchCallBack(UINT ID, LPVOID Param);\n\ntypedef LPVOID (CALLBACK* PATCHCALLBACK)(UINT, LPVOID);\ntypedef\tUINT (CALLBACK *PATCHFUNC)( LPSTR, PATCHCALLBACK, BOOL);\n\n//\n//  Apply any type of patch.  Filename in patchfile.  Product base registry\n//    (eg: \"SOFTWARE\\Westwood\\Red Alert\") should be in the config file as\n//  SKUX SKU base reg dir   where X = index\n//\nvoid Apply_Patch(char *patchfile,ConfigFile &config,int skuIndex)\n{\n  DBGMSG(\"PATCHFILE : \"<<patchfile);\n  char cwdbuf[256];\n  _getcwd(cwdbuf,255);\n  DBGMSG(\"CWD : \"<<cwdbuf);\n\n  //\n  // If patch is a .exe type patch\n  //\n  if (strcasecmp(patchfile+strlen(patchfile)-strlen(\".exe\"),\".exe\")==0)\n  {\n    // Set this as a run once service thing\n    HKEY   regKey;\n    LONG   regRetval;\n    DWORD  regPrevious;\n    regRetval=RegCreateKeyEx(\n      HKEY_LOCAL_MACHINE,\n      \"SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\RunOnce\",\n      0,\n      \"\",\n      REG_OPTION_NON_VOLATILE,\n      KEY_ALL_ACCESS,\n      NULL,\n      &regKey,\n      &regPrevious);\n\n    if (regRetval==ERROR_SUCCESS)\n    {\n      RegSetValueEx(regKey,\"EXEPatch\",0,REG_SZ,(const uint8*)patchfile,strlen(patchfile)+1);\n\n      char message[256];\n      LoadString(NULL,IDS_SYS_RESTART,message,256);\n      char title[128];\n      LoadString(NULL,IDS_SYS_RESTART_TITLE,title,128);\n\n      MessageBox(NULL,message,title,MB_OK);\n\n      Shutdown_Computer_Now();\n    }\n    else\n    {\n      char message[256];\n      LoadString(NULL,IDS_RUNONCE_ERR,message,256);\n      char string[256];\n      sprintf(string,message,patchfile);\n      MessageBox(NULL,string,\"ERROR\",MB_OK);\n    }\n  }\n  //\n  // RTPatch type patch\n  //\n  else if (strcasecmp(patchfile+strlen(patchfile)-strlen(\".rtp\"),\".rtp\")==0)\n  {\n    MSG msg;\n    HWND dialog=Create_Patch_Dialog();\n    while(PeekMessage(&msg,NULL,0,0, PM_REMOVE))\n    {\n      TranslateMessage(&msg);\n      DispatchMessage(&msg);\n    }\n    HINSTANCE hInst=LoadLibrary(\"patchw32.dll\");\n    if (hInst==NULL)\n    {\n      char message[256];\n      LoadString(NULL,IDS_ERR_MISSING_FILE,message,256);\n      char string[256];\n      sprintf(string,message,\"patchw32.dll\");\n      char title[128];\n      LoadString(NULL,IDS_ERROR,title,128);\n      MessageBox(NULL,string,title,MB_OK);\n      return;\n    }\n\n    DBGMSG(\"Patch SKU = \"<<skuIndex);\n\n\n    PATCHFUNC patchFunc;\n    patchFunc=(PATCHFUNC)GetProcAddress(hInst,\"RTPatchApply32@12\");\n    if (patchFunc==NULL)\n    {\n      char message[256];\n      LoadString(NULL,IDS_BAD_LIBRARY,message,256);\n      char title[128];\n      LoadString(NULL,IDS_ERROR,title,128);\n      MessageBox(NULL,message,title,MB_OK);\n      return;\n    }\n\n    char patchArgs[200];\n    sprintf(patchArgs,\"\\\"%s\\\" .\",patchfile);\n    int rtpErrCode=patchFunc(patchArgs,PatchCallBack,TRUE);\n    FreeLibrary(hInst);     // unload the DLL\n    _unlink(patchfile);     // delete the patch\n\n    DestroyWindow(dialog);  // get rid of the dialog\n\n    // Now we have to update the registry so the version is correct\n    // The version is the first integer in the filename\n    // Eg: 22456_patch.rtp  means version 22456 goes into the registry\n\n    // The version# starts after the last '\\' char\n    char   *cptr=patchfile;\n    char   *tempPtr;\n    DWORD   version;\n    while( (tempPtr=strchr(cptr,'\\\\')) !=NULL)\n      cptr=tempPtr+1;\n    if (cptr)\n      version=atol(cptr);\n    DBGMSG(\"VERSION TO = \"<<version);\n    \n\n    char      string[256];\n    Wstring   key;\n    // Get the InstallPath from the specified registry key\n    sprintf(string,\"SKU%d\",skuIndex);\n    if (config.getString(string,key)==FALSE)\n    {\n      ERRMSGX(\"SKU is missing from config file!\", \"D:\\\\dev\\\\launcher\\\\patch.cpp\"); //ERRMSG(\"SKU is missing from config file!\");\n      return;\n    }\n\n    int       temp=0;\n    Wstring   sku;\n    Wstring   path;\n    temp=key.getToken(temp,\" \",sku);\n    path=key;\n    path.remove(0,temp);\n    while((*(path.get()))==' ')  // remove leading spaces\n      path.remove(0,1);\n    // Open the registry key for modifying now...\n    HKEY regKey;\n    LONG regRetval;\n    regRetval=RegOpenKeyEx(HKEY_LOCAL_MACHINE,path.get(),0,\n        KEY_ALL_ACCESS,&regKey);\n    if (regRetval!=ERROR_SUCCESS)\n      DBGMSG(\"Can't open reg key for writing\");\n    regRetval=RegSetValueEx(regKey,\"Version\",0,REG_DWORD,(uint8 *)&version,\n        sizeof(version));\n\n\n    // Create blocking DLG for update info\n    DialogBox(Global_instance,MAKEINTRESOURCE(IDD_CHANGELOG),NULL,(DLGPROC)Update_Info_Proc);\n  }\n  //\n  // Execute now (without rebooting) type patch\n  //\n  else if (strcasecmp(patchfile+strlen(patchfile)-strlen(\".exn\"),\".exn\")==0)\n  {\n    Process proc;\n    strcpy(proc.directory,\".\");\n    strcpy(proc.command,patchfile);\n    Create_Process(proc);\n    Wait_Process(proc);\n    _unlink(patchfile);\n  }\n  //\n  // Web link type patch\n  //\n  // Im about 99.44% sure that this is completely useless.\n  //\n  else if (strcasecmp(patchfile+strlen(patchfile)-strlen(\".web\"),\".web\")==0)\n  {\n    char message[256];\n    LoadString(NULL,IDS_WEBPATCH,message,256);\n    char title[128];\n    LoadString(NULL,IDS_WEBPATCH_TITLE,title,128);\n    MessageBox(NULL,message,title,MB_OK);\n\n    FILE *in=fopen(patchfile,\"r\");\n    if (in!=NULL)\n    {\n      char URL[256];\n      fgets(URL,255,in);\n      fclose(in);\n      ShellExecute(NULL,NULL,URL,NULL,\".\",SW_SHOW);\n      _unlink(patchfile);\n      //// This is somewhat skanky, but we can't wait\n      //// for the viewer to exit (I tried).\n      exit(0);\n    }\n    else\n    {\n      MessageBox(NULL,patchfile,\"Patchfile vanished?\",MB_OK);\n    }\n  }\n}\n\n\n\nvoid Shutdown_Computer_Now(void)\n{\n  HANDLE hToken; \n  TOKEN_PRIVILEGES tkp; \n \n  // Get a token for this process. \n  if (!OpenProcessToken(GetCurrentProcess(), \n        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) \n  {\n    //error(\"OpenProcessToken\"); \n  }\n \n  // Get the LUID for the shutdown privilege. \n  LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, \n        &tkp.Privileges[0].Luid); \n \n  tkp.PrivilegeCount = 1;  // one privilege to set    \n  tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; \n \n  // Get the shutdown privilege for this process. \n  AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, \n        (PTOKEN_PRIVILEGES)NULL, 0); \n \n  // Cannot test the return value of AdjustTokenPrivileges. \n  if (GetLastError() != ERROR_SUCCESS) \n  {\n    //error(\"AdjustTokenPrivileges\"); \n  }\n \n  // Shut down the system and force all applications to close. \n  if (!ExitWindowsEx(EWX_REBOOT, 0))\n  {\n    // Should never happen\n    char restart[128];\n    LoadString(NULL,IDS_MUST_RESTART,restart,128);\n    MessageBox(NULL,restart,\"OK\",MB_OK);\n    exit(0);\n  }\n\n  MSG     msg;\n  while (GetMessage(&msg, NULL, 0, 0))\n  {\n    TranslateMessage( &msg );\n    DispatchMessage( &msg );\n  }\n}\n\n\n\n//\n// Callback during the patching process\n//\nLPVOID CALLBACK __export PatchCallBack(UINT Id, LPVOID Param)\n{\n  char         string[128];\n  static int   fileCount=0;    // number of files to be patched\n  static int   currFile=0;\n\n  // Make sure our windows get updated\n  MSG     msg;\n  int     counter=0;\n  while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE ))\n  {\n    TranslateMessage( &msg );\n    DispatchMessage( &msg );\n    counter++;\n    if (counter==100)     // just in case...\n      break;\n  }\n\n  LPVOID RetVal=\"\";\n  bit8 Abort=FALSE;\n\n  //// using the global Dialog pointer, set the current \"error\" code\n  //g_DlgPtr->SetRTPErrCode(Id);\n\n  int percent;\n\n  switch( Id )\n  {\n   case 1:\n\tcase 2:\n      // Warning message header/text\n\t  DBGMSG(\"P_MSG: \"<<((char *)Param));\n\tbreak;\n\n\tcase 3:\n      // Error message header\n     DBGMSG(\"P_MSG: \"<<((char *)Param));\n\tbreak;\n\n\tcase 4:\n\t  // Error message header/text\n      ///////*g_LogFile << (char *)Parm << endl;\n      MessageBox(NULL,(char *)Param,\"ERROR\",MB_OK);\n      {\n        FILE *out=fopen(\"patch.err\",\"a\");\n        time_t  timet=time(NULL);\n        fprintf(out,\"\\n\\nPatch Erorr: %s\\n\",ctime(&timet));\n        fprintf(out,\"%s\\n\",(char *)Param);\n        fclose(out);\n      }\n\tbreak;\n\n    case 9:\n      // progress message\n    break;\n\n    case 0xa:\n\t  // help message\n\tbreak;\n\n\tcase 0xb:\n\t  // patch file comment\n\tbreak;\n\n\tcase 0xc:\n\t  // copyright message\n\tbreak;  // these just display text\n\n    case 5:\n\t  // % completed\n\t  // so adjust the progress bar using the global Dialog pointer\n\t  /////////g_DlgPtr->SetProgressBar((int)((float)(*(UINT *)Parm)/(float)0x8000*(float)100));\n      percent=((*(UINT *)Param)*100)/0x8000;\n      SendMessage(GetDlgItem(PatchDialog,IDC_PROGRESS2),PBM_SETPOS,percent,0);\n\tbreak;\n\n\tcase 6:\n\t  // Number of patch files\n      DBGMSG(\"6: \"<<*((uint32 *)Param));\n      fileCount=*((uint32 *)Param);\n      currFile=0;\n\tbreak;\n\n\tcase 7:\n\t  //// begin patch\n\t  //LoadString(g_AppInstance, IDS_PROCESSING, lpcBuf, 256);\n\t  //strcpy(buf,lpcBuf);\n\t  //strcat(buf,(char *)Parm);\n\t  //g_DlgPtr->SetProgressText(buf);\n\t  //*g_LogFile << buf << \" : \";\n\t  //fileModified = true;\n\n      DBGMSG(\"7: \"<<(char *)Param);\n      SetWindowText(GetDlgItem(PatchDialog,IDC_FILENAME),(char *)Param);\n      percent=0;\n      SendMessage(GetDlgItem(PatchDialog,IDC_PROGRESS2),PBM_SETPOS,percent,0);\n\n      currFile++;\n      char xofy[64];\n      LoadString(NULL,IDS_FILE_X_OF_Y,xofy,64);\n      sprintf(string,xofy,currFile,fileCount);\n      SetWindowText(GetDlgItem(PatchDialog,IDC_CAPTION),string);\n\n\tbreak;\n\n\tcase 8:\n\t  //// end patch\n\t  //LoadString(g_AppInstance, IDS_PROCCOMPLETE, lpcBuf, 256);\n\t  //g_DlgPtr->SetProgressText(lpcBuf);\n\t  //*g_LogFile << \" complete\" << endl;\n      percent=100;\n      SendMessage(GetDlgItem(PatchDialog,IDC_PROGRESS2),PBM_SETPOS,percent,0);\n\t\tDBGMSG(\"P_DONE\");\n\tbreak;\n\n\tcase 0xd:\n\t  //// this one shouldn't happen (only occurs if the command line\n\t  ////   doesn't have a patch file in it, and we insure that it does).\n\t  //Abort = TRUE;\n\t  //*g_LogFile << \"Incorrect (or none) patch file specified in command line.\" << endl;\n\tbreak;\n\n\tcase 0xe:\n\t  //// this one shouldn't happen either (same reason)\n\t  //Abort = TRUE;\n\t  //*g_LogFile << \"Incorrect (or none) path specified in command line.\" << endl;\n\tbreak;\n\n\tcase 0xf:\n\t  //// Password Dialog\n\tbreak;\n\n\tcase 0x10:\n\t  //// Invalid Password Alert\n\tbreak;\n\n\tcase 0x11:\n\t  //// Disk Change Dialog\n\tbreak;\n\n\tcase 0x12:\n\t  //// Disk Change Alert\n\tbreak;\n\n\tcase 0x13:\n\t  //// Confirmation Dialog\n\tbreak;\n\n\tcase 0x14:\n\t  //// Location Dialog\n\t  //Abort = TRUE;\n      //*g_LogFile << \"Specified path is incorrect.\" << endl;\n\tbreak;\n\n\tcase 0x16:\n\t  //// Searching Call-back\n\tbreak;\n\n\tcase 0x15:\n\t //// Idle...\n    break;\n\n\tdefault:\n\tbreak;\n  }\n\n  if(Abort)\n    return (NULL);\n  else\n\treturn (RetVal);\n}\n"
  },
  {
    "path": "LAUNCHER/PATCH.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef PATCH_HEADER\n#define PATCH_HEADER\n\n#include \"winblows.h\"\n#include \"dialog.h\"\n#include \"resource.h\"\n#include \"wdebug.h\"\n#include \"process.h\"\n\nvoid Apply_Patch(char *patchfile,ConfigFile &config,int skuIndex);\n\n// Print an error message\n#define ERRMSGX(X,F)\\\n{\\\n  char     timebuf[40]; \\\n  time_t   clock=time(NULL); \\\n  strcpy(timebuf,ctime(&clock)); \\\n  if (MsgManager::errorStream()) \\\n    (*(MsgManager::errorStream())) << \"ERR \" << timebuf << \" [\" << \\\n        F <<  \" \" << __LINE__ << \"] \" << X << endl; \\\n}\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/PROCESS.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"process.h\"\n\nProcess::Process()\n{ \n  directory[0]=0;\n  command[0]=0;\n  args[0]=0;\n  hProcess=NULL;\n  hThread=NULL;\n}\n\n// Create a process\nbit8 Create_Process(Process &process)\n{\n    int                      retval;\n    STARTUPINFO              si;\n    PROCESS_INFORMATION      piProcess;\n    ZeroMemory(&si,sizeof(si));\n    si.cb=sizeof(si);\n \n    char cmdargs[513];\n    memset(cmdargs,0,513);\n    strcpy(cmdargs,process.command);\n    strcat(cmdargs,process.args);\n\n    retval=CreateProcess(NULL,cmdargs,NULL,NULL,FALSE, 0  ,NULL, NULL/*process.directory*/,&si,&piProcess);\n\n    process.hProcess=piProcess.hProcess;\n    process.hThread=piProcess.hThread;\n    return(TRUE);\n}\n\nbit8 Wait_Process(Process &process)\n{\n  DWORD retval;\n  retval=WaitForSingleObject(process.hProcess,INFINITE);\n  if (retval==WAIT_OBJECT_0)  // process exited\n    return(TRUE);\n  else                        // can this happen?\n    return(FALSE);\n}\n\n\n//\n// Get the process to run from the config object\n//\nbit8 Read_Process_Info(ConfigFile &config,OUT Process &info)\n{\n\n Wstring procinfo;\n if (config.getString(\"RUN\",procinfo)==FALSE)\n {\n   DBGMSG(\"Couldn't read the RUN line\");\n   return(FALSE);\n }\n int          offset=0;\n Wstring      dir;\n Wstring      executable;\n Wstring      args;\n offset=procinfo.getToken(offset,\" \",dir);\n offset=procinfo.getToken(offset,\" \",executable);\n args=procinfo;\n args.remove(0,offset);\n\n ///\n ///\n DBGMSG(\"RUN: EXE = \"<<executable.get()<<\"  DIR = \"<<dir.get()<<\n   \"  ARGS = \"<<args.get());\n strcpy(info.command,executable.get());\n strcpy(info.directory,dir.get());\n strcpy(info.args,args.get());\n return(TRUE);\n \n\n/*********************************************************\n  FILE     *in;\n  char      string[256];\n  bit8      found_space;\n  int       i;\n\n  if ((in=fopen(config,\"r\"))==NULL)\n    return(FALSE);\n\n  while(fgets(string,256,in))\n  {\n    i=0;\n    while ((isspace(string[i]))&&(i<int(strlen(string))))\n      i++;\n\n    // do nothing with empty line or commented line\n    if ((string[i]=='#')||(i==int(strlen(string)-1)))\n      continue;\n\n    strcpy(info.directory,string);\n    found_space=FALSE;\n    for (; i<int(strlen(string)); i++)\n    {\n      if (isspace(info.directory[i]))\n      {\n        info.directory[i]=0;\n        found_space=TRUE;\n      }\n      else if (found_space)\n        break;\n    }\n\n    strcpy(info.command,string+i);\n    for (i=0; i<int(strlen(info.command)); i++)\n      if ((info.command[i]=='\\n')||(info.command[i]=='\\r'))\n        info.command[i]=0;\n\n    //printf(\"DIR = '%s'  CMD = '%s'\\n\",info.directory,info.command);\n\n    // We only have 1 process for this\n    break;\n  }\n  fclose(in);\n  return(TRUE);\n**********************************************/\n}\n"
  },
  {
    "path": "LAUNCHER/PROCESS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef PROCESS_HEADER\n#define PROCESS_HEADER\n\n#include <windows.h>\n#include \"wstypes.h\"\n#include \"wdebug.h\"\n#include \"configfile.h\"\n\nclass Process\n{\n public:\n           Process();\n\n  char     directory[256];\n  char     command[256];\n  char     args[256];\n  HANDLE   hProcess;\n  HANDLE   hThread;\n};\n\nbit8 Read_Process_Info(ConfigFile &config,OUT Process &info);\nbit8 Create_Process(Process &process);\nbit8 Wait_Process(Process &process);\n\n\n#endif"
  },
  {
    "path": "LAUNCHER/RESOURCE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n//{{NO_DEPENDENCIES}}\n// Microsoft Developer Studio generated include file.\n// Used by launcher1.rc\n//\n#define IDS_SYS_RESTART                 1\n#define IDS_SYS_RESTART_TITLE           2\n#define IDS_WEBPATCH                    3\n#define IDS_WEBPATCH_TITLE              4\n#define IDS_FILE_X_OF_Y                 5\n#define IDS_MUST_RESTART                6\n#define IDS_RUNONCE_ERR                 7\n#define IDS_ERROR                       8\n#define IDS_ERR_MISSING_FILE            9\n#define IDS_BAD_LIBRARY                 10\n#define IDD_DIALOG1                     101\n#define IDI_ICON1                       102\n#define IDD_CHANGELOG                   103\n#define IDI_ICON                        108\n#define IDI_ICON2                       112\n#define IDI_ICON3                       117\n#define IDC_PROGRESS2                   1001\n#define IDC_SPLASH                      1004\n#define IDC_FILENAME                    1009\n#define IDC_CAPTION                     1010\n#define IDC_TEXT                        1011\n\n// Next default values for new objects\n// \n#ifdef APSTUDIO_INVOKED\n#ifndef APSTUDIO_READONLY_SYMBOLS\n#define _APS_NEXT_RESOURCE_VALUE        118\n#define _APS_NEXT_COMMAND_VALUE         40001\n#define _APS_NEXT_CONTROL_VALUE         1013\n#define _APS_NEXT_SYMED_VALUE           101\n#endif\n#endif\n"
  },
  {
    "path": "LAUNCHER/STREAMER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#include \"streamer.h\"\n#ifdef _WIN32\n  #include <windows.h>\n#endif\n\n\nStreamer::Streamer() : streambuf()\n{\n  int state=unbuffered();\n  unbuffered(0);  // 0 = buffered, 1 = unbuffered\n}\n \nStreamer::~Streamer()\n{\n  sync();\n  delete[](base());\n}\n\nint Streamer::setOutputDevice(OutputDevice *device)\n{\n  Output_Device=device;\n  return(0);\n}\n\n\n// put n chars from string into buffer\nint Streamer::xsputn(const char* buf, int size) //implementation of sputn\n{\n\n  if (size<=0)  // Nothing to do\n    return(0);\n\n  const unsigned char *ptr=(const unsigned char *)buf;\n  for (int i=0; i<size; i++, ptr++)\n  {\n    if(*ptr=='\\n')\n    {\n      if (overflow(*ptr)==EOF)\n        return(i);\n    }\n    else if (sputc(*ptr)==EOF)\n      return(i);\n  }\n  return(size);\n}\n\n// Flush the buffer and make more room if needed\nint Streamer::overflow(int c)\n{\n\n  if (c==EOF)\n    return(sync());\n  if ((pbase()==0) && (doallocate()==0))\n    return(EOF);\n  if((pptr() >= epptr()) && (sync()==EOF))\n    return(EOF);\n  else {\n    sputc(c);\n    if ((unbuffered() && c=='\\n' || pptr() >= epptr())\n        && sync()==EOF) {\n      return(EOF);\n    }\n    return(c);\n  }\n}\n\n// This is a write only stream, this should never happen\nint Streamer::underflow(void)\n{\n  return(EOF);\n}\n\nint Streamer::doallocate()\n{\n\n  if (base()==NULL)\n  {\n    char *buf=new char[(2*STREAMER_BUFSIZ)];   // deleted by destructor\n    memset(buf,0,2*STREAMER_BUFSIZ);\n\n    // Buffer\n    setb(\n       buf,         // base pointer\n       buf+STREAMER_BUFSIZ,  // ebuf pointer (end of buffer);\n       0);          // 0 = manual deletion of buff \n\n    // Get area\n    setg(\n        buf,   // eback \n        buf,   // gptr\n        buf);  // egptr\n\n    buf+=STREAMER_BUFSIZ;\n    // Put area\n    setp(buf,buf+STREAMER_BUFSIZ);\n    return(1);\n  }\n  else\n    return(0);\n}\n\n\nint Streamer::sync()\n{\n  if (pptr()<=pbase()) {\n    return(0);\n  }\n\n  int wlen=pptr()-pbase();\n\n  if (Output_Device)\n  {\n    Output_Device->print(pbase(),wlen);\n  }\n\n  if (unbuffered()) {\n    setp(pbase(),pbase());\n  }\n  else {\n    setp(pbase(),pbase()+STREAMER_BUFSIZ);\n  }\n  return(0);\n}\n"
  },
  {
    "path": "LAUNCHER/STREAMER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef STREAMER_HEADER\n#define STREAMER_HEADER\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <iostream.h>\n#include <string.h>\n\n#include \"odevice.h\"\n\n#ifndef STREAMER_BUFSIZ\n// This limits the number of characters that can be sent to a single 'print'\n// call.  If your debug message is bigger than this, it will get split over\n// multiple 'print' calls.  That's usually not a problem.\n #define STREAMER_BUFSIZ 2048\n#endif\n\n\n// Provide a streambuf interface for a class that can 'print'\nclass Streamer : public streambuf\n{\n public:\n               Streamer();\n    virtual   ~Streamer();\n\n    int        setOutputDevice(OutputDevice *output_device);\n\n protected:\n    // Virtual methods from streambuf\n    int       xsputn(const char* s, int n); // buffer some characters\n    int       overflow(int = EOF);          // flush buffer and make more room\n    int       underflow(void);              // Does nothing\n    int       sync();\n\n    int       doallocate();                 // allocate a buffer\n\n\n    OutputDevice  *Output_Device;\n};\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/UTIL/FILED.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef FILED_HEADER\n#define FILED_HEADER\n\n#include \"odevice.h\"\n\nclass FileD : public OutputDevice\n{\n public:\n   FileD(char *filename)\n   { \n     out=fopen(filename,\"w\");\n     if (out==NULL)\n       out=fopen(\"FileDev.out\",\"w\");\n   }\n\n   virtual ~FileD()\n   { fclose(out); }\n\n   virtual int print(const char *str,int len)\n   {\n     char *string=new char[len+1];\n     memset(string,0,len+1);\n     memcpy(string,str,len);\n     fprintf(out,\"%s\",string);\n     delete[](string);\n     fflush(out);\n     return(len);\n   }\n\n   FILE      *out;\n};\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/UTIL/MBOXD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef MBOXD_HEADER\n#define MBOXD_HEADER\n\n#include \"odevice.h\"\n\nclass MboxD : public OutputDevice\n{\n public:\n\n   virtual int print(const char *str,int len)\n   {\n     char *string=new char[len+1];\n     memset(string,0,len+1);\n     memcpy(string,str,len);\n     MessageBox(NULL,string,\"Debug Message\", MB_OK | MB_ICONINFORMATION);\n     delete[](string);\n     return(len);\n   }\n\n};\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/UTIL/MONOD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"monod.h\"\n\nMonoD::MonoD(void)\n{\n#ifdef _WIN32\n  unsigned long retval;\n  handle = CreateFile(\"\\\\\\\\.\\\\MONO\", GENERIC_READ|GENERIC_WRITE, 0, NULL,\n                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n\n  if (handle != INVALID_HANDLE_VALUE)\n  {\n    DeviceIoControl(handle, (DWORD)IOCTL_MONO_CLEAR_SCREEN, NULL, 0, NULL, 0,\n                     &retval,0);\n  }\n#endif\n}\n\nMonoD::~MonoD()\n{\n  #ifdef _WIN32\n    CloseHandle(handle);\n    handle=NULL;\n  #endif\n}\n\nint MonoD::print(const char *str, int len)\n{\n  #ifdef _WIN32\n    unsigned long retval;\n    WriteFile(handle, str, len, &retval, NULL);\n    ////DeviceIoControl(handle, (DWORD)IOCTL_MONO_PRINT_RAW, (void *)str, len, NULL, 0,\n    ////                 &retval,0);\n    return(len);\n  #else\n    for (int i=0; i<len; i++)\n      fprintf(stderr,\"%c\",str[i]); \n    return(len);\n  #endif\n}\n"
  },
  {
    "path": "LAUNCHER/UTIL/MONOD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef MONOD_HEADER\n#define MONOD_HEADER\n\n\n#include <stdlib.h>\n#include <stdio.h>\n#include \"odevice.h\"\n\n///////////////////////// WIN32 ONLY ///////////////////////////////////\n\n#ifdef _WIN32\n#include <windows.h>\n#include <winioctl.h>\n\n\n/*\n**  This is the identifier for the Monochrome Display Driver\n*/\n#define FILE_DEVICE_MONO 0x00008000\n\n/*\n**      These are the IOCTL commands supported by the Monochrome Display Driver.\n*/\n#define IOCTL_MONO_HELP_SCREEN  CTL_CODE(FILE_DEVICE_MONO, 0x800, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_CLEAR_SCREEN CTL_CODE(FILE_DEVICE_MONO, 0x801, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_PRINT_RAW            CTL_CODE(FILE_DEVICE_MONO, 0x802, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_SET_CURSOR           CTL_CODE(FILE_DEVICE_MONO, 0x803, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_SCROLL                       CTL_CODE(FILE_DEVICE_MONO, 0x804, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_BRING_TO_TOP CTL_CODE(FILE_DEVICE_MONO, 0x805, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_SET_ATTRIBUTE        CTL_CODE(FILE_DEVICE_MONO, 0x806, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_PAN                          CTL_CODE(FILE_DEVICE_MONO, 0x807, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_LOCK                         CTL_CODE(FILE_DEVICE_MONO, 0x808, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_UNLOCK                       CTL_CODE(FILE_DEVICE_MONO, 0x809, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_SET_WINDOW           CTL_CODE(FILE_DEVICE_MONO, 0x80A, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_RESET_WINDOW CTL_CODE(FILE_DEVICE_MONO, 0x80B, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_SET_FLAG             CTL_CODE(FILE_DEVICE_MONO, 0x80C, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_CLEAR_FLAG           CTL_CODE(FILE_DEVICE_MONO, 0x80D, METHOD_BUFFERED, FILE_WRITE_DATA)\n#define IOCTL_MONO_FILL_ATTRIB  CTL_CODE(FILE_DEVICE_MONO, 0x80E, METHOD_BUFFERED, FILE_WRITE_DATA)\n\n#endif  // ifdef _WIN32\n\nclass MonoD : public OutputDevice\n{\n public:\n                   MonoD();\n                  ~MonoD();\n\n   virtual int    print(const char *str,int len);\n\n private:\n   #ifdef _WIN32\n     HANDLE handle;\n   #endif\n};\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/UTIL/ODEVICE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef ODEVICE_HEADER\n#define ODEVICE_HEADER\n\n// This virtual base class provides an interface for output devices\n//  that can be used for the debugging package.\nclass OutputDevice\n{\n public:\n                 OutputDevice() {}\n    virtual     ~OutputDevice() {};\n    virtual int print(const char *s,int len)=0;\n};\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/UTIL/STDERRD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef STDERRD_HEADER\n#define STDERRD_HEADER\n\n#include \"odevice.h\"\n\nclass StderrD : public OutputDevice\n{\n public:\n\n   virtual int print(const char *str,int len)\n   {\n     char *string=new char[len+1];\n     memset(string,0,len+1);\n     memcpy(string,str,len);\n     fprintf(stderr,\"%s\",string);\n     delete[](string);\n     return(len);\n   }\n};\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/UTIL/STDOUTD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef STDOUTD_HEADER\n#define STDOUTD_HEADER\n\n#include \"odevice.h\"\n\nclass StdoutD : public OutputDevice\n{\n public:\n\n   virtual int print(const char *str,int len)\n   {\n     char *string=new char[len+1];\n     memcpy(string,str,len);\n     string[len]=0;\n     fprintf(stdout,\"%s\",string);\n     fflush(stdout);\n     delete[](string);\n     return(len);\n   }\n};\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/UTIL/STREAMER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#include \"streamer.h\"\n#ifdef _WIN32\n  #include <windows.h>\n#endif\n\n\nStreamer::Streamer() : streambuf()\n{\n  int state=unbuffered();\n  unbuffered(0);  // 0 = buffered, 1 = unbuffered\n}\n \nStreamer::~Streamer()\n{\n  sync();\n  delete[](base());\n}\n\nint Streamer::setOutputDevice(OutputDevice *device)\n{\n  Output_Device=device;\n  return(0);\n}\n\n\n// put n chars from string into buffer\nint Streamer::xsputn(const char* buf, int size) //implementation of sputn\n{\n  if (size<=0)  // Nothing to do\n    return(0);\n\n  const unsigned char *ptr=(const unsigned char *)buf;\n  for (int i=0; i<size; i++, ptr++)\n  {\n    if(*ptr=='\\n')\n    {\n      if (overflow(*ptr)==EOF)\n        return(i);\n    }\n    else if (sputc(*ptr)==EOF)\n      return(i);\n  }\n  return(size);\n}\n\n// Flush the buffer and make more room if needed\nint Streamer::overflow(int c)\n{\n  if (c==EOF)\n    return(sync());\n  if ((pbase()==0) && (doallocate()==0))\n    return(EOF);\n  if((pptr() >= epptr()) && (sync()==EOF))\n    return(EOF);\n  else {\n    sputc(c);\n    if ((unbuffered() && c=='\\n' || pptr() >= epptr())\n        && sync()==EOF) {\n      return(EOF);\n    }\n    return(c);\n  }\n}\n\n// This is a write only stream, this should never happen\nint Streamer::underflow(void)\n{\n  return(EOF);\n}\n\nint Streamer::doallocate()\n{\n  if (base()==NULL)\n  {\n    char *buf=new char[(2*STREAMER_BUFSIZ)];   // deleted by destructor\n    memset(buf,0,2*STREAMER_BUFSIZ);\n\n    // Buffer\n    setb(\n       buf,         // base pointer\n       buf+STREAMER_BUFSIZ,  // ebuf pointer (end of buffer);\n       0);          // 0 = manual deletion of buff \n\n    // Get area\n    setg(\n        buf,   // eback \n        buf,   // gptr\n        buf);  // egptr\n\n    buf+=STREAMER_BUFSIZ;\n    // Put area\n    setp(buf,buf+STREAMER_BUFSIZ);\n    return(1);\n  }\n  else\n    return(0);\n}\n\n\nint Streamer::sync()\n{\n  if (pptr()<=pbase()) {\n    return(0);\n  }\n\n  int wlen=pptr()-pbase();\n\n  if (Output_Device)\n  {\n    Output_Device->print(pbase(),wlen);\n  }\n\n  if (unbuffered()) {\n    setp(pbase(),pbase());\n  }\n  else {\n    setp(pbase(),pbase()+STREAMER_BUFSIZ);\n  }\n  return(0);\n}\n"
  },
  {
    "path": "LAUNCHER/UTIL/STREAMER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef STREAMER_HEADER\n#define STREAMER_HEADER\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <iostream.h>\n#include <string.h>\n\n#include \"odevice.h\"\n\n#ifndef STREAMER_BUFSIZ\n// This limits the number of characters that can be sent to a single 'print'\n// call.  If your debug message is bigger than this, it will get split over\n// multiple 'print' calls.  That's usually not a problem.\n #define STREAMER_BUFSIZ 2048\n#endif\n\n\n// Provide a streambuf interface for a class that can 'print'\nclass Streamer : public streambuf\n{\n public:\n               Streamer();\n    virtual   ~Streamer();\n\n    int        setOutputDevice(OutputDevice *output_device);\n\n protected:\n    // Virtual methods from streambuf\n    int       xsputn(const char* s, int n); // buffer some characters\n    int       overflow(int = EOF);          // flush buffer and make more room\n    int       underflow(void);              // Does nothing\n    int       sync();\n\n    int       doallocate();                 // allocate a buffer\n\n\n    OutputDevice  *Output_Device;\n};\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/UTIL/SYSLOGD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"syslogd.h\"\n\nSyslogD::SyslogD(char *ident,int logopt,int facility,int _priority)\n{\n  openlog(ident,logopt,facility);\n  priority=_priority;\n}\n\nint SyslogD::print(const char *str, int len)\n{\n  char *temp_str=new char[len+1];\n  memset(temp_str,0,len+1);\n  strncpy(temp_str,str,len);\n  syslog(priority,temp_str);\n  delete[](temp_str);\n  return(len);\n}\n"
  },
  {
    "path": "LAUNCHER/UTIL/SYSLOGD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef SYSLOGD_HEADER\n#define SYSLOGD_HEADER\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <syslog.h>\n#include <string.h>\n#include \"odevice.h\"\n\nclass SyslogD : public OutputDevice\n{\n public:\n   SyslogD(char *ident,int logopt,int facility,int priority);\n   virtual int print(const char *str,int len);\n\n private:\n   int priority;\n};\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/UTIL/WDEBUG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include <stdlib.h>\n#include \"wdebug.h\"\n#include \"streamer.h\"\n#include \"odevice.h\"\n\n\nstatic MsgManager         *msg_manager=NULL;\n\nstatic int                debug_enabled=0;\nstatic ostream           *debug_ostream=NULL;\nstatic Streamer           debug_streamer;\n\nstatic int                info_enabled=0;\nstatic ostream           *info_ostream=NULL;\nstatic Streamer           info_streamer;\n\nstatic int                warn_enabled=0;\nstatic ostream           *warn_ostream=NULL;\nstatic Streamer           warn_streamer;\n\nstatic int                error_enabled=0;\nstatic ostream           *error_ostream=NULL;  \nstatic Streamer           error_streamer;\n\n\n// Don't dare touch this semaphore in application code!\nSem4                      DebugLibSemaphore;\n\n\nint MsgManager::setAllStreams(OutputDevice *device)\n{\n  if (device==NULL)\n    return(1);\n\n  DebugLibSemaphore.Wait();\n  debug_streamer.setOutputDevice(device);\n  delete(debug_ostream);\n  debug_ostream=new ostream(&debug_streamer);\n\n  info_streamer.setOutputDevice(device);\n  delete(info_ostream);\n  info_ostream=new ostream(&info_streamer);\n\n  warn_streamer.setOutputDevice(device);\n  delete(warn_ostream);\n  warn_ostream=new ostream(&warn_streamer);\n\n  error_streamer.setOutputDevice(device);\n  delete(error_ostream);\n  error_ostream=new ostream(&error_streamer);\n\n  DebugLibSemaphore.Post();\n\n  return(0);\n}\n\n\nint MsgManager::setDebugStream(OutputDevice *device)\n{\n  if (device==NULL)\n    return(1);\n\n  DebugLibSemaphore.Wait();\n  debug_streamer.setOutputDevice(device);\n  delete(debug_ostream);\n  debug_ostream=new ostream(&debug_streamer);\n  DebugLibSemaphore.Post();\n  return(0);\n}\n\nint MsgManager::setInfoStream(OutputDevice *device)\n{\n  if (device==NULL)\n    return(1);\n\n  DebugLibSemaphore.Wait();\n  info_streamer.setOutputDevice(device);\n  delete(info_ostream);\n  info_ostream=new ostream(&info_streamer);\n  DebugLibSemaphore.Post();\n  return(0);\n}\n\nint MsgManager::setWarnStream(OutputDevice *device)\n{\n  if (device==NULL)\n    return(1);\n\n  DebugLibSemaphore.Wait();\n  warn_streamer.setOutputDevice(device);\n  delete(warn_ostream);\n  warn_ostream=new ostream(&warn_streamer);\n  DebugLibSemaphore.Post();\n  return(0);\n}\n\nint MsgManager::setErrorStream(OutputDevice *device)\n{\n  if (device==NULL)\n    return(1);\n\n  DebugLibSemaphore.Wait();\n  error_streamer.setOutputDevice(device);\n  delete(error_ostream);\n  error_ostream=new ostream(&error_streamer);\n  DebugLibSemaphore.Post();\n  return(0);\n}\n\n\n\nostream *MsgManager::debugStream(void)\n{\n  return(debug_ostream);\n}   \n\nostream *MsgManager::infoStream(void)\n{\n  return(info_ostream);\n}   \n\nostream *MsgManager::warnStream(void)\n{\n  return(warn_ostream);\n}\n\nostream *MsgManager::errorStream(void)\n{\n  return(error_ostream);\n}   \n"
  },
  {
    "path": "LAUNCHER/UTIL/WDEBUG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*****************************************************************************\\\nwdebug                        Neal Kettler\n\nMT-LEVEL\n    MT-Safe\n\nThe debugging module is pretty good for debugging and it has some message\nprinting stuff as well.  The basic idea is that you write a class that\ninherits from OutputDevice (severall are provided) and assign that output\ndevice to a stream.  There are seperate streams for debugging, information,\nwarning, and error messages.  Each one can have a seperate output device,\nor they can all have the same one.  Debugging messages only get compiled\nin if your module defines 'DEBUG'. If you don't define debug, then not even\nthe text of the debugging message gets into the binary.   All the other\noutput streams get printed regardless of whether DEBUG is defined.\n\nSample usage:\nFileD debug_device(\"gameres.debug\");     // create a file device\nMsgManager::setDebugStream(&debug_device);\nDBGMSG(\"This debug message #\" << 1 << \" you use C++ streams\");\n\nNote that since these are defines you really don't need to put a semicolon\nat the end, and it can be bad in situations like this:\n\nif (x)\n  DBGMSG(\"Stuff is broken\");\nelse\n  DBGMSG(\"Stuff is NOT broken\");\n\nThis won't compile, read the code until you figure it out.  Only then\nwill you be ready to leave grasshopper.\n\n\\*****************************************************************************/\n\n#ifndef WDEBUG_HEADER\n#define WDEBUG_HEADER\n\n#include <iostream.h>\n#include \"sem4.h\"\n#include \"odevice.h\"\n#include \"streamer.h\"\n\n// This is needed because the streams return a pointer.  Every time you\n//  change the output device the old stream is deleted, and a new one\n//  is created.\nextern Sem4 DebugLibSemaphore; \n\n// Print an information message\n#define INFMSG(X)\\\n{\\\n  char     timebuf[40]; \\\n  time_t   clock=time(NULL); \\\n  cftime(timebuf,\"%D %T\",&clock); \\\n  DebugLibSemaphore.Wait(); \\\n  if (MsgManager::infoStream()) \\\n    (*(MsgManager::infoStream())) << \"INF \" << timebuf << \" [\" << \\\n        __FILE__ <<  \" \" << __LINE__ << \"] \" << X << endl; \\\n  DebugLibSemaphore.Post(); \\\n}\n\n// Print a warning message\n#define WRNMSG(X)\\\n{\\\n  char     timebuf[40]; \\\n  time_t   clock=time(NULL); \\\n  cftime(timebuf,\"%D %T\",&clock); \\\n  DebugLibSemaphore.Wait(); \\\n  if (MsgManager::warnStream()) \\\n    (*(MsgManager::warnStream())) << \"WRN \" << timebuf << \" [\" << \\\n        __FILE__ <<  \" \" << __LINE__ << \"] \" << X << endl; \\\n  DebugLibSemaphore.Post(); \\\n}\n\n// Print an error message\n#define ERRMSG(X)\\\n{\\\n  char     timebuf[40]; \\\n  time_t   clock=time(NULL); \\\n  cftime(timebuf,\"%D %T\",&clock); \\\n  DebugLibSemaphore.Wait(); \\\n  if (MsgManager::errorStream()) \\\n    (*(MsgManager::errorStream())) << \"ERR \" << timebuf << \" [\" << \\\n        __FILE__ <<  \" \" << __LINE__ << \"] \" << X << endl; \\\n  DebugLibSemaphore.Post(); \\\n}\n\n\n// Just get a stream to the information device, no extra junk\n#define INFSTREAM(X)\\\n{\\\n  DebugLibSemaphore.Wait(); \\\n  if (MsgManager::infoStream()) \\\n    (*(MsgManager::infoStream())) << X;\\\n  DebugLibSemaphore.Post(); \\\n}    \n\n// Just get a stream to the warning device, no extra junk\n#define WRNSTREAM(X)\\\n{\\\n  DebugLibSemaphore.Wait(); \\\n  if (MsgManager::warnStream()) \\\n    (*(MsgManager::warnStream())) << X;\\\n  DebugLibSemaphore.Post(); \\\n}    \n\n// Just get a stream to the error device, no extra junk\n#define ERRSTREAM(X)\\\n{\\\n  DebugLibSemaphore.Wait(); \\\n  if (MsgManager::errorStream()) \\\n    (*(MsgManager::errorStream())) << X;\\\n  DebugLibSemaphore.Post(); \\\n}    \n\n#ifndef DEBUG\n\n// No debugging, no debug messages.\n// Note that anything enclosed in \"DBG()\" will NOT get executed\n// unless DEBUG is defined.\n// They are defined to {} for consistency when DEBUG is defined\n\n#define DBG(X)\n#define DBGSTREAM(X)  {}\n#define PVAR(v)       {}\n#define DBGMSG(X)     {}\n#define VERBOSE(X)    {}\n\n#else  // DEBUG _is_ defined\n\n// Execute only if in debugging mode\n#define DBG(X) X\n\n// Print a variable\n#define PVAR(v) \\\n{ \\\n  DebugLibSemaphore.Wait(); \\\n  if (MsgManager::debugStream()) \\\n    (*(MsgManager::debugStream())) << __FILE__ << \"[\" << __LINE__ << \\\n       \"]: \" << ##V << \" = \" << V << endl; \\\n  DebugLibSemaphore.Post(); \\\n}\n\n\n#define DBGMSG(X)\\\n{\\\n  DebugLibSemaphore.Wait(); \\\n  if (MsgManager::debugStream()) \\\n    (*(MsgManager::debugStream())) << \"DBG [\" << __FILE__ <<  \\\n    \" \" << __LINE__ << \"] \" << X << endl;\\\n  DebugLibSemaphore.Post(); \\\n}\n\n// Just get a stream to the debugging device, no extra junk\n#define DBGSTREAM(X)\\\n{\\\n  DebugLibSemaphore.Wait(); \\\n  if (MsgManager::debugStream()) \\\n    (*(MsgManager::debugStream())) << X;\\\n  DebugLibSemaphore.Post(); \\\n}    \n\n// Verbosely execute a statement\n#define VERBOSE(X)\\\n{ \\\n  DebugLibSemaphore.Wait(); \\\n  if (MsgManager::debugStream()) \\\n    (*(DebugManager::debugStream())) << __FILE__ << \"[\" << __LINE__ << \\\n     \"]: \" << ##X << endl; X \\\n  DebugLibSemaphore.Post(); \\\n}\n\n#endif  // DEBUG\n\n\nclass MsgManager\n{\n protected:\n   MsgManager();\n\n public:\n   static int                 setAllStreams(OutputDevice *device);\n   static int                 setDebugStream(OutputDevice *device);\n   static int                 setInfoStream(OutputDevice *device);\n   static int                 setWarnStream(OutputDevice *device);\n   static int                 setErrorStream(OutputDevice *device);\n\n   static void                enableDebug(int flag);\n   static void                enableInfo(int flag);\n   static void                enableWarn(int flag);\n   static void                enableError(int flag);\n\n   static ostream            *debugStream(void);\n   static ostream            *infoStream(void);\n   static ostream            *warnStream(void);\n   static ostream            *errorStream(void);\n};\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/WDEBUG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include <stdlib.h>\n#include \"wdebug.h\"\n#include \"streamer.h\"\n#include \"odevice.h\"\n\n\nstatic MsgManager         *msg_manager=NULL;\n\nstatic int                debug_enabled=0;\nstatic ostream           *debug_ostream=NULL;\nstatic Streamer           debug_streamer;\n\nstatic int                info_enabled=0;\nstatic ostream           *info_ostream=NULL;\nstatic Streamer           info_streamer;\n\nstatic int                warn_enabled=0;\nstatic ostream           *warn_ostream=NULL;\nstatic Streamer           warn_streamer;\n\nstatic int                error_enabled=0;\nstatic ostream           *error_ostream=NULL;  \nstatic Streamer           error_streamer;\n\n\n\nint MsgManager::setAllStreams(OutputDevice *device)\n{\n  if (device==NULL)\n    return(1);\n\n\n  debug_streamer.setOutputDevice(device);\n  delete(debug_ostream);\n  debug_ostream=new ostream(&debug_streamer);\n\n  info_streamer.setOutputDevice(device);\n  delete(info_ostream);\n  info_ostream=new ostream(&info_streamer);\n\n  warn_streamer.setOutputDevice(device);\n  delete(warn_ostream);\n  warn_ostream=new ostream(&warn_streamer);\n\n  error_streamer.setOutputDevice(device);\n  delete(error_ostream);\n  error_ostream=new ostream(&error_streamer);\n\n  return(0);\n}\n\n\nint MsgManager::setDebugStream(OutputDevice *device)\n{\n  if (device==NULL)\n    return(1);\n\n \n  debug_streamer.setOutputDevice(device);\n  delete(debug_ostream);\n  debug_ostream=new ostream(&debug_streamer);\n\n  return(0);\n}\n\nint MsgManager::setInfoStream(OutputDevice *device)\n{\n  if (device==NULL)\n    return(1);\n\n\n  info_streamer.setOutputDevice(device);\n  delete(info_ostream);\n  info_ostream=new ostream(&info_streamer);\n\n  return(0);\n}\n\nint MsgManager::setWarnStream(OutputDevice *device)\n{\n  if (device==NULL)\n    return(1);\n\n\n  warn_streamer.setOutputDevice(device);\n  delete(warn_ostream);\n  warn_ostream=new ostream(&warn_streamer);\n\n  return(0);\n}\n\nint MsgManager::setErrorStream(OutputDevice *device)\n{\n  if (device==NULL)\n    return(1);\n\n\n  error_streamer.setOutputDevice(device);\n  delete(error_ostream);\n  error_ostream=new ostream(&error_streamer);\n\n  return(0);\n}\n\n\n\nostream *MsgManager::debugStream(void)\n{\n  return(debug_ostream);\n}   \n\nostream *MsgManager::infoStream(void)\n{\n  return(info_ostream);\n}   \n\nostream *MsgManager::warnStream(void)\n{\n  return(warn_ostream);\n}\n\nostream *MsgManager::errorStream(void)\n{\n  return(error_ostream);\n}   \n"
  },
  {
    "path": "LAUNCHER/WDEBUG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*****************************************************************************\\\nwdebug                        Neal Kettler\n\nMT-LEVEL\n    MT-UnSafe! (UNIX version is safe though)\n\nThe debugging module is pretty good for debugging and it has some message\nprinting stuff as well.  The basic idea is that you write a class that\ninherits from OutputDevice (severall are provided) and assign that output\ndevice to a stream.  There are seperate streams for debugging, information,\nwarning, and error messages.  Each one can have a seperate output device,\nor they can all have the same one.  Debugging messages only get compiled\nin if your module defines 'DEBUG'. If you don't define debug, then not even\nthe text of the debugging message gets into the binary.   All the other\noutput streams get printed regardless of whether DEBUG is defined.\n\nSample usage:\nFileD debug_device(\"gameres.debug\");     // create a file device\nMsgManager::setDebugStream(&debug_device);\nDBGMSG(\"This debug message #\" << 1 << \" you use C++ streams\");\n\nNote that since these are defines you really don't need to put a semicolon\nat the end, and it can be bad in situations like this:\n\nif (x)\n  DBGMSG(\"Stuff is broken\");\nelse\n  DBGMSG(\"Stuff is NOT broken\");\n\nThis won't compile, read the code until you figure it out.  Only then\nwill you be ready to leave grasshopper.\n\n\\*****************************************************************************/\n\n#ifndef WDEBUG_HEADER\n#define WDEBUG_HEADER\n\n#include <iostream.h>\n#include \"odevice.h\"\n#include \"streamer.h\"\n#include <time.h>\n\n\n\n// Print an information message\n#define INFMSG(X)\\\n{\\\n  char     timebuf[40]; \\\n  time_t   clock=time(NULL); \\\n  cftime(timebuf,\"%D %T\",&clock); \\\n  if (MsgManager::infoStream()) \\\n    (*(MsgManager::infoStream())) << \"INF \" << timebuf << \" [\" << \\\n        __FILE__ <<  \" \" << __LINE__ << \"] \" << X << endl; \\\n}\n\n// Print a warning message\n#define WRNMSG(X)\\\n{\\\n  char     timebuf[40]; \\\n  time_t   clock=time(NULL); \\\n  cftime(timebuf,\"%D %T\",&clock); \\\n  if (MsgManager::warnStream()) \\\n    (*(MsgManager::warnStream())) << \"WRN \" << timebuf << \" [\" << \\\n        __FILE__ <<  \" \" << __LINE__ << \"] \" << X << endl; \\\n}\n\n// Print an error message\n#define ERRMSG(X)\\\n{\\\n  char     timebuf[40]; \\\n  time_t   clock=time(NULL); \\\n  strcpy(timebuf,ctime(&clock)); \\\n  if (MsgManager::errorStream()) \\\n    (*(MsgManager::errorStream())) << \"ERR \" << timebuf << \" [\" << \\\n        __FILE__ <<  \" \" << __LINE__ << \"] \" << X << endl; \\\n}\n\n\n// Just get a stream to the information device, no extra junk\n#define INFSTREAM(X)\\\n{\\\n  if (MsgManager::infoStream()) \\\n    (*(MsgManager::infoStream())) << X;\\\n}    \n\n// Just get a stream to the warning device, no extra junk\n#define WRNSTREAM(X)\\\n{\\\n  if (MsgManager::warnStream()) \\\n    (*(MsgManager::warnStream())) << X;\\\n}    \n\n// Just get a stream to the error device, no extra junk\n#define ERRSTREAM(X)\\\n{\\\n  if (MsgManager::errorStream()) \\\n    (*(MsgManager::errorStream())) << X;\\\n}    \n\n#ifndef DEBUG\n\n// No debugging, no debug messages.\n// Note that anything enclosed in \"DBG()\" will NOT get executed\n// unless DEBUG is defined.\n// They are defined to {} for consistency when DEBUG is defined\n\n#define DBG(X)\n#define DBGSTREAM(X)  {}\n#define PVAR(v)       {}\n#define DBGMSG(X)     {}\n#define VERBOSE(X)    {}\n\n#else  // DEBUG _is_ defined\n\n// Execute only if in debugging mode\n#define DBG(X) X\n\n// Print a variable\n#define PVAR(v) \\\n{ \\\n  if (MsgManager::debugStream()) \\\n    (*(MsgManager::debugStream())) << __FILE__ << \"[\" << __LINE__ << \\\n       \"]: \" << ##V << \" = \" << V << endl; \\\n}\n\n\n#define DBGMSG(X)\\\n{\\\n  if (MsgManager::debugStream()) \\\n    (*(MsgManager::debugStream())) << \"DBG [\" << __FILE__ <<  \\\n    \" \" << __LINE__ << \"] \" << X << endl;\\\n}\n\n// Just get a stream to the debugging device, no extra junk\n#define DBGSTREAM(X)\\\n{\\\n  if (MsgManager::debugStream()) \\\n    (*(MsgManager::debugStream())) << X;\\\n}    \n\n// Verbosely execute a statement\n#define VERBOSE(X)\\\n{ \\\n  if (MsgManager::debugStream()) \\\n    (*(DebugManager::debugStream())) << __FILE__ << \"[\" << __LINE__ << \\\n     \"]: \" << ##X << endl; X \\\n}\n\n#endif  // DEBUG\n\n\nclass MsgManager\n{\n protected:\n   MsgManager();\n\n public:\n   static int                 setAllStreams(OutputDevice *device);\n   static int                 setDebugStream(OutputDevice *device);\n   static int                 setInfoStream(OutputDevice *device);\n   static int                 setWarnStream(OutputDevice *device);\n   static int                 setErrorStream(OutputDevice *device);\n\n   static void                enableDebug(int flag);\n   static void                enableInfo(int flag);\n   static void                enableWarn(int flag);\n   static void                enableError(int flag);\n\n   static ostream            *debugStream(void);\n   static ostream            *infoStream(void);\n   static ostream            *warnStream(void);\n   static ostream            *errorStream(void);\n};\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/WINBLOWS.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <windowsx.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n\n#include \"winblows.h\"\n\n\nHINSTANCE Global_instance;\nLPSTR     Global_commandline;\nint       Global_commandshow;\n\n\n/*\n * WinMain - initialization, message loop\n */\nint PASCAL WinMain( HINSTANCE instance, HINSTANCE, char *command_line, int command_show)\n{\n    //////MSG         msg;\n\n    Global_instance = instance;\n    Global_commandline = command_line;\n    Global_commandshow = command_show;\n\n    int         argc;\n    char       *argv[64];\n\n    char        path_to_exe[512];\n    GetModuleFileName(instance,(char *)&path_to_exe,512);\n    argc=1;\n    argv[0]=path_to_exe;\n\n\n    int   command_scan=0;\n    char  command_char;\n    do \n    {\n      /*\n      ** Scan for non-space character on command line\n      */\n      do \n      {\n        command_char = *( command_line+command_scan++ );\n      } while ( command_char==' ' );\n\n      if ( command_char!=0 && command_char != 13 )\n      {\n        argv[argc++]=command_line+command_scan-1;\n\n        /*\n        ** Scan for space character on command line\n        */\n        do\n        {\n          command_char = *( command_line+command_scan++ );\n        } while ( command_char!=' ' && command_char != 0 && command_char!=13);\n                *( command_line+command_scan-1 ) = 0;\n      }\n\n    } while ( command_char != 0 && command_char != 13 && argc<20 );\n\n    return(main(argc,argv));\n\n} /* WinMain */\n\n\nint Print_WM(UINT message,char *out)\n{\n  switch(message)\n  {\n    case WM_NULL:\n      sprintf(out,\"WM_NULL\");\n      break;\n    case WM_CREATE:\n      sprintf(out,\"WM_CREATE\");\n      break;\n    case WM_DESTROY:\n      sprintf(out,\"WM_DESTROY\");\n      break;\n    case WM_CANCELMODE:\n      sprintf(out,\"WM_CANCELMODE\");\n      break;\n    case WM_ERASEBKGND:\n      sprintf(out,\"WM_ERASEBKGND\");\n      break;\n    case WM_GETTEXT:\n      sprintf(out,\"WM_GETTEXT\");\n      break;\n    case WM_QUERYOPEN:\n      sprintf(out,\"WM_QUERYOPEN\");\n      break;\n    case WM_MOVE:\n      sprintf(out,\"WM_MOVE\");\n      break;\n    case WM_SIZE:\n      sprintf(out,\"WM_SIZE\");\n      break;\n    case WM_ACTIVATE:\n      sprintf(out,\"WM_ACTIVATE\");\n      break;\n    case WM_SETFOCUS:\n      sprintf(out,\"WM_SETFOCUS\");\n      break;\n    case WM_KILLFOCUS:\n      sprintf(out,\"WM_KILLFOCUS\");\n      break;\n    case WM_ENABLE:\n      sprintf(out,\"WM_ENABLE\");\n      break;\n    case WM_SETREDRAW:\n      sprintf(out,\"WM_REDRAW\");\n      break;\n    case WM_PAINT:\n      sprintf(out,\"WM_PAINT\");\n      break;\n    case WM_CLOSE:\n      sprintf(out,\"WM_CLOSE\");\n      break;\n    case WM_QUIT:\n      sprintf(out,\"WM_QUIT\");\n      break;\n    case WM_ACTIVATEAPP:\n      sprintf(out,\"WM_ACTIVATEAPP\");\n      break;\n    case WM_SETCURSOR:\n      sprintf(out,\"WM_SETCURSOR\");\n      break;\n    case WM_KEYDOWN:\n      sprintf(out,\"WM_KEYDOWN\");\n      break;\n    case WM_MOUSEMOVE:\n      sprintf(out,\"WM_MOUSEMOVE\");\n      break;\n    case WM_WINDOWPOSCHANGING:\n      sprintf(out,\"WM_WINDOWPOSCHANGING\");\n      break;\n    case WM_WINDOWPOSCHANGED:\n      sprintf(out,\"WM_WINDOWPOSCHANGED\");\n      break;\n    case WM_DISPLAYCHANGE:\n      sprintf(out,\"WM_DISPLAYCHANGE\");\n      break;\n    case WM_NCPAINT:\n      sprintf(out,\"WM_NCPAINT\");\n      break;\n    case WM_PALETTEISCHANGING:\n      sprintf(out,\"WM_PALETTEISCHANGING\");\n      break;\n    case WM_PALETTECHANGED:\n      sprintf(out,\"WM_PALETTECHANGED\");\n      break;\n    case WM_NCACTIVATE:\n      sprintf(out,\"WM_NCACTIVATE\");\n      break;\n    case WM_NCCALCSIZE:\n      sprintf(out,\"WM_NCCALCSIZE\");\n      break;\n    case WM_SYSCOMMAND:\n      sprintf(out,\"WM_SYSCOMMAND\");\n      break;\n    default:\n      sprintf(out,\"? UNKNOWN ?\");\n      return(-1);\n  }\n  return(0);\n}\n"
  },
  {
    "path": "LAUNCHER/WINBLOWS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef WINBLOWS_HEADER\n#define WINBLOWS_HEADER\n\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <windowsx.h>\n#include <stdlib.h>\n\n#include\"wstypes.h\"\n\n  extern HINSTANCE Global_instance;\n  extern LPSTR     Global_commandline;\n  extern int       Global_commandshow;\n\n  extern int       main(int argc, char *argv[]);\n\n  int              Print_WM(UINT wm,char *out);\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/WSTRING.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\\\n*        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         *\n******************************************************************************\nProject Name: Carpenter  (The RedAlert ladder creator)\nFile Name   : string.cpp\nAuthor      : Neal Kettler\nStart Date  : June 1, 1997\nLast Update : June 17, 1997  \n\nA fairly typical string class.  This string class always copies any input\nstring to it's own memory (for assignment or construction).\n\\***************************************************************************/\n\n#include <ctype.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n\n#include \"wstring.h\"\n\nWstring::Wstring():str(NULL)\n{ }\n\nWstring::Wstring(IN char *string):str(NULL)\n{ set(string); }\n\nWstring::Wstring(IN const Wstring &other):str(NULL)\n{\n  if (other.str!=NULL)\n  {\n    str=new char[strlen(other.str)+1];\n    strcpy(str,other.str);\n  }\n}\n\nWstring::~Wstring()\n{ clear(); }\n\nbit8 Wstring::operator==(IN char *other)\n{\n  if ((str==NULL)&&(other==NULL))\n    return(TRUE);\n  if(strcmp(str, other) != 0)\n    return(FALSE);\n  else\n   return(TRUE);\n}\n\nbit8 Wstring::operator==(IN Wstring &other)\n{\n if((str == NULL) && (other.str == NULL))\n   return(TRUE);\n\n if((str == NULL) || (other.str == NULL))\n   return(FALSE);\n\n if(strcmp(str, other.str) != 0)\n   return(FALSE);\n else\n   return(TRUE);\n}\n\n\nbit8 Wstring::operator!=(IN char *other)\n{\n if(strcmp(str, other) != 0)\n   return(TRUE);\n else\n   return(FALSE);\n}\n\n\nbit8 Wstring::operator!=(IN Wstring &other)\n{\n if((str == NULL) && (other.str == NULL))\n   return(FALSE);\n\n if((str == NULL) || (other.str == NULL))\n   return(TRUE);\n\n if(strcmp(str, other.str) != 0)\n   return(TRUE);\n else\n   return(FALSE);\n}\n\n\nWstring &Wstring::operator=(char *other)\n{\n  set(other);\n  return(*this);\n}\n\n\nWstring &Wstring::operator=(IN Wstring &other)\n{\n if(*this == other)\n   return(*this);\n\n set(other.get());\n return(*this);\n}\n\n\nbit8 Wstring::cat(IN char *s)\n{\n  char    *oldStr;\n  uint32   len;\n\n  if (s==NULL)   // it's OK to cat nothing\n    return(TRUE);\n\n  // Save the contents of the string.\n  oldStr = str;\n\n  // Determine the length of the resultant string.\n  len = strlen(s) + 1;\n  if(oldStr)\n    len += strlen(oldStr);\n\n  // Allocate memory for the new string.\n\n  if(!(str = new char[(len * sizeof(char))]))\n  {\n    str = oldStr;\n    return(FALSE);\n  }\n\n  // Copy the contents of the old string and concatenate the passed\n  // string.\n  if(oldStr)   strcpy(str, oldStr);\n  else         str[0] = 0;\n\n  strcat(str, s);\n\n  // delete the old string.\n  if(oldStr)\n    delete[](oldStr);\n\n  return(TRUE);\n}\n\n\nbit8 Wstring::cat(uint32 size, IN char *s)\n{\n  char    *oldStr;\n  uint32   len;\n\n  // Save the contents of the string.\n  oldStr = str;\n\n  // Determine the length of the resultant string.\n  len = size + 1;\n  if(oldStr)\n    len += strlen(oldStr);\n\n  // Allocate memory for the new string.\n  if(!(str = new char[(len * sizeof(char))]))\n  {\n    str = oldStr;\n    return(FALSE);\n  }\n\n  // Copy the contents of the old string and concatenate the passed\n  // string.\n  if(oldStr)\n    strcpy(str, oldStr);\n  else\n    str[0] = 0;\n\n  strncat(str, s, size);\n\n  // delete the old string.\n  if(oldStr)\n    delete[](oldStr);\n\n  return(TRUE);\n}\n\nbit8 Wstring::cat(IN Wstring &other)\n{\n  return cat(other.get());\n}\n\nWstring &Wstring::operator+=(IN char *string)\n{\n  cat(string);\n  return(*this);\n}\n\nWstring &Wstring::operator+=(IN Wstring &other)\n{\n  cat(other.get());\n  return(*this);\n}\n\nWstring Wstring::operator+(IN char *string)\n{\n  Wstring temp = *this;\n  temp.cat(string);\n  return(temp);\n}\n\nWstring Wstring::operator+(IN Wstring &s)\n{\n  Wstring temp = *this;\n  temp.cat(s);\n  return(temp);\n}\n\n//\n// This function deletes 'count' characters indexed by `pos' from the Wstring.\n// If `pos'+'count' is > the length of the array, the last 'count' characters\n// of the string are removed.  If an error occurs, FALSE is returned.\n// Otherwise, TRUE is returned.  Note: count has a default value of 1.\n//\n//\nchar Wstring::remove(sint32 pos,sint32 count)\n{\n  char    *s;\n  sint32   len;\n\n  if (!str)\n    return(FALSE);\n\n  len = (sint32)strlen(str);\n\n  if(pos+count > len)\n    pos = len - count;\n  if (pos < 0)\n  {\n    count+=pos;    // If they remove before 0, ignore up till beginning\n    pos=0;\n  }\n  if (count<=0)\n    return(FALSE);\n\n  if(!(s = new char[len-count+1]))\n  {\n    //ErrorMessage(SET_EM, \"Insufficient memory to modify Wstring.\");\n    return(FALSE);\n  }\n\n  ///////DBGMSG(\"Wstring::remove  POS: \"<<pos<<\"  LEN: \"<<len);\n\n  // put nulls on both ends of substring to be removed\n  str[pos] = 0;\n  str[pos+count-1] = 0;\n\n  strcpy(s, str);\n  strcat(s, &(str[pos + count]));\n  delete[](str);\n  str = s;\n\n  return(TRUE);\n}\n\n// Remove all instances of a char from the string\nbit8 Wstring::removeChar(char c)\n{\n  int     len=0;\n  char   *cptr=NULL;\n  bit8    removed=FALSE;\n\n  if (str==NULL)\n    return(FALSE);\n\n  len=strlen(str);\n  while ((cptr=strchr(str,c)) !=NULL)\n  {\n    memmove(cptr,cptr+1,len-1-((int)(cptr-str)));\n    len--;\n    str[len]=0;\n    removed=TRUE;\n  }\n  if (removed)\n  {\n    char *newStr=new char[strlen(str)+1];\n    strcpy(newStr,str);\n    delete[](str);\n    str=newStr; \n  }\n  return(removed);\n}\n\nvoid Wstring::removeSpaces(void)\n{\n  removeChar(' ');\n  removeChar('\\t');\n}\n\nvoid Wstring::clear(void)\n{\n if(str)\n   delete[](str);\n str=NULL;\n}\n\nvoid Wstring::setSize(sint32 size)\n{\n  clear();\n  if (size<0)\n    return;\n  str=new char[size]; \n  memset(str,0,size);\n}\n\nvoid Wstring::cellCopy(char *dest, uint32 len)\n{\n  uint32 i;\n\n  strncpy(dest, str, len);\n  for(i = (uint32)strlen(str); i < len; i++)\n    dest[i] = ' ';\n  dest[len] = 0;\n}\n\nchar *Wstring::get(void)\n{\n  if(!str)\n    return \"\";\n  return str;\n}\n\nchar Wstring::get(uint32 index)\n{\n if(index < strlen(str))\n   return str[index];\n return(0);\n}\n\nuint32 Wstring::length(void)\n{\n  if(str == NULL)\n    return(0);\n  return((uint32)strlen(str));\n}\n\n\n// Insert at given position and shift old stuff to right\nbit8 Wstring::insert(char *instring, uint32 pos)\n{\n  if (str==NULL)\n    return(set(instring)); \n  if (pos>strlen(str))\n    pos=strlen(str);\n  char *newstr=new char[strlen(str)+strlen(instring)+1];\n  memset(newstr,0,strlen(str)+strlen(instring)+1);\n  strcpy(newstr,str);\n  // move the old data out of the way\n  int bytes=strlen(str)+1-pos;\n  memmove(newstr+pos+strlen(instring),newstr+pos,bytes);\n  // move the new data into place\n  memmove(newstr+pos,instring,strlen(instring));\n  delete[](str);\n  str=newstr;\n  return(TRUE);\n}\n\n// This function inserts the character specified by `k' into the string at the\n// position indexed by `pos'.  If `pos' is >= the length of the string, it is\n// appended to the string.  If an error occurs, FALSE is returned.  Otherwise,\n// TRUE is returned.\nbit8 Wstring::insert(char k, uint32 pos)\n{\n  char    *s;\n  uint32   len;\n  char     c[2];\n\n  if(!str)\n  {\n    c[0] = k;\n    c[1] = 0;\n    return(set(c));\n  }\n\n  len = (uint32)strlen(str);\n\n  if(pos > len)\n    pos = len;\n\n  if(!(s = (char *)new char[(len + 2)]))\n  {\n    //ErrorMessage(SET_EM, \"Insufficient memory to modify Wstring.\");\n    return(FALSE);\n  }\n\n  c[0]     = str[pos];\n  str[pos] = 0;\n  c[1]     = 0;\n  strcpy(s, str);\n  str[pos] = c[0];\n  c[0] = k;\n  strcat(s, c);\n  strcat(s, &(str[pos]));\n  delete[](str);\n  str = s;\n\n  return(TRUE);\n}\n\n\n// This function replaces any occurences of the string pointed to by\n// `replaceThis' with the string pointed to by `withThis'.  If an error\n// occurs, FALSE is returned.  Otherwise, TRUE is returned.\nbit8 Wstring::replace(char *replaceThis, char *withThis)\n{\n  Wstring  dest;\n  char    *foundStr, *src;\n  uint32   len;\n\n  src=get();\n  while(src && src[0])\n  {\n    foundStr = strstr(src, replaceThis);\n    if(foundStr)\n    {\n      len = (uint32)foundStr - (uint32)src;\n      if(len)\n      {\n        if(!dest.cat(len, src))\n          return(FALSE);\n      }\n      if(!dest.cat(withThis))\n        return(FALSE);\n      src = foundStr + strlen(replaceThis);\n    }\n    else\n    {\n      if(!dest.cat(src))\n        return(FALSE);\n\n      src=NULL;\n    }\n  }\n  return(set(dest.get()));\n}\n\n\nbit8 Wstring::set(IN char *s)\n{\n uint32 len;\n\n clear();\n\n len = (uint32)strlen(s) + 1;\n\n if(!(str = new char[len]))\n {\n   //ErrorMessage(SET_EM, \"Insufficient memory to set Wstring.\");\n   return(FALSE);\n }\n strcpy(str, s);\n\n return(TRUE);\n}\n\n\nbit8 Wstring::set(char c, uint32 index)\n{\n if(index >= (uint32)strlen(str))\n   return FALSE;\n\n str[index] = c;\n\n return TRUE;\n}\n\n\nchar Wstring::set(uint32 size, IN char *string)\n{\n uint32 len;\n\n clear();\n len = size + 1;\n\n if(!(str = new char[len]))\n {\n   //ErrorMessage(SET_EM, \"Insufficient memory to set Wstring.\");\n   return(FALSE);\n }\n\n // Copy the bytes in the string, and NULL-terminate it.\n strncpy(str, string, size);\n str[size] = 0;\n\n return(TRUE);\n}\n\n\n// This function converts all alphabetical characters in the string to lower\n// case.\nvoid Wstring::toLower(void)\n{\n  uint32 i;\n\n  for(i = 0; i < length(); i++)\n  {\n    if((str[i] >= 'A') && (str[i] <= 'Z'))\n      str[i] = tolower(str[i]);\n  }\n}\n\n\n// This function converts all alphabetical characters in the string to upper\n// case.\nvoid Wstring::toUpper(void)\n{\n  uint32 i;\n\n  for(i = 0; i < length(); i++)\n  {\n    if((str[i] >= 'a') && (str[i] <= 'z'))\n      str[i] = toupper(str[i]);\n  }\n}\n\n\n//  This function truncates the string so its length will match the specified\n// `len'.  If an error occurs, FALSE is returned.  Otherwise, TRUE is returned.\nbit8 Wstring::truncate(uint32 len)\n{\n  Wstring tmp;\n  if(!tmp.set(len, get()) || !set(tmp.get()))\n    return(FALSE);\n  return(TRUE);\n}\n\n// Truncate the string after the character 'c' (gets rid of 'c' as well)\n//   Do nothing if 'c' isn't in the string\nbit8 Wstring::truncate(char c)\n{\n  sint32  len;\n \n  if (str==NULL)\n    return(FALSE);\n\n  char   *cptr=strchr(str,c);\n  if (cptr==NULL)\n    return(FALSE);\n  len=(sint32)(cptr-str); \n  truncate((uint32)len);\n  return(TRUE);\n}\n\n// Get a token from this string that's seperated by one or more\n//  chars from the 'delim' string , start at offset & return offset\nsint32 Wstring::getToken(int offset,char *delim,Wstring &out)\n{\n  int i;\n  sint32 start;\n  sint32 stop;\n  for (i=offset; i<length(); i++) {\n    if(strchr(delim,str[i])==NULL)\n      break;\n  }\n  if (i>=length())\n    return(-1);\n  start=i;\n\n  for (; i<length(); i++) {\n    if(strchr(delim,str[i])!=NULL)\n      break;\n  }\n  stop=i-1; \n  out.set(str+start);\n  out.truncate((uint32)stop-start+1);\n  return(stop+1);\n}\n\n// Get the first line of text after offset.  Lines are terminated by '\\r\\n' or '\\n'\nsint32 Wstring::getLine(int offset, Wstring &out)\n{\n  int i;\n  sint32 start;\n  sint32 stop;\n\n  start=i=offset;\n  if (start >= length())\n    return(-1);\n \n  for (; i<length(); i++) {\n    if(strchr(\"\\r\\n\",str[i])!=NULL)\n      break;\n  }\n  stop=i;\n  if ((str[stop]=='\\r')&&(str[stop+1]=='\\n'))\n    stop++;\n\n  out.set(str+start);\n  out.truncate((uint32)stop-start+1);\n  return(stop+1);\n}\n"
  },
  {
    "path": "LAUNCHER/WSTRING.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\\\n*        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         *\n******************************************************************************\nProject Name: Carpenter  (The RedAlert ladder creator)\nFile Name   : main.cpp\nAuthor      : Neal Kettler\nStart Date  : June 1, 1997\nLast Update : June 17, 1997  \n\\****************************************************************************/\n\n#ifndef WSTRING_HEADER\n#define WSTRING_HEADER\n\n#include <stdio.h>\n#include <stdlib.h>\n#include \"wstypes.h\"\n\nclass Wstring\n{\n public: \n           Wstring();\n           Wstring(IN const Wstring &other);\n           Wstring(IN char *string);\n          ~Wstring();\n\n   void    clear(void);\n\n   bit8    cat(IN char *string);\n   bit8    cat(uint32 size,IN char *string);\n   bit8    cat(IN Wstring &string);\n\n   void    cellCopy(OUT char *dest, uint32 len);\n   char    remove(sint32 pos, sint32 count);\n   bit8    removeChar(char c);\n   void    removeSpaces(void);\n   char   *get(void);\n   char    get(uint32 index);\n   uint32  length(void);\n   bit8    insert(char c, uint32 pos);\n   bit8    insert(char *instring, uint32 pos);\n   bit8    replace(IN char *replaceThis,IN char *withThis);\n   char    set(IN char *str);\n   char    set(uint32 size,IN char *str);\n   bit8    set(char c, uint32 index);\n   void    setSize(sint32 bytes);  // create an empty string\n   void    toLower(void);\n   void    toUpper(void);\n   bit8    truncate(uint32 len);\n   bit8    truncate(char c);  // trunc after char c\n   sint32  getToken(int offset,char *delim,Wstring &out);\n   sint32  getLine(int offset, Wstring &out);\n\n   bit8    operator==(IN char *other);\n   bit8    operator==(IN Wstring &other);\n   bit8    operator!=(IN char *other);\n   bit8    operator!=(IN Wstring &other);\n\n   Wstring  &operator=(IN char *other);\n   Wstring  &operator=(IN Wstring &other);\n   Wstring  &operator+=(IN char *other);\n   Wstring  &operator+=(IN Wstring &other);\n   Wstring   operator+(IN char *other);\n   Wstring   operator+(IN Wstring &other);\n\n private:\n   char    *str;    // Pointer to allocated string.\n};\n\n#endif\n"
  },
  {
    "path": "LAUNCHER/WSTYPES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\\\n*        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         *\n******************************************************************************\nProject Name:\nFile Name   : wtypes.h\nAuthor      : Neal Kettler\nStart Date  : June 3, 1997\nLast Update : June 17, 1997  \n\nStandard type definitions for the sake of portability and readability.\n\\***************************************************************************/\n\n#ifndef WTYPES_HEADER\n#define WTYPES_HEADER\n\n#ifndef TRUE\n#define TRUE               1\n#endif\n\n#ifndef FALSE\n#define FALSE              0\n#endif\n\n#ifndef MIN\n#define MIN(x,y) (((x)<(y))?(x):(y))\n#endif\n\n#ifndef MAX\n#define MAX(x,y) (((x)>(y))?(x):(y))\n#endif\n\n#ifndef NULL\n#define NULL 0\n#endif\n\n//These are used for readability purposes mostly, when a method takes a\n//  pointer or reference these help specify what will happen to the data\n//  that is sent in.\n#define IN\n#define OUT\n#define INOUT\n\ntypedef char               bit8;\ntypedef char               sint8;\ntypedef unsigned char      uint8;\ntypedef signed short int   sint16;\ntypedef unsigned short int uint16;\ntypedef signed int         sint32;\ntypedef unsigned int       uint32;\n\n#define MAX_BIT8    0x1\n#define MAX_UINT32  0xFFFFFFFF\n#define MAX_UINT16  0xFFFF\n#define MAX_UINT8   0xFF\n#define MAX_SINT32  0x7FFFFFFF\n#define MAX_SINT16  0x7FFF\n#define MAX_SINT8   0x7F   \n\n#ifdef _WIN32\n#define strncasecmp _strnicmp\n#define strcasecmp  _stricmp\n#endif  \n\n#endif\n"
  },
  {
    "path": "LICENSE.md",
    "content": "Electronic Arts Inc. has released the source code for Command & Conquer Red Alert\nunder the GPL V3 license below, with additional terms at the bottom.\n\nGNU General Public License\n==========================\n\n_Version 3, 29 June 2007_  \n_Copyright © 2007 Free Software Foundation, Inc. &lt;<http://fsf.org/>&gt;_\n\nEveryone is permitted to copy and distribute verbatim copies of this license\ndocument, but changing it is not allowed.\n\n## Preamble\n\nThe GNU General Public License is a free, copyleft license for software and other\nkinds of works.\n\nThe licenses for most software and other practical works are designed to take away\nyour freedom to share and change the works. By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change all versions of a\nprogram--to make sure it remains free software for all its users. We, the Free\nSoftware Foundation, use the GNU General Public License for most of our software; it\napplies also to any other work released this way by its authors. You can apply it to\nyour programs, too.\n\nWhen we speak of free software, we are referring to freedom, not price. Our General\nPublic Licenses are designed to make sure that you have the freedom to distribute\ncopies of free software (and charge for them if you wish), that you receive source\ncode or can get it if you want it, that you can change the software or use pieces of\nit in new free programs, and that you know you can do these things.\n\nTo protect your rights, we need to prevent others from denying you these rights or\nasking you to surrender the rights. Therefore, you have certain responsibilities if\nyou distribute copies of the software, or if you modify it: responsibilities to\nrespect the freedom of others.\n\nFor example, if you distribute copies of such a program, whether gratis or for a fee,\nyou must pass on to the recipients the same freedoms that you received. You must make\nsure that they, too, receive or can get the source code. And you must show them these\nterms so they know their rights.\n\nDevelopers that use the GNU GPL protect your rights with two steps: **(1)** assert\ncopyright on the software, and **(2)** offer you this License giving you legal permission\nto copy, distribute and/or modify it.\n\nFor the developers' and authors' protection, the GPL clearly explains that there is\nno warranty for this free software. For both users' and authors' sake, the GPL\nrequires that modified versions be marked as changed, so that their problems will not\nbe attributed erroneously to authors of previous versions.\n\nSome devices are designed to deny users access to install or run modified versions of\nthe software inside them, although the manufacturer can do so. This is fundamentally\nincompatible with the aim of protecting users' freedom to change the software. The\nsystematic pattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable. Therefore, we have designed\nthis version of the GPL to prohibit the practice for those products. If such problems\narise substantially in other domains, we stand ready to extend this provision to\nthose domains in future versions of the GPL, as needed to protect the freedom of\nusers.\n\nFinally, every program is threatened constantly by software patents. States should\nnot allow patents to restrict development and use of software on general-purpose\ncomputers, but in those that do, we wish to avoid the special danger that patents\napplied to a free program could make it effectively proprietary. To prevent this, the\nGPL assures that patents cannot be used to render the program non-free.\n\nThe precise terms and conditions for copying, distribution and modification follow.\n\n## TERMS AND CONDITIONS\n\n### 0. Definitions\n\n“This License” refers to version 3 of the GNU General Public License.\n\n“Copyright” also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n“The Program” refers to any copyrightable work licensed under this\nLicense. Each licensee is addressed as “you”. “Licensees” and\n“recipients” may be individuals or organizations.\n\nTo “modify” a work means to copy from or adapt all or part of the work in\na fashion requiring copyright permission, other than the making of an exact copy. The\nresulting work is called a “modified version” of the earlier work or a\nwork “based on” the earlier work.\n\nA “covered work” means either the unmodified Program or a work based on\nthe Program.\n\nTo “propagate” a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for infringement under\napplicable copyright law, except executing it on a computer or modifying a private\ncopy. Propagation includes copying, distribution (with or without modification),\nmaking available to the public, and in some countries other activities as well.\n\nTo “convey” a work means any kind of propagation that enables other\nparties to make or receive copies. Mere interaction with a user through a computer\nnetwork, with no transfer of a copy, is not conveying.\n\nAn interactive user interface displays “Appropriate Legal Notices” to the\nextent that it includes a convenient and prominently visible feature that **(1)**\ndisplays an appropriate copyright notice, and **(2)** tells the user that there is no\nwarranty for the work (except to the extent that warranties are provided), that\nlicensees may convey the work under this License, and how to view a copy of this\nLicense. If the interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n### 1. Source Code\n\nThe “source code” for a work means the preferred form of the work for\nmaking modifications to it. “Object code” means any non-source form of a\nwork.\n\nA “Standard Interface” means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of interfaces\nspecified for a particular programming language, one that is widely used among\ndevelopers working in that language.\n\nThe “System Libraries” of an executable work include anything, other than\nthe work as a whole, that **(a)** is included in the normal form of packaging a Major\nComponent, but which is not part of that Major Component, and **(b)** serves only to\nenable use of the work with that Major Component, or to implement a Standard\nInterface for which an implementation is available to the public in source code form.\nA “Major Component”, in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system (if any) on which\nthe executable work runs, or a compiler used to produce the work, or an object code\ninterpreter used to run it.\n\nThe “Corresponding Source” for a work in object code form means all the\nsource code needed to generate, install, and (for an executable work) run the object\ncode and to modify the work, including scripts to control those activities. However,\nit does not include the work's System Libraries, or general-purpose tools or\ngenerally available free programs which are used unmodified in performing those\nactivities but which are not part of the work. For example, Corresponding Source\nincludes interface definition files associated with source files for the work, and\nthe source code for shared libraries and dynamically linked subprograms that the work\nis specifically designed to require, such as by intimate data communication or\ncontrol flow between those subprograms and other parts of the work.\n\nThe Corresponding Source need not include anything that users can regenerate\nautomatically from other parts of the Corresponding Source.\n\nThe Corresponding Source for a work in source code form is that same work.\n\n### 2. Basic Permissions\n\nAll rights granted under this License are granted for the term of copyright on the\nProgram, and are irrevocable provided the stated conditions are met. This License\nexplicitly affirms your unlimited permission to run the unmodified Program. The\noutput from running a covered work is covered by this License only if the output,\ngiven its content, constitutes a covered work. This License acknowledges your rights\nof fair use or other equivalent, as provided by copyright law.\n\nYou may make, run and propagate covered works that you do not convey, without\nconditions so long as your license otherwise remains in force. You may convey covered\nworks to others for the sole purpose of having them make modifications exclusively\nfor you, or provide you with facilities for running those works, provided that you\ncomply with the terms of this License in conveying all material for which you do not\ncontrol copyright. Those thus making or running the covered works for you must do so\nexclusively on your behalf, under your direction and control, on terms that prohibit\nthem from making any copies of your copyrighted material outside their relationship\nwith you.\n\nConveying under any other circumstances is permitted solely under the conditions\nstated below. Sublicensing is not allowed; section 10 makes it unnecessary.\n\n### 3. Protecting Users' Legal Rights From Anti-Circumvention Law\n\nNo covered work shall be deemed part of an effective technological measure under any\napplicable law fulfilling obligations under article 11 of the WIPO copyright treaty\nadopted on 20 December 1996, or similar laws prohibiting or restricting circumvention\nof such measures.\n\nWhen you convey a covered work, you waive any legal power to forbid circumvention of\ntechnological measures to the extent such circumvention is effected by exercising\nrights under this License with respect to the covered work, and you disclaim any\nintention to limit operation or modification of the work as a means of enforcing,\nagainst the work's users, your or third parties' legal rights to forbid circumvention\nof technological measures.\n\n### 4. Conveying Verbatim Copies\n\nYou may convey verbatim copies of the Program's source code as you receive it, in any\nmedium, provided that you conspicuously and appropriately publish on each copy an\nappropriate copyright notice; keep intact all notices stating that this License and\nany non-permissive terms added in accord with section 7 apply to the code; keep\nintact all notices of the absence of any warranty; and give all recipients a copy of\nthis License along with the Program.\n\nYou may charge any price or no price for each copy that you convey, and you may offer\nsupport or warranty protection for a fee.\n\n### 5. Conveying Modified Source Versions\n\nYou may convey a work based on the Program, or the modifications to produce it from\nthe Program, in the form of source code under the terms of section 4, provided that\nyou also meet all of these conditions:\n\n* **a)** The work must carry prominent notices stating that you modified it, and giving a\nrelevant date.\n* **b)** The work must carry prominent notices stating that it is released under this\nLicense and any conditions added under section 7. This requirement modifies the\nrequirement in section 4 to “keep intact all notices”.\n* **c)** You must license the entire work, as a whole, under this License to anyone who\ncomes into possession of a copy. This License will therefore apply, along with any\napplicable section 7 additional terms, to the whole of the work, and all its parts,\nregardless of how they are packaged. This License gives no permission to license the\nwork in any other way, but it does not invalidate such permission if you have\nseparately received it.\n* **d)** If the work has interactive user interfaces, each must display Appropriate Legal\nNotices; however, if the Program has interactive interfaces that do not display\nAppropriate Legal Notices, your work need not make them do so.\n\nA compilation of a covered work with other separate and independent works, which are\nnot by their nature extensions of the covered work, and which are not combined with\nit such as to form a larger program, in or on a volume of a storage or distribution\nmedium, is called an “aggregate” if the compilation and its resulting\ncopyright are not used to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit. Inclusion of a covered work in an aggregate\ndoes not cause this License to apply to the other parts of the aggregate.\n\n### 6. Conveying Non-Source Forms\n\nYou may convey a covered work in object code form under the terms of sections 4 and\n5, provided that you also convey the machine-readable Corresponding Source under the\nterms of this License, in one of these ways:\n\n* **a)** Convey the object code in, or embodied in, a physical product (including a\nphysical distribution medium), accompanied by the Corresponding Source fixed on a\ndurable physical medium customarily used for software interchange.\n* **b)** Convey the object code in, or embodied in, a physical product (including a\nphysical distribution medium), accompanied by a written offer, valid for at least\nthree years and valid for as long as you offer spare parts or customer support for\nthat product model, to give anyone who possesses the object code either **(1)** a copy of\nthe Corresponding Source for all the software in the product that is covered by this\nLicense, on a durable physical medium customarily used for software interchange, for\na price no more than your reasonable cost of physically performing this conveying of\nsource, or **(2)** access to copy the Corresponding Source from a network server at no\ncharge.\n* **c)** Convey individual copies of the object code with a copy of the written offer to\nprovide the Corresponding Source. This alternative is allowed only occasionally and\nnoncommercially, and only if you received the object code with such an offer, in\naccord with subsection 6b.\n* **d)** Convey the object code by offering access from a designated place (gratis or for\na charge), and offer equivalent access to the Corresponding Source in the same way\nthrough the same place at no further charge. You need not require recipients to copy\nthe Corresponding Source along with the object code. If the place to copy the object\ncode is a network server, the Corresponding Source may be on a different server\n(operated by you or a third party) that supports equivalent copying facilities,\nprovided you maintain clear directions next to the object code saying where to find\nthe Corresponding Source. Regardless of what server hosts the Corresponding Source,\nyou remain obligated to ensure that it is available for as long as needed to satisfy\nthese requirements.\n* **e)** Convey the object code using peer-to-peer transmission, provided you inform\nother peers where the object code and Corresponding Source of the work are being\noffered to the general public at no charge under subsection 6d.\n\nA separable portion of the object code, whose source code is excluded from the\nCorresponding Source as a System Library, need not be included in conveying the\nobject code work.\n\nA “User Product” is either **(1)** a “consumer product”, which\nmeans any tangible personal property which is normally used for personal, family, or\nhousehold purposes, or **(2)** anything designed or sold for incorporation into a\ndwelling. In determining whether a product is a consumer product, doubtful cases\nshall be resolved in favor of coverage. For a particular product received by a\nparticular user, “normally used” refers to a typical or common use of\nthat class of product, regardless of the status of the particular user or of the way\nin which the particular user actually uses, or expects or is expected to use, the\nproduct. A product is a consumer product regardless of whether the product has\nsubstantial commercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n“Installation Information” for a User Product means any methods,\nprocedures, authorization keys, or other information required to install and execute\nmodified versions of a covered work in that User Product from a modified version of\nits Corresponding Source. The information must suffice to ensure that the continued\nfunctioning of the modified object code is in no case prevented or interfered with\nsolely because modification has been made.\n\nIf you convey an object code work under this section in, or with, or specifically for\nuse in, a User Product, and the conveying occurs as part of a transaction in which\nthe right of possession and use of the User Product is transferred to the recipient\nin perpetuity or for a fixed term (regardless of how the transaction is\ncharacterized), the Corresponding Source conveyed under this section must be\naccompanied by the Installation Information. But this requirement does not apply if\nneither you nor any third party retains the ability to install modified object code\non the User Product (for example, the work has been installed in ROM).\n\nThe requirement to provide Installation Information does not include a requirement to\ncontinue to provide support service, warranty, or updates for a work that has been\nmodified or installed by the recipient, or for the User Product in which it has been\nmodified or installed. Access to a network may be denied when the modification itself\nmaterially and adversely affects the operation of the network or violates the rules\nand protocols for communication across the network.\n\nCorresponding Source conveyed, and Installation Information provided, in accord with\nthis section must be in a format that is publicly documented (and with an\nimplementation available to the public in source code form), and must require no\nspecial password or key for unpacking, reading or copying.\n\n### 7. Additional Terms\n\n“Additional permissions” are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions. Additional\npermissions that are applicable to the entire Program shall be treated as though they\nwere included in this License, to the extent that they are valid under applicable\nlaw. If additional permissions apply only to part of the Program, that part may be\nused separately under those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\nWhen you convey a copy of a covered work, you may at your option remove any\nadditional permissions from that copy, or from any part of it. (Additional\npermissions may be written to require their own removal in certain cases when you\nmodify the work.) You may place additional permissions on material, added by you to a\ncovered work, for which you have or can give appropriate copyright permission.\n\nNotwithstanding any other provision of this License, for material you add to a\ncovered work, you may (if authorized by the copyright holders of that material)\nsupplement the terms of this License with terms:\n\n* **a)** Disclaiming warranty or limiting liability differently from the terms of\nsections 15 and 16 of this License; or\n* **b)** Requiring preservation of specified reasonable legal notices or author\nattributions in that material or in the Appropriate Legal Notices displayed by works\ncontaining it; or\n* **c)** Prohibiting misrepresentation of the origin of that material, or requiring that\nmodified versions of such material be marked in reasonable ways as different from the\noriginal version; or\n* **d)** Limiting the use for publicity purposes of names of licensors or authors of the\nmaterial; or\n* **e)** Declining to grant rights under trademark law for use of some trade names,\ntrademarks, or service marks; or\n* **f)** Requiring indemnification of licensors and authors of that material by anyone\nwho conveys the material (or modified versions of it) with contractual assumptions of\nliability to the recipient, for any liability that these contractual assumptions\ndirectly impose on those licensors and authors.\n\nAll other non-permissive additional terms are considered “further\nrestrictions” within the meaning of section 10. If the Program as you received\nit, or any part of it, contains a notice stating that it is governed by this License\nalong with a term that is a further restriction, you may remove that term. If a\nlicense document contains a further restriction but permits relicensing or conveying\nunder this License, you may add to a covered work material governed by the terms of\nthat license document, provided that the further restriction does not survive such\nrelicensing or conveying.\n\nIf you add terms to a covered work in accord with this section, you must place, in\nthe relevant source files, a statement of the additional terms that apply to those\nfiles, or a notice indicating where to find the applicable terms.\n\nAdditional terms, permissive or non-permissive, may be stated in the form of a\nseparately written license, or stated as exceptions; the above requirements apply\neither way.\n\n### 8. Termination\n\nYou may not propagate or modify a covered work except as expressly provided under\nthis License. Any attempt otherwise to propagate or modify it is void, and will\nautomatically terminate your rights under this License (including any patent licenses\ngranted under the third paragraph of section 11).\n\nHowever, if you cease all violation of this License, then your license from a\nparticular copyright holder is reinstated **(a)** provisionally, unless and until the\ncopyright holder explicitly and finally terminates your license, and **(b)** permanently,\nif the copyright holder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\nMoreover, your license from a particular copyright holder is reinstated permanently\nif the copyright holder notifies you of the violation by some reasonable means, this\nis the first time you have received notice of violation of this License (for any\nwork) from that copyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\nTermination of your rights under this section does not terminate the licenses of\nparties who have received copies or rights from you under this License. If your\nrights have been terminated and not permanently reinstated, you do not qualify to\nreceive new licenses for the same material under section 10.\n\n### 9. Acceptance Not Required for Having Copies\n\nYou are not required to accept this License in order to receive or run a copy of the\nProgram. Ancillary propagation of a covered work occurring solely as a consequence of\nusing peer-to-peer transmission to receive a copy likewise does not require\nacceptance. However, nothing other than this License grants you permission to\npropagate or modify any covered work. These actions infringe copyright if you do not\naccept this License. Therefore, by modifying or propagating a covered work, you\nindicate your acceptance of this License to do so.\n\n### 10. Automatic Licensing of Downstream Recipients\n\nEach time you convey a covered work, the recipient automatically receives a license\nfrom the original licensors, to run, modify and propagate that work, subject to this\nLicense. You are not responsible for enforcing compliance by third parties with this\nLicense.\n\nAn “entity transaction” is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an organization, or\nmerging organizations. If propagation of a covered work results from an entity\ntransaction, each party to that transaction who receives a copy of the work also\nreceives whatever licenses to the work the party's predecessor in interest had or\ncould give under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if the predecessor\nhas it or can get it with reasonable efforts.\n\nYou may not impose any further restrictions on the exercise of the rights granted or\naffirmed under this License. For example, you may not impose a license fee, royalty,\nor other charge for exercise of rights granted under this License, and you may not\ninitiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging\nthat any patent claim is infringed by making, using, selling, offering for sale, or\nimporting the Program or any portion of it.\n\n### 11. Patents\n\nA “contributor” is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based. The work thus\nlicensed is called the contributor's “contributor version”.\n\nA contributor's “essential patent claims” are all patent claims owned or\ncontrolled by the contributor, whether already acquired or hereafter acquired, that\nwould be infringed by some manner, permitted by this License, of making, using, or\nselling its contributor version, but do not include claims that would be infringed\nonly as a consequence of further modification of the contributor version. For\npurposes of this definition, “control” includes the right to grant patent\nsublicenses in a manner consistent with the requirements of this License.\n\nEach contributor grants you a non-exclusive, worldwide, royalty-free patent license\nunder the contributor's essential patent claims, to make, use, sell, offer for sale,\nimport and otherwise run, modify and propagate the contents of its contributor\nversion.\n\nIn the following three paragraphs, a “patent license” is any express\nagreement or commitment, however denominated, not to enforce a patent (such as an\nexpress permission to practice a patent or covenant not to sue for patent\ninfringement). To “grant” such a patent license to a party means to make\nsuch an agreement or commitment not to enforce a patent against the party.\n\nIf you convey a covered work, knowingly relying on a patent license, and the\nCorresponding Source of the work is not available for anyone to copy, free of charge\nand under the terms of this License, through a publicly available network server or\nother readily accessible means, then you must either **(1)** cause the Corresponding\nSource to be so available, or **(2)** arrange to deprive yourself of the benefit of the\npatent license for this particular work, or **(3)** arrange, in a manner consistent with\nthe requirements of this License, to extend the patent license to downstream\nrecipients. “Knowingly relying” means you have actual knowledge that, but\nfor the patent license, your conveying the covered work in a country, or your\nrecipient's use of the covered work in a country, would infringe one or more\nidentifiable patents in that country that you have reason to believe are valid.\n\nIf, pursuant to or in connection with a single transaction or arrangement, you\nconvey, or propagate by procuring conveyance of, a covered work, and grant a patent\nlicense to some of the parties receiving the covered work authorizing them to use,\npropagate, modify or convey a specific copy of the covered work, then the patent\nlicense you grant is automatically extended to all recipients of the covered work and\nworks based on it.\n\nA patent license is “discriminatory” if it does not include within the\nscope of its coverage, prohibits the exercise of, or is conditioned on the\nnon-exercise of one or more of the rights that are specifically granted under this\nLicense. You may not convey a covered work if you are a party to an arrangement with\na third party that is in the business of distributing software, under which you make\npayment to the third party based on the extent of your activity of conveying the\nwork, and under which the third party grants, to any of the parties who would receive\nthe covered work from you, a discriminatory patent license **(a)** in connection with\ncopies of the covered work conveyed by you (or copies made from those copies), or **(b)**\nprimarily for and in connection with specific products or compilations that contain\nthe covered work, unless you entered into that arrangement, or that patent license\nwas granted, prior to 28 March 2007.\n\nNothing in this License shall be construed as excluding or limiting any implied\nlicense or other defenses to infringement that may otherwise be available to you\nunder applicable patent law.\n\n### 12. No Surrender of Others' Freedom\n\nIf conditions are imposed on you (whether by court order, agreement or otherwise)\nthat contradict the conditions of this License, they do not excuse you from the\nconditions of this License. If you cannot convey a covered work so as to satisfy\nsimultaneously your obligations under this License and any other pertinent\nobligations, then as a consequence you may not convey it at all. For example, if you\nagree to terms that obligate you to collect a royalty for further conveying from\nthose to whom you convey the Program, the only way you could satisfy both those terms\nand this License would be to refrain entirely from conveying the Program.\n\n### 13. Use with the GNU Affero General Public License\n\nNotwithstanding any other provision of this License, you have permission to link or\ncombine any covered work with a work licensed under version 3 of the GNU Affero\nGeneral Public License into a single combined work, and to convey the resulting work.\nThe terms of this License will continue to apply to the part which is the covered\nwork, but the special requirements of the GNU Affero General Public License, section\n13, concerning interaction through a network will apply to the combination as such.\n\n### 14. Revised Versions of this License\n\nThe Free Software Foundation may publish revised and/or new versions of the GNU\nGeneral Public License from time to time. Such new versions will be similar in spirit\nto the present version, but may differ in detail to address new problems or concerns.\n\nEach version is given a distinguishing version number. If the Program specifies that\na certain numbered version of the GNU General Public License “or any later\nversion” applies to it, you have the option of following the terms and\nconditions either of that numbered version or of any later version published by the\nFree Software Foundation. If the Program does not specify a version number of the GNU\nGeneral Public License, you may choose any version ever published by the Free\nSoftware Foundation.\n\nIf the Program specifies that a proxy can decide which future versions of the GNU\nGeneral Public License can be used, that proxy's public statement of acceptance of a\nversion permanently authorizes you to choose that version for the Program.\n\nLater license versions may give you additional or different permissions. However, no\nadditional obligations are imposed on any author or copyright holder as a result of\nyour choosing to follow a later version.\n\n### 15. Disclaimer of Warranty\n\nTHERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\nEXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER\nEXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE\nQUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE\nDEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n### 16. Limitation of Liability\n\nIN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY\nCOPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS\nPERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,\nINCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE\nPROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE\nOR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE\nWITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n### 17. Interpretation of Sections 15 and 16\n\nIf the disclaimer of warranty and limitation of liability provided above cannot be\ngiven local legal effect according to their terms, reviewing courts shall apply local\nlaw that most closely approximates an absolute waiver of all civil liability in\nconnection with the Program, unless a warranty or assumption of liability accompanies\na copy of the Program in return for a fee.\n\n_END OF TERMS AND CONDITIONS_\n\n## How to Apply These Terms to Your New Programs\n\nIf you develop a new program, and you want it to be of the greatest possible use to\nthe public, the best way to achieve this is to make it free software which everyone\ncan redistribute and change under these terms.\n\nTo do so, attach the following notices to the program. It is safest to attach them\nto the start of each source file to most effectively state the exclusion of warranty;\nand each file should have at least the “copyright” line and a pointer to\nwhere the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program does terminal interaction, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type 'show c' for details.\n\nThe hypothetical commands `show w` and `show c` should show the appropriate parts of\nthe General Public License. Of course, your program's commands might be different;\nfor a GUI interface, you would use an “about box”.\n\nYou should also get your employer (if you work as a programmer) or school, if any, to\nsign a “copyright disclaimer” for the program, if necessary. For more\ninformation on this, and how to apply and follow the GNU GPL, see\n&lt;<http://www.gnu.org/licenses/>&gt;.\n\nThe GNU General Public License does not permit incorporating your program into\nproprietary programs. If your program is a subroutine library, you may consider it\nmore useful to permit linking proprietary applications with the library. If this is\nwhat you want to do, use the GNU Lesser General Public License instead of this\nLicense. But first, please read\n&lt;<http://www.gnu.org/philosophy/why-not-lgpl.html>&gt;.\n\n## ADDITIONAL TERMS per GNU GPL Section 7\n\nNo trademark or publicity rights are granted. This license does NOT give you\nany right, title or interest in \"Command & Conquer\" or any other Electronic Arts\ntrademark. You may not distribute any modification of this program using any\nElectronic Arts trademark or claim any affiliation or association with\nElectronic Arts Inc. or its affiliates or their employees.\n\nAny propagation or conveyance of this program must include this copyright\nnotice and these terms.\n\nIf you convey this program (or any modifications of it) and assume\ncontractual liability for the program to recipients of it, you agree to\nindemnify Electronic Arts for any liability that those contractual\nassumptions impose on Electronic Arts.\n\nYou may not misrepresent the origins of this program; modified versions of\nthe program must be marked as such and not identified as the original program.\n\nThis disclaimer supplements the one included in the General Public License.\nTO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS PROGRAM IS\nPROVIDED TO YOU \"AS IS,\" WITH ALL FAULTS, WITHOUT WARRANTY OF ANY KIND, AND\nYOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF SATISFACTORY QUALITY AND\nPERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS DISCLAIMS ANY AND ALL EXPRESS,\nIMPLIED OR STATUTORY WARRANTIES, INCLUDING IMPLIED WARRANTIES OF\nMERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A PARTICULAR PURPOSE,\nNONINFRINGEMENT OF THIRD PARTY RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A\nCOURSE OF DEALING, USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT\nAGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL\nMEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE UNINTERRUPTED OR\nERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE WITH THIRD PARTY SOFTWARE\nOR THAT ANY ERRORS IN THE PROGRAM WILL BE CORRECTED. NO ORAL OR WRITTEN ADVICE\nPROVIDED BY ELECTRONIC ARTS OR ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A\nWARRANTY. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON\nIMPLIED WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A\nCONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY NOT APPLY\nTO YOU.\n"
  },
  {
    "path": "README.md",
    "content": "\n# Command & Conquer Red Alert\n\nThis repository includes source code for Command & Conquer Red Alert. This release provides support to the [Steam Workshop](https://steamcommunity.com/workshop/browse/?appid=2229840) for the game.\n\n\n## Dependencies\n\nIf you wish to rebuild the source code and tools successfully you will need to find or write new replacements (or remove the code using them entirely) for the following libraries;\n\n- DirectX 5 SDK\n- DirectX Media 5.1 SDK\n- Greenleaf Communications Library (GCL)\n- Human Machine Interface (HMI) “Sound Operating System” (SOS)\n\n\n## Compiling (Win32 Only)\n\nThe current state of the source code does not fully compile and will require some effort to restore it. If you wish to restore the original build environment, the following tools are required;\n\n- Watcom C/C++ (v10.6) for C/C++ source files\n- Borland Turbo Assembler (TASM v4.0) for assembly files\n\nTo use the compiled binaries, you must own the game. The C&C Ultimate Collection is available for purchase on [EA App](https://www.ea.com/en-gb/games/command-and-conquer/command-and-conquer-the-ultimate-collection/buy/pc) or [Steam](https://store.steampowered.com/bundle/39394/Command__Conquer_The_Ultimate_Collection/).\n\n\n## Contributing\n\nThis repository will not be accepting contributions (pull requests, issues, etc). If you wish to create changes to the source code and encourage collaboration, please create a fork of the repository under your GitHub user/organization space.\n\n\n## Support\n\nThis repository is for preservation purposes only and is archived without support. \n\n\n## License\n\nThis repository and its contents are licensed under the GPL v3 license, with additional terms applied. Please see [LICENSE.md](LICENSE.md) for details.\n"
  },
  {
    "path": "TOOLS/AUDIOMAK/AUDIOMAK.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n **             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                  **\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : AUDIOMAK.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : August 8, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t<stdio.h>\n#include\t<stdlib.h>\n#include\t<dir.h>\n#include\t<dos.h>\n#include\t<string.h>\n#include\t<ctype.h>\n#include\t<conio.h>\n\n#define\tFALSE\t0\n#define\tTRUE\t1\n\n#define\tMIN(a,b)\t\t(((a)<(b)) ? (a) : (b))\n#define\tMAX(a,b)\t\t(((a)>(b)) ? (a) : (b))\n\nchar * SourceFile = 0;\nint SourceWild = FALSE;\nchar * DestFile = 0;\nint DestDir = FALSE;\nint DoSpecial = TRUE;\t\t\t\t// Compression starts \"on\".\nlong MagicNumber = 0xDEAF;\nint DoVerbose = FALSE;\t\t\t\t// Verbose report starts \"off\".\n\nchar Path[MAXPATH];\nchar Drive[MAXDRIVE];\nchar Dir[MAXDIR];\nchar File[MAXFILE];\nchar Ext[MAXEXT];\n\n// The size of these buffers must be evenly divisble by 2048.\nchar far StageBuffer[1024*16];\nchar far padding[1024];\nchar far AltBuffer[1024*16];\nchar far padding2[1024];\n\n// General header to the RIFF file itself.\ntypedef struct {\n\tchar szRIFF[4];\t\t\t\t// \"RIFF\"\n\tlong dwFormatLength;\n\tchar szWAVE[4];\t\t\t\t// \"WAVE\"\n} RIFFHeaderType;\n\n// Header to each sub-block of a RIFF file.\ntypedef struct {\n\tchar szDATA[4];\t\t\t\t// ASCII identifier for block.\n\tlong dwDataLength;\t\t\t// Size of block (not counting this header).\n} RIFFBlockType;\n\n// First part of the \"fmt\" data block.\ntypedef struct {\n\tshort wFormatTag;\t\t\t\t// 1=raw, 33=sonarc\n\tshort wChannels;\t\t\t\t// 1=mono, 2=stereo\n\tlong dwSamplesPerSec;\t\t// Playback \"rate\".\n\tlong dwAvgBytesPerSec;\t\t// =(samples/sec)*(bytes/sample)*wChannels\n\tshort wBlockAlign;\n\tshort wBitsPerSample;\t\t\t// 8 or 16\n\n\t// Even more bytes can go here... examine dwDataLength to verify.\n\t// Optional for Sonarc\n//\t\tLONG cbSize;\t\t\t\t\t// Size of the extra portion of fmt (always 2)\n//\t\tWORD wCompType;\t\t\t\t// Compression algorithm index\n} RIFFfmtType;\n\ntypedef struct {\n\tchar\tDescription[0x14];\n\tshort\tOffset;\n\tshort\tVersion;\n\tshort\tIDCode;\n} VocHeaderType;\n\n// Compression types.\ntypedef enum {\n\tSCOMP_NONE=0,\t\t\t// No compression -- raw data.\n\tSCOMP_WESTWOOD,\t\t// Special sliding window delta compression.\n\tSCOMP_SONARC=33\t\t// Sonarc frame compression.\n} SCompressType;\n\n// Header to output file.\ntypedef struct {\n\tunsigned short\tRate;\t\t\t\t// Playback rate (hertz).\n\tlong\t\t\t\tSize;\t\t\t\t// Size of data (bytes).\n\tunsigned\t\t\tStereo:1;\t\t// Is the sample stereo?\n\tunsigned\t\t\tBits:1;\t\t\t// Is the sample 16 bits?\n\tunsigned\t\t\tpad:6;\t\t\t// Padding bits.\n\tunsigned char\tCompression;\t// What kind of compression for this sample?\n} RawHeaderType;\n\ntypedef struct {\n\tshort\tframeSize;\t\t\t\t// Size of the frame in bytes (including header).\n\tshort\tnSamples;\t\t\t\t\t// # of samples in the frame.\n\tshort\tchkSum;\t\t\t\t\t// A checksum -- Words XORed with 0xACED.\n\tchar\ttableIndex;\t\t\t\t// Bit 7 set if frame was RLE'd\n\tchar\torder;\t\t\t\t\t\t// The order of the predictor.\n} SonarcFrameType;\n\n\nint main(int argc, char **argv);\nvoid Process(char const *src, char const *name, char const *dest);\nvoid Convert(char const *src, char const *dst);\nint Is_WAV(FILE *src);\nvoid Convert_WAV(FILE * src, FILE * dst);\nint Is_VOC(FILE *src);\nvoid Convert_VOC(FILE *src, FILE *dst);\nlong Compress_Frame(void * source, void * dest, long size);\n\nextern \"C\" {\nshort Decompress_Frame(void * source, void * dest, short size);\n}\n\n\nint main(int argc, char **argv)\n{\n\n\t/*\n\t**\tProcess the command line parameters.\n\t*/\n\ttry {\n\t\tif (argc < 2) throw 1;\n\n\t\tfor (int index = 1; index < argc; index++) {\n\t\t\tchar *string = argv[index];\n\n\t\t\tswitch (string[0]) {\n\t\t\t\tcase '-':\n\t\t\t\tcase '/':\n\t\t\t\t\tswitch (toupper(string[1])) {\n\t\t\t\t\t\tcase 'X':\n\t\t\t\t\t\t\tif (string[2] == '-') {\n\t\t\t\t\t\t\t\tDoSpecial = FALSE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 'V':\n\t\t\t\t\t\t\tDoVerbose = TRUE;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tprintf(\"\\nERROR: Invalid command line argument.\\n\");\n\t\t\t\t\t\t\treturn (EXIT_FAILURE);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tif (!SourceFile) {\n\t\t\t\t\t\tSourceFile = string;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!DestFile) {\n\t\t\t\t\t\t\tDestFile = string;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tprintf(\"\\nERROR: Invalid command line argument.\\n\");\n\t\t\t\t\t\t\treturn (EXIT_FAILURE);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tVerify that the source filespec can locate at least one file.\n\t\t*/\n\t\t{\n\t\t\tstruct ffblk block;\n\n\t\t\tint result = fnsplit(SourceFile, Drive, Dir, File, Ext);\n\t\t\tif (result & WILDCARDS) SourceWild = TRUE;\n\t\t\tresult = findfirst(SourceFile, &block, FA_ARCH|FA_RDONLY);\n\t\t\tif (result) {\n\t\t\t\tprintf(\"\\nERROR: Cannot find source file '%s'.\\n\", SourceFile);\n\t\t\t\texit(EXIT_FAILURE);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tNo output file is necessary if only a single file is specified for\n\t\t**\tthe source.  In such a case, use the source file as the output file\n\t\t**\tname but change the extension to .AUD.\n\t\t*/\n\t\tif (!DestFile) {\n\t\t\tif (!SourceWild) {\n\t\t\t\tfnsplit(SourceFile, Drive, Dir, File, Ext);\n\t\t\t\tfnmerge(Path, Drive, Dir, File, \".AUD\");\n\t\t\t\tDestFile = strdup(Path);\n\t\t\t} else {\n\t\t\t\tDestFile = strdup(\".\");\n\t\t\t\t//printf(\"\\nERROR: No destination directory specified.\\n\");\n\t\t\t\t//exit(EXIT_FAILURE);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tThe source and destination files cannot be the same.\n\t\t*/\n\t\tif (stricmp(SourceFile, DestFile) == 0) {\n\t\t\tprintf(\"\\nERROR: Source and destination files must not be the same.\\n\");\n\t\t\texit(EXIT_FAILURE);\n\t\t}\n\n\t\t/*\n\t\t**\tMake sure that the destination filespec does not contain any \n\t\t**\twildcard specifications.\n\t\t*/\n\t\tif (fnsplit(DestFile, Drive, Dir, File, Ext) & WILDCARDS) {\n\t\t\tprintf(\"\\nERROR: Wildcard characters not allowed in destination file '%s'.\\n\", DestFile);\n\t\t\texit(EXIT_FAILURE);\n\t\t}\n\n\t\t/*\n\t\t**\tDetermine if the destination is a directory or not.  If it is\n\t\t**\ta directory, then it must be mutated into proper directory format.\n\t\t*/\n\t\t{\n\t\t\tstruct ffblk block;\n\n\t\t\tstrcpy(Path, DestFile);\n\t\t\tif (Path[strlen(Path)-1] == '\\\\') {\n\t\t\t\tPath[strlen(Path)-1] = '\\0';\n\t\t\t}\n\n\t\t\tint result = findfirst(Path, &block, FA_DIREC);\n\t\t\tif (!result && (block.ff_attrib & FA_DIREC)) {\n\t\t\t\tDestDir = TRUE;\n\t\t\t\t/*\n\t\t\t\t**\tMake sure that the output directory ends with a backslash or a colon.\n\t\t\t\t*/\n\t\t\t\tstrcpy(Path, DestFile);\n\t\t\t\tswitch (Path[strlen(Path)-1]) {\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tstrcat(Path, \"\\\\\");\n\t\t\t\t\t\tDestFile = strdup(Path);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase '\\\\':\n\t\t\t\t\tcase ':':\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tVerify that the destination is a directory if wildcards were specified\n\t\t**\tin the source filespec.\n\t\t*/\n\t\tif (SourceWild && !DestDir) {\n\t\t\tprintf(\"\\nERROR: Destination '%s' was not a directory.\\n\", DestFile);\n\t\t\texit(EXIT_FAILURE);\n\t\t}\n\n\t\t/*\n\t\t**\tScan through all specified source files and process them into the \n\t\t**\tappropriate audio format.\n\t\t*/\n\t\tstruct ffblk block;\n\n\t\tfindfirst(SourceFile, &block, FA_ARCH|FA_RDONLY);\n\t\tdo {\n\t\t\tProcess(SourceFile, block.ff_name, DestFile);\n\t\t} while (!findnext(&block));\n\n\t}\n\tcatch(int) {\n\t\tprintf(\"\\n\"\n\t\t\t\t\"AUDIOMAK V2.3 (c) 1994, by Westwood Studios\\n\"\n\t\t\t\t\"USAGE:  AUDIOMAK [option] <sourcefile> <destfile>\\n\"\n\t\t\t\t\"\\n\"\n\t\t\t\t\"  Options:\\n\"\n\t\t\t\t\"    -X-                : Turn compression off.\\n\"\n\t\t\t\t\"    -V                 : Verbose compression report.\\n\"\n\t\t\t\t\"\\n\"\n\t\t\t\t\"  <sourcefile>         : File or filespec of VOC or WAV files to process\\n\"\n\t\t\t\t\"                         Can be SONARC compressed.\\n\"\n\t\t\t\t\"  <destfile>           : Destination file or destination directory.  If\\n\"\n\t\t\t\t\"                         wildcards were used in the source file then this\\n\"\n\t\t\t\t\"                         can only be a destination directory.\\n\"\n\t\t\t\t\"\\n\");\n\t\treturn(EXIT_FAILURE);\n\t}\n\n\treturn(EXIT_SUCCESS);\n}\n\nlong\trawframes;\t\t// Number of non-compressed frames.\nlong\trate;\t\t\t\t// Sample rate.\nlong\traw;\t\t\t\t// Number of raw bytes output.\nlong\tbit5;\t\t\t\t// Number of 5bit codes output.\nlong\tbit4;\t\t\t\t// Number of 4bit codes output (@2 samples).\nlong\tbit2;\t\t\t\t// Number of 2bit codes output (@4 samples).\nlong\tbit0;\t\t\t\t// Number of 0 delta runs.\nlong\toverhead;\t\t// Overhead (wrapper) bytes.\nlong\toriginal;\t\t// Original data size.\nlong\tcompressed;\t\t// Compressed data output.\n\ninline void Log_RawFrame(long val) {rawframes += val;}\ninline void Log_Raw(long val) {raw += val;}\ninline void Log_5Bit(long val) {bit5 += val;}\ninline void Log_4Bit(long val) {bit4 += val;}\ninline void Log_2Bit(long val) {bit2 += val;}\ninline void Log_0Bit(long val) {bit0 += val;}\ninline void Log_Overhead(long val) {overhead += val;}\ninline void Log_Compressed(long val) {compressed += val;}\ninline void Log_Original(long val) {original += val;}\ninline void Log_Rate(long val) {rate = val;}\n\nvoid Stat_Reset(void)\n{\n\tif (DoVerbose) {\n\t\trawframes = 0;\n\t\trate = 0;\n\t\traw = 0;\n\t\tbit5 = 0;\n\t\tbit4 = 0;\n\t\tbit2 = 0;\n\t\tbit0 = 0;\n\t\toverhead = 0;\n\t\toriginal = 0;\n\t\tcompressed = 0;\n\t}\n}\n\nvoid Stat_Dump(void)\n{\n\tif (DoVerbose) {\n\t\tprintf(\"Compression efficiency = %ld%% (%ld bytes)\\n\", ((original - compressed) * 100) / original, original - compressed);\n\t\tprintf(\"  Sample Rate = %ld\\n\", rate);\n\t\tprintf(\"  Uncompressed data..:%7ld %ld%%\\n\", raw, (raw * 100) / original);\n\t\tprintf(\"  Uncompressed frames:%7ld\\n\", rawframes);\n\t\tprintf(\"  5 bit codes........:%7ld %ld%%\\n\", bit5, (bit5 * 100) / original);\n\t\tprintf(\"  4 bit codes........:%7ld %ld%%\\n\", bit4, (bit4 * 100) / original);\n\t\tprintf(\"  2 bit codes........:%7ld %ld%%\\n\", bit2, (bit2 * 100) / original);\n\t\tprintf(\"  0 bit codes........:%7ld %ld%%\\n\", bit0, (bit0 * 100) / original);\n\t\tprintf(\"  overhead bytes.....:%7ld %ld%%\\n\", overhead, (overhead * 100) / original);\n\t} else {\n\t\tprintf(\"%ld%%\\n\", ((original - compressed) * 100) / original);\n\t}\n}\n\n\nvoid Process(char const *src, char const *name, char const *dest)\n{\n\tchar sourcename[MAXPATH];\n\n\t/*\n\t** Open the input file.\n\t*/\n\tfnsplit(src, Drive, Dir, File, Ext);\n\tfnmerge(sourcename, Drive, Dir, NULL, NULL);\n\tstrcat(sourcename, name);\n\n\t/*\n\t**\tOpen the output filename based on the source filename and the destination\n\t**\tdirectory or filename.\n\t*/\n\tfnsplit(sourcename, NULL, NULL, File, Ext);\n\tif (DestDir) {\n\t\tfnsplit(dest, Drive, Dir, NULL, NULL);\n\t\tfnmerge(Path, Drive, Dir, File, \".AUD\");\n\t} else {\n\t\tfnsplit(dest, Drive, Dir, NULL, Ext);\n\t\tfnmerge(Path, Drive, Dir, File, Ext);\n\t}\n\n\tstrupr(sourcename);\n\tstrupr(Path);\n\tprintf(\"%s \", sourcename, Path);\n\tConvert(sourcename, Path);\n}\n\n\nvoid Convert(char const *src, char const *dst)\n{\n\tFILE\t*srcfile = 0;\n\tFILE\t*dstfile = 0;\n\n\tsrcfile = fopen(src, \"rb\");\n\tif (!srcfile) {\n\t\tperror(src);\n\t\texit(EXIT_FAILURE);\n\t}\n\n\tif (Is_WAV(srcfile)) {\n\t\tdstfile = fopen(dst, \"wb\");\n\t\tif (!dstfile) {\n\t\t\tperror(dst);\n\t\t\texit(EXIT_FAILURE);\n\t\t}\n\t\tStat_Reset();\n\t\tConvert_WAV(srcfile, dstfile);\n\t\tStat_Dump();\n\t} else {\n\t\tif (Is_VOC(srcfile)) {\n\t\t\tdstfile = fopen(dst, \"wb\");\n\t\t\tif (!dstfile) {\n\t\t\t\tperror(dst);\n\t\t\t\texit(EXIT_FAILURE);\n\t\t\t}\n\t\t\tStat_Reset();\n\t\t\tConvert_VOC(srcfile, dstfile);\n\t\t\tStat_Dump();\n\t\t} else {\n\t\t\tprintf(\"ERROR: Unrecognized source file format for '%s'.\\n\", src);\n\t\t\texit(EXIT_FAILURE);\n\t\t}\n\t}\n\tif (dstfile) fclose(dstfile);\n\tfclose(srcfile);\n}\n\n\nint Is_WAV(FILE *src)\n{\n\tlong\tsize;\n\tRIFFHeaderType\theader;\n\n\tfseek(src, 0, SEEK_SET);\n\n\t/*\n\t**\tDetermine if this is a WAV file.  Examining the file extension is\n\t**\tnot foolproof.  The actual data must be looked at.\n\t*/\n\tsize = fread(&header, 1, sizeof(header), src);\n\tif (size == sizeof(header)) {\n\t\tif (memcmp(header.szRIFF, \"RIFF\", 4) == 0) {\n\t\t\tif (memcmp(header.szWAVE, \"WAVE\", 4) == 0) {\n\t\t\t\treturn(TRUE);\n\t\t\t}\n\t\t}\n\t}\n\treturn(FALSE);\n}\n\nvoid Convert_WAV(FILE * src, FILE * dst)\n{\n\tRIFFBlockType block;\n\tRIFFfmtType fmt;\n\tRawHeaderType raw;\n\tint nodo = FALSE;\n\tlong fcount = 0;\n\n\traw.pad = 0;\n\traw.Size = 0;\n\tfwrite(&raw, 1, sizeof(raw), dst);\n\tLog_Overhead(sizeof(raw));\n\n\t/*\n\t**\tAt this point, we already know that it is a RIFF (wav) file, so\n\t**\tskip the identifier bytes at the beginning.\n\t*/\n\tfseek(src, sizeof(RIFFHeaderType), SEEK_SET);\n\n\t/*\n\t**\tProcess all the blocks in the RIFF file.\n\t*/\n\tfor (;;) {\n\t\tlong s;\n\n\t\ts = fread(&block, sizeof(block), 1, src);\n\t\tif (!s) break;\n\n\t\t/*\n\t\t**\tIf this is the format control block, the process it.\n\t\t*/\n\t\tif (memcmp(block.szDATA, \"fmt \", sizeof(\"fmt \")-1) == 0) {\n\t\t\ts = fread(&fmt, 1, sizeof(fmt), src);\n\t\t\tif (s != sizeof(fmt)) break;\n\n\t\t\traw.Rate = (short)fmt.dwSamplesPerSec;\n\t\t\tLog_Rate(raw.Rate);\n\t\t\traw.Stereo = (fmt.wChannels == 2);\n\t\t\traw.Bits = (fmt.wBitsPerSample == 16);\n\t\t\tswitch (fmt.wFormatTag) {\n\t\t\t\tdefault:\n\t\t\t\tcase 1:\n\t\t\t\t\traw.Compression = SCOMP_NONE;\n\t\t\t\t\tif (DoSpecial) {\n\t\t\t\t\t\traw.Compression = SCOMP_WESTWOOD;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 33:\n\t\t\t\t\traw.Compression = SCOMP_SONARC;\n\t\t\t\t\tif (DoSpecial) {\n\t\t\t\t\t\tprintf(\"ERROR: Cannot compress an already compressed WAV file.\\n\");\n\t\t\t\t\t\tnodo = TRUE;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSkip any extra format bytes.  For a Sonarc file, there are\n\t\t\t**\textra bytes to skip.\n\t\t\t*/\n\t\t\tfseek(src, block.dwDataLength - sizeof(fmt), SEEK_CUR);\n\n\t\t} else if (memcmp(block.szDATA, \"data\", sizeof(\"data\")-1) == 0) {\n\n\t\t\t/*\n\t\t\t**\tAdd in the size of this data block to the running total of data\n\t\t\t**\tcount.  For SONARC compressed blocks, there is an extra four bytes\n\t\t\t**\tat the start of the data that records the uncompressed size -- who\n\t\t\t**\tcares, so skip it.\n\t\t\t*/\n\t\t\tif (raw.Compression == SCOMP_SONARC) {\n\t\t\t\tfseek(src, 4, SEEK_CUR);\n\t\t\t\tblock.dwDataLength -= sizeof(raw.Size);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCopy the bulk of the data to the output file.\n\t\t\t*/\n\t\t\twhile (block.dwDataLength) {\n\t\t\t\tlong\tdesired;\n\t\t\t\tlong\tactual;\n\n\t\t\t\tdesired = sizeof(StageBuffer);\n\t\t\t\tif (block.dwDataLength < desired) {\n\t\t\t\t\tdesired = block.dwDataLength;\n\t\t\t\t}\n\t\t\t\tactual = fread(StageBuffer, 1, (unsigned)desired, src);\n\t\t\t\tLog_Original(actual);\n\t\t\t\tblock.dwDataLength -= actual;\n\n\t\t\t\t/*\n\t\t\t\t**\tSpecial process to convert audio data into deltas.\n\t\t\t\t*/\n\t\t\t\tif (DoSpecial && !nodo) {\n\t\t\t\t\tvoid *sptr = &StageBuffer[0];\n\t\t\t\t\tlong\ta = actual;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tWhen compressing the data, it must be processed in small\n\t\t\t\t\t**\tchunks.  Loop through the source and process the chunks\n\t\t\t\t\t**\tuntil there is no more source data.  Careful choice of the\n\t\t\t\t\t**\tsize of the buffers ensures that only full chunks are\n\t\t\t\t\t**\toutput.\n\t\t\t\t\t*/\n\t\t\t\t\twhile (a) {\n\t\t\t\t\t\tlong\ttocomp;\n\t\t\t\t\t\tlong\tcomped;\n\n\t\t\t\t\t\ttocomp = MIN(a, 2048);\n\t\t\t\t\t\tcomped = Compress_Frame(sptr, AltBuffer, tocomp);\n\t\t\t\t\t\ta -= tocomp;\n\t\t\t\t\t\tLog_Compressed(comped);\n\n\t\t\t\t\t\t#if(FALSE)\n\t\t\t\t\t\tif (comped < tocomp) {\n\t\t\t\t\t\t\tDecompress_Frame(AltBuffer, sptr, (short)tocomp);\n\t\t\t\t\t\t}\n\t\t\t\t\t\traw.Size += fwrite(sptr, 1, (size_t)tocomp, dst);\n\t\t\t\t\t\t(char*)sptr += (unsigned)tocomp;\n\t\t\t\t\t\t#else \n\n\t\t\t\t\t\t(char*)sptr += (unsigned)tocomp;\n\t\t\t\t\t\traw.Size += fwrite(&comped, 1, sizeof(short), dst);\n\t\t\t\t\t\traw.Size += fwrite(&tocomp, 1, sizeof(short), dst);\n\t\t\t\t\t\traw.Size += fwrite(&MagicNumber, 1, sizeof(MagicNumber), dst);\n\t\t\t\t\t\traw.Size += fwrite(&AltBuffer[0], 1, (size_t)comped, dst);\n\t\t\t\t\t\t#endif\n\t\t\t\t\t\tfcount++;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\traw.Size += actual;\n\t\t\t\t\tfwrite(StageBuffer, 1, (unsigned)actual, dst);\n\t\t\t\t\tLog_Compressed(actual);\n\t\t\t\t\tfcount++;\n\t\t\t\t}\n\t\t\t\tif (!actual) break;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tUnrecognized blocks are skipped.\n\t\t\t*/\n\t\t\tfseek(src, block.dwDataLength, SEEK_CUR);\n\t\t}\n\t}\n\n\t/*\n\t**\tOutput the finalized raw header structure.\n\t*/\n\tfseek(dst, 0, SEEK_SET);\n\tfwrite(&raw, 1, sizeof(raw), dst);\n}\n\n\nint Is_VOC(FILE *src)\n{\n\tlong \t\t\t\tsize;\n\tVocHeaderType\tvoc;\n\n\tfseek(src, 0, SEEK_SET);\n\tsize = fread(&voc, 1, sizeof(voc), src);\n\tif (size != sizeof(voc)) {\n\t\treturn(FALSE);\n\t}\n\n\tif (memicmp(voc.Description, \"Creative Voice File\", strlen(\"Creative Voice File\")) != 0) {\n\t\treturn(FALSE);\n\t}\n\n\treturn (TRUE);\n}\n\n\nvoid Convert_VOC(FILE *src, FILE *dst)\n{\n//\tlong\t\t\t\tsize = 0;\n\tVocHeaderType\tvoc;\n\tRawHeaderType\traw;\n\n\traw.pad = 0;\n\traw.Size = 0;\n\traw.Compression = SCOMP_NONE;\n\tif (DoSpecial) {\n\t\traw.Compression = SCOMP_WESTWOOD;\n\t}\n\n\tfseek(src, 0, SEEK_SET);\n\tfread(&voc, 1, sizeof(voc), src);\n\tfseek(src, voc.Offset, SEEK_SET);\n\n\t/*\n\t**\tOutput a dummy raw header (will be updated later).\n\t*/\n\traw.Size = 0;\n\traw.Rate = 11025;\n\traw.Stereo = FALSE;\n\traw.Bits = FALSE;\n\tfwrite(&raw, sizeof(raw), 1, dst);\n\n\t/*\n\t**\tLoop through all the VOC chunks in order to build the correct\n\t**\trawheader structure.\n\t*/\n\tchar code = -1;\n\twhile (code != 0) {\n\t\tchar\t\t\t\tc;\n\t\tlong\t\t\t\tblocksize=0;\n\t\tunsigned\t\t\trate=0;\n\t\tunsigned char\tpack=0;\n\t\tldiv_t\tresult;\n\n\t\tfread(&code, 1, sizeof(code), src);\n\t\tswitch (code) {\n\n\t\t\t/*\n\t\t\t**\tGeneral data block.  Packed data is not supported.\n\t\t\t**\tIf an extended control block has been processed, then\n\t\t\t**\tignore the control bytes in this file.\n\t\t\t*/\n\t\t\tcase 1:\n\t\t\t\tfread(&blocksize, 3, 1, src);\n\n\t\t\t\t/*\n\t\t\t\t**\tDetermine the sample rate from the special code provided\n\t\t\t\t**\tfor this block.  The formula is very inaccurate, so check\n\t\t\t\t**\tfor some special codes and fixe the playback rate accordingly.\n\t\t\t\t**\tWhen dealing with odd sample rates, then just figure out\n\t\t\t\t**\tthe rate based on the formula.\n\t\t\t\t*/\n\t\t\t\tfread(&rate, 1, 1, src);\n\t\t\t\tswitch (256-rate) {\n\t\t\t\t\tcase 22:\n\t\t\t\t\tcase 23:\n\t\t\t\t\t\traw.Rate = 44100U;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 45:\n\t\t\t\t\t\traw.Rate = 22050;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 90:\n\t\t\t\t\tcase 91:\n\t\t\t\t\t\traw.Rate = 11025;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 181:\n\t\t\t\t\t\traw.Rate = 5512;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tresult = ldiv(1000000L, (long)256-(long)rate);\n\t\t\t\t\t\traw.Rate = (int)result.quot;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tLog_Rate(raw.Rate);\n\t\t\t\tfread(&pack, 1, 1, src);\n\n\t\t\t\t/*\n\t\t\t\t**\tCopy over the raw data.  If the data is packed, then\n\t\t\t\t**\tit is skipped since packed data is not supported by this\n\t\t\t\t**\tutility (yet).\n\t\t\t\t*/\n\t\t\t\tif (pack == 0) {\n\t\t\t\t\tlong\tdesired;\n\t\t\t\t\tlong\tactual;\n\n\t\t\t\t\tblocksize -= 2;\n\t\t\t\t\t//raw.Size += blocksize;\n\t\t\t\t\twhile (blocksize) {\n\t\t\t\t\t\tdesired = MIN(blocksize, sizeof(StageBuffer));\n\t\t\t\t\t\tactual = fread(StageBuffer, 1, (unsigned)desired, src);\n\t\t\t\t\t\tLog_Original(actual);\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tSpecial process to convert audio data into deltas.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (DoSpecial) {\n\t\t\t\t\t\t\tvoid *sptr = &StageBuffer[0];\n\t\t\t\t\t\t\tlong\ta = actual;\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tWhen compressing the data, it must be processed in small\n\t\t\t\t\t\t\t**\tchunks.  Loop through the source and process the chunks\n\t\t\t\t\t\t\t**\tuntil there is no more source data.  Careful choice of the\n\t\t\t\t\t\t\t**\tsize of the buffers ensures that only full chunks are\n\t\t\t\t\t\t\t**\toutput.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\twhile (a) {\n\t\t\t\t\t\t\t\tshort\ttocomp;\n\t\t\t\t\t\t\t\tshort\tcomped;\n\n\t\t\t\t\t\t\t\ttocomp = (short)MIN(a, 2048);\n\t\t\t\t\t\t\t\tcomped = (short)Compress_Frame(sptr, AltBuffer, tocomp);\n\t\t\t\t\t\t\t\ta -= tocomp;\n\t\t\t\t\t\t\t\tLog_Compressed(comped);\n\n\t\t\t\t\t\t\t\t(char*)sptr += (unsigned)tocomp;\n\t\t\t\t\t\t\t\traw.Size += fwrite(&comped, 1, sizeof(short), dst);\n\t\t\t\t\t\t\t\traw.Size += fwrite(&tocomp, 1, sizeof(short), dst);\n\t\t\t\t\t\t\t\traw.Size += fwrite(&MagicNumber, 1, sizeof(MagicNumber), dst);\n\t\t\t\t\t\t\t\traw.Size += fwrite(&AltBuffer[0], 1, (size_t)comped, dst);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\traw.Size += actual;\n\t\t\t\t\t\t\tfwrite(StageBuffer, 1, (unsigned)actual, dst);\n\t\t\t\t\t\t\tLog_Compressed(actual);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//fwrite(StageBuffer, 1, (unsigned)actual, dst);\n\t\t\t\t\t\tblocksize -= actual;\n\t\t\t\t\t\tif (actual != desired) break;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfseek(src, blocksize-2, SEEK_CUR);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tContinuation block.  Sample rate and pack type is\n\t\t\t** inherited from the previous data block.\n\t\t\t*/\n\t\t\tcase 2:\n\t\t\t\tfread(&blocksize, 1, 3, src);\n\t\t\t\tif (pack == 0) {\n\t\t\t\t\tlong\tdesired;\n\t\t\t\t\tlong\tactual;\n\n\t\t\t\t\tblocksize -= 2;\n\t\t\t\t\traw.Size += blocksize;\n\t\t\t\t\twhile (blocksize) {\n\t\t\t\t\t\tdesired = MIN(blocksize, sizeof(StageBuffer));\n\t\t\t\t\t\tactual = fread(StageBuffer, 1, (unsigned)desired, src);\n\t\t\t\t\t\tfwrite(StageBuffer, 1, (unsigned)actual, dst);\n\t\t\t\t\t\tLog_Original(actual);\n\t\t\t\t\t\tLog_Compressed(actual);\n\t\t\t\t\t\tblocksize -= actual;\n\t\t\t\t\t\tif (actual != desired) break;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfseek(src, blocksize-2, SEEK_CUR);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tExtended block is used for highspeed or \n\t\t\t** stereo samples.\n\t\t\t*/\n\t\t\tcase 8:\n\t\t\t\tfseek(src, 3, SEEK_CUR);\n\t\t\t\tfread(&rate, 2, 1, src);\n\t\t\t\tfread(&pack, 1, 1, src);\n\t\t\t\tfread(&c, 1, 1, src);\n\t\t\t\traw.Stereo = (c == 1);\n\n\t\t\t\tif (raw.Stereo) {\n\t\t\t\t\tresult = ldiv(128000000L, 65536L-rate);\n\t\t\t\t} else {\n\t\t\t\t\tresult = ldiv(256000000L, 65532L-rate);\n\t\t\t\t}\n\t\t\t\traw.Rate = (int)result.quot;\n\t\t\t\tLog_Rate(raw.Rate);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tUnprocessed blocks are skipped.\n\t\t\t*/\n\t\t\tcase 3:\t\t// Silence block.\n\t\t\tcase 4:\t\t// Marker block.\n\t\t\tcase 5:\t\t// Embedded string.\n\t\t\tcase 6:\t\t// Loop start block.\n\t\t\tcase 7:\t\t// End of loop block.\n\t\t\t\tfread(&blocksize, 1, 3, src);\n\t\t\t\tfseek(src, blocksize, SEEK_CUR);\n\t\t\t\tbreak;\n\n\t\t\tcase 0:\t\t// End of file block.\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tcode = 0;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tfseek(dst, 0, SEEK_SET);\n\tfwrite(&raw, sizeof(raw), 1, dst);\n}\n\n\n\ntypedef enum {\n\tCODE_2BIT,\t\t\t\t// Bit packed 2 bit delta.\n\tCODE_4BIT,\t\t\t\t// Nibble packed 4 bit delta.\n\tCODE_RAW,\t\t\t\t// Raw sample.\n\tCODE_SILENCE\t\t\t// Run of silence.\n} SCodeType;\n\n\nsigned char _2bitencode[5] = {0, 1, 2, 3};\n//signed char _2bitencode[5] = {0, 1, (2), 2, 3};\nsigned int _2bitdecode[4] = {-2, -1, 0, 1};\n//signed int _2bitdecode[4] = {-2, -1, 1, 2};\n\n#if(TRUE)\nsigned char _4bitencode[19] = {\n\t0, 1, 2, 2, 3, 4, 5, 6, 7, (8), 8, 9, 10, 11, 12, 13, 13, 14, 15\n};\nsigned int _4bitdecode[16] = {-9, -8, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 8};\n#else\nsigned char _4bitencode[33] = {\n\t0,\t0, 0, 1, 1, 1, 2, 2, \n\t3, 3, 4, 4, 5, 5, 6, 7, \n\t8, (8), 9, 10, 11, 12, 12, 13, \n\t13, 13, 14, 14, 14, 15, 15, 15, \n\t15\n};\nsigned int _4bitdecode[16] = {-16, -13, -10, -8, -6, -4, -2, -1, 1, 2, 4, 6, 8, 10, 13, 16};\n#endif\n\nlong Compress_Frame(void * source, void * dest, long size)\n{\n\tunsigned char\t*s = (unsigned char *)source;\n\tunsigned char\t*d = (unsigned char *)dest;\n\tint\t\t\t\tdelta;\n\tunsigned int\tprevious = 0x80;\n\tlong\t\t\t\toutcount = 0;\n\tunsigned char\t*s4;\t\t\t\t// Scratch pointer into source data.\n\tunsigned int\tp4;\t\t\t\t// Scratch \"previous\" sample value.\n\tlong\t\t\t\tmax4;\n\tunsigned char\t*lastraw = 0;\t// Pointer to last raw sequence code.\n\tlong\t\t\t\tosize = size;\t// Copy of original compression data length.\n\n\t/*\n\t**\tReduce very small amplitudes to silence.  Usually a rather large\n\t**\tportion of a sample is hovering around the silence value.  This is\n\t**\tdue, in part, to the artifacting of the sample process.  These low\n\t**\tamplitudes are not audible.\n\t*/\n\tmax4 = size;\n#if(FALSE)\n\twhile (max4) {\n\t\tint delta = (int)s[1] - (int)s[0];\n\n\t\t/*\n\t\t**\tFor steep sample transitions that just border on the range of 4 bit\n\t\t**\tdeltas, adjust them to fit.  This results in small savings but at\n\t\t**\tno loss to audio quality.\n\t\t*/\n\t\tif (delta == -18)  s[1] += 2;\n\t\tif (delta == -17)  s[1]++;\n\t\tif (delta == 18)  s[1] -= 2;\n\t\tif (delta == 17)  s[1]--;\n\n\t\tif ((*s > 0x7F && *s < 0x81) && s[1] > 0x7F && s[1] < 0x81) *s = 0x80; \n\t\ts++;\n\t\tmax4--;\n\t}\n#endif\n\ts = (unsigned char *)source;\n\n\twhile (size > 0 && outcount < osize) {\n\n\t\t/*\n\t\t**\tFirst check for runs of zero deltas.  If a run of at least\n\t\t**\tany can be found, then output it.\n\t\t*/\n\t\ts4 = s;\n\t\tmax4 = MIN(63+1, size);\n\t\tfor (int i = 0; i < max4; i++) {\n\t\t\tif (previous != *s4++) break;\n\t\t}\n\t\tif (i > 2) {\n\t\t\t/*\n\t\t\t**\tWhen there is a code transition, terminate any run of raw\n\t\t\t**\tsamples.\n\t\t\t*/\n\t\t\tlastraw = 0;\n\n\t\t\t*d++ = (i-1) | (CODE_SILENCE<<6);\n\t\t\toutcount++;\n\t\t\ts += i;\n\t\t\tsize -= i;\n\t\t\tLog_0Bit(i);\n\t\t\tLog_Overhead(1);\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tIf there are fewer than 4 samples remaining, then using delta\n\t\t**\tcompression is inefficient.  Just drop into the raw routine\n\t\t*/\n\t\tif (size > 4) {\n\n\t\t\ts4 = s;\n\t\t\tp4 = previous;\n\n\t\t\t/*\n\t\t\t**\tFind out the number of lossless 2 bit deltas available.  These\n\t\t\t**\tdeltas are always present in quads.  The compressed code is\n\t\t\t**\tthe delta quad count followed by the deltas in bit packed\n\t\t\t**\tbytes.\n\t\t\t*/\n\t\t\tmax4 = MIN(64L*4L + 4L + 4L, size);\n\t\t\tfor (unsigned i = 0; i < max4; i++) {\n\t\t\t\tdelta = ((int)*s4++) - p4;\n\t\t\t\tif (delta < -2 || delta > 1 /*|| !delta*/) break;\n\t\t\t\t//if (delta < -2 || delta > 2 || !delta) break;\n\t\t\t\tp4 += _2bitdecode[_2bitencode[delta+2]];\n\n\t\t\t\tif (((signed)p4) < 0) p4 = 0;\n\t\t\t\tif (((signed)p4) > 255) p4 = 255;\n\t\t\t}\n\t\t\ti >>= 2;\t\t\t\t\t// Delta 2 always occur in quads -- force this.\n\n\t\t\t/*\n\t\t\t**\tIf there is the minimum benificial number of delta 2s available,\n\t\t\t**\tthen compress them.\n\t\t\t*/\n\t\t\tif (i) {\n\t\t\t\tLog_2Bit(i*4);\n\t\t\t\tLog_Overhead(1);\n\n\t\t\t\t/*\n\t\t\t\t**\tWhen there is a code transition, terminate any run of raw\n\t\t\t\t**\tsamples.\n\t\t\t\t*/\n\t\t\t\tlastraw = 0;\n\n\t\t\t\t/*\n\t\t\t\t**\tOutput the delta 4 pair count.  This is the number of pairs\n\t\t\t\t**\tminus the 'free' two pairs already assumed to be there.\n\t\t\t\t*/\n\t\t\t\ti = MIN(i, 63+1);\n\t\t\t\t*d++ = (i-1) | (CODE_2BIT<<6);\n\t\t\t\toutcount++;\n\n\t\t\t\tfor (int dd = 0; dd < i; dd++) {\n\t\t\t\t\tint delta1, delta2, delta3, delta4;\n\n\t\t\t\t\tdelta1 = _2bitencode[(((int)*s++) - previous)+2];\n\t\t\t\t\tprevious += _2bitdecode[delta1];\n\t\t\t\t\tif (((signed)previous) < 0) previous = 0;\n\t\t\t\t\tif (((signed)previous) > 255) previous = 255;\n\t\t\t\t\tsize--;\n\n\t\t\t\t\tdelta2 = _2bitencode[(((int)*s++) - previous)+2];\n\t\t\t\t\tprevious += _2bitdecode[delta2];\n\t\t\t\t\tif (((signed)previous) < 0) previous = 0;\n\t\t\t\t\tif (((signed)previous) > 255) previous = 255;\n\t\t\t\t\tsize--;\n\n\t\t\t\t\tdelta3 = _2bitencode[(((int)*s++) - previous)+2];\n\t\t\t\t\tprevious += _2bitdecode[delta3];\n\t\t\t\t\tif (((signed)previous) < 0) previous = 0;\n\t\t\t\t\tif (((signed)previous) > 255) previous = 255;\n\t\t\t\t\tsize--;\n\n\t\t\t\t\tdelta4 = _2bitencode[(((int)*s++) - previous)+2];\n\t\t\t\t\tprevious += _2bitdecode[delta4];\n\t\t\t\t\tif (((signed)previous) < 0) previous = 0;\n\t\t\t\t\tif (((signed)previous) > 255) previous = 255;\n\t\t\t\t\tsize--;\n\n\t\t\t\t\t*d++ = (delta4<<6) | (delta3<<4) | (delta2<<2) | delta1;\n\t\t\t\t\toutcount++;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\n\t\t\t} else {\n\n\t\t\t\ts4 = s;\n\t\t\t\tp4 = previous;\n\n\t\t\t\t/*\n\t\t\t\t**\tFind out the number of lossless 4 bit deltas follow.  These\n\t\t\t\t**\tdeltas are always present in pairs.  The compressed code is\n\t\t\t\t**\tthe delta pair count followed by the deltas in nibble packed\n\t\t\t\t**\tbytes.\n\t\t\t\t*/\n\t\t\t\tmax4 = MIN(64L*2L+4L+4L, size);\n\t\t\t\tfor (unsigned i = 0; i < max4; i++) {\n\t\t\t\t\tdelta = ((int)*s4++) - p4;\n\t\t\t\t\tif (delta < -9 || delta >= 9 /*|| !delta*/) break;\n\t\t\t\t\t//if (delta < -16 || delta > 16 || !delta) break;\n\t\t\t\t\tp4 += _4bitdecode[_4bitencode[delta+9]];\n\t\t\t\t\t//p4 += _4bitdecode[_4bitencode[delta+16]];\n\t\t\t\t\tif (((signed)p4) < 0) p4 = 0;\n\t\t\t\t\tif (((signed)p4) > 255) p4 = 255;\n\t\t\t\t}\n\t\t\t\ti >>= 1;\t\t\t\t\t// Delta 4 always occur in pairs -- force this.\n\n\t\t\t\t/*\n\t\t\t\t**\tIf there is the minimum benificial number of delta 4s available,\n\t\t\t\t**\tthen compress them.\n\t\t\t\t*/\n\t\t\t\tif (i) {\n\t\t\t\t\tLog_4Bit(2*i);\n\t\t\t\t\tLog_Overhead(1);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tWhen there is a code transition, terminate any run of raw\n\t\t\t\t\t**\tsamples.\n\t\t\t\t\t*/\n\t\t\t\t\tlastraw = 0;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tOutput the delta 4 pair count.  This is the number of pairs\n\t\t\t\t\t**\tminus the 'free' two pairs already assumed to be there.\n\t\t\t\t\t*/\n\t\t\t\t\ti = MIN(i, 63+1);\n\t\t\t\t\t*d++ = (i-1) | (CODE_4BIT<<6);\n\t\t\t\t\toutcount++;\n\n\t\t\t\t\tfor (int dd = 0; dd < i; dd++) {\n\t\t\t\t\t\tint delta1, delta2;\n\n\t\t\t\t\t\tdelta1 = _4bitencode[(((int)*s++) - previous) + 9];\n\t\t\t\t\t\t//delta1 = _4bitencode[(((int)*s++) - previous) + 16];\n\t\t\t\t\t\tprevious += _4bitdecode[delta1];\n\t\t\t\t\t\tif (((signed)previous) < 0) previous = 0;\n\t\t\t\t\t\tif (((signed)previous) > 255) previous = 255;\n\t\t\t\t\t\tsize--;\n\n\t\t\t\t\t\tdelta2 = _4bitencode[(((int)*s++) - previous) + 9];\n\t\t\t\t\t\t//delta2 = _4bitencode[(((int)*s++) - previous) + 16];\n\t\t\t\t\t\tprevious += _4bitdecode[delta2];\n\t\t\t\t\t\tif (((signed)previous) < 0) previous = 0;\n\t\t\t\t\t\tif (((signed)previous) > 255) previous = 255;\n\t\t\t\t\t\tsize--;\n\n\t\t\t\t\t\t*d++ = (delta2 << 4) | (delta1 & 0x0F);\n\t\t\t\t\t\toutcount++;\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tRaw output since deltas were unsuccessful.  If this is a run\n\t\t**\tof raw output, then merely tack it onto the run rather than\n\t\t**\tcreate a new code sequence.\n\t\t*/\n\t\tif (lastraw) {\n\t\t\t*lastraw = (*lastraw)+1;\n\n\t\t\t/*\n\t\t\t**\tThere is only so much a run code can accomodate.  If the limit\n\t\t\t**\thas been reached, then terminate this code.  A new one will be\n\t\t\t**\tcreated if necessary.\n\t\t\t*/\n\t\t\tif ((*lastraw & 0x1F) == 0x1F) {\n\t\t\t\tlastraw = 0;\n\t\t\t}\n\t\t} else {\n\t\t\t\n\t\t\t/*\n\t\t\t**\tIf there is no current raw dump of samples, then check to see if\n\t\t\t**\tthis sample can fit into a 5 bit delta.  If it can, then store\n\t\t\t**\tit as such as a parasite to the \"raw\" code.  This will save a byte\n\t\t\t** for any stray 5 bit deltas that happen along.  It is expected that\n\t\t\t**\tthis is more frequent than 6 or more bit deltas that would necessitate\n\t\t\t**\tthe use of the RAW code.\n\t\t\t*/\n\t\t\tdelta = ((int)*s) - previous;\n\t\t\tif (delta >= -16 && delta <= 15) {\n\t\t\t\tlastraw = 0;\n\t\t\t\t*d++ = (CODE_RAW<<6) | 0x20 | (delta & 0x1F);\n\t\t\t\toutcount++;\n\t\t\t\tprevious = *s++;\n\t\t\t\tsize--;\n\t\t\t\tLog_5Bit(1);\n\t\t\t\tcontinue;\n\t\t\t} else {\n\t\t\t\tlastraw = d;\n\t\t\t\t*d++ = (CODE_RAW<<6);\n\t\t\t\tLog_Overhead(1);\n\t\t\t\toutcount++;\n\t\t\t}\n\t\t}\n\t\tLog_Raw(1);\n\t\t*d++ = previous = *s++;\n\t\tsize--;\n\t\toutcount++;\n\t}\n\n\t/*\n\t**\tCheck to see if the compression process actually resulted in smaller\n\t**\tdata size.  In some cases, the 'compressed' data is actually larger.  In\n\t**\tthis case, just output the raw frame.  If the compressed and actual frame\n\t**\tsize match, then it is presumed that no compression occurs.\n\t*/\n\tif (outcount >= osize) {\n\t\tmemcpy(dest, source, (size_t)osize);\n\t\toutcount = osize;\n\t\tLog_RawFrame(1);\n\t}\n\n\treturn(outcount);\n}\n\n#if(FALSE)\nlong Decompress_Frame(void * source, void * dest, long size)\n{\n\tunsigned int\tprevious = 0x0080;\n\tsigned char\t\t*s = (signed char *)source;\n\tunsigned char\t*d = (unsigned char *)dest;\n\tlong incount = 0;\n\n\t/*\n\t**\tUncompress the source data until the buffer is filled.\n\t*/\n\twhile (size > 0) {\n\t\tsigned char code;\t\t// Compression code.\n\t\tint counter;\n\n\t\tcode = *s++;\n\t\tcounter = (code & 0x3F) + 1;\n\t\tincount++;\n\n\t\tswitch ((code >> 6) & 0x03) {\n\t\t\tcase CODE_RAW:\n\n\t\t\t\t/*\n\t\t\t\t**\tThe \"raw\" code could actually contain an embedded 5 bit delta.\n\t\t\t\t**\tIf this is the case then this is a self contained code.  Extract\n\t\t\t\t**\tand process the delta.\n\t\t\t\t*/\n\t\t\t\tif ((counter-1) & 0x20) {\n\t\t\t\t\tcounter = (counter-1) & 0x1F;\n\t\t\t\t\tif (counter & 0x10) counter |= 0xFFE0;\n\t\t\t\t\tprevious = *d++ = previous + counter;\n\t\t\t\t\tsize--;\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tNormal run of raw samples.\n\t\t\t\t\t*/\n\t\t\t\t\tmemcpy(d, s, counter);\n\t\t\t\t\tincount += counter;\n\t\t\t\t\tsize -= counter;\n\t\t\t\t\td += counter-1;\n\t\t\t\t\ts += counter;\n\t\t\t\t\tprevious = *d++;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase CODE_4BIT:\n\t\t\t\twhile (counter) {\n\t\t\t\t\tint delta;\n\n\t\t\t\t\tdelta = *s++;\n\t\t\t\t\tincount--;\n\n\t\t\t\t\tprevious += (signed)_4bitdecode[delta & 0x0F];\n\t\t\t\t\tif (((signed)previous) < 0) previous = 0;\n\t\t\t\t\tif (((signed)previous) > 255) previous = 255;\n\t\t\t\t\t*d++ = previous;\n\t\t\t\t\tsize--;\n\n\t\t\t\t\tprevious += (signed)_4bitdecode[(delta >> 4) & 0x0F];\n\t\t\t\t\tif (((signed)previous) < 0) previous = 0;\n\t\t\t\t\tif (((signed)previous) > 255) previous = 255;\n\t\t\t\t\t*d++ = previous;\n\t\t\t\t\tsize--;\n\n\t\t\t\t\tcounter--;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase CODE_2BIT:\n\t\t\t\twhile (counter) {\n\t\t\t\t\tint delta;\n\n\t\t\t\t\tdelta = *s++;\n\t\t\t\t\tincount--;\n\n\t\t\t\t\tprevious += (signed)_2bitdecode[delta & 0x03];\n\t\t\t\t\tif (((signed)previous) < 0) previous = 0;\n\t\t\t\t\tif (((signed)previous) > 255) previous = 255;\n\t\t\t\t\t*d++ = previous;\n\t\t\t\t\tsize--;\n\n\t\t\t\t\tprevious += (signed)_2bitdecode[(delta >> 2) & 0x03];\n\t\t\t\t\tif (((signed)previous) < 0) previous = 0;\n\t\t\t\t\tif (((signed)previous) > 255) previous = 255;\n\t\t\t\t\t*d++ = previous;\n\t\t\t\t\tsize--;\n\n\t\t\t\t\tprevious += (signed)_2bitdecode[(delta >> 4) & 0x03];\n\t\t\t\t\tif (((signed)previous) < 0) previous = 0;\n\t\t\t\t\tif (((signed)previous) > 255) previous = 255;\n\t\t\t\t\t*d++ = previous;\n\t\t\t\t\tsize--;\n\n\t\t\t\t\tprevious += (signed)_2bitdecode[(delta >> 6) & 0x03];\n\t\t\t\t\tif (((signed)previous) < 0) previous = 0;\n\t\t\t\t\tif (((signed)previous) > 255) previous = 255;\n\t\t\t\t\t*d++ = previous;\n\t\t\t\t\tsize--;\n\n\t\t\t\t\tcounter--;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\tcase CODE_SILENCE:\n\t\t\t\tmemset(d, previous, counter);\n\t\t\t\td += counter;\n\t\t\t\tsize -= counter;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn (incount);\n}\n#endif\n"
  },
  {
    "path": "TOOLS/AUDIOMAK/AUDIOMAK.PJT",
    "content": ";Codewright Project File (do not remove or modify this line)\n[ProjInit]\nProjSetConfigFlags=0x00010140\n\n[State]\nSysSetCwd='C:\\PROJECTS\\C&C\\CODE\\AUDIOMAK'\nSrchSetFlags=0x20aa\nFileSortMode=0x13\nStateWindowFrame=-1,0,1020,690,0x0981f5fa\n_StateWindow=0,0,1024,657,0x00000108,'c:\\projects\\c&c\\code\\audiomak\\audiomak.cpp',240,7,244,32,32,0,32,32,32,32,8,65535,65535,1,0,'8514oem',65518,255,49,0,4,243,14,15,241,252,249,560,28,400,0,246,252,245,242,0,0,0,0,0\n_StateBuffer='c:\\projects\\c&c\\code\\audiomak\\audiomak.cpp',0x0400048e,560,28,25,'4 7','',0x0,''\n_StateBuffer='c:\\projects\\c&c\\code\\audiomak\\scode.asm',0x0400048e,30,64,25,'9 17','',0x0,''\nWrapEnable=0\n_StateHistory=SEARCH,'UncompBuffer','saved','orig','FALSE','tasm','TASM','tasm','ASSEMBLER','Decom','.asm.'\n_StateHistory=REPLACE,'audiomak','desired','long','unsigned','unsigned char','int','source'\n_StateHistory=FILELIST,'c:\\projects\\c&c\\code\\audiomak\\cointabl.voc','c:\\projects\\c&c\\code\\audiomak\\cointabl.wav','c:\\projects\\c&c\\code\\audiomak\\globals.cpp','c:\\projects\\c&c\\code\\audiomak\\bfeared.aud','c:\\projects\\c&c\\code\\audiomak\\audiomak.asm','d:\\library\\source\\soundio.c','c:\\projects\\c&c\\code\\audiomak\\scode.asm','d:\\library\\wwlib.i','c:\\projects\\c&c\\code\\audiomak\\makefile','d:\\library\\source\\makefile'\n_StateHistory=GOTOMARK,'1','2','1'\n_StateHistory=GOTOLINE,'364','398','424','431','465'\n\n[Editor]\nFilterDeleteList \nFilterAdd='Source Files','*.c;*.h;*.asm;*.inc',-1\nFilterAdd='All Files','*.*',-1\nFilterAdd='C++ Source Files','*.cpp;*.h;*.asm;*.inc',-1\nStateSetMarkLevel=7\nClipboardSetTermStr='\\r\\n',0\nClipboardEnableTermStr=1\nClipboardSetSepStr='\\r\\n',0\nClipboardEnableSepStr=1\nScrapSetCount=1\nExtColorsAssoc='.cpp',1\nExtIndentEnableAssoc='.cpp',1\nExtSetDelimiters=.cpp,a-zA-Z_0-9\nExtColorsAssoc='.h',1\nExtIndentEnableAssoc='.h',1\nExtSetDelimiters=.h,a-zA-Z_0-9\nExtSetDelimiters=.*,a-zA-Z_0-9\nExtColorsAssoc='.int',1\nExtIndentEnableAssoc='.int',1\nExtSetDelimiters=.int,a-zA-Z_0-9\nExtColorsAssoc='.lst',1\nExtIndentEnableAssoc='.lst',1\nExtColorsAssoc='.asm',1\nExtSetDelimiters=.asm,a-zA-Z_0-9\nExtColorsAssoc='.scr',1\nExtIndentEnableAssoc='.scr',1\nExtSetDelimiters=.scr,a-zA-Z_0-9\nExtColorsAssoc='.c',1\nExtIndentEnableAssoc='.c',1\nExtSetDelimiters=.c,a-zA-Z_0-9\nExtColorsAssoc='.ash',1\nExtSetDelimiters=.ash,a-zA-Z_0-9\nExtColorsAssoc='.i',1\nExtIndentEnableAssoc='.i',1\nExtSetDelimiters=.i,a-zA-Z_0-9\nAutosave=15,15\nAutosaveDir=''\nExtSetUpdateDelay=10\nExtDelayedColoring=1\nExtCommentSearchLimit=200\nKeyDelay=635\nKeyRepeat=190\nBufSetGlobalBackupSpec='%b.bak'\n_FontDefault=0,'8514oem',65513,255,49,400,0\nSysSetDefault=DEFAULT_WINDOW_LEFT_MARGIN,4\nSysSetDefault=DEFAULT_WINDOW_VIS_MARGIN_COL,0\nSysSetDefault=DEFAULT_WINDOW_HINC,8\nSysSetDefault=DEFAULT_WINDOW_VIS_VIRTSPACES,32\nSysSetDefault=DEFAULT_WINDOW_VIS_VIRTLINES,32\nSysSetDefault=DEFAULT_WINDOW_VIS_TABS,32\nSysSetDefault=DEFAULT_WINDOW_VIS_SPACES,32\nSysSetDefault=DEFAULT_WINDOW_VIS_ELISION,0\nSysSetDefault=DEFAULT_WINDOW_VIS_EOL,32\nSysSetDefault=DEFAULT_WINDOW_VIS_EOF,32\nSysSetDefault=DEFAULT_WINDOW_SYSFLAGS,0x118\nSysSetDefault=DEFAULT_BUFFER_AUTOINDENT_MODE,0x0\nSysSetDefault=DEFAULT_BUFFER_BACKUP_SPEC,''\nSysSetDefault=DEFAULT_BUFFER_TABS,'5 9'\nSysSetDefault=DEFAULT_BUFFER_MAX_TAB,200\nSysSetDefault=DEFAULT_BUFFER_MAX_VLINES,25\nSysSetDefault=DEFAULT_BUFFER_SYSFLAGS,0xc800048e\n_RestoreSysFlags=0x0991f5fa, 0xfffffffc\n\n[Compiler]\nBrowseSetFile='c:\\projects\\c&c\\code\\audiomak\\audiomak.ptg'\nTagSetFile='c:\\projects\\c&c\\code\\audiomak\\audiomak.tag'\nCompilerAddBuild='Microsoft Assembler',1073741880,'ftee masm -w2 -zi %r%e;','','','','','_MicrosoftErrorInfo','','%v%p','','','','','',0\nCompilerAddBuild='Borland C++',1073742089,'ftee make -DDEBUG=1 %r.obj','','','','','','','','ftee make -DDEBUG=1 %r.obj','','','','',49152\nCompilerAddBuild='Borland Turbo Assembler',1073741835,'ftee make -B %r.obj','','','','','','','','','','','','',16384\nCompilerAddBuild='$_cw_proj_hash_$',1073741875,'','ftee maker -B -DDEBUG=1 %r.obj','ftee maker -DDEBUG=1','','','_TasmErrorInfo','proj.err','c:\\projects\\c&c\\code\\audiomak','','_BorlandCppErrorInfo','','','',197376\nCompilerAddBuild='Default Project',1073741880,'','ftee make','ftee make','','','_ErrorInfoDefault','proj.err','%v%p','','','','','',0\nCompilerAddBuild='Microsoft C',1073741835,'ftee cl -c -AL -Gsw -Ow -Zpe  %r%e','','','','','','','','','','','','',0\nCompilerAddBuild='Script',1073741880,'ftee make %r.inf','ftee make','ftee make','','','_BorlandCppErrorInfo','','','','','','','',0\nCompilerAddBuild='Zortech C++',1073741880,'ftee ztc -a -b -c -g -ml -W %r%e','','','','','_ZortechCppErrorInfo','','%v%p','','','','','',0\nCompilerAssign='Borland C++','.scr'\nCompilerAssign='Borland C++','.int'\nCompilerAssign='Borland C++','.c'\nCompilerNewExt=.prg\nCompilerAssign='Microsoft C','.h'\nCompilerAssign='Borland C++','.cpp'\nCompilerAssign='Default Project','.*'\nCompilerAssign='Zortech C++','.cxx'\nCompilerAssign='Borland Turbo Assembler','.asm'\nCompilerAssign='Borland C++','.hpp'\n"
  },
  {
    "path": "TOOLS/AUDIOMAK/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n.AUTODEPEND\n\nOBJECTS = audiomak.obj scode.obj\n\n.cpp.obj:\n\tbcc {$*.cpp }\n\n.asm.obj:\n\ttasm $<,$&.obj\n\t\naudiomak.exe: turboc.cfg tasm.cfg tlink.cfg $(OBJECTS)\n\ttlink @&&!\n\tc0l.obj $(OBJECTS)\n\taudiomak.exe\n\taudiomak.map\n\tCL.LIB MATHL.LIB EMU.LIB\n!\n\n\n####################################################################\n# Creates the TURBOC configuration file (also affects CPP.EXE)\nturboc.cfg: makefile\n\tcopy &&!\n -v\t\t\t\t\t# Debugging output.\n -y\n -Vt\t\t\t\t\t# Virtual table pointer comes at end of class members (NEVER CHANGE).\n -Vb-\t\t\t\t\t# Always near pointer to virtual table.\n -a-\t\t\t\t\t# Structures are packed (not byte aligned).\n -b-\t\t\t\t\t# Enums as small as possible.\n -3\t\t\t\t   # Enable 386 instructions.\n -ml\t\t\t\t\t# Large model.\n -C-\t\t\t\t\t# Don't allow nested comments (DON'T CHANGE THIS).\n -c\t\t\t\t\t# Just compile -- don't link.\n -Jg\t\t\t\t\t# Template instances are merged to avoid duplicates.\n -Id:\\bc4\\include\t# Header search path.\n -P-\t\t\t\t\t# If extension = .CPP then compile as C++, otherwise treat as C.\n -w\t\t\t\t\t# Enable all warnings.\n# -w!\t\t\t\t\t# Treat all warnings as errors.\n -X-\t\t\t\t\t# Turn on autodependency checking.\n -RT\t\t\t\t\t# Enable run time type itentification.\n -x\t\t\t\t\t# Enable exception handling code.\n -k-\t\t\t\t\t# Optimize: Use abbreviated stack frame.\n -vi\t\t\t\t\t# Turns \"inline\" expansion on.\n -Z\t\t\t\t\t# Optimize: Supress redundant register loads.\n -Oi\t\t\t\t\t# Optimize: Helper functions expanded inline.\n -O\t\t\t\t\t# Optimize: Jump optimization.\n -Op\t\t\t\t\t# Optimize: Copy propagation to supress reloads.\n -Ov\t\t\t\t\t# Optimize: Speeds array indexing inside of loops.\n -Og\t\t\t\t\t# Optimize: Eliminates common subexpressions (globally).\n -Oc\t\t\t\t\t# Optimize: Eliminates common subexpressions (locally).\n -Ol\t\t\t\t\t# Optimize: Use REP instruction where possible.\n -d\t\t\t\t\t# Optimize: Duplicate strings are merged.\n -r\t\t\t\t\t# Try to put auto variables into registers.\n -V\t\t\t\t\t# Use smart virtual tables (only usable with BCC and TLINK).\n -dc-\t\t\t\t\t# Keep strings in the data segment (DON'T CHANGE THIS).\n -Ff\t\t\t\t\t# Put very very large objects into the far segment.\n -K2-\t\t\t\t\t# Treat \"char\" different from \"signed char\" or \"unsigned char\".\n -Oa\t\t\t\t\t# Optimize: Assumes no pointer aliasing (could cause bugs)!\n -R-\t\t\t\t\t# Don't include browser data (only used by IDE).\n# -Oe\t\t\t\t\t# Optimize: Global register allocation tracking enabled.\n# -Ob\t\t\t\t\t# Optimize: Dead code elimination.\n# -Om\t\t\t\t\t# Optimize: Remove invariant code from loops.\n# -p\t\t\t\t\t# Pascal calling convention default.\n# -pr\t\t\t\t\t# Regiser calling convention default.\n# -po\t\t\t\t\t# Pass \"this\" in registers when calling member functions.\n# -f-\t\t\t\t\t# Floating point prohibited.\n# -Yo\t\t\t\t\t# Compile as overlay module.\n# -Ox\t\t\t\t\t# Optimize: Execution speed.\n! turboc.cfg /Q\n\n####################################################################\n# Creates TASM config file.\ntasm.cfg: makefile\n\tcopy &&!\n /Zi\t\t\t\t\t# Include debug information into object file.\n /w+ICG\n /w-PDC\n /t\n /w2\t\t\t\t\t# Maximum warning level.\n /ml \t\t\t\t\t# Large model.\n /w+\n /v\n /JIDEAL \t\t\t# Ideal mode.\n /JP386N\t\t\t\t# Enable 386 instructions.\n /UT300\t\t\t\t# Force compatibility with old TASM.\n! tasm.cfg\n\n####################################################################\n# Creates the TLINK.CFG file which implicitly controls linking.\ntlink.cfg: makefile\n\tcopy &&!\n /Ld:\\bc4\\lib\n /v \n /c \n /e\n /Tde \n! tlink.cfg /Q\n\n"
  },
  {
    "path": "TOOLS/AUDIOMAK/SCODE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\n\tIDEAL\nIDEAL_MODE\tEQU\t1\n\tVERSION T300\t\t; Code written for V3.0 TASM version.\n\tIDEAL\n\tP386N\t\t\t; target machine.\n\tSMART\t\t\t; Enable optimizations.\n\tWARN\t\t\t; Full warnings.\n\tLOCALS ??\n\tMODEL\tLARGE @filename\n;\tINCLUDE\t\"d:\\library\\wwlib.i\"\n\nCODE_2BIT\tEQU\t0\nCODE_4BIT\tEQU\t1\nCODE_RAW\tEQU\t2\nCODE_SILENCE\tEQU\t3\nMAGICNUMBER\tEQU\t00000DEAFh\nMAGICNUMBER2\tEQU\t0BABEBABEh\n\n;\tVERSION T300\t\t; Code written for V3.0 TASM version.\n;\tP386N\t\t\t; target machine.\n;\tMODEL\tLARGE @filename\n;\tWARN\t\t\t; Full warnings.\n;\tLOCALS ??\n\n\tCODESEG\n\n_2bitdecode\tDB\t-2, -1, 0, 1\n;_2bitdecode\tDB\t-2, -1, 1, 2\n_4bitdecode\tDB\t-9,-8,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,8\n;_4bitdecode\tDB\t-16,-13,-10,-8,-6,-4,-2,-1,1,2,4,6,8,10,13,16\n\n\tGLOBAL\tC Decompress_Frame:FAR\n\tPROC\tC Decompress_Frame FAR USES bx cx edx ds si es di bp\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tcount:WORD\n\n\tLOCAL\tprevious:BYTE\n\tLOCAL\tincount:WORD\n\n\t; Initialize counter for number of bytes read from source.\n\tmov\t[incount],0\n\n\t; Verify parameters for legality.\n\tcmp\t[source],0\n\tje\t??fini\n\tcmp\t[dest],0\n\tje\t??fini\n\tcmp\t[count],0\n\tje\t??fini\n\n\t; Fetch parameter values into working registers.\n\tlds\tsi,[source]\t\t; Pointer to source data.\n\tles\tdi,[dest]\t\t; Pointer to destination data.\n\tmov\tcx,[count]\t\t; Number of bytes to fill dest buffer.\n\tmov\tdl,080h\t\t\t; Previous sample (starting value).\n\n??mainloop:\n\t; Check to see if the destination is full.  Exit if so.\n\tcmp\tcx,0\n\tjle\t??fini\n\n\t; Fetch code byte from input stream.\n\txor\tah,ah\n\tmov\tal,[ds:si]\n\tinc\t[incount]\n\tinc\tsi\n\tshl\tax,2\t\t\t; AH contains code.\n\tshr\tal,2\t\t\t; AL contains sub-code data.\n\n\t; Check to see if a raw sequence follows.\n\tcmp\tah,CODE_RAW\n\tjne\tshort ??try4bit\n\n\t; The code contains either a 5 bit delta or a count of raw samples\n\t; to dump out.\n\ttest\tal,00100000b\n\tje\tshort ??justraw\n\n\t; The lower 5 bits are actually a signed delta.  Sign extend the\n\t; delta and add it to the stream.\n\tshl\tal,3\n\tsar\tal,3\n\tadd\tdl,al\n\tmov\t[es:di],dl\n\tdec\tcx\n\tinc\tdi\n\tjmp\t??mainloop\n\n\t; The lower 5 bits hold a count of the number of raw samples that\n\t; follow this code.  Dump these samples to the output buffer.\n??justraw:\n\tmov\tbx,cx\n\txor\tah,ah\n\tinc\tal\n\tmov\tcx,ax\n\tshr\tcx,1\n\trep movsw\n\tadc\tcx,cx\n\trep movsb\n\tmov\tcx,bx\n\tadd\t[incount],ax\n\tsub\tcx,ax\n\tdec\tdi\n\tmov\tdl,[es:di]\t\t; Set \"previous\" value.\n\tinc\tdi\n\tjmp\t??mainloop\n\n\t; Check to see if this is a 4 bit delta code sequence.\n??try4bit:\n\tinc\tal\t\t\t; Following codes use AL+1\n\tcmp\tah,CODE_4BIT\n\tjne\tshort ??try2bit\n\n\t; A sequence of 4bit deltas follow.  AL equals the number of nibble\n\t; packed delta bytes to process.\n??bit4loop:\n\t; Fetch nibble packed delta codes.\n\tmov\tah,[ds:si]\n\tmov\tbl,ah\n\tinc\t[incount]\n\tinc\tsi\n\n\t; Add first delta to 'previous' sample already in DL.\n\tand\tbx,00001111b\n\n\tadd\tdl,[cs:_4bitdecode+bx]\t\t; Add in delta\n\tpushf\n\tcmp\t[cs:_4bitdecode+bx],0\n\tjl\tshort ??neg1\n\tpopf\n\tjnc\tshort ??ok1\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok1\n??neg1:\n\tpopf\n\tjc\tshort ??ok1\n\txor\tdl,dl\n??ok1:\n\tmov\tdh,dl\t\t\t\t; DH now holds new 'previous' sample.\n\n\tmov\tbl,ah\n\tshr\tbl,4\n\tadd\tdh,[cs:_4bitdecode+bx]\t\t; Add in delta\n\tpushf\n\tcmp\t[cs:_4bitdecode+bx],0\n\tjl\tshort ??neg2\n\tpopf\n\tjnc\tshort ??ok2\n\tmov\tdh,0FFh\n\tjmp\tshort ??ok2\n??neg2:\n\tpopf\n\tjc\tshort ??ok2\n\txor\tdh,dh\n??ok2:\n\n\t; Output the two sample bytes.\n\tmov\t[es:di],dx\n\tsub\tcx,2\n\tadd\tdi,2\n\n\t; Put the correct 'previous' sample in DL where it belongs.\n\tmov\tdl,dh\n\n\t; If there are more deltas to process then loop back.\n\tdec\tal\n\tjnz\tshort ??bit4loop\n\n\tjmp\t??mainloop\n\n\t; Check to see if 2 bit deltas need to be processed.\n??try2bit:\n\tcmp\tah,CODE_2BIT\n\tjne\t??zerodelta\n\n\t; A sequence of 2bit deltas follow.  AL equals the number of \n\t; packed delta bytes to process.\n??bit2loop:\n\t; Fetch packed delta codes.\n\tmov\tah,[ds:si]\n\tinc\t[incount]\n\tinc\tsi\n\n\t; Add first delta to 'previous' sample already in DL.\n\tmov\tbl,ah\n\tand\tbx,000011b\n\tadd\tdl,[cs:_2bitdecode+bx]\t\t; Add in delta\n\n\tpushf\n\tcmp\t[cs:_2bitdecode+bx],0\n\tjl\tshort ??neg3\n\tpopf\n\tjnc\tshort ??ok3\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok3\n??neg3:\n\tpopf\n\tjc\tshort ??ok3\n\txor\tdl,dl\n??ok3:\n\n\tmov\tdh,dl\n\tror\tedx,8\n\n\tmov\tbl,ah\n\tshr\tbx,2\n\tand\tbl,00000011b\n\tadd\tdl,[cs:_2bitdecode+bx]\t\t; Add in delta\n\t\n\tpushf\n\tcmp\t[cs:_2bitdecode+bx],0\n\tjl\tshort ??neg4\n\tpopf\n\tjnc\tshort ??ok4\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok4\n??neg4:\n\tpopf\n\tjc\tshort ??ok4\n\txor\tdl,dl\n??ok4:\n\t\n\tmov\tdh,dl\n\tror\tedx,8\n\n\tmov\tbl,ah\n\tshr\tbx,4\n\tand\tbl,00000011b\n\tadd\tdl,[cs:_2bitdecode+bx]\t\t; Add in delta\n     \n\tpushf\n\tcmp\t[cs:_2bitdecode+bx],0\n\tjl\tshort ??neg5\n\tpopf\n\tjnc\tshort ??ok5\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok5\n??neg5:\n\tpopf\n\tjc\tshort ??ok5\n\txor\tdl,dl\n??ok5:\n\t\n\tmov\tdh,dl\n\tror\tedx,8\n\n\tmov\tbl,ah\n\tshr\tbx,6\n\tand\tbl,00000011b\n\tadd\tdl,[cs:_2bitdecode+bx]\t\t; Add in delta\n\t\n\tpushf\n\tcmp\t[cs:_2bitdecode+bx],0\n\tjl\tshort ??neg6\n\tpopf\n\tjnc\tshort ??ok6\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok6\n??neg6:\n\tpopf\n\tjc\tshort ??ok6\n\txor\tdl,dl\n??ok6:\n\t\n\t;mov\tdh,dl\n\tror\tedx,8\n\n\t; Output the two sample bytes.\n\tmov\t[es:di],edx\n\tsub\tcx,4\n\tadd\tdi,4\n\n\t; Put the correct 'previous' sample in DL where it belongs.\n\trol\tedx,8\n\n\t; If there are more deltas to process then loop back.\n\tdec\tal\n\tjnz\t??bit2loop\n\n\tjmp\t??mainloop\n\n\t; There is a run of zero deltas.  Zero deltas merely duplicate\n\t; the 'previous' sample the requested number of times.\n??zerodelta:\n\txor\tbh,bh\n\tmov\tbl,al\n\tmov\tal,dl\n\tsub\tcx,bx\n\txchg\tcx,bx\n\trep stosb\n\tmov\tcx,bx\n\tjmp\t??mainloop\n\n\t; Final cleanup and exit.\n??fini:\n\tmov\tax,[incount]\n\tret\n\n\tENDP\tDecompress_Frame\n\n\tEND\n\n"
  },
  {
    "path": "TOOLS/AUDIOMAK/TASM.CFG",
    "content": " /Zi\n /w+ICG\n /w-PDC\n /t\n /w2\n /ml\n /w+\n /v\n /JIDEAL\n /JP386N\n /UT300\n"
  },
  {
    "path": "TOOLS/AUDIOMAK/TLINK.CFG",
    "content": " /Ld:\\bc4\\lib\n /v \n /c \n /e\n /Tde \n"
  },
  {
    "path": "TOOLS/AUDIOMAK/TURBOC.CFG",
    "content": " -v\n -y\n -Vt\n -Vb-\n -a-\n -b-\n -3\n -ml\n -C-\n -c\n -Jg\n -Id:\\bc4\\include\n -P-\n -w\n -X-\n -RT\n -x\n -k-\n -vi\n -Z\n -Oi\n -O\n -Op\n -Ov\n -Og\n -Oc\n -Ol\n -d\n -r\n -V\n -dc-\n -Ff\n -K2-\n -Oa\n -R-\n"
  },
  {
    "path": "TOOLS/MIX/MIXFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n **             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                  **\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Data file creator.                                           *\n *                                                                                             *\n *                    File Name : MIXFILE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 6, 1994                                               *\n *                                                                                             *\n *                  Last Update : 10/27/94 [JLB]                                               *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Calc_CRC -- Calculate the CRC value of a block of data.                                   *\n *   compfunc -- Comparison function used by qsort().                                          *\n *   DataClass::DataClass -- Constructor for a data file object node.                          *\n *   DataClass::Process_Input -- Process the input file list and builds linked records.        *\n *   DataClass::Process_Output -- Creates the output data file from the component source files.*\n *   DataClass::~DataClass -- Destructor for the data file object.                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#pragma inline\n\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<ctype.h>\n#include\t<dir.h>\n#include\t<string.h>\n\n#define\tFALSE\t0\n#define\tTRUE\t1\n\nlong Calc_CRC(void const *data, long size);\n\n\n/********************************************************************\n**\tThis is the data block controlling class.  It is used for every data\n**\tfile as well as processing the entire data file list.\n*/\nclass DataClass {\n\tpublic:\n\t\tlong CRC;\n\t\tstatic short Count;\n\t\tstatic long TotalSize;\n\t\tstatic char *ExtFrom[10];\n\t\tstatic char *ExtTo[10];\n\t\tstatic int ExtCount;\n\t\tstatic char *AltPath[10];\n\t\tstatic int AltPathCount;\n\n\t\tDataClass(char const *filename);\n\t\t~DataClass(void);\n\t\tstatic void Process_Input(char const *infile, int quiet, int paths);\n\t\tstatic void Process_Output(char const *outfile);\n\n\t\tchar const * Output_Filename(void);\n\t\tchar const * Input_Filename(void);\n\n\tprivate:\n\t\tDataClass\t*Next;\t\t// Pointer to next file in chain.\n\t\tchar\t\t\t*Filename;\t// Raw original filename.\n\t\tlong\t\t\tSize;\t\t\t// Size of data element.\n\t\tlong\t\t\tOffset;\t\t// Offset within mixfile for data start.\n\t\tint\t\t\tIndex;\t\t// Write order number.\n\n\t\tstatic DataClass *First;\n\t\tstatic int Quiet;\n\t\tstatic int Paths;\n};\n\nchar *DataClass::AltPath[10];\nchar *DataClass::ExtFrom[10];\nchar *DataClass::ExtTo[10];\nint DataClass::ExtCount = 0;\nint DataClass::AltPathCount = 0;\nshort DataClass::Count = 0;\nDataClass * DataClass::First = 0;\nint DataClass::Quiet = FALSE;\nint DataClass::Paths = FALSE;\nlong DataClass::TotalSize = 0;\n\nint main(int argc, char ** argv)\n{\n\tclass UsageError{};\t\t// Parameter error or usage display desired.\n\tchar *infile = 0;\n\tchar *outfile = 0;\n\tint quiet = FALSE;\n\tint paths = FALSE;\n\n\t/*\n\t** Banner message.\n\t*/\n\tprintf(\"MIXFILE V1.4 (c)\\n\");\n\n\t/*\n\t**\tProcess the parameter list and dispatch the packing function.\n\t*/\n\ttry {\n\n\t\t/*\n\t\t**\tIf not enough parameters were specified, then immediately\n\t\t** display the usage instructions.\n\t\t*/\n\t\tif (argc < 2) throw UsageError();\n\n\t\ttry {\n\t\t\tfor (int index = 1; index < argc; index++) {\n\t\t\t\tchar *arg = argv[index];\n\n\t\t\t\tswitch (*arg) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tProcess any command line switches.\n\t\t\t\t\t*/\n\t\t\t\t\tcase '/':\n\t\t\t\t\tcase '-':\n\t\t\t\t\t\tswitch (toupper(arg[1])) {\n\t\t\t\t\t\t\tcase 'Q':\n\t\t\t\t\t\t\t\tquiet = TRUE;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 'S':\n\t\t\t\t\t\t\t\tpaths = TRUE;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 'E':\n\t\t\t\t\t\t\t\tif (DataClass::ExtCount >= sizeof(DataClass::ExtFrom)/sizeof(DataClass::ExtFrom[0])) {\n\t\t\t\t\t\t\t\t\tthrow \"Too many extensions specified\";\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tchar * ptr = strupr(strtok(&arg[2], \"=\"));\n\t\t\t\t\t\t\t\t\tif (*ptr == '.') ptr++;\n\t\t\t\t\t\t\t\t\tDataClass::ExtFrom[DataClass::ExtCount] = ptr;\n\n\t\t\t\t\t\t\t\t\tptr = strupr(strtok(NULL, \"=\\r\\n\"));\n\t\t\t\t\t\t\t\t\tif (*ptr == '.') ptr++;\n\t\t\t\t\t\t\t\t\tDataClass::ExtTo[DataClass::ExtCount] = ptr;\n\n\t\t\t\t\t\t\t\t\tDataClass::ExtCount++;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 'I':\n\t\t\t\t\t\t\t\tif (DataClass::AltPathCount >= sizeof(DataClass::AltPath)/sizeof(DataClass::AltPath[0])) {\n\t\t\t\t\t\t\t\t\tthrow \"Too many paths specified\";\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tchar dir[MAXDIR];\n\n\t\t\t\t\t\t\t\t\tstrcpy(dir, &arg[2]);\n\t\t\t\t\t\t\t\t\tif (dir[strlen(dir)-1] != '\\\\') {\n\t\t\t\t\t\t\t\t\t\tstrcat(dir, \"\\\\\");\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tDataClass::AltPath[DataClass::AltPathCount++] = strupr(strdup(dir));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tthrow \"Unrecognized option flag\";\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tProcess command line filenames for either input or output.\n\t\t\t\t\t*/\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tif (outfile) throw \"Unrecognized parameter\";\n\t\t\t\t\t\tif (!infile) {\n\t\t\t\t\t\t\tFILE *file = fopen(arg, \"r\");\n\t\t\t\t\t\t\tif (!file) throw \"Unable to open input file\";\n\t\t\t\t\t\t\tfclose(file);\n\t\t\t\t\t\t\tinfile = arg;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!outfile) {\n\t\t\t\t\t\t\toutfile = arg;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tPerform a last minute check to make sure both an input and\n\t\t\t**\toutput filename was specified.  If not, then throw an\n\t\t\t**\terror.\n\t\t\t*/\n\t\t\tif (!outfile) throw \"No output file specified\";\n\t\t\tif (!infile) throw \"No input file specified\";\n\n\t\t\t/*\n\t\t\t**\tProcess the data.\n\t\t\t*/\n\t\t\ttry {\n\t\t\t\tDataClass::Process_Input(infile, quiet, paths);\n\t\t\t\tDataClass::Process_Output(outfile);\n\t\t\t\tprintf(\"Created mix file '%s'\\nEmbedded objects = %d\\nTotal file size = %ld\\n\", outfile, DataClass::Count, DataClass::TotalSize);\n\t\t\t}\n\t\t\tcatch (char *message) {\n\t\t\t\tprintf(\"\\nERROR: %s.\\n\", message);\n\t\t\t\texit(EXIT_FAILURE);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tThis exception is called for any of the various fatal errors that\n\t\t**\tcan occur while parsing the parameters.\n\t\t*/\n\t\tcatch(char *message) {\n\t\t\tprintf(\"\\nERROR: %s.\\n\", message);\n\t\t\tthrow UsageError();\n\t\t}\n\t}\n\n\t/*\n\t**\tThis exception is thrown when the utility can't proceed and the\n\t**\tutility usage instructions are desired to be displayed.\n\t*/\n\tcatch(UsageError) {\n\t\tprintf(\"\\nUSAGE:  DATFILE <controlfile> <datafile>\\n\"\n\t\t\"\\n\"\n\t\t\"  <controlfile>        : list of filenames to pack\\n\"\n\t\t\"  <datafile>           : output data filename\\n\"\n\t\t\"  Options\\n\"\n\t\t\"    -q               : quiet operation\\n\"\n\t\t\"    -i<path>         : alternate to find files\\n\"\n\t\t\"    -e<ext1>=<ext2>  : changes file extensions from <ext1> to <ext2>\\n\"\n\t\t\"    -s               : record paths in ID\\n\");\n\t\texit(EXIT_FAILURE);\n\t}\n\n\treturn EXIT_SUCCESS;\n}\n\n\n/***********************************************************************************************\n * DataClass::Process_Input -- Process the input file list and builds linked records.          *\n *                                                                                             *\n *    This routine will process the list of files in the input file.  It builds a linked       *\n *    list of DataClass objects.  This routine is the initial process of creating a packed     *\n *    data file.                                                                               *                                                                                             *\n *                                                                                             *\n * INPUT:   infile   -- Pointer to input filename.                                             *\n *                                                                                             *\n *          quiet    -- Process quietly?                                                       *\n *                                                                                             *\n *          paths    -- Should the path of the filename be considered as part of its signature?*\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DataClass::Process_Input(char const *infile, int quiet, int paths)\n{\n\tFILE\t*file;\t\t//\tInput file.\n\tstatic char buffer[MAXFILE];\n\n\tQuiet = quiet;\n\tPaths = paths;\n\n\tif (!infile) throw \"No input file specified\";\n\n\tfile = fopen(infile, \"ra\");\n\tif (!file) throw \"Could not open input file\";\n\n\tif (!Quiet) {\n\t\tprintf(\"Processing '%s'.\\n\", infile);\n\t}\n\n\t/*\n\t**\tProcess the source file list.\n\t*/\n\ttry {\n\t\tfor (;;) {\n\t\t\tint result = fscanf(file, \"%s\", buffer);\n\t\t\tif (result == EOF) break;\n\n\t\t\tnew DataClass(buffer);\n\t\t}\n\t}\n\n\t/*\n\t**\tThis error handler is used if there are any errors that occur while\n\t**\tparsing and verifying the data block filenames.  Errors can include\n\t**\tsource filename errors as well as missing source files themselves.\n\t*/\n\tcatch (char *message) {\n\t\tfclose(file);\n\t\tthrow message;\n\t}\n\n\tfclose(file);\n}\n\n\n/***********************************************************************************************\n * DataClass::DataClass -- Constructor for a data file object node.                            *\n *                                                                                             *\n *    This constructs a data file object node and links it into the list of object nodes.      *\n *    It performs a preliminary check on the existance of the the source file.                 *\n *                                                                                             *\n * INPUT:   filename -- The filename of the object to add.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1994 JLB : Created.                                                                 *\n *   10/27/94   JLB : Handles multiple data paths.                                             * \n *=============================================================================================*/\nDataClass::DataClass(char const *filename)\n{\n\tstatic char buffer[100];\n\t\n\tif (!filename) throw \"NULL filename\";\n\n\tFilename = strdup(filename);\n\tstrupr(Filename);\n\n\t/*\n\t**\tTry to find the data file.\n\t*/\n\tFILE *datafile = fopen(Filename, \"rb\");\n\tif (!datafile) {\n\n\t\t/*\n\t\t**\tIf the file couldn't be found in the current directory, check\n\t\t**\tthe alternate paths.  If the alternate path is successful, then\n\t\t**\talter the pathname to match and continue.\n\t\t*/\n\t\tfor (int index = 0; index < AltPathCount; index++) {\n\t\t\tstrcpy(buffer, AltPath[index]);\n\t\t\tstrcat(buffer, Filename);\n\t\t\tdatafile = fopen(buffer, \"rb\");\n\t\t\tif (datafile) {\n\t\t\t\tfree(Filename);\n\t\t\t\tFilename = strdup(buffer);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!datafile) {\n\t\t\tsprintf(buffer, \"Could not find source file '%s'\", Filename);\n\t\t\tthrow buffer;\n\t\t}\n\t}\n\n\t/*\n\t**\tDetermine the CRC identifier for the filename,  This can be either\n\t**\tthe base filename or the complete path (as indicated by the command\n\t**\tline parameter).\n\t*/\n\tchar const * name = Output_Filename();\n\tCRC = Calc_CRC(name, strlen(name));\n\n\t/*\n\t**\tFind out the size of the source data file.\n\t*/\n\tfseek(datafile, 0, SEEK_END);\n\tlong size = ftell(datafile);\n\tfclose(datafile);\n\n\tif (size == -1) throw \"Seek failure\";\n\tSize = size;\n\n\tIndex = Count;\n\tCount++;\n\tNext = First;\n\tFirst = this;\n}\n\n\n/***********************************************************************************************\n * DataClass::~DataClass -- Destructor for the data file object.                               *\n *                                                                                             *\n *    This is the destructor for the data file object.  It deallocates any memory allocated    *\n *    and de-links it from the list of file objects.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nDataClass::~DataClass(void)\n{\n\tif (Filename) {\n\t\tfree(Filename);\n\t\tFilename = 0;\n\t}\n\n\tCount--;\n\tDataClass *ptr = First;\n\tDataClass *prev = 0;\n\twhile (ptr) {\n\t\tif (ptr == this) {\n\t\t\tif (prev) {\n\t\t\t\tprev->Next = Next;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tprev = ptr;\n\t\tptr = ptr->Next;\n\t}\n}\n\n\n/***********************************************************************************************\n * compfunc -- Comparison function used by qsort().                                            *\n *                                                                                             *\n *    This is a support function that compares two file data objects against their CRC         *\n *    values.                                                                                  *\n *                                                                                             *\n * INPUT:   ptr1  -- Pointer to object number 1.                                               *\n *                                                                                             *\n *          ptr2  -- Pointer to object number 2.                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a logical comparison of object 1 to object 2.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint compfunc(const void *ptr1, const void *ptr2)\n{\n\tDataClass const *obj1 = *(DataClass const **)ptr1;\n\tDataClass const *obj2 = *(DataClass const **)ptr2;\n\n\tif (obj1->CRC < obj2->CRC) {\n\t\treturn (-1);\n\t}\n\tif (obj1->CRC > obj2->CRC) {\n\t\treturn (1);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * DataClass::Process_Output -- Creates the output data file from the component source files.  *\n *                                                                                             *\n *    This is the final step in creation of the data output file.  It writes the header        *\n *    block and then appends the appropriate files to the output file.                         *\n *                                                                                             *\n * INPUT:   outname  -- Pointer to the filename to use for output.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DataClass::Process_Output(char const *outname)\n{\n\tFILE *outfile;\n\n\tif (Count) {\n\t\tDataClass **array = new DataClass *[Count];\n\n\t\t/*\n\t\t**\tOpen the output file for creation.\n\t\t*/\n\t\tif (!outname) throw \"Missing output filename\";\n\t\toutfile = fopen(outname, \"wb\");\n\t\tif (!outfile) {\n\t\t\tthrow \"Unable to open output file\";\n\t\t}\n\n\t\t/*\n\t\t**\tBuild a working array to the file objects.\n\t\t*/\n\t\tDataClass * ptr = First;\n\t\tfor (int index = 0; index < Count; index++) {\n\t\t\tarray[index] = ptr;\n\t\t\tptr->Index = index;\n\t\t\tptr = ptr->Next;\n\t\t}\n\n\t\t/*\n\t\t**\tPrecalculate the offset value for each data file will be.\n\t\t**\tThis value will be inserted into the header block. This is\n\t\t**\tperformed BEFORE the files are sorted because the data files\n\t\t**\tare written to disk in the order that they were specified.\n\t\t*/\n\t\tTotalSize = 0;\n\t\tfor (index = 0; index < Count; index++) {\n\t\t\tarray[index]->Offset = TotalSize;\n\t\t\tTotalSize += array[index]->Size;\n\t\t}\n\n\t\t/*\n\t\t**\tNext, sort the data objects so that a binary search on CRC values\n\t\t**\tcan be used for file retrieval.\n\t\t*/\n\t\tqsort(array, Count, sizeof(array[0]), compfunc);\n\n\t\t/*\n\t\t**\tOutput the header section of the data file.  This contains\n\t\t**\tthe count of objects contained, the CRC, and offset for each.\n\t\t*/\n\t\tfwrite(&Count, sizeof(Count), 1, outfile);\n\t\tfwrite(&TotalSize, sizeof(TotalSize), 1, outfile);\n\t\tfor (index = 0; index < Count; index++) {\n\t\t\tfwrite(&array[index]->CRC, sizeof(array[index]->CRC), 1, outfile);\n\t\t\tfwrite(&array[index]->Offset, sizeof(array[index]->Offset), 1, outfile);\n\t\t\tfwrite(&array[index]->Size, sizeof(array[index]->Size), 1, outfile);\n\t\t}\n\n\t\tTotalSize += sizeof(Count) + sizeof(TotalSize) + (Count*12);\n\n\t\tif (!Quiet) {\n\t\t\tprintf(\"size      CRC       Filename\\n\");\n\t\t\tprintf(\"------    --------  -------------------------\\n\");\n\t\t}\n\n\t\t/*\n\t\t**\tNow write the actual data -- one file at a time in the order that they were\n\t\t**\toriginally specified.\n\t\t*/\n\t\tfor (int order = 0; order < Count; order++) {\n\t\t\tfor (index = 0; index < Count; index++) {\n\t\t\t\tDataClass * entry = array[index];\n\n\t\t\t\tif (entry->Index == order) {\n\t\t\t\t\tFILE\t*infile;\n\t\t\t\t\tlong\tsize;\n\t\t\t\t\tstatic char buffer[1024*30];\n\n\t\t\t\t\tif (!Quiet) {\n\t\t\t\t\t\tprintf(\"%-8ld [%08lX] %s\\n\", entry->Size, entry->CRC, entry->Output_Filename());\n\t\t\t\t\t}\n\n\t\t\t\t\tsize = entry->Size;\n\t\t\t\t\tinfile = fopen(entry->Input_Filename(), \"rb\");\n\t\t\t\t\twhile (size > 0) {\n\t\t\t\t\t\tint count;\n\n\t\t\t\t\t\tcount = (size < sizeof(buffer)) ? (int)size : sizeof(buffer);\n\t\t\t\t\t\tcount = fread(buffer, sizeof(buffer[0]), count, infile);\n\t\t\t\t\t\tfwrite(buffer, sizeof(buffer[0]), count, outfile);\n\t\t\t\t\t\tsize -= count;\n\t\t\t\t\t\tif (!count) break;\t\t// Hmm..\n\t\t\t\t\t}\n\t\t\t\t\tfclose(infile);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfclose(outfile);\n\t}\n}\n\n\n/***********************************************************************************************\n * Calc_CRC -- Calculate the CRC value of a block of data.                                     *\n *                                                                                             *\n *    This routine is used to create a CRC value from a string of data bytes.                  *\n *                                                                                             *\n * INPUT:   data  -- Pointer to the data bytes to calculate the CRC value for.                 *\n *                                                                                             *\n *          size  -- The number of bytes in the data block.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the CRC value of the buffer specified.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Calc_CRC(void const *data, long size)\n{\n\tlong\tcrc = 0;\t\t\t\t// Accumulating CRC value.\n\tlong\tconst *ptr = static_cast<long const *>(data);\n\n\t/*\n\t**\tProcess the bulk of the data (4 bytes at a time).\n\t*/\n\tfor (; size > sizeof(long); size -= sizeof(long)) {\n\t\tlong temp = *ptr++;\n\t\tasm {\n\t\t\tmov\teax,crc\n\t\t\trol\teax,1\n\t\t\tadd\teax,temp\n\t\t\tmov\tcrc,eax\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there are any remainder bytes, then process them\n\t**\tas a group of four, but the trailing left over bytes\n\t**\tare forced to be NULL.\n\t*/\n\tif (size) {\n\t\tlong temp = 0;\n\n\t\tmemcpy(&temp, ptr, (size_t)size);\n\t\tasm {\n\t\t\tmov\teax,crc\n\t\t\trol\teax,1\n\t\t\tadd\teax,temp\n\t\t\tmov\tcrc,eax\n\t\t}\n\t}\n\n\treturn (crc);\n}\n\n\nchar const * DataClass::Output_Filename(void)\n{\n\tchar file[MAXFILE];\n\tchar ext[MAXEXT];\n\tchar path[MAXPATH];\n\tchar drive[MAXDRIVE];\n\tstatic char filename[255];\n\n\t/*\n\t**\tBreak the original filename into its component parts.\n\t*/\n\tfnsplit(Filename, drive, path, file, ext);\n\n\t/*\n\t**\tSubstitute the extension if a substitution is called for.\n\t*/\n\tfor (int index = 0; index < ExtCount; index++) {\n\t\tif (stricmp(ExtFrom[index], &ext[1]) == 0) {\n\t\t\tstrcpy(&ext[1], ExtTo[index]);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tStrip the path from the filename if path stripping is enabled.\n\t*/\n\tif (!Paths) {\n\t\tfnmerge(filename, NULL, NULL, file, ext);\n\t} else {\n\t\tfnmerge(filename, drive, path, file, ext);\n\t}\n\treturn(&filename[0]);\n}\t\n\n\nchar const * DataClass::Input_Filename(void)\n{\n\treturn(Filename);\n}\t\n"
  },
  {
    "path": "VQ/INCLUDE/HMI32/SOS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sos.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DEFINED   \n#define  _SOS_DEFINED   \n#include \"sosdefs.h\"\n\n#pragma pack(4)\n \n// error definition for sound operating system  \n#define  _SOS_ERR          -1\n\n// number of drivers allowed to be open at one time\n#define  _SOS_MAX_DRIVERS  5\n\n// structure definition for the capabilities\ntypedef struct _tagCAPABILITIES\n{\n   BYTE  szDeviceName[ 32 ];  // device name\n   WORD  wDeviceVersion;      // device version\n   WORD  wBitsPerSample;      // bits per sound sample\n   WORD  wChannels;           // stereo/mono sound card\n   WORD  wMinRate;            // minimum rate\n   WORD  wMaxRate;            // maximum rate\n   WORD  wMixerOnBoard;       // board contains mixer\n   WORD  wMixerFlags;         // mixer capabilities\n   WORD  wFlags;              // miscellaneous flags   \n   short far * lpPortList;         // list of usable ports\n   short far * lpDMAList;          // list of usable dma channels\n   short far * lpIRQList;          // list of usable irq channels\n   short far * lpRateList;         // list of usable rates, -1 if any in min to max\n   WORD  fBackground;         // foreground or background driver\n   WORD  wDeviceID;           // ID for the device\n   WORD  wTimerID;            // ID for the timer\n   \n} _SOS_CAPABILITIES; \n\n// far pointer to the device capabilities structure\ntypedef _SOS_CAPABILITIES far *  LPSOSDEVICECAPS;\n\n// flag types for driver\n#define  _FLAGS_SIGNED              0x8000\n  \n// devices that can be loaded\n#define  _SOUND_BLASTER_8_MONO      0xe000\n#define  _SOUND_BLASTER_8_ST        0xe001\n#define  _SBPRO_8_ST                _SOUND_BLASTER_8_ST\n#define  _SBPRO_8_MONO              0xe00f\n#define  _SOUND_MASTER_II_8_MONO    0xe002\n#define  _MV_PAS_8_MONO             0xe003\n#define  _MV_PAS_16_MONO            0xe004\n#define  _MV_PAS_8_ST               0xe005\n#define  _MV_PAS_16_ST              0xe006\n#define  _ADLIB_GOLD_8_ST           0xe007\n#define  _ADLIB_GOLD_16_ST          0xe008\n#define  _ADLIB_GOLD_8_MONO         0xe009\n#define  _ADLIB_GOLD_16_MONO        0xe00a\n#define  _MICROSOFT_8_MONO          0xe00b\n#define  _MICROSOFT_8_ST            0xe00c\n#define  _MICROSOFT_16_MONO         0xe00d\n#define  _MICROSOFT_16_ST           0xe00e\n#define  _SOUND_SOURCE_8_MONO_PC    0xe010\n#define  _SOUND_SOURCE_8_MONO_TANDY 0xe011\n#define  _GENERAL_PORT_8_MONO       0xe012\n#define  _GENERAL_PORT_8_MONO_R     0xe013\n#define  _SIERRA_8_MONO             0xe014\n#define  _SB16_8_MONO               0xe015\n#define  _SB16_8_ST                 0xe016\n#define  _SB16_16_MONO              0xe017\n#define  _SB16_16_ST                0xe018\n#define  _ESS_AUDIODRIVE_8_MONO     0xe019\n#define  _ESS_AUDIODRIVE_8_ST       0xe01a\n#define  _ESS_AUDIODRIVE_16_MONO    0xe01b\n#define  _ESS_AUDIODRIVE_16_ST      0xe01c\n#define  _SOUNDSCAPE_8_MONO         0xe01d\n#define  _SOUNDSCAPE_8_ST           0xe01e\n#define  _SOUNDSCAPE_16_MONO        0xe01f\n#define  _SOUNDSCAPE_16_ST          0xe020\n#define  _RAP10_8_MONO              0xe021\n#define  _RAP10_16_MONO             0xe022\n#define  _GUS_8_MONO                0xe023\n#define  _GUS_8_ST                  0xe024\n#define  _GUS_16_MONO               0xe025\n#define  _GUS_16_ST                 0xe026\n#define  _GUS_MAX_8_MONO            0xe027\n#define  _GUS_MAX_8_ST              0xe028\n#define  _GUS_MAX_16_MONO           0xe029\n#define  _GUS_MAX_16_ST             0xe02a\n#define  _WAVEJAMMER_8_MONO         0xe02b\n#define  _WAVEJAMMER_8_ST           0xe02c\n#define  _WAVEJAMMER_16_MONO        0xe02d\n#define  _WAVEJAMMER_16_ST          0xe02e\n#define  _TEMPOCS_8_MONO            0xe02f\n#define  _TEMPOCS_8_ST              0xe030\n#define  _TEMPOCS_16_MONO           0xe031\n#define  _TEMPOCS_16_ST             0xe032\n#define  _WAVEJAMMERCD_8_MONO       0xe033\n#define  _WAVEJAMMERCD_8_ST         0xe034\n#define  _WAVEJAMMERCD_16_MONO      0xe035\n#define  _WAVEJAMMERCD_16_ST        0xe036\n#define  _SOUND_BLASTER_8_MONO_R    0xe050\n#define  _MICROSOFT_8_MONO_R        0xe051\n#define  _SOUND_MASTER_II_8_MONO_R  0xe052\n#define  _ADLIB_GOLD_8_MONO_R       0xe053\n#define  _MV_PAS_8_MONO_R           0xe054\n#define  _RAP10_8_MONO_R            0xe058\n#define  _RAP10_16_MONO_R           0xe059\n#define  _SB16_8_MONO_R             0xe05a\n#define  _SB16_8_ST_R               0xe05b\n#define  _SB16_16_MONO_R            0xe05c\n#define  _SB16_16_ST_R              0xe05d\n#define  _MV_PAS_16_MONO_R          0xe060\n#define  _SOUNDSCAPE_8_MONO_R       0xe061\n#define  _SOUNDSCAPE_8_ST_R         0xe062\n#define  _SOUNDSCAPE_16_MONO_R      0xe063\n#define  _SOUNDSCAPE_16_ST_R        0xe064\n#define  _ESS_AUDIODRIVE_8_MONO_R   0xe065\n#define  _ESS_AUDIODRIVE_8_ST_R     0xe066\n#define  _ESS_AUDIODRIVE_16_MONO_R  0xe067\n#define  _ESS_AUDIODRIVE_16_ST_R    0xe068\n#define  _SPEECH_THING_8_MONO       0xe090\n#define  _YAMAHA_8_MONO             0xe106\n#define  _INT_SPEAKER_8_MONO        0xe107\n\n// call indexes for the loadable drivers\nenum\n{ \n   _DRV_INIT,\n   _DRV_UNINIT,\n   _DRV_SETRATE,\n   _DRV_SETACTION,\n   _DRV_START,\n   _DRV_STOP,\n   _DRV_PAUSE,\n   _DRV_RESUME,\n   _DRV_CAPABILITIES,\n   _DRV_PLAY_FOREGROUND,\n   _DRV_GET_FILL_INFO, \n   _DRV_GET_CALL_FUNCTIONS,\n   _DRV_SET_CALL_FUNCTIONS\n};\n\n// fill info\ntypedef  struct   _tagFillInfo\n         {\n\n            LPSTR lpFillHandler;                   // pointer to fill handler\n            LPWORD lpDMAFillCount;                 // pointer to dma count\n            LPSTR lpSampleList;                    // pointer to sample list\n            LPWORD lpDMAMasterVolume;              // pointer to dma count\n\n         } _SOS_FILL_INFO;\n\n// caps info structure\ntypedef  struct   _tagCapsInfo\n         {\n\n            LPSTR    lpPortList;                   // pointer to port list\n            LPSTR    lpDMAList;                    // pointer to DMA list\n            LPSTR    lpIRQList;                    // pointer to IRQ list\n            LPSTR    lpRateList;                   // pointer to rate list\n\n         } _SOS_CAPS_INFO;\n\n// maximum number of available voice\n#define  _MAX_VOICES    32\n\n// structure definition\ntypedef  struct   _tagSAMPLE\n{\n   LPSTR    samplePtr;                 // pointer to data buffer\n   LPSTR    sampleData;                // pointer to active data\n   LPSTR    sampleLoopPtr;             // pointer for loop back\n\n   WORD     sampleLength;              // length of sample\n   WORD     sampleIndex;               // index into sample\n   WORD     sampleLoopLength;          // length of loop\n   \n   WORD     sampleBytesLeft;           // bytes left to play in sample\n\n   WORD     sampleLoopPoint;           // byte count for loop point\n   WORD     sampleLoopEndLength;       // length of remaining chunk\n\n   short    sampleFlags;               // control sample\n   short    sampleVolume;              // volume control\n   short    sampleID;                  // sample ID\n\n   short    sampleChannel;             // channel to play sample on\n   short    sampleLoopCount;           // loop count\n   short    sampleLastFill;            // last fill position\n   VOID ( far cdecl * sampleCallback )( WORD, WORD, WORD ); // callback function for sample\n\n   WORD     samplePitchAdd;\n   short    samplePitchFraction;\n\n   short    samplePort;                // port to use for non-dma digitized\n\n   WORD     sampleTotalBytes;\n   WORD     sampleByteLength;\n\n   short    samplePanLocation;\n   short    samplePanSpeed;\n   short    samplePanDirection;\n   short    samplePanStart;\n   short    samplePanEnd;\n   \n   short    sampleDelayBytes;\n   short    sampleDelayRepeat;\n   \n   WORD     sampleADPCMPredicted;\n   short    sampleADPCMIndex;\n\n   short    sampleRootNoteMIDI;   \n\n   WORD  sampleTemp1;   \n   \n} _SOS_SAMPLE;\n\n// enumeration for left or right channel\nenum\n{\n   _LEFT_CHANNEL,\n   _RIGHT_CHANNEL,\n   _CENTER_CHANNEL,\n   _INTERLEAVED\n};\n\n// enumeration for foreground and background\nenum\n{ \n   _FOREGROUND,\n   _BACKGROUND \n};\n\n// defines for the sample flags\n#define  _ACTIVE           0x8000\n#define  _LOOPING          0x4000\n#define  _FIRST_TIME       0x2000\n#define  _PENDING_RELEASE  0x1000\n#define  _CONTINUE_BLOCK   0x0800\n#define  _PITCH_SHIFT      0x0400\n#define  _PANNING          0x0200\n#define  _VOLUME           0x0100\n#define  _TRANSLATE16TO8   0x0080\n#define  _STAGE_LOOP       0x0040\n#define  _TRANSLATE8TO16   0x0020\n#define  _STEREOTOMONO     0x0010\n\n// defines for the wParam flags \n#define  _SINGLE_SAMPLE 0x01\n\n#define  _SOS_DCAPS_AUTO_REINIT     0x01\n#define  _SOS_DCAPS_MPU_401         0x02\n#define  _SOS_DCAPS_OPL2            0x04\n#define  _SOS_DCAPS_OPL3            0x08\n#define  _SOS_DCAPS_OPL4            0x10\n#define  _SOS_DCAPS_WAVETABLE       0x20\n#define  _SOS_DCAPS_DL_SAMPLES      0x40\n#define  _SOS_DCAPS_FIFO_DEVICE     0x80\n#define  _SOS_DCAPS_ENV_NEEDED      0x100\n#define  _SOS_DCAPS_PSEUDO_DMA1     0x200\n#define  _SOS_DCAPS_SIGNED_DATA     0x8000\n\n// file header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // number of drivers in the file\n   WORD  wDrivers;\n\n   // offset of first driver\n   WORD  lOffset;\n\n   // size of the file\n   WORD  lFileSize;\n\n} _FILEHEADER;\n\n// driver header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // offset of next driver\n   WORD  lNextDriver;\n\n   // size of current driver\n   WORD  wSize;\n\n   // id for the current device\n   WORD  wDeviceID;\n\n   // id for the type of DOS extender\n   WORD  wExtenderType;\n\n} _DRIVERHEADER;\n\n// device hardware information\ntypedef struct\n{\n   // port to be used\n   WORD  wPort;\n\n   // irq to use\n   WORD  wIRQ;\n\n   // dma channel to se\n   WORD  wDMA; \n  \n   // extra parameter\n   WORD  wParam;\n\n} _SOS_HARDWARE;\n\n// structure definition for start sample\ntypedef struct\n{\n   // pointer to sample\n   LPSTR lpSamplePtr;\n\n   // size of the sample\n   WORD  dwSampleSize;\n\n   // number of times to loop the sample -1 is infinite\n   WORD  wLoopCount;\n\n   // channel to play sample on\n   WORD  wChannel;\n\n   // volume to play sample at\n   WORD wVolume;\n\n   // id for the sample\n   WORD  wSampleID;\n\n   // far pointer to the callback function\n   VOID ( far cdecl *lpCallback )( WORD, WORD, WORD );\n\n   // port to use if driver is a non-dma background driver\n   WORD  wSamplePort; \n\n   // flags field\n   WORD  wSampleFlags;\n\n   // total length of sample including loops, etc..\n   WORD     dwSampleByteLength;\n\n   // loop point for the sample\n   WORD  dwSampleLoopPoint;\n   WORD  dwSampleLoopLength;\n\n   // pitch shifting components \n   WORD     dwSamplePitchAdd;\n   WORD    wSamplePitchFraction;\n\n   // pan components\n   WORD    wSamplePanLocation;\n   WORD    wSamplePanSpeed;\n   WORD    wSamplePanDirection;\n   WORD    wSamplePanStart;\n   WORD    wSamplePanEnd;\n   \n   // delay parts\n   WORD    wSampleDelayBytes;\n   WORD    wSampleDelayRepeat;\n\n   // compression components   \n   WORD     dwSampleADPCMPredicted;\n   WORD    wSampleADPCMIndex;\n\n   // root note for pitch shifting \n   WORD    wSampleRootNoteMIDI;   \n\n   // filler for future upgrades\n   WORD  dwSampleTemp1;   \n   WORD  dwSampleTemp2;   \n   WORD  dwSampleTemp3;   \n\n} _SOS_START_SAMPLE;\n\n// structure for initializing a driver\ntypedef struct\n{  \n   WORD  wBufferSize;\n   LPSTR lpBuffer;\n   BOOL  wAllocateBuffer;\n   WORD  wSampleRate;\n   WORD  wParam;\n   LONG  dwParam;\n   VOID ( far *lpFillHandler )( VOID );\n   LPSTR lpDriverMemory;\n   LPSTR lpDriverMemoryCS;\n   LPSTR lpTimerMemory;\n   LPSTR lpTimerMemoryCS;\n   WORD  wTimerID;\n   WORD  wPhysical;\n\n} _SOS_INIT_DRIVER;\n\n// define for the timer types to use\n#define  _SOS_NORMAL_TIMER          0x00\n\n// enumeration for the timer types\nenum\n{\n   _TIMER_8_MONO   =     0x1000,\n   _TIMER_8_ST,          \n   _TIMER_16_MONO,       \n   _TIMER_16_ST,         \n   _TIMER_8_MONO_ULAW,  \n   _TIMER_8_ST_ULAW,    \n   _TIMER_16_MONO_ULAW, \n   _TIMER_16_ST_ULAW,   \n   _TIMER_8_MONO_REC,   \n   _TIMER_8_MONO_ULAW_REC,\n   _TIMER_UNDEFINED_1,      \n   _TIMER_UNDEFINED_2,\n   _TIMER_UNDEFINED_3,\n   _TIMER_UNDEFINED_4,\n   _TIMER_UNDEFINED_5,\n   _TIMER_UNDEFINED_6,\n   _TIMER_UNDEFINED_7,\n   _TIMER_UNDEFINED_8,\n   _TIMER_UNDEFINED_9,\n   _TIMER_UNDEFINED_A,\n   _TIMER_UNDEFINED_B,\n   _TIMER_UNDEFINED_C,\n   _TIMER_UNDEFINED_D,\n   _TIMER_UNDEFINED_E,\n   _TIMER_UNDEFINED_F,\n   _TIMER_UNDEFINED_10,\n   _TIMER_UNDEFINED_11,\n   _TIMER_UNDEFINED_12,\n   _TIMER_UNDEFINED_13,\n   _TIMER_UNDEFINED_14,\n   _TIMER_UNDEFINED_15,\n   _TIMER_UNDEFINED_16,\n   _TIMER_8_SOUND_SOURCE,\n   _TIMER_8_SOUND_SOURCE_TANDY,\n   _TIMER_8_GENERAL_PORT,\n   _TIMER_8_GENERAL_PORT_REC   \n};\n\n// define for no slots available\n#define  _ERR_NO_SLOTS ( WORD )-1\n\n// error codes for the system\nenum\n{\n   _ERR_NO_ERROR,\n   _ERR_DRIVER_NOT_LOADED,\n   _ERR_INVALID_POINTER,\n   _ERR_DETECT_INITIALIZED,\n   _ERR_FAIL_ON_FILE_OPEN,\n   _ERR_MEMORY_FAIL,\n   _ERR_INVALID_DRIVER_ID,\n   _ERR_NO_DRIVER_FOUND,\n   _ERR_DETECTION_FAILURE,\n   _ERR_DRIVER_LOADED,\n   _ERR_INVALID_HANDLE,\n   _ERR_NO_HANDLES,\n   _ERR_PAUSED,   \n   _ERR_NOT_PAUSED,\n   _ERR_INVALID_DATA,\n   _ERR_DRV_FILE_FAIL,\n   _ERR_INVALID_PORT,\n   _ERR_INVALID_IRQ,\n   _ERR_INVALID_DMA,\n   _ERR_INVALID_DMA_IRQ\n};   \n\n// maximum number of timer events that can be registered \n#define  _TIMER_MAX_EVENTS    0x10  \n\n// flags for the debugging system\n#define  _SOS_DEBUG_NORMAL       0x0000\n#define  _SOS_DEBUG_NO_TIMER     0x0001\n#define  _SOS_TIMER_DPMI         0x0002\n\n// define for types of DOS extenders\n#define  _SOS_RATIONAL           0x8000\n#define  _SOS_FLASHTECK          0x4000\n\n// defines for the types of timers for different\n// dos extenders\n#define  _SOS_TIMER_NEAR         0x8000\n#define  _SOS_TIMER_FAR          0x4000\n \n// values for callback information\nenum\n{\n   _SAMPLE_PROCESSED,\n   _SAMPLE_LOOPING,\n   _SAMPLE_DONE\n};\n\n// define for special 18.2 callback rate to dos\n#define  _TIMER_DOS_RATE   0xff00\n\n#pragma pack()\n\n#pragma aux int_3 = \"int 3\"\n \n#pragma pack( 1 ) \ntypedef struct\n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned       segment;\n\tunsigned short\tnumber_available;\n\tunsigned short number_used;\n\tunsigned       page0;\n\n} EVDS_STRUCT;\n\ntypedef struct \n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned short segment;\n\tunsigned short\tID;\n\tunsigned       physical;\n\n} VDS_STRUCT;\n\n#pragma pack() \n\n#include \"sosdata.h\"\n#include \"sosfnct.h\"\n\n#endif\n"
  },
  {
    "path": "VQ/INCLUDE/HMI32/SOSDATA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdata.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DATA\n#define  _SOS_DATA\n\n#include <stddef.h>\n\n#pragma pack(4) \nextern   WORD     _sosDIGIData_Start;\nextern   WORD     _sosDIGIData_End;\nextern   WORD     _wSOSDriverLinear[];\nextern   WORD     _wSOSTimerLinear[];\nextern   LPSTR    _lpSOSDriver[];\nextern   LPSTR    _lpSOSTimer[];\nextern   LPSTR    _lpSOSDriverCS[];\nextern   LPSTR    _lpSOSTimerCS[];\nextern   BOOL     _wSOSDriverLoaded[];\nextern   BOOL     _wSOSTimerLoaded[];\nextern   BOOL     _wSOSDriverInitialized[];\nextern   WORD     _wSOSOutputRate[];\nextern   WORD     _wSOSDMABuffersize[];\nextern   LONG     _dwSOSDMABufferPhysical[];\nextern   LPSTR    _lpSOSDMABuffer[];\nextern   BOOL     _wTimerUsed;\nextern   VOID ( far *_lpSOSFillHandler[] )( VOID );\nextern   WORD     _wSOSTimerType[];\nextern   WORD     _wSOSDriverType[];\nextern   _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ];\nextern   LPWORD      _lpSOSDMAIrqCount[];\nextern   LPWORD      _lpSOSDMAFillCount[];\nextern   WORD        _wSOSTmrNextCount;\nextern   VOID ( interrupt far *_lpSOSOldTimer )( VOID );\nextern   WORD     _wSOSDriverID[];\nextern   _SOS_CAPABILITIES _sSOSDriverCaps[];\nextern   WORD        _wSOSDMAPortList[];\nextern   BYTE        _bSOSDMAChannel[];\nextern   _SOS_INIT_DRIVER     _sSOSDIGIInitDriver[];\nextern   BYTE  _pSOSDriverPath[];\nextern   BYTE  _pSOSTempDriverPath[];\nextern   BOOL  _wTIMERUsed;\nextern   WORD  _wTIMERValue;\nextern   VOID ( far * _lpTIMEREvents[] )( VOID );\nextern   WORD _wTIMEREventRate[];\nextern   WORD _dwTIMEREventFraction[];\nextern   WORD _dwTIMEREventFractionCurrent[];\nextern   BYTE  _bSOSMIDITimerSongHandler[];\nextern   BYTE  _bSOSMIDISongHandle;\nextern   WORD  _wSOSTimerMemHandle[];\nextern   WORD  _wSOSDriverMemHandle[];\nextern   WORD  _wSOSRealSeg[];\n\nextern   _FILEHEADER    _sDETFileHeader;\nextern   _DRIVERHEADER  _sDETDriverHeader;\nextern   _FILEHEADER    sLOADFileHeader;\nextern   _DRIVERHEADER  sLOADDriverHeader;\nextern   BOOL           _wDETInitialized;\nextern   WORD           _wDETLinear;\nextern   LPSTR          _lpDETDriverBuffer;    \nextern   LPSTR          _lpDETDriverBufferCS;\nextern   WORD           _hDETFile;\nextern   DWORD          _dwDETDriverIndex;\nextern   WORD           _wDETDriverIndexCur;\nextern   WORD           _wDETMemHandle;\nextern   LPSOSDEVICECAPS _lpDETDeviceCaps;\nextern   _SOS_CAPABILITIES _sDETCaps;  \nextern   PSTR _pSOSErrorStrings[];\nextern   BOOL _wSOSBufferAllocated[];\nextern   BOOL _wSOSSystemInitialized;\nextern   VDS_STRUCT _sSOSVDSInfo;\nextern   _SOS_FILL_INFO _sSOSFillInfo;\nextern   WORD    _wSOSTimerEventIndex;\nextern   WORD  _wSOSTimerEntered;\nextern   WORD  _wSOSDriverSize[];\nextern   WORD  _wSOSTimerSize[];\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nextern   WORD  _sosDIGIData1_Start;\nextern   WORD  _sosDIGIData1_End;\nextern   WORD  _sosDIGIData2_Start;\nextern   WORD  _sosDIGIData2_End;\nextern   BYTE  _bTIMERInstalled;\nextern   BYTE  _bTIMERDPMI;\nextern   WORD  wDetectPort;\nextern   WORD  wDetectIRQ;\nextern   WORD  wDetectDMA;\nextern   WORD  wDetectParam;\n#ifdef __cplusplus\n}\n#endif \n\n#pragma pack()\n\n#endif\n\u001a\n"
  },
  {
    "path": "VQ/INCLUDE/HMI32/SOSDEFS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdefs.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n\n#ifndef  _SOSDEFS_DEFINED\n#define  _SOSDEFS_DEFINED\n\n#undef   _TRUE\n#undef   _FALSE\n#undef   _NULL\nenum  \n      { \n         _FALSE, \n         _TRUE \n      };\n\n#define  _NULL  0\n\n#ifndef  VOID\n#define  VOID           void\n#endif\ntypedef  int            BOOL;\ntypedef  unsigned int   UINT;\ntypedef  unsigned char  BYTE;\ntypedef  unsigned       WORD;\n#ifndef  LONG\ntypedef  signed long    LONG;\n#endif\ntypedef  unsigned long  DWORD;\n\ntypedef  BYTE  *        PBYTE;\ntypedef  char near *    PSTR;\ntypedef  WORD  *        PWORD;\ntypedef  LONG  *        PLONG;\ntypedef  VOID  *        PVOID;\n\ntypedef  BYTE  far   *  LPBYTE;\ntypedef  BYTE  far   *  LPSTR;\ntypedef  WORD  far   *  LPWORD;\ntypedef  LONG  far   *  LPLONG;\ntypedef  VOID  far   *  LPVOID;\n\ntypedef  BYTE  huge  *  HPBYTE;\ntypedef  BYTE  huge  *  HPSTR;\ntypedef  WORD  huge  *  HPWORD;\ntypedef  LONG  huge  *  HPLONG;\ntypedef  VOID  huge  *  HPVOID;\n\ntypedef  unsigned       HANDLE;\n\n#endif\n\u001a\n"
  },
  {
    "path": "VQ/INCLUDE/HMI32/SOSFNCT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosfnct.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_FUNCTIONS\n#define  _SOS_FUNCTIONS\n\n#pragma pack(4)\n\nWORD sosDIGILockMemory          (  VOID  );\nWORD sosDIGIUnLockMemory        (  VOID  );\nWORD sosDIGIInitSystem           (  LPSTR, WORD  );\nWORD sosDIGIUnInitSystem         (  VOID  );\nWORD sosDIGIInitDriver           (  WORD, _SOS_HARDWARE far *,\n                                    _SOS_INIT_DRIVER far *, WORD far *   );\nWORD sosDIGIUnInitDriver         (  WORD, BOOL, BOOL  );\nWORD sosDIGILoadDriver          (  WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD sosDIGIUnLoadDriver         (  WORD  );\nWORD sosDIGIGetDeviceCaps        (  WORD, LPSOSDEVICECAPS  );\n\n#ifdef PHARLAP\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#else\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#endif\n\nWORD sosDIGIStopSample           (  WORD, WORD  );\nWORD sosDIGISamplesPlaying       (  WORD  );\nBOOL sosDIGISampleDone           (  WORD, WORD  );\nBOOL sosDIGISampleFilling        (  WORD, WORD  );\nWORD sosDIGIStartSample          (  WORD, _SOS_START_SAMPLE far *  );\nWORD sosDIGIContinueSample       (  WORD, WORD, _SOS_START_SAMPLE far * );\n\n\nWORD  sosDIGIDetectInit          (  LPSTR  );\nWORD  sosDIGIDetectUnInit        (  VOID  );\nWORD  sosDIGIDetectFindHardware  (  WORD, _SOS_CAPABILITIES far *, WORD far * );\nWORD  sosDIGIDetectFindFirst     (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectFindNext      (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectGetSettings   (  _SOS_HARDWARE far *  );\nWORD  sosDIGIDetectGetCaps       (  WORD, _SOS_CAPABILITIES far *  );\nWORD  sosDIGIDetectVerifySettings(  _SOS_HARDWARE far *  );\nPSTR  sosGetErrorString          (  WORD  );\n\nWORD  sosDIGILoadTimer           (  WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD  sosDIGIUnLoadTimer         (  WORD  );\n\nWORD  sosTIMERRegisterEvent      ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle );\nWORD  sosTIMERInitSystem               (  WORD, WORD  );\nWORD  sosTIMERUnInitSystem             (  WORD  );\nWORD  sosTIMERSetRate                  (  WORD  );  \nWORD  sosTIMERRemoveEvent              (  WORD );\nWORD  sosTIMERAlterEventRate           (  WORD, WORD  );\nWORD  sosTIMERGetEventRate             (  WORD  );\nVOID far sosTIMEROldHandler            (  VOID  );\nVOID far sosTIMERHandler               (  VOID  );\n\n// functions in soscntl.c\nWORD  sosDIGISetSampleVolume     ( WORD, WORD, WORD );\nWORD  sosDIGIGetSampleVolume     ( WORD, WORD );\nWORD  sosDIGISetChannel          ( WORD, WORD, WORD );\nWORD  sosDIGIGetChannel          ( WORD, WORD );\nWORD  sosDIGIGetBytesProcessed   ( WORD, WORD );\nWORD  sosDIGIGetLoopCount        ( WORD, WORD );\nWORD  sosDIGISetPanLocation      ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanLocation      ( WORD, WORD );\nDWORD sosDIGISetPitch            ( WORD, WORD, DWORD );\nDWORD sosDIGIGetPitch            ( WORD, WORD );\nWORD  sosDIGIGetDMAPosition      ( WORD );\nWORD  sosDIGISetPanSpeed         ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanSpeed         ( WORD, WORD );\nWORD  sosDIGIGetSampleID         ( WORD, WORD );\nWORD  sosDIGIGetSampleHandle     ( WORD, WORD );\nWORD  sosDIGISetMasterVolume     ( WORD, WORD );\n#ifdef PHARLAP\nVOID  sosFreeVDSPage          ( unsigned short, unsigned short, DWORD );\nWORD  sosAllocVDSPage         ( unsigned short *, unsigned short *, DWORD * );\n#else\nWORD  sosAllocVDSPage            ( LPSTR *, WORD *, WORD * );\nVOID  sosFreeVDSPage             ( WORD, WORD, LONG );\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef PHARLAP\nextern   int   cdecl sosRealFree          ( int );\nextern   BOOL  cdecl  _sos_read( WORD, LPSTR, WORD, WORD * );\nextern   int   cdecl sosRealAlloc( int, int *, int * );\nextern   void  cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD );\nextern   int   cdecl sosGetCS( VOID );\nextern   int   cdecl sosGetES( VOID );\n#else\nextern   int   cdecl sosRealAlloc         ( int, int *, int * );\nextern   int   cdecl sosRealFree          ( int );\n#endif\n\n// sos driver functions\nextern   WORD  cdecl sosDRVLockMemory     ( DWORD, DWORD );\nextern   WORD  cdecl sosDRVUnLockMemory   ( DWORD, DWORD );\nextern   void  cdecl sosDRVGetCapsInfo    ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVGetCapsPtr     ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVInit           ( LPSTR, LPSTR, int, int, int, int, int, int );  \nextern   void  cdecl sosDRVStart          ( LPSTR, LPSTR, int, int );\nextern   void  cdecl sosDRVSetRate        ( LPSTR, LPSTR, int );\nextern   void  cdecl sosDRVSetAction      ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVStop           ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVUnInit         ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVGetFillInfo    ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * );\nextern   void  cdecl sosFillSampleStructs ( PSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVExist       ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVGetSettings ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR );\nextern   WORD  cdecl sosDIGIInitForWindows( WORD );\nextern   WORD  cdecl sosDIGIUnInitForWindows( WORD );\nextern   LPSTR cdecl sosAllocateFarMem      ( WORD, PSTR, WORD * );\nextern   LPSTR cdecl sosCreateAliasCS       ( LPSTR );\nextern   VOID  cdecl sosFreeSelector        ( LPSTR, DWORD );\nextern   LPSTR cdecl sosMAKEDOSPtr          ( PSTR );\nextern   VOID  cdecl sosDetDRVSetEnvString  ( DWORD, PSTR );\nextern   PSTR  cdecl sosDetDRVGetEnvString  ( DWORD );\nextern   VOID  cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR );\nextern   VOID  cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR );\nextern   WORD  cdecl sosDRVGetFreeMemory     ( VOID );\nextern   WORD  cdecl sosDRVAllocVDSStruct    ( WORD, WORD *, WORD * );\nextern   WORD  cdecl sosDRVFreeVDSStruct     ( WORD, WORD );\nextern   WORD  cdecl sosDRVIsWindowsActive   ( VOID );\nextern   WORD  cdecl sosDRVVDSGetBuffer    ( WORD );\nextern   WORD  cdecl sosDRVVDSFreeBuffer   ( WORD );\nextern   WORD  cdecl getDS( VOID );\nextern   WORD  cdecl sosDRVMakeDMASelector   ( WORD );  \nextern   WORD  cdecl sosDRVFreeDMASelector   ( WORD );  \n\n\nextern   void  cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) );\nextern   void  cdecl sosTIMERDRVUnInit( void );\nextern   void  cdecl sosTIMERDRVHandler( void );\nextern   void  cdecl sosTIMERDRVFHandler( void );\nextern   void  cdecl sosTIMERDRVEnable( void );\nextern   void  cdecl sosTIMERDRVDisable( void );\nextern   void  cdecl sosTIMERDRVCallOld( void );\nextern   void  cdecl sosTIMERDRVSetRate( WORD );    \nextern   void  cdecl sosDIGITimer_Start( void );\nextern   void  cdecl sosDIGITimer_End( void );\nextern   void  cdecl sosDIGIDrv_Start( void );\nextern   void  cdecl sosDIGIDrv_End( void );\n#ifdef __cplusplus\n}\n#endif \n\n// external functions for handling system initialization and \n// uninitialization\nWORD  sosEXDIGInitDriver               (  WORD, WORD, WORD, LPSTR,\n                                          _SOS_HARDWARE far *, WORD *  );\nWORD  sosEXDIGIUnInitDriver            (  VOID  );\n\nWORD  sosEXDETFindDriver               (  WORD, LPSTR, _SOS_HARDWARE far *,\n                                          _SOS_CAPABILITIES far *  );\n\n// memory locking prototypes\nVOID  sosDIGICaps_Start( VOID );\nVOID  sosDIGICaps_End( VOID );\nVOID  sosDIGIErr_Start( VOID );\nVOID  sosDIGIErr_End( VOID );\nVOID  sosDIGITmr_Start( VOID );\nVOID  sosDIGITmr_End( VOID );\nVOID  sosDIGIStart_Start( VOID );\nVOID  sosDIGIStart_End( VOID );\nVOID  sosDIGIPlyng_Start( VOID );\nVOID  sosDIGIPlyng_End( VOID );\nVOID  sosDIGIRate_Start( VOID );\nVOID  sosDIGIRate_End( VOID );\nVOID  sosDIGIDone_Start( VOID );\nVOID  sosDIGIDone_End( VOID );\nVOID  sosDIGIDetec_Start( VOID );\nVOID  sosDIGIDetec_End( VOID );\nVOID  sosDIGIInit_Start( VOID );\nVOID  sosDIGIInit_End( VOID );\nVOID  sosDIGILoad_Start( VOID );\nVOID  sosDIGILoad_End( VOID );\nVOID  sosDIGICntl_Start( VOID );\nVOID  sosDIGICntl_End( VOID );\n\n#pragma pack()\n\n#endif\n"
  },
  {
    "path": "VQ/INCLUDE/HMI32/SOSRES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosres.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#define  _SOS_RESOURCE\n#ifndef  _SOS_RESOURCE\n#define  _SOS_RESOURCE\n\n// structure for resource file header\ntypedef struct\n{\n   // file version\n   WORD     wVersion;\n\n   // file size\n   LONG     dwFileSize;\n\n   // number of resources in file\n   WORD     wResCount;\n\n   // offset of resource data from top of file\n   LONG     dwResOffset;\n\n   // offset of sync track from top of file\n   LONG     dwSyncTrackOffset;\n\n}  _RES_FILE_HEADER;\n\n// structure for resource block header\ntypedef struct\n{\n   // resource id\n   WORD     wID;\n\n   // resource type\n   WORD     wResType;\n\n   // offset of next block\n   LONG     dwNextBlock; \n\n   // size of the current resource information\n   LONG     dwResSize;\n\n   // rate to play block at\n   WORD     wBlockRate;\n\n   // id for the sync track to use\n   WORD     wSyncTrackID;\n\n}  _RES_BLOCK_HEADER;\n\n// structure for sync mark tag\ntypedef struct _tagSYNCMARK\n{\n   // ID of the type of mark being used\n   WORD  wID;\n\n   // location in data of sync mark\n   LONG  dwSyncOffset;\n\n   // length of sync block\n   LONG  dwSyncSize;\n\n   // start sample data\n   _SOS_START_SAMPLE sampleData;\n    \n} _RES_SYNCMARK;\n\ntypedef union\n{\n   // structure for sync mark tag\n   _RES_SYNCMARK  syncMark; \n\n} _RES_TAG;\n\n// union for filter information for prepareWave\ntypedef union\n{\n   // filter type\n   WORD     wFilterID;\n\n   // structure for volume\n   struct   volume \n   {\n      WORD  wVolume;\n   };\n\n   // structure for delay\n   struct   delay\n   {  \n      WORD  wDelaySamples;\n   };\n\n} _SOS_FILTER; \n\n \n#endif\n\n\u001a"
  },
  {
    "path": "VQ/INCLUDE/VOCFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VOCFILE_H\n#define VOCFILE_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     vocfile.h\n*\n* DESCRIPTION\n*     VOC audio file definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*      \n****************************************************************************/\n\n/* VOC file header.\n *\n * type   - File type description\n * offset - Offset of data block from the start of VOC file.\n * ver    - File format version number\n * id     - File identification code.\n */\ntypedef struct _VOCHeader {\n\tchar           type[0x14];\n\tunsigned short offset;\n\tunsigned short ver;\n\tunsigned short id;\n} VOCHeader;\n\n/* VOC sub-block block types */\n#define VBT_TERMINATE 0  /* Last block of file (no size field) */\n#define VBT_VOICEDATA 1  /* New set of voice data */\n#define VBT_VOICECONT 2  /* Continuation of voice data */\n#define VBT_SILENCE   3  /* Silence period */\n#define VBT_MARKER    4  /* Syncronization marker */\n#define VBT_ASCII     5  /* NULL terminated string */\n#define VBT_REPEAT    6  /* Mark beginning of repeat loop */\n#define VBT_ENDREPEAT 7  /* Mark end of repeat loop */\n#define VBT_EXTENDED  8\n\n#define IS_VOC(a,b) (((~a)+0x1234)==b)\n#define BLOCK_LEN(a) ((a&0x00FFFFFFL))\n\n#endif  /* VOCFILE_H */\n\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQ.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQ_H\n#define VQ_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* NAME\n*     vq.h\n*\n* DESCRIPTION\n*     Vq file definition\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n****************************************************************************/\n\n/* VQHeader - VQ header structure.\n *\n * ImageSize       - Compressed image size \n * ImageWidth      - Image x-dimension\n * ImageHeight     - Image y-dimension\n * BlockWidth      - Block x-dimension\n * BlockHeight     - Block y-dimension\n * BlockType       - Block type\n * PaletteRange    - Number of palette colors\n * Num1Color       - Number of 1-color blocks & 1-color colors\n * CodebookSize    - Number of actual codebook entries\n * CodingFlag      - Flag for 2-color blocks\n * FrameDiffMethod - Frame differencing method\n * ForcedPalette   - Force a palette on image\n * F555Palette     - Flag for output 15-bit palette\n * VQVersion       - VQ Version #\n * pad[5]          - Pad out to 40 bytes total\n */\ntypedef struct _VQHeader {\n\tunsigned long  ImageSize;\n\tunsigned short ImageWidth;\n\tunsigned short ImageHeight;\n\tunsigned short BlockWidth;\n\tunsigned short BlockHeight;\n\tunsigned short BlockType;\n\tunsigned short PaletteRange;\n\tunsigned short Num1Color;\n\tunsigned short CodebookSize;\n\tunsigned short CodingFlag;\n\tunsigned short FrameDiffMethod;\n\tunsigned short ForcedPalette;\n\tunsigned short F555Palette;\n\tunsigned short VQVersion;\n\tunsigned short pad[5];\n} VQHeader;\n\n#endif /* VQ_H */\n"
  },
  {
    "path": "VQ/INCLUDE/VQA32/VQAFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAFILE_H\n#define VQAFILE_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqafile.h\n*\n* DESCRIPTION\n*     VQA file format definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*      \n* DATE\n*     April 10, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\iff.h>\n\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n\n/*---------------------------------------------------------------------------\n * STRUCTURE DEFINITIONS AND RELATED DEFINES.\n *-------------------------------------------------------------------------*/\n\n/* VQAHeader: VQA movie description header. (VQHD)\n *\n * Version       - VQA version.\n * Flags         - Various flags. (See below)\n * ImageWidth    - Image width in pixels.\n * ImageHeight   - Image height in pixels.\n * BlockWidth    - Block width in pixels.\n * BlockHeight   - Block height in pixels.\n * Frames        - Total number of frames in the movie.\n * FPS           - Playback rate (Frame Per Second).\n * Groupsize     - Frame grouping size (frames per codebook).\n * Num1Colors    - Number of 1 color colors.\n * CBentries     - Number of codebook entries.\n * Xpos          - X position to draw frames. (-1 = Center)\n * Ypos          - Y position to draw frames. (-1 = Center)\n * MaxFramesize  - Size of largest frame.\n * SampleRate    - Sample rate of primary audio stream.\n * Channels      - Number of channels in primary audio stream.\n * BitsPerSample - Sample bit size in primary audio stream.\n * FutureUse     - Reserved for future expansion.\n */\ntypedef struct _VQAHeader {\n\tunsigned short Version;\n\tunsigned short Flags;\n\tunsigned short Frames;\n\tunsigned short ImageWidth;\n\tunsigned short ImageHeight;\n\tunsigned char  BlockWidth;\n\tunsigned char  BlockHeight;\n\tunsigned char  FPS;\n\tunsigned char  Groupsize;\n\tunsigned short Num1Colors;\n\tunsigned short CBentries;\n\tunsigned short Xpos;\n\tunsigned short Ypos;\n\tunsigned short MaxFramesize;\n\tunsigned short SampleRate;\n\tunsigned char  Channels;\n\tunsigned char  BitsPerSample;\n\tunsigned short AltSampleRate;\n\tunsigned char  AltChannels;\n\tunsigned char  AltBitsPerSample;\n\tunsigned short FutureUse[5];\n} VQAHeader;\n\n/* Version type. */\n#define VQAHD_VER1 1\n#define VQAHD_VER2 2\n\n/* VQA header flag definitions */\n#define VQAHDB_AUDIO    0 /* Audio track present. */\n#define VQAHDB_ALTAUDIO 1 /* Alternate audio track present. */\n#define VQAHDF_AUDIO    (1<<VQAHDB_AUDIO)\n#define VQAHDF_ALTAUDIO (1<<VQAHDB_ALTAUDIO)\n\n\n/* Frame information (FINF) chunk definitions\n *\n * The FINF chunk contains a longword (4 bytes) entry for each\n * frame in the movie. This entry is divided into two parts,\n * flags (4 bits) and offset (28 bits).\n *\n * BITS   NAME     DESCRIPTION\n * -----------------------------------------------------------\n * 31-28  Flags    4 bitwise boolean flags.\n * 27-0   Offset   Offset in WORDS from the start of the file.\n */\n#define VQAFINB_KEY  31\n#define VQAFINB_PAL  30\n#define VQAFINB_SYNC 29\n#define VQAFINF_KEY  (1L<<VQAFINB_KEY)\n#define VQAFINF_PAL  (1L<<VQAFINB_PAL)\n#define VQAFINF_SYNC (1L<<VQAFINB_SYNC)\n\n/* FINF related defines and macros. */\n#define VQAFINF_OFFSET 0x0FFFFFFFL\n#define VQAFINF_FLAGS  0xF0000000L\n#define VQAFRAME_OFFSET(a) (((a & VQAFINF_OFFSET)<<1))\n\n/* VQ vector pointer codes. */\n#define VPC_ONE_SINGLE    0xF000 /* One single color block */\n#define VPC_ONE_SEMITRANS 0xE000 /* One semitransparent block */\n#define VPC_SHORT_DUMP    0xD000 /* Short dump of single color blocks */\n#define VPC_LONG_DUMP     0xC000 /* Long dump of single color blocks */\n#define VPC_SHORT_RUN     0xB000 /* Short run of single color blocks */\n#define VPC_LONG_RUN      0xA000 /* Long run */\n\n/* Long run codes. */\n#define LRC_SEMITRANS 0xC000 /* Long run of semitransparent blocks. */\n#define LRC_SINGLE    0x8000 /* Long run of single color blocks. */\n\n/* Defines used for Run-Skip-Dump compression. */\n#define MIN_SHORT_RUN_LENGTH  2\n#define MAX_SHORT_RUN_LENGTH  15\n#define MIN_LONG_RUN_LENGTH   2\n#define MAX_LONG_RUN_LENGTH   4095\n#define MIN_SHORT_DUMP_LENGTH 3\n#define MAX_SHORT_DUMP_LENGTH 15\n#define MIN_LONG_DUMP_LENGTH  2\n#define MAX_LONG_DUMP_LENGTH  4095\n\n#define WORD_HI_BIT 0x8000\n\n/*---------------------------------------------------------------------------\n * VQA FILE CHUNK ID DEFINITIONS.\n *-------------------------------------------------------------------------*/\n\n#define ID_WVQA MAKE_ID('W','V','Q','A') /* Westwood VQ Animation form. */\n#define ID_VQHD MAKE_ID('V','Q','H','D') /* VQ header. */\n#define ID_NAME MAKE_ID('N','A','M','E') /* Name string. */\n#define ID_FINF MAKE_ID('F','I','N','F') /* Frame information. */\n#define ID_VQFR MAKE_ID('V','Q','F','R') /* VQ frame container. */\n#define ID_VQFK MAKE_ID('V','Q','F','K') /* VQ key frame container. */\n#define ID_CBF0 MAKE_ID('C','B','F','0') /* Full codebook. */\n#define ID_CBFZ MAKE_ID('C','B','F','Z') /* Full codebook (compressed). */\n#define ID_CBP0 MAKE_ID('C','B','P','0') /* Partial codebook. */\n#define ID_CBPZ MAKE_ID('C','B','P','Z') /* Partial codebook (compressed). */\n#define ID_VPT0 MAKE_ID('V','P','T','0') /* Vector pointers. */\n#define ID_VPTZ MAKE_ID('V','P','T','Z') /* Vector pointers (compressed). */\n#define ID_VPTK MAKE_ID('V','P','T','K') /* Vector pointers (Delta Key). */\n#define ID_VPTD MAKE_ID('V','P','T','D') /* Vector pointers (Delta). */\n#define ID_VPTR MAKE_ID('V','P','T','R') /* Pointers RSD compressed. */\n#define ID_VPRZ MAKE_ID('V','P','R','Z') /* Pointers RSD, lcw compressed. */\n#define ID_CPL0 MAKE_ID('C','P','L','0') /* Color palette. */\n#define ID_CPLZ MAKE_ID('C','P','L','Z') /* Color palette (compressed). */\n#define ID_SND0 MAKE_ID('S','N','D','0') /* Sound */\n#define ID_SND1 MAKE_ID('S','N','D','1') /* Sound (Zap compressed). */\n#define ID_SND2 MAKE_ID('S','N','D','2') /* Sound (ADPCM compressed). */\n#define ID_SNDZ MAKE_ID('S','N','D','Z') /* Sound (LCW compression). */\n\n#define ID_SNA0 MAKE_ID('S','N','A','0') /* Sound */\n#define ID_SNA1 MAKE_ID('S','N','A','1') /* Sound (Zap compressed). */\n#define ID_SNA2 MAKE_ID('S','N','A','2') /* Sound (ADPCM compressed). */\n#define ID_SNAZ MAKE_ID('S','N','A','Z') /* Sound (LCW compression). */\n\n#define ID_CAP0 MAKE_ID('C','A','P','0') /* Caption text */\n#define ID_EVA0 MAKE_ID('E','V','A','0') /* EVA text */\n\n#ifdef __WATCOMC__\n#pragma pack();\n#endif\n\n#endif /* VQAFILE_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQA32/VQAPLAY.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAPLAY_H\n#define VQAPLAY_H\n/****************************************************************************\n*\n*         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\n*\n*---------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqaplay.h\n*\n* DESCRIPTION\n*      VQAPlay library definitions.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     February 23, 1995\n*\n****************************************************************************/\n\n/*---------------------------------------------------------------------------\n * CONDITIONAL COMPILATION FLAGS\n *-------------------------------------------------------------------------*/\n\n#ifdef __WATCOMC__\n#define VQAVOC_ON    0  /* Enable VOC file override */\n#define\tVQAMONO_ON   1  /* Mono display output enable/disable */\n#define VQAAUDIO_ON  1  /* Audio playback enable/disable */\n#define VQAVIDEO_ON  0  /* Video manager enable/disable */\n#define VQAMCGA_ON   1  /* MCGA enable/disable */\n#define VQAXMODE_ON  0  /* Xmode enable/disable */\n#define VQAVESA_ON   0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2 1  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3 1  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2 1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4 1  /* 4x4 block decode enable/disable */\n#else\n#define VQAVOC_ON    1  /* Enable VOC file override */\n#define\tVQAMONO_ON   1  /* Mono display output enable/disable */\n#define VQAAUDIO_ON  0  /* Audio playback enable/disable */\n#define VQAVIDEO_ON  0  /* Video manager enable/disable */\n#define VQAMCGA_ON   1  /* MCGA enable/disable */\n#define VQAXMODE_ON  0  /* Xmode enable/disable */\n#define VQAVESA_ON   0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2 1  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3 1  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2 1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4 1  /* 4x4 block decode enable/disable */\n#endif\n\n/*---------------------------------------------------------------------------\n * GENERAL CONSTANT DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* Playback modes. */\n#define VQAMODE_RUN  0 /* Run the movie through the end. */\n#define VQAMODE_WALK 1 /* Draw the next frame then return. */\n#define VQAMODE_STOP 2 /* Stop the movie. */\n\n/* Playback timer methods */\n#define VQA_TMETHOD_DEFAULT -1 /* Use default timer method. */\n#define\tVQA_TMETHOD_DOS      1 /* DOS timer method */\n#define\tVQA_TMETHOD_INT      2 /* Interrupt timer method */\n#define\tVQA_TMETHOD_AUDIO    3 /* Audio timer method */\n\n/* Error/condition values */\n#define\tVQAERR_EOF      -1  /* Valid end of file */\n#define VQAERR_OPEN     -2  /* Unable to open */\n#define\tVQAERR_READ     -3  /* Read error */\n#define VQAERR_WRITE    -4  /* Write error */\n#define VQAERR_SEEK     -5  /* Seek error */\n#define VQAERR_NOTVQA   -6  /* Not a valid VQA file. */\n#define VQAERR_NOMEM    -7  /* Unable to allocate memory */\n#define\tVQAERR_NOBUFFER -8  /* No buffer avail for load/draw */\n#define\tVQAERR_NOT_TIME -9  /* Not time for frame yet */\n#define\tVQAERR_SLEEPING -10 /* Function is in a sleep state */\n#define VQAERR_VIDEO    -11 /* Video related error. */\n#define VQAERR_AUDIO    -12 /* Audio related error. */\n\n/* Memory limits */\n#define\tVQA_NUM_MAXRATES 5  /* Number of max rates in the Config struct */\n#define\tVQA_TIMETICKS    60 /* Clock ticks per second */\n\n/*---------------------------------------------------------------------------\n * STRUCTURES AND RELATED DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* VQAConfig: Player configuration structure\n *\n * DrawerCallback - User routine for Drawer to call each frame (NULL = none)\n * Vmode          - Requested Video mode (May be promoted).\n * VBIBit         - Vertical blank bit polarity.\n * ImageBuf       - Pointer to caller's buffer for the Drawer to use as its\n *                  ImageBuf; NULL = player will allocate its own, if\n *                  VQACFGF_BUFFER is set in DrawFlags.\n * ImageWidth     - Width of Image buffer.\n * ImageHeight    - Height of Image buffer.\n * X1             - Draw window X coordinate (-1 = Center).\n * Y1             - Draw window Y coordinate (-1 = Center).\n * FrameRate      - Desired frames per second (-1 = use VQA header's value).\n * DrawRate       - Desired drawing frame rate; allows the Drawer to draw at\n *                  a separate rate from the Loader.\n * TimerMethod    - Timer method to use during playback.\n * DrawFlags      - Bits control various special drawing options. (See below)\n * OptionFlags    - Bits control various special misc options. (See below)\n * NumFrameBufs   - Desired number of frame buffers. (Default = 6)\n * NumCBBufs      - Desired number of codebook buffers. (Default = 3)\n * VocFile        - Name of VOC file to play instead of VQA audio track.\n * AudioBuf       - Pointer to audio buffer.\n * AudioBufSize   - Size of audio buffer. (Default = 32768)\n * AudioRate      - Audio data playback rate (-1 = use 22050 scaled to the\n *                  frame rate)\n * Volume         - Audio playback volume. (0x7FFF = max)\n * HMIBufSize     - Desired HMI buffer size. (Default = 2000)\n * DigiHandle     - Handle to an initialized sound driver. (-1 = none)\n * DigiCard       - HMI ID of card to use. (0 = none, -1 = auto-detect)\n * DigiPort       - Audio port address. (-1 = auto-detect)\n * DigiIRQ        - Audio IRQ. (-1 = auto-detect)\n * DigiDMA        - Audio DMA channel. (-1 = auto-detect)\n * MaxRate        - Fixed rate playback table.\n */\ntypedef struct _VQAConfig {\n\tvoid (*DrawerCallback)(unsigned char *screen, long framenum);\n\tlong          Vmode;\n\tlong          VBIBit;\n\tunsigned char *ImageBuf;\n\tlong          ImageWidth;\n\tlong          ImageHeight;\n\tlong          X1,Y1;\n\tlong          FrameRate;\n\tlong          DrawRate;\n\tlong          TimerMethod;\n\tlong          DrawFlags;\n\tlong          OptionFlags;\n\tlong          NumFrameBufs;\n\tlong          NumCBBufs;\n\tchar          *VocFile;\n\tunsigned char *AudioBuf;\n\tlong          AudioBufSize;\n\tlong          AudioRate;\n\tlong          Volume;\n\tlong          HMIBufSize;\n\tlong          DigiHandle;\n\tlong          DigiCard;\n\tlong          DigiPort;\n\tlong          DigiIRQ;\n\tlong          DigiDMA;\n} VQAConfig;\n\n/* Drawer Configuration flags (DrawFlags) */\n#define\tVQACFGB_BUFFER   0 /* Buffer UnVQ enable */\n#define\tVQACFGB_NODRAW   1 /* Drawing disable */\n#define VQACFGB_NOSKIP   2 /* Disable frame skipping. */\n#define\tVQACFGB_VRAMCB   3 /* XMode VRAM copy enable */\n#define VQACFGB_ORIGIN   4 /* 0,0 origin position */\n#define\tVQACFGB_SCALEX2  6 /* Scale X2 enable (VESA 320x200 to 640x400) */\n#define\tVQACFGF_BUFFER   (1<<VQACFGB_BUFFER)\n#define\tVQACFGF_NODRAW   (1<<VQACFGB_NODRAW)\n#define\tVQACFGF_NOSKIP   (1<<VQACFGB_NOSKIP)\n#define\tVQACFGF_VRAMCB   (1<<VQACFGB_VRAMCB)\n#define\tVQACFGF_ORIGIN   (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPLEFT  (0<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPRIGHT (1<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTRIGHT (2<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTLEFT  (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_SCALEX2  (1<<VQACFGB_SCALEX2)\n\n/* Options Configuration (OptionFlags) */\n#define\tVQAOPTB_AUDIO   0 /* Audio enable */\n#define\tVQAOPTB_STEP    1 /* Single step enable */\n#define\tVQAOPTB_MONO    2 /* Mono output enable */\n#define\tVQAOPTB_FINF    3 /* Frame info chunk enable */\n#define\tVQAOPTB_SLOWPAL 4 /* Slow palette enable */\n#define VQAOPTB_HMIINIT 5 /* HMI already initialized by client. */\n#define\tVQAOPTF_AUDIO   (1<<VQAOPTB_AUDIO)\n#define\tVQAOPTF_STEP    (1<<VQAOPTB_STEP)\n#define\tVQAOPTF_MONO    (1<<VQAOPTB_MONO)\n#define\tVQAOPTF_FINF    (1<<VQAOPTB_FINF)\n#define\tVQAOPTF_SLOWPAL (1<<VQAOPTB_SLOWPAL)\n#define VQAOPTF_HMIINIT (1<<VQAOPTB_HMIINIT)\n\n/* VQAInfo: Information about the VQA movie.\n *\n * NumFrames   - The number of frames contained in the movie.\n * ImageHeight - Height of image in pixels.\n * ImageWidth  - Width of image in pixels.\n */\ntypedef struct _VQAInfo {\n\tlong NumFrames;\n\tlong ImageWidth;\n\tlong ImageHeight;\n} VQAInfo;\n\n/* VQAStatistics: Statistics about the VQA movie played.\n *\n * StartTime     - Time movie started.\n * EndTime       - Time movie stoped.\n * FramesLoaded  - Total number of frames loaded.\n * FramesDrawn   - Total number of frames drawn.\n * FramesSkipped - Total number of frames skipped.\n * MaxFrameSize  - Size of largest frame.\n * SamplesPlayed - Number of sample bytes played.\n * MemUsed       - Total bytes used. (Low memory)\n */\ntypedef struct _VQAStatistics {\n\tlong          StartTime;\n\tlong          EndTime;\n\tlong          FramesLoaded;\n\tlong          FramesDrawn;\n\tlong          FramesSkipped;\n\tlong          MaxFrameSize;\n\tunsigned long SamplesPlayed;\n\tunsigned long MemUsed;\n} VQAStatistics;\n\n/* VQAHandle: VQA file handle. (Must be obtained by calling VQA_Alloc()\n *            and freed through VQA_Free(). This is the only legal way\n *            to obtain and dispose of a VQAHandle.\n *\n * VQAStream - Something meaningful to the stream manager. (See DOCS)\n */\ntypedef struct _VQAHandle {\n\tunsigned long VQAStream;\n} VQAHandle;\n\n/* Possible stream command values */\n#define VQACMD_INIT    1 /* Prepare the stream for a session */\n#define VQACMD_CLEANUP 2 /* Terminate stream session */\n#define VQACMD_OPEN    3 /* Open stream */\n#define VQACMD_CLOSE   4 /* Close stream */\n#define VQACMD_READ    5 /* Read bytes from stream */\n#define VQACMD_WRITE   6 /* Write bytes to stream */\n#define VQACMD_SEEK    7 /* Seek on stream */\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\nvoid VQA_INIConfig(VQAConfig *config);\nvoid VQA_DefaultConfig(VQAConfig *config);\n\nVQAHandle *VQA_Alloc(void);\nvoid VQA_Free(VQAHandle *vqa);\nvoid VQA_InitAsDOS(VQAHandle *vqa);\nvoid VQA_Init(VQAHandle *vqa, unsigned long(*streamhandler)(VQAHandle *vqa,\n\t\tlong action, void *buffer, long nbytes));\n\nlong VQA_Open(VQAHandle *vqa, char const *filename, VQAConfig *config);\nvoid VQA_Close(VQAHandle *vqa);\nlong VQA_Play(VQAHandle *vqa, long mode);\n\nvoid VQA_GetInfo(VQAHandle *vqa, VQAInfo *info);\nvoid VQA_GetStats(VQAHandle *vqa, VQAStatistics *stats);\nchar *VQA_Version(void);\nchar *VQA_IDString(void);\n\n#endif  /* VQAPLAY_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQA32/VQAPLAY.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAPLAY_H\n#define VQAPLAY_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqaplay.h\n*\n* DESCRIPTION\n*      VQAPlay library definitions.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 10, 1995\n*\n****************************************************************************/\n\n/*---------------------------------------------------------------------------\n * CONDITIONAL COMPILATION FLAGS\n *-------------------------------------------------------------------------*/\n\n#ifdef __WATCOMC__\n#define VQASTANDALONE 0  /* Stand alone player */\n#define VQAVOC_ON     0  /* Enable VOC file override */\n#define\tVQAMONO_ON    0  /* Mono display output enable/disable */\n#define VQAAUDIO_ON   1  /* Audio playback enable/disable */\n#define VQAVIDEO_ON   0  /* Video manager enable/disable */\n#define VQAMCGA_ON    1  /* MCGA enable/disable */\n#define VQAXMODE_ON   0  /* Xmode enable/disable */\n#define VQAVESA_ON    0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2  1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4  0  /* 4x4 block decode enable/disable */\n#define VQAWOOFER_ON  0\n#else\n#define VQASTANDALONE 0  /* Stand alone player */\n#define VQAVOC_ON     0  /* Enable VOC file override */\n#define\tVQAMONO_ON    1  /* Mono display output enable/disable */\n#define VQAAUDIO_ON   0  /* Audio playback enable/disable */\n#define VQAVIDEO_ON   0  /* Video manager enable/disable */\n#define VQAMCGA_ON    1  /* MCGA enable/disable */\n#define VQAXMODE_ON   0  /* Xmode enable/disable */\n#define VQAVESA_ON    0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2  1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4  0  /* 4x4 block decode enable/disable */\n#define VQAWOOFER_ON  0\n#endif\n\n\n/*---------------------------------------------------------------------------\n * GENERAL CONSTANT DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* Playback modes. */\n#define VQAMODE_RUN   0  /* Run the movie through the end. */\n#define VQAMODE_WALK  1  /* Draw the next frame then return. */\n#define VQAMODE_PAUSE 2  /* Suspend movie playback. */\n#define VQAMODE_STOP  3  /* Stop the movie. */\n\n/* Playback timer methods */\n#define VQA_TMETHOD_DEFAULT -1 /* Use default timer method. */\n#define\tVQA_TMETHOD_DOS      1 /* DOS timer method */\n#define\tVQA_TMETHOD_INT      2 /* Interrupt timer method */\n#define\tVQA_TMETHOD_AUDIO    3 /* Audio timer method */\n\n#define\tVQA_TIMETICKS 60 /* Clock ticks per second */\n\n/* Error/Status conditions */\n#define VQAERR_NONE      0  /* No error */\n#define\tVQAERR_EOF      -1  /* Valid end of file */\n#define VQAERR_OPEN     -2  /* Unable to open */\n#define\tVQAERR_READ     -3  /* Read error */\n#define VQAERR_WRITE    -4  /* Write error */\n#define VQAERR_SEEK     -5  /* Seek error */\n#define VQAERR_NOTVQA   -6  /* Not a valid VQA file. */\n#define VQAERR_NOMEM    -7  /* Unable to allocate memory */\n#define\tVQAERR_NOBUFFER -8  /* No buffer avail for load/draw */\n#define\tVQAERR_NOT_TIME -9  /* Not time for frame yet */\n#define\tVQAERR_SLEEPING -10 /* Function is in a sleep state */\n#define VQAERR_VIDEO    -11 /* Video related error. */\n#define VQAERR_AUDIO    -12 /* Audio related error. */\n#define VQAERR_PAUSED   -13 /* In paused state. */\n\n/* Event flags. */\n#define VQAEVENT_PALETTE (1<<0)\n#define VQAEVENT_SYNC    (1<<1)\n\n\n/*---------------------------------------------------------------------------\n * STRUCTURES AND RELATED DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* VQAConfig: Player configuration structure\n *\n * DrawerCallback - User routine for Drawer to call each frame (NULL = none)\n * EventHandler   - User routine for notification to client of events.\n * NotifyFlags    - User specified events to be notified about.\n * Vmode          - Requested Video mode (May be promoted).\n * VBIBit         - Vertical blank bit polarity.\n * ImageBuf       - Pointer to caller's buffer for the Drawer to use as its\n *                  ImageBuf; NULL = player will allocate its own, if\n *                  VQACFGF_BUFFER is set in DrawFlags.\n * ImageWidth     - Width of Image buffer.\n * ImageHeight    - Height of Image buffer.\n * X1             - Draw window X coordinate (-1 = Center).\n * Y1             - Draw window Y coordinate (-1 = Center).\n * FrameRate      - Desired frames per second (-1 = use VQA header's value).\n * DrawRate       - Desired drawing frame rate; allows the Drawer to draw at\n *                  a separate rate from the Loader.\n * TimerMethod    - Timer method to use during playback.\n * DrawFlags      - Bits control various special drawing options. (See below)\n * OptionFlags    - Bits control various special misc options. (See below)\n * NumFrameBufs   - Desired number of frame buffers. (Default = 6)\n * NumCBBufs      - Desired number of codebook buffers. (Default = 3)\n * VocFile        - Name of VOC file to play instead of VQA audio track.\n * AudioBuf       - Pointer to audio buffer.\n * AudioBufSize   - Size of audio buffer. (Default = 32768)\n * AudioRate      - Audio data playback rate (-1 = use samplerate scaled\n *                  to the frame rate)\n * Volume         - Audio playback volume. (0x7FFF = max)\n * HMIBufSize     - Desired HMI buffer size. (Default = 2000)\n * DigiHandle     - Handle to an initialized sound driver. (-1 = none)\n * DigiCard       - HMI ID of card to use. (0 = none, -1 = auto-detect)\n * DigiPort       - Audio port address. (-1 = auto-detect)\n * DigiIRQ        - Audio IRQ. (-1 = auto-detect)\n * DigiDMA        - Audio DMA channel. (-1 = auto-detect)\n * Language       - Language identifier. (Not used)\n * CapFont        - Pointer to font to use for subtitle text captions.\n * EVAFont        - Pointer to font to use for E.V.A text cations. (For C&C)\n */\ntypedef struct _VQAConfig {\n\tlong          (*DrawerCallback)(unsigned char *screen, long framenum);\n\tlong          (*EventHandler)(unsigned long event,void *buffer,long nbytes);\n\tunsigned long NotifyFlags;\n\tlong          Vmode;\n\tlong          VBIBit;\n\tunsigned char *ImageBuf;\n\tlong          ImageWidth;\n\tlong          ImageHeight;\n\tlong          X1,Y1;\n\tlong          FrameRate;\n\tlong          DrawRate;\n\tlong          TimerMethod;\n\tlong          DrawFlags;\n\tlong          OptionFlags;\n\tlong          NumFrameBufs;\n\tlong          NumCBBufs;\n\tchar          *VocFile;\n\tunsigned char *AudioBuf;\n\tlong          AudioBufSize;\n\tlong          AudioRate;\n\tlong          Volume;\n\tlong          HMIBufSize;\n\tlong          DigiHandle;\n\tlong          DigiCard;\n\tlong          DigiPort;\n\tlong          DigiIRQ;\n\tlong          DigiDMA;\n\tlong          Language;\n\tchar          *CapFont;\n\tchar          *EVAFont; /* For C&C Only */\n} VQAConfig;\n\n/* Drawer Configuration flags (DrawFlags) */\n#define\tVQACFGB_BUFFER   0 /* Buffer UnVQ enable */\n#define\tVQACFGB_NODRAW   1 /* Drawing disable */\n#define VQACFGB_NOSKIP   2 /* Disable frame skipping. */\n#define\tVQACFGB_VRAMCB   3 /* XMode VRAM copy enable */\n#define VQACFGB_ORIGIN   4 /* 0,0 origin position */\n#define\tVQACFGB_SCALEX2  6 /* Scale X2 enable (VESA 320x200 to 640x400) */\n#define VQACFGB_WOOFER   7\n#define\tVQACFGF_BUFFER   (1<<VQACFGB_BUFFER)\n#define\tVQACFGF_NODRAW   (1<<VQACFGB_NODRAW)\n#define\tVQACFGF_NOSKIP   (1<<VQACFGB_NOSKIP)\n#define\tVQACFGF_VRAMCB   (1<<VQACFGB_VRAMCB)\n#define\tVQACFGF_ORIGIN   (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPLEFT  (0<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPRIGHT (1<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTRIGHT (2<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTLEFT  (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_SCALEX2  (1<<VQACFGB_SCALEX2)\n#define VQACFGF_WOOFER   (1<<VQACFGB_WOOFER)\n\n/* Options Configuration (OptionFlags) */\n#define\tVQAOPTB_AUDIO    0 /* Audio enable. */\n#define\tVQAOPTB_STEP     1 /* Single step enable. */\n#define\tVQAOPTB_MONO     2 /* Mono output enable. */\n#define VQAOPTB_PALOFF   3 /* Palette set disable. */\n#define\tVQAOPTB_SLOWPAL  4 /* Slow palette enable. */\n#define VQAOPTB_HMIINIT  5 /* HMI already initialized by client. */\n#define VQAOPTB_ALTAUDIO 6 /* Use alternate audio track. */\n#define VQAOPTB_CAPTIONS 7 /* Show captions. */\n#define VQAOPTB_EVA      8 /* Show EVA text (For C&C only) */\n#define\tVQAOPTF_AUDIO    (1<<VQAOPTB_AUDIO)\n#define\tVQAOPTF_STEP     (1<<VQAOPTB_STEP)\n#define\tVQAOPTF_MONO     (1<<VQAOPTB_MONO)\n#define VQAOPTF_PALOFF   (1<<VQAOPTB_PALOFF)\n#define\tVQAOPTF_SLOWPAL  (1<<VQAOPTB_SLOWPAL)\n#define VQAOPTF_HMIINIT  (1<<VQAOPTB_HMIINIT)\n#define\tVQAOPTF_ALTAUDIO (1<<VQAOPTB_ALTAUDIO)\n#define VQAOPTF_CAPTIONS (1<<VQAOPTB_CAPTIONS)\n#define VQAOPTF_EVA      (1<<VQAOPTB_EVA) /* For C&C only */\n\n\n/* VQAInfo: Information about the VQA movie.\n *\n * NumFrames   - The number of frames contained in the movie.\n * ImageHeight - Height of image in pixels.\n * ImageWidth  - Width of image in pixels.\n * ImageBuf    - Pointer to the image buffer VQA draw into.\n */\ntypedef struct _VQAInfo {\n\tlong NumFrames;\n\tlong ImageWidth;\n\tlong ImageHeight;\n\tunsigned char *ImageBuf;\n} VQAInfo;\n\n\n/* VQAStatistics: Statistics about the VQA movie played.\n *\n * StartTime     - Time movie started.\n * EndTime       - Time movie stoped.\n * FramesLoaded  - Total number of frames loaded.\n * FramesDrawn   - Total number of frames drawn.\n * FramesSkipped - Total number of frames skipped.\n * MaxFrameSize  - Size of largest frame.\n * SamplesPlayed - Number of sample bytes played.\n * MemUsed       - Total bytes used. (Low memory)\n */\ntypedef struct _VQAStatistics {\n\tlong          StartTime;\n\tlong          EndTime;\n\tlong          FramesLoaded;\n\tlong          FramesDrawn;\n\tlong          FramesSkipped;\n\tlong          MaxFrameSize;\n\tunsigned long SamplesPlayed;\n\tunsigned long MemUsed;\n} VQAStatistics;\n\n\n/* VQAHandle: VQA file handle. (Must be obtained by calling VQA_Alloc()\n *            and freed through VQA_Free(). This is the only legal way\n *            to obtain and dispose of a VQAHandle.\n *\n * VQAio - Something meaningful to the IO manager. (See DOCS)\n */\ntypedef struct _VQAHandle {\n\tunsigned long VQAio;\n} VQAHandle;\n\n/* Possible IO command values */\n#define VQACMD_INIT    1 /* Prepare the IO for a session */\n#define VQACMD_CLEANUP 2 /* Terminate IO session */\n#define VQACMD_OPEN    3 /* Open file */\n#define VQACMD_CLOSE   4 /* Close file */\n#define VQACMD_READ    5 /* Read bytes */\n#define VQACMD_WRITE   6 /* Write bytes */\n#define VQACMD_SEEK    7 /* Seek */\n\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n/* Configuration routines. */\nvoid VQA_INIConfig(VQAConfig *config);\nvoid VQA_DefaultConfig(VQAConfig *config);\n\n/* Handle manipulation routines. */\nVQAHandle *VQA_Alloc(void);\nvoid VQA_Free(VQAHandle *vqa);\nvoid VQA_InitAsDOS(VQAHandle *vqa);\nvoid VQA_Init(VQAHandle *vqa, long(*iohandler)(VQAHandle *vqa, long action,\n\t\tvoid *buffer, long nbytes));\n\n/* File routines. */\nlong VQA_Open(VQAHandle *vqa, char const *filename, VQAConfig *config);\nvoid VQA_Close(VQAHandle *vqa);\nlong VQA_Play(VQAHandle *vqa, long mode);\nlong VQA_SeekFrame(VQAHandle *vqa, long frame, long fromwhere);\n\n/* Information/statistics access routines. */\nvoid VQA_GetInfo(VQAHandle *vqa, VQAInfo *info);\nvoid VQA_GetStats(VQAHandle *vqa, VQAStatistics *stats);\nchar *VQA_Version(void);\nchar *VQA_IDString(void);\n\n#endif /* VQAPLAY_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/ALL.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMALL_H\n#define VQMALL_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     all.h\n*\n* DESCRIPTION\n*     All VQMisc32 library definitions. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 5, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\iff.h>\n#include <vqm32\\mono.h>\n#include <vqm32\\portio.h>\n#include <vqm32\\profile.h>\n#include <vqm32\\targa.h>\n#include <vqm32\\compress.h>\n#include <vqm32\\video.h>\n#include <vqm32\\palette.h>\n#include <vqm32\\vesavid.h>\n#include <vqm32\\vesablit.h>\n#include <vqm32\\graphics.h>\n#include <vqm32\\mixfile.h>\n#include <vqm32\\crc.h>\n#include <vqm32\\huffman.h>\n#include <vqm32\\mem.h>\n\n#endif /* VQMALL_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/CAPTOKEN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMCAPTOKEN_H\n#define VQMCAPTOKEN_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     captoken.h\n*\n* DESCRIPTION\n*     Text caption script definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 26, 1995\n*\n****************************************************************************/\n\n/* CaptionText: This structure describes a line of text to be displayed\n *              with the video/audio.\n *\n * Size     - Size of caption in bytes.\n * OnFrame  - Frame number to display caption.\n * OffFrame - Frame number to clear caption.\n * Flags    - Display modifiers.\n * CPF      - Characters to draw per frame.\n * Xpos     - X pixel position to display caption.\n * Ypos     - Y pixel position to display caption.\n * BgPen    - Background pen to use.\n * FgPen    - Foreground pen to use.\n * Text     - Text string to display. (WORD aligned)\n */\ntypedef struct _CaptionText {\n\tunsigned short Size;\n\tunsigned short OnFrame;\n\tunsigned short OffFrame;\n\tunsigned char  Flags;\n\tchar           CPF;\n\tunsigned short Xpos;\n\tunsigned short Ypos;\n\tchar           BgPen;\n\tchar           FgPen;\n\tchar           Text[];\n} CaptionText;\n\n/* CaptionText flag definitions. */\n#define CTF_JUSTIFY\t(3<<0)  /* Justification field. */\n#define CTF_ABS     (0<<0)  /* Use absolute X,Y positions. */\n#define CTF_CENTER  (1<<0)  /* Justify on Center */\n#define CTF_LEFT    (2<<0)  /* Justify on left */\n#define CTF_RIGHT   (3<<0)  /* Justify on right */\n#define CTF_FLASH   (1<<4)  /* Flash text. */\n\n/* Function prototypes. */\nlong BuildCaptions(char *name, char *buffer);\n\n#endif /* VQMCAPTOKEN_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/COMPRESS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMCOMP_H\n#define VQMCOMP_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     compress.h\n*\n* DESCRIPTION\n*     Compression definitions. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nunsigned long cdecl LCW_Compress(char const *source, char *dest,\n\t\tunsigned long length);\nunsigned long cdecl LCW_Uncompress(char const *source, char *dest,\n\t\tunsigned long length);\nlong AudioZap(void *source, void *dest, long size);\nlong cdecl AudioUnzap(void *source, void *dest, long);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMCOMP_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/CRC.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMCRC_H\n#define VQMCRC_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     CRC.h\n*\n* DESCRIPTION\n*     CRC calculation definitions.\n*\n* PROGRAMMER\n*     Joe L. Bostic\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nlong cdecl Calculate_CRC(void const *buffer, long length);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMCRC_H */\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/FONT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMFONT_H\n#define VQMFONT_H\n/****************************************************************************\n*\n*        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\n*\n*---------------------------------------------------------------------------\n*\n* FILE\n*     font.h\n*\n* DESCRIPTION\n*     Font definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     March 9, 1995\n*\n****************************************************************************/\n\n/* Font: A Westwood style font.\n *\n * Size       - Size of font.\n * CompMethod - Compression method of font. (0 = none)\n * NumBlks    - Number of data blocks.\n * InfoBlk    - Offset to font information block.\n * OffsetBlk  - Offset to character offset block.\n * WidthBlk   - Offset to character width block.\n * DataBlk    - Offset to character data block.\n * HeightBlk  - Offset to character height block.\n */\ntypedef struct _Font {\n\tunsigned short Size;\n\tunsigned char  CompMethod;\n\tunsigned char  NumBlks;\n\tunsigned short InfoBlk;\n\tunsigned short OffsetBlk;\n\tunsigned short WidthBlk;\n\tunsigned short DataBlk;\n\tunsigned short HeightBlk;\n} Font;\n\ntypedef struct _FontInfo {\n\tlong huh;\n\tunsigned char MaxHeight;\n\tunsigned char MaxWidth;\n} FontInfo;\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern void const *FontPtr;\nextern int FontXSpacing;\nextern int FontYSpacing;\n\n#ifdef __cplusplus\n}\n#endif\n\nextern char FontWidth;\nextern char FontHeight;\nextern char *FontWidthBlockPtr;\n\n/* Function prototypes. */\nvoid *cdecl Load_Font(char const *name);\nvoid *cdecl Set_Font(void const *font);\nunsigned short cdecl String_Pixel_Width(char const *string);\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef __WATCOMC__\nlong cdecl __saveregs Char_Pixel_Width(char chr);\n#else\nlong cdecl Char_Pixel_Width(char chr);\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMFONT_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/GRAPHICS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMGRAPHICS_H\n#define VQMGRAPHICS_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     graphics.h\n*\n* DESCRIPTION\n*     Graphic rendering and manipulation definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 27, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid cdecl Eor_Region(long sx, long sy, long dx, long dy, long color);\nvoid cdecl Fill_Rect(long x1, long y1, long x2, long y2, long color);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMGRAPHICS_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/HUFFMAN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef HUFFMAN_H\n#define HUFFMAN_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     huffman.h\n*\n* DESCRIPTION\n*     Huffman order 0 compress/decompress definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*      \n* DATE\n*     May 19, 1995\n*\n****************************************************************************/\n\n\n/* TreeNode: Huffman decoding tree node.\n *\n * count  - Weight of the node in the tree.\n * child0 - Child node 0\n * child1 - Child node 1\n */\ntypedef struct _TreeNode {\n \tunsigned long  count;\n\tunsigned short child0;\n\tunsigned short child1;\n} TreeNode;\n\n\n/* HuffCode: This structure is used for storing the code for each symbol\n *            during encoding. A table of codes for each symbol is built\n *            from the Huffman tree.\n *\n * code - Code used to represent a symbol.\n * bits - Length of code in bits.\n */\ntypedef struct _HuffCode {\n\tunsigned short code;\n\tshort          bits;\n} HuffCode;\n\n\n#define HUFF_EOS 256 /* End of stream symbol */\n\n/* Prototypes */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nlong cdecl HuffCompress(unsigned char *data, unsigned char *buffer,\n\t\tlong length, char *work);\n\nlong cdecl HuffDecompress(unsigned char *data, unsigned char *buffer,\n\t\tlong length, char *work);\n\nvoid cdecl HuffCount(unsigned char *data, TreeNode *nodes, long length,\n\t\tlong zero);\n\nvoid cdecl HuffScaleCounts(TreeNode *nodes);\nlong cdecl RLEHuffCounts(TreeNode *nodes, unsigned char *buffer);\nlong cdecl BuildHuffTree(TreeNode *nodes);\n\nvoid cdecl ConvertToCodes(TreeNode *nodes, HuffCode *codes,\n\t\tunsigned short code, short bits, short node);\n\nlong cdecl HuffEncode(unsigned char *data, unsigned char *buffer,\n\t\tHuffCode *codes, long length);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* HUFFMAN_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/IFF.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMIFF_H\n#define VQMIFF_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     iff.h\n* \n* DESCRIPTION\n*     IFF (Interchange File Format) manager definitions.\n*     (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/* FormHeader - Structure associated with IFF forms.\n *\n * id   - IFF form id (IE: \"FORM\")\n * size - Length of IFF in bytes\n * type - Form type (IE: \"ILBM\")\n */\ntypedef struct _FormHeader {\n\tlong id;\n\tlong size;\n\tlong type;\n} FormHeader;\n\n/* Context - Structure associated with chunks.\n *\n * id   - Chunk identifier.\n * size - Size of chunk in bytes.\n * scan - Bytes read/written.\n */\ntypedef struct _Context {\n\tlong id;\n\tlong size;\n\tlong scan;\n} Context;\n\n/* IFFHandle - Structure associated with an active IFF read\\write session.\n *\n * fh    - DOS filehandle\n * flags - Internal flags used by IFF routines.\n * form  - IFF form information.\n * scan  - Bytes read/written\n * cn    - Context of current chunk.\n */\ntypedef struct _IFFHandle {\n\tlong       fh;\n\tlong       flags;\n\tFormHeader form;\n\tlong       scan;\n\tContext    cn;\n} IFFHandle;\n\n/*\tbit masks for \"flags\" field. */\n#define IFFB_READ  0\n#define IFFB_WRITE 1\n#define IFFF_READ  (1<<IFFB_READ)\n#define IFFF_WRITE (1<<IFFB_WRITE)\n\n/* IFF return codes. Most functions return either zero for success or\n * one of these codes. The exceptions are the read/write functions which,\n * return positive values for number of bytes read or written, or a negative\n * error code.\n *\n * IFFERR_EOF   - End of file.\n * IFFERR_READ  - Read error.\n * IFFERR_WRITE - Write error.\n * IFFERR_NOMEM - Unable to allocate memory.\n */\n#define IFFERR_EOF   -1\n#define IFFERR_READ  -2\n#define IFFERR_WRITE -3\n#define IFFERR_NOMEM -4\n\n/* Macros to make things easier. */\n#define REVERSE_LONG(id) (unsigned long)((((unsigned long)(id)>>24) \\\n\t\t&0x000000FFL)|(((unsigned long)(id)>>8) \\\n\t\t&0x0000FF00L)|(((unsigned long)(id)<<8) \\\n\t\t&0x00FF0000L)|(((unsigned long)(id)<<24)&0xFF000000L))\n\n#define REVERSE_WORD(id) ((unsigned short)((((unsigned short)(id)<<8) \\\n\t\t&0x00FF00)|(((unsigned short)(id)>>8)&0x0FF)))\n\n#define PADSIZE(size) (((size)+1)&(~1))\n\n#ifndef MAKE_ID\n#define MAKE_ID(a,b,c,d) ((long)((long)(d)<<24)|((long)(c)<<16)| \\\n\t\t((long)(b)<<8)|(long)(a))\n#endif\n\n/* Universal IFF identifiers */\n#define ID_FORM MAKE_ID('F','O','R','M')\n#define ID_LIST MAKE_ID('L','I','S','T')\n#define ID_PROP MAKE_ID('P','R','O','P')\n#define ID_NULL MAKE_ID(' ',' ',' ',' ')\n\n/* Prototypes */\nIFFHandle *OpenIFF(char *, long);\nvoid CloseIFF(IFFHandle *);\nlong ReadForm(IFFHandle *, FormHeader *);\nlong WriteForm(IFFHandle *, FormHeader *);\nlong ReadChunkHeader(IFFHandle *);\nlong WriteChunkHeader(IFFHandle *, long, long);\nlong WriteChunk(IFFHandle *, long, char *, long);\nlong WriteChunkBytes(IFFHandle *, char *, long);\nlong ReadChunkBytes(IFFHandle *, char *, long);\nlong SkipChunkBytes(IFFHandle *, long);\nlong FindChunk(IFFHandle *, long);\nchar *IDtoStr(long, char *);\nlong CurrentFilePos(IFFHandle *);\n\n#endif /* VQMIFF_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/MEM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAMEM_H\n#define VQAMEM_H\n/****************************************************************************\n*\n*        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\n*\n*---------------------------------------------------------------------------\n*\n* FILE\n*     mem.h\n*\n* DESCRIPTION\n*     Memory management definitions.\n*\n* PROGRAMMER\n*     Phil Gorrow\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 5, 1995\n*\n****************************************************************************/\n\n/* Definitions */\n#define DPMI_INT    0x0031\n#define DPMI_LOCK   0x0600\n#define DPMI_UNLOCK 0x0601\n\n/* Prototypes */\n#ifdef __WATCOMC__\nvoid DPMI_Lock(void const *ptr, long const size);\nvoid DPMI_Unlock(void const *ptr, long const size);\n#else\n#define DPMI_Lock(a,b)\n#define DPMI_Unlock(a,b)\n#endif\n\n#endif /* VQAMEM_H */\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/MIXFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMMIXFILE_H\n#define VQMMIXFILE_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     mixfile.h\n*\n* DESCRIPTION\n*     A mix file is basically a group of files concatinated together\n*     proceeded by a header describing where in the file each individual\n*     entry is located. These definitions are provided to simplify the access\n*     to these file entries.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/* Disable structure alignment.*/\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n\n/*---------------------------------------------------------------------------\n * STRUCTURE DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* MIXHeader: Mix file data header.\n *\n * Count - Number of entries contained in this mix file.\n * Size  - Size of Mix file.\n */\ntypedef struct _MIXHeader {\n\tshort Count;\n\tlong  Size;\n} MIXHeader;\n\n/* MIXSubBlock: Mix file entry descriptor.\n *\n * CRC    - Unique entry identifier.\n * Offset - Offset from beginning of data segment to entry.\n * Size   - Size of entry.\n */\ntypedef struct _MIXSubBlock {\n\tlong CRC;\n\tlong Offset;\n\tlong Size;\n} MIXSubBlock;\n\n/* MIXHandle: Mix file handle.\n *\n * Name    - Pointer to the name of the mix file this handle is for.\n * Size    - Size of entire mix file.\n * FH      - DOS file handle of opened entry.\n * Count   - Number of files contained in this mix.\n * Entries - Array of 'Count' MIXSubBlock structure entries.\n */\ntypedef struct _MIXHandle {\n\tchar        *Name;\n\tlong        Size;\n\tlong        FH;\n\tlong        Count;\n\tMIXSubBlock Entries[];\n} MIXHandle;\n\n/*---------------------------------------------------------------------------\n * PROTOTYPES\n *-------------------------------------------------------------------------*/\n\nMIXHandle *OpenMix(char *name);\nvoid CloseMix(MIXHandle *mix);\nlong OpenMixEntry(MIXHandle *mix, char *name);\n\n/* Restore original alignment */\n#ifdef __WATCOMC__\n#pragma pack();\n#endif\n\n#endif /* VQMMIXFILE_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/MONO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMMONO_H\n#define VQMMONO_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     mono.h\n*\n* DESCRIPTION\n*     Mono screen definitions. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Feburary 8, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid cdecl Mono_Enable(void);\nvoid cdecl Mono_Disable(void);\nvoid cdecl Mono_Set_Cursor(long x, long y);\nvoid cdecl Mono_Clear_Screen(void);\nvoid cdecl Mono_Scroll(long lines);\nvoid cdecl Mono_Put_Char(long character, long attrib);\nvoid cdecl Mono_Draw_Rect(long x, long y, long w, long h, long attrib,\n\t\tlong thick);\n\nvoid cdecl Mono_Text_Print(void const *text, long x, long y, long attrib);\nvoid cdecl Mono_Print(void const *text);\nshort cdecl Mono_View_Page(long page);\nshort cdecl Mono_X(void);\t  \nshort cdecl Mono_Y(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMMONO_H */\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/PALETTE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMPALETTE_H\n#define VQMPALETTE_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Palette.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     Palette definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid cdecl SetPalette(unsigned char *palette,long numbytes,unsigned long slowpal);\nvoid cdecl ReadPalette(void *palette);\nvoid cdecl SetDAC(long color, long red, long green, long blue);\nvoid cdecl TranslatePalette(void *pal24, void *pal15, long numbytes);\n\n#ifdef __cplusplus\n}\n#endif\n\nvoid SortPalette(unsigned char *pal, long numcolors);\n\n#endif /* VQMPALETTE_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/PORTIO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMPORTIO_H\n#define VQMPORTIO_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Portio.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     Hardware port I/O\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n#ifdef __BORLANDC__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nshort cdecl inp(unsigned short portid);\nvoid cdecl outp(unsigned short portid, short value);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* __BORLANDC__ */\n\n#endif /* VQMPORTIO_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/PROFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMPROFILE_H\n#define VQMPROFILE_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Profile.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     INI file profiling definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\nlong GetINIInt(char const *section, char const *entry,\n\t\tlong deflt, char *fname);\n\nlong GetINIString(char const *section, char const *entry, \n\t\tchar const *def, char *retbuffer, long retlen, char *fname);\n\nlong Get_Frame_Pathname(char *inifile,long anim_frame,char *ext,\n\t\tchar *outbuf);\n\n#endif /* VQMPROFILE_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/REALMODE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMREALMODE_H\n#define VQMREALMODE_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     realmode.h\n*\n* DESCRIPTION\n*     Real-mode interfacing definitions and equates. Many of the definitions\n*     and descriptions in this file were taken from other sources and\n*     compiled here for use in MISC32 library.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 6, 1995\n*\n****************************************************************************/\n\n/* REALPTR: Real-mode pointer (segment:offset16).\n *\n * The REALPTR data type is used in protected mode to hold real-mode\n * pointers. The type is an unsigned long value, were the upper 16 bits\n * are the segment number and the lower 16 bit are an offset. This type\n * and the associated macros are identical to that of the PHARLAP \"pltypes.h\"\n * definitions for easy of conversion to WATCOM/4GW.\n */\ntypedef unsigned long REALPTR;\n\n#define RP_OFF(rp) ((unsigned short)(((unsigned long)(rp)) & 0xFFFF))\n#define RP_SEG(rp) ((unsigned short)(((unsigned long)(rp)) >> 16))\n#define RP_SET(rp, off, seg) (rp = ((unsigned long)(seg) << 16) + (off))\n#define RP_INCR(rp, incr) (rp += ((unsigned long)(incr)) & 0xFFFF)\n\n#define MK_PTR(off, seg) (void *)((((unsigned long)seg&0xFFFF)<<4)+off)\n\n/* RMInfo: Real-mode interrupt call structure.\n *\n * Information that needs to be passed down to the real-mode interrupt is\n * transfered using this structure. The address to this protected-mode\n * structure (allocated by user) is passed into DPMI function 0x300. DOS/4GW\n * will then use this information to set up the real-mode registers, switch\n * to real-mode and then execute the interrupt in real-mode.\n */\ntypedef struct _RMInfo {\n\tlong  edi;\n\tlong  esi;\n\tlong  ebp;\n\tlong  reservedbysystem;\n\tlong  ebx;\n\tlong  edx;\n\tlong  ecx;\n\tlong  eax;\n\tshort flags;\n\tshort es,ds,fs,gs,ip,cs,sp,ss;\n} RMInfo;\n\n#endif /* VQMREALMODE_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/SOSCOMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*  File              : soscomp.h\n*  Date Created      : 6/1/94\n*  Description       : \n*\n*  Programmer(s)     : Nick Skrepetos\n*  Last Modification : 10/1/94 - 11:37:9 AM\n*  Additional Notes  : Modified by Denzil E. Long, Jr.\n*\n*****************************************************************************\n*            Copyright (c) 1994,  HMI, Inc.  All Rights Reserved            *\n****************************************************************************/\n\n#ifndef  _SOS_COMPRESS\n#define  _SOS_COMPRESS\n\n/* compression types */\nenum {\n\t_ADPCM_TYPE_1,\n\t};\n\n/* define compression structure */\ntypedef struct _tagCOMPRESS_INFO {\n\tchar       *lpSource;\n\tchar       *lpDest;\n\tunsigned long dwCompSize;\n\tunsigned long dwUnCompSize;\n\tshort         wBitSize;\n\tshort\t\t\t    wChannels;\n\tunsigned long dwSampleIndex;\n\tlong          dwPredicted;\n\tlong          dwDifference;\n\tshort         wCodeBuf;\n\tshort         wCode;\n\tshort         wStep;\n\tshort         wIndex;\n\n\tunsigned long dwSampleIndex2; //added BP for channel 2\n\tlong          dwPredicted2;   //added BP for channel 2\n\tlong          dwDifference2; \t//added BP for channel 2\n\tshort         wCodeBuf2; \t\t//added BP for channel 2\n\tshort         wCode2; \t\t\t//added BP for channel 2\n\tshort         wStep2; \t\t\t//added BP for channel 2\n\tshort         wIndex2; \t\t\t//added BP for channel 2\n\t} _SOS_COMPRESS_INFO;\n\n/* compressed file type header */\ntypedef struct _tagCOMPRESS_HEADER {\n\tunsigned long dwType;              // type of compression\n\tunsigned long dwCompressedSize;    // compressed file size\n\tunsigned long dwUnCompressedSize;  // uncompressed file size\n\tunsigned long dwSourceBitSize;     // original bit size\n\tchar          szName[16];          // file type, for error checking\n\t} _SOS_COMPRESS_HEADER;\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid cdecl sosCODECInitStream(_SOS_COMPRESS_INFO *);\nunsigned long cdecl sosCODECCompressData(_SOS_COMPRESS_INFO *,unsigned long);\nunsigned long cdecl sosCODECDecompressData(_SOS_COMPRESS_INFO *,unsigned long);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/TARGA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMTARGA_H\n#define VQMTARGA_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Targa.h (32-Bit protected mode)\n* \n* DESCRIPTION\n*     Targa Image File definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/*---------------------------------------------------------------------------\n * Targa Header definitions\n *-------------------------------------------------------------------------*/\n\n/* TGAHeader - Targa Image File header.\n *\n * IDLength        - Size of Image ID field\n * ColorMapType    - Color map type.\n * ImageType       - Image type code.\n * CMapStart       - Color map origin.\n * CMapLength      - Color map length.\n * CMapDepth       - Depth of color map entries.\n * XOffset         - X origin of image.\n * YOffset         - Y origin of image.\n * Width           - Width of image.\n * Height          - Height of image.\n * PixelDepth      - Image pixel size\n * ImageDescriptor - Image descriptor byte.\n */\ntypedef struct _TGAHeader {\n\tchar  IDLength;\n\tchar  ColorMapType;\n\tchar  ImageType;\n\tshort CMapStart;\n\tshort CMapLength;\n\tchar  CMapDepth;\n\tshort XOffset;\n\tshort YOffset;\n\tshort Width;\n\tshort Height;\n\tchar  PixelDepth;\n\tchar  ImageDescriptor;\n} TGAHeader;\n\n/* ImageType definiton */\n#define TGA_NOIMAGE           0  /* No image data included in file */\n#define TGA_CMAPPED           1  /* Color-mapped image data */\n#define TGA_TRUECOLOR         2  /* Truecolor image data */\n#define TGA_MONO              3  /* Monochrome image data */\n#define TGA_CMAPPED_ENCODED   9  /* Color-mapped image data (Encoded) */\n#define TGA_TRUECOLOR_ENCODED 10 /* Truecolor image data (Encoded) */\n#define TGA_MONO_ENCODED      11 /* Monochrome image data (Encoded) */\n\n/* ImageDescriptor definition */\n#define TGAF_ATTRIB_BITS (0x0F<<0) /* Number of attribute bits per pixel */\n#define TGAF_XORIGIN     (1<<4)\n#define TGAF_YORIGIN     (1<<5)\n\n/*---------------------------------------------------------------------------\n * Targa Handle definitions\n *-------------------------------------------------------------------------*/\n\n/* TGAHandle - Targa Image File handle.\n *\n * fh     - File handle returned by open().\n * mode   - Access mode.\n * header - TGAHeader structure.\n */\ntypedef struct _TGAHandle {\n\tshort          fh;\n\tunsigned short mode;\n\tTGAHeader      header;\n} TGAHandle;\n\n/* Access modes. */\n#define TGA_READMODE  0\n#define TGA_WRITEMODE 1\n#define TGA_RDWRMODE  2\n\n/* Error codes */\n#define TGAERR_OPEN         -1\n#define TGAERR_READ         -2\n#define TGAERR_WRITE        -3\n#define TGAERR_SYNTAX       -4\n#define TGAERR_NOMEM        -5\n#define TGAERR_NOTSUPPORTED -6\n \n/*---------------------------------------------------------------------------\n * Function prototypes\n *-------------------------------------------------------------------------*/\n\nTGAHandle *OpenTarga(char *, unsigned short);\nvoid CloseTarga(TGAHandle *);\nlong LoadTarga(char *, char *, char *);\nlong SaveTarga(char *, TGAHeader *, char *, char *);\nvoid XFlipTarga(TGAHeader *, char *);\nvoid YFlipTarga(TGAHeader *, char *);\n\n#endif /* VQMTARGA_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/TEXT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMTEXT_H\n#define VQMTEXT_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     text.h\n*\n* DESCRIPTION\n*     Text printing definitions. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     March 13, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nlong cdecl Text_Print(char *string, long x, long y, long fcol, long bcol);\nvoid cdecl Draw_Char(long character, long x, long y);\nvoid cdecl Set_Font_Palette_Range(void *palette, long start, long end);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMTEXT_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/VESABLIT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMVESABLIT_H\n#define VQMVESABLIT_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     VESABlit.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     VESA bitblit routines.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\video.h>\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\nvoid VESA_Blit_640x480(DisplayInfo *disp,unsigned char *buf,long x1,\n\t\tlong y1,long width,long height);\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid cdecl Blit_VESA640x480(DisplayInfo *disp,unsigned char *buf,long x1,\n\t\tlong y1,long width,long height);\n\nvoid cdecl Buf_320x200_To_VESA_320x200(unsigned char *buffer, long grain);\nvoid cdecl Buf_320x200_To_VESA_640x400(unsigned char *buffer, long grain);\nvoid cdecl Buf_320x200_To_VESA_32K(unsigned char *buffer,\n\t\tunsigned char *palette, long grain);\n\nvoid cdecl Copy_Row(char *, char *, long);\nvoid cdecl Copy_Word_Row(char *source, char *dest, char *palette,\n\t\tlong numbytes);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMVESABLIT_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/VESAVID.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMVESAVID_H\n#define VQMVESAVID_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     VESAVid.h (32-Bit protected mode)\n* \n* DESCRIPTION\n*     VESA video manager definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n#ifndef __WATCOMC__\n#include <pharlap.h>\n#else\n#include \"realmode.h\"\n#endif\n\n/*---------------------------------------------------------------------------\n * VESA Video Modes\n *-------------------------------------------------------------------------*/\n\n#define\tVESA_640X400_256   0x100\n#define\tVESA_640X480_256   0x101\n#define\tVESA_800X600_16    0x102\n#define\tVESA_800X600_256   0x103\n#define\tVESA_1024X768_16   0x104\n#define\tVESA_1024X768_256  0x105\n#define\tVESA_1280X400_16   0x106\n#define\tVESA_1280X400_256  0x107\n#define\tVESA_TEXT_80X60    0x108\n#define\tVESA_TEXT_132X25   0x109\n#define\tVESA_TEXT_132X60   0x10C\n#define\tVESA_320X200_32K_1 0x10D\n#define\tVESA_320X200_32K_2 0x10E\n#define\tVESA_640X480_32K   0x110\n#define\tVESA_640X480_65K   0x111\n#define\tVESA_640X480_16M   0x112\n#define\tVESA_800X600_32K   0x113\n#define\tVESA_800X600_65K   0x114\n#define\tVESA_1024X768_32K  0x116\n#define\tVESA_1024X768_65K  0x117\n\n#define\tVESA_MIN VESA_640X400_256\n#define\tVESA_MAX VESA_1024X768_65K\n\n/*---------------------------------------------------------------------------\n * Structure definitions\n *-------------------------------------------------------------------------*/\n\n/* VESAInfo - General information about this VESA implementation.\n *            (Filled in by VESA BIOS Function 0)\n *\n * Signature    - Will always be 'VESA'\n * Version      - Version #\n * OEMString    - OEM ID string\n * Capabilities - Not defined by VESA yet\n * AvailModes   - List of available modes; terminated with -1 (0xffff)\n * TotalMemory  - ???\n * Reserved     - Pads structure to 256 bytes total\n */\ntypedef struct _VESAInfo {\n\tchar           Signature[4];\n\tunsigned short Version;\n\tREALPTR        OEMString;\n\tunsigned long  Capabilities;\n\tREALPTR        AvailModes;\n\tunsigned short TotalMemory;\n\tunsigned char  Reserved[236];\n} VESAInfo;\n\n/* VESAModeInfo - Information about this VESA mode.\n *                (Filled in by VESA BIOS Function 1)\n *\n * Attributes       - bit 0: 1 = mode is supported\n *                    bit 1: 1 = optional info available\n *                    bit 2: 1 = std BIOS output functions valid in this mode\n *                    bit 3: 0 = monochrome, 1 = color\n *                    bit 4: 0 = text mode, 1 = graphics\n * WinA_Attributes  - bit 0 = window exists, bit 1=readable, bit 2= writable\n * WinB_Attributes  - bit 0 = window exists, bit 1=readable, bit 2= writable\n * WinGranularity   - smallest address boundary window can be placed upon;\n *                    size is in KB (ie 64, 32, 4)\n * WinSize          - size of windows in KB (ie 64, 32)\n * WinA_Segment     - location of Window A in CPU space (usually 0xa000)\n * WinB_Segment     - location of Window B in CPU space (usually 0xb000)\n * WinFunc          - address of window-setting function (This is provided \n *                    as an alternative to Int 10 for speed.)\n * BytesPerScanline - # bytes per scan line\n * \n * Optional info (available if bit 1 of Attributes is set):\n *\n * XRes             - X-resolution\n * YRes             - Y-resolution\n * XCharSize        - Horizontal size of char cell\n * YCharSize        - Vertical size of char cell\n * NumPlanes        - # of memory planes (???)\n * BitsPerPixel     - # bites per pixel\n * NumBanks         - # of banks (ie planes)\n * MemoryModel      - 00h = Text mode\n *                    01h = CGA mode\n *                    02h = Hercules\n *                    03h = 4 plane planar mode\n *                    04h = packed pixel mode (1 byte/pixel)\n *                    05h = non-chain 4, 256-color mode\n *                    06-0Fh = \n *                    10-FFh = OEM-specific\n * BankSize         - Bank size in KB\n */\ntypedef struct _VESAModeInfo {\n\tunsigned short Attributes;\n\tunsigned char  WinA_Attributes;\n\tunsigned char  WinB_Attributes;\n\tunsigned short WinGranularity;\n\tunsigned short WinSize;\n\tunsigned short WinA_Segment;\n\tunsigned short WinB_Segment;\n\tREALPTR        WinFunc;\n\tunsigned short BytesPerScanline;\n\tunsigned short XRes;\n\tunsigned short YRes;\n\tunsigned char  XCharSize;\n\tunsigned char  YCharSize;\n\tunsigned char  NumPlanes;\n\tunsigned char  BitsPerPixel;\n\tunsigned char  NumBanks;\n\tunsigned char  MemoryModel;\n\tunsigned char  BankSize;\n\tunsigned char  NumInputPages;\n\tunsigned char  Reserved;\n\tunsigned char  RedMaskSize;\n\tunsigned char  RedFieldPosition;\n\tunsigned char  GreenMaskSize;\n\tunsigned char  GreenFieldPosition;\n\tunsigned char  BlueMaskSize; \n\tunsigned char  BlueFieldPosition;\n\tunsigned char  RsvdMaskSize;\n\tunsigned char  RsvdFieldPosition;\n\tunsigned char  DirectColorModeInfo;\n\tunsigned char  pad[216];\n} VESAModeInfo;\n\n/*---------------------------------------------------------------------------\n * Function prototypes\n *-------------------------------------------------------------------------*/\n\nlong InitVESA(void);\nvoid UninitVESA(void);\nVESAModeInfo *SetVESAMode(long mode);\nVESAModeInfo *ReadVESAModeInfo(long mode);\nvoid SetVESAWindow(long grain_num);\n\n#endif /* VQMVESAVID_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/VESAVID.I",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*       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\n;*\n;*----------------------------------------------------------------------------\n;*\n;* FILE\n;*     vesavid.i\n;*\n;* DESCRIPTION\n;*     VESA video manager definitions. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;****************************************************************************\n\n;----------------------------------------------------------------------------\n; VESA video modes\n;----------------------------------------------------------------------------\n\nVESA_640X400_256   EQU\t0x100\nVESA_640X480_256   EQU\t0x101\nVESA_800X600_16    EQU\t0x102\nVESA_800X600_256   EQU\t0x103\nVESA_1024X768_16   EQU\t0x104\nVESA_1024X768_256  EQU\t0x105\nVESA_1280X400_16   EQU\t0x106\nVESA_1280X400_256  EQU\t0x107\nVESA_TEXT_80X60    EQU\t0x108\nVESA_TEXT_132X25   EQU\t0x109\nVESA_TEXT_132X60   EQU\t0x10C\nVESA_320X200_32K_1 EQU\t0x10D\nVESA_320X200_32K_2 EQU\t0x10E\nVESA_640X480_32K   EQU\t0x110\nVESA_640X480_65K   EQU\t0x111\nVESA_640X480_16M   EQU\t0x112\nVESA_800X600_32K   EQU\t0x113\nVESA_800X600_65K   EQU\t0x114\nVESA_1024X768_32K  EQU\t0x116\nVESA_1024X768_65K  EQU\t0x117\n\nVESA_MIN EQU\tVESA_640X400_256\nVESA_MAX EQU\tVESA_1024X768_65K\n\n;----------------------------------------------------------------------------\n; Structure definitions\n;----------------------------------------------------------------------------\n\n; VESAInfo - General information about this VESA implementation.\n;            (Filled in by VESA BIOS Function 0)\n;\n; Signature    - Will always be 'VESA'\n; Ver          - Version #\n; OEMString    - OEM ID string\n; Capabilities - Not defined by VESA yet\n; AvailModes   - List of available modes; terminated with -1 (0xffff)\n; TotalMemory  - ???\n; Reserved     - Pads structure to 256 bytes total\n\n\tSTRUC\tVESAInfo\nSignature\tDD\t?\nVer\tDW\t?\nOEMString\tDD\t?\nCapabilities\tDD\t?\nAvailModes\tDD\t?\nTotalMemory\tDW\t?\nReserved\tDB\t236 DUP (?)\n\tENDS\tVESAInfo\n\n; VESAModeInfo - Information about this VESA mode.\n;                (Filled in by VESA BIOS Function 1)\n;\n; Attributes       - bit 0: 1 = mode is supported\n;                    bit 1: 1 = optional info available\n;                    bit 2: 1 = std BIOS output functions valid in this mode\n;                    bit 3: 0 = monochrome, 1 = color\n;                    bit 4: 0 = text mode, 1 = graphics\n; WinA_Attributes  - bit 0 = window exists, bit 1=readable, bit 2= writable\n; WinB_Attributes  - bit 0 = window exists, bit 1=readable, bit 2= writable\n; WinGranularity   - smallest address boundary window can be placed upon;\n;                    size is in KB (ie 64, 32, 4)\n; WinSize          - size of windows in KB (ie 64, 32)\n; WinA_Segment     - location of Window A in CPU space (usually 0xa000)\n; WinB_Segment     - location of Window B in CPU space (usually 0xb000)\n; WinFunc          - address of window-setting function (This is provided \n;                    as an alternative to Int 10 for speed.)\n; BytesPerScanline - # bytes per scan line\n; \n; Optional info (available if bit 1 of Attributes is set):\n;\n; XRes             - X-resolution\n; YRes             - Y-resolution\n; XCharSize        - Horizontal size of char cell\n; YCharSize        - Vertical size of char cell\n; NumPlanes        - # of memory planes (???)\n; BitsPerPixel     - # bites per pixel\n; NumBanks         - # of banks (ie planes)\n; MemoryModel      - 00h = Text mode\n;                    01h = CGA mode\n;                    02h = Hercules\n;                    03h = 4 plane planar mode\n;                    04h = packed pixel mode (1 byte/pixel)\n;                    05h = non-chain 4, 256-color mode\n;                    06-0Fh = \n;                    10-FFh = OEM-specific\n; BankSize         - Bank size in KB\n\n\t\tSTRUC\tVESAModeInfo \nAttributes\t\tDW\t?\nWinA_Attributes\tDB\t?\nWinB_Attributes\tDB\t?\nWinGranularity\tDW\t?\nWinSize\t\tDW\t?\nWinA_Segment\t\tDW\t?\nWinB_Segment\t\tDW\t?\nWinFunc\t\tDD\t?\nBytesPerScanline\tDW\t?\nXRes\t\tDW\t?\nYRes\t\tDW\t?\nXCharSize\t\tDB\t?\nYCharSize\t\tDB\t?\nNumPlanes\t\tDB\t?\nBitsPerPixel\t\tDB\t?\nNumBanks\t\tDB\t?\nMemoryModel\t\tDB\t?\nBankSize\t\tDB\t?\nNumInputPages\t\tDB\t?\nReserved\t\tDB\t?\nRedMaskSize\t\tDB\t?\nRedFieldPosition\tDB\t?\nGreenMaskSize\t\tDB\t?\nGreenFieldPosition\tDB\t?\nBlueMaskSize\t\tDB\t?\nBlueFieldPosition\tDB\t?\nRsvdMaskSize\t\tDB\t?\nRsvdFieldPosition\tDB\t?\nDirectColorModeInfo\tDB\t?\npad\t\tDB\t216 DUP (?)\n\t\tENDS\tVESAModeInfo\n\n;----------------------------------------------------------------------------\n; Function definitions\n;----------------------------------------------------------------------------\n\n\tGLOBAL C InitVESA:PROC\n\tGLOBAL C UninitVESA:PROC\n\tGLOBAL C SetVESAMode:PROC\n\tGLOBAL C ReadVESAModeInfo:PROC\n\tGLOBAL C SetVESAWindow:PROC\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     SET_WINDOW - Sets window A to the specified bank.\n;\n; SYNOPSIS\n;     SET_WINDOW GrainNum\n;\n; FUNCTION\n;     This routine uses the C Set_Window function rather than going through\n;     the BIOS, for two reasons: (1) Speed, and (2) On the Cirrus Logic 54xx\n;     VESA cards, BIOS calls make noise while playing digital audio.\n;\n; INPUTS\n;     GrainNum - Granularity number.\n;\n; RESULT\n;     NONE\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tSET_WINDOW grain_num\n\tpush\tesi\n\tpush\tedi\n\tpush\tes\n\tcall\tSetVESAWindow C,grain_num\n\tpop\tes\n\tpop\tedi\n\tpop\tesi\n\tENDM\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/VGA.I",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     vga.i\n;*\n;* DESCRIPTION\n;*     VGA hardware definitions. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;****************************************************************************\n\n;----------------------------------------------------------------------------\n; VGA Registers\n;----------------------------------------------------------------------------\n\nR_SEQUENCER\t\tEQU\t03C4h\t;Sequencer Controller Index reg\nSEQ_RESET\t\tEQU\t00h\t;Reset\nSEQ_MAP_MASK\t\tEQU\t02h\t;Index in Sequencer of Map Mask reg\nSEQ_MEMORY_MODE\tEQU\t04h\t;Memory Mode\n\nR_GRAPHICS_CONTROLLER\tEQU\t03CEh\t;Graphics Controller Index reg\nGC_READ_MAP\t\tEQU\t04h\t;Index in GController of Read Map reg\nGC_MODE\t\tEQU\t05h\t;Read/Write Modes\nGC_MISC\t\tEQU\t06h\t;Read/Write Modes\nGC_BITMASK\t\tEQU\t08h\t;Index in GController of BitMask reg\n\nR_CRT_CONTROLLER\tEQU\t03D4h\t;CRT Controller Index reg\nCRT_VERT_TOTAL\tEQU\t06h\t;Vertical total\nCRT_OVERFLOW\t\tEQU\t07h\t;Overflow\nCRT_MAX_SCANLINE\tEQU\t09h\t;Max scan line\nCRT_STARTADDR_HIGH\tEQU\t0Ch\t;Bitmap start address high byte\nCRT_STARTADDR_LOW\tEQU\t0Dh\t;Bitmap start address low byte\nCRT_VERTRET_START\tEQU\t010h\t;Vertical retrace pulse start\nCRT_VERTRET_END\tEQU\t011h\t;Vertical retrace pulse end\nCRT_VERTDISP_END\tEQU\t012h\t;Vertical display end\nCRT_UNDERLINE\t\tEQU\t014h\t;Underline location\nCRT_START_VB\t\tEQU\t015h\t;Start vertical blank\nCRT_END_VB\t\tEQU\t016h\t;End vertical blank\nCRT_MODE_CONTROL\tEQU\t017h\t;Mode control\nR_MISC_OUTPUT\t\tEQU\t03C2h\t;Miscellaneous Output reg\n\n;----------------------------------------------------------------------------\n; Palette Registers\n;----------------------------------------------------------------------------\n\nPEL_READ_ADDR\t\tEQU\t03C7h\nPEL_WRITE_ADDR\tEQU\t03C8h\nPEL_DATA\t\tEQU\t03C9h\n\n;----------------------------------------------------------------------------\n; XMode planes, for the Map Mask register\n;----------------------------------------------------------------------------\n\nXPLANE_1\tEQU\t1\nXPLANE_2\tEQU\t2\nXPLANE_3\tEQU\t4\nXPLANE_4\tEQU\t8\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     SET_PLANE - Set an XMode plane.\n;\n; SYNOPSIS\n;     SET_PLANE plane\n;\n; INPUTS\n;     plane - Number of Xmode plane to set.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tSET_PLANE plane\n\tmov\tedx,R_SEQUENCER\n\tmov\teax,SEQ_MAP_MASK\n\tout\tdx,al\n\tinc\tedx\n\tmov\teax,plane\n\tout\tdx,al\n\tENDM\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     SET_BITMASK - Set the BitMask register.\n;\n; SYNOPSIS\n;     SET_BITMASK mask\n;\n; INPUTS\n;     mask - Bitmask to use.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tSET_BITMASK mask\n\tmov\tedx,R_GRAPHICS_CONTROLLER\n\tmov\teax,GC_BITMASK\n\tout\tdx,al\n\tinc\tedx\n\tmov\teax,mask\n\tout\tdx,al\n\tENDM\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     SET_WRITEMODE - Set the VGA writemode.\n;\n; SYNOPSIS\n;     SET_WRITEMODE mode\n;\n; INPUTS\n;     mode - Write mode.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tSET_WRITEMODE mode\n\tmov\tedx,R_GRAPHICS_CONTROLLER\n\tmov\teax,GC_MODE\n\tout\tdx,al\n\tinc\tedx\n\tin\tal,dx\t;Read the register\n\tand\tal,0FCh\t;Turn off 2 lower bits\n\tor\tal,mode\t;Set write mode\n\tout\tdx,al\n\tENDM\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     OUTPORT - Output data to a VGA register.\n;\n; SYNOPSIS\n;     OUTPORT port,register,data\n;\n; INPUTS\n;     port     - Port address.\n;     register - Register to write to.\n;     data     - Data to write.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tOUTPORT port,register,data\n\tmov\tedx,port\n\tmov\tal,register\n\tout\tdx,al\n\tinc\tedx\n\tmov\tal,data\n\tout\tdx,al\n\tENDM\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     INPORT - Input data from a VGA register.\n;\n; SYNOPSIS\n;     data = INPORT port,register\n;\n; INPUTS\n;     port     - Port address.\n;     register - Register to read from.\n;\n; RESULT\n;     data - Value read from port in AL.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tINPORT port,register\n\tmov\tedx,port\n\tmov\tal,register\n\tout\tdx,al\n\tinc\tedx\n\tin\tal,dx\n\tENDM\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/VIDEO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMVIDEO_H\n#define VQMVIDEO_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Video.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     Video manager definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\vesavid.h>\n\n/*---------------------------------------------------------------------------\n * VGA video modes\n *-------------------------------------------------------------------------*/\n\n#define\tTEXT 0x02\n#define\tMCGA 0x13\n#define\tXMODE_320X200 0x50\n#define\tXMODE_320X240 0x51\n#define\tXMODE_320X400 0x52\n#define\tXMODE_320X480 0x53\n#define\tXMODE_360X400 0x54\n#define\tXMODE_360X480 0x55\n\n#define\tXMODE_MIN 0x50\n#define\tXMODE_MAX 0x55\n\n/*---------------------------------------------------------------------------\n * Structure definitions\n *-------------------------------------------------------------------------*/\n\n/* DisplayInfo - Information about the current display.\n *\n * Mode     - Mode identification.\n * XRes     - X resolution of mode.\n * YRes     - Y resolution of mode.\n * VBIbit   - Polarity of vertical blank bit.\n * Extended - Pointer to mode specific data structure.\n */\ntypedef struct _DisplayInfo {\n\tlong Mode;\n\tlong XRes;\n\tlong YRes;\n\tlong VBIbit;\n\tvoid *Extended;\n} DisplayInfo;\n\n/*---------------------------------------------------------------------------\n * Function prototypes\n *-------------------------------------------------------------------------*/\n\nDisplayInfo *SetVideoMode(long mode);\nDisplayInfo *GetDisplayInfo(void);\nlong TestVBIBit(void);\nlong GetVBIBit(void);\n\nvoid SetupXPaging(void);\nvoid FlipXPage(void);\nunsigned char *GetXHidPage(void);\nunsigned char *GetXSeenPage(void);\nvoid DisplayXPage(long page);\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid cdecl WaitNoVB(short vbibit);\nvoid cdecl WaitVB(short vbibit);\nvoid cdecl ClearVRAM(void);\nlong cdecl SetXMode(long mode);\nvoid cdecl ClearXMode(void);\nvoid cdecl ShowXPage(unsigned long StartOffset);\nvoid cdecl Xmode_BufferCopy_320x200(void *buff, void *screen);\nvoid cdecl Xmode_Blit(void *buffer, void *screen, long imgwidth, long imgheight);\nvoid cdecl MCGA_BufferCopy(unsigned char *buffer, unsigned char *dummy);\nvoid cdecl MCGA_Blit(unsigned char *buffer, unsigned char *screen,\n\t\tlong imgwidth, long imgheight);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMVIDEO_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/VQM32/VIDEO.I",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*       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\n;*\n;*----------------------------------------------------------------------------\n;*\n;* FILE\n;*     video.i\n;*\n;* DESCRIPTION\n;*     Video manager definitions. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;****************************************************************************\n\n\tINCLUDE\t\"vesavid.i\"\n\n;----------------------------------------------------------------------------\n; Video Modes\n;----------------------------------------------------------------------------\n\nTEXT\tEQU\t002h\nMCGA\tEQU\t013h\nXMODE_320X200\tEQU\t050h\nXMODE_320X240\tEQU\t051h\nXMODE_320X400\tEQU\t052h\nXMODE_320X480\tEQU\t053h\nXMODE_360X400\tEQU\t054h\nXMODE_360X480\tEQU\t055h\n\n;----------------------------------------------------------------------------\n; Structure definitions\n;----------------------------------------------------------------------------\n\n; DisplayInfo - Information about the current display.\n;\n; Mode     - Mode identification\n; XRes     - X resolution\n; YRes     - Y resolution\n; VBIbit   - Polarity of vertical blank bit.\n; Extended - Pointer to mode specified data structure.\n\n\tSTRUC\tDisplayInfo\nMode\tDD\t?\nXRes\tDD\t?\nYRes\tDD\t?\nVBIbit\tDD\t?\nExtended\tDD\t?\n\tENDS\tDisplayInfo\n\n;----------------------------------------------------------------------------\n; Function definitions\n;----------------------------------------------------------------------------\n\n\tGLOBAL C GetDisplayInfo:NEAR\n\tGLOBAL C GetVBIBit:NEAR\n\n"
  },
  {
    "path": "VQ/INCLUDE/WAVEFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef WAVEFILE_H\n#define WAVEFILE_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     wavefile.c\n*\n* DESCRIPTION\n*     WAVE file format definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*      \n* DATE\n*     February 21, 1995\n*\n****************************************************************************/\n\n/* WAVHeader: WAVE file header.\n *\n * RIFF - 4 byte identifier (always \"RIFF\").\n * Size - Size in bytes of entire file.\n * WAVE - 4 byte identifier (always \"WAVE\").\n */\ntypedef struct _WAVHeader {\n\tlong RIFF;\n\tlong Size;\n\tlong WAVE;\n} WAVHeader;\n\n/* WAVFormat: This structure describes the format of the audio data contained\n *            in the WAV file.\n *\n * FormatTag      - \n * Channels       - Number of channels (1 = mono, 2 = stereo).\n * SamplesPerSec  - Sampling rate.\n * AvgBytesPerSec - Bytes in 1 second of audio (Rate * SampleSize * Channels)\n * BlockAlign     - padding.\n * BitsPerSample  - Number of bits per sample (8, 16).\n */\ntypedef struct _WAVFormat {\n\tshort FormatTag;\n\tshort Channels;\n\tlong  SamplesPerSec;\n \tlong  AvgBytesPerSec;\n\tshort BlockAlign;\n\tshort BitsPerSample;\n} WAVFormat;\n\n#endif /* WAVEFILE_H */\n\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/AUDIO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : AUDIO.H                                  *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : March 10, 1995                           *\n *                                                                         *\n *                  Last Update : March 10, 1995   [PWG]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwstd.h\"\n\n/*=========================================================================*/\n/* AUD file header type\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tAUD_FLAG_STEREO\t1\n#define\tAUD_FLAG_16BIT\t\t2\n\n// PWG 3-14-95: This structure used to have bit fields defined for Stereo\n//   and Bits.  These were removed because watcom packs them into a 32 bit\n//   flag entry even though they could have fit in a 8 bit entry.\n#pragma pack(1);\ntypedef struct {\n\tshort int\tRate;\t\t\t\t// Playback rate (hertz).\n\tlong\tSize;\t\t\t\t// Size of data (bytes).\n\tunsigned char Flags;\t// Holds flags for info\n\t\t\t\t\t\t\t\t//  1: Is the sample stereo?\n\t\t\t\t\t\t\t\t//  2: Is the sample 16 bits?\n\tunsigned char Compression;\t// What kind of compression for this sample?\n} AUDHeaderType;\n\n\n/*=========================================================================*/\n/*\tThere can be a different sound driver for sound effects, digitized\t\t*/\n/*\tsamples, and musical scores.  Each one must be of these specified\t\t\t*/\n/*\ttypes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\ntypedef enum {\n\tSAMPLE_NONE,\t\t// No digitized sounds will be played.\n\tSAMPLE_SB,\t\t\t// Sound Blaster digitized driver.\n\tSAMPLE_SBPRO,\t\t// Sound Blaster Pro digitized driver.\n\tSAMPLE_PAS,\t\t\t// Pro-Audio Spectrum digitized driver.\n\tSAMPLE_ADLIBG,\t\t// Adlib-Gold digitized driver.\n\tSAMPLE_TANDY,\t\t// Tandy 'compatible' driver.\n\tSAMPLE_PCSPKR,\t\t// PC speaker digitized driver (The Audio Solution driver).\n\tSAMPLE_ADLIB,\t\t// Adlib digitized driver (The Audio Solution driver).\n\tSAMPLE_TEMP=0x1000,\n\tSAMPLE_LAST\n} Sample_Type;\n\ntypedef enum {\n\tSCORE_NONE,\t\t\t// No scores will be played.\n\tSCORE_ALFX,\t\t\t// Westwood's ALFX adlib compatable driver.\n\tSCORE_WWPCSPKR,\t// Westwood's PC-speaker driver (obsolete).\n\tSCORE_WWTANDY,\t\t// Westwood's PC-speaker driver with Tandy mod (obsolete).\n\tSCORE_PCSPKR,\t\t// PC speaker XMIDI driver.\n\tSCORE_TANDY,\t\t// Tandy XMIDI driver.\n\tSCORE_MT32,\t\t\t// MT-32 / LAPC-1 Roland XMIDI driver.\n\tSCORE_CANVAS,\t\t// Sound Canvas SC-55.\n\tSCORE_ADLIB,\t\t// Adlib XMIDI driver.\n\tSCORE_ADLIBG,\t\t// Adlib Gold XMIDI driver.\n\tSCORE_PASFM,\t\t// Pro Audio Spectrum XMIDI driver.\n\tSCORE_SBFM,\t\t\t// Sound Blaster XMIDI driver.\n\tSCORE_SBP1FM,\t\t// Sound Blaster Pro (YM3812) XMIDI driver.\n\tSCORE_SBP2FM,\t\t// Sound Blaster Pro (OPL3) XMIDI driver (Can't use with SFX_ALFX).\n\tSCORE_TEMP=0x1000,\n\tSCORE_LAST\n} Score_Type;\n\ntypedef enum {\n\tSFX_NONE,\t\t\t// No sound effects will be played.\n\tSFX_ALFX,\t\t\t// Westwood's ALFX adlib compatable driver.\n\tSFX_WWPCSPKR,\t\t// Westwood's PC-speaker driver.\n\tSFX_WWTANDY,\t\t// Westwood's PC-speaker driver with Tandy mod.\n\tSFX_PCSPKR,\t\t\t// PC speaker XMIDI driver.\n\tSFX_TANDY,\t\t\t// Tandy XMIDI driver.\n\tSFX_MT32,\t\t\t// MT-32 / LAPC-1 Roland XMIDI driver.\n\tSFX_CANVAS,\t\t\t// Sound Canvas SC-55.\n\tSFX_ADLIB,\t\t\t// Adlib XMIDI driver.\n\tSFX_ADLIBG,\t\t\t// Adlib Gold XMIDI driver.\n\tSFX_PASFM,\t\t\t// Pro Audio Spectrum XMIDI driver.\n\tSFX_SBFM,\t\t\t// Sound Blaster XMIDI driver.\n\tSFX_SBP1FM,\t\t\t// Sound Blaster Pro (YM3812) XMIDI driver.\n\tSFX_SBP2FM,\t\t\t// Sound Blaster Pro (OPL3) XMIDI driver.\n\tSFX_TEMP=0x1000,\n\tSFX_LAST\n} SFX_Type;\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SOUNDIO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nint File_Stream_Sample(char const *filename);\nint File_Stream_Sample_Vol(char const *filename, int volume);\nvoid cdecl _saveregs Sound_Callback(void);\nvoid cdecl far __saveregs __loadds maintenance_callback(void);\nvoid *Load_Sample(char const *filename);\nlong Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);\nlong Sample_Read(int fh, void *buffer, long size);\nvoid Free_Sample(void const *sample);\nBOOL Sound_Init(int sfx, int score, int sample, int reverse_channels = FALSE);\nBOOL Audio_Init(int sample, int address, int inter, int dma, int reverse_channels = FALSE);\nvoid Sound_End(void);\nvoid Stop_Sample(int handle);\nBOOL Sample_Status(int handle);\nBOOL Is_Sample_Playing(void const * sample);\nvoid Stop_Sample_Playing(void const * sample);\nint Play_Sample(void const *sample, int priority=0xFF, int volume=0xFF, signed short panloc = 0x0);\nint Set_Sound_Vol(int volume);\nint Set_Score_Vol(int volume);\nvoid Fade_Sample(int handle, int ticks);\n\nextern unsigned int DigiHandle;\nextern int Misc;\nextern SFX_Type SoundType;\nextern Sample_Type SampleType;\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/BUFFER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : GBUFFER.H                                *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 26, 1994                             *\n *                                                                         *\n *                  Last Update : July 5, 1994   [PWG]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   BC::Get_Size -- Returns the buffer size of the BufferClass instance   *\n *   BC::Get_Buffer -- Returns pointer to buffer inherent to BufferClass \t*\n *   BC::BufferClass -- inline constructor for BufferClass with size only  *\n *   BC::To_Page -- Copys a buffer class to a page with definable x, y, w, h*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BUFFER_H\n#define BUFFER_H\n\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\nclass GraphicViewPortClass;\nclass VideoViewPortClass;\n\n/*=========================================================================*/\n/* BufferClass - A base class which holds buffer information including a\t*/\n/*\t\tpointer and the size of the buffer.\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nclass BufferClass {\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBufferClass(void *ptr, long size);\n\t\tBufferClass(long size);\n\t\tBufferClass();\n\t\t~BufferClass();\n\t\t/*===================================================================*/\n\t\t/* Define functions which work with the buffer class.\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong To_Page(GraphicViewPortClass &view);\n\t\tlong To_Page(int w, int h, GraphicViewPortClass &view);\n\t\tlong To_Page(int x, int y, int w, int h, GraphicViewPortClass &view);\n\t\tlong To_Page(VideoViewPortClass &view);\n\t\tlong To_Page(int w, int h, VideoViewPortClass &view);\n\t\tlong To_Page(int x, int y, int w, int h, VideoViewPortClass &view);\n\n\t\t/*===================================================================*/\n\t\t/* define functions to get at the protected data members\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tvoid\t*Get_Buffer(void);\n\t\tlong\tGet_Size(void);\n\n\tprivate:\n\t\t/*===================================================================*/\n\t\t/* Define the operators we do not want to happen which are the copy\t*/\n\t\t/* and equal constructors.  These are bad because the Allocated flag\t*/\n\t\t/*\tcould be copied and the associated buffer freed.  If this were to\t*/\n\t\t/*\tgappen it could cause weird general protection fault.\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBufferClass(BufferClass const &);\n\t\tBufferClass &operator=(BufferClass const &);\n\n\tprotected:\n\t\tvoid\t*Buffer;\n\t\tlong\tSize;\n\t\tBOOL\tAllocated;\n};\n/***************************************************************************\n * BC::GET_SIZE -- Returns the buffer size of the BufferClass instance     *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long the size of the buffer                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::Get_Size(void)\n{\n\treturn(Size);\n}\n/***************************************************************************\n * BC::GET_BUFFER -- Returns pointer to buffer inherent to BufferClass \t\t*\n *                                                                         *\n * INPUT:\t\t\tnone                                                     *\n *                                                                         *\n * OUTPUT:        void * to the inherent buffer.                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline void *BufferClass::Get_Buffer(void)\n{\n\treturn(Buffer);\n}\n#endif\n\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/DESCMGMT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 library                          *\n *                                                                         *\n *                    File Name : DESCMGMT.H                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef DESCMGMT_H\n#define DESCMGMT_H\n\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n//=====================================================================\n// C type include files\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <dos.h>\n#include <bios.h>\n\n#ifdef __cplusplus\n}\n#endif\n\n// ====================================================================\n\n\n// types\n// These where taken from dos.h\n//==========================================\n\n// external functions\n// ===================================================\nextern ULONG Map_Segment_To_Address(ULONG address, ULONG length);\n\nextern \"C\" {\n\t// Assemble functions\n\textern UWORD FixSelector(UWORD sel);\n\textern UWORD GetDs(void);\n\textern UWORD GetCs(void);\n\textern VOID  GetDefaultSelectors(VOID);\n\textern UWORD Get_Standard_Selector(void);\n\n\t\n\t// Assembly data variables\n\textern UWORD CodeSelector;\n\textern UWORD DataSelector;\n\textern UWORD ScreenSelector;\n\textern UWORD GraphicsSelector;\n\textern UWORD PspSelector;\n\textern UWORD EnvSelector;\n\textern UWORD DosMemSelector;\n\textern UWORD Fp1167Selector;\n\textern UWORD FpWeitekSelector;\n\textern UWORD FpCyrixSelector;\n}\n\n#endif  // DESCMGMT_H\n\n\u001a\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/DIPTHONG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\nint Dip_Text(char const *source, char *dest);\nint UnDip_Text(char const *source, char *dest);\nchar *Extract_String(void const *data, int string);\nvoid Fixup_Text(char const *source, char *dest);\nextern char Common[];\nextern char Dipthong[16][8];\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/FILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library - Filio header stuff.            *\n *                                                                         *\n *                    File Name : FILE.H                                 \t*\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : September 13, 1993                       *\n *                                                                         *\n *                  Last Update : April 11, 1994\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FILE_H\n#define FILE_H\n\n#ifndef FILETEMP_H\n// This should be removed once the library is all intacked.\n#include \"filetemp.h\"\n#endif\n\n/*=========================================================================*/\n/* File IO system defines and enumerations\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#define\tXMAXPATH\t80\n\n/*\n**\tThese are the Open_File, Read_File, and Seek_File constants.\n*/\n#define READ\t\t\t\t\t\t1\t// Read access.\n#define WRITE\t\t\t\t\t\t2\t// Write access.\n#ifndef SEEK_SET\n#define SEEK_SET\t\t\t\t\t0\t// Seek from start of file.\n#define SEEK_CUR\t\t\t\t\t1\t// Seek relative from current location.\n#define SEEK_END\t\t\t\t\t2\t// Seek from end of file.\n#endif\n\n\ntypedef enum {\n\tFILEB_PROCESSED=8,// Was the packed file header of this file processed?\n\tFILEB_PRELOAD,\t\t// Scan for and make file resident at WWDOS_Init time?\n\tFILEB_RESIDENT,\t// Make resident at Open_File time?\n\tFILEB_FLUSH,\t\t// Un-resident at Close_File time?\n\tFILEB_PACKED,\t\t// Is this file packed?\n\tFILEB_KEEP,\t\t\t// Don't ever flush this resident file?\n\tFILEB_PRIORITY,\t// Flush this file last?\n\n\tFILEB_LAST\n} FileFlags_Type;\n\n#define\tFILEF_NONE\t\t\t0\n#define\tFILEF_PROCESSED\t(1<<FILEB_PROCESSED)\n#define\tFILEF_PRELOAD\t\t(1<<FILEB_PRELOAD)\n#define\tFILEF_RESIDENT\t\t(1<<FILEB_RESIDENT)\n#define\tFILEF_FLUSH\t\t\t(1<<FILEB_FLUSH)\n#define\tFILEF_PACKED\t\t(1<<FILEB_PACKED)\n#define\tFILEF_KEEP\t\t\t(1<<FILEB_KEEP)\n#define\tFILEF_PRIORITY\t\t(1<<FILEB_PRIORITY)\n\n/*\n** These errors are returned by WWDOS_Init().  All errors encountered are\n** or'd together so there may be more then one error returned.  Not all\n** errors are fatal, such as the cache errors.\n*/\ntypedef enum {\n\tFI_SUCCESS\t\t\t\t\t\t= 0x00,\n\tFI_CACHE_TOO_BIG\t\t\t\t= 0x01,\n\tFI_CACHE_ALREADY_INIT\t\t= 0x02,\n\tFI_FILEDATA_FILE_NOT_FOUND\t= 0x04,\n\tFI_FILEDATA_TOO_BIG\t\t\t= 0x08,\n \tFI_SEARCH_PATH_NOT_FOUND\t= 0x10,\n \tFI_STARTUP_PATH_NOT_FOUND\t= 0x20,\n\tFI_NO_CACHE_FOR_PRELOAD\t\t= 0x40,\n\tFI_FILETABLE_NOT_INIT\t\t= 0x80,\n} FileInitErrorType;\n\n\n/*\n**\tThese are the errors that are detected by the File I/O system and\n**\tpassed to the io error routine.\n*/\n//lint -strong(AJX,FileErrorType)\ntypedef enum {\n\tCANT_CREATE_FILE,\n\tBAD_OPEN_MODE,\n\tCOULD_NOT_OPEN,\n\tTOO_MANY_FILES,\n\tCLOSING_NON_HANDLE,\n\tREADING_NON_HANDLE,\n\tWRITING_NON_HANDLE,\n\tSEEKING_NON_HANDLE,\n\tSEEKING_BAD_OFFSET,\n\tWRITING_RESIDENT,\n\tUNKNOWN_INDEX,\n\tDID_NOT_CLOSE,\n\tFATAL_ERROR,\n\tFILE_NOT_LISTED,\n\tFILE_LENGTH_MISMATCH,\n\tINTERNAL_ERROR,\n\tMAKE_RESIDENT_ZERO_SIZE,\n\tRESIDENT_SORT_FAILURE,\n\n\tNUMBER_OF_ERRORS\t\t\t\t/* MAKE SURE THIS IS THE LAST ENTRY */\n} FileErrorType;\n\n// This is here tempararaly until library is put together.\n//extern WORD cdecl (*cdecl IO_Error)(FileErrorType error, BYTE const *filename);\nextern short (*Open_Error)(FileErrorType, BYTE const *);\n\n/*=========================================================================*/\n/* File IO system structures\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//lint -strong(AJX,FileDataType)\ntypedef struct {\n\tchar\t*Name;\t\t// File name (include sub-directory but not volume).\n\tlong\tSize;\t\t\t// File size (0=indeterminate).\n\tvoid\t*Ptr;\t\t\t// Resident file pointer.\n\tlong\tStart;\t\t// Starting offset in DOS handle file.\n\tunsigned char\tDisk;\t\t\t// Disk number location.\n\tunsigned char\tOpenCount;\t// Count of open locks on resident file.\n\tunsigned short\tFlag;\t\t\t// File control flags.\n} FileDataType;\n\n\n/*=========================================================================*/\n/* FIle IO system globals.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n// These are cpp errors in funtions declarations\tJULIO JEREZ\n\n// extern FileDataType cdecl FileData[];\n// extern BYTE cdecl ExecPath[XMAXPATH + 1];\n// extern BYTE cdecl DataPath[XMAXPATH + 1];\n// extern BYTE cdecl StartPath[XMAXPATH + 1];\n// extern BOOL cdecl UseCD;\n\n// The correct syntax is  NO TYPE MODIFIER APPLY TO DATA DECLARATIONS\nextern FileDataType FileData[];\nextern char ExecPath[XMAXPATH + 1];\nextern char DataPath[XMAXPATH + 1];\nextern char StartPath[XMAXPATH + 1];\nextern BOOL UseCD;\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILEINIT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid cdecl WWDOS_Shutdown(void);\nFileInitErrorType cdecl WWDOS_Init(unsigned long cachesize, char *filedata, char *cdpath);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILE.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort cdecl Open_File(char const *file_name, short mode);\nvoid cdecl Close_File(short handle);\nLONG cdecl Read_File(short handle, void *buf, unsigned long bytes);\nLONG cdecl Write_File(short handle, void const *buf, unsigned long bytes);\nunsigned long cdecl Seek_File(short handle, LONG offset, short starting);\nshort cdecl File_Exists(char const *file_name);\nunsigned long cdecl File_Size(short handle);\nBOOL cdecl Is_Handle_Valid(short handle, FileErrorType error, char const *name);\nshort cdecl Open_File_With_Recovery( char const *file_name, unsigned short mode );\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILECACH.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid Unfragment_File_Cache(void);\nBOOL cdecl Make_File_Resident(char const *filename);\nshort cdecl Flush_Unused_File_Cache(short flush_keeps);\nBOOL cdecl Free_Resident_File(char const *file);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILECHNG.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort cdecl Create_File(char const *file_name);\nshort cdecl Delete_File(char const *file_name);\nBOOL cdecl Change_File_Size(short handle, unsigned long new_size);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILEINFO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort cdecl Get_DOS_Handle(short fh);\nshort cdecl Free_Handles(void);\nshort cdecl Find_Disk_Number(char const *file_name);\nshort cdecl Set_File_Flags(char const *filename, short flags);\nshort cdecl Clear_File_Flags(char const *filename, short flags);\nshort cdecl Get_File_Flags(char const *filename);\nBOOL cdecl Multi_Drive_Search(BOOL on);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FINDFILE.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort cdecl Find_File(char const *file_name);\nshort cdecl Find_File_Index(char const *filename);\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FFIRST.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#include <dos.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern short Find_First(unsigned char *fname, unsigned short mode, struct find_t *ffblk);\nextern short Find_Next(struct find_t *ffblk);\n\n#ifdef __cplusplus\n}\n#endif\n\n\n\n\n#endif // FILE_H\n\u001a\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/FILETEMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Temp header for file routines.           *\n *                                                                         *\n *                    File Name : FILETEMP.H                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 20, 1994                           *\n *                                                                         *\n *                  Last Update : April 20, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FILETEMP_H\n#define FILETEMP_H\n\n/////////////////////////////////////////////////////////////////////\n// THIS DOES NOT BELONG HERE.  IT WAS PUT HERE JUST TO GET THE THING\n// TO COMPILE.  ONCE THE BUFFER AND PAGE SYSTEMS ARE PUT IN, THESE\n// WILL NEED TO BE TAKEN OUT AND MODS MADE TO ANY FUNCTION USING BuffType.\n// SKB 4/20/94.\n\n\n\n/*=========================================================================*/\n/* Defines and such that must go into wwstd.h\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n// Look at FileErrorType below for the IO_Error function.\n//extern WORD cdecl (*cdecl IO_Error)(FileErrorType error, BYTE const *filename);\nVOID cdecl Prog_End(VOID);\nextern WORD Hard_Error_Occured;\n\n\n\n//////////////////////// END OF DON'T BELONG //////////////////////////////////\n\n#endif //FILETEMP_H\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/FONT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Font and text print 32 bit library       *\n *                                                                         *\n *                    File Name : FONT.H                                   *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : June 27, 1994                            *\n *                                                                         *\n *                  Last Update : June 29, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   VVPC::Text_Print -- Text print into a virtual viewport.               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FONT_H\n#define FONT_H\n\n#ifndef GBUFFER_H\n#include <gbuffer.h>\n#endif\n\n#ifndef VBUFFER_H\n#include <vbuffer.h>\n#endif\n\n//////////////////////////////////////// Defines //////////////////////////////////////////\n\n// defines for font header, offsets to block offsets\n\n#define FONTINFOBLOCK\t\t\t4\n#define FONTOFFSETBLOCK\t\t\t6\n#define FONTWIDTHBLOCK\t\t\t8\n#define FONTDATABLOCK\t\t\t10\n#define FONTHEIGHTBLOCK\t\t\t12\n\n// defines for font info block\n\n#define FONTINFOMAXHEIGHT\t\t4\n#define FONTINFOMAXWIDTH\t\t5\n\n//////////////////////////////////////// Prototypes //////////////////////////////////////////\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SET_FONT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nVOID *cdecl Set_Font(VOID const *fontptr);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FONT.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD cdecl Char_Pixel_Width(BYTE chr);\nUWORD cdecl String_Pixel_Width(BYTE const *string);\nVOID cdecl Get_Next_Text_Print_XY(GraphicViewPortClass& vp, ULONG offset, INT *x, INT *y);\nVOID cdecl Get_Next_Text_Print_XY(VideoViewPortClass& vp, ULONG offset, INT *x, INT *y);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOADFONT.CPP\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\nVOID *cdecl Load_Font(BYTE  const *name);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TEXTPRNT.ASM\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\nVOID Set_Font_Palette_Range(VOID *palette, INT start_idx, INT end_idx);\n\n\n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n\n\n\n\n\n//////////////////////////////////////// External varables ///////////////////////////////////////\nextern \"C\" int FontXSpacing;\nextern \"C\" int FontYSpacing;\nextern BYTE FontWidth ;\nextern BYTE FontHeight;\nextern BYTE *FontWidthBlockPtr;\n\n\nextern \"C\" VOID const *FontPtr;\n\n\n\n\n#endif // FONT_H\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/FUNCTION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SOUNDIO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort Decompress_Frame(void * source, void * dest, short size);\nint cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback);\nint cdecl Stream_Sample(void *buffer, long size, BOOL (*callback);\nint cdecl File_Stream_Sample(char const *filename);\nint cdecl File_Stream_Sample_Vol(char const *filename, int volume);\nvoid cdecl _saveregs _loadds Sound_Callback(void);\nvoid cdecl far _saveregs _loadds maintenance_callback(void);\nvoid *cdecl Load_Sample(char const *filename);\nlong cdecl Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);\nlong cdecl Sample_Read(int fh, void *buffer, long size);\nvoid cdecl Free_Sample(void const *sample);\nBOOL cdecl Sound_Init(int sfx, int score, int sample);\nvoid far VQA_TimerCallback(void);\nBOOL Audio_Init(int sample, int address, int inter, int dma);\nvoid cdecl Sound_End(void);\nvoid cdecl Stop_Sample(int handle);\nBOOL cdecl Sample_Status(int handle);\nBOOL cdecl Is_Sample_Playing(void const * sample);\nvoid cdecl Stop_Sample_Playing(void const * sample);\nint cdecl Play_Sample(void const *sample);\nint cdecl Play_Sample_Vol(void const *sample, int priority, int volume);\nint cdecl Set_Sound_Vol(int volume);\nint cdecl Set_Score_Vol(int volume);\nvoid cdecl Fade_Sample(int handle, int ticks);\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/GBUFFER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : GBUFFER.H                                *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 26, 1994                             *\n *                                                                         *\n *                  Last Update : January 17, 1995   [PWG]                 *\n *                                                                         *\n ***************************************************************************\n *                                                                         *\n *\tThis module contains the definition for the graphic buffer class.  The\t*\n * primary functionality of the graphic buffer class is handled by inline\t*\n * functions that make a call through function pointers to the correct\t\t*\n * routine.  This has two benefits:\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t1) C++ name mangling is not a big deal since the function pointers\t*\n *\t\t   point to functions in standard C format.\t\t\t\t\t\t\t\t\t*\n *\t\t2) The function pointers can be changed when we set a different\t\t*\n *       graphic mode.  This allows us to have both supervga and mcga\t\t*\n *\t\t\troutines present in memory at once.\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * In the basic library, these functions point to stub routines which just\t*\n * return.  This makes a product that just uses a graphic buffer take the\t*\n * minimum amount of code space.  For programs that require MCGA or VESA\t*\n * support, all that is necessary to do is link either the MCGA or VESA\t\t*\n * specific libraries in, previous to WWLIB32.  The linker will then \t\t*\n * overide the the necessary stub functions automatically.\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * In addition, there are helpful inline function calls for parameter\t\t*\n * ellimination.  This header file gives the defintion for all\t\t\t\t\t*\n * GraphicViewPort and GraphicBuffer classes.  \t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Terminology:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tBuffer Class - A class which consists of a pointer to an allocated\t\t* \n *\t\tbuffer and the size of the buffer that was allocated.\t\t\t\t\t\t* \n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n *\tGraphic ViewPort - The Graphic ViewPort defines a window into a \t\t\t*\n *\t\tGraphic Buffer.  This means that although a Graphic Buffer \t\t\t\t*\n *\t\trepresents linear memory, this may not be true with a Graphic\t\t\t*\n *\t\tViewport.  All low level functions that act directly on a graphic\t\t*\n *\t\tviewport are included within this class.  This includes but is not\t*\n *\t\tlimited to most of the functions which can act on a Video Viewport\t*\n *\t\tVideo Buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n * Graphic Buffer - A Graphic Buffer is an instance of an allocated buffer\t* \n *\t\tused to represent a rectangular region of graphics memory.\t\t\t\t*\n *\t\tThe HidBuff\tand BackBuff are excellent examples of a Graphic Buffer.\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n * Below is a tree which shows the relationship of the VideoBuffer and \t\t*\n * Buffer classes to the GraphicBuffer class:\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t  BUFFER.H\t\t\t\t GBUFFER.H\t\t\t  BUFFER.H\t\t\t\t VBUFFER.H\t*\n *  ----------          ----------         ----------          ----------\t*\n * |  Buffer  |        | Graphic  |       |  Buffer  |        |  Video   |\t*\n * |  Class   |        | ViewPort |       |  Class   |        | ViewPort |\t*\n *  ----------          ----------         ----------          ----------\t*\n *            \\        /                             \\        /\t\t\t\t*\n *             \\      /                               \\      /\t\t\t\t\t*\n *            ----------                             ----------\t\t\t\t*\n *           |  Graphic |                           |  Video   |\t\t\t\t*\n *           |  Buffer  |                           |  Buffer  |\t\t\t\t*\n *            ----------                             ---------- \t\t\t\t*\n *\t  \t\t\t  GBUFFER.H\t\t\t                       VBUFFER.H\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   GBC::GraphicBufferClass -- inline constructor for GraphicBufferClass  *\n *   GVPC::Remap -- Short form to remap an entire graphic view port        *\n *   GVPC::Get_XPos -- Returns x offset for a graphic viewport class       *\n *   GVPC::Get_Ypos -- Return y offset in a GraphicViewPortClass           *\n *   VVPC::Get_XPos -- Get the x pos of the VP on the Video                *\n *   VVPC::Get_YPos -- Get the y pos of the VP on the video                *\n *   GBC::Get_Graphic_Buffer -- Get the graphic buffer of the VP.          *\n *   GVPC::Draw_Line -- Stub function to draw line in Graphic Viewport Class*\n *   GVPC::Fill_Rect -- Stub function to fill rectangle in a GVPC          *\n *   GVPC::Remap -- Stub function to remap a GVPC                          *\n *   GVPC::Print -- stub func to print a text string                       *\n *   GVPC::Print -- Stub function to print an integer                      *\n *   GVPC::Print -- Stub function to print a short to a graphic viewport   *\n *   GVPC::Print -- stub function to print a long on a graphic view port   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef GBUFFER_H\n#define GBUFFER_H\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n#ifndef MCGAPRIM_H\n#include \"mcgaprim.h\"\n#endif\n\n#ifndef BUFFER_H\n#include \"buffer.h\"\n#endif\n\n#include <stdlib.h>\n\n\n/*=========================================================================*/\n/* Define the screen width and height to make portability to other modules\t*/\n/*\t\teasier.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tDEFAULT_SCREEN_WIDTH\t\t320\n#define\tDEFAULT_SCREEN_HEIGHT\t200\n\n/*=========================================================================*/\n/* Let the compiler know that a GraphicBufferClass exists so that it can\t*/\n/*\t\tkeep a pointer to it in a VideoViewPortClass.\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nclass GraphicViewPortClass;\nclass GraphicBufferClass;\nclass VideoViewPortClass;\nclass VideoBufferClass;\n\nGraphicBufferClass *Set_Logic_Page(GraphicBufferClass *ptr);\nGraphicBufferClass *Set_Logic_Page(GraphicBufferClass &ptr);\n\n/*=========================================================================*/\n/* GraphicViewPortClass - Holds viewport information on a viewport which\t*/\n/*\t\thas been attached to a GraphicBuffer.  A viewport is effectively a\t*/\n/*\t\trectangular subset of the full buffer which is used for clipping and\t*/\n/*\t\tthe like.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tchar\t  \t*Buffer\t-\t\tis the offset to view port buffer\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis the width of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis the height of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis add value to go from the end of a line\t*/\n/*\t\t\t\t\t\t\t\t\t\t\tto the beginning of the next line\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\tx offset into its associated VideoBuffer\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\ty offset into its associated VideoBuffer\t*/\n/*=========================================================================*/\nclass GraphicViewPortClass {\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tGraphicViewPortClass(GraphicBufferClass* graphic_buff, int x, int y, int w, int h);\n\t\tGraphicViewPortClass();\n\t\t~GraphicViewPortClass();\n\n\t\t/*===================================================================*/\n\t\t/* define functions to get at the private data members\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\tGet_Offset(void);\n\t\tint\tGet_Height(void);\n\t\tint\tGet_Width(void);\n\t\tint\tGet_XAdd(void);\n\t\tint\tGet_XPos(void);\n\t\tint\tGet_YPos(void);\n\t\tGraphicBufferClass\t*Get_Graphic_Buffer(void);\n\n\t\t/*===================================================================*/\n\t\t/* Define a function which allows us to change a video viewport on\t*/\n\t\t/*\t\tthe fly.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBOOL Change(int x, int y, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the set of common graphic functions that are supported by\t*/\n\t\t/*\t\tboth Graphic ViewPorts and VideoViewPorts.\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\tSize_Of_Region(int w, int h);\n\t\tvoid\tPut_Pixel(int x, int y, unsigned char color);\n\t\tint\tGet_Pixel(int x, int y);\n\t\tvoid\tClear(unsigned char color = 0);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, void *buff, long size);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, BufferClass *buff);\n\t\tlong\tTo_Buffer(BufferClass *buff);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, char *remap);\n\t\tunsigned long\tPrint(char const *string, int x_pixel, int y_pixel, int fcolor, int bcolor);\n\t\tunsigned long\tPrint(short num, int x_pixel, int y_pixel, int fcol, int bcol);\n\t\tunsigned long\tPrint(int num, int x_pixel, int y_pixel, int fcol, int bcol);\n\t\tunsigned long\tPrint(long num, int x_pixel, int y_pixel, int fcol, int bcol);\n\n\t\t/*===================================================================*/\n\t\t/* Define the list of graphic functions which work only with a \t\t*/\n\t\t/*\t\tgraphic buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Draw_Line(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Draw_Rect(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Fill_Rect(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Fill_Quad(VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\tint x2, int y2, int x3, int y3, int color);\n\t\tVOID Remap(int sx, int sy, int width, int height, VOID *remap);\n\t\tVOID Remap(VOID *remap);\n\t\tvoid Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap);\n\t\tVOID Grey_Out_Region(int x, int y, int width, int height, int color);\n\tprotected:\n\t\t/*===================================================================*/\n\t\t/* Define functions to attach the viewport to a graphicbuffer\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Attach(GraphicBufferClass *graphic_buff, int x, int y, int w, int h);\n\t\tvoid Attach(GraphicBufferClass *video_buff, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the data used by a GraphicViewPortClass\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\t\t\t\t\t\tOffset;\t\t\t\t\t// offset to graphic page\n\t\tint\t\t\t\t\t\tWidth;\t\t\t\t\t// width of graphic page\n\t\tint\t\t\t\t\t\tHeight;\t\t\t\t\t// height of graphic page\n\t\tint\t\t\t\t\t\tXAdd;\t\t\t\t\t\t// xadd for graphic page (0)\n\t\tint\t\t\t\t\t\tXPos;\t\t\t\t\t\t// x offset in relation to graphicbuff\n\t\tint\t\t\t\t\t\tYPos;\t\t\t\t\t\t// y offset in relation to graphicbuff\n\t\tGraphicBufferClass\t*GraphicBuff;\t\t\t// related graphic buff\n};\n\n/*=========================================================================*/\n/* GraphicBufferClass - A GraphicBuffer refers to an actual instance of an\t*/\n/*\t\tallocated buffer.  The GraphicBuffer may be drawn to directly \t\t\t*/\n/*\t\tbecuase it inherits a ViewPort which represents its physcial size.\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tBYTE\t  \t*Buffer\t-\t\tis the offset to graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis the width of graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis the height of graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis the xadd of graphic buffer\t\t\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\twill be 0 because it is graphicbuff\t\t\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\twill be 0 because it is graphicbuff\t\t\t*/\n/*=========================================================================*/\nclass GraphicBufferClass : public GraphicViewPortClass, public BufferClass {\n\tpublic:\n\t\tGraphicBufferClass(\tlong size = 64500, int w = DEFAULT_SCREEN_WIDTH, int h = DEFAULT_SCREEN_HEIGHT, \n\t\t\t\t\t\t\t\t\tVOID *buffer = 0);\n\t\tGraphicBufferClass(int w, int h, void *buffer = 0);\n\t\t~GraphicBufferClass();\n};\n\n/***************************************************************************\n * GVPC::GET_OFFSET -- Get offset for virtual view port class instance     *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long the offset for the virtual viewport instance           *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long GraphicViewPortClass::Get_Offset(void)\n{\n\treturn(Offset);\n}\n\n/***************************************************************************\n * GVPC::GET_HEIGHT -- Gets the height of a virtual viewport instance      *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the height of the virtual viewport instance            *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_Height(void)\n{\n\treturn(Height);\n}\n\n/***************************************************************************\n * GVPC::GET_WIDTH -- Get the width of a virtual viewport instance\t\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the width of the virtual viewport instance             *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_Width(void)\n{\n\treturn(Width);\n}\n\n\n/***************************************************************************\n * GVPC::GET_XADD -- Get the X add offset for virtual viewport instance    *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the xadd for a virtual viewport instance               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_XAdd(void)\n{\t\n\treturn(XAdd);\n}\n/***************************************************************************\n * GVPC::GET_XPOS -- Get the x pos of the VP on the Video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n;*   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_XPos(void)\n{\n\treturn(XPos);\n}\n\n\n/***************************************************************************\n * GVPC::GET_YPOS -- Get the y pos of the VP on the video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n;*   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_YPos(void)\n{\n\treturn(YPos);\n}\n\n/***************************************************************************\n * GVPC::GET_GRAPHIC_BUFFER -- Get the graphic buffer of the VP.            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline GraphicBufferClass *GraphicViewPortClass::Get_Graphic_Buffer(void)\n{\n \treturn (GraphicBuff);\n}\n\n/***************************************************************************\n * GVPC::SIZE_OF_REGION -- stub to call curr graphic mode Size_Of_Region\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/01/1995 BWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::Size_Of_Region(int w, int h)\n{\n\treturn MCGA_Size_Of_Region(this, w, h);\n}\n\n/***************************************************************************\n * GVPC::PUT_PIXEL -- stub to call curr graphic mode Put_Pixel\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tGraphicViewPortClass::Put_Pixel(int x, int y, unsigned char color)\n{\n\tMCGA_Put_Pixel(this, x, y, color);\n}\n\n/***************************************************************************\n * GVPC::GET_PIXEL -- stub to call curr graphic mode Get_Pixel          \t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline int\tGraphicViewPortClass::Get_Pixel(int x, int y)\n{\n\treturn(MCGA_Get_Pixel(this, x, y));\n}\n\n/***************************************************************************\n * GVPC::CLEAR -- stub to call curr graphic mode Clear\t                  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tGraphicViewPortClass::Clear(unsigned char color)\n{\n\tMCGA_Clear(this, color);\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 1 to call curr graphic mode To_Buffer\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(int x, int y, int w, int h, void *buff, long size)\n{\n\treturn(MCGA_To_Buffer(this, x, y, w, h, buff, size));\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 2 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(int x, int y, int w, int h, BufferClass *buff)\n{\n\treturn(MCGA_To_Buffer(this, x, y, w, h, buff->Get_Buffer(), buff->Get_Size()));\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 3 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(BufferClass *buff)\n{\n\treturn(MCGA_To_Buffer(this, 0, 0, Width, Height, buff->Get_Buffer(), buff->Get_Size()));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 1 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans)\n{\n\treturn(Linear_Blit_To_Linear(this, &dest, x_pixel, y_pixel, dx_pixel, dy_pixel, pixel_width, pixel_height, trans));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- Stub 2 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans)\n{\n\treturn(Linear_Blit_To_Linear(this, &dest, 0, 0, dx, dy, Width, Height, trans));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 3 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, BOOL trans)\n{\n\treturn(Linear_Blit_To_Linear(this, &dest, 0, 0, 0, 0, Width, Height, trans));\n}\n\n\n/***************************************************************************\n * GVPC::SCALE -- stub 1 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, trans, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 2 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, FALSE, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 3 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, BOOL trans, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this,\t&dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), trans, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 4 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), FALSE, remap));\n}\n/***************************************************************************\n * GVPC::PRINT -- stub func to print a text string                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/17/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(char const *str, int x, int y, int fcol, int bcol)\n{\n\treturn(MCGA_Print(this, str, x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::PRINT -- Stub function to print an integer                        *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(int num, int x, int y, int fcol, int bcol)\n{\n\tchar str[17];\n\n\t\n\treturn(MCGA_Print(this, itoa(num, str, 10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::PRINT -- Stub function to print a short to a graphic viewport     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(short num, int x, int y, int fcol, int bcol)\n{\n\tchar str[17];\n\n\treturn(MCGA_Print(this, itoa(num, str, 10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::PRINT -- stub function to print a long on a graphic view port     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(long num, int x, int y, int fcol, int bcol)\n{\n\tchar str[33];\n\n\treturn(MCGA_Print(this, ltoa(num, str,10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::DRAW_STAMP -- stub function to draw a tile on a graphic view port *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline void GraphicViewPortClass::Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap)\n{\n\tMCGA_Draw_Stamp(this, icondata, icon, x_pixel, y_pixel, remap);\n}\n\n/***************************************************************************\n * GVPC::DRAW_LINE -- Stub function to draw line in Graphic Viewport Class *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Draw_Line(int sx, int sy, int dx, int dy, unsigned char color)\n{\n\tMCGA_Draw_Line(this, sx, sy, dx, dy, color);\n}\n\n/***************************************************************************\n * GVPC::FILL_RECT -- Stub function to fill rectangle in a GVPC            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Fill_Rect(int sx, int sy, int dx, int dy, unsigned char color)\n{\n\tMCGA_Fill_Rect(this, sx, sy, dx, dy, color);\n}\n\n\n/***************************************************************************\n * GVPC::REMAP -- Stub function to remap a GVPC                            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Remap(int sx, int sy, int width, int height, VOID *remap)\n{\n\tMCGA_Remap(this, sx, sy, width, height, remap);\n}\ninline VOID GraphicViewPortClass::Fill_Quad(VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\tint x2, int y2, int x3, int y3, int color)\n{\n\tMCGA_Fill_Quad(this, span_buff, x0, y0, x1, y1, x2, y2, x3, y3, color);\n}\n\n/***************************************************************************\n * GVPC::REMAP -- Short form to remap an entire graphic view port          *\n *                                                                         *\n * INPUT:\t\tBYTE * to the remap table to use\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Remap(VOID *remap)\n{\n\tMCGA_Remap(this, 0, 0, Width, Height, remap);\n}\n/*=========================================================================*/\n/* The following BufferClass functions are defined here because they act\t*/\n/*\t\ton graphic viewports.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n\n/***************************************************************************\n * BUFFER_TO_PAGE -- Generic 'c' callable form of Buffer_To_Page           *\n *                                                                         *\n * INPUT: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/12/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long Buffer_To_Page(int x, int y, int w, int h, void *Buffer, GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(x, y, w, h, Buffer, &view));\n}\n\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t*\n *\t\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t*\n *\t\t\t\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int w, int h, GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(0, 0, w, h, Buffer, &view));\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport.  width and height are assumed to be the\t\t\t*\n *\t\t\t\t\t\tviewport's width and height.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(0, 0, view.Get_Width(), view.Get_Height(), Buffer, &view));\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable x, y, w, h *\n *                                                                         *\n * INPUT:\tint\tx\t\t\t- x pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\ty\t\t\t- y pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t\t*\n *\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t\t*\n *\t\t\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\tnone                                                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int x, int y, int w, int h, GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(x, y, w, h, Buffer, &view));\n}\n\n\n#endif\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/GBUFFER.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 Bit Library\t\t   *\n;*                                                                         *\n;*                    File Name : GBUFFER.INC                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : May 26, 1994                             *\n;*                                                                         *\n;*                  Last Update : May 26, 1994   [PWG]                     *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n;******************************************************************************\n; Much testing was done to determine that only when there are 14 or more bytes\n; being copied does it speed the time it takes to do copies in this algorithm.\n; For this reason and because 1 and 2 byte copies crash, is the special case\n; used.  SKB 4/21/94.  Tested on 486 66mhz.  Copied by PWG 6/7/04.\nOPTIMAL_BYTE_COPY\tequ\t14\n\nSTRUC GraphicViewPort \nGVPOffset\t\tDD\t\t?\t\t; offset to virtual viewport\nGVPWidth\t\t\tDD\t\t?\t\t; width of virtual viewport\nGVPHeight\t\tDD\t\t?\t\t; height of virtual viewport\nGVPXAdd\t\t\tDD\t\t?\t\t; x mod to get to next line\nGVPXPos\t\t\tDD\t\t?\t\t; x pos relative to Graphic Buff\nGVPYPos\t\t\tDD\t\t?\t\t; y pos relative to Graphic Buff\nGVPBuffPtr\t\tDD\t\t?\t\t; ptr to associated Graphic Buff\nENDS\n\nSTRUC VideoViewPort \nVIVPOffset\t\t\tDD\t\t?\t\t; offset to virtual viewport\nVIVPWidth\t\t\tDD\t\t?\t\t; width of virtual viewport\nVIVPHeight\t\t\tDD\t\t?\t\t; height of virtual viewport\nVIVPXAdd\t\t\t\tDD\t\t?\t\t; x mod to get to next line\nVIVPXPos\t\t\t\tDD\t\t?\t\t; x pos relative to Graphic Buff\nVIVPYPos\t\t\t\tDD\t\t?\t\t; y pos relative to Graphic Buff\nVIVPBuffPtr\t\t\tDD\t\t?\t\t; ptr to associated Graphic Buff\nENDS\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/IFF.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the FILEIO Library               *\n *                                                                         *\n *                    File Name : IFF.H                                    *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 20, 1994                           *\n *                                                                         *\n *                  Last Update : April 20, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef IFF_H\n#define IFF_H\n\n#ifndef MISC_H\n#include <misc.h>\t\t// This is needed fro Reverse_WORD and _LONG\n#endif\n\n#ifndef MEMFLAG_H\n#include <memflag.h>\t// This is needed for MemoryFlagType.\n#endif\n\n#ifndef GBUFFER_H\n#include <gbuffer.h>\n#endif \n\n#define LZW_SUPPORTED\t\t\tFALSE\n\n/*=========================================================================*/\n/* Iff and Load Picture system defines and enumerations\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#define \tMAKE_ID(a,b,c,d)\t\t\t((LONG) ((LONG) d << 24) | ((LONG) c << 16) | ((LONG) b <<  8) | (LONG)(a))\n#define\tIFFize_WORD(a)\t\t\tReverse_WORD(a)\n#define\tIFFize_LONG(a)\t\t\tReverse_LONG(a)\n\n\n//lint -strong(AJX,PicturePlaneType)\ntypedef enum {\n\tBM_AMIGA,\t// Bit plane format (8K per bitplane).\n\tBM_MCGA,\t\t// Byte per pixel format (64K).\n\n\tBM_DEFAULT=BM_MCGA\t// Default picture format.\n} PicturePlaneType;\n\n/*\n**\tThis is the compression type code.  This value is used in the compressed\n**\tfile header to indicate the method of compression used.  Note that the\n**\tLZW method may not be supported.\n*/\n//lint -strong(AJX,CompressionType)\ntypedef enum {\n\tNOCOMPRESS,\t\t// No compression (raw data).\n\tLZW12,\t\t\t// LZW 12 bit codes.\n\tLZW14,\t\t\t// LZW 14 bit codes.\n\tHORIZONTAL,\t\t// Run length encoding (RLE).\n\tLCW\t\t\t\t// Westwood proprietary compression.\n} CompressionType;\n\n/*\n**\tCompressed blocks of data must start with this header structure.\n**\tNote that disk based compressed files have an additional two\n**\tleading bytes that indicate the size of the entire file.\n*/\n//lint -strong(AJX,CompHeaderType)\ntypedef struct {\n\tBYTE\tMethod;\t\t// Compression method (CompressionType).\n\tBYTE\tpad;\t\t\t// Reserved pad byte (always 0).\n\tLONG\tSize;\t\t\t// Size of the uncompressed data.\n\tWORD\tSkip;\t\t\t// Number of bytes to skip before data.\n} CompHeaderType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: IFF.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD cdecl Open_Iff_File(BYTE const *filename);\nVOID cdecl Close_Iff_File(WORD fh);\nULONG cdecl Get_Iff_Chunk_Size(WORD fh, LONG id);\nULONG cdecl Read_Iff_Chunk(WORD fh, LONG id, VOID *buffer, ULONG maxsize);\nVOID cdecl Write_Iff_Chunk(WORD file, LONG id, VOID *buffer, LONG length);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOADPICT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD cdecl Load_Picture(BYTE const *filename, BufferClass& scratchbuf, BufferClass& destbuf, UBYTE *palette=NULL, PicturePlaneType format=BM_DEFAULT);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOAD.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nULONG cdecl Load_Data(BYTE const *name, VOID *ptr, ULONG size);\nULONG cdecl Write_Data(BYTE const *name, VOID *ptr, ULONG size);\nVOID * cdecl Load_Alloc_Data(BYTE const *name, MemoryFlagType flags);\nULONG cdecl Load_Uncompress(BYTE const *file, BufferClass& uncomp_buff, BufferClass& dest_buff, VOID *reserved_data=NULL);\nULONG cdecl Uncompress_Data(VOID const *src, VOID *dst);\nVOID cdecl Set_Uncomp_Buffer(WORD buffer_segment, UWORD size_of_buffer);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WRITELBM.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nPUBLIC BOOL Write_LBM_File(WORD lbmhandle, BufferClass& buff, WORD bitplanes, UBYTE *palette);\n\n\n\n/*========================= Assembly Functions ============================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*=========================================================================*/\n/* The following prototypes are for the file: PACK2PLN.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern VOID Pack_2_Plane(VOID *buffer, VOID * pageptr, WORD planebit);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LCWCOMP.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern ULONG LCW_Compress(VOID *source, VOID *dest, ULONG length);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LCWUNCMP.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern ULONG LCW_Uncompress(VOID *source, VOID *dest, ULONG length);\n\n#ifdef __cplusplus\n}\n#endif\n/*=========================================================================*/\n\n\n\n#endif //IFF_H\n\u001a\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/KEYBOARD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : KEYBOARD.H                               *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : July 13, 1994                            *\n *                                                                         *\n *                  Last Update : July 13, 1994   [PWG]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef KEYBOARD_H\n#define KEYBOARD_H\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n\nextern \"C\" {\n\tvoid Install_Keyboard_Interrupt(void *addr, long size);\n\tvoid\t*Get_RM_Keyboard_Address(void);\n\tlong\tGet_RM_Keyboard_Size(void);\n\tvoid\tRemove_Keyboard_Interrupt(void);\n\tint\tCheck_Key_Num(void);\n\tint\tCheck_Key_Bits(void);\n\tint\tCheck_Key(void);\n\tshort\tGet_Key_Num(void);\n\tshort\tGet_Key_Bits(void);\n\tint\tGet_Key(void);\n\tint\tKN_To_KA(int keynum);\n\tint\tKeyboard_Attributes_On(int key_flags);\n\tint\tKeyboard_Attributes_Off(int key_flags);\n\tvoid\tClear_KeyBuffer(void);\n\tint\tKey_Down(int key);\n\tint\tKey_Satisfied(int key);\n\tvoid\tStuff_Key_WORD(int code);\n\tvoid\tStuff_Key_Num(int key);\n\tvoid  Install_Mouse(int max_width, int max_height, int scr_width, int scr_height);\n\tvoid\tReset_Mouse (void) ;\n\tvoid\tRemove_Mouse(void);\n\tint\tGet_Mouse_State(void);\n\tint\tGet_Mouse_X(void);\n\tint\tGet_Mouse_Y(void);\n\tint\tGet_Mouse_Disabled(void);\n\tvoid  *Set_Mouse_Cursor(int xhotspot,\tint yhotspot,\tvoid *cursor);\n\tvoid\tHide_Mouse(void);\n\tvoid\tShow_Mouse(void);\n\tvoid\tConditional_Hide_Mouse(int sx_pixel, int sy_pixel, int dx_pixel, int dy_pixel);\n\tvoid\tConditional_Show_Mouse(void);\n\n\n\tvoid  __interrupt far Keyboard_Interrupt(void);\n\textern int MouseQX;\n\textern int MouseQY;\n\n}\n\n\nenum {\n\tREPEATON     = 0x0001,\t/* 1:all makes into buffer, 0:only 1st make */\n\tTRACKEXT     = 0x0002,\t/* 1:Home != keypad Home, 0:Home=keypad Home */\n\tFILTERONLY   = 0x0004,\t/* 1:Normal BIOS operation with filter */\n\tCTRLALTTURBO = 0x0010,\t/* 1:Allow turbo up and down in application */\n\tNONUMLOCK    = 0x0200,\t/* 1:do NOT remap keypad to numbers */\n\tTASKSWITCHABLE = 0x400, /* 1:allows task switching keys thru ALT-TAB, */\n\t\t\t\t\t\t\t\t\t/*   ALT-ESC,CTRL-ESC */\n\tPASSBREAKS\t = 0x0800,\t// Pass all breaks to the keyboard buffer.\n\n\t/* The following flags, if turned on, should only be used for\n\t   debugging purposes (remember to take out the calls when BETA */\n\n\tCTRLSON      = 0x0008,\t/* 1:pass scroll lock sequence into BIOS */\n\tCTRLCON      = 0x0020,\t/* 1:pass stop code to BIOS */\n\tSCROLLLOCKON = 0x0040,\t/* 1:pass scroll lock key into BIOS */\n\tPAUSEON      = 0x0080,\t/* 1:pass the pause key and seq to BIOS */\n\t\t\t\t\t\t\t\t\t/*   make sure FILTERONLY is set */\n\tBREAKON      = 0x0100,\t/* 1:pass the ctrl break seq to BIOS */\n\tKEYMOUSE     = 0x1000,\t/* 1:keypad translates into mouse moves */\n\tSIMLBUTTON   = 0x2000\t/* 1:have space and enter keys simulate Left */\n\t\t\t\t\t\t\t\t\t/*   mouse button when KEYMOUSE is set */\n};\n\n\n/*\n**\tThese are the codes for the various key codes that are returned from the\n**\tkeyboard input routines Get_Key() and Input_ASCII().\n*/\ntypedef enum {\n\tKA_CTRL_AT = 0,\n\tKA_CTRL_A,\n\tKA_MORE = KA_CTRL_A,\n\tKA_CTRL_B,\n\tKA_SETBKGDCOL = KA_CTRL_B,\n\tKA_CTRL_C,\n\tKA_CTRL_D,\n\tKA_CTRL_E,\n\tKA_CTRL_F,\n\tKA_SETFORECOL = KA_CTRL_F,\n\tKA_CTRL_G,\n\tKA_CTRL_H,\n\tKA_BACKSPACE = KA_CTRL_H,\n\tKA_CTRL_I,\n\tKA_TAB = KA_CTRL_I,\n\tKA_CTRL_J,\n\tKA_CTRL_K,\n\tKA_CTRL_L,\n\tKA_FORMFEED = KA_CTRL_L,\n\tKA_CTRL_M,\n\tKA_RETURN = KA_CTRL_M,\n\tKA_CTRL_N,\n\n\tKA_CTRL_O,\n\tKA_CTRL_P,\n\tKA_CTRL_Q,\n\tKA_CTRL_R,\n\tKA_CTRL_S,\n\tKA_SPCTAB = KA_CTRL_S,\n\tKA_CTRL_T,\n\tKA_CTRL_U,\n\tKA_CTRL_V,\n\tKA_CTRL_W,\n\tKA_CTRL_X,\n\tKA_SETX = KA_CTRL_X,\n\tKA_CTRL_Y,\n\tKA_SETY = KA_CTRL_Y,\n\tKA_CTRL_Z,\n\tKA_CTRL_LBRACKET,\n\tKA_ESC = KA_CTRL_LBRACKET,\n\tKA_EXTEND = KA_ESC,\n\tKA_CTRL_BACKSLASH,\n\tKA_CTRL_RBRACKET,\n\tKA_LITERAL = KA_CTRL_RBRACKET,\n\tKA_CTRL_CARROT,\n\tKA_CTRL_UNDERLINE,\n\n\tKA_SPACE,\t\t\t\t\t\t\t\t\t/*   */\n\tKA_EXCLAMATION,\t\t\t\t\t\t\t/* ! */\n\tKA_DQUOTE,\t\t\t\t\t\t\t\t\t/* \" */\n\tKA_POUND,\t\t\t\t\t\t\t\t\t/* # */\n\tKA_DOLLAR,\t\t\t\t\t\t\t\t\t/* $ */\n\tKA_PERCENT,\t\t\t\t\t\t\t\t\t/* % */\n\tKA_AMPER,\t\t\t\t\t\t\t\t\t/* & */\n\tKA_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKA_LPAREN,\t\t\t\t\t\t\t\t\t/* ( */\n\tKA_RPAREN,\t\t\t\t\t\t\t\t\t/* ) */\n\tKA_ASTERISK,\t\t\t\t\t\t\t\t/* * */\n\tKA_PLUS,\t\t\t\t\t\t\t\t\t\t/* + */\n\tKA_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKA_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKA_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKA_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKA_0, KA_1, KA_2, KA_3, KA_4, KA_5, KA_6, KA_7, KA_8, KA_9,\n\tKA_COLON,\t\t\t\t\t\t\t\t\t/* : */\n\tKA_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKA_LESS_THAN,\t\t\t\t\t\t\t\t/* < */\n\tKA_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\tKA_GREATER_THAN,\t\t\t\t\t\t\t/* > */\n\tKA_QUESTION,\t\t\t\t\t\t\t\t/* ? */\n\n\tKA_AT,\t\t\t\t\t\t\t\t\t\t/* @ */\n\tKA_A,\t\t\t\t\t\t\t\t\t\t\t/* A */\n\tKA_B,\t\t\t\t\t\t\t\t\t\t\t/* B */\n\tKA_C,\t\t\t\t\t\t\t\t\t\t\t/* C */\n\tKA_D,\t\t\t\t\t\t\t\t\t\t\t/* D */\n\tKA_E,\t\t\t\t\t\t\t\t\t\t\t/* E */\n\tKA_F,\t\t\t\t\t\t\t\t\t\t\t/* F */\n\tKA_G,\t\t\t\t\t\t\t\t\t\t\t/* G */\n\tKA_H,\t\t\t\t\t\t\t\t\t\t\t/* H */\n\tKA_I,\t\t\t\t\t\t\t\t\t\t\t/* I */\n\tKA_J,\t\t\t\t\t\t\t\t\t\t\t/* J */\n\tKA_K,\t\t\t\t\t\t\t\t\t\t\t/* K */\n\tKA_L,\t\t\t\t\t\t\t\t\t\t\t/* L */\n\tKA_M,\t\t\t\t\t\t\t\t\t\t\t/* M */\n\tKA_N,\t\t\t\t\t\t\t\t\t\t\t/* N */\n\tKA_O,\t\t\t\t\t\t\t\t\t\t\t/* O */\n\n\tKA_P,\t\t\t\t\t\t\t\t\t\t\t/* P */\n\tKA_Q,\t\t\t\t\t\t\t\t\t\t\t/* Q */\n\tKA_R,\t\t\t\t\t\t\t\t\t\t\t/* R */\n\tKA_S,\t\t\t\t\t\t\t\t\t\t\t/* S */\n\tKA_T,\t\t\t\t\t\t\t\t\t\t\t/* T */\n\tKA_U,\t\t\t\t\t\t\t\t\t\t\t/* U */\n\tKA_V,\t\t\t\t\t\t\t\t\t\t\t/* V */\n\tKA_W,\t\t\t\t\t\t\t\t\t\t\t/* W */\n\tKA_X,\t\t\t\t\t\t\t\t\t\t\t/* X */\n\tKA_Y,\t\t\t\t\t\t\t\t\t\t\t/* Y */\n\tKA_Z,\t\t\t\t\t\t\t\t\t\t\t/* Z */\n\tKA_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKA_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\tKA_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKA_CARROT,\t\t\t\t\t\t\t\t\t/* ^ */\n\tKA_UNDERLINE,\t\t\t\t\t\t\t\t/* _ */\n\n\tKA_GRAVE,\t\t\t\t\t\t\t\t\t/* ` */\n\tKA_a,\t\t\t\t\t\t\t\t\t\t\t/* a */\n\tKA_b,\t\t\t\t\t\t\t\t\t\t\t/* b */\n\tKA_c,\t\t\t\t\t\t\t\t\t\t\t/* c */\n\tKA_d,\t\t\t\t\t\t\t\t\t\t\t/* d */\n\tKA_e,\t\t\t\t\t\t\t\t\t\t\t/* e */\n\tKA_f,\t\t\t\t\t\t\t\t\t\t\t/* f */\n\tKA_g,\t\t\t\t\t\t\t\t\t\t\t/* g */\n\tKA_h,\t\t\t\t\t\t\t\t\t\t\t/* h */\n\tKA_i,\t\t\t\t\t\t\t\t\t\t\t/* i */\n\tKA_j,\t\t\t\t\t\t\t\t\t\t\t/* j */\n\tKA_k,\t\t\t\t\t\t\t\t\t\t\t/* k */\n\tKA_l,\t\t\t\t\t\t\t\t\t\t\t/* l */\n\tKA_m,\t\t\t\t\t\t\t\t\t\t\t/* m */\n\tKA_n,\t\t\t\t\t\t\t\t\t\t\t/* n */\n\tKA_o,\t\t\t\t\t\t\t\t\t\t\t/* o */\n\n\tKA_p,\t\t\t\t\t\t\t\t\t\t\t/* p */\n\tKA_q,\t\t\t\t\t\t\t\t\t\t\t/* q */\n\tKA_r,\t\t\t\t\t\t\t\t\t\t\t/* r */\n\tKA_s,\t\t\t\t\t\t\t\t\t\t\t/* s */\n\tKA_t,\t\t\t\t\t\t\t\t\t\t\t/* t */\n\tKA_u,\t\t\t\t\t\t\t\t\t\t\t/* u */\n\tKA_v,\t\t\t\t\t\t\t\t\t\t\t/* v */\n\tKA_w,\t\t\t\t\t\t\t\t\t\t\t/* w */\n\tKA_x,\t\t\t\t\t\t\t\t\t\t\t/* x */\n\tKA_y,\t\t\t\t\t\t\t\t\t\t\t/* y */\n\tKA_z,\t\t\t\t\t\t\t\t\t\t\t/* z */\n\tKA_LBRACE,\t\t\t\t\t\t\t\t\t/* { */\n\tKA_BAR,\t\t\t\t\t\t\t\t\t\t/* | */\n\tKA_RBRACE,\t\t\t\t\t\t\t\t\t/* ] */\n\tKA_TILDA,\t\t\t\t\t\t\t\t\t/* ~ */\n\tKA_DEL,\t\t\t\t\t\t\t\t\t\t/* not used */\n\n\tKA_ALT_F10 = 143,\n\tKA_ALT_F9,    KA_ALT_F8,   KA_ALT_F7,   KA_ALT_F6,   KA_ALT_F5,\n\tKA_ALT_F4,    KA_ALT_F3,   KA_ALT_F2,   KA_ALT_F1,\n\n\tKA_CTRL_F10,  KA_CTRL_F9,  KA_CTRL_F8,  KA_CTRL_F7,  KA_CTRL_F6,\n\tKA_CTRL_F5,   KA_CTRL_F4,  KA_CTRL_F3,  KA_CTRL_F2,  KA_CTRL_F1,\n\n\tKA_SHIFT_F10, KA_SHIFT_F9, KA_SHIFT_F8, KA_SHIFT_F7, KA_SHIFT_F6,\n\tKA_SHIFT_F5,  KA_SHIFT_F4, KA_SHIFT_F3, KA_SHIFT_F2, KA_SHIFT_F1,\n\n\tKA_DELETE,\t\t\t\t\t\t\t\t\t/* <DELETE> */\n\tKA_INSERT,\t\t\t\t\t\t\t\t\t/* <INSERT> */\n\tKA_PGDN,\t\t\t\t\t\t\t\t\t\t/* <PAGE DOWN> */\n\tKA_DOWNRIGHT = KA_PGDN,\n\tKA_DOWN,\t\t\t\t\t\t\t\t\t\t/* <DOWN ARROW> */\n\tKA_END,\t\t\t\t\t\t\t\t\t\t/* <END> */\n\tKA_DOWNLEFT = KA_END,\n\n\tKA_RESERVED1,\n\n\tKA_RIGHT,\t\t\t\t\t\t\t\t\t/* <RIGHT ARROW> */\n\tKA_KEYPAD5,\t\t\t\t\t\t\t\t\t/* NUMERIC KEY PAD <5> */\n\tKA_LEFT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ARROW> */\n\n\tKA_RESERVED2,\n\n\tKA_PGUP,\t\t\t\t\t\t\t\t\t\t/* <PAGE UP> */\n\tKA_UPRIGHT = KA_PGUP,\n\tKA_UP,\t\t\t\t\t\t\t\t\t\t/* <UP ARROW> */\n\tKA_HOME,\t\t\t\t\t\t\t\t\t\t/* <HOME> */\n\tKA_UPLEFT = KA_HOME,\n\t\n\tKA_RESERVED3,\n\tKA_RESERVED4,\n\n\tKA_F10, KA_F9, KA_F8, KA_F7, KA_F6, KA_F5, KA_F4, KA_F3, KA_F2, KA_F1,\n\n\tKA_LMOUSE,\n\tKA_RMOUSE,\n\tKA_JBUTTON1,\n\tKA_JBUTTON2,\n\tKA_J_UP,\n\tKA_J_RIGHT,\n\tKA_J_DOWN,\n\tKA_J_LEFT,\n\n\tKA_SHIFT_BIT = 0x0100,\n\tKA_CTRL_BIT  = 0x0200,\n\tKA_ALT_BIT   = 0x0400,\n\tKA_RLSE_BIT  = 0x0800,\n\tKA_LCOMM_BIT = 0x1000,\t\t\t\t\t/* Amiga Left Comm key\t*/\n\tKA_RCOMM_BIT = 0x2000\t\t\t\t\t/* Amiga Right Comm key\t*/\n} KeyASCIIType;\n\n/*\n**\tThese are the keyboard codes that are returned from the input routines\n**\tGet_Key_Num and Input_Num.\n*/\ntypedef enum {\n\tKN_NONE = 0,\n\tKN_GRAVE = 1,\t\t\t\t\t\t\t\t/* ` */\n\tKN_1, KN_2, KN_3, KN_4, KN_5, KN_6, KN_7, KN_8, KN_9, KN_0,\n\tKN_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKN_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\n\tKN_RESERVED1,\n\n\tKN_BACKSPACE,\t\t\t\t\t\t\t\t/* <BACKSPACE> */\n\n\tKN_TAB,\t\t\t\t\t\t\t\t\t\t/* <TAB> */\n\tKN_Q, KN_W, KN_E, KN_R, KN_T, KN_Y, KN_U, KN_I, KN_O, KN_P,\n\tKN_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKN_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKN_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\n\tKN_CAPSLOCK,\t\t\t\t\t\t\t\t/* <CAPS LOCK> */\n\tKN_A, KN_S, KN_D, KN_F, KN_G, KN_H, KN_J, KN_K, KN_L,\n\tKN_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKN_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKN_BACKSLASH2,\n\tKN_RETURN,\t\t\t\t\t\t\t\t\t/* <RETURN> or <ENTER> */\n\n\tKN_LSHIFT,\t\t\t\t\t\t\t\t\t/* <LEFT SHIFT> */\n\n\tKN_MOUSE_MOVE,\t\t\t\t\t\t\t\t// Indicate a mouse move (for playback of\n\n\tKN_Z, KN_X, KN_C, KN_V, KN_B, KN_N, KN_M,\n\tKN_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKN_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKN_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKN_RESERVED3,\n\n\tKN_RSHIFT,\t\t\t\t\t\t\t\t\t/* <RIGHT SHIFT> */\n\n\tKN_LCTRL,\t\t\t\t\t\t\t\t\t/* <LEFT CTRL> */\n\tKN_LCOMM,\t\t\t\t\t\t\t\t\t/* for AMIGA */\n\tKN_LALT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ALT> */\n\tKN_SPACE,\t\t\t\t\t\t\t\t\t/* <SPACE BAR> */\n\tKN_RALT,\t\t\t\t\t\t\t\t\t\t/* <RIGHT ALT> */\n\tKN_RCOMM,\t\t\t\t\t\t\t\t\t/* for AMIGA */\n\tKN_RCTRL,\t\t\t\t\t\t\t\t\t/* <RIGHT CTRL> */\n\t\t\t\t\t\t\t/* the following are forced into key buffer */\n\tKN_LMOUSE,\n\tKN_RMOUSE,\n\tKN_JBUTTON1,\n\tKN_JBUTTON2,\n\tKN_J_UP,\n\tKN_J_RIGHT,\n\tKN_J_DOWN,\n\tKN_J_LEFT,\n\n\tKN_SPECIAL9,\n\n\tKN_SPECIAL10,\n\n\tKN_E_INSERT,\t\t\t\t\t\t\t\t/* extended <INSERT> */\n\tKN_E_DELETE,\t\t\t\t\t\t\t\t/* extended <DELETE> */\n\n\tKN_RESERVED4,\n\tKN_RESERVED5,\n\n\tKN_E_LEFT,\t\t\t\t\t\t\t\t\t/* extended <LEFT ARROW> */\n\tKN_E_HOME,\t\t\t\t\t\t\t\t\t/* extended <HOME> */\n\tKN_E_END,\t\t\t\t\t\t\t\t\t/* extended <END> */\n\n\tKN_RESERVED6,\n\n\tKN_E_UP,\t\t\t\t\t\t\t\t\t\t/* extended <UP ARROW> */\n\tKN_E_DOWN,\t\t\t\t\t\t\t\t\t/* extended <DOWN ARROW> */\n\tKN_E_PGUP,\t\t\t\t\t\t\t\t\t/* extended <PAGE UP> */\n\tKN_E_PGDN,\t\t\t\t\t\t\t\t\t/* extended <PAGE DOWN> */\n\tKN_K_LPAREN,\t\t\t/* for AMIGA */\n\tKN_K_RPAREN,\t\t\t/* for AMIGA */\n\tKN_E_RIGHT,\t\t\t\t\t\t\t\t\t/* extended <RIGHT ARROW> */\n\n\tKN_NUMLOCK,\t\t\t\t\t\t\t\t\t/* <NUM LOCK> */\n\tKN_HOME,\t\t\t\t\t\t\t\t\t\t/* num key pad 7 */\n\tKN_UPLEFT = KN_HOME,\n\tKN_LEFT,\t\t\t\t\t\t\t\t\t\t/* num key pad 4 */\n\tKN_END,\t\t\t\t\t\t\t\t\t\t/* num key pad 1 */\n\tKN_DOWNLEFT = KN_END,\n\n\tKN_RESERVED7,\n\n\tKN_KEYPAD_SLASH,\t\t\t\t\t\t\t/* num key pad / */\n\tKN_UP,\t\t\t\t\t\t\t\t\t\t/* num key pad 8 */\n\tKN_CENTER,\t\t\t\t\t\t\t\t\t/* num key pad 5 */\n\tKN_DOWN,\t\t\t\t\t\t\t\t\t\t/* num key pad 2 */\n\tKN_INSERT,\t\t\t\t\t\t\t\t\t/* num key pad 0 */\n\tKN_KEYPAD_ASTERISK,\t\t\t\t\t\t/* num key pad * */\n\tKN_PGUP,\t\t\t\t\t\t\t\t\t\t/* num key pad 9 */\n\tKN_UPRIGHT = KN_PGUP,\n\tKN_RIGHT,\t\t\t\t\t\t\t\t\t/* num key pad 6 */\n\tKN_PGDN,\t\t\t\t\t\t\t\t\t\t/* num key pad 3 */\n\tKN_DOWNRIGHT = KN_PGDN,\n\tKN_DELETE,\t\t\t\t\t\t\t\t\t/* num key pad . */\n\tKN_KEYPAD_MINUS,\t\t\t\t\t\t\t/* num key pad - */\n\tKN_KEYPAD_PLUS,\t\t\t\t\t\t\t/* num key pad + */\n\n\tKN_RESERVED8,\n\n\tKN_KEYPAD_RETURN,\t\t\t\t\t\t\t/* num key pad <ENTER> */\n\n\tKN_RESERVED9,\n\n\tKN_ESC,\n\tKN_HELP,\t\t\t\t\t\t\t\t\t\t/* for AMIGA */\n\tKN_F1, KN_F2, KN_F3, KN_F4, KN_F5, KN_F6, KN_F7, KN_F8, KN_F9, KN_F10,\n\tKN_F11,\n\tKN_F12,\n\tKN_PRNTSCRN,\t\t\t\t\t\t\t\t/* <PRINT SCRN> */\n\tKN_SCROLLLOCK,\t\t\t\t\t\t\t\t/* <SCROLL LOCK> */\n\tKN_PAUSE,\t\t\t\t\t\t\t\t\t/* <PAUSE> */\n\n\tKN_SHIFT_BIT = 0x0100,\n\tKN_CTRL_BIT  = 0x0200,\n\tKN_ALT_BIT   = 0x0400,\n\tKN_RLSE_BIT  = 0x0800,\n\tKN_LCOMM_BIT = 0x1000,\t\t\t\t\t/* Amiga Left Comm key\t*/\n\tKN_RCOMM_BIT = 0x2000,\t\t\t\t\t/* Amiga Right Comm key\t*/\n\tKN_BUTTON    = 0x8000\t\t\t\t\t/* Amiga Right Comm key\t*/\n} KeyNumType;\n\n#endif\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/KEYBOARD.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : KEYBOARD.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 12, 1994                            *\n;*                                                                         *\n;*                  Last Update : July 12, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Contains all the defines used by the keyboard interrupt for assembly    *\n;*   includes.                                                             *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nTRUE\t\tEQU\t1\t\t\t; numerical true\nFALSE\t\tEQU\t0\t\t\t; numerical false\nDEBUG\t\tEQU\t1\n\nMAX_X_PIXEL\t\tEQU\t319\nMAX_Y_PIXEL\t\tEQU\t199\n\n\nKN_RESERVED1\t\tEQU\t14\nKN_RESERVED2\t\tEQU\t45\nKN_RESERVED3\t\tEQU\t56\n\n\n; these two are reserved for AMIGA open and close.\nKN_LCOMM\t\tEQU\t59\nKN_RCOMM\t\tEQU\t63\n\nKN_LMOUSE\t\tEQU\t65\nKN_RMOUSE\t\tEQU\t66\nKN_JBUTTON1\t\tEQU\t67\nKN_JBUTTON2\t\tEQU\t68\nKN_J_UP\t\t\tEQU\t69\nKN_J_RIGHT\t\tEQU\t70\nKN_J_DOWN\t\tEQU\t71\nKN_J_LEFT\t\tEQU\t72\n\nKN_LEFT\t\t\tEQU\t92\nKN_UPLEFT\t\tEQU\t91\nKN_UP\t\t\tEQU\t96\nKN_UPRIGHT\t\tEQU\t101\nKN_RIGHT\t\tEQU\t102\nKN_DOWNRIGHT\t\tEQU\t103\nKN_DOWN\t\t\tEQU\t98\nKN_DOWNLEFT\t\tEQU\t93\nKN_CENTER\t\tEQU\t97\n\nKN_INSERT\t\tEQU\t99\nKN_DELETE\t\tEQU\t104\n\nKN_RETURN\t\tEQU\t43\nKN_SPACE\t\tEQU\t61\nKN_KEYPAD_RETURN\tEQU\t108\n\n\n; these two are reserved for AMIGA K left and right paren\nKN_KLPAREN\t\tEQU\t87\nKN_KRPAREN\t\tEQU\t88\n\n\nKN_NUMLOCK\t\tEQU\t90\n\nKN_SCROLLOCK\t\tEQU\t125\t\t; key ignored by the logging system\n\nKN_MOUSE_MOVE\tEQU\t45\t; Indicate a mouse move (for playback of logged data)\n\n; ----------------------------------------------------------------\n; flags used in Keyflags to customize keystroke interrupt.\n\nREPEATON\tEQU\t0001H\t; 1:all makes into buffer, 0:only 1st make\nTRACKEXT\tEQU\t0002H\t; 1:Home != keypad Home, 0:Home=keypad Home\nFILTERONLY\tEQU\t0004H\t; 1:Normal BIOS operation with filter\nCTRLSON\t\tEQU\t0008H\t; 1:pass scroll lock sequence into BIOS\nCTRLALTTURBO\tEQU\t0010H\t; 1:Allow turbo up and down in application\nCTRLCON\t\tEQU\t0020H\t; 1:pass stop code to BIOS\nSCROLLLOCKON\tEQU\t0040H\t; 1:pass scroll lock key into BIOS\nPAUSEON\t\tEQU\t0080H\t; 1:pass the pause key and seq to BIOS\nBREAKON\t\tEQU\t0100H\t; 1:pass the ctrl break seq to BIOS\nNONUMLOCK\tEQU\t0200H\t; 1:do NOT remap keypad to numbers\nTASKSWITCHABLE\tEQU\t0400H\t; 1:allows task switching keys thru ALT-TAB,\n\t\t\t\t;   ALT-ESC,CTRL-ESC\nPASSBREAKS\tEQU\t0800H\t; 1:Pass all break codes to keyboard buffer.\nKEYMOUSE\tEQU\t1000H\t; 1:Numeric keypad moves mouse\nSIMLBUTTON\tEQU\t2000H\t; 1:have space and enter keys simulate Left\n\t\t\t\t;   mouse button when KEYMOUSE is set\n\n\nSHIFTPRESS\tEQU\t001H\t; bit 0 for shift key pressed\nCTRLPRESS\tEQU\t002H\t; bit 1 for ctrl key pressed\nALTPRESS\tEQU\t004H\t; bit 2 for alt key pressed\nKEYRELEASE\tEQU\t008H\t; bit 3 for key released\nNOTKEYRELEASE\tEQU\t0F7H\t; not of key released\n\nCAPSLOCK\tEQU\t00001H\t; bit 0 for caps locked\nNUMLOCK\tEQU\t00002H\t; bit 1 for num locked\n\n\n\nCLEARISR\tEQU\t020H\t; value to clear In Service Register\nDOS\t\tEQU \t021H\nINTCHIP0\tEQU\t020H\t; 8259 interrupt chip controller 0\nKEYCTRL\t\tEQU\t061H\t; control bits for KB sense data\nKEYDATA\t\tEQU\t060H\t; keyboard scan code port\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/KEYSTRUC.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : KEYSTRUC.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 13, 1994                            *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nSTRUC\tKeyboardType\n\tSoundOn\t\t\tDW\t?\t; toggled by alt S\n\tMusicOn\t\t\tDW\t?\t; toggled by alt M\n\tKeyFlags\t\t\tDD\t?\t; all but repeat for now\n\tBreak\t\t\t\tDW\t?\n\tKeyMouseMove\tDB\t6  DUP(?)\n\tScreenEdge\t\tDW\t18 DUP (?)\n\tBits\t\t\t\tDB\t8  DUP (?)\n\tCondPassKey\t\tDW\t17 DUP (?) \n\tCondPassCond\tDW\t17 DUP (?)\n\tEscRoutine\t\tDD\t?\n\tExtCodes\t\t\tDB\t16 DUP (?)\n\tExtNums\t\t\tDB\t16 DUP (?)\n\tExtRemap\t\t\tDB\t16 DUP (?)\n\tExtRemapEnd\t\tDB\t?\n\tExtKeyboard\t\tDB\t?\n\tKeyBuffer\t\tDW\t128 DUP(?) ; set to empty\n\tKeyBufferHead\tDD\t?\t; set to first entry\n\tKeyBufferTail\tDD\t?\t; set to head for empty buffer\n\tKeyLock\t\t\tDW\t?\t; num and caps lock bits\n\tKeyNums\t\t\tDB\t89 DUP (?)\n\tKeysCapsLock\tDB\t16 DUP (?)\n\tKeysNumLock\t\tDB\t16 DUP (?)\n\tKeysUpDown\t\tDB\t16 DUP (?)\n\tKeyStream\t\tDB\t16 DUP (?)\n\tPassCount\t\tDW\t?\n\tKeyStreamIndex\tDW\t?\n\tLastKeyE0\t\tDB\t?\n\tLastKeyE1\t\tDB\t?\n\tPassAlways\t\tDB\t10 DUP (?)\n\tPassAlwaysEnd\tDB\t?\t\t; invalid code to END PassAlways\n\tCtrlFlags\t\tDB\t?\n\tBuffer\t\t\tDW\t?\n\tTime\t\t\t\tDW\t?\n\tXYAdjust\t\t\tDB\t26 DUP (?)\n\tEdgeConv\t\t\tDW\t16 DUP (?)\n\tMouseUpdate\t\tDW\t?\n\tMouseX\t\t\tDD\t?\n\tLocalMouseX\t\tDW\t?\n\tMouseY\t\t\tDD\t?\n\tLocalMouseY\t\tDW\t?\n\tIsExtKey\t\t\tDB\t?\n\tExtIndex\t\t\tDW\t?\n\n\tKeyOldRMI\t\t\tDD\t?\t; The origianl RM interrupt seg:off.\n\tKeyOldPMIOffset\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tKeyOldPMISelector\tDD\t?\t; The original PM interrupt segment.\n\n\tKeyCodeOffset\t\t\tDW\t?\t; Offset of the code in the RM stuff.\n\tCallKeyRMIntOffset\tDW\t?\t; Offset of function to call DOS timer interrupt.\n\tCallKeyRMIntAddr\t\tDD\t?\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedKeyInt\t\t\tDD\t?\t; did Protected mode pass this through?\n\n\tBrkOldRMI\t\t\t\tDD\t?\t; The origianl RM interrupt seg:off.\n\tBrkOldPMIOffset\t\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tBrkOldPMISelector\t\tDD\t?\t; The original PM interrupt segment.\n\n\tBrkCodeOffset\t\t\tDW\t?\t; Offset of the code in the RM stuff.\n\tCallBrkRMIntOffset\tDW\t?\t; Offset of function to call DOS timer interrupt.\n\tCallBrkRMIntAddr\t\tDD\t?\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedBrkInt\t\t\tDD\t?\t; did Protected mode pass this through?\n\tKeyIntDisabled\t\t\tDD\t?\n\n\tDbgOldPMIOffset\t\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tDbgOldPMISelector\t\tDD\t?\t; The original PM interrupt segment.\n\n\t;---------------------------------------------------------------------------\n\t; Begin definition of Mouse Specific Variables for real mode\n\t;---------------------------------------------------------------------------\n\tButton\t\t\t\tDB\t?\t; current value of the mouse button\n\tMDisabled\t\t\tDB\t?\t; Is the mouse driver disabled\n\tMInput\t\t\t\tDB\t?\t; Defaults to mouse input allowed.\n\tAdjust\t\t\t\tDW\t?\t; flag to adjust coordinates if necessary\n\tMouseStepX\t\t\tDW\t?\t; step values if the mouse moves at\n\tMouseStepY\t\t\tDW\t?\t;   more than one pixel at a time\n\tMouseOffsetX\t\tDW\t?\t; Fractional step values used if a mouse\n\tMouseOffsetY\t\tDW\t?\t;   moves at less than one pixel at a time\n\tMState\t\t\t\tDD\t?\t; Tracks if mouse is hidden (TRUE) or not (FALSE)\n\tMouseXOld     \t\tDW\t?\t; Holds last MouseX and MouseY to determine if \n\tMouseYOld     \t\tDW\t?\t;   mouse needs to be redrawn\n\tMCState\t\t\t\tDW\t?\t; Tracks if mouse conditional hidden (TRUE) or not\n\tMouseCXLeft\t\t\tDD\t?\t; Conditional hide mouse left x position\n\tMouseCYUpper\t\tDD\t?\t; Conditional hide mouse top y position\n\tMouseCXRight\t\tDD\t?\t; Conditional hide mouse right x position\n\tMouseCYLower\t\tDD\t?\t; Conditional hide mouse lower y position\n\tMouseCursor   \t\tDD\t?\t; Pointer to the mouse cursor to draw\n\tMouseCursorSize\tDW\t?\t; Size of mouse cursor draw area\n\tMouseBuffer   \t\tDD\t?\t; Pointer to buffer mouse is saved in\n\tMouseXHot     \t\tDD\t?\t; Offset to mouse's x hot spot\n\tMouseYHot     \t\tDD\t?\t; Offset to mouse's y hot spot\n\tMouseBuffX\t\t\tDD\t?\t; X position background was saved at\n\tMouseBuffY\t\t\tDD\t?\t; Y position background was saved at\n\tMouseBuffW\t\t\tDD\t?\t; Width of the region saved for mouse\n\tMouseBuffH\t\t\tDD\t?\t; Height of the region saved for mouse\n\tMouseWidth\t\t\tDD\t?\t; Mouse cursor theoretical width\n\tMouseHeight\t\t\tDD\t?\t; Mouse cursor theoretical height\n\tMouseCodeOffset\tDW\t?\t; Offset to the real mode code offset\n\tMouseRight\t\t\tDD\t?\t; Right hand side of the screen\n\tMouseBottom\t\t\tDD\t?\t; Bottom of the screen\n\n\n\tShadowPtr\t\t\tdw\t?\n\tDrawMousePtr \t\tdw\t?\n\n\tVGAMouseDraw\t\tdw\t?\n\tVGAMouseShadow\t\tdw\t?\n\n\tVESAMouseDraw\t\tdw\t?\n\tVESAMouseShadow\tdw\t?\n\n\tVesaPtr\t\t\t\tdd ?\t\n\tVesaBankTable\t   DD\t8 dup (?)\n\tAdjust_XPos\t\t\tdd ?\n\tAdjust_YPos\t\t\tdd ?\n\n\nENDS\n\n; InitFlags that are set to have a fully functional interrupt.\nIF_ALLOC_RM\t\t\tequ\t1\t\t; Allocation of RM was successful.\nIF_SET_VECTORS\t\tequ\t2\t\t; Vectors have been set.\nIF_LOCKED_PM_CODE\tequ\t4\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t8\t\t; Locked PM code for DPMI.\nIF_RATE_CHANGE\t\tequ\t10\t\t; Timer rate was changed.\nIF_FUNCTIONAL\t\tequ\t20\t\t; Timer is in and functional.\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/MCGAPRIM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n\n#ifndef MCGAPRIM_H\n#define MCGAPRIM_H\n\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\nclass GraphicViewPortClass;\nclass GraphicBufferClass;\nclass VideoBufferClass;\n/*=========================================================================*/\n/* Define functions which have not under-gone name mangling\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\t/*======================================================================*/\n\t/* Externs for all of the common functions between the video buffer\t\t*/\n\t/*\t\tclass and the graphic buffer class.\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\textern long MCGA_Size_Of_Region(void *thisptr, int w, int h);\n\n\textern void\tMCGA_Put_Pixel(void * thisptr, int x, int y, unsigned char color);\n\textern int\tMCGA_Get_Pixel(void * thisptr, int x, int y);\n\textern void\tMCGA_Clear(void *thisptr, unsigned char color);\n\textern long\tMCGA_To_Buffer(void *thisptr, int x, int y, int w, int h, void *buff, long size);\n\textern long MCGA_Buffer_To_Page(int x, int y, int w, int h, void *Buffer, void *view);\n\textern BOOL\tLinear_Blit_To_Linear(\tvoid *thisptr, void * dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\t\t\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans);\n\textern BOOL Linear_Scale_To_Linear(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\n\n\textern void\tVesa_Put_Pixel(void * thisptr, int x, int y, unsigned char color);\n\textern int\tVesa_Get_Pixel(void * thisptr, int x, int y);\n\textern void\tVesa_Clear(void *thisptr, unsigned char color);\n\textern long\tVesa_To_Buffer(void *thisptr, int x, int y, int w, int h, void *buff, long size);\n\textern long Vesa_Buffer_To_Page(int x, int y, int w, int h, void *Buffer, void *view);\n\n\textern BOOL\tLinear_Blit_To_Vesa(\t\tvoid *thisptr, void * dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\t\t\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans);\n\textern BOOL\tVesa_Blit_To_Linear(\t\tvoid *thisptr, void * dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\t\t\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans);\n\textern BOOL\tVesa_Blit_To_Vesa(\t\tvoid *thisptr, void * dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\t\t\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans);\n\textern BOOL Linear_Scale_To_Vesa(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\n\textern BOOL Vesa_Scale_To_Linear(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\n\textern BOOL Vesa_Scale_To_Vesa(\t\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\n\textern LONG MCGA_Print(\t\t\t\t\tvoid *thisptr, const char *str, int x, int y, int fcolor, int bcolor);\n\textern LONG Vesa_Print(\t\t\t\t\tvoid *thisptr, const char *str, int x, int y, int fcolor, int bcolor);\n\n\t/*======================================================================*/\n\t/* Externs for all of the graphic buffer class only functions\t\t\t\t*/\n\t/*======================================================================*/\n\textern VOID MCGA_Draw_Line(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color);\n\textern VOID MCGA_Fill_Rect(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color);\n\textern VOID MCGA_Remap(void * thisptr, int sx, int sy, int width, int height, void *remap);\t\n\textern VOID MCGA_Fill_Quad(void * thisptr, VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\tint x2, int y2, int x3, int y3, int color);\n\textern void MCGA_Draw_Stamp(void const *thisptr, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap);\n\n\textern void Shadow_Blit(long int xpix, long int ypix, long int width, long int height, GraphicViewPortClass &src, VideoBufferClass &dst, void *shadowbuff);\n\n//\textern int Get_Standard_Selector(VOID);\n//\textern VOID Set_Selector(UWORD sel);\n#ifdef __cplusplus\n}\n#endif\n\nextern BOOL (*VVPC_Blit_to_GVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nextern BOOL (*VVPC_Blit_to_VVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nextern void (*VVPC_Clear_Func)(void *, unsigned char);\nextern long (*VVPC_To_Buffer_Func)(void *,int x, int y, int w, int h, void *buff, long size);\nextern void (*VVPC_Put_Pixel_Func)(void *,int x, int y, unsigned char color);\nextern int  (*VVPC_Get_Pixel_Func)(void *, int x, int y);\nextern long (*VVPC_Buffer_To_Page)(int x, int y, int w, int h, void *buffer, void *view);\nextern BOOL (*GVPC_Blit_to_VVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nextern BOOL (*VVPC_Blit_to_GVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nextern BOOL (*VVPC_Blit_to_VVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nextern BOOL (*VVPC_Scale_To_GVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\nextern BOOL (*VVPC_Scale_To_VVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\nextern BOOL (*GVPC_Scale_To_VVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\nextern LONG (*VVPC_Print_Func)(void *, const char *, int, int, int, int);\nextern GraphicBufferClass *LogicPage;\n#endif\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/MCGAPRIM.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : MCGAPRIM.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 16, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n; Externs from REGIONSZ.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Size_Of_Region\t:NEAR\n\n; Externs from GETPIX.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Get_Pixel          \t:NEAR\n\n; Externs from VGETPIX.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Get_Pixel          \t:NEAR\n\n; Externs from PUTPIX.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Put_Pixel \t\t:NEAR\n\n; Externs from VPUTTPIX.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Put_Pixel \t\t:NEAR\n\n; Externs from CLEAR.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Clear\t          \t:NEAR\n\n; Externs from VCLEAR.ASM module of the MCGA/SVGAPRIM library\nGLOBAL Vesa_Clear\t\t\t:NEAR\n; Externs from BITBLIT.ASM module of the MCGAPRIM library\nGLOBAL Linear_Blit_To_Linear\t\t:NEAR\n\n; Externs from VBITBLIT.ASM module of the MCGA/SVGAPRIM library\nGLOBAL Linear_Blit_To_Vesa\t\t:NEAR\nGLOBAL Vesa_Blit_To_Linear\t\t:NEAR\nGLOBAL Vesa_Blit_To_Vesa\t\t:NEAR\n\n; Externs from TOBUFF.ASM module of the MCGAPRIM library\nGLOBAL MCGA_To_Buffer\t\t:NEAR\n\n; Externs from VTOBUFF.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_To_Buffer\t\t:NEAR\n\n; Externs from TOPAGE.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Buffer_To_Page\t\t:NEAR\n\n; Externs from VTOPAGE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Buffer_To_Page\t\t:NEAR\n\n; Externs from SCALE.ASM module of the MCGAPRIM library\nGLOBAL Linear_Scale_To_Linear \t:NEAR\n\n; Externs from VSCALE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Linear_Scale_To_Vesa \t\t:NEAR\nGLOBAL Vesa_Scale_To_Linear\t\t:NEAR\nGLOBAL Vesa_Scale_To_Vesa \t\t:NEAR\n\n; Externs from TXTPRNT.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Print\t\t\t:NEAR\n\n; Externs from VTXTPRNT.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Print\t\t\t:NEAR\n\n;*-------------------------------------------------------------------------*\n;* Define MCGA only assembly GLOBALS\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n\n; Externs from DRAWLINE.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Draw_Line \t\t:NEAR\n\n; Externs from FILLQUAD.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Fill_Quad \t\t:NEAR\n\n; Externs from FILLRECT.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Fill_Rect \t\t:NEAR\n\n; Externs from REMAP.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Remap      \t\t:NEAR\n\n; Externs from STAMP.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Draw_Stamp \t\t:NEAR\n\nGLOBAL get_clip\t \t   : NEAR\n\nstruc  RECTANGLE\n\t\t  x0\tdd\t?\n\t\t  y0 dd\t?\n\t\t  x1\tdd\t?\n\t\t  y1 dd ?\nends \t RECTANGLE\n\n\n\n\u001a\n\u001a"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/MEMFLAG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory System                            *\n *                                                                         *\n *                    File Name : MEMFLAG.H                                *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : April 4, 1994                            *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef MEMFLAG_H\n#define MEMFLAG_H\n// Memory Flags\n/*\n**\tMemory allocation flags.  These are the flags that are passed into Alloc\n**\tin order to control the type of memory allocated.\n*/\ntypedef enum {\n\tMEM_NORMAL = 0x0000,\t\t// Default memory (normal).\n\tMEM_NEW\t  = 0x0001,\t\t// Called by the operator new and was overloaded.\n\tMEM_CLEAR  = 0x0002,\t\t// Clear memory before returning.\n\tMEM_REAL   = 0x0004,\t\t// Clear memory before returning.\n\tMEM_TEMP   = 0x0008,\t\t// Clear memory before returning.\n} MemoryFlagType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: ALLOC.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid *Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags);\nvoid Free(void *pointer);\nvoid *Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes);\nlong Ram_Free(MemoryFlagType flag);\nlong Heap_Size(MemoryFlagType flag);\nlong Total_Ram_Free(MemoryFlagType flag);\n\n\ninline void * operator new(size_t size, MemoryFlagType flag) \n{\n\treturn(Alloc(size, flag));\n}\ninline void * operator new[] (size_t size, MemoryFlagType flag)\n{\n\treturn(Alloc(size, flag));\n}\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MEM_COPY.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\textern void Mem_Copy(void *source, void *dest, unsigned long bytes_to_copy);\n\n#ifdef __cplusplus\n}\n#endif\n\n\ninline void *Add_Long_To_Pointer(void const *ptr, long size) \n{\n \treturn ((void *) ( (char const *) ptr + size));\n}\n\nextern void (*Memory_Error)(void);\n\nextern unsigned long MinRam;\t\t// Record of least memory at worst case.\nextern unsigned long MaxRam;\t\t// Record of total allocated at worst case.\n\n\n#endif\n\n\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/MISC.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : 32 bit library                           *\n *                                                                         *\n *                    File Name : MISC.H                                   *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MISC_H\n#define MISC_H\n\n/*========================= C++ Routines ==================================*/\n\n/*=========================================================================*/\n/* The following prototypes are for the file: EXIT.CPP\t\t\t\t\t\t\t*/\n/* Prog_End Must be supplied by the user program in startup.cpp\t\t\t\t*/\n/*=========================================================================*/\nVOID cdecl Prog_End(VOID);\nVOID cdecl Exit(INT errorval, const BYTE *message, ...);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DELAY.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Delay(int duration);\nvoid Vsync(void);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FINDARGV.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nBYTE *cdecl Find_Argv(BYTE const *str);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LIB.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nchar *Find_Argv(char const *str);\nvoid Mono_Mem_Dump(void const *databuf, int bytes, int y);\nvoid Convert_RGB_To_HSV(unsigned int r, unsigned int g, unsigned int b, unsigned int *h, unsigned int *s, unsigned int *v);\nvoid Convert_HSV_To_RGB(unsigned int h, unsigned int s, unsigned int v, unsigned int *r, unsigned int *g, unsigned int *b);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: VERSION.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nBYTE *cdecl Version(VOID);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: IRANDOM.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nint IRandom(int minval, int maxval);\n\n\n/*========================= Assembly Routines ==============================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*=========================================================================*/\n/* The following prototypes are for the file: RANDOM.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nUBYTE Random(VOID);\nint Get_Random_Mask(int maxval);\n\n/*=========================================================================*/\n/* The following prototype is for the file: SHAKESCR.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid Shake_Screen(int shakes);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: REVERSE.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nLONG Reverse_LONG(LONG number);\nWORD Reverse_WORD(WORD number);\nLONG Swap_LONG(LONG number);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FACING8.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint Desired_Facing8(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FACING16.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint Desired_Facing16(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FACINGFF.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint Desired_Facing256(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FADING.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid *Build_Fading_Table(void const *palette, void const *dest, long int color, long int frac);\n\n/*=========================================================================*/\n/* The following prototype is for the file: CRC.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nlong Calculate_CRC(void *buffer, long length);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DETPROC.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern WORD  Processor(VOID);\nextern WORD  Operating_System(VOID);\nextern ULONG random ( ULONG mod )  ;\nextern void  randomize ( void ) ;\n\nextern int Clip_Rect ( int * x , int * y , int * dw , int * dh ,\n\t       \t   \t\t\t int width , int height ) ;          \t\t\t   \nextern int Confine_Rect ( int * x , int * y , int dw , int dh , \n\t      \t      \t\t\t int width , int height ) ;          \t\t   \n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: OPSYS.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern WORD OperationgSystem;\n\t\t\t\t\t\t\t\t\t\t  \n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n\n#endif // MISC_H\n\u001a\n\u001a\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/MONO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Mono Sub-system                          *\n *                                                                         *\n *                    File Name : MONO.H                                   *\n *                                                                         *\n *                   Programmer : Joe Bostic                               *\n *             32Bit Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : March 28, 1994                           *\n *                                                                         *\n *                  Last Update : March 28, 1994   []                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef MONO_H\n#define MONO_H\n\n// C++ Routines\n//==================================================================\n\n// Mono Screen routines\n//==================================================================\nint\tInitialize_Mono_Screen ( void );\n\t\t\t\t\t\t\t   \n\n// C Routines\n//==================================================================\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// Mono Screen routines\n//===================================================================\n\textern\tunsigned\tMonoScreen;\n\textern\tunsigned\tMonoEnabled;\n\t\t\t\n\textern\tvoid Mono_Set_Cursor(int x, int y);\n\textern \tvoid Mono_Clear_Screen(void); \n\textern \tvoid Mono_Scroll(int lines);\n\textern \tvoid Mono_Put_Char(char character, int attrib=2);\n\textern \tvoid Mono_Draw_Rect(int x, int y, int w, int h, int attrib=2, int thick=0);\n\textern\tvoid Mono_Text_Print(void const *text, int x, int y, int attrib=2);\n\textern\tvoid Mono_Print(void const *text);\n\textern \tvoid Mono_View_Page(int page);\n\textern\tint Mono_Printf(char const *string, ...);\n\t\t\t\t\t\t\t\t\n#ifdef __cplusplus\n}\n#endif\n\n\n#endif\n\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/PALETTE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Palette 32bit Library.                   *\n;*                                                                         *\n;*                    File Name : PALETTE.H                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : April 25, 1994                           *\n;*                                                                         *\n;*                  Last Update : April 27, 1994 [BRR]\t\t\t\t\t\t\t*\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef PALETTE_H\n#define PALETTE_H\n\n/*\n********************************* Constants *********************************\n*/\n#define RGB_BYTES\t\t\t3\n#define PALETTE_SIZE\t\t256\n#define PALETTE_BYTES\t768\n\n/*\n******************************** Prototypes *********************************\n*/\n/*\n-------------------------------- Palette.cpp --------------------------------\n*/\nVOID cdecl Set_Palette(VOID *palette);\nVOID cdecl Set_Palette_Color(VOID *palette, WORD color, VOID *data);\nVOID Fade_Palette_To(VOID *palette1, UWORD delay, VOID (*callback)() );\n\n/*\n-------------------------------- loadpal.cpp --------------------------------\n*/\nVOID cdecl Load_Palette(BYTE *palette_file_name, VOID *palette_pointer);\n\n/*\n------------------------------- morphpal.cpp --------------------------------\n*/\nVOID cdecl Morph_Palette (VOID *src_palette, VOID *dst_palette, UWORD delay,\n\tVOID *callback);\n\n/*\n---------------------------------- pal.asm ----------------------------------\n*/\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Set_Palette_Range(VOID *palette);\nextern BOOL Bump_Color(VOID *palette, WORD changable, WORD target);\n\n#ifdef __cplusplus\n}\n#endif\nextern \"C\" extern UBYTE  CurrentPalette[];\t\t/* in pal.asm */\n\n\n#endif // PALETTE_H\n\n/***************************** End of palette.h ****************************/\n\u001a\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/PLAYCD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB\t  \t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : PLAYCD.H\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : STEVE WETHERILL\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Start Date : 5/13/94\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : June 4, 1994   [SW]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*/\n\n#ifndef PLAYCD_H\n#define PLAYCD_H\n\n/* ==================================================================== */\n/* Defines */\n/* ==================================================================== */\n\n#define\tCHLEFT\t0\n#define\tCHRIGHT\t1\n#define\tCHBOTH\t2\n\n#define\tAUDIO_START_MIN\t1\n#define\tAUDIO_START_SEC  44\n\ntypedef struct {\n\t\t\t\t\t  unsigned short seg ;\n \t\t\t\t\t  unsigned short sel ;\n\t\t\t\t\t} SEGSEL ;\n\n\n\n\nextern \"C\" int  DPMI_real_alloc ( UINT , SEGSEL * , USHORT * ) ;\nextern \"C\" int  DPMI_real_free ( SEGSEL  ) ;\nextern \"C\" void DPMI_real_intr ( int , union REGS * , struct SREGS * );\nextern \"C\" void DPMI_real_call ( void * funct , union REGS * , struct SREGS * );\n\n\n\n\n/* ==================================================================== */\n/* Data structures */\n/* ==================================================================== */\n\n// Audio Track Info request block\n\nstruct\tTinfoType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tTrInfo;\n\tUBYTE\t\tTrack;\n\tULONG\t\tStart;\n\tUBYTE\t\tTrCtrl;\n};\n\n// Audio Track Status Control Block\n\nstruct\tStatType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tStatInfo;\n\tUWORD\t\tStat;\n\tULONG\t\tStart;\n\tULONG\t\tEnd;\n\t};\n\n// Audio Track Volume control block\n\nstruct\tVolmType\t{\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tTrInfo;\n\tUBYTE\t\tIn0;\n\tUBYTE\t\tVol0;   \n\tUBYTE\t\tIn1;\n\tUBYTE\t\tVol1;   \n\tUBYTE\t\tIn2;\n\tUBYTE\t\tVol2;   \n\tUBYTE\t\tIn3;\n\tUBYTE\t\tVol3;   \n\t};\n\n// Audio Track Play request block\n\nstruct\tPlayType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tAddrMd;\n\tULONG\t\tStart;\n\tULONG\t\tCntSect;\n\t};\n\n\n// Audio Track Stop request block\n\nstruct\tStopType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\t};\n\n\n/***************************************************************************\n * GetCDClass -- object which will return logical CD drive\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/04/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n\nclass\tGetCDClass {\n\nprotected:\n\n\tunion   REGS \tregs;\n\tstruct SREGS  sregs;\n\n\tSEGSEL \t\tcdDrive_addrp;\n\tUWORD\t\t\tlargestp;\n\tUBYTE\t\t\tcdDrive[26];\t\t// CD Drive letters from MSCDEX\n\t\npublic:\n\n\tGetCDClass(VOID);\t\t\t\t\t// This is the default constructor\n\t~GetCDClass(VOID);\t\t\t\t// This is the destructor\n\n\tWORD  GetCDDrive(VOID);\n\t\n};\n\n\n/***************************************************************************\n * RedBookClass -- adds red book functionality\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tthis class inherits from GetCDClass and adds red book play functionality*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/04/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n\nclass RedBookClass : public GetCDClass {\n\nprivate:\n\n\tSEGSEL\t\tTinfo_addrp;\n\tSEGSEL\t\tStat_addrp;\n\tSEGSEL\t\tStop_addrp;\n\tSEGSEL\t\tVolm_addrp;\n\tSEGSEL  \t   Play_addrp;\n\n\tStopType \tStop;\n\tPlayType\t\tPlay;\n\tVolmType\t\tVolm;\n\tStatType\t\tStat;\n\tTinfoType\tTinfo;\n\npublic:\n\n\tRedBookClass(VOID);\t\t\t\t\t// This is the default constructor\n\t~RedBookClass(VOID);\t\t\t\t\t// This is the destructor\n\n\tULONG\tRedToHS(ULONG i);\n\tULONG MSFtoRed(UBYTE m, UBYTE s, UBYTE f);\n\tVOID  FullCDVolume(UBYTE chan);\n\tVOID  PlayTrack(UWORD track);\n\tVOID  Play_CD_MSL(UWORD min_sec, UWORD len);\n\tVOID  PlayMSF(UBYTE startM, UBYTE startS, UBYTE startF, \n\t\t\t\tUBYTE endM, UBYTE endS, UBYTE endF, UBYTE chan);\n\tUWORD CheckCDMusic(VOID);\n\tVOID  StopCDMusic(VOID);\n\n};\n\n\n/***************************** End of Playcd.h ****************************/\n\n#endif // PLAYCD_H\n\u001a\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/SHAPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32                                  *\n *                                                                         *\n *                    File Name : SHAPE.H                                  *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : May 25, 1994                             *\n *                                                                         *\n *                  Last Update : September 14, 1994   [IML]               *\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef SHAPE_H\n#define SHAPE_H\n\n#ifndef GBUFFER_H\n#include \"gbuffer.h\"\n#endif\n/*\n*********************************** Types ***********************************\n*/\n/*\n--------------------------- Shape creation flags ----------------------------\n*/\ntypedef enum {\n\tMAKESHAPE_NORMAL\t = 0x0000,\t// 256-color compressed shape\n\tMAKESHAPE_COMPACT  = 0x0001,\t// 16-color shape (with built-in color table)\n\tMAKESHAPE_NOCOMP\t = 0x0002,\t// Uncompressed shape\n\tMAKESHAPE_VARIABLE =\t0x0004\t// <16-color shape\n} MakeShapeFlags_Type;\n\n/*---------------------------------------------------------------------------\nShape drawing flags:\n- The low byte is for coordinate transformations.\n- The high byte is for drawing effects.\n---------------------------------------------------------------------------*/\ntypedef enum {\n\tSHAPE_NORMAL \t\t\t= 0x0000,\t\t// Standard shape\n\tSHAPE_HORZ_REV \t\t= 0x0001,\t\t// Flipped horizontally\n\tSHAPE_VERT_REV \t\t= 0x0002,\t\t// Flipped vertically\n\tSHAPE_SCALING \t\t\t= 0x0004,\t\t// Scaled (WORD scale_x, WORD scale_y)\n\tSHAPE_VIEWPORT_REL \t= 0x0010,\t\t// Coords are window-relative \n\tSHAPE_WIN_REL \t\t\t= 0x0010,\t\t// Coordinates are window relative instead of absolute.\n\tSHAPE_CENTER \t\t\t= 0x0020,\t\t// Coords are based on shape's center pt\n\tSHAPE_FADING \t\t\t= 0x0100,\t\t// Fading effect (VOID * fading_table, \n\t\t\t\t\t\t\t\t\t\t\t\t\t//  WORD fading_num)\n\tSHAPE_PREDATOR \t\t= 0x0200,\t\t// Transparent warping effect\n\tSHAPE_COMPACT \t\t\t= 0x0400,\t\t// Never use this bit \n\tSHAPE_PRIORITY \t\t= 0x0800,\t\t// Use priority system when drawing\n\tSHAPE_GHOST\t\t\t\t= 0x1000,\t\t// Shape is drawn ghosted\n\tSHAPE_SHADOW\t\t\t= 0x2000,\n\tSHAPE_PARTIAL  \t\t= 0x4000,\n\tSHAPE_COLOR \t\t\t= 0x8000\t\t\t// Remap the shape's colors \n\t\t\t\t\t\t\t\t\t\t\t\t\t//  (VOID * color_table)\n} ShapeFlags_Type;\n\n/*\n------------------------------- Shape header --------------------------------\n*/\ntypedef struct {\n\tUWORD\t\tShapeType;\t\t\t// 0 = normal, 1 = 16 colors, \n\t\t\t\t\t\t\t\t\t\t//  2 = uncompressed, 4 = \t<16 colors\n\tUBYTE\t\tHeight;\t\t\t\t// Height of the shape in scan lines\n\tUWORD\t\tWidth;\t\t\t\t// Width of the shape in bytes\n\tUBYTE\t\tOriginalHeight;\t// Original height of shape in scan lines\n\tUWORD\t\tShapeSize;\t\t\t// Size of the shape, including header\n\tUWORD\t\tDataLength;\t\t\t// Size of the uncompressed shape (just data)\n\tUBYTE\t\tColortable[16];\t// Optional color table for compact shape\n} Shape_Type;\n\n/*\n------------------------------- Shape block ---------------------------------\n*/\ntypedef struct {\n\tUWORD\t\tNumShapes;\t\t\t// number of shapes in the block\n\tLONG\t\tOffsets[];\t\t\t// array of offsets to shape data\n\t\t\t\t\t\t\t\t\t\t//  (offsets within the shape block, with\n\t\t\t\t\t\t\t\t\t\t//  0 being the first offset value, not the\n\t\t\t\t\t\t\t\t\t\t//  start of the shape block)\n} ShapeBlock_Type;\n\n\n/*\n******************************** Prototypes *********************************\n*/\n\n/*\n-------------------------------- prioinit.c ---------------------------------\n*/\n\nextern \"C\" {\nextern VOID  *MaskPage;\nextern VOID  *BackGroundPage;\nextern LONG  _ShapeBufferSize;\nextern BYTE  *_ShapeBuffer;\n}\n\n\nVOID cdecl Init_Priority_System (GraphicBufferClass *mask,\n\t\t\t\t\t\t\t\t\t\t\tGraphicBufferClass *back);\n\n\n/*\n-------------------------------- drawshp.asm --------------------------------\n*/\n\nextern \"C\" {\nWORD Draw_Shape(GraphicViewPortClass *gvp, VOID const *shape, LONG x, LONG y, LONG flags, ...);\n}\n\n/*\n---------------------------------- shape.c ----------------------------------\n*/\nshort cdecl Get_Shape_Data(VOID const *shape, WORD data);\nint cdecl Extract_Shape_Count(VOID const *buffer);\nvoid * cdecl Extract_Shape(VOID const *buffer, int shape);\nint cdecl Restore_Shape_Height(VOID *shape);\nint cdecl Set_Shape_Height(VOID const *shape, WORD newheight);\n\nextern \"C\" {\nint Get_Shape_Width(VOID const *shape);\nint Get_Shape_Height(VOID const *shape);\nint Get_Shape_Original_Height(VOID const *shape);\nint Get_Shape_Uncomp_Size(VOID const *shape);\n}\n\n\n/*\n------------------------------- setshape.asm --------------------------------\n*/\nextern \"C\" {\nVOID Set_Shape_Buffer(void const *buffer, int size);\n}\n/*\n------------------------------- shapeinf.asm --------------------------------\n*/\nWORD cdecl Get_Shape_Flags(VOID const *shape);\nint  cdecl Get_Shape_Size(VOID const *shape);\nint  cdecl Get_Shape_Scaled_Width(VOID const *shape, WORD scale);\nint  cdecl Get_Shape_Scaled_Height(VOID const *shape, WORD scale);\n\n#endif // SHAPE_H\n\n/****************************** End of shape.h *****************************/\n\u001a\n\u001a\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/SHAPE.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : WWLIB32                                  *\n;*                                                                         *\n;*                    File Name : SHAPE.INC                                *\n;*                                                                         *\n;*                   Programmer : Scott Bowen\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : May 25, 1994                             *\n;*                                                                         *\n;*                  Last Update : September 14, 1994   [IML]               *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;****************************** Equates ************************************\n;\n\n\n\n\n\n\n;............................ Shape Types ..................................\n;\nTRUE\tequ\t1\t\t\t; Boolean 'true' value\nFALSE\tequ\t0\t\t\t; Boolean 'false' value\n\nMAKESHAPE_NORMAL\t\tEQU\t0\t; 256-color compressed shape\nMAKESHAPE_COMPACT\t\tEQU\t1\t; 16-color shape (built-in color table)\nMAKESHAPE_NOCOMP\t\tEQU\t2\t; non-wwcomped shape\nMAKESHAPE_VARIABLE\tEQU\t4\t; <16-color shape with variable #\n\t\t\t\t\t; of colors (ColorTable[0] = # of colors)\n; old names:\n;COLOR_SHAPE\t\tEQU\t1\t; flag which determines a color shape\n;NORM_SHAPE\t\t\tEQU\t2\t; flag that indicates non wwcomped shp\n;NORM_SHAPE_16\t\tEQU\t4\t; flag that tells us if we have a variable sized table\n\t\t\t\t\t;  variable sized table\n;\n;...........................................................................\n; Drawing flags:\n; The low byte is for coordinate transformations.\n; The high byte is for drawing effects.\n;...........................................................................\n;\nSHAPE_NORMAL\t\t\tEQU\t0000h\t; no options; just a copy\nSHAPE_HORZ_REV\t\t\tEQU\t0001h\t; reverse horizontally\nSHAPE_VERT_REV\t\t\tEQU\t0002h\t; reverse vertically\nSHAPE_SCALING\t\t\tEQU\t0004h\t; scale\nSHAPE_VIEWPORT_REL\tEQU\t0010h\t; viewport-relative coordinates\nSHAPE_CENTER\t\t\tEQU\t0020h\t; use centered coordinates\nSHAPE_FADING\t\t\tEQU\t0100h\t; fading effect shape\nSHAPE_PREDATOR\t\t\tEQU\t0200h\t; predator effect shape\nSHAPE_COMPACT\t\t\tEQU\t0400h\t; shape is in 16 colors\nSHAPE_PRIORITY\t\t\tEQU\t0800h\t; priority draw shape\nSHAPE_GHOST\t\t\t\tEQU\t1000h\t; ghosting effect\nSHAPE_SHADOW\t\t\tEQU\t2000h\t; shadow effect\nSHAPE_PARTIAL\t\t\tEQU\t4000h\t; partial predator effect\nSHAPE_COLOR\t\t\t\tEQU\t8000h\t; use alternative color table effect\n\nSHAPE_EFFECTS\t\t\tEQU    03F00h\t; shape effect flags \n\n;\n;.......................... Shadow Effect ..................................\n;\nSHADOW_COL\t\tEQU\t00FFh\t; magic number for shadows\n\n;......................... Priority System .................................\n;\nCLEAR_UNUSED_BITS  \tEQU\t0007h\t; and with 0000-0111 to clear \n\t\t\t\t\t;  non-walkable high bit and\n\t\t\t\t\t;  scaling id bits\nNON_WALKABLE_BIT  \tEQU\t0080h\t; and with 1000-0000 to clear all \n\t\t\t\t\t;  but non-walkable bit\n;\n;......................... Predator Effect .................................\n;\nPRED_MASK\t\tEQU\t0007h\t; mask used for predator pixel puts\n\n;---------------------------------------------------------------------------\n; This table is a list of the local stack variables in the function\n; Draw_Shape.  Many other functions in other modules access these variables\n; on the stack.  Since the BP is not changed when these other functions are\n; called by Draw_Shape (possibly indirectly), they can also access these\n; stack varibles.  When adding or removing from the table, one must be very\n; careful to change the offsets.  \n;---------------------------------------------------------------------------\n;.......................... proc addresses .................................\nLSkipRout\tEQU DWORD PTR ebp - 04h\t\t;DWORD  pointer to the skip routine\nRSkipRout\tEQU DWORD PTR ebp - 08h\t\t;DWORD  pointer to the skip routine\nDrawRout\tEQU DWORD PTR ebp - 0Ch\t\t\t;DWORD  pointer to the draw routine\n;........................ optional arguments ...............................\nColorTable\tEQU DWORD PTR ebp - 10h\t\t;DWORD\tptr to the shapes color table\nFadingTable\tEQU DWORD PTR ebp - 14h\t\t;DWORD  ptr to the fading table\n\nFadingNum\tEQU DWORD PTR ebp - 18h\t\t;DWORD  number of times to fade\nIsTranslucent\tEQU DWORD PTR ebp - 1Ch\t;DWORD\tptr to is_translucent table\nTranslucent\tEQU DWORD PTR ebp - 20h\t\t;DWORD\tptr to actual translucent tbl\nPriLevel\tEQU BYTE  PTR ebp - 24h\t\t\t;BYTE\tpriority level of the object \nScaleX\t\tEQU DWORD PTR ebp - 28h\t\t;DWORD  the x increment to scale by\nScaleY\t\tEQU DWORD PTR ebp - 2Ch\t\t;DWORD  the y increment to scale by\nShadowingTable\tEQU DWORD PTR ebp - 30h\t;DWORD\tptr to the shadowing table\n;........................ Shape header values ..............................\nShapeType\tEQU DWORD PTR ebp - 34h \t;DWORD\tshape type\nShapeWidth\tEQU DWORD PTR ebp - 38h \t;DWORD\tshape's unscaled width\nShapeHeight\tEQU DWORD PTR ebp - 3Ch \t;DWORD\tshape's unscaled height\nUncompDataLen\tEQU DWORD PTR ebp - 40h ;DWORD\tuncompressed data length\nShapeData\tEQU DWORD PTR ebp - 44h \t;DWORD\tpointer to shape data\n;...................... Scaled shape dimensions ............................\nScaledWidth\tEQU DWORD PTR ebp - 48h \t;DWORD\tshape's scaled width\nScaledHeight\tEQU DWORD PTR ebp - 4Ch ;DWORD\tshape's scaled height\n;...................... Pixel clipping variables ...........................\nLeftClipPixels\tEQU DWORD PTR ebp - 50h ;DWORD\t# left-clipped pixels\nRightClipPixels\tEQU DWORD PTR ebp - 54h ;DWORD\t# right-clipped pixels\nTopClipPixels\tEQU DWORD PTR ebp - 58h ;DWORD\t# top-clipped pixels\nBotClipPixels\tEQU DWORD PTR ebp - 5Ch ;DWORD\t# bottom-clipped pixels\nPixelWidth\tEQU DWORD PTR ebp - 60h \t;DWORD\tdrawable area in pixels\nPixelHeight\tEQU DWORD PTR ebp - 64h \t;DWORD\tdrawable area in pixels\n;......................... Drawing variables ...............................\nNumColors\tEQU DWORD PTR ebp - 68h ;DWORD\t# colors for 16-color shapes\nStartDraw\tEQU DWORD PTR ebp - 6Ch ;DWORD\toffset of drawing start pos\nNextLine\tEQU DWORD PTR ebp - 70h ;DWORD\toffset of next drawing line\nLeftClipBytes\tEQU DWORD PTR ebp - 74h ;DWORD\t# left-clipped bytes\nXTotal\t\tEQU DWORD PTR ebp - 78h ;DWORD\taccumulated x-pixels\nXTotalInit\tEQU DWORD PTR ebp - 7Ch ;DWORD\tinitial roundoff for XTotal\nYTotal\t\tEQU DWORD PTR ebp - 80h ;DWORD\taccumulated y-pixels\nHeightCount\tEQU DWORD PTR ebp - 84h ;DWORD\tht counter for drawing lines\nLineStart\tEQU DWORD PTR ebp - 88h ;DWORD\taddress of start of line\nWidthCount\tEQU DWORD PTR ebp - 8Ch ;DWORD\tcounts down # bytes skipped\nStashReg\tEQU DWORD PTR ebp - 90h \t;DWORD\ttemp variable for draw routines\nMaskAdjust\tEQU DWORD PTR ebp - 94h ;DWORD  priority buffer offset\nBackAdjust\tEQU DWORD PTR ebp - 98h ;DWORD  background buffer offset\nStashECX\tEQU DWORD PTR ebp - 9Ch \t;DWORD  temp variable for ECX register\nStashEDX\tEQU DWORD PTR ebp -0A0h \t;DWORD  temp variable for EDX register\n\nLocal_Size\tEQU 00A4h\t\t; Amt of data on stack: 4+last offset\n\n;****************************** Declarations *******************************\n;---------------------------------------------------------------------------\n; Global variables used by the shape routines, defined in drawshp.asm\n;---------------------------------------------------------------------------\nGLOBAL _ShapeBuffer:DWORD\nGLOBAL _ShapeBufferSize:DWORD\nGLOBAL _MaskPage:DWORD\nGLOBAL _BackGroundPage:DWORD\nGLOBAL PredCount:DWORD\nGLOBAL PredTable:BYTE\nGLOBAL PredValue:DWORD\nGLOBAL PartialPred:DWORD\nGLOBAL PartialCount:DWORD\nGLOBAL Flags:DWORD\n\n;---------------------------------------------------------------------------\n; External tables that are defined in ds_table.asm.\n;---------------------------------------------------------------------------\nGLOBAL LSkipTable:DWORD\nGLOBAL RSkipTable:DWORD\nGLOBAL DrawTable:DWORD \n\n;------------------------------------------------------------------------------\n; Public functions, declared in the order they appear in the function tables.\n;--------------------------------------------------------------------------------\nGLOBAL\tC Not_Supported:NEAR\n;\tLSkipTable:\nGLOBAL Left_Skip:NEAR\t\t\t\t\t\t; ds_ls\nGLOBAL Left_Reverse_Skip:NEAR\t\t\t\t; ds_lrs\nGLOBAL Left_Skip:NEAR\t\t\t\t\t\t; ds_ls\nGLOBAL Left_Reverse_Skip:NEAR\t\t\t\t; ds_lrs\nGLOBAL Left_Scale_Skip:NEAR\t\t\t\t; ds_lss\nGLOBAL Left_Scale_Reverse_Skip:NEAR\t\t; ds_lsrs\nGLOBAL Left_Scale_Skip:NEAR\t\t\t\t; ds_lss\nGLOBAL Left_Scale_Reverse_Skip:NEAR\t\t; ds_lsrs\n\n;\tRSkipTable:\nGLOBAL Right_Skip:NEAR\t\t\t\t\t   ; ds_rs\nGLOBAL Right_Reverse_Skip:NEAR\t\t\t; ds_rrs\nGLOBAL Right_Skip:NEAR\t\t\t\t\t   ; ds_rs\nGLOBAL Right_Reverse_Skip:NEAR\t\t\t; ds_rrs\nGLOBAL Right_Scale_Skip:NEAR\t\t\t\t; ds_rss\nGLOBAL Right_Scale_Reverse_Skip:NEAR\t; ds_rsrs\nGLOBAL Right_Scale_Skip:NEAR\t\t\t\t; ds_rss\nGLOBAL Right_Scale_Reverse_Skip:NEAR\t; ds_rsrs\n\n;\tDrawTable:\nGLOBAL Draw_Normal:NEAR\t\t\t\t\t; ds_dn\nGLOBAL Draw_Reverse:NEAR\t\t\t\t; ds_dr\nGLOBAL Draw_Normal:NEAR\t\t\t\t\t; ds_dn\nGLOBAL Draw_Reverse:NEAR\t\t\t\t; ds_dr\nGLOBAL Draw_Scale:NEAR\t\t\t\t\t; ds_ds\nGLOBAL Draw_Scale_Reverse:NEAR\t\t; ds_dsr\nGLOBAL Draw_Scale:NEAR\t\t\t\t\t; ds_ds\nGLOBAL Draw_Scale_Reverse:NEAR\t\t; ds_dsr\n\n\n;************************* End of shape.inc ********************************\n\u001a\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/SOS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sos.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DEFINED   \n#define  _SOS_DEFINED   \n#include \"sosdefs.h\"\n\n#pragma pack(4)\n \n// error definition for sound operating system  \n#define  _SOS_ERR          -1\n\n// number of drivers allowed to be open at one time\n#define  _SOS_MAX_DRIVERS  5\n\n// structure definition for the capabilities\ntypedef struct _tagCAPABILITIES\n{\n   BYTE  szDeviceName[ 32 ];  // device name\n   WORD  wDeviceVersion;      // device version\n   WORD  wBitsPerSample;      // bits per sound sample\n   WORD  wChannels;           // stereo/mono sound card\n   WORD  wMinRate;            // minimum rate\n   WORD  wMaxRate;            // maximum rate\n   WORD  wMixerOnBoard;       // board contains mixer\n   WORD  wMixerFlags;         // mixer capabilities\n   WORD  wFlags;              // miscellaneous flags   \n   short far * lpPortList;         // list of usable ports\n   short far * lpDMAList;          // list of usable dma channels\n   short far * lpIRQList;          // list of usable irq channels\n   short far * lpRateList;         // list of usable rates, -1 if any in min to max\n   WORD  fBackground;         // foreground or background driver\n   WORD  wDeviceID;           // ID for the device\n   WORD  wTimerID;            // ID for the timer\n   \n} _SOS_CAPABILITIES; \n\n// far pointer to the device capabilities structure\ntypedef _SOS_CAPABILITIES far *  LPSOSDEVICECAPS;\n\n// flag types for driver\n#define  _FLAGS_SIGNED              0x8000\n  \n// devices that can be loaded\n#define  _SOUND_BLASTER_8_MONO      0xe000\n#define  _SOUND_BLASTER_8_ST        0xe001\n#define  _SBPRO_8_ST                _SOUND_BLASTER_8_ST\n#define  _SBPRO_8_MONO              0xe00f\n#define  _SOUND_MASTER_II_8_MONO    0xe002\n#define  _MV_PAS_8_MONO             0xe003\n#define  _MV_PAS_16_MONO            0xe004\n#define  _MV_PAS_8_ST               0xe005\n#define  _MV_PAS_16_ST              0xe006\n#define  _ADLIB_GOLD_8_ST           0xe007\n#define  _ADLIB_GOLD_16_ST          0xe008\n#define  _ADLIB_GOLD_8_MONO         0xe009\n#define  _ADLIB_GOLD_16_MONO        0xe00a\n#define  _MICROSOFT_8_MONO          0xe00b\n#define  _MICROSOFT_8_ST            0xe00c\n#define  _MICROSOFT_16_MONO         0xe00d\n#define  _MICROSOFT_16_ST           0xe00e\n#define  _SOUND_SOURCE_8_MONO_PC    0xe010\n#define  _SOUND_SOURCE_8_MONO_TANDY 0xe011\n#define  _GENERAL_PORT_8_MONO       0xe012\n#define  _GENERAL_PORT_8_MONO_R     0xe013\n#define  _SIERRA_8_MONO             0xe014\n#define  _SB16_8_MONO               0xe015\n#define  _SB16_8_ST                 0xe016\n#define  _SB16_16_MONO              0xe017\n#define  _SB16_16_ST                0xe018\n#define  _ESS_AUDIODRIVE_8_MONO     0xe019\n#define  _ESS_AUDIODRIVE_8_ST       0xe01a\n#define  _ESS_AUDIODRIVE_16_MONO    0xe01b\n#define  _ESS_AUDIODRIVE_16_ST      0xe01c\n#define  _SOUNDSCAPE_8_MONO         0xe01d\n#define  _SOUNDSCAPE_8_ST           0xe01e\n#define  _SOUNDSCAPE_16_MONO        0xe01f\n#define  _SOUNDSCAPE_16_ST          0xe020\n#define  _RAP10_8_MONO              0xe021\n#define  _RAP10_16_MONO             0xe022\n#define  _GUS_8_MONO                0xe023\n#define  _GUS_8_ST                  0xe024\n#define  _GUS_16_MONO               0xe025\n#define  _GUS_16_ST                 0xe026\n#define  _GUS_MAX_8_MONO            0xe027\n#define  _GUS_MAX_8_ST              0xe028\n#define  _GUS_MAX_16_MONO           0xe029\n#define  _GUS_MAX_16_ST             0xe02a\n#define  _WAVEJAMMER_8_MONO         0xe02b\n#define  _WAVEJAMMER_8_ST           0xe02c\n#define  _WAVEJAMMER_16_MONO        0xe02d\n#define  _WAVEJAMMER_16_ST          0xe02e\n#define  _TEMPOCS_8_MONO            0xe02f\n#define  _TEMPOCS_8_ST              0xe030\n#define  _TEMPOCS_16_MONO           0xe031\n#define  _TEMPOCS_16_ST             0xe032\n#define  _WAVEJAMMERCD_8_MONO       0xe033\n#define  _WAVEJAMMERCD_8_ST         0xe034\n#define  _WAVEJAMMERCD_16_MONO      0xe035\n#define  _WAVEJAMMERCD_16_ST        0xe036\n#define  _SOUND_BLASTER_8_MONO_R    0xe050\n#define  _MICROSOFT_8_MONO_R        0xe051\n#define  _SOUND_MASTER_II_8_MONO_R  0xe052\n#define  _ADLIB_GOLD_8_MONO_R       0xe053\n#define  _MV_PAS_8_MONO_R           0xe054\n#define  _RAP10_8_MONO_R            0xe058\n#define  _RAP10_16_MONO_R           0xe059\n#define  _SB16_8_MONO_R             0xe05a\n#define  _SB16_8_ST_R               0xe05b\n#define  _SB16_16_MONO_R            0xe05c\n#define  _SB16_16_ST_R              0xe05d\n#define  _MV_PAS_16_MONO_R          0xe060\n#define  _SOUNDSCAPE_8_MONO_R       0xe061\n#define  _SOUNDSCAPE_8_ST_R         0xe062\n#define  _SOUNDSCAPE_16_MONO_R      0xe063\n#define  _SOUNDSCAPE_16_ST_R        0xe064\n#define  _ESS_AUDIODRIVE_8_MONO_R   0xe065\n#define  _ESS_AUDIODRIVE_8_ST_R     0xe066\n#define  _ESS_AUDIODRIVE_16_MONO_R  0xe067\n#define  _ESS_AUDIODRIVE_16_ST_R    0xe068\n#define  _SPEECH_THING_8_MONO       0xe090\n#define  _YAMAHA_8_MONO             0xe106\n#define  _INT_SPEAKER_8_MONO        0xe107\n\n// call indexes for the loadable drivers\nenum\n{ \n   _DRV_INIT,\n   _DRV_UNINIT,\n   _DRV_SETRATE,\n   _DRV_SETACTION,\n   _DRV_START,\n   _DRV_STOP,\n   _DRV_PAUSE,\n   _DRV_RESUME,\n   _DRV_CAPABILITIES,\n   _DRV_PLAY_FOREGROUND,\n   _DRV_GET_FILL_INFO, \n   _DRV_GET_CALL_FUNCTIONS,\n   _DRV_SET_CALL_FUNCTIONS\n};\n\n// fill info\ntypedef  struct   _tagFillInfo\n         {\n\n            LPSTR lpFillHandler;                   // pointer to fill handler\n            LPWORD lpDMAFillCount;                 // pointer to dma count\n            LPSTR lpSampleList;                    // pointer to sample list\n            LPWORD lpDMAMasterVolume;              // pointer to dma count\n\n         } _SOS_FILL_INFO;\n\n// caps info structure\ntypedef  struct   _tagCapsInfo\n         {\n\n            LPSTR    lpPortList;                   // pointer to port list\n            LPSTR    lpDMAList;                    // pointer to DMA list\n            LPSTR    lpIRQList;                    // pointer to IRQ list\n            LPSTR    lpRateList;                   // pointer to rate list\n\n         } _SOS_CAPS_INFO;\n\n// maximum number of available voice\n#define  _MAX_VOICES    32\n\n// structure definition\ntypedef  struct   _tagSAMPLE\n{\n   LPSTR    samplePtr;                 // pointer to data buffer\n   LPSTR    sampleData;                // pointer to active data\n   LPSTR    sampleLoopPtr;             // pointer for loop back\n\n   WORD     sampleLength;              // length of sample\n   WORD     sampleIndex;               // index into sample\n   WORD     sampleLoopLength;          // length of loop\n   \n   WORD     sampleBytesLeft;           // bytes left to play in sample\n\n   WORD     sampleLoopPoint;           // byte count for loop point\n   WORD     sampleLoopEndLength;       // length of remaining chunk\n\n   short    sampleFlags;               // control sample\n   short    sampleVolume;              // volume control\n   short    sampleID;                  // sample ID\n\n   short    sampleChannel;             // channel to play sample on\n   short    sampleLoopCount;           // loop count\n   short    sampleLastFill;            // last fill position\n   VOID ( far cdecl * sampleCallback )( WORD, WORD, WORD ); // callback function for sample\n\n   WORD     samplePitchAdd;\n   short    samplePitchFraction;\n\n   short    samplePort;                // port to use for non-dma digitized\n\n   WORD     sampleTotalBytes;\n   WORD     sampleByteLength;\n\n   short    samplePanLocation;\n   short    samplePanSpeed;\n   short    samplePanDirection;\n   short    samplePanStart;\n   short    samplePanEnd;\n   \n   short    sampleDelayBytes;\n   short    sampleDelayRepeat;\n   \n   WORD     sampleADPCMPredicted;\n   short    sampleADPCMIndex;\n\n   short    sampleRootNoteMIDI;   \n\n   WORD  sampleTemp1;   \n   \n} _SOS_SAMPLE;\n\n// enumeration for left or right channel\nenum\n{\n   _LEFT_CHANNEL,\n   _RIGHT_CHANNEL,\n   _CENTER_CHANNEL,\n   _INTERLEAVED\n};\n\n// enumeration for foreground and background\nenum\n{ \n   _FOREGROUND,\n   _BACKGROUND \n};\n\n// defines for the sample flags\n#define  _ACTIVE           0x8000\n#define  _LOOPING          0x4000\n#define  _FIRST_TIME       0x2000\n#define  _PENDING_RELEASE  0x1000\n#define  _CONTINUE_BLOCK   0x0800\n#define  _PITCH_SHIFT      0x0400\n#define  _PANNING          0x0200\n#define  _VOLUME           0x0100\n#define  _TRANSLATE16TO8   0x0080\n#define  _STAGE_LOOP       0x0040\n#define  _TRANSLATE8TO16   0x0020\n#define  _STEREOTOMONO     0x0010\n\n// defines for the wParam flags \n#define  _SINGLE_SAMPLE 0x01\n\n#define  _SOS_DCAPS_AUTO_REINIT     0x01\n#define  _SOS_DCAPS_MPU_401         0x02\n#define  _SOS_DCAPS_OPL2            0x04\n#define  _SOS_DCAPS_OPL3            0x08\n#define  _SOS_DCAPS_OPL4            0x10\n#define  _SOS_DCAPS_WAVETABLE       0x20\n#define  _SOS_DCAPS_DL_SAMPLES      0x40\n#define  _SOS_DCAPS_FIFO_DEVICE     0x80\n#define  _SOS_DCAPS_ENV_NEEDED      0x100\n#define  _SOS_DCAPS_PSEUDO_DMA1     0x200\n#define  _SOS_DCAPS_SIGNED_DATA     0x8000\n\n// file header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // number of drivers in the file\n   WORD  wDrivers;\n\n   // offset of first driver\n   WORD  lOffset;\n\n   // size of the file\n   WORD  lFileSize;\n\n} _FILEHEADER;\n\n// driver header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // offset of next driver\n   WORD  lNextDriver;\n\n   // size of current driver\n   WORD  wSize;\n\n   // id for the current device\n   WORD  wDeviceID;\n\n   // id for the type of DOS extender\n   WORD  wExtenderType;\n\n} _DRIVERHEADER;\n\n// device hardware information\ntypedef struct\n{\n   // port to be used\n   WORD  wPort;\n\n   // irq to use\n   WORD  wIRQ;\n\n   // dma channel to se\n   WORD  wDMA; \n  \n   // extra parameter\n   WORD  wParam;\n\n} _SOS_HARDWARE;\n\n// structure definition for start sample\ntypedef struct\n{\n   // pointer to sample\n   LPSTR lpSamplePtr;\n\n   // size of the sample\n   WORD  dwSampleSize;\n\n   // number of times to loop the sample -1 is infinite\n   WORD  wLoopCount;\n\n   // channel to play sample on\n   WORD  wChannel;\n\n   // volume to play sample at\n   WORD wVolume;\n\n   // id for the sample\n   WORD  wSampleID;\n\n   // far pointer to the callback function\n   VOID ( far cdecl *lpCallback )( WORD, WORD, WORD );\n\n   // port to use if driver is a non-dma background driver\n   WORD  wSamplePort; \n\n   // flags field\n   WORD  wSampleFlags;\n\n   // total length of sample including loops, etc..\n   WORD     dwSampleByteLength;\n\n   // loop point for the sample\n   WORD  dwSampleLoopPoint;\n   WORD  dwSampleLoopLength;\n\n   // pitch shifting components \n   WORD     dwSamplePitchAdd;\n   WORD    wSamplePitchFraction;\n\n   // pan components\n   WORD    wSamplePanLocation;\n   WORD    wSamplePanSpeed;\n   WORD    wSamplePanDirection;\n   WORD    wSamplePanStart;\n   WORD    wSamplePanEnd;\n   \n   // delay parts\n   WORD    wSampleDelayBytes;\n   WORD    wSampleDelayRepeat;\n\n   // compression components   \n   WORD     dwSampleADPCMPredicted;\n   WORD    wSampleADPCMIndex;\n\n   // root note for pitch shifting \n   WORD    wSampleRootNoteMIDI;   \n\n   // filler for future upgrades\n   WORD  dwSampleTemp1;   \n   WORD  dwSampleTemp2;   \n   WORD  dwSampleTemp3;   \n\n} _SOS_START_SAMPLE;\n\n// structure for initializing a driver\ntypedef struct\n{  \n   WORD  wBufferSize;\n   LPSTR lpBuffer;\n   BOOL  wAllocateBuffer;\n   WORD  wSampleRate;\n   WORD  wParam;\n   LONG  dwParam;\n   VOID ( far *lpFillHandler )( VOID );\n   LPSTR lpDriverMemory;\n   LPSTR lpDriverMemoryCS;\n   LPSTR lpTimerMemory;\n   LPSTR lpTimerMemoryCS;\n   WORD  wTimerID;\n   WORD  wPhysical;\n\n} _SOS_INIT_DRIVER;\n\n// define for the timer types to use\n#define  _SOS_NORMAL_TIMER          0x00\n\n// enumeration for the timer types\nenum\n{\n   _TIMER_8_MONO   =     0x1000,\n   _TIMER_8_ST,          \n   _TIMER_16_MONO,       \n   _TIMER_16_ST,         \n   _TIMER_8_MONO_ULAW,  \n   _TIMER_8_ST_ULAW,    \n   _TIMER_16_MONO_ULAW, \n   _TIMER_16_ST_ULAW,   \n   _TIMER_8_MONO_REC,   \n   _TIMER_8_MONO_ULAW_REC,\n   _TIMER_UNDEFINED_1,      \n   _TIMER_UNDEFINED_2,\n   _TIMER_UNDEFINED_3,\n   _TIMER_UNDEFINED_4,\n   _TIMER_UNDEFINED_5,\n   _TIMER_UNDEFINED_6,\n   _TIMER_UNDEFINED_7,\n   _TIMER_UNDEFINED_8,\n   _TIMER_UNDEFINED_9,\n   _TIMER_UNDEFINED_A,\n   _TIMER_UNDEFINED_B,\n   _TIMER_UNDEFINED_C,\n   _TIMER_UNDEFINED_D,\n   _TIMER_UNDEFINED_E,\n   _TIMER_UNDEFINED_F,\n   _TIMER_UNDEFINED_10,\n   _TIMER_UNDEFINED_11,\n   _TIMER_UNDEFINED_12,\n   _TIMER_UNDEFINED_13,\n   _TIMER_UNDEFINED_14,\n   _TIMER_UNDEFINED_15,\n   _TIMER_UNDEFINED_16,\n   _TIMER_8_SOUND_SOURCE,\n   _TIMER_8_SOUND_SOURCE_TANDY,\n   _TIMER_8_GENERAL_PORT,\n   _TIMER_8_GENERAL_PORT_REC   \n};\n\n// define for no slots available\n#define  _ERR_NO_SLOTS ( WORD )-1\n\n// error codes for the system\nenum\n{\n   _ERR_NO_ERROR,\n   _ERR_DRIVER_NOT_LOADED,\n   _ERR_INVALID_POINTER,\n   _ERR_DETECT_INITIALIZED,\n   _ERR_FAIL_ON_FILE_OPEN,\n   _ERR_MEMORY_FAIL,\n   _ERR_INVALID_DRIVER_ID,\n   _ERR_NO_DRIVER_FOUND,\n   _ERR_DETECTION_FAILURE,\n   _ERR_DRIVER_LOADED,\n   _ERR_INVALID_HANDLE,\n   _ERR_NO_HANDLES,\n   _ERR_PAUSED,   \n   _ERR_NOT_PAUSED,\n   _ERR_INVALID_DATA,\n   _ERR_DRV_FILE_FAIL,\n   _ERR_INVALID_PORT,\n   _ERR_INVALID_IRQ,\n   _ERR_INVALID_DMA,\n   _ERR_INVALID_DMA_IRQ\n};   \n\n// maximum number of timer events that can be registered \n#define  _TIMER_MAX_EVENTS    0x10  \n\n// flags for the debugging system\n#define  _SOS_DEBUG_NORMAL       0x0000\n#define  _SOS_DEBUG_NO_TIMER     0x0001\n#define  _SOS_TIMER_DPMI         0x0002\n\n// define for types of DOS extenders\n#define  _SOS_RATIONAL           0x8000\n#define  _SOS_FLASHTECK          0x4000\n\n// defines for the types of timers for different\n// dos extenders\n#define  _SOS_TIMER_NEAR         0x8000\n#define  _SOS_TIMER_FAR          0x4000\n \n// values for callback information\nenum\n{\n   _SAMPLE_PROCESSED,\n   _SAMPLE_LOOPING,\n   _SAMPLE_DONE\n};\n\n// define for special 18.2 callback rate to dos\n#define  _TIMER_DOS_RATE   0xff00\n\n#pragma pack()\n\n#pragma aux int_3 = \"int 3\"\n \n#pragma pack( 1 ) \ntypedef struct\n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned       segment;\n\tunsigned short\tnumber_available;\n\tunsigned short number_used;\n\tunsigned       page0;\n\n} EVDS_STRUCT;\n\ntypedef struct \n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned short segment;\n\tunsigned short\tID;\n\tunsigned       physical;\n\n} VDS_STRUCT;\n\n#pragma pack() \n\n#include \"sosdata.h\"\n#include \"sosfnct.h\"\n\n#endif\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/SOSCOMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*  File              : soscomp.h\n*  Date Created      : 6/1/94\n*  Description       : \n*\n*  Programmer(s)     : Nick Skrepetos\n*  Last Modification : 10/1/94 - 11:37:9 AM\n*  Additional Notes  : Modified by Denzil E. Long, Jr.\n*\n*****************************************************************************\n*            Copyright (c) 1994,  HMI, Inc.  All Rights Reserved            *\n****************************************************************************/\n\n#ifndef  _SOS_COMPRESS\n#define  _SOS_COMPRESS\n\n/* compression types */\nenum {\n\t_ADPCM_TYPE_1,\n\t};\n\n/* define compression structure */\ntypedef struct _tagCOMPRESS_INFO {\n\tchar       *lpSource;\n\tchar       *lpDest;\n\tunsigned long dwCompSize;\n\tunsigned long dwUnCompSize;\n\tunsigned long dwSampleIndex;\n\tlong          dwPredicted;\n\tlong          dwDifference;\n\tshort         wCodeBuf;\n\tshort         wCode;\n\tshort         wStep;\n\tshort         wIndex;\n\n\tunsigned long dwSampleIndex2; //added BP for channel 2\n\tlong          dwPredicted2;   //added BP for channel 2\n\tlong          dwDifference2; \t//added BP for channel 2\n\tshort         wCodeBuf2; \t\t//added BP for channel 2\n\tshort         wCode2; \t\t\t//added BP for channel 2\n\tshort         wStep2; \t\t\t//added BP for channel 2\n\tshort         wIndex2; \t\t\t//added BP for channel 2\n\tshort         wBitSize;\n\tshort\t\t\t  wChannels;\t\t//added BP for # of channels\n\t} _SOS_COMPRESS_INFO;\n\n/* compressed file type header */\ntypedef struct _tagCOMPRESS_HEADER {\n\tunsigned long dwType;              // type of compression\n\tunsigned long dwCompressedSize;    // compressed file size\n\tunsigned long dwUnCompressedSize;  // uncompressed file size\n\tunsigned long dwSourceBitSize;     // original bit size\n\tchar          szName[16];          // file type, for error checking\n\t} _SOS_COMPRESS_HEADER;\n\n/* Prototypes */\nextern \"C\" {\n\tvoid sosCODECInitStream(_SOS_COMPRESS_INFO *);\n\tunsigned long sosCODECCompressData(_SOS_COMPRESS_INFO *,\tunsigned long);\n\tunsigned long sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);\n}\n\n#endif\n\u001a\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/SOSDATA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdata.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DATA\n#define  _SOS_DATA\n\n#include <stddef.h>\n\n#pragma pack(4) \nextern   WORD     _sosDIGIData_Start;\nextern   WORD     _sosDIGIData_End;\nextern   WORD     _wSOSDriverLinear[];\nextern   WORD     _wSOSTimerLinear[];\nextern   LPSTR    _lpSOSDriver[];\nextern   LPSTR    _lpSOSTimer[];\nextern   LPSTR    _lpSOSDriverCS[];\nextern   LPSTR    _lpSOSTimerCS[];\nextern   BOOL     _wSOSDriverLoaded[];\nextern   BOOL     _wSOSTimerLoaded[];\nextern   BOOL     _wSOSDriverInitialized[];\nextern   WORD     _wSOSOutputRate[];\nextern   WORD     _wSOSDMABuffersize[];\nextern   LONG     _dwSOSDMABufferPhysical[];\nextern   LPSTR    _lpSOSDMABuffer[];\nextern   BOOL     _wTimerUsed;\nextern   VOID ( far *_lpSOSFillHandler[] )( VOID );\nextern   WORD     _wSOSTimerType[];\nextern   WORD     _wSOSDriverType[];\nextern   _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ];\nextern   LPWORD      _lpSOSDMAIrqCount[];\nextern   LPWORD      _lpSOSDMAFillCount[];\nextern   WORD        _wSOSTmrNextCount;\nextern   VOID ( interrupt far *_lpSOSOldTimer )( VOID );\nextern   WORD     _wSOSDriverID[];\nextern   _SOS_CAPABILITIES _sSOSDriverCaps[];\nextern   WORD        _wSOSDMAPortList[];\nextern   BYTE        _bSOSDMAChannel[];\nextern   _SOS_INIT_DRIVER     _sSOSDIGIInitDriver[];\nextern   BYTE  _pSOSDriverPath[];\nextern   BYTE  _pSOSTempDriverPath[];\nextern   BOOL  _wTIMERUsed;\nextern   WORD  _wTIMERValue;\nextern   VOID ( far * _lpTIMEREvents[] )( VOID );\nextern   WORD _wTIMEREventRate[];\nextern   WORD _dwTIMEREventFraction[];\nextern   WORD _dwTIMEREventFractionCurrent[];\nextern   BYTE  _bSOSMIDITimerSongHandler[];\nextern   BYTE  _bSOSMIDISongHandle;\nextern   WORD  _wSOSTimerMemHandle[];\nextern   WORD  _wSOSDriverMemHandle[];\nextern   WORD  _wSOSRealSeg[];\n\nextern   _FILEHEADER    _sDETFileHeader;\nextern   _DRIVERHEADER  _sDETDriverHeader;\nextern   _FILEHEADER    sLOADFileHeader;\nextern   _DRIVERHEADER  sLOADDriverHeader;\nextern   BOOL           _wDETInitialized;\nextern   WORD           _wDETLinear;\nextern   LPSTR          _lpDETDriverBuffer;    \nextern   LPSTR          _lpDETDriverBufferCS;\nextern   WORD           _hDETFile;\nextern   DWORD          _dwDETDriverIndex;\nextern   WORD           _wDETDriverIndexCur;\nextern   WORD           _wDETMemHandle;\nextern   LPSOSDEVICECAPS _lpDETDeviceCaps;\nextern   _SOS_CAPABILITIES _sDETCaps;  \nextern   PSTR _pSOSErrorStrings[];\nextern   BOOL _wSOSBufferAllocated[];\nextern   BOOL _wSOSSystemInitialized;\nextern   VDS_STRUCT _sSOSVDSInfo;\nextern   _SOS_FILL_INFO _sSOSFillInfo;\nextern   WORD    _wSOSTimerEventIndex;\nextern   WORD  _wSOSTimerEntered;\nextern   WORD  _wSOSDriverSize[];\nextern   WORD  _wSOSTimerSize[];\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nextern   WORD  _sosDIGIData1_Start;\nextern   WORD  _sosDIGIData1_End;\nextern   WORD  _sosDIGIData2_Start;\nextern   WORD  _sosDIGIData2_End;\nextern   BYTE  _bTIMERInstalled;\nextern   BYTE  _bTIMERDPMI;\nextern   WORD  wDetectPort;\nextern   WORD  wDetectIRQ;\nextern   WORD  wDetectDMA;\nextern   WORD  wDetectParam;\n#ifdef __cplusplus\n}\n#endif \n\n#pragma pack()\n\n#endif\n\u001a\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/SOSDEFS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdefs.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n\n#ifndef  _SOSDEFS_DEFINED\n#define  _SOSDEFS_DEFINED\n\n#undef   _TRUE\n#undef   _FALSE\n#undef   _NULL\nenum  \n      { \n         _FALSE, \n         _TRUE \n      };\n\n#define  _NULL  0\n\n#ifndef  VOID\n#define  VOID           void\n#endif\ntypedef  int            BOOL;\ntypedef  unsigned int   UINT;\ntypedef  unsigned char  BYTE;\ntypedef  unsigned       WORD;\n#ifndef  LONG\ntypedef  signed long    LONG;\n#endif\ntypedef  unsigned long  DWORD;\n\ntypedef  BYTE  *        PBYTE;\ntypedef  char near *    PSTR;\ntypedef  WORD  *        PWORD;\ntypedef  LONG  *        PLONG;\ntypedef  VOID  *        PVOID;\n\ntypedef  BYTE  far   *  LPBYTE;\ntypedef  BYTE  far   *  LPSTR;\ntypedef  WORD  far   *  LPWORD;\ntypedef  LONG  far   *  LPLONG;\ntypedef  VOID  far   *  LPVOID;\n\ntypedef  BYTE  huge  *  HPBYTE;\ntypedef  BYTE  huge  *  HPSTR;\ntypedef  WORD  huge  *  HPWORD;\ntypedef  LONG  huge  *  HPLONG;\ntypedef  VOID  huge  *  HPVOID;\n\ntypedef  unsigned       HANDLE;\n\n#endif\n\u001a\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/SOSFNCT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosfnct.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_FUNCTIONS\n#define  _SOS_FUNCTIONS\n\n#pragma pack(4)\n\nWORD sosDIGILockMemory          (  VOID  );\nWORD sosDIGIUnLockMemory        (  VOID  );\nWORD sosDIGIInitSystem           (  LPSTR, WORD  );\nWORD sosDIGIUnInitSystem         (  VOID  );\nWORD sosDIGIInitDriver           (  WORD, _SOS_HARDWARE far *,\n                                    _SOS_INIT_DRIVER far *, WORD far *   );\nWORD sosDIGIUnInitDriver         (  WORD, BOOL, BOOL  );\nWORD sosDIGILoadDriver          (  WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD sosDIGIUnLoadDriver         (  WORD  );\nWORD sosDIGIGetDeviceCaps        (  WORD, LPSOSDEVICECAPS  );\n\n#ifdef PHARLAP\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#else\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#endif\n\nWORD sosDIGIStopSample           (  WORD, WORD  );\nWORD sosDIGISamplesPlaying       (  WORD  );\nBOOL sosDIGISampleDone           (  WORD, WORD  );\nBOOL sosDIGISampleFilling        (  WORD, WORD  );\nWORD sosDIGIStartSample          (  WORD, _SOS_START_SAMPLE far *  );\nWORD sosDIGIContinueSample       (  WORD, WORD, _SOS_START_SAMPLE far * );\n\n\nWORD  sosDIGIDetectInit          (  LPSTR  );\nWORD  sosDIGIDetectUnInit        (  VOID  );\nWORD  sosDIGIDetectFindHardware  (  WORD, _SOS_CAPABILITIES far *, WORD far * );\nWORD  sosDIGIDetectFindFirst     (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectFindNext      (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectGetSettings   (  _SOS_HARDWARE far *  );\nWORD  sosDIGIDetectGetCaps       (  WORD, _SOS_CAPABILITIES far *  );\nWORD  sosDIGIDetectVerifySettings(  _SOS_HARDWARE far *  );\nPSTR  sosGetErrorString          (  WORD  );\n\nWORD  sosDIGILoadTimer           (  WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD  sosDIGIUnLoadTimer         (  WORD  );\n\nWORD  sosTIMERRegisterEvent      ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle );\nWORD  sosTIMERInitSystem               (  WORD, WORD  );\nWORD  sosTIMERUnInitSystem             (  WORD  );\nWORD  sosTIMERSetRate                  (  WORD  );  \nWORD  sosTIMERRemoveEvent              (  WORD );\nWORD  sosTIMERAlterEventRate           (  WORD, WORD  );\nWORD  sosTIMERGetEventRate             (  WORD  );\nVOID far sosTIMEROldHandler            (  VOID  );\nVOID far sosTIMERHandler               (  VOID  );\n\n// functions in soscntl.c\nWORD  sosDIGISetSampleVolume     ( WORD, WORD, WORD );\nWORD  sosDIGIGetSampleVolume     ( WORD, WORD );\nWORD  sosDIGISetChannel          ( WORD, WORD, WORD );\nWORD  sosDIGIGetChannel          ( WORD, WORD );\nWORD  sosDIGIGetBytesProcessed   ( WORD, WORD );\nWORD  sosDIGIGetLoopCount        ( WORD, WORD );\nWORD  sosDIGISetPanLocation      ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanLocation      ( WORD, WORD );\nDWORD sosDIGISetPitch            ( WORD, WORD, DWORD );\nDWORD sosDIGIGetPitch            ( WORD, WORD );\nWORD  sosDIGIGetDMAPosition      ( WORD );\nWORD  sosDIGISetPanSpeed         ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanSpeed         ( WORD, WORD );\nWORD  sosDIGIGetSampleID         ( WORD, WORD );\nWORD  sosDIGIGetSampleHandle     ( WORD, WORD );\nWORD  sosDIGISetMasterVolume     ( WORD, WORD );\n#ifdef PHARLAP\nVOID  sosFreeVDSPage          ( unsigned short, unsigned short, DWORD );\nWORD  sosAllocVDSPage         ( unsigned short *, unsigned short *, DWORD * );\n#else\nWORD  sosAllocVDSPage            ( LPSTR *, WORD *, WORD * );\nVOID  sosFreeVDSPage             ( WORD, WORD, LONG );\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef PHARLAP\nextern   int   cdecl sosRealFree          ( int );\nextern   BOOL  cdecl  _sos_read( WORD, LPSTR, WORD, WORD * );\nextern   int   cdecl sosRealAlloc( int, int *, int * );\nextern   void  cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD );\nextern   int   cdecl sosGetCS( VOID );\nextern   int   cdecl sosGetES( VOID );\n#else\nextern   int   cdecl sosRealAlloc         ( int, int *, int * );\nextern   int   cdecl sosRealFree          ( int );\n#endif\n\n// sos driver functions\nextern   WORD  cdecl sosDRVLockMemory     ( DWORD, DWORD );\nextern   WORD  cdecl sosDRVUnLockMemory   ( DWORD, DWORD );\nextern   void  cdecl sosDRVGetCapsInfo    ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVGetCapsPtr     ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVInit           ( LPSTR, LPSTR, int, int, int, int, int, int );  \nextern   void  cdecl sosDRVStart          ( LPSTR, LPSTR, int, int );\nextern   void  cdecl sosDRVSetRate        ( LPSTR, LPSTR, int );\nextern   void  cdecl sosDRVSetAction      ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVStop           ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVUnInit         ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVGetFillInfo    ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * );\nextern   void  cdecl sosFillSampleStructs ( PSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVExist       ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVGetSettings ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR );\nextern   WORD  cdecl sosDIGIInitForWindows( WORD );\nextern   WORD  cdecl sosDIGIUnInitForWindows( WORD );\nextern   LPSTR cdecl sosAllocateFarMem      ( WORD, PSTR, WORD * );\nextern   LPSTR cdecl sosCreateAliasCS       ( LPSTR );\nextern   VOID  cdecl sosFreeSelector        ( LPSTR, DWORD );\nextern   LPSTR cdecl sosMAKEDOSPtr          ( PSTR );\nextern   VOID  cdecl sosDetDRVSetEnvString  ( DWORD, PSTR );\nextern   PSTR  cdecl sosDetDRVGetEnvString  ( DWORD );\nextern   VOID  cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR );\nextern   VOID  cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR );\nextern   WORD  cdecl sosDRVGetFreeMemory     ( VOID );\nextern   WORD  cdecl sosDRVAllocVDSStruct    ( WORD, WORD *, WORD * );\nextern   WORD  cdecl sosDRVFreeVDSStruct     ( WORD, WORD );\nextern   WORD  cdecl sosDRVIsWindowsActive   ( VOID );\nextern   WORD  cdecl sosDRVVDSGetBuffer    ( WORD );\nextern   WORD  cdecl sosDRVVDSFreeBuffer   ( WORD );\nextern   WORD  cdecl getDS( VOID );\nextern   WORD  cdecl sosDRVMakeDMASelector   ( WORD );  \nextern   WORD  cdecl sosDRVFreeDMASelector   ( WORD );  \n\n\nextern   void  cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) );\nextern   void  cdecl sosTIMERDRVUnInit( void );\nextern   void  cdecl sosTIMERDRVHandler( void );\nextern   void  cdecl sosTIMERDRVFHandler( void );\nextern   void  cdecl sosTIMERDRVEnable( void );\nextern   void  cdecl sosTIMERDRVDisable( void );\nextern   void  cdecl sosTIMERDRVCallOld( void );\nextern   void  cdecl sosTIMERDRVSetRate( WORD );    \nextern   void  cdecl sosDIGITimer_Start( void );\nextern   void  cdecl sosDIGITimer_End( void );\nextern   void  cdecl sosDIGIDrv_Start( void );\nextern   void  cdecl sosDIGIDrv_End( void );\n#ifdef __cplusplus\n}\n#endif \n\n// external functions for handling system initialization and \n// uninitialization\nWORD  sosEXDIGInitDriver               (  WORD, WORD, WORD, LPSTR,\n                                          _SOS_HARDWARE far *, WORD *  );\nWORD  sosEXDIGIUnInitDriver            (  VOID  );\n\nWORD  sosEXDETFindDriver               (  WORD, LPSTR, _SOS_HARDWARE far *,\n                                          _SOS_CAPABILITIES far *  );\n\n// memory locking prototypes\nVOID  sosDIGICaps_Start( VOID );\nVOID  sosDIGICaps_End( VOID );\nVOID  sosDIGIErr_Start( VOID );\nVOID  sosDIGIErr_End( VOID );\nVOID  sosDIGITmr_Start( VOID );\nVOID  sosDIGITmr_End( VOID );\nVOID  sosDIGIStart_Start( VOID );\nVOID  sosDIGIStart_End( VOID );\nVOID  sosDIGIPlyng_Start( VOID );\nVOID  sosDIGIPlyng_End( VOID );\nVOID  sosDIGIRate_Start( VOID );\nVOID  sosDIGIRate_End( VOID );\nVOID  sosDIGIDone_Start( VOID );\nVOID  sosDIGIDone_End( VOID );\nVOID  sosDIGIDetec_Start( VOID );\nVOID  sosDIGIDetec_End( VOID );\nVOID  sosDIGIInit_Start( VOID );\nVOID  sosDIGIInit_End( VOID );\nVOID  sosDIGILoad_Start( VOID );\nVOID  sosDIGILoad_End( VOID );\nVOID  sosDIGICntl_Start( VOID );\nVOID  sosDIGICntl_End( VOID );\n\n#pragma pack()\n\n#endif\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/SOSRES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosres.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#define  _SOS_RESOURCE\n#ifndef  _SOS_RESOURCE\n#define  _SOS_RESOURCE\n\n// structure for resource file header\ntypedef struct\n{\n   // file version\n   WORD     wVersion;\n\n   // file size\n   LONG     dwFileSize;\n\n   // number of resources in file\n   WORD     wResCount;\n\n   // offset of resource data from top of file\n   LONG     dwResOffset;\n\n   // offset of sync track from top of file\n   LONG     dwSyncTrackOffset;\n\n}  _RES_FILE_HEADER;\n\n// structure for resource block header\ntypedef struct\n{\n   // resource id\n   WORD     wID;\n\n   // resource type\n   WORD     wResType;\n\n   // offset of next block\n   LONG     dwNextBlock; \n\n   // size of the current resource information\n   LONG     dwResSize;\n\n   // rate to play block at\n   WORD     wBlockRate;\n\n   // id for the sync track to use\n   WORD     wSyncTrackID;\n\n}  _RES_BLOCK_HEADER;\n\n// structure for sync mark tag\ntypedef struct _tagSYNCMARK\n{\n   // ID of the type of mark being used\n   WORD  wID;\n\n   // location in data of sync mark\n   LONG  dwSyncOffset;\n\n   // length of sync block\n   LONG  dwSyncSize;\n\n   // start sample data\n   _SOS_START_SAMPLE sampleData;\n    \n} _RES_SYNCMARK;\n\ntypedef union\n{\n   // structure for sync mark tag\n   _RES_SYNCMARK  syncMark; \n\n} _RES_TAG;\n\n// union for filter information for prepareWave\ntypedef union\n{\n   // filter type\n   WORD     wFilterID;\n\n   // structure for volume\n   struct   volume \n   {\n      WORD  wVolume;\n   };\n\n   // structure for delay\n   struct   delay\n   {  \n      WORD  wDelaySamples;\n   };\n\n} _SOS_FILTER; \n\n \n#endif\n\n\u001a"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/SOUND.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : SOUND.H                                  *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : September 1, 1993                        *\n *                                                                         *\n *                  Last Update : September 1, 1993   [JLB]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SOUND_H\n#define SOUND_H\n\n#define\tHMI_DRIVER\tTRUE\n#include\t\"sos.h\"\n#include\t\"soscomp.h\"\n\n/*\n**\tMaximum number of sound effects that may run at once.\n*/\n#define\tMAX_SFX\t\t4\n\n/*\n** Size of temp HMI low memory staging buffer.\n*/\n#define\tSFX_MINI_STAGE_BUFFER_SIZE\t\t(1024*4)\n\n\nextern WORD _SoundVolume;\nextern WORD _ScoreVolume;\n\n#endif\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/STAMP.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; This is the control structure at the start of a loaded icon set.  It must match\n; the structure in ICONSET.C!  This structure MUST be a multiple of 16 bytes long.\n\tSTRUC\tIControl_Type\nWidth\t\tDW\t?\t; Width in pixels (per icon).\nHeight\t\tDW\t?\t; Height in pixels (per icon).\nCount\t\tDW\t?\t; Number of icons in this set.\nAllocated\tDW\t?\t; Was this iconset allocated?\nSize\t\tDD\t?\t; Size of entire iconset memory block.\nIcons\t\tDD\t?\t; Offset from buffer start to icon data.\nPalettes\tDD\t?\t; Offset from buffer start to palette data.\nRemaps\t\tDD\t?\t; Offset from buffer start to remap index data.\nTransFlag\tDD\t?\t; Offset for transparency flag data.\nMap\t\tDD\t?\t; Icon map offset.\n\tENDS\n\nICON256\tEQU\t1\n\u001a"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/SVGAPRIM.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : SVGAPRIM.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : December 8, 1994                         *\n;*                                                                         *\n;*                  Last Update : December 8, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n\n; Externs from VIDEO.CPP module of the VIDEO library\nGLOBAL BankTable\t\t\t:DWORD\nGLOBAL VesaFunc\t\t\t:DWORD\nGLOBAL XRes\t\t\t\t\t:DWORD\nGLOBAL YRes\t\t\t\t\t:DWORD\nGLOBAL CurrentMode\t\t:DWORD\nglobal cpu_video_page\t:dword\nglobal cpu_page_limit   :dword\n\n\n; Externs from VESA.ASM module of the SVGAPRIM library\nGLOBAL Vesa_Asm_Set_Win\t\t:NEAR\nGLOBAL Vesa_Asm_Next_Win\t\t:NEAR\n\n; Externs from VGETPIX.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Get_Pixel          \t:NEAR\n\n; Externs from VPUTTPIX.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Put_Pixel \t\t:NEAR\n\n\n; Externs from VCLEAR.ASM module of the MCGA/SVGAPRIM library\nGLOBAL Vesa_Clear\t\t\t:NEAR\n\n; Externs from VBITBLIT.ASM module of the MCGA/SVGAPRIM library\nGLOBAL Linear_Blit_To_Vesa\t\t:NEAR\nGLOBAL Vesa_Blit_To_Linear\t\t:NEAR\nGLOBAL Vesa_Blit_To_Vesa\t\t:NEAR\n\n; Externs from VTOBUFF.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_To_Buffer\t\t:NEAR\n\n; Externs from VTOPAGE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Buffer_To_Page\t\t:NEAR\n\n; Externs from VSCALE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Linear_Scale_To_Vesa \t\t:NEAR\nGLOBAL Vesa_Scale_To_Linear\t\t:NEAR\nGLOBAL Vesa_Scale_To_Vesa \t\t:NEAR\n\n\n; Externs from VSCALE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Print\t \t\t:NEAR\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/TILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the TILE Library                 *\n *                                                                         *\n *                    File Name : TILE.H                                   *\n *                                                                         *\n *                   Programmer : Barry W. Green                           *\n *                                                                         *\n *                   Start Date : February 2, 1995                         *\n *                                                                         *\n *                  Last Update : February 2, 1995 [BWG]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TILE_H\n#define TILE_H\n\n/*=========================================================================*/\n/* The following prototypes are for the file: ICONSET.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid * Load_Icon_Set(char const *filename, void *iconsetptr, long buffsize);\nvoid Free_Icon_Set(void const *iconset);\nlong Get_Icon_Set_Size(void const *iconset);\nint Get_Icon_Set_Width(void const *iconset);\nint Get_Icon_Set_Height(void const *iconset);\nvoid * Get_Icon_Set_Icondata(void const *iconset);\nvoid * Get_Icon_Set_Trans(void const *iconset);\nvoid * Get_Icon_Set_Remapdata(void const *iconset);\nvoid * Get_Icon_Set_Palettedata(void const *iconset);\nint Get_Icon_Set_Count(void const *iconset);\nvoid * Get_Icon_Set_Map(void const *iconset);\n\n#endif //TILE_H\n\n\u001a"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/TIMER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Timer Class Functions                    *\n *                                                                         *\n *                    File Name : TIMER.H                                  *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : July 6, 1994                             *\n *                                                                         *\n *                  Last Update : July 12, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TIMER_H\n#define TIMER_H\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TIMERA.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// Externs /////////////////////////////////////////////\nextern BOOL TimerSystemOn;\n\n\n/*=========================================================================*/\ntypedef enum BaseTimerEnum {\n\tBT_SYSTEM,\t\t\t// System timer (60 / second).\n\tBT_USER\t\t\t\t// User controllable timer (? / second).\n} BaseTimerEnum;\n\nclass TimerClass {\n \tpublic:\n\t\t// Constructor.  Timers set before low level init has been done will not\n\t\t// be able to be 'Started' or 'on' until timer system is in place.\t\n\t\tTimerClass(BaseTimerEnum timer=BT_SYSTEM, BOOL start=FALSE);\n\n\t\t// No destructor.\n\t\t~TimerClass(void){}\n\n\t\t// \n\t\tlong Set(long value, BOOL start=TRUE);\t// Set initial timer value.\n\t\tlong Stop(void);\t\t\t\t// Pause timer.\n\t\tlong Start(void);\t\t\t\t// Resume timer.\n\t\tlong Reset(BOOL start=TRUE);\t// Reset timer to zero.\n\t\tlong Time(void);\t\t\t\t// Fetch current timer value.\n\n\tprotected:\n\t\tlong Started;\t\t\t\t\t// Time last started (0 == not paused).\n\t\tlong Accumulated;\t\t\t\t//\tTotal accumulated ticks.\n\n\tprivate:\n\t\tlong (*Get_Ticks)(void);\t// System timer fetch.\n};\n\n\ninline long TimerClass::Reset(BOOL start)\n{\n\treturn(Set(0, start));\n}\n\n\nclass CountDownTimerClass : private TimerClass {\n\tpublic:\n\t\t// Constructor.  Timers set before low level init has been done will not\n\t\t// be able to be 'Started' or 'on' until timer system is in place.\t\n\t\tCountDownTimerClass(BaseTimerEnum timer, long set, int on=FALSE);\n\t\tCountDownTimerClass(BaseTimerEnum timer=BT_SYSTEM, int on=FALSE);\n\n\t\t// No destructor.\n\t\t~CountDownTimerClass(void){}\n\n\t\t// Public functions\n\t\tlong Set(long set, BOOL start=TRUE);\t// Set count down value.\n\t\tlong Reset(BOOL start=TRUE);\t// Reset timer to zero.\n\t\tlong Stop(void);\t\t\t// Pause timer.\n\t\tlong Start(void);\t\t\t// Resume timer.\n\t\tlong Time(void);\t\t\t// Fetch current count down value.\n\n\tprotected:\n\t\tlong DelayTime;\t\t\t// Ticks remaining before countdown timer expires.\n};\n\ninline long CountDownTimerClass::Stop(void)\n{\n\tTimerClass::Stop();\n\treturn(Time());\n}\n\ninline long CountDownTimerClass::Start(void)\n{\n\tTimerClass::Start();\n\treturn(Time());\n}\n\ninline long CountDownTimerClass::Reset(BOOL start)\n{\n\treturn (TimerClass::Reset(start));\n}\n\n\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// externs  //////////////////////////////////////////\n\nextern TimerClass\t\t\t\t\tTickCount;\nextern CountDownTimerClass\t\tCountDown;\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// Prototypes //////////////////////////////////////////\n\nextern \"C\" {\n\tlong Get_System_Tick_Count(void);\n\tlong Get_User_Tick_Count(void);\n\tvoid far Timer_Interrupt_Func(void);\n//\tlong Get_Num_Interrupts(unsigned int realmode);\n}\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TIMER.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nBOOL Init_Timer_System(unsigned int freq, int partial = FALSE);\nBOOL Remove_Timer_System(VOID);\n\n\n#endif // TIMER_H\n\n\u001a\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/VBUFFER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : VBUFFER.H                                *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : January 6, 1995                          *\n *                                                                         *\n *                  Last Update : January 17, 1995   [PWG]                 *\n *                                                                         *\n *\tThis module contains the definition for the video buffer class.  The\t\t*\n * primary functionality of the video buffer class is handled by inline\t\t*\n * functions that make a call through function pointers to the correct\t\t*\n * routine.  This has two benefits:\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t1) C++ name mangling is not a big deal since the function pointers\t*\n *\t\t   point to functions in standard C format.\t\t\t\t\t\t\t\t\t*\n *\t\t2) The function pointers can be changed when we set a different\t\t*\n *       graphic mode.  This allows us to have both supervga and mcga\t\t*\n *\t\t\troutines present in memory at once.\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * In the basic library, these functions point to stub routines which just\t*\n * return.  This makes a product that just uses a graphic buffer take the\t*\n * minimum amount of code space.  For programs that require MCGA or VESA\t*\n * support, all that is necessary to do is link either the MCGA or VESA\t\t*\n * specific libraries in, previous to WWLIB32.  The linker will then \t\t*\n * overide the the necessary stub functions automatically.\t\t\t\t\t\t*\n * \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This header files gives the definition for all VideoViewPort and \t\t\t*\n * VideoBuffer functions.  These functions mirror some of the basic\t\t\t*\n * functionality of the GraphicViewPort and GraphicBuffer classes.\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Terminology:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Video ViewPort - The Video ViewPort holds all of the functions which\t\t* \n *\t\tcan be used on a Video Buffer.  The video viewport but cannot be \t\t*\n *\t\tattached to a Graphic Buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n *\tVideo Buffer - A refers to a physical object which has been mapped to\t* \n *\t\tram, like a graphic card.  The SeenPage is a good example of a Video\t* \n *\t\tBuffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n\n * Below is a tree which shows the relationship of the GraphicBuffer and \t*\n * Buffer classes to the VideoBuffer class:\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t  BUFFER.H\t\t\t\t GBUFFER.H\t\t\t  BUFFER.H\t\t\t\t VBUFFER.H\t*\n *  ----------          ----------         ----------          ----------\t*\n * |  Buffer  |        | Graphic  |       |  Buffer  |        |  Video   |\t*\n * |  Class   |        | ViewPort |       |  Class   |        | ViewPort |\t*\n *  ----------          ----------         ----------          ----------\t*\n *            \\        /                             \\        /\t\t\t\t*\n *             \\      /                               \\      /\t\t\t\t\t*\n *            ----------                             ----------\t\t\t\t*\n *           |  Graphic |                           |  Video   |\t\t\t\t*\n *           |  Buffer  |                           |  Buffer  |\t\t\t\t*\n *            ----------                             ---------- \t\t\t\t*\n *\t  \t\t\t  GBUFFER.H\t\t\t                       VBUFFER.H\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   VVPC::Get_Selector -- Get selector for virtual viewport instance\t\t*\n *   VVPC::Get_Offset -- Get offset for virtual view port class instance   *\n *   VVPC::Get_Height -- Gets the height of a virtual viewport instance    *\n *   VVPC::Get_Width -- Get the width of a virtual viewport instance\t\t\t*\n *   VVPC::Get_XAdd -- Get the X add offset for virtual viewport instance  *\n *   VVPC::Get_XPos -- Get the x pos of the VP on the Video                *\n *   VVPC::Get_YPos -- Get the y pos of the VP on the video                *\n *   VVPC::Get_Grasphic_Buffer -- Get the graphic buffer of the VP.        *\n *   VVPC::Put_Pixel -- stub to call curr graphic mode Put_Pixel\t\t\t\t*\n *   VVPC::Get_Pixel -- stub to call curr graphic mode Get_Pixel\t\t\t\t*\n *   VVPC::Clear -- stub to call curr graphic mode Clear        \t\t\t\t*\n *   VVPC::To_Buffer -- stub func 1 to call curr graphic mode To_Buffer\t\t*\n *   VVPC::To_Buffer -- stub func 2 to call curr graphic mode To_Buffer\t\t*\n *   VVPC::To_Buffer -- stub func 3 to call curr graphic mode To_Buffer\t\t*\n *   VVPC::Blit -- stub 1 to call curr graphic mode Blit to GVPC\t\t\t\t*\n *   VVPC::Blit -- stub 2 to call curr graphic mode Blit\tto GVPC\t\t\t\t*\n *   VVPC::Blit -- stub 3 to call curr graphic mode Blit\tto GVPC\t\t\t\t*\n *   VVPC::Blit -- stub 1 to call curr graphic mode Blit\tto VVPC\t\t\t\t*\n *   VVPC::Blit -- stub 2 to call curr graphic mode Blit\tto VVPC\t\t\t\t*\n *   VVPC::Blit -- stub 3 to call curr graphic mode Blit\tto VVPC\t\t\t\t*\n *   VVPC::Scale -- stub 1 to call curr graphic mode Scale to GVPC\t\t\t*\n *   VVPC::Scale -- stub 2 to call curr graphic mode Scale to GVPC\t\t\t*\n *   VVPC::Scale -- stub 3  to call curr graphic mode Scale\tto GVPC\t\t\t*\n *   VVPC::Scale -- stub 4 to call curr graphic mode Scale to GVPC\t\t\t*\n *   VVPC::Scale -- stub 1 to call curr graphic mode Scale to VVPC\t\t\t*\n *   VVPC::Scale -- stub 2 to call curr graphic mode Scale to VVPC\t\t\t*\n *   VVPC::Scale -- stub 3  to call curr graphic mode Scale\tto VVPC\t\t\t*\n *   VVPC::Scale -- stub 4 to call curr graphic mode Scale to VVPC\t\t\t*\n *   BC::To_Page -- Copys buffer class to page with definable w, h \t\t\t*\n *   BC::To_Page -- Copys buffer class to page with definable w, h \t\t\t*\n *   BC::To_Page -- Copys buffer class to page with definable x, y, w, h \t*\n *   Buffer_To_Page -- Generic 'c' callable form of Buffer_To_Page         *\n *   GVPC::Blit -- stub 1 to call curr graphic mode Blit to VVPC\t\t\t\t*\n *   GVPC::Blit -- stub 2 to call curr graphic mode Blit to VVPC\t\t\t\t*\n *   GVPC::Blit -- stub 3 to call curr graphic mode Blit to VVPC\t\t\t\t*\n *   GVPC::SCALE -- stub 1 to call curr graphic mode Scale to VVPC\t\t\t*\n *   GVPC::SCALE -- stub 2 to call curr graphic mode Scale to VVPC\t\t\t*\n *   GVPC::SCALE -- stub 3 to call curr graphic mode Scale to VVPC\t\t\t*\n *   GVPC::SCALE -- stub 4 to call curr graphic mode Scale to VVPC\t\t\t*\n *   VVPC::Print -- Stub function to print string on a Video View Port     *\n *   VVPC::Print -- Stub function to print an int on a Graphic Viewport Class*\n *   VVPC::Print -- Stub function to print long on a graphic viewport class*\n *   VVPC::Print -- Stub function to print a short on a Video Viewport     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef VBUFFER_H\n#define VBUFFER_H\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n\n/*=========================================================================*/\n/* The video buffer class is dependant on a buffer class so we need to\t\t*/\n/*\t\tinclude the definitions for that as well.\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#ifndef BUFFER_H\n#include \"buffer.h\"\n#endif\n\n/*=========================================================================*/\n/* The video buffer class is dependant on a buffer class so we need to\t\t*/\n/*\t\tinclude the definitions for that as well.\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#ifndef GBUFFER_H\n#include \"gbuffer.h\"\n#endif\n\n/*=========================================================================*/\n/* Define external assembly funcs which deals with buffers and viewports.\t*/\n/*=========================================================================*/\nlong Buffer_To_Page(int x, int y, int w, int h, void *Buffer, VideoViewPortClass &view);\n\n/*=========================================================================*/\n/* Define the screen width and height to make portability to other modules\t*/\n/*\t\teasier.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tDEFAULT_SCREEN_WIDTH\t\t320\n#define\tDEFAULT_SCREEN_HEIGHT\t200\n\n/*=========================================================================*/\n/* Define functions which have not under-gone name mangling\t\t\t\t\t\t*/\n/*=========================================================================*/\n#ifdef __cplusplus\nextern \"C\" {\n\textern UWORD Get_MCGA_Selector(VOID);\n}\n#endif\n\n/*=========================================================================*/\n/* Let the compiler know that a VideoBufferClass exists so that it can\t\t*/\n/*\t\tkeep a pointer to it in a VideoViewPortClass.\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nclass VideoBufferClass;\n\n\n/*=========================================================================*/\n/* VideoViewPortClass - Holds viewport information which has been attached\t*/\n/*\t\tto a VideoBuffer.  A viewport is effectively a\trectangular subset   */\n/*    of the full buffer which is used for clipping and the like.\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tint \t\tSelector\t-\t\tis the selector to view port buffer\t\t\t*/\n/*\t\t\tchar\t  \t*Buffer\t-\t\tis the offset to view port buffer\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis the width of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis the height of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis add value to go from the end of a line\t*/\n/*\t\t\t\t\t\t\t\t\t\t\tto the beginning of the next line\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\tx offset into its associated VideoBuffer\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\ty offset into its associated VideoBuffer\t*/\n/*=========================================================================*/\nclass VideoViewPortClass {\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVideoViewPortClass(VideoBufferClass* graphic_buff, int x, int y, int w, int h);\n\t\tVideoViewPortClass();\n\t\t~VideoViewPortClass();\n\t\t/*===================================================================*/\n\t\t/* Define functions to get at the private data members\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\tGet_Offset(void);\n\t\tint\tGet_Height(void);\n\t\tint\tGet_Width(void);\n\t\tint\tGet_XAdd(void);\n\t\tint\tGet_XPos(void);\n\t\tint\tGet_YPos(void);\n\t\tVideoBufferClass *Get_Video_Buffer(void);\n\n\t\t/*===================================================================*/\n\t\t/* Define a function which allows us to change a video viewport on\t*/\n\t\t/*\t\tthe fly.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBOOL Change(int x, int y, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the set of graphic functions that are members of a Video   */\n\t\t/*\t\tViewPort class.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tvoid\tPut_Pixel(int x, int y, unsigned char color);\n\t\tint\tGet_Pixel(int x, int y);\n\t\tvoid\tClear(unsigned char color = 0);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, void *buff, long size);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, BufferClass *buff);\n\t\tlong\tTo_Buffer(BufferClass *buff);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, char *remap);\n\t\tunsigned long  Print(char const *string, int x, int y, int fcolor, int bcolor);\n\t\tunsigned long\tPrint(int num, int x, int y, int fcol, int bcol);\n\t\tunsigned long\tPrint(short num, int x, int y, int fcol, int bcol);\n\t\tunsigned long\tPrint(long num, int x, int y, int fcol, int bcol);\n\n\tprotected:\n\t\t/*===================================================================*/\n\t\t/* Define functions to attach the viewport to a graphicbuffer\t\t\t*/\n\t\t/*===================================================================*/\n\t\tvoid Attach(VideoBufferClass *video_buff, int x, int y, int w, int h);\n\t\tvoid Attach(VideoBufferClass *video_buff, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the data used by a GraphicViewPortClass\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\t\t\t\t\t\tOffset;\t\t\t\t\t// offset to graphic page\n\t\tint\t\t\t\t\t\tWidth;\t\t\t\t\t// width of graphic page\n\t\tint\t\t\t\t\t\tHeight;\t\t\t\t\t// height of graphic page\n\t\tint\t\t\t\t\t\tXAdd;\t\t\t\t\t\t// xadd for graphic page (0)\n\t\tint\t\t\t\t\t\tXPos;\t\t\t\t\t\t// x offset in relation to graphicbuff\n\t\tint\t\t\t\t\t\tYPos;\t\t\t\t\t\t// y offset in relation to graphicbuff\n\t\tVideoBufferClass\t   *VideoBuff;\t\t\t\t// related graphic buff\n};\n\n\n/*=========================================================================*/\n/* VideoBufferClass - A VideoBuffer refers to an actual instance of a\t\t*/\n/*\t\tphyscial device which has been mapped to a memory address like a \t\t*/\n/*\t\tvideo card.  The VideoBuffer can be drawn to directly because it\t\t*/\n/*\t\tinherits a Video ViewPort which represent its full size.\t\t\t\t\t*/\n/*\t\tsize.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tSelector\t-\t\tis now the selector to graphic buffer\t\t*/\n/*\t\t\tchar\t  \t*Buffer\t-\t\tis now the offset to graphic buffer\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis now the width of graphic buffer\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis now the height of graphic buffer\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis now the xadd of graphic buffer\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\twill be 0 because it is graphicbuff\t\t\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\twill be 0 because it is graphicbuff\t\t\t*/\n/*=========================================================================*/\nclass VideoBufferClass: public VideoViewPortClass {\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVideoBufferClass(unsigned short selector, long offset, int w, int h);\n\t\tVideoBufferClass(int w = DEFAULT_SCREEN_WIDTH, int h = DEFAULT_SCREEN_HEIGHT);\n\t\t~VideoBufferClass();\n};\n\n/***************************************************************************\n * VVPC::GET_OFFSET -- Get offset for virtual view port class instance     *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long the offset for the virtual viewport instance           *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long VideoViewPortClass::Get_Offset(void)\n{\n\treturn(Offset);\n}\n\n/***************************************************************************\n * VVPC::GET_HEIGHT -- Gets the height of a virtual viewport instance      *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     int the height of the virtual viewport instance             *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int VideoViewPortClass::Get_Height(void)\n{\n\treturn(Height);\n}\n\n/***************************************************************************\n * VVPC::GET_WIDTH -- Get the width of a virtual viewport instance\t\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     int the width of the virtual viewport instance              *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int VideoViewPortClass::Get_Width(void)\n{\n\treturn(Width);\n}\n\n\n/***************************************************************************\n * VVPC::GET_XADD -- Get the X add offset for virtual viewport instance    *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     int the xadd for a virtual viewport instance                *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int VideoViewPortClass::Get_XAdd(void)\n{\t\n\treturn(XAdd);\n}\n/***************************************************************************\n * VVPC::GET_XPOS -- Get the x pos of the VP on the Video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     int the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n;*   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int VideoViewPortClass::Get_XPos(void)\n{\n\treturn(XPos);\n}\n\n\n/***************************************************************************\n * VVPC::GET_YPOS -- Get the y pos of the VP on the video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     int the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n;*   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int VideoViewPortClass::Get_YPos(void)\n{\n\treturn(YPos);\n}\n\n/***************************************************************************\n * VVPC::GET_GRAPHIC_BUFFER -- Get the graphic buffer of the VP.           *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline VideoBufferClass *VideoViewPortClass::Get_Video_Buffer(void)\n{\n \treturn (VideoBuff);\n}\n\n/***************************************************************************\n * VVPC::PUT_PIXEL -- stub to call curr graphic mode Put_Pixel\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tVideoViewPortClass::Put_Pixel(int x, int y, unsigned char color)\n{\n\tVVPC_Put_Pixel_Func(this, x, y, color);\n}\n\n/***************************************************************************\n * VVPC::GET_PIXEL -- stub to call curr graphic mode Get_Pixel          \t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline int\tVideoViewPortClass::Get_Pixel(int x, int y)\n{\n\treturn(VVPC_Get_Pixel_Func(this, x, y));\n}\n\n/***************************************************************************\n * VVPC::CLEAR -- stub to call curr graphic mode Clear\t                  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tVideoViewPortClass::Clear(unsigned char color)\n{\n\tVVPC_Clear_Func(this, color);\n}\n\n/***************************************************************************\n * VVPC::TO_BUFFER -- stub 1 to call curr graphic mode To_Buffer\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tVideoViewPortClass::To_Buffer(int x, int y, int w, int h, void *buff, long size)\n{\n\treturn(VVPC_To_Buffer_Func(this, x, y, w, h, buff, size));\n}\n\n/***************************************************************************\n * VVPC::TO_BUFFER -- stub 2 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tVideoViewPortClass::To_Buffer(int x, int y, int w, int h, BufferClass *buff)\n{\n\treturn(VVPC_To_Buffer_Func(this, x, y, w, h, buff->Get_Buffer(), buff->Get_Size()));\n}\n\n/***************************************************************************\n * VVPC::TO_BUFFER -- stub 3 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tVideoViewPortClass::To_Buffer(BufferClass *buff)\n{\n\treturn(VVPC_To_Buffer_Func(this, 0, 0, Width, Height, buff->Get_Buffer(), buff->Get_Size()));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- stub 1 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans)\n{\n\treturn(VVPC_Blit_to_GVPC_Func(this, &dest, x_pixel, y_pixel, dx_pixel, dy_pixel, pixel_width, pixel_height, trans));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- Stub 2 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans)\n{\n\treturn(VVPC_Blit_to_GVPC_Func(this, &dest, 0, 0, dx, dy, Width, Height, trans));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- stub 3 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tGraphicViewPortClass& dest, BOOL trans)\n{\n\treturn(VVPC_Blit_to_GVPC_Func(this, &dest, 0, 0, 0, 0, Width, Height, trans));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- stub 1 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tVideoViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans)\n{\n\treturn(VVPC_Blit_to_VVPC_Func(this, &dest, x_pixel, y_pixel, dx_pixel, dy_pixel, pixel_width, pixel_height, trans));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- stub 2 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tVideoViewPortClass& dest, int dx, int dy, BOOL trans)\n{\n\treturn(VVPC_Blit_to_VVPC_Func(this, &dest, 0, 0, dx, dy, Width, Height, trans));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- stub 3 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tVideoViewPortClass& dest, BOOL trans)\n{\n\treturn(VVPC_Blit_to_VVPC_Func(this, &dest, 0, 0, 0, 0, Width, Height, trans));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 1 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans, char *remap)\n{\n\treturn(VVPC_Scale_To_GVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, trans, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 2 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap)\n{\n\treturn(VVPC_Scale_To_GVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, FALSE, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 3 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tGraphicViewPortClass &dest, BOOL trans, char *remap)\n{\n\treturn(VVPC_Scale_To_GVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), trans, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 4 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tGraphicViewPortClass &dest, char *remap)\n{\n\treturn(VVPC_Scale_To_GVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), FALSE, remap));\n}\n/***************************************************************************\n * VVPC::SCALE -- stub 1 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans, char *remap)\n{\n\treturn(VVPC_Scale_To_VVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, trans, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 2 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap)\n{\n\treturn(VVPC_Scale_To_VVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, FALSE, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 3 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tVideoViewPortClass &dest, BOOL trans, char *remap)\n{\n\treturn(VVPC_Scale_To_VVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), trans, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 4 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tVideoViewPortClass &dest, char *remap)\n{\n\treturn(VVPC_Scale_To_VVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), FALSE, remap));\n}\n\n/***************************************************************************\n * VVPC::PRINT -- Stub function to print string on a Video View Port       *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tVideoViewPortClass::Print(char const *str, int x, int y, int fcol, int bcol)\n{\n\treturn(VVPC_Print_Func(this, str, x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * VVPC::PRINT -- Stub function to print an int on a Video Viewport\t\t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tVideoViewPortClass::Print(int num, int x, int y, int fcol, int bcol)\n{\n\tBYTE str[17];\n\n\treturn(VVPC_Print_Func(this, itoa(num, str, 10), x, y, fcol, bcol));\n}\n\n\n/***************************************************************************\n * VVPC::PRINT -- Stub function to print a short on a Video Viewport       *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tVideoViewPortClass::Print(short num, int x, int y, int fcol, int bcol)\n{\n\tBYTE str[17];\n\n\t\n\treturn(VVPC_Print_Func(this, itoa(num, str, 10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * VVPC::PRINT -- Stub function to print long on a Video Viewport\t\t\t\t*\n *                                                                         *\n * INPUT:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/17/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline unsigned long\tVideoViewPortClass::Print(long num, int x, int y, int fcol, int bcol)\n{\n\tBYTE str[33];\n\n\treturn(VVPC_Print_Func(this, ltoa(num, str, 10), x, y, fcol, bcol));\n}\n\n\n/*=========================================================================*/\n/*= The following BufferClass functions are defined here because they act =*/\n/*=\ton video viewports.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  =*/\n/*=========================================================================*/\n\n\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t*\n *\t\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t*\n *\t\t\t\t\tVIVC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int w, int h, VideoViewPortClass &view)\n{\n\treturn(VVPC_Buffer_To_Page(0, 0, w, h, Buffer, &view));\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tVIVC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport.  width and height are assumed to be the\t\t\t*\n *\t\t\t\t\t\tviewport's width and height.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(VideoViewPortClass &view)\n{\n\treturn(VVPC_Buffer_To_Page(0, 0, view.Get_Width(), view.Get_Height(), Buffer, &view));\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable x, y, w, h *\n *                                                                         *\n * INPUT:\tint\tx\t\t\t- x pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\ty\t\t\t- y pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t\t*\n *\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t\t*\n *\t\t\t\tVIVC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\tnone                                                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int x, int y, int w, int h, VideoViewPortClass &view)\n{\n\treturn(VVPC_Buffer_To_Page(x, y, w, h, Buffer, &view));\n}\n\n/***************************************************************************\n * BUFFER_TO_PAGE -- Generic 'c' callable form of Buffer_To_Page           *\n *                                                                         *\n * INPUT: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/12/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long Buffer_To_Page(int x, int y, int w, int h, void *Buffer, VideoViewPortClass &view)\n{\n\treturn(VVPC_Buffer_To_Page(x, y, w, h, Buffer, &view));\n}\n\n/*=========================================================================*/\n/* The following GraphicBufferClass functions are defined here because \t\t*/\n/* they act\ton graphic viewports.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n/***************************************************************************\n * GVPC::BLIT -- stub 1 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tVideoViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans)\n{\n\treturn(GVPC_Blit_to_VVPC_Func(this, &dest, x_pixel, y_pixel, dx_pixel, dy_pixel, pixel_width, pixel_height, trans));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 2 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tVideoViewPortClass& dest, int dx, int dy, BOOL trans)\n{\n\treturn(GVPC_Blit_to_VVPC_Func(this, &dest, 0, 0, dx, dy, Width, Height, trans));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 3 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tVideoViewPortClass& dest, BOOL trans)\n{\n\treturn(GVPC_Blit_to_VVPC_Func(this, &dest, 0, 0, 0, 0, Width, Height, trans));\n}\n/***************************************************************************\n * GVPC::SCALE -- stub 1 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans, char *remap)\n{\n\treturn(GVPC_Scale_To_VVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, trans, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 2 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap)\n{\n\treturn(GVPC_Scale_To_VVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, FALSE, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 3 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tVideoViewPortClass &dest, BOOL trans, char *remap)\n{\n\treturn(GVPC_Scale_To_VVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), trans, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 4 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tVideoViewPortClass &dest, char *remap)\n{\n\treturn(GVPC_Scale_To_VVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), FALSE, remap));\n}\n\n#endif // VBUFFER_H\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/VIDEO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : 32 bit library                           *\n *                                                                         *\n *                    File Name : VIDEO.H                                  *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef VIDEO_H\n#define VIDEO_H\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\t\t\t\t\t   \n/*=========================================================================*/\n/*\tThe machine can be in one of the following graphic modes.  The global\t*/\n/*\tGraphicMode is set to one of these values.\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tCGA_MODE\t\t\t\t\t4\t\t\t// DOS 320x200 4 color mode\n#define\tTGA_MODE\t\t\t\t\t9\t\t\t// TANDY 320x200 16 color mode\n#define\tEGA_MODE\t\t\t\t\t13\t\t\t// DOS 320x200 16 color mode\n#define\tMCGA_MODE\t\t\t\t0x13\t\t// DOS 320x200 256 color mode\n#define\tVGA_MODE\t\t\t\t\t0x13\t\t// DOS 320x200 256 color mode\n#define\tEEGA_MODE\t\t\t\t14\t\t\t// DOS 640x400 16 color mode\n#define\tETGA_MODE\t\t\t\t9\t\t\t// TANDY 640x400 16 color mode\n#define\tHGA_MODE\t\t\t\t\t7\t\t\t// DOS 768x400 2 color mode\n#define\tTXT_MODE\t\t\t\t\t3\t\t\t// DOS plain old color text mode\n#define\tVESA_640X400_256\t\t0x100\t\t// VESA 640x400 256 color mode\n#define\tVESA_640X480_256\t\t0x101\t\t// VESA 640x480 256 color mode\n#define\tVESA_800X600_256\t\t0x103\t\t// VESA 800x600 256 color mode\n#define\tVESA_1024X768_256\t\t0x105\t\t//\tVESA 1024x768 256 color mode\n#define\tVESA_1280X400_256\t\t0x107\t\t// VESA 1280x400 256 color mode\n#define\tVESA_TEXT_80X60\t\t0x108\t\t// VESA 80x60 text mode\n#define\tVESA_TEXT_132X25\t\t0x109\t\t// VESA 132x25 text mode\n#define\tVESA_TEXT_132X60\t\t0x10C\t\t// VESA 132x60 text mode\n#define\tRESET_MODE\t\t\t\t-1\n#define\tUNINITIALIZED_MODE\t-1\n#define\tVESA_MIN \t\t\t\tVESA_640X400_256\n#define\tVESA_MAX\t\t\t\t\tVESA_TEXT_132X60\n\n/*=========================================================================*/\n/* Define the maximum number of bank entries\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tMAX_BANK_ENTRIES\t\t((1280L*1024L)/65536L)\n\n\n/*=========================================================================*\n * VesaInfoType - General info about this VESA implementation\t\t\t\t\t*\n *                (Filled in by VESA BIOS Function 0)\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Signature    - Will always be 'VESA'\t\t\t\t\t\t\t\t\t\t\t\t*\n * Version      - Version #\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OEMString    - OEM ID string\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Capabilities - Not defined by VESA yet\t\t\t\t\t\t\t\t\t\t\t\t*\n * AvailModes   - List of available modes; terminated with -1 (0xffff)\t\t*\n * TotalMemory  - ???\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Reserved     - Pads structure to 256 bytes total\t\t\t\t\t\t\t\t*\n *=========================================================================*/\ntypedef struct {\n\tchar    Signature[4];\n\tshort   Version;\n\tREALPTR OEMString;\n\tlong    Capabilities;\n\tREALPTR AvailModes;\n\tshort   TotalMemory;\n\tchar    Reserved[236];\n} VesaInfoType;\n\n\n/*=========================================================================*\n * VesaModeInfoType - Info about this VESA mode\t\t\t\t\t\t\t\t\t\t*\n *                    (Filled in by VESA BIOS Function 1)\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Attributes       - bit 0: 1 = mode is supported\t\t\t\t\t\t\t\t\t*\n *                    bit 1: 1 = optional info available\t\t\t\t\t\t\t*\n *                    bit 2: 1 = std BIOS output funcs valid in this mode\t*\n *                    bit 3: 0 = monochrome, 1 = color\t\t\t\t\t\t\t*\n *                    bit 4: 0 = text mode, 1 = graphics\t\t\t\t\t\t\t*\n * WinA_Attributes  - bit 0 = win exists, bit 1=readable, bit 2= writable\t*\n * WinB_Attributes  - bit 0 = win exists, bit 1=readable, bit 2= writable\t*\n * WinGranularity   - smallest address boundary window can be placed upon;\t*\n *                    size is in KB (ie 64, 32, 4)\t\t\t\t\t\t\t\t\t*\n * WinSize          - size of windows in KB (ie 64, 32)\t\t\t\t\t\t\t*\n * WinA_Segment     - location of Window A in CPU space (usually 0xa000)\t*\n * WinB_Segment     - location of Window B in CPU space (usually 0xb000)\t*\n * WinFunc          - address of window-setting function (This is provided *\n *                    as an alternative to Int 10 for speed.)\t\t\t\t\t*\n * BytesPerScanline - # bytes per scan line\t\t\t\t\t\t\t\t\t\t\t*\n * \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Optional info (available if bit 1 of Attributes is set):\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * XRes             - X-resolution\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * YRes             - Y-resolution\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * XCharSize        - Horizontal size of char cell\t\t\t\t\t\t\t\t\t*\n * YCharSize        - Vertical size of char cell\t\t\t\t\t\t\t\t\t*\n * NumPlanes        - # of memory planes (???)\t\t\t\t\t\t\t\t\t\t*\n * BitsPerPixel     - # bites per pixel\t\t\t\t\t\t\t\t\t\t\t\t*\n * NumBanks         - # of banks (ie planes)\t\t\t\t\t\t\t\t\t\t\t*\n * MemoryModel      - 00h = Text mode\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                    01h = CGA mode\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                    02h = Hercules\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                    03h = 4 plane planar mode\t\t\t\t\t\t\t\t\t\t*\n *                    04h = packed pixel mode (1 byte/pixel)\t\t\t\t\t*\n *                    05h = non-chain 4, 256-color mode\t\t\t\t\t\t\t*\n *                    06-0Fh = \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                    10-FFh = OEM-specific\t\t\t\t\t\t\t\t\t\t\t*\n * BankSize         - Bank size in KB\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\ntypedef struct {\n\tshort   Attributes;\n\tchar    WinA_Attributes;\n\tchar    WinB_Attributes;\n\tshort   WinGranularity;\n\tshort   WinSize;\n\tshort   WinA_Segment;\n\tshort   WinB_Segment;\n\tREALPTR WinFunc;\n\tshort   BytesPerScanline;\n\tshort   XRes;\n\tshort   YRes;\n\tchar    XCharSize;\n\tchar    YCharSize;\n\tchar    NumPlanes;\n\tchar    BitsPerPixel;\n\tchar    NumBanks;\n\tchar    MemoryModel;\n\tchar    BankSize;\n\tchar    NumInputPages;\n\tchar    Reserved;\n\tchar    RedMaskSize;\n\tchar    RedFieldPosition;\n\tchar    GreenMaskSize;\n\tchar    GreenFieldPosition;\n\tchar    BlueMaskSize; \n\tchar    BlueFieldPosition;\n\tchar    RsvdMaskSize;\n\tchar    RsvdFieldPosition;\n\tchar    DirectColorModeInfo;\n\tchar    pad[216];\n} VesaModeInfoType;\n\n\nextern \"C\" {\nextern\tint\tGraphicMode;\nextern\tlong\tXRes;\nextern\tlong\tYRes;\n\nextern long\t\t BankTable [];\nextern REALPTR\t VesaFunc;\nextern unsigned long RMVesaVector ;\nextern unsigned long RMVesaRegs ;\n}\n\n/*=========================================================================*/\n/* The following prototypes are for the file: VIDEO.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint Get_Video_Mode(void);\nint Set_Video_Mode(int mode);\nvoid Vesa_Info(void);\nvoid Vesa_Set_Window(long grain_num);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: INITDLAY.CPP\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\nextern VOID Init_Delay(VOID);\nextern BOOL VertBlank;\n\n/*=========================================================================*/\n/* The following prototypes are for the file: VERTBLNK.ASM\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\t\t\t\t \t\t\t\t   \nextern \"C\" {\n\textern WORD Get_Vert_Blank(VOID);\n\textern VOID Wait_Vert_Blank(BOOL blank);\n}\n\n/*=========================================================================*/\n\n#endif // VIDEO_H\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/WINDOWS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the WINDOWS Library              *\n *                                                                         *\n *                    File Name : WINDOWS.H                                *\n *                                                                         *\n *                   Programmer : Barry W. Green                           *\n *                                                                         *\n *                   Start Date : February 16, 1995                        *\n *                                                                         *\n *                  Last Update : February 16, 1995 [BWG]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WINDOWS_H\n#define WINDOWS_H\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WINHIDE.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Window_Hide_Mouse(int window);\nvoid Window_Show_Mouse(void);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WINDOWS.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Standard_More_Prompt(char const *prompt, int space, int fcolor, int bcolor);\nvoid Set_More_Prompt(char const *prompt, int space, int fcolor, int bcolor);\nvoid Set_More_On(void);\nvoid Set_More_Off(void);\nint Change_Window(int windnum);\nint Change_New_Window(int windnum);\nvoid New_Window(void);\nvoid Window_Int_Print(int num);\nvoid Window_Print(char const string[], ...);\n\n/*\n**\tThe WindowList[][8] array contains the following elements.  Use these\n**\tdefines when accessing the WindowList.\n*/\ntypedef enum {\n\tWINDOWX,\t\t\t// X byte position of left edge.\n\tWINDOWY,\t\t\t// Y pixel position of top edge.\n\tWINDOWWIDTH,\t// Width in bytes of the window.\n\tWINDOWHEIGHT,\t// Height in pixels of the window.\n\tWINDOWFCOL,\t\t// Default foreground color.\n\tWINDOWBCOL,\t\t// Default background color.\n\tWINDOWCURSORX,\t// Current cursor X position (in rows).\n\tWINDOWCURSORY,\t// Current cursor Y position (in lines).\n\tWINDOWPADDING=0x1000\n} WindowIndexType;\n\nextern int WindowList[][8];\nextern int WindowColumns;\nextern int WindowLines;\nextern int WindowWidth;\nextern unsigned int WinB;\nextern unsigned int WinC;\nextern unsigned int WinX;\nextern unsigned int WinY;\nextern unsigned int WinCx;\nextern unsigned int WinCy;\nextern unsigned int WinH;\nextern unsigned int WinW;\nextern unsigned int Window;\n\nextern int MoreOn;\nextern char *TXT_MoreText;\n\nextern void (*Window_More_Ptr)(char const *, int, int, int);\n\n#endif //WINDOWS_H\n\n\u001a"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/WSA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WSA 32bit LIbrary                        *\n *                                                                         *\n *                    File Name : WSA.H                                    *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : May 23, 1994                             *\n *                                                                         *\n *                  Last Update : May 25, 1994   [SKB]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Open_Animation -- file name and flags, system allocates buffer.       *\n *   Open_Animation -- file name, flags, palette, system allocates buffer. *\n *   Open_Animation -- file_name, graphic buffer, flags.                   *\n *   Open_Animation -- file name, bufferclass, flags, palette.             *\n *   Open_Animation -- filename, ptr, size, flags, no palette.             *\n *   Animate_Frame -- Animate a frame to a page with magic colors.         *\n *   Animate_Frame -- Animate a frame to a viewport with magic colors.     *\n *   Animate_Frame -- Animate a frame to a page.                           *\n *   Animate_Frame -- Animate a frame to a viewport.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WSA_H\n#define WSA_H\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n#ifndef GBUFFER_H\n#include \"gbuffer.h\"\n#endif\n\n#ifndef VBUFFER_H\n#include \"vbuffer.h\"\n#endif\n\n//lint -strong(AJX,WSAType)\ntypedef enum {\n\tWSA_NORMAL,\t\t\t\t\t\t\t\t// Normal WSA animation\n\tWSA_GHOST\t \t= 0x1000,\t\t\t// Or'd with the above flags to get ghosting\n\tWSA_PRIORITY2 \t= 0x2000,\t\t\t// Copy using a priority (or in the priority)\n\tWSA_TRANS    \t= 0x4000,\t\t\t// Copy frame, ignoring transparent colors\n\tWSA_PRIORITY \t= 0x8000\t\t\t\t// Copy using a priority (or in the priority)\n} WSAType;\n\n\n//lint -strong(AJX,WSAOpenType)\ntypedef enum {\n\tWSA_OPEN_FROM_MEM\t\t= 0x0000,\t// Try to load entire anim into memory.\n\tWSA_OPEN_INDIRECT\t\t= 0x0000,\t// First animate to internal buffer, then copy to page/viewport.\n\tWSA_OPEN_FROM_DISK\t= 0x0001,\t// Force the animation to be disk based.\t\n\tWSA_OPEN_DIRECT\t\t= 0x0002,\t// Animate directly to page or viewport.\n\n\t// These next two have been added for the 32 bit library to give a better idea of what is\n\t// happening.  You may want to animate directly to the destination or indirectly to the\n\t// destination by using the animations buffer.  Indirecly is best if the dest is a seenpage\n\t// and the animation is not linear or if the destination is modified between frames.\n\tWSA_OPEN_TO_PAGE  = WSA_OPEN_DIRECT ,\n\tWSA_OPEN_TO_BUFFER= WSA_OPEN_INDIRECT ,\n\n} WSAOpenType;\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WSA.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nVOID * cdecl Open_Animation(BYTE const *file_name, BYTE *user_buffer, LONG user_buffer_size, WSAOpenType user_flags, UBYTE *palette=NULL);\nVOID cdecl Close_Animation( VOID *handle );\nBOOL cdecl Animate_Frame(VOID *handle, GraphicViewPortClass& view,\n                         WORD frame_number, WORD x_pixel=0, WORD y_pixel=0,\n                         WSAType flags_and_prio = WSA_NORMAL, VOID *magic_cols=NULL, VOID *magic=NULL);\nWORD cdecl Get_Animation_Frame_Count(VOID *handle);\nBOOL cdecl Animate_Frame(VOID *handle, VideoViewPortClass& view,\n                         WORD frame_number, WORD x_pixel=0, WORD y_pixel=0,\n                         WSAType flags_and_prio = WSA_NORMAL, VOID *magic_cols=NULL, VOID *magic=NULL);\nWORD cdecl Get_Animation_Frame_Count(VOID *handle);\nWORD cdecl Get_Animation_X(VOID const *handle);\nWORD cdecl Get_Animation_Y(VOID const *handle);\nWORD cdecl Get_Animation_Width(VOID const *handle);\nWORD cdecl Get_Animation_Height(VOID const *handle);\nWORD cdecl Get_Animation_Palette(VOID const *handle);\nULONG cdecl Get_Animation_Size(VOID const *handle);\n\n\n/***************************************************************************\n * OPEN_ANIMATION -- file name, flags, palette, system allocates buffer.   *\n *                                                                         *\n *                                                                         *\n * INPUT:   BYTE *file_name - name of file to open.                        *\n *          WSAOpenType user_flags - flags on how to open.                 *\n *          UBYTE *palette - pointer to a palette buffer to fill.          *\n *                                                                         *\n * OUTPUT:  VOID *pointer to animation data.  Must be used for all \t\t\t*\n *               other WSA calls.                                          *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/24/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline VOID *cdecl Open_Animation(BYTE *file_name, WSAOpenType user_flags, UBYTE *palette=NULL) \n{\n\treturn (Open_Animation(file_name, NULL, 0L, user_flags,  palette));\n}\n\n\n/***************************************************************************\n * OPEN_ANIMATION -- file_name, bufferclass, flags. \t\t\t\t\t\t\t\t*\n *                                                                         *\n *                                                                         *\n * INPUT:   BYTE *file_name - name of file to open.                        *\n *          GraphicBufferClass - pointer to a buffer.                      *\n *          WSAOpenType user_flags - flags on how to open.                 *\n *          UBYTE *palette - pointer to a palette buffer to fill.          *\n *                                                                         *\n * OUTPUT:  VOID *pointer to animation data.  Must be used for all \t\t\t*\n *               other WSA calls.                                          *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/24/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline VOID *cdecl Open_Animation(BYTE *file_name, BufferClass& buffer, WSAOpenType user_flags,  UBYTE *palette=NULL) \n{\n\treturn (Open_Animation(file_name, (BYTE *)buffer.Get_Buffer(), buffer.Get_Size(), user_flags, palette));\n}\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LP_ASM.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n\nextern \"C\" {\nUWORD Apply_XOR_Delta(BYTE *source_ptr, BYTE *delta_ptr);\nVOID  Apply_XOR_Delta_To_Page_Or_Viewport(VOID *target, VOID *delta, WORD width, WORD nextrow, WORD copy);\n}\n\n\n\n#endif // WSA_H\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/WWLIB32.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 User include file                *\n *                                                                         *\n *                    File Name : WWLIB32.H                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWLIB32_H\n#define WWLIB32_H\n\n#include <wwstd.h>\n\n#include <audio.h>\n#include <buffer.h>\n#include <descmgmt.h>\n#include\t<dipthong.h>\n#include <file.h>\n#include <font.h>\n#include <gbuffer.h>\n#include <iff.h>\n#include <keyboard.h>\n#include <mcgaprim.h>\n#include <misc.h>\n#include <mono.h>\n#include <palette.h>\n#include <playcd.h>\n#include <shape.h>\n#include <tile.h>\n#include <timer.h>\n#include <video.h>\n#include <vbuffer.h>\n#include <windows.h>\n#include <wsa.h>\n#include <wwmem.h>\n\n\n\n\n#endif // WWLIB32_H\n\u001a\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/WWMEM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory System                            *\n *                                                                         *\n *                    File Name : MEM.H                                    *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : April 4, 1994                            *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWMEM_H\n#define WWMEM_H\n\n#include \"wwstd.h\"\n#include \"new.h\"\n#include \"memflag.h\"\n\n// Defines\n//==============\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MEM.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint  Mem_Init(void *buffer, long size);\nvoid *Mem_Alloc(void *poolptr, long lsize, unsigned long id);\nint  Mem_Free(void *poolptr, void *buffer);\nvoid Mem_Reference(void *node);\nvoid Mem_Lock_Block(void *node);\nvoid Mem_In_Use(void *node);\nvoid *Mem_Find(void *poolptr, unsigned long id);\nunsigned long Mem_Get_ID(void *node);\nvoid *Mem_Find_Oldest(void *poolptr);\nvoid *Mem_Free_Oldest(void *poolptr);\nlong Mem_Pool_Size(void *poolptr);\nlong Mem_Avail(void *poolptr);\nlong Mem_Largest_Avail(void *poolptr);\nvoid Mem_Cleanup(void *poolptr);\n\n\n#endif\n\u001a\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/WWMEM.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Memory System                            *\n;*                                                                         *\n;*                    File Name : WWMEM.INC                                *\n;*                                                                         *\n;*                   Programmer : Ian M. Leslie                            *\n;*                                                                         *\n;*                   Start Date : August 11, 1994                          *\n;*                                                                         *\n;*                  Last Update : August 17, 1994   [IML]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nMEM_NORMAL EQU 0000h\t\t; Default memory (normal).\nMEM_NEW\t   EQU 0001h\t\t; Called by the operator new and was overloaded.\nMEM_CLEAR  EQU 0002h \t\t;\n\nGLOBAL\t\t@Alloc$qul14MemoryFlagType:PROC\nGLOBAL\t\t@Free$qpv:PROC\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/WWSTD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : wwstd.h                                  *\n *                                                                         *\n *                    File Name : WWLIB.H                                  *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : March 1, 1994                            *\n *                                                                         *\n *                  Last Update : March 1, 1994   []                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#define\tWWSTD_H\n\n\n// Note: SKB 4/11/94\n// Before this library is done, this needs to be able to be set to TRUE.\n// Once it is, the FALSE parts should be removed from the source code.\n#define LIB_EXTERNS_RESOLVED FALSE \n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <dos.h>\n#include <bios.h>\n\n//================================\n\n// TRUE and FALSE are defined in pltypes.h\n\n#ifndef IBM\n#define IBM\t\t\t\tTRUE\n#endif\n\n#ifndef AMIGA\n#define AMIGA\t\t\tFALSE\n#endif\n\n#ifndef\tSEGA\n#define\tSEGA\t\t\tFALSE\n#endif\n\n/*\n**\tCommon constants used in normal code.\n*/\n#define ERROR\t\t-1\n\n#ifdef NULL\n#undef\tNULL\n#endif\n\n#ifndef NULL\n#define NULL\t\t0L\n#endif\n\n#ifdef VOID\n#undef VOID\n#endif\n\n#define PRIVATE\t\tstatic\n#define PUBLIC\t\t\t/* Routines & data don't have a specifier */\n\n#ifdef __cplusplus\n#define\t__CPPARGS\t...\n#else\n#define\t__CPPARGS\t\n#endif\n\n// This macro will get the size (in elements) of the specified array.\n#ifdef GET_SIZE\n#undef GET_SIZE\n#endif\n#define GET_SIZE(a)\t\t\t\t\t((sizeof(a) / sizeof(*a)))\n\n// Returns the absolute value of the number.\n#ifdef ABS\n#undef ABS\n#endif\ntemplate<class T> T ABS(T a)\n{\n\treturn (a < 0) ? -a : a;\n}\nint ABS(int);\nlong ABS(long);\n\n// Returns the minimum of the two numbers.\n#ifdef MIN\n#undef MIN\n#endif\ntemplate<class T> T MIN(T a, T b)\n{\n\treturn (b < a) ? b : a;\n};\nshort MIN(short, short);\nint MIN(int, int);\nlong MIN(long, long);\n\n// Returns the maximum of the two numbers.\n#ifdef MAX\n#undef MAX\n#endif\ntemplate<class T> T MAX(T a, T b)\n{\n\treturn (b > a) ? b : a;\n};\nshort MAX(short, short);\nint MAX(int, int);\nlong MAX(long, long);\n\n// Returns the low word of a long\n#define\tLOW_WORD(a)\t\t((unsigned short)((long)(a) & 0x0000FFFFL))\n\n// Returns the high word of a long\n#define\tHIGH_WORD(a)\t((unsigned long)(a) >> 16)\n\n// Merges to shorts to become a long\n#define\tMAKE_LONG(a,b) (((long)(a) << 16) | (long)((b)&0x0000FFFFL))\n\n/*\n** Macro allows our routines to act like\n** sprintf etc..\n*/\n#ifdef AssembleTo\n#undef AssembleTo\n#endif\n\n#define AssembleTo(dest,fmt)\\\n{\\\n\tva_list argptr;\\\n\tif (fmt != (dest))\\\n\t\t{\\\n\t\tva_start (argptr, fmt);\\\n\t\tvsprintf ((dest), fmt, argptr);\\\n\t\tva_end (argptr);\\\n\t\t}\\\n}\n\n// type definitions\n//=======================================\ntypedef void \tVOID;\n\n//==================================================\n// Pharlape defines these for use so we use their\n// typedefs!\n//\t\ttypedef\tunsigned char\tBOOL;\n//\t\ttypedef signed long\t\tLONG;\n//\t\ttypedef unsigned long\tULONG;\n//==================================================\n#ifndef PRIVATE\n#define  PRIVATE\tstatic\n#endif\n\n// The purpose of the INT and UINT is for efficiency.  It says that while a short int (16 bit)\n// has enough precision, it is more efficient to pass in an int (32 bits).  For efficiency, most\n// WORD and UWORD should be an INT or UINT, especially on the stack and structures that will\n// not be in large arrays.  When size efficiency is more important then speed, use WORD UWORD.\n\n#define\tVOID\t\tvoid\n\n#pragma\twarn -eas\n#define\tTRUE\t\t1\n#define\tFALSE\t\t0\n\n#define\tBOOL\t\tint\t\t\t\t\t// 32 bits for speed. use CHAR for size optimizations.\n\n#ifndef HMI_DRIVER\n#define\tINT\t\tint\n#define\tUINT\t\tunsigned int\n#define\tBYTE\t\tchar\n#define\tUBYTE\t\tunsigned char\n#define  UCHAR\t   unsigned char\n#define\tWORD\t\tsigned \tshort\n#define\tUWORD\t\tunsigned short\n#define  USHORT\tunsigned short\n\n#define\tLONG\t\tsigned \tlong\n#define\tULONG\t\tunsigned long\n#define  REALPTR\tunsigned long\n\n#define\tFARPTR  char far *\n\n#endif\n\n\n/*\n**\tThe type of processor running on this system as\n**\treturned by Processor().\n*/\n#define\tPROC_80386\t\t0\n#define\tPROC_80486\t\t1\n#define\tPROC_PENTIUM\t2\n\n\n// Inline Routines\n//\n//\n// These Template functions are generally used \n// by classes when they havce over loaded > and <.\n//\n#ifdef __cplusplus\ntemplate<class T> T Min(T a, T b)\n{\n\treturn (a<b ? a : b);\n}\n\ntemplate<class T> inline  T Max(T a, T b)\n{\n\treturn (a>b ? a : b);\n}\n\ntemplate<class T> T Abs(T a)\n{\n\treturn ((a<0) ? -(a) : a);\n}\n\ntemplate<class T> VOID minimize(T &a, T b)\n{\n\tif( b<a )\n\t\ta=b;\n}\n\ntemplate<class T> VOID maximize(T &a, T b)\n{\n\tif( b>a )\n\t\ta=b;\n}\n#endif\n\n/*\n**\tMacros that control bit settings in a variable.\n*/\n#define Bit_Flags_On(a,b)\t\t\ta |= (b)\n#define Bit_Flags_Off(a,b)\t\t\ta &= (~(b))\n#define Bit_Flags_Value(a,b)\t\t(a & (b))\n#define Bit_Flags_Flip(a,b)\t\ta ^= (b)\n\n// Template replacements for the user defines above\n#ifdef __cplusplus\ntemplate<class T> VOID BitFlagsOn(T &a, T b)\n{\n\ta |= (b);\n}\n\ntemplate<class T> VOID BitFlagsOff(T &a, T b)\n{\n\ta &= (~(b));\n}\n\ntemplate<class T> T BitFlagsValue(T a, T b)\n{\n\treturn (a & (b));\n}\n\ntemplate<class T> VOID BitFlagsFlip(T &a, T b)\n{\n\ta ^= (b);\n}\n#endif\n\ntypedef enum {\t\n\tTBLACK, \n\tPURPLE, \n\tCYAN, \n\tGREEN, \n\tLTGREEN, \n\tYELLOW, \n\tPINK, \n\tBROWN, \n\tRED, \n\tLTCYAN, \n\tLTBLUE, \n\tBLUE, \n\tBLACK, \n\tGREY,\n\tLTGREY, \n\tWHITE,\n\tCOLOR_PADDING=0x1000\n} ColorType;\n\n\n#endif\n\n\n"
  },
  {
    "path": "VQ/INCLUDE/WWLIB32/_FILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library - Filio header stuff.            *\n;*                                                                         *\n;*                    File Name : FILE.H                                 \t*\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : September 13, 1993                       *\n;*                                                                         *\n;*                  Last Update : April 11, 1994\t\t\t\t\t\t\t\t\t*\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FILE_H\n#include \"file.h\"\n#endif\n\n#ifndef _FILE_H\n#define _FILE_H\n\n\n/*=========================================================================*/\n/* Fileio defines\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#define\tLIB_CDROM TRUE\n\n#define MODE_OLDFILE\t\t\t\t(O_RDONLY | O_BINARY)\n#define MODE_NEWFILE\t\t\t\t(O_WRONLY | O_BINARY | O_CREAT | O_TRUNC)\n#define MODE_READWRITE\t\t\t(O_RDWR   | O_BINARY)\n\n#define FILEOPENERROR\t\t\t-1\n#define FILEOPEN(f,m)\t\t\tibm_open(f, m, (((UWORD) m) == MODE_OLDFILE) ? S_IREAD : (S_IREAD | S_IWRITE))\n\n#define FILECLOSE(fd)\t\t\tibm_close(fd)\n#define FILEREAD(f,b,n)\t\t\tibm_read(f,b,(WORD)(n))\n#define FILEWRITE(f,b,n)\t\tibm_write(f,b,(WORD)(n))\n#define FILESEEK(f,b,n)\t\t\tibm_lseek(f, b, n)\n#define FILEDELETE(f)\t\t\tibm_unlink(f)\n#define CHANGEDIR(p)\t\t\t\tibm_chdir(p)\n\n#define FILENAMESIZE\t\t\t\t13\n#define IO_CHUNK_SIZE\t\t\t0xfff0UL\n\n/* \n**\tMaximum number of file handles \n*/\n#define TABLE_MAX\t\t\t20\n\n \n/*=========================================================================*/\n/* The file handle table */\n/*=========================================================================*/\ntypedef struct {\n\tBOOL\t\t\t\t\t\tEmpty;\t\t// Is this handle empty?\n\tWORD\t\t\t\t\t\tHandle;\t\t// DOS file handle (0 = resident).\n\tLONG\t\t\t\t\t\tPos;\t\t\t// Current file position.\n\tLONG\t\t\t\t\t\tStart;\t\t// Offset of file from pointer.\n\tWORD\t\t\t\t\t\tIndex;\t\t// FileData[] index.\n\tWORD\t\t\t\t\t\tMode;\t\t\t// Access mode (WW).\n\tBYTE\t\t\t\t\t\t*Name;\t\t// File name pointer.\n} FileHandleType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILEIO.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD ibm_getdisk(VOID);\nWORD ibm_setdisk(WORD drive);\nWORD ibm_close(WORD handle);\nWORD ibm_unlink(BYTE const *name);\nLONG ibm_lseek(WORD handle, LONG offset, WORD where);\nUWORD ibm_read(WORD handle, VOID *ptr, UWORD bytes);\nUWORD ibm_write(WORD handle, VOID *ptr, UWORD bytes);\nWORD ibm_open(BYTE const *name, UWORD mode, WORD attrib);\nWORD ibm_chdir(BYTE const *path);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILELIB.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD cdecl Do_Open_Error(FileErrorType errormsgnum, BYTE const *file_name);\nVOID cdecl Do_IO_Error(FileErrorType errormsgnum, BYTE const *filename);\nLONG cdecl Read_File_With_Recovery( WORD handle, VOID *buf, UWORD bytes );\nWORD cdecl Open_File_With_Recovery( BYTE const *file_name, UWORD mode );\nBOOL cdecl Cache_File(WORD index, WORD file_handle);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DEVICES.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Get_Devices(VOID);\nextern WORD Is_Device_Real(WORD device);\n\n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DEVTABLE.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Init_Device_Table(BYTE *table);\nextern WORD Max_Device(VOID);\n\n\n#ifdef __cplusplus\n}\n#endif\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: HARDERR.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Install_Hard_Error_Handler(VOID);\nextern VOID Remove_Hard_Error_Handler(VOID);\n\n#ifdef __cplusplus\n}\n#endif\n\n\n/*=========================================================================*/\n/* Globale variables in the fileio system.\t\t\t\t\t\t               */\n/*=========================================================================*/\n\nextern BYTE CallingDOSInt;\t\t\t\t\t \nextern \"C\" extern BYTE MaxDevice,DefaultDrive;\nextern BYTE MultiDriveSearch;\t\nextern FileDataType *FileDataPtr;\nextern FileHandleType FileHandleTable[TABLE_MAX];\nextern UWORD NumFiles;\t\t\t\t\t\t\t \t// Number of files, except PAK, in file table.\nextern UWORD NumPAKFiles;\t\t\t\t\t\t\t// Number of PAK files in filetable.\nextern VOID *FileCacheHeap;\t\t\t\t\t\t// Pointer to the cache in memory.\nextern WORD DiskNumber;\t\t\t\t\t\t \nextern WORD MaxDirNum;\n\n\n/*=========================================================================*/\n\t \n\n\n#endif // _FILE_H\n\n\n"
  },
  {
    "path": "VQ/INCLUDE/WWTYPES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef WWTYPES_H\n#define WWTYPES_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILENAME\n*     wwtypes.h\n*\n* DESCRIPTION\n*     Westwood standard types definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*      \n****************************************************************************/\n\n#define\tTRUE  1\n#define\tFALSE 0\n\n#define\tVOID    void\n#define\tPRIVATE static\n#define\tPUBLIC\n\n#define\tBOOL  short\n#define\tBYTE  char\n#define\tUBYTE unsigned char\n#define\tWORD  signed short\n#define\tUWORD unsigned short\n#define\tLONG  signed long\n#define\tULONG unsigned long\n\n#endif /* WWTYPES_H */\n\n"
  },
  {
    "path": "VQ/LIB/README.TXT",
    "content": "Library naming convention.\n\n   nnnssctm.lib\n\n   Where:\n     nnn = ID (such as 'VQA') 3 characters\n     ss  = Size field (32bit / 16bit) 2 characters\n     c   = Compiler name (W = Watcom, B = Borland)\n     t   = Compiler type (P = \"C++\", C = Standard \"C\")\n     m   = Memory model (F = flat, T = TNT)\n"
  },
  {
    "path": "VQ/VQA32/AUDIO.BAK1",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*---------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     audio.c\n*\n* DESCRIPTION\n*     Audio playback and timing.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 10, 1995\n*\n*---------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_StartTimerInt - Initialize system timer interrupt.\n*     VQA_StopTimerInt  - Remove system timer interrupt.\n*     VQA_SetTimer      - Resets current time to given tick value.\n*     VQA_GetTime       - Return current time.\n*     VQA_TimerMethod   - Get timer method being used.\n*     VQA_OpenAudio     - Open sound system.\n*     VQA_CloseAudio    - Close sound system\n*     VQA_StartAudio    - Starts audio playback\n*     VQA_StopAudio     - Stop audio playback.\n*     CopyAudio         - Copy data from Audio Temp buf into Audio play buf.\n*\n* PRIVATE\n*     TimerCallback - Timer callback routine; called by HMI\n*     AutoDetect    - Auto detect the sound card.\n*     AudioCallback - Sound system callback.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <malloc.h>\n#include <mem.h>\n#include <sys\\timeb.h>\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n\n#ifdef __WATCOMC__\n#pragma pack(4);\n#endif\n\n#if(VQAAUDIO_ON)\n#include \"sos.h\"\n#endif\n\n/*---------------------------------------------------------------------------\n * AUDIO DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n#define HMI_SAMPLE       0x1000\n#define HMI_DEFAULT_RATE 22050\n\n#define HMI_UNINIT  0  /* Unitialize state. */\n#define HMI_VQAINIT 1  /* VQA initialized */\n#define HMI_APPINIT 2  /* Application initialized */\n\n#if(VQAAUDIO_ON)\n/*---------------------------------------------------------------------------\n * PROTOTYPES\n *-------------------------------------------------------------------------*/\n\nlong AutoDetect(long bitsize, long channels);\nvoid far TimerCallback(void);\nvoid far cdecl AudioCallback(WORD wDriverHandle, WORD wAction,\n\t\tWORD wSampleID);\n\n/*---------------------------------------------------------------------------\n * GLOBAL DATA\n *-------------------------------------------------------------------------*/\n\n/* HMI Start Sample structure:\n *\n * lpSamplePtr            - Pointer to audio buffer.\n * dwSampleSize           - Size of buffer.\n * wLoopCount             - Number of time to loop (-1 = infinate)\n * wChannel               - Channel to play sample on.\n * wVolume                - Volume level to play at.\n * wSampleID              - ID for sample\n * lpCallback             - Callback function pointer.\n * wSamplePort            - Port to use for non-DMA\n * wSampleFlags           - Flags\n * dwSampleByteLength     - Total length including loops\n * dwSampleLoopPoint      -\n * dwSampleLoopLength     -\n * dwSamplePitchAdd       - Pitch shifting component.\n * wSamplePitchFraction   - Pitch shifting component.\n * wSamplePanLocation     - For panning\n * wSamplePanSpeed        - For panning\n * wSamplePanDirection    - For panning\n * wSamplePanStart        - For panning.\n * wSamplePanEnd          - For panning.\n * wSampleDelayBytes      - Delay part.\n * wSampleDelayRepeat     - Delay part.\n * dwSampleADPCMPredicted - For compression\n * wSampleADPCMIndex      - For compression\n * wSampleRootNoteMIDI    - Root note for pitch shift\n * dwFiller[3]            - Filler for future upgrades.\n */\n_SOS_START_SAMPLE sSOSSampleData = {\n\t_NULL,\n\t0L,\n\t0,\n\t_CENTER_CHANNEL,\n\t0x7FFF,\n\tHMI_SAMPLE,\n\tAudioCallback,\n\t0,\n\t0,\n\t0L,\n\t0L,0L,\n\t0L,0,\n\t0,0,0,0,0,\n\t0,0,\n\t0L,0,\n\t0,\n\t0L,0L,0L\n};\n\n/* HMI Driver structure: Driver initialization structure.\n *\n * wBufferSize     - Size of play buffer.\n * lpBuffer        - Pointer to buffer.\n * wAllocateBuffer - Allocate buffer flag.\n * wSampleRate     - Playback rate.\n * wParam          -\n * dwParam         -\n * lpFillHandler   -\n * lpDriverMemory  -\n * lpTimerMemory   -\n * wTimerID        -\n */\n_SOS_INIT_DRIVER sSOSInitDriver = {\n\t0,\n\t_NULL,\n\t_TRUE,\n\tHMI_DEFAULT_RATE,\n\t19,\n\t0L,\n\t_NULL,\n\t_NULL,\n\t_NULL,\n\t_SOS_NORMAL_TIMER\n};\n\nstatic _SOS_CAPABILITIES DigiCaps;\nstatic _SOS_HARDWARE DigiHardware;\nstatic WORD DigiHandle = -1;\nstatic WORD DigiTimer = 0;\nstatic WORD SampleHandle;\nstatic long DigiInitFlag = HMI_UNINIT;\nstatic long PlayingFlag = 0;\n\nstatic VQAHandleP *VQAP;\nstatic unsigned long CurBlock = 0;\nstatic unsigned long NextBlock;\n\nstatic WORD VQATimer = 0;\nstatic long TimerMethod;\nstatic long TimerInitFlag = HMI_UNINIT;\nstatic long HMITimerFlag = HMI_UNINIT;\nstatic long VQATickCount = 0;\n#endif /* VQAAUDIO_ON */\n\nstatic long TickOffset = 0;\nchar *HMIDevName = \"<none>\";\n\n\n#if(VQAAUDIO_ON)\n/****************************************************************************\n*\n* NAME\n*     VQA_StartTimerInt - Initialize system timer interrupt.\n*\n* SYNOPSIS\n*     Error = VQA_StartTimerInt(Init)\n*\n*     long VQA_StartTimerInt(long);\n*\n* FUNCTION\n*     Initialize the HMI timer system if it hasn't been already then add\n*     our own timer event.\n*\n* INPUTS\n*     Init - Initialize HMI timer system flag. (TRUE = Initialize)\n*\n* RESULT\n*     Error - 0 if successful, -1 if error.\n*\n****************************************************************************/\n\nlong VQA_StartTimerInt(long init)\n{\n\t/* Does the caller want me to initialize the timer system? */\n\tif (init == 0) {\n\n\t\t/* If the timer system is uninitialized then it is the players\n\t\t * responsibility to do it.\n\t\t */\n\t\tif (TimerInitFlag == HMI_UNINIT) {\n\t\t\tsosTIMERInitSystem(_TIMER_DOS_RATE, _SOS_DEBUG_NORMAL);\n\t\t\tTimerInitFlag = HMI_VQAINIT;\n\t\t}\n\t} else {\n\t\tTimerInitFlag = HMI_APPINIT;\n\t}\n\n\t/* Register the VQA_TickCount timer event. */\n\tif (HMITimerFlag == HMI_UNINIT) {\n\t\tif (sosTIMERRegisterEvent(VQA_TIMETICKS, TimerCallback,\n\t\t\t\t&VQATimer) == 0) {\n\n\t\t\tHMITimerFlag = HMI_VQAINIT;\n\t\t} else {\n\t\t\treturn (-1);\n\t\t}\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StopTimerInt - Remove system timer interrupt.\n*\n* SYNOPSIS\n*     VQA_StopTimerInt()\n*\n*     void VQA_StopTimerInt(void);\n*\n* FUNCTION\n*     Remove our timer event from the HMI timer system. Uninitialize the\n*     HMI timer system if we initialized it.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_StopTimerInt(void)\n{\n\t/* Remove the timer event */\n\tif (HMITimerFlag == HMI_VQAINIT) {\n\t\tsosTIMERRemoveEvent(VQATimer);\n\t}\n\n\tHMITimerFlag = HMI_UNINIT;\n\n\tif (TimerInitFlag == HMI_VQAINIT) {\n\t\tsosTIMERUnInitSystem(0);\n\t}\n\n\tTimerInitFlag = HMI_UNINIT;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     TimerCallback - VQA timer event. (Called by HMI)\n*\n* SYNOPSIS\n*     TimerCallback()\n*\n*     void TimerCallback(void);\n*\n* FUNCTION\n*     Our custom timer event. This is the timer event that we register with\n*     HMI for system timing.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid far TimerCallback(void)\n{\n\tVQATickCount++;\n}\n#endif /* VQAAUDIO_ON */\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_SetTimer - Resets current time to given tick value.\n*\n* SYNOPSIS\n*     VQA_SetTimer(Time, Method)\n*\n*     void VQA_SetTimer(long, long);\n*\n* FUNCTION\n*     Sets 'TickOffset' to a value that will make the current time look like\n*     the time passed in. This function allows the player to be \"paused\",\n*     by recording the time of the pause, and then setting the timer to\n*     that time. The timer method used by the player is also set. The method\n*     selected is not neccesarily the method that will be used because some\n*     timer methods work with only certain playback conditions. (EX: The\n*     audio DMA timer method cannot be used if there is not any audio\n*     playing.)\n*\n* INPUTS\n*     Time   - Value to set current time to.\n*     Method - Timer method to use.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_SetTimer(long time, long method)\n{\n\tunsigned long curtime;\n\n\t#if(VQAAUDIO_ON)\n\t/* If the client does not have a preferencee then pick a method\n\t * based on the state of the player.\n\t */\n\tif (method == VQA_TMETHOD_DEFAULT) {\n\n\t\t/* If we are playing audio, use the audio DMA position. */\n\t\tif (PlayingFlag) {\n\t\t\tmethod = VQA_TMETHOD_AUDIO;\n\t\t}\n\n\t\t/* Otherwise use the HMI timer if it is initialized. */\n\t\telse if (HMITimerFlag) {\n\t\t\tmethod = VQA_TMETHOD_INT;\n\t\t}\n\n\t\t/* If all else fails resort the the \"jerky\" DOS time. */\n\t\telse {\n\t\t\tmethod = VQA_TMETHOD_DOS;\n\t\t}\n\t} else {\n\n\t\t/* We cannot use the DMA position if there isn't any audio playing. */\n\t\tif (!PlayingFlag && (method == VQA_TMETHOD_AUDIO)) {\n\t\t\tmethod = VQA_TMETHOD_INT;\n\t\t}\n\n\t\t/* We cannot use the timer if it has not been initialized. */\n\t\tif (!HMITimerFlag && (method == VQA_TMETHOD_INT)) {\n\t\t\tmethod = VQA_TMETHOD_DOS;\n\t\t}\n\t}\n\n\tTimerMethod = method;\n\t#endif\n\n\tTickOffset = 0L;\n\tcurtime = VQA_GetTime();\n\tTickOffset = (time - curtime);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_GetTime - Return current time.\n*\n* SYNOPSIS\n*     Time = VQA_GetTime()\n*\n*     unsigned long VQA_GetTime(void);\n*\n* FUNCTION\n*     This routine returns timer ticks computed one of 3 ways:\n*\n*     1) If audio is playing, the timer is based on the DMA buffer position:\n*        Compute the number of audio samples that have actually been played.\n*        The following internal HMI variables are used:\n*\n*          _lpSOSDMAFillCount[drv_handle]: current DMA buffer position\n*          _lpSOSSampleList[drv_handle][samp_handle]:\n*          sampleTotalBytes: total bytes sent by HMI to the DMA buffer\n*          sampleLastFill: HMI's last fill position in DMA buffer\n*\n*        So, the number of samples actually played is:\n*\n*          sampleTotalBytes - <DMA_diff>\n*          where <DMA_diff> is how far ahead sampleLastFill is in front of\n*          _lpSOSDMAFillCount: (sampleLastFill - _lpSOSDMAFillCount)\n*\n*        These values are indices into a circular DMA buffer, so:\n*\n*          if (sampleLastFill >= _lpSOSDMAFillCount)\n*            <DMA_diff> = sampleLastFill - _lpSOSDMAFillCount\n*          else\n*            <DMA_diff> = (DMA_BUF_SIZE - lpSOSDMAFillCount) + sampleLastFill\n*\n*        Note that, if using the stereo driver with mono data, you must\n*        divide LastFill & FillCount by 2, but not TotalBytes. If using the\n*        stereo driver with stereo data, you must divide all 3 variables\n*        by 2.\n*\n*     2) If no audio is playing, but the timer interrupt is running,\n*        VQATickCount is used as the timer\n*\n*     3) If no audio is playing & no timer interrupt is going, the DOS 18.2\n*        system timer is used.\n*\n*     Regardless of the method, TickOffset is used as an offset from the\n*     computed time.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Time - Time in VQA_TIMETICKS\n*\n****************************************************************************/\n\nunsigned long VQA_GetTime(void)\n{\n\t#if(VQAAUDIO_ON)\n\tVQAAudio      *audio;\n\tunsigned long totalbytes;\n\tunsigned long fillcount;\n\tunsigned long lastfill;\n\tunsigned long dma_diff;\n\tunsigned long samples;\n\t#endif\n\n\tlong ticks;\n\n\t#if(VQAAUDIO_ON)\n\tswitch (TimerMethod) {\n\n\t\t/* If Audio is playing then timing is based on the audio DMA buffer\n\t\t * position.\n\t\t */\n\t\tcase VQA_TMETHOD_AUDIO:\n\n\t\t\t/* Dereference commonly used data members for quicker access. */\n\t\t\taudio = &VQAP->VQABuf->Audio;\n\n\t\t\t/* Get private HMI values */\n\t\t\tfillcount = (*_lpSOSDMAFillCount[DigiHandle]);\n\t\t\tlastfill = _lpSOSSampleList[DigiHandle][SampleHandle]->sampleLastFill;\n\t\t\ttotalbytes = _lpSOSSampleList[DigiHandle][SampleHandle]->sampleTotalBytes;\n\n \t\t\t/* At the very first, sometimes HMI reports a non-zero DMA buffer\n\t\t\t * position even though totalbytes is 0.  Obviously, if totalbytes\n\t\t\t * is 0, the DMA buffer position must be 0 too.\n\t\t\t */\n\t\t\tif (totalbytes == 0) {\n\t\t\t\tdma_diff = 0;\n\t\t\t} else {\n\n\t\t\t\t/* Compute the number of bytes played. */\n\t\t\t\tif (lastfill >= fillcount) {\n\t\t\t\t\tdma_diff = (lastfill - fillcount);\n\t\t\t\t} else {\n\t\t\t\t\tdma_diff = (VQAP->Config.HMIBufSize - fillcount) + lastfill;\n\t\t\t\t}\n\n\t\t\t\t/* Sometimes the dma difference ends up being larger than the number\n\t\t\t\t * of bytes processed, so we must compensate for this in order to\n\t\t\t\t * keep the player from skipping unecessarilly.\n\t\t\t\t */\n\t\t\t\tif (dma_diff > totalbytes) {\n\t\t\t\t\tdma_diff = 0L;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* The number of samples played is computed from the number of bytes\n\t\t\t * played divided by the size of the sample and the number of channels.\n\t\t\t */\n\t\t\tsamples = totalbytes - dma_diff;\n\n\t\t\t#if(0)\n\t\t\t/* Do not figure in skipped audio frames. */\n\t\t\tsamples -= (audio->NumSkipped * VQAP->Config.HMIBufSize);\n\t\t\t#endif\n\n\t\t\tsamples /= (audio->Channels * (audio->BitsPerSample >> 3));\n\n\t\t\t/* Convert to time ticks */\n\t\t\tticks = (long)((samples * VQA_TIMETICKS) / sSOSInitDriver.wSampleRate);\n\t\t\tticks += TickOffset;\n\t\t\tbreak;\n\n\t\t/* No audio playing, but timer interrupt is going; use VQATickCount */\n\t\tcase VQA_TMETHOD_INT:\n\t\t\tticks = (VQATickCount + TickOffset);\n\t\t\tbreak;\n\n\t\t/* No interrupts are going at all; use DOS's time */\n\t\tdefault:\n\t\tcase VQA_TMETHOD_DOS:\n\t\t\t{\n\t\t\tstruct timeb mytime;\n\n\t\t\tftime(&mytime);\n \t\t\tticks = (unsigned long)mytime.time*1000L+(unsigned long)mytime.millitm;\n\t\t\tticks = ((ticks * VQA_TIMETICKS) / 1000L);\n\t\t\tticks += TickOffset;\n\t\t\t}\n\t\t\tbreak;\n\t}\n\t#else\n\t{\n\tstruct timeb mytime;\n\n\tftime(&mytime);\n\tticks = (unsigned long)mytime.time*1000L+(unsigned long)mytime.millitm;\n\tticks = ((ticks * VQA_TIMETICKS) / 1000L);\n\tticks += TickOffset;\n\t}\n\t#endif\n\n\treturn (ticks);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_TimerMethod - Get timer method being used.\n*\n* SYNOPSIS\n*     Method = VQA_TimerMethod()\n*\n*     long VQA_TimerMethod(void);\n*\n* FUNCTION\n*     Returns the ID of the current timer method being used.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Method - Method used for the timer.\n*\n****************************************************************************/\n\nlong VQA_TimerMethod(void)\n{\n\t#if(VQAAUDIO_ON)\n\treturn (TimerMethod);\n\t#else\n\treturn (VQA_TMETHOD_DOS);\n\t#endif\n}\n\n\n#if(VQAAUDIO_ON)\n/****************************************************************************\n*\n* NAME\n*     VQA_OpenAudio - Open sound system.\n*\n* SYNOPSIS\n*     Error = VQA_OpenAudio(VQAHandleP)\n*\n*     long VQA_OpenAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Initialize the sound system by setting the DigiHandle to and HMI\n*     driver handle. The timer must first be initialized before calling\n*     this function.\n*\n* INPUTS\n*     VQAHandleP - Pointer to private VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, -1 if error.\n*\n****************************************************************************/\n\nlong VQA_OpenAudio(VQAHandleP *vqap)\n{\n\tVQAData       *vqabuf;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tVQAHeader     *header;\n\tunsigned char *driver_path;\n\tWORD          port;\n\tlong          rc;\n\n\t/* Return if already initialized */\n\tif (DigiInitFlag != HMI_UNINIT) {\n\t\treturn (0);\n\t}\n\n\t/* Dereference data memebers for quicker access. */\n\tconfig = &vqap->Config;\n\theader = &vqap->Header;\n\tvqabuf = vqap->VQABuf;\n\taudio = &vqabuf->Audio;\n\n\t/* Fail if no audio buffer or DigiCard is 0 (no sound) */\n\tif ((audio->Buffer == NULL) || (config->DigiCard == 0)) {\n\t\treturn (-1);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * Compute the playback rate:\n\t *\n\t * - If Config->AudioRate is -1, use HMI_DATA_RATE scaled to the specified\n\t *   frame rate (so the audio plays faster if we're playing faster)\n\t * - otherwise, use the specified rate\n\t *-----------------------------------------------------------------------*/\n\tif (config->AudioRate != -1) {\n\t\tsSOSInitDriver.wSampleRate = config->AudioRate;\n\t}\n\telse if (config->FrameRate != header->FPS) {\n\t\tsSOSInitDriver.wSampleRate = ((audio->SampleRate * config->FrameRate)\n\t\t\t\t/ (unsigned long)header->FPS);\n\n\t\tconfig->AudioRate = sSOSInitDriver.wSampleRate;\n\t} else {\n\t\tsSOSInitDriver.wSampleRate = audio->SampleRate;\n\t\tconfig->AudioRate = sSOSInitDriver.wSampleRate;\n\t}\n\n\t/* If the application has already initialized HMI then set the\n\t * necessary variables. Otherwise we must setup HMI ourself.\n\t */\n\tif (config->OptionFlags & VQAOPTF_HMIINIT) {\n\t\tDigiHandle = config->DigiHandle;\n\t\tHMIDevName = \"App-Specific\";\n\t\tTimerInitFlag = HMI_APPINIT;\n\t\tDigiInitFlag = HMI_APPINIT;\n\t} else {\n\n\t\t/* Init the detection system */\n\t\tdriver_path = (unsigned char *)\".\\\\\";\n\n\t\tif ((rc = sosDIGIDetectInit(driver_path)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/*-----------------------------------------------------------------------\n\t\t * Initialize DigiHardware with port, IRQ, and DMA, and make sure\n\t\t * Config.DigiCard contains the HMI ID we want to use:\n\t\t *\n\t\t * - If Config.DigiCard is -1, auto-detect the hardware; then, do a \n\t\t *   FindHardware so the GetSettings will work\n\t\t * - If Config.DigiCard is filled in, but port, IRQ or DMA is -1, use\n\t\t *   FindHardware & GetSettings to get the settings\n\t\t * - If all are filled in, just use them as they are\n\t\t *---------------------------------------------------------------------*/\n\n\t\t/* Auto-Detect */\n\t\tif (config->DigiCard == -1) {\n\n\t\t\t/* Version 1 VQA's have only 8 bit mono audio streams. */\n\t\t\tif (header->Version == VQAHD_VER1) {\n\t\t\t\tconfig->DigiCard = AutoDetect(8, 1);\n\t\t\t} else {\n\t\t\t\tconfig->DigiCard = AutoDetect(header->BitsPerSample,\n\t\t\t\t\t\theader->Channels);\n\t\t\t}\n\n\t\t\tif (config->DigiCard == -1) {\n\t\t\t\tsosDIGIDetectUnInit();\n\t\t\t\treturn (-1);\n\t\t\t}\n\t\t}\n\n\t\t/* Do a FindHardware & GetSettings */\n\t\tif (config->DigiPort == -1) {\n\t\t  if (sosDIGIDetectFindHardware(config->DigiCard, &DigiCaps, &port)) {\n\t\t\t\tsosDIGIDetectUnInit();\n\t\t\t\treturn (-1);\n\t\t\t}\n\n\t\t\tif (sosDIGIDetectGetSettings(&DigiHardware)) {\n\t\t\t\tsosDIGIDetectUnInit();\n\t\t\t\treturn (-1);\n\t\t\t}\n\n\t\t\tconfig->DigiPort = DigiHardware.wPort;\n\t\t\tconfig->DigiIRQ = DigiHardware.wIRQ;\n\t\t\tconfig->DigiDMA = DigiHardware.wDMA;\n\t\t\tHMIDevName = (char *)DigiCaps.szDeviceName;\n\t\t} else {\n\t\t\tDigiHardware.wPort = config->DigiPort;\n\t\t\tDigiHardware.wIRQ = config->DigiIRQ;\n\t\t\tDigiHardware.wDMA = config->DigiDMA;\n\t\t\tHMIDevName = \"App-Specific\";\n\t\t}\n\n\t\tsosDIGIDetectUnInit();\n\n\t\t/* Initialize the DIGI system & driver */\n\t\tsosDIGIInitSystem(driver_path, _SOS_DEBUG_NORMAL);\n\t\tsSOSInitDriver.wBufferSize = config->HMIBufSize;\n\t\tsSOSInitDriver.lpBuffer = NULL;\n\t\tsSOSInitDriver.lpFillHandler = NULL;\n\t\tsSOSInitDriver.lpDriverMemory = NULL;\n\t\tsSOSInitDriver.lpTimerMemory = NULL;\n\t\tDigiHandle = -1;\n\n\t\tif ((rc = sosDIGIInitDriver(config->DigiCard, &DigiHardware, \n\t\t\t\t&sSOSInitDriver, &DigiHandle)) != 0) {\n\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/*-----------------------------------------------------------------------\n\t\t * Register the timer event\n\t\t *---------------------------------------------------------------------*/\n\n\t\t/* If the timer hasn't been init'd, do it now */\n\t\tif (TimerInitFlag == HMI_UNINIT) {\n\t\t\tsosTIMERInitSystem(_TIMER_DOS_RATE ,_SOS_DEBUG_NORMAL);\n\t\t\tTimerInitFlag = HMI_VQAINIT;\n\t\t}\n\n\t\t/* Register the event */\n\t\trc = sosTIMERRegisterEvent(VQA_TIMETICKS, sSOSInitDriver.lpFillHandler,\n\t\t\t\t&DigiTimer);\n\n\t\tif (rc) {\n\t\t\tsosDIGIUnInitDriver(DigiHandle, _TRUE, _TRUE);\n\t\t\tsosDIGIUnInitSystem();\n\t\t\treturn (rc);\n\t\t}\n\n\t\tDigiInitFlag = HMI_VQAINIT;\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     AutoDetect - Auto detect the sound card.\n*\n* SYNOPSIS\n*     CardID = AutoDetect(BitSize, Channels)\n*\n*     long AutoDetect(long, long);\n*\n* FUNCTION\n*     Autodetects the type of sound card present in the system.\n*\n* INPUTS\n*     BitSize  - Bits per sample size.\n*     Channels - Number of desired channels.\n*\n* RESULT\n*     CardID - HMI ID of the sound card found, -1 if none.\n*\n****************************************************************************/\n\nlong AutoDetect(long bitsize, long channels)\n{\n\tlong device_id = -1;\n\tWORD port;\n\tlong i;\n\tlong rc;\n\n\t/* Search for an 8-bit mono device */\n\tif (sosDIGIDetectFindFirst(&DigiCaps, &port)) {\n\t\treturn (-1);\n\t}\n\n\tchannels--;\n\n\ti = 0;\n\twhile (i < 6) {\n\t\ti++;\n\n\t\tif ((DigiCaps.wBitsPerSample == bitsize)\n\t\t\t\t&& (DigiCaps.wChannels == channels)) {\n\n\t\t\tbreak;\n\t\t}\n\n\t\tif (sosDIGIDetectFindNext(&DigiCaps, &port)) {\n\t\t\treturn (-1);\n\t\t}\n\t}\n\n\t/* Exit if failed to find the required device */\n\tif ((DigiCaps.wBitsPerSample != bitsize)\n\t\t\t|| (DigiCaps.wChannels != channels)) {\n\n\t\treturn (-1);\n\t}\n\n\t/* Stash the ID */\n\tdevice_id = DigiCaps.wDeviceID;\n\n\t/* Now that we have handled the initial pass, verify that if we found an\n\t * _ADLIB_GOLD_8_MONO that it is not a Logitech Sound Wave man in disguise.\n\t */\n\tif ((WORD)DigiCaps.wDeviceID == _ADLIB_GOLD_8_MONO) {\n\t\trc = sosDIGIDetectFindNext(&DigiCaps, &port);\n\n\t\twhile ((i < 6) && (rc == 0)) {\n\t\t\ti++;\n\n\t\t\tif ((DigiCaps.wBitsPerSample == 8) && (DigiCaps.wChannels == 0)) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif ((rc = sosDIGIDetectFindNext(&DigiCaps, &port)) != 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/* If we don't have an error use the secondary device ID, after all, \n\t\t * anything's better than an Adlib Gold.  If we do have an error or there\n\t\t * is nothing we can use then the device ID is already set to the adlib \n\t\t * gold so just let it rip.\n\t\t */\n\t\tif ((rc == 0) && ((WORD)DigiCaps.wDeviceID == _SBPRO_8_MONO)) {\n\t\t\treturn (DigiCaps.wDeviceID);\n\t\t}\n\t}\n\n\treturn (device_id);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_CloseAudio - Close sound system\n*\n* SYNOPSIS\n*     VQA_CloseAudio()\n*\n*     void VQA_CloseAudio(void);\n*\n* FUNCTION\n*     Removes VQA's involvement in the audio system.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_CloseAudio(void)\n{\n\t/* Remove the Digi event */\n\tif (DigiInitFlag == HMI_VQAINIT) {\n\t\tsosTIMERRemoveEvent(DigiTimer);\n\t}\n\n\t/* Un-init timer if necessary */\n\tif (TimerInitFlag == HMI_VQAINIT) {\n\t\tsosTIMERUnInitSystem(0);\n\t}\n\n\tTimerInitFlag = HMI_UNINIT;\n\n\t/* Remove the driver */\n\tif (DigiInitFlag == HMI_VQAINIT) {\n\t\tsosDIGIUnInitDriver(DigiHandle, _TRUE, _TRUE);\n\t\tsosDIGIUnInitSystem();\n\t}\n\n\tDigiInitFlag = HMI_UNINIT;\n\n\tif (PlayingFlag) {\n\t\tPlayingFlag = 0;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StartAudio - Starts audio playback\n*\n* SYNOPSIS\n*     Error = VQA_StartAudio(VQA)\n*\n*     long VQA_StartAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Start the audio playback for the movie.\n*\n* INPUTS\n*     VQA - Pointer to private VQA handle.\n*\n* RESULT\n*     Error - 0 if successful, or -1 error code.\n*\n****************************************************************************/\n\nlong VQA_StartAudio(VQAHandleP *vqap)\n{\n\tVQAConfig *config;\n\tVQAAudio  *audio;\n\n\t/* Save buffers for the callback routine */\n\tVQAP = vqap;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tconfig = &vqap->Config;\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Return if already playing */\n\tif (audio->Flags & VQAAUDF_ISPLAYING) {\n\t\treturn (-1);\n\t}\n\n \t/* Set my driver handle */\n\tif (config->DigiHandle != -1) {\n\t\tDigiHandle = config->DigiHandle;\n\t}\n\n\tif (DigiHandle == (WORD)-1) {\n\t\treturn (-1);\n\t}\n\n\t/* Re-init the sample structure */\n\tmemset(&sSOSSampleData, 0, sizeof(_SOS_START_SAMPLE));\n  sSOSSampleData.lpSamplePtr = (unsigned char *)vqap->VQABuf->Audio.Buffer;\n \tsSOSSampleData.dwSampleSize = config->HMIBufSize;\n\tsSOSSampleData.wVolume = (config->Volume << 7);\n\tsSOSSampleData.wSampleID = HMI_SAMPLE;\n\tsSOSSampleData.lpCallback = AudioCallback;\n\tsSOSSampleData.wSampleFlags = (_VOLUME|1);\n\n\tif (audio->Channels == 2) {\n\t\tsSOSSampleData.wChannel = _INTERLEAVED;\n\t} else {\n\t\tsSOSSampleData.wChannel = _CENTER_CHANNEL;\n\t}\n\n\t/* Start playback */\n\t#if(0) // Don't reset this to zero or pause will break.\n\tCurBlock = 0;\n\t#endif\n\n \tSampleHandle = sosDIGIStartSample(DigiHandle, &sSOSSampleData);\n\taudio->Flags |= VQAAUDF_ISPLAYING;\n\tPlayingFlag = 1;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StopAudio - Stop audio playback.\n*\n* SYNOPSIS\n*     VQA_StopAudio(VQA)\n*\n*     void VQA_StopAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Halts the currently playing audio stream.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_StopAudio(VQAHandleP *vqap)\n{\n\t/* Just return if not playing */\n\tif (vqap->VQABuf->Audio.Flags & VQAAUDF_ISPLAYING) {\n\t\tvqap->VQABuf->Audio.Flags &= ~VQAAUDF_ISPLAYING;\n\t\tsosDIGIStopSample(DigiHandle, SampleHandle);\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     AudioCallback - Sound system callback.\n*\n* SYNOPSIS\n*     AudioCallback(DriverHandle, Action, SampleID)\n*\n*     void AudioCallback(WORD, WORD, WORD);\n*\n* FUNCTION\n*     Our custom audio callback routine that services HMI.\n*\n* INPUTS\n*     DriverHandle - HMI driver handle.\n*     Action       - Action taken.\n*     SampleID     - ID of sample.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid far cdecl AudioCallback(WORD wDriverHandle, WORD wAction,\n\t\tWORD wSampleID)\n{\n\tVQAAudio  *audio;\n\tVQAConfig *config;\n\n\t/* Dereference commonly used data members for quicker access. */\n\taudio = &VQAP->VQABuf->Audio;\n\tconfig = &VQAP->Config;\n\n\t/* Suppress compiler warnings */\n\twDriverHandle = wDriverHandle;\n\twSampleID = wSampleID;\n\n  /* See if we're called because the buffer is empty */\n\tif (wAction == _SAMPLE_PROCESSED) {\n\n\t\t/* Compute the 'NextBlock' index */\n\t\tNextBlock = CurBlock + 1;\n\n\t\tif (NextBlock >= audio->NumAudBlocks) {\n\t\t\tNextBlock = 0;\n\t\t}\n\n\t\t/* See if the next block has data in it; if so, update the audio\n\t\t * buffer play position & the 'CurBlock' value.\n\t\t * If not, don't change anything and replay this block.\n\t\t */\n\t\tif (audio->IsLoaded[NextBlock] == 1) {\n\n\t\t\t/* Update this block's status to loadable (0) */\n\t\t\taudio->IsLoaded[CurBlock] = 0;\n\n\t\t\t/* Update position within audio buffer */\n\t\t\taudio->PlayPosition += config->HMIBufSize;\n\t\t\tCurBlock++;\n\n\t\t\tif (audio->PlayPosition >= config->AudioBufSize) {\n\t\t\t\taudio->PlayPosition = 0;\n\t\t\t\tCurBlock = 0;\n\t\t\t}\n\t\t} else {\n\t\t\taudio->NumSkipped++;\n\t\t}\n\n\t\t/* Start the new buffer playing */\n\t  sSOSSampleData.lpSamplePtr = (unsigned char *)(audio->Buffer)+audio->PlayPosition;\n   \tsosDIGIContinueSample(DigiHandle, SampleHandle, &sSOSSampleData);\n\t\taudio->SamplesPlayed += config->HMIBufSize;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     CopyAudio - Copy data from Audio Temp buffer into Audio play buffer.\n*\n* SYNOPSIS\n*     Error = CopyAudio(VQA)\n*\n*     long CopyAudio(VQAHandleP *);\n*\n* FUNCTION\n*     This routine just copies the data in the TempBuf into the correct\n*     spots in the audio play buffer.  If there is no room available in the\n*     audio play buffer, the routine returns VQAERR_SLEEPING, which will put\n*     the whole Loader to \"sleep\" while it waits for a free buffer.\n*\n*     If there's no data in the TempBuf to copy, the routine just returns 0.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle structure.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nlong CopyAudio(VQAHandleP *vqap)\n{\n\tVQAAudio  *audio;\n\tVQAConfig *config;\n\tlong      startblock;\n\tlong      endblock;\n\tlong      len1,len2;\n\tlong      i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\taudio = &vqap->VQABuf->Audio;\n\tconfig = &vqap->Config;\n\n\t/* If audio is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, or if there's no data to copy, just return 0\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (vqap->vocfh != -1)\n\t\t\t|| (audio->Buffer == NULL) || (audio->TempBufLen == 0)) {\n\t#else  /* VQAVOC_ON */\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (audio->Buffer == NULL)\n\t\t\t|| (audio->TempBufLen == 0)) {\n\t#endif /* VQAVOC_ON */\n\n\t\treturn (0);\n\t}\n\n\t/* Compute start & end blocks to copy into */\n\tstartblock = (audio->AudBufPos / config->HMIBufSize);\n\tendblock = (audio->AudBufPos + audio->TempBufLen) / config->HMIBufSize;\n\n\tif (endblock >= audio->NumAudBlocks) {\n\t\tendblock -= audio->NumAudBlocks;\n\t}\n\n\t/* If 'endblock' hasn't played yet, return VQAERR_SLEEPING */\n\tif (audio->IsLoaded[endblock] == 1) {\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\t/* Copy the data:\n\t *\n\t *  - If 'startblock' < 'endblock', copy the entire buffer\n\t *  - Otherwise, fill to the end of the buffer with part of the data, then\n\t *    copy the rest to the beginning of the buffer\n\t */\n\tif (startblock <= endblock) {\n\n\t\t/* Copy data */\n\t\tmemcpy((audio->Buffer + audio->AudBufPos), audio->TempBuf,\n\t\t\t\taudio->TempBufLen);\n\n\t\t/* Adjust current load position */\n\t\taudio->AudBufPos += audio->TempBufLen;\n\n\t\t/* Mark buffer as empty */\n\t\taudio->TempBufLen = 0;\n\n\t\t/* Set all blocks to loaded */\n\t\tfor (i = startblock; i < endblock; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t} else {\n\n\t\t/* Compute length of each piece */\n\t\tlen1 = config->AudioBufSize - audio->AudBufPos;\n\t\tlen2 = audio->TempBufLen - len1;\n \n\t\t/* Copy 1st piece into end of Audio Buffer */\n\t\tmemcpy((audio->Buffer + audio->AudBufPos), audio->TempBuf, len1);\n\n\t\t/* Copy 2nd piece into start of Audio Buffer */\n\t\tmemcpy(audio->Buffer, audio->TempBuf + len1, len2);\n\t\t\n\t\t/* Adjust load position */\n\t\taudio->AudBufPos = len2;\n\n\t\t/* Mark buffer as empty */\n\t\taudio->TempBufLen = 0;\n\n\t\t/* Set blocks to loaded */\n\t\tfor (i = startblock; i < audio->NumAudBlocks; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\tfor (i = 0; i < endblock; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t}\n}\n\n\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n#endif /* VQAAUDIO_ON */\n\n"
  },
  {
    "path": "VQ/VQA32/AUDIO.BAK2",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     audio.c\n*\n* DESCRIPTION\n*     Audio playback and timing.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     June 22, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_StartTimerInt - Initialize system timer interrupt.\n*     VQA_StopTimerInt  - Remove system timer interrupt.\n*     VQA_SetTimer      - Resets current time to given tick value.\n*     VQA_GetTime       - Return current time.\n*     VQA_TimerMethod   - Get timer method being used.\n*     VQA_OpenAudio     - Open sound system.\n*     VQA_CloseAudio    - Close sound system\n*     VQA_StartAudio    - Starts audio playback\n*     VQA_StopAudio     - Stop audio playback.\n*     CopyAudio         - Copy data from Audio Temp buf into Audio play buf.\n*\n* PRIVATE\n*     TimerCallback - Timer callback routine; called by HMI\n*     AutoDetect    - Auto detect the sound card.\n*     AudioCallback - Sound system callback.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <malloc.h>\n#include <mem.h>\n#include <sys\\timeb.h>\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n\n#ifdef __WATCOMC__\n#pragma pack(4);\n#endif\n\n#if(VQAAUDIO_ON)\n#include \"sos.h\"\n#endif\n\n/*---------------------------------------------------------------------------\n * AUDIO DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n#define HMI_SAMPLE       0x1000\n#define HMI_DEFAULT_RATE 22050\n\n#define HMI_UNINIT  0  /* Unitialize state. */\n#define HMI_VQAINIT 1  /* VQA initialized */\n#define HMI_APPINIT 2  /* Application initialized */\n\n#if(VQAAUDIO_ON)\n/*---------------------------------------------------------------------------\n * PROTOTYPES\n *-------------------------------------------------------------------------*/\n\nlong AutoDetect(long bitsize, long channels);\nvoid far TimerCallback(void);\nvoid far cdecl AudioCallback(WORD wDriverHandle, WORD wAction,\n\t\tWORD wSampleID);\n\n/*---------------------------------------------------------------------------\n * GLOBAL DATA\n *-------------------------------------------------------------------------*/\n\n/* HMI Start Sample structure:\n *\n * lpSamplePtr            - Pointer to audio buffer.\n * dwSampleSize           - Size of buffer.\n * wLoopCount             - Number of time to loop (-1 = infinate)\n * wChannel               - Channel to play sample on.\n * wVolume                - Volume level to play at.\n * wSampleID              - ID for sample\n * lpCallback             - Callback function pointer.\n * wSamplePort            - Port to use for non-DMA\n * wSampleFlags           - Flags\n * dwSampleByteLength     - Total length including loops\n * dwSampleLoopPoint      -\n * dwSampleLoopLength     -\n * dwSamplePitchAdd       - Pitch shifting component.\n * wSamplePitchFraction   - Pitch shifting component.\n * wSamplePanLocation     - For panning\n * wSamplePanSpeed        - For panning\n * wSamplePanDirection    - For panning\n * wSamplePanStart        - For panning.\n * wSamplePanEnd          - For panning.\n * wSampleDelayBytes      - Delay part.\n * wSampleDelayRepeat     - Delay part.\n * dwSampleADPCMPredicted - For compression\n * wSampleADPCMIndex      - For compression\n * wSampleRootNoteMIDI    - Root note for pitch shift\n * dwFiller[3]            - Filler for future upgrades.\n */\n_SOS_START_SAMPLE sSOSSampleData = {\n\t_NULL,\n\t0L,\n\t0,\n\t_CENTER_CHANNEL,\n\t0x7FFF,\n\tHMI_SAMPLE,\n\tAudioCallback,\n\t0,\n\t0,\n\t0L,\n\t0L,0L,\n\t0L,0,\n\t0,0,0,0,0,\n\t0,0,\n\t0L,0,\n\t0,\n\t0L,0L,0L\n};\n\n/* HMI Driver structure: Driver initialization structure.\n *\n * wBufferSize     - Size of play buffer.\n * lpBuffer        - Pointer to buffer.\n * wAllocateBuffer - Allocate buffer flag.\n * wSampleRate     - Playback rate.\n * wParam          -\n * dwParam         -\n * lpFillHandler   -\n * lpDriverMemory  -\n * lpTimerMemory   -\n * wTimerID        -\n */\n_SOS_INIT_DRIVER sSOSInitDriver = {\n\t0,\n\t_NULL,\n\t_TRUE,\n\tHMI_DEFAULT_RATE,\n\t19,\n\t0L,\n\t_NULL,\n\t_NULL,\n\t_NULL,\n\t_SOS_NORMAL_TIMER\n};\n\nstatic _SOS_CAPABILITIES DigiCaps;\nstatic _SOS_HARDWARE DigiHardware;\nstatic WORD DigiHandle = -1;\nstatic WORD DigiTimer = 0;\nstatic WORD SampleHandle;\nstatic long DigiInitFlag = HMI_UNINIT;\nstatic long PlayingFlag = 0;\n\nstatic VQAHandleP *VQAP;\nstatic unsigned long CurBlock = 0;\nstatic unsigned long NextBlock;\n\nstatic WORD VQATimer = 0;\nstatic long TimerMethod;\nstatic long TimerInitFlag = HMI_UNINIT;\nstatic long HMITimerFlag = HMI_UNINIT;\nstatic long VQATickCount = 0;\n\n#endif /* VQAAUDIO_ON */\n\nstatic long TickOffset = 0;\nchar *HMIDevName = \"<none>\";\n\n\n#if(VQAAUDIO_ON)\n/****************************************************************************\n*\n* NAME\n*     VQA_StartTimerInt - Initialize system timer interrupt.\n*\n* SYNOPSIS\n*     Error = VQA_StartTimerInt(Init)\n*\n*     long VQA_StartTimerInt(long);\n*\n* FUNCTION\n*     Initialize the HMI timer system if it hasn't been already then add\n*     our own timer event.\n*\n* INPUTS\n*     Init - Initialize HMI timer system flag. (TRUE = Initialize)\n*\n* RESULT\n*     Error - 0 if successful, -1 if error.\n*\n****************************************************************************/\n\nlong VQA_StartTimerInt(long init)\n{\n\t/* Does the caller want me to initialize the timer system? */\n\tif (init == 0) {\n\n\t\t/* If the timer system is uninitialized then it is the players\n\t\t * responsibility to do it.\n\t\t */\n\t\tif (TimerInitFlag == HMI_UNINIT) {\n\t\t\tsosTIMERInitSystem(_TIMER_DOS_RATE, _SOS_DEBUG_NORMAL);\n\t\t\tTimerInitFlag = HMI_VQAINIT;\n\t\t}\n\t} else {\n\t\tTimerInitFlag = HMI_APPINIT;\n\t}\n\n\t/* Register the VQA_TickCount timer event. */\n\tif (HMITimerFlag == HMI_UNINIT) {\n\t\tif (sosTIMERRegisterEvent(VQA_TIMETICKS,TimerCallback,&VQATimer) == 0) {\n\t\t\tHMITimerFlag = HMI_VQAINIT;\n\t\t} else {\n\t\t\treturn (-1);\n\t\t}\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StopTimerInt - Remove system timer interrupt.\n*\n* SYNOPSIS\n*     VQA_StopTimerInt()\n*\n*     void VQA_StopTimerInt(void);\n*\n* FUNCTION\n*     Remove our timer event from the HMI timer system. Uninitialize the\n*     HMI timer system if we initialized it.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_StopTimerInt(void)\n{\n\t/* Remove the timer event */\n\tif (HMITimerFlag == HMI_VQAINIT) {\n\t\tsosTIMERRemoveEvent(VQATimer);\n\t}\n\n\tHMITimerFlag = HMI_UNINIT;\n\n\tif (TimerInitFlag == HMI_VQAINIT) {\n\t\tsosTIMERUnInitSystem(0);\n\t}\n\n\tTimerInitFlag = HMI_UNINIT;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     TimerCallback - VQA timer event. (Called by HMI)\n*\n* SYNOPSIS\n*     TimerCallback()\n*\n*     void TimerCallback(void);\n*\n* FUNCTION\n*     Our custom timer event. This is the timer event that we register with\n*     HMI for system timing.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid far TimerCallback(void)\n{\n\tVQATickCount++;\n}\n#endif /* VQAAUDIO_ON */\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_SetTimer - Resets current time to given tick value.\n*\n* SYNOPSIS\n*     VQA_SetTimer(Time, Method)\n*\n*     void VQA_SetTimer(long, long);\n*\n* FUNCTION\n*     Sets 'TickOffset' to a value that will make the current time look like\n*     the time passed in. This function allows the player to be \"paused\",\n*     by recording the time of the pause, and then setting the timer to\n*     that time. The timer method used by the player is also set. The method\n*     selected is not neccesarily the method that will be used because some\n*     timer methods work with only certain playback conditions. (EX: The\n*     audio DMA timer method cannot be used if there is not any audio\n*     playing.)\n*\n* INPUTS\n*     Time   - Value to set current time to.\n*     Method - Timer method to use.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_SetTimer(long time, long method)\n{\n\tunsigned long curtime;\n\n\t#if(VQAAUDIO_ON)\n\t/* If the client does not have a preferencee then pick a method\n\t * based on the state of the player.\n\t */\n\tif (method == VQA_TMETHOD_DEFAULT) {\n\n\t\t/* If we are playing audio, use the audio DMA position. */\n\t\tif (PlayingFlag) {\n\t\t\tmethod = VQA_TMETHOD_AUDIO;\n\t\t}\n\n\t\t/* Otherwise use the HMI timer if it is initialized. */\n\t\telse if (HMITimerFlag) {\n\t\t\tmethod = VQA_TMETHOD_INT;\n\t\t}\n\n\t\t/* If all else fails resort the the \"jerky\" DOS time. */\n\t\telse {\n\t\t\tmethod = VQA_TMETHOD_DOS;\n\t\t}\n\t} else {\n\n\t\t/* We cannot use the DMA position if there isn't any audio playing. */\n\t\tif (!PlayingFlag && (method == VQA_TMETHOD_AUDIO)) {\n\t\t\tmethod = VQA_TMETHOD_INT;\n\t\t}\n\n\t\t/* We cannot use the timer if it has not been initialized. */\n\t\tif (!HMITimerFlag && (method == VQA_TMETHOD_INT)) {\n\t\t\tmethod = VQA_TMETHOD_DOS;\n\t\t}\n\t}\n\n\tTimerMethod = method;\n\t#endif\n\n\tTickOffset = 0L;\n\tcurtime = VQA_GetTime();\n\tTickOffset = (time - curtime);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_GetTime - Return current time.\n*\n* SYNOPSIS\n*     Time = VQA_GetTime()\n*\n*     unsigned long VQA_GetTime(void);\n*\n* FUNCTION\n*     This routine returns timer ticks computed one of 3 ways:\n*\n*     1) If audio is playing, the timer is based on the DMA buffer position:\n*        Compute the number of audio samples that have actually been played.\n*        The following internal HMI variables are used:\n*\n*          _lpSOSDMAFillCount[drv_handle]: current DMA buffer position\n*          _lpSOSSampleList[drv_handle][samp_handle]:\n*          sampleTotalBytes: total bytes sent by HMI to the DMA buffer\n*          sampleLastFill: HMI's last fill position in DMA buffer\n*\n*        So, the number of samples actually played is:\n*\n*          sampleTotalBytes - <DMA_diff>\n*          where <DMA_diff> is how far ahead sampleLastFill is in front of\n*          _lpSOSDMAFillCount: (sampleLastFill - _lpSOSDMAFillCount)\n*\n*        These values are indices into a circular DMA buffer, so:\n*\n*          if (sampleLastFill >= _lpSOSDMAFillCount)\n*            <DMA_diff> = sampleLastFill - _lpSOSDMAFillCount\n*          else\n*            <DMA_diff> = (DMA_BUF_SIZE - lpSOSDMAFillCount) + sampleLastFill\n*\n*        Note that, if using the stereo driver with mono data, you must\n*        divide LastFill & FillCount by 2, but not TotalBytes. If using the\n*        stereo driver with stereo data, you must divide all 3 variables\n*        by 2.\n*\n*     2) If no audio is playing, but the timer interrupt is running,\n*        VQATickCount is used as the timer\n*\n*     3) If no audio is playing & no timer interrupt is going, the DOS 18.2\n*        system timer is used.\n*\n*     Regardless of the method, TickOffset is used as an offset from the\n*     computed time.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Time - Time in VQA_TIMETICKS\n*\n****************************************************************************/\n\nunsigned long VQA_GetTime(void)\n{\n\t#if(VQAAUDIO_ON)\n\tVQAAudio      *audio;\n\tunsigned long bytesleft;\n\tunsigned long samples;\n\t#endif\n\n\tlong ticks;\n\n\t#if(VQAAUDIO_ON)\n\tswitch (TimerMethod) {\n\n\t\t/* If Audio is playing then timing is based on the audio DMA buffer\n\t\t * position.\n\t\t */\n\t\tcase VQA_TMETHOD_AUDIO:\n\n\t\t\t/* Dereference commonly used data members for quicker access. */\n\t\t\taudio = &VQAP->VQABuf->Audio;\n\n\t\t\t/* Compute our current position in the audio track by getting the\n\t\t\t * bytes processed by HMI. Then adjust the bytes processed by the\n\t\t\t * position of the DMA fill handler, this should tell us exactly\n\t\t\t * where we are in the audio track.\n\t\t\t */\n\t\t\tsamples = _lpSOSSampleList[DigiHandle][SampleHandle]->sampleTotalBytes;\n\t\t\tbytesleft = _lpSOSSampleList[DigiHandle][SampleHandle]->sampleBytesLeft;\n\n\t\t\t/* Adjust the bytes processed from the bytes left to DMA in the\n\t\t\t * buffer.\n\t\t\t */\n\t\t\tif (samples >= bytesleft) {\n\t\t\t\tsamples -= bytesleft;\n\t\t\t}\n\n\t\t\t/* Calculate the number of samples by taking the total number of\n\t\t\t * bytes processed and divide it by the number of channels and \n\t\t\t * bits per sample.\n\t\t\t */\n\t\t\tsamples -= (audio->NumSkipped * VQAP->Config.HMIBufSize);\n\t\t\tsamples /= (audio->Channels * (audio->BitsPerSample >> 3));\n\n\t\t\t/* The elapsed ticks is calculated by the number of samples\n\t\t\t * processed times the tick resolution per second divided by the\n\t\t\t * sample rate.\n\t\t\t */\n\t\t\tticks = (long)((samples * VQA_TIMETICKS) / audio->SampleRate);\n\t\t\tticks += TickOffset;\n\t\t\tbreak;\n\n\t\t/* No audio playing, but timer interrupt is going; use VQATickCount */\n\t\tcase VQA_TMETHOD_INT:\n\t\t\tticks = (VQATickCount + TickOffset);\n\t\t\tbreak;\n\n\t\t/* No interrupts are going at all; use DOS's time */\n\t\tdefault:\n\t\tcase VQA_TMETHOD_DOS:\n\t\t\t{\n\t\t\tstruct timeb mytime;\n\n\t\t\tftime(&mytime);\n \t\t\tticks = (unsigned long)mytime.time*1000L+(unsigned long)mytime.millitm;\n\t\t\tticks = ((ticks * VQA_TIMETICKS) / 1000L);\n\t\t\tticks += TickOffset;\n\t\t\t}\n\t\t\tbreak;\n\t}\n\t#else\n\t{\n\tstruct timeb mytime;\n\n\tftime(&mytime);\n\tticks = (unsigned long)mytime.time*1000L+(unsigned long)mytime.millitm;\n\tticks = ((ticks * VQA_TIMETICKS) / 1000L);\n\tticks += TickOffset;\n\t}\n\t#endif\n\n\treturn (ticks);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_TimerMethod - Get timer method being used.\n*\n* SYNOPSIS\n*     Method = VQA_TimerMethod()\n*\n*     long VQA_TimerMethod(void);\n*\n* FUNCTION\n*     Returns the ID of the current timer method being used.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Method - Method used for the timer.\n*\n****************************************************************************/\n\nlong VQA_TimerMethod(void)\n{\n\t#if(VQAAUDIO_ON)\n\treturn (TimerMethod);\n\t#else\n\treturn (VQA_TMETHOD_DOS);\n\t#endif\n}\n\n\n#if(VQAAUDIO_ON)\n/****************************************************************************\n*\n* NAME\n*     VQA_OpenAudio - Open sound system.\n*\n* SYNOPSIS\n*     Error = VQA_OpenAudio(VQAHandleP)\n*\n*     long VQA_OpenAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Initialize the sound system by setting the DigiHandle to and HMI\n*     driver handle. The timer must first be initialized before calling\n*     this function.\n*\n* INPUTS\n*     VQAHandleP - Pointer to private VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, -1 if error.\n*\n****************************************************************************/\n\nlong VQA_OpenAudio(VQAHandleP *vqap)\n{\n\tVQAData       *vqabuf;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tVQAHeader     *header;\n\tunsigned char *driver_path;\n\tWORD          port;\n\tlong          rc;\n\n\t/* Return if already initialized */\n\tif (DigiInitFlag != HMI_UNINIT) {\n\t\treturn (0);\n\t}\n\n\t/* Dereference data memebers for quicker access. */\n\tconfig = &vqap->Config;\n\theader = &vqap->Header;\n\tvqabuf = vqap->VQABuf;\n\taudio = &vqabuf->Audio;\n\n\t/* Fail if no audio buffer or DigiCard is 0 (no sound) */\n\tif ((audio->Buffer == NULL) || (config->DigiCard == 0)) {\n\t\treturn (-1);\n\t}\n\n\t/* Reset the buffer position to the beginning. */\n\tCurBlock = 0;\n\n\t/*-------------------------------------------------------------------------\n\t * Compute the playback rate:\n\t *\n\t * - If Config->AudioRate is -1, use HMI_DATA_RATE scaled to the specified\n\t *   frame rate (so the audio plays faster if we're playing faster)\n\t * - otherwise, use the specified rate\n\t *-----------------------------------------------------------------------*/\n\tif (config->AudioRate != -1) {\n\t\tsSOSInitDriver.wSampleRate = config->AudioRate;\n\t}\n\telse if (config->FrameRate != header->FPS) {\n\t\tsSOSInitDriver.wSampleRate = ((audio->SampleRate * config->FrameRate)\n\t\t\t\t/ (unsigned long)header->FPS);\n\n\t\tconfig->AudioRate = sSOSInitDriver.wSampleRate;\n\t} else {\n\t\tsSOSInitDriver.wSampleRate = audio->SampleRate;\n\t\tconfig->AudioRate = audio->SampleRate;\n\t}\n\n\t/* If the application has already initialized HMI then set the\n\t * necessary variables. Otherwise we must setup HMI ourself.\n\t */\n\tif (config->OptionFlags & VQAOPTF_HMIINIT) {\n\n\t\t/* The application MUST provide the card type! */\n\t\tif (config->DigiCard == -1) {\n\t\t\treturn (-1);\n\t\t}\n\n\t\t/* Init the detection system */\n\t\tdriver_path = (unsigned char *)\".\\\\\";\n\n\t\tif ((rc = sosDIGIDetectInit(driver_path)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Get the capabilities of the card being used. */\n\t\trc = sosDIGIDetectGetCaps(config->DigiCard, &DigiCaps);\n\t\tsosDIGIDetectUnInit();\n\n\t\tif (rc != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\tDigiHandle = config->DigiHandle;\n\t\tHMIDevName = \"App-Specific\";\n\t\tTimerInitFlag = HMI_APPINIT;\n\t\tDigiInitFlag = HMI_APPINIT;\n\t} else {\n\n\t\t/* Init the detection system */\n\t\tdriver_path = (unsigned char *)\".\\\\\";\n\n\t\tif ((rc = sosDIGIDetectInit(driver_path)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/*-----------------------------------------------------------------------\n\t\t * Initialize DigiHardware with port, IRQ, and DMA, and make sure\n\t\t * Config.DigiCard contains the HMI ID we want to use:\n\t\t *\n\t\t * - If Config.DigiCard is -1, auto-detect the hardware; then, do a \n\t\t *   FindHardware so the GetSettings will work\n\t\t * - If Config.DigiCard is filled in, but port, IRQ or DMA is -1, use\n\t\t *   FindHardware & GetSettings to get the settings\n\t\t * - If all are filled in, just use them as they are\n\t\t *---------------------------------------------------------------------*/\n\n\t\t/* Auto-Detect */\n\t\tif (config->DigiCard == -1) {\n\n\t\t\t/* Version 1 VQA's have only 8 bit mono audio streams. */\n\t\t\tif (header->Version == VQAHD_VER1) {\n\t\t\t\tconfig->DigiCard = AutoDetect(8, 1);\n\t\t\t} else {\n\t\t\t\tconfig->DigiCard = AutoDetect(audio->BitsPerSample, audio->Channels);\n\n\t\t\t\t/* Resort to 8bit mono */\n\t\t\t\tif (config->DigiCard == -1) {\n\t\t\t\t\tconfig->DigiCard = AutoDetect(8, 1);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (config->DigiCard == -1) {\n\t\t\t\tsosDIGIDetectUnInit();\n\t\t\t\treturn (-1);\n\t\t\t}\n\t\t}\n\n\t\t/* Do a FindHardware & GetSettings */\n\t\tif (config->DigiPort == -1) {\n\t\t  if (sosDIGIDetectFindHardware(config->DigiCard, &DigiCaps, &port)) {\n\t\t\t\tsosDIGIDetectUnInit();\n\t\t\t\treturn (-1);\n\t\t\t}\n\n\t\t\tif (sosDIGIDetectGetSettings(&DigiHardware)) {\n\t\t\t\tsosDIGIDetectUnInit();\n\t\t\t\treturn (-1);\n\t\t\t}\n\n\t\t\tconfig->DigiPort = DigiHardware.wPort;\n\t\t\tconfig->DigiIRQ = DigiHardware.wIRQ;\n\t\t\tconfig->DigiDMA = DigiHardware.wDMA;\n\t\t\tHMIDevName = (char *)DigiCaps.szDeviceName;\n\t\t} else {\n\t\t\tDigiHardware.wPort = config->DigiPort;\n\t\t\tDigiHardware.wIRQ = config->DigiIRQ;\n\t\t\tDigiHardware.wDMA = config->DigiDMA;\n\t\t\tHMIDevName = \"App-Specific\";\n\t\t}\n\n\t\tsosDIGIDetectUnInit();\n\n\t\t/* Initialize the DIGI system & driver */\n\t\tsosDIGIInitSystem(driver_path, _SOS_DEBUG_NORMAL);\n\t\tsSOSInitDriver.wBufferSize = config->HMIBufSize;\n\t\tsSOSInitDriver.lpBuffer = NULL;\n\t\tsSOSInitDriver.lpFillHandler = NULL;\n\t\tsSOSInitDriver.lpDriverMemory = NULL;\n\t\tsSOSInitDriver.lpTimerMemory = NULL;\n\t\tDigiHandle = -1;\n\n\t\tif ((rc = sosDIGIInitDriver(config->DigiCard, &DigiHardware, \n\t\t\t\t&sSOSInitDriver, &DigiHandle)) != 0) {\n\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/*-----------------------------------------------------------------------\n\t\t * Register the timer event\n\t\t *---------------------------------------------------------------------*/\n\n\t\t/* If the timer hasn't been init'd, do it now */\n\t\tif (TimerInitFlag == HMI_UNINIT) {\n\t\t\tsosTIMERInitSystem(_TIMER_DOS_RATE ,_SOS_DEBUG_NORMAL);\n\t\t\tTimerInitFlag = HMI_VQAINIT;\n\t\t}\n\n\t\t/* Register the event */\n\t\trc = sosTIMERRegisterEvent(VQA_TIMETICKS, sSOSInitDriver.lpFillHandler,\n\t\t\t\t&DigiTimer);\n\n\t\tif (rc) {\n\t\t\tsosDIGIUnInitDriver(DigiHandle, _TRUE, _TRUE);\n\t\t\tsosDIGIUnInitSystem();\n\t\t\treturn (rc);\n\t\t}\n\n\t\tconfig->DigiHandle = DigiHandle;\n\t\tDigiInitFlag = HMI_VQAINIT;\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     AutoDetect - Auto detect the sound card.\n*\n* SYNOPSIS\n*     CardID = AutoDetect(BitSize, Channels)\n*\n*     long AutoDetect(long, long);\n*\n* FUNCTION\n*     Autodetects the type of sound card present in the system.\n*\n* INPUTS\n*     BitSize  - Bits per sample size.\n*     Channels - Number of desired channels.\n*\n* RESULT\n*     CardID - HMI ID of the sound card found, -1 if none.\n*\n****************************************************************************/\n\nlong AutoDetect(long bitsize, long channels)\n{\n\tlong device_id = -1;\n\tWORD port;\n\tlong i;\n\tlong rc;\n\n\t/* Search for an 8-bit mono device */\n\tif (sosDIGIDetectFindFirst(&DigiCaps, &port)) {\n\t\treturn (-1);\n\t}\n\n\tchannels--;\n\n\ti = 0;\n\twhile (i < 6) {\n\t\ti++;\n\n\t\tif ((DigiCaps.wBitsPerSample == bitsize)\n\t\t\t\t&& (DigiCaps.wChannels == channels)) {\n\n\t\t\tbreak;\n\t\t}\n\n\t\tif (sosDIGIDetectFindNext(&DigiCaps, &port)) {\n\t\t\treturn (-1);\n\t\t}\n\t}\n\n\t/* Exit if failed to find the required device */\n\tif ((DigiCaps.wBitsPerSample != bitsize)\n\t\t\t|| (DigiCaps.wChannels != channels)) {\n\n\t\treturn (-1);\n\t}\n\n\t/* Stash the ID */\n\tdevice_id = DigiCaps.wDeviceID;\n\n\t/* Now that we have handled the initial pass, verify that if we found an\n\t * _ADLIB_GOLD_8_MONO that it is not a Logitech Sound Wave man in disguise.\n\t */\n\tif ((WORD)DigiCaps.wDeviceID == _ADLIB_GOLD_8_MONO) {\n\t\trc = sosDIGIDetectFindNext(&DigiCaps, &port);\n\n\t\twhile ((i < 6) && (rc == 0)) {\n\t\t\ti++;\n\n\t\t\tif ((DigiCaps.wBitsPerSample == 8) && (DigiCaps.wChannels == 0)) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif ((rc = sosDIGIDetectFindNext(&DigiCaps, &port)) != 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/* If we don't have an error use the secondary device ID, after all, \n\t\t * anything's better than an Adlib Gold.  If we do have an error or there\n\t\t * is nothing we can use then the device ID is already set to the adlib \n\t\t * gold so just let it rip.\n\t\t */\n\t\tif ((rc == 0) && ((WORD)DigiCaps.wDeviceID == _SBPRO_8_MONO)) {\n\t\t\treturn (DigiCaps.wDeviceID);\n\t\t}\n\t}\n\n\treturn (device_id);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_CloseAudio - Close sound system\n*\n* SYNOPSIS\n*     VQA_CloseAudio()\n*\n*     void VQA_CloseAudio(void);\n*\n* FUNCTION\n*     Removes VQA's involvement in the audio system.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_CloseAudio(void)\n{\n\t/* Remove the Digi event */\n\tif (DigiInitFlag == HMI_VQAINIT) {\n\t\tsosTIMERRemoveEvent(DigiTimer);\n\t}\n\n\t/* Un-init timer if necessary */\n\tif (TimerInitFlag == HMI_VQAINIT) {\n\t\tsosTIMERUnInitSystem(0);\n\t}\n\n\tTimerInitFlag = HMI_UNINIT;\n\n\t/* Remove the driver */\n\tif (DigiInitFlag == HMI_VQAINIT) {\n\t\tsosDIGIUnInitDriver(DigiHandle, _TRUE, _TRUE);\n\t\tsosDIGIUnInitSystem();\n\t}\n\n\tDigiInitFlag = HMI_UNINIT;\n\n\tif (PlayingFlag) {\n\t\tPlayingFlag = 0;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StartAudio - Starts audio playback\n*\n* SYNOPSIS\n*     Error = VQA_StartAudio(VQA)\n*\n*     long VQA_StartAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Start the audio playback for the movie.\n*\n* INPUTS\n*     VQA - Pointer to private VQA handle.\n*\n* RESULT\n*     Error - 0 if successful, or -1 error code.\n*\n****************************************************************************/\n\nlong VQA_StartAudio(VQAHandleP *vqap)\n{\n\tVQAConfig *config;\n\tVQAAudio  *audio;\n\n\t/* Save buffers for the callback routine */\n\tVQAP = vqap;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tconfig = &vqap->Config;\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Return if already playing */\n\tif (audio->Flags & VQAAUDF_ISPLAYING) {\n\t\treturn (-1);\n\t}\n\n \t/* Set my driver handle */\n\tif (config->DigiHandle != -1) {\n\t\tDigiHandle = config->DigiHandle;\n\t}\n\n\tif (DigiHandle == (WORD)-1) {\n\t\treturn (-1);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * Initialize the sample structure.\n\t *-----------------------------------------------------------------------*/\n\tmemset(&sSOSSampleData, 0, sizeof(_SOS_START_SAMPLE));\n  sSOSSampleData.lpSamplePtr = (unsigned char *)vqap->VQABuf->Audio.Buffer;\n \tsSOSSampleData.dwSampleSize = config->HMIBufSize;\n\tsSOSSampleData.wVolume = (config->Volume << 7);\n\tsSOSSampleData.wSampleID = HMI_SAMPLE;\n\tsSOSSampleData.lpCallback = AudioCallback;\n\n\t/* Set the channel flags for the type of data we have. */\n\tif (audio->Channels == 2) {\n\t\tsSOSSampleData.wChannel = _INTERLEAVED;\n\t} else {\n\t\tsSOSSampleData.wChannel = _CENTER_CHANNEL;\n\t}\n\n\t/* If the card is unable to handle stereo data the we must notify the\n\t * sound system to convert the stereo data to mono data during playback.\n\t */\n\tif ((audio->Channels - 1) > DigiCaps.wChannels) {\n\t\tsSOSSampleData.wSampleFlags |= _STEREOTOMONO;\n\t}\n\n\t/* If the card is unable to handle the sample size of the audio data\n\t * then we must notify the sound system to convert the audio data to\n\t * the proper format.\n\t */\n\tif (audio->BitsPerSample != DigiCaps.wBitsPerSample) {\n\t\tif (audio->BitsPerSample > DigiCaps.wBitsPerSample) {\n\t\t\tsSOSSampleData.wSampleFlags |= _TRANSLATE16TO8;\n\t\t} else {\n\t\t\tsSOSSampleData.wSampleFlags |= _TRANSLATE8TO16;\n\t\t}\n\t}\n\n\t/* Start playback */\n \tSampleHandle = sosDIGIStartSample(DigiHandle, &sSOSSampleData);\n\taudio->Flags |= VQAAUDF_ISPLAYING;\n\tPlayingFlag = 1;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StopAudio - Stop audio playback.\n*\n* SYNOPSIS\n*     VQA_StopAudio(VQA)\n*\n*     void VQA_StopAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Halts the currently playing audio stream.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_StopAudio(VQAHandleP *vqap)\n{\n\t/* Just return if not playing */\n\tif (vqap->VQABuf->Audio.Flags & VQAAUDF_ISPLAYING) {\n\t\tvqap->VQABuf->Audio.Flags &= ~VQAAUDF_ISPLAYING;\n\t\tsosDIGIStopSample(DigiHandle, SampleHandle);\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     AudioCallback - Sound system callback.\n*\n* SYNOPSIS\n*     AudioCallback(DriverHandle, Action, SampleID)\n*\n*     void AudioCallback(WORD, WORD, WORD);\n*\n* FUNCTION\n*     Our custom audio callback routine that services HMI.\n*\n* INPUTS\n*     DriverHandle - HMI driver handle.\n*     Action       - Action taken.\n*     SampleID     - ID of sample.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid far cdecl AudioCallback(WORD wDriverHandle,WORD wAction,WORD wSampleID)\n{\n\tVQAAudio  *audio;\n\tVQAConfig *config;\n\n\t/* Dereference commonly used data members for quicker access. */\n\taudio = &VQAP->VQABuf->Audio;\n\tconfig = &VQAP->Config;\n\n\t/* Suppress compiler warnings */\n\twDriverHandle = wDriverHandle;\n\twSampleID = wSampleID;\n\n  /* See if we're called because the buffer is empty */\n\tif (wAction == _SAMPLE_PROCESSED) {\n\n\t\t/* Compute the 'NextBlock' index */\n\t\tNextBlock = CurBlock + 1;\n\n\t\tif (NextBlock >= audio->NumAudBlocks) {\n\t\t\tNextBlock = 0;\n\t\t}\n\n\t\t/* See if the next block has data in it; if so, update the audio\n\t\t * buffer play position & the 'CurBlock' value.\n\t\t * If not, don't change anything and replay this block.\n\t\t */\n\t\tif (audio->IsLoaded[NextBlock] == 1) {\n\n\t\t\t/* Update this block's status to loadable (0) */\n\t\t\taudio->IsLoaded[CurBlock] = 0;\n\n\t\t\t/* Update position within audio buffer */\n\t\t\taudio->PlayPosition += config->HMIBufSize;\n\t\t\tCurBlock++;\n\n\t\t\tif (audio->PlayPosition >= config->AudioBufSize) {\n\t\t\t\taudio->PlayPosition = 0;\n\t\t\t\tCurBlock = 0;\n\t\t\t}\n\t\t} else {\n\t\t\taudio->NumSkipped++;\n\t\t}\n\n\t\t/* Start the new buffer playing */\n\t  sSOSSampleData.lpSamplePtr = (unsigned char *)(audio->Buffer)\n\t\t\t\t+ audio->PlayPosition;\n   \tsosDIGIContinueSample(DigiHandle, SampleHandle, &sSOSSampleData);\n\t\taudio->SamplesPlayed += config->HMIBufSize;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     CopyAudio - Copy data from Audio Temp buffer into Audio play buffer.\n*\n* SYNOPSIS\n*     Error = CopyAudio(VQA)\n*\n*     long CopyAudio(VQAHandleP *);\n*\n* FUNCTION\n*     This routine just copies the data in the TempBuf into the correct\n*     spots in the audio play buffer.  If there is no room available in the\n*     audio play buffer, the routine returns VQAERR_SLEEPING, which will put\n*     the whole Loader to \"sleep\" while it waits for a free buffer.\n*\n*     If there's no data in the TempBuf to copy, the routine just returns 0.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle structure.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nlong CopyAudio(VQAHandleP *vqap)\n{\n\tVQAAudio  *audio;\n\tVQAConfig *config;\n\tlong      startblock;\n\tlong      endblock;\n\tlong      len1,len2;\n\tlong      i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\taudio = &vqap->VQABuf->Audio;\n\tconfig = &vqap->Config;\n\n\t/* If audio is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, or if there's no data to copy, just return 0\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (vqap->vocfh != -1)\n\t\t\t|| (audio->Buffer == NULL) || (audio->TempBufLen == 0)) {\n\t#else  /* VQAVOC_ON */\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (audio->Buffer == NULL)\n\t\t\t|| (audio->TempBufLen == 0)) {\n\t#endif /* VQAVOC_ON */\n\n\t\treturn (0);\n\t}\n\n\t/* Compute start & end blocks to copy into */\n\tstartblock = (audio->AudBufPos / config->HMIBufSize);\n\tendblock = (audio->AudBufPos + audio->TempBufLen) / config->HMIBufSize;\n\n\tif (endblock >= audio->NumAudBlocks) {\n\t\tendblock -= audio->NumAudBlocks;\n\t}\n\n\t/* If 'endblock' hasn't played yet, return VQAERR_SLEEPING */\n\tif (audio->IsLoaded[endblock] == 1) {\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\t/* Copy the data:\n\t *\n\t *  - If 'startblock' < 'endblock', copy the entire buffer\n\t *  - Otherwise, fill to the end of the buffer with part of the data, then\n\t *    copy the rest to the beginning of the buffer\n\t */\n\tif (startblock <= endblock) {\n\n\t\t/* Copy data */\n\t\tmemcpy((audio->Buffer + audio->AudBufPos), audio->TempBuf,\n\t\t\t\taudio->TempBufLen);\n\n\t\t/* Adjust current load position */\n\t\taudio->AudBufPos += audio->TempBufLen;\n\n\t\t/* Mark buffer as empty */\n\t\taudio->TempBufLen = 0;\n\n\t\t/* Set all blocks to loaded */\n\t\tfor (i = startblock; i < endblock; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t} else {\n\n\t\t/* Compute length of each piece */\n\t\tlen1 = config->AudioBufSize - audio->AudBufPos;\n\t\tlen2 = audio->TempBufLen - len1;\n \n\t\t/* Copy 1st piece into end of Audio Buffer */\n\t\tmemcpy((audio->Buffer + audio->AudBufPos), audio->TempBuf, len1);\n\n\t\t/* Copy 2nd piece into start of Audio Buffer */\n\t\tmemcpy(audio->Buffer, audio->TempBuf + len1, len2);\n\t\t\n\t\t/* Adjust load position */\n\t\taudio->AudBufPos = len2;\n\n\t\t/* Mark buffer as empty */\n\t\taudio->TempBufLen = 0;\n\n\t\t/* Set blocks to loaded */\n\t\tfor (i = startblock; i < audio->NumAudBlocks; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\tfor (i = 0; i < endblock; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t}\n}\n\n\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n#endif /* VQAAUDIO_ON */\n\n"
  },
  {
    "path": "VQ/VQA32/AUDIO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     audio.c\n*\n* DESCRIPTION\n*     Audio playback and timing.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     August 4, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_StartTimerInt - Initialize system timer interrupt.\n*     VQA_StopTimerInt  - Remove system timer interrupt.\n*     VQA_SetTimer      - Resets current time to given tick value.\n*     VQA_GetTime       - Return current time.\n*     VQA_TimerMethod   - Get timer method being used.\n*     VQA_OpenAudio     - Open sound system.\n*     VQA_CloseAudio    - Close sound system\n*     VQA_StartAudio    - Starts audio playback\n*     VQA_StopAudio     - Stop audio playback.\n*     CopyAudio         - Copy data from Audio Temp buf into Audio play buf.\n*\n* PRIVATE\n*     TimerCallback - VQA timer event. (Called by HMI)\n*     AutoDetect    - Auto detect the sound card.\n*     AudioCallback - Sound system callback.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <malloc.h>\n#include <mem.h>\n#include <sys\\timeb.h>\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n\n#ifdef __WATCOMC__\n#pragma pack(4);\n#endif\n\n#if(VQAAUDIO_ON)\n#include \"sos.h\"\n#endif\n\n\n/*---------------------------------------------------------------------------\n * AUDIO DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n#define HMI_SAMPLE 0x1000\n#define MAKE_LONG(a,b) (((long)(a)<<16)|(long)((b)&0x0000FFFFL))\n\n/*---------------------------------------------------------------------------\n * PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n#if(VQAAUDIO_ON)\nlong AutoDetect(_SOS_CAPABILITIES *digicaps, long bitsize, long channels);\nvoid far TimerCallback(void);\nvoid far cdecl AudioCallback(WORD wDriverHandle, WORD wAction,\n\t\tWORD wSampleID);\n\n/* Dummy functions used to mark the start/end address of the file. */\nstatic void StartAddr(void);\nstatic void EndAddr(void);\n\n\n/*---------------------------------------------------------------------------\n * GLOBAL DATA\n *-------------------------------------------------------------------------*/\n\nstatic VQAHandleP *VQAP = NULL;\nstatic long AudioFlags = 0;\nstatic long TimerSysCount = 0;\nstatic long TimerIntCount = 0;\nstatic WORD VQATimer = 0;\nstatic long TimerMethod;\nstatic long VQATickCount = 0;\n#endif /* VQAAUDIO_ON */\n\nstatic long TickOffset = 0;\nchar *HMIDevName = \"<none>\";\n\n#if(VQAAUDIO_ON)\n/* This is a dummy function that is used to mark the start of the module.\n * It is necessary for locking the memory the module occupies. This prevents\n * the virtual memory manager from swapping out this memory.\n */\nstatic void StartAddr(void)\n{\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StartTimerInt - Initialize system timer interrupt.\n*\n* SYNOPSIS\n*     Error = VQA_StartTimerInt(VQA, Init)\n*\n*     long VQA_StartTimerInt(VQAHandeP *, long);\n*\n* FUNCTION\n*     Initialize the HMI timer system and add our own timer event. If the\n*     system has already been initialized then we are given access to the\n*     the timer system.\n*\n* INPUTS\n*     VQA  - Pointer to private VQAHandle structure.\n*     Init - Initialize HMI timer system flag. (TRUE = Initialize)\n*\n* RESULT\n*     Error - 0 if successful, -1 if error.\n*\n****************************************************************************/\n\nlong VQA_StartTimerInt(VQAHandleP *vqap, long init)\n{\n\tVQAAudio *audio;\n\n\t/* Dereference for quick access. */\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Does the caller want me to initialize the timer system? */\n\tif (init == 0) {\n\n\t\t/* If the timer system is uninitialized then it is the players\n\t\t * responsibility to do it.\n\t\t */\n\t\tif ((AudioFlags & VQAAUDF_TIMERINIT)==(HMI_UNINIT<<VQAAUDB_TIMERINIT)) {\n\t\t\tsosTIMERInitSystem(_TIMER_DOS_RATE, _SOS_DEBUG_NORMAL);\n\n\t\t\t/* Flag the timer system as open. */\n\t\t\tAudioFlags |= (HMI_VQAINIT << VQAAUDB_TIMERINIT);\n\t\t}\n\n\t\t/* Flag availability of the timer system. */\n\t\taudio->Flags |= (HMI_VQAINIT << VQAAUDB_TIMERINIT);\n\t} else {\n\t\taudio->Flags |= (HMI_APPINIT << VQAAUDB_TIMERINIT);\n\t}\n\n\t/* Increment the timer system usage count. */\n\tTimerSysCount++;\n\n\t/* Register the VQA_TickCount timer event. */\n\tif ((AudioFlags & VQAAUDF_HMITIMER) == (HMI_UNINIT<<VQAAUDB_HMITIMER)) {\n\t\tif (sosTIMERRegisterEvent(VQA_TIMETICKS,TimerCallback,&VQATimer) == 0) {\n\n\t\t\t/* Flag the timer interrupt as being registered. */\n\t\t\tAudioFlags |= (HMI_VQAINIT << VQAAUDB_HMITIMER);\n\t\t} else {\n\t\t\treturn (-1);\n\t\t}\n\t}\n\n\t/* Flag availability of the timer interrupt. */\n\taudio->Flags |= (HMI_VQAINIT << VQAAUDB_HMITIMER);\n\t\n\t/* Increment the timer interrupt usage count. */\n\tTimerIntCount++;\n\n\t/* Lock the memory occupied by this module. */\n\tif ((audio->Flags & VQAAUDF_MODLOCKED) == 0) {\n\t\tDPMI_Lock((void *)&StartAddr, (long)&EndAddr - (long)&StartAddr);\n\t\taudio->Flags |= VQAAUDF_MODLOCKED;\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StopTimerInt - Remove system timer interrupt.\n*\n* SYNOPSIS\n*     VQA_StopTimerInt()\n*\n*     void VQA_StopTimerInt(void);\n*\n* FUNCTION\n*     Remove our timer event from the HMI timer system. Uninitialize the\n*     HMI timer system if we initialized it.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_StopTimerInt(VQAHandleP *vqap)\n{\n\tVQAAudio *audio;\n\n\t/* Dereference for quick access. */\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Decrement the timer interrupt usage count. */\n\tif (TimerIntCount) {\n\t\tTimerIntCount--;\n\t}\n\n\t/* Remove the timer interrrupt if it is initialized and the use count is\n\t * zero. Otherwise, clear the callers timer interrupt availability flag.\n\t */\n\tif (((AudioFlags & VQAAUDF_HMITIMER) == (HMI_VQAINIT<<VQAAUDB_HMITIMER))\n\t\t\t&& (TimerIntCount == 0)) {\n\n\t\tsosTIMERRemoveEvent(VQATimer);\n\t\tAudioFlags &= ~VQAAUDF_HMITIMER;\n\t} else {\n\t\taudio->Flags &= ~VQAAUDF_HMITIMER;\n\t}\n\n\t/* Derement the timer system usage count. */\n\tif (TimerSysCount) {\n\t\tTimerSysCount--;\n\t}\n\n\t/* Close the timer system if it has been opened and the use count is zero.\n\t * Otherwise, clear the callers timer system availability flag.\n\t */\n\tif (((AudioFlags & VQAAUDF_TIMERINIT) == (HMI_VQAINIT<<VQAAUDB_TIMERINIT))\n\t\t\t&& (TimerSysCount == 0)) {\n\n\t\tsosTIMERUnInitSystem(0);\n\t\tAudioFlags &= ~VQAAUDF_TIMERINIT;\n\t} else {\n\t\taudio->Flags &= ~VQAAUDF_TIMERINIT;\n\t}\n\n\t/* Unlock the memory accupied by this module. */\n\tif ((audio->Flags & VQAAUDF_MODLOCKED) == 1) {\n\t\tDPMI_Unlock(&StartAddr, (long)&EndAddr - (long)&StartAddr);\n\t\taudio->Flags &= ~VQAAUDF_MODLOCKED;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     TimerCallback - VQA timer event. (Called by HMI)\n*\n* SYNOPSIS\n*     TimerCallback()\n*\n*     void TimerCallback(void);\n*\n* FUNCTION\n*     Our custom timer event. This is the timer event that we register with\n*     HMI for system timing.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid far TimerCallback(void)\n{\n\tVQATickCount++;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_OpenAudio - Open sound system.\n*\n* SYNOPSIS\n*     Error = VQA_OpenAudio(VQAHandleP)\n*\n*     long VQA_OpenAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Initialize the sound system by setting the DigiHandle to and HMI\n*     driver handle. The timer must first be initialized before calling\n*     this function.\n*\n* INPUTS\n*     VQAHandleP - Pointer to private VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, -1 if error.\n*\n****************************************************************************/\n\nlong VQA_OpenAudio(VQAHandleP *vqap)\n{\n\tVQAData       *vqabuf;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tVQAHeader     *header;\n\tunsigned char *driver_path;\n\tWORD          port;\n\tlong          rc;\n\n\t/* Dereference data memebers for quicker access. */\n\tconfig = &vqap->Config;\n\theader = &vqap->Header;\n\tvqabuf = vqap->VQABuf;\n\taudio = &vqabuf->Audio;\n\n\t/* Fail if no audio buffer or DigiCard is 0 (no sound) */\n\tif ((audio->Buffer == NULL) || (config->DigiCard == 0)) {\n\t\treturn (-1);\n\t}\n\n\t/* Reset the buffer position to the beginning. */\n\taudio->CurBlock = 0;\n\n\t/* Initialize the HMI driver structure. */\n\taudio->sSOSInitDriver.wAllocateBuffer = _TRUE;\n\taudio->sSOSInitDriver.wParam = 19;\n\taudio->sSOSInitDriver.wTimerID = _SOS_NORMAL_TIMER;\n\n\t/*-------------------------------------------------------------------------\n\t * Compute the playback rate:\n\t *\n\t * - If Config->AudioRate is -1, use HMI_DATA_RATE scaled to the specified\n\t *   frame rate (so the audio plays faster if we're playing faster)\n\t * - otherwise, use the specified rate\n\t *-----------------------------------------------------------------------*/\n\tif (config->AudioRate != -1) {\n\t\taudio->sSOSInitDriver.wSampleRate = config->AudioRate;\n\t}\n\telse if (config->FrameRate != header->FPS) {\n\t\taudio->sSOSInitDriver.wSampleRate = ((audio->SampleRate*config->FrameRate)\n\t\t\t\t/ (unsigned long)header->FPS);\n\n\t\tconfig->AudioRate = audio->sSOSInitDriver.wSampleRate;\n\t} else {\n\t\taudio->sSOSInitDriver.wSampleRate = audio->SampleRate;\n\t\tconfig->AudioRate = audio->SampleRate;\n\t}\n\n\t/* If the application has already initialized HMI then set the\n\t * necessary variables. Otherwise we must setup HMI ourself.\n\t */\n\tif ((config->OptionFlags & VQAOPTF_HMIINIT)\n\t\t\t|| ((AudioFlags & VQAAUDF_DIGIINIT) != 0)) {\n\n\t\t/* The application MUST provide the card type! */\n\t\tif (config->DigiCard == -1) {\n\t\t\treturn (-1);\n\t\t}\n\n\t\t/* Init the detection system */\n\t\tdriver_path = (unsigned char *)\".\\\\\";\n\n\t\tif ((rc = sosDIGIDetectInit(driver_path)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Get the capabilities of the card being used. */\n\t\trc = sosDIGIDetectGetCaps(config->DigiCard, &audio->DigiCaps);\n\t\tsosDIGIDetectUnInit();\n\n\t\tif (rc != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\taudio->DigiHandle = config->DigiHandle;\n\t\taudio->Flags |= (HMI_APPINIT << VQAAUDB_TIMERINIT);\n\t\taudio->Flags |= (HMI_APPINIT << VQAAUDB_DIGIINIT);\n\n\t\tif ((AudioFlags & (VQAAUDF_TIMERINIT|VQAAUDF_DIGIINIT)) == 0) {\n\t\t\tHMIDevName = \"App-Specific\";\n\t\t\tAudioFlags |= (HMI_APPINIT << VQAAUDB_TIMERINIT);\n\t\t\tAudioFlags |= (HMI_APPINIT << VQAAUDB_DIGIINIT);\n\t\t}\n\t} else {\n\n\t\t/* Init the detection system */\n\t\tdriver_path = (unsigned char *)\".\\\\\";\n\n\t\tif ((rc = sosDIGIDetectInit(driver_path)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/*-----------------------------------------------------------------------\n\t\t * Initialize DigiHardware with port, IRQ, and DMA, and make sure\n\t\t * Config.DigiCard contains the HMI ID we want to use:\n\t\t *\n\t\t * - If Config.DigiCard is -1, auto-detect the hardware; then, do a \n\t\t *   FindHardware so the GetSettings will work\n\t\t * - If Config.DigiCard is filled in, but port, IRQ or DMA is -1, use\n\t\t *   FindHardware & GetSettings to get the settings\n\t\t * - If all are filled in, just use them as they are\n\t\t *---------------------------------------------------------------------*/\n\n\t\t/* Auto-Detect */\n\t\tif (config->DigiCard == -1) {\n\n\t\t\t/* Version 1 VQA's have only 8 bit mono audio streams. */\n\t\t\tif (header->Version == VQAHD_VER1) {\n\t\t\t\tconfig->DigiCard = AutoDetect(&audio->DigiCaps, 8, 1);\n\t\t\t} else {\n\t\t\t\tconfig->DigiCard = AutoDetect(&audio->DigiCaps, audio->BitsPerSample,\n\t\t\t\t\t\taudio->Channels);\n\n\t\t\t\t/* Resort to 8bit mono */\n\t\t\t\tif (config->DigiCard == -1) {\n\t\t\t\t\tconfig->DigiCard = AutoDetect(&audio->DigiCaps, 8, 1);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (config->DigiCard == -1) {\n\t\t\t\tsosDIGIDetectUnInit();\n\t\t\t\treturn (-1);\n\t\t\t}\n\t\t}\n\n\t\t/* Do a FindHardware & GetSettings */\n\t\tif (config->DigiPort == -1) {\n\t\t  if (sosDIGIDetectFindHardware(config->DigiCard, &audio->DigiCaps,\n\t\t\t\t\t&port)) {\n\n\t\t\t\tsosDIGIDetectUnInit();\n\t\t\t\treturn (-1);\n\t\t\t}\n\n\t\t\tif (sosDIGIDetectGetSettings(&audio->DigiHardware)) {\n\t\t\t\tsosDIGIDetectUnInit();\n\t\t\t\treturn (-1);\n\t\t\t}\n\n\t\t\tconfig->DigiPort = audio->DigiHardware.wPort;\n\t\t\tconfig->DigiIRQ = audio->DigiHardware.wIRQ;\n\t\t\tconfig->DigiDMA = audio->DigiHardware.wDMA;\n\t\t\tHMIDevName = (char *)audio->DigiCaps.szDeviceName;\n\t\t} else {\n\t\t\taudio->DigiHardware.wPort = config->DigiPort;\n\t\t\taudio->DigiHardware.wIRQ = config->DigiIRQ;\n\t\t\taudio->DigiHardware.wDMA = config->DigiDMA;\n\t\t\tHMIDevName = \"App-Specific\";\n\t\t}\n\n\t\tsosDIGIDetectUnInit();\n\n\t\t/* Initialize the DIGI system & driver */\n\t\tsosDIGIInitSystem(driver_path, _SOS_DEBUG_NORMAL);\n\t\taudio->sSOSInitDriver.wBufferSize = config->HMIBufSize;\n\t\taudio->sSOSInitDriver.lpBuffer = NULL;\n\t\taudio->sSOSInitDriver.lpFillHandler = NULL;\n\t\taudio->sSOSInitDriver.lpDriverMemory = NULL;\n\t\taudio->sSOSInitDriver.lpTimerMemory = NULL;\n\t\taudio->DigiHandle = -1;\n\n\t\tif ((rc = sosDIGIInitDriver(config->DigiCard, &audio->DigiHardware, \n\t\t\t\t&audio->sSOSInitDriver, &audio->DigiHandle)) != 0) {\n\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/*-----------------------------------------------------------------------\n\t\t * Register the timer event\n\t\t *---------------------------------------------------------------------*/\n\n\t\t/* If the timer hasn't been init'd, do it now */\n\t\tif ((AudioFlags & VQAAUDF_TIMERINIT) == (HMI_UNINIT<<VQAAUDB_TIMERINIT)) {\n\t\t\tsosTIMERInitSystem(_TIMER_DOS_RATE ,_SOS_DEBUG_NORMAL);\n\t\t\taudio->Flags |= (HMI_VQAINIT << VQAAUDB_TIMERINIT);\n \t\t\tAudioFlags |= (HMI_VQAINIT << VQAAUDB_TIMERINIT);\n\t\t}\n\n\t\t/* Register the event */\n\t\trc = sosTIMERRegisterEvent(VQA_TIMETICKS,\n\t\t\t\taudio->sSOSInitDriver.lpFillHandler, &audio->DigiTimer);\n\n\t\tif (rc) {\n\t\t\tsosDIGIUnInitDriver(audio->DigiHandle, _TRUE, _TRUE);\n\t\t\tsosDIGIUnInitSystem();\n\t\t\treturn (rc);\n\t\t}\n\n\t\tconfig->DigiHandle = audio->DigiHandle;\n\t\taudio->Flags |= (HMI_VQAINIT << VQAAUDB_DIGIINIT);\n\t\tAudioFlags |= (HMI_VQAINIT << VQAAUDB_DIGIINIT);\n\t}\n\n\tif ((audio->Flags & VQAAUDF_MODLOCKED) == 0) {\n\t\tDPMI_Lock(&StartAddr, (long)&EndAddr - (long)&StartAddr);\n\t\taudio->Flags |= VQAAUDF_MODLOCKED;\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_CloseAudio - Close sound system\n*\n* SYNOPSIS\n*     VQA_CloseAudio()\n*\n*     void VQA_CloseAudio(void);\n*\n* FUNCTION\n*     Removes VQA's involvement in the audio system.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_CloseAudio(VQAHandleP *vqap)\n{\n\tVQAAudio *audio;\n\n\t/* Dereference for quick access. */\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Remove the Digi event */\n\tif ((AudioFlags & VQAAUDF_DIGIINIT) == (HMI_VQAINIT<<VQAAUDB_DIGIINIT)) {\n\t\tsosTIMERRemoveEvent(audio->DigiTimer);\n\t}\n\n\t/* Un-init timer if necessary */\n\tif ((AudioFlags & VQAAUDF_TIMERINIT) == (HMI_VQAINIT<<VQAAUDB_TIMERINIT)) {\n\t\tsosTIMERUnInitSystem(0);\n\t}\n\n\taudio->Flags &= ~VQAAUDF_TIMERINIT;\n\tAudioFlags &= ~VQAAUDF_TIMERINIT;\n\n\t/* Remove the driver */\n\tif ((audio->Flags & VQAAUDF_DIGIINIT) == (HMI_VQAINIT<<VQAAUDB_DIGIINIT)) {\n\t\tsosDIGIUnInitDriver(audio->DigiHandle, _TRUE, _TRUE);\n\t\tsosDIGIUnInitSystem();\n\t}\n\n\taudio->Flags &= ~VQAAUDF_DIGIINIT;\n\tAudioFlags &= ~VQAAUDF_DIGIINIT;\n\tAudioFlags &= ~VQAAUDF_ISPLAYING;\n\n\t/* Unlock the memory accupied by this module. */\n\tif ((audio->Flags & VQAAUDF_MODLOCKED) == 1) {\n\t\tDPMI_Unlock(&StartAddr, (long)&EndAddr - (long)&StartAddr);\n\t\taudio->Flags &= ~VQAAUDF_MODLOCKED;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     AutoDetect - Auto detect the sound card.\n*\n* SYNOPSIS\n*     CardID = AutoDetect(DigiCaps, BitSize, Channels)\n*\n*     long AutoDetect(_SOS_CAPABILITIES *, long, long);\n*\n* FUNCTION\n*     Autodetects the type of sound card present in the system.\n*\n* INPUTS\n*     DigiCaps - Pointer to HMI digital card capabilities structure.\n*     BitSize  - Bits per sample size.\n*     Channels - Number of desired channels.\n*\n* RESULT\n*     CardID - HMI ID of the sound card found, -1 if none.\n*\n****************************************************************************/\n\nlong AutoDetect(_SOS_CAPABILITIES *digicaps, long bitsize, long channels)\n{\n\tlong device_id = -1;\n\tWORD port;\n\tlong i;\n\tlong rc;\n\n\t/* Search for an 8-bit mono device */\n\tif (sosDIGIDetectFindFirst(digicaps, &port)) {\n\t\treturn (-1);\n\t}\n\n\tchannels--;\n\n\ti = 0;\n\twhile (i < 6) {\n\t\ti++;\n\n\t\tif ((digicaps->wBitsPerSample == bitsize)\n\t\t\t\t&& (digicaps->wChannels == channels)) {\n\n\t\t\tbreak;\n\t\t}\n\n\t\tif (sosDIGIDetectFindNext(digicaps, &port)) {\n\t\t\treturn (-1);\n\t\t}\n\t}\n\n\t/* Exit if failed to find the required device */\n\tif ((digicaps->wBitsPerSample != bitsize)\n\t\t\t|| (digicaps->wChannels != channels)) {\n\n\t\treturn (-1);\n\t}\n\n\t/* Stash the ID */\n\tdevice_id = digicaps->wDeviceID;\n\n\t/* Now that we have handled the initial pass, verify that if we found an\n\t * _ADLIB_GOLD_8_MONO that it is not a Logitech Sound Wave man in disguise.\n\t */\n\tif ((WORD)digicaps->wDeviceID == _ADLIB_GOLD_8_MONO) {\n\t\trc = sosDIGIDetectFindNext(digicaps, &port);\n\n\t\twhile ((i < 6) && (rc == 0)) {\n\t\t\ti++;\n\n\t\t\tif ((digicaps->wBitsPerSample == 8) && (digicaps->wChannels == 0)) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif ((rc = sosDIGIDetectFindNext(digicaps, &port)) != 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/* If we don't have an error use the secondary device ID, after all, \n\t\t * anything's better than an Adlib Gold.  If we do have an error or there\n\t\t * is nothing we can use then the device ID is already set to the adlib \n\t\t * gold so just let it rip.\n\t\t */\n\t\tif ((rc == 0) && ((WORD)digicaps->wDeviceID == _SBPRO_8_MONO)) {\n\t\t\treturn (digicaps->wDeviceID);\n\t\t}\n\t}\n\n\treturn (device_id);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StartAudio - Starts audio playback\n*\n* SYNOPSIS\n*     Error = VQA_StartAudio(VQA)\n*\n*     long VQA_StartAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Start the audio playback for the movie.\n*\n* INPUTS\n*     VQA - Pointer to private VQA handle.\n*\n* RESULT\n*     Error - 0 if successful, or -1 error code.\n*\n****************************************************************************/\n\nlong VQA_StartAudio(VQAHandleP *vqap)\n{\n\tVQAConfig *config;\n\tVQAAudio  *audio;\n\n\t/* Save buffers for the callback routine */\n\tVQAP = vqap;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tconfig = &vqap->Config;\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Return if already playing */\n\tif (AudioFlags & VQAAUDF_ISPLAYING) {\n\t\treturn (-1);\n\t}\n\n \t/* Set my driver handle */\n\tif (config->DigiHandle != -1) {\n\t\taudio->DigiHandle = config->DigiHandle;\n\t}\n\n\tif (audio->DigiHandle == (WORD)-1) {\n\t\treturn (-1);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * Initialize the sample structure.\n\t *-----------------------------------------------------------------------*/\n\tmemset(&audio->sSOSSampleData, 0, sizeof(_SOS_START_SAMPLE));\n  audio->sSOSSampleData.lpSamplePtr = (unsigned char *)audio->Buffer;\n \taudio->sSOSSampleData.dwSampleSize = config->HMIBufSize;\n\taudio->sSOSSampleData.wVolume = (config->Volume << 7);\n\taudio->sSOSSampleData.wSampleID = HMI_SAMPLE;\n\taudio->sSOSSampleData.lpCallback = AudioCallback;\n\n\t/* Set the channel flags for the type of data we have. */\n\tif (audio->Channels == 2) {\n\t\taudio->sSOSSampleData.wChannel = _INTERLEAVED;\n\t} else {\n\t\taudio->sSOSSampleData.wChannel = _CENTER_CHANNEL;\n\t}\n\n\t/* If the card is unable to handle stereo data the we must notify the\n\t * sound system to convert the stereo data to mono data during playback.\n\t */\n\tif ((audio->Channels - 1) > audio->DigiCaps.wChannels) {\n\t\taudio->sSOSSampleData.wSampleFlags |= _STEREOTOMONO;\n\t}\n\n\t/* If the card is unable to handle the sample size of the audio data\n\t * then we must notify the sound system to convert the audio data to\n\t * the proper format.\n\t */\n\tif (audio->BitsPerSample != audio->DigiCaps.wBitsPerSample) {\n\t\tif (audio->BitsPerSample > audio->DigiCaps.wBitsPerSample) {\n\t\t\taudio->sSOSSampleData.wSampleFlags |= _TRANSLATE16TO8;\n\t\t} else {\n\t\t\taudio->sSOSSampleData.wSampleFlags |= _TRANSLATE8TO16;\n\t\t}\n\t}\n\n\t/* Adjust the pitch if the driver is setup to playback at a different\n\t * rate than what the sample was recorded at.\n\t */\n\tif (audio->sSOSInitDriver.wSampleRate != audio->SampleRate) {\n\t\tldiv_t result;\n\n\t\tresult = ldiv(audio->SampleRate, audio->sSOSInitDriver.wSampleRate);\n\t\taudio->sSOSSampleData.dwSamplePitchAdd = (long)MAKE_LONG((short)result.quot,\n\t\t\t\t(short)(((long)result.rem * 0x10000L) / audio->sSOSInitDriver.wSampleRate));\n\t\taudio->sSOSSampleData.wSampleFlags |= _PITCH_SHIFT;\n\t}\n\n\t/* Start playback */\n \taudio->SampleHandle = sosDIGIStartSample(audio->DigiHandle, \n\t\t\t&audio->sSOSSampleData);\n\n\taudio->Flags |= VQAAUDF_ISPLAYING;\n\tAudioFlags |= VQAAUDF_ISPLAYING;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StopAudio - Stop audio playback.\n*\n* SYNOPSIS\n*     VQA_StopAudio(VQA)\n*\n*     void VQA_StopAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Halts the currently playing audio stream.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_StopAudio(VQAHandleP *vqap)\n{\n\tVQAAudio *audio;\n\n\t/* Dereference for quick access. */\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Just return if not playing */\n\tif (AudioFlags & VQAAUDF_ISPLAYING) {\n\t\tsosDIGIStopSample(audio->DigiHandle, audio->SampleHandle);\n\t\taudio->Flags &= ~VQAAUDF_ISPLAYING;\n\t\tAudioFlags &= ~VQAAUDF_ISPLAYING;\n\t}\n\n\tVQAP = NULL;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     CopyAudio - Copy data from Audio Temp buffer into Audio play buffer.\n*\n* SYNOPSIS\n*     Error = CopyAudio(VQA)\n*\n*     long CopyAudio(VQAHandleP *);\n*\n* FUNCTION\n*     This routine just copies the data in the TempBuf into the correct\n*     spots in the audio play buffer.  If there is no room available in the\n*     audio play buffer, the routine returns VQAERR_SLEEPING, which will put\n*     the whole Loader to \"sleep\" while it waits for a free buffer.\n*\n*     If there's no data in the TempBuf to copy, the routine just returns 0.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle structure.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nlong CopyAudio(VQAHandleP *vqap)\n{\n\tVQAAudio  *audio;\n\tVQAConfig *config;\n\tlong      startblock;\n\tlong      endblock;\n\tlong      len1,len2;\n\tlong      i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\taudio = &vqap->VQABuf->Audio;\n\tconfig = &vqap->Config;\n\n\t/* If audio is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, or if there's no data to copy, just return 0\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (vqap->vocfh != -1)\n\t\t\t|| (audio->Buffer == NULL) || (audio->TempBufLen == 0)) {\n\t#else  /* VQAVOC_ON */\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (audio->Buffer == NULL)\n\t\t\t|| (audio->TempBufLen == 0)) {\n\t#endif /* VQAVOC_ON */\n\n\t\treturn (0);\n\t}\n\n\t/* Compute start & end blocks to copy into */\n\tstartblock = (audio->AudBufPos / config->HMIBufSize);\n\tendblock = (audio->AudBufPos + audio->TempBufLen) / config->HMIBufSize;\n\n\tif (endblock >= audio->NumAudBlocks) {\n\t\tendblock -= audio->NumAudBlocks;\n\t}\n\n\t/* If 'endblock' hasn't played yet, return VQAERR_SLEEPING */\n\tif (audio->IsLoaded[endblock] == 1) {\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\t/* Copy the data:\n\t *\n\t *  - If 'startblock' < 'endblock', copy the entire buffer\n\t *  - Otherwise, fill to the end of the buffer with part of the data, then\n\t *    copy the rest to the beginning of the buffer\n\t */\n\tif (startblock <= endblock) {\n\n\t\t/* Copy data */\n\t\tmemcpy((audio->Buffer + audio->AudBufPos), audio->TempBuf,\n\t\t\t\taudio->TempBufLen);\n\n\t\t/* Adjust current load position */\n\t\taudio->AudBufPos += audio->TempBufLen;\n\n\t\t/* Mark buffer as empty */\n\t\taudio->TempBufLen = 0;\n\n\t\t/* Set all blocks to loaded */\n\t\tfor (i = startblock; i < endblock; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t} else {\n\n\t\t/* Compute length of each piece */\n\t\tlen1 = config->AudioBufSize - audio->AudBufPos;\n\t\tlen2 = audio->TempBufLen - len1;\n \n\t\t/* Copy 1st piece into end of Audio Buffer */\n\t\tmemcpy((audio->Buffer + audio->AudBufPos), audio->TempBuf, len1);\n\n\t\t/* Copy 2nd piece into start of Audio Buffer */\n\t\tmemcpy(audio->Buffer, audio->TempBuf + len1, len2);\n\t\t\n\t\t/* Adjust load position */\n\t\taudio->AudBufPos = len2;\n\n\t\t/* Mark buffer as empty */\n\t\taudio->TempBufLen = 0;\n\n\t\t/* Set blocks to loaded */\n\t\tfor (i = startblock; i < audio->NumAudBlocks; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\tfor (i = 0; i < endblock; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     AudioCallback - Sound system callback.\n*\n* SYNOPSIS\n*     AudioCallback(DriverHandle, Action, SampleID)\n*\n*     void AudioCallback(WORD, WORD, WORD);\n*\n* FUNCTION\n*     Our custom audio callback routine that services HMI.\n*\n* INPUTS\n*     DriverHandle - HMI driver handle.\n*     Action       - Action taken.\n*     SampleID     - ID of sample.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid far cdecl AudioCallback(WORD wDriverHandle,WORD wAction,WORD wSampleID)\n{\n\tVQAAudio  *audio;\n\tVQAConfig *config;\n\n\t/* Dereference commonly used data members for quicker access. */\n\taudio = &VQAP->VQABuf->Audio;\n\tconfig = &VQAP->Config;\n\n\t/* Suppress compiler warnings */\n\twDriverHandle = wDriverHandle;\n\twSampleID = wSampleID;\n\n  /* See if we're called because the buffer is empty */\n\tif (wAction == _SAMPLE_PROCESSED) {\n\n\t\t/* Compute the 'NextBlock' index */\n\t\taudio->NextBlock = audio->CurBlock + 1;\n\n\t\tif (audio->NextBlock >= audio->NumAudBlocks) {\n\t\t\taudio->NextBlock = 0;\n\t\t}\n\n\t\t/* See if the next block has data in it; if so, update the audio\n\t\t * buffer play position & the 'CurBlock' value.\n\t\t * If not, don't change anything and replay this block.\n\t\t */\n\t\tif (audio->IsLoaded[audio->NextBlock] == 1) {\n\n\t\t\t/* Update this block's status to loadable (0) */\n\t\t\taudio->IsLoaded[audio->CurBlock] = 0;\n\n\t\t\t/* Update position within audio buffer */\n\t\t\taudio->PlayPosition += config->HMIBufSize;\n\t\t\taudio->CurBlock++;\n\n\t\t\tif (audio->PlayPosition >= config->AudioBufSize) {\n\t\t\t\taudio->PlayPosition = 0;\n\t\t\t\taudio->CurBlock = 0;\n\t\t\t}\n\t\t} else {\n\t\t\taudio->NumSkipped++;\n\t\t}\n\n\t\t/* Start the new buffer playing */\n\t  audio->sSOSSampleData.lpSamplePtr = (unsigned char *)(audio->Buffer)\n\t\t\t\t+ audio->PlayPosition;\n\n   \tsosDIGIContinueSample(audio->DigiHandle, audio->SampleHandle,\n\t\t\t\t&audio->sSOSSampleData);\n\n\t\taudio->SamplesPlayed += config->HMIBufSize;\n\t}\n}\n\n/* Dummy function used to mark the beginning address of the file. */\nstatic void EndAddr(void)\n{\n}\n#endif /* VQAAUDIO_ON */\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_SetTimer - Resets current time to given tick value.\n*\n* SYNOPSIS\n*     VQA_SetTimer(Time, Method)\n*\n*     void VQA_SetTimer(long, long);\n*\n* FUNCTION\n*     Sets 'TickOffset' to a value that will make the current time look like\n*     the time passed in. This function allows the player to be \"paused\",\n*     by recording the time of the pause, and then setting the timer to\n*     that time. The timer method used by the player is also set. The method\n*     selected is not neccesarily the method that will be used because some\n*     timer methods work with only certain playback conditions. (EX: The\n*     audio DMA timer method cannot be used if there is not any audio\n*     playing.)\n*\n* INPUTS\n*     Time   - Value to set current time to.\n*     Method - Timer method to use.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_SetTimer(VQAHandleP *vqap, long time, long method)\n{\n\tunsigned long curtime;\n\n\t#if(VQAAUDIO_ON)\n\tVQAAudio      *audio;\n\n\t/* Dereference for quick access. */\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* If the client does not have a preferencee then pick a method\n\t * based on the state of the player.\n\t */\n\tif (method == VQA_TMETHOD_DEFAULT) {\n\n\t\t/* If we are playing audio, use the audio DMA position. */\n\t\tif (AudioFlags & VQAAUDF_ISPLAYING) {\n\t\t\tmethod = VQA_TMETHOD_AUDIO;\n\t\t}\n\n\t\t/* Otherwise use the HMI timer if it is initialized. */\n\t\telse if (AudioFlags & VQAAUDF_HMITIMER) {\n\t\t\tmethod = VQA_TMETHOD_INT;\n\t\t}\n\n\t\t/* If all else fails resort the the \"jerky\" DOS time. */\n\t\telse {\n\t\t\tmethod = VQA_TMETHOD_DOS;\n\t\t}\n\t} else {\n\n\t\t/* We cannot use the DMA position if there isn't any audio playing. */\n\t\tif (!(AudioFlags & VQAAUDF_ISPLAYING) && (method == VQA_TMETHOD_AUDIO)) {\n\t\t\tmethod = VQA_TMETHOD_INT;\n\t\t}\n\n\t\t/* We cannot use the timer if it has not been initialized. */\n\t\tif (!(AudioFlags & VQAAUDF_HMITIMER) && (method == VQA_TMETHOD_INT)) {\n\t\t\tmethod = VQA_TMETHOD_DOS;\n\t\t}\n\t}\n\n\tTimerMethod = method;\n\t#else\n\tmethod = method;\n\t#endif\n\n\tTickOffset = 0L;\n\tcurtime = VQA_GetTime(vqap);\n\tTickOffset = (time - curtime);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_GetTime - Return current time.\n*\n* SYNOPSIS\n*     Time = VQA_GetTime()\n*\n*     unsigned long VQA_GetTime(void);\n*\n* FUNCTION\n*     This routine returns timer ticks computed one of 3 ways:\n*\n*     1) If audio is playing, the timer is based on the DMA buffer position:\n*        Compute the number of audio samples that have actually been played.\n*        The following internal HMI variables are used:\n*\n*          _lpSOSDMAFillCount[drv_handle]: current DMA buffer position\n*          _lpSOSSampleList[drv_handle][samp_handle]:\n*          sampleTotalBytes: total bytes sent by HMI to the DMA buffer\n*          sampleLastFill: HMI's last fill position in DMA buffer\n*\n*        So, the number of samples actually played is:\n*\n*          sampleTotalBytes - <DMA_diff>\n*          where <DMA_diff> is how far ahead sampleLastFill is in front of\n*          _lpSOSDMAFillCount: (sampleLastFill - _lpSOSDMAFillCount)\n*\n*        These values are indices into a circular DMA buffer, so:\n*\n*          if (sampleLastFill >= _lpSOSDMAFillCount)\n*            <DMA_diff> = sampleLastFill - _lpSOSDMAFillCount\n*          else\n*            <DMA_diff> = (DMA_BUF_SIZE - lpSOSDMAFillCount) + sampleLastFill\n*\n*        Note that, if using the stereo driver with mono data, you must\n*        divide LastFill & FillCount by 2, but not TotalBytes. If using the\n*        stereo driver with stereo data, you must divide all 3 variables\n*        by 2.\n*\n*     2) If no audio is playing, but the timer interrupt is running,\n*        VQATickCount is used as the timer\n*\n*     3) If no audio is playing & no timer interrupt is going, the DOS 18.2\n*        system timer is used.\n*\n*     Regardless of the method, TickOffset is used as an offset from the\n*     computed time.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Time - Time in VQA_TIMETICKS\n*\n****************************************************************************/\n\nunsigned long VQA_GetTime(VQAHandleP *vqap)\n{\n\t#if(VQAAUDIO_ON)\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tunsigned long fillcount;\n\tunsigned long lastfill;\n\tunsigned long dma_diff;\n\tunsigned long totalbytes;\n\tunsigned long samples;\n\t#endif\n\n\tlong ticks;\n\n\t#if(VQAAUDIO_ON)\n\tswitch (TimerMethod) {\n\n\t\t/* If Audio is playing then timing is based on the audio DMA buffer\n\t\t * position.\n\t\t */\n\t\tcase VQA_TMETHOD_AUDIO:\n\n\t\t\t/* Dereference commonly used data members for quicker access. */\n\t\t\taudio = &vqap->VQABuf->Audio;\n\t\t\tconfig = &vqap->Config;\n\n\t\t\t/* Compute our current position in the audio track by getting the\n\t\t\t * bytes processed by HMI. Then adjust the bytes processed by the\n\t\t\t * position of the DMA fill handler, this should tell us exactly\n\t\t\t * where we are in the audio track.\n\t\t\t */\n\t\t\tfillcount = (unsigned long)(*_lpSOSDMAFillCount[audio->DigiHandle]);\n\t\t\tlastfill = _lpSOSSampleList[audio->DigiHandle][audio->SampleHandle]->sampleLastFill;\n\t\t\ttotalbytes = _lpSOSSampleList[audio->DigiHandle][audio->SampleHandle]->sampleTotalBytes;\n\n\t\t\tif (totalbytes == 0) {\n\t\t\t\tdma_diff = 0;\n\t\t\t} else {\n\t\t\t\tif (lastfill > fillcount) {\n\t\t\t\t\tdma_diff = lastfill - fillcount;\n\t\t\t\t} else {\n\t\t\t\t\tdma_diff = (config->HMIBufSize - fillcount) + lastfill;\n\t\t\t\t}\n\n\t\t\t\tif (dma_diff > totalbytes) {\n\t\t\t\t\tdma_diff = totalbytes;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Calculate the number of samples by taking the total number of\n\t\t\t * bytes processed and divide it by the number of channels and \n\t\t\t * bits per sample.\n\t\t\t */\n\t\t\tsamples = totalbytes - dma_diff;\n\t\t\tsamples -= (audio->NumSkipped * config->HMIBufSize);\n\t\t\tsamples /= (audio->Channels * (audio->BitsPerSample >> 3));\n\n\t\t\t/* The elapsed ticks is calculated by the number of samples\n\t\t\t * processed times the tick resolution per second divided by the\n\t\t\t * sample rate.\n\t\t\t */\n\t\t\tticks = (long)((samples * VQA_TIMETICKS) / audio->SampleRate);\n\t\t\tticks += TickOffset;\n\t\t\tbreak;\n\n\t\t/* No audio playing, but timer interrupt is going; use VQATickCount */\n\t\tcase VQA_TMETHOD_INT:\n\t\t\tticks = (VQATickCount + TickOffset);\n\t\t\tbreak;\n\n\t\t/* No interrupts are going at all; use DOS's time */\n\t\tdefault:\n\t\tcase VQA_TMETHOD_DOS:\n\t\t\t{\n\t\t\tstruct timeb mytime;\n\n\t\t\tftime(&mytime);\n \t\t\tticks = (unsigned long)mytime.time*1000L+(unsigned long)mytime.millitm;\n\t\t\tticks = ((ticks * VQA_TIMETICKS) / 1000L);\n\t\t\tticks += TickOffset;\n\t\t\t}\n\t\t\tbreak;\n\t}\n\t#else\n\t{\n\tstruct timeb mytime;\n\n\tvqap = vqap;\n\tftime(&mytime);\n\tticks = (unsigned long)mytime.time*1000L+(unsigned long)mytime.millitm;\n\tticks = ((ticks * VQA_TIMETICKS) / 1000L);\n\tticks += TickOffset;\n\t}\n\t#endif\n\n\treturn (ticks);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_TimerMethod - Get timer method being used.\n*\n* SYNOPSIS\n*     Method = VQA_TimerMethod()\n*\n*     long VQA_TimerMethod(void);\n*\n* FUNCTION\n*     Returns the ID of the current timer method being used.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Method - Method used for the timer.\n*\n****************************************************************************/\n\nlong VQA_TimerMethod(void)\n{\n\t#if(VQAAUDIO_ON)\n\treturn (TimerMethod);\n\t#else\n\treturn (VQA_TMETHOD_DOS);\n\t#endif\n}\n\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n\n"
  },
  {
    "path": "VQ/VQA32/BCC32.CFG",
    "content": "-c\n-3\n-d\n-H=c:\\projects\\vqa32\\obj\\headers.sym\n-wpro\n-weas\n-wpre\n-IC:\\PROJECTS\\INCLUDE;C:\\DEV\\BC4\\INCLUDE;C:\\DEV\\TNT\\INCLUDE\n-DPHARLAP_TNT=1\n"
  },
  {
    "path": "VQ/VQA32/CAPTION.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library (32 bit protected mode)\n*\n* FILE\n*     caption.c\n*\n* DESCRIPTION\n*     Text caption process/display manager.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 26, 1995\n*\n****************************************************************************/\n\n#include <mem.h>\n#include <malloc.h>\n#include <vqm32\\font.h>\n#include <vqm32\\text.h>\n#include <vqm32\\graphics.h>\n#include <vqm32\\captoken.h>\n#include \"caption.h\"\n\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n#define NUM_NODES 3\n\n/* Function prototypes. */\nstatic CaptionNode *AddCaptionNode(CaptionList *list, CaptionText *captext);\nstatic void RemCaptionNode(CaptionList *list, CaptionNode *node);\n\n\n/****************************************************************************\n*\n* NAME\n*     OpenCaptions - Initialize the caption system.\n*\n* SYNOPSIS\n*     OpenCaptions(Captions, Font)\n*\n*     CaptionInfo *OpenCaptions(void *, void *);\n*\n* FUNCTION\n*     Allocate and initialize resources used by the caption system.\n*\n* INPUTS\n*     Captions - Captions to process.\n*     Font     - Font to use to display captions.\n*\n* RESULT\n*     CaptionInfo - Caption information structure.\n*\n* SEE ALSO\n*     CloseCaption\n*\n****************************************************************************/\n\nCaptionInfo *OpenCaptions(void *captions, void *font)\n{\n\tCaptionInfo *cap = NULL;\n\tCaptionNode *node;\n\tFontInfo    *fi;\n\tlong        i;\n\n\t/* Allocate memory for the captioning system. */\n\tcap = (CaptionInfo *)malloc(sizeof(CaptionInfo) + (sizeof(CaptionNode)\n\t\t\t* NUM_NODES));\n\n\tif (cap != NULL) {\n\t\tmemset(cap,0,(sizeof(CaptionInfo) + (sizeof(CaptionNode) * NUM_NODES)));\n\t\tcap->Buffer = captions;\n\t\tcap->Next = (CaptionText *)captions;\n\n\t\t/* Initialize font */\n\t\tfi = (FontInfo *)((char *)font + ((Font *)font)->InfoBlk);\n\t\tcap->Font = font;\n\t\tcap->FontHeight = fi->MaxHeight;\n\t\tcap->FontWidth = fi->MaxWidth;\n\n\t\t/* Initialize list header. */\n\t\tcap->List.Head = (CaptionNode *)&cap->List.Tail;\n\t\tcap->List.Tail = NULL;\n\t\tcap->List.TailPred = (CaptionNode *)&cap->List.Head;\n\n\t\t/* Link nodes. */\n\t\tnode = (CaptionNode *)((char *)cap + sizeof(CaptionInfo));\n\n\t\tfor (i = 0; i < NUM_NODES; i++) {\n\t\t\tnode->Succ = cap->List.Head;\n\t\t\tcap->List.Head = node;\n\t\t\tnode->Pred = (CaptionNode *)&cap->List.Head;\n\t\t\tnode->Succ->Pred = node;\n\n\t\t\t/* Next node. */\n\t\t\tnode = (CaptionNode *)((char *)node + sizeof(CaptionNode));\n\t\t}\n\t}\n\n\treturn (cap);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     CloseCaptions - Shutdown the caption system.\n*\n* SYNOPSIS\n*     CloseCaptions(CaptionInfo)\n*\n*     void CloseCaptions(CaptionInfo *);\n*\n* FUNCTION\n*     Free the resources allocated by the caption system.\n*\n* INPUTS\n*     CaptionInfo - Caption information structure.\n*\n* RESULT\n*     NONE\n*\n* SEE ALSO\n*     OpenCaptions\n*\n****************************************************************************/\n\nvoid CloseCaptions(CaptionInfo *cap)\n{\n\tfree(cap);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DoCaption - Process and display caption text.\n*\n* SYNOPSIS\n*     DoCaption(Captions, Frame)\n*\n*     void DoCaption(CaptionInfo *, unsigned long);\n*\n* FUNCTION\n*     Process the caption events.\n*\n* INPUTS\n*     Captions - Pointer to CaptionInfo structure.\n*     Frame    - Current frame number being processed.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid DoCaptions(CaptionInfo *cap, unsigned long frame)\n{\n\tCaptionText *captext;\n\tCaptionNode *node;\n\tvoid const  *oldfont;\n\tlong        width;\n\tlong        i;\n\n\t/* Initialize variables. */\n\toldfont = Set_Font((char *)cap->Font);\n\n\t/*-------------------------------------------------------------------------\n\t * Process the captions that are on the active queue.\n\t *-----------------------------------------------------------------------*/\n\tnode = cap->List.Head;\n\n\twhile ((node->Succ != NULL) && (node->Flags & CNF_USED)) {\n\t\tcaptext = node->Captext;\n\n\t\t/* Clear the any previous captions that have expired. */\n\t\tif (captext->OffFrame <= frame) {\n\t\t\tFill_Rect(captext->Xpos, captext->Ypos,\n\t\t\t\t\t(captext->Xpos + node->BoundW - 1),\n\t\t\t\t\t(captext->Ypos + node->BoundH - 1), 0);\n\n\t\t\t/* Remove the caption from the active list. */\n\t\t\tnode = node->Pred;\n\t\t\tRemCaptionNode(&cap->List, node->Succ);\n\t\t} else {\n\t\t\tif (captext->CPF != 0) {\n\n\t\t\t\t/* If a NULL terminator is not found then display the next set of\n\t\t\t\t * characters, otherwise remove the node.\n\t\t\t\t */\n\t\t\t\tif (*node->Char != 0) {\n\t\t\t\t\tSet_Font_Palette_Range(&captext->BgPen, 0, 1);\n\n\t\t\t\t\tfor (i = 0; i < captext->CPF; i++) {\n\n\t\t\t\t\t\t/* Check for terminator. */\n\t\t\t\t\t\tif (*node->Char == 0) {\n\t\t\t\t\t\t\tcaptext->CPF = 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t/* Check for newline. */\n\t\t\t\t\t\telse if (*node->Char == 0x0D) {\n\t\t\t\t\t\t\tnode->Char++;\n\t\t\t\t\t\t\tnode->CurX = captext->Xpos;\n\t\t\t\t\t\t\tnode->CurY += cap->FontHeight;\n\t\t\t\t\t\t\tnode->BoundH += cap->FontHeight;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tDraw_Char(*node->Char, node->CurX, node->CurY);\n\t\t\t\t\t\tnode->CurX += Char_Pixel_Width(*node->Char);\n\t\t\t\t\t\tnode->Char++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (captext->Flags & CTF_FLASH) {\n\t\t\t\tif (frame & 4) {\n\t\t\t\t\tFill_Rect(captext->Xpos, captext->Ypos,\n\t\t\t\t\t\t\t(captext->Xpos + node->BoundW - 1),\n\t\t\t\t\t\t\t(captext->Ypos + node->BoundH - 1), 0);\n\t\t\t\t} else {\n\t\t\t \t\tText_Print(captext->Text, captext->Xpos, captext->Ypos,\n\t\t\t\t\t\t\tcaptext->FgPen, captext->BgPen);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Next node. */\n\t\tnode = node->Succ;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * Process any captions that are waiting to be activated.\n\t *-----------------------------------------------------------------------*/\n\tcaptext = cap->Next;\n\n\twhile (captext->OnFrame <= frame) {\n\n\t\twidth = String_Pixel_Width(captext->Text);\n\n\t\tswitch (captext->Flags & CTF_JUSTIFY) {\n\t\t\tcase CTF_RIGHT:\n\t\t\t\tcaptext->Xpos = (319 - width);\n\t\t\t\tbreak;\n\n\t\t\tcase CTF_LEFT:\n\t\t\t\tcaptext->Xpos = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase CTF_CENTER:\n\t\t\t\tcaptext->Xpos = (160 - (width / 2));\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/* Display the text and record its bounding box. */\n\t\tif (captext->CPF == 0) {\n\t \t\ti = Text_Print(captext->Text, captext->Xpos, captext->Ypos,\n\t\t\t\t\tcaptext->FgPen, captext->BgPen);\n\n\t\t\tnode = AddCaptionNode(&cap->List, captext);\n\t\t\tnode->BoundW = width;\n\t\t\tnode->BoundH = (cap->FontHeight * i);\n\t\t} else {\n\t\t\tnode = AddCaptionNode(&cap->List, captext);\n\t\t\tnode->BoundW = width;\n\t\t\tnode->BoundH = cap->FontHeight;\n\t\t}\n\n\t\t/* Next */\n\t\tcap->Next = (CaptionText *)(((char *)captext) + captext->Size);\n\t\tcaptext = cap->Next;\n\t}\n\n\tSet_Font(oldfont);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     AddCaptionNode - Add a caption to the processing list.\n*\n* SYNOPSIS\n*     Node = AddCaptionNode(List, Caption)\n*\n*     CaptionNode *AddCaptionNode(CaptionList *, CaptionText *);\n*\n* FUNCTION\n*     Add a caption the caption processing list.\n*\n* INPUTS\n*     List    - Caption processing list.\n*     Caption - Caption to add to the list.\n*\n* RESULT\n*     Node - Pointer to node, otherwise NULL if error.\n*\n****************************************************************************/\n\nstatic CaptionNode *AddCaptionNode(CaptionList *list, CaptionText *captext)\n{\n\tCaptionNode *node = NULL;\n\n\t/* If this list is not full. */\n\tnode = list->TailPred;\n\n\tif (!(node->Flags & CNF_USED)) {\n\n\t\t/* Remove the node from the tail. */\n\t\tnode->Pred->Succ = node->Succ;\n\t\tlist->TailPred = node->Pred;\n\n\t\tnode->Flags |= CNF_USED;\n\t\tnode->Captext = captext;\n\t\tnode->Char = captext->Text;\n\t\tnode->CurX = captext->Xpos;\n\t\tnode->CurY = captext->Ypos;\n\t\t\n\t\t/* Add the node to the head. */\n\t\tnode->Succ = list->Head;\n\t\tlist->Head = node;\n\t\tnode->Pred = (CaptionNode *)&list->Head;\n\t\tnode->Succ->Pred = node;\n\t}\n\n\treturn (node);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     RemCaptionNode - Remove a caption from the processing list.\n*\n* SYNOPSIS\n*     RemCaptionNode(List, Node)\n*\n*     void RemCaptionNode(CaptionList *, CaptionNode *);\n*\n* FUNCTION\n*     Remove the caption from the processing list. Mark the node as unused\n*     and put it at the tail of the list.\n*\n* INPUTS\n*     List - Caption processing list.\n*     Node - Caption node to remove.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void RemCaptionNode(CaptionList *list, CaptionNode *node)\n{\n\t/* If the nodes successor is null then we are at the tail. */\n\tif (node->Succ != NULL) {\n\n\t\t/* Mark the node as unused. */\n\t\tnode->Flags = 0;\n\n\t\t/* Relink the node to the tail. */\n\t\tnode->Succ->Pred = node->Pred;\n\t\tnode->Pred->Succ = node->Succ;\n\t\tnode->Succ = (CaptionNode *)&list->Tail;\n\t\tnode->Pred = list->TailPred;\n\t\tlist->TailPred->Succ = node;\n\t\tlist->TailPred = node;\n\t}\n}\n\n\n\n"
  },
  {
    "path": "VQ/VQA32/CAPTION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQACAPTION_H\n#define VQACAPTION_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library (32 bit protected mode)\n*\n* FILE\n*     caption.h\n*\n* DESCRIPTION\n*     Text caption definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 26, 1995\n*\n****************************************************************************/\n\n\n/*---------------------------------------------------------------------------\n * STRUCTURES AND RELATED DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* CaptionNode: Node describing a caption to process.\n *\n * Succ    - Pointer to the next node in the list (successor).\n * Pred    - Pointer to the previous node in the list (predecessor).\n * Flags   - Status flags.\n * CapText - Pointer to the CaptionText being processed.\n * Char    - Pointer to current character in the string.\n * CurX    - Current X position.\n * CurY    - Current Y position.\n * BoundW  - Bounding width of text.\n * BoundH  - Bounding height of text.\n */\ntypedef struct _CaptionNode {\n\tstruct _CaptionNode *Succ;\n\tstruct _CaptionNode *Pred;\n\tunsigned short      Flags;\n\tCaptionText         *Captext;\n\tchar                *Char;\n\tunsigned short      CurX;\n\tunsigned short      CurY;\n\tunsigned short      BoundW;\n\tunsigned short      BoundH;\n} CaptionNode;\n\n/* CaptionNode flag definitions. */\n#define CNB_USED 0  /* This node is being used. */\n#define CNF_USED (1<<CNB_USED)\n\n\n/* CaptionList: Double linked list of outstanding captions to process.\n *\n * Head     - Pointer to the first node in the list.\n * Tail     - Always NULL\n * TailPred - Pointer to the last node in the list.\n */\ntypedef struct _CaptionList {\n\tCaptionNode *Head;\n\tCaptionNode *Tail;\n\tCaptionNode *TailPred;\n} CaptionList;\n\n\n/* CaptionInfo:\n *\n * Next   - Pointer to the next caption to be processed.\n * List   - List of pending captions to process.\n * Font   - Font to use for this caption.\n * BoundX - X position of bounding box.\n * BoundY - Y position of bounding box.\n * BoundW - Width of bounding box.\n * BoundH - Height of bounding box.\n * Buffer - Caption chunk buffer.\n */\ntypedef struct _CaptionInfo {\n\tCaptionText    *Next;\n\tCaptionList    List;\n\tvoid           *Font;\n\tchar           FontHeight;\n\tchar           FontWidth;\n\tvoid           *Buffer;\n} CaptionInfo;\n\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\nCaptionInfo *OpenCaptions(void *captions, void *font);\nvoid CloseCaptions(CaptionInfo *cap);\nvoid DoCaptions(CaptionInfo *cap, unsigned long frame);\n\n#endif /* VQACAPTION_H */\n\n"
  },
  {
    "path": "VQ/VQA32/CONFIG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     config.c\n*\n* DESCRIPTION\n*     Player configuration routines.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 10, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_INIConfig     - Initialize VQAConfig structure with INI settings.\n*     VQA_DefaultConfig - Initialize VQAConfig structure with defaults.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n/* Default configuration structure. */\nstatic VQAConfig _defaultconfig = {\n\n\t/* DrawerCallback: This is a function that is called for every frame\n\t * in the movie.\n\t */\n\tNULL,\n\n\t/* EventHandler: This is a function that is called for every event that\n\t * the client requested to be notified about.\n\t */\n\tNULL,\n\n\t/* NotifyFlags: Flags representing the events the client wishes to be\n\t * notified about during playback.\n\t */\n\tNULL,\n\n\t/* Vmode: Video mode to use. */\n\tMCGA,\n\n\t/* VBIBit: Vertical blank bit polarity. */\n\t-1,\n\n\t/* ImageBuf: Pointer to image buffer to draw into. */\n\tNULL,\n\n\t/* ImageWidth, ImageHeight: Width and height dimensions of image buffer.\n\t * A width and height value of -1 tells the player to consider the image\n\t * buffer as having the same dimensions as the frames in the movie.\n\t */\n\t320, 200, /* Image width and height */\n\n\t/* X1, Y1: These are the coordinates to put the movies frame in the image\n\t * buffer. Values of -1 tell the drawer to center the frames in the buffer.\n\t */\n\t-1, -1,\n\n\t/* FrameRate: The rate to load the frames at. A value of -1 tells the\n\t * player to use the framerate of the movie.\n\t */\n\t-1,\n\n\t/* DrawRate: The rate to draw the frames at. A value of -1 tells the\n\t * player to use the framerate of the movie. A value of 0 tells the player\n\t * to use a fixed rate based on the frame size.\n\t */\n\t-1,\n\n\t/* TimerMethod: Timer method to use for playback. */\n\t-1,\n\n\t/* DrawFlags: Various drawing related flags. */\n\t0,\n\n\t/* OptionFlags: Various player options. */\n\tVQAOPTF_AUDIO,\n\n\t/* NumFrameBufs: The number of frame buffers to allocate/use. */\n\t6,\n\n\t/* NumCBBufs: The number of codebook buffers to allocate/use. */\n\t3,\n\n\t/* VocFile: Filename of audio track override. A value of 0 tells the\n\t * player not to override the movies audio track.\n\t */\n\tNULL,\n\n\t/* AudioBuf: Audio buffer to use. A value of 0 tells the player that\n\t * it has to allocate a buffer itself.\n\t */\n\tNULL,\n\n\t/* AudioBufSize: Size of audio buffer to use/allocate. A value of -1\n\t * tells the player to compute the buffer size from the audio\n\t * information in the movie.\n\t */\n\t-1,\n\n\t/* AudioRate: Audio playback rate in samples per second. A value of -1\n\t * tells the player to use the audio rate of the movie.\n\t */\n\t-1,\n\n\t/* Volume: Volume level to playback audio track. */\n\t0x00FF,\n\n\t/* HMIBufSize: Size of HMIs internal buffer. */\n\t2048L,\n\n\t/* DigiHandle: Handle to an initialized HMI sound driver. A value of -1\n\t * tells the player it must initialize the HMI sound driver itself.\n\t */\n\t-1,\n\n\t/* DigiCard: HMI ID of audio card to use. A value of 0 tells the player\n\t * not to use any card. A value of -1 tells the player to autodetect the\n\t * card in the system.\n\t */\n\t-1,\n\n\t/* DigiPort: Port address of the sound card. A value of -1 tells the player\n\t * to autodetect this address.\n\t */\n\t-1,\n\n\t/* DigiIRQ: Interrupt number of sound card. A value of -1 tells the player\n\t * to autodetect the interrupt used by the card.\n\t */\n\t-1,\n\n\t/* DigiDMA: DMA channel of the sound card. A value of -1 tells the player\n\t * to autodetect the channel used by the card.\n \t */\n\t-1,\n\n\t/* Language: Prefered language. */\n\t0,\n\n\t/* CaptionFont: Caption text font. */\n\tNULL,\n\n\t/* EVAFont: EVA text font. */\n\tNULL,\n};\n\n/* Supported video modes. */\n#if(VQAVIDEO_ON)\nenum VMTAGS {\n\tVMTAG_NONE = 0,\n\n\t#if(VQAMCGA_ON)\n\tVMTAG_MCGA,\n\tVMTAG_MCGA_BUF,\n\t#endif\n\n\t#if(VQAXMODE_ON)\n\tVMTAG_XMODE320X200,\n\tVMTAG_XMODE320X200_BUF,\n\tVMTAG_XMODE320X200_VRAM,\n\tVMTAG_XMODE320X240,\n\tVMTAG_XMODE320X240_BUF,\n\tVMTAG_XMODE320X240_VRAM,\n\t#endif\n\n\t#if(VQAVESA_ON)\n\tVMTAG_VESA640X480_BUF,\n\tVMTAG_VESA640X480_X2,\n\tVMTAG_VESA320X200,\n\tVMTAG_VESA320X200_BUF,\n\t#endif\n};\n\ntypedef struct _VideoModeTag {\n\tchar const *token;\n\tlong       id;\n} VideoModeTag;\n\nVideoModeTag VideoModeTags[] = {\n\t{\"NONE\",VMTAG_NONE},\n\n\t#if(VQAMCGA_ON)\n\t{\"MCGA\",    VMTAG_MCGA},\n\t{\"MCGA_BUF\",VMTAG_MCGA_BUF},\n\t#endif /* VQAMCGA_ON */\n\n\t#if(VQAXMODE_ON)\n\t{\"XMODE_320X200\",     VMTAG_XMODE320X200},\n\t{\"XMODE_320X200_BUF\", VMTAG_XMODE320X200_BUF},\n\t{\"XMODE_320X200_VRAM\",VMTAG_XMODE320X200_VRAM},\n\t{\"XMODE_320X240\",     VMTAG_XMODE320X240},\n\t{\"XMODE_320X240_BUF\", VMTAG_XMODE320X240_BUF},\n\t{\"XMODE_320X240_VRAM\",VMTAG_XMODE320X240_VRAM},\n\t#endif /* VQAXMODE_ON */\n\n\t#if(VQAVESA_ON)\n\t{\"VESA_640X480_BUF\",VMTAG_VESA640X480_BUF},\n\t{\"VESA_640X480_X2\", VMTAG_VESA640X480_X2},\n\t{\"VESA_320X200\",    VMTAG_VESA320X200},\n\t{\"VESA_320X200_BUF\",VMTAG_VESA320X200_BUF},\n\t#endif /* VQAVESA_ON */\n\n\t{NULL, NULL}\n};\n#endif /* VQAVIDEO_ON */\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_INIConfig - Initialize VQAConfig structure with INI settings.\n*\n* SYNOPSIS\n*     VQA_INIConfig(Config)\n*\n*     void VQA_INIConfig(VQAConfig *);\n*\n* FUNCTION\n*     Initializes the configuration structure from the player INI file.\n*\n* INPUTS\n*     Config - Pointer to VQAConfig structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_INIConfig(VQAConfig *config)\n{\n\tchar *ininame;\n\tchar buf[80];\n\tlong i;\n\n\t/* Set all Config entries to 0. */\n\tmemset(config, 0, sizeof(VQAConfig));\n\n\t/* Retrieve player INI filename from an enviroment variable if\n\t * it is provided.\n\t */\n\tif ((ininame = getenv(\"VQACFG\")) == NULL) {\n\t\tininame = \"PLAYER.INI\";\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * VIDEO MODE AND DRAW FLAGS\n\t *-----------------------------------------------------------------------*/\n\t#if(VQAVIDEO_ON)\n\t/* Get video mode from INI */\n\tGetINIString(\"Player\", \"PlayerMode\", \"MCGA\", buf, 80, ininame);\n\n\t/* Search supported modes for a match. */\n\ti = 0;\n\n\twhile (VideoModeTags[i].token != NULL) {\n\t\tif (stricmp(buf, VideoModeTags[i].token) == 0) {\n\t\t\tbreak;\n\t\t}\n\t\ti++;\n\t}\n\n\t/* Setup for requested mode */\n\tswitch (VideoModeTags[i].id) {\n\n\t\t/* MCGA direct */\n\t\t#if(VQAMONO_ON)\n\t\tcase VMTAG_MCGA:\n\t\t\tconfig->Vmode = MCGA;\n\t\t\tbreak;\n\n\t\t/* MCGA buffered */\n\t\tcase VMTAG_MCGA_BUF:\n\t\t\tconfig->Vmode = MCGA;\n\t\t\tconfig->DrawFlags |= VQACFGF_BUFFER;\n\t\t\tbreak;\n\t\t#endif /* VQAMCGA_ON */\n\n\t\t/* XMODE direct (320x200) */\n\t\t#if(VQAXMODE_ON)\n\t\tcase VMTAG_XMODE320X200:\n\t\t\tconfig->Vmode = XMODE_320X200;\n\t\t\tbreak;\n\n\t\t/* XMODE buffered (320x200) */\n\t\tcase VMTAG_XMODE320X200_BUF:\n\t\t\tconfig->Vmode = XMODE_320X200;\n\t\t\tconfig->DrawFlags |= VQACFGF_BUFFER;\n\t\t\tbreak;\n\n\t\t/* XMODE VRAM codebook (320x200) */\n\t\tcase VMTAG_XMODE320X200_VRAM:\n\t\t\tconfig->Vmode = XMODE_320X200;\n\t\t\tconfig->DrawFlags |= VQACFGF_VRAMCB;\n\t\t\tbreak;\n\n\t\t/* XMODE direct (320x240) */\n\t\tcase VMTAG_XMODE320X240:\n\t\t\tconfig->Vmode = XMODE_320X240;\n\t\t\tbreak;\n\n\t\t/* XMODE buffered (320x240) */\n\t\tcase VMTAG_XMODE320X240_BUF:\n\t\t\tconfig->Vmode = XMODE_320X240;\n\t\t\tconfig->DrawFlags |= VQACFGF_BUFFER;\n\t\t\tbreak;\n\n\t\t/* XMODE VRAM codebook (320x240) */\n\t\tcase VMTAG_XMODE320X240_VRAM:\n\t\t\tconfig->Vmode = XMODE_320X240;\n\t\t\tconfig->DrawFlags |= VQACFGF_VRAMCB;\n\t\t\tbreak;\n\t\t#endif /* VQAXMODE_ON */\n\n\t\t/* VESA buffered (640x480_256) */\n\t\t#if(VQAVESA_ON)\n\t\tcase VMTAG_VESA640X480_BUF:\n\t\t\tconfig->Vmode = VESA_640X480_256;\n\t\t\tconfig->DrawFlags |= VQACFGF_BUFFER;\n\t\t\tbreak;\n\n\t\t/* VESA buffered scaled (640x480_256) */\n\t\tcase VMTAG_VESA640X480_X2:\n\t\t\tconfig->Vmode = VESA_640X480_256;\n\t\t\tconfig->DrawFlags |= (VQACFGF_BUFFER|VQACFGF_SCALEX2);\n\t\t\tbreak;\n\n\t\t/* VESA direct (320x200_32k) */\n\t\tcase VMTAG_VESA320X200:\n\t\t\tconfig->Vmode = VESA_320X200_32K_1;\n\t\t\tbreak;\n\n\t\t/* VESA buffered (320x200_32k) */\n\t\tcase VMTAG_VESA320X200_BUF:\n\t\t\tconfig->Vmode = VESA_320X200_32K_1;\n\t\t\tconfig->DrawFlags |= VQACFGF_BUFFER;\n\t\t\tbreak;\n\t\t#endif /* VQAVESA_ON */\n\n\t\t/* Default to MCGA direct */\n\t\tVMTAG_NONE:\n\t\tdefault:\n\t\t\tconfig->Vmode = MCGA;\n\t\t\tbreak;\n\t}\n\t#endif /* VQAVIDEO_ON */\n\n\t/* Get framerate and drawrate. */\n\tGetINIString(\"Player\", \"FrameRate\", \"-1\", buf, 80, ininame);\n\tconfig->FrameRate = atoi(buf);\n\n\tGetINIString(\"Player\", \"DrawRate\", \"Variable\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"Variable\")) {\n\t\tconfig->DrawRate = -1;\n\t} else {\n\t\tconfig->DrawRate = 0;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * AUDIO SETTINGS\t \n\t *-----------------------------------------------------------------------*/\n\tGetINIString(\"Player\", \"AudioRate\", \"-1\", buf, 80, ininame);\n\tconfig->AudioRate = atoi(buf);\n\n\t/* OptionFlags */\n\tGetINIString(\"Player\", \"SoundEnabled\", \"True\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"True\") || !stricmp(buf, \"1\")) {\n\t\tconfig->OptionFlags |= VQAOPTF_AUDIO;\n\t} else {\n\t\tconfig->OptionFlags &= (~VQAOPTF_AUDIO);\n\t}\n\n\t/* Default audio settings. */\n\tconfig->AudioBufSize = 32768U;\n\tconfig->HMIBufSize = 2048;\n\tconfig->DigiHandle = -1;\n\tconfig->Volume = 0x00FF;\n\tconfig->DigiCard = 0xFFFF;\n\tconfig->DigiPort = -1;\n\tconfig->DigiIRQ = -1;\n\tconfig->DigiDMA = -1;\n\n\t/* Configure sound hardware */\n\tGetINIString(\"Player\", \"Port\", \"-1\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"-1\")) {\n\t\tconfig->DigiPort = -1;\n\t} else {\n\t\tsscanf(buf, \"%x\", &config->DigiPort);\n\t}\n\n\tGetINIString(\"Player\", \"IRQ\", \"-1\", buf, 80, ininame);\n\tconfig->DigiIRQ = atoi(buf);\n\tGetINIString(\"Player\", \"DMA\", \"-1\", buf, 80, ininame);\n\tconfig->DigiDMA = atoi(buf);\n\n\t/*-------------------------------------------------------------------------\n\t * GENERAL OPTIONS\n\t *-----------------------------------------------------------------------*/\n\n\t/* Enable/Disable single stepping */ \n\tGetINIString(\"Player\", \"SingleStep\", \"False\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"True\") || !stricmp(buf, \"1\")) {\n\t\tconfig->OptionFlags |= VQAOPTF_STEP;\n\t\tconfig->DrawFlags |= VQACFGF_NOSKIP;\n\t} else {\n\t\tconfig->OptionFlags &= (~VQAOPTF_STEP);\n\t}\n\n\t/* Enable/Disable Slowpalette */\n\tGetINIString(\"Player\", \"SlowPalette\", \"False\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"True\") || !stricmp(buf, \"1\")) {\n\t\tconfig->OptionFlags |= VQAOPTF_SLOWPAL;\n\t} else {\n\t\tconfig->OptionFlags &= (~VQAOPTF_SLOWPAL);\n\t}\n\n\t/* Enable/Disable monochrome display */\n\tGetINIString(\"Player\", \"MonoOutput\", \"False\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"True\") || !stricmp(buf, \"1\")) {\n\t\tconfig->OptionFlags |= VQAOPTF_MONO;\n\t} else {\n\t\tconfig->OptionFlags &= (~VQAOPTF_MONO);\n\t}\n\n\t/* Frame and codebook buffers */\n\tconfig->NumFrameBufs = 6;\n\tconfig->NumCBBufs = 3;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_DefaultConfig - Initialize VQAConfig structure with defaults.\n*\n* SYNOPSIS\n*     VQA_DefaultConfig(Config);\n*\n*     void VQA_DefaultConfig(VQAConfig *);\n*\n* FUNCTION\n*     Initialize configuration with default settings.\n*\n* INPUTS\n*     Config - Pointer to VQA configuration structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_DefaultConfig(VQAConfig *config)\n{\n\tmemcpy(config, &_defaultconfig, sizeof(VQAConfig));\n}\n\n\n\n\n"
  },
  {
    "path": "VQ/VQA32/DRAWER.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQAPlay32 library. (32-Bit protected mode)\n*\n* FILE\n*     drawer.c\n*\n* DESCRIPTION\n*     Frame drawing and page flip control.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     February 8, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_Configure_Drawer - Configure the drawer routines.\n*\n* PRIVATE\n*     Select_Frame             - Selects frame to draw and preforms frame\n*                                skip.\n*     Prepare_Frame            - Process/Decompress frame information.\n*     DrawFrame_Xmode          - Draws a frame directly to Xmode screen.\n*     DrawFrame_XmodeBuf       - Draws a frame in Xmode format to a buffer.\n*     DrawFrame_XmodeVRAM      - Draws a frame in Xmode with resident\n*                                Codebook.\n*     PageFlip_Xmode           - Page flip Xmode display.\n*     DrawFrame_MCGA           - Draws a frame directly to MCGA screen.\n*     PageFlip_MCGA            - Page flip MCGA display.\n*     DrawFrame_MCGABuf        - Draws a frame in MCGA format to a buffer.\n*     PageFlip_MCGABuf         - Page flip a buffered MCGA display.\n*     DrawFrame_VESA640        - Draws a frame in VESA640 format.\n*     DrawFrame_VESA320_32K    - Draws a frame to VESA320_32K screen.\n*     DrawFrame_VESA320_32KBuf - Draws a frame in VESA320_32K format to a\n*                                buffer.\n*     PageFlip_VESA            - Page flip VESA display.\n*     DrawFrame_Buffer         - Draw a frame to a buffer.\n*     PageFlip_Nop             - Do nothing page flip.\n*     UnVQ_Nop                 - Do nothing UnVQ.\n*     Mask_Rect                - Sets non-drawable rectangle in image.\n*     Mask_Pointers            - Mask vector pointer that are in the mask\n*                                rectangle.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <malloc.h>\n#include <conio.h>\n#include <dos.h>\n#include <mem.h>\n#include \"vq.h\"\n#include \"unvq.h\"\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\nstatic long Select_Frame(VQAHandleP *vqap);\nstatic void Prepare_Frame(VQAData *vqabuf);\n\n#if(VQAMCGA_ON)\nstatic long DrawFrame_MCGABuf(VQAHandle *vqa);\nstatic void PageFlip_MCGABuf(VQAHandle *vqa);\nstatic long DrawFrame_MCGA(VQAHandle *vqa);\nstatic void PageFlip_MCGA(VQAHandle *vqa);\n#endif /* VQAMCGA_ON */\n\n#if(VQAXMODE_ON)\nstatic long DrawFrame_XmodeBuf(VQAHandle *vqa);\nstatic long DrawFrame_Xmode(VQAHandle *vqa);\nstatic long DrawFrame_XmodeVRAM(VQAHandle *vqa);\nstatic void PageFlip_Xmode(VQAHandle *vqabuf);\n#endif /* VQAXMODE_ON */\n\n#if(VQAVESA_ON)\nstatic long DrawFrame_VESA640(VQAHandle *vqa);\nstatic long DrawFrame_VESA320_32K(VQAHandle *vqa);\nstatic long DrawFrame_VESA320_32KBuf(VQAHandle *vqa);\nstatic void PageFlip_VESA(VQAHandle *vqabuf);\n#endif /* VQAVESA_ON */\n\nstatic long DrawFrame_Buffer(VQAHandle *vqa);\nstatic void PageFlip_Nop(VQAHandle *vqa);\n\n#ifndef PHARLAP_TNT\nstatic void cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n#else\nstatic void cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n#endif\n\n#if(0)\nstatic void Mask_Rect(VQAHandle *vqa, unsigned long x1, unsigned long y1,\n\t\tunsigned long x2, unsigned long y2);\nstatic void Mask_Pointers(VQAData *vqabuf);\n#endif\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Configure_Drawer - Configure the drawer routines.\n*\n* SYNOPSIS\n*     VQA_Configure_Drawer(VQA)\n*\n*     void VQA_Configure_Drawer(VQAHandleP *);\n*\n* FUNCTION\n*     Configure the drawing system for the current movie and configuration\n*     options.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Configure_Drawer(VQAHandleP *vqap)\n{\n\tVQAData   *vqabuf;\n\tVQAConfig *config;\n\tVQAHeader *header;\n\tVQADrawer *drawer;\n\tlong      origin;\n\tlong      blkdim;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\theader = &vqap->Header;\n\tconfig = &vqap->Config;\n\torigin = (config->DrawFlags & VQACFGF_ORIGIN);\n\n\t/*-------------------------------------------------------------------------\n\t * SET THE DRAW POSITION OF THE MOVIE.\n\t *\n\t * X1 = -1 -- Center image of the X axis, otherwise use X1 value.\n\t * Y1 = -1 -- Center image of the Y axis, otherwise use Y1 value.\n\t *-----------------------------------------------------------------------*/\n\tif ((config->X1 == -1) && (config->Y1 == -1)) {\n\n\t\t#if(VQAVIDEO_ON)\n\t\tdrawer->X1 = ((drawer->Display->XRes - header->image_width) / 2);\n\t\tdrawer->Y1 = ((drawer->Display->YRes - header->image_height) / 2);\n\t\t#else  /* VQAVIDEO_ON */\n\t\tdrawer->X1 = ((drawer->ImageWidth - header->ImageWidth) / 2);\n\t\tdrawer->Y1 = ((drawer->ImageHeight - header->ImageHeight) / 2);\n\t\t#endif /* VQAVIDEO_ON */\n\n\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\tdrawer->Y2 = ((drawer->Y1 + header->ImageHeight) - 1);\n\t} else {\n\t\tswitch (origin) {\n\t\t\tdefault:\n\t\t\tcase VQACFGF_TOPLEFT:\n\t\t\t\tdrawer->X1 = config->X1;\n\t\t\t\tdrawer->Y1 = config->Y1;\n\t\t\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\t\t\tdrawer->Y2 = ((drawer->Y1 + header->ImageHeight) - 1);\n\t\t\t\tbreak;\n\n\t\t\tcase VQACFGF_BOTLEFT:\n\t\t\t\tdrawer->X1 = config->X1;\n\t\t\t\tdrawer->Y1 = (drawer->ImageHeight - config->Y1);\n\t\t\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\t\t\tdrawer->Y2 = ((drawer->Y2 - header->ImageHeight) - 1);\n\t\t\t\tbreak;\n\n\t\t\tcase VQACFGF_BOTRIGHT:\n\t\t\t\tdrawer->X1 = (drawer->ImageWidth - config->X1);\n\t\t\t\tdrawer->Y1 = (drawer->ImageHeight - config->Y1);\n\t\t\t\tdrawer->X2 = (drawer->X1 - header->ImageWidth);\n\t\t\t\tdrawer->Y2 = (drawer->Y1 - header->ImageHeight);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE UNVQ ROUTINE FOR THE SPECIFIED VIDEO MODE AND BLOCK SIZE.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Pre-compute commonly used values for speed. */\n\tdrawer->BlocksPerRow = header->ImageWidth / header->BlockWidth;\n\tdrawer->NumRows = header->ImageHeight / header->BlockHeight;\n\tdrawer->NumBlocks = drawer->BlocksPerRow * drawer->NumRows;\n\tblkdim = BLOCK_DIM(header->BlockWidth, header->BlockHeight);\n\n\t/* Initialize draw routine vectors to a NOP routine in order to prevent\n\t * a crash.\n\t */\n\tvqabuf->UnVQ = UnVQ_Nop;\n\tvqabuf->Page_Flip = PageFlip_Nop;\n\n\t/* If the client specifies buffering then go ahead an set the unvq\n\t * vector. All of the buffered modes use the same unvq routines.\n\t */\n\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\tswitch (blkdim) {\n\t\t\t#if(VQABLOCK_2X2)\n\t\t\tcase BLOCK_2X2:\n\t\t\t\tvqabuf->UnVQ = UnVQ_2x2;\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\t#if(VQABLOCK_2X3)\n\t\t\tcase BLOCK_2X3:\n\t\t\t\tvqabuf->UnVQ = UnVQ_2x3;\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\t#if(VQABLOCK_4X2)\n\t\t\tcase BLOCK_4X2:\n\t\t\t\tvqabuf->UnVQ = UnVQ_4x2;\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\t#if(VQABLOCK_4X4)\n\t\t\tcase BLOCK_4X4:\n\t\t\t\tvqabuf->UnVQ = UnVQ_4x4;\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n \t\t}\n \t}\n\n\t/* Initialize the draw vectors for the specified video mode. */\n\tswitch (config->Vmode) {\n\n\t\t/* MCGA */\n\t\t#if(VQAMCGA_ON)\n\t\tcase MCGA:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_MCGABuf;\n\t\t\t\tvqabuf->Page_Flip = PageFlip_MCGABuf;\n\t\t\t} else {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_MCGA;\n\t\t\t\tvqabuf->Page_Flip = PageFlip_MCGA;\n\n\t\t\t\t/* MCGA uses the same unvq routines that are used for unvqing\n\t\t\t\t * to a buffer because MCGA mode is just another buffer. However,\n\t\t\t\t * instead of drawing to an allocated RAM buffer we are drawing\n\t\t\t\t * directly to the VRAM video buffer.\n\t\t\t\t */\n\t\t\t\tswitch (blkdim) {\n\t\t\t\t\t#if(VQABLOCK_2X2)\n\t\t\t\t\tcase BLOCK_2X2:\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_2x2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\n\t\t\t\t\t#if(VQABLOCK_2X3)\n\t\t\t\t\tcase BLOCK_2X3:\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_2x3;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\n\t\t\t\t\t#if(VQABLOCK_4X2)\n\t\t\t\t\tcase BLOCK_4X2:\n\t\t\t\t\t\t#if(0)\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2;\n\t\t\t\t\t\t#else\n\t\t\t\t\t\tif (config->DrawFlags & VQACFGF_WOOFER) {\n\t\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2_Woofer;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t#endif\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\n\t\t\t\t\t#if(VQABLOCK_4X4)\n\t\t\t\t\tcase BLOCK_4X4:\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x4;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Pre-compute the draw offset for speed. */\n\t\t\tdrawer->ScreenOffset = ((320 * drawer->Y1) + drawer->X1);\n\t\t\tbreak;\n\t\t#endif /* VQAMCGA_ON */\n\n\t\t/* XMODE */\n\t\t#if(VQAXMODE_ON)\n\t\tcase XMODE_320X200:\n\t\tcase XMODE_320X240:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_XmodeBuf;\n\t\t\t\tvqabuf->Page_Flip = PageFlip_Xmode;\n\t\t\t} else {\n\t\t\t\tvqabuf->Page_Flip = PageFlip_Xmode;\n\n\t\t\t\tif (config->DrawFlags & VQACFGF_VRAMCB) {\n\t\t\t\t\tvqabuf->Draw_Frame = DrawFrame_XmodeVRAM;\n\n\t\t\t\t\tswitch (blkdim) {\n\t\t\t\t\t\t#if(VQABLOCK_4X2)\n\t\t\t\t\t\tcase BLOCK_4X2:\n\t\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2_XmodeCB;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t#endif /* VQABLOCK_4X2 */\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tvqabuf->Draw_Frame = DrawFrame_Xmode;\n\n\t\t\t\t\tswitch (blkdim) {\n\t\t\t\t\t\t#if(VQABLOCK_4X2)\n\t\t\t\t\t\tcase BLOCK_4X2:\n\t\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2_Xmode;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t#endif /* VQABLOCK_4X2 */\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Pre-compute the draw offset for speed. */\n\t\t\tdrawer->ScreenOffset = (((320 / 4) * drawer->Y1) + (drawer->X1 / 4));\n\t\t\tbreak;\n\t\t#endif /* VQAXMODE_ON */\n\n\t\t/* VESA */\n\t\t#if(VQAVESA_ON)\n\n\t\t/* Currently this is a buffered mode, but should be optimized for\n\t\t * for screen direct.\n\t\t */\n\t\tcase VESA_640X480_256:\n\t\t\tvqabuf->Draw_Frame = DrawFrame_VESA640;\n\t\t\tvqabuf->Page_Flip = PageFlip_VESA;\n\t\t\tbreak;\n\n\t\tcase VESA_320X200_32K_1:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_VESA320_32KBuf;\n\t\t\t} else {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_VESA320_32K;\n\n\t\t\t\tswitch (blkdim) {\n\t\t\t\t\t#if(VQABLOCK_4X2)\n\t\t\t\t\tcase BLOCK_4X2:\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2_VESA320_32K;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t#endif /* VQAVESA_ON */\n\n\t\t/* Purely buffered (Video refresh is up to the client. */\n\t\tdefault:\n\t\t\tvqabuf->Draw_Frame = DrawFrame_Buffer;\n\n\t\t\t/* Pre-compute the draw offset for speed. */\n\t\t\tdrawer->ScreenOffset = ((drawer->ImageWidth * drawer->Y1)+drawer->X1);\n\t\t\tbreak;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Select_Frame - Selects frame to draw and preforms frame skip.\n*\n* SYNOPSIS\n*     Error = Select_Frame(VQA)\n*\n*     long Select_Frame(VQAHandleP *);\n*\n* FUNCTION\n*     Select a frame to draw. This is were the frame skipping/delay is\n*     performed.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Select_Frame(VQAHandleP *vqap)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAConfig    *config;\n\tVQAFrameNode *curframe;\n\tlong         curtime;\n\tlong         desiredframe;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tconfig = &vqap->Config;\n\tvqabuf = vqap->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = drawer->CurFrame;\n\n\t/* Make sure the current frame is drawable. If the frame is not ready\n\t * then we must wait for the loader to catch up.\n\t */\n\tif ((curframe->Flags & VQAFRMF_LOADED) == 0) {\n\t\tdrawer->WaitsOnLoader++;\n\t\treturn (VQAERR_NOBUFFER);\n\t}\n\n\t/* If single stepping then return with the next frame.*/\n\tif (config->OptionFlags & VQAOPTF_STEP) {\n\t\tdrawer->LastFrame = curframe->FrameNum;\n\t\treturn (0);\n\t}\n\n\t/* Find the frame # we should play (rounded to nearest frame): */\n\tcurtime = VQA_GetTime();\n\tdesiredframe = ((curtime * config->FrameRate) / VQA_TIMETICKS);\n\n\t#if(VQAMONO_ON)\n\tdrawer->DesiredFrame = desiredframe;\n\t#endif\n\n\t/* Handle the cases where the player is going so fast that it's not time \n\t * to draw this frame yet.\n\t *\n\t * - If the Drawer is using a slower frame rate than the Loader, use a\n\t *   delta-time-based wait; otherwise, use the frame number as the wait.\n\t */\n\tif (config->DrawRate != config->FrameRate) {\n\t\tif (curtime - drawer->LastTime < (VQA_TIMETICKS / config->DrawRate)) {\n\t\t\treturn (VQAERR_NOT_TIME);\n\t\t}\n\t} else {\n\t\tif (curframe->FrameNum > desiredframe) {\n\t\t\treturn (VQAERR_NOT_TIME);\n\t\t}\n\t}\n\n\t/* Make sure we draw at least 5 frames per second */\n\tif ((curframe->FrameNum - drawer->LastFrame) >= (config->FrameRate / 5)) {\n\t\tdrawer->LastFrame = curframe->FrameNum;\n\t\treturn (0);\n\t}\n\n\t/* If frame skipping is disabled then draw every frame. */\n\tif (config->DrawFlags & VQACFGF_NOSKIP) {\n\t\tdrawer->LastFrame = curframe->FrameNum;\n\t\treturn (0);\n\t}\n\n\t/* Handle the case where the player is going too slow, so we have to skip \n\t * some frames:\n\t *\n\t * - If this is a Key Frame, draw it\n\t * - If this frame's # is less than what we're supposed to draw, skip it\n\t *   (Because the 1st 'desiredframe' will be 0, FrameNum MUST be typecast \n\t *   to signed WORD for the comparison; otherwise, the comparison uses \n\t *   UWORDs, and the first frame is always skipped.)\n\t * - If this is a palette-set frame, set the palette before skipping it\n\t * - Loop until we get the frame we need, or there's no frames available\n\t */\n\twhile (1) {\n\n\t\t/* No frame available; return */\n\t\tif ((curframe->Flags & VQAFRMF_LOADED) == 0) {\n\t\t\treturn (VQAERR_NOBUFFER);\n\t\t}\n\n\t\t/* Force drawing of a Key Frame */\n\t\tif (curframe->Flags & VQAFRMF_KEY) {\n\t\t\tbreak;\n\t\t}\n\n\t\t/* Skip the frame */\n\t\tif (curframe->FrameNum < desiredframe) {\n\n\t\t\t/* Handle a palette in a skipped frame:\n\t\t\t *\n\t\t\t * - Stash the palette in Drawer.Palette_24\n\t\t\t * - Set the Drawer.Flags VQADRWF_SETPAL bit, to tell the page-flip\n\t\t\t *   routines that this palette must be set\n\t\t\t */\n\t\t\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\n\t\t\t\t/* Un-LCW if needed */\n\t\t\t\tif (curframe->Flags & VQAFRMF_PALCOMP) {\n\t\t\t\t\tcurframe->PaletteSize = LCW_Uncompress((char *)curframe->Palette\n\t\t\t\t\t\t\t+ curframe->PalOffset, (char *)curframe->Palette,\n\t\t\t\t\t\t\tvqabuf->Max_Pal_Size);\n\n\t\t\t\t\tcurframe->Flags &= ~VQAFRMF_PALCOMP;\n\t\t\t\t}\n\n\t\t\t\t/* Stash the palette */\n\t\t\t\tmemcpy(drawer->Palette_24, curframe->Palette, curframe->PaletteSize);\n\t\t\t\tdrawer->CurPalSize = curframe->PaletteSize;\n\t\t\t\tdrawer->Flags |= VQADRWF_SETPAL;\n\t\t\t}\n\n\t\t\t/* Invoke callback with NULL screen ptr */\n\t\t\tif (config->DrawerCallback != NULL) {\n\t\t\t\tif (config->DrawerCallback(NULL, curframe->FrameNum)) {\n\t\t\t\t\treturn VQAERR_READ;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Skip the frame */\n\t\t\tcurframe->Flags = 0L;\n\t\t\tcurframe = curframe->Next;\n\t\t\tdrawer->CurFrame = curframe;\n\t\t\tdrawer->NumSkipped++;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tdrawer->LastFrame = curframe->FrameNum;\n\tdrawer->LastTime = curtime;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Prepare_Frame - Process/Decompress frame information.\n*\n* SYNOPSIS\n*     Prepare_Frame(VQAData)\n*\n*     void Prepare_Frame(VQAData *);\n*\n* FUNCTION\n*     Decompress and preprocess the various frame elements (codebook,\n*     pointers, palette, etc...)\n*\n* INPUTS\n*     VQAData - Pointer to VQAData structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Prepare_Frame(VQAData *vqabuf)\n{\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tVQACBNode    *codebook;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = drawer->CurFrame;\n\tcodebook = curframe->Codebook;\n\n\t/* Decompress the codebook, if needed */\n\tif (codebook->Flags & VQACBF_CBCOMP) {\n\n\t\t/* Decompress the codebook. */\n\t\tLCW_Uncompress((char *)codebook->Buffer + codebook->CBOffset,\n\t\t\t\t(char *)codebook->Buffer, vqabuf->Max_CB_Size);\n\n\t\t/* Mark as uncompressed for the next time we use it */\n\t\tcodebook->Flags &= (~VQACBF_CBCOMP);\n\t}\n\n\t/* Decompress the palette, if needed */\n\tif (curframe->Flags & VQAFRMF_PALCOMP) {\n\t\tcurframe->PaletteSize = LCW_Uncompress((char *)curframe->Palette +\n\t\t\t\tcurframe->PalOffset,(char *)curframe->Palette,vqabuf->Max_Pal_Size);\n\n\t\t/* Mark as uncompressed */\n\t\tcurframe->Flags &= ~VQAFRMF_PALCOMP;\n\t}\n\n\t/* Decompress the pointer data, if needed */\n\tif (curframe->Flags & VQAFRMF_PTRCOMP) {\n\t\tLCW_Uncompress((char *)curframe->Pointers + curframe->PtrOffset,\n\t\t\t\t(char *)curframe->Pointers, vqabuf->Max_Ptr_Size);\n\n\t\t/* Mark as uncompressed */\n\t\tcurframe->Flags &= ~VQAFRMF_PTRCOMP;\n\t}\n\n\t/* Mask the pointers */\n\t#if(0)\n\tMask_Pointers(vqabuf);\n\t#endif\n}\n\n\n#if(VQAXMODE_ON)\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_Xmode - Draws a frame in Xmode format (Screen direct).\n*\n* SYNOPSIS\n*     Error = DrawFrame_Xmode(VQA)\n*\n*     long DrawFrame_Xmode(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Skip frames\n*       - UnLCW frame\n*       - Un-VQ into video RAM\n*       - Wait on Update_Enabled\n*       - Set the Flipper's CurFrame\n*       - Set Update_Enabled\n*       - Go to next frame\n*       - User_Update:\n*         Flip X-Page\n*         Set Palette from Flipper.CurFrame\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the correct spot on\n*     the Xmode screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_Xmode(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *scrn;\n\tlong          rc;\n\n\t/* Dereference data members for quick access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n \t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* Dereference current frame for quicker access */\n\t\tcurframe = drawer->CurFrame;\n\n\t\t/* Un-VQ the image */\n\t\tscrn = GetXHidPage();\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tscrn + drawer->ScreenOffset, drawer->BlocksPerRow,\n\t\t\t\tdrawer->NumRows, 320);\n\n\t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tconfig->DrawerCallback(scrn, curframe->FrameNum);\n\t\t}\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access */\n\tcurframe = drawer->CurFrame;\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_XmodeBuf - Draws a frame in Xmode format to a buffer.\n*\n* SYNOPSIS\n*     Error = DrawFrame_XmodeBuf(VQA)\n*\n*     long DrawFrame_XmodeBuf(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Skip frames\n*       - UnLCW frame\n*       - Un-VQ into ImageBuf\n*       - Copy ImageBuf to video RAM\n*       - Wait on Update_Enabled\n*       - Set the Flipper's CurFrame\n*       - Set Update_Enabled\n*       - Go to next frame\n*\t      - User_Update:\n*         Flip X-Page\n*         Set Palette from Flipper.CurFrame\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the upper-left\n*     corner of ImageBuf, then copying ImageBuf into the correct part of the\n*     Xmode screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_XmodeBuf(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAHeader     *header;\n\tVQAConfig     *config;\n\tunsigned char *scrn;\n\tlong          rc;\n\n\t/* Dereference data members for quicker access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\theader = &((VQAHandleP *)vqa)->Header;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* Dereference current frame for quicker access. */\n\t\tcurframe = drawer->CurFrame;\n\n\t\t/* Un-VQ the image */\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tdrawer->ImageBuf, drawer->BlocksPerRow, drawer->NumRows,\n\t\t\t\theader->ImageWidth);\n\n\t\t/* Copy the buffer */\n\t\tscrn = GetXHidPage();\n\n\t\tif ((header->ImageWidth < 320) || (header->ImageHeight < 200)) {\n\t\t\tXmode_Blit(drawer->ImageBuf, scrn + drawer->ScreenOffset,\n\t\t\t\t\theader->ImageWidth, header->ImageHeight);\n\t\t} else {\n\t\t\tXmode_BufferCopy_320x200(drawer->ImageBuf,scrn + drawer->ScreenOffset);\n\t\t}\n\n\t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tconfig->DrawerCallback(scrn, curframe->FrameNum);\n\t\t}\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_XmodeVRAM - Draws a frame in Xmode with resident Codebook.\n*\n* SYNOPSIS\n*     Error = DrawFrame_XmodeVRAM(VQA)\n*\n*     long DrawFrame_XmodeVRAM(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Download Codebook if it isn't already (do this before skipping\n*         frames, so Select_Frame will smooth out the delay)\n*       - Skip frames\n*       - UnLCW frame\n*       - Convert Pointers to VRAM format\n*       - Un-VQ by copying codebook blocks within VRAM\n*       - Wait on Update_Enabled\n*       - Set the Flipper's CurFrame\n*       - Set Update_Enabled\n*       - Go to next frame\n*       - User_Update:\n*         Flip X-Page\n*         Set Palette from Flipper.CurFrame\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the correct spot on\n*     the Xmode screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_XmodeVRAM(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *scrn;\n\tlong          rc;\n\n\t/* Dereference data members for quicker access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* Dereference current frame for quicker access. */\n\t\tcurframe = drawer->CurFrame;\n\n\t\t/* Download codebook to VRAM */\n\t\tif ((curframe->Codebook->Flags & VQACBF_DOWNLOADED) == 0) {\n\t\t\tUpload_4x2CB(curframe->Codebook->Buffer,\n\t\t\t\t\t((VQAHandleP *)vqa)->Header.CBentries\n\t\t\t\t\t+ ((VQAHandleP *)vqa)->Header.Num1Colors);\n\n\t\t\tcurframe->Codebook->Flags |= VQACBF_DOWNLOADED;\n\t\t}\n\n\t\t/* Convert pointers to VRAM format */\n\t\tXlatePointers(curframe->Pointers, drawer->NumBlocks);\n\n\t\t/* Un-VQ the image */\n\t\tscrn = GetXHidPage();\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tscrn + drawer->ScreenOffset, drawer->BlocksPerRow,\n\t\t\t\tdrawer->NumRows, 320);\n\n\t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tconfig->DrawerCallback(scrn, curframe->FrameNum);\n\t\t}\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_Xmode - Page flip Xmode display.\n*\n* SYNOPSIS\n*     PageFlip_Xmode(VQA)\n*\n*     void PageFlip_Xmode(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void PageFlip_Xmode(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tunsigned char *pal;\n\tVQAConfig     *config;\n\tlong          palsize;\n\tlong          slowpal;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = vqabuf->Flipper.CurFrame;\n\n\t/* Pre-decode 'vqa' for speed */\n\tpal = curframe->Palette;\n\tpalsize = curframe->PaletteSize;\n\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\n\t/* - If this is a palette-set frame:\n\t * - Wait for NoVB (active scan)\n\t * - Flip the page (doesn't take effect until next active scan\n\t * - Wait for VB\n\t * - Set the palette\n\t * - Otherwise, just flip the page\n\t */\n\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tFlipXPage();\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(pal, palsize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)pal, (long)palsize);\n\t\t}\n\t}\n\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\tdrawer->Flags &= (~VQADRWF_SETPAL);\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tFlipXPage();\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(drawer->Palette_24, drawer->CurPalSize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)drawer->Palette_24,\n\t\t\t\t\t(long)drawer->CurPalSize);\n\t\t}\n\t} else {\n\t\tFlipXPage();\n\t}\n}\n#endif /* VQAXMODE_ON */\n\n\n#if(VQAMCGA_ON)\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_MCGA - Draws a frame directly to MCGA screen.\n*\n* SYNOPSIS\n*     Error = DrawFrame_MCGA(VQA)\n*\n*     long DrawFrame_MCGA(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Skip frames\n*       - UnLCW frame\n*       - Wait on Update_Enabled\n*       - Set Update_Enabled\n*       - Go to next frame\n*       - User_Update:\n*         set palette\n*         UnVQ to screen\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the correct spot on\n*     the screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_MCGA(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tlong         rc;\n\n\t/* Dereference commonly used data members for quicker access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Select the frame to draw. */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_MCGA - Page flip MCGA display.\n*\n* SYNOPSIS\n*     PageFlip_MCGA(VQA)\n*\n*     void PageFlip_MCGA(VQAHandle *);\n*\n* FUNCTION\n*     Since the MCGA mode only has one buffer, the drawing is actually done\n*     at this point.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void PageFlip_MCGA(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *pal;\n\tunsigned char *ptrs;\n\tunsigned char *cb;\n\tlong          palsize;\n\tlong          slowpal;\n\tlong          blocksperrow;\n\tlong          numrows;\n\n\t#ifndef PHARLAP_TNT\n\tunsigned char *scrn;\n\t#else\n\tFARPTR        scrn;\n\t#endif\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = vqabuf->Flipper.CurFrame;\n\n\t/*-------------------------------------------------------------------------\n\t * WAIT FOR THE VERTICAL BLANK TO SET THE PALETTE.\n\t *-----------------------------------------------------------------------*/\n\tif ((curframe->Flags & VQAFRMF_PALETTE)\n\t\t\t|| (drawer->Flags & VQADRWF_SETPAL)) {\n\n\t\tpal = curframe->Palette;\n\t\tpalsize = curframe->PaletteSize;\n\t\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\n\t\t/* Wait for the VBlank. */\n\t \tWaitNoVB(vqabuf->VBIBit);\n\t \tWaitVB(vqabuf->VBIBit);\n\n\t\t/* Set the palette. */\n\t\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\t\tSetPalette(pal, palsize, slowpal);\n\t\t\t}\n\n\t\t\t/* Notify the client of the palette change. */\n\t\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)pal, (long)palsize);\n\t\t\t}\n\t\t}\n\t\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\t\tdrawer->Flags &= (~VQADRWF_SETPAL);\n\n\t\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\t\tSetPalette(drawer->Palette_24, drawer->CurPalSize, slowpal);\n\t\t\t}\n\n\t\t\t/* Notify the client of the palette change. */\n\t\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)drawer->Palette_24,\n\t\t\t\t\t\t(long)drawer->CurPalSize);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * UNVQ THE FRAME DIRECTLY TO THE MCGA SCREEN.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Get screen address, blocks per row and number of rows. */\n\t#ifndef PHARLAP_TNT\n\tscrn = (unsigned char *)(0xA0000 + (unsigned long)drawer->ScreenOffset);\n\t#else\n\tFP_SET(scrn, drawer->ScreenOffset, 0x1C);\n\t#endif\n\n\tblocksperrow = drawer->BlocksPerRow;\n\tnumrows = drawer->NumRows;\n\tptrs = curframe->Pointers;\n\tcb = curframe->Codebook->Buffer;\n\tvqabuf->UnVQ(cb, ptrs, scrn, blocksperrow, numrows, 320);\n\n\t/* Process captions. */\n\tif ((((VQAHandleP *)vqa)->Caption != NULL)\n\t\t\t&& (config->OptionFlags & VQAOPTF_CAPTIONS)) {\n\t\tDoCaptions(((VQAHandleP *)vqa)->Caption, curframe->FrameNum);\n\t}\n\n\tif ((((VQAHandleP *)vqa)->EVA != NULL)\n\t\t\t&& (config->OptionFlags & VQAOPTF_EVA)) {\n\t\tDoCaptions(((VQAHandleP *)vqa)->EVA, curframe->FrameNum);\n\t}\n\n\t/* Invoke user's callback routine */\n\tif (config->DrawerCallback != NULL) {\n\t\tif (config->DrawerCallback(NULL, curframe->FrameNum)) {\n\t\t\tvqabuf->Flags |= VQADATF_DDONE;\n\t\t}\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_MCGABuf - Draws a frame in MCGA format to a buffer.\n*\n* SYNOPSIS\n*     Error = DrawFrame_MCGABuf(VQA)\n*\n*     long DrawFrame_MCGABuf(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Skip frames\n*       - UnLCW frame\n*       - Wait on Update_Enabled (can't use imgbuf til User_Update's done)\n*       - Un-VQ into ImageBuf\n*       - Set the Flipper's CurFrame\n*       - Set Update_Enabled\n*       - Go to next frame\n*       - User_Update:\n*         set Palette from Flipper.CurFrame\n*         copy ImageBuf to screen\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the upper-left\n*     corner of ImageBuf, then copying ImageBuf onto the screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_MCGABuf(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tlong         rc;\n\n\t#ifndef PHARLAP_TNT\n\tunsigned char *scrn;\n\t#else\n\tFARPTR        scrn;\n\t#endif\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t#ifndef PHARLAP_TNT\n\tscrn = drawer->ImageBuf;\n\t#else\n\tFP_SET(scrn, drawer->ImageBuf, 0x14);\n\t#endif\n\n\t/* Un-VQ the image */\n\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, scrn,\n\t\t\tdrawer->BlocksPerRow, drawer->NumRows,\n\t\t\t((VQAHandleP *)vqa)->Header.ImageWidth);\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_MCGABuf - Page flip a buffered MCGA display.\n*\n* SYNOPSIS\n*     PageFlip_MCGABuf(VQA)\n*\n*     void PageFlip_MCGABuf(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void PageFlip_MCGABuf(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *pal;\n\tunsigned char *buf;\n\tunsigned char *scrn;\n\tlong          palsize;\n\tlong          slowpal;\n\tlong          imgwidth;\n\tlong          imgheight;\n\n\t/* Derefernce commonly used data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = vqabuf->Flipper.CurFrame;\n\n\t/* Pre-decode 'vqa' for speed */\n\tpal = curframe->Palette;\n\tpalsize = curframe->PaletteSize;\n\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\n\t/* - If this is a palette-set frame:\n\t * - Wait for the vertical blank\n\t * - Set the palette\n\t * - Copy ImageBuf to SEENPAGE:\n\t * - use blit routine if image is smaller than full-screen, since the\n\t *   buffer copy assumes a full-screen image\n\t */\n\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(pal, palsize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)pal, (long)palsize);\n\t\t}\n\t}\n\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\tdrawer->Flags &= (~VQADRWF_SETPAL);\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(drawer->Palette_24, drawer->CurPalSize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)drawer->Palette_24,\n\t\t\t\t\t(long)drawer->CurPalSize);\n\t\t}\n\t}\n\n\t/* Draw image to the screen. */\n\timgwidth = ((VQAHandleP *)vqa)->Header.ImageWidth;\n\timgheight = ((VQAHandleP *)vqa)->Header.ImageHeight;\n\tbuf = drawer->ImageBuf;\n\n\t#ifndef PHARLAP_TNT\n\tscrn = (unsigned char *)0xA0000;\n\t#endif\n\n\tif ((imgwidth < 320) || (imgheight < 200)) {\n\t\t#ifndef PHARLAP_TNT\n\t\tscrn += drawer->ScreenOffset;\n\t\t#else\n\t\tscrn = (unsigned char *)drawer->ScreenOffset;\n\t\t#endif\n\n\t\tMCGA_Blit(buf, scrn, imgwidth, imgheight);\n\t} else {\n\t\tMCGA_BufferCopy(buf, NULL);\n\t}\n\n\t/* Invoke user's callback routine */\n\tif (config->DrawerCallback != NULL) {\n\t\tconfig->DrawerCallback(NULL, curframe->FrameNum);\n\t}\n}\n#endif /* VQAMCGA_ON */\n\n\n#if(VQAVESA_ON)\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_VESA640 - Draws a frame in VESA 640 format.\n*\n* SYNOPSIS\n*     Error = DrawFrame_VESA640(VQA)\n*\n*     long DrawFrame_VESA640(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_VESA640(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tlong         rc;\n\n\t#ifndef PHARLAP_TNT\n\tunsigned char *scrn;\n\t#else\n\tFARPTR        scrn;\n\t#endif\n\n\t/* Dereference data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\t}\n\n\t/* Dereference current frame. */\n\tcurframe = drawer->CurFrame;\n\n\t/* Wait for Update_Enabled to be set low */\n \tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tvqabuf->Drawer.WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t#ifndef PHARLAP_TNT\n\tscrn = drawer->ImageBuf + drawer->ScreenOffset;\n\t#else\n\tFP_SET(scrn, drawer->ImageBuf + drawer->ScreenOffset, 0x14);\n\t#endif\n\n\t/* Un-VQ the image */\n\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, scrn,\n\t\t\tdrawer->BlocksPerRow, drawer->NumRows, drawer->ImageWidth);\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_VESA320_32K - Draws a frame in VESA 320 format.\n*\n* SYNOPSIS\n*     Error = DrawFrame_VESA320_32K(VQA)\n*\n*     long DrawFrame_VESA320_32K(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_VESA320_32K(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tVQAConfig    *config;\n\tlong         rc;\n\tlong         grain;\n\n\t/* Dereference data members for quicker access. */\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* Dereference current frame. */\n\t\tcurframe = drawer->CurFrame;\n\n\t\t/* Translate palette to 15-bit */\n\t\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\t\tTranslatePalette(curframe->Palette, drawer->Palette_15,\n\t\t\t\t\tcurframe->PaletteSize);\n\t\t}\n\t\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\t\tTranslatePalette(drawer->Palette_24, drawer->Palette_15,\n\t\t\t\t\tdrawer->CurPalSize);\n\t\t}\n\n\t\t/* UnVQ directly to screen */\n\t\tgrain = ((VESAModeInfo *)(drawer->Display->Extended))->WinSize\n\t\t\t\t/ ((VESAModeInfo *)(drawer->Display->Extended))->WinGranularity;\n\n\t\t#ifndef PHARLAP_TNT\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tdrawer->Palette_15, grain, 0, 0);\n\t\t#else\n\t\t{\n\t\tFARPTR temp;\n\n\t\tFP_SET(temp, drawer->Palette_15, 0x14);\n\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, temp,\n\t\t\t\tgrain, 0, 0);\n\t\t}\n\t\t#endif\n\n\t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tconfig->DrawerCallback(0, curframe->FrameNum);\n\t\t}\n\t}\n\n\t/* Wait for VQ_Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_VESA320_32KBuf - Draws a frame in VESA320_32K format to a\n*                                buffer.\n*\n* SYNOPSIS\n*     Error = DrawFrame_VESA320_32KBuf(VQA)\n*\n*     long DrawFrame_VESA320_32KBuf(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_VESA320_32KBuf(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tVQAConfig    *config;\n\tlong         rc;\n\tlong         grain;\n\n\t/* Dereference data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = drawer->CurFrame;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* UnVQ buffered mode */\n\t\t#ifndef PHARLAP_TNT\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tdrawer->ImageBuf, drawer->BlocksPerRow, drawer->NumRows,\n\t\t\t\t((VQAHandleP *)vqa)->Header.image_width);\n\t\t#else\n\t\t{\n\t\tFARPTR scrn;\n\n\t\tFP_SET(scrn, drawer->ImageBuf, 0x14);\n\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, scrn,\n\t\t\t\tdrawer->BlocksPerRow, drawer->NumRows,\n\t\t\t\t((VQAHandleP *)vqa)->Header.image_width);\n\t\t}\n\t\t#endif\n\n\t\t/* Translate the palette to 15-bit */\n\t\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\t\tTranslatePalette(curframe->Palette, drawer->Palette_15,\n\t\t\t\t\tcurframe->PaletteSize);\n\t\t}\n\t\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\t\tTranslatePalette(drawer->Palette_24, drawer->Palette_15,\n\t\t\t\t\tdrawer->CurPalSize);\n\t\t}\n\n\t\t/* Copy the buffer */\n\t\tgrain = ((VESAModeInfo *)(drawer->Display->Extended))->WinSize\n\t\t\t\t/ ((VESAModeInfo *)(drawer->Display->Extended))->WinGranularity;\n\n\t\tBuf_320x200_To_VESA_32K(drawer->ImageBuf, drawer->Palette_15, grain);\n\n \t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tconfig->DrawerCallback(0, curframe->FrameNum);\n\t\t}\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t\tdrawer->WaitsOnFlipper++;\n\t}\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_VESA - Page flip VESA display.\n*\n* SYNOPSIS\n*     PageFlip_VESA(VQA)\n*\n*     void PageFlip_VESA(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void PageFlip_VESA(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *pal;\n\tlong          palsize;\n\tlong          slowpal;\n\tlong          grain;\n\n\t/* Dereference date members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = vqabuf->Flipper.CurFrame;\n\n\t/* Pre-decode 'vqa' for speed */\n\tpal = curframe->Palette;\n\tpalsize = curframe->PaletteSize;\n\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\n\t/* Set the palette */\n\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(pal, palsize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)pal, (long)palsize);\n\t\t}\n\t}\n\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\tdrawer->Flags &= (~VQADRWF_SETPAL);\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(drawer->Palette_24, drawer->CurPalSize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)drawer->Palette_24,\n\t\t\t\t\t(long)drawer->CurPalSize);\n\t\t}\n\t}\n\n\t/* Copy the buffer */\n\tgrain = ((VESAModeInfo *)(drawer->Display->Extended))->WinSize\n\t\t\t/ ((VESAModeInfo *)(drawer->Display->Extended))->WinGranularity;\n\n\tswitch (((VQAHandleP *)vqa)->Header.image_width) {\n\t\tcase 320:\n\t\t\tif (config->DrawFlags & VQACFGF_SCALEX2) {\n\t\t\t\tBuf_320x200_To_VESA_640x400(drawer->ImageBuf, grain);\n\t\t\t} else {\n\t\t\t\tBuf_320x200_To_VESA_320x200(drawer->ImageBuf, grain);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tVESA_Blit_640x480(drawer->Display, drawer->ImageBuf, drawer->X1,\n\t\t\t\t\tdrawer->Y1, ((VQAHandleP *)vqa)->Header.image_width,\n\t\t\t\t\t((VQAHandleP *)vqa)->Header.image_height);\n\t\t\tbreak;\n\t}\n\n\t/* Invoke user's callback routine */\n\tif (config->DrawerCallback != NULL) {\n\t\tconfig->DrawerCallback(drawer->ImageBuf, curframe->FrameNum);\n\t}\n}\n#endif /* VQAVESA_ON */\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_Buffer - Draw a frame to a buffer.\n*\n* SYNOPSIS\n*     Error = DrawFrame_Buffer(VQA)\n*\n*     long DrawFrame_Buffere(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQA handle.\n*\n* RESULT\n*     Error - 0 if successful, otherwise VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_Buffer(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tVQAConfig    *config;\n\tlong         rc;\n\n\t#ifndef PHARLAP_TNT\n\tunsigned char *buff;\n\t#else\n\tFARPTR        buff;\n\t#endif\n\n\t/* Dereference data members for quicker access. */\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\t}\n \n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t#ifndef PHARLAP_TNT\n\tbuff = (unsigned char *)(drawer->ImageBuf + drawer->ScreenOffset);\n\t#else\n\tFP_SET(buff, drawer->ImageBuf + drawer->ScreenOffset, 0x14);\n\t#endif\n\n\t/* Un-VQ the image */\n\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, buff,\n\t\t\tdrawer->BlocksPerRow, drawer->NumRows, drawer->ImageWidth);\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Invoke user's callback routine */\n\tif (config->DrawerCallback != NULL) {\n\t\tconfig->DrawerCallback(drawer->ImageBuf, curframe->FrameNum);\n\t}\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     UnVQ_Nop - Do nothing UnVQ.\n*\n* SYNOPSIS\n*     UnVQ_Nop(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n*\n*     void UnVQ_Nop(unsigned char *, unsigned char *, unsigned char *,\n*                   unsigned long, unsigned long, unsigned long);\n* FUNCTION\n*\n* INPUTS\n*     Codebook - Not used. (Prototype placeholder)\n*     Pointers - Not used. (Prototype placeholder)\n*     Buffer   - Not used. (Prototype placeholder)\n*     BPR      - Not used. (Prototype placeholder)\n*     Rows     - Not used. (Prototype placeholder)\n*     BufWidth - Not used. (Prototype placeholder)\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\n#ifndef PHARLAP_TNT\nstatic void cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth)\n#else\nstatic void cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth)\n#endif\n{\n\t/* Suppress compiler warnings */\n\tcodebook = codebook;\n\tpointers = pointers;\n\tbuffer = buffer;\n\tblocksperrow = blocksperrow;\n\tnumrows = numrows;\n\tbufwidth = bufwidth;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_Nop - Do nothing page flip.\n*\n* SYNOPSIS\n*     PageFlip_Nop(VQA)\n*\n*     void PageFlip_Nop(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQA handle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void PageFlip_Nop(VQAHandle *vqa)\n{\n\tvqa = vqa;\n}\n\n\n#if(0)\n/****************************************************************************\n*\n* NAME\n*     Mask_Rect - Sets non-drawable rectangle in image.\n*\n* SYNOPSIS\n*     Mask_Rect(VQA, X1, Y1, X2, Y2)\n*\n*     void Mask_Rect(VQAHandle *, unsigned long, unsigned long,\n*                    unsigned long, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQA handle.\n*     X1  - X coordinate of upper-left corner\n*     Y1  - Y coordinate of upper-left corner\n*     X2  - X coordinate of lower-right corner\n*     Y2  - Y coordinate of lower-right corner\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Mask_Rect(VQAHandle *vqa, unsigned long x1, unsigned long y1,\n\t\tunsigned long x2, unsigned long y2)\n{\n\tVQAData   *vqabuf;\n\tVQADrawer *drawer;\n\tVQAHeader *header;\n\tlong      blocks_per_row;\n\n\t/* Dereference data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\theader = &((VQAHandleP *)vqa)->Header;\n\tdrawer =  &vqabuf->Drawer;\n\n\t/* Clip coords to image size */\n\tif (x1 < vqabuf->Drawer.X1) {\n\t\tx1 = vqabuf->Drawer.X1;\n\t}\n\n\tif (y1 < vqabuf->Drawer.Y1) {\n\t\ty1 = vqabuf->Drawer.Y1;\n\t}\n\n\tif (x2 > vqabuf->Drawer.X2) {\n\t\tx2 = vqabuf->Drawer.X2;\n\t}\n\n\tif (y2 > vqabuf->Drawer.Y2) {\n\t\ty2 = vqabuf->Drawer.Y2;\n\t}\n\n\t/* Convert pixel coords to block coords */\n\tx1 /= header->block_width;\n\tx2 /= header->block_width;\n\ty1 /= header->block_height;\n\ty2 /= header->block_height;\n\n\t/* Compute the mask values */\n\tblocks_per_row = (header->image_width / header->block_width);\n\tvqabuf->Drawer.MaskStart = blocks_per_row * y1 + x1;\n\n\tif (x1 == x2) {\n\t\tdrawer->MaskWidth = 0;\n\t} else {\n\t\tdrawer->MaskWidth = x2 - x1 + 1;\n\t}\n\n\tif (y1 == y2) {\n\t\tdrawer->MaskHeight = 0;\n\t} else {\n\t\tdrawer->MaskHeight = y2 - y1 + 1;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Mask_Pointers - Mask vector pointer that are in the mask rectangle.\n*\n* SYNOPSIS\n*     Mask_Pointers(VQAData)\n*\n*     void Mask_Pointers(VQAData *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQAData - Pointer to VQAData structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Mask_Pointers(VQAData *vqabuf)\n{\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tunsigned long *ptr;\n\tunsigned long i,j;\n\tunsigned long start;\n\n\t/* Dereference data members for quicker access. */\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = drawer->CurFrame;\n\tstart = vqabuf->Drawer.MaskStart;\n\n\tfor (i = 0; i < drawer->MaskHeight; i++) {\n\t\tptr = (unsigned long *)(curframe->Pointers) + start;\n\n\t\tfor (j = 0; j < drawer->MaskWidth; j++) {\n\t\t\tptr[j] = VQA_MASK_POINTER;\n\t\t}\n\n\t\tstart += drawer->BlocksPerRow;\n\t}\n}\n#endif\n\n"
  },
  {
    "path": "VQ/VQA32/DRAWER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQAPlay32 library. (32-Bit protected mode)\n*\n* FILE\n*     drawer.c\n*\n* DESCRIPTION\n*     Frame drawing and page flip control.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     June 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_Configure_Drawer - Configure the drawer routines.\n*\n* PRIVATE\n*     Select_Frame             - Selects frame to draw and preforms frame\n*                                skip.\n*     Prepare_Frame            - Process/Decompress frame information.\n*     DrawFrame_Xmode          - Draws a frame directly to Xmode screen.\n*     DrawFrame_XmodeBuf       - Draws a frame in Xmode format to a buffer.\n*     DrawFrame_XmodeVRAM      - Draws a frame in Xmode with resident\n*                                Codebook.\n*     PageFlip_Xmode           - Page flip Xmode display.\n*     DrawFrame_MCGA           - Draws a frame directly to MCGA screen.\n*     PageFlip_MCGA            - Page flip MCGA display.\n*     DrawFrame_MCGABuf        - Draws a frame in MCGA format to a buffer.\n*     PageFlip_MCGABuf         - Page flip a buffered MCGA display.\n*     DrawFrame_VESA640        - Draws a frame in VESA640 format.\n*     DrawFrame_VESA320_32K    - Draws a frame to VESA320_32K screen.\n*     DrawFrame_VESA320_32KBuf - Draws a frame in VESA320_32K format to a\n*                                buffer.\n*     PageFlip_VESA            - Page flip VESA display.\n*     DrawFrame_Buffer         - Draw a frame to a buffer.\n*     PageFlip_Nop             - Do nothing page flip.\n*     UnVQ_Nop                 - Do nothing UnVQ.\n*     Mask_Rect                - Sets non-drawable rectangle in image.\n*     Mask_Pointers            - Mask vector pointer that are in the mask\n*                                rectangle.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <malloc.h>\n#include <conio.h>\n#include <dos.h>\n#include <mem.h>\n#include \"vq.h\"\n#include \"unvq.h\"\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\nstatic long Select_Frame(VQAHandleP *vqap);\nstatic void Prepare_Frame(VQAData *vqabuf);\n\n#if(VQAMCGA_ON)\nstatic long DrawFrame_MCGABuf(VQAHandle *vqa);\nstatic long PageFlip_MCGABuf(VQAHandle *vqa);\nstatic long DrawFrame_MCGA(VQAHandle *vqa);\nstatic long PageFlip_MCGA(VQAHandle *vqa);\n#endif /* VQAMCGA_ON */\n\n#if(VQAXMODE_ON)\nstatic long DrawFrame_XmodeBuf(VQAHandle *vqa);\nstatic long DrawFrame_Xmode(VQAHandle *vqa);\nstatic long DrawFrame_XmodeVRAM(VQAHandle *vqa);\nstatic void PageFlip_Xmode(VQAHandle *vqabuf);\n#endif /* VQAXMODE_ON */\n\n#if(VQAVESA_ON)\nstatic long DrawFrame_VESA640(VQAHandle *vqa);\nstatic long DrawFrame_VESA320_32K(VQAHandle *vqa);\nstatic long DrawFrame_VESA320_32KBuf(VQAHandle *vqa);\nstatic void PageFlip_VESA(VQAHandle *vqabuf);\n#endif /* VQAVESA_ON */\n\nstatic long DrawFrame_Buffer(VQAHandle *vqa);\nstatic long PageFlip_Nop(VQAHandle *vqa);\n\n#ifndef PHARLAP_TNT\nstatic void cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n#else\nstatic void cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n#endif\n\n#if(0)\nstatic void Mask_Rect(VQAHandle *vqa, unsigned long x1, unsigned long y1,\n\t\tunsigned long x2, unsigned long y2);\nstatic void Mask_Pointers(VQAData *vqabuf);\n#endif\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Configure_Drawer - Configure the drawer routines.\n*\n* SYNOPSIS\n*     VQA_Configure_Drawer(VQA)\n*\n*     void VQA_Configure_Drawer(VQAHandleP *);\n*\n* FUNCTION\n*     Configure the drawing system for the current movie and configuration\n*     options.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Configure_Drawer(VQAHandleP *vqap)\n{\n\tVQAData   *vqabuf;\n\tVQAConfig *config;\n\tVQAHeader *header;\n\tVQADrawer *drawer;\n\tlong      origin;\n\tlong      blkdim;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\theader = &vqap->Header;\n\tconfig = &vqap->Config;\n\torigin = (config->DrawFlags & VQACFGF_ORIGIN);\n\n\t/*-------------------------------------------------------------------------\n\t * SET THE DRAW POSITION OF THE MOVIE.\n\t *\n\t * X1 = -1 -- Center image of the X axis, otherwise use X1 value.\n\t * Y1 = -1 -- Center image of the Y axis, otherwise use Y1 value.\n\t *-----------------------------------------------------------------------*/\n\tif ((config->X1 == -1) && (config->Y1 == -1)) {\n\n\t\t#if(VQAVIDEO_ON)\n\t\tdrawer->X1 = ((drawer->Display->XRes - header->image_width) / 2);\n\t\tdrawer->Y1 = ((drawer->Display->YRes - header->image_height) / 2);\n\t\t#else  /* VQAVIDEO_ON */\n\t\tdrawer->X1 = ((drawer->ImageWidth - header->ImageWidth) / 2);\n\t\tdrawer->Y1 = ((drawer->ImageHeight - header->ImageHeight) / 2);\n\t\t#endif /* VQAVIDEO_ON */\n\n\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\tdrawer->Y2 = ((drawer->Y1 + header->ImageHeight) - 1);\n\t} else {\n\t\tswitch (origin) {\n\t\t\tdefault:\n\t\t\tcase VQACFGF_TOPLEFT:\n\t\t\t\tdrawer->X1 = config->X1;\n\t\t\t\tdrawer->Y1 = config->Y1;\n\t\t\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\t\t\tdrawer->Y2 = ((drawer->Y1 + header->ImageHeight) - 1);\n\t\t\t\tbreak;\n\n\t\t\tcase VQACFGF_BOTLEFT:\n\t\t\t\tdrawer->X1 = config->X1;\n\t\t\t\tdrawer->Y1 = (drawer->ImageHeight - config->Y1);\n\t\t\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\t\t\tdrawer->Y2 = ((drawer->Y2 - header->ImageHeight) - 1);\n\t\t\t\tbreak;\n\n\t\t\tcase VQACFGF_BOTRIGHT:\n\t\t\t\tdrawer->X1 = (drawer->ImageWidth - config->X1);\n\t\t\t\tdrawer->Y1 = (drawer->ImageHeight - config->Y1);\n\t\t\t\tdrawer->X2 = (drawer->X1 - header->ImageWidth);\n\t\t\t\tdrawer->Y2 = (drawer->Y1 - header->ImageHeight);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE UNVQ ROUTINE FOR THE SPECIFIED VIDEO MODE AND BLOCK SIZE.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Pre-compute commonly used values for speed. */\n\tdrawer->BlocksPerRow = header->ImageWidth / header->BlockWidth;\n\tdrawer->NumRows = header->ImageHeight / header->BlockHeight;\n\tdrawer->NumBlocks = drawer->BlocksPerRow * drawer->NumRows;\n\tblkdim = BLOCK_DIM(header->BlockWidth, header->BlockHeight);\n\n\t/* Initialize draw routine vectors to a NOP routine in order to prevent\n\t * a crash.\n\t */\n\tvqabuf->UnVQ = UnVQ_Nop;\n\tvqabuf->Page_Flip = PageFlip_Nop;\n\n\t/* If the client specifies buffering then go ahead an set the unvq\n\t * vector. All of the buffered modes use the same unvq routines.\n\t */\n\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\tswitch (blkdim) {\n\t\t\t#if(VQABLOCK_2X2)\n\t\t\tcase BLOCK_2X2:\n\t\t\t\tvqabuf->UnVQ = UnVQ_2x2;\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\t#if(VQABLOCK_2X3)\n\t\t\tcase BLOCK_2X3:\n\t\t\t\tvqabuf->UnVQ = UnVQ_2x3;\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\t#if(VQABLOCK_4X2)\n\t\t\tcase BLOCK_4X2:\n\t\t\t\tvqabuf->UnVQ = UnVQ_4x2;\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\t#if(VQABLOCK_4X4)\n\t\t\tcase BLOCK_4X4:\n\t\t\t\tvqabuf->UnVQ = UnVQ_4x4;\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n \t\t}\n \t}\n\n\t/* Initialize the draw vectors for the specified video mode. */\n\tswitch (config->Vmode) {\n\n\t\t/* MCGA */\n\t\t#if(VQAMCGA_ON)\n\t\tcase MCGA:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_MCGABuf;\n\t\t\t\tvqabuf->Page_Flip = PageFlip_MCGABuf;\n\t\t\t} else {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_MCGA;\n\t\t\t\tvqabuf->Page_Flip = PageFlip_MCGA;\n\n\t\t\t\t/* MCGA uses the same unvq routines that are used for unvqing\n\t\t\t\t * to a buffer because MCGA mode is just another buffer. However,\n\t\t\t\t * instead of drawing to an allocated RAM buffer we are drawing\n\t\t\t\t * directly to the VRAM video buffer.\n\t\t\t\t */\n\t\t\t\tswitch (blkdim) {\n\t\t\t\t\t#if(VQABLOCK_2X2)\n\t\t\t\t\tcase BLOCK_2X2:\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_2x2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\n\t\t\t\t\t#if(VQABLOCK_2X3)\n\t\t\t\t\tcase BLOCK_2X3:\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_2x3;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\n\t\t\t\t\t#if(VQABLOCK_4X2)\n\t\t\t\t\tcase BLOCK_4X2:\n\t\t\t\t\t\t#if(!VQAWOOFER_ON)\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2;\n\t\t\t\t\t\t#else\n\t\t\t\t\t\tif (config->DrawFlags & VQACFGF_WOOFER) {\n\t\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2_Woofer;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t#endif\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\n\t\t\t\t\t#if(VQABLOCK_4X4)\n\t\t\t\t\tcase BLOCK_4X4:\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x4;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Pre-compute the draw offset for speed. */\n\t\t\tdrawer->ScreenOffset = ((320 * drawer->Y1) + drawer->X1);\n\t\t\tbreak;\n\t\t#endif /* VQAMCGA_ON */\n\n\t\t/* XMODE */\n\t\t#if(VQAXMODE_ON)\n\t\tcase XMODE_320X200:\n\t\tcase XMODE_320X240:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_XmodeBuf;\n\t\t\t\tvqabuf->Page_Flip = PageFlip_Xmode;\n\t\t\t} else {\n\t\t\t\tvqabuf->Page_Flip = PageFlip_Xmode;\n\n\t\t\t\tif (config->DrawFlags & VQACFGF_VRAMCB) {\n\t\t\t\t\tvqabuf->Draw_Frame = DrawFrame_XmodeVRAM;\n\n\t\t\t\t\tswitch (blkdim) {\n\t\t\t\t\t\t#if(VQABLOCK_4X2)\n\t\t\t\t\t\tcase BLOCK_4X2:\n\t\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2_XmodeCB;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t#endif /* VQABLOCK_4X2 */\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tvqabuf->Draw_Frame = DrawFrame_Xmode;\n\n\t\t\t\t\tswitch (blkdim) {\n\t\t\t\t\t\t#if(VQABLOCK_4X2)\n\t\t\t\t\t\tcase BLOCK_4X2:\n\t\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2_Xmode;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t#endif /* VQABLOCK_4X2 */\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Pre-compute the draw offset for speed. */\n\t\t\tdrawer->ScreenOffset = (((320 / 4) * drawer->Y1) + (drawer->X1 / 4));\n\t\t\tbreak;\n\t\t#endif /* VQAXMODE_ON */\n\n\t\t/* VESA */\n\t\t#if(VQAVESA_ON)\n\n\t\t/* Currently this is a buffered mode, but should be optimized for\n\t\t * for screen direct.\n\t\t */\n\t\tcase VESA_640X480_256:\n\t\t\tvqabuf->Draw_Frame = DrawFrame_VESA640;\n\t\t\tvqabuf->Page_Flip = PageFlip_VESA;\n\t\t\tbreak;\n\n\t\tcase VESA_320X200_32K_1:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_VESA320_32KBuf;\n\t\t\t} else {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_VESA320_32K;\n\n\t\t\t\tswitch (blkdim) {\n\t\t\t\t\t#if(VQABLOCK_4X2)\n\t\t\t\t\tcase BLOCK_4X2:\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2_VESA320_32K;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t#endif /* VQAVESA_ON */\n\n\t\t/* Purely buffered (Video refresh is up to the client. */\n\t\tdefault:\n\t\t\tvqabuf->Draw_Frame = DrawFrame_Buffer;\n\n\t\t\t/* Pre-compute the draw offset for speed. */\n\t\t\tdrawer->ScreenOffset = ((drawer->ImageWidth * drawer->Y1)+drawer->X1);\n\t\t\tbreak;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Select_Frame - Selects frame to draw and preforms frame skip.\n*\n* SYNOPSIS\n*     Error = Select_Frame(VQA)\n*\n*     long Select_Frame(VQAHandleP *);\n*\n* FUNCTION\n*     Select a frame to draw. This is were the frame skipping/delay is\n*     performed.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Select_Frame(VQAHandleP *vqap)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAConfig    *config;\n\tVQAFrameNode *curframe;\n\tlong         curtime;\n\tlong         desiredframe;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tconfig = &vqap->Config;\n\tvqabuf = vqap->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = drawer->CurFrame;\n\n\t/* Make sure the current frame is drawable. If the frame is not ready\n\t * then we must wait for the loader to catch up.\n\t */\n\tif ((curframe->Flags & VQAFRMF_LOADED) == 0) {\n\t\tdrawer->WaitsOnLoader++;\n\t\treturn (VQAERR_NOBUFFER);\n\t}\n\n\t/* If single stepping then return with the next frame.*/\n\tif (config->OptionFlags & VQAOPTF_STEP) {\n\t\tdrawer->LastFrame = curframe->FrameNum;\n\t\treturn (0);\n\t}\n\n\t/* Find the frame # we should play (rounded to nearest frame): */\n\tcurtime = VQA_GetTime(vqap);\n\tdesiredframe = ((curtime * config->FrameRate) / VQA_TIMETICKS);\n\n\t#if(VQAMONO_ON)\n\tdrawer->DesiredFrame = desiredframe;\n\t#endif\n\n\t/* Handle the cases where the player is going so fast that it's not time \n\t * to draw this frame yet.\n\t *\n\t * - If the Drawer is using a slower frame rate than the Loader, use a\n\t *   delta-time-based wait; otherwise, use the frame number as the wait.\n\t */\n\tif (config->DrawRate != config->FrameRate) {\n\t\tif (curtime - drawer->LastTime < (VQA_TIMETICKS / config->DrawRate)) {\n\t\t\treturn (VQAERR_NOT_TIME);\n\t\t}\n\t} else {\n\t\tif (curframe->FrameNum > desiredframe) {\n\t\t\treturn (VQAERR_NOT_TIME);\n\t\t}\n\t}\n\n\t/* Make sure we draw at least 5 frames per second */\n\tif ((curframe->FrameNum - drawer->LastFrame) >= (config->FrameRate / 5)) {\n\t\tdrawer->LastFrame = curframe->FrameNum;\n\t\treturn (0);\n\t}\n\n\t/* If frame skipping is disabled then draw every frame. */\n\tif (config->DrawFlags & VQACFGF_NOSKIP) {\n\t\tdrawer->LastFrame = curframe->FrameNum;\n\t\treturn (0);\n\t}\n\n\t/* Handle the case where the player is going too slow, so we have to skip \n\t * some frames:\n\t *\n\t * - If this is a Key Frame, draw it\n\t * - If this frame's # is less than what we're supposed to draw, skip it\n\t *   (Because the 1st 'desiredframe' will be 0, FrameNum MUST be typecast \n\t *   to signed WORD for the comparison; otherwise, the comparison uses \n\t *   UWORDs, and the first frame is always skipped.)\n\t * - If this is a palette-set frame, set the palette before skipping it\n\t * - Loop until we get the frame we need, or there's no frames available\n\t */\n\twhile (1) {\n\n\t\t/* No frame available; return */\n\t\tif ((curframe->Flags & VQAFRMF_LOADED) == 0) {\n\t\t\treturn (VQAERR_NOBUFFER);\n\t\t}\n\n\t\t/* Force drawing of a Key Frame */\n\t\tif (curframe->Flags & VQAFRMF_KEY) {\n\t\t\tbreak;\n\t\t}\n\n\t\t/* Skip the frame */\n\t\tif (curframe->FrameNum < desiredframe) {\n\n\t\t\t/* Handle a palette in a skipped frame:\n\t\t\t *\n\t\t\t * - Stash the palette in Drawer.Palette_24\n\t\t\t * - Set the Drawer.Flags VQADRWF_SETPAL bit, to tell the page-flip\n\t\t\t *   routines that this palette must be set\n\t\t\t */\n\t\t\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\n\t\t\t\t/* Un-LCW if needed */\n\t\t\t\tif (curframe->Flags & VQAFRMF_PALCOMP) {\n\t\t\t\t\tcurframe->PaletteSize = LCW_Uncompress((char *)curframe->Palette\n\t\t\t\t\t\t\t+ curframe->PalOffset, (char *)curframe->Palette,\n\t\t\t\t\t\t\tvqabuf->Max_Pal_Size);\n\n\t\t\t\t\tcurframe->Flags &= ~VQAFRMF_PALCOMP;\n\t\t\t\t}\n\n\t\t\t\t/* Stash the palette */\n\t\t\t\tmemcpy(drawer->Palette_24, curframe->Palette, curframe->PaletteSize);\n\t\t\t\tdrawer->CurPalSize = curframe->PaletteSize;\n\t\t\t\tdrawer->Flags |= VQADRWF_SETPAL;\n\t\t\t}\n\n\t\t\t/* Invoke callback with NULL screen ptr */\n\t\t\tif (config->DrawerCallback != NULL) {\n\t\t\t\tif ((config->DrawerCallback(NULL, curframe->FrameNum)) != 0) {\n\t\t\t\t\treturn (VQAERR_EOF);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Skip the frame */\n\t\t\tcurframe->Flags = 0L;\n\t\t\tcurframe = curframe->Next;\n\t\t\tdrawer->CurFrame = curframe;\n\t\t\tdrawer->NumSkipped++;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tdrawer->LastFrame = curframe->FrameNum;\n\tdrawer->LastTime = curtime;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Prepare_Frame - Process/Decompress frame information.\n*\n* SYNOPSIS\n*     Prepare_Frame(VQAData)\n*\n*     void Prepare_Frame(VQAData *);\n*\n* FUNCTION\n*     Decompress and preprocess the various frame elements (codebook,\n*     pointers, palette, etc...)\n*\n* INPUTS\n*     VQAData - Pointer to VQAData structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Prepare_Frame(VQAData *vqabuf)\n{\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tVQACBNode    *codebook;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = drawer->CurFrame;\n\tcodebook = curframe->Codebook;\n\n\t/* Decompress the codebook, if needed */\n\tif (codebook->Flags & VQACBF_CBCOMP) {\n\n\t\t/* Decompress the codebook. */\n\t\tLCW_Uncompress((char *)codebook->Buffer + codebook->CBOffset,\n\t\t\t\t(char *)codebook->Buffer, vqabuf->Max_CB_Size);\n\n\t\t/* Mark as uncompressed for the next time we use it */\n\t\tcodebook->Flags &= (~VQACBF_CBCOMP);\n\t}\n\n\t/* Decompress the palette, if needed */\n\tif (curframe->Flags & VQAFRMF_PALCOMP) {\n\t\tcurframe->PaletteSize = LCW_Uncompress((char *)curframe->Palette +\n\t\t\t\tcurframe->PalOffset,(char *)curframe->Palette,vqabuf->Max_Pal_Size);\n\n\t\t/* Mark as uncompressed */\n\t\tcurframe->Flags &= ~VQAFRMF_PALCOMP;\n\t}\n\n\t/* Decompress the pointer data, if needed */\n\tif (curframe->Flags & VQAFRMF_PTRCOMP) {\n\t\tLCW_Uncompress((char *)curframe->Pointers + curframe->PtrOffset,\n\t\t\t\t(char *)curframe->Pointers, vqabuf->Max_Ptr_Size);\n\n\t\t/* Mark as uncompressed */\n\t\tcurframe->Flags &= ~VQAFRMF_PTRCOMP;\n\t}\n\n\t/* Mask the pointers */\n\t#if(0)\n\tMask_Pointers(vqabuf);\n\t#endif\n}\n\n\n#if(VQAXMODE_ON)\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_Xmode - Draws a frame in Xmode format (Screen direct).\n*\n* SYNOPSIS\n*     Error = DrawFrame_Xmode(VQA)\n*\n*     long DrawFrame_Xmode(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Skip frames\n*       - UnLCW frame\n*       - Un-VQ into video RAM\n*       - Wait on Update_Enabled\n*       - Set the Flipper's CurFrame\n*       - Set Update_Enabled\n*       - Go to next frame\n*       - User_Update:\n*         Flip X-Page\n*         Set Palette from Flipper.CurFrame\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the correct spot on\n*     the Xmode screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_Xmode(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *scrn;\n\tlong          rc;\n\n\t/* Dereference data members for quick access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n \t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* Dereference current frame for quicker access */\n\t\tcurframe = drawer->CurFrame;\n\n\t\t/* Un-VQ the image */\n\t\tscrn = GetXHidPage();\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tscrn + drawer->ScreenOffset, drawer->BlocksPerRow,\n\t\t\t\tdrawer->NumRows, 320);\n\n\t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tif ((config->DrawerCallback(scrn, curframe->FrameNum)) != 0) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access */\n\tcurframe = drawer->CurFrame;\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_XmodeBuf - Draws a frame in Xmode format to a buffer.\n*\n* SYNOPSIS\n*     Error = DrawFrame_XmodeBuf(VQA)\n*\n*     long DrawFrame_XmodeBuf(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Skip frames\n*       - UnLCW frame\n*       - Un-VQ into ImageBuf\n*       - Copy ImageBuf to video RAM\n*       - Wait on Update_Enabled\n*       - Set the Flipper's CurFrame\n*       - Set Update_Enabled\n*       - Go to next frame\n*\t      - User_Update:\n*         Flip X-Page\n*         Set Palette from Flipper.CurFrame\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the upper-left\n*     corner of ImageBuf, then copying ImageBuf into the correct part of the\n*     Xmode screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_XmodeBuf(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAHeader     *header;\n\tVQAConfig     *config;\n\tunsigned char *scrn;\n\tlong          rc;\n\n\t/* Dereference data members for quicker access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\theader = &((VQAHandleP *)vqa)->Header;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* Dereference current frame for quicker access. */\n\t\tcurframe = drawer->CurFrame;\n\n\t\t/* Un-VQ the image */\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tdrawer->ImageBuf, drawer->BlocksPerRow, drawer->NumRows,\n\t\t\t\theader->ImageWidth);\n\n\t\t/* Copy the buffer */\n\t\tscrn = GetXHidPage();\n\n\t\tif ((header->ImageWidth < 320) || (header->ImageHeight < 200)) {\n\t\t\tXmode_Blit(drawer->ImageBuf, scrn + drawer->ScreenOffset,\n\t\t\t\t\theader->ImageWidth, header->ImageHeight);\n\t\t} else {\n\t\t\tXmode_BufferCopy_320x200(drawer->ImageBuf,scrn + drawer->ScreenOffset);\n\t\t}\n\n\t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tif ((config->DrawerCallback(scrn, curframe->FrameNum)) != 0) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_XmodeVRAM - Draws a frame in Xmode with resident Codebook.\n*\n* SYNOPSIS\n*     Error = DrawFrame_XmodeVRAM(VQA)\n*\n*     long DrawFrame_XmodeVRAM(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Download Codebook if it isn't already (do this before skipping\n*         frames, so Select_Frame will smooth out the delay)\n*       - Skip frames\n*       - UnLCW frame\n*       - Convert Pointers to VRAM format\n*       - Un-VQ by copying codebook blocks within VRAM\n*       - Wait on Update_Enabled\n*       - Set the Flipper's CurFrame\n*       - Set Update_Enabled\n*       - Go to next frame\n*       - User_Update:\n*         Flip X-Page\n*         Set Palette from Flipper.CurFrame\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the correct spot on\n*     the Xmode screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_XmodeVRAM(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *scrn;\n\tlong          rc;\n\n\t/* Dereference data members for quicker access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* Dereference current frame for quicker access. */\n\t\tcurframe = drawer->CurFrame;\n\n\t\t/* Download codebook to VRAM */\n\t\tif ((curframe->Codebook->Flags & VQACBF_DOWNLOADED) == 0) {\n\t\t\tUpload_4x2CB(curframe->Codebook->Buffer,\n\t\t\t\t\t((VQAHandleP *)vqa)->Header.CBentries\n\t\t\t\t\t+ ((VQAHandleP *)vqa)->Header.Num1Colors);\n\n\t\t\tcurframe->Codebook->Flags |= VQACBF_DOWNLOADED;\n\t\t}\n\n\t\t/* Convert pointers to VRAM format */\n\t\tXlatePointers(curframe->Pointers, drawer->NumBlocks);\n\n\t\t/* Un-VQ the image */\n\t\tscrn = GetXHidPage();\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tscrn + drawer->ScreenOffset, drawer->BlocksPerRow,\n\t\t\t\tdrawer->NumRows, 320);\n\n\t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tif ((config->DrawerCallback(scrn, curframe->FrameNum)) != 0) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_Xmode - Page flip Xmode display.\n*\n* SYNOPSIS\n*     PageFlip_Xmode(VQA)\n*\n*     void PageFlip_Xmode(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void PageFlip_Xmode(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tunsigned char *pal;\n\tVQAConfig     *config;\n\tlong          palsize;\n\tlong          slowpal;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = vqabuf->Flipper.CurFrame;\n\n\t/* Pre-decode 'vqa' for speed */\n\tpal = curframe->Palette;\n\tpalsize = curframe->PaletteSize;\n\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\n\t/* - If this is a palette-set frame:\n\t * - Wait for NoVB (active scan)\n\t * - Flip the page (doesn't take effect until next active scan\n\t * - Wait for VB\n\t * - Set the palette\n\t * - Otherwise, just flip the page\n\t */\n\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tFlipXPage();\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(pal, palsize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)pal, (long)palsize);\n\t\t}\n\t}\n\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\tdrawer->Flags &= (~VQADRWF_SETPAL);\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tFlipXPage();\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(drawer->Palette_24, drawer->CurPalSize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)drawer->Palette_24,\n\t\t\t\t\t(long)drawer->CurPalSize);\n\t\t}\n\t} else {\n\t\tFlipXPage();\n\t}\n}\n#endif /* VQAXMODE_ON */\n\n\n#if(VQAMCGA_ON)\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_MCGA - Draws a frame directly to MCGA screen.\n*\n* SYNOPSIS\n*     Error = DrawFrame_MCGA(VQA)\n*\n*     long DrawFrame_MCGA(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Skip frames\n*       - UnLCW frame\n*       - Wait on Update_Enabled\n*       - Set Update_Enabled\n*       - Go to next frame\n*       - User_Update:\n*         set palette\n*         UnVQ to screen\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the correct spot on\n*     the screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_MCGA(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tlong         rc;\n\n\t/* Dereference commonly used data members for quicker access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Select the frame to draw. */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_MCGA - Page flip MCGA display.\n*\n* SYNOPSIS\n*     PageFlip_MCGA(VQA)\n*\n*     long PageFlip_MCGA(VQAHandle *);\n*\n* FUNCTION\n*     Since the MCGA mode only has one buffer, the drawing is actually done\n*     at this point.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle structure.\n*\n* RESULT\n*     Error - 0 if successfull, otherwise VQAERR_???\n*\n****************************************************************************/\n\nstatic long PageFlip_MCGA(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *pal;\n\tunsigned char *ptrs;\n\tunsigned char *cb;\n\tlong          palsize;\n\tlong          slowpal;\n\tlong          blocksperrow;\n\tlong          numrows;\n\n\t#ifndef PHARLAP_TNT\n\tunsigned char *scrn;\n\t#else\n\tFARPTR        scrn;\n\t#endif\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = vqabuf->Flipper.CurFrame;\n\n\t/*-------------------------------------------------------------------------\n\t * WAIT FOR THE VERTICAL BLANK TO SET THE PALETTE.\n\t *-----------------------------------------------------------------------*/\n\tif ((curframe->Flags & VQAFRMF_PALETTE)\n\t\t\t|| (drawer->Flags & VQADRWF_SETPAL)) {\n\n\t\tpal = curframe->Palette;\n\t\tpalsize = curframe->PaletteSize;\n\t\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\n\t\t/* Wait for the VBlank. */\n\t \tWaitNoVB(vqabuf->VBIBit);\n\t \tWaitVB(vqabuf->VBIBit);\n\n\t\t/* Set the palette. */\n\t\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\t\tSetPalette(pal, palsize, slowpal);\n\t\t\t}\n\n\t\t\t/* Notify the client of the palette change. */\n\t\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)pal, (long)palsize);\n\t\t\t}\n\t\t}\n\t\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\t\tdrawer->Flags &= (~VQADRWF_SETPAL);\n\n\t\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\t\tSetPalette(drawer->Palette_24, drawer->CurPalSize, slowpal);\n\t\t\t}\n\n\t\t\t/* Notify the client of the palette change. */\n\t\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)drawer->Palette_24,\n\t\t\t\t\t\t(long)drawer->CurPalSize);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * UNVQ THE FRAME DIRECTLY TO THE MCGA SCREEN.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Get screen address, blocks per row and number of rows. */\n\t#ifndef PHARLAP_TNT\n\tscrn = (unsigned char *)(0xA0000 + (unsigned long)drawer->ScreenOffset);\n\t#else\n\tFP_SET(scrn, drawer->ScreenOffset, 0x1C);\n\t#endif\n\n\tblocksperrow = drawer->BlocksPerRow;\n\tnumrows = drawer->NumRows;\n\tptrs = curframe->Pointers;\n\tcb = curframe->Codebook->Buffer;\n\tvqabuf->UnVQ(cb, ptrs, scrn, blocksperrow, numrows, 320);\n\n\t/* Process captions. */\n\tif ((((VQAHandleP *)vqa)->Caption != NULL)\n\t\t\t&& (config->OptionFlags & VQAOPTF_CAPTIONS)) {\n\t\tDoCaptions(((VQAHandleP *)vqa)->Caption, curframe->FrameNum);\n\t}\n\n\tif ((((VQAHandleP *)vqa)->EVA != NULL)\n\t\t\t&& (config->OptionFlags & VQAOPTF_EVA)) {\n\t\tDoCaptions(((VQAHandleP *)vqa)->EVA, curframe->FrameNum);\n\t}\n\n\t/* Invoke user's callback routine */\n\tif (config->DrawerCallback != NULL) {\n\t\tif ((config->DrawerCallback(NULL, curframe->FrameNum)) != 0) {\n\t\t\treturn (VQAERR_EOF);\n\t\t}\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_MCGABuf - Draws a frame in MCGA format to a buffer.\n*\n* SYNOPSIS\n*     Error = DrawFrame_MCGABuf(VQA)\n*\n*     long DrawFrame_MCGABuf(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Skip frames\n*       - UnLCW frame\n*       - Wait on Update_Enabled (can't use imgbuf til User_Update's done)\n*       - Un-VQ into ImageBuf\n*       - Set the Flipper's CurFrame\n*       - Set Update_Enabled\n*       - Go to next frame\n*       - User_Update:\n*         set Palette from Flipper.CurFrame\n*         copy ImageBuf to screen\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the upper-left\n*     corner of ImageBuf, then copying ImageBuf onto the screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_MCGABuf(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tlong         rc;\n\n\t#ifndef PHARLAP_TNT\n\tunsigned char *scrn;\n\t#else\n\tFARPTR        scrn;\n\t#endif\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t#ifndef PHARLAP_TNT\n\tscrn = drawer->ImageBuf;\n\t#else\n\tFP_SET(scrn, drawer->ImageBuf, 0x14);\n\t#endif\n\n\t/* Un-VQ the image */\n\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, scrn,\n\t\t\tdrawer->BlocksPerRow, drawer->NumRows,\n\t\t\t((VQAHandleP *)vqa)->Header.ImageWidth);\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_MCGABuf - Page flip a buffered MCGA display.\n*\n* SYNOPSIS\n*     PageFlip_MCGABuf(VQA)\n*\n*     void PageFlip_MCGABuf(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successfull, otherwise VQAERR_???\n*\n****************************************************************************/\n\nstatic long PageFlip_MCGABuf(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *pal;\n\tunsigned char *buf;\n\tunsigned char *scrn;\n\tlong          palsize;\n\tlong          slowpal;\n\tlong          imgwidth;\n\tlong          imgheight;\n\n\t/* Derefernce commonly used data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = vqabuf->Flipper.CurFrame;\n\n\t/* Pre-decode 'vqa' for speed */\n\tpal = curframe->Palette;\n\tpalsize = curframe->PaletteSize;\n\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\n\t/* - If this is a palette-set frame:\n\t * - Wait for the vertical blank\n\t * - Set the palette\n\t * - Copy ImageBuf to SEENPAGE:\n\t * - use blit routine if image is smaller than full-screen, since the\n\t *   buffer copy assumes a full-screen image\n\t */\n\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(pal, palsize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)pal, (long)palsize);\n\t\t}\n\t}\n\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\tdrawer->Flags &= (~VQADRWF_SETPAL);\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(drawer->Palette_24, drawer->CurPalSize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)drawer->Palette_24,\n\t\t\t\t\t(long)drawer->CurPalSize);\n\t\t}\n\t}\n\n\t/* Draw image to the screen. */\n\timgwidth = ((VQAHandleP *)vqa)->Header.ImageWidth;\n\timgheight = ((VQAHandleP *)vqa)->Header.ImageHeight;\n\tbuf = drawer->ImageBuf;\n\n\t#ifndef PHARLAP_TNT\n\tscrn = (unsigned char *)0xA0000;\n\t#endif\n\n\tif ((imgwidth < 320) || (imgheight < 200)) {\n\t\t#ifndef PHARLAP_TNT\n\t\tscrn += drawer->ScreenOffset;\n\t\t#else\n\t\tscrn = (unsigned char *)drawer->ScreenOffset;\n\t\t#endif\n\n\t\tMCGA_Blit(buf, scrn, imgwidth, imgheight);\n\t} else {\n\t\tMCGA_BufferCopy(buf, NULL);\n\t}\n\n\t/* Invoke user's callback routine */\n\tif (config->DrawerCallback != NULL) {\n\t\tif ((config->DrawerCallback(NULL, curframe->FrameNum)) != 0) {\n\t\t\treturn (VQAERR_EOF);\n\t\t}\n\t}\n\n\treturn (0);\n}\n#endif /* VQAMCGA_ON */\n\n\n#if(VQAVESA_ON)\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_VESA640 - Draws a frame in VESA 640 format.\n*\n* SYNOPSIS\n*     Error = DrawFrame_VESA640(VQA)\n*\n*     long DrawFrame_VESA640(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_VESA640(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tlong         rc;\n\n\t#ifndef PHARLAP_TNT\n\tunsigned char *scrn;\n\t#else\n\tFARPTR        scrn;\n\t#endif\n\n\t/* Dereference data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\t}\n\n\t/* Dereference current frame. */\n\tcurframe = drawer->CurFrame;\n\n\t/* Wait for Update_Enabled to be set low */\n \tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tvqabuf->Drawer.WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t#ifndef PHARLAP_TNT\n\tscrn = drawer->ImageBuf + drawer->ScreenOffset;\n\t#else\n\tFP_SET(scrn, drawer->ImageBuf + drawer->ScreenOffset, 0x14);\n\t#endif\n\n\t/* Un-VQ the image */\n\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, scrn,\n\t\t\tdrawer->BlocksPerRow, drawer->NumRows, drawer->ImageWidth);\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_VESA320_32K - Draws a frame in VESA 320 format.\n*\n* SYNOPSIS\n*     Error = DrawFrame_VESA320_32K(VQA)\n*\n*     long DrawFrame_VESA320_32K(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_VESA320_32K(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tVQAConfig    *config;\n\tlong         rc;\n\tlong         grain;\n\n\t/* Dereference data members for quicker access. */\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* Dereference current frame. */\n\t\tcurframe = drawer->CurFrame;\n\n\t\t/* Translate palette to 15-bit */\n\t\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\t\tTranslatePalette(curframe->Palette, drawer->Palette_15,\n\t\t\t\t\tcurframe->PaletteSize);\n\t\t}\n\t\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\t\tTranslatePalette(drawer->Palette_24, drawer->Palette_15,\n\t\t\t\t\tdrawer->CurPalSize);\n\t\t}\n\n\t\t/* UnVQ directly to screen */\n\t\tgrain = ((VESAModeInfo *)(drawer->Display->Extended))->WinSize\n\t\t\t\t/ ((VESAModeInfo *)(drawer->Display->Extended))->WinGranularity;\n\n\t\t#ifndef PHARLAP_TNT\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tdrawer->Palette_15, grain, 0, 0);\n\t\t#else\n\t\t{\n\t\tFARPTR temp;\n\n\t\tFP_SET(temp, drawer->Palette_15, 0x14);\n\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, temp,\n\t\t\t\tgrain, 0, 0);\n\t\t}\n\t\t#endif\n\n\t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tif ((config->DrawerCallback(0, curframe->FrameNum)) != 0) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Wait for VQ_Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_VESA320_32KBuf - Draws a frame in VESA320_32K format to a\n*                                buffer.\n*\n* SYNOPSIS\n*     Error = DrawFrame_VESA320_32KBuf(VQA)\n*\n*     long DrawFrame_VESA320_32KBuf(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_VESA320_32KBuf(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tVQAConfig    *config;\n\tlong         rc;\n\tlong         grain;\n\n\t/* Dereference data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = drawer->CurFrame;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* UnVQ buffered mode */\n\t\t#ifndef PHARLAP_TNT\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tdrawer->ImageBuf, drawer->BlocksPerRow, drawer->NumRows,\n\t\t\t\t((VQAHandleP *)vqa)->Header.image_width);\n\t\t#else\n\t\t{\n\t\tFARPTR scrn;\n\n\t\tFP_SET(scrn, drawer->ImageBuf, 0x14);\n\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, scrn,\n\t\t\t\tdrawer->BlocksPerRow, drawer->NumRows,\n\t\t\t\t((VQAHandleP *)vqa)->Header.image_width);\n\t\t}\n\t\t#endif\n\n\t\t/* Translate the palette to 15-bit */\n\t\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\t\tTranslatePalette(curframe->Palette, drawer->Palette_15,\n\t\t\t\t\tcurframe->PaletteSize);\n\t\t}\n\t\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\t\tTranslatePalette(drawer->Palette_24, drawer->Palette_15,\n\t\t\t\t\tdrawer->CurPalSize);\n\t\t}\n\n\t\t/* Copy the buffer */\n\t\tgrain = ((VESAModeInfo *)(drawer->Display->Extended))->WinSize\n\t\t\t\t/ ((VESAModeInfo *)(drawer->Display->Extended))->WinGranularity;\n\n\t\tBuf_320x200_To_VESA_32K(drawer->ImageBuf, drawer->Palette_15, grain);\n\n \t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tif ((config->DrawerCallback(0, curframe->FrameNum)) != 0) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t\tdrawer->WaitsOnFlipper++;\n\t}\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_VESA - Page flip VESA display.\n*\n* SYNOPSIS\n*     PageFlip_VESA(VQA)\n*\n*     void PageFlip_VESA(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void PageFlip_VESA(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *pal;\n\tlong          palsize;\n\tlong          slowpal;\n\tlong          grain;\n\n\t/* Dereference date members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = vqabuf->Flipper.CurFrame;\n\n\t/* Pre-decode 'vqa' for speed */\n\tpal = curframe->Palette;\n\tpalsize = curframe->PaletteSize;\n\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\n\t/* Set the palette */\n\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(pal, palsize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)pal, (long)palsize);\n\t\t}\n\t}\n\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\tdrawer->Flags &= (~VQADRWF_SETPAL);\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(drawer->Palette_24, drawer->CurPalSize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)drawer->Palette_24,\n\t\t\t\t\t(long)drawer->CurPalSize);\n\t\t}\n\t}\n\n\t/* Copy the buffer */\n\tgrain = ((VESAModeInfo *)(drawer->Display->Extended))->WinSize\n\t\t\t/ ((VESAModeInfo *)(drawer->Display->Extended))->WinGranularity;\n\n\tswitch (((VQAHandleP *)vqa)->Header.image_width) {\n\t\tcase 320:\n\t\t\tif (config->DrawFlags & VQACFGF_SCALEX2) {\n\t\t\t\tBuf_320x200_To_VESA_640x400(drawer->ImageBuf, grain);\n\t\t\t} else {\n\t\t\t\tBuf_320x200_To_VESA_320x200(drawer->ImageBuf, grain);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tVESA_Blit_640x480(drawer->Display, drawer->ImageBuf, drawer->X1,\n\t\t\t\t\tdrawer->Y1, ((VQAHandleP *)vqa)->Header.image_width,\n\t\t\t\t\t((VQAHandleP *)vqa)->Header.image_height);\n\t\t\tbreak;\n\t}\n\n\t/* Invoke user's callback routine */\n\tif (config->DrawerCallback != NULL) {\n\t\tif ((config->DrawerCallback(drawer->ImageBuf, curframe->FrameNum)) != 0) {\n\t\t\treturn (VQAERR_EOF);\n\t\t}\n\t}\n}\n#endif /* VQAVESA_ON */\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_Buffer - Draw a frame to a buffer.\n*\n* SYNOPSIS\n*     Error = DrawFrame_Buffer(VQA)\n*\n*     long DrawFrame_Buffere(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQA handle.\n*\n* RESULT\n*     Error - 0 if successful, otherwise VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_Buffer(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tVQAConfig    *config;\n\tlong         rc;\n\n\t#ifndef PHARLAP_TNT\n\tunsigned char *buff;\n\t#else\n\tFARPTR        buff;\n\t#endif\n\n\t/* Dereference data members for quicker access. */\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\t}\n \n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t#ifndef PHARLAP_TNT\n\tbuff = (unsigned char *)(drawer->ImageBuf + drawer->ScreenOffset);\n\t#else\n\tFP_SET(buff, drawer->ImageBuf + drawer->ScreenOffset, 0x14);\n\t#endif\n\n\t/* Un-VQ the image */\n\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, buff,\n\t\t\tdrawer->BlocksPerRow, drawer->NumRows, drawer->ImageWidth);\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Invoke user's callback routine */\n\tif (config->DrawerCallback != NULL) {\n\t\tif ((config->DrawerCallback(drawer->ImageBuf, curframe->FrameNum)) != 0) {\n\t\t\treturn (VQAERR_EOF);\n\t\t}\n\t}\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     UnVQ_Nop - Do nothing UnVQ.\n*\n* SYNOPSIS\n*     UnVQ_Nop(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n*\n*     void UnVQ_Nop(unsigned char *, unsigned char *, unsigned char *,\n*                   unsigned long, unsigned long, unsigned long);\n* FUNCTION\n*\n* INPUTS\n*     Codebook - Not used. (Prototype placeholder)\n*     Pointers - Not used. (Prototype placeholder)\n*     Buffer   - Not used. (Prototype placeholder)\n*     BPR      - Not used. (Prototype placeholder)\n*     Rows     - Not used. (Prototype placeholder)\n*     BufWidth - Not used. (Prototype placeholder)\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\n#ifndef PHARLAP_TNT\nstatic void cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth)\n#else\nstatic void cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth)\n#endif\n{\n\t/* Suppress compiler warnings */\n\tcodebook = codebook;\n\tpointers = pointers;\n\tbuffer = buffer;\n\tblocksperrow = blocksperrow;\n\tnumrows = numrows;\n\tbufwidth = bufwidth;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_Nop - Do nothing page flip.\n*\n* SYNOPSIS\n*     PageFlip_Nop(VQA)\n*\n*     void PageFlip_Nop(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQA handle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic long PageFlip_Nop(VQAHandle *vqa)\n{\n\tvqa = vqa;\n\n\treturn (0);\n}\n\n\n#if(0)\n/****************************************************************************\n*\n* NAME\n*     Mask_Rect - Sets non-drawable rectangle in image.\n*\n* SYNOPSIS\n*     Mask_Rect(VQA, X1, Y1, X2, Y2)\n*\n*     void Mask_Rect(VQAHandle *, unsigned long, unsigned long,\n*                    unsigned long, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQA handle.\n*     X1  - X coordinate of upper-left corner\n*     Y1  - Y coordinate of upper-left corner\n*     X2  - X coordinate of lower-right corner\n*     Y2  - Y coordinate of lower-right corner\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Mask_Rect(VQAHandle *vqa, unsigned long x1, unsigned long y1,\n\t\tunsigned long x2, unsigned long y2)\n{\n\tVQAData   *vqabuf;\n\tVQADrawer *drawer;\n\tVQAHeader *header;\n\tlong      blocks_per_row;\n\n\t/* Dereference data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\theader = &((VQAHandleP *)vqa)->Header;\n\tdrawer =  &vqabuf->Drawer;\n\n\t/* Clip coords to image size */\n\tif (x1 < vqabuf->Drawer.X1) {\n\t\tx1 = vqabuf->Drawer.X1;\n\t}\n\n\tif (y1 < vqabuf->Drawer.Y1) {\n\t\ty1 = vqabuf->Drawer.Y1;\n\t}\n\n\tif (x2 > vqabuf->Drawer.X2) {\n\t\tx2 = vqabuf->Drawer.X2;\n\t}\n\n\tif (y2 > vqabuf->Drawer.Y2) {\n\t\ty2 = vqabuf->Drawer.Y2;\n\t}\n\n\t/* Convert pixel coords to block coords */\n\tx1 /= header->block_width;\n\tx2 /= header->block_width;\n\ty1 /= header->block_height;\n\ty2 /= header->block_height;\n\n\t/* Compute the mask values */\n\tblocks_per_row = (header->image_width / header->block_width);\n\tvqabuf->Drawer.MaskStart = blocks_per_row * y1 + x1;\n\n\tif (x1 == x2) {\n\t\tdrawer->MaskWidth = 0;\n\t} else {\n\t\tdrawer->MaskWidth = x2 - x1 + 1;\n\t}\n\n\tif (y1 == y2) {\n\t\tdrawer->MaskHeight = 0;\n\t} else {\n\t\tdrawer->MaskHeight = y2 - y1 + 1;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Mask_Pointers - Mask vector pointer that are in the mask rectangle.\n*\n* SYNOPSIS\n*     Mask_Pointers(VQAData)\n*\n*     void Mask_Pointers(VQAData *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQAData - Pointer to VQAData structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Mask_Pointers(VQAData *vqabuf)\n{\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tunsigned long *ptr;\n\tunsigned long i,j;\n\tunsigned long start;\n\n\t/* Dereference data members for quicker access. */\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = drawer->CurFrame;\n\tstart = vqabuf->Drawer.MaskStart;\n\n\tfor (i = 0; i < drawer->MaskHeight; i++) {\n\t\tptr = (unsigned long *)(curframe->Pointers) + start;\n\n\t\tfor (j = 0; j < drawer->MaskWidth; j++) {\n\t\t\tptr[j] = VQA_MASK_POINTER;\n\t\t}\n\n\t\tstart += drawer->BlocksPerRow;\n\t}\n}\n#endif\n\n"
  },
  {
    "path": "VQ/VQA32/DSTREAM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQAPlay32 library.\n*\n* FILE\n*     dstream.c\n*\n* DESCRIPTION\n*     DOS IO handler.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 10, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_InitAsDOS - Initialize IO with the standard DOS handler.\n*\n* PRIVATE\n*     VQADOSHandler - Standard DOS IO handler.\n*\n****************************************************************************/\n\n#include <fcntl.h>\n#include <io.h>\n#include \"vqaplayp.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\nstatic long VQADOSHandler(VQAHandle *vqa, long action, void *buffer,\n\t\tlong nbytes);\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_InitAsDOS - Initialize IO with the standard DOS handler.\n*\n* SYNOPSIS\n*     VQA_InitAsDOS(VQA)\n*\n*     VQA_InitAsDOS(VQAHandle *);\n*\n* FUNCTION\n*     Initialize the IO of the specified handle as a standard DOS access.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle to initialize as DOS.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_InitAsDOS(VQAHandle *vqa)\n{\n\t((VQAHandleP *)vqa)->IOHandler = VQADOSHandler;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQADOSHandler - Standard DOS IO handler.\n*\n* SYNOPSIS\n*     Error = VQADOSHandler(VQA, Action, Buffer, NBytes)\n*\n*     unsigned long VQADOSHandler(VQAHandle *, long, long, long);\n*\n* FUNCTION\n*      Perform the requested action on the standard DOS file system.\n*\n* INPUTS\n*      VQA    - VQAHandle to operate on.\n*      Action - Action to perform.\n*      Buffer - Buffer to Read/Write to/from.\n*      NBytes - Number of bytes to operate on.\n*\n* RESULT\n*      Error - 0 if successful, otherwise error.\n*\n****************************************************************************/\n\nstatic long VQADOSHandler(VQAHandle *vqa, long action, void *buffer,\n\t\tlong nbytes)\n{\n\tlong fh;\n\tlong error;\n\n\tfh = vqa->VQAio;\n\n\t/* Perform the action specified by the IO command */\n\tswitch (action) {\n\n\t\t/* VQACMD_READ means read NBytes and place it in the memory\n\t\t * pointed to by Buffer.\n\t\t *\n\t\t * Any error code returned will be remapped by VQA library into\n\t\t * VQAERR_READ.\n\t\t */\n\t\tcase VQACMD_READ:\n\t\t\terror = (read(fh, buffer, nbytes) != nbytes);\n\t\t\tbreak;\n\n\t\t/* VQACMD_WRITE is analogous to VQACMD_READ.\n\t\t *\n\t\t * Writing is not allowed to the VQA file, VQA library will remap the\n\t\t * error into VQAERR_WRITE.\n\t\t */\n\t\tcase VQACMD_WRITE:\n\t\t\terror = 1;\n\t\t\tbreak;\n\n\t\t/* VQACMD_SEEK asks that you perform a seek relative to the current\n\t\t * position. NBytes is a signed number, indicating seek direction\n\t\t * (positive for forward, negative for backward). Buffer has no meaning\n\t\t * here.\n\t\t *\n\t\t * Any error code returned will be remapped by VQA library into\n\t\t * VQAERR_SEEK.\n\t\t */\n\t\tcase VQACMD_SEEK:\n\t\t\terror = (lseek(fh, nbytes, (long)buffer) == -1);\n\t\t\tbreak;\n\n\t\t/* VQACMD_OPEN asks that you open the file for access. */\n\t\tcase VQACMD_OPEN:\n\t\t\terror = open((char *)buffer, (O_RDONLY|O_BINARY));\n\n\t\t\tif (error != -1) {\n\t\t\t\tvqa->VQAio = error;\n\t\t\t\terror = 0;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase VQACMD_CLOSE:\n\t\t\tclose(fh);\n\t\t\terror = 0;\n\t\t\tbreak;\n\n\t\t/* VQACMD_INIT means to prepare your IO for reading. This is used for\n\t\t * certain IOs that can't be read immediately upon opening, and need\n\t\t * further preparation. This operation is allowed to fail; the error code\n\t\t * will be returned directly to the client.\n\t\t */\n\t\tcase VQACMD_INIT:\n\n\t\t/* IFFCMD_CLEANUP means to terminate the transaction with the associated\n\t\t * IO. This is used for IOs that can't simply be closed. This operation\n\t\t * is not allowed to fail; any error returned will be ignored.\n\t\t */\n\t\tcase VQACMD_CLEANUP:\n\t\t\terror = 0;\n\t\t\tbreak;\n\t}\n\n\treturn (error);\n}\n\n"
  },
  {
    "path": "VQ/VQA32/LOADER.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*---------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     loader.c\n*\n* DESCRIPTION\n*     Stream loading and pre-processing.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     February 23, 1995\n*\n*---------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_Open      - Open a VQA file to play.\n*     VQA_Close     - Close an opened VQA file.\n*     VQA_LoadFrame - Load the next video frame from the VQA data stream.\n*\n* PRIVATE\n*     AllocBuffers   - Allocates the numerous VQA play buffers\n*     FreeBuffers    - Frees the VQA play buffers\n*     Load_FINF      - Loads the Frame Info Table.\n*     Load_VQHD      - Loads a VQA Header.\n*     Load_CBF0      - Loads a full, uncompressed codebook\n*     Load_CBFZ      - Loads a full, compressed codebook\n*     Load_CBP0      - Loads a partial uncompressed codebook\n*     Load_CBPZ      - Loads a partial compressed codebook\n*     Load_CPL0      - Loads an uncompressed palette\n*     Load_CPLZ      - Loads a compressed palette\n*     Load_VPT0      - Loads uncompressed pointers\n*     Load_VPTZ      - Loads compressed pointers\n*     Load_VQF       - Loads a VQ Frame chunk\n*     Load_SND0      - Loads an uncompressed sound chunk\n*     Load_SND1      - Loads a compressed sound chunk\n*     Copy_SND       - Copies data from Audio Temp buf into Audio play buf\n*     Load_VOC_Block - Loads blocks from separate VOC file, if needed.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <fcntl.h>\n#include <io.h>\n#include <malloc.h>\n#include <mem.h>\n#include <dos.h>\n#include \"vq.h\"\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\ntypedef struct _ChunkHeader {\n\tunsigned long id;\n\tunsigned long size;\n} ChunkHeader;\n\nstatic VQAData *AllocBuffers(VQAHeader *header, VQAConfig *config);\nstatic void FreeBuffers(VQAData *vqa, VQAConfig *config);\nstatic long Load_VQF(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_FINF(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_VQHD(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CBF0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CBFZ(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CBP0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CBPZ(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CPL0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CPLZ(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_VPT0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_VPTZ(VQAHandleP *vqap, unsigned long iffsize);\n\n#if(VQAAUDIO_ON)\nstatic long Load_SND0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_SND1(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_SND2(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Copy_SND(VQAHandleP *vqap);\n\n#if(VQAVOC_ON && VQAAUDIO_ON)\nstatic void Load_VOC_Block(VQAHandleP *vqap);\n#endif /* VQAVOC_ON */\n\n#endif /* VQAAUDIO_ON */\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Open - Open a VQA file to play.\n*\n* SYNOPSIS\n*     Error = VQA_Open(VQAHandle, Name, Config)\n*\n*     short VQA_Open(VQAHandle *, char *, VQAConfig *);\n*\n* FUNCTION\n*     - Open a VQA file for reading.\n*     - Validate that it is an IFF file, of the VQA type.\n*     - Read the VQA header.\n*     - Open a VOC file for playback, if requested.\n*     - Set the Loader's frame rate, if the caller's Config structure's\n*       FrameRate is set to -1\n*     - Set the Drawer's frame rate, if the caller's Config structure's\n*       DrawRate is set to -1\n*\n* INPUTS\n*     VQAHandle - Pointer to initialized handle. Obtained by VQA_Alloc().\n*     Name      - Pointer to name of VQA file to open.\n*     Config    - Pointer to initialized VQA configuration structure.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_ error code.\n*\n****************************************************************************/\n\nlong VQA_Open(VQAHandle *vqa, char const *filename, VQAConfig *config)\n{\n\tVQAHandleP  *vqap;\n\tVQAHeader   *header;\n\tChunkHeader chunk;\n\tlong        max_frm_size;\n\tlong        i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqap = (VQAHandleP *)vqa;\n\theader = &vqap->Header;\n\n\t/*-------------------------------------------------------------------------\n\t * VERIFY VALIDITY OF VQA FILE.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Open the file. */\n\tif (vqap->StreamHandler(vqa, VQACMD_OPEN, (void *)filename, 0)) {\n\t\treturn (VQAERR_OPEN);\n\t}\n\n\t/* Read the file ID & Size */\n\tif (vqap->StreamHandler(vqa, VQACMD_READ, &chunk, 8)) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Verify an IFF FORM */\n\tif ((chunk.id != ID_FORM) || (chunk.size == 0)) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_NOTVQA);\n\t}\n\n\t/* Read in WVQA ID */\n\tif (vqap->StreamHandler(vqa, VQACMD_READ, &chunk, 4)) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Verify VQA */\n\tif (chunk.id != ID_WVQA) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_NOTVQA);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * READ IN THE VQA HEADER.\n\t *-----------------------------------------------------------------------*/\n\tif (vqap->StreamHandler(vqa, VQACMD_READ, &chunk, 8)) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_READ);\n\t}\n\n\tchunk.size = REVERSE_LONG(chunk.size);\n\n\t/* Is this a valid VQA header? */\n\tif ((chunk.id != ID_VQHD) || (chunk.size != sizeof(VQAHeader))) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_NOTVQA);\n\t}\n\n\t/* Read the header data. */\n\tif (vqap->StreamHandler(vqa, VQACMD_READ, header, PADSIZE(chunk.size))) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE PLAYERS CONFIGURATION\n\t *-----------------------------------------------------------------------*/\n\n\t/* Use the clients configuration if they provided one. */\n\tif (config != NULL) {\n\t\tmemcpy(&vqap->Config, config, sizeof(VQAConfig));\n\t} else {\n\t\tVQA_DefaultConfig(&vqap->Config);\n\t}\n\n\t/* Use the internal configuration structure from now on. */\n\tconfig = &vqap->Config;\n\n\tif (config->ImageWidth == -1) {\n\t\tconfig->ImageWidth = header->ImageWidth;\n\t}\n\n\tif (config->ImageHeight == -1) {\n\t\tconfig->ImageHeight = header->ImageHeight;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE THE BUFFERS THAT WE NEED TO PLAY THE VQA.\n\t *-----------------------------------------------------------------------*/\n\tif ((vqap->VQABuf = AllocBuffers(header, config)) == NULL) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_NOMEM);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * SET THE LOADER AND DRAWER PLAYBACK RATES.\n\t *-----------------------------------------------------------------------*/\n\n\t/* If Loaders frame rate is -1 then use the value from the header. */\n\tif (config->FrameRate == -1) {\n\t\tconfig->FrameRate = header->FPS;\n\t}\n\n\t/* If Drawers frame rate is -1 then use the value from the header, which\n\t * will result in a \"variable\" frame rate.\n\t */\n\tif (config->DrawRate == -1) {\n\t\tconfig->DrawRate = header->FPS;\n\t}\n\n\t/* Finally, if the DrawRate was set to -1 or 0 (ie MaxRate contained bogus\n\t * values), set it to the header value.\n\t */\n\tif ((config->DrawRate == -1) || (config->DrawRate == 0)) {\n\t\tconfig->DrawRate = header->FPS;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE VIDEO SYSTEM IF WE ARE REQUIRED TO HANDLE THAT.\n\t *-----------------------------------------------------------------------*/\n\t#if(VQAVIDEO_ON)\n\tif ((vqap->VQABuf->Drawer.Display = SetVideoMode(config->Vmode)) == 0) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_VIDEO);\n\t}\n\n\t/* Set the VBIBit polarity. */\n\tvqap->VQABuf->VBIBit = GetVBIBit();\n\t#else\n\tif (config->VBIBit == -1) {\n\t\tconfig->VBIBit = TestVBIBit();\n\t}\n\n\tvqap->VQABuf->VBIBit = config->VBIBit;\n\t#endif /* VQAVIDEO_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * AUDIO TRACK OVERRIDE (VOC FILE)\n\t *-----------------------------------------------------------------------*/\n\n\t/* Open VOC file if one is requested. */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (config->VocFile != NULL) {\n\t\tvqap->vocfh = open(config->VocFile, (O_RDONLY|O_BINARY));\n\t} else {\n\t\tvqap->vocfh = -1;\n\t}\n\n\t/* Make sure we won't try to play audio. */\n\tif ((vqap->vocfh == -1) && ((header->Flags & VQAHDF_AUDIO) == 0)) {\n\t\tconfig->OptionFlags &= (~VQAOPTF_AUDIO);\n\t}\n\t#else  /* VQAVOC_ON */\n\n\t/* If the movie does not contain an audio track make sure we won't try\n\t * to play one.\n\t */\n\tif (((header->Flags & VQAHDF_AUDIO) == 0)) {\n\t\tconfig->OptionFlags &= (~VQAOPTF_AUDIO);\n\t}\n\t#endif /* VQAVOC_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE AUDIO PLAYBACK/TIMING SYSTEM.\n\t *-----------------------------------------------------------------------*/\n\t#if(VQAAUDIO_ON)\n\tif (config->OptionFlags & VQAOPTF_AUDIO) {\n\n\t\t/* Open HMI audio resource for playback. */\n\t\tif (VQA_OpenAudio(vqap)) {\n\t\t\tVQA_Close(vqa);\n\t\t\treturn (VQAERR_AUDIO);\n\t\t}\n\t}\n\n\tif (!(config->OptionFlags & VQAOPTF_AUDIO)\n\t\t\t|| (config->TimerMethod == VQA_TMETHOD_INT)) {\n\n\t\t/* Start HMI timer system for timing. */\n\t\tif (VQA_StartTimerInt((config->OptionFlags & VQAOPTF_HMIINIT))) { \n\t\t\tVQA_Close(vqa);\n\t\t\treturn (VQAERR_AUDIO);\n\t\t}\n\t}\n\t#endif /* VQAAUDIO_ON */\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Close - Close an opened VQA file.\n*\n* SYNOPSIS\n*     VQA_Close(VQAHandle)\n*\n*     void VQA_Close(VQAHandle *);\n*\n* FUNCTION\n*     Close the file that was opened with VQA_Open().\n*\n* INPUTS\n*     VQAHandle - Pointer VQAHandle to close.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Close(VQAHandle *vqa)\n{\n\t/* Restore video mode to text. */\n\t#if(VQAVIDEO_ON)\n\tSetVideoMode(TEXT);\n\t#endif /* VQAVIDEO_ON */\n\n\t/* Shutdown audio/timing system. */\n\t#if(VQAAUDIO_ON)\n\tif (((VQAHandleP *)vqa)->Config.OptionFlags & VQAOPTF_AUDIO) {\n\t\tVQA_CloseAudio();\n\t} else {\n\t\tVQA_StopTimerInt();\n\t}\n\t#endif /* VQAAUDIO_ON */\n\n\t/* Free memory */\n\tif (((VQAHandleP *)vqa)->VQABuf != NULL) {\n\t\tFreeBuffers(((VQAHandleP *)vqa)->VQABuf, &((VQAHandleP *)vqa)->Config);\n\t}\n\n\t/* Close the VOC override file if one was opened */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((VQAHandleP *)vqa)->vocfh != -1) {\n\t\tclose(((VQAHandleP *)vqa)->vocfh);\n\t}\n\t#endif /* VQAVOC_ON */\n\n\t/* Close the VQA file */\n\t((VQAHandleP *)vqa)->StreamHandler(vqa, VQACMD_CLOSE, NULL, 0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_LoadFrame - Load the next video frame from the VQA data stream.\n*\n* SYNOPSIS\n*     Error = VQA_LoadFrame(VQAHandle)\n*\n*     short VQA_LoadFrame(VQAHandle *);\n*\n* FUNCTION\n*     The codebook is split up such that the last frame of every group gets\n*     a new, complete codebook, ready for the next group.  The first codebook\n*     in the VQA is a full codebook, and goes with the first frame's data.\n*     Partial codebooks are stored per frame after that, and they add up to\n*     a full codebook just before the first frame for the next group is read.\n*\n*     (Currently, this routine can read either the older non-frame-grouped\n*     VQA file format, or the new frame-chunk format.  For the older format,\n*     it's assumed that the last chunk in a frame is the pointer data.)\n*\n*     This routine also does a sort of \"cooperative multitasking\".  If the\n*     Loader hits a \"wait state\" where it has to wait on the audio to finish\n*     playing before it can continue to load, it sets a \"sleep\" flag and\n*     just returns.  The sleep flag is checked on entry to see if it needs\n*     to jump to the proper execution point. This may improve performance on\n*     some platforms, but it also allows the Loader to be called regardless\n*     of the size of the buffers; if the buffers fill up or the audio fails\n*     to play, the Loader won't just get stuck.\n*\n* INPUTS\n*     VQAHandle - Pointer to VQAHandle structure.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nlong VQA_LoadFrame(VQAHandle *vqa)\n{\n\tVQAHandleP    *vqap;\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQAFrameNode  *curframe;\n\tChunkHeader   chunk;\n\tunsigned long iffsize;\n\tlong          frame_loaded = 0;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqap = (VQAHandleP *)vqa;\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\tcurframe = loader->CurFrame;\n\n\t/* If we're reading audio from a VOC file then service that requirement. */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (vqap->vocfh != -1) {\n\t\tLoad_VOC_Block(vqap);\n\t}\n\t#endif /* VQAAUDIO_ON & VQAVOC_ON */\n\n\t/* If no buffer is available for loading then return. This allows the\n\t * drawer to service one of the buffers more readily. (We'll wait for one\n\t * to free up).\n\t */\n\tif (curframe->Flags & VQAFRMF_LOADED) {\n\t\tloader->WaitsOnDrawer++;\n\t\treturn (VQAERR_NOBUFFER);\n\t}\n\n\t/* If we're not sleeping, initialize */\n\tif (!(vqabuf->Flags & VQADATF_LSLEEP)) {\n\t\tframe_loaded = 0;\n\t\tloader->FrameSize = 0;\n\n\t\t/* Initialize the codebook ptr for the frame we're about to load:\n\t\t * (This frame's codebook is the last full codebook; we have to init it\n\t\t * now, because if we're on the last frame in a group, we'll get a new\n\t\t * FullCB pointer.)\n\t\t */\n\t\tcurframe->Codebook = loader->FullCB;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * THE MAIN LOADER LOOP\n\t *-----------------------------------------------------------------------*/\n\twhile (frame_loaded == 0) {\n\n\t\t/* Read new chunk, only if we're not sleeping */\n\t\tif (!(vqabuf->Flags & VQADATF_LSLEEP)) {\n\n\t\t\t/* Read chunk ID */\n\t\t\tif (vqap->StreamHandler(vqa, VQACMD_READ, &chunk, 8)) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\n\t\t\tiffsize = REVERSE_LONG(chunk.size);\n\t\t\tloader->FrameSize += iffsize;\n\t\t}\n\n\t\t/* Handle each chunk type */\n\t\tswitch (chunk.id) {\n\n\t\t\t/* VQ Normal Frame */\n\t\t\tcase ID_VQFR:\n\t\t\t\tif (Load_VQF(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* VQ Key Frame */\n\t\t\tcase ID_VQFK:\n\t\t\t\tif (Load_VQF(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as being key. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_KEY;\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* Frame Info Table */\n\t\t\tcase ID_FINF:\n\t\t\t\tif (Load_FINF(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* VQA Header */\n\t\t\tcase ID_VQHD:\n\t\t\t\tif (Load_VQHD(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Full uncompressed codebook */\n\t\t\tcase ID_CBF0:\n\t\t\t\tif (Load_CBF0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Full compressed codebook */\n\t\t\tcase ID_CBFZ:\n\t\t\t\tif (Load_CBFZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Partial uncompressed codebook */\n\t\t\tcase ID_CBP0:\n\t\t\t\tif (Load_CBP0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Partial compressed codebook */\n\t\t\tcase ID_CBPZ:\n\t\t\t\tif (Load_CBPZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed palette */\n\t\t\tcase ID_CPL0:\n\t\t\t\tif (Load_CPL0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as having a palette. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_PALETTE;\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed palette */\n\t\t\tcase ID_CPLZ:\n\t\t\t\tif (Load_CPLZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as having a palette. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_PALETTE;\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed pointer data */\n\t\t\tcase ID_VPT0:\n\t\t\t\tif (Load_VPT0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed pointer data */\n\t\t\tcase ID_VPTZ:\n\t\t\tcase ID_VPTD:\n\t\t\t\tif (Load_VPTZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* Pointer data Key (Must draw) */\n\t\t\tcase ID_VPTK:\n\t\t\t\tif (Load_VPTZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as being key. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_KEY;\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed audio frame.\n\t\t\t *\n\t\t\t *  - Make sure the sound load buffer (Audio.TempBuf) is empty; if not\n\t\t\t *    go into a sleep state.\n\t\t\t *  - Load the data into TempBuf.\n\t\t\t */\n\t\t\t#if(VQAAUDIO_ON)\n\t\t\tcase ID_SND0:\n\n\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\tif (Copy_SND(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t} else {\n\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t}\n\n\t\t\t\t/* Load an uncompressed audio frame. */\n\t\t\t\tif (Load_SND0(vqap, iffsize) != 0) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed audio frame.\n\t\t\t *\n\t\t\t *  - Make sure the sound load buffer (Audio.TempBuf) is empty; if not\n\t\t\t *    go into a sleep state.\n\t\t\t *  - Load the data into TempBuf.\n\t\t\t */\n\t\t\tcase ID_SND1:\n\n\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\tif (Copy_SND(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t} else {\n\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t}\n\n\t\t\t\t/* Load a compressed audio frame. */\n\t\t\t\tif (Load_SND1(vqap, iffsize) != 0) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* HMI ADPCM compressed audio frame.\n\t\t\t *\n\t\t\t *  - Make sure the sound load buffer (Audio.TempBuf) is empty; if not\n\t\t\t *    go into a sleep state.\n\t\t\t *  - Load the data into TempBuf.\n\t\t\t */\n\t\t\tcase ID_SND2:\n\n\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\tif (Copy_SND(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t} else {\n\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t}\n\n\t\t\t\t/* Load a compressed audio frame. */\n\t\t\t\tif (Load_SND2(vqap, iffsize) != 0) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\t/* Skip any unknown chunks. */\n\t\t\tdefault:\n\t\t\t\tif (vqap->StreamHandler(vqa, VQACMD_SEEK, NULL, PADSIZE(iffsize))) {\n\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/* Update maximum frame size stat. */\n\tif ((loader->CurFrameNum>0) && (loader->FrameSize>loader->MaxFrameSize)) {\n\t\tloader->MaxFrameSize = loader->FrameSize;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * SET UP THE FRAME FOR DRAWING.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Set the frame # */\n\tcurframe->FrameNum = loader->CurFrameNum;\n\tloader->CurFrameNum++;\n\n\t/* Update data for mono output */\n\tloader->LastFrameNum = loader->CurFrameNum;\n\n\t/* Loader is finished with this frame; tell Drawer to draw it */\n\tcurframe->Flags |= VQAFRMF_LOADED;\n\tloader->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     AllocBuffers - Allocate VQA play buffers.\n*\n* SYNOPSIS\n*     VQAData = AllocBuffers(VQAFile)\n*\n*     VQAData *AllocBuffers(VQAFile *);\n*\n* FUNCTION\n*     For those structures that contain buffer pointers (codebook nodes,\n*     frame buffer nodes), enough memory is allocated for both the structure\n*     and its associated buffers, then the buffer pointers are pointed to\n*     the appropriate offset from the structure pointer.  This allows us\n*     to perform only one malloc & free for each node.\n*\n*     Buffers allocated:\n*       - vqa\n*       - vqa->CBData (list)\n*       - vqa->FrameData (list)\n*       - vqa->Drawer.ImageBuf\n*       - vqa->Audio.Buffer\n*       - vqa->Audio.IsLoaded\n*       - vqa->Foff\n*\n* INPUTS\n*     VQAHeader - Pointer to VQAHeader structure.\n*     VQAConfig - Pointer to VQA configuration structure.\n*\n* RESULT\n*     VQAData - Pointer to initialized VQAData structure.\n*\n****************************************************************************/\n\nstatic VQAData *AllocBuffers(VQAHeader *header, VQAConfig *config)\n{\n\tVQAData      *vqa;\n\tVQACBNode    *cbnode;\n\tVQACBNode    *this_cb;\n\tVQAFrameNode *framenode;\n\tVQAFrameNode *this_frame;\n\tlong         i;\n\n\t/* Check the configuration for valid values. */\n\tif ((config->NumCBBufs == 0) || (config->NumFrameBufs == 0)\n\t\t\t|| (config->AudioBufSize < config->HMIBufSize)) {\n\n\t\treturn (NULL);\n\t}\n\n\t/* Allocate the master structure */\n\tif ((vqa = (VQAData *)malloc(sizeof(VQAData))) == NULL) {\n\t\treturn (NULL);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE VQA DATA STRUCTURES.\n\t *\n\t * Pointers are set to NULL initially, and filled in as the buffers are\n\t * allocated.  The Max buffer sizes are computed with 1K of padding,\n\t * and'd with 0xFFFC to make the size divisible by 4, to ensure DWORD\n\t * alignment.\n\t *-----------------------------------------------------------------------*/\n\tmemset(vqa, 0, sizeof(VQAData));\n\tvqa->MemUsed = sizeof(VQAData);\n\tvqa->Drawer.LastTime = (-VQA_TIMETICKS);\n\n\t/* Set maximum codebook size. */\n\tvqa->Max_CB_Size = ((header->CBentries) * header->BlockWidth\n\t\t\t* header->BlockHeight + 250) & 0xFFFC;\n\n\t/* Set maximum palette size. */\n\tvqa->Max_Pal_Size = (768 + 1024) & 0xFFFC;\n\n\t/* Set maximum vector pointers size. */\n\tvqa->Max_Ptr_Size = ((header->ImageWidth / header->BlockWidth)\n\t\t\t* (header->ImageHeight / header->BlockHeight)\n\t\t\t* sizeof(short) + 1024) & 0xFFFC;\n\n\t/* Set the frame number of the frame containing the last codebook. */\n\tvqa->Loader.LastCBFrame = (((header->Frames - 1) / header->Groupsize)\n\t\t\t* header->Groupsize);\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE THE CODEBOOK BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\tfor (i = 0; i < config->NumCBBufs; i++) {\n\n\t\t/* Allocate a codebook node. */\n\t\tcbnode = (VQACBNode *)malloc((sizeof(VQACBNode) + vqa->Max_CB_Size));\n\n\t\t/* If failure then clean up and exit. */\n\t\tif (cbnode == NULL) {\n\t\t\tFreeBuffers(vqa, config);\n\t\t\treturn (NULL);\n\t\t}\n\n\t\t/* Keep count of the memory usage. */\n\t\tvqa->MemUsed += (long)(sizeof(VQACBNode) + vqa->Max_CB_Size);\n\n\t\t/* Initialize the node */\n\t\tmemset(cbnode, 0, sizeof(VQACBNode));\n\t\tcbnode->Buffer = (unsigned char *)cbnode + sizeof(VQACBNode);\n\n\t\t/* Install the node */\n\t\tif (i == 0) {\n\t\t\tvqa->CBData = cbnode;\n\t\t\tthis_cb = cbnode;\n\t\t} else {\n\t\t\tthis_cb->Next = cbnode;\n\t\t\tthis_cb = cbnode;\n\t\t}\n\t}\n\n\t/* Make the list circular */\n\tcbnode->Next = vqa->CBData;\n\n\t/* Install the Codebook list */\n\tvqa->Loader.CurCB = vqa->CBData;\n\tvqa->Loader.FullCB = vqa->CBData;\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE THE FRAME BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\tfor (i = 0; i < config->NumFrameBufs; i++) {\n\t\t\n\t\t/* Allocate a pointer node */\n\t\tframenode = (VQAFrameNode *)malloc((sizeof(VQAFrameNode)\n\t\t\t\t+ vqa->Max_Ptr_Size + vqa->Max_Pal_Size));\n\n\t\t/* If failure then clean up and exit. */\n\t\tif (framenode == NULL) {\n\t\t\tFreeBuffers(vqa, config);\n\t\t\treturn (NULL);\n\t\t}\n\n\t\t/* Keep count of the memory usage. */\n\t\tvqa->MemUsed += (long)(sizeof(VQAFrameNode) + vqa->Max_Ptr_Size\n\t\t\t\t+ vqa->Max_Pal_Size);\n\n\t\t/* Initialize the node */\n\t\tmemset(framenode, 0, sizeof(VQAFrameNode));\n\t\tframenode->Pointers = (unsigned char *)framenode + sizeof(VQAFrameNode);\n\t\tframenode->Palette = (unsigned char *)framenode + sizeof(VQAFrameNode)\n\t\t\t\t+ vqa->Max_Ptr_Size;\n\n\t\tframenode->Codebook = vqa->CBData;\n\n\t\t/* Install the node */\n\t\tif (i == 0) {\n\t\t\tvqa->FrameData = framenode;\n\t\t\tthis_frame = framenode;\n\t\t} else {\n\t\t\tthis_frame->Next = framenode;\n\t\t\tthis_frame = framenode;\n\t\t}\n\t}\n\n\t/* Make the list circular */\n\tframenode->Next = vqa->FrameData;\n\n\t/* Install the Frame Buffer list */\n\tvqa->Loader.CurFrame = vqa->FrameData;\n\tvqa->Drawer.CurFrame = vqa->FrameData;\n\tvqa->Flipper.CurFrame = vqa->FrameData;\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE THE IMAGE BUFFERS IF ONE IS NOT ALREADY PROVIDED.\n\t *-----------------------------------------------------------------------*/\n\tif (config->ImageBuf == NULL) {\n\n\t\t/* Allocate our own buffer. */\n\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\tvqa->Drawer.ImageBuf = (unsigned char *)malloc((header->ImageWidth\n\t\t\t\t\t* header->ImageHeight));\n\n\t\t\t/* If the allocation failed we must free up and exit. */\n\t\t\tif (vqa->Drawer.ImageBuf == NULL) {\n\t\t\t\tFreeBuffers(vqa, config);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\n\t\t\t/* Plugin image buffer information. */\n\t\t\tvqa->Drawer.ImageWidth = header->ImageWidth;\n\t\t\tvqa->Drawer.ImageHeight = header->ImageHeight;\n\t\t\tvqa->MemUsed += (long)(header->ImageWidth * header->ImageHeight);\n\t\t} else {\n\t\t\tvqa->Drawer.ImageWidth = config->ImageWidth;\n\t\t\tvqa->Drawer.ImageHeight = config->ImageHeight;\n\t\t}\n\t} else {\n\n\t\t/* Use caller provided buffer */\n\t\tvqa->Drawer.ImageBuf = config->ImageBuf;\n\t\tvqa->Drawer.ImageWidth = config->ImageWidth;\n\t\tvqa->Drawer.ImageHeight = config->ImageHeight;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE AND INITIALIZE AUDIO BUFFERS AND STRUCTURES.\n\t *-----------------------------------------------------------------------*/\n\t#if(VQAAUDIO_ON)\n\t/* Version 1 VQA's only supported 22050 8 bit mono audio. */\n\tif (header->Version < VQAHD_VER2) {\n\t\tvqa->Audio.SampleRate = 22050U;\n\t\tvqa->Audio.Channels = 1;\n\t\tvqa->Audio.BitsPerSample = 8;\n\t} else {\n\t\tvqa->Audio.SampleRate = header->SampleRate;\n\t\tvqa->Audio.Channels = header->Channels;\n\t\tvqa->Audio.BitsPerSample = header->BitsPerSample;\n\t}\n\n\tif ((config->AudioBufSize == 0) && (config->HMIBufSize == 0)) {\n\t\tvqa->Audio.NumAudBlocks = 0;\n\t} else {\n\t\tvqa->Audio.NumAudBlocks = (config->AudioBufSize / config->HMIBufSize);\n\t}\n\n\tif (config->AudioBufSize > 0) {\n\n\t\t/* Allocate an audio buffer if the user did not provide one. */\n\t\tif (config->AudioBuf == NULL) {\n\t\t\tvqa->Audio.Buffer = (unsigned char *)malloc(config->AudioBufSize);\n\n\t\t\t/* If failure then clean up and exit. */\n\t\t\tif (vqa->Audio.Buffer == NULL) {\n\t\t\t\tFreeBuffers(vqa, config);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\n\t\t\t/* Add audio buffer size to memory usage. */\n\t\t\tvqa->MemUsed += (long)config->AudioBufSize;\n\t\t} else {\n\t\t\tvqa->Audio.Buffer = config->AudioBuf;\n\t\t}\n\n\t\t/* Allocate IsLoaded flags */\n\t\tvqa->Audio.IsLoaded = (short *)malloc(vqa->Audio.NumAudBlocks\n\t\t\t\t* sizeof(short));\n\n\t\t/* If failure then clean up and exit. */\n\t\tif (vqa->Audio.IsLoaded == NULL) {\n\t\t\tFreeBuffers(vqa, config);\n\t\t\treturn (NULL);\n\t\t}\n\n\t\t/* Keep a running total of memory usage. */\n\t\tvqa->MemUsed += (long)(vqa->Audio.NumAudBlocks * sizeof(short));\n\n\t\t/* Initalize audio frames is loaded flags to false. */\n\t\tmemset(vqa->Audio.IsLoaded,0,vqa->Audio.NumAudBlocks * sizeof(short));\n\n\t\t/* Temp buffer */\n\t\t#if(0) // DENZIL\n\t\tvqa->Audio.TempBuf = (unsigned char *)malloc(VQA_AUD_TEMPSIZE);\n\t\t#else\n\n\t\t/* Adjust the temp buffer size for the size of audio data. */\n\t\ti = VQA_AUD_TEMPSIZE;\n\t\ti *= vqa->Audio.Channels * (vqa->Audio.BitsPerSample >> 3);\n\t\tvqa->Audio.TempBuf = (unsigned char *)malloc(i);\n\t\t#endif\n\n\t\tif (vqa->Audio.TempBuf == NULL) {\n\t\t\tFreeBuffers(vqa, config);\n\t\t\treturn (NULL);\n\t\t}\n\n\t\t/* Keep a running total of memory usage. */\n\t\tvqa->MemUsed += i;\n\t}\n\t#endif /* VQAAUDIO_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE THE FRAME INFORMATION TABLE IF REQUESTED.\n\t *-----------------------------------------------------------------------*/\n\tif (config->OptionFlags & VQAOPTF_FINF) {\n\t\tvqa->Foff = (long *)malloc(header->Frames * sizeof(long));\n\n\t\tif (vqa->Foff == NULL) {\n\t\t\tFreeBuffers(vqa, config);\n\t\t\treturn (NULL);\n\t\t} \n\n\t\t/* Keep a running total of memory usage. */\n\t\tvqa->MemUsed += (header->Frames * sizeof(long));\n\t} \n\t\n\treturn (vqa);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     FreeBuffers - Free VQA play buffers.\n*\n* SYNOPSIS\n*     FreeBuffers(VQAData)\n*\n*     void FreeBuffers(VQAData *);\n*\n* FUNCTION\n*      Free the buffers allocated by AllocBuffers().\n*\n* INPUTS\n*      VQAData - Pointer to VQAData structure.\n*\n* RESULT\n*      NONE\n*\n****************************************************************************/\n\nstatic void FreeBuffers(VQAData *vqa, VQAConfig *config)\n{\n\tVQACBNode    *cb_this, *cb_next;\n\tVQAFrameNode *frame_this, *frame_next;\n\tlong         i;\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE FRAME INFORMATION TABLE.\n\t *-----------------------------------------------------------------------*/\n\tif (vqa->Foff) {\n\t\tfree(vqa->Foff);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE AUDIO BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\n\t#if(VQAAUDIO_ON)\n\tif ((config->AudioBuf == NULL) && (vqa->Audio.Buffer)) {\n\t\tfree(vqa->Audio.Buffer);\n\t}\n\n\t/* Free the audio segments loaded flag array. */\n\tif (vqa->Audio.IsLoaded) {\n\t\tfree(vqa->Audio.IsLoaded);\n\t}\n\n\t/* Free the temporary audio buffer. */\n\tif (vqa->Audio.TempBuf) {\n\t\tfree(vqa->Audio.TempBuf);\n\t}\n\t#endif /* VQAAUDIO_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE IMAGE BUFFER ONLY IF WE ALLOCATED IT.\n\t *-----------------------------------------------------------------------*/\n\tif ((config->ImageBuf == NULL) && vqa->Drawer.ImageBuf) {\n\t\tfree(vqa->Drawer.ImageBuf);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE FRAME BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\tframe_this = vqa->FrameData;\n\n\tfor (i = 0; i < config->NumFrameBufs; i++) {\n\t\tif (frame_this) {\n\t\t\tframe_next = frame_this->Next;\n\t\t\tfree(frame_this);\n\t\t\tframe_this = frame_next;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE CODEBOOK BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\tcb_this = vqa->CBData;\n\n\tfor (i = 0; i < config->NumCBBufs; i++) {\n\t\tif (cb_this) {\n\t\t\tcb_next = cb_this->Next;\n\t\t\tfree(cb_this);\n\t\t\tcb_this = cb_next;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE VQA DATA STRUCTURES.\n\t *-----------------------------------------------------------------------*/\n\tfree(vqa);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_VQF - Loads a VQ Frame chunk.\n*\n* SYNOPSIS\n*     Error = Load_VQF(VQAFile, VQAData, Iffsize)\n*\n*     short Load_VQF(VQAFile *, VQAData *, unsigned long);\n*\n* FUNCTION\n*     The VQ Frame Chunk contains a set of other chunks (codebooks,\n*     palettes, pointers).  This routine reads the frame's chunk size,\n*     then loops until it's read that many bytes.\n*\n* INPUTS\n*     VQAFile - Pointer to VQAFile structure.\n*     VQAData - Pointer to VQAData structure.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_VQF(VQAHandleP *vqap, unsigned long frame_iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQAFrameNode  *curframe;\n\tChunkHeader   chunk;\n\tunsigned long iffsize;\n\tunsigned long framesize;\n\tunsigned long bytes_loaded = 0;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tcurframe = vqabuf->Loader.CurFrame;\n\tframesize = PADSIZE(frame_iffsize);\n\n\t/*-------------------------------------------------------------------------\n\t * FRAME LOADING LOOP.\n\t *-----------------------------------------------------------------------*/\n\twhile (bytes_loaded < framesize) {\n\n\t\t/* Read chunk ID */\n\t\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, &chunk, 8)) {\n\t\t\treturn (VQAERR_EOF);\n\t\t}\n\n\t\tiffsize = REVERSE_LONG(chunk.size);\n\t\tbytes_loaded += 8;\n\t\tbytes_loaded += PADSIZE(iffsize);\n\n\t\t/* Handle each chunk type */\n\t\tswitch (chunk.id) {\n\n\t\t\t/* Full uncompressed codebook */\n\t\t\tcase ID_CBF0:\n\t\t\t\tif (Load_CBF0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Full compressed codebook */\n\t\t\tcase ID_CBFZ:\n\t\t\t\tif (Load_CBFZ(vqap, iffsize)) {\n\t\t\t\t \treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Partial uncompressed codebook */\n\t\t\tcase ID_CBP0:\n\t\t\t\tif (Load_CBP0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Partial compressed codebook */\n\t\t\tcase ID_CBPZ:\n\t\t\t\tif (Load_CBPZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed palette */\n\t\t\tcase ID_CPL0:\n\t\t\t\tif (Load_CPL0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as having a palette. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_PALETTE;\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed palette */\n\t\t\tcase ID_CPLZ:\n\t\t\t\tif (Load_CPLZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as having a palette. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_PALETTE;\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed pointer data */\n\t\t\tcase ID_VPT0:\n\t\t\t\tif (Load_VPT0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed pointer data */\n\t\t\tcase ID_VPTZ:\n\t\t\tcase ID_VPTD:\n\t\t\t\tif (Load_VPTZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed pointer data */\n\t\t\tcase ID_VPTK:\n\t\t\t\tif (Load_VPTZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as being key. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_KEY;\n\t\t\t\tbreak;\n\n\t\t\t/* An unknown chunk in the video frame is an error. */\n\t\t\tdefault:\n\t\t\t\treturn (VQAERR_READ);\n\t\t}\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_FINF - Load Frame Info chunk.\n*\n* SYNOPSIS\n*     Error = Load_FINF(VQAFile, VQAData, Iffsize)\n*\n*     short Load_FINF(VQAFile *, VQAData *, Iffsize);\n*\n* FUNCTION\n*     Load FINF chunk if buffer available, otherwise skip it.\n*\n* INPUTS\n*     VQAFile - Pointer to VQAFile structure\n*     VQAData - Pointer to VQAData structure\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_FINF(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData *vqabuf;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\n\t/* Load the frame information table if we need to, otherwise we will\n\t * skip it.\n\t */\n\tif ((vqap->Config.OptionFlags & VQAOPTF_FINF) && (vqabuf->Foff != NULL)) {\n\t\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, vqabuf->Foff,\n\t\t\t\tPADSIZE(iffsize))) {\n\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\t} else {\n\t\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_SEEK, NULL,\n\t\t\t\tPADSIZE(iffsize))) {\n\n\t\t\treturn (VQAERR_SEEK);\n\t\t}\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_VQHD - Load VQA header chunk.\n*\n* SYNOPSIS\n*     Error = Load_VQHD(VQAFile, VQAData, Iffsize)\n*\n*     short Load_VQHD(VQAFile *, VQAData *, Iffsize);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQAFile - Pointer to VQAFile structure\n*     VQAData - Pointer to VQAData structure\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_VQHD(VQAHandleP *vqap, unsigned long iffsize)\n{\n\t/* Read the header */\n\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, &vqap->Header,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Reconfigure the Drawer for the new settings */\n\tVQA_Configure_Drawer(vqap);\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CBF0 - Load full uncompressed codebook.\n*\n* SYNOPSIS\n*     Error = Load_CBF0(VQAFile, VQAData, Iffsize)\n*\n*     short Load_CBF0(VQAFile *, VQAData *, Iffsize);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQAFile - Pointer to VQAFile structure\n*     VQAData - Pointer to VQAData structure\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CBF0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQALoader *loader;\n\tVQACBNode *curcb;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tloader = &vqap->VQABuf->Loader;\n\tcurcb = loader->CurCB;\n\n\t/* Read into the start of the buffer */\n\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, curcb->Buffer,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Reset the partial codebook counter. */\n\tloader->NumPartialCB = 0;\n\n\t/* Flag this codebook as uncompressed. */\n\tcurcb->Flags &= (~VQACBF_CBCOMP);\n\tcurcb->CBOffset = 0;\n\n\t/* Clock pointers to next CB Buffer. */\n\tloader->FullCB = curcb;\n\tloader->FullCB->Flags &= (~VQACBF_DOWNLOADED);\n\tloader->CurCB = curcb->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CBFZ - Load full compressed codebook.\n*\n* SYNOPSIS\n*     Error = Load_CBFZ(VQAFile, VQAData, Iffsize)\n*\n*     short Load_CBFZ(VQAFile *, VQAData *, Iffsize);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQAFile - Pointer to VQAFile structure\n*     VQAData - Pointer to VQAData structure\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CBFZ(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQALoader     *loader;\n\tVQACBNode     *curcb;\n\tvoid          *buffer;\n\tunsigned long padsize;\n\tunsigned long lcwoffset;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tloader = &vqap->VQABuf->Loader;\n\tcurcb = loader->CurCB;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* Load the codebook into the end of the buffer. */\n\tlcwoffset = vqap->VQABuf->Max_CB_Size - (unsigned short)padsize;\n\tbuffer = curcb->Buffer + lcwoffset;\n\n\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Reset the partial codebook counter. */\n\tloader->NumPartialCB = 0;\n\n\t/* Flag this codebook as compressed */\n\tcurcb->Flags |= VQACBF_CBCOMP;\n\tcurcb->CBOffset = lcwoffset;\n\n\t/* Clock pointers to next CB Buffer */\n\tloader->FullCB = curcb;\n\tloader->FullCB->Flags &= (~VQACBF_DOWNLOADED);\n\tloader->CurCB = curcb->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CBP0 - Load partial uncompressed codebook.\n*\n* SYNOPSIS\n*     Error = Load_CBP0(VQAFile, VQAData, Iffsize)\n*\n*     short Load_CBP0(VQAFile *, VQAData *, Iffsize);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQAFile - Pointer to VQAFile structure\n*     VQAData - Pointer to VQAData structure\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CBP0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData   *vqabuf;\n\tVQALoader *loader;\n\tVQACBNode *curcb;\n\tvoid      *buffer;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\tcurcb = loader->CurCB;\n\n\t/*-------------------------------------------------------------------------\n\t * ASSEMBLY PARTIAL CODEBOOKS.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Read the partial codebook into the next position in the buffer. */\n\tbuffer = curcb->Buffer + loader->PartialCBSize;\n\n\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, buffer,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Accumulate the partial codebook values. */\n\tloader->PartialCBSize += (unsigned short)iffsize;\n\tloader->NumPartialCB++;\n\n\t/*-------------------------------------------------------------------------\n\t * PROCESS FULL CODEBOOK.\n\t *-----------------------------------------------------------------------*/\n\tif (loader->NumPartialCB == vqap->Header.Groupsize) {\n\n\t\t/* Reset the codebook accumulator values */\n\t\tloader->NumPartialCB = 0;\n\t\tloader->PartialCBSize = 0;\n\n\t\t/* Flag this codebook as uncompressed */\n\t\tcurcb->Flags &= (~VQACBF_CBCOMP);\n\t\tcurcb->CBOffset = 0;\n\n\t\t/* Go to the next codebook buffer */\n\t\tloader->FullCB = curcb;\n\t\tloader->FullCB->Flags &= (~VQACBF_DOWNLOADED);\n\t\tloader->CurCB = curcb->Next;\n\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CBPZ - Load partial compressed codebook.\n*\n* SYNOPSIS\n*     Error = Load_CBPZ(VQAFile, VQAData, Iffsize)\n*\n*     short Load_CBPZ(VQAFile *, VQAData *, Iffsize);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQAFile - Pointer to VQAFile structure\n*     VQAData - Pointer to VQAData structure\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CBPZ(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQACBNode     *curcb;\n\tvoid          *buffer;\n\tunsigned long padsize;\n\n\t/* Dereference commonly used data members for quicker access */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\tcurcb = loader->CurCB;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* Attempt to compute the LCW offset into the codebook buffer by\n\t * multiplying the size of this chunk by the # frames/group, and adding\n\t * a small fudge factor on, then subtracting that from the CB buffer size.\n\t */\n\tif (loader->PartialCBSize == 0) {\n\t\tcurcb->CBOffset = (vqabuf->Max_CB_Size - ((unsigned short)padsize\n\t\t\t\t* vqap->Header.Groupsize + 100));\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * ASSEMBLE PARTIAL CODEBOOKS.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Read the partial codebook into the next position in the buffer. */\n\tbuffer = ((curcb->Buffer + curcb->CBOffset) + loader->PartialCBSize);\n\n\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Accumulate partial codebook values */\n\tloader->PartialCBSize += (unsigned short)iffsize;\n\tloader->NumPartialCB++;\n\n\t/*-------------------------------------------------------------------------\n\t * PROCESS FULL CODEBOOK.\n\t *-----------------------------------------------------------------------*/\n\tif (loader->NumPartialCB == vqap->Header.Groupsize) {\n\n\t\t/* Reset the codebook accumulator values. */\n\t\tloader->NumPartialCB = 0;\n\t\tloader->PartialCBSize = 0;\n\n\t\t/* Flag this codebook as compressed. */\n\t\tcurcb->Flags |= VQACBF_CBCOMP;\n\n\t\t/* Go to the next codebook buffer */\n\t\tloader->FullCB = curcb;\n\t\tloader->FullCB->Flags &= (~VQACBF_DOWNLOADED);\n\t\tloader->CurCB = curcb->Next;\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CPL0 - Load an uncompressed palette.\n*\n* SYNOPSIS\n*     Error = Load_CPL0(VQAFile, VQAData, Iffsize)\n*\n*     short Load_CPL0(VQAFile *, VQAData *, Iffsize);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQAFile - Pointer to VQAFile structure\n*     VQAData - Pointer to VQAData structure\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CPL0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAFrameNode *curframe;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tcurframe = vqap->VQABuf->Loader.CurFrame;\n\n\t/* Read the palette into the palette buffer */\n\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, curframe->Palette,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Flag the palette as uncompressed. */\n\tcurframe->Flags &= ~VQAFRMF_PALCOMP;\n\tcurframe->PalOffset = 0;\n\tcurframe->PaletteSize = (unsigned short)iffsize;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CPLZ - Load compressed palette.\n*\n* SYNOPSIS\n*     Error = Load_CPLZ(VQAFile, VQAData, Iffsize)\n*\n*     short Load_CPLZ(VQAFile *, VQAData *, Iffsize);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQAFile - Pointer to VQAFile structure\n*     VQAData - Pointer to VQAData structure\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CPLZ(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAFrameNode  *curframe;\n\tvoid          *buffer;\n\tunsigned long padsize;\n\tunsigned long lcwoffset;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tcurframe = vqap->VQABuf->Loader.CurFrame;\n\tpadsize = PADSIZE(iffsize);\n\n \t/* Read the palette into the end of the palette buffer. */\n\tlcwoffset = vqap->VQABuf->Max_Pal_Size - (unsigned short)padsize;\n\tbuffer = curframe->Palette + lcwoffset;\n\n\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Flag this palette as compressed. */\n\tcurframe->Flags |= VQAFRMF_PALCOMP;\n\tcurframe->PalOffset = lcwoffset;\n\tcurframe->PaletteSize = (unsigned short)iffsize;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_VPT0 - Load uncompressed pointers.\n*\n* SYNOPSIS\n*     Error = Load_VPT0(VQAFile, VQAData, Iffsize)\n*\n*     short Load_VPT0(VQAFile *, VQAData *, Iffsize);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQAFile - Pointer to VQAFile structure\n*     VQAData - Pointer to VQAData structure\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_VPT0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAFrameNode *curframe;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tcurframe = vqap->VQABuf->Loader.CurFrame;\n\n\t/* Read the pointers into start of the pointer buffer. */\n\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, curframe->Pointers,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Flag this frame as uncompressed */\n\tcurframe->Flags &= ~VQAFRMF_PTRCOMP;\n\tcurframe->PtrOffset = 0;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_VPTZ - Load compressed pointers.\n*\n* SYNOPSIS\n*     Error = Load_VPTZ(VQAFile, VQAData, Iffsize)\n*\n*     short Load_VPTZ(VQAFile *, VQAData *, Iffsize);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQAFile - Pointer to VQAFile structure\n*     VQAData - Pointer to VQAData structure\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_VPTZ(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAFrameNode  *curframe;\n\tvoid          *buffer;\n\tunsigned long padsize;\n\tunsigned long lcwoffset;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tcurframe = vqap->VQABuf->Loader.CurFrame;\n\tpadsize = PADSIZE(iffsize);\n\tlcwoffset = vqap->VQABuf->Max_Ptr_Size - (unsigned short)padsize;\n\n\t/* Read the pointers into end of the pointer buffer. */\n\tbuffer = curframe->Pointers + lcwoffset;\n\n\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Flag this frame as compressed. */\n\tcurframe->Flags |= VQAFRMF_PTRCOMP;\n\tcurframe->PtrOffset = lcwoffset;\n\n\treturn (0);\n}\n\n\n#if(VQAAUDIO_ON)\n/****************************************************************************\n*\n* NAME\n*     Load_SND0 - Load uncompressed sound chunk.\n*\n* SYNOPSIS\n*     Error = Load_SND0(VQAFile, VQAData, Iffsize)\n*\n*     short Load_SND0(VQAFile *, VQAData *, Iffsize);\n*\n* FUNCTION\n*     This routine normally loads the chunk into the TempBuf, unless the\n*     chunk is larger than the temp buffer size, in which case it puts it\n*     directly into the audio buffer itself.  This assumes that the only\n*     such chunk will be the first audio chunk!\n*\n* INPUTS\n*     VQAFile - Pointer to VQAFile structure\n*     VQAData - Pointer to VQAData structure\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_SND0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tunsigned long padsize;\n\tlong          i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\taudio = &vqabuf->Audio;\n\tconfig = &vqap->Config;\n\tpadsize = PADSIZE((unsigned short)iffsize);\n\n\t/* If sound is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, just skip the chunk.\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0)\n\t\t\t|| (vqap->vocfh != -1) || (audio->Buffer == NULL)) {\n\t#else  /* VQAVOC_ON */\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0)\n\t\t\t|| (audio->Buffer == NULL)) {\n\t#endif /* VQAVOC_ON */\n\n\t\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_SEEK, NULL, padsize)) {\n\t\t\treturn (VQAERR_SEEK);\n\t\t} else {\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\t/* Read large startup chunk directly into AudioBuf */\n\tif ((padsize > VQA_AUD_TEMPSIZE) && (loader->AudBufPos == 0)) {\n\t\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, audio->Buffer,\n\t\t\t\tpadsize)) {\n\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\n\t\tloader->AudBufPos += (unsigned short)iffsize;\n\n\t\t/* Flag the audio frame flags as loaded for the initial audio frame. */\n\t\tfor (i = 0; i < (iffsize / config->HMIBufSize); i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t} else {\n\n\t\t/*  Read data into TempBuf */\n\t\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, audio->TempBuf,\n\t\t\t\tpadsize)) {\n\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\t}\n\n\t/* Set the TempBufLen */\n\taudio->TempBufLen = (unsigned short)iffsize;\n\t\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_SND1 - Load compressed sound chunk.\n*\n* SYNOPSIS\n*     Error = Load_SND1(VQAFile, VQAData, Iffsize)\n*\n*     short Load_SND1(VQAFile *, VQAData *, Iffsize);\n*\n* FUNCTION\n*     This routine normally loads the chunk into the TempBuf, unless the\n*     chunk is larger than the temp buffer size, in which case it puts it\n*     directly into the audio buffer itself.  This assumes that the only\n*     such chunk will be the first audio chunk!\n*\n* INPUTS\n*     VQAFile - Pointer to VQAFile structure\n*     VQAData - Pointer to VQAData structure\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_SND1(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tunsigned char *loadbuf;\n\tunsigned long padsize;\n\tunsigned long uncomp_size;\n\tunsigned long comp_size;\n\tlong          i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\taudio = &vqabuf->Audio;\n\tconfig = &vqap->Config;\n\tpadsize = PADSIZE((unsigned short)iffsize);\n\n\t/* If sound is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, just skip the chunk\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (vqap->vocfh != -1)\n\t\t\t|| (audio->Buffer == NULL)) {\n\t#else  /* VQAVOC_ON */\n\tif (((config->OptionFlags & VQAOPTF_AUDIO)==0) || (audio->Buffer==NULL)) {\n\t#endif /* VQAVOC_ON */\n\n\t\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_SEEK, NULL, padsize)) {\n\t\t\treturn (VQAERR_SEEK);\n\t\t} else {\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\t/* Read the uncompressed data size */\n\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, &uncomp_size, 2)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Read the compressed data size */\n\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, &comp_size, 2)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Adjust chunk size */\n\tpadsize -= 4;\n\n\t/* Read large startup chunk directly into AudioBuf */\n\tif ((uncomp_size > VQA_AUD_TEMPSIZE) && (loader->AudBufPos == 0)) {\n\n\t\t/* Load uncompressed data */\n\t\tif (uncomp_size == comp_size) {\n\t\t\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, audio->Buffer,\n\t\t\t\t\tpadsize)) {\n\n\t\t\t\treturn (VQAERR_READ);\n\t\t\t}\n\t\t} else {\n\n\t\t\t/* Load compressed data into the end of the buffer. */\n\t\t\tloadbuf = (audio->Buffer + config->AudioBufSize) - padsize;\n\n\t\t\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, loadbuf,\n\t\t\t\t\tpadsize)) {\n\n\t\t\t\treturn (VQAERR_READ);\n\t\t\t}\n\n\t\t\t/* Uncompress the audio frame. */\n\t\t\tAudioUnzap(loadbuf, audio->Buffer, uncomp_size);\n\t\t}\n\n\t\t/* Set buffer positions & flags */\n\t\tloader->AudBufPos += uncomp_size;\n\n\t\tfor (i = 0; i < (uncomp_size / config->HMIBufSize); i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t}\n\n\t/* Load an audio frame. */\n\tif (uncomp_size == comp_size) {\n\n\t\t/* If the frame is uncompressed the load it in directly. */\n\t\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_READ, audio->TempBuf,\n\t\t\t\tpadsize)) {\n\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\t} else {\n\n\t\t/* Load the audio frame into the end of the buffer. */\n\t\tloadbuf = ((audio->TempBuf + VQA_AUD_TEMPSIZE) - padsize);\n\n\t\tif (vqap->StreamHandler((VQAHandle *)vqap,VQACMD_READ,loadbuf,padsize)) {\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\n\t\t/* Uncompress the audio frame. */\n\t\tAudioUnzap(loadbuf, audio->TempBuf, uncomp_size);\n\t}\n\n\t/* Set the TempBufLen */\n\taudio->TempBufLen = uncomp_size;\n\t\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_SND2 - Load compressed sound chunk.\n*\n* SYNOPSIS\n*     Error = Load_SND2(VQAFile, VQAData, Iffsize)\n*\n*     short Load_SND2(VQAFile *, VQAData *, Iffsize);\n*\n* FUNCTION\n*     This routine normally loads the chunk into the TempBuf, unless the\n*     chunk is larger than the temp buffer size, in which case it puts it\n*     directly into the audio buffer itself.  This assumes that the only\n*     such chunk will be the first audio chunk!\n*\n* INPUTS\n*     VQAFile - Pointer to VQAFile structure\n*     VQAData - Pointer to VQAData structure\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_SND2(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tunsigned char *loadbuf;\n\tunsigned long padsize;\n\tunsigned long uncomp_size;\n\tlong          i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\taudio = &vqabuf->Audio;\n\tconfig = &vqap->Config;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* If sound is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, just skip the chunk\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (vqap->vocfh != -1)\n\t\t\t|| (audio->Buffer == NULL)) {\n\t#else  /* VQAVOC_ON */\n\tif (((config->OptionFlags & VQAOPTF_AUDIO)==0) || (audio->Buffer==NULL)) {\n\t#endif /* VQAVOC_ON */\n\n\t\tif (vqap->StreamHandler((VQAHandle *)vqap, VQACMD_SEEK, NULL, padsize)) {\n\t\t\treturn (VQAERR_SEEK);\n\t\t} else {\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\tuncomp_size = iffsize * (8 / 4);\n\n\t/* Read large startup chunk directly into AudioBuf */\n\tif ((uncomp_size > VQA_AUD_TEMPSIZE) && (loader->AudBufPos == 0)) {\n\n\t\t/* Load compressed data into the end of the buffer. */\n\t\tloadbuf = (audio->Buffer + config->AudioBufSize) - padsize;\n\n\t\tif (vqap->StreamHandler((VQAHandle *)vqap,VQACMD_READ,loadbuf,padsize)) {\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\n\t\t/* Uncompress the audio frame. */\n\t\taudio->sSOSInfo.lpSource = (char *)loadbuf;\n\t\taudio->sSOSInfo.lpDest = (char *)audio->Buffer;\n\t\tsosCODECDecompressData(&audio->sSOSInfo, uncomp_size);\n\n\t\t/* Set buffer positions & flags */\n\t\tloader->AudBufPos += uncomp_size;\n\n\t\tfor (i = 0; i < (uncomp_size / config->HMIBufSize); i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t}\n\n\t/* Load an audio frame. */\n\tloadbuf = ((audio->TempBuf + VQA_AUD_TEMPSIZE) - padsize);\n\n\tif (vqap->StreamHandler((VQAHandle *)vqap,VQACMD_READ,loadbuf,padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Uncompress the audio frame. */\n\taudio->sSOSInfo.lpSource = (char *)loadbuf;\n\taudio->sSOSInfo.lpDest = (char *)audio->TempBuf;\n\tsosCODECDecompressData(&audio->sSOSInfo, uncomp_size);\n\n\t/* Set the TempBufLen */\n\taudio->TempBufLen = uncomp_size;\n\t\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Copy_SND - Copy data from Audio Temp buffer into Audio play buffer.\n*\n* SYNOPSIS\n*     Error = Copy_SND(VQAFile, VQAData)\n*\n*     short Load_SND0(VQAFile *, VQAData *);\n*\n* FUNCTION\n*     This routine just copies the data in the TempBuf into the correct\n*     spots in the audio play buffer.  If there is no room available in the\n*     audio play buffer, the routine returns VQAERR_SLEEPING, which will put\n*     the whole Loader to \"sleep\" while it waits for a free buffer.\n*\n*     If there's no data in the TempBuf to copy, the routine just returns 0.\n*\n* INPUTS\n*     VQAFile - Pointer to VQAFile structure\n*     VQAData - Pointer to VQAData structure\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Copy_SND(VQAHandleP *vqap)\n{\n\tVQAData   *vqabuf;\n\tVQALoader *loader;\n\tVQAAudio  *audio;\n\tVQAConfig *config;\n\tlong      startblock;\n\tlong      endblock;\n\tlong      len1,len2;\n\tlong      i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\taudio = &vqabuf->Audio;\n\tconfig = &vqap->Config;\n\n\t/* If audio is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, or if there's no data to copy, just return 0\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (vqap->vocfh != -1)\n\t\t\t|| (audio->Buffer == NULL) || (audio->TempBufLen == 0)) {\n\t#else  /* VQAVOC_ON */\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (audio->Buffer == NULL)\n\t\t\t|| (audio->TempBufLen == 0)) {\n\t#endif /* VQAVOC_ON */\n\n\t\treturn (0);\n\t}\n\n\t/* Compute start & end blocks to copy into */\n\tstartblock = (loader->AudBufPos / config->HMIBufSize);\n\tendblock = (loader->AudBufPos + audio->TempBufLen) / config->HMIBufSize;\n\n\tif (endblock >= audio->NumAudBlocks) {\n\t\tendblock -= audio->NumAudBlocks;\n\t}\n\n\t/* If 'endblock' hasn't played yet, return VQAERR_SLEEPING */\n\tif (audio->IsLoaded[endblock] == 1) {\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\t/* Copy the data:\n\t *\n\t *  - If 'startblock' < 'endblock', copy the entire buffer\n\t *  - Otherwise, fill to the end of the buffer with part of the data, then\n\t *    copy the rest to the beginning of the buffer\n\t */\n\tif (startblock <= endblock) {\n\n\t\t/* Copy data */\n\t\tmemcpy((audio->Buffer + loader->AudBufPos), audio->TempBuf,\n\t\t\t\taudio->TempBufLen);\n\n\t\t/* Adjust current load position */\n\t\tloader->AudBufPos += audio->TempBufLen;\n\n\t\t/* Mark buffer as empty */\n\t\taudio->TempBufLen = 0;\n\n\t\t/* Set all blocks to loaded */\n\t\tfor (i = startblock; i < endblock; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t} else {\n\n\t\t/* Compute length of each piece */\n\t\tlen1 = config->AudioBufSize - loader->AudBufPos;\n\t\tlen2 = audio->TempBufLen - len1;\n \n\t\t/* Copy 1st piece into end of Audio Buffer */\n\t\tmemcpy((audio->Buffer + loader->AudBufPos), audio->TempBuf, len1);\n\n\t\t/* Copy 2nd piece into start of Audio Buffer */\n\t\tmemcpy(audio->Buffer, audio->TempBuf + len1, len2);\n\t\t\n\t\t/* Adjust load position */\n\t\tloader->AudBufPos = len2;\n\n\t\t/* Mark buffer as empty */\n\t\taudio->TempBufLen = 0;\n\n\t\t/* Set blocks to loaded */\n\t\tfor (i = startblock; i < audio->NumAudBlocks; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\tfor (i = 0; i < endblock; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t}\n}\n\n\n#if(VQAVOC_ON && VQAAUDIO_ON)\n/****************************************************************************\n*\n* NAME\n*     Load_VOC_Block - Loads blocks from seperate VOC file.\n*\n* SYNOPSIS\n*     Load_VOC_Block(VQAFile, VQAData)\n*\n*     void Load_VOC_Block(VQAFile *, VQAData *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQAFile - Pointer to VQAFile structure\n*     VQAData - Pointer to VQAData structure\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Load_VOC_Block(VQAHandleP *vqap)\n{\n\tVQAData     *vqabuf;\n\tVQALoader   *loader;\n\tVQAAudio    *audio;\n\tVQAConfig   *config;\n\tstatic long lastplayblock = -1;\n\tstatic long myblock = 0;\n\tstatic long firsttime = 1;\n\tlong        numblocks;\n\tlong        i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\taudio = &vqabuf->Audio;\n\tconfig = &vqap->Config;\n\n\t/* Do nothing if no buffer */\n\tif (audio->Buffer == NULL) {\n\t\treturn;\n\t}\n\n\t/* If this is the first time we're called, pre-load the 1st 'n' audio\n\t * blocks, where 'n' is half the total audio buffer size; this way, we'll\n\t * always stay ahead of HMI.\n\t */\n\tif (firsttime) {\n\t\tnumblocks = (audio->NumAudBlocks / 2);\n\t\tread(vqap->vocfh, audio->Buffer, config->HMIBufSize * numblocks);\n\t\tloader->AudBufPos += config->HMIBufSize * numblocks;\n\n\t\tif (loader->AudBufPos >= config->AudioBufSize) {\n\t\t\tloader->AudBufPos = 0;\n\t\t}\n\n\t\tfor (i = 0; i < numblocks; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\tmyblock += numblocks;\n\t\t\n\t\tif (myblock >= audio->NumAudBlocks) {\n\t\t\tmyblock = 0;\n\t\t}\n\n\t\tfirsttime = 0;\n\t}\n\n\t/* If HMI's block has changed, load the next block & mark it as loaded */\n\tif (audio->PlayPosition / config->HMIBufSize != lastplayblock) {\n\n\t\t/* update HMI's last known block position */\n\t\tlastplayblock = audio->PlayPosition / config->HMIBufSize;\n\n\t\t/* read the VOC data */\n\t\tread(vqap->vocfh, (audio->Buffer + myblock * config->HMIBufSize),\n\t\t\t\tconfig->HMIBufSize);\n\n\t\tloader->AudBufPos += config->HMIBufSize;\n\n\t\tif (loader->AudBufPos >= config->AudioBufSize) {\n\t\t\tloader->AudBufPos = 0;\n\t\t}\n\n\t\t/* set the IsLoaded flags */\n\t\taudio->IsLoaded[myblock] = 1;\n\n\t\t/* increment my block counter */\n\t\tmyblock++;\n\n\t\tif (myblock >= audio->NumAudBlocks) {\n\t\t\tmyblock = 0;\n\t\t}\n\t}\n}\n#endif /* VQAVOC_ON */\n#endif /* VQAAUDIO_ON */\n\n"
  },
  {
    "path": "VQ/VQA32/LOADER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     loader.c\n*\n* DESCRIPTION\n*     Stream loading and pre-processing.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     August 21, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_Open      - Open a VQA file to play.\n*     VQA_Close     - Close an opened VQA file.\n*     VQA_LoadFrame - Load the next video frame from the VQA data stream.\n*     VQA_SeekFrame - Position the movie stream to the specified frame.\n*\n* PRIVATE\n*     AllocBuffers  - Allocates the numerous VQA play buffers\n*     FreeBuffers   - Frees the VQA play buffers\n*     PrimeBuffers  - Pre-Load the internal buffers.\n*     Load_FINF     - Loads the Frame Info Table.\n*     Load_VQHD     - Loads a VQA Header.\n*     Load_CBF0     - Loads a full, uncompressed codebook\n*     Load_CBFZ     - Loads a full, compressed codebook\n*     Load_CBP0     - Loads a partial uncompressed codebook\n*     Load_CBPZ     - Loads a partial compressed codebook\n*     Load_CPL0     - Loads an uncompressed palette\n*     Load_CPLZ     - Loads a compressed palette\n*     Load_VPT0     - Loads uncompressed pointers\n*     Load_VPTZ     - Loads compressed pointers\n*     Load_VQF      - Loads a VQ Frame chunk\n*     Load_SND0     - Loads an uncompressed sound chunk\n*     Load_SND1     - Loads a compressed sound chunk\n*     Load_AudFrame - Loads blocks from separate audio file, if needed.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <fcntl.h>\n#include <io.h>\n#include <malloc.h>\n#include <mem.h>\n#include <dos.h>\n#include \"vq.h\"\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\nstatic VQAData *AllocBuffers(VQAHeader *header, VQAConfig *config);\nstatic void FreeBuffers(VQAData *vqa, VQAConfig *config, VQAHeader *header);\nstatic long PrimeBuffers(VQAHandle *vqa);\nstatic long Load_VQF(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_FINF(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_VQHD(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CBF0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CBFZ(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CBP0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CBPZ(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CPL0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CPLZ(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_VPT0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_VPTZ(VQAHandleP *vqap, unsigned long iffsize);\n\n#if(VQAAUDIO_ON)\nstatic long Load_SND0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_SND1(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_SND2(VQAHandleP *vqap, unsigned long iffsize);\n\n#if(VQAVOC_ON)\nstatic void Load_AudFrame(VQAHandleP *vqap);\n#endif /* VQAVOC_ON */\n\n#endif /* VQAAUDIO_ON */\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Open - Open a VQA file to play.\n*\n* SYNOPSIS\n*     Error = VQA_Open(VQA, Name, Config)\n*\n*     long VQA_Open(VQAHandle *, char *, VQAConfig *);\n*\n* FUNCTION\n*     - Open a VQA file for reading.\n*     - Validate that it is an IFF file, of the VQA type.\n*     - Read the VQA header.\n*     - Open a VOC file for playback, if requested.\n*     - Set the Loader's frame rate, if the caller's Config structure's\n*       FrameRate is set to -1\n*     - Set the Drawer's frame rate, if the caller's Config structure's\n*       DrawRate is set to -1\n*\n* INPUTS\n*     VQA    - Pointer to initialized handle. Obtained by VQA_Alloc().\n*     Name   - Pointer to name of VQA file to open.\n*     Config - Pointer to initialized VQA configuration structure.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_ error code.\n*\n****************************************************************************/\n\n#define OPEN_VQHD     (1<<0)\n#define OPEN_FINF     (1<<1)\n#define OPEN_CAPTIONS (1<<2)\n#define OPEN_EVA      (1<<3)\n\nlong VQA_Open(VQAHandle *vqa, char const *filename, VQAConfig *config)\n{\n\tVQAHandleP  *vqap;\n\tVQAHeader   *header;\n\tChunkHeader chunk;\n\tlong        max_frm_size;\n\tlong        i;\n\tlong        done;\n\tlong        found;\n\tchar        *ptr;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqap = (VQAHandleP *)vqa;\n\theader = &vqap->Header;\n\n\t/*-------------------------------------------------------------------------\n\t * VERIFY VALIDITY OF VQA FILE.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Open the file. */\n\tif (vqap->IOHandler(vqa, VQACMD_OPEN, (void *)filename, 0)) {\n\t\treturn (VQAERR_OPEN);\n\t}\n\n\t/* Read the file ID & Size */\n\tif (vqap->IOHandler(vqa, VQACMD_READ, &chunk, 8)) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Verify an IFF FORM */\n\tif ((chunk.id != ID_FORM) || (chunk.size == 0)) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_NOTVQA);\n\t}\n\n\t/* Read in WVQA ID */\n\tif (vqap->IOHandler(vqa, VQACMD_READ, &chunk, 4)) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Verify VQA */\n\tif (chunk.id != ID_WVQA) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_NOTVQA);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE PLAYERS CONFIGURATION\n\t *-----------------------------------------------------------------------*/\n\n\t/* Use the clients configuration if they provided one. */\n\tif (config != NULL) {\n\t\tmemcpy(&vqap->Config, config, sizeof(VQAConfig));\n\t} else {\n\t\tVQA_DefaultConfig(&vqap->Config);\n\t}\n\n\t/* Use the internal configuration structure from now on. */\n\tconfig = &vqap->Config;\n\n\t/*-------------------------------------------------------------------------\n\t * PROCESS THE PRE-FRAME CHUNKS (VQHD, CAP, FINF, ETC...)\n\t *-----------------------------------------------------------------------*/\n\tfound = 0;\n\tdone = 0;\n\n\twhile (!done) {\n\t\tif (vqap->IOHandler(vqa, VQACMD_READ, &chunk, 8)) {\n\t\t\tVQA_Close(vqa);\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\n\t\tchunk.size = REVERSE_LONG(chunk.size);\n\n\t\tswitch (chunk.id) {\n\n\t\t\t/*---------------------------------------------------------------------\n\t\t\t * READ IN THE VQA HEADER.\n\t\t\t *-------------------------------------------------------------------*/\n\t\t\tcase ID_VQHD:\n\t\t\t\tif (chunk.size != sizeof(VQAHeader)) {\n\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\treturn (VQAERR_NOTVQA);\n\t\t\t\t}\n\n\t\t\t\t/* Read the header data. */\n\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_READ, header, PADSIZE(chunk.size))) {\n\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/*-------------------------------------------------------------------\n\t\t\t\t * SETUP THE CONFIGURATION FROM THE HEADER.\n\t\t\t\t *-----------------------------------------------------------------*/\n\t\t\t\tif (config->ImageWidth == -1) {\n\t\t\t\t\tconfig->ImageWidth = header->ImageWidth;\n\t\t\t\t}\n\n\t\t\t\tif (config->ImageHeight == -1) {\n\t\t\t\t\tconfig->ImageHeight = header->ImageHeight;\n\t\t\t\t}\n\n\t\t\t\t/* If Loaders frame rate is -1 then use the value from the header. */\n\t\t\t\tif (config->FrameRate == -1) {\n\t\t\t\t\tconfig->FrameRate = header->FPS;\n\t\t\t\t}\n\n\t\t\t\t/* If Drawers frame rate is -1 then use the value from the header,\n\t\t\t\t * which will result in a \"variable\" frame rate.\n\t\t\t\t */\n\t\t\t\tif (config->DrawRate == -1) {\n\t\t\t\t\tconfig->DrawRate = header->FPS;\n\t\t\t\t}\n\n\t\t\t\t/* Finally, if the DrawRate was set to -1 or 0 (ie MaxRate contained\n\t\t\t\t * bogus values), set it to the header value.\n\t\t\t\t */\n\t\t\t\tif ((config->DrawRate == -1) || (config->DrawRate == 0)) {\n\t\t\t\t\tconfig->DrawRate = header->FPS;\n\t\t\t\t}\n\n\t\t\t\t#if(VQAAUDIO_ON)\n\t\t\t\t/* If an alternate audio track is not available then turn it off.\n\t\t\t\t * This enables the primary audio track to be played.\n\t\t\t\t */\n\t\t\t\tif ((header->Version > VQAHD_VER1)\n\t\t\t\t\t\t&& !(header->Flags & VQAHDF_ALTAUDIO)) {\n\t\t\t\t\tconfig->OptionFlags &= ~VQAOPTF_ALTAUDIO;\n\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\t/*-------------------------------------------------------------------\n\t\t\t\t * ALLOCATE THE BUFFERS THAT WE NEED TO PLAY THE VQA.\n\t\t\t\t *-----------------------------------------------------------------*/\n\t\t\t\tif ((vqap->VQABuf = AllocBuffers(header, config)) == NULL) {\n\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\treturn (VQAERR_NOMEM);\n\t\t\t\t}\n\n\t\t\t\tfound |= OPEN_VQHD;\n\t\t\t\tbreak;\n\n\t\t\t/*---------------------------------------------------------------------\n\t\t\t * READ IN AND OPEN THE CAPTIONS STREAM.\n\t\t\t *-------------------------------------------------------------------*/\n\t\t\tcase ID_CAP0:\n\t\t\t\tif ((config->CapFont != NULL)\n\t\t\t\t\t\t&& (config->OptionFlags & VQAOPTF_CAPTIONS)) {\n\n\t\t\t\t\tshort size = 0;\n\n\t\t\t\t\t/* Get uncompressed size of captions. */\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_READ, &size, sizeof(short))) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Allocate buffer for captions. */\n\t\t\t\t\ti = size + 50;\n\n\t\t\t\t\tif ((ptr = (char *)malloc(i)) == NULL) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_NOMEM);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Read in the captions chunk. */\n\t\t\t\t\ti -= PADSIZE(chunk.size);\n\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_READ, (ptr + i),\n\t\t\t\t\t\t\tPADSIZE(chunk.size - sizeof(short)))) {\n\n\t\t\t\t\t\tfree(ptr);\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Decompress the captions. */\n\t\t\t\t\tLCW_Uncompress((ptr + i), ptr, size);\n\t\t\t\t\tvqap->Caption = OpenCaptions(ptr, config->CapFont);\n\n\t\t\t\t\tif (vqap->Caption == NULL) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_NOMEM);\n\t\t\t\t\t}\n\n\t\t\t\t\tfound |= OPEN_CAPTIONS;\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(chunk.size))) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ID_EVA0:\n\t\t\t\tif ((config->EVAFont != NULL)\n\t\t\t\t\t\t&& (config->OptionFlags & VQAOPTF_EVA)) {\n\n\t\t\t\t\tshort size = 0;\n\n\t\t\t\t\t/* Get uncompressed size of captions. */\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_READ, &size, sizeof(short))) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Allocate buffer for captions. */\n\t\t\t\t\ti = size + 50;\n\n\t\t\t\t\tif ((ptr = (char *)malloc(i)) == NULL) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_NOMEM);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Read in the captions chunk. */\n\t\t\t\t\ti -= PADSIZE(chunk.size);\n\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_READ, (ptr + i),\n\t\t\t\t\t\t\tPADSIZE(chunk.size - sizeof(short)))) {\n\t\t\t\t\t\tfree (ptr);\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Decompress the captions. */\n\t\t\t\t\tLCW_Uncompress((ptr + i), ptr, size);\n\t\t\t\t\tvqap->EVA = OpenCaptions(ptr, config->EVAFont);\n\n\t\t\t\t\tif (vqap->EVA == NULL) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_NOMEM);\n\t\t\t\t\t}\n\n\t\t\t\t\tfound |= OPEN_EVA;\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(chunk.size))) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*---------------------------------------------------------------------\n\t\t\t * READ FRAME INFORMATION\n\t\t\t *-------------------------------------------------------------------*/\n\t\t\tcase ID_FINF:\n\t\t\t\tif (Load_FINF(vqap, chunk.size)) {\n\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\tdone = 1;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\tPADSIZE(chunk.size))) {\n\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE VIDEO SYSTEM IF WE ARE REQUIRED TO HANDLE THAT.\n\t *-----------------------------------------------------------------------*/\n\t#if(VQAVIDEO_ON)\n\tif ((vqap->VQABuf->Drawer.Display = SetVideoMode(config->Vmode)) == 0) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_VIDEO);\n\t}\n\n\t/* Set the VBIBit polarity. */\n\tvqap->VQABuf->VBIBit = GetVBIBit();\n\t#else\n\tif (config->VBIBit == -1) {\n\t\tconfig->VBIBit = TestVBIBit();\n\t}\n\n\tvqap->VQABuf->VBIBit = config->VBIBit;\n\n\tif (found & (OPEN_CAPTIONS|OPEN_EVA)) {\n\t\tSetDAC(251,255,255,255); /* White */\n\t\tSetDAC(252,255,000,000); /* Red */\n\t\tSetDAC(253,000,255,000); /* Green */\n\t\tSetDAC(254,255,255,255);\n\t\tSetDAC(255,255,000,255); /* Cycle */\n\t}\n\t#endif /* VQAVIDEO_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * AUDIO TRACK OVERRIDE FROM EXTERNAL FILE (.VOC)\n\t *-----------------------------------------------------------------------*/\n\n\t/* Open VOC file if one is requested. */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (config->VocFile != NULL) {\n\t\tvqap->vocfh = open(config->VocFile, (O_RDONLY|O_BINARY));\n\t} else {\n\t\tvqap->vocfh = -1;\n\t}\n\n\t/* Make sure we won't try to play audio. */\n\tif ((vqap->vocfh == -1) && ((header->Flags & VQAHDF_AUDIO) == 0)) {\n\t\tconfig->OptionFlags &= (~VQAOPTF_AUDIO);\n\t}\n\t#else  /* VQAVOC_ON */\n\n\t/* If the movie does not contain an audio track make sure we won't try\n\t * to play one.\n\t */\n\tif (((header->Flags & VQAHDF_AUDIO) == 0)) {\n\t\tconfig->OptionFlags &= (~VQAOPTF_AUDIO);\n\t}\n\t#endif /* VQAVOC_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE AUDIO PLAYBACK/TIMING SYSTEM.\n\t *-----------------------------------------------------------------------*/\n\t#if(VQAAUDIO_ON)\n\tif (config->OptionFlags & VQAOPTF_AUDIO) {\n\t\tVQAAudio *audio;\n\n\t\t/* Dereference for quick access. */\n\t\taudio = &vqap->VQABuf->Audio;\n\n\t\t/* Open HMI audio resource for playback. */\n\t\tif (VQA_OpenAudio(vqap)) {\n\t\t\tVQA_Close(vqa);\n\t\t\treturn (VQAERR_AUDIO);\n\t\t}\n\n\t\t/* Initialize ADPCM information structure for audio stream. */\n\t\tsosCODECInitStream(&audio->ADPCM_Info);\n\n\t\tif (header->Version == VQAHD_VER1) {\n\t\t\taudio->ADPCM_Info.wBitSize = 8;\n\t\t\taudio->ADPCM_Info.dwUnCompSize = (22050L/header->FPS) * header->Frames;\n\t\t\taudio->ADPCM_Info.wChannels = 1;\n\t\t} else {\n\t\t\taudio->ADPCM_Info.wBitSize = audio->BitsPerSample;\n\t\t\taudio->ADPCM_Info.dwUnCompSize = (((audio->SampleRate / header->FPS)\n\t\t\t\t\t* (audio->BitsPerSample >> 3)) * audio->Channels) * header->Frames;\n\n\t\t\taudio->ADPCM_Info.wChannels = audio->Channels;\n\t\t}\n\n\t\taudio->ADPCM_Info.dwCompSize = audio->ADPCM_Info.dwUnCompSize\n\t\t\t\t/ (audio->ADPCM_Info.wBitSize / 4);\n\t}\n\n\t/* Turn off audio if the HMI DigiHandle is invalid. */\n\tif (config->DigiHandle == -1) {\n\t\tconfig->OptionFlags &= ~VQAOPTF_AUDIO;\n\t}\n\n\t/* Setup the timer interrupt if the client requests it for the timing\n\t * source.\n\t */\n\tif (!(config->OptionFlags & VQAOPTF_AUDIO)\n\t\t\t|| (config->TimerMethod == VQA_TMETHOD_INT)) {\n\n\t\t/* Start HMI timer system for timing. */\n\t\tif (VQA_StartTimerInt(vqap, (config->OptionFlags & VQAOPTF_HMIINIT))) { \n\t\t\tVQA_Close(vqa);\n\t\t\treturn (VQAERR_AUDIO);\n\t\t}\n\t}\n\t#endif /* VQAAUDIO_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * PRIME THE BUFFERS BY PRE-LOADING THEM WITH FRAME DATA.\n\t *-----------------------------------------------------------------------*/\n\tif (PrimeBuffers(vqa) != 0) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_READ);\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Close - Close an opened VQA file.\n*\n* SYNOPSIS\n*     VQA_Close(VQA)\n*\n*     void VQA_Close(VQAHandle *);\n*\n* FUNCTION\n*     Close the file that was opened with VQA_Open().\n*\n* INPUTS\n*     VQA - Pointer VQAHandle to close.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Close(VQAHandle *vqa)\n{\n\tlong (*iohandler)(VQAHandle *, long, void *, long);\n\n\t/* Restore video mode to text. */\n\t#if(VQAVIDEO_ON)\n\tSetVideoMode(TEXT);\n\t#endif /* VQAVIDEO_ON */\n\n\t/* Shutdown audio/timing system. */\n\t#if(VQAAUDIO_ON)\n\tif (((VQAHandleP *)vqa)->Config.OptionFlags & VQAOPTF_AUDIO) {\n\t\tVQA_CloseAudio((VQAHandleP *)vqa);\n\t} else {\n\t\tVQA_StopTimerInt((VQAHandleP *)vqa);\n\t}\n\t#endif /* VQAAUDIO_ON */\n\n\t/* Free captions. */\n\tif (((VQAHandleP *)vqa)->Caption != NULL) {\n\t\tif (((VQAHandleP *)vqa)->Caption->Buffer != NULL) {\n\t\t\tfree(((VQAHandleP *)vqa)->Caption->Buffer);\n\t\t}\n\n\t\tCloseCaptions(((VQAHandleP *)vqa)->Caption);\n\t}\n\n\t/* Free EVA. */\n\tif (((VQAHandleP *)vqa)->EVA != NULL) {\n\t\tif (((VQAHandleP *)vqa)->EVA->Buffer != NULL) {\n\t\t\tfree(((VQAHandleP *)vqa)->EVA->Buffer);\n\t\t}\n\n\t\tCloseCaptions(((VQAHandleP *)vqa)->EVA);\n\t}\n\n\t/* Free memory */\n\tif (((VQAHandleP *)vqa)->VQABuf != NULL) {\n\t\tFreeBuffers(((VQAHandleP *)vqa)->VQABuf, &((VQAHandleP *)vqa)->Config,\n\t\t\t\t&((VQAHandleP *)vqa)->Header);\n\t}\n\n\t/* Close the VOC override file if one was opened */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((VQAHandleP *)vqa)->vocfh != -1) {\n\t\tclose(((VQAHandleP *)vqa)->vocfh);\n\t}\n\t#endif /* VQAVOC_ON */\n\n\t/* Close the VQA file */\n\t((VQAHandleP *)vqa)->IOHandler(vqa, VQACMD_CLOSE, NULL, 0);\n\n\t/* Reset the VQAHandle */\n\tiohandler = ((VQAHandleP *)vqa)->IOHandler;\n\tmemset(vqa, 0, sizeof(VQAHandleP));\n\t((VQAHandleP *)vqa)->IOHandler = iohandler;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_LoadFrame - Load the next video frame from the VQA data stream.\n*\n* SYNOPSIS\n*     Error = VQA_LoadFrame(VQA)\n*\n*     long VQA_LoadFrame(VQAHandle *);\n*\n* FUNCTION\n*     The codebook is split up such that the last frame of every group gets\n*     a new, complete codebook, ready for the next group.  The first codebook\n*     in the VQA is a full codebook, and goes with the first frame's data.\n*     Partial codebooks are stored per frame after that, and they add up to\n*     a full codebook just before the first frame for the next group is read.\n*\n*     (Currently, this routine can read either the older non-frame-grouped\n*     VQA file format, or the new frame-chunk format.  For the older format,\n*     it's assumed that the last chunk in a frame is the pointer data.)\n*\n*     This routine also does a sort of \"cooperative multitasking\".  If the\n*     Loader hits a \"wait state\" where it has to wait on the audio to finish\n*     playing before it can continue to load, it sets a \"sleep\" flag and\n*     just returns.  The sleep flag is checked on entry to see if it needs\n*     to jump to the proper execution point. This may improve performance on\n*     some platforms, but it also allows the Loader to be called regardless\n*     of the size of the buffers; if the buffers fill up or the audio fails\n*     to play, the Loader won't just get stuck.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle structure.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nlong VQA_LoadFrame(VQAHandle *vqa)\n{\n\tVQAHandleP    *vqap;\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQAFrameNode  *curframe;\n\tChunkHeader   *chunk;\n\tunsigned long iffsize;\n\tlong          frame_loaded = 0;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqap = (VQAHandleP *)vqa;\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\tcurframe = loader->CurFrame;\n\tchunk = &loader->CurChunkHdr;\n\n\t/* We have reached the end of the file if we loaded all the frames. */\n\tif (loader->CurFrameNum >= vqap->Header.Frames) {\n\t\treturn (VQAERR_EOF);\n\t}\n\n\t/* If we're reading audio from a VOC file then service that requirement. */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (vqap->vocfh != -1) {\n\t\tLoad_AudFrame(vqap);\n\t}\n\t#endif /* VQAAUDIO_ON & VQAVOC_ON */\n\n\t/* If no buffer is available for loading then return. This allows the\n\t * drawer to service one of the buffers more readily. (We'll wait for one\n\t * to free up).\n\t */\n\tif (curframe->Flags & VQAFRMF_LOADED) {\n\t\tloader->WaitsOnDrawer++;\n\t\treturn (VQAERR_NOBUFFER);\n\t}\n\n\t/* If we're not sleeping, initialize */\n\tif (!(vqabuf->Flags & VQADATF_LSLEEP)) {\n\t\tframe_loaded = 0;\n\t\tloader->FrameSize = 0;\n\n\t\t/* Initialize the codebook ptr for the frame we're about to load:\n\t\t * (This frame's codebook is the last full codebook; we have to init it\n\t\t * now, because if we're on the last frame in a group, we'll get a new\n\t\t * FullCB pointer.)\n\t\t */\n\t\tcurframe->Codebook = loader->FullCB;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * THE MAIN LOADER LOOP\n\t *-----------------------------------------------------------------------*/\n\twhile (frame_loaded == 0) {\n\n\t\t/* Read new chunk, only if we're not sleeping */\n\t\tif (!(vqabuf->Flags & VQADATF_LSLEEP)) {\n\n\t\t\t/* Read chunk ID */\n\t\t\tif (vqap->IOHandler(vqa, VQACMD_READ, chunk, 8)) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\n\t\t\tiffsize = REVERSE_LONG(chunk->size);\n\t\t\tloader->FrameSize += iffsize;\n\t\t}\n\n\t\t/* Handle each chunk type */\n\t\tswitch (chunk->id) {\n\n\t\t\t/* VQ Normal Frame */\n\t\t\tcase ID_VQFR:\n\t\t\t\tif (Load_VQF(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* VQ Key Frame */\n\t\t\tcase ID_VQFK:\n\t\t\t\tif (Load_VQF(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as being key. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_KEY;\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* Full uncompressed codebook */\n\t\t\tcase ID_CBF0:\n\t\t\t\tif (Load_CBF0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Full compressed codebook */\n\t\t\tcase ID_CBFZ:\n\t\t\t\tif (Load_CBFZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Partial uncompressed codebook */\n\t\t\tcase ID_CBP0:\n\t\t\t\tif (Load_CBP0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Partial compressed codebook */\n\t\t\tcase ID_CBPZ:\n\t\t\t\tif (Load_CBPZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed palette */\n\t\t\tcase ID_CPL0:\n\t\t\t\tif (Load_CPL0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as having a palette. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_PALETTE;\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed palette */\n\t\t\tcase ID_CPLZ:\n\t\t\t\tif (Load_CPLZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as having a palette. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_PALETTE;\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed pointer data */\n\t\t\tcase ID_VPT0:\n\t\t\t\tif (Load_VPT0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed pointer data */\n\t\t\tcase ID_VPTZ:\n\t\t\tcase ID_VPTD:\n\t\t\t\tif (Load_VPTZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* Pointer data Key (Must draw) */\n\t\t\tcase ID_VPTK:\n\t\t\t\tif (Load_VPTZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as being key. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_KEY;\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed audio frame.\n\t\t\t *\n\t\t\t *  - Make sure the sound load buffer (Audio.TempBuf) is empty; if not\n\t\t\t *    go into a sleep state.\n\t\t\t *  - Load the data into TempBuf.\n\t\t\t */\n\t\t\t#if(VQAAUDIO_ON)\n\t\t\tcase ID_SND0:\n\t\t\t\tif (!(vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO)) {\n\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load an uncompressed audio frame. */\n\t\t\t\t\tif (Load_SND0(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ID_SNA0:\n\t\t\t\tif (vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO) {\n\t\t\t\t\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load an uncompressed audio frame. */\n\t\t\t\t\tif (Load_SND0(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed audio frame.\n\t\t\t *\n\t\t\t *  - Make sure the sound load buffer (Audio.TempBuf) is empty; if not\n\t\t\t *    go into a sleep state.\n\t\t\t *  - Load the data into TempBuf.\n\t\t\t */\n\t\t\tcase ID_SND1:\n\t\t\t\tif (!(vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO)) {\n\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load a compressed audio frame. */\n\t\t\t\t\tif (Load_SND1(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ID_SNA1:\n\t\t\t\tif (vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO) {\n\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load a compressed audio frame. */\n\t\t\t\t\tif (Load_SND1(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* HMI ADPCM compressed audio frame.\n\t\t\t *\n\t\t\t *  - Make sure the sound load buffer (Audio.TempBuf) is empty; if not\n\t\t\t *    go into a sleep state.\n\t\t\t *  - Load the data into TempBuf.\n\t\t\t */\n\t\t\tcase ID_SND2:\n\t\t\t\tif (!(vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO)) {\n\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load a compressed audio frame. */\n\t\t\t\t\tif (Load_SND2(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ID_SNA2:\n\t\t\t\tif (vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO) {\n\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load a compressed audio frame. */\n\t\t\t\t\tif (Load_SND2(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\t/* Skip any unknown chunks. */\n\t\t\tdefault:\n\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/* Update maximum frame size stat. */\n\tif ((loader->CurFrameNum>0) && (loader->FrameSize>loader->MaxFrameSize)) {\n\t\tloader->MaxFrameSize = loader->FrameSize;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * SET UP THE FRAME FOR DRAWING.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Set the frame # */\n\tcurframe->FrameNum = loader->CurFrameNum;\n\tloader->CurFrameNum++;\n\n\t/* Update data for mono output */\n\tloader->LastFrameNum = loader->CurFrameNum;\n\n\t/* Loader is finished with this frame; tell Drawer to draw it */\n\tcurframe->Flags |= VQAFRMF_LOADED;\n\tloader->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_SeekFrame - Position the movie stream to the specified frame.\n*\n* SYNOPSIS\n*     Frame = VQA_SeekFrame(VQA, Frame, FromWhere)\n*\n*     long VQA_SeekFrame(VQAHandle *, long, long);\n*\n* FUNCTION\n*     This function sets the movie stream to the new frame specified by\n*     the 'offset' parameter. 'FromWhere' is a symbolic constant that is used\n*     to specify from where in the stream offset should be applied. \n*\n* INPUTS\n*     VQA       - Pointer to VQAHandle of movie to seek into.\n*     Frame     - Frame to seek to.\n*     FromWhere - Relative position indicator.\n*\n* RESULT\n*     Frame - New frame position or -1 if error.\n*\n****************************************************************************/\n\nlong VQA_SeekFrame(VQAHandle *vqa, long framenum, long fromwhere)\n{\n\tVQAHandleP   *vqap;\n\tVQAData      *vqabuf;\n\tVQALoader    *loader;\n\tVQAHeader    *header;\n\tVQAFrameNode *frame;\n\tlong         group;\n\tlong         i;\n\tlong         rc = VQAERR_SLEEPING;\n\n\t#if(VQAAUDIO_ON)\n\tVQAConfig    *config;\n\tVQAAudio     *audio;\n\tlong         audio_on;\n \t#endif\n\n\t/* Dereference commonly used data members for quick access. */\n\tvqap = (VQAHandleP *)vqa;\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\theader = &vqap->Header;\n\n\t#if(VQAAUDIO_ON)\n\tconfig = &vqap->Config;\n\t#endif\n\n\tfromwhere = fromwhere;\n\t\n\t#if(VQAAUDIO_ON)\n\taudio = &vqabuf->Audio;\n\n\t/* Stop audio playback. */\n\taudio_on = (audio->Flags & VQAAUDF_ISPLAYING);\n\tVQA_StopAudio(vqap);\n\t#endif\n\n\t/* Make sure the requested frame is valid and the frame information\n\t * array is allocated before continuing.\n\t */\n\tif ((framenum < header->Frames) && (vqabuf->Foff != NULL)) {\n\t\t\n\t\t/* Get the current frame. */\n\t\tframe = loader->CurFrame;\n\n\t\t/* Find and load the most recent palette. */\n\t\tfor (i = framenum; i >= 0; i--) {\n\t\t\tif (vqabuf->Foff[i] & VQAFINF_PAL) {\n\n\t\t\t\t/* Seek to the palette frame. */\n\t\t\t\trc = vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_SET,\n\t\t\t\t\t\tVQAFRAME_OFFSET(vqabuf->Foff[i]));\n\n\t\t\t\tif (!rc) {\n\n\t\t\t\t\t/* Fool the loader into thinking this frame is empty. */\n\t\t\t\t\tloader->NumPartialCB = 0;\n\t\t\t\t\tloader->PartialCBSize = 0;\n\t\t\t\t\tloader->FullCB = vqabuf->CBData;\n\t\t\t\t\tloader->CurCB = vqabuf->CBData;\n\t\t\t\t\tloader->CurFrameNum = 0;\n\t\t\t\t\tframe->Flags = 0;\n\n\t\t\t\t\t/* Load the frame with the palette. */\n\t\t\t\t\tif (VQA_LoadFrame(vqa) == 0) {\n\n\t\t\t\t\t\t/* Decompress the palette if neccessary.*/\n\t\t\t\t\t\tif (frame->Flags & VQAFRMF_PALCOMP) {\n\t\t\t\t\t\t\tframe->PaletteSize = LCW_Uncompress((char *)frame->Palette\n\t\t\t\t\t\t\t\t\t+ frame->PalOffset, (char *)frame->Palette,\n\t\t\t\t\t\t\t\t\tvqabuf->Max_Pal_Size);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tSetPalette(frame->Palette, frame->PaletteSize, 0);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\trc = VQAERR_SEEK;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!rc) {\n\t\t\t/* Compute the starting group frame of the requested frame. */\n\t\t\tgroup = (framenum / header->Groupsize);\n\t\t\tgroup = (group * header->Groupsize);\n\n\t\t\t/* The codebook for the group we want to goto is found in the previous\n\t\t\t * group, with the exception of the very first group.\n\t\t\t */\n\t\t\tif (group >= header->Groupsize) {\n\t\t\t\tgroup -= header->Groupsize;\n\t\t\t}\n\n\t\t\t/* Seek to the start of the group containing the partial codebooks for\n\t\t\t * the target frame.\n\t\t\t */\n\t\t\tif (!vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_SET,\n\t\t\t\t\tVQAFRAME_OFFSET(vqabuf->Foff[group]))) {\n\n\t\t\t\t/* Throw away any audio frames that were loaded. */\n\t\t\t\t#if(VQAAUDIO_ON)\n\t\t\t\tif ((config->OptionFlags & VQAOPTF_AUDIO)\n\t\t\t\t\t\t&& (audio->Buffer != NULL)) {\n\t\t\t\t\tmemset(audio->IsLoaded, 0, audio->NumAudBlocks * sizeof(short));\n\t\t\t\t\tmemset(audio->Buffer, 0, config->AudioBufSize);\n\n\t\t\t\t\t/* Position the audio buffer to 1/2 second. */\n\t\t\t\t\taudio->AudBufPos = (long)(((audio->SampleRate * audio->Channels)\n\t\t\t\t\t\t\t* (audio->BitsPerSample >> 3)) / 2);\n\n\t\t\t\t\t/* Mark 1/2 second of the audio buffer as loaded. */\n\t\t\t\t\tfor (i = 0; i < (audio->AudBufPos / config->HMIBufSize); i++) {\n\t\t\t\t\t\taudio->IsLoaded[i] = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\t/* Force the loader to the desired frame. */\n\t\t\t\tloader->NumPartialCB = 0;\n\t\t\t\tloader->PartialCBSize = 0;\n\t\t\t\tloader->FullCB = vqabuf->CBData;\n\t\t\t\tloader->CurCB = vqabuf->CBData;\n\t\t\t\tloader->CurFrameNum = group;\n\n\t\t\t\t/* Load frames up to the target frame collecting partial codebooks\n\t\t\t\t * along the way.\n\t\t\t\t */\n\t\t\t\tfor (i = 0; i < (framenum - group); i++) {\n\t\t\t\n\t\t\t\t\t/* Fool the loader into thinking the frame has been drawn. */\n\t\t\t\t\tloader->CurFrame->Flags = 0;\n\n\t\t\t\t\t#if(VQAAUDIO_ON)\n\t\t\t\t\taudio->TempBufLen = 0;\n\t\t\t\t\t#endif\n\n\t\t\t\t\t/* Load the frame. */\n\t\t\t\t\tif ((rc = VQA_LoadFrame(vqa)) != 0) {\n\t\t\t\t\t\tif ((rc != VQAERR_NOBUFFER) && (rc != VQAERR_SLEEPING)) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\trc = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* If everything is okay, then re-prime the buffers. */\n\t\t\t\tif (!rc) {\n\n\t\t\t\t\t/* Mark all the frames except the current one as empty. */\n\t\t\t\t\tloader->CurFrame->Flags = 0;\n\t\t\t\t\tframe = loader->CurFrame->Next;\n\n\t\t\t\t\twhile (frame != loader->CurFrame) {\n\t\t\t\t\t\tframe->Flags = 0;\n\t\t\t\t\t\tframe = frame->Next;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Set the drawer to the current frame and the loader\n\t\t\t\t\t * to the next.\n\t\t\t\t\t */\n\t\t\t\t\tvqabuf->Drawer.CurFrame = loader->CurFrame;\n\n\t\t\t\t\t/* Prime the buffers for the new position. */\n\t\t\t\t\trc = PrimeBuffers(vqa);\n\n\t\t\t\t\t/* An end of file is not considered and error. */\n\t\t\t\t\tif ((rc == 0) || (rc == VQAERR_EOF)) {\n\t\t\t\t\t\trc = framenum;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trc = VQAERR_SEEK;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Restart audio playback. */\n\t#if(VQAAUDIO_ON)\n\tif (audio_on) {\n\t\tVQA_StartAudio(vqap);\n\t}\n\t#endif\n\n\treturn (rc);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     AllocBuffers - Allocate VQA play buffers.\n*\n* SYNOPSIS\n*     VQAData = AllocBuffers(Header, Config)\n*\n*     VQAData *AllocBuffers(VQAHeader *, VQAConfig *);\n*\n* FUNCTION\n*     For those structures that contain buffer pointers (codebook nodes,\n*     frame buffer nodes), enough memory is allocated for both the structure\n*     and its associated buffers, then the buffer pointers are pointed to\n*     the appropriate offset from the structure pointer.  This allows us\n*     to perform only one malloc & free for each node.\n*\n*     Buffers allocated:\n*       - vqa\n*       - vqa->CBData (list)\n*       - vqa->FrameData (list)\n*       - vqa->Drawer.ImageBuf\n*       - vqa->Audio.Buffer\n*       - vqa->Audio.IsLoaded\n*       - vqa->Foff\n*\n* INPUTS\n*     Header - Pointer to VQAHeader structure.\n*     Config - Pointer to VQA configuration structure.\n*\n* RESULT\n*     VQAData - Pointer to initialized VQAData structure.\n*\n****************************************************************************/\n\nstatic VQAData *AllocBuffers(VQAHeader *header, VQAConfig *config)\n{\n\tVQAData      *vqa;\n\tVQACBNode    *cbnode;\n\tVQACBNode    *this_cb;\n\tVQAFrameNode *framenode;\n\tVQAFrameNode *this_frame;\n\tlong         i;\n\n\t/* Check the configuration for valid values. */\n\tif ((config->NumCBBufs == 0) || (config->NumFrameBufs == 0)) {\n\t\treturn (NULL);\n\t}\n\n\t/* Allocate the master structure */\n\tif ((vqa = (VQAData *)malloc(sizeof(VQAData))) == NULL) {\n\t\treturn (NULL);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE VQA DATA STRUCTURES.\n\t *\n\t * Pointers are set to NULL initially, and filled in as the buffers are\n\t * allocated.  The Max buffer sizes are computed with 1K of padding,\n\t * and'd with 0xFFFC to make the size divisible by 4, to ensure DWORD\n\t * alignment.\n\t *-----------------------------------------------------------------------*/\n\tDPMI_Lock(vqa, sizeof(VQAData));\n\tmemset(vqa, 0, sizeof(VQAData));\n\tvqa->MemUsed = sizeof(VQAData);\n\tvqa->Drawer.LastTime = (-VQA_TIMETICKS);\n\n\t/* Set maximum codebook size. */\n\tvqa->Max_CB_Size = ((header->CBentries) * header->BlockWidth\n\t\t\t* header->BlockHeight + 250) & 0xFFFC;\n\n\t/* Set maximum palette size. */\n\tvqa->Max_Pal_Size = (768 + 1024) & 0xFFFC;\n\n\t/* Set maximum vector pointers size. */\n\tvqa->Max_Ptr_Size = ((header->ImageWidth / header->BlockWidth)\n\t\t\t* (header->ImageHeight / header->BlockHeight)\n\t\t\t* sizeof(short) + 1024) & 0xFFFC;\n\n\t/* Set the frame number of the frame containing the last codebook. */\n\tvqa->Loader.LastCBFrame = (((header->Frames - 1) / header->Groupsize)\n\t\t\t* header->Groupsize);\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE THE CODEBOOK BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\tfor (i = 0; i < config->NumCBBufs; i++) {\n\n\t\t/* Allocate a codebook node. */\n\t\tcbnode = (VQACBNode *)malloc((sizeof(VQACBNode) + vqa->Max_CB_Size));\n\n\t\t/* If failure then clean up and exit. */\n\t\tif (cbnode == NULL) {\n\t\t\tFreeBuffers(vqa, config, header);\n\t\t\treturn (NULL);\n\t\t}\n\n\t\t/* Lock the buffer to prevent page swapping. */\n\t\tDPMI_Lock(cbnode, (sizeof(VQACBNode) + vqa->Max_CB_Size));\n\n\t\t/* Keep count of the memory usage. */\n\t\tvqa->MemUsed += (long)(sizeof(VQACBNode) + vqa->Max_CB_Size);\n\n\t\t/* Initialize the node */\n\t\tmemset(cbnode, 0, sizeof(VQACBNode));\n\t\tcbnode->Buffer = (unsigned char *)cbnode + sizeof(VQACBNode);\n\n\t\t/* Install the node */\n\t\tif (i == 0) {\n\t\t\tvqa->CBData = cbnode;\n\t\t\tthis_cb = cbnode;\n\t\t} else {\n\t\t\tthis_cb->Next = cbnode;\n\t\t\tthis_cb = cbnode;\n\t\t}\n\t}\n\n\t/* Make the list circular */\n\tcbnode->Next = vqa->CBData;\n\n\t/* Install the Codebook list */\n\tvqa->Loader.CurCB = vqa->CBData;\n\tvqa->Loader.FullCB = vqa->CBData;\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE THE FRAME BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\tfor (i = 0; i < config->NumFrameBufs; i++) {\n\t\t\n\t\t/* Allocate a pointer node */\n\t\tframenode = (VQAFrameNode *)malloc((sizeof(VQAFrameNode)\n\t\t\t\t+ vqa->Max_Ptr_Size + vqa->Max_Pal_Size));\n\n\t\t/* If failure then clean up and exit. */\n\t\tif (framenode == NULL) {\n\t\t\tFreeBuffers(vqa, config, header);\n\t\t\treturn (NULL);\n\t\t}\n\n\t\t/* Lock the buffer to prevent page swapping. */\n\t\tDPMI_Lock(framenode, sizeof(VQAFrameNode) + vqa->Max_Ptr_Size\n\t\t\t\t+ vqa->Max_Pal_Size);\n\n\t\t/* Keep count of the memory usage. */\n\t\tvqa->MemUsed += (long)(sizeof(VQAFrameNode) + vqa->Max_Ptr_Size\n\t\t\t\t+ vqa->Max_Pal_Size);\n\n\t\t/* Initialize the node */\n\t\tmemset(framenode, 0, sizeof(VQAFrameNode));\n\t\tframenode->Pointers = (unsigned char *)framenode + sizeof(VQAFrameNode);\n\t\tframenode->Palette = (unsigned char *)framenode + sizeof(VQAFrameNode)\n\t\t\t\t+ vqa->Max_Ptr_Size;\n\n\t\tframenode->Codebook = vqa->CBData;\n\n\t\t/* Install the node */\n\t\tif (i == 0) {\n\t\t\tvqa->FrameData = framenode;\n\t\t\tthis_frame = framenode;\n\t\t} else {\n\t\t\tthis_frame->Next = framenode;\n\t\t\tthis_frame = framenode;\n\t\t}\n\t}\n\n\t/* Make the list circular */\n\tframenode->Next = vqa->FrameData;\n\n\t/* Install the Frame Buffer list */\n\tvqa->Loader.CurFrame = vqa->FrameData;\n\tvqa->Drawer.CurFrame = vqa->FrameData;\n\tvqa->Flipper.CurFrame = vqa->FrameData;\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE THE IMAGE BUFFERS IF ONE IS NOT ALREADY PROVIDED.\n\t *-----------------------------------------------------------------------*/\n\tif (config->ImageBuf == NULL) {\n\n\t\t/* Allocate our own buffer. */\n\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\tvqa->Drawer.ImageBuf = (unsigned char *)malloc((header->ImageWidth\n\t\t\t\t\t* header->ImageHeight));\n\n\t\t\t/* If the allocation failed we must free up and exit. */\n\t\t\tif (vqa->Drawer.ImageBuf == NULL) {\n\t\t\t\tFreeBuffers(vqa, config, header);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\n\t\t\t/* Lock to prevent page swapping. */\n\t\t\tDPMI_Lock(vqa->Drawer.ImageBuf,header->ImageWidth*header->ImageHeight);\n\n\t\t\t/* Plugin image buffer information. */\n\t\t\tvqa->Drawer.ImageWidth = header->ImageWidth;\n\t\t\tvqa->Drawer.ImageHeight = header->ImageHeight;\n\t\t\tvqa->MemUsed += (long)(header->ImageWidth * header->ImageHeight);\n\t\t} else {\n\t\t\tvqa->Drawer.ImageWidth = config->ImageWidth;\n\t\t\tvqa->Drawer.ImageHeight = config->ImageHeight;\n\t\t}\n\t} else {\n\n\t\t/* Use caller provided buffer */\n\t\tvqa->Drawer.ImageBuf = config->ImageBuf;\n\t\tvqa->Drawer.ImageWidth = config->ImageWidth;\n\t\tvqa->Drawer.ImageHeight = config->ImageHeight;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE AND INITIALIZE AUDIO BUFFERS AND STRUCTURES.\n\t *-----------------------------------------------------------------------*/\n\t#if(VQAAUDIO_ON)\n\tif ((header->Flags & VQAHDF_AUDIO)\n\t\t\t&& (config->OptionFlags & VQAOPTF_AUDIO)) {\n\n\t\t/* Dereference audio structure for quick access. */\n\t\tVQAAudio *audio = &vqa->Audio;\n\n\t\t/* Version 1 VQA's only supported 22050 8 bit mono audio. */\n\t\tif (header->Version < VQAHD_VER2) {\n\t\t\taudio->SampleRate = 22050U;\n\t\t\taudio->Channels = 1;\n\t\t\taudio->BitsPerSample = 8;\n\t\t\taudio->BytesPerSec = 22050;\n\t\t} else {\n\t\t\tif ((config->OptionFlags & VQAOPTF_ALTAUDIO)\n\t\t\t\t\t&& (header->Flags & VQAHDF_ALTAUDIO)) {\n\t\t\t\taudio->SampleRate = header->AltSampleRate;\n\t\t\t\taudio->Channels = header->AltChannels;\n\t\t\t\taudio->BitsPerSample = header->AltBitsPerSample;\n\t\t\t} else {\n\t\t\t\taudio->SampleRate = header->SampleRate;\n\t\t\t\taudio->Channels = header->Channels;\n\t\t\t\taudio->BitsPerSample = header->BitsPerSample;\n\t\t\t}\n\n\t\t\taudio->BytesPerSec = ((audio->SampleRate * audio->Channels)\n\t\t\t\t\t* (audio->BitsPerSample >> 3));\n\t\t}\n\n\t\t/* Adjust the HMI buffer to accomodate the amount of data. */\n\t\t#if(0)\n\t\tconfig->HMIBufSize *= (audio->SampleRate / 22050);\n\t\tconfig->HMIBufSize *= audio->Channels * (audio->BitsPerSample >> 3);\n\t\t#endif\n\n\t\t/* The default audio buffer size should be large enough to hold\n\t\t * 1.5 seconds of data.\n\t\t */\n\t\tif (config->AudioBufSize == -1) {\n\n\t\t\t/* Compute the number of HMI buffers that will completly fit into\n\t\t\t * 1.5 seconds of audio data.\n\t\t\t */\n\t\t\ti = ((audio->BytesPerSec+(audio->BytesPerSec/2))/config->HMIBufSize);\n\t\t\tconfig->AudioBufSize = (config->HMIBufSize * i);\n\t\t}\n\n\t\t/* Do not allocate anything if the audio buffer is zero length. */\n\t\tif (config->AudioBufSize > 0) {\n\n\t\t\t/* Allocate an audio buffer if the user did not provide one.\n\t\t\t * Otherwise, use the user supplied buffer.\n\t\t\t */\n\t\t\tif (config->AudioBuf == NULL) {\n\t\t\t\taudio->Buffer = (unsigned char *)malloc(config->AudioBufSize);\n\n\t\t\t\t/* If failure then clean up and exit. */\n\t\t\t\tif (audio->Buffer == NULL) {\n\t\t\t\t\tFreeBuffers(vqa, config, header);\n\t\t\t\t\treturn (NULL);\n\t\t\t\t}\n\n\t\t\t\tDPMI_Lock(audio->Buffer, config->AudioBufSize);\n\n\t\t\t\t/* Add audio buffer size to memory usage. */\n\t\t\t\tvqa->MemUsed += config->AudioBufSize;\n\t\t\t} else {\n\t\t\t\taudio->Buffer = config->AudioBuf;\n\t\t\t}\n\n\t\t\t/* Allocate IsLoaded flags */\n\t\t\taudio->NumAudBlocks = (config->AudioBufSize / config->HMIBufSize);\n\t\t\taudio->IsLoaded = (short *)malloc(audio->NumAudBlocks * sizeof(short));\n\n\t\t\t/* If failure then clean up and exit. */\n\t\t\tif (audio->IsLoaded == NULL) {\n\t\t\t\tFreeBuffers(vqa, config, header);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\n\t\t\t/* Lock to prevent page swapping. */\n\t\t\tDPMI_Lock(audio->IsLoaded, audio->NumAudBlocks * sizeof(short));\n\n\t\t\t/* Add IsLoaded flags array to memory usage. */\n\t\t\tvqa->MemUsed += (audio->NumAudBlocks * sizeof(short));\n\n\t\t\t/* Initialize audio IsLoaded flags to false. */\n\t\t\tmemset(audio->IsLoaded, 0, audio->NumAudBlocks * sizeof(short));\n\n\t\t\t/* Allocate temporary staging buffer for the audio frames. */\n\t\t\taudio->TempBufSize = ((audio->BytesPerSec / header->FPS) * 2) + 100;\n\t\t\taudio->TempBuf = (unsigned char *)malloc(audio->TempBufSize);\n\n\t\t\tif (audio->TempBuf == NULL) {\n\t\t\t\tFreeBuffers(vqa, config, header);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\n\t\t\t/* Lock to prevent page swapping. */\n\t\t\tDPMI_Lock(audio->TempBuf, audio->TempBufSize);\n\n\t\t\t/* Add temporary buffer size to memory usage. */\n\t\t\tvqa->MemUsed += audio->TempBufSize;\n\t\t}\n\t}\n\t#endif /* VQAAUDIO_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE THE FRAME INFORMATION TABLE IF REQUESTED.\n\t *-----------------------------------------------------------------------*/\n\tvqa->Foff = (long *)malloc(header->Frames * sizeof(long));\n\n\tif (vqa->Foff == NULL) {\n\t\tFreeBuffers(vqa, config, header);\n\t\treturn (NULL);\n\t} \n\n\t/* Lock to prevent page swapping. */\n\tDPMI_Lock(vqa->Foff, header->Frames * sizeof(long));\n\n\t/* Keep a running total of memory usage. */\n\tvqa->MemUsed += (header->Frames * sizeof(long));\n\t\n\treturn (vqa);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     FreeBuffers - Free VQA play buffers.\n*\n* SYNOPSIS\n*     FreeBuffers(VQAData, Config, Header)\n*\n*     void FreeBuffers(VQAData *, VQAConfig *, VQAHeader *);\n*\n* FUNCTION\n*      Free the buffers allocated by AllocBuffers().\n*\n* INPUTS\n*      VQAData - Pointer to VQAData structure.\n*      Config  - Pointer to configuration structure.\n*      Header  - Pointer to movie header structure.\n*\n* RESULT\n*      NONE\n*\n****************************************************************************/\n\nstatic void FreeBuffers(VQAData *vqa, VQAConfig *config, VQAHeader *header)\n{\n\tVQACBNode    *cb_this,\n\t             *cb_next;\n\tVQAFrameNode *frame_this,\n\t             *frame_next;\n\tlong         i;\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE FRAME INFORMATION TABLE.\n\t *-----------------------------------------------------------------------*/\n\tif (vqa->Foff) {\n\t\tDPMI_Unlock(vqa->Foff, header->Frames * sizeof(long));\n\t\tfree(vqa->Foff);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE AUDIO BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\n\t#if(VQAAUDIO_ON)\n\tif ((config->AudioBuf == NULL) && (vqa->Audio.Buffer)) {\n\t\tDPMI_Unlock(vqa->Audio.Buffer, config->AudioBufSize);\n\t\tfree(vqa->Audio.Buffer);\n\t}\n\n\t/* Free the audio segments loaded flag array. */\n\tif (vqa->Audio.IsLoaded) {\n\t\tDPMI_Unlock(vqa->Audio.IsLoaded,vqa->Audio.NumAudBlocks * sizeof(short));\n\t\tfree(vqa->Audio.IsLoaded);\n\t}\n\n\t/* Free the temporary audio buffer. */\n\tif (vqa->Audio.TempBuf) {\n\t\tDPMI_Unlock(vqa->Audio.TempBuf, vqa->Audio.TempBufSize);\n\t\tfree(vqa->Audio.TempBuf);\n\t}\n\t#endif /* VQAAUDIO_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE IMAGE BUFFER ONLY IF WE ALLOCATED IT.\n\t *-----------------------------------------------------------------------*/\n\tif ((config->ImageBuf == NULL) && vqa->Drawer.ImageBuf) {\n\t\tDPMI_Unlock(vqa->Drawer.ImageBuf,header->ImageWidth*header->ImageHeight);\n\t\tfree(vqa->Drawer.ImageBuf);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE FRAME BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\tframe_this = vqa->FrameData;\n\n\tfor (i = 0; i < config->NumFrameBufs; i++) {\n\t\tif (frame_this) {\n\t\t\tframe_next = frame_this->Next;\n\t\t\tDPMI_Unlock(frame_this, sizeof(VQAFrameNode) + vqa->Max_Ptr_Size\n\t\t\t\t\t+ vqa->Max_Pal_Size);\n\t\t\tfree(frame_this);\n\t\t\tframe_this = frame_next;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE CODEBOOK BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\tcb_this = vqa->CBData;\n\n\tfor (i = 0; i < config->NumCBBufs; i++) {\n\t\tif (cb_this) {\n\t\t\tcb_next = cb_this->Next;\n\t\t\tDPMI_Unlock(cb_this, sizeof(VQACBNode) + vqa->Max_CB_Size);\n\t\t\tfree(cb_this);\n\t\t\tcb_this = cb_next;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE VQA DATA STRUCTURES.\n\t *-----------------------------------------------------------------------*/\n\tDPMI_Unlock(vqa, sizeof(VQAData));\n\tfree(vqa);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PrimeBuffers - Pre-Load the internal buffers.\n*\n* SYNOPSIS\n*     Error = PrimeBuffers(VQA)\n*\n*     long = PrimeBuffers(VQAHandle *);\n*\n* FUNCTION\n*     Pre-load the internal buffers in order to give the player some slack\n*     in the playback of large frames.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle structure.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nlong PrimeBuffers(VQAHandle *vqa)\n{\n\tVQAData   *vqabuf;\n\tVQAConfig *config;\n\tlong      rc;\n\tlong      i;\n\n\t/* Dereference commonly used data members for quick access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* Pre-load the buffers */\n\tfor (i = 0; i < config->NumFrameBufs; i++) {\n\t\tif ((rc = VQA_LoadFrame(vqa)) == 0) {\n\t\t\tvqabuf->LoadedFrames++;\n\t\t}\n\t\telse if ((rc != VQAERR_NOBUFFER) && (rc != VQAERR_SLEEPING)) {\n\t\t\treturn (rc);\n\t\t}\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_VQF - Loads a VQ Frame chunk.\n*\n* SYNOPSIS\n*     Error = Load_VQF(VQA, Iffsize)\n*\n*     long Load_VQF(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*     The VQ Frame Chunk contains a set of other chunks (codebooks,\n*     palettes, pointers).  This routine reads the frame's chunk size,\n*     then loops until it's read that many bytes.\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_VQF(VQAHandleP *vqap, unsigned long frame_iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQAFrameNode  *curframe;\n\tChunkHeader   *chunk;\n\tunsigned long iffsize;\n\tunsigned long framesize;\n\tunsigned long bytes_loaded = 0;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tcurframe = vqabuf->Loader.CurFrame;\n\tchunk = &vqabuf->Loader.CurChunkHdr;\n\tframesize = PADSIZE(frame_iffsize);\n\n\t/*-------------------------------------------------------------------------\n\t * FRAME LOADING LOOP.\n\t *-----------------------------------------------------------------------*/\n\twhile (bytes_loaded < framesize) {\n\n\t\t/* Read chunk ID */\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, chunk, 8)) {\n\t\t\treturn (VQAERR_EOF);\n\t\t}\n\n\t\tiffsize = REVERSE_LONG(chunk->size);\n\t\tbytes_loaded += 8;\n\t\tbytes_loaded += PADSIZE(iffsize);\n\n\t\t/* Handle each chunk type */\n\t\tswitch (chunk->id) {\n\n\t\t\t/* Full uncompressed codebook */\n\t\t\tcase ID_CBF0:\n\t\t\t\tif (Load_CBF0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Full compressed codebook */\n\t\t\tcase ID_CBFZ:\n\t\t\t\tif (Load_CBFZ(vqap, iffsize)) {\n\t\t\t\t \treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Partial uncompressed codebook */\n\t\t\tcase ID_CBP0:\n\t\t\t\tif (Load_CBP0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Partial compressed codebook */\n\t\t\tcase ID_CBPZ:\n\t\t\t\tif (Load_CBPZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed palette */\n\t\t\tcase ID_CPL0:\n\t\t\t\tif (Load_CPL0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as having a palette. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_PALETTE;\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed palette */\n\t\t\tcase ID_CPLZ:\n\t\t\t\tif (Load_CPLZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as having a palette. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_PALETTE;\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed pointer data */\n\t\t\tcase ID_VPT0:\n\t\t\t\tif (Load_VPT0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed pointer data */\n\t\t\tcase ID_VPTZ:\n\t\t\tcase ID_VPTD:\n\t\t\t\tif (Load_VPTZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed pointer data */\n\t\t\tcase ID_VPTK:\n\t\t\t\tif (Load_VPTZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as being key. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_KEY;\n\t\t\t\tbreak;\n\n\t\t\t/* An unknown chunk in the video frame is an error. */\n\t\t\tdefault:\n\t\t\t\treturn (VQAERR_READ);\n\t\t}\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_FINF - Load Frame Info chunk.\n*\n* SYNOPSIS\n*     Error = Load_FINF(VQA, Iffsize)\n*\n*     long Load_FINF(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*     Load FINF chunk if buffer available, otherwise skip it.\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_FINF(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData *vqabuf;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\n\t/* Load the frame information table if we need to, otherwise we will\n\t * skip it.\n\t */\n\tif (vqabuf->Foff != NULL) {\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, vqabuf->Foff,\n\t\t\t\tPADSIZE(iffsize))) {\n\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\t} else {\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\tPADSIZE(iffsize))) {\n\t\t\treturn (VQAERR_SEEK);\n\t\t}\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_VQHD - Load VQA header chunk.\n*\n* SYNOPSIS\n*     Error = Load_VQHD(VQA, Iffsize)\n*\n*     long Load_VQHD(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_VQHD(VQAHandleP *vqap, unsigned long iffsize)\n{\n\t/* Read the header */\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, &vqap->Header,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Reconfigure the Drawer for the new settings */\n\tVQA_Configure_Drawer(vqap);\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CBF0 - Load full uncompressed codebook.\n*\n* SYNOPSIS\n*     Error = Load_CBF0(VQA, Iffsize)\n*\n*     long Load_CBF0(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CBF0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQALoader *loader;\n\tVQACBNode *curcb;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tloader = &vqap->VQABuf->Loader;\n\tcurcb = loader->CurCB;\n\n\t/* Read into the start of the buffer */\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, curcb->Buffer,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Reset the partial codebook counter. */\n\tloader->NumPartialCB = 0;\n\n\t/* Flag this codebook as uncompressed. */\n\tcurcb->Flags &= (~VQACBF_CBCOMP);\n\tcurcb->CBOffset = 0;\n\n\t/* Clock pointers to next CB Buffer. */\n\tloader->FullCB = curcb;\n\tloader->FullCB->Flags &= (~VQACBF_DOWNLOADED);\n\tloader->CurCB = curcb->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CBFZ - Load full compressed codebook.\n*\n* SYNOPSIS\n*     Error = Load_CBFZ(VQA, Iffsize)\n*\n*     long Load_CBFZ(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CBFZ(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQALoader     *loader;\n\tVQACBNode     *curcb;\n\tvoid          *buffer;\n\tunsigned long padsize;\n\tunsigned long lcwoffset;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tloader = &vqap->VQABuf->Loader;\n\tcurcb = loader->CurCB;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* Load the codebook into the end of the buffer. */\n\tlcwoffset = vqap->VQABuf->Max_CB_Size - padsize;\n\tbuffer = curcb->Buffer + lcwoffset;\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Reset the partial codebook counter. */\n\tloader->NumPartialCB = 0;\n\n\t/* Flag this codebook as compressed */\n\tcurcb->Flags |= VQACBF_CBCOMP;\n\tcurcb->CBOffset = lcwoffset;\n\n\t/* Clock pointers to next CB Buffer */\n\tloader->FullCB = curcb;\n\tloader->FullCB->Flags &= (~VQACBF_DOWNLOADED);\n\tloader->CurCB = curcb->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CBP0 - Load partial uncompressed codebook.\n*\n* SYNOPSIS\n*     Error = Load_CBP0(VQA, Iffsize)\n*\n*     long Load_CBP0(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CBP0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData   *vqabuf;\n\tVQALoader *loader;\n\tVQACBNode *curcb;\n\tvoid      *buffer;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\tcurcb = loader->CurCB;\n\n\t/*-------------------------------------------------------------------------\n\t * ASSEMBLY PARTIAL CODEBOOKS.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Read the partial codebook into the next position in the buffer. */\n\tbuffer = curcb->Buffer + loader->PartialCBSize;\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Accumulate the partial codebook values. */\n\tloader->PartialCBSize += iffsize;\n\tloader->NumPartialCB++;\n\n\t/*-------------------------------------------------------------------------\n\t * PROCESS FULL CODEBOOK.\n\t *-----------------------------------------------------------------------*/\n\tif (loader->NumPartialCB == vqap->Header.Groupsize) {\n\n\t\t/* Reset the codebook accumulator values */\n\t\tloader->NumPartialCB = 0;\n\t\tloader->PartialCBSize = 0;\n\n\t\t/* Flag this codebook as uncompressed */\n\t\tcurcb->Flags &= (~VQACBF_CBCOMP);\n\t\tcurcb->CBOffset = 0;\n\n\t\t/* Go to the next codebook buffer */\n\t\tloader->FullCB = curcb;\n\t\tloader->FullCB->Flags &= (~VQACBF_DOWNLOADED);\n\t\tloader->CurCB = curcb->Next;\n\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CBPZ - Load partial compressed codebook.\n*\n* SYNOPSIS\n*     Error = Load_CBPZ(VQA, Iffsize)\n*\n*     long Load_CBPZ(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CBPZ(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQACBNode     *curcb;\n\tvoid          *buffer;\n\tunsigned long padsize;\n\n\t/* Dereference commonly used data members for quicker access */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\tcurcb = loader->CurCB;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* Attempt to compute the LCW offset into the codebook buffer by\n\t * multiplying the size of this chunk by the # frames/group, and adding\n\t * a small fudge factor on, then subtracting that from the CB buffer size.\n\t */\n\tif (loader->PartialCBSize == 0) {\n\t\tcurcb->CBOffset = (vqabuf->Max_CB_Size\n\t\t\t\t- (padsize * vqap->Header.Groupsize + 100));\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * ASSEMBLE PARTIAL CODEBOOKS.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Read the partial codebook into the next position in the buffer. */\n\tbuffer = ((curcb->Buffer + curcb->CBOffset) + loader->PartialCBSize);\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Accumulate partial codebook values */\n\tloader->PartialCBSize += iffsize;\n\tloader->NumPartialCB++;\n\n\t/*-------------------------------------------------------------------------\n\t * PROCESS FULL CODEBOOK.\n\t *-----------------------------------------------------------------------*/\n\tif (loader->NumPartialCB == vqap->Header.Groupsize) {\n\n\t\t/* Reset the codebook accumulator values. */\n\t\tloader->NumPartialCB = 0;\n\t\tloader->PartialCBSize = 0;\n\n\t\t/* Flag this codebook as compressed. */\n\t\tcurcb->Flags |= VQACBF_CBCOMP;\n\n\t\t/* Go to the next codebook buffer */\n\t\tloader->FullCB = curcb;\n\t\tloader->FullCB->Flags &= (~VQACBF_DOWNLOADED);\n\t\tloader->CurCB = curcb->Next;\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CPL0 - Load an uncompressed palette.\n*\n* SYNOPSIS\n*     Error = Load_CPL0(VQA, Iffsize)\n*\n*     long Load_CPL0(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CPL0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAFrameNode *curframe;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tcurframe = vqap->VQABuf->Loader.CurFrame;\n\n\t/* Read the palette into the palette buffer */\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, curframe->Palette,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Flag the palette as uncompressed. */\n\tcurframe->Flags &= ~VQAFRMF_PALCOMP;\n\tcurframe->PalOffset = 0;\n\tcurframe->PaletteSize = iffsize;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CPLZ - Load compressed palette.\n*\n* SYNOPSIS\n*     Error = Load_CPLZ(VQA, Iffsize)\n*\n*     long Load_CPLZ(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CPLZ(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAFrameNode  *curframe;\n\tvoid          *buffer;\n\tunsigned long padsize;\n\tunsigned long lcwoffset;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tcurframe = vqap->VQABuf->Loader.CurFrame;\n\tpadsize = PADSIZE(iffsize);\n\n \t/* Read the palette into the end of the palette buffer. */\n\tlcwoffset = vqap->VQABuf->Max_Pal_Size - padsize;\n\tbuffer = curframe->Palette + lcwoffset;\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Flag this palette as compressed. */\n\tcurframe->Flags |= VQAFRMF_PALCOMP;\n\tcurframe->PalOffset = lcwoffset;\n\tcurframe->PaletteSize = iffsize;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_VPT0 - Load uncompressed pointers.\n*\n* SYNOPSIS\n*     Error = Load_VPT0(VQA, Iffsize)\n*\n*     long Load_VPT0(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_VPT0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAFrameNode *curframe;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tcurframe = vqap->VQABuf->Loader.CurFrame;\n\n\t/* Read the pointers into start of the pointer buffer. */\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, curframe->Pointers,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Flag this frame as uncompressed */\n\tcurframe->Flags &= ~VQAFRMF_PTRCOMP;\n\tcurframe->PtrOffset = 0;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_VPTZ - Load compressed pointers.\n*\n* SYNOPSIS\n*     Error = Load_VPTZ(VQA, Iffsize)\n*\n*     long Load_VPTZ(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_VPTZ(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAFrameNode  *curframe;\n\tvoid          *buffer;\n\tunsigned long padsize;\n\tunsigned long lcwoffset;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tcurframe = vqap->VQABuf->Loader.CurFrame;\n\tpadsize = PADSIZE(iffsize);\n\tlcwoffset = vqap->VQABuf->Max_Ptr_Size - padsize;\n\n\t/* Read the pointers into end of the pointer buffer. */\n\tbuffer = curframe->Pointers + lcwoffset;\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Flag this frame as compressed. */\n\tcurframe->Flags |= VQAFRMF_PTRCOMP;\n\tcurframe->PtrOffset = lcwoffset;\n\n\treturn (0);\n}\n\n\n#if(VQAAUDIO_ON)\n/****************************************************************************\n*\n* NAME\n*     Load_SND0 - Load uncompressed sound chunk.\n*\n* SYNOPSIS\n*     Error = Load_SND0(VQA, Iffsize)\n*\n*     long Load_SND0(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*     This routine normally loads the chunk into the TempBuf, unless the\n*     chunk is larger than the temp buffer size, in which case it puts it\n*     directly into the audio buffer itself.  This assumes that the only\n*     such chunk will be the first audio chunk!\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_SND0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tunsigned long padsize;\n\tlong          i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\taudio = &vqabuf->Audio;\n\tconfig = &vqap->Config;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* If sound is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, just skip the chunk.\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0)\n\t\t\t|| (vqap->vocfh != -1) || (audio->Buffer == NULL)) {\n\t#else  /* VQAVOC_ON */\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0)\n\t\t\t|| (audio->Buffer == NULL)) {\n\t#endif /* VQAVOC_ON */\n\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\tpadsize)) {\n\t\t\treturn (VQAERR_SEEK);\n\t\t} else {\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\t/* Read large startup chunk directly into AudioBuf */\n\tif ((padsize > audio->TempBufSize) && (audio->AudBufPos == 0)) {\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, audio->Buffer,\n\t\t\t\tpadsize)) {\n\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\n\t\taudio->AudBufPos += iffsize;\n\n\t\t/* Flag the audio frame flags as loaded for the initial audio frame. */\n\t\tfor (i = 0; i < (iffsize / config->HMIBufSize); i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t} else {\n\n\t\t/*  Read data into TempBuf */\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, audio->TempBuf,\n\t\t\t\tpadsize)) {\n\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\t}\n\n\t/* Set the TempBufLen */\n\taudio->TempBufLen = iffsize;\n\t\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_SND1 - Load compressed sound chunk.\n*\n* SYNOPSIS\n*     Error = Load_SND1(VQA, Iffsize)\n*\n*     long Load_SND1(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*     This routine normally loads the chunk into the TempBuf, unless the\n*     chunk is larger than the temp buffer size, in which case it puts it\n*     directly into the audio buffer itself.  This assumes that the only\n*     such chunk will be the first audio chunk!\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_SND1(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tunsigned char *loadbuf;\n\tunsigned long padsize;\n\tZAPHeader     zap;\n\tlong          i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\taudio = &vqabuf->Audio;\n\tconfig = &vqap->Config;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* If sound is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, just skip the chunk\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (vqap->vocfh != -1)\n\t\t\t|| (audio->Buffer == NULL)) {\n\t#else\n\tif (((config->OptionFlags & VQAOPTF_AUDIO)==0) || (audio->Buffer==NULL)) {\n\t#endif /* VQAVOC_ON */\n\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\tpadsize)) {\n\t\t\treturn (VQAERR_SEEK);\n\t\t} else {\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\t/* Read the ZAP audio frame header. */\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, &zap,\n\t\t\tsizeof(ZAPHeader))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Adjust chunk size */\n\tpadsize -= sizeof(ZAPHeader);\n\n\t/* Read large startup chunk directly into AudioBuf */\n\tif ((zap.UnCompSize > audio->TempBufSize) && (audio->AudBufPos == 0)) {\n\n\t\t/* Load RAW uncompressed data. */\n\t\tif (zap.UnCompSize == zap.CompSize) {\n\t\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, audio->Buffer,\n\t\t\t\t\tpadsize)) {\n\n\t\t\t\treturn (VQAERR_READ);\n\t\t\t}\n\t\t} else {\n\n\t\t\t/* Load compressed data into the end of the buffer. */\n\t\t\tloadbuf = (audio->Buffer + config->AudioBufSize) - padsize;\n\n\t\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, loadbuf,\n\t\t\t\t\tpadsize)) {\n\n\t\t\t\treturn (VQAERR_READ);\n\t\t\t}\n\n\t\t\t/* Uncompress the audio frame. */\n\t\t\tAudioUnzap(loadbuf, audio->Buffer, zap.UnCompSize);\n\t\t}\n\n\t\t/* Set buffer positions & flags */\n\t\taudio->AudBufPos += zap.UnCompSize;\n\n\t\tfor (i = 0; i < (zap.UnCompSize / config->HMIBufSize); i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t}\n\n\t/* Load an audio frame. */\n\tif (zap.UnCompSize == zap.CompSize) {\n\n\t\t/* If the frame is uncompressed the load it in directly. */\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, audio->TempBuf,\n\t\t\t\tpadsize)) {\n\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\t} else {\n\n\t\t/* Load the audio frame into the end of the buffer. */\n\t\tloadbuf = ((audio->TempBuf + audio->TempBufSize) - padsize);\n\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, loadbuf, padsize)) {\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\n\t\t/* Uncompress the audio frame. */\n\t\tAudioUnzap(loadbuf, audio->TempBuf, zap.UnCompSize);\n\t}\n\n\t/* Set the TempBufLen */\n\taudio->TempBufLen = zap.UnCompSize;\n\t\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_SND2 - Load ADPCM compressed sound chunk.\n*\n* SYNOPSIS\n*     Error = Load_SND2(VQA, Iffsize)\n*\n*     long Load_SND2(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*     This routine normally loads the chunk into the TempBuf, unless the\n*     chunk is larger than the temp buffer size, in which case it puts it\n*     directly into the audio buffer itself.  This assumes that the only\n*     such chunk will be the first audio chunk!\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_SND2(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tunsigned char *loadbuf;\n\tunsigned long padsize;\n\tunsigned long uncomp_size;\n\tlong          i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\taudio = &vqabuf->Audio;\n\tconfig = &vqap->Config;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* If sound is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, just skip the chunk\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (vqap->vocfh != -1)\n\t\t\t|| (audio->Buffer == NULL)) {\n\t#else  /* VQAVOC_ON */\n\tif (((config->OptionFlags & VQAOPTF_AUDIO)==0) || (audio->Buffer==NULL)) {\n\t#endif /* VQAVOC_ON */\n\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\tpadsize)) {\n\t\t\treturn (VQAERR_SEEK);\n\t\t} else {\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\tuncomp_size = iffsize * (audio->BitsPerSample / 4);\n\n\t/* Read large startup chunk directly into AudioBuf */\n\tif ((uncomp_size > audio->TempBufSize) && (audio->AudBufPos == 0)) {\n\n\t\t/* Load compressed data into the end of the buffer. */\n\t\tloadbuf = (audio->Buffer + config->AudioBufSize) - padsize;\n\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, loadbuf, padsize)) {\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\n\t\t/* Uncompress the audio frame. */\n\t\taudio->ADPCM_Info.lpSource = (char *)loadbuf;\n\t\taudio->ADPCM_Info.lpDest = (char *)audio->Buffer;\n\t\tsosCODECDecompressData(&audio->ADPCM_Info, uncomp_size);\n\n\t\t/* Set buffer positions & flags */\n\t\taudio->AudBufPos += uncomp_size;\n\n\t\tfor (i = 0; i < (uncomp_size / config->HMIBufSize); i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t}\n\n\t/* Load an audio frame. */\n\tloadbuf = ((audio->TempBuf + audio->TempBufSize) - padsize);\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, loadbuf, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Uncompress the audio frame. */\n\taudio->ADPCM_Info.lpSource = (char *)loadbuf;\n\taudio->ADPCM_Info.lpDest = (char *)audio->TempBuf;\n\tsosCODECDecompressData(&audio->ADPCM_Info, uncomp_size);\n\n\t/* Set the TempBufLen */\n\taudio->TempBufLen = uncomp_size;\n\t\n\treturn (0);\n}\n\n\n#if(VQAVOC_ON)\n/****************************************************************************\n*\n* NAME\n*     Load_AudFrame - Loads blocks from seperate VOC file.\n*\n* SYNOPSIS\n*     Load_AudFrame(VQA)\n*\n*     void Load_AudFrame(VQAHandleP *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to private VQA handle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Load_AudFrame(VQAHandleP *vqap)\n{\n\tVQAData     *vqabuf;\n\tVQALoader   *loader;\n\tVQAAudio    *audio;\n\tVQAConfig   *config;\n\tstatic long lastplayblock = -1;\n\tstatic long myblock = 0;\n\tstatic long firsttime = 1;\n\tlong        numblocks;\n\tlong        i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\taudio = &vqabuf->Audio;\n\tconfig = &vqap->Config;\n\n\t/* Do nothing if no buffer */\n\tif (audio->Buffer == NULL) {\n\t\treturn;\n\t}\n\n\t/* If this is the first time we're called, pre-load the 1st 'n' audio\n\t * blocks, where 'n' is half the total audio buffer size; this way, we'll\n\t * always stay ahead of HMI.\n\t */\n\tif (firsttime) {\n\t\tnumblocks = (audio->NumAudBlocks / 2);\n\t\tread(vqap->vocfh, audio->Buffer, config->HMIBufSize * numblocks);\n\t\taudio->AudBufPos += config->HMIBufSize * numblocks;\n\n\t\tif (audio->AudBufPos >= config->AudioBufSize) {\n\t\t\taudio->AudBufPos = 0;\n\t\t}\n\n\t\tfor (i = 0; i < numblocks; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\tmyblock += numblocks;\n\t\t\n\t\tif (myblock >= audio->NumAudBlocks) {\n\t\t\tmyblock = 0;\n\t\t}\n\n\t\tfirsttime = 0;\n\t}\n\n\t/* If HMI's block has changed, load the next block & mark it as loaded */\n\tif (audio->PlayPosition / config->HMIBufSize != lastplayblock) {\n\n\t\t/* update HMI's last known block position */\n\t\tlastplayblock = audio->PlayPosition / config->HMIBufSize;\n\n\t\t/* read the VOC data */\n\t\tread(vqap->vocfh, (audio->Buffer + myblock * config->HMIBufSize),\n\t\t\t\tconfig->HMIBufSize);\n\n\t\taudio->AudBufPos += config->HMIBufSize;\n\n\t\tif (audio->AudBufPos >= config->AudioBufSize) {\n\t\t\taudio->AudBufPos = 0;\n\t\t}\n\n\t\t/* set the IsLoaded flags */\n\t\taudio->IsLoaded[myblock] = 1;\n\n\t\t/* increment my block counter */\n\t\tmyblock++;\n\n\t\tif (myblock >= audio->NumAudBlocks) {\n\t\t\tmyblock = 0;\n\t\t}\n\t}\n}\n#endif /* VQAVOC_ON */\n#endif /* VQAAUDIO_ON */\n\n"
  },
  {
    "path": "VQ/VQA32/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQAPlay 32-bit library.\n#\n# FILE\n#     makefile (Watcom C/C++ 10.0a)\n#\n# DESCRIPTION\n#     Makefile for generating the 32-bit VQAPlay library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n# \n# DATE\n#     February 10, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     WATCOM - Watcom C installation path.\n#\n#****************************************************************************\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n!ifndef %PRJ || %PRJVCS || %WATCOM\n!error Environment not configured.\n!endif\n\n.OPTIMIZE\n.ERASE\n\n#----------------------------------------------------------------------------\n# PROJECTS DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJNAME = vqa32wp\nPRJDIR  = $(%PRJ)\\VQA32\n\nOBJECTS = &\n\tconfig.obj &\n\ttask.obj &\n\tloader.obj &\n\tdrawer.obj &\n\taudio.obj &\n\tmonodisp.obj &\n\tdstream.obj &\n\tunvqbuff.obj &\n\tunvqvesa.obj &\n\tvertag.obj &\n\tcaption.obj &\n#\tunvqxmde.obj\n\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!ifdef %LIB\nLIBPATH = $(%PRJ)\\LIB;$(%LIB)\n!else\nLIBPATH = $(%PRJ)\\LIB;$(%WATCOM)\\LIB386\n!endif\n\n!ifdef %INCLUDE\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%INCLUDE)\n!else\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%WATCOM)\\H\n!endif\n\npath_c   = .\\\npath_cpp = .\\\npath_h   = .\\\npath_asm = .\\\npath_i   = .\\\npath_obj = .\\O\npath_lib = $(%PRJ)\\LIB\npath_exe = .\\\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULE EXTENSIONS AND PATHS\n#----------------------------------------------------------------------------\n\n.EXTENSIONS :\n.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i\n\n.c : $(path_c)\n.cpp : $(path_cpp)\n.h : $(path_h)\n.asm : $(path_asm)\n.i : $(path_i)\n.obj : $(path_obj)\n.lib : $(path_lib)\n.exe : $(path_exe)\n\n#----------------------------------------------------------------------------\n# Tools/commands & configurations\n#----------------------------------------------------------------------------\n\nCC_CMD   = wcc386\nCCP_CMD  = wpp386\nASM_CMD  = tasm32\nLINK_CMD = wlink\nLIB_CMD  = wlib\n\nCC_OPTS  = -i$(INCLUDEPATH) -j -zp1 -5s -mf -oaeilrt -s -zq\nASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /i$(%PRJ)\\INCLUDE\\VQM32 /dPHARLAP_TNT=0\nLIB_OPTS = /b /c /q\nLINK_CFG = $(PRJNAME).lnk\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall : $(PRJNAME).lib .SYMBOLIC\n\n$(PRJNAME).lib : $(OBJECTS) .SYMBOLIC\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj :\n  $(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.cpp.obj :\n  $(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\\$^.\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\nupdate: .SYMBOLIC\n\t@echo Updating VQAPlay32 header files!\n\t@copy vqaplay.h ..\\include\\vqa32 >NUL\n\t@copy vqafile.h ..\\include\\vqa32 >NUL\n\n"
  },
  {
    "path": "VQ/VQA32/MAKEFILE.BAK",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQAPlay 32-bit library.\n#\n# FILE\n#     makefile (Watcom C/C++ 10.0a)\n#\n# DESCRIPTION\n#     Makefile for generating the 32-bit VQAPlay library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n# \n# DATE\n#     February 10, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     WATCOM - Watcom C installation path.\n#\n#****************************************************************************\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n!ifndef %PRJ\nPRJ=..\n!endif\n\n!ifndef %WATCOM\n!error Environment not configured.\n!endif\n\n.OPTIMIZE\n.ERASE\n\n#----------------------------------------------------------------------------\n# PROJECTS DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJNAME = vqa32wp\nPRJDIR  = $(PRJ)\\VQA32\n\nOBJECTS = &\n\tconfig.obj &\n\ttask.obj &\n\tloader.obj &\n\tdrawer.obj &\n\taudio.obj &\n\tmonodisp.obj &\n\tdstream.obj &\n\tunvqbuff.obj &\n\tunvqvesa.obj &\n\tvertag.obj &\n\tcaption.obj &\n#\tunvqxmde.obj\n\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!ifdef %LIB\nLIBPATH = $(PRJ)\\LIB;$(%LIB)\n!else\nLIBPATH = $(PRJ)\\LIB;$(%WATCOM)\\LIB386\n!endif\n\n!ifdef %INCLUDE\nINCLUDEPATH = $(PRJ)\\INCLUDE;$(%INCLUDE)\n!else\nINCLUDEPATH = $(PRJ)\\INCLUDE;$(%WATCOM)\\H\n!endif\n\npath_c   = .\\\npath_cpp = .\\\npath_h   = .\\\npath_asm = .\\\npath_i   = .\\\npath_obj = .\\O\npath_lib = $(PRJ)\\LIB\npath_exe = .\\\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULE EXTENSIONS AND PATHS\n#----------------------------------------------------------------------------\n\n.EXTENSIONS :\n.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i\n\n.c : $(path_c)\n.cpp : $(path_cpp)\n.h : $(path_h)\n.asm : $(path_asm)\n.i : $(path_i)\n.obj : $(path_obj)\n.lib : $(path_lib)\n.exe : $(path_exe)\n\n#----------------------------------------------------------------------------\n# Tools/commands & configurations\n#----------------------------------------------------------------------------\n\nCC_CMD   = wcc386\nCCP_CMD  = wpp386\nASM_CMD  = tasm32\nLINK_CMD = wlink\nLIB_CMD  = wlib\n\nCC_OPTS  = -i$(INCLUDEPATH) -j -zp1 -5s -mf -oaeilrt -s -zq\nASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /i$(PRJ)\\INCLUDE\\VQM32 /dPHARLAP_TNT=0\nLIB_OPTS = /b /c /q\nLINK_CFG = $(PRJNAME).lnk\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall : $(PRJNAME).lib .SYMBOLIC\n\n$(PRJNAME).lib : $(OBJECTS) .SYMBOLIC\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj :\n  $(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.cpp.obj :\n  $(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\\$^.\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\nupdate: .SYMBOLIC\n\t@echo Updating VQAPlay32 header files!\n\t@copy vqaplay.h ..\\include\\vqa32 >NUL\n\t@copy vqafile.h ..\\include\\vqa32 >NUL\n\n"
  },
  {
    "path": "VQ/VQA32/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQAPlay32 library.\n#\n# FILE\n#     makefile (Borland/TNT)\n#\n# DESCRIPTION\n#     Makefile for generating the 32-bit VQAPlay library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n#\n# DATE\n#     Feburary 7, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     BCDIR  - Borland C installation path.\n#     TNTDIR - Pharlap/TNT installation path.\n#\n#****************************************************************************\n\n.AUTODEPEND\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n!if !$d(PRJ) || !$d(PRJVCS) || !$d(BCDIR) || !$d(TNTDIR) \n!error Environment not configured.\n!endif\n\n#----------------------------------------------------------------------------\n# PROJECTS DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJNAME\t= vqa32bp\nPRJDIR = $(PRJ)\\VQA32\n\nOBJECTS = \\\n\tconfig.obj \\\n\ttask.obj \\\n\tloader.obj \\\n\tdrawer.obj \\\n\taudio.obj \\\n\tmonodisp.obj \\\n\tdstream.obj \\\n\tunvqbuff.obj \\\n\tunvqvesa.obj \\\n\tvertag.obj \\\n\tcaption.obj \\\n#\tunvqxmde.obj \\\n\nPRJLIBS = \\\n\tvqm32bp.lib \\\n\t\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!if $d(LIB)\nLIBPATH = $(PRJ)\\LIB;$(LIB)\n!else\nLIBPATH = $(PRJ)\\LIB;$(TNTDIR)\\LIB;$(BCDIR)\\LIB\n!endif\n\n!if $d(INCLUDE)\nINCLUDEPATH\t= $(PRJ)\\INCLUDE;$(INCLUDE)\n!else\nINCLUDEPATH\t= $(PRJ)\\INCLUDE;$(TNTDIR)\\INCLUDE;$(BCDIR)\\INCLUDE\n!endif\n\n.path.asm = $(PRJDIR)\n.path.c   = $(PRJDIR)\n.path.cpp = $(PRJDIR)\n.path.h   = $(PRJDIR)\n.path.exe = $(PRJDIR)\n.path.obj = $(PRJDIR)\\OBJ\n.path.sym = $(PRJDIR)\\OBJ\n.path.lib = $(PRJ)\\LIB\n\n#----------------------------------------------------------------------------\n# TOOLS, COMMAND AND CONFIGURATIONS\n#----------------------------------------------------------------------------\n\nCC_CMD   = bcc32\nASM_CMD  = tasm32\nLINK_CMD = tlink32\nLIB_CMD  = tlib\n\nCC_CFG    = bcc32.cfg\nASM_CFG   = tasm32.cfg\nLINK_CFG  = tlink32.cfg\nLIB_CFG   = tlib.cfg\nCFG_FILES = $(CC_CFG) $(ASM_CFG) $(LINK_CFG) $(LIB_CFG)\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall: $(PRJNAME).lib\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj:\n\t$(CC_CMD) -P- -n$(.path.obj) {$< }\n\n.cpp.obj:\n\t$(CC_CMD) -P -n$(.path.obj) {$< }\n\n.asm.obj:\n\t$(ASM_CMD) @$(ASM_CFG) $<,$(.path.obj)\\$&\n\n#----------------------------------------------------------------------------\n# BUILD LIBRARY\n#----------------------------------------------------------------------------\n\n$(PRJNAME).lib: $(OBJECTS)\n\t- @del $(.path.lib)\\$(PRJNAME).lib >&NUL\n\t$(LIB_CMD) $(.path.lib)\\$(PRJNAME).lib @$(LIB_CFG) @&&|\n-+$(**: = -+)\n|\n\t- @copy vqaplay.h $(PRJ)\\INCLUDE\\VQA32 >&NUL\n\t- @copy vqafile.h $(PRJ)\\INCLUDE\\VQA32 >&NUL\n\n#----------------------------------------------------------------------------\n# ALL OBJECTS DEPEND ON THE CONFIGURATION FILES\n#----------------------------------------------------------------------------\n\n$(OBJECTS):\t$(CFG_FILES)\n\n#----------------------------------------------------------------------------\n# COMPILER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(CC_CFG): makefile\n\tcopy &&|\n-c\n-3\n-d\n-H=$(.path.sym)\\headers.sym\n-wpro\n-weas\n-wpre\n-I$(INCLUDEPATH)\n-DPHARLAP_TNT=1\n#-v\n| $(CC_CFG)\n \n#----------------------------------------------------------------------------\n# ASSEMBLER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(ASM_CFG): makefile\n\tcopy &&|\n/t\n/m\n/w+\n/jJUMPS\n/ml\n/p\n/z\n/i$(PRJ)\\INCLUDE\\VQM32\n/zi\n/dPHARLAP_TNT=1\n| $(ASM_CFG)\n\n#----------------------------------------------------------------------------\n# LINKER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(LINK_CFG): makefile\n\tcopy &&|\n/c\n/m\n/Gm\n-L$(LIBPATH)\n-v\n| $(LINK_CFG)\n\n#----------------------------------------------------------------------------\n# LIBRARIAN CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(LIB_CFG):\tmakefile\n\tcopy &&|\n/C /E\n| $(LIB_CFG)\n\n"
  },
  {
    "path": "VQ/VQA32/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQAPlay 32-bit library.\n#\n# FILE\n#     makefile (Watcom C/C++ 10.0a)\n#\n# DESCRIPTION\n#     Makefile for generating the 32-bit VQAPlay library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n# \n# DATE\n#     February 10, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     WATCOM - Watcom C installation path.\n#\n#****************************************************************************\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n!ifndef %PRJ || %PRJVCS || %WATCOM\n!error Environment not configured.\n!endif\n\n.OPTIMIZE\n.ERASE\n\n#----------------------------------------------------------------------------\n# PROJECTS DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJNAME = vqa32wp\nPRJDIR  = $(%PRJ)\\VQA32\n\nOBJECTS = &\n\tconfig.obj &\n\ttask.obj &\n\tloader.obj &\n\tdrawer.obj &\n\taudio.obj &\n\tmonodisp.obj &\n\tdstream.obj &\n\tunvqbuff.obj &\n\tunvqvesa.obj &\n\tvertag.obj &\n\tcaption.obj &\n#\tunvqxmde.obj\n\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!ifdef %LIB\nLIBPATH = $(%PRJ)\\LIB;$(%LIB)\n!else\nLIBPATH = $(%PRJ)\\LIB;$(%WATCOM)\\LIB386\n!endif\n\n!ifdef %INCLUDE\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%INCLUDE)\n!else\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%WATCOM)\\H\n!endif\n\npath_c   = .\\\npath_cpp = .\\\npath_h   = .\\\npath_asm = .\\\npath_i   = .\\\npath_obj = .\\O\npath_lib = $(%PRJ)\\LIB\npath_exe = .\\\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULE EXTENSIONS AND PATHS\n#----------------------------------------------------------------------------\n\n.EXTENSIONS :\n.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i\n\n.c : $(path_c)\n.cpp : $(path_cpp)\n.h : $(path_h)\n.asm : $(path_asm)\n.i : $(path_i)\n.obj : $(path_obj)\n.lib : $(path_lib)\n.exe : $(path_exe)\n\n#----------------------------------------------------------------------------\n# Tools/commands & configurations\n#----------------------------------------------------------------------------\n\nCC_CMD   = wcc386\nCCP_CMD  = wpp386\nASM_CMD  = tasm32\nLINK_CMD = wlink\nLIB_CMD  = wlib\n\nCC_OPTS  = -i$(INCLUDEPATH) -j -zp1 -5s -mf -oaeilrt -s -zq\nASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /i$(%PRJ)\\INCLUDE\\VQM32 /dPHARLAP_TNT=0\nLIB_OPTS = /b /c /q\nLINK_CFG = $(PRJNAME).lnk\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall : $(PRJNAME).lib .SYMBOLIC\n\n$(PRJNAME).lib : $(OBJECTS) .SYMBOLIC\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj :\n  $(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.cpp.obj :\n  $(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\\$^.\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\nupdate: .SYMBOLIC\n\t@echo Updating VQAPlay32 header files!\n\t@copy vqaplay.h ..\\include\\vqa32 >NUL\n\t@copy vqafile.h ..\\include\\vqa32 >NUL\n\n"
  },
  {
    "path": "VQ/VQA32/MONODISP.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*---------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     monodisp.c\n*\n* DESCRIPTION\n*     Monochrome display (debug)\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Feburary 23, 1995\n*\n*---------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_InitMono   - Initialize the player's mono screen.\n*     VQA_UpdateMono - Update the player's mono output.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <string.h>\n#include \"vq.h\"\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n\n#if(VQAMONO_ON)\n\n/* Main window */\n#define\tMAIN_WX1   0\n#define\tMAIN_WX2   79\n#define\tMAIN_WY1   0\n#define\tMAIN_WY2   9\n#define\tMAIN_TITLE \"VQA Player\"\n\n/* Loader data window */\n#define\tLOADER_WX1   0\n#define\tLOADER_WX2   39\n#define\tLOADER_WY1   10\n#define\tLOADER_WY2   20\n#define\tLOADER_TITLE \" Frame Loader \"\n\n/* Drawer data window */\n#define\tDRAWER_WX1   40\n#define\tDRAWER_WX2   79\n#define\tDRAWER_WY1   10\n#define\tDRAWER_WY2   20\n#define\tDRAWER_TITLE \" Frame Drawer \"\n\n/* Audio data window */\n#define\tAUDIO_WX1   0\n#define\tAUDIO_WX2   39\n#define\tAUDIO_WY1   21\n#define\tAUDIO_WY2   24\n#define\tAUDIO_TITLE \" Audio Callback \"\n\n/* Flipper data window */\n#define\tFLIPPER_WX1   40\n#define\tFLIPPER_WX2   79\n#define\tFLIPPER_WY1   21\n#define\tFLIPPER_WY2   24\n#define\tFLIPPER_TITLE \" Frame Flipper \"\n\nextern char *HMIDevName;\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_InitMono - Initialize the player's mono screen.\n*\n* SYNOPSIS\n*     VQA_InitMono(VQAData)\n*\n*     void VQA_InitMono(VQAData *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQAData - Pointer to VQAData structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\n#pragma argsused\nvoid VQA_InitMono(VQAHandleP *vqap)\n{\n\tVQAData   *vqabuf;\n\tVQAConfig *config;\n\tchar      txt[80];\n\n\t/* Dereference commonly used data members of quick access. */\n\tvqabuf = vqap->VQABuf;\n\tconfig = &vqap->Config;\n\n\t/* Enable and clear the mono screen */\n\tMono_Enable();\n\tMono_Clear_Screen();\n\n\t/* Init main window */\n\tMono_Draw_Rect(MAIN_WX1, MAIN_WY1, (MAIN_WX2 - MAIN_WX1 + 1),\n\t\t\t(MAIN_WY2 - MAIN_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((MAIN_WX2 + MAIN_WX1 - strlen(MAIN_TITLE)) / 2, MAIN_WY1);\n\tMono_Print(MAIN_TITLE);\n\n\t/* Video mode */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 1);\n\tMono_Print(\"Video Mode: \");\n\n\tswitch (config->Vmode) {\n\n\t\t#if(VQAMONO_ON)\n\t\tcase MCGA:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tMono_Print(\"MCGA Buffered\");\n\t\t\t} else {\n\t\t\t\tMono_Print(\"MCGA Direct to screen\");\n\t\t\t}\n\t\t\tbreak;\n\t\t#endif\n\n\t\t#if(VQAXMODE_ON)\n\t\tcase XMODE_320X200:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tMono_Print(\"XMODE 320x200 Buffered\");\n\t\t\t} else {\n\t\t\t\tif (config->DrawFlags & VQACFGF_VRAMCB) {\n\t\t\t\t\tMono_Print(\"XMODE 320x200 VRAM Copy\");\n\t\t\t\t} else {\n\t\t\t\t\tMono_Print(\"XMODE 320x200 Linear->Banked\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase XMODE_320X240:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tMono_Print(\"XMODE 320x240 Buffered\");\n\t\t\t} else {\n\t\t\t\tif (config->DrawFlags & VQACFGF_VRAMCB) {\n\t\t\t\t\tMono_Print(\"XMODE 320x240 VRAM Copy\");\n\t\t\t\t} else {\n\t\t\t\t\tMono_Print(\"XMODE 320x240 Linear->Banked\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t#endif\n\n\t\t#if(VQAVESA_ON)\n\t\tcase VESA_640X480_256:\n\t\t\tMono_Print(\"VESA 640x480\");\n\t\t\tbreak;\n\n\t\tcase VESA_320X200_32K_1:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tMono_Print(\"VESA 320x200 Buffered\");\n\t\t\t} else {\n\t\t\t\tMono_Print(\"VESA 320x200 Direct to screen\");\n\t\t\t}\n\t\t\tbreak;\n\t\t#endif\n\n\t\tdefault:\n\t\t\tMono_Print(\"UNKNOWN\");\n\t\t\tbreak;\n\t}\n\n\t/* Sound status */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 2);\n\tMono_Print(\"               Sound: \");\n\n\tif (config->OptionFlags & VQAOPTF_AUDIO) {\n\t\tsprintf(txt,\"%u Hz\", config->AudioRate);\n\t\tMono_Print(txt);\n\t}\telse {\n\t\tMono_Print(\"OFF\");\n\t}\n\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 3);\n\tMono_Print(\"         Driver Name: \");\n\tMono_Print(HMIDevName);\n\n\t/* Frame rates */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 4);\n\tsprintf(txt,\"     Load Frame Rate: %d\", config->FrameRate);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 5);\n\tsprintf(txt,\"     Draw Frame Rate: %d\", config->DrawRate);\n\tMono_Print(txt);\n\n\t/* Slow palette */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 6);\n\tMono_Print(\"        Slow palette: \");\n\n\tif (config->OptionFlags & VQAOPTF_SLOWPAL) {\n\t\tMono_Print(\"ON\");\n\t} else {\n\t\tMono_Print(\"OFF\");\n\t}\n\n\t/* Memory Usage */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 7);\n\tsprintf(txt,\"         Memory Used: %ld\", vqabuf->MemUsed);\n\tMono_Print(txt);\n\n\t/* Timer Method */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 8);\n\n\tif (VQA_TimerMethod() == VQA_TMETHOD_DOS) {\n\t\tMono_Print(\"           DOS Timer:\");\n\t} else if (VQA_TimerMethod() == VQA_TMETHOD_INT) {\n\t\tMono_Print(\"     Interrupt Timer:\");\n\t} else if (VQA_TimerMethod() == VQA_TMETHOD_AUDIO) {\n\t\tMono_Print(\"     Audio DMA Timer:\");\n\t} else {\n\t\tMono_Print(\"             Defualt:\");\n\t}\n\n\t/* Init loader data window */\n\tMono_Draw_Rect(LOADER_WX1, LOADER_WY1, (LOADER_WX2 - LOADER_WX1 + 1),\n\t\t\t(LOADER_WY2 - LOADER_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((LOADER_WX2 + LOADER_WX1 - strlen(LOADER_TITLE)) / 2,\n\t\t\tLOADER_WY1);\n\n\tMono_Print(LOADER_TITLE);\n\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 1);\n\tMono_Print(\"  Current Frame #:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 2);\n\tMono_Print(\"# Waits on Drawer:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 3);\n\tMono_Print(\" # Waits on Audio:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 4);\n\tMono_Print(\"       Frame Size:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 5);\n\tMono_Print(\"   Max Frame Size:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY2 - 2);\n\tMono_Print(\"Audio:\");\n\n\t/* Init drawer data window */\n\tMono_Draw_Rect(DRAWER_WX1, DRAWER_WY1, (DRAWER_WX2 - DRAWER_WX1 + 1),\n\t\t\t(DRAWER_WY2 - DRAWER_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((DRAWER_WX2 + DRAWER_WX1 - strlen(DRAWER_TITLE)) / 2,\n\t\t\tDRAWER_WY1);\n\n\tMono_Print(DRAWER_TITLE);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 1);\n\tMono_Print(\"   Current Frame #:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 2);\n\tMono_Print(\"   Desired Frame #:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 3);\n\tMono_Print(\"# Waits on Flipper:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 4);\n\tMono_Print(\" # Waits on Loader:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 5);\n\tMono_Print(\"  # Frames Skipped:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 6);\n\tMono_Print(\"     VQ Block Size:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY2 - 2);\n\tMono_Print(\"Frames:                 Cbooks:\");\n\n\t/* Init audio data window */\n\tMono_Draw_Rect(AUDIO_WX1, AUDIO_WY1, (AUDIO_WX2 - AUDIO_WX1 + 1),\n\t\t\t(AUDIO_WY2 - AUDIO_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((AUDIO_WX2 + AUDIO_WX1 - strlen(AUDIO_TITLE)) / 2,\n\t\t\tAUDIO_WY1);\n\n\tMono_Print(AUDIO_TITLE);\n\n\tMono_Set_Cursor(AUDIO_WX1 + 2, AUDIO_WY1 + 1);\n\tMono_Print(\"# Repeated Buffers:\");\n\n\t/* Init flipper data window */\n\tMono_Draw_Rect(FLIPPER_WX1, FLIPPER_WY1, (FLIPPER_WX2 - FLIPPER_WX1 + 1),\n\t\t\t(FLIPPER_WY2 - FLIPPER_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((FLIPPER_WX2 + FLIPPER_WX1 - strlen(FLIPPER_TITLE)) / 2,\n\t\t\tFLIPPER_WY1);\n\n\tMono_Print(FLIPPER_TITLE);\n\n\tMono_Set_Cursor(FLIPPER_WX1 + 2, FLIPPER_WY1 + 1);\n\tMono_Print(\"Current Frame #:\");\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_UpdateMono - Update the player's mono output.\n*\n* SYNOPSIS\n*     VQA_UpdateMono(VQAData)\n*\n*     void VQA_UpdateMono(VQAData *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQAData - Pointer to VQAData structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\n#pragma argsused\nvoid VQA_UpdateMono(VQAHandleP *vqap)\n{\n\tVQAData       *vqabuf;\n\tVQAConfig     *config;\n\tVQAFrameNode  *frame;\n\tVQACBNode     *cbook;\n\tlong          frameindex = -1;\n\tlong          loadcb = -1;\n\tlong          drawcb = -1;\n\tlong          i;\n\tchar          txt[80];\n\tunsigned long curtime;\n\n\t/* Dereference commonly used data members for quick access. */\n\tvqabuf = vqap->VQABuf;\n\tconfig = &vqap->Config;\n\n\t/* Timer value */\n\tcurtime = VQA_GetTime();\n\tMono_Set_Cursor(MAIN_WX1 + 40, MAIN_WY1 + 8);\n\tsprintf(txt,\"%02ld:%02ld.%02ld\",curtime / (VQA_TIMETICKS * VQA_TIMETICKS),\n\t\t\tcurtime / VQA_TIMETICKS,((curtime * 100L) / VQA_TIMETICKS)\n\t\t\t-((curtime / VQA_TIMETICKS) * 100L));\n\n\tMono_Print(txt);\n\n\t/* Loader data */\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 1);\n\tsprintf(txt,\"%4d\",vqabuf->Loader.LastFrameNum);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 2);\n\tsprintf(txt,\"%4ld\",vqabuf->Loader.WaitsOnDrawer);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 3);\n\tsprintf(txt,\"%4ld\",vqabuf->Loader.WaitsOnAudio);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 4);\n\tsprintf(txt,\"%5u\",vqabuf->Loader.FrameSize);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 5);\n\tsprintf(txt,\"%5u\",vqabuf->Loader.MaxFrameSize);\n\tMono_Print(txt);\n\n\t/* Draw a picture of the audio buffers */\n\tfor (i = 0; i < vqabuf->Audio.NumAudBlocks; i++) {\n\t\tif (vqabuf->Audio.IsLoaded[i] == 0) {\n\t\t\ttxt[i] = '_';\n\t\t} else {\n\t\t\ttxt[i] = 'X';\n\t\t}\n\t}\n\n\ttxt[i] = 0;\n\tMono_Set_Cursor(LOADER_WX1 + 9,LOADER_WY2 - 2);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 9,LOADER_WY2-1); \n\tMono_Print(\"                        \");\n\n\tMono_Set_Cursor(LOADER_WX1 + 9 + vqabuf->Audio.PlayPosition\n\t\t\t/ config->HMIBufSize,LOADER_WY2 - 1);\n\n\tMono_Print(\"P\");\n\n\tMono_Set_Cursor(LOADER_WX1 + 9 + vqabuf->Loader.AudBufPos\n\t\t\t/ config->HMIBufSize,LOADER_WY2 - 1);\n\n\tMono_Print(\"L\");\n\n\t/* Drawer data */\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 1);\n\tsprintf(txt,\"%4d\", vqabuf->Drawer.LastFrameNum);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 2);\n\tsprintf(txt,\"%4d\", vqabuf->Drawer.DesiredFrame);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 3);\n\tsprintf(txt,\"%4ld\", vqabuf->Drawer.WaitsOnFlipper);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 4);\n\tsprintf(txt,\"%4ld\", vqabuf->Drawer.WaitsOnLoader);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 5);\n\tsprintf(txt,\"%4d\", vqabuf->Drawer.NumSkipped);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 6);\n\tsprintf(txt,\" %dx%d\", vqap->Header.BlockWidth, vqap->Header.BlockHeight);\n\tMono_Print(txt);\n\n\t/* Draw a picture of the frame buffers */\n\tframe = vqabuf->FrameData;\n\n\tfor (i = 0; i < config->NumFrameBufs; i++) {\n\t\tif (frame->Flags & VQAFRMF_LOADED) {\n\t\t\ttxt[i] = 'X';\n\t\t} else {\n\t\t\ttxt[i] = '_';\n\t\t}\n\n\t\tif (vqabuf->Flipper.CurFrame == frame) {\n\t\t\tframeindex = i;\n\t\t}\n\n\t\tframe = frame->Next;\n\t}\n\n\ttxt[i] = 0;\n\tMono_Set_Cursor(DRAWER_WX1 + 10,DRAWER_WY2 - 2);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 10,DRAWER_WY2 - 1);\n\tMono_Print(\"              \");\n\n\tMono_Set_Cursor(DRAWER_WX1 + 10 + frameindex,DRAWER_WY2 - 1);\n\tMono_Print(\"^\");\n\n\t/* Draw a picture of the codebook buffers */\n\tcbook = vqabuf->CBData;\n\n\tfor (i = 0; i < config->NumCBBufs; i++) {\n\t\tif (vqabuf->Loader.CurCB == cbook) {\n\t\t\tloadcb = i;\n\t\t}\n\n\t\tif (vqabuf->Flipper.CurFrame->Codebook == cbook) {\n\t\t\tdrawcb = i;\n\t\t}\n\n\t\tcbook = cbook->Next;\n\t}\n\n\tMono_Set_Cursor(DRAWER_WX1 + 34,DRAWER_WY2 - 2);\n\tMono_Print(\"___\");\n\n\tMono_Set_Cursor(DRAWER_WX1 + 34,DRAWER_WY2 - 1);\n\tMono_Print(\"   \");\n\n\tMono_Set_Cursor(DRAWER_WX1 + 34 + loadcb,DRAWER_WY2 - 1);\n\tMono_Print(\"L\");\n\n\tMono_Set_Cursor(DRAWER_WX1 + 34 + drawcb,DRAWER_WY2 - 1);\n\tMono_Print(\"D\");\n\n\t/* Audio data */\n\tMono_Set_Cursor(AUDIO_WX1 + 22, AUDIO_WY1 + 1);\n\tsprintf(txt,\"%4ld\", vqabuf->Audio.NumSkipped);\n\tMono_Print(txt);\n\n\t/* Flipper data */\n\tMono_Set_Cursor(FLIPPER_WX1 + 22,FLIPPER_WY1 + 1);\n\tsprintf(txt,\"%4d\", vqabuf->Flipper.LastFrameNum);\n\tMono_Print(txt);\n\tMono_Set_Cursor(0,0);\n}\n\n#endif /* VQAMONO_ON */\n\n"
  },
  {
    "path": "VQ/VQA32/MONODISP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     monodisp.c\n*\n* DESCRIPTION\n*     Monochrome display (debug)\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 6, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_InitMono   - Initialize the player's mono screen.\n*     VQA_UpdateMono - Update the player's mono output.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <string.h>\n#include \"vq.h\"\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n\n#if(VQAMONO_ON)\n\n/* Main window */\n#define\tMAIN_WX1   0\n#define\tMAIN_WX2   79\n#define\tMAIN_WY1   0\n#define\tMAIN_WY2   9\n#define\tMAIN_TITLE \"VQA Player\"\n\n/* Loader data window */\n#define\tLOADER_WX1   0\n#define\tLOADER_WX2   39\n#define\tLOADER_WY1   10\n#define\tLOADER_WY2   20\n#define\tLOADER_TITLE \" Frame Loader \"\n\n/* Drawer data window */\n#define\tDRAWER_WX1   40\n#define\tDRAWER_WX2   79\n#define\tDRAWER_WY1   10\n#define\tDRAWER_WY2   20\n#define\tDRAWER_TITLE \" Frame Drawer \"\n\n/* Audio data window */\n#define\tAUDIO_WX1   0\n#define\tAUDIO_WX2   39\n#define\tAUDIO_WY1   21\n#define\tAUDIO_WY2   24\n#define\tAUDIO_TITLE \" Audio Callback \"\n\n/* Flipper data window */\n#define\tFLIPPER_WX1   40\n#define\tFLIPPER_WX2   79\n#define\tFLIPPER_WY1   21\n#define\tFLIPPER_WY2   24\n#define\tFLIPPER_TITLE \" Frame Flipper \"\n\nextern char *HMIDevName;\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_InitMono - Initialize the player's mono screen.\n*\n* SYNOPSIS\n*     VQA_InitMono(VQA)\n*\n*     void VQA_InitMono(VQAHandleP *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to private VQA handle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\n#pragma argsused\nvoid VQA_InitMono(VQAHandleP *vqap)\n{\n\tVQAData   *vqabuf;\n\tVQAConfig *config;\n\tchar      txt[80];\n\n\t/* Dereference commonly used data members of quick access. */\n\tvqabuf = vqap->VQABuf;\n\tconfig = &vqap->Config;\n\n\t/* Enable and clear the mono screen */\n\tMono_Enable();\n\tMono_Clear_Screen();\n\n\t/* Init main window */\n\tMono_Draw_Rect(MAIN_WX1, MAIN_WY1, (MAIN_WX2 - MAIN_WX1 + 1),\n\t\t\t(MAIN_WY2 - MAIN_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((MAIN_WX2 + MAIN_WX1 - strlen(MAIN_TITLE)) / 2, MAIN_WY1);\n\tMono_Print(MAIN_TITLE);\n\n\t/* Video mode */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 1);\n\tMono_Print(\"Video Mode: \");\n\n\tswitch (config->Vmode) {\n\n\t\t#if(VQAMONO_ON)\n\t\tcase MCGA:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tMono_Print(\"MCGA Buffered\");\n\t\t\t} else {\n\t\t\t\tMono_Print(\"MCGA Direct to screen\");\n\t\t\t}\n\t\t\tbreak;\n\t\t#endif\n\n\t\t#if(VQAXMODE_ON)\n\t\tcase XMODE_320X200:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tMono_Print(\"XMODE 320x200 Buffered\");\n\t\t\t} else {\n\t\t\t\tif (config->DrawFlags & VQACFGF_VRAMCB) {\n\t\t\t\t\tMono_Print(\"XMODE 320x200 VRAM Copy\");\n\t\t\t\t} else {\n\t\t\t\t\tMono_Print(\"XMODE 320x200 Linear->Banked\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase XMODE_320X240:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tMono_Print(\"XMODE 320x240 Buffered\");\n\t\t\t} else {\n\t\t\t\tif (config->DrawFlags & VQACFGF_VRAMCB) {\n\t\t\t\t\tMono_Print(\"XMODE 320x240 VRAM Copy\");\n\t\t\t\t} else {\n\t\t\t\t\tMono_Print(\"XMODE 320x240 Linear->Banked\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t#endif\n\n\t\t#if(VQAVESA_ON)\n\t\tcase VESA_640X480_256:\n\t\t\tMono_Print(\"VESA 640x480\");\n\t\t\tbreak;\n\n\t\tcase VESA_320X200_32K_1:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tMono_Print(\"VESA 320x200 Buffered\");\n\t\t\t} else {\n\t\t\t\tMono_Print(\"VESA 320x200 Direct to screen\");\n\t\t\t}\n\t\t\tbreak;\n\t\t#endif\n\n\t\tdefault:\n\t\t\tMono_Print(\"UNKNOWN\");\n\t\t\tbreak;\n\t}\n\n\t/* Sound status */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 2);\n\tMono_Print(\"               Sound: \");\n\n\tif (config->OptionFlags & VQAOPTF_AUDIO) {\n\t\tsprintf(txt,\"%u Hz\", config->AudioRate);\n\t\tMono_Print(txt);\n\t}\telse {\n\t\tMono_Print(\"OFF\");\n\t}\n\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 3);\n\tMono_Print(\"         Driver Name: \");\n\tMono_Print(HMIDevName);\n\n\t/* Frame rates */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 4);\n\tsprintf(txt,\"     Load Frame Rate: %d\", config->FrameRate);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 5);\n\tsprintf(txt,\"     Draw Frame Rate: %d\", config->DrawRate);\n\tMono_Print(txt);\n\n\t/* Slow palette */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 6);\n\tMono_Print(\"        Slow palette: \");\n\n\tif (config->OptionFlags & VQAOPTF_SLOWPAL) {\n\t\tMono_Print(\"ON\");\n\t} else {\n\t\tMono_Print(\"OFF\");\n\t}\n\n\t/* Memory Usage */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 7);\n\tsprintf(txt,\"         Memory Used: %ld\", vqabuf->MemUsed);\n\tMono_Print(txt);\n\n\t/* Timer Method */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 8);\n\n\tif (VQA_TimerMethod() == VQA_TMETHOD_DOS) {\n\t\tMono_Print(\"           DOS Timer:\");\n\t} else if (VQA_TimerMethod() == VQA_TMETHOD_INT) {\n\t\tMono_Print(\"     Interrupt Timer:\");\n\t} else if (VQA_TimerMethod() == VQA_TMETHOD_AUDIO) {\n\t\tMono_Print(\"     Audio DMA Timer:\");\n\t} else {\n\t\tMono_Print(\"             Defualt:\");\n\t}\n\n\t/* Init loader data window */\n\tMono_Draw_Rect(LOADER_WX1, LOADER_WY1, (LOADER_WX2 - LOADER_WX1 + 1),\n\t\t\t(LOADER_WY2 - LOADER_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((LOADER_WX2 + LOADER_WX1 - strlen(LOADER_TITLE)) / 2,\n\t\t\tLOADER_WY1);\n\n\tMono_Print(LOADER_TITLE);\n\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 1);\n\tMono_Print(\"  Current Frame #:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 2);\n\tMono_Print(\"# Waits on Drawer:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 3);\n\tMono_Print(\" # Waits on Audio:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 4);\n\tMono_Print(\"       Frame Size:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 5);\n\tMono_Print(\"   Max Frame Size:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY2 - 2);\n\tMono_Print(\"Audio:\");\n\n\t/* Init drawer data window */\n\tMono_Draw_Rect(DRAWER_WX1, DRAWER_WY1, (DRAWER_WX2 - DRAWER_WX1 + 1),\n\t\t\t(DRAWER_WY2 - DRAWER_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((DRAWER_WX2 + DRAWER_WX1 - strlen(DRAWER_TITLE)) / 2,\n\t\t\tDRAWER_WY1);\n\n\tMono_Print(DRAWER_TITLE);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 1);\n\tMono_Print(\"   Current Frame #:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 2);\n\tMono_Print(\"   Desired Frame #:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 3);\n\tMono_Print(\"# Waits on Flipper:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 4);\n\tMono_Print(\" # Waits on Loader:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 5);\n\tMono_Print(\"  # Frames Skipped:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 6);\n\tMono_Print(\"     VQ Block Size:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY2 - 2);\n\tMono_Print(\"Frames:                 Cbooks:\");\n\n\t/* Init audio data window */\n\tMono_Draw_Rect(AUDIO_WX1, AUDIO_WY1, (AUDIO_WX2 - AUDIO_WX1 + 1),\n\t\t\t(AUDIO_WY2 - AUDIO_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((AUDIO_WX2 + AUDIO_WX1 - strlen(AUDIO_TITLE)) / 2,\n\t\t\tAUDIO_WY1);\n\n\tMono_Print(AUDIO_TITLE);\n\n\tMono_Set_Cursor(AUDIO_WX1 + 2, AUDIO_WY1 + 1);\n\tMono_Print(\"# Repeated Buffers:\");\n\n\t/* Init flipper data window */\n\tMono_Draw_Rect(FLIPPER_WX1, FLIPPER_WY1, (FLIPPER_WX2 - FLIPPER_WX1 + 1),\n\t\t\t(FLIPPER_WY2 - FLIPPER_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((FLIPPER_WX2 + FLIPPER_WX1 - strlen(FLIPPER_TITLE)) / 2,\n\t\t\tFLIPPER_WY1);\n\n\tMono_Print(FLIPPER_TITLE);\n\n\tMono_Set_Cursor(FLIPPER_WX1 + 2, FLIPPER_WY1 + 1);\n\tMono_Print(\"Current Frame #:\");\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_UpdateMono - Update the player's mono output.\n*\n* SYNOPSIS\n*     VQA_UpdateMono(VQA)\n*\n*     void VQA_UpdateMono(VQAHandleP *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to private VQA handle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\n#pragma argsused\nvoid VQA_UpdateMono(VQAHandleP *vqap)\n{\n\tVQAData       *vqabuf;\n\tVQAConfig     *config;\n\tVQAFrameNode  *frame;\n\tVQACBNode     *cbook;\n\tlong          frameindex = -1;\n\tlong          loadcb = -1;\n\tlong          drawcb = -1;\n\tlong          i;\n\tunsigned long curtime;\n\tchar          txt[80];\n\n\t/* Dereference commonly used data members for quick access. */\n\tvqabuf = vqap->VQABuf;\n\tconfig = &vqap->Config;\n\n\t/* Timer value */\n\tcurtime = VQA_GetTime(vqap);\n\tMono_Set_Cursor(MAIN_WX1 + 40, MAIN_WY1 + 8);\n\tsprintf(txt,\"%02ld:%02ld.%02ld\",curtime / (VQA_TIMETICKS * VQA_TIMETICKS),\n\t\t\tcurtime / VQA_TIMETICKS,((curtime * 100L) / VQA_TIMETICKS)\n\t\t\t-((curtime / VQA_TIMETICKS) * 100L));\n\n\tMono_Print(txt);\n\n\t/* Loader data */\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 1);\n\tsprintf(txt,\"%4d\",vqabuf->Loader.LastFrameNum);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 2);\n\tsprintf(txt,\"%4ld\",vqabuf->Loader.WaitsOnDrawer);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 3);\n\tsprintf(txt,\"%4ld\",vqabuf->Loader.WaitsOnAudio);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 4);\n\tsprintf(txt,\"%5u\",vqabuf->Loader.FrameSize);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 5);\n\tsprintf(txt,\"%5u\",vqabuf->Loader.MaxFrameSize);\n\tMono_Print(txt);\n\n\t#if(VQAAUDIO_ON)\n\t/* Draw a picture of the audio buffers */\n\tfor (i = 0; i < vqabuf->Audio.NumAudBlocks; i++) {\n\t\tif (vqabuf->Audio.IsLoaded[i] == 0) {\n\t\t\ttxt[i] = '_';\n\t\t} else {\n\t\t\ttxt[i] = 'X';\n\t\t}\n\t}\n\n\ttxt[i] = 0;\n\tMono_Set_Cursor(LOADER_WX1 + 9,LOADER_WY2 - 2);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 9,LOADER_WY2-1); \n\tMono_Print(\"                        \");\n\n\tMono_Set_Cursor(LOADER_WX1 + 9 + vqabuf->Audio.PlayPosition\n\t\t\t/ config->HMIBufSize,LOADER_WY2 - 1);\n\n\tMono_Print(\"P\");\n\n\tMono_Set_Cursor(LOADER_WX1 + 9 + vqabuf->Audio.AudBufPos\n\t\t\t/ config->HMIBufSize,LOADER_WY2 - 1);\n\n\tMono_Print(\"L\");\n\t#endif /* VQAAUDIO_ON */\n\n\t/* Drawer data */\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 1);\n\tsprintf(txt,\"%4d\", vqabuf->Drawer.LastFrameNum);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 2);\n\tsprintf(txt,\"%4d\", vqabuf->Drawer.DesiredFrame);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 3);\n\tsprintf(txt,\"%4ld\", vqabuf->Drawer.WaitsOnFlipper);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 4);\n\tsprintf(txt,\"%4ld\", vqabuf->Drawer.WaitsOnLoader);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 5);\n\tsprintf(txt,\"%4d\", vqabuf->Drawer.NumSkipped);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 6);\n\tsprintf(txt,\" %dx%d\", vqap->Header.BlockWidth, vqap->Header.BlockHeight);\n\tMono_Print(txt);\n\n\t/* Draw a picture of the frame buffers */\n\tframe = vqabuf->FrameData;\n\n\tfor (i = 0; i < config->NumFrameBufs; i++) {\n\t\tif (frame->Flags & VQAFRMF_LOADED) {\n\t\t\ttxt[i] = 'X';\n\t\t} else {\n\t\t\ttxt[i] = '_';\n\t\t}\n\n\t\tif (vqabuf->Flipper.CurFrame == frame) {\n\t\t\tframeindex = i;\n\t\t}\n\n\t\tframe = frame->Next;\n\t}\n\n\ttxt[i] = 0;\n\tMono_Set_Cursor(DRAWER_WX1 + 10,DRAWER_WY2 - 2);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 10,DRAWER_WY2 - 1);\n\tMono_Print(\"              \");\n\n\tMono_Set_Cursor(DRAWER_WX1 + 10 + frameindex,DRAWER_WY2 - 1);\n\tMono_Print(\"^\");\n\n\t/* Draw a picture of the codebook buffers */\n\tcbook = vqabuf->CBData;\n\n\tfor (i = 0; i < config->NumCBBufs; i++) {\n\t\tif (vqabuf->Loader.CurCB == cbook) {\n\t\t\tloadcb = i;\n\t\t}\n\n\t\tif (vqabuf->Flipper.CurFrame->Codebook == cbook) {\n\t\t\tdrawcb = i;\n\t\t}\n\n\t\tcbook = cbook->Next;\n\t}\n\n\tMono_Set_Cursor(DRAWER_WX1 + 34,DRAWER_WY2 - 2);\n\tMono_Print(\"___\");\n\n\tMono_Set_Cursor(DRAWER_WX1 + 34,DRAWER_WY2 - 1);\n\tMono_Print(\"   \");\n\n\tMono_Set_Cursor(DRAWER_WX1 + 34 + loadcb,DRAWER_WY2 - 1);\n\tMono_Print(\"L\");\n\n\tMono_Set_Cursor(DRAWER_WX1 + 34 + drawcb,DRAWER_WY2 - 1);\n\tMono_Print(\"D\");\n\n\t/* Audio data */\n\t#if(VQAAUDIO_ON)\n\tMono_Set_Cursor(AUDIO_WX1 + 22, AUDIO_WY1 + 1);\n\tsprintf(txt,\"%4ld\", vqabuf->Audio.NumSkipped);\n\tMono_Print(txt);\n\t#endif\n\n\t/* Flipper data */\n\tMono_Set_Cursor(FLIPPER_WX1 + 22,FLIPPER_WY1 + 1);\n\tsprintf(txt,\"%4d\", vqabuf->Flipper.LastFrameNum);\n\tMono_Print(txt);\n\tMono_Set_Cursor(0,0);\n}\n\n#endif /* VQAMONO_ON */\n\n"
  },
  {
    "path": "VQ/VQA32/SOS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sos.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DEFINED   \n#define  _SOS_DEFINED   \n#include \"sosdefs.h\"\n\n#pragma pack(4)\n \n// error definition for sound operating system  \n#define  _SOS_ERR          -1\n\n// number of drivers allowed to be open at one time\n#define  _SOS_MAX_DRIVERS  5\n\n// structure definition for the capabilities\ntypedef struct _tagCAPABILITIES\n{\n   BYTE  szDeviceName[ 32 ];  // device name\n   WORD  wDeviceVersion;      // device version\n   WORD  wBitsPerSample;      // bits per sound sample\n   WORD  wChannels;           // stereo/mono sound card\n   WORD  wMinRate;            // minimum rate\n   WORD  wMaxRate;            // maximum rate\n   WORD  wMixerOnBoard;       // board contains mixer\n   WORD  wMixerFlags;         // mixer capabilities\n   WORD  wFlags;              // miscellaneous flags   \n   short far * lpPortList;         // list of usable ports\n   short far * lpDMAList;          // list of usable dma channels\n   short far * lpIRQList;          // list of usable irq channels\n   short far * lpRateList;         // list of usable rates, -1 if any in min to max\n   WORD  fBackground;         // foreground or background driver\n   WORD  wDeviceID;           // ID for the device\n   WORD  wTimerID;            // ID for the timer\n   \n} _SOS_CAPABILITIES; \n\n// far pointer to the device capabilities structure\ntypedef _SOS_CAPABILITIES far *  LPSOSDEVICECAPS;\n\n// flag types for driver\n#define  _FLAGS_SIGNED              0x8000\n  \n// devices that can be loaded\n#define  _SOUND_BLASTER_8_MONO      0xe000\n#define  _SOUND_BLASTER_8_ST        0xe001\n#define  _SBPRO_8_ST                _SOUND_BLASTER_8_ST\n#define  _SBPRO_8_MONO              0xe00f\n#define  _SOUND_MASTER_II_8_MONO    0xe002\n#define  _MV_PAS_8_MONO             0xe003\n#define  _MV_PAS_16_MONO            0xe004\n#define  _MV_PAS_8_ST               0xe005\n#define  _MV_PAS_16_ST              0xe006\n#define  _ADLIB_GOLD_8_ST           0xe007\n#define  _ADLIB_GOLD_16_ST          0xe008\n#define  _ADLIB_GOLD_8_MONO         0xe009\n#define  _ADLIB_GOLD_16_MONO        0xe00a\n#define  _MICROSOFT_8_MONO          0xe00b\n#define  _MICROSOFT_8_ST            0xe00c\n#define  _MICROSOFT_16_MONO         0xe00d\n#define  _MICROSOFT_16_ST           0xe00e\n#define  _SOUND_SOURCE_8_MONO_PC    0xe010\n#define  _SOUND_SOURCE_8_MONO_TANDY 0xe011\n#define  _GENERAL_PORT_8_MONO       0xe012\n#define  _GENERAL_PORT_8_MONO_R     0xe013\n#define  _SIERRA_8_MONO             0xe014\n#define  _SB16_8_MONO               0xe015\n#define  _SB16_8_ST                 0xe016\n#define  _SB16_16_MONO              0xe017\n#define  _SB16_16_ST                0xe018\n#define  _ESS_AUDIODRIVE_8_MONO     0xe019\n#define  _ESS_AUDIODRIVE_8_ST       0xe01a\n#define  _ESS_AUDIODRIVE_16_MONO    0xe01b\n#define  _ESS_AUDIODRIVE_16_ST      0xe01c\n#define  _SOUNDSCAPE_8_MONO         0xe01d\n#define  _SOUNDSCAPE_8_ST           0xe01e\n#define  _SOUNDSCAPE_16_MONO        0xe01f\n#define  _SOUNDSCAPE_16_ST          0xe020\n#define  _RAP10_8_MONO              0xe021\n#define  _RAP10_16_MONO             0xe022\n#define  _GUS_8_MONO                0xe023\n#define  _GUS_8_ST                  0xe024\n#define  _GUS_16_MONO               0xe025\n#define  _GUS_16_ST                 0xe026\n#define  _GUS_MAX_8_MONO            0xe027\n#define  _GUS_MAX_8_ST              0xe028\n#define  _GUS_MAX_16_MONO           0xe029\n#define  _GUS_MAX_16_ST             0xe02a\n#define  _WAVEJAMMER_8_MONO         0xe02b\n#define  _WAVEJAMMER_8_ST           0xe02c\n#define  _WAVEJAMMER_16_MONO        0xe02d\n#define  _WAVEJAMMER_16_ST          0xe02e\n#define  _TEMPOCS_8_MONO            0xe02f\n#define  _TEMPOCS_8_ST              0xe030\n#define  _TEMPOCS_16_MONO           0xe031\n#define  _TEMPOCS_16_ST             0xe032\n#define  _WAVEJAMMERCD_8_MONO       0xe033\n#define  _WAVEJAMMERCD_8_ST         0xe034\n#define  _WAVEJAMMERCD_16_MONO      0xe035\n#define  _WAVEJAMMERCD_16_ST        0xe036\n#define  _SOUND_BLASTER_8_MONO_R    0xe050\n#define  _MICROSOFT_8_MONO_R        0xe051\n#define  _SOUND_MASTER_II_8_MONO_R  0xe052\n#define  _ADLIB_GOLD_8_MONO_R       0xe053\n#define  _MV_PAS_8_MONO_R           0xe054\n#define  _RAP10_8_MONO_R            0xe058\n#define  _RAP10_16_MONO_R           0xe059\n#define  _SB16_8_MONO_R             0xe05a\n#define  _SB16_8_ST_R               0xe05b\n#define  _SB16_16_MONO_R            0xe05c\n#define  _SB16_16_ST_R              0xe05d\n#define  _MV_PAS_16_MONO_R          0xe060\n#define  _SOUNDSCAPE_8_MONO_R       0xe061\n#define  _SOUNDSCAPE_8_ST_R         0xe062\n#define  _SOUNDSCAPE_16_MONO_R      0xe063\n#define  _SOUNDSCAPE_16_ST_R        0xe064\n#define  _ESS_AUDIODRIVE_8_MONO_R   0xe065\n#define  _ESS_AUDIODRIVE_8_ST_R     0xe066\n#define  _ESS_AUDIODRIVE_16_MONO_R  0xe067\n#define  _ESS_AUDIODRIVE_16_ST_R    0xe068\n#define  _SPEECH_THING_8_MONO       0xe090\n#define  _YAMAHA_8_MONO             0xe106\n#define  _INT_SPEAKER_8_MONO        0xe107\n\n// call indexes for the loadable drivers\nenum\n{ \n   _DRV_INIT,\n   _DRV_UNINIT,\n   _DRV_SETRATE,\n   _DRV_SETACTION,\n   _DRV_START,\n   _DRV_STOP,\n   _DRV_PAUSE,\n   _DRV_RESUME,\n   _DRV_CAPABILITIES,\n   _DRV_PLAY_FOREGROUND,\n   _DRV_GET_FILL_INFO, \n   _DRV_GET_CALL_FUNCTIONS,\n   _DRV_SET_CALL_FUNCTIONS\n};\n\n// fill info\ntypedef  struct   _tagFillInfo\n         {\n\n            LPSTR lpFillHandler;                   // pointer to fill handler\n            LPWORD lpDMAFillCount;                 // pointer to dma count\n            LPSTR lpSampleList;                    // pointer to sample list\n            LPWORD lpDMAMasterVolume;              // pointer to dma count\n\n         } _SOS_FILL_INFO;\n\n// caps info structure\ntypedef  struct   _tagCapsInfo\n         {\n\n            LPSTR    lpPortList;                   // pointer to port list\n            LPSTR    lpDMAList;                    // pointer to DMA list\n            LPSTR    lpIRQList;                    // pointer to IRQ list\n            LPSTR    lpRateList;                   // pointer to rate list\n\n         } _SOS_CAPS_INFO;\n\n// maximum number of available voice\n#define  _MAX_VOICES    32\n\n// structure definition\ntypedef  struct   _tagSAMPLE\n{\n   LPSTR    samplePtr;                 // pointer to data buffer\n   LPSTR    sampleData;                // pointer to active data\n   LPSTR    sampleLoopPtr;             // pointer for loop back\n\n   WORD     sampleLength;              // length of sample\n   WORD     sampleIndex;               // index into sample\n   WORD     sampleLoopLength;          // length of loop\n   \n   WORD     sampleBytesLeft;           // bytes left to play in sample\n\n   WORD     sampleLoopPoint;           // byte count for loop point\n   WORD     sampleLoopEndLength;       // length of remaining chunk\n\n   short    sampleFlags;               // control sample\n   short    sampleVolume;              // volume control\n   short    sampleID;                  // sample ID\n\n   short    sampleChannel;             // channel to play sample on\n   short    sampleLoopCount;           // loop count\n   short    sampleLastFill;            // last fill position\n   VOID ( far cdecl * sampleCallback )( WORD, WORD, WORD ); // callback function for sample\n\n   WORD     samplePitchAdd;\n   short    samplePitchFraction;\n\n   short    samplePort;                // port to use for non-dma digitized\n\n   WORD     sampleTotalBytes;\n   WORD     sampleByteLength;\n\n   short    samplePanLocation;\n   short    samplePanSpeed;\n   short    samplePanDirection;\n   short    samplePanStart;\n   short    samplePanEnd;\n   \n   short    sampleDelayBytes;\n   short    sampleDelayRepeat;\n   \n   WORD     sampleADPCMPredicted;\n   short    sampleADPCMIndex;\n\n   short    sampleRootNoteMIDI;   \n\n   WORD  sampleTemp1;   \n   \n} _SOS_SAMPLE;\n\n// enumeration for left or right channel\nenum\n{\n   _LEFT_CHANNEL,\n   _RIGHT_CHANNEL,\n   _CENTER_CHANNEL,\n   _INTERLEAVED\n};\n\n// enumeration for foreground and background\nenum\n{ \n   _FOREGROUND,\n   _BACKGROUND \n};\n\n// defines for the sample flags\n#define  _ACTIVE           0x8000\n#define  _LOOPING          0x4000\n#define  _FIRST_TIME       0x2000\n#define  _PENDING_RELEASE  0x1000\n#define  _CONTINUE_BLOCK   0x0800\n#define  _PITCH_SHIFT      0x0400\n#define  _PANNING          0x0200\n#define  _VOLUME           0x0100\n#define  _TRANSLATE16TO8   0x0080\n#define  _STAGE_LOOP       0x0040\n#define  _TRANSLATE8TO16   0x0020\n#define  _STEREOTOMONO     0x0010\n\n// defines for the wParam flags \n#define  _SINGLE_SAMPLE 0x01\n\n#define  _SOS_DCAPS_AUTO_REINIT     0x01\n#define  _SOS_DCAPS_MPU_401         0x02\n#define  _SOS_DCAPS_OPL2            0x04\n#define  _SOS_DCAPS_OPL3            0x08\n#define  _SOS_DCAPS_OPL4            0x10\n#define  _SOS_DCAPS_WAVETABLE       0x20\n#define  _SOS_DCAPS_DL_SAMPLES      0x40\n#define  _SOS_DCAPS_FIFO_DEVICE     0x80\n#define  _SOS_DCAPS_ENV_NEEDED      0x100\n#define  _SOS_DCAPS_PSEUDO_DMA1     0x200\n#define  _SOS_DCAPS_SIGNED_DATA     0x8000\n\n// file header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // number of drivers in the file\n   WORD  wDrivers;\n\n   // offset of first driver\n   WORD  lOffset;\n\n   // size of the file\n   WORD  lFileSize;\n\n} _FILEHEADER;\n\n// driver header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // offset of next driver\n   WORD  lNextDriver;\n\n   // size of current driver\n   WORD  wSize;\n\n   // id for the current device\n   WORD  wDeviceID;\n\n   // id for the type of DOS extender\n   WORD  wExtenderType;\n\n} _DRIVERHEADER;\n\n// device hardware information\ntypedef struct\n{\n   // port to be used\n   WORD  wPort;\n\n   // irq to use\n   WORD  wIRQ;\n\n   // dma channel to se\n   WORD  wDMA; \n  \n   // extra parameter\n   WORD  wParam;\n\n} _SOS_HARDWARE;\n\n// structure definition for start sample\ntypedef struct\n{\n   // pointer to sample\n   LPSTR lpSamplePtr;\n\n   // size of the sample\n   WORD  dwSampleSize;\n\n   // number of times to loop the sample -1 is infinite\n   WORD  wLoopCount;\n\n   // channel to play sample on\n   WORD  wChannel;\n\n   // volume to play sample at\n   WORD wVolume;\n\n   // id for the sample\n   WORD  wSampleID;\n\n   // far pointer to the callback function\n   VOID ( far cdecl *lpCallback )( WORD, WORD, WORD );\n\n   // port to use if driver is a non-dma background driver\n   WORD  wSamplePort; \n\n   // flags field\n   WORD  wSampleFlags;\n\n   // total length of sample including loops, etc..\n   WORD     dwSampleByteLength;\n\n   // loop point for the sample\n   WORD  dwSampleLoopPoint;\n   WORD  dwSampleLoopLength;\n\n   // pitch shifting components \n   WORD     dwSamplePitchAdd;\n   WORD    wSamplePitchFraction;\n\n   // pan components\n   WORD    wSamplePanLocation;\n   WORD    wSamplePanSpeed;\n   WORD    wSamplePanDirection;\n   WORD    wSamplePanStart;\n   WORD    wSamplePanEnd;\n   \n   // delay parts\n   WORD    wSampleDelayBytes;\n   WORD    wSampleDelayRepeat;\n\n   // compression components   \n   WORD     dwSampleADPCMPredicted;\n   WORD    wSampleADPCMIndex;\n\n   // root note for pitch shifting \n   WORD    wSampleRootNoteMIDI;   \n\n   // filler for future upgrades\n   WORD  dwSampleTemp1;   \n   WORD  dwSampleTemp2;   \n   WORD  dwSampleTemp3;   \n\n} _SOS_START_SAMPLE;\n\n// structure for initializing a driver\ntypedef struct\n{  \n   WORD  wBufferSize;\n   LPSTR lpBuffer;\n   BOOL  wAllocateBuffer;\n   WORD  wSampleRate;\n   WORD  wParam;\n   LONG  dwParam;\n   VOID ( far *lpFillHandler )( VOID );\n   LPSTR lpDriverMemory;\n   LPSTR lpDriverMemoryCS;\n   LPSTR lpTimerMemory;\n   LPSTR lpTimerMemoryCS;\n   WORD  wTimerID;\n   WORD  wPhysical;\n\n} _SOS_INIT_DRIVER;\n\n// define for the timer types to use\n#define  _SOS_NORMAL_TIMER          0x00\n\n// enumeration for the timer types\nenum\n{\n   _TIMER_8_MONO   =     0x1000,\n   _TIMER_8_ST,          \n   _TIMER_16_MONO,       \n   _TIMER_16_ST,         \n   _TIMER_8_MONO_ULAW,  \n   _TIMER_8_ST_ULAW,    \n   _TIMER_16_MONO_ULAW, \n   _TIMER_16_ST_ULAW,   \n   _TIMER_8_MONO_REC,   \n   _TIMER_8_MONO_ULAW_REC,\n   _TIMER_UNDEFINED_1,      \n   _TIMER_UNDEFINED_2,\n   _TIMER_UNDEFINED_3,\n   _TIMER_UNDEFINED_4,\n   _TIMER_UNDEFINED_5,\n   _TIMER_UNDEFINED_6,\n   _TIMER_UNDEFINED_7,\n   _TIMER_UNDEFINED_8,\n   _TIMER_UNDEFINED_9,\n   _TIMER_UNDEFINED_A,\n   _TIMER_UNDEFINED_B,\n   _TIMER_UNDEFINED_C,\n   _TIMER_UNDEFINED_D,\n   _TIMER_UNDEFINED_E,\n   _TIMER_UNDEFINED_F,\n   _TIMER_UNDEFINED_10,\n   _TIMER_UNDEFINED_11,\n   _TIMER_UNDEFINED_12,\n   _TIMER_UNDEFINED_13,\n   _TIMER_UNDEFINED_14,\n   _TIMER_UNDEFINED_15,\n   _TIMER_UNDEFINED_16,\n   _TIMER_8_SOUND_SOURCE,\n   _TIMER_8_SOUND_SOURCE_TANDY,\n   _TIMER_8_GENERAL_PORT,\n   _TIMER_8_GENERAL_PORT_REC   \n};\n\n// define for no slots available\n#define  _ERR_NO_SLOTS ( WORD )-1\n\n// error codes for the system\nenum\n{\n   _ERR_NO_ERROR,\n   _ERR_DRIVER_NOT_LOADED,\n   _ERR_INVALID_POINTER,\n   _ERR_DETECT_INITIALIZED,\n   _ERR_FAIL_ON_FILE_OPEN,\n   _ERR_MEMORY_FAIL,\n   _ERR_INVALID_DRIVER_ID,\n   _ERR_NO_DRIVER_FOUND,\n   _ERR_DETECTION_FAILURE,\n   _ERR_DRIVER_LOADED,\n   _ERR_INVALID_HANDLE,\n   _ERR_NO_HANDLES,\n   _ERR_PAUSED,   \n   _ERR_NOT_PAUSED,\n   _ERR_INVALID_DATA,\n   _ERR_DRV_FILE_FAIL,\n   _ERR_INVALID_PORT,\n   _ERR_INVALID_IRQ,\n   _ERR_INVALID_DMA,\n   _ERR_INVALID_DMA_IRQ\n};   \n\n// maximum number of timer events that can be registered \n#define  _TIMER_MAX_EVENTS    0x10  \n\n// flags for the debugging system\n#define  _SOS_DEBUG_NORMAL       0x0000\n#define  _SOS_DEBUG_NO_TIMER     0x0001\n#define  _SOS_TIMER_DPMI         0x0002\n\n// define for types of DOS extenders\n#define  _SOS_RATIONAL           0x8000\n#define  _SOS_FLASHTECK          0x4000\n\n// defines for the types of timers for different\n// dos extenders\n#define  _SOS_TIMER_NEAR         0x8000\n#define  _SOS_TIMER_FAR          0x4000\n \n// values for callback information\nenum\n{\n   _SAMPLE_PROCESSED,\n   _SAMPLE_LOOPING,\n   _SAMPLE_DONE\n};\n\n// define for special 18.2 callback rate to dos\n#define  _TIMER_DOS_RATE   0xff00\n\n#pragma pack()\n\n#pragma aux int_3 = \"int 3\"\n \n#pragma pack( 1 ) \ntypedef struct\n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned       segment;\n\tunsigned short\tnumber_available;\n\tunsigned short number_used;\n\tunsigned       page0;\n\n} EVDS_STRUCT;\n\ntypedef struct \n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned short segment;\n\tunsigned short\tID;\n\tunsigned       physical;\n\n} VDS_STRUCT;\n\n#pragma pack() \n\n#include \"sosdata.h\"\n#include \"sosfnct.h\"\n\n#endif\n"
  },
  {
    "path": "VQ/VQA32/SOSDATA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdata.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DATA\n#define  _SOS_DATA\n\n#include <stddef.h>\n\n#pragma pack(4) \nextern   WORD     _sosDIGIData_Start;\nextern   WORD     _sosDIGIData_End;\nextern   WORD     _wSOSDriverLinear[];\nextern   WORD     _wSOSTimerLinear[];\nextern   LPSTR    _lpSOSDriver[];\nextern   LPSTR    _lpSOSTimer[];\nextern   LPSTR    _lpSOSDriverCS[];\nextern   LPSTR    _lpSOSTimerCS[];\nextern   BOOL     _wSOSDriverLoaded[];\nextern   BOOL     _wSOSTimerLoaded[];\nextern   BOOL     _wSOSDriverInitialized[];\nextern   WORD     _wSOSOutputRate[];\nextern   WORD     _wSOSDMABuffersize[];\nextern   LONG     _dwSOSDMABufferPhysical[];\nextern   LPSTR    _lpSOSDMABuffer[];\nextern   BOOL     _wTimerUsed;\nextern   VOID ( far *_lpSOSFillHandler[] )( VOID );\nextern   WORD     _wSOSTimerType[];\nextern   WORD     _wSOSDriverType[];\nextern   _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ];\nextern   LPWORD      _lpSOSDMAIrqCount[];\nextern   LPWORD      _lpSOSDMAFillCount[];\nextern   WORD        _wSOSTmrNextCount;\nextern   VOID ( interrupt far *_lpSOSOldTimer )( VOID );\nextern   WORD     _wSOSDriverID[];\nextern   _SOS_CAPABILITIES _sSOSDriverCaps[];\nextern   WORD        _wSOSDMAPortList[];\nextern   BYTE        _bSOSDMAChannel[];\nextern   _SOS_INIT_DRIVER     _sSOSDIGIInitDriver[];\nextern   BYTE  _pSOSDriverPath[];\nextern   BYTE  _pSOSTempDriverPath[];\nextern   BOOL  _wTIMERUsed;\nextern   WORD  _wTIMERValue;\nextern   VOID ( far * _lpTIMEREvents[] )( VOID );\nextern   WORD _wTIMEREventRate[];\nextern   WORD _dwTIMEREventFraction[];\nextern   WORD _dwTIMEREventFractionCurrent[];\nextern   BYTE  _bSOSMIDITimerSongHandler[];\nextern   BYTE  _bSOSMIDISongHandle;\nextern   WORD  _wSOSTimerMemHandle[];\nextern   WORD  _wSOSDriverMemHandle[];\nextern   WORD  _wSOSRealSeg[];\n\nextern   _FILEHEADER    _sDETFileHeader;\nextern   _DRIVERHEADER  _sDETDriverHeader;\nextern   _FILEHEADER    sLOADFileHeader;\nextern   _DRIVERHEADER  sLOADDriverHeader;\nextern   BOOL           _wDETInitialized;\nextern   WORD           _wDETLinear;\nextern   LPSTR          _lpDETDriverBuffer;    \nextern   LPSTR          _lpDETDriverBufferCS;\nextern   WORD           _hDETFile;\nextern   DWORD          _dwDETDriverIndex;\nextern   WORD           _wDETDriverIndexCur;\nextern   WORD           _wDETMemHandle;\nextern   LPSOSDEVICECAPS _lpDETDeviceCaps;\nextern   _SOS_CAPABILITIES _sDETCaps;  \nextern   PSTR _pSOSErrorStrings[];\nextern   BOOL _wSOSBufferAllocated[];\nextern   BOOL _wSOSSystemInitialized;\nextern   VDS_STRUCT _sSOSVDSInfo;\nextern   _SOS_FILL_INFO _sSOSFillInfo;\nextern   WORD    _wSOSTimerEventIndex;\nextern   WORD  _wSOSTimerEntered;\nextern   WORD  _wSOSDriverSize[];\nextern   WORD  _wSOSTimerSize[];\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nextern   WORD  _sosDIGIData1_Start;\nextern   WORD  _sosDIGIData1_End;\nextern   WORD  _sosDIGIData2_Start;\nextern   WORD  _sosDIGIData2_End;\nextern   BYTE  _bTIMERInstalled;\nextern   BYTE  _bTIMERDPMI;\nextern   WORD  wDetectPort;\nextern   WORD  wDetectIRQ;\nextern   WORD  wDetectDMA;\nextern   WORD  wDetectParam;\n#ifdef __cplusplus\n}\n#endif \n\n#pragma pack()\n\n#endif\n\u001a\n"
  },
  {
    "path": "VQ/VQA32/SOSDEFS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdefs.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n\n#ifndef  _SOSDEFS_DEFINED\n#define  _SOSDEFS_DEFINED\n\n#undef   _TRUE\n#undef   _FALSE\n#undef   _NULL\nenum  \n      { \n         _FALSE, \n         _TRUE \n      };\n\n#define  _NULL  0\n\n#ifndef  VOID\n#define  VOID           void\n#endif\ntypedef  int            BOOL;\ntypedef  unsigned int   UINT;\ntypedef  unsigned char  BYTE;\ntypedef  unsigned       WORD;\n#ifndef  LONG\ntypedef  signed long    LONG;\n#endif\ntypedef  unsigned long  DWORD;\n\ntypedef  BYTE  *        PBYTE;\ntypedef  char near *    PSTR;\ntypedef  WORD  *        PWORD;\ntypedef  LONG  *        PLONG;\ntypedef  VOID  *        PVOID;\n\ntypedef  BYTE  far   *  LPBYTE;\ntypedef  BYTE  far   *  LPSTR;\ntypedef  WORD  far   *  LPWORD;\ntypedef  LONG  far   *  LPLONG;\ntypedef  VOID  far   *  LPVOID;\n\ntypedef  BYTE  huge  *  HPBYTE;\ntypedef  BYTE  huge  *  HPSTR;\ntypedef  WORD  huge  *  HPWORD;\ntypedef  LONG  huge  *  HPLONG;\ntypedef  VOID  huge  *  HPVOID;\n\ntypedef  unsigned       HANDLE;\n\n#endif\n\u001a\n"
  },
  {
    "path": "VQ/VQA32/SOSFNCT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosfnct.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_FUNCTIONS\n#define  _SOS_FUNCTIONS\n\n#pragma pack(4)\n\nWORD sosDIGILockMemory          (  VOID  );\nWORD sosDIGIUnLockMemory        (  VOID  );\nWORD sosDIGIInitSystem           (  LPSTR, WORD  );\nWORD sosDIGIUnInitSystem         (  VOID  );\nWORD sosDIGIInitDriver           (  WORD, _SOS_HARDWARE far *,\n                                    _SOS_INIT_DRIVER far *, WORD far *   );\nWORD sosDIGIUnInitDriver         (  WORD, BOOL, BOOL  );\nWORD sosDIGILoadDriver          (  WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD sosDIGIUnLoadDriver         (  WORD  );\nWORD sosDIGIGetDeviceCaps        (  WORD, LPSOSDEVICECAPS  );\n\n#ifdef PHARLAP\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#else\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#endif\n\nWORD sosDIGIStopSample           (  WORD, WORD  );\nWORD sosDIGISamplesPlaying       (  WORD  );\nBOOL sosDIGISampleDone           (  WORD, WORD  );\nBOOL sosDIGISampleFilling        (  WORD, WORD  );\nWORD sosDIGIStartSample          (  WORD, _SOS_START_SAMPLE far *  );\nWORD sosDIGIContinueSample       (  WORD, WORD, _SOS_START_SAMPLE far * );\n\n\nWORD  sosDIGIDetectInit          (  LPSTR  );\nWORD  sosDIGIDetectUnInit        (  VOID  );\nWORD  sosDIGIDetectFindHardware  (  WORD, _SOS_CAPABILITIES far *, WORD far * );\nWORD  sosDIGIDetectFindFirst     (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectFindNext      (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectGetSettings   (  _SOS_HARDWARE far *  );\nWORD  sosDIGIDetectGetCaps       (  WORD, _SOS_CAPABILITIES far *  );\nWORD  sosDIGIDetectVerifySettings(  _SOS_HARDWARE far *  );\nPSTR  sosGetErrorString          (  WORD  );\n\nWORD  sosDIGILoadTimer           (  WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD  sosDIGIUnLoadTimer         (  WORD  );\n\nWORD  sosTIMERRegisterEvent      ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle );\nWORD  sosTIMERInitSystem               (  WORD, WORD  );\nWORD  sosTIMERUnInitSystem             (  WORD  );\nWORD  sosTIMERSetRate                  (  WORD  );  \nWORD  sosTIMERRemoveEvent              (  WORD );\nWORD  sosTIMERAlterEventRate           (  WORD, WORD  );\nWORD  sosTIMERGetEventRate             (  WORD  );\nVOID far sosTIMEROldHandler            (  VOID  );\nVOID far sosTIMERHandler               (  VOID  );\n\n// functions in soscntl.c\nWORD  sosDIGISetSampleVolume     ( WORD, WORD, WORD );\nWORD  sosDIGIGetSampleVolume     ( WORD, WORD );\nWORD  sosDIGISetChannel          ( WORD, WORD, WORD );\nWORD  sosDIGIGetChannel          ( WORD, WORD );\nWORD  sosDIGIGetBytesProcessed   ( WORD, WORD );\nWORD  sosDIGIGetLoopCount        ( WORD, WORD );\nWORD  sosDIGISetPanLocation      ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanLocation      ( WORD, WORD );\nDWORD sosDIGISetPitch            ( WORD, WORD, DWORD );\nDWORD sosDIGIGetPitch            ( WORD, WORD );\nWORD  sosDIGIGetDMAPosition      ( WORD );\nWORD  sosDIGISetPanSpeed         ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanSpeed         ( WORD, WORD );\nWORD  sosDIGIGetSampleID         ( WORD, WORD );\nWORD  sosDIGIGetSampleHandle     ( WORD, WORD );\nWORD  sosDIGISetMasterVolume     ( WORD, WORD );\n#ifdef PHARLAP\nVOID  sosFreeVDSPage          ( unsigned short, unsigned short, DWORD );\nWORD  sosAllocVDSPage         ( unsigned short *, unsigned short *, DWORD * );\n#else\nWORD  sosAllocVDSPage            ( LPSTR *, WORD *, WORD * );\nVOID  sosFreeVDSPage             ( WORD, WORD, LONG );\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef PHARLAP\nextern   int   cdecl sosRealFree          ( int );\nextern   BOOL  cdecl  _sos_read( WORD, LPSTR, WORD, WORD * );\nextern   int   cdecl sosRealAlloc( int, int *, int * );\nextern   void  cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD );\nextern   int   cdecl sosGetCS( VOID );\nextern   int   cdecl sosGetES( VOID );\n#else\nextern   int   cdecl sosRealAlloc         ( int, int *, int * );\nextern   int   cdecl sosRealFree          ( int );\n#endif\n\n// sos driver functions\nextern   WORD  cdecl sosDRVLockMemory     ( DWORD, DWORD );\nextern   WORD  cdecl sosDRVUnLockMemory   ( DWORD, DWORD );\nextern   void  cdecl sosDRVGetCapsInfo    ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVGetCapsPtr     ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVInit           ( LPSTR, LPSTR, int, int, int, int, int, int );  \nextern   void  cdecl sosDRVStart          ( LPSTR, LPSTR, int, int );\nextern   void  cdecl sosDRVSetRate        ( LPSTR, LPSTR, int );\nextern   void  cdecl sosDRVSetAction      ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVStop           ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVUnInit         ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVGetFillInfo    ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * );\nextern   void  cdecl sosFillSampleStructs ( PSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVExist       ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVGetSettings ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR );\nextern   WORD  cdecl sosDIGIInitForWindows( WORD );\nextern   WORD  cdecl sosDIGIUnInitForWindows( WORD );\nextern   LPSTR cdecl sosAllocateFarMem      ( WORD, PSTR, WORD * );\nextern   LPSTR cdecl sosCreateAliasCS       ( LPSTR );\nextern   VOID  cdecl sosFreeSelector        ( LPSTR, DWORD );\nextern   LPSTR cdecl sosMAKEDOSPtr          ( PSTR );\nextern   VOID  cdecl sosDetDRVSetEnvString  ( DWORD, PSTR );\nextern   PSTR  cdecl sosDetDRVGetEnvString  ( DWORD );\nextern   VOID  cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR );\nextern   VOID  cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR );\nextern   WORD  cdecl sosDRVGetFreeMemory     ( VOID );\nextern   WORD  cdecl sosDRVAllocVDSStruct    ( WORD, WORD *, WORD * );\nextern   WORD  cdecl sosDRVFreeVDSStruct     ( WORD, WORD );\nextern   WORD  cdecl sosDRVIsWindowsActive   ( VOID );\nextern   WORD  cdecl sosDRVVDSGetBuffer    ( WORD );\nextern   WORD  cdecl sosDRVVDSFreeBuffer   ( WORD );\nextern   WORD  cdecl getDS( VOID );\nextern   WORD  cdecl sosDRVMakeDMASelector   ( WORD );  \nextern   WORD  cdecl sosDRVFreeDMASelector   ( WORD );  \n\n\nextern   void  cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) );\nextern   void  cdecl sosTIMERDRVUnInit( void );\nextern   void  cdecl sosTIMERDRVHandler( void );\nextern   void  cdecl sosTIMERDRVFHandler( void );\nextern   void  cdecl sosTIMERDRVEnable( void );\nextern   void  cdecl sosTIMERDRVDisable( void );\nextern   void  cdecl sosTIMERDRVCallOld( void );\nextern   void  cdecl sosTIMERDRVSetRate( WORD );    \nextern   void  cdecl sosDIGITimer_Start( void );\nextern   void  cdecl sosDIGITimer_End( void );\nextern   void  cdecl sosDIGIDrv_Start( void );\nextern   void  cdecl sosDIGIDrv_End( void );\n#ifdef __cplusplus\n}\n#endif \n\n// external functions for handling system initialization and \n// uninitialization\nWORD  sosEXDIGInitDriver               (  WORD, WORD, WORD, LPSTR,\n                                          _SOS_HARDWARE far *, WORD *  );\nWORD  sosEXDIGIUnInitDriver            (  VOID  );\n\nWORD  sosEXDETFindDriver               (  WORD, LPSTR, _SOS_HARDWARE far *,\n                                          _SOS_CAPABILITIES far *  );\n\n// memory locking prototypes\nVOID  sosDIGICaps_Start( VOID );\nVOID  sosDIGICaps_End( VOID );\nVOID  sosDIGIErr_Start( VOID );\nVOID  sosDIGIErr_End( VOID );\nVOID  sosDIGITmr_Start( VOID );\nVOID  sosDIGITmr_End( VOID );\nVOID  sosDIGIStart_Start( VOID );\nVOID  sosDIGIStart_End( VOID );\nVOID  sosDIGIPlyng_Start( VOID );\nVOID  sosDIGIPlyng_End( VOID );\nVOID  sosDIGIRate_Start( VOID );\nVOID  sosDIGIRate_End( VOID );\nVOID  sosDIGIDone_Start( VOID );\nVOID  sosDIGIDone_End( VOID );\nVOID  sosDIGIDetec_Start( VOID );\nVOID  sosDIGIDetec_End( VOID );\nVOID  sosDIGIInit_Start( VOID );\nVOID  sosDIGIInit_End( VOID );\nVOID  sosDIGILoad_Start( VOID );\nVOID  sosDIGILoad_End( VOID );\nVOID  sosDIGICntl_Start( VOID );\nVOID  sosDIGICntl_End( VOID );\n\n#pragma pack()\n\n#endif\n"
  },
  {
    "path": "VQ/VQA32/SOSRES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosres.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#define  _SOS_RESOURCE\n#ifndef  _SOS_RESOURCE\n#define  _SOS_RESOURCE\n\n// structure for resource file header\ntypedef struct\n{\n   // file version\n   WORD     wVersion;\n\n   // file size\n   LONG     dwFileSize;\n\n   // number of resources in file\n   WORD     wResCount;\n\n   // offset of resource data from top of file\n   LONG     dwResOffset;\n\n   // offset of sync track from top of file\n   LONG     dwSyncTrackOffset;\n\n}  _RES_FILE_HEADER;\n\n// structure for resource block header\ntypedef struct\n{\n   // resource id\n   WORD     wID;\n\n   // resource type\n   WORD     wResType;\n\n   // offset of next block\n   LONG     dwNextBlock; \n\n   // size of the current resource information\n   LONG     dwResSize;\n\n   // rate to play block at\n   WORD     wBlockRate;\n\n   // id for the sync track to use\n   WORD     wSyncTrackID;\n\n}  _RES_BLOCK_HEADER;\n\n// structure for sync mark tag\ntypedef struct _tagSYNCMARK\n{\n   // ID of the type of mark being used\n   WORD  wID;\n\n   // location in data of sync mark\n   LONG  dwSyncOffset;\n\n   // length of sync block\n   LONG  dwSyncSize;\n\n   // start sample data\n   _SOS_START_SAMPLE sampleData;\n    \n} _RES_SYNCMARK;\n\ntypedef union\n{\n   // structure for sync mark tag\n   _RES_SYNCMARK  syncMark; \n\n} _RES_TAG;\n\n// union for filter information for prepareWave\ntypedef union\n{\n   // filter type\n   WORD     wFilterID;\n\n   // structure for volume\n   struct   volume \n   {\n      WORD  wVolume;\n   };\n\n   // structure for delay\n   struct   delay\n   {  \n      WORD  wDelaySamples;\n   };\n\n} _SOS_FILTER; \n\n \n#endif\n\n\u001a"
  },
  {
    "path": "VQ/VQA32/TASK.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     task.c\n*\n* DESCRIPTION\n*     Loading and drawing delegation\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 25, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_Alloc    - Allocate a VQAHandle to use.\n*     VQA_Free     - Free a VQAHandle.\n*     VQA_Init     - Initialize the VQAHandle IO.\n*     VQA_Play     - Play the VQA movie.\n*     VQA_GetInfo  - Get VQA movie information.\n*     VQA_GetStats - Get VQA movie statistics.\n*     VQA_Version  - Get VQA library version number.\n*     VQA_IDString - Get the VQA player library's ID string.\n*\n* PRIVATE\n*     VQA_IO_Task        - Loader task for multitasking.\n*     VQA_Rendering_Task - Drawer task for multitasking.\n*     User_Update        - Page flip routine called by the task interrupt.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <malloc.h>\n#include <dos.h>\n#include <mem.h>\n#include <conio.h>\n#include <sys\\timeb.h>\n#include <vqm32\\all.h>\n#include \"vqaplayp.h\"\n\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n/* Externals */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern int cdecl Check_Key(void);\nextern int cdecl Get_Key(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Alloc - Allocate a VQAHandle to use.\n*\n* SYNOPSIS\n*     VQAHandle = VQA_Alloc()\n*\n*     VQAHandle *VQA_Alloc(void);\n*\n* FUNCTION\n*     Obtain a VQAHandle. This handle is used by most VQA library functions,\n*     and contains the current position in the file. This is the only legal\n*     way to obtain a VQAHandle.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     VQA - Handle of a VQA.\n*\n****************************************************************************/\n\nVQAHandle *VQA_Alloc(void)\n{\n\tVQAHandleP *vqa;\n\n\tif ((vqa = (VQAHandleP *)malloc(sizeof(VQAHandleP))) != NULL) {\n\t\tmemset(vqa, 0, sizeof(VQAHandleP));\n\t}\n\n\treturn ((VQAHandle *)vqa);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Free - Free a VQAHandle.\n*\n* SYNOPSIS\n*     VQA_Free(VQA)\n*\n*     void VQA_Free(VQAHandle *);\n*\n* FUNCTION\n*     Dispose of a VQAHandle. This is the only legal way to dispose of a\n*     VQAHandle.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle to dispose of.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Free(VQAHandle *vqa)\n{\n\tif (vqa) free(vqa);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Init - Initialize the VQAHandle IO handler.\n*\n* SYNOPSIS\n*     VQA_Init(VQA, IOHandler)\n*\n*     void VQA_Init(VQAHandle *, IOHandler *);\n*\n* FUNCTION\n*     Initialize the specified VQAHandle IO with the client provided custom\n*     IO handler.\n*\n* INPUTS\n*     VQA       - Pointer to VQAHandle to initialize.\n*     IOHandler - Pointer to custom file I/O handler function.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Init(VQAHandle *vqa, long(*iohandler)(VQAHandle *vqa, long action,\n\t\tvoid *buffer, long nbytes))\n{\n\t((VQAHandleP *)vqa)->IOHandler = iohandler;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Play - Play the VQA movie.\n*\n* SYNOPSIS\n*     Error = VQA_Play(VQA, Mode)\n*\n*     long VQA_Play(VQAHandle *, long);\n*\n* FUNCTION\n*     Playback the movie associated with the specified VQAHandle.\n*\n* INPUTS\n*     VQA  - Pointer to handle of movie to play.\n*     Mode - Playback mode.\n*              VQAMODE_RUN   - Run the movie until completion.\n*              VQAMODE_WALK  - Walk the movie frame by frame.\n*              VQAMODE_PAUSE - Pause the movie.\n*              VQAMODE_STOP  - Stop the movie (Shutdown).\n*\n* RESULT\n*     Error - 0 if successful, or error code.\n*\n****************************************************************************/\n\nlong VQA_Play(VQAHandle *vqa, long mode)\n{\n\tVQAData   *vqabuf;\n\tVQAConfig *config;\n\tVQADrawer *drawer;\n\tlong      rc;\n\tlong      i;\n\tlong      key;\n\n\t/* Dereference commonly used data members for quick access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* One time player priming. */\n\tif (!(vqabuf->Flags & VQADATF_PRIMED)) {\n\n\t\t/* Init the Drawer's configuration */\n\t\tVQA_Configure_Drawer((VQAHandleP *)vqa);\n\n\t\t/* If audio enabled & loaded, start playing */\n\t\t#if(VQAAUDIO_ON)\n\t\tif ((config->OptionFlags & VQAOPTF_AUDIO) && vqabuf->Audio.IsLoaded[0]) {\n\t\t\tVQA_StartAudio((VQAHandleP *)vqa);\n\t\t}\n\t\t#endif\n\n\t\t/* Initialize the timer */\n\t\ti = ((vqabuf->Drawer.CurFrame->FrameNum * VQA_TIMETICKS)\n\t\t\t\t/ config->DrawRate);\n\n\t\tVQA_SetTimer((VQAHandleP *)vqa, i, config->TimerMethod);\n\t\tvqabuf->StartTime = VQA_GetTime((VQAHandleP *)vqa);\n\n\t\t/* Set up the Mono screen */\n\t\t#if(VQAMONO_ON)\n\t\tif (config->OptionFlags & VQAOPTF_MONO) {\n\t\t\tVQA_InitMono((VQAHandleP *)vqa);\n\t\t}\n\t\t#endif\n\n\t\t/* Priming is complete. */\n\t\tvqabuf->Flags |= VQADATF_PRIMED;\n\t}\n\n\t/* Main Player Loop */\n\tswitch (mode) {\n\t\tcase VQAMODE_PAUSE:\n\t\t\tif ((vqabuf->Flags & VQADATF_PAUSED) == 0) {\n\t\t\t\tvqabuf->Flags |= VQADATF_PAUSED;\n\t\t\t\tvqabuf->EndTime = VQA_GetTime((VQAHandleP *)vqa);\n\n\t\t\t\t/* Stop the audio while the movie is paused. */\n\t\t\t\t#if(VQAAUDIO_ON)\n\t\t\t\tif (vqabuf->Audio.Flags & VQAAUDF_ISPLAYING) {\n\t\t\t\t\tVQA_StopAudio((VQAHandleP *)vqa);\n\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\trc = VQAERR_PAUSED;\n\t\t\tbreak;\n\n\t\tcase VQAMODE_RUN:\n\t\tcase VQAMODE_WALK:\n\t\tdefault:\n\n\t\t\t/* Start up the movie if is it currently paused. */\n\t\t\tif (vqabuf->Flags & VQADATF_PAUSED) {\n\t\t\t\tvqabuf->Flags &= ~VQADATF_PAUSED;\n\t\t\t \n\t\t\t\t/* Start the audio if it was previously on. */\n\t\t\t\t#if(VQAAUDIO_ON)\n\t\t\t\tif (config->OptionFlags & VQAOPTF_AUDIO) {\n\t\t\t\t\tVQA_StartAudio((VQAHandleP *)vqa);\n\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\tVQA_SetTimer((VQAHandleP *)vqa, vqabuf->EndTime, config->TimerMethod);\n\t\t\t}\n\t\t\t\n\t\t\t/* Load, Draw, Load, Draw, Load, Draw ... */\n\t\t\twhile ((vqabuf->Flags & (VQADATF_DDONE|VQADATF_LDONE))\n\t\t\t\t\t!= (VQADATF_DDONE|VQADATF_LDONE)) {\n\n\t\t\t\t/* Load a frame */\n\t\t\t\tif (!(vqabuf->Flags & VQADATF_LDONE)) {\n\t\t\t\t\tif ((rc = VQA_LoadFrame(vqa)) == 0) {\n\t\t\t\t\t\tvqabuf->LoadedFrames++;\n\t\t\t\t\t}\n\t\t\t\t\telse if ((rc != VQAERR_NOBUFFER) && (rc != VQAERR_SLEEPING)) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LDONE;\n\t\t\t\t\t\trc = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* Draw a frame */\n\t\t\t\tif ((config->DrawFlags & VQACFGF_NODRAW) == 0) {\n\t\t\t\t\tif ((rc = (*(vqabuf->Draw_Frame))(vqa)) == 0) {\n\t\t\t\t\t\tvqabuf->DrawnFrames++;\n\n\t\t\t\t\t\tif (User_Update(vqa)) {\n\t\t\t\t\t\t\tvqabuf->Flags |= (VQADATF_DDONE|VQADATF_LDONE);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if ((vqabuf->Flags & VQADATF_LDONE)\n\t\t\t\t\t\t\t&& (rc == VQAERR_NOBUFFER)) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_DDONE;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tvqabuf->Flags |= VQADATF_DDONE;\n\t\t\t\t\tdrawer->CurFrame->Flags = 0L;\n\t\t\t\t\tdrawer->CurFrame = drawer->CurFrame->Next;\n\t\t\t\t}\n\n\t\t\t\t/* Update Mono output */\n\t\t\t\t#if(VQAMONO_ON)\n\t\t\t\tif (config->OptionFlags & VQAOPTF_MONO) {\n\t\t\t\t\tVQA_UpdateMono((VQAHandleP *)vqa);\n\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\tif (mode == VQAMODE_WALK) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t#if(VQASTANDALONE)\n\t\t\t\telse {\n\n\t\t\t\t\t/* Do single-stepping check. */\n\t\t\t\t\tif (config->OptionFlags & VQAOPTF_STEP) {\n\t\t\t\t\t\twhile ((key = Check_Key()) == 0);\n\t\t\t\t\t\tGet_Key();\n\n\t\t\t\t\t\t/* Escape key still quits. */\n\t\t\t\t\t\tif (key == 27) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Check for ESC */\n\t\t\t\t\tif ((key = Check_Key()) != 0) {\n\t\t\t\t\t\tmode = VQAMODE_STOP;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n\t/* If the movie is finished or we are requested to stop then shutdown. */\n\tif (((vqabuf->Flags & (VQADATF_DDONE|VQADATF_LDONE))\n\t\t\t== (VQADATF_DDONE|VQADATF_LDONE)) || (mode == VQAMODE_STOP)) {\n\n\t\t/* Record the end time; must be done before stopping audio, since we're\n\t\t * getting the elapsed time from the audio DMA position.\n\t\t */\n\t\tvqabuf->EndTime = VQA_GetTime((VQAHandleP *)vqa);\n\n\t\t/* Stop audio, if it's playing. */\n\t\t#if(VQAAUDIO_ON)\n\t\tif (vqabuf->Audio.Flags & VQAAUDF_ISPLAYING) {\n\t\t\tVQA_StopAudio((VQAHandleP *)vqa);\n\t\t}\n\t\t#endif\n\n\t\t/* Movie is finished. */\n\t\trc = VQAERR_EOF;\n\t}\n\n\treturn (rc);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_GetInfo - Get VQA movie information.\n*\n* SYNOPSIS\n*     VQA_GetInfo(VQA, Info)\n*\n*     void VQA_GetInfo(VQAHandle *, VQAInfo *);\n*\n* FUNCTION\n*     Retrieve information about the opened movie.\n*\n* INPUTS\n*     VQA  - Pointer to VQAHandle of opened movie.\n*     Info - Pointer to VQAInfo structure to fill.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_GetInfo(VQAHandle *vqa, VQAInfo *info)\n{\n\tVQAHeader *header;\n\n\t/* Dereference header structure. */\n\theader = &((VQAHandleP *)vqa)->Header;\n\n\tinfo->NumFrames = header->Frames;\n\tinfo->ImageHeight = header->ImageHeight;\n\tinfo->ImageWidth = header->ImageWidth;\n\tinfo->ImageBuf = ((VQAHandleP *)vqa)->VQABuf->Drawer.ImageBuf;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_GetStats - Get VQA movie statistics.\n*\n* SYNOPSIS\n*     VQA_GetStats(VQA, Stats)\n*\n*     void VQA_GetStats(VQAHandle *, VQAStatistics *);\n*\n* FUNCTION\n*     Retrieve the statistics for the VQA movie.\n*\n* INPUTS\n*     VQA   - Handle of VQA movie to get statistics for.\n*     Stats - Pointer to VQAStatistics to fill.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_GetStats(VQAHandle *vqa, VQAStatistics *stats)\n{\n\tVQAData *vqabuf;\n\n\t/* Dereference VQAData structure from VQAHandle */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\n\tstats->MemUsed = vqabuf->MemUsed;\n\tstats->StartTime = vqabuf->StartTime;\n\tstats->EndTime = vqabuf->EndTime;\n\tstats->FramesLoaded = vqabuf->LoadedFrames;\n\tstats->FramesDrawn = vqabuf->DrawnFrames;\n\tstats->FramesSkipped = vqabuf->Drawer.NumSkipped;\n\tstats->MaxFrameSize = vqabuf->Loader.MaxFrameSize;\n\n\t#if(VQAAUDIO_ON)\n\tstats->SamplesPlayed = vqabuf->Audio.SamplesPlayed;\n\t#else\n\tstats->SamplesPlayed = 0;\n\t#endif\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Version - Get VQA library version number.\n*\n* SYNOPSIS\n*     Version = VQA_Version()\n*\n*     char *VQA_Version(void);\n*\n* FUNCTION\n*     Return the version of the VQA player library.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Version - Pointer to version number string.\n*\n****************************************************************************/\n\nchar *VQA_Version(void)\n{\n\treturn(VQA_VERSION);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_IDString - Get the VQA player library's ID string.\n*\n* SYNOPSIS\n*     IDString = VQA_IDString()\n*\n*     char *VQA_IDString(void);\n*\n* FUNCTION\n*     Return the ID string of this VQA player library.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     IDString - Pointer to ID string.\n*\n****************************************************************************/\n\nchar *VQA_IDString(void)\n{\n\treturn (VQA_IDSTRING);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     User_Update - Page flip routine called by the task interrupt.\n*\n* SYNOPSIS\n*     User_Update(VQA)\n*\n*     long User_Update(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Handle of VQA movie.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nlong User_Update(VQAHandle *vqa)\n{\n\tVQAData *vqabuf;\n\tlong    rc = 0;\n\n\t/* Dereference data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\n\t\t/* Invoke the page flip routine */\n\t\trc = (*(vqabuf->Page_Flip))(vqa);\n\n\t\t/* Update data for mono output */\n\t\tvqabuf->Flipper.LastFrameNum = vqabuf->Flipper.CurFrame->FrameNum;\n\n\t\t/* Mark the frame as loadable */\n\t\tvqabuf->Flipper.CurFrame->Flags = 0L;\n\t\tvqabuf->Flags &= (~VQADATF_UPDATE);\n\t}\n\n\treturn (rc);\n}\n\n"
  },
  {
    "path": "VQ/VQA32/TASM32.CFG",
    "content": "/t\n/m\n/w+\n/jJUMPS\n/ml\n/p\n/z\n/iC:\\PROJECTS\\INCLUDE\\VQM32\n/zi\n/dPHARLAP_TNT=1\n"
  },
  {
    "path": "VQ/VQA32/TLIB.CFG",
    "content": "/C /E\n"
  },
  {
    "path": "VQ/VQA32/TLINK32.CFG",
    "content": "/c\n/m\n/Gm\n-LC:\\PROJECTS\\LIB;C:\\DEV\\BC4\\LIB\n-v\n"
  },
  {
    "path": "VQ/VQA32/UNVQ.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAUNVQ_H\n#define VQAUNVQ_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQAPlay32 library. (32-Bit protected mode)\n*\n* FILE\n*     unvq.h\n*\n* DESCRIPTION\n*     VQ frame decompress definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Feburary 8, 1995\n*\n****************************************************************************/\n\n#ifdef PHARLAP_TNT\n#include <pltypes.h>\n#endif\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* unvqbuff.asm */\n#ifndef PHARLAP_TNT\nvoid cdecl UnVQ_2x2(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\nvoid cdecl UnVQ_2x3(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\nvoid cdecl UnVQ_4x2(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\nvoid cdecl UnVQ_4x4(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\nvoid cdecl UnVQ_4x2_Woofer(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\n/* unvqvesa.asm */\nvoid cdecl UnVQ_4x2_VESA320_32K(unsigned char *codebook,\n\t\tunsigned char *pointers, unsigned char *palette,\n\t\tunsigned long grains_per_win,unsigned long dummy1,unsigned long dummy2);\n\n#else /* PHARLAP_TNT */\n\nvoid cdecl UnVQ_2x2(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n\nvoid cdecl UnVQ_2x3(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n\nvoid cdecl UnVQ_4x2(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n\nvoid cdecl UnVQ_4x4(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n\n/* unvqvesa.asm */\nvoid cdecl UnVQ_4x2_VESA320_32K(unsigned char *codebook,\n\t\tunsigned char *pointers, FARPTR palette, unsigned long grains_per_win,\n\t\tunsigned long dummy1, unsigned long dummy2);\n\n#endif /* PHARLAP_TNT */\n\n/* unvqxmde.asm */\nvoid cdecl UnVQ_4x2_Xmode(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long dummy);\n\nvoid cdecl UnVQ_4x2_XmodeCB(unsigned char *cbdummy, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long dummy);\n\nvoid cdecl Upload_4x2CB(unsigned char *codebook, unsigned long numentries);\nvoid cdecl XlatePointers(unsigned char *pointers, unsigned long numpointers);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQAUNVQ_H */\n"
  },
  {
    "path": "VQ/VQA32/UNVQBUFF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PROJECT\n;*     VQAPlay library.\n;*\n;* FILE\n;*     UnVQBuff.asm\n;*\n;* DESCRIPTION\n;*     Buffered VQ decompress/draw routines.\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     Feburary 8, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     UnVQ_2x2 - Draw 2x2 block VQ frame to a buffer.\n;*     UnVQ_2x3 - Draw 2x3 block VQ frame to a buffer.\n;*     UnVQ_4x2 - Draw 4x2 block VQ frame to a buffer.\n;*     UnVQ_4x4 - Draw 4x4 block VQ frame to a buffer.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"vga.i\"\n\tINCLUDE\t\"vesavid.i\"\n\tINCLUDE\t\"vqaplay.i\"\n\tCODESEG\n\nSKIP_PTR\tEQU\t8000h\n\n\n\tIF\tVQABLOCK_2X2\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_2x2 - Draw 2x2 block VQ frame to a buffer.\n;*\n;* SYNOPSIS\n;*     UnVQ_2x2(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n;*\n;*     void UnVQ_2x2(unsigned char *, unsigned char *, unsigned char *,\n;*                        unsigned short, unsigned short, unsigned short);\n;*\n;* FUNCTION\n;*     This function draws an image into the specified buffer from the\n;*     pointers and codebook provided. This routine has been optimized for\n;*     a 320x200 image.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook used to draw image.\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to buffer to draw image into.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*     BufWidth - Width of destination buffer in pixels.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC UnVQ_2x2:NEAR\n\tPROC\tUnVQ_2x2 C NEAR USES ebx ecx edx esi edi\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tARG\tbuffer:NEAR PTR\n\tENDIF\n\n\tARG\tblocksperrow:DWORD\n\tARG\tnumrows:DWORD\n\tARG\tbufwidth:DWORD\n\n\tLOCAL\tdata_end:DWORD\n\tLOCAL\tcb_offset:DWORD\n\tLOCAL\tedi_startval:DWORD\n\tLOCAL\trowoffset:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tmov\teax,[codebook]\t\t;Adjust the codebook address so\n\tsub\teax,4\t\t; that the pointer offsets will\n\tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n\tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n\tshl\teax,1\t\t; row of blocks.\n\tmov\t[rowoffset],eax\n\n\tmov\tesi,[pointers]\n\tmov\teax,[numrows]\t\t;Compute the end address of the\n\tmul\t[blocksperrow]\t\t; pointer data.\n\tshl\teax,1\n\tadd\teax,esi\n\tmov\t[data_end],eax\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tmov\tedi,[buffer]\n\tENDIF\n\n\tmov\t[edi_startval],edi\n\n;----------------------------------------------------------------------------\n;\tDrawing loop\n;----------------------------------------------------------------------------\n\n??Start_row:\n\tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n??Not_finished_a_line:\n\tsub\tebx,ebx\n\tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n\tadd\tesi,2\t\t; then advance to the next one.\n\n\tor\tbx,bx\t\t;Is it a one color block?\n\tjs\tshort ??One_color\n\n;\tDraw multi-color block\n\n\tadd\tebx,[cb_offset]\t;Codeword address\n\tmov\teax,[ebx]\t\t;Read codeword\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],ax\t\t;Write 1st row to dest\n\tELSE\n\tmov\t[edi],ax\t\t;Write 1st row to dest\n\tENDIF\n\n\tshr\teax,16\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],ax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi+ebx],ax\t\t;Write 2nd row to dest\n\tENDIF\n\n\n\tadd\tedi,2\t\t;Next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n;\tDraw 1-color block\n\n??One_color:\n\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n\tjne\t??Draw_One_Color\n\n\tadd\tedi,2\t\t;Move to next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Next_row\n\n??Draw_One_Color:\n\tnot\tbx\t\t;NOT pointer value to get color\n\tmov\tbh,bl\t\t;Duplicate color through the\n\tmov\tax,bx\t\t; entire dword register.\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],ax\t\t;Write 1st row to dest\n\tmov\t[es:edi+ebx],ax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi],ax\t\t;Write 1st row to dest\n\tmov\t[edi+ebx],ax\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tedi,2\t\t;Next dest block positionw\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n??Next_row:\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n??End_of_data:\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\n\tENDP\tUnVQ_2x2\n\tENDIF\t;VQABLOCK_2X2\n\n\n\tIF\tVQABLOCK_2X3\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_2x3 - Draw 2x3 block VQ frame to a buffer.\n;*\n;* SYNOPSIS\n;*     UnVQ_2x3(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n;*\n;*     void UnVQ_2x3(unsigned char *, unsigned char *, unsigned char *,\n;*                        unsigned short, unsigned short, unsigned short);\n;*\n;* FUNCTION\n;*     This function draws an image into the specified buffer from the\n;*     pointers and codebook provided. This routine has been optimized for\n;*     a 320x200 image.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook used to draw image.\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to buffer to draw image into.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*     BufWidth - Width of destination buffer in pixels.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC UnVQ_2x3:NEAR\n\tPROC\tUnVQ_2x3 C NEAR USES ebx ecx edx esi edi\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tARG\tbuffer:NEAR PTR\n\tENDIF\n\n\tARG\tblocksperrow:DWORD\n\tARG\tnumrows:DWORD\n\tARG\tbufwidth:DWORD\n\n\tLOCAL\tdata_end:DWORD\n\tLOCAL\tcb_offset:DWORD\n\tLOCAL\tedi_startval:DWORD\n\tLOCAL\trowoffset:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tmov\teax,[codebook]\t\t;Adjust the codebook address so\n\tsub\teax,4\t\t; that the pointer offsets will\n\tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n\tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n\tshl\teax,1\t\t; row of blocks.\n\tadd\teax,[bufwidth]\n\tmov\t[rowoffset],eax\n\n\tmov\tesi,[pointers]\n\tmov\teax,[numrows]\t\t;Compute the end address of the\n\tmul\t[blocksperrow]\t\t; pointer data.\n\tshl\teax,1\n\tadd\teax,esi\n\tmov\t[data_end],eax\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tmov\tedi,[buffer]\n\tENDIF\n\n\tmov\t[edi_startval],edi\n\n;----------------------------------------------------------------------------\n;\tDrawing loop\n;----------------------------------------------------------------------------\n\n??Start_row:\n\tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n??Not_finished_a_line:\n\tsub\tebx,ebx\n\tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n\tadd\tesi,2\t\t; then advance to the next one.\n\n\tor\tbx,bx\t\t;Is it a one color block?\n\tjs\tshort ??One_color\n\n;\tDraw multi-color block\n\n\tadd\tebx,[cb_offset]\t;Codeword address\n\tmov\teax,[ebx]\t\t;Read 1st row of codeword\n\tmov\tdx,[ebx+4]\t\t;Read 2nd row of codeword\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],ax\t\t;Write 1st row to dest\n\tELSE\n\tmov\t[edi],ax\t\t;Write 1st row to dest\n\tENDIF\n\n\tshr\teax,16\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],ax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi+ebx],ax\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],dx\n\tELSE\n\tmov\t[edi+ebx],dx\n\tENDIF\n\n\tadd\tedi,2\t\t;Next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n;\tDraw 1-color block\n\n??One_color:\n\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n\tjne\t??Draw_One_Color\n\n\tadd\tedi,2\t\t;Move to next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Next_row\n\n??Draw_One_Color:\n\tnot\tbx\t\t;NOT pointer value to get color\n\tmov\tbh,bl\t\t;Duplicate color through the\n\tmov\tax,bx\t\t; entire dword register.\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],ax\t\t;Write 1st row to dest\n\tmov\t[es:edi+ebx],ax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi],ax\t\t;Write 1st row to dest\n\tmov\t[edi+ebx],ax\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],ax\t;Write 2rd row to dest\n\tELSE\n\tmov\t[edi+ebx],ax\t\t;Write 2rd row to dest\n\tENDIF\n\n\tadd\tedi,2\t\t;Next dest block positionw\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n??Next_row:\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n??End_of_data:\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\n\tENDP\tUnVQ_2x3\n\tENDIF\t;VQABLOCK_2X3\n\n\n\tIF\tVQABLOCK_4X2\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x2 - Draw 4x2 block VQ frame to a buffer.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x2(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n;*\n;*     void UnVQ_4x2(unsigned char *, unsigned char *, unsigned char *,\n;*                        long, long, long);\n;*\n;* FUNCTION\n;*     This function draws an image into the specified buffer from the\n;*     pointers and codebook provided. This routine has been optimized for\n;*     a 320x200 image.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook used to draw image.\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to buffer to draw image into.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*     BufWidth - Width of destination buffer in pixels.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n;;;\tGLOBAL\tC UnVQ_4x2:NEAR\n;;;\tPROC\tUnVQ_4x2 C NEAR USES ebx ecx edx esi edi\n;;;\n;;;\tARG\tcodebook:NEAR PTR\n;;;\tARG\tpointers:NEAR PTR\n;;;\n;;;\tIF\tPHARLAP_TNT\n;;;\tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n;;;\tELSE\n;;;\tARG\tbuffer:NEAR PTR\n;;;\tENDIF\n;;;\n;;;\tARG\tblocksperrow:DWORD\n;;;\tARG\tnumrows:DWORD\n;;;\tARG\tbufwidth:DWORD\n;;;\n;;;\tLOCAL\tdata_end:DWORD\n;;;\tLOCAL\tcb_offset:DWORD\n;;;\tLOCAL\tedi_startval:DWORD\n;;;\tLOCAL\trowoffset:DWORD\n;;;\n;;;;----------------------------------------------------------------------------\n;;;;\tInitialize\n;;;;----------------------------------------------------------------------------\n;;;\n;;;\tmov\teax,[codebook]\t\t;Adjust the codebook address so\n;;;\tsub\teax,4\t\t; that the pointer offsets will\n;;;\tmov\t[cb_offset],eax\t; point directly at the codeword.\n;;;\n;;;\tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n;;;\tshl\teax,1\t\t; row of blocks.\n;;;\tmov\t[rowoffset],eax\n;;;\n;;;\tmov\tesi,[pointers]\n;;;\tmov\teax,[numrows]\t\t;Compute the end address of the\n;;;\tmul\t[blocksperrow]\t\t; pointer data.\n;;;\tshl\teax,1\n;;;\tadd\teax,esi\n;;;\tmov\t[data_end],eax\n;;;\n;;;\tIF\tPHARLAP_TNT\n;;;\tpush\tes\n;;;\tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n;;;\tELSE\n;;;\tmov\tedi,[buffer]\n;;;\tENDIF\n;;;\n;;;\tmov\t[edi_startval],edi\n;;;\n;;;;----------------------------------------------------------------------------\n;;;;\tDrawing loop\n;;;;----------------------------------------------------------------------------\n;;;\n;;;??Start_row:\n;;;\tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n;;;\n;;;??Not_finished_a_line:\n;;;\tsub\tebx,ebx\n;;;\tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n;;;\tadd\tesi,2\t\t; then advance to the next one.\n;;;\n;;;\tor\tbx,bx\t\t;Is it a one color block?\n;;;\tjs\tshort ??One_color\n;;;\n;;;;\tDraw multi-color block\n;;;\n;;;\tadd\tebx,[cb_offset]\t;Codeword address\n;;;\tmov\teax,[ebx]\t\t;Read 1st row of codeword\n;;;\tmov\tedx,[ebx+4]\t\t;Read 2nd row of codeword\n;;;\tmov\tebx,[bufwidth]\n;;;\n;;;\tIF\tPHARLAP_TNT\n;;;\tmov\t[es:edi],eax\t\t;Write 1st row to dest\n;;;\tmov\t[es:edi+ebx],edx\t;Write 2nd row to dest\n;;;\tELSE\n;;;\tmov\t[edi],eax\t\t;Write 1st row to dest\n;;;\tmov\t[edi+ebx],edx\t\t;Write 2nd row to dest\n;;;\tENDIF\n;;;\n;;;\tadd\tedi,4\t\t;Next dest block position\n;;;\tdec\tecx\t\t;More blocks for this row?\n;;;\tjnz\tshort ??Not_finished_a_line\n;;;\n;;;;\tAdvance to the next destination row of blocks.\n;;;\n;;;\tmov\tedi,[edi_startval]\n;;;\tadd\tedi,[rowoffset]\n;;;\tmov\t[edi_startval],edi\n;;;\n;;;\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n;;;\tjnb\tshort ??End_of_data\t; pointers buffer?\n;;;\tjmp\t??Start_row\n;;;\n;;;;\tDraw 1-color block\n;;;\n;;;??One_color:\n;;;\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n;;;\tjne\t??Draw_One_Color\n;;;\n;;;\tadd\tedi,4\t\t;Move to next dest block position\n;;;\tdec\tecx\t\t;More blocks for this row?\n;;;\tjnz\tshort ??Not_finished_a_line\n;;;\tjmp\t??Next_row\n;;;\n;;;??Draw_One_Color:\n;;;\tnot\tbx\t\t;NOT pointer value to get color\n;;;\tmov\tbh,bl\t\t;Duplicate color through the\n;;;\tmov\tax,bx\t\t; entire dword register.\n;;;\trol\teax,16\n;;;\tmov\tax,bx\n;;;\tmov\tebx,[bufwidth]\n;;;\n;;;\tIF\tPHARLAP_TNT\n;;;\tmov\t[es:edi],eax\t\t;Write 1st row to dest\n;;;\tmov\t[es:edi+ebx],eax\t;Write 2nd row to dest\n;;;\tELSE\n;;;\tmov\t[edi],eax\t\t;Write 1st row to dest\n;;;\tmov\t[edi+ebx],eax\t\t;Write 2nd row to dest\n;;;\tENDIF\n;;;\n;;;\tadd\tedi,4\t\t;Next dest block positionw\n;;;\tdec\tecx\t\t;More blocks for this row?\n;;;\tjnz\tshort ??Not_finished_a_line\n;;;\n;;;;\tAdvance to the next destination row of blocks.\n;;;\n;;;??Next_row:\n;;;\tmov\tedi,[edi_startval]\n;;;\tadd\tedi,[rowoffset]\n;;;\tmov\t[edi_startval],edi\n;;;\n;;;\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n;;;\tjnb\tshort ??End_of_data\t; pointers buffer?\n;;;\tjmp\t??Start_row\n;;;\n;;;??End_of_data:\n;;;\tIF\tPHARLAP_TNT\n;;;\tpop\tes\n;;;\tENDIF\n;;;\n;;;\tret\n;;;\n;;;\tENDP\tUnVQ_4x2\n;;;\tENDIF\t;VQABLOCK_4X2\n\n\tGLOBAL\tC UnVQ_4x2:NEAR\n\tPROC\tUnVQ_4x2 C NEAR USES ebx ecx edx esi edi\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\tARG\tbuffer:NEAR PTR\n\tARG\tblocksperrow:DWORD\n\tARG\tnumrows:DWORD\n\tARG\tbufwidth:DWORD\n\n\tLOCAL\tdata_end:DWORD\n\tLOCAL\tcb_offset:DWORD\n\tLOCAL\tedi_startval:DWORD\n\tLOCAL\trowoffset:DWORD\n\tLOCAL\tentries:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tmov\teax,[codebook]\t\t;Adjust the codebook address so\n;\tsub\teax,4\t\t; that the pointer offsets will\n\tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n\tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n\tshl\teax,1\t\t; row of blocks.\n\tmov\t[rowoffset],eax\n\n\tmov\tesi,[pointers]\n\tmov\teax,[numrows]\t\t;Compute the end address of the\n\tmul\t[blocksperrow]\t\t; pointer data.\n\tmov\t[entries],eax\n\tadd\teax,esi\n\tmov\t[data_end],eax\n\t\n\tmov\tedi,[buffer]\n\tmov\t[edi_startval],edi\n\n;----------------------------------------------------------------------------\n;\tDrawing loop\n;----------------------------------------------------------------------------\n\n??Start_row:\n\tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n??Not_finished_a_line:\n\tmov\teax,[entries]\n\txor\tebx,ebx\n\tmov\tbl,[esi]\n\tmov\tbh,[esi + eax]\t;Get the codebook pointer value\n\tinc\tesi\t\t; then advance to the next one.\n\n\tcmp\tbh,00Fh\t\t;Is it a one color block?\n\tje\tshort ??One_color\n\n;\tDraw multi-color block\n\n\tshl\tebx,3\n\tadd\tebx,[cb_offset]\t;Codeword address\n\tmov\teax,[ebx]\t\t;Read 1st row of codeword\n\tmov\tedx,[ebx+4]\t\t;Read 2nd row of codeword\n\tmov\tebx,[bufwidth]\n\tmov\t[edi],eax\t\t;Write 1st row to dest\n\tmov\t[edi+ebx],edx\t\t;Write 2nd row to dest\n\n\tadd\tedi,4\t\t;Next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n;\tDraw 1-color block\n\n??One_color:\n;\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n;\tjne\t??Draw_One_Color\n;\n;\tadd\tedi,4\t\t;Move to next dest block position\n;\tdec\tecx\t\t;More blocks for this row?\n;\tjnz\tshort ??Not_finished_a_line\n;\tjmp\t??Next_row\n\n??Draw_One_Color:\n;\tnot\tbx\t\t;NOT pointer value to get color\n\tmov\tbh,bl\t\t;Duplicate color through the\n\tmov\tax,bx\t\t; entire dword register.\n\trol\teax,16\n\tmov\tax,bx\n\tmov\tebx,[bufwidth]\n\tmov\t[edi],eax\t\t;Write 1st row to dest\n\tmov\t[edi+ebx],eax\t\t;Write 2nd row to dest\n\n\tadd\tedi,4\t\t;Next dest block positionw\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n??Next_row:\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n??End_of_data:\n\tret\n\n\tENDP\tUnVQ_4x2\n\tENDIF\t;VQABLOCK_4X2\n\n\n\tIF\tVQABLOCK_4X4\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x4 - Draw 4x4 block VQ frame to a buffer.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x4(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n;*\n;*     void UnVQ_4x4(unsigned char *, unsigned char *, unsigned char *,\n;*                        unsigned short, unsigned short, unsigned short);\n;*\n;* FUNCTION\n;*     This function draws an image into the specified buffer from the\n;*     pointers and codebook provided. This routine has been optimized for\n;*     a 320x200 image.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook used to draw image.\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to buffer to draw image into.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*     BufWidth - Width of destination buffer in pixels.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC UnVQ_4x4:NEAR\n\tPROC\tUnVQ_4x4 C NEAR USES ebx ecx edx esi edi\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tARG\tbuffer:NEAR PTR\n\tENDIF\n\n\tARG\tblocksperrow:DWORD\n\tARG\tnumrows:DWORD\n\tARG\tbufwidth:DWORD\n\n\tLOCAL\tdata_end:DWORD\n\tLOCAL\tcb_offset:DWORD\n\tLOCAL\tedi_startval:DWORD\n\tLOCAL\trowoffset:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tmov\teax,[codebook]\t\t;Adjust the codebook address so\n\tsub\teax,4\t\t; that the pointer offsets will\n\tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n\tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n\tshl\teax,2\t\t; row of blocks\n\tmov\t[rowoffset],eax \n\n\tmov\tesi,[pointers]\n\tmov\teax,[numrows]\t\t;Compute the end address of the\n\tmul\t[blocksperrow]\t\t; pointer data.\n\tshl\teax,1\n\tadd\teax,esi\n\tmov\t[data_end],eax\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tmov\tedi,[buffer]\n\tENDIF\n\n\tmov\t[edi_startval],edi\n\n;----------------------------------------------------------------------------\n;\tDrawing loop\n;----------------------------------------------------------------------------\n\n??Start_row:\n\tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n??Not_finished_a_line:\n\tsub\tebx,ebx\n\tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n\tadd\tesi,2\t\t; then advance to the next one.\n\n\tor\tbx,bx\t\t;Is it a one color block?\n\tjs\tshort ??One_color\n\n;\tDraw multi-color block\n\n\tadd\tebx,[cb_offset]\t;Codeword address\n\tmov\teax,[ebx]\t\t;Read 1st row of codeword\n\tmov\tedx,[ebx+4]\t\t;Read 2nd row of codeword\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],eax\t\t;Write 1st row to dest\n\tELSE\n\tmov\t[edi],eax\t\t;Write 1st row to dest\n\tENDIF\n\n\tmov\teax,ebx\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],edx\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi+ebx],edx\t\t;Write 2nd row to dest\n\tENDIF\n\n\tmov\tebx,eax\n\tmov\teax,[ebx+8]\n\tmov\tedx,[ebx+12]\n\tmov\tebx,[bufwidth]\n\tshl\tebx,1\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],eax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi+ebx],eax\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],edx\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi+ebx],edx\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tedi,4\t\t;Next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n;\tDraw 1-color block\n\n??One_color:\n\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n\tjne\t??Draw_One_Color\n\n\tadd\tedi,4\t\t;Move to next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Next_row\n\n??Draw_One_Color:\n\tnot\tbx\t\t;NOT pointer value to get color\n\tmov\tbh,bl\t\t;Duplicate color through the\n\tmov\tax,bx\t\t; entire dword register.\n\trol\teax,16\n\tmov\tax,bx\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],eax\t\t;Write 1st row to dest\n\tmov\t[es:edi+ebx],eax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi],eax\t\t;Write 1st row to dest\n\tmov\t[edi+ebx],eax\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],eax\t;Write 3rd row to dest\n\tELSE\n\tmov\t[edi+ebx],eax\t\t;Write 3rd row to dest\n\tENDIF\n\n\tadd\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],eax\t;Write 4th row to dest\n\tELSE\n\tmov\t[edi+ebx],eax\t\t;Write 4th row to dest\n\tENDIF\n\n\tadd\tedi,4\t\t;Next dest block positionw\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\t??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n??Next_row:\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n??End_of_data:\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\n\tENDP\tUnVQ_4x4\n\tENDIF\t;VQABLOCK_4X4\n\n\n\tIF\tVQABLOCK_WOOFER\n\tIF\tVQABLOCK_4X2\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x2_Woofer - Draw 4x2 block VQ frame to a buffer.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x2_Woofer(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n;*\n;*     void UnVQ_4x2_Woofer(unsigned char *, unsigned char *,\n;*                          unsigned char *, long, long, long);\n;*\n;* FUNCTION\n;*     This function draws an image into the specified buffer from the\n;*     pointers and codebook provided. This routine has been optimized for\n;*     a 320x200 image.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook used to draw image.\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to buffer to draw image into.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*     BufWidth - Width of destination buffer in pixels.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC UnVQ_4x2_Woofer:NEAR\n\tPROC\tUnVQ_4x2_Woofer C NEAR USES ebx ecx edx esi edi\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tARG\tbuffer:NEAR PTR\n\tENDIF\n\n\tARG\tblocksperrow:DWORD\n\tARG\tnumrows:DWORD\n\tARG\tbufwidth:DWORD\n\n\tLOCAL\tdata_end:DWORD\n\tLOCAL\tcb_offset:DWORD\n\tLOCAL\tedi_startval:DWORD\n\tLOCAL\trowoffset:DWORD\n\tLOCAL\tentries:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tmov\teax,[codebook]\t\t;Adjust the codebook address so\n;\tsub\teax,4\t\t; that the pointer offsets will\n\tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n\tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n\tshl\teax,1\t\t; row of blocks.\n\tmov\t[rowoffset],eax\n\n\tmov\tesi,[pointers]\n\tmov\teax,[numrows]\t\t;Compute the end address of the\n\tmul\t[blocksperrow]\t\t; pointer data.\n\tmov\t[entries],eax\n;\tshl\teax,1\n\tadd\teax,esi\n\tmov\t[data_end],eax\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tmov\tedi,[buffer]\n\tENDIF\n\n\tmov\t[edi_startval],edi\n\n;----------------------------------------------------------------------------\n;\tDrawing loop\n;----------------------------------------------------------------------------\n\n??Start_row:\n\tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n??Not_finished_a_line:\n\tmov\teax,[entries]\n\txor\tebx,ebx\n;\tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n;\tadd\tesi,2\t\t; then advance to the next one.\n\tmov\tbl,[esi]\n\tmov\tbh,[esi + eax]\n\tinc\tesi\n\n;\tor\tbx,bx\t\t;Is it a one color block?\n;\tjs\tshort ??One_color\n\n\tcmp\tbh,00Fh\n\tje\tshort ??One_color\n\n;\tDraw multi-color block\n\n\tshl\tebx,3\n\n\tadd\tebx,[cb_offset]\t;Codeword address\n\tmov\teax,[ebx]\t\t;Read 1st row of codeword\n\tmov\tedx,[ebx+4]\t\t;Read 2nd row of codeword\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],al\t\t;Write 1st row to dest\n\tshr\teax,16\n\tmov\t[es:edi+2],al\n\tmov\t[es:edi+ebx+1],dh\t\t;Write 1st row to dest\n\tshr\tedx,16\n\tmov\t[es:edi+ebx+3],dh\n\tELSE\n\tmov\t[edi],al\t\t;Write 1st row to dest\n\tshr\teax,16\n\tmov\t[edi+2],al\n\tmov\t[edi+ebx+1],dh\t\t;Write 1st row to dest\n\tshr\tedx,16\n\tmov\t[edi+ebx+3],dh\n\tENDIF\n\n\tadd\tedi,4\t\t;Next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n;\tDraw 1-color block\n\n??One_color:\n;\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n;\tjne\t??Draw_One_Color\n\n;\tadd\tedi,4\t\t;Move to next dest block position\n;\tdec\tecx\t\t;More blocks for this row?\n;\tjnz\tshort ??Not_finished_a_line\n;\tjmp\t??Next_row\n\n??Draw_One_Color:\n;\tnot\tbx\t\t;NOT pointer value to get color\n\tmov\tal,bl\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],al\n\tmov\t[es:edi+2],al\n\tmov\t[es:edi+ebx+1],al\t;Write 2nd row to dest\n\tmov\t[es:edi+ebx+3],al\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi],al\n\tmov\t[edi+2],al\n\tmov\t[edi+ebx+1],al\t\t;Write 2nd row to dest\n\tmov\t[edi+ebx+3],al\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tedi,4\t\t;Next dest block positionw\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\t??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n??Next_row:\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n??End_of_data:\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\n\tENDP\tUnVQ_4x2_Woofer\n\tENDIF\t;VQABLOCK_4X2\n\tENDIF\t;VQABLOCK_WOOFER\n\n\tEND\n\n"
  },
  {
    "path": "VQ/VQA32/UNVQVESA.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PROJECT\n;*     VQAPlay32 library.\n;*\n;* FILE\n;*     unvqvesa.asm\n;*\n;* DESCRIPTION\n;*     VESA VQ decompress/draw routines. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     UnVQ_4x2_VESA320_32K - Draw 4x2 VQ frame to VESA320 32k color.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"vga.i\"\n\tINCLUDE\t\"vesavid.i\"\n\tINCLUDE\t\"vqaplay.i\"\n\tCODESEG\n\nSKIP_PTR\tEQU\t8000h\n\n\tIF\tVQAVESA_ON\n\tIF\tVQABLOCK_4X2\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x2_VESA320_32K - Draw 4x2 VQ frame to VESA320 32k color.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x2_VESA320_32K(Codebook, Pointers, Palette, GrainPerWin)\n;*\n;*     void UnVQ_4x2_VESA320_32K(char *, char *, char *, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Codebook    - Pointer to codebook.\n;*     Pointers    - Pointer to vector pointer data to unvq.\n;*     Palette     - Pointer to 15-bit palette.\n;*     GrainPerWin - Granularity units for 64k window.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n \n;---------------------------------------------------------------------------\n; SET_2_PIXELS:\n; - Loads 2 bytes from codebook, expands them into words in eax\n; - Sets them on the screen\n;   cb_index: offset into codebook of start of 2 bytes to load\n;   di_index: offset from current di to draw 2 pixels\n;   BX: offset into codebook of this block\n; Uses: EAX, DX, SI!\n;---------------------------------------------------------------------------\n\n\tMACRO\tSET_2_PIXELS cb_index,edi_index\n\txor\tedx,edx\n\tmov\tdl,[BYTE PTR ebx+1+cb_index]\n\tshl\tedx,1\n\tadd\tedx,[palette]\n\tmov\tesi,edx\n\tmov\tax,[WORD PTR esi]\n\tshl\teax,16\n\txor\tedx,edx\n\tmov\tdl,[BYTE PTR ebx+cb_index]\n\tshl\tedx,1\n\tadd\tedx,[palette]\n\tmov\tesi,edx\n\tmov\tax,[WORD PTR esi]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[DWORD PTR es:edi+edi_index],eax\n\tELSE\n\tmov\t[DWORD PTR edi+edi_index],eax\n\tENDIF\n\tENDM\n\n;---------------------------------------------------------------------------\n; DRAW_BLOCK_ROWS macro:\n; Draws 'numrows' rows of 'blocksperrow' blocks each\n;---------------------------------------------------------------------------\n\n\tMACRO\tDRAW_BLOCK_ROWS numrows,blocksperrow\n\tLOCAL\t??Start_row\n\tLOCAL\t??Not_finished_a_line\n\tLOCAL\t??One_color\n\tLOCAL\t??Draw_One_Color\n\tLOCAL\t??Next_row\n\tLOCAL\t??Done\n\n\tmov\t[rowcount],numrows\t\t; initialize row counter\n\n\t;---------------------------------------- Start a new row:\n??Start_row:\n\tmov\tecx,blocksperrow\t\t\t; # blocks to fill a line\n\n\t;---------------------------------------- Start a new block:\n??Not_finished_a_line:\n\t;........................................ Get next pointer word:\n\txor\tebx,ebx\n\tmov\tbx,[WORD PTR esi]\t\t; BX = pointer word\n\tadd\tesi,2\n\n\t;........................................ Check for a 1-color block:\n\tor\tbx,bx\t\t\t\t; see if high bit is set\n\tjs\t??One_color\n\n\t;---------------------------------------- Multi-color block:\n\tmov\t[esi_save],esi\t\t\t; save current SI\n\tadd\tebx,[cb_offset]\t\t\t; get codebook offset\n\tSET_2_PIXELS 0,0\n\tSET_2_PIXELS 2,4\n\tSET_2_PIXELS 4,640\n\tSET_2_PIXELS 6,644\n\tadd\tedi,8\t\t\t\t; next block position\n\tmov\tesi,[esi_save]\t\t\t; get current SI\n\n\t;........................................ Check block count\n\tdec\tecx\t\t\t\t; decrement block count\n\tjnz\t??Not_finished_a_line\n\n\t;---------------------------------------- Next block row:\n\tadd\tedi,640\n\t;\n\t;............ see if we're past the end of the ptr data ............\n\t;\n\tdec\t[rowcount]\n\tjnz\t??Start_row\n\tjmp\t??Done\n\n\t;---------------------------------------- 1-color block:\n??One_color:\n\t;................... skip ptr value SKIP_PTR .......................\n\tcmp\tbx,SKIP_PTR\n\tjne\t??Draw_One_Color\n\tadd\tedi,8\n\tdec\tecx\n\tjnz\t??Not_finished_a_line\n\tjmp\t??Next_row\n??Draw_One_Color:\n\tnot\tbx\t\t\t\t; get palette index\n\tshl\tbx,1\t\t\t\t; convert to WORD offset\n\tadd\tebx,[palette]\n\tmov\tax,[WORD PTR ebx]\t\t; get 15-bit palette value\n\tmov\tdx,ax\t\t\t\t; copy it into dx\n\tshl\teax,16\n\tmov\tax,dx\t\t\t\t; eax = 2 pixels, same color\n\tmov\tedx,eax\t\t\t\t; edx = 2 pixels, same color\n\n\tIF\tPHARLAP_TNT\n\tmov\t[DWORD PTR es:edi],eax\t\t; set 2 pixels\n\tmov\t[DWORD PTR es:edi+4],edx\t\t; set 2 pixels\n\tmov\t[DWORD PTR es:edi+640],eax\t; set 2 pixels\n\tmov\t[DWORD PTR es:edi+644],edx\t; set 2 pixels\n\tELSE\n\tmov\t[DWORD PTR edi],eax\t\t; set 2 pixels\n\tmov\t[DWORD PTR edi+4],edx\t\t; set 2 pixels\n\tmov\t[DWORD PTR edi+640],eax\t; set 2 pixels\n\tmov\t[DWORD PTR edi+644],edx\t; set 2 pixels\n\tENDIF\n\n\tadd\tedi,8\t\t\t\t; next block position\n\n\t;........................................ Check block count\n\tdec\tecx\t\t\t\t; decrement block count\n\tjnz\t??Not_finished_a_line\n\n\t;---------------------------------------- Next block row:\n??Next_row:\n\tadd\tedi,640\n\t;\n\t;............ see if we're past the end of the ptr data ............\n\t;\n\tdec\t[rowcount]\n\tjnz\t??Start_row\n??Done:\n\tENDM\n\n;---------------------------------------------------------------------------\n; DRAW_BLOCK_PART_ROW macro:\n; Draws top or bottom half of blocks on a row\n; 'numblocks' = # blocks to draw\n; 'cb_add' = amt to add to codebook (0=top half, 4=bottom half)\n;---------------------------------------------------------------------------\n\n\tMACRO\tDRAW_BLOCK_PART_ROW numblocks,cb_add\n\tLOCAL\t??Not_finished_a_line\n\tLOCAL\t??One_color\n\tLOCAL\t??Draw_One_Color\n\tLOCAL\t??Done\n\n\tmov\tecx,numblocks\n\n\t;---------------------------------------- Start a new block:\n??Not_finished_a_line:\n\t;........................................ Get next pointer word:\n\txor\tebx,ebx\n\tmov\tbx,[WORD PTR esi]\t\t; BX = pointer word\n\tadd\tesi,2\n\n\t;........................................ Check for a 1-color block:\n\tor\tbx,bx\t\t\t\t; see if high bit is set\n\tjs\tshort ??One_color\n\n\t;---------------------------------------- Multi-color block:\n\tmov\t[esi_save],esi\t\t\t; save current SI\n\tadd\tebx,[cb_offset]\t\t\t; get codebook offset\n\tSET_2_PIXELS cb_add,0\n\tSET_2_PIXELS cb_add+2,4\n\tadd\tedi,8\t\t\t\t; next block position\n\tmov\tesi,[esi_save]\t\t\t; get current SI\n\n\t;........................................ Check block count\n\tdec\tecx\t\t\t\t; decrement block count\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Done\n\n\t;---------------------------------------- 1-color block:\n??One_color:\n\t;................... skip ptr value SKIP_PTR .......................\n\tcmp\tbx,SKIP_PTR\n\tjne\t??Draw_One_Color\n\tadd\tedi,8\n\tdec\tecx\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Done\n??Draw_One_Color:\n\tnot\tbx\t\t\t\t; get palette index\n\tshl\tbx,1\t\t\t\t; convert to WORD offset\n\tadd\tebx,[palette]\n\tmov\tax,[WORD PTR ebx]\t\t; get 15-bit palette value\n\tmov\tdx,ax\t\t\t\t; copy it into dx\n\tshl\teax,16\n\tmov\tax,dx\t\t\t\t; eax = 2 pixels, same color\n\tmov\tedx,eax\t\t\t\t; edx = 2 pixels, same color\n\n\tIF\tPHARLAP_TNT\n\tmov\t[DWORD PTR es:edi],eax\t\t; set 2 pixels\n\tmov\t[DWORD PTR es:edi+4],edx\t\t; set 2 pixels\n\tELSE\n\tmov\t[DWORD PTR edi],eax\t\t; set 2 pixels\n\tmov\t[DWORD PTR edi+4],edx\t\t; set 2 pixels\n\tENDIF\n\n\tadd\tedi,8\t\t\t\t; next block position\n\n\t;........................................ Check block count\n\tdec\tecx\t\t\t\t; decrement block count\n\tjnz\t??Not_finished_a_line\n??Done:\n\tENDM\n\n;===========================================================================\n; The actual procedure:\n;===========================================================================\n\n\tGLOBAL\tC UnVQ_4x2_VESA320_32K:NEAR\n\tPROC\tUnVQ_4x2_VESA320_32K C NEAR\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tARG\tpal:QWORD\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tARG\tpalette:NEAR PTR\n\tENDIF\n\n\tARG\tgrains_per_win:DWORD\n\tARG\tdummy1:DWORD\n\tARG\tdummy2:DWORD\n\n\tLOCAL\trowcount:DWORD\t\t; # rows drawn\n\tLOCAL\tesi_save:DWORD\n\tLOCAL\tcb_offset:DWORD\n\n\tIF\tPHARLAP_TNT\n\tLOCAL\tpalette:NEAR PTR\n\tENDIF\n\n\t;-------------------------------------------------------------------\n\t; Save registers\n\t;-------------------------------------------------------------------\n\tpushad\n\n\t;-------------------------------------------------------------------\n\t; Set GS:[cb_offset] to codebook\n\t;-------------------------------------------------------------------\n\tmov\teax,[codebook]\n\tsub\teax,4\n\tmov\t[cb_offset],eax\n\tmov\tesi,[pointers]\n\n\t;-------------------------------------------------------------------\n\t; Set ES:DI to screen\n\t;-------------------------------------------------------------------\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tles\tedi,[FWORD pal]\n\tmov\t[palette],edi\n\tmov\teax,01Ch\n\tmov\tes,ax\n\tmov\tedi,0\n\tELSE\n\tmov\tedi,0A0000h\n\tENDIF\n\n\t;-------------------------------------------------------------------\n\t; Do Bank 0:\n\t; - 102 full scanlines (51 rows of blocks)\n\t; - 128 pixels of the top half of blocks (32 top-half blocks)\n\t;-------------------------------------------------------------------\n\tSET_WINDOW 0\n\tDRAW_BLOCK_ROWS 51,80\n\tDRAW_BLOCK_PART_ROW 32,0\t; do top half\n\n\t;-------------------------------------------------------------------\n\t; Do Bank 1:\n\t; - 128 pixels of the bottom half of the previous 32 blocks\n\t; - 192 pixels of full blocks (1 row of 48 blocks)\n\t; - 96 full scanlines (48 rows of blocks)\n\t;-------------------------------------------------------------------\n\tSET_WINDOW [grains_per_win]\n\tsub\tesi,64\t\t\t; subtract word size of last 32 blks\n\tmov\tedi,384\n\tDRAW_BLOCK_PART_ROW 32,4\t; do bottom half\n\tmov\tedi,0\n\tDRAW_BLOCK_ROWS 1,48\t\t; draw one row of 48 full blocks\n\tDRAW_BLOCK_ROWS 48,80\t\t; draw 48 full block rows\n\n??End_of_data:\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tpopad\n\tret\n\n\tENDP\tUnVQ_4x2_VESA320_32K\n\n\tENDIF\t;VQABLOCK_4X2\n\tENDIF\t;VQAVESA_ON\n\n\tEND\n\n"
  },
  {
    "path": "VQ/VQA32/UNVQXMDE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PROJECT\n;*     VQAPlay library.\n;*\n;* FILE\n;*     UnVQxmde.asm\n;*\n;* DESCRIPTION\n;*     XMode VQ decompress/draw routines.\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     May 18, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     UnVQ_4x2_Xmode       - Draw 4x2 VQ frame directly to Xmode.\n;*     UnVQ_4x2_XmodeCB     - Draw 4x2 VQ frame to Xmode from VRAM codebook.\n;*     Upload_4x2CB         - Upload 4x2 codebook into XMode VRAM.\n;*     UnVQ_4x2_VESA320_32K - Draw 4x2 VQ frame to VESA320 32k color.\n;*     XlatePointers        - Translate pointer to optimal XMode format.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"vga.i\"\n\tINCLUDE\t\"vesavid.i\"\n\tINCLUDE\t\"vqaplay.i\"\n\tCODESEG\n\n\tIF\tVQAXMODE_ON\n\nSKIP_PTR\tEQU\t8000h\nCBOOK_SEG\tEQU\t(0B0000h - 270h)\n\n\n\tIF\tVQABLOCK_4X2\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x2_Xmode - Draw 4x2 VQ frame directly to Xmode.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x2_Xmode(Codebook, Pointers, Buffer, BPR, Rows, Dummy)\n;*\n;*     void UnVQ_4x2_Xmode(unsigned char *, unsigned char *, unsigned char *,\n;*                         unsigned short, unsigned short, unsigned short);\n;*\n;* FUNCTION\n;*     This function draws an image to the Xmode display from the pointers\n;*     and codebook provided. This routine has been optimized for a 320x200\n;*     image.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook used to draw image.\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to buffer to draw image into.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*     Dummy    - Not used (prototype placeholder)\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC UnVQ_4x2_Xmode:NEAR\n\tPROC\tUnVQ_4x2_Xmode C NEAR USES\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tARG\tbuffer:NEAR PTR\n\tENDIF\n\n\tARG\tblocksperrow:DWORD\n\tARG\tnumrows:DWORD\n\tARG\tbufwidth:DWORD\n\n\tLOCAL\tdata_end:DWORD\n\tLOCAL\tcb_offset:DWORD\n\tLOCAL\tedi_startval:DWORD\n\tLOCAL\trowoffset:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tmov\teax,[codebook]\t\t;Adjust the codebook address so\n\tsub\teax,4\t\t; that the pointer offsets will\n\tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n\tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n\tshl\teax,1\t\t; row of blocks.\n\tmov\t[rowoffset],eax\n\n\tmov\tesi,[pointers]\n\tmov\teax,[numrows]\t\t;Compute the end address of the\n\tmul\t[blocksperrow]\t\t; pointer data.\n\tshl\teax,1\n\tadd\teax,esi\n\tmov\t[data_end],eax\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tmov\tedi,[buffer]\n\tENDIF\n\n\tmov\t[edi_startval],edi\n\n;----------------------------------------------------------------------------\n;\tDrawing loop\n;----------------------------------------------------------------------------\n\n\tSET_PLANE\tXPLANE_1\n\n??Start_row:\n\tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n??Not_finished_a_line1:\n\tsub\tebx,ebx\n\tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n\tadd\tesi,2\t\t; then advance to the next one.\n\n\tor\tbx,bx\t\t;Is it a one color block?\n\tjs\tshort ??One_color1\n\n;\tDraw multi-color block\n\n\tadd\tebx,[cb_offset]\t;Codeword address\n\tmov\teax,[ebx]\t\t;Read 1st row of codeword\n\tmov\tedx,[ebx+4]\t\t;Read 2nd row of codeword\n;\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],eax\t\t;Write 1st row to dest\n\tmov\t[es:edi+ebx],edx\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi],al\t\t;Write 1st row to dest\n\tmov\t[edi+80],dl\t\t;Write 2nd row to dest\n\tENDIF\n\n;\tadd\tedi,4\t\t;Next dest block position\n\tinc\tedi\t\t;Next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n;\tDraw 1-color block\n\n??One_color1:\n\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n\tjne\t??Draw_One_Color\n\n\tadd\tedi,4\t\t;Move to next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Next_row\n\n??Draw_One_Color:\n\tnot\tbx\t\t;NOT pointer value to get color\n\tmov\tbh,bl\t\t;Duplicate color through the\n\tmov\tax,bx\t\t; entire dword register.\n\trol\teax,16\n\tmov\tax,bx\n;\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],eax\t\t;Write 1st row to dest\n\tmov\t[es:edi+ebx],eax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi],al\t\t;Write 1st row to dest\n\tmov\t[edi+80],al\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tedi,4\t\t;Next dest block positionw\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n??Next_row:\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n??End_of_data:\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\tENDP\tUnVQ_4x2_Xmode\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x2_XmodeCB - Draw 4x2 VQ frame to Xmode from VRAM codebook.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x2_XmodeCB(Dummy, Pointers, Buffer, BPR, Rows)\n;* \n;*     void UnVQ_4x2_XmodeCB(unsigned char *, unsigned char *,\n;*                           unsigned char *, unsigned short,\n;*                           unsigned short);\n;*\n;* FUNCTION\n;*     This routine copies codebook entries from video RAM to video RAM.\n;*     The procedure for Write Mode 1 is:\n;*\n;*       - Perform a CPU read at the address of the 4-byte codebook entry;\n;*         this will load each byte at that address from all 4 bitplanes\n;*         into the VGA's internal latches.\n;*\n;*       - Perform a CPU write at the destination address, with the BitMask\n;*         register set to 0 (this tells the VGA hardware to only use the\n;*         data stored in the latches to write with), and the Map Mask\n;*         register set to 0Fh (all bitplanes enabled).\n;*\n;*     Optimized for 320x200.\n;*     The codebook must have been downloaded to video RAM before this\n;*     routine is called. This routine assumes the multicolor block pointers\n;*     have been pre-divided by 4, and have a total of 512 added to them, so\n;*     the pointer is an exact offset into the codebook.\n;*\n;* INPUTS\n;*     Dummy    - Not used (prototype placeholder)\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to Xmode buffer.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC UnVQ_4x2_XmodeCB:NEAR\n\tPROC\tUnVQ_4x2_XmodeCB C NEAR USES\n\n\tARG\tcbdummy:FAR PTR\n\tARG\tpointers:FAR PTR\n\tARG\tbuffer:FAR PTR\n\tARG\tblocksperrow:WORD\n\tARG\tnumrows:WORD\n\n;\t;-------------------------------------------------------------------\n;\t; Local variables:\n;\t;-------------------------------------------------------------------\n;\tLOCAL\tdi_startval:WORD\t; init value for DI, for new row\n;\n;\t;===================================================================\n;\t; Initialization\n;\t;===================================================================\n;\t;-------------------------------------------------------------------\n;\t; Save our registers\n;\t;-------------------------------------------------------------------\n;\tpush\tds\n;\tpush\tes\n;\tpush\tfs\n;\tpushad\n;\n;\t;-------------------------------------------------------------------\n;\t; Save codebook's segment in DS\n;\t;-------------------------------------------------------------------\n;\tmov\tax,CBOOK_SEG\n;\tmov\tds,ax\n;\n;\t;-------------------------------------------------------------------\n;\t; Load pointers into FS:BX\n;\t;-------------------------------------------------------------------\n;\tles\tdi,[pointers]\n;\tmov\tax,es\n;\tmov\tfs,ax\n;\tmov\tbx,di\n;\n;\t;-------------------------------------------------------------------\n;\t; Load screen address into ES:DI\n;\t;-------------------------------------------------------------------\n;\tles\tdi, [buffer]   \t\t\t; point ES:DI to dest\n;\tmov\t[di_startval],di\t\t; store it\n;\n;\t;-------------------------------------------------------------------\n;\t; Initialize VGA registers:\n;\t; - Enable all bitplanes for writing\n;\t; - Set the BitMask register to 0, so only the data from the\n;\t;   VGA latches is written into the bitplanes\n;\t;-------------------------------------------------------------------\n;\tSET_PLANE 0fh\t\t\t\t; enable all planes for write\n;\tSET_WRITEMODE 1\n;\n;\t;===================================================================\n;\t; The drawing loop:\n;\t; DS:SI = codebook\n;\t; ES:DI = drawing buffer\n;\t; FS:BX = pointers\n;\t;===================================================================\n;\t;-------------------------------------------------------------------\n;\t; Start a new row of drawing\n;\t;-------------------------------------------------------------------\n;??Start_row:\n;\tmov\tcx,[blocksperrow]\t\t; # blocks to fill a line\n;\n;\t;-------------------------------------------------------------------\n;\t; Start a new block\n;\t;-------------------------------------------------------------------\n;??Not_finished_a_line:\n;\t;\n;\t;..................... get next pointer word .......................\n;\t;\n;\tmov\tsi,[WORD PTR fs:bx]\t\t; SI = ptr word (cbook offset)\n;\tadd\tbx,2\t\t\t\t; next ptr word\n;\t;\n;\t;................... skip ptr value SKIP_PTR .......................\n;\t;\n;\tcmp\tsi,SKIP_PTR\n;\tjne\t??Draw_Block\n;\tinc\tdi\n;\tdec\tcx\n;\tjnz\tshort ??Not_finished_a_line\n;\tjmp\t??Next_row\n;\n;\t;-------------------------------------------------------------------\n;\t; Draw a block via the VGA internal latches:\n;\t; DS:SI = codebook address\n;\t; ES:DI = buffer position to draw at\n;\t; - Load the VGA latches from the 1st 4 codebook bytes\n;\t; - write 4 pixels with one CPU write\n;\t; - If this is a one-color block, skip the next codebook read\n;\t;   (Video RAM reads are very slow); otherwise, latch the next 4\n;\t;   codebook bytes\n;\t; - write the next 4 pixels\n;\t;-------------------------------------------------------------------\n;\t;\n;\t;..................... draw 1st 4 pixels ...........................\n;\t;\n;??Draw_Block:\n;\tmov\tal,[ds:si]\t\t\t; latch 1st 4 cbook bytes\n;\tmov\t[es:di],al\t\t\t; write 4 pixels\n;\t;\n;\t;.................. check for 1-color block ........................\n;\t;\n;\tcmp\tsi,512\t\t\t\t; if 1color blk, don't read\n;\tjb\t??One_Color\n;\t;\n;\t;..................... draw next 4 pixels ..........................\n;\t;\n;\tmov\tal,[ds:si+1]\t\t\t; latch next 4 cbook bytes\n;??One_Color:\n;\tmov\t[es:di+80],al\t\t\t; write next 4 pixels\n;\tinc\tdi\t\t\t\t; next block position\n;\t;\n;\t;...................... check block count ..........................\n;\t;\n;\tdec\tcx\t\t\t\t; decrement block count\n;\tjnz\tshort ??Not_finished_a_line\n;\n;\t;-------------------------------------------------------------------\n;\t; Go to the next block row:\n;\t; - Add (80*2/16) to ES, and set DI to its start-row value\n;\t;   (Incrementing the segment allows us to unpack up to 1MB of data)\n;\t;-------------------------------------------------------------------\n;\t;\n;\t;...................... add (320*2/16) to ES .......................\n;\t;\n;??Next_row:\n;\tmov\tax,es\n;\tadd\tax,10\t\t\t\t; add 80*2/16\n;\tmov\tes,ax\n;\t;\n;\t;.................. set DI to its start-row value ..................\n;\t;\n;\tmov\tdi,[di_startval]\n;\t;\n;\t;............ see if we're past the end of the ptr data ............\n;\t;\n;\tdec\t[numrows]\n;\tjg\t??Start_row\n;\n;??End_of_data:\n;\t;-------------------------------------------------------------------\n;\t; Restore VGA Write Mode to 0\n;\t;-------------------------------------------------------------------\n;\tSET_WRITEMODE 0\n;\n;\tpopad\n;\tpop\tfs\n;\tpop\tes\n;\tpop\tds\n\tret\n\n\tENDP\tUnVQ_4x2_XmodeCB\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Upload_4x2CB - Upload 4x2 codebook into XMode VRAM.\n;*\n;* SYNOPSIS\n;*     Upload_4x2CB(Codebook, Entries)\n;*\n;*     void Upload_4x2CB(unsigned char *, unsigned short);\n;*\n;* FUNCTION\n;*     This routine copies the given codebook into Xmode VRAM, so that it\n;*     can be used later for direct video-to-video copies. The address used\n;*     is the end of video memory minus 02700h (10K). This should be plenty\n;*     for a 3000-entry codebook; each 4x2 codebook entry will take up 8\n;*     8 bytes, or 2 addresses in XMode (6000 addresses).\n;*\n;*     The routine also creates a 1-color-block table in VRAM, so the 1-color\n;*     blocks can be generated the same way as the multicolor blocks.\n;*\n;*     XMode 320x200 uses 320x200/4 addresses per page, for a total of 32000\n;*     addresses.  XMode 320x240 uses 320x240/4 addresses per page, for a\n;*     total of 38400 addresses.  This leaves 27136 addresses unused.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook to copy.\n;*     Entries  - Number of codebook entries to copy.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Upload_4x2CB:NEAR\n\tPROC\tUpload_4x2CB C NEAR USES\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tnumentries:DWORD\n\n;\t;===================================================================\n;\t; Generate the 1-color block table by writing each color value from\n;\t; 0-255 into all 4 bitplanes, at 256 consecutive addresses:\n;\t;===================================================================\n;\tSET_PLANE 0fh\t\t\t; enable all bitplanes for writing\n;\t;...................................................................\n;\t; Set ES:DI to destination address, set up CX for the loop\n;\t;...................................................................\n;\tmov\tax,CBOOK_SEG\n;\tmov\tes,ax\n;\tmov\tdi,0\n;\tmov\tcx,256\n;\tmov\tax,0\n;??1_Color_Loop:\n;\tmov\t[es:di],al\t\t\t; write 4 bytes\n;\tinc\tdi\t\t\t\t; next 4-byte position\n;\tmov\t[es:di],al\t\t\t; write 4 bytes\n;\tinc\tdi\t\t\t\t; next 4-byte position\n;\tinc\tax\t\t\t\t; next color #\n;\tdec\tcx\t\t\t\t; decrement loop counter\n;\tjnz\t??1_Color_Loop\n;\n;\t;===================================================================\n;\t; Copy the codebook into video RAM, one plane at a time:\n;\t;===================================================================\n;\t;-------------------------------------------------------------------\n;\t; Copy codebook byte 0 into Plane 1\n;\t;-------------------------------------------------------------------\n;\t;...................................................................\n;\t; Set DS:SI to codebook address, ES:DI to screen address\n;\t; (Codebook is stored at offset 1, so the pointers will point at\n;\t; exactly the right offset.)\n;\t;...................................................................\n;\tlds\tsi, [codebook]\t\t\t; DS:SI = codebook\n;\tmov\tax,CBOOK_SEG\n;\tmov\tes,ax\n;\tmov\tdi,512\n;\n;\t;...................................................................\n;\t; Set up the loop\n;\t;...................................................................\n;\tSET_PLANE XPLANE_1\n;\tmov\tcx,[numentries]\t\t\t; set loop counter\n;\tshl\tcx,1\t\t\t\t; do 2 DWORDS per cbook entry\n;\n;\t;...................................................................\n;\t; Loop through codebook entries\n;\t;...................................................................\n;??CB_Loop_1:\n;\tmov\tal,[ds:si]\n;\tmov\t[es:di],al\n;\tadd\tsi,4\n;\tinc\tdi\n;\tdec\tcx\n;\tjnz\t??CB_Loop_1\n;\n;\t;-------------------------------------------------------------------\n;\t; Copy codebook byte 1 Plane 2\n;\t;-------------------------------------------------------------------\n;\t;...................................................................\n;\t; Set DS:SI to codebook address, ES:DI to screen address\n;\t; (Codebook is stored at offset 1, so the pointers will point at\n;\t; exactly the right offset.)\n;\t;...................................................................\n;\tlds\tsi, [codebook]\t\t\t; DS:SI = codebook\n;\tmov\tax,CBOOK_SEG\n;\tmov\tes,ax\n;\tmov\tdi,512\n;\tadd\tsi,1\t\t\t\t; use 2nd byte value\n;\n;\t;...................................................................\n;\t; Set up the loop\n;\t;...................................................................\n;\tSET_PLANE XPLANE_2\n;\tmov\tcx,[numentries]\t\t\t; set loop counter\n;\tshl\tcx,1\t\t\t\t; do 2 DWORDS per cbook entry\n;\n;\t;...................................................................\n;\t; Loop through codebook entries\n;\t;...................................................................\n;??CB_Loop_2:\n;\tmov\tal,[ds:si]\n;\tmov\t[es:di],al\n;\tadd\tsi,4\n;\tinc\tdi\n;\tdec\tcx\n;\tjnz\t??CB_Loop_2\n;\n;\t;-------------------------------------------------------------------\n;\t; Copy codebook byte 2 Plane 3\n;\t;-------------------------------------------------------------------\n;\t;...................................................................\n;\t; Set DS:SI to codebook address, ES:DI to screen address\n;\t; (Codebook is stored at offset 1, so the pointers will point at\n;\t; exactly the right offset.)\n;\t;...................................................................\n;\tlds\tsi, [codebook]\t\t\t; DS:SI = codebook\n;\tmov\tax,CBOOK_SEG\n;\tmov\tes,ax\n;\tmov\tdi,512\n;\tadd\tsi,2\t\t\t\t; use 3rd byte value\n;\n;\t;...................................................................\n;\t; Set up the loop\n;\t;...................................................................\n;\tSET_PLANE XPLANE_3\n;\tmov\tcx,[numentries]\t\t\t; set loop counter\n;\tshl\tcx,1\t\t\t\t; do 2 DWORDS per cbook entry\n;\n;\t;...................................................................\n;\t; Loop through codebook entries\n;\t;...................................................................\n;??CB_Loop_3:\n;\tmov\tal,[ds:si]\n;\tmov\t[es:di],al\n;\tadd\tsi,4\n;\tinc\tdi\n;\tdec\tcx\n;\tjnz\t??CB_Loop_3\n;\n;\t;-------------------------------------------------------------------\n;\t; Copy codebook byte 3 Plane 4\n;\t;-------------------------------------------------------------------\n;\t;...................................................................\n;\t; Set DS:SI to codebook address, ES:DI to screen address\n;\t; (Codebook is stored at offset 1, so the pointers will point at\n;\t; exactly the right offset.)\n;\t;...................................................................\n;\tlds\tsi, [codebook]\t\t\t; DS:SI = codebook\n;\tmov\tax,CBOOK_SEG\n;\tmov\tes,ax\n;\tmov\tdi,512\n;\tadd\tsi,3\t\t\t\t; use 4th byte value\n;\n;\t;...................................................................\n;\t; Set up the loop\n;\t;...................................................................\n;\tSET_PLANE XPLANE_4\n;\tmov\tcx,[numentries]\t\t\t; set loop counter\n;\tshl\tcx,1\t\t\t\t; do 2 DWORDS per cbook entry\n;\n;\t;...................................................................\n;\t; Loop through codebook entries\n;\t;...................................................................\n;??CB_Loop_4:\n;\tmov\tal,[ds:si]\n;\tmov\t[es:di],al\n;\tadd\tsi,4\n;\tinc\tdi\n;\tdec\tcx\n;\tjnz\t??CB_Loop_4\n;\n\tret\n\n\tENDP\tUpload_4x2CB\n\n\tENDIF\t;VQABLOCK_4X2\n\n;****************************************************************************\n;*\n;* NAME\n;*     XlatePointers - Translate pointer to optimal XMode format.\n;*\n;* SYNOPSIS\n;*     XlatePointers(Pointers, Entries)\n;*\n;*     void XlatePointers(unsigned char *, unsigned short);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Pointers - Pointer to vector pointers to translate.\n;*     Entries  - Number of pointer entries.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC XlatePointers:NEAR\n\tPROC\tXlatePointers C NEAR USES\n\n\tARG\tpointers:NEAR PTR\n\tARG\tnumpointers:DWORD\n\n;\t;-------------------------------------------------------------------\n;\t; Load pointers into DS:SI\n;\t;-------------------------------------------------------------------\n;\tlds\tsi,[pointers]\n;\n;\tmov\tcx,[numpointers]\t\t; init to # pointers on scrn\n;\n;??Process_pointer:\n;\t;\n;\t;..................... get next pointer word .......................\n;\t;\n;\tmov\tax,[WORD PTR ds:si]\t\t; SI = ptr word (cbook offset)\n;\t;\n;\t;.................... check for a 1-color block ....................\n;\t;\n;\tor\tax,ax\t\t\t\t; check to see if high bit set\n;\tjs\tshort ??One_color\n;\t;\n;\t;....................... multi-color pointer .......................\n;\t;\n;\tsub\tax,4\t\t\t\t; subtract 4\n;\tshr\tax,2\t\t\t\t; divide by 4\n;\tadd\tax,512\t\t\t\t; add 512\n;\tmov\t[WORD PTR ds:si],ax\t\t; save new value\n;\tadd\tsi,2\t\t\t\t; next ptr word\n;\t;\n;\t;....................... see if we're done .........................\n;\t;\n;\tdec\tcx\n;\tjnz\t??Process_pointer\n;\tjmp\t??Done\n;\n;??One_color:\n;\t;\n;\t;......................... 1-color pointer .........................\n;\t;\n;\tnot\tax\t\t\t\t; get actual color value\n;\tshl\tax,1\t\t\t\t; multiply by 2\n;\tmov\t[WORD PTR ds:si],ax\t\t; save new value\n;\tadd\tsi,2\t\t\t\t; next ptr word\n;\t;\n;\t;....................... see if we're done .........................\n;\t;\n;\tdec\tcx\n;\tjnz\t??Process_pointer\n;\n;??Done:\n\tret\n\n\tENDP\tXlatePointers\n\n\tENDIF\t;VQAXMODE_ON\n\tEND\n\n\n\n\n\n"
  },
  {
    "path": "VQ/VQA32/UNVQXMDE.ASM.BAK",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PROJECT\n;*     VQA player library.\n;*\n;* FILE\n;*     UnVQ4x2.asm\n;*\n;* DESCRIPTION\n;*     4x2 VQ decompress/draw routines.\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     UnVQ_4x2_Xmode       - Draw 4x2 VQ frame directly to Xmode.\n;*     UnVQ_4x2_XmodeCB     - Draw 4x2 VQ frame to Xmode from VRAM codebook.\n;*     Upload_4x2CB         - Upload 4x2 codebook into XMode VRAM.\n;*     UnVQ_4x2_VESA320_32K - Draw 4x2 VQ frame to VESA320 32k color.\n;*     XlatePointers        - Translate pointer to optimal XMode format.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tMODEL\tLARGE\n\tP386N\n\tLOCALS\t??\n\tINCLUDE\t\"vga.i\"\n\tINCLUDE\t\"vesavid.i\"\n\tINCLUDE\t\"vqaplay.i\"\n\tCODESEG\n\n\tIF\tVQAXMODE_ON\n\nSKIP_PTR\tEQU\t8000h\nCBOOK_SEG\tEQU\t(0B000h - 270h)\n\n\tIF\tVQABLOCK_4X2\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x2_Xmode - Draw 4x2 VQ frame directly to Xmode.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x2_Xmode(Codebook, Pointers, Buffer, BPR, Rows, Dummy)\n;*\n;*     void UnVQ_4x2_Xmode(unsigned char *, unsigned char *, unsigned char *,\n;*                         unsigned short, unsigned short, unsigned short);\n;*\n;* FUNCTION\n;*     This function draws an image to the Xmode display from the pointers\n;*     and codebook provided. This routine has been optimized for a 320x200\n;*     image.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook used to draw image.\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to buffer to draw image into.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*     Dummy    - Not used (prototype placeholder)\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tPUBLIC\tC UnVQ_4x2_Xmode\n\tPROC\tC UnVQ_4x2_Xmode FAR USES\n\n\tARG\tcodebook:FAR PTR\n\tARG\tpointers:FAR PTR\n\tARG\tbuffer:FAR PTR\n\tARG\tblocksperrow:WORD\n\tARG\tnumrows:WORD\n\tARG\tdummy:WORD\n\n\t;-------------------------------------------------------------------\n\t; Local variables:\n\t;-------------------------------------------------------------------\n\tLOCAL\tdata_end:WORD\t\t; end of pointer data\n\tLOCAL\tsi_startval:WORD\t; init value for SI, for new plane\n\tLOCAL\tes_startval:WORD\t; init value for ES, for new plane\n\tLOCAL\tdi_startval:WORD\t; init value for DI, for new row\n\tLOCAL\tcb_offset:WORD\t\t; codebook offset\n\n\t;===================================================================\n\t; Initialization\n\t;===================================================================\n\t;-------------------------------------------------------------------\n\t; Save our registers\n\t;-------------------------------------------------------------------\n\tpush\tds\n\tpush\tes\n\tpush\tfs\n\tpushad\n\n\t;-------------------------------------------------------------------\n\t; Save codebook's address in FS:[cb_offset]:\n\t; - load it into DS:SI, and normalize it\n\t; - save it into FS:[cb_offset], and subtract 4 from it, so the \n\t;   pointer offsets will point directly at the correct codeword\n\t;-------------------------------------------------------------------\n\tlds\tsi,[codebook]\t\t\t; DS:SI = codebook\n\tcmp\tsi, 16\t\t\t\t; SI < 16 ?\n\tjb\tshort ??Decrement_codebook\t; yes - don't normalize it\n\tmov\tax, si\t\t\t\t; AX = SI\n\tshr\tax, 4\t\t\t\t; AX = SI / 16\n\tmov\tbx, ds\t\t\t\t; BX = DS\n\tadd\tax, bx\t\t\t\t; AX = (SI / 16) + DS\n\tmov\tds, ax\t\t\t\t; adjust DS upward\n\tand\tsi, 000Fh\t\t\t; save only low nybble\n??Decrement_codebook:\n\tmov\tax,ds\t\t\t\t; AX = cb segment\n\tsub\tax,1\t\t\t\t; subtract 16 bytes\n\tmov\tfs,ax\t\t\t\t; save in FS\n\tmov\t[cb_offset],si\n\tadd\t[cb_offset],12\n\n\t;-------------------------------------------------------------------\n\t; Load pointers into DS:SI, then normalize DS:SI to minimize offset\n\t;-------------------------------------------------------------------\n??Normalize_pointers:\n\tlds\tsi, [pointers]\t\t\t; DS:SI = pointers\n\tcmp\tsi, 16\t\t\t\t; SI < 16 ?\n\tjb\tshort ??Set_Data_End\t\t; yes - don't normalize it\n\tmov\tax, si\t\t\t\t; AX = SI\n\tshr\tax, 4\t\t\t\t; AX = SI / 16\n\tmov\tbx, ds\t\t\t\t; BX = DS\n\tadd\tax, bx\t\t\t\t; AX = (SI / 16) + DS\n\tmov\tds, ax\t\t\t\t; adjust DS upward\n\tand\tsi, 000Fh\t\t\t; save only low nybble\n\n\t;-------------------------------------------------------------------\n\t; Set [data_end] to [pointers] + size of ptr data\n\t;-------------------------------------------------------------------\n??Set_Data_End:\n\tmov\tax,[numrows]\n\tmul\t[blocksperrow]\t\t\t; AX = total # blocks\n\tshl\tax,1\t\t\t\t; mult by 2 for word size\n\tadd\tax,si\t\t\t\t; compute end of data\n\tmov\t[data_end],ax\t\t\t; store it\n\tmov\t[si_startval],si\t\t; save SI\n\n\t;-------------------------------------------------------------------\n\t; Load buffer into ES:DI, then normalize ES:DI to minimize offset\n\t;-------------------------------------------------------------------\n\tles\tdi, [buffer]   \t\t\t; point ES:DI to dest\n\tmov\t[es_startval],es\t\t; save ES's start value\n\tmov\t[di_startval],di\t\t; store it\n\tcmp\tdi, 16\t\t\t\t; DI < 16 ?\n\tjb\tshort ??Set_XPlane1\t\t; yes - don't normalize it\n\tmov\tax, di\t\t\t\t; AX = DI\n\tshr\tax, 4\t\t\t\t; AX = DI / 16\n\tmov\tbx, es\t\t\t\t; BX = ES\n\tadd\tax, bx\t\t\t\t; AX = (DI / 16) + ES\n\tmov\tes, ax\t\t\t\t; adjust ES upward\n\tand\tdi, 000Fh\t\t\t; save only low nybble\n\tmov\t[es_startval],es\t\t; save ES's start value\n\tmov\t[di_startval],di\t\t; save DI's start value\n\n\n\t;===================================================================\n\t; The drawing loop:\n\t; DS:SI = pointer data\n\t; ES:DI = drawing buffer\n\t; FS:[cb_offset] = codebook\n\t;===================================================================\n\t;===================================================================\n\t; Set X-Mode Plane 1\n\t; Plane 1 is the left half of even-numbered blocks on a row.\n\t; (left pixel = low byte of codebook word)\n\t;===================================================================\n??Set_XPlane1:\n\tSET_PLANE XPLANE_1\n\n\t;-------------------------------------------------------------------\n\t; Start a new row of drawing\n\t;-------------------------------------------------------------------\n??Start_row_1:\n\tmov\tcx,[blocksperrow]\t\t; # blocks to fill a line\n\n\t;-------------------------------------------------------------------\n\t; Start a new block\n\t;-------------------------------------------------------------------\n??Not_finished_a_line_1:\n\t;\n\t;..................... get next pointer word .......................\n\t;\n\tmov\tbx,[WORD PTR DS:SI]\t\t; AX = pointer word\n\tadd\tsi,2\t\t\t\t; SI = next pointer\n\t;\n\t;.................... check for a 1-color block ....................\n\t;\n\tor\tbx,bx\t\t\t\t; check to see if high bit set\n\tjs\tshort ??One_color_1\n\n\t;-------------------------------------------------------------------\n\t; Draw a multi-color block\n\t; (AX = pointer byte)\n\t; (ES:DI = buffer position to draw at)\n\t; (FS:[cb_offset] = codebook address)\n\t;-------------------------------------------------------------------\n\tadd\tbx,[cb_offset]\t\t; get codebook offset\n\t;\n\t;................ transfer bytes from FS:BX to ES:DI ...............\n\t;\n\tmov\tax,[fs:bx]\t\t\t; get 1st codeword\n\tmov\tdx,[fs:bx+4]\t\t\t; get 2nd codeword\n\tmov\t[es:di],al\t\t\t; draw 1st\n\tmov\t[es:di+80],dl\t\t\t; draw 2nd\n\tinc\tdi\t\t\t\t; next pixel\n\t;\n\t;..................... check block count ...........................\n\t;\n\tdec\tcx\t\t\t\t; decrement block count\n\tjnz\tshort ??Not_finished_a_line_1\n\n\t;-------------------------------------------------------------------\n\t; Go to the next block row:\n\t; - Add new offset to ES, and set DI to its start-row value\n\t;   (Incrementing the segment allows us to unpack up to 1MB of data)\n\t;   (Divide by 4 because there's 1/4 as many addresses per line\n\t;   in XMODE)\n\t;-------------------------------------------------------------------\n\t;\n\t;....................... Add 80*2/16 to ES .........................\n\t;\n\tmov\tax,es\n\tadd\tax,10\t\t\t\t; add 80*2/16\n\tmov\tes,ax\n\t;\n\t;.................. set DI to its start-row value ..................\n\t;\n\tmov\tdi,[di_startval]\n\t;\n\t;............ see if we're past the end of the ptr data ............\n\t;\n\tcmp\tsi,[data_end]\n\tjnb\tshort ??End_of_data_1\t\t; no - goto end\n\tjmp\t??Start_row_1\t\t\t; start new block row\n\n\t;-------------------------------------------------------------------\n\t; Draw 1-color block\n\t; (AX = pointer byte)\n\t; (ES:DI = buffer position to draw at)\n\t; (FS:[cb_offset] = codebook address)\n\t;-------------------------------------------------------------------\n??One_color_1:\n\t;\n\t;................... skip ptr value SKIP_PTR .......................\n\t;\n\tcmp\tbx,SKIP_PTR\n\tjne\t??Draw_One_Color_1\n\tinc\tdi\n\tdec\tcx\n\tjnz\tshort ??Not_finished_a_line_1\n\tjmp\t??Next_row_1\n\t;\n\t;................. transfer bytes from AX to DS:SI .................\n\t;\n??Draw_One_Color_1:\n\tnot\tbx\n\tmov\tbh,bl\t\t\t\t; dup al in al&ah\n\tmov\t[es:di],bl\t\t\t; set pixel\n\tmov\t[es:di+80],bl\t\t\t; set pixel\n\tinc\tdi\t\t\t\t; next pixel\n\t;\n\t;..................... check block count ...........................\n\t;\n\tdec\tcx\t\t\t\t; decrement block count\n\tjnz\tshort ??Not_finished_a_line_1\n\n\t;-------------------------------------------------------------------\n\t; Go to the next block row:\n\t; - Add new offset to ES, and set DI to its start-row value\n\t;   (Incrementing the segment allows us to unpack up to 1MB of data)\n\t;   (Divide by 4 because there's 1/4 as many addresses per line\n\t;   in XMODE)\n\t;-------------------------------------------------------------------\n\t;\n\t;....................... Add 80*2/16 to ES .........................\n\t;\n??Next_row_1:\n\tmov\tax,es\n\tadd\tax,10\t\t\t\t; add 80*2/16\n\tmov\tes,ax\n\t;\n\t;.................. set DI to its start-row value ..................\n\t;\n\tmov\tdi,[di_startval]\n\t;\n\t;............ see if we're past the end of the ptr data ............\n\t;\n\tcmp\tsi,[data_end]\n\tjnb\tshort ??End_of_data_1\t\t; no - goto end\n\tjmp\t??Start_row_1\t\t\t; start new block row\n\n??End_of_data_1:\n\t;-------------------------------------------------------------------\n\t; Restore DS:SI to start of pointer data, and ES:DI to Xmode page\n\t;-------------------------------------------------------------------\n\tmov\tsi,[si_startval]\n\tmov\tes,[es_startval]\n\tmov\tdi,[di_startval]\n\n\t;===================================================================\n\t; Set X-Mode Plane 2\n\t; Plane 2 is the right half of even-numbered blocks on a row.\n\t; (right pixel = high byte of codebook word)\n\t;===================================================================\n\tSET_PLANE XPLANE_2\n\n\t;-------------------------------------------------------------------\n\t; Start a new row of drawing\n\t;-------------------------------------------------------------------\n??Start_row_2:\n\tmov\tcx,[blocksperrow]\t\t; # blocks to fill a line\n\n\t;-------------------------------------------------------------------\n\t; Start a new block\n\t;-------------------------------------------------------------------\n??Not_finished_a_line_2:\n\t;\n\t;..................... get next pointer word .......................\n\t;\n\tmov\tbx,[WORD PTR DS:SI]\t\t; AX = pointer word\n\tadd\tsi,2\t\t\t\t; SI = next pointer\n\t;\n\t;.................... check for a 1-color block ....................\n\t;\n\tor\tbx,bx\t\t\t\t; check to see if high bit set\n\tjs\tshort ??One_color_2\n\n\t;-------------------------------------------------------------------\n\t; Draw a multi-color block\n\t; (AX = pointer byte)\n\t; (ES:DI = buffer position to draw at)\n\t; (FS:[cb_offset] = codebook address)\n\t;-------------------------------------------------------------------\n\tadd\tbx,[cb_offset]\t\t; get codebook offset\n\t;\n\t;................ transfer bytes from FS:BX to ES:DI ...............\n\t;\n\tmov\tax,[fs:bx]\t\t\t; get 1st codeword\n\tmov\tdx,[fs:bx+4]\t\t\t; get 2nd codeword\n\tmov\t[es:di],ah\t\t\t; draw 1st\n\tmov\t[es:di+80],dh\t\t\t; draw 2nd\n\tinc\tdi\t\t\t\t; next pixel\n\t;\n\t;..................... check block count ...........................\n\t;\n\tdec\tcx\t\t\t\t; decrement block count\n\tjnz\tshort ??Not_finished_a_line_2\n\n\t;-------------------------------------------------------------------\n\t; Go to the next block row:\n\t; - Add new offset to ES, and set DI to its start-row value\n\t;   (Incrementing the segment allows us to unpack up to 1MB of data)\n\t;   (Divide by 4 because there's 1/4 as many addresses per line\n\t;   in XMODE)\n\t;-------------------------------------------------------------------\n\t;\n\t;....................... Add 80*2/16 to ES .........................\n\t;\n\tmov\tax,es\n\tadd\tax,10\t\t\t\t; add 80*2/16\n\tmov\tes,ax\n\t;\n\t;.................. set DI to its start-row value ..................\n\t;\n\tmov\tdi,[di_startval]\n\t;\n\t;............ see if we're past the end of the ptr data ............\n\t;\n\tcmp\tsi,[data_end]\n\tjnb\tshort ??End_of_data_2\t\t; no - goto end\n\tjmp\t??Start_row_2\t\t\t; start new block row\n\n\t;-------------------------------------------------------------------\n\t; Draw 1-color block\n\t; (AX = pointer byte)\n\t; (ES:DI = buffer position to draw at)\n\t; (FS:[cb_offset] = codebook address)\n\t;-------------------------------------------------------------------\n??One_color_2:\n\t;\n\t;................... skip ptr value SKIP_PTR .......................\n\t;\n\tcmp\tbx,SKIP_PTR\n\tjne\t??Draw_One_Color_2\n\tinc\tdi\n\tdec\tcx\n\tjnz\tshort ??Not_finished_a_line_2\n\tjmp\t??Next_row_2\n\t;\n\t;................. transfer bytes from AX to DS:SI .................\n\t;\n??Draw_One_Color_2:\n\tnot\tbx\n\tmov\tbh,bl\t\t\t\t; dup al in al&ah\n\tmov\t[es:di],bh\t\t\t; store 2 colors\n\tmov\t[es:di+80],bh\t\t\t; store 2 colors\n\tinc\tdi\t\t\t\t; next pixel\n\t;\n\t;..................... check block count ...........................\n\t;\n\tdec\tcx\t\t\t\t; decrement block count\n\tjnz\tshort ??Not_finished_a_line_2\n\n\t;-------------------------------------------------------------------\n\t; Go to the next block row:\n\t; - Add new offset to ES, and set DI to its start-row value\n\t;   (Incrementing the segment allows us to unpack up to 1MB of data)\n\t;   (Divide by 4 because there's 1/4 as many addresses per line\n\t;   in XMODE)\n\t;-------------------------------------------------------------------\n\t;\n\t;....................... Add 80*2/16 to ES .........................\n\t;\n??Next_row_2:\n\tmov\tax,es\n\tadd\tax,10\t\t\t\t; add 80*2/16\n\tmov\tes,ax\n\t;\n\t;.................. set DI to its start-row value ..................\n\t;\n\tmov\tdi,[di_startval]\n\t;\n\t;............ see if we're past the end of the ptr data ............\n\t;\n\tcmp\tsi,[data_end]\n\tjnb\tshort ??End_of_data_2\t\t; no - goto end\n\tjmp\t??Start_row_2\t\t\t; start new block row\n\n??End_of_data_2:\n\t;-------------------------------------------------------------------\n\t; Restore DS:SI to start of pointer data, and ES:DI to Xmode page\n\t;-------------------------------------------------------------------\n\tmov\tsi,[si_startval]\n\tmov\tes,[es_startval]\n\tmov\tdi,[di_startval]\n\n\t;===================================================================\n\t; Set X-Mode Plane 3\n\t; Plane 3 is the left half of odd-numbered blocks on a row.\n\t; (left pixel = low byte of codebook word)\n\t;===================================================================\n\tSET_PLANE XPLANE_3\n\n\t;-------------------------------------------------------------------\n\t; Start a new row of drawing\n\t;-------------------------------------------------------------------\n??Start_row_3:\n\tmov\tcx,[blocksperrow]\t\t; # blocks to fill a line\n\n\t;-------------------------------------------------------------------\n\t; Start a new block\n\t;-------------------------------------------------------------------\n??Not_finished_a_line_3:\n\t;\n\t;..................... get next pointer word .......................\n\t;\n\tmov\tbx,[WORD PTR DS:SI]\t\t; AX = pointer word\n\tadd\tsi,2\t\t\t\t; SI = next pointer\n\t;\n\t;.................... check for a 1-color block ....................\n\t;\n\tor\tbx,bx\t\t\t\t; check to see if high bit set\n\tjs\tshort ??One_color_3\n\n\t;-------------------------------------------------------------------\n\t; Draw a multi-color block\n\t; (AX = pointer byte)\n\t; (ES:DI = buffer position to draw at)\n\t; (FS:[cb_offset] = codebook address)\n\t;-------------------------------------------------------------------\n\tadd\tbx,[cb_offset]\t\t; get codebook offset\n\t;\n\t;................ transfer bytes from FS:BX to ES:DI ...............\n\t;\n\tmov\tax,[fs:bx+2]\t\t\t; get 1st codeword\n\tmov\tdx,[fs:bx+6]\t\t\t; get 2nd codeword\n\tmov\t[es:di],al\t\t\t; draw 1st\n\tmov\t[es:di+80],dl\t\t\t; draw 2nd\n\tinc\tdi\t\t\t\t; next pixel\n\t;\n\t;..................... check block count ...........................\n\t;\n\tdec\tcx\t\t\t\t; decrement block count\n\tjnz\tshort ??Not_finished_a_line_3\n\n\t;-------------------------------------------------------------------\n\t; Go to the next block row:\n\t; - Add new offset to ES, and set DI to its start-row value\n\t;   (Incrementing the segment allows us to unpack up to 1MB of data)\n\t;   (Divide by 4 because there's 1/4 as many addresses per line\n\t;   in XMODE)\n\t;-------------------------------------------------------------------\n\t;\n\t;....................... Add 80*2/16 to ES .........................\n\t;\n\tmov\tax,es\n\tadd\tax,10\t\t\t\t; add 80*2/16\n\tmov\tes,ax\n\t;\n\t;.................. set DI to its start-row value ..................\n\t;\n\tmov\tdi,[di_startval]\n\t;\n\t;............ see if we're past the end of the ptr data ............\n\t;\n\tcmp\tsi,[data_end]\n\tjnb\tshort ??End_of_data_3\t\t; no - goto end\n\tjmp\t??Start_row_3\t\t\t; start new block row\n\n\t;-------------------------------------------------------------------\n\t; Draw 1-color block\n\t; (AX = pointer byte)\n\t; (ES:DI = buffer position to draw at)\n\t; (FS:[cb_offset] = codebook address)\n\t;-------------------------------------------------------------------\n??One_color_3:\n\t;\n\t;................... skip ptr value SKIP_PTR .......................\n\t;\n\tcmp\tbx,SKIP_PTR\n\tjne\t??Draw_One_Color_3\n\tinc\tdi\n\tdec\tcx\n\tjnz\tshort ??Not_finished_a_line_3\n\tjmp\t??Next_row_3\n\t;\n\t;................. transfer bytes from AX to DS:SI .................\n\t;\n??Draw_One_Color_3:\n\tnot\tbx\n\tmov\tbh,bl\t\t\t\t; dup al in al&ah\n\tmov\t[es:di],bl\t\t\t; store 2 colors\n\tmov\t[es:di+80],bl\t\t\t; store 2 colors\n\tinc\tdi\t\t\t\t; next pixel\n\t;\n\t;..................... check block count ...........................\n\t;\n\tdec\tcx\t\t\t\t; decrement block count\n\tjnz\tshort ??Not_finished_a_line_3\n\n\t;-------------------------------------------------------------------\n\t; Go to the next block row:\n\t; - Add new offset to ES, and set DI to its start-row value\n\t;   (Incrementing the segment allows us to unpack up to 1MB of data)\n\t;   (Divide by 4 because there's 1/4 as many addresses per line\n\t;   in XMODE)\n\t;-------------------------------------------------------------------\n\t;\n\t;....................... Add 80*2/16 to ES .........................\n\t;\n??Next_row_3:\n\tmov\tax,es\n\tadd\tax,10\t\t\t\t; add 80*2/16\n\tmov\tes,ax\n\t;\n\t;.................. set DI to its start-row value ..................\n\t;\n\tmov\tdi,[di_startval]\n\t;\n\t;............ see if we're past the end of the ptr data ............\n\t;\n\tcmp\tsi,[data_end]\n\tjnb\tshort ??End_of_data_3\t\t; no - goto end\n\tjmp\t??Start_row_3\t\t\t; start new block row\n\n??End_of_data_3:\n\t;-------------------------------------------------------------------\n\t; Restore DS:SI to start of pointer data, and ES:DI to Xmode page\n\t;-------------------------------------------------------------------\n\tmov\tsi,[si_startval]\n\tmov\tes,[es_startval]\n\tmov\tdi,[di_startval]\n\n\t;===================================================================\n\t; Set X-Mode Plane 4\n\t; Plane 4 is the right half of odd-numbered blocks on a row.\n\t; (right pixel = high byte of codebook word)\n\t;===================================================================\n\tSET_PLANE XPLANE_4\n\n\t;-------------------------------------------------------------------\n\t; Start a new row of drawing\n\t;-------------------------------------------------------------------\n??Start_row_4:\n\tmov\tcx,[blocksperrow]\t\t; # blocks to fill a line\n\n\t;-------------------------------------------------------------------\n\t; Start a new block\n\t;-------------------------------------------------------------------\n??Not_finished_a_line_4:\n\t;\n\t;..................... get next pointer word .......................\n\t;\n\tmov\tbx,[WORD PTR DS:SI]\t\t; AX = pointer word\n\tadd\tsi,2\t\t\t\t; SI = next pointer\n\t;\n\t;.................... check for a 1-color block ....................\n\t;\n\tor\tbx,bx\t\t\t\t; check to see if high bit set\n\tjs\tshort ??One_color_4\n\n\t;-------------------------------------------------------------------\n\t; Draw a multi-color block\n\t; (AX = pointer byte)\n\t; (ES:DI = buffer position to draw at)\n\t; (FS:[cb_offset] = codebook address)\n\t;-------------------------------------------------------------------\n\tadd\tbx,[cb_offset]\t\t; get codebook offset\n\t;\n\t;................ transfer bytes from FS:BX to ES:DI ...............\n\t;\n\tmov\tax,[fs:bx+2]\t\t\t; get 1st codeword\n\tmov\tdx,[fs:bx+6]\t\t\t; get 2nd codeword\n\tmov\t[es:di],ah\t\t\t; draw 1st\n\tmov\t[es:di+80],dh\t\t\t; draw 2nd\n\tinc\tdi\t\t\t\t; next pixel\n\t;\n\t;..................... check block count ...........................\n\t;\n\tdec\tcx\t\t\t\t; decrement block count\n\tjnz\tshort ??Not_finished_a_line_4\n\n\t;-------------------------------------------------------------------\n\t; Go to the next block row:\n\t; - Add new offset to ES, and set DI to its start-row value\n\t;   (Incrementing the segment allows us to unpack up to 1MB of data)\n\t;   (Divide by 4 because there's 1/4 as many addresses per line\n\t;   in XMODE)\n\t;-------------------------------------------------------------------\n\t;\n\t;....................... Add 80*2/16 to ES .........................\n\t;\n\tmov\tax,es\n\tadd\tax,10\t\t\t\t; add 80*2/16\n\tmov\tes,ax\n\t;\n\t;.................. set DI to its start-row value ..................\n\t;\n\tmov\tdi,[di_startval]\n\t;\n\t;............ see if we're past the end of the ptr data ............\n\t;\n\tcmp\tsi,[data_end]\n\tjnb\tshort ??End_of_data_4\t\t; no - goto end\n\tjmp\t??Start_row_4\t\t\t; start new block row\n\n\t;-------------------------------------------------------------------\n\t; Draw 1-color block\n\t; (AX = pointer byte)\n\t; (ES:DI = buffer position to draw at)\n\t; (FS:[cb_offset] = codebook address)\n\t;-------------------------------------------------------------------\n??One_color_4:\n\t;\n\t;................... skip ptr value SKIP_PTR .......................\n\t;\n\tcmp\tbx,SKIP_PTR\n\tjne\t??Draw_One_Color_4\n\tinc\tdi\n\tdec\tcx\n\tjnz\tshort ??Not_finished_a_line_4\n\tjmp\t??Next_row_4\n\t;\n\t;................. transfer bytes from AX to DS:SI .................\n\t;\n??Draw_One_Color_4:\n\tnot\tbx\n\tmov\tbh,bl\t\t\t\t; dup al in al&ah\n\tmov\t[es:di],bh\t\t\t; store 2 colors\n\tmov\t[es:di+80],bh\t\t\t; store 2 colors\n\tinc\tdi\t\t\t\t; next pixel\n\t;\n\t;..................... check block count ...........................\n\t;\n\tdec\tcx\t\t\t\t; decrement block count\n\tjnz\tshort ??Not_finished_a_line_4\n\n\t;-------------------------------------------------------------------\n\t; Go to the next block row:\n\t; - Add new offset to ES, and set DI to its start-row value\n\t;   (Incrementing the segment allows us to unpack up to 1MB of data)\n\t;   (Divide by 4 because there's 1/4 as many addresses per line\n\t;   in XMODE)\n\t;-------------------------------------------------------------------\n\t;\n\t;....................... Add 80*2/16 to ES .........................\n\t;\n??Next_row_4:\n\tmov\tax,es\n\tadd\tax,10\t\t\t\t; add 80*2/16\n\tmov\tes,ax\n\t;\n\t;.................. set DI to its start-row value ..................\n\t;\n\tmov\tdi,[di_startval]\n\t;\n\t;............ see if we're past the end of the ptr data ............\n\t;\n\tcmp\tsi,[data_end]\n\tjnb\tshort ??End_of_data_4\t\t; no - goto end\n\tjmp\t??Start_row_4\t\t\t; start new block row\n\n??End_of_data_4:\n\tpopad\n\tpop\tfs\n\tpop\tes\n\tpop\tds\n\tret\n\n\tENDP\tUnVQ_4x2_Xmode\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x2_XmodeCB - Draw 4x2 VQ frame to Xmode from VRAM codebook.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x2_XmodeCB(Dummy, Pointers, Buffer, BPR, Rows)\n;* \n;*     void UnVQ_4x2_XmodeCB(unsigned char *, unsigned char *,\n;*                           unsigned char *, unsigned short,\n;*                           unsigned short);\n;*\n;* FUNCTION\n;*     This routine copies codebook entries from video RAM to video RAM.\n;*     The procedure for Write Mode 1 is:\n;*\n;*       - Perform a CPU read at the address of the 4-byte codebook entry;\n;*         this will load each byte at that address from all 4 bitplanes\n;*         into the VGA's internal latches.\n;*\n;*       - Perform a CPU write at the destination address, with the BitMask\n;*         register set to 0 (this tells the VGA hardware to only use the\n;*         data stored in the latches to write with), and the Map Mask\n;*         register set to 0Fh (all bitplanes enabled).\n;*\n;*     Optimized for 320x200.\n;*     The codebook must have been downloaded to video RAM before this\n;*     routine is called. This routine assumes the multicolor block pointers\n;*     have been pre-divided by 4, and have a total of 512 added to them, so\n;*     the pointer is an exact offset into the codebook.\n;*\n;* INPUTS\n;*     Dummy    - Not used (prototype placeholder)\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to Xmode buffer.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tPUBLIC\tC UnVQ_4x2_XmodeCB\n\tPROC\tC UnVQ_4x2_XmodeCB FAR USES\n\n\tARG\tcbdummy:FAR PTR\n\tARG\tpointers:FAR PTR\n\tARG\tbuffer:FAR PTR\n\tARG\tblocksperrow:WORD\n\tARG\tnumrows:WORD\n\n\t;-------------------------------------------------------------------\n\t; Local variables:\n\t;-------------------------------------------------------------------\n\tLOCAL\tdi_startval:WORD\t; init value for DI, for new row\n\n\t;===================================================================\n\t; Initialization\n\t;===================================================================\n\t;-------------------------------------------------------------------\n\t; Save our registers\n\t;-------------------------------------------------------------------\n\tpush\tds\n\tpush\tes\n\tpush\tfs\n\tpushad\n\n\t;-------------------------------------------------------------------\n\t; Save codebook's segment in DS\n\t;-------------------------------------------------------------------\n\tmov\tax,CBOOK_SEG\n\tmov\tds,ax\n\n\t;-------------------------------------------------------------------\n\t; Load pointers into FS:BX\n\t;-------------------------------------------------------------------\n\tles\tdi,[pointers]\n\tmov\tax,es\n\tmov\tfs,ax\n\tmov\tbx,di\n\n\t;-------------------------------------------------------------------\n\t; Load screen address into ES:DI\n\t;-------------------------------------------------------------------\n\tles\tdi, [buffer]   \t\t\t; point ES:DI to dest\n\tmov\t[di_startval],di\t\t; store it\n\n\t;-------------------------------------------------------------------\n\t; Initialize VGA registers:\n\t; - Enable all bitplanes for writing\n\t; - Set the BitMask register to 0, so only the data from the\n\t;   VGA latches is written into the bitplanes\n\t;-------------------------------------------------------------------\n\tSET_PLANE 0fh\t\t\t\t; enable all planes for write\n\tSET_WRITEMODE 1\n\n\t;===================================================================\n\t; The drawing loop:\n\t; DS:SI = codebook\n\t; ES:DI = drawing buffer\n\t; FS:BX = pointers\n\t;===================================================================\n\t;-------------------------------------------------------------------\n\t; Start a new row of drawing\n\t;-------------------------------------------------------------------\n??Start_row:\n\tmov\tcx,[blocksperrow]\t\t; # blocks to fill a line\n\n\t;-------------------------------------------------------------------\n\t; Start a new block\n\t;-------------------------------------------------------------------\n??Not_finished_a_line:\n\t;\n\t;..................... get next pointer word .......................\n\t;\n\tmov\tsi,[WORD PTR fs:bx]\t\t; SI = ptr word (cbook offset)\n\tadd\tbx,2\t\t\t\t; next ptr word\n\t;\n\t;................... skip ptr value SKIP_PTR .......................\n\t;\n\tcmp\tsi,SKIP_PTR\n\tjne\t??Draw_Block\n\tinc\tdi\n\tdec\tcx\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Next_row\n\n\t;-------------------------------------------------------------------\n\t; Draw a block via the VGA internal latches:\n\t; DS:SI = codebook address\n\t; ES:DI = buffer position to draw at\n\t; - Load the VGA latches from the 1st 4 codebook bytes\n\t; - write 4 pixels with one CPU write\n\t; - If this is a one-color block, skip the next codebook read\n\t;   (Video RAM reads are very slow); otherwise, latch the next 4\n\t;   codebook bytes\n\t; - write the next 4 pixels\n\t;-------------------------------------------------------------------\n\t;\n\t;..................... draw 1st 4 pixels ...........................\n\t;\n??Draw_Block:\n\tmov\tal,[ds:si]\t\t\t; latch 1st 4 cbook bytes\n\tmov\t[es:di],al\t\t\t; write 4 pixels\n\t;\n\t;.................. check for 1-color block ........................\n\t;\n\tcmp\tsi,512\t\t\t\t; if 1color blk, don't read\n\tjb\t??One_Color\n\t;\n\t;..................... draw next 4 pixels ..........................\n\t;\n\tmov\tal,[ds:si+1]\t\t\t; latch next 4 cbook bytes\n??One_Color:\n\tmov\t[es:di+80],al\t\t\t; write next 4 pixels\n\tinc\tdi\t\t\t\t; next block position\n\t;\n\t;...................... check block count ..........................\n\t;\n\tdec\tcx\t\t\t\t; decrement block count\n\tjnz\tshort ??Not_finished_a_line\n\n\t;-------------------------------------------------------------------\n\t; Go to the next block row:\n\t; - Add (80*2/16) to ES, and set DI to its start-row value\n\t;   (Incrementing the segment allows us to unpack up to 1MB of data)\n\t;-------------------------------------------------------------------\n\t;\n\t;...................... add (320*2/16) to ES .......................\n\t;\n??Next_row:\n\tmov\tax,es\n\tadd\tax,10\t\t\t\t; add 80*2/16\n\tmov\tes,ax\n\t;\n\t;.................. set DI to its start-row value ..................\n\t;\n\tmov\tdi,[di_startval]\n\t;\n\t;............ see if we're past the end of the ptr data ............\n\t;\n\tdec\t[numrows]\n\tjg\t??Start_row\n\n??End_of_data:\n\t;-------------------------------------------------------------------\n\t; Restore VGA Write Mode to 0\n\t;-------------------------------------------------------------------\n\tSET_WRITEMODE 0\n\n\tpopad\n\tpop\tfs\n\tpop\tes\n\tpop\tds\n\tret\n\n\tENDP\tUnVQ_4x2_XmodeCB\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Upload_4x2CB - Upload 4x2 codebook into XMode VRAM.\n;*\n;* SYNOPSIS\n;*     Upload_4x2CB(Codebook, Entries)\n;*\n;*     void Upload_4x2CB(unsigned char *, unsigned short);\n;*\n;* FUNCTION\n;*     This routine copies the given codebook into Xmode VRAM, so that it\n;*     can be used later for direct video-to-video copies. The address used\n;*     is the end of video memory minus 02700h (10K). This should be plenty\n;*     for a 3000-entry codebook; each 4x2 codebook entry will take up 8\n;*     8 bytes, or 2 addresses in XMode (6000 addresses).\n;*\n;*     The routine also creates a 1-color-block table in VRAM, so the 1-color\n;*     blocks can be generated the same way as the multicolor blocks.\n;*\n;*     XMode 320x200 uses 320x200/4 addresses per page, for a total of 32000\n;*     addresses.  XMode 320x240 uses 320x240/4 addresses per page, for a\n;*     total of 38400 addresses.  This leaves 27136 addresses unused.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook to copy.\n;*     Entries  - Number of codebook entries to copy.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tPUBLIC\tC Upload_4x2CB\n\tPROC\tC Upload_4x2CB FAR USES ds si es di cx dx\n\n\tARG\tcodebook:FAR PTR\n\tARG\tnumentries:WORD\n\n\t;===================================================================\n\t; Generate the 1-color block table by writing each color value from\n\t; 0-255 into all 4 bitplanes, at 256 consecutive addresses:\n\t;===================================================================\n\tSET_PLANE 0fh\t\t\t; enable all bitplanes for writing\n\t;...................................................................\n\t; Set ES:DI to destination address, set up CX for the loop\n\t;...................................................................\n\tmov\tax,CBOOK_SEG\n\tmov\tes,ax\n\tmov\tdi,0\n\tmov\tcx,256\n\tmov\tax,0\n??1_Color_Loop:\n\tmov\t[es:di],al\t\t\t; write 4 bytes\n\tinc\tdi\t\t\t\t; next 4-byte position\n\tmov\t[es:di],al\t\t\t; write 4 bytes\n\tinc\tdi\t\t\t\t; next 4-byte position\n\tinc\tax\t\t\t\t; next color #\n\tdec\tcx\t\t\t\t; decrement loop counter\n\tjnz\t??1_Color_Loop\n\n\t;===================================================================\n\t; Copy the codebook into video RAM, one plane at a time:\n\t;===================================================================\n\t;-------------------------------------------------------------------\n\t; Copy codebook byte 0 into Plane 1\n\t;-------------------------------------------------------------------\n\t;...................................................................\n\t; Set DS:SI to codebook address, ES:DI to screen address\n\t; (Codebook is stored at offset 1, so the pointers will point at\n\t; exactly the right offset.)\n\t;...................................................................\n\tlds\tsi, [codebook]\t\t\t; DS:SI = codebook\n\tmov\tax,CBOOK_SEG\n\tmov\tes,ax\n\tmov\tdi,512\n\n\t;...................................................................\n\t; Set up the loop\n\t;...................................................................\n\tSET_PLANE XPLANE_1\n\tmov\tcx,[numentries]\t\t\t; set loop counter\n\tshl\tcx,1\t\t\t\t; do 2 DWORDS per cbook entry\n\n\t;...................................................................\n\t; Loop through codebook entries\n\t;...................................................................\n??CB_Loop_1:\n\tmov\tal,[ds:si]\n\tmov\t[es:di],al\n\tadd\tsi,4\n\tinc\tdi\n\tdec\tcx\n\tjnz\t??CB_Loop_1\n\n\t;-------------------------------------------------------------------\n\t; Copy codebook byte 1 Plane 2\n\t;-------------------------------------------------------------------\n\t;...................................................................\n\t; Set DS:SI to codebook address, ES:DI to screen address\n\t; (Codebook is stored at offset 1, so the pointers will point at\n\t; exactly the right offset.)\n\t;...................................................................\n\tlds\tsi, [codebook]\t\t\t; DS:SI = codebook\n\tmov\tax,CBOOK_SEG\n\tmov\tes,ax\n\tmov\tdi,512\n\tadd\tsi,1\t\t\t\t; use 2nd byte value\n\n\t;...................................................................\n\t; Set up the loop\n\t;...................................................................\n\tSET_PLANE XPLANE_2\n\tmov\tcx,[numentries]\t\t\t; set loop counter\n\tshl\tcx,1\t\t\t\t; do 2 DWORDS per cbook entry\n\n\t;...................................................................\n\t; Loop through codebook entries\n\t;...................................................................\n??CB_Loop_2:\n\tmov\tal,[ds:si]\n\tmov\t[es:di],al\n\tadd\tsi,4\n\tinc\tdi\n\tdec\tcx\n\tjnz\t??CB_Loop_2\n\n\t;-------------------------------------------------------------------\n\t; Copy codebook byte 2 Plane 3\n\t;-------------------------------------------------------------------\n\t;...................................................................\n\t; Set DS:SI to codebook address, ES:DI to screen address\n\t; (Codebook is stored at offset 1, so the pointers will point at\n\t; exactly the right offset.)\n\t;...................................................................\n\tlds\tsi, [codebook]\t\t\t; DS:SI = codebook\n\tmov\tax,CBOOK_SEG\n\tmov\tes,ax\n\tmov\tdi,512\n\tadd\tsi,2\t\t\t\t; use 3rd byte value\n\n\t;...................................................................\n\t; Set up the loop\n\t;...................................................................\n\tSET_PLANE XPLANE_3\n\tmov\tcx,[numentries]\t\t\t; set loop counter\n\tshl\tcx,1\t\t\t\t; do 2 DWORDS per cbook entry\n\n\t;...................................................................\n\t; Loop through codebook entries\n\t;...................................................................\n??CB_Loop_3:\n\tmov\tal,[ds:si]\n\tmov\t[es:di],al\n\tadd\tsi,4\n\tinc\tdi\n\tdec\tcx\n\tjnz\t??CB_Loop_3\n\n\t;-------------------------------------------------------------------\n\t; Copy codebook byte 3 Plane 4\n\t;-------------------------------------------------------------------\n\t;...................................................................\n\t; Set DS:SI to codebook address, ES:DI to screen address\n\t; (Codebook is stored at offset 1, so the pointers will point at\n\t; exactly the right offset.)\n\t;...................................................................\n\tlds\tsi, [codebook]\t\t\t; DS:SI = codebook\n\tmov\tax,CBOOK_SEG\n\tmov\tes,ax\n\tmov\tdi,512\n\tadd\tsi,3\t\t\t\t; use 4th byte value\n\n\t;...................................................................\n\t; Set up the loop\n\t;...................................................................\n\tSET_PLANE XPLANE_4\n\tmov\tcx,[numentries]\t\t\t; set loop counter\n\tshl\tcx,1\t\t\t\t; do 2 DWORDS per cbook entry\n\n\t;...................................................................\n\t; Loop through codebook entries\n\t;...................................................................\n??CB_Loop_4:\n\tmov\tal,[ds:si]\n\tmov\t[es:di],al\n\tadd\tsi,4\n\tinc\tdi\n\tdec\tcx\n\tjnz\t??CB_Loop_4\n\n\tret\n\n\tENDP\tUpload_4x2CB\n\n\tENDIF\t;VQABLOCK_4X2\n\n;****************************************************************************\n;*\n;* NAME\n;*     XlatePointers - Translate pointer to optimal XMode format.\n;*\n;* SYNOPSIS\n;*     XlatePointers(Pointers, Entries)\n;*\n;*     void XlatePointers(unsigned char *, unsigned short);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Pointers - Pointer to vector pointers to translate.\n;*     Entries  - Number of pointer entries.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tPUBLIC\tC XlatePointers\n\tPROC\tC XlatePointers FAR USES ds si cx\n\n\tARG\tpointers:FAR PTR\n\tARG\tnumpointers:WORD\n\n\t;-------------------------------------------------------------------\n\t; Load pointers into DS:SI\n\t;-------------------------------------------------------------------\n\tlds\tsi,[pointers]\n\n\tmov\tcx,[numpointers]\t\t; init to # pointers on scrn\n\n??Process_pointer:\n\t;\n\t;..................... get next pointer word .......................\n\t;\n\tmov\tax,[WORD PTR ds:si]\t\t; SI = ptr word (cbook offset)\n\t;\n\t;.................... check for a 1-color block ....................\n\t;\n\tor\tax,ax\t\t\t\t; check to see if high bit set\n\tjs\tshort ??One_color\n\t;\n\t;....................... multi-color pointer .......................\n\t;\n\tsub\tax,4\t\t\t\t; subtract 4\n\tshr\tax,2\t\t\t\t; divide by 4\n\tadd\tax,512\t\t\t\t; add 512\n\tmov\t[WORD PTR ds:si],ax\t\t; save new value\n\tadd\tsi,2\t\t\t\t; next ptr word\n\t;\n\t;....................... see if we're done .........................\n\t;\n\tdec\tcx\n\tjnz\t??Process_pointer\n\tjmp\t??Done\n\n??One_color:\n\t;\n\t;......................... 1-color pointer .........................\n\t;\n\tnot\tax\t\t\t\t; get actual color value\n\tshl\tax,1\t\t\t\t; multiply by 2\n\tmov\t[WORD PTR ds:si],ax\t\t; save new value\n\tadd\tsi,2\t\t\t\t; next ptr word\n\t;\n\t;....................... see if we're done .........................\n\t;\n\tdec\tcx\n\tjnz\t??Process_pointer\n\n??Done:\n\tret\n\n\tENDP\tXlatePointers\n\n\tENDIF\t;VQAXMODE_ON\n\tEND\n\n"
  },
  {
    "path": "VQ/VQA32/VERTAG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vertag.c\n*\n* DESCRIPTION\n*     Version Tag\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     February 23, 1995\n*\n****************************************************************************/\n\n#include \"vqaplayp.h\"\n\n#ifdef __WATCOMC__\n#define DEVNAME \"Watcom/4GW\"\n#else\n#define DEVNAME \"Borland/TNT\"\n#endif\n\nchar VerTag[] = {\"$VER$\" VQA_IDSTRING\" \"DEVNAME\" (\"VQA_DATE\")\"};\nchar ReqTag[] = {\"$REQ$\" VQA_REQUIRES};\n\n"
  },
  {
    "path": "VQ/VQA32/VQAFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAFILE_H\n#define VQAFILE_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqafile.h\n*\n* DESCRIPTION\n*     VQA file format definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*      \n* DATE\n*     April 10, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\iff.h>\n\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n\n/*---------------------------------------------------------------------------\n * STRUCTURE DEFINITIONS AND RELATED DEFINES.\n *-------------------------------------------------------------------------*/\n\n/* VQAHeader: VQA movie description header. (VQHD)\n *\n * Version       - VQA version.\n * Flags         - Various flags. (See below)\n * ImageWidth    - Image width in pixels.\n * ImageHeight   - Image height in pixels.\n * BlockWidth    - Block width in pixels.\n * BlockHeight   - Block height in pixels.\n * Frames        - Total number of frames in the movie.\n * FPS           - Playback rate (Frame Per Second).\n * Groupsize     - Frame grouping size (frames per codebook).\n * Num1Colors    - Number of 1 color colors.\n * CBentries     - Number of codebook entries.\n * Xpos          - X position to draw frames. (-1 = Center)\n * Ypos          - Y position to draw frames. (-1 = Center)\n * MaxFramesize  - Size of largest frame.\n * SampleRate    - Sample rate of primary audio stream.\n * Channels      - Number of channels in primary audio stream.\n * BitsPerSample - Sample bit size in primary audio stream.\n * FutureUse     - Reserved for future expansion.\n */\ntypedef struct _VQAHeader {\n\tunsigned short Version;\n\tunsigned short Flags;\n\tunsigned short Frames;\n\tunsigned short ImageWidth;\n\tunsigned short ImageHeight;\n\tunsigned char  BlockWidth;\n\tunsigned char  BlockHeight;\n\tunsigned char  FPS;\n\tunsigned char  Groupsize;\n\tunsigned short Num1Colors;\n\tunsigned short CBentries;\n\tunsigned short Xpos;\n\tunsigned short Ypos;\n\tunsigned short MaxFramesize;\n\tunsigned short SampleRate;\n\tunsigned char  Channels;\n\tunsigned char  BitsPerSample;\n\tunsigned short AltSampleRate;\n\tunsigned char  AltChannels;\n\tunsigned char  AltBitsPerSample;\n\tunsigned short FutureUse[5];\n} VQAHeader;\n\n/* Version type. */\n#define VQAHD_VER1 1\n#define VQAHD_VER2 2\n\n/* VQA header flag definitions */\n#define VQAHDB_AUDIO    0 /* Audio track present. */\n#define VQAHDB_ALTAUDIO 1 /* Alternate audio track present. */\n#define VQAHDF_AUDIO    (1<<VQAHDB_AUDIO)\n#define VQAHDF_ALTAUDIO (1<<VQAHDB_ALTAUDIO)\n\n\n/* Frame information (FINF) chunk definitions\n *\n * The FINF chunk contains a longword (4 bytes) entry for each\n * frame in the movie. This entry is divided into two parts,\n * flags (4 bits) and offset (28 bits).\n *\n * BITS   NAME     DESCRIPTION\n * -----------------------------------------------------------\n * 31-28  Flags    4 bitwise boolean flags.\n * 27-0   Offset   Offset in WORDS from the start of the file.\n */\n#define VQAFINB_KEY  31\n#define VQAFINB_PAL  30\n#define VQAFINB_SYNC 29\n#define VQAFINF_KEY  (1L<<VQAFINB_KEY)\n#define VQAFINF_PAL  (1L<<VQAFINB_PAL)\n#define VQAFINF_SYNC (1L<<VQAFINB_SYNC)\n\n/* FINF related defines and macros. */\n#define VQAFINF_OFFSET 0x0FFFFFFFL\n#define VQAFINF_FLAGS  0xF0000000L\n#define VQAFRAME_OFFSET(a) (((a & VQAFINF_OFFSET)<<1))\n\n/* VQ vector pointer codes. */\n#define VPC_ONE_SINGLE    0xF000 /* One single color block */\n#define VPC_ONE_SEMITRANS 0xE000 /* One semitransparent block */\n#define VPC_SHORT_DUMP    0xD000 /* Short dump of single color blocks */\n#define VPC_LONG_DUMP     0xC000 /* Long dump of single color blocks */\n#define VPC_SHORT_RUN     0xB000 /* Short run of single color blocks */\n#define VPC_LONG_RUN      0xA000 /* Long run */\n\n/* Long run codes. */\n#define LRC_SEMITRANS 0xC000 /* Long run of semitransparent blocks. */\n#define LRC_SINGLE    0x8000 /* Long run of single color blocks. */\n\n/* Defines used for Run-Skip-Dump compression. */\n#define MIN_SHORT_RUN_LENGTH  2\n#define MAX_SHORT_RUN_LENGTH  15\n#define MIN_LONG_RUN_LENGTH   2\n#define MAX_LONG_RUN_LENGTH   4095\n#define MIN_SHORT_DUMP_LENGTH 3\n#define MAX_SHORT_DUMP_LENGTH 15\n#define MIN_LONG_DUMP_LENGTH  2\n#define MAX_LONG_DUMP_LENGTH  4095\n\n#define WORD_HI_BIT 0x8000\n\n/*---------------------------------------------------------------------------\n * VQA FILE CHUNK ID DEFINITIONS.\n *-------------------------------------------------------------------------*/\n\n#define ID_WVQA MAKE_ID('W','V','Q','A') /* Westwood VQ Animation form. */\n#define ID_VQHD MAKE_ID('V','Q','H','D') /* VQ header. */\n#define ID_NAME MAKE_ID('N','A','M','E') /* Name string. */\n#define ID_FINF MAKE_ID('F','I','N','F') /* Frame information. */\n#define ID_VQFR MAKE_ID('V','Q','F','R') /* VQ frame container. */\n#define ID_VQFK MAKE_ID('V','Q','F','K') /* VQ key frame container. */\n#define ID_CBF0 MAKE_ID('C','B','F','0') /* Full codebook. */\n#define ID_CBFZ MAKE_ID('C','B','F','Z') /* Full codebook (compressed). */\n#define ID_CBP0 MAKE_ID('C','B','P','0') /* Partial codebook. */\n#define ID_CBPZ MAKE_ID('C','B','P','Z') /* Partial codebook (compressed). */\n#define ID_VPT0 MAKE_ID('V','P','T','0') /* Vector pointers. */\n#define ID_VPTZ MAKE_ID('V','P','T','Z') /* Vector pointers (compressed). */\n#define ID_VPTK MAKE_ID('V','P','T','K') /* Vector pointers (Delta Key). */\n#define ID_VPTD MAKE_ID('V','P','T','D') /* Vector pointers (Delta). */\n#define ID_VPTR MAKE_ID('V','P','T','R') /* Pointers RSD compressed. */\n#define ID_VPRZ MAKE_ID('V','P','R','Z') /* Pointers RSD, lcw compressed. */\n#define ID_CPL0 MAKE_ID('C','P','L','0') /* Color palette. */\n#define ID_CPLZ MAKE_ID('C','P','L','Z') /* Color palette (compressed). */\n#define ID_SND0 MAKE_ID('S','N','D','0') /* Sound */\n#define ID_SND1 MAKE_ID('S','N','D','1') /* Sound (Zap compressed). */\n#define ID_SND2 MAKE_ID('S','N','D','2') /* Sound (ADPCM compressed). */\n#define ID_SNDZ MAKE_ID('S','N','D','Z') /* Sound (LCW compression). */\n\n#define ID_SNA0 MAKE_ID('S','N','A','0') /* Sound */\n#define ID_SNA1 MAKE_ID('S','N','A','1') /* Sound (Zap compressed). */\n#define ID_SNA2 MAKE_ID('S','N','A','2') /* Sound (ADPCM compressed). */\n#define ID_SNAZ MAKE_ID('S','N','A','Z') /* Sound (LCW compression). */\n\n#define ID_CAP0 MAKE_ID('C','A','P','0') /* Caption text */\n#define ID_EVA0 MAKE_ID('E','V','A','0') /* EVA text */\n\n#ifdef __WATCOMC__\n#pragma pack();\n#endif\n\n#endif /* VQAFILE_H */\n\n"
  },
  {
    "path": "VQ/VQA32/VQAPLAY.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAPLAY_H\n#define VQAPLAY_H\n/****************************************************************************\n*\n*         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\n*\n*---------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqaplay.h\n*\n* DESCRIPTION\n*      VQAPlay library definitions.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     February 23, 1995\n*\n****************************************************************************/\n\n/*---------------------------------------------------------------------------\n * CONDITIONAL COMPILATION FLAGS\n *-------------------------------------------------------------------------*/\n\n#ifdef __WATCOMC__\n#define VQAVOC_ON    0  /* Enable VOC file override */\n#define\tVQAMONO_ON   0  /* Mono display output enable/disable */\n#define VQAAUDIO_ON  0  /* Audio playback enable/disable */\n#define VQAVIDEO_ON  0  /* Video manager enable/disable */\n#define VQAMCGA_ON   1  /* MCGA enable/disable */\n#define VQAXMODE_ON  0  /* Xmode enable/disable */\n#define VQAVESA_ON   0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2 1  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3 1  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2 1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4 1  /* 4x4 block decode enable/disable */\n#else\n#define VQAVOC_ON    1  /* Enable VOC file override */\n#define\tVQAMONO_ON   1  /* Mono display output enable/disable */\n#define VQAAUDIO_ON  0  /* Audio playback enable/disable */\n#define VQAVIDEO_ON  0  /* Video manager enable/disable */\n#define VQAMCGA_ON   1  /* MCGA enable/disable */\n#define VQAXMODE_ON  0  /* Xmode enable/disable */\n#define VQAVESA_ON   0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2 1  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3 1  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2 1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4 1  /* 4x4 block decode enable/disable */\n#endif\n\n/*---------------------------------------------------------------------------\n * GENERAL CONSTANT DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* Playback modes. */\n#define VQAMODE_RUN  0 /* Run the movie through the end. */\n#define VQAMODE_WALK 1 /* Draw the next frame then return. */\n#define VQAMODE_STOP 2 /* Stop the movie. */\n\n/* Playback timer methods */\n#define VQA_TMETHOD_DEFAULT -1 /* Use default timer method. */\n#define\tVQA_TMETHOD_DOS      1 /* DOS timer method */\n#define\tVQA_TMETHOD_INT      2 /* Interrupt timer method */\n#define\tVQA_TMETHOD_AUDIO    3 /* Audio timer method */\n\n/* Error/condition values */\n#define\tVQAERR_EOF      -1  /* Valid end of file */\n#define VQAERR_OPEN     -2  /* Unable to open */\n#define\tVQAERR_READ     -3  /* Read error */\n#define VQAERR_WRITE    -4  /* Write error */\n#define VQAERR_SEEK     -5  /* Seek error */\n#define VQAERR_NOTVQA   -6  /* Not a valid VQA file. */\n#define VQAERR_NOMEM    -7  /* Unable to allocate memory */\n#define\tVQAERR_NOBUFFER -8  /* No buffer avail for load/draw */\n#define\tVQAERR_NOT_TIME -9  /* Not time for frame yet */\n#define\tVQAERR_SLEEPING -10 /* Function is in a sleep state */\n#define VQAERR_VIDEO    -11 /* Video related error. */\n#define VQAERR_AUDIO    -12 /* Audio related error. */\n\n/* Memory limits */\n#define\tVQA_NUM_MAXRATES 5  /* Number of max rates in the Config struct */\n#define\tVQA_TIMETICKS    60 /* Clock ticks per second */\n\n/*---------------------------------------------------------------------------\n * STRUCTURES AND RELATED DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* VQAConfig: Player configuration structure\n *\n * DrawerCallback - User routine for Drawer to call each frame (NULL = none)\n * Vmode          - Requested Video mode (May be promoted).\n * VBIBit         - Vertical blank bit polarity.\n * ImageBuf       - Pointer to caller's buffer for the Drawer to use as its\n *                  ImageBuf; NULL = player will allocate its own, if\n *                  VQACFGF_BUFFER is set in DrawFlags.\n * ImageWidth     - Width of Image buffer.\n * ImageHeight    - Height of Image buffer.\n * X1             - Draw window X coordinate (-1 = Center).\n * Y1             - Draw window Y coordinate (-1 = Center).\n * FrameRate      - Desired frames per second (-1 = use VQA header's value).\n * DrawRate       - Desired drawing frame rate; allows the Drawer to draw at\n *                  a separate rate from the Loader.\n * TimerMethod    - Timer method to use during playback.\n * DrawFlags      - Bits control various special drawing options. (See below)\n * OptionFlags    - Bits control various special misc options. (See below)\n * NumFrameBufs   - Desired number of frame buffers. (Default = 6)\n * NumCBBufs      - Desired number of codebook buffers. (Default = 3)\n * VocFile        - Name of VOC file to play instead of VQA audio track.\n * AudioBuf       - Pointer to audio buffer.\n * AudioBufSize   - Size of audio buffer. (Default = 32768)\n * AudioRate      - Audio data playback rate (-1 = use 22050 scaled to the\n *                  frame rate)\n * Volume         - Audio playback volume. (0x7FFF = max)\n * HMIBufSize     - Desired HMI buffer size. (Default = 2000)\n * DigiHandle     - Handle to an initialized sound driver. (-1 = none)\n * DigiCard       - HMI ID of card to use. (0 = none, -1 = auto-detect)\n * DigiPort       - Audio port address. (-1 = auto-detect)\n * DigiIRQ        - Audio IRQ. (-1 = auto-detect)\n * DigiDMA        - Audio DMA channel. (-1 = auto-detect)\n * MaxRate        - Fixed rate playback table.\n */\ntypedef struct _VQAConfig {\n\tvoid (*DrawerCallback)(unsigned char *screen, long framenum);\n\tlong          Vmode;\n\tlong          VBIBit;\n\tunsigned char *ImageBuf;\n\tlong          ImageWidth;\n\tlong          ImageHeight;\n\tlong          X1,Y1;\n\tlong          FrameRate;\n\tlong          DrawRate;\n\tlong          TimerMethod;\n\tlong          DrawFlags;\n\tlong          OptionFlags;\n\tlong          NumFrameBufs;\n\tlong          NumCBBufs;\n\tchar          *VocFile;\n\tunsigned char *AudioBuf;\n\tlong          AudioBufSize;\n\tlong          AudioRate;\n\tlong          Volume;\n\tlong          HMIBufSize;\n\tlong          DigiHandle;\n\tlong          DigiCard;\n\tlong          DigiPort;\n\tlong          DigiIRQ;\n\tlong          DigiDMA;\n} VQAConfig;\n\n/* Drawer Configuration flags (DrawFlags) */\n#define\tVQACFGB_BUFFER   0 /* Buffer UnVQ enable */\n#define\tVQACFGB_NODRAW   1 /* Drawing disable */\n#define VQACFGB_NOSKIP   2 /* Disable frame skipping. */\n#define\tVQACFGB_VRAMCB   3 /* XMode VRAM copy enable */\n#define VQACFGB_ORIGIN   4 /* 0,0 origin position */\n#define\tVQACFGB_SCALEX2  6 /* Scale X2 enable (VESA 320x200 to 640x400) */\n#define\tVQACFGF_BUFFER   (1<<VQACFGB_BUFFER)\n#define\tVQACFGF_NODRAW   (1<<VQACFGB_NODRAW)\n#define\tVQACFGF_NOSKIP   (1<<VQACFGB_NOSKIP)\n#define\tVQACFGF_VRAMCB   (1<<VQACFGB_VRAMCB)\n#define\tVQACFGF_ORIGIN   (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPLEFT  (0<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPRIGHT (1<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTRIGHT (2<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTLEFT  (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_SCALEX2  (1<<VQACFGB_SCALEX2)\n\n/* Options Configuration (OptionFlags) */\n#define\tVQAOPTB_AUDIO   0 /* Audio enable */\n#define\tVQAOPTB_STEP    1 /* Single step enable */\n#define\tVQAOPTB_MONO    2 /* Mono output enable */\n#define\tVQAOPTB_FINF    3 /* Frame info chunk enable */\n#define\tVQAOPTB_SLOWPAL 4 /* Slow palette enable */\n#define VQAOPTB_HMIINIT 5 /* HMI already initialized by client. */\n#define\tVQAOPTF_AUDIO   (1<<VQAOPTB_AUDIO)\n#define\tVQAOPTF_STEP    (1<<VQAOPTB_STEP)\n#define\tVQAOPTF_MONO    (1<<VQAOPTB_MONO)\n#define\tVQAOPTF_FINF    (1<<VQAOPTB_FINF)\n#define\tVQAOPTF_SLOWPAL (1<<VQAOPTB_SLOWPAL)\n#define VQAOPTF_HMIINIT (1<<VQAOPTB_HMIINIT)\n\n/* VQAInfo: Information about the VQA movie.\n *\n * NumFrames   - The number of frames contained in the movie.\n * ImageHeight - Height of image in pixels.\n * ImageWidth  - Width of image in pixels.\n */\ntypedef struct _VQAInfo {\n\tlong NumFrames;\n\tlong ImageWidth;\n\tlong ImageHeight;\n} VQAInfo;\n\n/* VQAStatistics: Statistics about the VQA movie played.\n *\n * StartTime     - Time movie started.\n * EndTime       - Time movie stoped.\n * FramesLoaded  - Total number of frames loaded.\n * FramesDrawn   - Total number of frames drawn.\n * FramesSkipped - Total number of frames skipped.\n * MaxFrameSize  - Size of largest frame.\n * SamplesPlayed - Number of sample bytes played.\n * MemUsed       - Total bytes used. (Low memory)\n */\ntypedef struct _VQAStatistics {\n\tlong          StartTime;\n\tlong          EndTime;\n\tlong          FramesLoaded;\n\tlong          FramesDrawn;\n\tlong          FramesSkipped;\n\tlong          MaxFrameSize;\n\tunsigned long SamplesPlayed;\n\tunsigned long MemUsed;\n} VQAStatistics;\n\n/* VQAHandle: VQA file handle. (Must be obtained by calling VQA_Alloc()\n *            and freed through VQA_Free(). This is the only legal way\n *            to obtain and dispose of a VQAHandle.\n *\n * VQAStream - Something meaningful to the stream manager. (See DOCS)\n */\ntypedef struct _VQAHandle {\n\tunsigned long VQAStream;\n} VQAHandle;\n\n/* Possible stream command values */\n#define VQACMD_INIT    1 /* Prepare the stream for a session */\n#define VQACMD_CLEANUP 2 /* Terminate stream session */\n#define VQACMD_OPEN    3 /* Open stream */\n#define VQACMD_CLOSE   4 /* Close stream */\n#define VQACMD_READ    5 /* Read bytes from stream */\n#define VQACMD_WRITE   6 /* Write bytes to stream */\n#define VQACMD_SEEK    7 /* Seek on stream */\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\nvoid VQA_INIConfig(VQAConfig *config);\nvoid VQA_DefaultConfig(VQAConfig *config);\n\nVQAHandle *VQA_Alloc(void);\nvoid VQA_Free(VQAHandle *vqa);\nvoid VQA_InitAsDOS(VQAHandle *vqa);\nvoid VQA_Init(VQAHandle *vqa, unsigned long(*streamhandler)(VQAHandle *vqa,\n\t\tlong action, void *buffer, long nbytes));\n\nlong VQA_Open(VQAHandle *vqa, char const *filename, VQAConfig *config);\nvoid VQA_Close(VQAHandle *vqa);\nlong VQA_Play(VQAHandle *vqa, long mode);\n\nvoid VQA_GetInfo(VQAHandle *vqa, VQAInfo *info);\nvoid VQA_GetStats(VQAHandle *vqa, VQAStatistics *stats);\nchar *VQA_Version(void);\nchar *VQA_IDString(void);\n\n#endif  /* VQAPLAY_H */\n\n"
  },
  {
    "path": "VQ/VQA32/VQAPLAY.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAPLAY_H\n#define VQAPLAY_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqaplay.h\n*\n* DESCRIPTION\n*      VQAPlay library definitions.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 10, 1995\n*\n****************************************************************************/\n\n/*---------------------------------------------------------------------------\n * CONDITIONAL COMPILATION FLAGS\n *-------------------------------------------------------------------------*/\n\n#ifdef __WATCOMC__\n#define VQASTANDALONE 0  /* Stand alone player */\n#define VQAVOC_ON     0  /* Enable VOC file override */\n#define\tVQAMONO_ON    0  /* Mono display output enable/disable */\n#define VQAAUDIO_ON   1  /* Audio playback enable/disable */\n#define VQAVIDEO_ON   0  /* Video manager enable/disable */\n#define VQAMCGA_ON    1  /* MCGA enable/disable */\n#define VQAXMODE_ON   0  /* Xmode enable/disable */\n#define VQAVESA_ON    0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2  1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4  0  /* 4x4 block decode enable/disable */\n#define VQAWOOFER_ON  0\n#else\n#define VQASTANDALONE 0  /* Stand alone player */\n#define VQAVOC_ON     0  /* Enable VOC file override */\n#define\tVQAMONO_ON    1  /* Mono display output enable/disable */\n#define VQAAUDIO_ON   0  /* Audio playback enable/disable */\n#define VQAVIDEO_ON   0  /* Video manager enable/disable */\n#define VQAMCGA_ON    1  /* MCGA enable/disable */\n#define VQAXMODE_ON   0  /* Xmode enable/disable */\n#define VQAVESA_ON    0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2  1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4  0  /* 4x4 block decode enable/disable */\n#define VQAWOOFER_ON  0\n#endif\n\n\n/*---------------------------------------------------------------------------\n * GENERAL CONSTANT DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* Playback modes. */\n#define VQAMODE_RUN   0  /* Run the movie through the end. */\n#define VQAMODE_WALK  1  /* Draw the next frame then return. */\n#define VQAMODE_PAUSE 2  /* Suspend movie playback. */\n#define VQAMODE_STOP  3  /* Stop the movie. */\n\n/* Playback timer methods */\n#define VQA_TMETHOD_DEFAULT -1 /* Use default timer method. */\n#define\tVQA_TMETHOD_DOS      1 /* DOS timer method */\n#define\tVQA_TMETHOD_INT      2 /* Interrupt timer method */\n#define\tVQA_TMETHOD_AUDIO    3 /* Audio timer method */\n\n#define\tVQA_TIMETICKS 60 /* Clock ticks per second */\n\n/* Error/Status conditions */\n#define VQAERR_NONE      0  /* No error */\n#define\tVQAERR_EOF      -1  /* Valid end of file */\n#define VQAERR_OPEN     -2  /* Unable to open */\n#define\tVQAERR_READ     -3  /* Read error */\n#define VQAERR_WRITE    -4  /* Write error */\n#define VQAERR_SEEK     -5  /* Seek error */\n#define VQAERR_NOTVQA   -6  /* Not a valid VQA file. */\n#define VQAERR_NOMEM    -7  /* Unable to allocate memory */\n#define\tVQAERR_NOBUFFER -8  /* No buffer avail for load/draw */\n#define\tVQAERR_NOT_TIME -9  /* Not time for frame yet */\n#define\tVQAERR_SLEEPING -10 /* Function is in a sleep state */\n#define VQAERR_VIDEO    -11 /* Video related error. */\n#define VQAERR_AUDIO    -12 /* Audio related error. */\n#define VQAERR_PAUSED   -13 /* In paused state. */\n\n/* Event flags. */\n#define VQAEVENT_PALETTE (1<<0)\n#define VQAEVENT_SYNC    (1<<1)\n\n\n/*---------------------------------------------------------------------------\n * STRUCTURES AND RELATED DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* VQAConfig: Player configuration structure\n *\n * DrawerCallback - User routine for Drawer to call each frame (NULL = none)\n * EventHandler   - User routine for notification to client of events.\n * NotifyFlags    - User specified events to be notified about.\n * Vmode          - Requested Video mode (May be promoted).\n * VBIBit         - Vertical blank bit polarity.\n * ImageBuf       - Pointer to caller's buffer for the Drawer to use as its\n *                  ImageBuf; NULL = player will allocate its own, if\n *                  VQACFGF_BUFFER is set in DrawFlags.\n * ImageWidth     - Width of Image buffer.\n * ImageHeight    - Height of Image buffer.\n * X1             - Draw window X coordinate (-1 = Center).\n * Y1             - Draw window Y coordinate (-1 = Center).\n * FrameRate      - Desired frames per second (-1 = use VQA header's value).\n * DrawRate       - Desired drawing frame rate; allows the Drawer to draw at\n *                  a separate rate from the Loader.\n * TimerMethod    - Timer method to use during playback.\n * DrawFlags      - Bits control various special drawing options. (See below)\n * OptionFlags    - Bits control various special misc options. (See below)\n * NumFrameBufs   - Desired number of frame buffers. (Default = 6)\n * NumCBBufs      - Desired number of codebook buffers. (Default = 3)\n * VocFile        - Name of VOC file to play instead of VQA audio track.\n * AudioBuf       - Pointer to audio buffer.\n * AudioBufSize   - Size of audio buffer. (Default = 32768)\n * AudioRate      - Audio data playback rate (-1 = use samplerate scaled\n *                  to the frame rate)\n * Volume         - Audio playback volume. (0x7FFF = max)\n * HMIBufSize     - Desired HMI buffer size. (Default = 2000)\n * DigiHandle     - Handle to an initialized sound driver. (-1 = none)\n * DigiCard       - HMI ID of card to use. (0 = none, -1 = auto-detect)\n * DigiPort       - Audio port address. (-1 = auto-detect)\n * DigiIRQ        - Audio IRQ. (-1 = auto-detect)\n * DigiDMA        - Audio DMA channel. (-1 = auto-detect)\n * Language       - Language identifier. (Not used)\n * CapFont        - Pointer to font to use for subtitle text captions.\n * EVAFont        - Pointer to font to use for E.V.A text cations. (For C&C)\n */\ntypedef struct _VQAConfig {\n\tlong          (*DrawerCallback)(unsigned char *screen, long framenum);\n\tlong          (*EventHandler)(unsigned long event,void *buffer,long nbytes);\n\tunsigned long NotifyFlags;\n\tlong          Vmode;\n\tlong          VBIBit;\n\tunsigned char *ImageBuf;\n\tlong          ImageWidth;\n\tlong          ImageHeight;\n\tlong          X1,Y1;\n\tlong          FrameRate;\n\tlong          DrawRate;\n\tlong          TimerMethod;\n\tlong          DrawFlags;\n\tlong          OptionFlags;\n\tlong          NumFrameBufs;\n\tlong          NumCBBufs;\n\tchar          *VocFile;\n\tunsigned char *AudioBuf;\n\tlong          AudioBufSize;\n\tlong          AudioRate;\n\tlong          Volume;\n\tlong          HMIBufSize;\n\tlong          DigiHandle;\n\tlong          DigiCard;\n\tlong          DigiPort;\n\tlong          DigiIRQ;\n\tlong          DigiDMA;\n\tlong          Language;\n\tchar          *CapFont;\n\tchar          *EVAFont; /* For C&C Only */\n} VQAConfig;\n\n/* Drawer Configuration flags (DrawFlags) */\n#define\tVQACFGB_BUFFER   0 /* Buffer UnVQ enable */\n#define\tVQACFGB_NODRAW   1 /* Drawing disable */\n#define VQACFGB_NOSKIP   2 /* Disable frame skipping. */\n#define\tVQACFGB_VRAMCB   3 /* XMode VRAM copy enable */\n#define VQACFGB_ORIGIN   4 /* 0,0 origin position */\n#define\tVQACFGB_SCALEX2  6 /* Scale X2 enable (VESA 320x200 to 640x400) */\n#define VQACFGB_WOOFER   7\n#define\tVQACFGF_BUFFER   (1<<VQACFGB_BUFFER)\n#define\tVQACFGF_NODRAW   (1<<VQACFGB_NODRAW)\n#define\tVQACFGF_NOSKIP   (1<<VQACFGB_NOSKIP)\n#define\tVQACFGF_VRAMCB   (1<<VQACFGB_VRAMCB)\n#define\tVQACFGF_ORIGIN   (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPLEFT  (0<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPRIGHT (1<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTRIGHT (2<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTLEFT  (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_SCALEX2  (1<<VQACFGB_SCALEX2)\n#define VQACFGF_WOOFER   (1<<VQACFGB_WOOFER)\n\n/* Options Configuration (OptionFlags) */\n#define\tVQAOPTB_AUDIO    0 /* Audio enable. */\n#define\tVQAOPTB_STEP     1 /* Single step enable. */\n#define\tVQAOPTB_MONO     2 /* Mono output enable. */\n#define VQAOPTB_PALOFF   3 /* Palette set disable. */\n#define\tVQAOPTB_SLOWPAL  4 /* Slow palette enable. */\n#define VQAOPTB_HMIINIT  5 /* HMI already initialized by client. */\n#define VQAOPTB_ALTAUDIO 6 /* Use alternate audio track. */\n#define VQAOPTB_CAPTIONS 7 /* Show captions. */\n#define VQAOPTB_EVA      8 /* Show EVA text (For C&C only) */\n#define\tVQAOPTF_AUDIO    (1<<VQAOPTB_AUDIO)\n#define\tVQAOPTF_STEP     (1<<VQAOPTB_STEP)\n#define\tVQAOPTF_MONO     (1<<VQAOPTB_MONO)\n#define VQAOPTF_PALOFF   (1<<VQAOPTB_PALOFF)\n#define\tVQAOPTF_SLOWPAL  (1<<VQAOPTB_SLOWPAL)\n#define VQAOPTF_HMIINIT  (1<<VQAOPTB_HMIINIT)\n#define\tVQAOPTF_ALTAUDIO (1<<VQAOPTB_ALTAUDIO)\n#define VQAOPTF_CAPTIONS (1<<VQAOPTB_CAPTIONS)\n#define VQAOPTF_EVA      (1<<VQAOPTB_EVA) /* For C&C only */\n\n\n/* VQAInfo: Information about the VQA movie.\n *\n * NumFrames   - The number of frames contained in the movie.\n * ImageHeight - Height of image in pixels.\n * ImageWidth  - Width of image in pixels.\n * ImageBuf    - Pointer to the image buffer VQA draw into.\n */\ntypedef struct _VQAInfo {\n\tlong NumFrames;\n\tlong ImageWidth;\n\tlong ImageHeight;\n\tunsigned char *ImageBuf;\n} VQAInfo;\n\n\n/* VQAStatistics: Statistics about the VQA movie played.\n *\n * StartTime     - Time movie started.\n * EndTime       - Time movie stoped.\n * FramesLoaded  - Total number of frames loaded.\n * FramesDrawn   - Total number of frames drawn.\n * FramesSkipped - Total number of frames skipped.\n * MaxFrameSize  - Size of largest frame.\n * SamplesPlayed - Number of sample bytes played.\n * MemUsed       - Total bytes used. (Low memory)\n */\ntypedef struct _VQAStatistics {\n\tlong          StartTime;\n\tlong          EndTime;\n\tlong          FramesLoaded;\n\tlong          FramesDrawn;\n\tlong          FramesSkipped;\n\tlong          MaxFrameSize;\n\tunsigned long SamplesPlayed;\n\tunsigned long MemUsed;\n} VQAStatistics;\n\n\n/* VQAHandle: VQA file handle. (Must be obtained by calling VQA_Alloc()\n *            and freed through VQA_Free(). This is the only legal way\n *            to obtain and dispose of a VQAHandle.\n *\n * VQAio - Something meaningful to the IO manager. (See DOCS)\n */\ntypedef struct _VQAHandle {\n\tunsigned long VQAio;\n} VQAHandle;\n\n/* Possible IO command values */\n#define VQACMD_INIT    1 /* Prepare the IO for a session */\n#define VQACMD_CLEANUP 2 /* Terminate IO session */\n#define VQACMD_OPEN    3 /* Open file */\n#define VQACMD_CLOSE   4 /* Close file */\n#define VQACMD_READ    5 /* Read bytes */\n#define VQACMD_WRITE   6 /* Write bytes */\n#define VQACMD_SEEK    7 /* Seek */\n\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n/* Configuration routines. */\nvoid VQA_INIConfig(VQAConfig *config);\nvoid VQA_DefaultConfig(VQAConfig *config);\n\n/* Handle manipulation routines. */\nVQAHandle *VQA_Alloc(void);\nvoid VQA_Free(VQAHandle *vqa);\nvoid VQA_InitAsDOS(VQAHandle *vqa);\nvoid VQA_Init(VQAHandle *vqa, long(*iohandler)(VQAHandle *vqa, long action,\n\t\tvoid *buffer, long nbytes));\n\n/* File routines. */\nlong VQA_Open(VQAHandle *vqa, char const *filename, VQAConfig *config);\nvoid VQA_Close(VQAHandle *vqa);\nlong VQA_Play(VQAHandle *vqa, long mode);\nlong VQA_SeekFrame(VQAHandle *vqa, long frame, long fromwhere);\n\n/* Information/statistics access routines. */\nvoid VQA_GetInfo(VQAHandle *vqa, VQAInfo *info);\nvoid VQA_GetStats(VQAHandle *vqa, VQAStatistics *stats);\nchar *VQA_Version(void);\nchar *VQA_IDString(void);\n\n#endif /* VQAPLAY_H */\n\n"
  },
  {
    "path": "VQ/VQA32/VQAPLAY.I",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PROJECT\n;*     VQAPlay 32 library.\n;*\n;* FILE\n;*     vqaplay.i\n;*\n;* DESCRIPTION\n;*      VQA player definitions.\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 30, 1995\n;*\n;****************************************************************************\n\n;*---------------------------------------------------------------------------\n;* CONDITIONAL COMPILATION FLAGS\n;*---------------------------------------------------------------------------\n\n\tIF\tPHARLAP_TNT\n\nVQASTANDALONE\tEQU\t0\t;Stand alone player\nVQAMONO_ON\tEQU\t1\t;Mono display output enable/disable\nVQAAUDIO_ON\tEQU\t0\t;Audio playback enable/disable\nVQAVIDEO_ON\tEQU\t0\t;Video manager enable/disable\nVQAMCGA_ON\tEQU\t1\t;MCGA enable/disable\nVQAXMODE_ON\tEQU\t0\t;Xmode enable/disable\nVQAVESA_ON\tEQU\t0\t;VESA enable/disable\nVQABLOCK_2X2\tEQU\t0\t;2x2 block decode enable/disable\nVQABLOCK_2X3\tEQU\t0\t;2x3 block decode enable/disable\nVQABLOCK_4X2\tEQU\t1\t;4x2 block decode enable/disable\nVQABLOCK_4X4\tEQU\t0\t;4x4 block decode enable/disable\nVQABLOCK_WOOFER\tEQU\t0\n\n\tELSE\n\nVQASTANDALONE\tEQU\t0\t;Stand alone player\nVQAMONO_ON\tEQU\t0\t;Mono display output enable/disable\nVQAAUDIO_ON\tEQU\t1\t;Audio playback enable/disable\nVQAVIDEO_ON\tEQU\t0\t;Video manager enable/disable\nVQAMCGA_ON\tEQU\t1\t;MCGA enable/disable\nVQAXMODE_ON\tEQU\t0\t;Xmode enable/disable\nVQAVESA_ON\tEQU\t0\t;VESA enable/disable\nVQABLOCK_2X2\tEQU\t0\t;2x2 block decode enable/disable\nVQABLOCK_2X3\tEQU\t0\t;2x3 block decode enable/disable\nVQABLOCK_4X2\tEQU\t1\t;4x2 block decode enable/disable\nVQABLOCK_4X4\tEQU\t0\t;4x4 block decode enable/disable\nVQABLOCK_WOOFER\tEQU\t0\n\n\tENDIF\n"
  },
  {
    "path": "VQ/VQA32/VQAPLAYP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAPLAYP_H\n#define VQAPLAYP_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqaplayp.h\n*\n* DESCRIPTION\n*     VQAPlay private library definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*     Bill Randolph\n*\n* DATE\n*     August 21, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\video.h>\n#include <vqm32\\soscomp.h>\n#include <vqm32\\captoken.h>\n#include \"vqafile.h\"\n#include \"vqaplay.h\"\n#include \"caption.h\"\n\n#if(VQAAUDIO_ON)\n#include \"sos.h\"\n#endif\n\n/*---------------------------------------------------------------------------\n * GENERAL CONSTANT DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* Internal library version. */\n#define VQA_VERSION \"2.41\"\n#define VQA_DATE    __DATE__\" \"__TIME__\n\n#define VQA_IDSTRING \"VQA32 \"VQA_VERSION\" (\"VQA_DATE\")\"\n#define VQA_REQUIRES \"VQM32 2.12 or better.\"\n\n/* Block dimensions macro and identifiers. */\n#define BLOCK_DIM(a,b) (((a&0xFF)<<8)|(b&0xFF))\n#define BLOCK_2X2 BLOCK_DIM(2,2)\n#define BLOCK_2X3 BLOCK_DIM(2,3)\n#define BLOCK_4X2 BLOCK_DIM(4,2)\n#define BLOCK_4X4 BLOCK_DIM(4,4)\n\n/* Memory limits */\n#define\tVQA_MAX_CBBUFS    10 /* Maximum number of codebook buffers */\n#define\tVQA_MAX_FRAMEBUFS 30 /* Maximum number of frame buffers */\n\n/* Special Constants */\n#define\tVQA_MASK_POINTER 0x8000 /* Pointer value to use for masking. */\n\n\n/*---------------------------------------------------------------------------\n * STRUCTURES AND RELATED DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* ChunkHeader: IFF chunk identifier header.\n *\n * id   - 4 Byte chunk id.\n * size - Size of chunk.\n */\ntypedef struct _ChunkHeader {\n\tunsigned long id;\n\tunsigned long size;\n} ChunkHeader;\n\n\n/* ZAPHeader: ZAP audio compression header. NOTE: If the uncompressed size\n *            and the compressed size are equal then the audio frame is RAW\n *            (NOT COMPRESSED).\n *\n * UnCompSize - Uncompressed size in bytes.\n * CompSize   - Compressed size in bytes.\n */\ntypedef struct _ZAPHeader {\n\tunsigned short UnCompSize;\n\tunsigned short CompSize;\n} ZAPHeader;\n\n\n/* VQACBNode: A circular list of codebook buffers, used by the load task.\n *            If the data is compressed, it is loaded into the end of the\n *            buffer and the compression flags is set. Otherwise the data\n *            is loaded into the start of the buffer.\n *            (Make sure this structure's size is always DWORD aligned.)\n *\n * Buffer   - Pointer to Codebook data.\n * Next     - Pointer to next VQACBNode in the codebook list.\n * Flags    - Used by the drawer to tell if certain operations have been\n *            performed on this codebook, such as downloading to VRAM,\n *            or pre-scaling it. This field is cleared by the Loader when a\n *            new codebook is loaded.\n * CBOffset - Offset into the buffer of the compressed data.\n */\ntypedef struct _VQACBNode {\n\tunsigned char     *Buffer;\n\tstruct _VQACBNode *Next;\n\tunsigned long     Flags;\n\tunsigned long     CBOffset;\n} VQACBNode;\n\n/* VQACBNode flags */\n#define\tVQACBB_DOWNLOADED 0 /* Download codebook to VRAM (XMODE VRAM) */\n#define VQACBB_CBCOMP     1 /* Codebook is compressed */\n#define\tVQACBF_DOWNLOADED (1<<VQACBB_DOWNLOADED)\n#define\tVQACBF_CBCOMP     (1<<VQACBB_CBCOMP)\n\n\n/* VQAFrameNode: A circular list of frame buffers, filled in by the load\n *               task. If the data is compressed, it is loaded into the end\n *               of the buffer and the compress flag is set. Otherwise, it's\n *               loaded into the start of the buffer.\n *               (Make sure this structure's size is always DWORD aligned.)\n *\n * Pointers    - Pointer to the vector pointer data.\n * Codebook    - Pointer to VQACBNode list entry for this frame.\n * Palette     - Pointer to an array of palette colors (R,G,B).\n * Next        - Pointer to the next entry in the Frame Buffer List.\n * Flags       - Inter-process communication flags for this frame (see below)\n *               set by Loader, cleared by Flipper.\n * FrameNum    - Number of this frame in the animation.\n * PtrOffset   - Offset into buffer of the compressed vector pointer data.\n * PalOffset   - Offset into buffer of the compressed palette data.\n * PaletteSize - Size of the palette for this frame (in bytes).\n */\ntypedef struct _VQAFrameNode {\n\tunsigned char        *Pointers;\n\tVQACBNode            *Codebook;\n\tunsigned char        *Palette;\n\tstruct _VQAFrameNode *Next;\n\tunsigned long        Flags; \n\tlong                 FrameNum;\n\tlong                 PtrOffset;\n\tlong                 PalOffset;\n\tlong                 PaletteSize;\n} VQAFrameNode;\n\n/* FrameNode flags */\n#define\tVQAFRMB_LOADED  0 /* Frame loaded */\n#define\tVQAFRMB_KEY     1 /* Key Frame (must be drawn) */\n#define\tVQAFRMB_PALETTE 2 /* Palette needs set */\n#define VQAFRMB_PALCOMP 3 /* Palette is compressed */\n#define VQAFRMB_PTRCOMP 4 /* Vector pointer data is compressed */\n#define\tVQAFRMF_LOADED  (1<<VQAFRMB_LOADED)\n#define\tVQAFRMF_KEY     (1<<VQAFRMB_KEY)\n#define\tVQAFRMF_PALETTE (1<<VQAFRMB_PALETTE)\n#define\tVQAFRMF_PALCOMP (1<<VQAFRMB_PALCOMP)\n#define\tVQAFRMF_PTRCOMP (1<<VQAFRMB_PTRCOMP)\n\n\n/* VQALoader: Data needed exclusively by the Loader.\n *            (Make sure this structure's size is always DWORD aligned.)\n *\n * CurCB         - Pointer to the current codebook node to load data into.\n * FullCB        - Pointer to the last fully-loaded codebook node.\n * CurFrame      - Pointer to the current frame node to load data into.\n * NumPartialCB  - Number of partial codebooks accumulated.\n * PartialCBSize - Size of partial codebook (LCW'd or not), in bytes\n * CurFrameNum   - The number of the frame being loaded by the Loader.\n * LastCBFrame   - Last frame in the animation that contains a partial CB\n * LastFrameNum  - Number of the last loaded frame\n * WaitsOnDrawer - Number of wait states Loader hits waiting on the Drawer\n * WaitsOnAudio  - Number of wait states Loader hits waiting on HMI\n * FrameSize     - Size of the last frame in bytes.\n * MaxFrameSize  - Size of the largest frame in the animation.\n * CurChunkHdr   - Chunk header of the chunk currently being processed.\n */\ntypedef struct _VQALoader {\n\tVQACBNode    *CurCB;\n\tVQACBNode    *FullCB;\n\tVQAFrameNode *CurFrame;\n\tlong         NumPartialCB;\n\tlong         PartialCBSize;\n\tlong         CurFrameNum;\n\tlong         LastCBFrame;\n\tlong         LastFrameNum;\n\tlong         WaitsOnDrawer;\n\tlong         WaitsOnAudio;\n\tlong         FrameSize;\n\tlong         MaxFrameSize;\n\tChunkHeader  CurChunkHdr;\n} VQALoader;\n\n\n/* VQADrawer: Data needed exclusively by the Drawer.\n *            (Make sure this structure's size is always DWORD aligned.)\n *\n * CurFrame       - Pointer to the current frame to draw.\n * Flags          - Flags for the draw routines (IE: VQADRWF_SETPAL)\n * Display        - Pointer to DisplayInfo structure for active video mode.\n * ImageBuf       - Buffer to un-vq into, must be DWORD aligned.\n * ImageWidth     - Width of Image buffer (in pixels).\n * ImageHeight    - Height of Image buffer (in pixels).\n * X1,Y1,X2,Y2    - Coordinates of image corners (in pixels).\n * ScreenOffset   - Offset into screen memory, for centering small images.\n * CurPalSize     - Size of the current palette in bytes.\n * Palette_24     - Copy of the last-loaded palette\n * Palette_15     - 15-bit version of Palette_24, for 32K-color modes\n * BlocksPerRow   - # of VQ blocks per row for this resolution/block width.\n * NumRows        - # of rows of VQ blocks for this resolution/block height.\n * NumBlocks      - Total number of blocks in the image.\n * MaskStart      - Pointer index of start of mask rectangle.\n * MaskWidth      - Width of mask rectangle, in blocks.\n * MaskHeight     - Height of mask rectangle, in blocks.\n * LastTime       - The time when that last frame was drawn.\n * LastFrame      - The number of the last frame selected.\n * LastFrameNum   - Number of the last frame drawn.\n * DesiredFrame   - The number of the frame that should be drawn.\n * NumSkipped     - Number of frames skipped.\n * WaitsOnFlipper - Number of wait states Drawer hits waiting on the Flipper.\n * WaitsOnLoader  - Number of wait states Drawer hits waiting on the Loader.\n */\ntypedef struct _VQADrawer {\n\tVQAFrameNode  *CurFrame;\n\tunsigned long Flags;\n\tDisplayInfo   *Display;\n\tunsigned char *ImageBuf;\n\tlong          ImageWidth;\n\tlong          ImageHeight;\n\tlong          X1,Y1,X2,Y2;\n\tlong          ScreenOffset;\n\tlong          CurPalSize;\n\tunsigned char Palette_24[768];\n\tunsigned char Palette_15[512];\n\tlong          BlocksPerRow;\n\tlong          NumRows;\n\tlong          NumBlocks;\n\tlong          MaskStart;\n\tlong          MaskWidth;\n\tlong          MaskHeight;\n\tlong          LastTime;\n\tlong          LastFrame;\n\tlong          LastFrameNum;\n\tlong          DesiredFrame;\n\tlong          NumSkipped;\n\tlong          WaitsOnFlipper;\n\tlong          WaitsOnLoader;\n} VQADrawer;\n\n/* Drawer flags */\n#define\tVQADRWB_SETPAL 0  /* Set palette */\n#define\tVQADRWF_SETPAL (1<<VQADRWB_SETPAL)\n\n\n/* VQAFlipper: Data needed exclusively by the page-flipper.\n *             (Make sure this structure's size is always DWORD aligned.)\n *\n * CurFrame     - Pointer to current flipper frame.\n * LastFrameNum - Number of last flipped frame\n * pad          - DWORD alignment padding.\n */\ntypedef struct _VQAFlipper {\n\tVQAFrameNode *CurFrame;\n\tlong         LastFrameNum;\n} VQAFlipper;\n\n\n#if(VQAAUDIO_ON)\n\n#ifdef __WATCOMC__\n#pragma pack(4);\n#endif\n\n/* VQAAudio: Data needed exclusively by audio playback.\n *           (Make sure this structure's size is always DWORD aligned.)\n *\n * Buffer         - Pointer to the audio buffer.\n * AudBufPos      - Current audio buffer position, for copying data in buffer.\n * IsLoaded       - Inter-process communication flag:\n *                  0 = is loadable, 1 = is not. Loader sets it when it\n *                  loads, audio callback clears it when it plays one.\n * NumAudBlocks   - Number of HMI blocks in the audio buffer.\n * CurBlock       - Current audio block\n * NextBlock      - Next audio block\n * TempBuf        - Pointer to temp buffer for loading/decompressing audio\n *                  data.\n * TempBufLen     - Number of bytes loaded into temp buffer.\n * TempBufSize    - Size of temp buffer in bytes.\n * Flags          - Various audio flags. (See below)\n * PlayPosition   - HMI's current buffer position.\n * SamplesPlayed  - Total samples played.\n * NumSkipped     - Count of buffers missed.\n * SampleRate     - Recorded sampling rate of the track.\n * Channels       - Number of channels in the track.\n * BitsPerSample  - Bit resolution size of sample (8,16)\n * BytesPerSec    - Recorded data transfer for one second.\n * DigiHandle     - HMI digital device handle.\n * SampleHandle   - HMI sample handle.\n * DigiTimer      - HMI digital fill handler timer handle.\n * sSOSSampleData - HMI sample structure.\n * ADPCM_Info     - ADPCM decompression information structure.\n * DigiCaps       - HMI sound card digital capabilities.\n * DigiHardware   - HMI sound card digital hardware settings.\n * sSOSInitDriver - HMI driver initialization structure.\n */\ntypedef struct _VQAAudio {\n\tunsigned char      *Buffer;\n\tunsigned long      AudBufPos;\n\tshort              *IsLoaded;\n\tunsigned long      NumAudBlocks;\n\tunsigned long      CurBlock;\n\tunsigned long      NextBlock;\n\tunsigned char      *TempBuf;\n\tunsigned long      TempBufLen;\n\tunsigned long      TempBufSize;\n\tunsigned long      Flags;\n\tunsigned long      PlayPosition;\n\tunsigned long      SamplesPlayed;\n\tunsigned long      NumSkipped;\n\tunsigned short     SampleRate;\n\tunsigned char      Channels;\n\tunsigned char      BitsPerSample;\n\tunsigned long      BytesPerSec;\n\tWORD               DigiHandle;\n\tWORD               SampleHandle;\n\tWORD               DigiTimer;\n\t_SOS_START_SAMPLE  sSOSSampleData;\n\t_SOS_COMPRESS_INFO ADPCM_Info;\n\t_SOS_CAPABILITIES  DigiCaps;\n\t_SOS_HARDWARE      DigiHardware;\n\t_SOS_INIT_DRIVER   sSOSInitDriver;\n} VQAAudio;\n\n/* Audio flags. */\n#define VQAAUDB_DIGIINIT  0  /* HMI digital driver initialized (2 bits) */\n#define VQAAUDB_TIMERINIT 2  /* HMI timer system initialized (2 bits) */\n#define VQAAUDB_HMITIMER  4  /* HMI timer callback initialized (2 bits) */\n#define VQAAUDB_ISPLAYING 6  /* Audio playing flag. */\n#define VQAAUDB_MEMLOCKED 30 /* Audio memory page locked. */\n#define VQAAUDB_MODLOCKED 31 /* Audio module page locked. */\n\n#define VQAAUDF_DIGIINIT  (3<<VQAAUDB_DIGIINIT)\n#define VQAAUDF_TIMERINIT (3<<VQAAUDB_TIMERINIT)\n#define VQAAUDF_HMITIMER  (3<<VQAAUDB_HMITIMER)\n#define VQAAUDF_ISPLAYING (1<<VQAAUDB_ISPLAYING)\n#define VQAAUDF_MEMLOCKED (1<<VQAAUDB_MEMLOCKED)\n#define VQAAUDF_MODLOCKED (1<<VQAAUDB_MODLOCKED)\n\n/* HMI device initialization conditions. (DIGIINIT, TIMERINIT, HMITIMER) */\n#define HMI_UNINIT  0  /* Unitialize state. */\n#define HMI_VQAINIT 1  /* VQA initialized */\n#define HMI_APPINIT 2  /* Application initialized */\n\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n\n#endif /* VQAAUDIO_ON */\n\n\n/* VQAData: This stucture contains all the data used for playing a VQA.\n *\n * Draw_Frame   - Pointer to the draw-frame routine for this video mode.\n * Page_Flip    - Pointer to the page flip function for this video mode.\n * UnVQ         - Pointer to the UnVQ routine for this vid mode & blk size.\n * FrameData    - Frame buffer circular list head.\n * CBData       - Codebook circular list head.\n * Audio        - Audio buffer\n * Loader       - Loader's data\n * Drawer       - Drawer's data\n * Flipper      - Flipper's data\n * Flags        - Flags used by the player.\n * Foff         - Pointer to frame offset table.\n * VBIBit       - Vertical blank bit polarity.\n * Max_CB_Size  - Maximum size of an uncompressed codebook\n * Max_Pal_Size - Maximum size of an uncompressed palette\n * Max_Ptr_Size - Maximum size of uncompressed pointer data\n * LoadedFrames - Number of frames loaded\n * DrawnFrames  - Number of frames drawn\n * StartTime    - Start time in VQA time ticks\n * EndTime      - Stop time in VQA time ticks\n * MemUsed      - Number of bytes allocated by VQA_AllocBuffers\n */\ntypedef struct _VQAData {\n\tlong (*Draw_Frame)(VQAHandle *vqa);\n\tlong (*Page_Flip)(VQAHandle *vqa);\n\n\t#ifndef PHARLAP_TNT\n\tvoid cdecl (*UnVQ)(unsigned char *codebook, unsigned char *pointers,\n\t\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\t\tunsigned long numrows, unsigned long bufwidth);\n\t#else\n\tvoid cdecl (*UnVQ)(unsigned char *codebook, unsigned char *pointers,\n\t\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\t\tunsigned long bufwidth);\n\t#endif\n\n\tVQAFrameNode  *FrameData;\n\tVQACBNode     *CBData;\n\n\t#if(VQAAUDIO_ON)\n\tVQAAudio      Audio;\n\t#endif\n\n\tVQALoader     Loader;\n\tVQADrawer     Drawer;\n\tVQAFlipper    Flipper;\n\tunsigned long Flags;\n\tlong          *Foff;\n\tlong          VBIBit;\n\tlong          Max_CB_Size;\n\tlong          Max_Pal_Size;\n\tlong          Max_Ptr_Size;\n\tlong          LoadedFrames;\n\tlong          DrawnFrames;\n\tlong          StartTime;\n\tlong          EndTime;\n\tlong          MemUsed;\n} VQAData;\n\n/* VQAData flags */\n#define VQADATB_UPDATE 0 /* Update the display. */\n#define VQADATB_DSLEEP 1 /* Drawer sleep state. */\n#define VQADATB_LSLEEP 2 /* Loader sleep state. */\n#define VQADATB_DDONE  3 /* Drawer done flag. (0 = done) */\n#define VQADATB_LDONE  4 /* Loader done flag. (0 = done) */\n#define VQADATB_PRIMED 5 /* Buffers are primed. */\n#define VQADATB_PAUSED 6 /* The player is paused. */\n#define VQADATF_UPDATE (1<<VQADATB_UPDATE)\n#define VQADATF_DSLEEP (1<<VQADATB_DSLEEP)\n#define VQADATF_LSLEEP (1<<VQADATB_LSLEEP)\n#define VQADATF_DDONE  (1<<VQADATB_DDONE)\n#define VQADATF_LDONE  (1<<VQADATB_LDONE)\n#define VQADATF_PRIMED (1<<VQADATB_PRIMED)\n#define VQADATF_PAUSED (1<<VQADATB_PAUSED)\n\n\n/* VQAHandleP: Private VQA file handle. Must be obtained by calling\n *             VQA_Alloc() and freed through VQA_Free(). This is the only\n *             legal way to obtain and dispose of a VQAHandle.\n *\n * VQAio     - Something meaningful to the IO manager. (See DOCS)\n * IOHandler - IO handler callback.\n * VQABuf    - Pointer to internal data buffers.\n * Config    - Configuration structure.\n * Header    - VQA header structure.\n * vocfh     - Override audiotrack file handle.\n */\ntypedef struct _VQAHandleP {\n\tunsigned long VQAio;\n\tlong          (*IOHandler)(VQAHandle *vqa, long action, void *buffer,\n\t                          long nbytes);\n\tVQAData       *VQABuf;\n\tVQAConfig     Config;\n\tVQAHeader     Header;\n\tlong          vocfh;\n\tCaptionInfo   *Caption;\n\tCaptionInfo   *EVA;\n} VQAHandleP;\n\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n/* Loader/Drawer system. */\nlong VQA_LoadFrame(VQAHandle *vqa);\nvoid VQA_Configure_Drawer(VQAHandleP *vqap);\nlong User_Update(VQAHandle *vqa);\n\n/* Timer system. */\nlong VQA_StartTimerInt(VQAHandleP *vqap, long init);\nvoid VQA_StopTimerInt(VQAHandleP *vqap);\nvoid VQA_SetTimer(VQAHandleP *vqap, long time, long method);\nunsigned long VQA_GetTime(VQAHandleP *vqap);\nlong VQA_TimerMethod(void);\n\n/* Audio system. */\n#if(VQAAUDIO_ON)\nlong VQA_OpenAudio(VQAHandleP *vqap);\nvoid VQA_CloseAudio(VQAHandleP *vqap);\nlong VQA_StartAudio(VQAHandleP *vqap);\nvoid VQA_StopAudio(VQAHandleP *vqap);\nlong CopyAudio(VQAHandleP *vqap);\n#endif\n\n/* Debugging system. */\nvoid VQA_InitMono(VQAHandleP *vqap);\nvoid VQA_UpdateMono(VQAHandleP *vqap);\n\n#endif /* VQAPLAYP_H */\n\n"
  },
  {
    "path": "VQ/VQM32/ALL.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMALL_H\n#define VQMALL_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     all.h\n*\n* DESCRIPTION\n*     All VQMisc32 library definitions. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 5, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\iff.h>\n#include <vqm32\\mono.h>\n#include <vqm32\\portio.h>\n#include <vqm32\\profile.h>\n#include <vqm32\\targa.h>\n#include <vqm32\\compress.h>\n#include <vqm32\\video.h>\n#include <vqm32\\palette.h>\n#include <vqm32\\vesavid.h>\n#include <vqm32\\vesablit.h>\n#include <vqm32\\graphics.h>\n#include <vqm32\\mixfile.h>\n#include <vqm32\\crc.h>\n#include <vqm32\\huffman.h>\n#include <vqm32\\mem.h>\n\n#endif /* VQMALL_H */\n\n"
  },
  {
    "path": "VQ/VQM32/AUDUNZAP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     audunzap.asm \n;*\n;* DESCRIPTION\n;*     Audio uncompress (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Joe L. Bostic\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     February 9, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     AudioUnzap - Uncompress zapped audio sample.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\nCODE_2BIT\tEQU\t0\nCODE_4BIT\tEQU\t1\nCODE_RAW\tEQU\t2\nCODE_SILENCE\tEQU\t3\nMAGICNUMBER\tEQU\t00000DEAFh\nMAGICNUMBER2\tEQU\t0BABEBABEh\n\n_2bitdecode\tDB\t-2,-1,0,1\n_4bitdecode\tDB\t-9,-8,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,8\n\n;****************************************************************************\n;*\n;* NAME\n;*     AudioUnzap - Uncompress zapped audio sample.\n;*\n;* SYNOPSIS\n;*     Size = AudioUnzap(Source, Dest, Size)\n;*\n;*     long AudioUnzap(void *, void *, long);\n;*\n;* FUNCTION\n;*     Decompress the zapped audio sample data into a buffer.\n;*\n;* INPUTS\n;*     Source - Pointer to encoded audio data.\n;*     Dest   - Pointer to buffer to decompress into.\n;*     Size   - Maximum size of dest buffer.\n;*\n;* RESULT\n;*     Size - Number of uncompressed bytes.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC AudioUnzap:NEAR\n\tPROC\tAudioUnzap C NEAR USES ebx ecx edx esi edi\n\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tcount:DWORD\n\n\tLOCAL\tprevious:BYTE\n\tLOCAL\tincount:DWORD\n\n\tmov\t[incount],0\t;Bytes read from source\n\n;\tSource, Dest and count must be valid.\n\n;\tcmp\t[source],0\n;\tje\t??fini\n\n;\tcmp\t[dest],0\n;\tje\t??fini\n\n;\tcmp\t[count],0\n;\tje\t??fini\n\n\tmov\tesi,[source]\t;Pointer to source data.\n\tmov\tedi,[dest]\t;Pointer to destination data.\n\tmov\tecx,[count]\t;Number of bytes to fill dest buffer.\n\tmov\tdl,080h\t;Previous sample (starting value).\n\tcld\n\n??mainloop:\n\tcmp\tecx,0\t;If dest full then exit\n\tjle\t??fini\n\n\txor\teax,eax\n\tmov\tal,[esi]\t;Get code byte\n\tinc\t[incount]\n\tinc\tesi\n\tshl\teax,2\t;AH contains code.\n\tshr\tal,2\t;AL contains sub-code data.\n\n\tcmp\tah,CODE_RAW\t;Raw sequence?\n\tjne\tshort ??try4bit\n\n;\tThe code contains either a 5 bit delta or a count of\n;\traw samples to dump out.\n\n\ttest\tal,00100000b\n\tje\tshort ??justraw\n\n;\tThe lower 5 bits are actually a signed delta.\n;\tSign extend the delta and add it to the stream.\n\n\tshl\tal,3\n\tsar\tal,3\n\tadd\tdl,al\n\tmov\t[edi],dl\n\tdec\tecx\n\tinc\tedi\n\tjmp\t??mainloop\n\n;\tThe lower 5 bits hold a count of the number of raw\n;\tsamples that follow this code. Dump these samples to\n;\tthe output buffer.\n\n??justraw:\n\tmov\tebx,ecx\n\txor\tah,ah\n\tinc\tal\n\tmov\tecx,eax\n\tshr\tecx,1\n\trep\tmovsw\n\tadc\tecx,ecx\n\trep\tmovsb\n\tmov\tecx,ebx\n\tadd\t[incount],eax\n\tsub\tecx,eax\n\tdec\tedi\n\tmov\tdl,[edi]\t;Set \"previous\" value.\n\tinc\tedi\n\tjmp\t??mainloop\n\n;\tCheck to see if this is a 4 bit delta code sequence.\n\n??try4bit:\n\tinc\tal\t;Following codes use AL+1\n\tcmp\tah,CODE_4BIT\n\tjne\tshort ??try2bit\n\n;\tA sequence of 4bit deltas follow. AL equals the\n;\tnumber of nibble packed delta bytes to process.\n\n??bit4loop:\n\tmov\tah,[esi]\t;Fetch nibble packed delta codes\n\tmov\tbl,ah\n\tinc\t[incount]\n\tinc\tesi\n\n;\tAdd first delta to 'previous' sample already in DL.\n\n\tand\tebx,00001111b\n\tadd\tdl,[_4bitdecode+ebx]\n\tpushf\n\tcmp\t[_4bitdecode+ebx],0\n\tjl\tshort ??neg1\n\n\tpopf\n\tjnc\tshort ??ok1\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok1\n\n??neg1:\n\tpopf\n\tjc\tshort ??ok1\n\n\txor\tdl,dl\n\n??ok1:\n\tmov\tdh,dl\t;DH now holds new 'previous' sample.\n\tmov\tbl,ah\n\tshr\tbl,4\n\tadd\tdh,[_4bitdecode+ebx]\n\tpushf\n\tcmp\t[_4bitdecode+ebx],0\n\tjl\tshort ??neg2\n\n\tpopf\n\tjnc\tshort ??ok2\n\n\tmov\tdh,0FFh\n\tjmp\tshort ??ok2\n\n??neg2:\n\tpopf\n\tjc\tshort ??ok2\n\n\txor\tdh,dh\n\n??ok2:\n\tmov\t[edi],dx\t;Output the two sample bytes\n\tsub\tecx,2\n\tadd\tedi,2\n\n;\tPut the correct 'previous' sample in DL where it belongs.\n\n\tmov\tdl,dh\n\n;\tIf there are more deltas to process then loop back.\n\n\tdec\tal\n\tjnz\tshort ??bit4loop\n\tjmp\t??mainloop\n\n;\tCheck to see if 2 bit deltas need to be processed.\n\n??try2bit:\n\tcmp\tah,CODE_2BIT\n\tjne\t??zerodelta\n\n;\tA sequence of 2bit deltas follow.  AL equals the number of \n;\tpacked delta bytes to process.\n\n??bit2loop:\n\tmov\tah,[esi]\t;Fetch packed delat codes\n\tinc\t[incount]\n\tinc\tesi\n\n;\tAdd first delta to 'previous' sample already in DL.\n\n\tmov\tbl,ah\n\tand\tebx,000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushf\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg3\n\n\tpopf\n\tjnc\tshort ??ok3\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok3\n\n??neg3:\n\tpopf\n\tjc\tshort ??ok3\n\txor\tdl,dl\n\n??ok3:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,2\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushf\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg4\n\n\tpopf\n\tjnc\tshort ??ok4\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok4\n\n??neg4:\n\tpopf\n\tjc\tshort ??ok4\n\n\txor\tdl,dl\n\n??ok4:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,4\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushf\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg5\n\n\tpopf\n\tjnc\tshort ??ok5\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok5\n\n??neg5:\n\tpopf\n\tjc\tshort ??ok5\n\n\txor\tdl,dl\n\n??ok5:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,6\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushf\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg6\n\n\tpopf\n\tjnc\tshort ??ok6\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok6\n\n??neg6:\n\tpopf\n\tjc\tshort ??ok6\n\n\txor\tdl,dl\n\n??ok6:\n\tror\tedx,8\n\tmov\t[edi],edx\t;Output two sample bytes\n\tsub\tecx,4\n\tadd\tedi,4\n\n;\tPut the correct 'previous' sample in DL where it belongs.\n\n\trol\tedx,8\n\n;\tIf there are more deltas to process then loop back.\n\n\tdec\tal\n\tjnz\t??bit2loop\n\tjmp\t??mainloop\n\n;\tThere is a run of zero deltas.  Zero deltas merely duplicate\n;\tthe 'previous' sample the requested number of times.\n\n??zerodelta:\n\txor\tebx,ebx\n\tmov\tbl,al\n\tmov\tal,dl\n\tsub\tecx,ebx\n\txchg\tecx,ebx\n\trep\tstosb\n\tmov\tecx,ebx\n\tjmp\t??mainloop\n\n??fini:\n\tmov\teax,[incount]\n\tret\n\n\tENDP\tAudioUnzap\n\n\tEND\n\n"
  },
  {
    "path": "VQ/VQM32/AUDZAP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Audzap.c\n*\n* DESCRIPTION\n*     Lossy audio compression. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Joe L. Bostic\n*      \n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     AudioZap - Compress audio sample data.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <mem.h>\n#include \"compress.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n#define\tMIN(a,b) (((a)<(b)) ? (a) : (b))\n#define\tMAX(a,b) (((a)>(b)) ? (a) : (b))\n\ntypedef enum {\n\tCODE_2BIT,    /* Bit packed 2 bit delta. */\n\tCODE_4BIT,    /* Nibble packed 4 bit delta. */\n\tCODE_RAW,     /* Raw sample. */\n\tCODE_SILENCE  /* Run of silence. */\n} SCodeType;\n\nchar _2bitencode[5] = {\n\t0,1,2,3\n};\n\nlong _2bitdecode[4] = {\n\t-2,-1,0,1\n};\n\nchar _4bitencode[19] = {\n\t0,1,2,2,3,4,5,6,7,(8),\n\t8,9,10,11,12,13,13,14,15\n};\n\nlong _4bitdecode[16] = {\n\t-9,-8,-6,-5,-4,-3,-2,\n\t-1,0,1,2,3,4,5,6,8\n};\n\n\n/****************************************************************************\n*\n* NAME\n*     AudioZap - Compress audio sample data.\n*\n* SYNOPSIS\n*     Size = AudioZap(Source, Dest, Size)\n*\n*     long AudioZap(void *, void *, long);\n*\n* FUNCTION\n*     NOTE - If the compressed size is equal to or greater than the original\n*     size then the data could not be compressed and the uncompressed data\n*     should be written.\n*\n* INPUTS\n*     Source - Pointer to buffer containing audio sample data.\n*     Dest   - Pointer to buffer to put encoded data.\n*     Size   - Number of bytes to compress.\n*\n* RESULT\n*     Size - Size in bytes of encoded data.\n*\n****************************************************************************/\n\nlong AudioZap(void *source, void *dest, long size)\n{\n\tunsigned char *s = (unsigned char *)source;\n\tunsigned char *d = (unsigned char *)dest;\n\tlong          delta;\n\tunsigned long previous = 0x80;\n\tlong          outcount = 0;\n\tunsigned char *s4;\n\tunsigned long p4;\n\tlong          max4;\n\tunsigned char *lastraw = 0;\n\tlong          osize = size;\n\tunsigned long i;\n\tunsigned long dd;\n\n\t/* Reduce very small amplitudes to silence.  Usually a rather large\n\t * portion of a sample is hovering around the silence value.  This is\n\t * due, in part, to the artifacting of the sample process.  These low\n\t * amplitudes are not audible.\n\t */\n\tmax4 = size;\n\ts = (unsigned char *)source;\n\n\twhile (size > 0 && outcount < osize) {\n\n\t\t/* First check for runs of zero deltas.  If a run of at least\n\t\t * any can be found, then output it.\n\t\t */\n\t\ts4 = s;\n\t\tmax4 = MIN(63 + 1, size);\n\n\t\tfor (i = 0; i < max4; i++) {\n\t\t\tif (previous != *s4++)\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/* When there is a code transition, terminate any run of raw\n\t\t * samples.\n\t\t */\n\t\tif (i > 2) {\n\t\t\tlastraw = 0;\n\t\t\t*d++ = ((i - 1)|(CODE_SILENCE << 6));\n\t\t\toutcount++;\n\t\t\ts += i;\n\t\t\tsize -= i;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/* If there are fewer than 4 samples remaining, then using delta\n\t\t * compression is inefficient.  Just drop into the raw routine\n\t\t */\n\t\tif (size > 4) {\n\t\t\ts4 = s;\n\t\t\tp4 = previous;\n\n\t\t\t/* Find out the number of lossless 2 bit deltas available.  These\n\t\t\t * deltas are always present in quads.  The compressed code is\n\t\t\t * the delta quad count followed by the deltas in bit packed bytes.\n\t\t\t */\n\t\t\tmax4 = MIN(64L * 4L + 4L + 4L, size);\n\n\t\t\tfor (i = 0; i < max4; i++) {\n\t\t\t\tdelta = (((int)*s4++) - p4);\n\n\t\t\t\tif ((delta < -2) || (delta > 1)) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tp4 += _2bitdecode[_2bitencode[delta + 2]];\n\n\t\t\t\tif (((signed)p4) < 0) {\n\t\t\t\t\tp4 = 0;\n\t\t\t\t}\n\n\t\t\t\tif (((signed)p4) > 255) {\n\t\t\t\t\tp4 = 255;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ti >>= 2;  // Delta 2 always occur in quads -- force this.\n\n\t\t\t/* If there is the minimum benificial number of delta 2s available,\n\t\t\t * then compress them.\n\t\t\t */\n\t\t\tif (i) {\n\n\t\t\t\t/* When there is a code transition, terminate any run of raw\n\t\t\t\t * samples.\n\t\t\t\t */\n\t\t\t\tlastraw = 0;\n\n\t\t\t\t/* Output the delta 4 pair count.  This is the number of pairs\n\t\t\t\t * minus the 'free' two pairs already assumed to be there.\n\t\t\t\t */\n\t\t\t\ti = MIN(i, (63 + 1));\n\t\t\t\t*d++ = ((i - 1)|(CODE_2BIT << 6));\n\t\t\t\toutcount++;\n\n\t\t\t\tfor (dd = 0; dd < i; dd++) {\n\t\t\t\t\tint delta1, delta2, delta3, delta4;\n\n\t\t\t\t\tdelta1 = _2bitencode[((((int)*s++) - previous) + 2)];\n\t\t\t\t\tprevious += _2bitdecode[delta1];\n\n\t\t\t\t\tif (((signed)previous) < 0) {\n\t\t\t\t\t\tprevious = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (((signed)previous) > 255) {\n\t\t\t\t\t\tprevious = 255;\n\t\t\t\t\t}\n\n\t\t\t\t\tsize--;\n\t\t\t\t\tdelta2 = _2bitencode[((((int)*s++) - previous) + 2)];\n\t\t\t\t\tprevious += _2bitdecode[delta2];\n\n\t\t\t\t\tif (((signed)previous) < 0) {\n\t\t\t\t\t\tprevious = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (((signed)previous) > 255) {\n\t\t\t\t\t\tprevious = 255;\n\t\t\t\t\t}\n\n\t\t\t\t\tsize--;\n\t\t\t\t\tdelta3 = _2bitencode[((((int)*s++) - previous) + 2)];\n\t\t\t\t\tprevious += _2bitdecode[delta3];\n\n\t\t\t\t\tif (((signed)previous) < 0) {\n\t\t\t\t\t\tprevious = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (((signed)previous) > 255) {\n\t\t\t\t\t\tprevious = 255;\n\t\t\t\t\t}\n\n\t\t\t\t\tsize--;\n\t\t\t\t\tdelta4 = _2bitencode[((((int)*s++) - previous) + 2)];\n\t\t\t\t\tprevious += _2bitdecode[delta4];\n\n\t\t\t\t\tif (((signed)previous) < 0) {\n\t\t\t\t\t\tprevious = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (((signed)previous) > 255) {\n\t\t\t\t\t\tprevious = 255;\n\t\t\t\t\t}\n\n\t\t\t\t\tsize--;\n\t\t\t\t\t*d++ = ((delta4 << 6)|(delta3 << 4)|(delta2 << 2)|delta1);\n\t\t\t\t\toutcount++;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t} else {\n\t\t\t\ts4 = s;\n\t\t\t\tp4 = previous;\n\n\t\t\t\t/* Find out the number of lossless 4 bit deltas follow.  These\n\t\t\t\t * deltas are always present in pairs.  The compressed code is\n\t\t\t\t * the delta pair count followed by the deltas in nibble packed\n\t\t\t\t * bytes.\n\t\t\t\t */\n\t\t\t\tmax4 = MIN(64L * 2L + 4L + 4L, size);\n\n\t\t\t\tfor (i = 0; i < max4; i++) {\n\t\t\t\t\tdelta = (((int)*s4++) - p4);\n\n\t\t\t\t\tif (delta < -9 || delta >= 9) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tp4 += _4bitdecode[_4bitencode[(delta + 9)]];\n\n\t\t\t\t\tif (((signed)p4) < 0) {\n\t\t\t\t\t\tp4 = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (((signed)p4) > 255) {\n\t\t\t\t\t\tp4 = 255;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\ti >>= 1; // Delta 4 always occur in pairs -- force this.\n\n\t\t\t\t/* If there is the minimum benificial number of delta 4s available,\n\t\t\t\t * then compress them.\n\t\t\t\t */\n\t\t\t\tif (i) {\n\n\t\t\t\t\t/* When there is a code transition, terminate any run of raw\n\t\t\t\t\t * samples.\n\t\t\t\t\t */\n\t\t\t\t\tlastraw = 0;\n\n\t\t\t\t\t/* Output the delta 4 pair count.  This is the number of pairs\n\t\t\t\t\t * minus the 'free' two pairs already assumed to be there.\n\t\t\t\t\t */\n\t\t\t\t\ti = MIN(i, (63 + 1));\n\t\t\t\t\t*d++ = ((i - 1)|(CODE_4BIT << 6));\n\t\t\t\t\toutcount++;\n\n\t\t\t\t\tfor (dd = 0; dd < i; dd++) {\n\t\t\t\t\t\tint delta1, delta2;\n\n\t\t\t\t\t\tdelta1 = _4bitencode[((((int)*s++) - previous) + 9)];\n\t\t\t\t\t\tprevious += _4bitdecode[delta1];\n\n\t\t\t\t\t\tif (((signed)previous) < 0) {\n\t\t\t\t\t\t\tprevious = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (((signed)previous) > 255) {\n\t\t\t\t\t\t\tprevious = 255;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tsize--;\n\t\t\t\t\t\tdelta2 = _4bitencode[((((int)*s++) - previous) + 9)];\n\t\t\t\t\t\tprevious += _4bitdecode[delta2];\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (((signed)previous) < 0) {\n\t\t\t\t\t\t\tprevious = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (((signed)previous) > 255) {\n\t\t\t\t\t\t\tprevious = 255;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tsize--;\n\t\t\t\t\t\t*d++ = ((delta2 << 4)|(delta1 & 0x0F));\n\t\t\t\t\t\toutcount++;\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Raw output since deltas were unsuccessful.  If this is a run\n\t\t * of raw output, then merely tack it onto the run rather than\n\t\t * create a new code sequence.\n\t\t */\n\t\tif (lastraw) {\n\t\t\t*lastraw = ((*lastraw) + 1);\n\n\t\t\t/* There is only so much a run code can accomodate.  If the limit\n\t\t\t * has been reached, then terminate this code.  A new one will be\n\t\t\t * created if necessary.\n\t\t\t */\n\t\t\tif ((*lastraw & 0x1F) == 0x1F) {\n\t\t\t\tlastraw = 0;\n\t\t\t}\n\t\t} else {\n\t\t\t\n\t\t\t/* If there is no current raw dump of samples, then check to see if\n\t\t\t * this sample can fit into a 5 bit delta.  If it can, then store\n\t\t\t * it as such as a parasite to the \"raw\" code.  This will save a byte\n\t\t\t * for any stray 5 bit deltas that happen along.  It is expected that\n\t\t\t * this is more frequent than 6 or more bit deltas that would necessitate\n\t\t\t * the use of the RAW code.\n\t\t\t */\n\t\t\tdelta = (((int)*s) - previous);\n\n\t\t\tif ((delta >= -16) && (delta <= 15)) {\n\t\t\t\tlastraw = 0;\n\t\t\t\t*d++ = ((CODE_RAW << 6)|0x20|(delta & 0x1F));\n\t\t\t\toutcount++;\n\t\t\t\tprevious = *s++;\n\t\t\t\tsize--;\n\t\t\t\tcontinue;\n\t\t\t} else {\n\t\t\t\tlastraw = d;\n\t\t\t\t*d++ = (CODE_RAW << 6);\n\t\t\t\toutcount++;\n\t\t\t}\n\t\t}\n\n\t\t*d++ = previous = *s++;\n\t\tsize--;\n\t\toutcount++;\n\t}\n\n\t/* Check to see if the compression process actually resulted in smaller\n\t * data size.  In some cases, the 'compressed' data is actually larger.  In\n\t * this case, just output the raw frame.  If the compressed and actual frame\n\t * size match, then it is presumed that no compression occurs.\n\t */\n\tif (outcount >= osize) {\n\t\tmemcpy(dest, source, (size_t)osize);\n\t\toutcount = osize;\n\t}\n\n\treturn(outcount);\n}\n\n"
  },
  {
    "path": "VQ/VQM32/BCC32.CFG",
    "content": "-c\n-3\n-d\n-H=c:\\projects\\vqm32\\obj\\headers.sym\n-wpro\n-weas\n-wpre\n-IC:\\PROJECTS\\INCLUDE;C:\\DEV\\BC4\\INCLUDE;C:\\DEV\\TNT\\INCLUDE\n-DPHARLAP_TNT=1\n"
  },
  {
    "path": "VQ/VQM32/CAPTOKEN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     captoken.c\n*\n* DESCRIPTION\n*     Tokenize a caption script for playback processing.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 26, 1995\n*\n****************************************************************************/\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <errno.h>\n#include <string.h>\n#include <ctype.h>\n#include \"captoken.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n#define STRING_LENGTH 256\n#define PADSIZE(size) (((size)+1)&(~1))\n\ntypedef enum {\n\tTOKEN_NULL = 0,\n\tTOKEN_BGCOL,\n\tTOKEN_FGCOL,\n\tTOKEN_XPOS,\n\tTOKEN_YPOS,\n\tTOKEN_ABS,\n\tTOKEN_LEFT,\n\tTOKEN_RIGHT,\n\tTOKEN_CENTER,\n\tTOKEN_FLASH,\n\tTOKEN_CPF,\n\tTOKEN_END\n} TokenTag;\n\ntypedef struct _Token {\n\tchar *name;\n\tlong tag;\n} Token;\n\n/* Script tokens:\n * BG/BGCOL     - Background pen color (EX: BG=<color name>)\n * FG/FGCOL     - Foreground pen color (EX: FG=<color name>)\n * X/XPOS       - X pixel position of text (EX: X=<pixel cord>)\n * Y/YPOS       - Y pixel position of text (EX: Y=<pixel cord>)\n * ABS/ABSOLUTE - Absolute justification\n * LEFT         - Left side justification\n * RIGHT        - Right side justification\n * CENTER       - Center justification\n * FLASH        - Enable flashing of text\n * CPF          - Print rate in characters per frame (EX: CPF=<rate>)\n * END          - Terminate compilation of caption script\n */\nToken tokens[] = {\n\t\"BG\", TOKEN_BGCOL,\n\t\"BGCOL\", TOKEN_BGCOL,\n\t\"FG\", TOKEN_FGCOL,\n\t\"FGCOL\", TOKEN_FGCOL,\n\t\"X\", TOKEN_XPOS,\n\t\"XPOS\", TOKEN_XPOS,\n\t\"Y\", TOKEN_YPOS,\n\t\"YPOS\", TOKEN_YPOS,\n\t\"ABS\", TOKEN_ABS,\n\t\"ABSOLUTE\", TOKEN_ABS,\n\t\"LEFT\", TOKEN_LEFT,\n\t\"RIGHT\", TOKEN_RIGHT,\n\t\"CENTER\", TOKEN_CENTER,\n\t\"FLASH\", TOKEN_FLASH,\n\t\"CPF\", TOKEN_CPF,\n\t\"END\", TOKEN_END,\n\tNULL, TOKEN_NULL,\n};\n\nToken colors[] = {\n\t\"BLACK\", 0,\n\t\"WHITE\", 251,\n\t\"RED\", 252,\n\t\"GREEN\", 253,\n\t\"SHADOW\", 254,\n\t\"CYCLE\", 255,\n\tNULL, -1,\n};\n\n/* Prototypes. */\nstatic long GetColorNum(char *name);\nstatic long IsNumeric(char *string);\nstatic void FormatString(char *string);\n\n\n/****************************************************************************\n*\n* NAME\n*     BuildCaptions - Compile a caption script.\n*\n* SYNOPSIS\n*     Size = BuildCaptions(Name, Buffer)\n*\n*     long BuildCaptions(char *, char *);\n*\n* FUNCTION\n*     Generate a compiled caption script for use in VQA playback.\n*\n* INPUTS\n*     Name   - Name of caption script file to compile.\n*     Buffer - Buffer to put compiled captions into.\n*\n* RESULT\n*     Size - Size of compiled captions (in bytes).\n*\n****************************************************************************/\n\nlong BuildCaptions(char *name, char *buffer)\n{\n\tFILE        *fp;\n\tchar        *ptr;\n\tchar        *ptr1;\n\tlong        size = 0;\n\tlong        error;\n\tlong        i;\n\tlong        tag;\n\tCaptionText caption;\n\tchar        string[STRING_LENGTH];\n\n\t/* Initialize the caption parameters. */\n\tmemset(&caption, 0, sizeof(CaptionText));\n\n\t/* Open the captions script file. */\n\tfp = fopen(name, \"r\");\n\n\tif (fp != NULL) {\n\t\terror = 0;\n\n\t\twhile (!error) {\n\t\t\tif (fgets(string, STRING_LENGTH, fp) == NULL) {\n\t\t\t\tif (errno == 0) {\n\t\t\t\t\terror = 1;\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\n\t\t\t/* Replace the newline with a NULL terminator. */\n\t\t\tstring[strlen(string) - 1] = 0;\n\n\t\t\t/* Ignore comment lines. */\n\t\t\tif (string[0] == ';') continue;\n\n\t\t\tptr = strtok(string, \"=\");\n\n\t\t\tif (ptr != NULL) {\n\n\t\t\t\t/* Check for a comma */\n\t\t\t\tptr1 = strchr(ptr, ',');\n\n\t\t\t\tif (ptr1 != NULL) {\n\t\t\t\t\t*ptr1++ = 0;\n\t\t\t\t}\n\n\t\t\t\t/* Is this a frame number. */\n\t\t\t\tif (IsNumeric(ptr) && IsNumeric(ptr1)) {\n\t\t\t\t\ti = atoi(ptr);\n\n\t\t\t\t\t/* Frames must be defined in ascending order. */\n\t\t\t\t\tif ((unsigned short)i >= caption.OnFrame) {\n\t\t\t\t\t\tcaption.OnFrame = i;\n\t\t\t\t\t\tcaption.OffFrame = atoi(ptr1);\n\t\t\t\t\t\tcaption.Size = sizeof(CaptionText);\n\n\t\t\t\t\t\t/* Get caption text. */\n\t\t\t\t\t\tptr = strtok(NULL, \"\");\n\n\t\t\t\t\t\tif (ptr != NULL) {\n\t\t\t\t\t\t\tFormatString(ptr);\n\t\t\t\t\t\t\ti = strlen(ptr) + 1;\n\t\t\t\t\t\t\tcaption.Size += PADSIZE(i);\n\t\t\t\t\t\t\tsize += caption.Size;\n\n\t\t\t\t\t\t\t/* Copy the caption structure. */\n\t\t\t\t\t\t\tmemcpy(buffer, &caption, sizeof(CaptionText));\n\t\t\t\t\t\t\tbuffer += sizeof(CaptionText);\n\n\t\t\t\t\t\t\t/* Copy the caption text. */\n\t\t\t\t\t\t\tmemcpy(buffer, ptr, i);\n\t\t\t\t\t\t\tbuffer += i;\n\n\t\t\t\t\t\t\t/* WORD align */\n\t\t\t\t\t\t\tif (PADSIZE(i) > i) {\n\t\t\t\t\t\t\t\t*buffer++ = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\terror = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/* Search for matching token. */\n\t\t\t\t\ttag = TOKEN_NULL;\n\t\t\t\t\ti = 0;\n\n\t\t\t\t\twhile (tokens[i].name != NULL) {\n\t\t\t\t\t\tif (strcmpi(tokens[i].name, ptr) == 0) {\n\t\t\t\t\t\t\ttag = tokens[i].tag;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ti++;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Get the data element. */\n\t\t\t\t\tptr = strtok(NULL, \"\");\n\n\t\t\t\t\tswitch (tag) {\n\t\t\t\t\t\tcase TOKEN_BGCOL:\n\t\t\t\t\t\t\tcaption.BgPen = (char)GetColorNum(ptr);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_FGCOL:\n\t\t\t\t\t\t\tcaption.FgPen = (char)GetColorNum(ptr);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_XPOS:\n\t\t\t\t\t\t\tcaption.Xpos = (unsigned short)atoi(ptr);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_YPOS:\n\t\t\t\t\t\t\tcaption.Ypos = (unsigned short)atoi(ptr);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_ABS:\n\t\t\t\t\t\t\tcaption.Flags &= ~CTF_JUSTIFY;\n\t\t\t\t\t\t\tcaption.Flags |= CTF_ABS;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_LEFT:\n\t\t\t\t\t\t\tcaption.Flags &= ~CTF_JUSTIFY;\n\t\t\t\t\t\t\tcaption.Flags |= CTF_LEFT;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_RIGHT:\n\t\t\t\t\t\t\tcaption.Flags &= ~CTF_JUSTIFY;\n\t\t\t\t\t\t\tcaption.Flags |= CTF_RIGHT;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_CENTER:\n\t\t\t\t\t\t\tcaption.Flags &= ~CTF_JUSTIFY;\n\t\t\t\t\t\t\tcaption.Flags |= CTF_CENTER;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_FLASH:\n\t\t\t\t\t\t\tif (strcmpi(ptr, \"OFF\") == 0) {\n\t\t\t\t\t\t\t\tcaption.Flags &= ~CTF_FLASH;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcaption.Flags |= CTF_FLASH;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_CPF:\n\t\t\t\t\t\t\tcaption.CPF = (char)atoi(ptr);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t/* Termination captions */\n\t\t\t\t\t\tcase TOKEN_END:\n\t\t\t\t\t\t\tcaption.Size = sizeof(CaptionText);\n\t\t\t\t\t\t\tcaption.OnFrame = (unsigned short)-1;\n\t\t\t\t\t\t\tmemcpy(buffer, &caption, sizeof(CaptionText));\n\t\t\t\t\t\t\tbuffer += sizeof(CaptionText);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Close the script file. */\n\t\tfclose(fp);\n\t}\n\n\treturn (size);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetColorNum - Get the color number from the color name.\n*\n* SYNOPSIS\n*     Color = GetColorNum(Name)\n*\n*     long GetColorNum(char *);\n*\n* FUNCTION\n*     Look the color number that corresponds to the color name.\n*\n* INPUTS\n*     Name - Name of color.\n*\n* RESULT\n*     Color - Color number.\n*\n****************************************************************************/\n\nstatic long GetColorNum(char *name)\n{\n\tlong color = -1;\n\tlong i;\n\n\ti = 0;\n\n\t/* Scan for a matching name and return the corresponding color number. */\n\twhile (colors[i].name != NULL) {\n\t\tif (strcmpi(colors[i].name, name) == 0) {\n\t\t\tcolor = colors[i].tag;\n\t\t}\n\n\t\ti++;\n\t}\n\n\treturn (color);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     IsNumeric - Check if a string is numeric.\n*\n* SYNOPSIS\n*     Condition = IsNumeric(String)\n*\n*     long IsNumeric(char *);\n*\n* FUNCTION\n*     Interogate the string to see if it represents a numeric value. Each\n*     byte of the string must be between 0x30 and 0x39 inclusively.\n*\n* INPUTS\n*     String - String to check.\n*\n* RESULT\n*     Condition - 1 if numeric, 0 if not.\n*\n****************************************************************************/\n\nstatic long IsNumeric(char *string)\n{\n\tlong flag = 1;\n\n\t/* Ignore any proceeding sign designation. */\n\tif ((*string == '-') || (*string == '+')) {\n\t\tstring++;\n\t}\n\n\t/* Check to see if every byte in the string is a digit. */\n\twhile (flag && (*string != 0)) {\n\t\tif (!isdigit(*string++)) {\n\t\t\tflag = 0;\n\t\t}\n\t}\n\n\treturn (flag);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     FormatString - Parse any format codes in the string.\n*\n* SYNOPSIS\n*     FormatString(String)\n*\n*     void FormatString(char *);\n*\n* FUNCTION\n*     Format a string with any embedded format commands contained in the\n*     input string.\n*\n*     Supported format commands:\n*       /n - Insert carriage return. (0x0D)\n*       /r - Insert carriage return. (0x0D)\n*       // - Literal backslash.\n*\n* INPUTS\n*     String - Pointer to string to format.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void FormatString(char *string)\n{\n\tchar *ptr;\n\n\t/* NULL strings are invalid. */\n\tif (string != NULL) {\n\t\tptr = string;\n\n\t\t/* Scan the string for embedded format commands. */\n\t\twhile ((ptr = strchr(ptr, '/')) != NULL) {\n\t\t\tswitch (*(ptr + 1)) {\n\n\t\t\t\t/* Carriage return. */\n\t\t\t\tcase 'n':\n\t\t\t\tcase 'r':\n\t\t\t\t\t*ptr = 0x0D;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/* Literal backslash. */\n\t\t\t\tcase '/':\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/* Remove the unwanted character. */\n\t\t\tstrcpy((ptr + 1), (ptr + 2));\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "VQ/VQM32/CAPTOKEN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMCAPTOKEN_H\n#define VQMCAPTOKEN_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     captoken.h\n*\n* DESCRIPTION\n*     Text caption script definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 26, 1995\n*\n****************************************************************************/\n\n/* CaptionText: This structure describes a line of text to be displayed\n *              with the video/audio.\n *\n * Size     - Size of caption in bytes.\n * OnFrame  - Frame number to display caption.\n * OffFrame - Frame number to clear caption.\n * Flags    - Display modifiers.\n * CPF      - Characters to draw per frame.\n * Xpos     - X pixel position to display caption.\n * Ypos     - Y pixel position to display caption.\n * BgPen    - Background pen to use.\n * FgPen    - Foreground pen to use.\n * Text     - Text string to display. (WORD aligned)\n */\ntypedef struct _CaptionText {\n\tunsigned short Size;\n\tunsigned short OnFrame;\n\tunsigned short OffFrame;\n\tunsigned char  Flags;\n\tchar           CPF;\n\tunsigned short Xpos;\n\tunsigned short Ypos;\n\tchar           BgPen;\n\tchar           FgPen;\n\tchar           Text[];\n} CaptionText;\n\n/* CaptionText flag definitions. */\n#define CTF_JUSTIFY\t(3<<0)  /* Justification field. */\n#define CTF_ABS     (0<<0)  /* Use absolute X,Y positions. */\n#define CTF_CENTER  (1<<0)  /* Justify on Center */\n#define CTF_LEFT    (2<<0)  /* Justify on left */\n#define CTF_RIGHT   (3<<0)  /* Justify on right */\n#define CTF_FLASH   (1<<4)  /* Flash text. */\n\n/* Function prototypes. */\nlong BuildCaptions(char *name, char *buffer);\n\n#endif /* VQMCAPTOKEN_H */\n\n"
  },
  {
    "path": "VQ/VQM32/CHRWIDTH.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*---------------------------------------------------------------------------\n*\n* FILE\n*     chrwidth.c\n*\n* DESCRIPTION\n*     Character pixel width.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     June 9, 1995\n*\n*---------------------------------------------------------------------------\n*\n* PUBLIC\n*     Char_Pixel_Width - Get the pixel width of a character.\n*\n****************************************************************************/\n\n#include \"font.h\"\n\n\n/****************************************************************************\n*\n* NAME\n*     Char_Pixel_Width - Get the pixel width of a character.\n*\n* SYNOPSIS\n*     Width = Char_Pixel_Width(Character)\n*\n*     long Char_Pixel_Width(char);\n*\n* FUNCTION\n*     Gets the pixel width of the specified character.\n*\n* INPUTS\n*     Character - Character to get the width for.\n*\n* RESULT\n*     Width - Width in pixels.\n*\n****************************************************************************/\n\n#ifdef __WATCOMC__\nlong cdecl __saveregs Char_Pixel_Width(char chr)\n#else\n#pragma saveregs\nlong cdecl Char_Pixel_Width(char chr)\n#endif\n{\n\treturn (*(FontWidthBlockPtr + chr) + FontXSpacing);\n}\n"
  },
  {
    "path": "VQ/VQM32/COMPRESS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMCOMP_H\n#define VQMCOMP_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     compress.h\n*\n* DESCRIPTION\n*     Compression definitions. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nunsigned long cdecl LCW_Compress(char const *source, char *dest,\n\t\tunsigned long length);\nunsigned long cdecl LCW_Uncompress(char const *source, char *dest,\n\t\tunsigned long length);\nlong AudioZap(void *source, void *dest, long size);\nlong cdecl AudioUnzap(void *source, void *dest, long);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMCOMP_H */\n\n"
  },
  {
    "path": "VQ/VQM32/CRC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     crc.asm\n;*\n;* DESCRIPTION\n;*     CRC checksum calculation.\n;*\n;* PROGRAMMER\n;*     Joe L. Bostic\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     Calculate_CRC - Calculate CRC checksum.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     Calculate_CRC - Calculate CRC checksum.\n;*\n;* SYNOPSIS\n;*     CRC = Calculate_CRC(Buffer, Length)\n;*\n;*     long Calculate_CRC(void *, long);\n;*\n;* FUNCTION\n;*     Compute a CRC checksum for a block of memory.\n;*\n;* INPUTS\n;*     Buffer - Pointer to buffer to calculate CRC for.\n;*     Length - Length of buffer.\n;*\n;* RESULT\n;*     CRC - CRC value.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Calculate_CRC:NEAR\n\tPROC\tCalculate_CRC C NEAR USES esi ebx ecx edx\n\tARG\tbuffer:NEAR PTR\n\tARG\tlength:DWORD\n\n\tmov\tesi,[buffer]\n\tcld\n\n\t; Clear CRC to default (NULL) value.\n\txor\tebx,ebx\n\n\tmov\tecx,[length]\t;Get length of data block\n\tor\tecx,ecx\n\tjz\tshort ??fini\n\n\t; Prepare the length counters.\n\tmov\tedx,ecx\n\tand\tdl,011b\n\tshr\tecx,2\n\n\t; Perform the bulk of the CRC scanning.\n\tor\tecx,ecx\n\tjz\tshort ??remainder\n\n??accumloop:\n\tlodsd\n\trol\tebx,1\n\tadd\tebx,eax\n\tloop\t??accumloop\n\n\t; Handle the remainder bytes.\n??remainder:\n\tor\tdl,dl\n\tjz\tshort ??fini\n\tmov\tecx,edx\n\txor\teax,eax\n\n\tpush\tecx\n??nextbyte:\n\tlodsb\n\tror\teax,8\n\tloop\t??nextbyte\n\tpop\tecx\n\tneg\tecx\n\tadd\tecx,4\n\tshl\tecx,3\n\tror\teax,cl\n\n;??nextbyte:\n;\tshl\teax,8\n;\tlodsb\n;\tloop\t??nextbyte\n\trol\tebx,1\n\tadd\tebx,eax\n\n??fini:\n\tmov\teax,ebx\n\tret\n\n\tENDP\tCalculate_CRC\n\n\tEND\n"
  },
  {
    "path": "VQ/VQM32/CRC.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMCRC_H\n#define VQMCRC_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     CRC.h\n*\n* DESCRIPTION\n*     CRC calculation definitions.\n*\n* PROGRAMMER\n*     Joe L. Bostic\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nlong cdecl Calculate_CRC(void const *buffer, long length);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMCRC_H */\n"
  },
  {
    "path": "VQ/VQM32/DRAWCHAR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header:   U:\\vq\\projects\\vqm32\\drawchar.asv   1.1   08 May 1995 10:48:32   DENZIL_LONG  $\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : DRAWCHAR.ASM                             *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : August 20, 1993                          *\n;*                                                                         *\n;*                  Last Update : August 20, 1993   [JLB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\nXPIXEL_MAX\t\tEQU\t320\nYPIXEL_MAX\t\tEQU\t200\n\nFONTINFOBLOCK\t\tEQU\t4\nFONTOFFSETBLOCK\tEQU\t6\nFONTWIDTHBLOCK\tEQU\t8\nFONTDATABLOCK\t\tEQU\t10\nFONTHEIGHTBLOCK\tEQU\t12\n\nFONTINFOMAXHEIGHT\tEQU\t4\nFONTINFOMAXWIDTH\tEQU\t5\n\n\tEXTRN\tFontPtr:NEAR PTR\n\n;***********************************************************\n; DRAW_CHAR\n;\n; VOID Draw_Char(BYTE fontchar, WORD x_pixel, WORD y_pixel);\n;\n; Draws a character to the screen only if given coordinates that will allow\n; the entire character to be drawn on the screen else will exit.\n; \n; NOTE: This is a routine called by Text_Print.\n;\n;*\n\tGLOBAL\tC Draw_Char:NEAR\n\tPROC\tDraw_Char C NEAR USES eax ebx ecx edx esi edi \n\tARG\tfontchar:DWORD\n\tARG\tx_pixel:DWORD\n\tARG\ty_pixel:DWORD\n\n\tLOCAL\tinfoblock:DWORD\n\tLOCAL\toffsetblock:DWORD\n\tLOCAL\twidthblock:DWORD\n\tLOCAL\theightblock:DWORD\n\tLOCAL\tfwidth:DWORD\n\tLOCAL\tnextline:DWORD\n\tLOCAL\tstartv:BYTE\n\tLOCAL\tdheight:BYTE\n\tLOCAL\twheight:BYTE\n\n\tmov\tesi,[FontPtr]\n\n\t; Set up some working local variables.\n\n\txor\teax,eax\n\tmov\tax,[esi+FONTINFOBLOCK]\t; get offset to info block\n\tmov\t[infoblock],eax\t\t; save offset to info block\n\tmov\tax,[esi+FONTOFFSETBLOCK]\t; get offset to offset block\n\tmov\t[offsetblock],eax\t\t; save offset to offset block\n\tmov\tax,[esi+FONTWIDTHBLOCK]\t; get offset to width block\n\tmov\t[widthblock],eax\t\t; save offset to width block\n\tmov\tax,[esi+FONTHEIGHTBLOCK]\t; get offset to height block\n\tmov\t[heightblock],eax\t\t; save offset to height block\n\n\t; Fetch character data offset -- if NULL then undefined character.\n\n\tmov\tebx,[fontchar]\n\tand\tebx,0FFh\n\tshl\tebx,1\t\t; make word index\n\tadd\tebx,[offsetblock]\t; add offset to offset block\n\txor\tecx,ecx\n\tmov\tcx,[esi+ebx]\t\t; load offset to font data\n\tor\tecx,ecx\n\tjz\t??exit\t\t; is this character a null? if so exit\n\n\t; If the character is off the left/right edge of the screen then abort.\n\n\tmov\tedx,[x_pixel]\n\tcmp\tedx,XPIXEL_MAX\n\tjae\t??exit\n\n\t; If the character is off the top/bottom edge of the screen then abort.\n\n\tmov\tebx,[fontchar]\t\t; get char\n\tand\tebx,0FFh\n\tadd\tebx,[widthblock]\t; add offset to width block\n\txor\teax,eax\n\tmov\tal,[esi+ebx]\t\t; get width for character\n\tmov\t[fwidth],eax\t\t; save char width\n\tadd\teax,edx\t\t; ax = char len + x\n\tcmp\teax,XPIXEL_MAX\n\tja\t??exit\n\n\tmov\tedi,edx\t\t; save xpos in di\n\n\tmov\tedx,[y_pixel]\n\tcmp\tedx,YPIXEL_MAX\n\tjae\t??exit\n\n\tmov\tebx,[infoblock]\t; get offset to offset block\n\txor\teax,eax\n\t\t\t\t; get font max height from info block\n\tmov\tal,[esi+ebx+FONTINFOMAXHEIGHT]\n\tmov\t[wheight],al\t\t; save max height of character\n\tadd\teax,edx\t\t; add height to y pos\n\tcmp\teax,YPIXEL_MAX\t\t; will it go off the bottom\n\tja\t??exit\n\n??vdraw:\n\tmov\tebx,[fontchar]\t\t; get char\n\tand\tebx,0FFh\n\tshl\tebx,1\t\t; make 2 byte index\n\tadd\tebx,[heightblock]\t; add offset to height block\n\tmov\tah,[esi+ebx]\t\t; get start vertical for character\n\tmov\t[startv],ah\t\t; save start vertical for later\n\tmov\tal,[esi+ebx+1]\t\t; get data height for character\n\tmov\t[dheight],al\t\t; save data height for later\n\tadd\tah,al\t\t; add background and data\n\tsub\t[wheight],ah\t\t; remaining background height\n\n\tadd\tesi,ecx\t\t; add font offset to font data\n\n\tpush\tedx\n\tmov\teax,XPIXEL_MAX\n\tmul\tedx\n\tadd\tedi,eax\n\tpop\tedx\n\n\tmov\teax,XPIXEL_MAX\n\tsub\teax,[fwidth]\n\tmov\t[nextline],eax\t\t; ?? to add to index for the nextline\n\n\tadd\tedi,0A0000h\n\tmov\tebx,OFFSET ColorXlat\t; setup up bx for xlat commands\n\txor\tecx,ecx\n\tmov\tcl,[startv]\t\t; number of scan lines that are\n\t\t\t\t; background color\n\tor\tecx,ecx\t\t; if starting vertical is zero\n\tje\tshort ??skiplead\t; skip drawing top background lines\n\n\tmov\tal,0\n\txlat\t[ebx]\t\t; get background color\n\n\tor\tal,al\t\t; check for none zero color\n\tjne\tshort ??lheight\t; update background color\n\n\tpush\tedx\n\tmov\teax,XPIXEL_MAX\n\tmul\tecx\n\tadd\tedi,eax\n\tpop\tedx\n\n\tmov\tebx,OFFSET ColorXlat\t; restore bx for xlat commands\n\tjmp\tSHORT ??skiplead\n\n??lheight:\n\tmov\tedx,[fwidth]\t\t; width of char\n\n??lwidth:\n\tstosb\t\t\t; write out line of pixels for width\n\tdec\tedx\n\tjne\t??lwidth\n\n??lnext:\n\tadd\tedi,[nextline]\t\t; goto next line at the start of char\n\tloop\t??lheight\t\t; any more lines\n\n??skiplead:\n\tmov\tcl,[dheight]\t\t; number of scan lines that are data\n\tor\tecx,ecx\t\t; is there any data to be drawn\n\tje\tshort ??exit\n\n??vheight:\n\tmov\tedx,[fwidth]\t\t; width of char\n\n??vwidth:\n\tlodsb\t\t\t\t; get byte value from font data\n\tmov\tah,al\t\t\t; save hinibble\n\tand\tal,00FH\t\t\t; get lonibble\n\txlat\t[ebx]\t\t\t; get new color\n\tor\tal,al\n\tje\tshort ??chklowidth\t\t; skip color zero\n\n\tmov\t[edi],al\t\t; write out pixel of lonibble\n\n??chklowidth:\n\tinc\tedi\n\tdec\tedx\n\tje\tshort ??vnext\t\t\t; check if done with width of char\n\n\tmov\tal,ah\t\t\t; get byte value\n\tand\tal,0F0H\t\t\t; get hinibble\n\txlat\t[ebx]\t\t\t; get new color\n\tor\tal,al\n\tje\tshort ??chkhiwidth\t\t; skip color zero\n\n\tmov\t[edi],al\t\t; write out pixel of hinibble\n\n??chkhiwidth:\n\tinc\tedi\n\tdec\tedx\n\tjne\t??vwidth\t\t; check if done with width of char\n\n??vnext:\n\tadd\tedi,[nextline]\t\t; next line at start of char\n\tloop\t??vheight\t\t; any more lines\n\n\n??trail:\n\tmov\tcl,[wheight]\t\t; remaining height of background color\n\tor\tecx,ecx\t\t\t; if trailing height is zero\n\tjle\tshort ??exit\t\t\t; skip drawing bottom background lines\n\n\tmov\tal,0\n\txlat\t[ebx]\t\t\t; get background color\n\tor\tal,al\t\t\t; check for color zero\n\tje\tshort ??exit\t\t\t; skip drawing\n\n??theight:\n\tmov\tedx,[fwidth]\t\t; width of char\n\n??twidth:\n\tstosb\t\t\t\t; write out line of pixels for width\n\tdec\tedx\n\tjne\t??twidth\n\n??tnext:\n\tadd\tedi,[nextline]\t\t; next line at start of char\n\tloop\t??theight\t\t; any more lines\n\n\n??exit:\n\tret\n\n\tENDP\tDraw_Char\n\n;***********************************************************\n\n\n;***********************************************************\n; SET_FONT_PALETTE_RANGE\n;\n; VOID Set_Font_Palette_Range(VOID *palette, WORD start, WORD end);\n;\n; This routine changes the local Draw_Char color translation table\n; with the color numbers in palette.\n;\n; Bounds Checking: forces start and end to a range of 0-15\n;*\n\tGLOBAL\tC Set_Font_Palette_Range:NEAR\n\tPROC\tSet_Font_Palette_Range C NEAR USES eax ebx ecx edi esi\n\tARG\tpalette:NEAR PTR\n\tARG\tstart:DWORD\n\tARG\tendval:DWORD\n\n\tcld\n\tmov\tesi,[palette]\n\tmov\tebx,[start]\n\tand\tebx,0FH\t\t\t; value 0-15\n\n\tmov\tecx,[endval]\n\tand\tecx,0FH\t\t\t; value 0-15\n\n\tcmp\tecx,ebx\t\t\t; if end < start then exit\n\tjl\tshort ??exit\n\n\tsub\tecx,ebx\t\t\t; number of colors = end - start + 1\n\tinc\tecx\n\n\tmov\tedi,OFFSET ColorXlat\t; get start of xlat table\n\tadd\tedi,ebx\t\t\t; add starting offset\n\tshl\tebx,4\t\t\t; multiply start offset by 16\n\tadd\tebx,OFFSET ColorXlat\t; add start of xlat table\n\n; updates 0-15 for lonibble xlat\n; updates 0,16,32,...,240 for hinibble xlat\n\n??setpal:\n\tlodsb\t\t\t\t; get color number\n\tstosb\t\t\t\t; save color number for lonibble xlat\n\tmov\t[ebx],al\t\t; save color number for hinibble xlat\n\tadd\tebx,010H\t\t\t; add 16 to index for hinibble offset\n\tloop\t??setpal\n\n??exit:\n\tret\n\n\tENDP\tSet_Font_Palette_Range\n\n;***********************************************************\n\n\n;***********************************************************\n; DRAW_CHAR_SETUP\n;\n; VOID Draw_Char_Setup(VOID);\n;\n; This routine sets up code segment variables for Draw_Char.\n; \n; NOTE: This is a routine called by Set_Font.\n;\n;*\n\tGLOBAL\tC Draw_Char_Setup:NEAR\n\tPROC\tDraw_Char_Setup C NEAR\n\n\tret\n\n\tENDP\tDraw_Char_Setup\n\n\tDATASEG\n\nColorXlat\tDB\t000H,001H,002H,003H,004H,005H,006H,007H\n\tDB\t008H,009H,00AH,00BH,00CH,00DH,00EH,00FH\n\n\tDB\t001H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t002H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t003H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t004H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t005H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t006H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t007H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t008H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t009H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00AH,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00BH,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00CH,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00DH,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00EH,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00FH\n\n;***********************************************************\n\tEND\n\n"
  },
  {
    "path": "VQ/VQM32/FILLRECT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     fillrect.asm\n;*\n;* DESCRIPTION\n;*     Rectangle rendering.\n;*\n;* PROGRAMMER\n;*     Joe L. Bostic\n;*\n;* DATE\n;*     Febuary 8, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     Fill_Rect - Draw a filled rectangle.\n;*     Eor_Region - Hilights or unhilights a region by EOR it.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     Eor_Region - Hilights or unhilights a region by EOR it.\n;*\n;* SYNOPSIS\n;*     Eor_Region(X1, Y1, X2, Y2, Color)\n;*\n;*     void Eor_Region(long, long, long, long, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     X1    - Starting X position.\n;*     Y1    - Starting Y position.\n;*     X2    - Ending X position.\n;*     Y2    - Ending Y position.\n;*     Color - Color to EOR.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Eor_Region:NEAR\n\tPROC\tEor_Region C NEAR USES eax ebx ecx edx edi\n\tARG\tx1_pixel:DWORD\n\tARG\ty1_pixel:DWORD\n\tARG\tx2_pixel:DWORD\n\tARG\ty2_pixel:DWORD\n\tARG\tcolor:DWORD\n\tLOCAL\teorit:DWORD\n\n\tmov\t[eorit],1\n\tjmp\tshort Fill_Rect_Entry\n\n\tENDP\tEor_Region\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Fill_Rect - Draw a filled rectangle.\n;*\n;* SYNOPSIS\n;*     Fill_Rect(X1, Y1, X2, Y2, Color)\n;*\n;*     void Fill_Rect(long, long, long, long, long);\n;*\n;* FUNCTION\n;*     Fill a rectangle area with a specified color.\n;*\n;* INPUTS\n;*     X1    - Starting X position.\n;*     Y1    - Starting Y position.\n;*     X2    - Ending X position.\n;*     Y2    - Ending Y position.\n;*     Color - Color to draw rectangle\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Fill_Rect:NEAR\n\tPROC\tFill_Rect C NEAR USES eax ebx ecx edx edi\n\tARG\tx1_pixel:DWORD\n\tARG\ty1_pixel:DWORD\n\tARG\tx2_pixel:DWORD\n\tARG\ty2_pixel:DWORD\n\tARG\tcolor:DWORD\n\tLOCAL\teorit:DWORD\n\n\tmov\t[eorit],0\n\nFill_Rect_Entry:\n\tcld\t\t\t; always go forward\n\tmov\tedi,0A0000h\n\n\t; Verify bounds of x1_pixel.\n\tmov\teax,[x1_pixel]\n\tcmp\teax,320\t;XPIXEL_MAX\n\tjae\tshort ??exit\n\n\t; Verify bounds of x2_pixel.\n\tmov\tebx,[x2_pixel]\n\tcmp\tebx,320\t;XPIXEL_MAX\n\tjae\tshort ??exit\n\n\t; Backward rectangles are legal -- adjust for it.\n\tcmp\teax,ebx\n\tjbe\tshort ??okx\n\txchg\teax,ebx\n??okx:\n\n\t; Verify bounds of y1_pixel.\n\tmov\tecx,[y1_pixel]\n\tcmp\tecx,200\t;YPIXEL_MAX\n\tjae\tshort ??exit\n\n\t; Verify bounds of y2_pixel.\n\tmov\tedx,[y2_pixel]\n\tcmp\tedx,200\t;YPIXEL_MAX\n\tjae\tshort ??exit\n\n\t; Backward rectangles are legal -- adjust for it.\n\tcmp\tecx,edx\n\tjbe\tshort ??oky\n\txchg\tecx,edx\n??oky:\n\n\t; Set DX for height and BX for width.\n\tsub\tedx,ecx\n\tinc\tedx\n\tsub\tebx,eax\n\tinc\tebx\n\n\t; Adjust DI to match offset into page of upper left corner.\n\tpush\tedx\n\tpush\teax\n\tmov\teax,320\t;XPIXEL_MAX\n\tmul\tecx\n\tadd\tedi,eax\t\t\t; Add in Y offset.\n\tpop\tedx\n\tadd\tedi,edx\t\t\t; Add in X offset.\n\tpop\tedx\n\n\t; Fill the region with the specified color.\n\tmov\teax,320\t;XPIXEL_MAX\n\tsub\teax,ebx\n\txchg\teax,[color]\n\tmov\tah,al\n\tcmp\t[eorit],0\n\tje\tshort ??loop\n\n;------\tEOR rectangle filling.\n??loop2:\n\tmov\tecx,ebx\t\t\t; Length of row\n??loop2in:\n\tlodsb\n\txor\tal,ah\n\tstosb\n\tloop\t??loop2in\n\tadd\tedi,[color]\t\t; Modulo add for next line prep.\n\tdec\tedx\n\tjg\tshort ??loop2\n\tjmp\tshort ??exit\n\n;------\tConventional rectangle filling.\n??loop:\n\tmov\tecx,ebx\t\t\t; Length of row\n\tshr\tecx,1\n\trep\tstosw\n\tadc\tecx,0\n\trep\tstosb\n\tadd\tedi,[color]\t\t; Modulo add for next line prep.\n\tdec\tedx\n\tjg\tshort ??loop\n\n??exit:\n\tret\n\n\tENDP\tFill_Rect\n\n\tEND\n\n"
  },
  {
    "path": "VQ/VQM32/FONT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*---------------------------------------------------------------------------\n*\n* FILE\n*     font.c\n*\n* DESCRIPTION\n*     Font manipulation.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     March 9, 1995\n*\n*---------------------------------------------------------------------------\n*\n* PUBLIC\n*     Load_Font          - Open a font for use.\n*     Set_Font           - Set the default system font.\n*     String_Pixel_Width - Get the pixel width of a string.\n*\n****************************************************************************/\n\n#include <stdlib.h>\n#include <fcntl.h>\n#include <io.h>\n#include <string.h>\n#include <malloc.h>\n#include \"font.h\"\n\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n/* min and max macros */\n#ifdef __cplusplus\n#ifndef max\n#define max(a,b)  (((a) > (b)) ? (a) : (b))\n#endif\n#ifndef min\n#define min(a,b)  (((a) < (b)) ? (a) : (b))\n#endif\n#endif\n\nvoid const *FontPtr = NULL;\nchar FontHeight = 8;\nchar FontWidth = 8;\nint FontXSpacing = 0;\nint FontYSpacing = 0;\nchar *FontWidthBlockPtr = NULL;\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_Font - Open a font for use.\n*\n* SYNOPSIS\n*     Font = Load_Font(Name)\n*\n*     char *Load_Font(char *);\n*\n* FUNCTION\n*     Open a graphics font for use by Text_Print(). Use free() to dispose\n*     of the font.\n*\n* INPUTS\n*     Name - Name of font file to open.\n*\n* RESULT\n*     Font - Pointer to font, NULL if error.\n*\n****************************************************************************/\n\nvoid *cdecl Load_Font(char const *name)\n{\n\tFont  *font = NULL;\n\tlong  fh;\n\tshort size;\n\tshort valid;\n\n\t/* Open the font. */\n\tif ((fh = open(name, (O_RDONLY|O_BINARY))) != -1) {\n\n\t\t/* Get the size of the font. */\n\t\tif (read(fh, &size, 2) == 2) {\n\n\t\t\t/* Allocate memory to contain the font. */\n\t\t\tif ((font = (Font *)malloc((unsigned long)size)) != NULL) {\n\t\t\t\tvalid = 0;\t\n\n\t\t\t\t/* Read in the body of the font. */\n\t\t\t\tif (read(fh, &font->CompMethod, (unsigned long)(size - 2))\n\t\t\t\t\t\t== (unsigned long)(size - 2)) {\n\t\t\t\t\t\n\t\t\t\t\t/* Verify the validity of the font. */\n\t\t\t\t\tif ((font->CompMethod == 0) && (font->NumBlks == 5)) {\n\t\t\t\t\t\tfont->Size = size;\n\t\t\t\t\t\tvalid = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* Free the font if it is not valid. */\n\t\t\t\tif (valid == 0) {\n\t\t\t\t\tfree(font);\n\t\t\t\t\tfont = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Close the font. */\n\t\tclose(fh);\n\t}\n\n\treturn ((char *)font);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Set_Font - Set the default system font.\n*\n* SYNOPSIS\n*     OldFont = Set_Font(Font)\n*\n*     char *Set_Font(char *);\n*\n* FUNCTION\n*     Sets up the specified font as the default font used by the system.\n*\n* INPUTS\n*     Font - Pointer to Font to set as default. (NULL returns current font)\n*\n* RESULT\n*     OldFont - Previous font.\n*\n****************************************************************************/\n\nvoid *cdecl Set_Font(void const *font)\n{\n\tvoid const *oldfont;\n\tFontInfo   *fi;\n\n\toldfont = FontPtr;\n\t\n\tif (font != NULL) {\n\t\tFontWidthBlockPtr = ((char *)font + ((Font *)font)->WidthBlk);\n\t\tfi = (FontInfo *)((char *)font + ((Font *)font)->InfoBlk);\n\t\tFontHeight = fi->MaxHeight;\n\t\tFontWidth = fi->MaxWidth;\n\t\tFontPtr = font;\n\t}\n\n\treturn ((void *)oldfont);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     String_Pixel_Width - Get the pixel width of a string.\n*\n* SYNOPSIS\n*     Width = String_Pixel_Width(String)\n*\n*     long String_Pixel_Width(char *);\n*\n* FUNCTION\n*     Calculates the pixel width of a string of characters.\n*\n* INPUTS\n*     String - Pointer to string to calculate width for.\n*\n* RESULT\n*     Width - Width of string in pixels.\n*\n****************************************************************************/\n\nunsigned short String_Pixel_Width(char const *string)\n{\n\tlong width = 0;\n\tlong largest = 0;\n\n\twhile (*string != NULL) {\n\t\tif (*string == '\\r') {\n\t\t\tstring++;\n\t\t\tlargest = max(largest, width);\n\t\t\twidth = 0;\n\t\t} else {\n\t\t\twidth += Char_Pixel_Width(*string++);\n\t\t}\n\t}\n\n\tlargest = max(largest, width);\n\n\treturn (largest);\n}\n\n"
  },
  {
    "path": "VQ/VQM32/FONT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMFONT_H\n#define VQMFONT_H\n/****************************************************************************\n*\n*        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\n*\n*---------------------------------------------------------------------------\n*\n* FILE\n*     font.h\n*\n* DESCRIPTION\n*     Font definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     March 9, 1995\n*\n****************************************************************************/\n\n/* Font: A Westwood style font.\n *\n * Size       - Size of font.\n * CompMethod - Compression method of font. (0 = none)\n * NumBlks    - Number of data blocks.\n * InfoBlk    - Offset to font information block.\n * OffsetBlk  - Offset to character offset block.\n * WidthBlk   - Offset to character width block.\n * DataBlk    - Offset to character data block.\n * HeightBlk  - Offset to character height block.\n */\ntypedef struct _Font {\n\tunsigned short Size;\n\tunsigned char  CompMethod;\n\tunsigned char  NumBlks;\n\tunsigned short InfoBlk;\n\tunsigned short OffsetBlk;\n\tunsigned short WidthBlk;\n\tunsigned short DataBlk;\n\tunsigned short HeightBlk;\n} Font;\n\ntypedef struct _FontInfo {\n\tlong huh;\n\tunsigned char MaxHeight;\n\tunsigned char MaxWidth;\n} FontInfo;\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern void const *FontPtr;\nextern int FontXSpacing;\nextern int FontYSpacing;\n\n#ifdef __cplusplus\n}\n#endif\n\nextern char FontWidth;\nextern char FontHeight;\nextern char *FontWidthBlockPtr;\n\n/* Function prototypes. */\nvoid *cdecl Load_Font(char const *name);\nvoid *cdecl Set_Font(void const *font);\nunsigned short cdecl String_Pixel_Width(char const *string);\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef __WATCOMC__\nlong cdecl __saveregs Char_Pixel_Width(char chr);\n#else\nlong cdecl Char_Pixel_Width(char chr);\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMFONT_H */\n\n"
  },
  {
    "path": "VQ/VQM32/GRAPHICS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMGRAPHICS_H\n#define VQMGRAPHICS_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     graphics.h\n*\n* DESCRIPTION\n*     Graphic rendering and manipulation definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 27, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid cdecl Eor_Region(long sx, long sy, long dx, long dy, long color);\nvoid cdecl Fill_Rect(long x1, long y1, long x2, long y2, long color);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMGRAPHICS_H */\n\n"
  },
  {
    "path": "VQ/VQM32/HUFFCMP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     huffcmp.h\n*\n* DESCRIPTION\n*     Huffman order 0 compressor.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*      \n* DATE\n*     May 19, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     HuffCompress    - Compress data using huffman order 0 compression.\n*     HuffCount       - Count the frequency of occurence of every byte.\n*     HuffScaleCounts - Scale down the frequency counts.\n*     RLEHuffCounts   - Run Length Encode the Huffman counts.\n*     ConvertToCodes  - Convert the Huffman tree into a table of codes.\n*     HuffEncode      - Huffman encode the data.\n*\n****************************************************************************/\n\n#include <mem.h>\n#include \"huffman.h\"\n\n\n/****************************************************************************\n*\n* NAME\n*     HuffCompress - Compress data using huffman order 0 compression.\n*\n* SYNOPSIS\n*     Size = HuffCompress(Data, Buffer, Size, Temp)\n*\n*     long HuffCompress(unsigned char *, unsigned char *, long, char *);\n*\n* FUNCTION\n*     This function performs an order 0 Huffman encoding of the input data.\n*     The algorithm used is fairly straightforward. First a count is made of\n*     all the bytes in the input data, then the counts are scaled down to\n*     a single byte representation in the node array. After the counts are\n*     scaled, a Huffman decoding tree is built from the node array. Then\n*     a code array is built by traversing the tree for each symbol. Finally,\n*     the input data is compressed.\n*\n* INPUTS\n*     Data   - Pointer to data to compress.\n*     Buffer - Pointer to compressed data.\n*     Size   - Length of data to compress.\n*     Temp   - Pointer to temporary working buffer. (Must be >= 5120 bytes!)\n*\n* RESULT\n*     Size - Compressed size.\n*\n****************************************************************************/\n\nlong cdecl HuffCompress(unsigned char *data, unsigned char *buffer,\n\t\tlong length, char *temp)\n{\n\t#if(1)\n\tTreeNode *nodes;\n\tHuffCode *codes;\n\tlong     size;\n\tlong     root;\n\n\t/* Initialize variables */\n\tnodes = (TreeNode *)temp;\n\ttemp += (514 * sizeof(TreeNode));\n\tcodes = (HuffCode *)temp;\n\n\t/* Analyze the frequency of the data. */\n\tHuffCount(data, nodes, length, 1);\n\tHuffScaleCounts(nodes);\n\n\t/* Save the counts for the decompression. */\n\tsize = RLEHuffCounts(nodes, buffer);\n\tbuffer += size;\n\n\t/* Build the Huffman decode tree and generate codes for encoding. */\n\troot = BuildHuffTree(nodes);\n\tConvertToCodes(nodes, codes, 0, 0, root);\n\n\t/* Encode the data. */\n\tsize += HuffEncode(data, buffer, codes, length);\n\n\treturn (size);\n\t#else\n\tTreeNode      *nodes;\n\tHuffCode      *codes;\n\tunsigned long *counts;\n\tunsigned long max_count;\n\tlong          i;\n\tlong          size;\n\tlong          first;\n\tlong          last;\n\tlong          next;\n\tunsigned long symbol;\n\tunsigned long mask;\n\n\t/* Initialize variables. */\n\tnodes = (TreeNode *)temp;\n\ttemp += (514 * sizeof(TreeNode));\n\tcounts = (unsigned long *)temp;\n\tcodes = (HuffCode *)temp;\n\n\t/* Zero the initial counts. */\n\tmemset(temp, 0, 256 * sizeof(unsigned long));\n\tsize = 0;\n\n\t/*-------------------------------------------------------------------------\n\t * Calculate the distribution of the data then scale down the counts so\n\t * they fit in an 8 bit value. This is done in order to limit the size of\n\t * the codes to 16 bits.\n\t *-----------------------------------------------------------------------*/\n\ti = 0;\n\n\twhile (i < length) {\n\t\tcounts[((unsigned char *)data)[i]]++;\n\t\ti++;\n\t}\n\n\t/* Scale down the counts. */\n\tmax_count = 0;\n\n\t/* Find the maximum count. */\n\tfor (i = 0; i < 256; i++) {\n\t\tif (counts[i] > max_count) {\n\t\t\tmax_count = counts[i];\n\t\t}\n\t}\n\n\tif (max_count == 0) {\n\t\tcounts[0] = 1;\n\t\tmax_count = 1;\n\t}\n\n\tmax_count /= 255;\n\tmax_count++;\n\n\t/* Scale down the counts. */\n\tfor (i = 0; i < 256; i++) {\n\t\tnodes[i].count = (unsigned long)(counts[i] / max_count);\n\n\t\t/* Make sure that a node with a non-zero count does not get scaled\n\t\t * down to zero.\n\t\t */\n\t\tif ((nodes[i].count == 0) && (counts[i] != 0)) {\n\t\t\tnodes[i].count = 1;\n\t\t}\n\t}\n\n\tnodes[HUFF_EOS].count = 1;\n\n\t/*-------------------------------------------------------------------------\n\t * OUTPUT THE COUNTS\n\t *\n\t * In order to save space, we store runs of counts in the following format:\n\t *\n\t *   Start, Stop, Counts..., Start, Stop, Counts..., ..., 0\n\t *\n\t * The list is terminated by storing a start value of zero (0).\n\t *\n\t * In order to efficiently use this format, we do not want to stop a run\n\t * because of just one or two zero counts. So we include zero counts of\n\t * less than three (3) in the run.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Find the first occurance of a non-zero count. */\n\tfirst = 0;\n\n\twhile ((first < 255) && (nodes[first].count == 0)) {\n\t\tfirst++;\n\t}\n\n\t/* Each time I hit the start of the loop, I assume that first is the\n\t * number for a run of non-zero values.  The rest of the loop is\n\t * concerned with finding the value for last, which is the end of the\n\t * run, and the value of next, which is the start of the next run.\n\t * At the end of the loop, I assign next to first, so it starts in on\n\t * the next run.\n\t */\n\tfor (; first < 256; first = next) {\n\t\tlast = first + 1;\n\n\t\tfor (;;) {\n\n\t\t\t/* Find the end of the run of non-zeros. */\n\t\t\tfor (; last < 256; last++) {\n\t\t\t\tif (nodes[last].count == 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t    last--;\n\n\t\t\t/* Check the beginning of the next run of non-zero counts. */\n\t\t\tfor (next = last + 1; next < 256; next++) {\n\t\t\t\tif (nodes[next].count != 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Quit the run if we have reached the end. */\n\t\t\tif (next > 255) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/* Quit the run if there is more than three non-zero counts. */\n\t\t\tif ((next - last) > 3) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t  last = next;\n\t\t};\n\n\t\t/* Output Start and Stop. */\n\t\t*buffer++ = first;\n\t\t*buffer++ = last;\n\n\t\t/* Output the run of counts. */\n\t\tfor (i = first; i <= last; i++) {\n\t\t\t*buffer++ = (char)nodes[i].count;\n\t\t}\n\n\t\tsize += (((last - first) + 1) + 2);\n\t}\n\n\t/* Output terminator. */\n\t*buffer++ = 0;\n\tsize++;\n\n\t/*-------------------------------------------------------------------------\n\t * Build the Huffman tree. All active nodes are scanned in order to locate\n\t * the two nodes with the minimum weights. These two weights are added\n\t * together and assigned to a new node. The new node makes the two minimum\n\t * nodes into its 0 child and 1 child. The two minimum nodes are then\n\t * marked as inactive. This process repeats until their is only one node\n\t * left, which is the root node.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Node 513 is used to arbitratilly provide a node with a guaranteed\n\t * maximum value.\n\t */\n\tnodes[513].count = 0xFFFF;\n\n\tfor (next = (HUFF_EOS + 1); ; next++) {\n\t\tfirst = 513;\n\t\tlast = 513;\n\n\t\tfor (i = 0; i < next; i++) {\n\n\t\t\t/* We are only concerned with non-zero count nodes. */\n\t\t\tif (nodes[i].count != 0) {\n\t\t\t\tif (nodes[i].count < nodes[first].count) {\n\t\t\t\t\tlast = first;\n\t\t\t\t\tfirst = i;\n\t\t\t\t} else if (nodes[i].count < nodes[last].count) {\n\t\t\t\t\tlast = i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (last == 513) {\n\t\t\tbreak;\n\t\t}\n\n\t\tnodes[next].count = (nodes[first].count + nodes[last].count);\n\t\tnodes[first].count = 0;\n\t\tnodes[last].count = 0;\n\t\tnodes[next].child0 = (first << 3);\n\t\tnodes[next].child1 = (last << 3);\n\t}\n\n\tnext--;\n\n\t/*-------------------------------------------------------------------------\n\t * Convert the Huffman tree into an encoding table then encode the data.\n\t *-----------------------------------------------------------------------*/\n\tConvertToCodes(nodes, codes, 0, 0, (next << 3));\n\n\t/* Encode the data. */\n\t*buffer = 0;\n\tnext = 0x80;\n\ti = 0;\n\n\tdo {\n\t\tif (i < length) {\n\t\t\tsymbol = ((unsigned char *)data)[i];\n\t\t} else {\n\t\t\tsymbol = HUFF_EOS;\n\t\t}\n\n\t\tmask = 1L << (codes[symbol].bits - 1);\n\t\t\n\t\twhile (mask != 0) {\n\n\t\t\t/* Set a bit in the output stream for each bit in the code. */\n\t\t\tif (mask & codes[symbol].code) {\n\t\t\t\t*buffer |= next;\n\t\t\t}\n\n\t\t\t/* Next bit position. */\n\t\t\tnext >>= 1;\n\n\t\t\t/* Advance to the next byte in the output stream when the current\n\t\t\t * byte is full.\n\t\t\t */\n\t\t\tif (next == 0) {\n\t\t\t\tbuffer++;\n\t\t\t\t*buffer = 0;\n\t\t\t\tnext = 0x80;\n\t\t\t\tsize++;\n\t\t\t}\n\n\t\t\t/* Next bit in the code. */\n\t\t\tmask >>= 1;\n\t\t}\n\n\t\ti++;\n\t} while (symbol != HUFF_EOS);\n\n\tif (next != 0x80) {\n\t\tsize++;\n\t}\n\n\treturn (size);\n\t#endif\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     HuffCount - Count the frequency of occurence of every byte.\n*\n* SYNOPSIS\n*     HuffCount(Data, Nodes, Length, Zero)\n*\n*     void HuffCounts(unsigned char *, TreeNode *, long, long);\n*\n* FUNCTION\n*     This function counts the frequency of occurence of every byte in the\n*     input data. The nodes must be initialized to zero prior to calling this\n*     function for the first time, otherwise the counts will be flawed.\n*\n* INPUTS\n*     Data     - Pointer to data to analyze.\n*     TreeNode - Pointer to array of nodes.\n*     Length   - Length of data to analyze.\n*     Zero     - Zero any previous counts flag. (TRUE = zero counts)\n*\n* RESULT\n*     Size - Amount of buffer used to hold counts.\n*\n****************************************************************************/\n\nvoid cdecl HuffCount(unsigned char *data, TreeNode *nodes, long length,\n\t\tlong zero)\n{\n\tlong i;\n\t\n\t/* Zero any previous counts. */\n\tif (zero) {\n\t\tfor (i = 0; i < 256; i++) {\n\t\t\tnodes[i].count = 0;\n\t\t}\n\t}\n\n\t/* Calculate the distribution of the data. */\n\ti = 0;\n\n\twhile (i < length) {\n\t\tnodes[((unsigned char *)data)[i]].count++;\n\t\ti++;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     HuffScaleCounts - Scale down the frequency counts.\n*\n* SYNOPSIS\n*     HuffScaleCounts(Nodes)\n*\n*     void HuffScaleCounts(TreeNode *);\n*\n* FUNCTION\n*     In order to limit the size of the Huffman codes to 16 bits, we must\n*     scale down the counts so they can be represented by a BYTE size value.\n*\n* INPUTS\n*     Nodes  - Pointer to nodes to scale counts for.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid cdecl HuffScaleCounts(TreeNode *nodes)\n{\n\tunsigned long max_count;\n\tunsigned long unscaled;\n\tlong          i;\n\tlong          first;\n\tlong          last;\n\tlong          next;\n\n\t/* Scale down the counts so they fit in an 8 bit value. This is done in\n\t * order to limit the size of the codes to 16 bits.\n\t */\n\tmax_count = 0;\n\n\t/* Find the maximum count. */\n\tfor (i = 0; i < 256; i++) {\n\t\tif (nodes[i].count > max_count) {\n\t\t\tmax_count = nodes[i].count;\n\t\t}\n\t}\n\n\tif (max_count == 0) {\n\t\tnodes[0].count = 1;\n\t\tmax_count = 1;\n\t}\n\n\tmax_count /= 255;\n\tmax_count++;\n\n\t/* Scale down the counts. */\n\tfor (i = 0; i < 256; i++) {\n\t\tunscaled = nodes[i].count;\n\t\tnodes[i].count /= max_count;\n\n\t\t/* Make sure that a node with a non-zero count does not get scaled\n\t\t * down to zero.\n\t\t */\n\t\tif ((nodes[i].count == 0) && (unscaled != 0)) {\n\t\t\tnodes[i].count = 1;\n\t\t}\n\t}\n\n\tnodes[HUFF_EOS].count = 1;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     RLEHuffCounts - Run Length Encode the Huffman counts.\n*\n* SYNOPSIS\n*     Size = RLEHuffCounts(Nodes, Buffer)\n*\n*     long RLEHuffCounts(TreeNode *, unsigned char *);\n*\n* FUNCTION\n*     In order for the decoder to build the same model, we have to transmit\n*     the symbol counts to it. To save space we do not save all 256 symbols\n*     unconditionally, instead we run length encode the counts. The format\n*     used to store the counts is as follows:\n*\n*       Start, Stop, Counts[n], Start, Stop, Counts[n], .... 0\n*\n*     Note: The sequence is terminated by a start value of 0. Also at least\n*     1 run of counts has to be stored, even if the first start value is 0.\n*\n* INPUTS\n*     Nodes  - Pointer to initialized nodes.\n*     Buffer - Pointer to buffer to store RLE'd counts.\n*\n* RESULT\n*     Size - Size of the RLE'd counts.\n*\n****************************************************************************/\n\nlong cdecl RLEHuffCounts(TreeNode *nodes, unsigned char *buffer)\n{\n\tlong i;\n\tlong first;\n\tlong last;\n\tlong next;\n\tlong size = 0;\n\n\t/* Find the first occurance of a non-zero count. */\n\tfirst = 0;\n\n\twhile ((first < 255) && (nodes[first].count == 0)) {\n\t\tfirst++;\n\t}\n\n\t/* Each time I hit the start of the loop, I assume that first is the\n\t * number for a run of non-zero values.  The rest of the loop is\n\t * concerned with finding the value for last, which is the end of the\n\t * run, and the value of next, which is the start of the next run.\n\t * At the end of the loop, I assign next to first, so it starts in on\n\t * the next run.\n\t */\n\tfor (; first < 256; first = next) {\n\t\tlast = first + 1;\n\n\t\tfor (;;) {\n\n\t\t\t/* Find the end of the run of non-zeros. */\n\t\t\tfor (; last < 256; last++) {\n\t\t\t\tif (nodes[last].count == 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t    last--;\n\n\t\t\t/* Check the beginning of the next run of non-zero counts. */\n\t\t\tfor (next = last + 1; next < 256; next++) {\n\t\t\t\tif (nodes[next].count != 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Quit the run if we have reached the end. */\n\t\t\tif (next > 255) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/* Quit the run if there is more than three non-zero counts. */\n\t\t\tif ((next - last) > 3) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t  last = next;\n\t\t};\n\n\t\t/* Output Start and Stop. */\n\t\t*buffer++ = first;\n\t\t*buffer++ = last;\n\n\t\t/* Output the run of counts. */\n\t\tfor (i = first; i <= last; i++) {\n\t\t\t*buffer++ = (unsigned char)nodes[i].count;\n\t\t}\n\n\t\tsize += (((last - first) + 1) + 2);\n\t}\n\n\t/* Output terminator. */\n\t*buffer = 0;\n\tsize++;\n\n\treturn (size);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     ConvertToCodes - Convert the Huffman tree into a table of codes.\n*\n* SYNOPSIS\n*     ConvertToCodes(Nodes, Codes, Code, Bits, Node)\n*\n*     void ConvertToCodes(TreeNode *, HuffCode *, unsigned short, short,\n*                         short);\n*\n* FUNCTION\n*     Since the Huffman tree is built as a decoding tree, there is no simple\n*     way to get the encoding values for each symbol. This routine\n*     recursively walks through the tree, adding the child bits to each code\n*     until it gets to a leaf. When it gets to a leaf, it stores the code\n*     value.\n*\n* INPUTS\n*     Nodes - Pointer to the Huffman tree.\n*     Codes - Pointer to the table of codes to generate.\n*     Code  - Code being built (initialize with 0).\n*     Bits  - Number of bits the code is comprised of (initialize with 0).\n*     Node  - Number of the current node.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid cdecl ConvertToCodes(TreeNode *nodes, HuffCode *codes,\n\t\tunsigned short code, short bits, short node)\n{\n\tnode >>= 3;\n\n\tif (node <= HUFF_EOS) {\n\t\tcodes[node].code = code;\n\t\tcodes[node].bits = bits;\n\t\treturn;\n\t}\n\n\tcode <<= 1;\n\tbits++;\n\tConvertToCodes(nodes, codes, code, bits, nodes[node].child0);\n\tConvertToCodes(nodes, codes, code|1, bits, nodes[node].child1);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     HuffEncode - Huffman encode the data.\n*\n* SYNOPSIS\n*     Size = HuffEncode(Data, Buffer, Codes, Length);\n*\n*     long HuffEncode(unsigned char *, unsigned char *, HuffCodes *, long);\n*\n* FUNCTION\n*     Encoding of the data is simple. Each byte of data is taken as the index\n*     of the codes array, the corresponding code is then put in the output.\n*\n* INPUTS\n*     Data   - Pointer to data to encode.\n*     Buffer - Pointer to buffer to hold encoded data.\n*     Codes  - Pointer to array of Huffman codes.\n*     Length - Length of data buffer to encode.\n*\n* RESULT\n*     Size - Size of encoded data.\n*\n****************************************************************************/\n\nlong cdecl HuffEncode(unsigned char *data, unsigned char *buffer,\n\t\tHuffCode *codes, long length)\n{\n\tlong          i;\n\tlong          size;\n\tlong          next;\n\tunsigned long mask;\n\tunsigned long symbol;\n\n\t/* Initialize */\n\t*buffer = 0;\n\tnext = 0x80;\n\ti = 0;\n\n\tdo {\n\t\tif (i < length) {\n\t\t\tsymbol = ((unsigned char *)data)[i];\n\t\t} else {\n\t\t\tsymbol = HUFF_EOS;\n\t\t}\n\n\t\tmask = 1L << (codes[symbol].bits - 1);\n\t\t\n\t\twhile (mask != 0) {\n\n\t\t\t/* Set a bit in the output stream for each bit in the code. */\n\t\t\tif (mask & codes[symbol].code) {\n\t\t\t\t*buffer |= next;\n\t\t\t}\n\n\t\t\t/* Next bit position. */\n\t\t\tnext >>= 1;\n\n\t\t\t/* Advance to the next byte in the output stream when the current\n\t\t\t * byte is full.\n\t\t\t */\n\t\t\tif (next == 0) {\n\t\t\t\tbuffer++;\n\t\t\t\t*buffer = 0;\n\t\t\t\tnext = 0x80;\n\t\t\t\tsize++;\n\t\t\t}\n\n\t\t\t/* Next bit in the code. */\n\t\t\tmask >>= 1;\n\t\t}\n\n\t\ti++;\n\t} while (symbol != HUFF_EOS);\n\n\tif (next != 0x80) {\n\t\tsize++;\n\t}\n\n\treturn (size);\n}\n\n"
  },
  {
    "path": "VQ/VQM32/HUFFDCMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     huffdcmp.asm\n;*\n;* DESCRIPTION\n;*     Huffman order 0 decompressor.\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     May 22, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     HuffDecompress - Decompress Huffman order 0 encoded data.\n;*     BuildHuffTree  - Build the Huffman decode tree.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\n\tSTRUC\tTreeNode\ncount\tDD\t?\t;Weight of the node\nchild0\tDW\t?\t;Child node 0\nchild1\tDW\t?\t;Child node 1\n\tENDS\tTreeNode\n\nHUFF_EOS\tEQU\t256\n\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     HuffDecompress - Decompress Huffman order 0 encoded data.\n;*\n;* SYNOPSIS\n;*     Size = HuffDecompress(Data, Buffer, Length, Temp)\n;*\n;*     long = HuffDecompress(unsigned char *, unsigned char *, long, char *);\n;*\n;* FUNCTION\n;*     Expand data that has been compressed with order 0 Huffman coding.\n;*     The model (counts) are extracted from the data and a decode tree is\n;*     built. The data is expanded by reading a bit and traversing the tree\n;*     until a leaf node is encountered.\n;*\n;* INPUTS\n;*     Data   - Pointer to Huffman encoded data.\n;*     Buffer - Pointer to decompress buffer.\n;*     Length - Maximum decompress length.\n;*     Temp   - Pointer to temporary working buffer. (Must be >= 5120 bytes!)\n;*\n;* RESULT\n;*     Size - Size of decompressed data.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC HuffDecompress:NEAR\n\tPROC\tHuffDecompress C NEAR USES esi edi ebx ecx edx\n\n\tARG\tdata:NEAR PTR\n\tARG\tbuffer:NEAR PTR\n\tARG\tlength:DWORD\n\tARG\ttemp:NEAR PTR\n\n\tLOCAL\tnext:DWORD\n\n;*---------------------------------------------------------------------------\n;*\tRead in the set of counts\n;*---------------------------------------------------------------------------\n\n\tmov\tesi,[data]\t\t;Compressed data\n\tmov\tebx,[temp]\t\t;Nodes array\n\n\tmov\tax,[esi]\t\t;Get first and last count\n\txor\tedx,edx\t\t;i = 0\n\txor\tecx,ecx\n\tadd\tesi,2\n\n??getcounts:\n\tcmp\tal,dl\t\t;Reached start of run?\n\tjne\t??zerocount\n\n;*\tCopy the run of counts to the nodes\n\n\tsub\tah,al\t\t;Run length = Stop - Start\n\txor\tecx,ecx\n\tmov\tcl,ah\n\txor\teax,eax\n\tinc\tecx\t\t;Run length + 1\n\n??copycounts:\n\tmov\tal,[esi]\t\t;Get count\n\tinc\tedx\t\t;i++\n\tmov\t[ebx],eax\t\t;Write count to node\n\tinc\tesi\n\tadd\tebx,8\t\t;Next node\n\tdec\tecx\n\tjnz\t??copycounts\n\n\tmov\tax,[esi]\t\t;Get next start\n\tinc\tesi\n\tcmp\tal,0\t\t;Terminator?\n\tje\tshort ??nextcount\n\n\tinc\tesi\n\tjmp\tshort ??nextcount\n\n;*\tFill empty nodes with 0\n\n??zerocount:\n\tmov\t[DWORD PTR ebx],ecx\n\tinc\tedx\t\t;i++\n\tadd\tebx,8\t\t;Next node\n\n??nextcount:\n\tcmp\tedx,256\n\tjl\tshort ??getcounts\n\n\tmov\t[WORD PTR ebx],1\n\tmov\t[data],esi\n\n;*---------------------------------------------------------------------------\n;*\tBuild the Huffman tree. All active nodes are scanned in order\n;*\tto locate the two nodes with the minimum weights. These two\n;*\tweights are added together and assigned a new node. The new\n;*\tnode makes the two minimum nodes into its 0 child and 1 child.\n;*\tThe two minimum nodes are then marked as inactive. This process\n;*\trepeats until their is only one node left, which is the root.\n;*---------------------------------------------------------------------------\n\t\n\tmov\teax,[temp]\t\t;Nodes array\n\tmov\tesi,eax\n\tadd\teax,(513 * 8)\t\t;Node[513] = guaranteed maximum\n\tmov\t[DWORD PTR eax],-1\n\n\tmov\t[next],((HUFF_EOS + 1) * 8)\n\n??sortnext:\n\tmov\tedx,(513 * 8)\t\t;first = 513\n\tmov\tedi,edx\t\t;last = 513\n\txor\tecx,ecx\t\t;i = 0\n\tmov\tebx,esi\t\t;nodes[i]\n\n??sortnodes:\n\tcmp\t[WORD PTR ebx],0\t;Only check non-zero nodes\n\tjz\t??nextnode\n\n;*\tnodes[i].count < nodes[first].count\n\n\tmov\teax,[DWORD PTR esi + edx]\n\tcmp\teax,[DWORD PTR ebx]\n\tjbe\t??checklast\n\n\tmov\tedi,edx\t\t;last = first\n\tmov\tedx,ecx\t\t;first = i\n\tjmp\tshort ??nextnode\n\n;*\tnodes[i].count < nodes[last].count\n\n??checklast:\n\tmov\teax,[DWORD PTR esi + edi]\n\tcmp\teax,[DWORD PTR ebx]\n\tjbe\t??nextnode\n\n\tmov\tedi,ecx\t\t;last = i\n\n??nextnode:\n\tadd\tecx,8\t\t;i++\n\tadd\tebx,8\t\t;nodes[i]\n\tcmp\tecx,[next]\n\tjne\tshort ??sortnodes\n\n;*\tTree done when last = 513\n\n\tcmp\tedi,(513 * 8)\n\tje\tshort ??decode\n\n\tmov\tebx,[next]\n\tadd\tebx,esi\n\tmov\t[WORD PTR ebx+4],dx\t;nodes[next].child0 = first\n\tmov\t[WORD PTR ebx+6],di\t;nodes[next].child1 = last\n\n\tadd\tedx,esi\n\tmov\teax,[DWORD PTR edx]\t;nodes[first].count\n\tadd\tedi,esi\n\tmov\t[DWORD PTR ebx],eax\n\t\n\tmov\tecx,[DWORD PTR edi]\t;nodes[last].count\n\txor\teax,eax\n\tadd\t[DWORD PTR ebx],ecx\n\n\tmov\t[DWORD PTR edx],eax\t;nodes[first].count = 0\n\tmov\t[DWORD PTR edi],eax\t;nodes[lats].count = 0\n\tadd\t[next],8\n\tjmp\t??sortnext\n\n;*---------------------------------------------------------------------------\n;*\tExpand the compressed data. As each new symbol is decoded, the\n;*\ttree is traversed, starting at the root node, reading a bit in,\n;*\tand taking either the child0 or child1 path. Eventually, the\n;*\ttree winds down to a leaf node, and the corresponding symbol is\n;*\toutput. If the symbol is the HUFF_EOS symbol the process\n;*\tterminates.\n;*---------------------------------------------------------------------------\n\n??decode:\n\tsub\t[next],8\t\t;rootnode - 1\n\txor\tecx,ecx\n\tmov\tesi,[data]\t\t;Input data buffer\n\tmov\tal,080h\t\t;mask = 0x80\n\tmov\tedi,[buffer]\t\t;Output buffer\n\tmov\tah,[esi]\t\t;Data byte\n\tmov\tebx,[temp]\n\tinc\tesi\n\n??decodeloop:\n\tmov\tedx,[next]\t\t;node = root\n\t\n??walktree:\n\tmov\tecx,4\n\tadd\tecx,edx\n\ttest\tal,ah\n\tjz\tshort ??getnode\n\n\tadd\tecx,2\n\n??getnode:\n\tmov\tdx,[WORD PTR ebx + ecx]\t\t;nodes[node].child\n\tshr\tal,1\n\tjnz\tshort ??checkleaf\n\n\tmov\tah,[esi]\t\t;Get next data byte\n\tmov\tal,080h\t\t;Reset mask\n\tinc\tesi\n\n??checkleaf:\n\tcmp\tedx,(HUFF_EOS * 8)\n\tjg\tshort ??walktree\n\tje\tshort ??done\n\n\tshr\tedx,3\n\tmov\t[edi],dl\n\tinc\tedi\n\tjmp\tshort ??decodeloop\n\n??done:\n\tmov\teax,edi\n\tsub\teax,[buffer]\n\tret\n\n\tENDP\tHuffDecompress\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     BuildHuffTree - Build the Huffman decode tree.\n;*\n;* SYNOPSIS\n;*     Root = BuildHuffTree(Nodes)\n;*\n;*     long BuildHuffTree(TreeNode *);\n;*\n;* FUNCTION\n;*     Build the Huffman tree. All active nodes are scanned in order to\n;*     locate the two nodes with the minimum weights. These two weights are\n;*     added together and assigned a new node. The new node makes the two\n;*     minimum nodes into its 0 child and 1 child. The two minimum nodes are\n;*     then marked as inactive. This process repeats until their is only one\n;*     node left, which is the root.\n;*\n;* INPUTS\n;*     Nodes - Pointer to array of nodes.\n;*\n;* RESULT\n;*     Root - Number of root node.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC BuildHuffTree:NEAR\n\tPROC\tBuildHuffTree C NEAR USES esi edi ebx ecx edx\n\n\tARG\ttemp:NEAR PTR\n\t\n\tLOCAL\tnext:DWORD\n\n\tmov\teax,[temp]\t\t;Nodes array\n\tmov\tesi,eax\n\tadd\teax,(513 * 8)\t\t;Node[513] = guaranteed maximum\n\tmov\t[DWORD PTR eax],-1\n\n\tmov\t[next],((HUFF_EOS + 1) * 8)\n\n??sortnext:\n\tmov\tedx,(513 * 8)\t\t;first = 513\n\tmov\tedi,edx\t\t;last = 513\n\txor\tecx,ecx\t\t;i = 0\n\tmov\tebx,esi\t\t;nodes[i]\n\n??sortnodes:\n\tcmp\t[WORD PTR ebx],0\t;Only check non-zero nodes\n\tjz\t??nextnode\n\n;*\tnodes[i].count < nodes[first].count\n\n\tmov\teax,[DWORD PTR esi + edx]\n\tcmp\teax,[DWORD PTR ebx]\n\tjbe\t??checklast\n\n\tmov\tedi,edx\t\t;last = first\n\tmov\tedx,ecx\t\t;first = i\n\tjmp\tshort ??nextnode\n\n;*\tnodes[i].count < nodes[last].count\n\n??checklast:\n\tmov\teax,[DWORD PTR esi + edi]\n\tcmp\teax,[DWORD PTR ebx]\n\tjbe\t??nextnode\n\n\tmov\tedi,ecx\t\t;last = i\n\n??nextnode:\n\tadd\tecx,8\t\t;i++\n\tadd\tebx,8\n\tcmp\tecx,[next]\n\tjne\tshort ??sortnodes\n\n;*\tTree done when last = 513\n\n\tcmp\tedi,(513 * 8)\n\tje\tshort ??done\n\n\tmov\tebx,[next]\n\tadd\tebx,esi\t\t;nodes[next]\n\tmov\t[WORD PTR ebx+4],dx\t;nodes[next].child0 = first\n\tmov\t[WORD PTR ebx+6],di\t;nodes[next].child1 = last\n\n\tadd\tedx,esi\n\tmov\teax,[DWORD PTR edx]\t;nodes[first].count\n\tadd\tedi,esi\n\tmov\t[DWORD PTR ebx],eax\n\n\tmov\tecx,[DWORD PTR edi]\t;nodes[last].count\n\txor\teax,eax \n\tadd\t[DWORD PTR ebx],ecx\n\n\tmov\t[DWORD PTR edx],eax\t;nodes[first].count = 0\n\tmov\t[DWORD PTR edi],eax\t;nodes[lats].count = 0\n\tadd\t[next],8\n\tjmp\t??sortnext\n\n??done:\n\tmov\teax,[next]\n\tsub\teax,8\n\tret\n\n\tENDP\tBuildHuffTree\n\n\tEND\n\n"
  },
  {
    "path": "VQ/VQM32/HUFFMAN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef HUFFMAN_H\n#define HUFFMAN_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     huffman.h\n*\n* DESCRIPTION\n*     Huffman order 0 compress/decompress definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*      \n* DATE\n*     May 19, 1995\n*\n****************************************************************************/\n\n\n/* TreeNode: Huffman decoding tree node.\n *\n * count  - Weight of the node in the tree.\n * child0 - Child node 0\n * child1 - Child node 1\n */\ntypedef struct _TreeNode {\n \tunsigned long  count;\n\tunsigned short child0;\n\tunsigned short child1;\n} TreeNode;\n\n\n/* HuffCode: This structure is used for storing the code for each symbol\n *            during encoding. A table of codes for each symbol is built\n *            from the Huffman tree.\n *\n * code - Code used to represent a symbol.\n * bits - Length of code in bits.\n */\ntypedef struct _HuffCode {\n\tunsigned short code;\n\tshort          bits;\n} HuffCode;\n\n\n#define HUFF_EOS 256 /* End of stream symbol */\n\n/* Prototypes */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nlong cdecl HuffCompress(unsigned char *data, unsigned char *buffer,\n\t\tlong length, char *work);\n\nlong cdecl HuffDecompress(unsigned char *data, unsigned char *buffer,\n\t\tlong length, char *work);\n\nvoid cdecl HuffCount(unsigned char *data, TreeNode *nodes, long length,\n\t\tlong zero);\n\nvoid cdecl HuffScaleCounts(TreeNode *nodes);\nlong cdecl RLEHuffCounts(TreeNode *nodes, unsigned char *buffer);\nlong cdecl BuildHuffTree(TreeNode *nodes);\n\nvoid cdecl ConvertToCodes(TreeNode *nodes, HuffCode *codes,\n\t\tunsigned short code, short bits, short node);\n\nlong cdecl HuffEncode(unsigned char *data, unsigned char *buffer,\n\t\tHuffCode *codes, long length);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* HUFFMAN_H */\n\n"
  },
  {
    "path": "VQ/VQM32/IFF.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     iff.c\n*\n* DESCRIPTION\n*     IFF manager. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*      \n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     OpenIFF          - Open an IFF for reading or writting.\n*     CloseIFF         - Close an IFF.\n*     ReadForm         - Read the IFF FORM, size and type of the file.\n*     WriteForm        - Write IFF form ID, size and type fields.\n*     ReadChunkHeader  - Read the IFF chunk identification header.\n*     WriteChunkHeader - Write an IFF chunk identification header.\n*     WriteChunk       - Write an IFF chunk with data from a buffer.\n*     WriteChunkBytes  - Write data from a buffer to the IFF stream.\n*     SkipChunkBytes   - Skip bytes in a chunk.\n*     FindChunk        - Scan for a specific chunk name.\n*     IDtoStr          - Convert a longword identifier to a NULL-terminated\n*                        string.\n*     CurrentFilePos   - Get the current file position.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <malloc.h>\n#include <io.h>\n#include <fcntl.h>\n#include <sys\\stat.h>\n#include <mem.h>\n#include \"iff.h\"\n\n\n/****************************************************************************\n*\n* NAME\n*     OpenIFF - Open an IFF for reading or writting.\n*\n* SYNOPSIS\n*     IFFHandle = OpenIFF(Name, Mode)\n*\n*     IFFHandle *OpenIFF(char *, long);\n*\n* FUNCTION\n*     Opens an IFF for a new read or write.  The direction of the I/O is\n*     given by the value of Mode, which can be either IFF_READ or IFF_WRITE.\n*\n* INPUTS\n*     Name - Pointer to name of file to open.\n*     Mode - IFF_READ or IFF_WRITE.\n*\n* RESULT\n*     IFFHandle - Pointer to IFFHandle structure or NULL if error.\n*\n****************************************************************************/\n\nIFFHandle *OpenIFF(char *name, long mode)\n{\n\tIFFHandle *iff;\n\n\t/* Allocate IFFHandle structure. */\n\tif ((iff = (IFFHandle *)malloc(sizeof(IFFHandle))) != NULL) {\n\n\t\t/* Initialize handle.*/\n\t\tmemset(iff, 0, sizeof(IFFHandle));\n\t\tiff->flags = mode;\n\n\t\tswitch (mode) {\n\t\t\tcase IFFF_READ:\n\t\t\t\tiff->fh = open(name, O_RDONLY|O_BINARY);\n\t\t\t\tbreak;\n\n\t\t\tcase IFFF_WRITE:\n\t\t\t\tiff->fh = open(name, (O_CREAT|O_TRUNC|O_WRONLY|O_BINARY),\n\t\t\t\t\t\t(S_IREAD|S_IWRITE));\n\n\t\t\t\tprintf(\"\\r\");\n\t\t\t\tbreak;\n\n\t\t\tcase (IFFF_READ|IFFF_WRITE):\n\t\t\t\tiff->fh = open(name, (O_RDWR|O_BINARY), (S_IREAD|S_IWRITE));\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tiff->fh = -1;\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/* If something went wrong we must free up any resources\n\t\t * that we have opened.\n\t\t */\n\t\tif (iff->fh == -1) {\n\t\t\tfree(iff);\n\t\t\tiff = NULL;\n\t\t}\n\t}\n\n\treturn (iff);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     CloseIFF - Close an IFF.\n*\n* SYNOPSIS\n*     CloseIFF(IFFHandle)\n*\n*     void CloseIFF(IFFHandle *);\n*\n* FUNCTION\n*     Completes an IFF read or write operation.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid CloseIFF(IFFHandle *iff)\n{\n\tlong length;\n\n\t/* Write the length of the FORM */\n\tif ((iff->flags & IFFF_WRITE) && ((iff->form.size == 0)\n\t\t\t|| (iff->scan > iff->form.size))) {\n\n\t\tlseek(iff->fh, 4, SEEK_SET);\n\t\tlength = REVERSE_LONG(iff->scan);\n\t\twrite(iff->fh, &length, 4);\n\t}\n\n\tclose(iff->fh);\n\tfree(iff);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     ReadForm - Read the IFF FORM, size and type of the file.\n*\n* SYNOPSIS\n*     Error = ReadForm(IFFHandle, FormHeader)\n*\n*     long ReadForm(IFFHandle *, FormHeader *);\n*\n* FUNCTION\n*     Read in the IFF form, size, type information. If the FormHeader\n*     structure pointer is NULL then the FORM will be read into the\n*     IFFHandles form structure.\n*\n* INPUTS\n*     IFFHandle  - Pointer to IFFHandle structure.\n*     FormHeader - Pointer to FormHeader structure.\n*\n* RESULT\n*     Error - 0 if successful or IFFERR_??? error code.\n*\n****************************************************************************/\n\nlong ReadForm(IFFHandle *iff, FormHeader *form)\n{\n\tFormHeader *ptr;\n \tlong       error;\n\n\t/* Read the FORM into the IFFHandle or the provided FormHeader. */\n\tif (form == NULL) {\n\t\tptr = &iff->form;\n\t} else {\n\t\tptr = form;\n\t}\n\n\t/* Read in IFF FORM from the file stream.. */\n\tif ((error = read(iff->fh, ptr, 12)) == 12) {\n\t\tptr->size = REVERSE_LONG(ptr->size);\n\t\tiff->scan = 4;\n\t\terror = 0;\n\t} else {\n\t\tif (error == -1)\n\t\t\terror = IFFERR_READ;\n\t\telse if (error == 0)\n\t\t\terror = IFFERR_EOF;\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     WriteForm - Write IFF form ID, size and type fields.\n*\n* SYNOPSIS\n*     Error = WriteForm(IFFHandle)\n*\n*     long WriteForm(IFFHandle, FormHeader *);\n*\n* FUNCTION\n*     Write out the IFF form, size, type information. If the size field\n*     is zero then the IFF form size will be calculated and written by\n*     the CloseIFF() function. If the FormHeader structure pointer is NULL\n*     the the form from the IFFHandle will be written.\n*\n* INPUTS\n*     IFFHandle  - Pointer to IFFHandle structure.\n*     FormHeader - Pointer to FormHeader structure.\n*\n* RESULT\n*     Error - 0 if successful or IFFERR_??? error code.\n*\n****************************************************************************/\n\nlong WriteForm(IFFHandle *iff, FormHeader *form)\n{\n\tFormHeader *ptr;\n\tlong       error = 0;\n\n\t/* Use the FORM from the IFFHandle or the provided FormHeader. */\n\tif (form == NULL) {\n\t\tptr = &iff->form;\n\t} else {\n\t\tptr = form;\n\t}\n\n\t/* Write the IFF form to the file stream. */\n\tif (iff->flags & IFFF_WRITE) {\n\t\tptr->size = REVERSE_LONG(ptr->size);\n\n\t\tif (write(iff->fh, ptr, 12) == 12) {\n\t\t\tiff->scan = 4;\n\t\t} else {\n\t\t\terror = IFFERR_WRITE;\n\t\t}\n\t} else {\n\t\terror = IFFERR_WRITE;\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     ReadChunkHeader - Read the IFF chunk identification header.\n*\n* SYNOPSIS\n*     Error = ReadChunkHeader(IFFHandle)\n*\n*     long ReadChunkHeader(IFFHandle *);\n*\n* FUNCTION\n*     Read the IFF identification header from the files data stream.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*\n* RESULT\n*     Error - 0 if successful or IFFERR_??? error code.\n*\n****************************************************************************/\n\nlong ReadChunkHeader(IFFHandle *iff)\n{\n\tlong error = 0;\n\n\t/* Skip any part of the previous chunk that hasn't been processed. */\n\tif ((iff->cn.size != 0) && (iff->cn.scan < PADSIZE(iff->cn.size))) {\n\t\terror = lseek(iff->fh, (PADSIZE(iff->cn.size) - iff->cn.scan), SEEK_CUR);\n\n\t\tif (error == -1) {\n\t\t\terror = IFFERR_READ;\n\t\t} else {\n\t\t\terror = 0;\n\t\t}\n\t}\n\n\t/* Read in the next chunk header context. */\n\tif (!error) {\n\t\tif ((error = read(iff->fh, &iff->cn, 8)) == 8) {\n\t\t\terror = 0;\n\t\t\tiff->scan += 8;\n\t\t\tiff->cn.size = REVERSE_LONG(iff->cn.size);\n\t\t\tiff->cn.scan = 0;\n\t\t} else {\n\t\t\tif (error == -1) {\n\t\t\t\terror = IFFERR_READ;\n\t\t\t}\telse if (error == 0) {\n\t\t\t\terror = IFFERR_EOF;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     WriteChunkHeader - Write an IFF chunk identification header.\n*\n* SYNOPSIS\n*     Error = WriteChunkHeader(IFFHandle, ID, Size)\n*\n*     long WriteChunkHeader(IFFHandle *, long, long);\n*\n* FUNCTION\n*     Write an IFF identification header to the files data stream.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*     ID        - ID code of chunk.\n*     Size      - Size of chunk in bytes (WORD aligned).\n*\n* RESULT\n*     Error - 0 if successful or IFFERR_??? error code.\n*\n****************************************************************************/\n\nlong WriteChunkHeader(IFFHandle *iff, long id, long size)\n{\n\tlong error = 0;\n\n\t/* Make sure it is okay to write. */\n\tif (iff->flags & IFFF_WRITE) {\n\t\tiff->cn.id = id;\n\t\tiff->cn.size = REVERSE_LONG(size);\n\t\tiff->cn.scan = 0;\n\n\t\tif (write(iff->fh, &iff->cn, 8) == 8) {\n\t\t\tiff->scan += 8;\n\t\t} else {\n\t\t\terror = IFFERR_WRITE;\n\t\t}\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     WriteChunk - Write an IFF chunk with data from a buffer.\n*\n* SYNOPSIS\n*     Actual = WriteChunk(IFFHandle, ID, Buffer, Size)\n*\n*     long WriteChunk(IFFHandle *, long, char *, long);\n*\n* FUNCTION\n*     Write a IFF chunk at the current file position.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*     ID        - ID code of chunk.\n*     Buffer    - Pointer to buffer area with bytes to be written.\n*     Size      - Number of bytes to write.\n*\n* RESULT\n*     Actual - (positive) Bytes written or (negative) IFFERR_??? error code.\n*\n****************************************************************************/\n\nlong WriteChunk(IFFHandle *iff, long id, char *buffer, long size)\n{\n\tContext cn;\n \tlong    actual;\n\n\t/* Make sure we can write to this file. */\n\tif (iff->flags & IFFF_WRITE) {\n\t\tcn.id = id;\n\t  cn.size = REVERSE_LONG(size);\n\n\t\t/* Write chunk header. */\n\t\tif (write(iff->fh, &cn, 8) == 8) {\n\t\t\tiff->scan += 8;\n\t\t\tiff->cn.scan += 8;\n\n\t\t\t/* Write chunk data. */\n\t\t\tactual = write(iff->fh, buffer, size);\n\n\t\t\tif (actual == size) {\n\t\t\t\tiff->scan += actual;\n\t\t\t\tiff->cn.scan += actual;\n\n\t\t\t\t/* Write chunk padding if necessary. */\n\t\t\t\tif (PADSIZE(size) > size) {\n\t\t\t\t\tid = 0;\n\n\t\t\t\t\tif (write(iff->fh, &id, 1) == 1) {\n\t\t\t\t\t\tiff->scan++;\n\t\t\t\t\t\tiff->cn.scan++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tactual = IFFERR_WRITE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tactual = IFFERR_WRITE;\n\t\t\t}\n\t\t} else {\n\t\t\tactual = IFFERR_WRITE;\n\t\t}\n\t} else {\n\t\tactual = IFFERR_WRITE;\n\t}\n\n\treturn (actual);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     WriteChunkBytes - Write data from a buffer to the IFF stream.\n*\n* SYNOPSIS\n*     Actual = WriteChunkBytes(IFFHandle, Buffer, Size)\n*\n*     long WriteChunk(IFFHandle *, char *, long);\n*\n* FUNCTION\n*     Write a IFF chunk at the current file position.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*     Buffer    - Pointer to buffer area with bytes to be written.\n*     Size      - Number of bytes to write.\n*\n* RESULT\n*     Actual - (positive) Bytes written or (negative) IFFERR_??? error code.\n*\n****************************************************************************/\n\nlong WriteChunkBytes(IFFHandle *iff, char *buffer, long size)\n{\n\tlong actual;\n\n\t/* Make sure we can write to this file. */\n\tif (iff->flags & IFFF_WRITE) {\n\n\t\t/* Write data. */\n\t\tif ((actual = (unsigned short)write(iff->fh, buffer, size)) == size) {\n\t\t\tiff->scan += actual;\n\t\t\tiff->cn.scan += actual;\n\t\t} else {\n\t\t\tactual = IFFERR_WRITE;\n\t\t}\n\t} else {\n\t\tactual = IFFERR_WRITE;\n\t}\n\n\treturn (actual);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     ReadChunkBytes - Read data from a chunk into a buffer.\n*\n* SYNOPSIS\n*     Actual = ReadChunkBytes(IFFHandle, Buffer, Length)\n*\n*     long ReadChunkBytes(IFFHandle *, char *, long);\n*\n* FUNCTION\n*     Read in 'Length' number of bytes from the current chunk context.\n*     If the specified length exceeds the number of bytes remaining in the\n*     chunk ReadChunkBytes() will read in only the number of remaining\n*     bytes. ReadChunkBytes() will never read beyond the scope of the\n*     current chunk.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*     Buffer    - Pointer to buffer to read data into.\n*     Length    - Number of bytes to read.\n*\n* RESULT\n*     Actual - (positive) Bytes written or (negative) IFFERR_??? error code.\n*\n****************************************************************************/\n\nlong ReadChunkBytes(IFFHandle *iff, char *buffer, long size)\n{\n\tlong actual;\n\n\t/* If the actual bytes remaining in the current chunk is less than\n\t * the requested bytes to read then adjust the read request size\n\t * to only read in the bytes that remain in the chunk.\n\t */\n\tactual = (iff->cn.size - iff->cn.scan);\n\n\tif (size > actual) {\n\t\tsize = actual;\n\t}\n\n\t/* Read in the requested number of bytes. */\n\tif ((actual = read(iff->fh, buffer, size)) != size) {\n\t\tactual = IFFERR_READ;\n\t} else {\n\t\tiff->scan += actual;\n\t\tiff->cn.scan += actual;\n\t}\n\n\treturn (actual);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     SkipChunkBytes - Skip bytes in a chunk.\n*\n* SYNOPSIS\n*     Error = SkipChunkBytes(IFFHandle, Skip)\n*\n*     long SkipChunkBytes(IFFHandle *, long);\n*\n* FUNCTION\n*     Skip the specified number of bytes of the chunk.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*     Skip      - Number of bytes to skip.\n*\n* RESULT\n*     Error - 0 if successful or FAIL_??? error code.\n*\n****************************************************************************/\n\nlong SkipChunkBytes(IFFHandle *iff, long skip)\n{\n\tlong error = 0;\n\n\tif (lseek(iff->fh, skip, SEEK_CUR) == -1) {\n\t\terror = IFFERR_READ;\n\t} else {\n\t\tiff->scan += skip;\n\t\tiff->cn.scan += skip;\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     FindChunk - Scan for a specific chunk name.\n*\n* SYNOPSIS\n*     Error = FindChunk(IFFHandle, ID)\n*\n*     long FindChunk(IFFHandle *, long);\n*\n* FUNCTION\n*     Scan from the current file position for the next occurance of the\n*     specified chunk ID. When a match is found the function will return\n*     with the matching chunk as the current context.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*     ID        - ID code of chunk.\n*\n* RESULT\n*     Error - 0 if successful or FAIL_??? error code.\n*\n****************************************************************************/\n\nlong FindChunk(IFFHandle *iff, long id)\n{\n\tlong found = 0;\n\tlong error = 0;\n\n\t/* Invalid handle check. */\n\tif (iff != NULL) {\n\n\t\t/* Scan until we have a match or an error. */\n\t\twhile ((found == 0) && !(error = ReadChunkHeader(iff))) {\n\n\t\t\t/* If we found a match the terminate scan, otherwise skip this\n\t\t\t * chunk and process the next.\n\t\t\t */\n\t\t\tif (iff->cn.id == id) {\n\t\t\t\tfound = 1;\n\t\t\t} else {\n\t\t\t\terror = SkipChunkBytes(iff, PADSIZE(iff->cn.size));\n\t\t\t}\n\t\t}\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     IDtoStr - Convert a longword identifier to a NULL-terminated string.\n*\n* SYNOPSIS\n*     String = IDtoStr(ID, Buffer)\n*\n*     char *IDtoStr(long, char *);\n*\n* FUNCTION\n*     Writes the ASCII equivalent of the given longword ID into buffer as a\n*     NULL-terminated string.\n*\n* INPUTS\n*     ID     - Longword ID.\n*     Buffer - Character buffer to accept string (at least 5 characters).\n*\n* RESULT\n*     String - The value of \"Buffer\".\n*\n****************************************************************************/\n\nchar *IDtoStr(long id, char *buf)\n{\n\tmemcpy(buf, &id, 4);\n\t*(buf + 4) = 0;\n\n\treturn (buf);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     CurrentFilePos - Get the current file position.\n*\n* SYNOPSIS\n*     Position = CurrentFilePos(IFFHandle)\n*\n*     long CurrentFilePos(IFFHandle *);\n*\n* FUNCTION\n*     This function returns the offset in bytes of the current file position\n*     from the beginning of the IFF.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*\n* RESULT\n*     Position - Offset in bytes from the beginning of the file to the\n*                current position.\n*\n****************************************************************************/\n\nlong CurrentFilePos(IFFHandle *iff)\n{\n\tlong offset;\n\n\tif ((offset = lseek(iff->fh, 0, SEEK_CUR)) == -1) {\n\t\toffset = IFFERR_READ;\n\t}\n\n\treturn (offset);\n}\n\n"
  },
  {
    "path": "VQ/VQM32/IFF.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMIFF_H\n#define VQMIFF_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     iff.h\n* \n* DESCRIPTION\n*     IFF (Interchange File Format) manager definitions.\n*     (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/* FormHeader - Structure associated with IFF forms.\n *\n * id   - IFF form id (IE: \"FORM\")\n * size - Length of IFF in bytes\n * type - Form type (IE: \"ILBM\")\n */\ntypedef struct _FormHeader {\n\tlong id;\n\tlong size;\n\tlong type;\n} FormHeader;\n\n/* Context - Structure associated with chunks.\n *\n * id   - Chunk identifier.\n * size - Size of chunk in bytes.\n * scan - Bytes read/written.\n */\ntypedef struct _Context {\n\tlong id;\n\tlong size;\n\tlong scan;\n} Context;\n\n/* IFFHandle - Structure associated with an active IFF read\\write session.\n *\n * fh    - DOS filehandle\n * flags - Internal flags used by IFF routines.\n * form  - IFF form information.\n * scan  - Bytes read/written\n * cn    - Context of current chunk.\n */\ntypedef struct _IFFHandle {\n\tlong       fh;\n\tlong       flags;\n\tFormHeader form;\n\tlong       scan;\n\tContext    cn;\n} IFFHandle;\n\n/*\tbit masks for \"flags\" field. */\n#define IFFB_READ  0\n#define IFFB_WRITE 1\n#define IFFF_READ  (1<<IFFB_READ)\n#define IFFF_WRITE (1<<IFFB_WRITE)\n\n/* IFF return codes. Most functions return either zero for success or\n * one of these codes. The exceptions are the read/write functions which,\n * return positive values for number of bytes read or written, or a negative\n * error code.\n *\n * IFFERR_EOF   - End of file.\n * IFFERR_READ  - Read error.\n * IFFERR_WRITE - Write error.\n * IFFERR_NOMEM - Unable to allocate memory.\n */\n#define IFFERR_EOF   -1\n#define IFFERR_READ  -2\n#define IFFERR_WRITE -3\n#define IFFERR_NOMEM -4\n\n/* Macros to make things easier. */\n#define REVERSE_LONG(id) (unsigned long)((((unsigned long)(id)>>24) \\\n\t\t&0x000000FFL)|(((unsigned long)(id)>>8) \\\n\t\t&0x0000FF00L)|(((unsigned long)(id)<<8) \\\n\t\t&0x00FF0000L)|(((unsigned long)(id)<<24)&0xFF000000L))\n\n#define REVERSE_WORD(id) ((unsigned short)((((unsigned short)(id)<<8) \\\n\t\t&0x00FF00)|(((unsigned short)(id)>>8)&0x0FF)))\n\n#define PADSIZE(size) (((size)+1)&(~1))\n\n#ifndef MAKE_ID\n#define MAKE_ID(a,b,c,d) ((long)((long)(d)<<24)|((long)(c)<<16)| \\\n\t\t((long)(b)<<8)|(long)(a))\n#endif\n\n/* Universal IFF identifiers */\n#define ID_FORM MAKE_ID('F','O','R','M')\n#define ID_LIST MAKE_ID('L','I','S','T')\n#define ID_PROP MAKE_ID('P','R','O','P')\n#define ID_NULL MAKE_ID(' ',' ',' ',' ')\n\n/* Prototypes */\nIFFHandle *OpenIFF(char *, long);\nvoid CloseIFF(IFFHandle *);\nlong ReadForm(IFFHandle *, FormHeader *);\nlong WriteForm(IFFHandle *, FormHeader *);\nlong ReadChunkHeader(IFFHandle *);\nlong WriteChunkHeader(IFFHandle *, long, long);\nlong WriteChunk(IFFHandle *, long, char *, long);\nlong WriteChunkBytes(IFFHandle *, char *, long);\nlong ReadChunkBytes(IFFHandle *, char *, long);\nlong SkipChunkBytes(IFFHandle *, long);\nlong FindChunk(IFFHandle *, long);\nchar *IDtoStr(long, char *);\nlong CurrentFilePos(IFFHandle *);\n\n#endif /* VQMIFF_H */\n\n"
  },
  {
    "path": "VQ/VQM32/LCWCOMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     lcwcomp.asm\n;*\n;* DESCRIPTION\n;*     LCW compression code. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Louis Castle\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     LCW_Compress - LCW compress a buffer of memory.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     LCW_Compress - LCW compress a buffer of memory.\n;*\n;* SYNOPSIS\n;*     Size = LCW_Compress(Source, Dest, Length)\n;*\n;*     long LCW_Compress(void *, void *, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Source - Pointer to data to compress.\n;*     Dest   - Pointer to buffer to put compressed data.\n;*     Length - Length in bytes of data to compress.\n;*\n;* RESULT\n;*     Size - Size in bytes of compresed data.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC LCW_Compress:NEAR\n\tPROC\tLCW_Compress C NEAR USES ebx ecx edx esi edi\n\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tdatasize:DWORD\n\n\tLOCAL\tinlen:DWORD\n\tLOCAL\ta1stdest:DWORD\n\tLOCAL\ta1stsrc:DWORD\n\tLOCAL\tlenoff:DWORD\n\tLOCAL\tndest:DWORD\n\tLOCAL\tcount:DWORD\n\tLOCAL\tmatchoff:DWORD\n\tLOCAL\tend_of_data:DWORD\n\n\tmov\tesi,[source]\n\tmov\tedi,[dest]\n\tmov\tedx,[datasize]\n\n\tcld\t\t\t;Forward direction\n\tmov\tebx,esi\n\tadd\tebx,edx\n\tmov\t[end_of_data],ebx\t;Save end of source address\n\tmov\t[inlen],1\t\t;Set the in-length flag\n\tmov\t[a1stdest],edi\t \t;Save original dest\n\tmov\t[a1stsrc],esi\t \t;Save original source\n\tmov\t[lenoff],edi\t \t;Save offset length\n\n\tmov\tal,081h\t\t;First byte is always a len\n\tstosb\t\t\t;Write out a len of 1\n\tlodsb\t\t\t;Get the byte\n\tstosb\t\t\t;Save it\n\n??loop:\n\tmov\t[ndest],edi\t\t;Save offset of compressed data\n\tmov\tedi,[a1stsrc]\t\t;Get address of first byte\n\tmov\t[count],1\t\t;Set the count of run to 0\n\n??searchloop:\n \tsub\teax,eax\n\tmov\tal,[esi]\t\t;Get the current byte of data\n\tcmp\tal,[esi + 64]\n\tjne\tshort ??notrunlength\n\n\tmov\tebx,edi\n\tmov\tedi,esi\n\tmov\tecx,[end_of_data]\n\tsub\tecx,edi\n   \trepe\tscasb\n\tdec\tedi\n\tmov\tecx,edi\n\tsub\tecx,esi\n\tcmp\tecx,65\n\tjb\tshort ??notlongenough\n\n\tmov\t[inlen],0\t\t;Clear the in-length flag\n\tmov\tesi,edi\n\tmov\tedi,[ndest]\n\tmov\tah,al\n\tmov\tal,0FEh\n\tstosb\n\txchg\tecx,eax\n\tstosw\n\tmov\tal,ch\n\tstosb\n\n\tmov\t[ndest],edi\t\t;Save offset of compressed data\n\tmov\tedi,ebx\n\tjmp\t??searchloop\n\n??notlongenough:\n\tmov\tedi,ebx\n\n??notrunlength:\n??oploop:\n\tmov\tecx,esi\t\t;Address of the last byte +1\n\tsub\tecx,edi\t\t;Total number of bytes left\n\tjz\tshort ??searchdone\n\n\trepne\tscasb\t\t;Look for a match\n\tjne\tshort ??searchdone\t;If we don't find one we're done\n\n\tmov\tebx,[count]\n\tmov\tah,[esi+ebx-1]\n\tcmp\tah,[edi+ebx-2]\n\tjne\t??oploop\n\n\tmov\tedx,esi\t\t;Save address for the next search\n\tmov\tebx,edi\t\t;Save address for the length calc\n\tdec\tedi\t\t;Back up one for compare\n\tmov\tecx,[end_of_data]\t;Get the end of data\n\tsub\tecx,esi\t\t;Sub current source for max len\n\trepe\tcmpsb  \t\t;See how many bytes match\n\tjne\tshort ??notend\n\n\tinc\tedi\n\n??notend:\n\tmov\tesi,edx\n\tmov\teax,edi\t\t;Get the dest\n\tsub\teax,ebx\t\t;Sub the start for total bytes that match\n\tmov\tedi,ebx\t\t;Restore dest\n\tcmp\teax,[count]\t\t;See if its better than before\n\tjb\t??searchloop\t\t;If not keep looking\n\n\tmov\t[count],eax\t\t;If so keep the count\n\tdec\tebx\t\t;Back it up for the actual match offset\n\tmov\t[matchoff],ebx \t;Save the offset for later\n\tjmp\t??searchloop\t\t;Loop until we searched it all\n\n??searchdone:\n\tmov\tecx,[count]\t\t;Get the count of the longest run\n\tmov\tedi,[ndest]\t\t;Get the paragraph of our compressed data\n\tcmp\tecx,2\t\t;See if its not enough run to matter\n\tjbe\tshort ??lenin\t\t;If its 0,1, or 2 its too small\n\n\tcmp\tecx,10\t\t;If not, see if it would fit in a short\n\tja\tshort ??medrun\t\t;If not, see if its a medium run\n\n\tmov\teax,esi\t\t;If its short get the current address\n\tsub\teax,[matchoff] \t;Sub the offset of the match\n\tcmp\teax,0FFFh\t\t;If its less than 12 bits its a short\n\tja\tshort ??medrun\t\t;If its not, its a medium\n\n??shortrun:\n\tmov\tbl,cl\t\t;Get the length (3-10)\n\tsub\tbl,3\t\t;Sub 3 for a 3 bit number 0-7\n\tshl\tbl,4\n\tadd\tah,bl\n\txchg\tah,al\n\tjmp\tshort ??srunnxt\t;Do the run fixup code\n\n??medrun:\n\tcmp\tecx,64\t\t;See if its a short run\n\tja\tshort ??longrun\t;If not, oh well at least its long\n\n\tsub\tcl,3\t\t;Back down 3 to keep it in 6 bits\n\tor\tcl,0C0h\t\t;The highest bits are always on\n\tmov\tal,cl\t\t;Put it in al for the stosb\n\tstosb\t\t\t;Store it\n\tjmp\tshort ??medrunnxt \t;Do the run fixup code\n\n??lenin:\n\tcmp\t[inlen],0\t\t;Is it doing a length?\n\tjnz\tshort ??len\t\t;If so, skip code\n\n??lenin1:\n\tmov\t[lenoff],edi\t\t;Save the length code offset\n\tmov\tal,80h\t\t;Set the length to 0\n\tstosb\t\t\t;Save it\n\n??len:\n\tmov\tebx,[lenoff]\t\t;Get the offset of the length code\n\tcmp\t[BYTE PTR ebx],0BFh\t;See if its maxed out\n\tje\t??lenin1\t\t;If so put out a new len code\n\n??stolen:\n\tinc\t[BYTE PTR ebx] \t;Inc the count code\n\tlodsb\t\t\t;Get the byte\n\tstosb\t\t\t;Store it\n\tmov\t[inlen],1\t\t;We are now in a length so save it\n\tjmp\tshort ??nxt\t\t;Do the next code\n\n??longrun:\n\tmov\tal,0FFh\t\t;Its a long so set a code of FF\n\tstosb\t\t\t;Store it\n\tmov\teax,[count]\t\t;Send out the count\n\tstosw\t\t\t;Store it\n\n??medrunnxt:\n\tmov\teax,[matchoff] \t;Get the offset\n\tsub\teax,[a1stsrc]\t\t;Make it relative tot he start of data\n\n??srunnxt:\n\tstosw\t\t\t;Store it\n\tadd\tesi,[count]\t\t;Add in the length of the run to the source\n\tmov\t[inlen],0\t\t;Set the in leght flag to false\n\n??nxt:\n\tcmp\tesi,[end_of_data]\t;See if we did the whole pic\n\tjae\tshort ??out\t\t;If so, cool! were done\n\tjmp\t??loop\n\n??out:\n\tmov\teax,080h\t\t;Remember to send an end of data code\n\tstosb\t\t\t;Store it\n\tmov\teax,edi\t\t;Get the last compressed address\n\tsub\teax,[a1stdest]\t\t;Sub the first for the compressed size\n\tret\n\n\tENDP\tLCW_Compress\n\n\tEND\n"
  },
  {
    "path": "VQ/VQM32/LCWUNCMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     lcwuncmp.asm\n;*\n;* DESCRIPTION\n;*     LCW uncompress routine. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Chris Yates\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     LCW_Uncompress - Uncompress LCW encoded data.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     LCW_Uncompress - Uncompress LCW encoded data.\n;*\n;* SYNOPSIS\n;*     Size = LCW_Uncompress(Source, Dest, Length)\n;*\n;*     LONG LCW_Uncompress(void *, void *, long);\n;*\n;* FUNCTION\n;*     Uncompress data to the following codes in the format b = byte,\n;*     w = word, n = byte code pulled from compressed data.\n;*\n;*     Bit field of n            Command     Description\n;*     ------------------------------------------------------------------\n;*     n=0xxxyyyy,yyyyyyyy       short run   back y bytes and run x+3\n;*     n=10xxxxxx,n1,n2,..,nx+1  med length  copy the next x+1 bytes\n;*     n=11xxxxxx,w1             med run     run x+3 bytes from offset w1\n;*     n=11111111,w1,w2          long copy   copy w1 bytes from offset w2\n;*     n=11111110,w1,b1          long run    run byte b1 for w1 bytes\n;*     n=10000000                end         end of data reached\n;*\n;* INPUTS\n;*     Source - Pointer to LCW encoded data.\n;*     Dest   - Pointer to buffer to uncompress into.\n;*     Length -\n;*\n;* RESULT\n;*     Size - Size of uncompressed data in bytes.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC LCW_Uncompress:NEAR\n\tPROC\tLCW_Uncompress C NEAR USES ebx ecx edx esi edi\n\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tlength:DWORD\n\n\tLOCAL\ta1stdest:DWORD\n\tLOCAL\tmaxlen:DWORD\n\tLOCAL\tlastbyte:DWORD\n\tLOCAL\tlastcom:DWORD\n\tLOCAL\tlastcom1:DWORD\n\n\tmov\tesi,[source]\t\t;ESI - Source address\n\tmov\tedi,[dest]\t\t;EDI - Destination address\n\tmov\tedx,[length]\t\t;EDX - Maximum length\n\n\tmov\t[a1stdest],edi\t\t;Save dest address\n\tadd\tedx,edi\t\t;Last address (Dest + length)\n\tmov\t[lastbyte],edx\n\n\tcld\t\t\t;Forward direction\n\tmov\tebx,esi\t\t;Save source address\n\n??loop:\n;\tExit if no bytes are remaining.\n\n\tmov\teax,[lastbyte]\n\tsub\teax,edi\n\tjz\tshort ??out\n\n\tmov\t[maxlen],eax\t\t;Save for string commands\n\tmov\tesi,ebx\t\t;Restore source address\n\tlodsb\n\tor\tal,al\t\t;See if its a short run\n\tjs\tshort ??notshort\n\n\tmov\tah,al\t\t;Put rel offset high nibble in ah\n\tand\tah,0Fh\t\t; Only 4 bits count\n \tsub\tecx,ecx\n\tmov\tch,al\t\t;Put count nibble in ch\n\tshr\tch,4\n\tmov\tcl,ch\n\txor\tch,ch\n\tadd\tecx,3\t\t;Get actual run length\n\tcmp\tecx,[maxlen]\t\t;Is it too big to fit?\n\tjbe\tshort ??rsok\t\t;If not, its ok\n\n\tmov\tecx,[maxlen]\t\t;If so, max it out so it dosen't overrun\n\n??rsok:\n\tlodsb\t\t\t;Get rel offset low byte\n\tmov\tebx,esi\t\t;Save the source address\n\tmov\tesi,edi\t\t;Get the current dest\n\tsub\tesi,eax\t\t;Get relative offset\n\trep\tmovsb\n\tjmp\t??loop\n\n??notshort:\n\ttest\tal,40h\t\t;Is it a length?\n\tjne\tshort ??notlength\t;If not it could be med or long run\n\n;\tIf end code then exit.\n\n\tcmp\tal,80h\n\tje\tshort ??out\n\n\tmov\tcl,al\t\t;Put the byte in count register\n\tand\tecx,3Fh\t\t;Mask off the extra bits\n\tcmp\tecx,[maxlen]\t\t;Is it too big to fit?\n\tjbe\tshort ??lenok\t\t;If not, its ok\n\n\tmov\tecx,[maxlen]\t\t;If so, max it out so it dosen't overrun\n\n??lenok:\n\trep\tmovsb\n\tmov\tebx,esi\t\t;Save the source offset\n\tjmp\t??loop\n\n??out:\n      \tmov\teax,edi\n\tsub\teax,[a1stdest]\n\tjmp\tshort ??exit\n\n??notlength:\n\tmov\tcl,al\t\t;Get the entire code\n\tand\tecx,3Fh\t\t;Mask off all but the size -3\n\tadd\tecx,3\t\t;Add 3 for byte count\n\tcmp\tal,0FEh\n\tjne\tshort ??notrunlength\n\n\tsub\teax,eax\n\tlodsw\n\tmov\tecx,eax\n\tsub\teax,eax\n\tlodsb\n\tmov\tebx,esi\t\t;Save the source offset\n\tcmp\tecx,[maxlen]\t\t;Is it too big to fit?\n\tjbe\tshort ??runlenok\t;If not, its ok\n\n\tmov\tecx,[maxlen]\t\t;If so, max it out so it dosen't overrun\n\n??runlenok:\n\trep\tstosb\n\tjmp\t??loop\n\n??notrunlength:\n\tcmp\tal,0FFh\t\t;Is it a long run?\n\tjne\tshort ??notlong\t;If not use the code as the size\n\n\tsub\teax,eax\n\tlodsw\t\t\t;If so, get the size\n\tmov\tecx,eax\t\t;Put int the count byte\n\n??notlong:\n\tlodsw\t\t\t;Get the rel index\n\tmov\tebx,esi\t\t;Save the source offset\n\tadd\teax,[a1stdest]\t\t;Add in the first index\n\tmov\tesi,eax\t\t;Use this as a source\n\tcmp\tecx,[maxlen]\t\t;Is it too big to fit?\n\tjbe\tshort ??runok\t\t;If not, its ok\n\n\tmov\tecx,[maxlen]\t\t;If so, max it out so it dosen't overrun\n\n??runok:\n\trep\tmovsb\n\tjmp\t??loop\n\n??exit:\n\tmov\teax,edi\n\tmov\tebx,[dest]\n\tsub\teax,ebx\t\t;Calculate bytes uncompressed.\n\tret\n\n\tENDP\tLCW_Uncompress\n\n\tEND\n        \n"
  },
  {
    "path": "VQ/VQM32/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQMisc 32-bit library. (Watcom/4GW)\n#\n# FILE\n#     makefile\n#\n# DESCRIPTION\n#     Makefile for generating VQMisc32 library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n# \n# DATE\n#     Feburary 10, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     WATCOM - Watcom C installation path.\n#\n#****************************************************************************\n\n.OPTIMIZE\n.ERASE\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n!ifndef %PRJ || %PRJVCS || %WATCOM\n!error Environment not configured.\n!endif\n\n#----------------------------------------------------------------------------\n# PROJECTS DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJNAME = vqm32wp\nPRJDIR  = $(%PRJ)\\VQM32\n\nOBJECTS = &\n\tiff.obj &\n\tprofile.obj &\n\taudzap.obj &\n\taudunzap.obj &\n\ttarga.obj &\n\tvertag.obj &\n\tsortpal.obj &\n\tpalette.obj &\n\tmono.obj &\n\tlcwuncmp.obj &\n\tlcwcomp.obj &\n\ttestvb.obj &\n\tvb.obj &\n\tmcgabuf.obj &\n\tvideo.obj &\n\txmode.obj &\n\txmodepg.obj &\n\tvesabuf.obj &\n\tvesablit.obj &\n\tvesavid.obj &\n\tsoscodec.obj &\n\tdrawchar.obj &\n\ttextprnt.obj &\n\tfont.obj &\n\tchrwidth.obj &\n\tmixfile.obj &\n\tcrc.obj &\n\tfillrect.obj &\n\tcaptoken.obj &\n\thuffcmp.obj &\n\thuffdcmp.obj &\n\tmem.obj &\n\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!ifdef %LIB\nLIBPATH = $(%PRJ)\\LIB;$(%LIB)\n!else\nLIBPATH = $(%PRJ)\\LIB;$(%WATCOM)\\LIB386\n!endif\n\n!ifdef %INCLUDE\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%INCLUDE)\n!else\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%WATCOM)\\H\n!endif\n\npath_c   = .\\\npath_cpp = .\\\npath_h   = .\\\npath_asm = .\\\npath_i   = .\\\npath_obj = .\\O\npath_lib = $(%PRJ)\\LIB\npath_exe = .\\\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULE EXTENSIONS AND PATHS\n#----------------------------------------------------------------------------\n\n.EXTENSIONS :\n.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i\n\n.c : $(path_c)\n.cpp : $(path_cpp)\n.h : $(path_h)\n.asm : $(path_asm)\n.i : $(path_i)\n.obj : $(path_obj)\n.lib : $(path_lib)\n.exe : $(path_exe)\n\n#----------------------------------------------------------------------------\n# TOOLS, COMMANDS AND CONFIGURATIONS\n#----------------------------------------------------------------------------\n\nCC_CMD   = wcc386\nCCP_CMD  = wpp386\nASM_CMD  = tasm32\nLINK_CMD = wlink\nLIB_CMD  = wlib\n\nCC_OPTS  = -i$(INCLUDEPATH) -j -zp1 -5s -mf -oaeilrt -s -zq\nASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /dPHARLAP_TNT=0\nLIB_OPTS = /b /c /q\nLINK_CFG = $(PRJNAME).lnk\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall : $(PRJNAME).lib .SYMBOLIC\n\n$(PRJNAME).lib : $(OBJECTS) .SYMBOLIC\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj :\n  $(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.cpp.obj :\n  $(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\\$^.\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\nupdate: .SYMBOLIC\n\t@echo Updating VQMisc32 header files!\n\t@copy *.h $(%PRJ)\\INCLUDE\\VQM32 >NUL\n\t@copy *.i $(%PRJ)\\INCLUDE\\VQM32 >NUL\n\n"
  },
  {
    "path": "VQ/VQM32/MAKEFILE.BAK",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQMisc 32-bit library. (Watcom/4GW)\n#\n# FILE\n#     makefile\n#\n# DESCRIPTION\n#     Makefile for generating VQMisc32 library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n# \n# DATE\n#     Feburary 10, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     WATCOM - Watcom C installation path.\n#\n#****************************************************************************\n\n.OPTIMIZE\n.ERASE\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\nPRJ=.\n\n!ifndef PRJ || %WATCOM\n!error Environment not configured.\n!endif\n\n#----------------------------------------------------------------------------\n# PROJECTS DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJNAME = VQM32W\nPRJDIR  = $(PRJ)\\VQM32\n\nOBJECTS = &\n\tiff.obj &\n\tprofile.obj &\n\taudzap.obj &\n\taudunzap.obj &\n\ttarga.obj &\n\tvertag.obj &\n\tsortpal.obj &\n\tpalette.obj &\n\tlcwuncmp.obj &\n\tlcwcomp.obj &\n\ttestvb.obj &\n\tvb.obj &\n\tmcgabuf.obj &\n\tvideo.obj &\n\txmode.obj &\n\txmodepg.obj &\n\tvesabuf.obj &\n\tvesablit.obj &\n\tvesavid.obj &\n\tsoscodec.obj\n\n#\tmono.obj &\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!ifdef %LIB\nLIBPATH = $(PRJ)\\LIB;$(%LIB)\n!else\nLIBPATH = $(PRJ)\\LIB;$(%WATCOM)\\LIB386\n!endif\n\n!ifdef %INCLUDE\nINCLUDEPATH = $(PRJ)\\INCLUDE;$(%INCLUDE)\n!else\nINCLUDEPATH = $(PRJ)\\INCLUDE;$(%WATCOM)\\H\n!endif\n\npath_c   = .\\\npath_cpp = .\\\npath_h   = .\\\npath_asm = .\\\npath_i   = .\\\npath_obj = .\\O\npath_lib = $(PRJ)\\LIB\npath_exe = .\\\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULE EXTENSIONS AND PATHS\n#----------------------------------------------------------------------------\n\n.EXTENSIONS :\n.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i\n\n.c : $(path_c)\n.cpp : $(path_cpp)\n.h : $(path_h)\n.asm : $(path_asm)\n.i : $(path_i)\n.obj : $(path_obj)\n.lib : $(path_lib)\n.exe : $(path_exe)\n\n#----------------------------------------------------------------------------\n# TOOLS, COMMANDS AND CONFIGURATIONS\n#----------------------------------------------------------------------------\n\nCC_CMD   = wcc386\nCCP_CMD  = wpp386\nASM_CMD  = tasm32\nLINK_CMD = wlink\nLIB_CMD  = wlib\n\nCC_OPTS  = -i$(INCLUDEPATH) -j -zp1 -5s -mf -oaeilrt -s -zq\nASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /dPHARLAP_TNT=0\nLIB_OPTS = /b /c /q\nLINK_CFG = $(PRJNAME).lnk\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall : $(PRJNAME).lib .SYMBOLIC\n\n$(PRJNAME).lib : $(OBJECTS) .SYMBOLIC\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj :\n  $(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.cpp.obj :\n  $(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\\$^.\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\nupdate: .SYMBOLIC\n\t@echo Updating VQMisc32 header files!\n\t@copy *.h $(PRJ)\\INCLUDE\\VQM32 >NUL\n\t@copy *.i $(PRJ)\\INCLUDE\\VQM32 >NUL\n\n"
  },
  {
    "path": "VQ/VQM32/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#       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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQMisc32 library. (Borland/TNT)\n#\n# FILE\n#     makefile\n#\n# DESCRIPTION\n#     Makefile for generating VQMisc32 library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n# \n# DATE\n#     Febuary 7, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     BCDIR  - Borland C installation path.\n#     TNTDIR - Pharlap/TNT installation path.\n#\n#****************************************************************************\n\n.AUTODEPEND\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n!if !$d(PRJ) || !$d(PRJVCS) || !$d(BCDIR) || !$d(TNTDIR)\n!error Environment not configured.\n!endif\n\n#----------------------------------------------------------------------------\n# PROJECT DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJNAME = VQM32BP\nPRJDIR  = $(PRJ)\\VQM32\n\nOBJECTS = \\\n\tiff.obj \\\n\tprofile.obj \\\n\taudzap.obj \\\n\taudunzap.obj \\\n\ttarga.obj \\\n\tvertag.obj \\\n\tsortpal.obj \\\n \tpalette.obj \\\n\tmono.obj \\\n\tlcwuncmp.obj \\\n\tlcwcomp.obj \\\n\ttestvb.obj \\\n\tvb.obj \\\n\tmcgabuf.obj \\\n\tvideo.obj \\\n\txmode.obj \\\n\txmodepg.obj \\\n\tvesabuf.obj \\\n\tvesablit.obj \\\n\tvesavid.obj \\\n\tsoscodec.obj \\\n\tdrawchar.obj \\\n\ttextprnt.obj \\\n\tfont.obj \\\n\tchrwidth.obj \\\n\tmixfile.obj \\\n\tcrc.obj \\\n\tfillrect.obj \\\n\tcaptoken.obj \\\n\thuffcmp.obj \\\n\thuffdcmp.obj \\\n\tmem.obj \\\n\tportio.obj \\\n\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!if $d(LIB)\nLIBPATH = $(PRJ)\\LIB;$(LIB)\n!else\nLIBPATH = $(PRJ)\\LIB;$(TNTDIR)\\LIB;$(BCDIR)\\LIB\n!endif\n\n!if $d(INCLUDE)\nINCLUDEPATH = $(PRJ)\\INCLUDE;$(INCLUDE)\n!else\nINCLUDEPATH = $(PRJ)\\INCLUDE;$(TNTDIR)\\INCLUDE;$(BCDIR)\\INCLUDE\n!endif\n\n.path.asm = $(PRJDIR)\n.path.c   = $(PRJDIR)\n.path.cpp = $(PRJDIR)\n.path.h   = $(PRJDIR)\n.path.exe = $(PRJDIR)\n.path.obj = $(PRJDIR)\\OBJ\n.path.sym = $(PRJDIR)\\OBJ\n.path.lib = $(PRJ)\\LIB\n\n#----------------------------------------------------------------------------\n# TOOLS, COMMANDS AND CONFIGURATIONS\n#----------------------------------------------------------------------------\n\nCC_CMD   = bcc32\nASM_CMD  = tasm32\nLINK_CMD = tlink32\nLIB_CMD  = tlib\n\nCC_CFG    = bcc32.cfg\nASM_CFG   = tasm32.cfg\nLINK_CFG  = tlink32.cfg\nLIB_CFG   = tlib.cfg\nCFG_FILES = $(CC_CFG) $(ASM_CFG) $(LINK_CFG) $(LIB_CFG)\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall: $(PRJNAME).lib\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj:\n  $(CC_CMD) -P- -n$(.path.obj) {$< }\n\n.cpp.obj:\n  $(CC_CMD) -P -n$(.path.obj) {$< }\n\n.asm.obj:\n  $(ASM_CMD) @$(ASM_CFG) $<,$(.path.obj)\\$&\n\n#----------------------------------------------------------------------------\n# BUILD THE LIBRARY\n#----------------------------------------------------------------------------\n\n$(PRJNAME).lib: $(OBJECTS)\n\t- @del $(.path.lib)\\$(PRJNAME).lib >&NUL\n\t$(LIB_CMD) $(.path.lib)\\$(PRJNAME).lib @$(LIB_CFG) @&&|\n-+$(**: = -+)\n|\n\t- @copy *.h $(PRJ)\\INCLUDE\\VQM32 >&NUL\n\t- @copy *.i $(PRJ)\\INCLUDE\\VQM32 >&NUL\n\n#----------------------------------------------------------------------------\n# ALL OBJECTS DEPEND ON THE CONFIGURATION FILES\n#----------------------------------------------------------------------------\n\n$(OBJECTS): $(CFG_FILES)\n\n#----------------------------------------------------------------------------\n# COMPILER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(CC_CFG): makefile\n\tcopy &&|\n-c\n-3\n-d\n-H=$(.path.sym)\\headers.sym\n-wpro\n-weas\n-wpre\n-I$(INCLUDEPATH)\n-DPHARLAP_TNT=1\n#-v\n| $(CC_CFG)\n \n#----------------------------------------------------------------------------\n# ASSEMBLER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(ASM_CFG): makefile\n\tcopy &&|\n/t\n/m\n/w+\n/jJUMPS\n/ml\n/p\n/z\n/i$(PRJ)\\INCLUDE\n/zi\n/dPHARLAP_TNT=1\n| $(ASM_CFG)\n\n#----------------------------------------------------------------------------\n# LINKER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(LINK_CFG): makefile\n\tcopy &&|\n/c\n/m\n/Gm\n-L$(LIBPATH)\n-v\n| $(LINK_CFG)\n\n#----------------------------------------------------------------------------\n# LIBRARIAN CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(LIB_CFG):\tmakefile\n\tcopy &&|\n/C /E\n| $(LIB_CFG)\n\n"
  },
  {
    "path": "VQ/VQM32/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQMisc 32-bit library. (Watcom/4GW)\n#\n# FILE\n#     makefile\n#\n# DESCRIPTION\n#     Makefile for generating VQMisc32 library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n# \n# DATE\n#     Feburary 10, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     WATCOM - Watcom C installation path.\n#\n#****************************************************************************\n\n.OPTIMIZE\n.ERASE\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n!ifndef %PRJ || %PRJVCS || %WATCOM\n!error Environment not configured.\n!endif\n\n#----------------------------------------------------------------------------\n# PROJECTS DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJNAME = vqm32wp\nPRJDIR  = $(%PRJ)\\VQM32\n\nOBJECTS = &\n\tiff.obj &\n\tprofile.obj &\n\taudzap.obj &\n\taudunzap.obj &\n\ttarga.obj &\n\tvertag.obj &\n\tsortpal.obj &\n\tpalette.obj &\n\tmono.obj &\n\tlcwuncmp.obj &\n\tlcwcomp.obj &\n\ttestvb.obj &\n\tvb.obj &\n\tmcgabuf.obj &\n\tvideo.obj &\n\txmode.obj &\n\txmodepg.obj &\n\tvesabuf.obj &\n\tvesablit.obj &\n\tvesavid.obj &\n\tsoscodec.obj &\n\tdrawchar.obj &\n\ttextprnt.obj &\n\tfont.obj &\n\tchrwidth.obj &\n\tmixfile.obj &\n\tcrc.obj &\n\tfillrect.obj &\n\tcaptoken.obj &\n\thuffcmp.obj &\n\thuffdcmp.obj &\n\tmem.obj &\n\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!ifdef %LIB\nLIBPATH = $(%PRJ)\\LIB;$(%LIB)\n!else\nLIBPATH = $(%PRJ)\\LIB;$(%WATCOM)\\LIB386\n!endif\n\n!ifdef %INCLUDE\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%INCLUDE)\n!else\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%WATCOM)\\H\n!endif\n\npath_c   = .\\\npath_cpp = .\\\npath_h   = .\\\npath_asm = .\\\npath_i   = .\\\npath_obj = .\\O\npath_lib = $(%PRJ)\\LIB\npath_exe = .\\\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULE EXTENSIONS AND PATHS\n#----------------------------------------------------------------------------\n\n.EXTENSIONS :\n.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i\n\n.c : $(path_c)\n.cpp : $(path_cpp)\n.h : $(path_h)\n.asm : $(path_asm)\n.i : $(path_i)\n.obj : $(path_obj)\n.lib : $(path_lib)\n.exe : $(path_exe)\n\n#----------------------------------------------------------------------------\n# TOOLS, COMMANDS AND CONFIGURATIONS\n#----------------------------------------------------------------------------\n\nCC_CMD   = wcc386\nCCP_CMD  = wpp386\nASM_CMD  = tasm32\nLINK_CMD = wlink\nLIB_CMD  = wlib\n\nCC_OPTS  = -i$(INCLUDEPATH) -j -zp1 -5s -mf -oaeilrt -s -zq\nASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /dPHARLAP_TNT=0\nLIB_OPTS = /b /c /q\nLINK_CFG = $(PRJNAME).lnk\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall : $(PRJNAME).lib .SYMBOLIC\n\n$(PRJNAME).lib : $(OBJECTS) .SYMBOLIC\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj :\n  $(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.cpp.obj :\n  $(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\\$^.\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\nupdate: .SYMBOLIC\n\t@echo Updating VQMisc32 header files!\n\t@copy *.h $(%PRJ)\\INCLUDE\\VQM32 >NUL\n\t@copy *.i $(%PRJ)\\INCLUDE\\VQM32 >NUL\n\n"
  },
  {
    "path": "VQ/VQM32/MCGABUF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     mcgabuf.asm\n;*\n;* DESCRIPTION\n;*     MCGA display routines. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Bill Randolph\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     Febuary 3, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     ClearVRAM       - Clear all VRAM.\n;*     MCGA_BufferCopy - Copy 320x200 buffer to MCGA VRAM\n;*     MCGA_Blit       - Bit blit a block to the MCGA screen.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"vga.i\"\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     ClearVRAM - Clear all VRAM.\n;*\n;* SYNOPSIS\n;*     ClearVRAM()\n;*\n;*     void ClearVRAM(void);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC ClearVRAM:NEAR\n \tPROC\tClearVRAM C NEAR USES eax ecx edi es\n\n\tIF\tPHARLAP_TNT\n\tmov\teax,01Ch\t;Set ES selector to video memory\n\tmov\tes,ax\n\tmov\tedi,0\n\tELSE\n\tmov\tedi,0A0000h\n\tENDIF\n\n\tSET_PLANE 0Fh\t;Enable all planes for writing\n\tcld\n\tmov\tecx,16000\t;Clear 320x200\n\txor\teax,eax\n\trep\tstosd\n\tret\n\n\tENDP\tClearVRAM\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     MCGA_BufferCopy - Copy 320x200 buffer to MCGA VRAM\n;*\n;* SYNOPSIS\n;*     MCGA_BufferCopy(Buffer, Dummy)\n;*\n;*     void MCGA_BufferCopy(char *, char *);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Buffer - Pointer to buffer to transfer.\n;*     Dummy  - Prototype placeholder.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC MCGA_BufferCopy:NEAR\n\tPROC\tMCGA_BufferCopy C NEAR USES ecx esi edi es\n\n\tARG\tbuffer:NEAR PTR\n\tARG\tdummy:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tmov\teax,01Ch\n\tmov\tes,ax\n\tmov\tedi,0\n\tELSE\n\tmov\tedi,0A0000h\n\tENDIF\n\n\tmov\tesi, [buffer]\n\tmov\tecx,16000\n\trep \tmovsd\t;Transfer the data\n\tret\n\n\tENDP\tMCGA_BufferCopy\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     MCGA_Blit - Bit blit a block to the MCGA screen.\n;*\n;* SYNOPSIS\n;*     MCGA_Blit(Buffer, Screen, Width, Height)\n;*\n;*     void MCGA_Blit(char *, char *, long, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Buffer - Pointer to buffer to copy.\n;*     Screen - Screen address to copy buffer to.\n;*     Width  - Width of block.\n;*     Height - Height of block.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC MCGA_Blit:NEAR\n\tPROC\tMCGA_Blit C NEAR USES ecx edx esi edi\n\n\tARG\tbuffer:NEAR PTR\n\tARG\tscreen:NEAR PTR\n\tARG\timgwidth:DWORD\n\tARG\timgheight:DWORD\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tmov\teax,1Ch\t;Set ES selector to VRAM\n\tmov\tes,ax\n\tENDIF\n\n\tmov\tesi,[buffer]\n\tmov\tedi,[screen]\n\tmov\tedx,320\n\tsub\tedx,[imgwidth]\t;Compute modulo\n\n??Do_row:\n\tmov\tecx,[imgwidth]\n\trep \tmovsb\n\tadd\tedi,edx\n\tdec\t[imgheight]\n\tjnz\t??Do_row\n\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\n\tENDP\tMCGA_Blit\n\n\tEND\n\n"
  },
  {
    "path": "VQ/VQM32/MEM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*---------------------------------------------------------------------------\n*\n* FILE\n*     mem.c\n*\n* DESCRIPTION\n*     Memory management.\n*\n* PROGRAMMER\n*     Phil Gorrow\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 5, 1995\n*\n*---------------------------------------------------------------------------\n*\n* PUBLIC\n*     DPMI_Lock   - Lock a memory page.\n*     DPMI_Unlock - Unlock a locked memory page.\n*\n****************************************************************************/\n\n#ifdef __WATCOMC__\n#include <dos.h>\n#include <mem.h>\n#include <vqm32\\mem.h>\n\n\n/****************************************************************************\n*\n* NAME\n*     DPMI_Lock - Lock a memory page.\n*\n* SYNOPSIS\n*     DPMI_Lock(Address, Size)\n*\n*     void DPMI_Lock(void *, long);\n*\n* FUNCTION\n*\n* INPUTS\n*     Address - Starting linear address of memory to lock.\n*     Size    - Size of region to lock in bytes.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid DPMI_Lock(void const *ptr, long const size)\n{\n\tunion REGS   regs;\n\tstruct SREGS sregs;\n\n\tmemset(&regs, 0, sizeof(REGS));\n\tsegread(&sregs);\n\n\t/* Lock the memory page.\n\t *\n\t * AX    = 0x600\n\t * BX:CX = Starting linear address of memory to lock.\n\t * SI:DI = Size of region to lock in bytes.\n\t */\n\tregs.x.eax = DPMI_LOCK;\n\tregs.x.ebx = ((long)ptr & 0xFFFF0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000FFFF);\n\tregs.x.esi = ((long)size & 0xFFFF0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000FFFF);\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DPMI_Unlock - Unlock a locked memory page.\n*\n* SYNOPSIS\n*     DPMI_Unlock(Address, Size)\n*\n*     void DPMI_Unlock(void *, long);\n*\n* FUNCTION\n*\n* INPUTS\n*     Address - Starting linear address of memory to unlock.\n*     Size    - Size of region to unlock in bytes.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid DPMI_Unlock(void const *ptr, long const size)\n{\n\tunion REGS   regs;\n\tstruct SREGS sregs;\n\n\t/* Unlock memory page. */\n\tmemset(&regs, 0 ,sizeof(REGS));\n\tsegread(&sregs);\n\n\tregs.x.eax = DPMI_UNLOCK;\n\tregs.x.ebx = ((long)ptr & 0xFFFF0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000FFFF);\n\tregs.x.esi = ((long)size & 0xFFFF0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000FFFF);\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n}\n\n#endif /* __WATCOMC__ */\n"
  },
  {
    "path": "VQ/VQM32/MEM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAMEM_H\n#define VQAMEM_H\n/****************************************************************************\n*\n*        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\n*\n*---------------------------------------------------------------------------\n*\n* FILE\n*     mem.h\n*\n* DESCRIPTION\n*     Memory management definitions.\n*\n* PROGRAMMER\n*     Phil Gorrow\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 5, 1995\n*\n****************************************************************************/\n\n/* Definitions */\n#define DPMI_INT    0x0031\n#define DPMI_LOCK   0x0600\n#define DPMI_UNLOCK 0x0601\n\n/* Prototypes */\n#ifdef __WATCOMC__\nvoid DPMI_Lock(void const *ptr, long const size);\nvoid DPMI_Unlock(void const *ptr, long const size);\n#else\n#define DPMI_Lock(a,b)\n#define DPMI_Unlock(a,b)\n#endif\n\n#endif /* VQAMEM_H */\n"
  },
  {
    "path": "VQ/VQM32/MIXFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     mixfile.c\n*\n* DESCRIPTION\n*     A mix file is basically a group of files concatinated together\n*     proceeded by a header describing where in the file each individual\n*     entry is located. These routines are provided to simplify the access\n*     to these file entries.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* MixFile format:\n*\n*     HEADER\n*       (2 bytes) Count - The number of entries in this file.\n*       (4 bytes) Size  - Size of the mix file in bytes.\n*\n*     SUBBLOCKS (There are \"Count\" number of these.)\n*       (4 bytes) CRC    - Entry descriptor (CRC of filename).\n*       (4 bytes) Offset - Offset in bytes from beginning of the DATA chunk.\n*       (4 bytes) Size   - Size of entry.\n*\n*     DATA\n*       Entry data.\n* \n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     OpenMix - Open mix file for access.\n*     CloseMix - Close a mix file.\n*     OpenMixEntry - Open a mix file entry.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <fcntl.h>\n#include <io.h>\n#include <mem.h>\n#include <string.h>\n#include \"mixfile.h\"\n#include \"crc.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\nint compfunc(void const *ptr1, void const *ptr2);\n\n\n/****************************************************************************\n*\n* NAME\n*     OpenMix - Open mix file for access.\n*\n* SYNOPSIS\n*     MixHandle = OpenMix(Name)\n*\n*     MixHandle *OpenMix(char *);\n*\n* FUNCTION\n*     Open a mix file for access.\n*\n* INPUTS\n*     Name - Pointer to name of mix file to open.\n*\n* RESULT\n*     MixHandle - Pointer to handle for mix file.\n*\n****************************************************************************/\n\nMIXHandle *OpenMix(char *name)\n{\n  MIXHeader mfhdr;\n\tMIXHandle *mix = NULL;\n\tlong      fh;\n\tlong      sbsize;\n\tlong      size;\n\n\t/* Open mix file and read in header. */\n\tif ((fh = open(name, (O_RDONLY|O_BINARY))) != -1) {\n\t\tif (read(fh, &mfhdr, sizeof(MIXHeader)) == sizeof(MIXHeader)) {\n\n\t\t\t/* Allocate handle based on the number of SubBlocks. */\n\t\t\tsbsize = (mfhdr.Count * sizeof(MIXSubBlock));\n\t\t\tsize = sbsize + sizeof(MIXHandle);\n\n\t\t\tif ((mix = (MIXHandle *)malloc(size)) != NULL) {\n\t\t\t\tmemset(mix, 0, size);\n\t\t\t\tmix->Name = name;\n\t\t\t\tmix->Size = mfhdr.Size;\n\t\t\t\tmix->Count = mfhdr.Count;\n\n\t\t\t\t/* Read in the SubBlock entries. */\n\t\t\t\tif (read(fh, &mix->Entries[0], sbsize) != sbsize) {\n\t\t\t\t\tfree(mix);\n\t\t\t\t\tmix = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tclose(fh);\n\t}\n\n\treturn (mix);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     CloseMix - Close a mix file.\n*\n* SYNOPSIS\n*     CloseMix(MixHandle)\n*\n*     void CloseMix(MixHandle *);\n*\n* FUNCTION\n*     Close a mix file by freeing its handle.\n*\n* INPUTS\n*     MixHandle - Pointer to MixHandle returned by OpenMix().\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid CloseMix(MIXHandle *mix)\n{\n\tfree(mix);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     OpenMixEntry - Open a mix file entry.\n*\n* SYNOPSIS\n*     FH = OpenMixEntry(MixHandle, EntryName)\n*\n*     short OpenMixEntry(MIXHandle *, char *);\n*\n* FUNCTION\n*     Opens an entry from the specified mix file handle. Use close() to close\n*     the file when done.\n*\n* INPUTS\n*     MixHandle - Pointer to MIXHandle containing entry to open.\n*     EntryName - Pointer to name of mix file entry to open.\n*\n* RESULT\n*     FH - DOS filehandle, -1 if unable to open.\n*\n****************************************************************************/\n\nlong OpenMixEntry(MIXHandle *mix, char *name)\n{\n\tMIXSubBlock key;\n\tMIXSubBlock *block;\n\tlong        fh;\n\n\t/* Search for the specified file in the mix file. */\n\tkey.CRC = Calculate_CRC(name, strlen(name));\n\tblock = (MIXSubBlock *)bsearch(&key, &mix->Entries[0], mix->Count,\n\t\t\tsizeof(MIXSubBlock), compfunc);\n\n\t/* If the block exists for the requested filename. */\n\tif (block != NULL) {\n\n\t\t/* Initialize the key for file access. */\n\t\tkey.Offset = block->Offset;\n\t\tkey.Offset += (mix->Count * sizeof(MIXSubBlock)) + sizeof(MIXHeader);\n\n\t\t/* Open the mix file. */\n\t\tif ((fh = open(mix->Name, (O_RDONLY|O_BINARY))) != -1) {\n\n\t\t\t/* Seek to the start of the file. */\n\t\t\tif (lseek(fh, key.Offset, SEEK_SET) == -1) {\n\t\t\t\tclose(fh);\n\t\t\t\tfh = -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn (fh);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     compfunc - Compare function for bsearch().\n*\n* SYNOPSIS\n*     Result = compfunc(Entry1, Entry2);\n*\n*     int compfunc(void const *, void const *);\n*\n* FUNCTION\n*\n* INPUTS\n*     Entry1 - Pointer to first entry to compare.\n*     Entry2 - Pointer to second entry to compare.\n*\n* RESULT\n*     Result -\n*\n****************************************************************************/\n\nint compfunc(void const *ptr1, void const *ptr2) \n{\n\tif (((MIXSubBlock *)ptr1)->CRC < ((MIXSubBlock *)ptr2)->CRC) return -1;\n\tif (((MIXSubBlock *)ptr1)->CRC > ((MIXSubBlock *)ptr2)->CRC) return 1;\n\treturn(0);\n}\n\n\n"
  },
  {
    "path": "VQ/VQM32/MIXFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMMIXFILE_H\n#define VQMMIXFILE_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     mixfile.h\n*\n* DESCRIPTION\n*     A mix file is basically a group of files concatinated together\n*     proceeded by a header describing where in the file each individual\n*     entry is located. These definitions are provided to simplify the access\n*     to these file entries.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/* Disable structure alignment.*/\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n\n/*---------------------------------------------------------------------------\n * STRUCTURE DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* MIXHeader: Mix file data header.\n *\n * Count - Number of entries contained in this mix file.\n * Size  - Size of Mix file.\n */\ntypedef struct _MIXHeader {\n\tshort Count;\n\tlong  Size;\n} MIXHeader;\n\n/* MIXSubBlock: Mix file entry descriptor.\n *\n * CRC    - Unique entry identifier.\n * Offset - Offset from beginning of data segment to entry.\n * Size   - Size of entry.\n */\ntypedef struct _MIXSubBlock {\n\tlong CRC;\n\tlong Offset;\n\tlong Size;\n} MIXSubBlock;\n\n/* MIXHandle: Mix file handle.\n *\n * Name    - Pointer to the name of the mix file this handle is for.\n * Size    - Size of entire mix file.\n * FH      - DOS file handle of opened entry.\n * Count   - Number of files contained in this mix.\n * Entries - Array of 'Count' MIXSubBlock structure entries.\n */\ntypedef struct _MIXHandle {\n\tchar        *Name;\n\tlong        Size;\n\tlong        FH;\n\tlong        Count;\n\tMIXSubBlock Entries[];\n} MIXHandle;\n\n/*---------------------------------------------------------------------------\n * PROTOTYPES\n *-------------------------------------------------------------------------*/\n\nMIXHandle *OpenMix(char *name);\nvoid CloseMix(MIXHandle *mix);\nlong OpenMixEntry(MIXHandle *mix, char *name);\n\n/* Restore original alignment */\n#ifdef __WATCOMC__\n#pragma pack();\n#endif\n\n#endif /* VQMMIXFILE_H */\n\n"
  },
  {
    "path": "VQ/VQM32/MONO.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     mono.asm\n;*\n;* DESCRIPTION\n;*     Mono screen print and output routines. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     Febuary 8, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     Mono_Enable       - Enable mono output.\n;*     Mono_Disable      - Disable mono output.\n;*     Mono_X            - Get mono cursors X position.\n;*     Mono_Y            - Get mono cursors Y position.\n;*     Mono_Set_Cursor   - Set the mono cursor to specified coordinates.\n;*     Mono_Clear_Screen - Clear the mono screen.\n;*     Mono_Scroll       - Scroll the mono screen up.\n;*     Mono_Put_Char     - Ouput a character to the mono screen.\n;*     Mono_Draw_Rect    - Draw a box on the mono screen.\n;*     Mono_Text_Print   - Print a string to the mono screen at a specified\n;*                         position.\n;*     Mono_Print        - Print a string to the mono screen.\n;*     Mono_View_Page    - View a mono page.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\n\tDATASEG\n\nMonoEnabled\tDD\t1\nMonoX\tDD\t0\nMonoY\tDD\t0\nMonoOff\tDD\t0\n\nCharData\tDB\t0DAh,0C4h,0BFh,0B3h,0D9h,0C4h,0C0h,0B3h\t; Single line\n\tDB\t0D5h,0CDh,0B8h,0B3h,0BEh,0CDh,0D4h,0B3h\t; Double horz.\n\tDB\t0D6h,0C4h,0B7h,0BAh,0BDh,0C4h,0D3h,0BAh\t; Double vert.\n\tDB\t0C9h,0CDh,0BBh,0BAh,0BCh,0CDh,0C8h,0BAh\t; Double line.\n\n\n;\t\tx,y,dist\nBoxData\tDB\t1,0,0\t\t; Upper left corner.\n\tDB\t1,0,1\t\t; Top edge.\n\tDB\t0,1,0\t\t; Upper right corner.\n\tDB\t0,1,2\t\t; Right edge.\n\tDB\t-1,0,0\t\t; Bottom right corner.\n\tDB\t-1,0,1\t\t; Bottom edge.\n\tDB\t0,-1,0\t\t; Bottom left corner.\n\tDB\t0,-1,2\t\t; Left edge.\n\tDB\t0,0,-1\t\t; End of list.\n\nPageMap\tDD\t0,1,2,3,4,5,6,7\n\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Enable - Enable mono output.\n;*\n;* SYNOPSIS\n;*     Mono_Enable()\n;*\n;*     void Mono_Enable(void);\n;*\n;* FUNCTION\n;*     Turn on the MonoEnabled flag.\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Enable:NEAR\n\tPROC\tMono_Enable C NEAR\n\n\tmov\t[MonoEnabled],1\n\tret\n\n\tENDP\tMono_Enable\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Disable - Disable mono output.\n;*\n;* SYNOPSIS\n;*     Mono_Disable()\n;*\n;*     void Mono_Disable(void);\n;*\n;* FUNCTION\n;*     Turn off the MonoEnabled flag.\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Disable:NEAR\n\tPROC\tMono_Disable C NEAR\n\n\tmov\t[MonoEnabled],0\n\tret\n\n\tENDP\tMono_Disable\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_X - Get mono cursors X position.\n;*\n;* SYNOPSIS\n;*     X = Mono_X()\n;*\n;*     long Mono_X(void);\n;*\n;* FUNCTION\n;*     Return the X position of the mono screen cursor.\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     X - X coordinate position.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_X:NEAR\n\tPROC\tMono_X C NEAR\n\n\tmov\teax,[MonoX]\n\tret\n\n\tENDP\tMono_X\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Y - Get mono cursors Y position.\n;*\n;* SYNOPSIS\n;*     Y = Mono_Y()\n;*\n;*     long Mono_Y(void);\n;*\n;* FUNCTION\n;*     Return the Y position of the mono screen cursor.\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     Y - Y coordinate position.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Y:NEAR\n\tPROC\tMono_Y C NEAR\n\n\tmov\teax,[MonoY]\n\tret\n\n\tENDP\tMono_Y\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Set_Cursor - Set the mono cursor to specified coordinates.\n;*\n;* SYNOPSIS\n;*     Mono_Set_Cursor(X, Y)\n;*\n;*     void Mono_Set_Cursor(long, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     X - X coordinate position.\n;*     Y - Y coordinate position.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Set_Cursor:NEAR\n\tPROC\tMono_Set_Cursor C NEAR USES eax ebx edx\n\n\tARG\txpos:DWORD\n\tARG\typos:DWORD\n\n\tcmp\t[MonoEnabled],0\n\tje\tshort ??fini\n\n\tmov\teax,[ypos]\n\tmov\tah,80\n\timul\tah\n\tadd\teax,[xpos]\n\tmov\tebx,eax\n\n;\tUpdate cursor position.\n\n\tmov\tdx,03B4h\n\tmov\tal,0Eh\t\t;High byte register set.\n\tout\tdx,al\n\tinc\tdx\n\tmov\tal,bh\n\tout\tdx,al\t\t;Set high byte.\n\n\tdec\tdx\n\tmov\tal,0Fh\t\t;Low byte register set.\n\tout\tdx,al\n\tinc\tdx\n\tmov\tal,bl\n\tout\tdx,al\t\t;Set low byte.\n\n;\tUpdate the globals.\n\n\tadd\tebx,ebx\n\tmov\t[MonoOff],ebx\n\tmov\teax,[xpos]\n\tmov\t[MonoX],eax\n\tmov\teax,[ypos]\n\tmov\t[MonoY],eax\n\n??fini:\n\tret\n\n\tENDP\tMono_Set_Cursor\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Clear_Screen - Clear the mono screen.\n;*\n;* SYNOPSIS\n;*     Mono_Clear_Screen()\n;*\n;*     void Mono_Clear_Screen(void);\n;*\n;* FUNCTION\n;*     Clear the mono screen and set the mono cursor to the upperleft corner\n;*     of the screen.\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Clear_Screen:NEAR\n\tPROC\tMono_Clear_Screen C NEAR USES es eax ecx edi\n\n;\tExit if mono disabled\n\n\tcmp\t[MonoEnabled],0\n\tje\tshort ??fini\n\n;\tClear the mono screen\n\n\tIF\tPHARLAP_TNT\n\tmov\tax,034h\n\tmov\tes,ax\t\t;Set ES selector to first MB\n\tENDIF\n\n\tmov\tedi,0B0000h\t\t;EDI = Mono screen address\n\txor\teax,eax\t\t;Set char & attributes to 0\n\tmov\tecx,8000h/4\t\t;Number of longwords to clear\n\trep\tstosd\t\t;Clear the mono screen.\n\tcall\tMono_Set_Cursor C,eax,eax\n\n??fini:\n\tret\n\n\tENDP\tMono_Clear_Screen\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Scroll - Scroll the mono screen up.\n;*\n;* SYNOPSIS\n;*     Mono_Scroll(Lines)\n;*\n;*     void Mono_Scroll(long);\n;*\n;* FUNCTION\n;*     Move the contents of the mono screen up the specified number of lines\n;*     while clearing out the bottom lines.\n;*\n;* INPUTS\n;*     Lines - Number of lines to scroll the screen up.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Scroll:NEAR\n\tPROC\tMono_Scroll C NEAR USES es eax ebx ecx esi edi\n\tARG\tlines:DWORD\n\n;\tExit if mono disabled\n\n\tcmp\t[MonoEnabled],0\n\tje\tshort ??fini\n\n;\tExit if lines to scroll is 0.\n\n\tmov\teax,[lines]\n\tor\teax,eax\n\tje\tshort ??fini\n\n;\tMove the screen data up the specified lines\n\n\tmov\tebx,eax\n\n??looper:\n\tIF\tPHARLAP_TNT\n\tmov\tax,034h\n\tmov\tes,ax\t\t;Set ES selector to first MB\n\tENDIF\n\n   \tpush\tds\t\t;Save DS selector\n\tmov\tds,ax\t\t;Set DS selector to first MB\n\n\tmov\tecx,((80*24)/2)\t;Number of DWORDs to move\n\tmov\tesi,0B00A0h\n\tmov\tedi,0B0000h\n\trep\tmovsd\n\n\tpop\tds\t\t;Restore DS selector\n\tdec\t[MonoY]\n\tsub\t[MonoOff],(80*2)\n\n\txor\teax,eax\n\tmov\tecx,(80/2)\n\trep\tstosd\n\n\tdec\tebx\n\tjne\t??looper\n\n??fini:\n\tret\n\n\tENDP\tMono_Scroll\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Put_Char - Ouput a character to the mono screen.\n;*\n;* SYNOPSIS\n;*     Mono_Put_Char(Character, Attributes)\n;*\n;*     void Mono_Put_Char(long, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Character  - ASCII character to output.\n;*     Attributes - Display attributes\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Put_Char:NEAR\n\tPROC\tMono_Put_Char C NEAR USES es eax edi\n\tARG\tcharacter:DWORD\n\tARG\tattrib:DWORD\n\n;\tExit if mono disabled\n\n\tcmp\t[MonoEnabled],0\n\tje\tshort ??fini\n\n;\tOutput character to the mono screen\n\n\tcld\n\n\tIF\tPHARLAP_TNT\n\tmov\tax,034h\n\tmov\tes,ax\t\t;Set ES selector to first MB\n\tENDIF\n\n\tmov\tedi,0B0000h\t\t;EDI = mono screen\n\tadd\tedi,[MonoOff]\t\t;Add cursor offset\n\tmov\teax,[character]\n\tmov\tah,[BYTE PTR attrib]\n\tstosw\n\n;\tUpdate cursor position.\n\n\tinc\t[MonoX]\t\t; X position moves.\n\tcall\tMono_Set_Cursor C,[MonoX],[MonoY]\n\n??fini:\n\tret\n\n\tENDP\tMono_Put_Char\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Draw_Rect - Draw a box on the mono screen.\n;*\n;* SYNOPSIS\n;*     Mono_Draw_Rect(X, Y, Width, Height, Attributes, Thickness)\n;*\n;*     void Mono_Draw_Rect();\n;*\n;* FUNCTION\n;*     Draw a rectangle text box on the mono screen.\n;*\n;* INPUTS\n;*     X          - X coordinate position of upperleft corner.\n;*     Y          - Y coordinate position of upperleft corner.\n;*     Width      - Desired width.\n;*     Height     - Desired height.\n;*     Attributes - Display attributes.\n;*     Thickness  - Line thickness.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Draw_Rect:NEAR\n\tPROC\tMono_Draw_Rect C NEAR\n\tARG\txpos:DWORD\n\tARG\typos:DWORD\n\tARG\twidth:DWORD\n\tARG\theight:DWORD\n\tARG\tattrib:DWORD\n\tARG\tthick:DWORD\n\n;\tExit if mono disabled\n\n\tpushad\n\tcmp\t[MonoEnabled],0\n\tje\t??fini\n\n;\tSelect the character table for the desired line thickness\n\n\tmov\tedi,OFFSET CharData\n\tmov\tcl,3\n\tmov\teax,[thick]\n\tand\teax,011b\n\tshl\teax,cl\n\tadd\tedi,eax\n\n;\tPrep width and height.\n\n\tcmp\t[width],2\n\tjb\t??fini\n\n\tcmp\t[height],2\n\tjb\t??fini\n\n\tsub\t[width],2\n\tsub\t[height],2\n\n;\tSet cursor position to upperleft corner of box\n\n\tpush\t[MonoY]\n\tpush\t[MonoX]\t\t;Save current cursor position\n\tcall\tMono_Set_Cursor C,[xpos],[ypos]\n\n;\tDraw the rectangle\n\n\tmov\tesi,OFFSET BoxData\n\n;\tDetermine the number of characters to output\n\n??drawloop:\n\tmov\tecx,[width]\n\tcmp\t[BYTE PTR esi+2],1\n\tje\tshort ??gotlen\n\n\tmov\tecx,[height]\n\tcmp\t[BYTE PTR esi+2],2\n\tje\tshort ??gotlen\n\n\tmov\tecx,1\n\n??gotlen:\n\tjecxz\t??donerun\n\n??runloop:\n\txor\teax,eax\n\tmov\tal,[BYTE PTR edi]\n\tcall\tMono_Put_Char C,eax,[attrib]\t;Output the character.\n\n\tmov\tal,[BYTE PTR esi+1]\n\tcbw\n\tcwde\n\tadd\teax,[MonoY]\n\tpush\teax\n\tmov\tal,[BYTE PTR esi]\n\tcbw\n\tcwde\n\tadd\teax,[MonoX]\n\tdec\teax\t\t; Undo cursor advance.\n\tpush\teax\n\tcall\tMono_Set_Cursor\t; Properly advance cursor.\n\tadd\tsp,8\n\tloop\t??runloop\n\n;\tAdvance to next control entry.\n\n??donerun:\n\tadd\tesi,3\n\tinc\tedi\n\tcmp\t[BYTE PTR esi+2],-1\n\tjne\t??drawloop\n\n;\tRestore cursor to original position.\n\n\tcall\tMono_Set_Cursor\n\tadd\tsp,8\n\n??fini:\n\tpopad\n\tret\n\n\tENDP\tMono_Draw_Rect\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Text_Print - Print a string to the mono screen at a specified\n;*                       position.\n;*\n;* SYNOPSIS\n;*     Mono_Text_Print(String, X, Y, Attributes, Update)\n;*\n;*     void Mono_Text_Print(char *, long, long, long, long);\n;*\n;* FUNCTION\n;*     Print a NULL terminated string to the mono screen at the specified\n;*     cooridinates and attributes.\n;*\n;* INPUTS\n;*     String     - Pointer to NULL terminated string.\n;*     X          - X coordinate position.\n;*     Y          - Y coordinate position.\n;*     Attributes - Display attributes\n;*     Update     - Update cursor position flag.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC _Mono_Text_Print:NEAR\n\tPROC\t_Mono_Text_Print C NEAR USES eax esi\n\tARG\ttext:NEAR PTR\n\tARG\txpos:DWORD\n\tARG\typos:DWORD\n\tARG\tattrib:DWORD\n\tARG\tupdate:DWORD\n\n;\tSave the current cursor position.\n\n\tpush\t[MonoY]\n\tpush\t[MonoX]\n\tcmp\t[text],0\t\t;Exit if the string is NULL\n\tje\tshort ??fini\n\n\tcall\tMono_Set_Cursor C,[xpos],[ypos]\n\n;\tPrint string to the mono screen\n\n\tmov\tesi,[text]\t\t;Text pointer\n\n??charloop:\n\tmov\teax,[esi]\n\tinc\tesi\n\tor\tal,al\t\t;Stop on a NULL\n\tje\tshort ??fini\n\n\tcmp\tal,13\t\t;Special processing for '\\r'\n\tje\tshort ??cr\n\n;\tOutput character to mono screen\n\n??normal:\n\txor\tah,ah\n\tcall\tMono_Put_Char C,eax,[attrib]\n\n;\tPerform adjustments if wrapping past right margin.\n\n\tcmp\t[MonoX],80\n\tjb\tshort ??nowrap\n\n\tinc\t[ypos]\n\tcall\tMono_Set_Cursor C,0,[ypos]\n\tjmp\tshort ??nowrap\n\n\t; Move to start of next line.\n\n??cr:\n\tinc\t[ypos]\n\tcall\tMono_Set_Cursor C,[xpos],[ypos]\n\n;\tScroll the monochrome screen if necessary.\n\n??nowrap:\n\tcmp\t[MonoY],25\n\tjb\tshort ??noscroll\n\n\tcall\tMono_Scroll C,1\n\tdec\t[ypos]\n\n??noscroll:\n\tjmp\tshort ??charloop\n\n??fini:\n\tcmp\t[update],0\n\tjne\tshort ??noupdate\n\n\tcall\tMono_Set_Cursor\n\n??noupdate:\n\tpop\teax\n\tpop\teax\n\tret\n\n\tENDP\t_Mono_Text_Print\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Text_Print - Print a string to the mono screen. (ASM call)\n;*\n;* SYNOPSIS\n;*     Mono_Text_Print(String, X, Y, Attributes)\n;*\n;*     void Mono_Text_Print(char *, long, long, long);\n;*\n;* FUNCTION\n;*     Print a NULL terminated string to the mono screen at the specified\n;*     cooridinates and attributes.\n;*\n;* INPUTS\n;*     String     - Pointer to NULL terminated string.\n;*     X          - X coordinate position.\n;*     Y          - Y coordinate position.\n;*     Attributes - Display attributes\n;*\n;* RESULT\n;*     NONE\n;*\n;* SEE ALSO\n;*     _Mono_Text_Print\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Text_Print:NEAR\n\tPROC\tMono_Text_Print C NEAR USES\n\tARG\ttext:NEAR PTR\n\tARG\txpos:DWORD\n\tARG\typos:DWORD\n\tARG\tattrib:DWORD\n\n;\tExit if mono disabled\n\n\tcmp\t[MonoEnabled],0\n\tje\tshort ??fini\n\n\tcall\t_Mono_Text_Print C,[text],[xpos],[ypos],[attrib],0\n\n??fini:\n\tret\n\n\tENDP\tMono_Text_Print\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Print - Print a string to the mono screen.\n;*\n;* SYNOPSIS\n;*     Mono_Print(String)\n;*\n;*     void Mono_Print(char *);\n;*\n;* FUNCTION\n;*     Print a string to the mono screen at the current cursor position and\n;*     update the cursor position.\n;*\n;* INPUTS\n;*     String - Pointer to NULL terminated string.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Print:NEAR\n\tPROC\tMono_Print C NEAR\n\tARG\ttext:NEAR PTR\n\n;\tExit if mono disabled\n\n\tcmp\t[MonoEnabled],0\n\tje\tshort ??fini\n\n\tcall\t_Mono_Text_Print C,[text],[MonoX],[MonoY],2,1\n\n??fini:\n\tret\n\n\tENDP\tMono_Print\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_View_Page - View a mono page.\n;*\n;* SYNOPSIS\n;*     Oldpage = Mono_View_Page(Page)\n;*\n;*     long Mono_View_Page(long);\n;*\n;* FUNCTION\n;*     Displays the specified page in displayable mono memory.\n;*\n;* INPUTS\n;*     Page - Page to view.\n;*\n;* RESULT\n;*     Oldpage - Previous page.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_View_Page:NEAR\n\tPROC\tMono_View_Page C NEAR USES ds es eax ebx ecx edi esi\n\tARG\tpage:DWORD\n\tLOCAL\toldpage:DWORD\n\n;\tPrepare the original page number for return to caller.\n\n\tcld\n\tmov\tebx,[PageMap]\n\tmov\t[oldpage],ebx\n\n;\tExit of mono disabled\n\n\tcmp\t[MonoEnabled],0\n\tje\tshort ??fini\n\n;\tIf the desired page is already displayed, then don't do anything.\n\n\tmov\teax,[page]\n\tcmp\teax,ebx\n\tje\tshort ??fini\n\n;\tVerify that page specified is legal.\n\n\tcmp\teax,7\n\tja\tshort ??fini\n\n;\tFind where the logical page to display is actually located.\n\n\tmov\tecx,8\n\tpush\tds\n\tpop\tes\n\tlea\tedi,[PageMap]\n\trepne\tscasw\n\tneg\tecx\n\tadd\tecx,7\t\t; CX = where desired page is located.\n\n;\tSwap the page ID bytes in the PageMap array.\n\n\tsub\tedi,4\n\tmov\tebx,[PageMap]\n\tmov\teax,[edi]\n\tmov\t[edi],ebx\n\tmov\t[PageMap],eax\n\n\tshl\tecx,8\n\tadd\tecx,eax\n\tmov\tesi,ecx\n\n\tIF\tPHARLAP_TNT\n\tmov\tax,034h\n\tmov\tds,ax\n\tENDIF\n\n\tmov\tedi,0B0000h\n\n;\tExchange the two pages.\n\n\tmov\tecx,1000H/4\n\n??looper:\n\tmov\tedx,[edi]\n\tmov\tebx,[esi]\n\tmov\t[edi],ebx\n\tmov\t[esi],edx\n\tadd\tesi,4\n\tadd\tedi,4\n\tloop\t??looper\n\n;\tReturn with the original page number.\n\n??fini:\n\tmov      \teax,[oldpage]\n\tret\n\t\n\tENDP\tMono_View_Page\n\n\tEND\n\n"
  },
  {
    "path": "VQ/VQM32/MONO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMMONO_H\n#define VQMMONO_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     mono.h\n*\n* DESCRIPTION\n*     Mono screen definitions. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Feburary 8, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid cdecl Mono_Enable(void);\nvoid cdecl Mono_Disable(void);\nvoid cdecl Mono_Set_Cursor(long x, long y);\nvoid cdecl Mono_Clear_Screen(void);\nvoid cdecl Mono_Scroll(long lines);\nvoid cdecl Mono_Put_Char(long character, long attrib);\nvoid cdecl Mono_Draw_Rect(long x, long y, long w, long h, long attrib,\n\t\tlong thick);\n\nvoid cdecl Mono_Text_Print(void const *text, long x, long y, long attrib);\nvoid cdecl Mono_Print(void const *text);\nshort cdecl Mono_View_Page(long page);\nshort cdecl Mono_X(void);\t  \nshort cdecl Mono_Y(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMMONO_H */\n"
  },
  {
    "path": "VQ/VQM32/PALETTE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     palette.asm\n;*\n;* DESCRIPTION\n;*     Hardware level palette routines. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Bill Randolph\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* To write palette colors:\n;* - Out color # to 3c8h\n;* - Out RGB values to 3c9h (data must be written in three's; PEL address\n;*   register auto-increments after 3 reads or writes)\n;*\n;* A time interval of about 240 ns is required between successive reads/\n;* writes; on very fast machines, this means that the system may not be\n;* able to handle a rapid-fire of RGB values.  So, a \"safe\" routine is\n;* provided that has wait states between each out.\n;* \n;* Reference: Progammers Guide to the EGA & VGA Cards, Ferraro, 2nd ed.\n;* (Chapter 8.)\n;*\n;* Note that, if you set the palette in active scan, the screen will\n;* flash; to prevent this, wait for vertical retrace (Vertical Blank\n;* Interval), or turn the display off by using the Screen Off field in\n;* the Clocking Mode register (Hmmmm....).\n;*\n;* To read palette colors:\n;* - Out color # to 3c7h\n;* - In RGB values from 3c9h (data must be read in three's; PEL address\n;*   register auto-increments after 3 reads or writes)\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     SetPalette       - Set the palette without waiting to Vblank.\n;*     ReadPalette      - Read the palette from the display adapter.\n;*     SetDAC           - Set a single palette color in the DAC.\n;*     TranslatePalette - Translate 24-bit color to 15-bit color.\n;*      \n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"vga.i\"\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     SetPalette - Set the palette without waiting to Vblank.\n;*\n;* SYNOPSIS\n;*     SetPalette(Palette, Numbytes, SlowFlag)\n;*\n;*     void SetPalette(char *, long, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Palette  - Pointer to the palette to set.\n;*     NumBytes - Number of bytes of palette to transfer (multiple of 3).\n;*     SlowFlag - Slow palette set flag.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC SetPalette:NEAR\n\tPROC\tSetPalette C NEAR USES eax ecx edx esi ds\n\n\tARG\tpalette:NEAR PTR\n\tARG\tnumbytes:DWORD\n\tARG\tslowpal:DWORD\n\n\tpushf\n\tcld\n\n\tcmp\t[slowpal],0\t;Do slow palette?\n\tjne\t??safe_palette_routine\n\n;----------------------------------------------------------------------------\n;\tFast palette set\n;----------------------------------------------------------------------------\n\n\tmov\tesi,[palette]\n\tmov\tedx,PEL_WRITE_ADDR\n\txor\tal,al\t\t\t\n\tout\tdx,al\t;Select color to write too.\n\tinc\tal\t;Step to the next color for next loop\n\tinc\tedx\t;DX = PEL_DATA\n\tmov\tecx,[numbytes]\t;Max # colors to set\n\trep \toutsb\t;Write 256 * RGB out to the palette\n\tpopf\n\tret\n\t\n;----------------------------------------------------------------------------\n;\tSafe palette set\n;----------------------------------------------------------------------------\n\n??safe_palette_routine:\n\tmov\tesi,[palette]\n\tmov\tecx,[numbytes]\n\tmov\tedx,PEL_WRITE_ADDR\n\tsub\teax,eax\n\tout\tdx,al\n\tmov\tedx,PEL_DATA\n\n??Write_loop:\n\tlodsb\n\tout\tdx,al\t;Red\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tlodsb\n\tout\tdx,al\t;Green\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tlodsb\n\tout\tdx,al\t;Blue\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tsub\tcx,3\n\tja\t??Write_loop\n\n\tpopf\n\tret\n\n\tENDP\tSetPalette\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     ReadPalette - Read the palette from the display adapter.\n;*\n;* SYNOPSIS\n;*     ReadPalette(Palette)\n;*\n;*     void SetPalette(char *);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Palette - Pointer buffer to copy palette into.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC ReadPalette:NEAR\n\tPROC\tReadPalette C NEAR USES ecx edx edi es\n\n\tARG\tpalette:NEAR PTR\n\n\tmov\tedi,[palette]\n\tmov\tecx,256\n\tmov\tedx,PEL_READ_ADDR\n\tsub\teax,eax\n\tout\tdx,al\n\tmov\tedx,PEL_DATA\n\n??Read_loop:\n\tin\tal,dx\t;Red\n\tstosb\t\t;Save the byte\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tin\tal,dx\t;Green\n\tstosb\t\t;Save the byte\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tin\tal,dx\t;Blue\n\tstosb\t\t;Save the byte\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tdec\tecx\n\tjnz\t??Read_loop\n\tret\n\n\tENDP\tReadPalette\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     SetDAC - Set a single palette color in the DAC.\n;*\n;* SYNOPSIS\n;*     SetDAC(ColorNum, Red, Green, Blue)\n;*\n;*     void SetPalette(long, char, char);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     ColorNum - Position number in palette of color to set.\n;*     Red      - Red gun value.\n;*     Green    - Green gun value.\n;*     Blue     - Blue gun value.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC SetDAC:NEAR\n\tPROC\tSetDAC C NEAR USES edx\n\n\tARG\tcolor_num:DWORD\n\tARG\tred:BYTE\n\tARG\tgreen:BYTE\n\tARG\tblue:BYTE\n\n\tmov\tedx,PEL_WRITE_ADDR\n\tmov\teax,[color_num]\n\tout\tdx,al\t;Set color position\n\tinc\tedx\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tmov\tal,[red]\n\tout\tdx,al\t;Set red gun\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tmov\tal,[green]\n\tout\tdx,al\t;Set green gun\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tmov\tal,[blue]\n\tout\tdx,al\t;Set blue gun\n\tret\n\n\tENDP\tSetDAC\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     TranslatePalette - Translate 24-bit color to 15-bit color.\n;*\n;* SYNOPSIS\n;*     TranslatePalette(Pal24, Pal15, NumBytes)\n;*\n;*     void TranslatePalette(char *, char *, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Pal24 - Pointer to 24-bit palette. (Input)\n;*     Pal15 - Pointer to 15-bit palette. (Output)\n;*     NumBytes - Number of bytes to translate. (divisible by 3)\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC TranslatePalette:NEAR\n\tPROC\tTranslatePalette C NEAR USES ecx edx edi esi\n\n\tARG\tpal24:NEAR PTR\n\tARG\tpal15:NEAR PTR\n\tARG\tnumbytes:DWORD\n\n\tmov\tesi,[pal24]\n\tmov\tedi,[pal15]\n\tmov\tecx,[numbytes]\n\n??TranslatePalette:\n\tmov\tah,[BYTE PTR esi]\t;AH = red\n\tmov\tal,[BYTE PTR esi+1]\t;AL = green\n\tmov\tdl,[BYTE PTR esi+2]\t;DL = blue\n\tshr\tah,1\t\t;Red = lower 5 bits of AH\n\tshl\tal,2\t\t;Green = upper 6 bits of AL\n\tshr\tdl,1\t\t;Blue = lower 5 bits of DL\n\tshl\teax,2\t\t;Make room for blue\n\tand\tal,0E0h\t\t;Trim off bottom bit of green\n\tor\tal,dl\t\t;Load in blue bits\n\tmov\t[WORD PTR edi],ax\t;Store the value\n\tadd\tesi,3\t\t;Increment to next RGB values\n\tadd\tedi,2\t\t;Increment to next palette word\n\tsub\tecx,3\n\tja\t??TranslatePalette\n\tret\n\n\tENDP\tTranslatePalette\n\n\tEND\n"
  },
  {
    "path": "VQ/VQM32/PALETTE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMPALETTE_H\n#define VQMPALETTE_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Palette.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     Palette definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid cdecl SetPalette(unsigned char *palette,long numbytes,unsigned long slowpal);\nvoid cdecl ReadPalette(void *palette);\nvoid cdecl SetDAC(long color, long red, long green, long blue);\nvoid cdecl TranslatePalette(void *pal24, void *pal15, long numbytes);\n\n#ifdef __cplusplus\n}\n#endif\n\nvoid SortPalette(unsigned char *pal, long numcolors);\n\n#endif /* VQMPALETTE_H */\n\n"
  },
  {
    "path": "VQ/VQM32/PORTIO.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     portio.asm\n;*\n;* DESCRIPTION\n;*     I/O Port access. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     inp  - Read a byte from a hardware port.\n;*     outp - Write a byte to a hardware port.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     inp - Read a byte from a hardware port.\n;*\n;* SYNOPSIS\n;*     Data = inp(PortID)\n;*\n;*     short inp(unsinged short);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     PortID - Address if hardware port.\n;*\n;* RESULT\n;*     Data - Data read from port.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC inp:NEAR\n\tPROC\tinp C NEAR USES edx\n\tARG\tport:WORD\n\n\tmov\tdx,[port]\n\txor\teax,eax\n\tin\tal,dx\n\tret\n\n\tENDP\tinp\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     outp - Write a byte to a hardware port.\n;*\n;* SYNOPSIS\n;*     outp(PortID, Value)\n;*\n;*     void outp(unsinged short, short);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     PortID - Address if hardware port.\n;*     Value  - Value to write.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC outp:NEAR\n\tPROC\toutp C NEAR USES edx\n\tARG\tport:WORD\n\tARG\tvalue:WORD\n\n\tmov\tdx,[port]\n\tmov\tax,[value]\n\tout\tdx,al\n\tret\n\n\tENDP\toutp\n\n\tEND\n"
  },
  {
    "path": "VQ/VQM32/PORTIO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMPORTIO_H\n#define VQMPORTIO_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Portio.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     Hardware port I/O\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n#ifdef __BORLANDC__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nshort cdecl inp(unsigned short portid);\nvoid cdecl outp(unsigned short portid, short value);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* __BORLANDC__ */\n\n#endif /* VQMPORTIO_H */\n\n"
  },
  {
    "path": "VQ/VQM32/PROFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     profile.c\n*\n* DESCRIPTION\n*     INI file processing. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*      \n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     Get_Frame_Pathname - Get pathname for a given frame and file type.\n*     GetINIInt          - Get an integer value from an INI file.\n*     GetINIString       - Get a string from the INI file.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"profile.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n#ifndef max\n#define max(a,b) (((a)>(b))?(a):(b))\n#endif\n#ifndef min\n#define min(a,b) (((a)<(b))?(a):(b))\n#endif\n\n#define isspace(c) ((c==' ')||(c=='\\t')||(c=='\\n')||(c=='\\r')?1:0)\n\nstatic char *strtrim(char *string);\nstatic long FileGets(FILE *fp, char *buf, long buflen);\n\n\n/****************************************************************************\n*\n* NAME\n*     Get_Frame_Pathname - Get pathname for a given frame and file type.\n*\n* SYNOPSIS\n*     Error = Get_Frame_Pathname(IniFile, Frame, Extension, Buffer)\n*\n*     long Get_Frame_Pathname(char *, long, char *, char *);\n*\n* FUNCTION\n*\n* INPUTS\n*     IniFile   - Pointer to INI filename.\n*     Frame     - Number of frame to get filename for.\n*     Extension - File extension type.\n*     Buffer    - Pointer to buffer to put pathname into.\n*\n* RESULT\n*     Error - 0 if successful, or -1 if error.\n*\n***************************************************************************/\n\nlong Get_Frame_Pathname(char *inifile, long anim_frame, char *ext,\n\t\tchar *outbuf)\n{\n\tchar rootdir[_MAX_PATH];\t// Root directory from INI file\n\tchar extdir[_MAX_PATH];\t\t// this extension's directory\n\tchar entry_name[40];\t\t\t// INI entry name\n\tchar inibuf[80];\t\t\t\t\t// string returned from INI file\n\tchar *prefix;\t\t\t\t\t\t\t// 4-char prefix for this scene\n\tchar *startstr;\t\t\t\t\t\t// starting frame #, string\n\tchar *endstr;\t\t\t\t\t\t\t// ending frame #, string\n\tchar *palstr;\t\t\t\t\t\t\t// palette filename string\n\tlong startnum;\t\t\t\t\t\t// scene's starting frame #\n\tlong endnum;\t\t\t\t\t\t\t// scene's ending frame #\n\tlong total_frames;\t\t\t\t// accumulated frame total\n\tlong scene_frames;\t\t\t\t// # frames in a given scene\n\tlong scene_num;\t\t\t\t\t\t// scene #\n\tlong file_frame;\t\t\t\t\t// file's frame #\n\tlong rc;\n\t\n\t/* Get directory for this file type */\n\tGetINIString(\"Path\", \"Root\", \"\", rootdir, 80, inifile);\n\n\tif (rootdir[strlen (rootdir) - 1] != '\\\\') {\n\t\tstrcat(rootdir,\"\\\\\");\n\t}\n\n\tGetINIString(\"Path\", ext, \"\", extdir, 80, inifile);\n\n\tif (extdir[strlen (extdir) - 1] != '\\\\') {\n\t\tstrcat(extdir,\"\\\\\");\n\t}\n\n\t/* VQG is a special case:\n\t *\n\t * The VQG files are named based upon the 1st 4 characters of the 'Name'\n\t * entry in the INI file, and their numbers match the actual animation\n\t * frame numbers, not the scene frame numbers.\n\t */\n\tif (!stricmp(ext, \"VQG\")) {\n\t\tGetINIString(\"Common\", \"Name\", \"\", inibuf, 80, inifile);\n\n\t\tif (strlen(inibuf) > 4) {\n\t\t\tinibuf[4] = 0;\n\t\t}\n\n\t\tsprintf(outbuf,\"%s%s%s%04d.%s\",rootdir,extdir,inibuf,anim_frame,ext);\n\t\treturn (0);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * Loop through scenes until the desired frame # is found\n\t *-----------------------------------------------------------------------*/\n\ttotal_frames = 0;\n\tscene_num = 1;\n\n\twhile (1) {\n\n\t\t/* Get this scene's entry */\n\t\tsprintf(entry_name, \"Scene%d\", scene_num);\n\t\trc = GetINIString(\"Scenes\",entry_name,\"\",inibuf,80,inifile);\n\n\t\tif (rc == 0) {\n\t\t\treturn (-1);\n\t\t}\n\n\t\t/* Parse the INI entry */\n\t\tprefix = strtok(inibuf, \",\");\n\t\tstartstr = strtok(NULL, \",\");\n\t\tendstr = strtok(NULL, \",\");\n\t\tpalstr = strtok(NULL, \",\");\n\n\t\tif ((prefix == NULL) || (startstr == NULL) || (endstr == NULL)) {\n\t\t\treturn (-1);\n\t\t}\n\n\t\tstartnum = atoi(startstr);\n\t\tendnum = atoi(endstr);\n\t\tscene_frames = ((endnum - startnum) + 1);\n\n\t\t/* requested frame is found */\n\t\tif (anim_frame < (total_frames + scene_frames)) {\n\n\t\t\t/* Palette is a special case */\n\t\t\tif (!stricmp(ext, \"PAL\")) {\n\t\t\t\tif (palstr == NULL) {\n\t\t\t\t\treturn (-1);\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(outbuf, \"%s%s%s.PAL\", rootdir, extdir, palstr);\n\t\t\t\t\treturn (0);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfile_frame = ((anim_frame - total_frames) + startnum);\n\t\t\t\tsprintf(outbuf,\"%s%s%s%04d.%s\",rootdir,extdir,prefix,file_frame,ext);\n\t\t\t\treturn (0);\n\t\t\t}\n\t\t}\n\n\t\t/* Frame not found; go to next scene */\n\t\ttotal_frames += scene_frames;\n\t\tscene_num++;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetINIInt - Get an integer value from an INI file.\n*\n* SYNOPSIS\n*     Value = GetINIInt(Section, Entry, Default, ININame)\n*\n*     long GetINIInt(char *, char *, long, char *);\n*\n* FUNCTION\n*     Retrieve an integer value from the INI file at the specified 'Section'\n*     and 'Entry' fields. If no value is defined then return the passed in\n*     'Default' value.\n*\n* INPUTS\n*     Section - Pointer to section name.\n*     Entry   - Pointer to entry name.\n*     Default - Default value.\n*     ININame - Pointer to INI filename.\n*\n* RESULT\n*     Value - Integer value from INI file or 'Default'.\n*\n****************************************************************************/\n\nlong GetINIInt(char const *section, char const *entry, long deflt, \n\t\tchar *fname)\n{\n\tchar buffer[20];\n\n\tsprintf(buffer, \"%d\", deflt);\n\tGetINIString(section, entry, buffer, buffer, sizeof(buffer),\n\t\t\tfname);\n\n\treturn (atoi(buffer));\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetINIString - Get a string from the INI file.\n*\n* SYNOPSIS\n*     Length = GetINIString(Section, Entry, Default, Buffer,\n*                                      Length, ININame)\n*\n*     long GetINIString(char *, char *, char *, char *, long,\n*                                  char *);\n*\n* FUNCTION\n*\n* INPUTS\n*     Section - Pointer to section name.\n*     Entry   - Pointer to entry name.\n*     Default - Pointer to default string.\n*     Buffer  - Pointer to buffer to copy string into.\n*     Length  - Maximum length of string.\n*     ININame - Pointer to INI filename.\n*\n* RESULT\n*     Length - Length of string copied into the buffer.\n*\n****************************************************************************/\n\nlong GetINIString(char const *section, char const *entry, \n\t\tchar const *def, char *retbuffer, long retlen, char *fname)\n{\n\tFILE *fp;\n\tlong retval;\n\tchar txt[80];\n\tchar secname[40];\n\tlong len;\n\tchar *workptr;\n\n\t/* Copy default value in case entry isn't found */\n\tstrncpy(retbuffer, def, (retlen - 1));\n\tretbuffer[retlen - 1] = 0;\n\tretval = min(strlen(def), (unsigned)retlen);\n\n\t/* Open the file */\n\tif ((fp = fopen(fname, \"rt\")) == NULL) {\n\t\treturn (retval);\n\t}\n\n\t/* Generate section name for search */\n\tsprintf(secname, \"[%s]\", section);\n\tlen = strlen(secname);\n\n\t/* Scan file for section name */\n\twhile (1) {\n\n\t\t/* Read line; return if end-of-file */\n\t\tif (FileGets(fp,txt,80)!=0) {\n\t\t\tfclose(fp);\n\t\t\treturn (retval);\n\t\t}\n\n\t\t/* Skip comments */\n\t\tif (txt[0] == ';') continue;\n\n\t\t/* Parse a section name */\n\t\tif (txt[0] == '[') {\n\t\t\tif (!memicmp(secname, txt, len)) break;\n\t\t}\n\t}\n\n\t/* Scan file for desired entry */\n\tlen = strlen(entry);\n\n\twhile (1) {\n\n\t\t/* Read line; return if end-of-file */\n\t\tif (FileGets(fp, txt, 80) != 0) {\n\t\t\tfclose(fp);\n\t\t\treturn (retval);\n\t\t}\n\n\t\t/* Skip comments */\n\t\tif (txt[0] == ';') continue;\n\n\t\t/* Return if start of next section reached */\n\t\tif (txt[0] == '[') {\n\t\t\tfclose(fp);\n\t\t\treturn (retval);\n\t\t}\n\n\t\t/* Entry found; parse it */\n\t\tif (!memicmp(entry, txt, len) && (isspace(txt[len])\n\t\t\t\t|| txt[len] == '=')) {\n\n\t\t\tfclose(fp);\n\n\t\t\t/* Find '=' character */\n\t\t\tworkptr = strchr(txt, '=');\n\n\t\t\t/* Return if not found */\n\t\t\tif (workptr == NULL) return (retval);\n\n\t\t\t/* Skip past '=' */\n\t\t\tworkptr++;\n\n\t\t\t/* Skip white space */\n\t\t\twhile (isspace(*workptr) && strlen(workptr) > 0) {\n\t\t\t\tworkptr++;\n\t\t\t}\n\n\t\t\t/* Return if no string left */\n\t\t\tif ((*workptr) == 0) return (retval);\n\n\t\t\tstrtrim(workptr);\n\t\t\tstrcpy(retbuffer,workptr);\n\n\t\t\treturn (strlen(workptr));\n\t\t}\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     strtrim - Trim off trailing spaces from a string.\n*\n* SYNOPSIS\n*     String = strtrim(String)\n*\n*     char *strtrim(char *);\n*\n* FUNCTION\n*\n* INPUTS\n*     String - Pointer to string to trim.\n*\n* RESULT\n*     String - Pointer to trimmed string.\n*\n****************************************************************************/\n\nstatic char *strtrim(char *string)\n{\n\tlong i;\n\n\t/* Return if NULL ptr or zero-length string */\n\tif ((string == NULL) || (strlen(string) == 0)) {\n\t\treturn (string);\n\t}\n\n\t/* Find 1st non-white-space character from the right */\n\ti = (strlen(string) - 1);\n\n\twhile ((i > 0) && isspace(string[i])) {\n\t\ti--;\n\t}\n\n\t/* Set end of string */\n\ti++;\n\tstring[i] = 0;\n\n\treturn (string);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     FileGets - A better fgets.\n*\n* SYNOPSIS\n*     Error = FileGets(FilePtr, Buffer, Length)\n*\n*     long FileGets(FILE *, char *, long);\n*\n* FUNCTION\n*\n* INPUTS\n*     FilePtr - File pointer.\n*     Buffer  - Pointer to buffer to fill.\n*     Length  - Maximum length of buffer.\n*\n* RESULT\n*     Error = 0 if successfull, or -1 if error.\n*\n****************************************************************************/\n\nstatic long FileGets(FILE *fp, char *buf, long buflen)\n{\n\tif (fgets(buf, buflen, fp)) {\n\t\tbuf[(strlen(buf) - 1)] = 0;\n\t\treturn (0);\n\t} else {\n\t\treturn (-1);\n\t}\n}\n\n"
  },
  {
    "path": "VQ/VQM32/PROFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMPROFILE_H\n#define VQMPROFILE_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Profile.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     INI file profiling definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\nlong GetINIInt(char const *section, char const *entry,\n\t\tlong deflt, char *fname);\n\nlong GetINIString(char const *section, char const *entry, \n\t\tchar const *def, char *retbuffer, long retlen, char *fname);\n\nlong Get_Frame_Pathname(char *inifile,long anim_frame,char *ext,\n\t\tchar *outbuf);\n\n#endif /* VQMPROFILE_H */\n\n"
  },
  {
    "path": "VQ/VQM32/REALMODE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMREALMODE_H\n#define VQMREALMODE_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     realmode.h\n*\n* DESCRIPTION\n*     Real-mode interfacing definitions and equates. Many of the definitions\n*     and descriptions in this file were taken from other sources and\n*     compiled here for use in MISC32 library.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 6, 1995\n*\n****************************************************************************/\n\n/* REALPTR: Real-mode pointer (segment:offset16).\n *\n * The REALPTR data type is used in protected mode to hold real-mode\n * pointers. The type is an unsigned long value, were the upper 16 bits\n * are the segment number and the lower 16 bit are an offset. This type\n * and the associated macros are identical to that of the PHARLAP \"pltypes.h\"\n * definitions for easy of conversion to WATCOM/4GW.\n */\ntypedef unsigned long REALPTR;\n\n#define RP_OFF(rp) ((unsigned short)(((unsigned long)(rp)) & 0xFFFF))\n#define RP_SEG(rp) ((unsigned short)(((unsigned long)(rp)) >> 16))\n#define RP_SET(rp, off, seg) (rp = ((unsigned long)(seg) << 16) + (off))\n#define RP_INCR(rp, incr) (rp += ((unsigned long)(incr)) & 0xFFFF)\n\n#define MK_PTR(off, seg) (void *)((((unsigned long)seg&0xFFFF)<<4)+off)\n\n/* RMInfo: Real-mode interrupt call structure.\n *\n * Information that needs to be passed down to the real-mode interrupt is\n * transfered using this structure. The address to this protected-mode\n * structure (allocated by user) is passed into DPMI function 0x300. DOS/4GW\n * will then use this information to set up the real-mode registers, switch\n * to real-mode and then execute the interrupt in real-mode.\n */\ntypedef struct _RMInfo {\n\tlong  edi;\n\tlong  esi;\n\tlong  ebp;\n\tlong  reservedbysystem;\n\tlong  ebx;\n\tlong  edx;\n\tlong  ecx;\n\tlong  eax;\n\tshort flags;\n\tshort es,ds,fs,gs,ip,cs,sp,ss;\n} RMInfo;\n\n#endif /* VQMREALMODE_H */\n\n"
  },
  {
    "path": "VQ/VQM32/SORTPAL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     sortpal.c\n*\n* DESCRIPTION\n*     Palette sorting routines. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*     Bill Randolph\n*\n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     SortPalette    - Sort a palette.\n*     Comp_Luminance - Compare the luminace of two 24-bit palette entries.\n*     Comp_HSV       - Compare the HSV of two 24-bit palette entries.\n*     RGB_To_HSV     - Convert RGB color to HSV color.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include \"palette.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n/* HSV color model */\n#define DIVIDE_WITH_ROUND(n,d) (unsigned short)(((n)/(d))+ \\\n\t\t(unsigned short)(((n)%(d)) >= (((d)+1)>>1)))\n\n#define HSV_BASE          255\n#define HUE_WEIGHT        10L\n#define SATURATION_WEIGHT 100L\n#define VALUE_WEIGHT      1000L\n\n/* Prototypes */\nstatic int Comp_Luminance(const void *elem1, const void *elem2);\nstatic int Comp_HSV(const void *elem1, const void *elem2);\nstatic void RGB_To_HSV(unsigned short r, unsigned short g, unsigned short b, \n\t\tunsigned short *h, unsigned short *s, unsigned short *v);\n\n\n/****************************************************************************\n*\n* NAME\n*     SortPalette - Sort a palette.\n*\n* SYNOPSIS\n*     SortPalette(Palette, NumColors)\n*\n*     void SortPalette(unsigned char *, long);\n*\n* FUNCTION\n*     Sort the palette colors.\n*\n* INPUTS\n*     Palette   - Pointer to palette to sort.\n*     NumColors - Number of colors in the palette.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid SortPalette(unsigned char *pal, long numcolors)\n{\n\tqsort(pal, numcolors, 3, Comp_Luminance);\n\n\tpal[0] = 0;\n\tpal[1] = 0;\n\tpal[2] = 0;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Comp_Luminance - Compare the luminace of two 24-bit palette entries.\n*\n* SYNOPSIS\n*     Result = Comp_Luminance(Color1, Color2)\n*\n*     long Comp_Luminance(void *, void *);\n*\n* FUNCTION\n*     Compare the luminace of the two colors and determine which color is\n*     brighter than the other.\n*\n*     The computation used is:\n*       Luminance = (red * .299) + (green * .587) + (blue * .114)\n*\n* INPUTS\n*     Color1 - Pointer to palette entry.\n*     Color2 - Pointer to palette entry.\n*\n* RESULT\n*     Result - 0 = same, 1 = Color1 > Color2, -1 = Color1 < Color2\n*\n****************************************************************************/\n\nstatic int Comp_Luminance(const void *elem1, const void *elem2)\n{\n\tunsigned char *pal;\n\tlong          r,g,b;\n\tlong          total1,total2;\n\n\t/* Compute luminance for color1 */\n\tpal = (unsigned char *)elem1;\n\tr = ((long)pal[0]);\n\tg = ((long)pal[1]);\n\tb = ((long)pal[2]);\n\ttotal1 = ((r * 19595L) + (g * 38470L) + (b * 7471L));\n\n\t/* Compute luminance for color2 */\n\tpal = (unsigned char *)elem2;\n\tr = ((long)pal[0]);\n\tg = ((long)pal[1]);\n\tb = ((long)pal[2]);\n\ttotal2 = ((r * 19595L) + (g * 38470L) + (b * 7471L));\n\n\tif (total1 < total2) {\n\t\treturn (-1);\n\t} else if (total1 > total2) {\n\t\treturn (1);\n\t} else {\n\t\treturn (0);\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Comp_HSV - Compare the HSV of two 24-bit palette entries.\n*\n* SYNOPSIS\n*     Result = Comp_HSV(Color1, Color2)\n*\n*     long Comp_HSV(void *, void *);\n*\n* FUNCTION\n*     Compare the HSV color values of two colors and determine the\n*     relationship between the colors in the color space.\n*\n* INPUTS\n*     Color1 - Pointer to 1st palette entry.\n*     Color2 - Pointer to 2nd palette entry.\n*\n* RESULT\n*     Result - 0 = same, 1 = Color1 > Color2, -1 = Color1 < Color2\n*\n****************************************************************************/\n\nstatic int Comp_HSV(const void *elem1, const void *elem2)\n{\n\tunsigned char  *pal;\n\tunsigned char  r,g,b;\n\tunsigned short h,s,v;\n\tunsigned long  key1,key2;\n\tlong           retval;\n\n\t/* Convert 1st element to HSV */\n\tpal = (unsigned char *)elem1;\n\tr = pal[0];\n\tg = pal[1];\n\tb = pal[2];\n\n\tRGB_To_HSV((unsigned short)r,(unsigned short)g,(unsigned short)b,&h,&s,&v);\n\tkey1 = ((h * HUE_WEIGHT) + (s * SATURATION_WEIGHT) + (v * VALUE_WEIGHT));\n\n\t/* Convert 2nd element to HSV */\n\tpal = (unsigned char *)elem2;\n\tr = pal[0];\n\tg = pal[1];\n\tb = pal[2];\n\n\tRGB_To_HSV((unsigned short)r,(unsigned short)g,(unsigned short)b,&h,&s,&v);\n\tkey2 = ((h * HUE_WEIGHT) + (s * SATURATION_WEIGHT) + (v * VALUE_WEIGHT));\n\n\tif (key1 != key2) {\n\t\tretval = ((key1 < key2) ? -1 : 1);\n\t} else {\n\t\tretval = 0;\n\t}\n\n\treturn (retval);\n}\n\n\n/***************************************************************************\n*\n* NAME\n*     RGB_To_HSV - Convert RGB color to HSV color.\n*\n* SYNOPSIS\n*     RGB_To_HSV(R, G, B, H, S, V)\n*\n*     void RGB_To_HSV(unsigned short, unsigned short, unsigned short,\n*                     unsigned short *, unsigned short *, unsigned short *);\n*\n* FUNCTION\n*     Convert the RBG color to a HSV color. Assumes 8 bits per gun of R, G\n*     and B data. Also the HSV is based on a 255 degree scale rather than\n*     the more accurate 360 degree scale.\n*\n* INPUTS\n*     R - Red gun value.\n*     G - Green gun value.\n*     B - Blue gun value.\n*     H - Pointer to H value. (H will be set upon return of this function)\n*     S - Pointer to S value. (S will be set upon return of this function)\n*     V - Pointer to V value. (V will be set upon return of this function)\n*\n* RESULT\n*     NONE\n*\n***************************************************************************/\n\nstatic void RGB_To_HSV(unsigned short r, unsigned short g, unsigned short b, \n\t\tunsigned short *h, unsigned short *s, unsigned short *v)\n{\n \tunsigned short m;\n\tunsigned short r1;\n\tunsigned short g1;\n\tunsigned short b1;\n\tunsigned short tmp;\n\n\t/* Set hue to default. */\n\t*h = 0;\n\n\t/* Set v = Max(r,g,b) to find dominant primary color. */\n\t*v = ((r > g) ? r : g);\n\n\tif (b > *v) {\n\t\t*v = b;\n\t}\n\n\t/* Set m = min(r,g,b) to find amount of white. */\n\tm = ((r < g) ? r : g);\n\n\tif (b < m) {\n\t\tm = b;\n\t}\n\n\t/* Determine the normalized saturation. */\n\tif (*v != 0) {\n\t\t*s = DIVIDE_WITH_ROUND((*v - m) * HSV_BASE, *v);\n\t} else {\n\t\t*s = 0;\n\t}\n\n\tif (*s != 0) {\n\t\ttmp = *v - m;\n\t \tr1 = DIVIDE_WITH_ROUND((*v - r) * HSV_BASE, tmp);\n\t \tg1 = DIVIDE_WITH_ROUND((*v - g) * HSV_BASE, tmp);\n\t \tb1 = DIVIDE_WITH_ROUND((*v - b) * HSV_BASE, tmp);\n\n\t\t/* Find effect of second most predominant color.\n\t\t * In which section of the hexagon of colors does the color lie?\n\t\t */\n\t\tif ((*v) == r) {\n\t\t \tif (m == g) {\n\t\t\t\t*h = 5 * HSV_BASE + b1;\n\t\t\t} else {\n\t\t\t\t*h = 1 * HSV_BASE - g1;\n\t\t\t}\n\t\t} else {\n\t\t\tif ((*v) == g) {\n\t\t\t \tif (m == b) {\n\t\t\t\t\t*h = 1 * HSV_BASE + r1;\n\t\t\t\t} else {\n\t\t\t\t\t*h = 3 * HSV_BASE - b1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t \tif (m == r) {\n\t\t\t\t\t*h = 3 * HSV_BASE + g1;\n\t\t\t\t} else {\n\t\t\t\t\t*h = 5 * HSV_BASE - r1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Divide by six and round. */\n\t\t*h = DIVIDE_WITH_ROUND(*h, 6);\n\t}\n}\n"
  },
  {
    "path": "VQ/VQM32/SOSCODEC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*          Copyright (c) 1994, HMI, INC. All Rights Reserved\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     soscodec.asm\n;*\n;* DESCRIPTION\n;*     HMI SOS ADPCM compression/decompression.\n;*\n;* PROGRAMMER\n;*     Nick Skrepetos\n;*     Denzil E. Long, Jr. (Fixed bugs, rewrote for watcom)\n;*\t   Bill Petro\t\t   (Added stereo support)\n;* DATE\n;*     Febuary 15, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\n\tSTRUC\tsCompInfo\nlpSource\tDD\t?\t;Compressed data pointer\nlpDest\tDD\t?\t;Uncompressed data pointer\ndwCompSize\tDD\t?\t;Compressed size\ndwUnCompSize\tDD\t?\t;Uncompressed size\nwBitSize\tDW\t?\t;Bit size for decompression\nwChannels\tDW\t?\t;number of channels\n\ndwSampleIndex\tDD\t?\t;Index into sample\ndwPredicted\tDD\t?\t;Next predicted value\ndwDifference\tDD\t?\t;Difference from last sample\nwCodeBuf\tDW\t?\t;Holds 2 nibbles for decompression\nwCode\tDW\t?\t;Current 4 bit code\nwStep\tDW\t?\t;Step value in table\nwIndex\tDW\t?\t;Index into step table\n\ndwSampleIndex2\tDD\t?\t;Index into sample\ndwPredicted2\tDD\t?\t;Next predicted value\ndwDifference2\tDD\t?\t;Difference from last sample\nwCodeBuf2 \tDW\t?\t;Holds 2 nibbles for decompression\nwCode2\tDW\t?\t;Current 4 bit code\nwStep2\tDW\t?\t;Step value in table\nwIndex2\tDW\t?\t;Index into step table\n\tENDS\tsCompInfo\n\n\tDATASEG\n\n;* Index table for stepping into step table\n\nwCODECIndexTab\tDW\t-1,-1,-1,-1,2,4,6,8\n\t\tDW\t-1,-1,-1,-1,2,4,6,8\n\n\n;Lookup table of replacement values\n;The actual sound value is replaced with an index to lookup in this table\n;The index only takes up a nibble(4bits) and represents an int(16bits)\n;Essentially: \n;Get a value\n;compare it with the value before it\n;find closest value in table and store the index into the table\n;if i'm going down then negitize it\n;go to next byte.\n\n;Theory for stereo:\n;1)handle stereo and mono in two seperate loops. cleaner...\n;start at byte 0 and skip every other byte(or word) both write and read\n;when we get done set start byte to 1 and do it again \n\n\n;This table essentialy round off to closes values in 3 distinct bands\n; precalculated and optimized(i guess) for human hearing.\n\nwCODECStepTab\tDW\t7,8,9,10,11,12,13,14   \t\t\n\tDW\t16,17,19,21,23,25,28,31\t\t\t\n\tDW\t34,37,41,45,50,55,60,66\t\t\t\n\tDW\t73,80,88,97,107,118,130,143\t\t\t\n\tDW\t157,173,190,209,230,253,279,307\t\t\t\n\tDW\t337,371,408,449,494,544,598,658\t\t\t\n\tDW\t724,796,876,963,1060,1166,1282,1411\t\t\t\n\tDW\t1552,1707,1878,2066,2272,2499,2749,3024\t\t\t\n\tDW\t3327,3660,4026,4428,4871,5358,5894,6484\n\tDW\t7132,7845,8630,9493,10442,11487,12635,13899\t\t\n\tDW\t15289,16818,18500,20350,22385,24623,27086,29794 \n\tDW\t32767\t\t\t\n\ndwCODECByteIndex\t\tDD\t0 ; this is when to stop compressing\ndwCODECBytesProcessed\t\tDD\t0 ; this is how many so far compressed\ndwCODECTempStep\t\tDD\t0 ; tempory storage for step value\nwCODECMask\t\t\tDW\t0 ; Current mask\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECInitStream - Initialize compression stream.\n;*\n;* SYNOPSIS\n;*     sosCODECInitStream(CompInfo)\n;*\n;*     void sosCODECInitStream(_SOS_COMPRESS_INFO *);\n;*\n;* FUNCTION\n;*     Initialize compression stream for compression and decompression.\n;*\n;* INPUTS\n;*     CompInfo - Compression information structure.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC sosCODECInitStream:NEAR\n\tPROC\tsosCODECInitStream C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\n\tmov\teax,[sSOSInfo]\n\tmov\t[(sCompInfo eax).wIndex],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).wStep],7  \t\t; start with a step of 7\n\tmov\t[(sCompInfo eax).dwPredicted],0 \t; no predicted value\n\tmov\t[(sCompInfo eax).dwSampleIndex],0\t;start at head of index\n\tmov\t[(sCompInfo eax).wIndex2],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).wStep2],7  \t\t; start with a step of 7\n\tmov\t[(sCompInfo eax).dwPredicted2],0 \t; no predicted value\n\tmov\t[(sCompInfo eax).dwSampleIndex2],0 \t;start at head of index\n\tret\n\n\tENDP\tsosCODECInitStream\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECCompressData - Compress audio data.\n;*\n;* SYNOPSIS\n;*     Size = sosCODECCompressData(CompInfo, NumBytes)\n;*\n;*     long sosCODECCompressData(_SOS_COMPRESS_INFO *, long);\n;*\n;* FUNCTION\n;*     Compress an audio data stream into 4:1 ADPCM. 16 bit data is\n;*     compressed 4:1, 8 bit data is compressed 2:1.\n;*\n;* INPUTS\n;*     CompInfo - Pointer to initialized compress information structure.\n;*     NumBytes - Number of bytes to compress.\n;*\n;* RESULT\n;*     Size - Size of compressed data.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC sosCODECCompressData:NEAR\n\tPROC\tsosCODECCompressData C NEAR\n\tARG\tsSOSInfo:NEAR PTR\n\tARG\twBytes:DWORD\n\n\tpush\tesi\n\tpush\tedi\n\tpush\tebx\n\tpush\tecx\n\tpush\tedx\n\n;*---------------------------------------------------------------------------\n;*\tInitialize\n;*---------------------------------------------------------------------------\n\n\tmov\tebx,[sSOSInfo]\n\tmov\teax,[wBytes]\n\tmov\t[dwCODECBytesProcessed],eax\t\t\n\tmov\t[(sCompInfo ebx).dwSampleIndex],0 \t;start at head of index\n\tmov\t[(sCompInfo ebx).dwSampleIndex2],0\t;start at head of index\n\n;\tCheck for 16 bit decompression\n\n\tcmp\t[(sCompInfo ebx).wBitSize],16\t\t;16 bit requested?\n\tjne\tshort ??skipByteDivide\t\t\t;no so skip divide\n\tshr\teax,1\t\t\t\t\t;divide size by 2\n\n??skipByteDivide:\n\tmov\t[dwCODECByteIndex],eax\n\tmov\tesi,[(sCompInfo ebx).lpSource]\t;ESI = source\n\tmov\tedi,[(sCompInfo ebx).lpDest]\t\t;EDI = dest\n\n\tcmp\t[(sCompInfo ebx).wChannels],2\t\t;stereo check\n\tje\t??mainloopl\n\n;------------------------------------------------------------------------\n; Mono start\n;------------------------------------------------------------------------\n\t\n??mainloop:\n\tcmp\t[(sCompInfo ebx).wBitSize],16  \t;are we doing 16 bit\n\tjne\tshort ??input8Bit\t       \t\t;no. goto 8 bit input\t\n\n\tmovsx\teax,[word ptr esi]\t       \t\t;Get 16bit sample\n\tadd\tesi,2\n\tjmp\tshort ??computeDiff\t\t\t\t;skip 8 bit load\n\n??input8Bit:\n\tmov\tah,[esi]\t\t\t\t\t;Get 8bit sample\n\tinc\tesi\n\txor\tal,al\t\t\t\t\t;zero out low byte\n\txor\tah,80h\t\t\t\t\t;flip sign bit\n\tmovsx\teax,ax\n\n??computeDiff:\n\tmovsx\tecx,[word ptr (sCompInfo ebx).dwPredicted] \n\tsub\teax,ecx\t\t\t\t\t;sample-predicted\n\txor\tecx,ecx\t\t\t\t\t;clear ecx\n\tcmp\teax,0\t\t\t\t\t;Diff > = 0\n\tjge\t??positive\n\n\tneg\teax\t\t\t\t\t;else difference= -difference\n\tor\tecx,8\t\t\t\t\t;set nibble sign bit in ecx\n\n??positive:\n\tmov\t[(sCompInfo ebx).wCode],cx\t\t;Store code\n\tmovsx\tecx,[(sCompInfo ebx).wStep]   \t;Get step value\n\tmov\t[dwCODECTempStep],ecx\n\tmov\tedx,4\t\t\t\t\t;mask value (i think)\t\n\tmov\tecx,3\t\t\t\t\t;loop count\n\n??quantizeLoop:\n\tcmp\teax,[dwCODECTempStep]\t  \t\t;Diff < step ?\n\tjl\tshort ??nextQLoop\t\t\t\t;goto nextQloop\n\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\n\t; OR in mask value into code and adjust difference.\t\t   \t\n\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\n\tor\t[(sCompInfo ebx).wCode],dx\t\t;else or mask into code\n\tsub\teax,[dwCODECTempStep]\t\t\t;difference-=tempstep\n\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\n??nextQLoop:\n\tshr\t[dwCODECTempStep],1\t\t\t\t; TempStep>>=1\t\t   \t\t\t\n\tshr\tedx,1\t\t\t\t\t; mask>>=1\t\t   \t\t\t\t\n\tloop\t??quantizeLoop\t\t\t\t\t; back to quatize loop  \t\t\n\n;-----------------------------------------------------------------------------------------\n; now i'v got the new diff and code is masked right\n;-----------------------------------------------------------------------------------------\n\n\t; store off new difference value\n\n\tmov\t[(sCompInfo ebx).dwDifference],eax\n\n\t; determine if sample index is even or odd.\n\t; this will determine if we need to get a new token or not.\n\n\ttest\t[(sCompInfo ebx).dwSampleIndex],1 \t; is it even? (starts at 0)\n\tjne\tshort ??storeToken\t\t\t; if so goto store token\n\n\t; else its odd so get token \n\n\txor\teax,eax\t\t\t\t\n\tmov\tax,[(sCompInfo ebx).wCode]\t\t;ax=wCode\n\tand\teax,0Fh\t\t\t\t\t;and off high nibble\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\t\t;wCodeBuf=ax\n\tjmp\tshort ??calcDifference\t\t\t;goto calcDifference\n\n??storeToken:\n\t; fetch new token\n\n\txor\teax,eax\t\t\t\t\n\tmov\tax,[(sCompInfo ebx).wCode]\t\t;ax=code\n\tshl\teax,4\t\t\t\t\t;shift low nibble to high\n\tor\tax,[(sCompInfo ebx).wCodeBuf]\t\t;or in the stored nibble\n\tmov\t[edi],al\t\t\t\t;*dest=al\n\tinc\tedi\t\t\t\t\t;dest++\n\n??calcDifference:\n\tmov\t[(sCompInfo ebx).dwDifference],0\t;dwDifference=0\n\txor\tecx,ecx\t\t\t\t\t;ecx=0\n\tmov\tcx,[(sCompInfo ebx).wStep]\t\t;cx=Step\n\txor\teax,eax\t\t\t\t\t;eax=0\n\tmov\tax,[(sCompInfo ebx).wCode]\t\t;ax=wCode\n\ttest\teax,4\t\t\t\t\t;Check 0100\n\tje\tshort ??no4\n\tadd\t[(sCompInfo ebx).dwDifference],ecx  \t;difference+=step\n\n??no4:\n\ttest\teax,2\t\t\t\t\t;Check 0010\n\tje\tshort ??no2\n\tmov\tedx,ecx\t\t\t\t\t;edx=wStep\n\tshr\tedx,1\t\t\t\t\t;edx>>1\n\tadd\t[(sCompInfo ebx).dwDifference],edx \t;Difference=wstep>>1\n\n??no2:\n\ttest\teax,1\t\t\t\t\t;Check 0001\n\tje\tshort ??no1\n\tmov\tedx,ecx\t\t\t\t\t;edx=wStep\n\tshr\tedx,2\t\t\t\t\t;edx>>2\n\tadd\t[(sCompInfo ebx).dwDifference],edx \t;Difference=wstep>>2\n\n??no1:\n\tmov\tedx,ecx\t\t\t\t\t\n\tshr\tedx,3\t\t\t\t\t\n\tadd\t[(sCompInfo ebx).dwDifference],edx\t;Difference=wstep>>3\n\ttest\teax,8\t\t\t\t\t;Check 1000\n\tje\tshort ??no8\n\tneg\t[(sCompInfo ebx).dwDifference]\t\t;Negate diff because sign bit was set \n\n??no8:\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\n\tadd\teax,[(sCompInfo ebx).dwDifference]\t;eax=Preditcted+Difference\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflow\n\tmov\teax,7FFFh\t\t\t\t;if overflow store 7fff in diff\n\n??noOverflow:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflow\n\tmov\teax,0FFFF8000h\t\t\t\t;if overflow  0FFFF8000 in diff\n\n??noUnderflow:\n\tmov\t[(sCompInfo ebx).dwPredicted],eax \t;store into predicted\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode]\t\t;cx=Code\n\txor\teax,eax\n\tshl\tecx,1\t\t\t\t\t;cx<<1\n\tmov\tax,[wCODECIndexTab + ecx]\t\t;ax=Indextab[ecx]\n\tadd\t[(sCompInfo ebx).wIndex],ax   \t\t;wIndex+=ax\n\tcmp\t[(sCompInfo ebx).wIndex],8000h\t\t; check if wIndex < 0\n\tjb\tshort ??checkOverflow\n\tmov\t[(sCompInfo ebx).wIndex],0\t\t; reset index to zero\n\tjmp\tshort ??adjustStep\n\n??checkOverflow:\n\tcmp\t[(sCompInfo ebx).wIndex],88\t\t; check if wIndex > 88\n\tjbe\tshort ??adjustStep\n\tmov\t[(sCompInfo ebx).wIndex],88\t\t; reset index to 88\n\n\n??adjustStep:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex],1\n\tmov\t[(sCompInfo ebx).wStep],ax\n\n\t; decrement bytes processed and loop back.\n\n\tdec\t[dwCODECByteIndex]\n\tjne\t??mainloop\t\t    \t\t; }while !0\n\n\tjmp\t??exitout\n;-----------------------------------------------------------------------\n;Stereo\tLeft Side\n;-----------------------------------------------------------------------\n\n??mainloopl:\n; determine bit size for input\t\t\t\t;do{\n\n\tcmp\t[(sCompInfo ebx).wBitSize],16  \t\t;are we doing 16 bit\n\tjne\tshort ??input8Bitl\t       \t\t;no. goto 8 bit input\t\t**\n\n\tmovsx\teax,[word ptr esi]\t       \t\t;load next word from source\n\tadd\tesi,4\t\t\t\t\t;inc source by 2 words  \t\t**\n\tjmp\tshort ??computeDiffl\t\t\t;skip 8 bit load\t\t\t**\n\n??input8Bitl:\n\tmov\tah,[esi]\t\t\t\t;Get 8 bit sample\n\tadd\tesi,2   \t\t\t\t;inc source by 2 bytes\t\t**\n\txor\tal,al\t\t\t\t\t;zero out low byte\n\txor\tah,80h\t\t\t\t\t;flip sign bit\n\tmovsx\teax,ax\t\t\t\t\t;sign extend into eax\n\n??computeDiffl:\n\t; compute difference\n\n\tmovsx\tecx,[word ptr (sCompInfo ebx).dwPredicted] \n\t\t\t\t\t\t\t;load predicted (starts at 0)\n\tsub\teax,ecx\t\t\t\t\t;difference=sample-preditcted\n\n\t; check if dwDifference > 0.  ECX is the\n\t; sign bit, it is initialized to positive.\n\n\txor\tecx,ecx\t\t\t\t       \t;clear ecx\n\tcmp\teax,0\t\t\t\t\t;if(difference>=0)\n\tjge\tshort ??positivel\t\t\t;goto positive\n\n\tneg\teax\t\t\t\t\t;else difference= -difference\n\tor\tecx,8\t\t\t\t\t;set nibble sign bit in ecx\n\n??positivel:\n\tmov\t[(sCompInfo ebx).wCode],cx\t\t;Store code from cx into struct\n\n\t; set up to quantize difference. initialize \n\t; wCODECTempStep = step value.\n\n\tmovsx\tecx,[(sCompInfo ebx).wStep]   \t\t;ecx=step value(starts at 7)\n\tmov\t[dwCODECTempStep],ecx\t\t\t;tempstep=step\n\tmov\tedx,4\t\t\t\t\t;edx=4   mask value (i think)\t\n\tmov\tecx,3\t\t\t\t\t;ecx is loop number so loop 3 times \n\n??quantizeLoopl:\n\t; check to see if difference > tempstep value.\t\t\t    \n\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\n\tcmp\teax,[dwCODECTempStep]\t  \t\t;if(difference < tempstep)\t\n\tjl\tshort ??nextQLoopl\t\t\t;goto nextQloop\t   \t\t\n\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\n\t; OR in mask value into code and adjust difference.\t\t   \t\n\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\n\tor\t[(sCompInfo ebx).wCode],dx\t\t;else or mask into code \t   \t\n\tsub\teax,[dwCODECTempStep]\t\t\t;difference-=tempstep\t   \t\n\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\n??nextQLoopl:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t; shift down tempstep and mask\t\t\t\t\t   \t\t\n\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\n\tshr\t[dwCODECTempStep],1\t\t\t; TempStep>>=1\t\t   \t\t\t\n\tshr\tedx,1\t\t\t\t\t; mask>>=1\t\t   \t\t\t\t\n\tloop\t??quantizeLoopl\t\t\t\t; back to quatize loop  \t\t\n;------------------------------------------------------------------------------------------\n; now i'v got the new diff and code is masked right\n\n\t; store off new difference value\n\n\tmov\t[(sCompInfo ebx).dwDifference],eax\n\n\t; determine if sample index is even or odd.\n\t; this will determine if we need to get a new token or not.\n\n\ttest\t[(sCompInfo ebx).dwSampleIndex],1 \t; is it even? (starts at 0)\n\tjne\tshort ??storeTokenl\t\t\t; if so goto store token\t\t**\n\n\t; else its odd so get token \n\n\txor\teax,eax\t\t\t\t\n\tmov\tax,[(sCompInfo ebx).wCode]\t\t;ax=wCode\n\tand\teax,0Fh\t\t\t\t\t;and off high nibble\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\t\t;wCodeBuf=ax\n\tjmp\tshort ??calcDifferencel\t\t\t;goto calcDifference\t\t**\n\n??storeTokenl:\n\t; fetch new token\n\n\txor\teax,eax\t\t\t\t\n\tmov\tax,[(sCompInfo ebx).wCode]\t\t;ax=code\n\tshl\teax,4\t\t\t\t\t;shift low nibble to hign nibble\n\tor\tax,[(sCompInfo ebx).wCodeBuf]\t\t;or in the stored nibble\n\tmov\t[edi],al\t\t\t\t;*dest=al\n\tadd\tedi,2\t\t\t\t\t;dest+=2\t\t\t\t\t**\n\n??calcDifferencel:\n\tmov\t[(sCompInfo ebx).dwDifference],0;dwDifference=0\n\txor\tecx,ecx\t\t\t\t\t;ecx=0\n\tmov\tcx,[(sCompInfo ebx).wStep]\t\t;cx=Step\n\txor\teax,eax\t\t\t\t\t;eax=0\n\tmov\tax,[(sCompInfo ebx).wCode]\t\t;ax=wCode\n\ttest\teax,4\t\t\t\t\t;Check 0100\n\tje\tshort ??no4l\t\t\t\t;\t\t\t\t\t\t**\n\tadd\t[(sCompInfo ebx).dwDifference],ecx  \t;difference+=step\n\n??no4l:\n\ttest\teax,2\t\t\t\t\t;Check 0010\n\tje\tshort ??no2l\t\t\t\t;\t\t\t\t\t\t**\t\n\tmov\tedx,ecx\t\t\t\t\t;edx=wStep\n\tshr\tedx,1\t\t\t\t\t;edx>>1\n\tadd\t[(sCompInfo ebx).dwDifference],edx \t;Difference=wstep>>1\n\n??no2l:\n\ttest\teax,1\t\t\t\t\t;Check 0001\n\tje\tshort ??no1l\t\t\t\t;\t\t\t\t\t\t**\n\tmov\tedx,ecx\t\t\t\t\t;edx=wStep\n\tshr\tedx,2\t\t\t\t\t;edx>>2\n\tadd\t[(sCompInfo ebx).dwDifference],edx \t;Difference=wstep>>2\n\n??no1l:\n\tmov\tedx,ecx\t\t\t\t\t\n\tshr\tedx,3\t\t\t\t\t\n\tadd\t[(sCompInfo ebx).dwDifference],edx\t;Difference=wstep>>3\n\ttest\teax,8\t\t\t\t\t;Check 1000\n\tje\tshort ??no8l\t\t\t\t\t\t\t\t\t\t\n\n\t;Negate diff because sign bit was set \n\n\tneg\t[(sCompInfo ebx).dwDifference]\t\n\n??no8l:\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\n\tadd\teax,[(sCompInfo ebx).dwDifference]\t;eax=Preditcted+Difference\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowl\t\t\t\t\t\t\t\t\t\n\tmov\teax,7FFFh\t\t\t\t;if overflow store 7fff in diff\n\n??noOverflowl:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowl\t\t\t\t\t\t\t\t\t\n\tmov\teax,0FFFF8000h\t\t\t\t;if overflow  0FFFF8000 in diff\n\n??noUnderflowl:\n\tmov\t[(sCompInfo ebx).dwPredicted],eax \t;store into predicted\n\txor\tecx,ecx\t\t\t\t\t;adjust index\n\tmov\tcx,[(sCompInfo ebx).wCode]\t\t;cx=Code\n\txor\teax,eax\t\t\t\t\t\t\n\tshl\tecx,1\t\t\t\t\t;cx<<1\n\tmov\tax,[wCODECIndexTab + ecx]\t\t;ax=Indextab[ecx]\n\tadd\t[(sCompInfo ebx).wIndex],ax   \t\t;wIndex+=ax\n\n\n\tcmp\t[(sCompInfo ebx).wIndex],8000h\t\t;check if wIndex < 0\n\tjb\tshort ??checkOverflowl\t\t\t;\t\t\t\t\t\t\t\t**\n\tmov\t[(sCompInfo ebx).wIndex],0\t\t; reset index to zero\n\tjmp\tshort ??adjustStepl\t\t\t;\t\t\t\t\t\t\t**\n\n??checkOverflowl:\n\t; check if wIndex > 88\n\n\tcmp\t[(sCompInfo ebx).wIndex],88\n\tjbe\tshort ??adjustStepl\t\t\t;\t\t\t\t\t\t\t**\n\n\t; reset index to 88\n\n\tmov\t[(sCompInfo ebx).wIndex],88\n\n??adjustStepl:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex],1\n\tmov\t[(sCompInfo ebx).wStep],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2    ; sub 2 for stereo\t\t\t\t\t**\t\n\tjne\t??mainloopl\t\t    ; }while !0\t\t\t\t\t\t**\n\n;-------------------------------------------------------------------------\n;Right channel re-set up varibles\n;-------------------------------------------------------------------------\t\n\t\n\tmov\teax,[wBytes]\n\tmov\tesi,[(sCompInfo ebx).lpSource] \t\t; point to source buffer\n\tmov\tedi,[(sCompInfo ebx).lpDest]   \t\t; point to destination buffer\n\tinc esi\t\t\t\t\t\t; skip first byte\n\tinc edi\t\t\t\t\t\t; ship first byte\n\n;\tCheck for 16 bit compression\n\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tje\tshort ??do16bit\n\tmov\t[dwCODECByteIndex],eax\n\tjmp\tshort ??mainloopr\n\n??do16bit:\n\tshr\teax,1\t\t\t\t\t;16 bit so half as many bytes\n\tinc\tesi\t\t\t\t\t;16 bit so 1 more byte to skip\n\tmov\t[dwCODECByteIndex],eax\n\n\n;-----------------------------------------------------------------------\n;Start of Stereo Right Side\n;-----------------------------------------------------------------------\n\n??mainloopr:\n; determine bit size for input\t\t\t\t;do{\n\n\tcmp\t[(sCompInfo ebx).wBitSize],16  \t\t;are we doing 16 bit\n\tjne\tshort ??input8Bitr\t       \t\t;no. goto 8 bit input\t\t**\n\n\tmovsx\teax,[word ptr esi]\t       \t\t;load next word from source\n\tadd\tesi,4\t\t\t\t\t;inc source by 2 words  \t\t**\n\tjmp\tshort ??computeDiffr\t\t\t;skip 8 bit load\t\t\t**\n\n??input8Bitr:\n\tmov\tah,[esi]\t\t\t\t;Get 8 bit sample\n\tadd\tesi,2   \t\t\t\t;inc source by 2 bytes\t\t**\n\txor\tal,al\t\t\t\t\t;zero out low byte\n\txor\tah,80h\t\t\t\t\t;flip sign bit\n\tmovsx eax,ax\t\t\t\t\t;sign extend into eax\n\n??computeDiffr:\n\t; compute difference\n\n\tmovsx ecx,[word ptr (sCompInfo ebx).dwPredicted2] \n\t\t\t\t\t\t\t;load predicted (starts at 0)\n\tsub\teax,ecx\t\t\t\t\t;difference=sample-preditcted\n\n\t; check if dwDifference > 0.  ECX is the\n\t; sign bit, it is initialized to positive.\n\n\txor\tecx,ecx\t\t\t\t\t;clear ecx\n\tcmp\teax,0\t\t\t\t\t;if(difference>=0)\n\tjge\tshort ??positiver \t\t\t;goto positive\n\n\tneg\teax\t\t\t\t\t;else difference= -difference\n\tor\tecx,8\t\t\t\t\t;set nibble sign bit in ecx\n\n??positiver:\n\tmov\t[(sCompInfo ebx).wCode2],cx\t\t;Store code from cx into struct\n\n\t; set up to quantize difference. initialize \n\t; wCODECTempStep = step value.\n\n\tmovsx\tecx,[(sCompInfo ebx).wStep2]   \t\t;ecx=step value(starts at 7)\n\tmov\t[dwCODECTempStep],ecx\t\t\t;tempstep=step\n\tmov\tedx,4\t\t\t\t\t;edx=4   mask value (i think)\t\n\tmov\tecx,3\t\t\t\t\t;ecx is loop number so loop 3 times \n\n??quantizeLoopr:\n\t; check to see if difference > tempstep value.\t\t\t    \n\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\n\tcmp\teax,[dwCODECTempStep]\t  \t\t;if(difference < tempstep)\t\n\tjl\tshort ??nextQLoopr\t\t\t;goto nextQloop\t   \t\t\n\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\n\t; OR in mask value into code and adjust difference.\t\t   \t\n\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\n\tor\t[(sCompInfo ebx).wCode2],dx\t\t;else or mask into code \t   \t\n\tsub\teax,[dwCODECTempStep]\t\t\t;difference-=tempstep\t   \t\n\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\n??nextQLoopr:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t; shift down tempstep and mask\t\t\t\t\t   \t\t\n\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\n\tshr\t[dwCODECTempStep],1\t\t\t; TempStep>>=1\t\t   \t\t\t\n\tshr\tedx,1\t\t\t\t\t; mask>>=1\t\t   \t\t\t\t\n\tloop\t??quantizeLoopr\t\t\t\t; back to quatize loop  \t\t\n;------------------------------------------------------------------------------------------\n; now i'v got the new diff and code is masked right\n\n\t; store off new difference value\n\n\tmov\t[(sCompInfo ebx).dwDifference2],eax\n\n\t; determine if sample index is even or odd.\n\t; this will determine if we need to get a new token or not.\n\n\ttest\t[(sCompInfo ebx).dwSampleIndex2],1\t; is it even? (starts at 0)\n\tjne\tshort ??storeTokenr\t\t\t; if so goto store token\t\t**\n\n\t; else its odd so get token \n\n\txor\teax,eax\t\t\t\t\n\tmov\tax,[(sCompInfo ebx).wCode2]\t\t;ax=wCode\n\tand\teax,0Fh\t\t\t\t\t;and off high nibble\n\tmov\t[(sCompInfo ebx).wCodeBuf2],ax\t\t;wCodeBuf=ax\n\tjmp\tshort ??calcDifferencer\t\t\t;goto calcDifference\t\t**\n\n??storeTokenr:\n\txor\teax,eax\t\t\t\t\n\tmov\tax,[(sCompInfo ebx).wCode2]\t\t;ax=code\n\tshl\teax,4\t\t\t\t\t;shift low nibble to hign nibble\n\tor\tax,[(sCompInfo ebx).wCodeBuf2]\t\t;or in the stored nibble\n\tmov\t[edi],al\t\t\t\t;*dest=al\n\tadd\tedi,2\t\t\t\t\t;dest+=2\t\t\t\t\t**\n\n??calcDifferencer:\n\tmov\t[(sCompInfo ebx).dwDifference2],0\t;dwDifference=0\n\txor\tecx,ecx\t\t\t\t\t;ecx=0\n\tmov\tcx,[(sCompInfo ebx).wStep2]\t\t;cx=Step\n\txor\teax,eax\t\t\t\t\t;eax=0\n\tmov\tax,[(sCompInfo ebx).wCode2]\t\t;ax=wCode\n\ttest\teax,4\t\t\t\t\t;Check 0100\n\tje\tshort ??no4r\t\t\t\t\t\t\t\t\t\t\n\tadd\t[(sCompInfo ebx).dwDifference2],ecx  \t;difference+=step\n\n??no4r:\n\ttest\teax,2\t\t\t\t\t;Check 0010\n\tje\tshort ??no2r\t\t\t\t\t\t\t\t\t\t\t\n\tmov\tedx,ecx\t\t\t\t\t;edx=wStep\n\tshr\tedx,1\t\t\t\t\t;edx>>1\n\tadd\t[(sCompInfo ebx).dwDifference2],edx ;Difference=wstep>>1\n\n??no2r:\n\ttest\teax,1\t\t\t\t\t;Check 0001\n\tje\tshort ??no1r\t\t\t\t\t\t\t\t\t\t\n\tmov\tedx,ecx\t\t\t\t\t;edx=wStep\n\tshr\tedx,2\t\t\t\t\t;edx>>2\n\tadd\t[(sCompInfo ebx).dwDifference2],edx \t;Difference=wstep>>2\n\n??no1r:\n\tmov\tedx,ecx\t\t\t\t\t\n\tshr\tedx,3\t\t\t\t\t\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\t;Difference=wstep>>3\n\ttest\teax,8\t\t\t\t\t;Check 1000\n\tje\tshort ??no8r\t\t\t\t\t\t\t\t\t\t\n\tneg\t[(sCompInfo ebx).dwDifference2]\t\n\n??no8r:\n\t; add difference to predicted value.\n\tmov\teax,[(sCompInfo ebx).dwPredicted2]\n\tadd\teax,[(sCompInfo ebx).dwDifference2]\t;eax=Preditcted+Difference\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowr\t\t\t\t\t\t\t\t\t\n\tmov\teax,7FFFh\t\t\t\t;if overflow store 7fff in diff\n\n??noOverflowr:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowr\t\t\t\t\t\t\t\t\t\n\tmov\teax,0FFFF8000h\t\t\t\t;if overflow  0FFFF8000 in diff\n\n??noUnderflowr:\n\tmov\t[(sCompInfo ebx).dwPredicted2],eax \t;store into predicted\n\txor\tecx,ecx\t\t\t\t\t;adjust index \n\tmov\tcx,[(sCompInfo ebx).wCode2]\t\t;cx=Code\n\txor\teax,eax\n\tshl\tecx,1\t\t\t\t\t;cx<<1\n\tmov\tax,[wCODECIndexTab + ecx]\t\t;ax=Indextab[ecx]\n\tadd\t[(sCompInfo ebx).wIndex2],ax   \t\t;wIndex+=ax\n\tcmp\t[(sCompInfo ebx).wIndex2],8000h\t\t;check if wIndex < 0\n\tjb\tshort ??checkOverflowr\t\t\t\t\t\t\t\t\t\n\tmov\t[(sCompInfo ebx).wIndex2],0\t\t;reset index to zero\n\tjmp\tshort ??adjustStepr\t\t\t\t\t\t\t\t\t\t\n\n??checkOverflowr:\n\n\tcmp\t[(sCompInfo ebx).wIndex2],88\t\t;check if wIndex > 88\n\tjbe\tshort ??adjustStepr\t\t\t\t\t\t\t\t\t\t\n\tmov\t[(sCompInfo ebx).wIndex2],88\t\t;reset index to 88\n\n\n??adjustStepr:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex2]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex2],1\n\tmov\t[(sCompInfo ebx).wStep2],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2    \t\t; sub 2 for stereo\t\t\t\t\t\t\n\tjne\t??mainloopr\t\t    \t\t; }while !0\t\t\t\t\t\t\n\n\t\n;-------------------------------------------------------------------------\n;Final clean up\n;-------------------------------------------------------------------------\t\n\t\n??exitout:\n\t; save off ESI and EDI back into compress info structure.\n\n;\tmov\t[(sCompInfo ebx).lpSource],esi\n;\tmov\t[(sCompInfo ebx).lpDest],edi\n\n\t; set up return value for number of bytes processed.\n\n\tmov\teax,[dwCODECBytesProcessed]\n\tshr\teax,1\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\t??leave\n\tshr\teax,1\t\t\t\t\t;if not 16 bit then div/2\n\n??leave:\t\n\tpop\tedx\n\tpop\tecx\n\tpop\tebx\n\tpop\tedi\n\tpop\tesi\n\tret\n\n\tENDP\tsosCODECCompressData\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECDecompressData - Decompress audio data.\n;*\n;* SYNOPSIS\n;*     Size = sosCODECDecompressData(CompInfo, NumBytes)\n;*\n;*     long sosCODECDecompressData(_SOS_COMPRESS_INFO *, long);\n;*\n;* FUNCTION\n;*     Decompress data from a 4:1 ADPCM compressed stream. The number of\n;*     bytes decompressed is returned.\n;*\n;* INPUTS\n;*     CompInfo - Compress information structure.\n;*     NumBytes - Number of bytes to compress.\n;*\n;* RESULT\n;*     Size - Size of decompressed data.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC sosCODECDecompressData:NEAR\n\tPROC\tsosCODECDecompressData C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\tARG\twBytes:DWORD\n\n\tpush\tesi\n\tpush\tedi\t\t\t   \n\tpush\tebx\n\tpush\tecx\n\tpush\tedx\n\n;*---------------------------------------------------------------------------\n;*\tInitialize\n;*---------------------------------------------------------------------------\n\n\tmov\tebx,[sSOSInfo]\n\tmov\teax,[wBytes]\n\tmov\t[dwCODECBytesProcessed],eax\n\tmov\t[(sCompInfo ebx).dwSampleIndex],0 \t;start at head of index\n\tmov\t[(sCompInfo ebx).dwSampleIndex2],0 \t;start at head of index\n\n;*\tCheck for 16 bit decompression\n\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??skipByteDivide\n\tshr\teax,1\n\n??skipByteDivide:\n\tmov\t[dwCODECByteIndex],eax\n\tmov\tesi,[(sCompInfo ebx).lpSource]\n\tmov\tedi,[(sCompInfo ebx).lpDest]\n\tcmp\t[(sCompInfo ebx).wChannels],2\t\t;stereo check\n\tje\t??mainloopl\t\t\t\t;do left side first\t\n\t\n;\tDetermine if sample index is even or odd. This will determine\n;\tif we need to get a new token or not.\n\n;*---------------------------------------------------------------------------\n;*\tMain Mono Loop\n;*---------------------------------------------------------------------------\n\n??mainloop:\t \n\ttest\t[(sCompInfo ebx).dwSampleIndex],1\t;odd ??\n\tje\tshort ??fetchToken\t\t\t\t;if so get new token\n\txor\teax,eax\t\t\t\t\t;else shift int codebuf \n\tmov\tax,[(sCompInfo ebx).wCodeBuf]\t\t;ored with Code\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\tjmp\tshort ??calcDifference\n\n??fetchToken:\n\txor\teax,eax\t\t\t\t\t;get a new token\n\tmov\tal,[esi]\t\t\t\t\t;put in codebuf\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\n\tinc\tesi\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\t\t;and then code\n\n??calcDifference:\n\tmov\t[(sCompInfo ebx).dwDifference],0\t;reset diff\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep]\t\t;cx is step value\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4\n\tadd\t[(sCompInfo ebx).dwDifference],ecx\t;Add wStep\n\n??no4:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no2:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no1:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8\n\tneg\t[(sCompInfo ebx).dwDifference]\t;Negate diff\n\n??no8:\n\t; add difference to predicted value.\n\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\n\tadd\teax,[(sCompInfo ebx).dwDifference]\n\n\t; make sure there is no under or  overflow.\n\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflow\n\tmov\teax,7FFFh\n\n??noOverflow:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflow\n\tmov\teax,0FFFF8000h\n\n??noUnderflow:\n\tmov\t[(sCompInfo ebx).dwPredicted],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bit\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,2\n\tjmp\tshort ??adjustIndex\n\n??output8Bit:\n\t; output 8 bit sample\n\n\txor\tah,80h\n\tmov\t[edi],ah\n\tinc\tedi\n\n??adjustIndex:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex],ax \t\t;check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex],8000h\n\tjb\tshort ??checkOverflow\n\tmov\t[(sCompInfo ebx).wIndex],0\t\t;reset index to zero\n\tjmp\tshort ??adjustStep\n\n??checkOverflow:\n\tcmp\t[(sCompInfo ebx).wIndex],88\t\t;check if wIndex > 88\n\tjbe\tshort ??adjustStep\n\tmov\t[(sCompInfo ebx).wIndex],88\t\t;reset index to 88\n\n??adjustStep:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex],1\n\tmov\t[(sCompInfo ebx).wStep],ax\n\n\t; decrement bytes processed and loop back.\n\n\tdec\t[dwCODECByteIndex]\n\tjne\t??mainloop\n\tjmp\t??exitout\n\n;--------------------------------------------------------------------------\n;Left Channel Start\n;--------------------------------------------------------------------------\n\n\n??mainloopl:\n\ttest\t[(sCompInfo ebx).dwSampleIndex],1\n\tje\tshort ??fetchTokenl\n\t\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCodeBuf]\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\tjmp\tshort ??calcDifferencel\n\n??fetchTokenl:\n\txor\teax,eax\n\tmov\tal,[esi]\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\n\tadd\tesi,2\t\t\t\t\t;2 for stereo\t\t\t\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\n??calcDifferencel:\n\t\t\t\t\t\t\t; reset difference\n\n\tmov\t[(sCompInfo ebx).dwDifference],0\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep]\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4l\n\tadd\t[(sCompInfo ebx).dwDifference],ecx\t;Add wStep\n\n??no4l:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2l\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no2l:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1l\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no1l:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8l\n\tneg\t[(sCompInfo ebx).dwDifference]\t\t;Negate diff\n\n??no8l:\n\t\t; add difference to predicted value.\n\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\n\tadd\teax,[(sCompInfo ebx).dwDifference]\n\n\t\t; make sure there is no under or  overflow.\n\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowl\n\tmov\teax,7FFFh\n\n??noOverflowl:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowl\n\tmov\teax,0FFFF8000h\n\n??noUnderflowl:\n\tmov\t[(sCompInfo ebx).dwPredicted],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bitl\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,4\t\t\t\t\t;4 for stereo\t\t\n\tjmp\tshort ??adjustIndexl\n\n??output8Bitl:\n\t; output 8 bit sample\n\n\txor\tah,80h\n\tmov\t[edi],ah\n\tadd\tedi,2\t\t\t\t\t;2 for stereo       \n\n??adjustIndexl:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex],ax\n\t\t\t\t\t\t\t; check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex],8000h\n\tjb\tshort ??checkOverflowl\n\tmov\t[(sCompInfo ebx).wIndex],0\n\tjmp\tshort ??adjustStepl\t\t\t;reset index to zero\n\n\n??checkOverflowl:\n\t\t\t\t\t\t\t\n\tcmp\t[(sCompInfo ebx).wIndex],88\t\t; check if wIndex > 88\n\tjbe\tshort ??adjustStepl\n\tmov\t[(sCompInfo ebx).wIndex],88\t\t; reset index to 88\n\n??adjustStepl:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex],1\n\tmov\t[(sCompInfo ebx).wStep],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2\n\tjne\t??mainloopl\n;----------------------------------------------------------------------------\n; Right Side Setup\n;----------------------------------------------------------------------------\n\tmov\teax,[wBytes]\n\tmov\t[dwCODECBytesProcessed],eax\n\tmov\tesi,[(sCompInfo ebx).lpSource]\n\tmov\tedi,[(sCompInfo ebx).lpDest]\n\tinc\tesi\t\t\t\t\t; skip left channel\n\tinc\tedi\t\t\t\t     \t; skip left channel\n\tcmp\t[(sCompInfo ebx).wBitSize],16\t\t;16 bit ??\n\tje\tshort ??doByteDivide\t\t\t\n\tmov\t[dwCODECByteIndex],eax\n\tjmp  short ??mainloopr\n\t\n??doByteDivide:\n\tshr\teax,1 \t\t\t\t\t;Divide size by two\n\tinc\tedi   \t\t\t\t\t; 16 bit so skip 1 more\n\tmov\t[dwCODECByteIndex],eax\n\t\n\n;--------------------------------------------------------------------------\n;Right Channel Start\n;--------------------------------------------------------------------------\n\n\n??mainloopr:\t \n\ttest\t[(sCompInfo ebx).dwSampleIndex2],1\n\tje\tshort ??fetchTokenr\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCodeBuf2]\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode2],ax\n\tjmp\tshort ??calcDifferencer\n\n??fetchTokenr:\n\txor\teax,eax\n\tmov\tal,[esi]\n\tmov\t[(sCompInfo ebx).wCodeBuf2],ax\n\tadd\tesi,2\t\t\t\t     \t;2 for stereo\t\t\t\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode2],ax\n\n??calcDifferencer:\n\t\t\t\t\t\t\t; reset difference\n\n\tmov\t[(sCompInfo ebx).dwDifference2],0\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep2]\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4r\n\tadd\t[(sCompInfo ebx).dwDifference2],ecx\t;Add wStep\n\n??no4r:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2r\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\n??no2r:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1r\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\n??no1r:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8r\n\tneg\t[(sCompInfo ebx).dwDifference2]\t\t;Negate diff\n\n??no8r:\n\t; add difference to predicted value.\n\tmov\teax,[(sCompInfo ebx).dwPredicted2]\n\tadd\teax,[(sCompInfo ebx).dwDifference2]\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowr\n\tmov\teax,7FFFh\n\n??noOverflowr:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowr\n\tmov\teax,0FFFF8000h\n\n??noUnderflowr:\n\tmov\t[(sCompInfo ebx).dwPredicted2],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bitr\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,4\t\t\t\t\t;4 for stereo\t\t***\n\tjmp\tshort ??adjustIndexr\n\n??output8Bitr:\n\t\t\t\t\t\t\t; output 8 bit sample\n\txor\tah,80h\n\tmov\t[edi],ah\n\tadd\tedi,2\t\t\t\t\t;2 for stereo       \n\n??adjustIndexr:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode2]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex2],ax\n\t\t\t\t\t\t\t; check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex2],8000h\n\tjb\tshort ??checkOverflowr\n\t\t\t\t\t\t\t; reset index to zero\n\tmov\t[(sCompInfo ebx).wIndex2],0\n\tjmp\tshort ??adjustStepr\n\n??checkOverflowr:\n\t\t\t\t\t\t\t; check if wIndex > 88\n\tcmp\t[(sCompInfo ebx).wIndex2],88\t        \n\tjbe\tshort ??adjustStepr\n\tmov\t[(sCompInfo ebx).wIndex2],88\t\t; reset index to 88\n\n??adjustStepr:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex2]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex2],1\n\tmov\t[(sCompInfo ebx).wStep2],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2\n\tjne\t??mainloopr\n\t\n\n??exitout:\n;\t\tdon't think we need this but just in case i'll leave it here!!\n\n;\tmov\t[(sCompInfo ebx).lpSource],esi\n;\tmov\t[(sCompInfo ebx).lpDest],edi\n\t; set up return value for number of bytes processed.\n\tmov\teax,[dwCODECBytesProcessed]\n\tpop\tedx\n\tpop\tecx\n\tpop\tebx\n\tpop\tedi\n\tpop\tesi\n\tret\n\n\tENDP\tsosCODECDecompressData\n\tEND\n\n\u001a\n"
  },
  {
    "path": "VQ/VQM32/SOSCOMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*  File              : soscomp.h\n*  Date Created      : 6/1/94\n*  Description       : \n*\n*  Programmer(s)     : Nick Skrepetos\n*  Last Modification : 10/1/94 - 11:37:9 AM\n*  Additional Notes  : Modified by Denzil E. Long, Jr.\n*\n*****************************************************************************\n*            Copyright (c) 1994,  HMI, Inc.  All Rights Reserved            *\n****************************************************************************/\n\n#ifndef  _SOS_COMPRESS\n#define  _SOS_COMPRESS\n\n/* compression types */\nenum {\n\t_ADPCM_TYPE_1,\n\t};\n\n/* define compression structure */\ntypedef struct _tagCOMPRESS_INFO {\n\tchar       *lpSource;\n\tchar       *lpDest;\n\tunsigned long dwCompSize;\n\tunsigned long dwUnCompSize;\n\tshort         wBitSize;\n\tshort\t\t\t    wChannels;\n\tunsigned long dwSampleIndex;\n\tlong          dwPredicted;\n\tlong          dwDifference;\n\tshort         wCodeBuf;\n\tshort         wCode;\n\tshort         wStep;\n\tshort         wIndex;\n\n\tunsigned long dwSampleIndex2; //added BP for channel 2\n\tlong          dwPredicted2;   //added BP for channel 2\n\tlong          dwDifference2; \t//added BP for channel 2\n\tshort         wCodeBuf2; \t\t//added BP for channel 2\n\tshort         wCode2; \t\t\t//added BP for channel 2\n\tshort         wStep2; \t\t\t//added BP for channel 2\n\tshort         wIndex2; \t\t\t//added BP for channel 2\n\t} _SOS_COMPRESS_INFO;\n\n/* compressed file type header */\ntypedef struct _tagCOMPRESS_HEADER {\n\tunsigned long dwType;              // type of compression\n\tunsigned long dwCompressedSize;    // compressed file size\n\tunsigned long dwUnCompressedSize;  // uncompressed file size\n\tunsigned long dwSourceBitSize;     // original bit size\n\tchar          szName[16];          // file type, for error checking\n\t} _SOS_COMPRESS_HEADER;\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid cdecl sosCODECInitStream(_SOS_COMPRESS_INFO *);\nunsigned long cdecl sosCODECCompressData(_SOS_COMPRESS_INFO *,unsigned long);\nunsigned long cdecl sosCODECDecompressData(_SOS_COMPRESS_INFO *,unsigned long);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n\n"
  },
  {
    "path": "VQ/VQM32/TARGA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     targa.c\n* \n* DESCRIPTION\n*     Targa Image File reader. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     OpenTarga  - Open Targa image file.\n*     CloseTarga - Close Targa image file.\n*     LoadTarga  - Load Targa image file.\n*     XFlipTarga - X flip the image.\n*     YFlipTarga - Y flip the image.\n*\n* PRIVATE\n*     DecodeImageData - Decompress Targa image data.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <malloc.h>\n#include <mem.h>\n#include <io.h>\n#include <fcntl.h>\n#include <sys\\stat.h>\n#include \"targa.h\"\n\n/* Private data declerations. */\nstatic long DecodeImageData(TGAHandle *, char *);\nstatic void InvertImageData(TGAHeader *, char *);\n\n/****************************************************************************\n*\n* NAME\n*     OpenTarga - Open Targa image file.\n*\n* SYNOPSIS\n*     TGAHandle = OpenTarga(Name, Mode)\n*\n*     TGAHandle *OpenTarga(char *, unsigned short);\n*\n* FUNCTION\n*     Open a Targa image file and read in its header. The file stream will\n*     positioned after the ID field (if there is one).\n*\n* INPUTS\n*     Name - Pointer to name of Targa file.\n*     Mode - Access mode.\n*\n* RESULT\n*     TGAHandle - Pointer to initialized TGAHandle or NULL if error.\n*\n****************************************************************************/\n\nTGAHandle *OpenTarga(char *name, unsigned short mode)\n{\n\tTGAHandle *tga;\n\tlong       size;\n\tlong       error = 0;\n\n\t/* Allocate TGAHandle */\n\tif ((tga = (TGAHandle *)malloc(sizeof(TGAHandle))) != NULL) {\n\n\t\t/* Initialize TGAHandle structure. */\n\t\tmemset((void *)tga, 0, sizeof(TGAHandle));\n\t\ttga->mode = mode;\n\n\t\tswitch (mode) {\n\n\t\t\t/* Open targa file for read. */\n\t\t\tcase TGA_READMODE:\n\t\t\t\tif ((tga->fh = open(name, (O_RDONLY|O_BINARY))) != -1) {\n\n\t\t\t\t\t/* Read in header. */\n\t\t\t\t\tsize = read(tga->fh, &tga->header, sizeof(TGAHeader));\n\n\t\t\t\t\tif (size != sizeof(TGAHeader)) {\n\t\t\t\t\t\terror = 1;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Skip the ID field */\n\t\t\t\t\tif (!error && (tga->header.IDLength != 0)) {\n\t\t\t\t\t\tif (lseek(tga->fh, tga->header.IDLength, SEEK_CUR) == -1) {\n\t\t\t\t\t\t\terror = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\terror = 1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Open targa file for write. */\n\t\t\tcase TGA_WRITEMODE:\n\t\t\t\tif ((tga->fh = open(name, (O_CREAT|O_TRUNC|O_WRONLY|O_BINARY),\n\t\t\t\t\t\t(S_IREAD|S_IWRITE))) == -1) {\n\n\t\t\t\t\terror = 1;\n\t\t\t\t} else {\n\t\t\t\t\tprintf(\"\\r\");\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Open targa file for read/write.*/\n\t\t\tcase TGA_RDWRMODE:\n\t\t\t\tif ((tga->fh = open(name, (O_RDWR|O_BINARY),\n\t\t\t\t\t\t(S_IREAD|S_IWRITE))) != -1) {\n\n\t\t\t\t\t/* Read in header. */\n\t\t\t\t\tsize = read(tga->fh, &tga->header, sizeof(TGAHeader));\n\n\t\t\t\t\tif (size != sizeof(TGAHeader)) {\n\t\t\t\t\t\terror = 1;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Skip the ID field */\n\t\t\t\t\tif (!error && (tga->header.IDLength != 0)) {\n\t\t\t\t\t\tif (lseek(tga->fh, tga->header.IDLength, SEEK_CUR) == -1) {\n\t\t\t\t\t\t\terror = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\terror = 1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n \n\t\t/* Close on any error! */\n\t\tif (error) {\n\t\t\tCloseTarga(tga);\n\t\t\ttga = NULL;\n\t\t}\n\t}\n\n\treturn (tga);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     CloseTarga - Close Targa image file.\n*\n* SYNOPSIS\n*     CloseTarga(TGAHandle)\n*\n*     void CloseTarga(TGAHandle *);\n*\n* FUNCTION\n*     Close the Targa image file and free its handle.\n*\n* INPUTS\n*     TGAHandle - Pointer to TGAHandle returned by OpenTarga().\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid CloseTarga(TGAHandle *tga)\n{\n\t/* Ensure valid handle. */\n\tif (tga) {\n\n\t\t/* Close the file if it is open. */\n\t\tif (tga->fh != -1) close(tga->fh);\n\n\t\t/* Free TGAHandle */\n\t\tfree(tga);\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     LoadTarga - Load Targa Image File.\n*\n* SYNOPSIS\n*     Error = LoadTarga(Name, Palette, ImageBuffer)\n*\n*     long LoadTarga(char *, char *, char *);\n*\n* FUNCTION\n*     Open and load the Targa into the specified buffers. If either buffer\n*     pointer is NULL then that field will not be processed.\n*\n* INPUTS\n*     Name        - Name of Targa image file to load.\n*     Palette     - Pointer to buffer to load the palette into.\n*     ImageBuffer - Pointer to buffer to load the image data into.\n*\n* RESULT\n*     Error - 0 if successful, or TGAERR_??? error code.\n*\n****************************************************************************/\n\nlong LoadTarga(char *name, char *palette, char *image)\n{\n\tTGAHandle *tga;\n\tlong       size;\n\tlong       depth;\n\tlong       i,n;\n\tchar       c;\n\tlong       error = 0;\n\n\t/* Open the Targa */\n\tif ((tga = OpenTarga(name, TGA_READMODE)) != NULL) {\n\n\t\t/* Process ColorMap (palette) */\n\t\tif (tga->header.ColorMapType == 1) {\n\t\t\tdepth = (tga->header.CMapDepth >> 3);\n\t\t\tsize = (tga->header.CMapLength * depth);\n\n\t\t\t/* Load the palette from the TGA if a palette buffer is provided\n\t\t\t * otherwise we will skip it.\n\t\t\t */\n\t\t\tif ((palette != NULL) && (tga->header.CMapLength > 0)) {\n\n\t\t\t\t/* Adjust palette to the starting color entry. */\n\t\t\t\tpalette += (tga->header.CMapStart * depth);\n\n\t\t\t\t/* Read in the palette. */\n\t\t\t\tif (read(tga->fh, palette, size) == size) {\n\n\t\t\t\t\t/* Swap the byte ordering of the palette entries. */\n\t\t\t\t\tfor (i = 0; i < tga->header.CMapLength; i++) {\n\t\t\t\t\t\t#if(0)\n\t\t\t\t\t\tfor (n = 0; n < depth; n++) {\n\t\t\t\t\t\t\tc = *(palette + n);\n\t\t\t\t\t\t\t*(palette + n) = *(palette + ((depth - 1) - n));\n\t\t\t\t\t\t\t*(palette + ((depth - 1) - n)) = c;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t#else\n\t\t\t\t\t\tc = *palette;\n\t\t\t\t\t\t*palette = *(palette + (depth - 1));\n\t\t\t\t\t\t*(palette + (depth - 1)) = c;\n\t\t\t\t\t\t#endif\n\n\t\t\t\t\t\t/* Next entry */\n\t\t\t\t\t\tpalette += depth;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\terror = TGAERR_READ;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (lseek(tga->fh, size, SEEK_CUR) == -1) {\n\t\t\t\t\terror = TGAERR_READ;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Load the image data from the TGA if an image buffer is provided\n\t\t * otherwise we are done.\n\t\t */\n\t\tif (!error && (image != NULL)) {\n\t\t\tdepth = (tga->header.PixelDepth >> 3);\n\t\t\tsize = ((tga->header.Width * tga->header.Height) * depth);\n\n\t\t\tswitch (tga->header.ImageType) {\n\t\t\t\tcase TGA_CMAPPED:\n\t\t\t\t\tif (read(tga->fh, image, size) != size) {\n\t\t\t\t\t\terror = TGAERR_READ;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TGA_TRUECOLOR:\n\t\t\t\t\tif (read(tga->fh, image, size) == size) {\n\t\t\t\t\t\tInvertImageData(&tga->header, image);\n\t\t\t\t\t} else {\n\t\t\t\t\t\terror = TGAERR_READ;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TGA_CMAPPED_ENCODED:\n\t\t\t\t\terror = DecodeImageData(tga, image);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TGA_TRUECOLOR_ENCODED:\n\t\t\t\t\tif ((error = DecodeImageData(tga, image)) == NULL) {\n\t\t\t\t\t\tInvertImageData(&tga->header, image);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\terror = TGAERR_NOTSUPPORTED;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/* Arrange the image so that the origin position (coordinate 0,0)\n\t\t\t * is the upperleft hand corner of the image.\n\t\t\t */\n\t\t\tif (!error) {\n\t\t\t\tif (tga->header.ImageDescriptor & TGAF_XORIGIN) {\n\t\t\t\t\tXFlipTarga(&tga->header, image);\n\t\t\t\t}\n\n\t\t\t\tif ((tga->header.ImageDescriptor & TGAF_YORIGIN) == 0) {\n\t\t\t\t\tYFlipTarga(&tga->header, image);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Close the Targa */\n\t\tCloseTarga(tga);\n\t} else {\n\t\terror = TGAERR_OPEN;\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     SaveTarga - Save a Targa Image File.\n*\n* SYNOPSIS\n*     Error = SaveTarga(Name, TGAHeader, Palette, ImageBuffer)\n*\n*     long SaveTarga(char *, TGAHeader *, char *, char *);\n*\n* FUNCTION\n*\n* INPUTS\n*     Name        - Pointer to name of file to save.\n*     TGAHeader   - Pointer to initialized targa header structure.\n*     Palette     - Pointer to palette.\n*     ImageBuffer - Pointer to raw image data.\n*\n* RESULT\n*     Error - 0 if successful, or TGAERR_??? error code.\n*\n****************************************************************************/\n\nlong SaveTarga(char *name, TGAHeader *tgahd, char *palette, char *image)\n{\n\tTGAHandle *tga;\n\tlong       size;\n\tlong       depth;\n\tchar      *temppal;\n\tchar      *ptr;\n\tlong       i,n;\n\tchar       c;\n\tlong       error = 0;\n\n\t/* Open the Targa for write. */\n\tif ((tga = OpenTarga(name, TGA_WRITEMODE)) != NULL) {\n\n\t\t/* Write the header. */\n\t\tif (write(tga->fh, tgahd, sizeof(TGAHeader)) != sizeof(TGAHeader)) {\n\t\t\terror = TGAERR_WRITE;\n\t\t}\n\n\t\t/* Write the palette. */\n\t\tif (!error && (palette != NULL) && (tgahd->CMapLength > 0)) {\n\n\t\t\t/* Adjust palette to the starting color entry. */\n\t\t\tdepth = (tgahd->CMapDepth >> 3);\n\t\t\tpalette += (tgahd->CMapStart * depth);\n\t\t\tsize = (tgahd->CMapLength * depth);\n\n\t\t\t/* Allocate temporary buffer for palette manipulation. */\n\t\t\tif ((temppal = (char *)malloc(size)) != NULL) {\n\t\t\t\tmemcpy(temppal, palette, size);\n\t\t\t\tptr = temppal;\n\n\t\t\t\t/* Swap the byte ordering of the palette entries. */\n\t\t\t\tfor (i = 0; i < tga->header.CMapLength; i++) {\n\t\t\t\t\tfor (n = 0; n < (depth >> 1); n++) {\n\t\t\t\t\t\tc = *(ptr + n);\n\t\t\t\t\t\t*(ptr + n) = *(ptr + (depth - n));\n\t\t\t\t\t\t*(ptr + (depth - n)) = c;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Next entry */\n\t\t\t\t\tpalette += depth;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Write the palette. */\n\t\t\t\tif (write(tga->fh, temppal, size) != size) {\n\t\t\t\t\terror = TGAERR_WRITE;\n\t\t\t\t}\n\n\t\t\t\t/* Free temporary palette buffer. */\n\t\t\t\tfree(temppal);\n\t\t\t} else {\n\t\t\t\terror = TGAERR_NOMEM;\n\t\t\t}\n\t\t}\n\n\t\t/* Invert truecolor data. */\n\t\tif (tgahd->ImageType == TGA_TRUECOLOR) {\n\t\t\tInvertImageData(tgahd, image);\n\t\t}\n\n\t\t/* Write the image. */\n\t\tif (!error && (image != NULL)) {\n\t\t\tdepth = (tgahd->PixelDepth >> 3);\n\t\t\tsize = (((tgahd->Width * tgahd->Height)) * depth);\n\n\t\t\tif (write(tga->fh, image, size) != size) {\n\t\t\t\terror = TGAERR_WRITE;\n\t\t\t}\n\t\t}\n\n\t\t/* Close targa file. */\n\t\tCloseTarga(tga);\n\t} else {\n\t\terror = TGAERR_OPEN;\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     XFlipTarga - X flip the image.\n*\n* SYNOPSIS\n*     XFlipTarga(TGAHeader, Image)\n*\n*     void XFlipTarga(TGAHeader *, char *);\n*\n* FUNCTION\n*     Flip the image in memory on its X axis. (left to right)\n*\n* INPUTS\n*     TGAHeader - Pointer to initialized TGAHeader structure.\n*     Image     - Pointer to image buffer.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid XFlipTarga(TGAHeader *tga, char *image)\n{\n\tchar *ptr,*ptr1;\n\tlong  x,y,d;\n\tchar  v,v1;\n\tchar  depth;\n\n\t/* Pixel depth in bytes. */\n\tdepth = (tga->PixelDepth >> 3);\n\n\tfor (y = 0; y < tga->Height; y++) {\n\t\tptr = (image + ((tga->Width * depth) * y));\n\t\tptr1 = (ptr + ((tga->Width * depth) - depth));\n\n\t\tfor (x = 0; x < (tga->Width / 2); x++) {\n\t\t\tfor (d = 0; d < depth; d++) {\n\t\t\t\tv = *(ptr + d);\n\t\t\t\tv1 = *(ptr1 + d);\n\t\t\t\t*(ptr + d) = v1;\n\t\t\t\t*(ptr1 + d) = v;\n\t\t\t}\n\n\t\t\tptr += depth;\n\t\t\tptr1 -= depth;\n\t\t}\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     YFlipTarga - Y flip the image.\n*\n* SYNOPSIS\n*     YFlipTarga(TGAHeader, Image)\n*\n*     void YFlipTarga(TGAHeader *, char *);\n*\n* FUNCTION\n*     Flip the image in memory on its Y axis. (top to bottom)\n*\n* INPUTS\n*     TGAHeader - Pointer to initialized TGAHeader structure.\n*     Image     - Pointer to image buffer.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid YFlipTarga(TGAHeader *tga, char *image)\n{\n\tchar *ptr,*ptr1;\n\tlong  x,y;\n\tchar  v,v1;\n\tchar  depth;\n\n\t/* Pixel depth in bytes. */\n\tdepth = (tga->PixelDepth >> 3);\n\n\tfor (y = 0; y < (tga->Height >> 1); y++) {\n\n\t\t/* Compute address of lines to exchange. */\n\t\tptr = (image + ((tga->Width * y) * depth));\n\t\tptr1 = (image + ((tga->Width * (tga->Height - 1)) * depth));\n\t\tptr1 -= ((tga->Width * y) * depth);\n\n\t\t/* Exchange all the pixels on this scan line. */\n\t\tfor (x = 0; x < (tga->Width * depth); x++) {\n\t\t\tv = *ptr;\n\t\t\tv1 = *ptr1;\n\t\t\t*ptr = v1;\n\t\t\t*ptr1 = v;\n\t\t\tptr++;\n\t\t\tptr1++;\n\t\t}\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DecodeImageData - Decompress Targa image data.\n*\n* SYNOPSIS\n*     Error = DecodeImageData(TGAHandle, ImageBuffer)\n*\n*     long DecodeImageData(TGAHandle *, char *);\n*\n* FUNCTION\n*     Decode the RLE compressed image data into the specified buffer from\n*     the file I/O stream.\n*\n* INPUTS\n*     TGAHandle   - Pointer to TGAHandle returned by OpenTarga().\n*     ImageBuffer - Pointer to buffer to decompress image into.\n*\n* RESULT\n*     Error - 0 if successful, or TGAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DecodeImageData(TGAHandle *tga, char *image)\n{\n\tchar          *packet;\n\tunsigned char  count;\n\tunsigned char  depth;\n\tunsigned long  pixel_count;\n\tunsigned long  size;\n\tunsigned long  c,i;\n\tlong           error = 0;\n\n\t/* Compute pixel depth in bytes. */\n\tdepth = (tga->header.PixelDepth >> 3);\n\n\t/* Total number of pixels compressed in this image. */\n\tpixel_count = (tga->header.Width * tga->header.Height);\n\n\t/* Allocate packet buffer to hold maximum encoded data run. */\n\tif ((packet = (char *)malloc(128 * depth)) != NULL) {\n\t\twhile ((pixel_count > 0) && !error) {\n\n\t\t\t/* Read count. */\n\t\t\tif (read(tga->fh, &count, 1) == 1) {\n\n\t\t\t\t/* If bit 8 of the count is set then we have a run of pixels,\n\t\t\t\t * otherwise the data is raw pixels.\n\t\t\t\t */\n\t\t\t\tif (count & 0x80) {\n\t\t\t\t\tcount &= 0x7F;\n\t\t\t\t\tcount++;\n\n\t\t\t\t\t/* Read in run pixel. */\n\t\t\t\t\tif (read(tga->fh, packet, depth) == depth) {\n\n\t\t\t\t\t\t/* Repeat the pixel for the run count in the image buffer. */\n\t\t\t\t\t\tfor (c = 0; c < count; c++) {\n\t\t\t\t\t\t\tfor (i = 0; i < depth; i++) {\n\t\t\t\t\t\t\t\t*image++ = *(packet + i);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\terror = TGAERR_READ;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tcount++;\n\t\t\t\t\tsize = (count * depth);\n\n\t\t\t\t\t/* Read in raw pixels. */\n\t\t\t\t\tif (read(tga->fh, packet, size) == size) {\n\n\t\t\t\t\t\t/* Copy the raw pixel data into the image buffer. */\n\t\t\t\t\t\tmemcpy(image, packet, size);\n\t\t\t\t\t\timage += size;\n\t\t\t\t\t} else {\n\t\t\t\t\t\terror = TGAERR_READ;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* Adjust the pixel count. */\n\t\t\t\tpixel_count -= count;\n\t\t\t} else {\n\t\t\t\terror = TGAERR_READ;\n\t\t\t}\n\t\t}\n\n\t\t/* Free packet buffer. */\n\t\tfree(packet);\n\t} else {\n\t\terror = TGAERR_NOMEM;\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     InvertImageData - Invert TrueColor image data.\n*\n* SYNOPSIS\n*     InvertImageData(TGAHeader, ImageData)\n*\n*     void InvertImageData(TGAHeader *, char *);\n*\n* FUNCTION\n*\n* INPUTS\n*     TGAHeader - Pointer to initialized TGAHeader structure.\n*     ImageData - Pointer to TrueColor image data.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void InvertImageData(TGAHeader *tga, char *image)\n{\n\tlong depth;\n\tlong pixel_count;\n\tlong i;\n\tchar c;\n\n\t/* Compute the pixel depth in bytes. */\n\tdepth = (tga->PixelDepth >> 3);\n\n\t/* Total number of pixels in this image. */\n\tpixel_count = (tga->Width * tga->Height);\n\n\t/* 16-bit pixel layout is different that 24-bit and 32-bit. */\n\tif (depth > 2) {\n\t\twhile (pixel_count > 0) {\n\t\t\tfor (i = 0; i < (depth / 2); i++) {\n\t\t\t\tc = *(image + i);\n\t\t\t\t*(image + i) = *(image + ((depth - 1) - i));\n\t\t\t\t*(image + ((depth - 1) - i)) = c;\n\t\t\t}\n\n\t\t\t/* Next pixel */\n\t\t\tpixel_count--;\n\t\t\timage += depth;\n\t\t}\n\t} else {\n\t}\n}\n\n\n"
  },
  {
    "path": "VQ/VQM32/TARGA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMTARGA_H\n#define VQMTARGA_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Targa.h (32-Bit protected mode)\n* \n* DESCRIPTION\n*     Targa Image File definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/*---------------------------------------------------------------------------\n * Targa Header definitions\n *-------------------------------------------------------------------------*/\n\n/* TGAHeader - Targa Image File header.\n *\n * IDLength        - Size of Image ID field\n * ColorMapType    - Color map type.\n * ImageType       - Image type code.\n * CMapStart       - Color map origin.\n * CMapLength      - Color map length.\n * CMapDepth       - Depth of color map entries.\n * XOffset         - X origin of image.\n * YOffset         - Y origin of image.\n * Width           - Width of image.\n * Height          - Height of image.\n * PixelDepth      - Image pixel size\n * ImageDescriptor - Image descriptor byte.\n */\ntypedef struct _TGAHeader {\n\tchar  IDLength;\n\tchar  ColorMapType;\n\tchar  ImageType;\n\tshort CMapStart;\n\tshort CMapLength;\n\tchar  CMapDepth;\n\tshort XOffset;\n\tshort YOffset;\n\tshort Width;\n\tshort Height;\n\tchar  PixelDepth;\n\tchar  ImageDescriptor;\n} TGAHeader;\n\n/* ImageType definiton */\n#define TGA_NOIMAGE           0  /* No image data included in file */\n#define TGA_CMAPPED           1  /* Color-mapped image data */\n#define TGA_TRUECOLOR         2  /* Truecolor image data */\n#define TGA_MONO              3  /* Monochrome image data */\n#define TGA_CMAPPED_ENCODED   9  /* Color-mapped image data (Encoded) */\n#define TGA_TRUECOLOR_ENCODED 10 /* Truecolor image data (Encoded) */\n#define TGA_MONO_ENCODED      11 /* Monochrome image data (Encoded) */\n\n/* ImageDescriptor definition */\n#define TGAF_ATTRIB_BITS (0x0F<<0) /* Number of attribute bits per pixel */\n#define TGAF_XORIGIN     (1<<4)\n#define TGAF_YORIGIN     (1<<5)\n\n/*---------------------------------------------------------------------------\n * Targa Handle definitions\n *-------------------------------------------------------------------------*/\n\n/* TGAHandle - Targa Image File handle.\n *\n * fh     - File handle returned by open().\n * mode   - Access mode.\n * header - TGAHeader structure.\n */\ntypedef struct _TGAHandle {\n\tshort          fh;\n\tunsigned short mode;\n\tTGAHeader      header;\n} TGAHandle;\n\n/* Access modes. */\n#define TGA_READMODE  0\n#define TGA_WRITEMODE 1\n#define TGA_RDWRMODE  2\n\n/* Error codes */\n#define TGAERR_OPEN         -1\n#define TGAERR_READ         -2\n#define TGAERR_WRITE        -3\n#define TGAERR_SYNTAX       -4\n#define TGAERR_NOMEM        -5\n#define TGAERR_NOTSUPPORTED -6\n \n/*---------------------------------------------------------------------------\n * Function prototypes\n *-------------------------------------------------------------------------*/\n\nTGAHandle *OpenTarga(char *, unsigned short);\nvoid CloseTarga(TGAHandle *);\nlong LoadTarga(char *, char *, char *);\nlong SaveTarga(char *, TGAHeader *, char *, char *);\nvoid XFlipTarga(TGAHeader *, char *);\nvoid YFlipTarga(TGAHeader *, char *);\n\n#endif /* VQMTARGA_H */\n\n"
  },
  {
    "path": "VQ/VQM32/TASM32.CFG",
    "content": "/t\n/m\n/w+\n/jJUMPS\n/ml\n/p\n/z\n/iC:\\PROJECTS\\INCLUDE\n/zi\n/dPHARLAP_TNT=1\n"
  },
  {
    "path": "VQ/VQM32/TESTVB.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     testvb.c\n*\n* DESCRIPTION\n*     Video mode setting. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     TestVBIBit     - Test the polarity of the vertical blank bit.\n*\n****************************************************************************/\n\n#include <sys\\timeb.h>\n\n#ifdef __BORLANDC__\n#include \"portio.h\"\n#else\n#include <conio.h>\n#endif\n\n/****************************************************************************\n*\n* NAME\n*     TestVBIBit - Test the polarity of the vertical blank bit.\n*\n* SYNOPSIS\n*     Polarity = TestVBIBit()\n*\n*     long TestVBIBit(void);\n*\n* FUNCTION\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Polarity - Polarity of the vertical blank bit.\n*\n****************************************************************************/\n\nlong TestVBIBit(void)\n{\n\tstatic struct timeb mytime;\n\tlong          curtime;\n\tlong          endtime;\n\tunsigned long high = 0;\n\tunsigned long low = 0;\n\n\t/* Set the check time for .25 (1/4) of a second. */\n\tftime(&mytime);\n\tcurtime = ((mytime.time * 1000) + mytime.millitm);\n\tendtime = (curtime + (1000 / 4));\n\n\t/* Sample the vertical blank bit for the specified period of time.\n\t * The state in which it is in the least is the vertical blank state,\n\t * the state in which it is in the most is the active scan state.\n\t */\n\twhile (endtime >= curtime) {\n\t\tftime(&mytime);\n\t\tcurtime = ((mytime.time * 1000) + mytime.millitm);\n\n\t\tif (inp(0x3DA) & 0x08) {\n\t\t\thigh++;\n\t\t} else {\n\t\t\tlow++;\n\t\t}\n\t}\n\n\treturn (high > low);\n}\n\n\n\n"
  },
  {
    "path": "VQ/VQM32/TEXT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMTEXT_H\n#define VQMTEXT_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     text.h\n*\n* DESCRIPTION\n*     Text printing definitions. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     March 13, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nlong cdecl Text_Print(char *string, long x, long y, long fcol, long bcol);\nvoid cdecl Draw_Char(long character, long x, long y);\nvoid cdecl Set_Font_Palette_Range(void *palette, long start, long end);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMTEXT_H */\n\n"
  },
  {
    "path": "VQ/VQM32/TEXTPRNT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header:   J:\\vq\\projects\\vqm32\\textprnt.asv   1.5   27 Jul 1995 13:57:04   DENZIL_LONG  $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : TEXTPRNT.ASM                             *\n;*                                                                         *\n;*                   Programmer : David R. Dettmer                         *\n;*                                                                         *\n;*                   Start Date : January 28, 1992                         *\n;*                                                                         *\n;*                  Last Update : February 3, 1992   [DRD]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n;  VOID Text_Print(BYTE *string, WORD x_pixel, WORD y_pixel,               *\n;                  WORD fcolor,  WORD bcolor);                             *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\nXPIXEL_MAX    EQU\t320\nYPIXEL_MAX\tEQU\t200\n\nFONTINFOBLOCK\t\tEQU\t4\nFONTOFFSETBLOCK\tEQU\t6\nFONTWIDTHBLOCK\tEQU\t8\nFONTDATABLOCK\t\tEQU\t10\nFONTHEIGHTBLOCK\tEQU\t12\n\nFONTINFOMAXHEIGHT\tEQU\t4\nFONTINFOMAXWIDTH\tEQU\t5\n\n\tEXTRN\tC Char_Pixel_Width:NEAR\n\tEXTRN\tC Draw_Char:NEAR\n\tEXTRN\tC Set_Font_Palette_Range:NEAR\n\tEXTRN\tFontPtr:NEAR PTR\n\tEXTRN\tFontYSpacing:DWORD\n\t\n;----------------------------------------------------------------------------\n; TEXT_PRINT\n;\n; VOID Text_Print(BYTE *string, WORD x_pixel, WORD y_pixel,\n;\t\t  WORD fcolor,  WORD bcolor);\n;\n; Print the given string to the LogicPage.\n;\n; Bounds Checking:\n;\n; if x_pixel < 0, then x_pixel = 0\n; if x_pixel >= XPIXEL_MAX, then exit\n; if y_pixel < 0, then y_pixel = 0\n; if y_pixel >= YPIXEL_MAX, then exit\n;*\n\n\tGLOBAL\tC Text_Print:NEAR\n\tPROC\tText_Print C NEAR USES ebx ecx edx edi esi\n\tARG\tstring:NEAR PTR\n\tARG\tx_pixel:DWORD\n\tARG\ty_pixel:DWORD\n\tARG\tfcol:DWORD\n\tARG\tbcol:DWORD\n\n\tLOCAL\tfwidth:DWORD\t;Pixel width of font.\n\tLOCAL\tfgbg:DWORD\t;Two bytes of background & foreground colors.\n\tLOCAL\tlines:DWORD\t;Number of lines\n\tLOCAL\tfontheight:DWORD\n\n\t; Make sure there is a font available. If not, then bail.\n\n\txor\teax,eax\n\tmov\t[lines],eax\n\n\tmov\teax,[FontPtr]\n\tor\teax,eax\n\tje\t??exit\n\n\tmovzx\tebx,[WORD PTR eax+FONTINFOBLOCK]\n\tadd\tebx,eax\n\tmovzx\teax,[BYTE PTR ebx+FONTINFOMAXHEIGHT]\n\tmov\t[fontheight],eax\n\tmov\tesi,[string]\n\n\tmov\tebx,[x_pixel]\t\t; x pixel\n\tcmp\tebx,XPIXEL_MAX\t\t; check max x pos\n\tjae\tshort ??exit\n\n\tmov\tecx,[y_pixel]\t\t; y pixel\n\tcmp\tecx,YPIXEL_MAX\t\t; check max y pos\n\tjge\tshort ??exit\n\n\tmov\tal,[BYTE PTR bcol]\n\tmov\tah,[BYTE PTR fcol]\n\tmov\t[fgbg],eax\n\tlea\teax,[fgbg]\n\tcall\tSet_Font_Palette_Range C,eax,0,1\n\n; start of loop to print string\n\n\txor\tedx,edx\n\tinc\t[lines]\n??loop:\n\tmov\tdl,[esi]\n\tinc\tesi\n\n\tcmp\tedx,0\t\t\t; end of string\n\tje\tshort ??exit\n\n\tcmp\tedx,13\t\t\t; cmp to a '\\r'\n\tjne\tshort ??chkxy\n\n\t; Advance the screen to the left edge and down one line. Check\n\t; to see if the coordinate would still be visible. If not, then\n\t; bail.\n\n??onelinedown:\n \tmov\tebx,[x_pixel]\t\t; get original x position\n\tadd\tecx,[fontheight]\n\tadd\tecx,[FontYSpacing]\n\tcmp\tecx,YPIXEL_MAX\t  \t; check y pos\n\tjae\tshort ??exit\n\tinc\t[lines]\n\tjmp\t??loop\n\n??chkxy:\n\tcall\tChar_Pixel_Width C,edx\n\n\t; Check to see if this character would spill past the right edge\n\t; of the screen. If it would then drop down a line.\n\n\tmov\t[fwidth],eax\t\t; save width of char for later\n\tadd\teax,ebx\n\n\tcmp\teax,XPIXEL_MAX\t\t; check x pos\n\tja\tshort ??onelinedown\n\n\tcall\tDraw_Char C,edx,ebx,ecx\n\n\tadd\tebx,[fwidth]\t\t; add font width\n\tjmp\t??loop\n\n\t; Exit routine and unlock string if it was in EMS.\n\n??exit:\n\tmov\teax,[lines]\n\tret\n\n\tENDP\tText_Print\n\n;----------------------------------------------------------------------------\n\tEND\n\n"
  },
  {
    "path": "VQ/VQM32/TLIB.CFG",
    "content": "/C /E\n"
  },
  {
    "path": "VQ/VQM32/TLINK32.CFG",
    "content": "/c\n/m\n/Gm\n-LC:\\PROJECTS\\LIB;C:\\DEV\\BC4\\LIB\n-v\n"
  },
  {
    "path": "VQ/VQM32/VB.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     vb.asm\n;*\n;* DESCRIPTION\n;*     Vertical blank routines. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     WaitNoVB - Wait for active scan.\n;*     WaitVB   - Wait for vertical blank.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"video.i\"\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     WaitNoVB - Wait for active scan.\n;*\n;* SYNOPSIS\n;*     WaitNoVB()\n;*\n;*     void WaitNoVB(void);\n;*\n;* FUNCTION\n;*     Sit and wait for the active scan of the display.\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC WaitNoVB:NEAR\n\tPROC\tWaitNoVB C NEAR USES edx\n\tARG\tvbibit:DWORD\n\n\tmov\teax,[vbibit]\n\tand\tal,1\n\tshl\tal,3\n\tmov\tah,al\n\n;\tloop while VBL bit != VQ_VertBlank\n\n??no_scan_yet:\n\tmov\tedx,03DAH\n\tin\tal,dx\n\tand\tal,8\n\txor\tal,ah\n\tjnz\tshort ??no_scan_yet\n\tret\n\n\tENDP\tWaitNoVB\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     WaitVB - Wait for vertical blank.\n;*\n;* SYNOPSIS\n;*     WaitVB()\n;*\n;*     void WaitVB(void);\n;*\n;* FUNCTION\n;*     Sit and wait for the vertical blank of the display.\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC WaitVB:NEAR\n\tPROC\tWaitVB C NEAR USES\n\tARG\tvbibit:DWORD\n\n\tmov\teax,[vbibit]\n\tand\tal,1\n\tshl\tal,3\n\tmov\tah,al\n\n;\tLoop while VBL bit = VQ_VertBlank\n\n??no_vbl_yet:\n\tmov\tedx,03DAH\n\tin\tal,dx\n\tand\tal,8\n\txor\tal,ah\n\tjz\tshort ??no_vbl_yet\n\tret\n\n\tENDP\tWaitVB\n\n\tEND\n"
  },
  {
    "path": "VQ/VQM32/VERTAG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*       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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQMisc32 library.\n*\n* FILE\n*     vertag.c (32-Bit protected mode)\n*\n* DESCRIPTION\n*     Embedded version string. This string is prefixed with a tag (\"$VER$\")\n*     which can be search for to find this string.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*      \n* DATE\n*     Febuary 8, 1995\n*\n****************************************************************************/\n\n#ifdef __WATCOMC__\n#define DEVNAME \"Watcom/4GW\"\n#else\n#define DEVNAME \"Borland/TNT\"\n#endif\n\nchar VerTag[] = {\"$VER$VQM32 2.12 \"DEVNAME\" (\"__DATE__\" \"__TIME__\")\"};\n"
  },
  {
    "path": "VQ/VQM32/VESABLIT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     vesablit.c\n*\n* DESCRIPTION\n*     VESA bitblit routines. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VESA_Blit_640x480 - Blit to 640x480 256 color VESA mode.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <mem.h>\n#include <dos.h>\n#include \"video.h\"\n#include \"vesavid.h\"\n#include \"vesablit.h\"\n\n\n/****************************************************************************\n*\n* NAME\n*     VESA_Blit_640x480 - Blit to 640x480 256 color VESA mode.\n*\n* SYNOPSIS\n*     VESA_Blit_640x480(DisplayInfo, Buffer, X, Y, Width, Height)\n*\n*     void VESA_Blit_640x480(DisplayInfo *, char *, long, long, long, long);\n*\n* FUNCTION\n*\n* INPUTS\n*     DisplayInfo - Pointer to display information structure.\n*     Buffer      - Pointer to buffer to blit to VRAM.\n*     X           - Destination X coordinate of blit (upper left).\n*     Y           - Destination Y coordinate of blit (upper left).\n*     Width       - Width of blit.\n*     Height      - Height of blit.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VESA_Blit_640x480(DisplayInfo *disp,unsigned char *buf,long x1,long y1,\n\t\tlong width,long height)\n{\n\tVESAModeInfo *vminfo;\n\tlong         bank;\n\tlong         last_bank;\n\tlong         bank_offset;\n\tlong         scrn_offset;\n\tlong         grains_per_win;\n\tlong         part1;\n\tlong         part2;\n\tlong         i;\n\n\t/* Initialize values */\n\tvminfo = (VESAModeInfo *)disp->Extended;\n\tscrn_offset = ((disp->XRes * y1) + x1);\n\tgrains_per_win = ((long)vminfo->WinSize / (long)vminfo->WinGranularity);\n\tbank_offset = scrn_offset % 65536L;\n\tlast_bank = -1;\n\n\tfor (i = 0; i < height; i++) {\n\n\t\t/* Compute which bank this scanline is in */\n\t\tbank = (scrn_offset / 65536L);\n\n\t\t/* Set a new bank */\n\t\tif (bank != last_bank) {\n\t\t\tSetVESAWindow(bank);\n\t\t\tlast_bank = bank;\n\t\t\tbank_offset = (scrn_offset % 65536L);\n\t\t}\n\n\t\t/* Copy a full scanline */\n\t\tif ((bank_offset + width) < 65536L) {\n\t\t\tCopy_Row((char *)buf, (char *)bank_offset, width);\n\t\t\tbuf += width;\n\t\t\tscrn_offset += disp->XRes;\n\t\t\tbank_offset += disp->XRes;\n\t\t}\n\n\t\t/* Copy two partial scanlines */\n\t\telse {\n\t\t\tpart1 = (65536L - bank_offset);\n\t\t\tpart2 = (width - part1);\n\t\t\tCopy_Row((char *)buf, (char *)bank_offset, part1);\n\n\t\t\tbuf += part1;\n\t\t\tbank += grains_per_win;\n\t\t\tlast_bank += grains_per_win;\n\t\t\tSetVESAWindow(bank);\n\t\t\tCopy_Row((char *)buf, (char *)0, part2);\n\n\t\t\tbuf += part2;\n\t\t\tscrn_offset += disp->XRes;\n\t\t\tbank_offset = (scrn_offset % 65536L);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "VQ/VQM32/VESABLIT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMVESABLIT_H\n#define VQMVESABLIT_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     VESABlit.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     VESA bitblit routines.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\video.h>\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\nvoid VESA_Blit_640x480(DisplayInfo *disp,unsigned char *buf,long x1,\n\t\tlong y1,long width,long height);\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid cdecl Blit_VESA640x480(DisplayInfo *disp,unsigned char *buf,long x1,\n\t\tlong y1,long width,long height);\n\nvoid cdecl Buf_320x200_To_VESA_320x200(unsigned char *buffer, long grain);\nvoid cdecl Buf_320x200_To_VESA_640x400(unsigned char *buffer, long grain);\nvoid cdecl Buf_320x200_To_VESA_32K(unsigned char *buffer,\n\t\tunsigned char *palette, long grain);\n\nvoid cdecl Copy_Row(char *, char *, long);\nvoid cdecl Copy_Word_Row(char *source, char *dest, char *palette,\n\t\tlong numbytes);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMVESABLIT_H */\n\n"
  },
  {
    "path": "VQ/VQM32/VESABUF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     vesabuf.asm\n;*\n;* DESCRIPTION\n;*     VESA buffered blit routines.  (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Bill Randolph\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     Febuary 3, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     Buf_320x200_To_VESA_320x200 - Buffer copy, unscaled\n;*     Buf_320x200_To_VESA_640x400 - Scales and copies 320x200 to 640x400\n;*     Buf_320x200_To_VESA_32K     - Copies 320x200 buffer to VESA 32K\n;*                                   colors\n;*     Copy_Row                    - Copy a row of pixels to VRAM.\n;*     Copy_Word_Row               - Copy a row of 15-bit pixels to VRAM\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"video.i\"\n\tCODESEG\n\n;---------------------------------------------------------------------------\n; DRAW_BLOCK_ROWS: draws 'numrows' rows of 2x2 blocks\n; Set ES:DI to current screen location\n; Set DS:SI to current source location\n; Uses: ax, cx, dx\n;---------------------------------------------------------------------------\n\tMACRO\tDRAW_BLOCK_ROWS numrows\n\tLOCAL\t??Start_row\n\tLOCAL\t??Not_finished_a_line\n\tLOCAL\t??Done\n\n\tmov\tedx,numrows\n??Start_row:\n\tmov\tecx,320\n\n??Not_finished_a_line:\n\tmov\tal,[BYTE PTR esi]\n\tmov\tah,al\n\tinc\tesi\n\n\tIF\tPHARLAP_TNT\n\tmov\t[WORD PTR es:edi],ax\n\tmov\t[WORD PTR es:edi+640],ax\n\tELSE\n\tmov\t[WORD PTR edi],ax\n\tmov\t[WORD PTR edi+640],ax\n\tENDIF\n\n\tadd\tedi,2\n\tdec\tecx\n\tjnz\t??Not_finished_a_line\n\n\tadd\tedi,640\n\tdec\tedx\n\tjz\t??Done\n\tjmp\t??Start_row\n\n??Done:\n\tENDM\n\n;---------------------------------------------------------------------------\n; DRAW_BLOCK_ROW: draws one row of 'numblks' 2x2 blocks\n; Set ES:DI to current screen location\n; Set DS:SI to current source location\n; Uses: ax, cx\n;---------------------------------------------------------------------------\n\tMACRO\tDRAW_BLOCK_ROW numblks\n\tLOCAL\t??Not_done\n\n\tmov\tecx,numblks\n\n??Not_done:\n\tmov\tal,[BYTE PTR esi]\n\tmov\tah,al\n\tinc\tesi\n\n\tIF\tPHARLAP_TNT\n\tmov\t[WORD PTR es:edi],ax\n\tmov\t[WORD PTR es:edi+640],ax\n\tELSE\n\tmov\t[WORD PTR edi],ax\n\tmov\t[WORD PTR edi+640],ax\n\tENDIF\n\n\tadd\tedi,2\n\tdec\tecx\n\tjnz\t??Not_done\n\n\tENDM\n\n;---------------------------------------------------------------------------\n; DRAW_PIXEL_ROW: draws 'numblks' 2x1 blocks\n; Set ES:DI to current screen location\n; Set DS:SI to current source location\n; Uses: ax, cx\n;---------------------------------------------------------------------------\n\tMACRO\tDRAW_PIXEL_ROW numblks\n\tLOCAL\t??Not_done\n\n\tmov\tecx,numblks\n\n??Not_done:\n\tmov\tal,[BYTE PTR esi]\n\tmov\tah,al\n\tinc\tesi\n\n\tIF\tPHARLAP_TNT\n\tmov\t[WORD PTR es:edi],ax\n\tELSE\n\tmov\t[WORD PTR edi],ax\n\tENDIF\n\n\tadd\tedi,2\n\tdec\tecx\n\tjnz\t??Not_done\n\n\tENDM\n\n;****************************************************************************\n;*\n;* NAME\n;*     Blit_VESA640x480 - Blit to 640x480 256 color VESA mode.\n;*\n;* SYNOPSIS\n;*     Blit_VESA640x480(DisplayInfo, Buffer, X, Y, Width, Height)\n;*\n;*     void Blit_VESA640x480(DisplayInfo *, char *, long, long, long, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     DisplayInfo - Pointer to display information structure.\n;*     Buffer      - Pointer to buffer to blit to VRAM.\n;*     X           - Destination X coordinate of blit (upper left).\n;*     Y           - Destination Y coordinate of blit (upper left).\n;*     Width       - Width of blit.\n;*     Height      - Height of blit.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n;\tGLOBAL\tC Blit_VESA640x480:NEAR\n;\tPROC\tBlit_VESA640x480 C NEAR USES\n;\n;\tARG\tdisp:NEAR PTR DisplayInfo\n;\tARG\tbuffer:NEAR PTR\n;\tARG\tx:DWORD\n;\tARG\ty:DWORD\n;\tARG\twidth:DWORD\n;\tARG\theight:DWORD\n;\n;\tLOCAL\tgrain:DWORD\n;\tLOCAL\tscrn_offset:DWORD\n;\tLOCAL\tbank_offset:DWORD\n;\tLOCAL\tbank:DWORD\n;\tLOCAL\txres:DWORD\n;\n;;----------------------------------------------------------------------------\n;;\tINITIALIZE\n;;----------------------------------------------------------------------------\n;\n;\tpushad\n;\n;;\tCalculate granularity units per window\n;\n;\tmov\tesi,[disp]\n;\txor\teax,eax\n;\tmov\tedi,[(DisplayInfo esi).Extended]\n;\txor\tebx,ebx\n;\tmov\tax,[(VESAModeInfo edi).WinSize]\n;\txor\tedx,edx\n;\tmov\tbx,[(VESAModeInfo edi).WinGranularity]\n;\tidiv\tebx\n;\tmov\t[grain],eax\n;\n;;\tCalculate screen offset\n;\n;\tmov\teax,[(DisplayInfo esi).XRes]\n;\tmov\t[xres],eax\n;\timul\t[y]\n;\tadd\teax,[x]\n;\tmov\t[scrn_offset],eax\n;\n;;\tCalculate bank offset\n;\n;\tmov\tebx,65536\n;\tidiv\tebx\n;\tmov\t[bank_offset],edx\n;\tmov\t[bank],eax\n;\n;\tpopad\n;\tret\n;\n;\tENDP\tBlit_VESA640x480\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Buf_320x200_To_VESA_320x200 - Buffer copy, unscaled\n;*\n;* SYNOPSIS\n;*     Buf_320x200_To_VESA_320x200(Buffer, GrainPerWin)\n;*\n;*     void Buf_320x200_To_VESA_320x200(char *, long);\n;*\n;* FUNCTION\n;*     To center the buffer on the screen, it's upper-left corner goes at\n;*     (160,140).  This means the buffer spans VESA banks 1,2 & 3, so it must\n;*     be copied in 3 parts:\n;*\n;*     Bank 1: starting offset 24224, 65 lines\n;*     Bank 2: starting offset 288, 102 lines\n;*     Bank 3: starting offset 32, 33 lines\n;*\n;* INPUTS\n;*     Buffer      - Pointer to buffer to transfer to VRAM\n;*     GrainPerWin - Granularity units per 64k window.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Buf_320x200_To_VESA_320x200:NEAR\n\tPROC\tBuf_320x200_To_VESA_320x200 C NEAR USES ebx ecx edx esi edi\n\n\tARG\tbuffer:NEAR PTR\n\tARG\tgrains_per_win:DWORD\n\n\tLOCAL\tgrain_num:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tmov\teax,01Ch\t;Set ES selector to VRAM\n\tmov\tes,ax\n\tENDIF\n\n\tmov\teax,[grains_per_win]\n\tmov\tesi,[buffer]\n\tmov\t[grain_num],eax\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 1\n;----------------------------------------------------------------------------\n\n\tSET_WINDOW [grain_num]\n\tmov\tedi,24224\t;Starting screen address\n\tmov\tedx,65\t;Lines to copy\n\n??SetBank1:\n\tmov\tecx,80\t;DWORDS to copy\n\trep\tmovsd\t;Move the pixels\n\tadd\tedi,320\t;Wrap to start of next line\n\tdec\tedx\t;Decrement our line counter\n\tjnz\t??SetBank1\t;Draw more lines\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 2\n;----------------------------------------------------------------------------\n\n\tmov\teax,[grains_per_win]\n\tadd\t[grain_num],eax\n\n\tSET_WINDOW [grain_num]\n\tmov\tedi,288\t;Starting screen address\n\tmov\tedx,102\t;Lines to copy\n\n??SetBank2:\n\tmov\tecx,80\t;DWORDS to copy\n\trep\tmovsd\t;Move the pixels\n\tadd\tedi,320\t;Wrap to start of next line\n\tdec\tedx\t;Decrement our line counter\n\tjnz\t??SetBank2\t;Draw more lines\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 3\n;----------------------------------------------------------------------------\n\n\tmov\teax,[grains_per_win]\n\tadd\t[grain_num],eax\n\n\tSET_WINDOW [grain_num]\n\tmov\tedi,32\t;Starting screen address\n\tmov\tedx,33\t;Lines to copy\n\n??SetBank3:\n\tmov\tecx,80\t;DWORDS to copy\n\trep\tmovsd\t;Move the pixels\n\tadd\tedi,320\t;Wrap to start of next line\n\tdec\tedx\t;Decrement our line counter\n\tjnz\t??SetBank3\t;Draw more lines\n\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\tret\n\n\tENDP\tBuf_320x200_To_VESA_320x200\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Buf_320x200_To_VESA_640x400 - Scales and copies 320x200 to 640x400\n;*\n;* SYNOPSIS\n;*     Buf_320x200_To_VESA_640x400(Buffer, GrainPerWin)\n;*     \n;*     void Buf_320x200_To_VESA_640x400(char *, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Buffer      - Pointer to buffer to transfer to VRAM\n;*     GrainPerWin - Granularity units per 64k window.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Buf_320x200_To_VESA_640x400:NEAR\n\tPROC\tBuf_320x200_To_VESA_640x400 C NEAR USES ebx ecx edx esi edi\n\n\tARG\tbuffer:NEAR PTR\n\tARG\tgrains_per_win:DWORD\n\n\tLOCAL\tgrain_num:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tmov\teax,01Ch\t;Set ES selector to VRAM\n\tmov\tes,ax\n\tENDIF\n\n\tmov\tesi,[buffer]\n\tmov\t[grain_num],0\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 0\n;\t- Skip down 40 scanlines (to center the image)\n;\t- Draw 62 scanlines (31 rows of blocks)\n;\t- Draw top half of 128 blocks\n;----------------------------------------------------------------------------\n\n\tSET_WINDOW [grain_num]\n\tmov\tedi,25600\t;Starting screen address\n\n\tDRAW_BLOCK_ROWS 62/2\t;Draw 31 rows of blocks\n\tDRAW_PIXEL_ROW 256/2\t;Draw top half of next 128 blocks\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 1\n;\t- Draw bottom half of previous 128 blocks\n;\t- Finish the scan line with full blocks\n;\t- Draw 100 scanlines of blocks\n;\t- last line: top half of 256 blocks\n;----------------------------------------------------------------------------\n\n\tmov\teax,[grains_per_win]\n\tadd\t[grain_num],eax\n\tSET_WINDOW [grain_num]\n\n\tsub\tesi,256/2\t;Draw bottom half of prev 128 blks\n\tmov\tedi,384\n\tDRAW_PIXEL_ROW 256/2\n\n\tmov\tedi,0\n\tDRAW_BLOCK_ROW 384/2\t;Fill rest of this block row\n\n\tadd\tedi,640\n\tDRAW_BLOCK_ROWS 100/2\t;Draw the block rows\n\tDRAW_PIXEL_ROW 512/2\t;Draw top half of next 512 blocks\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 2\n;\t- Draw bottom half of previous 256 blocks\n;\t- Finish the scan line with full blocks\n;\t- Draw 101 scanlines of blocks\n;\t- last line: 64 full blocks plus top half of 256 blocks\n;----------------------------------------------------------------------------\n\n\tmov\teax,[grains_per_win]\n\tadd\t[grain_num],eax\n\tSET_WINDOW [grain_num]\n\n\tsub\tesi,512/2\t;Draw bottom half of prev 256 blks\n\tmov\tedi,128\n\tDRAW_PIXEL_ROW 512/2\n\n\tmov\tedi,0\n\tDRAW_BLOCK_ROW 128/2\t;Fill rest of this block row\n\n\tadd\tedi,640\n\tDRAW_BLOCK_ROWS 101/2\t;Draw the block rows\n\tDRAW_BLOCK_ROW 128/2\t;Draw next 64 blocks\n\tDRAW_PIXEL_ROW 512/2\t;Top half of 256 blocks\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 3\n;\t- Draw bottom half of previous 256 blocks\n;\t- Finish the scan line with full blocks\n;\t- Draw 101 scanlines of blocks\n;\t- last line: 192 full blocks, top half of 128 blocks\n;----------------------------------------------------------------------------\n\n\tmov\teax,[grains_per_win]\n\tadd\t[grain_num],eax\n\tSET_WINDOW [grain_num]\n\n\tsub\tesi,512/2\t;Draw bottom half of prev 256 blks\n\tmov\tedi,0\n\tDRAW_PIXEL_ROW 512/2\n\tDRAW_BLOCK_ROWS 101/2\t;Draw the block rows\n\tDRAW_BLOCK_ROW 384/2\t;Last row of full blocks\n\tDRAW_PIXEL_ROW 256/2\t;Top half of 128 blocks\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 4\n;\t- Draw bottom half of previous 128 blocks\n;\t- Draw 30 scanlines of blocks\n;----------------------------------------------------------------------------\n\n\tmov\teax,[grains_per_win]\n\tadd\t[grain_num],eax\n\tSET_WINDOW [grain_num]\n\n\tsub\tesi,256/2\t;Draw bottom half of prev 256 blks\n\tmov\tedi,0\n\tDRAW_PIXEL_ROW 256/2\n\tDRAW_BLOCK_ROWS 30/2\t;Draw the block rows\n\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\n\tENDP\tBuf_320x200_To_VESA_640x400\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Buf_320x200_To_VESA_32K - Copies 320x200 buffer to VESA 32K colors\n;*\n;* SYNOPSIS\n;*     Buf_320x200_To_VESA_32K(Buffer, Palette, GrainPerWin)\n;*     \n;*     void Buf_320x200_To_VESA_32K(char *, char *, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Buffer      - Pointer to buffer to transfer to VRAM\n;*     Palette     - Pointer to 15-bit palette to use.\n;*     GrainPerWin - Granularity units per 64k window.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Buf_320x200_To_VESA_32K:NEAR\n\tPROC\tBuf_320x200_To_VESA_32K C NEAR USES ebx ecx edx esi edi\n\n\tARG\tbuffer:NEAR PTR\n\tARG\tpalette:NEAR PTR\n\tARG\tgrains_per_win:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tmov\teax,01Ch\t;Set ES selector to VRAM\n\tmov\tes,ax\n\tENDIF\n\n\tmov\tesi,[buffer]\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 0\n;----------------------------------------------------------------------------\n\n\tSET_WINDOW 0\n\tmov\tedi,0\t;Start at Bank 0, offset 0\n\tmov\tecx,32768\t;# words we'll be setting\n\n;\tGet the pixel's offset into the palette\n\n??Buf0Loop:\n\txor\teax,eax\n\tmov\tebx,[palette]\n\tmov\tal,[BYTE PTR esi]\n\tadd\tebx,eax\n\tinc\tesi\n\tadd\tebx,eax\n\n;\tstore the 15-bit palette value\n\n\tmov\tax,[WORD PTR ebx]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[WORD PTR es:edi],ax\n\tELSE\n\tmov\t[WORD PTR edi],ax\n\tENDIF\n\n\tadd\tedi,2\n\tdec\tecx\n\tjnz\t??Buf0Loop\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 1\n;----------------------------------------------------------------------------\n\n\tSET_WINDOW [grains_per_win]\n\tmov\tedi,0\t;Start at Bank 1, offset 0\n\tmov\tecx,31232\t;# words we'll be setting\n\n;\tGet the pixel's offset into the palette\n\n??Buf1Loop:\n\txor\teax,eax\n\tmov\tebx,[palette]\n\tmov\tal,[BYTE PTR esi]\n\tadd\tebx,eax\n\tinc\tesi\n\tadd\tebx,eax\n\n;\tStore the 15-bit palette value\n\n\tmov\tax,[WORD PTR ebx]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[WORD PTR es:edi],ax\n\tELSE\n\tmov\t[WORD PTR edi],ax\n\tENDIF\n\n\tadd\tedi,2\n\tdec\tecx\n\tjnz\t??Buf1Loop\n\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\n\tENDP\tBuf_320x200_To_VESA_32K\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Copy_Row - Copy a row of pixels to VRAM.\n;*\n;* SYNOPSIS\n;*     Copy_Row(Source, Dest, Length)\n;*\n;*     void Copy_Row(char *, char *, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Source - Pointer to data to copy to VRAM\n;*     Dest   - Destination VRAM address.\n;*     Length - Number of bytes to copy.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Copy_Row:NEAR\n\tPROC\tCopy_Row C NEAR USES ecx esi edi\n\t\n\tARG\tsource:NEAR PTR\n\tARG\tdest:NEAR PTR\n\tARG\tnumbytes:DWORD\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tmov\teax,01Ch\n\tmov\tes,ax\n\tENDIF\n\n\tcld\n\tmov\tesi,[source]\n\tmov\tedi,[dest]\n\tmov\tecx,[numbytes]\n\trep\tmovsb\n\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\n\tENDP\tCopy_Row\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Copy_Word_Row - Copy a row of 15-bit pixels to VRAM\n;*\n;* SYNOPSIS\n;*     Copy_Word_Row(Source, Dest, Palette, Length)\n;*\n;*     void Copy_Word_Row(char *, char *, char *, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Source  - Pointer to data to transfer.\n;*     Dest    - Destination screen address.\n;*     Palette - 15bit palette to use.\n;*     Length  - Bytes to transfer.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Copy_Word_Row:NEAR\n\tPROC\tCopy_Word_Row C NEAR USES ebx ecx esi edi\n\n\tARG\tsource:NEAR PTR\n\tARG\tdest:NEAR PTR\n\tARG\tpalette:NEAR PTR\n\tARG\tnumbytes:DWORD\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tmov\teax,01Ch\n\tmov\tes,ax\n\tENDIF\n\n\tmov\tesi,[source]\n\tmov\tedi,[dest]\n\tmov\tecx,[numbytes]\n\n??loop:\n\tmov\tebx,[palette]\n\txor\teax,eax\n\tmov\tal,[esi]\t;Get pixel value\n\tshl\teax,1\t;Adjust for word entry\n\tadd\tebx,eax\t;Compute color address\n\tmov\tax,[ebx]\t;Get color\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],ax\t;Set 16bit pixel\n\tELSE\n\tmov\t[edi],ax\t;Set 16bit pixel\n\tENDIF\n\n\tinc\tesi\t;Next source pixel\n\tadd\tedi,2\t;Next dest pixel\n\tdec\tecx\t;Decrement pixel count\n\tjnz\t??loop\n\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret  \n\n\tENDP\tCopy_Word_Row\n\n\tEND\n\n"
  },
  {
    "path": "VQ/VQM32/VESAVID.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     vesavid.c\n*\n* DESCRIPTION\n*     VESA video manager. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     InitVESA         - Initialize the VESA video manager.\n*     UninitVESA       - Uninitialize the VESA video manager.\n*     SetVESAMode      - Set the display to the specified VESA video mode.\n*     ReadVESAModeInfo - Read the VESA mode information from the video card.\n*     SetVESAWindow    - Set VESA window A's start address.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <mem.h>\n#include <dos.h>\n\n#ifndef __WATCOMC__\n#include <pldos32.h>\n#include <pharlap.h>\n#else\n#include \"realmode.h\"\n#endif\n\n#include \"vesavid.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n#ifdef __WATCOMC__\nstatic short _VInfoSel = NULL;\nstatic short _VInfoSeg = NULL;\nstatic short _ModeInfoSel = NULL;\nstatic short _ModeInfoSeg = NULL;\n\n#else  /* __WATCOMC__ */\n/* _regs       - Registers used for calling software interrupts.\n * _rpVInfo    - Real pointer to VInfo structure in conventional memory.\n * _rpModeInfo - Real pointer to ModeInfo structure in conventional memory.\n * _VInfo      - Protected mode copy of VInfo structure.\n * _ModeInfo   - Protected mode copy of ModeInfo structure.\n */\nstatic SWI_REGS _regs;\nstatic REALPTR _rpVInfo = NULL;\nstatic REALPTR _rpModeInfo = NULL;\nstatic VESAInfo _VInfo;\nstatic VESAModeInfo _ModeInfo;\n\n#endif /* __WATCOMC__ */\n\n\n/****************************************************************************\n*\n* NAME\n*     InitVESA - Initialize the VESA video manager.\n*\n* SYNOPSIS\n*     Error = InitVESA()\n*\n*     long InitVESA(void);\n*\n* FUNCTION\n*     Initialize the VESA video system. Get the VESA information from the\n*     VESA video bios.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Error - 0 if successful, or -1 error/VESA not supported.\n*\n****************************************************************************/\n\nlong InitVESA(void)\n{\n\t#ifdef __WATCOMC__\n\tunion REGS   r;\n\tstruct SREGS sr;\n\tRMInfo       rmi;\n\tlong         error = -1;\n\n\t/* Allocate real-mode memory for VESA structure. */\n\tr.x.eax = 0x0100;\n\tr.x.ebx = (sizeof(VESAInfo) + 15) >> 4;\n\tint386(0x31, &r, &r);\n\n\tif (r.x.cflag == 0) {\n\t\t_VInfoSel = r.w.dx;\n\t\t_VInfoSeg = r.w.ax;\n\n\t\t/* Allocate real-mode memory for VESAModeInfo structure. */\n\t\tr.x.eax = 0x0100;\n\t\tr.x.ebx = (sizeof(VESAModeInfo) + 15) >> 4;\n\t\tint386(0x31, &r, &r);\n\n\t\tif (r.x.cflag == 0) {\n\t\t\t_ModeInfoSel = r.w.dx;\n\t\t\t_ModeInfoSeg = r.w.ax;\n\n\t\t\t/* Clear VESAInfo structure. */\n\t\t\tmemset(MK_PTR(0, _VInfoSeg), 0, sizeof(VESAInfo));\n\n\t\t\t/* Get VESA information. */\n\t\t\tmemset(&rmi, 0, sizeof(RMInfo));\n\t\t\trmi.eax = 0x4F00;\n\t\t\trmi.edi = 0;\n\t\t\trmi.es = _VInfoSeg;\n\n\t\t\tsegread(&sr);\n\t\t\tr.w.ax = 0x0300;\n\t\t\tr.h.bl = 0x10;\n\t\t\tr.h.bh = 0;\n\t\t\tr.w.cx = 0;\n\t\t\tsr.es = FP_SEG(&rmi);\n\t\t\tr.x.edi = FP_OFF(&rmi);\n\t\t\tint386x(0x31, &r, &r, &sr);\n\n\t\t\tif ((r.x.cflag == 0) && (rmi.eax == 0x004F)) {\n\t\t\t\terror = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\n\tif (error != 0) {\n\t\tUninitVESA();\n\t}\n\n\treturn (error);\n\n\t#else  /* __WATCOMC__ */\n\n\tunsigned short rseg;\n\tlong           paras;\n\tlong           error = -1;\n\n\t/* Calculate size of VESAInfo structure in paragraphs */\n\tparas = (sizeof(VESAInfo) + 15) >> 4;\n\t\n\t/* Allocate real-mode memory for VESA structure. */\n\tif (_dx_real_alloc(paras, (unsigned short *)&rseg,\n\t\t\t(unsigned short *)&paras) == 0) {\n\n\t\tRP_SET(_rpVInfo, 0, rseg);\n\n\t\t/* Calculate size of VESAModeInfo structure in paragraphs */\n\t\tparas = (sizeof(VESAModeInfo) + 15) >> 4;\n\n\t\t/* Allocate real-mode memory for VESAModeInfo structure. */\n\t\tif (_dx_real_alloc(paras, (unsigned short *)&rseg,\n\t\t\t\t(unsigned short *)&paras) == 0) {\n\n\t\t\tRP_SET(_rpModeInfo, 0, rseg);\n\n\t\t\t/* Clear the input buffer */\n\t\t\tFillRealMem(_rpVInfo, 0, sizeof(VESAInfo));\n\n\t\t\t/* Set up function call */\n\t\t\t_regs.eax = 0x4F00;\n\t\t\t_regs.edi = RP_OFF(_rpVInfo);\n\t\t\t_regs.es = RP_SEG(_rpVInfo);\n\t\t\t_dx_real_int(0x10, &_regs);\n\n\t\t\tif (_regs.eax == 0x004F) {\n\t\t\t\tReadRealMem(&_VInfo, _rpVInfo, sizeof(VESAInfo));\n\t\t\t\terror = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (error != 0) {\n\t\tUninitVESA();\t\t\n\t}\n\n\treturn (error);\n\n\t#endif /* __WATCOMC__ */\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     UninitVESA - Uninitialize the VESA video manager.\n*\n* SYNOPSIS\n*     UninitVESA()\n*\n*     void UninitVESA(void);\n*\n* FUNCTION\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid UninitVESA(void)\n{\n\t#ifdef __WATCOMC__\n\tunion REGS r;\n\n\t/* Free VESAInfo structure */\n\tif (_VInfoSeg != NULL) {\n\t\tr.x.eax = 0x0101;\n\t\tr.x.edx = _VInfoSel;\n\t\tint386(0x31, &r, &r);\n\n\t\t_VInfoSeg = NULL;\n\t\t_VInfoSel = NULL;\n\t}\n\n\t/* Free VESAModeInfo structure */\n\tif (_ModeInfoSeg != NULL) {\n\t\tr.x.eax = 0x0101;\n\t\tr.x.edx = _VInfoSel;\n\t\tint386(0x31, &r, &r);\n\n\t\t_ModeInfoSeg = NULL;\n\t\t_ModeInfoSel = NULL;\n\t}\n\n\t#else  /* __WATCOMC__ */\n\n\t/* Free VESAInfo structure */\n\tif (_rpVInfo != NULL) {\n\t\t_dx_real_free(RP_SEG(_rpVInfo));\n\t\t_rpVInfo = NULL;\n\t}\n\n\t/* Free VESAModeInfo structure */\n\tif (_rpModeInfo != NULL) {\n\t\t_dx_real_free(RP_SEG(_rpModeInfo));\n\t\t_rpModeInfo = NULL;\n\t}\n\t#endif /* __WATCOMC__ */\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     SetVESAMode - Set the display adapter to the given VESA video mode.\n*\n* SYNOPSIS\n*     VESAModeInfo = SetVESAMode(Mode)\n*\n*     VESAModeInfo *SetVESAMode(long);\n*\n* FUNCTION\n*     Set the display adapter to the specified VESA video mode.\n*\n* INPUTS\n*     Mode - VESA video mode to set the display to.\n*\n* RESULT\n*     VESAModeInfo - Pointer to VESA mode information structure or NULL if\n*                    error.\n*\n****************************************************************************/\n\nVESAModeInfo *SetVESAMode(long mode)\n{\n\tVESAModeInfo *vminfo;\n\n\t/* Get mode info */\n\tif ((vminfo = ReadVESAModeInfo(mode)) != NULL) {\n\n\t\t/* If the mode is supported, set it. */\n\t\tif ((vminfo->Attributes & 0x01) != 0) {\n\n\t\t\t#ifdef __WATCOMC__\n\t\t\t{\n\t\t\tunion REGS r;\n\t\t\t\n\t\t\tr.x.eax = 0x4F02;\n\t\t\tr.x.ebx = mode;\n\t\t\tint386(0x10, &r, &r);\n\n\t\t\tif (r.x.eax != 0x004F)\n\t\t\t\tvminfo = NULL;\n\t\t\t}\n\n\t\t\t#else  /* __WATCOMC__ */\n\n\t\t\t/* Set up function call */\n\t\t\t_regs.eax = 0x4F02;\n\t\t\t_regs.ebx = mode;\n\t\t\t_dx_real_int(0x10, &_regs);\n\n\t\t\tif (_regs.eax != 0x004F) {\n\t\t\t\tvminfo = NULL;\n\t\t\t}\n\t\t\t#endif /* __WATCOMC__ */\n\t\t}\n\t}\n\n\treturn (vminfo);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     ReadVESAModeInfo - Read the VESA mode information from the video card.\n*\n* SYNOPSIS\n*     VESAModeInfo = ReadVESAModeInfo(Mode)\n*\n*     VESAModeInfo *ReadVESAModeInfo(long);\n*\n* FUNCTION\n*     Read information about the specified mode from the VESA video BIOS.\n*\n* INPUTS\n*     Mode - Mode ID to get information about.\n*\n* RESULT\n*     VESAModeInfo - Pointer to VESA mode information structure or NULL if\n*                    error.\n*\n****************************************************************************/\n\nVESAModeInfo *ReadVESAModeInfo(long mode)\n{\n\tVESAModeInfo *vminfo = NULL;\n\n\t#ifdef __WATCOMC__\n\tunion REGS   r;\n\tstruct SREGS sr;\n\tRMInfo       rmi;\n\n\t/* Make sure we have real-mode memory. */\n\tif (_ModeInfoSeg != NULL) {\n\t\tmemset(MK_PTR(0, _ModeInfoSeg), 0, sizeof(VESAModeInfo));\n\n\t\t/* Get mode information. */\n\t\tmemset(&rmi, 0, sizeof(RMInfo));\n\t\trmi.eax = 0x4F01;\n\t\trmi.ecx = mode;\n\t\trmi.edi = 0;\n\t\trmi.es = _ModeInfoSeg;\n\n\t\tsegread(&sr);\n\t\tr.w.ax = 0x0300;\n\t\tr.w.bx = 0x0010;\n\t\tr.w.cx = 0;\n\t\tsr.es = FP_SEG(&rmi);\n\t\tr.x.edi = FP_OFF(&rmi);\n\t\tint386x(0x31, &r, &r, &sr);\n\n\t\tif ((r.x.cflag == 0) && (rmi.eax == 0x004F)) {\n\t\t\tvminfo = (VESAModeInfo *)MK_PTR(0, _ModeInfoSeg);\n\t\t}\n\t}\n\n\t#else  /* __WATCOMC__ */\n\n\t/* Make sure we have real-mode memory. */\n\tif (_rpModeInfo != NULL) {\n\n\t\t/* Clear the input buffer */\n\t\tFillRealMem(_rpModeInfo, 0, sizeof(VESAModeInfo));\n\n\t\t/* Set up function call */\n\t\t_regs.eax = 0x4F01;\n\t\t_regs.ecx = mode;\n\t\t_regs.edi = RP_OFF(_rpModeInfo);\n\t\t_regs.es = RP_SEG(_rpModeInfo);\n\t\t_dx_real_int(0x10, &_regs);\n\n\t\tif (_regs.eax == 0x004F) {\n\t\t\tReadRealMem(&_ModeInfo, _rpModeInfo, sizeof(VESAModeInfo));\n\t\t\tvminfo = &_ModeInfo;\n\t\t}\n\t}\n\t#endif /* __WATCOMC__ */\n\n\treturn (vminfo);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     SetVESAWindow - Set VESA window A's start address.\n*\n* SYNOPSIS\n*     Error = SetVESAWindow(GrainNum)\n*\n*     long SetVESAWindow(long);\n*\n* FUNCTION\n*     This function invokes the Window Function, whose address is provided\n*     in the VESAModeInfo structure. The 'GrainNum' must be in granularity\n*     units as specified in the ModeInfo structure.\n*\n* INPUTS\n*     GrainNum - Granularity number to set window to.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid SetVESAWindow(long grain)\n{\n\t#ifdef __WATCOMC__\n\t#else  /* __WATCOMC__ */\n\n  RMC_BLK regp;\n\t\n\tregp.eax = 0x4F05;\n\tregp.ebx = 0x00;\n\tregp.edx = grain;\n\t_dx_call_real(_ModeInfo.WinFunc, &regp, 0);\n\t#endif /* __WATCOMC__ */\n}\n\n"
  },
  {
    "path": "VQ/VQM32/VESAVID.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMVESAVID_H\n#define VQMVESAVID_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     VESAVid.h (32-Bit protected mode)\n* \n* DESCRIPTION\n*     VESA video manager definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n#ifndef __WATCOMC__\n#include <pharlap.h>\n#else\n#include \"realmode.h\"\n#endif\n\n/*---------------------------------------------------------------------------\n * VESA Video Modes\n *-------------------------------------------------------------------------*/\n\n#define\tVESA_640X400_256   0x100\n#define\tVESA_640X480_256   0x101\n#define\tVESA_800X600_16    0x102\n#define\tVESA_800X600_256   0x103\n#define\tVESA_1024X768_16   0x104\n#define\tVESA_1024X768_256  0x105\n#define\tVESA_1280X400_16   0x106\n#define\tVESA_1280X400_256  0x107\n#define\tVESA_TEXT_80X60    0x108\n#define\tVESA_TEXT_132X25   0x109\n#define\tVESA_TEXT_132X60   0x10C\n#define\tVESA_320X200_32K_1 0x10D\n#define\tVESA_320X200_32K_2 0x10E\n#define\tVESA_640X480_32K   0x110\n#define\tVESA_640X480_65K   0x111\n#define\tVESA_640X480_16M   0x112\n#define\tVESA_800X600_32K   0x113\n#define\tVESA_800X600_65K   0x114\n#define\tVESA_1024X768_32K  0x116\n#define\tVESA_1024X768_65K  0x117\n\n#define\tVESA_MIN VESA_640X400_256\n#define\tVESA_MAX VESA_1024X768_65K\n\n/*---------------------------------------------------------------------------\n * Structure definitions\n *-------------------------------------------------------------------------*/\n\n/* VESAInfo - General information about this VESA implementation.\n *            (Filled in by VESA BIOS Function 0)\n *\n * Signature    - Will always be 'VESA'\n * Version      - Version #\n * OEMString    - OEM ID string\n * Capabilities - Not defined by VESA yet\n * AvailModes   - List of available modes; terminated with -1 (0xffff)\n * TotalMemory  - ???\n * Reserved     - Pads structure to 256 bytes total\n */\ntypedef struct _VESAInfo {\n\tchar           Signature[4];\n\tunsigned short Version;\n\tREALPTR        OEMString;\n\tunsigned long  Capabilities;\n\tREALPTR        AvailModes;\n\tunsigned short TotalMemory;\n\tunsigned char  Reserved[236];\n} VESAInfo;\n\n/* VESAModeInfo - Information about this VESA mode.\n *                (Filled in by VESA BIOS Function 1)\n *\n * Attributes       - bit 0: 1 = mode is supported\n *                    bit 1: 1 = optional info available\n *                    bit 2: 1 = std BIOS output functions valid in this mode\n *                    bit 3: 0 = monochrome, 1 = color\n *                    bit 4: 0 = text mode, 1 = graphics\n * WinA_Attributes  - bit 0 = window exists, bit 1=readable, bit 2= writable\n * WinB_Attributes  - bit 0 = window exists, bit 1=readable, bit 2= writable\n * WinGranularity   - smallest address boundary window can be placed upon;\n *                    size is in KB (ie 64, 32, 4)\n * WinSize          - size of windows in KB (ie 64, 32)\n * WinA_Segment     - location of Window A in CPU space (usually 0xa000)\n * WinB_Segment     - location of Window B in CPU space (usually 0xb000)\n * WinFunc          - address of window-setting function (This is provided \n *                    as an alternative to Int 10 for speed.)\n * BytesPerScanline - # bytes per scan line\n * \n * Optional info (available if bit 1 of Attributes is set):\n *\n * XRes             - X-resolution\n * YRes             - Y-resolution\n * XCharSize        - Horizontal size of char cell\n * YCharSize        - Vertical size of char cell\n * NumPlanes        - # of memory planes (???)\n * BitsPerPixel     - # bites per pixel\n * NumBanks         - # of banks (ie planes)\n * MemoryModel      - 00h = Text mode\n *                    01h = CGA mode\n *                    02h = Hercules\n *                    03h = 4 plane planar mode\n *                    04h = packed pixel mode (1 byte/pixel)\n *                    05h = non-chain 4, 256-color mode\n *                    06-0Fh = \n *                    10-FFh = OEM-specific\n * BankSize         - Bank size in KB\n */\ntypedef struct _VESAModeInfo {\n\tunsigned short Attributes;\n\tunsigned char  WinA_Attributes;\n\tunsigned char  WinB_Attributes;\n\tunsigned short WinGranularity;\n\tunsigned short WinSize;\n\tunsigned short WinA_Segment;\n\tunsigned short WinB_Segment;\n\tREALPTR        WinFunc;\n\tunsigned short BytesPerScanline;\n\tunsigned short XRes;\n\tunsigned short YRes;\n\tunsigned char  XCharSize;\n\tunsigned char  YCharSize;\n\tunsigned char  NumPlanes;\n\tunsigned char  BitsPerPixel;\n\tunsigned char  NumBanks;\n\tunsigned char  MemoryModel;\n\tunsigned char  BankSize;\n\tunsigned char  NumInputPages;\n\tunsigned char  Reserved;\n\tunsigned char  RedMaskSize;\n\tunsigned char  RedFieldPosition;\n\tunsigned char  GreenMaskSize;\n\tunsigned char  GreenFieldPosition;\n\tunsigned char  BlueMaskSize; \n\tunsigned char  BlueFieldPosition;\n\tunsigned char  RsvdMaskSize;\n\tunsigned char  RsvdFieldPosition;\n\tunsigned char  DirectColorModeInfo;\n\tunsigned char  pad[216];\n} VESAModeInfo;\n\n/*---------------------------------------------------------------------------\n * Function prototypes\n *-------------------------------------------------------------------------*/\n\nlong InitVESA(void);\nvoid UninitVESA(void);\nVESAModeInfo *SetVESAMode(long mode);\nVESAModeInfo *ReadVESAModeInfo(long mode);\nvoid SetVESAWindow(long grain_num);\n\n#endif /* VQMVESAVID_H */\n\n"
  },
  {
    "path": "VQ/VQM32/VESAVID.I",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*       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\n;*\n;*----------------------------------------------------------------------------\n;*\n;* FILE\n;*     vesavid.i\n;*\n;* DESCRIPTION\n;*     VESA video manager definitions. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;****************************************************************************\n\n;----------------------------------------------------------------------------\n; VESA video modes\n;----------------------------------------------------------------------------\n\nVESA_640X400_256   EQU\t0x100\nVESA_640X480_256   EQU\t0x101\nVESA_800X600_16    EQU\t0x102\nVESA_800X600_256   EQU\t0x103\nVESA_1024X768_16   EQU\t0x104\nVESA_1024X768_256  EQU\t0x105\nVESA_1280X400_16   EQU\t0x106\nVESA_1280X400_256  EQU\t0x107\nVESA_TEXT_80X60    EQU\t0x108\nVESA_TEXT_132X25   EQU\t0x109\nVESA_TEXT_132X60   EQU\t0x10C\nVESA_320X200_32K_1 EQU\t0x10D\nVESA_320X200_32K_2 EQU\t0x10E\nVESA_640X480_32K   EQU\t0x110\nVESA_640X480_65K   EQU\t0x111\nVESA_640X480_16M   EQU\t0x112\nVESA_800X600_32K   EQU\t0x113\nVESA_800X600_65K   EQU\t0x114\nVESA_1024X768_32K  EQU\t0x116\nVESA_1024X768_65K  EQU\t0x117\n\nVESA_MIN EQU\tVESA_640X400_256\nVESA_MAX EQU\tVESA_1024X768_65K\n\n;----------------------------------------------------------------------------\n; Structure definitions\n;----------------------------------------------------------------------------\n\n; VESAInfo - General information about this VESA implementation.\n;            (Filled in by VESA BIOS Function 0)\n;\n; Signature    - Will always be 'VESA'\n; Ver          - Version #\n; OEMString    - OEM ID string\n; Capabilities - Not defined by VESA yet\n; AvailModes   - List of available modes; terminated with -1 (0xffff)\n; TotalMemory  - ???\n; Reserved     - Pads structure to 256 bytes total\n\n\tSTRUC\tVESAInfo\nSignature\tDD\t?\nVer\tDW\t?\nOEMString\tDD\t?\nCapabilities\tDD\t?\nAvailModes\tDD\t?\nTotalMemory\tDW\t?\nReserved\tDB\t236 DUP (?)\n\tENDS\tVESAInfo\n\n; VESAModeInfo - Information about this VESA mode.\n;                (Filled in by VESA BIOS Function 1)\n;\n; Attributes       - bit 0: 1 = mode is supported\n;                    bit 1: 1 = optional info available\n;                    bit 2: 1 = std BIOS output functions valid in this mode\n;                    bit 3: 0 = monochrome, 1 = color\n;                    bit 4: 0 = text mode, 1 = graphics\n; WinA_Attributes  - bit 0 = window exists, bit 1=readable, bit 2= writable\n; WinB_Attributes  - bit 0 = window exists, bit 1=readable, bit 2= writable\n; WinGranularity   - smallest address boundary window can be placed upon;\n;                    size is in KB (ie 64, 32, 4)\n; WinSize          - size of windows in KB (ie 64, 32)\n; WinA_Segment     - location of Window A in CPU space (usually 0xa000)\n; WinB_Segment     - location of Window B in CPU space (usually 0xb000)\n; WinFunc          - address of window-setting function (This is provided \n;                    as an alternative to Int 10 for speed.)\n; BytesPerScanline - # bytes per scan line\n; \n; Optional info (available if bit 1 of Attributes is set):\n;\n; XRes             - X-resolution\n; YRes             - Y-resolution\n; XCharSize        - Horizontal size of char cell\n; YCharSize        - Vertical size of char cell\n; NumPlanes        - # of memory planes (???)\n; BitsPerPixel     - # bites per pixel\n; NumBanks         - # of banks (ie planes)\n; MemoryModel      - 00h = Text mode\n;                    01h = CGA mode\n;                    02h = Hercules\n;                    03h = 4 plane planar mode\n;                    04h = packed pixel mode (1 byte/pixel)\n;                    05h = non-chain 4, 256-color mode\n;                    06-0Fh = \n;                    10-FFh = OEM-specific\n; BankSize         - Bank size in KB\n\n\t\tSTRUC\tVESAModeInfo \nAttributes\t\tDW\t?\nWinA_Attributes\tDB\t?\nWinB_Attributes\tDB\t?\nWinGranularity\tDW\t?\nWinSize\t\tDW\t?\nWinA_Segment\t\tDW\t?\nWinB_Segment\t\tDW\t?\nWinFunc\t\tDD\t?\nBytesPerScanline\tDW\t?\nXRes\t\tDW\t?\nYRes\t\tDW\t?\nXCharSize\t\tDB\t?\nYCharSize\t\tDB\t?\nNumPlanes\t\tDB\t?\nBitsPerPixel\t\tDB\t?\nNumBanks\t\tDB\t?\nMemoryModel\t\tDB\t?\nBankSize\t\tDB\t?\nNumInputPages\t\tDB\t?\nReserved\t\tDB\t?\nRedMaskSize\t\tDB\t?\nRedFieldPosition\tDB\t?\nGreenMaskSize\t\tDB\t?\nGreenFieldPosition\tDB\t?\nBlueMaskSize\t\tDB\t?\nBlueFieldPosition\tDB\t?\nRsvdMaskSize\t\tDB\t?\nRsvdFieldPosition\tDB\t?\nDirectColorModeInfo\tDB\t?\npad\t\tDB\t216 DUP (?)\n\t\tENDS\tVESAModeInfo\n\n;----------------------------------------------------------------------------\n; Function definitions\n;----------------------------------------------------------------------------\n\n\tGLOBAL C InitVESA:PROC\n\tGLOBAL C UninitVESA:PROC\n\tGLOBAL C SetVESAMode:PROC\n\tGLOBAL C ReadVESAModeInfo:PROC\n\tGLOBAL C SetVESAWindow:PROC\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     SET_WINDOW - Sets window A to the specified bank.\n;\n; SYNOPSIS\n;     SET_WINDOW GrainNum\n;\n; FUNCTION\n;     This routine uses the C Set_Window function rather than going through\n;     the BIOS, for two reasons: (1) Speed, and (2) On the Cirrus Logic 54xx\n;     VESA cards, BIOS calls make noise while playing digital audio.\n;\n; INPUTS\n;     GrainNum - Granularity number.\n;\n; RESULT\n;     NONE\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tSET_WINDOW grain_num\n\tpush\tesi\n\tpush\tedi\n\tpush\tes\n\tcall\tSetVESAWindow C,grain_num\n\tpop\tes\n\tpop\tedi\n\tpop\tesi\n\tENDM\n\n"
  },
  {
    "path": "VQ/VQM32/VGA.I",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     vga.i\n;*\n;* DESCRIPTION\n;*     VGA hardware definitions. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;****************************************************************************\n\n;----------------------------------------------------------------------------\n; VGA Registers\n;----------------------------------------------------------------------------\n\nR_SEQUENCER\t\tEQU\t03C4h\t;Sequencer Controller Index reg\nSEQ_RESET\t\tEQU\t00h\t;Reset\nSEQ_MAP_MASK\t\tEQU\t02h\t;Index in Sequencer of Map Mask reg\nSEQ_MEMORY_MODE\tEQU\t04h\t;Memory Mode\n\nR_GRAPHICS_CONTROLLER\tEQU\t03CEh\t;Graphics Controller Index reg\nGC_READ_MAP\t\tEQU\t04h\t;Index in GController of Read Map reg\nGC_MODE\t\tEQU\t05h\t;Read/Write Modes\nGC_MISC\t\tEQU\t06h\t;Read/Write Modes\nGC_BITMASK\t\tEQU\t08h\t;Index in GController of BitMask reg\n\nR_CRT_CONTROLLER\tEQU\t03D4h\t;CRT Controller Index reg\nCRT_VERT_TOTAL\tEQU\t06h\t;Vertical total\nCRT_OVERFLOW\t\tEQU\t07h\t;Overflow\nCRT_MAX_SCANLINE\tEQU\t09h\t;Max scan line\nCRT_STARTADDR_HIGH\tEQU\t0Ch\t;Bitmap start address high byte\nCRT_STARTADDR_LOW\tEQU\t0Dh\t;Bitmap start address low byte\nCRT_VERTRET_START\tEQU\t010h\t;Vertical retrace pulse start\nCRT_VERTRET_END\tEQU\t011h\t;Vertical retrace pulse end\nCRT_VERTDISP_END\tEQU\t012h\t;Vertical display end\nCRT_UNDERLINE\t\tEQU\t014h\t;Underline location\nCRT_START_VB\t\tEQU\t015h\t;Start vertical blank\nCRT_END_VB\t\tEQU\t016h\t;End vertical blank\nCRT_MODE_CONTROL\tEQU\t017h\t;Mode control\nR_MISC_OUTPUT\t\tEQU\t03C2h\t;Miscellaneous Output reg\n\n;----------------------------------------------------------------------------\n; Palette Registers\n;----------------------------------------------------------------------------\n\nPEL_READ_ADDR\t\tEQU\t03C7h\nPEL_WRITE_ADDR\tEQU\t03C8h\nPEL_DATA\t\tEQU\t03C9h\n\n;----------------------------------------------------------------------------\n; XMode planes, for the Map Mask register\n;----------------------------------------------------------------------------\n\nXPLANE_1\tEQU\t1\nXPLANE_2\tEQU\t2\nXPLANE_3\tEQU\t4\nXPLANE_4\tEQU\t8\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     SET_PLANE - Set an XMode plane.\n;\n; SYNOPSIS\n;     SET_PLANE plane\n;\n; INPUTS\n;     plane - Number of Xmode plane to set.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tSET_PLANE plane\n\tmov\tedx,R_SEQUENCER\n\tmov\teax,SEQ_MAP_MASK\n\tout\tdx,al\n\tinc\tedx\n\tmov\teax,plane\n\tout\tdx,al\n\tENDM\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     SET_BITMASK - Set the BitMask register.\n;\n; SYNOPSIS\n;     SET_BITMASK mask\n;\n; INPUTS\n;     mask - Bitmask to use.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tSET_BITMASK mask\n\tmov\tedx,R_GRAPHICS_CONTROLLER\n\tmov\teax,GC_BITMASK\n\tout\tdx,al\n\tinc\tedx\n\tmov\teax,mask\n\tout\tdx,al\n\tENDM\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     SET_WRITEMODE - Set the VGA writemode.\n;\n; SYNOPSIS\n;     SET_WRITEMODE mode\n;\n; INPUTS\n;     mode - Write mode.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tSET_WRITEMODE mode\n\tmov\tedx,R_GRAPHICS_CONTROLLER\n\tmov\teax,GC_MODE\n\tout\tdx,al\n\tinc\tedx\n\tin\tal,dx\t;Read the register\n\tand\tal,0FCh\t;Turn off 2 lower bits\n\tor\tal,mode\t;Set write mode\n\tout\tdx,al\n\tENDM\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     OUTPORT - Output data to a VGA register.\n;\n; SYNOPSIS\n;     OUTPORT port,register,data\n;\n; INPUTS\n;     port     - Port address.\n;     register - Register to write to.\n;     data     - Data to write.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tOUTPORT port,register,data\n\tmov\tedx,port\n\tmov\tal,register\n\tout\tdx,al\n\tinc\tedx\n\tmov\tal,data\n\tout\tdx,al\n\tENDM\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     INPORT - Input data from a VGA register.\n;\n; SYNOPSIS\n;     data = INPORT port,register\n;\n; INPUTS\n;     port     - Port address.\n;     register - Register to read from.\n;\n; RESULT\n;     data - Value read from port in AL.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tINPORT port,register\n\tmov\tedx,port\n\tmov\tal,register\n\tout\tdx,al\n\tinc\tedx\n\tin\tal,dx\n\tENDM\n\n"
  },
  {
    "path": "VQ/VQM32/VIDEO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     video.c\n*\n* DESCRIPTION\n*     Video mode setting. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     SetVideoMode   - Set the video mode.\n*     GetDisplayInfo - Get the display info for the current video mode.\n*     GetVBIBit      - Get the vertical blank bit polarity.\n*\n****************************************************************************/\n\n#include <stdlib.h>\n#include <dos.h>\n#include <conio.h>\n\n#ifndef __WATCOMC__\n#include <pharlap.h>\n#include <pldos32.h>\n#else\n#include \"realmode.h\"\n#endif\n\n#include \"video.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\nstatic DisplayInfo _Display = {-1,0,0,0,NULL};\n\n\n/****************************************************************************\n*\n* NAME\n*     SetVideoMode - Set the display to the specified video mode.\n*\n* SYNOPSIS\n*     DisplayInfo = SetVideoMode(Mode)\n*\n*     DisplayInfo *SetVideoMode(long);\n*\n* FUNCTION\n*     Set the video display adapter to the desired video mode.\n*\n* INPUTS\n*     Mode - Desired video mode.\n*\n* RESULT\n*     DisplayInfo - Pointer to DisplayInfo structure, otherwise 0 for error.\n*\n****************************************************************************/\n\nDisplayInfo *SetVideoMode(long mode)\n{\n\t#ifdef __WATCOMC__\n\tunion REGS   regs;\n\tstruct SREGS sregs;\n\t#else\n\tunion _REGS  regs;\n\t#endif\n\n\tDisplayInfo  *di = NULL;\n\tVESAModeInfo *vminfo;\n\tlong         error;\n\n\t/* Initialize the video manager on the first invocation of\n\t * SetVideoMode()\n\t */\n\tif (_Display.Mode == -1) {\n\t\t_Display.VBIbit = TestVBIBit();\n\t}\n\n\t/* Clear the VRAM before enabling the mode so that there is\n\t * not any garbage on the screen.\n\t */\n\tClearVRAM();\n\n\t/* If the requested mode is the same as the current mode then\n\t * we do not need to do anything.\n\t */\n\tif (mode != _Display.Mode) {\n\n\t\t/* Uninitialize VESA if the previous mode was a VESA mode and the new\n\t\t * mode is not.\n\t\t */\n\t\tif (((_Display.Mode >= VESA_MIN) && (_Display.Mode <= VESA_MAX))\n\t\t\t\t&& ((mode < VESA_MIN) && (mode > VESA_MAX))) {\n\n\t\t\tUninitVESA();\n\t\t}\n\n\t\t/* Set display to an XMode. */\n\t\tif ((mode >= XMODE_MIN) && (mode <= XMODE_MAX)) {\n\t\t\tSetXMode(mode);\n\t\t\tClearXMode();\n\t\t\tSetupXPaging();\n\t\t\tShowXPage(0);\n\t\t\t_Display.Mode = mode;\n\t\t\t_Display.Extended = NULL;\n\t\t\tdi = &_Display;\n\n\t\t\t/* Set display resolution information */\n\t\t\tswitch (mode) {\n\t\t\t\tcase XMODE_320X200:\n\t\t\t\t\t_Display.XRes = 320;\n\t\t\t\t\t_Display.YRes = 200;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase XMODE_320X240:\n\t\t\t\t\t_Display.XRes = 320;\n\t\t\t\t\t_Display.YRes = 240;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase XMODE_320X400:\n\t\t\t\t\t_Display.XRes = 320;\n\t\t\t\t\t_Display.YRes = 400;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase XMODE_320X480:\n\t\t\t\t\t_Display.XRes = 320;\n\t\t\t\t\t_Display.YRes = 480;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase XMODE_360X400:\n\t\t\t\t\t_Display.XRes = 360;\n\t\t\t\t\t_Display.YRes = 400;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase XMODE_360X480:\n\t\t\t\t\t_Display.XRes = 360;\n\t\t\t\t\t_Display.YRes = 480;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\telse if ((mode >= VESA_MIN) && (mode <= VESA_MAX)) {\n\n\t\t\t/* Initialize the VESA manager if the current mode is not a VESA\n\t\t\t * mode.\n\t\t\t */\n\t\t\tif ((_Display.Mode < VESA_MIN) || (_Display.Mode > VESA_MAX)) {\n\t\t\t\t error = InitVESA();\n\t\t\t}\n\n\t\t\tif (!error) {\n\n\t\t\t\t/* Set the display to MCGA before going into VESA. This needs to be\n\t\t\t\t * done to ensure that the video ram selector is initialized. This\n\t\t\t\t * fixes a bug in some VESA BIOS'.\n\t\t\t\t */\n\t\t\t\t#ifndef __WATCOMC__\n\t\t\t\tregs.x.ax = mode;\n\t\t\t\t_int86(0x10, &regs, &regs);\n\t\t\t\t#else\n\t\t\t\tsegread(&sregs);\n\t\t\t\tregs.x.eax = mode;\n\t\t\t\tint386x(0x10, &regs, &regs, &sregs);\n\t\t\t\t#endif\n\n\t\t\t\tif ((vminfo = SetVESAMode(mode)) != NULL) {\n\t\t\t\t\t_Display.Mode = mode;\n\t\t\t\t\t_Display.XRes = (long)vminfo->XRes;\n\t\t\t\t\t_Display.YRes = (long)vminfo->YRes;\n\t\t\t\t\t_Display.Extended = vminfo;\n\t\t\t\t\tdi = &_Display;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t#ifndef __WATCOMC__\n\t\t\tregs.x.ax = mode;\n\t\t\t_int86(0x10, &regs, &regs);\n\t\t\t#else\n\t\t\tsegread(&sregs);\n\t\t\tregs.x.eax = mode;\n\t\t\tint386x(0x10, &regs, &regs, &sregs);\n\t\t\t#endif\n\n\t\t\t_Display.Mode = mode;\n\t\t\t_Display.XRes = 320;\n\t\t\t_Display.YRes = 200;\n\t\t\t_Display.Extended = NULL;\n\t\t\tdi = &_Display;\n\t\t}\n\t} else {\n\t\tdi = &_Display;\n\t}\n\n\treturn (di);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetDisplayInfo - Get the display info for the current video mode.\n*\n* SYNOPSIS\n*     DisplayInfo = GetDisplayInfo()\n*\n*     DisplayInfo *GetDisplayInfo(void);\n*\n* FUNCTION\n*     Return a pointer to the current display information structure.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     DisplayInfo - Pointer to initialized display info or NULL if not valid.\n*\n****************************************************************************/\n\nDisplayInfo *GetDisplayInfo(void)\n{\n\tif (_Display.Mode != 0) {\n\t\treturn (&_Display);\n\t} else {\n\t\treturn (NULL);\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetVBIBit - Get the vertical blank bit polarity.\n*\n* SYNOPSIS\n*     VBIBit = GetVBIBit()\n*\n*     long GetVBIBit(void);\n*\n* FUNCTION\n*     Return the polarity of the vertical blank bit.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     VBIBit - Vertical blank bit polarity.\n*\n****************************************************************************/\n\nlong GetVBIBit(void)\n{\n\treturn (_Display.VBIbit);\n}\n\n"
  },
  {
    "path": "VQ/VQM32/VIDEO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMVIDEO_H\n#define VQMVIDEO_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Video.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     Video manager definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\vesavid.h>\n\n/*---------------------------------------------------------------------------\n * VGA video modes\n *-------------------------------------------------------------------------*/\n\n#define\tTEXT 0x02\n#define\tMCGA 0x13\n#define\tXMODE_320X200 0x50\n#define\tXMODE_320X240 0x51\n#define\tXMODE_320X400 0x52\n#define\tXMODE_320X480 0x53\n#define\tXMODE_360X400 0x54\n#define\tXMODE_360X480 0x55\n\n#define\tXMODE_MIN 0x50\n#define\tXMODE_MAX 0x55\n\n/*---------------------------------------------------------------------------\n * Structure definitions\n *-------------------------------------------------------------------------*/\n\n/* DisplayInfo - Information about the current display.\n *\n * Mode     - Mode identification.\n * XRes     - X resolution of mode.\n * YRes     - Y resolution of mode.\n * VBIbit   - Polarity of vertical blank bit.\n * Extended - Pointer to mode specific data structure.\n */\ntypedef struct _DisplayInfo {\n\tlong Mode;\n\tlong XRes;\n\tlong YRes;\n\tlong VBIbit;\n\tvoid *Extended;\n} DisplayInfo;\n\n/*---------------------------------------------------------------------------\n * Function prototypes\n *-------------------------------------------------------------------------*/\n\nDisplayInfo *SetVideoMode(long mode);\nDisplayInfo *GetDisplayInfo(void);\nlong TestVBIBit(void);\nlong GetVBIBit(void);\n\nvoid SetupXPaging(void);\nvoid FlipXPage(void);\nunsigned char *GetXHidPage(void);\nunsigned char *GetXSeenPage(void);\nvoid DisplayXPage(long page);\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid cdecl WaitNoVB(short vbibit);\nvoid cdecl WaitVB(short vbibit);\nvoid cdecl ClearVRAM(void);\nlong cdecl SetXMode(long mode);\nvoid cdecl ClearXMode(void);\nvoid cdecl ShowXPage(unsigned long StartOffset);\nvoid cdecl Xmode_BufferCopy_320x200(void *buff, void *screen);\nvoid cdecl Xmode_Blit(void *buffer, void *screen, long imgwidth, long imgheight);\nvoid cdecl MCGA_BufferCopy(unsigned char *buffer, unsigned char *dummy);\nvoid cdecl MCGA_Blit(unsigned char *buffer, unsigned char *screen,\n\t\tlong imgwidth, long imgheight);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMVIDEO_H */\n\n"
  },
  {
    "path": "VQ/VQM32/VIDEO.I",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*       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\n;*\n;*----------------------------------------------------------------------------\n;*\n;* FILE\n;*     video.i\n;*\n;* DESCRIPTION\n;*     Video manager definitions. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;****************************************************************************\n\n\tINCLUDE\t\"vesavid.i\"\n\n;----------------------------------------------------------------------------\n; Video Modes\n;----------------------------------------------------------------------------\n\nTEXT\tEQU\t002h\nMCGA\tEQU\t013h\nXMODE_320X200\tEQU\t050h\nXMODE_320X240\tEQU\t051h\nXMODE_320X400\tEQU\t052h\nXMODE_320X480\tEQU\t053h\nXMODE_360X400\tEQU\t054h\nXMODE_360X480\tEQU\t055h\n\n;----------------------------------------------------------------------------\n; Structure definitions\n;----------------------------------------------------------------------------\n\n; DisplayInfo - Information about the current display.\n;\n; Mode     - Mode identification\n; XRes     - X resolution\n; YRes     - Y resolution\n; VBIbit   - Polarity of vertical blank bit.\n; Extended - Pointer to mode specified data structure.\n\n\tSTRUC\tDisplayInfo\nMode\tDD\t?\nXRes\tDD\t?\nYRes\tDD\t?\nVBIbit\tDD\t?\nExtended\tDD\t?\n\tENDS\tDisplayInfo\n\n;----------------------------------------------------------------------------\n; Function definitions\n;----------------------------------------------------------------------------\n\n\tGLOBAL C GetDisplayInfo:NEAR\n\tGLOBAL C GetVBIBit:NEAR\n\n"
  },
  {
    "path": "VQ/VQM32/XMODE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     xmode.asm\n;*\n;* DESCRIPTION\n;*     Xmode graphics display routines. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Bill Randolph\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     Febuary 3, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     SetXMode                 - Set the specified Xmode video mode.\n;*     ClearXMode               - Clear the XMode VRAM.\n;*     ShowXPage                - Set a specific page for XMode display.\n;*     Xmode_BufferCopy_320x200 - Copy 320x200 buffer to Xmode VRAM.\n;*     Xmode_Blit               - Bit blit a block to the XMode display.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"vga.i\"\n\tINCLUDE\t\"video.i\"\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     SetXMode - Set the specified Xmode video mode.\n;*\n;* SYNOPSIS\n;*     Error = SetXMode(Mode)\n;*\n;*     long SetXMode(long);\n;*\n;* FUNCTION\n;*     This routines set the current display adapter to the specified Xmode.\n;*     Portions of this routine were take from Dr. Dobb's, written in C, and\n;*     portions were taken from Dominic's 320x200 code.\n;*\n;* INPUTS\n;*     Mode - Xmode mode to set display to.\n;*\n;* RESULT\n;*     Error - 0 if successful, or -1 if error.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC SetXMode:NEAR\n\tPROC\tSetXMode C NEAR USES edx\n\n\tARG\tmode:DWORD\n\n??Set320x200:\n\tcmp\t[mode],XMODE_320X200\t;320x200?\n\tjne\t??Set320x240\n\n\tIF\t0\n\tmov\teax,MCGA\n\tint\t10h\n\n;\tMemory Mode:\n;\tbit3 (chain) = 0 (planes are accessed via Map Mask)\n;\tbit2 (odd/even) = 1 (use sequential addressing mode)\n\n\tINPORT R_SEQUENCER,SEQ_MEMORY_MODE\n\tand\tal,not 08h\t\t\t;Turn off chain 4\n\tor\tal,04h\t\t\t;Turn off odd/even\n\tout\tdx,al\n\n\tINPORT R_GRAPHICS_CONTROLLER,GC_MODE\n\tand\tal,not 10h\t\t\t;Turn off odd/even\n\tout\tdx,al\n\n\tINPORT R_GRAPHICS_CONTROLLER,GC_MISC\n\tand\tal,not 02h\t\t\t;Turn off chain\n\tout\tdx,al\n\n\tOUTPORT R_SEQUENCER,SEQ_MAP_MASK,0Fh\n\tINPORT R_CRT_CONTROLLER, CRT_MAX_SCANLINE\n\tand\tal,not 1fh\t\t\t;Clear low 5 bits\n\tor\tal,1     \t\t\t;Mode = 0 => 400 lines\n\tout\tdx,al\t\t\t;Mode =1  => 200\n\n\tINPORT R_CRT_CONTROLLER,CRT_UNDERLINE\n\tand\tal,not 40h\t\t\t;Turn off doubleword\n\tout\tdx,al\n\n\tINPORT R_CRT_CONTROLLER,CRT_MODE_CONTROL\n\tor\tal,40h\t\t\t;Turn on byte mode bit,\n\tout\tdx,al\t    \t\t; so mem scanned linearly\n\tENDIF\n\n;\tThe following section of code is from Roger Stevens' XMode\n;\texample code; it's the same as 320x400, except the value sent\n;\tto CRT_MAX_SCANLINE is 41, not 40.\n\n\tmov\teax,MCGA\n\tint\t10h\n\n\tOUTPORT R_SEQUENCER,SEQ_MEMORY_MODE,06h\n\tINPORT R_CRT_CONTROLLER,CRT_VERTRET_END\n\tand\tal,07Fh\n\tout\tdx,al\n\n\tOUTPORT R_CRT_CONTROLLER,CRT_MAX_SCANLINE,41h\n\tOUTPORT R_CRT_CONTROLLER,CRT_UNDERLINE,00h\n\tOUTPORT R_CRT_CONTROLLER,CRT_MODE_CONTROL,0E3h\n\n\tmov\teax,0\n\tjmp\t??Done\n\n??Set320x240:\n\tcmp\t[mode],XMODE_320X240\t;320x240?\n\tjne\t??Set320x400\n\n;\tStart by setting MCGA to let the BIOS program the registers;\n;\tthen, reprogram the registers that need it.\n\n\tmov\teax,MCGA\n\tint\t10h\n\n;\tMemory Mode:\n;\tbit3 (chain) = 0 (planes are accessed via Map Mask)\n;\tbit2 (odd/even) = 1 (use sequential addressing mode)\n;\tbit1 (extended mem) = 1 (>64K video RAM)\n;\tbit0 (alpha/graph) = 0 (graphics mode)\n\n\tOUTPORT R_SEQUENCER,SEQ_MEMORY_MODE,06h\n\n;\tIssue a Sequencer Reset\n\tOUTPORT R_SEQUENCER,SEQ_RESET,01h\n\n;\tMisc Output: (set to 1100 0011)\n;\tBit 7: VSync polarity (1=negative)\n;\tBit 6: HSync polarity (1=negative)\n;\tBit 5: page bit for odd/even (0=low 64K)\n;\tBit 4: Video drivers (0=enable)\n;\tBit 3,2: clock select (0=25-MHz clock)\n;\tBit 1: VRAM access (1 = enable CPU to access)\n;\tBit 0: I/O Address (1=color emulation)\n\n\tmov\tedx,R_MISC_OUTPUT\n\tmov\tal,0C3h\n\tout\tdx,al\n\n;\tClear Sequencer Reset\n\n\tOUTPORT R_SEQUENCER,SEQ_RESET,03h\n\n;\tRead Vertical Retrace End, and with 07f to clear high bit\n;\t(clearing bit 7 enables writing to registers 0-7)\n\n\tINPORT R_CRT_CONTROLLER,CRT_VERTRET_END\n\tand\tal,07Fh\n\tout\tdx,al\n\n;\tProgram the CRT Controller to display 480 scanlines, but to\n;\tdouble each scanline so only 240 are displayed:\n\n\tOUTPORT R_CRT_CONTROLLER,CRT_UNDERLINE,00h\n\tOUTPORT R_CRT_CONTROLLER,CRT_MODE_CONTROL,0E3h\n\tOUTPORT R_CRT_CONTROLLER,CRT_VERT_TOTAL,0Dh\n\tOUTPORT R_CRT_CONTROLLER,CRT_OVERFLOW,03Eh\n\tOUTPORT R_CRT_CONTROLLER,CRT_VERTRET_START,0EAh\n\tOUTPORT R_CRT_CONTROLLER,CRT_VERTRET_END,0ACh\n\tOUTPORT R_CRT_CONTROLLER,CRT_VERTDISP_END,0DFh\n\tOUTPORT R_CRT_CONTROLLER,CRT_START_VB,0E7h\n\tOUTPORT R_CRT_CONTROLLER,CRT_END_VB,06h\n\tOUTPORT R_CRT_CONTROLLER,CRT_MAX_SCANLINE,041h\n\n\txor\teax,eax\n\tjmp\t??Done\n\n??Set320x400:\n\tcmp\t[mode],XMODE_320X400\t;320x400\n\tjne\t??Set320x480\n\n\tmov\teax,MCGA\n\tint\t10h\n\n\tOUTPORT R_SEQUENCER,04h,06h\n\tINPORT R_CRT_CONTROLLER,011h\n\tand\tal,07Fh\n\tout\tdx,al\n\n\tOUTPORT R_CRT_CONTROLLER,09h,40h\n\tOUTPORT R_CRT_CONTROLLER,014h,00h\n\tOUTPORT R_CRT_CONTROLLER,017h,0E3h\n\n\txor\teax,eax\n\tjmp\t??Done\n\n??Set320x480:\n\tcmp\t[mode],XMODE_320X480\t;320x480?\n\tjne\t??Set360x400\n\n\tmov\teax,MCGA\n\tint\t10h\n\n\tmov\tedx,R_SEQUENCER\n\tmov\teax,0604h\n\tout\tdx,ax\n\n\tmov\teax,0100h\n\tout\tdx,ax\n\n\tmov\tedx,R_MISC_OUTPUT\n\tmov\tal,0C3h\n\tout\tdx,al\n\n\tmov\tedx,R_SEQUENCER\n\tmov\teax,0300h\n\tout\tdx,ax\n\n\tmov\tedx,R_CRT_CONTROLLER\n\tmov\tal,011h\n\tout\tdx,al\n\n\tmov\tedx,03D5h\n\tin\tal,dx\n\tand\tal,07Fh\n\tout\tdx,al\n\n\tmov\tedx,R_CRT_CONTROLLER\n\tmov\teax,04009h\n\tout\tdx,ax\n\tmov\teax,00014h\n\tout\tdx,ax\n\tmov\teax,0E317h\n\tout\tdx,ax\n\tmov\teax,00D06h\n\tout\tdx,ax\n\tmov\teax,03E07h\n\tout\tdx,ax\n\tmov\teax,0EA10h\n\tout\tdx,ax\n\tmov\teax,0AC11h\n\tout\tdx,ax\n\tmov\teax,0DF12h\n\tout\tdx,ax\n\tmov\teax,0E715h\n\tout\tdx,ax\n\tmov\teax,00616h\n\tout\tdx,ax\n\tmov\teax,04009h\n\tout\tdx,ax\n\n\txor\teax,eax\n\tjmp\t??Done\n\n??Set360x400:\n\tcmp\t[mode],XMODE_360X400\t;360x400\n\tjne\t??Set360x480\n\n\tmov\teax,MCGA\n\tint\t10h\n\n\tmov\tedx,R_SEQUENCER\n\tmov\teax,0604h\n\tout\tdx,ax\n\n\tmov\teax,0100h\n\tout\tdx,ax\n\n\tmov\tedx,R_MISC_OUTPUT\n\tmov\tal,067h\n\tout\tdx,al\n\n\tmov\tedx,R_SEQUENCER\n\tmov\teax,0300h\n\tout\tdx,ax\n\n\tmov\tedx,R_CRT_CONTROLLER\n\tmov\tal,011h\n\tout\tdx,al\n\n\tmov\tedx,03D5h\n\tin\tal,dx\n\tand\tal,07Fh\n\tout\tdx,al\n\n\tmov\tedx,R_CRT_CONTROLLER\n\tmov\teax,06B00h\n\tout\tdx,ax\n\tmov\teax,05901h\n\tout\tdx,ax\n\tmov\teax,05A02h\n\tout\tdx,ax\n\tmov\teax,08E03h\n\tout\tdx,ax\n\tmov\teax,05E04h\n\tout\tdx,ax\n\tmov\teax,08A05h\n\tout\tdx,ax\n\tmov\teax,04009\n\tout\tdx,ax\n\tmov\teax,00014h\n\tout\tdx,ax\n\tmov\teax,0E317h\n\tout\tdx,ax\n\tmov\teax,02D13h\n\tout\tdx,ax\n\n\txor\teax,eax\n\tjmp\t??Done\n\n??Set360x480:\n\tcmp\t[mode],XMODE_360X480\t;360x480?\n\tjne\t??Unknown_mode\n\n\tmov\teax,MCGA\n\tint\t10h\n\n\tmov\tedx,R_SEQUENCER\n\tmov\teax,0604h\n\tout\tdx,ax\n\n\tmov\teax,0100h\n\tout\tdx,ax\n\n\tmov\tedx,R_MISC_OUTPUT\n\tmov\tal,0E7h\n\tout\tdx,al\n\n\tmov\tedx,R_SEQUENCER\n\tmov\teax,0300h\n\tout\tdx,ax\n\n\tmov\tedx,R_CRT_CONTROLLER\n\tmov\tal,011h\n\tout\tdx,al\n\n\tmov\tedx,03D5h\n\tin\tal,dx\n\tand\tal,07Fh\n\tout\tdx,al\n\n\tmov\tedx,R_CRT_CONTROLLER\n\tmov\teax,06B00h\n\tout\tdx,ax\n\tmov\teax,05901h\n\tout\tdx,ax\n\tmov\teax,05A02h\n\tout\tdx,ax\n\tmov\teax,08E03h\n\tout\tdx,ax\n\tmov\teax,05E04h\n\tout\tdx,ax\n\tmov\teax,08A05h\n\tout\tdx,ax\n\tmov\teax,04009h\n\tout\tdx,ax\n\tmov\teax,00014h\n\tout\tdx,ax\n\tmov\teax,0E317h\n\tout\tdx,ax\n\tmov\teax,00D06h\n\tout\tdx,ax\n\tmov\teax,03E07h\n\tout\tdx,ax\n\tmov\teax,0EA10h\n\tout\tdx,ax\n\tmov\teax,0AC11h\n\tout\tdx,ax\n\tmov\teax,0DF12h\n\tout\tdx,ax\n\tmov\teax,0E715h\n\tout\tdx,ax\n\tmov\teax,00616h\n\tout\tdx,ax\n\tmov\teax,02D13h\n\tout\tdx,ax\n\n\txor\teax,eax\n\tjmp\t??Done\n\n??Unknown_mode:\n\tmov\teax,0FFFFFFFFh\t;Unknown mode\n\n??Done:\n\tret\n\n\tENDP\tSetXMode\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     ClearXMode - Clear the XMode VRAM.\n;*\n;* SYNOPSIS\n;*     ClearXMode()\n;*\n;*     void ClearXMode(void);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC ClearXMode:NEAR\n\tPROC\tClearXMode C NEAR USES eax ecx edi es\n\n\tIF\tPHARLAP_TNT\n\tmov\teax,01Ch\n\tmov\tes,ax\t\t;Set ES selector to VRAM\n\tmov\tedi,0\n\tELSE\n\tmov\tedi,0A0000h\n\tENDIF\n\tSET_PLANE 0Fh\n\tmov\tecx,((320*240*2)/4/4)\n\txor\teax,eax\n\trep\tstosd\n\tret\n\n\tENDP\tClearXMode\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     ShowXPage - Set a specific page for XMode display.\n;*\n;* SYNOPSIS\n;*     ShowXPage(Offset)\n;*\n;*     void ShowXPage();\n;*\n;* FUNCTION\n;*     Show the page at the specified offset in the bitmap. Page-flip takes\n;*     effect on the next active scan cycle.\n;*\n;* INPUTS\n;*     Offset - Offset to set page to.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC ShowXPage:NEAR\n\tPROC\tShowXPage C NEAR USES eax ebx ecx edx\n\n\tARG\tStartOffset:DWORD\n\n\tmov\tedx,R_CRT_CONTROLLER\n\tmov\tbl,CRT_STARTADDR_LOW\n\tmov\tbh,[byte ptr StartOffset]\n\tmov\tcl,CRT_STARTADDR_HIGH\n\tmov\tch,[byte ptr StartOffset+1]\n\tmov\teax,ebx\n\tout\tdx,ax\n\tmov\teax,ecx\n\tout\tdx,ax\n\tret\n\n\tENDP\tShowXPage\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Xmode_BufferCopy_320x200 - Copy 320x200 buffer to Xmode VRAM.\n;*\n;* SYNOPSIS\n;*     Xmode_BufferCopy_320x200(Buffer, Screen)\n;*\n;*     void Xmode_BufferCopy_320x200(char *, char *);\n;*\n;* FUNCTION\n;*     BitBlt copy to VRAM.\n;*\n;* INPUTS\n;*     Buffer - Pointer to buffer to copy to XMode VRAM.\n;*     Screen - XMode VRAM screen address to copy buffer to.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Xmode_BufferCopy_320x200:NEAR\n\tPROC\tXmode_BufferCopy_320x200 C NEAR USES eax ecx edx edi esi es\n\n\tARG\tbuffer:NEAR PTR\n\tARG\tscreen:NEAR PTR\n\n\tLOCAL\tsave_esi:DWORD\n\tLOCAL\tsave_edi:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\t\n\tIF\tPHARLAP_TNT\n\tmov\teax,01Ch\t;Set ES selector to VRAM.\n\tmov\tes,ax\n\tENDIF\n\n\tmov\tesi,[buffer]\t;Set pointers\n\tmov\tedi,[screen]\n\tmov\t[save_esi],esi\n\tmov\t[save_edi],edi\n\n;----------------------------------------------------------------------------\n;\tCopy plane 1\n;----------------------------------------------------------------------------\n\n\tSET_PLANE XPLANE_1\n\tmov\tecx,4000\n\nx_loop_1:\n\tmov\tal,[esi + 8]\t;Get pixel\n\tmov\tah,[esi + 12]\t;Get pixel\n\tror\teax,16\n\tmov\tal,[esi]\t;Get pixel\n\tmov\tah,[esi + 4]\t;Get pixel\n\tmov\t[es:edi],eax \t;Write plane 1 pixels to VRAM\n\n\tadd\tesi,16\t;Next source pixel position\n\tadd\tedi,4\t;Next VRAM position\n\tdec\tecx\n\tjnz\tshort x_loop_1\n\n;----------------------------------------------------------------------------\n;\tCopy plane 2\n;----------------------------------------------------------------------------\n\n\tmov\tesi,[save_esi]\t;Restore pointers\n\tmov\tedi,[save_edi]\n\tinc\tesi\t;Adjust source pointer to plane 2\n\n\tSET_PLANE XPLANE_2\n\tmov\tecx,4000\n\nx_loop_2:\n\tmov\tal,[esi + 8]\t;Get pixel\n\tmov\tah,[esi + 12]\t;Get pixel\n\tror\teax,16\n\tmov\tal,[esi]\t;Get pixel\n\tmov\tah,[esi + 4]\t;Get pixel\n\tmov\t[es:edi],eax\t;Write plane 2 pixels to VRAM\n\n\tadd\tesi,16\t;Next source pixel position\n\tadd\tedi,4\t;Next VRAM position\n\tdec\tecx\n\tjnz\tshort x_loop_2\n\n;----------------------------------------------------------------------------\n;\tCopy plane 3\n;----------------------------------------------------------------------------\n\n\tmov\tesi,[save_esi]\t;Restore pointers\n\tmov\tedi,[save_edi]\n\tadd\tesi,2\t;Adjust source pointer to plane 3\n\n\tSET_PLANE XPLANE_3\n\tmov\tecx,4000\n\nx_loop_3:\n\tmov\tal,[esi + 8]\t;Get pixel\n\tmov\tah,[esi + 12]\t;Get pixel\n\tror\teax,16\n\tmov\tal,[esi]\t;Get pixel\n\tmov\tah,[esi + 4]\t;Get pixel\n\tmov\t[es:edi],eax\t;Write plane 3 pixels to VRAM\n\n\tadd\tesi,16\t;Next source pixel position\n\tadd\tedi,4\t;Next VRAM position\n\tdec\tecx\n\tjnz\tshort x_loop_3\n\n;----------------------------------------------------------------------------\n;\tCopy plane 4\n;----------------------------------------------------------------------------\n\n\tmov\tesi,[save_esi]\t;Restore pointers\n\tmov\tedi,[save_edi]\n\tadd\tesi,3\t;Adjust source pointer to plane 4\n\n\tSET_PLANE XPLANE_4\n\tmov\tecx,4000\nx_loop_4:\n\tmov\tal,[esi + 8]\t;Get pixel\n\tmov\tah,[esi + 12]\t;Get pixel\n\tror\teax,16\n\tmov\tal,[esi]\t;Get pixel\n\tmov\tah,[esi + 4]\t;Get pixel\n\tmov\t[es:edi],eax\t;Write plane 4 pixels to VRAM\n\n\tadd\tesi,16\t;Next source pixel position\n\tadd\tedi,4\t;Next screen position\n\tdec\tecx\n\tjnz\tshort x_loop_4\n\tret\n\n\tENDP\tXmode_BufferCopy_320x200\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Xmode_Blit - Bit blit a block to the XMode display.\n;*\n;* SYNOPSIS\n;*     XMode_Blit(Buffer, Screen, Width, Height)\n;*\n;*     void XMode_Blit(char *, char *, long, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Buffer - Pointer buffer to blit to screen.\n;*     Screen - Screen address to blit buffer to.\n;*     Width  - Width of buffer.\n;*     Height - Height of buffer.\n;*\n;* RESULT\n;*     NONE\n;*\n;* WARNINGS\n;*     Assumes the screen to be 320 pixels wide and the source buffer width\n;*     to be divisible by 16.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Xmode_Blit:NEAR\n\tPROC\tXmode_Blit C NEAR USES ecx edx esi edi es\n\n\tARG\tbuffer:NEAR PTR\n\tARG\tscreen:NEAR PTR\n\tARG\timgwidth:DWORD\n\tARG\timgheight:DWORD\n\n\tLOCAL\trowcount:DWORD\n\tLOCAL\txplane:DWORD\n\tLOCAL\tedi_startval:DWORD\n\tLOCAL\tesi_startval:DWORD\n\tLOCAL\txadd:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tIF\tPHARLAP_TNT\n\tmov\teax,01Ch\t;Set ES selector to VRAM\n\tmov\tes,ax\n\tENDIF\n\n\tmov\tesi,[buffer]\n\tmov\tedi,[screen]\n\tmov\t[esi_startval],esi\n\tmov\t[edi_startval],edi\n\n\tmov\tedx,320\t;Compute modulo\n\tsub\tedx,[imgwidth]\n\tshr\tedx,2\n\tmov\t[xadd],edx\n\n;----------------------------------------------------------------------------\n;\tTransfer the data on plane at a time.\n;----------------------------------------------------------------------------\n\n\tmov\t[xplane],1\n\n??Do_plane:\n\tSET_PLANE [xplane]\t;Set plane to transfer to\n\tmov\teax,[imgheight]\n\tmov\t[rowcount],eax\n\tmov\tedx,[xadd]\n\n??Do_row:\n\tmov\tecx,[imgwidth]\t;Length of row to copy in DWORDS\n\tshr\tecx,4\n\n;\tTransfer a row of pixels\n\n??Not_done:\n\tmov\tal,[esi + 8]\t;Get pixel\n\tmov\tah,[esi + 12]\t;Get pixel\n\tror\teax,16\n\tmov\tal,[esi]\t;Get pixel\n\tmov\tah,[esi + 4]\t;Get pixel\n\tmov\t[es:edi],eax\t;Write pixels to VRAM plane\n\n\tadd\tesi,16\t;Next source position\n\tadd\tedi,4\t;Next VRAM position\n\tdec\tecx\n\tjnz\t??Not_done\n\n\tadd\tedi,edx\t;Next VRAM row\n\tdec\t[rowcount]\t;Decrement the row count\n\tjnz\t??Do_row\n\n;\tGo to next X-Plane\n\n\tinc\t[esi_startval]\n\tmov\teax,[esi_startval]\n\tmov\tesi,eax\n\tmov\teax,[edi_startval]\n\tmov\tedi,eax\n\tshl\t[xplane],1\n\tcmp\t[xplane],16\n\tjnz\t??Do_plane\n\tret\n\n\tENDP\tXmode_Blit\n\n\tEND\n\n"
  },
  {
    "path": "VQ/VQM32/XMODEPG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     xmodepg.c\n*\n* DESCRIPTION\n*     Xmode page access. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     SetupXPaging - Setup Xmode paging variables.\n*     FlipXPage    - Page flip to next Xmode page.\n*     ShowXPage    - Show the specified Xmode page.\n*     GetXHidPage  - Get the address of the current Xmode HidPage.\n*     GetXSeenPage - Get the address of the current Xmode SeenPage.\n*\n****************************************************************************/\n\n#include <dos.h>\n#include \"video.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n#define PAGE0_START_OFFSET 0\n#define PAGE1_START_OFFSET ((320 * 240) / 4)\n\n/* PageFlip page values. */\nstatic unsigned long PageStartOffsets[2] = {\n\tPAGE0_START_OFFSET,\n\tPAGE1_START_OFFSET\n};\n\nstatic long DisplayedPage;\nstatic long NonDisplayedPage;\n\n/****************************************************************************\n*\n* NAME\n*     SetupXPaging - Setup Xmode paging variables.\n*\n* SYNOPSIS\n*     SetupXPaging()\n*\n*     void SetupXPaging(void);\n*\n* FUNCTION\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid SetupXPaging(void)\n{\n\tDisplayedPage = 1;\n\tNonDisplayedPage = DisplayedPage ^ 1;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     FlipXPage - Page flip to next Xmode page.\n*\n* SYNOPSIS\n*     FlipXPage()\n*\n*     void FlipXPage(void);\n*\n* FUNCTION\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid FlipXPage(void)\n{\n\tShowXPage(PageStartOffsets[NonDisplayedPage]);\n\tDisplayedPage = NonDisplayedPage;\n\tNonDisplayedPage = DisplayedPage ^ 1;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     ShowXPage - Show the specified Xmode page.\n*\n* SYNOPSIS\n*     ShowXPage(page)\n*\n*     void ShowXPage(long);\n*\n* FUNCTION\n*\n* INPUTS\n*     Page - Xmode page number to show.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid DisplayXPage(long page)\n{\n\tShowXPage(PageStartOffsets[page & 1]);\n\tDisplayedPage = page;\n\tNonDisplayedPage = DisplayedPage ^ 1;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetXHidPage - Get the address of the current Xmode HidPage.\n*\n* SYNOPSIS\n*     HidPage = GetXHidPage()\n*\n*     unsigned char *GetXHidPage(void);\n*\n* FUNCTION\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     HidPage - Address of Xmode HidPage.\n*\n****************************************************************************/\n\nunsigned char *GetXHidPage(void)\n{\n\treturn((unsigned char *)PageStartOffsets[NonDisplayedPage]);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetXSeenPage - Get the address of the current Xmode SeenPage.\n*\n* SYNOPSIS\n*     SeenPage = GetXSeenPage()\n*\n*     unsigned char *GetXSeenPage(void);\n*\n* FUNCTION\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     SeePage - Address of the Xmode SeenPage.\n*\n****************************************************************************/\n\nunsigned char *GetXSeenPage(void)\n{\n\treturn ((unsigned char *)PageStartOffsets[DisplayedPage]);\n}\n\n"
  },
  {
    "path": "WIN32LIB/AUDIO/AUDIO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : AUDIO.H                                  *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : March 10, 1995                           *\n *                                                                         *\n *                  Last Update : March 10, 1995   [PWG]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwstd.h\"\n\n/*=========================================================================*/\n/* AUD file header type\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tAUD_FLAG_STEREO\t1\n#define\tAUD_FLAG_16BIT\t\t2\n\n// PWG 3-14-95: This structure used to have bit fields defined for Stereo\n//   and Bits.  These were removed because watcom packs them into a 32 bit\n//   flag entry even though they could have fit in a 8 bit entry.\n#pragma pack(1);\ntypedef struct {\n\tunsigned short int\tRate;\t\t\t\t// Playback rate (hertz).\n\tlong\tSize;\t\t\t\t// Size of data (bytes).\n\tlong\tUncompSize;\t\t\t\t// Size of data (bytes).\n\tunsigned char Flags;\t// Holds flags for info\n\t\t\t\t\t\t\t\t//  1: Is the sample stereo?\n\t\t\t\t\t\t\t\t//  2: Is the sample 16 bits?\n\tunsigned char Compression;\t// What kind of compression for this sample?\n} AUDHeaderType;\n\n\n/*=========================================================================*/\n/*\tThere can be a different sound driver for sound effects, digitized\t\t*/\n/*\tsamples, and musical scores.  Each one must be of these specified\t\t\t*/\n/*\ttypes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\ntypedef enum {\n\tSAMPLE_NONE,\t\t// No digitized sounds will be played.\n\tSAMPLE_SB,\t\t\t// Sound Blaster digitized driver.\n\tSAMPLE_SBPRO,\t\t// Sound Blaster Pro digitized driver.\n\tSAMPLE_PAS,\t\t\t// Pro-Audio Spectrum digitized driver.\n\tSAMPLE_ADLIBG,\t\t// Adlib-Gold digitized driver.\n\tSAMPLE_TANDY,\t\t// Tandy 'compatible' driver.\n\tSAMPLE_PCSPKR,\t\t// PC speaker digitized driver (The Audio Solution driver).\n\tSAMPLE_ADLIB,\t\t// Adlib digitized driver (The Audio Solution driver).\n\tSAMPLE_TEMP=0x1000,\n\tSAMPLE_LAST\n} Sample_Type;\n\ntypedef enum {\n\tSCORE_NONE,\t\t\t// No scores will be played.\n\tSCORE_ALFX,\t\t\t// Westwood's ALFX adlib compatable driver.\n\tSCORE_WWPCSPKR,\t// Westwood's PC-speaker driver (obsolete).\n\tSCORE_WWTANDY,\t\t// Westwood's PC-speaker driver with Tandy mod (obsolete).\n\tSCORE_PCSPKR,\t\t// PC speaker XMIDI driver.\n\tSCORE_TANDY,\t\t// Tandy XMIDI driver.\n\tSCORE_MT32,\t\t\t// MT-32 / LAPC-1 Roland XMIDI driver.\n\tSCORE_CANVAS,\t\t// Sound Canvas SC-55.\n\tSCORE_ADLIB,\t\t// Adlib XMIDI driver.\n\tSCORE_ADLIBG,\t\t// Adlib Gold XMIDI driver.\n\tSCORE_PASFM,\t\t// Pro Audio Spectrum XMIDI driver.\n\tSCORE_SBFM,\t\t\t// Sound Blaster XMIDI driver.\n\tSCORE_SBP1FM,\t\t// Sound Blaster Pro (YM3812) XMIDI driver.\n\tSCORE_SBP2FM,\t\t// Sound Blaster Pro (OPL3) XMIDI driver (Can't use with SFX_ALFX).\n\tSCORE_TEMP=0x1000,\n\tSCORE_LAST\n} Score_Type;\n\ntypedef enum {\n\tSFX_NONE,\t\t\t// No sound effects will be played.\n\tSFX_ALFX,\t\t\t// Westwood's ALFX adlib compatable driver.\n\tSFX_WWPCSPKR,\t\t// Westwood's PC-speaker driver.\n\tSFX_WWTANDY,\t\t// Westwood's PC-speaker driver with Tandy mod.\n\tSFX_PCSPKR,\t\t\t// PC speaker XMIDI driver.\n\tSFX_TANDY,\t\t\t// Tandy XMIDI driver.\n\tSFX_MT32,\t\t\t// MT-32 / LAPC-1 Roland XMIDI driver.\n\tSFX_CANVAS,\t\t\t// Sound Canvas SC-55.\n\tSFX_ADLIB,\t\t\t// Adlib XMIDI driver.\n\tSFX_ADLIBG,\t\t\t// Adlib Gold XMIDI driver.\n\tSFX_PASFM,\t\t\t// Pro Audio Spectrum XMIDI driver.\n\tSFX_SBFM,\t\t\t// Sound Blaster XMIDI driver.\n\tSFX_SBP1FM,\t\t\t// Sound Blaster Pro (YM3812) XMIDI driver.\n\tSFX_SBP2FM,\t\t\t// Sound Blaster Pro (OPL3) XMIDI driver.\n\tSFX_TEMP=0x1000,\n\tSFX_LAST\n} SFX_Type;\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SOUNDIO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nint File_Stream_Sample(char const *filename, BOOL real_time_start = FALSE);\nint File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start = FALSE);\nvoid __cdecl Sound_Callback(void);\nvoid __cdecl far maintenance_callback(void);\nvoid *Load_Sample(char const *filename);\nlong Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);\nlong Sample_Read(int fh, void *buffer, long size);\nvoid Free_Sample(void const *sample);\nBOOL Audio_Init( HWND window , int bits_per_sample, BOOL stereo , int rate , int reverse_channels);\nvoid Sound_End(void);\nvoid Stop_Sample(int handle);\nBOOL Sample_Status(int handle);\nBOOL Is_Sample_Playing(void const * sample);\nvoid Stop_Sample_Playing(void const * sample);\nint Play_Sample(void const *sample, int priority=0xFF, int volume=0xFF, signed short panloc = 0x0);\nint Play_Sample_Handle(void const *sample, int priority, int volume, signed short panloc, int id);\nint Set_Sound_Vol(int volume);\nint Set_Score_Vol(int volume);\nvoid Fade_Sample(int handle, int ticks);\nint Get_Free_Sample_Handle(int priority);\nint Get_Digi_Handle(void);\nlong Sample_Length(void const *sample);\nvoid Restore_Sound_Buffers (void);\nBOOL Set_Primary_Buffer_Format(void);\nBOOL Start_Primary_Sound_Buffer (BOOL forced);\nvoid Stop_Primary_Sound_Buffer (void);\n\n/*\n** Function to call if we detect focus loss\n*/\nextern\tvoid (*Audio_Focus_Loss_Function)(void);\n\n\nextern int Misc;\nextern SFX_Type SoundType;\nextern Sample_Type SampleType;\n\nextern CRITICAL_SECTION\tGlobalAudioCriticalSection;\n\nextern int StreamLowImpact;\n"
  },
  {
    "path": "WIN32LIB/AUDIO/AUDUNCMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Audio Library            *\n;*                                                                         *\n;*                    File Name : AUDUNCMP.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : March 14, 1995                           *\n;*                                                                         *\n;*                  Last Update : June 26, 1995   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Decompress_Frame_Lock -- locks the JLB audio decompression code       *\n;*   Decompress_Frame_Unlock -- Unlocks the JLB audio compression code     *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\nDPMI_INTR\t\tequ\t31h\n\nLABEL \tLockedCodeStart\tBYTE\n\nCODE_2BIT\tEQU\t0\nCODE_4BIT\tEQU\t1\nCODE_RAW\tEQU\t2\nCODE_SILENCE\tEQU\t3\nMAGICNUMBER\tEQU\t00000DEAFh\nMAGICNUMBER2\tEQU\t0BABEBABEh\n\n_2bitdecode\tDB\t-2,-1,0,1\n_4bitdecode\tDB\t-9,-8,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,8\n\n\n;***************************************************************************\n;* DECOMPRESS_FRAME -- Uncompresses a WW compressed audio frame            *\n;*                                                                         *\n;* INPUT:\tvoid * source - pointer to encoded audio data              *\n;*\t\tvoid * dest   - pointer to decompression area\t\t   *\n;*\t\tlong size     - the maximum size of destination buffer\t   *\n;*                                                                         *\n;* OUTPUT:      long - the number of bytes we uncompressed                 *\n;*                                                                         *\n;* PROTO:\tlong Decompress_Frame(void *, void *, long);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/14/1995 PWG : Created.                                             *\n;*=========================================================================*\n\n\tGLOBAL\tC Decompress_Frame:NEAR\n\tPROC\tDecompress_Frame C NEAR USES ebx ecx edx esi edi\n\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tcount:DWORD\n\n\tLOCAL\tprevious:BYTE\n\tLOCAL\tincount:DWORD\n\n\tpushfd\n\tcld\n\tmov\t[incount],0\t;Bytes read from source\n\n\n;\tSource, Dest and count must be valid.\n\n\tcmp\t[source],0\n\tje\t??fini\n\n\tcmp\t[dest],0\n\tje\t??fini\n\n\tcmp\t[count],0\n\tje\t??fini\n\n\tmov\tesi,[source]\t;Pointer to source data.\n\tmov\tedi,[dest]\t;Pointer to destination data.\n\tmov\tecx,[count]\t;Number of bytes to fill dest buffer.\n\tmov\tdl,080h\t;Previous sample (starting value).\n\n??mainloop:\n\tcmp\tecx,0\t;If dest full then exit\n\tjle\t??fini\n\n\txor\teax,eax\n\tmov\tal,[esi]\t;Get code byte\n\tinc\t[incount]\n\tinc\tesi\n\tshl\teax,2\t;AH contains code.\n\tshr\tal,2\t;AL contains sub-code data.\n\n\tcmp\tah,CODE_RAW\t;Raw sequence?\n\tjne\tshort ??try4bit\n\n;\tThe code contains either a 5 bit delta or a count of\n;\traw samples to dump out.\n\n\ttest\tal,00100000b\n\tje\tshort ??justraw\n\n;\tThe lower 5 bits are actually a signed delta.\n;\tSign extend the delta and add it to the stream.\n\n\tshl\tal,3\n\tsar\tal,3\n\tadd\tdl,al\n\tmov\t[edi],dl\n\tdec\tecx\n\tinc\tedi\n\tjmp\t??mainloop\n\n;\tThe lower 5 bits hold a count of the number of raw\n;\tsamples that follow this code. Dump these samples to\n;\tthe output buffer.\n\n??justraw:\n\tmov\tebx,ecx\n\txor\tah,ah\n\tinc\tal\n\tmov\tecx,eax\n\tshr\tecx,1\n\trep\tmovsw\n\tadc\tecx,ecx\n\trep\tmovsb\n\tmov\tecx,ebx\n\tadd\t[incount],eax\n\tsub\tecx,eax\n\tdec\tedi\n\tmov\tdl,[edi]\t;Set \"previous\" value.\n\tinc\tedi\n\tjmp\t??mainloop\n\n;\tCheck to see if this is a 4 bit delta code sequence.\n\n??try4bit:\n\tinc\tal\t;Following codes use AL+1\n\tcmp\tah,CODE_4BIT\n\tjne\tshort ??try2bit\n\n;\tA sequence of 4bit deltas follow. AL equals the\n;\tnumber of nibble packed delta bytes to process.\n\n??bit4loop:\n\tmov\tah,[esi]\t;Fetch nibble packed delta codes\n\tmov\tbl,ah\n\tinc\t[incount]\n\tinc\tesi\n\n;\tAdd first delta to 'previous' sample already in DL.\n\n\tand\tebx,00001111b\n\tadd\tdl,[_4bitdecode+ebx]\n\tpushfd\n\tcmp\t[_4bitdecode+ebx],0\n\tjl\tshort ??neg1\n\n\tpopfd\n\tjnc\tshort ??ok1\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok1\n\n??neg1:\n\tpopfd\n\tjc\tshort ??ok1\n\n\txor\tdl,dl\n\n??ok1:\n\tmov\tdh,dl\t;DH now holds new 'previous' sample.\n\tmov\tbl,ah\n\tshr\tbl,4\n\tadd\tdh,[_4bitdecode+ebx]\n\tpushfd\n\tcmp\t[_4bitdecode+ebx],0\n\tjl\tshort ??neg2\n\n\tpopfd\n\tjnc\tshort ??ok2\n\n\tmov\tdh,0FFh\n\tjmp\tshort ??ok2\n\n??neg2:\n\tpopfd\n\tjc\tshort ??ok2\n\n\txor\tdh,dh\n\n??ok2:\n\tmov\t[edi],dx\t;Output the two sample bytes\n\tsub\tecx,2\n\tadd\tedi,2\n\n;\tPut the correct 'previous' sample in DL where it belongs.\n\n\tmov\tdl,dh\n\n;\tIf there are more deltas to process then loop back.\n\n\tdec\tal\n\tjnz\tshort ??bit4loop\n\tjmp\t??mainloop\n\n;\tCheck to see if 2 bit deltas need to be processed.\n\n??try2bit:\n\tcmp\tah,CODE_2BIT\n\tjne\t??zerodelta\n\n;\tA sequence of 2bit deltas follow.  AL equals the number of\n;\tpacked delta bytes to process.\n\n??bit2loop:\n\tmov\tah,[esi]\t;Fetch packed delat codes\n\tinc\t[incount]\n\tinc\tesi\n\n;\tAdd first delta to 'previous' sample already in DL.\n\n\tmov\tbl,ah\n\tand\tebx,000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushfd\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg3\n\n\tpopfd\n\tjnc\tshort ??ok3\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok3\n\n??neg3:\n\tpopfd\n\tjc\tshort ??ok3\n\txor\tdl,dl\n\n??ok3:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,2\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushfd\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg4\n\n\tpopfd\n\tjnc\tshort ??ok4\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok4\n\n??neg4:\n\tpopfd\n\tjc\tshort ??ok4\n\n\txor\tdl,dl\n\n??ok4:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,4\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushfd\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg5\n\n\tpopfd\n\tjnc\tshort ??ok5\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok5\n\n??neg5:\n\tpopfd\n\tjc\tshort ??ok5\n\n\txor\tdl,dl\n\n??ok5:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,6\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushfd\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg6\n\n\tpopfd\n\tjnc\tshort ??ok6\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok6\n\n??neg6:\n\tpopfd\n\tjc\tshort ??ok6\n\n\txor\tdl,dl\n\n??ok6:\n\tror\tedx,8\n\tmov\t[edi],edx\t;Output two sample bytes\n\tsub\tecx,4\n\tadd\tedi,4\n\n;\tPut the correct 'previous' sample in DL where it belongs.\n\n\trol\tedx,8\n\n;\tIf there are more deltas to process then loop back.\n\n\tdec\tal\n\tjnz\t??bit2loop\n\tjmp\t??mainloop\n\n;\tThere is a run of zero deltas.  Zero deltas merely duplicate\n;\tthe 'previous' sample the requested number of times.\n\n??zerodelta:\n\txor\tebx,ebx\n\tmov\tbl,al\n\tmov\tal,dl\n\tsub\tecx,ebx\n\txchg\tecx,ebx\n\trep\tstosb\n\tmov\tecx,ebx\n\tjmp\t??mainloop\n\n??fini:\n\tpopfd\n\tmov\teax,[incount]\n\tret\n\n\tENDP\tDecompress_Frame\n\nLABEL \tLockedCodeEnd\tBYTE\n\n\n\n\n\n\tEND"
  },
  {
    "path": "WIN32LIB/AUDIO/DIFFTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* dwDiffTable - ADPCM Lookup table for sample differences\n;****************************************************************************\n\n\t\talign\t4\n\ndwDiffTable\tDD\t0\t; Index = 0 Token = 0\n\t\tDD\t1\t; Index = 0 Token = 1\n\t\tDD\t3\t; Index = 0 Token = 2\n\t\tDD\t4\t; Index = 0 Token = 3\n\t\tDD\t7\t; Index = 0 Token = 4\n\t\tDD\t8\t; Index = 0 Token = 5\n\t\tDD\t10\t; Index = 0 Token = 6\n\t\tDD\t11\t; Index = 0 Token = 7\n\t\tDD\t0\t; Index = 0 Token = 8\n\t\tDD\t-1\t; Index = 0 Token = 9\n\t\tDD\t-3\t; Index = 0 Token = 10\n\t\tDD\t-4\t; Index = 0 Token = 11\n\t\tDD\t-7\t; Index = 0 Token = 12\n\t\tDD\t-8\t; Index = 0 Token = 13\n\t\tDD\t-10\t; Index = 0 Token = 14\n\t\tDD\t-11\t; Index = 0 Token = 15\n\t\tDD\t1\t; Index = 1 Token = 0\n\t\tDD\t3\t; Index = 1 Token = 1\n\t\tDD\t5\t; Index = 1 Token = 2\n\t\tDD\t7\t; Index = 1 Token = 3\n\t\tDD\t9\t; Index = 1 Token = 4\n\t\tDD\t11\t; Index = 1 Token = 5\n\t\tDD\t13\t; Index = 1 Token = 6\n\t\tDD\t15\t; Index = 1 Token = 7\n\t\tDD\t-1\t; Index = 1 Token = 8\n\t\tDD\t-3\t; Index = 1 Token = 9\n\t\tDD\t-5\t; Index = 1 Token = 10\n\t\tDD\t-7\t; Index = 1 Token = 11\n\t\tDD\t-9\t; Index = 1 Token = 12\n\t\tDD\t-11\t; Index = 1 Token = 13\n\t\tDD\t-13\t; Index = 1 Token = 14\n\t\tDD\t-15\t; Index = 1 Token = 15\n\t\tDD\t1\t; Index = 2 Token = 0\n\t\tDD\t3\t; Index = 2 Token = 1\n\t\tDD\t5\t; Index = 2 Token = 2\n\t\tDD\t7\t; Index = 2 Token = 3\n\t\tDD\t10\t; Index = 2 Token = 4\n\t\tDD\t12\t; Index = 2 Token = 5\n\t\tDD\t14\t; Index = 2 Token = 6\n\t\tDD\t16\t; Index = 2 Token = 7\n\t\tDD\t-1\t; Index = 2 Token = 8\n\t\tDD\t-3\t; Index = 2 Token = 9\n\t\tDD\t-5\t; Index = 2 Token = 10\n\t\tDD\t-7\t; Index = 2 Token = 11\n\t\tDD\t-10\t; Index = 2 Token = 12\n\t\tDD\t-12\t; Index = 2 Token = 13\n\t\tDD\t-14\t; Index = 2 Token = 14\n\t\tDD\t-16\t; Index = 2 Token = 15\n\t\tDD\t1\t; Index = 3 Token = 0\n\t\tDD\t3\t; Index = 3 Token = 1\n\t\tDD\t6\t; Index = 3 Token = 2\n\t\tDD\t8\t; Index = 3 Token = 3\n\t\tDD\t11\t; Index = 3 Token = 4\n\t\tDD\t13\t; Index = 3 Token = 5\n\t\tDD\t16\t; Index = 3 Token = 6\n\t\tDD\t18\t; Index = 3 Token = 7\n\t\tDD\t-1\t; Index = 3 Token = 8\n\t\tDD\t-3\t; Index = 3 Token = 9\n\t\tDD\t-6\t; Index = 3 Token = 10\n\t\tDD\t-8\t; Index = 3 Token = 11\n\t\tDD\t-11\t; Index = 3 Token = 12\n\t\tDD\t-13\t; Index = 3 Token = 13\n\t\tDD\t-16\t; Index = 3 Token = 14\n\t\tDD\t-18\t; Index = 3 Token = 15\n\t\tDD\t1\t; Index = 4 Token = 0\n\t\tDD\t3\t; Index = 4 Token = 1\n\t\tDD\t6\t; Index = 4 Token = 2\n\t\tDD\t8\t; Index = 4 Token = 3\n\t\tDD\t12\t; Index = 4 Token = 4\n\t\tDD\t14\t; Index = 4 Token = 5\n\t\tDD\t17\t; Index = 4 Token = 6\n\t\tDD\t19\t; Index = 4 Token = 7\n\t\tDD\t-1\t; Index = 4 Token = 8\n\t\tDD\t-3\t; Index = 4 Token = 9\n\t\tDD\t-6\t; Index = 4 Token = 10\n\t\tDD\t-8\t; Index = 4 Token = 11\n\t\tDD\t-12\t; Index = 4 Token = 12\n\t\tDD\t-14\t; Index = 4 Token = 13\n\t\tDD\t-17\t; Index = 4 Token = 14\n\t\tDD\t-19\t; Index = 4 Token = 15\n\t\tDD\t1\t; Index = 5 Token = 0\n\t\tDD\t4\t; Index = 5 Token = 1\n\t\tDD\t7\t; Index = 5 Token = 2\n\t\tDD\t10\t; Index = 5 Token = 3\n\t\tDD\t13\t; Index = 5 Token = 4\n\t\tDD\t16\t; Index = 5 Token = 5\n\t\tDD\t19\t; Index = 5 Token = 6\n\t\tDD\t22\t; Index = 5 Token = 7\n\t\tDD\t-1\t; Index = 5 Token = 8\n\t\tDD\t-4\t; Index = 5 Token = 9\n\t\tDD\t-7\t; Index = 5 Token = 10\n\t\tDD\t-10\t; Index = 5 Token = 11\n\t\tDD\t-13\t; Index = 5 Token = 12\n\t\tDD\t-16\t; Index = 5 Token = 13\n\t\tDD\t-19\t; Index = 5 Token = 14\n\t\tDD\t-22\t; Index = 5 Token = 15\n\t\tDD\t1\t; Index = 6 Token = 0\n\t\tDD\t4\t; Index = 6 Token = 1\n\t\tDD\t7\t; Index = 6 Token = 2\n\t\tDD\t10\t; Index = 6 Token = 3\n\t\tDD\t14\t; Index = 6 Token = 4\n\t\tDD\t17\t; Index = 6 Token = 5\n\t\tDD\t20\t; Index = 6 Token = 6\n\t\tDD\t23\t; Index = 6 Token = 7\n\t\tDD\t-1\t; Index = 6 Token = 8\n\t\tDD\t-4\t; Index = 6 Token = 9\n\t\tDD\t-7\t; Index = 6 Token = 10\n\t\tDD\t-10\t; Index = 6 Token = 11\n\t\tDD\t-14\t; Index = 6 Token = 12\n\t\tDD\t-17\t; Index = 6 Token = 13\n\t\tDD\t-20\t; Index = 6 Token = 14\n\t\tDD\t-23\t; Index = 6 Token = 15\n\t\tDD\t1\t; Index = 7 Token = 0\n\t\tDD\t4\t; Index = 7 Token = 1\n\t\tDD\t8\t; Index = 7 Token = 2\n\t\tDD\t11\t; Index = 7 Token = 3\n\t\tDD\t15\t; Index = 7 Token = 4\n\t\tDD\t18\t; Index = 7 Token = 5\n\t\tDD\t22\t; Index = 7 Token = 6\n\t\tDD\t25\t; Index = 7 Token = 7\n\t\tDD\t-1\t; Index = 7 Token = 8\n\t\tDD\t-4\t; Index = 7 Token = 9\n\t\tDD\t-8\t; Index = 7 Token = 10\n\t\tDD\t-11\t; Index = 7 Token = 11\n\t\tDD\t-15\t; Index = 7 Token = 12\n\t\tDD\t-18\t; Index = 7 Token = 13\n\t\tDD\t-22\t; Index = 7 Token = 14\n\t\tDD\t-25\t; Index = 7 Token = 15\n\t\tDD\t2\t; Index = 8 Token = 0\n\t\tDD\t6\t; Index = 8 Token = 1\n\t\tDD\t10\t; Index = 8 Token = 2\n\t\tDD\t14\t; Index = 8 Token = 3\n\t\tDD\t18\t; Index = 8 Token = 4\n\t\tDD\t22\t; Index = 8 Token = 5\n\t\tDD\t26\t; Index = 8 Token = 6\n\t\tDD\t30\t; Index = 8 Token = 7\n\t\tDD\t-2\t; Index = 8 Token = 8\n\t\tDD\t-6\t; Index = 8 Token = 9\n\t\tDD\t-10\t; Index = 8 Token = 10\n\t\tDD\t-14\t; Index = 8 Token = 11\n\t\tDD\t-18\t; Index = 8 Token = 12\n\t\tDD\t-22\t; Index = 8 Token = 13\n\t\tDD\t-26\t; Index = 8 Token = 14\n\t\tDD\t-30\t; Index = 8 Token = 15\n\t\tDD\t2\t; Index = 9 Token = 0\n\t\tDD\t6\t; Index = 9 Token = 1\n\t\tDD\t10\t; Index = 9 Token = 2\n\t\tDD\t14\t; Index = 9 Token = 3\n\t\tDD\t19\t; Index = 9 Token = 4\n\t\tDD\t23\t; Index = 9 Token = 5\n\t\tDD\t27\t; Index = 9 Token = 6\n\t\tDD\t31\t; Index = 9 Token = 7\n\t\tDD\t-2\t; Index = 9 Token = 8\n\t\tDD\t-6\t; Index = 9 Token = 9\n\t\tDD\t-10\t; Index = 9 Token = 10\n\t\tDD\t-14\t; Index = 9 Token = 11\n\t\tDD\t-19\t; Index = 9 Token = 12\n\t\tDD\t-23\t; Index = 9 Token = 13\n\t\tDD\t-27\t; Index = 9 Token = 14\n\t\tDD\t-31\t; Index = 9 Token = 15\n\t\tDD\t2\t; Index = 10 Token = 0\n\t\tDD\t6\t; Index = 10 Token = 1\n\t\tDD\t11\t; Index = 10 Token = 2\n\t\tDD\t15\t; Index = 10 Token = 3\n\t\tDD\t21\t; Index = 10 Token = 4\n\t\tDD\t25\t; Index = 10 Token = 5\n\t\tDD\t30\t; Index = 10 Token = 6\n\t\tDD\t34\t; Index = 10 Token = 7\n\t\tDD\t-2\t; Index = 10 Token = 8\n\t\tDD\t-6\t; Index = 10 Token = 9\n\t\tDD\t-11\t; Index = 10 Token = 10\n\t\tDD\t-15\t; Index = 10 Token = 11\n\t\tDD\t-21\t; Index = 10 Token = 12\n\t\tDD\t-25\t; Index = 10 Token = 13\n\t\tDD\t-30\t; Index = 10 Token = 14\n\t\tDD\t-34\t; Index = 10 Token = 15\n\t\tDD\t2\t; Index = 11 Token = 0\n\t\tDD\t7\t; Index = 11 Token = 1\n\t\tDD\t12\t; Index = 11 Token = 2\n\t\tDD\t17\t; Index = 11 Token = 3\n\t\tDD\t23\t; Index = 11 Token = 4\n\t\tDD\t28\t; Index = 11 Token = 5\n\t\tDD\t33\t; Index = 11 Token = 6\n\t\tDD\t38\t; Index = 11 Token = 7\n\t\tDD\t-2\t; Index = 11 Token = 8\n\t\tDD\t-7\t; Index = 11 Token = 9\n\t\tDD\t-12\t; Index = 11 Token = 10\n\t\tDD\t-17\t; Index = 11 Token = 11\n\t\tDD\t-23\t; Index = 11 Token = 12\n\t\tDD\t-28\t; Index = 11 Token = 13\n\t\tDD\t-33\t; Index = 11 Token = 14\n\t\tDD\t-38\t; Index = 11 Token = 15\n\t\tDD\t2\t; Index = 12 Token = 0\n\t\tDD\t7\t; Index = 12 Token = 1\n\t\tDD\t13\t; Index = 12 Token = 2\n\t\tDD\t18\t; Index = 12 Token = 3\n\t\tDD\t25\t; Index = 12 Token = 4\n\t\tDD\t30\t; Index = 12 Token = 5\n\t\tDD\t36\t; Index = 12 Token = 6\n\t\tDD\t41\t; Index = 12 Token = 7\n\t\tDD\t-2\t; Index = 12 Token = 8\n\t\tDD\t-7\t; Index = 12 Token = 9\n\t\tDD\t-13\t; Index = 12 Token = 10\n\t\tDD\t-18\t; Index = 12 Token = 11\n\t\tDD\t-25\t; Index = 12 Token = 12\n\t\tDD\t-30\t; Index = 12 Token = 13\n\t\tDD\t-36\t; Index = 12 Token = 14\n\t\tDD\t-41\t; Index = 12 Token = 15\n\t\tDD\t3\t; Index = 13 Token = 0\n\t\tDD\t9\t; Index = 13 Token = 1\n\t\tDD\t15\t; Index = 13 Token = 2\n\t\tDD\t21\t; Index = 13 Token = 3\n\t\tDD\t28\t; Index = 13 Token = 4\n\t\tDD\t34\t; Index = 13 Token = 5\n\t\tDD\t40\t; Index = 13 Token = 6\n\t\tDD\t46\t; Index = 13 Token = 7\n\t\tDD\t-3\t; Index = 13 Token = 8\n\t\tDD\t-9\t; Index = 13 Token = 9\n\t\tDD\t-15\t; Index = 13 Token = 10\n\t\tDD\t-21\t; Index = 13 Token = 11\n\t\tDD\t-28\t; Index = 13 Token = 12\n\t\tDD\t-34\t; Index = 13 Token = 13\n\t\tDD\t-40\t; Index = 13 Token = 14\n\t\tDD\t-46\t; Index = 13 Token = 15\n\t\tDD\t3\t; Index = 14 Token = 0\n\t\tDD\t10\t; Index = 14 Token = 1\n\t\tDD\t17\t; Index = 14 Token = 2\n\t\tDD\t24\t; Index = 14 Token = 3\n\t\tDD\t31\t; Index = 14 Token = 4\n\t\tDD\t38\t; Index = 14 Token = 5\n\t\tDD\t45\t; Index = 14 Token = 6\n\t\tDD\t52\t; Index = 14 Token = 7\n\t\tDD\t-3\t; Index = 14 Token = 8\n\t\tDD\t-10\t; Index = 14 Token = 9\n\t\tDD\t-17\t; Index = 14 Token = 10\n\t\tDD\t-24\t; Index = 14 Token = 11\n\t\tDD\t-31\t; Index = 14 Token = 12\n\t\tDD\t-38\t; Index = 14 Token = 13\n\t\tDD\t-45\t; Index = 14 Token = 14\n\t\tDD\t-52\t; Index = 14 Token = 15\n\t\tDD\t3\t; Index = 15 Token = 0\n\t\tDD\t10\t; Index = 15 Token = 1\n\t\tDD\t18\t; Index = 15 Token = 2\n\t\tDD\t25\t; Index = 15 Token = 3\n\t\tDD\t34\t; Index = 15 Token = 4\n\t\tDD\t41\t; Index = 15 Token = 5\n\t\tDD\t49\t; Index = 15 Token = 6\n\t\tDD\t56\t; Index = 15 Token = 7\n\t\tDD\t-3\t; Index = 15 Token = 8\n\t\tDD\t-10\t; Index = 15 Token = 9\n\t\tDD\t-18\t; Index = 15 Token = 10\n\t\tDD\t-25\t; Index = 15 Token = 11\n\t\tDD\t-34\t; Index = 15 Token = 12\n\t\tDD\t-41\t; Index = 15 Token = 13\n\t\tDD\t-49\t; Index = 15 Token = 14\n\t\tDD\t-56\t; Index = 15 Token = 15\n\t\tDD\t4\t; Index = 16 Token = 0\n\t\tDD\t12\t; Index = 16 Token = 1\n\t\tDD\t21\t; Index = 16 Token = 2\n\t\tDD\t29\t; Index = 16 Token = 3\n\t\tDD\t38\t; Index = 16 Token = 4\n\t\tDD\t46\t; Index = 16 Token = 5\n\t\tDD\t55\t; Index = 16 Token = 6\n\t\tDD\t63\t; Index = 16 Token = 7\n\t\tDD\t-4\t; Index = 16 Token = 8\n\t\tDD\t-12\t; Index = 16 Token = 9\n\t\tDD\t-21\t; Index = 16 Token = 10\n\t\tDD\t-29\t; Index = 16 Token = 11\n\t\tDD\t-38\t; Index = 16 Token = 12\n\t\tDD\t-46\t; Index = 16 Token = 13\n\t\tDD\t-55\t; Index = 16 Token = 14\n\t\tDD\t-63\t; Index = 16 Token = 15\n\t\tDD\t4\t; Index = 17 Token = 0\n\t\tDD\t13\t; Index = 17 Token = 1\n\t\tDD\t22\t; Index = 17 Token = 2\n\t\tDD\t31\t; Index = 17 Token = 3\n\t\tDD\t41\t; Index = 17 Token = 4\n\t\tDD\t50\t; Index = 17 Token = 5\n\t\tDD\t59\t; Index = 17 Token = 6\n\t\tDD\t68\t; Index = 17 Token = 7\n\t\tDD\t-4\t; Index = 17 Token = 8\n\t\tDD\t-13\t; Index = 17 Token = 9\n\t\tDD\t-22\t; Index = 17 Token = 10\n\t\tDD\t-31\t; Index = 17 Token = 11\n\t\tDD\t-41\t; Index = 17 Token = 12\n\t\tDD\t-50\t; Index = 17 Token = 13\n\t\tDD\t-59\t; Index = 17 Token = 14\n\t\tDD\t-68\t; Index = 17 Token = 15\n\t\tDD\t5\t; Index = 18 Token = 0\n\t\tDD\t15\t; Index = 18 Token = 1\n\t\tDD\t25\t; Index = 18 Token = 2\n\t\tDD\t35\t; Index = 18 Token = 3\n\t\tDD\t46\t; Index = 18 Token = 4\n\t\tDD\t56\t; Index = 18 Token = 5\n\t\tDD\t66\t; Index = 18 Token = 6\n\t\tDD\t76\t; Index = 18 Token = 7\n\t\tDD\t-5\t; Index = 18 Token = 8\n\t\tDD\t-15\t; Index = 18 Token = 9\n\t\tDD\t-25\t; Index = 18 Token = 10\n\t\tDD\t-35\t; Index = 18 Token = 11\n\t\tDD\t-46\t; Index = 18 Token = 12\n\t\tDD\t-56\t; Index = 18 Token = 13\n\t\tDD\t-66\t; Index = 18 Token = 14\n\t\tDD\t-76\t; Index = 18 Token = 15\n\t\tDD\t5\t; Index = 19 Token = 0\n\t\tDD\t16\t; Index = 19 Token = 1\n\t\tDD\t27\t; Index = 19 Token = 2\n\t\tDD\t38\t; Index = 19 Token = 3\n\t\tDD\t50\t; Index = 19 Token = 4\n\t\tDD\t61\t; Index = 19 Token = 5\n\t\tDD\t72\t; Index = 19 Token = 6\n\t\tDD\t83\t; Index = 19 Token = 7\n\t\tDD\t-5\t; Index = 19 Token = 8\n\t\tDD\t-16\t; Index = 19 Token = 9\n\t\tDD\t-27\t; Index = 19 Token = 10\n\t\tDD\t-38\t; Index = 19 Token = 11\n\t\tDD\t-50\t; Index = 19 Token = 12\n\t\tDD\t-61\t; Index = 19 Token = 13\n\t\tDD\t-72\t; Index = 19 Token = 14\n\t\tDD\t-83\t; Index = 19 Token = 15\n\t\tDD\t6\t; Index = 20 Token = 0\n\t\tDD\t18\t; Index = 20 Token = 1\n\t\tDD\t31\t; Index = 20 Token = 2\n\t\tDD\t43\t; Index = 20 Token = 3\n\t\tDD\t56\t; Index = 20 Token = 4\n\t\tDD\t68\t; Index = 20 Token = 5\n\t\tDD\t81\t; Index = 20 Token = 6\n\t\tDD\t93\t; Index = 20 Token = 7\n\t\tDD\t-6\t; Index = 20 Token = 8\n\t\tDD\t-18\t; Index = 20 Token = 9\n\t\tDD\t-31\t; Index = 20 Token = 10\n\t\tDD\t-43\t; Index = 20 Token = 11\n\t\tDD\t-56\t; Index = 20 Token = 12\n\t\tDD\t-68\t; Index = 20 Token = 13\n\t\tDD\t-81\t; Index = 20 Token = 14\n\t\tDD\t-93\t; Index = 20 Token = 15\n\t\tDD\t6\t; Index = 21 Token = 0\n\t\tDD\t19\t; Index = 21 Token = 1\n\t\tDD\t33\t; Index = 21 Token = 2\n\t\tDD\t46\t; Index = 21 Token = 3\n\t\tDD\t61\t; Index = 21 Token = 4\n\t\tDD\t74\t; Index = 21 Token = 5\n\t\tDD\t88\t; Index = 21 Token = 6\n\t\tDD\t101\t; Index = 21 Token = 7\n\t\tDD\t-6\t; Index = 21 Token = 8\n\t\tDD\t-19\t; Index = 21 Token = 9\n\t\tDD\t-33\t; Index = 21 Token = 10\n\t\tDD\t-46\t; Index = 21 Token = 11\n\t\tDD\t-61\t; Index = 21 Token = 12\n\t\tDD\t-74\t; Index = 21 Token = 13\n\t\tDD\t-88\t; Index = 21 Token = 14\n\t\tDD\t-101\t; Index = 21 Token = 15\n\t\tDD\t7\t; Index = 22 Token = 0\n\t\tDD\t22\t; Index = 22 Token = 1\n\t\tDD\t37\t; Index = 22 Token = 2\n\t\tDD\t52\t; Index = 22 Token = 3\n\t\tDD\t67\t; Index = 22 Token = 4\n\t\tDD\t82\t; Index = 22 Token = 5\n\t\tDD\t97\t; Index = 22 Token = 6\n\t\tDD\t112\t; Index = 22 Token = 7\n\t\tDD\t-7\t; Index = 22 Token = 8\n\t\tDD\t-22\t; Index = 22 Token = 9\n\t\tDD\t-37\t; Index = 22 Token = 10\n\t\tDD\t-52\t; Index = 22 Token = 11\n\t\tDD\t-67\t; Index = 22 Token = 12\n\t\tDD\t-82\t; Index = 22 Token = 13\n\t\tDD\t-97\t; Index = 22 Token = 14\n\t\tDD\t-112\t; Index = 22 Token = 15\n\t\tDD\t8\t; Index = 23 Token = 0\n\t\tDD\t24\t; Index = 23 Token = 1\n\t\tDD\t41\t; Index = 23 Token = 2\n\t\tDD\t57\t; Index = 23 Token = 3\n\t\tDD\t74\t; Index = 23 Token = 4\n\t\tDD\t90\t; Index = 23 Token = 5\n\t\tDD\t107\t; Index = 23 Token = 6\n\t\tDD\t123\t; Index = 23 Token = 7\n\t\tDD\t-8\t; Index = 23 Token = 8\n\t\tDD\t-24\t; Index = 23 Token = 9\n\t\tDD\t-41\t; Index = 23 Token = 10\n\t\tDD\t-57\t; Index = 23 Token = 11\n\t\tDD\t-74\t; Index = 23 Token = 12\n\t\tDD\t-90\t; Index = 23 Token = 13\n\t\tDD\t-107\t; Index = 23 Token = 14\n\t\tDD\t-123\t; Index = 23 Token = 15\n\t\tDD\t9\t; Index = 24 Token = 0\n\t\tDD\t27\t; Index = 24 Token = 1\n\t\tDD\t45\t; Index = 24 Token = 2\n\t\tDD\t63\t; Index = 24 Token = 3\n\t\tDD\t82\t; Index = 24 Token = 4\n\t\tDD\t100\t; Index = 24 Token = 5\n\t\tDD\t118\t; Index = 24 Token = 6\n\t\tDD\t136\t; Index = 24 Token = 7\n\t\tDD\t-9\t; Index = 24 Token = 8\n\t\tDD\t-27\t; Index = 24 Token = 9\n\t\tDD\t-45\t; Index = 24 Token = 10\n\t\tDD\t-63\t; Index = 24 Token = 11\n\t\tDD\t-82\t; Index = 24 Token = 12\n\t\tDD\t-100\t; Index = 24 Token = 13\n\t\tDD\t-118\t; Index = 24 Token = 14\n\t\tDD\t-136\t; Index = 24 Token = 15\n\t\tDD\t10\t; Index = 25 Token = 0\n\t\tDD\t30\t; Index = 25 Token = 1\n\t\tDD\t50\t; Index = 25 Token = 2\n\t\tDD\t70\t; Index = 25 Token = 3\n\t\tDD\t90\t; Index = 25 Token = 4\n\t\tDD\t110\t; Index = 25 Token = 5\n\t\tDD\t130\t; Index = 25 Token = 6\n\t\tDD\t150\t; Index = 25 Token = 7\n\t\tDD\t-10\t; Index = 25 Token = 8\n\t\tDD\t-30\t; Index = 25 Token = 9\n\t\tDD\t-50\t; Index = 25 Token = 10\n\t\tDD\t-70\t; Index = 25 Token = 11\n\t\tDD\t-90\t; Index = 25 Token = 12\n\t\tDD\t-110\t; Index = 25 Token = 13\n\t\tDD\t-130\t; Index = 25 Token = 14\n\t\tDD\t-150\t; Index = 25 Token = 15\n\t\tDD\t11\t; Index = 26 Token = 0\n\t\tDD\t33\t; Index = 26 Token = 1\n\t\tDD\t55\t; Index = 26 Token = 2\n\t\tDD\t77\t; Index = 26 Token = 3\n\t\tDD\t99\t; Index = 26 Token = 4\n\t\tDD\t121\t; Index = 26 Token = 5\n\t\tDD\t143\t; Index = 26 Token = 6\n\t\tDD\t165\t; Index = 26 Token = 7\n\t\tDD\t-11\t; Index = 26 Token = 8\n\t\tDD\t-33\t; Index = 26 Token = 9\n\t\tDD\t-55\t; Index = 26 Token = 10\n\t\tDD\t-77\t; Index = 26 Token = 11\n\t\tDD\t-99\t; Index = 26 Token = 12\n\t\tDD\t-121\t; Index = 26 Token = 13\n\t\tDD\t-143\t; Index = 26 Token = 14\n\t\tDD\t-165\t; Index = 26 Token = 15\n\t\tDD\t12\t; Index = 27 Token = 0\n\t\tDD\t36\t; Index = 27 Token = 1\n\t\tDD\t60\t; Index = 27 Token = 2\n\t\tDD\t84\t; Index = 27 Token = 3\n\t\tDD\t109\t; Index = 27 Token = 4\n\t\tDD\t133\t; Index = 27 Token = 5\n\t\tDD\t157\t; Index = 27 Token = 6\n\t\tDD\t181\t; Index = 27 Token = 7\n\t\tDD\t-12\t; Index = 27 Token = 8\n\t\tDD\t-36\t; Index = 27 Token = 9\n\t\tDD\t-60\t; Index = 27 Token = 10\n\t\tDD\t-84\t; Index = 27 Token = 11\n\t\tDD\t-109\t; Index = 27 Token = 12\n\t\tDD\t-133\t; Index = 27 Token = 13\n\t\tDD\t-157\t; Index = 27 Token = 14\n\t\tDD\t-181\t; Index = 27 Token = 15\n\t\tDD\t13\t; Index = 28 Token = 0\n\t\tDD\t39\t; Index = 28 Token = 1\n\t\tDD\t66\t; Index = 28 Token = 2\n\t\tDD\t92\t; Index = 28 Token = 3\n\t\tDD\t120\t; Index = 28 Token = 4\n\t\tDD\t146\t; Index = 28 Token = 5\n\t\tDD\t173\t; Index = 28 Token = 6\n\t\tDD\t199\t; Index = 28 Token = 7\n\t\tDD\t-13\t; Index = 28 Token = 8\n\t\tDD\t-39\t; Index = 28 Token = 9\n\t\tDD\t-66\t; Index = 28 Token = 10\n\t\tDD\t-92\t; Index = 28 Token = 11\n\t\tDD\t-120\t; Index = 28 Token = 12\n\t\tDD\t-146\t; Index = 28 Token = 13\n\t\tDD\t-173\t; Index = 28 Token = 14\n\t\tDD\t-199\t; Index = 28 Token = 15\n\t\tDD\t14\t; Index = 29 Token = 0\n\t\tDD\t43\t; Index = 29 Token = 1\n\t\tDD\t73\t; Index = 29 Token = 2\n\t\tDD\t102\t; Index = 29 Token = 3\n\t\tDD\t132\t; Index = 29 Token = 4\n\t\tDD\t161\t; Index = 29 Token = 5\n\t\tDD\t191\t; Index = 29 Token = 6\n\t\tDD\t220\t; Index = 29 Token = 7\n\t\tDD\t-14\t; Index = 29 Token = 8\n\t\tDD\t-43\t; Index = 29 Token = 9\n\t\tDD\t-73\t; Index = 29 Token = 10\n\t\tDD\t-102\t; Index = 29 Token = 11\n\t\tDD\t-132\t; Index = 29 Token = 12\n\t\tDD\t-161\t; Index = 29 Token = 13\n\t\tDD\t-191\t; Index = 29 Token = 14\n\t\tDD\t-220\t; Index = 29 Token = 15\n\t\tDD\t16\t; Index = 30 Token = 0\n\t\tDD\t48\t; Index = 30 Token = 1\n\t\tDD\t81\t; Index = 30 Token = 2\n\t\tDD\t113\t; Index = 30 Token = 3\n\t\tDD\t146\t; Index = 30 Token = 4\n\t\tDD\t178\t; Index = 30 Token = 5\n\t\tDD\t211\t; Index = 30 Token = 6\n\t\tDD\t243\t; Index = 30 Token = 7\n\t\tDD\t-16\t; Index = 30 Token = 8\n\t\tDD\t-48\t; Index = 30 Token = 9\n\t\tDD\t-81\t; Index = 30 Token = 10\n\t\tDD\t-113\t; Index = 30 Token = 11\n\t\tDD\t-146\t; Index = 30 Token = 12\n\t\tDD\t-178\t; Index = 30 Token = 13\n\t\tDD\t-211\t; Index = 30 Token = 14\n\t\tDD\t-243\t; Index = 30 Token = 15\n\t\tDD\t17\t; Index = 31 Token = 0\n\t\tDD\t52\t; Index = 31 Token = 1\n\t\tDD\t88\t; Index = 31 Token = 2\n\t\tDD\t123\t; Index = 31 Token = 3\n\t\tDD\t160\t; Index = 31 Token = 4\n\t\tDD\t195\t; Index = 31 Token = 5\n\t\tDD\t231\t; Index = 31 Token = 6\n\t\tDD\t266\t; Index = 31 Token = 7\n\t\tDD\t-17\t; Index = 31 Token = 8\n\t\tDD\t-52\t; Index = 31 Token = 9\n\t\tDD\t-88\t; Index = 31 Token = 10\n\t\tDD\t-123\t; Index = 31 Token = 11\n\t\tDD\t-160\t; Index = 31 Token = 12\n\t\tDD\t-195\t; Index = 31 Token = 13\n\t\tDD\t-231\t; Index = 31 Token = 14\n\t\tDD\t-266\t; Index = 31 Token = 15\n\t\tDD\t19\t; Index = 32 Token = 0\n\t\tDD\t58\t; Index = 32 Token = 1\n\t\tDD\t97\t; Index = 32 Token = 2\n\t\tDD\t136\t; Index = 32 Token = 3\n\t\tDD\t176\t; Index = 32 Token = 4\n\t\tDD\t215\t; Index = 32 Token = 5\n\t\tDD\t254\t; Index = 32 Token = 6\n\t\tDD\t293\t; Index = 32 Token = 7\n\t\tDD\t-19\t; Index = 32 Token = 8\n\t\tDD\t-58\t; Index = 32 Token = 9\n\t\tDD\t-97\t; Index = 32 Token = 10\n\t\tDD\t-136\t; Index = 32 Token = 11\n\t\tDD\t-176\t; Index = 32 Token = 12\n\t\tDD\t-215\t; Index = 32 Token = 13\n\t\tDD\t-254\t; Index = 32 Token = 14\n\t\tDD\t-293\t; Index = 32 Token = 15\n\t\tDD\t21\t; Index = 33 Token = 0\n\t\tDD\t64\t; Index = 33 Token = 1\n\t\tDD\t107\t; Index = 33 Token = 2\n\t\tDD\t150\t; Index = 33 Token = 3\n\t\tDD\t194\t; Index = 33 Token = 4\n\t\tDD\t237\t; Index = 33 Token = 5\n\t\tDD\t280\t; Index = 33 Token = 6\n\t\tDD\t323\t; Index = 33 Token = 7\n\t\tDD\t-21\t; Index = 33 Token = 8\n\t\tDD\t-64\t; Index = 33 Token = 9\n\t\tDD\t-107\t; Index = 33 Token = 10\n\t\tDD\t-150\t; Index = 33 Token = 11\n\t\tDD\t-194\t; Index = 33 Token = 12\n\t\tDD\t-237\t; Index = 33 Token = 13\n\t\tDD\t-280\t; Index = 33 Token = 14\n\t\tDD\t-323\t; Index = 33 Token = 15\n\t\tDD\t23\t; Index = 34 Token = 0\n\t\tDD\t70\t; Index = 34 Token = 1\n\t\tDD\t118\t; Index = 34 Token = 2\n\t\tDD\t165\t; Index = 34 Token = 3\n\t\tDD\t213\t; Index = 34 Token = 4\n\t\tDD\t260\t; Index = 34 Token = 5\n\t\tDD\t308\t; Index = 34 Token = 6\n\t\tDD\t355\t; Index = 34 Token = 7\n\t\tDD\t-23\t; Index = 34 Token = 8\n\t\tDD\t-70\t; Index = 34 Token = 9\n\t\tDD\t-118\t; Index = 34 Token = 10\n\t\tDD\t-165\t; Index = 34 Token = 11\n\t\tDD\t-213\t; Index = 34 Token = 12\n\t\tDD\t-260\t; Index = 34 Token = 13\n\t\tDD\t-308\t; Index = 34 Token = 14\n\t\tDD\t-355\t; Index = 34 Token = 15\n\t\tDD\t26\t; Index = 35 Token = 0\n\t\tDD\t78\t; Index = 35 Token = 1\n\t\tDD\t130\t; Index = 35 Token = 2\n\t\tDD\t182\t; Index = 35 Token = 3\n\t\tDD\t235\t; Index = 35 Token = 4\n\t\tDD\t287\t; Index = 35 Token = 5\n\t\tDD\t339\t; Index = 35 Token = 6\n\t\tDD\t391\t; Index = 35 Token = 7\n\t\tDD\t-26\t; Index = 35 Token = 8\n\t\tDD\t-78\t; Index = 35 Token = 9\n\t\tDD\t-130\t; Index = 35 Token = 10\n\t\tDD\t-182\t; Index = 35 Token = 11\n\t\tDD\t-235\t; Index = 35 Token = 12\n\t\tDD\t-287\t; Index = 35 Token = 13\n\t\tDD\t-339\t; Index = 35 Token = 14\n\t\tDD\t-391\t; Index = 35 Token = 15\n\t\tDD\t28\t; Index = 36 Token = 0\n\t\tDD\t85\t; Index = 36 Token = 1\n\t\tDD\t143\t; Index = 36 Token = 2\n\t\tDD\t200\t; Index = 36 Token = 3\n\t\tDD\t258\t; Index = 36 Token = 4\n\t\tDD\t315\t; Index = 36 Token = 5\n\t\tDD\t373\t; Index = 36 Token = 6\n\t\tDD\t430\t; Index = 36 Token = 7\n\t\tDD\t-28\t; Index = 36 Token = 8\n\t\tDD\t-85\t; Index = 36 Token = 9\n\t\tDD\t-143\t; Index = 36 Token = 10\n\t\tDD\t-200\t; Index = 36 Token = 11\n\t\tDD\t-258\t; Index = 36 Token = 12\n\t\tDD\t-315\t; Index = 36 Token = 13\n\t\tDD\t-373\t; Index = 36 Token = 14\n\t\tDD\t-430\t; Index = 36 Token = 15\n\t\tDD\t31\t; Index = 37 Token = 0\n\t\tDD\t94\t; Index = 37 Token = 1\n\t\tDD\t157\t; Index = 37 Token = 2\n\t\tDD\t220\t; Index = 37 Token = 3\n\t\tDD\t284\t; Index = 37 Token = 4\n\t\tDD\t347\t; Index = 37 Token = 5\n\t\tDD\t410\t; Index = 37 Token = 6\n\t\tDD\t473\t; Index = 37 Token = 7\n\t\tDD\t-31\t; Index = 37 Token = 8\n\t\tDD\t-94\t; Index = 37 Token = 9\n\t\tDD\t-157\t; Index = 37 Token = 10\n\t\tDD\t-220\t; Index = 37 Token = 11\n\t\tDD\t-284\t; Index = 37 Token = 12\n\t\tDD\t-347\t; Index = 37 Token = 13\n\t\tDD\t-410\t; Index = 37 Token = 14\n\t\tDD\t-473\t; Index = 37 Token = 15\n\t\tDD\t34\t; Index = 38 Token = 0\n\t\tDD\t103\t; Index = 38 Token = 1\n\t\tDD\t173\t; Index = 38 Token = 2\n\t\tDD\t242\t; Index = 38 Token = 3\n\t\tDD\t313\t; Index = 38 Token = 4\n\t\tDD\t382\t; Index = 38 Token = 5\n\t\tDD\t452\t; Index = 38 Token = 6\n\t\tDD\t521\t; Index = 38 Token = 7\n\t\tDD\t-34\t; Index = 38 Token = 8\n\t\tDD\t-103\t; Index = 38 Token = 9\n\t\tDD\t-173\t; Index = 38 Token = 10\n\t\tDD\t-242\t; Index = 38 Token = 11\n\t\tDD\t-313\t; Index = 38 Token = 12\n\t\tDD\t-382\t; Index = 38 Token = 13\n\t\tDD\t-452\t; Index = 38 Token = 14\n\t\tDD\t-521\t; Index = 38 Token = 15\n\t\tDD\t38\t; Index = 39 Token = 0\n\t\tDD\t114\t; Index = 39 Token = 1\n\t\tDD\t191\t; Index = 39 Token = 2\n\t\tDD\t267\t; Index = 39 Token = 3\n\t\tDD\t345\t; Index = 39 Token = 4\n\t\tDD\t421\t; Index = 39 Token = 5\n\t\tDD\t498\t; Index = 39 Token = 6\n\t\tDD\t574\t; Index = 39 Token = 7\n\t\tDD\t-38\t; Index = 39 Token = 8\n\t\tDD\t-114\t; Index = 39 Token = 9\n\t\tDD\t-191\t; Index = 39 Token = 10\n\t\tDD\t-267\t; Index = 39 Token = 11\n\t\tDD\t-345\t; Index = 39 Token = 12\n\t\tDD\t-421\t; Index = 39 Token = 13\n\t\tDD\t-498\t; Index = 39 Token = 14\n\t\tDD\t-574\t; Index = 39 Token = 15\n\t\tDD\t42\t; Index = 40 Token = 0\n\t\tDD\t126\t; Index = 40 Token = 1\n\t\tDD\t210\t; Index = 40 Token = 2\n\t\tDD\t294\t; Index = 40 Token = 3\n\t\tDD\t379\t; Index = 40 Token = 4\n\t\tDD\t463\t; Index = 40 Token = 5\n\t\tDD\t547\t; Index = 40 Token = 6\n\t\tDD\t631\t; Index = 40 Token = 7\n\t\tDD\t-42\t; Index = 40 Token = 8\n\t\tDD\t-126\t; Index = 40 Token = 9\n\t\tDD\t-210\t; Index = 40 Token = 10\n\t\tDD\t-294\t; Index = 40 Token = 11\n\t\tDD\t-379\t; Index = 40 Token = 12\n\t\tDD\t-463\t; Index = 40 Token = 13\n\t\tDD\t-547\t; Index = 40 Token = 14\n\t\tDD\t-631\t; Index = 40 Token = 15\n\t\tDD\t46\t; Index = 41 Token = 0\n\t\tDD\t138\t; Index = 41 Token = 1\n\t\tDD\t231\t; Index = 41 Token = 2\n\t\tDD\t323\t; Index = 41 Token = 3\n\t\tDD\t417\t; Index = 41 Token = 4\n\t\tDD\t509\t; Index = 41 Token = 5\n\t\tDD\t602\t; Index = 41 Token = 6\n\t\tDD\t694\t; Index = 41 Token = 7\n\t\tDD\t-46\t; Index = 41 Token = 8\n\t\tDD\t-138\t; Index = 41 Token = 9\n\t\tDD\t-231\t; Index = 41 Token = 10\n\t\tDD\t-323\t; Index = 41 Token = 11\n\t\tDD\t-417\t; Index = 41 Token = 12\n\t\tDD\t-509\t; Index = 41 Token = 13\n\t\tDD\t-602\t; Index = 41 Token = 14\n\t\tDD\t-694\t; Index = 41 Token = 15\n\t\tDD\t51\t; Index = 42 Token = 0\n\t\tDD\t153\t; Index = 42 Token = 1\n\t\tDD\t255\t; Index = 42 Token = 2\n\t\tDD\t357\t; Index = 42 Token = 3\n\t\tDD\t459\t; Index = 42 Token = 4\n\t\tDD\t561\t; Index = 42 Token = 5\n\t\tDD\t663\t; Index = 42 Token = 6\n\t\tDD\t765\t; Index = 42 Token = 7\n\t\tDD\t-51\t; Index = 42 Token = 8\n\t\tDD\t-153\t; Index = 42 Token = 9\n\t\tDD\t-255\t; Index = 42 Token = 10\n\t\tDD\t-357\t; Index = 42 Token = 11\n\t\tDD\t-459\t; Index = 42 Token = 12\n\t\tDD\t-561\t; Index = 42 Token = 13\n\t\tDD\t-663\t; Index = 42 Token = 14\n\t\tDD\t-765\t; Index = 42 Token = 15\n\t\tDD\t56\t; Index = 43 Token = 0\n\t\tDD\t168\t; Index = 43 Token = 1\n\t\tDD\t280\t; Index = 43 Token = 2\n\t\tDD\t392\t; Index = 43 Token = 3\n\t\tDD\t505\t; Index = 43 Token = 4\n\t\tDD\t617\t; Index = 43 Token = 5\n\t\tDD\t729\t; Index = 43 Token = 6\n\t\tDD\t841\t; Index = 43 Token = 7\n\t\tDD\t-56\t; Index = 43 Token = 8\n\t\tDD\t-168\t; Index = 43 Token = 9\n\t\tDD\t-280\t; Index = 43 Token = 10\n\t\tDD\t-392\t; Index = 43 Token = 11\n\t\tDD\t-505\t; Index = 43 Token = 12\n\t\tDD\t-617\t; Index = 43 Token = 13\n\t\tDD\t-729\t; Index = 43 Token = 14\n\t\tDD\t-841\t; Index = 43 Token = 15\n\t\tDD\t61\t; Index = 44 Token = 0\n\t\tDD\t184\t; Index = 44 Token = 1\n\t\tDD\t308\t; Index = 44 Token = 2\n\t\tDD\t431\t; Index = 44 Token = 3\n\t\tDD\t555\t; Index = 44 Token = 4\n\t\tDD\t678\t; Index = 44 Token = 5\n\t\tDD\t802\t; Index = 44 Token = 6\n\t\tDD\t925\t; Index = 44 Token = 7\n\t\tDD\t-61\t; Index = 44 Token = 8\n\t\tDD\t-184\t; Index = 44 Token = 9\n\t\tDD\t-308\t; Index = 44 Token = 10\n\t\tDD\t-431\t; Index = 44 Token = 11\n\t\tDD\t-555\t; Index = 44 Token = 12\n\t\tDD\t-678\t; Index = 44 Token = 13\n\t\tDD\t-802\t; Index = 44 Token = 14\n\t\tDD\t-925\t; Index = 44 Token = 15\n\t\tDD\t68\t; Index = 45 Token = 0\n\t\tDD\t204\t; Index = 45 Token = 1\n\t\tDD\t340\t; Index = 45 Token = 2\n\t\tDD\t476\t; Index = 45 Token = 3\n\t\tDD\t612\t; Index = 45 Token = 4\n\t\tDD\t748\t; Index = 45 Token = 5\n\t\tDD\t884\t; Index = 45 Token = 6\n\t\tDD\t1020\t; Index = 45 Token = 7\n\t\tDD\t-68\t; Index = 45 Token = 8\n\t\tDD\t-204\t; Index = 45 Token = 9\n\t\tDD\t-340\t; Index = 45 Token = 10\n\t\tDD\t-476\t; Index = 45 Token = 11\n\t\tDD\t-612\t; Index = 45 Token = 12\n\t\tDD\t-748\t; Index = 45 Token = 13\n\t\tDD\t-884\t; Index = 45 Token = 14\n\t\tDD\t-1020\t; Index = 45 Token = 15\n\t\tDD\t74\t; Index = 46 Token = 0\n\t\tDD\t223\t; Index = 46 Token = 1\n\t\tDD\t373\t; Index = 46 Token = 2\n\t\tDD\t522\t; Index = 46 Token = 3\n\t\tDD\t672\t; Index = 46 Token = 4\n\t\tDD\t821\t; Index = 46 Token = 5\n\t\tDD\t971\t; Index = 46 Token = 6\n\t\tDD\t1120\t; Index = 46 Token = 7\n\t\tDD\t-74\t; Index = 46 Token = 8\n\t\tDD\t-223\t; Index = 46 Token = 9\n\t\tDD\t-373\t; Index = 46 Token = 10\n\t\tDD\t-522\t; Index = 46 Token = 11\n\t\tDD\t-672\t; Index = 46 Token = 12\n\t\tDD\t-821\t; Index = 46 Token = 13\n\t\tDD\t-971\t; Index = 46 Token = 14\n\t\tDD\t-1120\t; Index = 46 Token = 15\n\t\tDD\t82\t; Index = 47 Token = 0\n\t\tDD\t246\t; Index = 47 Token = 1\n\t\tDD\t411\t; Index = 47 Token = 2\n\t\tDD\t575\t; Index = 47 Token = 3\n\t\tDD\t740\t; Index = 47 Token = 4\n\t\tDD\t904\t; Index = 47 Token = 5\n\t\tDD\t1069\t; Index = 47 Token = 6\n\t\tDD\t1233\t; Index = 47 Token = 7\n\t\tDD\t-82\t; Index = 47 Token = 8\n\t\tDD\t-246\t; Index = 47 Token = 9\n\t\tDD\t-411\t; Index = 47 Token = 10\n\t\tDD\t-575\t; Index = 47 Token = 11\n\t\tDD\t-740\t; Index = 47 Token = 12\n\t\tDD\t-904\t; Index = 47 Token = 13\n\t\tDD\t-1069\t; Index = 47 Token = 14\n\t\tDD\t-1233\t; Index = 47 Token = 15\n\t\tDD\t90\t; Index = 48 Token = 0\n\t\tDD\t271\t; Index = 48 Token = 1\n\t\tDD\t452\t; Index = 48 Token = 2\n\t\tDD\t633\t; Index = 48 Token = 3\n\t\tDD\t814\t; Index = 48 Token = 4\n\t\tDD\t995\t; Index = 48 Token = 5\n\t\tDD\t1176\t; Index = 48 Token = 6\n\t\tDD\t1357\t; Index = 48 Token = 7\n\t\tDD\t-90\t; Index = 48 Token = 8\n\t\tDD\t-271\t; Index = 48 Token = 9\n\t\tDD\t-452\t; Index = 48 Token = 10\n\t\tDD\t-633\t; Index = 48 Token = 11\n\t\tDD\t-814\t; Index = 48 Token = 12\n\t\tDD\t-995\t; Index = 48 Token = 13\n\t\tDD\t-1176\t; Index = 48 Token = 14\n\t\tDD\t-1357\t; Index = 48 Token = 15\n\t\tDD\t99\t; Index = 49 Token = 0\n\t\tDD\t298\t; Index = 49 Token = 1\n\t\tDD\t497\t; Index = 49 Token = 2\n\t\tDD\t696\t; Index = 49 Token = 3\n\t\tDD\t895\t; Index = 49 Token = 4\n\t\tDD\t1094\t; Index = 49 Token = 5\n\t\tDD\t1293\t; Index = 49 Token = 6\n\t\tDD\t1492\t; Index = 49 Token = 7\n\t\tDD\t-99\t; Index = 49 Token = 8\n\t\tDD\t-298\t; Index = 49 Token = 9\n\t\tDD\t-497\t; Index = 49 Token = 10\n\t\tDD\t-696\t; Index = 49 Token = 11\n\t\tDD\t-895\t; Index = 49 Token = 12\n\t\tDD\t-1094\t; Index = 49 Token = 13\n\t\tDD\t-1293\t; Index = 49 Token = 14\n\t\tDD\t-1492\t; Index = 49 Token = 15\n\t\tDD\t109\t; Index = 50 Token = 0\n\t\tDD\t328\t; Index = 50 Token = 1\n\t\tDD\t547\t; Index = 50 Token = 2\n\t\tDD\t766\t; Index = 50 Token = 3\n\t\tDD\t985\t; Index = 50 Token = 4\n\t\tDD\t1204\t; Index = 50 Token = 5\n\t\tDD\t1423\t; Index = 50 Token = 6\n\t\tDD\t1642\t; Index = 50 Token = 7\n\t\tDD\t-109\t; Index = 50 Token = 8\n\t\tDD\t-328\t; Index = 50 Token = 9\n\t\tDD\t-547\t; Index = 50 Token = 10\n\t\tDD\t-766\t; Index = 50 Token = 11\n\t\tDD\t-985\t; Index = 50 Token = 12\n\t\tDD\t-1204\t; Index = 50 Token = 13\n\t\tDD\t-1423\t; Index = 50 Token = 14\n\t\tDD\t-1642\t; Index = 50 Token = 15\n\t\tDD\t120\t; Index = 51 Token = 0\n\t\tDD\t360\t; Index = 51 Token = 1\n\t\tDD\t601\t; Index = 51 Token = 2\n\t\tDD\t841\t; Index = 51 Token = 3\n\t\tDD\t1083\t; Index = 51 Token = 4\n\t\tDD\t1323\t; Index = 51 Token = 5\n\t\tDD\t1564\t; Index = 51 Token = 6\n\t\tDD\t1804\t; Index = 51 Token = 7\n\t\tDD\t-120\t; Index = 51 Token = 8\n\t\tDD\t-360\t; Index = 51 Token = 9\n\t\tDD\t-601\t; Index = 51 Token = 10\n\t\tDD\t-841\t; Index = 51 Token = 11\n\t\tDD\t-1083\t; Index = 51 Token = 12\n\t\tDD\t-1323\t; Index = 51 Token = 13\n\t\tDD\t-1564\t; Index = 51 Token = 14\n\t\tDD\t-1804\t; Index = 51 Token = 15\n\t\tDD\t132\t; Index = 52 Token = 0\n\t\tDD\t397\t; Index = 52 Token = 1\n\t\tDD\t662\t; Index = 52 Token = 2\n\t\tDD\t927\t; Index = 52 Token = 3\n\t\tDD\t1192\t; Index = 52 Token = 4\n\t\tDD\t1457\t; Index = 52 Token = 5\n\t\tDD\t1722\t; Index = 52 Token = 6\n\t\tDD\t1987\t; Index = 52 Token = 7\n\t\tDD\t-132\t; Index = 52 Token = 8\n\t\tDD\t-397\t; Index = 52 Token = 9\n\t\tDD\t-662\t; Index = 52 Token = 10\n\t\tDD\t-927\t; Index = 52 Token = 11\n\t\tDD\t-1192\t; Index = 52 Token = 12\n\t\tDD\t-1457\t; Index = 52 Token = 13\n\t\tDD\t-1722\t; Index = 52 Token = 14\n\t\tDD\t-1987\t; Index = 52 Token = 15\n\t\tDD\t145\t; Index = 53 Token = 0\n\t\tDD\t436\t; Index = 53 Token = 1\n\t\tDD\t728\t; Index = 53 Token = 2\n\t\tDD\t1019\t; Index = 53 Token = 3\n\t\tDD\t1311\t; Index = 53 Token = 4\n\t\tDD\t1602\t; Index = 53 Token = 5\n\t\tDD\t1894\t; Index = 53 Token = 6\n\t\tDD\t2185\t; Index = 53 Token = 7\n\t\tDD\t-145\t; Index = 53 Token = 8\n\t\tDD\t-436\t; Index = 53 Token = 9\n\t\tDD\t-728\t; Index = 53 Token = 10\n\t\tDD\t-1019\t; Index = 53 Token = 11\n\t\tDD\t-1311\t; Index = 53 Token = 12\n\t\tDD\t-1602\t; Index = 53 Token = 13\n\t\tDD\t-1894\t; Index = 53 Token = 14\n\t\tDD\t-2185\t; Index = 53 Token = 15\n\t\tDD\t160\t; Index = 54 Token = 0\n\t\tDD\t480\t; Index = 54 Token = 1\n\t\tDD\t801\t; Index = 54 Token = 2\n\t\tDD\t1121\t; Index = 54 Token = 3\n\t\tDD\t1442\t; Index = 54 Token = 4\n\t\tDD\t1762\t; Index = 54 Token = 5\n\t\tDD\t2083\t; Index = 54 Token = 6\n\t\tDD\t2403\t; Index = 54 Token = 7\n\t\tDD\t-160\t; Index = 54 Token = 8\n\t\tDD\t-480\t; Index = 54 Token = 9\n\t\tDD\t-801\t; Index = 54 Token = 10\n\t\tDD\t-1121\t; Index = 54 Token = 11\n\t\tDD\t-1442\t; Index = 54 Token = 12\n\t\tDD\t-1762\t; Index = 54 Token = 13\n\t\tDD\t-2083\t; Index = 54 Token = 14\n\t\tDD\t-2403\t; Index = 54 Token = 15\n\t\tDD\t176\t; Index = 55 Token = 0\n\t\tDD\t528\t; Index = 55 Token = 1\n\t\tDD\t881\t; Index = 55 Token = 2\n\t\tDD\t1233\t; Index = 55 Token = 3\n\t\tDD\t1587\t; Index = 55 Token = 4\n\t\tDD\t1939\t; Index = 55 Token = 5\n\t\tDD\t2292\t; Index = 55 Token = 6\n\t\tDD\t2644\t; Index = 55 Token = 7\n\t\tDD\t-176\t; Index = 55 Token = 8\n\t\tDD\t-528\t; Index = 55 Token = 9\n\t\tDD\t-881\t; Index = 55 Token = 10\n\t\tDD\t-1233\t; Index = 55 Token = 11\n\t\tDD\t-1587\t; Index = 55 Token = 12\n\t\tDD\t-1939\t; Index = 55 Token = 13\n\t\tDD\t-2292\t; Index = 55 Token = 14\n\t\tDD\t-2644\t; Index = 55 Token = 15\n\t\tDD\t194\t; Index = 56 Token = 0\n\t\tDD\t582\t; Index = 56 Token = 1\n\t\tDD\t970\t; Index = 56 Token = 2\n\t\tDD\t1358\t; Index = 56 Token = 3\n\t\tDD\t1746\t; Index = 56 Token = 4\n\t\tDD\t2134\t; Index = 56 Token = 5\n\t\tDD\t2522\t; Index = 56 Token = 6\n\t\tDD\t2910\t; Index = 56 Token = 7\n\t\tDD\t-194\t; Index = 56 Token = 8\n\t\tDD\t-582\t; Index = 56 Token = 9\n\t\tDD\t-970\t; Index = 56 Token = 10\n\t\tDD\t-1358\t; Index = 56 Token = 11\n\t\tDD\t-1746\t; Index = 56 Token = 12\n\t\tDD\t-2134\t; Index = 56 Token = 13\n\t\tDD\t-2522\t; Index = 56 Token = 14\n\t\tDD\t-2910\t; Index = 56 Token = 15\n\t\tDD\t213\t; Index = 57 Token = 0\n\t\tDD\t639\t; Index = 57 Token = 1\n\t\tDD\t1066\t; Index = 57 Token = 2\n\t\tDD\t1492\t; Index = 57 Token = 3\n\t\tDD\t1920\t; Index = 57 Token = 4\n\t\tDD\t2346\t; Index = 57 Token = 5\n\t\tDD\t2773\t; Index = 57 Token = 6\n\t\tDD\t3199\t; Index = 57 Token = 7\n\t\tDD\t-213\t; Index = 57 Token = 8\n\t\tDD\t-639\t; Index = 57 Token = 9\n\t\tDD\t-1066\t; Index = 57 Token = 10\n\t\tDD\t-1492\t; Index = 57 Token = 11\n\t\tDD\t-1920\t; Index = 57 Token = 12\n\t\tDD\t-2346\t; Index = 57 Token = 13\n\t\tDD\t-2773\t; Index = 57 Token = 14\n\t\tDD\t-3199\t; Index = 57 Token = 15\n\t\tDD\t234\t; Index = 58 Token = 0\n\t\tDD\t703\t; Index = 58 Token = 1\n\t\tDD\t1173\t; Index = 58 Token = 2\n\t\tDD\t1642\t; Index = 58 Token = 3\n\t\tDD\t2112\t; Index = 58 Token = 4\n\t\tDD\t2581\t; Index = 58 Token = 5\n\t\tDD\t3051\t; Index = 58 Token = 6\n\t\tDD\t3520\t; Index = 58 Token = 7\n\t\tDD\t-234\t; Index = 58 Token = 8\n\t\tDD\t-703\t; Index = 58 Token = 9\n\t\tDD\t-1173\t; Index = 58 Token = 10\n\t\tDD\t-1642\t; Index = 58 Token = 11\n\t\tDD\t-2112\t; Index = 58 Token = 12\n\t\tDD\t-2581\t; Index = 58 Token = 13\n\t\tDD\t-3051\t; Index = 58 Token = 14\n\t\tDD\t-3520\t; Index = 58 Token = 15\n\t\tDD\t258\t; Index = 59 Token = 0\n\t\tDD\t774\t; Index = 59 Token = 1\n\t\tDD\t1291\t; Index = 59 Token = 2\n\t\tDD\t1807\t; Index = 59 Token = 3\n\t\tDD\t2324\t; Index = 59 Token = 4\n\t\tDD\t2840\t; Index = 59 Token = 5\n\t\tDD\t3357\t; Index = 59 Token = 6\n\t\tDD\t3873\t; Index = 59 Token = 7\n\t\tDD\t-258\t; Index = 59 Token = 8\n\t\tDD\t-774\t; Index = 59 Token = 9\n\t\tDD\t-1291\t; Index = 59 Token = 10\n\t\tDD\t-1807\t; Index = 59 Token = 11\n\t\tDD\t-2324\t; Index = 59 Token = 12\n\t\tDD\t-2840\t; Index = 59 Token = 13\n\t\tDD\t-3357\t; Index = 59 Token = 14\n\t\tDD\t-3873\t; Index = 59 Token = 15\n\t\tDD\t284\t; Index = 60 Token = 0\n\t\tDD\t852\t; Index = 60 Token = 1\n\t\tDD\t1420\t; Index = 60 Token = 2\n\t\tDD\t1988\t; Index = 60 Token = 3\n\t\tDD\t2556\t; Index = 60 Token = 4\n\t\tDD\t3124\t; Index = 60 Token = 5\n\t\tDD\t3692\t; Index = 60 Token = 6\n\t\tDD\t4260\t; Index = 60 Token = 7\n\t\tDD\t-284\t; Index = 60 Token = 8\n\t\tDD\t-852\t; Index = 60 Token = 9\n\t\tDD\t-1420\t; Index = 60 Token = 10\n\t\tDD\t-1988\t; Index = 60 Token = 11\n\t\tDD\t-2556\t; Index = 60 Token = 12\n\t\tDD\t-3124\t; Index = 60 Token = 13\n\t\tDD\t-3692\t; Index = 60 Token = 14\n\t\tDD\t-4260\t; Index = 60 Token = 15\n\t\tDD\t312\t; Index = 61 Token = 0\n\t\tDD\t936\t; Index = 61 Token = 1\n\t\tDD\t1561\t; Index = 61 Token = 2\n\t\tDD\t2185\t; Index = 61 Token = 3\n\t\tDD\t2811\t; Index = 61 Token = 4\n\t\tDD\t3435\t; Index = 61 Token = 5\n\t\tDD\t4060\t; Index = 61 Token = 6\n\t\tDD\t4684\t; Index = 61 Token = 7\n\t\tDD\t-312\t; Index = 61 Token = 8\n\t\tDD\t-936\t; Index = 61 Token = 9\n\t\tDD\t-1561\t; Index = 61 Token = 10\n\t\tDD\t-2185\t; Index = 61 Token = 11\n\t\tDD\t-2811\t; Index = 61 Token = 12\n\t\tDD\t-3435\t; Index = 61 Token = 13\n\t\tDD\t-4060\t; Index = 61 Token = 14\n\t\tDD\t-4684\t; Index = 61 Token = 15\n\t\tDD\t343\t; Index = 62 Token = 0\n\t\tDD\t1030\t; Index = 62 Token = 1\n\t\tDD\t1717\t; Index = 62 Token = 2\n\t\tDD\t2404\t; Index = 62 Token = 3\n\t\tDD\t3092\t; Index = 62 Token = 4\n\t\tDD\t3779\t; Index = 62 Token = 5\n\t\tDD\t4466\t; Index = 62 Token = 6\n\t\tDD\t5153\t; Index = 62 Token = 7\n\t\tDD\t-343\t; Index = 62 Token = 8\n\t\tDD\t-1030\t; Index = 62 Token = 9\n\t\tDD\t-1717\t; Index = 62 Token = 10\n\t\tDD\t-2404\t; Index = 62 Token = 11\n\t\tDD\t-3092\t; Index = 62 Token = 12\n\t\tDD\t-3779\t; Index = 62 Token = 13\n\t\tDD\t-4466\t; Index = 62 Token = 14\n\t\tDD\t-5153\t; Index = 62 Token = 15\n\t\tDD\t378\t; Index = 63 Token = 0\n\t\tDD\t1134\t; Index = 63 Token = 1\n\t\tDD\t1890\t; Index = 63 Token = 2\n\t\tDD\t2646\t; Index = 63 Token = 3\n\t\tDD\t3402\t; Index = 63 Token = 4\n\t\tDD\t4158\t; Index = 63 Token = 5\n\t\tDD\t4914\t; Index = 63 Token = 6\n\t\tDD\t5670\t; Index = 63 Token = 7\n\t\tDD\t-378\t; Index = 63 Token = 8\n\t\tDD\t-1134\t; Index = 63 Token = 9\n\t\tDD\t-1890\t; Index = 63 Token = 10\n\t\tDD\t-2646\t; Index = 63 Token = 11\n\t\tDD\t-3402\t; Index = 63 Token = 12\n\t\tDD\t-4158\t; Index = 63 Token = 13\n\t\tDD\t-4914\t; Index = 63 Token = 14\n\t\tDD\t-5670\t; Index = 63 Token = 15\n\t\tDD\t415\t; Index = 64 Token = 0\n\t\tDD\t1246\t; Index = 64 Token = 1\n\t\tDD\t2078\t; Index = 64 Token = 2\n\t\tDD\t2909\t; Index = 64 Token = 3\n\t\tDD\t3742\t; Index = 64 Token = 4\n\t\tDD\t4573\t; Index = 64 Token = 5\n\t\tDD\t5405\t; Index = 64 Token = 6\n\t\tDD\t6236\t; Index = 64 Token = 7\n\t\tDD\t-415\t; Index = 64 Token = 8\n\t\tDD\t-1246\t; Index = 64 Token = 9\n\t\tDD\t-2078\t; Index = 64 Token = 10\n\t\tDD\t-2909\t; Index = 64 Token = 11\n\t\tDD\t-3742\t; Index = 64 Token = 12\n\t\tDD\t-4573\t; Index = 64 Token = 13\n\t\tDD\t-5405\t; Index = 64 Token = 14\n\t\tDD\t-6236\t; Index = 64 Token = 15\n\t\tDD\t457\t; Index = 65 Token = 0\n\t\tDD\t1372\t; Index = 65 Token = 1\n\t\tDD\t2287\t; Index = 65 Token = 2\n\t\tDD\t3202\t; Index = 65 Token = 3\n\t\tDD\t4117\t; Index = 65 Token = 4\n\t\tDD\t5032\t; Index = 65 Token = 5\n\t\tDD\t5947\t; Index = 65 Token = 6\n\t\tDD\t6862\t; Index = 65 Token = 7\n\t\tDD\t-457\t; Index = 65 Token = 8\n\t\tDD\t-1372\t; Index = 65 Token = 9\n\t\tDD\t-2287\t; Index = 65 Token = 10\n\t\tDD\t-3202\t; Index = 65 Token = 11\n\t\tDD\t-4117\t; Index = 65 Token = 12\n\t\tDD\t-5032\t; Index = 65 Token = 13\n\t\tDD\t-5947\t; Index = 65 Token = 14\n\t\tDD\t-6862\t; Index = 65 Token = 15\n\t\tDD\t503\t; Index = 66 Token = 0\n\t\tDD\t1509\t; Index = 66 Token = 1\n\t\tDD\t2516\t; Index = 66 Token = 2\n\t\tDD\t3522\t; Index = 66 Token = 3\n\t\tDD\t4529\t; Index = 66 Token = 4\n\t\tDD\t5535\t; Index = 66 Token = 5\n\t\tDD\t6542\t; Index = 66 Token = 6\n\t\tDD\t7548\t; Index = 66 Token = 7\n\t\tDD\t-503\t; Index = 66 Token = 8\n\t\tDD\t-1509\t; Index = 66 Token = 9\n\t\tDD\t-2516\t; Index = 66 Token = 10\n\t\tDD\t-3522\t; Index = 66 Token = 11\n\t\tDD\t-4529\t; Index = 66 Token = 12\n\t\tDD\t-5535\t; Index = 66 Token = 13\n\t\tDD\t-6542\t; Index = 66 Token = 14\n\t\tDD\t-7548\t; Index = 66 Token = 15\n\t\tDD\t553\t; Index = 67 Token = 0\n\t\tDD\t1660\t; Index = 67 Token = 1\n\t\tDD\t2767\t; Index = 67 Token = 2\n\t\tDD\t3874\t; Index = 67 Token = 3\n\t\tDD\t4981\t; Index = 67 Token = 4\n\t\tDD\t6088\t; Index = 67 Token = 5\n\t\tDD\t7195\t; Index = 67 Token = 6\n\t\tDD\t8302\t; Index = 67 Token = 7\n\t\tDD\t-553\t; Index = 67 Token = 8\n\t\tDD\t-1660\t; Index = 67 Token = 9\n\t\tDD\t-2767\t; Index = 67 Token = 10\n\t\tDD\t-3874\t; Index = 67 Token = 11\n\t\tDD\t-4981\t; Index = 67 Token = 12\n\t\tDD\t-6088\t; Index = 67 Token = 13\n\t\tDD\t-7195\t; Index = 67 Token = 14\n\t\tDD\t-8302\t; Index = 67 Token = 15\n\t\tDD\t608\t; Index = 68 Token = 0\n\t\tDD\t1825\t; Index = 68 Token = 1\n\t\tDD\t3043\t; Index = 68 Token = 2\n\t\tDD\t4260\t; Index = 68 Token = 3\n\t\tDD\t5479\t; Index = 68 Token = 4\n\t\tDD\t6696\t; Index = 68 Token = 5\n\t\tDD\t7914\t; Index = 68 Token = 6\n\t\tDD\t9131\t; Index = 68 Token = 7\n\t\tDD\t-608\t; Index = 68 Token = 8\n\t\tDD\t-1825\t; Index = 68 Token = 9\n\t\tDD\t-3043\t; Index = 68 Token = 10\n\t\tDD\t-4260\t; Index = 68 Token = 11\n\t\tDD\t-5479\t; Index = 68 Token = 12\n\t\tDD\t-6696\t; Index = 68 Token = 13\n\t\tDD\t-7914\t; Index = 68 Token = 14\n\t\tDD\t-9131\t; Index = 68 Token = 15\n\t\tDD\t669\t; Index = 69 Token = 0\n\t\tDD\t2008\t; Index = 69 Token = 1\n\t\tDD\t3348\t; Index = 69 Token = 2\n\t\tDD\t4687\t; Index = 69 Token = 3\n\t\tDD\t6027\t; Index = 69 Token = 4\n\t\tDD\t7366\t; Index = 69 Token = 5\n\t\tDD\t8706\t; Index = 69 Token = 6\n\t\tDD\t10045\t; Index = 69 Token = 7\n\t\tDD\t-669\t; Index = 69 Token = 8\n\t\tDD\t-2008\t; Index = 69 Token = 9\n\t\tDD\t-3348\t; Index = 69 Token = 10\n\t\tDD\t-4687\t; Index = 69 Token = 11\n\t\tDD\t-6027\t; Index = 69 Token = 12\n\t\tDD\t-7366\t; Index = 69 Token = 13\n\t\tDD\t-8706\t; Index = 69 Token = 14\n\t\tDD\t-10045\t; Index = 69 Token = 15\n\t\tDD\t736\t; Index = 70 Token = 0\n\t\tDD\t2209\t; Index = 70 Token = 1\n\t\tDD\t3683\t; Index = 70 Token = 2\n\t\tDD\t5156\t; Index = 70 Token = 3\n\t\tDD\t6630\t; Index = 70 Token = 4\n\t\tDD\t8103\t; Index = 70 Token = 5\n\t\tDD\t9577\t; Index = 70 Token = 6\n\t\tDD\t11050\t; Index = 70 Token = 7\n\t\tDD\t-736\t; Index = 70 Token = 8\n\t\tDD\t-2209\t; Index = 70 Token = 9\n\t\tDD\t-3683\t; Index = 70 Token = 10\n\t\tDD\t-5156\t; Index = 70 Token = 11\n\t\tDD\t-6630\t; Index = 70 Token = 12\n\t\tDD\t-8103\t; Index = 70 Token = 13\n\t\tDD\t-9577\t; Index = 70 Token = 14\n\t\tDD\t-11050\t; Index = 70 Token = 15\n\t\tDD\t810\t; Index = 71 Token = 0\n\t\tDD\t2431\t; Index = 71 Token = 1\n\t\tDD\t4052\t; Index = 71 Token = 2\n\t\tDD\t5673\t; Index = 71 Token = 3\n\t\tDD\t7294\t; Index = 71 Token = 4\n\t\tDD\t8915\t; Index = 71 Token = 5\n\t\tDD\t10536\t; Index = 71 Token = 6\n\t\tDD\t12157\t; Index = 71 Token = 7\n\t\tDD\t-810\t; Index = 71 Token = 8\n\t\tDD\t-2431\t; Index = 71 Token = 9\n\t\tDD\t-4052\t; Index = 71 Token = 10\n\t\tDD\t-5673\t; Index = 71 Token = 11\n\t\tDD\t-7294\t; Index = 71 Token = 12\n\t\tDD\t-8915\t; Index = 71 Token = 13\n\t\tDD\t-10536\t; Index = 71 Token = 14\n\t\tDD\t-12157\t; Index = 71 Token = 15\n\t\tDD\t891\t; Index = 72 Token = 0\n\t\tDD\t2674\t; Index = 72 Token = 1\n\t\tDD\t4457\t; Index = 72 Token = 2\n\t\tDD\t6240\t; Index = 72 Token = 3\n\t\tDD\t8023\t; Index = 72 Token = 4\n\t\tDD\t9806\t; Index = 72 Token = 5\n\t\tDD\t11589\t; Index = 72 Token = 6\n\t\tDD\t13372\t; Index = 72 Token = 7\n\t\tDD\t-891\t; Index = 72 Token = 8\n\t\tDD\t-2674\t; Index = 72 Token = 9\n\t\tDD\t-4457\t; Index = 72 Token = 10\n\t\tDD\t-6240\t; Index = 72 Token = 11\n\t\tDD\t-8023\t; Index = 72 Token = 12\n\t\tDD\t-9806\t; Index = 72 Token = 13\n\t\tDD\t-11589\t; Index = 72 Token = 14\n\t\tDD\t-13372\t; Index = 72 Token = 15\n\t\tDD\t980\t; Index = 73 Token = 0\n\t\tDD\t2941\t; Index = 73 Token = 1\n\t\tDD\t4902\t; Index = 73 Token = 2\n\t\tDD\t6863\t; Index = 73 Token = 3\n\t\tDD\t8825\t; Index = 73 Token = 4\n\t\tDD\t10786\t; Index = 73 Token = 5\n\t\tDD\t12747\t; Index = 73 Token = 6\n\t\tDD\t14708\t; Index = 73 Token = 7\n\t\tDD\t-980\t; Index = 73 Token = 8\n\t\tDD\t-2941\t; Index = 73 Token = 9\n\t\tDD\t-4902\t; Index = 73 Token = 10\n\t\tDD\t-6863\t; Index = 73 Token = 11\n\t\tDD\t-8825\t; Index = 73 Token = 12\n\t\tDD\t-10786\t; Index = 73 Token = 13\n\t\tDD\t-12747\t; Index = 73 Token = 14\n\t\tDD\t-14708\t; Index = 73 Token = 15\n\t\tDD\t1078\t; Index = 74 Token = 0\n\t\tDD\t3235\t; Index = 74 Token = 1\n\t\tDD\t5393\t; Index = 74 Token = 2\n\t\tDD\t7550\t; Index = 74 Token = 3\n\t\tDD\t9708\t; Index = 74 Token = 4\n\t\tDD\t11865\t; Index = 74 Token = 5\n\t\tDD\t14023\t; Index = 74 Token = 6\n\t\tDD\t16180\t; Index = 74 Token = 7\n\t\tDD\t-1078\t; Index = 74 Token = 8\n\t\tDD\t-3235\t; Index = 74 Token = 9\n\t\tDD\t-5393\t; Index = 74 Token = 10\n\t\tDD\t-7550\t; Index = 74 Token = 11\n\t\tDD\t-9708\t; Index = 74 Token = 12\n\t\tDD\t-11865\t; Index = 74 Token = 13\n\t\tDD\t-14023\t; Index = 74 Token = 14\n\t\tDD\t-16180\t; Index = 74 Token = 15\n\t\tDD\t1186\t; Index = 75 Token = 0\n\t\tDD\t3559\t; Index = 75 Token = 1\n\t\tDD\t5932\t; Index = 75 Token = 2\n\t\tDD\t8305\t; Index = 75 Token = 3\n\t\tDD\t10679\t; Index = 75 Token = 4\n\t\tDD\t13052\t; Index = 75 Token = 5\n\t\tDD\t15425\t; Index = 75 Token = 6\n\t\tDD\t17798\t; Index = 75 Token = 7\n\t\tDD\t-1186\t; Index = 75 Token = 8\n\t\tDD\t-3559\t; Index = 75 Token = 9\n\t\tDD\t-5932\t; Index = 75 Token = 10\n\t\tDD\t-8305\t; Index = 75 Token = 11\n\t\tDD\t-10679\t; Index = 75 Token = 12\n\t\tDD\t-13052\t; Index = 75 Token = 13\n\t\tDD\t-15425\t; Index = 75 Token = 14\n\t\tDD\t-17798\t; Index = 75 Token = 15\n\t\tDD\t1305\t; Index = 76 Token = 0\n\t\tDD\t3915\t; Index = 76 Token = 1\n\t\tDD\t6526\t; Index = 76 Token = 2\n\t\tDD\t9136\t; Index = 76 Token = 3\n\t\tDD\t11747\t; Index = 76 Token = 4\n\t\tDD\t14357\t; Index = 76 Token = 5\n\t\tDD\t16968\t; Index = 76 Token = 6\n\t\tDD\t19578\t; Index = 76 Token = 7\n\t\tDD\t-1305\t; Index = 76 Token = 8\n\t\tDD\t-3915\t; Index = 76 Token = 9\n\t\tDD\t-6526\t; Index = 76 Token = 10\n\t\tDD\t-9136\t; Index = 76 Token = 11\n\t\tDD\t-11747\t; Index = 76 Token = 12\n\t\tDD\t-14357\t; Index = 76 Token = 13\n\t\tDD\t-16968\t; Index = 76 Token = 14\n\t\tDD\t-19578\t; Index = 76 Token = 15\n\t\tDD\t1435\t; Index = 77 Token = 0\n\t\tDD\t4306\t; Index = 77 Token = 1\n\t\tDD\t7178\t; Index = 77 Token = 2\n\t\tDD\t10049\t; Index = 77 Token = 3\n\t\tDD\t12922\t; Index = 77 Token = 4\n\t\tDD\t15793\t; Index = 77 Token = 5\n\t\tDD\t18665\t; Index = 77 Token = 6\n\t\tDD\t21536\t; Index = 77 Token = 7\n\t\tDD\t-1435\t; Index = 77 Token = 8\n\t\tDD\t-4306\t; Index = 77 Token = 9\n\t\tDD\t-7178\t; Index = 77 Token = 10\n\t\tDD\t-10049\t; Index = 77 Token = 11\n\t\tDD\t-12922\t; Index = 77 Token = 12\n\t\tDD\t-15793\t; Index = 77 Token = 13\n\t\tDD\t-18665\t; Index = 77 Token = 14\n\t\tDD\t-21536\t; Index = 77 Token = 15\n\t\tDD\t1579\t; Index = 78 Token = 0\n\t\tDD\t4737\t; Index = 78 Token = 1\n\t\tDD\t7896\t; Index = 78 Token = 2\n\t\tDD\t11054\t; Index = 78 Token = 3\n\t\tDD\t14214\t; Index = 78 Token = 4\n\t\tDD\t17372\t; Index = 78 Token = 5\n\t\tDD\t20531\t; Index = 78 Token = 6\n\t\tDD\t23689\t; Index = 78 Token = 7\n\t\tDD\t-1579\t; Index = 78 Token = 8\n\t\tDD\t-4737\t; Index = 78 Token = 9\n\t\tDD\t-7896\t; Index = 78 Token = 10\n\t\tDD\t-11054\t; Index = 78 Token = 11\n\t\tDD\t-14214\t; Index = 78 Token = 12\n\t\tDD\t-17372\t; Index = 78 Token = 13\n\t\tDD\t-20531\t; Index = 78 Token = 14\n\t\tDD\t-23689\t; Index = 78 Token = 15\n\t\tDD\t1737\t; Index = 79 Token = 0\n\t\tDD\t5211\t; Index = 79 Token = 1\n\t\tDD\t8686\t; Index = 79 Token = 2\n\t\tDD\t12160\t; Index = 79 Token = 3\n\t\tDD\t15636\t; Index = 79 Token = 4\n\t\tDD\t19110\t; Index = 79 Token = 5\n\t\tDD\t22585\t; Index = 79 Token = 6\n\t\tDD\t26059\t; Index = 79 Token = 7\n\t\tDD\t-1737\t; Index = 79 Token = 8\n\t\tDD\t-5211\t; Index = 79 Token = 9\n\t\tDD\t-8686\t; Index = 79 Token = 10\n\t\tDD\t-12160\t; Index = 79 Token = 11\n\t\tDD\t-15636\t; Index = 79 Token = 12\n\t\tDD\t-19110\t; Index = 79 Token = 13\n\t\tDD\t-22585\t; Index = 79 Token = 14\n\t\tDD\t-26059\t; Index = 79 Token = 15\n\t\tDD\t1911\t; Index = 80 Token = 0\n\t\tDD\t5733\t; Index = 80 Token = 1\n\t\tDD\t9555\t; Index = 80 Token = 2\n\t\tDD\t13377\t; Index = 80 Token = 3\n\t\tDD\t17200\t; Index = 80 Token = 4\n\t\tDD\t21022\t; Index = 80 Token = 5\n\t\tDD\t24844\t; Index = 80 Token = 6\n\t\tDD\t28666\t; Index = 80 Token = 7\n\t\tDD\t-1911\t; Index = 80 Token = 8\n\t\tDD\t-5733\t; Index = 80 Token = 9\n\t\tDD\t-9555\t; Index = 80 Token = 10\n\t\tDD\t-13377\t; Index = 80 Token = 11\n\t\tDD\t-17200\t; Index = 80 Token = 12\n\t\tDD\t-21022\t; Index = 80 Token = 13\n\t\tDD\t-24844\t; Index = 80 Token = 14\n\t\tDD\t-28666\t; Index = 80 Token = 15\n\t\tDD\t2102\t; Index = 81 Token = 0\n\t\tDD\t6306\t; Index = 81 Token = 1\n\t\tDD\t10511\t; Index = 81 Token = 2\n\t\tDD\t14715\t; Index = 81 Token = 3\n\t\tDD\t18920\t; Index = 81 Token = 4\n\t\tDD\t23124\t; Index = 81 Token = 5\n\t\tDD\t27329\t; Index = 81 Token = 6\n\t\tDD\t31533\t; Index = 81 Token = 7\n\t\tDD\t-2102\t; Index = 81 Token = 8\n\t\tDD\t-6306\t; Index = 81 Token = 9\n\t\tDD\t-10511\t; Index = 81 Token = 10\n\t\tDD\t-14715\t; Index = 81 Token = 11\n\t\tDD\t-18920\t; Index = 81 Token = 12\n\t\tDD\t-23124\t; Index = 81 Token = 13\n\t\tDD\t-27329\t; Index = 81 Token = 14\n\t\tDD\t-31533\t; Index = 81 Token = 15\n\t\tDD\t2312\t; Index = 82 Token = 0\n\t\tDD\t6937\t; Index = 82 Token = 1\n\t\tDD\t11562\t; Index = 82 Token = 2\n\t\tDD\t16187\t; Index = 82 Token = 3\n\t\tDD\t20812\t; Index = 82 Token = 4\n\t\tDD\t25437\t; Index = 82 Token = 5\n\t\tDD\t30062\t; Index = 82 Token = 6\n\t\tDD\t34687\t; Index = 82 Token = 7\n\t\tDD\t-2312\t; Index = 82 Token = 8\n\t\tDD\t-6937\t; Index = 82 Token = 9\n\t\tDD\t-11562\t; Index = 82 Token = 10\n\t\tDD\t-16187\t; Index = 82 Token = 11\n\t\tDD\t-20812\t; Index = 82 Token = 12\n\t\tDD\t-25437\t; Index = 82 Token = 13\n\t\tDD\t-30062\t; Index = 82 Token = 14\n\t\tDD\t-34687\t; Index = 82 Token = 15\n\t\tDD\t2543\t; Index = 83 Token = 0\n\t\tDD\t7630\t; Index = 83 Token = 1\n\t\tDD\t12718\t; Index = 83 Token = 2\n\t\tDD\t17805\t; Index = 83 Token = 3\n\t\tDD\t22893\t; Index = 83 Token = 4\n\t\tDD\t27980\t; Index = 83 Token = 5\n\t\tDD\t33068\t; Index = 83 Token = 6\n\t\tDD\t38155\t; Index = 83 Token = 7\n\t\tDD\t-2543\t; Index = 83 Token = 8\n\t\tDD\t-7630\t; Index = 83 Token = 9\n\t\tDD\t-12718\t; Index = 83 Token = 10\n\t\tDD\t-17805\t; Index = 83 Token = 11\n\t\tDD\t-22893\t; Index = 83 Token = 12\n\t\tDD\t-27980\t; Index = 83 Token = 13\n\t\tDD\t-33068\t; Index = 83 Token = 14\n\t\tDD\t-38155\t; Index = 83 Token = 15\n\t\tDD\t2798\t; Index = 84 Token = 0\n\t\tDD\t8394\t; Index = 84 Token = 1\n\t\tDD\t13990\t; Index = 84 Token = 2\n\t\tDD\t19586\t; Index = 84 Token = 3\n\t\tDD\t25183\t; Index = 84 Token = 4\n\t\tDD\t30779\t; Index = 84 Token = 5\n\t\tDD\t36375\t; Index = 84 Token = 6\n\t\tDD\t41971\t; Index = 84 Token = 7\n\t\tDD\t-2798\t; Index = 84 Token = 8\n\t\tDD\t-8394\t; Index = 84 Token = 9\n\t\tDD\t-13990\t; Index = 84 Token = 10\n\t\tDD\t-19586\t; Index = 84 Token = 11\n\t\tDD\t-25183\t; Index = 84 Token = 12\n\t\tDD\t-30779\t; Index = 84 Token = 13\n\t\tDD\t-36375\t; Index = 84 Token = 14\n\t\tDD\t-41971\t; Index = 84 Token = 15\n\t\tDD\t3077\t; Index = 85 Token = 0\n\t\tDD\t9232\t; Index = 85 Token = 1\n\t\tDD\t15388\t; Index = 85 Token = 2\n\t\tDD\t21543\t; Index = 85 Token = 3\n\t\tDD\t27700\t; Index = 85 Token = 4\n\t\tDD\t33855\t; Index = 85 Token = 5\n\t\tDD\t40011\t; Index = 85 Token = 6\n\t\tDD\t46166\t; Index = 85 Token = 7\n\t\tDD\t-3077\t; Index = 85 Token = 8\n\t\tDD\t-9232\t; Index = 85 Token = 9\n\t\tDD\t-15388\t; Index = 85 Token = 10\n\t\tDD\t-21543\t; Index = 85 Token = 11\n\t\tDD\t-27700\t; Index = 85 Token = 12\n\t\tDD\t-33855\t; Index = 85 Token = 13\n\t\tDD\t-40011\t; Index = 85 Token = 14\n\t\tDD\t-46166\t; Index = 85 Token = 15\n\t\tDD\t3385\t; Index = 86 Token = 0\n\t\tDD\t10156\t; Index = 86 Token = 1\n\t\tDD\t16928\t; Index = 86 Token = 2\n\t\tDD\t23699\t; Index = 86 Token = 3\n\t\tDD\t30471\t; Index = 86 Token = 4\n\t\tDD\t37242\t; Index = 86 Token = 5\n\t\tDD\t44014\t; Index = 86 Token = 6\n\t\tDD\t50785\t; Index = 86 Token = 7\n\t\tDD\t-3385\t; Index = 86 Token = 8\n\t\tDD\t-10156\t; Index = 86 Token = 9\n\t\tDD\t-16928\t; Index = 86 Token = 10\n\t\tDD\t-23699\t; Index = 86 Token = 11\n\t\tDD\t-30471\t; Index = 86 Token = 12\n\t\tDD\t-37242\t; Index = 86 Token = 13\n\t\tDD\t-44014\t; Index = 86 Token = 14\n\t\tDD\t-50785\t; Index = 86 Token = 15\n\t\tDD\t3724\t; Index = 87 Token = 0\n\t\tDD\t11172\t; Index = 87 Token = 1\n\t\tDD\t18621\t; Index = 87 Token = 2\n\t\tDD\t26069\t; Index = 87 Token = 3\n\t\tDD\t33518\t; Index = 87 Token = 4\n\t\tDD\t40966\t; Index = 87 Token = 5\n\t\tDD\t48415\t; Index = 87 Token = 6\n\t\tDD\t55863\t; Index = 87 Token = 7\n\t\tDD\t-3724\t; Index = 87 Token = 8\n\t\tDD\t-11172\t; Index = 87 Token = 9\n\t\tDD\t-18621\t; Index = 87 Token = 10\n\t\tDD\t-26069\t; Index = 87 Token = 11\n\t\tDD\t-33518\t; Index = 87 Token = 12\n\t\tDD\t-40966\t; Index = 87 Token = 13\n\t\tDD\t-48415\t; Index = 87 Token = 14\n\t\tDD\t-55863\t; Index = 87 Token = 15\n\t\tDD\t4095\t; Index = 88 Token = 0\n\t\tDD\t12286\t; Index = 88 Token = 1\n\t\tDD\t20478\t; Index = 88 Token = 2\n\t\tDD\t28669\t; Index = 88 Token = 3\n\t\tDD\t36862\t; Index = 88 Token = 4\n\t\tDD\t45053\t; Index = 88 Token = 5\n\t\tDD\t53245\t; Index = 88 Token = 6\n\t\tDD\t61436\t; Index = 88 Token = 7\n\t\tDD\t-4095\t; Index = 88 Token = 8\n\t\tDD\t-12286\t; Index = 88 Token = 9\n\t\tDD\t-20478\t; Index = 88 Token = 10\n\t\tDD\t-28669\t; Index = 88 Token = 11\n\t\tDD\t-36862\t; Index = 88 Token = 12\n\t\tDD\t-45053\t; Index = 88 Token = 13\n\t\tDD\t-53245\t; Index = 88 Token = 14\n\t\tDD\t-61436\t; Index = 88 Token = 15\n"
  },
  {
    "path": "WIN32LIB/AUDIO/FUNCTION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SOUNDIO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort Decompress_Frame(void * source, void * dest, short size);\nint __cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback);\nint __cdecl Stream_Sample(void *buffer, long size, BOOL (*callback);\nint __cdecl File_Stream_Sample(char const *filename);\nint __cdecl File_Stream_Sample_Vol(char const *filename, int volume);\nvoid __cdecl _saveregs _loadds Sound_Callback(void);\nvoid __cdecl far _saveregs _loadds maintenance_callback(void);\nvoid  __cdecl Load_Sample(char const *filename);\nlong __cdecl Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);\nlong __cdecl Sample_Read(int fh, void *buffer, long size);\nvoid __cdecl Free_Sample(void const *sample);\nBOOL __cdecl Sound_Init(int sfx, int score, int sample);\nvoid far VQA_TimerCallback(void);\nBOOL Audio_Init(int sample, int address, int inter, int dma);\nvoid __cdecl Sound_End(void);\nvoid __cdecl Stop_Sample(int handle);\nBOOL __cdecl Sample_Status(int handle);\nBOOL __cdecl Is_Sample_Playing(void const * sample);\nvoid __cdecl Stop_Sample_Playing(void const * sample);\nint __cdecl Play_Sample(void const *sample);\nint __cdecl Play_Sample_Vol(void const *sample, int priority, int volume);\nint __cdecl Set_Sound_Vol(int volume);\nint __cdecl Set_Score_Vol(int volume);\nvoid __cdecl Fade_Sample(int handle, int ticks);"
  },
  {
    "path": "WIN32LIB/AUDIO/INDEXTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* wIndexTable - ADPCM Lookup table for indexes\n;****************************************************************************\n\n\t\talign\t4\n\nwIndexTable\tDW\t0\t* 2\t; Index = 0 Token = 0\n\t\tDW\t0\t* 2\t; Index = 0 Token = 1\n\t\tDW\t0\t* 2\t; Index = 0 Token = 2\n\t\tDW\t0\t* 2\t; Index = 0 Token = 3\n\t\tDW\t32\t* 2\t; Index = 0 Token = 4\n\t\tDW\t64\t* 2\t; Index = 0 Token = 5\n\t\tDW\t96\t* 2\t; Index = 0 Token = 6\n\t\tDW\t128\t* 2\t; Index = 0 Token = 7\n\t\tDW\t0\t* 2\t; Index = 0 Token = 8\n\t\tDW\t0\t* 2\t; Index = 0 Token = 9\n\t\tDW\t0\t* 2\t; Index = 0 Token = 10\n\t\tDW\t0\t* 2\t; Index = 0 Token = 11\n\t\tDW\t32\t* 2\t; Index = 0 Token = 12\n\t\tDW\t64\t* 2\t; Index = 0 Token = 13\n\t\tDW\t96\t* 2\t; Index = 0 Token = 14\n\t\tDW\t128\t* 2\t; Index = 0 Token = 15\n\t\tDW\t0\t* 2\t; Index = 1 Token = 0\n\t\tDW\t0\t* 2\t; Index = 1 Token = 1\n\t\tDW\t0\t* 2\t; Index = 1 Token = 2\n\t\tDW\t0\t* 2\t; Index = 1 Token = 3\n\t\tDW\t48\t* 2\t; Index = 1 Token = 4\n\t\tDW\t80\t* 2\t; Index = 1 Token = 5\n\t\tDW\t112\t* 2\t; Index = 1 Token = 6\n\t\tDW\t144\t* 2\t; Index = 1 Token = 7\n\t\tDW\t0\t* 2\t; Index = 1 Token = 8\n\t\tDW\t0\t* 2\t; Index = 1 Token = 9\n\t\tDW\t0\t* 2\t; Index = 1 Token = 10\n\t\tDW\t0\t* 2\t; Index = 1 Token = 11\n\t\tDW\t48\t* 2\t; Index = 1 Token = 12\n\t\tDW\t80\t* 2\t; Index = 1 Token = 13\n\t\tDW\t112\t* 2\t; Index = 1 Token = 14\n\t\tDW\t144\t* 2\t; Index = 1 Token = 15\n\t\tDW\t16\t* 2\t; Index = 2 Token = 0\n\t\tDW\t16\t* 2\t; Index = 2 Token = 1\n\t\tDW\t16\t* 2\t; Index = 2 Token = 2\n\t\tDW\t16\t* 2\t; Index = 2 Token = 3\n\t\tDW\t64\t* 2\t; Index = 2 Token = 4\n\t\tDW\t96\t* 2\t; Index = 2 Token = 5\n\t\tDW\t128\t* 2\t; Index = 2 Token = 6\n\t\tDW\t160\t* 2\t; Index = 2 Token = 7\n\t\tDW\t16\t* 2\t; Index = 2 Token = 8\n\t\tDW\t16\t* 2\t; Index = 2 Token = 9\n\t\tDW\t16\t* 2\t; Index = 2 Token = 10\n\t\tDW\t16\t* 2\t; Index = 2 Token = 11\n\t\tDW\t64\t* 2\t; Index = 2 Token = 12\n\t\tDW\t96\t* 2\t; Index = 2 Token = 13\n\t\tDW\t128\t* 2\t; Index = 2 Token = 14\n\t\tDW\t160\t* 2\t; Index = 2 Token = 15\n\t\tDW\t32\t* 2\t; Index = 3 Token = 0\n\t\tDW\t32\t* 2\t; Index = 3 Token = 1\n\t\tDW\t32\t* 2\t; Index = 3 Token = 2\n\t\tDW\t32\t* 2\t; Index = 3 Token = 3\n\t\tDW\t80\t* 2\t; Index = 3 Token = 4\n\t\tDW\t112\t* 2\t; Index = 3 Token = 5\n\t\tDW\t144\t* 2\t; Index = 3 Token = 6\n\t\tDW\t176\t* 2\t; Index = 3 Token = 7\n\t\tDW\t32\t* 2\t; Index = 3 Token = 8\n\t\tDW\t32\t* 2\t; Index = 3 Token = 9\n\t\tDW\t32\t* 2\t; Index = 3 Token = 10\n\t\tDW\t32\t* 2\t; Index = 3 Token = 11\n\t\tDW\t80\t* 2\t; Index = 3 Token = 12\n\t\tDW\t112\t* 2\t; Index = 3 Token = 13\n\t\tDW\t144\t* 2\t; Index = 3 Token = 14\n\t\tDW\t176\t* 2\t; Index = 3 Token = 15\n\t\tDW\t48\t* 2\t; Index = 4 Token = 0\n\t\tDW\t48\t* 2\t; Index = 4 Token = 1\n\t\tDW\t48\t* 2\t; Index = 4 Token = 2\n\t\tDW\t48\t* 2\t; Index = 4 Token = 3\n\t\tDW\t96\t* 2\t; Index = 4 Token = 4\n\t\tDW\t128\t* 2\t; Index = 4 Token = 5\n\t\tDW\t160\t* 2\t; Index = 4 Token = 6\n\t\tDW\t192\t* 2\t; Index = 4 Token = 7\n\t\tDW\t48\t* 2\t; Index = 4 Token = 8\n\t\tDW\t48\t* 2\t; Index = 4 Token = 9\n\t\tDW\t48\t* 2\t; Index = 4 Token = 10\n\t\tDW\t48\t* 2\t; Index = 4 Token = 11\n\t\tDW\t96\t* 2\t; Index = 4 Token = 12\n\t\tDW\t128\t* 2\t; Index = 4 Token = 13\n\t\tDW\t160\t* 2\t; Index = 4 Token = 14\n\t\tDW\t192\t* 2\t; Index = 4 Token = 15\n\t\tDW\t64\t* 2\t; Index = 5 Token = 0\n\t\tDW\t64\t* 2\t; Index = 5 Token = 1\n\t\tDW\t64\t* 2\t; Index = 5 Token = 2\n\t\tDW\t64\t* 2\t; Index = 5 Token = 3\n\t\tDW\t112\t* 2\t; Index = 5 Token = 4\n\t\tDW\t144\t* 2\t; Index = 5 Token = 5\n\t\tDW\t176\t* 2\t; Index = 5 Token = 6\n\t\tDW\t208\t* 2\t; Index = 5 Token = 7\n\t\tDW\t64\t* 2\t; Index = 5 Token = 8\n\t\tDW\t64\t* 2\t; Index = 5 Token = 9\n\t\tDW\t64\t* 2\t; Index = 5 Token = 10\n\t\tDW\t64\t* 2\t; Index = 5 Token = 11\n\t\tDW\t112\t* 2\t; Index = 5 Token = 12\n\t\tDW\t144\t* 2\t; Index = 5 Token = 13\n\t\tDW\t176\t* 2\t; Index = 5 Token = 14\n\t\tDW\t208\t* 2\t; Index = 5 Token = 15\n\t\tDW\t80\t* 2\t; Index = 6 Token = 0\n\t\tDW\t80\t* 2\t; Index = 6 Token = 1\n\t\tDW\t80\t* 2\t; Index = 6 Token = 2\n\t\tDW\t80\t* 2\t; Index = 6 Token = 3\n\t\tDW\t128\t* 2\t; Index = 6 Token = 4\n\t\tDW\t160\t* 2\t; Index = 6 Token = 5\n\t\tDW\t192\t* 2\t; Index = 6 Token = 6\n\t\tDW\t224\t* 2\t; Index = 6 Token = 7\n\t\tDW\t80\t* 2\t; Index = 6 Token = 8\n\t\tDW\t80\t* 2\t; Index = 6 Token = 9\n\t\tDW\t80\t* 2\t; Index = 6 Token = 10\n\t\tDW\t80\t* 2\t; Index = 6 Token = 11\n\t\tDW\t128\t* 2\t; Index = 6 Token = 12\n\t\tDW\t160\t* 2\t; Index = 6 Token = 13\n\t\tDW\t192\t* 2\t; Index = 6 Token = 14\n\t\tDW\t224\t* 2\t; Index = 6 Token = 15\n\t\tDW\t96\t* 2\t; Index = 7 Token = 0\n\t\tDW\t96\t* 2\t; Index = 7 Token = 1\n\t\tDW\t96\t* 2\t; Index = 7 Token = 2\n\t\tDW\t96\t* 2\t; Index = 7 Token = 3\n\t\tDW\t144\t* 2\t; Index = 7 Token = 4\n\t\tDW\t176\t* 2\t; Index = 7 Token = 5\n\t\tDW\t208\t* 2\t; Index = 7 Token = 6\n\t\tDW\t240\t* 2\t; Index = 7 Token = 7\n\t\tDW\t96\t* 2\t; Index = 7 Token = 8\n\t\tDW\t96\t* 2\t; Index = 7 Token = 9\n\t\tDW\t96\t* 2\t; Index = 7 Token = 10\n\t\tDW\t96\t* 2\t; Index = 7 Token = 11\n\t\tDW\t144\t* 2\t; Index = 7 Token = 12\n\t\tDW\t176\t* 2\t; Index = 7 Token = 13\n\t\tDW\t208\t* 2\t; Index = 7 Token = 14\n\t\tDW\t240\t* 2\t; Index = 7 Token = 15\n\t\tDW\t112\t* 2\t; Index = 8 Token = 0\n\t\tDW\t112\t* 2\t; Index = 8 Token = 1\n\t\tDW\t112\t* 2\t; Index = 8 Token = 2\n\t\tDW\t112\t* 2\t; Index = 8 Token = 3\n\t\tDW\t160\t* 2\t; Index = 8 Token = 4\n\t\tDW\t192\t* 2\t; Index = 8 Token = 5\n\t\tDW\t224\t* 2\t; Index = 8 Token = 6\n\t\tDW\t256\t* 2\t; Index = 8 Token = 7\n\t\tDW\t112\t* 2\t; Index = 8 Token = 8\n\t\tDW\t112\t* 2\t; Index = 8 Token = 9\n\t\tDW\t112\t* 2\t; Index = 8 Token = 10\n\t\tDW\t112\t* 2\t; Index = 8 Token = 11\n\t\tDW\t160\t* 2\t; Index = 8 Token = 12\n\t\tDW\t192\t* 2\t; Index = 8 Token = 13\n\t\tDW\t224\t* 2\t; Index = 8 Token = 14\n\t\tDW\t256\t* 2\t; Index = 8 Token = 15\n\t\tDW\t128\t* 2\t; Index = 9 Token = 0\n\t\tDW\t128\t* 2\t; Index = 9 Token = 1\n\t\tDW\t128\t* 2\t; Index = 9 Token = 2\n\t\tDW\t128\t* 2\t; Index = 9 Token = 3\n\t\tDW\t176\t* 2\t; Index = 9 Token = 4\n\t\tDW\t208\t* 2\t; Index = 9 Token = 5\n\t\tDW\t240\t* 2\t; Index = 9 Token = 6\n\t\tDW\t272\t* 2\t; Index = 9 Token = 7\n\t\tDW\t128\t* 2\t; Index = 9 Token = 8\n\t\tDW\t128\t* 2\t; Index = 9 Token = 9\n\t\tDW\t128\t* 2\t; Index = 9 Token = 10\n\t\tDW\t128\t* 2\t; Index = 9 Token = 11\n\t\tDW\t176\t* 2\t; Index = 9 Token = 12\n\t\tDW\t208\t* 2\t; Index = 9 Token = 13\n\t\tDW\t240\t* 2\t; Index = 9 Token = 14\n\t\tDW\t272\t* 2\t; Index = 9 Token = 15\n\t\tDW\t144\t* 2\t; Index = 10 Token = 0\n\t\tDW\t144\t* 2\t; Index = 10 Token = 1\n\t\tDW\t144\t* 2\t; Index = 10 Token = 2\n\t\tDW\t144\t* 2\t; Index = 10 Token = 3\n\t\tDW\t192\t* 2\t; Index = 10 Token = 4\n\t\tDW\t224\t* 2\t; Index = 10 Token = 5\n\t\tDW\t256\t* 2\t; Index = 10 Token = 6\n\t\tDW\t288\t* 2\t; Index = 10 Token = 7\n\t\tDW\t144\t* 2\t; Index = 10 Token = 8\n\t\tDW\t144\t* 2\t; Index = 10 Token = 9\n\t\tDW\t144\t* 2\t; Index = 10 Token = 10\n\t\tDW\t144\t* 2\t; Index = 10 Token = 11\n\t\tDW\t192\t* 2\t; Index = 10 Token = 12\n\t\tDW\t224\t* 2\t; Index = 10 Token = 13\n\t\tDW\t256\t* 2\t; Index = 10 Token = 14\n\t\tDW\t288\t* 2\t; Index = 10 Token = 15\n\t\tDW\t160\t* 2\t; Index = 11 Token = 0\n\t\tDW\t160\t* 2\t; Index = 11 Token = 1\n\t\tDW\t160\t* 2\t; Index = 11 Token = 2\n\t\tDW\t160\t* 2\t; Index = 11 Token = 3\n\t\tDW\t208\t* 2\t; Index = 11 Token = 4\n\t\tDW\t240\t* 2\t; Index = 11 Token = 5\n\t\tDW\t272\t* 2\t; Index = 11 Token = 6\n\t\tDW\t304\t* 2\t; Index = 11 Token = 7\n\t\tDW\t160\t* 2\t; Index = 11 Token = 8\n\t\tDW\t160\t* 2\t; Index = 11 Token = 9\n\t\tDW\t160\t* 2\t; Index = 11 Token = 10\n\t\tDW\t160\t* 2\t; Index = 11 Token = 11\n\t\tDW\t208\t* 2\t; Index = 11 Token = 12\n\t\tDW\t240\t* 2\t; Index = 11 Token = 13\n\t\tDW\t272\t* 2\t; Index = 11 Token = 14\n\t\tDW\t304\t* 2\t; Index = 11 Token = 15\n\t\tDW\t176\t* 2\t; Index = 12 Token = 0\n\t\tDW\t176\t* 2\t; Index = 12 Token = 1\n\t\tDW\t176\t* 2\t; Index = 12 Token = 2\n\t\tDW\t176\t* 2\t; Index = 12 Token = 3\n\t\tDW\t224\t* 2\t; Index = 12 Token = 4\n\t\tDW\t256\t* 2\t; Index = 12 Token = 5\n\t\tDW\t288\t* 2\t; Index = 12 Token = 6\n\t\tDW\t320\t* 2\t; Index = 12 Token = 7\n\t\tDW\t176\t* 2\t; Index = 12 Token = 8\n\t\tDW\t176\t* 2\t; Index = 12 Token = 9\n\t\tDW\t176\t* 2\t; Index = 12 Token = 10\n\t\tDW\t176\t* 2\t; Index = 12 Token = 11\n\t\tDW\t224\t* 2\t; Index = 12 Token = 12\n\t\tDW\t256\t* 2\t; Index = 12 Token = 13\n\t\tDW\t288\t* 2\t; Index = 12 Token = 14\n\t\tDW\t320\t* 2\t; Index = 12 Token = 15\n\t\tDW\t192\t* 2\t; Index = 13 Token = 0\n\t\tDW\t192\t* 2\t; Index = 13 Token = 1\n\t\tDW\t192\t* 2\t; Index = 13 Token = 2\n\t\tDW\t192\t* 2\t; Index = 13 Token = 3\n\t\tDW\t240\t* 2\t; Index = 13 Token = 4\n\t\tDW\t272\t* 2\t; Index = 13 Token = 5\n\t\tDW\t304\t* 2\t; Index = 13 Token = 6\n\t\tDW\t336\t* 2\t; Index = 13 Token = 7\n\t\tDW\t192\t* 2\t; Index = 13 Token = 8\n\t\tDW\t192\t* 2\t; Index = 13 Token = 9\n\t\tDW\t192\t* 2\t; Index = 13 Token = 10\n\t\tDW\t192\t* 2\t; Index = 13 Token = 11\n\t\tDW\t240\t* 2\t; Index = 13 Token = 12\n\t\tDW\t272\t* 2\t; Index = 13 Token = 13\n\t\tDW\t304\t* 2\t; Index = 13 Token = 14\n\t\tDW\t336\t* 2\t; Index = 13 Token = 15\n\t\tDW\t208\t* 2\t; Index = 14 Token = 0\n\t\tDW\t208\t* 2\t; Index = 14 Token = 1\n\t\tDW\t208\t* 2\t; Index = 14 Token = 2\n\t\tDW\t208\t* 2\t; Index = 14 Token = 3\n\t\tDW\t256\t* 2\t; Index = 14 Token = 4\n\t\tDW\t288\t* 2\t; Index = 14 Token = 5\n\t\tDW\t320\t* 2\t; Index = 14 Token = 6\n\t\tDW\t352\t* 2\t; Index = 14 Token = 7\n\t\tDW\t208\t* 2\t; Index = 14 Token = 8\n\t\tDW\t208\t* 2\t; Index = 14 Token = 9\n\t\tDW\t208\t* 2\t; Index = 14 Token = 10\n\t\tDW\t208\t* 2\t; Index = 14 Token = 11\n\t\tDW\t256\t* 2\t; Index = 14 Token = 12\n\t\tDW\t288\t* 2\t; Index = 14 Token = 13\n\t\tDW\t320\t* 2\t; Index = 14 Token = 14\n\t\tDW\t352\t* 2\t; Index = 14 Token = 15\n\t\tDW\t224\t* 2\t; Index = 15 Token = 0\n\t\tDW\t224\t* 2\t; Index = 15 Token = 1\n\t\tDW\t224\t* 2\t; Index = 15 Token = 2\n\t\tDW\t224\t* 2\t; Index = 15 Token = 3\n\t\tDW\t272\t* 2\t; Index = 15 Token = 4\n\t\tDW\t304\t* 2\t; Index = 15 Token = 5\n\t\tDW\t336\t* 2\t; Index = 15 Token = 6\n\t\tDW\t368\t* 2\t; Index = 15 Token = 7\n\t\tDW\t224\t* 2\t; Index = 15 Token = 8\n\t\tDW\t224\t* 2\t; Index = 15 Token = 9\n\t\tDW\t224\t* 2\t; Index = 15 Token = 10\n\t\tDW\t224\t* 2\t; Index = 15 Token = 11\n\t\tDW\t272\t* 2\t; Index = 15 Token = 12\n\t\tDW\t304\t* 2\t; Index = 15 Token = 13\n\t\tDW\t336\t* 2\t; Index = 15 Token = 14\n\t\tDW\t368\t* 2\t; Index = 15 Token = 15\n\t\tDW\t240\t* 2\t; Index = 16 Token = 0\n\t\tDW\t240\t* 2\t; Index = 16 Token = 1\n\t\tDW\t240\t* 2\t; Index = 16 Token = 2\n\t\tDW\t240\t* 2\t; Index = 16 Token = 3\n\t\tDW\t288\t* 2\t; Index = 16 Token = 4\n\t\tDW\t320\t* 2\t; Index = 16 Token = 5\n\t\tDW\t352\t* 2\t; Index = 16 Token = 6\n\t\tDW\t384\t* 2\t; Index = 16 Token = 7\n\t\tDW\t240\t* 2\t; Index = 16 Token = 8\n\t\tDW\t240\t* 2\t; Index = 16 Token = 9\n\t\tDW\t240\t* 2\t; Index = 16 Token = 10\n\t\tDW\t240\t* 2\t; Index = 16 Token = 11\n\t\tDW\t288\t* 2\t; Index = 16 Token = 12\n\t\tDW\t320\t* 2\t; Index = 16 Token = 13\n\t\tDW\t352\t* 2\t; Index = 16 Token = 14\n\t\tDW\t384\t* 2\t; Index = 16 Token = 15\n\t\tDW\t256\t* 2\t; Index = 17 Token = 0\n\t\tDW\t256\t* 2\t; Index = 17 Token = 1\n\t\tDW\t256\t* 2\t; Index = 17 Token = 2\n\t\tDW\t256\t* 2\t; Index = 17 Token = 3\n\t\tDW\t304\t* 2\t; Index = 17 Token = 4\n\t\tDW\t336\t* 2\t; Index = 17 Token = 5\n\t\tDW\t368\t* 2\t; Index = 17 Token = 6\n\t\tDW\t400\t* 2\t; Index = 17 Token = 7\n\t\tDW\t256\t* 2\t; Index = 17 Token = 8\n\t\tDW\t256\t* 2\t; Index = 17 Token = 9\n\t\tDW\t256\t* 2\t; Index = 17 Token = 10\n\t\tDW\t256\t* 2\t; Index = 17 Token = 11\n\t\tDW\t304\t* 2\t; Index = 17 Token = 12\n\t\tDW\t336\t* 2\t; Index = 17 Token = 13\n\t\tDW\t368\t* 2\t; Index = 17 Token = 14\n\t\tDW\t400\t* 2\t; Index = 17 Token = 15\n\t\tDW\t272\t* 2\t; Index = 18 Token = 0\n\t\tDW\t272\t* 2\t; Index = 18 Token = 1\n\t\tDW\t272\t* 2\t; Index = 18 Token = 2\n\t\tDW\t272\t* 2\t; Index = 18 Token = 3\n\t\tDW\t320\t* 2\t; Index = 18 Token = 4\n\t\tDW\t352\t* 2\t; Index = 18 Token = 5\n\t\tDW\t384\t* 2\t; Index = 18 Token = 6\n\t\tDW\t416\t* 2\t; Index = 18 Token = 7\n\t\tDW\t272\t* 2\t; Index = 18 Token = 8\n\t\tDW\t272\t* 2\t; Index = 18 Token = 9\n\t\tDW\t272\t* 2\t; Index = 18 Token = 10\n\t\tDW\t272\t* 2\t; Index = 18 Token = 11\n\t\tDW\t320\t* 2\t; Index = 18 Token = 12\n\t\tDW\t352\t* 2\t; Index = 18 Token = 13\n\t\tDW\t384\t* 2\t; Index = 18 Token = 14\n\t\tDW\t416\t* 2\t; Index = 18 Token = 15\n\t\tDW\t288\t* 2\t; Index = 19 Token = 0\n\t\tDW\t288\t* 2\t; Index = 19 Token = 1\n\t\tDW\t288\t* 2\t; Index = 19 Token = 2\n\t\tDW\t288\t* 2\t; Index = 19 Token = 3\n\t\tDW\t336\t* 2\t; Index = 19 Token = 4\n\t\tDW\t368\t* 2\t; Index = 19 Token = 5\n\t\tDW\t400\t* 2\t; Index = 19 Token = 6\n\t\tDW\t432\t* 2\t; Index = 19 Token = 7\n\t\tDW\t288\t* 2\t; Index = 19 Token = 8\n\t\tDW\t288\t* 2\t; Index = 19 Token = 9\n\t\tDW\t288\t* 2\t; Index = 19 Token = 10\n\t\tDW\t288\t* 2\t; Index = 19 Token = 11\n\t\tDW\t336\t* 2\t; Index = 19 Token = 12\n\t\tDW\t368\t* 2\t; Index = 19 Token = 13\n\t\tDW\t400\t* 2\t; Index = 19 Token = 14\n\t\tDW\t432\t* 2\t; Index = 19 Token = 15\n\t\tDW\t304\t* 2\t; Index = 20 Token = 0\n\t\tDW\t304\t* 2\t; Index = 20 Token = 1\n\t\tDW\t304\t* 2\t; Index = 20 Token = 2\n\t\tDW\t304\t* 2\t; Index = 20 Token = 3\n\t\tDW\t352\t* 2\t; Index = 20 Token = 4\n\t\tDW\t384\t* 2\t; Index = 20 Token = 5\n\t\tDW\t416\t* 2\t; Index = 20 Token = 6\n\t\tDW\t448\t* 2\t; Index = 20 Token = 7\n\t\tDW\t304\t* 2\t; Index = 20 Token = 8\n\t\tDW\t304\t* 2\t; Index = 20 Token = 9\n\t\tDW\t304\t* 2\t; Index = 20 Token = 10\n\t\tDW\t304\t* 2\t; Index = 20 Token = 11\n\t\tDW\t352\t* 2\t; Index = 20 Token = 12\n\t\tDW\t384\t* 2\t; Index = 20 Token = 13\n\t\tDW\t416\t* 2\t; Index = 20 Token = 14\n\t\tDW\t448\t* 2\t; Index = 20 Token = 15\n\t\tDW\t320\t* 2\t; Index = 21 Token = 0\n\t\tDW\t320\t* 2\t; Index = 21 Token = 1\n\t\tDW\t320\t* 2\t; Index = 21 Token = 2\n\t\tDW\t320\t* 2\t; Index = 21 Token = 3\n\t\tDW\t368\t* 2\t; Index = 21 Token = 4\n\t\tDW\t400\t* 2\t; Index = 21 Token = 5\n\t\tDW\t432\t* 2\t; Index = 21 Token = 6\n\t\tDW\t464\t* 2\t; Index = 21 Token = 7\n\t\tDW\t320\t* 2\t; Index = 21 Token = 8\n\t\tDW\t320\t* 2\t; Index = 21 Token = 9\n\t\tDW\t320\t* 2\t; Index = 21 Token = 10\n\t\tDW\t320\t* 2\t; Index = 21 Token = 11\n\t\tDW\t368\t* 2\t; Index = 21 Token = 12\n\t\tDW\t400\t* 2\t; Index = 21 Token = 13\n\t\tDW\t432\t* 2\t; Index = 21 Token = 14\n\t\tDW\t464\t* 2\t; Index = 21 Token = 15\n\t\tDW\t336\t* 2\t; Index = 22 Token = 0\n\t\tDW\t336\t* 2\t; Index = 22 Token = 1\n\t\tDW\t336\t* 2\t; Index = 22 Token = 2\n\t\tDW\t336\t* 2\t; Index = 22 Token = 3\n\t\tDW\t384\t* 2\t; Index = 22 Token = 4\n\t\tDW\t416\t* 2\t; Index = 22 Token = 5\n\t\tDW\t448\t* 2\t; Index = 22 Token = 6\n\t\tDW\t480\t* 2\t; Index = 22 Token = 7\n\t\tDW\t336\t* 2\t; Index = 22 Token = 8\n\t\tDW\t336\t* 2\t; Index = 22 Token = 9\n\t\tDW\t336\t* 2\t; Index = 22 Token = 10\n\t\tDW\t336\t* 2\t; Index = 22 Token = 11\n\t\tDW\t384\t* 2\t; Index = 22 Token = 12\n\t\tDW\t416\t* 2\t; Index = 22 Token = 13\n\t\tDW\t448\t* 2\t; Index = 22 Token = 14\n\t\tDW\t480\t* 2\t; Index = 22 Token = 15\n\t\tDW\t352\t* 2\t; Index = 23 Token = 0\n\t\tDW\t352\t* 2\t; Index = 23 Token = 1\n\t\tDW\t352\t* 2\t; Index = 23 Token = 2\n\t\tDW\t352\t* 2\t; Index = 23 Token = 3\n\t\tDW\t400\t* 2\t; Index = 23 Token = 4\n\t\tDW\t432\t* 2\t; Index = 23 Token = 5\n\t\tDW\t464\t* 2\t; Index = 23 Token = 6\n\t\tDW\t496\t* 2\t; Index = 23 Token = 7\n\t\tDW\t352\t* 2\t; Index = 23 Token = 8\n\t\tDW\t352\t* 2\t; Index = 23 Token = 9\n\t\tDW\t352\t* 2\t; Index = 23 Token = 10\n\t\tDW\t352\t* 2\t; Index = 23 Token = 11\n\t\tDW\t400\t* 2\t; Index = 23 Token = 12\n\t\tDW\t432\t* 2\t; Index = 23 Token = 13\n\t\tDW\t464\t* 2\t; Index = 23 Token = 14\n\t\tDW\t496\t* 2\t; Index = 23 Token = 15\n\t\tDW\t368\t* 2\t; Index = 24 Token = 0\n\t\tDW\t368\t* 2\t; Index = 24 Token = 1\n\t\tDW\t368\t* 2\t; Index = 24 Token = 2\n\t\tDW\t368\t* 2\t; Index = 24 Token = 3\n\t\tDW\t416\t* 2\t; Index = 24 Token = 4\n\t\tDW\t448\t* 2\t; Index = 24 Token = 5\n\t\tDW\t480\t* 2\t; Index = 24 Token = 6\n\t\tDW\t512\t* 2\t; Index = 24 Token = 7\n\t\tDW\t368\t* 2\t; Index = 24 Token = 8\n\t\tDW\t368\t* 2\t; Index = 24 Token = 9\n\t\tDW\t368\t* 2\t; Index = 24 Token = 10\n\t\tDW\t368\t* 2\t; Index = 24 Token = 11\n\t\tDW\t416\t* 2\t; Index = 24 Token = 12\n\t\tDW\t448\t* 2\t; Index = 24 Token = 13\n\t\tDW\t480\t* 2\t; Index = 24 Token = 14\n\t\tDW\t512\t* 2\t; Index = 24 Token = 15\n\t\tDW\t384\t* 2\t; Index = 25 Token = 0\n\t\tDW\t384\t* 2\t; Index = 25 Token = 1\n\t\tDW\t384\t* 2\t; Index = 25 Token = 2\n\t\tDW\t384\t* 2\t; Index = 25 Token = 3\n\t\tDW\t432\t* 2\t; Index = 25 Token = 4\n\t\tDW\t464\t* 2\t; Index = 25 Token = 5\n\t\tDW\t496\t* 2\t; Index = 25 Token = 6\n\t\tDW\t528\t* 2\t; Index = 25 Token = 7\n\t\tDW\t384\t* 2\t; Index = 25 Token = 8\n\t\tDW\t384\t* 2\t; Index = 25 Token = 9\n\t\tDW\t384\t* 2\t; Index = 25 Token = 10\n\t\tDW\t384\t* 2\t; Index = 25 Token = 11\n\t\tDW\t432\t* 2\t; Index = 25 Token = 12\n\t\tDW\t464\t* 2\t; Index = 25 Token = 13\n\t\tDW\t496\t* 2\t; Index = 25 Token = 14\n\t\tDW\t528\t* 2\t; Index = 25 Token = 15\n\t\tDW\t400\t* 2\t; Index = 26 Token = 0\n\t\tDW\t400\t* 2\t; Index = 26 Token = 1\n\t\tDW\t400\t* 2\t; Index = 26 Token = 2\n\t\tDW\t400\t* 2\t; Index = 26 Token = 3\n\t\tDW\t448\t* 2\t; Index = 26 Token = 4\n\t\tDW\t480\t* 2\t; Index = 26 Token = 5\n\t\tDW\t512\t* 2\t; Index = 26 Token = 6\n\t\tDW\t544\t* 2\t; Index = 26 Token = 7\n\t\tDW\t400\t* 2\t; Index = 26 Token = 8\n\t\tDW\t400\t* 2\t; Index = 26 Token = 9\n\t\tDW\t400\t* 2\t; Index = 26 Token = 10\n\t\tDW\t400\t* 2\t; Index = 26 Token = 11\n\t\tDW\t448\t* 2\t; Index = 26 Token = 12\n\t\tDW\t480\t* 2\t; Index = 26 Token = 13\n\t\tDW\t512\t* 2\t; Index = 26 Token = 14\n\t\tDW\t544\t* 2\t; Index = 26 Token = 15\n\t\tDW\t416\t* 2\t; Index = 27 Token = 0\n\t\tDW\t416\t* 2\t; Index = 27 Token = 1\n\t\tDW\t416\t* 2\t; Index = 27 Token = 2\n\t\tDW\t416\t* 2\t; Index = 27 Token = 3\n\t\tDW\t464\t* 2\t; Index = 27 Token = 4\n\t\tDW\t496\t* 2\t; Index = 27 Token = 5\n\t\tDW\t528\t* 2\t; Index = 27 Token = 6\n\t\tDW\t560\t* 2\t; Index = 27 Token = 7\n\t\tDW\t416\t* 2\t; Index = 27 Token = 8\n\t\tDW\t416\t* 2\t; Index = 27 Token = 9\n\t\tDW\t416\t* 2\t; Index = 27 Token = 10\n\t\tDW\t416\t* 2\t; Index = 27 Token = 11\n\t\tDW\t464\t* 2\t; Index = 27 Token = 12\n\t\tDW\t496\t* 2\t; Index = 27 Token = 13\n\t\tDW\t528\t* 2\t; Index = 27 Token = 14\n\t\tDW\t560\t* 2\t; Index = 27 Token = 15\n\t\tDW\t432\t* 2\t; Index = 28 Token = 0\n\t\tDW\t432\t* 2\t; Index = 28 Token = 1\n\t\tDW\t432\t* 2\t; Index = 28 Token = 2\n\t\tDW\t432\t* 2\t; Index = 28 Token = 3\n\t\tDW\t480\t* 2\t; Index = 28 Token = 4\n\t\tDW\t512\t* 2\t; Index = 28 Token = 5\n\t\tDW\t544\t* 2\t; Index = 28 Token = 6\n\t\tDW\t576\t* 2\t; Index = 28 Token = 7\n\t\tDW\t432\t* 2\t; Index = 28 Token = 8\n\t\tDW\t432\t* 2\t; Index = 28 Token = 9\n\t\tDW\t432\t* 2\t; Index = 28 Token = 10\n\t\tDW\t432\t* 2\t; Index = 28 Token = 11\n\t\tDW\t480\t* 2\t; Index = 28 Token = 12\n\t\tDW\t512\t* 2\t; Index = 28 Token = 13\n\t\tDW\t544\t* 2\t; Index = 28 Token = 14\n\t\tDW\t576\t* 2\t; Index = 28 Token = 15\n\t\tDW\t448\t* 2\t; Index = 29 Token = 0\n\t\tDW\t448\t* 2\t; Index = 29 Token = 1\n\t\tDW\t448\t* 2\t; Index = 29 Token = 2\n\t\tDW\t448\t* 2\t; Index = 29 Token = 3\n\t\tDW\t496\t* 2\t; Index = 29 Token = 4\n\t\tDW\t528\t* 2\t; Index = 29 Token = 5\n\t\tDW\t560\t* 2\t; Index = 29 Token = 6\n\t\tDW\t592\t* 2\t; Index = 29 Token = 7\n\t\tDW\t448\t* 2\t; Index = 29 Token = 8\n\t\tDW\t448\t* 2\t; Index = 29 Token = 9\n\t\tDW\t448\t* 2\t; Index = 29 Token = 10\n\t\tDW\t448\t* 2\t; Index = 29 Token = 11\n\t\tDW\t496\t* 2\t; Index = 29 Token = 12\n\t\tDW\t528\t* 2\t; Index = 29 Token = 13\n\t\tDW\t560\t* 2\t; Index = 29 Token = 14\n\t\tDW\t592\t* 2\t; Index = 29 Token = 15\n\t\tDW\t464\t* 2\t; Index = 30 Token = 0\n\t\tDW\t464\t* 2\t; Index = 30 Token = 1\n\t\tDW\t464\t* 2\t; Index = 30 Token = 2\n\t\tDW\t464\t* 2\t; Index = 30 Token = 3\n\t\tDW\t512\t* 2\t; Index = 30 Token = 4\n\t\tDW\t544\t* 2\t; Index = 30 Token = 5\n\t\tDW\t576\t* 2\t; Index = 30 Token = 6\n\t\tDW\t608\t* 2\t; Index = 30 Token = 7\n\t\tDW\t464\t* 2\t; Index = 30 Token = 8\n\t\tDW\t464\t* 2\t; Index = 30 Token = 9\n\t\tDW\t464\t* 2\t; Index = 30 Token = 10\n\t\tDW\t464\t* 2\t; Index = 30 Token = 11\n\t\tDW\t512\t* 2\t; Index = 30 Token = 12\n\t\tDW\t544\t* 2\t; Index = 30 Token = 13\n\t\tDW\t576\t* 2\t; Index = 30 Token = 14\n\t\tDW\t608\t* 2\t; Index = 30 Token = 15\n\t\tDW\t480\t* 2\t; Index = 31 Token = 0\n\t\tDW\t480\t* 2\t; Index = 31 Token = 1\n\t\tDW\t480\t* 2\t; Index = 31 Token = 2\n\t\tDW\t480\t* 2\t; Index = 31 Token = 3\n\t\tDW\t528\t* 2\t; Index = 31 Token = 4\n\t\tDW\t560\t* 2\t; Index = 31 Token = 5\n\t\tDW\t592\t* 2\t; Index = 31 Token = 6\n\t\tDW\t624\t* 2\t; Index = 31 Token = 7\n\t\tDW\t480\t* 2\t; Index = 31 Token = 8\n\t\tDW\t480\t* 2\t; Index = 31 Token = 9\n\t\tDW\t480\t* 2\t; Index = 31 Token = 10\n\t\tDW\t480\t* 2\t; Index = 31 Token = 11\n\t\tDW\t528\t* 2\t; Index = 31 Token = 12\n\t\tDW\t560\t* 2\t; Index = 31 Token = 13\n\t\tDW\t592\t* 2\t; Index = 31 Token = 14\n\t\tDW\t624\t* 2\t; Index = 31 Token = 15\n\t\tDW\t496\t* 2\t; Index = 32 Token = 0\n\t\tDW\t496\t* 2\t; Index = 32 Token = 1\n\t\tDW\t496\t* 2\t; Index = 32 Token = 2\n\t\tDW\t496\t* 2\t; Index = 32 Token = 3\n\t\tDW\t544\t* 2\t; Index = 32 Token = 4\n\t\tDW\t576\t* 2\t; Index = 32 Token = 5\n\t\tDW\t608\t* 2\t; Index = 32 Token = 6\n\t\tDW\t640\t* 2\t; Index = 32 Token = 7\n\t\tDW\t496\t* 2\t; Index = 32 Token = 8\n\t\tDW\t496\t* 2\t; Index = 32 Token = 9\n\t\tDW\t496\t* 2\t; Index = 32 Token = 10\n\t\tDW\t496\t* 2\t; Index = 32 Token = 11\n\t\tDW\t544\t* 2\t; Index = 32 Token = 12\n\t\tDW\t576\t* 2\t; Index = 32 Token = 13\n\t\tDW\t608\t* 2\t; Index = 32 Token = 14\n\t\tDW\t640\t* 2\t; Index = 32 Token = 15\n\t\tDW\t512\t* 2\t; Index = 33 Token = 0\n\t\tDW\t512\t* 2\t; Index = 33 Token = 1\n\t\tDW\t512\t* 2\t; Index = 33 Token = 2\n\t\tDW\t512\t* 2\t; Index = 33 Token = 3\n\t\tDW\t560\t* 2\t; Index = 33 Token = 4\n\t\tDW\t592\t* 2\t; Index = 33 Token = 5\n\t\tDW\t624\t* 2\t; Index = 33 Token = 6\n\t\tDW\t656\t* 2\t; Index = 33 Token = 7\n\t\tDW\t512\t* 2\t; Index = 33 Token = 8\n\t\tDW\t512\t* 2\t; Index = 33 Token = 9\n\t\tDW\t512\t* 2\t; Index = 33 Token = 10\n\t\tDW\t512\t* 2\t; Index = 33 Token = 11\n\t\tDW\t560\t* 2\t; Index = 33 Token = 12\n\t\tDW\t592\t* 2\t; Index = 33 Token = 13\n\t\tDW\t624\t* 2\t; Index = 33 Token = 14\n\t\tDW\t656\t* 2\t; Index = 33 Token = 15\n\t\tDW\t528\t* 2\t; Index = 34 Token = 0\n\t\tDW\t528\t* 2\t; Index = 34 Token = 1\n\t\tDW\t528\t* 2\t; Index = 34 Token = 2\n\t\tDW\t528\t* 2\t; Index = 34 Token = 3\n\t\tDW\t576\t* 2\t; Index = 34 Token = 4\n\t\tDW\t608\t* 2\t; Index = 34 Token = 5\n\t\tDW\t640\t* 2\t; Index = 34 Token = 6\n\t\tDW\t672\t* 2\t; Index = 34 Token = 7\n\t\tDW\t528\t* 2\t; Index = 34 Token = 8\n\t\tDW\t528\t* 2\t; Index = 34 Token = 9\n\t\tDW\t528\t* 2\t; Index = 34 Token = 10\n\t\tDW\t528\t* 2\t; Index = 34 Token = 11\n\t\tDW\t576\t* 2\t; Index = 34 Token = 12\n\t\tDW\t608\t* 2\t; Index = 34 Token = 13\n\t\tDW\t640\t* 2\t; Index = 34 Token = 14\n\t\tDW\t672\t* 2\t; Index = 34 Token = 15\n\t\tDW\t544\t* 2\t; Index = 35 Token = 0\n\t\tDW\t544\t* 2\t; Index = 35 Token = 1\n\t\tDW\t544\t* 2\t; Index = 35 Token = 2\n\t\tDW\t544\t* 2\t; Index = 35 Token = 3\n\t\tDW\t592\t* 2\t; Index = 35 Token = 4\n\t\tDW\t624\t* 2\t; Index = 35 Token = 5\n\t\tDW\t656\t* 2\t; Index = 35 Token = 6\n\t\tDW\t688\t* 2\t; Index = 35 Token = 7\n\t\tDW\t544\t* 2\t; Index = 35 Token = 8\n\t\tDW\t544\t* 2\t; Index = 35 Token = 9\n\t\tDW\t544\t* 2\t; Index = 35 Token = 10\n\t\tDW\t544\t* 2\t; Index = 35 Token = 11\n\t\tDW\t592\t* 2\t; Index = 35 Token = 12\n\t\tDW\t624\t* 2\t; Index = 35 Token = 13\n\t\tDW\t656\t* 2\t; Index = 35 Token = 14\n\t\tDW\t688\t* 2\t; Index = 35 Token = 15\n\t\tDW\t560\t* 2\t; Index = 36 Token = 0\n\t\tDW\t560\t* 2\t; Index = 36 Token = 1\n\t\tDW\t560\t* 2\t; Index = 36 Token = 2\n\t\tDW\t560\t* 2\t; Index = 36 Token = 3\n\t\tDW\t608\t* 2\t; Index = 36 Token = 4\n\t\tDW\t640\t* 2\t; Index = 36 Token = 5\n\t\tDW\t672\t* 2\t; Index = 36 Token = 6\n\t\tDW\t704\t* 2\t; Index = 36 Token = 7\n\t\tDW\t560\t* 2\t; Index = 36 Token = 8\n\t\tDW\t560\t* 2\t; Index = 36 Token = 9\n\t\tDW\t560\t* 2\t; Index = 36 Token = 10\n\t\tDW\t560\t* 2\t; Index = 36 Token = 11\n\t\tDW\t608\t* 2\t; Index = 36 Token = 12\n\t\tDW\t640\t* 2\t; Index = 36 Token = 13\n\t\tDW\t672\t* 2\t; Index = 36 Token = 14\n\t\tDW\t704\t* 2\t; Index = 36 Token = 15\n\t\tDW\t576\t* 2\t; Index = 37 Token = 0\n\t\tDW\t576\t* 2\t; Index = 37 Token = 1\n\t\tDW\t576\t* 2\t; Index = 37 Token = 2\n\t\tDW\t576\t* 2\t; Index = 37 Token = 3\n\t\tDW\t624\t* 2\t; Index = 37 Token = 4\n\t\tDW\t656\t* 2\t; Index = 37 Token = 5\n\t\tDW\t688\t* 2\t; Index = 37 Token = 6\n\t\tDW\t720\t* 2\t; Index = 37 Token = 7\n\t\tDW\t576\t* 2\t; Index = 37 Token = 8\n\t\tDW\t576\t* 2\t; Index = 37 Token = 9\n\t\tDW\t576\t* 2\t; Index = 37 Token = 10\n\t\tDW\t576\t* 2\t; Index = 37 Token = 11\n\t\tDW\t624\t* 2\t; Index = 37 Token = 12\n\t\tDW\t656\t* 2\t; Index = 37 Token = 13\n\t\tDW\t688\t* 2\t; Index = 37 Token = 14\n\t\tDW\t720\t* 2\t; Index = 37 Token = 15\n\t\tDW\t592\t* 2\t; Index = 38 Token = 0\n\t\tDW\t592\t* 2\t; Index = 38 Token = 1\n\t\tDW\t592\t* 2\t; Index = 38 Token = 2\n\t\tDW\t592\t* 2\t; Index = 38 Token = 3\n\t\tDW\t640\t* 2\t; Index = 38 Token = 4\n\t\tDW\t672\t* 2\t; Index = 38 Token = 5\n\t\tDW\t704\t* 2\t; Index = 38 Token = 6\n\t\tDW\t736\t* 2\t; Index = 38 Token = 7\n\t\tDW\t592\t* 2\t; Index = 38 Token = 8\n\t\tDW\t592\t* 2\t; Index = 38 Token = 9\n\t\tDW\t592\t* 2\t; Index = 38 Token = 10\n\t\tDW\t592\t* 2\t; Index = 38 Token = 11\n\t\tDW\t640\t* 2\t; Index = 38 Token = 12\n\t\tDW\t672\t* 2\t; Index = 38 Token = 13\n\t\tDW\t704\t* 2\t; Index = 38 Token = 14\n\t\tDW\t736\t* 2\t; Index = 38 Token = 15\n\t\tDW\t608\t* 2\t; Index = 39 Token = 0\n\t\tDW\t608\t* 2\t; Index = 39 Token = 1\n\t\tDW\t608\t* 2\t; Index = 39 Token = 2\n\t\tDW\t608\t* 2\t; Index = 39 Token = 3\n\t\tDW\t656\t* 2\t; Index = 39 Token = 4\n\t\tDW\t688\t* 2\t; Index = 39 Token = 5\n\t\tDW\t720\t* 2\t; Index = 39 Token = 6\n\t\tDW\t752\t* 2\t; Index = 39 Token = 7\n\t\tDW\t608\t* 2\t; Index = 39 Token = 8\n\t\tDW\t608\t* 2\t; Index = 39 Token = 9\n\t\tDW\t608\t* 2\t; Index = 39 Token = 10\n\t\tDW\t608\t* 2\t; Index = 39 Token = 11\n\t\tDW\t656\t* 2\t; Index = 39 Token = 12\n\t\tDW\t688\t* 2\t; Index = 39 Token = 13\n\t\tDW\t720\t* 2\t; Index = 39 Token = 14\n\t\tDW\t752\t* 2\t; Index = 39 Token = 15\n\t\tDW\t624\t* 2\t; Index = 40 Token = 0\n\t\tDW\t624\t* 2\t; Index = 40 Token = 1\n\t\tDW\t624\t* 2\t; Index = 40 Token = 2\n\t\tDW\t624\t* 2\t; Index = 40 Token = 3\n\t\tDW\t672\t* 2\t; Index = 40 Token = 4\n\t\tDW\t704\t* 2\t; Index = 40 Token = 5\n\t\tDW\t736\t* 2\t; Index = 40 Token = 6\n\t\tDW\t768\t* 2\t; Index = 40 Token = 7\n\t\tDW\t624\t* 2\t; Index = 40 Token = 8\n\t\tDW\t624\t* 2\t; Index = 40 Token = 9\n\t\tDW\t624\t* 2\t; Index = 40 Token = 10\n\t\tDW\t624\t* 2\t; Index = 40 Token = 11\n\t\tDW\t672\t* 2\t; Index = 40 Token = 12\n\t\tDW\t704\t* 2\t; Index = 40 Token = 13\n\t\tDW\t736\t* 2\t; Index = 40 Token = 14\n\t\tDW\t768\t* 2\t; Index = 40 Token = 15\n\t\tDW\t640\t* 2\t; Index = 41 Token = 0\n\t\tDW\t640\t* 2\t; Index = 41 Token = 1\n\t\tDW\t640\t* 2\t; Index = 41 Token = 2\n\t\tDW\t640\t* 2\t; Index = 41 Token = 3\n\t\tDW\t688\t* 2\t; Index = 41 Token = 4\n\t\tDW\t720\t* 2\t; Index = 41 Token = 5\n\t\tDW\t752\t* 2\t; Index = 41 Token = 6\n\t\tDW\t784\t* 2\t; Index = 41 Token = 7\n\t\tDW\t640\t* 2\t; Index = 41 Token = 8\n\t\tDW\t640\t* 2\t; Index = 41 Token = 9\n\t\tDW\t640\t* 2\t; Index = 41 Token = 10\n\t\tDW\t640\t* 2\t; Index = 41 Token = 11\n\t\tDW\t688\t* 2\t; Index = 41 Token = 12\n\t\tDW\t720\t* 2\t; Index = 41 Token = 13\n\t\tDW\t752\t* 2\t; Index = 41 Token = 14\n\t\tDW\t784\t* 2\t; Index = 41 Token = 15\n\t\tDW\t656\t* 2\t; Index = 42 Token = 0\n\t\tDW\t656\t* 2\t; Index = 42 Token = 1\n\t\tDW\t656\t* 2\t; Index = 42 Token = 2\n\t\tDW\t656\t* 2\t; Index = 42 Token = 3\n\t\tDW\t704\t* 2\t; Index = 42 Token = 4\n\t\tDW\t736\t* 2\t; Index = 42 Token = 5\n\t\tDW\t768\t* 2\t; Index = 42 Token = 6\n\t\tDW\t800\t* 2\t; Index = 42 Token = 7\n\t\tDW\t656\t* 2\t; Index = 42 Token = 8\n\t\tDW\t656\t* 2\t; Index = 42 Token = 9\n\t\tDW\t656\t* 2\t; Index = 42 Token = 10\n\t\tDW\t656\t* 2\t; Index = 42 Token = 11\n\t\tDW\t704\t* 2\t; Index = 42 Token = 12\n\t\tDW\t736\t* 2\t; Index = 42 Token = 13\n\t\tDW\t768\t* 2\t; Index = 42 Token = 14\n\t\tDW\t800\t* 2\t; Index = 42 Token = 15\n\t\tDW\t672\t* 2\t; Index = 43 Token = 0\n\t\tDW\t672\t* 2\t; Index = 43 Token = 1\n\t\tDW\t672\t* 2\t; Index = 43 Token = 2\n\t\tDW\t672\t* 2\t; Index = 43 Token = 3\n\t\tDW\t720\t* 2\t; Index = 43 Token = 4\n\t\tDW\t752\t* 2\t; Index = 43 Token = 5\n\t\tDW\t784\t* 2\t; Index = 43 Token = 6\n\t\tDW\t816\t* 2\t; Index = 43 Token = 7\n\t\tDW\t672\t* 2\t; Index = 43 Token = 8\n\t\tDW\t672\t* 2\t; Index = 43 Token = 9\n\t\tDW\t672\t* 2\t; Index = 43 Token = 10\n\t\tDW\t672\t* 2\t; Index = 43 Token = 11\n\t\tDW\t720\t* 2\t; Index = 43 Token = 12\n\t\tDW\t752\t* 2\t; Index = 43 Token = 13\n\t\tDW\t784\t* 2\t; Index = 43 Token = 14\n\t\tDW\t816\t* 2\t; Index = 43 Token = 15\n\t\tDW\t688\t* 2\t; Index = 44 Token = 0\n\t\tDW\t688\t* 2\t; Index = 44 Token = 1\n\t\tDW\t688\t* 2\t; Index = 44 Token = 2\n\t\tDW\t688\t* 2\t; Index = 44 Token = 3\n\t\tDW\t736\t* 2\t; Index = 44 Token = 4\n\t\tDW\t768\t* 2\t; Index = 44 Token = 5\n\t\tDW\t800\t* 2\t; Index = 44 Token = 6\n\t\tDW\t832\t* 2\t; Index = 44 Token = 7\n\t\tDW\t688\t* 2\t; Index = 44 Token = 8\n\t\tDW\t688\t* 2\t; Index = 44 Token = 9\n\t\tDW\t688\t* 2\t; Index = 44 Token = 10\n\t\tDW\t688\t* 2\t; Index = 44 Token = 11\n\t\tDW\t736\t* 2\t; Index = 44 Token = 12\n\t\tDW\t768\t* 2\t; Index = 44 Token = 13\n\t\tDW\t800\t* 2\t; Index = 44 Token = 14\n\t\tDW\t832\t* 2\t; Index = 44 Token = 15\n\t\tDW\t704\t* 2\t; Index = 45 Token = 0\n\t\tDW\t704\t* 2\t; Index = 45 Token = 1\n\t\tDW\t704\t* 2\t; Index = 45 Token = 2\n\t\tDW\t704\t* 2\t; Index = 45 Token = 3\n\t\tDW\t752\t* 2\t; Index = 45 Token = 4\n\t\tDW\t784\t* 2\t; Index = 45 Token = 5\n\t\tDW\t816\t* 2\t; Index = 45 Token = 6\n\t\tDW\t848\t* 2\t; Index = 45 Token = 7\n\t\tDW\t704\t* 2\t; Index = 45 Token = 8\n\t\tDW\t704\t* 2\t; Index = 45 Token = 9\n\t\tDW\t704\t* 2\t; Index = 45 Token = 10\n\t\tDW\t704\t* 2\t; Index = 45 Token = 11\n\t\tDW\t752\t* 2\t; Index = 45 Token = 12\n\t\tDW\t784\t* 2\t; Index = 45 Token = 13\n\t\tDW\t816\t* 2\t; Index = 45 Token = 14\n\t\tDW\t848\t* 2\t; Index = 45 Token = 15\n\t\tDW\t720\t* 2\t; Index = 46 Token = 0\n\t\tDW\t720\t* 2\t; Index = 46 Token = 1\n\t\tDW\t720\t* 2\t; Index = 46 Token = 2\n\t\tDW\t720\t* 2\t; Index = 46 Token = 3\n\t\tDW\t768\t* 2\t; Index = 46 Token = 4\n\t\tDW\t800\t* 2\t; Index = 46 Token = 5\n\t\tDW\t832\t* 2\t; Index = 46 Token = 6\n\t\tDW\t864\t* 2\t; Index = 46 Token = 7\n\t\tDW\t720\t* 2\t; Index = 46 Token = 8\n\t\tDW\t720\t* 2\t; Index = 46 Token = 9\n\t\tDW\t720\t* 2\t; Index = 46 Token = 10\n\t\tDW\t720\t* 2\t; Index = 46 Token = 11\n\t\tDW\t768\t* 2\t; Index = 46 Token = 12\n\t\tDW\t800\t* 2\t; Index = 46 Token = 13\n\t\tDW\t832\t* 2\t; Index = 46 Token = 14\n\t\tDW\t864\t* 2\t; Index = 46 Token = 15\n\t\tDW\t736\t* 2\t; Index = 47 Token = 0\n\t\tDW\t736\t* 2\t; Index = 47 Token = 1\n\t\tDW\t736\t* 2\t; Index = 47 Token = 2\n\t\tDW\t736\t* 2\t; Index = 47 Token = 3\n\t\tDW\t784\t* 2\t; Index = 47 Token = 4\n\t\tDW\t816\t* 2\t; Index = 47 Token = 5\n\t\tDW\t848\t* 2\t; Index = 47 Token = 6\n\t\tDW\t880\t* 2\t; Index = 47 Token = 7\n\t\tDW\t736\t* 2\t; Index = 47 Token = 8\n\t\tDW\t736\t* 2\t; Index = 47 Token = 9\n\t\tDW\t736\t* 2\t; Index = 47 Token = 10\n\t\tDW\t736\t* 2\t; Index = 47 Token = 11\n\t\tDW\t784\t* 2\t; Index = 47 Token = 12\n\t\tDW\t816\t* 2\t; Index = 47 Token = 13\n\t\tDW\t848\t* 2\t; Index = 47 Token = 14\n\t\tDW\t880\t* 2\t; Index = 47 Token = 15\n\t\tDW\t752\t* 2\t; Index = 48 Token = 0\n\t\tDW\t752\t* 2\t; Index = 48 Token = 1\n\t\tDW\t752\t* 2\t; Index = 48 Token = 2\n\t\tDW\t752\t* 2\t; Index = 48 Token = 3\n\t\tDW\t800\t* 2\t; Index = 48 Token = 4\n\t\tDW\t832\t* 2\t; Index = 48 Token = 5\n\t\tDW\t864\t* 2\t; Index = 48 Token = 6\n\t\tDW\t896\t* 2\t; Index = 48 Token = 7\n\t\tDW\t752\t* 2\t; Index = 48 Token = 8\n\t\tDW\t752\t* 2\t; Index = 48 Token = 9\n\t\tDW\t752\t* 2\t; Index = 48 Token = 10\n\t\tDW\t752\t* 2\t; Index = 48 Token = 11\n\t\tDW\t800\t* 2\t; Index = 48 Token = 12\n\t\tDW\t832\t* 2\t; Index = 48 Token = 13\n\t\tDW\t864\t* 2\t; Index = 48 Token = 14\n\t\tDW\t896\t* 2\t; Index = 48 Token = 15\n\t\tDW\t768\t* 2\t; Index = 49 Token = 0\n\t\tDW\t768\t* 2\t; Index = 49 Token = 1\n\t\tDW\t768\t* 2\t; Index = 49 Token = 2\n\t\tDW\t768\t* 2\t; Index = 49 Token = 3\n\t\tDW\t816\t* 2\t; Index = 49 Token = 4\n\t\tDW\t848\t* 2\t; Index = 49 Token = 5\n\t\tDW\t880\t* 2\t; Index = 49 Token = 6\n\t\tDW\t912\t* 2\t; Index = 49 Token = 7\n\t\tDW\t768\t* 2\t; Index = 49 Token = 8\n\t\tDW\t768\t* 2\t; Index = 49 Token = 9\n\t\tDW\t768\t* 2\t; Index = 49 Token = 10\n\t\tDW\t768\t* 2\t; Index = 49 Token = 11\n\t\tDW\t816\t* 2\t; Index = 49 Token = 12\n\t\tDW\t848\t* 2\t; Index = 49 Token = 13\n\t\tDW\t880\t* 2\t; Index = 49 Token = 14\n\t\tDW\t912\t* 2\t; Index = 49 Token = 15\n\t\tDW\t784\t* 2\t; Index = 50 Token = 0\n\t\tDW\t784\t* 2\t; Index = 50 Token = 1\n\t\tDW\t784\t* 2\t; Index = 50 Token = 2\n\t\tDW\t784\t* 2\t; Index = 50 Token = 3\n\t\tDW\t832\t* 2\t; Index = 50 Token = 4\n\t\tDW\t864\t* 2\t; Index = 50 Token = 5\n\t\tDW\t896\t* 2\t; Index = 50 Token = 6\n\t\tDW\t928\t* 2\t; Index = 50 Token = 7\n\t\tDW\t784\t* 2\t; Index = 50 Token = 8\n\t\tDW\t784\t* 2\t; Index = 50 Token = 9\n\t\tDW\t784\t* 2\t; Index = 50 Token = 10\n\t\tDW\t784\t* 2\t; Index = 50 Token = 11\n\t\tDW\t832\t* 2\t; Index = 50 Token = 12\n\t\tDW\t864\t* 2\t; Index = 50 Token = 13\n\t\tDW\t896\t* 2\t; Index = 50 Token = 14\n\t\tDW\t928\t* 2\t; Index = 50 Token = 15\n\t\tDW\t800\t* 2\t; Index = 51 Token = 0\n\t\tDW\t800\t* 2\t; Index = 51 Token = 1\n\t\tDW\t800\t* 2\t; Index = 51 Token = 2\n\t\tDW\t800\t* 2\t; Index = 51 Token = 3\n\t\tDW\t848\t* 2\t; Index = 51 Token = 4\n\t\tDW\t880\t* 2\t; Index = 51 Token = 5\n\t\tDW\t912\t* 2\t; Index = 51 Token = 6\n\t\tDW\t944\t* 2\t; Index = 51 Token = 7\n\t\tDW\t800\t* 2\t; Index = 51 Token = 8\n\t\tDW\t800\t* 2\t; Index = 51 Token = 9\n\t\tDW\t800\t* 2\t; Index = 51 Token = 10\n\t\tDW\t800\t* 2\t; Index = 51 Token = 11\n\t\tDW\t848\t* 2\t; Index = 51 Token = 12\n\t\tDW\t880\t* 2\t; Index = 51 Token = 13\n\t\tDW\t912\t* 2\t; Index = 51 Token = 14\n\t\tDW\t944\t* 2\t; Index = 51 Token = 15\n\t\tDW\t816\t* 2\t; Index = 52 Token = 0\n\t\tDW\t816\t* 2\t; Index = 52 Token = 1\n\t\tDW\t816\t* 2\t; Index = 52 Token = 2\n\t\tDW\t816\t* 2\t; Index = 52 Token = 3\n\t\tDW\t864\t* 2\t; Index = 52 Token = 4\n\t\tDW\t896\t* 2\t; Index = 52 Token = 5\n\t\tDW\t928\t* 2\t; Index = 52 Token = 6\n\t\tDW\t960\t* 2\t; Index = 52 Token = 7\n\t\tDW\t816\t* 2\t; Index = 52 Token = 8\n\t\tDW\t816\t* 2\t; Index = 52 Token = 9\n\t\tDW\t816\t* 2\t; Index = 52 Token = 10\n\t\tDW\t816\t* 2\t; Index = 52 Token = 11\n\t\tDW\t864\t* 2\t; Index = 52 Token = 12\n\t\tDW\t896\t* 2\t; Index = 52 Token = 13\n\t\tDW\t928\t* 2\t; Index = 52 Token = 14\n\t\tDW\t960\t* 2\t; Index = 52 Token = 15\n\t\tDW\t832\t* 2\t; Index = 53 Token = 0\n\t\tDW\t832\t* 2\t; Index = 53 Token = 1\n\t\tDW\t832\t* 2\t; Index = 53 Token = 2\n\t\tDW\t832\t* 2\t; Index = 53 Token = 3\n\t\tDW\t880\t* 2\t; Index = 53 Token = 4\n\t\tDW\t912\t* 2\t; Index = 53 Token = 5\n\t\tDW\t944\t* 2\t; Index = 53 Token = 6\n\t\tDW\t976\t* 2\t; Index = 53 Token = 7\n\t\tDW\t832\t* 2\t; Index = 53 Token = 8\n\t\tDW\t832\t* 2\t; Index = 53 Token = 9\n\t\tDW\t832\t* 2\t; Index = 53 Token = 10\n\t\tDW\t832\t* 2\t; Index = 53 Token = 11\n\t\tDW\t880\t* 2\t; Index = 53 Token = 12\n\t\tDW\t912\t* 2\t; Index = 53 Token = 13\n\t\tDW\t944\t* 2\t; Index = 53 Token = 14\n\t\tDW\t976\t* 2\t; Index = 53 Token = 15\n\t\tDW\t848\t* 2\t; Index = 54 Token = 0\n\t\tDW\t848\t* 2\t; Index = 54 Token = 1\n\t\tDW\t848\t* 2\t; Index = 54 Token = 2\n\t\tDW\t848\t* 2\t; Index = 54 Token = 3\n\t\tDW\t896\t* 2\t; Index = 54 Token = 4\n\t\tDW\t928\t* 2\t; Index = 54 Token = 5\n\t\tDW\t960\t* 2\t; Index = 54 Token = 6\n\t\tDW\t992\t* 2\t; Index = 54 Token = 7\n\t\tDW\t848\t* 2\t; Index = 54 Token = 8\n\t\tDW\t848\t* 2\t; Index = 54 Token = 9\n\t\tDW\t848\t* 2\t; Index = 54 Token = 10\n\t\tDW\t848\t* 2\t; Index = 54 Token = 11\n\t\tDW\t896\t* 2\t; Index = 54 Token = 12\n\t\tDW\t928\t* 2\t; Index = 54 Token = 13\n\t\tDW\t960\t* 2\t; Index = 54 Token = 14\n\t\tDW\t992\t* 2\t; Index = 54 Token = 15\n\t\tDW\t864\t* 2\t; Index = 55 Token = 0\n\t\tDW\t864\t* 2\t; Index = 55 Token = 1\n\t\tDW\t864\t* 2\t; Index = 55 Token = 2\n\t\tDW\t864\t* 2\t; Index = 55 Token = 3\n\t\tDW\t912\t* 2\t; Index = 55 Token = 4\n\t\tDW\t944\t* 2\t; Index = 55 Token = 5\n\t\tDW\t976\t* 2\t; Index = 55 Token = 6\n\t\tDW\t1008\t* 2\t; Index = 55 Token = 7\n\t\tDW\t864\t* 2\t; Index = 55 Token = 8\n\t\tDW\t864\t* 2\t; Index = 55 Token = 9\n\t\tDW\t864\t* 2\t; Index = 55 Token = 10\n\t\tDW\t864\t* 2\t; Index = 55 Token = 11\n\t\tDW\t912\t* 2\t; Index = 55 Token = 12\n\t\tDW\t944\t* 2\t; Index = 55 Token = 13\n\t\tDW\t976\t* 2\t; Index = 55 Token = 14\n\t\tDW\t1008\t* 2\t; Index = 55 Token = 15\n\t\tDW\t880\t* 2\t; Index = 56 Token = 0\n\t\tDW\t880\t* 2\t; Index = 56 Token = 1\n\t\tDW\t880\t* 2\t; Index = 56 Token = 2\n\t\tDW\t880\t* 2\t; Index = 56 Token = 3\n\t\tDW\t928\t* 2\t; Index = 56 Token = 4\n\t\tDW\t960\t* 2\t; Index = 56 Token = 5\n\t\tDW\t992\t* 2\t; Index = 56 Token = 6\n\t\tDW\t1024\t* 2\t; Index = 56 Token = 7\n\t\tDW\t880\t* 2\t; Index = 56 Token = 8\n\t\tDW\t880\t* 2\t; Index = 56 Token = 9\n\t\tDW\t880\t* 2\t; Index = 56 Token = 10\n\t\tDW\t880\t* 2\t; Index = 56 Token = 11\n\t\tDW\t928\t* 2\t; Index = 56 Token = 12\n\t\tDW\t960\t* 2\t; Index = 56 Token = 13\n\t\tDW\t992\t* 2\t; Index = 56 Token = 14\n\t\tDW\t1024\t* 2\t; Index = 56 Token = 15\n\t\tDW\t896\t* 2\t; Index = 57 Token = 0\n\t\tDW\t896\t* 2\t; Index = 57 Token = 1\n\t\tDW\t896\t* 2\t; Index = 57 Token = 2\n\t\tDW\t896\t* 2\t; Index = 57 Token = 3\n\t\tDW\t944\t* 2\t; Index = 57 Token = 4\n\t\tDW\t976\t* 2\t; Index = 57 Token = 5\n\t\tDW\t1008\t* 2\t; Index = 57 Token = 6\n\t\tDW\t1040\t* 2\t; Index = 57 Token = 7\n\t\tDW\t896\t* 2\t; Index = 57 Token = 8\n\t\tDW\t896\t* 2\t; Index = 57 Token = 9\n\t\tDW\t896\t* 2\t; Index = 57 Token = 10\n\t\tDW\t896\t* 2\t; Index = 57 Token = 11\n\t\tDW\t944\t* 2\t; Index = 57 Token = 12\n\t\tDW\t976\t* 2\t; Index = 57 Token = 13\n\t\tDW\t1008\t* 2\t; Index = 57 Token = 14\n\t\tDW\t1040\t* 2\t; Index = 57 Token = 15\n\t\tDW\t912\t* 2\t; Index = 58 Token = 0\n\t\tDW\t912\t* 2\t; Index = 58 Token = 1\n\t\tDW\t912\t* 2\t; Index = 58 Token = 2\n\t\tDW\t912\t* 2\t; Index = 58 Token = 3\n\t\tDW\t960\t* 2\t; Index = 58 Token = 4\n\t\tDW\t992\t* 2\t; Index = 58 Token = 5\n\t\tDW\t1024\t* 2\t; Index = 58 Token = 6\n\t\tDW\t1056\t* 2\t; Index = 58 Token = 7\n\t\tDW\t912\t* 2\t; Index = 58 Token = 8\n\t\tDW\t912\t* 2\t; Index = 58 Token = 9\n\t\tDW\t912\t* 2\t; Index = 58 Token = 10\n\t\tDW\t912\t* 2\t; Index = 58 Token = 11\n\t\tDW\t960\t* 2\t; Index = 58 Token = 12\n\t\tDW\t992\t* 2\t; Index = 58 Token = 13\n\t\tDW\t1024\t* 2\t; Index = 58 Token = 14\n\t\tDW\t1056\t* 2\t; Index = 58 Token = 15\n\t\tDW\t928\t* 2\t; Index = 59 Token = 0\n\t\tDW\t928\t* 2\t; Index = 59 Token = 1\n\t\tDW\t928\t* 2\t; Index = 59 Token = 2\n\t\tDW\t928\t* 2\t; Index = 59 Token = 3\n\t\tDW\t976\t* 2\t; Index = 59 Token = 4\n\t\tDW\t1008\t* 2\t; Index = 59 Token = 5\n\t\tDW\t1040\t* 2\t; Index = 59 Token = 6\n\t\tDW\t1072\t* 2\t; Index = 59 Token = 7\n\t\tDW\t928\t* 2\t; Index = 59 Token = 8\n\t\tDW\t928\t* 2\t; Index = 59 Token = 9\n\t\tDW\t928\t* 2\t; Index = 59 Token = 10\n\t\tDW\t928\t* 2\t; Index = 59 Token = 11\n\t\tDW\t976\t* 2\t; Index = 59 Token = 12\n\t\tDW\t1008\t* 2\t; Index = 59 Token = 13\n\t\tDW\t1040\t* 2\t; Index = 59 Token = 14\n\t\tDW\t1072\t* 2\t; Index = 59 Token = 15\n\t\tDW\t944\t* 2\t; Index = 60 Token = 0\n\t\tDW\t944\t* 2\t; Index = 60 Token = 1\n\t\tDW\t944\t* 2\t; Index = 60 Token = 2\n\t\tDW\t944\t* 2\t; Index = 60 Token = 3\n\t\tDW\t992\t* 2\t; Index = 60 Token = 4\n\t\tDW\t1024\t* 2\t; Index = 60 Token = 5\n\t\tDW\t1056\t* 2\t; Index = 60 Token = 6\n\t\tDW\t1088\t* 2\t; Index = 60 Token = 7\n\t\tDW\t944\t* 2\t; Index = 60 Token = 8\n\t\tDW\t944\t* 2\t; Index = 60 Token = 9\n\t\tDW\t944\t* 2\t; Index = 60 Token = 10\n\t\tDW\t944\t* 2\t; Index = 60 Token = 11\n\t\tDW\t992\t* 2\t; Index = 60 Token = 12\n\t\tDW\t1024\t* 2\t; Index = 60 Token = 13\n\t\tDW\t1056\t* 2\t; Index = 60 Token = 14\n\t\tDW\t1088\t* 2\t; Index = 60 Token = 15\n\t\tDW\t960\t* 2\t; Index = 61 Token = 0\n\t\tDW\t960\t* 2\t; Index = 61 Token = 1\n\t\tDW\t960\t* 2\t; Index = 61 Token = 2\n\t\tDW\t960\t* 2\t; Index = 61 Token = 3\n\t\tDW\t1008\t* 2\t; Index = 61 Token = 4\n\t\tDW\t1040\t* 2\t; Index = 61 Token = 5\n\t\tDW\t1072\t* 2\t; Index = 61 Token = 6\n\t\tDW\t1104\t* 2\t; Index = 61 Token = 7\n\t\tDW\t960\t* 2\t; Index = 61 Token = 8\n\t\tDW\t960\t* 2\t; Index = 61 Token = 9\n\t\tDW\t960\t* 2\t; Index = 61 Token = 10\n\t\tDW\t960\t* 2\t; Index = 61 Token = 11\n\t\tDW\t1008\t* 2\t; Index = 61 Token = 12\n\t\tDW\t1040\t* 2\t; Index = 61 Token = 13\n\t\tDW\t1072\t* 2\t; Index = 61 Token = 14\n\t\tDW\t1104\t* 2\t; Index = 61 Token = 15\n\t\tDW\t976\t* 2\t; Index = 62 Token = 0\n\t\tDW\t976\t* 2\t; Index = 62 Token = 1\n\t\tDW\t976\t* 2\t; Index = 62 Token = 2\n\t\tDW\t976\t* 2\t; Index = 62 Token = 3\n\t\tDW\t1024\t* 2\t; Index = 62 Token = 4\n\t\tDW\t1056\t* 2\t; Index = 62 Token = 5\n\t\tDW\t1088\t* 2\t; Index = 62 Token = 6\n\t\tDW\t1120\t* 2\t; Index = 62 Token = 7\n\t\tDW\t976\t* 2\t; Index = 62 Token = 8\n\t\tDW\t976\t* 2\t; Index = 62 Token = 9\n\t\tDW\t976\t* 2\t; Index = 62 Token = 10\n\t\tDW\t976\t* 2\t; Index = 62 Token = 11\n\t\tDW\t1024\t* 2\t; Index = 62 Token = 12\n\t\tDW\t1056\t* 2\t; Index = 62 Token = 13\n\t\tDW\t1088\t* 2\t; Index = 62 Token = 14\n\t\tDW\t1120\t* 2\t; Index = 62 Token = 15\n\t\tDW\t992\t* 2\t; Index = 63 Token = 0\n\t\tDW\t992\t* 2\t; Index = 63 Token = 1\n\t\tDW\t992\t* 2\t; Index = 63 Token = 2\n\t\tDW\t992\t* 2\t; Index = 63 Token = 3\n\t\tDW\t1040\t* 2\t; Index = 63 Token = 4\n\t\tDW\t1072\t* 2\t; Index = 63 Token = 5\n\t\tDW\t1104\t* 2\t; Index = 63 Token = 6\n\t\tDW\t1136\t* 2\t; Index = 63 Token = 7\n\t\tDW\t992\t* 2\t; Index = 63 Token = 8\n\t\tDW\t992\t* 2\t; Index = 63 Token = 9\n\t\tDW\t992\t* 2\t; Index = 63 Token = 10\n\t\tDW\t992\t* 2\t; Index = 63 Token = 11\n\t\tDW\t1040\t* 2\t; Index = 63 Token = 12\n\t\tDW\t1072\t* 2\t; Index = 63 Token = 13\n\t\tDW\t1104\t* 2\t; Index = 63 Token = 14\n\t\tDW\t1136\t* 2\t; Index = 63 Token = 15\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 0\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 1\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 2\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 3\n\t\tDW\t1056\t* 2\t; Index = 64 Token = 4\n\t\tDW\t1088\t* 2\t; Index = 64 Token = 5\n\t\tDW\t1120\t* 2\t; Index = 64 Token = 6\n\t\tDW\t1152\t* 2\t; Index = 64 Token = 7\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 8\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 9\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 10\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 11\n\t\tDW\t1056\t* 2\t; Index = 64 Token = 12\n\t\tDW\t1088\t* 2\t; Index = 64 Token = 13\n\t\tDW\t1120\t* 2\t; Index = 64 Token = 14\n\t\tDW\t1152\t* 2\t; Index = 64 Token = 15\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 0\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 1\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 2\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 3\n\t\tDW\t1072\t* 2\t; Index = 65 Token = 4\n\t\tDW\t1104\t* 2\t; Index = 65 Token = 5\n\t\tDW\t1136\t* 2\t; Index = 65 Token = 6\n\t\tDW\t1168\t* 2\t; Index = 65 Token = 7\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 8\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 9\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 10\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 11\n\t\tDW\t1072\t* 2\t; Index = 65 Token = 12\n\t\tDW\t1104\t* 2\t; Index = 65 Token = 13\n\t\tDW\t1136\t* 2\t; Index = 65 Token = 14\n\t\tDW\t1168\t* 2\t; Index = 65 Token = 15\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 0\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 1\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 2\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 3\n\t\tDW\t1088\t* 2\t; Index = 66 Token = 4\n\t\tDW\t1120\t* 2\t; Index = 66 Token = 5\n\t\tDW\t1152\t* 2\t; Index = 66 Token = 6\n\t\tDW\t1184\t* 2\t; Index = 66 Token = 7\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 8\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 9\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 10\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 11\n\t\tDW\t1088\t* 2\t; Index = 66 Token = 12\n\t\tDW\t1120\t* 2\t; Index = 66 Token = 13\n\t\tDW\t1152\t* 2\t; Index = 66 Token = 14\n\t\tDW\t1184\t* 2\t; Index = 66 Token = 15\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 0\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 1\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 2\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 3\n\t\tDW\t1104\t* 2\t; Index = 67 Token = 4\n\t\tDW\t1136\t* 2\t; Index = 67 Token = 5\n\t\tDW\t1168\t* 2\t; Index = 67 Token = 6\n\t\tDW\t1200\t* 2\t; Index = 67 Token = 7\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 8\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 9\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 10\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 11\n\t\tDW\t1104\t* 2\t; Index = 67 Token = 12\n\t\tDW\t1136\t* 2\t; Index = 67 Token = 13\n\t\tDW\t1168\t* 2\t; Index = 67 Token = 14\n\t\tDW\t1200\t* 2\t; Index = 67 Token = 15\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 0\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 1\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 2\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 3\n\t\tDW\t1120\t* 2\t; Index = 68 Token = 4\n\t\tDW\t1152\t* 2\t; Index = 68 Token = 5\n\t\tDW\t1184\t* 2\t; Index = 68 Token = 6\n\t\tDW\t1216\t* 2\t; Index = 68 Token = 7\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 8\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 9\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 10\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 11\n\t\tDW\t1120\t* 2\t; Index = 68 Token = 12\n\t\tDW\t1152\t* 2\t; Index = 68 Token = 13\n\t\tDW\t1184\t* 2\t; Index = 68 Token = 14\n\t\tDW\t1216\t* 2\t; Index = 68 Token = 15\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 0\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 1\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 2\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 3\n\t\tDW\t1136\t* 2\t; Index = 69 Token = 4\n\t\tDW\t1168\t* 2\t; Index = 69 Token = 5\n\t\tDW\t1200\t* 2\t; Index = 69 Token = 6\n\t\tDW\t1232\t* 2\t; Index = 69 Token = 7\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 8\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 9\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 10\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 11\n\t\tDW\t1136\t* 2\t; Index = 69 Token = 12\n\t\tDW\t1168\t* 2\t; Index = 69 Token = 13\n\t\tDW\t1200\t* 2\t; Index = 69 Token = 14\n\t\tDW\t1232\t* 2\t; Index = 69 Token = 15\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 0\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 1\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 2\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 3\n\t\tDW\t1152\t* 2\t; Index = 70 Token = 4\n\t\tDW\t1184\t* 2\t; Index = 70 Token = 5\n\t\tDW\t1216\t* 2\t; Index = 70 Token = 6\n\t\tDW\t1248\t* 2\t; Index = 70 Token = 7\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 8\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 9\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 10\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 11\n\t\tDW\t1152\t* 2\t; Index = 70 Token = 12\n\t\tDW\t1184\t* 2\t; Index = 70 Token = 13\n\t\tDW\t1216\t* 2\t; Index = 70 Token = 14\n\t\tDW\t1248\t* 2\t; Index = 70 Token = 15\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 0\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 1\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 2\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 3\n\t\tDW\t1168\t* 2\t; Index = 71 Token = 4\n\t\tDW\t1200\t* 2\t; Index = 71 Token = 5\n\t\tDW\t1232\t* 2\t; Index = 71 Token = 6\n\t\tDW\t1264\t* 2\t; Index = 71 Token = 7\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 8\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 9\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 10\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 11\n\t\tDW\t1168\t* 2\t; Index = 71 Token = 12\n\t\tDW\t1200\t* 2\t; Index = 71 Token = 13\n\t\tDW\t1232\t* 2\t; Index = 71 Token = 14\n\t\tDW\t1264\t* 2\t; Index = 71 Token = 15\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 0\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 1\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 2\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 3\n\t\tDW\t1184\t* 2\t; Index = 72 Token = 4\n\t\tDW\t1216\t* 2\t; Index = 72 Token = 5\n\t\tDW\t1248\t* 2\t; Index = 72 Token = 6\n\t\tDW\t1280\t* 2\t; Index = 72 Token = 7\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 8\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 9\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 10\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 11\n\t\tDW\t1184\t* 2\t; Index = 72 Token = 12\n\t\tDW\t1216\t* 2\t; Index = 72 Token = 13\n\t\tDW\t1248\t* 2\t; Index = 72 Token = 14\n\t\tDW\t1280\t* 2\t; Index = 72 Token = 15\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 0\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 1\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 2\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 3\n\t\tDW\t1200\t* 2\t; Index = 73 Token = 4\n\t\tDW\t1232\t* 2\t; Index = 73 Token = 5\n\t\tDW\t1264\t* 2\t; Index = 73 Token = 6\n\t\tDW\t1296\t* 2\t; Index = 73 Token = 7\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 8\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 9\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 10\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 11\n\t\tDW\t1200\t* 2\t; Index = 73 Token = 12\n\t\tDW\t1232\t* 2\t; Index = 73 Token = 13\n\t\tDW\t1264\t* 2\t; Index = 73 Token = 14\n\t\tDW\t1296\t* 2\t; Index = 73 Token = 15\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 0\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 1\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 2\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 3\n\t\tDW\t1216\t* 2\t; Index = 74 Token = 4\n\t\tDW\t1248\t* 2\t; Index = 74 Token = 5\n\t\tDW\t1280\t* 2\t; Index = 74 Token = 6\n\t\tDW\t1312\t* 2\t; Index = 74 Token = 7\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 8\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 9\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 10\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 11\n\t\tDW\t1216\t* 2\t; Index = 74 Token = 12\n\t\tDW\t1248\t* 2\t; Index = 74 Token = 13\n\t\tDW\t1280\t* 2\t; Index = 74 Token = 14\n\t\tDW\t1312\t* 2\t; Index = 74 Token = 15\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 0\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 1\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 2\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 3\n\t\tDW\t1232\t* 2\t; Index = 75 Token = 4\n\t\tDW\t1264\t* 2\t; Index = 75 Token = 5\n\t\tDW\t1296\t* 2\t; Index = 75 Token = 6\n\t\tDW\t1328\t* 2\t; Index = 75 Token = 7\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 8\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 9\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 10\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 11\n\t\tDW\t1232\t* 2\t; Index = 75 Token = 12\n\t\tDW\t1264\t* 2\t; Index = 75 Token = 13\n\t\tDW\t1296\t* 2\t; Index = 75 Token = 14\n\t\tDW\t1328\t* 2\t; Index = 75 Token = 15\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 0\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 1\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 2\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 3\n\t\tDW\t1248\t* 2\t; Index = 76 Token = 4\n\t\tDW\t1280\t* 2\t; Index = 76 Token = 5\n\t\tDW\t1312\t* 2\t; Index = 76 Token = 6\n\t\tDW\t1344\t* 2\t; Index = 76 Token = 7\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 8\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 9\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 10\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 11\n\t\tDW\t1248\t* 2\t; Index = 76 Token = 12\n\t\tDW\t1280\t* 2\t; Index = 76 Token = 13\n\t\tDW\t1312\t* 2\t; Index = 76 Token = 14\n\t\tDW\t1344\t* 2\t; Index = 76 Token = 15\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 0\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 1\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 2\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 3\n\t\tDW\t1264\t* 2\t; Index = 77 Token = 4\n\t\tDW\t1296\t* 2\t; Index = 77 Token = 5\n\t\tDW\t1328\t* 2\t; Index = 77 Token = 6\n\t\tDW\t1360\t* 2\t; Index = 77 Token = 7\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 8\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 9\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 10\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 11\n\t\tDW\t1264\t* 2\t; Index = 77 Token = 12\n\t\tDW\t1296\t* 2\t; Index = 77 Token = 13\n\t\tDW\t1328\t* 2\t; Index = 77 Token = 14\n\t\tDW\t1360\t* 2\t; Index = 77 Token = 15\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 0\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 1\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 2\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 3\n\t\tDW\t1280\t* 2\t; Index = 78 Token = 4\n\t\tDW\t1312\t* 2\t; Index = 78 Token = 5\n\t\tDW\t1344\t* 2\t; Index = 78 Token = 6\n\t\tDW\t1376\t* 2\t; Index = 78 Token = 7\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 8\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 9\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 10\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 11\n\t\tDW\t1280\t* 2\t; Index = 78 Token = 12\n\t\tDW\t1312\t* 2\t; Index = 78 Token = 13\n\t\tDW\t1344\t* 2\t; Index = 78 Token = 14\n\t\tDW\t1376\t* 2\t; Index = 78 Token = 15\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 0\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 1\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 2\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 3\n\t\tDW\t1296\t* 2\t; Index = 79 Token = 4\n\t\tDW\t1328\t* 2\t; Index = 79 Token = 5\n\t\tDW\t1360\t* 2\t; Index = 79 Token = 6\n\t\tDW\t1392\t* 2\t; Index = 79 Token = 7\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 8\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 9\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 10\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 11\n\t\tDW\t1296\t* 2\t; Index = 79 Token = 12\n\t\tDW\t1328\t* 2\t; Index = 79 Token = 13\n\t\tDW\t1360\t* 2\t; Index = 79 Token = 14\n\t\tDW\t1392\t* 2\t; Index = 79 Token = 15\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 0\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 1\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 2\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 3\n\t\tDW\t1312\t* 2\t; Index = 80 Token = 4\n\t\tDW\t1344\t* 2\t; Index = 80 Token = 5\n\t\tDW\t1376\t* 2\t; Index = 80 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 80 Token = 7\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 8\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 9\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 10\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 11\n\t\tDW\t1312\t* 2\t; Index = 80 Token = 12\n\t\tDW\t1344\t* 2\t; Index = 80 Token = 13\n\t\tDW\t1376\t* 2\t; Index = 80 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 80 Token = 15\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 0\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 1\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 2\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 3\n\t\tDW\t1328\t* 2\t; Index = 81 Token = 4\n\t\tDW\t1360\t* 2\t; Index = 81 Token = 5\n\t\tDW\t1392\t* 2\t; Index = 81 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 81 Token = 7\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 8\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 9\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 10\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 11\n\t\tDW\t1328\t* 2\t; Index = 81 Token = 12\n\t\tDW\t1360\t* 2\t; Index = 81 Token = 13\n\t\tDW\t1392\t* 2\t; Index = 81 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 81 Token = 15\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 0\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 1\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 2\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 3\n\t\tDW\t1344\t* 2\t; Index = 82 Token = 4\n\t\tDW\t1376\t* 2\t; Index = 82 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 7\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 8\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 9\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 10\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 11\n\t\tDW\t1344\t* 2\t; Index = 82 Token = 12\n\t\tDW\t1376\t* 2\t; Index = 82 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 15\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 0\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 1\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 2\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 3\n\t\tDW\t1360\t* 2\t; Index = 83 Token = 4\n\t\tDW\t1392\t* 2\t; Index = 83 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 7\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 8\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 9\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 10\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 11\n\t\tDW\t1360\t* 2\t; Index = 83 Token = 12\n\t\tDW\t1392\t* 2\t; Index = 83 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 15\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 0\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 1\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 2\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 3\n\t\tDW\t1376\t* 2\t; Index = 84 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 7\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 8\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 9\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 10\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 11\n\t\tDW\t1376\t* 2\t; Index = 84 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 15\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 0\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 1\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 2\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 3\n\t\tDW\t1392\t* 2\t; Index = 85 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 7\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 8\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 9\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 10\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 11\n\t\tDW\t1392\t* 2\t; Index = 85 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 15\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 0\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 1\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 2\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 7\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 8\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 9\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 10\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 15\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 0\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 1\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 2\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 7\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 8\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 9\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 10\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 15\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 0\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 1\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 2\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 7\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 8\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 9\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 10\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 15\n"
  },
  {
    "path": "WIN32LIB/AUDIO/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = AUDIO\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS = \t\t\t\t&\n\t\tsoundio.obj\t\t&\n\t\tsoundint.obj\t&\n\t\tsoundlck.obj\t&\n\t\tsoscodec.obj\t&\n                olsosdec.obj    &\n\t\tauduncmp.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;..\\..\\dxsdk\\lib;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;..\\..\\dxsdk\\inc;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.lib  $(%WIN32LIB)\\lib\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t copy *.lib $(%WIN32LIB)\\lib\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\tcopy *.386 test\n\n#**************************** End of makefile ******************************\n"
  },
  {
    "path": "WIN32LIB/AUDIO/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = audio\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t\tsoundio.obj\t\t\\\n\t\t\t\tsoundint.obj\t\\\n\t\t\t\tsoundlck.obj\t\\\n\t\t\t\tsoscodec.obj\t\\\n\t\t\t\tauduncmp.obj\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) \n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n +-soundio.obj\t\t&\n+-soundint.obj\t\t&\n+-soundlck.obj\t\t&\n+-soscodec.obj\t\t&\n+-auduncmp.obj\t\n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/AUDIO/NYBBTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* bNybbleTablexxxx - ADPCM Lookup table for nybbles\n;****************************************************************************\n\n\t\talign\t4\n\nbNybbleTableLow\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\n\t\talign 4\n\nbNybbleTableHigh\tDB\t00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2\n\t\tDB\t01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2\n\t\tDB\t02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2\n\t\tDB\t03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2\n\t\tDB\t04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2\n\t\tDB\t05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2\n\t\tDB\t06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2\n\t\tDB\t07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2\n\t\tDB\t08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2\n\t\tDB\t09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2\n\t\tDB\t0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2\n\t\tDB\t0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2\n\t\tDB\t0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2\n\t\tDB\t0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2\n\t\tDB\t0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2\n\t\tDB\t0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/AUDIO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : AUDIO.H                                  *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : March 10, 1995                           *\n *                                                                         *\n *                  Last Update : March 10, 1995   [PWG]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwstd.h\"\n\n/*=========================================================================*/\n/* AUD file header type\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tAUD_FLAG_STEREO\t1\n#define\tAUD_FLAG_16BIT\t\t2\n\n// PWG 3-14-95: This structure used to have bit fields defined for Stereo\n//   and Bits.  These were removed because watcom packs them into a 32 bit\n//   flag entry even though they could have fit in a 8 bit entry.\n#pragma pack(1);\ntypedef struct {\n\tunsigned short int\tRate;\t\t\t\t// Playback rate (hertz).\n\tlong\tSize;\t\t\t\t// Size of data (bytes).\n\tlong\tUncompSize;\t\t\t\t// Size of data (bytes).\n\tunsigned char Flags;\t// Holds flags for info\n\t\t\t\t\t\t\t\t//  1: Is the sample stereo?\n\t\t\t\t\t\t\t\t//  2: Is the sample 16 bits?\n\tunsigned char Compression;\t// What kind of compression for this sample?\n} AUDHeaderType;\n\n\n/*=========================================================================*/\n/*\tThere can be a different sound driver for sound effects, digitized\t\t*/\n/*\tsamples, and musical scores.  Each one must be of these specified\t\t\t*/\n/*\ttypes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\ntypedef enum {\n\tSAMPLE_NONE,\t\t// No digitized sounds will be played.\n\tSAMPLE_SB,\t\t\t// Sound Blaster digitized driver.\n\tSAMPLE_SBPRO,\t\t// Sound Blaster Pro digitized driver.\n\tSAMPLE_PAS,\t\t\t// Pro-Audio Spectrum digitized driver.\n\tSAMPLE_ADLIBG,\t\t// Adlib-Gold digitized driver.\n\tSAMPLE_TANDY,\t\t// Tandy 'compatible' driver.\n\tSAMPLE_PCSPKR,\t\t// PC speaker digitized driver (The Audio Solution driver).\n\tSAMPLE_ADLIB,\t\t// Adlib digitized driver (The Audio Solution driver).\n\tSAMPLE_TEMP=0x1000,\n\tSAMPLE_LAST\n} Sample_Type;\n\ntypedef enum {\n\tSCORE_NONE,\t\t\t// No scores will be played.\n\tSCORE_ALFX,\t\t\t// Westwood's ALFX adlib compatable driver.\n\tSCORE_WWPCSPKR,\t// Westwood's PC-speaker driver (obsolete).\n\tSCORE_WWTANDY,\t\t// Westwood's PC-speaker driver with Tandy mod (obsolete).\n\tSCORE_PCSPKR,\t\t// PC speaker XMIDI driver.\n\tSCORE_TANDY,\t\t// Tandy XMIDI driver.\n\tSCORE_MT32,\t\t\t// MT-32 / LAPC-1 Roland XMIDI driver.\n\tSCORE_CANVAS,\t\t// Sound Canvas SC-55.\n\tSCORE_ADLIB,\t\t// Adlib XMIDI driver.\n\tSCORE_ADLIBG,\t\t// Adlib Gold XMIDI driver.\n\tSCORE_PASFM,\t\t// Pro Audio Spectrum XMIDI driver.\n\tSCORE_SBFM,\t\t\t// Sound Blaster XMIDI driver.\n\tSCORE_SBP1FM,\t\t// Sound Blaster Pro (YM3812) XMIDI driver.\n\tSCORE_SBP2FM,\t\t// Sound Blaster Pro (OPL3) XMIDI driver (Can't use with SFX_ALFX).\n\tSCORE_TEMP=0x1000,\n\tSCORE_LAST\n} Score_Type;\n\ntypedef enum {\n\tSFX_NONE,\t\t\t// No sound effects will be played.\n\tSFX_ALFX,\t\t\t// Westwood's ALFX adlib compatable driver.\n\tSFX_WWPCSPKR,\t\t// Westwood's PC-speaker driver.\n\tSFX_WWTANDY,\t\t// Westwood's PC-speaker driver with Tandy mod.\n\tSFX_PCSPKR,\t\t\t// PC speaker XMIDI driver.\n\tSFX_TANDY,\t\t\t// Tandy XMIDI driver.\n\tSFX_MT32,\t\t\t// MT-32 / LAPC-1 Roland XMIDI driver.\n\tSFX_CANVAS,\t\t\t// Sound Canvas SC-55.\n\tSFX_ADLIB,\t\t\t// Adlib XMIDI driver.\n\tSFX_ADLIBG,\t\t\t// Adlib Gold XMIDI driver.\n\tSFX_PASFM,\t\t\t// Pro Audio Spectrum XMIDI driver.\n\tSFX_SBFM,\t\t\t// Sound Blaster XMIDI driver.\n\tSFX_SBP1FM,\t\t\t// Sound Blaster Pro (YM3812) XMIDI driver.\n\tSFX_SBP2FM,\t\t\t// Sound Blaster Pro (OPL3) XMIDI driver.\n\tSFX_TEMP=0x1000,\n\tSFX_LAST\n} SFX_Type;\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SOUNDIO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nint File_Stream_Sample(char const *filename, BOOL real_time_start = FALSE);\nint File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start = FALSE);\nvoid __cdecl Sound_Callback(void);\nvoid __cdecl far maintenance_callback(void);\nvoid *Load_Sample(char const *filename);\nlong Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);\nlong Sample_Read(int fh, void *buffer, long size);\nvoid Free_Sample(void const *sample);\nBOOL Audio_Init( HWND window , int bits_per_sample, BOOL stereo , int rate , int reverse_channels);\nvoid Sound_End(void);\nvoid Stop_Sample(int handle);\nBOOL Sample_Status(int handle);\nBOOL Is_Sample_Playing(void const * sample);\nvoid Stop_Sample_Playing(void const * sample);\nint Play_Sample(void const *sample, int priority=0xFF, int volume=0xFF, signed short panloc = 0x0);\nint Play_Sample_Handle(void const *sample, int priority, int volume, signed short panloc, int id);\nint Set_Sound_Vol(int volume);\nint Set_Score_Vol(int volume);\nvoid Fade_Sample(int handle, int ticks);\nint Get_Free_Sample_Handle(int priority);\nint Get_Digi_Handle(void);\nlong Sample_Length(void const *sample);\nvoid Restore_Sound_Buffers (void);\nBOOL Set_Primary_Buffer_Format(void);\nBOOL Start_Primary_Sound_Buffer (BOOL forced);\nvoid Stop_Primary_Sound_Buffer (void);\n\n/*\n** Function to call if we detect focus loss\n*/\nextern\tvoid (*Audio_Focus_Loss_Function)(void);\n\n\nextern int Misc;\nextern SFX_Type SoundType;\nextern Sample_Type SampleType;\n\nextern CRITICAL_SECTION\tGlobalAudioCriticalSection;\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/AUDUNCMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Audio Library            *\n;*                                                                         *\n;*                    File Name : AUDUNCMP.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : March 14, 1995                           *\n;*                                                                         *\n;*                  Last Update : June 26, 1995   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Decompress_Frame_Lock -- locks the JLB audio decompression code       *\n;*   Decompress_Frame_Unlock -- Unlocks the JLB audio compression code     *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\nDPMI_INTR\t\tequ\t31h\n\nLABEL \tLockedCodeStart\tBYTE\n\nCODE_2BIT\tEQU\t0\nCODE_4BIT\tEQU\t1\nCODE_RAW\tEQU\t2\nCODE_SILENCE\tEQU\t3\nMAGICNUMBER\tEQU\t00000DEAFh\nMAGICNUMBER2\tEQU\t0BABEBABEh\n\n_2bitdecode\tDB\t-2,-1,0,1\n_4bitdecode\tDB\t-9,-8,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,8\n\n\n;***************************************************************************\n;* DECOMPRESS_FRAME -- Uncompresses a WW compressed audio frame            *\n;*                                                                         *\n;* INPUT:\tvoid * source - pointer to encoded audio data              *\n;*\t\tvoid * dest   - pointer to decompression area\t\t   *\n;*\t\tlong size     - the maximum size of destination buffer\t   *\n;*                                                                         *\n;* OUTPUT:      long - the number of bytes we uncompressed                 *\n;*                                                                         *\n;* PROTO:\tlong Decompress_Frame(void *, void *, long);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/14/1995 PWG : Created.                                             *\n;*=========================================================================*\n\n\tGLOBAL\tC Decompress_Frame:NEAR\n\tPROC\tDecompress_Frame C NEAR USES ebx ecx edx esi edi\n\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tcount:DWORD\n\n\tLOCAL\tprevious:BYTE\n\tLOCAL\tincount:DWORD\n\n\tpushfd\n\tcld\n\tmov\t[incount],0\t;Bytes read from source\n\n\n;\tSource, Dest and count must be valid.\n\n\tcmp\t[source],0\n\tje\t??fini\n\n\tcmp\t[dest],0\n\tje\t??fini\n\n\tcmp\t[count],0\n\tje\t??fini\n\n\tmov\tesi,[source]\t;Pointer to source data.\n\tmov\tedi,[dest]\t;Pointer to destination data.\n\tmov\tecx,[count]\t;Number of bytes to fill dest buffer.\n\tmov\tdl,080h\t;Previous sample (starting value).\n\n??mainloop:\n\tcmp\tecx,0\t;If dest full then exit\n\tjle\t??fini\n\n\txor\teax,eax\n\tmov\tal,[esi]\t;Get code byte\n\tinc\t[incount]\n\tinc\tesi\n\tshl\teax,2\t;AH contains code.\n\tshr\tal,2\t;AL contains sub-code data.\n\n\tcmp\tah,CODE_RAW\t;Raw sequence?\n\tjne\tshort ??try4bit\n\n;\tThe code contains either a 5 bit delta or a count of\n;\traw samples to dump out.\n\n\ttest\tal,00100000b\n\tje\tshort ??justraw\n\n;\tThe lower 5 bits are actually a signed delta.\n;\tSign extend the delta and add it to the stream.\n\n\tshl\tal,3\n\tsar\tal,3\n\tadd\tdl,al\n\tmov\t[edi],dl\n\tdec\tecx\n\tinc\tedi\n\tjmp\t??mainloop\n\n;\tThe lower 5 bits hold a count of the number of raw\n;\tsamples that follow this code. Dump these samples to\n;\tthe output buffer.\n\n??justraw:\n\tmov\tebx,ecx\n\txor\tah,ah\n\tinc\tal\n\tmov\tecx,eax\n\tshr\tecx,1\n\trep\tmovsw\n\tadc\tecx,ecx\n\trep\tmovsb\n\tmov\tecx,ebx\n\tadd\t[incount],eax\n\tsub\tecx,eax\n\tdec\tedi\n\tmov\tdl,[edi]\t;Set \"previous\" value.\n\tinc\tedi\n\tjmp\t??mainloop\n\n;\tCheck to see if this is a 4 bit delta code sequence.\n\n??try4bit:\n\tinc\tal\t;Following codes use AL+1\n\tcmp\tah,CODE_4BIT\n\tjne\tshort ??try2bit\n\n;\tA sequence of 4bit deltas follow. AL equals the\n;\tnumber of nibble packed delta bytes to process.\n\n??bit4loop:\n\tmov\tah,[esi]\t;Fetch nibble packed delta codes\n\tmov\tbl,ah\n\tinc\t[incount]\n\tinc\tesi\n\n;\tAdd first delta to 'previous' sample already in DL.\n\n\tand\tebx,00001111b\n\tadd\tdl,[_4bitdecode+ebx]\n\tpushfd\n\tcmp\t[_4bitdecode+ebx],0\n\tjl\tshort ??neg1\n\n\tpopfd\n\tjnc\tshort ??ok1\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok1\n\n??neg1:\n\tpopfd\n\tjc\tshort ??ok1\n\n\txor\tdl,dl\n\n??ok1:\n\tmov\tdh,dl\t;DH now holds new 'previous' sample.\n\tmov\tbl,ah\n\tshr\tbl,4\n\tadd\tdh,[_4bitdecode+ebx]\n\tpushfd\n\tcmp\t[_4bitdecode+ebx],0\n\tjl\tshort ??neg2\n\n\tpopfd\n\tjnc\tshort ??ok2\n\n\tmov\tdh,0FFh\n\tjmp\tshort ??ok2\n\n??neg2:\n\tpopfd\n\tjc\tshort ??ok2\n\n\txor\tdh,dh\n\n??ok2:\n\tmov\t[edi],dx\t;Output the two sample bytes\n\tsub\tecx,2\n\tadd\tedi,2\n\n;\tPut the correct 'previous' sample in DL where it belongs.\n\n\tmov\tdl,dh\n\n;\tIf there are more deltas to process then loop back.\n\n\tdec\tal\n\tjnz\tshort ??bit4loop\n\tjmp\t??mainloop\n\n;\tCheck to see if 2 bit deltas need to be processed.\n\n??try2bit:\n\tcmp\tah,CODE_2BIT\n\tjne\t??zerodelta\n\n;\tA sequence of 2bit deltas follow.  AL equals the number of\n;\tpacked delta bytes to process.\n\n??bit2loop:\n\tmov\tah,[esi]\t;Fetch packed delat codes\n\tinc\t[incount]\n\tinc\tesi\n\n;\tAdd first delta to 'previous' sample already in DL.\n\n\tmov\tbl,ah\n\tand\tebx,000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushfd\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg3\n\n\tpopfd\n\tjnc\tshort ??ok3\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok3\n\n??neg3:\n\tpopfd\n\tjc\tshort ??ok3\n\txor\tdl,dl\n\n??ok3:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,2\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushfd\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg4\n\n\tpopfd\n\tjnc\tshort ??ok4\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok4\n\n??neg4:\n\tpopfd\n\tjc\tshort ??ok4\n\n\txor\tdl,dl\n\n??ok4:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,4\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushfd\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg5\n\n\tpopfd\n\tjnc\tshort ??ok5\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok5\n\n??neg5:\n\tpopfd\n\tjc\tshort ??ok5\n\n\txor\tdl,dl\n\n??ok5:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,6\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushfd\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg6\n\n\tpopfd\n\tjnc\tshort ??ok6\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok6\n\n??neg6:\n\tpopfd\n\tjc\tshort ??ok6\n\n\txor\tdl,dl\n\n??ok6:\n\tror\tedx,8\n\tmov\t[edi],edx\t;Output two sample bytes\n\tsub\tecx,4\n\tadd\tedi,4\n\n;\tPut the correct 'previous' sample in DL where it belongs.\n\n\trol\tedx,8\n\n;\tIf there are more deltas to process then loop back.\n\n\tdec\tal\n\tjnz\t??bit2loop\n\tjmp\t??mainloop\n\n;\tThere is a run of zero deltas.  Zero deltas merely duplicate\n;\tthe 'previous' sample the requested number of times.\n\n??zerodelta:\n\txor\tebx,ebx\n\tmov\tbl,al\n\tmov\tal,dl\n\tsub\tecx,ebx\n\txchg\tecx,ebx\n\trep\tstosb\n\tmov\tecx,ebx\n\tjmp\t??mainloop\n\n??fini:\n\tpopfd\n\tmov\teax,[incount]\n\tret\n\n\tENDP\tDecompress_Frame\n\nLABEL \tLockedCodeEnd\tBYTE\n\n\n\n\n\n\tEND"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/DIFFTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* dwDiffTable - ADPCM Lookup table for sample differences\n;****************************************************************************\n\n\t\talign\t4\n\ndwDiffTable\tDD\t0\t; Index = 0 Token = 0\n\t\tDD\t1\t; Index = 0 Token = 1\n\t\tDD\t3\t; Index = 0 Token = 2\n\t\tDD\t4\t; Index = 0 Token = 3\n\t\tDD\t7\t; Index = 0 Token = 4\n\t\tDD\t8\t; Index = 0 Token = 5\n\t\tDD\t10\t; Index = 0 Token = 6\n\t\tDD\t11\t; Index = 0 Token = 7\n\t\tDD\t0\t; Index = 0 Token = 8\n\t\tDD\t-1\t; Index = 0 Token = 9\n\t\tDD\t-3\t; Index = 0 Token = 10\n\t\tDD\t-4\t; Index = 0 Token = 11\n\t\tDD\t-7\t; Index = 0 Token = 12\n\t\tDD\t-8\t; Index = 0 Token = 13\n\t\tDD\t-10\t; Index = 0 Token = 14\n\t\tDD\t-11\t; Index = 0 Token = 15\n\t\tDD\t1\t; Index = 1 Token = 0\n\t\tDD\t3\t; Index = 1 Token = 1\n\t\tDD\t5\t; Index = 1 Token = 2\n\t\tDD\t7\t; Index = 1 Token = 3\n\t\tDD\t9\t; Index = 1 Token = 4\n\t\tDD\t11\t; Index = 1 Token = 5\n\t\tDD\t13\t; Index = 1 Token = 6\n\t\tDD\t15\t; Index = 1 Token = 7\n\t\tDD\t-1\t; Index = 1 Token = 8\n\t\tDD\t-3\t; Index = 1 Token = 9\n\t\tDD\t-5\t; Index = 1 Token = 10\n\t\tDD\t-7\t; Index = 1 Token = 11\n\t\tDD\t-9\t; Index = 1 Token = 12\n\t\tDD\t-11\t; Index = 1 Token = 13\n\t\tDD\t-13\t; Index = 1 Token = 14\n\t\tDD\t-15\t; Index = 1 Token = 15\n\t\tDD\t1\t; Index = 2 Token = 0\n\t\tDD\t3\t; Index = 2 Token = 1\n\t\tDD\t5\t; Index = 2 Token = 2\n\t\tDD\t7\t; Index = 2 Token = 3\n\t\tDD\t10\t; Index = 2 Token = 4\n\t\tDD\t12\t; Index = 2 Token = 5\n\t\tDD\t14\t; Index = 2 Token = 6\n\t\tDD\t16\t; Index = 2 Token = 7\n\t\tDD\t-1\t; Index = 2 Token = 8\n\t\tDD\t-3\t; Index = 2 Token = 9\n\t\tDD\t-5\t; Index = 2 Token = 10\n\t\tDD\t-7\t; Index = 2 Token = 11\n\t\tDD\t-10\t; Index = 2 Token = 12\n\t\tDD\t-12\t; Index = 2 Token = 13\n\t\tDD\t-14\t; Index = 2 Token = 14\n\t\tDD\t-16\t; Index = 2 Token = 15\n\t\tDD\t1\t; Index = 3 Token = 0\n\t\tDD\t3\t; Index = 3 Token = 1\n\t\tDD\t6\t; Index = 3 Token = 2\n\t\tDD\t8\t; Index = 3 Token = 3\n\t\tDD\t11\t; Index = 3 Token = 4\n\t\tDD\t13\t; Index = 3 Token = 5\n\t\tDD\t16\t; Index = 3 Token = 6\n\t\tDD\t18\t; Index = 3 Token = 7\n\t\tDD\t-1\t; Index = 3 Token = 8\n\t\tDD\t-3\t; Index = 3 Token = 9\n\t\tDD\t-6\t; Index = 3 Token = 10\n\t\tDD\t-8\t; Index = 3 Token = 11\n\t\tDD\t-11\t; Index = 3 Token = 12\n\t\tDD\t-13\t; Index = 3 Token = 13\n\t\tDD\t-16\t; Index = 3 Token = 14\n\t\tDD\t-18\t; Index = 3 Token = 15\n\t\tDD\t1\t; Index = 4 Token = 0\n\t\tDD\t3\t; Index = 4 Token = 1\n\t\tDD\t6\t; Index = 4 Token = 2\n\t\tDD\t8\t; Index = 4 Token = 3\n\t\tDD\t12\t; Index = 4 Token = 4\n\t\tDD\t14\t; Index = 4 Token = 5\n\t\tDD\t17\t; Index = 4 Token = 6\n\t\tDD\t19\t; Index = 4 Token = 7\n\t\tDD\t-1\t; Index = 4 Token = 8\n\t\tDD\t-3\t; Index = 4 Token = 9\n\t\tDD\t-6\t; Index = 4 Token = 10\n\t\tDD\t-8\t; Index = 4 Token = 11\n\t\tDD\t-12\t; Index = 4 Token = 12\n\t\tDD\t-14\t; Index = 4 Token = 13\n\t\tDD\t-17\t; Index = 4 Token = 14\n\t\tDD\t-19\t; Index = 4 Token = 15\n\t\tDD\t1\t; Index = 5 Token = 0\n\t\tDD\t4\t; Index = 5 Token = 1\n\t\tDD\t7\t; Index = 5 Token = 2\n\t\tDD\t10\t; Index = 5 Token = 3\n\t\tDD\t13\t; Index = 5 Token = 4\n\t\tDD\t16\t; Index = 5 Token = 5\n\t\tDD\t19\t; Index = 5 Token = 6\n\t\tDD\t22\t; Index = 5 Token = 7\n\t\tDD\t-1\t; Index = 5 Token = 8\n\t\tDD\t-4\t; Index = 5 Token = 9\n\t\tDD\t-7\t; Index = 5 Token = 10\n\t\tDD\t-10\t; Index = 5 Token = 11\n\t\tDD\t-13\t; Index = 5 Token = 12\n\t\tDD\t-16\t; Index = 5 Token = 13\n\t\tDD\t-19\t; Index = 5 Token = 14\n\t\tDD\t-22\t; Index = 5 Token = 15\n\t\tDD\t1\t; Index = 6 Token = 0\n\t\tDD\t4\t; Index = 6 Token = 1\n\t\tDD\t7\t; Index = 6 Token = 2\n\t\tDD\t10\t; Index = 6 Token = 3\n\t\tDD\t14\t; Index = 6 Token = 4\n\t\tDD\t17\t; Index = 6 Token = 5\n\t\tDD\t20\t; Index = 6 Token = 6\n\t\tDD\t23\t; Index = 6 Token = 7\n\t\tDD\t-1\t; Index = 6 Token = 8\n\t\tDD\t-4\t; Index = 6 Token = 9\n\t\tDD\t-7\t; Index = 6 Token = 10\n\t\tDD\t-10\t; Index = 6 Token = 11\n\t\tDD\t-14\t; Index = 6 Token = 12\n\t\tDD\t-17\t; Index = 6 Token = 13\n\t\tDD\t-20\t; Index = 6 Token = 14\n\t\tDD\t-23\t; Index = 6 Token = 15\n\t\tDD\t1\t; Index = 7 Token = 0\n\t\tDD\t4\t; Index = 7 Token = 1\n\t\tDD\t8\t; Index = 7 Token = 2\n\t\tDD\t11\t; Index = 7 Token = 3\n\t\tDD\t15\t; Index = 7 Token = 4\n\t\tDD\t18\t; Index = 7 Token = 5\n\t\tDD\t22\t; Index = 7 Token = 6\n\t\tDD\t25\t; Index = 7 Token = 7\n\t\tDD\t-1\t; Index = 7 Token = 8\n\t\tDD\t-4\t; Index = 7 Token = 9\n\t\tDD\t-8\t; Index = 7 Token = 10\n\t\tDD\t-11\t; Index = 7 Token = 11\n\t\tDD\t-15\t; Index = 7 Token = 12\n\t\tDD\t-18\t; Index = 7 Token = 13\n\t\tDD\t-22\t; Index = 7 Token = 14\n\t\tDD\t-25\t; Index = 7 Token = 15\n\t\tDD\t2\t; Index = 8 Token = 0\n\t\tDD\t6\t; Index = 8 Token = 1\n\t\tDD\t10\t; Index = 8 Token = 2\n\t\tDD\t14\t; Index = 8 Token = 3\n\t\tDD\t18\t; Index = 8 Token = 4\n\t\tDD\t22\t; Index = 8 Token = 5\n\t\tDD\t26\t; Index = 8 Token = 6\n\t\tDD\t30\t; Index = 8 Token = 7\n\t\tDD\t-2\t; Index = 8 Token = 8\n\t\tDD\t-6\t; Index = 8 Token = 9\n\t\tDD\t-10\t; Index = 8 Token = 10\n\t\tDD\t-14\t; Index = 8 Token = 11\n\t\tDD\t-18\t; Index = 8 Token = 12\n\t\tDD\t-22\t; Index = 8 Token = 13\n\t\tDD\t-26\t; Index = 8 Token = 14\n\t\tDD\t-30\t; Index = 8 Token = 15\n\t\tDD\t2\t; Index = 9 Token = 0\n\t\tDD\t6\t; Index = 9 Token = 1\n\t\tDD\t10\t; Index = 9 Token = 2\n\t\tDD\t14\t; Index = 9 Token = 3\n\t\tDD\t19\t; Index = 9 Token = 4\n\t\tDD\t23\t; Index = 9 Token = 5\n\t\tDD\t27\t; Index = 9 Token = 6\n\t\tDD\t31\t; Index = 9 Token = 7\n\t\tDD\t-2\t; Index = 9 Token = 8\n\t\tDD\t-6\t; Index = 9 Token = 9\n\t\tDD\t-10\t; Index = 9 Token = 10\n\t\tDD\t-14\t; Index = 9 Token = 11\n\t\tDD\t-19\t; Index = 9 Token = 12\n\t\tDD\t-23\t; Index = 9 Token = 13\n\t\tDD\t-27\t; Index = 9 Token = 14\n\t\tDD\t-31\t; Index = 9 Token = 15\n\t\tDD\t2\t; Index = 10 Token = 0\n\t\tDD\t6\t; Index = 10 Token = 1\n\t\tDD\t11\t; Index = 10 Token = 2\n\t\tDD\t15\t; Index = 10 Token = 3\n\t\tDD\t21\t; Index = 10 Token = 4\n\t\tDD\t25\t; Index = 10 Token = 5\n\t\tDD\t30\t; Index = 10 Token = 6\n\t\tDD\t34\t; Index = 10 Token = 7\n\t\tDD\t-2\t; Index = 10 Token = 8\n\t\tDD\t-6\t; Index = 10 Token = 9\n\t\tDD\t-11\t; Index = 10 Token = 10\n\t\tDD\t-15\t; Index = 10 Token = 11\n\t\tDD\t-21\t; Index = 10 Token = 12\n\t\tDD\t-25\t; Index = 10 Token = 13\n\t\tDD\t-30\t; Index = 10 Token = 14\n\t\tDD\t-34\t; Index = 10 Token = 15\n\t\tDD\t2\t; Index = 11 Token = 0\n\t\tDD\t7\t; Index = 11 Token = 1\n\t\tDD\t12\t; Index = 11 Token = 2\n\t\tDD\t17\t; Index = 11 Token = 3\n\t\tDD\t23\t; Index = 11 Token = 4\n\t\tDD\t28\t; Index = 11 Token = 5\n\t\tDD\t33\t; Index = 11 Token = 6\n\t\tDD\t38\t; Index = 11 Token = 7\n\t\tDD\t-2\t; Index = 11 Token = 8\n\t\tDD\t-7\t; Index = 11 Token = 9\n\t\tDD\t-12\t; Index = 11 Token = 10\n\t\tDD\t-17\t; Index = 11 Token = 11\n\t\tDD\t-23\t; Index = 11 Token = 12\n\t\tDD\t-28\t; Index = 11 Token = 13\n\t\tDD\t-33\t; Index = 11 Token = 14\n\t\tDD\t-38\t; Index = 11 Token = 15\n\t\tDD\t2\t; Index = 12 Token = 0\n\t\tDD\t7\t; Index = 12 Token = 1\n\t\tDD\t13\t; Index = 12 Token = 2\n\t\tDD\t18\t; Index = 12 Token = 3\n\t\tDD\t25\t; Index = 12 Token = 4\n\t\tDD\t30\t; Index = 12 Token = 5\n\t\tDD\t36\t; Index = 12 Token = 6\n\t\tDD\t41\t; Index = 12 Token = 7\n\t\tDD\t-2\t; Index = 12 Token = 8\n\t\tDD\t-7\t; Index = 12 Token = 9\n\t\tDD\t-13\t; Index = 12 Token = 10\n\t\tDD\t-18\t; Index = 12 Token = 11\n\t\tDD\t-25\t; Index = 12 Token = 12\n\t\tDD\t-30\t; Index = 12 Token = 13\n\t\tDD\t-36\t; Index = 12 Token = 14\n\t\tDD\t-41\t; Index = 12 Token = 15\n\t\tDD\t3\t; Index = 13 Token = 0\n\t\tDD\t9\t; Index = 13 Token = 1\n\t\tDD\t15\t; Index = 13 Token = 2\n\t\tDD\t21\t; Index = 13 Token = 3\n\t\tDD\t28\t; Index = 13 Token = 4\n\t\tDD\t34\t; Index = 13 Token = 5\n\t\tDD\t40\t; Index = 13 Token = 6\n\t\tDD\t46\t; Index = 13 Token = 7\n\t\tDD\t-3\t; Index = 13 Token = 8\n\t\tDD\t-9\t; Index = 13 Token = 9\n\t\tDD\t-15\t; Index = 13 Token = 10\n\t\tDD\t-21\t; Index = 13 Token = 11\n\t\tDD\t-28\t; Index = 13 Token = 12\n\t\tDD\t-34\t; Index = 13 Token = 13\n\t\tDD\t-40\t; Index = 13 Token = 14\n\t\tDD\t-46\t; Index = 13 Token = 15\n\t\tDD\t3\t; Index = 14 Token = 0\n\t\tDD\t10\t; Index = 14 Token = 1\n\t\tDD\t17\t; Index = 14 Token = 2\n\t\tDD\t24\t; Index = 14 Token = 3\n\t\tDD\t31\t; Index = 14 Token = 4\n\t\tDD\t38\t; Index = 14 Token = 5\n\t\tDD\t45\t; Index = 14 Token = 6\n\t\tDD\t52\t; Index = 14 Token = 7\n\t\tDD\t-3\t; Index = 14 Token = 8\n\t\tDD\t-10\t; Index = 14 Token = 9\n\t\tDD\t-17\t; Index = 14 Token = 10\n\t\tDD\t-24\t; Index = 14 Token = 11\n\t\tDD\t-31\t; Index = 14 Token = 12\n\t\tDD\t-38\t; Index = 14 Token = 13\n\t\tDD\t-45\t; Index = 14 Token = 14\n\t\tDD\t-52\t; Index = 14 Token = 15\n\t\tDD\t3\t; Index = 15 Token = 0\n\t\tDD\t10\t; Index = 15 Token = 1\n\t\tDD\t18\t; Index = 15 Token = 2\n\t\tDD\t25\t; Index = 15 Token = 3\n\t\tDD\t34\t; Index = 15 Token = 4\n\t\tDD\t41\t; Index = 15 Token = 5\n\t\tDD\t49\t; Index = 15 Token = 6\n\t\tDD\t56\t; Index = 15 Token = 7\n\t\tDD\t-3\t; Index = 15 Token = 8\n\t\tDD\t-10\t; Index = 15 Token = 9\n\t\tDD\t-18\t; Index = 15 Token = 10\n\t\tDD\t-25\t; Index = 15 Token = 11\n\t\tDD\t-34\t; Index = 15 Token = 12\n\t\tDD\t-41\t; Index = 15 Token = 13\n\t\tDD\t-49\t; Index = 15 Token = 14\n\t\tDD\t-56\t; Index = 15 Token = 15\n\t\tDD\t4\t; Index = 16 Token = 0\n\t\tDD\t12\t; Index = 16 Token = 1\n\t\tDD\t21\t; Index = 16 Token = 2\n\t\tDD\t29\t; Index = 16 Token = 3\n\t\tDD\t38\t; Index = 16 Token = 4\n\t\tDD\t46\t; Index = 16 Token = 5\n\t\tDD\t55\t; Index = 16 Token = 6\n\t\tDD\t63\t; Index = 16 Token = 7\n\t\tDD\t-4\t; Index = 16 Token = 8\n\t\tDD\t-12\t; Index = 16 Token = 9\n\t\tDD\t-21\t; Index = 16 Token = 10\n\t\tDD\t-29\t; Index = 16 Token = 11\n\t\tDD\t-38\t; Index = 16 Token = 12\n\t\tDD\t-46\t; Index = 16 Token = 13\n\t\tDD\t-55\t; Index = 16 Token = 14\n\t\tDD\t-63\t; Index = 16 Token = 15\n\t\tDD\t4\t; Index = 17 Token = 0\n\t\tDD\t13\t; Index = 17 Token = 1\n\t\tDD\t22\t; Index = 17 Token = 2\n\t\tDD\t31\t; Index = 17 Token = 3\n\t\tDD\t41\t; Index = 17 Token = 4\n\t\tDD\t50\t; Index = 17 Token = 5\n\t\tDD\t59\t; Index = 17 Token = 6\n\t\tDD\t68\t; Index = 17 Token = 7\n\t\tDD\t-4\t; Index = 17 Token = 8\n\t\tDD\t-13\t; Index = 17 Token = 9\n\t\tDD\t-22\t; Index = 17 Token = 10\n\t\tDD\t-31\t; Index = 17 Token = 11\n\t\tDD\t-41\t; Index = 17 Token = 12\n\t\tDD\t-50\t; Index = 17 Token = 13\n\t\tDD\t-59\t; Index = 17 Token = 14\n\t\tDD\t-68\t; Index = 17 Token = 15\n\t\tDD\t5\t; Index = 18 Token = 0\n\t\tDD\t15\t; Index = 18 Token = 1\n\t\tDD\t25\t; Index = 18 Token = 2\n\t\tDD\t35\t; Index = 18 Token = 3\n\t\tDD\t46\t; Index = 18 Token = 4\n\t\tDD\t56\t; Index = 18 Token = 5\n\t\tDD\t66\t; Index = 18 Token = 6\n\t\tDD\t76\t; Index = 18 Token = 7\n\t\tDD\t-5\t; Index = 18 Token = 8\n\t\tDD\t-15\t; Index = 18 Token = 9\n\t\tDD\t-25\t; Index = 18 Token = 10\n\t\tDD\t-35\t; Index = 18 Token = 11\n\t\tDD\t-46\t; Index = 18 Token = 12\n\t\tDD\t-56\t; Index = 18 Token = 13\n\t\tDD\t-66\t; Index = 18 Token = 14\n\t\tDD\t-76\t; Index = 18 Token = 15\n\t\tDD\t5\t; Index = 19 Token = 0\n\t\tDD\t16\t; Index = 19 Token = 1\n\t\tDD\t27\t; Index = 19 Token = 2\n\t\tDD\t38\t; Index = 19 Token = 3\n\t\tDD\t50\t; Index = 19 Token = 4\n\t\tDD\t61\t; Index = 19 Token = 5\n\t\tDD\t72\t; Index = 19 Token = 6\n\t\tDD\t83\t; Index = 19 Token = 7\n\t\tDD\t-5\t; Index = 19 Token = 8\n\t\tDD\t-16\t; Index = 19 Token = 9\n\t\tDD\t-27\t; Index = 19 Token = 10\n\t\tDD\t-38\t; Index = 19 Token = 11\n\t\tDD\t-50\t; Index = 19 Token = 12\n\t\tDD\t-61\t; Index = 19 Token = 13\n\t\tDD\t-72\t; Index = 19 Token = 14\n\t\tDD\t-83\t; Index = 19 Token = 15\n\t\tDD\t6\t; Index = 20 Token = 0\n\t\tDD\t18\t; Index = 20 Token = 1\n\t\tDD\t31\t; Index = 20 Token = 2\n\t\tDD\t43\t; Index = 20 Token = 3\n\t\tDD\t56\t; Index = 20 Token = 4\n\t\tDD\t68\t; Index = 20 Token = 5\n\t\tDD\t81\t; Index = 20 Token = 6\n\t\tDD\t93\t; Index = 20 Token = 7\n\t\tDD\t-6\t; Index = 20 Token = 8\n\t\tDD\t-18\t; Index = 20 Token = 9\n\t\tDD\t-31\t; Index = 20 Token = 10\n\t\tDD\t-43\t; Index = 20 Token = 11\n\t\tDD\t-56\t; Index = 20 Token = 12\n\t\tDD\t-68\t; Index = 20 Token = 13\n\t\tDD\t-81\t; Index = 20 Token = 14\n\t\tDD\t-93\t; Index = 20 Token = 15\n\t\tDD\t6\t; Index = 21 Token = 0\n\t\tDD\t19\t; Index = 21 Token = 1\n\t\tDD\t33\t; Index = 21 Token = 2\n\t\tDD\t46\t; Index = 21 Token = 3\n\t\tDD\t61\t; Index = 21 Token = 4\n\t\tDD\t74\t; Index = 21 Token = 5\n\t\tDD\t88\t; Index = 21 Token = 6\n\t\tDD\t101\t; Index = 21 Token = 7\n\t\tDD\t-6\t; Index = 21 Token = 8\n\t\tDD\t-19\t; Index = 21 Token = 9\n\t\tDD\t-33\t; Index = 21 Token = 10\n\t\tDD\t-46\t; Index = 21 Token = 11\n\t\tDD\t-61\t; Index = 21 Token = 12\n\t\tDD\t-74\t; Index = 21 Token = 13\n\t\tDD\t-88\t; Index = 21 Token = 14\n\t\tDD\t-101\t; Index = 21 Token = 15\n\t\tDD\t7\t; Index = 22 Token = 0\n\t\tDD\t22\t; Index = 22 Token = 1\n\t\tDD\t37\t; Index = 22 Token = 2\n\t\tDD\t52\t; Index = 22 Token = 3\n\t\tDD\t67\t; Index = 22 Token = 4\n\t\tDD\t82\t; Index = 22 Token = 5\n\t\tDD\t97\t; Index = 22 Token = 6\n\t\tDD\t112\t; Index = 22 Token = 7\n\t\tDD\t-7\t; Index = 22 Token = 8\n\t\tDD\t-22\t; Index = 22 Token = 9\n\t\tDD\t-37\t; Index = 22 Token = 10\n\t\tDD\t-52\t; Index = 22 Token = 11\n\t\tDD\t-67\t; Index = 22 Token = 12\n\t\tDD\t-82\t; Index = 22 Token = 13\n\t\tDD\t-97\t; Index = 22 Token = 14\n\t\tDD\t-112\t; Index = 22 Token = 15\n\t\tDD\t8\t; Index = 23 Token = 0\n\t\tDD\t24\t; Index = 23 Token = 1\n\t\tDD\t41\t; Index = 23 Token = 2\n\t\tDD\t57\t; Index = 23 Token = 3\n\t\tDD\t74\t; Index = 23 Token = 4\n\t\tDD\t90\t; Index = 23 Token = 5\n\t\tDD\t107\t; Index = 23 Token = 6\n\t\tDD\t123\t; Index = 23 Token = 7\n\t\tDD\t-8\t; Index = 23 Token = 8\n\t\tDD\t-24\t; Index = 23 Token = 9\n\t\tDD\t-41\t; Index = 23 Token = 10\n\t\tDD\t-57\t; Index = 23 Token = 11\n\t\tDD\t-74\t; Index = 23 Token = 12\n\t\tDD\t-90\t; Index = 23 Token = 13\n\t\tDD\t-107\t; Index = 23 Token = 14\n\t\tDD\t-123\t; Index = 23 Token = 15\n\t\tDD\t9\t; Index = 24 Token = 0\n\t\tDD\t27\t; Index = 24 Token = 1\n\t\tDD\t45\t; Index = 24 Token = 2\n\t\tDD\t63\t; Index = 24 Token = 3\n\t\tDD\t82\t; Index = 24 Token = 4\n\t\tDD\t100\t; Index = 24 Token = 5\n\t\tDD\t118\t; Index = 24 Token = 6\n\t\tDD\t136\t; Index = 24 Token = 7\n\t\tDD\t-9\t; Index = 24 Token = 8\n\t\tDD\t-27\t; Index = 24 Token = 9\n\t\tDD\t-45\t; Index = 24 Token = 10\n\t\tDD\t-63\t; Index = 24 Token = 11\n\t\tDD\t-82\t; Index = 24 Token = 12\n\t\tDD\t-100\t; Index = 24 Token = 13\n\t\tDD\t-118\t; Index = 24 Token = 14\n\t\tDD\t-136\t; Index = 24 Token = 15\n\t\tDD\t10\t; Index = 25 Token = 0\n\t\tDD\t30\t; Index = 25 Token = 1\n\t\tDD\t50\t; Index = 25 Token = 2\n\t\tDD\t70\t; Index = 25 Token = 3\n\t\tDD\t90\t; Index = 25 Token = 4\n\t\tDD\t110\t; Index = 25 Token = 5\n\t\tDD\t130\t; Index = 25 Token = 6\n\t\tDD\t150\t; Index = 25 Token = 7\n\t\tDD\t-10\t; Index = 25 Token = 8\n\t\tDD\t-30\t; Index = 25 Token = 9\n\t\tDD\t-50\t; Index = 25 Token = 10\n\t\tDD\t-70\t; Index = 25 Token = 11\n\t\tDD\t-90\t; Index = 25 Token = 12\n\t\tDD\t-110\t; Index = 25 Token = 13\n\t\tDD\t-130\t; Index = 25 Token = 14\n\t\tDD\t-150\t; Index = 25 Token = 15\n\t\tDD\t11\t; Index = 26 Token = 0\n\t\tDD\t33\t; Index = 26 Token = 1\n\t\tDD\t55\t; Index = 26 Token = 2\n\t\tDD\t77\t; Index = 26 Token = 3\n\t\tDD\t99\t; Index = 26 Token = 4\n\t\tDD\t121\t; Index = 26 Token = 5\n\t\tDD\t143\t; Index = 26 Token = 6\n\t\tDD\t165\t; Index = 26 Token = 7\n\t\tDD\t-11\t; Index = 26 Token = 8\n\t\tDD\t-33\t; Index = 26 Token = 9\n\t\tDD\t-55\t; Index = 26 Token = 10\n\t\tDD\t-77\t; Index = 26 Token = 11\n\t\tDD\t-99\t; Index = 26 Token = 12\n\t\tDD\t-121\t; Index = 26 Token = 13\n\t\tDD\t-143\t; Index = 26 Token = 14\n\t\tDD\t-165\t; Index = 26 Token = 15\n\t\tDD\t12\t; Index = 27 Token = 0\n\t\tDD\t36\t; Index = 27 Token = 1\n\t\tDD\t60\t; Index = 27 Token = 2\n\t\tDD\t84\t; Index = 27 Token = 3\n\t\tDD\t109\t; Index = 27 Token = 4\n\t\tDD\t133\t; Index = 27 Token = 5\n\t\tDD\t157\t; Index = 27 Token = 6\n\t\tDD\t181\t; Index = 27 Token = 7\n\t\tDD\t-12\t; Index = 27 Token = 8\n\t\tDD\t-36\t; Index = 27 Token = 9\n\t\tDD\t-60\t; Index = 27 Token = 10\n\t\tDD\t-84\t; Index = 27 Token = 11\n\t\tDD\t-109\t; Index = 27 Token = 12\n\t\tDD\t-133\t; Index = 27 Token = 13\n\t\tDD\t-157\t; Index = 27 Token = 14\n\t\tDD\t-181\t; Index = 27 Token = 15\n\t\tDD\t13\t; Index = 28 Token = 0\n\t\tDD\t39\t; Index = 28 Token = 1\n\t\tDD\t66\t; Index = 28 Token = 2\n\t\tDD\t92\t; Index = 28 Token = 3\n\t\tDD\t120\t; Index = 28 Token = 4\n\t\tDD\t146\t; Index = 28 Token = 5\n\t\tDD\t173\t; Index = 28 Token = 6\n\t\tDD\t199\t; Index = 28 Token = 7\n\t\tDD\t-13\t; Index = 28 Token = 8\n\t\tDD\t-39\t; Index = 28 Token = 9\n\t\tDD\t-66\t; Index = 28 Token = 10\n\t\tDD\t-92\t; Index = 28 Token = 11\n\t\tDD\t-120\t; Index = 28 Token = 12\n\t\tDD\t-146\t; Index = 28 Token = 13\n\t\tDD\t-173\t; Index = 28 Token = 14\n\t\tDD\t-199\t; Index = 28 Token = 15\n\t\tDD\t14\t; Index = 29 Token = 0\n\t\tDD\t43\t; Index = 29 Token = 1\n\t\tDD\t73\t; Index = 29 Token = 2\n\t\tDD\t102\t; Index = 29 Token = 3\n\t\tDD\t132\t; Index = 29 Token = 4\n\t\tDD\t161\t; Index = 29 Token = 5\n\t\tDD\t191\t; Index = 29 Token = 6\n\t\tDD\t220\t; Index = 29 Token = 7\n\t\tDD\t-14\t; Index = 29 Token = 8\n\t\tDD\t-43\t; Index = 29 Token = 9\n\t\tDD\t-73\t; Index = 29 Token = 10\n\t\tDD\t-102\t; Index = 29 Token = 11\n\t\tDD\t-132\t; Index = 29 Token = 12\n\t\tDD\t-161\t; Index = 29 Token = 13\n\t\tDD\t-191\t; Index = 29 Token = 14\n\t\tDD\t-220\t; Index = 29 Token = 15\n\t\tDD\t16\t; Index = 30 Token = 0\n\t\tDD\t48\t; Index = 30 Token = 1\n\t\tDD\t81\t; Index = 30 Token = 2\n\t\tDD\t113\t; Index = 30 Token = 3\n\t\tDD\t146\t; Index = 30 Token = 4\n\t\tDD\t178\t; Index = 30 Token = 5\n\t\tDD\t211\t; Index = 30 Token = 6\n\t\tDD\t243\t; Index = 30 Token = 7\n\t\tDD\t-16\t; Index = 30 Token = 8\n\t\tDD\t-48\t; Index = 30 Token = 9\n\t\tDD\t-81\t; Index = 30 Token = 10\n\t\tDD\t-113\t; Index = 30 Token = 11\n\t\tDD\t-146\t; Index = 30 Token = 12\n\t\tDD\t-178\t; Index = 30 Token = 13\n\t\tDD\t-211\t; Index = 30 Token = 14\n\t\tDD\t-243\t; Index = 30 Token = 15\n\t\tDD\t17\t; Index = 31 Token = 0\n\t\tDD\t52\t; Index = 31 Token = 1\n\t\tDD\t88\t; Index = 31 Token = 2\n\t\tDD\t123\t; Index = 31 Token = 3\n\t\tDD\t160\t; Index = 31 Token = 4\n\t\tDD\t195\t; Index = 31 Token = 5\n\t\tDD\t231\t; Index = 31 Token = 6\n\t\tDD\t266\t; Index = 31 Token = 7\n\t\tDD\t-17\t; Index = 31 Token = 8\n\t\tDD\t-52\t; Index = 31 Token = 9\n\t\tDD\t-88\t; Index = 31 Token = 10\n\t\tDD\t-123\t; Index = 31 Token = 11\n\t\tDD\t-160\t; Index = 31 Token = 12\n\t\tDD\t-195\t; Index = 31 Token = 13\n\t\tDD\t-231\t; Index = 31 Token = 14\n\t\tDD\t-266\t; Index = 31 Token = 15\n\t\tDD\t19\t; Index = 32 Token = 0\n\t\tDD\t58\t; Index = 32 Token = 1\n\t\tDD\t97\t; Index = 32 Token = 2\n\t\tDD\t136\t; Index = 32 Token = 3\n\t\tDD\t176\t; Index = 32 Token = 4\n\t\tDD\t215\t; Index = 32 Token = 5\n\t\tDD\t254\t; Index = 32 Token = 6\n\t\tDD\t293\t; Index = 32 Token = 7\n\t\tDD\t-19\t; Index = 32 Token = 8\n\t\tDD\t-58\t; Index = 32 Token = 9\n\t\tDD\t-97\t; Index = 32 Token = 10\n\t\tDD\t-136\t; Index = 32 Token = 11\n\t\tDD\t-176\t; Index = 32 Token = 12\n\t\tDD\t-215\t; Index = 32 Token = 13\n\t\tDD\t-254\t; Index = 32 Token = 14\n\t\tDD\t-293\t; Index = 32 Token = 15\n\t\tDD\t21\t; Index = 33 Token = 0\n\t\tDD\t64\t; Index = 33 Token = 1\n\t\tDD\t107\t; Index = 33 Token = 2\n\t\tDD\t150\t; Index = 33 Token = 3\n\t\tDD\t194\t; Index = 33 Token = 4\n\t\tDD\t237\t; Index = 33 Token = 5\n\t\tDD\t280\t; Index = 33 Token = 6\n\t\tDD\t323\t; Index = 33 Token = 7\n\t\tDD\t-21\t; Index = 33 Token = 8\n\t\tDD\t-64\t; Index = 33 Token = 9\n\t\tDD\t-107\t; Index = 33 Token = 10\n\t\tDD\t-150\t; Index = 33 Token = 11\n\t\tDD\t-194\t; Index = 33 Token = 12\n\t\tDD\t-237\t; Index = 33 Token = 13\n\t\tDD\t-280\t; Index = 33 Token = 14\n\t\tDD\t-323\t; Index = 33 Token = 15\n\t\tDD\t23\t; Index = 34 Token = 0\n\t\tDD\t70\t; Index = 34 Token = 1\n\t\tDD\t118\t; Index = 34 Token = 2\n\t\tDD\t165\t; Index = 34 Token = 3\n\t\tDD\t213\t; Index = 34 Token = 4\n\t\tDD\t260\t; Index = 34 Token = 5\n\t\tDD\t308\t; Index = 34 Token = 6\n\t\tDD\t355\t; Index = 34 Token = 7\n\t\tDD\t-23\t; Index = 34 Token = 8\n\t\tDD\t-70\t; Index = 34 Token = 9\n\t\tDD\t-118\t; Index = 34 Token = 10\n\t\tDD\t-165\t; Index = 34 Token = 11\n\t\tDD\t-213\t; Index = 34 Token = 12\n\t\tDD\t-260\t; Index = 34 Token = 13\n\t\tDD\t-308\t; Index = 34 Token = 14\n\t\tDD\t-355\t; Index = 34 Token = 15\n\t\tDD\t26\t; Index = 35 Token = 0\n\t\tDD\t78\t; Index = 35 Token = 1\n\t\tDD\t130\t; Index = 35 Token = 2\n\t\tDD\t182\t; Index = 35 Token = 3\n\t\tDD\t235\t; Index = 35 Token = 4\n\t\tDD\t287\t; Index = 35 Token = 5\n\t\tDD\t339\t; Index = 35 Token = 6\n\t\tDD\t391\t; Index = 35 Token = 7\n\t\tDD\t-26\t; Index = 35 Token = 8\n\t\tDD\t-78\t; Index = 35 Token = 9\n\t\tDD\t-130\t; Index = 35 Token = 10\n\t\tDD\t-182\t; Index = 35 Token = 11\n\t\tDD\t-235\t; Index = 35 Token = 12\n\t\tDD\t-287\t; Index = 35 Token = 13\n\t\tDD\t-339\t; Index = 35 Token = 14\n\t\tDD\t-391\t; Index = 35 Token = 15\n\t\tDD\t28\t; Index = 36 Token = 0\n\t\tDD\t85\t; Index = 36 Token = 1\n\t\tDD\t143\t; Index = 36 Token = 2\n\t\tDD\t200\t; Index = 36 Token = 3\n\t\tDD\t258\t; Index = 36 Token = 4\n\t\tDD\t315\t; Index = 36 Token = 5\n\t\tDD\t373\t; Index = 36 Token = 6\n\t\tDD\t430\t; Index = 36 Token = 7\n\t\tDD\t-28\t; Index = 36 Token = 8\n\t\tDD\t-85\t; Index = 36 Token = 9\n\t\tDD\t-143\t; Index = 36 Token = 10\n\t\tDD\t-200\t; Index = 36 Token = 11\n\t\tDD\t-258\t; Index = 36 Token = 12\n\t\tDD\t-315\t; Index = 36 Token = 13\n\t\tDD\t-373\t; Index = 36 Token = 14\n\t\tDD\t-430\t; Index = 36 Token = 15\n\t\tDD\t31\t; Index = 37 Token = 0\n\t\tDD\t94\t; Index = 37 Token = 1\n\t\tDD\t157\t; Index = 37 Token = 2\n\t\tDD\t220\t; Index = 37 Token = 3\n\t\tDD\t284\t; Index = 37 Token = 4\n\t\tDD\t347\t; Index = 37 Token = 5\n\t\tDD\t410\t; Index = 37 Token = 6\n\t\tDD\t473\t; Index = 37 Token = 7\n\t\tDD\t-31\t; Index = 37 Token = 8\n\t\tDD\t-94\t; Index = 37 Token = 9\n\t\tDD\t-157\t; Index = 37 Token = 10\n\t\tDD\t-220\t; Index = 37 Token = 11\n\t\tDD\t-284\t; Index = 37 Token = 12\n\t\tDD\t-347\t; Index = 37 Token = 13\n\t\tDD\t-410\t; Index = 37 Token = 14\n\t\tDD\t-473\t; Index = 37 Token = 15\n\t\tDD\t34\t; Index = 38 Token = 0\n\t\tDD\t103\t; Index = 38 Token = 1\n\t\tDD\t173\t; Index = 38 Token = 2\n\t\tDD\t242\t; Index = 38 Token = 3\n\t\tDD\t313\t; Index = 38 Token = 4\n\t\tDD\t382\t; Index = 38 Token = 5\n\t\tDD\t452\t; Index = 38 Token = 6\n\t\tDD\t521\t; Index = 38 Token = 7\n\t\tDD\t-34\t; Index = 38 Token = 8\n\t\tDD\t-103\t; Index = 38 Token = 9\n\t\tDD\t-173\t; Index = 38 Token = 10\n\t\tDD\t-242\t; Index = 38 Token = 11\n\t\tDD\t-313\t; Index = 38 Token = 12\n\t\tDD\t-382\t; Index = 38 Token = 13\n\t\tDD\t-452\t; Index = 38 Token = 14\n\t\tDD\t-521\t; Index = 38 Token = 15\n\t\tDD\t38\t; Index = 39 Token = 0\n\t\tDD\t114\t; Index = 39 Token = 1\n\t\tDD\t191\t; Index = 39 Token = 2\n\t\tDD\t267\t; Index = 39 Token = 3\n\t\tDD\t345\t; Index = 39 Token = 4\n\t\tDD\t421\t; Index = 39 Token = 5\n\t\tDD\t498\t; Index = 39 Token = 6\n\t\tDD\t574\t; Index = 39 Token = 7\n\t\tDD\t-38\t; Index = 39 Token = 8\n\t\tDD\t-114\t; Index = 39 Token = 9\n\t\tDD\t-191\t; Index = 39 Token = 10\n\t\tDD\t-267\t; Index = 39 Token = 11\n\t\tDD\t-345\t; Index = 39 Token = 12\n\t\tDD\t-421\t; Index = 39 Token = 13\n\t\tDD\t-498\t; Index = 39 Token = 14\n\t\tDD\t-574\t; Index = 39 Token = 15\n\t\tDD\t42\t; Index = 40 Token = 0\n\t\tDD\t126\t; Index = 40 Token = 1\n\t\tDD\t210\t; Index = 40 Token = 2\n\t\tDD\t294\t; Index = 40 Token = 3\n\t\tDD\t379\t; Index = 40 Token = 4\n\t\tDD\t463\t; Index = 40 Token = 5\n\t\tDD\t547\t; Index = 40 Token = 6\n\t\tDD\t631\t; Index = 40 Token = 7\n\t\tDD\t-42\t; Index = 40 Token = 8\n\t\tDD\t-126\t; Index = 40 Token = 9\n\t\tDD\t-210\t; Index = 40 Token = 10\n\t\tDD\t-294\t; Index = 40 Token = 11\n\t\tDD\t-379\t; Index = 40 Token = 12\n\t\tDD\t-463\t; Index = 40 Token = 13\n\t\tDD\t-547\t; Index = 40 Token = 14\n\t\tDD\t-631\t; Index = 40 Token = 15\n\t\tDD\t46\t; Index = 41 Token = 0\n\t\tDD\t138\t; Index = 41 Token = 1\n\t\tDD\t231\t; Index = 41 Token = 2\n\t\tDD\t323\t; Index = 41 Token = 3\n\t\tDD\t417\t; Index = 41 Token = 4\n\t\tDD\t509\t; Index = 41 Token = 5\n\t\tDD\t602\t; Index = 41 Token = 6\n\t\tDD\t694\t; Index = 41 Token = 7\n\t\tDD\t-46\t; Index = 41 Token = 8\n\t\tDD\t-138\t; Index = 41 Token = 9\n\t\tDD\t-231\t; Index = 41 Token = 10\n\t\tDD\t-323\t; Index = 41 Token = 11\n\t\tDD\t-417\t; Index = 41 Token = 12\n\t\tDD\t-509\t; Index = 41 Token = 13\n\t\tDD\t-602\t; Index = 41 Token = 14\n\t\tDD\t-694\t; Index = 41 Token = 15\n\t\tDD\t51\t; Index = 42 Token = 0\n\t\tDD\t153\t; Index = 42 Token = 1\n\t\tDD\t255\t; Index = 42 Token = 2\n\t\tDD\t357\t; Index = 42 Token = 3\n\t\tDD\t459\t; Index = 42 Token = 4\n\t\tDD\t561\t; Index = 42 Token = 5\n\t\tDD\t663\t; Index = 42 Token = 6\n\t\tDD\t765\t; Index = 42 Token = 7\n\t\tDD\t-51\t; Index = 42 Token = 8\n\t\tDD\t-153\t; Index = 42 Token = 9\n\t\tDD\t-255\t; Index = 42 Token = 10\n\t\tDD\t-357\t; Index = 42 Token = 11\n\t\tDD\t-459\t; Index = 42 Token = 12\n\t\tDD\t-561\t; Index = 42 Token = 13\n\t\tDD\t-663\t; Index = 42 Token = 14\n\t\tDD\t-765\t; Index = 42 Token = 15\n\t\tDD\t56\t; Index = 43 Token = 0\n\t\tDD\t168\t; Index = 43 Token = 1\n\t\tDD\t280\t; Index = 43 Token = 2\n\t\tDD\t392\t; Index = 43 Token = 3\n\t\tDD\t505\t; Index = 43 Token = 4\n\t\tDD\t617\t; Index = 43 Token = 5\n\t\tDD\t729\t; Index = 43 Token = 6\n\t\tDD\t841\t; Index = 43 Token = 7\n\t\tDD\t-56\t; Index = 43 Token = 8\n\t\tDD\t-168\t; Index = 43 Token = 9\n\t\tDD\t-280\t; Index = 43 Token = 10\n\t\tDD\t-392\t; Index = 43 Token = 11\n\t\tDD\t-505\t; Index = 43 Token = 12\n\t\tDD\t-617\t; Index = 43 Token = 13\n\t\tDD\t-729\t; Index = 43 Token = 14\n\t\tDD\t-841\t; Index = 43 Token = 15\n\t\tDD\t61\t; Index = 44 Token = 0\n\t\tDD\t184\t; Index = 44 Token = 1\n\t\tDD\t308\t; Index = 44 Token = 2\n\t\tDD\t431\t; Index = 44 Token = 3\n\t\tDD\t555\t; Index = 44 Token = 4\n\t\tDD\t678\t; Index = 44 Token = 5\n\t\tDD\t802\t; Index = 44 Token = 6\n\t\tDD\t925\t; Index = 44 Token = 7\n\t\tDD\t-61\t; Index = 44 Token = 8\n\t\tDD\t-184\t; Index = 44 Token = 9\n\t\tDD\t-308\t; Index = 44 Token = 10\n\t\tDD\t-431\t; Index = 44 Token = 11\n\t\tDD\t-555\t; Index = 44 Token = 12\n\t\tDD\t-678\t; Index = 44 Token = 13\n\t\tDD\t-802\t; Index = 44 Token = 14\n\t\tDD\t-925\t; Index = 44 Token = 15\n\t\tDD\t68\t; Index = 45 Token = 0\n\t\tDD\t204\t; Index = 45 Token = 1\n\t\tDD\t340\t; Index = 45 Token = 2\n\t\tDD\t476\t; Index = 45 Token = 3\n\t\tDD\t612\t; Index = 45 Token = 4\n\t\tDD\t748\t; Index = 45 Token = 5\n\t\tDD\t884\t; Index = 45 Token = 6\n\t\tDD\t1020\t; Index = 45 Token = 7\n\t\tDD\t-68\t; Index = 45 Token = 8\n\t\tDD\t-204\t; Index = 45 Token = 9\n\t\tDD\t-340\t; Index = 45 Token = 10\n\t\tDD\t-476\t; Index = 45 Token = 11\n\t\tDD\t-612\t; Index = 45 Token = 12\n\t\tDD\t-748\t; Index = 45 Token = 13\n\t\tDD\t-884\t; Index = 45 Token = 14\n\t\tDD\t-1020\t; Index = 45 Token = 15\n\t\tDD\t74\t; Index = 46 Token = 0\n\t\tDD\t223\t; Index = 46 Token = 1\n\t\tDD\t373\t; Index = 46 Token = 2\n\t\tDD\t522\t; Index = 46 Token = 3\n\t\tDD\t672\t; Index = 46 Token = 4\n\t\tDD\t821\t; Index = 46 Token = 5\n\t\tDD\t971\t; Index = 46 Token = 6\n\t\tDD\t1120\t; Index = 46 Token = 7\n\t\tDD\t-74\t; Index = 46 Token = 8\n\t\tDD\t-223\t; Index = 46 Token = 9\n\t\tDD\t-373\t; Index = 46 Token = 10\n\t\tDD\t-522\t; Index = 46 Token = 11\n\t\tDD\t-672\t; Index = 46 Token = 12\n\t\tDD\t-821\t; Index = 46 Token = 13\n\t\tDD\t-971\t; Index = 46 Token = 14\n\t\tDD\t-1120\t; Index = 46 Token = 15\n\t\tDD\t82\t; Index = 47 Token = 0\n\t\tDD\t246\t; Index = 47 Token = 1\n\t\tDD\t411\t; Index = 47 Token = 2\n\t\tDD\t575\t; Index = 47 Token = 3\n\t\tDD\t740\t; Index = 47 Token = 4\n\t\tDD\t904\t; Index = 47 Token = 5\n\t\tDD\t1069\t; Index = 47 Token = 6\n\t\tDD\t1233\t; Index = 47 Token = 7\n\t\tDD\t-82\t; Index = 47 Token = 8\n\t\tDD\t-246\t; Index = 47 Token = 9\n\t\tDD\t-411\t; Index = 47 Token = 10\n\t\tDD\t-575\t; Index = 47 Token = 11\n\t\tDD\t-740\t; Index = 47 Token = 12\n\t\tDD\t-904\t; Index = 47 Token = 13\n\t\tDD\t-1069\t; Index = 47 Token = 14\n\t\tDD\t-1233\t; Index = 47 Token = 15\n\t\tDD\t90\t; Index = 48 Token = 0\n\t\tDD\t271\t; Index = 48 Token = 1\n\t\tDD\t452\t; Index = 48 Token = 2\n\t\tDD\t633\t; Index = 48 Token = 3\n\t\tDD\t814\t; Index = 48 Token = 4\n\t\tDD\t995\t; Index = 48 Token = 5\n\t\tDD\t1176\t; Index = 48 Token = 6\n\t\tDD\t1357\t; Index = 48 Token = 7\n\t\tDD\t-90\t; Index = 48 Token = 8\n\t\tDD\t-271\t; Index = 48 Token = 9\n\t\tDD\t-452\t; Index = 48 Token = 10\n\t\tDD\t-633\t; Index = 48 Token = 11\n\t\tDD\t-814\t; Index = 48 Token = 12\n\t\tDD\t-995\t; Index = 48 Token = 13\n\t\tDD\t-1176\t; Index = 48 Token = 14\n\t\tDD\t-1357\t; Index = 48 Token = 15\n\t\tDD\t99\t; Index = 49 Token = 0\n\t\tDD\t298\t; Index = 49 Token = 1\n\t\tDD\t497\t; Index = 49 Token = 2\n\t\tDD\t696\t; Index = 49 Token = 3\n\t\tDD\t895\t; Index = 49 Token = 4\n\t\tDD\t1094\t; Index = 49 Token = 5\n\t\tDD\t1293\t; Index = 49 Token = 6\n\t\tDD\t1492\t; Index = 49 Token = 7\n\t\tDD\t-99\t; Index = 49 Token = 8\n\t\tDD\t-298\t; Index = 49 Token = 9\n\t\tDD\t-497\t; Index = 49 Token = 10\n\t\tDD\t-696\t; Index = 49 Token = 11\n\t\tDD\t-895\t; Index = 49 Token = 12\n\t\tDD\t-1094\t; Index = 49 Token = 13\n\t\tDD\t-1293\t; Index = 49 Token = 14\n\t\tDD\t-1492\t; Index = 49 Token = 15\n\t\tDD\t109\t; Index = 50 Token = 0\n\t\tDD\t328\t; Index = 50 Token = 1\n\t\tDD\t547\t; Index = 50 Token = 2\n\t\tDD\t766\t; Index = 50 Token = 3\n\t\tDD\t985\t; Index = 50 Token = 4\n\t\tDD\t1204\t; Index = 50 Token = 5\n\t\tDD\t1423\t; Index = 50 Token = 6\n\t\tDD\t1642\t; Index = 50 Token = 7\n\t\tDD\t-109\t; Index = 50 Token = 8\n\t\tDD\t-328\t; Index = 50 Token = 9\n\t\tDD\t-547\t; Index = 50 Token = 10\n\t\tDD\t-766\t; Index = 50 Token = 11\n\t\tDD\t-985\t; Index = 50 Token = 12\n\t\tDD\t-1204\t; Index = 50 Token = 13\n\t\tDD\t-1423\t; Index = 50 Token = 14\n\t\tDD\t-1642\t; Index = 50 Token = 15\n\t\tDD\t120\t; Index = 51 Token = 0\n\t\tDD\t360\t; Index = 51 Token = 1\n\t\tDD\t601\t; Index = 51 Token = 2\n\t\tDD\t841\t; Index = 51 Token = 3\n\t\tDD\t1083\t; Index = 51 Token = 4\n\t\tDD\t1323\t; Index = 51 Token = 5\n\t\tDD\t1564\t; Index = 51 Token = 6\n\t\tDD\t1804\t; Index = 51 Token = 7\n\t\tDD\t-120\t; Index = 51 Token = 8\n\t\tDD\t-360\t; Index = 51 Token = 9\n\t\tDD\t-601\t; Index = 51 Token = 10\n\t\tDD\t-841\t; Index = 51 Token = 11\n\t\tDD\t-1083\t; Index = 51 Token = 12\n\t\tDD\t-1323\t; Index = 51 Token = 13\n\t\tDD\t-1564\t; Index = 51 Token = 14\n\t\tDD\t-1804\t; Index = 51 Token = 15\n\t\tDD\t132\t; Index = 52 Token = 0\n\t\tDD\t397\t; Index = 52 Token = 1\n\t\tDD\t662\t; Index = 52 Token = 2\n\t\tDD\t927\t; Index = 52 Token = 3\n\t\tDD\t1192\t; Index = 52 Token = 4\n\t\tDD\t1457\t; Index = 52 Token = 5\n\t\tDD\t1722\t; Index = 52 Token = 6\n\t\tDD\t1987\t; Index = 52 Token = 7\n\t\tDD\t-132\t; Index = 52 Token = 8\n\t\tDD\t-397\t; Index = 52 Token = 9\n\t\tDD\t-662\t; Index = 52 Token = 10\n\t\tDD\t-927\t; Index = 52 Token = 11\n\t\tDD\t-1192\t; Index = 52 Token = 12\n\t\tDD\t-1457\t; Index = 52 Token = 13\n\t\tDD\t-1722\t; Index = 52 Token = 14\n\t\tDD\t-1987\t; Index = 52 Token = 15\n\t\tDD\t145\t; Index = 53 Token = 0\n\t\tDD\t436\t; Index = 53 Token = 1\n\t\tDD\t728\t; Index = 53 Token = 2\n\t\tDD\t1019\t; Index = 53 Token = 3\n\t\tDD\t1311\t; Index = 53 Token = 4\n\t\tDD\t1602\t; Index = 53 Token = 5\n\t\tDD\t1894\t; Index = 53 Token = 6\n\t\tDD\t2185\t; Index = 53 Token = 7\n\t\tDD\t-145\t; Index = 53 Token = 8\n\t\tDD\t-436\t; Index = 53 Token = 9\n\t\tDD\t-728\t; Index = 53 Token = 10\n\t\tDD\t-1019\t; Index = 53 Token = 11\n\t\tDD\t-1311\t; Index = 53 Token = 12\n\t\tDD\t-1602\t; Index = 53 Token = 13\n\t\tDD\t-1894\t; Index = 53 Token = 14\n\t\tDD\t-2185\t; Index = 53 Token = 15\n\t\tDD\t160\t; Index = 54 Token = 0\n\t\tDD\t480\t; Index = 54 Token = 1\n\t\tDD\t801\t; Index = 54 Token = 2\n\t\tDD\t1121\t; Index = 54 Token = 3\n\t\tDD\t1442\t; Index = 54 Token = 4\n\t\tDD\t1762\t; Index = 54 Token = 5\n\t\tDD\t2083\t; Index = 54 Token = 6\n\t\tDD\t2403\t; Index = 54 Token = 7\n\t\tDD\t-160\t; Index = 54 Token = 8\n\t\tDD\t-480\t; Index = 54 Token = 9\n\t\tDD\t-801\t; Index = 54 Token = 10\n\t\tDD\t-1121\t; Index = 54 Token = 11\n\t\tDD\t-1442\t; Index = 54 Token = 12\n\t\tDD\t-1762\t; Index = 54 Token = 13\n\t\tDD\t-2083\t; Index = 54 Token = 14\n\t\tDD\t-2403\t; Index = 54 Token = 15\n\t\tDD\t176\t; Index = 55 Token = 0\n\t\tDD\t528\t; Index = 55 Token = 1\n\t\tDD\t881\t; Index = 55 Token = 2\n\t\tDD\t1233\t; Index = 55 Token = 3\n\t\tDD\t1587\t; Index = 55 Token = 4\n\t\tDD\t1939\t; Index = 55 Token = 5\n\t\tDD\t2292\t; Index = 55 Token = 6\n\t\tDD\t2644\t; Index = 55 Token = 7\n\t\tDD\t-176\t; Index = 55 Token = 8\n\t\tDD\t-528\t; Index = 55 Token = 9\n\t\tDD\t-881\t; Index = 55 Token = 10\n\t\tDD\t-1233\t; Index = 55 Token = 11\n\t\tDD\t-1587\t; Index = 55 Token = 12\n\t\tDD\t-1939\t; Index = 55 Token = 13\n\t\tDD\t-2292\t; Index = 55 Token = 14\n\t\tDD\t-2644\t; Index = 55 Token = 15\n\t\tDD\t194\t; Index = 56 Token = 0\n\t\tDD\t582\t; Index = 56 Token = 1\n\t\tDD\t970\t; Index = 56 Token = 2\n\t\tDD\t1358\t; Index = 56 Token = 3\n\t\tDD\t1746\t; Index = 56 Token = 4\n\t\tDD\t2134\t; Index = 56 Token = 5\n\t\tDD\t2522\t; Index = 56 Token = 6\n\t\tDD\t2910\t; Index = 56 Token = 7\n\t\tDD\t-194\t; Index = 56 Token = 8\n\t\tDD\t-582\t; Index = 56 Token = 9\n\t\tDD\t-970\t; Index = 56 Token = 10\n\t\tDD\t-1358\t; Index = 56 Token = 11\n\t\tDD\t-1746\t; Index = 56 Token = 12\n\t\tDD\t-2134\t; Index = 56 Token = 13\n\t\tDD\t-2522\t; Index = 56 Token = 14\n\t\tDD\t-2910\t; Index = 56 Token = 15\n\t\tDD\t213\t; Index = 57 Token = 0\n\t\tDD\t639\t; Index = 57 Token = 1\n\t\tDD\t1066\t; Index = 57 Token = 2\n\t\tDD\t1492\t; Index = 57 Token = 3\n\t\tDD\t1920\t; Index = 57 Token = 4\n\t\tDD\t2346\t; Index = 57 Token = 5\n\t\tDD\t2773\t; Index = 57 Token = 6\n\t\tDD\t3199\t; Index = 57 Token = 7\n\t\tDD\t-213\t; Index = 57 Token = 8\n\t\tDD\t-639\t; Index = 57 Token = 9\n\t\tDD\t-1066\t; Index = 57 Token = 10\n\t\tDD\t-1492\t; Index = 57 Token = 11\n\t\tDD\t-1920\t; Index = 57 Token = 12\n\t\tDD\t-2346\t; Index = 57 Token = 13\n\t\tDD\t-2773\t; Index = 57 Token = 14\n\t\tDD\t-3199\t; Index = 57 Token = 15\n\t\tDD\t234\t; Index = 58 Token = 0\n\t\tDD\t703\t; Index = 58 Token = 1\n\t\tDD\t1173\t; Index = 58 Token = 2\n\t\tDD\t1642\t; Index = 58 Token = 3\n\t\tDD\t2112\t; Index = 58 Token = 4\n\t\tDD\t2581\t; Index = 58 Token = 5\n\t\tDD\t3051\t; Index = 58 Token = 6\n\t\tDD\t3520\t; Index = 58 Token = 7\n\t\tDD\t-234\t; Index = 58 Token = 8\n\t\tDD\t-703\t; Index = 58 Token = 9\n\t\tDD\t-1173\t; Index = 58 Token = 10\n\t\tDD\t-1642\t; Index = 58 Token = 11\n\t\tDD\t-2112\t; Index = 58 Token = 12\n\t\tDD\t-2581\t; Index = 58 Token = 13\n\t\tDD\t-3051\t; Index = 58 Token = 14\n\t\tDD\t-3520\t; Index = 58 Token = 15\n\t\tDD\t258\t; Index = 59 Token = 0\n\t\tDD\t774\t; Index = 59 Token = 1\n\t\tDD\t1291\t; Index = 59 Token = 2\n\t\tDD\t1807\t; Index = 59 Token = 3\n\t\tDD\t2324\t; Index = 59 Token = 4\n\t\tDD\t2840\t; Index = 59 Token = 5\n\t\tDD\t3357\t; Index = 59 Token = 6\n\t\tDD\t3873\t; Index = 59 Token = 7\n\t\tDD\t-258\t; Index = 59 Token = 8\n\t\tDD\t-774\t; Index = 59 Token = 9\n\t\tDD\t-1291\t; Index = 59 Token = 10\n\t\tDD\t-1807\t; Index = 59 Token = 11\n\t\tDD\t-2324\t; Index = 59 Token = 12\n\t\tDD\t-2840\t; Index = 59 Token = 13\n\t\tDD\t-3357\t; Index = 59 Token = 14\n\t\tDD\t-3873\t; Index = 59 Token = 15\n\t\tDD\t284\t; Index = 60 Token = 0\n\t\tDD\t852\t; Index = 60 Token = 1\n\t\tDD\t1420\t; Index = 60 Token = 2\n\t\tDD\t1988\t; Index = 60 Token = 3\n\t\tDD\t2556\t; Index = 60 Token = 4\n\t\tDD\t3124\t; Index = 60 Token = 5\n\t\tDD\t3692\t; Index = 60 Token = 6\n\t\tDD\t4260\t; Index = 60 Token = 7\n\t\tDD\t-284\t; Index = 60 Token = 8\n\t\tDD\t-852\t; Index = 60 Token = 9\n\t\tDD\t-1420\t; Index = 60 Token = 10\n\t\tDD\t-1988\t; Index = 60 Token = 11\n\t\tDD\t-2556\t; Index = 60 Token = 12\n\t\tDD\t-3124\t; Index = 60 Token = 13\n\t\tDD\t-3692\t; Index = 60 Token = 14\n\t\tDD\t-4260\t; Index = 60 Token = 15\n\t\tDD\t312\t; Index = 61 Token = 0\n\t\tDD\t936\t; Index = 61 Token = 1\n\t\tDD\t1561\t; Index = 61 Token = 2\n\t\tDD\t2185\t; Index = 61 Token = 3\n\t\tDD\t2811\t; Index = 61 Token = 4\n\t\tDD\t3435\t; Index = 61 Token = 5\n\t\tDD\t4060\t; Index = 61 Token = 6\n\t\tDD\t4684\t; Index = 61 Token = 7\n\t\tDD\t-312\t; Index = 61 Token = 8\n\t\tDD\t-936\t; Index = 61 Token = 9\n\t\tDD\t-1561\t; Index = 61 Token = 10\n\t\tDD\t-2185\t; Index = 61 Token = 11\n\t\tDD\t-2811\t; Index = 61 Token = 12\n\t\tDD\t-3435\t; Index = 61 Token = 13\n\t\tDD\t-4060\t; Index = 61 Token = 14\n\t\tDD\t-4684\t; Index = 61 Token = 15\n\t\tDD\t343\t; Index = 62 Token = 0\n\t\tDD\t1030\t; Index = 62 Token = 1\n\t\tDD\t1717\t; Index = 62 Token = 2\n\t\tDD\t2404\t; Index = 62 Token = 3\n\t\tDD\t3092\t; Index = 62 Token = 4\n\t\tDD\t3779\t; Index = 62 Token = 5\n\t\tDD\t4466\t; Index = 62 Token = 6\n\t\tDD\t5153\t; Index = 62 Token = 7\n\t\tDD\t-343\t; Index = 62 Token = 8\n\t\tDD\t-1030\t; Index = 62 Token = 9\n\t\tDD\t-1717\t; Index = 62 Token = 10\n\t\tDD\t-2404\t; Index = 62 Token = 11\n\t\tDD\t-3092\t; Index = 62 Token = 12\n\t\tDD\t-3779\t; Index = 62 Token = 13\n\t\tDD\t-4466\t; Index = 62 Token = 14\n\t\tDD\t-5153\t; Index = 62 Token = 15\n\t\tDD\t378\t; Index = 63 Token = 0\n\t\tDD\t1134\t; Index = 63 Token = 1\n\t\tDD\t1890\t; Index = 63 Token = 2\n\t\tDD\t2646\t; Index = 63 Token = 3\n\t\tDD\t3402\t; Index = 63 Token = 4\n\t\tDD\t4158\t; Index = 63 Token = 5\n\t\tDD\t4914\t; Index = 63 Token = 6\n\t\tDD\t5670\t; Index = 63 Token = 7\n\t\tDD\t-378\t; Index = 63 Token = 8\n\t\tDD\t-1134\t; Index = 63 Token = 9\n\t\tDD\t-1890\t; Index = 63 Token = 10\n\t\tDD\t-2646\t; Index = 63 Token = 11\n\t\tDD\t-3402\t; Index = 63 Token = 12\n\t\tDD\t-4158\t; Index = 63 Token = 13\n\t\tDD\t-4914\t; Index = 63 Token = 14\n\t\tDD\t-5670\t; Index = 63 Token = 15\n\t\tDD\t415\t; Index = 64 Token = 0\n\t\tDD\t1246\t; Index = 64 Token = 1\n\t\tDD\t2078\t; Index = 64 Token = 2\n\t\tDD\t2909\t; Index = 64 Token = 3\n\t\tDD\t3742\t; Index = 64 Token = 4\n\t\tDD\t4573\t; Index = 64 Token = 5\n\t\tDD\t5405\t; Index = 64 Token = 6\n\t\tDD\t6236\t; Index = 64 Token = 7\n\t\tDD\t-415\t; Index = 64 Token = 8\n\t\tDD\t-1246\t; Index = 64 Token = 9\n\t\tDD\t-2078\t; Index = 64 Token = 10\n\t\tDD\t-2909\t; Index = 64 Token = 11\n\t\tDD\t-3742\t; Index = 64 Token = 12\n\t\tDD\t-4573\t; Index = 64 Token = 13\n\t\tDD\t-5405\t; Index = 64 Token = 14\n\t\tDD\t-6236\t; Index = 64 Token = 15\n\t\tDD\t457\t; Index = 65 Token = 0\n\t\tDD\t1372\t; Index = 65 Token = 1\n\t\tDD\t2287\t; Index = 65 Token = 2\n\t\tDD\t3202\t; Index = 65 Token = 3\n\t\tDD\t4117\t; Index = 65 Token = 4\n\t\tDD\t5032\t; Index = 65 Token = 5\n\t\tDD\t5947\t; Index = 65 Token = 6\n\t\tDD\t6862\t; Index = 65 Token = 7\n\t\tDD\t-457\t; Index = 65 Token = 8\n\t\tDD\t-1372\t; Index = 65 Token = 9\n\t\tDD\t-2287\t; Index = 65 Token = 10\n\t\tDD\t-3202\t; Index = 65 Token = 11\n\t\tDD\t-4117\t; Index = 65 Token = 12\n\t\tDD\t-5032\t; Index = 65 Token = 13\n\t\tDD\t-5947\t; Index = 65 Token = 14\n\t\tDD\t-6862\t; Index = 65 Token = 15\n\t\tDD\t503\t; Index = 66 Token = 0\n\t\tDD\t1509\t; Index = 66 Token = 1\n\t\tDD\t2516\t; Index = 66 Token = 2\n\t\tDD\t3522\t; Index = 66 Token = 3\n\t\tDD\t4529\t; Index = 66 Token = 4\n\t\tDD\t5535\t; Index = 66 Token = 5\n\t\tDD\t6542\t; Index = 66 Token = 6\n\t\tDD\t7548\t; Index = 66 Token = 7\n\t\tDD\t-503\t; Index = 66 Token = 8\n\t\tDD\t-1509\t; Index = 66 Token = 9\n\t\tDD\t-2516\t; Index = 66 Token = 10\n\t\tDD\t-3522\t; Index = 66 Token = 11\n\t\tDD\t-4529\t; Index = 66 Token = 12\n\t\tDD\t-5535\t; Index = 66 Token = 13\n\t\tDD\t-6542\t; Index = 66 Token = 14\n\t\tDD\t-7548\t; Index = 66 Token = 15\n\t\tDD\t553\t; Index = 67 Token = 0\n\t\tDD\t1660\t; Index = 67 Token = 1\n\t\tDD\t2767\t; Index = 67 Token = 2\n\t\tDD\t3874\t; Index = 67 Token = 3\n\t\tDD\t4981\t; Index = 67 Token = 4\n\t\tDD\t6088\t; Index = 67 Token = 5\n\t\tDD\t7195\t; Index = 67 Token = 6\n\t\tDD\t8302\t; Index = 67 Token = 7\n\t\tDD\t-553\t; Index = 67 Token = 8\n\t\tDD\t-1660\t; Index = 67 Token = 9\n\t\tDD\t-2767\t; Index = 67 Token = 10\n\t\tDD\t-3874\t; Index = 67 Token = 11\n\t\tDD\t-4981\t; Index = 67 Token = 12\n\t\tDD\t-6088\t; Index = 67 Token = 13\n\t\tDD\t-7195\t; Index = 67 Token = 14\n\t\tDD\t-8302\t; Index = 67 Token = 15\n\t\tDD\t608\t; Index = 68 Token = 0\n\t\tDD\t1825\t; Index = 68 Token = 1\n\t\tDD\t3043\t; Index = 68 Token = 2\n\t\tDD\t4260\t; Index = 68 Token = 3\n\t\tDD\t5479\t; Index = 68 Token = 4\n\t\tDD\t6696\t; Index = 68 Token = 5\n\t\tDD\t7914\t; Index = 68 Token = 6\n\t\tDD\t9131\t; Index = 68 Token = 7\n\t\tDD\t-608\t; Index = 68 Token = 8\n\t\tDD\t-1825\t; Index = 68 Token = 9\n\t\tDD\t-3043\t; Index = 68 Token = 10\n\t\tDD\t-4260\t; Index = 68 Token = 11\n\t\tDD\t-5479\t; Index = 68 Token = 12\n\t\tDD\t-6696\t; Index = 68 Token = 13\n\t\tDD\t-7914\t; Index = 68 Token = 14\n\t\tDD\t-9131\t; Index = 68 Token = 15\n\t\tDD\t669\t; Index = 69 Token = 0\n\t\tDD\t2008\t; Index = 69 Token = 1\n\t\tDD\t3348\t; Index = 69 Token = 2\n\t\tDD\t4687\t; Index = 69 Token = 3\n\t\tDD\t6027\t; Index = 69 Token = 4\n\t\tDD\t7366\t; Index = 69 Token = 5\n\t\tDD\t8706\t; Index = 69 Token = 6\n\t\tDD\t10045\t; Index = 69 Token = 7\n\t\tDD\t-669\t; Index = 69 Token = 8\n\t\tDD\t-2008\t; Index = 69 Token = 9\n\t\tDD\t-3348\t; Index = 69 Token = 10\n\t\tDD\t-4687\t; Index = 69 Token = 11\n\t\tDD\t-6027\t; Index = 69 Token = 12\n\t\tDD\t-7366\t; Index = 69 Token = 13\n\t\tDD\t-8706\t; Index = 69 Token = 14\n\t\tDD\t-10045\t; Index = 69 Token = 15\n\t\tDD\t736\t; Index = 70 Token = 0\n\t\tDD\t2209\t; Index = 70 Token = 1\n\t\tDD\t3683\t; Index = 70 Token = 2\n\t\tDD\t5156\t; Index = 70 Token = 3\n\t\tDD\t6630\t; Index = 70 Token = 4\n\t\tDD\t8103\t; Index = 70 Token = 5\n\t\tDD\t9577\t; Index = 70 Token = 6\n\t\tDD\t11050\t; Index = 70 Token = 7\n\t\tDD\t-736\t; Index = 70 Token = 8\n\t\tDD\t-2209\t; Index = 70 Token = 9\n\t\tDD\t-3683\t; Index = 70 Token = 10\n\t\tDD\t-5156\t; Index = 70 Token = 11\n\t\tDD\t-6630\t; Index = 70 Token = 12\n\t\tDD\t-8103\t; Index = 70 Token = 13\n\t\tDD\t-9577\t; Index = 70 Token = 14\n\t\tDD\t-11050\t; Index = 70 Token = 15\n\t\tDD\t810\t; Index = 71 Token = 0\n\t\tDD\t2431\t; Index = 71 Token = 1\n\t\tDD\t4052\t; Index = 71 Token = 2\n\t\tDD\t5673\t; Index = 71 Token = 3\n\t\tDD\t7294\t; Index = 71 Token = 4\n\t\tDD\t8915\t; Index = 71 Token = 5\n\t\tDD\t10536\t; Index = 71 Token = 6\n\t\tDD\t12157\t; Index = 71 Token = 7\n\t\tDD\t-810\t; Index = 71 Token = 8\n\t\tDD\t-2431\t; Index = 71 Token = 9\n\t\tDD\t-4052\t; Index = 71 Token = 10\n\t\tDD\t-5673\t; Index = 71 Token = 11\n\t\tDD\t-7294\t; Index = 71 Token = 12\n\t\tDD\t-8915\t; Index = 71 Token = 13\n\t\tDD\t-10536\t; Index = 71 Token = 14\n\t\tDD\t-12157\t; Index = 71 Token = 15\n\t\tDD\t891\t; Index = 72 Token = 0\n\t\tDD\t2674\t; Index = 72 Token = 1\n\t\tDD\t4457\t; Index = 72 Token = 2\n\t\tDD\t6240\t; Index = 72 Token = 3\n\t\tDD\t8023\t; Index = 72 Token = 4\n\t\tDD\t9806\t; Index = 72 Token = 5\n\t\tDD\t11589\t; Index = 72 Token = 6\n\t\tDD\t13372\t; Index = 72 Token = 7\n\t\tDD\t-891\t; Index = 72 Token = 8\n\t\tDD\t-2674\t; Index = 72 Token = 9\n\t\tDD\t-4457\t; Index = 72 Token = 10\n\t\tDD\t-6240\t; Index = 72 Token = 11\n\t\tDD\t-8023\t; Index = 72 Token = 12\n\t\tDD\t-9806\t; Index = 72 Token = 13\n\t\tDD\t-11589\t; Index = 72 Token = 14\n\t\tDD\t-13372\t; Index = 72 Token = 15\n\t\tDD\t980\t; Index = 73 Token = 0\n\t\tDD\t2941\t; Index = 73 Token = 1\n\t\tDD\t4902\t; Index = 73 Token = 2\n\t\tDD\t6863\t; Index = 73 Token = 3\n\t\tDD\t8825\t; Index = 73 Token = 4\n\t\tDD\t10786\t; Index = 73 Token = 5\n\t\tDD\t12747\t; Index = 73 Token = 6\n\t\tDD\t14708\t; Index = 73 Token = 7\n\t\tDD\t-980\t; Index = 73 Token = 8\n\t\tDD\t-2941\t; Index = 73 Token = 9\n\t\tDD\t-4902\t; Index = 73 Token = 10\n\t\tDD\t-6863\t; Index = 73 Token = 11\n\t\tDD\t-8825\t; Index = 73 Token = 12\n\t\tDD\t-10786\t; Index = 73 Token = 13\n\t\tDD\t-12747\t; Index = 73 Token = 14\n\t\tDD\t-14708\t; Index = 73 Token = 15\n\t\tDD\t1078\t; Index = 74 Token = 0\n\t\tDD\t3235\t; Index = 74 Token = 1\n\t\tDD\t5393\t; Index = 74 Token = 2\n\t\tDD\t7550\t; Index = 74 Token = 3\n\t\tDD\t9708\t; Index = 74 Token = 4\n\t\tDD\t11865\t; Index = 74 Token = 5\n\t\tDD\t14023\t; Index = 74 Token = 6\n\t\tDD\t16180\t; Index = 74 Token = 7\n\t\tDD\t-1078\t; Index = 74 Token = 8\n\t\tDD\t-3235\t; Index = 74 Token = 9\n\t\tDD\t-5393\t; Index = 74 Token = 10\n\t\tDD\t-7550\t; Index = 74 Token = 11\n\t\tDD\t-9708\t; Index = 74 Token = 12\n\t\tDD\t-11865\t; Index = 74 Token = 13\n\t\tDD\t-14023\t; Index = 74 Token = 14\n\t\tDD\t-16180\t; Index = 74 Token = 15\n\t\tDD\t1186\t; Index = 75 Token = 0\n\t\tDD\t3559\t; Index = 75 Token = 1\n\t\tDD\t5932\t; Index = 75 Token = 2\n\t\tDD\t8305\t; Index = 75 Token = 3\n\t\tDD\t10679\t; Index = 75 Token = 4\n\t\tDD\t13052\t; Index = 75 Token = 5\n\t\tDD\t15425\t; Index = 75 Token = 6\n\t\tDD\t17798\t; Index = 75 Token = 7\n\t\tDD\t-1186\t; Index = 75 Token = 8\n\t\tDD\t-3559\t; Index = 75 Token = 9\n\t\tDD\t-5932\t; Index = 75 Token = 10\n\t\tDD\t-8305\t; Index = 75 Token = 11\n\t\tDD\t-10679\t; Index = 75 Token = 12\n\t\tDD\t-13052\t; Index = 75 Token = 13\n\t\tDD\t-15425\t; Index = 75 Token = 14\n\t\tDD\t-17798\t; Index = 75 Token = 15\n\t\tDD\t1305\t; Index = 76 Token = 0\n\t\tDD\t3915\t; Index = 76 Token = 1\n\t\tDD\t6526\t; Index = 76 Token = 2\n\t\tDD\t9136\t; Index = 76 Token = 3\n\t\tDD\t11747\t; Index = 76 Token = 4\n\t\tDD\t14357\t; Index = 76 Token = 5\n\t\tDD\t16968\t; Index = 76 Token = 6\n\t\tDD\t19578\t; Index = 76 Token = 7\n\t\tDD\t-1305\t; Index = 76 Token = 8\n\t\tDD\t-3915\t; Index = 76 Token = 9\n\t\tDD\t-6526\t; Index = 76 Token = 10\n\t\tDD\t-9136\t; Index = 76 Token = 11\n\t\tDD\t-11747\t; Index = 76 Token = 12\n\t\tDD\t-14357\t; Index = 76 Token = 13\n\t\tDD\t-16968\t; Index = 76 Token = 14\n\t\tDD\t-19578\t; Index = 76 Token = 15\n\t\tDD\t1435\t; Index = 77 Token = 0\n\t\tDD\t4306\t; Index = 77 Token = 1\n\t\tDD\t7178\t; Index = 77 Token = 2\n\t\tDD\t10049\t; Index = 77 Token = 3\n\t\tDD\t12922\t; Index = 77 Token = 4\n\t\tDD\t15793\t; Index = 77 Token = 5\n\t\tDD\t18665\t; Index = 77 Token = 6\n\t\tDD\t21536\t; Index = 77 Token = 7\n\t\tDD\t-1435\t; Index = 77 Token = 8\n\t\tDD\t-4306\t; Index = 77 Token = 9\n\t\tDD\t-7178\t; Index = 77 Token = 10\n\t\tDD\t-10049\t; Index = 77 Token = 11\n\t\tDD\t-12922\t; Index = 77 Token = 12\n\t\tDD\t-15793\t; Index = 77 Token = 13\n\t\tDD\t-18665\t; Index = 77 Token = 14\n\t\tDD\t-21536\t; Index = 77 Token = 15\n\t\tDD\t1579\t; Index = 78 Token = 0\n\t\tDD\t4737\t; Index = 78 Token = 1\n\t\tDD\t7896\t; Index = 78 Token = 2\n\t\tDD\t11054\t; Index = 78 Token = 3\n\t\tDD\t14214\t; Index = 78 Token = 4\n\t\tDD\t17372\t; Index = 78 Token = 5\n\t\tDD\t20531\t; Index = 78 Token = 6\n\t\tDD\t23689\t; Index = 78 Token = 7\n\t\tDD\t-1579\t; Index = 78 Token = 8\n\t\tDD\t-4737\t; Index = 78 Token = 9\n\t\tDD\t-7896\t; Index = 78 Token = 10\n\t\tDD\t-11054\t; Index = 78 Token = 11\n\t\tDD\t-14214\t; Index = 78 Token = 12\n\t\tDD\t-17372\t; Index = 78 Token = 13\n\t\tDD\t-20531\t; Index = 78 Token = 14\n\t\tDD\t-23689\t; Index = 78 Token = 15\n\t\tDD\t1737\t; Index = 79 Token = 0\n\t\tDD\t5211\t; Index = 79 Token = 1\n\t\tDD\t8686\t; Index = 79 Token = 2\n\t\tDD\t12160\t; Index = 79 Token = 3\n\t\tDD\t15636\t; Index = 79 Token = 4\n\t\tDD\t19110\t; Index = 79 Token = 5\n\t\tDD\t22585\t; Index = 79 Token = 6\n\t\tDD\t26059\t; Index = 79 Token = 7\n\t\tDD\t-1737\t; Index = 79 Token = 8\n\t\tDD\t-5211\t; Index = 79 Token = 9\n\t\tDD\t-8686\t; Index = 79 Token = 10\n\t\tDD\t-12160\t; Index = 79 Token = 11\n\t\tDD\t-15636\t; Index = 79 Token = 12\n\t\tDD\t-19110\t; Index = 79 Token = 13\n\t\tDD\t-22585\t; Index = 79 Token = 14\n\t\tDD\t-26059\t; Index = 79 Token = 15\n\t\tDD\t1911\t; Index = 80 Token = 0\n\t\tDD\t5733\t; Index = 80 Token = 1\n\t\tDD\t9555\t; Index = 80 Token = 2\n\t\tDD\t13377\t; Index = 80 Token = 3\n\t\tDD\t17200\t; Index = 80 Token = 4\n\t\tDD\t21022\t; Index = 80 Token = 5\n\t\tDD\t24844\t; Index = 80 Token = 6\n\t\tDD\t28666\t; Index = 80 Token = 7\n\t\tDD\t-1911\t; Index = 80 Token = 8\n\t\tDD\t-5733\t; Index = 80 Token = 9\n\t\tDD\t-9555\t; Index = 80 Token = 10\n\t\tDD\t-13377\t; Index = 80 Token = 11\n\t\tDD\t-17200\t; Index = 80 Token = 12\n\t\tDD\t-21022\t; Index = 80 Token = 13\n\t\tDD\t-24844\t; Index = 80 Token = 14\n\t\tDD\t-28666\t; Index = 80 Token = 15\n\t\tDD\t2102\t; Index = 81 Token = 0\n\t\tDD\t6306\t; Index = 81 Token = 1\n\t\tDD\t10511\t; Index = 81 Token = 2\n\t\tDD\t14715\t; Index = 81 Token = 3\n\t\tDD\t18920\t; Index = 81 Token = 4\n\t\tDD\t23124\t; Index = 81 Token = 5\n\t\tDD\t27329\t; Index = 81 Token = 6\n\t\tDD\t31533\t; Index = 81 Token = 7\n\t\tDD\t-2102\t; Index = 81 Token = 8\n\t\tDD\t-6306\t; Index = 81 Token = 9\n\t\tDD\t-10511\t; Index = 81 Token = 10\n\t\tDD\t-14715\t; Index = 81 Token = 11\n\t\tDD\t-18920\t; Index = 81 Token = 12\n\t\tDD\t-23124\t; Index = 81 Token = 13\n\t\tDD\t-27329\t; Index = 81 Token = 14\n\t\tDD\t-31533\t; Index = 81 Token = 15\n\t\tDD\t2312\t; Index = 82 Token = 0\n\t\tDD\t6937\t; Index = 82 Token = 1\n\t\tDD\t11562\t; Index = 82 Token = 2\n\t\tDD\t16187\t; Index = 82 Token = 3\n\t\tDD\t20812\t; Index = 82 Token = 4\n\t\tDD\t25437\t; Index = 82 Token = 5\n\t\tDD\t30062\t; Index = 82 Token = 6\n\t\tDD\t34687\t; Index = 82 Token = 7\n\t\tDD\t-2312\t; Index = 82 Token = 8\n\t\tDD\t-6937\t; Index = 82 Token = 9\n\t\tDD\t-11562\t; Index = 82 Token = 10\n\t\tDD\t-16187\t; Index = 82 Token = 11\n\t\tDD\t-20812\t; Index = 82 Token = 12\n\t\tDD\t-25437\t; Index = 82 Token = 13\n\t\tDD\t-30062\t; Index = 82 Token = 14\n\t\tDD\t-34687\t; Index = 82 Token = 15\n\t\tDD\t2543\t; Index = 83 Token = 0\n\t\tDD\t7630\t; Index = 83 Token = 1\n\t\tDD\t12718\t; Index = 83 Token = 2\n\t\tDD\t17805\t; Index = 83 Token = 3\n\t\tDD\t22893\t; Index = 83 Token = 4\n\t\tDD\t27980\t; Index = 83 Token = 5\n\t\tDD\t33068\t; Index = 83 Token = 6\n\t\tDD\t38155\t; Index = 83 Token = 7\n\t\tDD\t-2543\t; Index = 83 Token = 8\n\t\tDD\t-7630\t; Index = 83 Token = 9\n\t\tDD\t-12718\t; Index = 83 Token = 10\n\t\tDD\t-17805\t; Index = 83 Token = 11\n\t\tDD\t-22893\t; Index = 83 Token = 12\n\t\tDD\t-27980\t; Index = 83 Token = 13\n\t\tDD\t-33068\t; Index = 83 Token = 14\n\t\tDD\t-38155\t; Index = 83 Token = 15\n\t\tDD\t2798\t; Index = 84 Token = 0\n\t\tDD\t8394\t; Index = 84 Token = 1\n\t\tDD\t13990\t; Index = 84 Token = 2\n\t\tDD\t19586\t; Index = 84 Token = 3\n\t\tDD\t25183\t; Index = 84 Token = 4\n\t\tDD\t30779\t; Index = 84 Token = 5\n\t\tDD\t36375\t; Index = 84 Token = 6\n\t\tDD\t41971\t; Index = 84 Token = 7\n\t\tDD\t-2798\t; Index = 84 Token = 8\n\t\tDD\t-8394\t; Index = 84 Token = 9\n\t\tDD\t-13990\t; Index = 84 Token = 10\n\t\tDD\t-19586\t; Index = 84 Token = 11\n\t\tDD\t-25183\t; Index = 84 Token = 12\n\t\tDD\t-30779\t; Index = 84 Token = 13\n\t\tDD\t-36375\t; Index = 84 Token = 14\n\t\tDD\t-41971\t; Index = 84 Token = 15\n\t\tDD\t3077\t; Index = 85 Token = 0\n\t\tDD\t9232\t; Index = 85 Token = 1\n\t\tDD\t15388\t; Index = 85 Token = 2\n\t\tDD\t21543\t; Index = 85 Token = 3\n\t\tDD\t27700\t; Index = 85 Token = 4\n\t\tDD\t33855\t; Index = 85 Token = 5\n\t\tDD\t40011\t; Index = 85 Token = 6\n\t\tDD\t46166\t; Index = 85 Token = 7\n\t\tDD\t-3077\t; Index = 85 Token = 8\n\t\tDD\t-9232\t; Index = 85 Token = 9\n\t\tDD\t-15388\t; Index = 85 Token = 10\n\t\tDD\t-21543\t; Index = 85 Token = 11\n\t\tDD\t-27700\t; Index = 85 Token = 12\n\t\tDD\t-33855\t; Index = 85 Token = 13\n\t\tDD\t-40011\t; Index = 85 Token = 14\n\t\tDD\t-46166\t; Index = 85 Token = 15\n\t\tDD\t3385\t; Index = 86 Token = 0\n\t\tDD\t10156\t; Index = 86 Token = 1\n\t\tDD\t16928\t; Index = 86 Token = 2\n\t\tDD\t23699\t; Index = 86 Token = 3\n\t\tDD\t30471\t; Index = 86 Token = 4\n\t\tDD\t37242\t; Index = 86 Token = 5\n\t\tDD\t44014\t; Index = 86 Token = 6\n\t\tDD\t50785\t; Index = 86 Token = 7\n\t\tDD\t-3385\t; Index = 86 Token = 8\n\t\tDD\t-10156\t; Index = 86 Token = 9\n\t\tDD\t-16928\t; Index = 86 Token = 10\n\t\tDD\t-23699\t; Index = 86 Token = 11\n\t\tDD\t-30471\t; Index = 86 Token = 12\n\t\tDD\t-37242\t; Index = 86 Token = 13\n\t\tDD\t-44014\t; Index = 86 Token = 14\n\t\tDD\t-50785\t; Index = 86 Token = 15\n\t\tDD\t3724\t; Index = 87 Token = 0\n\t\tDD\t11172\t; Index = 87 Token = 1\n\t\tDD\t18621\t; Index = 87 Token = 2\n\t\tDD\t26069\t; Index = 87 Token = 3\n\t\tDD\t33518\t; Index = 87 Token = 4\n\t\tDD\t40966\t; Index = 87 Token = 5\n\t\tDD\t48415\t; Index = 87 Token = 6\n\t\tDD\t55863\t; Index = 87 Token = 7\n\t\tDD\t-3724\t; Index = 87 Token = 8\n\t\tDD\t-11172\t; Index = 87 Token = 9\n\t\tDD\t-18621\t; Index = 87 Token = 10\n\t\tDD\t-26069\t; Index = 87 Token = 11\n\t\tDD\t-33518\t; Index = 87 Token = 12\n\t\tDD\t-40966\t; Index = 87 Token = 13\n\t\tDD\t-48415\t; Index = 87 Token = 14\n\t\tDD\t-55863\t; Index = 87 Token = 15\n\t\tDD\t4095\t; Index = 88 Token = 0\n\t\tDD\t12286\t; Index = 88 Token = 1\n\t\tDD\t20478\t; Index = 88 Token = 2\n\t\tDD\t28669\t; Index = 88 Token = 3\n\t\tDD\t36862\t; Index = 88 Token = 4\n\t\tDD\t45053\t; Index = 88 Token = 5\n\t\tDD\t53245\t; Index = 88 Token = 6\n\t\tDD\t61436\t; Index = 88 Token = 7\n\t\tDD\t-4095\t; Index = 88 Token = 8\n\t\tDD\t-12286\t; Index = 88 Token = 9\n\t\tDD\t-20478\t; Index = 88 Token = 10\n\t\tDD\t-28669\t; Index = 88 Token = 11\n\t\tDD\t-36862\t; Index = 88 Token = 12\n\t\tDD\t-45053\t; Index = 88 Token = 13\n\t\tDD\t-53245\t; Index = 88 Token = 14\n\t\tDD\t-61436\t; Index = 88 Token = 15\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/FUNCTION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SOUNDIO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort Decompress_Frame(void * source, void * dest, short size);\nint __cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback);\nint __cdecl Stream_Sample(void *buffer, long size, BOOL (*callback);\nint __cdecl File_Stream_Sample(char const *filename);\nint __cdecl File_Stream_Sample_Vol(char const *filename, int volume);\nvoid __cdecl _saveregs _loadds Sound_Callback(void);\nvoid __cdecl far _saveregs _loadds maintenance_callback(void);\nvoid  __cdecl Load_Sample(char const *filename);\nlong __cdecl Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);\nlong __cdecl Sample_Read(int fh, void *buffer, long size);\nvoid __cdecl Free_Sample(void const *sample);\nBOOL __cdecl Sound_Init(int sfx, int score, int sample);\nvoid far VQA_TimerCallback(void);\nBOOL Audio_Init(int sample, int address, int inter, int dma);\nvoid __cdecl Sound_End(void);\nvoid __cdecl Stop_Sample(int handle);\nBOOL __cdecl Sample_Status(int handle);\nBOOL __cdecl Is_Sample_Playing(void const * sample);\nvoid __cdecl Stop_Sample_Playing(void const * sample);\nint __cdecl Play_Sample(void const *sample);\nint __cdecl Play_Sample_Vol(void const *sample, int priority, int volume);\nint __cdecl Set_Sound_Vol(int volume);\nint __cdecl Set_Score_Vol(int volume);\nvoid __cdecl Fade_Sample(int handle, int ticks);"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/INDEXTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* wIndexTable - ADPCM Lookup table for indexes\n;****************************************************************************\n\n\t\talign\t4\n\nwIndexTable\tDW\t0\t* 2\t; Index = 0 Token = 0\n\t\tDW\t0\t* 2\t; Index = 0 Token = 1\n\t\tDW\t0\t* 2\t; Index = 0 Token = 2\n\t\tDW\t0\t* 2\t; Index = 0 Token = 3\n\t\tDW\t32\t* 2\t; Index = 0 Token = 4\n\t\tDW\t64\t* 2\t; Index = 0 Token = 5\n\t\tDW\t96\t* 2\t; Index = 0 Token = 6\n\t\tDW\t128\t* 2\t; Index = 0 Token = 7\n\t\tDW\t0\t* 2\t; Index = 0 Token = 8\n\t\tDW\t0\t* 2\t; Index = 0 Token = 9\n\t\tDW\t0\t* 2\t; Index = 0 Token = 10\n\t\tDW\t0\t* 2\t; Index = 0 Token = 11\n\t\tDW\t32\t* 2\t; Index = 0 Token = 12\n\t\tDW\t64\t* 2\t; Index = 0 Token = 13\n\t\tDW\t96\t* 2\t; Index = 0 Token = 14\n\t\tDW\t128\t* 2\t; Index = 0 Token = 15\n\t\tDW\t0\t* 2\t; Index = 1 Token = 0\n\t\tDW\t0\t* 2\t; Index = 1 Token = 1\n\t\tDW\t0\t* 2\t; Index = 1 Token = 2\n\t\tDW\t0\t* 2\t; Index = 1 Token = 3\n\t\tDW\t48\t* 2\t; Index = 1 Token = 4\n\t\tDW\t80\t* 2\t; Index = 1 Token = 5\n\t\tDW\t112\t* 2\t; Index = 1 Token = 6\n\t\tDW\t144\t* 2\t; Index = 1 Token = 7\n\t\tDW\t0\t* 2\t; Index = 1 Token = 8\n\t\tDW\t0\t* 2\t; Index = 1 Token = 9\n\t\tDW\t0\t* 2\t; Index = 1 Token = 10\n\t\tDW\t0\t* 2\t; Index = 1 Token = 11\n\t\tDW\t48\t* 2\t; Index = 1 Token = 12\n\t\tDW\t80\t* 2\t; Index = 1 Token = 13\n\t\tDW\t112\t* 2\t; Index = 1 Token = 14\n\t\tDW\t144\t* 2\t; Index = 1 Token = 15\n\t\tDW\t16\t* 2\t; Index = 2 Token = 0\n\t\tDW\t16\t* 2\t; Index = 2 Token = 1\n\t\tDW\t16\t* 2\t; Index = 2 Token = 2\n\t\tDW\t16\t* 2\t; Index = 2 Token = 3\n\t\tDW\t64\t* 2\t; Index = 2 Token = 4\n\t\tDW\t96\t* 2\t; Index = 2 Token = 5\n\t\tDW\t128\t* 2\t; Index = 2 Token = 6\n\t\tDW\t160\t* 2\t; Index = 2 Token = 7\n\t\tDW\t16\t* 2\t; Index = 2 Token = 8\n\t\tDW\t16\t* 2\t; Index = 2 Token = 9\n\t\tDW\t16\t* 2\t; Index = 2 Token = 10\n\t\tDW\t16\t* 2\t; Index = 2 Token = 11\n\t\tDW\t64\t* 2\t; Index = 2 Token = 12\n\t\tDW\t96\t* 2\t; Index = 2 Token = 13\n\t\tDW\t128\t* 2\t; Index = 2 Token = 14\n\t\tDW\t160\t* 2\t; Index = 2 Token = 15\n\t\tDW\t32\t* 2\t; Index = 3 Token = 0\n\t\tDW\t32\t* 2\t; Index = 3 Token = 1\n\t\tDW\t32\t* 2\t; Index = 3 Token = 2\n\t\tDW\t32\t* 2\t; Index = 3 Token = 3\n\t\tDW\t80\t* 2\t; Index = 3 Token = 4\n\t\tDW\t112\t* 2\t; Index = 3 Token = 5\n\t\tDW\t144\t* 2\t; Index = 3 Token = 6\n\t\tDW\t176\t* 2\t; Index = 3 Token = 7\n\t\tDW\t32\t* 2\t; Index = 3 Token = 8\n\t\tDW\t32\t* 2\t; Index = 3 Token = 9\n\t\tDW\t32\t* 2\t; Index = 3 Token = 10\n\t\tDW\t32\t* 2\t; Index = 3 Token = 11\n\t\tDW\t80\t* 2\t; Index = 3 Token = 12\n\t\tDW\t112\t* 2\t; Index = 3 Token = 13\n\t\tDW\t144\t* 2\t; Index = 3 Token = 14\n\t\tDW\t176\t* 2\t; Index = 3 Token = 15\n\t\tDW\t48\t* 2\t; Index = 4 Token = 0\n\t\tDW\t48\t* 2\t; Index = 4 Token = 1\n\t\tDW\t48\t* 2\t; Index = 4 Token = 2\n\t\tDW\t48\t* 2\t; Index = 4 Token = 3\n\t\tDW\t96\t* 2\t; Index = 4 Token = 4\n\t\tDW\t128\t* 2\t; Index = 4 Token = 5\n\t\tDW\t160\t* 2\t; Index = 4 Token = 6\n\t\tDW\t192\t* 2\t; Index = 4 Token = 7\n\t\tDW\t48\t* 2\t; Index = 4 Token = 8\n\t\tDW\t48\t* 2\t; Index = 4 Token = 9\n\t\tDW\t48\t* 2\t; Index = 4 Token = 10\n\t\tDW\t48\t* 2\t; Index = 4 Token = 11\n\t\tDW\t96\t* 2\t; Index = 4 Token = 12\n\t\tDW\t128\t* 2\t; Index = 4 Token = 13\n\t\tDW\t160\t* 2\t; Index = 4 Token = 14\n\t\tDW\t192\t* 2\t; Index = 4 Token = 15\n\t\tDW\t64\t* 2\t; Index = 5 Token = 0\n\t\tDW\t64\t* 2\t; Index = 5 Token = 1\n\t\tDW\t64\t* 2\t; Index = 5 Token = 2\n\t\tDW\t64\t* 2\t; Index = 5 Token = 3\n\t\tDW\t112\t* 2\t; Index = 5 Token = 4\n\t\tDW\t144\t* 2\t; Index = 5 Token = 5\n\t\tDW\t176\t* 2\t; Index = 5 Token = 6\n\t\tDW\t208\t* 2\t; Index = 5 Token = 7\n\t\tDW\t64\t* 2\t; Index = 5 Token = 8\n\t\tDW\t64\t* 2\t; Index = 5 Token = 9\n\t\tDW\t64\t* 2\t; Index = 5 Token = 10\n\t\tDW\t64\t* 2\t; Index = 5 Token = 11\n\t\tDW\t112\t* 2\t; Index = 5 Token = 12\n\t\tDW\t144\t* 2\t; Index = 5 Token = 13\n\t\tDW\t176\t* 2\t; Index = 5 Token = 14\n\t\tDW\t208\t* 2\t; Index = 5 Token = 15\n\t\tDW\t80\t* 2\t; Index = 6 Token = 0\n\t\tDW\t80\t* 2\t; Index = 6 Token = 1\n\t\tDW\t80\t* 2\t; Index = 6 Token = 2\n\t\tDW\t80\t* 2\t; Index = 6 Token = 3\n\t\tDW\t128\t* 2\t; Index = 6 Token = 4\n\t\tDW\t160\t* 2\t; Index = 6 Token = 5\n\t\tDW\t192\t* 2\t; Index = 6 Token = 6\n\t\tDW\t224\t* 2\t; Index = 6 Token = 7\n\t\tDW\t80\t* 2\t; Index = 6 Token = 8\n\t\tDW\t80\t* 2\t; Index = 6 Token = 9\n\t\tDW\t80\t* 2\t; Index = 6 Token = 10\n\t\tDW\t80\t* 2\t; Index = 6 Token = 11\n\t\tDW\t128\t* 2\t; Index = 6 Token = 12\n\t\tDW\t160\t* 2\t; Index = 6 Token = 13\n\t\tDW\t192\t* 2\t; Index = 6 Token = 14\n\t\tDW\t224\t* 2\t; Index = 6 Token = 15\n\t\tDW\t96\t* 2\t; Index = 7 Token = 0\n\t\tDW\t96\t* 2\t; Index = 7 Token = 1\n\t\tDW\t96\t* 2\t; Index = 7 Token = 2\n\t\tDW\t96\t* 2\t; Index = 7 Token = 3\n\t\tDW\t144\t* 2\t; Index = 7 Token = 4\n\t\tDW\t176\t* 2\t; Index = 7 Token = 5\n\t\tDW\t208\t* 2\t; Index = 7 Token = 6\n\t\tDW\t240\t* 2\t; Index = 7 Token = 7\n\t\tDW\t96\t* 2\t; Index = 7 Token = 8\n\t\tDW\t96\t* 2\t; Index = 7 Token = 9\n\t\tDW\t96\t* 2\t; Index = 7 Token = 10\n\t\tDW\t96\t* 2\t; Index = 7 Token = 11\n\t\tDW\t144\t* 2\t; Index = 7 Token = 12\n\t\tDW\t176\t* 2\t; Index = 7 Token = 13\n\t\tDW\t208\t* 2\t; Index = 7 Token = 14\n\t\tDW\t240\t* 2\t; Index = 7 Token = 15\n\t\tDW\t112\t* 2\t; Index = 8 Token = 0\n\t\tDW\t112\t* 2\t; Index = 8 Token = 1\n\t\tDW\t112\t* 2\t; Index = 8 Token = 2\n\t\tDW\t112\t* 2\t; Index = 8 Token = 3\n\t\tDW\t160\t* 2\t; Index = 8 Token = 4\n\t\tDW\t192\t* 2\t; Index = 8 Token = 5\n\t\tDW\t224\t* 2\t; Index = 8 Token = 6\n\t\tDW\t256\t* 2\t; Index = 8 Token = 7\n\t\tDW\t112\t* 2\t; Index = 8 Token = 8\n\t\tDW\t112\t* 2\t; Index = 8 Token = 9\n\t\tDW\t112\t* 2\t; Index = 8 Token = 10\n\t\tDW\t112\t* 2\t; Index = 8 Token = 11\n\t\tDW\t160\t* 2\t; Index = 8 Token = 12\n\t\tDW\t192\t* 2\t; Index = 8 Token = 13\n\t\tDW\t224\t* 2\t; Index = 8 Token = 14\n\t\tDW\t256\t* 2\t; Index = 8 Token = 15\n\t\tDW\t128\t* 2\t; Index = 9 Token = 0\n\t\tDW\t128\t* 2\t; Index = 9 Token = 1\n\t\tDW\t128\t* 2\t; Index = 9 Token = 2\n\t\tDW\t128\t* 2\t; Index = 9 Token = 3\n\t\tDW\t176\t* 2\t; Index = 9 Token = 4\n\t\tDW\t208\t* 2\t; Index = 9 Token = 5\n\t\tDW\t240\t* 2\t; Index = 9 Token = 6\n\t\tDW\t272\t* 2\t; Index = 9 Token = 7\n\t\tDW\t128\t* 2\t; Index = 9 Token = 8\n\t\tDW\t128\t* 2\t; Index = 9 Token = 9\n\t\tDW\t128\t* 2\t; Index = 9 Token = 10\n\t\tDW\t128\t* 2\t; Index = 9 Token = 11\n\t\tDW\t176\t* 2\t; Index = 9 Token = 12\n\t\tDW\t208\t* 2\t; Index = 9 Token = 13\n\t\tDW\t240\t* 2\t; Index = 9 Token = 14\n\t\tDW\t272\t* 2\t; Index = 9 Token = 15\n\t\tDW\t144\t* 2\t; Index = 10 Token = 0\n\t\tDW\t144\t* 2\t; Index = 10 Token = 1\n\t\tDW\t144\t* 2\t; Index = 10 Token = 2\n\t\tDW\t144\t* 2\t; Index = 10 Token = 3\n\t\tDW\t192\t* 2\t; Index = 10 Token = 4\n\t\tDW\t224\t* 2\t; Index = 10 Token = 5\n\t\tDW\t256\t* 2\t; Index = 10 Token = 6\n\t\tDW\t288\t* 2\t; Index = 10 Token = 7\n\t\tDW\t144\t* 2\t; Index = 10 Token = 8\n\t\tDW\t144\t* 2\t; Index = 10 Token = 9\n\t\tDW\t144\t* 2\t; Index = 10 Token = 10\n\t\tDW\t144\t* 2\t; Index = 10 Token = 11\n\t\tDW\t192\t* 2\t; Index = 10 Token = 12\n\t\tDW\t224\t* 2\t; Index = 10 Token = 13\n\t\tDW\t256\t* 2\t; Index = 10 Token = 14\n\t\tDW\t288\t* 2\t; Index = 10 Token = 15\n\t\tDW\t160\t* 2\t; Index = 11 Token = 0\n\t\tDW\t160\t* 2\t; Index = 11 Token = 1\n\t\tDW\t160\t* 2\t; Index = 11 Token = 2\n\t\tDW\t160\t* 2\t; Index = 11 Token = 3\n\t\tDW\t208\t* 2\t; Index = 11 Token = 4\n\t\tDW\t240\t* 2\t; Index = 11 Token = 5\n\t\tDW\t272\t* 2\t; Index = 11 Token = 6\n\t\tDW\t304\t* 2\t; Index = 11 Token = 7\n\t\tDW\t160\t* 2\t; Index = 11 Token = 8\n\t\tDW\t160\t* 2\t; Index = 11 Token = 9\n\t\tDW\t160\t* 2\t; Index = 11 Token = 10\n\t\tDW\t160\t* 2\t; Index = 11 Token = 11\n\t\tDW\t208\t* 2\t; Index = 11 Token = 12\n\t\tDW\t240\t* 2\t; Index = 11 Token = 13\n\t\tDW\t272\t* 2\t; Index = 11 Token = 14\n\t\tDW\t304\t* 2\t; Index = 11 Token = 15\n\t\tDW\t176\t* 2\t; Index = 12 Token = 0\n\t\tDW\t176\t* 2\t; Index = 12 Token = 1\n\t\tDW\t176\t* 2\t; Index = 12 Token = 2\n\t\tDW\t176\t* 2\t; Index = 12 Token = 3\n\t\tDW\t224\t* 2\t; Index = 12 Token = 4\n\t\tDW\t256\t* 2\t; Index = 12 Token = 5\n\t\tDW\t288\t* 2\t; Index = 12 Token = 6\n\t\tDW\t320\t* 2\t; Index = 12 Token = 7\n\t\tDW\t176\t* 2\t; Index = 12 Token = 8\n\t\tDW\t176\t* 2\t; Index = 12 Token = 9\n\t\tDW\t176\t* 2\t; Index = 12 Token = 10\n\t\tDW\t176\t* 2\t; Index = 12 Token = 11\n\t\tDW\t224\t* 2\t; Index = 12 Token = 12\n\t\tDW\t256\t* 2\t; Index = 12 Token = 13\n\t\tDW\t288\t* 2\t; Index = 12 Token = 14\n\t\tDW\t320\t* 2\t; Index = 12 Token = 15\n\t\tDW\t192\t* 2\t; Index = 13 Token = 0\n\t\tDW\t192\t* 2\t; Index = 13 Token = 1\n\t\tDW\t192\t* 2\t; Index = 13 Token = 2\n\t\tDW\t192\t* 2\t; Index = 13 Token = 3\n\t\tDW\t240\t* 2\t; Index = 13 Token = 4\n\t\tDW\t272\t* 2\t; Index = 13 Token = 5\n\t\tDW\t304\t* 2\t; Index = 13 Token = 6\n\t\tDW\t336\t* 2\t; Index = 13 Token = 7\n\t\tDW\t192\t* 2\t; Index = 13 Token = 8\n\t\tDW\t192\t* 2\t; Index = 13 Token = 9\n\t\tDW\t192\t* 2\t; Index = 13 Token = 10\n\t\tDW\t192\t* 2\t; Index = 13 Token = 11\n\t\tDW\t240\t* 2\t; Index = 13 Token = 12\n\t\tDW\t272\t* 2\t; Index = 13 Token = 13\n\t\tDW\t304\t* 2\t; Index = 13 Token = 14\n\t\tDW\t336\t* 2\t; Index = 13 Token = 15\n\t\tDW\t208\t* 2\t; Index = 14 Token = 0\n\t\tDW\t208\t* 2\t; Index = 14 Token = 1\n\t\tDW\t208\t* 2\t; Index = 14 Token = 2\n\t\tDW\t208\t* 2\t; Index = 14 Token = 3\n\t\tDW\t256\t* 2\t; Index = 14 Token = 4\n\t\tDW\t288\t* 2\t; Index = 14 Token = 5\n\t\tDW\t320\t* 2\t; Index = 14 Token = 6\n\t\tDW\t352\t* 2\t; Index = 14 Token = 7\n\t\tDW\t208\t* 2\t; Index = 14 Token = 8\n\t\tDW\t208\t* 2\t; Index = 14 Token = 9\n\t\tDW\t208\t* 2\t; Index = 14 Token = 10\n\t\tDW\t208\t* 2\t; Index = 14 Token = 11\n\t\tDW\t256\t* 2\t; Index = 14 Token = 12\n\t\tDW\t288\t* 2\t; Index = 14 Token = 13\n\t\tDW\t320\t* 2\t; Index = 14 Token = 14\n\t\tDW\t352\t* 2\t; Index = 14 Token = 15\n\t\tDW\t224\t* 2\t; Index = 15 Token = 0\n\t\tDW\t224\t* 2\t; Index = 15 Token = 1\n\t\tDW\t224\t* 2\t; Index = 15 Token = 2\n\t\tDW\t224\t* 2\t; Index = 15 Token = 3\n\t\tDW\t272\t* 2\t; Index = 15 Token = 4\n\t\tDW\t304\t* 2\t; Index = 15 Token = 5\n\t\tDW\t336\t* 2\t; Index = 15 Token = 6\n\t\tDW\t368\t* 2\t; Index = 15 Token = 7\n\t\tDW\t224\t* 2\t; Index = 15 Token = 8\n\t\tDW\t224\t* 2\t; Index = 15 Token = 9\n\t\tDW\t224\t* 2\t; Index = 15 Token = 10\n\t\tDW\t224\t* 2\t; Index = 15 Token = 11\n\t\tDW\t272\t* 2\t; Index = 15 Token = 12\n\t\tDW\t304\t* 2\t; Index = 15 Token = 13\n\t\tDW\t336\t* 2\t; Index = 15 Token = 14\n\t\tDW\t368\t* 2\t; Index = 15 Token = 15\n\t\tDW\t240\t* 2\t; Index = 16 Token = 0\n\t\tDW\t240\t* 2\t; Index = 16 Token = 1\n\t\tDW\t240\t* 2\t; Index = 16 Token = 2\n\t\tDW\t240\t* 2\t; Index = 16 Token = 3\n\t\tDW\t288\t* 2\t; Index = 16 Token = 4\n\t\tDW\t320\t* 2\t; Index = 16 Token = 5\n\t\tDW\t352\t* 2\t; Index = 16 Token = 6\n\t\tDW\t384\t* 2\t; Index = 16 Token = 7\n\t\tDW\t240\t* 2\t; Index = 16 Token = 8\n\t\tDW\t240\t* 2\t; Index = 16 Token = 9\n\t\tDW\t240\t* 2\t; Index = 16 Token = 10\n\t\tDW\t240\t* 2\t; Index = 16 Token = 11\n\t\tDW\t288\t* 2\t; Index = 16 Token = 12\n\t\tDW\t320\t* 2\t; Index = 16 Token = 13\n\t\tDW\t352\t* 2\t; Index = 16 Token = 14\n\t\tDW\t384\t* 2\t; Index = 16 Token = 15\n\t\tDW\t256\t* 2\t; Index = 17 Token = 0\n\t\tDW\t256\t* 2\t; Index = 17 Token = 1\n\t\tDW\t256\t* 2\t; Index = 17 Token = 2\n\t\tDW\t256\t* 2\t; Index = 17 Token = 3\n\t\tDW\t304\t* 2\t; Index = 17 Token = 4\n\t\tDW\t336\t* 2\t; Index = 17 Token = 5\n\t\tDW\t368\t* 2\t; Index = 17 Token = 6\n\t\tDW\t400\t* 2\t; Index = 17 Token = 7\n\t\tDW\t256\t* 2\t; Index = 17 Token = 8\n\t\tDW\t256\t* 2\t; Index = 17 Token = 9\n\t\tDW\t256\t* 2\t; Index = 17 Token = 10\n\t\tDW\t256\t* 2\t; Index = 17 Token = 11\n\t\tDW\t304\t* 2\t; Index = 17 Token = 12\n\t\tDW\t336\t* 2\t; Index = 17 Token = 13\n\t\tDW\t368\t* 2\t; Index = 17 Token = 14\n\t\tDW\t400\t* 2\t; Index = 17 Token = 15\n\t\tDW\t272\t* 2\t; Index = 18 Token = 0\n\t\tDW\t272\t* 2\t; Index = 18 Token = 1\n\t\tDW\t272\t* 2\t; Index = 18 Token = 2\n\t\tDW\t272\t* 2\t; Index = 18 Token = 3\n\t\tDW\t320\t* 2\t; Index = 18 Token = 4\n\t\tDW\t352\t* 2\t; Index = 18 Token = 5\n\t\tDW\t384\t* 2\t; Index = 18 Token = 6\n\t\tDW\t416\t* 2\t; Index = 18 Token = 7\n\t\tDW\t272\t* 2\t; Index = 18 Token = 8\n\t\tDW\t272\t* 2\t; Index = 18 Token = 9\n\t\tDW\t272\t* 2\t; Index = 18 Token = 10\n\t\tDW\t272\t* 2\t; Index = 18 Token = 11\n\t\tDW\t320\t* 2\t; Index = 18 Token = 12\n\t\tDW\t352\t* 2\t; Index = 18 Token = 13\n\t\tDW\t384\t* 2\t; Index = 18 Token = 14\n\t\tDW\t416\t* 2\t; Index = 18 Token = 15\n\t\tDW\t288\t* 2\t; Index = 19 Token = 0\n\t\tDW\t288\t* 2\t; Index = 19 Token = 1\n\t\tDW\t288\t* 2\t; Index = 19 Token = 2\n\t\tDW\t288\t* 2\t; Index = 19 Token = 3\n\t\tDW\t336\t* 2\t; Index = 19 Token = 4\n\t\tDW\t368\t* 2\t; Index = 19 Token = 5\n\t\tDW\t400\t* 2\t; Index = 19 Token = 6\n\t\tDW\t432\t* 2\t; Index = 19 Token = 7\n\t\tDW\t288\t* 2\t; Index = 19 Token = 8\n\t\tDW\t288\t* 2\t; Index = 19 Token = 9\n\t\tDW\t288\t* 2\t; Index = 19 Token = 10\n\t\tDW\t288\t* 2\t; Index = 19 Token = 11\n\t\tDW\t336\t* 2\t; Index = 19 Token = 12\n\t\tDW\t368\t* 2\t; Index = 19 Token = 13\n\t\tDW\t400\t* 2\t; Index = 19 Token = 14\n\t\tDW\t432\t* 2\t; Index = 19 Token = 15\n\t\tDW\t304\t* 2\t; Index = 20 Token = 0\n\t\tDW\t304\t* 2\t; Index = 20 Token = 1\n\t\tDW\t304\t* 2\t; Index = 20 Token = 2\n\t\tDW\t304\t* 2\t; Index = 20 Token = 3\n\t\tDW\t352\t* 2\t; Index = 20 Token = 4\n\t\tDW\t384\t* 2\t; Index = 20 Token = 5\n\t\tDW\t416\t* 2\t; Index = 20 Token = 6\n\t\tDW\t448\t* 2\t; Index = 20 Token = 7\n\t\tDW\t304\t* 2\t; Index = 20 Token = 8\n\t\tDW\t304\t* 2\t; Index = 20 Token = 9\n\t\tDW\t304\t* 2\t; Index = 20 Token = 10\n\t\tDW\t304\t* 2\t; Index = 20 Token = 11\n\t\tDW\t352\t* 2\t; Index = 20 Token = 12\n\t\tDW\t384\t* 2\t; Index = 20 Token = 13\n\t\tDW\t416\t* 2\t; Index = 20 Token = 14\n\t\tDW\t448\t* 2\t; Index = 20 Token = 15\n\t\tDW\t320\t* 2\t; Index = 21 Token = 0\n\t\tDW\t320\t* 2\t; Index = 21 Token = 1\n\t\tDW\t320\t* 2\t; Index = 21 Token = 2\n\t\tDW\t320\t* 2\t; Index = 21 Token = 3\n\t\tDW\t368\t* 2\t; Index = 21 Token = 4\n\t\tDW\t400\t* 2\t; Index = 21 Token = 5\n\t\tDW\t432\t* 2\t; Index = 21 Token = 6\n\t\tDW\t464\t* 2\t; Index = 21 Token = 7\n\t\tDW\t320\t* 2\t; Index = 21 Token = 8\n\t\tDW\t320\t* 2\t; Index = 21 Token = 9\n\t\tDW\t320\t* 2\t; Index = 21 Token = 10\n\t\tDW\t320\t* 2\t; Index = 21 Token = 11\n\t\tDW\t368\t* 2\t; Index = 21 Token = 12\n\t\tDW\t400\t* 2\t; Index = 21 Token = 13\n\t\tDW\t432\t* 2\t; Index = 21 Token = 14\n\t\tDW\t464\t* 2\t; Index = 21 Token = 15\n\t\tDW\t336\t* 2\t; Index = 22 Token = 0\n\t\tDW\t336\t* 2\t; Index = 22 Token = 1\n\t\tDW\t336\t* 2\t; Index = 22 Token = 2\n\t\tDW\t336\t* 2\t; Index = 22 Token = 3\n\t\tDW\t384\t* 2\t; Index = 22 Token = 4\n\t\tDW\t416\t* 2\t; Index = 22 Token = 5\n\t\tDW\t448\t* 2\t; Index = 22 Token = 6\n\t\tDW\t480\t* 2\t; Index = 22 Token = 7\n\t\tDW\t336\t* 2\t; Index = 22 Token = 8\n\t\tDW\t336\t* 2\t; Index = 22 Token = 9\n\t\tDW\t336\t* 2\t; Index = 22 Token = 10\n\t\tDW\t336\t* 2\t; Index = 22 Token = 11\n\t\tDW\t384\t* 2\t; Index = 22 Token = 12\n\t\tDW\t416\t* 2\t; Index = 22 Token = 13\n\t\tDW\t448\t* 2\t; Index = 22 Token = 14\n\t\tDW\t480\t* 2\t; Index = 22 Token = 15\n\t\tDW\t352\t* 2\t; Index = 23 Token = 0\n\t\tDW\t352\t* 2\t; Index = 23 Token = 1\n\t\tDW\t352\t* 2\t; Index = 23 Token = 2\n\t\tDW\t352\t* 2\t; Index = 23 Token = 3\n\t\tDW\t400\t* 2\t; Index = 23 Token = 4\n\t\tDW\t432\t* 2\t; Index = 23 Token = 5\n\t\tDW\t464\t* 2\t; Index = 23 Token = 6\n\t\tDW\t496\t* 2\t; Index = 23 Token = 7\n\t\tDW\t352\t* 2\t; Index = 23 Token = 8\n\t\tDW\t352\t* 2\t; Index = 23 Token = 9\n\t\tDW\t352\t* 2\t; Index = 23 Token = 10\n\t\tDW\t352\t* 2\t; Index = 23 Token = 11\n\t\tDW\t400\t* 2\t; Index = 23 Token = 12\n\t\tDW\t432\t* 2\t; Index = 23 Token = 13\n\t\tDW\t464\t* 2\t; Index = 23 Token = 14\n\t\tDW\t496\t* 2\t; Index = 23 Token = 15\n\t\tDW\t368\t* 2\t; Index = 24 Token = 0\n\t\tDW\t368\t* 2\t; Index = 24 Token = 1\n\t\tDW\t368\t* 2\t; Index = 24 Token = 2\n\t\tDW\t368\t* 2\t; Index = 24 Token = 3\n\t\tDW\t416\t* 2\t; Index = 24 Token = 4\n\t\tDW\t448\t* 2\t; Index = 24 Token = 5\n\t\tDW\t480\t* 2\t; Index = 24 Token = 6\n\t\tDW\t512\t* 2\t; Index = 24 Token = 7\n\t\tDW\t368\t* 2\t; Index = 24 Token = 8\n\t\tDW\t368\t* 2\t; Index = 24 Token = 9\n\t\tDW\t368\t* 2\t; Index = 24 Token = 10\n\t\tDW\t368\t* 2\t; Index = 24 Token = 11\n\t\tDW\t416\t* 2\t; Index = 24 Token = 12\n\t\tDW\t448\t* 2\t; Index = 24 Token = 13\n\t\tDW\t480\t* 2\t; Index = 24 Token = 14\n\t\tDW\t512\t* 2\t; Index = 24 Token = 15\n\t\tDW\t384\t* 2\t; Index = 25 Token = 0\n\t\tDW\t384\t* 2\t; Index = 25 Token = 1\n\t\tDW\t384\t* 2\t; Index = 25 Token = 2\n\t\tDW\t384\t* 2\t; Index = 25 Token = 3\n\t\tDW\t432\t* 2\t; Index = 25 Token = 4\n\t\tDW\t464\t* 2\t; Index = 25 Token = 5\n\t\tDW\t496\t* 2\t; Index = 25 Token = 6\n\t\tDW\t528\t* 2\t; Index = 25 Token = 7\n\t\tDW\t384\t* 2\t; Index = 25 Token = 8\n\t\tDW\t384\t* 2\t; Index = 25 Token = 9\n\t\tDW\t384\t* 2\t; Index = 25 Token = 10\n\t\tDW\t384\t* 2\t; Index = 25 Token = 11\n\t\tDW\t432\t* 2\t; Index = 25 Token = 12\n\t\tDW\t464\t* 2\t; Index = 25 Token = 13\n\t\tDW\t496\t* 2\t; Index = 25 Token = 14\n\t\tDW\t528\t* 2\t; Index = 25 Token = 15\n\t\tDW\t400\t* 2\t; Index = 26 Token = 0\n\t\tDW\t400\t* 2\t; Index = 26 Token = 1\n\t\tDW\t400\t* 2\t; Index = 26 Token = 2\n\t\tDW\t400\t* 2\t; Index = 26 Token = 3\n\t\tDW\t448\t* 2\t; Index = 26 Token = 4\n\t\tDW\t480\t* 2\t; Index = 26 Token = 5\n\t\tDW\t512\t* 2\t; Index = 26 Token = 6\n\t\tDW\t544\t* 2\t; Index = 26 Token = 7\n\t\tDW\t400\t* 2\t; Index = 26 Token = 8\n\t\tDW\t400\t* 2\t; Index = 26 Token = 9\n\t\tDW\t400\t* 2\t; Index = 26 Token = 10\n\t\tDW\t400\t* 2\t; Index = 26 Token = 11\n\t\tDW\t448\t* 2\t; Index = 26 Token = 12\n\t\tDW\t480\t* 2\t; Index = 26 Token = 13\n\t\tDW\t512\t* 2\t; Index = 26 Token = 14\n\t\tDW\t544\t* 2\t; Index = 26 Token = 15\n\t\tDW\t416\t* 2\t; Index = 27 Token = 0\n\t\tDW\t416\t* 2\t; Index = 27 Token = 1\n\t\tDW\t416\t* 2\t; Index = 27 Token = 2\n\t\tDW\t416\t* 2\t; Index = 27 Token = 3\n\t\tDW\t464\t* 2\t; Index = 27 Token = 4\n\t\tDW\t496\t* 2\t; Index = 27 Token = 5\n\t\tDW\t528\t* 2\t; Index = 27 Token = 6\n\t\tDW\t560\t* 2\t; Index = 27 Token = 7\n\t\tDW\t416\t* 2\t; Index = 27 Token = 8\n\t\tDW\t416\t* 2\t; Index = 27 Token = 9\n\t\tDW\t416\t* 2\t; Index = 27 Token = 10\n\t\tDW\t416\t* 2\t; Index = 27 Token = 11\n\t\tDW\t464\t* 2\t; Index = 27 Token = 12\n\t\tDW\t496\t* 2\t; Index = 27 Token = 13\n\t\tDW\t528\t* 2\t; Index = 27 Token = 14\n\t\tDW\t560\t* 2\t; Index = 27 Token = 15\n\t\tDW\t432\t* 2\t; Index = 28 Token = 0\n\t\tDW\t432\t* 2\t; Index = 28 Token = 1\n\t\tDW\t432\t* 2\t; Index = 28 Token = 2\n\t\tDW\t432\t* 2\t; Index = 28 Token = 3\n\t\tDW\t480\t* 2\t; Index = 28 Token = 4\n\t\tDW\t512\t* 2\t; Index = 28 Token = 5\n\t\tDW\t544\t* 2\t; Index = 28 Token = 6\n\t\tDW\t576\t* 2\t; Index = 28 Token = 7\n\t\tDW\t432\t* 2\t; Index = 28 Token = 8\n\t\tDW\t432\t* 2\t; Index = 28 Token = 9\n\t\tDW\t432\t* 2\t; Index = 28 Token = 10\n\t\tDW\t432\t* 2\t; Index = 28 Token = 11\n\t\tDW\t480\t* 2\t; Index = 28 Token = 12\n\t\tDW\t512\t* 2\t; Index = 28 Token = 13\n\t\tDW\t544\t* 2\t; Index = 28 Token = 14\n\t\tDW\t576\t* 2\t; Index = 28 Token = 15\n\t\tDW\t448\t* 2\t; Index = 29 Token = 0\n\t\tDW\t448\t* 2\t; Index = 29 Token = 1\n\t\tDW\t448\t* 2\t; Index = 29 Token = 2\n\t\tDW\t448\t* 2\t; Index = 29 Token = 3\n\t\tDW\t496\t* 2\t; Index = 29 Token = 4\n\t\tDW\t528\t* 2\t; Index = 29 Token = 5\n\t\tDW\t560\t* 2\t; Index = 29 Token = 6\n\t\tDW\t592\t* 2\t; Index = 29 Token = 7\n\t\tDW\t448\t* 2\t; Index = 29 Token = 8\n\t\tDW\t448\t* 2\t; Index = 29 Token = 9\n\t\tDW\t448\t* 2\t; Index = 29 Token = 10\n\t\tDW\t448\t* 2\t; Index = 29 Token = 11\n\t\tDW\t496\t* 2\t; Index = 29 Token = 12\n\t\tDW\t528\t* 2\t; Index = 29 Token = 13\n\t\tDW\t560\t* 2\t; Index = 29 Token = 14\n\t\tDW\t592\t* 2\t; Index = 29 Token = 15\n\t\tDW\t464\t* 2\t; Index = 30 Token = 0\n\t\tDW\t464\t* 2\t; Index = 30 Token = 1\n\t\tDW\t464\t* 2\t; Index = 30 Token = 2\n\t\tDW\t464\t* 2\t; Index = 30 Token = 3\n\t\tDW\t512\t* 2\t; Index = 30 Token = 4\n\t\tDW\t544\t* 2\t; Index = 30 Token = 5\n\t\tDW\t576\t* 2\t; Index = 30 Token = 6\n\t\tDW\t608\t* 2\t; Index = 30 Token = 7\n\t\tDW\t464\t* 2\t; Index = 30 Token = 8\n\t\tDW\t464\t* 2\t; Index = 30 Token = 9\n\t\tDW\t464\t* 2\t; Index = 30 Token = 10\n\t\tDW\t464\t* 2\t; Index = 30 Token = 11\n\t\tDW\t512\t* 2\t; Index = 30 Token = 12\n\t\tDW\t544\t* 2\t; Index = 30 Token = 13\n\t\tDW\t576\t* 2\t; Index = 30 Token = 14\n\t\tDW\t608\t* 2\t; Index = 30 Token = 15\n\t\tDW\t480\t* 2\t; Index = 31 Token = 0\n\t\tDW\t480\t* 2\t; Index = 31 Token = 1\n\t\tDW\t480\t* 2\t; Index = 31 Token = 2\n\t\tDW\t480\t* 2\t; Index = 31 Token = 3\n\t\tDW\t528\t* 2\t; Index = 31 Token = 4\n\t\tDW\t560\t* 2\t; Index = 31 Token = 5\n\t\tDW\t592\t* 2\t; Index = 31 Token = 6\n\t\tDW\t624\t* 2\t; Index = 31 Token = 7\n\t\tDW\t480\t* 2\t; Index = 31 Token = 8\n\t\tDW\t480\t* 2\t; Index = 31 Token = 9\n\t\tDW\t480\t* 2\t; Index = 31 Token = 10\n\t\tDW\t480\t* 2\t; Index = 31 Token = 11\n\t\tDW\t528\t* 2\t; Index = 31 Token = 12\n\t\tDW\t560\t* 2\t; Index = 31 Token = 13\n\t\tDW\t592\t* 2\t; Index = 31 Token = 14\n\t\tDW\t624\t* 2\t; Index = 31 Token = 15\n\t\tDW\t496\t* 2\t; Index = 32 Token = 0\n\t\tDW\t496\t* 2\t; Index = 32 Token = 1\n\t\tDW\t496\t* 2\t; Index = 32 Token = 2\n\t\tDW\t496\t* 2\t; Index = 32 Token = 3\n\t\tDW\t544\t* 2\t; Index = 32 Token = 4\n\t\tDW\t576\t* 2\t; Index = 32 Token = 5\n\t\tDW\t608\t* 2\t; Index = 32 Token = 6\n\t\tDW\t640\t* 2\t; Index = 32 Token = 7\n\t\tDW\t496\t* 2\t; Index = 32 Token = 8\n\t\tDW\t496\t* 2\t; Index = 32 Token = 9\n\t\tDW\t496\t* 2\t; Index = 32 Token = 10\n\t\tDW\t496\t* 2\t; Index = 32 Token = 11\n\t\tDW\t544\t* 2\t; Index = 32 Token = 12\n\t\tDW\t576\t* 2\t; Index = 32 Token = 13\n\t\tDW\t608\t* 2\t; Index = 32 Token = 14\n\t\tDW\t640\t* 2\t; Index = 32 Token = 15\n\t\tDW\t512\t* 2\t; Index = 33 Token = 0\n\t\tDW\t512\t* 2\t; Index = 33 Token = 1\n\t\tDW\t512\t* 2\t; Index = 33 Token = 2\n\t\tDW\t512\t* 2\t; Index = 33 Token = 3\n\t\tDW\t560\t* 2\t; Index = 33 Token = 4\n\t\tDW\t592\t* 2\t; Index = 33 Token = 5\n\t\tDW\t624\t* 2\t; Index = 33 Token = 6\n\t\tDW\t656\t* 2\t; Index = 33 Token = 7\n\t\tDW\t512\t* 2\t; Index = 33 Token = 8\n\t\tDW\t512\t* 2\t; Index = 33 Token = 9\n\t\tDW\t512\t* 2\t; Index = 33 Token = 10\n\t\tDW\t512\t* 2\t; Index = 33 Token = 11\n\t\tDW\t560\t* 2\t; Index = 33 Token = 12\n\t\tDW\t592\t* 2\t; Index = 33 Token = 13\n\t\tDW\t624\t* 2\t; Index = 33 Token = 14\n\t\tDW\t656\t* 2\t; Index = 33 Token = 15\n\t\tDW\t528\t* 2\t; Index = 34 Token = 0\n\t\tDW\t528\t* 2\t; Index = 34 Token = 1\n\t\tDW\t528\t* 2\t; Index = 34 Token = 2\n\t\tDW\t528\t* 2\t; Index = 34 Token = 3\n\t\tDW\t576\t* 2\t; Index = 34 Token = 4\n\t\tDW\t608\t* 2\t; Index = 34 Token = 5\n\t\tDW\t640\t* 2\t; Index = 34 Token = 6\n\t\tDW\t672\t* 2\t; Index = 34 Token = 7\n\t\tDW\t528\t* 2\t; Index = 34 Token = 8\n\t\tDW\t528\t* 2\t; Index = 34 Token = 9\n\t\tDW\t528\t* 2\t; Index = 34 Token = 10\n\t\tDW\t528\t* 2\t; Index = 34 Token = 11\n\t\tDW\t576\t* 2\t; Index = 34 Token = 12\n\t\tDW\t608\t* 2\t; Index = 34 Token = 13\n\t\tDW\t640\t* 2\t; Index = 34 Token = 14\n\t\tDW\t672\t* 2\t; Index = 34 Token = 15\n\t\tDW\t544\t* 2\t; Index = 35 Token = 0\n\t\tDW\t544\t* 2\t; Index = 35 Token = 1\n\t\tDW\t544\t* 2\t; Index = 35 Token = 2\n\t\tDW\t544\t* 2\t; Index = 35 Token = 3\n\t\tDW\t592\t* 2\t; Index = 35 Token = 4\n\t\tDW\t624\t* 2\t; Index = 35 Token = 5\n\t\tDW\t656\t* 2\t; Index = 35 Token = 6\n\t\tDW\t688\t* 2\t; Index = 35 Token = 7\n\t\tDW\t544\t* 2\t; Index = 35 Token = 8\n\t\tDW\t544\t* 2\t; Index = 35 Token = 9\n\t\tDW\t544\t* 2\t; Index = 35 Token = 10\n\t\tDW\t544\t* 2\t; Index = 35 Token = 11\n\t\tDW\t592\t* 2\t; Index = 35 Token = 12\n\t\tDW\t624\t* 2\t; Index = 35 Token = 13\n\t\tDW\t656\t* 2\t; Index = 35 Token = 14\n\t\tDW\t688\t* 2\t; Index = 35 Token = 15\n\t\tDW\t560\t* 2\t; Index = 36 Token = 0\n\t\tDW\t560\t* 2\t; Index = 36 Token = 1\n\t\tDW\t560\t* 2\t; Index = 36 Token = 2\n\t\tDW\t560\t* 2\t; Index = 36 Token = 3\n\t\tDW\t608\t* 2\t; Index = 36 Token = 4\n\t\tDW\t640\t* 2\t; Index = 36 Token = 5\n\t\tDW\t672\t* 2\t; Index = 36 Token = 6\n\t\tDW\t704\t* 2\t; Index = 36 Token = 7\n\t\tDW\t560\t* 2\t; Index = 36 Token = 8\n\t\tDW\t560\t* 2\t; Index = 36 Token = 9\n\t\tDW\t560\t* 2\t; Index = 36 Token = 10\n\t\tDW\t560\t* 2\t; Index = 36 Token = 11\n\t\tDW\t608\t* 2\t; Index = 36 Token = 12\n\t\tDW\t640\t* 2\t; Index = 36 Token = 13\n\t\tDW\t672\t* 2\t; Index = 36 Token = 14\n\t\tDW\t704\t* 2\t; Index = 36 Token = 15\n\t\tDW\t576\t* 2\t; Index = 37 Token = 0\n\t\tDW\t576\t* 2\t; Index = 37 Token = 1\n\t\tDW\t576\t* 2\t; Index = 37 Token = 2\n\t\tDW\t576\t* 2\t; Index = 37 Token = 3\n\t\tDW\t624\t* 2\t; Index = 37 Token = 4\n\t\tDW\t656\t* 2\t; Index = 37 Token = 5\n\t\tDW\t688\t* 2\t; Index = 37 Token = 6\n\t\tDW\t720\t* 2\t; Index = 37 Token = 7\n\t\tDW\t576\t* 2\t; Index = 37 Token = 8\n\t\tDW\t576\t* 2\t; Index = 37 Token = 9\n\t\tDW\t576\t* 2\t; Index = 37 Token = 10\n\t\tDW\t576\t* 2\t; Index = 37 Token = 11\n\t\tDW\t624\t* 2\t; Index = 37 Token = 12\n\t\tDW\t656\t* 2\t; Index = 37 Token = 13\n\t\tDW\t688\t* 2\t; Index = 37 Token = 14\n\t\tDW\t720\t* 2\t; Index = 37 Token = 15\n\t\tDW\t592\t* 2\t; Index = 38 Token = 0\n\t\tDW\t592\t* 2\t; Index = 38 Token = 1\n\t\tDW\t592\t* 2\t; Index = 38 Token = 2\n\t\tDW\t592\t* 2\t; Index = 38 Token = 3\n\t\tDW\t640\t* 2\t; Index = 38 Token = 4\n\t\tDW\t672\t* 2\t; Index = 38 Token = 5\n\t\tDW\t704\t* 2\t; Index = 38 Token = 6\n\t\tDW\t736\t* 2\t; Index = 38 Token = 7\n\t\tDW\t592\t* 2\t; Index = 38 Token = 8\n\t\tDW\t592\t* 2\t; Index = 38 Token = 9\n\t\tDW\t592\t* 2\t; Index = 38 Token = 10\n\t\tDW\t592\t* 2\t; Index = 38 Token = 11\n\t\tDW\t640\t* 2\t; Index = 38 Token = 12\n\t\tDW\t672\t* 2\t; Index = 38 Token = 13\n\t\tDW\t704\t* 2\t; Index = 38 Token = 14\n\t\tDW\t736\t* 2\t; Index = 38 Token = 15\n\t\tDW\t608\t* 2\t; Index = 39 Token = 0\n\t\tDW\t608\t* 2\t; Index = 39 Token = 1\n\t\tDW\t608\t* 2\t; Index = 39 Token = 2\n\t\tDW\t608\t* 2\t; Index = 39 Token = 3\n\t\tDW\t656\t* 2\t; Index = 39 Token = 4\n\t\tDW\t688\t* 2\t; Index = 39 Token = 5\n\t\tDW\t720\t* 2\t; Index = 39 Token = 6\n\t\tDW\t752\t* 2\t; Index = 39 Token = 7\n\t\tDW\t608\t* 2\t; Index = 39 Token = 8\n\t\tDW\t608\t* 2\t; Index = 39 Token = 9\n\t\tDW\t608\t* 2\t; Index = 39 Token = 10\n\t\tDW\t608\t* 2\t; Index = 39 Token = 11\n\t\tDW\t656\t* 2\t; Index = 39 Token = 12\n\t\tDW\t688\t* 2\t; Index = 39 Token = 13\n\t\tDW\t720\t* 2\t; Index = 39 Token = 14\n\t\tDW\t752\t* 2\t; Index = 39 Token = 15\n\t\tDW\t624\t* 2\t; Index = 40 Token = 0\n\t\tDW\t624\t* 2\t; Index = 40 Token = 1\n\t\tDW\t624\t* 2\t; Index = 40 Token = 2\n\t\tDW\t624\t* 2\t; Index = 40 Token = 3\n\t\tDW\t672\t* 2\t; Index = 40 Token = 4\n\t\tDW\t704\t* 2\t; Index = 40 Token = 5\n\t\tDW\t736\t* 2\t; Index = 40 Token = 6\n\t\tDW\t768\t* 2\t; Index = 40 Token = 7\n\t\tDW\t624\t* 2\t; Index = 40 Token = 8\n\t\tDW\t624\t* 2\t; Index = 40 Token = 9\n\t\tDW\t624\t* 2\t; Index = 40 Token = 10\n\t\tDW\t624\t* 2\t; Index = 40 Token = 11\n\t\tDW\t672\t* 2\t; Index = 40 Token = 12\n\t\tDW\t704\t* 2\t; Index = 40 Token = 13\n\t\tDW\t736\t* 2\t; Index = 40 Token = 14\n\t\tDW\t768\t* 2\t; Index = 40 Token = 15\n\t\tDW\t640\t* 2\t; Index = 41 Token = 0\n\t\tDW\t640\t* 2\t; Index = 41 Token = 1\n\t\tDW\t640\t* 2\t; Index = 41 Token = 2\n\t\tDW\t640\t* 2\t; Index = 41 Token = 3\n\t\tDW\t688\t* 2\t; Index = 41 Token = 4\n\t\tDW\t720\t* 2\t; Index = 41 Token = 5\n\t\tDW\t752\t* 2\t; Index = 41 Token = 6\n\t\tDW\t784\t* 2\t; Index = 41 Token = 7\n\t\tDW\t640\t* 2\t; Index = 41 Token = 8\n\t\tDW\t640\t* 2\t; Index = 41 Token = 9\n\t\tDW\t640\t* 2\t; Index = 41 Token = 10\n\t\tDW\t640\t* 2\t; Index = 41 Token = 11\n\t\tDW\t688\t* 2\t; Index = 41 Token = 12\n\t\tDW\t720\t* 2\t; Index = 41 Token = 13\n\t\tDW\t752\t* 2\t; Index = 41 Token = 14\n\t\tDW\t784\t* 2\t; Index = 41 Token = 15\n\t\tDW\t656\t* 2\t; Index = 42 Token = 0\n\t\tDW\t656\t* 2\t; Index = 42 Token = 1\n\t\tDW\t656\t* 2\t; Index = 42 Token = 2\n\t\tDW\t656\t* 2\t; Index = 42 Token = 3\n\t\tDW\t704\t* 2\t; Index = 42 Token = 4\n\t\tDW\t736\t* 2\t; Index = 42 Token = 5\n\t\tDW\t768\t* 2\t; Index = 42 Token = 6\n\t\tDW\t800\t* 2\t; Index = 42 Token = 7\n\t\tDW\t656\t* 2\t; Index = 42 Token = 8\n\t\tDW\t656\t* 2\t; Index = 42 Token = 9\n\t\tDW\t656\t* 2\t; Index = 42 Token = 10\n\t\tDW\t656\t* 2\t; Index = 42 Token = 11\n\t\tDW\t704\t* 2\t; Index = 42 Token = 12\n\t\tDW\t736\t* 2\t; Index = 42 Token = 13\n\t\tDW\t768\t* 2\t; Index = 42 Token = 14\n\t\tDW\t800\t* 2\t; Index = 42 Token = 15\n\t\tDW\t672\t* 2\t; Index = 43 Token = 0\n\t\tDW\t672\t* 2\t; Index = 43 Token = 1\n\t\tDW\t672\t* 2\t; Index = 43 Token = 2\n\t\tDW\t672\t* 2\t; Index = 43 Token = 3\n\t\tDW\t720\t* 2\t; Index = 43 Token = 4\n\t\tDW\t752\t* 2\t; Index = 43 Token = 5\n\t\tDW\t784\t* 2\t; Index = 43 Token = 6\n\t\tDW\t816\t* 2\t; Index = 43 Token = 7\n\t\tDW\t672\t* 2\t; Index = 43 Token = 8\n\t\tDW\t672\t* 2\t; Index = 43 Token = 9\n\t\tDW\t672\t* 2\t; Index = 43 Token = 10\n\t\tDW\t672\t* 2\t; Index = 43 Token = 11\n\t\tDW\t720\t* 2\t; Index = 43 Token = 12\n\t\tDW\t752\t* 2\t; Index = 43 Token = 13\n\t\tDW\t784\t* 2\t; Index = 43 Token = 14\n\t\tDW\t816\t* 2\t; Index = 43 Token = 15\n\t\tDW\t688\t* 2\t; Index = 44 Token = 0\n\t\tDW\t688\t* 2\t; Index = 44 Token = 1\n\t\tDW\t688\t* 2\t; Index = 44 Token = 2\n\t\tDW\t688\t* 2\t; Index = 44 Token = 3\n\t\tDW\t736\t* 2\t; Index = 44 Token = 4\n\t\tDW\t768\t* 2\t; Index = 44 Token = 5\n\t\tDW\t800\t* 2\t; Index = 44 Token = 6\n\t\tDW\t832\t* 2\t; Index = 44 Token = 7\n\t\tDW\t688\t* 2\t; Index = 44 Token = 8\n\t\tDW\t688\t* 2\t; Index = 44 Token = 9\n\t\tDW\t688\t* 2\t; Index = 44 Token = 10\n\t\tDW\t688\t* 2\t; Index = 44 Token = 11\n\t\tDW\t736\t* 2\t; Index = 44 Token = 12\n\t\tDW\t768\t* 2\t; Index = 44 Token = 13\n\t\tDW\t800\t* 2\t; Index = 44 Token = 14\n\t\tDW\t832\t* 2\t; Index = 44 Token = 15\n\t\tDW\t704\t* 2\t; Index = 45 Token = 0\n\t\tDW\t704\t* 2\t; Index = 45 Token = 1\n\t\tDW\t704\t* 2\t; Index = 45 Token = 2\n\t\tDW\t704\t* 2\t; Index = 45 Token = 3\n\t\tDW\t752\t* 2\t; Index = 45 Token = 4\n\t\tDW\t784\t* 2\t; Index = 45 Token = 5\n\t\tDW\t816\t* 2\t; Index = 45 Token = 6\n\t\tDW\t848\t* 2\t; Index = 45 Token = 7\n\t\tDW\t704\t* 2\t; Index = 45 Token = 8\n\t\tDW\t704\t* 2\t; Index = 45 Token = 9\n\t\tDW\t704\t* 2\t; Index = 45 Token = 10\n\t\tDW\t704\t* 2\t; Index = 45 Token = 11\n\t\tDW\t752\t* 2\t; Index = 45 Token = 12\n\t\tDW\t784\t* 2\t; Index = 45 Token = 13\n\t\tDW\t816\t* 2\t; Index = 45 Token = 14\n\t\tDW\t848\t* 2\t; Index = 45 Token = 15\n\t\tDW\t720\t* 2\t; Index = 46 Token = 0\n\t\tDW\t720\t* 2\t; Index = 46 Token = 1\n\t\tDW\t720\t* 2\t; Index = 46 Token = 2\n\t\tDW\t720\t* 2\t; Index = 46 Token = 3\n\t\tDW\t768\t* 2\t; Index = 46 Token = 4\n\t\tDW\t800\t* 2\t; Index = 46 Token = 5\n\t\tDW\t832\t* 2\t; Index = 46 Token = 6\n\t\tDW\t864\t* 2\t; Index = 46 Token = 7\n\t\tDW\t720\t* 2\t; Index = 46 Token = 8\n\t\tDW\t720\t* 2\t; Index = 46 Token = 9\n\t\tDW\t720\t* 2\t; Index = 46 Token = 10\n\t\tDW\t720\t* 2\t; Index = 46 Token = 11\n\t\tDW\t768\t* 2\t; Index = 46 Token = 12\n\t\tDW\t800\t* 2\t; Index = 46 Token = 13\n\t\tDW\t832\t* 2\t; Index = 46 Token = 14\n\t\tDW\t864\t* 2\t; Index = 46 Token = 15\n\t\tDW\t736\t* 2\t; Index = 47 Token = 0\n\t\tDW\t736\t* 2\t; Index = 47 Token = 1\n\t\tDW\t736\t* 2\t; Index = 47 Token = 2\n\t\tDW\t736\t* 2\t; Index = 47 Token = 3\n\t\tDW\t784\t* 2\t; Index = 47 Token = 4\n\t\tDW\t816\t* 2\t; Index = 47 Token = 5\n\t\tDW\t848\t* 2\t; Index = 47 Token = 6\n\t\tDW\t880\t* 2\t; Index = 47 Token = 7\n\t\tDW\t736\t* 2\t; Index = 47 Token = 8\n\t\tDW\t736\t* 2\t; Index = 47 Token = 9\n\t\tDW\t736\t* 2\t; Index = 47 Token = 10\n\t\tDW\t736\t* 2\t; Index = 47 Token = 11\n\t\tDW\t784\t* 2\t; Index = 47 Token = 12\n\t\tDW\t816\t* 2\t; Index = 47 Token = 13\n\t\tDW\t848\t* 2\t; Index = 47 Token = 14\n\t\tDW\t880\t* 2\t; Index = 47 Token = 15\n\t\tDW\t752\t* 2\t; Index = 48 Token = 0\n\t\tDW\t752\t* 2\t; Index = 48 Token = 1\n\t\tDW\t752\t* 2\t; Index = 48 Token = 2\n\t\tDW\t752\t* 2\t; Index = 48 Token = 3\n\t\tDW\t800\t* 2\t; Index = 48 Token = 4\n\t\tDW\t832\t* 2\t; Index = 48 Token = 5\n\t\tDW\t864\t* 2\t; Index = 48 Token = 6\n\t\tDW\t896\t* 2\t; Index = 48 Token = 7\n\t\tDW\t752\t* 2\t; Index = 48 Token = 8\n\t\tDW\t752\t* 2\t; Index = 48 Token = 9\n\t\tDW\t752\t* 2\t; Index = 48 Token = 10\n\t\tDW\t752\t* 2\t; Index = 48 Token = 11\n\t\tDW\t800\t* 2\t; Index = 48 Token = 12\n\t\tDW\t832\t* 2\t; Index = 48 Token = 13\n\t\tDW\t864\t* 2\t; Index = 48 Token = 14\n\t\tDW\t896\t* 2\t; Index = 48 Token = 15\n\t\tDW\t768\t* 2\t; Index = 49 Token = 0\n\t\tDW\t768\t* 2\t; Index = 49 Token = 1\n\t\tDW\t768\t* 2\t; Index = 49 Token = 2\n\t\tDW\t768\t* 2\t; Index = 49 Token = 3\n\t\tDW\t816\t* 2\t; Index = 49 Token = 4\n\t\tDW\t848\t* 2\t; Index = 49 Token = 5\n\t\tDW\t880\t* 2\t; Index = 49 Token = 6\n\t\tDW\t912\t* 2\t; Index = 49 Token = 7\n\t\tDW\t768\t* 2\t; Index = 49 Token = 8\n\t\tDW\t768\t* 2\t; Index = 49 Token = 9\n\t\tDW\t768\t* 2\t; Index = 49 Token = 10\n\t\tDW\t768\t* 2\t; Index = 49 Token = 11\n\t\tDW\t816\t* 2\t; Index = 49 Token = 12\n\t\tDW\t848\t* 2\t; Index = 49 Token = 13\n\t\tDW\t880\t* 2\t; Index = 49 Token = 14\n\t\tDW\t912\t* 2\t; Index = 49 Token = 15\n\t\tDW\t784\t* 2\t; Index = 50 Token = 0\n\t\tDW\t784\t* 2\t; Index = 50 Token = 1\n\t\tDW\t784\t* 2\t; Index = 50 Token = 2\n\t\tDW\t784\t* 2\t; Index = 50 Token = 3\n\t\tDW\t832\t* 2\t; Index = 50 Token = 4\n\t\tDW\t864\t* 2\t; Index = 50 Token = 5\n\t\tDW\t896\t* 2\t; Index = 50 Token = 6\n\t\tDW\t928\t* 2\t; Index = 50 Token = 7\n\t\tDW\t784\t* 2\t; Index = 50 Token = 8\n\t\tDW\t784\t* 2\t; Index = 50 Token = 9\n\t\tDW\t784\t* 2\t; Index = 50 Token = 10\n\t\tDW\t784\t* 2\t; Index = 50 Token = 11\n\t\tDW\t832\t* 2\t; Index = 50 Token = 12\n\t\tDW\t864\t* 2\t; Index = 50 Token = 13\n\t\tDW\t896\t* 2\t; Index = 50 Token = 14\n\t\tDW\t928\t* 2\t; Index = 50 Token = 15\n\t\tDW\t800\t* 2\t; Index = 51 Token = 0\n\t\tDW\t800\t* 2\t; Index = 51 Token = 1\n\t\tDW\t800\t* 2\t; Index = 51 Token = 2\n\t\tDW\t800\t* 2\t; Index = 51 Token = 3\n\t\tDW\t848\t* 2\t; Index = 51 Token = 4\n\t\tDW\t880\t* 2\t; Index = 51 Token = 5\n\t\tDW\t912\t* 2\t; Index = 51 Token = 6\n\t\tDW\t944\t* 2\t; Index = 51 Token = 7\n\t\tDW\t800\t* 2\t; Index = 51 Token = 8\n\t\tDW\t800\t* 2\t; Index = 51 Token = 9\n\t\tDW\t800\t* 2\t; Index = 51 Token = 10\n\t\tDW\t800\t* 2\t; Index = 51 Token = 11\n\t\tDW\t848\t* 2\t; Index = 51 Token = 12\n\t\tDW\t880\t* 2\t; Index = 51 Token = 13\n\t\tDW\t912\t* 2\t; Index = 51 Token = 14\n\t\tDW\t944\t* 2\t; Index = 51 Token = 15\n\t\tDW\t816\t* 2\t; Index = 52 Token = 0\n\t\tDW\t816\t* 2\t; Index = 52 Token = 1\n\t\tDW\t816\t* 2\t; Index = 52 Token = 2\n\t\tDW\t816\t* 2\t; Index = 52 Token = 3\n\t\tDW\t864\t* 2\t; Index = 52 Token = 4\n\t\tDW\t896\t* 2\t; Index = 52 Token = 5\n\t\tDW\t928\t* 2\t; Index = 52 Token = 6\n\t\tDW\t960\t* 2\t; Index = 52 Token = 7\n\t\tDW\t816\t* 2\t; Index = 52 Token = 8\n\t\tDW\t816\t* 2\t; Index = 52 Token = 9\n\t\tDW\t816\t* 2\t; Index = 52 Token = 10\n\t\tDW\t816\t* 2\t; Index = 52 Token = 11\n\t\tDW\t864\t* 2\t; Index = 52 Token = 12\n\t\tDW\t896\t* 2\t; Index = 52 Token = 13\n\t\tDW\t928\t* 2\t; Index = 52 Token = 14\n\t\tDW\t960\t* 2\t; Index = 52 Token = 15\n\t\tDW\t832\t* 2\t; Index = 53 Token = 0\n\t\tDW\t832\t* 2\t; Index = 53 Token = 1\n\t\tDW\t832\t* 2\t; Index = 53 Token = 2\n\t\tDW\t832\t* 2\t; Index = 53 Token = 3\n\t\tDW\t880\t* 2\t; Index = 53 Token = 4\n\t\tDW\t912\t* 2\t; Index = 53 Token = 5\n\t\tDW\t944\t* 2\t; Index = 53 Token = 6\n\t\tDW\t976\t* 2\t; Index = 53 Token = 7\n\t\tDW\t832\t* 2\t; Index = 53 Token = 8\n\t\tDW\t832\t* 2\t; Index = 53 Token = 9\n\t\tDW\t832\t* 2\t; Index = 53 Token = 10\n\t\tDW\t832\t* 2\t; Index = 53 Token = 11\n\t\tDW\t880\t* 2\t; Index = 53 Token = 12\n\t\tDW\t912\t* 2\t; Index = 53 Token = 13\n\t\tDW\t944\t* 2\t; Index = 53 Token = 14\n\t\tDW\t976\t* 2\t; Index = 53 Token = 15\n\t\tDW\t848\t* 2\t; Index = 54 Token = 0\n\t\tDW\t848\t* 2\t; Index = 54 Token = 1\n\t\tDW\t848\t* 2\t; Index = 54 Token = 2\n\t\tDW\t848\t* 2\t; Index = 54 Token = 3\n\t\tDW\t896\t* 2\t; Index = 54 Token = 4\n\t\tDW\t928\t* 2\t; Index = 54 Token = 5\n\t\tDW\t960\t* 2\t; Index = 54 Token = 6\n\t\tDW\t992\t* 2\t; Index = 54 Token = 7\n\t\tDW\t848\t* 2\t; Index = 54 Token = 8\n\t\tDW\t848\t* 2\t; Index = 54 Token = 9\n\t\tDW\t848\t* 2\t; Index = 54 Token = 10\n\t\tDW\t848\t* 2\t; Index = 54 Token = 11\n\t\tDW\t896\t* 2\t; Index = 54 Token = 12\n\t\tDW\t928\t* 2\t; Index = 54 Token = 13\n\t\tDW\t960\t* 2\t; Index = 54 Token = 14\n\t\tDW\t992\t* 2\t; Index = 54 Token = 15\n\t\tDW\t864\t* 2\t; Index = 55 Token = 0\n\t\tDW\t864\t* 2\t; Index = 55 Token = 1\n\t\tDW\t864\t* 2\t; Index = 55 Token = 2\n\t\tDW\t864\t* 2\t; Index = 55 Token = 3\n\t\tDW\t912\t* 2\t; Index = 55 Token = 4\n\t\tDW\t944\t* 2\t; Index = 55 Token = 5\n\t\tDW\t976\t* 2\t; Index = 55 Token = 6\n\t\tDW\t1008\t* 2\t; Index = 55 Token = 7\n\t\tDW\t864\t* 2\t; Index = 55 Token = 8\n\t\tDW\t864\t* 2\t; Index = 55 Token = 9\n\t\tDW\t864\t* 2\t; Index = 55 Token = 10\n\t\tDW\t864\t* 2\t; Index = 55 Token = 11\n\t\tDW\t912\t* 2\t; Index = 55 Token = 12\n\t\tDW\t944\t* 2\t; Index = 55 Token = 13\n\t\tDW\t976\t* 2\t; Index = 55 Token = 14\n\t\tDW\t1008\t* 2\t; Index = 55 Token = 15\n\t\tDW\t880\t* 2\t; Index = 56 Token = 0\n\t\tDW\t880\t* 2\t; Index = 56 Token = 1\n\t\tDW\t880\t* 2\t; Index = 56 Token = 2\n\t\tDW\t880\t* 2\t; Index = 56 Token = 3\n\t\tDW\t928\t* 2\t; Index = 56 Token = 4\n\t\tDW\t960\t* 2\t; Index = 56 Token = 5\n\t\tDW\t992\t* 2\t; Index = 56 Token = 6\n\t\tDW\t1024\t* 2\t; Index = 56 Token = 7\n\t\tDW\t880\t* 2\t; Index = 56 Token = 8\n\t\tDW\t880\t* 2\t; Index = 56 Token = 9\n\t\tDW\t880\t* 2\t; Index = 56 Token = 10\n\t\tDW\t880\t* 2\t; Index = 56 Token = 11\n\t\tDW\t928\t* 2\t; Index = 56 Token = 12\n\t\tDW\t960\t* 2\t; Index = 56 Token = 13\n\t\tDW\t992\t* 2\t; Index = 56 Token = 14\n\t\tDW\t1024\t* 2\t; Index = 56 Token = 15\n\t\tDW\t896\t* 2\t; Index = 57 Token = 0\n\t\tDW\t896\t* 2\t; Index = 57 Token = 1\n\t\tDW\t896\t* 2\t; Index = 57 Token = 2\n\t\tDW\t896\t* 2\t; Index = 57 Token = 3\n\t\tDW\t944\t* 2\t; Index = 57 Token = 4\n\t\tDW\t976\t* 2\t; Index = 57 Token = 5\n\t\tDW\t1008\t* 2\t; Index = 57 Token = 6\n\t\tDW\t1040\t* 2\t; Index = 57 Token = 7\n\t\tDW\t896\t* 2\t; Index = 57 Token = 8\n\t\tDW\t896\t* 2\t; Index = 57 Token = 9\n\t\tDW\t896\t* 2\t; Index = 57 Token = 10\n\t\tDW\t896\t* 2\t; Index = 57 Token = 11\n\t\tDW\t944\t* 2\t; Index = 57 Token = 12\n\t\tDW\t976\t* 2\t; Index = 57 Token = 13\n\t\tDW\t1008\t* 2\t; Index = 57 Token = 14\n\t\tDW\t1040\t* 2\t; Index = 57 Token = 15\n\t\tDW\t912\t* 2\t; Index = 58 Token = 0\n\t\tDW\t912\t* 2\t; Index = 58 Token = 1\n\t\tDW\t912\t* 2\t; Index = 58 Token = 2\n\t\tDW\t912\t* 2\t; Index = 58 Token = 3\n\t\tDW\t960\t* 2\t; Index = 58 Token = 4\n\t\tDW\t992\t* 2\t; Index = 58 Token = 5\n\t\tDW\t1024\t* 2\t; Index = 58 Token = 6\n\t\tDW\t1056\t* 2\t; Index = 58 Token = 7\n\t\tDW\t912\t* 2\t; Index = 58 Token = 8\n\t\tDW\t912\t* 2\t; Index = 58 Token = 9\n\t\tDW\t912\t* 2\t; Index = 58 Token = 10\n\t\tDW\t912\t* 2\t; Index = 58 Token = 11\n\t\tDW\t960\t* 2\t; Index = 58 Token = 12\n\t\tDW\t992\t* 2\t; Index = 58 Token = 13\n\t\tDW\t1024\t* 2\t; Index = 58 Token = 14\n\t\tDW\t1056\t* 2\t; Index = 58 Token = 15\n\t\tDW\t928\t* 2\t; Index = 59 Token = 0\n\t\tDW\t928\t* 2\t; Index = 59 Token = 1\n\t\tDW\t928\t* 2\t; Index = 59 Token = 2\n\t\tDW\t928\t* 2\t; Index = 59 Token = 3\n\t\tDW\t976\t* 2\t; Index = 59 Token = 4\n\t\tDW\t1008\t* 2\t; Index = 59 Token = 5\n\t\tDW\t1040\t* 2\t; Index = 59 Token = 6\n\t\tDW\t1072\t* 2\t; Index = 59 Token = 7\n\t\tDW\t928\t* 2\t; Index = 59 Token = 8\n\t\tDW\t928\t* 2\t; Index = 59 Token = 9\n\t\tDW\t928\t* 2\t; Index = 59 Token = 10\n\t\tDW\t928\t* 2\t; Index = 59 Token = 11\n\t\tDW\t976\t* 2\t; Index = 59 Token = 12\n\t\tDW\t1008\t* 2\t; Index = 59 Token = 13\n\t\tDW\t1040\t* 2\t; Index = 59 Token = 14\n\t\tDW\t1072\t* 2\t; Index = 59 Token = 15\n\t\tDW\t944\t* 2\t; Index = 60 Token = 0\n\t\tDW\t944\t* 2\t; Index = 60 Token = 1\n\t\tDW\t944\t* 2\t; Index = 60 Token = 2\n\t\tDW\t944\t* 2\t; Index = 60 Token = 3\n\t\tDW\t992\t* 2\t; Index = 60 Token = 4\n\t\tDW\t1024\t* 2\t; Index = 60 Token = 5\n\t\tDW\t1056\t* 2\t; Index = 60 Token = 6\n\t\tDW\t1088\t* 2\t; Index = 60 Token = 7\n\t\tDW\t944\t* 2\t; Index = 60 Token = 8\n\t\tDW\t944\t* 2\t; Index = 60 Token = 9\n\t\tDW\t944\t* 2\t; Index = 60 Token = 10\n\t\tDW\t944\t* 2\t; Index = 60 Token = 11\n\t\tDW\t992\t* 2\t; Index = 60 Token = 12\n\t\tDW\t1024\t* 2\t; Index = 60 Token = 13\n\t\tDW\t1056\t* 2\t; Index = 60 Token = 14\n\t\tDW\t1088\t* 2\t; Index = 60 Token = 15\n\t\tDW\t960\t* 2\t; Index = 61 Token = 0\n\t\tDW\t960\t* 2\t; Index = 61 Token = 1\n\t\tDW\t960\t* 2\t; Index = 61 Token = 2\n\t\tDW\t960\t* 2\t; Index = 61 Token = 3\n\t\tDW\t1008\t* 2\t; Index = 61 Token = 4\n\t\tDW\t1040\t* 2\t; Index = 61 Token = 5\n\t\tDW\t1072\t* 2\t; Index = 61 Token = 6\n\t\tDW\t1104\t* 2\t; Index = 61 Token = 7\n\t\tDW\t960\t* 2\t; Index = 61 Token = 8\n\t\tDW\t960\t* 2\t; Index = 61 Token = 9\n\t\tDW\t960\t* 2\t; Index = 61 Token = 10\n\t\tDW\t960\t* 2\t; Index = 61 Token = 11\n\t\tDW\t1008\t* 2\t; Index = 61 Token = 12\n\t\tDW\t1040\t* 2\t; Index = 61 Token = 13\n\t\tDW\t1072\t* 2\t; Index = 61 Token = 14\n\t\tDW\t1104\t* 2\t; Index = 61 Token = 15\n\t\tDW\t976\t* 2\t; Index = 62 Token = 0\n\t\tDW\t976\t* 2\t; Index = 62 Token = 1\n\t\tDW\t976\t* 2\t; Index = 62 Token = 2\n\t\tDW\t976\t* 2\t; Index = 62 Token = 3\n\t\tDW\t1024\t* 2\t; Index = 62 Token = 4\n\t\tDW\t1056\t* 2\t; Index = 62 Token = 5\n\t\tDW\t1088\t* 2\t; Index = 62 Token = 6\n\t\tDW\t1120\t* 2\t; Index = 62 Token = 7\n\t\tDW\t976\t* 2\t; Index = 62 Token = 8\n\t\tDW\t976\t* 2\t; Index = 62 Token = 9\n\t\tDW\t976\t* 2\t; Index = 62 Token = 10\n\t\tDW\t976\t* 2\t; Index = 62 Token = 11\n\t\tDW\t1024\t* 2\t; Index = 62 Token = 12\n\t\tDW\t1056\t* 2\t; Index = 62 Token = 13\n\t\tDW\t1088\t* 2\t; Index = 62 Token = 14\n\t\tDW\t1120\t* 2\t; Index = 62 Token = 15\n\t\tDW\t992\t* 2\t; Index = 63 Token = 0\n\t\tDW\t992\t* 2\t; Index = 63 Token = 1\n\t\tDW\t992\t* 2\t; Index = 63 Token = 2\n\t\tDW\t992\t* 2\t; Index = 63 Token = 3\n\t\tDW\t1040\t* 2\t; Index = 63 Token = 4\n\t\tDW\t1072\t* 2\t; Index = 63 Token = 5\n\t\tDW\t1104\t* 2\t; Index = 63 Token = 6\n\t\tDW\t1136\t* 2\t; Index = 63 Token = 7\n\t\tDW\t992\t* 2\t; Index = 63 Token = 8\n\t\tDW\t992\t* 2\t; Index = 63 Token = 9\n\t\tDW\t992\t* 2\t; Index = 63 Token = 10\n\t\tDW\t992\t* 2\t; Index = 63 Token = 11\n\t\tDW\t1040\t* 2\t; Index = 63 Token = 12\n\t\tDW\t1072\t* 2\t; Index = 63 Token = 13\n\t\tDW\t1104\t* 2\t; Index = 63 Token = 14\n\t\tDW\t1136\t* 2\t; Index = 63 Token = 15\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 0\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 1\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 2\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 3\n\t\tDW\t1056\t* 2\t; Index = 64 Token = 4\n\t\tDW\t1088\t* 2\t; Index = 64 Token = 5\n\t\tDW\t1120\t* 2\t; Index = 64 Token = 6\n\t\tDW\t1152\t* 2\t; Index = 64 Token = 7\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 8\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 9\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 10\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 11\n\t\tDW\t1056\t* 2\t; Index = 64 Token = 12\n\t\tDW\t1088\t* 2\t; Index = 64 Token = 13\n\t\tDW\t1120\t* 2\t; Index = 64 Token = 14\n\t\tDW\t1152\t* 2\t; Index = 64 Token = 15\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 0\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 1\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 2\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 3\n\t\tDW\t1072\t* 2\t; Index = 65 Token = 4\n\t\tDW\t1104\t* 2\t; Index = 65 Token = 5\n\t\tDW\t1136\t* 2\t; Index = 65 Token = 6\n\t\tDW\t1168\t* 2\t; Index = 65 Token = 7\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 8\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 9\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 10\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 11\n\t\tDW\t1072\t* 2\t; Index = 65 Token = 12\n\t\tDW\t1104\t* 2\t; Index = 65 Token = 13\n\t\tDW\t1136\t* 2\t; Index = 65 Token = 14\n\t\tDW\t1168\t* 2\t; Index = 65 Token = 15\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 0\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 1\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 2\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 3\n\t\tDW\t1088\t* 2\t; Index = 66 Token = 4\n\t\tDW\t1120\t* 2\t; Index = 66 Token = 5\n\t\tDW\t1152\t* 2\t; Index = 66 Token = 6\n\t\tDW\t1184\t* 2\t; Index = 66 Token = 7\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 8\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 9\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 10\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 11\n\t\tDW\t1088\t* 2\t; Index = 66 Token = 12\n\t\tDW\t1120\t* 2\t; Index = 66 Token = 13\n\t\tDW\t1152\t* 2\t; Index = 66 Token = 14\n\t\tDW\t1184\t* 2\t; Index = 66 Token = 15\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 0\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 1\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 2\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 3\n\t\tDW\t1104\t* 2\t; Index = 67 Token = 4\n\t\tDW\t1136\t* 2\t; Index = 67 Token = 5\n\t\tDW\t1168\t* 2\t; Index = 67 Token = 6\n\t\tDW\t1200\t* 2\t; Index = 67 Token = 7\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 8\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 9\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 10\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 11\n\t\tDW\t1104\t* 2\t; Index = 67 Token = 12\n\t\tDW\t1136\t* 2\t; Index = 67 Token = 13\n\t\tDW\t1168\t* 2\t; Index = 67 Token = 14\n\t\tDW\t1200\t* 2\t; Index = 67 Token = 15\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 0\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 1\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 2\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 3\n\t\tDW\t1120\t* 2\t; Index = 68 Token = 4\n\t\tDW\t1152\t* 2\t; Index = 68 Token = 5\n\t\tDW\t1184\t* 2\t; Index = 68 Token = 6\n\t\tDW\t1216\t* 2\t; Index = 68 Token = 7\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 8\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 9\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 10\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 11\n\t\tDW\t1120\t* 2\t; Index = 68 Token = 12\n\t\tDW\t1152\t* 2\t; Index = 68 Token = 13\n\t\tDW\t1184\t* 2\t; Index = 68 Token = 14\n\t\tDW\t1216\t* 2\t; Index = 68 Token = 15\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 0\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 1\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 2\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 3\n\t\tDW\t1136\t* 2\t; Index = 69 Token = 4\n\t\tDW\t1168\t* 2\t; Index = 69 Token = 5\n\t\tDW\t1200\t* 2\t; Index = 69 Token = 6\n\t\tDW\t1232\t* 2\t; Index = 69 Token = 7\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 8\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 9\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 10\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 11\n\t\tDW\t1136\t* 2\t; Index = 69 Token = 12\n\t\tDW\t1168\t* 2\t; Index = 69 Token = 13\n\t\tDW\t1200\t* 2\t; Index = 69 Token = 14\n\t\tDW\t1232\t* 2\t; Index = 69 Token = 15\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 0\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 1\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 2\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 3\n\t\tDW\t1152\t* 2\t; Index = 70 Token = 4\n\t\tDW\t1184\t* 2\t; Index = 70 Token = 5\n\t\tDW\t1216\t* 2\t; Index = 70 Token = 6\n\t\tDW\t1248\t* 2\t; Index = 70 Token = 7\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 8\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 9\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 10\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 11\n\t\tDW\t1152\t* 2\t; Index = 70 Token = 12\n\t\tDW\t1184\t* 2\t; Index = 70 Token = 13\n\t\tDW\t1216\t* 2\t; Index = 70 Token = 14\n\t\tDW\t1248\t* 2\t; Index = 70 Token = 15\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 0\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 1\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 2\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 3\n\t\tDW\t1168\t* 2\t; Index = 71 Token = 4\n\t\tDW\t1200\t* 2\t; Index = 71 Token = 5\n\t\tDW\t1232\t* 2\t; Index = 71 Token = 6\n\t\tDW\t1264\t* 2\t; Index = 71 Token = 7\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 8\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 9\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 10\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 11\n\t\tDW\t1168\t* 2\t; Index = 71 Token = 12\n\t\tDW\t1200\t* 2\t; Index = 71 Token = 13\n\t\tDW\t1232\t* 2\t; Index = 71 Token = 14\n\t\tDW\t1264\t* 2\t; Index = 71 Token = 15\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 0\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 1\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 2\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 3\n\t\tDW\t1184\t* 2\t; Index = 72 Token = 4\n\t\tDW\t1216\t* 2\t; Index = 72 Token = 5\n\t\tDW\t1248\t* 2\t; Index = 72 Token = 6\n\t\tDW\t1280\t* 2\t; Index = 72 Token = 7\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 8\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 9\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 10\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 11\n\t\tDW\t1184\t* 2\t; Index = 72 Token = 12\n\t\tDW\t1216\t* 2\t; Index = 72 Token = 13\n\t\tDW\t1248\t* 2\t; Index = 72 Token = 14\n\t\tDW\t1280\t* 2\t; Index = 72 Token = 15\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 0\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 1\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 2\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 3\n\t\tDW\t1200\t* 2\t; Index = 73 Token = 4\n\t\tDW\t1232\t* 2\t; Index = 73 Token = 5\n\t\tDW\t1264\t* 2\t; Index = 73 Token = 6\n\t\tDW\t1296\t* 2\t; Index = 73 Token = 7\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 8\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 9\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 10\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 11\n\t\tDW\t1200\t* 2\t; Index = 73 Token = 12\n\t\tDW\t1232\t* 2\t; Index = 73 Token = 13\n\t\tDW\t1264\t* 2\t; Index = 73 Token = 14\n\t\tDW\t1296\t* 2\t; Index = 73 Token = 15\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 0\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 1\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 2\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 3\n\t\tDW\t1216\t* 2\t; Index = 74 Token = 4\n\t\tDW\t1248\t* 2\t; Index = 74 Token = 5\n\t\tDW\t1280\t* 2\t; Index = 74 Token = 6\n\t\tDW\t1312\t* 2\t; Index = 74 Token = 7\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 8\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 9\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 10\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 11\n\t\tDW\t1216\t* 2\t; Index = 74 Token = 12\n\t\tDW\t1248\t* 2\t; Index = 74 Token = 13\n\t\tDW\t1280\t* 2\t; Index = 74 Token = 14\n\t\tDW\t1312\t* 2\t; Index = 74 Token = 15\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 0\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 1\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 2\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 3\n\t\tDW\t1232\t* 2\t; Index = 75 Token = 4\n\t\tDW\t1264\t* 2\t; Index = 75 Token = 5\n\t\tDW\t1296\t* 2\t; Index = 75 Token = 6\n\t\tDW\t1328\t* 2\t; Index = 75 Token = 7\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 8\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 9\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 10\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 11\n\t\tDW\t1232\t* 2\t; Index = 75 Token = 12\n\t\tDW\t1264\t* 2\t; Index = 75 Token = 13\n\t\tDW\t1296\t* 2\t; Index = 75 Token = 14\n\t\tDW\t1328\t* 2\t; Index = 75 Token = 15\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 0\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 1\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 2\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 3\n\t\tDW\t1248\t* 2\t; Index = 76 Token = 4\n\t\tDW\t1280\t* 2\t; Index = 76 Token = 5\n\t\tDW\t1312\t* 2\t; Index = 76 Token = 6\n\t\tDW\t1344\t* 2\t; Index = 76 Token = 7\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 8\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 9\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 10\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 11\n\t\tDW\t1248\t* 2\t; Index = 76 Token = 12\n\t\tDW\t1280\t* 2\t; Index = 76 Token = 13\n\t\tDW\t1312\t* 2\t; Index = 76 Token = 14\n\t\tDW\t1344\t* 2\t; Index = 76 Token = 15\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 0\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 1\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 2\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 3\n\t\tDW\t1264\t* 2\t; Index = 77 Token = 4\n\t\tDW\t1296\t* 2\t; Index = 77 Token = 5\n\t\tDW\t1328\t* 2\t; Index = 77 Token = 6\n\t\tDW\t1360\t* 2\t; Index = 77 Token = 7\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 8\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 9\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 10\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 11\n\t\tDW\t1264\t* 2\t; Index = 77 Token = 12\n\t\tDW\t1296\t* 2\t; Index = 77 Token = 13\n\t\tDW\t1328\t* 2\t; Index = 77 Token = 14\n\t\tDW\t1360\t* 2\t; Index = 77 Token = 15\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 0\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 1\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 2\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 3\n\t\tDW\t1280\t* 2\t; Index = 78 Token = 4\n\t\tDW\t1312\t* 2\t; Index = 78 Token = 5\n\t\tDW\t1344\t* 2\t; Index = 78 Token = 6\n\t\tDW\t1376\t* 2\t; Index = 78 Token = 7\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 8\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 9\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 10\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 11\n\t\tDW\t1280\t* 2\t; Index = 78 Token = 12\n\t\tDW\t1312\t* 2\t; Index = 78 Token = 13\n\t\tDW\t1344\t* 2\t; Index = 78 Token = 14\n\t\tDW\t1376\t* 2\t; Index = 78 Token = 15\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 0\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 1\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 2\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 3\n\t\tDW\t1296\t* 2\t; Index = 79 Token = 4\n\t\tDW\t1328\t* 2\t; Index = 79 Token = 5\n\t\tDW\t1360\t* 2\t; Index = 79 Token = 6\n\t\tDW\t1392\t* 2\t; Index = 79 Token = 7\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 8\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 9\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 10\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 11\n\t\tDW\t1296\t* 2\t; Index = 79 Token = 12\n\t\tDW\t1328\t* 2\t; Index = 79 Token = 13\n\t\tDW\t1360\t* 2\t; Index = 79 Token = 14\n\t\tDW\t1392\t* 2\t; Index = 79 Token = 15\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 0\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 1\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 2\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 3\n\t\tDW\t1312\t* 2\t; Index = 80 Token = 4\n\t\tDW\t1344\t* 2\t; Index = 80 Token = 5\n\t\tDW\t1376\t* 2\t; Index = 80 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 80 Token = 7\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 8\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 9\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 10\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 11\n\t\tDW\t1312\t* 2\t; Index = 80 Token = 12\n\t\tDW\t1344\t* 2\t; Index = 80 Token = 13\n\t\tDW\t1376\t* 2\t; Index = 80 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 80 Token = 15\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 0\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 1\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 2\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 3\n\t\tDW\t1328\t* 2\t; Index = 81 Token = 4\n\t\tDW\t1360\t* 2\t; Index = 81 Token = 5\n\t\tDW\t1392\t* 2\t; Index = 81 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 81 Token = 7\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 8\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 9\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 10\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 11\n\t\tDW\t1328\t* 2\t; Index = 81 Token = 12\n\t\tDW\t1360\t* 2\t; Index = 81 Token = 13\n\t\tDW\t1392\t* 2\t; Index = 81 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 81 Token = 15\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 0\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 1\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 2\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 3\n\t\tDW\t1344\t* 2\t; Index = 82 Token = 4\n\t\tDW\t1376\t* 2\t; Index = 82 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 7\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 8\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 9\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 10\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 11\n\t\tDW\t1344\t* 2\t; Index = 82 Token = 12\n\t\tDW\t1376\t* 2\t; Index = 82 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 15\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 0\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 1\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 2\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 3\n\t\tDW\t1360\t* 2\t; Index = 83 Token = 4\n\t\tDW\t1392\t* 2\t; Index = 83 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 7\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 8\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 9\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 10\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 11\n\t\tDW\t1360\t* 2\t; Index = 83 Token = 12\n\t\tDW\t1392\t* 2\t; Index = 83 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 15\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 0\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 1\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 2\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 3\n\t\tDW\t1376\t* 2\t; Index = 84 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 7\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 8\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 9\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 10\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 11\n\t\tDW\t1376\t* 2\t; Index = 84 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 15\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 0\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 1\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 2\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 3\n\t\tDW\t1392\t* 2\t; Index = 85 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 7\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 8\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 9\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 10\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 11\n\t\tDW\t1392\t* 2\t; Index = 85 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 15\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 0\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 1\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 2\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 7\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 8\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 9\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 10\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 15\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 0\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 1\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 2\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 7\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 8\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 9\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 10\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 15\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 0\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 1\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 2\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 7\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 8\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 9\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 10\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 15\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = AUDIO\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS = \t\t\t\t&\n\t\tsoundio.obj\t\t&\n\t\tsoundint.obj\t&\n\t\tsoundlck.obj\t&\n\t\tsoscodec.obj\t&\n                olsosdec.obj    &\n\t\tauduncmp.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.lib  $(%WIN32LIB)\\lib\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t copy *.lib $(%WIN32LIB)\\lib\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\tcopy *.386 test\n\n#**************************** End of makefile ******************************\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = audio\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t\tsoundio.obj\t\t\\\n\t\t\t\tsoundint.obj\t\\\n\t\t\t\tsoundlck.obj\t\\\n\t\t\t\tsoscodec.obj\t\\\n\t\t\t\tauduncmp.obj\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) \n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n +-soundio.obj\t\t&\n+-soundint.obj\t\t&\n+-soundlck.obj\t\t&\n+-soscodec.obj\t\t&\n+-auduncmp.obj\t\n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = audio\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t\tsoundio.obj\t\t\\\n\t\t\t\tsoundint.obj\t\\\n\t\t\t\tsoundlck.obj\t\\\n\t\t\t\tsoscodec.obj\t\\\n\t\t\t\tauduncmp.obj\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) \n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n +-soundio.obj\t\t&\n+-soundint.obj\t\t&\n+-soundlck.obj\t\t&\n+-soscodec.obj\t\t&\n+-auduncmp.obj\t\n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/NYBBTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* bNybbleTablexxxx - ADPCM Lookup table for nybbles\n;****************************************************************************\n\n\t\talign\t4\n\nbNybbleTableLow\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\n\t\talign 4\n\nbNybbleTableHigh\tDB\t00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2\n\t\tDB\t01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2\n\t\tDB\t02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2\n\t\tDB\t03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2\n\t\tDB\t04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2\n\t\tDB\t05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2\n\t\tDB\t06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2\n\t\tDB\t07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2\n\t\tDB\t08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2\n\t\tDB\t09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2\n\t\tDB\t0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2\n\t\tDB\t0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2\n\t\tDB\t0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2\n\t\tDB\t0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2\n\t\tDB\t0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2\n\t\tDB\t0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/OLSOSDEC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*          Copyright (c) 1994, HMI, INC. All Rights Reserved\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     soscodec.asm\n;*\n;* DESCRIPTION\n;*     HMI SOS ADPCM compression/decompression.\n;*\n;* PROGRAMMER\n;*     Nick Skrepetos\n;*     Denzil E. Long, Jr. (Fixed bugs, rewrote for watcom)\n;*\t   Bill Petro\t\t   (Added stereo support)\n;* DATE\n;*     Febuary 15, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\n\nDPMI_INTR\t\tequ\t31h\nIF_LOCKED_PM_CODE\tequ\t1h\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t2h\t\t; Locked PM code for DPMI.\n\n\tSTRUC\tsCompInfo\nlpSource\t\tDD\t?\t;Compressed data pointer\nlpDest\t\t\tDD\t?\t;Uncompressed data pointer\ndwCompSize\t\tDD\t?\t;Compressed size\ndwUnCompSize\t\tDD\t?\t;Uncompressed size\n\ndwSampleIndex\t\tDD\t?\t;Index into sample\ndwPredicted\t\tDD\t?\t;Next predicted value\ndwDifference\t\tDD\t?\t;Difference from last sample\nwCodeBuf\t\tDW\t?\t;Holds 2 nibbles for decompression\nwCode\t\t\tDW\t?\t;Current 4 bit code\nwStep\t\t\tDW\t?\t;Step value in table\nwIndex\t\t\tDW\t?\t;Index into step table\n\ndwSampleIndex2\t\tDD\t?\t;Index into sample\ndwPredicted2\t\tDD\t?\t;Next predicted value\ndwDifference2\t\tDD\t?\t;Difference from last sample\nwCodeBuf2 \t\tDW\t?\t;Holds 2 nibbles for decompression\nwCode2\t\t\tDW\t?\t;Current 4 bit code\nwStep2\t\t\tDW\t?\t;Step value in table\nwIndex2\t\tDW\t?\t;Index into step table\n\nwBitSize\t\tDW\t?\t;Bit size for decompression\nwChannels\t\tDW\t?    \t;number of channels\n\tENDS\tsCompInfo\n\n\tDATASEG\n\n\nInitFlags\tDD\t0\t\t; Flags to indicate what has been initialized.\n\n\nLABEL\tLockedDataStart\tBYTE\n\n;* Index table for stepping into step table\n\nwCODECIndexTab\tDW\t-1,-1,-1,-1,2,4,6,8\n\t\tDW\t-1,-1,-1,-1,2,4,6,8\n\n\n;Lookup table of replacement values\n;The actual sound value is replaced with an index to lookup in this table\n;The index only takes up a nibble(4bits) and represents an int(16bits)\n;Essentially:\n;Get a value\n;compare it with the value before it\n;find closest value in table and store the index into the table\n;if i'm going down then negitize it\n;go to next byte.\n\n;Theory for stereo:\n;1)handle stereo and mono in two seperate loops. cleaner...\n;start at byte 0 and skip every other byte(or word) both write and read\n;when we get done\n;\tset start byte to 1 and do it again\n\n\n\n\n;This table essentialy round off to closes values in 3 distinct bands\n; precalculated and optimized(i guess) for human hearing.\n\nwCODECStepTab\tDW\t7,  \t8,  \t9,   \t10,   \t11,  \t12,   \t13,14\n\tDW\t16, \t17, \t19, \t21,  \t23,   \t25,  \t28,   \t31\n\tDW\t34, \t37, \t41, \t45,  \t50,   \t55,  \t60,   \t66\n\tDW\t73, \t80, \t88, \t97,  \t107,  \t118, \t130,  \t143\n\tDW\t157,\t173,\t190,\t209, \t230,  \t253, \t279,  \t307\n\tDW\t337,\t371,\t408,\t449, \t494,  \t544, \t598,  \t658\n\tDW\t724,\t796,\t876,\t963, \t1060,\t1166,\t1282,\t1411\n\tDW\t1552,\t1707,\t1878,\t2066,\t2272,\t2499,\t2749,\t3024\n\tDW\t3327,\t3660,\t4026,\t4428,\t4871,\t5358,\t5894,\t6484\n\tDW\t7132,\t7845,\t8630,\t9493,\t10442,\t11487,\t12635,\t13899\n\tDW\t15289,\t16818,\t18500,\t20350,\t22385,\t24623,\t27086,\t29794\n\tDW\t32767\n\n;dwCODECByteIndex\t\tDD\t0 ; this is when to stop compressing\n;dwCODECTempStep\t\tDD\t0 ; tempory storage for step value\n;wCODECMask\t\t\tDW\t0 ; Current mask\n\nLABEL\tLockedDataEnd\tBYTE\n\n\n\tCODESEG\n\nLABEL\tLockedCodeStart\tBYTE\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECInitStream - Initialize compression stream.\n;*\n;* SYNOPSIS\n;*     sosCODECInitStream(CompInfo)\n;*\n;*     void sosCODECInitStream(_SOS_COMPRESS_INFO *);\n;*\n;* FUNCTION\n;*     Initialize compression stream for compression and decompression.\n;*\n;* INPUTS\n;*     CompInfo - Compression information structure.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC sosCODECInitStream:NEAR\n\tPROC\tsosCODECInitStream C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\n\tmov\teax,[sSOSInfo]\n\tmov\t[(sCompInfo eax).wIndex],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).wStep],7  \t\t; start with a step of 7\n\tmov\t[(sCompInfo eax).dwPredicted],0 \t; no predicted value\n\tmov\t[(sCompInfo eax).dwSampleIndex],0\t;start at head of index\n\tmov\t[(sCompInfo eax).wIndex2],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).wStep2],7  \t\t; start with a step of 7\n\tmov\t[(sCompInfo eax).dwPredicted2],0 \t; no predicted value\n\tmov\t[(sCompInfo eax).dwSampleIndex2],0 \t;start at head of index\n\tret\n\n\tENDP\tsosCODECInitStream\n\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECDecompressData - Decompress audio data.\n;*\n;* SYNOPSIS\n;*     Size = sosCODECDecompressData(CompInfo, NumBytes)\n;*\n;*     long sosCODECDecompressData(_SOS_COMPRESS_INFO *, long);\n;*\n;* FUNCTION\n;*     Decompress data from a 4:1 ADPCM compressed stream. The number of\n;*     bytes decompressed is returned.\n;*\n;* INPUTS\n;*     CompInfo - Compress information structure.\n;*     NumBytes - Number of bytes to compress.\n;*\n;* RESULT\n;*     Size - Size of decompressed data.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC General_sosCODECDecompressData:NEAR\n\tPROC\tGeneral_sosCODECDecompressData C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\tARG\twBytes:DWORD\n\n\tlocal\tdwCODECBytesProcessed:dword             ;bytes to decompress\n\tlocal\tdwCODECByteIndex:dword\t\t\t;this is when to stop compressing\n\t\t\t\t\t\t\t; these need to be local if the function is to be reenterant\n\tpush\tesi\n\tpush\tedi\n\tpush\tebx\n\tpush\tecx\n\tpush\tedx\n\n;*---------------------------------------------------------------------------\n;*\tInitialize\n;*---------------------------------------------------------------------------\n\n\tmov\tebx,[sSOSInfo]\n\tmov\teax,[wBytes]\n\tmov\t[dwCODECBytesProcessed],eax\n\tmov\t[(sCompInfo ebx).dwSampleIndex],0 \t;start at head of index\n\tmov\t[(sCompInfo ebx).dwSampleIndex2],0 \t;start at head of index\n\n\t\t\t\t\t\t\t;Check for 16 bit decompression\n\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??skipByteDivide\n\n\tshr\teax,1\t;Divide size by two\n\n??skipByteDivide:\n\tmov\t[dwCODECByteIndex],eax\n\tmov\tesi,[(sCompInfo ebx).lpSource]\n\tmov\tedi,[(sCompInfo ebx).lpDest]\n\tcmp\t[(sCompInfo ebx).wChannels],2\t\t;stereo check\n\tje\t??mainloopl\t\t\t\t;do left side first\n\n;\tDetermine if sample index is even or odd. This will determine\n;\tif we need to get a new token or not.\n\n;---------------------------------------------------------------------------\n;Main Mono Loop\n;---------------------------------------------------------------------------\n\n\n\n??mainloop:\n\ttest\t[(sCompInfo ebx).dwSampleIndex],1\t;odd ??\n\tje\tshort ??fetchToken\t\t\t; if so get new token\n\txor\teax,eax\t\t\t\t\t;else shift int codebuf\n\tmov\tax,[(sCompInfo ebx).wCodeBuf]\t\t;ored with Code\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\tjmp\tshort ??calcDifference\n\n??fetchToken:\n\txor\teax,eax\t\t\t\t\t;get a new token\n\tmov\tal,[esi]\t\t\t\t;put in codebuf\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\n\tinc\tesi\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\t\t;and then code\n\n??calcDifference:\n\tmov\t[(sCompInfo ebx).dwDifference],0\t;reset diff\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep]\t\t;cx is step value\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4\n\tadd\t[(sCompInfo ebx).dwDifference],ecx\t;Add wStep\n\n??no4:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no2:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no1:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8\n\tneg\t[(sCompInfo ebx).dwDifference]\t\t;Negate diff\n\n??no8:\n\t; add difference to predicted value.\n\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\n\tadd\teax,[(sCompInfo ebx).dwDifference]\n\n\t; make sure there is no under or  overflow.\n\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflow\n\tmov\teax,7FFFh\n\n??noOverflow:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflow\n\tmov\teax,0FFFF8000h\n\n??noUnderflow:\n\tmov\t[(sCompInfo ebx).dwPredicted],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bit\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,2\n\tjmp\tshort ??adjustIndex\n\n??output8Bit:\n\t; output 8 bit sample\n\n\txor\tah,80h\n\tmov\t[edi],ah\n\tinc\tedi\n\n??adjustIndex:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex],ax \t\t;check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex],8000h\n\tjb\tshort ??checkOverflow\n\tmov\t[(sCompInfo ebx).wIndex],0\t\t;reset index to zero\n\tjmp\tshort ??adjustStep\n\n??checkOverflow:\n\tcmp\t[(sCompInfo ebx).wIndex],88\t\t;check if wIndex > 88\n\tjbe\tshort ??adjustStep\n\tmov\t[(sCompInfo ebx).wIndex],88\t\t;reset index to 88\n\n??adjustStep:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex],1\n\tmov\t[(sCompInfo ebx).wStep],ax\n\n\t; decrement bytes processed and loop back.\n\n\tdec\t[dwCODECByteIndex]\n\tjne\t??mainloop\n\tjmp\t??exitout\n\n;--------------------------------------------------------------------------\n;Left Channel Start\n;--------------------------------------------------------------------------\n\n\n??mainloopl:\n\ttest\t[(sCompInfo ebx).dwSampleIndex],1\n\tje\tshort ??fetchTokenl\n\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCodeBuf]\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\tjmp\tshort ??calcDifferencel\n\n??fetchTokenl:\n\txor\teax,eax\n\tmov\tal,[esi]\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\n\tadd\tesi,2\t\t\t\t\t;2 for stereo\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\n??calcDifferencel:\n\t\t\t\t\t\t\t; reset difference\n\n\tmov\t[(sCompInfo ebx).dwDifference],0\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep]\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4l\n\tadd\t[(sCompInfo ebx).dwDifference],ecx\t;Add wStep\n\n??no4l:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2l\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no2l:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1l\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no1l:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8l\n\tneg\t[(sCompInfo ebx).dwDifference]\t\t;Negate diff\n\n??no8l:\n\t\t; add difference to predicted value.\n\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\n\tadd\teax,[(sCompInfo ebx).dwDifference]\n\n\t\t; make sure there is no under or  overflow.\n\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowl\n\tmov\teax,7FFFh\n\n??noOverflowl:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowl\n\tmov\teax,0FFFF8000h\n\n??noUnderflowl:\n\tmov\t[(sCompInfo ebx).dwPredicted],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bitl\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,4\t\t\t\t\t;4 for stereo\n\tjmp\tshort ??adjustIndexl\n\n??output8Bitl:\n\t; output 8 bit sample\n\n\txor\tah,80h\n\tmov\t[edi],ah\n\tadd\tedi,2\t\t\t\t\t;2 for stereo\n\n??adjustIndexl:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex],ax\n\t\t\t\t\t\t\t; check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex],8000h\n\tjb\tshort ??checkOverflowl\n\tmov\t[(sCompInfo ebx).wIndex],0\n\tjmp\tshort ??adjustStepl\t\t\t;reset index to zero\n\n\n??checkOverflowl:\n\n\tcmp\t[(sCompInfo ebx).wIndex],88\t\t; check if wIndex > 88\n\tjbe\tshort ??adjustStepl\n\tmov\t[(sCompInfo ebx).wIndex],88\t\t; reset index to 88\n\n??adjustStepl:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex],1\n\tmov\t[(sCompInfo ebx).wStep],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2\n\tjne\t??mainloopl\n;----------------------------------------------------------------------------\n; Right Side Setup\n;----------------------------------------------------------------------------\n\tmov\teax,[wBytes]\n\tmov\t[dwCODECBytesProcessed],eax\n\tmov\tesi,[(sCompInfo ebx).lpSource]\n\tmov\tedi,[(sCompInfo ebx).lpDest]\n\tinc\tesi\t\t\t\t\t; skip left channel\n\tinc\tedi\t\t\t\t     \t; skip left channel\n\tcmp\t[(sCompInfo ebx).wBitSize],16\t\t;16 bit ??\n\tje\tshort ??doByteDivide\n\tmov\t[dwCODECByteIndex],eax\n\tjmp  short ??mainloopr\n\n??doByteDivide:\n\tshr\teax,1 \t\t\t\t\t;Divide size by two\n\tinc\tedi   \t\t\t\t\t; 16 bit so skip 1 more\n\tmov\t[dwCODECByteIndex],eax\n\n\n;--------------------------------------------------------------------------\n;Right Channel Start\n;--------------------------------------------------------------------------\n\n\n??mainloopr:\n\ttest\t[(sCompInfo ebx).dwSampleIndex2],1\n\tje\tshort ??fetchTokenr\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCodeBuf2]\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode2],ax\n\tjmp\tshort ??calcDifferencer\n\n??fetchTokenr:\n\txor\teax,eax\n\tmov\tal,[esi]\n\tmov\t[(sCompInfo ebx).wCodeBuf2],ax\n\tadd\tesi,2\t\t\t\t     \t;2 for stereo\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode2],ax\n\n??calcDifferencer:\n\t\t\t\t\t\t\t; reset difference\n\n\tmov\t[(sCompInfo ebx).dwDifference2],0\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep2]\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4r\n\tadd\t[(sCompInfo ebx).dwDifference2],ecx\t;Add wStep\n\n??no4r:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2r\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\n??no2r:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1r\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\n??no1r:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8r\n\tneg\t[(sCompInfo ebx).dwDifference2]\t\t;Negate diff\n\n??no8r:\n\t; add difference to predicted value.\n\tmov\teax,[(sCompInfo ebx).dwPredicted2]\n\tadd\teax,[(sCompInfo ebx).dwDifference2]\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowr\n\tmov\teax,7FFFh\n\n??noOverflowr:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowr\n\tmov\teax,0FFFF8000h\n\n??noUnderflowr:\n\tmov\t[(sCompInfo ebx).dwPredicted2],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bitr\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,4\t\t\t\t\t;4 for stereo\t\t***\n\tjmp\tshort ??adjustIndexr\n\n??output8Bitr:\n\t\t\t\t\t\t\t; output 8 bit sample\n\txor\tah,80h\n\tmov\t[edi],ah\n\tadd\tedi,2\t\t\t\t\t;2 for stereo\n\n??adjustIndexr:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode2]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex2],ax\n\t\t\t\t\t\t\t; check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex2],8000h\n\tjb\tshort ??checkOverflowr\n\t\t\t\t\t\t\t; reset index to zero\n\tmov\t[(sCompInfo ebx).wIndex2],0\n\tjmp\tshort ??adjustStepr\n\n??checkOverflowr:\n\t\t\t\t\t\t\t; check if wIndex > 88\n\tcmp\t[(sCompInfo ebx).wIndex2],88\n\tjbe\tshort ??adjustStepr\n\tmov\t[(sCompInfo ebx).wIndex2],88\t\t; reset index to 88\n\n??adjustStepr:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex2]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex2],1\n\tmov\t[(sCompInfo ebx).wStep2],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2\n\tjne\t??mainloopr\n\n\n??exitout:\n;\t\tdon't think we need this but just in case i'll leave it here!!\n\n;\tmov\t[(sCompInfo ebx).lpSource],esi\n;\tmov\t[(sCompInfo ebx).lpDest],edi\n\t; set up return value for number of bytes processed.\n\tmov\teax,[dwCODECBytesProcessed]\n\tpop\tedx\n\tpop\tecx\n\tpop\tebx\n\tpop\tedi\n\tpop\tesi\n\tret\n\n\tENDP\tGeneral_sosCODECDecompressData\n\nLABEL\tLockedCodeEnd\tBYTE\n\n;***************************************************************************\n;* sosCODEC_LOCK -- locks the JLB audio decompression code\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is lock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:       BOOL sosCODEC_Lock(void);                         \t   *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC sosCODEC_Lock:NEAR\n\tPROC\tsosCODEC_Lock C NEAR USES ebx ecx edx esi edi\n\n\t;\n\t; Lock the code that is used by the sos decompression method.\n\t;\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n  \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags], IF_LOCKED_PM_CODE\n\n\t;\n\t; Lock the data used by the sos decompression method.\n\t;\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags], IF_LOCKED_PM_DATA\n\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\tENDP\tsosCODEC_Lock\n\n;***************************************************************************\n;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code       *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is unlock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:\tBOOL sosCODEC_Unlock(void);                        \t   *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC sosCODEC_Unlock:NEAR\n\tPROC\tsosCODEC_Unlock C NEAR USES ebx ecx edx esi edi\n\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\n??code_not_locked:\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??data_not_locked:\n\tmov\t[InitFlags],0\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\tENDP\tsosCODEC_Unlock\n\n\n\tEND\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/SOS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sos.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces\n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DEFINED\n#define  _SOS_DEFINED\n#include \"sosdefs.h\"\n\n#pragma pack(4)\n\n// error definition for sound operating system\n#define  _SOS_ERR          -1\n\n// number of drivers allowed to be open at one time\n#define  _SOS_MAX_DRIVERS  5\n\n// structure definition for the capabilities\ntypedef struct _tagCAPABILITIES\n{\n   BYTE  szDeviceName[ 32 ];  // device name\n   WORD  wDeviceVersion;      // device version\n   WORD  wBitsPerSample;      // bits per sound sample\n   WORD  wChannels;           // stereo/mono sound card\n   WORD  wMinRate;            // minimum rate\n   WORD  wMaxRate;            // maximum rate\n   WORD  wMixerOnBoard;       // board contains mixer\n   WORD  wMixerFlags;         // mixer capabilities\n   WORD  wFlags;              // miscellaneous flags\n   short far * lpPortList;         // list of usable ports\n   short far * lpDMAList;          // list of usable dma channels\n   short far * lpIRQList;          // list of usable irq channels\n   short far * lpRateList;         // list of usable rates, -1 if any in min to max\n   WORD  fBackground;         // foreground or background driver\n   WORD  wDeviceID;           // ID for the device\n   WORD  wTimerID;            // ID for the timer\n\n} _SOS_CAPABILITIES;\n\n// far pointer to the device capabilities structure\ntypedef _SOS_CAPABILITIES far *  LPSOSDEVICECAPS;\n\n// flag types for driver\n#define  _FLAGS_SIGNED              0x8000\n\n// devices that can be loaded\n#define  _SOUND_BLASTER_8_MONO      0xe000\n#define  _SOUND_BLASTER_8_ST        0xe001\n#define  _SBPRO_8_ST                _SOUND_BLASTER_8_ST\n#define  _SBPRO_8_MONO              0xe00f\n#define  _SOUND_MASTER_II_8_MONO    0xe002\n#define  _MV_PAS_8_MONO             0xe003\n#define  _MV_PAS_16_MONO            0xe004\n#define  _MV_PAS_8_ST               0xe005\n#define  _MV_PAS_16_ST              0xe006\n#define  _ADLIB_GOLD_8_ST           0xe007\n#define  _ADLIB_GOLD_16_ST          0xe008\n#define  _ADLIB_GOLD_8_MONO         0xe009\n#define  _ADLIB_GOLD_16_MONO        0xe00a\n#define  _MICROSOFT_8_MONO          0xe00b\n#define  _MICROSOFT_8_ST            0xe00c\n#define  _MICROSOFT_16_MONO         0xe00d\n#define  _MICROSOFT_16_ST           0xe00e\n#define  _SOUND_SOURCE_8_MONO_PC    0xe010\n#define  _SOUND_SOURCE_8_MONO_TANDY 0xe011\n#define  _GENERAL_PORT_8_MONO       0xe012\n#define  _GENERAL_PORT_8_MONO_R     0xe013\n#define  _SIERRA_8_MONO             0xe014\n#define  _SB16_8_MONO               0xe015\n#define  _SB16_8_ST                 0xe016\n#define  _SB16_16_MONO              0xe017\n#define  _SB16_16_ST                0xe018\n#define  _ESS_AUDIODRIVE_8_MONO     0xe019\n#define  _ESS_AUDIODRIVE_8_ST       0xe01a\n#define  _ESS_AUDIODRIVE_16_MONO    0xe01b\n#define  _ESS_AUDIODRIVE_16_ST      0xe01c\n#define  _SOUNDSCAPE_8_MONO         0xe01d\n#define  _SOUNDSCAPE_8_ST           0xe01e\n#define  _SOUNDSCAPE_16_MONO        0xe01f\n#define  _SOUNDSCAPE_16_ST          0xe020\n#define  _RAP10_8_MONO              0xe021\n#define  _RAP10_16_MONO             0xe022\n#define  _GUS_8_MONO                0xe023\n#define  _GUS_8_ST                  0xe024\n#define  _GUS_16_MONO               0xe025\n#define  _GUS_16_ST                 0xe026\n#define  _GUS_MAX_8_MONO            0xe027\n#define  _GUS_MAX_8_ST              0xe028\n#define  _GUS_MAX_16_MONO           0xe029\n#define  _GUS_MAX_16_ST             0xe02a\n#define  _WAVEJAMMER_8_MONO         0xe02b\n#define  _WAVEJAMMER_8_ST           0xe02c\n#define  _WAVEJAMMER_16_MONO        0xe02d\n#define  _WAVEJAMMER_16_ST          0xe02e\n#define  _TEMPOCS_8_MONO            0xe02f\n#define  _TEMPOCS_8_ST              0xe030\n#define  _TEMPOCS_16_MONO           0xe031\n#define  _TEMPOCS_16_ST             0xe032\n#define  _WAVEJAMMERCD_8_MONO       0xe033\n#define  _WAVEJAMMERCD_8_ST         0xe034\n#define  _WAVEJAMMERCD_16_MONO      0xe035\n#define  _WAVEJAMMERCD_16_ST        0xe036\n#define  _SOUND_BLASTER_8_MONO_R    0xe050\n#define  _MICROSOFT_8_MONO_R        0xe051\n#define  _SOUND_MASTER_II_8_MONO_R  0xe052\n#define  _ADLIB_GOLD_8_MONO_R       0xe053\n#define  _MV_PAS_8_MONO_R           0xe054\n#define  _RAP10_8_MONO_R            0xe058\n#define  _RAP10_16_MONO_R           0xe059\n#define  _SB16_8_MONO_R             0xe05a\n#define  _SB16_8_ST_R               0xe05b\n#define  _SB16_16_MONO_R            0xe05c\n#define  _SB16_16_ST_R              0xe05d\n#define  _MV_PAS_16_MONO_R          0xe060\n#define  _SOUNDSCAPE_8_MONO_R       0xe061\n#define  _SOUNDSCAPE_8_ST_R         0xe062\n#define  _SOUNDSCAPE_16_MONO_R      0xe063\n#define  _SOUNDSCAPE_16_ST_R        0xe064\n#define  _ESS_AUDIODRIVE_8_MONO_R   0xe065\n#define  _ESS_AUDIODRIVE_8_ST_R     0xe066\n#define  _ESS_AUDIODRIVE_16_MONO_R  0xe067\n#define  _ESS_AUDIODRIVE_16_ST_R    0xe068\n#define  _SPEECH_THING_8_MONO       0xe090\n#define  _YAMAHA_8_MONO             0xe106\n#define  _INT_SPEAKER_8_MONO        0xe107\n\n// call indexes for the loadable drivers\nenum\n{\n   _DRV_INIT,\n   _DRV_UNINIT,\n   _DRV_SETRATE,\n   _DRV_SETACTION,\n   _DRV_START,\n   _DRV_STOP,\n   _DRV_PAUSE,\n   _DRV_RESUME,\n   _DRV_CAPABILITIES,\n   _DRV_PLAY_FOREGROUND,\n   _DRV_GET_FILL_INFO,\n   _DRV_GET_CALL_FUNCTIONS,\n   _DRV_SET_CALL_FUNCTIONS\n};\n\n// fill info\ntypedef  struct   _tagFillInfo\n         {\n\n            LPSTR lpFillHandler;                   // pointer to fill handler\n            LPWORD lpDMAFillCount;                 // pointer to dma count\n            LPSTR lpSampleList;                    // pointer to sample list\n            LPWORD lpDMAMasterVolume;              // pointer to dma count\n\n         } _SOS_FILL_INFO;\n\n// caps info structure\ntypedef  struct   _tagCapsInfo\n         {\n\n            LPSTR    lpPortList;                   // pointer to port list\n            LPSTR    lpDMAList;                    // pointer to DMA list\n            LPSTR    lpIRQList;                    // pointer to IRQ list\n            LPSTR    lpRateList;                   // pointer to rate list\n\n         } _SOS_CAPS_INFO;\n\n// maximum number of available voice\n#define  _MAX_VOICES    32\n\n// structure definition\ntypedef  struct   _tagSAMPLE\n{\n   LPSTR    samplePtr;                 // pointer to data buffer\n   LPSTR    sampleData;                // pointer to active data\n   LPSTR    sampleLoopPtr;             // pointer for loop back\n\n   WORD     sampleLength;              // length of sample\n   WORD     sampleIndex;               // index into sample\n   WORD     sampleLoopLength;          // length of loop\n\n   WORD     sampleBytesLeft;           // bytes left to play in sample\n\n   WORD     sampleLoopPoint;           // byte count for loop point\n   WORD     sampleLoopEndLength;       // length of remaining chunk\n\n   short    sampleFlags;               // control sample\n   short    sampleVolume;              // volume control\n   short    sampleID;                  // sample ID\n\n   short    sampleChannel;             // channel to play sample on\n   short    sampleLoopCount;           // loop count\n   short    sampleLastFill;            // last fill position\n   VOID ( far __cdecl * sampleCallback )( WORD, WORD, WORD ); // callback function for sample\n\n   WORD     samplePitchAdd;\n   short    samplePitchFraction;\n\n   short    samplePort;                // port to use for non-dma digitized\n\n   WORD     sampleTotalBytes;\n   WORD     sampleByteLength;\n\n   short    samplePanLocation;\n   short    samplePanSpeed;\n   short    samplePanDirection;\n   short    samplePanStart;\n   short    samplePanEnd;\n\n   short    sampleDelayBytes;\n   short    sampleDelayRepeat;\n\n   WORD     sampleADPCMPredicted;\n   short    sampleADPCMIndex;\n\n   short    sampleRootNoteMIDI;\n\n   WORD  sampleTemp1;\n\n} _SOS_SAMPLE;\n\n// enumeration for left or right channel\nenum\n{\n   _LEFT_CHANNEL,\n   _RIGHT_CHANNEL,\n   _CENTER_CHANNEL,\n   _INTERLEAVED\n};\n\n// enumeration for foreground and background\nenum\n{\n   _FOREGROUND,\n   _BACKGROUND\n};\n\n// defines for the sample flags\n#define  _ACTIVE           0x8000\n#define  _LOOPING          0x4000\n#define  _FIRST_TIME       0x2000\n#define  _PENDING_RELEASE  0x1000\n#define  _CONTINUE_BLOCK   0x0800\n#define  _PITCH_SHIFT      0x0400\n#define  _PANNING          0x0200\n#define  _VOLUME           0x0100\n#define  _TRANSLATE16TO8   0x0080\n#define  _STAGE_LOOP       0x0040\n#define  _TRANSLATE8TO16   0x0020\n#define  _STEREOTOMONO     0x0010\n\n// defines for the wParam flags\n#define  _SINGLE_SAMPLE 0x01\n\n#define  _SOS_DCAPS_AUTO_REINIT     0x01\n#define  _SOS_DCAPS_MPU_401         0x02\n#define  _SOS_DCAPS_OPL2            0x04\n#define  _SOS_DCAPS_OPL3            0x08\n#define  _SOS_DCAPS_OPL4            0x10\n#define  _SOS_DCAPS_WAVETABLE       0x20\n#define  _SOS_DCAPS_DL_SAMPLES      0x40\n#define  _SOS_DCAPS_FIFO_DEVICE     0x80\n#define  _SOS_DCAPS_ENV_NEEDED      0x100\n#define  _SOS_DCAPS_PSEUDO_DMA1     0x200\n#define  _SOS_DCAPS_SIGNED_DATA     0x8000\n\n// file header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // number of drivers in the file\n   WORD  wDrivers;\n\n   // offset of first driver\n   WORD  lOffset;\n\n   // size of the file\n   WORD  lFileSize;\n\n} _FILEHEADER;\n\n// driver header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // offset of next driver\n   WORD  lNextDriver;\n\n   // size of current driver\n   WORD  wSize;\n\n   // id for the current device\n   WORD  wDeviceID;\n\n   // id for the type of DOS extender\n   WORD  wExtenderType;\n\n} _DRIVERHEADER;\n\n// device hardware information\ntypedef struct\n{\n   // port to be used\n   WORD  wPort;\n\n   // irq to use\n   WORD  wIRQ;\n\n   // dma channel to se\n   WORD  wDMA;\n\n   // extra parameter\n   WORD  wParam;\n\n} _SOS_HARDWARE;\n\n// structure definition for start sample\ntypedef struct\n{\n   // pointer to sample\n   LPSTR lpSamplePtr;\n\n   // size of the sample\n   WORD  dwSampleSize;\n\n   // number of times to loop the sample -1 is infinite\n   WORD  wLoopCount;\n\n   // channel to play sample on\n   WORD  wChannel;\n\n   // volume to play sample at\n   WORD wVolume;\n\n   // id for the sample\n   WORD  wSampleID;\n\n   // far pointer to the callback function\n   VOID ( far __cdecl *lpCallback )( WORD, WORD, WORD );\n\n   // port to use if driver is a non-dma background driver\n   WORD  wSamplePort;\n\n   // flags field\n   WORD  wSampleFlags;\n\n   // total length of sample including loops, etc..\n   WORD     dwSampleByteLength;\n\n   // loop point for the sample\n   WORD  dwSampleLoopPoint;\n   WORD  dwSampleLoopLength;\n\n   // pitch shifting components\n   WORD     dwSamplePitchAdd;\n   WORD    wSamplePitchFraction;\n\n   // pan components\n   WORD    wSamplePanLocation;\n   WORD    wSamplePanSpeed;\n   WORD    wSamplePanDirection;\n   WORD    wSamplePanStart;\n   WORD    wSamplePanEnd;\n\n   // delay parts\n   WORD    wSampleDelayBytes;\n   WORD    wSampleDelayRepeat;\n\n   // compression components\n   WORD     dwSampleADPCMPredicted;\n   WORD    wSampleADPCMIndex;\n\n   // root note for pitch shifting\n   WORD    wSampleRootNoteMIDI;\n\n   // filler for future upgrades\n   WORD  dwSampleTemp1;\n   WORD  dwSampleTemp2;\n   WORD  dwSampleTemp3;\n\n} _SOS_START_SAMPLE;\n\n// structure for initializing a driver\ntypedef struct\n{\n   WORD  wBufferSize;\n   LPSTR lpBuffer;\n   BOOL  wAllocateBuffer;\n   WORD  wSampleRate;\n   WORD  wParam;\n   LONG  dwParam;\n   VOID ( far *lpFillHandler )( VOID );\n   LPSTR lpDriverMemory;\n   LPSTR lpDriverMemoryCS;\n   LPSTR lpTimerMemory;\n   LPSTR lpTimerMemoryCS;\n   WORD  wTimerID;\n   WORD  wPhysical;\n\n} _SOS_INIT_DRIVER;\n\n// define for the timer types to use\n#define  _SOS_NORMAL_TIMER          0x00\n\n// enumeration for the timer types\nenum\n{\n   _TIMER_8_MONO   =     0x1000,\n   _TIMER_8_ST,\n   _TIMER_16_MONO,\n   _TIMER_16_ST,\n   _TIMER_8_MONO_ULAW,\n   _TIMER_8_ST_ULAW,\n   _TIMER_16_MONO_ULAW,\n   _TIMER_16_ST_ULAW,\n   _TIMER_8_MONO_REC,\n   _TIMER_8_MONO_ULAW_REC,\n   _TIMER_UNDEFINED_1,\n   _TIMER_UNDEFINED_2,\n   _TIMER_UNDEFINED_3,\n   _TIMER_UNDEFINED_4,\n   _TIMER_UNDEFINED_5,\n   _TIMER_UNDEFINED_6,\n   _TIMER_UNDEFINED_7,\n   _TIMER_UNDEFINED_8,\n   _TIMER_UNDEFINED_9,\n   _TIMER_UNDEFINED_A,\n   _TIMER_UNDEFINED_B,\n   _TIMER_UNDEFINED_C,\n   _TIMER_UNDEFINED_D,\n   _TIMER_UNDEFINED_E,\n   _TIMER_UNDEFINED_F,\n   _TIMER_UNDEFINED_10,\n   _TIMER_UNDEFINED_11,\n   _TIMER_UNDEFINED_12,\n   _TIMER_UNDEFINED_13,\n   _TIMER_UNDEFINED_14,\n   _TIMER_UNDEFINED_15,\n   _TIMER_UNDEFINED_16,\n   _TIMER_8_SOUND_SOURCE,\n   _TIMER_8_SOUND_SOURCE_TANDY,\n   _TIMER_8_GENERAL_PORT,\n   _TIMER_8_GENERAL_PORT_REC\n};\n\n// define for no slots available\n#define  _ERR_NO_SLOTS ( WORD )-1\n\n// error codes for the system\nenum\n{\n   _ERR_NO_ERROR,\n   _ERR_DRIVER_NOT_LOADED,\n   _ERR_INVALID_POINTER,\n   _ERR_DETECT_INITIALIZED,\n   _ERR_FAIL_ON_FILE_OPEN,\n   _ERR_MEMORY_FAIL,\n   _ERR_INVALID_DRIVER_ID,\n   _ERR_NO_DRIVER_FOUND,\n   _ERR_DETECTION_FAILURE,\n   _ERR_DRIVER_LOADED,\n   _ERR_INVALID_HANDLE,\n   _ERR_NO_HANDLES,\n   _ERR_PAUSED,\n   _ERR_NOT_PAUSED,\n   _ERR_INVALID_DATA,\n   _ERR_DRV_FILE_FAIL,\n   _ERR_INVALID_PORT,\n   _ERR_INVALID_IRQ,\n   _ERR_INVALID_DMA,\n   _ERR_INVALID_DMA_IRQ\n};\n\n// maximum number of timer events that can be registered\n#define  _TIMER_MAX_EVENTS    0x10\n\n// flags for the debugging system\n#define  _SOS_DEBUG_NORMAL       0x0000\n#define  _SOS_DEBUG_NO_TIMER     0x0001\n#define  _SOS_TIMER_DPMI         0x0002\n\n// define for types of DOS extenders\n#define  _SOS_RATIONAL           0x8000\n#define  _SOS_FLASHTECK          0x4000\n\n// defines for the types of timers for different\n// dos extenders\n#define  _SOS_TIMER_NEAR         0x8000\n#define  _SOS_TIMER_FAR          0x4000\n\n// values for callback information\nenum\n{\n   _SAMPLE_PROCESSED,\n   _SAMPLE_LOOPING,\n   _SAMPLE_DONE\n};\n\n// define for special 18.2 callback rate to dos\n#define  _TIMER_DOS_RATE   0xff00\n\n#pragma pack()\n\n#pragma aux int_3 = \"int 3\"\n\n#pragma pack( 1 )\ntypedef struct\n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned       segment;\n\tunsigned short\tnumber_available;\n\tunsigned short number_used;\n\tunsigned       page0;\n\n} EVDS_STRUCT;\n\ntypedef struct\n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned short segment;\n\tunsigned short\tID;\n\tunsigned       physical;\n\n} VDS_STRUCT;\n\n#pragma pack()\n\n#include \"sosdata.h\"\n#include \"sosfnct.h\"\n\n#endif"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/SOSCODEC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*          Copyright (c) 1994, HMI, INC. All Rights Reserved\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     soscodec.asm\n;*\n;* DESCRIPTION\n;*     HMI SOS ADPCM compression/decompression.\n;*\n;* PROGRAMMER\n;*     Nick Skrepetos\n;*     Denzil E. Long, Jr. (Fixed bugs, rewrote for watcom)\n;*     Bill Petro\t\t   (Added stereo support)\n;*     Jonathan Lanier\n;*\n;* DATE\n;*     Febuary 15, 1995\n;*\n;* LAST MODIFIED\n;*     08/07/95 [jdl] - Rewrote/optimized sosCODECDecompressData\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\nDPMI_INTR\t\tequ\t31h\nIF_LOCKED_PM_CODE\tequ\t1h\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t2h\t\t; Locked PM code for DPMI.\n\nSTRUC\tsCompInfo\nlpSource\t\tDD\t?\t;Compressed data pointer\nlpDest\t\t\tDD\t?\t;Uncompressed data pointer\ndwCompSize\t\tDD\t?\t;Compressed size\ndwUnCompSize\t\tDD\t?\t;Uncompressed size\n\ndwSampleIndex\t\tDD\t?\t;Index into sample\ndwPredicted\t\tDD\t?\t;Next predicted value\ndwDifference\t\tDD\t?\t;Difference from last sample\nwCodeBuf\t\tDW\t?\t;Holds 2 nibbles for decompression\nwCode\t\t\tDW\t?\t;Current 4 bit code\nwStep\t\t\tDW\t?\t;Step value in table\nwIndex\t\t\tDW\t?\t;Index into step table\n\ndwSampleIndex2\t\tDD\t?\t;Index into sample\ndwPredicted2\t\tDD\t?\t;Next predicted value\ndwDifference2\t\tDD\t?\t;Difference from last sample\nwCodeBuf2 \t\tDW\t?\t;Holds 2 nibbles for decompression\nwCode2\t\t\tDW\t?\t;Current 4 bit code\nwStep2\t\t\tDW\t?\t;Step value in table\nwIndex2\t\t\tDW\t?\t;Index into step table\n\nwBitSize\t\tDW\t?\t;Bit size for decompression\nwChannels\t\tDW\t?    \t;number of channels\nENDS\tsCompInfo\n\n\n\tDATASEG\n\n\nInitFlags\tDD\t0\t\t; Flags to indicate what has been initialized.\n\n\nLABEL\tLockedDataStart\tBYTE\n\n;* Index table for stepping into step table\n\nINCLUDE\t\t\"difftb.inc\"\nINCLUDE\t\t\"indextb.inc\"\nINCLUDE\t\t\"nybbtb.inc\"\n\nLABEL\tLockedDataEnd\tBYTE\n\n\tCODESEG\n\nLABEL\tLockedCodeStart\tBYTE\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECInitStream - Initialize compression stream.\n;*\n;* SYNOPSIS\n;*     sosCODECInitStream(CompInfo)\n;*\n;*     void sosCODECInitStream(_SOS_COMPRESS_INFO *);\n;*\n;* FUNCTION\n;*     Initialize compression stream for compression and decompression.\n;*\n;* INPUTS\n;*     CompInfo - Compression information structure.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tsosCODECInitStream:NEAR\n\tPROC\tsosCODECInitStream C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\n\tmov\teax,[sSOSInfo]\n\tmov\t[(sCompInfo eax).wIndex],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).dwPredicted],0 \t; no predicted value\n\tmov\t[(sCompInfo eax).wIndex2],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).dwPredicted2],0 \t; no predicted value\n\tret\n\n\tENDP\tsosCODECInitStream\n\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECDecompressData - Decompress audio data.\n;*\n;* SYNOPSIS\n;*     Size = sosCODECDecompressData(CompInfo, NumBytes)\n;*\n;*     long sosCODECDecompressData(_SOS_COMPRESS_INFO *, long);\n;*\n;* FUNCTION\n;*     Decompress data from a 4:1 ADPCM compressed stream. The number of\n;*     bytes decompressed is returned.\n;*\n;* INPUTS\n;*     CompInfo - Compress information structure.\n;*     NumBytes - Number of bytes to decompress.\n;*\n;* RESULT\n;*     Size - Size of decompressed data.\n;*\n;*\n;* NOTES\n;*     This routine has been optimized for pipelining on both\n;*     486 and Pentium processors.  Changing, inserting, or moving any\n;*     instructions will most likely slow down the code, in some cases by\n;*     as much as 20%.  It can burst-decompress 16384 samples in about\n;*     1940s on a Pentium 90Mhz, and about 3960s on a 486 66Mhz.\n;*     Instruction reordering could bring this down to below 1870s on\n;*     the Pentium, but this would cause a great degradation in 486\n;*     performance.  Since slow 486's are the reason this code was\n;*     written to be fast, it has been optimized for the Pentium only where\n;*     it would not degrade 486 performance.  So, be careful when changing\n;*     ANY of this code, because it is very carefully balanced...\n;****************************************************************************\n\n\tGLOBAL\tC sosCODECDecompressData:NEAR\n\tPROC\tsosCODECDecompressData C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\tARG\twBytes:DWORD\n\n\tpush\tesi\n\tpush\tedi\n\tpush\tebx\n\tpush\tecx\n\tpush\tedx\t\t\t;save all the regs\n\n\tmov\tebx,[sSOSInfo]\t\t;get base of sCompInfo struct\n\tmov\tcx,[(sCompInfo ebx).wBitSize] ;check the bit size\n\tmov\tdx,[(sCompInfo ebx).wChannels] ;check the number of channels\n;\n;\n; Determine the correct routine to use for decoding\n; (for now only ADPCM 4:1 Mono 16-bit is implemented)\n\tcmp\tcx,8\n\tjne\t??do16Bits\n\n??do8Bits:\n\tcmp\tdx,2\n\tjne\t??not8Stereo\n;\tjmp\t??decomp8Stereo\n\tjmp\t??byeBye\n\n??not8Stereo:\n\tcmp\tdx,1\n\tjne\t??byeBye\n;\tjmp\tdecomp8Mono\n\tjmp\t??byeBye\n\n??do16Bits:\n\tcmp\tcx,16\n\tjne\t??byeBye\n\n\tcmp\tdx,2\n\tjne\t??not16Stereo\n;\tjmp\t??decomp16Stereo\n\tjmp\t??byeBye\n\n??not16Stereo:\n\tcmp\tdx,1\n\tjne\t??byeBye\n\n\tpush\tebp\n;\n;\n; 16 bit ADPCM 4:1 Mono pre-loop initialization\n??decomp16Mono:\n\tpush\tebx\t\t\t;save struct base\n\txor\tedx,edx\t\t\t;clear index\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\t;get last sample\n\tmov\tdx,[(sCompInfo ebx).wIndex]\t;get last index value\n\tmov\tesi,[(sCompInfo ebx).lpSource]\t;get source address\n\tmov\tedi,[(sCompInfo ebx).lpDest]\t;get dest address\n\n\tmov\tebp,[wBytes]\t\t;get the number of dest. bytes\n\tcmp\tebp,16\t\t\t;less than 16? (less than 8 samples)\n\tjl\t??fixAlign16Mono0\t;if so, don't bother with alignment\n;\n;\n; Check to see if we need to fix an alignment problem on the source buffer\n; (non-aligned buffers are MUCH slower; if we're given a non-DWORD aligned\n; source address, we do as many samples as needed to get to the nearest\n; DWORD boundary, then finish the bulk as a DWORD-aligned decompress).\n\tmov\tebx,esi\t\t\t;get source address\n\tand\tebx,03h\t\t\t;check LSB\n\tjnz\t??fixalign16Mono\t;if non-zero, need to align for\n\t\t\t\t\t;warp speed\n??fixAlign16Mono0:\n\tpush\tebp\t\t\t;save for later\n\tshr\tebp,4\t\t\t;divide by 16 for 16-bit,\n\t\t\t\t\t;because we do 8 nybbles per loop,\n\t\t\t\t\t;and there are two samples per\n\t\t\t\t\t;byte, so there are n/16 iterations\n\t\t\t\t\t;required\n\txor\tebx,ebx\t\t\t;clear our nybble index\n\tor\tebp,ebp\t\t\t;set flags for EBP\n\tjmp\t??start16Mono\t\t;start with test... don't go if\n\t\t\t\t\t;we have zero bytes to do\n??fixalign16Mono:\n\tjmp\t[DWORD PTR dwMono16AlignJmpTable+ebx*4] ;do non-aligned first\n\n\talign\t4\n??fixAlign16Mono1:\n\tsub\tebp,12\t\t\t;adjust # of dest. bytes\n\tpush\tebp\t\t\t;save it\n\tshr\tebp,4\t\t\t;divide by 16 to get samples/8\n\txor\tebx,ebx\t\t\t;clear our nybble index\n\tinc\tebp\t\t\t;adjust ebp for loop\n\tjmp\t??finish16Mono6\t\t;borrow exit code to go through a\n\t\t\t\t\t;piece of a loop\n\talign\t4\n??fixAlign16Mono2:\n\tsub\tebp,8\t\t\t;adjust # of dest. bytes\n\tpush\tebp\t\t\t;save it\n\tshr\tebp,4\t\t\t;divide by 16 to get samples/8\n\txor\tebx,ebx\t\t\t;clear our nybble index\n\tinc\tebp\t\t\t;adjust ebp for loop\n\tjmp\t??finish16Mono4\t\t;borrow exit code to go through a\n\t\t\t\t\t;piece of a loop\n\talign\t4\n??fixAlign16Mono3:\n\tsub\tebp,4\t\t\t;adjust # of dest. bytes\n\tpush\tebp\t\t\t;save it\n\tshr\tebp,4\t\t\t;divide by 16 to get samples/8\n\txor\tebx,ebx\t\t\t;clear our nybble index\n\tinc\tebp\t\t\t;adjust ebp for loop\n\tjmp\t??finish16Mono2\t\t;borrow exit code to go through a\n\t\t\t\t\t;piece of a loop\n; \"The Loop\"\n;\n; Process 1st nybble\n\talign\t4\n??loop16Mono:\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix1Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix1Smp16MonoU\n??fixed1Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tmov\t[edi],ax\t\t;save the sample\n;\n;\n; Process 2nd nybble\n??finish7Smp16Mono:\n\tmov\tbl,ch\t\t\t;get next 2 nybbles in ebx\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix2Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix2Smp16MonoU\n??fixed2Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tmov\t[edi+02h],ax\t\t;save the sample\n\tshr\tecx,16\t\t\t;move top four nybbles into bottom\n;\n;\n; Process 3rd nybble\n??finish6Smp16Mono:\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix3Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix3Smp16MonoU\n??fixed3Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tmov\t[edi+04h],ax\t\t;save the sample\n;\n;\n; Process 4th nybble\n??finish5Smp16Mono:\n\tmov\tbl,cl\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix4Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix4Smp16MonoU\n??fixed4Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tmov\t[edi+06h],ax\t\t;save the sample\n;\n;\n; Process 5th nybble\n??finish4Smp16Mono:\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix5Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix5Smp16MonoU\n??fixed5Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tmov\t[edi+08h],ax\t\t;save the sample\n;\n;\n; Process 6th nybble\n??finish3Smp16Mono:\n\tmov\tbl,ch\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix6Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix6Smp16MonoU\n??fixed6Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tmov\t[edi+0Ah],ax\t\t;save the sample\n;\n;\n; Process 7th nybble\n??finish2Smp16Mono:\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix7Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix7Smp16MonoU\n??fixed7Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tmov\t[edi+0Ch],ax\t\t;save the sample\n;\n;\n; Process 8th nybble\n??finish1Smp16Mono:\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix8Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix8Smp16MonoU\n;\n;\n; Loop cleanup for next pass\n??fixed8Smp16Mono:\n\tmov\t[edi+0Eh],ax\t\t;save the sample\n\tadd\tesi,04h\t\t\t;bump esi to point to next longword\n\tadd\tedi,10h\t\t\t;incr. the destination buffer ptr\n\tdec\tebp\t\t\t;count down the number of samples/8\n??start16Mono:\n\tjng\t??cleanup16Mono\t\t;if done, clean up\n\tmov\tecx,[esi]\t\t;get 4 nybbles in one whack (whee!)\n\tmov\tbl,cl\t\t\t;get next 2 nybbles in ebx\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tjmp\t??loop16Mono\t\t;loop until done\n\n??cleanup16Mono:\n\tjnz\t??done16Mono\t\t;if ebp is non-zero, we're DONE\n\t\t\t\t\t;if exactly zero, finish the tail-end\n\t\t\t\t\t;of the conversion (may be a non-\n\t\t\t\t\t;multiple of 8 nybbles)\n;\n;\n; Loop cleanup for last (incomplete) pass\n\tpop\tecx\t\t\t;restore # of words\n\tshr\tecx,1\t\t\t;divide by two to get samples\n\tand\tecx,07h\t\t\t;get # of samples we missed\n\tjmp\t[DWORD PTR dwMono16JmpTable+ecx*4] ;go finish the job...\n;\n;\n; Structure cleanup\n??done16Mono:\n\tpop\tebx\t\t\t;restore struct base\n\tpop\tebp\t\t\t;restore stack frame pointer\n\tmov\t[(sCompInfo ebx).dwPredicted],eax ;save last sample\n\tmov\t[(sCompInfo ebx).wIndex],dx ;save last index value\n\tmov\teax,[wBytes]\t\t;get # of bytes we did\n??byeBye:\n\tpop\tedx\t\t\t;restore all the regs\n\tpop\tecx\n\tpop\tebx\n\tpop\tedi\n\tpop\tesi\n\tret\n;\n;\n; Jumps for -32768/+32767 bounds check go to these vvvv\n\talign\t4\n??fix1Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed1Smp16Mono\t;go back\n\n\talign\t4\n??fix1Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed1Smp16Mono\t;go back\n\n\talign\t4\n??fix2Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed2Smp16Mono\t;go back\n\n\talign\t4\n??fix2Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed2Smp16Mono\t;go back\n\n\talign\t4\n??fix3Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed3Smp16Mono\t;go back\n\n\talign\t4\n??fix3Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed3Smp16Mono\t;go back\n\n\talign\t4\n??fix4Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed4Smp16Mono\t;go back\n\n\talign\t4\n??fix4Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed4Smp16Mono\t;go back\n\n\talign\t4\n??fix5Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed5Smp16Mono\t;go back\n\n\talign\t4\n??fix5Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed5Smp16Mono\t;go back\n\n\talign\t4\n??fix6Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed6Smp16Mono\t;go back\n\n\talign\t4\n??fix6Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed6Smp16Mono\t;go back\n\n\talign\t4\n??fix7Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed7Smp16Mono\t;go back\n\n\talign\t4\n??fix7Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed7Smp16Mono\t;go back\n\n\talign\t4\n??fix8Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed8Smp16Mono\t;go back\n\n\talign\t4\n??fix8Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed8Smp16Mono\t;go back\n;\n;\n; Jump tables for cleanup after loop unroll point to these vvvv\n\talign\t4\n??finish16Mono1:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tch,[esi]\t\t;get 1 nybble (1 byte)\n\tshl\tch,4\t\t\t;move it over\n\tmov\tbl,ch\t\t\t;get nybble in ebx\n\tsub\tedi,0Eh\t\t\t;back edi up\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tjmp\t??finish1Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono2:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tch,[esi]\t\t;get 2 nybbles (1 byte)\n\tmov\tbl,ch\t\t\t;get nybbles in ebx\n\tsub\tedi,0Ch\t\t\t;back edi up\n\tsub\tesi,3\t\t\t;adjust esi (used for dword aligning)\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tjmp\t??finish2Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono3:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tcx,[esi]\t\t;get 3 nybbles (2 bytes)\n\tshl\tcx,4\t\t\t;move it over\n\tmov\tbl,cl\t\t\t;get nybbles in ebx\n\tsub\tedi,0Ah\t\t\t;back edi up\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tjmp\t??finish3Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono4:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tcx,[esi]\t\t;get 4 nybbles (2 bytes)\n\tmov\tbl,cl\t\t\t;get nybbles in ebx\n\tsub\tedi,08h\t\t\t;back edi up\n\tsub\tesi,2\t\t\t;adjust esi (used for dword aligning)\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tjmp\t??finish4Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono5:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tcl,[esi+2]\t\t;get 1 nybble (1 byte)\n\tshl\tecx,16\t\t\t;shift it over\n\tmov\tcx,[esi]\t\t;get 4 nybbles (2 bytes)\n\tmov\tbl,cl\t\t\t;get nybbles in ebx\n\tshr\tecx,4\t\t\t;move it over\n\tshl\tbl,4\t\t\t;move it over\n\tsub\tedi,06h\t\t\t;back edi up\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tjmp\t??finish5Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono6:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tcl,[esi+2]\t\t;get 2 nybbles (1 byte)\n\tshl\tecx,16\t\t\t;move it over\n\tmov\tcx,[esi]\t\t;get 4 nybbles (2 bytes)\n\tmov\tbl,cl\t\t\t;get nybbles in ebx\n\tshr\tecx,8\t\t\t;move it over\n\tsub\tesi,1\t\t\t;adjust esi (used for dword aligning)\n\tsub\tedi,04h\t\t\t;back edi up\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tjmp\t??finish6Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono7:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tecx,[esi]\t\t;get 7 nybbles (4 bytes)\n\tshl\tecx,4\t\t\t;move it over\n\tmov\tbl,cl\t\t\t;get nybbles in ebx\n\tsub\tedi,02h\t\t\t;back edi up\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tjmp\t??finish7Smp16Mono\t;go finish it\n;\n;\n; Jump Tables\n\t\t\talign 4\n\ndwMono16JmpTable\tDD\t??done16Mono\n\t\t\tDD\t??finish16Mono1\n\t\t\tDD\t??finish16Mono2\n\t\t\tDD\t??finish16Mono3\n\t\t\tDD\t??finish16Mono4\n\t\t\tDD\t??finish16Mono5\n\t\t\tDD\t??finish16Mono6\n\t\t\tDD\t??finish16Mono7\n\n\t\t\talign 4\ndwMono16AlignJmpTable\tDD\t??fixAlign16Mono0\n\t\t\tDD\t??fixAlign16Mono1\n\t\t\tDD\t??fixAlign16Mono2\n\t\t\tDD\t??fixAlign16Mono3\n\n\tENDP\tsosCODECDecompressData\n\nLABEL\tLockedCodeEnd\tBYTE\n\n;***************************************************************************\n;* sosCODEC_LOCK -- locks the JLB audio decompression code\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is lock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:       BOOL sosCODEC_Lock(void);                         \t   *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tsosCODEC_Lock:NEAR\n\tPROC\tsosCODEC_Lock C NEAR USES ebx ecx edx esi edi\n\n\t;\n\t; Lock the code that is used by the sos decompression method.\n\t;\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n  \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags], IF_LOCKED_PM_CODE\n\n\t;\n\t; Lock the data used by the sos decompression method.\n\t;\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags], IF_LOCKED_PM_DATA\n\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\tENDP\tsosCODEC_Lock\n\n;***************************************************************************\n;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code       *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is unlock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:\tBOOL sosCODEC_Unlock(void);                        \t   *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tsosCODEC_Unlock:NEAR\n\tPROC\tsosCODEC_Unlock C NEAR USES ebx ecx edx esi edi\n\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\n??code_not_locked:\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??data_not_locked:\n\tmov\t[InitFlags],0\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\tENDP\tsosCODEC_Unlock\n\n\tEND\n\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/SOSCOMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*  File              : soscomp.h\n*  Date Created      : 6/1/94\n*  Description       :\n*\n*  Programmer(s)     : Nick Skrepetos\n*  Last Modification : 10/1/94 - 11:37:9 AM\n*  Additional Notes  : Modified by Denzil E. Long, Jr.\n*\n*****************************************************************************\n*            Copyright (c) 1994,  HMI, Inc.  All Rights Reserved            *\n****************************************************************************/\n\n#ifndef  _SOS_COMPRESS\n#define  _SOS_COMPRESS\n\n/* compression types */\nenum {\n\t_ADPCM_TYPE_1,\n\t};\n\n/* define compression structure */\ntypedef struct _tagCOMPRESS_INFO {\n\tchar       *lpSource;\n\tchar       *lpDest;\n\tunsigned long dwCompSize;\n\tunsigned long dwUnCompSize;\n\tunsigned long dwSampleIndex;\n\tlong          dwPredicted;\n\tlong          dwDifference;\n\tshort         wCodeBuf;\n\tshort         wCode;\n\tshort         wStep;\n\tshort         wIndex;\n\n\tunsigned long dwSampleIndex2; //added BP for channel 2\n\tlong          dwPredicted2;   //added BP for channel 2\n\tlong          dwDifference2; \t//added BP for channel 2\n\tshort         wCodeBuf2; \t\t//added BP for channel 2\n\tshort         wCode2; \t\t\t//added BP for channel 2\n\tshort         wStep2; \t\t\t//added BP for channel 2\n\tshort         wIndex2; \t\t\t//added BP for channel 2\n\tshort         wBitSize;\n\tshort\t\t\t  wChannels;\t\t//added BP for # of channels\n\t} _SOS_COMPRESS_INFO;\n\n/* compressed file type header */\ntypedef struct _tagCOMPRESS_HEADER {\n\tunsigned long dwType;              // type of compression\n\tunsigned long dwCompressedSize;    // compressed file size\n\tunsigned long dwUnCompressedSize;  // uncompressed file size\n\tunsigned long dwSourceBitSize;     // original bit size\n\tchar          szName[16];          // file type, for error checking\n\t} _SOS_COMPRESS_HEADER;\n\n/* Prototypes */\nextern \"C\" {\n\tvoid __cdecl sosCODECInitStream(_SOS_COMPRESS_INFO *);\n\tunsigned long __cdecl sosCODECCompressData(_SOS_COMPRESS_INFO *,\tunsigned long);\n\tunsigned long __cdecl sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);\n\tunsigned long __cdecl General_sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);\n}\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/SOSDATA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdata.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces\n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DATA\n#define  _SOS_DATA\n\n#include <stddef.h>\n\n#pragma pack(4)\nextern   WORD     _sosDIGIData_Start;\nextern   WORD     _sosDIGIData_End;\nextern   WORD     _wSOSDriverLinear[];\nextern   WORD     _wSOSTimerLinear[];\nextern   LPSTR    _lpSOSDriver[];\nextern   LPSTR    _lpSOSTimer[];\nextern   LPSTR    _lpSOSDriverCS[];\nextern   LPSTR    _lpSOSTimerCS[];\nextern   BOOL     _wSOSDriverLoaded[];\nextern   BOOL     _wSOSTimerLoaded[];\nextern   BOOL     _wSOSDriverInitialized[];\nextern   WORD     _wSOSOutputRate[];\nextern   WORD     _wSOSDMABuffersize[];\nextern   LONG     _dwSOSDMABufferPhysical[];\nextern   LPSTR    _lpSOSDMABuffer[];\nextern   BOOL     _wTimerUsed;\nextern   VOID ( far *_lpSOSFillHandler[] )( VOID );\nextern   WORD     _wSOSTimerType[];\nextern   WORD     _wSOSDriverType[];\nextern   _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ];\nextern   LPWORD      _lpSOSDMAIrqCount[];\nextern   LPWORD      _lpSOSDMAFillCount[];\nextern   WORD        _wSOSTmrNextCount;\nextern   VOID ( interrupt far *_lpSOSOldTimer )( VOID );\nextern   WORD     _wSOSDriverID[];\nextern   _SOS_CAPABILITIES _sSOSDriverCaps[];\nextern   WORD        _wSOSDMAPortList[];\nextern   BYTE        _bSOSDMAChannel[];\nextern   _SOS_INIT_DRIVER     _sSOSDIGIInitDriver[];\nextern   BYTE  _pSOSDriverPath[];\nextern   BYTE  _pSOSTempDriverPath[];\nextern   BOOL  _wTIMERUsed;\nextern   WORD  _wTIMERValue;\nextern   VOID ( far * _lpTIMEREvents[] )( VOID );\nextern   WORD _wTIMEREventRate[];\nextern   WORD _dwTIMEREventFraction[];\nextern   WORD _dwTIMEREventFractionCurrent[];\nextern   BYTE  _bSOSMIDITimerSongHandler[];\nextern   BYTE  _bSOSMIDISongHandle;\nextern   WORD  _wSOSTimerMemHandle[];\nextern   WORD  _wSOSDriverMemHandle[];\nextern   WORD  _wSOSRealSeg[];\n\nextern   _FILEHEADER    _sDETFileHeader;\nextern   _DRIVERHEADER  _sDETDriverHeader;\nextern   _FILEHEADER    sLOADFileHeader;\nextern   _DRIVERHEADER  sLOADDriverHeader;\nextern   BOOL           _wDETInitialized;\nextern   WORD           _wDETLinear;\nextern   LPSTR          _lpDETDriverBuffer;\nextern   LPSTR          _lpDETDriverBufferCS;\nextern   WORD           _hDETFile;\nextern   DWORD          _dwDETDriverIndex;\nextern   WORD           _wDETDriverIndexCur;\nextern   WORD           _wDETMemHandle;\nextern   LPSOSDEVICECAPS _lpDETDeviceCaps;\nextern   _SOS_CAPABILITIES _sDETCaps;\nextern   PSTR _pSOSErrorStrings[];\nextern   BOOL _wSOSBufferAllocated[];\nextern   BOOL _wSOSSystemInitialized;\nextern   VDS_STRUCT _sSOSVDSInfo;\nextern   _SOS_FILL_INFO _sSOSFillInfo;\nextern   WORD    _wSOSTimerEventIndex;\nextern   WORD  _wSOSTimerEntered;\nextern   WORD  _wSOSDriverSize[];\nextern   WORD  _wSOSTimerSize[];\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nextern   WORD  _sosDIGIData1_Start;\nextern   WORD  _sosDIGIData1_End;\nextern   WORD  _sosDIGIData2_Start;\nextern   WORD  _sosDIGIData2_End;\nextern   BYTE  _bTIMERInstalled;\nextern   BYTE  _bTIMERDPMI;\nextern   WORD  wDetectPort;\nextern   WORD  wDetectIRQ;\nextern   WORD  wDetectDMA;\nextern   WORD  wDetectParam;\n#ifdef __cplusplus\n}\n#endif\n\n#pragma pack()\n\n#endif\n\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/SOSDEFS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdefs.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces\n                            All Rights Reserved\n****************************************************************************/\n\n\n#ifndef  _SOSDEFS_DEFINED\n#define  _SOSDEFS_DEFINED\n\n#undef   _TRUE\n#undef   _FALSE\n#undef   _NULL\nenum\n      {\n         _FALSE,\n         _TRUE\n      };\n\n#define  _NULL  0\n\n#ifndef  VOID\n#define  VOID           void\n#endif\ntypedef  int            BOOL;\ntypedef  unsigned int   UINT;\ntypedef  unsigned char  BYTE;\ntypedef  unsigned       WORD;\n#ifndef  LONG\ntypedef  signed long    LONG;\n#endif\ntypedef  unsigned long  DWORD;\n\ntypedef  BYTE  *        PBYTE;\ntypedef  char near *    PSTR;\ntypedef  WORD  *        PWORD;\ntypedef  LONG  *        PLONG;\ntypedef  VOID  *        PVOID;\n\ntypedef  BYTE  far   *  LPBYTE;\ntypedef  BYTE  far   *  LPSTR;\ntypedef  WORD  far   *  LPWORD;\ntypedef  LONG  far   *  LPLONG;\ntypedef  VOID  far   *  LPVOID;\n\ntypedef  BYTE  huge  *  HPBYTE;\ntypedef  BYTE  huge  *  HPSTR;\ntypedef  WORD  huge  *  HPWORD;\ntypedef  LONG  huge  *  HPLONG;\ntypedef  VOID  huge  *  HPVOID;\n\ntypedef  unsigned       HANDLE;\n\n#endif\n\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/SOSFNCT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosfnct.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces\n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_FUNCTIONS\n#define  _SOS_FUNCTIONS\n\n#pragma pack(4)\n\nWORD sosDIGILockMemory          (  VOID  );\nWORD sosDIGIUnLockMemory        (  VOID  );\nWORD sosDIGIInitSystem           (  LPSTR, WORD  );\nWORD sosDIGIUnInitSystem         (  VOID  );\nWORD sosDIGIInitDriver           (  WORD, _SOS_HARDWARE far *,\n                                    _SOS_INIT_DRIVER far *, WORD far *   );\nWORD sosDIGIUnInitDriver         (  WORD, BOOL, BOOL  );\nWORD sosDIGILoadDriver          (  WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD sosDIGIUnLoadDriver         (  WORD  );\nWORD sosDIGIGetDeviceCaps        (  WORD, LPSOSDEVICECAPS  );\n\n#ifdef PHARLAP\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#else\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#endif\n\nWORD sosDIGIStopSample           (  WORD, WORD  );\nWORD sosDIGISamplesPlaying       (  WORD  );\nBOOL sosDIGISampleDone           (  WORD, WORD  );\nBOOL sosDIGISampleFilling        (  WORD, WORD  );\nWORD sosDIGIStartSample          (  WORD, _SOS_START_SAMPLE far *  );\nWORD sosDIGIContinueSample       (  WORD, WORD, _SOS_START_SAMPLE far * );\n\n\nWORD  sosDIGIDetectInit          (  LPSTR  );\nWORD  sosDIGIDetectUnInit        (  VOID  );\nWORD  sosDIGIDetectFindHardware  (  WORD, _SOS_CAPABILITIES far *, WORD far * );\nWORD  sosDIGIDetectFindFirst     (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectFindNext      (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectGetSettings   (  _SOS_HARDWARE far *  );\nWORD  sosDIGIDetectGetCaps       (  WORD, _SOS_CAPABILITIES far *  );\nWORD  sosDIGIDetectVerifySettings(  _SOS_HARDWARE far *  );\nPSTR  sosGetErrorString          (  WORD  );\n\nWORD  sosDIGILoadTimer           (  WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD  sosDIGIUnLoadTimer         (  WORD  );\n\nWORD  sosTIMERRegisterEvent      ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle );\nWORD  sosTIMERInitSystem               (  WORD, WORD  );\nWORD  sosTIMERUnInitSystem             (  WORD  );\nWORD  sosTIMERSetRate                  (  WORD  );\nWORD  sosTIMERRemoveEvent              (  WORD );\nWORD  sosTIMERAlterEventRate           (  WORD, WORD  );\nWORD  sosTIMERGetEventRate             (  WORD  );\nVOID far sosTIMEROldHandler            (  VOID  );\nVOID far sosTIMERHandler               (  VOID  );\n\n// functions in soscntl.c\nWORD  sosDIGISetSampleVolume     ( WORD, WORD, WORD );\nWORD  sosDIGIGetSampleVolume     ( WORD, WORD );\nWORD  sosDIGISetChannel          ( WORD, WORD, WORD );\nWORD  sosDIGIGetChannel          ( WORD, WORD );\nWORD  sosDIGIGetBytesProcessed   ( WORD, WORD );\nWORD  sosDIGIGetLoopCount        ( WORD, WORD );\nWORD  sosDIGISetPanLocation      ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanLocation      ( WORD, WORD );\nDWORD sosDIGISetPitch            ( WORD, WORD, DWORD );\nDWORD sosDIGIGetPitch            ( WORD, WORD );\nWORD  sosDIGIGetDMAPosition      ( WORD );\nWORD  sosDIGISetPanSpeed         ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanSpeed         ( WORD, WORD );\nWORD  sosDIGIGetSampleID         ( WORD, WORD );\nWORD  sosDIGIGetSampleHandle     ( WORD, WORD );\nWORD  sosDIGISetMasterVolume     ( WORD, WORD );\n#ifdef PHARLAP\nVOID  sosFreeVDSPage          ( unsigned short, unsigned short, DWORD );\nWORD  sosAllocVDSPage         ( unsigned short *, unsigned short *, DWORD * );\n#else\nWORD  sosAllocVDSPage            ( LPSTR *, WORD *, WORD * );\nVOID  sosFreeVDSPage             ( WORD, WORD, LONG );\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef PHARLAP\nextern   int   __cdecl sosRealFree          ( int );\nextern   BOOL  __cdecl  _sos_read( WORD, LPSTR, WORD, WORD * );\nextern   int   __cdecl sosRealAlloc( int, int *, int * );\nextern   void  __cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD );\nextern   int   __cdecl sosGetCS( VOID );\nextern   int   __cdecl sosGetES( VOID );\n#else\nextern   int   __cdecl sosRealAlloc         ( int, int *, int * );\nextern   int   __cdecl sosRealFree          ( int );\n#endif\n\n// sos driver functions\nextern   WORD  __cdecl sosDRVLockMemory     ( DWORD, DWORD );\nextern   WORD  __cdecl sosDRVUnLockMemory   ( DWORD, DWORD );\nextern   void  __cdecl sosDRVGetCapsInfo    ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  __cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  __cdecl sosDRVGetCapsPtr     ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  __cdecl sosDRVInit           ( LPSTR, LPSTR, int, int, int, int, int, int );\nextern   void  __cdecl sosDRVStart          ( LPSTR, LPSTR, int, int );\nextern   void  __cdecl sosDRVSetRate        ( LPSTR, LPSTR, int );\nextern   void  __cdecl sosDRVSetAction      ( LPSTR, LPSTR );\nextern   void  __cdecl sosDRVStop           ( LPSTR, LPSTR );\nextern   void  __cdecl sosDRVUnInit         ( LPSTR, LPSTR );\nextern   void  __cdecl sosDRVGetFillInfo    ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * );\nextern   void  __cdecl sosFillSampleStructs ( PSTR, LPSTR );\nextern   WORD  __cdecl sosDetDRVExist       ( LPSTR, LPSTR );\nextern   WORD  __cdecl sosDetDRVGetSettings ( LPSTR, LPSTR );\nextern   WORD  __cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR );\nextern   WORD  __cdecl sosDIGIInitForWindows( WORD );\nextern   WORD  __cdecl sosDIGIUnInitForWindows( WORD );\nextern   LPSTR __cdecl sosAllocateFarMem      ( WORD, PSTR, WORD * );\nextern   LPSTR __cdecl sosCreateAliasCS       ( LPSTR );\nextern   VOID  __cdecl sosFreeSelector        ( LPSTR, DWORD );\nextern   LPSTR __cdecl sosMAKEDOSPtr          ( PSTR );\nextern   VOID  __cdecl sosDetDRVSetEnvString  ( DWORD, PSTR );\nextern   PSTR  __cdecl sosDetDRVGetEnvString  ( DWORD );\nextern   VOID  __cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR );\nextern   VOID  __cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR );\nextern   WORD  __cdecl sosDRVGetFreeMemory     ( VOID );\nextern   WORD  __cdecl sosDRVAllocVDSStruct    ( WORD, WORD *, WORD * );\nextern   WORD  __cdecl sosDRVFreeVDSStruct     ( WORD, WORD );\nextern   WORD  __cdecl sosDRVIsWindowsActive   ( VOID );\nextern   WORD  __cdecl sosDRVVDSGetBuffer    ( WORD );\nextern   WORD  __cdecl sosDRVVDSFreeBuffer   ( WORD );\nextern   WORD  __cdecl getDS( VOID );\nextern   WORD  __cdecl sosDRVMakeDMASelector   ( WORD );\nextern   WORD  __cdecl sosDRVFreeDMASelector   ( WORD );\n\n\nextern   void  __cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) );\nextern   void  __cdecl sosTIMERDRVUnInit( void );\nextern   void  __cdecl sosTIMERDRVHandler( void );\nextern   void  __cdecl sosTIMERDRVFHandler( void );\nextern   void  __cdecl sosTIMERDRVEnable( void );\nextern   void  __cdecl sosTIMERDRVDisable( void );\nextern   void  __cdecl sosTIMERDRVCallOld( void );\nextern   void  __cdecl sosTIMERDRVSetRate( WORD );\nextern   void  __cdecl sosDIGITimer_Start( void );\nextern   void  __cdecl sosDIGITimer_End( void );\nextern   void  __cdecl sosDIGIDrv_Start( void );\nextern   void  __cdecl sosDIGIDrv_End( void );\n#ifdef __cplusplus\n}\n#endif\n\n// external functions for handling system initialization and\n// uninitialization\nWORD  sosEXDIGInitDriver               (  WORD, WORD, WORD, LPSTR,\n                                          _SOS_HARDWARE far *, WORD *  );\nWORD  sosEXDIGIUnInitDriver            (  VOID  );\n\nWORD  sosEXDETFindDriver               (  WORD, LPSTR, _SOS_HARDWARE far *,\n                                          _SOS_CAPABILITIES far *  );\n\n// memory locking prototypes\nVOID  sosDIGICaps_Start( VOID );\nVOID  sosDIGICaps_End( VOID );\nVOID  sosDIGIErr_Start( VOID );\nVOID  sosDIGIErr_End( VOID );\nVOID  sosDIGITmr_Start( VOID );\nVOID  sosDIGITmr_End( VOID );\nVOID  sosDIGIStart_Start( VOID );\nVOID  sosDIGIStart_End( VOID );\nVOID  sosDIGIPlyng_Start( VOID );\nVOID  sosDIGIPlyng_End( VOID );\nVOID  sosDIGIRate_Start( VOID );\nVOID  sosDIGIRate_End( VOID );\nVOID  sosDIGIDone_Start( VOID );\nVOID  sosDIGIDone_End( VOID );\nVOID  sosDIGIDetec_Start( VOID );\nVOID  sosDIGIDetec_End( VOID );\nVOID  sosDIGIInit_Start( VOID );\nVOID  sosDIGIInit_End( VOID );\nVOID  sosDIGILoad_Start( VOID );\nVOID  sosDIGILoad_End( VOID );\nVOID  sosDIGICntl_Start( VOID );\nVOID  sosDIGICntl_End( VOID );\n\n#pragma pack()\n\n#endif\n\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/SOSRES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosres.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#define  _SOS_RESOURCE\n#ifndef  _SOS_RESOURCE\n#define  _SOS_RESOURCE\n\n// structure for resource file header\ntypedef struct\n{\n   // file version\n   WORD     wVersion;\n\n   // file size\n   LONG     dwFileSize;\n\n   // number of resources in file\n   WORD     wResCount;\n\n   // offset of resource data from top of file\n   LONG     dwResOffset;\n\n   // offset of sync track from top of file\n   LONG     dwSyncTrackOffset;\n\n}  _RES_FILE_HEADER;\n\n// structure for resource block header\ntypedef struct\n{\n   // resource id\n   WORD     wID;\n\n   // resource type\n   WORD     wResType;\n\n   // offset of next block\n   LONG     dwNextBlock; \n\n   // size of the current resource information\n   LONG     dwResSize;\n\n   // rate to play block at\n   WORD     wBlockRate;\n\n   // id for the sync track to use\n   WORD     wSyncTrackID;\n\n}  _RES_BLOCK_HEADER;\n\n// structure for sync mark tag\ntypedef struct _tagSYNCMARK\n{\n   // ID of the type of mark being used\n   WORD  wID;\n\n   // location in data of sync mark\n   LONG  dwSyncOffset;\n\n   // length of sync block\n   LONG  dwSyncSize;\n\n   // start sample data\n   _SOS_START_SAMPLE sampleData;\n    \n} _RES_SYNCMARK;\n\ntypedef union\n{\n   // structure for sync mark tag\n   _RES_SYNCMARK  syncMark; \n\n} _RES_TAG;\n\n// union for filter information for prepareWave\ntypedef union\n{\n   // filter type\n   WORD     wFilterID;\n\n   // structure for volume\n   struct   volume \n   {\n      WORD  wVolume;\n   };\n\n   // structure for delay\n   struct   delay\n   {  \n      WORD  wDelaySamples;\n   };\n\n} _SOS_FILTER; \n\n \n#endif\n\n\u001a"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/SOUND.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : SOUND.H                                  *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : September 1, 1993                        *\n *                                                                         *\n *                  Last Update : September 1, 1993   [JLB]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SOUND_H\n#define SOUND_H\n\n//#define\tHMI_DRIVER\tTRUE\n//#include\t\"sos.h\"\n#include\t\"soscomp.h\"\n\n/*\n**\tMaximum number of sound effects that may run at once.\n*/\n#define\tMAX_SFX\t\t5\n\n/*\n** Size of temp HMI low memory staging buffer.\n*/\n#define\tSECONDARY_BUFFER_SIZE\t\t(1024*32)\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/SOUNDINT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDINT.CPP                             *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 28, 1995   [PWG]                    *\n *                                                                         *\n * This module contains all of the functions that are used within our      *\n * sound interrupt.  They are stored in a seperate module because memory\t*\n * around these functions must be locked or they will cause a read to\t\t*\n * be generated while in an interrupt.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Simple_Copy -- Copyies 1 or 2 source chuncks to a dest                *\n *   Sample_Copy -- Copies sound data from source format to raw format.    *\n *   DigiCallback -- Low level double buffering handler.                   *\n *   save_my_regs -- Inline function which will save assembly regs         *\n *   restore_my_regs -- Inline function which will restore saved registes  *\n *   Audio_Add_Long_To_Pointer -- Adds an offset to a ptr casted void      *\n *   Init_Locked_Data -- Initializes sound driver locked data              *\n *   Audio_Mem_Set -- Quick see routine to set memory to a value           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n#pragma pack(4)\n#define WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#include\t<windows.h>\n#include\t<windowsx.h>\n#include\t\"dsound.h\"\n#include\t<wwstd.h>\n#include \"soundint.h\"\n#include \"memflag.h\"\n#include \"audio.h\"\n\nextern\tDebugBuffer[];\n\n/***************************************************************************\n** All routines past this point must be locked for the sound driver to\t  **\n** function under a VCPI memory manager.  These locks are unnecessary if  **\n** the driver does not have to run under windows or does not use virtual  **\n** memory.                                                                **\n***************************************************************************/\n\n\n\n/***************************************************************************\n * SIMPLE_COPY -- Copyies 1 or 2 source chuncks to a dest                  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nlong Simple_Copy(void ** source, long * ssize, void ** alternate, long * altsize, void **dest, long size)\n{\n\n\n\tlong\tout = 0;\t\t// Number of bytes copied to the destination.\n\n\t/*\n\t**\tIt could happen that entering this routine, the source buffer\n\t**\thas been exhausted, but the alternate buffer is still valid.\n\t**\tMove the alternate into the primary position before proceeding.\n\t*/\n\tif (!(*ssize)) {\n\t\t*source = *alternate;\n\t\t*ssize = *altsize;\n\t\t*alternate = NULL;\n\t\t*altsize = 0;\n\t}\n\n\tif (*source && *ssize) {\n\t\tlong\ts;\t\t\t\t// Scratch length var.\n\n\t\t/*\n\t\t**\tCopy as much as possible from the primary source, but no\n\t\t**\tmore than the primary source has to offer.\n\t\t*/\n\t\ts = size;\n\t\tif (*ssize < s) s = *ssize;\n\t\tMem_Copy(*source, *dest, s);\n\t\t*source = Audio_Add_Long_To_Pointer(*source, s);\n\t\t*ssize -= s;\n\t\t*dest = Audio_Add_Long_To_Pointer(*dest, s);\n\t\tsize -= s;\n\t\tout += s;\n\n\t\t/*\n\t\t**\tIf the primary source was insufficient to fill the request, then\n\t\t**\tmove the alternate into the primary position and try again.\n\t\t*/\n\t\tif (size) {\n\t\t\t*source = *alternate;\n\t\t\t*ssize = *altsize;\n\t\t\t*alternate = 0;\n\t\t\t*altsize = 0;\n\t\t\tout += Simple_Copy(source, ssize, alternate, altsize, dest, size);\n\t\t}\n\t}\n\n\treturn(out);\n}\n\n/***********************************************************************************************\n * Sample_Copy -- Copies sound data from source format to raw format.                          *\n *                                                                                             *\n *    This routine is used to copy the sound data (possibly compressed) to the destination     *\n *    buffer in raw format.                                                                    *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the source data (possibly compressed).                      *\n *                                                                                             *\n *          dest     -- Pointer to the destination buffer.                                     *\n *                                                                                             *\n *          size     -- The size of the destination buffer.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes placed into the output buffer.  This is usually   *\n *          the number of bytes requested except in the case when the source is exhausted.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/03/1994 JLB : Created.                                                                 *\n *   09/04/1994 JLB : Revamped entirely.                                                       *\n *=============================================================================================*/\n#pragma argsused\nlong Sample_Copy(SampleTrackerType *st, void ** source, long * ssize, void ** alternate, long * altsize, void * dest, long size, SCompressType scomp, void * , short int *)\n{\n\n\tlong\ts;\n\tlong\tdatasize = 0;\t\t// Output bytes.\n\n\tswitch (scomp) {\n\t\tdefault:\n\n\t\tcase SCOMP_NONE:\n\t\t\tdatasize = Simple_Copy(source, ssize, alternate, altsize, &dest, size);\n\t\t\tbreak;\n\n\t\tcase SCOMP_WESTWOOD:\n\t\tcase SCOMP_SOS:\n\t\t\twhile (size > 0) {\n\n\t\t\t\t/*\n\t\t\t\t**\tThe block spans two buffers.  It must be copied down to\n\t\t\t\t**\ta staging area before it can be decompressed.\n\t\t\t\t*/\n\t\t\t\t{\n\t\t\t\t\tlong magic;\n\t\t\t\t\tunsigned short fsize;\n\t\t\t\t\tunsigned short dsize;\n\t\t\t\t\tvoid *fptr;\n\t\t\t\t\tvoid *dptr;\n\t\t\t\t\tvoid *mptr;\n\n\t\t\t\t\tfptr = &fsize;\n\t\t\t\t\tdptr = &dsize;\n\t\t\t\t\tmptr = &magic;\n\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &fptr, sizeof(fsize));\n\t\t\t\t\tif (s < sizeof(fsize)) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &dptr, sizeof(dsize));\n\t\t\t\t\tif (s < sizeof(dsize) || size < dsize) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &mptr, sizeof(magic));\n\t\t\t\t\tif (s < sizeof(magic) || magic != LockedData.MagicNumber) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the frame and uncompressed data size are identical, then this\n\t\t\t\t\t**\tindicates that the frame is not compressed.  Just copy it directly\n\t\t\t\t\t**\tto the destination buffer in this case.\n\t\t\t\t\t*/\n\t\t\t\t\tif (fsize == dsize) {\n\t\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &dest, fsize);\n\t\t\t\t\t\tif (s < dsize) {\n\t\t\t\t\t\t\treturn (datasize);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tThe frame was compressed, so copy it to the staging buffer, and then\n\t\t\t\t\t\t**\tuncompress it into the final destination buffer.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tfptr = LockedData.UncompBuffer;\n\t\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &fptr, fsize);\n\t\t\t\t\t\tif (s < fsize) {\n\t\t\t\t\t\t\treturn (datasize);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (scomp == SCOMP_WESTWOOD) {\n\t\t\t\t\t\t\tDecompress_Frame(LockedData.UncompBuffer, dest, dsize);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tst->sosinfo.lpSource = (char *)LockedData.UncompBuffer;\n\t\t\t\t\t\t\tst->sosinfo.lpDest\t = (char *)dest;\n\t\t\t\t\t\t\tif (st->sosinfo.wBitSize==16 && st->sosinfo.wChannels==1){\n\t\t\t\t\t\t\t\tsosCODECDecompressData(&st->sosinfo, dsize);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tGeneral_sosCODECDecompressData(&st->sosinfo, dsize);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdest = Audio_Add_Long_To_Pointer(dest, dsize);\n\t\t\t\t\t}\n\t\t\t\t\tdatasize += dsize;\n\t\t\t\t\tsize -= dsize;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak;\n\t}\n\treturn(datasize);\n}\n\n\n\n\n\n\n\n/***********************************************************************************************\n * maintenance_callback -- routine to service the direct play secondary buffers                *\n *                         and other stuff..?                                                  *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *     ....Unknown                                                                             *\n *    10/17/95 10:15PM ST : tidied up a tad for direct sound                                   *\n *=============================================================================================*/\nVOID far __cdecl maintenance_callback(VOID)\n{\n\n\tint\t\t\t\t\tindex;\t\t\t\t//index used in for loop\n\tSampleTrackerType\t*st;\t\t\t\t\t//ptr to SampleTracker structure\n\tDWORD\t\t\t\t\tplay_cursor;\t\t//Position that direct sound is reading from\n\tDWORD\t\t\t\t\twrite_cursor;\t\t//Position in buffer that we can write to\n\tint\t\t\t \t\tbytes_copied;\t\t//Number of bytes copied into the buffer\n\tBOOL\t\t\t\t\twrite_more;\t\t\t//Flag to set if we need to write more into the buffer\n\tLPVOID\t\t\t\tplay_buffer_ptr;\t//Beginning of locked area of buffer\n\tLPVOID\t\t\t\tdummy_buffer_ptr;\t//Length of locked area in buffer\n\tDWORD\t\t\t\t\tlock_length1;\t\t//Beginning of second locked area in buffer\n\tDWORD\t\t\t\t\tlock_length2;\t\t//Length of second locked area in buffer\n\tHRESULT\t\t\t\treturn_code;\n\n\t//EnterCriticalSection(&GlobalAudioCriticalSection);\n\n\tst = &LockedData.SampleTracker[0];\n\tfor (index = 0; index < MAX_SFX; index++) {\n\n\t\tif (st->Active) {\n\n\t\t\t/*\n\t\t\t**\tGeneral service routine to handle moving small blocks from the\n\t\t\t**\tsource into the direct sound buffers.  If the source is\n\t\t\t**\tcompressed, then this will also uncompress it as the copy\n\t\t\t**\tis performed.\n\t\t\t*/\n\t\t\tif (st->Service && !st->DontTouch ) {\n\n\t\t\t\t//EnterCriticalSection (&st->AudioCriticalSection);\n\n\t\t\t\tst->DontTouch = TRUE;\n\n\t\t\t\t/*\n\t\t\t\t** Get the current position of the direct sound play cursor within the buffer\n\t\t\t\t*/\n\t\t\t\treturn_code = st->PlayBuffer->GetCurrentPosition ( &play_cursor , &write_cursor );\n\n\t\t\t\t/*\n\t\t\t\t** Check for unusual situations like a focus loss\n\t\t\t\t*/\n\t\t\t\tif (return_code != DS_OK){\n\t\t\t\t\tif (return_code == DSERR_BUFFERLOST){\n\t\t\t\t\t\tif (Audio_Focus_Loss_Function){\n\t\t\t\t\t\t\tAudio_Focus_Loss_Function();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\t\t//LeaveCriticalSection (&st->AudioCriticalSection);\n\t\t\t\t\treturn;\t\t//Our app has lost focus or something else nasty has happened\n\t\t\t\t}\t\t\t\t\t//so dont update the sound buffers\n\n\n\t\t\t\tif (st->MoreSource){\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If the direct sound read pointer is less than a quarter\n\t\t\t\t\t** of a buffer away from the end of the data then copy some\n\t\t\t\t\t** more.\n\t\t\t\t \t*/\n\t\t\t\t\twrite_more = FALSE;\n\n\t\t\t\t\tif ( play_cursor < (unsigned)st->DestPtr ){\n\t\t\t\t\t\tif ( (unsigned)st->DestPtr - (unsigned)play_cursor <= SECONDARY_BUFFER_SIZE/4 ){\n\t\t\t\t\t\t\twrite_more=TRUE;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t/* The only time that play_cursor can be greater than DestPtr is\n\t\t\t\t\t\t** if we wrote right to the end of the buffer last time and DestPtr\n\t\t\t\t\t\t** looped back to the beginning of the buffer.\n\t\t\t\t\t\t** That being the case, all we have to do is see if play_cursor is\n\t\t\t\t\t\t** within the last 25% of the buffer\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif ( ( (int)play_cursor > SECONDARY_BUFFER_SIZE*3/4) &&st->DestPtr==0 ){\n\t\t\t\t\t\t\twrite_more=TRUE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (write_more){\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Lock a 1/2 of the direct sound buffer so we can write to it\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif ( DS_OK== st->PlayBuffer->Lock (\t(DWORD)st->DestPtr ,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(DWORD)SECONDARY_BUFFER_SIZE/2,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&play_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&lock_length1,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&dummy_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&lock_length2,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t0 )){\n\n\t\t\t\t\t\t\tbytes_copied = Sample_Copy(\tst,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Source,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Remainder,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->QueueBuffer,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->QueueSize,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tplay_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tSECONDARY_BUFFER_SIZE/4,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tst->Compression,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Trailer[0],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->TrailerLen);\n\n\n\t\t\t\t\t\t\tif ( bytes_copied != (SECONDARY_BUFFER_SIZE/4) ){\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** We must have reached the end of the sample\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tst->MoreSource=FALSE;\n\t\t\t\t\t\t\t\tmemset (((char*)play_buffer_ptr)+bytes_copied ,\n\t\t\t\t\t\t\t\t\t\t0 ,\n\t\t\t\t\t\t\t\t\t\t(SECONDARY_BUFFER_SIZE/4)-bytes_copied);\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** Clear out an extra area in the buffer ahead of the play cursor\n\t\t\t\t\t\t\t\t** to give us a quiet period of grace in which to stop the buffer playing\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tif ( (unsigned)st->DestPtr == SECONDARY_BUFFER_SIZE*3/4 ){\n\t\t\t\t\t\t\t\t\tif ( dummy_buffer_ptr && lock_length2 ){\n\t\t\t\t\t\t\t\t\t\tmemset (dummy_buffer_ptr , 0 , lock_length2);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tmemset ((char*)play_buffer_ptr+SECONDARY_BUFFER_SIZE/4 , 0 , SECONDARY_BUFFER_SIZE/4);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**  Update our pointer into the direct sound buffer\n\t\t\t\t\t\t\t**\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tst->DestPtr = Audio_Add_Long_To_Pointer (st->DestPtr,bytes_copied);\n\n\t\t\t\t\t\t\tif ( (unsigned)st->DestPtr >= (unsigned)SECONDARY_BUFFER_SIZE ){\n\t\t\t\t\t\t\t\tst->DestPtr = Audio_Add_Long_To_Pointer (st->DestPtr,(long)-SECONDARY_BUFFER_SIZE);\n\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Unlock the direct sound buffer\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tst->PlayBuffer->Unlock(\tplay_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\t\tlock_length1,\n\t\t\t\t\t\t\t\t\t\t\t\t\tdummy_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\t\tlock_length2);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\t\t\t\t//write_more\n\n\t\t\t\t} else {\t\t\t//!more_source\n\n\t\t\t\t\t/*\n\t\t\t\t\t** no more source to write - check if the buffer play\n\t\t\t\t\t** has overrun the end of the sample and stop it if it has\n\t\t\t\t\t*/\n\t\t\t\t\tif ( ( (play_cursor >= (unsigned)st->DestPtr) && ( ((unsigned)play_cursor - (unsigned)st->DestPtr) <SECONDARY_BUFFER_SIZE/4) ) ||\n\t\t\t\t\t\t(!st->OneShot &&( (play_cursor < (unsigned)st->DestPtr) && ( ((unsigned)st->DestPtr - (unsigned)play_cursor) >(SECONDARY_BUFFER_SIZE*3/4) ) ))\t ){\n\t\t\t\t\t\t\tst->PlayBuffer->Stop();\n\t\t\t\t\t\t\tst->Service = FALSE;\n\t\t\t\t\t\t\tStop_Sample( index );\n\t\t\t\t\t}\n\t\t\t\t}\t\t\t\t\t//more_source\n\n\t\t\t\tst->DontTouch = FALSE;\n\n\t\t\t\t//LeaveCriticalSection (&st->AudioCriticalSection);\n\t\t\t}\n\t\t\t/*\n\t\t\t**\tFor file streamed samples, fill the queue pointer if needed.\n\t\t\t**\tThis allows for delays in calling the Sound_Callback function.\n\t\t\t*/\n\t\t\tif (!st->DontTouch && !st->QueueBuffer && st->FilePending) {\n\t\t\t\tst->QueueBuffer = Audio_Add_Long_To_Pointer(st->FileBuffer, (long)(st->Odd%LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t\t\t\tst->FilePending--;\n\t\t\t\tst->Odd++;\n\t\t\t\tif (!st->FilePending) {\n\t\t\t\t\tst->QueueSize = st->FilePendingSize;\n\t\t\t\t} else {\n\t\t\t\t\tst->QueueSize = LockedData.StreamBufferSize;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tAdvance to the next sample control structure.\n\t\t*/\n\t\tst++;\n\t}\n\n\n\tif (!LockedData._int) {\n\n\t\tLockedData._int++;\n\t\tst = &LockedData.SampleTracker[0];\n\t\tfor (index = 0; index < MAX_SFX; index++) {\n\n\t\t\t/*\n\t\t\t**\tIf there are any samples that require fading, then do so at this\n\t\t\t**\ttime.\n\t\t\t*/\n\t\t\tif (st->Active && st->Reducer && st->Volume) {\n\t\t\t\t//EnterCriticalSection (&st->AudioCriticalSection);\n\t\t\t\tif (st->Reducer >= st->Volume) {\n\t\t\t\t\tst->Volume = 0;\n\t\t\t\t} else {\n\t\t\t\t\tst->Volume -= st->Reducer;\n\t\t\t\t}\n\n#ifdef NO_VOLUME_CONTROL\n\t\t\t\tst->PlayBuffer->SetVolume (-( ( (32768-st->Volume)*1000) >>15 ) );\n#endif\t//ifdef NO_VOLUME_CONTROL\n\t\t\t\t//LeaveCriticalSection (&st->AudioCriticalSection);\n\t\t\t}\n\t\t\tst++;\n\t\t}\n\t\tLockedData._int--;\n\t}\n\n\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n}\n\n\n\n\n\n\n\n/***************************************************************************\n * ADD_LONG_TO_POINTER -- Adds an offset to a ptr casted void              *\n *                                                                         *\n * INPUT:\t\tvoid * ptr - the pointer to add to                            *\n *\t\t\t\t\tlong size  - the size to add to it\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:     void * ptr - the new location it will point to              *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n\nvoid *Audio_Add_Long_To_Pointer(void const *ptr, long size)\n{\n\treturn ((void *) ( (char const *) ptr + size));\n}\n\n/***************************************************************************\n * AUDIO_MEM_SET -- Quick see routine to set memory to a value             *\n *                                                                         *\n * INPUT:\t\tvoid const *  - the memory that needs to be set               *\n *\t\t\t\t\tunsigned char - the value to set the memory to\t\t\t\t  *\n *\t\t\t\t\tlong size     - how big an area to set\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:\t\tnone                                                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/28/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid Audio_Mem_Set(void const *ptr, unsigned char value, long size)\n{\n\tunsigned char *temp = (unsigned char *)ptr;\n\tfor (int lp = 0; lp < size; lp ++) {\n\t\t*temp++ = value;\n\t}\n}\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/SOUNDINT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDINT.H                               *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 23, 1995   [PWG]                    *\n *                                                                         *\n * This file is the include file for the Westwood Sound Sytem defines and  *\n * routines that are handled in an interrupt.\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"sound.h\"\n\n/*\n** Defines for true and false.  These are included because we do not allow\n** the sound int to include any of the westwood standard headers.  If we\n** did, there might be too much temptation to call another library function.\n** this would be bad, because then that function would not be locked.\n*/\n#define\tFALSE\t\t0\n#define\tTRUE\t\t1\n\n/*\n** Define the different type of sound compression avaliable to the westwood\n** library.\n*/\ntypedef enum {\n\tSCOMP_NONE=0,\t\t\t// No compression -- raw data.\n\tSCOMP_WESTWOOD=1,\t\t// Special sliding window delta compression.\n\tSCOMP_SONARC=33,\t\t// Sonarc frame compression.\n\tSCOMP_SOS=99\t\t\t// SOS frame compression.\n} SCompressType;\n\n/*\n**\tThis is the safety overrun margin for the sonarc compressed\n** data frames.  This value should be equal the maximum 'order' times\n**\tthe maximum number of bytes per sample.  It should be evenly divisible\n**\tby 16 to aid paragraph alignment.\n*/\n#define\tSONARC_MARGIN\t\t\t\t32\n\n\n/*\n** Define the sample control structure which helps us to handle feeding\n** data to the sound interrupt.\n*/\n#pragma pack(1);\ntypedef struct {\n\t/*\n\t**\tThis flags whether this sample structure is active or not.\n\t*/\n\tunsigned Active;\n\t//unsigned Active:1;\n\n\t/*\n\t**\tThis flags whether the sample is loading or has been started.\n\t*/\n\t//unsigned Loading:1;\n\tunsigned Loading;\n\n\t/*\n\t**\tThis semaphore ensures that simultaneous update of this structure won't\n\t**\toccur.  This is necessary since both interrupt and regular code can modify\n\t**\tthis structure.\n\t*/\n\t//unsigned DontTouch:1;\n\tunsigned DontTouch;\n\n\t/*\n\t**\tIf this sample is really to be considered a score rather than\n\t**\ta sound effect, then special rules apply.  These largely fall into\n\t**\tthe area of volume control.\n\t*/\n\t//unsigned IsScore:1;\n\tunsigned IsScore;\n\n\t/*\n\t**\tThis is the original sample pointer. It is used to control the sample based on\n\t**\tpointer rather than handle. The handle method is necessary when more than one\n\t**\tsample could be playing simultaneously. The pointer method is necessary when\n\t**\tthe dealing with a sample that may have stopped behind the programmer's back and\n\t**\tthis occurance is not otherwise determinable.  It is also used in\n\t** conjunction with original size to unlock a sample which has been DPMI\n\t** locked.\n\t*/\n\tvoid const *Original;\n\tlong OriginalSize;\n\n\t/*\n\t**\tThese are pointers to the double buffers.\n\t*/\n\tLPDIRECTSOUNDBUFFER PlayBuffer;\n\n\t/*\n\t** Variable to keep track of the playback rate of this buffer\n\t*/\n\tint\tPlaybackRate;\n\n\t/*\n\t** Variable to keep track of the sample type ( 8 or 16 bit ) of this buffer\n\t*/\n\tint\tBitSize;\n\n\t/*\n\t** Variable to keep track of the stereo ability of this buffer\n\t*/\n\tint\tStereo;\n\n\t/*\n\t**\tThe number of bytes in the buffer that has been filled but is not\n\t**\tyet playing.  This value is normally the size of the buffer,\n\t**\texcept for the case of the last bit of the sample.\n\t*/\n\tLONG DataLength;\n\n\t/*\n\t**\tThis is the buffer index for the low buffer that\n\t**\thas been filled with data but not yet being\n\t**\tplayed.\n\t*/\n//\tshort int Index;\n\n\t/*\n\t**\tPointer into the play buffer for writing the next\n\t**  chunk of sample to\n\t**\n\t*/\n\tVOID *DestPtr;\n\n\t/*\n\t**\tThis flag indicates that there is more source data\n\t**  to copy to the play buffer\n\t**\n\t*/\n\tBOOL MoreSource;\n\n\t/*\n\t**\tThis flag indicates that the entire sample fitted inside the\n\t** direct sound secondary buffer\n\t**\n\t*/\n\tBOOL OneShot;\n\n\t/*\n\t**\tPointer to the sound data that has not yet been copied\n\t**\tto the playback buffers.\n\t*/\n\tVOID *Source;\n\n\t/*\n\t**\tThis is the number of bytes remaining in the source data as\n\t**\tpointed to by the \"Source\" element.\n\t*/\n\tLONG Remainder;\n\n\t/*\n\t**\tObject to use with Enter/LeaveCriticalSection\n\t**\n\t*/\n\tCRITICAL_SECTION AudioCriticalSection;\n\n\t/*\n\t**\tSamples maintain a priority which is used to determine\n\t**\twhich sounds live or die when the maximum number of\n\t**\tsounds are being played.\n\t*/\n\tint Priority;\n\n\t/*\n\t**\tThis is the handle as returned by sosDIGIStartSample function.\n\t*/\n\tshort int Handle;\n\n\t/*\n\t**\tThis is the current volume of the sample as it is being played.\n\t*/\n\tint Volume;\n\tint Reducer;\t\t// Amount to reduce volume per tick.\n\n\t/*\n\t**\tThis is the compression that the sound data is using.\n\t*/\n\tSCompressType Compression;\n\tshort int TrailerLen;\t\t\t\t\t\t// Number of trailer bytes in buffer.\n\tBYTE Trailer[SONARC_MARGIN];\t\t// Maximum number of 'order' samples needed.\n\n\n\tDWORD Pitch;\n\tWORD Flags;\n\n\t/*\n\t**\tThis flag indicates whether this sample needs servicing.\n\t**\tServicing entails filling one of the empty low buffers.\n\t*/\n\tshort int Service;\n\n\t/*\n\t**\tThis flag is TRUE when the sample has stopped playing,\n\t**\tBUT there is more data available.  The sample must be\n\t**\trestarted upon filling the low buffer.\n\t*/\n\tBOOL Restart;\n\n\t/*\n\t**\tStreaming control handlers.\n\t*/\n\tBOOL (*Callback)(short int id, short int *odd, VOID **buffer, LONG *size);\n\tVOID\t*QueueBuffer;\t// Pointer to continued sample data.\n\tLONG\tQueueSize;\t\t// Size of queue buffer attached.\n\tshort int\tOdd;\t\t\t\t// Block number tracker (0..StreamBufferCount-1).\n\tint\tFilePending;\t// Number of buffers already filled ahead.\n\tlong\tFilePendingSize;\t// Number of bytes in last filled buffer.\n\n\t/*\n\t**\tThe file variables are used when streaming directly off of the\n\t**\thard drive.\n\t*/\n\tint\tFileHandle;\t\t// Streaming file handle (ERROR = not in use).\n\tVOID\t*FileBuffer;\t// Temporary streaming buffer (allowed to be freed).\n\t/*\n\t** The following structure is used if the sample if compressed using\n\t** the sos 16 bit compression Codec.\n\t*/\n\n\t_SOS_COMPRESS_INFO sosinfo;\n\n\n} SampleTrackerType;\n\n\ntypedef struct LockedData {\n\tunsigned int \t\tDigiHandle; \t\t\t// = -1;\n\tBOOL \t\t\t\t\tServiceSomething;\t\t// = FALSE;\n\tlong \t\t\t\t\tMagicNumber; \t\t\t// = 0xDEAF;\n\tVOID \t\t\t\t\t*UncompBuffer;\t\t\t// = NULL;\n\tlong \t\t\t\t\tStreamBufferSize; \t// = (2*SECONDARY_BUFFER_SIZE)+128;\n\tshort \t\t\t\tStreamBufferCount; \t// = 32;\n\tSampleTrackerType SampleTracker[MAX_SFX];\n\tunsigned int\t\tSoundVolume;\n\tunsigned int\t\tScoreVolume;\n\tBOOL\t\t\t\t\t_int;\n} LockedDataType;\n\nextern LockedDataType LockedData;\n#pragma pack(4);\n\nvoid Init_Locked_Data(void);\nlong Simple_Copy(void ** source, long * ssize, void ** alternate, long * altsize, void **dest, long size);\nlong Sample_Copy(SampleTrackerType *st, void ** source, long * ssize, void ** alternate, long * altsize, void * dest, long size, SCompressType scomp, void * trailer, short int *trailersize);\nVOID far __cdecl maintenance_callback(VOID);\nVOID __cdecl far DigiCallback(unsigned int driverhandle, unsigned int callsource, unsigned int sampleid);\nvoid far HMI_TimerCallback(void);\nvoid *Audio_Add_Long_To_Pointer(void const *ptr, long size);\nvoid\tDPMI_Unlock(VOID const *ptr, long const size);\nextern \"C\" {\n\tvoid __cdecl Audio_Mem_Set(void const *ptr, unsigned char value, long size);\n//\tvoid\tMem_Copy(void *source, void *dest, unsigned long bytes_to_copy);\n\tlong  __cdecl Decompress_Frame(void * source, void * dest, long size);\n\tint\t__cdecl Decompress_Frame_Lock(void);\n\tint\t__cdecl Decompress_Frame_Unlock(void);\n\tint\t__cdecl sosCODEC_Lock(void);\n\tint\t__cdecl sosCODEC_Unlock(void);\n\tvoid\t__GETDS(void);\n}\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/SOUNDIO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Id: soundio.cpp 1.41 1994/06/20 15:01:39 joe_bostic Exp $ */\n/***********************************************************************************************\n **             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             **\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Sound Library                                                *\n *                                                                                             *\n *                    File Name : SOUND.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 22, 1991                                                *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Load_Long_Sample -- Loads a sample into XMS for double buffer system.                     *\n *   Read_Long_Sample -- Loads/Processes/Formats/Builds offset.                                             *\n *   Save_Table_Entry -- Put an entry in the offset table.                                     *\n *   Play_Long_Sample -- Calls Init_Long_Sample and Start_Long_Sample.                         *\n *   Start_Long_Sample -- Starts a sample playing that has be initialized.                     *\n *   Get_Table_Entry -- Gets next entry in table.                                              *\n *   Long_Sample_Ticks -- Gets number of ticks in sample if in header.                         *\n *   Long_Sample_Status -- Returns the status of the sample.                                   *\n *   Find_Table_Entry -- Finds next entry in table that matches mask.                          *\n *   Get_Table_Start -- Returns a pointer to first entry in table.                             *\n *   Long_Sample_Ticks_Played -- Number of ticks since sample started.                         *\n *   Install_Sample_Driver_Callback -- Pokes callback function into JM driver                  *\n *   Stop_Long_Sample -- Stops current long sample from playing.                               *\n *   Long_Sample_Loaded_Size -- Max buffer size to load a long sample.                         *\n *   Sound_Callback -- Audio driver callback function.                                         *\n *   DigiCallback -- Low level double buffering handler.                                       *\n *   Load_Sample_Into_Buffer -- Loads a digitized sample into a buffer.                        *\n *   Stream_Sample -- Streams a sample directly from a file.                                   *\n *   Sample_Read -- Reads sample data from an openned file.                                    *\n *   Continue_Sample -- Tags another block of data onto the currently playing.                 *\n *   Sample_Copy -- Copies sound data from source format to raw format.                        *\n *   File_Stream_Preload -- Handles initial proload of a streaming samples bu*\n *   Sample_Length -- returns length of a sample in ticks                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nextern\tvoid Colour_Debug (int call_number);\n#pragma \tpack(4)\n\n#define WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n\n#include\t<windows.h>\n#include\t<windowsx.h>\n#include\t\"dsound.h\"\n\n#include\t<mem.h>\n#include\t<wwmem.h>\n#include\t\"soundint.h\"\n#include\t<stdio.h>\n#include\t<string.h>\n#include\t<direct.h>\n#include\t<stdlib.h>\n#include <process.h>\n#include\t<keyboard.h>\n#include\t<file.h>\n#include\t<bios.h>\n#include\t<timer.h>\n#pragma\t\tpack(1)\n#include\t\"audio.h\"\n#pragma\t\tpack(4)\n\nLPDIRECTSOUNDBUFFER\tDumpBuffer;\nHANDLE\t\t\t\t\t\tSoundThreadHandle = NULL;\nBOOL\t\t\t\t\t\tSoundThreadActive = FALSE;\n\n/*\n**      If this is defined, then the streaming audio buffer will be filled\n**      to maximum whenever filling is to occur. If undefined, it will fill\n**      the streaming buffer in smaller chunks.\n*/\n#define SIMPLE_FILLING\n\n/*\n**      This is the number of times per sec that the maintenance callback gets called.\n*/\n#define MAINTENANCE_RATE                        40\t//30 times per sec plus a safety margin\n\n/*\n**      Size of the temporary buffer in XMS/EMS that direct file\n**      streaming of sounds will allocate.\n*/\n//#define STREAM_BUFFER_SIZE              (128L*1024L)\n#define STREAM_BUFFER_SIZE              (128L*1024L)\n\n/*\n** Define the number of \"StreamBufferSize\" blocks that are read in\n** at a minimum when the streaming sample load callback routine\n** is called.  We will IGNORE loads that are less that this in order\n** to avoid constant seeking on the CD.\n*/\n#define STREAM_CUSHION_BLOCKS   4\n\n\n/*\n**      This is the maximum size that a sonarc block can be.  All sonarc blocks\n**      must be either a multiple of this value or a binary root of this value.\n*/\n#define LARGEST_SONARC_BLOCK            2048\n\n\n//////////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////// structs ///////////////////////////////////////\n\n//void\t\t\t\t\t\t*DigiBuffer = NULL;\nstatic BOOL\t\t\t\tStartingFileStream = FALSE;\nshort\t\t\t\t\t\tStreamLowImpact = FALSE;\nMemoryFlagType\t\t\tStreamBufferFlag = MEM_NORMAL;\nint\t\t\t\t\t\t\tMisc;\nSFX_Type\t\t\t\t\tSoundType;\nSample_Type\t\t\t\tSampleType;\nint\t\t\t\t\t\t\tReverseChannels = FALSE;\nLPDIRECTSOUND\t\t\tSoundObject;\t\t\t//Direct sound object\nLPDIRECTSOUNDBUFFER\tPrimaryBufferPtr;\t\t//Pointer to the  buffer that the\nunsigned\t\t\t\t\tSoundTimerHandle=0;\t//Windows Handle for sound timer\nWAVEFORMATEX\t\t\t\tDsBuffFormat;\t\t\t//format of direct sound buffer\nDSBUFFERDESC\t\t\t\tBufferDesc;\t\t\t\t//Buffer description for creating buffers\nWAVEFORMATEX\t\t\t\tPrimaryBuffFormat;\t//Copy of format of direct sound primary buffer\nDSBUFFERDESC\t\t\t\tPrimaryBufferDesc;\t//Copy of buffer description for re-creating primary buffer\nCRITICAL_SECTION\t\tGlobalAudioCriticalSection;\n/*\n** Function to call if we detect focus loss\n*/\nextern\tvoid (*Audio_Focus_Loss_Function)(void) = NULL;\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nstatic BOOL File_Callback(short id, short *odd, void **buffer, long *size);\nstatic int __cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback)(short id, short *odd, void **buffer, long *size), int volume, int handle);\nvoid CALLBACK Sound_Timer_Callback ( UINT, UINT, DWORD, DWORD, DWORD );\n//static int __cdecl Stream_Sample(void *buffer, long size, BOOL (*callback)(short id, short *odd, void **buffer, long *size));\nvoid Sound_Thread (void *);\nvolatile BOOL AudioDone;\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n// This callback is called whenever the queue buffer playback has begun\n// and another buffer is needed for queuing up.  Returns TRUE if there\n// is more data to read from the file.\nstatic BOOL File_Callback(short id, short *odd, void **buffer, long *size)\n{\n\tSampleTrackerType       *st;            // Pointer to sample playback control struct.\n\tvoid                    *ptr;           // Pointer to working portion of file buffer.\n\n\tif (id != -1) {\n\t\tst = &LockedData.SampleTracker[id];\n\t \tptr = st->FileBuffer;\n\t \tif (ptr) {\n\n\t \t  \t/*\n\t \t  \t** Move the next pending block into the primary\n\t \t  \t** position.  Do this only if the queue pointer is\n\t \t  \t** null.\n\t \t  \t*/\n\t\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t \t  \tst->DontTouch = TRUE;\n\t\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t \t  \tif (!*buffer && st->FilePending) {\n\t \t  \t\t*buffer = Add_Long_To_Pointer(ptr, (long)(*odd % LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t \t  \t\tst->FilePending--;\n\t \t  \t\t*odd = (short)(*odd + 1);\n\t \t  \t\tif (!st->FilePending) {\n\t \t  \t\t\t*size = st->FilePendingSize;\n\t \t  \t\t} else {\n\t \t  \t\t\t*size = LockedData.StreamBufferSize;\n\t \t  \t\t}\n\t \t  \t}\n\t\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t \t  \tst->DontTouch = FALSE;\n\t\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\tSound_Timer_Callback(0,0,0,0,0);\t//Shouldnt block as we are calling it from the same thread\n\n\t \t  \t/*\n\t \t  \t** If the file handle is still valid, then read in the next\n\t \t  \t** block and add it to the next pending slot available.\n\t \t  \t*/\n\t \t  \tif (st->FilePending <\n\t \t  \t\t(StreamLowImpact ? (LockedData.StreamBufferCount>>1) : ((LockedData.StreamBufferCount-3))) && st->FileHandle != WW_ERROR) {\n\n\n\t \t  \t\tint num_empty_buffers;\n\n#ifdef SIMPLE_FILLING\n\t\t\t\tnum_empty_buffers = (LockedData.StreamBufferCount-2) - st->FilePending;\n#else\n\n\t\t\t\t//\n\t\t\t\t// num_empty_buffers will be from 1 to StreamBufferCount\n\t\t\t\t//\n\t\t\t\tif (StreamLowImpact) {\n\t\t\t\t\tnum_empty_buffers = MIN((LockedData.StreamBufferCount >> 1)+STREAM_CUSHION_BLOCKS, (LockedData.StreamBufferCount - 2) - st->FilePending);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tnum_empty_buffers = (LockedData.StreamBufferCount - 2) - st->FilePending;\n\t\t\t\t}\n#endif\n\n\t\t\t\twhile (num_empty_buffers && (st->FileHandle != WW_ERROR)) {\n\t\t\t\t\tint     tofill;\n\t\t\t\t\tlong    psize;\n\n\t\t\t\t\ttofill = (*odd + st->FilePending) % LockedData.StreamBufferCount;\n\n\t\t\t\t\tptr = Add_Long_To_Pointer(st->FileBuffer, (long)tofill * (long)LockedData.StreamBufferSize);\n\t\t\t\t\tpsize = Read_File(st->FileHandle, ptr, LockedData.StreamBufferSize);\n\n\t\t\t\t \t/*\n\t\t\t\t \t**      If less than the requested amount of data was read, this\n\t\t\t\t \t**      indicates that the source file is exhausted.  Flag the source\n\t\t\t\t \t**      file as closed so that no further reading is attempted.\n\t\t\t\t \t*/\n\t\t\t\t \tif (psize != LockedData.StreamBufferSize) {\n\t\t\t\t \t\tClose_File(st->FileHandle);\n\t\t\t\t\t\tst->FileHandle = WW_ERROR;\n\t\t\t\t \t}\n\n                /*\n\t\t\t\t \t**      If any real data went into the pending buffer, then flag\n\t\t\t\t \t**      that this buffer is valid.\n                */\n\t\t\t\t \tif (psize) {\n\t\t\t\t\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\t\t\tst->DontTouch = TRUE;\n\t\t\t\t \t  \tst->FilePendingSize = psize;\n\t\t\t\t \t  \tst->FilePending++;\n\t\t\t\t \t  \tst->DontTouch = FALSE;\n\t\t\t\t\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\t\t\tSound_Timer_Callback(0,0,0,0,0);\t//Shouldnt block as we are calling it from the same thread\n\t\t\t\t \t}\n\t\t\t\t \tnum_empty_buffers--;\n\t\t\t\t}\n\n\t\t\t\t/*\n             **  After filling all pending buffers, check to see if the queue buffer\n\t\t\t\t**  is empty.  If so, then assign the first available pending buffer to the\n             **  queue.\n\t\t\t\t*/\n\t\t\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\tst->DontTouch = TRUE;\n             if (!st->QueueBuffer && st->FilePending) {\n\t\t\t\t\tst->QueueBuffer = Add_Long_To_Pointer(st->FileBuffer, (long)(st->Odd%LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t\t\t\t\tst->FilePending--;\n                st->Odd++;\n                if (!st->FilePending) {\n\t\t\t\t\t\tst->QueueSize = st->FilePendingSize;\n\t\t\t\t\t} else {\n                \tst->QueueSize = LockedData.StreamBufferSize;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tst->DontTouch = FALSE;\n\t\t\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\tSound_Timer_Callback(0,0,0,0,0);\t//Shouldnt block as we are calling it from the same thread\n\t\t\t}\n\n\t\t\t/*\n          **      If there are no more buffers that the callback routine\n\t\t\t**      can slot into the primary position, then signal that\n\t\t\t**      no furthur callbacks are needed.\n\t\t\t*/\n\t\t\tif (st->FilePending) {\n\t\t\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\treturn(TRUE);\n\t\t\t}\n\t\t}\n\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\n\t}\n  return(FALSE);\n}\n\n\n\n\n\n// Generic streaming sample playback initialization.\nstatic int __cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback)(short id, short *odd, void **buffer, long *size), int volume, int handle)\n{\n\tint\t\t\t\t\t\t\t\tplayid=-1;      // Sample play ID.\n\tSampleTrackerType               *st;                    // Working pointer to sample control structure.\n\tlong\t\t\t\t\t\t\toldsize;                // Copy of original sound size.\n\tAUDHeaderType                   header;\n\n\tif (buffer && size && LockedData.DigiHandle != -1) {\n\n\t\t/*\n\t \t** Start the first section of the sound playing.\n\t \t*/\n\t \tMem_Copy(buffer, &header, sizeof(header));\n\t \toldsize = header.Size;\n\t \theader.Size = size-sizeof(header);\n\t \tMem_Copy(&header, buffer, sizeof(header));\n\t \tplayid = Play_Sample_Handle(buffer, 0xFF, volume, 0x0, handle);\n\t \theader.Size = oldsize;\n\t \tMem_Copy(&header, buffer, sizeof(header));\n\n\t \t/*\n\t \t** If the sample actually started playing, then flag this\n\t \t** sample as a streaming type and signal for a callback\n\t \t** to occur.\n\t \t*/\n\t \tif (playid != -1) {\n\t \t\tst = &LockedData.SampleTracker[playid];\n\n\t \t\tst->Callback = callback;\n\t \t\tst->Odd = 0;\n//             ServiceSomething = TRUE;\n    \t}\n\t}\n\t\t  return (playid);\n}\n\n\n\n#if (0)\nstatic int __cdecl Stream_Sample(void *buffer, long size, BOOL (*callback)(short id, short *odd, void **buffer, long *size), int handle)\n{\n\treturn Stream_Sample_Vol(buffer, size, callback, 0xFF, handle);\n}\n#endif\n\n\n/***********************************************************************************************\n * File_Stream_Sample -- Streams a sample directly from a file.                                *\n *                                                                                             *\n *    This will take the file specified and play it directly from disk.                        *\n *    It performs this by allocating a temporary buffer in XMS/EMS and                         *\n *    then keeping this buffer filled by the Sound_Callback() routine.                         *\n *                                                                                             *\n * INPUT:   filename -- The name of the file to play.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the handle to the sound -- just like Play_Sample().                        *\n *                                                                                             *\n * WARNINGS:   The temporary buffer is allocated when this routine is                          *\n *             called and then freed when the sound is finished.  Keep                         *\n *             this in mind.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint File_Stream_Sample(char const *filename, BOOL real_time_start)\n{\n\treturn File_Stream_Sample_Vol(filename, 0xFF, real_time_start);\n}\n\n/***************************************************************************\n * FILE_STREAM_PRELOAD -- Handles initial proload of streaming samples     *\n *                                                                         *\n * This function is called before a sample which streams from disk is      *\n * started.  It can be called to either fill the buffer in small chunks    *\n * from the call back routine or to fill the entire buffer at once.  This  *\n * is wholely dependant on whether the Loading bit is set within the       *\n * sample tracker.                                                         *\n *                                                                         *\n * INPUT:LockedData.SampleTracker * to the header which tracks this samples*\n *                                                              processing.*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/05/1995 PWG : Created.                                             *\n *=========================================================================*/\n\nvoid File_Stream_Preload(int handle)\n{\n\tSampleTrackerType\t*st\t\t= &LockedData.SampleTracker[handle];\n\tint\t\t\t\t\tfh\t\t\t= st->FileHandle;\n\tint\t\t\t\t\tmaxnum\t= (LockedData.StreamBufferCount >> 1) + STREAM_CUSHION_BLOCKS;\n\tvoid\t\t\t\t\t*buffer\t= st->FileBuffer;\n\tint\t\t\t\t\tnum;\n\n\t/*\n    ** Figure just how much we need to load.  If we are doing the load in progress\n\t** then we will only load two blocks.\n\t*/\n    if (st->Loading) {\n    \tnum = st->FilePending + 2;\n       num = MIN(num, maxnum);\n    } else {\n\t\tnum = maxnum;\n\t}\n\n\t//EnterCriticalSection(&GlobalAudioCriticalSection);\n\n    /*\n    ** Loop through the blocks and load up the number we need.\n    */\n    for (int index = st->FilePending; index < num; index++) {\n\t\tlong s = Read_File(fh, Add_Long_To_Pointer(buffer, (long)index * (long)LockedData.StreamBufferSize), LockedData.StreamBufferSize);\n       if (s) {\n         \tst->FilePendingSize = s;\n\t  \t\tst->FilePending++;\n\t\t}\n\t\tif (s < LockedData.StreamBufferSize) break;\n    }\n\n\tSound_Timer_Callback(0,0,0,0,0);\t//Shouldnt block as we are calling it from the same thread\n\n\n\t/*\n\t** If the last block was incomplete (ie. it didn't completely fill the buffer) or\n\t** we have now filled up as much of the Streaming Buffer as we need to, then now is\n\t** the time to kick off the sample.\n\t*/\n\tif (st->FilePendingSize < LockedData.StreamBufferSize || index == maxnum) {\n\n\t\t/*\n\t\t** Actually start the sample playing, and don't worry about the file callback\n\t\t** it won't be called for a while.\n\t\t*/\n \t\tint old\t\t\t\t\t\t= LockedData.SoundVolume;\n\t\tint size\t\t\t\t\t\t= (st->FilePending == 1) ? st->FilePendingSize : LockedData.StreamBufferSize;\n\t\tLockedData.SoundVolume\t= LockedData.ScoreVolume;\n\t\tStartingFileStream\t\t= TRUE;\n\n\t\tStream_Sample_Vol(buffer, size, File_Callback, st->Volume, handle);\n\t\tStartingFileStream\t\t= FALSE;\n       LockedData.SoundVolume\t= old;\n\n\t\t/*\n\t\t** The Sample is finished loading (if it was loading in small pieces) so record that\n\t\t** so that it will now use the active logic in the file call back.\n\t\t*/\n\t\tst->Loading\t\t\t\t\t= FALSE;\n\n\t\t/*\n\t\t** Decrement the file pending because the first block is already playing thanks\n\t\t** to the play sample call above.\n\t\t*/\n\t\tst->FilePending--;\n\n\t\t/*\n\t\t** If File pending is now a zero, then we only preloaded one block and there\n\t\t** is nothing more to play.  So clear the sample tracing structure of the\n\t\t** information it no longer needs.\n\t\t*/\n\t\tif (!st->FilePending) {\n\t\t\tst->Odd\t\t\t\t\t= 0;\n          st->QueueBuffer\t\t= 0;\n\t\t\tst->QueueSize\t\t\t= 0;\n\t\t\tst->FilePendingSize\t= 0;\n          st->Callback\t\t\t= NULL;\n\t\t\tClose_File(fh);\n\t\t} else {\n\t\t\t/*\n\t\t\t** The QueueBuffer counts as an already played block so remove it from the total.\n          ** Note: We didn't remove it before because there might not have been one.\n          */\n          st->FilePending--;\n\n          /*\n          ** When we start loading we need to start past the first two blocks.  Why this\n          ** is called Odd, I haven't got the slightest.\n\t\t\t*/\n          st->Odd = 2;\n\n          /*\n          ** If the file pending size is less than the stream buffer, then the last block\n          ** we loaded was the last block period.  So close the file and reset the handle.\n          */\n          if (st->FilePendingSize != LockedData.StreamBufferSize) {\n\t\t\t\tClose_File(fh);\n             st->FileHandle = WW_ERROR;\n          }\n\n          /*\n          ** The Queue buffer needs to point at the next block to be processed.  The size\n          ** of the queue is dependant on how many more blocks there are.\n          */\n\t\t\tst->QueueBuffer = Add_Long_To_Pointer(buffer, LockedData.StreamBufferSize);\n\t\t\tif (!st->FilePending) {\n          \tst->QueueSize = st->FilePendingSize;\n          } else {\n          \tst->QueueSize = LockedData.StreamBufferSize;\n          }\n\t\t}\n\t}\n\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\n}\n\n\n\n\n\n\n\n/***********************************************************************************************\n * File_Stream_Sample_Vol -- Streams a sample directly from a file.                            *\n *                                                                                             *\n *    This will take the file specified and play it directly from disk.                        *\n *    It performs this by allocating a temporary buffer in XMS/EMS and                         *\n *    then keeping this buffer filled by the Sound_Callback() routine.                         *\n *                                                                                             *\n * INPUT:   filename -- The name of the file to play.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the handle to the sound -- just like Play_Sample().                        *\n *                                                                                             *\n * WARNINGS:   The temporary buffer is allocated when this routine is                          *\n *             called and then freed when the sound is finished.  Keep                         *\n *             this in mind.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *=============================================================================================*/\n\nint File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start)\n{\n\tstatic void     *buffer = NULL;\n\tSampleTrackerType       *st;\n\tint     fh;\n\tint     handle = -1;\n\tint     index;\n\n\tif (LockedData.DigiHandle != -1 && filename && Find_File(filename)) {\n\n\t/*\n\t**  Make sure all sample tracker structures point to the same\n\t**  upper memory buffer.  This allocation only occurs if at\n\t**  least one sample gets \"streamed\".\n\t*/\n\tif (!buffer) {\n\t\tbuffer = Alloc(LockedData.StreamBufferSize * LockedData.StreamBufferCount, (MemoryFlagType)(StreamBufferFlag | MEM_TEMP | MEM_LOCK));\n       for (index = 0; index < MAX_SFX; index++) {\n       \tLockedData.SampleTracker[index].FileBuffer = buffer;\n\t\t}\n\t}\n\t/*\n\t** If after trying to allocate the buffer we still fail then\n\t** we can stream this sample.\n\t*/\n\tif (!buffer) return(-1);\n\n\n    \t/*\n    \t** Lets see if we can sucessfully open up the file.  If we can't,\n    \t** then there is no point in going any farther.\n    \t*/\n    \tif ((fh = Open_File(filename, READ)) == -1) {\n \t \t\t\treturn (-1);\n    \t}\n\n\t\t/*\n\t\t** Reserve a handle so that we can fill in the sample tracker\n\t\t** with the needed information.  If we dont get valid handle then\n\t\t** we might as well give up.\n\t\t*/\n\t\tif ((unsigned)(handle = Get_Free_Sample_Handle(0xFF)) >= MAX_SFX) {\n \t\t\t\treturn(-1);\n\t\t}\n\n\t\t/*\n\t\t** Now lets get a pointer to the proper sample handler and start\n\t\t** our manipulations.\n\t\t*/\n\t\tst\t\t\t\t\t\t\t= &LockedData.SampleTracker[handle];\n\t\tst->IsScore\t\t\t\t= TRUE;\n\t\tst->FilePending\t\t= 0;\n\t\tst->FilePendingSize\t= 0;\n\t\tst->Loading\t\t\t\t= real_time_start;\n\t\tst->Volume\t\t\t\t= volume;\n\t\tst->FileHandle\t\t\t= fh;\n\n\t\t/*\n\t\t** Now that we have setup our initial data properly, let load up\n\t\t** the beginning of the sample we intend to stream.\n\t\t*/\n\t\tFile_Stream_Preload(handle);\n\t}\n\n\treturn (handle);\n}\n\n/***********************************************************************************************\n * Sound_Callback -- Audio driver callback function.                                           *\n *                                                                                             *\n *    Maintains the audio buffers.  This routine must be called at least                       *\n *    11 times per second or else audio glitches will occur.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If this routine is not called often enough then audio                           *\n *             glitches will occur.                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid __cdecl Sound_Callback(void)\n{\n\tint\t\t\t\t\tindex;\n    SampleTrackerType\t*st;\n\n    if (LockedData.DigiHandle != -1) {\n\n\t\t/*\n\t\t** Call the timer callback now as we may block it in this function\n\t\t*/\n\t\tSound_Timer_Callback(0,0,0,0,0);\n\n\t\tst = &LockedData.SampleTracker[0];\n\t\tfor (index = 0; index < MAX_SFX; index++) {\n\t\t\tif (st->Loading) {\n\t\t\t\tFile_Stream_Preload(index);\n\t\t\t} else {\n          \t/*\n          \t**  General service routine to handle moving small blocks from the\n          \t**  source into the low RAM staging buffers.\n          \t*/\n\n\t\t\t\tif (st->Active) {\n\n\t\t\t\t\t/*\n          \t\t**  Special check to see if the sample is a fading one AND\n          \t\t**  it has faded to silence, then stop it here.\n          \t\t*/\n          \t\tif (st->Reducer && !st->Volume) {\n\t\t\t\t\t\t//EnterCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\t\t\tStop_Sample(index);\n\t\t\t\t\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\t\t} else {\n\n          \t\t\t/*\n             \t\t**  Fill the queuebuffer if it is currently empty\n             \t\t**  and there is a callback function defined to fill it.\n             \t\t**\n             \t\t** PWG/CDY & CO: We should be down by at least two blocks\n\t\t\t\t\t\t**                                        before we bother with this\n             \t\t*/\n\n             \t\tif ((!st->QueueBuffer ||\n\t\t\t\t\t\t\t(st->FileHandle != WW_ERROR && st->FilePending < LockedData.StreamBufferCount-3)) &&\n\t\t\t\t \t\t\tst->Callback) {\n\n                \t\tif (!st->Callback((short)index, (short int *)&st->Odd, &st->QueueBuffer, &st->QueueSize)) {\n\t\t\t\t\t\t\t\tst->Callback = NULL;\n                \t\t}\n             \t\t}\n          \t\t}\n\n\t\t\t\t} else {\n\n          \t\t/*\n          \t\t** This catches the case where a streaming sample gets\n          \t\t** aborted prematurely because of failure to call the\n          \t\t** callback function frequently enough.  In this case, the\n          \t\t** sample will be flagged as inactive, but the file handle\n          \t\t** will not have been closed.\n          \t\t*/\n          \t\tif (st->FileHandle != WW_ERROR) {\n\t\t\t\t\t\t//EnterCriticalSection(&GlobalAudioCriticalSection);\n          \t\t\tClose_File(st->FileHandle);\n             \t\tst->FileHandle = WW_ERROR;\n\t\t\t\t\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n          \t\t}\n\t\t\t\t}\n\t\t\t}\n\n          /*\n          **      Advance to the next sample control structure.\n\t\t\t*/\n    \t\tst++;\n\t\t}\n\n    }\n}\n\n\n/***********************************************************************************************\n * Load_Sample -- Loads a digitized sample into RAM.                                           *\n *                                                                                             *\n *    This routine loads a digitized sample into RAM.                                          *\n *                                                                                             *\n * INPUT:   filename -- Name of the sound file to load.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the loaded sound file.  This pointer                     *\n *          is passed to Play_Sample when playback is desired.                                 *\n *                                                                                             *\n * WARNINGS:   If there is insufficient memory to load the sample, then                        *\n *             NULL will be returned.                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *   01/06/1994 JLB : HMI version.                                                             *\n *=============================================================================================*/\nvoid *Load_Sample(char const *filename)\n{\n\tvoid *buffer = NULL;\n\tlong    size;\n\tint     fh;\n\n\tif (LockedData.DigiHandle == -1 || !filename || !Find_File(filename)) {\n\t\treturn (NULL);\n\t}\n\n\tfh = Open_File(filename, READ);\n\tif (fh != WW_ERROR) {\n\t\tsize = File_Size(fh)+sizeof(AUDHeaderType);\n\t\tbuffer = Alloc(size, MEM_NORMAL);\n\n\t\tif (buffer) {\n\t\t\tSample_Read(fh, buffer, size);\n\t\t}\n\t\tClose_File(fh);\n\t\tMisc = size;\n\t}\n\treturn(buffer);\n}\n\n\n/***********************************************************************************************\n * Load_Sample_Into_Buffer -- Loads a digitized sample into a buffer.                          *\n *                                                                                             *\n *    This routine is used to load a digitized sample into a buffer                            *\n *    provided by the programmer.  This buffer can be in XMS or EMS.                           *\n *                                                                                             *\n * INPUT:   filename -- The filename to load.                                                  *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer to load into.                                    *\n *                                                                                             *\n *          size     -- The size of the buffer to load into.                                   *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually used in the buffer.                           *\n *                                                                                             *\n * WARNINGS:   This routine will not overflow the buffer provided.  This                       *\n *             means that the buffer must be big enough to hold the data                       *\n *             or else the sound will be cut short.                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Load_Sample_Into_Buffer(char const *filename, void *buffer, long size)\n{\n\tint     fh;\n\n\t/*\n\t**      Verify legality of parameters.\n\t*/\n\tif (!buffer || !size || LockedData.DigiHandle == -1 || !filename || !Find_File(filename)) {\n\t\treturn (NULL);\n\t}\n\n\tfh = Open_File(filename, READ);\n\tif (fh != WW_ERROR) {\n\t\tsize = Sample_Read(fh, buffer, size);\n       Close_File(fh);\n\t} else {\n\t\treturn(0);\n\t}\n\treturn(size);\n}\n\n\n/***********************************************************************************************\n * Sample_Read -- Reads sample data from an openned file.                                      *\n *                                                                                             *\n *    This routine reads a sample file.  It is presumed that the file is                       *\n *    already positioned at the start of the sample.  From this, it can                        *\n *    determine if it is a VOC or raw data and proceed accordingly.                            *\n *                                                                                             *\n * INPUT:   fh       -- File handle of already openned sample file.                            *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer to load data into.                               *\n *                                                                                             *\n *          size     -- The size of the buffer.                                                *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually used in the buffer.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Sample_Read(int fh, void *buffer, long size)\n{\n\n\tAUDHeaderType\tRawHeader;\n\tvoid    \t\t\t*outbuffer;\t\t\t\t// Pointer to start of raw data.\n\tlong    \t\t\tactual_bytes_read;\t// Actual bytes read in, including header\n\n/*\n** Conversion formula for TCrate and Hz rate.\n**\n** TC = 256 - 1m/rate\n** rate = 1m / (256-TC)\n*/\n\n\tif (!buffer || fh == WW_ERROR || size <= sizeof(RawHeader)) return(NULL);\n\n\tsize -= sizeof(RawHeader);\n\toutbuffer = Add_Long_To_Pointer(buffer, sizeof(RawHeader));\n  \tactual_bytes_read = Read_File(fh, &RawHeader, sizeof(RawHeader));\n\tactual_bytes_read +=Read_File(fh, outbuffer, MIN(size, RawHeader.Size));\n\tMem_Copy(&RawHeader, buffer, sizeof(RawHeader));\n\treturn(actual_bytes_read);\n}\n\n\n/***********************************************************************************************\n * Free_Sample -- Frees a previously loaded digitized sample.                                  *\n *                                                                                             *\n *    Use this routine to free the memory allocated by a previous call to                      *\n *    Load_Sample.                                                                             *\n *                                                                                             *\n * INPUT:   sample   -- Pointer to the sample to be freed.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Free_Sample(void const *sample)\n{\n\tif (sample) Free((void *)sample);\n}\n\n\n\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Sound_Timer_Callback -- windows timer callback for sound maintenance                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:01PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid CALLBACK Sound_Timer_Callback ( UINT, UINT, DWORD, DWORD, DWORD )\n{\n\t//if (!InTimerCallback){\n\t\t//InTimerCallback++;\n\t\t//Colour_Debug (5);\n\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t\tmaintenance_callback();\n\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t//Colour_Debug (0);\n\t\t//InTimerCallback--;\n\t//}\n}\n\nvoid Sound_Thread (void *)\n{\n\tDuplicateHandle (GetCurrentProcess(), GetCurrentThread() , GetCurrentProcess() ,&SoundThreadHandle , THREAD_ALL_ACCESS , TRUE , 0);\n\tSetThreadPriority (SoundThreadHandle, THREAD_PRIORITY_TIME_CRITICAL);\n\tSoundThreadActive = TRUE;\n\n\twhile (!AudioDone){\n\n\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t\tmaintenance_callback();\n\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\tSleep(1000/40);\n\t}\n\n\tSoundThreadActive = FALSE;\n}\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Set_Primary_Buffer_Format -- set the format of the primary sound buffer                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   TRUE if successfully set                                                          *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    12/22/95 4:06PM ST : Created                                                             *\n *=============================================================================================*/\n\nBOOL Set_Primary_Buffer_Format(void)\n{\n\tif (SoundObject && PrimaryBufferPtr){\n\t\treturn (PrimaryBufferPtr->SetFormat ( &PrimaryBuffFormat ) == DS_OK);\n\t}\n\treturn (FALSE);\n}\n\n\n\n/***********************************************************************************************\n * Print_Sound_Error -- show error messages from failed sound initialisation                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    error text                                                                        *\n *           handle to window                                                                  *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    2/7/96 10:17AM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Print_Sound_Error(char *sound_error, HWND window)\n{\n\tMessageBox(window, sound_error, \"Command & Conquer\", MB_ICONEXCLAMATION|MB_OK);\n}\n\n\n\n/***********************************************************************************************\n * Audio_Init -- Initialise the sound system                                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    window - window to send callback messages to                                      *\n *           maximum bits_per_sample - 8 or 16                                                 *\n *           stereo - will stereo samples be played                                            *\n *           rate - maximum sample rate required                                               *\n *           reverse_channels                                                                  *\n *                                                                                             *\n * OUTPUT:   TRUE if correctly initialised                                                     *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   Unknown....                                                                               *\n *   08-24-95 10:01am ST : Modified for Windows 95 Direct Sound                                *\n *=============================================================================================*/\n\nBOOL Audio_Init( HWND window , int bits_per_sample, BOOL stereo , int rate , int reverse_channels)\n{\n\tint\tindex;\n\tint\tsample=1;\n\tshort old_bits_per_sample;\n\tshort old_block_align;\n\tlong\told_bytes_per_sec;\n\n\n\tInit_Locked_Data();\n\tmemset(&LockedData.SampleTracker[0], 0, sizeof(LockedData.SampleTracker));\n\n\tif ( !SoundObject ){\n\n\t\t/*\n\t\t**\tCreate the direct sound object\n\t\t*/\n\t\tif ( DirectSoundCreate (NULL,&SoundObject,NULL) !=DS_OK ) {\n\t\t\tPrint_Sound_Error(\"Warning - Unable to create Direct Sound Object\",window);\n\t\t\treturn (FALSE);\n\t\t}\n\n\t\t/*\n\t\t**\tGive ourselves exclusive access to it\n\t\t*/\n\t\tif ( SoundObject->SetCooperativeLevel( window, DSSCL_EXCLUSIVE ) != DS_OK){\n\t\t\tPrint_Sound_Error(\"Warning - Unable to set Direct Sound cooperative level\",window);\n\t\t\tSoundObject->Release();\n\t\t\tSoundObject = NULL;\n\t\t\treturn (FALSE);\n\t\t}\n\n\t\t/*\n\t\t** Set up the primary buffer structure\n\t\t*/\n\t\tmemset (&BufferDesc , 0 , sizeof(DSBUFFERDESC));\n\t\tBufferDesc.dwSize=sizeof(DSBUFFERDESC);\n\t\tBufferDesc.dwFlags=DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;\n\n\t\t/*\n\t\t**\tSet up the primary buffer format\n\t\t*/\n\t\tmemset (&DsBuffFormat , 0 , sizeof(WAVEFORMATEX));\n\t\tDsBuffFormat.wFormatTag\t\t= WAVE_FORMAT_PCM;\n\t\tDsBuffFormat.nChannels\t\t= (unsigned short) (1 + stereo);\n\t\tDsBuffFormat.nSamplesPerSec\t= rate;\n\t\tDsBuffFormat.wBitsPerSample\t= (short) bits_per_sample;\n\t\tDsBuffFormat.nBlockAlign\t= (unsigned short)( (DsBuffFormat.wBitsPerSample/8) * DsBuffFormat.nChannels);\n\t\tDsBuffFormat.nAvgBytesPerSec= DsBuffFormat.nSamplesPerSec * DsBuffFormat.nBlockAlign;\n\t\tDsBuffFormat.cbSize = 0;\n\n\n\t\t/*\n\t\t** Make a copy of the primary buffer description so we can reset its format later\n\t\t*/\n\t\tmemcpy (&PrimaryBufferDesc , &BufferDesc , sizeof(DSBUFFERDESC));\n\t\tmemcpy (&PrimaryBuffFormat , &DsBuffFormat , sizeof(WAVEFORMATEX));\n\n\t\t/*\n\t\t**\tCreate the primary buffer object\n\t\t*/\n\t\tif ( SoundObject->CreateSoundBuffer (&PrimaryBufferDesc ,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&PrimaryBufferPtr ,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tNULL ) !=DS_OK ){\n\t\t\tPrint_Sound_Error(\"Warning - Unable to create Direct Sound primary buffer\",window);\n\t\t\tSoundObject->Release();\n\t\t\tSoundObject = NULL;\n\t\t\treturn (FALSE);\n\t\t}\n\n\t\t/*\n\t\t** Set the format of the primary sound buffer\n\t\t**\n\t\t*/\n\t\tif (!Set_Primary_Buffer_Format()){\n\n\t\t\t/*\n\t\t\t** If we failed to create a 16 bit primary buffer - try for an 8bit one\n\t\t\t*/\n\t\t\tif (DsBuffFormat.wBitsPerSample == 16){\n\t\t\t\t/*\n\t\t\t\t** Save the old values\n\t\t\t\t*/\n\t\t\t\told_bits_per_sample\t= DsBuffFormat.wBitsPerSample;\n\t\t\t\told_block_align\t\t= DsBuffFormat.nBlockAlign;\n\t\t\t\told_bytes_per_sec\t\t= DsBuffFormat.nAvgBytesPerSec;\n\n\t\t\t\t/*\n\t\t\t\t** Set up the 8-bit ones\n\t\t\t\t*/\n\t\t\t\tDsBuffFormat.wBitsPerSample\t= 8;\n\t\t\t\tDsBuffFormat.nBlockAlign\t= (unsigned short)( (DsBuffFormat.wBitsPerSample/8) * DsBuffFormat.nChannels);\n\t\t\t\tDsBuffFormat.nAvgBytesPerSec= DsBuffFormat.nSamplesPerSec * DsBuffFormat.nBlockAlign;\n\n\t\t\t\t/*\n\t\t\t\t** Make a copy of the primary buffer description so we can reset its format later\n\t\t\t\t*/\n\t\t\t\tmemcpy (&PrimaryBufferDesc , &BufferDesc , sizeof(DSBUFFERDESC));\n\t\t\t\tmemcpy (&PrimaryBuffFormat , &DsBuffFormat , sizeof(WAVEFORMATEX));\n\t\t\t}\n\n\t\t\tif (!Set_Primary_Buffer_Format()){\n\n\t\t\t\t/*\n\t\t\t\t** We failed to set any useful format so print up an error message and give up\n\t\t\t\t*/\n\t\t\t\tPrimaryBufferPtr->Release();\n\t\t\t\tPrimaryBufferPtr = NULL;\n\t\t\t\tSoundObject->Release();\n\t\t\t\tSoundObject = NULL;\n\n\t\t\t\tPrint_Sound_Error(\"Warning - Your sound card does not match C&C's audio requirements\",window);\n\n\t\t\t\treturn (FALSE);\n\t\t\t}else{\n\n\t\t\t\t/*\n\t\t\t\t** OK, got an 8bit sound buffer. Not perfect but it will do\n\t\t\t\t** We still want 16 bit secondary buffers so restore those values\n\t\t\t\t*/\n\t\t\t\tDsBuffFormat.wBitsPerSample\t= old_bits_per_sample;\n\t\t\t\tDsBuffFormat.nBlockAlign\t\t= old_block_align;\n\t\t\t\tDsBuffFormat.nAvgBytesPerSec\t= old_bytes_per_sec;\n\t\t\t}\n\t\t}\n\n\n\t\t/*\n\t\t** Start the primary sound buffer playing\n\t\t**\n\t\t*/if ( PrimaryBufferPtr->Play(0,0,DSBPLAY_LOOPING) != DS_OK ){\n\t\t\tPrint_Sound_Error(\"Unable to play Direct Sound primary buffer\",window);\n\t\t\tPrimaryBufferPtr->Release();\n\t\t\tPrimaryBufferPtr = NULL;\n\t\t\tSoundObject->Release();\n\t\t\tSoundObject = NULL;\n\t\t\treturn (FALSE);\n\t\t}\n\n\t\tLockedData.DigiHandle=1;\n\n\n\t\t/*\n\t\t** Initialise the global critical section object for sound thread syncronisation\n\t\t*/\n\t\tInitializeCriticalSection(&GlobalAudioCriticalSection);\n\n\t\t/*\n\t\t** Initialise the Windows timer system to provide us with a callback\n\t\t**\n\t\t*/\n\t\tSoundTimerHandle = timeSetEvent ( 1000/MAINTENANCE_RATE , 1 , Sound_Timer_Callback , 0 , TIME_PERIODIC);\n\t\tAudioDone = FALSE;\n\t\t//_beginthread(&Sound_Thread, NULL, 16*1024, NULL);\n\n\t\t/*\n\t\t**\tDefine the format for the secondary sound buffers\n\t\t*/\n\t\tBufferDesc.dwFlags=DSBCAPS_CTRLVOLUME;\n\t\tBufferDesc.dwBufferBytes=SECONDARY_BUFFER_SIZE;\n\t\tBufferDesc.lpwfxFormat = (LPWAVEFORMATEX) &DsBuffFormat;\n\n\n\n\t\t/*\n    \t** Allocate a decompression buffer equal to the size of a SONARC frame\n\t\t** block.\n    \t*/\n    \tLockedData.UncompBuffer = Alloc(LARGEST_SONARC_BLOCK + 50, (MemoryFlagType)(MEM_NORMAL|MEM_CLEAR|MEM_LOCK));\n\n    \t/*\n    \t** Allocate once secondary direct sound buffer for each simultaneous sound effect\n\t\t**\n    \t*/\n\t\tfor (index = 0; index < MAX_SFX; index++) {\n\n\t\t\tSoundObject->CreateSoundBuffer (&BufferDesc , &LockedData.SampleTracker[index].PlayBuffer , NULL);\n\n\t\t\tLockedData.SampleTracker[index].PlaybackRate\t= rate;\n\t\t\tLockedData.SampleTracker[index].Stereo\t\t\t= (stereo) ? AUD_FLAG_STEREO : 0;\n\t\t\tLockedData.SampleTracker[index].BitSize \t\t= (bits_per_sample == 16) ? AUD_FLAG_16BIT : 0;\n\t\t\tLockedData.SampleTracker[index].FileHandle \t= WW_ERROR;\n\t\t\tLockedData.SampleTracker[index].QueueBuffer \t= NULL;\n\t\t\tInitializeCriticalSection (&LockedData.SampleTracker[index].AudioCriticalSection);\n\n\t\t}\n\n\t\tSoundType = (SFX_Type)sample;\n\t\tSampleType = (Sample_Type)sample;\n\t\tReverseChannels = reverse_channels;\n\n\t}\n\n\treturn(TRUE);\n}\n\n\n/***********************************************************************************************\n * Sound_End -- Uninitializes the sound driver.                                                *\n *                                                                                             *\n *    This routine will uninitialize the sound driver (if any was                              *\n *    installed).  This routine must be called at program termination                          *\n *    time.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/23/1991 JLB : Created.                                                                 *\n *   11/02/1995 ST  : Modified for Direct Sound                                                *\n *=============================================================================================*/\nvoid Sound_End(void)\n{\n\n\tint\tindex;\n\n\tif (SoundObject && PrimaryBufferPtr){\n\t\t/*\n\t\t** Stop all sounds and release the Direct Sound secondary sound buffers\n\t\t*/\n\t\tfor (index=0 ; index < MAX_SFX; index++){\n\t\t\tif ( LockedData.SampleTracker[index].PlayBuffer ){\n\t\t\t\tStop_Sample (index);\n\t\t\t\tLockedData.SampleTracker[index].PlayBuffer->Stop();\n\t\t\t\tLockedData.SampleTracker[index].PlayBuffer->Release();\n\t\t\t\tLockedData.SampleTracker[index].PlayBuffer = NULL;\n\t\t\t\tDeleteCriticalSection(&LockedData.SampleTracker[index].AudioCriticalSection);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Stop and release the direct sound primary buffer\n\t*/\n\tif (PrimaryBufferPtr){\n\t\tPrimaryBufferPtr->Stop();\n\t\tPrimaryBufferPtr->Release();\n\t\tPrimaryBufferPtr = NULL;\n\t}\n\n\t/*\n\t** Release the Direct Sound Object\n\t*/\n\tif (SoundObject){\n\t\tSoundObject->Release();\n\t\tSoundObject = NULL;\n\t}\n\n\n\tif (LockedData.UncompBuffer) {\n    \tFree(LockedData.UncompBuffer);\n\t\tLockedData.UncompBuffer = 0;\n\t}\n\n\t/*\n\t** Remove the Windows timer event we installed for the sound callback\n\t*/\n\tif (SoundTimerHandle){\n\t\ttimeKillEvent(SoundTimerHandle);\n\t\tSoundTimerHandle = 0;\n\t}\n\tAudioDone = TRUE;\n\n\t/*\n\t** Since the timer has stopped, we are finished with our global critical section.\n\t*/\n\tDeleteCriticalSection(&GlobalAudioCriticalSection);\n}\n\n\n\n\n/***********************************************************************************************\n * Stop_Sample -- Stops any currently playing sampled sound.                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1992 JLB : Created.                                                                 *\n *   11/2/95 4:09PM ST : Modified for Direct Sound                                             *\n *=============================================================================================*/\nvoid Stop_Sample(int handle)\n{\n\tif (LockedData.DigiHandle != -1 && (unsigned)handle < MAX_SFX) {\n\n\t\tEnterCriticalSection (&GlobalAudioCriticalSection);\n\n\t\tif (LockedData.SampleTracker[handle].Active || LockedData.SampleTracker[handle].Loading) {\n\n\t\t\tLockedData.SampleTracker[handle].Active = FALSE;\n\n\t\t\tif (!LockedData.SampleTracker[handle].IsScore) {\n          \tLockedData.SampleTracker[handle].Original = NULL;\n\t\t\t}\n\n\t\t\tLockedData.SampleTracker[handle].Priority = 0;\n\n\t\t\t/*\n          **  Stop the sample if it is playing.\n          */\n\t\t\tif (!LockedData.SampleTracker[handle].Loading) {\n\t\t\t\tLockedData.SampleTracker[handle].PlayBuffer->Stop();\n          }\n\n\t\t\tLockedData.SampleTracker[handle].Loading = FALSE;\n\n          /*\n\t\t\t**  If this is a streaming sample, then close the source file.\n          */\n\t\t\tif (LockedData.SampleTracker[handle].FileHandle != WW_ERROR) {\n\t\t\t\tClose_File(LockedData.SampleTracker[handle].FileHandle);\n\t\t\t\tLockedData.SampleTracker[handle].FileHandle = WW_ERROR;\n\t\t\t}\n\n\t\t\tLockedData.SampleTracker[handle].QueueBuffer = NULL;\n\t\t}\n\t\tLeaveCriticalSection (&GlobalAudioCriticalSection);\n\t}\n}\n\n\n/***********************************************************************************************\n * Sample_Status -- Queries the current playing sample status (if any).                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nBOOL Sample_Status(int handle)\n{\n\tDWORD\tstatus;\n\n\t/*\n\t** If its an invalid handle or we do not have a sound driver then\n\t** the sample in question is not playing.\n\t*/\n\tif (LockedData.DigiHandle == -1 || (unsigned)handle >= MAX_SFX) return(FALSE);\n\n\t/*\n\t** If the sample is loading, then for all intents and purposes the\n\t** sample is playing.\n\t*/\n\tif (LockedData.SampleTracker[handle].Loading) return(TRUE);\n\n\t/*\n\t** If the sample is not active, then it is not playing\n\t*/\n\tif (!LockedData.SampleTracker[handle].Active) return(FALSE);\n\n\t/*\n\t** If we made it this far, then the Sample is still playing if sos says\n\t** that it is.\n\t*/\n\tDumpBuffer = LockedData.SampleTracker[handle].PlayBuffer;\n\tif (LockedData.SampleTracker[handle].PlayBuffer->GetStatus( &status ) == DS_OK){\n\t\treturn ( (DSBSTATUS_PLAYING & status) || (DSBSTATUS_LOOPING & status) );\n\t}else{\n\t\treturn (TRUE);\n\t}\n}\n\n\n\n/***********************************************************************************************\n * Is_Sample_Playing -- returns the play state of a sample                                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to sample data                                                                *\n *                                                                                             *\n * OUTPUT:   TRUE if sample is currently playing                                               *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:11PM ST : Commented                                                            *\n *=============================================================================================*/\n\nBOOL Is_Sample_Playing(void const * sample)\n{\n\tint index;\n\n\t//EnterCriticalSection(&GlobalAudioCriticalSection);\n\n\tif (!sample) {\n\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\treturn FALSE;\n\t}\n\tfor (index = 0; index < MAX_SFX; index++) {\n\t\tif (LockedData.SampleTracker[index].Original == sample && Sample_Status(index)) {\n\t\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\treturn (TRUE);\n\t\t}\n\t}\n\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\treturn (FALSE);\n}\n\n\n/***********************************************************************************************\n * Stop_Sample_Playing -- stops a playing sample                                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to sample data                                                                *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:13PM ST : Commented                                                            *\n *=============================================================================================*/\n\nvoid Stop_Sample_Playing(void const * sample)\n{\n\tint index;\n\n\tif (sample) {\n\t\tfor (index = 0; index < MAX_SFX; index++) {\n\t\t\tif (LockedData.SampleTracker[index].Original == sample) {\n\t\t\t\tStop_Sample(index);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n\n\n/***********************************************************************************************\n * Get_Free_Sample_Handle -- finds a free slot in which to play a new sample                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    priority of sample we want to play                                                *\n *                                                                                             *\n * OUTPUT:   Handle or -1 if none free                                                         *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:14PM ST : Added function header                                                *\n *=============================================================================================*/\n\nint Get_Free_Sample_Handle(int priority)\n{\n\tint     id;\n\n\t/*\n\t**      Find a free SFX holding buffer slot.\n\t*/\n\tfor (id = MAX_SFX - 1; id >= 0; id--) {\n\t\tif (!LockedData.SampleTracker[id].Active && !LockedData.SampleTracker[id].Loading) {\n\t\t\tif (!StartingFileStream && LockedData.SampleTracker[id].IsScore) {\n\t\t\t\tStartingFileStream = TRUE;      // Ensures only one channel is kept free for scores.\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (id < 0) {\n\t\tfor (id = 0; id < MAX_SFX; id++) {\n\t\t\tif (LockedData.SampleTracker[id].Priority <= priority) break;\n\t\t}\n\n\t\tif (id == MAX_SFX) {\n\t\t\treturn(-1);             // Cannot play!\n\t\t}\n\t\tStop_Sample(id);                                                        // This sample gets clobbered.\n\t}\n\n\tif (id == -1) {\n\t\treturn -1;\n\t}\n\n\tif (LockedData.SampleTracker[id].FileHandle != WW_ERROR) {\n\t\tClose_File(LockedData.SampleTracker[id].FileHandle);\n\t\tLockedData.SampleTracker[id].FileHandle = WW_ERROR;\n\t}\n\n\tif (LockedData.SampleTracker[id].Original && !LockedData.SampleTracker[id].IsScore) {\n\t\tLockedData.SampleTracker[id].Original = NULL;\n\t}\n\tLockedData.SampleTracker[id].IsScore = FALSE;\n\treturn(id);\n}\n\nint Play_Sample(void const *sample, int priority, int volume, signed short panloc)\n{\n\t\t  return(Play_Sample_Handle(sample, priority, volume, panloc, Get_Free_Sample_Handle(priority)));\n}\n\n\n\n\n\n/***********************************************************************************************\n * Attempt_Audio_Restore -- tries to restore the direct sound buffers                          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to direct sound buffer                                                        *\n *                                                                                             *\n * OUTPUT:   TRUE if buffer was successfully restored                                          *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 9:47AM ST : Created                                                              *\n *=============================================================================================*/\n\nBOOL Attempt_Audio_Restore (LPDIRECTSOUNDBUFFER sound_buffer)\n{\n\n\tint \treturn_code;\n\tDWORD\tplay_status;\n\tint\trestore_attempts=0;\n\n\t/*\n\t** Call the audio focus loss function if it has been set up\n\t*/\n\tif (Audio_Focus_Loss_Function){\n\t\tAudio_Focus_Loss_Function();\n\t}\n\n\t/*\n\t** Try to restore the sound buffer\n\t*/\n\tdo{\n\t\tRestore_Sound_Buffers();\n\t\treturn_code = sound_buffer->GetStatus ( &play_status );\n\n\t} while (restore_attempts++<2 && return_code == DSERR_BUFFERLOST);\n\n\treturn ((BOOL) ~(return_code == DSERR_BUFFERLOST));\n}\n\n\n\n\n/***********************************************************************************************\n * Play_Sample_Vol -- Plays a digitized sample.                                                *\n *                                                                                             *\n *    Use this routine to play a previously loaded digitized sample.                           *\n *                                                                                             *\n * INPUT:   sample   -- Sample pointer as returned from Load_Sample.                           *\n *                                                                                             *\n *          volume   -- The volume to play (0..255 with 255=loudest).                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *   05/24/1992 JLB : Volume support -- Soundblaster Pro                                       *\n *   04/22/1994 JLB : Multiple sample playback rates.                                          *\n *   11/02/1995 ST  : Windows Direct Sound support                                             *\n *=============================================================================================*/\nextern BOOL Any_Locked(void);\nint Play_Sample_Handle(void const *sample, int priority, int volume, signed short , int id)\n{\n\tAUDHeaderType                   RawHeader;\n\tSampleTrackerType               *st=NULL;       // Working pointer to sample tracker structure.\n\n\tLPVOID\t\t\t\tplay_buffer_ptr;\t\t//pointer to locked direct sound buffer\n\tLPVOID\t\t\t\tdummy_buffer_ptr;\t\t//dummy pointer to second area of locked direct sound buffer\n\tDWORD\t\t\t\t\tlock_length1;\n\tDWORD\t\t\t\t\tlock_length2;\n\tDWORD\t\t\t\t\tplay_status;\n\tHRESULT\t\t\t\treturn_code;\n\tint\t\t\t\t\tretries=0;\n\n\n\tif (Any_Locked()) return(0);\n\n\tst = &LockedData.SampleTracker[id];\n\t//EnterCriticalSection (&GlobalAudioCriticalSection);\n\n\tif (!sample || LockedData.DigiHandle == -1) {\n\t\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\treturn(-1);\n\t}\n\n\tif (id == -1) {\n\t\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\treturn -1;\n\t}\n\n\t/*\n\t**      Fetch the control bytes from the start of the sample data.\n\t*/\n\tMem_Copy((void *)sample, (void *)&RawHeader, sizeof(RawHeader));\n\n\t/*\n\t** Fudge the sample rate to 22k\n\t*/\n\tif (RawHeader.Rate <24000 && RawHeader.Rate >20000) RawHeader.Rate = 22050;\n\n\t/*\n\t**      Prepare the sample tracker structure for processing of this\n\t**      sample.  Fill the structure with data that can be determined\n\t**      before the sample is started.\n\t*/\n\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\tst->Compression \t\t\t= (SCompressType) ((unsigned char)RawHeader.Compression);\n\tst->Original            = sample;\n\tst->OriginalSize        = RawHeader.Size + sizeof(RawHeader);\n\tst->Priority            = (short)priority;\n\tst->DontTouch           = TRUE;\n\tst->Odd\t\t\t\t\t\t= 0;\n\tst->Reducer             = 0;\n\tst->Restart             = FALSE;\n\tst->QueueBuffer \t\t\t= NULL;\n\tst->QueueSize           = NULL;\n\tst->TrailerLen  \t\t\t= 0;\n\tst->Remainder           = RawHeader.Size;\n\tst->Source              = Add_Long_To_Pointer((void *)sample, sizeof(RawHeader));\n\tst->Service             = FALSE;\n\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\n    /*\n\t ** If the code in question using HMI based compression then we need\n    ** to set up for uncompressing it.\n\t */\n    if (st->Compression == SCOMP_SOS) {\n\t\tst->sosinfo.wChannels    = (RawHeader.Flags & AUD_FLAG_STEREO) ? 2  : 1;\n\t\tst->sosinfo.wBitSize             = (RawHeader.Flags & AUD_FLAG_16BIT)  ? 16 : 8;\n\t\tst->sosinfo.dwCompSize   = RawHeader.Size;\n\t\tst->sosinfo.dwUnCompSize = RawHeader.Size * ( st->sosinfo.wBitSize / 4 );\n\t\tsosCODECInitStream(&st->sosinfo);\n\t}\n\n\t/*\n\t** If the sample rate , bits per sample or stereo capabilities of the buffer do not\n\t** match the sample then reallocate the direct sound buffer with the required capabilities\n\t*/\n\tif (  ( RawHeader.Rate != st->PlaybackRate ) ||\n\t\t\t( ( RawHeader.Flags & AUD_FLAG_16BIT ) != ( st->BitSize & AUD_FLAG_16BIT ) ) ||\n\t\t\t( ( RawHeader.Flags & AUD_FLAG_STEREO) != ( st->Stereo & AUD_FLAG_STEREO ) ) ) {\n\n\t\tst->Active=0;\n\t\tst->Service=0;\n\t\tst->MoreSource=0;\n\n\t\t/*\n\t\t** Stop the sound buffer playing\n\t\t*/\n\t\tDumpBuffer = st->PlayBuffer;\n\t\tdo {\n\t\t\treturn_code = st->PlayBuffer->GetStatus ( &play_status );\n\t\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t\t}\n\t\t}while (return_code == DSERR_BUFFERLOST);\n\n\t\tif (play_status & (DSBSTATUS_PLAYING | DSBSTATUS_LOOPING) ){\n\t\t\tst->PlayBuffer->Stop();\n\t\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t\t}\n\t\t}\n\n\t\tst->PlayBuffer->Release();\n\t\tst->PlayBuffer=NULL;\n\n\t\tDsBuffFormat.nSamplesPerSec\t= (unsigned short int) RawHeader.Rate;\n\t\tDsBuffFormat.nChannels\t\t\t= (RawHeader.Flags & AUD_FLAG_STEREO) ? 2 : 1 ;\n\t\tDsBuffFormat.wBitsPerSample\t= (RawHeader.Flags & AUD_FLAG_16BIT) ? 16 : 8 ;\n\t\tDsBuffFormat.nBlockAlign\t= (short) ((DsBuffFormat.wBitsPerSample/8) * DsBuffFormat.nChannels);\n\t\tDsBuffFormat.nAvgBytesPerSec= DsBuffFormat.nSamplesPerSec * DsBuffFormat.nBlockAlign;\n\n\t\t/*\n\t\t** Create the new sound buffer\n\t\t*/\n\t\treturn_code= SoundObject->CreateSoundBuffer (&BufferDesc , &st->PlayBuffer , NULL);\n\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t}\n\t\t/*\n\t\t** Just return if the create failed unexpectedly\n\t\t**\n\t\t** If we failed then flag the buffer as having an impossible format so it wont match\n\t\t** any sample. This will ensure that we try and create the buffer again next time its used.\n\t\t*/\n\t\tif (return_code!=DS_OK && return_code!=DSERR_BUFFERLOST){\n\t\t\tst->PlaybackRate = 0;\n\t\t\tst->Stereo = 0;\n\t\t\tst->BitSize = 0;\n\t\t\treturn(-1);\n\t\t}\n\n\t\t/*\n\t\t** Remember the format of the new buffer\n\t\t*/\n\t\tst->PlaybackRate \t= RawHeader.Rate;\n\t\tst->Stereo\t\t\t= RawHeader.Flags & AUD_FLAG_STEREO;\n\t\tst->BitSize \t\t= RawHeader.Flags & AUD_FLAG_16BIT;\n\t}\n\n\t/*\n\t**      Fill in 3/4 of the play buffer.\n\t*/\n\n\t//\n\t// Stop the sound buffer playing before we lock it\n\t//\n\tdo {\n\t\tDumpBuffer = st->PlayBuffer;\n\t\treturn_code = st->PlayBuffer->GetStatus ( &play_status );\n\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t}\n\t} while (return_code==DSERR_BUFFERLOST);\n\n\tif (play_status & (DSBSTATUS_PLAYING | DSBSTATUS_LOOPING) ){\n\t\tst->Active=0;\n\t\tst->Service=0;\n\t\tst->MoreSource=0;\n\t\tst->PlayBuffer->Stop();\n\t}\n\t//\n\t// Lock the direct sound buffer so we can write to it\n\t//\n\tdo {\n\t\treturn_code = st->PlayBuffer->Lock (\t0 ,\n\t\t\t\t\t\t\t\t\t\tSECONDARY_BUFFER_SIZE,\n\t\t\t\t\t\t\t\t\t\t&play_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t&lock_length1,\n\t\t\t\t\t\t\t\t\t\t&dummy_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t&lock_length2,\n\t\t\t\t\t\t\t\t\t\t0 );\n\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t}\n\t} while (return_code==DSERR_BUFFERLOST);\n\n\tif (return_code != DS_OK) {\n\t\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\treturn (-1);\n\t}\n\n\t//\n\t// Decompress the sample into the direct sound buffer\n\t//\n\tst->DestPtr=(void*)Sample_Copy ( \tst,\n\t\t\t\t\t\t\t\t&st->Source,\n\t\t\t\t\t\t\t\t&st->Remainder,\n\t\t\t\t\t\t\t\t&st->QueueBuffer,\n\t\t\t\t\t\t\t\t&st->QueueSize,\n\t\t\t\t\t\t\t\tplay_buffer_ptr,\n\t\t\t\t\t\t\t\tSECONDARY_BUFFER_SIZE*1/4,\n\t\t\t\t\t\t\t\tst->Compression,\n\t\t\t\t\t\t\t\t&st->Trailer[0],\n\t\t\t\t\t\t\t\t&st->TrailerLen);\n\n\tif ( st->DestPtr==(void*) (SECONDARY_BUFFER_SIZE*1/4) ){\n\n\t\t// Must be more data to copy so we dont need to zero the buffer\n\t\tst->MoreSource=TRUE;\n\t\tst->Service=TRUE;\n\t\tst->OneShot=FALSE;\n\t} else {\n\n\t\t// Whole sample is in the buffer so flag that we dont need to\n\t\t// copy more. Clear out the end of the buffer so that it\n\t\t// goes quiet if we play past the end\n\t\tst->MoreSource=FALSE;\n\t\tst->OneShot=TRUE;\n\t\tst->Service=TRUE;\t\t\t\t//We still need to service it so that we can stop it when\n\t\t\t\t\t\t\t\t\t\t\t// it plays past the end of the sample data\n\t\t//memset ( (char*)( (unsigned)play_buffer_ptr + (unsigned)st->DestPtr ), 0 , SECONDARY_BUFFER_SIZE - (unsigned)st->DestPtr );\n\t\tmemset ( (char*)( (unsigned)play_buffer_ptr + (unsigned)st->DestPtr ), 0 , SECONDARY_BUFFER_SIZE/4);\n\t}\n\n\tst->PlayBuffer->Unlock(\tplay_buffer_ptr,\n\t\t\t\t\t\t\tlock_length1,\n\t\t\t\t\t\t\tdummy_buffer_ptr,\n\t\t\t\t\t\t\tlock_length2);\n\n\n\t/*\n    **\n    **  Set the volume of the sample.\n    **\n    */\n\tst->Volume = (volume << 7);\n#ifdef NO_VOLUME_CONTROL\n\tdo {\n\t\treturn_code = st->PlayBuffer->SetVolume (- ( ( (32768- ( (st->Volume >> 8) *LockedData.SoundVolume) )\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*1000) >>15 ) );\n\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t}\n\t} while (return_code==DSERR_BUFFERLOST);\n\n#endif\t//NO_VOLUME_CONTROL\n\n\t/*\n\t** Make sure the primary sound buffer is playing\n\t*/\n\tif (!Start_Primary_Sound_Buffer(FALSE)){\n\t\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\treturn(-1);\n\t}\n\n\n\t/*\n\t** Set the buffers play pointer to the beginning of the buffer\n\t*/\n\tdo {\n\t\treturn_code = st->PlayBuffer->SetCurrentPosition (0);\n\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t}\n\t} while (return_code==DSERR_BUFFERLOST);\n\n\n\t/*\n    ** Start the sample playing now.\n\t*/\n\tdo\n\t{\n\t\treturn_code = st->PlayBuffer->Play (0,0,DSBPLAY_LOOPING);\n\n\t\tswitch (return_code){\n\n\t\t\tcase DS_OK :\n\t\t\t\tEnterCriticalSection (&GlobalAudioCriticalSection);\n\t\t\t\tst->Active=TRUE;\n\t\t\t\tst->Handle=(short)id;\n\t\t\t\tst->DontTouch = FALSE;\n\t\t\t\tLeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\t\t\treturn (st->Handle);\n\n\t\t\tcase DSERR_BUFFERLOST :\n\t\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tst->Active=FALSE;\n\t\t\t\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\t\t\treturn (st->Handle);\n\t\t}\n\n\t} while (return_code==DSERR_BUFFERLOST);\n\n\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\treturn (st->Handle);\n}\n\n\n\n\n\n/***********************************************************************************************\n * Restore_Sound_Buffers -- restore the sound buffers                                          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/3/95 3:53PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Restore_Sound_Buffers ( void )\n{\n\n\tif (PrimaryBufferPtr){\n\t\tPrimaryBufferPtr->Restore();\n\t}\n\n\n\tfor ( int index = 0; index < MAX_SFX; index++) {\n\t\tif (LockedData.SampleTracker[index].PlayBuffer){\n\t\t\tLockedData.SampleTracker[index].PlayBuffer->Restore();\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Set_Sound_Vol -- sets the overall volume for sampled sounds                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    volume                                                                            *\n *                                                                                             *\n * OUTPUT:   the previous volume setting                                                       *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:19PM ST : Added function header                                                *\n *=============================================================================================*/\n\nint Set_Sound_Vol(int volume)\n{\n\tint old;\n \told = LockedData.SoundVolume;\n \tLockedData.SoundVolume = volume & 0xFF;\n\treturn(old);\n}\n\n\n/***********************************************************************************************\n * Set_Score_Vol -- sets the overall volume for music scores                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    volume                                                                            *\n *                                                                                             *\n * OUTPUT:   the previous volume setting                                                       *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:19PM ST : Added function header                                                *\n *=============================================================================================*/\nint Set_Score_Vol(int volume)\n{\n\tint old;\n\tSampleTrackerType\t*st;\t\t\t\t\t//ptr to SampleTracker structure\n\n\told = LockedData.ScoreVolume;\n\tLockedData.ScoreVolume = volume & 0xFF;\n\n\tfor (int index=0 ; index<MAX_SFX ; index++){\n\t\tst = &LockedData.SampleTracker[index];\n\n\t\tif (st->IsScore && st->Active){\n#ifdef NO_VOLUME_CONTROL\n\t\t\tst->PlayBuffer->SetVolume (- ( ( (32768- ( (st->Volume >> 8) *LockedData.ScoreVolume) )\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*1000) >>15 ) );\n#endif\t//ifdef NO_VOLUME_CONTROL\n\t\t}\n\t}\n\treturn(old);\n}\n\n\n\n/***********************************************************************************************\n * Fade_Sample -- Start a sample fading                                                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Sample handle                                                                     *\n *           fade rate                                                                         *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:21PM ST : Added function header                                                *\n *=============================================================================================*/\n\nvoid Fade_Sample(int handle, int ticks)\n{\n\tif (Sample_Status(handle)) {\n    \tif (!ticks || LockedData.SampleTracker[handle].Loading) {\n       \tStop_Sample(handle);\n\t\t\t} else {\n\t\t\t\tSampleTrackerType * st;\n\t\t\t\tst = &LockedData.SampleTracker[handle];\n\t\t\t\tst->Reducer = (short) ((st->Volume / ticks)+1);\n\t\t\t}\n\t}\n}\n\n\n\nint Get_Digi_Handle(void)\n{\n        return(LockedData.DigiHandle);\n}\n\n\n\n/***************************************************************************\n * SAMPLE_LENGTH -- returns length of a sample in ticks                    *\n *                                                                         *\n * INPUT:  void const *sample - pointer to the sample to get length of.    *\n *                                                                         *\n * OUTPUT: long - length of the sample in ticks (60/sec)                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/05/1995 PWG : Created.                                             *\n *=========================================================================*/\nlong Sample_Length(void const *sample)\n{\n\tAUDHeaderType\tRawHeader;\n\n\tif (!sample) return(0);\n\n\tMem_Copy((void *)sample, (void *)&RawHeader, sizeof(RawHeader));\n\n\tlong time = RawHeader.UncompSize;\n\n\t/*\n\t** If the sample is a 16 bit sample, then it will take only half\n\t** as long to play.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_16BIT) {\n\t\ttime >>= 1;\n\t}\n\n\t/*\n\t** If the sample is a stereo sample, then it will take only half\n\t** as long to play.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_STEREO) {\n\t\ttime >>= 1;\n\t}\n\n\tif (RawHeader.Rate/60) {\n\t\ttime /= (RawHeader.Rate/60);\n\t}\n\treturn(time);\n}\n\n\n\n/***********************************************************************************************\n * Start_Primary_Sound_Buffer -- start the primary sound buffer playing                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    2/1/96 12:28PM ST : Created                                                              *\n *=============================================================================================*/\nextern BOOL GameInFocus;\nBOOL Start_Primary_Sound_Buffer (BOOL forced)\n{\n\tDWORD status;\n\n\tif (PrimaryBufferPtr && GameInFocus){\n\t\tif (forced){\n\t\t\tPrimaryBufferPtr->Play(0,0,DSBPLAY_LOOPING);\n\t\t\treturn (TRUE);\n\t\t} else {\n\n\t\t\tif (PrimaryBufferPtr->GetStatus (&status) == DS_OK){\n\t\t\t\tif (! ((status & DSBSTATUS_PLAYING) || (status & DSBSTATUS_LOOPING))){\n\t\t\t\t\tPrimaryBufferPtr->Play(0,0,DSBPLAY_LOOPING);\n\t\t\t\t\treturn (TRUE);\n\t\t\t\t}else{\n\t\t\t\t\treturn (TRUE);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn (FALSE);\n}\n\n\n/***********************************************************************************************\n * Stop_Primary_Sound_Buffer -- stops the primary sound buffer from playing.                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: This stops all sound playback                                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    2/1/96 12:28PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Stop_Primary_Sound_Buffer (void)\n{\n\tif (PrimaryBufferPtr){\n\t\tPrimaryBufferPtr->Stop();\n\t\tPrimaryBufferPtr->Stop();\t      // Oh I\n\t\tPrimaryBufferPtr->Stop();\t\t\t// Hate Direct Sound\n\t\tPrimaryBufferPtr->Stop();\t\t\t// So much.....\n\t}\n\n\tfor ( int index = 0; index < MAX_SFX; index++) {\n\t\tStop_Sample(index);\n\t}\n\n}\n\n\nvoid Suspend_Audio_Thread(void)\n{\n\tif (SoundThreadActive){\n\t\tSuspendThread(SoundThreadHandle);\n\t\tSoundThreadActive = FALSE;\n\t}\n}\n\n\n\n\nvoid Resume_Audio_Thread(void)\n{\n\tif (!SoundThreadActive){\n\t\tResumeThread(SoundThreadHandle);\n\t\tSoundThreadActive = TRUE;\n\t}\n}\n\n\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/SOUNDLCK.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDLCK.CPP                             *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 23, 1995   [PWG]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#define WIN32\n#include <windows.h>\n#include <windowsx.h>\n#include <objbase.h>\n#include \"dsound.h\"\n#include <mem.h>\n#include \"wwmem.h\"\n#include \"wwstd.h\"\n#include \"soundint.h\"\n\n\n\nLockedDataType LockedData;\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * INIT_LOCKED_DATA -- Initializes sound driver locked data                *\n *                                                                         *\n * INPUT:\t\tnone                                                          *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid Init_Locked_Data(void)\n{\n\n\t/*\n\t** Initialize all of the data elements that need to be locked.\n\t*/\n\tLockedData.DigiHandle\t\t\t= -1;\n\tLockedData.ServiceSomething\t= FALSE;\n\tLockedData.MagicNumber\t\t\t= 0xDEAF;\n\tLockedData.UncompBuffer\t\t\t= NULL;\n//\tLockedData.StreamBufferSize\t= (2*SECONDARY_BUFFER_SIZE)+128;\n\tLockedData.StreamBufferSize\t= (SECONDARY_BUFFER_SIZE/4)+128;\n\tLockedData.StreamBufferCount\t= 16;\n\tLockedData.SoundVolume\t\t\t= 255;\n\tLockedData.ScoreVolume\t\t\t= 255;\n\tLockedData._int\t\t\t\t\t= FALSE;\n\n\t#ifdef cuts\n\t/*\n\t** Lock the sound specific c functions that will cause us problems if\n\t** they are swapped out during an interrupt.\n\t*/\n\tDPMI_Lock(&LockedData,\t\t\t\t\t\t\t4096L);\n\tDPMI_Lock(Simple_Copy, \t\t\t\t\t\t\t4096L);\n\tDPMI_Lock(Sample_Copy, \t\t\t\t\t\t\t4096L);\n\tDPMI_Lock((void *)maintenance_callback, \t4096L);\n\tDPMI_Lock((void *)DigiCallback, \t\t\t\t4096L);\n\tDPMI_Lock((void *)HMI_TimerCallback, \t\t4096L);\n\tDPMI_Lock(Audio_Add_Long_To_Pointer,\t\t4096L);\n\tDPMI_Lock(DPMI_Unlock,\t\t\t\t\t\t\t4096L);\n\n\t/*\n\t** Lock the library functions that will cause us problems if they are\n\t** swapped out during an interrupt.\n\t*/\n\tDPMI_Lock(Mem_Copy,\t\t\t\t\t\t\t\t4096L);\n\tDPMI_Lock(Audio_Mem_Set,\t\t\t\t\t\t4096L);\n\tDPMI_Lock(__GETDS,\t\t\t\t\t\t\t\t4096L);\n\n\t/*\n\t** Finally lock the two assembly modules that need locking.  This can\n\t** be handled by calling the lock function that is local to thier module\n\t** swapped out during an interrupt.\n\t*/\n\tDecompress_Frame_Lock();\n\tsosCODEC_Lock();\n\n\t#endif\t//cuts\n}\n\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/TEST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <windowsx.h>\n#include \"audio.h\"\n\n\n\nint PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,\n                        LPSTR lpCmdLine, int nCmdShow)\n{\n\n\n\n\t\t\t \n\n\n\tFile_Stream_Sample_Vol(\"file\", 0, 0);\n\n\treturn (0);\n}"
  },
  {
    "path": "WIN32LIB/AUDIO/OLD/TST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#undef _WINDOWS_16_\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#define WIN32\n#define __WIN32\n\n#include <windows.h>\n#include <windowsx.h>\n#include <ole2.h>\n\nmain\n{}\n"
  },
  {
    "path": "WIN32LIB/AUDIO/OLSOSDEC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*          Copyright (c) 1994, HMI, INC. All Rights Reserved\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     soscodec.asm\n;*\n;* DESCRIPTION\n;*     HMI SOS ADPCM compression/decompression.\n;*\n;* PROGRAMMER\n;*     Nick Skrepetos\n;*     Denzil E. Long, Jr. (Fixed bugs, rewrote for watcom)\n;*\t   Bill Petro\t\t   (Added stereo support)\n;* DATE\n;*     Febuary 15, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\n\nDPMI_INTR\t\tequ\t31h\nIF_LOCKED_PM_CODE\tequ\t1h\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t2h\t\t; Locked PM code for DPMI.\n\n\tSTRUC\tsCompInfo\nlpSource\t\tDD\t?\t;Compressed data pointer\nlpDest\t\t\tDD\t?\t;Uncompressed data pointer\ndwCompSize\t\tDD\t?\t;Compressed size\ndwUnCompSize\t\tDD\t?\t;Uncompressed size\n\ndwSampleIndex\t\tDD\t?\t;Index into sample\ndwPredicted\t\tDD\t?\t;Next predicted value\ndwDifference\t\tDD\t?\t;Difference from last sample\nwCodeBuf\t\tDW\t?\t;Holds 2 nibbles for decompression\nwCode\t\t\tDW\t?\t;Current 4 bit code\nwStep\t\t\tDW\t?\t;Step value in table\nwIndex\t\t\tDW\t?\t;Index into step table\n\ndwSampleIndex2\t\tDD\t?\t;Index into sample\ndwPredicted2\t\tDD\t?\t;Next predicted value\ndwDifference2\t\tDD\t?\t;Difference from last sample\nwCodeBuf2 \t\tDW\t?\t;Holds 2 nibbles for decompression\nwCode2\t\t\tDW\t?\t;Current 4 bit code\nwStep2\t\t\tDW\t?\t;Step value in table\nwIndex2\t\tDW\t?\t;Index into step table\n\nwBitSize\t\tDW\t?\t;Bit size for decompression\nwChannels\t\tDW\t?    \t;number of channels\n\tENDS\tsCompInfo\n\n\tDATASEG\n\n\nInitFlags\tDD\t0\t\t; Flags to indicate what has been initialized.\n\n\nLABEL\tLockedDataStart\tBYTE\n\n;* Index table for stepping into step table\n\nwCODECIndexTab\tDW\t-1,-1,-1,-1,2,4,6,8\n\t\tDW\t-1,-1,-1,-1,2,4,6,8\n\n\n;Lookup table of replacement values\n;The actual sound value is replaced with an index to lookup in this table\n;The index only takes up a nibble(4bits) and represents an int(16bits)\n;Essentially:\n;Get a value\n;compare it with the value before it\n;find closest value in table and store the index into the table\n;if i'm going down then negitize it\n;go to next byte.\n\n;Theory for stereo:\n;1)handle stereo and mono in two seperate loops. cleaner...\n;start at byte 0 and skip every other byte(or word) both write and read\n;when we get done\n;\tset start byte to 1 and do it again\n\n\n\n\n;This table essentialy round off to closes values in 3 distinct bands\n; precalculated and optimized(i guess) for human hearing.\n\nwCODECStepTab\tDW\t7,  \t8,  \t9,   \t10,   \t11,  \t12,   \t13,14\n\tDW\t16, \t17, \t19, \t21,  \t23,   \t25,  \t28,   \t31\n\tDW\t34, \t37, \t41, \t45,  \t50,   \t55,  \t60,   \t66\n\tDW\t73, \t80, \t88, \t97,  \t107,  \t118, \t130,  \t143\n\tDW\t157,\t173,\t190,\t209, \t230,  \t253, \t279,  \t307\n\tDW\t337,\t371,\t408,\t449, \t494,  \t544, \t598,  \t658\n\tDW\t724,\t796,\t876,\t963, \t1060,\t1166,\t1282,\t1411\n\tDW\t1552,\t1707,\t1878,\t2066,\t2272,\t2499,\t2749,\t3024\n\tDW\t3327,\t3660,\t4026,\t4428,\t4871,\t5358,\t5894,\t6484\n\tDW\t7132,\t7845,\t8630,\t9493,\t10442,\t11487,\t12635,\t13899\n\tDW\t15289,\t16818,\t18500,\t20350,\t22385,\t24623,\t27086,\t29794\n\tDW\t32767\n\n;dwCODECByteIndex\t\tDD\t0 ; this is when to stop compressing\n;dwCODECTempStep\t\tDD\t0 ; tempory storage for step value\n;wCODECMask\t\t\tDW\t0 ; Current mask\n\nLABEL\tLockedDataEnd\tBYTE\n\n\n\tCODESEG\n\nLABEL\tLockedCodeStart\tBYTE\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECInitStream - Initialize compression stream.\n;*\n;* SYNOPSIS\n;*     sosCODECInitStream(CompInfo)\n;*\n;*     void sosCODECInitStream(_SOS_COMPRESS_INFO *);\n;*\n;* FUNCTION\n;*     Initialize compression stream for compression and decompression.\n;*\n;* INPUTS\n;*     CompInfo - Compression information structure.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC sosCODECInitStream:NEAR\n\tPROC\tsosCODECInitStream C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\n\tmov\teax,[sSOSInfo]\n\tmov\t[(sCompInfo eax).wIndex],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).wStep],7  \t\t; start with a step of 7\n\tmov\t[(sCompInfo eax).dwPredicted],0 \t; no predicted value\n\tmov\t[(sCompInfo eax).dwSampleIndex],0\t;start at head of index\n\tmov\t[(sCompInfo eax).wIndex2],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).wStep2],7  \t\t; start with a step of 7\n\tmov\t[(sCompInfo eax).dwPredicted2],0 \t; no predicted value\n\tmov\t[(sCompInfo eax).dwSampleIndex2],0 \t;start at head of index\n\tret\n\n\tENDP\tsosCODECInitStream\n\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECDecompressData - Decompress audio data.\n;*\n;* SYNOPSIS\n;*     Size = sosCODECDecompressData(CompInfo, NumBytes)\n;*\n;*     long sosCODECDecompressData(_SOS_COMPRESS_INFO *, long);\n;*\n;* FUNCTION\n;*     Decompress data from a 4:1 ADPCM compressed stream. The number of\n;*     bytes decompressed is returned.\n;*\n;* INPUTS\n;*     CompInfo - Compress information structure.\n;*     NumBytes - Number of bytes to compress.\n;*\n;* RESULT\n;*     Size - Size of decompressed data.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC General_sosCODECDecompressData:NEAR\n\tPROC\tGeneral_sosCODECDecompressData C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\tARG\twBytes:DWORD\n\n\tlocal\tdwCODECBytesProcessed:dword             ;bytes to decompress\n\tlocal\tdwCODECByteIndex:dword\t\t\t;this is when to stop compressing\n\t\t\t\t\t\t\t; these need to be local if the function is to be reenterant\n\tpush\tesi\n\tpush\tedi\n\tpush\tebx\n\tpush\tecx\n\tpush\tedx\n\n;*---------------------------------------------------------------------------\n;*\tInitialize\n;*---------------------------------------------------------------------------\n\n\tmov\tebx,[sSOSInfo]\n\tmov\teax,[wBytes]\n\tmov\t[dwCODECBytesProcessed],eax\n\tmov\t[(sCompInfo ebx).dwSampleIndex],0 \t;start at head of index\n\tmov\t[(sCompInfo ebx).dwSampleIndex2],0 \t;start at head of index\n\n\t\t\t\t\t\t\t;Check for 16 bit decompression\n\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??skipByteDivide\n\n\tshr\teax,1\t;Divide size by two\n\n??skipByteDivide:\n\tmov\t[dwCODECByteIndex],eax\n\tmov\tesi,[(sCompInfo ebx).lpSource]\n\tmov\tedi,[(sCompInfo ebx).lpDest]\n\tcmp\t[(sCompInfo ebx).wChannels],2\t\t;stereo check\n\tje\t??mainloopl\t\t\t\t;do left side first\n\n;\tDetermine if sample index is even or odd. This will determine\n;\tif we need to get a new token or not.\n\n;---------------------------------------------------------------------------\n;Main Mono Loop\n;---------------------------------------------------------------------------\n\n\n\n??mainloop:\n\ttest\t[(sCompInfo ebx).dwSampleIndex],1\t;odd ??\n\tje\tshort ??fetchToken\t\t\t; if so get new token\n\txor\teax,eax\t\t\t\t\t;else shift int codebuf\n\tmov\tax,[(sCompInfo ebx).wCodeBuf]\t\t;ored with Code\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\tjmp\tshort ??calcDifference\n\n??fetchToken:\n\txor\teax,eax\t\t\t\t\t;get a new token\n\tmov\tal,[esi]\t\t\t\t;put in codebuf\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\n\tinc\tesi\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\t\t;and then code\n\n??calcDifference:\n\tmov\t[(sCompInfo ebx).dwDifference],0\t;reset diff\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep]\t\t;cx is step value\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4\n\tadd\t[(sCompInfo ebx).dwDifference],ecx\t;Add wStep\n\n??no4:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no2:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no1:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8\n\tneg\t[(sCompInfo ebx).dwDifference]\t\t;Negate diff\n\n??no8:\n\t; add difference to predicted value.\n\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\n\tadd\teax,[(sCompInfo ebx).dwDifference]\n\n\t; make sure there is no under or  overflow.\n\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflow\n\tmov\teax,7FFFh\n\n??noOverflow:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflow\n\tmov\teax,0FFFF8000h\n\n??noUnderflow:\n\tmov\t[(sCompInfo ebx).dwPredicted],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bit\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,2\n\tjmp\tshort ??adjustIndex\n\n??output8Bit:\n\t; output 8 bit sample\n\n\txor\tah,80h\n\tmov\t[edi],ah\n\tinc\tedi\n\n??adjustIndex:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex],ax \t\t;check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex],8000h\n\tjb\tshort ??checkOverflow\n\tmov\t[(sCompInfo ebx).wIndex],0\t\t;reset index to zero\n\tjmp\tshort ??adjustStep\n\n??checkOverflow:\n\tcmp\t[(sCompInfo ebx).wIndex],88\t\t;check if wIndex > 88\n\tjbe\tshort ??adjustStep\n\tmov\t[(sCompInfo ebx).wIndex],88\t\t;reset index to 88\n\n??adjustStep:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex],1\n\tmov\t[(sCompInfo ebx).wStep],ax\n\n\t; decrement bytes processed and loop back.\n\n\tdec\t[dwCODECByteIndex]\n\tjne\t??mainloop\n\tjmp\t??exitout\n\n;--------------------------------------------------------------------------\n;Left Channel Start\n;--------------------------------------------------------------------------\n\n\n??mainloopl:\n\ttest\t[(sCompInfo ebx).dwSampleIndex],1\n\tje\tshort ??fetchTokenl\n\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCodeBuf]\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\tjmp\tshort ??calcDifferencel\n\n??fetchTokenl:\n\txor\teax,eax\n\tmov\tal,[esi]\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\n\tadd\tesi,2\t\t\t\t\t;2 for stereo\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\n??calcDifferencel:\n\t\t\t\t\t\t\t; reset difference\n\n\tmov\t[(sCompInfo ebx).dwDifference],0\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep]\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4l\n\tadd\t[(sCompInfo ebx).dwDifference],ecx\t;Add wStep\n\n??no4l:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2l\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no2l:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1l\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no1l:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8l\n\tneg\t[(sCompInfo ebx).dwDifference]\t\t;Negate diff\n\n??no8l:\n\t\t; add difference to predicted value.\n\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\n\tadd\teax,[(sCompInfo ebx).dwDifference]\n\n\t\t; make sure there is no under or  overflow.\n\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowl\n\tmov\teax,7FFFh\n\n??noOverflowl:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowl\n\tmov\teax,0FFFF8000h\n\n??noUnderflowl:\n\tmov\t[(sCompInfo ebx).dwPredicted],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bitl\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,4\t\t\t\t\t;4 for stereo\n\tjmp\tshort ??adjustIndexl\n\n??output8Bitl:\n\t; output 8 bit sample\n\n\txor\tah,80h\n\tmov\t[edi],ah\n\tadd\tedi,2\t\t\t\t\t;2 for stereo\n\n??adjustIndexl:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex],ax\n\t\t\t\t\t\t\t; check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex],8000h\n\tjb\tshort ??checkOverflowl\n\tmov\t[(sCompInfo ebx).wIndex],0\n\tjmp\tshort ??adjustStepl\t\t\t;reset index to zero\n\n\n??checkOverflowl:\n\n\tcmp\t[(sCompInfo ebx).wIndex],88\t\t; check if wIndex > 88\n\tjbe\tshort ??adjustStepl\n\tmov\t[(sCompInfo ebx).wIndex],88\t\t; reset index to 88\n\n??adjustStepl:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex],1\n\tmov\t[(sCompInfo ebx).wStep],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2\n\tjne\t??mainloopl\n;----------------------------------------------------------------------------\n; Right Side Setup\n;----------------------------------------------------------------------------\n\tmov\teax,[wBytes]\n\tmov\t[dwCODECBytesProcessed],eax\n\tmov\tesi,[(sCompInfo ebx).lpSource]\n\tmov\tedi,[(sCompInfo ebx).lpDest]\n\tinc\tesi\t\t\t\t\t; skip left channel\n\tinc\tedi\t\t\t\t     \t; skip left channel\n\tcmp\t[(sCompInfo ebx).wBitSize],16\t\t;16 bit ??\n\tje\tshort ??doByteDivide\n\tmov\t[dwCODECByteIndex],eax\n\tjmp  short ??mainloopr\n\n??doByteDivide:\n\tshr\teax,1 \t\t\t\t\t;Divide size by two\n\tinc\tedi   \t\t\t\t\t; 16 bit so skip 1 more\n\tmov\t[dwCODECByteIndex],eax\n\n\n;--------------------------------------------------------------------------\n;Right Channel Start\n;--------------------------------------------------------------------------\n\n\n??mainloopr:\n\ttest\t[(sCompInfo ebx).dwSampleIndex2],1\n\tje\tshort ??fetchTokenr\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCodeBuf2]\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode2],ax\n\tjmp\tshort ??calcDifferencer\n\n??fetchTokenr:\n\txor\teax,eax\n\tmov\tal,[esi]\n\tmov\t[(sCompInfo ebx).wCodeBuf2],ax\n\tadd\tesi,2\t\t\t\t     \t;2 for stereo\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode2],ax\n\n??calcDifferencer:\n\t\t\t\t\t\t\t; reset difference\n\n\tmov\t[(sCompInfo ebx).dwDifference2],0\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep2]\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4r\n\tadd\t[(sCompInfo ebx).dwDifference2],ecx\t;Add wStep\n\n??no4r:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2r\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\n??no2r:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1r\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\n??no1r:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8r\n\tneg\t[(sCompInfo ebx).dwDifference2]\t\t;Negate diff\n\n??no8r:\n\t; add difference to predicted value.\n\tmov\teax,[(sCompInfo ebx).dwPredicted2]\n\tadd\teax,[(sCompInfo ebx).dwDifference2]\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowr\n\tmov\teax,7FFFh\n\n??noOverflowr:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowr\n\tmov\teax,0FFFF8000h\n\n??noUnderflowr:\n\tmov\t[(sCompInfo ebx).dwPredicted2],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bitr\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,4\t\t\t\t\t;4 for stereo\t\t***\n\tjmp\tshort ??adjustIndexr\n\n??output8Bitr:\n\t\t\t\t\t\t\t; output 8 bit sample\n\txor\tah,80h\n\tmov\t[edi],ah\n\tadd\tedi,2\t\t\t\t\t;2 for stereo\n\n??adjustIndexr:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode2]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex2],ax\n\t\t\t\t\t\t\t; check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex2],8000h\n\tjb\tshort ??checkOverflowr\n\t\t\t\t\t\t\t; reset index to zero\n\tmov\t[(sCompInfo ebx).wIndex2],0\n\tjmp\tshort ??adjustStepr\n\n??checkOverflowr:\n\t\t\t\t\t\t\t; check if wIndex > 88\n\tcmp\t[(sCompInfo ebx).wIndex2],88\n\tjbe\tshort ??adjustStepr\n\tmov\t[(sCompInfo ebx).wIndex2],88\t\t; reset index to 88\n\n??adjustStepr:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex2]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex2],1\n\tmov\t[(sCompInfo ebx).wStep2],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2\n\tjne\t??mainloopr\n\n\n??exitout:\n;\t\tdon't think we need this but just in case i'll leave it here!!\n\n;\tmov\t[(sCompInfo ebx).lpSource],esi\n;\tmov\t[(sCompInfo ebx).lpDest],edi\n\t; set up return value for number of bytes processed.\n\tmov\teax,[dwCODECBytesProcessed]\n\tpop\tedx\n\tpop\tecx\n\tpop\tebx\n\tpop\tedi\n\tpop\tesi\n\tret\n\n\tENDP\tGeneral_sosCODECDecompressData\n\nLABEL\tLockedCodeEnd\tBYTE\n\n;***************************************************************************\n;* sosCODEC_LOCK -- locks the JLB audio decompression code\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is lock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:       BOOL sosCODEC_Lock(void);                         \t   *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC sosCODEC_Lock:NEAR\n\tPROC\tsosCODEC_Lock C NEAR USES ebx ecx edx esi edi\n\n\t;\n\t; Lock the code that is used by the sos decompression method.\n\t;\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n  \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags], IF_LOCKED_PM_CODE\n\n\t;\n\t; Lock the data used by the sos decompression method.\n\t;\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags], IF_LOCKED_PM_DATA\n\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\tENDP\tsosCODEC_Lock\n\n;***************************************************************************\n;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code       *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is unlock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:\tBOOL sosCODEC_Unlock(void);                        \t   *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC sosCODEC_Unlock:NEAR\n\tPROC\tsosCODEC_Unlock C NEAR USES ebx ecx edx esi edi\n\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\n??code_not_locked:\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??data_not_locked:\n\tmov\t[InitFlags],0\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\tENDP\tsosCODEC_Unlock\n\n\n\tEND\n"
  },
  {
    "path": "WIN32LIB/AUDIO/SOS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sos.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces\n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DEFINED\n#define  _SOS_DEFINED\n#include \"sosdefs.h\"\n\n#pragma pack(4)\n\n// error definition for sound operating system\n#define  _SOS_ERR          -1\n\n// number of drivers allowed to be open at one time\n#define  _SOS_MAX_DRIVERS  5\n\n// structure definition for the capabilities\ntypedef struct _tagCAPABILITIES\n{\n   BYTE  szDeviceName[ 32 ];  // device name\n   WORD  wDeviceVersion;      // device version\n   WORD  wBitsPerSample;      // bits per sound sample\n   WORD  wChannels;           // stereo/mono sound card\n   WORD  wMinRate;            // minimum rate\n   WORD  wMaxRate;            // maximum rate\n   WORD  wMixerOnBoard;       // board contains mixer\n   WORD  wMixerFlags;         // mixer capabilities\n   WORD  wFlags;              // miscellaneous flags\n   short far * lpPortList;         // list of usable ports\n   short far * lpDMAList;          // list of usable dma channels\n   short far * lpIRQList;          // list of usable irq channels\n   short far * lpRateList;         // list of usable rates, -1 if any in min to max\n   WORD  fBackground;         // foreground or background driver\n   WORD  wDeviceID;           // ID for the device\n   WORD  wTimerID;            // ID for the timer\n\n} _SOS_CAPABILITIES;\n\n// far pointer to the device capabilities structure\ntypedef _SOS_CAPABILITIES far *  LPSOSDEVICECAPS;\n\n// flag types for driver\n#define  _FLAGS_SIGNED              0x8000\n\n// devices that can be loaded\n#define  _SOUND_BLASTER_8_MONO      0xe000\n#define  _SOUND_BLASTER_8_ST        0xe001\n#define  _SBPRO_8_ST                _SOUND_BLASTER_8_ST\n#define  _SBPRO_8_MONO              0xe00f\n#define  _SOUND_MASTER_II_8_MONO    0xe002\n#define  _MV_PAS_8_MONO             0xe003\n#define  _MV_PAS_16_MONO            0xe004\n#define  _MV_PAS_8_ST               0xe005\n#define  _MV_PAS_16_ST              0xe006\n#define  _ADLIB_GOLD_8_ST           0xe007\n#define  _ADLIB_GOLD_16_ST          0xe008\n#define  _ADLIB_GOLD_8_MONO         0xe009\n#define  _ADLIB_GOLD_16_MONO        0xe00a\n#define  _MICROSOFT_8_MONO          0xe00b\n#define  _MICROSOFT_8_ST            0xe00c\n#define  _MICROSOFT_16_MONO         0xe00d\n#define  _MICROSOFT_16_ST           0xe00e\n#define  _SOUND_SOURCE_8_MONO_PC    0xe010\n#define  _SOUND_SOURCE_8_MONO_TANDY 0xe011\n#define  _GENERAL_PORT_8_MONO       0xe012\n#define  _GENERAL_PORT_8_MONO_R     0xe013\n#define  _SIERRA_8_MONO             0xe014\n#define  _SB16_8_MONO               0xe015\n#define  _SB16_8_ST                 0xe016\n#define  _SB16_16_MONO              0xe017\n#define  _SB16_16_ST                0xe018\n#define  _ESS_AUDIODRIVE_8_MONO     0xe019\n#define  _ESS_AUDIODRIVE_8_ST       0xe01a\n#define  _ESS_AUDIODRIVE_16_MONO    0xe01b\n#define  _ESS_AUDIODRIVE_16_ST      0xe01c\n#define  _SOUNDSCAPE_8_MONO         0xe01d\n#define  _SOUNDSCAPE_8_ST           0xe01e\n#define  _SOUNDSCAPE_16_MONO        0xe01f\n#define  _SOUNDSCAPE_16_ST          0xe020\n#define  _RAP10_8_MONO              0xe021\n#define  _RAP10_16_MONO             0xe022\n#define  _GUS_8_MONO                0xe023\n#define  _GUS_8_ST                  0xe024\n#define  _GUS_16_MONO               0xe025\n#define  _GUS_16_ST                 0xe026\n#define  _GUS_MAX_8_MONO            0xe027\n#define  _GUS_MAX_8_ST              0xe028\n#define  _GUS_MAX_16_MONO           0xe029\n#define  _GUS_MAX_16_ST             0xe02a\n#define  _WAVEJAMMER_8_MONO         0xe02b\n#define  _WAVEJAMMER_8_ST           0xe02c\n#define  _WAVEJAMMER_16_MONO        0xe02d\n#define  _WAVEJAMMER_16_ST          0xe02e\n#define  _TEMPOCS_8_MONO            0xe02f\n#define  _TEMPOCS_8_ST              0xe030\n#define  _TEMPOCS_16_MONO           0xe031\n#define  _TEMPOCS_16_ST             0xe032\n#define  _WAVEJAMMERCD_8_MONO       0xe033\n#define  _WAVEJAMMERCD_8_ST         0xe034\n#define  _WAVEJAMMERCD_16_MONO      0xe035\n#define  _WAVEJAMMERCD_16_ST        0xe036\n#define  _SOUND_BLASTER_8_MONO_R    0xe050\n#define  _MICROSOFT_8_MONO_R        0xe051\n#define  _SOUND_MASTER_II_8_MONO_R  0xe052\n#define  _ADLIB_GOLD_8_MONO_R       0xe053\n#define  _MV_PAS_8_MONO_R           0xe054\n#define  _RAP10_8_MONO_R            0xe058\n#define  _RAP10_16_MONO_R           0xe059\n#define  _SB16_8_MONO_R             0xe05a\n#define  _SB16_8_ST_R               0xe05b\n#define  _SB16_16_MONO_R            0xe05c\n#define  _SB16_16_ST_R              0xe05d\n#define  _MV_PAS_16_MONO_R          0xe060\n#define  _SOUNDSCAPE_8_MONO_R       0xe061\n#define  _SOUNDSCAPE_8_ST_R         0xe062\n#define  _SOUNDSCAPE_16_MONO_R      0xe063\n#define  _SOUNDSCAPE_16_ST_R        0xe064\n#define  _ESS_AUDIODRIVE_8_MONO_R   0xe065\n#define  _ESS_AUDIODRIVE_8_ST_R     0xe066\n#define  _ESS_AUDIODRIVE_16_MONO_R  0xe067\n#define  _ESS_AUDIODRIVE_16_ST_R    0xe068\n#define  _SPEECH_THING_8_MONO       0xe090\n#define  _YAMAHA_8_MONO             0xe106\n#define  _INT_SPEAKER_8_MONO        0xe107\n\n// call indexes for the loadable drivers\nenum\n{\n   _DRV_INIT,\n   _DRV_UNINIT,\n   _DRV_SETRATE,\n   _DRV_SETACTION,\n   _DRV_START,\n   _DRV_STOP,\n   _DRV_PAUSE,\n   _DRV_RESUME,\n   _DRV_CAPABILITIES,\n   _DRV_PLAY_FOREGROUND,\n   _DRV_GET_FILL_INFO,\n   _DRV_GET_CALL_FUNCTIONS,\n   _DRV_SET_CALL_FUNCTIONS\n};\n\n// fill info\ntypedef  struct   _tagFillInfo\n         {\n\n            LPSTR lpFillHandler;                   // pointer to fill handler\n            LPWORD lpDMAFillCount;                 // pointer to dma count\n            LPSTR lpSampleList;                    // pointer to sample list\n            LPWORD lpDMAMasterVolume;              // pointer to dma count\n\n         } _SOS_FILL_INFO;\n\n// caps info structure\ntypedef  struct   _tagCapsInfo\n         {\n\n            LPSTR    lpPortList;                   // pointer to port list\n            LPSTR    lpDMAList;                    // pointer to DMA list\n            LPSTR    lpIRQList;                    // pointer to IRQ list\n            LPSTR    lpRateList;                   // pointer to rate list\n\n         } _SOS_CAPS_INFO;\n\n// maximum number of available voice\n#define  _MAX_VOICES    32\n\n// structure definition\ntypedef  struct   _tagSAMPLE\n{\n   LPSTR    samplePtr;                 // pointer to data buffer\n   LPSTR    sampleData;                // pointer to active data\n   LPSTR    sampleLoopPtr;             // pointer for loop back\n\n   WORD     sampleLength;              // length of sample\n   WORD     sampleIndex;               // index into sample\n   WORD     sampleLoopLength;          // length of loop\n\n   WORD     sampleBytesLeft;           // bytes left to play in sample\n\n   WORD     sampleLoopPoint;           // byte count for loop point\n   WORD     sampleLoopEndLength;       // length of remaining chunk\n\n   short    sampleFlags;               // control sample\n   short    sampleVolume;              // volume control\n   short    sampleID;                  // sample ID\n\n   short    sampleChannel;             // channel to play sample on\n   short    sampleLoopCount;           // loop count\n   short    sampleLastFill;            // last fill position\n   VOID ( far __cdecl * sampleCallback )( WORD, WORD, WORD ); // callback function for sample\n\n   WORD     samplePitchAdd;\n   short    samplePitchFraction;\n\n   short    samplePort;                // port to use for non-dma digitized\n\n   WORD     sampleTotalBytes;\n   WORD     sampleByteLength;\n\n   short    samplePanLocation;\n   short    samplePanSpeed;\n   short    samplePanDirection;\n   short    samplePanStart;\n   short    samplePanEnd;\n\n   short    sampleDelayBytes;\n   short    sampleDelayRepeat;\n\n   WORD     sampleADPCMPredicted;\n   short    sampleADPCMIndex;\n\n   short    sampleRootNoteMIDI;\n\n   WORD  sampleTemp1;\n\n} _SOS_SAMPLE;\n\n// enumeration for left or right channel\nenum\n{\n   _LEFT_CHANNEL,\n   _RIGHT_CHANNEL,\n   _CENTER_CHANNEL,\n   _INTERLEAVED\n};\n\n// enumeration for foreground and background\nenum\n{\n   _FOREGROUND,\n   _BACKGROUND\n};\n\n// defines for the sample flags\n#define  _ACTIVE           0x8000\n#define  _LOOPING          0x4000\n#define  _FIRST_TIME       0x2000\n#define  _PENDING_RELEASE  0x1000\n#define  _CONTINUE_BLOCK   0x0800\n#define  _PITCH_SHIFT      0x0400\n#define  _PANNING          0x0200\n#define  _VOLUME           0x0100\n#define  _TRANSLATE16TO8   0x0080\n#define  _STAGE_LOOP       0x0040\n#define  _TRANSLATE8TO16   0x0020\n#define  _STEREOTOMONO     0x0010\n\n// defines for the wParam flags\n#define  _SINGLE_SAMPLE 0x01\n\n#define  _SOS_DCAPS_AUTO_REINIT     0x01\n#define  _SOS_DCAPS_MPU_401         0x02\n#define  _SOS_DCAPS_OPL2            0x04\n#define  _SOS_DCAPS_OPL3            0x08\n#define  _SOS_DCAPS_OPL4            0x10\n#define  _SOS_DCAPS_WAVETABLE       0x20\n#define  _SOS_DCAPS_DL_SAMPLES      0x40\n#define  _SOS_DCAPS_FIFO_DEVICE     0x80\n#define  _SOS_DCAPS_ENV_NEEDED      0x100\n#define  _SOS_DCAPS_PSEUDO_DMA1     0x200\n#define  _SOS_DCAPS_SIGNED_DATA     0x8000\n\n// file header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // number of drivers in the file\n   WORD  wDrivers;\n\n   // offset of first driver\n   WORD  lOffset;\n\n   // size of the file\n   WORD  lFileSize;\n\n} _FILEHEADER;\n\n// driver header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // offset of next driver\n   WORD  lNextDriver;\n\n   // size of current driver\n   WORD  wSize;\n\n   // id for the current device\n   WORD  wDeviceID;\n\n   // id for the type of DOS extender\n   WORD  wExtenderType;\n\n} _DRIVERHEADER;\n\n// device hardware information\ntypedef struct\n{\n   // port to be used\n   WORD  wPort;\n\n   // irq to use\n   WORD  wIRQ;\n\n   // dma channel to se\n   WORD  wDMA;\n\n   // extra parameter\n   WORD  wParam;\n\n} _SOS_HARDWARE;\n\n// structure definition for start sample\ntypedef struct\n{\n   // pointer to sample\n   LPSTR lpSamplePtr;\n\n   // size of the sample\n   WORD  dwSampleSize;\n\n   // number of times to loop the sample -1 is infinite\n   WORD  wLoopCount;\n\n   // channel to play sample on\n   WORD  wChannel;\n\n   // volume to play sample at\n   WORD wVolume;\n\n   // id for the sample\n   WORD  wSampleID;\n\n   // far pointer to the callback function\n   VOID ( far __cdecl *lpCallback )( WORD, WORD, WORD );\n\n   // port to use if driver is a non-dma background driver\n   WORD  wSamplePort;\n\n   // flags field\n   WORD  wSampleFlags;\n\n   // total length of sample including loops, etc..\n   WORD     dwSampleByteLength;\n\n   // loop point for the sample\n   WORD  dwSampleLoopPoint;\n   WORD  dwSampleLoopLength;\n\n   // pitch shifting components\n   WORD     dwSamplePitchAdd;\n   WORD    wSamplePitchFraction;\n\n   // pan components\n   WORD    wSamplePanLocation;\n   WORD    wSamplePanSpeed;\n   WORD    wSamplePanDirection;\n   WORD    wSamplePanStart;\n   WORD    wSamplePanEnd;\n\n   // delay parts\n   WORD    wSampleDelayBytes;\n   WORD    wSampleDelayRepeat;\n\n   // compression components\n   WORD     dwSampleADPCMPredicted;\n   WORD    wSampleADPCMIndex;\n\n   // root note for pitch shifting\n   WORD    wSampleRootNoteMIDI;\n\n   // filler for future upgrades\n   WORD  dwSampleTemp1;\n   WORD  dwSampleTemp2;\n   WORD  dwSampleTemp3;\n\n} _SOS_START_SAMPLE;\n\n// structure for initializing a driver\ntypedef struct\n{\n   WORD  wBufferSize;\n   LPSTR lpBuffer;\n   BOOL  wAllocateBuffer;\n   WORD  wSampleRate;\n   WORD  wParam;\n   LONG  dwParam;\n   VOID ( far *lpFillHandler )( VOID );\n   LPSTR lpDriverMemory;\n   LPSTR lpDriverMemoryCS;\n   LPSTR lpTimerMemory;\n   LPSTR lpTimerMemoryCS;\n   WORD  wTimerID;\n   WORD  wPhysical;\n\n} _SOS_INIT_DRIVER;\n\n// define for the timer types to use\n#define  _SOS_NORMAL_TIMER          0x00\n\n// enumeration for the timer types\nenum\n{\n   _TIMER_8_MONO   =     0x1000,\n   _TIMER_8_ST,\n   _TIMER_16_MONO,\n   _TIMER_16_ST,\n   _TIMER_8_MONO_ULAW,\n   _TIMER_8_ST_ULAW,\n   _TIMER_16_MONO_ULAW,\n   _TIMER_16_ST_ULAW,\n   _TIMER_8_MONO_REC,\n   _TIMER_8_MONO_ULAW_REC,\n   _TIMER_UNDEFINED_1,\n   _TIMER_UNDEFINED_2,\n   _TIMER_UNDEFINED_3,\n   _TIMER_UNDEFINED_4,\n   _TIMER_UNDEFINED_5,\n   _TIMER_UNDEFINED_6,\n   _TIMER_UNDEFINED_7,\n   _TIMER_UNDEFINED_8,\n   _TIMER_UNDEFINED_9,\n   _TIMER_UNDEFINED_A,\n   _TIMER_UNDEFINED_B,\n   _TIMER_UNDEFINED_C,\n   _TIMER_UNDEFINED_D,\n   _TIMER_UNDEFINED_E,\n   _TIMER_UNDEFINED_F,\n   _TIMER_UNDEFINED_10,\n   _TIMER_UNDEFINED_11,\n   _TIMER_UNDEFINED_12,\n   _TIMER_UNDEFINED_13,\n   _TIMER_UNDEFINED_14,\n   _TIMER_UNDEFINED_15,\n   _TIMER_UNDEFINED_16,\n   _TIMER_8_SOUND_SOURCE,\n   _TIMER_8_SOUND_SOURCE_TANDY,\n   _TIMER_8_GENERAL_PORT,\n   _TIMER_8_GENERAL_PORT_REC\n};\n\n// define for no slots available\n#define  _ERR_NO_SLOTS ( WORD )-1\n\n// error codes for the system\nenum\n{\n   _ERR_NO_ERROR,\n   _ERR_DRIVER_NOT_LOADED,\n   _ERR_INVALID_POINTER,\n   _ERR_DETECT_INITIALIZED,\n   _ERR_FAIL_ON_FILE_OPEN,\n   _ERR_MEMORY_FAIL,\n   _ERR_INVALID_DRIVER_ID,\n   _ERR_NO_DRIVER_FOUND,\n   _ERR_DETECTION_FAILURE,\n   _ERR_DRIVER_LOADED,\n   _ERR_INVALID_HANDLE,\n   _ERR_NO_HANDLES,\n   _ERR_PAUSED,\n   _ERR_NOT_PAUSED,\n   _ERR_INVALID_DATA,\n   _ERR_DRV_FILE_FAIL,\n   _ERR_INVALID_PORT,\n   _ERR_INVALID_IRQ,\n   _ERR_INVALID_DMA,\n   _ERR_INVALID_DMA_IRQ\n};\n\n// maximum number of timer events that can be registered\n#define  _TIMER_MAX_EVENTS    0x10\n\n// flags for the debugging system\n#define  _SOS_DEBUG_NORMAL       0x0000\n#define  _SOS_DEBUG_NO_TIMER     0x0001\n#define  _SOS_TIMER_DPMI         0x0002\n\n// define for types of DOS extenders\n#define  _SOS_RATIONAL           0x8000\n#define  _SOS_FLASHTECK          0x4000\n\n// defines for the types of timers for different\n// dos extenders\n#define  _SOS_TIMER_NEAR         0x8000\n#define  _SOS_TIMER_FAR          0x4000\n\n// values for callback information\nenum\n{\n   _SAMPLE_PROCESSED,\n   _SAMPLE_LOOPING,\n   _SAMPLE_DONE\n};\n\n// define for special 18.2 callback rate to dos\n#define  _TIMER_DOS_RATE   0xff00\n\n#pragma pack()\n\n#pragma aux int_3 = \"int 3\"\n\n#pragma pack( 1 )\ntypedef struct\n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned       segment;\n\tunsigned short\tnumber_available;\n\tunsigned short number_used;\n\tunsigned       page0;\n\n} EVDS_STRUCT;\n\ntypedef struct\n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned short segment;\n\tunsigned short\tID;\n\tunsigned       physical;\n\n} VDS_STRUCT;\n\n#pragma pack()\n\n#include \"sosdata.h\"\n#include \"sosfnct.h\"\n\n#endif"
  },
  {
    "path": "WIN32LIB/AUDIO/SOSCODEC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*          Copyright (c) 1994, HMI, INC. All Rights Reserved\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     soscodec.asm\n;*\n;* DESCRIPTION\n;*     HMI SOS ADPCM compression/decompression.\n;*\n;* PROGRAMMER\n;*     Nick Skrepetos\n;*     Denzil E. Long, Jr. (Fixed bugs, rewrote for watcom)\n;*     Bill Petro\t\t   (Added stereo support)\n;*     Jonathan Lanier\n;*\n;* DATE\n;*     Febuary 15, 1995\n;*\n;* LAST MODIFIED\n;*     08/07/95 [jdl] - Rewrote/optimized sosCODECDecompressData\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\nDPMI_INTR\t\tequ\t31h\nIF_LOCKED_PM_CODE\tequ\t1h\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t2h\t\t; Locked PM code for DPMI.\n\nSTRUC\tsCompInfo\nlpSource\t\tDD\t?\t;Compressed data pointer\nlpDest\t\t\tDD\t?\t;Uncompressed data pointer\ndwCompSize\t\tDD\t?\t;Compressed size\ndwUnCompSize\t\tDD\t?\t;Uncompressed size\n\ndwSampleIndex\t\tDD\t?\t;Index into sample\ndwPredicted\t\tDD\t?\t;Next predicted value\ndwDifference\t\tDD\t?\t;Difference from last sample\nwCodeBuf\t\tDW\t?\t;Holds 2 nibbles for decompression\nwCode\t\t\tDW\t?\t;Current 4 bit code\nwStep\t\t\tDW\t?\t;Step value in table\nwIndex\t\t\tDW\t?\t;Index into step table\n\ndwSampleIndex2\t\tDD\t?\t;Index into sample\ndwPredicted2\t\tDD\t?\t;Next predicted value\ndwDifference2\t\tDD\t?\t;Difference from last sample\nwCodeBuf2 \t\tDW\t?\t;Holds 2 nibbles for decompression\nwCode2\t\t\tDW\t?\t;Current 4 bit code\nwStep2\t\t\tDW\t?\t;Step value in table\nwIndex2\t\t\tDW\t?\t;Index into step table\n\nwBitSize\t\tDW\t?\t;Bit size for decompression\nwChannels\t\tDW\t?    \t;number of channels\nENDS\tsCompInfo\n\n\n\tDATASEG\n\n\nInitFlags\tDD\t0\t\t; Flags to indicate what has been initialized.\n\n\nLABEL\tLockedDataStart\tBYTE\n\n;* Index table for stepping into step table\n\nINCLUDE\t\t\"difftb.inc\"\nINCLUDE\t\t\"indextb.inc\"\nINCLUDE\t\t\"nybbtb.inc\"\n\nLABEL\tLockedDataEnd\tBYTE\n\n\tCODESEG\n\nLABEL\tLockedCodeStart\tBYTE\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECInitStream - Initialize compression stream.\n;*\n;* SYNOPSIS\n;*     sosCODECInitStream(CompInfo)\n;*\n;*     void sosCODECInitStream(_SOS_COMPRESS_INFO *);\n;*\n;* FUNCTION\n;*     Initialize compression stream for compression and decompression.\n;*\n;* INPUTS\n;*     CompInfo - Compression information structure.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tsosCODECInitStream:NEAR\n\tPROC\tsosCODECInitStream C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\n\tmov\teax,[sSOSInfo]\n\tmov\t[(sCompInfo eax).wIndex],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).dwPredicted],0 \t; no predicted value\n\tmov\t[(sCompInfo eax).wIndex2],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).dwPredicted2],0 \t; no predicted value\n\tret\n\n\tENDP\tsosCODECInitStream\n\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECDecompressData - Decompress audio data.\n;*\n;* SYNOPSIS\n;*     Size = sosCODECDecompressData(CompInfo, NumBytes)\n;*\n;*     long sosCODECDecompressData(_SOS_COMPRESS_INFO *, long);\n;*\n;* FUNCTION\n;*     Decompress data from a 4:1 ADPCM compressed stream. The number of\n;*     bytes decompressed is returned.\n;*\n;* INPUTS\n;*     CompInfo - Compress information structure.\n;*     NumBytes - Number of bytes to decompress.\n;*\n;* RESULT\n;*     Size - Size of decompressed data.\n;*\n;*\n;* NOTES\n;*     This routine has been optimized for pipelining on both\n;*     486 and Pentium processors.  Changing, inserting, or moving any\n;*     instructions will most likely slow down the code, in some cases by\n;*     as much as 20%.  It can burst-decompress 16384 samples in about\n;*     1940s on a Pentium 90Mhz, and about 3960s on a 486 66Mhz.\n;*     Instruction reordering could bring this down to below 1870s on\n;*     the Pentium, but this would cause a great degradation in 486\n;*     performance.  Since slow 486's are the reason this code was\n;*     written to be fast, it has been optimized for the Pentium only where\n;*     it would not degrade 486 performance.  So, be careful when changing\n;*     ANY of this code, because it is very carefully balanced...\n;****************************************************************************\n\n\tGLOBAL\tC sosCODECDecompressData:NEAR\n\tPROC\tsosCODECDecompressData C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\tARG\twBytes:DWORD\n\n\tpush\tesi\n\tpush\tedi\n\tpush\tebx\n\tpush\tecx\n\tpush\tedx\t\t\t;save all the regs\n\n\tmov\tebx,[sSOSInfo]\t\t;get base of sCompInfo struct\n\tmov\tcx,[(sCompInfo ebx).wBitSize] ;check the bit size\n\tmov\tdx,[(sCompInfo ebx).wChannels] ;check the number of channels\n;\n;\n; Determine the correct routine to use for decoding\n; (for now only ADPCM 4:1 Mono 16-bit is implemented)\n\tcmp\tcx,8\n\tjne\t??do16Bits\n\n??do8Bits:\n\tcmp\tdx,2\n\tjne\t??not8Stereo\n;\tjmp\t??decomp8Stereo\n\tjmp\t??byeBye\n\n??not8Stereo:\n\tcmp\tdx,1\n\tjne\t??byeBye\n;\tjmp\tdecomp8Mono\n\tjmp\t??byeBye\n\n??do16Bits:\n\tcmp\tcx,16\n\tjne\t??byeBye\n\n\tcmp\tdx,2\n\tjne\t??not16Stereo\n;\tjmp\t??decomp16Stereo\n\tjmp\t??byeBye\n\n??not16Stereo:\n\tcmp\tdx,1\n\tjne\t??byeBye\n\n\tpush\tebp\n;\n;\n; 16 bit ADPCM 4:1 Mono pre-loop initialization\n??decomp16Mono:\n\tpush\tebx\t\t\t;save struct base\n\txor\tedx,edx\t\t\t;clear index\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\t;get last sample\n\tmov\tdx,[(sCompInfo ebx).wIndex]\t;get last index value\n\tmov\tesi,[(sCompInfo ebx).lpSource]\t;get source address\n\tmov\tedi,[(sCompInfo ebx).lpDest]\t;get dest address\n\n\tmov\tebp,[wBytes]\t\t;get the number of dest. bytes\n\tcmp\tebp,16\t\t\t;less than 16? (less than 8 samples)\n\tjl\t??fixAlign16Mono0\t;if so, don't bother with alignment\n;\n;\n; Check to see if we need to fix an alignment problem on the source buffer\n; (non-aligned buffers are MUCH slower; if we're given a non-DWORD aligned\n; source address, we do as many samples as needed to get to the nearest\n; DWORD boundary, then finish the bulk as a DWORD-aligned decompress).\n\tmov\tebx,esi\t\t\t;get source address\n\tand\tebx,03h\t\t\t;check LSB\n\tjnz\t??fixalign16Mono\t;if non-zero, need to align for\n\t\t\t\t\t;warp speed\n??fixAlign16Mono0:\n\tpush\tebp\t\t\t;save for later\n\tshr\tebp,4\t\t\t;divide by 16 for 16-bit,\n\t\t\t\t\t;because we do 8 nybbles per loop,\n\t\t\t\t\t;and there are two samples per\n\t\t\t\t\t;byte, so there are n/16 iterations\n\t\t\t\t\t;required\n\txor\tebx,ebx\t\t\t;clear our nybble index\n\tor\tebp,ebp\t\t\t;set flags for EBP\n\tjmp\t??start16Mono\t\t;start with test... don't go if\n\t\t\t\t\t;we have zero bytes to do\n??fixalign16Mono:\n\tjmp\t[DWORD PTR dwMono16AlignJmpTable+ebx*4] ;do non-aligned first\n\n\talign\t4\n??fixAlign16Mono1:\n\tsub\tebp,12\t\t\t;adjust # of dest. bytes\n\tpush\tebp\t\t\t;save it\n\tshr\tebp,4\t\t\t;divide by 16 to get samples/8\n\txor\tebx,ebx\t\t\t;clear our nybble index\n\tinc\tebp\t\t\t;adjust ebp for loop\n\tjmp\t??finish16Mono6\t\t;borrow exit code to go through a\n\t\t\t\t\t;piece of a loop\n\talign\t4\n??fixAlign16Mono2:\n\tsub\tebp,8\t\t\t;adjust # of dest. bytes\n\tpush\tebp\t\t\t;save it\n\tshr\tebp,4\t\t\t;divide by 16 to get samples/8\n\txor\tebx,ebx\t\t\t;clear our nybble index\n\tinc\tebp\t\t\t;adjust ebp for loop\n\tjmp\t??finish16Mono4\t\t;borrow exit code to go through a\n\t\t\t\t\t;piece of a loop\n\talign\t4\n??fixAlign16Mono3:\n\tsub\tebp,4\t\t\t;adjust # of dest. bytes\n\tpush\tebp\t\t\t;save it\n\tshr\tebp,4\t\t\t;divide by 16 to get samples/8\n\txor\tebx,ebx\t\t\t;clear our nybble index\n\tinc\tebp\t\t\t;adjust ebp for loop\n\tjmp\t??finish16Mono2\t\t;borrow exit code to go through a\n\t\t\t\t\t;piece of a loop\n; \"The Loop\"\n;\n; Process 1st nybble\n\talign\t4\n??loop16Mono:\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix1Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix1Smp16MonoU\n??fixed1Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tmov\t[edi],ax\t\t;save the sample\n;\n;\n; Process 2nd nybble\n??finish7Smp16Mono:\n\tmov\tbl,ch\t\t\t;get next 2 nybbles in ebx\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix2Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix2Smp16MonoU\n??fixed2Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tmov\t[edi+02h],ax\t\t;save the sample\n\tshr\tecx,16\t\t\t;move top four nybbles into bottom\n;\n;\n; Process 3rd nybble\n??finish6Smp16Mono:\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix3Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix3Smp16MonoU\n??fixed3Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tmov\t[edi+04h],ax\t\t;save the sample\n;\n;\n; Process 4th nybble\n??finish5Smp16Mono:\n\tmov\tbl,cl\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix4Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix4Smp16MonoU\n??fixed4Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tmov\t[edi+06h],ax\t\t;save the sample\n;\n;\n; Process 5th nybble\n??finish4Smp16Mono:\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix5Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix5Smp16MonoU\n??fixed5Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tmov\t[edi+08h],ax\t\t;save the sample\n;\n;\n; Process 6th nybble\n??finish3Smp16Mono:\n\tmov\tbl,ch\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix6Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix6Smp16MonoU\n??fixed6Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tmov\t[edi+0Ah],ax\t\t;save the sample\n;\n;\n; Process 7th nybble\n??finish2Smp16Mono:\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix7Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix7Smp16MonoU\n??fixed7Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tmov\t[edi+0Ch],ax\t\t;save the sample\n;\n;\n; Process 8th nybble\n??finish1Smp16Mono:\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix8Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix8Smp16MonoU\n;\n;\n; Loop cleanup for next pass\n??fixed8Smp16Mono:\n\tmov\t[edi+0Eh],ax\t\t;save the sample\n\tadd\tesi,04h\t\t\t;bump esi to point to next longword\n\tadd\tedi,10h\t\t\t;incr. the destination buffer ptr\n\tdec\tebp\t\t\t;count down the number of samples/8\n??start16Mono:\n\tjng\t??cleanup16Mono\t\t;if done, clean up\n\tmov\tecx,[esi]\t\t;get 4 nybbles in one whack (whee!)\n\tmov\tbl,cl\t\t\t;get next 2 nybbles in ebx\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tjmp\t??loop16Mono\t\t;loop until done\n\n??cleanup16Mono:\n\tjnz\t??done16Mono\t\t;if ebp is non-zero, we're DONE\n\t\t\t\t\t;if exactly zero, finish the tail-end\n\t\t\t\t\t;of the conversion (may be a non-\n\t\t\t\t\t;multiple of 8 nybbles)\n;\n;\n; Loop cleanup for last (incomplete) pass\n\tpop\tecx\t\t\t;restore # of words\n\tshr\tecx,1\t\t\t;divide by two to get samples\n\tand\tecx,07h\t\t\t;get # of samples we missed\n\tjmp\t[DWORD PTR dwMono16JmpTable+ecx*4] ;go finish the job...\n;\n;\n; Structure cleanup\n??done16Mono:\n\tpop\tebx\t\t\t;restore struct base\n\tpop\tebp\t\t\t;restore stack frame pointer\n\tmov\t[(sCompInfo ebx).dwPredicted],eax ;save last sample\n\tmov\t[(sCompInfo ebx).wIndex],dx ;save last index value\n\tmov\teax,[wBytes]\t\t;get # of bytes we did\n??byeBye:\n\tpop\tedx\t\t\t;restore all the regs\n\tpop\tecx\n\tpop\tebx\n\tpop\tedi\n\tpop\tesi\n\tret\n;\n;\n; Jumps for -32768/+32767 bounds check go to these vvvv\n\talign\t4\n??fix1Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed1Smp16Mono\t;go back\n\n\talign\t4\n??fix1Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed1Smp16Mono\t;go back\n\n\talign\t4\n??fix2Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed2Smp16Mono\t;go back\n\n\talign\t4\n??fix2Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed2Smp16Mono\t;go back\n\n\talign\t4\n??fix3Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed3Smp16Mono\t;go back\n\n\talign\t4\n??fix3Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed3Smp16Mono\t;go back\n\n\talign\t4\n??fix4Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed4Smp16Mono\t;go back\n\n\talign\t4\n??fix4Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed4Smp16Mono\t;go back\n\n\talign\t4\n??fix5Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed5Smp16Mono\t;go back\n\n\talign\t4\n??fix5Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed5Smp16Mono\t;go back\n\n\talign\t4\n??fix6Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed6Smp16Mono\t;go back\n\n\talign\t4\n??fix6Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed6Smp16Mono\t;go back\n\n\talign\t4\n??fix7Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed7Smp16Mono\t;go back\n\n\talign\t4\n??fix7Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed7Smp16Mono\t;go back\n\n\talign\t4\n??fix8Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed8Smp16Mono\t;go back\n\n\talign\t4\n??fix8Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed8Smp16Mono\t;go back\n;\n;\n; Jump tables for cleanup after loop unroll point to these vvvv\n\talign\t4\n??finish16Mono1:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tch,[esi]\t\t;get 1 nybble (1 byte)\n\tshl\tch,4\t\t\t;move it over\n\tmov\tbl,ch\t\t\t;get nybble in ebx\n\tsub\tedi,0Eh\t\t\t;back edi up\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tjmp\t??finish1Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono2:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tch,[esi]\t\t;get 2 nybbles (1 byte)\n\tmov\tbl,ch\t\t\t;get nybbles in ebx\n\tsub\tedi,0Ch\t\t\t;back edi up\n\tsub\tesi,3\t\t\t;adjust esi (used for dword aligning)\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tjmp\t??finish2Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono3:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tcx,[esi]\t\t;get 3 nybbles (2 bytes)\n\tshl\tcx,4\t\t\t;move it over\n\tmov\tbl,cl\t\t\t;get nybbles in ebx\n\tsub\tedi,0Ah\t\t\t;back edi up\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tjmp\t??finish3Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono4:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tcx,[esi]\t\t;get 4 nybbles (2 bytes)\n\tmov\tbl,cl\t\t\t;get nybbles in ebx\n\tsub\tedi,08h\t\t\t;back edi up\n\tsub\tesi,2\t\t\t;adjust esi (used for dword aligning)\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tjmp\t??finish4Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono5:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tcl,[esi+2]\t\t;get 1 nybble (1 byte)\n\tshl\tecx,16\t\t\t;shift it over\n\tmov\tcx,[esi]\t\t;get 4 nybbles (2 bytes)\n\tmov\tbl,cl\t\t\t;get nybbles in ebx\n\tshr\tecx,4\t\t\t;move it over\n\tshl\tbl,4\t\t\t;move it over\n\tsub\tedi,06h\t\t\t;back edi up\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tjmp\t??finish5Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono6:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tcl,[esi+2]\t\t;get 2 nybbles (1 byte)\n\tshl\tecx,16\t\t\t;move it over\n\tmov\tcx,[esi]\t\t;get 4 nybbles (2 bytes)\n\tmov\tbl,cl\t\t\t;get nybbles in ebx\n\tshr\tecx,8\t\t\t;move it over\n\tsub\tesi,1\t\t\t;adjust esi (used for dword aligning)\n\tsub\tedi,04h\t\t\t;back edi up\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tjmp\t??finish6Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono7:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tecx,[esi]\t\t;get 7 nybbles (4 bytes)\n\tshl\tecx,4\t\t\t;move it over\n\tmov\tbl,cl\t\t\t;get nybbles in ebx\n\tsub\tedi,02h\t\t\t;back edi up\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tjmp\t??finish7Smp16Mono\t;go finish it\n;\n;\n; Jump Tables\n\t\t\talign 4\n\ndwMono16JmpTable\tDD\t??done16Mono\n\t\t\tDD\t??finish16Mono1\n\t\t\tDD\t??finish16Mono2\n\t\t\tDD\t??finish16Mono3\n\t\t\tDD\t??finish16Mono4\n\t\t\tDD\t??finish16Mono5\n\t\t\tDD\t??finish16Mono6\n\t\t\tDD\t??finish16Mono7\n\n\t\t\talign 4\ndwMono16AlignJmpTable\tDD\t??fixAlign16Mono0\n\t\t\tDD\t??fixAlign16Mono1\n\t\t\tDD\t??fixAlign16Mono2\n\t\t\tDD\t??fixAlign16Mono3\n\n\tENDP\tsosCODECDecompressData\n\nLABEL\tLockedCodeEnd\tBYTE\n\n;***************************************************************************\n;* sosCODEC_LOCK -- locks the JLB audio decompression code\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is lock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:       BOOL sosCODEC_Lock(void);                         \t   *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tsosCODEC_Lock:NEAR\n\tPROC\tsosCODEC_Lock C NEAR USES ebx ecx edx esi edi\n\n\t;\n\t; Lock the code that is used by the sos decompression method.\n\t;\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n  \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags], IF_LOCKED_PM_CODE\n\n\t;\n\t; Lock the data used by the sos decompression method.\n\t;\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags], IF_LOCKED_PM_DATA\n\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\tENDP\tsosCODEC_Lock\n\n;***************************************************************************\n;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code       *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is unlock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:\tBOOL sosCODEC_Unlock(void);                        \t   *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tsosCODEC_Unlock:NEAR\n\tPROC\tsosCODEC_Unlock C NEAR USES ebx ecx edx esi edi\n\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\n??code_not_locked:\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??data_not_locked:\n\tmov\t[InitFlags],0\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\tENDP\tsosCODEC_Unlock\n\n\tEND\n\n"
  },
  {
    "path": "WIN32LIB/AUDIO/SOSCOMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*  File              : soscomp.h\n*  Date Created      : 6/1/94\n*  Description       :\n*\n*  Programmer(s)     : Nick Skrepetos\n*  Last Modification : 10/1/94 - 11:37:9 AM\n*  Additional Notes  : Modified by Denzil E. Long, Jr.\n*\n*****************************************************************************\n*            Copyright (c) 1994,  HMI, Inc.  All Rights Reserved            *\n****************************************************************************/\n\n#ifndef  _SOS_COMPRESS\n#define  _SOS_COMPRESS\n\n/* compression types */\nenum {\n\t_ADPCM_TYPE_1,\n\t};\n\n/* define compression structure */\ntypedef struct _tagCOMPRESS_INFO {\n\tchar       *lpSource;\n\tchar       *lpDest;\n\tunsigned long dwCompSize;\n\tunsigned long dwUnCompSize;\n\tunsigned long dwSampleIndex;\n\tlong          dwPredicted;\n\tlong          dwDifference;\n\tshort         wCodeBuf;\n\tshort         wCode;\n\tshort         wStep;\n\tshort         wIndex;\n\n\tunsigned long dwSampleIndex2; //added BP for channel 2\n\tlong          dwPredicted2;   //added BP for channel 2\n\tlong          dwDifference2; \t//added BP for channel 2\n\tshort         wCodeBuf2; \t\t//added BP for channel 2\n\tshort         wCode2; \t\t\t//added BP for channel 2\n\tshort         wStep2; \t\t\t//added BP for channel 2\n\tshort         wIndex2; \t\t\t//added BP for channel 2\n\tshort         wBitSize;\n\tshort\t\t\t  wChannels;\t\t//added BP for # of channels\n\t} _SOS_COMPRESS_INFO;\n\n/* compressed file type header */\ntypedef struct _tagCOMPRESS_HEADER {\n\tunsigned long dwType;              // type of compression\n\tunsigned long dwCompressedSize;    // compressed file size\n\tunsigned long dwUnCompressedSize;  // uncompressed file size\n\tunsigned long dwSourceBitSize;     // original bit size\n\tchar          szName[16];          // file type, for error checking\n\t} _SOS_COMPRESS_HEADER;\n\n/* Prototypes */\nextern \"C\" {\n\tvoid __cdecl sosCODECInitStream(_SOS_COMPRESS_INFO *);\n\tunsigned long __cdecl sosCODECCompressData(_SOS_COMPRESS_INFO *,\tunsigned long);\n\tunsigned long __cdecl sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);\n\tunsigned long __cdecl General_sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);\n}\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/AUDIO/SOSDATA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdata.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces\n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DATA\n#define  _SOS_DATA\n\n#include <stddef.h>\n\n#pragma pack(4)\nextern   WORD     _sosDIGIData_Start;\nextern   WORD     _sosDIGIData_End;\nextern   WORD     _wSOSDriverLinear[];\nextern   WORD     _wSOSTimerLinear[];\nextern   LPSTR    _lpSOSDriver[];\nextern   LPSTR    _lpSOSTimer[];\nextern   LPSTR    _lpSOSDriverCS[];\nextern   LPSTR    _lpSOSTimerCS[];\nextern   BOOL     _wSOSDriverLoaded[];\nextern   BOOL     _wSOSTimerLoaded[];\nextern   BOOL     _wSOSDriverInitialized[];\nextern   WORD     _wSOSOutputRate[];\nextern   WORD     _wSOSDMABuffersize[];\nextern   LONG     _dwSOSDMABufferPhysical[];\nextern   LPSTR    _lpSOSDMABuffer[];\nextern   BOOL     _wTimerUsed;\nextern   VOID ( far *_lpSOSFillHandler[] )( VOID );\nextern   WORD     _wSOSTimerType[];\nextern   WORD     _wSOSDriverType[];\nextern   _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ];\nextern   LPWORD      _lpSOSDMAIrqCount[];\nextern   LPWORD      _lpSOSDMAFillCount[];\nextern   WORD        _wSOSTmrNextCount;\nextern   VOID ( interrupt far *_lpSOSOldTimer )( VOID );\nextern   WORD     _wSOSDriverID[];\nextern   _SOS_CAPABILITIES _sSOSDriverCaps[];\nextern   WORD        _wSOSDMAPortList[];\nextern   BYTE        _bSOSDMAChannel[];\nextern   _SOS_INIT_DRIVER     _sSOSDIGIInitDriver[];\nextern   BYTE  _pSOSDriverPath[];\nextern   BYTE  _pSOSTempDriverPath[];\nextern   BOOL  _wTIMERUsed;\nextern   WORD  _wTIMERValue;\nextern   VOID ( far * _lpTIMEREvents[] )( VOID );\nextern   WORD _wTIMEREventRate[];\nextern   WORD _dwTIMEREventFraction[];\nextern   WORD _dwTIMEREventFractionCurrent[];\nextern   BYTE  _bSOSMIDITimerSongHandler[];\nextern   BYTE  _bSOSMIDISongHandle;\nextern   WORD  _wSOSTimerMemHandle[];\nextern   WORD  _wSOSDriverMemHandle[];\nextern   WORD  _wSOSRealSeg[];\n\nextern   _FILEHEADER    _sDETFileHeader;\nextern   _DRIVERHEADER  _sDETDriverHeader;\nextern   _FILEHEADER    sLOADFileHeader;\nextern   _DRIVERHEADER  sLOADDriverHeader;\nextern   BOOL           _wDETInitialized;\nextern   WORD           _wDETLinear;\nextern   LPSTR          _lpDETDriverBuffer;\nextern   LPSTR          _lpDETDriverBufferCS;\nextern   WORD           _hDETFile;\nextern   DWORD          _dwDETDriverIndex;\nextern   WORD           _wDETDriverIndexCur;\nextern   WORD           _wDETMemHandle;\nextern   LPSOSDEVICECAPS _lpDETDeviceCaps;\nextern   _SOS_CAPABILITIES _sDETCaps;\nextern   PSTR _pSOSErrorStrings[];\nextern   BOOL _wSOSBufferAllocated[];\nextern   BOOL _wSOSSystemInitialized;\nextern   VDS_STRUCT _sSOSVDSInfo;\nextern   _SOS_FILL_INFO _sSOSFillInfo;\nextern   WORD    _wSOSTimerEventIndex;\nextern   WORD  _wSOSTimerEntered;\nextern   WORD  _wSOSDriverSize[];\nextern   WORD  _wSOSTimerSize[];\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nextern   WORD  _sosDIGIData1_Start;\nextern   WORD  _sosDIGIData1_End;\nextern   WORD  _sosDIGIData2_Start;\nextern   WORD  _sosDIGIData2_End;\nextern   BYTE  _bTIMERInstalled;\nextern   BYTE  _bTIMERDPMI;\nextern   WORD  wDetectPort;\nextern   WORD  wDetectIRQ;\nextern   WORD  wDetectDMA;\nextern   WORD  wDetectParam;\n#ifdef __cplusplus\n}\n#endif\n\n#pragma pack()\n\n#endif\n\n"
  },
  {
    "path": "WIN32LIB/AUDIO/SOSDEFS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdefs.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces\n                            All Rights Reserved\n****************************************************************************/\n\n\n#ifndef  _SOSDEFS_DEFINED\n#define  _SOSDEFS_DEFINED\n\n#undef   _TRUE\n#undef   _FALSE\n#undef   _NULL\nenum\n      {\n         _FALSE,\n         _TRUE\n      };\n\n#define  _NULL  0\n\n#ifndef  VOID\n#define  VOID           void\n#endif\ntypedef  int            BOOL;\ntypedef  unsigned int   UINT;\ntypedef  unsigned char  BYTE;\ntypedef  unsigned       WORD;\n#ifndef  LONG\ntypedef  signed long    LONG;\n#endif\ntypedef  unsigned long  DWORD;\n\ntypedef  BYTE  *        PBYTE;\ntypedef  char near *    PSTR;\ntypedef  WORD  *        PWORD;\ntypedef  LONG  *        PLONG;\ntypedef  VOID  *        PVOID;\n\ntypedef  BYTE  far   *  LPBYTE;\ntypedef  BYTE  far   *  LPSTR;\ntypedef  WORD  far   *  LPWORD;\ntypedef  LONG  far   *  LPLONG;\ntypedef  VOID  far   *  LPVOID;\n\ntypedef  BYTE  huge  *  HPBYTE;\ntypedef  BYTE  huge  *  HPSTR;\ntypedef  WORD  huge  *  HPWORD;\ntypedef  LONG  huge  *  HPLONG;\ntypedef  VOID  huge  *  HPVOID;\n\ntypedef  unsigned       HANDLE;\n\n#endif\n\n"
  },
  {
    "path": "WIN32LIB/AUDIO/SOSFNCT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosfnct.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces\n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_FUNCTIONS\n#define  _SOS_FUNCTIONS\n\n#pragma pack(4)\n\nWORD sosDIGILockMemory          (  VOID  );\nWORD sosDIGIUnLockMemory        (  VOID  );\nWORD sosDIGIInitSystem           (  LPSTR, WORD  );\nWORD sosDIGIUnInitSystem         (  VOID  );\nWORD sosDIGIInitDriver           (  WORD, _SOS_HARDWARE far *,\n                                    _SOS_INIT_DRIVER far *, WORD far *   );\nWORD sosDIGIUnInitDriver         (  WORD, BOOL, BOOL  );\nWORD sosDIGILoadDriver          (  WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD sosDIGIUnLoadDriver         (  WORD  );\nWORD sosDIGIGetDeviceCaps        (  WORD, LPSOSDEVICECAPS  );\n\n#ifdef PHARLAP\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#else\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#endif\n\nWORD sosDIGIStopSample           (  WORD, WORD  );\nWORD sosDIGISamplesPlaying       (  WORD  );\nBOOL sosDIGISampleDone           (  WORD, WORD  );\nBOOL sosDIGISampleFilling        (  WORD, WORD  );\nWORD sosDIGIStartSample          (  WORD, _SOS_START_SAMPLE far *  );\nWORD sosDIGIContinueSample       (  WORD, WORD, _SOS_START_SAMPLE far * );\n\n\nWORD  sosDIGIDetectInit          (  LPSTR  );\nWORD  sosDIGIDetectUnInit        (  VOID  );\nWORD  sosDIGIDetectFindHardware  (  WORD, _SOS_CAPABILITIES far *, WORD far * );\nWORD  sosDIGIDetectFindFirst     (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectFindNext      (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectGetSettings   (  _SOS_HARDWARE far *  );\nWORD  sosDIGIDetectGetCaps       (  WORD, _SOS_CAPABILITIES far *  );\nWORD  sosDIGIDetectVerifySettings(  _SOS_HARDWARE far *  );\nPSTR  sosGetErrorString          (  WORD  );\n\nWORD  sosDIGILoadTimer           (  WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD  sosDIGIUnLoadTimer         (  WORD  );\n\nWORD  sosTIMERRegisterEvent      ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle );\nWORD  sosTIMERInitSystem               (  WORD, WORD  );\nWORD  sosTIMERUnInitSystem             (  WORD  );\nWORD  sosTIMERSetRate                  (  WORD  );\nWORD  sosTIMERRemoveEvent              (  WORD );\nWORD  sosTIMERAlterEventRate           (  WORD, WORD  );\nWORD  sosTIMERGetEventRate             (  WORD  );\nVOID far sosTIMEROldHandler            (  VOID  );\nVOID far sosTIMERHandler               (  VOID  );\n\n// functions in soscntl.c\nWORD  sosDIGISetSampleVolume     ( WORD, WORD, WORD );\nWORD  sosDIGIGetSampleVolume     ( WORD, WORD );\nWORD  sosDIGISetChannel          ( WORD, WORD, WORD );\nWORD  sosDIGIGetChannel          ( WORD, WORD );\nWORD  sosDIGIGetBytesProcessed   ( WORD, WORD );\nWORD  sosDIGIGetLoopCount        ( WORD, WORD );\nWORD  sosDIGISetPanLocation      ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanLocation      ( WORD, WORD );\nDWORD sosDIGISetPitch            ( WORD, WORD, DWORD );\nDWORD sosDIGIGetPitch            ( WORD, WORD );\nWORD  sosDIGIGetDMAPosition      ( WORD );\nWORD  sosDIGISetPanSpeed         ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanSpeed         ( WORD, WORD );\nWORD  sosDIGIGetSampleID         ( WORD, WORD );\nWORD  sosDIGIGetSampleHandle     ( WORD, WORD );\nWORD  sosDIGISetMasterVolume     ( WORD, WORD );\n#ifdef PHARLAP\nVOID  sosFreeVDSPage          ( unsigned short, unsigned short, DWORD );\nWORD  sosAllocVDSPage         ( unsigned short *, unsigned short *, DWORD * );\n#else\nWORD  sosAllocVDSPage            ( LPSTR *, WORD *, WORD * );\nVOID  sosFreeVDSPage             ( WORD, WORD, LONG );\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef PHARLAP\nextern   int   __cdecl sosRealFree          ( int );\nextern   BOOL  __cdecl  _sos_read( WORD, LPSTR, WORD, WORD * );\nextern   int   __cdecl sosRealAlloc( int, int *, int * );\nextern   void  __cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD );\nextern   int   __cdecl sosGetCS( VOID );\nextern   int   __cdecl sosGetES( VOID );\n#else\nextern   int   __cdecl sosRealAlloc         ( int, int *, int * );\nextern   int   __cdecl sosRealFree          ( int );\n#endif\n\n// sos driver functions\nextern   WORD  __cdecl sosDRVLockMemory     ( DWORD, DWORD );\nextern   WORD  __cdecl sosDRVUnLockMemory   ( DWORD, DWORD );\nextern   void  __cdecl sosDRVGetCapsInfo    ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  __cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  __cdecl sosDRVGetCapsPtr     ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  __cdecl sosDRVInit           ( LPSTR, LPSTR, int, int, int, int, int, int );\nextern   void  __cdecl sosDRVStart          ( LPSTR, LPSTR, int, int );\nextern   void  __cdecl sosDRVSetRate        ( LPSTR, LPSTR, int );\nextern   void  __cdecl sosDRVSetAction      ( LPSTR, LPSTR );\nextern   void  __cdecl sosDRVStop           ( LPSTR, LPSTR );\nextern   void  __cdecl sosDRVUnInit         ( LPSTR, LPSTR );\nextern   void  __cdecl sosDRVGetFillInfo    ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * );\nextern   void  __cdecl sosFillSampleStructs ( PSTR, LPSTR );\nextern   WORD  __cdecl sosDetDRVExist       ( LPSTR, LPSTR );\nextern   WORD  __cdecl sosDetDRVGetSettings ( LPSTR, LPSTR );\nextern   WORD  __cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR );\nextern   WORD  __cdecl sosDIGIInitForWindows( WORD );\nextern   WORD  __cdecl sosDIGIUnInitForWindows( WORD );\nextern   LPSTR __cdecl sosAllocateFarMem      ( WORD, PSTR, WORD * );\nextern   LPSTR __cdecl sosCreateAliasCS       ( LPSTR );\nextern   VOID  __cdecl sosFreeSelector        ( LPSTR, DWORD );\nextern   LPSTR __cdecl sosMAKEDOSPtr          ( PSTR );\nextern   VOID  __cdecl sosDetDRVSetEnvString  ( DWORD, PSTR );\nextern   PSTR  __cdecl sosDetDRVGetEnvString  ( DWORD );\nextern   VOID  __cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR );\nextern   VOID  __cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR );\nextern   WORD  __cdecl sosDRVGetFreeMemory     ( VOID );\nextern   WORD  __cdecl sosDRVAllocVDSStruct    ( WORD, WORD *, WORD * );\nextern   WORD  __cdecl sosDRVFreeVDSStruct     ( WORD, WORD );\nextern   WORD  __cdecl sosDRVIsWindowsActive   ( VOID );\nextern   WORD  __cdecl sosDRVVDSGetBuffer    ( WORD );\nextern   WORD  __cdecl sosDRVVDSFreeBuffer   ( WORD );\nextern   WORD  __cdecl getDS( VOID );\nextern   WORD  __cdecl sosDRVMakeDMASelector   ( WORD );\nextern   WORD  __cdecl sosDRVFreeDMASelector   ( WORD );\n\n\nextern   void  __cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) );\nextern   void  __cdecl sosTIMERDRVUnInit( void );\nextern   void  __cdecl sosTIMERDRVHandler( void );\nextern   void  __cdecl sosTIMERDRVFHandler( void );\nextern   void  __cdecl sosTIMERDRVEnable( void );\nextern   void  __cdecl sosTIMERDRVDisable( void );\nextern   void  __cdecl sosTIMERDRVCallOld( void );\nextern   void  __cdecl sosTIMERDRVSetRate( WORD );\nextern   void  __cdecl sosDIGITimer_Start( void );\nextern   void  __cdecl sosDIGITimer_End( void );\nextern   void  __cdecl sosDIGIDrv_Start( void );\nextern   void  __cdecl sosDIGIDrv_End( void );\n#ifdef __cplusplus\n}\n#endif\n\n// external functions for handling system initialization and\n// uninitialization\nWORD  sosEXDIGInitDriver               (  WORD, WORD, WORD, LPSTR,\n                                          _SOS_HARDWARE far *, WORD *  );\nWORD  sosEXDIGIUnInitDriver            (  VOID  );\n\nWORD  sosEXDETFindDriver               (  WORD, LPSTR, _SOS_HARDWARE far *,\n                                          _SOS_CAPABILITIES far *  );\n\n// memory locking prototypes\nVOID  sosDIGICaps_Start( VOID );\nVOID  sosDIGICaps_End( VOID );\nVOID  sosDIGIErr_Start( VOID );\nVOID  sosDIGIErr_End( VOID );\nVOID  sosDIGITmr_Start( VOID );\nVOID  sosDIGITmr_End( VOID );\nVOID  sosDIGIStart_Start( VOID );\nVOID  sosDIGIStart_End( VOID );\nVOID  sosDIGIPlyng_Start( VOID );\nVOID  sosDIGIPlyng_End( VOID );\nVOID  sosDIGIRate_Start( VOID );\nVOID  sosDIGIRate_End( VOID );\nVOID  sosDIGIDone_Start( VOID );\nVOID  sosDIGIDone_End( VOID );\nVOID  sosDIGIDetec_Start( VOID );\nVOID  sosDIGIDetec_End( VOID );\nVOID  sosDIGIInit_Start( VOID );\nVOID  sosDIGIInit_End( VOID );\nVOID  sosDIGILoad_Start( VOID );\nVOID  sosDIGILoad_End( VOID );\nVOID  sosDIGICntl_Start( VOID );\nVOID  sosDIGICntl_End( VOID );\n\n#pragma pack()\n\n#endif\n\n"
  },
  {
    "path": "WIN32LIB/AUDIO/SOSRES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosres.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#define  _SOS_RESOURCE\n#ifndef  _SOS_RESOURCE\n#define  _SOS_RESOURCE\n\n// structure for resource file header\ntypedef struct\n{\n   // file version\n   WORD     wVersion;\n\n   // file size\n   LONG     dwFileSize;\n\n   // number of resources in file\n   WORD     wResCount;\n\n   // offset of resource data from top of file\n   LONG     dwResOffset;\n\n   // offset of sync track from top of file\n   LONG     dwSyncTrackOffset;\n\n}  _RES_FILE_HEADER;\n\n// structure for resource block header\ntypedef struct\n{\n   // resource id\n   WORD     wID;\n\n   // resource type\n   WORD     wResType;\n\n   // offset of next block\n   LONG     dwNextBlock; \n\n   // size of the current resource information\n   LONG     dwResSize;\n\n   // rate to play block at\n   WORD     wBlockRate;\n\n   // id for the sync track to use\n   WORD     wSyncTrackID;\n\n}  _RES_BLOCK_HEADER;\n\n// structure for sync mark tag\ntypedef struct _tagSYNCMARK\n{\n   // ID of the type of mark being used\n   WORD  wID;\n\n   // location in data of sync mark\n   LONG  dwSyncOffset;\n\n   // length of sync block\n   LONG  dwSyncSize;\n\n   // start sample data\n   _SOS_START_SAMPLE sampleData;\n    \n} _RES_SYNCMARK;\n\ntypedef union\n{\n   // structure for sync mark tag\n   _RES_SYNCMARK  syncMark; \n\n} _RES_TAG;\n\n// union for filter information for prepareWave\ntypedef union\n{\n   // filter type\n   WORD     wFilterID;\n\n   // structure for volume\n   struct   volume \n   {\n      WORD  wVolume;\n   };\n\n   // structure for delay\n   struct   delay\n   {  \n      WORD  wDelaySamples;\n   };\n\n} _SOS_FILTER; \n\n \n#endif\n\n\u001a"
  },
  {
    "path": "WIN32LIB/AUDIO/SOUND.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : SOUND.H                                  *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : September 1, 1993                        *\n *                                                                         *\n *                  Last Update : September 1, 1993   [JLB]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SOUND_H\n#define SOUND_H\n\n//#define\tHMI_DRIVER\tTRUE\n//#include\t\"sos.h\"\n#include\t\"soscomp.h\"\n\n/*\n**\tMaximum number of sound effects that may run at once.\n*/\n#define\tMAX_SFX\t\t5\n\n/*\n** Size of temp HMI low memory staging buffer.\n*/\n#define\tSECONDARY_BUFFER_SIZE\t\t(1024*32)\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/AUDIO/SOUNDINT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDINT.CPP                             *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 28, 1995   [PWG]                    *\n *                                                                         *\n * This module contains all of the functions that are used within our      *\n * sound interrupt.  They are stored in a seperate module because memory\t*\n * around these functions must be locked or they will cause a read to\t\t*\n * be generated while in an interrupt.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Simple_Copy -- Copyies 1 or 2 source chuncks to a dest                *\n *   Sample_Copy -- Copies sound data from source format to raw format.    *\n *   DigiCallback -- Low level double buffering handler.                   *\n *   save_my_regs -- Inline function which will save assembly regs         *\n *   restore_my_regs -- Inline function which will restore saved registes  *\n *   Audio_Add_Long_To_Pointer -- Adds an offset to a ptr casted void      *\n *   Init_Locked_Data -- Initializes sound driver locked data              *\n *   Audio_Mem_Set -- Quick see routine to set memory to a value           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n#pragma pack(4)\n#define WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#include\t<windows.h>\n#include\t<windowsx.h>\n#include\t\"dsound.h\"\n#include\t<wwstd.h>\n#include \"soundint.h\"\n#include \"memflag.h\"\n#include \"audio.h\"\n\nextern\tDebugBuffer[];\n\n/***************************************************************************\n** All routines past this point must be locked for the sound driver to\t  **\n** function under a VCPI memory manager.  These locks are unnecessary if  **\n** the driver does not have to run under windows or does not use virtual  **\n** memory.                                                                **\n***************************************************************************/\n\n\n\n/***************************************************************************\n * SIMPLE_COPY -- Copyies 1 or 2 source chuncks to a dest                  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nlong Simple_Copy(void ** source, long * ssize, void ** alternate, long * altsize, void **dest, long size)\n{\n\n\n\tlong\tout = 0;\t\t// Number of bytes copied to the destination.\n\n\t/*\n\t**\tIt could happen that entering this routine, the source buffer\n\t**\thas been exhausted, but the alternate buffer is still valid.\n\t**\tMove the alternate into the primary position before proceeding.\n\t*/\n\tif (!(*ssize)) {\n\t\t*source = *alternate;\n\t\t*ssize = *altsize;\n\t\t*alternate = NULL;\n\t\t*altsize = 0;\n\t}\n\n\tif (*source && *ssize) {\n\t\tlong\ts;\t\t\t\t// Scratch length var.\n\n\t\t/*\n\t\t**\tCopy as much as possible from the primary source, but no\n\t\t**\tmore than the primary source has to offer.\n\t\t*/\n\t\ts = size;\n\t\tif (*ssize < s) s = *ssize;\n\t\tMem_Copy(*source, *dest, s);\n\t\t*source = Audio_Add_Long_To_Pointer(*source, s);\n\t\t*ssize -= s;\n\t\t*dest = Audio_Add_Long_To_Pointer(*dest, s);\n\t\tsize -= s;\n\t\tout += s;\n\n\t\t/*\n\t\t**\tIf the primary source was insufficient to fill the request, then\n\t\t**\tmove the alternate into the primary position and try again.\n\t\t*/\n\t\tif (size) {\n\t\t\t*source = *alternate;\n\t\t\t*ssize = *altsize;\n\t\t\t*alternate = 0;\n\t\t\t*altsize = 0;\n\t\t\tout += Simple_Copy(source, ssize, alternate, altsize, dest, size);\n\t\t}\n\t}\n\n\treturn(out);\n}\n\n/***********************************************************************************************\n * Sample_Copy -- Copies sound data from source format to raw format.                          *\n *                                                                                             *\n *    This routine is used to copy the sound data (possibly compressed) to the destination     *\n *    buffer in raw format.                                                                    *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the source data (possibly compressed).                      *\n *                                                                                             *\n *          dest     -- Pointer to the destination buffer.                                     *\n *                                                                                             *\n *          size     -- The size of the destination buffer.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes placed into the output buffer.  This is usually   *\n *          the number of bytes requested except in the case when the source is exhausted.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/03/1994 JLB : Created.                                                                 *\n *   09/04/1994 JLB : Revamped entirely.                                                       *\n *=============================================================================================*/\n#pragma argsused\nlong Sample_Copy(SampleTrackerType *st, void ** source, long * ssize, void ** alternate, long * altsize, void * dest, long size, SCompressType scomp, void * , short int *)\n{\n\n\tlong\ts;\n\tlong\tdatasize = 0;\t\t// Output bytes.\n\n\tswitch (scomp) {\n\t\tdefault:\n\n\t\tcase SCOMP_NONE:\n\t\t\tdatasize = Simple_Copy(source, ssize, alternate, altsize, &dest, size);\n\t\t\tbreak;\n\n\t\tcase SCOMP_WESTWOOD:\n\t\tcase SCOMP_SOS:\n\t\t\twhile (size > 0) {\n\n\t\t\t\t/*\n\t\t\t\t**\tThe block spans two buffers.  It must be copied down to\n\t\t\t\t**\ta staging area before it can be decompressed.\n\t\t\t\t*/\n\t\t\t\t{\n\t\t\t\t\tlong magic;\n\t\t\t\t\tunsigned short fsize;\n\t\t\t\t\tunsigned short dsize;\n\t\t\t\t\tvoid *fptr;\n\t\t\t\t\tvoid *dptr;\n\t\t\t\t\tvoid *mptr;\n\n\t\t\t\t\tfptr = &fsize;\n\t\t\t\t\tdptr = &dsize;\n\t\t\t\t\tmptr = &magic;\n\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &fptr, sizeof(fsize));\n\t\t\t\t\tif (s < sizeof(fsize)) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &dptr, sizeof(dsize));\n\t\t\t\t\tif (s < sizeof(dsize) || size < dsize) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &mptr, sizeof(magic));\n\t\t\t\t\tif (s < sizeof(magic) || magic != LockedData.MagicNumber) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the frame and uncompressed data size are identical, then this\n\t\t\t\t\t**\tindicates that the frame is not compressed.  Just copy it directly\n\t\t\t\t\t**\tto the destination buffer in this case.\n\t\t\t\t\t*/\n\t\t\t\t\tif (fsize == dsize) {\n\t\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &dest, fsize);\n\t\t\t\t\t\tif (s < dsize) {\n\t\t\t\t\t\t\treturn (datasize);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tThe frame was compressed, so copy it to the staging buffer, and then\n\t\t\t\t\t\t**\tuncompress it into the final destination buffer.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tfptr = LockedData.UncompBuffer;\n\t\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &fptr, fsize);\n\t\t\t\t\t\tif (s < fsize) {\n\t\t\t\t\t\t\treturn (datasize);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (scomp == SCOMP_WESTWOOD) {\n\t\t\t\t\t\t\tDecompress_Frame(LockedData.UncompBuffer, dest, dsize);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tst->sosinfo.lpSource = (char *)LockedData.UncompBuffer;\n\t\t\t\t\t\t\tst->sosinfo.lpDest\t = (char *)dest;\n\t\t\t\t\t\t\tif (st->sosinfo.wBitSize==16 && st->sosinfo.wChannels==1){\n\t\t\t\t\t\t\t\tsosCODECDecompressData(&st->sosinfo, dsize);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tGeneral_sosCODECDecompressData(&st->sosinfo, dsize);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdest = Audio_Add_Long_To_Pointer(dest, dsize);\n\t\t\t\t\t}\n\t\t\t\t\tdatasize += dsize;\n\t\t\t\t\tsize -= dsize;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak;\n\t}\n\treturn(datasize);\n}\n\n\n\n\n\n\nextern int Convert_HMI_To_Direct_Sound_Volume(int volume);\n\n/***********************************************************************************************\n * maintenance_callback -- routine to service the direct play secondary buffers                *\n *                         and other stuff..?                                                  *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *     ....Unknown                                                                             *\n *    10/17/95 10:15PM ST : tidied up a tad for direct sound                                   *\n *=============================================================================================*/\nVOID far __cdecl maintenance_callback(VOID)\n{\n\n\tint\t\t\t\t\tindex;\t\t\t\t//index used in for loop\n\tSampleTrackerType\t*st;\t\t\t\t\t//ptr to SampleTracker structure\n\tDWORD\t\t\t\t\tplay_cursor;\t\t//Position that direct sound is reading from\n\tDWORD\t\t\t\t\twrite_cursor;\t\t//Position in buffer that we can write to\n\tint\t\t\t \t\tbytes_copied;\t\t//Number of bytes copied into the buffer\n\tBOOL\t\t\t\t\twrite_more;\t\t\t//Flag to set if we need to write more into the buffer\n\tLPVOID\t\t\t\tplay_buffer_ptr;\t//Beginning of locked area of buffer\n\tLPVOID\t\t\t\tdummy_buffer_ptr;\t//Length of locked area in buffer\n\tDWORD\t\t\t\t\tlock_length1;\t\t//Beginning of second locked area in buffer\n\tDWORD\t\t\t\t\tlock_length2;\t\t//Length of second locked area in buffer\n\tHRESULT\t\t\t\treturn_code;\n\n\t//EnterCriticalSection(&GlobalAudioCriticalSection);\n\n\tst = &LockedData.SampleTracker[0];\n\tfor (index = 0; index < MAX_SFX; index++) {\n\n\t\tif (st->Active) {\n\n\t\t\t/*\n\t\t\t**\tGeneral service routine to handle moving small blocks from the\n\t\t\t**\tsource into the direct sound buffers.  If the source is\n\t\t\t**\tcompressed, then this will also uncompress it as the copy\n\t\t\t**\tis performed.\n\t\t\t*/\n\t\t\tif (st->Service && !st->DontTouch ) {\n\n\t\t\t\t//EnterCriticalSection (&st->AudioCriticalSection);\n\n\t\t\t\tst->DontTouch = TRUE;\n\n\t\t\t\t/*\n\t\t\t\t** Get the current position of the direct sound play cursor within the buffer\n\t\t\t\t*/\n\t\t\t\treturn_code = st->PlayBuffer->GetCurrentPosition ( &play_cursor , &write_cursor );\n\n\t\t\t\t/*\n\t\t\t\t** Check for unusual situations like a focus loss\n\t\t\t\t*/\n\t\t\t\tif (return_code != DS_OK){\n\t\t\t\t\tif (return_code == DSERR_BUFFERLOST){\n\t\t\t\t\t\tif (Audio_Focus_Loss_Function){\n\t\t\t\t\t\t\tAudio_Focus_Loss_Function();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\t\t//LeaveCriticalSection (&st->AudioCriticalSection);\n\t\t\t\t\treturn;\t\t//Our app has lost focus or something else nasty has happened\n\t\t\t\t}\t\t\t\t\t//so dont update the sound buffers\n\n\n\t\t\t\tif (st->MoreSource){\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If the direct sound read pointer is less than a quarter\n\t\t\t\t\t** of a buffer away from the end of the data then copy some\n\t\t\t\t\t** more.\n\t\t\t\t \t*/\n\t\t\t\t\twrite_more = FALSE;\n\n\t\t\t\t\tif ( play_cursor < (unsigned)st->DestPtr ){\n\t\t\t\t\t\tif ( (unsigned)st->DestPtr - (unsigned)play_cursor <= SECONDARY_BUFFER_SIZE/4 ){\n\t\t\t\t\t\t\twrite_more=TRUE;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t/* The only time that play_cursor can be greater than DestPtr is\n\t\t\t\t\t\t** if we wrote right to the end of the buffer last time and DestPtr\n\t\t\t\t\t\t** looped back to the beginning of the buffer.\n\t\t\t\t\t\t** That being the case, all we have to do is see if play_cursor is\n\t\t\t\t\t\t** within the last 25% of the buffer\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif ( ( (int)play_cursor > SECONDARY_BUFFER_SIZE*3/4) &&st->DestPtr==0 ){\n\t\t\t\t\t\t\twrite_more=TRUE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (write_more){\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Lock a 1/2 of the direct sound buffer so we can write to it\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif ( DS_OK== st->PlayBuffer->Lock (\t(DWORD)st->DestPtr ,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(DWORD)SECONDARY_BUFFER_SIZE/2,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&play_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&lock_length1,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&dummy_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&lock_length2,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t0 )){\n\n\t\t\t\t\t\t\tbytes_copied = Sample_Copy(\tst,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Source,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Remainder,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->QueueBuffer,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->QueueSize,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tplay_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tSECONDARY_BUFFER_SIZE/4,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tst->Compression,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Trailer[0],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->TrailerLen);\n\n\n\t\t\t\t\t\t\tif ( bytes_copied != (SECONDARY_BUFFER_SIZE/4) ){\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** We must have reached the end of the sample\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tst->MoreSource=FALSE;\n\t\t\t\t\t\t\t\tmemset (((char*)play_buffer_ptr)+bytes_copied ,\n\t\t\t\t\t\t\t\t\t\t0 ,\n\t\t\t\t\t\t\t\t\t\t(SECONDARY_BUFFER_SIZE/4)-bytes_copied);\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** Clear out an extra area in the buffer ahead of the play cursor\n\t\t\t\t\t\t\t\t** to give us a quiet period of grace in which to stop the buffer playing\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tif ( (unsigned)st->DestPtr == SECONDARY_BUFFER_SIZE*3/4 ){\n\t\t\t\t\t\t\t\t\tif ( dummy_buffer_ptr && lock_length2 ){\n\t\t\t\t\t\t\t\t\t\tmemset (dummy_buffer_ptr , 0 , lock_length2);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tmemset ((char*)play_buffer_ptr+SECONDARY_BUFFER_SIZE/4 , 0 , SECONDARY_BUFFER_SIZE/4);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**  Update our pointer into the direct sound buffer\n\t\t\t\t\t\t\t**\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tst->DestPtr = Audio_Add_Long_To_Pointer (st->DestPtr,bytes_copied);\n\n\t\t\t\t\t\t\tif ( (unsigned)st->DestPtr >= (unsigned)SECONDARY_BUFFER_SIZE ){\n\t\t\t\t\t\t\t\tst->DestPtr = Audio_Add_Long_To_Pointer (st->DestPtr,(long)-SECONDARY_BUFFER_SIZE);\n\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Unlock the direct sound buffer\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tst->PlayBuffer->Unlock(\tplay_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\t\tlock_length1,\n\t\t\t\t\t\t\t\t\t\t\t\t\tdummy_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\t\tlock_length2);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\t\t\t\t//write_more\n\n\t\t\t\t} else {\t\t\t//!more_source\n\n\t\t\t\t\t/*\n\t\t\t\t\t** no more source to write - check if the buffer play\n\t\t\t\t\t** has overrun the end of the sample and stop it if it has\n\t\t\t\t\t*/\n\t\t\t\t\tif ( ( (play_cursor >= (unsigned)st->DestPtr) && ( ((unsigned)play_cursor - (unsigned)st->DestPtr) <SECONDARY_BUFFER_SIZE/4) ) ||\n\t\t\t\t\t\t(!st->OneShot &&( (play_cursor < (unsigned)st->DestPtr) && ( ((unsigned)st->DestPtr - (unsigned)play_cursor) >(SECONDARY_BUFFER_SIZE*3/4) ) ))\t ){\n\t\t\t\t\t\t\tst->PlayBuffer->Stop();\n\t\t\t\t\t\t\tst->Service = FALSE;\n\t\t\t\t\t\t\tStop_Sample( index );\n\t\t\t\t\t}\n\t\t\t\t}\t\t\t\t\t//more_source\n\n\t\t\t\tst->DontTouch = FALSE;\n\n\t\t\t\t//LeaveCriticalSection (&st->AudioCriticalSection);\n\t\t\t}\n\t\t\t/*\n\t\t\t**\tFor file streamed samples, fill the queue pointer if needed.\n\t\t\t**\tThis allows for delays in calling the Sound_Callback function.\n\t\t\t*/\n\t\t\tif (!st->DontTouch && !st->QueueBuffer && st->FilePending) {\n\t\t\t\tst->QueueBuffer = Audio_Add_Long_To_Pointer(st->FileBuffer, (long)(st->Odd%LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t\t\t\tst->FilePending--;\n\t\t\t\tst->Odd++;\n\t\t\t\tif (!st->FilePending) {\n\t\t\t\t\tst->QueueSize = st->FilePendingSize;\n\t\t\t\t} else {\n\t\t\t\t\tst->QueueSize = LockedData.StreamBufferSize;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tAdvance to the next sample control structure.\n\t\t*/\n\t\tst++;\n\t}\n\n\n\tif (!LockedData._int) {\n\n\t\tLockedData._int++;\n\t\tst = &LockedData.SampleTracker[0];\n\t\tfor (index = 0; index < MAX_SFX; index++) {\n\n\t\t\t/*\n\t\t\t**\tIf there are any samples that require fading, then do so at this\n\t\t\t**\ttime.\n\t\t\t*/\n\t\t\tif (st->Active && st->Reducer && st->Volume) {\n\t\t\t\t//EnterCriticalSection (&st->AudioCriticalSection);\n\t\t\t\tif (st->Reducer >= st->Volume) {\n\t\t\t\t\tst->Volume = 0;\n\t\t\t\t} else {\n\t\t\t\t\tst->Volume -= st->Reducer;\n\t\t\t\t}\n\n\t\t\t\t//st->PlayBuffer->SetVolume (-( ( (32768-st->Volume)*1000) >>15 ) );\n\n\t\t\t\tif (st->IsScore){\n\t\t\t\t\tst->PlayBuffer->SetVolume ( Convert_HMI_To_Direct_Sound_Volume( ( LockedData.ScoreVolume*(st->Volume >>7))/256) );\n\t\t\t\t}else{\n\t\t\t\t\tst->PlayBuffer->SetVolume ( Convert_HMI_To_Direct_Sound_Volume( ( LockedData.SoundVolume*(st->Volume >>7))/256) );\n\t\t\t\t}\n\n\t\t\t\t//LeaveCriticalSection (&st->AudioCriticalSection);\n\t\t\t}\n\t\t\tst++;\n\t\t}\n\t\tLockedData._int--;\n\t}\n\n\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n}\n\n\n\n\n\n\n\n/***************************************************************************\n * ADD_LONG_TO_POINTER -- Adds an offset to a ptr casted void              *\n *                                                                         *\n * INPUT:\t\tvoid * ptr - the pointer to add to                            *\n *\t\t\t\t\tlong size  - the size to add to it\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:     void * ptr - the new location it will point to              *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n\nvoid *Audio_Add_Long_To_Pointer(void const *ptr, long size)\n{\n\treturn ((void *) ( (char const *) ptr + size));\n}\n\n/***************************************************************************\n * AUDIO_MEM_SET -- Quick see routine to set memory to a value             *\n *                                                                         *\n * INPUT:\t\tvoid const *  - the memory that needs to be set               *\n *\t\t\t\t\tunsigned char - the value to set the memory to\t\t\t\t  *\n *\t\t\t\t\tlong size     - how big an area to set\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:\t\tnone                                                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/28/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid Audio_Mem_Set(void const *ptr, unsigned char value, long size)\n{\n\tunsigned char *temp = (unsigned char *)ptr;\n\tfor (int lp = 0; lp < size; lp ++) {\n\t\t*temp++ = value;\n\t}\n}\n"
  },
  {
    "path": "WIN32LIB/AUDIO/SOUNDINT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDINT.H                               *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 23, 1995   [PWG]                    *\n *                                                                         *\n * This file is the include file for the Westwood Sound Sytem defines and  *\n * routines that are handled in an interrupt.\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"sound.h\"\n\n/*\n** Defines for true and false.  These are included because we do not allow\n** the sound int to include any of the westwood standard headers.  If we\n** did, there might be too much temptation to call another library function.\n** this would be bad, because then that function would not be locked.\n*/\n#define\tFALSE\t\t0\n#define\tTRUE\t\t1\n\n/*\n** Define the different type of sound compression avaliable to the westwood\n** library.\n*/\ntypedef enum {\n\tSCOMP_NONE=0,\t\t\t// No compression -- raw data.\n\tSCOMP_WESTWOOD=1,\t\t// Special sliding window delta compression.\n\tSCOMP_SONARC=33,\t\t// Sonarc frame compression.\n\tSCOMP_SOS=99\t\t\t// SOS frame compression.\n} SCompressType;\n\n/*\n**\tThis is the safety overrun margin for the sonarc compressed\n** data frames.  This value should be equal the maximum 'order' times\n**\tthe maximum number of bytes per sample.  It should be evenly divisible\n**\tby 16 to aid paragraph alignment.\n*/\n#define\tSONARC_MARGIN\t\t\t\t32\n\n\n/*\n** Define the sample control structure which helps us to handle feeding\n** data to the sound interrupt.\n*/\n#pragma pack(1);\ntypedef struct {\n\t/*\n\t**\tThis flags whether this sample structure is active or not.\n\t*/\n\tunsigned Active;\n\t//unsigned Active:1;\n\n\t/*\n\t**\tThis flags whether the sample is loading or has been started.\n\t*/\n\t//unsigned Loading:1;\n\tunsigned Loading;\n\n\t/*\n\t**\tThis semaphore ensures that simultaneous update of this structure won't\n\t**\toccur.  This is necessary since both interrupt and regular code can modify\n\t**\tthis structure.\n\t*/\n\t//unsigned DontTouch:1;\n\tunsigned DontTouch;\n\n\t/*\n\t**\tIf this sample is really to be considered a score rather than\n\t**\ta sound effect, then special rules apply.  These largely fall into\n\t**\tthe area of volume control.\n\t*/\n\t//unsigned IsScore:1;\n\tunsigned IsScore;\n\n\t/*\n\t**\tThis is the original sample pointer. It is used to control the sample based on\n\t**\tpointer rather than handle. The handle method is necessary when more than one\n\t**\tsample could be playing simultaneously. The pointer method is necessary when\n\t**\tthe dealing with a sample that may have stopped behind the programmer's back and\n\t**\tthis occurance is not otherwise determinable.  It is also used in\n\t** conjunction with original size to unlock a sample which has been DPMI\n\t** locked.\n\t*/\n\tvoid const *Original;\n\tlong OriginalSize;\n\n\t/*\n\t**\tThese are pointers to the double buffers.\n\t*/\n\tLPDIRECTSOUNDBUFFER PlayBuffer;\n\n\t/*\n\t** Variable to keep track of the playback rate of this buffer\n\t*/\n\tint\tPlaybackRate;\n\n\t/*\n\t** Variable to keep track of the sample type ( 8 or 16 bit ) of this buffer\n\t*/\n\tint\tBitSize;\n\n\t/*\n\t** Variable to keep track of the stereo ability of this buffer\n\t*/\n\tint\tStereo;\n\n\t/*\n\t**\tThe number of bytes in the buffer that has been filled but is not\n\t**\tyet playing.  This value is normally the size of the buffer,\n\t**\texcept for the case of the last bit of the sample.\n\t*/\n\tLONG DataLength;\n\n\t/*\n\t**\tThis is the buffer index for the low buffer that\n\t**\thas been filled with data but not yet being\n\t**\tplayed.\n\t*/\n//\tshort int Index;\n\n\t/*\n\t**\tPointer into the play buffer for writing the next\n\t**  chunk of sample to\n\t**\n\t*/\n\tVOID *DestPtr;\n\n\t/*\n\t**\tThis flag indicates that there is more source data\n\t**  to copy to the play buffer\n\t**\n\t*/\n\tBOOL MoreSource;\n\n\t/*\n\t**\tThis flag indicates that the entire sample fitted inside the\n\t** direct sound secondary buffer\n\t**\n\t*/\n\tBOOL OneShot;\n\n\t/*\n\t**\tPointer to the sound data that has not yet been copied\n\t**\tto the playback buffers.\n\t*/\n\tVOID *Source;\n\n\t/*\n\t**\tThis is the number of bytes remaining in the source data as\n\t**\tpointed to by the \"Source\" element.\n\t*/\n\tLONG Remainder;\n\n\t/*\n\t**\tObject to use with Enter/LeaveCriticalSection\n\t**\n\t*/\n\tCRITICAL_SECTION AudioCriticalSection;\n\n\t/*\n\t**\tSamples maintain a priority which is used to determine\n\t**\twhich sounds live or die when the maximum number of\n\t**\tsounds are being played.\n\t*/\n\tint Priority;\n\n\t/*\n\t**\tThis is the handle as returned by sosDIGIStartSample function.\n\t*/\n\tshort int Handle;\n\n\t/*\n\t**\tThis is the current volume of the sample as it is being played.\n\t*/\n\tint Volume;\n\tint Reducer;\t\t// Amount to reduce volume per tick.\n\n\t/*\n\t**\tThis is the compression that the sound data is using.\n\t*/\n\tSCompressType Compression;\n\tshort int TrailerLen;\t\t\t\t\t\t// Number of trailer bytes in buffer.\n\tBYTE Trailer[SONARC_MARGIN];\t\t// Maximum number of 'order' samples needed.\n\n\n\tDWORD Pitch;\n\tWORD Flags;\n\n\t/*\n\t**\tThis flag indicates whether this sample needs servicing.\n\t**\tServicing entails filling one of the empty low buffers.\n\t*/\n\tshort int Service;\n\n\t/*\n\t**\tThis flag is TRUE when the sample has stopped playing,\n\t**\tBUT there is more data available.  The sample must be\n\t**\trestarted upon filling the low buffer.\n\t*/\n\tBOOL Restart;\n\n\t/*\n\t**\tStreaming control handlers.\n\t*/\n\tBOOL (*Callback)(short int id, short int *odd, VOID **buffer, LONG *size);\n\tVOID\t*QueueBuffer;\t// Pointer to continued sample data.\n\tLONG\tQueueSize;\t\t// Size of queue buffer attached.\n\tshort int\tOdd;\t\t\t\t// Block number tracker (0..StreamBufferCount-1).\n\tint\tFilePending;\t// Number of buffers already filled ahead.\n\tlong\tFilePendingSize;\t// Number of bytes in last filled buffer.\n\n\t/*\n\t**\tThe file variables are used when streaming directly off of the\n\t**\thard drive.\n\t*/\n\tint\tFileHandle;\t\t// Streaming file handle (ERROR = not in use).\n\tVOID\t*FileBuffer;\t// Temporary streaming buffer (allowed to be freed).\n\t/*\n\t** The following structure is used if the sample if compressed using\n\t** the sos 16 bit compression Codec.\n\t*/\n\n\t_SOS_COMPRESS_INFO sosinfo;\n\n\n} SampleTrackerType;\n\n\ntypedef struct LockedData {\n\tunsigned int \t\tDigiHandle; \t\t\t// = -1;\n\tBOOL \t\t\t\t\tServiceSomething;\t\t// = FALSE;\n\tlong \t\t\t\t\tMagicNumber; \t\t\t// = 0xDEAF;\n\tVOID \t\t\t\t\t*UncompBuffer;\t\t\t// = NULL;\n\tlong \t\t\t\t\tStreamBufferSize; \t// = (2*SECONDARY_BUFFER_SIZE)+128;\n\tshort \t\t\t\tStreamBufferCount; \t// = 32;\n\tSampleTrackerType SampleTracker[MAX_SFX];\n\tunsigned int\t\tSoundVolume;\n\tunsigned int\t\tScoreVolume;\n\tBOOL\t\t\t\t\t_int;\n} LockedDataType;\n\nextern LockedDataType LockedData;\n#pragma pack(4);\n\nvoid Init_Locked_Data(void);\nlong Simple_Copy(void ** source, long * ssize, void ** alternate, long * altsize, void **dest, long size);\nlong Sample_Copy(SampleTrackerType *st, void ** source, long * ssize, void ** alternate, long * altsize, void * dest, long size, SCompressType scomp, void * trailer, short int *trailersize);\nVOID far __cdecl maintenance_callback(VOID);\nVOID __cdecl far DigiCallback(unsigned int driverhandle, unsigned int callsource, unsigned int sampleid);\nvoid far HMI_TimerCallback(void);\nvoid *Audio_Add_Long_To_Pointer(void const *ptr, long size);\nvoid\tDPMI_Unlock(VOID const *ptr, long const size);\nextern \"C\" {\n\tvoid __cdecl Audio_Mem_Set(void const *ptr, unsigned char value, long size);\n//\tvoid\tMem_Copy(void *source, void *dest, unsigned long bytes_to_copy);\n\tlong  __cdecl Decompress_Frame(void * source, void * dest, long size);\n\tint\t__cdecl Decompress_Frame_Lock(void);\n\tint\t__cdecl Decompress_Frame_Unlock(void);\n\tint\t__cdecl sosCODEC_Lock(void);\n\tint\t__cdecl sosCODEC_Unlock(void);\n\tvoid\t__GETDS(void);\n}\n"
  },
  {
    "path": "WIN32LIB/AUDIO/SOUNDIO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Id: soundio.cpp 1.41 1994/06/20 15:01:39 joe_bostic Exp $ */\n/***********************************************************************************************\n **             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             **\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Sound Library                                                *\n *                                                                                             *\n *                    File Name : SOUND.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 22, 1991                                                *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Load_Long_Sample -- Loads a sample into XMS for double buffer system.                     *\n *   Read_Long_Sample -- Loads/Processes/Formats/Builds offset.                                             *\n *   Save_Table_Entry -- Put an entry in the offset table.                                     *\n *   Play_Long_Sample -- Calls Init_Long_Sample and Start_Long_Sample.                         *\n *   Start_Long_Sample -- Starts a sample playing that has be initialized.                     *\n *   Get_Table_Entry -- Gets next entry in table.                                              *\n *   Long_Sample_Ticks -- Gets number of ticks in sample if in header.                         *\n *   Long_Sample_Status -- Returns the status of the sample.                                   *\n *   Find_Table_Entry -- Finds next entry in table that matches mask.                          *\n *   Get_Table_Start -- Returns a pointer to first entry in table.                             *\n *   Long_Sample_Ticks_Played -- Number of ticks since sample started.                         *\n *   Install_Sample_Driver_Callback -- Pokes callback function into JM driver                  *\n *   Stop_Long_Sample -- Stops current long sample from playing.                               *\n *   Long_Sample_Loaded_Size -- Max buffer size to load a long sample.                         *\n *   Sound_Callback -- Audio driver callback function.                                         *\n *   DigiCallback -- Low level double buffering handler.                                       *\n *   Load_Sample_Into_Buffer -- Loads a digitized sample into a buffer.                        *\n *   Stream_Sample -- Streams a sample directly from a file.                                   *\n *   Sample_Read -- Reads sample data from an openned file.                                    *\n *   Continue_Sample -- Tags another block of data onto the currently playing.                 *\n *   Sample_Copy -- Copies sound data from source format to raw format.                        *\n *   File_Stream_Preload -- Handles initial proload of a streaming samples bu*\n *   Sample_Length -- returns length of a sample in ticks                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nextern\tvoid Colour_Debug (int call_number);\n#pragma \tpack(4)\n\n#define WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n\n#include\t<windows.h>\n#include\t<windowsx.h>\n#include\t\"dsound.h\"\n\n#include\t<mem.h>\n#include\t<wwmem.h>\n#include\t\"soundint.h\"\n#include\t<stdio.h>\n#include\t<string.h>\n#include\t<direct.h>\n#include\t<stdlib.h>\n#include <process.h>\n#include\t<keyboard.h>\n#include\t<file.h>\n#include\t<bios.h>\n#include\t<timer.h>\n#include\t<math.h>\n#pragma\t\tpack(1)\n#include\t\"audio.h\"\n#pragma\t\tpack(4)\n\nLPDIRECTSOUNDBUFFER\tDumpBuffer;\nHANDLE\t\t\t\t\t\tSoundThreadHandle = NULL;\nBOOL\t\t\t\t\t\tSoundThreadActive = FALSE;\n\n/*\n**      If this is defined, then the streaming audio buffer will be filled\n**      to maximum whenever filling is to occur. If undefined, it will fill\n**      the streaming buffer in smaller chunks.\n*/\n#define SIMPLE_FILLING\n\n/*\n**      This is the number of times per sec that the maintenance callback gets called.\n*/\n#define MAINTENANCE_RATE                        40\t//30 times per sec plus a safety margin\n\n/*\n**      Size of the temporary buffer in XMS/EMS that direct file\n**      streaming of sounds will allocate.\n*/\n//#define STREAM_BUFFER_SIZE              (128L*1024L)\n#define STREAM_BUFFER_SIZE              (128L*1024L)\n\n/*\n** Define the number of \"StreamBufferSize\" blocks that are read in\n** at a minimum when the streaming sample load callback routine\n** is called.  We will IGNORE loads that are less that this in order\n** to avoid constant seeking on the CD.\n*/\n#define STREAM_CUSHION_BLOCKS   4\n\n\n/*\n**      This is the maximum size that a sonarc block can be.  All sonarc blocks\n**      must be either a multiple of this value or a binary root of this value.\n*/\n#define LARGEST_SONARC_BLOCK            2048\n\n\n//////////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////// structs ///////////////////////////////////////\n\n//void\t\t\t\t\t\t*DigiBuffer = NULL;\nstatic BOOL\t\t\t\tStartingFileStream = FALSE;\nint\t\t\t\t\t\tStreamLowImpact = FALSE;\nMemoryFlagType\t\t\tStreamBufferFlag = MEM_NORMAL;\nint\t\t\t\t\t\t\tMisc;\nSFX_Type\t\t\t\t\tSoundType;\nSample_Type\t\t\t\tSampleType;\nint\t\t\t\t\t\t\tReverseChannels = FALSE;\nLPDIRECTSOUND\t\t\tSoundObject;\t\t\t//Direct sound object\nLPDIRECTSOUNDBUFFER\tPrimaryBufferPtr;\t\t//Pointer to the  buffer that the\nunsigned\t\t\t\t\tSoundTimerHandle=0;\t//Windows Handle for sound timer\nWAVEFORMATEX\t\t\t\tDsBuffFormat;\t\t\t//format of direct sound buffer\nDSBUFFERDESC\t\t\t\tBufferDesc;\t\t\t\t//Buffer description for creating buffers\nWAVEFORMATEX\t\t\t\tPrimaryBuffFormat;\t//Copy of format of direct sound primary buffer\nDSBUFFERDESC\t\t\t\tPrimaryBufferDesc;\t//Copy of buffer description for re-creating primary buffer\nCRITICAL_SECTION\t\tGlobalAudioCriticalSection;\nvoid\t\t\t\t\t\t*FileStreamBuffer = NULL;\t//Buffer for streaming audio from CD\n/*\n** Function to call if we detect focus loss\n*/\nextern\tvoid (*Audio_Focus_Loss_Function)(void) = NULL;\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nstatic BOOL File_Callback(short id, short *odd, void **buffer, long *size);\nstatic int __cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback)(short id, short *odd, void **buffer, long *size), int volume, int handle);\nvoid CALLBACK Sound_Timer_Callback ( UINT, UINT, DWORD, DWORD, DWORD );\n//static int __cdecl Stream_Sample(void *buffer, long size, BOOL (*callback)(short id, short *odd, void **buffer, long *size));\nvoid Sound_Thread (void *);\nvolatile BOOL AudioDone;\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n// This callback is called whenever the queue buffer playback has begun\n// and another buffer is needed for queuing up.  Returns TRUE if there\n// is more data to read from the file.\nstatic BOOL File_Callback(short id, short *odd, void **buffer, long *size)\n{\n\tSampleTrackerType       *st;            // Pointer to sample playback control struct.\n\tvoid                    *ptr;           // Pointer to working portion of file buffer.\n\n\tif (id != -1) {\n\t\tst = &LockedData.SampleTracker[id];\n\t \tptr = st->FileBuffer;\n\t \tif (ptr) {\n\n\t \t  \t/*\n\t \t  \t** Move the next pending block into the primary\n\t \t  \t** position.  Do this only if the queue pointer is\n\t \t  \t** null.\n\t \t  \t*/\n\t\t\tif (!AudioDone){\n\t\t\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t}\n\n\t\t\tst->DontTouch = TRUE;\n\n\t\t\tif (!AudioDone){\n\t\t\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t}\n\n\t\t\tif (!*buffer && st->FilePending) {\n\t \t  \t\t*buffer = Add_Long_To_Pointer(ptr, (long)(*odd % LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t \t  \t\tst->FilePending--;\n\t \t  \t\t*odd = (short)(*odd + 1);\n\t \t  \t\tif (!st->FilePending) {\n\t \t  \t\t\t*size = st->FilePendingSize;\n\t \t  \t\t} else {\n\t \t  \t\t\t*size = LockedData.StreamBufferSize;\n\t \t  \t\t}\n\t \t  \t}\n\t\t\tif (!AudioDone){\n\t\t\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t}\n\t \t  \tst->DontTouch = FALSE;\n\t\t\tif (!AudioDone){\n\t\t\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t}\n\t\t\tSound_Timer_Callback(0,0,0,0,0);\t//Shouldnt block as we are calling it from the same thread\n\n\t \t  \t/*\n\t \t  \t** If the file handle is still valid, then read in the next\n\t \t  \t** block and add it to the next pending slot available.\n\t \t  \t*/\n\t \t  \tif (st->FilePending <\n\t \t  \t\t(StreamLowImpact ? (LockedData.StreamBufferCount>>1) : ((LockedData.StreamBufferCount-3))) && st->FileHandle != WW_ERROR) {\n\n\n\t \t  \t\tint num_empty_buffers;\n\n#ifdef SIMPLE_FILLING\n\t\t\t\tnum_empty_buffers = (LockedData.StreamBufferCount-2) - st->FilePending;\n#else\n\n\t\t\t\t//\n\t\t\t\t// num_empty_buffers will be from 1 to StreamBufferCount\n\t\t\t\t//\n\t\t\t\tif (StreamLowImpact) {\n\t\t\t\t\tnum_empty_buffers = MIN((LockedData.StreamBufferCount >> 1)+STREAM_CUSHION_BLOCKS, (LockedData.StreamBufferCount - 2) - st->FilePending);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tnum_empty_buffers = (LockedData.StreamBufferCount - 2) - st->FilePending;\n\t\t\t\t}\n#endif\n\n\t\t\t\twhile (num_empty_buffers && (st->FileHandle != WW_ERROR)) {\n\t\t\t\t\tint     tofill;\n\t\t\t\t\tlong    psize;\n\n\t\t\t\t\ttofill = (*odd + st->FilePending) % LockedData.StreamBufferCount;\n\n\t\t\t\t\tptr = Add_Long_To_Pointer(st->FileBuffer, (long)tofill * (long)LockedData.StreamBufferSize);\n\t\t\t\t\tpsize = Read_File(st->FileHandle, ptr, LockedData.StreamBufferSize);\n\n\t\t\t\t \t/*\n\t\t\t\t \t**      If less than the requested amount of data was read, this\n\t\t\t\t \t**      indicates that the source file is exhausted.  Flag the source\n\t\t\t\t \t**      file as closed so that no further reading is attempted.\n\t\t\t\t \t*/\n\t\t\t\t \tif (psize != LockedData.StreamBufferSize) {\n\t\t\t\t \t\tClose_File(st->FileHandle);\n\t\t\t\t\t\tst->FileHandle = WW_ERROR;\n\t\t\t\t \t}\n\n                /*\n\t\t\t\t \t**      If any real data went into the pending buffer, then flag\n\t\t\t\t \t**      that this buffer is valid.\n                */\n\t\t\t\t \tif (psize) {\n\t\t\t\t\t\tif (!AudioDone){\n\t\t\t\t\t\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tst->DontTouch = TRUE;\n\t\t\t\t \t  \tst->FilePendingSize = psize;\n\t\t\t\t \t  \tst->FilePending++;\n\t\t\t\t \t  \tst->DontTouch = FALSE;\n\t\t\t\t\t\tif (!AudioDone){\n\t\t\t\t\t\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSound_Timer_Callback(0,0,0,0,0);\t//Shouldnt block as we are calling it from the same thread\n\t\t\t\t \t}\n\t\t\t\t \tnum_empty_buffers--;\n\t\t\t\t}\n\n\t\t\t\t/*\n             **  After filling all pending buffers, check to see if the queue buffer\n\t\t\t\t**  is empty.  If so, then assign the first available pending buffer to the\n             **  queue.\n\t\t\t\t*/\n\t\t\t\tif (!AudioDone){\n\t\t\t\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\t}\n\t\t\t\tst->DontTouch = TRUE;\n             if (!st->QueueBuffer && st->FilePending) {\n\t\t\t\t\tst->QueueBuffer = Add_Long_To_Pointer(st->FileBuffer, (long)(st->Odd%LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t\t\t\t\tst->FilePending--;\n                st->Odd++;\n                if (!st->FilePending) {\n\t\t\t\t\t\tst->QueueSize = st->FilePendingSize;\n\t\t\t\t\t} else {\n                \tst->QueueSize = LockedData.StreamBufferSize;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tst->DontTouch = FALSE;\n\t\t\t\tif (!AudioDone){\n\t\t\t\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\t}\n\t\t\t\tSound_Timer_Callback(0,0,0,0,0);\t//Shouldnt block as we are calling it from the same thread\n\t\t\t}\n\n\t\t\t/*\n          **      If there are no more buffers that the callback routine\n\t\t\t**      can slot into the primary position, then signal that\n\t\t\t**      no furthur callbacks are needed.\n\t\t\t*/\n\t\t\tif (st->FilePending) {\n\t\t\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\treturn(TRUE);\n\t\t\t}\n\t\t}\n\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\n\t}\n  return(FALSE);\n}\n\n\n\n\n\n// Generic streaming sample playback initialization.\nstatic int __cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback)(short id, short *odd, void **buffer, long *size), int volume, int handle)\n{\n\tint\t\t\t\t\t\t\t\tplayid=-1;      // Sample play ID.\n\tSampleTrackerType               *st;                    // Working pointer to sample control structure.\n\tlong\t\t\t\t\t\t\toldsize;                // Copy of original sound size.\n\tAUDHeaderType                   header;\n\n\tif (!AudioDone && buffer && size && LockedData.DigiHandle != -1) {\n\n\t\t/*\n\t \t** Start the first section of the sound playing.\n\t \t*/\n\t \tMem_Copy(buffer, &header, sizeof(header));\n\t \toldsize = header.Size;\n\t \theader.Size = size-sizeof(header);\n\t \tMem_Copy(&header, buffer, sizeof(header));\n\t \tplayid = Play_Sample_Handle(buffer, 0xFF, volume, 0x0, handle);\n\t \theader.Size = oldsize;\n\t \tMem_Copy(&header, buffer, sizeof(header));\n\n\t \t/*\n\t \t** If the sample actually started playing, then flag this\n\t \t** sample as a streaming type and signal for a callback\n\t \t** to occur.\n\t \t*/\n\t \tif (playid != -1) {\n\t \t\tst = &LockedData.SampleTracker[playid];\n\n\t \t\tst->Callback = callback;\n\t \t\tst->Odd = 0;\n//             ServiceSomething = TRUE;\n    \t}\n\t}\n\t\t  return (playid);\n}\n\n\n\n#if (0)\nstatic int __cdecl Stream_Sample(void *buffer, long size, BOOL (*callback)(short id, short *odd, void **buffer, long *size), int handle)\n{\n\treturn Stream_Sample_Vol(buffer, size, callback, 0xFF, handle);\n}\n#endif\n\n\n/***********************************************************************************************\n * File_Stream_Sample -- Streams a sample directly from a file.                                *\n *                                                                                             *\n *    This will take the file specified and play it directly from disk.                        *\n *    It performs this by allocating a temporary buffer in XMS/EMS and                         *\n *    then keeping this buffer filled by the Sound_Callback() routine.                         *\n *                                                                                             *\n * INPUT:   filename -- The name of the file to play.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the handle to the sound -- just like Play_Sample().                        *\n *                                                                                             *\n * WARNINGS:   The temporary buffer is allocated when this routine is                          *\n *             called and then freed when the sound is finished.  Keep                         *\n *             this in mind.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint File_Stream_Sample(char const *filename, BOOL real_time_start)\n{\n\treturn File_Stream_Sample_Vol(filename, 0xFF, real_time_start);\n}\n\n/***************************************************************************\n * FILE_STREAM_PRELOAD -- Handles initial proload of streaming samples     *\n *                                                                         *\n * This function is called before a sample which streams from disk is      *\n * started.  It can be called to either fill the buffer in small chunks    *\n * from the call back routine or to fill the entire buffer at once.  This  *\n * is wholely dependant on whether the Loading bit is set within the       *\n * sample tracker.                                                         *\n *                                                                         *\n * INPUT:LockedData.SampleTracker * to the header which tracks this samples*\n *                                                              processing.*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/05/1995 PWG : Created.                                             *\n *=========================================================================*/\n\nvoid File_Stream_Preload(int handle)\n{\n\tSampleTrackerType\t*st\t\t= &LockedData.SampleTracker[handle];\n\tint\t\t\t\t\tfh\t\t\t= st->FileHandle;\n\tint\t\t\t\t\tmaxnum\t= (LockedData.StreamBufferCount >> 1) + STREAM_CUSHION_BLOCKS;\n\tvoid\t\t\t\t\t*buffer\t= st->FileBuffer;\n\tint\t\t\t\t\tnum;\n\n\t/*\n    ** Figure just how much we need to load.  If we are doing the load in progress\n\t** then we will only load two blocks.\n\t*/\n    if (st->Loading) {\n    \tnum = st->FilePending + 2;\n       num = MIN(num, maxnum);\n    } else {\n\t\tnum = maxnum;\n\t}\n\n\t//EnterCriticalSection(&GlobalAudioCriticalSection);\n\n    /*\n    ** Loop through the blocks and load up the number we need.\n    */\n    for (int index = st->FilePending; index < num; index++) {\n\t\tlong s = Read_File(fh, Add_Long_To_Pointer(buffer, (long)index * (long)LockedData.StreamBufferSize), LockedData.StreamBufferSize);\n       if (s) {\n         \tst->FilePendingSize = s;\n\t  \t\tst->FilePending++;\n\t\t}\n\t\tif (s < LockedData.StreamBufferSize) break;\n    }\n\n\tSound_Timer_Callback(0,0,0,0,0);\t//Shouldnt block as we are calling it from the same thread\n\n\n\t/*\n\t** If the last block was incomplete (ie. it didn't completely fill the buffer) or\n\t** we have now filled up as much of the Streaming Buffer as we need to, then now is\n\t** the time to kick off the sample.\n\t*/\n\tif (st->FilePendingSize < LockedData.StreamBufferSize || index == maxnum) {\n\n\t\t/*\n\t\t** Actually start the sample playing, and don't worry about the file callback\n\t\t** it won't be called for a while.\n\t\t*/\n \t\tint old\t\t\t\t\t\t= LockedData.SoundVolume;\n\t\tint size\t\t\t\t\t\t= (st->FilePending == 1) ? st->FilePendingSize : LockedData.StreamBufferSize;\n\t\tLockedData.SoundVolume\t= LockedData.ScoreVolume;\n\t\tStartingFileStream\t\t= TRUE;\n\n\t\tStream_Sample_Vol(buffer, size, File_Callback, st->Volume, handle);\n\t\tStartingFileStream\t\t= FALSE;\n       LockedData.SoundVolume\t= old;\n\n\t\t/*\n\t\t** The Sample is finished loading (if it was loading in small pieces) so record that\n\t\t** so that it will now use the active logic in the file call back.\n\t\t*/\n\t\tst->Loading\t\t\t\t\t= FALSE;\n\n\t\t/*\n\t\t** Decrement the file pending because the first block is already playing thanks\n\t\t** to the play sample call above.\n\t\t*/\n\t\tst->FilePending--;\n\n\t\t/*\n\t\t** If File pending is now a zero, then we only preloaded one block and there\n\t\t** is nothing more to play.  So clear the sample tracing structure of the\n\t\t** information it no longer needs.\n\t\t*/\n\t\tif (!st->FilePending) {\n\t\t\tst->Odd\t\t\t\t\t= 0;\n          st->QueueBuffer\t\t= 0;\n\t\t\tst->QueueSize\t\t\t= 0;\n\t\t\tst->FilePendingSize\t= 0;\n          st->Callback\t\t\t= NULL;\n\t\t\tClose_File(fh);\n\t\t} else {\n\t\t\t/*\n\t\t\t** The QueueBuffer counts as an already played block so remove it from the total.\n          ** Note: We didn't remove it before because there might not have been one.\n          */\n          st->FilePending--;\n\n          /*\n          ** When we start loading we need to start past the first two blocks.  Why this\n          ** is called Odd, I haven't got the slightest.\n\t\t\t*/\n          st->Odd = 2;\n\n          /*\n          ** If the file pending size is less than the stream buffer, then the last block\n          ** we loaded was the last block period.  So close the file and reset the handle.\n          */\n          if (st->FilePendingSize != LockedData.StreamBufferSize) {\n\t\t\t\tClose_File(fh);\n             st->FileHandle = WW_ERROR;\n          }\n\n          /*\n          ** The Queue buffer needs to point at the next block to be processed.  The size\n          ** of the queue is dependant on how many more blocks there are.\n          */\n\t\t\tst->QueueBuffer = Add_Long_To_Pointer(buffer, LockedData.StreamBufferSize);\n\t\t\tif (!st->FilePending) {\n          \tst->QueueSize = st->FilePendingSize;\n          } else {\n          \tst->QueueSize = LockedData.StreamBufferSize;\n          }\n\t\t}\n\t}\n\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\n}\n\n\n\n\n\n\n\n/***********************************************************************************************\n * File_Stream_Sample_Vol -- Streams a sample directly from a file.                            *\n *                                                                                             *\n *    This will take the file specified and play it directly from disk.                        *\n *    It performs this by allocating a temporary buffer in XMS/EMS and                         *\n *    then keeping this buffer filled by the Sound_Callback() routine.                         *\n *                                                                                             *\n * INPUT:   filename -- The name of the file to play.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the handle to the sound -- just like Play_Sample().                        *\n *                                                                                             *\n * WARNINGS:   The temporary buffer is allocated when this routine is                          *\n *             called and then freed when the sound is finished.  Keep                         *\n *             this in mind.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *=============================================================================================*/\n\nint File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start)\n{\n\tSampleTrackerType       *st;\n\tint     fh;\n\tint     handle = -1;\n\tint     index;\n\n\tif (!AudioDone && LockedData.DigiHandle != -1 && filename && Find_File(filename)) {\n\n\t/*\n\t**  Make sure all sample tracker structures point to the same\n\t**  upper memory buffer.  This allocation only occurs if at\n\t**  least one sample gets \"streamed\".\n\t*/\n\tif (!FileStreamBuffer) {\n\t\tFileStreamBuffer = Alloc(LockedData.StreamBufferSize * LockedData.StreamBufferCount, (MemoryFlagType)(StreamBufferFlag | MEM_TEMP | MEM_LOCK));\n       for (index = 0; index < MAX_SFX; index++) {\n       \tLockedData.SampleTracker[index].FileBuffer = FileStreamBuffer;\n\t\t}\n\t}\n\t/*\n\t** If after trying to allocate the buffer we still fail then\n\t** we can stream this sample.\n\t*/\n\tif (!FileStreamBuffer) return(-1);\n\n\n    \t/*\n    \t** Lets see if we can sucessfully open up the file.  If we can't,\n    \t** then there is no point in going any farther.\n    \t*/\n    \tif ((fh = Open_File(filename, READ)) == -1) {\n \t \t\t\treturn (-1);\n    \t}\n\n\t\t/*\n\t\t** Reserve a handle so that we can fill in the sample tracker\n\t\t** with the needed information.  If we dont get valid handle then\n\t\t** we might as well give up.\n\t\t*/\n\t\tif ((unsigned)(handle = Get_Free_Sample_Handle(0xFF)) >= MAX_SFX) {\n \t\t\t\treturn(-1);\n\t\t}\n\n\t\t/*\n\t\t** Now lets get a pointer to the proper sample handler and start\n\t\t** our manipulations.\n\t\t*/\n\t\tst\t\t\t\t\t\t\t= &LockedData.SampleTracker[handle];\n\t\tst->IsScore\t\t\t\t= TRUE;\n\t\tst->FilePending\t\t= 0;\n\t\tst->FilePendingSize\t= 0;\n\t\tst->Loading\t\t\t\t= real_time_start;\n\t\tst->Volume\t\t\t\t= volume;\n\t\tst->FileHandle\t\t\t= fh;\n\n\t\t/*\n\t\t** Now that we have setup our initial data properly, let load up\n\t\t** the beginning of the sample we intend to stream.\n\t\t*/\n\t\tFile_Stream_Preload(handle);\n\t}\n\n\treturn (handle);\n}\n\n/***********************************************************************************************\n * Sound_Callback -- Audio driver callback function.                                           *\n *                                                                                             *\n *    Maintains the audio buffers.  This routine must be called at least                       *\n *    11 times per second or else audio glitches will occur.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If this routine is not called often enough then audio                           *\n *             glitches will occur.                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid __cdecl Sound_Callback(void)\n{\n\tint\t\t\t\t\tindex;\n    SampleTrackerType\t*st;\n\n    if (!AudioDone && LockedData.DigiHandle != -1) {\n\n\t\t/*\n\t\t** Call the timer callback now as we may block it in this function\n\t\t*/\n\t\tSound_Timer_Callback(0,0,0,0,0);\n\n\t\tst = &LockedData.SampleTracker[0];\n\t\tfor (index = 0; index < MAX_SFX; index++) {\n\t\t\tif (st->Loading) {\n\t\t\t\tFile_Stream_Preload(index);\n\t\t\t} else {\n          \t/*\n          \t**  General service routine to handle moving small blocks from the\n          \t**  source into the low RAM staging buffers.\n          \t*/\n\n\t\t\t\tif (st->Active) {\n\n\t\t\t\t\t/*\n          \t\t**  Special check to see if the sample is a fading one AND\n          \t\t**  it has faded to silence, then stop it here.\n          \t\t*/\n          \t\tif (st->Reducer && !st->Volume) {\n\t\t\t\t\t\t//EnterCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\t\t\tStop_Sample(index);\n\t\t\t\t\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\t\t} else {\n\n          \t\t\t/*\n             \t\t**  Fill the queuebuffer if it is currently empty\n             \t\t**  and there is a callback function defined to fill it.\n             \t\t**\n             \t\t** PWG/CDY & CO: We should be down by at least two blocks\n\t\t\t\t\t\t**                                        before we bother with this\n             \t\t*/\n\n             \t\tif ((!st->QueueBuffer ||\n\t\t\t\t\t\t\t(st->FileHandle != WW_ERROR && st->FilePending < LockedData.StreamBufferCount-3)) &&\n\t\t\t\t \t\t\tst->Callback) {\n\n                \t\tif (!st->Callback((short)index, (short int *)&st->Odd, &st->QueueBuffer, &st->QueueSize)) {\n\t\t\t\t\t\t\t\tst->Callback = NULL;\n                \t\t}\n             \t\t}\n          \t\t}\n\n\t\t\t\t} else {\n\n          \t\t/*\n          \t\t** This catches the case where a streaming sample gets\n          \t\t** aborted prematurely because of failure to call the\n          \t\t** callback function frequently enough.  In this case, the\n          \t\t** sample will be flagged as inactive, but the file handle\n          \t\t** will not have been closed.\n          \t\t*/\n          \t\tif (st->FileHandle != WW_ERROR) {\n\t\t\t\t\t\t//EnterCriticalSection(&GlobalAudioCriticalSection);\n          \t\t\tClose_File(st->FileHandle);\n             \t\tst->FileHandle = WW_ERROR;\n\t\t\t\t\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n          \t\t}\n\t\t\t\t}\n\t\t\t}\n\n          /*\n          **      Advance to the next sample control structure.\n\t\t\t*/\n    \t\tst++;\n\t\t}\n\n    }\n}\n\n\n/***********************************************************************************************\n * Load_Sample -- Loads a digitized sample into RAM.                                           *\n *                                                                                             *\n *    This routine loads a digitized sample into RAM.                                          *\n *                                                                                             *\n * INPUT:   filename -- Name of the sound file to load.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the loaded sound file.  This pointer                     *\n *          is passed to Play_Sample when playback is desired.                                 *\n *                                                                                             *\n * WARNINGS:   If there is insufficient memory to load the sample, then                        *\n *             NULL will be returned.                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *   01/06/1994 JLB : HMI version.                                                             *\n *=============================================================================================*/\nvoid *Load_Sample(char const *filename)\n{\n\tvoid *buffer = NULL;\n\tlong    size;\n\tint     fh;\n\n\tif (LockedData.DigiHandle == -1 || !filename || !Find_File(filename)) {\n\t\treturn (NULL);\n\t}\n\n\tfh = Open_File(filename, READ);\n\tif (fh != WW_ERROR) {\n\t\tsize = File_Size(fh)+sizeof(AUDHeaderType);\n\t\tbuffer = Alloc(size, MEM_NORMAL);\n\n\t\tif (buffer) {\n\t\t\tSample_Read(fh, buffer, size);\n\t\t}\n\t\tClose_File(fh);\n\t\tMisc = size;\n\t}\n\treturn(buffer);\n}\n\n\n/***********************************************************************************************\n * Load_Sample_Into_Buffer -- Loads a digitized sample into a buffer.                          *\n *                                                                                             *\n *    This routine is used to load a digitized sample into a buffer                            *\n *    provided by the programmer.  This buffer can be in XMS or EMS.                           *\n *                                                                                             *\n * INPUT:   filename -- The filename to load.                                                  *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer to load into.                                    *\n *                                                                                             *\n *          size     -- The size of the buffer to load into.                                   *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually used in the buffer.                           *\n *                                                                                             *\n * WARNINGS:   This routine will not overflow the buffer provided.  This                       *\n *             means that the buffer must be big enough to hold the data                       *\n *             or else the sound will be cut short.                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Load_Sample_Into_Buffer(char const *filename, void *buffer, long size)\n{\n\tint     fh;\n\n\t/*\n\t**      Verify legality of parameters.\n\t*/\n\tif (!buffer || !size || LockedData.DigiHandle == -1 || !filename || !Find_File(filename)) {\n\t\treturn (NULL);\n\t}\n\n\tfh = Open_File(filename, READ);\n\tif (fh != WW_ERROR) {\n\t\tsize = Sample_Read(fh, buffer, size);\n       Close_File(fh);\n\t} else {\n\t\treturn(0);\n\t}\n\treturn(size);\n}\n\n\n/***********************************************************************************************\n * Sample_Read -- Reads sample data from an openned file.                                      *\n *                                                                                             *\n *    This routine reads a sample file.  It is presumed that the file is                       *\n *    already positioned at the start of the sample.  From this, it can                        *\n *    determine if it is a VOC or raw data and proceed accordingly.                            *\n *                                                                                             *\n * INPUT:   fh       -- File handle of already openned sample file.                            *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer to load data into.                               *\n *                                                                                             *\n *          size     -- The size of the buffer.                                                *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually used in the buffer.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Sample_Read(int fh, void *buffer, long size)\n{\n\n\tAUDHeaderType\tRawHeader;\n\tvoid    \t\t\t*outbuffer;\t\t\t\t// Pointer to start of raw data.\n\tlong    \t\t\tactual_bytes_read;\t// Actual bytes read in, including header\n\n/*\n** Conversion formula for TCrate and Hz rate.\n**\n** TC = 256 - 1m/rate\n** rate = 1m / (256-TC)\n*/\n\n\tif (!buffer || fh == WW_ERROR || size <= sizeof(RawHeader)) return(NULL);\n\n\tsize -= sizeof(RawHeader);\n\toutbuffer = Add_Long_To_Pointer(buffer, sizeof(RawHeader));\n  \tactual_bytes_read = Read_File(fh, &RawHeader, sizeof(RawHeader));\n\tactual_bytes_read +=Read_File(fh, outbuffer, MIN(size, RawHeader.Size));\n\tMem_Copy(&RawHeader, buffer, sizeof(RawHeader));\n\treturn(actual_bytes_read);\n}\n\n\n/***********************************************************************************************\n * Free_Sample -- Frees a previously loaded digitized sample.                                  *\n *                                                                                             *\n *    Use this routine to free the memory allocated by a previous call to                      *\n *    Load_Sample.                                                                             *\n *                                                                                             *\n * INPUT:   sample   -- Pointer to the sample to be freed.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Free_Sample(void const *sample)\n{\n\tif (sample) Free((void *)sample);\n}\n\n\n\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Sound_Timer_Callback -- windows timer callback for sound maintenance                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:01PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid CALLBACK Sound_Timer_Callback ( UINT, UINT, DWORD, DWORD, DWORD )\n{\n\t//if (!InTimerCallback){\n\t\t//InTimerCallback++;\n\t\t//Colour_Debug (5);\n\t\tif (!AudioDone){\n\t\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t\t\tmaintenance_callback();\n\t\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t}\n\t\t//Colour_Debug (0);\n\t\t//InTimerCallback--;\n\t//}\n}\n\nvoid Sound_Thread (void *)\n{\n\tDuplicateHandle (GetCurrentProcess(), GetCurrentThread() , GetCurrentProcess() ,&SoundThreadHandle , THREAD_ALL_ACCESS , TRUE , 0);\n\tSetThreadPriority (SoundThreadHandle, THREAD_PRIORITY_TIME_CRITICAL);\n\tSoundThreadActive = TRUE;\n\n\twhile (!AudioDone){\n\n\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t\tmaintenance_callback();\n\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\tSleep(1000/40);\n\t}\n\n\tSoundThreadActive = FALSE;\n}\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Set_Primary_Buffer_Format -- set the format of the primary sound buffer                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   TRUE if successfully set                                                          *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    12/22/95 4:06PM ST : Created                                                             *\n *=============================================================================================*/\n\nBOOL Set_Primary_Buffer_Format(void)\n{\n\tif (SoundObject && PrimaryBufferPtr){\n\t\treturn (PrimaryBufferPtr->SetFormat ( &PrimaryBuffFormat ) == DS_OK);\n\t}\n\treturn (FALSE);\n}\n\n\n\n/***********************************************************************************************\n * Print_Sound_Error -- show error messages from failed sound initialisation                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    error text                                                                        *\n *           handle to window                                                                  *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    2/7/96 10:17AM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Print_Sound_Error(char *sound_error, HWND window)\n{\n\tMessageBox(window, sound_error, \"Command & Conquer\", MB_ICONEXCLAMATION|MB_OK);\n}\n\n\n\n/***********************************************************************************************\n * Audio_Init -- Initialise the sound system                                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    window - window to send callback messages to                                      *\n *           maximum bits_per_sample - 8 or 16                                                 *\n *           stereo - will stereo samples be played                                            *\n *           rate - maximum sample rate required                                               *\n *           reverse_channels                                                                  *\n *                                                                                             *\n * OUTPUT:   TRUE if correctly initialised                                                     *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   Unknown....                                                                               *\n *   08-24-95 10:01am ST : Modified for Windows 95 Direct Sound                                *\n *=============================================================================================*/\n\nBOOL Audio_Init( HWND window , int bits_per_sample, BOOL stereo , int rate , int reverse_channels)\n{\n\tint\tindex;\n\tint\tsample=1;\n\tshort old_bits_per_sample;\n\tshort old_block_align;\n\tlong\told_bytes_per_sec;\n\n\n\tInit_Locked_Data();\n\tFileStreamBuffer = NULL;\n\tmemset(&LockedData.SampleTracker[0], 0, sizeof(LockedData.SampleTracker));\n\n\tif ( !SoundObject ){\n\n\t\t/*\n\t\t**\tCreate the direct sound object\n\t\t*/\n\t\tif ( DirectSoundCreate (NULL,&SoundObject,NULL) !=DS_OK ) {\n\t\t\tPrint_Sound_Error(\"Warning - Unable to create Direct Sound Object\",window);\n\t\t\treturn (FALSE);\n\t\t}\n\n\t\t/*\n\t\t**\tGive ourselves exclusive access to it\n\t\t*/\n\t\tif ( SoundObject->SetCooperativeLevel( window, DSSCL_PRIORITY ) != DS_OK){\n\t\t\tPrint_Sound_Error(\"Warning - Unable to set Direct Sound cooperative level\",window);\n\t\t\tSoundObject->Release();\n\t\t\tSoundObject = NULL;\n\t\t\treturn (FALSE);\n\t\t}\n\n\t\t/*\n\t\t** Set up the primary buffer structure\n\t\t*/\n\t\tmemset (&BufferDesc , 0 , sizeof(DSBUFFERDESC));\n\t\tBufferDesc.dwSize=sizeof(DSBUFFERDESC);\n\t\tBufferDesc.dwFlags=DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;\n\n\t\t/*\n\t\t**\tSet up the primary buffer format\n\t\t*/\n\t\tmemset (&DsBuffFormat , 0 , sizeof(WAVEFORMATEX));\n\t\tDsBuffFormat.wFormatTag\t\t= WAVE_FORMAT_PCM;\n\t\tDsBuffFormat.nChannels\t\t= (unsigned short) (1 + stereo);\n\t\tDsBuffFormat.nSamplesPerSec\t= rate;\n\t\tDsBuffFormat.wBitsPerSample\t= (short) bits_per_sample;\n\t\tDsBuffFormat.nBlockAlign\t= (unsigned short)( (DsBuffFormat.wBitsPerSample/8) * DsBuffFormat.nChannels);\n\t\tDsBuffFormat.nAvgBytesPerSec= DsBuffFormat.nSamplesPerSec * DsBuffFormat.nBlockAlign;\n\t\tDsBuffFormat.cbSize = 0;\n\n\n\t\t/*\n\t\t** Make a copy of the primary buffer description so we can reset its format later\n\t\t*/\n\t\tmemcpy (&PrimaryBufferDesc , &BufferDesc , sizeof(DSBUFFERDESC));\n\t\tmemcpy (&PrimaryBuffFormat , &DsBuffFormat , sizeof(WAVEFORMATEX));\n\n\t\t/*\n\t\t**\tCreate the primary buffer object\n\t\t*/\n\t\tif ( SoundObject->CreateSoundBuffer (&PrimaryBufferDesc ,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&PrimaryBufferPtr ,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tNULL ) !=DS_OK ){\n\t\t\tPrint_Sound_Error(\"Warning - Unable to create Direct Sound primary buffer\",window);\n\t\t\tSoundObject->Release();\n\t\t\tSoundObject = NULL;\n\t\t\treturn (FALSE);\n\t\t}\n\n\t\t/*\n\t\t** Set the format of the primary sound buffer\n\t\t**\n\t\t*/\n\t\tif (!Set_Primary_Buffer_Format()){\n\n\t\t\t/*\n\t\t\t** If we failed to create a 16 bit primary buffer - try for an 8bit one\n\t\t\t*/\n\t\t\tif (DsBuffFormat.wBitsPerSample == 16){\n\t\t\t\t/*\n\t\t\t\t** Save the old values\n\t\t\t\t*/\n\t\t\t\told_bits_per_sample\t= DsBuffFormat.wBitsPerSample;\n\t\t\t\told_block_align\t\t= DsBuffFormat.nBlockAlign;\n\t\t\t\told_bytes_per_sec\t\t= DsBuffFormat.nAvgBytesPerSec;\n\n\t\t\t\t/*\n\t\t\t\t** Set up the 8-bit ones\n\t\t\t\t*/\n\t\t\t\tDsBuffFormat.wBitsPerSample\t= 8;\n\t\t\t\tDsBuffFormat.nBlockAlign\t= (unsigned short)( (DsBuffFormat.wBitsPerSample/8) * DsBuffFormat.nChannels);\n\t\t\t\tDsBuffFormat.nAvgBytesPerSec= DsBuffFormat.nSamplesPerSec * DsBuffFormat.nBlockAlign;\n\n\t\t\t\t/*\n\t\t\t\t** Make a copy of the primary buffer description so we can reset its format later\n\t\t\t\t*/\n\t\t\t\tmemcpy (&PrimaryBufferDesc , &BufferDesc , sizeof(DSBUFFERDESC));\n\t\t\t\tmemcpy (&PrimaryBuffFormat , &DsBuffFormat , sizeof(WAVEFORMATEX));\n\t\t\t}\n\n\t\t\tif (!Set_Primary_Buffer_Format()){\n\n\t\t\t\t/*\n\t\t\t\t** We failed to set any useful format so print up an error message and give up\n\t\t\t\t*/\n\t\t\t\tPrimaryBufferPtr->Release();\n\t\t\t\tPrimaryBufferPtr = NULL;\n\t\t\t\tSoundObject->Release();\n\t\t\t\tSoundObject = NULL;\n\n\t\t\t\tPrint_Sound_Error(\"Warning - Your sound card does not meet the products audio requirements\",window);\n\n\t\t\t\treturn (FALSE);\n\t\t\t}else{\n\n\t\t\t\t/*\n\t\t\t\t** OK, got an 8bit sound buffer. Not perfect but it will do\n\t\t\t\t** We still want 16 bit secondary buffers so restore those values\n\t\t\t\t*/\n\t\t\t\tDsBuffFormat.wBitsPerSample\t= old_bits_per_sample;\n\t\t\t\tDsBuffFormat.nBlockAlign\t\t= old_block_align;\n\t\t\t\tDsBuffFormat.nAvgBytesPerSec\t= old_bytes_per_sec;\n\t\t\t}\n\t\t}\n\n\n\t\t/*\n\t\t** Start the primary sound buffer playing\n\t\t**\n\t\t*/if ( PrimaryBufferPtr->Play(0,0,DSBPLAY_LOOPING) != DS_OK ){\n\t\t\tPrint_Sound_Error(\"Unable to play Direct Sound primary buffer\",window);\n\t\t\tPrimaryBufferPtr->Release();\n\t\t\tPrimaryBufferPtr = NULL;\n\t\t\tSoundObject->Release();\n\t\t\tSoundObject = NULL;\n\t\t\treturn (FALSE);\n\t\t}\n\n\t\tLockedData.DigiHandle=1;\n\n\n\t\t/*\n\t\t** Initialise the global critical section object for sound thread syncronisation\n\t\t*/\n\t\tInitializeCriticalSection(&GlobalAudioCriticalSection);\n\n\t\t/*\n\t\t** Initialise the Windows timer system to provide us with a callback\n\t\t**\n\t\t*/\n\t\tSoundTimerHandle = timeSetEvent ( 1000/MAINTENANCE_RATE , 1 , Sound_Timer_Callback , 0 , TIME_PERIODIC);\n\t\tAudioDone = FALSE;\n\t\t//_beginthread(&Sound_Thread, NULL, 16*1024, NULL);\n\n\t\t/*\n\t\t**\tDefine the format for the secondary sound buffers\n\t\t*/\n\t\tBufferDesc.dwFlags=DSBCAPS_CTRLVOLUME;\n\t\tBufferDesc.dwBufferBytes=SECONDARY_BUFFER_SIZE;\n\t\tBufferDesc.lpwfxFormat = (LPWAVEFORMATEX) &DsBuffFormat;\n\n\n\n\t\t/*\n    \t** Allocate a decompression buffer equal to the size of a SONARC frame\n\t\t** block.\n    \t*/\n    \tLockedData.UncompBuffer = Alloc(LARGEST_SONARC_BLOCK + 50, (MemoryFlagType)(MEM_NORMAL|MEM_CLEAR|MEM_LOCK));\n\n    \t/*\n    \t** Allocate once secondary direct sound buffer for each simultaneous sound effect\n\t\t**\n    \t*/\n\t\tfor (index = 0; index < MAX_SFX; index++) {\n\n\t\t\tSoundObject->CreateSoundBuffer (&BufferDesc , &LockedData.SampleTracker[index].PlayBuffer , NULL);\n\n\t\t\tLockedData.SampleTracker[index].PlaybackRate\t= rate;\n\t\t\tLockedData.SampleTracker[index].Stereo\t\t\t= (stereo) ? AUD_FLAG_STEREO : 0;\n\t\t\tLockedData.SampleTracker[index].BitSize \t\t= (bits_per_sample == 16) ? AUD_FLAG_16BIT : 0;\n\t\t\tLockedData.SampleTracker[index].FileHandle \t= WW_ERROR;\n\t\t\tLockedData.SampleTracker[index].QueueBuffer \t= NULL;\n\t\t\tInitializeCriticalSection (&LockedData.SampleTracker[index].AudioCriticalSection);\n\n\t\t}\n\n\t\tSoundType = (SFX_Type)sample;\n\t\tSampleType = (Sample_Type)sample;\n\t\tReverseChannels = reverse_channels;\n\n\t}\n\n\treturn(TRUE);\n}\n\n\n/***********************************************************************************************\n * Sound_End -- Uninitializes the sound driver.                                                *\n *                                                                                             *\n *    This routine will uninitialize the sound driver (if any was                              *\n *    installed).  This routine must be called at program termination                          *\n *    time.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/23/1991 JLB : Created.                                                                 *\n *   11/02/1995 ST  : Modified for Direct Sound                                                *\n *=============================================================================================*/\nvoid Sound_End(void)\n{\n\n\tint\tindex;\n\n\t/*\n\t** Remove the Windows timer event we installed for the sound callback\n\t*/\n\tif (SoundTimerHandle){\n\t\ttimeKillEvent(SoundTimerHandle);\n\t\tSoundTimerHandle = 0;\n\t}\n\n\n\tif (SoundObject && PrimaryBufferPtr){\n\t\t/*\n\t\t** Stop all sounds and release the Direct Sound secondary sound buffers\n\t\t*/\n\t\tfor (index=0 ; index < MAX_SFX; index++){\n\t\t\tif ( LockedData.SampleTracker[index].PlayBuffer ){\n\t\t\t\tStop_Sample (index);\n\t\t\t\tLockedData.SampleTracker[index].PlayBuffer->Stop();\n\t\t\t\tLockedData.SampleTracker[index].PlayBuffer->Release();\n\t\t\t\tLockedData.SampleTracker[index].PlayBuffer = NULL;\n\t\t\t\tDeleteCriticalSection(&LockedData.SampleTracker[index].AudioCriticalSection);\n\t\t\t}\n\t\t}\n\t}\n\n\tAudioDone = TRUE;\n\n\tif (FileStreamBuffer){\n\t\tFree (FileStreamBuffer);\n\t\tFileStreamBuffer = NULL;\n\t}\n\n\t/*\n\t** Stop and release the direct sound primary buffer\n\t*/\n\tif (PrimaryBufferPtr){\n\t\tPrimaryBufferPtr->Stop();\n\t\tPrimaryBufferPtr->Release();\n\t\tPrimaryBufferPtr = NULL;\n\t}\n\n\t/*\n\t** Release the Direct Sound Object\n\t*/\n\tif (SoundObject){\n\t\tSoundObject->Release();\n\t\tSoundObject = NULL;\n\t}\n\n\n\tif (LockedData.UncompBuffer) {\n    \tFree(LockedData.UncompBuffer);\n\t\tLockedData.UncompBuffer = 0;\n\t}\n\n\t/*\n\t** Since the timer has stopped, we are finished with our global critical section.\n\t*/\n\tDeleteCriticalSection(&GlobalAudioCriticalSection);\n}\n\n\n\n\n/***********************************************************************************************\n * Stop_Sample -- Stops any currently playing sampled sound.                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1992 JLB : Created.                                                                 *\n *   11/2/95 4:09PM ST : Modified for Direct Sound                                             *\n *=============================================================================================*/\nvoid Stop_Sample(int handle)\n{\n\tif (LockedData.DigiHandle != -1 && (unsigned)handle < MAX_SFX) {\n\n\t\tif (AudioDone)\treturn;\n\n\t\tEnterCriticalSection (&GlobalAudioCriticalSection);\n\n\t\tif (LockedData.SampleTracker[handle].Active || LockedData.SampleTracker[handle].Loading) {\n\n\t\t\tLockedData.SampleTracker[handle].Active = FALSE;\n\n\t\t\tif (!LockedData.SampleTracker[handle].IsScore) {\n          \tLockedData.SampleTracker[handle].Original = NULL;\n\t\t\t}\n\n\t\t\tLockedData.SampleTracker[handle].Priority = 0;\n\n\t\t\t/*\n          **  Stop the sample if it is playing.\n          */\n\t\t\tif (!LockedData.SampleTracker[handle].Loading) {\n\t\t\t\tLockedData.SampleTracker[handle].PlayBuffer->Stop();\n          }\n\n\t\t\tLockedData.SampleTracker[handle].Loading = FALSE;\n\n          /*\n\t\t\t**  If this is a streaming sample, then close the source file.\n          */\n\t\t\tif (LockedData.SampleTracker[handle].FileHandle != WW_ERROR) {\n\t\t\t\tClose_File(LockedData.SampleTracker[handle].FileHandle);\n\t\t\t\tLockedData.SampleTracker[handle].FileHandle = WW_ERROR;\n\t\t\t}\n\n\t\t\tLockedData.SampleTracker[handle].QueueBuffer = NULL;\n\t\t}\n\t\tLeaveCriticalSection (&GlobalAudioCriticalSection);\n\t}\n}\n\n\n/***********************************************************************************************\n * Sample_Status -- Queries the current playing sample status (if any).                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nBOOL Sample_Status(int handle)\n{\n\tDWORD\tstatus;\n\n\tif (AudioDone) return (FALSE);\n\n\t/*\n\t** If its an invalid handle or we do not have a sound driver then\n\t** the sample in question is not playing.\n\t*/\n\tif (LockedData.DigiHandle == -1 || (unsigned)handle >= MAX_SFX) return(FALSE);\n\n\t/*\n\t** If the sample is loading, then for all intents and purposes the\n\t** sample is playing.\n\t*/\n\tif (LockedData.SampleTracker[handle].Loading) return(TRUE);\n\n\t/*\n\t** If the sample is not active, then it is not playing\n\t*/\n\tif (!LockedData.SampleTracker[handle].Active) return(FALSE);\n\n\t/*\n\t** If we made it this far, then the Sample is still playing if sos says\n\t** that it is.\n\t*/\n\tDumpBuffer = LockedData.SampleTracker[handle].PlayBuffer;\n\tif (LockedData.SampleTracker[handle].PlayBuffer->GetStatus( &status ) == DS_OK){\n\t\treturn ( (DSBSTATUS_PLAYING & status) || (DSBSTATUS_LOOPING & status) );\n\t}else{\n\t\treturn (TRUE);\n\t}\n}\n\n\n\n/***********************************************************************************************\n * Is_Sample_Playing -- returns the play state of a sample                                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to sample data                                                                *\n *                                                                                             *\n * OUTPUT:   TRUE if sample is currently playing                                               *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:11PM ST : Commented                                                            *\n *=============================================================================================*/\n\nBOOL Is_Sample_Playing(void const * sample)\n{\n\tint index;\n\n\tif (AudioDone) return (FALSE);\n\n\t//EnterCriticalSection(&GlobalAudioCriticalSection);\n\n\tif (!sample) {\n\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\treturn FALSE;\n\t}\n\tfor (index = 0; index < MAX_SFX; index++) {\n\t\tif (LockedData.SampleTracker[index].Original == sample && Sample_Status(index)) {\n\t\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\treturn (TRUE);\n\t\t}\n\t}\n\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\treturn (FALSE);\n}\n\n\n/***********************************************************************************************\n * Stop_Sample_Playing -- stops a playing sample                                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to sample data                                                                *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:13PM ST : Commented                                                            *\n *=============================================================================================*/\n\nvoid Stop_Sample_Playing(void const * sample)\n{\n\tint index;\n\n\tif (sample) {\n\t\tfor (index = 0; index < MAX_SFX; index++) {\n\t\t\tif (LockedData.SampleTracker[index].Original == sample) {\n\t\t\t\tStop_Sample(index);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n\n\n/***********************************************************************************************\n * Get_Free_Sample_Handle -- finds a free slot in which to play a new sample                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    priority of sample we want to play                                                *\n *                                                                                             *\n * OUTPUT:   Handle or -1 if none free                                                         *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:14PM ST : Added function header                                                *\n *=============================================================================================*/\n\nint Get_Free_Sample_Handle(int priority)\n{\n\tint     id;\n\n\t/*\n\t**      Find a free SFX holding buffer slot.\n\t*/\n\tfor (id = MAX_SFX - 1; id >= 0; id--) {\n\t\tif (!LockedData.SampleTracker[id].Active && !LockedData.SampleTracker[id].Loading) {\n\t\t\tif (!StartingFileStream && LockedData.SampleTracker[id].IsScore) {\n\t\t\t\tStartingFileStream = TRUE;      // Ensures only one channel is kept free for scores.\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (id < 0) {\n\t\tfor (id = 0; id < MAX_SFX; id++) {\n\t\t\tif (LockedData.SampleTracker[id].Priority <= priority) break;\n\t\t}\n\n\t\tif (id == MAX_SFX) {\n\t\t\treturn(-1);             // Cannot play!\n\t\t}\n\t\tStop_Sample(id);                                                        // This sample gets clobbered.\n\t}\n\n\tif (id == -1) {\n\t\treturn -1;\n\t}\n\n\tif (LockedData.SampleTracker[id].FileHandle != WW_ERROR) {\n\t\tClose_File(LockedData.SampleTracker[id].FileHandle);\n\t\tLockedData.SampleTracker[id].FileHandle = WW_ERROR;\n\t}\n\n\tif (LockedData.SampleTracker[id].Original && !LockedData.SampleTracker[id].IsScore) {\n\t\tLockedData.SampleTracker[id].Original = NULL;\n\t}\n\tLockedData.SampleTracker[id].IsScore = FALSE;\n\treturn(id);\n}\n\nint Play_Sample(void const *sample, int priority, int volume, signed short panloc)\n{\n\t\t  return(Play_Sample_Handle(sample, priority, volume, panloc, Get_Free_Sample_Handle(priority)));\n}\n\n\n\n\n\n/***********************************************************************************************\n * Attempt_Audio_Restore -- tries to restore the direct sound buffers                          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to direct sound buffer                                                        *\n *                                                                                             *\n * OUTPUT:   TRUE if buffer was successfully restored                                          *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 9:47AM ST : Created                                                              *\n *=============================================================================================*/\n\nBOOL Attempt_Audio_Restore (LPDIRECTSOUNDBUFFER sound_buffer)\n{\n\n\tint \treturn_code;\n\tDWORD\tplay_status;\n\tint\trestore_attempts=0;\n\n\tif (AudioDone){\n\t\treturn (FALSE);\n\t}\n\n\t/*\n\t** Call the audio focus loss function if it has been set up\n\t*/\n\tif (Audio_Focus_Loss_Function){\n\t\tAudio_Focus_Loss_Function();\n\t}\n\n\t/*\n\t** Try to restore the sound buffer\n\t*/\n\tdo{\n\t\tRestore_Sound_Buffers();\n\t\treturn_code = sound_buffer->GetStatus ( &play_status );\n\n\t} while (restore_attempts++<2 && return_code == DSERR_BUFFERLOST);\n\n\treturn ((BOOL) ~(return_code == DSERR_BUFFERLOST));\n}\n\n\n\n/***********************************************************************************************\n * Convert_HMI_To_Direct_Sound_Volume -- Converts a linear volume value into an expotential    *\n *                                        value                                                *\n *                                                                                             *\n * This function converts a linear C&C volume in the range 0-255 (255 loudest) to a direct     *\n *  sound volume in the range 0 to -10000 (with 0 being the loadest)                           *\n *                                                                                             *\n * INPUT:    volume in range 0-255                                                             *\n *                                                                                             *\n * OUTPUT:   volume in range -10000 to 0                                                       *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * Note: The 27.685 value comes from 255 divided by the log of 10001                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/18/96 11:36AM ST : Created                                                             *\n *=============================================================================================*/\nint Convert_HMI_To_Direct_Sound_Volume(int volume)\n{\n\tif (volume == 0) return -10000;\n\tif (volume == 255) return 0;\n\n\tfloat vol = (float)volume;\n\tfloat retval = exp ( (255.0-vol)/27.68597374) -1;\n\treturn ((int)-retval);\n}\n\n\n\n\n\n/***********************************************************************************************\n * Play_Sample_Vol -- Plays a digitized sample.                                                *\n *                                                                                             *\n *    Use this routine to play a previously loaded digitized sample.                           *\n *                                                                                             *\n * INPUT:   sample   -- Sample pointer as returned from Load_Sample.                           *\n *                                                                                             *\n *          volume   -- The volume to play (0..255 with 255=loudest).                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *   05/24/1992 JLB : Volume support -- Soundblaster Pro                                       *\n *   04/22/1994 JLB : Multiple sample playback rates.                                          *\n *   11/02/1995 ST  : Windows Direct Sound support                                             *\n *=============================================================================================*/\nextern BOOL Any_Locked(void);\nint Play_Sample_Handle(void const *sample, int priority, int volume, signed short , int id)\n{\n\tAUDHeaderType                   RawHeader;\n\tSampleTrackerType               *st=NULL;       // Working pointer to sample tracker structure.\n\n\tLPVOID\t\t\t\tplay_buffer_ptr;\t\t//pointer to locked direct sound buffer\n\tLPVOID\t\t\t\tdummy_buffer_ptr;\t\t//dummy pointer to second area of locked direct sound buffer\n\tDWORD\t\t\t\t\tlock_length1;\n\tDWORD\t\t\t\t\tlock_length2;\n\tDWORD\t\t\t\t\tplay_status;\n\tHRESULT\t\t\t\treturn_code;\n\tint\t\t\t\t\tretries=0;\n\n\n\tif (Any_Locked()) return(0);\n\n\tif (AudioDone) return (0);\n\n\tst = &LockedData.SampleTracker[id];\n\t//EnterCriticalSection (&GlobalAudioCriticalSection);\n\n\tif (!sample || LockedData.DigiHandle == -1) {\n\t\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\treturn(-1);\n\t}\n\n\tif (id == -1) {\n\t\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\treturn -1;\n\t}\n\n\t/*\n\t**      Fetch the control bytes from the start of the sample data.\n\t*/\n\tMem_Copy((void *)sample, (void *)&RawHeader, sizeof(RawHeader));\n\n\t/*\n\t** Fudge the sample rate to 22k\n\t*/\n\tif (RawHeader.Rate <24000 && RawHeader.Rate >20000) RawHeader.Rate = 22050;\n\n\t/*\n\t**      Prepare the sample tracker structure for processing of this\n\t**      sample.  Fill the structure with data that can be determined\n\t**      before the sample is started.\n\t*/\n\tif (!AudioDone){\n\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t}\n\tst->Compression \t\t\t= (SCompressType) ((unsigned char)RawHeader.Compression);\n\tst->Original            = sample;\n\tst->OriginalSize        = RawHeader.Size + sizeof(RawHeader);\n\tst->Priority            = (short)priority;\n\tst->DontTouch           = TRUE;\n\tst->Odd\t\t\t\t\t\t= 0;\n\tst->Reducer             = 0;\n\tst->Restart             = FALSE;\n\tst->QueueBuffer \t\t\t= NULL;\n\tst->QueueSize           = NULL;\n\tst->TrailerLen  \t\t\t= 0;\n\tst->Remainder           = RawHeader.Size;\n\tst->Source              = Add_Long_To_Pointer((void *)sample, sizeof(RawHeader));\n\tst->Service             = FALSE;\n\tif (!AudioDone){\n\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t}\n\n    /*\n\t ** If the code in question using HMI based compression then we need\n    ** to set up for uncompressing it.\n\t */\n    if (st->Compression == SCOMP_SOS) {\n\t\tst->sosinfo.wChannels    = (RawHeader.Flags & AUD_FLAG_STEREO) ? 2  : 1;\n\t\tst->sosinfo.wBitSize             = (RawHeader.Flags & AUD_FLAG_16BIT)  ? 16 : 8;\n\t\tst->sosinfo.dwCompSize   = RawHeader.Size;\n\t\tst->sosinfo.dwUnCompSize = RawHeader.Size * ( st->sosinfo.wBitSize / 4 );\n\t\tsosCODECInitStream(&st->sosinfo);\n\t}\n\n\t/*\n\t** If the sample rate , bits per sample or stereo capabilities of the buffer do not\n\t** match the sample then reallocate the direct sound buffer with the required capabilities\n\t*/\n\tif (  ( RawHeader.Rate != st->PlaybackRate ) ||\n\t\t\t( ( RawHeader.Flags & AUD_FLAG_16BIT ) != ( st->BitSize & AUD_FLAG_16BIT ) ) ||\n\t\t\t( ( RawHeader.Flags & AUD_FLAG_STEREO) != ( st->Stereo & AUD_FLAG_STEREO ) ) ) {\n\n\t\tst->Active=0;\n\t\tst->Service=0;\n\t\tst->MoreSource=0;\n\n\t\t/*\n\t\t** Stop the sound buffer playing\n\t\t*/\n\t\tDumpBuffer = st->PlayBuffer;\n\t\tdo {\n\t\t\treturn_code = st->PlayBuffer->GetStatus ( &play_status );\n\t\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t\t}\n\t\t}while (return_code == DSERR_BUFFERLOST);\n\n\t\tif (play_status & (DSBSTATUS_PLAYING | DSBSTATUS_LOOPING) ){\n\t\t\tst->PlayBuffer->Stop();\n\t\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t\t}\n\t\t}\n\n\t\tst->PlayBuffer->Release();\n\t\tst->PlayBuffer=NULL;\n\n\t\tDsBuffFormat.nSamplesPerSec\t= (unsigned short int) RawHeader.Rate;\n\t\tDsBuffFormat.nChannels\t\t\t= (RawHeader.Flags & AUD_FLAG_STEREO) ? 2 : 1 ;\n\t\tDsBuffFormat.wBitsPerSample\t= (RawHeader.Flags & AUD_FLAG_16BIT) ? 16 : 8 ;\n\t\tDsBuffFormat.nBlockAlign\t= (short) ((DsBuffFormat.wBitsPerSample/8) * DsBuffFormat.nChannels);\n\t\tDsBuffFormat.nAvgBytesPerSec= DsBuffFormat.nSamplesPerSec * DsBuffFormat.nBlockAlign;\n\n\t\t/*\n\t\t** Create the new sound buffer\n\t\t*/\n\t\treturn_code= SoundObject->CreateSoundBuffer (&BufferDesc , &st->PlayBuffer , NULL);\n\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t}\n\t\t/*\n\t\t** Just return if the create failed unexpectedly\n\t\t**\n\t\t** If we failed then flag the buffer as having an impossible format so it wont match\n\t\t** any sample. This will ensure that we try and create the buffer again next time its used.\n\t\t*/\n\t\tif (return_code!=DS_OK && return_code!=DSERR_BUFFERLOST){\n\t\t\tst->PlaybackRate = 0;\n\t\t\tst->Stereo = 0;\n\t\t\tst->BitSize = 0;\n\t\t\treturn(-1);\n\t\t}\n\n\t\t/*\n\t\t** Remember the format of the new buffer\n\t\t*/\n\t\tst->PlaybackRate \t= RawHeader.Rate;\n\t\tst->Stereo\t\t\t= RawHeader.Flags & AUD_FLAG_STEREO;\n\t\tst->BitSize \t\t= RawHeader.Flags & AUD_FLAG_16BIT;\n\t}\n\n\t/*\n\t**      Fill in 3/4 of the play buffer.\n\t*/\n\n\t//\n\t// Stop the sound buffer playing before we lock it\n\t//\n\tdo {\n\t\tDumpBuffer = st->PlayBuffer;\n\t\treturn_code = st->PlayBuffer->GetStatus ( &play_status );\n\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t}\n\t} while (return_code==DSERR_BUFFERLOST);\n\n\tif (play_status & (DSBSTATUS_PLAYING | DSBSTATUS_LOOPING) ){\n\t\tst->Active=0;\n\t\tst->Service=0;\n\t\tst->MoreSource=0;\n\t\tst->PlayBuffer->Stop();\n\t}\n\t//\n\t// Lock the direct sound buffer so we can write to it\n\t//\n\tdo {\n\t\treturn_code = st->PlayBuffer->Lock (\t0 ,\n\t\t\t\t\t\t\t\t\t\tSECONDARY_BUFFER_SIZE,\n\t\t\t\t\t\t\t\t\t\t&play_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t&lock_length1,\n\t\t\t\t\t\t\t\t\t\t&dummy_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t&lock_length2,\n\t\t\t\t\t\t\t\t\t\t0 );\n\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t}\n\t} while (return_code==DSERR_BUFFERLOST);\n\n\tif (return_code != DS_OK) {\n\t\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\treturn (-1);\n\t}\n\n\t//\n\t// Decompress the sample into the direct sound buffer\n\t//\n\tst->DestPtr=(void*)Sample_Copy ( \tst,\n\t\t\t\t\t\t\t\t&st->Source,\n\t\t\t\t\t\t\t\t&st->Remainder,\n\t\t\t\t\t\t\t\t&st->QueueBuffer,\n\t\t\t\t\t\t\t\t&st->QueueSize,\n\t\t\t\t\t\t\t\tplay_buffer_ptr,\n\t\t\t\t\t\t\t\tSECONDARY_BUFFER_SIZE*1/4,\n\t\t\t\t\t\t\t\tst->Compression,\n\t\t\t\t\t\t\t\t&st->Trailer[0],\n\t\t\t\t\t\t\t\t&st->TrailerLen);\n\n\tif ( st->DestPtr==(void*) (SECONDARY_BUFFER_SIZE*1/4) ){\n\n\t\t// Must be more data to copy so we dont need to zero the buffer\n\t\tst->MoreSource=TRUE;\n\t\tst->Service=TRUE;\n\t\tst->OneShot=FALSE;\n\t} else {\n\n\t\t// Whole sample is in the buffer so flag that we dont need to\n\t\t// copy more. Clear out the end of the buffer so that it\n\t\t// goes quiet if we play past the end\n\t\tst->MoreSource=FALSE;\n\t\tst->OneShot=TRUE;\n\t\tst->Service=TRUE;\t\t\t\t//We still need to service it so that we can stop it when\n\t\t\t\t\t\t\t\t\t\t\t// it plays past the end of the sample data\n\t\t//memset ( (char*)( (unsigned)play_buffer_ptr + (unsigned)st->DestPtr ), 0 , SECONDARY_BUFFER_SIZE - (unsigned)st->DestPtr );\n\t\tmemset ( (char*)( (unsigned)play_buffer_ptr + (unsigned)st->DestPtr ), 0 , SECONDARY_BUFFER_SIZE/4);\n\t}\n\n\tst->PlayBuffer->Unlock(\tplay_buffer_ptr,\n\t\t\t\t\t\t\tlock_length1,\n\t\t\t\t\t\t\tdummy_buffer_ptr,\n\t\t\t\t\t\t\tlock_length2);\n\n\n\t/*\n    **\n    **  Set the volume of the sample.\n    **\n    */\n\tst->Volume = (volume << 7);\n\tdo {\n\n\t\t//return_code = st->PlayBuffer->SetVolume ( Convert_HMI_To_Direct_Sound_Volume(volume));\n\t\tst->PlayBuffer->SetVolume ( Convert_HMI_To_Direct_Sound_Volume( ( LockedData.SoundVolume*volume)/256) );\n\t\t//return_code = st->PlayBuffer->SetVolume (- ( ( (32768- ( (st->Volume >> 8) *LockedData.SoundVolume) )\n\t\t//\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*1000) >>15 ) );\n\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t}\n\t} while (return_code==DSERR_BUFFERLOST);\n\n\n\t/*\n\t** Make sure the primary sound buffer is playing\n\t*/\n\tif (!Start_Primary_Sound_Buffer(FALSE)){\n\t\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\treturn(-1);\n\t}\n\n\n\t/*\n\t** Set the buffers play pointer to the beginning of the buffer\n\t*/\n\tdo {\n\t\treturn_code = st->PlayBuffer->SetCurrentPosition (0);\n\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t}\n\t} while (return_code==DSERR_BUFFERLOST);\n\n\n\t/*\n    ** Start the sample playing now.\n\t*/\n\tdo\n\t{\n\t\treturn_code = st->PlayBuffer->Play (0,0,DSBPLAY_LOOPING);\n\n\t\tswitch (return_code){\n\n\t\t\tcase DS_OK :\n\t\t\t\tif (!AudioDone){\n\t\t\t\t\tEnterCriticalSection (&GlobalAudioCriticalSection);\n\t\t\t\t}\n\t\t\t\tst->Active=TRUE;\n\t\t\t\tst->Handle=(short)id;\n\t\t\t\tst->DontTouch = FALSE;\n\t\t\t\tif (!AudioDone){\n\t\t\t\t\tLeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\t\t\t}\n\t\t\t\treturn (st->Handle);\n\n\t\t\tcase DSERR_BUFFERLOST :\n\t\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tst->Active=FALSE;\n\t\t\t\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\t\t\treturn (st->Handle);\n\t\t}\n\n\t} while (return_code==DSERR_BUFFERLOST);\n\n\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\treturn (st->Handle);\n}\n\n\n\n\n\n/***********************************************************************************************\n * Restore_Sound_Buffers -- restore the sound buffers                                          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/3/95 3:53PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Restore_Sound_Buffers ( void )\n{\n\n\tif (PrimaryBufferPtr){\n\t\tPrimaryBufferPtr->Restore();\n\t}\n\n\n\tfor ( int index = 0; index < MAX_SFX; index++) {\n\t\tif (LockedData.SampleTracker[index].PlayBuffer){\n\t\t\tLockedData.SampleTracker[index].PlayBuffer->Restore();\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Set_Sound_Vol -- sets the overall volume for sampled sounds                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    volume                                                                            *\n *                                                                                             *\n * OUTPUT:   the previous volume setting                                                       *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:19PM ST : Added function header                                                *\n *=============================================================================================*/\n\nint Set_Sound_Vol(int volume)\n{\n\tint old;\n \told = LockedData.SoundVolume;\n \tLockedData.SoundVolume = volume & 0xFF;\n\treturn(old);\n}\n\n\n/***********************************************************************************************\n * Set_Score_Vol -- sets the overall volume for music scores                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    volume                                                                            *\n *                                                                                             *\n * OUTPUT:   the previous volume setting                                                       *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:19PM ST : Added function header                                                *\n *=============================================================================================*/\nint Set_Score_Vol(int volume)\n{\n\tint old;\n\tSampleTrackerType\t*st;\t\t\t\t\t//ptr to SampleTracker structure\n\n\told = LockedData.ScoreVolume;\n\tLockedData.ScoreVolume = volume & 0xFF;\n\n\tfor (int index=0 ; index<MAX_SFX ; index++){\n\t\tst = &LockedData.SampleTracker[index];\n\n\t\tif (st->IsScore && st->Active){\n\t\t\t//st->PlayBuffer->SetVolume (- ( ( (32768- ( (st->Volume >> 8) *LockedData.ScoreVolume) )\n\t\t\t//\t\t\t\t\t\t\t\t\t\t\t\t\t\t*1000) >>15 ) );\n\n\t\t\t//st->PlayBuffer->SetVolume ( Convert_HMI_To_Direct_Sound_Volume ( st->Volume >>7 ) );\n\t\t\tst->PlayBuffer->SetVolume ( Convert_HMI_To_Direct_Sound_Volume( ( LockedData.ScoreVolume*(st->Volume >>7))/256) );\n\t\t}\n\t}\n\treturn(old);\n}\n\n\n\n/***********************************************************************************************\n * Fade_Sample -- Start a sample fading                                                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Sample handle                                                                     *\n *           fade rate                                                                         *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:21PM ST : Added function header                                                *\n *=============================================================================================*/\n\nvoid Fade_Sample(int handle, int ticks)\n{\n\tif (Sample_Status(handle)) {\n    \tif (!ticks || LockedData.SampleTracker[handle].Loading) {\n       \tStop_Sample(handle);\n\t\t\t} else {\n\t\t\t\tSampleTrackerType * st;\n\t\t\t\tst = &LockedData.SampleTracker[handle];\n\t\t\t\tst->Reducer = (short) ((st->Volume / ticks)+1);\n\t\t\t}\n\t}\n}\n\n\n\nint Get_Digi_Handle(void)\n{\n        return(LockedData.DigiHandle);\n}\n\n\n\n/***************************************************************************\n * SAMPLE_LENGTH -- returns length of a sample in ticks                    *\n *                                                                         *\n * INPUT:  void const *sample - pointer to the sample to get length of.    *\n *                                                                         *\n * OUTPUT: long - length of the sample in ticks (60/sec)                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/05/1995 PWG : Created.                                             *\n *=========================================================================*/\nlong Sample_Length(void const *sample)\n{\n\tAUDHeaderType\tRawHeader;\n\n\tif (!sample) return(0);\n\n\tMem_Copy((void *)sample, (void *)&RawHeader, sizeof(RawHeader));\n\n\tlong time = RawHeader.UncompSize;\n\n\t/*\n\t** If the sample is a 16 bit sample, then it will take only half\n\t** as long to play.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_16BIT) {\n\t\ttime >>= 1;\n\t}\n\n\t/*\n\t** If the sample is a stereo sample, then it will take only half\n\t** as long to play.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_STEREO) {\n\t\ttime >>= 1;\n\t}\n\n\tif (RawHeader.Rate/60) {\n\t\ttime /= (RawHeader.Rate/60);\n\t}\n\treturn(time);\n}\n\n\n\n/***********************************************************************************************\n * Start_Primary_Sound_Buffer -- start the primary sound buffer playing                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    2/1/96 12:28PM ST : Created                                                              *\n *=============================================================================================*/\nextern BOOL GameInFocus;\nBOOL Start_Primary_Sound_Buffer (BOOL forced)\n{\n\tDWORD status;\n\n\tif (PrimaryBufferPtr && GameInFocus){\n\t\tif (forced){\n\t\t\tPrimaryBufferPtr->Play(0,0,DSBPLAY_LOOPING);\n\t\t\treturn (TRUE);\n\t\t} else {\n\n\t\t\tif (PrimaryBufferPtr->GetStatus (&status) == DS_OK){\n\t\t\t\tif (! ((status & DSBSTATUS_PLAYING) || (status & DSBSTATUS_LOOPING))){\n\t\t\t\t\tPrimaryBufferPtr->Play(0,0,DSBPLAY_LOOPING);\n\t\t\t\t\treturn (TRUE);\n\t\t\t\t}else{\n\t\t\t\t\treturn (TRUE);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn (FALSE);\n}\n\n\n/***********************************************************************************************\n * Stop_Primary_Sound_Buffer -- stops the primary sound buffer from playing.                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: This stops all sound playback                                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    2/1/96 12:28PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Stop_Primary_Sound_Buffer (void)\n{\n\tif (PrimaryBufferPtr){\n\t\tPrimaryBufferPtr->Stop();\n\t\tPrimaryBufferPtr->Stop();\t      // Oh I\n\t\tPrimaryBufferPtr->Stop();\t\t\t// Hate Direct Sound\n\t\tPrimaryBufferPtr->Stop();\t\t\t// So much.....\n\t}\n\n\tfor ( int index = 0; index < MAX_SFX; index++) {\n\t\tStop_Sample(index);\n\t}\n\n}\n\n\nvoid Suspend_Audio_Thread(void)\n{\n\tif (SoundThreadActive){\n\t\t//SuspendThread(SoundThreadHandle);\n\t\ttimeKillEvent(SoundTimerHandle);\n\t\tSoundTimerHandle = NULL;\n\t\tSoundThreadActive = FALSE;\n\t}\n}\n\n\n\n\nvoid Resume_Audio_Thread(void)\n{\n\tif (!SoundThreadActive){\n\t\t//ResumeThread(SoundThreadHandle);\n\t\tSoundTimerHandle = timeSetEvent ( 1000/MAINTENANCE_RATE , 1 , Sound_Timer_Callback , 0 , TIME_PERIODIC);\n\t\tSoundThreadActive = TRUE;\n\t}\n}\n\n\n"
  },
  {
    "path": "WIN32LIB/AUDIO/SOUNDLCK.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDLCK.CPP                             *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 23, 1995   [PWG]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#define WIN32\n#include <windows.h>\n#include <windowsx.h>\n#include <objbase.h>\n#include \"dsound.h\"\n#include <mem.h>\n#include \"wwmem.h\"\n#include \"wwstd.h\"\n#include \"soundint.h\"\n\n\n\nLockedDataType LockedData;\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * INIT_LOCKED_DATA -- Initializes sound driver locked data                *\n *                                                                         *\n * INPUT:\t\tnone                                                          *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid Init_Locked_Data(void)\n{\n\n\t/*\n\t** Initialize all of the data elements that need to be locked.\n\t*/\n\tLockedData.DigiHandle\t\t\t= -1;\n\tLockedData.ServiceSomething\t= FALSE;\n\tLockedData.MagicNumber\t\t\t= 0xDEAF;\n\tLockedData.UncompBuffer\t\t\t= NULL;\n//\tLockedData.StreamBufferSize\t= (2*SECONDARY_BUFFER_SIZE)+128;\n\tLockedData.StreamBufferSize\t= (SECONDARY_BUFFER_SIZE/4)+128;\n\tLockedData.StreamBufferCount\t= 16;\n\tLockedData.SoundVolume\t\t\t= 255;\n\tLockedData.ScoreVolume\t\t\t= 255;\n\tLockedData._int\t\t\t\t\t= FALSE;\n\n\t#ifdef cuts\n\t/*\n\t** Lock the sound specific c functions that will cause us problems if\n\t** they are swapped out during an interrupt.\n\t*/\n\tDPMI_Lock(&LockedData,\t\t\t\t\t\t\t4096L);\n\tDPMI_Lock(Simple_Copy, \t\t\t\t\t\t\t4096L);\n\tDPMI_Lock(Sample_Copy, \t\t\t\t\t\t\t4096L);\n\tDPMI_Lock((void *)maintenance_callback, \t4096L);\n\tDPMI_Lock((void *)DigiCallback, \t\t\t\t4096L);\n\tDPMI_Lock((void *)HMI_TimerCallback, \t\t4096L);\n\tDPMI_Lock(Audio_Add_Long_To_Pointer,\t\t4096L);\n\tDPMI_Lock(DPMI_Unlock,\t\t\t\t\t\t\t4096L);\n\n\t/*\n\t** Lock the library functions that will cause us problems if they are\n\t** swapped out during an interrupt.\n\t*/\n\tDPMI_Lock(Mem_Copy,\t\t\t\t\t\t\t\t4096L);\n\tDPMI_Lock(Audio_Mem_Set,\t\t\t\t\t\t4096L);\n\tDPMI_Lock(__GETDS,\t\t\t\t\t\t\t\t4096L);\n\n\t/*\n\t** Finally lock the two assembly modules that need locking.  This can\n\t** be handled by calling the lock function that is local to thier module\n\t** swapped out during an interrupt.\n\t*/\n\tDecompress_Frame_Lock();\n\tsosCODEC_Lock();\n\n\t#endif\t//cuts\n}\n\n"
  },
  {
    "path": "WIN32LIB/AUDIO/TEST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <windowsx.h>\n#include \"audio.h\"\n\n\n\nint PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,\n                        LPSTR lpCmdLine, int nCmdShow)\n{\n\n\n\n\t\t\t \n\n\n\tFile_Stream_Sample_Vol(\"file\", 0, 0);\n\n\treturn (0);\n}"
  },
  {
    "path": "WIN32LIB/AUDIO/TST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#undef _WINDOWS_16_\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#define WIN32\n#define __WIN32\n\n#include <windows.h>\n#include <windowsx.h>\n#include <ole2.h>\n\nmain\n{}\n"
  },
  {
    "path": "WIN32LIB/DIPTHONG/DIPTHONG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./dipthong.c 1.15 1994/05/20 15:35:17 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : DIPTHONG.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : February 23, 1992                        *\n *                                                                         *\n *                  Last Update : February 13, 1995 [BWG]                  *\n *                                                                         *\n * DIGRAM or DIATOMIC encoding is the correct term for this method.        *\n * This is a fixed dictionary digram encoding optimized for English text.  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Extract_String -- Extracts a string pointer from a string data block. *\n *   UnDip_Text -- Undipthongs a text string into specified buffer.        *\n *   Dip_Text -- Compresses text by using dipthonging.                     *\n *   Fixup_Text -- Converts dipthonged foreign text into normal text.      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n//#include\t\"function.h\"\n//#include\t\"ems.h\"\n#include <keyboard.h>\n#include \"dipthong.h\"\n\n/***************************************************************************\n * Fixup_Text -- Converts dipthonged foreign text into normal text.        *\n *                                                                         *\n *    Takes text that has been processed (or undipped) to hold foriegn     *\n *    language character pairs (needed for Window_Print) and converts it   *\n *    so that Text_Print will print it properly.  Typically this would be  *\n *    used after text has been undipped but before it will be Text_Printed.*\n *    Text that is to be Window_Printed doesn't and mustn't have its text  *\n *    processed by this routine.                                           *\n *                                                                         *\n * INPUT:   source   -- Pointer to the source string to process.           *\n *                                                                         *\n *          dest     -- Destination buffer to hold the processed string.   *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine will only reduce the size of the string if it  *\n *             modifies it at all.  Because of this it is quite legal to   *\n *             pass the same pointers to this routine so that it will      *\n *             modify the string \"in place\".                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/13/1993 JLB : Created.                                             *\n *   10/06/1994 JLB : Handles source string in EMS.                        *\n *=========================================================================*/\nvoid Fixup_Text(char const *source, char *dest)\n{\n\tif (source && dest) {\n\t\tchar const \t*src;\n\t\tchar\t\t\ttemp;\n\n\t\tsrc = source;\n\t\twhile (*src) {\n\t\t\tif (*src == KA_EXTEND) {\n\t\t\t\tsrc++;\n\t\t\t\ttemp = *src++;\n\t\t\t\ttemp += 127;\n\t\t\t\t*dest++ = temp;\n\t\t\t} else {\n\t\t\t\t*dest++ = *src++;\n\t\t\t}\n\t\t}\n\t\t*dest = '\\0';\n\n\t}\n}\n\n\n/***************************************************************************\n * Dip_Text -- Compresses text by using dipthonging.                       *\n *                                                                         *\n *    This routine is used to compress text by using dipthonging.  Text    *\n *    that is compressed in this fashion usually is reduced in size by     *\n *    approximately 40%.                                                   *\n *                                                                         *\n * INPUT:   source   -- Pointer to the source string to compress.          *\n *                                                                         *\n *          dest     -- Pointer to the buffer that will hold the dipthong  *\n *                      text output.                                       *\n *                                                                         *\n * OUTPUT:  Returns the number of bytes output into the output buffer.     *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/13/1993 JLB : Created.                                             *\n *=========================================================================*/\nint Dip_Text(char const *source, char *dest)\n{\n\tunsigned char\tfirst,\t\t// First character in pair.\n\t\t\t\t\t\tnext;\t\t\t// Second character in pair.\n\tint\t\t\t\tcommon,\t\t// Common character index.\n\t\t\t\t\t\tdipthong;\t// Dipthong character index.\n\n\tunsigned long length=0;\t\t// Length of output string\n\n\tfirst = *source++;\n\tnext = *source;\n\twhile (first) {\n\n\t\tif (first > 127) {\n\n\t\t\t/*\n\t\t\t**\tCharacters greater than 127 cannot be dipthonged.  They must\n\t\t\t**\tbe preceeded with an extended character code.\n\t\t\t*/\n\t\t\t*dest++ = (char)KA_EXTEND;\n\t\t\tfirst -= 127;\n\t\t\tlength++;\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tNormal characters can be dipthonged.  First see if there is a\n\t\t\t**\tmatch in the Common table.\n\t\t\t*/\n\t\t\tfor (common = 0; common < 16; common++) {\n\t\t\t\tif (Common[common] == first) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCommon character found.  See if there is a matching\n\t\t\t\t\t**\tDipthong character.\n\t\t\t\t\t*/\n\t\t\t\t\tfor (dipthong = 0; dipthong < 8; dipthong++) {\n\t\t\t\t\t\tif (Dipthong[common][dipthong] == next) {\n\t\t\t\t\t\t\tfirst = (unsigned char) (common << 3);\n\t\t\t\t\t\t\tfirst |= (unsigned char)dipthong;\n\t\t\t\t\t\t\tfirst |= (unsigned char)0x80;\n\t\t\t\t\t\t\tsource++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tOutput the translated character to the destination buffer.\n\t\t*/\n\t\t*dest++ = first;\n\t\tlength++;\n\n\t\tfirst = *source++;\n\t\tnext = *source;\n\t}\n\n\t*dest = '\\0';\n\n\treturn(length);\n}\n\n\n/***************************************************************************\n * UnDip_Text -- Undipthongs a text string into specified buffer.          *\n *                                                                         *\n *    This routine is used to undipthong a text string and place the       *\n *    undipped text into the buffer specified.  Since dipthonged text is   *\n *    compressed, in order for the text to be used it must be undipped     *\n *    first.                                                               *\n *                                                                         *\n * INPUT:   source   -- Pointer to the dipped string.                      *\n *                                                                         *\n *          dest     -- Pointer to the destination buffer.                 *\n *                                                                         *\n * OUTPUT:  Returns the number of bytes placed into the destination        *\n *          buffer.                                                        *\n *                                                                         *\n * WARNINGS:   Be sure the destination buffer is big enough to hold the    *\n *             undipped text.                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/13/1993 JLB : Created.                                             *\n *   10/06/1994 JLB : Handles source string in EMS.                        *\n *=========================================================================*/\nint UnDip_Text(char const *source, char *dest)\n{\n\tint\tc;\t\t\t// Source input character.\n\tint\tcommon;\t// Common character index.\n\tint\tlen;\t\t// Length of output string.\n\tchar const *src;\n\n\tlen = 0;\t\t\t\t\t\t// Presume no translation.\n\n\t/*\n\t**\tSweep through the source text and dipthong it.\n\t*/\n\tsrc = source;\n\tc = *src++;\n\twhile (c) {\n\n\t\t/*\n\t\t**\tConvert a dipthong character into it's component\n\t\t**\tASCII characters.\n\t\t*/\n\t\tif (c & 0x80) {\n\t\t\tc &= 0x7F;\n\n\t\t\tcommon = (c & 0x78) >> 3;\n\n\t\t\t*dest++ = Common[common];\n\t\t\tlen++;\n\n\t\t\tc = Dipthong[common][c & 0x07];\n\t\t}\n\n\t\t*dest++ = (unsigned char)c;\n\t\tlen++;\n\n\t\tc = *src++;\n\t}\n\n\t/*\n\t**\tEnd the output text with a '\\0'.\n\t*/\n\t*dest++ = '\\0';\n\n\treturn(len);\n}\n\n\n/***************************************************************************\n * Extract_String -- Extracts a string pointer from a string data block.   *\n *                                                                         *\n *    This routine is used to find a pointer to the specified string       *\n *    inside a string block.  String data blocks are created with the      *\n *    TEXTMAKE utility.  The data block my reside in XMS or EMS memory,    *\n *    but of course the returned string pointer will also point to         *\n *    such memory.  In this case, the string must be placed in real        *\n *    memory before it can be used.                                        *\n *                                                                         *\n * INPUT:   data     -- Pointer to the string data block.                  *\n *                                                                         *\n *          string   -- The string number to extract (if < 0 then NULL     *\n *                      is returned).                                      *\n *                                                                         *\n * OUTPUT:  Returns with pointer to the string number specified.           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/13/1993 JLB : Created.                                             *\n *   08/13/1993 JLB : Handles EMS or XMS data pointer.                     *\n *=========================================================================*/\n\n#define TXT_GUEST \t\t\t\t\t4567+3\n#define TXT_LOGIN \t\t\t\t\t4567+4\n#define TXT_LOGIN_TO_INTERNET \t4567+5\n#define TXT_YOUR_HANDLE \t\t\t4567+6\n#define TXT_YOUR_PASSWORD \t\t4567+7\n#define TXT_INTERNET_HOST\t\t4567+8\n#define TXT_INTERNET_JOIN\t\t4567+9\n#define TXT_INTERNET_GAME_TYPE\t4567+10\n#define TXT_JOIN_INTERNET_GAME\t4567+11\n#define TXT_ENTER_IP_ADDRESS\t4567+12\n#define TXT_WINSOCK_CONNECTING\t\t\t\t\t\t\t4567+13\n#define TXT_WINSOCK_NOT_CONNECTING\t\t\t\t\t4567+14\n#define TXT_WINSOCK_UNABLE_TO_CONNECT_TO_SERVER\t4567+15\n#define TXT_WINSOCK_CONTACTING_SERVER\t\t\t\t4567+16\n#define TXT_WINSOCK_SERVER_ADDRESS_LOOKUP_FAILED\t4567+17\n#define TXT_WINSOCK_UNABLE_TO_ACCEPT_CLIENT\t\t4567+18\n#define TXT_WINSOCK_UNABLE_TO_CONNECT\t\t\t\t4567+19\n#define TXT_WINSOCK_CONNECTION_LOST\t\t\t\t\t4567+20\n#define TXT_WINSOCK_RESOLVING_HOST_ADDRESS\t\t\t4567+21\n\nstatic char InternetTxt[22][40]={\n\t\"Internet H2H\",\n\t\"Host Internet Game\",\n\t\"Join Internet Game\",\n\t\"Guest\",\n\t\"Login\",\n\t\"Login to Planet Westwood\",\n\t\"Planet Westwood Handle\",\n\t\"Planet Westwood Password\",\n\t\"Host Game\",\n\t\"Join Game\",\n\t\"Choose Type of Internet Game\",\n\t\"Join Internet Game\",\n\t\"Address of Host\",\n\t\"Connecting...\",\n\t\"Connection Error!\",\n\t\"Unable to connect to host!\",\n\t\"Connecting to host...\",\n\t\"Unable to resolve host address!\",\n\t\"Unable to accept client connection\",\n\t\"Unable to connect!\",\n\t\"Connection lost!\",\n\t\"Resolving address of host...\"\n};\n\nchar *Extract_String(void const *data, int string)\n{\n\tunsigned short int\tconst *ptr;\n\n\tif (!data || string < 0) return(NULL);\n\n\tif (string >= 4567) return (InternetTxt[string-4567]);\n\n\tptr = (unsigned short int const *)data;\n\treturn (((char*)data) + ptr[string]);\n}\n"
  },
  {
    "path": "WIN32LIB/DIPTHONG/DIPTHONG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\nint Dip_Text(char const *source, char *dest);\nint UnDip_Text(char const *source, char *dest);\nchar *Extract_String(void const *data, int string);\nvoid Fixup_Text(char const *source, char *dest);\nextern char Common[];\nextern char Dipthong[16][8];\n"
  },
  {
    "path": "WIN32LIB/DIPTHONG/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = dipthong\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tdipthong.obj\t&\n\t_diptabl.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\tmkdir run\n\tcd run\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\run\\vcs.cfg\n\tupdate\n\tcd..\n\tmkdir art\n\tcd art\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\art\\vcs.cfg\n\tupdate\n\tcd..\n\twmake\n\tcd ..\n\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/DIPTHONG/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = dipthong\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t\tdipthong.obj\t\\\n\t\t\t\t_diptabl.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) \n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n +-dipthong.obj\t&\n+-_diptabl.obj\n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/DIPTHONG/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = dipthong\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tdipthong.obj\t&\n\t_diptabl.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include \n\t copy *.inc $(%WIN32LIB)\\include \n\t copy *.cpp $(%WIN32LIB)\\srcdebug \n\t copy *.asm $(%WIN32LIB)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\tmkdir run\n\tcd run\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\run\\vcs.cfg\n\tupdate\n\tcd..\n\tmkdir art\n\tcd art\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\art\\vcs.cfg\n\tupdate\n\tcd..\n\twmake \n\tcd ..\n\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/DIPTHONG/_DIPTABL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./_diptabl.c 1.11 1994/05/20 15:36:04 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : _DIPTABL.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : July 3, 1991                             *\n *                                                                         *\n *                  Last Update : July 3, 1991   [JLB]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nchar Common[16]={' ','e','t','a','i','n','o','s','r','l','h','c','d','u','p','m'};\n\nchar Dipthong[16][8]={\n\t{'t','a','s','i','o',' ','w','b'},\n\t{' ','r','n','s','d','a','l','m'},\n\t{'h',' ','i','e','o','r','a','s'},\n\t{'n','r','t','l','c',' ','s','y'},\n\t{'n','s','t','c','l','o','e','r'},\n\t{' ','d','t','g','e','s','i','o'},\n\t{'n','r',' ','u','f','m','s','w'},\n\t{' ','t','e','p','.','i','c','a'},\n\t{'e',' ','o','i','a','d','u','r'},\n\t{' ','l','a','e','i','y','o','d'},\n\t{'e','i','a',' ','o','t','r','u'},\n\t{'e','t','o','a','k','h','l','r'},\n\t{' ','e','i','u',',','.','o','a'},\n\t{'n','s','r','c','t','l','a','i'},\n\t{'l','e','o','i','r','a','t','p'},\n\t{'e','a','o','i','p',' ','b','m'},\n};\n\u001a"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/BITBLIT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : BITBLIT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Julio R. Jerez                           *\n;*                                                                         *\n;*                   Start Date : Feb 6, 1995                              *\n;*                                                                         *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nCODESEG\n\n\tPROC\tLinear_Blit_To_Linear C near\n\tUSES\tebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG    \tthis_object :DWORD\t\t; this is a member function\n\tARG\tdest        :DWORD\t\t; what are we blitting to\n\tARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\tARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\tARG\tdest_x0     :dword\n\tARG\tdest_y0     :dword\n\tARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\tARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\tARG\ttrans       :DWORD\t\t\t; do we deal with transparents?\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tLOCAL\tdest_x1 : dword\n\tLOCAL\tdest_y1 : dword\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_ajust_width:DWORD\n        LOCAL\tsource_area :  dword\n        LOCAL\tdest_area :  dword\n\n;This Clipping algorithm is a derivation of the very well known\n;Cohen-Sutherland Line-Clipping test. Due to its simplicity and efficiency\n;it is probably the most commontly implemented algorithm both in software\n;and hardware for clipping lines, rectangles, and convex polygons against\n;a rectagular clipping window. For reference see\n;\"COMPUTER GRAPHICS principles and practice by Foley, Vandam, Feiner, Hughes\n; pages 113 to 177\".\n; Briefly consist in computing the Sutherland code for both end point of\n; the rectangle to find out if the rectangle is:\n; - trivially accepted (no further clipping test, display rectangle)\n; - trivially rejected (return with no action)\n; - retangle must be iteratively clipped again edges of the clipping window\n;   and the remaining retangle is display.\n\n; Clip Source Rectangle against source Window boundaries.\n\tmov  \tesi,[this_object]    ; get ptr to src\n\txor \tecx,ecx\t\t    ; Set sutherland code to zero\n\txor \tedx,edx\t\t    ; Set sutherland code to zero\n\n   ; compute the difference in the X axis and get the bit signs into ecx , edx\n\tmov\tedi,[(GraphicViewPort esi).GVPWidth]  ; get width into register\n\tmov\tebx,[x_pixel]\t    ; Get first end point x_pixel into register\n\tmov\teax,[x_pixel]\t    ; Get second end point x_pixel into register\n\tadd\tebx,[pixel_width]   ; second point x1_pixel = x + width\n\tshld\tecx, eax,1\t    ; the sign bit of x_pixel is sutherland code0 bit4\n\tmov\t[x1_pixel],ebx\t    ; save second for future use\n\tinc\tedi\t\t    ; move the right edge by one unit\n\tshld\tedx,ebx,1\t    ; the sign bit of x1_pixel is sutherland code0 bit4\n\tsub\teax,edi\t\t    ; compute the difference x0_pixel - width\n\tsub\tebx,edi\t\t    ; compute the difference x1_pixel - width\n\tshld\tecx,eax,1\t    ; the sign bit of the difference is sutherland code0 bit3\n\tshld\tedx,ebx,1\t    ; the sign bit of the difference is sutherland code0 bit3\n\n   ; the following code is just a repeticion of the above code\n   ; in the Y axis.\n\tmov\tedi,[(GraphicViewPort esi).GVPHeight] ; get height into register\n\tmov\tebx,[y_pixel]\n\tmov\teax,[y_pixel]\n\tadd\tebx,[pixel_height]\n\tshld\tecx,eax,1\n\tmov\t[y1_pixel ],ebx\n\tinc\tedi\n\tshld\tedx,ebx,1\n\tsub\teax,edi\n\tsub\tebx,edi\n\tshld\tecx,eax,1\n\tshld\tedx,ebx,1\n\n    ; Here we have the to Sutherland code into cl and dl\n\txor\tcl,5\t\t       ; bit 2 and 0 are complented, reverse then\n\txor\tdl,5\t\t       ; bit 2 and 0 are complented, reverse then\n\tmov\tal,cl\t\t       ; save code1 in case we have to clip iteratively\n\ttest\tdl,cl\t\t       ; if any bit in code0 and its counter bit\n\tjnz\t??real_out\t       ; in code1 is set then the rectangle in outside\n\tor\tal,dl\t\t       ; if all bit of code0 the counter bit in\n\tjz\t??clip_against_dest    ; in code1 is set to zero, then all\n\t\t\t\t       ; end points of the rectangle are\n\t\t\t\t       ; inside the clipping window\n\n     ; if we are here the polygon have to be clip iteratively\n\ttest\tcl,1000b\t       ; if bit 4 in code0 is set then\n\tjz\t??scr_left_ok\t       ; x_pixel is smaller than zero\n\tmov\t[x_pixel],0\t       ; set x_pixel to cero.\n\n??scr_left_ok:\n\ttest\tcl,0010b\t       ; if bit 2 in code0 is set then\n\tjz\t??scr_bottom_ok\t       ; y_pixel is smaller than zero\n\tmov\t[ y_pixel ],0\t       ; set y_pixel to cero.\n\n??scr_bottom_ok:\n\ttest\tdl,0100b\t       ; if bit 3 in code1 is set then\n\tjz\t??scr_right_ok\t       ; x1_pixel is greater than the width\n\tmov\teax,[(GraphicViewPort esi).GVPWidth] ; get width into register\n\tmov\t[ x1_pixel ],eax       ; set x1_pixel to width.\n??scr_right_ok:\n\ttest\tdl,0001b\t       ; if bit 0 in code1 is set then\n\tjz\t??clip_against_dest    ; y1_pixel is greater than the width\n\tmov\teax,[(GraphicViewPort esi).GVPHeight]  ; get height into register\n\tmov\t[ y1_pixel ],eax       ; set y1_pixel to height.\n\n; Clip Source Rectangle against destination Window boundaries.\n??clip_against_dest:\n\n   ; build the destination rectangle before clipping\n   ; dest_x1 = dest_x0 + ( x1_pixel - x_pixel )\n   ; dest_y1 = dest_y0 + ( y1_pixel - y_pixel )\n\tmov\teax,[dest_x0]\t     ; get dest_x0 into eax\n\tmov\tebx,[dest_y0]\t     ; get dest_y0 into ebx\n\tsub\teax,[x_pixel]\t     ; subtract x_pixel from eax\n\tsub\tebx,[y_pixel]\t     ; subtract y_pixel from ebx\n\tadd\teax,[x1_pixel]\t     ; add x1_pixel to eax\n\tadd\tebx,[y1_pixel]\t     ; add y1_pixel to ebx\n\tmov\t[dest_x1],eax\t     ; save eax into dest_x1\n\tmov\t[dest_y1],ebx\t     ; save eax into dest_y1\n\n\n  ; The followin code is a repeticion of the Sutherland clipping\n  ; descrived above.\n\tmov  \tesi,[dest]\t    ; get ptr to src\n\txor \tecx,ecx\n\txor \tedx,edx\n\tmov\tedi,[(GraphicViewPort esi).GVPWidth]  ; get width into register\n\tmov\teax,[dest_x0]\n\tmov\tebx,[dest_x1]\n\tshld\tecx,eax,1\n\tinc\tedi\n\tshld\tedx,ebx,1\n\tsub\teax,edi\n\tsub\tebx,edi\n\tshld\tecx,eax,1\n\tshld\tedx,ebx,1\n\n\tmov\tedi,[( GraphicViewPort esi) . GVPHeight ] ; get height into register\n\tmov\teax,[dest_y0]\n\tmov\tebx,[dest_y1]\n\tshld\tecx,eax,1\n\tinc\tedi\n\tshld\tedx,ebx,1\n\tsub\teax,edi\n\tsub\tebx,edi\n\tshld\tecx,eax,1\n\tshld\tedx,ebx,1\n\n\txor\tcl,5\n\txor\tdl,5\n\tmov\tal,cl\n\ttest\tdl,cl\n\tjnz\t??real_out\n\tor\tal,dl\n\tjz\t??do_blit\n\n\ttest\tcl,1000b\n\tjz\t??dest_left_ok\n\tmov\teax,[ dest_x0 ]\n\tmov\t[ dest_x0 ],0\n\tsub\t[ x_pixel ],eax\n\n??dest_left_ok:\n\ttest\tcl,0010b\n\tjz\t??dest_bottom_ok\n\tmov\teax,[ dest_y0 ]\n\tmov\t[ dest_y0 ],0\n\tsub\t[ y_pixel ],eax\n\n\n??dest_bottom_ok:\n\ttest\tdl,0100b\n\tjz\t??dest_right_ok\n\tmov\tebx,[ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\teax,[ dest_x1 ]\n\tmov\t[ dest_x1 ],ebx\n\tsub\teax,ebx\n\tsub\t[ x1_pixel ],eax\n\n??dest_right_ok:\n\ttest\tdl,0001b\n\tjz\t??do_blit\n\tmov\tebx,[ (GraphicViewPort esi) . GVPHeight ]  ; get width into register\n\tmov\teax,[ dest_y1 ]\n\tmov\t[ dest_y1 ],ebx\n\tsub\teax,ebx\n\tsub\t[ y1_pixel ],eax\n\n\n; Here is where\twe do the actual blit\n??do_blit:\n       cld\n       mov\tebx,[this_object]\n       mov\tesi,[(GraphicViewPort ebx).GVPOffset]\n       mov\teax,[(GraphicViewPort ebx).GVPXAdd]\n       add\teax,[(GraphicViewPort ebx).GVPWidth]\n       add\teax,[(GraphicViewPort ebx).GVPPitch]\n       mov\tecx,eax\n       mul\t[y_pixel]\n       add\tesi,[x_pixel]\n       mov\t[source_area],ecx\n       add\tesi,eax\n\n       add\tecx,[x_pixel ]\n       sub\tecx,[x1_pixel ]\n       mov\t[scr_ajust_width ],ecx\n\n       mov\tebx,[dest]\n       mov\tedi,[(GraphicViewPort ebx).GVPOffset]\n       mov\teax,[(GraphicViewPort ebx).GVPXAdd]\n       add\teax,[(GraphicViewPort ebx).GVPWidth]\n       add\teax,[(GraphicViewPort ebx).GVPPitch]\n       mov\tecx,eax\n       mul\t[ dest_y0 ]\n       add\tedi,[ dest_x0 ]\n       mov\t[ dest_area ],ecx\n       add\tedi,eax\n\n       mov\teax,[ dest_x1 ]\n       sub\teax,[ dest_x0 ]\n       jle\t??real_out\n       sub\tecx,eax\n       mov\t[ dest_ajust_width ],ecx\n\n       mov\tedx,[ dest_y1 ]\n       sub\tedx,[ dest_y0 ]\n       jle\t??real_out\n\n       cmp\tesi,edi\n       jz\t??real_out\n       jl\t??backupward_blit\n\n; ********************************************************************\n; Forward bitblit\n\n       test\t[ trans ],1\n       jnz\t??forward_Blit_trans\n\n\n; the inner loop is so efficient that\n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax,10\n       jl\t??forward_loop_bytes\n\n??forward_loop_dword:\n       mov\tecx,edi\n       mov\tebx,eax\n       neg\tecx\n       and\tecx,3\n       sub\tebx,ecx\n       rep\tmovsb\n       mov\tecx,ebx\n       shr\tecx,2\n       rep\tmovsd\n       mov\tecx,ebx\n       and\tecx,3\n       rep\tmovsb\n       add\tesi,[ scr_ajust_width ]\n       add\tedi,[ dest_ajust_width ]\n       dec\tedx\n       jnz\t??forward_loop_dword\n       ret\n\n??forward_loop_bytes:\n       mov\tecx,eax\n       rep\tmovsb\n       add\tesi,[ scr_ajust_width ]\n       add\tedi,[ dest_ajust_width ]\n       dec\tedx\n       jnz\t??forward_loop_bytes\n       ret\n\n??forward_Blit_trans:\n       mov\tecx,eax\n       and\tecx,01fh\n       lea\tecx,[ ecx + ecx * 4 ]\n       neg\tecx\n       shr\teax,5\n       lea\tecx,[ ??transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ],ecx\n\n??forward_loop_trans:\n       mov\tecx,eax\n       jmp\t[ y1_pixel ]\n??forward_trans_line:\n       REPT\t32\n       local\ttransp_pixel\n       \t\tmov\tbl,[ esi ]\n       \t\ttest\tbl,bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ],bl\n    \t    transp_pixel:\n       \t\tinc\tesi\n\t    \tinc\tedi\n\tENDM\n    ??transp_reference:\n       dec\tecx\n       jge\t??forward_trans_line\n       add\tesi,[ scr_ajust_width ]\n       add\tedi,[ dest_ajust_width ]\n       dec\tedx\n       jnz\t??forward_loop_trans\n       ret\n\n\n; ************************************************************************\n; backward bitblit\n\n??backupward_blit:\n\n\tmov\tebx,[ source_area ]\n\tdec\tedx\n\tadd\tesi,eax\n\timul    ebx,edx\n\tstd\n\tlea\tesi,[ esi + ebx - 1 ]\n\n\tmov\tebx,[ dest_area ]\n\tadd\tedi,eax\n\timul    ebx,edx\n\tlea\tedi,[ edi + ebx - 1]\n\n       test\t[ trans ],1\n       jnz\t??backward_Blit_trans\n\n        cmp\teax,15\n        jl\t??backward_loop_bytes\n\n??backward_loop_dword:\n\tpush\tedi\n\tpush\tesi\n\tlea\tecx,[edi+1]\n\tmov\tebx,eax\n\tand\tecx,3\t\t; Get non aligned bytes.\n\tsub\tebx,ecx\t\t; remove that from the total size to be copied later.\n\trep\tmovsb\t\t; do the copy.\n\tsub\tesi,3\n\tmov\tecx,ebx\t\t; Get number of bytes left.\n \tsub\tedi,3\n\tshr\tecx,2\t\t; Do 4 bytes at a time.\n\trep\tmovsd\t\t; do the dword copy.\n\tmov\tecx,ebx\n\tadd\tesi,3\n\tadd\tedi,3\n\tand\tecx,03h\n\trep\tmovsb\t\t; finnish the remaining bytes.\n\tpop\tesi\n\tpop\tedi\n        sub\tesi,[ source_area ]\n        sub\tedi,[ dest_area ]\n\tdec\tedx\n\tjge\t??backward_loop_dword\n\tcld\n\tret\n\n??backward_loop_bytes:\n\tpush\tedi\n\tmov\tecx,eax\t\t; remove that from the total size to be copied later.\n\tpush\tesi\n\trep\tmovsb\t\t; do the copy.\n\tpop\tesi\n\tpop\tedi\n        sub\tesi,[ source_area ]\n        sub\tedi,[ dest_area ]\n\tdec\tedx\n\tjge\t??backward_loop_bytes\n\tcld\n\tret\n\n??backward_Blit_trans:\n       mov\tecx,eax\n       and\tecx,01fh\n       lea\tecx,[ ecx + ecx * 4 ]\n       neg\tecx\n       shr\teax,5\n       lea\tecx,[ ??back_transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ],ecx\n\n??backward_loop_trans:\n       mov\tecx,eax\n       push\tedi\n       push\tesi\n       jmp\t[ y1_pixel ]\n??backward_trans_line:\n       REPT\t32\n       local\ttransp_pixel\n       \t\tmov\tbl,[ esi ]\n       \t\ttest\tbl,bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ],bl\n    \t    transp_pixel:\n       \t\tdec\tesi\n\t    \tdec\tedi\n\tENDM\n    ??back_transp_reference:\n       dec\tecx\n       jge\t??backward_trans_line\n       pop\tesi\n       pop\tedi\n       sub\tesi,[ source_area ]\n       sub\tedi,[ dest_area ]\n       dec\tedx\n       jge\t??backward_loop_trans\n       cld\n       ret\n\n??real_out:\n       ret\n       ENDP\tLinear_Blit_To_Linear\n\n\n\nEND"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/BUFFER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library                  *\n *                                                                         *\n *                    File Name : BUFFER.CPP                               *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 18, 1994                             *\n *                                                                         *\n *                  Last Update : June 1, 1994   [PWG]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   BC::BufferClass -- The default (void) constructor for a buffer class  *\n *   BC::~BufferClass -- The destructor for the buffer class               *\n *   BC::BufferClass -- The standard constructor for a buffer class        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BUFFER_H\n#include \"buffer.h\"\n#endif\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * BC::BufferClass -- The standard constructor for a buffer class          *\n *                                                                         *\n * INPUT:\t\tVOID *\tbuffer to which should be included in buffer class *\n *\t\t\t\t\tLONG\t\tsize of the buffer which we included\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     NONE                                                        *\n *                                                                         *\n * WARNINGS:   If the buffer passed to this function is equal to NULL,     *\n *\t\t\t\t\tthe buffer will be allocated using new.\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\nBufferClass::BufferClass(VOID *buffer, LONG size)\n{\n\tSize\t\t\t= size;\t\t\t\t\t\t\t\t// find size of physical buffer\n\n\tif (buffer) {\t\t\t\t\t\t\t\t\t\t// if buffer is specified\n\t\tBuffer\t\t\t= (BYTE *)buffer;\t\t\t//\t\tpoint to it and mark\n\t\tAllocated\t\t= FALSE;\t\t\t\t\t\t//\t\tit as user allocated\n\t} else {\n\t\tBuffer\t\t\t= new BYTE[Size];\t\t\t// otherwise allocate it and\n\t\tAllocated\t\t= TRUE;\t\t\t\t\t\t//\t\tmark it system alloced\n\t}\n}\n\n/***************************************************************************\n * BC::BufferClass -- constructor for BufferClass with size only    \t\t\t*\n *                                                                         *\n * INPUT:\t\tLONG the size of the buffer that needs to be allocated\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\nBufferClass::BufferClass(LONG size)\n{\n\tSize\t\t\t\t= size;\n\tBuffer\t\t\t= new BYTE[Size];\t\t\t// otherwise allocate it and\n\tAllocated\t\t= TRUE;\t\t\t\t\t\t//\t\tmark it system alloced\n}\n\n/***************************************************************************\n * BC::BufferClass -- The default (void) constructor for a buffer class    *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * NOTES:   \tThe primary function of this class is to be called by a     *\n *\t\t\t\t\tderived class which will fill in the values after the\t\t\t*\n *\t\t\t\t\tfact.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\nBufferClass::BufferClass(VOID)\n{\n\tBuffer\t\t= NULL;\n\tSize\t\t\t= 0;\n\tAllocated\t= FALSE;\n}\n\n/***************************************************************************\n * BC::~BUFFERCLASS -- The destructor for the buffer class                 *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\nBufferClass::~BufferClass(VOID)\n{\n\tif (Allocated) {\n\t\tdelete[] Buffer;\n\t}\n}\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/BUFFER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : GBUFFER.H                                *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 26, 1994                             *\n *                                                                         *\n *                  Last Update : July 5, 1994   [PWG]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   BC::Get_Size -- Returns the buffer size of the BufferClass instance   *\n *   BC::Get_Buffer -- Returns pointer to buffer inherent to BufferClass \t*\n *   BC::BufferClass -- inline constructor for BufferClass with size only  *\n *   BC::To_Page -- Copys a buffer class to a page with definable x, y, w, h*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BUFFER_H\n#define BUFFER_H\n\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\nclass GraphicViewPortClass;\n\n/*=========================================================================*/\n/* BufferClass - A base class which holds buffer information including a\t*/\n/*\t\tpointer and the size of the buffer.\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nclass BufferClass {\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBufferClass(void *ptr, long size);\n\t\tBufferClass(long size);\n\t\tBufferClass();\n\t\t~BufferClass();\n\t\t/*===================================================================*/\n\t\t/* Define functions which work with the buffer class.\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong To_Page(GraphicViewPortClass &view);\n\t\tlong To_Page(int w, int h, GraphicViewPortClass &view);\n\t\tlong To_Page(int x, int y, int w, int h, GraphicViewPortClass &view);\n\n\t\t/*===================================================================*/\n\t\t/* define functions to get at the protected data members\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tvoid\t*Get_Buffer(void);\n\t\tlong\tGet_Size(void);\n\n\tprivate:\n\t\t/*===================================================================*/\n\t\t/* Define the operators we do not want to happen which are the copy\t*/\n\t\t/* and equal constructors.  These are bad because the Allocated flag\t*/\n\t\t/*\tcould be copied and the associated buffer freed.  If this were to\t*/\n\t\t/*\tgappen it could cause weird general protection fault.\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBufferClass(BufferClass const &);\n\t\tBufferClass &operator=(BufferClass const &);\n\n\tprotected:\n\t\tvoid\t*Buffer;\n\t\tlong\tSize;\n\t\tBOOL\tAllocated;\n};\n/***************************************************************************\n * BC::GET_SIZE -- Returns the buffer size of the BufferClass instance     *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long the size of the buffer                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::Get_Size(void)\n{\n\treturn(Size);\n}\n/***************************************************************************\n * BC::GET_BUFFER -- Returns pointer to buffer inherent to BufferClass \t\t*\n *                                                                         *\n * INPUT:\t\t\tnone                                                     *\n *                                                                         *\n * OUTPUT:        void * to the inherent buffer.                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline void *BufferClass::Get_Buffer(void)\n{\n\treturn(Buffer);\n}\n#endif\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/BUFFGLBL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : BUFFGLBL.CPP                             *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : January 10, 1995                         *\n *                                                                         *\n *                  Last Update : January 10, 1995   [PWG]                 *\n *                                                                         *\n * This module holds the global fixup tables for the MCGA buffer class.    *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include \"gbuffer.h\"\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/*=========================================================================*/\n/* Globals required by GraphicBufferClass for function pointers.  These\t\t*/\n/*   pointers will be set to the proper function when set mode is called.\t*/\n/*=========================================================================*/\nBOOL (*GVPC_Blit_to_VVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nBOOL (*GVPC_Scale_To_VVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\n\n#ifdef not_any_more_it_doesnt\n/*=========================================================================*/\n/* Globals required by VideoBufferClass for function pointers.  These\t\t*/\n/*   pointers will be set to the proper function when set mode is called.\t*/\n/*=========================================================================*/\nvoid (*VVPC_Clear_Func)(void *, unsigned char);\nlong (*VVPC_To_Buffer_Func)(void *,int x, int y, int w, int h, void *buff, long size);\nvoid (*VVPC_Put_Pixel_Func)(void *,int x, int y, unsigned char color);\nint  (*VVPC_Get_Pixel_Func)(void *, int x, int y);\nlong (*VVPC_Buffer_To_Page)(int x, int y, int w, int h, void *Buffer, void *view);\nBOOL (*VVPC_Blit_to_GVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nBOOL (*VVPC_Blit_to_VVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nBOOL (*VVPC_Scale_To_GVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\nBOOL (*VVPC_Scale_To_VVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\nLONG (*VVPC_Print_Func)(\t\tvoid *, const char *, int, int, int, int);\nvoid (*VVPC_Draw_Stamp)(void *, void *, int, int, int, void *);\nlong (*VVPC_Size_Of_Region)(void *, int, int);\n\n#endif\t//not_any_more_it_doesnt\n\n/*=========================================================================*/\n/* We need to keep a pointer to the logic page hanging around somewhere\t\t*/\n/*=========================================================================*/\nGraphicViewPortClass\t*LogicPage;\n\nBOOL IconCacheAllowed = TRUE;\n\n/*\n** Pointer to a function we will call if we detect loss of focus\n*/\nvoid (*Gbuffer_Focus_Loss_Function)(void) = NULL;\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/CLEAR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Clear the Full Graphics Buffer\t   *\n;*                                                                         *\n;*                    File Name : CLEAR.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : August 23, 1994   [SKB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   GVPC::Clear -- Clears a virtual viewport instance                     *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nCODESEG\n\n;***************************************************************************\n;* VVPC::CLEAR -- Clears a virtual viewport instance                       *\n;*                                                                         *\n;* INPUT:\tUBYTE the color (optional) to clear the view port to\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* NOTE:\tThis function is optimized to handle viewport with no XAdd *\n;*\t\tvalue.  It also handles DWORD aligning the destination\t   *\n;*\t\twhen speed can be gained by doing it.\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/07/1994 PWG : Created.                                             *\n;*   08/23/1994 SKB : Clear the direction flag to always go forward.       *\n;*=========================================================================*\n\tPROC\tBuffer_Clear C near\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tARG    \tthis_object:DWORD\t\t\t; this is a member function\n\tARG    \tcolor:BYTE\t\t\t\t; what color should we clear to\n\n\tcld \t\t \t\t\t\t; always go forward\n\n\tmov\tebx,[this_object]\t\t\t; get a pointer to viewport\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get the correct offset\n\tmov\tedx,[(GraphicViewPort ebx).GVPHeight]\t; ecx = height of viewport\n\tmov\tesi,[(GraphicViewPort ebx).GVPWidth]\t; edx = width of viewport\n\tpush\t[dword (GraphicViewPort ebx).GVPPitch]\t; extra pitch of direct draw surface\n\tmov\tebx,[(GraphicViewPort ebx).GVPXAdd]\t; esi = add for each line\n\tadd\tebx,[esp]\t\t\t\t; Yes, I know its nasty but\n\tadd\tesp,4\t\t\t\t\t;      it works!\n\n\t;*===================================================================\n\t; Convert the color byte to a DWORD for fast storing\n\t;*===================================================================\n\tmov\tal,[color]\t\t\t\t; get color to clear to\n\tmov\tah,al\t\t\t\t\t; extend across WORD\n\tmov\tecx,eax\t\t\t\t\t; extend across DWORD in\n\tshl\teax,16\t\t\t\t\t;   several steps\n\tmov\tax,cx\n\n\t;*===================================================================\n\t; Find out if we should bother to align the row.\n\t;*===================================================================\n\n\tcmp\tesi , OPTIMAL_BYTE_COPY\t\t\t; is it worth aligning them?\n\tjl\t??byte_by_byte\t\t\t\t;   if not then skip\n\n\t;*===================================================================\n\t; Figure out the alignment offset if there is any\n\t;*===================================================================\n\tpush\tebx\n??dword_aligned_loop:\n       mov\tecx , edi\n       mov\tebx , esi\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tstosb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tstosd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tstosb\n       add\tedi , [ esp ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??dword_aligned_loop\t\t\t\t; if more to do than do it\n       pop\teax\n       ret\n\n\t;*===================================================================\n\t; If not enough bytes to bother aligning copy each line across a byte\n\t;    at a time.\n\t;*===================================================================\n??byte_by_byte:\n\tmov\tecx,esi\t\t\t\t\t; get total width in bytes\n\trep\tstosb\t\t\t\t\t; store the width\n\tadd\tedi,ebx\t\t\t\t\t; handle the xadd\n\tdec\tedx\t\t\t\t\t; decrement the height\n\tjnz\t??byte_by_byte\t\t\t\t; if any left then next line\n??exit:\n\tret\n\tENDP\tBuffer_Clear\nEND"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/DRAWBUFF.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#ifndef DRAWBUFF_H\n#define DRAWBUFF_H\n\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\nclass GraphicViewPortClass;\nclass GraphicBufferClass;\n/*=========================================================================*/\n/* Define functions which have not under-gone name mangling\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern \"C\" {\n\t/*======================================================================*/\n\t/* Externs for all of the common functions between the video buffer\t\t*/\n\t/*\t\tclass and the graphic buffer class.\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\t long __cdecl Buffer_Size_Of_Region(void *thisptr, int w, int h);\n\n\t void\t__cdecl Buffer_Put_Pixel(void * thisptr, int x, int y, unsigned char color);\n\t int\t__cdecl Buffer_Get_Pixel(void * thisptr, int x, int y);\n\t void\t__cdecl Buffer_Clear(void *thisptr, unsigned char color);\n\t long\t__cdecl Buffer_To_Buffer(void *thisptr, int x, int y, int w, int h, void *buff, long size);\n\t long __cdecl Buffer_To_Page(int x, int y, int w, int h, void *Buffer, void *view);\n\t BOOL\t__cdecl Linear_Blit_To_Linear(\tvoid *thisptr, void * dest, int x_pixel, int y_pixel, int dx_pixel,\n\t\t\t \t\t\t\t\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans);\n\t BOOL __cdecl Linear_Scale_To_Linear(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\n\n\t LONG __cdecl Buffer_Print(void *thisptr, const char *str, int x, int y, int fcolor, int bcolor);\n\n\t/*======================================================================*/\n\t/* Externs for all of the graphic buffer class only functions\t\t\t\t*/\n\t/*======================================================================*/\n\t VOID __cdecl Buffer_Draw_Line(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color);\n\t VOID __cdecl Buffer_Fill_Rect(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color);\n\t VOID __cdecl Buffer_Remap(void * thisptr, int sx, int sy, int width, int height, void *remap);\n\t VOID __cdecl Buffer_Fill_Quad(void * thisptr, VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\t \tint x2, int y2, int x3, int y3, int color);\n\t void __cdecl Buffer_Draw_Stamp(void const *thisptr, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap);\n\t void __cdecl Buffer_Draw_Stamp_Clip(void const *thisptr, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int ,int,int,int);\n\t void * __cdecl Get_Font_Palette_Ptr ( void );\n}\n\nextern GraphicViewPortClass *LogicPage;\nextern BOOL AllowHardwareBlitFills;\n#endif\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/DRAWBUFF.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : DRAWBUFF.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 16, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n; Externs from REGIONSZ.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Size_Of_Region\t:NEAR\n\n; Externs from GETPIX.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Get_Pixel          \t:NEAR\n\n; Externs from PUTPIX.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Put_Pixel \t\t:NEAR\n\n; Externs from CLEAR.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Clear\t          \t:NEAR\n\n; Externs from BITBLIT.ASM module of the DRAWBUFF library\nGLOBAL C Linear_Blit_To_Linear\t\t:NEAR\n\n; Externs from TOBUFF.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_To_Buffer\t\t:NEAR\n\n; Externs from TOPAGE.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_To_Page\t\t:NEAR\n\n; Externs from SCALE.ASM module of the DRAWBUFF library\nGLOBAL C Linear_Scale_To_Linear \t:NEAR\n\n; Externs from TXTPRNT.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Print\t\t\t:NEAR\n\n\n;*-------------------------------------------------------------------------*\n;* Define Buffer only assembly GLOBALS\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n\n; Externs from DRAWLINE.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Draw_Line:NEAR\n\n; Externs from FILLQUAD.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Fill_Quad \t\t:NEAR\n\n; Externs from FILLRECT.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Fill_Rect \t\t:NEAR\n\n; Externs from REMAP.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Remap      \t\t:NEAR\n\n; Externs from STAMP.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Draw_Stamp \t\t:NEAR\n\nGLOBAL C get_clip\t \t   : NEAR\n\nstruc  RECTANGLE\n\t\t  x0\tdd\t?\n\t\t  y0 dd\t?\n\t\t  x1\tdd\t?\n\t\t  y1 dd ?\nends \t RECTANGLE\n\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/DRAWLINE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : DRAWLINE.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 16, 1994                            *\n;*                                                                         *\n;*                  Last Update : August 30, 1994   [IML]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVC::Scale -- Scales a virtual viewport to another virtual viewport   *\n;*   Normal_Draw -- jump loc for drawing  scaled line of normal pixel      *\n;*   __DRAW_LINE -- Assembly routine to draw a line                        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n\n\n;***************************************************************************\n;* VVC::DRAW_LINE -- Scales a virtual viewport to another virtual viewport *\n;*                                                                         *\n;* INPUT:\tWORD sx_pixel \t- the starting x pixel position\t\t   *\n;*\t\tWORD sy_pixel\t- the starting y pixel position\t\t   *\n;*\t\tWORD dx_pixel\t- the destination x pixel position\t   *\n;*\t\tWORD dy_pixel   - the destination y pixel position\t   *\n;*\t\tWORD color      - the color of the line to draw\t\t   *\n;*                                                                         *\n;* Bounds Checking: Compares sx_pixel, sy_pixel, dx_pixel and dy_pixel\t   *\n;*       with the graphic viewport it has been assigned to.\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/16/1994 PWG : Created.                                             *\n;*   08/30/1994 IML : Fixed clipping bug.\t\t\t\t   *\n;*=========================================================================*\n\tPROC\tBuffer_Draw_Line C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\t;*==================================================================\n\t;* Define the arguements that the function takes.\n\t;*==================================================================\n\tARG\tthis_object:DWORD\t; associated graphic view port\n\tARG\tx1_pixel:DWORD\t\t; the start x pixel position\n\tARG\ty1_pixel:DWORD\t\t; the start y pixel position\n\tARG\tx2_pixel:DWORD\t\t; the dest x pixel position\n\tARG\ty2_pixel:DWORD\t\t; the dest y pixel position\n\tARG\tcolor:DWORD\t\t; the color we are drawing\n\n\t;*==================================================================\n\t;* Define the local variables that we will use on the stack\n\t;*==================================================================\n\tLOCAL\tclip_min_x:DWORD\n\tLOCAL\tclip_max_x:DWORD\n\tLOCAL\tclip_min_y:DWORD\n\tLOCAL\tclip_max_y:DWORD\n\tLOCAL\tclip_var:DWORD\n\tLOCAL\taccum:DWORD\n\tLOCAL\tbpr:DWORD\n\n\t;*==================================================================\n\t;* Take care of find the clip minimum and maximums\n\t;*==================================================================\n\tmov\tebx,[this_object]\n\txor\teax,eax\n\tmov\t[clip_min_x],eax\n\tmov\t[clip_min_y],eax\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\n\tmov\t[clip_max_x],eax\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\n\tadd\teax,[(GraphicViewPort ebx).GVPPitch]\n\tmov\t[bpr],eax\n\tmov\teax,[(GraphicViewPort ebx).GVPHeight]\n\tmov\t[clip_max_y],eax\n\n\t;*==================================================================\n\t;* Adjust max pixels as they are tested inclusively.\n\t;*==================================================================\n\tdec\t[clip_max_x]\n\tdec\t[clip_max_y]\n\n\t;*==================================================================\n\t;* Set the registers with the data for drawing the line\n\t;*==================================================================\n\tmov\teax,[x1_pixel]\t\t; eax = start x pixel position\n\tmov\tebx,[y1_pixel]\t\t; ebx = start y pixel position\n\tmov\tecx,[x2_pixel]\t\t; ecx = dest x pixel position\n\tmov\tedx,[y2_pixel]\t\t; edx = dest y pixel position\n\n\t;*==================================================================\n\t;* This is the section that \"pushes\" the line into bounds.\n\t;* I have marked the section with PORTABLE start and end to signify\n\t;* how much of this routine is 100% portable between graphics modes.\n\t;* It was just as easy to have variables as it would be for constants\n\t;* so the global vars ClipMaxX,ClipMinY,ClipMaxX,ClipMinY are used\n\t;* to clip the line (default is the screen)\n\t;* PORTABLE start\n\t;*==================================================================\n\n\tcmp\teax,[clip_min_x]\n\tjl\tshort ??clip_it\n\tcmp\teax,[clip_max_x]\n\tjg\tshort ??clip_it\n\tcmp\tebx,[clip_min_y]\n\tjl\tshort ??clip_it\n\tcmp\tebx,[clip_max_y]\n\tjg\tshort ??clip_it\n\tcmp\tecx,[clip_min_x]\n\tjl\tshort ??clip_it\n\tcmp\tecx,[clip_max_x]\n\tjg\tshort ??clip_it\n\tcmp\tedx,[clip_min_y]\n\tjl\tshort ??clip_it\n\tcmp\tedx,[clip_max_y]\n\tjle\tshort ??on_screen\n\n\t;*==================================================================\n\t;* Takes care off clipping the line.\n\t;*==================================================================\n??clip_it:\n\tcall\tNEAR PTR ??set_bits\n\txchg\teax,ecx\n\txchg\tebx,edx\n\tmov\tedi,esi\n\tcall\tNEAR PTR ??set_bits\n\tmov\t[clip_var],edi\n\tor\t[clip_var],esi\n\tjz\tshort ??on_screen\n\ttest\tedi,esi\n\tjne\tshort ??off_screen\n\tshl\tesi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+esi]\n\tjc\t??clip_it\n\txchg\teax,ecx\n\txchg\tebx,edx\n\tshl\tedi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+edi]\n\tjmp\t??clip_it\n\n??on_screen:\n\tjmp\t??draw_it\n\n??off_screen:\n\tjmp\t??out\n\n\t;*==================================================================\n\t;* Jump table for clipping conditions\n\t;*==================================================================\n??clip_tbl\tDD\t??nada,??a_up,??a_dwn,??nada\n\t\tDD\t??a_lft,??a_lft,??a_dwn,??nada\n\t\tDD\t??a_rgt,??a_up,??a_rgt,??nada\n\t\tDD\t??nada,??nada,??nada,??nada\n\n??nada:\n\tclc\n\tretn\n\n??a_up:\n\tmov\tesi,[clip_min_y]\n\tcall\tNEAR PTR ??clip_vert\n\tstc\n\tretn\n\n??a_dwn:\n\tmov\tesi,[clip_max_y]\n\tneg\tesi\n\tneg\tebx\n\tneg\tedx\n\tcall\tNEAR PTR ??clip_vert\n\tneg\tebx\n\tneg\tedx\n\tstc\n\tretn\n\n\t;*==================================================================\n\t;* xa'=xa+[(miny-ya)(xb-xa)/(yb-ya)]\n\t;*==================================================================\n??clip_vert:\n\tpush\tedx\n\tpush\teax\n\tmov\t[clip_var],edx\t\t; clip_var = yb\n\tsub\t[clip_var],ebx\t\t; clip_var = (yb-ya)\n\tneg\teax\t\t\t; eax=-xa\n\tadd\teax,ecx\t\t\t; (ebx-xa)\n\tmov\tedx,esi\t\t\t; edx=miny\n\tsub\tedx,ebx\t\t\t; edx=(miny-ya)\n\timul\tedx\n\tidiv\t[clip_var]\n\tpop\tedx\n\tadd\teax,edx\n\tpop\tedx\n\tmov\tebx,esi\n\tretn\n\n??a_lft:\n\tmov\tesi,[clip_min_x]\n\tcall\tNEAR PTR ??clip_horiz\n\tstc\n\tretn\n\n??a_rgt:\n\tmov\tesi,[clip_max_x]\n\tneg\teax\n\tneg\tecx\n\tneg\tesi\n\tcall\tNEAR PTR ??clip_horiz\n\tneg\teax\n\tneg\tecx\n\tstc\n\tretn\n\n\t;*==================================================================\n\t;* ya'=ya+[(minx-xa)(yb-ya)/(xb-xa)]\n\t;*==================================================================\n??clip_horiz:\n\tpush\tedx\n\tmov\t[clip_var],ecx\t\t; clip_var = xb\n\tsub\t[clip_var],eax\t\t; clip_var = (xb-xa)\n\tsub\tedx,ebx\t\t\t; edx = (yb-ya)\n\tneg\teax\t\t\t; eax = -xa\n\tadd\teax,esi\t\t\t; eax = (minx-xa)\n\timul\tedx\t\t\t; eax = (minx-xa)(yb-ya)\n\tidiv\t[clip_var]\t\t; eax = (minx-xa)(yb-ya)/(xb-xa)\n\tadd\tebx,eax\t\t\t; ebx = xa+[(minx-xa)(yb-ya)/(xb-xa)]\n\tpop\tedx\n\tmov\teax,esi\n\tretn\n\n\t;*==================================================================\n\t;* Sets the condition bits\n\t;*==================================================================\n??set_bits:\n\txor\tesi,esi\n\tcmp\tebx,[clip_min_y]\t; if y >= top its not up\n\tjge\tshort ??a_not_up\n\tor\tesi,1\n\n??a_not_up:\n\tcmp\tebx,[clip_max_y]\t; if y <= bottom its not down\n\tjle\tshort ??a_not_down\n\tor\tesi,2\n\n??a_not_down:\n\tcmp\teax,[clip_min_x]   \t; if x >= left its not left\n\tjge\tshort ??a_not_left\n\tor\tesi,4\n\n??a_not_left:\n\tcmp\teax,[clip_max_x]\t; if x <= right its not right\n\tjle\tshort ??a_not_right\n\tor\tesi,8\n\n??a_not_right:\n\tretn\n\n\t;*==================================================================\n\t;* Draw the line to the screen.\n\t;* PORTABLE end\n\t;*==================================================================\n??draw_it:\n\tsub\tedx,ebx\t\t\t; see if line is being draw down\n\tjnz\tshort ??not_hline\t; if not then its not a hline\n\tjmp\tshort ??hline\t\t; do special case h line\n\n??not_hline:\n\tjg\tshort ??down\t\t; if so there is no need to rev it\n\tneg\tedx\t\t\t; negate for actual pixel length\n\txchg\teax,ecx\t\t\t; swap x's to rev line draw\n\tsub\tebx,edx\t\t\t; get old edx\n\n??down:\n\tpush\tedx\n\tpush\teax\n\tmov\teax,[bpr]\n\tmul\tebx\n\tmov\tebx,eax\n\tmov\teax,[this_object]\n\tadd\tebx,[(GraphicViewPort eax).GVPOffset]\n\tpop\teax\n\tpop\tedx\n\n\tmov\tesi,1\t\t\t; assume a right mover\n\tsub\tecx,eax\t\t\t; see if line is right\n\tjnz\tshort ??not_vline\t; see if its a vertical line\n\tjmp\t??vline\n\n??not_vline:\n\tjg\tshort ??right\t\t; if so, the difference = length\n\n??left:\n\tneg\tecx\t\t\t; else negate for actual pixel length\n\tneg\tesi\t\t\t; negate counter to move left\n\n??right:\n\tcmp\tecx,edx\t\t\t; is it a horiz or vert line\n\tjge\tshort ??horiz\t\t; if ecx > edx then |x|>|y| or horiz\n\n??vert:\n\txchg\tecx,edx\t\t\t; make ecx greater and edx lesser\n\tmov\tedi,ecx\t\t\t; set greater\n\tmov\t[accum],ecx\t\t; set accumulator to 1/2 greater\n\tshr\t[accum],1\n\n\t;*==================================================================\n\t;* at this point ...\n\t;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;\n\t;* esi=adder; accum=accumulator\n\t;* in a vertical loop the adder is conditional and the inc constant\n\t;*==================================================================\n??vert_loop:\n\tadd\tebx,eax\n\tmov\teax,[color]\n\n??v_midloop:\n\tmov\t[ebx],al\n\tdec\tecx\n\tjl\t??out\n\tadd\tebx,[bpr]\n\tsub\t[accum],edx\t\t; sub the lesser\n\tjge\t??v_midloop\t\t; any line could be new\n\tadd\t[accum],edi\t\t; add greater for new accum\n\tadd\tebx,esi\t\t\t; next pixel over\n\tjmp\t??v_midloop\n\n??horiz:\n\tmov\tedi,ecx\t\t\t; set greater\n\tmov\t[accum],ecx\t\t; set accumulator to 1/2 greater\n\tshr\t[accum],1\n\n\t;*==================================================================\n\t;* at this point ...\n\t;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;\n\t;* esi=adder; accum=accumulator\n\t;* in a vertical loop the adder is conditional and the inc constant\n\t;*==================================================================\n??horiz_loop:\n\tadd\tebx,eax\n\tmov\teax,[color]\n\n??h_midloop:\n\tmov\t[ebx],al\n\tdec\tecx\t\t\t\t; dec counter\n\tjl\t??out\t\t\t\t; end of line\n\tadd\tebx,esi\n\tsub     [accum],edx\t\t\t; sub the lesser\n\tjge\t??h_midloop\n\tadd\t[accum],edi\t\t\t; add greater for new accum\n\tadd\tebx,[bpr]\t\t\t; goto next line\n\tjmp\t??h_midloop\n\n\t;*==================================================================\n\t;* Special case routine for horizontal line draws\n\t;*==================================================================\n??hline:\n\tcmp\teax,ecx\t\t\t; make eax < ecx\n\tjl\tshort ??hl_ac\n\txchg\teax,ecx\n\n??hl_ac:\n\tsub\tecx,eax\t\t\t; get len\n\tinc\tecx\n\n\tpush\tedx\n\tpush\teax\n\tmov\teax,[bpr]\n\tmul\tebx\n\tmov\tebx,eax\n\tmov\teax,[this_object]\n\tadd\tebx,[(GraphicViewPort eax).GVPOffset]\n\tpop\teax\n\tpop\tedx\n\tadd\tebx,eax\n\tmov\tedi,ebx\n\tcmp\tecx,15\n\tjg\t??big_line\n\tmov\tal,[byte color]\n\trep\tstosb\t\t\t; write as many words as possible\n\tjmp\tshort ??out\t\t; get outt\n\n\n??big_line:\n\tmov\tal,[byte color]\n\tmov\tah,al\n\tmov     ebx,eax\n\tshl\teax,16\n\tmov\tax,bx\n\ttest\tedi,3\n\tjz\t??aligned\n\tmov\t[edi],al\n\tinc\tedi\n\tdec\tecx\n\ttest\tedi,3\n\tjz\t??aligned\n\tmov\t[edi],al\n\tinc\tedi\n\tdec\tecx\n\ttest\tedi,3\n\tjz\t??aligned\n\tmov\t[edi],al\n\tinc\tedi\n\tdec\tecx\n\n??aligned:\n\tmov\tebx,ecx\n\tshr\tecx,2\n\trep\tstosd\n\tmov\tecx,ebx\n\tand\tecx,3\n\trep\tstosb\n\tjmp\t??out\n\n\n\t;*==================================================================\n\t;* a special case routine for vertical line draws\n\t;*==================================================================\n??vline:\n\tmov\tecx,edx\t\t\t; get length of line to draw\n\tinc\tecx\n\tadd\tebx,eax\n\tmov\teax,[color]\n\n??vl_loop:\n\tmov\t[ebx],al\t\t; store bit\n\tadd\tebx,[bpr]\n\tdec\tecx\n\tjnz\t??vl_loop\n\n??out:\n\tret\n\tENDP\tBuffer_Draw_Line\n\n\nEND\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/DRAWRECT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : DRAWRECT.C                               *\n *                                                                         *\n *                   Programmer : Christopher Yates                        *\n *                                                                         *\n *                  Last Update : August 20, 1993   [JLB]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Draw_Rect -- Draws a rectangle to the LogicPage.                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"gbuffer.h\"\n\n/***************************************************************************\n * Draw_Rect -- Draws a rectangle to the LogicPage.                        *\n *                                                                         *\n *    This routine will draw a rectangle to the LogicPage.  The rectangle  *\n *    doesn't have to be aligned on the vertical or horizontal axis.  In   *\n *    fact, it doesn't even have to be a rectangle.  The \"square\" can be   *\n *    skewed.                                                              *\n *                                                                         *\n * INPUT:   x1_pixel, y1_pixel   -- One corner.                            *\n *                                                                         *\n *          x2_pixel, y2_pixel   -- The other corner.                      *\n *                                                                         *\n *          color                -- The color to draw the lines.           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   None, but the rectangle will be clipped to the current      *\n *             draw line clipping rectangle.                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/20/1993 JLB : Created.                                             *\n *=========================================================================*/\nVOID GraphicViewPortClass::Draw_Rect(int x1_pixel, int y1_pixel, int x2_pixel, int y2_pixel, unsigned char color)\n{\n\tLock();\n\tDraw_Line(x1_pixel, y1_pixel, x2_pixel, y1_pixel, color);\n\tDraw_Line(x1_pixel, y2_pixel, x2_pixel, y2_pixel, color);\n\tDraw_Line(x1_pixel, y1_pixel, x1_pixel, y2_pixel, color);\n\tDraw_Line(x2_pixel, y1_pixel, x2_pixel, y2_pixel, color);\n\tUnlock();\n}\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/FILLQUAD.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : FILLQUAD.ASM                             *\n;*                                                                         *\n;*                   Programmer : Ian M. Leslie                            *\n;*                                                                         *\n;*                   Start Date : August 11, 1994                          *\n;*                                                                         *\n;*                  Last Update : August 30, 1994   [IML]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:\t\t\t\t\t\t\t\t   *\n;*\tFill_Quad -- Flood fills an arbitrary convex quadrilateral\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nSLOT_VACANT\tEQU\t80008000h\nNULL\t\tEQU\t0h\n\n\nCODESEG\n\n;***************************************************************************\n;* VVC::FILL_QUAD -- Flood fills an arbitrary convex quadrilateral\t   *\n;*                                                                         *\n;* INPUT:      \tDWORD this_object\t- associated graphic viewport\t\t   *\n;*\t\tDWORD span_buff - pointer to span array\t\t\t   *\n;*\t\tDWORD x0_pixel \t- the zeroth x pixel position\t\t   *\n;*\t       \tDWORD y0_pixel\t- the zeroth y pixel position\t\t   *\n;*\t       \tDWORD x1_pixel\t- the first x pixel position\t\t   *\n;*\t       \tDWORD y1_pixel  - the first y pixel position\t\t   *\n;*\t       \tDWORD x2_pixel\t- the second x pixel position\t\t   *\n;*\t       \tDWORD y2_pixel\t- the second y pixel position\t\t   *\n;*\t       \tDWORD x3_pixel\t- the third x pixel position\t\t   *\n;*\t       \tDWORD y3_pixel\t- the third y pixel position\t\t   *\n;*\t\tDWORD color     - the color of the quad to fill\t\t   *\n;*                                                                         *\n;* Bounds Checking: Compares quad points with the graphic viewport it \t   *\n;*\t\t    has been assigned to.\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* Rasterization Rules: FILL_QUAD is designed to be used within a quad\t   *\n;*\t\t\tmesh. There is no pixel overlapping or stitching   *\n;*\t\t\teffects at shared borders. FILL_QUAD is NOT\t   *\n;*                      recommended for isolated quads.                    *                                *\n;* HISTORY:                                                                *\n;*   08/11/1994 IML : Created.\t\t\t\t\t\t   *\n;*   08/26/1994 IML : Various optimizations.\t\t\t\t   *\n;*   08/30/1994 IML : Added rasterization rules for shared borders.\t   *\n;*=========================================================================*\n\tPROC\tBuffer_Fill_Quad C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\n\t;*==================================================================\n\t;* Define the arguments that the function takes.\n\t;*==================================================================\n\tARG\tthis_object:DWORD\t\t; associated graphic viewport\n\tARG\tspan_buff:DWORD\t\t; pointer to span array\n\tARG\tx0_pixel:DWORD\t\t; the zeroth x pixel position\n\tARG\ty0_pixel:DWORD\t\t; the zeroth y pixel position\n\tARG\tx1_pixel:DWORD\t\t; the first x pixel position\n\tARG\ty1_pixel:DWORD\t\t; the first y pixel position\n\tARG\tx2_pixel:DWORD\t\t; the second x pixel position\n\tARG\ty2_pixel:DWORD\t\t; the second y pixel position\n\tARG\tx3_pixel:DWORD\t\t; the third x pixel position\n\tARG\ty3_pixel:DWORD\t\t; the third y pixel position\n\tARG\tcolor:DWORD\t\t; the color of the quad\n\n\n\t;*==================================================================\n\t;* Define the local variables that we will use on the stack.\n\t;*==================================================================\n\tLOCAL\tclip_min_x:DWORD\t; boundary of viewport\n\tLOCAL\tclip_max_x:DWORD\t;\n\tLOCAL\tclip_min_y:DWORD\t;\n\tLOCAL\tclip_max_y:DWORD\t;\n\tLOCAL\tclip_var:DWORD\n\tLOCAL\tleft_clip_base:DWORD:2\t; storage for additional edges\n\tLOCAL\tleft_clip_index:DWORD\t;   generated by clipping\n\tLOCAL\tright_clip_base:DWORD:2\t;\n\tLOCAL\tright_clip_index:DWORD\t;\n\tLOCAL\tscanline_min:DWORD\t; vertical extent of quad\n\tLOCAL\tscanline_max:DWORD\n\tLOCAL\trealignment:DWORD\n\tLOCAL\tbpr:DWORD\t\t; bytes per row of associated buffer\n\n\n\t;*==================================================================\n\t;* Extract essential GraphicViewPort info.\n\t;*==================================================================\n\tmov\tebx,[this_object]\n\tmov\teax,[(GraphicViewPort ebx).GVPXPos]\n\tmov\t[clip_min_x],eax\n\tmov\teax,[(GraphicViewPort ebx).GVPYPos]\n\tmov\t[clip_min_y],eax\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\n\tmov\t[clip_max_x],eax\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\n\tadd\teax,[(GraphicViewPort ebx).GVPPitch]\n\tmov\t[bpr],eax\n\tmov\teax,[(GraphicViewPort ebx).GVPHeight]\n\tmov\t[clip_max_y],eax\n\n\n\t;*==================================================================\n\t;* Adjust top and right edges of viewport for rasterization rules.\n\t;*==================================================================\n\tdec\t[clip_max_y]\n\tdec\t[clip_min_y]\n\n\n\t;*==================================================================\n\t;* Find the vertical extent of the quad BEFORE clipping.\n\t;* y0_pixel = y0, y1_pixel = y1, y2_pixel = y2, y3_pixel = y3\n\t;*==================================================================\n\tmov\teax,[y0_pixel]\n\tcmp\teax,[y1_pixel]\n\tjle\tshort ??y1_not_smaller\n\tmov\teax,[y1_pixel]\n\n??y1_not_smaller:\n\tcmp\teax,[y2_pixel]\n\tjle\tshort ??y2_not_smaller\n\tmov\teax,[y2_pixel]\n\n??y2_not_smaller:\n\tcmp\teax,[y3_pixel]\n\tjle\tshort ??y3_not_smaller\n\tmov\teax,[y3_pixel]\n\n??y3_not_smaller:\n\tcmp\teax,[clip_min_y]\n\tjge\tshort ??no_clamp_min_min\n\tmov\teax,[clip_min_y]\n\n??no_clamp_min_min:\n\tcmp\teax,[clip_max_y]\n\tjle\tshort ??no_clamp_max_min\n\tmov\teax,[clip_max_y]\n\t\t\t\t\t; scanline_min = MIN (y0, y1, y2, y3)\n??no_clamp_max_min:\t\t\t; scanline_min = MAX (scanline_min, clip_min_y)\n\tmov\t[scanline_min],eax\t; scanline_min = MIN (scanline_min, clip_max_y)\n\n\tmov\teax,[y0_pixel]\n\tcmp\teax,[y1_pixel]\n\tjge\tshort ??y1_not_greater\n\tmov\teax,[y1_pixel]\n\n??y1_not_greater:\n\tcmp\teax,[y2_pixel]\n\tjge\tshort ??y2_not_greater\n\tmov\teax,[y2_pixel]\n\n??y2_not_greater:\n\tcmp\teax,[y3_pixel]\n\tjge\tshort ??y3_not_greater\n\tmov\teax,[y3_pixel]\n\n??y3_not_greater:\n\tcmp\teax,[clip_min_y]\n\tjge\tshort ??no_clamp_min_max\n\tmov\teax,[clip_min_y]\n\n??no_clamp_min_max:\n\tcmp\teax,[clip_max_y]\n\tjle\tshort ??no_clamp_max_max\n\tmov\teax,[clip_max_y]\n\t\t\t\t\t; scanline_max = MAX (y0, y1, y2, y3)\n??no_clamp_max_max:\t\t\t; scanline_max = MAX (scanline_max, clip_min_y)\n\tmov\t[scanline_max],eax\t; scanline_max = MIN (scanline_max, clip_max_y)\n\n\n\t;*==================================================================\n\t;* Initialize memory for spans.\n\t;*==================================================================\n\tsub\teax,[scanline_min]\n\tje\t??abort_fill_quad\t; don't render quads with zero height\n\tmov\tebx,eax\n\tmov\teax,[span_buff]\t\t; check span_buff for NULL ptr\n\tcmp\teax,NULL\n\tje\t??abort_fill_quad\n\tsal\tebx,2\n\n??span_initialize_loop:\n\tmov\t[DWORD PTR eax + ebx],SLOT_VACANT\n\tsub\tebx,4\n\tjl\tshort ??exit_span_initialize\n\tmov\t[DWORD PTR eax + ebx],SLOT_VACANT\n\tsub\tebx,4\n     \tjl\tshort ??exit_span_initialize\n\tmov\t[DWORD PTR eax + ebx],SLOT_VACANT\n\tsub\tebx,4\n     \tjl\tshort ??exit_span_initialize\n\tmov\t[DWORD PTR eax + ebx],SLOT_VACANT\n\tsub\tebx,4\n\tjge\tshort ??span_initialize_loop\n\n\n\t;*==================================================================\n\t;* Clip and scan convert the four edges defining the quad.\n\t;*==================================================================\n??exit_span_initialize:\n\tmov\t[left_clip_index],0\n\tmov\t[right_clip_index],0\n\n\tmov\teax,[x0_pixel]\n\tmov\tebx,[y0_pixel]\n\tmov\tecx,[x1_pixel]\n\tmov\tedx,[y1_pixel]\n\tcall\tNEAR PTR ??clip_and_scan_convert\n\tmov\teax,[x1_pixel]\n\tmov\tebx,[y1_pixel]\n\tmov\tecx,[x2_pixel]\n\tmov\tedx,[y2_pixel]\n\tcall\tNEAR PTR ??clip_and_scan_convert\n\tmov\teax,[x2_pixel]\n\tmov\tebx,[y2_pixel]\n\tmov\tecx,[x3_pixel]\n\tmov\tedx,[y3_pixel]\n\tcall\tNEAR PTR ??clip_and_scan_convert\n\tmov\teax,[x3_pixel]\n\tmov\tebx,[y3_pixel]\n\tmov\tecx,[x0_pixel]\n\tmov\tedx,[y0_pixel]\n\tcall\tNEAR PTR ??clip_and_scan_convert\n\n\n\t;*==================================================================\n\t;* Scan convert up to 2 additional left and right vertical edges\n\t;* generated by the clipping process.\n\t;*==================================================================\n\tcmp\t[left_clip_index],0\n\tje\tshort ??no_left_edge\n\tmov\teax,[clip_min_x]\n\tmov\tebx,[left_clip_base]\n\tmov\tecx,eax\n\tmov\tedx,[left_clip_base + 4]\n\tcall\tNEAR PTR ??scan_convert\n\n??no_left_edge:\n\tcmp\t[right_clip_index],0\n\tje\tshort ??no_right_edge\n\tmov\teax,[clip_max_x]\n\tmov\tebx,[right_clip_base]\n\tmov\tecx,eax\n\tmov\tedx,[right_clip_base + 4]\n\tcall\tNEAR PTR ??scan_convert\n\n\n\t;*==================================================================\n\t;* Fill the quad with specified color. Use DWORD copies where\n\t;* appropriate.\n\t;*==================================================================\n??no_right_edge:\n\tmov\teax,[this_object]\n\tmov\tedi,[(GraphicViewPort eax).GVPOffset]\n\tmov\teax,[scanline_min]\t\t; eax = scanline_min\n\n\tmov\tebx,[scanline_max]\n\tsub\tebx,[scanline_min]\t\t; ebx = span count\n\n\tmov\tesi,[span_buff]\t\t\t; esi = address of top span\n\n\tmul\t[bpr]\n\tadd\tedi,eax\t\t\t\t; edi = address of top scanline\n\t\t\t\t\t\t;  containing quad\n\tmov\tal,[BYTE PTR color]\t\t; extend pixel color into eax ready\n\tmov\tah,al\t\t\t\t;   for DWORD copies\n\tmov\tedx,eax\n\tshl\teax,16\n\tmov\tax,dx\n\n\tcld\t\t\t\t\t; only fill forwards\n\n\tjmp\t??skip_span\t\t\t; rasterization rule: don't\n\t\t\t\t\t\t;   render topmost span\n\n??quad_fill_loop:\n\tcmp\t[DWORD PTR esi],SLOT_VACANT\t; test for unused spans\tdue to clipping\n\tje\t??skip_span\n\txor\tecx,ecx\n\txor\tedx,edx\n\tmov\tcx,[WORD PTR esi]\n\tmov\tdx,[WORD PTR esi + 2]\n\tsub\tecx,edx\n\tpush\tedi\n\tjns\tshort ??not_negative_count\n\tadd\tedi,ecx\n\tneg\tecx\t\t\t\t; ecx = span width\n\n??not_negative_count:\n\tadd\tedi,edx\t\t\t\t; edi = address of start of span\n\tcmp\tecx,OPTIMAL_BYTE_COPY\t\t; does span width justify DWORD copies?\n\tjl\tshort ??byte_copy\n\tmov\tedx,ecx\n\tmov\tecx,edi\n\tand\tecx,3\t\t\t\t; if (ecx == 0) edi is already\n\tjz\tshort ??dword_copy_no_alignment\t;   DWORD aligned\n\txor\tecx,3\n\tinc\tecx\t\t\t\t; ecx = number of pixels before alignment\n\tsub\tedx,ecx\n\trep\tstosb\n\n??dword_copy_no_alignment:\n\tmov\tecx,edx\t\t\t\t; ecx = remaining pixels on span\n\tshr\tecx,2\t\t\t\t; copy (ecx / 4) DWORDS\n\trep\tstosd\n\tmov\tecx,edx\n\tand\tecx,3\t\t\t\t; ecx = remaining pixels on span\n\n??byte_copy:\n\trep\tstosb\t\t\t\t; byte copy remaining pixels on span\n\tpop\tedi\n\n??skip_span:\n\tadd\tedi,[bpr]\t\t\t; edi = address of start of next scanline\n\tadd\tesi,4\t\t\t\t; esi = address of next span\n\tdec\tebx\n\tjge\tshort ??quad_fill_loop\t\t; is span count >= 0?\n\n??abort_fill_quad:\n\tret\n\n\n\t;*==================================================================\n\t;* This is the section that \"pushes\" the edge into bounds.\n\t;* I have marked the section with PORTABLE start and end to signify\n\t;* how much of this routine is 100% portable between graphics modes.\n\t;* It was just as easy to have variables as it would be for constants\n\t;* so the global vars clip_min_x, clip_min_y, clip_max_x, clip_max_y\n\t;* are used to clip the edge (default is the screen).\n\t;* PORTABLE start.\n\t;*==================================================================\n\n\n\t;*==================================================================\n\t;* Clip an edge against the viewport.\n\t;*==================================================================\n??clip_and_scan_convert:\n\tcall\tNEAR PTR ??set_left_right_bits\n\txchg\teax,ecx\n\txchg\tebx,edx\n\tmov\tedi,esi\n\tcall\tNEAR PTR ??set_left_right_bits\n\tmov\t[clip_var],edi\n\tor\t[clip_var],esi\n\tjz\t??clip_up_down\t\t\t; trivial acceptance?\n\ttest\tedi,esi\n\tjne\t??exit\t\t\t\t; trivial rejection?\n\tshl\tesi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+esi]\n\txchg\teax,ecx\n\txchg\tebx,edx\n\tshl\tedi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+edi]\n\n??clip_up_down:\n\tcall\tNEAR PTR ??set_up_down_bits\n\txchg\teax,ecx\n\txchg\tebx,edx\n\tmov\tedi,esi\n\tcall\tNEAR PTR ??set_up_down_bits\n\tmov\t[clip_var],edi\n\tor\t[clip_var],esi\n\tjz\t??scan_convert\t\t\t; trivial acceptance?\n\ttest\tedi,esi\n\tjne\t??exit\t\t\t\t; trivial rejection?\n\tshl\tesi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+esi]\n\txchg\teax,ecx\n\txchg\tebx,edx\n\tshl\tedi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+edi]\n\tjmp\t??scan_convert\n\n\n\t;*==================================================================\n\t;* Subroutine table for clipping conditions.\n\t;*==================================================================\n??clip_tbl\tDD\t??nada,??a_lft,??a_rgt,??nada\n\t\tDD\t??a_up,??nada,??nada,??nada\n\t\tDD\t??a_dwn\n\n\n\t;*==================================================================\n\t;* Subroutines for clipping conditions.\n\t;*==================================================================\n??nada:\n\tretn\n\n??a_up:\n\tmov\tesi,[clip_min_y]\n\tcall\tNEAR PTR ??clip_vert\n\tretn\n\n??a_dwn:\n\tmov\tesi,[clip_max_y]\n\tcall\tNEAR PTR ??clip_vert\n\tretn\n\n??a_lft:\n\tmov\tesi,[clip_min_x]\n\tcall\tNEAR PTR ??clip_horiz\n\tpush\tebx\n\tmov\tesi,[left_clip_index]\n\tcmp\tebx,[clip_min_y]\n\tjge\t??no_left_min_clip\n\tmov\tebx,[clip_min_y]\n\n??no_left_min_clip:\n\tcmp\tebx,[clip_max_y]\n\tjle\t??no_left_max_clip\n\tmov\tebx,[clip_max_y]\n\n??no_left_max_clip:\n\tmov\t[left_clip_base + esi],ebx\t; a left edge will be generated\n\tmov\t[left_clip_index],4\t\t;   store off yb\n\tpop\tebx\n\tretn\n\n??a_rgt:\n\tmov\tesi,[clip_max_x]\n\tcall\tNEAR PTR ??clip_horiz\n\tpush\tebx\n\tmov\tesi,[right_clip_index]\n\tcmp\tebx,[clip_min_y]\n\tjge\t??no_right_min_clip\n\tmov\tebx,[clip_min_y]\n\n??no_right_min_clip:\n\tcmp\tebx,[clip_max_y]\n\tjle\t??no_right_max_clip\n\tmov\tebx,[clip_max_y]\n\n??no_right_max_clip:\n\tmov\t[right_clip_base + esi],ebx\t; a right edge will be generated\n\tmov\t[right_clip_index],4\t\t;   store off yb\n\tpop\tebx\n\tretn\n\n\n\t;*==================================================================\n\t;* Clip a line against a horizontal edge at clip_y.\n\t;* (eax,ebx) = (xa,ya), (ecx,edx) = (xb,yb)\n\t;* xa' = xa+[(clip_y-ya)(xb-xa)/(yb-ya)]\n\t;* ya' = clip_y\n\t;*==================================================================\n??clip_vert:\n\tpush\tedx\n\tpush\teax\n\tmov\t[clip_var],edx\t\t; clip_var = yb\n\tsub\t[clip_var],ebx\t\t; clip_var = (yb-ya)\n\tneg\teax\t\t\t; eax = -xa\n\tadd\teax,ecx\t\t\t; eax = (xb-xa)\n\tmov\tedx,esi\t\t\t; edx = clip_y\n\tsub\tedx,ebx\t\t\t; edx = (clip_y-ya)\n\timul\tedx\t\t\t; eax = (clip_y-ya)(xb-xa)\n\tidiv\t[clip_var]\t\t; eax = (clip_y-ya)(xb-xa)/(yb-ya)\n\tpop\tedx\n\tadd\teax,edx\t\t\t; eax = xa+[(clip_y-ya)(xb-xa)/(yb-ya)]\n\tpop\tedx\n\tmov\tebx,esi\t\t\t; ebx =\tclip_y\n\tretn\n\n\n\t;*==================================================================\n\t;* Clip a line against a vertical edge at clip_x.\n\t;* (eax,ebxx) = (xa,ya), (ecx,edxx) = (xb,yb)\n\t;* ya' = ya+[(clip_x-xa)(yb-ya)/(xb-xa)]\n\t;* xa' = clip_x\n\t;*==================================================================\n??clip_horiz:\n\tpush\tedx\n\tmov\t[clip_var],ecx\t\t; clip_var = xb\n\tsub\t[clip_var],eax\t\t; clip_var = (xb-xa)\n\tsub\tedx,ebx\t\t\t; edx = (yb-ya)\n\tneg\teax\t\t\t; eax = -xa\n\tadd\teax,esi\t\t\t; eax = (clip_x-xa)\n\timul\tedx\t\t\t; eax = (clip_x-xa)(yb-ya)\n\tidiv\t[clip_var]\t\t; eax = (clip_x-xa)(yb-ya)/(xb-xa)\n\tadd\tebx,eax\t\t\t; ebx = ya+[(clip_x-xa)(yb-ya)/(xb-xa)]\n\tpop\tedx\n\tmov\teax,esi\t\t\t; eax = clip_x\n\tretn\n\n\n\t;*==================================================================\n\t;* Set the condition bits for the subroutine table.\n\t;*==================================================================\n??set_left_right_bits:\n\txor\tesi,esi\n\tcmp\teax,[clip_min_x]   \t; if x >= left its not left\n\tjge\tshort ??a_not_left\n\tor\tesi,1\n\n??a_not_left:\n\tcmp\teax,[clip_max_x]\t; if x <= right its not right\n\tjle\tshort ??a_not_right\n\tor\tesi,2\n\n??a_not_right:\n\tretn\n\n??set_up_down_bits:\n\txor\tesi,esi\n\tcmp\tebx,[clip_min_y]\t; if y >= top its not up\n\tjge\tshort ??a_not_up\n\tor\tesi,4\n\n??a_not_up:\n\tcmp\tebx,[clip_max_y]\t; if y <= bottom its not down\n\tjle\tshort ??a_not_down\n\tor\tesi,8\n\n??a_not_down:\n\tretn\n\n\n\t;*==================================================================\n\t;* PORTABLE end.\n\t;*==================================================================\n\n\t;*==================================================================\n\t;* Scan convert an edge.\n\t;* (eax,ebx) = (xa,ya), (ecx,edx) = (xb,yb)\n\t;*==================================================================\n??scan_convert:\n\tcmp\tebx,edx\n\tje\t??exit\t\t       \t\t; if (ya == yb) don't scan convert\n\tjl\tshort ??no_swap\t\t\t; if (ya < yb)  swap vertices\n\txchg\teax,ecx\n\txchg\tebx,edx\n\n??no_swap:\n\tsub\tedx,ebx \t\t\t; edx = (yb - ya)\n\tsub\tebx,[scanline_min]\n\tsal\tebx,2\n\tadd\tebx,[span_buff]\t\t\t; ebx = span_buff + 4(ya - clip_min_y)\n\tsub\tecx,eax\t\t\t\t; ecx = (xb - xa)\n\tje\t??v_scan\t\t\t; if the edge is vertical use a\n\t\t\t\t\t\t;  special case routine\n\tpush\teax\n\tmov\teax,ecx\t\t\t\t; eax = (xb - xa)\n\tmov\tecx,edx\t\t\t\t; ecx = (yb - ya)\n\tsal\tedx,1\n\tmov\t[realignment],edx\t\t; realignment = 2(yb - ya)\n\tcwd\n\tidiv\tcx\n\tcwde\n\tmovsx\tedx,dx\n\tmov\tedi,eax\t\t\t\t; edi = (xb - xa) / (yb - ya)\n\tmov\tesi,edx\n\tmov\tedx,ecx\n\tpop\teax\t\t\t\t; eax = xa\n\tneg\tedx\t\t\t\t; edx = -(yb - ya)\n\tsal\tesi,1\t\t\t\t; esi = 2[(xb - xa) % (yb - ya)]\n\tjns\tshort ??r_scan\t\t\t; scan to the left or right?\n\tneg\tesi\n\n\t;*==================================================================\n\t;* Edge scan conversion DDA moving down and to the left.\n\t;* eax = xpos, ebx = span to reference\n\t;*==================================================================\n\tcmp\tebx,[span_buff]\n\tjg\t??l_scan_convert\n\n??l_scan_convert_loop:\n\tcmp\t[DWORD PTR ebx],SLOT_VACANT    ; if the left slot of span is\n\tjne\tshort ??l_next_slot\t       ;   vacant fill it with xpos\n\tmov\t[ebx],ax\n\n??l_next_slot:\n\tmov\t[ebx + 2],ax\t\t       ; otherwise fill the right slot\n\t\t\t\t\t       ;   with xpos\n??l_scan_convert:\n\tdec\tecx\n\tjl\tshort ??exit\n\tadd\tebx,4\n\tadd\teax,edi\n\tadd\tedx,esi\n\tjle\tshort ??l_scan_convert_loop\n\tdec\teax\n\tsub\tedx,[realignment]\n\tjmp\t??l_scan_convert_loop\n\n\n\t;*==================================================================\n\t;* Edge scan conversion DDA moving down and to the right.\n\t;* eax = xpos, ebx = span to reference\n\t;*==================================================================\n??r_scan:\n\tcmp\tebx,[span_buff]\n\tjg\t??r_scan_convert\n\n??r_scan_convert_loop:\n\tcmp\t[DWORD PTR ebx],SLOT_VACANT    ; if the left slot of span is\n\tjne\tshort ??r_next_slot\t       ;   vacant fill it with xpos\n\tmov\t[ebx],ax\n\n??r_next_slot:\n\tmov\t[ebx + 2],ax\t\t       ; otherwise fill the right slot\n\t\t\t\t\t       ;   with xpos\n??r_scan_convert:\n\tdec\tecx\n\tjl\tshort ??exit\n\tadd\tebx,4\n\tadd\teax,edi\n\tadd\tedx,esi\n\tjle\tshort ??r_scan_convert_loop\n\tinc\teax\n\tsub\tedx,[realignment]\n\tjmp\t??r_scan_convert_loop\n\n\n\t;*==================================================================\n\t;* Scan convert a vertical edge.\n\t;* eax = xpos, ebx = span to reference\n\t;*==================================================================\n??v_scan:\n\tcmp\tebx,[span_buff]\n\tjg\t??v_scan_convert\n\n??v_scan_convert_loop:\n\tcmp\t[DWORD PTR ebx],SLOT_VACANT   ; if the left slot of span is\n \tjne\tshort ??v_next_slot\t      ;   vacant fill it with xpos\n\tmov\t[ebx],ax\n\n??v_next_slot:\n\tmov\t[ebx + 2],ax\t\t      ; otherwise fill the right slot\n\t\t\t\t\t      ;   with xpos\n??v_scan_convert:\n\tadd\tebx,4\n\tdec\tedx\n\tjge\t??v_scan_convert_loop\n\n??exit:\n\tretn\n\n\tENDP\tBuffer_Fill_Quad\n\nEND\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/FILLRECT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : GraphicViewPortClass\t\t\t   *\n;*                                                                         *\n;*                    File Name : CLEAR.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : June 7, 1994   [PWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   GVPC::Fill_Rect -- draws a filled rectangle to a graphics buffer      *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n;***************************************************************************\n;* GVPC::FILL_RECT -- Fills a rectangular region of a graphic view port\t   *\n;*                                                                         *\n;* INPUT:\tWORD the left hand x pixel position of region\t\t   *\n;*\t\tWORD the upper x pixel position of region\t\t   *\n;*\t\tWORD the right hand x pixel position of region\t\t   *\n;*\t\tWORD the lower x pixel position of region\t\t   *\n;*\t\tUBYTE the color (optional) to clear the view port to\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* NOTE:\tThis function is optimized to handle viewport with no XAdd *\n;*\t\tvalue.  It also handles DWORD aligning the destination\t   *\n;*\t\twhen speed can be gained by doing it.\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/07/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_Fill_Rect C near\n\tUSES\teax,ebx,ecx,edx,esi,edi,ebp\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG    \tthis_object:DWORD\t\t\t; this is a member function\n\tARG\tx1_pixel:WORD\n\tARG\ty1_pixel:WORD\n\tARG\tx2_pixel:WORD\n\tARG\ty2_pixel:WORD\n\tARG    \tcolor:BYTE\t\t\t; what color should we clear to\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL\tVPwidth:DWORD\t\t; the width of the viewport\n\tLOCAL\tVPheight:DWORD\t\t; the height of the viewport\n\tLOCAL\tVPxadd:DWORD\t\t; the additional x offset of viewport\n\tLOCAL\tVPbpr:DWORD\t\t; the number of bytes per row of viewport\n\n\t;*===================================================================\n\t;* save off the viewport characteristics on the stack\n\t;*===================================================================\n\tmov\tebx,[this_object]\t\t\t\t; get a pointer to viewport\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\t; get width from viewport\n\tmov\tecx,[(GraphicViewPort ebx).GVPHeight]\t; get height from viewport\n\tmov\tedx,[(GraphicViewPort ebx).GVPXAdd]\t; get xadd from viewport\n\tadd\tedx,[(GraphicViewPort ebx).GVPPitch]\t; extra pitch of direct draw surface\n\tmov\t[VPwidth],eax\t\t\t\t; store the width of locally\n\tmov\t[VPheight],ecx\n\tmov\t[VPxadd],edx\n\tadd\teax,edx\n\tmov\t[VPbpr],eax\n\n\t;*===================================================================\n\t;* move the important parameters into local registers\n\t;*===================================================================\n\tmovsx\teax,[x1_pixel]\n\tmovsx\tebx,[y1_pixel]\n\tmovsx\tecx,[x2_pixel]\n\tmovsx\tedx,[y2_pixel]\n\n\t;*===================================================================\n\t;* Convert the x2 and y2 pixel to a width and height\n\t;*===================================================================\n\tcmp\teax,ecx\n\tjl\t??no_swap_x\n\txchg\teax,ecx\n\n??no_swap_x:\n\tsub\tecx,eax\n\tcmp\tebx,edx\n\tjl\t??no_swap_y\n\txchg\tebx,edx\n??no_swap_y:\n\tsub\tedx,ebx\n\tinc\tecx\n\tinc\tedx\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\tcmp\teax, [VPwidth]\t\t\t; compare with the max\n\tjge\t??out\t\t\t\t; starts off screen, then later\n\tjb\tshort ??sx_done\t\t\t; if it's not negative, it's ok\n\n\t;------ Clip source X to left edge of screen.\n\tadd\tecx, eax\t\t\t; Reduce width (add in negative src X).\n\txor\teax, eax\t\t\t; Clip to left of screen.\n??sx_done:\n\n\t;*===================================================================\n\t;* Bounds check source Y.\n\t;*===================================================================\n\tcmp\tebx, [VPheight]\t\t\t; compare with the max\n\tjge\t??out\t\t\t\t; starts off screen, then later\n\tjb\tshort ??sy_done\t\t\t; if it's not negative, it's ok\n\n\t;------ Clip source Y to top edge of screen.\n\tadd\tedx, ebx\t\t\t; Reduce height (add in negative src Y).\n\txor\tebx, ebx\t\t\t; Clip to top of screen.\n\n??sy_done:\n\t;*===================================================================\n\t;* Bounds check width versus width of source and dest view ports\n\t;*===================================================================\n\tpush\tebx\t\t\t\t; save off ebx for later use\n\tmov\tebx,[VPwidth]\t\t\t; get the source width\n\tsub\tebx, eax\t\t\t; Maximum allowed pixel width (given coordinates).\n\tsub\tebx, ecx\t\t\t; Pixel width undershoot.\n\tjns\tshort ??width_ok\t\t; if not signed no adjustment necessary\n\tadd\tecx, ebx\t\t\t; Reduce width to screen limits.\n\n??width_ok:\n\tpop\tebx\t\t\t\t; restore ebx to old value\n\n\t;*===================================================================\n\t;* Bounds check height versus height of source view port\n\t;*===================================================================\n\tpush\teax\t\t\t\t; save of eax for later use\n\tmov\teax, [VPheight]\t\t\t; get the source height\n\tsub\teax, ebx\t\t\t; Maximum allowed pixel height (given coordinates).\n\tsub\teax, edx\t\t\t; Pixel height undershoot.\n\tjns\tshort ??height_ok\t\t; if not signed no adjustment necessary\n\tadd\tedx, eax\t\t\t; Reduce height to screen limits.\n??height_ok:\n\tpop\teax\t\t\t\t; restore eax to old value\n\n\t;*===================================================================\n\t;* Perform the last minute checks on the width and height\n\t;*===================================================================\n\tor\tecx,ecx\n\tjz\t??out\n\n\tor\tedx,edx\n\tjz\t??out\n\n\tcmp\tecx,[VPwidth]\n\tja\t??out\n\tcmp\tedx,[VPheight]\n\tja\t??out\n\n\t;*===================================================================\n\t;* Get the offset into the virtual viewport.\n\t;*===================================================================\n\txchg\tedi,eax\t\t\t; save off the contents of eax\n\txchg\tesi,edx\t\t\t;   and edx for size test\n\tmov\teax,ebx\t\t\t; move the y pixel into eax\n\tmul\t[VPbpr]\t\t\t; multiply by bytes per row\n\tadd\tedi,eax\t\t\t; add the result into the x position\n\tmov\tebx,[this_object]\n\tadd\tedi,[(GraphicViewPort ebx).GVPOffset]\n\n\tmov\tedx,esi\t\t\t; restore edx back to real value\n\tmov\teax,ecx\t\t\t; store total width in ecx\n\tsub\teax,[VPwidth]\t\t; modify xadd value to include clipped\n\tsub\t[VPxadd],eax\t\t;   width bytes (subtract a negative number)\n\n\t;*===================================================================\n\t; Convert the color byte to a DWORD for fast storing\n\t;*===================================================================\n\tmov\tal,[color]\t\t\t\t; get color to clear to\n\tmov\tah,al\t\t\t\t\t; extend across WORD\n\tmov\tebx,eax\t\t\t\t\t; extend across DWORD in\n\tshl\teax,16\t\t\t\t\t;   several steps\n\tmov\tax,bx\n\n\t;*===================================================================\n\t; If there is no row offset then adjust the width to be the size of\n\t;   the entire viewport and adjust the height to be 1\n\t;*===================================================================\n\tmov\tesi,[VPxadd]\n\tor\tesi,esi\t\t\t\t\t; set the flags for esi\n\tjnz\t??row_by_row_aligned\t\t\t;   and act on them\n\n\txchg\teax,ecx\t\t\t\t\t; switch bit pattern and width\n\tmul\tedx\t\t\t\t\t; multiply by edx to get size\n\txchg\teax,ecx\t\t\t\t\t; switch size and bit pattern\n\tmov\tedx,1\t\t\t\t\t; only 1 line off view port size to do\n\n\t;*===================================================================\n\t; Find out if we should bother to align the row.\n\t;*===================================================================\n??row_by_row_aligned:\n\tmov\tebp,ecx\t\t\t\t\t; width saved in ebp\n\tcmp\tecx,OPTIMAL_BYTE_COPY\t\t\t; is it worth aligning them?\n\tjl\t??row_by_row\t\t\t\t;   if not then skip\n\n\t;*===================================================================\n\t; Figure out the alignment offset if there is any\n\t;*===================================================================\n\tmov\tebx,edi\t\t\t\t\t; get output position\n\tand\tebx,3\t\t\t\t\t;   is there a remainder?\n\tjz\t??aligned_loop\t\t\t\t;   if not we are aligned\n\txor\tebx,3\t\t\t\t\t; find number of align bytes\n\tinc\tebx\t\t\t\t\t; this number is off by one\n\tsub\tebp,ebx\t\t\t\t\t; subtract from width\n\n\t;*===================================================================\n\t; Now that we have the alignment offset copy each row\n\t;*===================================================================\n??aligned_loop:\n\tmov\tecx,ebx\t\t\t\t\t; get number of bytes to align\n\trep\tstosb\t\t\t\t\t;   and move them over\n\tmov\tecx,ebp\t\t\t\t\t; get number of aligned bytes\n\tshr\tecx,2\t\t\t\t\t;   convert to DWORDS\n\trep\tstosd\t\t\t\t\t;   and move them over\n\tmov\tecx,ebp\t\t\t\t\t; get number of aligned bytes\n\tand\tecx,3\t\t\t\t\t;   find the remainder\n\trep\tstosb\t\t\t\t\t;   and move it over\n\tadd\tedi,esi\t\t\t\t\t; fix the line offset\n\tdec\tedx\t\t\t\t\t; decrement the height\n\tjnz\t??aligned_loop\t\t\t\t; if more to do than do it\n\tjmp\t??exit\t\t\t\t\t; we are all done\n\n\t;*===================================================================\n\t; If not enough bytes to bother aligning copy each line across a byte\n\t;    at a time.\n\t;*===================================================================\n??row_by_row:\n\tmov\tecx,ebp\t\t\t\t\t; get total width in bytes\n\trep\tstosb\t\t\t\t\t; store the width\n\tadd\tedi,esi\t\t\t\t\t; handle the xadd\n\tdec\tedx\t\t\t\t\t; decrement the height\n\tjnz\t??row_by_row\t\t\t\t; if any left then next line\n??out:\n??exit:\n\tret\n\tENDP\tBuffer_Fill_Rect\n\nEND"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/FTPUTPIX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : GraphicViewPortClass\t\t\t   *\n;*                                                                         *\n;*                    File Name : GETPIXEL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : June 7, 1994   [PWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVPC::Buffer_Get_Pixel -- get the colour of a pixel at given coords   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n;***************************************************************************\n;* VVPC::GET_PIXEL -- Gets a pixel from the current view port\t\t   *\n;*                                                                         *\n;* INPUT:\tWORD the x pixel on the screen.\t\t\t\t   *\n;*\t\tWORD the y pixel on the screen.\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      UBYTE the pixel at the specified location\t\t   *\n;*                                                                         *\n;* WARNING:\tIf pixel is to be placed outside of the viewport then\t   *\n;*\t\tthis routine will abort.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/07/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_Get_Pixel C near\n\tUSES\tebx,ecx,edx,edi\n\n\tARG    \tthis_object:DWORD\t\t\t\t; this is a member function\n\tARG\tx_pixel:DWORD\t\t\t\t; x position of pixel to set\n\tARG\ty_pixel:DWORD\t\t\t\t; y position of pixel to set\n\n\t;*===================================================================\n\t; Get the viewport information and put bytes per row in ecx\n\t;*===================================================================\n\tmov\tebx,[this_object]\t\t\t\t; get a pointer to viewport\n\txor\teax,eax\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get the correct offset\n\tmov\tecx,[(GraphicViewPort ebx).GVPHeight]\t; edx = height of viewport\n\tmov\tedx,[(GraphicViewPort ebx).GVPWidth]\t; ecx = width of viewport\n\n\t;*===================================================================\n\t; Verify that the X pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[x_pixel]\t\t\t\t; find the x position\n\tcmp\teax,edx\t\t\t\t\t;   is it out of bounds\n\tjae\tshort ??exit\t\t\t\t; if so then get out\n\tadd\tedi,eax\t\t\t\t\t; otherwise add in offset\n\n\t;*===================================================================\n\t; Verify that the Y pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[y_pixel]\t\t\t\t; get the y position\n\tcmp\teax,ecx\t\t\t\t\t;  is it out of bounds\n\tjae\t??exit\t\t\t\t\t; if so then get out\n\tadd\tedx,[(GraphicViewPort ebx).GVPXAdd]\t; otherwise find bytes per row\n\tadd\tedx,[(GraphicViewPort ebx).GVPPitch]\t; otherwise find bytes per row\n\tmul\tedx\t\t\t\t\t; offset = bytes per row * y\n\tadd\tedi,eax\t\t\t\t\t; add it into the offset\n\n\t;*===================================================================\n\t; Write the pixel to the screen\n\t;*===================================================================\n\txor\teax,eax\t\t\t\t\t; clear the word\n\tmov\tal,[edi]\t\t\t\t; read in the pixel\n??exit:\n\tret\n\tENDP\tBuffer_Get_Pixel\n\nEND\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/GBUFFER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : GBUFFER.CPP                              *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 3, 1994                              *\n *                                                                         *\n *                  Last Update : October 9, 1995   []                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   VVPC::VirtualViewPort -- Default constructor for a virtual viewport   *\n *   VVPC:~VirtualViewPortClass -- Destructor for a virtual viewport       *\n *   VVPC::Clear -- Clears a graphic page to correct color                 *\n *   VBC::VideoBufferClass -- Lowlevel constructor for video buffer class  *\n *   GVPC::Change -- Changes position and size of a Graphic View Port      *\n *   VVPC::Change -- Changes position and size of a Video View Port      \t*\n *   Set_Logic_Page -- Sets LogicPage to new buffer                        *\n *   GBC::DD_Init -- Inits a direct draw surface for a GBC                 *\n *   GBC::Init -- Core function responsible for initing a GBC              *\n *   GBC::Lock -- Locks a Direct Draw Surface                              *\n *   GBC::Unlock -- Unlocks a direct draw surface                          *\n *   GBC::GraphicBufferClass -- Default constructor (requires explicit init)*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef GBUFFER_H\n#include \"gbuffer.h\"\n#include \"misc.h\"\n#endif\n#pragma inline\n\nint\t\tTotalLocks;\nBOOL \tAllowHardwareBlitFills = TRUE;\n\n\n//int\tCacheAllowed;\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n/***************************************************************************\n * GVPC::GRAPHICVIEWPORTCLASS -- Constructor for basic view port class     *\n *                                                   m                      *\n * INPUT:\t\tGraphicBufferClass * gbuffer\t- buffer to attach to\t\t\t*\n *\t\t\t\t\tint x\t\t\t\t\t\t\t\t- x offset into buffer\t\t\t*\n *\t\t\t\t\tint y\t\t\t\t\t\t\t\t- y offset into buffer\t\t\t*\n *\t\t\t\t\tint w\t\t\t\t\t\t\t\t- view port width in pixels   *\n *\t\t\t\t\tint h   \t\t\t\t\t\t\t- view port height in pixels\t*\n *                                                                         *\n * OUTPUT:     Constructors may not have a return value\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/09/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicViewPortClass::GraphicViewPortClass(GraphicBufferClass *gbuffer, int x, int y, int w, int h) :\n\tLockCount(0),\n\tGraphicBuff(NULL)\n{\n\tAttach(gbuffer, x, y, w, h);\n}\n\n/***************************************************************************\n * GVPC::GRAPHICVIEWPORTCLASS -- Default constructor for view port class   *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/09/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicViewPortClass::GraphicViewPortClass(void)\n{\n}\n\n/***************************************************************************\n * GVPC::~GRAPHICVIEWPORTCLASS -- Destructor for GraphicViewPortClass\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     A destructor may not return a value.                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/10/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicViewPortClass::~GraphicViewPortClass(void)\n{\n \tOffset\t\t\t= 0;\n\tWidth\t\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record width of Buffer\n\tHeight\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record height of Buffer\n\tXAdd\t\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XAdd of Buffer\n\tXPos\t\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XPos of Buffer\n\tYPos\t\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record YPos of Buffer\n\tPitch\t\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record width of Buffer\n\tIsDirectDraw\t= FALSE;\n\tLockCount\t\t= 0;\n\tGraphicBuff\t\t= NULL;\n}\n\n/***************************************************************************\n * GVPC::ATTACH -- Attaches a viewport to a buffer class                   *\n *                                                                         *\n * INPUT:\t\tGraphicBufferClass *g_buff\t- pointer to gbuff to attach to  *\n *\t\t\t\t\tint x                     - x position to attach to\t\t\t*\n *\t\t\t\t\tint y \t\t\t\t\t\t\t- y position to attach to\t\t\t*\n *\t\t\t\t\tint w\t\t\t\t\t\t\t- width of the view port\t\t\t*\n *\t\t\t\t\tint h\t\t\t\t\t\t\t- height of the view port\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/10/1994 PWG : Created.                                             *\n *=========================================================================*/\nvoid GraphicViewPortClass::Attach(GraphicBufferClass *gbuffer, int x, int y, int w, int h)\n{\n\t/*======================================================================*/\n\t/* Can not attach a Graphic View Port if it is actually the physical\t\t*/\n\t/*\t   representation of a Graphic Buffer.\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (this == Get_Graphic_Buffer())  {\n\t\treturn;\n\t}\n\n\t/*======================================================================*/\n\t/* Verify that the x and y coordinates are valid and placed within the\t*/\n\t/*\t\tphysical buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (x < 0) \t\t\t\t\t\t\t\t\t\t// you cannot place view port off\n\t\tx = 0;\t\t\t\t\t\t\t\t\t\t//\t\tthe left edge of physical buf\n\tif (x >= gbuffer->Get_Width())\t\t\t// you cannot place left edge off\n\t\tx = gbuffer->Get_Width() - 1;\t\t\t//\t\tthe right edge of physical buf\n\tif (y < 0) \t\t\t\t\t\t\t\t\t\t// you cannot place view port off\n\t\ty = 0;\t\t\t\t\t\t\t\t\t\t//\t\tthe top edge of physical buf\n\tif (y >= gbuffer->Get_Height()) \t\t\t// you cannot place view port off\n\t\ty = gbuffer->Get_Height() - 1;\t\t//\t\tbottom edge of physical buf\n\n\t/*======================================================================*/\n\t/* Adjust the width and height of necessary\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (x + w > gbuffer->Get_Width()) \t\t// if the x plus width is larger\n\t\tw = gbuffer->Get_Width() - x;\t\t\t//\t\tthan physical, fix width\n\n\tif (y + h > gbuffer->Get_Height()) \t\t// if the y plus height is larger\n\t\th = gbuffer->Get_Height() - y;\t\t//\t\tthan physical, fix height\n\n\t/*======================================================================*/\n\t/* Get a pointer to the top left edge of the buffer.\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n \tOffset \t\t= gbuffer->Get_Offset() + ((gbuffer->Get_Width()+gbuffer->Get_Pitch()) * y) + x;\n\n\t/*======================================================================*/\n\t/* Copy over all of the variables that we need to store.\t\t\t\t\t\t*/\n\t/*======================================================================*/\n \tXPos\t\t\t= x;\n \tYPos\t\t\t= y;\n \tXAdd\t\t\t= gbuffer->Get_Width() - w;\n \tWidth\t\t\t= w;\n \tHeight\t\t= h;\n\tPitch\t\t\t= gbuffer->Get_Pitch();\n \tGraphicBuff = gbuffer;\n\tIsDirectDraw= gbuffer->IsDirectDraw;\n}\n\n\n/***************************************************************************\n * GVPC::CHANGE -- Changes position and size of a Graphic View Port        *\n *                                                                         *\n * INPUT:   \tint the new x pixel position of the graphic view port      *\n *\t\t\t\t\tint the new y pixel position of the graphic view port\t\t*\n *\t\t\t\t\tint the new width of the viewport in pixels\t\t\t\t\t\t*\n *\t\t\t\t\tint the new height of the viewport in pixels\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:  \tBOOL whether the Graphic View Port could be sucessfully     *\n *\t\t\t\t      resized.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:   You may not resize a Graphic View Port which is derived \t\t*\n *\t\t\t\t\t\tfrom a Graphic View Port Buffer, \t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/14/1994 SKB : Created.                                             *\n *=========================================================================*/\nBOOL GraphicViewPortClass::Change(int x, int y, int w, int h)\n{\n\t/*======================================================================*/\n\t/* Can not change a Graphic View Port if it is actually the physical\t\t*/\n\t/*\t   representation of a Graphic Buffer.\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (this == Get_Graphic_Buffer())  {\n\t\treturn(FALSE);\n\t}\n\n\t/*======================================================================*/\n\t/* Since there is no allocated information, just re-attach it to the\t\t*/\n\t/*\t\texisting graphic buffer as if we were creating the\t\t\t\t\t\t*/\n\t/*\t\tGraphicViewPort.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tAttach(Get_Graphic_Buffer(), x, y, w, h);\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * GBC::DD_INIT -- Inits a direct draw surface for a GBC                   *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/09/1995     : Created.                                             *\n *=========================================================================*/\nvoid GraphicBufferClass::DD_Init(GBC_Enum flags)\n{\n\t//\n\t// Create the direct draw surface description\n\t//\n\tmemset (&VideoSurfaceDescription , 0 , sizeof ( VideoSurfaceDescription ));\n\n\tVideoSurfaceDescription.dwSize\t\t\t= sizeof( VideoSurfaceDescription );\n\tVideoSurfaceDescription.dwFlags \t\t\t= DDSD_CAPS;\n\tVideoSurfaceDescription.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;\n\n\n\tif (!(flags & GBC_VISIBLE)) {\n\t\tVideoSurfaceDescription.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;\n\t\tVideoSurfaceDescription.dwFlags \t\t  |=\tDDSD_HEIGHT | DDSD_WIDTH;\n\t\tVideoSurfaceDescription.dwHeight\t\t\t= Height;\n\t\tVideoSurfaceDescription.dwWidth\t\t\t= Width;\n\t}\n\n\t//\n\t// Need to set the DDSCAPS_MODEX  flag if we want a 320 wide mode\n\t//\n\tif ( Width == 320 ) {\n\t\tVideoSurfaceDescription.ddsCaps.dwCaps |= DDSCAPS_MODEX;\n\t}\n\n\t//\n\t// Call CreateSurface\n\t//\n\tDirectDrawObject->CreateSurface( &VideoSurfaceDescription , &VideoSurfacePtr , NULL);\n\tAllSurfaces.Add_DD_Surface (VideoSurfacePtr);\n\n\tif ( GBC_VISIBLE & flags ){\n\t\tPaletteSurface=VideoSurfacePtr;\n\t}\n\n\tAllocated\t\t= FALSE;\t\t\t//\teven if system alloced, dont flag it cuz\n\t\t\t\t\t\t\t\t\t\t\t//   we dont want it freed.\n\tIsDirectDraw\t= TRUE;\t\t\t//\tflag it as a video surface\n\tOffset\t\t\t= NOT_LOCKED;\t//\tflag it as unavailable for reading or writing\n\tLockCount\t\t= 0;\t\t\t\t//  surface is not locked\n}\n\n\nvoid GraphicBufferClass::Attach_DD_Surface (GraphicBufferClass * attach_buffer)\n{\n\tVideoSurfacePtr->AddAttachedSurface (attach_buffer->Get_DD_Surface());\n}\n\n\n/***************************************************************************\n * GBC::INIT -- Core function responsible for initing a GBC                *\n *                                                                         *\n * INPUT:\t\tint \t\t- the width in pixels of the GraphicBufferClass    *\n *\t\t\t\t\tint\t\t- the heigh in pixels of the GraphicBufferClass\t\t*\n *\t\t\t\t\tvoid *\t- pointer to user supplied buffer (system will\t\t*\n *\t\t\t\t\t\t\t\t  allocate space if buffer is NULL)\t\t\t\t\t\t*\n *\t\t\t\t\tlong\t\t- size of the user provided buffer\t\t\t\t\t\t*\n *\t\t\t\t\tGBC_Enum\t- flags if this is defined as a direct draw\t\t\t*\n *\t                       surface\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/09/1995     : Created.                                             *\n *=========================================================================*/\nvoid GraphicBufferClass::Init(int w, int h, void *buffer, long size, GBC_Enum flags)\n{\n\tSize\t\t\t= size;\t\t\t\t\t\t\t\t\t// find size of physical buffer\n\tWidth\t\t\t= w;\t\t\t\t\t\t\t\t\t\t// Record width of Buffer\n\tHeight\t\t= h;\t\t\t\t\t\t\t\t\t\t// Record height of Buffer\n\n\t//\n\t// If the surface we are creating is a direct draw object then\n\t//   we need to do a direct draw init.  Otherwise we will do\n\t//   a normal alloc.\n\t//\n\tif (flags & (GBC_VIDEOMEM | GBC_VISIBLE)) {\n\t\tDD_Init(flags);\n\t} else {\n\t\tif (buffer) {\t\t\t\t\t\t\t\t\t\t// if buffer is specified\n\t\t\tBuffer\t\t= (BYTE *)buffer;\t\t\t\t//\t\tpoint to it and mark\n\t\t\tAllocated\t= FALSE;\t\t\t\t\t\t\t//\t\tit as user allocated\n\t\t} else {\n\t\t\tif (!Size) Size = w*h;\n\t\t\tBuffer\t\t= new BYTE[Size];\t\t\t\t// otherwise allocate it and\n\t\t\tAllocated\t= TRUE;\t\t\t\t\t\t\t//\t\tmark it system alloced\n\t\t}\n\t\tOffset\t\t\t= (long)Buffer;\t\t\t\t// Get offset to the buffer\n\t\tIsDirectDraw\t= FALSE;\n\t}\n\n\tPitch\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record width of Buffer\n\tXAdd\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XAdd of Buffer\n\tXPos\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XPos of Buffer\n\tYPos\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record YPos of Buffer\n\tGraphicBuff\t= this;\t\t\t\t\t\t\t\t\t// Get a pointer to our self\n}\n\n\n/***********************************************************************************************\n * GBC::Un_Init -- releases the video surface belonging to this gbuffer                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/6/96 12:44PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid GraphicBufferClass::Un_Init (void)\n{\n\tif ( IsDirectDraw ){\n\n\t\tif ( VideoSurfacePtr ){\n\n\t\t\twhile ( LockCount ){\n\n\t\t\t\tif (VideoSurfacePtr->Unlock ( NULL ) == DDERR_SURFACELOST){\n\t\t\t\t\tif (Gbuffer_Focus_Loss_Function){\n\t\t\t\t\t\tGbuffer_Focus_Loss_Function();\n\t\t\t\t\t}\n\t\t\t\t\tAllSurfaces.Restore_Surfaces();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tAllSurfaces.Remove_DD_Surface (VideoSurfacePtr);\n\t\t\tVideoSurfacePtr->Release();\n\t\t\tVideoSurfacePtr = NULL;\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * GBC::GRAPHICBUFFERCLASS -- Default constructor (requires explicit init) *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/09/1995     : Created.                                             *\n *=========================================================================*/\nGraphicBufferClass::GraphicBufferClass(void)\n{\n\tGraphicBuff\t\t\t= this; \t\t\t\t\t\t\t// Get a pointer to our self\n\tVideoSurfacePtr\t= NULL;\n\tmemset(&VideoSurfaceDescription, 0, sizeof(DDSURFACEDESC));\n}\n\n\n/***************************************************************************\n * GBC::GRAPHICBUFFERCLASS -- Constructor for fixed size buffers           *\n *                                                                         *\n * INPUT:\t\tlong size\t\t- size of the buffer to create\t\t\t\t\t*\n *\t\t\t\t\tint w\t\t\t- width of buffer in pixels (default = 320)  *\n *\t\t\t\t\tint h\t\t\t- height of buffer in pixels (default = 200) *\n *\t\t\t\t\tvoid *buffer\t- a pointer to the buffer if any (optional)\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/13/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicBufferClass::GraphicBufferClass(int w, int h, void *buffer, long size)\n{\n\tInit(w, h, buffer, size, GBC_NONE);\n}\n/*=========================================================================*\n * GBC::GRAPHICBUFFERCLASS -- inline constructor for GraphicBufferClass\t\t*\n *                                                                         *\n * INPUT:\t\tint w\t\t\t- width of buffer in pixels (default = 320)  *\n *\t\t\t\t\tint h\t\t\t- height of buffer in pixels (default = 200) *\n *\t\t\t\t\tvoid *buffer\t- a pointer to the buffer if any (optional)\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicBufferClass::GraphicBufferClass(int w, int h, void *buffer)\n{\n\tInit(w, h, buffer, w * h, GBC_NONE);\n}\n\n/*====================================================================================*\n * GBC::GRAPHICBUFFERCLASS -- contructor for GraphicsBufferClass with special flags   *\n *                                                                                    *\n * INPUT:\t\tint w\t\t\t- width of buffer in pixels (default = 320)           *\n *\t\t\t\t\tint h\t\t\t- height of buffer in pixels (default = 200)      *\n *\t\t\t\t\tvoid *buffer\t- unused                                \t      *\n *               unsigned flags - flags for creation of special buffer types          *\n *                                GBC_VISIBLE - buffer is a visible screen surface    *\n *                                GBC_VIDEOMEM - buffer resides in video memory       *\n *                                                                                    *\n * OUTPUT:     none                                                                   *\n *                                                                                    *\n * HISTORY:                                                                           *\n *   09-21-95 04:19pm ST : Created                                                    *\n *====================================================================================*/\nGraphicBufferClass::GraphicBufferClass(int w, int h, GBC_Enum flags)\n{\n\tInit(w, h, NULL, w * h, flags);\n}\n\n/*=========================================================================*\n * GBC::~GRAPHICBUFFERCLASS -- Destructor for the graphic buffer class     *\n *                                                                         *\n *\tINPUT:\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicBufferClass::~GraphicBufferClass()\n{\n\n//\n// Release the direct draw surface if it exists\n//\n\tUn_Init();\n}\n\n\n\n/***************************************************************************\n * SET_LOGIC_PAGE -- Sets LogicPage to new buffer                          *\n *                                                                         *\n * INPUT:\t\tGraphicBufferClass * the buffer we are going to set         *\n *                                                                         *\n * OUTPUT:     GraphicBufferClass * the previous buffer type\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nGraphicViewPortClass *Set_Logic_Page(GraphicViewPortClass *ptr)\n{\n\tGraphicViewPortClass *old = LogicPage;\n\tLogicPage\t\t\t\t\t= ptr;\n\treturn(old);\n}\n\n/***************************************************************************\n * SET_LOGIC_PAGE -- Sets LogicPage to new buffer                          *\n *                                                                         *\n * INPUT:\t\tGraphicBufferClass & the buffer we are going to set         *\n *                                                                         *\n * OUTPUT:     GraphicBufferClass * the previous buffer type\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nGraphicViewPortClass *Set_Logic_Page(GraphicViewPortClass &ptr)\n{\n\tGraphicViewPortClass *old = LogicPage;\n\tLogicPage\t\t\t\t\t= &ptr;\n\treturn(old);\n}\n\n\n/***************************************************************************\n * GBC::LOCK -- Locks a Direct Draw Surface                                *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/09/1995     : Created.                                             *\n *   10/09/1995     : Code stolen from Steve Tall                          *\n *=========================================================================*/\nextern\tvoid Colour_Debug (int call_number);\nextern BOOL GameInFocus;\n\nextern void Block_Mouse(GraphicBufferClass *buffer);\nextern void Unblock_Mouse(GraphicBufferClass *buffer);\n\nBOOL GraphicBufferClass::Lock(void)\n{\n\tHRESULT\tresult;\n\tint\t\trestore_attempts=0;\n\n\t//\n\t// If its not a direct draw surface then the lock is always sucessful.\n\t//\n\tif (!IsDirectDraw) return(TRUE);\n\n\t/*\n\t** If the video surface pointer is null then return\n\t*/\n\tif (!VideoSurfacePtr) return (FALSE);\n\n\t/*\n\t** If we dont have focus then return failure\n\t*/\n\tif (!GameInFocus) return (FALSE);\n\n\n\tBlock_Mouse(this);\n\n\n\t//\n\t// If surface is already locked then inc the lock count and return true\n\t//\n\tif (LockCount){\n\t\tLockCount++;\n\t\tUnblock_Mouse(this);\n\t\treturn(TRUE);\n\t}\n\n\t//\n\t// If it isn't locked at all then we will have to request that Direct\n\t// Draw actually lock the surface.\n\t//\n\n\tif (VideoSurfacePtr){\n\t\twhile (!LockCount && restore_attempts<2) {\n\t\t\tresult = VideoSurfacePtr->Lock ( NULL\n\t\t\t\t\t\t\t\t\t\t, &(VideoSurfaceDescription)\n\t\t\t\t\t\t\t\t\t\t, DDLOCK_WAIT\n\t\t\t\t\t\t\t\t\t\t, NULL);\n\n\t\t\tswitch (result){\n\t\t\t\tcase DD_OK :\n\t\t\t\t\tOffset\t= (unsigned long)VideoSurfaceDescription.lpSurface;\n\t\t\t\t\tPitch\t\t= VideoSurfaceDescription.lPitch;\n\t\t\t\t\tPitch\t  -= Width;\n\t\t\t\t\tLockCount++;\t\t// increment count so we can track if\n\t\t\t\t\tTotalLocks++;\t\t// Total number of times we have locked (for debugging)\n\t\t\t\t\t//Colour_Debug (1);\n\t\t\t\t\tUnblock_Mouse(this);\n\t\t\t\t\treturn (TRUE);\t\t// we locked it multiple times.\n\n\t\t\t\tcase DDERR_SURFACELOST :\n\t\t\t\t\tif (Gbuffer_Focus_Loss_Function){\n\t\t\t\t\t\tGbuffer_Focus_Loss_Function();\n\t\t\t\t\t}\n\t\t\t\t\tAllSurfaces.Restore_Surfaces();\n\t\t\t\t\trestore_attempts++;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault :\n\t\t\t\t\tUnblock_Mouse(this);\n\t\t\t\t\treturn (FALSE);\n\t\t\t}\n\t\t}\n\t}\n\t//Colour_Debug(1);\n\tUnblock_Mouse(this);\n\treturn (FALSE);\t\t//Return false because we couldnt lock or restore the surface\n}\n\n/***************************************************************************\n * GBC::UNLOCK -- Unlocks a direct draw surface                            *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/09/1995     : Created.                                             *\n *   10/09/1995     : Code stolen from Steve Tall                          *\n *=========================================================================*/\n\n\nBOOL GraphicBufferClass::Unlock(void)\n{\n\t//\n\t// If there is no lock count or this is not a direct draw surface\n\t// then just return true as there is no harm done.\n\t//\n\tif (!(LockCount && IsDirectDraw)) {\n\t\treturn(TRUE);\n\t}\n\n\t//\n\t// If lock count is directly equal to one then we actually need to\n\t// unlock so just give it a shot.\n\t//\n\tif (LockCount == 1 && VideoSurfacePtr) {\n\t\tBlock_Mouse(this);\n\t\tif ( VideoSurfacePtr->Unlock ( NULL ) != DD_OK ){\n\t\t\tUnblock_Mouse(this);\n\t\t\treturn(FALSE);\n\t\t} else {\n\t\t\tOffset=NOT_LOCKED;\n\t\t\tLockCount--;\n\t\t\tUnblock_Mouse(this);\n\t\t\treturn(TRUE);\n\t\t}\n\t}\n\t//Colour_Debug (0);\n\tLockCount--;\n\treturn(TRUE);\n}\n\n\n/***********************************************************************************************\n * GVPC::DD_Linear_Blit_To_Linear -- blit using the hardware blitter                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    destination vvpc                                                                  *\n *           x coord to blit from                                                              *\n *           y coord to blit from                                                              *\n *           x coord to blit to                                                                *\n *           y coord to blit to                                                                *\n *           width to blit                                                                     *\n *           height to blit                                                                    *\n *                                                                                             *\n * OUTPUT:   DD_OK if successful                                                               *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09-22-95 11:05am ST : Created                                                             *\n *=============================================================================================*/\n\nHRESULT GraphicViewPortClass::DD_Linear_Blit_To_Linear (\n\t\t\t\t\t\t\t\t  GraphicViewPortClass &dest\n\t\t\t\t\t\t\t\t, int source_x\n\t\t\t\t\t\t\t\t, int source_y\n\t\t\t\t\t\t\t\t, int dest_x\n\t\t\t\t\t\t\t\t, int dest_y\n\t\t\t\t\t\t\t\t, int width\n\t\t\t\t\t\t\t\t, int height\n\t\t\t\t\t\t\t\t, BOOL mask )\n\n{\n\tRECT\tsource_rectangle;\n\tRECT\tdest_rectangle;\n\tint\t\tkey_source=0;\n\n\tif ( mask ){\n\t\tkey_source=DDBLT_KEYSRC;\n\t}\n\n\n\tsource_rectangle.left \t= source_x;\n\tsource_rectangle.top  \t= source_y;\n\tsource_rectangle.right\t= source_x+width;\n\tsource_rectangle.bottom\t= source_y+height;\n\n\tdest_rectangle.left \t= dest_x;\n\tdest_rectangle.top  \t= dest_y;\n\tdest_rectangle.right\t= dest_x+width;\n\tdest_rectangle.bottom\t= dest_y+height;\n\n   return (\tdest.GraphicBuff->Get_DD_Surface()->Blt ( &dest_rectangle,\n\t\t\t\t\t\t\t\t\t\t\t\tGraphicBuff->Get_DD_Surface(),\n\t\t\t\t\t\t\t\t\t\t\t\t&source_rectangle,\n\t\t\t\t\t\t\t\t\t\t\t\tkey_source | DDBLT_WAIT | DDBLT_ASYNC,\n\t\t\t\t\t\t\t\t\t\t\t\tNULL ) );\n}\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/GBUFFER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : GBUFFER.H                                *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 26, 1994                             *\n *                                                                         *\n *                  Last Update : October 9, 1995   []                     *\n *                                                                         *\n ***************************************************************************\n *                                                                         *\n *\tThis module contains the definition for the graphic buffer class.  The\t*\n * primary functionality of the graphic buffer class is handled by inline\t*\n * functions that make a call through function pointers to the correct\t\t*\n * routine.  This has two benefits:\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t1) C++ name mangling is not a big deal since the function pointers\t*\n *\t\t   point to functions in standard C format.\t\t\t\t\t\t\t\t\t*\n *\t\t2) The function pointers can be changed when we set a different\t\t*\n *       graphic mode.  This allows us to have both supervga and mcga\t\t*\n *\t\t\troutines present in memory at once.\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * In the basic library, these functions point to stub routines which just\t*\n * return.  This makes a product that just uses a graphic buffer take the\t*\n * minimum amount of code space.  For programs that require MCGA or VESA\t*\n * support, all that is necessary to do is link either the MCGA or VESA\t\t*\n * specific libraries in, previous to WWLIB32.  The linker will then \t\t*\n * overide the the necessary stub functions automatically.\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * In addition, there are helpful inline function calls for parameter\t\t*\n * ellimination.  This header file gives the defintion for all\t\t\t\t\t*\n * GraphicViewPort and GraphicBuffer classes.  \t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Terminology:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tBuffer Class - A class which consists of a pointer to an allocated\t\t*\n *\t\tbuffer and the size of the buffer that was allocated.\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tGraphic ViewPort - The Graphic ViewPort defines a window into a \t\t\t*\n *\t\tGraphic Buffer.  This means that although a Graphic Buffer \t\t\t\t*\n *\t\trepresents linear memory, this may not be true with a Graphic\t\t\t*\n *\t\tViewport.  All low level functions that act directly on a graphic\t\t*\n *\t\tviewport are included within this class.  This includes but is not\t*\n *\t\tlimited to most of the functions which can act on a Video Viewport\t*\n *\t\tVideo Buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Graphic Buffer - A Graphic Buffer is an instance of an allocated buffer\t*\n *\t\tused to represent a rectangular region of graphics memory.\t\t\t\t*\n *\t\tThe HidBuff\tand BackBuff are excellent examples of a Graphic Buffer.\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Below is a tree which shows the relationship of the VideoBuffer and \t\t*\n * Buffer classes to the GraphicBuffer class:\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t  BUFFER.H\t\t\t\t GBUFFER.H\t\t\t  BUFFER.H\t\t\t\t VBUFFER.H\t*\n *  ----------          ----------         ----------          ----------\t*\n * |  Buffer  |        | Graphic  |       |  Buffer  |        |  Video   |\t*\n * |  Class   |        | ViewPort |       |  Class   |        | ViewPort |\t*\n *  ----------          ----------         ----------          ----------\t*\n *            \\        /                             \\        /\t\t\t\t*\n *             \\      /                               \\      /\t\t\t\t\t*\n *            ----------                             ----------\t\t\t\t*\n *           |  Graphic |                           |  Video   |\t\t\t\t*\n *           |  Buffer  |                           |  Buffer  |\t\t\t\t*\n *            ----------                             ---------- \t\t\t\t*\n *\t  \t\t\t  GBUFFER.H\t\t\t                       VBUFFER.H\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   GBC::GraphicBufferClass -- inline constructor for GraphicBufferClass  *\n *   GVPC::Remap -- Short form to remap an entire graphic view port        *\n *   GVPC::Get_XPos -- Returns x offset for a graphic viewport class       *\n *   GVPC::Get_Ypos -- Return y offset in a GraphicViewPortClass           *\n *   VVPC::Get_XPos -- Get the x pos of the VP on the Video                *\n *   VVPC::Get_YPos -- Get the y pos of the VP on the video                *\n *   GBC::Get_Graphic_Buffer -- Get the graphic buffer of the VP.          *\n *   GVPC::Draw_Line -- Stub function to draw line in Graphic Viewport Class*\n *   GVPC::Fill_Rect -- Stub function to fill rectangle in a GVPC          *\n *   GVPC::Remap -- Stub function to remap a GVPC                          *\n *   GVPC::Print -- stub func to print a text string                       *\n *   GVPC::Print -- Stub function to print an integer                      *\n *   GVPC::Print -- Stub function to print a short to a graphic viewport   *\n *   GVPC::Print -- stub function to print a long on a graphic view port   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n\n#define WIN32_LEAN_AND_MEAN\n#include <ddraw.h>\n\n\n#ifndef GBUFFER_H\n#define GBUFFER_H\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n#ifndef DRAWBUFF_H\n#include \"drawbuff.h\"\n#endif\n\n#ifndef BUFFER_H\n#include \"buffer.h\"\n#endif\n\n#ifndef WINDOWS_H\n#include \"ww_win.h\"\n#endif\n#include <stdlib.h>\n\n#include \"iconcach.h\"\n\n\n\n#ifndef FUNCTION_H\n\n#pragma off (unreferenced)\n\n#ifndef BITMAPCLASS\n#define BITMAPCLASS\nclass BitmapClass\n{\n\tpublic:\n\t\tBitmapClass(int w, int h, unsigned char * data) :\n\t\t\tWidth(w), Height(h), Data(data) {};\n\n\t\tint Width;\n\t\tint Height;\n\t\tunsigned char * Data;\n};\n\nclass TPoint2D\n{\n\tpublic:\n\t\tTPoint2D(int xx, int yy) : x(xx), y(yy) {};\n\t\tTPoint2D(void) : x(0), y(0) {};\n\n\t\tint x;\n\t\tint y;\n};\n#endif\n\n#pragma on (unreferenced)\n#endif\n\n\n//////////////////////////////////////////////////////////////////////////\n//\n// Defines for direct draw\n//\n//\nextern\tLPDIRECTDRAW\tDirectDrawObject;\t//pointer to direct draw object\nextern\tHWND\t\t\tMainWindow;\t\t\t//handle to programs main window\n\n/*\n** Pointer to function to call if we detect a focus loss\n*/\nextern\tvoid (*Gbuffer_Focus_Loss_Function)(void);\n\nenum GBC_Enum {\n\tGBC_NONE\t\t\t\t= 0,\n\tGBC_VIDEOMEM\t\t= 1,\n\tGBC_VISIBLE\t\t\t= 2,\n};\n\n#define\tNOT_LOCKED\t\tNULL\n\n/*=========================================================================*/\n/* Define the screen width and height to make portability to other modules\t*/\n/*\t\teasier.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tDEFAULT_SCREEN_WIDTH\t\t320\n#define\tDEFAULT_SCREEN_HEIGHT\t200\n\n/*=========================================================================*/\n/* Let the compiler know that a GraphicBufferClass exists so that it can\t*/\n/*\t\tkeep a pointer to it in a VideoViewPortClass.\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nclass GraphicViewPortClass;\nclass GraphicBufferClass;\nclass VideoViewPortClass;\nclass VideoBufferClass;\n\nGraphicViewPortClass *Set_Logic_Page(GraphicViewPortClass *ptr);\nGraphicViewPortClass *Set_Logic_Page(GraphicViewPortClass &ptr);\n\n/*=========================================================================*/\n/* GraphicViewPortClass - Holds viewport information on a viewport which\t*/\n/*\t\thas been attached to a GraphicBuffer.  A viewport is effectively a\t*/\n/*\t\trectangular subset of the full buffer which is used for clipping and\t*/\n/*\t\tthe like.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tchar\t  \t*Buffer\t-\t\tis the offset to view port buffer\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis the width of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis the height of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis add value to go from the end of a line\t*/\n/*\t\t\t\t\t\t\t\t\t\t\tto the beginning of the next line\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\tx offset into its associated VideoBuffer\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\ty offset into its associated VideoBuffer\t*/\n/*=========================================================================*/\nclass GraphicViewPortClass {\n\tpublic:\n\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tGraphicViewPortClass(GraphicBufferClass* graphic_buff, int x, int y, int w, int h);\n\t\tGraphicViewPortClass();\n\t\t~GraphicViewPortClass();\n\n\t\t/*===================================================================*/\n\t\t/* define functions to get at the private data members\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\tGet_Offset(void);\n\t\tint\tGet_Height(void);\n\t\tint\tGet_Width(void);\n\t\tint\tGet_XAdd(void);\n\t\tint\tGet_XPos(void);\n\t\tint\tGet_YPos(void);\n\t\tint\tGet_Pitch(void);\n\t\tinline BOOL\tGet_IsDirectDraw(void);\n\t\tGraphicBufferClass\t*Get_Graphic_Buffer(void);\n\n\t\t/*===================================================================*/\n\t\t/* Define a function which allows us to change a video viewport on\t*/\n\t\t/*\t\tthe fly.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBOOL Change(int x, int y, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the set of common graphic functions that are supported by\t*/\n\t\t/*\t\tboth Graphic ViewPorts and VideoViewPorts.\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\tSize_Of_Region(int w, int h);\n\t\tvoid\tPut_Pixel(int x, int y, unsigned char color);\n\t\tint\tGet_Pixel(int x, int y);\n\t\tvoid\tClear(unsigned char color = 0);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, void *buff, long size);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, BufferClass *buff);\n\t\tlong\tTo_Buffer(BufferClass *buff);\n\t\tHRESULT\tBlit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel,\n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tHRESULT\tBlit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tHRESULT\tBlit(\tGraphicViewPortClass& dest, BOOL trans = FALSE);\n\t\tHRESULT\tBlit(\tVideoViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel,\n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tHRESULT\tBlit(\tVideoViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tHRESULT\tBlit(\tVideoViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, char *remap);\n\t\tunsigned long\tPrint(char const *string, int x_pixel, int y_pixel, int fcolor, int bcolor);\n\t\tunsigned long\tPrint(short num, int x_pixel, int y_pixel, int fcol, int bcol);\n\t\tunsigned long\tPrint(int num, int x_pixel, int y_pixel, int fcol, int bcol);\n\t\tunsigned long\tPrint(long num, int x_pixel, int y_pixel, int fcol, int bcol);\n\n\t\t/*===================================================================*/\n\t\t/* Define the list of graphic functions which work only with a \t\t*/\n\t\t/*\t\tgraphic buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Draw_Line(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Draw_Rect(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Fill_Rect(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Fill_Quad(VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\tint x2, int y2, int x3, int y3, int color);\n\t\tVOID Remap(int sx, int sy, int width, int height, VOID *remap);\n\t\tVOID Remap(VOID *remap);\n\t\tvoid Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap);\n\t\tvoid Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int clip_window);\n\n//\tThis doesnt seem to exist anywhere?? - Steve T 9/26/95 6:05PM\n//\t\tVOID Grey_Out_Region(int x, int y, int width, int height, int color);\n\n\t\t//\n\t\t// New members to lock and unlock the direct draw video memory\n\t\t//\n\t\tinline BOOL \tLock ();\n\t\tinline BOOL \tUnlock();\n\t\tinline int\t\tGet_LockCount();\n\n\t\t// Member to blit using direct draw access to hardware blitter\n\t\tHRESULT DD_Linear_Blit_To_Linear ( GraphicViewPortClass &dest, int source_x, int source_y, int dest_x, int dest_y, int width\t, int height, BOOL mask );\n\n\t\t/*===================================================================*/\n\t\t/* Define functions to attach the viewport to a graphicbuffer\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Attach(GraphicBufferClass *graphic_buff, int x, int y, int w, int h);\n\t\tvoid Attach(GraphicBufferClass *video_buff, int w, int h);\n\n\tprotected:\n\n\t\t/*===================================================================*/\n\t\t/* Define the data used by a GraphicViewPortClass\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\t\t\t\t\tOffset;\t\t\t// offset to graphic page\n\t\tint\t\t\t\t\t\tWidth;\t\t\t// width of graphic page\n\t\tint\t\t\t\t\t\tHeight;\t\t\t// height of graphic page\n\t\tint\t\t\t\t\t\tXAdd;\t\t\t// xadd for graphic page (0)\n\t\tint\t\t\t\t\t\tXPos;\t\t\t// x offset in relation to graphicbuff\n\t\tint\t\t\t\t\t\tYPos;\t\t\t// y offset in relation to graphicbuff\n\t\tlong\t\t\t\t\tPitch;\t\t\t//Distance from one line to the next\n\t\tGraphicBufferClass\t\t*GraphicBuff;\t// related graphic buff\n\t\tBOOL\t\t\t\t\tIsDirectDraw;\t//Flag to let us know if it is a direct draw surface\n\t\tint\t\t\t\t\t\tLockCount;\t\t// Count for stacking locks if non-zero the buffer\n};                                              //   is a locked DD surface\n\n/*=========================================================================*/\n/* GraphicBufferClass - A GraphicBuffer refers to an actual instance of an\t*/\n/*\t\tallocated buffer.  The GraphicBuffer may be drawn to directly \t\t\t*/\n/*\t\tbecuase it inherits a ViewPort which represents its physcial size.\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tBYTE\t  \t*Buffer\t-\t\tis the offset to graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis the width of graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis the height of graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis the xadd of graphic buffer\t\t\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\twill be 0 because it is graphicbuff\t\t\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\twill be 0 because it is graphicbuff\t\t\t*/\n/*\t\t\tlong\tPitch\t\t-\t\tmodulo of buffer for reading and writing\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tBOOL\tIsDirectDraw - \t\tflag if its a direct draw surface\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nclass GraphicBufferClass : public GraphicViewPortClass, public BufferClass {\n\n\tpublic:\n\t\tGraphicBufferClass(int w, int h, GBC_Enum flags);\n\t\tGraphicBufferClass(int w, int h,\tvoid *buffer, long size);\n\t\tGraphicBufferClass(int w, int h, void *buffer = 0);\n\t\tGraphicBufferClass(void);\n\t\t~GraphicBufferClass();\n\n\t\tvoid DD_Init(GBC_Enum flags);\n\t\tvoid Init(int w, int h, void *buffer, long size, GBC_Enum flags);\n\t\tvoid Un_Init(void);\n\t\tvoid GraphicBufferClass::Attach_DD_Surface (GraphicBufferClass * attach_buffer);\n\t\tBOOL Lock(void);\n\t\tBOOL Unlock(void);\n\n\t\tvoid Scale_Rotate(BitmapClass &bmp,TPoint2D const &pt,long scale,unsigned char angle);\n\n\t\t// Member to get a pointer to a direct draw surface\n\t\tLPDIRECTDRAWSURFACE Get_DD_Surface ( void );\n\n\tprotected:\n\t\tLPDIRECTDRAWSURFACE\tVideoSurfacePtr;\t\t//Pointer to the related direct draw surface\n\t\tDDSURFACEDESC\t\t\tVideoSurfaceDescription;//Description of the said surface\n\n};\n\n\n\ninline int GraphicViewPortClass::Get_LockCount(void)\n{\n\treturn (LockCount);\n}\n\n\n\n/***********************************************************************************************\n * GVPC::Get_IsDirectDraw -- provide read access to the IsDirectDraw flag                      *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   IsDirectDraw                                                                      *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/29/95 1:02PM ST : Created                                                             *\n *=============================================================================================*/\ninline BOOL GraphicViewPortClass::Get_IsDirectDraw(void)\n{\n\treturn (IsDirectDraw);\n}\n\n\n\n/***********************************************************************************************\n * GBC::Get_DD_Surface -- returns a pointer to the buffer direct draw surface                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   ptr to direct draw surface                                                        *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/29/95 9:43AM ST : Created                                                              *\n *=============================================================================================*/\ninline LPDIRECTDRAWSURFACE GraphicBufferClass::Get_DD_Surface ( void )\n{\n\treturn ( VideoSurfacePtr );\n\n}\n\n\n\n/***********************************************************************************************\n * GVPC::Lock -- lock the graphics buffer for reading or writing                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   TRUE if surface was successfully locked                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09-19-95 12:33pm ST : Created                                                             *\n *   10/09/1995     : Moved actually functionality to GraphicBuffer                            *\n *=============================================================================================*/\ninline BOOL GraphicViewPortClass::Lock(void)\n{\n\tBOOL lock = GraphicBuff->Lock();\n\tif ( !lock ) return(FALSE);\n\n\tif (this != GraphicBuff) {\n\t\tAttach(GraphicBuff, XPos, YPos,  Width, Height);\n\t}\n\treturn(TRUE);\n}\n\n/***********************************************************************************************\n * GVPC::Unlock -- unlock the video buffer                                                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   TRUE if surface was successfully unlocked                                         *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09-19-95 02:20pm ST : Created                                                             *\n *   10/09/1995     : Moved actually functionality to GraphicBuffer                            *\n *=============================================================================================*/\ninline BOOL GraphicViewPortClass::Unlock(void)\n{\n\tBOOL unlock = GraphicBuff->Unlock();\n\tif (!unlock) return(FALSE);\n\tif (this != GraphicBuff && IsDirectDraw && !GraphicBuff->LockCount) {\n\t\tOffset = 0;\n\t}\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * GVPC::GET_OFFSET -- Get offset for virtual view port class instance     *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long the offset for the virtual viewport instance           *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long GraphicViewPortClass::Get_Offset(void)\n{\n\treturn(Offset);\n}\n\n/***************************************************************************\n * GVPC::GET_HEIGHT -- Gets the height of a virtual viewport instance      *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the height of the virtual viewport instance            *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_Height(void)\n{\n\treturn(Height);\n}\n\n/***************************************************************************\n * GVPC::GET_WIDTH -- Get the width of a virtual viewport instance\t\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the width of the virtual viewport instance             *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_Width(void)\n{\n\treturn(Width);\n}\n\n\n/***************************************************************************\n * GVPC::GET_XADD -- Get the X add offset for virtual viewport instance    *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the xadd for a virtual viewport instance               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_XAdd(void)\n{\n\treturn(XAdd);\n}\n/***************************************************************************\n * GVPC::GET_XPOS -- Get the x pos of the VP on the Video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_XPos(void)\n{\n\treturn(XPos);\n}\n\n\n/***************************************************************************\n * GVPC::GET_YPOS -- Get the y pos of the VP on the video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_YPos(void)\n{\n\treturn(YPos);\n}\n\n/***************************************************************************\n * GVPC::GET_GRAPHIC_BUFFER -- Get the graphic buffer of the VP.            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline GraphicBufferClass *GraphicViewPortClass::Get_Graphic_Buffer(void)\n{\n\treturn (GraphicBuff);\n}\n\n/***************************************************************************\n * GVPC::SIZE_OF_REGION -- stub to call curr graphic mode Size_Of_Region\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/01/1995 BWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::Size_Of_Region(int w, int h)\n{\n\treturn Buffer_Size_Of_Region(this, w, h);\n}\n\n\n/***************************************************************************\n * GVPC::PUT_PIXEL -- stub to call curr graphic mode Put_Pixel\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tGraphicViewPortClass::Put_Pixel(int x, int y, unsigned char color)\n{\n\n\tif (Lock()){\n\t\tBuffer_Put_Pixel(this, x, y, color);\n\t}\n\tUnlock();\n\n\n}\n\n/***************************************************************************\n * GVPC::GET_PIXEL -- stub to call curr graphic mode Get_Pixel          \t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline int\tGraphicViewPortClass::Get_Pixel(int x, int y)\n{\n\tint\t\treturn_code=0;\n\n\tif (Lock()){\n\t\treturn_code=(Buffer_Get_Pixel(this, x, y));\n\t}\n\tUnlock();\n\treturn(return_code);\n\n}\n\n/***************************************************************************\n * GVPC::CLEAR -- stub to call curr graphic mode Clear\t                  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tGraphicViewPortClass::Clear(unsigned char color)\n{\n\tif (Lock()){\n\t\tBuffer_Clear(this, color);\n\t}\n\tUnlock();\n\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 1 to call curr graphic mode To_Buffer\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(int x, int y, int w, int h, void *buff, long size)\n{\n\tlong\treturn_code=0;\n\tif (Lock()){\n\t\treturn_code = (Buffer_To_Buffer(this, x, y, w, h, buff, size));\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 2 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(int x, int y, int w, int h, BufferClass *buff)\n{\n\tlong\treturn_code=0;\n\tif (Lock()){\n\t\treturn_code = (Buffer_To_Buffer(this, x, y, w, h, buff->Get_Buffer(), buff->Get_Size()));\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 3 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(BufferClass *buff)\n{\n\tlong\treturn_code=0;\n\tif (Lock()){\n\t\treturn_code = (Buffer_To_Buffer(this, 0, 0, Width, Height, buff->Get_Buffer(), buff->Get_Size()));\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 1 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline HRESULT\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel,\n\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans)\n{\n\tHRESULT\t\treturn_code=0;\n\n\tif ( IsDirectDraw && dest.IsDirectDraw ){\n\treturn(DD_Linear_Blit_To_Linear( dest, XPos+x_pixel, YPos+y_pixel\n\t\t\t\t\t\t\t\t, dest.Get_XPos()+dx_pixel, dest.Get_YPos()+dy_pixel\n\t\t\t\t\t\t\t\t, pixel_width, pixel_height, trans));\n\t} else {\n\n\t\tif (Lock()){\n\t\t\tif (dest.Lock()){\n\t\t\t\treturn_code=(Linear_Blit_To_Linear(this, &dest, x_pixel, y_pixel\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t, dx_pixel, dy_pixel\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t, pixel_width, pixel_height, trans));\n\t\t\t}\n\t\t\tdest.Unlock();\n\t\t}\n\t\tUnlock();\n\t}\n\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::BLIT -- Stub 2 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline HRESULT\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans)\n{\n\tHRESULT\t\treturn_code=0;\n\n\n\tif ( IsDirectDraw && dest.IsDirectDraw ){\n\treturn(DD_Linear_Blit_To_Linear( dest, XPos, YPos\n\t\t\t\t\t\t\t\t, dest.Get_XPos()+dx, dest.Get_YPos()+dy\n\t\t\t\t\t\t\t\t, Width, Height, trans));\n\t} else {\n\n\t\tif (Lock()){\n\t\t\tif (dest.Lock()){\n\t\t\t\treturn_code=(Linear_Blit_To_Linear(this, &dest, 0, 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t, dx, dy\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t, Width, Height, trans));\n\t\t\t}\n\t\t\tdest.Unlock();\n\t\t}\n\t\tUnlock();\n\t}\n\n\treturn (return_code);\n\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 3 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline HRESULT\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, BOOL trans)\n{\n\tHRESULT\t\treturn_code=0;\n\n\n\tif ( IsDirectDraw && dest.IsDirectDraw ){\n\treturn(DD_Linear_Blit_To_Linear( dest, XPos, YPos\n\t\t\t\t\t\t\t\t, dest.Get_XPos(), dest.Get_YPos()\n\t\t\t\t\t\t\t\t, MAX( Width, dest.Get_Width())\n\t\t\t\t\t\t\t\t, MAX( Height, dest.Get_Height())\n\t\t\t\t\t\t\t\t, trans));\n\t} else {\n\n\t\tif (Lock()){\n\t\t\tif (dest.Lock()){\n\t\t\t\treturn_code=(Linear_Blit_To_Linear(this, &dest, 0, 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t, 0, 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t, Width, Height, trans));\n\t\t\t}\n\t\t\tdest.Unlock();\n\t\t}\n\t\tUnlock();\n\t}\n\n\treturn (return_code);\n\n}\n\n\n/***************************************************************************\n * GVPC::SCALE -- stub 1 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans, char *remap)\n{\n\tBOOL\treturn_code=0;\n\tif (Lock()){\n\t\tif (dest.Lock()){\n\t\t\treturn_code = (Linear_Scale_To_Linear(this, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, trans, remap));\n\t\t}\n\t\tdest.Unlock();\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 2 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap)\n{\n\tBOOL\treturn_code=0;\n\tif (Lock()){\n\t\tif (dest.Lock()){\n\t\t\treturn_code = (Linear_Scale_To_Linear(this, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, FALSE, remap));\n\t\t}\n\t\tdest.Unlock();\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 3 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, BOOL trans, char *remap)\n{\n\tBOOL\treturn_code=0;\n\tif (Lock()){\n\t\tif (dest.Lock()){\n\t\t\treturn_code = (Linear_Scale_To_Linear(this,\t&dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), trans, remap));\n\t\t}\n\t\tdest.Unlock();\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 4 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, char *remap)\n{\n\tBOOL\treturn_code=0;\n\tif (Lock()){\n\t\tif (dest.Lock()){\n\t\t\treturn_code = (Linear_Scale_To_Linear(this, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), FALSE, remap));\n\t\t}\n\t\tdest.Unlock();\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n/***************************************************************************\n * GVPC::PRINT -- stub func to print a text string                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/17/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(char const *str, int x, int y, int fcol, int bcol)\n{\n\tunsigned long\treturn_code=0;\n\tif (Lock()){\n\t\treturn_code = (Buffer_Print(this, str, x, y, fcol, bcol));\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::PRINT -- Stub function to print an integer                        *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(int num, int x, int y, int fcol, int bcol)\n{\n\tchar str[17];\n\n\tunsigned long\treturn_code=0;\n\tif (Lock()){\n\t\treturn_code = (Buffer_Print(this, itoa(num, str, 10), x, y, fcol, bcol));\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::PRINT -- Stub function to print a short to a graphic viewport     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(short num, int x, int y, int fcol, int bcol)\n{\n\tchar str[17];\n\n\tunsigned long\treturn_code=0;\n\tif (Lock()){\n\t\treturn_code = (Buffer_Print(this, itoa(num, str, 10), x, y, fcol, bcol));\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::PRINT -- stub function to print a long on a graphic view port     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(long num, int x, int y, int fcol, int bcol)\n{\n\tchar str[33];\n\n\tunsigned long\treturn_code=0;\n\tif (Lock()){\n\t\treturn_code = (Buffer_Print(this, ltoa(num, str,10), x, y, fcol, bcol));\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::DRAW_STAMP -- stub function to draw a tile on a graphic view port *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline void GraphicViewPortClass::Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap)\n{\n\tif (Lock()){\n\t\tBuffer_Draw_Stamp(this, icondata, icon, x_pixel, y_pixel, remap);\n\t}\n\tUnlock();\n}\n\n\n\n/***************************************************************************\n * GVPC::DRAW_STAMP -- stub function to draw a tile on a graphic view port *\n *                     This version clips the tile to a window             *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *    07/31/1995 BWG : Created.                                            *\n *=========================================================================*/\nextern BOOL IconCacheAllowed;\ninline void GraphicViewPortClass::Draw_Stamp(void const * icondata, int icon, int x_pixel, int y_pixel, void const * remap, int clip_window)\n{\n\tint\tcache_index=-1;\n\n   int drewit = 0;\n\tif (IconCacheAllowed){\n\t\tif (IsDirectDraw){\n\t\t\tif (!remap){\n\t\t\t\tcache_index = Is_Icon_Cached(icondata,icon);\n\t\t\t}\n\n\t\t\tif (cache_index != -1){\n\t\t\t\tif (CachedIcons[cache_index].Get_Is_Cached()  ){\n\t\t\t\t\tCachedIcons[cache_index].Draw_It (GraphicBuff->Get_DD_Surface() , x_pixel, y_pixel,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[clip_window][WINDOWX] + XPos,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[clip_window][WINDOWY] +YPos,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[clip_window][WINDOWWIDTH],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[clip_window][WINDOWHEIGHT]);\n\t\t\t\t\tCachedIconsDrawn++;\n               drewit = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n   if (drewit == 0) {\n\t\tif (Lock()){\n\t\t\tUnCachedIconsDrawn++;\n\t\t\tBuffer_Draw_Stamp_Clip(this, icondata, icon, x_pixel, y_pixel, remap, WindowList[clip_window][WINDOWX], WindowList[clip_window][WINDOWY], WindowList[clip_window][WINDOWWIDTH], WindowList[clip_window][WINDOWHEIGHT]);\n\t\t}\n   }\n\tUnlock();\n}\n\n\n/***************************************************************************\n * GVPC::DRAW_LINE -- Stub function to draw line in Graphic Viewport Class *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Draw_Line(int sx, int sy, int dx, int dy, unsigned char color)\n{\n\tif (Lock()){\n\t\tBuffer_Draw_Line(this, sx, sy, dx, dy, color);\n\t}\n\tUnlock();\n}\n\n/***************************************************************************\n * GVPC::FILL_RECT -- Stub function to fill rectangle in a GVPC            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Fill_Rect(int sx, int sy, int dx, int dy, unsigned char color)\n{\n\tif (  AllowHardwareBlitFills\n\t\t\t&& IsDirectDraw\n\t\t\t&& ( (dx-sx) * (dy-sy) >= (32*32) )\n\t\t\t&& GraphicBuff->Get_DD_Surface()->GetBltStatus(DDGBS_CANBLT) == DD_OK){\n\t\tDDBLTFX\tblit_effects;\n\t\tRECT\tdest_rectangle;\n\n\t\tdest_rectangle.left\t=sx+XPos;\n\t\tdest_rectangle.top\t=sy+YPos;\n\t\tdest_rectangle.right\t=dx+XPos;\n\t\tdest_rectangle.bottom=dy+YPos;\n\n\t\tif (dest_rectangle.left<XPos){\n\t\t\tdest_rectangle.left=XPos;\n\t\t}\n\n\t\tif (dest_rectangle.right >= Width + XPos){\n\t\t\tdest_rectangle.right = Width +XPos -1;\n\t\t}\n\n\t\tif (dest_rectangle.top<YPos){\n\t\t\tdest_rectangle.top=YPos;\n\t\t}\n\n\t\tif (dest_rectangle.bottom >= Height + YPos){\n\t\t\tdest_rectangle.bottom = Height + YPos -1;\n\t\t}\n\n\t\tif (dest_rectangle.left >= dest_rectangle.right)  return;\n\t\tif (dest_rectangle.top  >= dest_rectangle.bottom) return;\n\n\t\tdest_rectangle.right++;\n\t\tdest_rectangle.bottom++;\n\n\t\tblit_effects.dwSize=sizeof(blit_effects);\n\t\tblit_effects.dwFillColor = color;\n\t\tGraphicBuff->Get_DD_Surface()->Blt(&dest_rectangle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tDDBLT_WAIT | DDBLT_ASYNC | DDBLT_COLORFILL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&blit_effects);\n\t} else {\n\t\tif (Lock()){\n\t\t\tBuffer_Fill_Rect(this, sx, sy, dx, dy, color);\n\t\t\tUnlock();\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * GVPC::REMAP -- Stub function to remap a GVPC                            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Remap(int sx, int sy, int width, int height, VOID *remap)\n{\n\tif (Lock()){\n\t\tBuffer_Remap(this, sx, sy, width, height, remap);\n\t}\n\tUnlock();\n}\n\n\ninline VOID GraphicViewPortClass::Fill_Quad(VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\tint x2, int y2, int x3, int y3, int color)\n{\n\tif (Lock()){\n\t\tBuffer_Fill_Quad(this, span_buff, x0, y0, x1, y1, x2, y2, x3, y3, color);\n\t}\n\tUnlock();\n}\n\n/***************************************************************************\n * GVPC::REMAP -- Short form to remap an entire graphic view port          *\n *                                                                         *\n * INPUT:\t\tBYTE * to the remap table to use\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Remap(VOID *remap)\n{\n\tif (Lock()){\n\t\tBuffer_Remap(this, 0, 0, Width, Height, remap);\n\t}\n\tUnlock();\n}\n\ninline int GraphicViewPortClass::Get_Pitch(void)\n{\n\treturn(Pitch);\n}\n/*=========================================================================*/\n/* The following BufferClass functions are defined here because they act\t*/\n/*\t\ton graphic viewports.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n\n/***************************************************************************\n * BUFFER_TO_PAGE -- Generic 'c' callable form of Buffer_To_Page           *\n *                                                                         *\n * INPUT: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/12/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long Buffer_To_Page(int x, int y, int w, int h, void *Buffer, GraphicViewPortClass &view)\n{\n\tlong\treturn_code=0;\n\tif (view.Lock()){\n\t\treturn_code = (Buffer_To_Page(x, y, w, h, Buffer, &view));\n\t}\n\tview.Unlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t*\n *\t\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t*\n *\t\t\t\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int w, int h, GraphicViewPortClass &view)\n{\n\tlong\treturn_code=0;\n\tif (view.Lock()){\n\t\treturn_code = (Buffer_To_Page(0, 0, w, h, Buffer, &view));\n\t}\n\tview.Unlock();\n\treturn ( return_code );\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport.  width and height are assumed to be the\t\t\t*\n *\t\t\t\t\t\tviewport's width and height.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(GraphicViewPortClass &view)\n{\n\tlong\treturn_code=0;\n\tif (view.Lock()){\n\t\treturn_code = (Buffer_To_Page(0, 0, view.Get_Width(), view.Get_Height(), Buffer, &view));\n\t}\n\tview.Unlock();\n\treturn ( return_code );\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable x, y, w, h *\n *                                                                         *\n * INPUT:\tint\tx\t\t\t- x pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\ty\t\t\t- y pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t\t*\n *\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t\t*\n *\t\t\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\tnone                                                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int x, int y, int w, int h, GraphicViewPortClass &view)\n{\n\tlong\treturn_code=0;\n\tif (view.Lock()){\n\t\treturn_code = (Buffer_To_Page(x, y, w, h, Buffer, &view));\n\t}\n\tview.Unlock();\n\treturn ( return_code );\n}\n\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/GBUFFER.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 Bit Library\t\t   *\n;*                                                                         *\n;*                    File Name : GBUFFER.INC                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : May 26, 1994                             *\n;*                                                                         *\n;*                  Last Update : May 26, 1994   [PWG]                     *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n;******************************************************************************\n; Much testing was done to determine that only when there are 14 or more bytes\n; being copied does it speed the time it takes to do copies in this algorithm.\n; For this reason and because 1 and 2 byte copies crash, is the special case\n; used.  SKB 4/21/94.  Tested on 486 66mhz.  Copied by PWG 6/7/04.\nOPTIMAL_BYTE_COPY\tequ\t14\n\nSTRUC GraphicViewPort\nGVPOffset\t\tDD\t\t?\t\t; offset to virtual viewport\nGVPWidth\t\t\tDD\t\t?\t\t; width of virtual viewport\nGVPHeight\t\tDD\t\t?\t\t; height of virtual viewport\nGVPXAdd\t\t\tDD\t\t?\t\t; x mod to get to next line\nGVPXPos\t\t\tDD\t\t?\t\t; x pos relative to Graphic Buff\nGVPYPos\t\t\tDD\t\t?\t\t; y pos relative to Graphic Buff\nGVPPitch\t\tdd\t\t?\t\t; modulo of graphic view port\nGVPBuffPtr\t\tDD\t\t?\t\t; ptr to associated Graphic Buff\nENDS"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/GETCLIP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : BITBLIT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Julio R. Jerez                           *\n;*                                                                         *\n;*                   Start Date : Feb 6, 1995                              *\n;*                                                                         *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\n; typedef struct {\n;\t\t     int x0 , y0 ;\n;\t\t     int x1 , y1 ;\n;\t\t } CLIP_WIN ;\n; Note for efficiency reasons x1 must be >= x0 and y1 >= y0\n; int get_clip ( CLIP_WIN * window , CLIP_WIN * sorce_rect ) ;\n\nCODESEG\n\n\tPROC\tget_clip C near\n\tUSES\teax , ebx\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG\twin\t    : dword\n\tARG     rect\t    : dword\n\n\n\tmov\tedi , [ rect ]\n\tmov  \tesi , [ win ]\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ (RECTANGLE edi) . x0 ]\n\tmov\tebx , [ (RECTANGLE edi) . x1 ]\n\tsub\tecx , [ (RECTANGLE esi) . x0 ]\n\tsub\tebx , [ (RECTANGLE esi) . x0 ]\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n;\tmov\tebx , [ (RECTANGLE esi) . x1 ]\n;\tinc\tebx\n;\tmov\t[ rect ] , ebx\n\tmov\tecx , [ (RECTANGLE edi) . x0 ]\n\tmov\tebx , [ (RECTANGLE edi) . x1 ]\n\tsub\tecx , [ (RECTANGLE esi) . x1 ]\n\tsub\tebx , [ (RECTANGLE esi) . x1 ]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ (RECTANGLE edi) . y0 ]\n\tmov\tebx , [ (RECTANGLE edi) . y1 ]\n\tsub\tecx , [ (RECTANGLE esi) . y0 ]\n\tsub\tebx , [ (RECTANGLE esi) . y0 ]\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n;\tmov\tebx , [ (RECTANGLE esi) . y1 ]\n;\tinc\tebx\n;\tmov\t[ rect ] , ebx\n\tmov\tecx , [ (RECTANGLE edi) . y0 ]\n\tmov\tebx , [ (RECTANGLE edi) . y1 ]\n\tsub\tecx , [ (RECTANGLE esi) . y1 ]\n\tsub\tebx , [ (RECTANGLE esi) . y1 ]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , dl\n\tret\n       ENDP\tget_clip\n\n\n\nEND"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/GETPIX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : GraphicViewPortClass\t\t\t   *\n;*                                                                         *\n;*                    File Name : GETPIXEL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : June 7, 1994   [PWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVPC::Buffer_Get_Pixel -- get the colour of a pixel at given coords   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n;***************************************************************************\n;* VVPC::GET_PIXEL -- Gets a pixel from the current view port\t\t   *\n;*                                                                         *\n;* INPUT:\tWORD the x pixel on the screen.\t\t\t\t   *\n;*\t\tWORD the y pixel on the screen.\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      UBYTE the pixel at the specified location\t\t   *\n;*                                                                         *\n;* WARNING:\tIf pixel is to be placed outside of the viewport then\t   *\n;*\t\tthis routine will abort.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/07/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_Get_Pixel C near\n\tUSES\tebx,ecx,edx,edi\n\n\tARG    \tthis_object:DWORD\t\t\t\t; this is a member function\n\tARG\tx_pixel:DWORD\t\t\t\t; x position of pixel to set\n\tARG\ty_pixel:DWORD\t\t\t\t; y position of pixel to set\n\n\t;*===================================================================\n\t; Get the viewport information and put bytes per row in ecx\n\t;*===================================================================\n\tmov\tebx,[this_object]\t\t\t\t; get a pointer to viewport\n\txor\teax,eax\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get the correct offset\n\tmov\tecx,[(GraphicViewPort ebx).GVPHeight]\t; edx = height of viewport\n\tmov\tedx,[(GraphicViewPort ebx).GVPWidth]\t; ecx = width of viewport\n\n\t;*===================================================================\n\t; Verify that the X pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[x_pixel]\t\t\t\t; find the x position\n\tcmp\teax,edx\t\t\t\t\t;   is it out of bounds\n\tjae\tshort ??exit\t\t\t\t; if so then get out\n\tadd\tedi,eax\t\t\t\t\t; otherwise add in offset\n\n\t;*===================================================================\n\t; Verify that the Y pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[y_pixel]\t\t\t\t; get the y position\n\tcmp\teax,ecx\t\t\t\t\t;  is it out of bounds\n\tjae\t??exit\t\t\t\t\t; if so then get out\n\tadd\tedx,[(GraphicViewPort ebx).GVPXAdd]\t; otherwise find bytes per row\n\tadd\tedx,[(GraphicViewPort ebx).GVPPitch]\t; otherwise find bytes per row\n\tmul\tedx\t\t\t\t\t; offset = bytes per row * y\n\tadd\tedi,eax\t\t\t\t\t; add it into the offset\n\n\t;*===================================================================\n\t; Write the pixel to the screen\n\t;*===================================================================\n\txor\teax,eax\t\t\t\t\t; clear the word\n\tmov\tal,[edi]\t\t\t\t; read in the pixel\n??exit:\n\tret\n\tENDP\tBuffer_Get_Pixel\n\nEND"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/ICONCACH.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***             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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Drawbuff - Westwood win95 library                            *\n *                                                                                             *\n *                    File Name : Iconcach.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : November 8th, 1995                                           *\n *                                                                                             *\n *                  Last Update : November 13th, 1995 [ST]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview: This file cantains members of the IconCacheClass and associated non member        *\n *           functions. All functions are to do with caching individual icons from icon sets   *\n *           into video memory to improve the speed of subsequent drawing                      *\n *                                                                                             *\n * Functions:                                                                                  *\n *  Cache_New_Icon -- Call the Cache_It member to cache a registered icon to video memory      *\n *  Invalidate_Cached_Icons -- Uncache all the icons                                           *\n *  Restore_Cached_Icons -- restore cached icons after a focus loss                            *\n *  Register_Icon_Set -- register an icon set as cachable                                      *\n *  Get_Free_Cache_Slot -- find an empty cache slot                                            *\n *  IconCacheClass::IconCacheClass -- IconCacheClass constructor                               *\n *  IconCacheClass::~IconCacheClass -- IconCacheClass destructor                               *\n *  IconCacheClass::Restore -- restore the icons surface and recache it                        *\n *  IconCacheClass::Cache_It -- cache an icon into video memory                                *\n *  IconCacheClass::Uncache_It -- restore the video memory used by a cached icon               *\n *  IconCacheClass::Draw_It -- use the blitter to draw the cached icon                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#define\tWIN32_LEAN_AND_MEAN\n#define\t_WIN32\n\n#include <windows.h>\n#include \"ddraw.h\"\n#include \"misc.h\"\n#include \"iconcach.h\"\n#include \"gbuffer.h\"\n\n\nstatic\tDDSURFACEDESC\tVideoSurfaceDescription;\n\nIconCacheClass\tCachedIcons[MAX_CACHED_ICONS];\n\nextern \"C\"{\nIconSetType\t\tIconSetList[MAX_ICON_SETS];\nshort\t\t\t\tIconCacheLookup[MAX_LOOKUP_ENTRIES];\n}\n\nint\t\tCachedIconsDrawn=0;\t\t//Counter of number of cache hits\nint\t\tUnCachedIconsDrawn=0;\t//Counter of number of cache misses\nBOOL\tCacheMemoryExhausted;\t//Flag set if we have run out of video RAM\n\n\n\n\n/***********************************************************************************************\n * Optimise_Video_Memory_Cache -- optimises usage of video memory                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   TRUE if memory was freed up                                                       *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/29/95 12:47PM ST : Created                                                            *\n *=============================================================================================*/\nBOOL Optimize_Video_Memory_Cache (void)\n{\n\n\tif (CacheMemoryExhausted &&\n\t\t(UnCachedIconsDrawn+CachedIconsDrawn > 1000) &&\n\t\tUnCachedIconsDrawn > CachedIconsDrawn){\n\n\t\tint\tcache_misses[MAX_CACHED_ICONS];\n\t\tint\tcache_hits[MAX_CACHED_ICONS];\n\t\tint\ttotal_cache_misses=0;\n\t\tint\ttotal_cache_hits=0;\n\t\tint\tcounter;\n\t\tint\ti;\n\t\tint\tj;\n\t\tint\ttemp;\n\t\tBOOL\tswapped;\n\n\t\t/*\n\t\t** make list of icons that have failed to cache more than 5 times\n\t\t*/\n\t\tfor (counter=0 ; counter<MAX_CACHED_ICONS ; counter++){\n\n\t\t\tif (CachedIcons[counter].TimesFailed>5){\n\t\t\t\tcache_misses[total_cache_misses++] = counter;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Make list of icons that have been drawn less than 3 times\n\t\t*/\n\t\tfor (counter=0 ; counter<MAX_CACHED_ICONS ; counter++){\n\n\t\t\tif (CachedIcons[counter].TimesDrawn<3){\n\t\t\t\tcache_hits[total_cache_hits++] = counter;\n\t\t\t}\n\t\t}\n\n\n\t\t/*\n\t\t** Sort drawn icons into order\n\t\t*/\n\t\tif (total_cache_hits > 1){\n\t\t\tfor (i = 0 ; i<total_cache_hits ; i++){\n\t\t\t\tswapped=FALSE;\n\t\t\t\tfor (j=0 ; j<total_cache_hits-1 ; j++){\n\n\t\t\t\t\tif (CachedIcons[cache_hits[j]].TimesDrawn > CachedIcons[cache_hits[j+1]].TimesDrawn){\n\t\t\t\t\t\ttemp=cache_hits[j];\n\t\t\t\t\t\tcache_hits[j]=cache_hits[j+1];\n\t\t\t\t\t\tcache_hits[j+1]=temp;\n\t\t\t\t\t\tswapped = TRUE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!swapped) break;\n\t\t\t}\n\t\t}\n\n\n\t\t/*\n\t\t** Uncache icons up to the number of failed icons\n\t\t*/\n\n\t\tfor (counter=0 ; counter<total_cache_misses && counter<total_cache_hits; counter++){\n\t\t\tCachedIcons[cache_hits[counter]].Uncache_It();\n\t\t}\n\n\t\tCacheMemoryExhausted=FALSE;\n\t\tCachedIconsDrawn=0;\n\t\tUnCachedIconsDrawn=0;\n\t\treturn (TRUE);\n\t}\n\treturn (FALSE);\n\n}\n\n\n\n\n\n/***********************************************************************************************\n * Cache_New_Icon -- cache a registered icon to video memory                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    icon_index -- index into registered icon table of icon to cache                   *\n *           icon_ptr -- ptr to icon data                                                      *\n *                                                                                             *\n * OUTPUT:   BOOL success                                                                      *\n *                                                                                             *\n * WARNINGS: icon must already have been registered and assigned an index                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:36AM ST : Created                                                             *\n *=============================================================================================*/\nBOOL Cache_New_Icon (int icon_index, void *icon_ptr)\n{\n\tif (!CacheMemoryExhausted){\n\t\treturn (CachedIcons[icon_index].Cache_It(icon_ptr));\n\t} else {\n\t\tCachedIcons[icon_index].TimesFailed++;\n\t\tif (Optimize_Video_Memory_Cache()){\n\t\t\treturn (CachedIcons[icon_index].Cache_It(icon_ptr));\n\t\t} else {\n\t\t\treturn (FALSE);\n\t\t}\n\t}\n}\n\n\n\n\n\n/***********************************************************************************************\n * Invalidat_Cached_Icons -- used to release any icons that have been cached                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:37AM ST : Created                                                             *\n *=============================================================================================*/\nvoid Invalidate_Cached_Icons (void)\n{\n\tfor (int i=0 ; i<MAX_CACHED_ICONS ; i++){\n\t\tCachedIcons[i].Uncache_It();\n\t}\n\n\tmemset (&IconCacheLookup[0] , -1 ,MAX_LOOKUP_ENTRIES*sizeof(IconCacheLookup[0]));\n\n\tfor (i=0 ; i<MAX_ICON_SETS ; i++){\n\t\tIconSetList[i].IconSetPtr=NULL;\n\t}\n\n\tCacheMemoryExhausted=FALSE;\n}\n\n\n\n\n/***********************************************************************************************\n * Restore_Cached_Icons -- re-cache icons into video memory after a loss of focus              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: Assumes that the pointers that were originally used to cache the icons            *\n *           are still valid.                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:38AM ST : Created                                                             *\n *=============================================================================================*/\nvoid Restore_Cached_Icons (void)\n{\n\tfor (int i=0 ; i<MAX_CACHED_ICONS ; i++){\n\t\tCachedIcons[i].Restore();\n\t}\n\tCacheMemoryExhausted=FALSE;\n}\n\n\n\n/***********************************************************************************************\n * Register_Icon_Set -- used to register an icon set as cachable                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    icon_data - ptr to icon set                                                       *\n *           pre_cache -- should we pre-cache the icon data?                                   *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:39AM ST : Created                                                             *\n *=============================================================================================*/\nvoid Register_Icon_Set (void *icon_data , BOOL pre_cache)\n{\n\n\tfor (int i=0 ; i<MAX_ICON_SETS ; i++){\n\t\tif (!IconSetList[i].IconSetPtr){\n\t\t\tIconSetList[i].IconSetPtr = (IControl_Type*)icon_data;\n\n\t\t\tif (i){\n\t\t\t\tIControl_Type *previous_set = IconSetList[i-1].IconSetPtr;\n\t\t\t\tIconSetList[i].IconListOffset = IconSetList[i-1].IconListOffset + ((int)previous_set->Count)*2;\n\t\t\t\tif (IconSetList[i].IconListOffset > MAX_LOOKUP_ENTRIES*2){\n\t\t\t\t\tIconSetList[i].IconSetPtr = NULL;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tIconSetList[i].IconListOffset = 0;\n\t\t\t}\n\n\t\t\tif (pre_cache){\n\t\t\t\tfor (i=0 ; i<256 ; i++){\n\t\t\t\t\tIs_Icon_Cached(icon_data,i);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n\n\n/***********************************************************************************************\n * Get_Free_Cache_Slot -- find a free slot in which to cache an icon                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   int - icon index                                                                  *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:40AM ST : Created                                                             *\n *=============================================================================================*/\nint Get_Free_Cache_Slot (void)\n{\n\tfor (int i=0 ; i<MAX_CACHED_ICONS ; i++){\n\t\tif (!CachedIcons[i].Get_Is_Cached()){\n\t\t\treturn (i);\n\t\t}\n\t}\n\treturn (-1);\n}\n\n\n\n/***********************************************************************************************\n * ICC::IconCacheClass -- constructor for icon cache class                                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:41AM ST : Created                                                             *\n *=============================================================================================*/\nIconCacheClass::IconCacheClass (void)\n{\n\tIsCached\t\t\t=FALSE;\n\tSurfaceLost\t\t=FALSE;\n\tDrawFrequency\t=0;\n\tCacheSurface\t=NULL;\n\tIconSource\t\t=NULL;\n}\n\n\n\n/***********************************************************************************************\n * ICC::~IconCacheClass -- destructor for icon cache class                                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:41AM ST : Created                                                             *\n *=============================================================================================*/\nIconCacheClass::~IconCacheClass (void)\n{\n\tif (IsCached && CacheSurface){\n\t\tCacheSurface->Release();\n\t}\n}\n\n\n\n\n/***********************************************************************************************\n * ICC::Restore -- Restores the icons video surface memory and reloads it based on the original*\n *                 icon pointer                                                                *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: Relies on the icons original pointer still being valie                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:43AM ST : Created                                                             *\n *=============================================================================================*/\nvoid IconCacheClass::Restore (void)\n{\n\tif (IsCached && CacheSurface){\n\t\tCacheSurface->Restore();\n\t\tif (IconSource){\n\t\t\tCache_It(IconSource);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * ICC::Cache_It -- allocate video memory and copy an icon to it                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    icon_ptr -- ptr to icon data                                                      *\n *                                                                                             *\n * OUTPUT:   bool -- success?                                                                  *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:44AM ST : Created                                                             *\n *=============================================================================================*/\nBOOL IconCacheClass::Cache_It (void *icon_ptr)\n{\n\tDDSCAPS\tsurface_capabilities;\n\tBOOL\t\treturn_value;\n\n\t/*\n\t** If we dont have a direct draw interface yet then just fail\n\t*/\n\tif (!DirectDrawObject) return(FALSE);\n\n\t/*\n\t** Set up the description of the surface we want to create\n\t*/\n\tmemset (&VideoSurfaceDescription , 0 , sizeof ( VideoSurfaceDescription ));\n\n\tVideoSurfaceDescription.dwSize\t\t\t= sizeof( VideoSurfaceDescription );\n\tVideoSurfaceDescription.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;\n\tVideoSurfaceDescription.dwFlags\t\t\t= DDSD_CAPS |\tDDSD_HEIGHT | DDSD_WIDTH;\n\tVideoSurfaceDescription.dwHeight\t\t\t= ICON_WIDTH;\n\tVideoSurfaceDescription.dwWidth\t\t\t= ICON_HEIGHT;\n\n\t/*\n\t** If this cache object doesnt already have a surface then create one\n\t*/\n\tif (!CacheSurface){\n\t\tif (DD_OK!=DirectDrawObject->CreateSurface( &VideoSurfaceDescription , &CacheSurface , NULL)){\n\t\t\tCacheMemoryExhausted = TRUE;\n\t\t\treturn(FALSE);\n\t\t}\n\n\t}\n\n\t/*\n\t** Make sure the surface we created isnt really in system memory\n\t*/\n\tif (DD_OK != CacheSurface->GetCaps(&surface_capabilities)){\n\t\treturn(FALSE);\n\t}\n\n\tif ((DDSCAPS_SYSTEMMEMORY & surface_capabilities.dwCaps) == DDSCAPS_SYSTEMMEMORY){\n\t\tCacheSurface->Release();\n\t\treturn(FALSE);\n\t}\n\n\treturn_value=FALSE;\n\t/*\n\t** Lock the surface so we can copy the icon to it\n\t*/\n\tif (DD_OK== CacheSurface->Lock ( NULL\n\t\t\t\t\t\t\t\t, &(VideoSurfaceDescription)\n\t\t\t\t\t\t\t\t, DDLOCK_WAIT\n\t\t\t\t\t\t\t\t, NULL)){\n\t\t/*\n\t\t** Copy the icon to the surface and flag that icon is cached\n\t\t*/\n\t\tCache_Copy_Icon (icon_ptr , VideoSurfaceDescription.lpSurface , VideoSurfaceDescription.lPitch);\n\t\tIsCached=TRUE;\n\t\tSurfaceLost=FALSE;\n\t\tIconSource=icon_ptr;\n\t\treturn_value=TRUE;\n\t}\n\tCacheSurface->Unlock(NULL);\n\treturn (return_value);\n}\n\n\n/***********************************************************************************************\n * ICC::Uncache_It -- release the video memory used to cache an icon                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:48AM ST : Created                                                             *\n *=============================================================================================*/\nvoid IconCacheClass::Uncache_It(void)\n{\n\n\tif (IsCached && CacheSurface){\n\t\tCacheSurface->Release();\n\t\tIsCached=FALSE;\n\t\tCacheSurface=NULL;\n\t\tIconSource=NULL;\n\t\tCacheMemoryExhausted=FALSE;\n\t}\n}\n\n\n\n/***********************************************************************************************\n * ICC::Draw_It -- use the blitter to draw a cached icon                                       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    surface to draw to                                                                *\n *           x coord to draw to (relative to window)                                           *\n *           y coord to draw to (relative to window)                                           *\n *           window left coord                                                                 *\n *           window top coord                                                                  *\n *           window width                                                                      *\n *           window height                                                                     *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:48AM ST : Created                                                             *\n *=============================================================================================*/\nvoid IconCacheClass::Draw_It (LPDIRECTDRAWSURFACE dest_surface , int x_pixel, int y_pixel, int window_left , int window_top , int window_width , int window_height)\n{\n\tRECT\t\tsource_rectangle;\n\tRECT\t\tdest_rectangle;\n\tint\t\tclip;\n\tHRESULT\treturn_code;\n\n\t/*\n\t** Set up the source and destination coordinates as required by direct draw\n\t*/\n\tsource_rectangle.left \t= 0;\n\tsource_rectangle.top  \t= 0;\n\tsource_rectangle.right\t= ICON_WIDTH;\n\tsource_rectangle.bottom\t= ICON_HEIGHT;\n\n\tdest_rectangle.left \t= window_left+x_pixel;\n\tdest_rectangle.top  \t= window_top+y_pixel;\n\tdest_rectangle.right\t= dest_rectangle.left+ICON_WIDTH;\n\tdest_rectangle.bottom\t= dest_rectangle.top+ICON_HEIGHT;\n\n\t/*\n\t** Clip the coordinates to the window\n\t*/\n\tif (dest_rectangle.left<window_left){\n\t\tsource_rectangle.left += window_left-dest_rectangle.left;\n\t\tdest_rectangle.left=window_left;\n\t}\n\n\tif (dest_rectangle.right>=window_left+window_width){\n\t\tclip = dest_rectangle.right-(window_left+window_width);\n\t\tsource_rectangle.right -= clip;\n\t\tdest_rectangle.right -= clip;\n\t}\n\n\tif (dest_rectangle.top<window_top){\n\t\tsource_rectangle.top += window_top-dest_rectangle.top;\n\t\tdest_rectangle.top=window_top;\n\t}\n\n\tif (dest_rectangle.bottom>=window_top+window_height){\n\t\tclip = dest_rectangle.bottom-(window_top+window_height);\n\t\tsource_rectangle.bottom -= clip;\n\t\tdest_rectangle.bottom -= clip;\n\t}\n\n\tif (source_rectangle.left>=source_rectangle.right){\n\t\treturn;\n\t}\n\n\tif (source_rectangle.top>=source_rectangle.bottom){\n\t\treturn;\n\t}\n\n\t/*\n\t** Do the blit\n\t*/\n\t\treturn_code = dest_surface->Blt (&dest_rectangle ,\n\t\t\t\t\t\t\t\t\t\t\t\t\tCacheSurface ,\n\t\t\t\t\t\t\t\t\t\t\t\t\t&source_rectangle ,\n\t\t\t\t\t\t\t\t\t\t\t\t\tDDBLT_WAIT |\n\t\t\t\t\t\t\t\t\t\t\t\t\tDDBLT_ASYNC ,\n\t\t\t\t\t\t\t\t\t\t\t\t\tNULL);\n\n\tif (return_code == DDERR_SURFACELOST && Gbuffer_Focus_Loss_Function){\n\t\tGbuffer_Focus_Loss_Function();\n\t}\n\n\tif ( return_code != DDERR_SURFACELOST && return_code != DD_OK ) {\n\t\tchar temp[100];\n\t\tsprintf(temp,\"DD Error code %d\\n\", return_code & 0xFFFF);\n\t\tOutputDebugString(temp);\n\t}\n\n\tTimesDrawn++;\n\n}\n\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/ICONCACH.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***             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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Drawbuff - Westwood win95 library                            *\n *                                                                                             *\n *                    File Name : Iconcach.H                                                   *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : November 8th, 1995                                           *\n *                                                                                             *\n *                  Last Update : November 16th, 1995 [ST]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview: This file cantains definition of the IconCacheClass and associated non member     *\n *           function prototypes.                                                              *\n *                                                                                             *\n * Functions:                                                                                  *\n *  IconCacheClass::Get_Is_Cached -- member to allow access to private IsCached flag           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\n\n#ifndef\tICONCACH_H\n#define\tICONCACH_H\n\n#include\t<tile.h>\n\n#define\tICON_WIDTH\t\t\t24\t\t\t// Icons must be this width to be cached\n#define\tICON_HEIGHT\t\t\t24\t\t\t// Icons must be this height to be cached\n#define\tMAX_CACHED_ICONS\t500\t\t// Maximum number of icons that can be cached\n#define\tMAX_ICON_SETS\t\t100\t\t// Maximum number of icon sets that can be registered\n#define\tMAX_LOOKUP_ENTRIES 3000\t\t// Size of icon index table\n\n\n/*\n** IconCacheClass for tracking individual icons cached into video memory\n**\n** Use Register_Icon_Set to identify a set of icons as cachable. Once registered, the icons\n** will be cached automatically when drawn.\n** Use Invalidate_Cached_Icons at the end of icon drawing to release the video memory used by the\n** caching system.\n** Restore_Cached_Icons may be used to reload the icons into video memory after a focus loss.\n**\n*/\n\nclass IconCacheClass {\n\n\tpublic:\n\n\t\tIconCacheClass (void);\t\t\t\t\t// class constructor\n\t\t~IconCacheClass (void);\t\t\t\t\t// class destructor\n\n\t\tvoid Restore(void);\t\t\t\t\t\t// restore the surface\n\t\tBOOL Cache_It (void * icon_ptr);\t\t// Cache the icon to video memory\n\t\tvoid Uncache_It (void);\t\t\t\t\t// Restore the video memory and flag the icon as uncached\n\t\tvoid Draw_It (LPDIRECTDRAWSURFACE dest_surface , int x_pixel, int y_pixel, int window_left , int window_top , int window_width , int window_height);\n\t\tinline BOOL Get_Is_Cached(void);\t\t// Return the IsCached member\n\n\t\tint\t\t\t\t\t\tTimesDrawn;\t\t// counter of times cached icon has been drawn\n\t\tint\t\t\t\t\t\tTimesFailed;\t// counter of times cached icon has failed to draw\n\n\n\tprivate:\n\n\t\tLPDIRECTDRAWSURFACE\tCacheSurface;\t// Ptr to direct draw surface where icon resides\n\t\tBOOL\t\t\t\t\t\tIsCached;\t\t// Flag to say whether an icon is cached\n\t\tBOOL\t\t\t\t\t\tSurfaceLost;\t// Flag to indicate that our icons surface has been lost\n\t\tint\t\t\t\t\t\tDrawFrequency;\t// Number of times icon has been drawn\n\t\tvoid\t\t\t\t\t\t*IconSource;\t// Ptr to original icon data in system memory\n\n};\n\n\n\n/*\n** Structure to keep track of registered icon sets\n**\n*/\n\ntypedef struct tIconSetType{\n\tIControl_Type\t*IconSetPtr;\t\t\t\t// Ptr to icon set data\n\tint\t\t\t\tIconListOffset;\t\t\t// Offset into icon index table for this icon set\n}IconSetType;\n\n\nextern\tIconCacheClass\tCachedIcons[MAX_CACHED_ICONS];\n\nextern void Invalidate_Cached_Icons (void);\nextern void Restore_Cached_Icons (void);\nextern void Register_Icon_Set (void *icon_data , BOOL pre_cache);\n\n//\n// Prototypes for assembly language procedures in STMPCACH.ASM\n//\nextern \"C\" void Clear_Icon_Pointers (void);\nextern \"C\" void Cache_Copy_Icon (void const *icon_ptr ,void * , int);\nextern \"C\" int Is_Icon_Cached (void const *icon_data , int icon);\nextern \"C\" int Get_Icon_Index (void *icon_ptr);\nextern \"C\" int Get_Free_Index (void);\nextern \"C\" BOOL Cache_New_Icon (int icon_index, void *icon_ptr);\nextern \"C\" int Get_Free_Cache_Slot(void);\n\n\nextern\tint\tCachedIconsDrawn;\nextern\tint\tUnCachedIconsDrawn;\n\n\n/***********************************************************************************************\n * ICC::Get_Is_Cached -- member to allow access to the private IsCached flag                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   IsCached                                                                          *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:42AM ST : Created                                                             *\n *=============================================================================================*/\ninline BOOL IconCacheClass::Get_Is_Cached (void)\n{\n\treturn (IsCached);\n}\n\n\n\n\n\n#endif\t//ICONCACH_H\n\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = drawbuff\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS = \t\t\t&\n\tbitblit.obj \t&\n\tbuffer.obj \t\t&\n\tbuffglbl.obj\t&\n\tclear.obj \t\t&\n\tdrawline.obj \t&\n\tdrawrect.obj \t&\n\tfillquad.obj \t&\n\tfillrect.obj \t&\n\tgbuffer.obj \t&\n\tgetclip.obj\t\t&\n\tgetpix.obj \t\t&\n\tputpix.obj \t\t&\n\tregionsz.obj \t&\n\tremap.obj \t\t&\n\tscale.obj \t\t&\n\tstamp.obj \t\t&\n\tszregion.obj \t&\n\ttobuff.obj \t\t&\n\ttopage.obj\t\t&\n\ttxtprnt.obj \t&\n\ticoncach.obj\t&\n\tstmpcach.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\n#**************************** End of makefile ******************************\n\u001a\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = drawbuff\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t   bitblit.obj\t\t\\\n   \t\t\tbuffer.obj\t\t\\\n   \t\t\tbuffglbl.obj\t\\\n   \t\t\tclear.obj\t\t\\\n   \t\t\tdrawline.obj\t\\\n   \t\t\tdrawrect.obj\t\\\n   \t\t\tfillquad.obj\t\\\n   \t\t\tfillrect.obj\t\\\n   \t\t\tgbuffer.obj\t\t\\\n   \t\t\tgetclip.obj\t\t\\\n   \t\t\tgetpix.obj\t\t\\\t  \t\n   \t\t\tputpix.obj\t\t\\\n   \t\t\tregionsz.obj\t\\\n   \t\t\tremap.obj\t\t\\\n   \t\t\tscale.obj\t\t\\\n   \t\t\tstamp.obj\t\t\\\n   \t\t\tszregion.obj\t\\\n   \t\t\ttobuff.obj\t\t\\\n   \t\t\ttopage.obj\t\t\\\n   \t\t\ttxtprnt.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) \n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n -+bitblit.obj\t\t&\n-+buffer.obj\t\t&\n-+buffglbl.obj\t\t&\n-+clear.obj\t\t\t&\n-+drawline.obj\t\t&\n-+drawrect.obj\t\t&\n-+fillquad.obj\t\t&\t\n-+fillrect.obj\t\t&\n-+gbuffer.obj\t\t&\n-+getclip.obj\t\t&\n-+getpix.obj\t\t&\t  \t\n-+putpix.obj\t\t&\n-+regionsz.obj\t\t&\n-+remap.obj\t\t\t&\n-+scale.obj\t\t\t&\n-+stamp.obj\t\t\t&\n-+szregion.obj\t\t&\n-+tobuff.obj\t\t&\n-+topage.obj\t\t&\n-+txtprnt.obj\n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/PUTPIX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : GraphicViewPortClass\t\t\t   *\n;*                                                                         *\n;*                    File Name : PUTPIXEL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : June 8, 1994   [PWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVPC::Put_Pixel -- Puts a pixel on a virtual viewport                 *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n;***************************************************************************\n;* VVPC::PUT_PIXEL -- Puts a pixel on a virtual viewport                   *\n;*                                                                         *\n;* INPUT:\tWORD the x position for the pixel relative to the upper    *\n;*\t\t\tleft corner of the viewport\t\t\t   *\n;*\t\tWORD the y pos for the pixel relative to the upper left\t   *\n;*\t\t\tcorner of the viewport\t\t\t\t   *\n;*\t\tUBYTE the color of the pixel to write\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNING:\tIf pixel is to be placed outside of the viewport then\t   *\n;*\t\tthis routine will abort.\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/08/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_Put_Pixel C near\n\tUSES\teax,ebx,ecx,edx,edi\n\n\tARG    \tthis_object:DWORD\t\t\t\t; this is a member function\n\tARG\tx_pixel:DWORD\t\t\t\t; x position of pixel to set\n\tARG\ty_pixel:DWORD\t\t\t\t; y position of pixel to set\n\tARG    \tcolor:BYTE\t\t\t\t; what color should we clear to\n\n\t;*===================================================================\n\t; Get the viewport information and put bytes per row in ecx\n\t;*===================================================================\n\tmov\tebx,[this_object]\t\t\t\t; get a pointer to viewport\n\txor\teax,eax\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get the correct offset\n\tmov\tecx,[(GraphicViewPort ebx).GVPHeight]\t; edx = height of viewport\n\tmov\tedx,[(GraphicViewPort ebx).GVPWidth]\t; ecx = width of viewport\n\n\t;*===================================================================\n\t; Verify that the X pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[x_pixel]\t\t\t\t; find the x position\n\tcmp\teax,edx\t\t\t\t\t;   is it out of bounds\n\tjae\tshort ??exit\t\t\t\t; if so then get out\n\tadd\tedi,eax\t\t\t\t\t; otherwise add in offset\n\n\t;*===================================================================\n\t; Verify that the Y pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[y_pixel]\t\t\t\t; get the y position\n\tcmp\teax,ecx\t\t\t\t\t;  is it out of bounds\n\tjae\t??exit\t\t\t\t\t; if so then get out\n\tadd\tedx,[(GraphicViewPort ebx).GVPXAdd]\t; otherwise find bytes per row\n\tadd\tedx,[(GraphicViewPort ebx).GVPPitch]\t; add in direct draw pitch\n\tmul\tedx\t\t\t\t\t; offset = bytes per row * y\n\tadd\tedi,eax\t\t\t\t\t; add it into the offset\n\n\t;*===================================================================\n\t; Write the pixel to the screen\n\t;*===================================================================\n\tmov\tal,[color]\t\t\t\t; read in color value\n\tmov\t[edi],al\t\t\t\t; write it to the screen\n??exit:\n\tret\n\tENDP\tBuffer_Put_Pixel\n\nEND"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/REGIONSZ.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB 32                                 *\n *                                                                         *\n *                    File Name : REGIONSZ.CPP                             *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : November 3, 1994                         *\n *                                                                         *\n *                  Last Update : November 3, 1994   [PWG]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Size_Of_Region -- Calculates the size of a given region               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * SIZE_OF_REGION -- Calculates the size of a given region                 *\n *                                                                         *\n * INPUT:\tint width  - the width of the region                           *\n *\t\t\t\tint height - the height of the region\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:  long - the size of the region                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/03/1994 PWG : Created.                                             *\n *=========================================================================*/\nlong Size_Of_Region(int width, int height)                                 \n{\n\treturn(width * height);\n}\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/REMAP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : REMAP.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 1, 1994                             *\n;*                                                                         *\n;*                  Last Update : July 1, 1994   [PWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n\tPROC\tBuffer_Remap C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* Define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tthis_object:DWORD\n\tARG\tx0_pixel:DWORD\n\tARG\ty0_pixel:DWORD\n\tARG\tregion_width:DWORD\n\tARG\tregion_height:DWORD\n\tARG\tremap\t:DWORD\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tlocal\tx1_pixel  : DWORD\n\tlocal\ty1_pixel  : DWORD\n\tlocal\twin_width : dword\n\tlocal\tcounter_x : dword\n\n\n\tcmp\t[ remap ] , 0\n\tjz\t??real_out\n\n; Clip Source Rectangle against source Window boundaries.\n\tmov  \tesi , [ this_object ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\tebx , [ x0_pixel ]\n\tmov\teax , [ x0_pixel ]\n\tadd\tebx , [ region_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register\n\tmov\tebx , [ y0_pixel ]\n\tmov\teax , [ y0_pixel ]\n\tadd\tebx , [ region_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_remap\n\n\ttest\tcl , 1000b\n\tjz\t??scr_left_ok\n\tmov\t[ x0_pixel ] , 0\n\n??scr_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\t[ y0_pixel ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_remap\n\tmov\teax , [ (GraphicViewPort esi) . GVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n\n??do_remap:\n       cld\n       mov\tedi , [ (GraphicViewPort esi) . GVPOffset ]\n       mov\teax , [ (GraphicViewPort esi) . GVPXAdd ]\n       mov\tebx , [ x1_pixel ]\n       add\teax , [ (GraphicViewPort esi) . GVPWidth ]\n       add\teax , [ (GraphicViewPort esi) . GVPPitch ]\n       mov\tesi , eax\n       mul\t[ y0_pixel ]\n       add\tedi , [ x0_pixel ]\n       sub\tebx , [ x0_pixel ]\n       jle\t??real_out\n       add\tedi , eax\n       sub\tesi , ebx\n\n       mov\tecx , [ y1_pixel ]\n       sub\tecx , [ y0_pixel ]\n       jle\t??real_out\n       mov\teax , [ remap ]\n       mov\t[ counter_x ] , ebx\n       xor\tedx , edx\n\n??outer_loop:\n       mov\tebx , [ counter_x ]\n??inner_loop:\n       mov\tdl , [ edi ]\n       mov\tdl , [ eax + edx ]\n       mov\t[ edi ] , dl\n       inc\tedi\n       dec\tebx\n       jnz\t??inner_loop\n       add\tedi , esi\n       dec\tecx\n       jnz\t??outer_loop\n\n\n\n\n??real_out:\n\tret\n\n\tENDP\tBuffer_Remap\n\n\tEND\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/SCALE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : SCALE.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 16, 1994                            *\n;*                                                                         *\n;*                  Last Update : June 21, 1994   [PWG]                    *\n;*                  New version : feb 12, 1995  [JRJ]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVC::Scale -- Scales a virtual viewport to another virtual viewport   *\n;*   Normal_Draw -- jump loc for drawing  scaled line of normal pixel      *\n;*   Normal_Remapped_Draw -- jump loc for draw scaled line of remap pixel  *\n;*   Transparent_Draw -- jump loc for scaled line of transparent pixels    *\n;*   Transparent_Remapped_Draw -- jump loc for scaled remap trans pixels   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n\n;***************************************************************************\n;* VVC::SCALE -- Scales a virtual viewport to another virtual viewport     *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/16/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tLinear_Scale_To_Linear C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* Define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tthis_object:DWORD\t\t; pointer to source view port\n\tARG\tdest:DWORD\t\t; pointer to destination view port\n\tARG\tsrc_x:DWORD\t\t; source x offset into view port\n\tARG\tsrc_y:DWORD\t\t; source y offset into view port\n\tARG\tdst_x:DWORD\t\t; dest x offset into view port\n\tARG\tdst_y:DWORD\t\t; dest y offset into view port\n\tARG\tsrc_width:DWORD\t\t; width of source rectangle\n\tARG\tsrc_height:DWORD\t; height of source rectangle\n\tARG\tdst_width:DWORD\t\t; width of dest rectangle\n\tARG\tdst_height:DWORD\t; width of dest height\n\tARG\ttrans:DWORD\t\t; is this transparent?\n\tARG\tremap:DWORD\t\t; pointer to table to remap source\n\n\t;*===================================================================\n\t;* Define local variables to hold the viewport characteristics\n\t;*===================================================================\n\tlocal\tsrc_x0 : dword\n\tlocal\tsrc_y0 : dword\n\tlocal\tsrc_x1 : dword\n\tlocal\tsrc_y1 : dword\n\n\tlocal\tdst_x0 : dword\n\tlocal\tdst_y0 : dword\n\tlocal\tdst_x1 : dword\n\tlocal\tdst_y1 : dword\n\n\tlocal\tsrc_win_width : dword\n\tlocal\tdst_win_width : dword\n\tlocal\tdy_intr : dword\n\tlocal\tdy_frac : dword\n\tlocal\tdy_acc  : dword\n\tlocal\tdx_frac : dword\n\n\tlocal\tcounter_x     : dword\n\tlocal\tcounter_y     : dword\n\tlocal\tremap_counter :dword\n\tlocal\tentry : dword\n\n\t;*===================================================================\n\t;* Check for scale error when to or from size 0,0\n\t;*===================================================================\n\tcmp\t[dst_width],0\n\tje\t??all_done\n\tcmp\t[dst_height],0\n\tje\t??all_done\n\tcmp\t[src_width],0\n\tje\t??all_done\n\tcmp\t[src_height],0\n\tje\t??all_done\n\n\tmov\teax , [ src_x ]\n\tmov\tebx , [ src_y ]\n\tmov\t[ src_x0 ] , eax\n\tmov\t[ src_y0 ] , ebx\n\tadd\teax , [ src_width ]\n\tadd\tebx , [ src_height ]\n\tmov\t[ src_x1 ] , eax\n\tmov\t[ src_y1 ] , ebx\n\n\tmov\teax , [ dst_x ]\n\tmov\tebx , [ dst_y ]\n\tmov\t[ dst_x0 ] , eax\n\tmov\t[ dst_y0 ] , ebx\n\tadd\teax , [ dst_width ]\n\tadd\tebx , [ dst_height ]\n\tmov\t[ dst_x1 ] , eax\n\tmov\t[ dst_y1 ] , ebx\n\n; Clip Source Rectangle against source Window boundaries.\n\tmov  \tesi , [ this_object ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\teax , [ src_x0 ]\n\tmov\tebx , [ src_x1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register\n\tmov\teax , [ src_y0 ]\n\tmov\tebx , [ src_y1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??all_done\n\tor\tal , dl\n\tjz\t??clip_against_dest\n\tmov\tbl , dl\n\ttest\tcl , 1000b\n\tjz\t??src_left_ok\n\txor\teax , eax\n\tmov\t[ src_x0 ] , eax\n\tsub\teax , [ src_x ]\n\timul\t[ dst_width ]\n\tidiv\t[ src_width ]\n\tadd\teax , [ dst_x ]\n\tmov\t[ dst_x0 ] , eax\n\n??src_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??src_bottom_ok\n\txor\teax , eax\n\tmov\t[ src_y0 ] , eax\n\tsub\teax , [ src_y ]\n\timul\t[ dst_height ]\n\tidiv\t[ src_height ]\n\tadd\teax , [ dst_y ]\n\tmov\t[ dst_y0 ] , eax\n\n??src_bottom_ok:\n\ttest\tbl , 0100b\n\tjz\t??src_right_ok\n\tmov\teax , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\t[ src_x1 ] , eax\n\tsub\teax , [ src_x ]\n\timul\t[ dst_width ]\n\tidiv\t[ src_width ]\n\tadd\teax , [ dst_x ]\n\tmov\t[ dst_x1 ] , eax\n\n??src_right_ok:\n\ttest\tbl , 0001b\n\tjz\t??clip_against_dest\n\tmov\teax , [ (GraphicViewPort esi) . GVPHeight ]  ; get width into register\n\tmov\t[ src_y1 ] , eax\n\tsub\teax , [ src_y ]\n\timul\t[ dst_height ]\n\tidiv\t[ src_height ]\n\tadd\teax , [ dst_y ]\n\tmov\t[ dst_y1 ] , eax\n\n; Clip destination Rectangle against source Window boundaries.\n??clip_against_dest:\n\tmov  \tesi , [ dest ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\teax , [ dst_x0 ]\n\tmov\tebx , [ dst_x1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register\n\tmov\teax , [ dst_y0 ]\n\tmov\tebx , [ dst_y1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??all_done\n\tor\tal , dl\n\tjz\t??do_scaling\n\tmov\tbl , dl\n\ttest\tcl , 1000b\n\tjz\t??dst_left_ok\n\txor\teax , eax\n\tmov\t[ dst_x0 ] , eax\n\tsub\teax , [ dst_x ]\n\timul\t[ src_width ]\n\tidiv\t[ dst_width ]\n\tadd\teax , [ src_x ]\n\tmov\t[ src_x0 ] , eax\n\n??dst_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dst_bottom_ok\n\txor\teax , eax\n\tmov\t[ dst_y0 ] , eax\n\tsub\teax , [ dst_y ]\n\timul\t[ src_height ]\n\tidiv\t[ dst_height ]\n\tadd\teax , [ src_y ]\n\tmov\t[ src_y0 ] , eax\n\n??dst_bottom_ok:\n\ttest\tbl , 0100b\n\tjz\t??dst_right_ok\n\tmov\teax , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\t[ dst_x1 ] , eax\n\tsub\teax , [ dst_x ]\n\timul\t[ src_width ]\n\tidiv\t[ dst_width ]\n\tadd\teax , [ src_x ]\n\tmov\t[ src_x1 ] , eax\n\n??dst_right_ok:\n\ttest\tbl , 0001b\n\tjz\t??do_scaling\n\n\tmov\teax , [ (GraphicViewPort esi) . GVPHeight ]  ; get width into register\n\tmov\t[ dst_y1 ] , eax\n\tsub\teax , [ dst_y ]\n\timul\t[ src_height ]\n\tidiv\t[ dst_height ]\n\tadd\teax , [ src_y ]\n\tmov\t[ src_y1 ] , eax\n\n??do_scaling:\n\n       cld\n       mov\tebx , [ this_object ]\n       mov\tesi , [ (GraphicViewPort ebx) . GVPOffset ]\n       mov\teax , [ (GraphicViewPort ebx) . GVPXAdd ]\n       add\teax , [ (GraphicViewPort ebx) . GVPWidth ]\n       add\teax , [ (GraphicViewPort ebx) . GVPPitch ]\n       mov\t[ src_win_width ] , eax\n       mul\t[ src_y0 ]\n       add\tesi , [ src_x0 ]\n       add\tesi , eax\n\n       mov\tebx , [ dest ]\n       mov\tedi , [ (GraphicViewPort ebx) . GVPOffset ]\n       mov\teax , [ (GraphicViewPort ebx) . GVPXAdd ]\n       add\teax , [ (GraphicViewPort ebx) . GVPWidth ]\n       add\teax , [ (GraphicViewPort ebx) . GVPPitch ]\n       mov\t[ dst_win_width ] , eax\n       mul\t[ dst_y0 ]\n       add\tedi , [ dst_x0 ]\n       add\tedi , eax\n\n       mov\teax , [ src_height ]\n       xor\tedx , edx\n       mov\tebx , [ dst_height ]\n       idiv\t[ dst_height ]\n       imul\teax , [ src_win_width ]\n       neg\tebx\n       mov\t[ dy_intr ] , eax\n       mov\t[ dy_frac ] , edx\n       mov\t[ dy_acc ]  , ebx\n\n       mov\teax , [ src_width ]\n       xor\tedx , edx\n       shl\teax , 16\n       idiv\t[ dst_width ]\n       xor\tedx , edx\n       shld\tedx , eax , 16\n       shl\teax , 16\n\n       mov\tecx , [ dst_y1 ]\n       mov\tebx , [ dst_x1 ]\n       sub\tecx , [ dst_y0 ]\n       jle\t??all_done\n       sub\tebx , [ dst_x0 ]\n       jle\t??all_done\n\n       mov\t[ counter_y ] , ecx\n\n       cmp\t[ trans ] , 0\n       jnz\t??transparency\n\n       cmp\t[ remap ] , 0\n       jnz\t??normal_remap\n\n; *************************************************************************\n; normal scale\n       mov\tecx , ebx\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 2 ]\n       shr\tebx , 5\n       neg\tecx\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??ref_point + ecx + ecx * 2 ]\n       mov\t[ entry ] , ecx\n\n ??outter_loop:\n       push\tesi\n       push\tedi\n       xor\tecx , ecx\n       mov\tebx , [ counter_x ]\n       jmp\t[ entry ]\n ??inner_loop:\n       REPT\t32\n\t       mov\tcl , [ esi ]\n\t       add\tecx , eax\n\t       adc\tesi , edx\n\t       mov\t[ edi ] , cl\n\t       inc\tedi\n       ENDM\n ??ref_point:\n       dec\tebx\n       jge\t??inner_loop\n\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??skip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??skip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??outter_loop\n\tret\n\n\n; *************************************************************************\n; normal scale with remap\n\n??normal_remap:\n       mov\tecx , ebx\n       mov\t[ dx_frac ], eax\n       and\tecx , 01fh\n       mov\teax , [ remap ]\n       shr\tebx , 5\n       imul\tecx , - 13\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??remapref_point + ecx ]\n       mov\t[ entry ] , ecx\n\n ??remapoutter_loop:\n       mov\tebx , [ counter_x ]\n       push\tesi\n       mov\t[ remap_counter ] , ebx\n       push\tedi\n       xor\tecx , ecx\n       xor\tebx , ebx\n       jmp\t[ entry ]\n ??remapinner_loop:\n       REPT\t32\n\t       mov\tbl , [ esi ]\n\t       add\tecx , [ dx_frac ]\n\t       adc\tesi , edx\n\t       mov\tcl , [ eax + ebx ]\n\t       mov\t[ edi ] , cl\n\t       inc\tedi\n       ENDM\n ??remapref_point:\n       dec\t[ remap_counter ]\n       jge\t??remapinner_loop\n\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??remapskip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??remapskip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??remapoutter_loop\n\tret\n\n\n;****************************************************************************\n; scale with trnsparency\n\n??transparency:\n       cmp\t[ remap ] , 0\n       jnz\t??trans_remap\n\n; *************************************************************************\n; normal scale with transparency\n       mov\tecx , ebx\n       and\tecx , 01fh\n       imul\tecx , -13\n       shr\tebx , 5\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??trans_ref_point + ecx ]\n       mov\t[ entry ] , ecx\n\n ??trans_outter_loop:\n       xor\tecx , ecx\n       push\tesi\n       push\tedi\n       mov\tebx , [ counter_x ]\n       jmp\t[ entry ]\n ??trans_inner_loop:\n       REPT\t32\n       local\ttrans_pixel\n\t       mov\tcl , [ esi ]\n\t       test\tcl , cl\n\t       jz\ttrans_pixel\n\t       mov\t[ edi ] , cl\n       trans_pixel:\n\t       add\tecx , eax\n\t       adc\tesi , edx\n\t       inc\tedi\n       ENDM\n ??trans_ref_point:\n       dec\tebx\n       jge\t??trans_inner_loop\n\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??trans_skip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??trans_skip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??trans_outter_loop\n\tret\n\n\n; *************************************************************************\n; normal scale with remap\n\n??trans_remap:\n       mov\tecx , ebx\n       mov\t[ dx_frac ], eax\n       and\tecx , 01fh\n       mov\teax , [ remap ]\n       shr\tebx , 5\n       imul\tecx , - 17\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??trans_remapref_point + ecx ]\n       mov\t[ entry ] , ecx\n\n ??trans_remapoutter_loop:\n       mov\tebx , [ counter_x ]\n       push\tesi\n       mov\t[ remap_counter ] , ebx\n       push\tedi\n       xor\tecx , ecx\n       xor\tebx , ebx\n       jmp\t[ entry ]\n ??trans_remapinner_loop:\n       REPT\t32\n       local\ttrans_pixel\n\t       mov\tbl , [ esi ]\n\t       test\tbl , bl\n\t       jz\ttrans_pixel\n\t       mov\tcl , [ eax + ebx ]\n\t       mov\t[ edi ] , cl\n\t  trans_pixel:\n\t       add\tecx , [ dx_frac ]\n\t       adc\tesi , edx\n\t       inc\tedi\n       ENDM\n ??trans_remapref_point:\n       dec\t[ remap_counter ]\n       jge\t??trans_remapinner_loop\n\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??trans_remapskip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??trans_remapskip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??trans_remapoutter_loop\n\tret\n\n\n\n\n\n??all_done:\n\tret\nendp\n\n\nEND"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/SHADOW.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/source/rcs/./shadow.asm 1.9 1994/05/20 15:30:49 joe_bostic Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : SHADOW.ASM                               *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : February 28, 1995   [BG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n;* void Shadow_Blit(int xpix, int ypix, int width, int height, GVPC src, GVPC dst, void *shadowbuff);\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\nINCLUDE \".\\keystruc.inc\"\n\nGLOBAL\tC Shadow_Blit\t: NEAR\n\nGLOBAL\tC RealModePtr : DWORD\nGLOBAL\tC Hide_Mouse  : NEAR\nGLOBAL\tC Show_Mouse  : NEAR\n\n\tCODESEG\n\n; void Shadow_Blit(int xpix, int ypix, int width, int height, GVPC src, VBC dst, void *shadowbuff);\n; Warning: Shadow_Blit appears to be relatively stupid, in that while it is\n;\t   optimized to perform word or dword blits, it only does so if the\n;\t   entire region is word or dword-sized.  In other words, if you blit\n;\t   a region that is 200 pixels wide (clearly dword-sized), then it\n;\t   will use the dword loop.  However, if you blit a region that is\n;\t   201 pixels wide, the dumb thing will use the byte loop for the\n;\t   entire blit.\n\tPROC    Shadow_Blit C near\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tARG\tx:DWORD\n\tARG\ty:DWORD\n\tARG\tregion_width:DWORD\n\tARG\tregion_height:DWORD\n\tARG     srcpage:DWORD\n\tARG     dstpage:DWORD\n\tARG     shadow:DWORD\n\n\tLOCAL\tmodulo:DWORD\t\t; Row modulo\n\tLOCAL\thidemouse:DWORD\t\t; Was the mouse hidden?\n\tLOCAL\tdwordwidth:DWORD\n\tLOCAL\tbytewidth:DWORD\n\n\tcld                             ; Always move forward.\n\tmov\t[hidemouse],0\t\t; Presume mouse hasn't been hidden.\n\n; Fetch the segment of the seenpage.\n\tmov\tebx,[dstpage]\n\tmov\tebx,[(GraphicViewPort ebx).GVPOffset]\n\n\t; Determine if the mouse needs to be hidden at all.  If this happens to be\n\t; a shadow blit to non visible page (who knows why!?) then don't bother to\n\t; hide the mouse since it isn't necessary.\n;\tcmp\tebx,0A0000h\n;\tsetne\t[BYTE PTR hidemouse]\t; Flag that mouse need not be hidden.\n;\tjne\tshort ??itsok\n\tmov\tesi,[RealModePtr]\n\tcmp\t[(KeyboardType esi).MState],0\n\tje\tshort ??itsok\n\tmov\t[hidemouse],1\n\tcall\tHide_Mouse C\t\t; Hides mouse again (just to be sure).\n??itsok:\n\tmov\tedi,[srcpage]\n\tmov\tesi,[(GraphicViewPort edi).GVPOffset]\n\n\tmov\teax,[(GraphicViewPort edi).GVPWidth]\n\tadd\teax,[(GraphicViewPort edi).GVPXAdd]\n\tadd\teax,[(GraphicViewPort edi).GVPPitch]\n\tpush\teax\t\t\t; save width+xadd for later calc\n\tmov\tedx,[y]\n\tmul\tedx\n\tadd\teax,[x]\n\tadd\tesi,eax\n; At this point, esi points to the source page and ebx points to the dest page\n\tsub\tebx,esi\t\t\t; esi+ebx == dest page pointer\n\n\tmov\tedi,[shadow]             ; EDI points to shadow buffer.\n\n\tmov     ecx,[region_height]\t\t; get the height of the window in cx\n\n\tmov\tedx,[RealModePtr]\n\n\t; Calculate the row add module.\n\tpop\teax\t\t\t; restore width+xadd\n\tsub\teax,[region_width]\n\tmov\t[modulo],eax\n\n\tmov\teax,[region_width]\n\tshr\teax,2\n\tmov\t[dwordwidth],eax\n\tmov\teax,[region_width]\n\tand\teax,3\n\tmov\t[bytewidth],eax\n\n;---------------------------------------\n; DOUBLE WORD shadow blit if possible.\n;---------------------------------------\n??dloop_top:\n\tpush\tecx\n\tmov\tecx,[dwordwidth]\n\n??lcontinue:\n\trepe    cmpsd                   ; check the entire row for changed longs\n\tje      short ??loop_top\n\n\t; If this row would interfere with the mouse image, then hide it.\n\tcmp\t[hidemouse],0\n\tjnz\tshort ??dok\n\tmov\teax,[(KeyboardType edx).MouseY]\n\tsub\teax,[(KeyboardType edx).MouseYHot]\n\tcmp\teax,[y]\n\tjg\tshort ??dok\n\tadd\teax,[(KeyboardType edx).MouseHeight]\n\tcmp\teax,[y]\n\tjb\tshort ??dok\n\tmov\t[hidemouse],1\t\t; Manual hide of the mouse.\n\tcall\tHide_Mouse C\n??dok:\n\n\tmov     eax,[esi-4]\n\tmov     [ebx+esi-4],eax\t\t; Update destination page.\n\tmov     [edi-4],eax\t\t; Update shadow buffer.\n\tor\tecx,ecx\n\tjne     short ??lcontinue\n\n;---------------------------------------\n; Row loop start for BYTES.\n;---------------------------------------\n??loop_top:\n\tmov\tecx,[bytewidth]\n\n; Column loop start -- by bytes.\n??continue:\n\trepe    cmpsb                   ; check the entire row for changed longs\n\tje      short ??done_x\n\n\t; If this row would interfere with the mouse image, then hide it.\n\tcmp\t[hidemouse],0\n\tjnz\tshort ??bok\n\tmov\teax,[(KeyboardType edx).MouseY]\n\tsub\teax,[(KeyboardType edx).MouseYHot]\n\tcmp\teax,[y]\n\tjg\tshort ??bok\n\tadd\teax,[(KeyboardType edx).MouseHeight]\n\tcmp\teax,[y]\n\tjl\tshort ??bok\n\tmov\t[hidemouse],1\t\t; Manual hide of the mouse.\n\tcall\tHide_Mouse C\n??bok:\n\n\tmov     al,[esi-1]\n\tmov     [ebx+esi-1],al\t\t; Update destination page.\n\tmov     [edi-1],al\t\t; Update shadow buffer.\n\n\tor\tecx,ecx\n\tjne     short ??continue\n\n??done_x:\n\tinc\t[y]\n\tadd     esi,[modulo]\n\tpop     ecx\n\tdec\t\tecx\n    jnz\t\t??dloop_top\n\n??fini:\n\t; Re show the mouse if it was hidden by this routine.\n\tcmp\t[hidemouse],0\n\tje\tshort ??reallyfini\n\tcall\tShow_Mouse C\n??reallyfini:\n\tret\n\n\tENDP    Shadow_Blit\n\n\tEND"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/STAMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : STAMP.ASM                                *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : August 23, 1993                          *\n;*                                                                         *\n;*                  Last Update : August 23, 1993   [JLB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nINCLUDE\t\"stamp.inc\"\n\nglobal\t\tC Init_Stamps:near\nglobal\t\tLastIconset:dword\nglobal\t\tMapPtr:dword\nglobal\t\tIconCount:dword\nglobal\t\tIconSize:dword\nglobal\t\tStampPtr:dword\n\n\tDATASEG\n\n\nLastIconset\tDD\t0\t; Pointer to last iconset initialized.\nStampPtr\tDD\t0\t; Pointer to icon data.\n\nIsTrans\t\tDD\t0\t; Pointer to transparent icon flag table.\n\nMapPtr\t\tDD\t0\t; Pointer to icon map.\nIconWidth\tDD\t0\t; Width of icon in pixels.\nIconHeight\tDD\t0\t; Height of icon in pixels.\nIconSize\tDD\t0\t; Number of bytes for each icon data.\nIconCount\tDD\t0\t; Number of icons in the set.\n\n\tEVEN\n\n\tCODESEG\n\n\nGLOBAL C\tBuffer_Draw_Stamp:near\nGLOBAL C\tBuffer_Draw_Stamp_Clip:near\n\n; 256 color icon system.\n\n;***********************************************************\n; INIT_STAMPS\n;\n; VOID cdecl Init_Stamps(VOID *icondata);\n;\n; This routine initializes the stamp data.\n; Bounds Checking: NONE\n;\n;*\n\tPROC\tInit_Stamps C near USES eax ebx edx edi\n\tARG\ticondata:DWORD\n\n\t; Verify legality of parameter.\n\tcmp\t[icondata],0\n\tje\tshort ??fini\n\n\t; Don't initialize if already initialized to this set (speed reasons).\n\tmov\tedi,[icondata]\n\tcmp\t[LastIconset],edi\n\tje\tshort ??fini\n\tmov\t[LastIconset],edi\n\n\t; Record number of icons in set.\n\tmovzx\teax,[(IControl_Type edi).Count]\n\tmov\t[IconCount],eax\n\n\t; Record width of icon.\n\tmovzx\teax,[(IControl_Type edi).Width]\n\tmov\t[IconWidth],eax\n\n\t; Record height of icon.\n\tmovzx\tebx,[(IControl_Type edi).Height]\n\tmov\t[IconHeight],ebx\n\n\t; Record size of icon (in bytes).\n\tmul\tebx\n\tmov\t[IconSize],eax\n\n\t; Record hard pointer to icon map data.\n\tmov\teax,[(IControl_Type edi).Map]\n\tadd\teax,edi\n\tmov\t[MapPtr],eax\n\n??nomap:\n\t; Record hard pointer to icon data.\n\tmov\teax,edi\n\tadd\teax,[(IControl_Type edi).Icons]\n\tmov\t[StampPtr],eax\n\n\t; Record the transparent table.\n\tmov\teax,edi\n\tadd\teax,[(IControl_Type edi).TransFlag]\n\tmov\t[IsTrans],eax\n\n??fini:\n\tret\n\n\tENDP\tInit_Stamps\n\n\n;***********************************************************\n\n\n;***********************************************************\n; DRAW_STAMP\n;\n; VOID cdecl Buffer_Draw_Stamp(VOID *icondata, WORD icon, WORD x_pixel, WORD y_pixel, VOID *remap);\n;\n; This routine renders the icon at the given coordinate.\n;\n; The remap table is a 256 byte simple pixel translation table to use when\n; drawing the icon.  Transparency check is performed AFTER the remap so it is possible to\n; remap valid colors to be invisible (for special effect reasons).\n; This routine is fastest when no remap table is passed in.\n;*\n\tPROC\tBuffer_Draw_Stamp C near\n\n\tARG\tthis_object:DWORD\t\t; this is a member function\n\tARG\ticondata:DWORD\t\t; Pointer to icondata.\n\tARG\ticon:DWORD\t\t; Icon number to draw.\n\tARG\tx_pixel:DWORD\t\t; X coordinate of icon.\n\tARG\ty_pixel:DWORD\t\t; Y coordinate of icon.\n\tARG\tremap:DWORD \t\t; Remap table.\n\n\tLOCAL\tmodulo:DWORD\t\t; Modulo to get to next row.\n\tLOCAL\tiwidth:DWORD\t\t; Icon width (here for speedy access).\n\tLOCAL\tdoremap:BYTE\t\t; Should remapping occur?\n\n\tpushad\n\tcmp\t[icondata],0\n\tje\t??out\n\n\t; Initialize the stamp data if necessary.\n\tmov\teax,[icondata]\n\tcmp\t[LastIconset],eax\n\tje\tshort ??noreset\n\tcall\tInit_Stamps C,eax\n??noreset:\n\n\t; Determine if the icon number requested is actually in the set.\n\t; Perform the logical icon to actual icon number remap if necessary.\n\tmov\tebx,[icon]\n\tcmp\t[MapPtr],0\n\tje\tshort ??notmap\n\tmov\tedi,[MapPtr]\n\tmov\tbl,[edi+ebx]\n??notmap:\n\tcmp\tebx,[IconCount]\n\tjae\t??out\n\tmov\t[icon],ebx\t\t; Updated icon number.\n\n\t; If the remap table pointer passed in is NULL, then flag this condition\n\t; so that the faster (non-remapping) icon draw loop will be used.\n\tcmp\t[remap],0\n\tsetne\t[doremap]\n\n\t; Get pointer to position to render icon. EDI = ptr to destination page.\n\tmov\tebx,[this_object]\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\n\tadd\teax,[(GraphicViewPort ebx).GVPPitch]\n\tpush\teax\t\t\t; save viewport full width for lower\n\tmul\t[y_pixel]\n\tadd\tedi,eax\n\tadd\tedi,[x_pixel]\n\n\t; Determine row modulo for advancing to next line.\n\tpop\teax\t\t\t; retrieve viewport width\n\tsub\teax,[IconWidth]\n\tmov\t[modulo],eax\n\n\t; Setup some working variables.\n\tmov\tecx,[IconHeight]\t; Row counter.\n\tmov\teax,[IconWidth]\n\tmov\t[iwidth],eax\t\t; Stack copy of byte width for easy BP access.\n\n\t; Fetch pointer to start of icon's data.  ESI = ptr to icon data.\n\tmov\teax,[icon]\n\tmul\t[IconSize]\n\tmov\tesi,[StampPtr]\n\tadd\tesi,eax\n\n\t; Determine whether simple icon draw is sufficient or whether the\n\t; extra remapping icon draw is needed.\n\tcmp\t[BYTE PTR doremap],0\n\tje\tshort ??istranscheck\n\n\t;************************************************************\n\t; Complex icon draw -- extended remap.\n\t; EBX = Palette pointer (ready for XLAT instruction).\n\t; EDI = Pointer to icon destination in page.\n\t; ESI = Pointer to icon data.\n\t; ECX = Number of pixel rows.\n;;;\tmov\tedx,[remap]\n mov ebx,[remap]\n\txor\teax,eax\n??xrowloop:\n\tpush\tecx\n\tmov\tecx,[iwidth]\n\n??xcolumnloop:\n\tlodsb\n;;;\tmov\tebx,edx\n;;;\tadd\tebx,eax\n;;;\tmov\tal,[ebx]\t\t; New real color to draw.\n xlatb\n\tor\tal,al\n\tjz\tshort ??xskip1\t\t; Transparency skip check.\n\tmov\t[edi],al\n??xskip1:\n\tinc\tedi\n\tloop\t??xcolumnloop\n\n\tpop\tecx\n\tadd\tedi,[modulo]\n\tloop\t??xrowloop\n\tjmp\tshort ??out\n\n\n\t;************************************************************\n\t; Check to see if transparent or generic draw is necessary.\n??istranscheck:\n\tmov\tebx,[IsTrans]\n\tadd\tebx,[icon]\n\tcmp\t[BYTE PTR ebx],0\n\tjne\tshort ??rowloop\n\n\t;************************************************************\n\t; Fast non-transparent icon draw routine.\n\t; ES:DI = Pointer to icon destination in page.\n\t; DS:SI = Pointer to icon data.\n\t; CX = Number of pixel rows.\n\tmov\tebx,ecx\n\tshr\tebx,2\n\tmov\tedx,[modulo]\n\tmov\teax,[iwidth]\n\tshr\teax,2\n??loop1:\n\tmov\tecx,eax\n\trep movsd\n\tadd\tedi,edx\n\n\tmov\tecx,eax\n\trep movsd\n\tadd\tedi,edx\n\n\tmov\tecx,eax\n\trep movsd\n\tadd\tedi,edx\n\n\tmov\tecx,eax\n\trep movsd\n\tadd\tedi,edx\n\n\tdec\tebx\n\tjnz\t??loop1\n\tjmp\tshort ??out\n\n\t;************************************************************\n\t; Transparent icon draw routine -- no extended remap.\n\t; ES:DI = Pointer to icon destination in page.\n\t; DS:SI = Pointer to icon data.\n\t; CX = Number of pixel rows.\n??rowloop:\n\tpush\tecx\n\tmov\tecx,[iwidth]\n\n??columnloop:\n\tlodsb\n\tor\tal,al\n\tjz\tshort ??skip1\t\t; Transparency check.\n\tmov\t[edi],al\n??skip1:\n\tinc\tedi\n\tloop\t??columnloop\n\n\tpop\tecx\n\tadd\tedi,[modulo]\n\tloop\t??rowloop\n\n\t; Cleanup and exit icon drawing routine.\n??out:\n\tpopad\n\tret\n\n\tENDP\tBuffer_Draw_Stamp\n\n\n\n\n;***********************************************************\n; DRAW_STAMP_CLIP\n;\n; VOID cdecl MCGA_Draw_Stamp_Clip(VOID *icondata, WORD icon, WORD x_pixel, WORD y_pixel, VOID *remap, LONG min_x, LONG min_y, LONG max_x, LONG max_y);\n;\n; This routine renders the icon at the given coordinate.\n;\n; The remap table is a 256 byte simple pixel translation table to use when\n; drawing the icon.  Transparency check is performed AFTER the remap so it is possible to\n; remap valid colors to be invisible (for special effect reasons).\n; This routine is fastest when no remap table is passed in.\n;*\n\tPROC\tBuffer_Draw_Stamp_Clip C near\n\n\tARG\tthis_object:DWORD\t; this is a member function\n\tARG\ticondata:DWORD\t\t; Pointer to icondata.\n\tARG\ticon:DWORD\t\t; Icon number to draw.\n\tARG\tx_pixel:DWORD\t\t; X coordinate of icon.\n\tARG\ty_pixel:DWORD\t\t; Y coordinate of icon.\n\tARG\tremap:DWORD \t\t; Remap table.\n\tARG\tmin_x:DWORD\t\t; Clipping rectangle boundary\n\tARG\tmin_y:DWORD\t\t; Clipping rectangle boundary\n\tARG\tmax_x:DWORD\t\t; Clipping rectangle boundary\n\tARG\tmax_y:DWORD\t\t; Clipping rectangle boundary\n\n\tLOCAL\tmodulo:DWORD\t\t; Modulo to get to next row.\n\tLOCAL\tiwidth:DWORD\t\t; Icon width (here for speedy access).\n\tLOCAL\tskip:DWORD\t\t; amount to skip per row of icon data\n\tLOCAL\tdoremap:BYTE\t\t; Should remapping occur?\n\n\tpushad\n\tcmp\t[icondata],0\n\tje\t??out2\n\n\t; Initialize the stamp data if necessary.\n\tmov\teax,[icondata]\n\tcmp\t[LastIconset],eax\n\tje\tshort ??noreset2\n\tcall\tInit_Stamps C,eax\n??noreset2:\n\n\t; Determine if the icon number requested is actually in the set.\n\t; Perform the logical icon to actual icon number remap if necessary.\n\tmov\tebx,[icon]\n\tcmp\t[MapPtr],0\n\tje\tshort ??notmap2\n\tmov\tedi,[MapPtr]\n\tmov\tbl,[edi+ebx]\n??notmap2:\n\tcmp\tebx,[IconCount]\n\tjae\t??out2\n\tmov\t[icon],ebx\t\t; Updated icon number.\n\n\t; Setup some working variables.\n\tmov\tecx,[IconHeight]\t; Row counter.\n\tmov\teax,[IconWidth]\n\tmov\t[iwidth],eax\t\t; Stack copy of byte width for easy BP access.\n\n\t; Fetch pointer to start of icon's data.  ESI = ptr to icon data.\n\tmov\teax,[icon]\n\tmul\t[IconSize]\n\tmov\tesi,[StampPtr]\n\tadd\tesi,eax\n\n\t; Update the clipping window coordinates to be valid maxes instead of width & height\n\t; , and change the coordinates to be window-relative\n\tmov\tebx,[min_x]\n\tadd\t[max_x],ebx\n\tadd\t[x_pixel],ebx\t\t; make it window-relative\n\tmov\tebx,[min_y]\n\tadd\t[max_y],ebx\n\tadd\t[y_pixel],ebx\t\t; make it window-relative\n\n\t; See if the icon is within the clipping window\n\t; First, verify that the icon position is less than the maximums\n\tmov\tebx,[x_pixel]\n\tcmp\tebx,[max_x]\n\tjge\t??out2\n\tmov\tebx,[y_pixel]\n\tcmp\tebx,[max_y]\n\tjge\t??out2\n\t; Now verify that the icon position is >= the minimums\n\tadd\tebx,[IconHeight]\n\tcmp\tebx,[min_y]\n\tjle\t??out2\n\tmov\tebx,[x_pixel]\n\tadd\tebx,[IconWidth]\n\tcmp\tebx,[min_x]\n\tjle\t??out2\n\n\t; Now, clip the x, y, width, and height variables to be within the\n\t; clipping rectangle\n\tmov\tebx,[x_pixel]\n\tcmp\tebx,[min_x]\n\tjge\t??nominxclip\n\t; x < minx, so must clip\n\tmov\tebx,[min_x]\n\tsub\tebx,[x_pixel]\n\tadd\tesi,ebx\t\t; source ptr += (minx - x)\n\tsub\t[iwidth],ebx\t; icon width -= (minx - x)\n\tmov\tebx,[min_x]\n\tmov\t[x_pixel],ebx\n\n??nominxclip:\n\tmov\teax,[IconWidth]\n\tsub\teax,[iwidth]\n\tmov\t[skip],eax\n\n\t; Check for x+width > max_x\n\tmov\teax,[x_pixel]\n\tadd\teax,[iwidth]\n\tcmp\teax,[max_x]\n\tjle\t??nomaxxclip\n\t; x+width is greater than max_x, so must clip width down\n\tmov\teax,[iwidth]\t; eax = old width\n\tmov\tebx,[max_x]\n\tsub\tebx,[x_pixel]\n\tmov\t[iwidth],ebx\t; iwidth = max_x - xpixel\n\tsub\teax,ebx\n\tadd\t[skip],eax\t; skip += (old width - iwidth)\n??nomaxxclip:\n\t; check if y < miny\n\tmov\teax,[min_y]\n\tcmp\teax,[y_pixel]\t; if(miny <= y_pixel), no clip needed\n\tjle\t??nominyclip\n\tsub\teax,[y_pixel]\n\tsub\tecx,eax\t\t; height -= (miny - y)\n\tmul\t[IconWidth]\n\tadd\tesi,eax\t\t; icon source ptr += (width * (miny - y))\n\tmov\teax,[min_y]\n\tmov\t[y_pixel],eax\t; y = miny\n??nominyclip:\n\t; check if (y+height) > max y\n\tmov\teax,[y_pixel]\n\tadd\teax,ecx\n\tcmp\teax,[max_y]\t; if (y + height <= max_y), no clip needed\n\tjle\t??nomaxyclip\n\tmov\tecx,[max_y]\t; height = max_y - y_pixel\n\tsub\tecx,[y_pixel]\n??nomaxyclip:\n\n\t; If the remap table pointer passed in is NULL, then flag this condition\n\t; so that the faster (non-remapping) icon draw loop will be used.\n\tcmp\t[remap],0\n\tsetne\t[doremap]\n\n\t; Get pointer to position to render icon. EDI = ptr to destination page.\n\tmov\tebx,[this_object]\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\n\tadd\teax,[(GraphicViewPort ebx).GVPPitch]\n\tpush\teax\t\t\t; save viewport full width for lower\n\tmul\t[y_pixel]\n\tadd\tedi,eax\n\tadd\tedi,[x_pixel]\n\n\t; Determine row modulo for advancing to next line.\n\tpop\teax\t\t\t; retrieve viewport width\n\tsub\teax,[iwidth]\n\tmov\t[modulo],eax\n\n\t; Determine whether simple icon draw is sufficient or whether the\n\t; extra remapping icon draw is needed.\n\tcmp\t[BYTE PTR doremap],0\n\tje\tshort ??istranscheck2\n\n\t;************************************************************\n\t; Complex icon draw -- extended remap.\n\t; EBX = Palette pointer (ready for XLAT instruction).\n\t; EDI = Pointer to icon destination in page.\n\t; ESI = Pointer to icon data.\n\t; ECX = Number of pixel rows.\n\tmov\tebx,[remap]\n\txor\teax,eax\n??xrowloopc:\n\tpush\tecx\n\tmov\tecx,[iwidth]\n\n??xcolumnloopc:\n\tlodsb\n\txlatb\n\tor\tal,al\n\tjz\tshort ??xskip1c\t\t; Transparency skip check.\n\tmov\t[edi],al\n??xskip1c:\n\tinc\tedi\n\tloop\t??xcolumnloopc\n\n\tpop\tecx\n\tadd\tedi,[modulo]\n add esi,[skip]\n\tloop\t??xrowloopc\n\tjmp\tshort ??out2\n\n\n\t;************************************************************\n\t; Check to see if transparent or generic draw is necessary.\n??istranscheck2:\n\tmov\tebx,[IsTrans]\n\tadd\tebx,[icon]\n\tcmp\t[BYTE PTR ebx],0\n\tjne\tshort ??rowloopc\n\n\t;************************************************************\n\t; Fast non-transparent icon draw routine.\n\t; ES:DI = Pointer to icon destination in page.\n\t; DS:SI = Pointer to icon data.\n\t; CX = Number of pixel rows.\n\tmov\tebx,ecx\n\tmov\tedx,[modulo]\n\tmov\teax,[iwidth]\n\n\t;\n\t; Optimise copy by dword aligning the destination\n\t;\n??loop1c:\n\tpush\teax\n rept 3\n\ttest\tedi,3\n\tjz\t??aligned\n\tmovsb\n\tdec\teax\n\tjz\t??finishedit\n endm\n??aligned:\n\tmov\tecx,eax\n\tshr\tecx,2\n\trep\tmovsd\n\tmov\tecx,eax\n\tand\tecx,3\n\trep\tmovsb\n\n??finishedit:\n\tadd\tedi,edx\n\tadd\tesi,[skip]\n\tpop\teax\n\n\tdec\tebx\n\tjnz\t??loop1c\n\tjmp\tshort ??out2\n\n\t;************************************************************\n\t; Transparent icon draw routine -- no extended remap.\n\t; ES:DI = Pointer to icon destination in page.\n\t; DS:SI = Pointer to icon data.\n\t; CX = Number of pixel rows.\n??rowloopc:\n\tpush\tecx\n\tmov\tecx,[iwidth]\n\n??columnloopc:\n\tlodsb\n\tor\tal,al\n\tjz\tshort ??skip1c\t\t; Transparency check.\n\tmov\t[edi],al\n??skip1c:\n\tinc\tedi\n\tloop\t??columnloopc\n\n\tpop\tecx\n\tadd\tedi,[modulo]\n add esi,[skip]\n\tloop\t??rowloopc\n\n\t; Cleanup and exit icon drawing routine.\n??out2:\n\tpopad\n\tret\n\n\tENDP\tBuffer_Draw_Stamp_Clip\n\n\tEND\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/STAMP.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; This is the control structure at the start of a loaded icon set.  It must match\n; the structure in ICONSET.C!  This structure MUST be a multiple of 16 bytes long.\n\nifdef NO_WAY_THIS_WILL_BE_DEFINED_HAHAHAHA\n\n\tSTRUC\tIControl_Type\nWidth\t\tDW\t?\t; Width in pixels (per icon).\nHeight\t\tDW\t?\t; Height in pixels (per icon).\nCount\t\tDW\t?\t; Number of icons in this set.\nAllocated\tDW\t?\t; Was this iconset allocated?\nSize\t\tDD\t?\t; Size of entire iconset memory block.\nIcons\t\tDD\t?\t; Offset from buffer start to icon data.\nPalettes\tDD\t?\t; Offset from buffer start to palette data.\nRemaps\t\tDD\t?\t; Offset from buffer start to remap index data.\nTransFlag\tDD\t?\t; Offset for transparency flag data.\nMap\t\tDD\t?\t; Icon map offset.\n\tENDS\n\nelse\n\n\n\tSTRUC\tIControl_Type\n\nWidth\t\tDW\t?\t; Width in pixels (per icon).\nHeight\t\tDW\t?\t; Height in pixels (per icon).\nCount\t\tDW\t?\t; Number of icons in this set.\nAllocated\tDW\t?\t; Was this iconset allocated?\nMapWidth\tDW\t?\nMapHeight\tDW\t?\nSize\t\tDD\t?\t; Size of entire iconset memory block.\nIcons\t\tDD\t?\t; Offset from buffer start to icon data.\nPalettes\tDD\t?\t; Offset from buffer start to palette data.\nRemaps\t\tDD\t?\t; Offset from buffer start to remap index data.\nTransFlag\tDD\t?\t; Offset for transparency flag data.\nColorMap\tDD\t?\nMap\t\tDD\t?\t; Icon map offset.\n\tENDS\n\nendif\n\nICON256\tEQU\t1\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/STMPCACH.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : STAMP.ASM                                *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : August 23, 1993                          *\n;*                                                                         *\n;*                  Last Update : August 23, 1993   [JLB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nJUMPS\n\nMAX_CACHED_ICONS=300\nICON_WIDTH\t=24\nICON_HEIGHT\t=24\nMAX_ICON_SETS\t=100\n\n\nglobal\t\tC IconPointers:dword\nglobal\t\tC Init_Stamps:near\nglobal\t\tC IconCacheLookup:word\nglobal\t\tLastIconset:dword\nglobal\t\tMapPtr:dword\nglobal\t\tIconCount:dword\nglobal\t\tIconSize:dword\nglobal\t\tStampPtr:dword\nglobal\t\tIconEntry:dword\nglobal\t\tIconData:dword\n\nglobal\t\tClear_Icon_Pointers_:near\nglobal\t\tCache_Copy_Icon_:near\nglobal\t\tIs_Icon_Cached_:near\nglobal\t\tGet_Icon_Index_:near\nglobal\t\tGet_Free_Index_:near\nglobal\t\tCache_New_Icon_:near\nglobal\t\tIs_Stamp_Registered_:near\nglobal\t\tGet_Free_Cache_Slot_:near\n\n\n\t\tstruc\tIconSetType\n\n\t\tIconSetPtr\tdd\t?\n\t\tIconListOffset\tdd\t?\n\n\t\tends\n\nglobal\t\tC IconSetList:IconSetType\n\n\t\tcodeseg\n\n\n\n;************************************************************************************************\n;* Cache_Copy_Icon -- copy an icon to its video memory cache                                    *\n;*                                                                                              *\n;*                                                                                              *\n;* INPUT:\teax - ptr to icon_data                                                          *\n;*              edx - ptr to video surface                                                      *\n;*              ebx - pitch of video surface                                                    *\n;*                                                                                              *\n;* OUTPUT:      none                                                                            *\n;*                                                                                              *\n;* PROTO:       extern \"C\" Cache_Copy_Icon (void const *icon_ptr ,                              *\n;*\t\tVideoSurfaceDescription.lpSurface ,                                             *\n;*\t\tVideoSurfaceDescription.lPitch);\t\t\t\t\t\t*\n;*                                                                                              *\n;* HISTORY:                                                                                     *\n;*   11/8/95 3:16PM ST: Created                                                                 *\n;*==============================================================================================*\n\nproc\t\tCache_Copy_Icon_ near\n\t\tpushad\n\n\t\tmov\tesi,eax\n\t\tmov\tedi,edx\n\t\tsub\tebx,ICON_WIDTH\n\n\t\tmov\tdl,ICON_HEIGHT\t\t;icon height\n\n??each_line_lp:\tmov\tecx,ICON_WIDTH/4\n\t\trep\tmovsd\n\t\tlea\tedi,[edi+ebx]\n\t\tdec\tdl\n\t\tjnz\t??each_line_lp\n\n\t\tpopad\n\t\tret\n\nendp\t\tCache_Copy_Icon_\n\n\n\n\n\n;************************************************************************************************\n;* Is_Icon_Cached -- has an icon been cached? If not, is it cacheable?                          *\n;*                                                                                              *\n;*                                                                                              *\n;* INPUT:\teax - ptr to icon_data                                                          *\n;*              edx - icon number                                                               *\n;*                                                                                              *\n;* OUTPUT:      eax - index of cached icon or -1 if not cached                                  *\n;*                                                                                              *\n;* PROTO:       extern \"C\" int Is_Icon_Cached (void const *icon_data , int icon);               *\n;*                                                                                              *\n;* HISTORY:                                                                                     *\n;*   11/8/95 2:16PM ST: Created                                                                 *\n;*==============================================================================================*\n\nproc\t\tIs_Icon_Cached_ near\n\n\t\tmov\t[IconData],eax\t\t;save the icon data ptr for later\n\t\tpush\tedx\n\t\ttest\teax,eax\n\t\tje\t??out\n\n; Initialize the stamp data if necessary.\n\t\tcmp\t[LastIconset],eax\n\t\tje\tshort ??noreset\n\t\tcall\tInit_Stamps C,eax\n\n; Determine if the icon number requested is actually in the set.\n; Perform the logical icon to actual icon number remap if necessary.\n??noreset:\tcmp\t[MapPtr],0\n\t\tje\tshort ??notmap\n\t\tpush\tedi\n\t\tmov\tedi,[MapPtr]\n\t\tmov\tdl,[edi+edx]\n\t\tpop\tedi\n\n??notmap:\tcmp\tedx,[IconCount]\n\t\tjl\t??in_range\n\t\tpop\tedx\n\t\tmov\teax,-1\n\t\tret\n\n; See if the stamp is registered - if not then it cant be cached\n??in_range:\tmov\teax,[IconData]\n\t\tcall\tIs_Stamp_Registered_\n\t\tcmp\teax,-1\n\t\tjnz\t??got_entry\n\t\tpop\tedx\n\t\tret\n\n; Stamp is registered - if its cached already then just return the index\n??got_entry:\tmov\teax,[(IconSetType eax).IconListOffset]\n\t\tcmp\t[word eax+edx*2+IconCacheLookup],-1\n\t\tjz\t??not_cached\n\n; it is cached and [eax+edx] is the index\n\t\tmovzx\teax,[word eax+edx*2+IconCacheLookup]\n\t\tpop\tedx\n\t\tret\n\n\n\n;\n; The stamps set is registered but we havn't seen this stamp before\n; so try caching it\n;\n\n??not_cached:\tmov\t[IconEntry],eax\n\t\tadd\t[IconEntry],edx\n\t\tadd\t[IconEntry],edx\n\t\tcall\tGet_Free_Cache_Slot_\n\t\ttest\teax,eax\n\t\tjge\t??got_free_slot\n\t\tpop\tedx\t\t\t;eax is -1 here anyway\n\t\tret\n\n; We found a free caching slot so try caching the stamp into it\n??got_free_slot:imul\tedx,[IconSize]\n\t\tadd\tedx,[StampPtr]\n\t\tpush\teax\n\t\tcall\tCache_New_Icon_\t\t;takes icon index in eax, ptr to icon in edx\n\t\ttest\teax,eax\n\t\tjz\t??cache_failed\n\n\n; Success! Add the index into the table\n\t\tpop\teax\n\t\tmov\tedx,[IconEntry]\n\t\tmov\t[edx+IconCacheLookup],ax\n\t\tand\teax,0ffffh\n\t\tpop\tedx\n\t\tret\n\n; Couldnt cache the new Icon - return -1 to say icon isnt cached\n??cache_failed:\tpop\teax\n??out:\t\tpop\tedx\n\t\tmov\teax,-1\n\t\tret\n\n\nendp\t\tIs_Icon_Cached_\n\n\n\n\n\n\n\n;************************************************************************************************\n;* Is_Stamp_Registered -- has an icon's set been previously registered?                         *\n;*                                                                                              *\n;*                                                                                              *\n;* INPUT:\teax - ptr to icon_data                                                          *\n;*                                                                                              *\n;* OUTPUT:      eax - ptr to registration entry or -1 if not registered                         *\n;*                                                                                              *\n;* PROTO:       extern \"C\" int Is_Stamp_Registered (void const *icon_data);                     *\n;*                                                                                              *\n;* HISTORY:                                                                                     *\n;*   11/10/95 10:00AM ST: Created                                                               *\n;*==============================================================================================*\n\nproc\t\tIs_Stamp_Registered_\n\n\t\tpush\tedi\n\t\tpush\tecx\n\t\tmov\tedi,offset IconSetList\n\t\tmov\tecx,MAX_ICON_SETS\n\n??each_set_lp:\tcmp\teax,[edi]\n\t\tjz\t??got_icon_set\n\t\tadd\tedi,size IconSetType\n\t\tdec\tecx\n\t\tjnz\t??each_set_lp\n\t\tmov\teax,-1\n\t\tpop\tecx\n\t\tpop\tedi\n\t\tret\n\n??got_icon_set:\tmov\teax,edi\n\t\tpop\tecx\n\t\tpop\tedi\n\t\tret\n\nendp\t\tIs_Stamp_Registered_\n\n\n\n\n\n\n\n\t\tdataseg\n\n\nIconEntry\tdd\t0\t;Temporary pointer to icon index entry in table\nIconData\tdd\t0\t;Temporary ptr to icon set data\n\n\n\nend\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/SZREGION.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Calculate size of an MCGA region\t   *\n;*                                                                         *\n;*                    File Name : REGIONSZ.ASM                             *\n;*                                                                         *\n;*                   Programmer : Barry W. Green\t\t\t   *\n;*                                                                         *\n;*                   Start Date : March 1, 1995\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : March 1, 1995  [BWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVPC::Size_Of_Region - calculate graphic buffer region size           *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nGLOBAL\tBuffer_Size_Of_Region\t: NEAR\n\nCODESEG\n\n;***************************************************************************\n;* VVPC::Size_Of_Region - calculate buffer region size\t\t\t   *\n;*                                                                         *\n;* INPUT:\tDWORD the width of the region\t\t\t\t   *\n;*                                                                         *\n;*\t\tDWORD the height of the region\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      calculated size of the region (size = width * height)      *\n;*                                                                         *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   03/01/1995 BWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_Size_Of_Region C near\n\tUSES\tebx,ecx,edx\n\n\tARG    \tthis_object:DWORD\t\t\t; this is a member function\n\tARG\tregion_width:DWORD\t\t\t; width of region\n\tARG\tregion_height:DWORD\t\t\t; height of region\n\n\t;*===================================================================\n\t; Get the viewport information\n\t;*===================================================================\n\tmov\tebx,[this_object]\t\t\t\t; get a pointer to viewport\n\txor\teax,eax\n\tmov\tecx,[(GraphicViewPort ebx).GVPHeight]\t; ecx = height of viewport\n\tmov\tedx,[(GraphicViewPort ebx).GVPWidth]\t; edx = width of viewport\n\n\t;*===================================================================\n\t; Verify that the width is legal\n\t;*===================================================================\n\tmov\teax,[region_width]\t\t\t\t; find the width\n\tcmp\teax,edx\t\t\t\t\t; is it too wide?\n\tjb\tshort ??wok\t\t\t\t; if not, leave it alone\n\tmov\teax,edx\t\t\t\t\t; otherwise clip it\n\n\t;*===================================================================\n\t; Verify that the height is ok\n\t;*===================================================================\n??wok:\tmov\tebx,[region_height]\t\t\t; get the height\n\tcmp\tebx,ecx\t\t\t\t\t; is it too tall?\n\tjb\t??hok\t\t\t\t\t; if not, leave it alone\n\tmov\tebx,ecx\t\t\t\t\t; otherwise clip it\n\n\t;*===================================================================\n\t; Now multiply 'em to calculate the size of the region\n\t;*===================================================================\n??hok:\tmul\tebx\t\t\t\t\t; size = w * h\n\n\tret\n\tENDP\tBuffer_Size_Of_Region\n\n\tEND"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/TEST/HOLD.DEF",
    "content": "IMPORTS\n\tDirectDrawCreate=DDRAW.DirectDrawCreate\n\tDirectSoundCreate=DSOUND.DirectSoundCreate\n\tDirectPlayEnumerate=DPLAY.DirectPlayEnumerate\n\tDirectPlayCreate=DPLAY.DirectPlayCreate\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/TEST/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .EXE makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 20, 1995  \t                   \t\t*\n#*                                                                         *\n#*                  Last Update : \t\t\t                   \t\t\t\t\t*\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the executable program you're building \t   \t\t*\n#* PROJ_LIBS\t= Westwood libraries to link your EXE to \t           \t\t\t*\n#* OBJECTS\t= list of objects in your current working directory\t   \t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t= full pathname of your working directory\t\t   \t\t\t\t\t*\n#* .xxx:\t= full pathname where various file types live\t\t   \t\t\t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n#---------------------------------------------------------------------------\n# PROJ_NAME = library name\n# PROJ_DIR = directory containing source & objects\n#---------------------------------------------------------------------------\nPROJ_NAME\t= TEST\nPROJ_DIR\t\t= $(%WIN32LIB)\\drawbuff\\TEST\nLIB_DIR\t\t= $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t   \t&\n\t$(PROJ_NAME).obj\t&\n\ttestasm.obj\n\nCPS_FILES = \t\t\t&\n\ttest1.cps\t\t&\n\ttest2.cps\n\nPROJ_LIBS =\t&\n\t\t\t   drawbuff.lib\t&\n\t\t\t\tmem.lib\t\t\t&\n\t\t\t\tmisc.lib\t\t\t&\n\t\t\t\tiff.lib\t\t\t&\n\t\t\t\trawfile.lib\t\t&\n\t\t\t\ttile.lib\t\t\t&\n                                font.lib                &\n                                profile.lib\n\n#PROJ_LIBS = \t\t\t&\n#\t    drawbuff.lib\t&\n#\t    win32lib.lib\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t $(PROJ_DIR)\n.c:   \t $(PROJ_DIR)\n.cpp:\t $(PROJ_DIR)\n.h:   \t $(PROJ_DIR)\n.obj:\t $(PROJ_DIR)\n.lib:\t $(%WIN32LIB)\\lib\n.exe:\t $(PROJ_DIR)\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n# If LIB & INCLUDE are already defined, they are used in addition to the\n# WWLIB32 lib & include; otherwise, they're constructed from\n# BCDIR\n#---------------------------------------------------------------------------\n\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB386\\NT\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(PROJ_NAME).exe\n\n#---------------------------------------------------------------------------\n# Build the EXE\n#---------------------------------------------------------------------------\n$(PROJ_NAME).exe: $(OBJECTS)  $(PROJ_NAME).lnk $(PROJ_LIBS) $(CPS_FILES)\n\t $(LINK_CMD) $(LINK_CFG) name $^@ @$(PROJ_NAME).lnk\n\n\n$(PROJ_LIBS):\n\techo updating base library $^@\n\tcd ..\n\twmake\n\tcd $(PROJ_DIR)\n\n\n$(PROJ_NAME).lnk : $(OBJECTS)\n       %create $^@\n       for %index in ($(OBJECTS))  do %append $^@ file %index\n       for %index in ($(PROJ_LIBS)) do %append $^@ library $(LIB_DIR)\\%index\n\t\t %append $^@ library $(LIB_DIR)\\ddraw.lib\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/TEST/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .EXE makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 20, 1995  \t                   \t\t*\n#*                                                                         *\n#*                  Last Update : \t\t\t                   \t\t\t\t\t*\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the executable program you're building \t   \t\t*\n#* PROJ_LIBS\t= Westwood libraries to link your EXE to \t           \t\t\t*\n#* OBJECTS\t= list of objects in your current working directory\t   \t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t= full pathname of your working directory\t\t   \t\t\t\t\t*\n#* .xxx:\t= full pathname where various file types live\t\t   \t\t\t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n#---------------------------------------------------------------------------\n# PROJ_NAME = library name\n# PROJ_DIR = directory containing source & objects\n#---------------------------------------------------------------------------\nPROJ_NAME   = test\nPROJ_DIR    = $(WIN32LIB)\\drawbuff\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS =  \t\\\n\t\t\t\t$(PROJ_NAME).obj\n\nCPS_FILES = \\\n\t\t\t\ttest1.cps\t\t\\\n\t\t\t\ttest2.cps\n!if 0\nPROJ_LIBS =\t\\\n\t\t\t   drawbuff.lib\t\\\n\t\t\t   win32lib.lib\n!else\nPROJ_LIBS =\t\\\n\t\t\t   drawbuff.lib\t\\\n\t\t\t\tmem.lib\t\t\t\\\n\t\t\t\tmisc.lib\t\t\t\\\n\t\t\t\tiff.lib\t\t\t\\\n\t\t\t\trawfile.lib\t\t\\\n\t\t\t\ttile.lib\t\t\t\\\n\t\t\t\tfont.lib\t\t\t\n!endif\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n# If LIB & INCLUDE are already defined, they are used in addition to the\n# WWLIB32 lib & include; otherwise, they're constructed from\n# BCDIR \n#---------------------------------------------------------------------------\n\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n.lbm.cps:\n\t$(WIN32LIB)\\\\TOOLS\\WWCOMP $*.lbm $*.cps\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(PROJ_NAME).exe $(CPS_FILES)\n\n#---------------------------------------------------------------------------\n# Build the EXE\n#---------------------------------------------------------------------------\n$(PROJ_NAME).exe: $(OBJECTS) $(PROJ_LIBS) \n\t $(LINK_CMD) @&&|\n$(LINK_CFG) +\n$(COMPILER)\\\\LIB\\\\c0w32.obj+\n$(OBJECTS)\n$<,$*\n$(PROJ_LIBS) +\nimport32.lib +\ncw32i.lib\n$*.def\n|\n\n$(PROJ_LIBS):\t\t\n\techo updating base library $^@\n\tcd ..\n\tmake\n\tcd $(PROJ_DIR)\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/TEST/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .EXE makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 20, 1995  \t                   \t\t*\n#*                                                                         *\n#*                  Last Update : \t\t\t                   \t\t\t\t\t*\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the executable program you're building \t   \t\t*\n#* PROJ_LIBS\t= Westwood libraries to link your EXE to \t           \t\t\t*\n#* OBJECTS\t= list of objects in your current working directory\t   \t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t= full pathname of your working directory\t\t   \t\t\t\t\t*\n#* .xxx:\t= full pathname where various file types live\t\t   \t\t\t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n#---------------------------------------------------------------------------\n# PROJ_NAME = library name\n# PROJ_DIR = directory containing source & objects\n#---------------------------------------------------------------------------\nPROJ_NAME\t= TEST\nPROJ_DIR\t\t= $(%WIN32LIB)\\drawbuff\\TEST\nLIB_DIR\t\t= $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t   \t&\n\t$(PROJ_NAME).obj\n\nCPS_FILES = \t\t\t&\n\ttest1.cps\t\t&\n\ttest2.cps\n\nPROJ_LIBS =\t&\n\t\t\t   drawbuff.lib\t&\n\t\t\t\tmem.lib\t\t\t&\n\t\t\t\tmisc.lib\t\t\t&\n\t\t\t\tiff.lib\t\t\t&\n\t\t\t\trawfile.lib\t\t&\n\t\t\t\ttile.lib\t\t\t&\n\t\t\t\tfont.lib\t\t\t\n#PROJ_LIBS = \t\t\t&\n#\t    drawbuff.lib\t&\n#\t    win32lib.lib\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t $(PROJ_DIR)\n.c:   \t $(PROJ_DIR)\n.cpp:\t $(PROJ_DIR)\n.h:   \t $(PROJ_DIR)\n.obj:\t $(PROJ_DIR)\n.lib:\t $(%WIN32LIB)\\lib\n.exe:\t $(PROJ_DIR)\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n# If LIB & INCLUDE are already defined, they are used in addition to the\n# WWLIB32 lib & include; otherwise, they're constructed from\n# BCDIR \n#---------------------------------------------------------------------------\n\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB386\\NT\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(PROJ_NAME).exe \n\n#---------------------------------------------------------------------------\n# Build the EXE\n#---------------------------------------------------------------------------\n$(PROJ_NAME).exe: $(OBJECTS)  $(PROJ_NAME).lnk $(PROJ_LIBS) $(CPS_FILES)\n\t $(LINK_CMD) $(LINK_CFG) name $^@ @$(PROJ_NAME).lnk\n\n\n$(PROJ_LIBS):\t\t\n\techo updating base library $^@\n\tcd ..\n\twmake\n\tcd $(PROJ_DIR)\n\n\n$(PROJ_NAME).lnk : $(OBJECTS)\n       %create $^@\n       for %index in ($(OBJECTS))  do %append $^@ file %index\n       for %index in ($(PROJ_LIBS)) do %append $^@ library $(LIB_DIR)\\%index\n\t\t %append $^@ library $(LIB_DIR)\\ddraw.lib\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/TEST/TEST/TEST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"stdio.h\"\n\nextern \"C\" {\n\tvoid func_1(void);\n}\n\nvoid func_2(void)\n{\n\tprintf(\"There\\r\");\n}\n\nvoid main(void)\n{\n\tfunc_1();\n\tfunc_2();\n}\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/TEST/TEST.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***             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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : GraphicBufferClass Test Program                              *\n *                                                                                             *\n *                    File Name : DRAWTEST.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : September 25, 1995                                           *\n *                                                                                             *\n *                  Last Update : September 27, 1995 [ST]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *  WinMain \t\t-- Program entry point                                                     *\n *  Set_Mode\t\t-- Set up direct draw system                                               *\n *  WndProc\t\t\t-- Callback procedure for main window                                      *\n *  Font_Test\t\t-- Test GVPC::Print                                                        *\n *  Rect_Test\t\t-- Test GVPC::Draw_Rect and GVPC::Draw_Line                                *\n *  Clear_Test\t\t-- Test GVPC::Clear                                                        *\n *  Pixel_Test\t\t-- Test GVPC::Put_Pixel                                                    *\n *  Read_Pixel_Test\t-- Test GVPC::Read_Pixel                                                   *\n *  Scale_Test\t\t-- Test GVPC::Scale                                                        *\n *  Blit_Test1\t\t-- Test GVPC::Blit from video mem to video mem                             *\n *  Blit_Test1\t\t-- Test GVPC::Blit from system mem to video mem                            *\n *  Fill_Rect_Test\t-- Test GVPC::Fill_Rect                                                    *\n *  Remap_Test\t\t-- Test GVPC::Remap                                                        *\n *  Quad_Test\t\t-- Test GVPC::Fill_Quad                                                    *\n *  Copy_Test\t\t-- Test GVPC::To_Buffer and BufferClass::To_Page                           *\n *  Test_All\t\t-- Calls the other tests                                                   *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\n\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <windowsx.h>\n#include \"..\\gbuffer.h\"\n#include <ddraw.h>\n#include <font.h>\n#include <tile.h>\n#include <file.h>\n\n\n#define NAME \"DRAWBUFF test\"\n#define TITLE \"DRAWBUFF library test\"\n\n\nvoid Test_All (void);\n\n//\n// Misc globals for testing\n//\nint\t\t\t\tTest=0;\t\t\t\t\t\t// Number of test currently in progress\nBOOL\t\t\tAllDone;\t\t\t\t\t// Flag that we should exit\n\nint\t\t\t\tx1,y1,x2,y2;\t\t\t\t// Coordinates for rectangle drawing\n\nint\t\t\t\tBlitXAdd;\t\t\t\t\t//\nint\t\t\t\tBlitXDir;                   // Vars for blit testing\nint\t\t\t\tBlitYAdd;                   //\nint\t\t\t\tBlitYDir;                   //\n\nint\t\t\t\tBlitStretchX;\t\t\t\t//\nint\t\t\t\tBlitStretchY;               // Vars for scale testing\nint\t\t\t\tBlitStretchXAdd;            //\nint\t\t\t\tBlitStretchYAdd;            //\n\nchar\t\t\tRemapTable[256];\t\t\t// Table for colour remap testing\n\nint\t\t\t\tFontPrintX;\t\t\t\t\t// Vars for test font printing\nint\t\t\t\tFontPrintY;\t\t\t\t\t//\n\nint\t\t\t\tStampX;\t\t\t\t\t\t//\nint\t\t\t\tStampY;                     // Vars for moving the stamp test icon around\nint\t\t\t\tStampXDir;                  //   the screen\nint\t\t\t\tStampYDir;                  //\n\n#define\tMAX_TESTS \t13\t\t\t\t\t\t// Number of tests we have defined\n#define\tMODE_WIDTH\t640\t\t\t\t\t\t// Width in pixels of required video mode\n#define\tMODE_HEIGHT\t400\t\t\t\t\t\t// Height in pixels of required video mode\n\nGraphicBufferClass\t*ScreenBuffer=NULL;\t\t// Global pointer to screen GraphicBufferClass\nGraphicBufferClass\t*BackBuffer=NULL;\t\t// Global pointer to a back buffer\n\nvoid \t*IconPointer;\t\t\t\t\t\t// Global pointer to our test icons\n\nPALETTEENTRY\t\t\tpe[256];\t\t\t// DD Palette entries\nunsigned char\t\t\tPalette[256*3];\t\t// Place to load palette to\nextern LPDIRECTDRAWPALETTE\tPalettePtr;\t\t\t\t// Pointer to direct draw palette object\n\n//\n// Prototypes\n//\nlong FAR PASCAL _export WndProc (HWND, UINT, UINT, LONG) ;\nvoid Set_Video_Mode(HWND hwnd, int w, int h, int bits_per_pixel);\nvoid Reset_Video_Mode(void);\n\n\n//\n// Externs\n//\nextern\tLPDIRECTDRAW\tDirectDrawObject;\nextern\tHWND\t\t\tMainWindow;\n\n/***********************************************************************************************\n * WinMain -- Program entry point                                                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Standard Windows startup parameters                                               *\n *                                                                                             *\n * OUTPUT:   msg.wParam                                                                        *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 1:28PM ST : Created                                                              *\n *=============================================================================================*/\n\nint PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,\n\t\t\t\t\t\t  LPSTR lpszCmdParam, int nCmdShow)\n{\n\tstatic char \tszAppName[] = \"HelloWin\" ;\n\tHWND        \thwnd ;\n\tMSG         \tmsg ;\n\tWNDCLASS    \twndclass ;\n\tint\t\t\t\ti,j,k;\n\n\n\t//\n\t// Register the window class\n\t//\n\n\tif (!hPrevInstance)\n\t\t{\n\t\twndclass.style         = CS_HREDRAW | CS_VREDRAW ;\n\t\twndclass.lpfnWndProc   = WndProc ;\n\t\twndclass.cbClsExtra    = 0 ;\n\t\twndclass.cbWndExtra    = 0 ;\n\t\twndclass.hInstance     = hInstance ;\n\t\twndclass.hIcon         = LoadIcon (hInstance, IDI_APPLICATION) ;\n\t\twndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;\n\t\twndclass.hbrBackground = NULL;\n\t\twndclass.lpszMenuName  = NULL;\n\t\twndclass.lpszClassName = NAME;\n\n\t\tRegisterClass (&wndclass) ;\n\t}\n\n\n\t//\n\t// Create our main window\n\t//\n\thwnd = CreateWindowEx (\n\t\t\t\t\t\t\tWS_EX_TOPMOST,\n\t\t\t\t\t\t\tNAME,\n\t\t\t\t\t\t\tTITLE,\n\t\t\t\t\t\t\tWS_POPUP | WS_MAXIMIZE,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tMODE_WIDTH,\n\t\t\t\t\t\t\tMODE_HEIGHT,\n\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\thInstance,\n\t\t\t\t\t\t\tNULL );\n\n\tShowWindow (hwnd, nCmdShow) ;\n\tUpdateWindow (hwnd) ;\n\tSetFocus (hwnd);\n\tMainWindow=hwnd;\t\t\t//Save the handle to our main window\n\t\t\t\t\t\t\t\t// (Dangerous  if Windoze can change the handle)\n\n\n\n\t//\n\t// Allocate space for the icons and load them\n\t//\n\tIconPointer=malloc (20000);\n\tLoad_File ( \"bridge3.des\" , IconPointer  );\n\n\t//\n\t// Load the desert palette\n\t//\n\tLoad_File ( \"desert.pal\" , Palette );\n\tk=0;\n\tfor( j=0 ; j<768 ; j+=3 )\n\t{\n\t\tpe[k].peRed = Palette[j];\n\t\tpe[k].peGreen = Palette[j+1];\n\t\tpe[k].peBlue = Palette[j+2];\n\t\tk++;\n\t}\n\n\n\t//\n\t// Initialise global stuff required for the tests\n\t//\n\n\t// Force load of font\n\tFontPtr=NULL;\n\n\n\t// Set the video mode\n\tSet_Video_Mode( MainWindow , MODE_WIDTH , MODE_HEIGHT , 8 );\n\n\t//\n\t// Init the stuff for drawing rectangles\n\t//\n\tx1=0;\n\ty1=0;\n\tx2=319;\n\ty2=199;\n\n\n\t//\n\t// Init the stamp test variables\n\t//\n\n\tStampX=100;\n\tStampY=100;\n\tStampXDir=1;\n    StampYDir=1;\n\n\t//\n\t// Create the GraphicBufferClass that will be the screen buffer\n\t//\n\tScreenBuffer = new GraphicBufferClass ( MODE_WIDTH , MODE_HEIGHT , (GBC_Enum)(GBC_VIDEOMEM | GBC_VISIBLE));\n\n\n\t//\n\t// Set the palette\n\t//\n\tDirectDrawObject->CreatePalette( DDPCAPS_8BIT | DDPCAPS_ALLOW256, &pe[0] , &PalettePtr ,NULL);\n\tScreenBuffer->Get_Graphic_Buffer()->Get_DD_Surface()->SetPalette( PalettePtr );\n\tPalettePtr->SetEntries( DDPSETPAL_VSYNC , 0 , 256 , &pe[0] );\n\n\n\t//\n\t// Set up the remap table for the Buffer_Remap test\n\t//\n\tfor ( i=0 ; i<256 ; i++ ){\n\t\tRemapTable[i]=255-i;\n\t}\n\n\n\t//\n\t// Get rid of the windows cursor\n\t//\n\tShowCursor (FALSE);\n\n\tAllDone = FALSE;\n\n\t//\n\t// Windows message loop\n\t//\n\twhile ( ! AllDone ){\n\n\t\tTest_All();\t\t\t// Perform a test\n\n\t\tif( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ){\n\t\t\tif( !GetMessage( &msg, NULL, 0, 0 ) ){\n\t\t\t\treturn msg.wParam;\n\t\t\t}\n\t\t\tTranslateMessage(&msg);\n\t\t\tDispatchMessage(&msg);\n\t\t}\n\n\t}\n\n\treturn msg.wParam;\n}\n\n\n\n\n#ifdef cuts\t\t//this is now in a seperate file\n/***********************************************************************************************\n * Set_Mode -- temporary replacement for library set mode function                             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    int - mode width                                                                  *\n *           int - mode height                                                                 *\n *           int - bits per pixel                                                              *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 1:51PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Set_Mode ( int width , int height , int bpp )\n{\n\n\t//\n\t// Setup the direct draw system by\n\t//\t1. Creating the DirectDraw object\n\t//\t2. Setting the cooperative level to exclusive so we own the screen\n\t//\t3. Setting the video mode\n\t//\n\n\tif ( DirectDrawObject == NULL ){\n\n\t\t// Create the direct draw object\n\t\tDirectDrawCreate ( NULL , &DirectDrawObject , NULL);\n\n\t\t// Set the cooperative level\n\t\tDirectDrawObject->SetCooperativeLevel ( MainWindow , DDSCL_EXCLUSIVE\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t| DDSCL_FULLSCREEN\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t| DDSCL_ALLOWMODEX );\n\t\t// Set the required display mode with 8 bits per pixel\n\t\tDirectDrawObject->SetDisplayMode ( width , height , bpp );\n\t}\n\n}\n#endif\t//cuts\n\n\n/***********************************************************************************************\n * WndProc -- windows message callback                                                         *\n *                                                                                             *\n *   Pilfered from a windows example program - HELLOWIN.C                                      *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Standard Windoze callback parameters                                              *\n *                                                                                             *\n * OUTPUT:   long                                                                              *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 1:39PM ST : Pilfered                                                             *\n *=============================================================================================*/\n\nlong FAR PASCAL _export WndProc (HWND hwnd, UINT message, UINT wParam,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  LONG lParam)\n {\n\n\tswitch (message){\n\n\n\t\tcase WM_KEYDOWN:\n\n\t\t\tswitch ( wParam ){\n\n\t\t\t\tcase VK_SPACE:\n\t\t\t\t\tTest++;\n\t\t\t\t\tif ( Test>=MAX_TESTS ) {\n\t\t\t\t\t\tTest=0;\n\t\t\t\t\t}\n\t\t\t\t\tif ( BackBuffer ){\n\t\t\t\t\t\tdelete BackBuffer;\n\t\t\t\t\t\tBackBuffer=NULL;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\n\n\t\tcase WM_DESTROY:\n\t\t\t//\n\t\t\t// Tidy up\n\t\t\t//\n\n\t\t\tif ( BackBuffer ) {\n\t\t\t\tdelete BackBuffer;\n\t\t\t}\n\t\t\tdelete ScreenBuffer;\n\n\t\t\tif ( DirectDrawObject ){\n\t\t\t\tReset_Video_Mode();\n\t\t\t}\n\n\t\t\tAllDone = TRUE;\n\t\t\tPostQuitMessage (0) ;\n\t\t\treturn(0);\n\t}\n\n\treturn DefWindowProc (hwnd, message, wParam, lParam) ;\n}\n\n\n\n\n\n\n/***********************************************************************************************\n * Font_Test -- test the font print member of the GBC                                          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 3:29PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Font_Test ( void )\n{\n\tconst char\tfont_name[]={\"font.fnt\"};\n\n\tif ( !FontPtr ){\n\t\tFontPtr = Load_Font ( &font_name[0] );\n\t\tFontXSpacing=0;\n\t\tFontYSpacing=0;\n\t\tFontPrintX=0;\n\t\tFontPrintY=0;\n\t}\n\n\tif ( FontPtr ){\n\t\tScreenBuffer->Print ( \"Hello Windoze\" , FontPrintX , FontPrintY ,255 , 0);\n\t}\n\n\tif ( FontPrintX<550 ){\n\t\tFontPrintX+=8;\n\t}\n\n\tif ( FontPrintY<380 ){\n\t\tFontPrintY+=8;\n\t}\n\n\n}\n\n\n\n/***********************************************************************************************\n * Rect_Test -- test the rectangle and line functions of the GBC                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/25/95 3:03PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Rect_Test ( GraphicBufferClass *screen_buffer )\n{\n\n\tscreen_buffer->Draw_Rect ( x1 , y1 , x2 , y2 , 255 );\n\tif ( x1<90 ){\n\t\tx1+=2;\n\t}\n\n\tif ( y1<90 ){\n\t\ty1+=2;\n\t}\n\n\tif ( x2>230 ){\n\t\tx2-=2;\n\t}\n\n\tif ( y2>110 ){\n\t\ty2-=2;\n\t}\n\n}\n\n\n\n\n/***********************************************************************************************\n * Clear_Test -- test the clear function of the GraphicBufferClass                             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/25/95 3:05PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Clear_Test ( void )\n{\n\n\tx1=0;\n\ty1=0;\n\tx2=319;\n\ty2=199;\n\n\tFontPrintX=0;\n\tFontPrintY=0;\n\n\tScreenBuffer->Clear ( rand()&255 );\n}\n\n\n\n\n\n/***********************************************************************************************\n * Stamp_Test -- test the Draw_Stamp member of GraphicBufferClass                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/28/95 6:02PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Stamp_Test ( void )\n{\n\tint\t\tx;\n\tint\t\ty;\n\tint\t\ticon=0;\n\n\t//\n\t// Use stacking locks to speed things up\n\t//\n\tScreenBuffer->Lock();\n\n\tfor\t( y=0 ; y<5*24 ; y+=24 ){\n\n\t\tfor ( x=0 ; x<6*24 ; x+=24 ){\n\n\t\t\tScreenBuffer->Draw_Stamp( IconPointer, icon++ , x+StampX, y+StampY, NULL );\n\n\t\t}\n\t}\n\n    ScreenBuffer->Unlock();\n\n\tStampX+=StampXDir;\n\tStampY+=StampYDir;\n\n\tif ( StampX>640-6*24 || StampX<1 ){\n\t\tStampXDir=-StampXDir;\n\t}\n\n\tif ( StampY>400-6*24 || StampY<1 ){\n\t\tStampYDir=-StampYDir;\n\t}\n\n}\n\n\n\n/***********************************************************************************************\n * Pixel_Test -- test the GVPclass put_pixel member                                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/25/95 5:29PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Pixel_Test ( void )\n{\n\tScreenBuffer->Put_Pixel ( rand() & 511 , rand() & 255 , rand () &255 );\n\n}\n\n\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Read_Pixel_Test -- test the GVPclass Read_Pixel member                                      *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/26/95 4:51PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Read_Pixel_Test ( void )\n{\n\n\tint\t\ti;\n\tint\t\tcolour;\n\tint\t\tpixel_x;\n\tint\t\tpixel_y;\n\n\tif ( !BackBuffer ) {\n\n\t\tBackBuffer = new GraphicBufferClass(640,400, GBC_VIDEOMEM );\n\n\t\tBackBuffer->Clear( 0 );\n\t\tScreenBuffer->Clear ( 0 );\n\n\t\tx1=0;\n\t\ty1=0;\n\t\tx2=319;\n\t\ty2=199;\n\n\t\tfor ( i=0 ; i<50 ; i++ ) {\n\t\t\tRect_Test ( BackBuffer );\n\t\t}\n\n\t}\n\n\n\t//\n\t// Use the stacking lock feature to lock the surfaces once only and\n\t// then draw 10 pixels\n\t//\n\n\tScreenBuffer->Lock();\n\tBackBuffer->Lock();\n\n\tfor ( i=0 ; i<10 ; i++ ){\n\n\t\tpixel_x = rand() &511;\n\t\tpixel_y = rand() &255;\n\n\t\tcolour=BackBuffer->Get_Pixel ( pixel_x , pixel_y );\n\n\t\tScreenBuffer->Put_Pixel ( pixel_x , pixel_y , colour );\n\t}\n\n\tBackBuffer->Unlock();\n\tScreenBuffer->Unlock();\n\n}\n\n\n\n/***********************************************************************************************\n * Scale_Test -- test the GVPclass scale member                                                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/26/95 10:27AM ST : Created                                                             *\n *=============================================================================================*/\nvoid Scale_Test ( void )\n{\n\n\tint\t\ti;\n\n\tif ( !BackBuffer ) {\n\n\t\tBackBuffer = new GraphicBufferClass(640, 400);\n\n\t\tBackBuffer->Clear( 0 );\n\n\t\tx1=0;\n\t\ty1=0;\n\t\tx2=319;\n\t\ty2=199;\n\n\t\tfor ( i=0 ; i<50 ; i++ ) {\n\t\t\tRect_Test ( BackBuffer );\n\t\t}\n\n\t\tBlitStretchX=0;\n\t\tBlitStretchY=0;\n\t\tBlitStretchXAdd=1;\n\t\tBlitStretchYAdd=1;\n\t}\n\n\tBackBuffer->Scale ( *ScreenBuffer , 0 , 0 , 10 , 10\n\t\t\t\t\t\t,320 , 200 , 320+BlitStretchX , 200+BlitStretchY );\n\n\tBlitStretchX += BlitStretchXAdd;\n\tBlitStretchY += BlitStretchYAdd;\n\n\tif ( (BlitStretchX == 100) || (BlitStretchX==-100) ){\n\t\tBlitStretchXAdd=-BlitStretchXAdd;\n\t}\n\n\tif ( (BlitStretchY == 100) || (BlitStretchY==-100) ){\n\t\tBlitStretchYAdd=-BlitStretchYAdd;\n\t}\n\n\n\n\n}\n\n\n\n/***********************************************************************************************\n * Blit_Test1 -- test the blit member of the GraphicBufferClass                                *\n *                                                                                             *\n *    Blits from video memory to video memory                                                  *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/25/95 5:39PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Blit_Test1 ( void )\n{\n\n\tint\ti;\n\n\tif ( !BackBuffer ) {\n\t\tBackBuffer = new GraphicBufferClass(640, 400, GBC_VIDEOMEM);\n\n\t\tBackBuffer->Clear( 0 );\n\n\t\tx1=0;\n\t\ty1=0;\n\t\tx2=319;\n\t\ty2=199;\n\n\t\tfor ( i=0 ; i<50 ; i++ ) {\n\t\t\tRect_Test ( BackBuffer );\n\t\t}\n\n\t\tBlitXAdd=0;\n\t\tBlitXDir=1;\n\t\tBlitYAdd=0;\n\t\tBlitYDir=1;\n\t}\n\n\n\tBackBuffer->Blit ( *ScreenBuffer , 0 , 0 , BlitXAdd , BlitYAdd , 320 , 200 , (BOOL) FALSE );\n\n\tBlitXAdd+=BlitXDir;\n\n\tif ( (BlitXAdd == 0) || (BlitXAdd == 320 )){\n\t\tBlitXDir=-BlitXDir;\n\t}\n\n\n\tBlitYAdd+=BlitYDir;\n\n\tif ( (BlitYAdd == 0) || (BlitYAdd == 200 )){\n\t\tBlitYDir=-BlitYDir;\n\t}\n\n\n}\n\n\n\n\n\n/***********************************************************************************************\n * Blit_Test2 -- test the blit member of the GraphicBufferClass                                *\n *                                                                                             *\n *    Blits from system memory to video memory                                                 *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 9:36AM ST : Created                                                              *\n *=============================================================================================*/\nvoid Blit_Test2 ( void )\n{\n\n\tint\ti;\n\n\tif ( !BackBuffer ) {\n\t\tBackBuffer = new GraphicBufferClass(640, 400);\n\n\t\tBackBuffer->Clear( 0 );\n\n\t\tx1=0;\n\t\ty1=0;\n\t\tx2=319;\n\t\ty2=199;\n\n\t\tfor ( i=0 ; i<50 ; i++ ) {\n\t\t\tRect_Test ( BackBuffer );\n\t\t}\n\n\t\tBlitXAdd=0;\n\t\tBlitXDir=1;\n\t\tBlitYAdd=0;\n\t\tBlitYDir=1;\n\t}\n\n\n\tBackBuffer->Blit ( *ScreenBuffer , 0 , 0 , BlitXAdd , BlitYAdd , 320 , 200 , (BOOL) FALSE );\n\n\tBlitXAdd+=BlitXDir;\n\n\tif ( (BlitXAdd == 0) || (BlitXAdd == 320 )){\n\t\tBlitXDir=-BlitXDir;\n\t}\n\n\n\tBlitYAdd+=BlitYDir;\n\n\tif ( (BlitYAdd == 0) || (BlitYAdd == 200 )){\n\t\tBlitYDir=-BlitYDir;\n\t}\n\n\n}\n\n\n\n\n\n/***********************************************************************************************\n * Fill_Rect_Test -- test the GraphicBufferClass fill rectangle member                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/26/95 5:23PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Fill_Rect_Test ( void )\n{\n\n\tint\t\tx1;\n\tint\t\ty1;\n\tint\t\tx2;\n\tint\t\ty2;\n\n\tx1= rand()&511;\n\tx2= rand()&511;\n\ty1= rand()&255;\n\ty2= rand()&255;\n\n\tScreenBuffer->Fill_Rect ( min ( x1,x2 ) , min ( y1,y2) , max ( x1,x2 ) , max ( y1,y2 ) , rand()&255 );\n\n\n}\n\n\n\n\n\n/***********************************************************************************************\n * Remap_Test -- test the Remap member of GraphicsBufferClass                                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/26/95 6:26PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Remap_Test ( void )\n{\n\tScreenBuffer->Remap ( 20 , 20 , 580 , 350 , &RemapTable[0] );\n}\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Quad_Test -- test the quad fill member of GraphicBufferClass                                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 11:12AM ST : Created                                                             *\n *=============================================================================================*/\n\nvoid Quad_Test ( void )\n{\n\tchar\tspan_buff[500000];\t//Dont know how big this should be so its *BIG*\n\tint\t\tcolour;\n\tint\t\tx0;\n\tint\t\tx1;\n\tint\t\tx2;\n\tint\t\tx3;\n\tint\t\ty0;\n\tint\t\ty1;\n\tint\t\ty2;\n\tint\t\ty3;\n\n\tx0 = rand() & 255;\n\tx1 = rand() & 255+320;\n\tx2 = rand() & 255+320;\n\tx3 = rand() & 255;\n\n\ty0 = rand() & 127;\n\ty1 = rand() & 127;\n\ty2 = rand() & 127+250;\n\ty3 = rand() & 127+250;\n\n\tcolour= rand()&255;\n\n\tScreenBuffer->Fill_Quad ( span_buff , x0,y0,x1,y1,x2,y2,x3,y3,colour);\n\n}\n\n\n\n\n\n\n/***********************************************************************************************\n * Copy_Test - test the To_Buffer member of GraphicsBufferClass                                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 11:36AM ST : Created                                                             *\n *=============================================================================================*/\nvoid Copy_Test ( void )\n{\n\n\tBufferClass\t*buffer;\n\tchar\t\t*buffer_ptr;\n\n\n\tbuffer = new BufferClass (640*400);\n\n\tScreenBuffer->To_Buffer(buffer);\n\n\tbuffer_ptr = (char*)buffer->Get_Buffer();\n\tmemcpy ( buffer_ptr , buffer_ptr+4 , 640*400-4 );\n\n\tbuffer->To_Page ( *ScreenBuffer );\n\n    delete buffer;\n\n}\n\n\n\n\n\n\n/***********************************************************************************************\n * Test_All -- perform tests on GraphicsBufferClass                                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/25/95 2:53PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Test_All ( void )\n\n{\n\n\tswitch ( Test ){\n\n\t\tcase 0:\n\t\t\tClear_Test();\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tRect_Test( ScreenBuffer );\n\t\t\tbreak;\n\n\t\tcase 2:\n\t\t\tPixel_Test();\n\t\t\tbreak;\n\n\t\tcase 3:\n\t\t\tBlit_Test1();\n\t\t\tbreak;\n\n\t\tcase 4:\n\t\t\tBlit_Test2();\n\t\t\tbreak;\n\n\t\tcase 5:\n\t\t\tScale_Test();\n\t\t\tbreak;\n\n\t\tcase 6:\n\t\t\tRead_Pixel_Test();\n\t\t\tbreak;\n\n\t\tcase 7:\n\t\t\tFill_Rect_Test();\n\t\t\tbreak;\n\n\t\tcase 8:\n\t\t\tRemap_Test();\n\t\t\tbreak;\n\n\t\tcase 9:\n\t\t\tQuad_Test();\n\t\t\tbreak;\n\n\t\tcase 10:\n\t\t\tCopy_Test();\n\t\t\tbreak;\n\n\t\tcase 11:\n\t\t\tFont_Test();\n\t\t\tbreak;\n\n\t\tcase 12:\n\t\t\tStamp_Test();\n\t\t\tbreak;\n\n\t}\n\n}\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/TEST/TEST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***             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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : GraphicBufferClass Test Program                              *\n *                                                                                             *\n *                    File Name : DRAWTEST.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : September 25, 1995                                           *\n *                                                                                             *\n *                  Last Update : September 27, 1995 [ST]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *  WinMain \t\t-- Program entry point                                                     *\n *  Set_Mode\t\t-- Set up direct draw system                                               *\n *  WndProc\t\t\t-- Callback procedure for main window                                      *\n *  Font_Test\t\t-- Test GVPC::Print                                                        *\n *  Rect_Test\t\t-- Test GVPC::Draw_Rect and GVPC::Draw_Line                                *\n *  Clear_Test\t\t-- Test GVPC::Clear                                                        *\n *  Pixel_Test\t\t-- Test GVPC::Put_Pixel                                                    *\n *  Read_Pixel_Test\t-- Test GVPC::Read_Pixel                                                   *\n *  Scale_Test\t\t-- Test GVPC::Scale                                                        *\n *  Blit_Test1\t\t-- Test GVPC::Blit from video mem to video mem                             *\n *  Blit_Test1\t\t-- Test GVPC::Blit from system mem to video mem                            *\n *  Fill_Rect_Test\t-- Test GVPC::Fill_Rect                                                    *\n *  Remap_Test\t\t-- Test GVPC::Remap                                                        *\n *  Quad_Test\t\t-- Test GVPC::Fill_Quad                                                    *\n *  Copy_Test\t\t-- Test GVPC::To_Buffer and BufferClass::To_Page                           *\n *  Test_All\t\t-- Calls the other tests                                                   *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\n#define WIN32\n#define WIN32\n#include <windows.h>\n#include <windowsx.h>\n#include \"..\\gbuffer.h\"\n#include <ddraw.h>\n#include <font.h>\n#include <tile.h>\n#include <file.h>\n#include <iconcach.h>\n#include <wwmem.h>\n\n#define NAME \"DRAWBUFF test\"\n#define TITLE \"DRAWBUFF library test\"\n\n\nvoid Test_All (void);\n\n//\n// Misc globals for testing\n//\nint\t\t\t\tTest=0;\t\t\t\t\t\t// Number of test currently in progress\nBOOL\t\t\tAllDone;\t\t\t\t\t// Flag that we should exit\n\nint\t\t\t\tx1,y1,x2,y2;\t\t\t\t// Coordinates for rectangle drawing\n\nint\t\t\t\tBlitXAdd;\t\t\t\t\t//\nint\t\t\t\tBlitXDir;                   // Vars for blit testing\nint\t\t\t\tBlitYAdd;                   //\nint\t\t\t\tBlitYDir;                   //\n\nint\t\t\t\tBlitStretchX;\t\t\t\t//\nint\t\t\t\tBlitStretchY;               // Vars for scale testing\nint\t\t\t\tBlitStretchXAdd;            //\nint\t\t\t\tBlitStretchYAdd;            //\n\nchar\t\t\tRemapTable[256];\t\t\t// Table for colour remap testing\n\nint\t\t\t\tFontPrintX;\t\t\t\t\t// Vars for test font printing\nint\t\t\t\tFontPrintY;\t\t\t\t\t//\n\nint\t\t\t\tStampX;\t\t\t\t\t\t//\nint\t\t\t\tStampY;                     // Vars for moving the stamp test icon around\nint\t\t\t\tStampXDir;                  //   the screen\nint\t\t\t\tStampYDir;                  //\n\n\n#define\tMAX_TESTS \t14\t\t\t\t\t\t// Number of tests we have defined\n#define\tMODE_WIDTH\t640\t\t\t\t\t\t// Width in pixels of required video mode\n#define\tMODE_HEIGHT\t400\t\t\t\t\t\t// Height in pixels of required video mode\n\nint\t\t\t\tScreenWidth=MODE_WIDTH;\n\nBOOL\t\t\tGameInFocus = TRUE;\n\nextern \"C\"{\nchar\tCurrentPalette\t[768];\n}\n\nint WindowList[][8] = {\n\t{20>>3,20,(MODE_WIDTH-20)>>3,MODE_HEIGHT-20,0,0,0,0}\t/* screen window */\n};\nchar\tSpanBuff[500000];\t//Dont know how big this should be so its *BIG*\n\nGraphicBufferClass\t*ScreenBuffer=NULL;\t\t// Global pointer to screen GraphicBufferClass\nGraphicBufferClass\t*BackBuffer=NULL;\t\t// Global pointer to a back buffer\n\nvoid \t*IconPointer;\t\t\t\t\t\t// Global pointer to our test icons\n\nPALETTEENTRY\t\t\tpe[256];\t\t\t// DD Palette entries\nunsigned char\t\t\tPalette[256*3];\t\t// Place to load palette to\nextern LPDIRECTDRAWPALETTE\tPalettePtr;\t\t\t\t// Pointer to direct draw palette object\n\n//\n// Prototypes\n//\nlong FAR PASCAL _export WndProc (HWND, UINT, UINT, LONG) ;\nBOOL Set_Video_Mode(HWND hwnd, int w, int h, int bits_per_pixel);\nvoid Reset_Video_Mode(void);\nextern \"C\" void Wait_Vert_Blank(void);\nvoid Block_Mouse(GraphicBufferClass *ptr){}\nvoid Unblock_Mouse(GraphicBufferClass *ptr){}\n\n\n//\n// Externs\n//\nextern\tLPDIRECTDRAW\tDirectDrawObject;\nextern\tHWND\t\t\tMainWindow;\n\n\n\n\n\n\ntypedef struct tColourList {\n\n\tchar\tRed;\n\tchar\tGreen;\n\tchar\tBlue;\n} ColourList;\n\nColourList\tColourLookup[9]={\n\t0,0,0,\n\t63,0,0,\n\t0,63,0,\n\t0,0,63,\n\t63,0,63,\n\t63,63,0,\n\t0,63,63,\n\t32,32,32,\n\t63,63,63\n};\n\n\n\n\n\nextern \"C\" void Set_Palette_Register(int number,int red ,int green ,int blue);\n\nvoid Colour_Debug (int call_number)\n{\n\tSet_Palette_Register (0,ColourLookup[call_number].Red ,\n\t\t\t\t\t\t\t\t\tColourLookup[call_number].Green,\n\t\t\t\t\t\t\t\t\tColourLookup[call_number].Blue);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * WinMain -- Program entry point                                                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Standard Windows startup parameters                                               *\n *                                                                                             *\n * OUTPUT:   msg.wParam                                                                        *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 1:28PM ST : Created                                                              *\n *=============================================================================================*/\n\nint PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,\n\t\t\t\t\t\t  LPSTR lpszCmdParam, int nCmdShow)\n{\n\tstatic char \tszAppName[] = \"HelloWin\" ;\n\tHWND        \thwnd ;\n\tMSG         \tmsg ;\n\tWNDCLASS    \twndclass ;\n\tint\t\t\t\ti,j,k;\n\tchar\t\t\t\ta[10];\n\tchar\t\t\t\tb[10];\n\n\n\t//\n\t// Register the window class\n\t//\n\n\tMem_Copy(a,b,10);\n\tif (!hPrevInstance)\n\t\t{\n\t\twndclass.style         = CS_HREDRAW | CS_VREDRAW ;\n\t\twndclass.lpfnWndProc   = WndProc ;\n\t\twndclass.cbClsExtra    = 0 ;\n\t\twndclass.cbWndExtra    = 0 ;\n\t\twndclass.hInstance     = hInstance ;\n\t\twndclass.hIcon         = LoadIcon (hInstance, IDI_APPLICATION) ;\n\t\twndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;\n\t\twndclass.hbrBackground = NULL;\n\t\twndclass.lpszMenuName  = NULL;\n\t\twndclass.lpszClassName = NAME;\n\n\t\tRegisterClass (&wndclass) ;\n\t}\n\n\n\t//\n\t// Create our main window\n\t//\n\thwnd = CreateWindowEx (\n\t\t\t\t\t\t\tWS_EX_TOPMOST,\n\t\t\t\t\t\t\tNAME,\n\t\t\t\t\t\t\tTITLE,\n\t\t\t\t\t\t\tWS_POPUP | WS_MAXIMIZE,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tMODE_WIDTH,\n\t\t\t\t\t\t\tMODE_HEIGHT,\n\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\thInstance,\n\t\t\t\t\t\t\tNULL );\n\n\tShowWindow (hwnd, nCmdShow) ;\n\tUpdateWindow (hwnd) ;\n\tSetFocus (hwnd);\n\tMainWindow=hwnd;\t\t\t//Save the handle to our main window\n\t\t\t\t\t\t\t\t// (Dangerous  if Windoze can change the handle)\n\n\n\n\t//\n\t// Allocate space for the icons and load them\n\t//\n\tIconPointer=malloc (20000);\n\tLoad_File ( \"bridge3.des\" , IconPointer  );\n\tInvalidate_Cached_Icons();\n\tRegister_Icon_Set (IconPointer,TRUE);\n\n\t//\n\t// Load the desert palette\n\t//\n\tLoad_File ( \"desert.pal\" , Palette );\n\tk=0;\n\tfor( j=0 ; j<768 ; j+=3 )\n\t{\n\t\tpe[k].peRed = Palette[j];\n\t\tpe[k].peGreen = Palette[j+1];\n\t\tpe[k].peBlue = Palette[j+2];\n\t\tk++;\n\t}\n\n\n\t//\n\t// Initialise global stuff required for the tests\n\t//\n\n\t// Force load of font\n\tFontPtr=NULL;\n\n\n\t// Set the video mode\n\tSet_Video_Mode( MainWindow , MODE_WIDTH , MODE_HEIGHT , 8 );\n\n\n\t//\n\t// Init the stuff for drawing rectangles\n\t//\n\tx1=0;\n\ty1=0;\n\tx2=319;\n\ty2=199;\n\n\n\t//\n\t// Init the stamp test variables\n\t//\n\n\tStampX=100;\n\tStampY=100;\n\tStampXDir=1;\n    StampYDir=1;\n\n\t//\n\t// Create the GraphicBufferClass that will be the screen buffer\n\t//\n\tScreenBuffer = new GraphicBufferClass ( MODE_WIDTH , MODE_HEIGHT , (GBC_Enum)(GBC_VIDEOMEM | GBC_VISIBLE));\n\n\n\t//\n\t// Set the palette\n\t//\n\tDirectDrawObject->CreatePalette( DDPCAPS_8BIT | DDPCAPS_ALLOW256, &pe[0] , &PalettePtr ,NULL);\n\tScreenBuffer->Get_Graphic_Buffer()->Get_DD_Surface()->SetPalette( PalettePtr );\n\tPalettePtr->SetEntries( DDPSETPAL_VSYNC , 0 , 256 , &pe[0] );\n\n\n\t//\n\t// Set up the remap table for the Buffer_Remap test\n\t//\n\tfor ( i=0 ; i<256 ; i++ ){\n\t\tRemapTable[i]=(char)255-i;\n\t}\n\n\n\t//\n\t// Get rid of the windows cursor\n\t//\n\tShowCursor (FALSE);\n\n\tAllDone = FALSE;\n\n\t//\n\t// Windows message loop\n\t//\n\twhile ( ! AllDone ){\n\n\t\tTest_All();\t\t\t// Perform a test\n\n\t\tif( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ){\n\t\t\tif( !GetMessage( &msg, NULL, 0, 0 ) ){\n\t\t\t\treturn msg.wParam;\n\t\t\t}\n\t\t\tTranslateMessage(&msg);\n\t\t\tDispatchMessage(&msg);\n\t\t}\n\n\t}\n\n\treturn msg.wParam;\n}\n\n\n\n\n#ifdef cuts\t\t//this is now in a seperate file\n/***********************************************************************************************\n * Set_Mode -- temporary replacement for library set mode function                             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    int - mode width                                                                  *\n *           int - mode height                                                                 *\n *           int - bits per pixel                                                              *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 1:51PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Set_Mode ( int width , int height , int bpp )\n{\n\n\t//\n\t// Setup the direct draw system by\n\t//\t1. Creating the DirectDraw object\n\t//\t2. Setting the cooperative level to exclusive so we own the screen\n\t//\t3. Setting the video mode\n\t//\n\n\tif ( DirectDrawObject == NULL ){\n\n\t\t// Create the direct draw object\n\t\tDirectDrawCreate ( NULL , &DirectDrawObject , NULL);\n\n\t\t// Set the cooperative level\n\t\tDirectDrawObject->SetCooperativeLevel ( MainWindow , DDSCL_EXCLUSIVE\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t| DDSCL_FULLSCREEN\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t| DDSCL_ALLOWMODEX );\n\t\t// Set the required display mode with 8 bits per pixel\n\t\tDirectDrawObject->SetDisplayMode ( width , height , bpp );\n\t}\n\n}\n#endif\t//cuts\n\n\n/***********************************************************************************************\n * WndProc -- windows message callback                                                         *\n *                                                                                             *\n *   Pilfered from a windows example program - HELLOWIN.C                                      *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Standard Windoze callback parameters                                              *\n *                                                                                             *\n * OUTPUT:   long                                                                              *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 1:39PM ST : Pilfered                                                             *\n *=============================================================================================*/\n\nlong FAR PASCAL _export WndProc (HWND hwnd, UINT message, UINT wParam,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  LONG lParam)\n {\n\n\tswitch (message){\n\n\n\t\tcase WM_KEYDOWN:\n\n\t\t\tswitch ( wParam ){\n\n\t\t\t\tcase VK_SPACE:\n\t\t\t\t\tTest++;\n\t\t\t\t\tif ( Test>=MAX_TESTS ) {\n\t\t\t\t\t\tTest=0;\n\t\t\t\t\t}\n\t\t\t\t\tif ( BackBuffer ){\n\t\t\t\t\t\tdelete BackBuffer;\n\t\t\t\t\t\tBackBuffer=NULL;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WM_ACTIVATEAPP:\n\t\t\tif ((BOOL)wParam) {\n\t\t\t\tif (ScreenBuffer) {\n\t\t\t\t\tScreenBuffer->Get_DD_Surface()->Restore();\n\t\t\t\t\tRestore_Cached_Icons();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tTest++;\n\t\t\t\tTest--;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WM_DESTROY:\n\t\t\t//\n\t\t\t// Tidy up\n\t\t\t//\n\n\t\t\tif ( BackBuffer ) {\n\t\t\t\tdelete BackBuffer;\n\t\t\t}\n\t\t\tdelete ScreenBuffer;\n\n\t\t\tInvalidate_Cached_Icons();\n\n\t\t\tif ( DirectDrawObject ){\n\t\t\t\tReset_Video_Mode();\n\t\t\t}\n\n\t\t\tAllDone = TRUE;\n\t\t\tPostQuitMessage (0) ;\n\t\t\treturn(0);\n\t}\n\n\treturn DefWindowProc (hwnd, message, wParam, lParam) ;\n}\n\n\n\n\n\n\n/***********************************************************************************************\n * Font_Test -- test the font print member of the GBC                                          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 3:29PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Font_Test ( void )\n{\n\tconst char\tfont_name[]={\"font.fnt\"};\n\n\tif ( !FontPtr ){\n\t\tFontPtr = Load_Font ( &font_name[0] );\n\t\tFontXSpacing=0;\n\t\tFontYSpacing=0;\n\t\tFontPrintX=0;\n\t\tFontPrintY=0;\n\t}\n\n\tif ( FontPtr ){\n\t\tScreenBuffer->Print ( \"Hello Windoze\" , FontPrintX , FontPrintY ,255 , 0);\n\t}\n\n\tif ( FontPrintX<550 ){\n\t\tFontPrintX+=8;\n\t}\n\n\tif ( FontPrintY<380 ){\n\t\tFontPrintY+=8;\n\t}\n\n\n}\n\n\n\n/***********************************************************************************************\n * Rect_Test -- test the rectangle and line functions of the GBC                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/25/95 3:03PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Rect_Test ( GraphicBufferClass *screen_buffer )\n{\n\tScreenBuffer->Lock();\n\n\tscreen_buffer->Draw_Rect ( x1 , y1 , x2 , y2 , 255 );\n\tif ( x1<90 ){\n\t\tx1+=2;\n\t}\n\n\tif ( y1<90 ){\n\t\ty1+=2;\n\t}\n\n\tif ( x2>230 ){\n\t\tx2-=2;\n\t}\n\n\tif ( y2>110 ){\n\t\ty2-=2;\n\t}\n\n\tScreenBuffer->Unlock();\n}\n\n\n\n\n/***********************************************************************************************\n * Clear_Test -- test the clear function of the GraphicBufferClass                             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/25/95 3:05PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Clear_Test ( void )\n{\n\n\tx1=0;\n\ty1=0;\n\tx2=319;\n\ty2=199;\n\n\tFontPrintX=0;\n\tFontPrintY=0;\n\n\tScreenBuffer->Clear ( rand()&255 );\n}\n\n\n\n\n\n/***********************************************************************************************\n * Stamp_Test -- test the Draw_Stamp member of GraphicBufferClass                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/28/95 6:02PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Stamp_Test ( void )\n{\n\tint\t\tx;\n\tint\t\ty;\n\tint\t\ticon=0;\n\n\t//\n\t// Use stacking locks to speed things up\n\t//\n\t//ScreenBuffer->Lock();\n\n\tWait_Vert_Blank();\n\tColour_Debug(1);\n\tfor\t( y=0 ; y<5*24 ; y+=24 ){\n\n\t\tfor ( x=0 ; x<6*24 ; x+=24 ){\n\n\t\t\tScreenBuffer->Draw_Stamp( IconPointer, icon++ , x+StampX, y+StampY, NULL ,0);\n\n\t\t}\n\t}\n\tColour_Debug(0);\n\n    //ScreenBuffer->Unlock();\n\n\tStampX+=StampXDir;\n\tStampY+=StampYDir;\n\n\tif ( StampX>640-6*24 || StampX<1 ){\n\t\tStampXDir=-StampXDir;\n\t}\n\n\tif ( StampY>400-6*24 || StampY<1 ){\n\t\tStampYDir=-StampYDir;\n\t}\n\n}\n\n\n\n/***********************************************************************************************\n * Stamp_Test2 -- test the Draw_Stamp member of GraphicBufferClass (no caching)                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/28/95 6:02PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Stamp_Test2 ( void )\n{\n\tint\t\tx;\n\tint\t\ty;\n\tint\t\ticon=0;\n\n\t//\n\t// Use stacking locks to speed things up\n\t//\n\t//ScreenBuffer->Lock();\n\n\tWait_Vert_Blank();\n\tColour_Debug(2);\n\tfor\t( y=0 ; y<5*24 ; y+=24 ){\n\n\t\tfor ( x=0 ; x<6*24 ; x+=24 ){\n\n\t\t\tScreenBuffer->Draw_Stamp( IconPointer, icon++ , x+StampX, y+StampY, NULL);\n\n\t\t}\n\t}\n\tColour_Debug(0);\n\n    //ScreenBuffer->Unlock();\n\n\tStampX+=StampXDir;\n\tStampY+=StampYDir;\n\n\tif ( StampX>640-6*24 || StampX<1 ){\n\t\tStampXDir=-StampXDir;\n\t}\n\n\tif ( StampY>400-6*24 || StampY<1 ){\n\t\tStampYDir=-StampYDir;\n\t}\n\n}\n\n\n\n\n/***********************************************************************************************\n * Pixel_Test -- test the GVPclass put_pixel member                                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/25/95 5:29PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Pixel_Test ( void )\n{\n\tScreenBuffer->Put_Pixel ( rand() & 511 , rand() & 255 , rand () &255 );\n\n}\n\n\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Read_Pixel_Test -- test the GVPclass Read_Pixel member                                      *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/26/95 4:51PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Read_Pixel_Test ( void )\n{\n\n\tint\t\ti;\n\tint\t\tcolour;\n\tint\t\tpixel_x;\n\tint\t\tpixel_y;\n\n\tif ( !BackBuffer ) {\n\n\t\tBackBuffer = new GraphicBufferClass(640,400, GBC_VIDEOMEM );\n\n\t\tBackBuffer->Clear( 0 );\n\t\tScreenBuffer->Clear ( 0 );\n\n\t\tx1=0;\n\t\ty1=0;\n\t\tx2=319;\n\t\ty2=199;\n\n\t\tfor ( i=0 ; i<50 ; i++ ) {\n\t\t\tRect_Test ( BackBuffer );\n\t\t}\n\n\t}\n\n\n\t//\n\t// Use the stacking lock feature to lock the surfaces once only and\n\t// then draw 10 pixels\n\t//\n\n\tScreenBuffer->Lock();\n\tBackBuffer->Lock();\n\n\tfor ( i=0 ; i<10 ; i++ ){\n\n\t\tpixel_x = rand() &511;\n\t\tpixel_y = rand() &255;\n\n\t\tcolour=BackBuffer->Get_Pixel ( pixel_x , pixel_y );\n\n\t\tScreenBuffer->Put_Pixel ( pixel_x , pixel_y , colour );\n\t}\n\n\tBackBuffer->Unlock();\n\tScreenBuffer->Unlock();\n\n}\n\n\n\n/***********************************************************************************************\n * Scale_Test -- test the GVPclass scale member                                                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/26/95 10:27AM ST : Created                                                             *\n *=============================================================================================*/\nvoid Scale_Test ( void )\n{\n\n\tint\t\ti;\n\n\tif ( !BackBuffer ) {\n\n\t\tBackBuffer = new GraphicBufferClass(640, 400);\n\n\t\tBackBuffer->Clear( 0 );\n\n\t\tx1=0;\n\t\ty1=0;\n\t\tx2=319;\n\t\ty2=199;\n\n\t\tfor ( i=0 ; i<50 ; i++ ) {\n\t\t\tRect_Test ( BackBuffer );\n\t\t}\n\n\t\tBlitStretchX=0;\n\t\tBlitStretchY=0;\n\t\tBlitStretchXAdd=1;\n\t\tBlitStretchYAdd=1;\n\t}\n\n\tBackBuffer->Scale ( *ScreenBuffer , 0 , 0 , 10 , 10\n\t\t\t\t\t\t,320 , 200 , 320+BlitStretchX , 200+BlitStretchY );\n\n\tBlitStretchX += BlitStretchXAdd;\n\tBlitStretchY += BlitStretchYAdd;\n\n\tif ( (BlitStretchX == 100) || (BlitStretchX==-100) ){\n\t\tBlitStretchXAdd=-BlitStretchXAdd;\n\t}\n\n\tif ( (BlitStretchY == 100) || (BlitStretchY==-100) ){\n\t\tBlitStretchYAdd=-BlitStretchYAdd;\n\t}\n\n\n\n\n}\n\n\n\n/***********************************************************************************************\n * Blit_Test1 -- test the blit member of the GraphicBufferClass                                *\n *                                                                                             *\n *    Blits from video memory to video memory                                                  *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/25/95 5:39PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Blit_Test1 ( void )\n{\n\n\tint\ti;\n\n\tif ( !BackBuffer ) {\n\t\tBackBuffer = new GraphicBufferClass(640, 400, GBC_VIDEOMEM);\n\n\t\tBackBuffer->Clear( 0 );\n\n\t\tx1=0;\n\t\ty1=0;\n\t\tx2=319;\n\t\ty2=199;\n\n\t\tfor ( i=0 ; i<50 ; i++ ) {\n\t\t\tRect_Test ( BackBuffer );\n\t\t}\n\n\t\tBlitXAdd=0;\n\t\tBlitXDir=1;\n\t\tBlitYAdd=0;\n\t\tBlitYDir=1;\n\t}\n\n\n\tBackBuffer->Blit ( *ScreenBuffer , 0 , 0 , BlitXAdd , BlitYAdd , 320 , 200 , (BOOL) FALSE );\n\n\tBlitXAdd+=BlitXDir;\n\n\tif ( (BlitXAdd == 0) || (BlitXAdd == 320 )){\n\t\tBlitXDir=-BlitXDir;\n\t}\n\n\n\tBlitYAdd+=BlitYDir;\n\n\tif ( (BlitYAdd == 0) || (BlitYAdd == 200 )){\n\t\tBlitYDir=-BlitYDir;\n\t}\n\n\n}\n\n\n\n\n\n/***********************************************************************************************\n * Blit_Test2 -- test the blit member of the GraphicBufferClass                                *\n *                                                                                             *\n *    Blits from system memory to video memory                                                 *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 9:36AM ST : Created                                                              *\n *=============================================================================================*/\nvoid Blit_Test2 ( void )\n{\n\n\tint\ti;\n\n\tif ( !BackBuffer ) {\n\t\tBackBuffer = new GraphicBufferClass(640, 400);\n\n\t\tBackBuffer->Clear( 0 );\n\n\t\tx1=0;\n\t\ty1=0;\n\t\tx2=319;\n\t\ty2=199;\n\n\t\tfor ( i=0 ; i<50 ; i++ ) {\n\t\t\tRect_Test ( BackBuffer );\n\t\t}\n\n\t\tBlitXAdd=0;\n\t\tBlitXDir=1;\n\t\tBlitYAdd=0;\n\t\tBlitYDir=1;\n\t}\n\n\n\tBackBuffer->Blit ( *ScreenBuffer , 0 , 0 , BlitXAdd , BlitYAdd , 320 , 200 , (BOOL) FALSE );\n\n\tBlitXAdd+=BlitXDir;\n\n\tif ( (BlitXAdd == 0) || (BlitXAdd == 320 )){\n\t\tBlitXDir=-BlitXDir;\n\t}\n\n\n\tBlitYAdd+=BlitYDir;\n\n\tif ( (BlitYAdd == 0) || (BlitYAdd == 200 )){\n\t\tBlitYDir=-BlitYDir;\n\t}\n\n\n}\n\n\n\n\n\n/***********************************************************************************************\n * Fill_Rect_Test -- test the GraphicBufferClass fill rectangle member                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/26/95 5:23PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Fill_Rect_Test ( void )\n{\n\n\tint\t\tx1;\n\tint\t\ty1;\n\tint\t\tx2;\n\tint\t\ty2;\n\n\tx1= rand()&511;\n\tx2= rand()&511;\n\ty1= rand()&255;\n\ty2= rand()&255;\n\n\tScreenBuffer->Fill_Rect ( min ( x1,x2 ) , min ( y1,y2) , max ( x1,x2 ) , max ( y1,y2 ) , rand()&255 );\n\n\n}\n\n\n\n\n\n/***********************************************************************************************\n * Remap_Test -- test the Remap member of GraphicsBufferClass                                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/26/95 6:26PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Remap_Test ( void )\n{\n\tScreenBuffer->Remap ( 0 , 0 , 640 , 400 , &RemapTable[0] );\n}\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Quad_Test -- test the quad fill member of GraphicBufferClass                                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 11:12AM ST : Created                                                             *\n *=============================================================================================*/\n\nvoid Quad_Test ( void )\n{\n\tint\t\tcolour;\n\tint\t\tx0;\n\tint\t\tx1;\n\tint\t\tx2;\n\tint\t\tx3;\n\tint\t\ty0;\n\tint\t\ty1;\n\tint\t\ty2;\n\tint\t\ty3;\n\n\tx0 = rand() & 255;\n\tx1 = rand() & 255+320;\n\tx2 = rand() & 255+320;\n\tx3 = rand() & 255;\n\n\ty0 = rand() & 127;\n\ty1 = rand() & 127;\n\ty2 = rand() & 127+250;\n\ty3 = rand() & 127+250;\n\n\tcolour= rand()&255;\n\n\tScreenBuffer->Fill_Quad ( SpanBuff , x0,y0,x1,y1,x2,y2,x3,y3,colour);\n\n}\n\n\n\n\n\n\n/***********************************************************************************************\n * Copy_Test - test the To_Buffer member of GraphicsBufferClass                                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 11:36AM ST : Created                                                             *\n *=============================================================================================*/\nvoid Copy_Test ( void )\n{\n\n\tBufferClass\t*buffer;\n\tchar\t\t*buffer_ptr;\n\n\n\tbuffer = new BufferClass (640*400);\n\n\tScreenBuffer->To_Buffer(buffer);\n\n\tbuffer_ptr = (char*)buffer->Get_Buffer();\n\tmemcpy ( buffer_ptr , buffer_ptr+4 , 640*400-4 );\n\n\tbuffer->To_Page ( *ScreenBuffer );\n\n    delete buffer;\n\n}\n\n\n\n\n\n\n/***********************************************************************************************\n * Test_All -- perform tests on GraphicsBufferClass                                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/25/95 2:53PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Test_All ( void )\n\n{\n\n\tswitch ( Test ){\n\n\t\tcase 0:\n\t\t\tClear_Test();\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tRect_Test( ScreenBuffer );\n\t\t\tbreak;\n\n\t\tcase 2:\n\t\t\tPixel_Test();\n\t\t\tbreak;\n\n\t\tcase 3:\n\t\t\tBlit_Test1();\n\t\t\tbreak;\n\n\t\tcase 4:\n\t\t\tBlit_Test2();\n\t\t\tbreak;\n\n\t\tcase 5:\n\t\t\tScale_Test();\n\t\t\tbreak;\n\n\t\tcase 6:\n\t\t\tRead_Pixel_Test();\n\t\t\tbreak;\n\n\t\tcase 7:\n\t\t\tFill_Rect_Test();\n\t\t\tbreak;\n\n\t\tcase 8:\n\t\t\tRemap_Test();\n\t\t\tbreak;\n\n\t\tcase 9:\n\t\t\tQuad_Test();\n\t\t\tbreak;\n\n\t\tcase 10:\n\t\t\tCopy_Test();\n\t\t\tbreak;\n\n\t\tcase 11:\n\t\t\tFont_Test();\n\t\t\tbreak;\n\n\t\tcase 12:\n\t\t\tStamp_Test();\n\t\t\tbreak;\n\n\t\tcase 13:\n\t\t\tStamp_Test2();\n\t\t\tbreak;\n\n\t}\n\n}\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/TEST/TEST.DEF",
    "content": "IMPORTS\n\tDirectDrawCreate=DDRAW.DirectDrawCreate\n\tDirectSoundCreate=DSOUND.DirectSoundCreate\n\tDirectPlayEnumerate=DPLAY.DirectPlayEnumerate\n\tDirectPlayCreate=DPLAY.DirectPlayCreate\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/TEST/TESTASM.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\nIDEAL\nP386\nMODEL USE32 FLAT\njumps\n\n\tcodeseg\n\n\tmasm\n;\n; Change a DAC colour register directly\n;\n; register number in al\n;\n; bh=red bl=green cl=blue\n;\n\nset_dac_col proc near\n\t\tpushad\n\t\tcli\n\t\tpush\teax\n\t\tmov\tdx,03dah\n\t\tin\tal,dx\n\t\tjmp\t@@1\n@@1:\t\tmov\tdx,03c8h\n\t\tpop\teax\n\t\tout\tdx,al\n\t\tjmp\t@@2\n@@2:\t\tinc\tdl\n\t\tmov\tal,bh\n\t\tout\tdx,al\n\t\tjmp\t@@3\n@@3:\t\tmov\tal,bl\n\t\tout\tdx,al\n\t\tjmp\t@@4\n@@4:\t\tmov\tal,cl\n\t\tout\tdx,al\n\t\tjmp\t@@5\n@@5:\t\tsti\n\t\tpopad\n\t\tret\nset_dac_col endp\n\n\tideal\n\n\nglobal\tSet_Palette_Register_:near\n\n\nproc Set_Palette_Register_ near\n\n\t\tpushad\n\t\tand\tcl,63\n\t\tmov\tbh,dl\n\t\tand\tbh,63\n\t\tand\tbl,63\n\t\tcall\tset_dac_col\n\t\tpopad\n\t\tret\n\nendp Set_Palette_Register_\n\nend\n"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/TOBUFF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TOBUFFER.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                  Last Update : Feb 10, 1995   [jrj]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVC::TOBUFFER -- Copies a virtual viewport to a linear buffer         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\n\nTRANSP equ 0\n\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n\n;***************************************************************************\n;* VIVC::TOBUFFER -- Copies a virtual viewport to a linear buffer          *\n;*                                                                         *\n;* INPUT:\tBYTE *\tdest\t\t- buffer to copy to\t\t   *\n;*\t\t\tsize\t\t- size of the buffer to copy to\t   *\n;*\t\t\tx_pixel\t\t- x pixel on viewport to copy from *\n;*\t\t\ty_pixel \t- y pixel on viewport to copy from *\n;*\t\t\tpixel_width\t- the width of copy region\t   *\n;*\t\t\tpixel_height\t- the height of copy region\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    Coordinates and dimensions will be adjusted if they exceed *\n;*\t        the boundaries.  In the event that no adjustment is \t   *\n;*\t        possible this routine will abort.  If the size of the \t   *\n;*\t\tregion to copy exceeds the size passed in for the buffer   *\n;*\t\tthe routine will automatically abort.\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_To_Buffer C near\n\tUSES\tebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tthis_object:DWORD\t\t; this is a class member function\n\tARG\tx_pixel:DWORD\t\t; Page X pixel coordinate.\n\tARG\ty_pixel:DWORD\t\t; Page Y pixel coordinate.\n\tARG\tpixel_width:DWORD\t; Width of region in pixels.\n\tARG\tpixel_height:DWORD\t; Height of region in pixels.\n\tARG\tdest:DWORD\t\t; the buffer to copy to\n\tARG\tbuffer_size:DWORD\t; the size of the buffer\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tLOCAL\tdest_x1 : dword\n\tLOCAL\tdest_y1 : dword\n\tLOCAL\tdest_ajust_width:DWORD\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_area   :  dword\n\n; Clip dest Rectangle against source Window boundaries.\n\n\tmov\t[ dest_x1 ] , 0\n\tmov\t[ dest_y1 ] , 0\n\n\tmov  \tesi , [ this_object ]\t    ; get ptr to dest\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_blit\n\n\ttest\tcl , 1000b\n\tjz\t??scr_left_ok\n\tmov\teax , [ x_pixel ]\n\tneg\teax\n\tmov\t[ x_pixel ] , 0\n\tmov\t[ dest_x1 ] , eax\n\n??scr_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??scr_bottom_ok\n \tmov\teax , [ y_pixel ]\n\tneg\teax\n\tmov\t[ y_pixel ] , 0\n\tmov\t[ dest_y1 ] , eax\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\tmov\teax , [ (GraphicViewPort esi) . GVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n??do_blit:\n\n       cld\n\n       mov\teax , [ (GraphicViewPort esi) . GVPXAdd ]\n       add\teax , [ (GraphicViewPort esi) . GVPWidth ]\n       add\teax , [ (GraphicViewPort esi) . GVPPitch ]\n       mov\tesi , [ (GraphicViewPort esi) . GVPOffset ]\n\n       mov\tecx , eax\n       mul\t[ y_pixel ]\n       add\tesi , [ x_pixel ]\n       add\tesi , eax\n\n       add\tecx , [ x_pixel ]\n       sub\tecx , [ x1_pixel ]\n       mov\t[ scr_ajust_width ] , ecx\n\n       mov\tedi , [ dest ]\n       mov\teax , [ pixel_width ]\n       sub\teax , [ x1_pixel ]\n       add\teax , [ x_pixel ]\n       mov\t[ dest_ajust_width ] , eax\n\n       mov\teax , [ dest_y1 ]\n       mul \t[ pixel_width ]\n       add\teax , [ dest_x1 ]\n       add\tedi , eax\n\n       mov\tedx , [ y1_pixel ]\n       mov\teax , [ x1_pixel ]\n       sub\tedx , [ y_pixel ]\n       jle\t??real_out\n       sub\teax , [ x_pixel ]\n       jle\t??real_out\n\n       mov\tebx , [ pixel_width ]\n       imul\tebx , edx\n       cmp\tebx , [ buffer_size ]\n       jg\t??real_out\n\n\n; ********************************************************************\n; Forward bitblit only\n\nIF TRANSP\n       cmp\t[ transp ] , 0\n       jnz\t??forward_Blit_trans\nENDIF\n\n; the inner loop is so efficient that\n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10\n       jl\t??forward_loop_bytes\n\n??forward_loop_dword:\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\n       jnz\t??forward_loop_dword\n       ret\n\n??forward_loop_bytes:\n       mov\tecx , eax\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_bytes\n       ret\n\n\nIF  TRANSP\n\n??forward_Blit_trans:\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n??forward_loop_trans:\n       mov\tecx , eax\n       jmp\t[ y1_pixel ]\n??forward_trans_line:\n       REPT\t32\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tesi\n\t    \tinc\tedi\n\tENDM\n    ??transp_reference:\n       dec\tecx\n       jge\t??forward_trans_line\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\n       jnz\t??forward_loop_trans\n       ret\nENDIF\n\n??real_out:\n       ret\n\nENDP\tBuffer_To_Buffer\n\nEND"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/TOPAGE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TOPAGE.ASM                               *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : June 15, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Buffer_To_Page -- Copies a linear buffer to a virtual viewport\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nTRANSP\tequ  0\n\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nCODESEG\n\n;***************************************************************************\n;* VVC::TOPAGE -- Copies a linear buffer to a virtual viewport\t\t   *\n;*                                                                         *\n;* INPUT:\tWORD\tx_pixel\t\t- x pixel on viewport to copy from *\n;*\t\tWORD\ty_pixel \t- y pixel on viewport to copy from *\n;*\t\tWORD\tpixel_width\t- the width of copy region\t   *\n;*\t\tWORD\tpixel_height\t- the height of copy region\t   *\n;*\t\tBYTE *\tsrc\t\t- buffer to copy from\t\t   *\n;*\t\tVVPC *  dest\t\t- virtual viewport to copy to\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    Coordinates and dimensions will be adjusted if they exceed *\n;*\t        the boundaries.  In the event that no adjustment is \t   *\n;*\t        possible this routine will abort.  If the size of the \t   *\n;*\t\tregion to copy exceeds the size passed in for the buffer   *\n;*\t\tthe routine will automatically abort.\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_To_Page C near\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\tARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\tARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\tARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\tARG    \tsrc         :DWORD\t\t; this is a member function\n\tARG\tdest        :DWORD\t\t; what are we blitting to\n\n;\tARG\ttrans       :DWORD\t\t\t; do we deal with transparents?\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tlocal\tscr_x \t: dword\n\tlocal\tscr_y \t: dword\n\tLOCAL\tdest_ajust_width:DWORD\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_area   :  dword\n\n\tcmp\t[ src ] , 0\n\tjz\t??real_out\n\n\n; Clip dest Rectangle against source Window boundaries.\n\n\tmov\t[ scr_x ] , 0\n\tmov\t[ scr_y ] , 0\n\tmov  \tesi , [ dest ]\t    ; get ptr to dest\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_blit\n\n\ttest\tcl , 1000b\n\tjz\t??dest_left_ok\n\tmov\teax , [ x_pixel ]\n\tneg\teax\n\tmov\t[ x_pixel ] , 0\n\tmov\t[ scr_x ] , eax\n\n??dest_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dest_bottom_ok\n\tmov\teax , [ y_pixel ]\n\tneg\teax\n\tmov\t[ y_pixel ] , 0\n\tmov\t[ scr_y ] , eax\n\n??dest_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??dest_right_ok\n\tmov\teax , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??dest_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\tmov\teax , [ (GraphicViewPort esi) . GVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n??do_blit:\n\n       cld\n\n       mov\teax , [ (GraphicViewPort esi) . GVPXAdd ]\n       add\teax , [ (GraphicViewPort esi) . GVPWidth ]\n       add\teax , [ (GraphicViewPort esi) . GVPPitch ]\n       mov\tedi , [ (GraphicViewPort esi) . GVPOffset ]\n\n       mov\tecx , eax\n       mul\t[ y_pixel ]\n       add\tedi , [ x_pixel ]\n       add\tedi , eax\n\n       add\tecx , [ x_pixel ]\n       sub\tecx , [ x1_pixel ]\n       mov\t[ dest_ajust_width ] , ecx\n\n\n       mov\tesi , [ src ]\n       mov\teax , [ pixel_width ]\n       sub\teax , [ x1_pixel ]\n       add\teax , [ x_pixel ]\n       mov\t[ scr_ajust_width ] , eax\n\n       mov\teax , [ scr_y ]\n       mul \t[ pixel_width ]\n       add\teax , [ scr_x ]\n       add\tesi , eax\n\n       mov\tedx , [ y1_pixel ]\n       mov\teax , [ x1_pixel ]\n\n       sub\tedx , [ y_pixel ]\n       jle\t??real_out\n       sub\teax , [ x_pixel ]\n       jle\t??real_out\n\n\n; ********************************************************************\n; Forward bitblit only\n\nIF TRANSP\n       test\t[ trans ] , 1\n       jnz\t??forward_Blit_trans\nENDIF\n\n\n; the inner loop is so efficient that\n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10\n       jl\t??forward_loop_bytes\n\n??forward_loop_dword:\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\n       jnz\t??forward_loop_dword\n       ret\n\n??forward_loop_bytes:\n       mov\tecx , eax\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_bytes\n       ret\n\nIF  TRANSP\n\n\n??forward_Blit_trans:\n\n\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n\n??forward_loop_trans:\n       mov\tecx , eax\n       jmp\t[ y1_pixel ]\n??forward_trans_line:\n       REPT\t32\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\tinc\tesi\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tedi\n\tENDM\n    ??transp_reference:\n       dec\tecx\n       jge\t??forward_trans_line\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\n       jnz\t??forward_loop_trans\n       ret\nENDIF\n\n??real_out:\n       ret\n\n\n\tENDP\tBuffer_To_Page\nEND"
  },
  {
    "path": "WIN32LIB/DRAWBUFF/TXTPRNT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TXTPRNT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 17, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 17, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Buffer_Print -- Assembly Buffer text print routine                    *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n;*=========================================================================*\n;* Extern the font pointer which is defined by the font class\t\t   *\n;*=========================================================================*\nGLOBAL\tC FontPtr:DWORD\nGLOBAL\tC FontXSpacing:DWORD\nGLOBAL\tC FontYSpacing:DWORD\nGLOBAL\tC ColorXlat:BYTE\n\n;*=========================================================================*\n;* Define the necessary equates for structures and bounds checking\t   *\n;*=========================================================================*\n; The header of the font file looks like object:\n; \tUWORD\tFontLength;\t\t0\n; \tBYTE\tFontCompress;\t\t2\n;\tBYTE\tFontDataBlocks;\t\t3\n;\tUWORD\tInfoBlockOffset;\t4\n;\tUWORD\tOffsetBlockOffset;\t6\n;\tUWORD\tWidthBlockOffset;\t8\n;\tUWORD\tDataBlockOffset;\t10\n;\tUWORD\tHeightOffset;\t\t12\n; For this reason the following equates have these values:\nFONTINFOBLOCK\t\tEQU\t4\nFONTOFFSETBLOCK\t\tEQU\t6\nFONTWIDTHBLOCK\t\tEQU\t8\nFONTDATABLOCK\t\tEQU\t10\nFONTHEIGHTBLOCK\t\tEQU\t12\n\nFONTINFOMAXHEIGHT\tEQU\t4\nFONTINFOMAXWIDTH\tEQU\t5\n\n\nLOCALS ??\n;*=========================================================================*\n;* Define the color xlate table in the data segment\t\t\t   *\n;*=========================================================================*\n\tDATASEG\n\nColorXlat\tDB\t000H,001H,002H,003H,004H,005H,006H,007H\n\t\tDB\t008H,009H,00AH,00BH,00CH,00DH,00EH,00FH\n\n\t\tDB\t001H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t002H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t003H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t004H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t005H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t006H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t007H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t008H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t009H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00AH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00BH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00CH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00DH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00EH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00FH\n\n\tCODESEG\n\n\n;***************************************************************************\n;* Buffer_PRINT -- Assembly buffer text print routine                      *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/17/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_Print C near\n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\tthis_object:DWORD\n\tARG\tstring:DWORD\n\tARG\tx_pixel:DWORD\n\tARG\ty_pixel:DWORD\n\tARG\tfcolor:DWORD\n\tARG\tbcolor:DWORD\n\n\tLOCAL\tinfoblock:DWORD\t\t; pointer to info block\n\tLOCAL\toffsetblock:DWORD\t; pointer to offset block  (UWORD *)\n\tLOCAL\twidthblock:DWORD\t; pointer to width block   (BYTE  *)\n\tLOCAL\theightblock:DWORD\t; pointer to height block  (UWORD *)\n\n\tLOCAL\tcurline:DWORD\t\t; pointer to first column of current row.\n\tLOCAL\tbufferwidth:DWORD    \t; width of buffer (vpwidth + Xadd)\n\tLOCAL\tnextdraw:DWORD\t\t; bufferwidth - width of cur character.\n\tLOCAL\tstartdraw:DWORD\t\t; where next character will start being drawn.\n\n\tLOCAL\tchar:DWORD\t\t; current character value.\n\tlocal\tptr_string:dword\t\t; pointer to string\n\tLOCAL\tmaxheight:BYTE\t\t; max height of characters in font.\n\tLOCAL\tbottomblank:BYTE\t; amount of empty space below current character.\n\tLOCAL\tcharheight:BYTE\t\t; true height of current character.\n\tLOCAL\tvpwidth:DWORD\n\tLOCAL\tvpheight:DWORD\n\tLOCAL\toriginal_x:DWORD\t; Starting X position.\n\n\tmov\teax,[string]\t\t; check that the string is not NULL\n\tmov\t[ptr_string],eax\n\tcmp\teax,0\n\tjz\t??done\n\n;-------------------------------- Where to draw -----------------------------------------------\n\t; Set up memory location to start drawing.\n\tmov  \tebx,[this_object]\t\t\t\t; get a pointer to dest\n\tmov\teax,[(GraphicViewPort ebx).GVPHeight]\t; get height of viewport\n\tmov\t[vpheight],eax\t\t\t\t; save off height of viewport\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\t; get width of viewport\n\tmov\t[vpwidth],eax\t\t\t\t; save it off for later\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\t; add in xadd for bytes_per_line\n\tadd\teax,[(GraphicViewPort ebx).GVPPitch]\t; add in pitch of direct draw surface\n\tmov\t[bufferwidth],eax     \t\t\t; save it off for later use.\n\n\tmul\t[y_pixel]\t\t\t\t; multiply rowsize * y_pixel start.\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get start of the viewport\n\tadd\tedi,eax\t\t\t\t\t; add y position to start of vp\n\tmov\t[curline],edi\t\t\t\t; save 0,y address for line feed stuff.\n\tadd\tedi,[x_pixel]\t\t\t\t; add to get starting column in starting row.\n\tmov\t[startdraw],edi\t\t\t\t; save it off.\n\n\n\tmov\teax,[x_pixel]\n\tmov\t[original_x],eax\n\n;-------------------------------- Create block pointers ----------------------------------------\n\t; Get the pointer to the font.\n\t; We could check for NULL but why waste the time.\n\t; It is up to programmer to make sure it is set.\n\tmov\tesi,[FontPtr]\t\t; Get the font pointer\n\tor\tesi,esi\n\tjz\t??overflow\n\n\t; Set up some pointers to the different memory blocks.\n\t; esi (FontPtr) is added to each to get the true address of each block.\n\t; Many registers are used for P5 optimizations.\n\t; ebx is used for InfoBlock which is then used in the next section.\n\tmovzx\teax,[WORD PTR esi+FONTOFFSETBLOCK]\t; get offset to offset block\n\tmovzx\tebx,[WORD PTR esi+FONTINFOBLOCK]      \t; get offset to info block (must be ebx for height test)\n\tmovzx\tecx,[WORD PTR esi+FONTWIDTHBLOCK] \t; get offset to width block\n\tmovzx\tedx,[WORD PTR esi+FONTHEIGHTBLOCK]\t; get offset to height block\n\n\tadd\teax,esi\t\t\t\t; add offset of FontPtr to offset block\n\tadd\tebx,esi\t\t\t\t; add offset of FontPtr to info block\n\tadd\tecx,esi\t\t\t\t; add offset of FontPtr to width block\n\tadd\tedx,esi\t\t\t\t; add offset of FontPtr to height block\n\n\tmov\t[offsetblock],eax\t\t; save offset to offset block\n\tmov\t[infoblock],ebx\t\t\t; save offset to info block\n\tmov\t[widthblock],ecx   \t\t; save offset to width block\n\tmov\t[heightblock],edx\t\t; save offset to height block\n\n;------------------------------------------ Test for fit ----------------------------------------------\n\t; Test to make sure the height of the max character will fit on this line\n\t; and and not fall out of the viewport.\n\t; remember we set ebx to FONTINFOBLOCK above.\n\tmovzx\teax,[BYTE PTR ebx + FONTINFOMAXHEIGHT]; get the max height in font.\n\tmov\t[maxheight],al\t\t\t; save it for later use.\n\tadd\teax,[y_pixel]\t\t\t; add current y_value.\n\tcmp\teax,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we're outa here.\n\n\tmov\t[y_pixel],eax\t\t\t; save for next line feed. y value for next line.\n\n\tcld\t\t\t\t\t; Make sure we are always forward copying.\n\n;------------------------ Set palette foreground and background ----------------------------------\n\tmov\teax,[fcolor]\t\t; foreground color\n\tmov\t[ColorXlat+1],al\n\tmov\t[ColorXlat+16],al\n\n\tmov\teax,[bcolor]\t\t; background color\n\tmov\t[ColorXlat],al\n\n;-------------------------------------------------------------------------------------------------\n;----------------------------------------- Main loop ----------------------------------------------\n\t; Now we go into the main loop of reading each character in the string and doing\n\t; something with it.\n??next_char:\n\t; while (*string++)\n\txor\teax,eax\t\t\t\t; zero out since we will just load al.\n\tmov\tesi,[string]\t\t\t; get address on next character.\n\tlodsb\t\t\t\t\t; load the character into al.\n\ttest\teax,0FFH\t\t\t; test to see if character is a NULL\n\tjz\t??done\t\t\t\t; character is NULL, get outa here.\n\n\tmov\tedi,[startdraw]\t\t\t; Load the starting address.\n\n\tmov\t[string],esi\t\t\t; save index into string. (incremented by lodsb)\n\n\tcmp\tal,10\t\t\t\t; is the character a carry return?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\n\tcmp\tal,13\t\t\t\t; is the character a line feed?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\n\tmov\t[char],eax\t\t\t; save the character off for later reference.\n\tmov\tebx,eax\t\t\t\t; save it in ebx for later use also.\n\n\tadd\teax,[widthblock]\t\t; figure address of width of character.\n\tmov\tecx,[x_pixel]\t\t\t; get current x_pixel.\n\tmovzx\tedx,[BYTE PTR eax]\t \t; get the width of the character in dl.\n\tadd\tecx,edx\t\t\t\t; add width of char to current x_pixel.\n\tmov\teax,[FontXSpacing]\n\tadd\tecx,eax\n\tadd\t[startdraw],edx\t\t\t; save start draw for next character.\n\tadd\t[startdraw],eax\t\t\t; adjust for the font spacing value\n\n\tcmp\tecx,[vpwidth]\t\t\t; is the pixel greater then the vp width?\n\tjg\t??force_line_feed\t\t; if so, force a line feed.\n\n\tmov\t[x_pixel],ecx\t\t\t; save value of start of next character.\n\tmov\tecx,[bufferwidth]\t\t; get amount to next y same x (one row down)\n\tsub\tecx,edx\t\t\t\t; take the current width off.\n\tmov\t[nextdraw],ecx\t\t\t; save it to add to edi when done with a row.\n\n\t; At this point we got the character. It is now time to find out specifics\n\t; about drawing the darn thing.\n\t; ebx = char so they can be used as an indexes.\n\t; edx = width of character for loop later.\n\n\t; get offset of data for character into esi.\n\tshl\tebx,1\t\t\t\t; mult by 2 to later use as a WORD index.\n\tmov\tesi,[offsetblock]\t\t; get pointer to begining of offset block.\n\tadd\tesi,ebx\t\t\t\t; index into offset block.\n\tmovzx\tesi,[WORD PTR esi]\t\t; get true offset into data block from FontPtr.\n\tadd\tesi,[FontPtr]\t\t\t; Now add FontPtr address to get true address.\n\n\t; Get top and bottom blank sizes and the true height of the character.\n\tadd\tebx,[heightblock]\t\t; point ebx to element in height array.\n\tmov\tal,[ebx+1]\t\t\t; load the data height into dl.\n\tmov\tcl,[ebx]\t\t\t; load the first data row into cl.\n\tmov\tbl,[maxheight]\t\t\t; get the max height of characters.\n\tmov\t[charheight],al\t\t\t; get number of rows with data.\n\tadd\tal,cl\t\t\t\t; add the two heights.\n\tsub\tbl,al\t\t\t\t; subract topblank + char height from maxheight.\n\tmov\t[bottomblank],bl\t\t; save off the number of blank rows on the bottom.\n\t; leaving this section:\n\t; dl is still the width of the character.\n\t; cl is the height of the top blank area.\n\n\tmov\tebx,OFFSET ColorXlat\t\t; setup ebx for xlat commands.\n\tmov\tdh,dl\t\t\t\t; save the width of the character to restore each loop.\n\n\tcmp\tcl,0\t\t\t\t; is there any blank rows on top?\n\tjz\t??draw_char\t\t\t; if not go and draw the real character.\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjnz\t??loop_top\t\t\t; if not go and write the color\n\n;----------------------------------------- skip Top blank area ----------------------------------------\n\t; this case, the top is transparrent, but we need to increase our dest pointer to correct row.\n\tmovzx\teax,cl\t\t\t\t; get number of rows into eax;\n\tmov\tecx,edx\t\t\t\t; save width since edx will be destroyed by mul.\n\tmul\t[bufferwidth]\t\t\t; multiply that by the width of the buffer.\n\tmov\tedx,ecx\t\t\t\t; restore the width\n\tadd\tedi,eax\t\t\t\t; update the pointer.\n\tjmp\tshort ??draw_char\t\t; now go draw the character.\n\n;----------------------------------------- fill Top blank area ----------------------------------------\n\t; edi was set a long time ago.\n\t; al is the translated color\n??loop_top:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_top\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tdec\tcl\t\t\t\t; decrement or row count\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tjz\t??draw_char\t\t\t; we are done here, go draw the character.\n\tjmp\tshort ??loop_top\t\t; go back to top of loop.\n\n\n;----------------------------------------- Draw character ----------------------------------------------\n??draw_char:\n\tmovzx\tecx,[charheight]\t\t; get the height of character to count down rows.\n\ttest\tecx,ecx\t\t\t\t; is there any data? (blank would not have any)\n\tjz\t??next_char\t\t\t; if no data, go on to next character.\n\n??while_data:\n\tlodsb\t\t\t\t\t; get byte value from font data\n\tmov\tah,al\t\t\t\t; save hinibble\n\tand\teax,0F00FH\t       \t\t; mask of low nibble in al hi nibble in ah.\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiplo\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiplo:\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjz\tshort ??nextrow\t\t\t; check if done with width of char\n\n\tmov\tal,ah\t\t\t\t; restore to get\n\t; test the time difference between looking up in a large table when shr al,4 is not done as\n\t; compared to using only a 16 byte table when using the shr al,4\n\t;shr\tal,4\t\t\t\t; shift the hi nibble down to low nibble\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiphi\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiphi:\n\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\tshort ??while_data\t\t; check if done with width of char\n\n??nextrow:\n\tadd\tedi,[nextdraw]\t\t\t; go to next line.\n\tdec\tecx\t\t\t\t; decrement the number of rows to go\n\tmov\tdh,dl\t\t\t\t; restore our column count for row.\n\tjnz\t??while_data\t\t\t; more data for character.\n\n\t; Now it is time to setup for clearing out the bottom of the character.\n\tmovzx\tecx,[bottomblank]\t\t; get amount on bottom that is blank\n\tcmp\tecx,0\t\t\t\t; if there is no blank bottom...\n\tjz\t??next_char\t\t\t; then skip to go to next character\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjz\t??next_char\t\t\t; skip the top black section to let the background through\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\n;----------------------------------------- Blank below character -----------------------------------\n??loop_bottom:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_bottom\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tdec\tcl\t\t\t\t; decrement or row count\n\tjz\t??next_char\t\t\t; we are done here, go to the next character.\n\tjmp\tshort ??loop_bottom\t\t; go back to top of loop.\n\n;----------------------------------- end of next_char (main) loop ------------------------------------\n;-------------------------------------------------------------------------------------------------\n\n\n;----------------------------------- special case line feeds ----------------------------------------\n\n??force_line_feed:\n\t; decrement pointer *string so that it will be back at same character\n\t; when it goes through the loop.\n\tmov\teax,[string]\t\t\t; get string pointer.\n\tdec\teax\t\t\t\t; decrement it to point to previos char\n\tmov\t[string],eax\t\t\t; save it back off.\n\txor\teax,eax\n\t; Now go into the line feed code.....\n\n??line_feed:\n\tmov\tbl,al\n\tmov\tedx,[y_pixel]\t\t\t; get the current y pixel value.\n\tmovzx\tecx,[maxheight]\t\t\t; get max height for later use.\n\tadd\tecx,[FontYSpacing]\n\tadd\tedx,ecx\t\t\t\t; add max height to y_pixel\n\tcmp\tedx,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we are outa here.\n\n\tmov\teax,[bufferwidth]      \t\t; get bytes to next line.\n\tmov\tedi,[curline]\t\t\t; get start of current line.\n\tmul\tecx\t\t\t\t; mult max height * next line.\n\n\tadd\tedi,eax\t\t\t\t; add adjustment to current line.\n\tadd\t[y_pixel],ecx\t\t\t; increment to our next y position.\n;;; DRD\n\tmov\t[curline],edi\t\t\t; save it off for next line_feed.\n\n\t; Move the cursor to either the left edge of the screen\n\t; or the left margin of the print position depending\n\t; on whether <CR> or <LF> was specified. <CR> = left margin\n\t; <LF> = left edge of screen\n\txor\teax,eax\n\tcmp\tbl,10\n\tje\t??lfeed\n\tmov\teax,[original_x]\n??lfeed:\n\tmov\t[x_pixel],eax\t\t\t; zero out x_pixel\n\n\tadd\tedi,eax\n;;; DRD\tmov\t[curline],edi\t\t\t; save it off for next line_feed.\n\tmov\t[startdraw],edi\t\t\t; save it off so we know where to draw next char.w\n\n\tjmp\t??next_char\n\n??overflow:\n\tmov\t[startdraw],0\t\t\t; Indicate that there is no valid next pos.\n??done:\n\tmov\teax,[startdraw]\t\t\t; return this so calling routine\n\tret\t\t\t\t\t; can figure out where to draw next.\n\n\tENDP\tBuffer_Print\n\n;***************************************************************************\n;* GET_FONT_PALETTE_PTR -- Returns a pointer to the 256 byte font palette  *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tvoid *Get_Font_Palette_Ptr(void);                          *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   08/18/1995 PWG : Created.                                             *\n;*=========================================================================*\n\n\tGLOBAL C\tGet_Font_Palette_Ptr:NEAR\n\tPROC\tGet_Font_Palette_Ptr C near\n\tmov\teax, OFFSET ColorXlat\n\tret\n\tENDP\tGet_Font_Palette_Ptr\n\n\nEND\n\nEND"
  },
  {
    "path": "WIN32LIB/EXAMPLE/DEFINES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 Example                          *\n *                                                                         *\n *                    File Name : DEFINES.H                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\n#define USER_TIMER_FREQ\t\t60\n"
  },
  {
    "path": "WIN32LIB/EXAMPLE/EXTERNS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 Example                          *\n *                                                                         *\n *                    File Name : EXTERNS.H                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\nextern char\tNoTimer;\nextern char\tNoKeyBoard;\n"
  },
  {
    "path": "WIN32LIB/EXAMPLE/FUNCTION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 Example                          *\n *                                                                         *\n *                    File Name : FUNCTION.H                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwlib32.h\"\n#include \"defines.h\"\n#include \"structs.h\"\n#include\t\"externs.h\"\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MAIN.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern WORD Main_Program(WORD argc, BYTE *argv[]);\n\n\n/*=========================================================================*/\n"
  },
  {
    "path": "WIN32LIB/EXAMPLE/GLOBALS.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 Examples                         *\n *                                                                         *\n *                    File Name : GLOBALS.CPP                              *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\nchar\tNoTimer;\nchar\tNoKeyBoard;\n"
  },
  {
    "path": "WIN32LIB/EXAMPLE/MAIN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : libtest                                  *\n *                                                                         *\n *                    File Name : LIBTEST.CPP                              *\n *                                                                         *\n *                   Programmer : Jeff Wilson                            \t*\n *                                                                         *\n *                   Start Date : April 27, 1994                           *\n *                                                                         *\n *                  Last Update : May 3, 1994   [BR]                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Main_Program -- user-defined main routine, called from startup.c      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include \"function.h\"\n\n\n/***************************************************************************\n * Main_Program -- user-defined main routine, called from startup.c        *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tWORD argc\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tUBYTE *argv[]\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tReturns: TRUE\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1994 BR : Created.                                              *\n *=========================================================================*/\n#pragma argsused\nWORD Main_Program(WORD argc, BYTE *argv[])\n{\t  \t\t\t     \n\treturn (TRUE);\t\t\t  \n}\n\n\n//////////////////////////////////// End of File /////////////////////////////////////\n"
  },
  {
    "path": "WIN32LIB/EXAMPLE/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .EXE makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 20, 1995  \t                   *\n#*                                                                         *\n#*                  Last Update : \t\t\t                   *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*                                                                         *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the executable program you're building \t   *\n#* PROJ_LIBS\t= Westwood libraries to link your EXE to \t           *\n#* OBJECTS\t= list of objects in your current working directory\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .xxx:\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS\n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n#---------------------------------------------------------------------------\n# PROJ_NAME = library name\n# PROJ_DIR = directory containing source & objects\n#---------------------------------------------------------------------------\nPROJ_NAME\t= TEST\nPROJ_DIR\t= $(%WWFLAT)\\example\\TEST\nLIB_DIR\t        = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t   \t&\n\tmain.obj\t\t&\n\tstartup.obj\t\t&\n\tglobals.obj\n\nPROJ_LIBS = \t\t\t&\n\t    wwflat32.lib\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t $(PROJ_DIR)\n.c:   \t $(PROJ_DIR)\n.cpp:\t $(PROJ_DIR)\n.h:   \t $(PROJ_DIR)\n.obj:\t $(PROJ_DIR)\n.lib:\t $(%WWFLAT)\\lib\n.exe:\t $(PROJ_DIR)\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n# If LIB & INCLUDE are already defined, they are used in addition to the\n# WWLIB32 lib & include; otherwise, they're constructed from\n# BCDIR\n#---------------------------------------------------------------------------\n\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND\n\t$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(PROJ_NAME).exe\n\n#---------------------------------------------------------------------------\n# Build the EXE\n#---------------------------------------------------------------------------\n$(PROJ_NAME).exe: $(OBJECTS)  $(PROJ_NAME).lnk $(PROJ_LIBS)\n\t $(LINK_CMD) $(LINK_CFG) system dos4g name $^@ @$(PROJ_NAME).lnk\n\n\n$(PROJ_LIBS):\n\techo updating base library $^@\n\tcd ..\n\twmake\n\tcd $(PROJ_DIR)\n\n\n$(PROJ_NAME).lnk : $(OBJECTS)\n       %create $^@\n       for %index in ($(OBJECTS))  do %append $^@ file %index\n       for %index in ($(PROJ_LIBS)) do %append $^@ library $(LIB_DIR)\\%index\n\n#**************************** End of makefile ******************************\n\n\n"
  },
  {
    "path": "WIN32LIB/EXAMPLE/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .EXE makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 20, 1995  \t                   *\n#*                                                                         *\n#*                  Last Update : \t\t\t                   *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*                                                                         *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the executable program you're building \t   *\n#* PROJ_LIBS\t= Westwood libraries to link your EXE to \t           *\n#* OBJECTS\t= list of objects in your current working directory\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .xxx:\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n#---------------------------------------------------------------------------\n# PROJ_NAME = library name\n# PROJ_DIR = directory containing source & objects\n#---------------------------------------------------------------------------\nPROJ_NAME\t= TEST\nPROJ_DIR\t= $(%WWFLAT)\\example\\TEST\nLIB_DIR\t        = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t   \t&\n\tmain.obj\t\t&\n\tstartup.obj\t\t&\n\tglobals.obj\n\nPROJ_LIBS = \t\t\t&\n\t    wwflat32.lib\n\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t $(PROJ_DIR)\n.c:   \t $(PROJ_DIR)\n.cpp:\t $(PROJ_DIR)\n.h:   \t $(PROJ_DIR)\n.obj:\t $(PROJ_DIR)\n.lib:\t $(%WWFLAT)\\lib\n.exe:\t $(PROJ_DIR)\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n# If LIB & INCLUDE are already defined, they are used in addition to the\n# WWLIB32 lib & include; otherwise, they're constructed from\n# BCDIR \n#---------------------------------------------------------------------------\n\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(PROJ_NAME).exe \n\n#---------------------------------------------------------------------------\n# Build the EXE\n#---------------------------------------------------------------------------\n$(PROJ_NAME).exe: $(OBJECTS)  $(PROJ_NAME).lnk $(PROJ_LIBS)\n\t $(LINK_CMD) $(LINK_CFG) system dos4g name $^@ @$(PROJ_NAME).lnk\n\n\n$(PROJ_LIBS):\t\t\n\techo updating base library $^@\n\tcd ..\n\twmake\n\tcd $(PROJ_DIR)\n\n\n$(PROJ_NAME).lnk : $(OBJECTS)\n       %create $^@\n       for %index in ($(OBJECTS))  do %append $^@ file %index\n       for %index in ($(PROJ_LIBS)) do %append $^@ library $(LIB_DIR)\\%index\n\n#**************************** End of makefile ******************************\n\n\n"
  },
  {
    "path": "WIN32LIB/EXAMPLE/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .EXE makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 20, 1995  \t                   *\n#*                                                                         *\n#*                  Last Update : \t\t\t                   *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*                                                                         *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the executable program you're building \t   *\n#* PROJ_LIBS\t= Westwood libraries to link your EXE to \t           *\n#* OBJECTS\t= list of objects in your current working directory\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .xxx:\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n#---------------------------------------------------------------------------\n# PROJ_NAME = library name\n# PROJ_DIR = directory containing source & objects\n#---------------------------------------------------------------------------\nPROJ_NAME\t= TEST\nPROJ_DIR\t= $(%WWFLAT)\\example\\TEST\nLIB_DIR\t        = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t   \t&\n\tmain.obj\t\t&\n\tstartup.obj\t\t&\n\tglobals.obj\n\nPROJ_LIBS = \t\t\t&\n\t    wwflat32.lib\n\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t $(PROJ_DIR)\n.c:   \t $(PROJ_DIR)\n.cpp:\t $(PROJ_DIR)\n.h:   \t $(PROJ_DIR)\n.obj:\t $(PROJ_DIR)\n.lib:\t $(%WWFLAT)\\lib\n.exe:\t $(PROJ_DIR)\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n# If LIB & INCLUDE are already defined, they are used in addition to the\n# WWLIB32 lib & include; otherwise, they're constructed from\n# BCDIR \n#---------------------------------------------------------------------------\n\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(PROJ_NAME).exe \n\n#---------------------------------------------------------------------------\n# Build the EXE\n#---------------------------------------------------------------------------\n$(PROJ_NAME).exe: $(OBJECTS)  $(PROJ_NAME).lnk $(PROJ_LIBS)\n\t $(LINK_CMD) $(LINK_CFG) system dos4g name $^@ @$(PROJ_NAME).lnk\n\n\n$(PROJ_LIBS):\t\t\n\techo updating base library $^@\n\tcd ..\n\twmake\n\tcd $(PROJ_DIR)\n\n\n$(PROJ_NAME).lnk : $(OBJECTS)\n       %create $^@\n       for %index in ($(OBJECTS))  do %append $^@ file %index\n       for %index in ($(PROJ_LIBS)) do %append $^@ library $(LIB_DIR)\\%index\n\n#**************************** End of makefile ******************************\n\n\n"
  },
  {
    "path": "WIN32LIB/EXAMPLE/STARTUP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library startup routine.\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : STARTUP.CPP                              *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : July 14, 1994                            *\n *                                                                         *\n *                  Last Update : August 1, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Prog_End -- Called to shutdown Westood's library.                     *\n *   main -- Programs main entry point.                                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include <stdio.h>\n#include <stdlib.h>\n\n#define\tGRAPHICS\t\tTRUE\nvoid *ShapeBuffer = NULL;\n\n\n/***************************************************************************\n * MAIN -- Programs main entry point.                                      *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/01/1994 SKB : Created.                                             *\n *=========================================================================*/\n#pragma argsused\nWORD main(WORD argc, BYTE *argv[])\n{\n\tvoid *fontptr;\n\n\t/*======================================================================*/\n\t/* Install page fault handle in case of fatal crash.\t\t\t\t\t\t   */\n\t/*======================================================================*/\n\t  Install_Page_Fault_Handle ();\n\n\t/*======================================================================*/\n\t/* Setup the monochrome monitor for testing.\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\n\tMonoEnabled = (Find_Argv(\"-MONO\") ? TRUE : FALSE);\n\tMono_Clear_Screen();\n\n\t/*======================================================================*/\n\t/* Initialize the file data table.\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tWWDOS_Init(200, NULL, NULL);\n\n\t/*======================================================================*/\n\t/* Initialize the system font.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n#if GRAPHICS\n\tfontptr = Load_Font(\"STD6P.FNT\");\n\tif (!fontptr)  {\n\t\tprintf(\"Unable to load font.\");\n\t\texit(1);\n\t}\n\tSet_Font(fontptr);\n#endif\n\n\t/*======================================================================*/\n\t/* Setup the timer system.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (Find_Argv(\"-NOTIME\"))  {\n\t\tNoTimer = TRUE;\n\t} else {\n\t\tInit_Timer_System(USER_TIMER_FREQ);\n\t\tNoTimer = FALSE;\n\t}\n\n\t/*======================================================================*/\n\t/* Get the initial graphic mode.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n#if GRAPHICS\n\t if ( Set_Video_Mode(MCGA_MODE) == FALSE ) \n\t {\n\t\tprintf(\"Unable to Set Graphic Mode\\n\");\n\t\texit ( 0 ) ;\n\t }\n#endif\n\n\n\t/*======================================================================*/\n\t/* Now we get a keyboard handler.\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (Find_Argv(\"-NOKEY\")) {\n\t\tNoKeyBoard = TRUE;\n\t} else {\n\t\tNoKeyBoard = FALSE;\n\t\tInstall_Keyboard_Interrupt(\tGet_RM_Keyboard_Address(),\tGet_RM_Keyboard_Size());\n\n\t\tShapeBuffer = Alloc(5000, MEM_NORMAL);\n\t\tSet_Shape_Buffer(ShapeBuffer, 5000);\n\t\tInstall_Mouse(20, 20, 320, 200);\n\t}\n\n\t/*======================================================================*/\n\t/* Give the game some variance.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\trandomize();\n\n\t/*======================================================================*/\n\t/* Call the user main program.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tMain_Program(argc, argv);\n\n\t/*======================================================================*/\n\t/* Exit gracefully.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tProg_End();\n\n\treturn(0);\n}\n\n\n\n/***************************************************************************\n * PROG_END -- Called to shutdown Westood's library.                       *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:  exit() should not be called until this has been called       *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/01/1994 SKB : Created.                                             *\n *=========================================================================*/\nVOID Prog_End(VOID)\n{\n\t\n\t/*======================================================================*/\n\t/* Get rid of the keyboard handler.\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (!NoKeyBoard) {\n\t\tRemove_Mouse();\n\t\tFree(ShapeBuffer);\n\t\tRemove_Keyboard_Interrupt();\n\t}\n\n\t/*======================================================================*/\n\t/* Get rid of the timer system.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (!NoTimer)  {\n\t\tRemove_Timer_System();\n\t}\n\n\t/*======================================================================*/\n\t/* Restore the Video mode.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n#if GRAPHICS\n\tSet_Video_Mode(RESET_MODE);\n#endif\n\n\t/*======================================================================*/\n\t/* Close down the file system.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tWWDOS_Shutdown();\n}\n"
  },
  {
    "path": "WIN32LIB/EXAMPLE/STRUCTS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 Examples                         *\n *                                                                         *\n *                    File Name : STRUCTS.H                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n"
  },
  {
    "path": "WIN32LIB/EXAMPLE/WWLIB32.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 User include file                *\n *                                                                         *\n *                    File Name : WWLIB32.H                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWLIB32_H\n#define WWLIB32_H\n\n#include <wwstd.h>\n\n#include <buffer.h>\n#include <descmgmt.h>\n#include <file.h>\n#include <font.h>\n#include <gbuffer.h>\n#include <vbuffer.h>\n#include <iff.h>\n#include <filepcx.h>\n#include <keyboard.h>\n#include <mcgaprim.h>\n#include <misc.h>\n#include <mono.h>\n#include <palette.h>\n#include <playcd.h>\n#include <shape.h>\n#include <timer.h>\n#include <video.h>\n#include <wsa.h>\n#include <wwmem.h>\n\n\n\n#endif // WWLIB32_H\n"
  },
  {
    "path": "WIN32LIB/FONT/FONT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\t\t\t\t\t\t/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : FONT.C                                   *\n *                                                                         *\n *                   Programmer : David Dettmer                            *\n *                                                                         *\n *                  Last Update : July 20, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Char_Pixel_Width -- Return pixel width of a character.\t\t\t\t\t\t*\n *   String_Pixel_Width -- Return pixel width of a string of characters.   *\n *   Get_Next_Text_Print_XY -- Calculates X and Y given ret value from Text_P*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"font.h\"\n#include <malloc.h>\n#include <dos.h>\n#include <fcntl.h>\n#include <io.h>\n#include <sys\\stat.h>\n#include <string.h>\n#include <wwstd.h>\n\n\n/***************************************************************************\n * CHAR_PIXEL_WIDTH -- Return pixel width of a character.\t\t\t\t\t\t*\n *                                                                         *\n *    Retreives the pixel width of a character from the font width block.\t*\n *                                                                         *\n * INPUT:      Character.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     Pixel width of a string of characters.                      *\n *                                                                         *\n * WARNINGS:   Set_Font must have been called first.                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/31/1992 DRD : Created.                                             *\n *   06/30/1994 SKB : Converted to 32 bit library.                         *\n *=========================================================================*/\nint __cdecl Char_Pixel_Width(char chr)\n{\n\tint\twidth;\n\n\twidth = (unsigned char)*(FontWidthBlockPtr + (unsigned char)chr) + FontXSpacing;\n\n\treturn(width);\n}\n\n\n/***************************************************************************\n * STRING_PIXEL_WIDTH -- Return pixel width of a string of characters.     *\n *                                                                         *\n *    Calculates the pixel width of a string of characters.  This uses     *\n *\t\tthe font width block for the widths.\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:      Pointer to string of characters.                            *\n *                                                                         *\n * OUTPUT:     Pixel width of a string of characters.                      *\n *                                                                         *\n * WARNINGS:   Set_Font must have been called first.                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/30/1992 DRD : Created.                                             *\n *   01/31/1992 DRD : Use Char_Pixel_Width.                                *\n *   06/30/1994 SKB : Converted to 32 bit library.                         *\n *=========================================================================*/\nunsigned int __cdecl String_Pixel_Width(char const *string)\n{\n\tWORD\twidth;\t\t\t\t// Working accumulator of string width.\n\tWORD\tlargest = 0;\t\t// Largest recorded width of the string.\n\n\tif (!string) return(0);\n\n\twidth = 0;\n\twhile (*string) {\n\t\tif (*string == '\\r') {\n\t\t\tstring++;\n\t\t\tlargest = MAX(largest, width);\n\t\t\twidth = 0;\n\t\t} else {\n\t\t\twidth += Char_Pixel_Width(*string++);\t// add each char's width\n\t\t}\n\t}\n\tlargest = MAX(largest, width);\n\treturn(largest);\n}\n\n\n\n/***************************************************************************\n * GET_NEXT_TEXT_PRINT_XY -- Calculates X and Y given ret value from Text_P*\n *                                                                         *\n *                                                                         *\n * INPUT:   VVPC& vp - viewport that was printed to.                       *\n *          unsigned long offset - offset that Text_Print returned.                *\n *          INT *x - x return value.                                       *\n *          INT *y - y return value.                                       *\n *                                                                         *\n * OUTPUT:  x and y are set.                                               *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/20/1994 SKB : Created.                                             *\n *=========================================================================*/\nVOID __cdecl Get_Next_Text_Print_XY(GraphicViewPortClass& gp, unsigned long offset, INT *x, INT *y)\n{\n\tINT\tbuffwidth;\n\n\tif (offset) {\n\t\tbuffwidth = gp.Get_Width() + gp.Get_XAdd();\n\t\toffset -= gp.Get_Offset();\n\t\t*x = offset % buffwidth;\n\t\t*y = offset / buffwidth;\n\t} else {\n\t\t*x = *y = 0;\n\t}\n}\n"
  },
  {
    "path": "WIN32LIB/FONT/FONT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Font and text print 32 bit library       *\n *                                                                         *\n *                    File Name : FONT.H                                   *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : June 27, 1994                            *\n *                                                                         *\n *                  Last Update : June 29, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   VVPC::Text_Print -- Text print into a virtual viewport.               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FONT_H\n#define FONT_H\n\n#ifndef GBUFFER_H\n#include <gbuffer.h>\n#endif\n\n\n//////////////////////////////////////// Defines //////////////////////////////////////////\n\n// defines for font header, offsets to block offsets\n\n#define FONTINFOBLOCK\t\t\t4\n#define FONTOFFSETBLOCK\t\t\t6\n#define FONTWIDTHBLOCK\t\t\t8\n#define FONTDATABLOCK\t\t\t10\n#define FONTHEIGHTBLOCK\t\t\t12\n\n// defines for font info block\n\n#define FONTINFOMAXHEIGHT\t\t4\n#define FONTINFOMAXWIDTH\t\t5\n\n//////////////////////////////////////// Prototypes //////////////////////////////////////////\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SET_FONT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid  * __cdecl Set_Font(void const *fontptr);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FONT.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Char_Pixel_Width(char chr);\nunsigned int __cdecl String_Pixel_Width(char const *string);\nvoid __cdecl Get_Next_Text_Print_XY(GraphicViewPortClass& vp, unsigned long offset, INT *x, INT *y);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOADFONT.CPP\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid * __cdecl Load_Font(char  const *name);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TEXTPRNT.ASM\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\nvoid __cdecl Set_Font_Palette_Range(void const *palette, INT start_idx, INT end_idx);\n\n\n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n\n\n\n\n\n//////////////////////////////////////// External varables ///////////////////////////////////////\nextern \"C\" int FontXSpacing;\nextern \"C\" int FontYSpacing;\nextern char FontWidth ;\nextern char FontHeight;\nextern char *FontWidthBlockPtr;\n\n\nextern \"C\" void const *FontPtr;\n\n\n\n\n#endif // FONT_H\n"
  },
  {
    "path": "WIN32LIB/FONT/LOADFONT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : LOADFONT.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : September 6, 1991                        *\n *                                                                         *\n *                  Last Update : June 27, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Load_Font -- Loads a font from disk.                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"font.h\"\n#include <file.h>\n#include <wwmem.h>\n#include <wwstd.h>\n\n#if(IBM)\n#include <fcntl.h>\n#include <io.h>\n\n#include <errno.h>\n\nint FontXSpacing = 0;\nint FontYSpacing = 0;\nvoid const *FontPtr = NULL;\nchar FontWidth  = 8;\nchar FontHeight = 8;\n\n// only font.c and set_font.c use the following\nchar *FontWidthBlockPtr = NULL;\n\n\n\n/***************************************************************************\n * LOAD_FONT -- Loads a font from disk.                                    *\n *                                                                         *\n *    This loads a font from disk.  This function must be called as a    \t*\n *    precursor to calling Set_Font().  You need only call this function \t*\n *    once per desired font at the beginning of your code, but AFTER     \t*\n *    Prog_Init() is called.                                             \t*\n *                                                                         *\n * INPUT:      name  - Pointer to font name to use (eg. \"topaz.font\")    \t*\n *                                                                       \t*\n *             fontsize - Size in points of the font loaded.             \t*\n *                                                                       \t*\n * OUTPUT:     Pointer to font data or NULL if unable to load.           \t*\n *                                                                       \t*\n * WARNINGS:   Some system memory is grabbed by this routine.            \t*\n *                                                                       \t*\n * HISTORY:                                                                *\n *   4/10/91    BS  : 2.0 compatibily                                     \t*\n *   6/09/91    JLB : IBM and Amiga compatability.                        \t*\n *   11/27/1991 JLB : Uses file I/O routines for disk access.              *\n *   01/29/1992 DRD : Modified to use new font format.                     *\n *   02/01/1992 DRD : Added font file verification.                        *\n *   06/29/1994 SKB : modified for 32 bit library                          *\n *=========================================================================*/\nvoid * __cdecl Load_Font(char const *name)\n{\n\tchar\tvalid;\n\tint\t\tfh;\t\t// DOS file handle for font file.\n\tunsigned short\tsize;\t\t// Size of the data in the file (-2);\n\tchar\t*ptr = NULL;\t\t// Pointer to newly loaded font.\n\n\n\n\tfh=Open_File(name,READ);\n\tif ( fh>=0 ){\n\t\tif ( Read_File(fh, (char *) &size, 2) != 2) return(NULL);\n\n\t\tptr = (char *) Alloc(size , MEM_NORMAL );\n\t\t*(short *)ptr = size;\n\t\tRead_File(fh, ptr + 2, size - 2);\n\t\tClose_File(fh);\n\t} else {\n\t\treturn ((void*)errno);\n\t}\n\n\n\n#ifdef cuts\n\tif (Find_File(name)) {\n\t\tfh = Open_File(name, READ);\n\t\tif (Read_File(fh, (char *) &size, 2) != 2) return(NULL);\n\n\t\tptr = (char *) Alloc(size, MEM_NORMAL);\n\t\t*(short *)ptr = size;\n\t\tRead_File(fh, ptr + 2, size - 2);\n\t\tClose_File(fh);\n\t} else {\n\t\treturn (NULL);\n\t}\n#endif\n\n\t//\n\t// verify that the file loaded is a valid font file.\n\t//\n\n\tvalid = FALSE;\n\tif (*(ptr + 2) == 0) {\t\t// no compression\n\t\tif (*(ptr + 3) == 5) {\t\t// currently only 5 data blocks are used.\n\t\t\tvalid = TRUE;\n\t\t}\n\t}\n\n\tif ( !valid ) {\n\t\treturn (NULL);\n\t}\n\n   return(ptr);\n}\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/FONT/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = font\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tfont.obj\t&\n\tloadfont.obj\t&\n\tset_font.obj\t&\n\tsetfpal.obj\t&\n\ttextprnt.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\tmkdir run\n\tcd run\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\run\\vcs.cfg\n\tupdate\n\tcd..\n\tmkdir art\n\tcd art\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\art\\vcs.cfg\n\tupdate\n\tcd..\n\twmake\n\tcd ..\n\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/FONT/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = font\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t\tfont.obj\t\t\t\\\n\t\t\t\tloadfont.obj\t\\\n\t\t\t\tset_font.obj\t\\\n\t\t\t\tsetfpal.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) \n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n -+font.obj\t\t\t&\n-+loadfont.obj\t\t&\n-+set_font.obj\t\t&\n-+setfpal.obj\t\t\n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/FONT/SETFPAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : 32 bit library Text Print                *\n;*                                                                         *\n;*                    File Name : TEXTPRNT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : July 2, 1994                             *\n;*                                                                         *\n;*                  Last Update : July 2, 1994   [SKB]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Text_Print -- Assembly text print routine.                            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nGLOBAL  C ColorXlat:BYTE\nGLOBAL\tC Set_Font_Palette_Range:NEAR\n\n\tCODESEG\n\n;***********************************************************\n; SET_FONT_PALETTE_RANGE\n;\n; VOID Set_Font_Palette_Range(VOID *palette, WORD start, WORD end);\n;\n; This routine changes the local Draw_Char color translation table\n; with the color numbers in palette.\n;\n; Bounds Checking: forces start and end to a range of 0-15\n;*\n\tPROC\tSet_Font_Palette_Range C near\n\tUSES\teax, ebx, ecx,edi,esi\n\tARG\tpalette:DWORD\n\tARG\tstart:DWORD\n\tARG\tendval:DWORD\n\n\tcld\n\n\tmov\tesi,[palette]\n\n\tmov\tebx,[start]\n\tand\tebx,0FH\t\t\t; value 0-15\n\n\tmov\tecx,[endval]\n\tand\tecx,0FH\t\t\t; value 0-15\n\n\tcmp\tecx,ebx\t\t\t; if end < start then exit\n\tjl\tshort ??exit\n\n\tsub\tecx,ebx\t\t\t; number of colors = end - start + 1\n\tinc\tecx\n\n\tmov\tedi,OFFSET ColorXlat\t; get start of xlat table\n\tadd\tedi,ebx\t\t\t; add starting offset\n\tshl\tebx,4\t\t\t; multiply start offset by 16\n\tadd\tebx,OFFSET ColorXlat\t; add start of xlat table\n\n; updates 0-15 for lonibble xlat\n; updates 0,16,32,...,240 for hinibble xlat\n\n??setpal:\n\tlodsb\t\t\t\t; get color number\n\tstosb\t\t\t\t; save color number for lonibble xlat\n\tmov\t[ebx],al\t\t; save color number for hinibble xlat\n\tadd\tebx,010H    \t\t; add 16 to index for hinibble offset\n\tdec\tecx\n\tjnz\t??setpal\n\n??exit:\n\tret\n\n\tENDP\tSet_Font_Palette_Range\n\n;***********************************************************\n\n\n;***********************************************************\n\n\tEND"
  },
  {
    "path": "WIN32LIB/FONT/SET_FONT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : SET_FONT.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : September 6, 1991                        *\n *                                                                         *\n *                  Last Update : June 29, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Set_Font -- Changes the default text printing font.                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"font.h\"\n#include <wwstd.h>\n\n\n\n/***************************************************************************\n * SET_FONT -- Changes the default text printing font.                     *\n *                                                                         *\n *    This routine will change the default text printing font for all      *\n *    text output.  It handles updating the system where necessary.        *\n *                                                                         *\n * INPUT:   fontptr  -- Pointer to the font to change to.                  *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the previous font.                   *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/06/1991 JLB : Created.                                             *\n *   09/17/1991 JLB : Fixed return value bug.                              *\n *   01/31/1992 DRD : Modified to use new font format.                     *\n *   06/29/1994 SKB : modified for 32 bit library                          *\n *=========================================================================*/\nvoid * __cdecl Set_Font(void const *fontptr)\n{\n\tvoid *oldfont;\n\tchar\tconst *blockptr;\n\n\toldfont = (void *) FontPtr;\n\n\tif (fontptr) {\n\t\tFontPtr    = (void *) fontptr;\n\n\t\t/*\n\t\t**\tInform the system about the new font.\n\t\t*/\n\n\t\tFontWidthBlockPtr = (char*)fontptr + *(unsigned short *)((char*)fontptr + FONTWIDTHBLOCK);\n\t\tblockptr  = (char*)fontptr + *(unsigned short *)((char*)fontptr + FONTINFOBLOCK);\n\t\tFontHeight = *(blockptr + FONTINFOMAXHEIGHT);\n\t\tFontWidth  = *(blockptr + FONTINFOMAXWIDTH);\n\t\t//Draw_Char_Setup();\n\n#if FALSE\n\t\tWindowLines = WinH / FontHeight;\n\t\tWindowWidth = WinW << 3;\n\t\tWindowColumns = WindowWidth / FontWidth;\n#endif\n\t}\n\n\treturn(oldfont);\n}\n"
  },
  {
    "path": "WIN32LIB/FONT/TEXTPRNT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : 32 bit library Text Print                *\n;*                                                                         *\n;*                    File Name : TEXTPRNT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : July 2, 1994                             *\n;*                                                                         *\n;*                  Last Update : July 2, 1994   [SKB]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Text_Print -- Assembly text print routine.                            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n\nGLOBAL\tFontPtr:DWORD\nGLOBAL\tText_Print:NEAR\n\n; The header of the font file looks like this:\n; \tUWORD\tFontLength;\t\t0\n; \tBYTE\tFontCompress;\t\t2\n;\tBYTE\tFontDataBlocks;\t\t3\n;\tUWORD\tInfoBlockOffset;\t4\n;\tUWORD\tOffsetBlockOffset;\t6\n;\tUWORD\tWidthBlockOffset;\t8\n;\tUWORD\tDataBlockOffset;\t10\n;\tUWORD\tHeightOffset;\t\t12\n; For this reason the following equates have these values:\nFONTINFOBLOCK\t\tEQU\t4\nFONTOFFSETBLOCK\t\tEQU\t6\nFONTWIDTHBLOCK\t\tEQU\t8\nFONTDATABLOCK\t\tEQU\t10\nFONTHEIGHTBLOCK\t\tEQU\t12\n\nFONTINFOMAXHEIGHT\tEQU\t4\nFONTINFOMAXWIDTH\tEQU\t5\n\nLOCALS ??\n\n\tDATASEG\n\nColorXlat\tDB\t000H,001H,002H,003H,004H,005H,006H,007H\n\t\tDB\t008H,009H,00AH,00BH,00CH,00DH,00EH,00FH\n\n\t\tDB\t001H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t002H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t003H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t004H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t005H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t006H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t007H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t008H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t009H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00AH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00BH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00CH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00DH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00EH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00FH\n\n\tCODESEG\n\n\n;***************************************************************************\n;* TEXT_PRINT -- Assembly text print routine.                              *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/28/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tText_Print C near\n\tUSES\tebx,ecx,edx,esi,edi\n\tARG\tvpselector:WORD\n\tARG\tvpoffset:DWORD\n\tARG\tvpwidth:DWORD\n\tARG\tvpheight:DWORD\n\tARG\tvpxadd:DWORD\n\tARG\tstring:DWORD\n\tARG\tx_pixel:DWORD\n\tARG\ty_pixel:DWORD\n\tARG\tfcolor:DWORD\n\tARG\tbcolor:DWORD\n\t\t\n\tLOCAL\tinfoblock:DWORD\t\t; pointer to info block\n\tLOCAL\toffsetblock:DWORD\t; pointer to offset block  (UWORD *)\n\tLOCAL\twidthblock:DWORD\t; pointer to width block   (BYTE  *)\n\tLOCAL\theightblock:DWORD\t; pointer to height block  (UWORD *)\n\n\tLOCAL\tcurline:DWORD\t\t; pointer to first column of current row.\n\tLOCAL\tbufferwidth:DWORD    \t; width of buffer (vpwidth + Xadd)\n\tLOCAL\tnextdraw:DWORD\t\t; bufferwidth - width of cur character.\n\tLOCAL\tstartdraw:DWORD\t\t; where next character will start being drawn.\n\n\tLOCAL\tchar:DWORD\t\t; current character value.\t\n\n\tLOCAL\tmaxheight:BYTE\t\t; max height of characters in font.\n\tLOCAL\tbottomblank:BYTE\t; amount of empty space below current character.\n\tLOCAL\tcharheight:BYTE\t\t; true height of current character.\n\n\n;-------------------------------- Where to draw -----------------------------------------------\n\t; Set up memory location to start drawing.\n\tmovzx\teax,[vpselector]\n\tmov\tes,ax\t\t\t; Set up selector to write to.\n\n\tmov\teax,[vpwidth]\t\t; get the width of the viewport\n\tadd\teax,[vpxadd]\t\t; add amount to add to get to left edge of next line.\t\n\tmov\t[bufferwidth],eax     \t; save it off for later use.\n\n\tmul\t[y_pixel]\t\t; multiply rowsize * y_pixel start.\n\tmov\tedi,[vpoffset]\t\t; get start of the viewport\n\tadd\tedi,eax\t\t\t; add x,y position to start of vp to get starting row address.\t\n\tmov\t[curline],edi\t\t; save 0,y address for line feed stuff.\n\tadd\tedi,[x_pixel]\t\t; add to get starting column in starting row.\n\tmov\t[startdraw],edi\t\t; save it off.\n\n\n;-------------------------------- Create block pointers ----------------------------------------\n\t; Get the pointer to the font.\n\t; We could check for NULL but why waste the time.\n\t; It is up to programmer to make sure it is set.\n\tmov\tesi,[FontPtr]\t\t; Get the font pointer\n\n\t; Set up some pointers to the different memory blocks.\n\t; esi (FontPtr) is added to each to get the true address of each block.\n\t; Many registers are used for P5 optimizations.\n\t; ebx is used for InfoBlock which is then used in the next section.\n\tmovzx\teax,[WORD PTR esi+FONTOFFSETBLOCK]\t; get offset to offset block\n\tmovzx\tebx,[WORD PTR esi+FONTINFOBLOCK]      \t; get offset to info block (must be ebx for height test)\n\tmovzx\tecx,[WORD PTR esi+FONTWIDTHBLOCK] \t; get offset to width block\n\tmovzx\tedx,[WORD PTR esi+FONTHEIGHTBLOCK]\t; get offset to height block\n\n\tadd\teax,esi\t\t\t\t; add offset of FontPtr to offset block  \n\tadd\tebx,esi\t\t\t\t; add offset of FontPtr to info block \n\tadd\tecx,esi\t\t\t\t; add offset of FontPtr to width block\n\tadd\tedx,esi\t\t\t\t; add offset of FontPtr to height block\n\n\tmov\t[offsetblock],eax\t\t; save offset to offset block\n\tmov\t[infoblock],ebx\t\t\t; save offset to info block\n\tmov\t[widthblock],ecx   \t\t; save offset to width block\n\tmov\t[heightblock],edx\t\t; save offset to height block\n\n;------------------------------------------ Test for fit ----------------------------------------------\n\t; Test to make sure the height of the max character will fit on this line\n\t; and and not fall out of the viewport.\n\t; remember we set ebx to FONTINFOBLOCK above.\n\tmovzx\teax,[BYTE PTR ebx + FONTINFOMAXHEIGHT]; get the max height in font.\n\tmov\t[maxheight],al\t\t\t; save it for later use.\n\tadd\teax,[y_pixel]\t\t\t; add current y_value.\n\tcmp\teax,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we're outa here.\n\n\tmov\t[y_pixel],eax\t\t\t; save for next line feed. y value for next line.\n\n\tcld\t\t\t\t\t; Make sure we are always forward copying.\n\n;------------------------ Set palette foreground and background ----------------------------------\n\tmov\teax,[fcolor]\t\t; foreground color\n\tmov\t[ColorXlat+1],al\n\tmov\t[ColorXlat+16],al\n\n\tmov\teax,[bcolor]\t\t; background color\n\tmov\t[ColorXlat],al\n\n;-------------------------------------------------------------------------------------------------\n;----------------------------------------- Main loop ----------------------------------------------\n\t; Now we go into the main loop of reading each character in the string and doing\n\t; something with it.\n??next_char:\n\t; while (*string++)\n\txor\teax,eax\t\t\t\t; zero out since we will just load al.\t\n\tmov\tesi,[string]\t\t\t; get address on next character.\t\n\tlodsb\t\t\t\t\t; load the character into al.\n\ttest\teax,0FFH\t\t\t; test to see if character is a NULL\n\tjz\t??done\t\t\t\t; character is NULL, get outa here.\n\n\tmov\tedi,[startdraw]\t\t\t; Load the starting address.\n\n\tmov\t[string],esi\t\t\t; save index into string. (incremented by lodsb)\t\n\t\n\tcmp\teax,13\t\t\t\t; is the character a line feed?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\n\tmov\t[char],eax\t\t\t; save the character off for later reference.\n\tmov\tebx,eax\t\t\t\t; save it in ebx for later use also.\n\n\tadd\teax,[widthblock]\t\t; figure address of width of character.\n\tmov\tecx,[x_pixel]\t\t\t; get current x_pixel.\n\tmovzx\tedx,[BYTE PTR eax]\t \t; get the width of the character in dl.\n\tadd\tecx,edx\t\t\t\t; add width of char to current x_pixel.\n\tadd\t[startdraw],edx\t\t\t; save start draw for next character.\n\n\tcmp\tecx,[vpwidth]\t\t\t; is the pixel greater then the vp width?\n\tjg\t??force_line_feed\t\t; if so, force a line feed.\n\n\tmov\t[x_pixel],ecx\t\t\t; save value of start of next character.\n\tmov\tecx,[bufferwidth]\t\t; get amount to next y same x (one row down)\n\tsub\tecx,edx\t\t\t\t; take the current width off.\n\tmov\t[nextdraw],ecx\t\t\t; save it to add to edi when done with a row.\n\n\t; At this point we got the character. It is now time to find out specifics\n\t; about drawing the darn thing.\n\t; ebx = char so they can be used as an indexes.\n\t; edx = width of character for loop later.\n\n\t; get offset of data for character into esi.\n\tshl\tebx,1\t\t\t\t; mult by 2 to later use as a WORD index.\n\tmov\tesi,[offsetblock]\t\t; get pointer to begining of offset block.\n\tadd\tesi,ebx\t\t\t\t; index into offset block.\t\n\tmovzx\tesi,[WORD PTR esi]\t\t; get true offset into data block from FontPtr.\n\tadd\tesi,[FontPtr]\t\t\t; Now add FontPtr address to get true address.\n\n\t; Get top and bottom blank sizes and the true height of the character.\n\tadd\tebx,[heightblock]\t\t; point ebx to element in height array.\n\tmov\tal,[ebx+1]\t\t\t; load the data height into dl.\n\tmov\tcl,[ebx]\t\t\t; load the first data row into cl.\n\tmov\tbl,[maxheight]\t\t\t; get the max height of characters.\n\tmov\t[charheight],al\t\t\t; get number of rows with data.\n\tadd\tal,cl\t\t\t\t; add the two heights.\n\tsub\tbl,al\t\t\t\t; subract topblank + char height from maxheight.\n\tmov\t[bottomblank],bl\t\t; save off the number of blank rows on the bottom.\n\t; leaving this section:\n\t; dl is still the width of the character.\n\t; cl is the height of the top blank area.\n\n\tmov\tebx,OFFSET ColorXlat\t\t; setup ebx for xlat commands.\n\tmov\tdh,dl\t\t\t\t; save the width of the character to restore each loop.\n\n\tcmp\tcl,0\t\t\t\t; is there any blank rows on top?\n\tjz\t??draw_char\t\t\t; if not go and draw the real character.\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjnz\t??loop_top\t\t\t; if not go and write the color\n\n;----------------------------------------- skip Top blank area ----------------------------------------\n\t; this case, the top is transparrent, but we need to increase our dest pointer to correct row.\n\tmovzx\teax,cl\t\t\t\t; get number of rows into eax;\n\tmov\tecx,edx\t\t\t\t; save width since edx will be destroyed by mul.\n\tmul\t[bufferwidth]\t\t\t; multiply that by the width of the buffer.\n\tmov\tedx,ecx\t\t\t\t; restore the width\n\tadd\tedi,eax\t\t\t\t; update the pointer.\t\n\tjmp\tshort ??draw_char\t\t; now go draw the character.\n\n;----------------------------------------- fill Top blank area ----------------------------------------\n\t; edi was set a long time ago.\n\t; al is the translated color\n??loop_top:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_top\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tdec\tcl\t\t\t\t; decrement or row count\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tjz\t??draw_char\t\t\t; we are done here, go draw the character.\n\tjmp\tshort ??loop_top\t\t; go back to top of loop.\n\n\n;----------------------------------------- Draw character ----------------------------------------------\n??draw_char:\n\tmovzx\tecx,[charheight]\t\t; get the height of character to count down rows.\n\ttest\tecx,ecx\t\t\t\t; is there any data? (blank would not have any)\n\tjz\t??next_char\t\t\t; if no data, go on to next character.\t\n\n??while_data:\n\tlodsb\t\t\t\t\t; get byte value from font data\n\tmov\tah,al\t\t\t\t; save hinibble\n\tand\teax,0F00FH\t       \t\t; mask of low nibble in al hi nibble in ah.\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiplo\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiplo:\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjz\tshort ??nextrow\t\t\t; check if done with width of char\n\n\tmov\tal,ah\t\t\t\t; restore to get\n\t; test the time difference between looking up in a large table when shr al,4 is not done as\n\t; compared to using only a 16 byte table when using the shr al,4\n\t;shr\tal,4\t\t\t\t; shift the hi nibble down to low nibble\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiphi\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiphi:\n\t\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\tshort ??while_data\t\t; check if done with width of char\n\n??nextrow:\n\tadd\tedi,[nextdraw]\t\t\t; go to next line.\n\tdec\tecx\t\t\t\t; decrement the number of rows to go\n\tmov\tdh,dl\t\t\t\t; restore our column count for row.\n\tjnz\t??while_data\t\t\t; more data for character.\n\n\t; Now it is time to setup for clearing out the bottom of the character.\n\tmovzx\tecx,[bottomblank]\t\t; get amount on bottom that is blank\n\tcmp\tecx,0\t\t\t\t; if there is no blank bottom...\n\tjz\t??next_char\t\t\t; then skip to go to next character\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjz\t??next_char\t\t\t; skip the top black section to let the background through\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\n;----------------------------------------- Blank below character -----------------------------------\n??loop_bottom:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_bottom\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tdec\tcl\t\t\t\t; decrement or row count\n\tjz\t??next_char\t\t\t; we are done here, go to the next character.\n\tjmp\tshort ??loop_bottom\t\t; go back to top of loop.\n\n;----------------------------------- end of next_char (main) loop ------------------------------------\n;-------------------------------------------------------------------------------------------------\n\n\n;----------------------------------- special case line feeds ----------------------------------------\n\n??force_line_feed:\t\n\t; decrement pointer *string so that it will be back at same character\n\t; when it goes through the loop.\n\tmov\teax,[string]\t\t\t; get string pointer.\n\tdec\teax\t\t\t\t; decrement it to point to previos char\n\tmov\t[string],eax\t\t\t; save it back off.\n\t; Now go into the line feed code.....\n\n??line_feed:\n\tmov\tedx,[y_pixel]\t\t\t; get the current y pixel value.\n\tmovzx\tecx,[maxheight]\t\t\t; get max height for later use.\n\tadd\tedx,ecx\t\t\t\t; add max height to y_pixel\n\tcmp\tedx,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we are outa here.\n\n\tmov\teax,[bufferwidth]      \t\t; get bytes to next line.\n\tmov\tedi,[curline]\t\t\t; get start of current line.\t\n\tmul\tecx\t\t\t\t; mult max height * next line.\t\n\n\tadd\tedi,eax\t\t\t\t; add adjustment to current line.\n\tadd\t[y_pixel],ecx\t\t\t; increment to our next y position.\n\tmov\t[curline],edi\t\t\t; save it off for next line_feed.\n\tmov\t[startdraw],edi\t\t\t; save it off so we know where to draw next char.w\n\n\tmov\t[x_pixel],0\t\t\t; zero out x_pixel\n\n\tjmp\t??next_char\n\n??overflow:\n\tmov\t[startdraw],0\t\t\t; Indicate that there is no valid next pos.\n??done:\n\tmov\teax,[startdraw]\t\t\t; return this so calling routine\n\tret\t\t\t\t\t; can figure out where to draw next.\n\t\t\n\tENDP\tText_Print\n\n\n\n;***********************************************************\n\n\tEND\n"
  },
  {
    "path": "WIN32LIB/IFF/FILEPCX.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : iff                                      *\n;*                                                                         *\n;*                    File Name : FILEPCX.H                                *\n;*                                                                         *\n;*                   Programmer : Julio R. Jerez                           *\n;*                                                                         *\n;*                   Start Date : May 2, 1995                              *\n;*                                                                         *\n;*                  Last Update : May 2, 1995   [JRJ]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* GraphicBufferClass* Read_PCX_File (char* name, BYTE* palette,void *buff, long size);\n;* GraphicBufferClass* Read_PCX_File (char* name, BYTE* palette, BufferClass& Buff); \n;* int Write_PCX_File (char* name, GraphicViewPortClass& pic, BYTE* palette );*\n;*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n#include <gbuffer.h>\n#include <string.h>\n#include <buffer.h>\n#include\t<file.h>\n\n#ifndef PCX_H\n#define PCX_H\n\n\ntypedef\tstruct {\n\t\t\t\t\t\t  char\tred ;\n\t\t\t\t\t\t  char\tgreen ;\n\t\t\t\t\t\t  char\tblue ;\n\t\t\t\t\t} RGB ;\n\ntypedef\tstruct\t{\n\t\t\t\t\t\t  char      id ;\n\t\t\t\t\t\t  char\t   version ;\n\t\t\t\t\t\t  char\t   encoding ;\n\t\t\t\t\t\t  char\t   pixelsize ;\n\t\t\t\t\t\t  short \t   x ;\n\t\t\t\t\t\t  short\t\ty ;\n\t\t\t\t\t\t  short     width ;\n\t\t\t\t\t\t  short\t\theight ;\n\t\t\t\t\t\t  short \t   xres ;\n\t\t\t\t\t\t  short\t\tyres ;\n\t\t\t\t\t\t  RGB       ega_palette [ 16 ] ;\n\t\t\t\t\t\t  char\t   nothing ;\n\t\t\t\t\t\t  char      color_planes ;\n\t\t\t\t\t\t  short \t\tbyte_per_line ;\n\t\t\t\t\t\t  short \t \tpalette_type ;\n\t\t\t\t\t\t  char\t   filler [ 58 ] ;\n\t\t\t\t\t\t} PCX_HEADER ;\n\nGraphicBufferClass* Read_PCX_File (char* name, char* palette= NULL,void *buff=NULL, long size=0);\nGraphicBufferClass* Read_PCX_File (char* name, BufferClass& Buff,char* palette= NULL) ;\nint Write_PCX_File (char* name, GraphicViewPortClass& pic, unsigned char* palette );\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/IFF/IFF.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : IFF.C                                    *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : May 16, 1991                             *\n *                                                                         *\n *                  Last Update : April 19, 1994   [SKB]                   *\n *                                                                         *\n *                                                                         *\n * IFF reader code designed for loading pictures (ILBM or PBM).            *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Close_Iff_File -- Closes an IFF file handle.                          *\n *   Get_Iff_Chunk_Size -- Get the size of the given IFF chunk.            *\n *   Open_Iff_File -- Opens an IFF file for reading.                       *\n *   Read_Iff_Chunk -- Reads a chunk from an IFF file.                     *\n *   Write_Iff_Chunk -- Writes an IFF chuck out.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"iff.h\"\n#include \"file.h\"\n\n#define ID_FORM\t\t\tMAKE_ID('F','O','R','M')\n\n#ifdef MIN\n#undef MIN\n#endif\n\n/***************************************************************************\n * OPEN_IFF_FILE -- Opens an IFF file for reading.                         *\n *                                                                         *\n *    This function will open an IFF file for reading.  It will perform    *\n *    a the simple validity test of checking the first four bytes to make  *\n *    sure they are \"FORM\".  The value returned is the filehandle of the   *\n *    opened file.                                                         *\n *                                                                         *\n * INPUT:   filename - ASCII name of the IFF file to be opened.            *\n *                                                                         *\n * OUTPUT:  Returns the filehandle.  If there is an error or the file      *\n *          is not an IFF FORM then -1 will be returned.                   *\n *                                                                         *\n * WARNINGS:   You are responsible for error handling if this function     *\n *             returns -1 (not an IFF file).                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1991 JLB : Created.                                             *\n *   04/19/1994 SKB : Update to 32 bit library.                            *\n *=========================================================================*/\nint __cdecl Open_Iff_File(char const *filename)\n{\n\tint\tfh;\t\t// File handle.\n\tlong\ttype;\t\t// IFF file type.\n\n\n\t/* We want to be able to open the file for READ | WRITE, but we do not\n\t   want the Open_File to create it.  So check to see if it exists before\n\t\tthe Open_File */\n\n//\tfh = Open_File(filename, READ);\t\t// Open the source file for READ\n//\tClose_File(fh);\n\n\t//fh = Open_File(filename, READ | WRITE);\t// Open the source file again\n\tfh = Open_File(filename, READ);\t// Open the source file again\n\n\t//\tValidate that it is a FORM type.\n\n\tRead_File(fh, &type, 4L);\n\n\tif (type == ID_FORM) {\n\n\t\t//\tThe file is valid (so far).  Position the read so that the actual\n\t\t//\tIFF file type code can be read.\n\n\t\tSeek_File(fh, 4L, SEEK_CUR);\t\t// Skip the filesize bytes.\n\n\t} else {\n\n\t\t// This is NOT an IFF file.  Close the source file and return with\n\t\t//\tthe error code.\n\t\tClose_File(fh);\n\t\tfh = WW_ERROR;\n\t}\n\treturn fh;\n}\n\n\n/***************************************************************************\n * CLOSE_IFF_FILE -- Closes an IFF file handle.                            *\n *                                                                         *\n *    The routine will close the file that was opened with the             *\n *    Open_Iff_File() function.                                            *\n *                                                                         *\n * INPUT:   fh - File handle that was returned from Open_Iff_File().       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1991 JLB : Created.                                             *\n *   04/19/1994 SKB : Update to 32 bit library.                            *\n *=========================================================================*/\nvoid __cdecl Close_Iff_File(int fh)\n{\n\tif (fh != WW_ERROR) Close_File(fh);\n}\n\n\n/***************************************************************************\n * GET_IFF_CHUNK_SIZE -- Get the size of the given IFF chunk.              *\n *                                                                         *\n * INPUT:      int file handle to open IFF file, long id to get size of   *\n *                                                                         *\n * OUTPUT:     long size of the chunk or 0L if it was not found            *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/03/1991  CY : Created.                                             *\n *   04/19/1994 SKB : Update to 32 bit library.                            *\n *=========================================================================*/\nunsigned long __cdecl Get_Iff_Chunk_Size(int fh, long id)\n{\n\tlong\tform;\t\t\t\t\t// Chunk iff form name.\n\tlong\tchunksize;\t\t\t// Size of the chunk.\n\tchar\tfirst_iteration;\t// Check once the current chunk name\n\n\n\tfirst_iteration = TRUE;\n\n\tfor (;;) {\n\t\tif (Read_File(fh, &form, 4L) != 4L && !first_iteration) break;\n\n\n\t\tif (Read_File(fh, (char *) &chunksize, 4L) != 4L && !first_iteration) break;\n\n#if(IBM)\n\t\tchunksize = Reverse_Long(chunksize);\n#endif\n\n\t\tif (id == form) {\n\t\t\tSeek_File(fh, -8L, SEEK_CUR);\t\t\t// Seek back to the start of\n\t\t\treturn(chunksize);\t\t\t\t\t\t// the chunk & return size\n\t\t} else {\n\n\t\t\tif (first_iteration) {\n\t\t\t\tSeek_File(fh, 12L, SEEK_SET);\t\t// Start at beginning of file.\n\t\t\t\tfirst_iteration = FALSE;\t\t\t// Don't do this again\n\t\t\t} else {\n\n\t\t\t\t/* Otherwise, go to the next chunk in the file */\n\n\t\t\t\tchunksize = (chunksize + 1) & 0xFFFFFFFEL;\n\t\t\t\tSeek_File(fh, chunksize, SEEK_CUR);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(0L);\n}\n\n\n/***************************************************************************\n * READ_IFF_CHUNK -- Reads a chunk from an IFF file.                       *\n *                                                                         *\n *    Once an IFF file is opened, various chunks must be read from it.     *\n *    This routine will search through the IFF file and load in the        *\n *    specified chunk.  It will scan through the entire file when          *\n *    searching for the chunk.  It will load the FIRST chunk of the given  *\n *    type.                                                                *\n *                                                                         *\n * INPUT:   fh       - File handle of IFF file.                            *\n *                                                                         *\n *          id       - Chunk ID code.                                      *\n *                                                                         *\n *          buffer   - Pointer to buffer to load the chunk.                *\n *                                                                         *\n *          maxsize  - Maximum data bytes to read.                         *\n *                                                                         *\n * OUTPUT:     Returns with the number of bytes read from the chunk.       *\n *             If 0 is returned, this indicates that the chunk wasn't      *\n *             found.                                                      *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1991 JLB : Created.                                             *\n *   04/19/1994 SKB : Update to 32 bit library.                            *\n *=========================================================================*/\nunsigned long __cdecl Read_Iff_Chunk(int fh, long id, void *buffer, unsigned long maxsize)\n{\n\tlong\tform;\t\t\t\t\t// Chunk iff form name.\n\tunsigned long\tchunksize;\t\t\t// Size of the chunk.\n\tchar\tfirst_iteration;\t// Check once the current chunk name\n\n\tfirst_iteration = TRUE;\n\n\tfor (;;) {\n\t\tif (Read_File(fh, &form, 4L) != 4L && !first_iteration) break;\n\n\t\tif (Read_File(fh, (char *) &chunksize, 4L) != 4L && !first_iteration) break;\n\n#if(IBM)\n\t\tchunksize = Reverse_Long(chunksize);\n#endif\n\n\t\tif (id == form) {\n\n\t\t\tmaxsize = MIN(maxsize, chunksize);\n\t\t\tRead_File(fh, buffer, maxsize);\t\t// Read the buffer.\n\n\t\t\tchunksize = (chunksize + 1) & 0xFFFFFFFEL;\n\t\t\tif (maxsize < chunksize) {\n\t\t\t\tSeek_File(fh, chunksize - maxsize, SEEK_CUR);\n\t\t\t}\n\t\t\treturn(maxsize);\n\t\t} else {\n\n\t\t\tif (first_iteration) {\n\t\t\t\tSeek_File(fh, 12L, SEEK_SET);\t\t// Start at beginning of file.\n\t\t\t\tfirst_iteration = FALSE;\t\t\t// Don't do this again\n\n\t\t\t} else {\n\n\t\t\t\t/* Otherwise, go to the next chunk in the file */\n\n\t\t\t\tchunksize = (chunksize + 1) & 0xFFFFFFFEL;\n\t\t\t\tSeek_File(fh, chunksize, SEEK_CUR);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(0L);\n}\n\n\n\n/***************************************************************************\n * WRITE_IFF_CHUNK -- Writes an IFF chuck out.                             *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid __cdecl Write_Iff_Chunk(int file, long id, void *buffer, long length)\n{\n\tlong\tpos;\t\t// Current position in the IFF file.\n\tlong\toldpos;\t// Record of start of chunk offset.\n\tlong\tendpos;\t// end of file offset before we write our data\n\tlong\tvalue;\n\tBOOL\todd;\t\t// Is length odd?\n\tchar\tpad = 0;\t// Optional padding byte for even sized chunks.\n\n\t/*\n\t** Get the current end of file (before we write more data to the file)\n\t*/\n\tpos \t = Seek_File (file, 0L, SEEK_CUR);\n\tendpos = Seek_File (file, 0L, SEEK_END);\n\tSeek_File (file, pos, SEEK_SET);\n\n\tif (length) {\n\t\tvalue = id;\n\t\todd = (short)length & 0x01;\n\n\t\tWrite_File(file, &value, 4L);\n\t\toldpos = Seek_File(file, 0L, SEEK_CUR);\n\t\tWrite_File(file, &value, 4L);\n\t\tWrite_File(file, buffer, length);\n\t\tpos = Seek_File(file, 0L, SEEK_CUR);\n\t\tif (odd) {\n\t\t\tWrite_File(file, &pad, 1L);\n\t\t}\n\n\t\t/*\n\t\t**\tUpdate the chunk size long.\n\t\t*/\n\t\tSeek_File(file, oldpos, SEEK_SET);\n\t\tvalue = IFFize_LONG((pos - oldpos)-4);\n\t\tWrite_File(file, &value, 4L);\n\n\t\t/*\n\t\t**\tUpdate the file size LONG. if we are not just overwriting existing data\n\t\t*/\n\t\t// (MCC)\n\t\tif ( endpos < pos ) {\n\t\t\tSeek_File(file, 4L, SEEK_SET);\n\t\t\tvalue = IFFize_LONG((pos+odd) - 8);\n\t\t\tWrite_File(file, &value, 4L);\n\t\t}\n\n\t\t/*\n\t\t**\tReturn to end of file.\n\t\t*/\n\t\tSeek_File(file, 0L, SEEK_END);\n\t}\n}\n\n\n"
  },
  {
    "path": "WIN32LIB/IFF/IFF.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the FILEIO Library               *\n *                                                                         *\n *                    File Name : IFF.H                                    *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 20, 1994                           *\n *                                                                         *\n *                  Last Update : April 20, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef IFF_H\n#define IFF_H\n\n#ifndef GBUFFER_H\n#include <gbuffer.h>\n#endif\n\n#ifndef MISC_H\n#include <misc.h>\t\t// This is needed fro Reverse_WORD and _LONG\n#endif\n\n#ifndef MEMFLAGS_H\n#include <memflag.h>\t// This is needed for MemoryFlagType.\n#endif\n\n#define LZW_SUPPORTED\t\t\tFALSE\n\n/*=========================================================================*/\n/* Iff and Load Picture system defines and enumerations\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#define \tMAKE_ID(a,b,c,d)\t\t\t((long) ((long) d << 24) | ((long) c << 16) | ((long) b <<  8) | (long)(a))\n#define\tIFFize_WORD(a)\t\t\tReverse_Word(a)\n#define\tIFFize_LONG(a)\t\t\tReverse_Long(a)\n\n\n//lint -strong(AJX,PicturePlaneType)\ntypedef enum {\n\tBM_AMIGA,\t// Bit plane format (8K per bitplane).\n\tBM_MCGA,\t\t// Byte per pixel format (64K).\n\n\tBM_DEFAULT=BM_MCGA\t// Default picture format.\n} PicturePlaneType;\n\n/*\n**\tThis is the compression type code.  This value is used in the compressed\n**\tfile header to indicate the method of compression used.  Note that the\n**\tLZW method may not be supported.\n*/\n//lint -strong(AJX,CompressionType)\ntypedef enum {\n\tNOCOMPRESS,\t\t// No compression (raw data).\n\tLZW12,\t\t\t// LZW 12 bit codes.\n\tLZW14,\t\t\t// LZW 14 bit codes.\n\tHORIZONTAL,\t\t// Run length encoding (RLE).\n\tLCW\t\t\t\t// Westwood proprietary compression.\n} CompressionType;\n\n/*\n**\tCompressed blocks of data must start with this header structure.\n**\tNote that disk based compressed files have an additional two\n**\tleading bytes that indicate the size of the entire file.\n*/\n//lint -strong(AJX,CompHeaderType)\ntypedef struct {\n\tchar\tMethod;\t\t// Compression method (CompressionType).\n\tchar\tpad;\t\t\t// Reserved pad byte (always 0).\n\tlong\tSize;\t\t\t// Size of the uncompressed data.\n\tshort\tSkip;\t\t\t// Number of bytes to skip before data.\n} CompHeaderType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: IFF.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Open_Iff_File(char const *filename);\nvoid __cdecl Close_Iff_File(int fh);\nunsigned long __cdecl Get_Iff_Chunk_Size(int fh, long id);\nunsigned long __cdecl Read_Iff_Chunk(int fh, long id, void *buffer, unsigned long maxsize);\nvoid __cdecl Write_Iff_Chunk(int file, long id, void *buffer, long length);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOADPICT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Load_Picture(char const *filename, BufferClass& scratchbuf, BufferClass& destbuf, unsigned char *palette=NULL, PicturePlaneType format=BM_DEFAULT);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOAD.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nunsigned long __cdecl Load_Data(char const *name, void *ptr, unsigned long size);\nunsigned long __cdecl Write_Data(char const *name, void *ptr, unsigned long size);\nvoid * __cdecl Load_Alloc_Data(char const *name, MemoryFlagType flags);\nunsigned long __cdecl Load_Uncompress(char const *file, BufferClass& uncomp_buff, BufferClass& dest_buff, void *reserved_data=NULL);\nunsigned long __cdecl Uncompress_Data(void const *src, void *dst);\nvoid __cdecl Set_Uncomp_Buffer(int buffer_segment, int size_of_buffer);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WRITELBM.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nPUBLIC BOOL Write_LBM_File(int lbmhandle, BufferClass& buff, int bitplanes, unsigned char *palette);\n\n\n\n/*========================= Assembly Functions ============================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*=========================================================================*/\n/* The following prototypes are for the file: PACK2PLN.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern void __cdecl Pack_2_Plane(void *buffer, void * pageptr, int planebit);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LCWCOMP.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern unsigned long __cdecl LCW_Compress(void *source, void *dest, unsigned long length);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LCWUNCMP.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern unsigned long __cdecl LCW_Uncompress(void *source, void *dest, unsigned long length);\n\n#ifdef __cplusplus\n}\n#endif\n/*=========================================================================*/\n\n\n\n#endif //IFF_H\n"
  },
  {
    "path": "WIN32LIB/IFF/LCWCOMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/misc/rcs/lcwcomp.asm 1.1 1994/04/11 15:31:10 jeff_wilson Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library routine                          *\n;*                                                                         *\n;*                    File Name : COMPRESS.ASM                             *\n;*                                                                         *\n;*                   Programmer : Louis Castle                             *\n;*                                                                         *\n;*                  Last Update : 20 August, 1990   [CY]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n; ULONG LCW_Compress(BYTE *source,BYTE *dest, ULONG length);                *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL    LCW_Compress          :NEAR\n\nCODESEG\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; ULONG LCW_Compress(BYTE *source,BYTE *dest, ULONG length);\n;\n; ----------------------------------------------------------------\n\n\n\n;***********************************************************\n;\n; ULONG LCW_Compress(BYTE *source, BYTE *dest, ULONG length)\n;\n; returns the size of the compressed data in bytes\n;\n;*\nPROC\tLCW_Compress C near \n\tUSES ebx,ecx,edx,edi,esi\n\t\n\tARG\tsource:DWORD   \n\tARG\tdest:DWORD\n\tARG\tdatasize:DWORD\n\n\tLOCAL inlen:DWORD\n\tLOCAL a1stdest:DWORD\n\tLOCAL a1stsrc:DWORD\n\tLOCAL lenoff:DWORD\n\tLOCAL ndest:DWORD\n\tLOCAL count:DWORD\n\tLOCAL matchoff:DWORD\n\tLOCAL end_of_data:DWORD\n\n\n\tcld\n \tmov\tedi,[dest]\n \tmov\tesi,[source]\n \tmov\tedx,[datasize]\t\t; get length of data to compress\n\t\n;\tmov\tax,ds\n;\tmov\tes,ax\n\n;\n; compress data to the following codes in the format b = byte, w = word\n; n = byte code pulled from compressed data\n;   Bit field of n\t\tcommand\t\tdescription\n; n=0xxxyyyy,yyyyyyyy\t\tshort run\tback y bytes and run x+3\n; n=10xxxxxx,n1,n2,...,nx+1\tmed length\tcopy the next x+1 bytes\n; n=11xxxxxx,w1\t\t\tmed run\t\trun x+3 bytes from offset w1\n; n=11111111,w1,w2\t\tlong run\trun w1 bytes from offset w2\n; n=10000000\t\t\tend\t\tend of data reached\n;\n\tcld\t\t\t; make sure all string commands are forward\n\tmov\tebx,esi\n\tadd\tebx,edx\n\tmov\t[end_of_data],ebx\n\tmov\t[inlen],1\t; set the in-length flag\n\tmov\t[a1stdest],edi\t; save original dest offset for size calc\n\tmov\t[a1stsrc],esi\t; save offset of first byte of data\n\tmov\t[lenoff],edi\t; save the offset of the legth of this len\n\tsub\teax,eax\n\tmov\tal,081h\t\t; the first byte is always a len\n\tstosb\t\t\t; write out a len of 1\n\tlodsb\t\t\t; get the byte\n\tstosb\t\t\t; save it\n??loop:\n\tmov\t[ndest],edi\t; save offset of compressed data\n\tmov\tedi,[a1stsrc]\t; get the offset to the first byte of data\n\tmov\t[count],1\t; set the count of run to 0\n??searchloop:\n\tsub\teax,eax\n\tmov\tal,[esi]\t; get the current byte of data\n\tcmp\tal,[esi+64]\n\tjne\tshort ??notrunlength\n\t\n\tmov\tebx,edi\t\t \n\t\n\tmov\tedi,esi\n\tmov\tecx,[end_of_data]\n\tsub\tecx,edi\n   \trepe\tscasb\n\tdec\tedi\n\tmov\tecx,edi\n\tsub\tecx,esi\n\tcmp\tecx,65\n\tjb\tshort ??notlongenough\n\t\n\tmov\t[DWORD PTR inlen],0\t; clear the in-length flag\n\tmov\tesi,edi\n\tmov\tedi,[ndest]\t; get the offset of our compressed data\n\t\n\tmov\tah,al\n\tmov\tal,0FEh\n\tstosb\n\txchg\tecx,eax\n\tstosw\n\tmov\tal,ch\n\tstosb\n\t\n\tmov\t[ndest],edi\t; save offset of compressed data\n\tmov\tedi,ebx\n\tjmp\t??searchloop\n??notlongenough:\n\tmov\tedi,ebx\n??notrunlength:\n\n??oploop:\n\tmov\tecx,esi\t\t; get the address of the last byte +1\n\tsub\tecx,edi\t\t; get the total number of bytes left to comp\n\tjz\tshort ??searchdone\n\t\n\trepne\tscasb\t\t; look for a match\n\tjne\tshort ??searchdone\t; if we don't find one we're done\n\n\tmov\tebx,[count]\n\tmov\tah,[esi+ebx-1]\n\tcmp\tah,[edi+ebx-2]\n\n\tjne\t??oploop\n\n\tmov\tedx,esi\t\t; save this spot for the next search\n\tmov\tebx,edi\t\t; save this spot for the length calc\n\tdec\tedi\t\t; back up one for compare\n\tmov\tecx,[end_of_data]\t\t; get the end of data\n\tsub\tecx,esi\t\t; sub current source for max len\n\t\n\trepe\tcmpsb\t\t; see how many bytes match\n\n; start of change MH 9-24-91\n\tjne\tshort ??notend\t; if found mismatch then di - bx = match count\n\n\tinc\tedi\t\t; else cx = 0 and di + 1 - bx = match count\n\t\n??notend:\n; end of change MH 9-24-91\n\n\tmov\tesi,edx\t\t; restore si\n\tmov\teax,edi\t\t; get the dest\n\tsub\teax,ebx\t\t; sub the start for total bytes that match\n\tmov\tedi,ebx\t\t; restore dest\n\tcmp\teax,[count]\t; see if its better than before\n\tjb\t??searchloop\t; if not keep looking\n\t\n\tmov\t[count],eax\t; if so keep the count\n\tdec\tebx\t\t; back it up for the actual match offset\n\tmov\t[matchoff],ebx ; save the offset for later\n\tjmp\t??searchloop\t; loop until we searched it all\n\t\n??searchdone:\n\t\n\tmov\tecx,[count]\t; get the count of the longest run\n\tmov\tedi,[ndest]\t; get the offset of our compressed data\n\tcmp\tecx,2\t\t; see if its not enough run to matter\n\tjbe\tshort ??lenin\t\t; if its 0,1, or 2 its too small\n\t\n\tcmp\tecx,10\t\t; if not, see if it would fit in a short\n\tja\tshort ??medrun\t; if not, see if its a medium run\n\t\n\tmov\teax,esi\t\t; if its short get the current address\n\tsub\teax,[matchoff] ; sub the offset of the match\n\tcmp\teax,0FFFh\t; if its less than 12 bits its a short\n\tja\tshort ??medrun\t; if its not, its a medium\n\t\n??shortrun:\n\tsub\tebx,ebx\n\tmov\tbl,cl\t\t; get the length (3-10)\n\tsub\tbl,3\t\t; sub 3 for a 3 bit number 0-7\n\tshl\tbl,4\t\t; shift it left 4\n\tadd\tah,bl\t\t; add in the length for the high nibble\n\txchg\tah,al\t\t; reverse the bytes for a word store\n\tjmp\tshort ??srunnxt\t; do the run fixup code\n\n??medrun:\n\tcmp\tecx,64\t\t; see if its a short run\n\tja\tshort ??longrun\t; if not, oh well at least its long\n\t\n\tsub\tcl,3\t\t; back down 3 to keep it in 6 bits\n\tor\tcl,0C0h\t\t; the highest bits are always on\n\tmov\tal,cl\t\t; put it in al for the stosb\n\tstosb\t\t\t; store it\n\tjmp\tshort ??medrunnxt ; do the run fixup code\n\n??lenin:\n\tcmp\t[DWORD PTR inlen],0\t; is it doing a length?\n\tjnz\tshort ??len\t; if so, skip code\n\t\n??lenin1:\n\tmov\t[lenoff],edi\t; save the length code offset\n\tmov\tal,80h\t\t; set the length to 0\n\tstosb\t\t\t; save it\n\t\n??len:\n\tmov\tebx,[lenoff]\t; get the offset of the length code\n\tcmp\t[BYTE PTR ebx],0BFh\t; see if its maxed out\n\tje\t??lenin1\t; if so put out a new len code\n\t\n??stolen:\n\tinc\t[BYTE PTR ebx] ; inc the count code\n\tlodsb\t\t\t; get the byte\n\tstosb\t\t\t; store it\n\tmov\t[DWORD PTR inlen],1\t; we are now in a length so save it\n\tjmp\tshort ??nxt\t; do the next code\n\t\n??longrun:\n\tmov\tal,0ffh\t\t; its a long so set a code of FF\n\tstosb\t\t\t; store it\n\t\n\tmov\teax,[count]\t; send out the count\n\tstosw\t\t\t; store it\n??medrunnxt:\n\tmov\teax,[matchoff] ; get the offset\n\tsub\teax,[a1stsrc]\t; make it relative tot he start of data\n??srunnxt:\n\tstosw\t\t\t; store it\n; this code common to all runs\n\tadd\tesi,[count]\t; add in the length of the run to the source\n\tmov\t[DWORD PTR inlen],0\t; set the in leght flag to false\n\t\n;=======================================================================\t\n\n??nxt:\n\tcmp\tesi,[end_of_data]\t\t; see if we did the whole pic\n\tjae\tshort ??out\t\t; if so, cool! were done\n\t\n\tjmp\t??loop\n\t\n??out:\n\tmov\tax,080h\t\t; remember to send an end of data code\n\tstosb\t\t\t; store it\n\tmov\teax,edi\t\t; get the last compressed address\n\tsub\teax,[a1stdest]\t; sub the first for the compressed size\n\n\n\tret\n\nENDP\tLCW_Compress\n\n\nEND\n\u001a"
  },
  {
    "path": "WIN32LIB/IFF/LCWUNCMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/misc/rcs/lcwuncmp.asm 1.1 1994/04/11 15:31:21 jeff_wilson Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library routine                          *\n;*                                                                         *\n;*                    File Name : UNCOMP.ASM                               *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : 20 August, 1990   [CY]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length);\t\t   *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL            C LCW_Uncompress          :NEAR\n\nCODESEG\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length);\n;\n; ----------------------------------------------------------------\n\n\n\nPROC\tLCW_Uncompress C near\n\n\tUSES ebx,ecx,edx,edi,esi\n\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tlength:DWORD\n;LOCALS\n\tLOCAL a1stdest:DWORD\n\tLOCAL maxlen:DWORD\n\tLOCAL lastbyte:DWORD\n\tLOCAL lastcom:DWORD\n\tLOCAL lastcom1:DWORD\n\n\n\tmov\tedi,[dest]\n\tmov\tesi,[source]\n\tmov\tedx,[length]\n\n;\n;\n; uncompress data to the following codes in the format b = byte, w = word\n; n = byte code pulled from compressed data\n;   Bit field of n\t\tcommand\t\tdescription\n; n=0xxxyyyy,yyyyyyyy\t\tshort run\tback y bytes and run x+3\n; n=10xxxxxx,n1,n2,...,nx+1\tmed length\tcopy the next x+1 bytes\n; n=11xxxxxx,w1\t\t\tmed run\t\trun x+3 bytes from offset w1\n; n=11111111,w1,w2\t\tlong copy\tcopy w1 bytes from offset w2\n; n=11111110,w1,b1\t\tlong run\trun byte b1 for w1 bytes\n; n=10000000\t\t\tend\t\tend of data reached\n;\n\n\tmov\t[a1stdest],edi\n\tadd\tedx,edi\n\tmov\t[lastbyte],edx\n\tcld\t\t\t; make sure all lod and sto are forward\n\tmov\tebx,esi\t\t; save the source offset\n\n??loop:\n\tmov\teax,[lastbyte]\n\tsub\teax,edi\t\t; get the remaining byte to uncomp\n\tjz\tshort ??out\t\t; were done\n\n\tmov\t[maxlen],eax\t; save for string commands\n\tmov\tesi,ebx\t\t; mov in the source index\n\n\txor\teax,eax\n\tmov\tal,[esi]\n\tinc\tesi\n\ttest\tal,al\t\t; see if its a short run\n\tjs\tshort ??notshort\n\n\tmov\tecx,eax\t\t;put count nibble in cl\n\n\tmov\tah,al\t\t; put rel offset high nibble in ah\n\tand\tah,0Fh\t\t; only 4 bits count\n\n\tshr\tcl,4\t\t; get run -3\n\tadd\tecx,3\t\t; get actual run length\n\n\tcmp\tecx,[maxlen]\t; is it too big to fit?\n\tjbe\tshort ??rsok\t\t; if not, its ok\n\n\tmov\tecx,[maxlen]\t; if so, max it out so it dosen't overrun\n\n??rsok:\n\tmov\tal,[esi]\t; get rel offset low byte\n\tlea\tebx,[esi+1]\t; save the source offset\n\tmov\tesi,edi\t\t; get the current dest\n\tsub\tesi,eax\t\t; get relative offset\n\n\trep\tmovsb\n\n\tjmp\t??loop\n\n??notshort:\n\ttest\tal,40h\t\t; is it a length?\n\tjne\tshort ??notlength\t; if not it could be med or long run\n\n\tcmp\tal,80h\t\t; is it the end?\n\tje\tshort ??out\t\t; if so its over\n\n\tmov\tcl,al\t\t; put the byte in count register\n\tand\tecx,3Fh\t\t; and off the extra bits\n\n\tcmp\tecx,[maxlen]\t; is it too big to fit?\n\tjbe\tshort ??lenok\t\t; if not, its ok\n\n\tmov\tecx,[maxlen]\t; if so, max it out so it dosen't overrun\n\n??lenok:\n\trep movsb\n\n\tmov\tebx,esi\t\t; save the source offset\n\tjmp\t??loop\n\n??out:\n      \tmov\teax,edi\n\tsub\teax,[a1stdest]\n\tjmp\t??exit\n\n??notlength:\n\tmov\tcl,al\t\t; get the entire code\n\tand\tecx,3Fh\t\t; and off all but the size -3\n\tadd\tecx,3\t\t; add 3 for byte count\n\n\tcmp\tal,0FEh\n\tjne\tshort ??notrunlength\n\n\txor\tecx,ecx\n\tmov\tcx,[esi]\n\n\txor\teax,eax\n\tmov\tal,[esi+2]\n\tlea\tebx,[esi+3]\t;save the source offset\n\n\tcmp\tecx,[maxlen]\t; is it too big to fit?\n\tjbe\tshort ??runlenok\t\t; if not, its ok\n\n\tmov\tecx,[maxlen]\t; if so, max it out so it dosen't overrun\n\n??runlenok:\n\ttest\tecx,0ffe0h\n\tjnz\t??dont_use_stosb\n\trep\tstosb\n\tjmp\t??loop\n\n\n??dont_use_stosb:\n\tmov\tah,al\n\tmov\tedx,eax\n\tshl\teax,16\n\tor\teax,edx\n\n\ttest\tedi,3\n\tjz\t??aligned\n\n\tmov\t[edi],eax\n\tmov\tedx,edi\n\tand\tedi,0fffffffch\n\tlea\tedi,[edi+4]\n\tand\tedx,3\n\tdec\tdl\n\txor\tdl,3\n\tsub\tecx,edx\n\n??aligned:\n\tmov\tedx,ecx\n\tshr\tecx,2\n\trep\tstosd\n\n\tand\tedx,3\n\tjz\t??loop\n\tmov\tecx,edx\n\trep\tstosb\n\tjmp\t??loop\n\n\n\n\n\n\n??notrunlength:\n\tcmp\tal,0FFh\t\t; is it a long run?\n\tjne\tshort ??notlong\t; if not use the code as the size\n\n\txor     ecx,ecx\n\txor\teax,eax\n\tmov\tcx,[esi]\t; if so, get the size\n\tlea\tesi,[esi+2]\n\n??notlong:\n\tmov\tax,[esi]\t;get the real index\n\tadd\teax,[a1stdest]\t;add in the 1st index\n\tlea\tebx,[esi+2]\t;save the source offset\n\tcmp\tecx,[maxlen]\t;compare for overrun\n\tmov\tesi,eax\t\t;use eax as new source\n\tjbe\tshort ??runok\t; if not, its ok\n\n\tmov\tecx,[maxlen]\t; if so, max it out so it dosen't overrun\n\n??runok:\n\ttest\tecx,0ffe0h\n\tjnz\t??dont_use_movsb\n\trep\tmovsb\n\tjmp\t??loop\n\n\n\n\n??dont_use_movsb:\n\tlea\tedx,[edi+0fffffffch]\n\tcmp\tesi,edx\n\tja\t??use_movsb\n\n\ttest\tedi,3\n\tjz\t??aligned2\n\n\tmov\teax,[esi]\n\tmov\t[edi],eax\n\tmov\tedx,edi\n\tand\tedi,0fffffffch\n\tlea\tedi,[edi+4]\n\tand\tedx,3\n\tdec\tdl\n\txor\tdl,3\n\tsub\tecx,edx\n\tadd\tesi,edx\n\n??aligned2:\n\tmov\tedx,ecx\n\tshr\tecx,2\n\tand\tedx,3\n\trep\tmovsd\n\tmov\tecx,edx\n??use_movsb:\n\trep\tmovsb\n\tjmp\t??loop\n\n\n\n\n??exit:\n\tmov\teax,edi\n\tmov\tebx,[dest]\n\tsub\teax,ebx\n\n\tret\n\nENDP\tLCW_Uncompress\n\n;***********************************************************\n\n\n\tEND\n\n"
  },
  {
    "path": "WIN32LIB/IFF/LOAD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/wwlib32/file/rcs/load.cpp 1.4 1994/04/22 12:42:21 scott_bowen Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : LOAD.C                                   *\n *                                                                         *\n *                   Programmer : Christopher Yates                        *\n *                                                                         *\n *                  Last Update : September 17, 1993   [JLB]               *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Load_Uncompress -- Load and uncompress the given file.                *\n *   Uncompress_Data -- Uncompress standard CPS buffer.                    *\n *   Load_Data -- Loads a data file from disk.                             *\n *   Load_Alloc_Data -- Loads and allocates buffer for a file.             *\n *   Write_Data -- Writes a block of data as a file to disk.               *\n *   Uncompress_Data -- Uncompresses data from one buffer to another.      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"iff.h\"\n#include \"file.h\"\n#include <misc.h>\n#include <wwstd.h>\n#include <dos.h>\n#include <wwmem.h>\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * LOAD_DATA -- Loads a data file from disk.                               *\n *                                                                         *\n *    This routine will load a data file from disk.  It does no translation*\n *    on the data.                                                         *\n *                                                                         *\n * INPUT:   name  -- Pointer to ASCII filename of the data file.           *\n *                                                                         *\n *          ptr   -- Buffer to load the data file into.                    *\n *                                                                         *\n *          size  -- Maximum size of the buffer (in bytes).                *\n *                                                                         *\n * OUTPUT:  Returns with the number of bytes read.                         *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/24/1991 JLB : Created.                                             *\n *=========================================================================*/\nunsigned long __cdecl Load_Data(char const *name, void *ptr, unsigned long size)\n{\n\tint fd;\n\n\tfd = Open_File(name, READ);\n\tsize = Read_File(fd, ptr, size);\n\tClose_File(fd);\n\treturn(size);\n}\n\n\n/***************************************************************************\n * WRITE_DATA -- Writes a block of data as a file to disk.                 *\n *                                                                         *\n *    This routine will write a block of data as a file to the disk.  It   *\n *    is the compliment of Load_Data.                                      *\n *                                                                         *\n * INPUT:   name     -- Name of the file to create.                        *\n *                                                                         *\n *          ptr      -- Pointer to the block of data to write.             *\n *                                                                         *\n *          size     -- Size of the data block to be written.              *\n *                                                                         *\n * OUTPUT:  Returns with the number of bytes actually written.             *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/05/1992 JLB : Created.                                             *\n *=========================================================================*/\nunsigned long __cdecl Write_Data(char const *name, void *ptr, unsigned long size)\n{\n\tint fd;\n\n\tfd = Open_File(name, WRITE);\n\tsize = Write_File(fd, ptr, size);\n\tClose_File(fd);\n\treturn(size);\n}\n\n\n/***************************************************************************\n * LOAD_ALLOC_DATA -- Loads and allocates buffer for a file.               *\n *                                                                         *\n *    The routine will allocate a buffer and load the specified file into  *\n *    it.  The kind of memory used for the buffer is determined by the     *\n *    memory allocation flags passed in.                                   *\n *                                                                         *\n * INPUT:   name  -- Name of the file to load.                             *\n *                                                                         *\n *          flags -- Memory allocation flags to use when allocating.       *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the buffer that contains the file's  *\n *          data.                                                          *\n *                                                                         *\n * WARNINGS:   A memory error could occur if regular memory flags are      *\n *             specified.  If XMS memory is specified, then this routine   *\n *             could likely return NULL.                                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/28/1992 JLB : Created.                                             *\n *=========================================================================*/\nvoid * __cdecl Load_Alloc_Data(char const *name, MemoryFlagType flags)\n{\n\tint\tfd;\t\t// Working file handle.\n\tunsigned long\tsize;\t\t// Size of the file to load.\n\tvoid\t*buffer;\t// Buffer to hold the file.\n\n\tfd = Open_File(name, READ);\n\tsize = File_Size(fd);\n\tbuffer = Alloc(size, flags);\n\tif (buffer) {\n\t\tRead_File(fd, buffer, size);\n\t}\n\tClose_File(fd);\n\treturn(buffer);\n}\n\n\n/***************************************************************************\n * LOAD_UNCOMPRESS -- Load and uncompress the given file.                  *\n *                                                                         *\n * INPUT:      char *\t\t\t\t\t- file name to uncompress \t\t\t\t\t*\n *\t\t\t\t\tGraphicBufferClass&\t- to load the source data into\t\t\t*\n *\t\t\t\t\tGraphicBufferClass&\t- for the picture\t\t\t\t\t\t\t\t*\n *             void *\t\t\t\t\t- ptr for header uncompressed data     *\n *                                                                         *\n * OUTPUT:     unsigned long size of uncompressed data                             *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/28/1991  CY : Created.                                             *\n *   06/26/1991 JLB : Handles load & uncompress to same buffer.            *\n *=========================================================================*/\nunsigned long __cdecl Load_Uncompress(char const *file, BufferClass& uncomp_buff, BufferClass& dest_buff, void *reserved_data)\n{\n\tint\tfd;\t\t\t\t// Source file handle.\n\tunsigned int\tisize=0;\t\t\t// Size of the file.\n\tunsigned int\tskipsize;\t\t// Size of the skip data bytes.\n\tvoid\t*uncomp_ptr;\t//\tSource buffer pointer.\n\tchar\t*newuncomp_ptr;\t// Adjusted source pointer.\n\n\n\tuncomp_ptr = uncomp_buff.Get_Buffer();\t\t// get a pointer to buffer\n\n\t/*======================================================================*/\n\t/* Read the file into the uncompression buffer.\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\n\tfd = Open_File(file, READ);\t\t\t\t\t// Open up the file to read from\n\tRead_File(fd, (char *) &isize,\t2L);\t\t// Read the file size\n\tRead_File(fd, uncomp_ptr, \t\t\t8L);\t\t// Read the header bytes in.\n\tisize -= 8; \t\t\t\t\t\t\t\t\t\t// Remaining data in file.\n\n\t/*======================================================================*/\n\t/* Check for and read in the skip data block.\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\n\tskipsize = *(((short *)uncomp_ptr) + 3);\n\n\tif (reserved_data && skipsize) {\n\t\tRead_File(fd, reserved_data, (unsigned long) skipsize);\n\t} else {\n\t\tSeek_File(fd, skipsize, SEEK_CUR);\n\t}\n\n\t*( ((short *)uncomp_ptr+3) )\t = 0;\t\t\t\t// K/O any skip value.\n\tisize \t\t\t\t\t\t\t-= skipsize;\n\n\t/*======================================================================*/\n\t/*\tIf the source and dest buffer are the same, we adjust the pointer so */\n\t/* that the compressed data is loaded into the end of the buffer.  In \t*/\n\t/* this way the uncompress code can write to the same buffer.\t\t\t\t*/\n\t/*======================================================================*/\n\tnewuncomp_ptr = (char *)Add_Long_To_Pointer(uncomp_buff.Get_Buffer(), uncomp_buff.Get_Size() - (isize+8L));\n\n\t/*======================================================================*/\n\t/*\tDuplicate the header bytes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tMem_Copy(uncomp_ptr,newuncomp_ptr,8);\n\n\t/*======================================================================*/\n\t/*\tRead in the main compressed part of the file.\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tRead_File(fd, newuncomp_ptr + 8, (unsigned long)isize);\n\tClose_File(fd);\n\n\t/*======================================================================*/\n\t/* Uncompress the file into the destination buffer (which may very well\t*/\n\t/*\t\tbe the source buffer).\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\treturn(Uncompress_Data(newuncomp_ptr, dest_buff.Get_Buffer()));\n}\n#if(0)\n/***************************************************************************\n * LOAD_UNCOMPRESS -- Load and uncompress the given file.                  *\n *                                                                         *\n * INPUT:      char *file name to uncompress, BuffType uncomp_buff to load *\n *             the source data into, BuffType dest_buff for the picture,   *\n *             void *reserved_data pointer for header uncompressed data    *\n *                                                                         *\n * OUTPUT:     unsigned long size of uncompressed data                             *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/28/1991  CY : Created.                                             *\n *   06/26/1991 JLB : Handles load & uncompress to same buffer.            *\n *=========================================================================*/\nunsigned long __cdecl Load_Uncompress(char const *file, BuffType uncomp_buff, BuffType dest_buff, void *reserved_data)\n{\n\tint\tfd;\t\t\t\t// Source file handle.\n\tunsigned int\tisize;\t\t\t// Size of the file.\n\tunsigned int\tskipsize;\t\t// Size of the skip data bytes.\n\tvoid\t*uncomp_ptr;\t//\tSource buffer pointer.\n\tchar\t*newuncomp_ptr;\t// Adjusted source pointer.\n\n\n\tuncomp_ptr = Get_Buff(uncomp_buff);\t\t/* Get pointer to uncomp buffer */\n\n\t/* Read the file into the uncomp_buff */\n\n\tfd = Open_File(file, READ);\n\tRead_File(fd, (char *) &isize, 2L);\t\t\t\t/* Read the file size \t\t*/\n\t#if(AMIGA)\n\t\tisize = Reverse_Word(isize);\n\t#endif\n\n\tRead_File(fd, uncomp_ptr, 8L);\t\t// Read the header bytes in.\n\tisize -= 8; \t\t\t\t\t\t\t\t// Remaining data in file.\n\n\t/*\n\t**\tCheck for and read in the skip data block.\n\t*/\n\n\tskipsize = *(((short*)uncomp_ptr) + 3);\n\t#if(AMIGA)\n\t\tskipsize = Reverse_Word(skipsize);\n\t#endif\n\n\tif (reserved_data && skipsize) {\n\t\tRead_File(fd, reserved_data, (unsigned long) skipsize);\n\t} else {\n\t\tSeek_File(fd, skipsize, SEEK_CUR);\n\t}\n\t*( ((short *)uncomp_ptr+3) ) = 0;\t\t// K/O any skip value.\n\tisize -= skipsize;\n\n\t/*\n\t**\tIf the source and dest buffer are the same, we\n\t**\tadjust the pointer so that the compressed data is\n\t**\tloaded into the end of the buffer.  In this way the\n\t**\tuncompress code can write to the same buffer.\n\t*/\n\t#if(IBM)\n\t\tnewuncomp_ptr = (char *)Add_Long_To_Pointer(Get_Buff(uncomp_buff), PageArraySize[uncomp_buff] - (isize+8L));\n\t#else\n\t\tnewuncomp_ptr = Get_Buff(uncomp_buff);\n\t\tnewuncomp_ptr += PageArraySize[uncomp_buff] - ((isize+10) & 0xFFFE);\n\t#endif\n\n\t/*\n\t**\tDuplicate the header bytes.\n\t*/\n\tMem_Copy(uncomp_ptr,newuncomp_ptr,8);\n\n\t/*\n\t**\tRead in the main compressed part of the file.\n\t*/\n\tRead_File(fd, newuncomp_ptr + 8, (unsigned long)isize);\n\tClose_File(fd);\n\n\treturn(Uncompress_Data(newuncomp_ptr, Get_Buff(dest_buff)));\n}\n\n#endif\n/***************************************************************************\n * Uncompress_Data -- Uncompresses data from one buffer to another.        *\n *                                                                         *\n *    This routine takes data from a compressed file (sans the first two   *\n *    size bytes) and uncompresses it to a destination buffer.  The source *\n *    data MUST have the CompHeaderType at its start.                      *\n *                                                                         *\n * INPUT:   src   -- Source compressed data pointer.                       *\n *                                                                         *\n *          dst   -- Destination (paragraph aligned) pointer.              *\n *                                                                         *\n * OUTPUT:  Returns with the size of the uncompressed data.                *\n *                                                                         *\n * WARNINGS:   If LCW compression is used, the destination buffer must     *\n *             be paragraph aligned.                                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/17/1993 JLB : Created.                                             *\n *=========================================================================*/\nunsigned long __cdecl Uncompress_Data(void const *src, void *dst)\n{\n\tunsigned int\t\t\t\t\tskip;\t\t\t// Number of leading data to skip.\n\tCompressionType\tmethod;\t\t// Compression method used.\n\tunsigned long\t\t\t\t\tuncomp_size=NULL;\n\n\tif (!src || !dst) return(NULL);\n\n\t/*\n\t**\tInterpret the data block header structure to determine\n\t**\tcompression method, size, and skip data amount.\n\t*/\n\tuncomp_size = ((CompHeaderType*)src)->Size;\n\t#if(AMIGA)\n\t\tuncomp_size = Reverse_Long(uncomp_size);\n\t#endif\n\tskip = ((CompHeaderType*)src)->Skip;\n\t#if(AMIGA)\n\t\tskip = Reverse_Word(skip);\n\t#endif\n\tmethod = (CompressionType) ((CompHeaderType*)src)->Method;\n\tsrc = Add_Long_To_Pointer((void *)src, (long)sizeof(CompHeaderType) + (long)skip);\n\n\tswitch (method) {\n\n\t\tdefault:\n\t\tcase NOCOMPRESS:\n\t\t\tMem_Copy((void *) src, dst, uncomp_size);\n\t\t\tbreak;\n\n\t\tcase HORIZONTAL:\n#if LIB_EXTERNS_RESOLVED\n\t\t\tRLE_Uncompress((void *) src, dst, uncomp_size);\n#endif\n\t\t\tbreak;\n\n\t\tcase LCW:\n\t\t\tLCW_Uncompress((void *) src, (void *) dst, (unsigned long) uncomp_size);\n\t\t\tbreak;\n\n\t}\n\n\treturn(uncomp_size);\n}\n\n\n"
  },
  {
    "path": "WIN32LIB/IFF/LOADPCX.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : IFF                                      *\n *                                                                         *\n *                    File Name : LOADPCX.CPP                              *\n *                                                                         *\n *                   Programmer : Julio R. Jerez                           *\n *                                                                         *\n *                   Start Date : May 2, 1995                              *\n *                                                                         *\n *                  Last Update : May 3, 1995   [JRJ]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * GraphicBufferClass* Read_PCX_File (char* name, void *Buff, long size ); *\n * int Get_PCX_Palette (char * name, void& palette )\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include  <wwlib32.h>\n#include \"filepcx.h\"\n\n/***************************************************************************\n * READ_PCX_FILE -- read a pcx file into a Graphic Buffer                  *\n *                                                                         *\n *\tGraphicBufferClass* Read_PCX_File (char* name, char* palette ,void *Buff, long size );\t*\n *  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT: name is a NULL terminated string of the fromat [xxxx.pcx]        *\n *        palette is optional, if palette != NULL the the color palette of *\n *\t\t\t\t\t the pcx file will be place in the memory block pointed\t   *\n *               by palette.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t Buff is optinal, if Buff == NULL a new memory Buffer\t\t \t\t\t*\n *\t\t\t\t\t will be allocated, otherwise the file will be placed \t\t*\n *\t\t\t\t\t at location pointd by Buffer;\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tSize is the size in bytes of the memory block pointed by Buff\t\t*\n *\t\t\t\t  is also optional;\n *                                                                         *\n * OUTPUT: on succes a pointer to a GraphicBufferClass cointaining the     *\n *         pcx file, NULL othewise.                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1995 JRJ : Created.                                             *\n *=========================================================================*/\n\n#define\tPOOL_SIZE 2048\n#define\tREAD_CHAR()  *file_ptr++ ; \\\n\t\t\t\t\t\t\t if ( file_ptr\t>= & pool [ POOL_SIZE ]\t) { \\\n\t\t\t\t\t\t\t\t Read_File ( file_handle, pool , POOL_SIZE ) ; \\\n\t\t\t\t\t\t\t\t file_ptr = pool ; \\\n\t\t\t\t\t\t\t }\n\n\nGraphicBufferClass* Read_PCX_File(char* name, char* Palette, void *Buff, long Size)\n{\n  unsigned     i , j ;\n  unsigned     rle ;\n  unsigned     color ;\n  unsigned\t\tscan_pos ;\n  char\t\t * file_ptr ;\n  int\t\t\t\twidth\t;\n  int\t\t\t\theight ;\n  int \t      file_handle ;\n  char\t\t * buffer ;\n  PCX_HEADER   header ;\n  RGB  \t\t * pal ;\n  char \t\t\tpool [ POOL_SIZE ] ;\n  GraphicBufferClass * pic\t;\n\n  // Open file name\n  file_handle = Open_File ( name , READ ) ;\n  if ( file_handle == WW_ERROR ) return NULL ;\n\n  Read_File ( file_handle, & header , sizeof (PCX_HEADER)) ;\n  if ( header.id != 10 &&  header.version != 5 &&\n\t   header.pixelsize != 8 ) return NULL ;\n\n  width = header.width - header.x + 1 ;\n  height = header.height - header.y + 1 ;\n\n  if ( Buff ) {\n\t  buffer = ( char * ) Buff;\n\t  i = Size / width;\n\t  height = MIN ( i - 1, height);\n\t  pic = new GraphicBufferClass( width, height, buffer ,Size);\n\t  if ( !(pic && pic->Get_Buffer()))return NULL ;\n  } else {\n\t  pic = new GraphicBufferClass( width, height, NULL, width*(height+4));\n\t  if ( !(pic && pic->Get_Buffer()))return NULL ;\n  }\n\n  buffer = (char *) pic->Get_Buffer() ;\n  file_ptr = pool ;\n  Read_File ( file_handle, pool , POOL_SIZE ) ;\n\n  if ( header.byte_per_line != width )\n\t for ( scan_pos = j = 0 ; j < height ; j ++, scan_pos += width ) {\n      for ( i = 0 ; i < width ; ) {\n\t\t\t\t rle = READ_CHAR ();\n\t\t\t\t if ( rle > 192 ) {\n\t\t\t\t rle -= 192 ;\n\t\t\t\t color =\tREAD_CHAR (); ;\n\t\t \t\t memset ( buffer + scan_pos + i , color , rle ) ;\n\t\t \t\t i += rle ;\n\t        } else * ( buffer + scan_pos + i ++ ) = (char)rle ;\n\t    }\n\t\t if ( i == width )\n\t\t rle = READ_CHAR () ;\n//\t\t if ( rle > 192 ) rle = READ_CHAR ();\n    }\n\n\n  else for ( i = 0 ; i < width * height ; ) {\n\t\trle = READ_CHAR ();\n\t\trle &= 0xff;\n\t\tif ( rle > 192 ) {\n\t      rle -= 192 ;\n\t      color = READ_CHAR ();\n\t\t\tmemset ( buffer + i , color , rle ) ;\n\t      i += rle ;\n\t    }\telse * ( buffer + i ++ ) = (char)rle ;\n  }\n\n if ( Palette ) {\n\t  //Seek_File ( file_handle , - 256 * sizeof ( RGB ) , SEEK_END ) ;\n\t  Seek_File ( file_handle , 256 * sizeof ( RGB ) , SEEK_END ) ;\n\t  Read_File ( file_handle,\tPalette , 256L * sizeof ( RGB )) ;\n\n\t  pal = ( RGB * ) Palette ;\n\t  for ( i = 0 ; i < 256 ; i ++ ) {\n\t\t pal -> red >>= 2 ;\n\t\t pal -> green >>= 2 ;\n\t\t pal -> blue >>= 2 ;\n\t\t pal ++ ;\n\t  }\n  }\n Close_File (file_handle) ;\n return pic ;\n}\n\n/***************************************************************************\n * READ_PCX_FILE -- read a pcx file into a Graphic Buffer                  *\n *                                                                         *\n *\tGraphicBufferClass* Read_PCX_File (char* name, BufferClass& Buff,\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  char* palette)\t*\t\t\t*\n *  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT: name is a NULL terminated string of the fromat [xxxx.pcx]        *\n *\t\t\t Buff is a pointer to a BufferClass the will hold the pcx file \t*\n *\t\t\t\t\t at location pointd by Buffer;\t\t\t\t\t\t\t\t\t\t*\n *        palette is optional, if palette != NULL the the color palette of *\n *\t\t\t\t\t the pcx file will be place in the memory block pointed\t   *\n *               by palette.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT: on succes a pointer to a GraphicBufferClass cointaining the     *\n *         pcx file, NULL othewise.                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1995 JRJ : Created.                                             *\n *=========================================================================*/\n\nGraphicBufferClass* Read_PCX_File (char* name, BufferClass& Buff,char* palette)\n{\n  return Read_PCX_File(name, palette, (void*)Buff.Get_Buffer(), Buff.Get_Size());\n}"
  },
  {
    "path": "WIN32LIB/IFF/LOADPICT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/wwlib32/file/rcs/loadpict.cpp 1.1 1994/04/20 14:38:08 scott_bowen Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : IFFEXTRA.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : June 11, 1991                            *\n *                                                                         *\n *                  Last Update : April 20, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   ILBM_To_Amiga -- Convert ILBM to bitplane Amiga format.               *\n *   ILBM_To_MCGA -- Converts ILBM picture into MCGA format.               *\n *   PBM_To_Amiga -- Converts a PBM picture into Amiga format.             *\n *   Load_Picture -- Loads a picture file (CPS or LBM format).             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"iff.h\"\n#include \"file.h\"\n#include <wwmem.h>\t// For Alloc.\n\n#if(IBM)\n#include <mem.h>\n#endif\n\n// Since we are not currently using AMIGA, this has been put in to\n// give us back some code space.  If it is needed for a utility,\n// this module should be recompiled with that utility and set the\n// define to TRUE.\n#define\tMAKE_AMIGA_ART\tFALSE\n\n/*\n** An IFF picture file can have one of two formats:\n**\tILBM\t- InterLeaved Bit Map\n**\tPBM\t- Packed Bit Map\n*/\ntypedef enum {\n\tFORM_ILBM,\n\tFORM_PBM\n} IFFForm_Type;\n\n/*\n**\tThese are the various chunks that compose an IFF picture file.\n*/\n#define ID_FORM\t\t\tMAKE_ID('F','O','R','M')\n#define ID_ILBM\t\t\tMAKE_ID('I','L','B','M')\n#define ID_PBM \t\t\tMAKE_ID('P','B','M',' ')\n#define ID_CMAP \t\t\tMAKE_ID('C','M','A','P')\n#define ID_BODY \t\t\tMAKE_ID('B','O','D','Y')\n#define ID_BMHD \t\t\tMAKE_ID('B','M','H','D')\n\n\n/*\n**\tThe BMHD (Bit Map HeaDer) chunk in an IFF picture file contains the\n**\tinformation necessary to extract that picture from the BODY chunk.\n**\tIt also indicates the size and depth of the source art.\n*/\ntypedef struct {\n\tunsigned short\tW, H;\t\t\t\t// Raster width and height in pixels.\n\tshort \tX, Y;\t\t\t\t\t\t// Pixel postion for this image.\n\tchar\tBPlanes;\t\t\t\t\t\t// Number of bitplanes.\n\tunsigned char\tMasking;\t\t\t// Masking control byte.\n\t\t\t\t\t\t\t\t\t\t\t// 0 = No masking.\n\t\t\t\t\t\t\t\t\t\t\t//\t1 = Has a mask.\n\t\t\t\t\t\t\t\t\t\t\t//\t2 = Has transparent color.\n\t\t\t\t\t\t\t\t\t\t\t//\t3 = Lasso.\n\tunsigned char\tCompression;\t// Compression method.\n\t\t\t\t\t\t\t\t\t\t\t// 0 = No compression.\n\t\t\t\t\t\t\t\t\t\t\t// 1 = Byte run compression.\n\tchar\tpad;\n\tunsigned short\tTransparent;\t// Transparent color number.\n\tunsigned char\tXAspect,\t\t\t// Pixel aspect ratio of source art.\n\t\t\tYAspect;\n\tshort\tPageWidth, \t\t\t\t\t// Source 'page' size in pixels.\n\t\t\tPageHeight;\n} BitMapHeader_Type;\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE void __cdecl ILBM_To_MCGA(BufferClass& src, BufferClass& dest, int planes);\nPRIVATE void __cdecl ILBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes);\nPRIVATE void __cdecl PBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes);\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n/***************************************************************************\n * ILBM_TO_MCGA -- Converts ILBM picture into MCGA format.                 *\n *                                                                         *\n *    This converts an ILBM picture (typical of DPaint LBM files) and      *\n *    converts it to MCGA mode (byte per pixel).  This function would be   *\n *    used after the body of an ILBM picture is loaded.  Because the       *\n *    number of bitplanes can vary greatly, it is necessary to pass the    *\n *    bitplane count to this function.  The size (320 by 200) of the       *\n *    source picture is presumed.                                          *\n *                                                                         *\n * INPUT:   src   - Buffer number for source ILBM picture.                 *\n *                                                                         *\n *          dest  - Buffer number for place to put MCGA format.            *\n *                                                                         *\n *          planes- The number of bitplanes in the ILBM picture.           *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1991 JLB : Created.                                             *\n *   04/20/1994 SKB : Update to 32 bit library and make private.           *\n *=========================================================================*/\nPRIVATE void __cdecl ILBM_To_MCGA(BufferClass& src, BufferClass& dest, int planes)\n{\n\tchar\t*source;\t\t\t// Source pointer.\n\tchar\t*destination;\t// Destination pointer.\n\tint\tindex,j,i;\t\t// Working index values.\n\tint\tbplane;\t\t\t// Bit plane counter.\n\tchar\tbytes[8];\t\t// Byte array holding max bitplanes (8).\n\tchar\tvalue;\t\t\t// Composed byte(pixel) value.\n\n\tsource = (char *) src.Get_Buffer();\n\tdestination = (char *) dest.Get_Buffer();\n\n\tmemset(bytes, '\\0', 8);\t// Makes sure upper bits will be clear.\n\n\t// Each row is grouped and processed together.\n\n\tfor (index = 0; index < 200 /*bmhd.H*/; index++) {\n\n\t\t// Process each line in groups of 8 bytes.\n\n\t\tfor (j = 0; j < 40 /*(bmhd.W>>3)*/; j++) {\n\n\t\t\t// Get the bitplane bytes.\n\n\t\t\tfor (bplane = 0; bplane < planes /*bmhd.BPlanes*/; bplane++) {\n\t\t\t\tbytes[bplane] = *(source + (bplane * 40 /*(bmhd.W>>3)*/));\n\t\t\t}\n\t\t\tsource++;\n\n\t\t\t// Roll the bits out to create 8 pixels (by bytes).\n\t\t\tfor (i = 0; i < 8; i++) {\n\n\t\t\t\t// 8 bits per byte.\n\t\t\t\tvalue = 0;\n\t\t\t\tfor (bplane = planes - 1/*bmhd.BPlanes-1*/; bplane >= 0; bplane--) {\n\t\t\t\t\tvalue <<= 1;\t\t\t// Make room for next bit.\n\t\t\t\t\tif (bytes[bplane] & 0x80) value |= 1;\t// Set the bit.\n\t\t\t\t\tbytes[bplane] <<= 1;\n\t\t\t\t}\n\t\t\t\t*destination++ = value;\t// Output the pixel byte.\n\t\t\t}\n\t\t}\n\n\t\t// Advance to next scan line.\n\t\tsource += 40 /* (bmhd.W >> 3)*/ * (planes /* bmhd.BPlanes */ - 1);\n\t}\n}\n\n\n/***************************************************************************\n * ILBM_TO_AMIGA -- Convert ILBM to bitplane Amiga format.                 *\n *                                                                         *\n *    This converts an InterLeaved BitMap picture into Amiga bitplane      *\n *    format (8K per bitplane).  The data of an ILBM picture is controlled *\n *    by the number of bitplanes it contains.  The bitplane count is       *\n *    passed into this program.                                            *\n *                                                                         *\n * INPUT:   src   - Buffer number for source ILBM picture data.            *\n *                                                                         *\n *          dest  - Buffer number for destination Amiga picture data.      *\n *                                                                         *\n *          planes- The number of bitplanes in the source ILBM data.       *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   The amount of data placed into the destination buffer is    *\n *             controlled by the number of bitplanes specified.  It is     *\n *             8000 per bitplane.                                          *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/20/1991 JLB : Created.                                             *\n *   04/20/1994 SKB : Update to 32 bit library and make private.           *\n *   04/20/1994 SKB : #if out for main library.  Only used in utils maybe. *\n *=========================================================================*/\n#if MAKE_AMIGA_ART\nPRIVATE void __cdecl ILBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes)\n{\n\tint\trow;\t\t\t// Working row counter.\n\tint\tbp;\t\t\t// Working bitplane counter.\n\tchar\t*srcptr,\t\t// Source buffer pointer.\n\t\t\t*dstptr;\t\t// Destination buffer pointer.\n\n\tsrcptr = (char *) src.Get_Buffer();\t\t// Source buffer pointer.\n\tdstptr = (char *) dest.Get_Buffer();\t// Destination buffer pointer.\n\n\tfor (row = 0; row < 200; row++) {\n\t\tfor (bp = 0; bp < planes; bp++) {\n\t\t\tMem_Copy(srcptr,dstptr+(8000*bp),40);\n\t\t\tsrcptr += 40;\n\t\t}\n\t\tdstptr += 40;\n\t}\n}\n#endif\n\n\n/***************************************************************************\n * PBM_TO_AMIGA -- Converts a PBM picture into Amiga format.               *\n *                                                                         *\n *    This converts a PBM (Packed Bit Map) MCGA picture into Amiga         *\n *    bitplane format.  A PBM picture presumes 8 bitplanes, but this       *\n *    can be controlled by the 'plane' parameter passed in.                *\n *                                                                         *\n * INPUT:   src   - Buffer number for the source PBM data.                 *\n *                                                                         *\n *          dest  - Buffer number to place the Amiga format picture.       *\n *                                                                         *\n *          planes- The number of bitplanes to extract from the PBM source *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   The amount of data placed into the destination buffer is    *\n *             controlled by the number of bitplanes specified.  It is     *\n *             8000 per bitplane.                                          *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/20/1991 JLB : Created.                                             *\n *   04/20/1994 SKB : Update to 32 bit library and make private.           *\n *   04/20/1994 SKB : #if out for main library.  Only used in utils maybe. *\n *=========================================================================*/\n#if MAKE_AMIGA_ART\nPRIVATE void __cdecl PBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes)\n{\n\tint\trow,\t\t\t\t\t\t\t// Working row counter.\n\t\t\tcol,\t\t\t\t\t\t\t// Working column (by byte) counter.\n\t\t\tbit;\t\t\t\t\t\t\t// Working bitplane counter.\n\tunsigned char\t*destptr,\t\t// Destination byte pointer.\n\t\t\t\t\t\t*srcptr;\t\t\t// Source byte pointer.\n\tunsigned char\tvalue;\t\t\t// Working input MCGA pixel number.\n\n\n\tdestptr = (unsigned char *) dest.Get_Buffer();\n\tsrcptr = (unsigned char *) src.Get_Buffer();\n\n\tmemset(destptr, 0, 32000);\n\tmemset(destptr+32000, 0, 32000);\n\n\tfor (row = 0; row < 200; row++) {\n\n\t\tfor (col = 0; col < 320; col++) {\n\t\t\tvalue = *srcptr++;\n\n\t\t\tfor (bit = 0; bit < planes; bit++) {\n\t\t\t\tif (value & (0x01 << bit)) {\n\t\t\t\t\tdestptr[(short)((8000L * (long)bit) + (col>>3))] |= 0x80 >> (col & 0x07);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tdestptr += 40;\n\t}\n}\n#endif\n\n/***************************************************************************\n * LOAD_PICTURE -- Loads a picture file (CPS or LBM format).               *\n *                                                                         *\n *    This loads a picture file into a page buffer.  The loaded file will  *\n *    be in MCGA or Amiga mode as requested.  Supported source formats     *\n *    are CPS or all forms of IFF dpaint files.                            *\n *                                                                         *\n * INPUT:   filename    - Source filename.  The only files that are        *\n *                        processed as IFF are those files that end with   *\n *                        \".LBM\".                                          *\n *                                                                         *\n *          loadbuf     - Buffer type number for the temporary loading     *\n *                        buffer.  It will be trashed.                     *\n *                                                                         *\n *          destbuf     - Buffer type number for the picture to be placed. *\n *                                                                         *\n *          palette     - Palette buffer pointer.  If this value is NULL   *\n *                        then no palette is loaded.                       *\n *                                                                         *\n *          format      - Desired destination format.                      *\n *                      BM_AMIGA - Destination buffer will contain the     *\n *                                 picture in bitplane format (Amiga).     *\n *                                 The buffer will contain data equal to   *\n *                                 8K times the number of bit planes.      *\n *                                                                         *\n *                      BM_MCGA  - Destination buffer will contain the     *\n *                                 picture in MCGA format (byte per pixel).*\n *                                 The buffer will be 64K in size.         *\n *                                                                         *\n * OUTPUT:  int number of bitplanes read into the dest buffer\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1991 JLB : Created.                                             *\n *   05/20/1991 JLB : Handles Amiga and IBM destination formats.           *\n *=========================================================================*/\nint __cdecl Load_Picture(char const *filename, BufferClass& scratchbuf, BufferClass& destbuf, unsigned char *palette, PicturePlaneType format)\n{\n\tint\tfh;\t\t\t\t\t\t// Input file handle.\n\tlong\tifftype;\t\t\t\t\t// Iff form type.\n\tint\tcounter;\t\t\t\t\t// Count of the bytes decompressed.\n\tint\tvalue;\t\t\t\t\t// Working compression code value.\n\tint\tlen;\t\t\t\t\t\t// int sized length value.\n\tint\tindex;\t\t\t\t\t// Working index values.\n\tBitMapHeader_Type\tbmhd;\t\t// BMHD chunk data.\n\tIFFForm_Type\t   formtype; // ILBM, PBM.\n\tchar\t*src;\t\t\t\t\t\t // Working source body pointer.\n\tchar\t*dest;\t\t\t\t\t // Working destination body pointer.\n\n\n\t//len = strlen(filename);\n\t//strupr(filename);\n\n\tfh = Open_File(filename,READ);\n\tif (fh == WW_ERROR) return(FALSE);\n\tRead_File(fh,&ifftype,4L);\n\tClose_File(fh);\n\n\tif (ifftype != ID_FORM) {\n\t\treturn((int)Load_Uncompress(filename, scratchbuf, destbuf,  palette ) / 8000 ) ;\n\t} else {\n\n\t\tfh = Open_Iff_File(filename);\t// Opens and checks for IFF form.\n\t\tif (fh == WW_ERROR) return(FALSE);\n\n\t\tRead_File(fh, &ifftype, 4L);\n\t\tif (ifftype == ID_ILBM) {\n\t\t\tformtype = FORM_ILBM;\t\t\t\t// Inter-Leaved Bit Map.\n\t\t} else {\n\t\t\tif (ifftype == ID_PBM) {\n\t\t\t\tformtype = FORM_PBM;\t\t\t// Packed Bit Map.\n\t\t\t} else {\n\t\t\t\treturn FALSE;\t\t\t\t// Not a recognizable picture file.\n\t\t\t}\n\t\t}\n\n\t\t// Load the BMHD chunk.\n\t\tif (Read_Iff_Chunk(fh,ID_BMHD,(char*)&bmhd,sizeof(BitMapHeader_Type))) {\n\n\t\t\t#if(IBM)\n\t\t\t\t// Perform necessary IBM conversions to the data.\n\t\t\t\tbmhd.W = Reverse_Short(bmhd.W);\n\t\t\t\tbmhd.H = Reverse_Short(bmhd.H);\n\t\t\t\tbmhd.X = Reverse_Short(bmhd.X);\n\t\t\t\tbmhd.Y = Reverse_Short(bmhd.Y);\n\n\t\t\t\t// this is a mistake Xaspect and YAspect are char type\n\t\t\t\t// bmhd.XAspect = Reverse_Short(bmhd.XAspect);\n\t\t\t\t// bmhd.YAspect = Reverse_Short(bmhd.YAspect);\n\t\t\t\t  value = bmhd.XAspect\t;\n\t\t\t\t  bmhd.XAspect = bmhd.YAspect ;\n\t\t\t\t  bmhd.YAspect = ( unsigned char ) value ;\n\n\t\t\t\tbmhd.PageWidth = Reverse_Short(bmhd.PageWidth);\n\t\t\t\tbmhd.PageHeight = Reverse_Short(bmhd.PageHeight);\n\t\t\t#endif\n\n\t\t\tif (bmhd.Masking > 2) return FALSE;\t\t\t// Don't allow brushes.\n\t\t\tif (bmhd.Compression > 1) return FALSE;\t// Unknown compression.\n\n\t\t} else {\n\t\t\treturn FALSE;\t\t\t\t// Unable to read the required BMHD chunk.\n\t\t}\n\n\t\t// Load the palette if asked.\n\t\tif (palette)\n\t\t{\n\t\t\tint\tpbytes ;\t\t\t       \t// Number of CMAP bytes required.\n\t\t\tunsigned char\tcolor;\t\t\t// Palette color value.\n\t\t\tunsigned char *paletteptr;\t\t// Allocated buffer for palette conversions.\n\t\t\tunsigned char *source;\t\t  \t// Scratch source CMAP data pointer.\n\t\t\tunsigned char *dest2;\t\t  \t// Scratch destination palette pointer.\n\n\t\t\t//\tNumber of CMAP bytes that are needed.\n\t\t\tpbytes = (1 << bmhd.BPlanes) * 3;\n\n\t\t\t// Allocate the temporary palette buffer.\n\t\t\tpaletteptr = (unsigned char *)Alloc(pbytes, MEM_CLEAR);\n\t\t\tsource = paletteptr;\n\t\t\tdest2 = palette;\n\n\t\t\t//\tRead in only the bytes that are needed.\n\t\t\tpbytes = (int)Read_Iff_Chunk(fh, ID_CMAP, (char *) paletteptr, pbytes);\n\n\t\t\tif (pbytes) {\n\n\t\t\t\t/*\n\t\t\t\t** CMAP to machine specific palette conversion code.  Conversion\n\t\t\t\t**\tgoes from CMAP three bytes per color register to the machine\n\t\t\t\t**\tspecific form.\n\t\t\t\t*/\n\t\t\t\tswitch(format) {\n\t\t\t\t\tdefault:\n\t\t\t\t\tcase BM_MCGA:\n\t\t\t\t\t\t// Convert CMAP to IBM MCGA palette form.\n\t\t\t\t\t\tfor (index = 0; index < pbytes; index++) {\n\t\t\t\t\t\t\t*dest2++ = *source++ >> 2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n#if MAKE_AMIGA_ART\n\n\t\t\t\t\tcase BM_AMIGA:\n\t\t\t\t\t\t// Convert CMAP to Amiga nibble packed palette form.\n\t\t\t\t\t\tfor (index = 0; index < pbytes; index += 3) {\n\t\t\t\t\t\t\t*dest2++   = *(source++) >> 4;\n\t\t\t\t\t\t\tcolor \t = (*(source++) & 0xf0);\n\t\t\t\t\t\t\tcolor \t+= *(source++) >> 4;\n\t\t\t\t\t\t\t*dest2++\t = color;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n#endif\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tFree(paletteptr);\n\t\t}\n\n\n\t\t//\tLoad in BODY chunk.\n\t\tdest = (char *) scratchbuf.Get_Buffer();\n\t\tsrc  = (char *) destbuf.Get_Buffer();\n\n\t\tif (Read_Iff_Chunk(fh, ID_BODY, src, destbuf.Get_Size()))\n\t\t{\n\t\t\tfor (index = 0; index < (short)bmhd.H; index++)\n\t\t\t{\n\t\t\t   /* Height of source */\n\t\t\t\t//\tTransfer (possibly uncompress) one row of data.\n\t\t\t\t// PBM or ILBM reader. Bytes per row (all bitplanes).\n\n\t\t\t\tcounter = bmhd.BPlanes * (bmhd.W >> 3);\n\n\t\t\t\t//\tIf there is a mask then there is one more bitplane.\n\t\t\t\tif (bmhd.Masking == 1)\n\t\t\t\t\t\t\t\t\t\t\tcounter += bmhd.W >> 3 ;\n\n\t\t\t\tif (bmhd.Compression == 1)\n\t\t\t\t{\n\t\t\t\t   // The data is compressed.\n\t\t\t\t\t//\tDecompress one scanline (all bitplanes) at a time.\n\t\t\t\t\twhile (counter)\n\t\t\t\t\t{\n\t\t\t\t\t\tvalue = ( signed char ) *src++; \t\t\t// Decompression code.\n\t\t\t\t\t\tif (value == -128) continue;\t// NOOP code.\n\n\t\t\t\t\t\tif (value >= 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Copy N+1 bytes.\n\t\t\t\t\t\t\tlen = ((short) value) + 1;\n\n\t\t\t\t\t\t\t//\tIgnore the masking bitplane.\n\t\t\t\t\t\t\tif ( bmhd.Masking != 1 ||\n\t\t\t\t\t\t\t     (bmhd.Masking==1 && counter > ((short)bmhd.W >> 3) ) )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmemcpy(dest, src, len);\n\t\t\t\t\t\t\t\tdest += len;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcounter -= len;\n\t\t\t\t\t\t\tsrc += len;\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Replicate -N+1 bytes.\n\t\t\t\t\t\t\tlen = (-((short) value)) + 1;\n\t\t\t\t\t\t\tvalue = *src++;\n\n\t\t\t\t\t\t\t//\tIgnore the masking bitplane.\n\t\t\t\t\t\t\tif (bmhd.Masking != 1 || (bmhd.Masking==1 && counter > ((short)bmhd.W >> 3)))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmemset(dest,value,len);\n\t\t\t\t\t\t\t\tdest += len;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcounter -= len;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t   // Plain data is just copied.\n\t\t\t\t\tmemcpy(dest,src,counter);\n\t\t\t\t\tdest += counter;\n\t\t\t\t\tsrc += counter;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tPerform necessary conversions to the data in order to reach\n\t\t\t**\tthe desired format.\n\t\t\t*/\n\t\t\tswitch (format) {\n\t\t\t\tdefault:\n\t\t\t\tcase BM_MCGA:\t\t\t// Byte per pixel desired.\n\t\t\t\t\tif (formtype == FORM_ILBM) {\n\t\t\t\t\t\tILBM_To_MCGA(scratchbuf, destbuf, bmhd.BPlanes);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMem_Copy(scratchbuf.Get_Buffer(), destbuf.Get_Buffer(), 64000L);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n#if MAKE_AMIGA_ART\n\t\t\t\tcase BM_AMIGA:\t\t\t// Bitplane format desired.\n\t\t\t\t\tif (formtype == FORM_ILBM) {\n\t\t\t\t\t\tILBM_To_Amiga(scratchbuf, destbuf, bmhd.BPlanes);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tPBM_To_Amiga(scratchbuf, destbuf, bmhd.BPlanes);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n#endif\n\t\t\t}\n\t\t}\n\n\t\tClose_Iff_File(fh);\n\t}\n\n\treturn((short)bmhd.BPlanes);\t\t\t// Loaded the picture successfully.\n}\n"
  },
  {
    "path": "WIN32LIB/IFF/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = iff\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t\t&\n\tiff.obj \t\t\t&\n\tload.obj \t\t&\n\tloadpict.obj \t&\n\twritelbm.obj \t&\n\tlcwcomp.obj \t&\n\tlcwuncmp.obj \t&\n\tloadpcx.obj\t\t&\n\twritepcx.obj\t&\n\tpack2pln.obj \n\n\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WWLIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\srcdEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/IFF/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = iff\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t\tiff.obj \t\t\t\\\n\t\t\t\tload.obj\t\t\t\\\n\t\t\t\tloadpict.obj\t\\\n\t\t\t\twritelbm.obj\t\\\n\t\t\t\tlcwcomp.obj\t\t\\\n\t\t\t\tlcwuncmp.obj\t\\\n\t\t\t\tpack2pln.obj \n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) \n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n +-iff.obj \t\t\t\\\n+-load.obj\t\t\t\\\n+-loadpict.obj\t\\\n+-writelbm.obj\t\\\n+-lcwcomp.obj\t\t\\\n+-lcwuncmp.obj\t\\\n+-pack2pln.obj \n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/IFF/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = iff\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tiff.obj \t&\n\tload.obj \t&\n\tloadpict.obj \t&\n\twritelbm.obj \t&\n\tlcwcomp.obj \t&\n\tlcwuncmp.obj \t&\n\tpack2pln.obj \n\n\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WWLIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\srcdEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include \n\t copy *.inc $(%WIN32LIB)\\include \n\t copy *.cpp $(%WIN32LIB)\\srcdebug \n\t copy *.asm $(%WIN32LIB)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/IFF/PACK2PLN.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/file/rcs/pack2pln.asm 1.1 1994/04/22 18:07:46 scott_bowen Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : PACK2PLN.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen\t\t\t   *\n;*                                                                         *\n;*                   Start Date : November 20, 1991                        *\n;*                                                                         *\n;*                  Last Update : April 22, 1994   [SKB]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nLOCALS ??\n\n\n;******************************************************************************\n; External declares so these functions can be called\n;\nGLOBAL  \t\tPack_2_Plane:NEAR\n\n\tCODESEG\n\n;***************************************************************************\n;* PACK_2_PLANE -- packed to planar scanline conversion                    *\n;*                                                                         *\n;* INPUT:  BYTE *buffer (far) -- pointer to planar output buffer           *\n;*         BYTE *pageptr (far) -- pointer to current row in packed page    *\n;*         WORD planebit -- current bit used in plane -- use only low byte *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*         Return result in buffer.                                        *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/20/1991  SB : Created.                                             *\n;*   04/22/1994 SKB : Converted to 32 bit library.                         *\n;*=========================================================================*\n;\t\t\t\t\t\t\t\t\t   *\n;\tThis is the original function that is converted to asm\n;  \n;PRIVATE VOID Pack_2_Plane(UBYTE * buffer, BYTE * pageptr, BYTE planebit)\n;{\n;  WORD currbit=0x80;\t\t// current bit to be written to\n;  WORD pixel;\t  \t\t// current pixel in row used as a counter;\n;\n;  buffer--;\t\t\t// will be incremented at the start\n;  for (currbit = 0, pixel = 0; pixel < 320; pixel++) {\n;    if (!currbit) {\n;      currbit = 0x80;\t\t// reset bit 7\n;      buffer++;\t\t// go to next byte in buffer\n;      *buffer = 0;\t\t// clear byte so we only need to set bits needed\n;    }\n;  if (planebit & *pageptr++)\n;    *buffer |= currbit;\t// set bit in destination if plane was set is source\n;\n;  currbit >>= 1;\t\t// shift destination bit one right\n;  }\n;}\n\nPROC\tPack_2_Plane C NEAR \n\tUSES\tebx,ecx,esi,edi\n \tARG\tbuffer:DWORD\n\tARG\tpage:DWORD\n\tARG\tplanebit:WORD\n\n\n\tmov\tedi,[buffer]\n\tmov\tesi,[page]\n\n\tmov\tax,[planebit]\t\t; move bit set for current plane (planebit) to ax\n\t\t\t\t\t; the low byte will only be used\n\t      \n\tmov\tecx,320d\t      \t; set counter to 320 columns (320x200 picture)\n\tmov\tah,80h\t\t\t; set bit 7 of current_bit \n\tdec\tedi\t\t\t; this will get incremented at the start\n\n??top_loop:\t\t\t\t; while (columns left)\n\tcmp\tah,80h\t\t\t;   if current_bit is bit 7\n\tjnz\tshort ??same_dest\t\t\t\n\t\t\t\t\t;   Then\n\tinc\tedi\t\t\t;     buffer++  increment pointer\n\tmov\t[BYTE PTR edi],0\t;     *buffer = 0 \n\n??same_dest:\t\t\t\t;   EndIf\n\tmov\tbl,al\n\tand\tbl,[esi]\t\t;   if (planebit & *pageptr)\n\tjz\tshort ??no_set_bit\n\n\tor\t[BYTE PTR edi],ah     \t;     Then *buffer |= current_bit\n\n??no_set_bit:\n\tinc\tesi\t\t\t;   pageptr++\tgoto next in source byte\n\tror\tah,1\t\t\t;   rotate current_bit right one\n\tdec\tecx\t\t\t; \n\tjnz\t??top_loop\n\n\tret\n\n\tENDP\tPack_2_Plane\n\n\tEND\n\u001a"
  },
  {
    "path": "WIN32LIB/IFF/WRITELBM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/wwlib32/file/rcs/writelbm.cpp 1.1 1994/04/20 14:38:57 scott_bowen Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Write LBM File                           *\n *                                                                         *\n *                    File Name : writelbm.c                               *\n *                                                                         *\n *                   Programmer : Scott Bowen                              *\n *                                                                         *\n *                   Start Date :  November 18, 1991                       *\n *                                                                         *\n *                  Last Update : November 19, 1991   [SB]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Get_Line -- convert one plane of one row to a packed plane            *\n *   Write_BMHD -- writes out the bit map header (LocalHeader)             *\n *   Write_Body -- writes out compressed data in an LBM file               *\n *   Write_CMAP -- Writes out CMAP (palette) information                   *\n *   Write_LBM_File -- Writes out a file in LBM format                     *\n *   Write_Row -- compresses and writes a row plane to .lbm file           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n// At the end of this file there is an IFF definition for a .LBM file.\n\n#include \"iff.h\"\n#include \"file.h\"\n#include <wwstd.h>\n#include <stdio.h>\n#include <string.h>\n\n\n\t// A BitMapHeader is stored in a BMHD chunk.  This structure MUST be an even size\ntypedef struct {\n    unsigned short w, h;\t\t\t\t\t\t\t// raster width & height in pixels \n    unsigned short x, y;\t\t\t\t\t\t\t// position for this image\n    unsigned char planes;\t\t\t\t\t\t\t// # source bitplanes \n    unsigned char masking;\t\t\t\t\t\t\t// masking technique \n    unsigned char compression;\t\t\t\t\t// compression algoithm\n    unsigned char pad1;\t\t\t\t\t\t\t\t// UNUSED.  For consistency, put 0 here.\n    unsigned short transcolor;\t\t\t\t\t// transparent \"color number\"\n    unsigned char xaspect, yaspect;\t\t\t\t// aspect ratio, a rational number x/y\n    unsigned short pagewidth, pageheight;\t\t// source \"page\" size in pixels\n} BitMapHeaderType;\n\n\n// All values in LocalHeader are always the same except planes.  This is set in Write_BMHD\n// the short values must be in low-high order for compatibility.\n\nPRIVATE BitMapHeaderType LocalHeader = {\n\t0x4001, 0xc800, 0, 0, 0, 0,\t\t// width, height, x, y, planes, mask\n\t1,   0, 0xFF00, 5, 6, \t\t\t\t// compress, pad1, transcolor, xasptect, yaspect\n\t0x4001,\t0xC800 };\t\t\t\t\t// pagewidth, pageheight\n\n\t\n\t// Used to verify that the write of the header was valid\n#define BM_HEADER_SIZE\t\t(((sizeof(BitMapHeaderType) + 1) & 0xFFFE) + 8L)\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE long Write_BMHD(int lbmhandle, int bitplanes);\nPRIVATE long Write_CMAP(int lbmhandle, unsigned char * palette, int bitplanes);\nPRIVATE long Write_BODY(int lbmhandle, BufferClass& buff, int bitplanes);\nPRIVATE long Write_Row(int lbmhandle, unsigned char *buffer);\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * WRITE_LBM_FILE -- Writes out a file in LBM format                       *\n *                                                                         *\n * INPUT:  int lbmhandle -- lbm file handle already opened by caller      *\n *         BufferClass buff -- buff where MCGA picture is                     *\n *         int bitplane -- number of bitplanes to convert to              *\n *         char *palette -- pointer to palette for buff                    *\n *                                                                         *\n * OUTPUT: Returns BOOL -- successfull or not                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/18/1991  SB : Created.                                             *\n *=========================================================================*/\n\nPUBLIC BOOL Write_LBM_File(int lbmhandle, BufferClass& buff, int bitplanes, unsigned char *palette)\n{\n\tlong filesize;\n\n\n\tSeek_File(lbmhandle, 0L, SEEK_SET);\t\t\t\t\t\t// goto beginning of file \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\tWrite_File(lbmhandle, \"FORM????ILBM\", 12L);\t\t\t// First 12 bytes of all .lbm files \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// size is unkown so write ????\n\tfilesize = 12L; \t\t\t\t\t\t\t\t\t\t\t\t// 4 bytes for \"ILBM\" \n\n\tfilesize += Write_BMHD(lbmhandle, bitplanes);\t\t// write out BMHD (fixed size)\n\tfilesize += Write_CMAP(lbmhandle, palette, bitplanes);\t// write out CMAP \n\n\t\t// Write out the body, or compressed picture image.  This size will depend\n\t\t// on the compression, but the value passed back is what the compressor\n\t\t// assumed was written to file\n\n\tfilesize += Write_BODY(lbmhandle, buff, bitplanes);\n\n\t\t// Verify that we were able to write out the file without running out of space\n\tif (Seek_File(lbmhandle, 0L, SEEK_END) != filesize) {\n\t\treturn(FALSE);\n\t}\n\n\tSeek_File(lbmhandle, 4L, SEEK_SET);\t\t\t\t\t\t// goto beginning of file \n\tfilesize = Reverse_Long(filesize - 8L);\t\t\t\t// - 8 because of \"FORM\" + WORD (size)\n\tWrite_File(lbmhandle, (char *) &filesize, 4L);\t\t// patch in filesize \n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * WRITE_BMHD -- writes out the bit map header (LocalHeader)               *\n *                                                                         *\n * INPUT:  int lbmhandle -- file handle for lbm file                      *\n *         int pitplanes -- number of bitplanes to write out              *\n *                                                                         *\n * OUTPUT: long number of bytes hopefully written out to .LBM file         *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/19/1991  SB : Created.                                             *\n *=========================================================================*/\nPRIVATE long Write_BMHD(int lbmhandle, int bitplanes)\n{\n\tlong size;\n\t\n\tWrite_File(lbmhandle, \"BMHD\", 4L);\t\t\t\t\t// write out chunk title \n\tsize = Reverse_Long(sizeof(LocalHeader));\t\t\t// write out size of LocalHeader chunk\n\tWrite_File(lbmhandle, (char *) &size, 4L);\n\n\tLocalHeader.planes\t= bitplanes;\t\t\t\t\t// only nonconstant value in LocalHeader\n\n\t\t// Make sure size is even. Return 8 = \"BMHD\" + size of the bitmap header structure\n\n\treturn(Write_File(lbmhandle, (char *) &LocalHeader,\n\t                 (sizeof(LocalHeader) + 1) & 0xFFFE) + 8L);\n}\n\n\n/***************************************************************************\n * WRITE_CMAP -- Writes out CMAP (palette) information                     *\n *                                                                         *\n *                                                                         *\n * INPUT:  int lbmhandle -- file handle of lbm file                       *\n *         char * palette -- pointer to paletter information       \t\t\t*\n *         int bitplanes -- used to figure out size of palette            *\n *                                                                         *\n * OUTPUT: long number of bytes that should have been written out to .LBM. *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/19/1991  SB : Created.                                             *\n *=========================================================================*/\n\nPRIVATE long Write_CMAP(int lbmhandle, unsigned char * palette, int bitplanes)\n{\n\tint color, r, g, b, colors;\n\tlong size;\n\tunsigned char *pal_ptr;\n\tchar rgb[3];\n\n\n\tWrite_File(lbmhandle, \"CMAP\", 4L);\t\t\t\t\t\t// write out palette info\n\tcolors = 1 << bitplanes;\t\t\t\t\t\t\t\t\t// colors = 2 to the bitplanes\n\tsize = Reverse_Long(colors * 3L);\t\t\t\t\t\t// size = colors * 3 guns\n\n \tWrite_File(lbmhandle, (char *) &size, 4L);\n\n\tfor (pal_ptr = palette, color = 0; color < colors; color++) { // for each color\n\n\t\tif ((r = *pal_ptr++) != 0) {\t\t\t// DPaint changes allows 0 - 100 for gun values\t\t\n\t\t\tr = (r << 2) | 0x03;\t\t\t\t\t// this must be converted to 0 - 256 for LBM\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t// so LBM_val = (DP_val * 4) | 3 if DP_val != 0\n\t\tif ((g = *pal_ptr++) != 0) {\t\t\t\n\t\t\tg = (g << 2) | 0x03;\n\t\t}\n\t\tif ((b = *pal_ptr++) != 0) {\n\t\t\tb = (b << 2) | 0x03;\n\t\t}\n\t\trgb[0] = r;\t\t\t\t\t\t\t\t\t// assign gun values to an array to write out\n\t\trgb[1] = g;\n\t\trgb[2] = b;\n\t\t\n\t\tWrite_File(lbmhandle, rgb, 3L);\n\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// size = colors * 3\n\treturn(((colors << 1) + colors) + 8L);\t// total size of CMAP 8 = \"CMAP\" + WORD (size)\n}\n\n\n/***************************************************************************\n * WRITE_BODY -- writes out compressed data in an LBM file                 *\n *                                                                         *\n * INPUT: int lbmhandle -- file handle of lbm file                        *\n *                                                                         *\n * OUTPUT: long - number of byte written                                   *\n *  \t                                                                     *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/19/1991  SB : Created.                                             *\n *=========================================================================*/\n\nPRIVATE long Write_BODY(int lbmhandle, BufferClass& buff, int bitplanes)\n{\n\tlong bodysize = 0;\n\tlong actualsize;\n\tlong size;\n\tint planebit;\n\tint line, plane;\n\tunsigned char buffer[40];\n\tunsigned char *buffptr;\n\n\tWrite_File(lbmhandle, \"BODY????\", 8L);\t\t// BODY chunk ID, ???? reserved for chuncksize \n\n\tbuffptr = (unsigned char *) buff.Get_Buffer();\t\t\t\t\t\t// point to beginning of buff\n\n\tfor (line = 0; line < 200; line++) {\n\t\tplanebit = 1;\t\t\t\t\t\t\t\t\t\t\t// start with bit 1 set \n\n\t\tfor (plane = 0; plane < bitplanes; plane++) {\n\t\t\tPack_2_Plane(buffer, buffptr, planebit);\t// convert to planar\n\t\t\tbodysize += Write_Row(lbmhandle, buffer); // write to to the BODY in the LBM\n\n\t\t\tplanebit <<= 1;\t\t\t\t\t\t\t\t\t// set next bit\n\t\t}\n\n\t\tbuffptr += 320;\t\t\t\t\t\t\t\t\t\t// row size is 320\n\t}\n\n\tactualsize = bodysize + (bodysize&0x01);\n\n\tif (actualsize != bodysize) {\n\t\tWrite_File(lbmhandle, buffer, 1);\t\t// Padd the block.\n\t}\n\n\tSeek_File(lbmhandle, -(actualsize + 4L), SEEK_CUR);\t\t// Patch in chunksize\n\tsize = Reverse_Long(bodysize);\n\tWrite_File(lbmhandle, (char *) &size ,4L);\t\t\t\n\n\treturn(actualsize + 8L);\t\t// total size of BODY,  \"BODY????\" = 8 bytes\n}\n\n/***************************************************************************\n * WRITE_ROW -- compresses and writes a row plane to .lbm file             *\n *                                                                         *\n * INPUT:  int lbmhandle -- lbm file handle                               *\n *         unsigned char *buffer -- pointer to buffer to be written out            *\n *                                                                         *\n * OUTPUT: long size of chunk that should have been written out            *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/19/1991  SB : Created.                                             *\n *=========================================================================*/\n// this algorithm was taken from WILBM.c written by EA that was in the\n// 1985 yearbook.  This is the compression method that DP.EXE uses.\n// Change only if DP.EXE changes.\n\nPRIVATE long Write_Row(int lbmhandle, unsigned char *buffer)\n{\n\tint i;\n\tint chunksize = 0;\n\tint dataLength = 40;\t  \t\t\t\t\t// 320 rows / 8 ( 1 plane per row)\n\tunsigned char repCode, current, curr_plus_2;\n\tunsigned char *buffptr;\n\n\twhile (dataLength) {\n\n  \t\t// If at least 2 more bytes and they are equal, then replicate \n\n\t\tif ((dataLength >= 2) && (buffer[0] == buffer[1])) {\n\t\t\tbuffptr = buffer;\n\t\t\tfor (i = 0; (i <= 128) &&  (i < (dataLength - 1)); i++) {\n\t\t\t\tif (*buffptr != buffptr[1]) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbuffptr++;\n\t\t\t}\n\t\t\ti++;\n\t\t\trepCode = -i + 1;\n\t\t\tWrite_File(lbmhandle, &repCode, 1L);\t\t\t// Write count as -count+1\n\t\t\tWrite_File(lbmhandle, buffer,   1L);\t\t\t// Write byte to replicate\n\t\t\tbuffer += i;\n\t\t\tdataLength -= i;\n\t\t\tchunksize  += 2;\n\n\t\t}\n\t\telse { // Copy literally till 3 byte run or two 2 byte runs found \n\n\t\t\tfor (i = 0; (i <= 128) && (i < dataLength); i++) {\n\t\t\t\tcurrent     = buffer[i];\n\t\t\t\tcurr_plus_2 = buffer[i + 2];\n\n\t\t\t\tif (i == dataLength - 1)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (current != buffer[i + 1])\n\t\t\t\t\tcontinue;\n\t\t\t\tif (i == dataLength - 2)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (current == curr_plus_2)\n\t\t\t\t\tbreak;\n\t\t\t\tif (i == dataLength - 3)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (curr_plus_2 == buffer[i + 3])\n\t\t\t\t\t break;\n\t\t\t}\n\t\t\trepCode = i - 1;\n\t\t\tWrite_File(lbmhandle, &repCode, 1L);\t\t\t// Write count as count-1 \n\t\t\tWrite_File(lbmhandle, buffer, (long) i);\t\t// Write 'count' bytes\n\t\t\tbuffer += i;\n\t\t\tdataLength -= i;\n\t\t\tchunksize += i + 1;\n\t\t}\n\t}  // end while\n\n\treturn(chunksize);\n}\n\n\n#if(FALSE)\n\nThis is a definition of a DPII .LBM file.\nBelow this definition are differences in DPIIe .LMB files.\n\nCreated by : Scott K. Bowen Nov 18, 1991\n\t\nStart with .LBM to read definition :\n\n.LBM\t\t-> \"FORM\" + FILESIZE + \"ILMB\" + CHUNKS\n\nBITPLANES\t-> (word) // number of bit planes used\nBLUE\t\t\t-> (byte) // blue color gun value\nBMHD \t\t\t-> \"BMHD\" + CHUNKSIZE + CONTEXT\nBODY\t\t\t->\n\nCHUNKS\t\t-> BMHD | BODY | CMAP | DPPV | CRNG | ????\nCHUNKSIZE\t-> (long) // size of chunk not including header or size.\nCMAP\t\t\t-> \"CMAP\" + CHUNKSIZE + PALETTE_INFO\nCOMPRESS_METHOD -> (byte) // compression method used\nCONTEXT\t\t-> WIDTH + HEIGHT + POSX + POSY + #_BITPLANES + MASKING +\n\t\t\t\t   COMPRESS_METHOD + PAD + TRANS_COL + XASPECT + YASPECT +\n\t\t\t\t\tPAGEWIDTH + PAGEHEIGHT\nCRNG\t\t\t-> // we do not use\n\nDPPV\t\t\t-> // we do not use\n\nFILESIZE\t\t-> (long)   //size of file minus (sizeof(FORM) + sizeof(FILESIZE)\n\nGREEN\t\t\t-> (byte) // green color gun value\n\nHEIGHT\t\t-> (word) // of picture\n\nMASKING\t\t-> (byte) // masking type ?\n\nNUM_COLORS\t-> //number of colors used depending on format\n\nPAGE_WIDTH\t-> (word) // width of page\nPAGE_HEIGHT\t-> (word) // height of page\nPALETTE_INFO-> (RED+GREEN+BLUE) @ NUM_COLORS\nPAD \t\t\t-> (byte) // not used.  used as a padding\nPOSX \t\t\t-> (word) // staring position\nPOSY\t\t\t-> (word) // staring position\n\nRED\t\t\t-> (byte) // red color gun value\n\nTRANS_COL\t-> (word) // transparrent color\n\nWIDTH\t\t\t-> (word) // of picture \n\nXASPECT\t\t-> (byte) // x aspect ratio\n\nYASPECT\t\t-> (byte) // y aspect ratio\n\n????\t\t\t-> // other possibilities\n\n\nDifferences in DPII enhance version\n\n.LBM \t\t-> \"FORM\" + FILESIZE + \"PBM \" + CHUNKS\nDPPV\t\t-> DPPS\t\t// uses dpps instead of dppv\nCHUNKS\t\t-> + TINY\t// add these to old definition\n \n\n\n\n#endif\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/IFF/WRITEPCX.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : iff                                      *\n *                                                                         *\n *                    File Name : WRITEPCX.CPP                             *\n *                                                                         *\n *                   Programmer : Julio R. Jerez                           *\n *                                                                         *\n *                   Start Date : May 2, 1995                              *\n *                                                                         *\n *                  Last Update : May 2, 1995   [JRJ]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * int Save_PCX_File (char* name, GraphicViewPortClass& pic, char* palette)*\n *= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n#include  <wwlib32.h>\n#include \"filepcx.h\"\n#include <wwmem.h>\nstatic void Write_Pcx_ScanLine ( int file_handle , int scansize , char * ptr );\n\n\n/***************************************************************************\n * WRITE_PCX_FILE -- Write the data in ViewPort to a pcx file              *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:  name is a NULL terminated string of the fromat [xxxx.pcx]\t\t\t*\n *\t\t\t  pic\t is a pointer to a GraphicViewPortClass or to a \t\t\t\t*\n *\t\t\t\t\t GraphicBufferClass holding the picture. \t\t\t\t\t\t\t*\n *        palette is a pointer the the memry block holding the color \t\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *              palette of the picture.                                    *\n *                                                                         *\n * OUTPUT: FALSE  if the function fails zero otherwise             \t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/04/1995 JRJ : Created.                                             *\n *   08/01/1995 SKB : Copy the palette so it is not modified.              *\n *=========================================================================*/\nint Write_PCX_File (char* name, GraphicViewPortClass& pic, unsigned char* palette )\n{\n \tunsigned char palcopy[256 * 3];\n\tunsigned     i ;\n\tunsigned\t   width ;\n\tint \t      file_handle ;\n\tint\t\t\t\tVP_Scan_Line ;\n\tchar\t     * ptr ;\n\tRGB  \t\t  * pal ;\n\tGraphicBufferClass\t* Graphic_Buffer ;\n\tPCX_HEADER   header = { 10 , 5 , 1 , 8 , 0 , 0 , 319 , 199 ,\n\t\t\t\t\t\t\t\t\t320 , 200 , { 0 } , 0 , 1 , 320 , 1 , {0} } ;\n\n\t// Open file name\n\tfile_handle = Open_File ( name , WRITE ) ;\n\tif ( file_handle == ERROR ) return FALSE ;\n\n\n\theader.width  = pic.Get_Width() - 1 ;\n\theader.height = pic.Get_Height() - 1 ;\n\theader.byte_per_line = pic.Get_Width() ;\n\tWrite_File ( file_handle, & header , sizeof (PCX_HEADER)) ;\n\n\tVP_Scan_Line = pic.Get_Width()\t+ pic.Get_XAdd();\n\tGraphic_Buffer = pic.Get_Graphic_Buffer() ;\n\tptr = ( char * ) Graphic_Buffer->Get_Buffer() ;\n\tptr += ( (pic.Get_YPos() * VP_Scan_Line) + pic.Get_XPos() );\n\n\tfor ( i = 0 ; i < header.height + 1 ; i ++ )\n   \tWrite_Pcx_ScanLine ( file_handle , header.byte_per_line, ptr + i * VP_Scan_Line ) ;\n\n\tMem_Copy(palette, palcopy, 256 * 3);\n\tpal = ( RGB * ) palcopy ;\n\tfor ( i = 0 ; i < 256 ; i ++ ) {\n\t\tpal -> red <<= 2 ;\n\t\tpal -> green <<= 2 ;\n\t\tpal -> blue <<= 2 ;\n\t\tpal ++ ;\n\t}\n\ti = 0x0c ;\n\tWrite_File ( file_handle, & i , 1 ) ;\n\tWrite_File ( file_handle, palcopy , 256 * sizeof (RGB) ) ;\n\tClose_File (file_handle) ;\n\treturn 0 ;\n}\n\n\n\n\n/***************************************************************************\n * WRITE_PCX_SCANLINE -- function to write a single pcx scanline to a file *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/04/1995 JRJ : Created.                                             *\n *=========================================================================*/\n\n#define\tPOOL_SIZE 2048\n#define WRITE_CHAR(x) {\t\\\n\t\t\t\t\t\t\t\t* file_ptr ++ = x ; \\\n\t\t\t\t\t\t\t   if ( file_ptr >= & pool [ POOL_SIZE ]\t) { \\\n\t\t\t\t\t\t\t\t  Write_File ( file_handle, pool , POOL_SIZE ) ; \\\n\t\t\t\t\t\t\t\t  file_ptr = pool ; \\\n\t\t\t\t\t\t\t }\t}\n\n\nvoid Write_Pcx_ScanLine ( int file_handle , int scansize , char * ptr )\n{\n\tunsigned     i ;\n\tunsigned     rle ;\n\tunsigned     color ;\n\tunsigned\t\tlast ;\n\tchar\t\t  * file_ptr ;\n\tchar\t\t \tpool [ POOL_SIZE ] ;\n\n\tfile_ptr = pool ;\n\tlast = * ptr ;\n\trle = 1 ;\n\n\tfor ( i = 1 ; i < scansize ; i ++ ) {\n   \tcolor = 0xff & * ++ ptr ;\n\t\tif ( color == last ) {\n\t\t\trle ++ ;\n\t\t\tif ( rle == 63 )\t {\n\t\t\t\tWRITE_CHAR ( 255 ) ;\n\t\t\t\tWRITE_CHAR ( color ) ;\n\t\t\t\trle = 0 ;\n\t\t\t}\n\t\t} else {\n\t  \t\tif ( rle ) {\n\t\t \t\tif ( rle == 1 && ( 192 != ( 192 & last ))) {\n\t\t\t   \tWRITE_CHAR ( last ) ;\n\t\t     \t} else {\n\t\t      \tWRITE_CHAR ( rle | 192 ) ;\n\t     \t   \tWRITE_CHAR ( last ) ;\n\t\t\t\t}\n\t\t\t}\n\t\t\tlast = color ;\n\t\t\trle = 1 ;\n\t\t}\n\t}\n\tif ( rle ) {\n\t\tif ( rle == 1 && ( 192 != ( 192 & last ))) {\n\t\t\tWRITE_CHAR ( last ) ;\n\t\t} else {\n\t\t\tWRITE_CHAR ( rle | 192 ) ;\n\t   \tWRITE_CHAR ( last) ;\n\t\t}\n\t}\n\n\tWrite_File ( file_handle, pool , ( int ) file_ptr - ( int ) pool ) ;\n}\n\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/AUDIO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : AUDIO.H                                  *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : March 10, 1995                           *\n *                                                                         *\n *                  Last Update : March 10, 1995   [PWG]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwstd.h\"\n\n/*=========================================================================*/\n/* AUD file header type\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tAUD_FLAG_STEREO\t1\n#define\tAUD_FLAG_16BIT\t\t2\n\n// PWG 3-14-95: This structure used to have bit fields defined for Stereo\n//   and Bits.  These were removed because watcom packs them into a 32 bit\n//   flag entry even though they could have fit in a 8 bit entry.\n#pragma pack(1);\ntypedef struct {\n\tunsigned short int\tRate;\t\t\t\t// Playback rate (hertz).\n\tlong\tSize;\t\t\t\t// Size of data (bytes).\n\tlong\tUncompSize;\t\t\t\t// Size of data (bytes).\n\tunsigned char Flags;\t// Holds flags for info\n\t\t\t\t\t\t\t\t//  1: Is the sample stereo?\n\t\t\t\t\t\t\t\t//  2: Is the sample 16 bits?\n\tunsigned char Compression;\t// What kind of compression for this sample?\n} AUDHeaderType;\n\n\n/*=========================================================================*/\n/*\tThere can be a different sound driver for sound effects, digitized\t\t*/\n/*\tsamples, and musical scores.  Each one must be of these specified\t\t\t*/\n/*\ttypes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\ntypedef enum {\n\tSAMPLE_NONE,\t\t// No digitized sounds will be played.\n\tSAMPLE_SB,\t\t\t// Sound Blaster digitized driver.\n\tSAMPLE_SBPRO,\t\t// Sound Blaster Pro digitized driver.\n\tSAMPLE_PAS,\t\t\t// Pro-Audio Spectrum digitized driver.\n\tSAMPLE_ADLIBG,\t\t// Adlib-Gold digitized driver.\n\tSAMPLE_TANDY,\t\t// Tandy 'compatible' driver.\n\tSAMPLE_PCSPKR,\t\t// PC speaker digitized driver (The Audio Solution driver).\n\tSAMPLE_ADLIB,\t\t// Adlib digitized driver (The Audio Solution driver).\n\tSAMPLE_TEMP=0x1000,\n\tSAMPLE_LAST\n} Sample_Type;\n\ntypedef enum {\n\tSCORE_NONE,\t\t\t// No scores will be played.\n\tSCORE_ALFX,\t\t\t// Westwood's ALFX adlib compatable driver.\n\tSCORE_WWPCSPKR,\t// Westwood's PC-speaker driver (obsolete).\n\tSCORE_WWTANDY,\t\t// Westwood's PC-speaker driver with Tandy mod (obsolete).\n\tSCORE_PCSPKR,\t\t// PC speaker XMIDI driver.\n\tSCORE_TANDY,\t\t// Tandy XMIDI driver.\n\tSCORE_MT32,\t\t\t// MT-32 / LAPC-1 Roland XMIDI driver.\n\tSCORE_CANVAS,\t\t// Sound Canvas SC-55.\n\tSCORE_ADLIB,\t\t// Adlib XMIDI driver.\n\tSCORE_ADLIBG,\t\t// Adlib Gold XMIDI driver.\n\tSCORE_PASFM,\t\t// Pro Audio Spectrum XMIDI driver.\n\tSCORE_SBFM,\t\t\t// Sound Blaster XMIDI driver.\n\tSCORE_SBP1FM,\t\t// Sound Blaster Pro (YM3812) XMIDI driver.\n\tSCORE_SBP2FM,\t\t// Sound Blaster Pro (OPL3) XMIDI driver (Can't use with SFX_ALFX).\n\tSCORE_TEMP=0x1000,\n\tSCORE_LAST\n} Score_Type;\n\ntypedef enum {\n\tSFX_NONE,\t\t\t// No sound effects will be played.\n\tSFX_ALFX,\t\t\t// Westwood's ALFX adlib compatable driver.\n\tSFX_WWPCSPKR,\t\t// Westwood's PC-speaker driver.\n\tSFX_WWTANDY,\t\t// Westwood's PC-speaker driver with Tandy mod.\n\tSFX_PCSPKR,\t\t\t// PC speaker XMIDI driver.\n\tSFX_TANDY,\t\t\t// Tandy XMIDI driver.\n\tSFX_MT32,\t\t\t// MT-32 / LAPC-1 Roland XMIDI driver.\n\tSFX_CANVAS,\t\t\t// Sound Canvas SC-55.\n\tSFX_ADLIB,\t\t\t// Adlib XMIDI driver.\n\tSFX_ADLIBG,\t\t\t// Adlib Gold XMIDI driver.\n\tSFX_PASFM,\t\t\t// Pro Audio Spectrum XMIDI driver.\n\tSFX_SBFM,\t\t\t// Sound Blaster XMIDI driver.\n\tSFX_SBP1FM,\t\t\t// Sound Blaster Pro (YM3812) XMIDI driver.\n\tSFX_SBP2FM,\t\t\t// Sound Blaster Pro (OPL3) XMIDI driver.\n\tSFX_TEMP=0x1000,\n\tSFX_LAST\n} SFX_Type;\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SOUNDIO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nint File_Stream_Sample(char const *filename, BOOL real_time_start = FALSE);\nint File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start = FALSE);\nvoid __cdecl Sound_Callback(void);\nvoid __cdecl far maintenance_callback(void);\nvoid *Load_Sample(char const *filename);\nlong Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);\nlong Sample_Read(int fh, void *buffer, long size);\nvoid Free_Sample(void const *sample);\nBOOL Audio_Init( HWND window , int bits_per_sample, BOOL stereo , int rate , int reverse_channels);\nvoid Sound_End(void);\nvoid Stop_Sample(int handle);\nBOOL Sample_Status(int handle);\nBOOL Is_Sample_Playing(void const * sample);\nvoid Stop_Sample_Playing(void const * sample);\nint Play_Sample(void const *sample, int priority=0xFF, int volume=0xFF, signed short panloc = 0x0);\nint Play_Sample_Handle(void const *sample, int priority, int volume, signed short panloc, int id);\nint Set_Sound_Vol(int volume);\nint Set_Score_Vol(int volume);\nvoid Fade_Sample(int handle, int ticks);\nint Get_Free_Sample_Handle(int priority);\nint Get_Digi_Handle(void);\nlong Sample_Length(void const *sample);\nvoid Restore_Sound_Buffers (void);\nBOOL Set_Primary_Buffer_Format(void);\nBOOL Start_Primary_Sound_Buffer (BOOL forced);\nvoid Stop_Primary_Sound_Buffer (void);\n\n/*\n** Function to call if we detect focus loss\n*/\nextern\tvoid (*Audio_Focus_Loss_Function)(void);\n\n\nextern int Misc;\nextern SFX_Type SoundType;\nextern Sample_Type SampleType;\n\nextern CRITICAL_SECTION\tGlobalAudioCriticalSection;\n\nextern int StreamLowImpact;\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/BUFFER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : GBUFFER.H                                *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 26, 1994                             *\n *                                                                         *\n *                  Last Update : July 5, 1994   [PWG]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   BC::Get_Size -- Returns the buffer size of the BufferClass instance   *\n *   BC::Get_Buffer -- Returns pointer to buffer inherent to BufferClass \t*\n *   BC::BufferClass -- inline constructor for BufferClass with size only  *\n *   BC::To_Page -- Copys a buffer class to a page with definable x, y, w, h*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BUFFER_H\n#define BUFFER_H\n\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\nclass GraphicViewPortClass;\n\n/*=========================================================================*/\n/* BufferClass - A base class which holds buffer information including a\t*/\n/*\t\tpointer and the size of the buffer.\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nclass BufferClass {\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBufferClass(void *ptr, long size);\n\t\tBufferClass(long size);\n\t\tBufferClass();\n\t\t~BufferClass();\n\t\t/*===================================================================*/\n\t\t/* Define functions which work with the buffer class.\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong To_Page(GraphicViewPortClass &view);\n\t\tlong To_Page(int w, int h, GraphicViewPortClass &view);\n\t\tlong To_Page(int x, int y, int w, int h, GraphicViewPortClass &view);\n\n\t\t/*===================================================================*/\n\t\t/* define functions to get at the protected data members\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tvoid\t*Get_Buffer(void);\n\t\tlong\tGet_Size(void);\n\n\tprivate:\n\t\t/*===================================================================*/\n\t\t/* Define the operators we do not want to happen which are the copy\t*/\n\t\t/* and equal constructors.  These are bad because the Allocated flag\t*/\n\t\t/*\tcould be copied and the associated buffer freed.  If this were to\t*/\n\t\t/*\tgappen it could cause weird general protection fault.\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBufferClass(BufferClass const &);\n\t\tBufferClass &operator=(BufferClass const &);\n\n\tprotected:\n\t\tvoid\t*Buffer;\n\t\tlong\tSize;\n\t\tBOOL\tAllocated;\n};\n/***************************************************************************\n * BC::GET_SIZE -- Returns the buffer size of the BufferClass instance     *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long the size of the buffer                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::Get_Size(void)\n{\n\treturn(Size);\n}\n/***************************************************************************\n * BC::GET_BUFFER -- Returns pointer to buffer inherent to BufferClass \t\t*\n *                                                                         *\n * INPUT:\t\t\tnone                                                     *\n *                                                                         *\n * OUTPUT:        void * to the inherent buffer.                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline void *BufferClass::Get_Buffer(void)\n{\n\treturn(Buffer);\n}\n#endif\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/DEFINES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 Example                          *\n *                                                                         *\n *                    File Name : DEFINES.H                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\n#define USER_TIMER_FREQ\t\t60\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/DESCMGMT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 library                          *\n *                                                                         *\n *                    File Name : DESCMGMT.H                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef DESCMGMT_H\n#define DESCMGMT_H\n\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n//=====================================================================\n// C type include files\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <dos.h>\n#include <bios.h>\n\n#ifdef __cplusplus\n}\n#endif\n\n// ====================================================================\n\n\n// types\n// These where taken from dos.h\n//==========================================\n\n// external functions\n// ===================================================\nextern ULONG Map_Segment_To_Address(ULONG address, ULONG length);\n\nextern \"C\" {\n\t// Assemble functions\n\textern UWORD FixSelector(UWORD sel);\n\textern UWORD GetDs(void);\n\textern UWORD GetCs(void);\n\textern VOID  GetDefaultSelectors(VOID);\n\textern UWORD Get_Standard_Selector(void);\n\n\t\n\t// Assembly data variables\n\textern UWORD CodeSelector;\n\textern UWORD DataSelector;\n\textern UWORD ScreenSelector;\n\textern UWORD GraphicsSelector;\n\textern UWORD PspSelector;\n\textern UWORD EnvSelector;\n\textern UWORD DosMemSelector;\n\textern UWORD Fp1167Selector;\n\textern UWORD FpWeitekSelector;\n\textern UWORD FpCyrixSelector;\n}\n\n#endif  // DESCMGMT_H\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/DIFFTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* dwDiffTable - ADPCM Lookup table for sample differences\n;****************************************************************************\n\n\t\talign\t4\n\ndwDiffTable\tDD\t0\t; Index = 0 Token = 0\n\t\tDD\t1\t; Index = 0 Token = 1\n\t\tDD\t3\t; Index = 0 Token = 2\n\t\tDD\t4\t; Index = 0 Token = 3\n\t\tDD\t7\t; Index = 0 Token = 4\n\t\tDD\t8\t; Index = 0 Token = 5\n\t\tDD\t10\t; Index = 0 Token = 6\n\t\tDD\t11\t; Index = 0 Token = 7\n\t\tDD\t0\t; Index = 0 Token = 8\n\t\tDD\t-1\t; Index = 0 Token = 9\n\t\tDD\t-3\t; Index = 0 Token = 10\n\t\tDD\t-4\t; Index = 0 Token = 11\n\t\tDD\t-7\t; Index = 0 Token = 12\n\t\tDD\t-8\t; Index = 0 Token = 13\n\t\tDD\t-10\t; Index = 0 Token = 14\n\t\tDD\t-11\t; Index = 0 Token = 15\n\t\tDD\t1\t; Index = 1 Token = 0\n\t\tDD\t3\t; Index = 1 Token = 1\n\t\tDD\t5\t; Index = 1 Token = 2\n\t\tDD\t7\t; Index = 1 Token = 3\n\t\tDD\t9\t; Index = 1 Token = 4\n\t\tDD\t11\t; Index = 1 Token = 5\n\t\tDD\t13\t; Index = 1 Token = 6\n\t\tDD\t15\t; Index = 1 Token = 7\n\t\tDD\t-1\t; Index = 1 Token = 8\n\t\tDD\t-3\t; Index = 1 Token = 9\n\t\tDD\t-5\t; Index = 1 Token = 10\n\t\tDD\t-7\t; Index = 1 Token = 11\n\t\tDD\t-9\t; Index = 1 Token = 12\n\t\tDD\t-11\t; Index = 1 Token = 13\n\t\tDD\t-13\t; Index = 1 Token = 14\n\t\tDD\t-15\t; Index = 1 Token = 15\n\t\tDD\t1\t; Index = 2 Token = 0\n\t\tDD\t3\t; Index = 2 Token = 1\n\t\tDD\t5\t; Index = 2 Token = 2\n\t\tDD\t7\t; Index = 2 Token = 3\n\t\tDD\t10\t; Index = 2 Token = 4\n\t\tDD\t12\t; Index = 2 Token = 5\n\t\tDD\t14\t; Index = 2 Token = 6\n\t\tDD\t16\t; Index = 2 Token = 7\n\t\tDD\t-1\t; Index = 2 Token = 8\n\t\tDD\t-3\t; Index = 2 Token = 9\n\t\tDD\t-5\t; Index = 2 Token = 10\n\t\tDD\t-7\t; Index = 2 Token = 11\n\t\tDD\t-10\t; Index = 2 Token = 12\n\t\tDD\t-12\t; Index = 2 Token = 13\n\t\tDD\t-14\t; Index = 2 Token = 14\n\t\tDD\t-16\t; Index = 2 Token = 15\n\t\tDD\t1\t; Index = 3 Token = 0\n\t\tDD\t3\t; Index = 3 Token = 1\n\t\tDD\t6\t; Index = 3 Token = 2\n\t\tDD\t8\t; Index = 3 Token = 3\n\t\tDD\t11\t; Index = 3 Token = 4\n\t\tDD\t13\t; Index = 3 Token = 5\n\t\tDD\t16\t; Index = 3 Token = 6\n\t\tDD\t18\t; Index = 3 Token = 7\n\t\tDD\t-1\t; Index = 3 Token = 8\n\t\tDD\t-3\t; Index = 3 Token = 9\n\t\tDD\t-6\t; Index = 3 Token = 10\n\t\tDD\t-8\t; Index = 3 Token = 11\n\t\tDD\t-11\t; Index = 3 Token = 12\n\t\tDD\t-13\t; Index = 3 Token = 13\n\t\tDD\t-16\t; Index = 3 Token = 14\n\t\tDD\t-18\t; Index = 3 Token = 15\n\t\tDD\t1\t; Index = 4 Token = 0\n\t\tDD\t3\t; Index = 4 Token = 1\n\t\tDD\t6\t; Index = 4 Token = 2\n\t\tDD\t8\t; Index = 4 Token = 3\n\t\tDD\t12\t; Index = 4 Token = 4\n\t\tDD\t14\t; Index = 4 Token = 5\n\t\tDD\t17\t; Index = 4 Token = 6\n\t\tDD\t19\t; Index = 4 Token = 7\n\t\tDD\t-1\t; Index = 4 Token = 8\n\t\tDD\t-3\t; Index = 4 Token = 9\n\t\tDD\t-6\t; Index = 4 Token = 10\n\t\tDD\t-8\t; Index = 4 Token = 11\n\t\tDD\t-12\t; Index = 4 Token = 12\n\t\tDD\t-14\t; Index = 4 Token = 13\n\t\tDD\t-17\t; Index = 4 Token = 14\n\t\tDD\t-19\t; Index = 4 Token = 15\n\t\tDD\t1\t; Index = 5 Token = 0\n\t\tDD\t4\t; Index = 5 Token = 1\n\t\tDD\t7\t; Index = 5 Token = 2\n\t\tDD\t10\t; Index = 5 Token = 3\n\t\tDD\t13\t; Index = 5 Token = 4\n\t\tDD\t16\t; Index = 5 Token = 5\n\t\tDD\t19\t; Index = 5 Token = 6\n\t\tDD\t22\t; Index = 5 Token = 7\n\t\tDD\t-1\t; Index = 5 Token = 8\n\t\tDD\t-4\t; Index = 5 Token = 9\n\t\tDD\t-7\t; Index = 5 Token = 10\n\t\tDD\t-10\t; Index = 5 Token = 11\n\t\tDD\t-13\t; Index = 5 Token = 12\n\t\tDD\t-16\t; Index = 5 Token = 13\n\t\tDD\t-19\t; Index = 5 Token = 14\n\t\tDD\t-22\t; Index = 5 Token = 15\n\t\tDD\t1\t; Index = 6 Token = 0\n\t\tDD\t4\t; Index = 6 Token = 1\n\t\tDD\t7\t; Index = 6 Token = 2\n\t\tDD\t10\t; Index = 6 Token = 3\n\t\tDD\t14\t; Index = 6 Token = 4\n\t\tDD\t17\t; Index = 6 Token = 5\n\t\tDD\t20\t; Index = 6 Token = 6\n\t\tDD\t23\t; Index = 6 Token = 7\n\t\tDD\t-1\t; Index = 6 Token = 8\n\t\tDD\t-4\t; Index = 6 Token = 9\n\t\tDD\t-7\t; Index = 6 Token = 10\n\t\tDD\t-10\t; Index = 6 Token = 11\n\t\tDD\t-14\t; Index = 6 Token = 12\n\t\tDD\t-17\t; Index = 6 Token = 13\n\t\tDD\t-20\t; Index = 6 Token = 14\n\t\tDD\t-23\t; Index = 6 Token = 15\n\t\tDD\t1\t; Index = 7 Token = 0\n\t\tDD\t4\t; Index = 7 Token = 1\n\t\tDD\t8\t; Index = 7 Token = 2\n\t\tDD\t11\t; Index = 7 Token = 3\n\t\tDD\t15\t; Index = 7 Token = 4\n\t\tDD\t18\t; Index = 7 Token = 5\n\t\tDD\t22\t; Index = 7 Token = 6\n\t\tDD\t25\t; Index = 7 Token = 7\n\t\tDD\t-1\t; Index = 7 Token = 8\n\t\tDD\t-4\t; Index = 7 Token = 9\n\t\tDD\t-8\t; Index = 7 Token = 10\n\t\tDD\t-11\t; Index = 7 Token = 11\n\t\tDD\t-15\t; Index = 7 Token = 12\n\t\tDD\t-18\t; Index = 7 Token = 13\n\t\tDD\t-22\t; Index = 7 Token = 14\n\t\tDD\t-25\t; Index = 7 Token = 15\n\t\tDD\t2\t; Index = 8 Token = 0\n\t\tDD\t6\t; Index = 8 Token = 1\n\t\tDD\t10\t; Index = 8 Token = 2\n\t\tDD\t14\t; Index = 8 Token = 3\n\t\tDD\t18\t; Index = 8 Token = 4\n\t\tDD\t22\t; Index = 8 Token = 5\n\t\tDD\t26\t; Index = 8 Token = 6\n\t\tDD\t30\t; Index = 8 Token = 7\n\t\tDD\t-2\t; Index = 8 Token = 8\n\t\tDD\t-6\t; Index = 8 Token = 9\n\t\tDD\t-10\t; Index = 8 Token = 10\n\t\tDD\t-14\t; Index = 8 Token = 11\n\t\tDD\t-18\t; Index = 8 Token = 12\n\t\tDD\t-22\t; Index = 8 Token = 13\n\t\tDD\t-26\t; Index = 8 Token = 14\n\t\tDD\t-30\t; Index = 8 Token = 15\n\t\tDD\t2\t; Index = 9 Token = 0\n\t\tDD\t6\t; Index = 9 Token = 1\n\t\tDD\t10\t; Index = 9 Token = 2\n\t\tDD\t14\t; Index = 9 Token = 3\n\t\tDD\t19\t; Index = 9 Token = 4\n\t\tDD\t23\t; Index = 9 Token = 5\n\t\tDD\t27\t; Index = 9 Token = 6\n\t\tDD\t31\t; Index = 9 Token = 7\n\t\tDD\t-2\t; Index = 9 Token = 8\n\t\tDD\t-6\t; Index = 9 Token = 9\n\t\tDD\t-10\t; Index = 9 Token = 10\n\t\tDD\t-14\t; Index = 9 Token = 11\n\t\tDD\t-19\t; Index = 9 Token = 12\n\t\tDD\t-23\t; Index = 9 Token = 13\n\t\tDD\t-27\t; Index = 9 Token = 14\n\t\tDD\t-31\t; Index = 9 Token = 15\n\t\tDD\t2\t; Index = 10 Token = 0\n\t\tDD\t6\t; Index = 10 Token = 1\n\t\tDD\t11\t; Index = 10 Token = 2\n\t\tDD\t15\t; Index = 10 Token = 3\n\t\tDD\t21\t; Index = 10 Token = 4\n\t\tDD\t25\t; Index = 10 Token = 5\n\t\tDD\t30\t; Index = 10 Token = 6\n\t\tDD\t34\t; Index = 10 Token = 7\n\t\tDD\t-2\t; Index = 10 Token = 8\n\t\tDD\t-6\t; Index = 10 Token = 9\n\t\tDD\t-11\t; Index = 10 Token = 10\n\t\tDD\t-15\t; Index = 10 Token = 11\n\t\tDD\t-21\t; Index = 10 Token = 12\n\t\tDD\t-25\t; Index = 10 Token = 13\n\t\tDD\t-30\t; Index = 10 Token = 14\n\t\tDD\t-34\t; Index = 10 Token = 15\n\t\tDD\t2\t; Index = 11 Token = 0\n\t\tDD\t7\t; Index = 11 Token = 1\n\t\tDD\t12\t; Index = 11 Token = 2\n\t\tDD\t17\t; Index = 11 Token = 3\n\t\tDD\t23\t; Index = 11 Token = 4\n\t\tDD\t28\t; Index = 11 Token = 5\n\t\tDD\t33\t; Index = 11 Token = 6\n\t\tDD\t38\t; Index = 11 Token = 7\n\t\tDD\t-2\t; Index = 11 Token = 8\n\t\tDD\t-7\t; Index = 11 Token = 9\n\t\tDD\t-12\t; Index = 11 Token = 10\n\t\tDD\t-17\t; Index = 11 Token = 11\n\t\tDD\t-23\t; Index = 11 Token = 12\n\t\tDD\t-28\t; Index = 11 Token = 13\n\t\tDD\t-33\t; Index = 11 Token = 14\n\t\tDD\t-38\t; Index = 11 Token = 15\n\t\tDD\t2\t; Index = 12 Token = 0\n\t\tDD\t7\t; Index = 12 Token = 1\n\t\tDD\t13\t; Index = 12 Token = 2\n\t\tDD\t18\t; Index = 12 Token = 3\n\t\tDD\t25\t; Index = 12 Token = 4\n\t\tDD\t30\t; Index = 12 Token = 5\n\t\tDD\t36\t; Index = 12 Token = 6\n\t\tDD\t41\t; Index = 12 Token = 7\n\t\tDD\t-2\t; Index = 12 Token = 8\n\t\tDD\t-7\t; Index = 12 Token = 9\n\t\tDD\t-13\t; Index = 12 Token = 10\n\t\tDD\t-18\t; Index = 12 Token = 11\n\t\tDD\t-25\t; Index = 12 Token = 12\n\t\tDD\t-30\t; Index = 12 Token = 13\n\t\tDD\t-36\t; Index = 12 Token = 14\n\t\tDD\t-41\t; Index = 12 Token = 15\n\t\tDD\t3\t; Index = 13 Token = 0\n\t\tDD\t9\t; Index = 13 Token = 1\n\t\tDD\t15\t; Index = 13 Token = 2\n\t\tDD\t21\t; Index = 13 Token = 3\n\t\tDD\t28\t; Index = 13 Token = 4\n\t\tDD\t34\t; Index = 13 Token = 5\n\t\tDD\t40\t; Index = 13 Token = 6\n\t\tDD\t46\t; Index = 13 Token = 7\n\t\tDD\t-3\t; Index = 13 Token = 8\n\t\tDD\t-9\t; Index = 13 Token = 9\n\t\tDD\t-15\t; Index = 13 Token = 10\n\t\tDD\t-21\t; Index = 13 Token = 11\n\t\tDD\t-28\t; Index = 13 Token = 12\n\t\tDD\t-34\t; Index = 13 Token = 13\n\t\tDD\t-40\t; Index = 13 Token = 14\n\t\tDD\t-46\t; Index = 13 Token = 15\n\t\tDD\t3\t; Index = 14 Token = 0\n\t\tDD\t10\t; Index = 14 Token = 1\n\t\tDD\t17\t; Index = 14 Token = 2\n\t\tDD\t24\t; Index = 14 Token = 3\n\t\tDD\t31\t; Index = 14 Token = 4\n\t\tDD\t38\t; Index = 14 Token = 5\n\t\tDD\t45\t; Index = 14 Token = 6\n\t\tDD\t52\t; Index = 14 Token = 7\n\t\tDD\t-3\t; Index = 14 Token = 8\n\t\tDD\t-10\t; Index = 14 Token = 9\n\t\tDD\t-17\t; Index = 14 Token = 10\n\t\tDD\t-24\t; Index = 14 Token = 11\n\t\tDD\t-31\t; Index = 14 Token = 12\n\t\tDD\t-38\t; Index = 14 Token = 13\n\t\tDD\t-45\t; Index = 14 Token = 14\n\t\tDD\t-52\t; Index = 14 Token = 15\n\t\tDD\t3\t; Index = 15 Token = 0\n\t\tDD\t10\t; Index = 15 Token = 1\n\t\tDD\t18\t; Index = 15 Token = 2\n\t\tDD\t25\t; Index = 15 Token = 3\n\t\tDD\t34\t; Index = 15 Token = 4\n\t\tDD\t41\t; Index = 15 Token = 5\n\t\tDD\t49\t; Index = 15 Token = 6\n\t\tDD\t56\t; Index = 15 Token = 7\n\t\tDD\t-3\t; Index = 15 Token = 8\n\t\tDD\t-10\t; Index = 15 Token = 9\n\t\tDD\t-18\t; Index = 15 Token = 10\n\t\tDD\t-25\t; Index = 15 Token = 11\n\t\tDD\t-34\t; Index = 15 Token = 12\n\t\tDD\t-41\t; Index = 15 Token = 13\n\t\tDD\t-49\t; Index = 15 Token = 14\n\t\tDD\t-56\t; Index = 15 Token = 15\n\t\tDD\t4\t; Index = 16 Token = 0\n\t\tDD\t12\t; Index = 16 Token = 1\n\t\tDD\t21\t; Index = 16 Token = 2\n\t\tDD\t29\t; Index = 16 Token = 3\n\t\tDD\t38\t; Index = 16 Token = 4\n\t\tDD\t46\t; Index = 16 Token = 5\n\t\tDD\t55\t; Index = 16 Token = 6\n\t\tDD\t63\t; Index = 16 Token = 7\n\t\tDD\t-4\t; Index = 16 Token = 8\n\t\tDD\t-12\t; Index = 16 Token = 9\n\t\tDD\t-21\t; Index = 16 Token = 10\n\t\tDD\t-29\t; Index = 16 Token = 11\n\t\tDD\t-38\t; Index = 16 Token = 12\n\t\tDD\t-46\t; Index = 16 Token = 13\n\t\tDD\t-55\t; Index = 16 Token = 14\n\t\tDD\t-63\t; Index = 16 Token = 15\n\t\tDD\t4\t; Index = 17 Token = 0\n\t\tDD\t13\t; Index = 17 Token = 1\n\t\tDD\t22\t; Index = 17 Token = 2\n\t\tDD\t31\t; Index = 17 Token = 3\n\t\tDD\t41\t; Index = 17 Token = 4\n\t\tDD\t50\t; Index = 17 Token = 5\n\t\tDD\t59\t; Index = 17 Token = 6\n\t\tDD\t68\t; Index = 17 Token = 7\n\t\tDD\t-4\t; Index = 17 Token = 8\n\t\tDD\t-13\t; Index = 17 Token = 9\n\t\tDD\t-22\t; Index = 17 Token = 10\n\t\tDD\t-31\t; Index = 17 Token = 11\n\t\tDD\t-41\t; Index = 17 Token = 12\n\t\tDD\t-50\t; Index = 17 Token = 13\n\t\tDD\t-59\t; Index = 17 Token = 14\n\t\tDD\t-68\t; Index = 17 Token = 15\n\t\tDD\t5\t; Index = 18 Token = 0\n\t\tDD\t15\t; Index = 18 Token = 1\n\t\tDD\t25\t; Index = 18 Token = 2\n\t\tDD\t35\t; Index = 18 Token = 3\n\t\tDD\t46\t; Index = 18 Token = 4\n\t\tDD\t56\t; Index = 18 Token = 5\n\t\tDD\t66\t; Index = 18 Token = 6\n\t\tDD\t76\t; Index = 18 Token = 7\n\t\tDD\t-5\t; Index = 18 Token = 8\n\t\tDD\t-15\t; Index = 18 Token = 9\n\t\tDD\t-25\t; Index = 18 Token = 10\n\t\tDD\t-35\t; Index = 18 Token = 11\n\t\tDD\t-46\t; Index = 18 Token = 12\n\t\tDD\t-56\t; Index = 18 Token = 13\n\t\tDD\t-66\t; Index = 18 Token = 14\n\t\tDD\t-76\t; Index = 18 Token = 15\n\t\tDD\t5\t; Index = 19 Token = 0\n\t\tDD\t16\t; Index = 19 Token = 1\n\t\tDD\t27\t; Index = 19 Token = 2\n\t\tDD\t38\t; Index = 19 Token = 3\n\t\tDD\t50\t; Index = 19 Token = 4\n\t\tDD\t61\t; Index = 19 Token = 5\n\t\tDD\t72\t; Index = 19 Token = 6\n\t\tDD\t83\t; Index = 19 Token = 7\n\t\tDD\t-5\t; Index = 19 Token = 8\n\t\tDD\t-16\t; Index = 19 Token = 9\n\t\tDD\t-27\t; Index = 19 Token = 10\n\t\tDD\t-38\t; Index = 19 Token = 11\n\t\tDD\t-50\t; Index = 19 Token = 12\n\t\tDD\t-61\t; Index = 19 Token = 13\n\t\tDD\t-72\t; Index = 19 Token = 14\n\t\tDD\t-83\t; Index = 19 Token = 15\n\t\tDD\t6\t; Index = 20 Token = 0\n\t\tDD\t18\t; Index = 20 Token = 1\n\t\tDD\t31\t; Index = 20 Token = 2\n\t\tDD\t43\t; Index = 20 Token = 3\n\t\tDD\t56\t; Index = 20 Token = 4\n\t\tDD\t68\t; Index = 20 Token = 5\n\t\tDD\t81\t; Index = 20 Token = 6\n\t\tDD\t93\t; Index = 20 Token = 7\n\t\tDD\t-6\t; Index = 20 Token = 8\n\t\tDD\t-18\t; Index = 20 Token = 9\n\t\tDD\t-31\t; Index = 20 Token = 10\n\t\tDD\t-43\t; Index = 20 Token = 11\n\t\tDD\t-56\t; Index = 20 Token = 12\n\t\tDD\t-68\t; Index = 20 Token = 13\n\t\tDD\t-81\t; Index = 20 Token = 14\n\t\tDD\t-93\t; Index = 20 Token = 15\n\t\tDD\t6\t; Index = 21 Token = 0\n\t\tDD\t19\t; Index = 21 Token = 1\n\t\tDD\t33\t; Index = 21 Token = 2\n\t\tDD\t46\t; Index = 21 Token = 3\n\t\tDD\t61\t; Index = 21 Token = 4\n\t\tDD\t74\t; Index = 21 Token = 5\n\t\tDD\t88\t; Index = 21 Token = 6\n\t\tDD\t101\t; Index = 21 Token = 7\n\t\tDD\t-6\t; Index = 21 Token = 8\n\t\tDD\t-19\t; Index = 21 Token = 9\n\t\tDD\t-33\t; Index = 21 Token = 10\n\t\tDD\t-46\t; Index = 21 Token = 11\n\t\tDD\t-61\t; Index = 21 Token = 12\n\t\tDD\t-74\t; Index = 21 Token = 13\n\t\tDD\t-88\t; Index = 21 Token = 14\n\t\tDD\t-101\t; Index = 21 Token = 15\n\t\tDD\t7\t; Index = 22 Token = 0\n\t\tDD\t22\t; Index = 22 Token = 1\n\t\tDD\t37\t; Index = 22 Token = 2\n\t\tDD\t52\t; Index = 22 Token = 3\n\t\tDD\t67\t; Index = 22 Token = 4\n\t\tDD\t82\t; Index = 22 Token = 5\n\t\tDD\t97\t; Index = 22 Token = 6\n\t\tDD\t112\t; Index = 22 Token = 7\n\t\tDD\t-7\t; Index = 22 Token = 8\n\t\tDD\t-22\t; Index = 22 Token = 9\n\t\tDD\t-37\t; Index = 22 Token = 10\n\t\tDD\t-52\t; Index = 22 Token = 11\n\t\tDD\t-67\t; Index = 22 Token = 12\n\t\tDD\t-82\t; Index = 22 Token = 13\n\t\tDD\t-97\t; Index = 22 Token = 14\n\t\tDD\t-112\t; Index = 22 Token = 15\n\t\tDD\t8\t; Index = 23 Token = 0\n\t\tDD\t24\t; Index = 23 Token = 1\n\t\tDD\t41\t; Index = 23 Token = 2\n\t\tDD\t57\t; Index = 23 Token = 3\n\t\tDD\t74\t; Index = 23 Token = 4\n\t\tDD\t90\t; Index = 23 Token = 5\n\t\tDD\t107\t; Index = 23 Token = 6\n\t\tDD\t123\t; Index = 23 Token = 7\n\t\tDD\t-8\t; Index = 23 Token = 8\n\t\tDD\t-24\t; Index = 23 Token = 9\n\t\tDD\t-41\t; Index = 23 Token = 10\n\t\tDD\t-57\t; Index = 23 Token = 11\n\t\tDD\t-74\t; Index = 23 Token = 12\n\t\tDD\t-90\t; Index = 23 Token = 13\n\t\tDD\t-107\t; Index = 23 Token = 14\n\t\tDD\t-123\t; Index = 23 Token = 15\n\t\tDD\t9\t; Index = 24 Token = 0\n\t\tDD\t27\t; Index = 24 Token = 1\n\t\tDD\t45\t; Index = 24 Token = 2\n\t\tDD\t63\t; Index = 24 Token = 3\n\t\tDD\t82\t; Index = 24 Token = 4\n\t\tDD\t100\t; Index = 24 Token = 5\n\t\tDD\t118\t; Index = 24 Token = 6\n\t\tDD\t136\t; Index = 24 Token = 7\n\t\tDD\t-9\t; Index = 24 Token = 8\n\t\tDD\t-27\t; Index = 24 Token = 9\n\t\tDD\t-45\t; Index = 24 Token = 10\n\t\tDD\t-63\t; Index = 24 Token = 11\n\t\tDD\t-82\t; Index = 24 Token = 12\n\t\tDD\t-100\t; Index = 24 Token = 13\n\t\tDD\t-118\t; Index = 24 Token = 14\n\t\tDD\t-136\t; Index = 24 Token = 15\n\t\tDD\t10\t; Index = 25 Token = 0\n\t\tDD\t30\t; Index = 25 Token = 1\n\t\tDD\t50\t; Index = 25 Token = 2\n\t\tDD\t70\t; Index = 25 Token = 3\n\t\tDD\t90\t; Index = 25 Token = 4\n\t\tDD\t110\t; Index = 25 Token = 5\n\t\tDD\t130\t; Index = 25 Token = 6\n\t\tDD\t150\t; Index = 25 Token = 7\n\t\tDD\t-10\t; Index = 25 Token = 8\n\t\tDD\t-30\t; Index = 25 Token = 9\n\t\tDD\t-50\t; Index = 25 Token = 10\n\t\tDD\t-70\t; Index = 25 Token = 11\n\t\tDD\t-90\t; Index = 25 Token = 12\n\t\tDD\t-110\t; Index = 25 Token = 13\n\t\tDD\t-130\t; Index = 25 Token = 14\n\t\tDD\t-150\t; Index = 25 Token = 15\n\t\tDD\t11\t; Index = 26 Token = 0\n\t\tDD\t33\t; Index = 26 Token = 1\n\t\tDD\t55\t; Index = 26 Token = 2\n\t\tDD\t77\t; Index = 26 Token = 3\n\t\tDD\t99\t; Index = 26 Token = 4\n\t\tDD\t121\t; Index = 26 Token = 5\n\t\tDD\t143\t; Index = 26 Token = 6\n\t\tDD\t165\t; Index = 26 Token = 7\n\t\tDD\t-11\t; Index = 26 Token = 8\n\t\tDD\t-33\t; Index = 26 Token = 9\n\t\tDD\t-55\t; Index = 26 Token = 10\n\t\tDD\t-77\t; Index = 26 Token = 11\n\t\tDD\t-99\t; Index = 26 Token = 12\n\t\tDD\t-121\t; Index = 26 Token = 13\n\t\tDD\t-143\t; Index = 26 Token = 14\n\t\tDD\t-165\t; Index = 26 Token = 15\n\t\tDD\t12\t; Index = 27 Token = 0\n\t\tDD\t36\t; Index = 27 Token = 1\n\t\tDD\t60\t; Index = 27 Token = 2\n\t\tDD\t84\t; Index = 27 Token = 3\n\t\tDD\t109\t; Index = 27 Token = 4\n\t\tDD\t133\t; Index = 27 Token = 5\n\t\tDD\t157\t; Index = 27 Token = 6\n\t\tDD\t181\t; Index = 27 Token = 7\n\t\tDD\t-12\t; Index = 27 Token = 8\n\t\tDD\t-36\t; Index = 27 Token = 9\n\t\tDD\t-60\t; Index = 27 Token = 10\n\t\tDD\t-84\t; Index = 27 Token = 11\n\t\tDD\t-109\t; Index = 27 Token = 12\n\t\tDD\t-133\t; Index = 27 Token = 13\n\t\tDD\t-157\t; Index = 27 Token = 14\n\t\tDD\t-181\t; Index = 27 Token = 15\n\t\tDD\t13\t; Index = 28 Token = 0\n\t\tDD\t39\t; Index = 28 Token = 1\n\t\tDD\t66\t; Index = 28 Token = 2\n\t\tDD\t92\t; Index = 28 Token = 3\n\t\tDD\t120\t; Index = 28 Token = 4\n\t\tDD\t146\t; Index = 28 Token = 5\n\t\tDD\t173\t; Index = 28 Token = 6\n\t\tDD\t199\t; Index = 28 Token = 7\n\t\tDD\t-13\t; Index = 28 Token = 8\n\t\tDD\t-39\t; Index = 28 Token = 9\n\t\tDD\t-66\t; Index = 28 Token = 10\n\t\tDD\t-92\t; Index = 28 Token = 11\n\t\tDD\t-120\t; Index = 28 Token = 12\n\t\tDD\t-146\t; Index = 28 Token = 13\n\t\tDD\t-173\t; Index = 28 Token = 14\n\t\tDD\t-199\t; Index = 28 Token = 15\n\t\tDD\t14\t; Index = 29 Token = 0\n\t\tDD\t43\t; Index = 29 Token = 1\n\t\tDD\t73\t; Index = 29 Token = 2\n\t\tDD\t102\t; Index = 29 Token = 3\n\t\tDD\t132\t; Index = 29 Token = 4\n\t\tDD\t161\t; Index = 29 Token = 5\n\t\tDD\t191\t; Index = 29 Token = 6\n\t\tDD\t220\t; Index = 29 Token = 7\n\t\tDD\t-14\t; Index = 29 Token = 8\n\t\tDD\t-43\t; Index = 29 Token = 9\n\t\tDD\t-73\t; Index = 29 Token = 10\n\t\tDD\t-102\t; Index = 29 Token = 11\n\t\tDD\t-132\t; Index = 29 Token = 12\n\t\tDD\t-161\t; Index = 29 Token = 13\n\t\tDD\t-191\t; Index = 29 Token = 14\n\t\tDD\t-220\t; Index = 29 Token = 15\n\t\tDD\t16\t; Index = 30 Token = 0\n\t\tDD\t48\t; Index = 30 Token = 1\n\t\tDD\t81\t; Index = 30 Token = 2\n\t\tDD\t113\t; Index = 30 Token = 3\n\t\tDD\t146\t; Index = 30 Token = 4\n\t\tDD\t178\t; Index = 30 Token = 5\n\t\tDD\t211\t; Index = 30 Token = 6\n\t\tDD\t243\t; Index = 30 Token = 7\n\t\tDD\t-16\t; Index = 30 Token = 8\n\t\tDD\t-48\t; Index = 30 Token = 9\n\t\tDD\t-81\t; Index = 30 Token = 10\n\t\tDD\t-113\t; Index = 30 Token = 11\n\t\tDD\t-146\t; Index = 30 Token = 12\n\t\tDD\t-178\t; Index = 30 Token = 13\n\t\tDD\t-211\t; Index = 30 Token = 14\n\t\tDD\t-243\t; Index = 30 Token = 15\n\t\tDD\t17\t; Index = 31 Token = 0\n\t\tDD\t52\t; Index = 31 Token = 1\n\t\tDD\t88\t; Index = 31 Token = 2\n\t\tDD\t123\t; Index = 31 Token = 3\n\t\tDD\t160\t; Index = 31 Token = 4\n\t\tDD\t195\t; Index = 31 Token = 5\n\t\tDD\t231\t; Index = 31 Token = 6\n\t\tDD\t266\t; Index = 31 Token = 7\n\t\tDD\t-17\t; Index = 31 Token = 8\n\t\tDD\t-52\t; Index = 31 Token = 9\n\t\tDD\t-88\t; Index = 31 Token = 10\n\t\tDD\t-123\t; Index = 31 Token = 11\n\t\tDD\t-160\t; Index = 31 Token = 12\n\t\tDD\t-195\t; Index = 31 Token = 13\n\t\tDD\t-231\t; Index = 31 Token = 14\n\t\tDD\t-266\t; Index = 31 Token = 15\n\t\tDD\t19\t; Index = 32 Token = 0\n\t\tDD\t58\t; Index = 32 Token = 1\n\t\tDD\t97\t; Index = 32 Token = 2\n\t\tDD\t136\t; Index = 32 Token = 3\n\t\tDD\t176\t; Index = 32 Token = 4\n\t\tDD\t215\t; Index = 32 Token = 5\n\t\tDD\t254\t; Index = 32 Token = 6\n\t\tDD\t293\t; Index = 32 Token = 7\n\t\tDD\t-19\t; Index = 32 Token = 8\n\t\tDD\t-58\t; Index = 32 Token = 9\n\t\tDD\t-97\t; Index = 32 Token = 10\n\t\tDD\t-136\t; Index = 32 Token = 11\n\t\tDD\t-176\t; Index = 32 Token = 12\n\t\tDD\t-215\t; Index = 32 Token = 13\n\t\tDD\t-254\t; Index = 32 Token = 14\n\t\tDD\t-293\t; Index = 32 Token = 15\n\t\tDD\t21\t; Index = 33 Token = 0\n\t\tDD\t64\t; Index = 33 Token = 1\n\t\tDD\t107\t; Index = 33 Token = 2\n\t\tDD\t150\t; Index = 33 Token = 3\n\t\tDD\t194\t; Index = 33 Token = 4\n\t\tDD\t237\t; Index = 33 Token = 5\n\t\tDD\t280\t; Index = 33 Token = 6\n\t\tDD\t323\t; Index = 33 Token = 7\n\t\tDD\t-21\t; Index = 33 Token = 8\n\t\tDD\t-64\t; Index = 33 Token = 9\n\t\tDD\t-107\t; Index = 33 Token = 10\n\t\tDD\t-150\t; Index = 33 Token = 11\n\t\tDD\t-194\t; Index = 33 Token = 12\n\t\tDD\t-237\t; Index = 33 Token = 13\n\t\tDD\t-280\t; Index = 33 Token = 14\n\t\tDD\t-323\t; Index = 33 Token = 15\n\t\tDD\t23\t; Index = 34 Token = 0\n\t\tDD\t70\t; Index = 34 Token = 1\n\t\tDD\t118\t; Index = 34 Token = 2\n\t\tDD\t165\t; Index = 34 Token = 3\n\t\tDD\t213\t; Index = 34 Token = 4\n\t\tDD\t260\t; Index = 34 Token = 5\n\t\tDD\t308\t; Index = 34 Token = 6\n\t\tDD\t355\t; Index = 34 Token = 7\n\t\tDD\t-23\t; Index = 34 Token = 8\n\t\tDD\t-70\t; Index = 34 Token = 9\n\t\tDD\t-118\t; Index = 34 Token = 10\n\t\tDD\t-165\t; Index = 34 Token = 11\n\t\tDD\t-213\t; Index = 34 Token = 12\n\t\tDD\t-260\t; Index = 34 Token = 13\n\t\tDD\t-308\t; Index = 34 Token = 14\n\t\tDD\t-355\t; Index = 34 Token = 15\n\t\tDD\t26\t; Index = 35 Token = 0\n\t\tDD\t78\t; Index = 35 Token = 1\n\t\tDD\t130\t; Index = 35 Token = 2\n\t\tDD\t182\t; Index = 35 Token = 3\n\t\tDD\t235\t; Index = 35 Token = 4\n\t\tDD\t287\t; Index = 35 Token = 5\n\t\tDD\t339\t; Index = 35 Token = 6\n\t\tDD\t391\t; Index = 35 Token = 7\n\t\tDD\t-26\t; Index = 35 Token = 8\n\t\tDD\t-78\t; Index = 35 Token = 9\n\t\tDD\t-130\t; Index = 35 Token = 10\n\t\tDD\t-182\t; Index = 35 Token = 11\n\t\tDD\t-235\t; Index = 35 Token = 12\n\t\tDD\t-287\t; Index = 35 Token = 13\n\t\tDD\t-339\t; Index = 35 Token = 14\n\t\tDD\t-391\t; Index = 35 Token = 15\n\t\tDD\t28\t; Index = 36 Token = 0\n\t\tDD\t85\t; Index = 36 Token = 1\n\t\tDD\t143\t; Index = 36 Token = 2\n\t\tDD\t200\t; Index = 36 Token = 3\n\t\tDD\t258\t; Index = 36 Token = 4\n\t\tDD\t315\t; Index = 36 Token = 5\n\t\tDD\t373\t; Index = 36 Token = 6\n\t\tDD\t430\t; Index = 36 Token = 7\n\t\tDD\t-28\t; Index = 36 Token = 8\n\t\tDD\t-85\t; Index = 36 Token = 9\n\t\tDD\t-143\t; Index = 36 Token = 10\n\t\tDD\t-200\t; Index = 36 Token = 11\n\t\tDD\t-258\t; Index = 36 Token = 12\n\t\tDD\t-315\t; Index = 36 Token = 13\n\t\tDD\t-373\t; Index = 36 Token = 14\n\t\tDD\t-430\t; Index = 36 Token = 15\n\t\tDD\t31\t; Index = 37 Token = 0\n\t\tDD\t94\t; Index = 37 Token = 1\n\t\tDD\t157\t; Index = 37 Token = 2\n\t\tDD\t220\t; Index = 37 Token = 3\n\t\tDD\t284\t; Index = 37 Token = 4\n\t\tDD\t347\t; Index = 37 Token = 5\n\t\tDD\t410\t; Index = 37 Token = 6\n\t\tDD\t473\t; Index = 37 Token = 7\n\t\tDD\t-31\t; Index = 37 Token = 8\n\t\tDD\t-94\t; Index = 37 Token = 9\n\t\tDD\t-157\t; Index = 37 Token = 10\n\t\tDD\t-220\t; Index = 37 Token = 11\n\t\tDD\t-284\t; Index = 37 Token = 12\n\t\tDD\t-347\t; Index = 37 Token = 13\n\t\tDD\t-410\t; Index = 37 Token = 14\n\t\tDD\t-473\t; Index = 37 Token = 15\n\t\tDD\t34\t; Index = 38 Token = 0\n\t\tDD\t103\t; Index = 38 Token = 1\n\t\tDD\t173\t; Index = 38 Token = 2\n\t\tDD\t242\t; Index = 38 Token = 3\n\t\tDD\t313\t; Index = 38 Token = 4\n\t\tDD\t382\t; Index = 38 Token = 5\n\t\tDD\t452\t; Index = 38 Token = 6\n\t\tDD\t521\t; Index = 38 Token = 7\n\t\tDD\t-34\t; Index = 38 Token = 8\n\t\tDD\t-103\t; Index = 38 Token = 9\n\t\tDD\t-173\t; Index = 38 Token = 10\n\t\tDD\t-242\t; Index = 38 Token = 11\n\t\tDD\t-313\t; Index = 38 Token = 12\n\t\tDD\t-382\t; Index = 38 Token = 13\n\t\tDD\t-452\t; Index = 38 Token = 14\n\t\tDD\t-521\t; Index = 38 Token = 15\n\t\tDD\t38\t; Index = 39 Token = 0\n\t\tDD\t114\t; Index = 39 Token = 1\n\t\tDD\t191\t; Index = 39 Token = 2\n\t\tDD\t267\t; Index = 39 Token = 3\n\t\tDD\t345\t; Index = 39 Token = 4\n\t\tDD\t421\t; Index = 39 Token = 5\n\t\tDD\t498\t; Index = 39 Token = 6\n\t\tDD\t574\t; Index = 39 Token = 7\n\t\tDD\t-38\t; Index = 39 Token = 8\n\t\tDD\t-114\t; Index = 39 Token = 9\n\t\tDD\t-191\t; Index = 39 Token = 10\n\t\tDD\t-267\t; Index = 39 Token = 11\n\t\tDD\t-345\t; Index = 39 Token = 12\n\t\tDD\t-421\t; Index = 39 Token = 13\n\t\tDD\t-498\t; Index = 39 Token = 14\n\t\tDD\t-574\t; Index = 39 Token = 15\n\t\tDD\t42\t; Index = 40 Token = 0\n\t\tDD\t126\t; Index = 40 Token = 1\n\t\tDD\t210\t; Index = 40 Token = 2\n\t\tDD\t294\t; Index = 40 Token = 3\n\t\tDD\t379\t; Index = 40 Token = 4\n\t\tDD\t463\t; Index = 40 Token = 5\n\t\tDD\t547\t; Index = 40 Token = 6\n\t\tDD\t631\t; Index = 40 Token = 7\n\t\tDD\t-42\t; Index = 40 Token = 8\n\t\tDD\t-126\t; Index = 40 Token = 9\n\t\tDD\t-210\t; Index = 40 Token = 10\n\t\tDD\t-294\t; Index = 40 Token = 11\n\t\tDD\t-379\t; Index = 40 Token = 12\n\t\tDD\t-463\t; Index = 40 Token = 13\n\t\tDD\t-547\t; Index = 40 Token = 14\n\t\tDD\t-631\t; Index = 40 Token = 15\n\t\tDD\t46\t; Index = 41 Token = 0\n\t\tDD\t138\t; Index = 41 Token = 1\n\t\tDD\t231\t; Index = 41 Token = 2\n\t\tDD\t323\t; Index = 41 Token = 3\n\t\tDD\t417\t; Index = 41 Token = 4\n\t\tDD\t509\t; Index = 41 Token = 5\n\t\tDD\t602\t; Index = 41 Token = 6\n\t\tDD\t694\t; Index = 41 Token = 7\n\t\tDD\t-46\t; Index = 41 Token = 8\n\t\tDD\t-138\t; Index = 41 Token = 9\n\t\tDD\t-231\t; Index = 41 Token = 10\n\t\tDD\t-323\t; Index = 41 Token = 11\n\t\tDD\t-417\t; Index = 41 Token = 12\n\t\tDD\t-509\t; Index = 41 Token = 13\n\t\tDD\t-602\t; Index = 41 Token = 14\n\t\tDD\t-694\t; Index = 41 Token = 15\n\t\tDD\t51\t; Index = 42 Token = 0\n\t\tDD\t153\t; Index = 42 Token = 1\n\t\tDD\t255\t; Index = 42 Token = 2\n\t\tDD\t357\t; Index = 42 Token = 3\n\t\tDD\t459\t; Index = 42 Token = 4\n\t\tDD\t561\t; Index = 42 Token = 5\n\t\tDD\t663\t; Index = 42 Token = 6\n\t\tDD\t765\t; Index = 42 Token = 7\n\t\tDD\t-51\t; Index = 42 Token = 8\n\t\tDD\t-153\t; Index = 42 Token = 9\n\t\tDD\t-255\t; Index = 42 Token = 10\n\t\tDD\t-357\t; Index = 42 Token = 11\n\t\tDD\t-459\t; Index = 42 Token = 12\n\t\tDD\t-561\t; Index = 42 Token = 13\n\t\tDD\t-663\t; Index = 42 Token = 14\n\t\tDD\t-765\t; Index = 42 Token = 15\n\t\tDD\t56\t; Index = 43 Token = 0\n\t\tDD\t168\t; Index = 43 Token = 1\n\t\tDD\t280\t; Index = 43 Token = 2\n\t\tDD\t392\t; Index = 43 Token = 3\n\t\tDD\t505\t; Index = 43 Token = 4\n\t\tDD\t617\t; Index = 43 Token = 5\n\t\tDD\t729\t; Index = 43 Token = 6\n\t\tDD\t841\t; Index = 43 Token = 7\n\t\tDD\t-56\t; Index = 43 Token = 8\n\t\tDD\t-168\t; Index = 43 Token = 9\n\t\tDD\t-280\t; Index = 43 Token = 10\n\t\tDD\t-392\t; Index = 43 Token = 11\n\t\tDD\t-505\t; Index = 43 Token = 12\n\t\tDD\t-617\t; Index = 43 Token = 13\n\t\tDD\t-729\t; Index = 43 Token = 14\n\t\tDD\t-841\t; Index = 43 Token = 15\n\t\tDD\t61\t; Index = 44 Token = 0\n\t\tDD\t184\t; Index = 44 Token = 1\n\t\tDD\t308\t; Index = 44 Token = 2\n\t\tDD\t431\t; Index = 44 Token = 3\n\t\tDD\t555\t; Index = 44 Token = 4\n\t\tDD\t678\t; Index = 44 Token = 5\n\t\tDD\t802\t; Index = 44 Token = 6\n\t\tDD\t925\t; Index = 44 Token = 7\n\t\tDD\t-61\t; Index = 44 Token = 8\n\t\tDD\t-184\t; Index = 44 Token = 9\n\t\tDD\t-308\t; Index = 44 Token = 10\n\t\tDD\t-431\t; Index = 44 Token = 11\n\t\tDD\t-555\t; Index = 44 Token = 12\n\t\tDD\t-678\t; Index = 44 Token = 13\n\t\tDD\t-802\t; Index = 44 Token = 14\n\t\tDD\t-925\t; Index = 44 Token = 15\n\t\tDD\t68\t; Index = 45 Token = 0\n\t\tDD\t204\t; Index = 45 Token = 1\n\t\tDD\t340\t; Index = 45 Token = 2\n\t\tDD\t476\t; Index = 45 Token = 3\n\t\tDD\t612\t; Index = 45 Token = 4\n\t\tDD\t748\t; Index = 45 Token = 5\n\t\tDD\t884\t; Index = 45 Token = 6\n\t\tDD\t1020\t; Index = 45 Token = 7\n\t\tDD\t-68\t; Index = 45 Token = 8\n\t\tDD\t-204\t; Index = 45 Token = 9\n\t\tDD\t-340\t; Index = 45 Token = 10\n\t\tDD\t-476\t; Index = 45 Token = 11\n\t\tDD\t-612\t; Index = 45 Token = 12\n\t\tDD\t-748\t; Index = 45 Token = 13\n\t\tDD\t-884\t; Index = 45 Token = 14\n\t\tDD\t-1020\t; Index = 45 Token = 15\n\t\tDD\t74\t; Index = 46 Token = 0\n\t\tDD\t223\t; Index = 46 Token = 1\n\t\tDD\t373\t; Index = 46 Token = 2\n\t\tDD\t522\t; Index = 46 Token = 3\n\t\tDD\t672\t; Index = 46 Token = 4\n\t\tDD\t821\t; Index = 46 Token = 5\n\t\tDD\t971\t; Index = 46 Token = 6\n\t\tDD\t1120\t; Index = 46 Token = 7\n\t\tDD\t-74\t; Index = 46 Token = 8\n\t\tDD\t-223\t; Index = 46 Token = 9\n\t\tDD\t-373\t; Index = 46 Token = 10\n\t\tDD\t-522\t; Index = 46 Token = 11\n\t\tDD\t-672\t; Index = 46 Token = 12\n\t\tDD\t-821\t; Index = 46 Token = 13\n\t\tDD\t-971\t; Index = 46 Token = 14\n\t\tDD\t-1120\t; Index = 46 Token = 15\n\t\tDD\t82\t; Index = 47 Token = 0\n\t\tDD\t246\t; Index = 47 Token = 1\n\t\tDD\t411\t; Index = 47 Token = 2\n\t\tDD\t575\t; Index = 47 Token = 3\n\t\tDD\t740\t; Index = 47 Token = 4\n\t\tDD\t904\t; Index = 47 Token = 5\n\t\tDD\t1069\t; Index = 47 Token = 6\n\t\tDD\t1233\t; Index = 47 Token = 7\n\t\tDD\t-82\t; Index = 47 Token = 8\n\t\tDD\t-246\t; Index = 47 Token = 9\n\t\tDD\t-411\t; Index = 47 Token = 10\n\t\tDD\t-575\t; Index = 47 Token = 11\n\t\tDD\t-740\t; Index = 47 Token = 12\n\t\tDD\t-904\t; Index = 47 Token = 13\n\t\tDD\t-1069\t; Index = 47 Token = 14\n\t\tDD\t-1233\t; Index = 47 Token = 15\n\t\tDD\t90\t; Index = 48 Token = 0\n\t\tDD\t271\t; Index = 48 Token = 1\n\t\tDD\t452\t; Index = 48 Token = 2\n\t\tDD\t633\t; Index = 48 Token = 3\n\t\tDD\t814\t; Index = 48 Token = 4\n\t\tDD\t995\t; Index = 48 Token = 5\n\t\tDD\t1176\t; Index = 48 Token = 6\n\t\tDD\t1357\t; Index = 48 Token = 7\n\t\tDD\t-90\t; Index = 48 Token = 8\n\t\tDD\t-271\t; Index = 48 Token = 9\n\t\tDD\t-452\t; Index = 48 Token = 10\n\t\tDD\t-633\t; Index = 48 Token = 11\n\t\tDD\t-814\t; Index = 48 Token = 12\n\t\tDD\t-995\t; Index = 48 Token = 13\n\t\tDD\t-1176\t; Index = 48 Token = 14\n\t\tDD\t-1357\t; Index = 48 Token = 15\n\t\tDD\t99\t; Index = 49 Token = 0\n\t\tDD\t298\t; Index = 49 Token = 1\n\t\tDD\t497\t; Index = 49 Token = 2\n\t\tDD\t696\t; Index = 49 Token = 3\n\t\tDD\t895\t; Index = 49 Token = 4\n\t\tDD\t1094\t; Index = 49 Token = 5\n\t\tDD\t1293\t; Index = 49 Token = 6\n\t\tDD\t1492\t; Index = 49 Token = 7\n\t\tDD\t-99\t; Index = 49 Token = 8\n\t\tDD\t-298\t; Index = 49 Token = 9\n\t\tDD\t-497\t; Index = 49 Token = 10\n\t\tDD\t-696\t; Index = 49 Token = 11\n\t\tDD\t-895\t; Index = 49 Token = 12\n\t\tDD\t-1094\t; Index = 49 Token = 13\n\t\tDD\t-1293\t; Index = 49 Token = 14\n\t\tDD\t-1492\t; Index = 49 Token = 15\n\t\tDD\t109\t; Index = 50 Token = 0\n\t\tDD\t328\t; Index = 50 Token = 1\n\t\tDD\t547\t; Index = 50 Token = 2\n\t\tDD\t766\t; Index = 50 Token = 3\n\t\tDD\t985\t; Index = 50 Token = 4\n\t\tDD\t1204\t; Index = 50 Token = 5\n\t\tDD\t1423\t; Index = 50 Token = 6\n\t\tDD\t1642\t; Index = 50 Token = 7\n\t\tDD\t-109\t; Index = 50 Token = 8\n\t\tDD\t-328\t; Index = 50 Token = 9\n\t\tDD\t-547\t; Index = 50 Token = 10\n\t\tDD\t-766\t; Index = 50 Token = 11\n\t\tDD\t-985\t; Index = 50 Token = 12\n\t\tDD\t-1204\t; Index = 50 Token = 13\n\t\tDD\t-1423\t; Index = 50 Token = 14\n\t\tDD\t-1642\t; Index = 50 Token = 15\n\t\tDD\t120\t; Index = 51 Token = 0\n\t\tDD\t360\t; Index = 51 Token = 1\n\t\tDD\t601\t; Index = 51 Token = 2\n\t\tDD\t841\t; Index = 51 Token = 3\n\t\tDD\t1083\t; Index = 51 Token = 4\n\t\tDD\t1323\t; Index = 51 Token = 5\n\t\tDD\t1564\t; Index = 51 Token = 6\n\t\tDD\t1804\t; Index = 51 Token = 7\n\t\tDD\t-120\t; Index = 51 Token = 8\n\t\tDD\t-360\t; Index = 51 Token = 9\n\t\tDD\t-601\t; Index = 51 Token = 10\n\t\tDD\t-841\t; Index = 51 Token = 11\n\t\tDD\t-1083\t; Index = 51 Token = 12\n\t\tDD\t-1323\t; Index = 51 Token = 13\n\t\tDD\t-1564\t; Index = 51 Token = 14\n\t\tDD\t-1804\t; Index = 51 Token = 15\n\t\tDD\t132\t; Index = 52 Token = 0\n\t\tDD\t397\t; Index = 52 Token = 1\n\t\tDD\t662\t; Index = 52 Token = 2\n\t\tDD\t927\t; Index = 52 Token = 3\n\t\tDD\t1192\t; Index = 52 Token = 4\n\t\tDD\t1457\t; Index = 52 Token = 5\n\t\tDD\t1722\t; Index = 52 Token = 6\n\t\tDD\t1987\t; Index = 52 Token = 7\n\t\tDD\t-132\t; Index = 52 Token = 8\n\t\tDD\t-397\t; Index = 52 Token = 9\n\t\tDD\t-662\t; Index = 52 Token = 10\n\t\tDD\t-927\t; Index = 52 Token = 11\n\t\tDD\t-1192\t; Index = 52 Token = 12\n\t\tDD\t-1457\t; Index = 52 Token = 13\n\t\tDD\t-1722\t; Index = 52 Token = 14\n\t\tDD\t-1987\t; Index = 52 Token = 15\n\t\tDD\t145\t; Index = 53 Token = 0\n\t\tDD\t436\t; Index = 53 Token = 1\n\t\tDD\t728\t; Index = 53 Token = 2\n\t\tDD\t1019\t; Index = 53 Token = 3\n\t\tDD\t1311\t; Index = 53 Token = 4\n\t\tDD\t1602\t; Index = 53 Token = 5\n\t\tDD\t1894\t; Index = 53 Token = 6\n\t\tDD\t2185\t; Index = 53 Token = 7\n\t\tDD\t-145\t; Index = 53 Token = 8\n\t\tDD\t-436\t; Index = 53 Token = 9\n\t\tDD\t-728\t; Index = 53 Token = 10\n\t\tDD\t-1019\t; Index = 53 Token = 11\n\t\tDD\t-1311\t; Index = 53 Token = 12\n\t\tDD\t-1602\t; Index = 53 Token = 13\n\t\tDD\t-1894\t; Index = 53 Token = 14\n\t\tDD\t-2185\t; Index = 53 Token = 15\n\t\tDD\t160\t; Index = 54 Token = 0\n\t\tDD\t480\t; Index = 54 Token = 1\n\t\tDD\t801\t; Index = 54 Token = 2\n\t\tDD\t1121\t; Index = 54 Token = 3\n\t\tDD\t1442\t; Index = 54 Token = 4\n\t\tDD\t1762\t; Index = 54 Token = 5\n\t\tDD\t2083\t; Index = 54 Token = 6\n\t\tDD\t2403\t; Index = 54 Token = 7\n\t\tDD\t-160\t; Index = 54 Token = 8\n\t\tDD\t-480\t; Index = 54 Token = 9\n\t\tDD\t-801\t; Index = 54 Token = 10\n\t\tDD\t-1121\t; Index = 54 Token = 11\n\t\tDD\t-1442\t; Index = 54 Token = 12\n\t\tDD\t-1762\t; Index = 54 Token = 13\n\t\tDD\t-2083\t; Index = 54 Token = 14\n\t\tDD\t-2403\t; Index = 54 Token = 15\n\t\tDD\t176\t; Index = 55 Token = 0\n\t\tDD\t528\t; Index = 55 Token = 1\n\t\tDD\t881\t; Index = 55 Token = 2\n\t\tDD\t1233\t; Index = 55 Token = 3\n\t\tDD\t1587\t; Index = 55 Token = 4\n\t\tDD\t1939\t; Index = 55 Token = 5\n\t\tDD\t2292\t; Index = 55 Token = 6\n\t\tDD\t2644\t; Index = 55 Token = 7\n\t\tDD\t-176\t; Index = 55 Token = 8\n\t\tDD\t-528\t; Index = 55 Token = 9\n\t\tDD\t-881\t; Index = 55 Token = 10\n\t\tDD\t-1233\t; Index = 55 Token = 11\n\t\tDD\t-1587\t; Index = 55 Token = 12\n\t\tDD\t-1939\t; Index = 55 Token = 13\n\t\tDD\t-2292\t; Index = 55 Token = 14\n\t\tDD\t-2644\t; Index = 55 Token = 15\n\t\tDD\t194\t; Index = 56 Token = 0\n\t\tDD\t582\t; Index = 56 Token = 1\n\t\tDD\t970\t; Index = 56 Token = 2\n\t\tDD\t1358\t; Index = 56 Token = 3\n\t\tDD\t1746\t; Index = 56 Token = 4\n\t\tDD\t2134\t; Index = 56 Token = 5\n\t\tDD\t2522\t; Index = 56 Token = 6\n\t\tDD\t2910\t; Index = 56 Token = 7\n\t\tDD\t-194\t; Index = 56 Token = 8\n\t\tDD\t-582\t; Index = 56 Token = 9\n\t\tDD\t-970\t; Index = 56 Token = 10\n\t\tDD\t-1358\t; Index = 56 Token = 11\n\t\tDD\t-1746\t; Index = 56 Token = 12\n\t\tDD\t-2134\t; Index = 56 Token = 13\n\t\tDD\t-2522\t; Index = 56 Token = 14\n\t\tDD\t-2910\t; Index = 56 Token = 15\n\t\tDD\t213\t; Index = 57 Token = 0\n\t\tDD\t639\t; Index = 57 Token = 1\n\t\tDD\t1066\t; Index = 57 Token = 2\n\t\tDD\t1492\t; Index = 57 Token = 3\n\t\tDD\t1920\t; Index = 57 Token = 4\n\t\tDD\t2346\t; Index = 57 Token = 5\n\t\tDD\t2773\t; Index = 57 Token = 6\n\t\tDD\t3199\t; Index = 57 Token = 7\n\t\tDD\t-213\t; Index = 57 Token = 8\n\t\tDD\t-639\t; Index = 57 Token = 9\n\t\tDD\t-1066\t; Index = 57 Token = 10\n\t\tDD\t-1492\t; Index = 57 Token = 11\n\t\tDD\t-1920\t; Index = 57 Token = 12\n\t\tDD\t-2346\t; Index = 57 Token = 13\n\t\tDD\t-2773\t; Index = 57 Token = 14\n\t\tDD\t-3199\t; Index = 57 Token = 15\n\t\tDD\t234\t; Index = 58 Token = 0\n\t\tDD\t703\t; Index = 58 Token = 1\n\t\tDD\t1173\t; Index = 58 Token = 2\n\t\tDD\t1642\t; Index = 58 Token = 3\n\t\tDD\t2112\t; Index = 58 Token = 4\n\t\tDD\t2581\t; Index = 58 Token = 5\n\t\tDD\t3051\t; Index = 58 Token = 6\n\t\tDD\t3520\t; Index = 58 Token = 7\n\t\tDD\t-234\t; Index = 58 Token = 8\n\t\tDD\t-703\t; Index = 58 Token = 9\n\t\tDD\t-1173\t; Index = 58 Token = 10\n\t\tDD\t-1642\t; Index = 58 Token = 11\n\t\tDD\t-2112\t; Index = 58 Token = 12\n\t\tDD\t-2581\t; Index = 58 Token = 13\n\t\tDD\t-3051\t; Index = 58 Token = 14\n\t\tDD\t-3520\t; Index = 58 Token = 15\n\t\tDD\t258\t; Index = 59 Token = 0\n\t\tDD\t774\t; Index = 59 Token = 1\n\t\tDD\t1291\t; Index = 59 Token = 2\n\t\tDD\t1807\t; Index = 59 Token = 3\n\t\tDD\t2324\t; Index = 59 Token = 4\n\t\tDD\t2840\t; Index = 59 Token = 5\n\t\tDD\t3357\t; Index = 59 Token = 6\n\t\tDD\t3873\t; Index = 59 Token = 7\n\t\tDD\t-258\t; Index = 59 Token = 8\n\t\tDD\t-774\t; Index = 59 Token = 9\n\t\tDD\t-1291\t; Index = 59 Token = 10\n\t\tDD\t-1807\t; Index = 59 Token = 11\n\t\tDD\t-2324\t; Index = 59 Token = 12\n\t\tDD\t-2840\t; Index = 59 Token = 13\n\t\tDD\t-3357\t; Index = 59 Token = 14\n\t\tDD\t-3873\t; Index = 59 Token = 15\n\t\tDD\t284\t; Index = 60 Token = 0\n\t\tDD\t852\t; Index = 60 Token = 1\n\t\tDD\t1420\t; Index = 60 Token = 2\n\t\tDD\t1988\t; Index = 60 Token = 3\n\t\tDD\t2556\t; Index = 60 Token = 4\n\t\tDD\t3124\t; Index = 60 Token = 5\n\t\tDD\t3692\t; Index = 60 Token = 6\n\t\tDD\t4260\t; Index = 60 Token = 7\n\t\tDD\t-284\t; Index = 60 Token = 8\n\t\tDD\t-852\t; Index = 60 Token = 9\n\t\tDD\t-1420\t; Index = 60 Token = 10\n\t\tDD\t-1988\t; Index = 60 Token = 11\n\t\tDD\t-2556\t; Index = 60 Token = 12\n\t\tDD\t-3124\t; Index = 60 Token = 13\n\t\tDD\t-3692\t; Index = 60 Token = 14\n\t\tDD\t-4260\t; Index = 60 Token = 15\n\t\tDD\t312\t; Index = 61 Token = 0\n\t\tDD\t936\t; Index = 61 Token = 1\n\t\tDD\t1561\t; Index = 61 Token = 2\n\t\tDD\t2185\t; Index = 61 Token = 3\n\t\tDD\t2811\t; Index = 61 Token = 4\n\t\tDD\t3435\t; Index = 61 Token = 5\n\t\tDD\t4060\t; Index = 61 Token = 6\n\t\tDD\t4684\t; Index = 61 Token = 7\n\t\tDD\t-312\t; Index = 61 Token = 8\n\t\tDD\t-936\t; Index = 61 Token = 9\n\t\tDD\t-1561\t; Index = 61 Token = 10\n\t\tDD\t-2185\t; Index = 61 Token = 11\n\t\tDD\t-2811\t; Index = 61 Token = 12\n\t\tDD\t-3435\t; Index = 61 Token = 13\n\t\tDD\t-4060\t; Index = 61 Token = 14\n\t\tDD\t-4684\t; Index = 61 Token = 15\n\t\tDD\t343\t; Index = 62 Token = 0\n\t\tDD\t1030\t; Index = 62 Token = 1\n\t\tDD\t1717\t; Index = 62 Token = 2\n\t\tDD\t2404\t; Index = 62 Token = 3\n\t\tDD\t3092\t; Index = 62 Token = 4\n\t\tDD\t3779\t; Index = 62 Token = 5\n\t\tDD\t4466\t; Index = 62 Token = 6\n\t\tDD\t5153\t; Index = 62 Token = 7\n\t\tDD\t-343\t; Index = 62 Token = 8\n\t\tDD\t-1030\t; Index = 62 Token = 9\n\t\tDD\t-1717\t; Index = 62 Token = 10\n\t\tDD\t-2404\t; Index = 62 Token = 11\n\t\tDD\t-3092\t; Index = 62 Token = 12\n\t\tDD\t-3779\t; Index = 62 Token = 13\n\t\tDD\t-4466\t; Index = 62 Token = 14\n\t\tDD\t-5153\t; Index = 62 Token = 15\n\t\tDD\t378\t; Index = 63 Token = 0\n\t\tDD\t1134\t; Index = 63 Token = 1\n\t\tDD\t1890\t; Index = 63 Token = 2\n\t\tDD\t2646\t; Index = 63 Token = 3\n\t\tDD\t3402\t; Index = 63 Token = 4\n\t\tDD\t4158\t; Index = 63 Token = 5\n\t\tDD\t4914\t; Index = 63 Token = 6\n\t\tDD\t5670\t; Index = 63 Token = 7\n\t\tDD\t-378\t; Index = 63 Token = 8\n\t\tDD\t-1134\t; Index = 63 Token = 9\n\t\tDD\t-1890\t; Index = 63 Token = 10\n\t\tDD\t-2646\t; Index = 63 Token = 11\n\t\tDD\t-3402\t; Index = 63 Token = 12\n\t\tDD\t-4158\t; Index = 63 Token = 13\n\t\tDD\t-4914\t; Index = 63 Token = 14\n\t\tDD\t-5670\t; Index = 63 Token = 15\n\t\tDD\t415\t; Index = 64 Token = 0\n\t\tDD\t1246\t; Index = 64 Token = 1\n\t\tDD\t2078\t; Index = 64 Token = 2\n\t\tDD\t2909\t; Index = 64 Token = 3\n\t\tDD\t3742\t; Index = 64 Token = 4\n\t\tDD\t4573\t; Index = 64 Token = 5\n\t\tDD\t5405\t; Index = 64 Token = 6\n\t\tDD\t6236\t; Index = 64 Token = 7\n\t\tDD\t-415\t; Index = 64 Token = 8\n\t\tDD\t-1246\t; Index = 64 Token = 9\n\t\tDD\t-2078\t; Index = 64 Token = 10\n\t\tDD\t-2909\t; Index = 64 Token = 11\n\t\tDD\t-3742\t; Index = 64 Token = 12\n\t\tDD\t-4573\t; Index = 64 Token = 13\n\t\tDD\t-5405\t; Index = 64 Token = 14\n\t\tDD\t-6236\t; Index = 64 Token = 15\n\t\tDD\t457\t; Index = 65 Token = 0\n\t\tDD\t1372\t; Index = 65 Token = 1\n\t\tDD\t2287\t; Index = 65 Token = 2\n\t\tDD\t3202\t; Index = 65 Token = 3\n\t\tDD\t4117\t; Index = 65 Token = 4\n\t\tDD\t5032\t; Index = 65 Token = 5\n\t\tDD\t5947\t; Index = 65 Token = 6\n\t\tDD\t6862\t; Index = 65 Token = 7\n\t\tDD\t-457\t; Index = 65 Token = 8\n\t\tDD\t-1372\t; Index = 65 Token = 9\n\t\tDD\t-2287\t; Index = 65 Token = 10\n\t\tDD\t-3202\t; Index = 65 Token = 11\n\t\tDD\t-4117\t; Index = 65 Token = 12\n\t\tDD\t-5032\t; Index = 65 Token = 13\n\t\tDD\t-5947\t; Index = 65 Token = 14\n\t\tDD\t-6862\t; Index = 65 Token = 15\n\t\tDD\t503\t; Index = 66 Token = 0\n\t\tDD\t1509\t; Index = 66 Token = 1\n\t\tDD\t2516\t; Index = 66 Token = 2\n\t\tDD\t3522\t; Index = 66 Token = 3\n\t\tDD\t4529\t; Index = 66 Token = 4\n\t\tDD\t5535\t; Index = 66 Token = 5\n\t\tDD\t6542\t; Index = 66 Token = 6\n\t\tDD\t7548\t; Index = 66 Token = 7\n\t\tDD\t-503\t; Index = 66 Token = 8\n\t\tDD\t-1509\t; Index = 66 Token = 9\n\t\tDD\t-2516\t; Index = 66 Token = 10\n\t\tDD\t-3522\t; Index = 66 Token = 11\n\t\tDD\t-4529\t; Index = 66 Token = 12\n\t\tDD\t-5535\t; Index = 66 Token = 13\n\t\tDD\t-6542\t; Index = 66 Token = 14\n\t\tDD\t-7548\t; Index = 66 Token = 15\n\t\tDD\t553\t; Index = 67 Token = 0\n\t\tDD\t1660\t; Index = 67 Token = 1\n\t\tDD\t2767\t; Index = 67 Token = 2\n\t\tDD\t3874\t; Index = 67 Token = 3\n\t\tDD\t4981\t; Index = 67 Token = 4\n\t\tDD\t6088\t; Index = 67 Token = 5\n\t\tDD\t7195\t; Index = 67 Token = 6\n\t\tDD\t8302\t; Index = 67 Token = 7\n\t\tDD\t-553\t; Index = 67 Token = 8\n\t\tDD\t-1660\t; Index = 67 Token = 9\n\t\tDD\t-2767\t; Index = 67 Token = 10\n\t\tDD\t-3874\t; Index = 67 Token = 11\n\t\tDD\t-4981\t; Index = 67 Token = 12\n\t\tDD\t-6088\t; Index = 67 Token = 13\n\t\tDD\t-7195\t; Index = 67 Token = 14\n\t\tDD\t-8302\t; Index = 67 Token = 15\n\t\tDD\t608\t; Index = 68 Token = 0\n\t\tDD\t1825\t; Index = 68 Token = 1\n\t\tDD\t3043\t; Index = 68 Token = 2\n\t\tDD\t4260\t; Index = 68 Token = 3\n\t\tDD\t5479\t; Index = 68 Token = 4\n\t\tDD\t6696\t; Index = 68 Token = 5\n\t\tDD\t7914\t; Index = 68 Token = 6\n\t\tDD\t9131\t; Index = 68 Token = 7\n\t\tDD\t-608\t; Index = 68 Token = 8\n\t\tDD\t-1825\t; Index = 68 Token = 9\n\t\tDD\t-3043\t; Index = 68 Token = 10\n\t\tDD\t-4260\t; Index = 68 Token = 11\n\t\tDD\t-5479\t; Index = 68 Token = 12\n\t\tDD\t-6696\t; Index = 68 Token = 13\n\t\tDD\t-7914\t; Index = 68 Token = 14\n\t\tDD\t-9131\t; Index = 68 Token = 15\n\t\tDD\t669\t; Index = 69 Token = 0\n\t\tDD\t2008\t; Index = 69 Token = 1\n\t\tDD\t3348\t; Index = 69 Token = 2\n\t\tDD\t4687\t; Index = 69 Token = 3\n\t\tDD\t6027\t; Index = 69 Token = 4\n\t\tDD\t7366\t; Index = 69 Token = 5\n\t\tDD\t8706\t; Index = 69 Token = 6\n\t\tDD\t10045\t; Index = 69 Token = 7\n\t\tDD\t-669\t; Index = 69 Token = 8\n\t\tDD\t-2008\t; Index = 69 Token = 9\n\t\tDD\t-3348\t; Index = 69 Token = 10\n\t\tDD\t-4687\t; Index = 69 Token = 11\n\t\tDD\t-6027\t; Index = 69 Token = 12\n\t\tDD\t-7366\t; Index = 69 Token = 13\n\t\tDD\t-8706\t; Index = 69 Token = 14\n\t\tDD\t-10045\t; Index = 69 Token = 15\n\t\tDD\t736\t; Index = 70 Token = 0\n\t\tDD\t2209\t; Index = 70 Token = 1\n\t\tDD\t3683\t; Index = 70 Token = 2\n\t\tDD\t5156\t; Index = 70 Token = 3\n\t\tDD\t6630\t; Index = 70 Token = 4\n\t\tDD\t8103\t; Index = 70 Token = 5\n\t\tDD\t9577\t; Index = 70 Token = 6\n\t\tDD\t11050\t; Index = 70 Token = 7\n\t\tDD\t-736\t; Index = 70 Token = 8\n\t\tDD\t-2209\t; Index = 70 Token = 9\n\t\tDD\t-3683\t; Index = 70 Token = 10\n\t\tDD\t-5156\t; Index = 70 Token = 11\n\t\tDD\t-6630\t; Index = 70 Token = 12\n\t\tDD\t-8103\t; Index = 70 Token = 13\n\t\tDD\t-9577\t; Index = 70 Token = 14\n\t\tDD\t-11050\t; Index = 70 Token = 15\n\t\tDD\t810\t; Index = 71 Token = 0\n\t\tDD\t2431\t; Index = 71 Token = 1\n\t\tDD\t4052\t; Index = 71 Token = 2\n\t\tDD\t5673\t; Index = 71 Token = 3\n\t\tDD\t7294\t; Index = 71 Token = 4\n\t\tDD\t8915\t; Index = 71 Token = 5\n\t\tDD\t10536\t; Index = 71 Token = 6\n\t\tDD\t12157\t; Index = 71 Token = 7\n\t\tDD\t-810\t; Index = 71 Token = 8\n\t\tDD\t-2431\t; Index = 71 Token = 9\n\t\tDD\t-4052\t; Index = 71 Token = 10\n\t\tDD\t-5673\t; Index = 71 Token = 11\n\t\tDD\t-7294\t; Index = 71 Token = 12\n\t\tDD\t-8915\t; Index = 71 Token = 13\n\t\tDD\t-10536\t; Index = 71 Token = 14\n\t\tDD\t-12157\t; Index = 71 Token = 15\n\t\tDD\t891\t; Index = 72 Token = 0\n\t\tDD\t2674\t; Index = 72 Token = 1\n\t\tDD\t4457\t; Index = 72 Token = 2\n\t\tDD\t6240\t; Index = 72 Token = 3\n\t\tDD\t8023\t; Index = 72 Token = 4\n\t\tDD\t9806\t; Index = 72 Token = 5\n\t\tDD\t11589\t; Index = 72 Token = 6\n\t\tDD\t13372\t; Index = 72 Token = 7\n\t\tDD\t-891\t; Index = 72 Token = 8\n\t\tDD\t-2674\t; Index = 72 Token = 9\n\t\tDD\t-4457\t; Index = 72 Token = 10\n\t\tDD\t-6240\t; Index = 72 Token = 11\n\t\tDD\t-8023\t; Index = 72 Token = 12\n\t\tDD\t-9806\t; Index = 72 Token = 13\n\t\tDD\t-11589\t; Index = 72 Token = 14\n\t\tDD\t-13372\t; Index = 72 Token = 15\n\t\tDD\t980\t; Index = 73 Token = 0\n\t\tDD\t2941\t; Index = 73 Token = 1\n\t\tDD\t4902\t; Index = 73 Token = 2\n\t\tDD\t6863\t; Index = 73 Token = 3\n\t\tDD\t8825\t; Index = 73 Token = 4\n\t\tDD\t10786\t; Index = 73 Token = 5\n\t\tDD\t12747\t; Index = 73 Token = 6\n\t\tDD\t14708\t; Index = 73 Token = 7\n\t\tDD\t-980\t; Index = 73 Token = 8\n\t\tDD\t-2941\t; Index = 73 Token = 9\n\t\tDD\t-4902\t; Index = 73 Token = 10\n\t\tDD\t-6863\t; Index = 73 Token = 11\n\t\tDD\t-8825\t; Index = 73 Token = 12\n\t\tDD\t-10786\t; Index = 73 Token = 13\n\t\tDD\t-12747\t; Index = 73 Token = 14\n\t\tDD\t-14708\t; Index = 73 Token = 15\n\t\tDD\t1078\t; Index = 74 Token = 0\n\t\tDD\t3235\t; Index = 74 Token = 1\n\t\tDD\t5393\t; Index = 74 Token = 2\n\t\tDD\t7550\t; Index = 74 Token = 3\n\t\tDD\t9708\t; Index = 74 Token = 4\n\t\tDD\t11865\t; Index = 74 Token = 5\n\t\tDD\t14023\t; Index = 74 Token = 6\n\t\tDD\t16180\t; Index = 74 Token = 7\n\t\tDD\t-1078\t; Index = 74 Token = 8\n\t\tDD\t-3235\t; Index = 74 Token = 9\n\t\tDD\t-5393\t; Index = 74 Token = 10\n\t\tDD\t-7550\t; Index = 74 Token = 11\n\t\tDD\t-9708\t; Index = 74 Token = 12\n\t\tDD\t-11865\t; Index = 74 Token = 13\n\t\tDD\t-14023\t; Index = 74 Token = 14\n\t\tDD\t-16180\t; Index = 74 Token = 15\n\t\tDD\t1186\t; Index = 75 Token = 0\n\t\tDD\t3559\t; Index = 75 Token = 1\n\t\tDD\t5932\t; Index = 75 Token = 2\n\t\tDD\t8305\t; Index = 75 Token = 3\n\t\tDD\t10679\t; Index = 75 Token = 4\n\t\tDD\t13052\t; Index = 75 Token = 5\n\t\tDD\t15425\t; Index = 75 Token = 6\n\t\tDD\t17798\t; Index = 75 Token = 7\n\t\tDD\t-1186\t; Index = 75 Token = 8\n\t\tDD\t-3559\t; Index = 75 Token = 9\n\t\tDD\t-5932\t; Index = 75 Token = 10\n\t\tDD\t-8305\t; Index = 75 Token = 11\n\t\tDD\t-10679\t; Index = 75 Token = 12\n\t\tDD\t-13052\t; Index = 75 Token = 13\n\t\tDD\t-15425\t; Index = 75 Token = 14\n\t\tDD\t-17798\t; Index = 75 Token = 15\n\t\tDD\t1305\t; Index = 76 Token = 0\n\t\tDD\t3915\t; Index = 76 Token = 1\n\t\tDD\t6526\t; Index = 76 Token = 2\n\t\tDD\t9136\t; Index = 76 Token = 3\n\t\tDD\t11747\t; Index = 76 Token = 4\n\t\tDD\t14357\t; Index = 76 Token = 5\n\t\tDD\t16968\t; Index = 76 Token = 6\n\t\tDD\t19578\t; Index = 76 Token = 7\n\t\tDD\t-1305\t; Index = 76 Token = 8\n\t\tDD\t-3915\t; Index = 76 Token = 9\n\t\tDD\t-6526\t; Index = 76 Token = 10\n\t\tDD\t-9136\t; Index = 76 Token = 11\n\t\tDD\t-11747\t; Index = 76 Token = 12\n\t\tDD\t-14357\t; Index = 76 Token = 13\n\t\tDD\t-16968\t; Index = 76 Token = 14\n\t\tDD\t-19578\t; Index = 76 Token = 15\n\t\tDD\t1435\t; Index = 77 Token = 0\n\t\tDD\t4306\t; Index = 77 Token = 1\n\t\tDD\t7178\t; Index = 77 Token = 2\n\t\tDD\t10049\t; Index = 77 Token = 3\n\t\tDD\t12922\t; Index = 77 Token = 4\n\t\tDD\t15793\t; Index = 77 Token = 5\n\t\tDD\t18665\t; Index = 77 Token = 6\n\t\tDD\t21536\t; Index = 77 Token = 7\n\t\tDD\t-1435\t; Index = 77 Token = 8\n\t\tDD\t-4306\t; Index = 77 Token = 9\n\t\tDD\t-7178\t; Index = 77 Token = 10\n\t\tDD\t-10049\t; Index = 77 Token = 11\n\t\tDD\t-12922\t; Index = 77 Token = 12\n\t\tDD\t-15793\t; Index = 77 Token = 13\n\t\tDD\t-18665\t; Index = 77 Token = 14\n\t\tDD\t-21536\t; Index = 77 Token = 15\n\t\tDD\t1579\t; Index = 78 Token = 0\n\t\tDD\t4737\t; Index = 78 Token = 1\n\t\tDD\t7896\t; Index = 78 Token = 2\n\t\tDD\t11054\t; Index = 78 Token = 3\n\t\tDD\t14214\t; Index = 78 Token = 4\n\t\tDD\t17372\t; Index = 78 Token = 5\n\t\tDD\t20531\t; Index = 78 Token = 6\n\t\tDD\t23689\t; Index = 78 Token = 7\n\t\tDD\t-1579\t; Index = 78 Token = 8\n\t\tDD\t-4737\t; Index = 78 Token = 9\n\t\tDD\t-7896\t; Index = 78 Token = 10\n\t\tDD\t-11054\t; Index = 78 Token = 11\n\t\tDD\t-14214\t; Index = 78 Token = 12\n\t\tDD\t-17372\t; Index = 78 Token = 13\n\t\tDD\t-20531\t; Index = 78 Token = 14\n\t\tDD\t-23689\t; Index = 78 Token = 15\n\t\tDD\t1737\t; Index = 79 Token = 0\n\t\tDD\t5211\t; Index = 79 Token = 1\n\t\tDD\t8686\t; Index = 79 Token = 2\n\t\tDD\t12160\t; Index = 79 Token = 3\n\t\tDD\t15636\t; Index = 79 Token = 4\n\t\tDD\t19110\t; Index = 79 Token = 5\n\t\tDD\t22585\t; Index = 79 Token = 6\n\t\tDD\t26059\t; Index = 79 Token = 7\n\t\tDD\t-1737\t; Index = 79 Token = 8\n\t\tDD\t-5211\t; Index = 79 Token = 9\n\t\tDD\t-8686\t; Index = 79 Token = 10\n\t\tDD\t-12160\t; Index = 79 Token = 11\n\t\tDD\t-15636\t; Index = 79 Token = 12\n\t\tDD\t-19110\t; Index = 79 Token = 13\n\t\tDD\t-22585\t; Index = 79 Token = 14\n\t\tDD\t-26059\t; Index = 79 Token = 15\n\t\tDD\t1911\t; Index = 80 Token = 0\n\t\tDD\t5733\t; Index = 80 Token = 1\n\t\tDD\t9555\t; Index = 80 Token = 2\n\t\tDD\t13377\t; Index = 80 Token = 3\n\t\tDD\t17200\t; Index = 80 Token = 4\n\t\tDD\t21022\t; Index = 80 Token = 5\n\t\tDD\t24844\t; Index = 80 Token = 6\n\t\tDD\t28666\t; Index = 80 Token = 7\n\t\tDD\t-1911\t; Index = 80 Token = 8\n\t\tDD\t-5733\t; Index = 80 Token = 9\n\t\tDD\t-9555\t; Index = 80 Token = 10\n\t\tDD\t-13377\t; Index = 80 Token = 11\n\t\tDD\t-17200\t; Index = 80 Token = 12\n\t\tDD\t-21022\t; Index = 80 Token = 13\n\t\tDD\t-24844\t; Index = 80 Token = 14\n\t\tDD\t-28666\t; Index = 80 Token = 15\n\t\tDD\t2102\t; Index = 81 Token = 0\n\t\tDD\t6306\t; Index = 81 Token = 1\n\t\tDD\t10511\t; Index = 81 Token = 2\n\t\tDD\t14715\t; Index = 81 Token = 3\n\t\tDD\t18920\t; Index = 81 Token = 4\n\t\tDD\t23124\t; Index = 81 Token = 5\n\t\tDD\t27329\t; Index = 81 Token = 6\n\t\tDD\t31533\t; Index = 81 Token = 7\n\t\tDD\t-2102\t; Index = 81 Token = 8\n\t\tDD\t-6306\t; Index = 81 Token = 9\n\t\tDD\t-10511\t; Index = 81 Token = 10\n\t\tDD\t-14715\t; Index = 81 Token = 11\n\t\tDD\t-18920\t; Index = 81 Token = 12\n\t\tDD\t-23124\t; Index = 81 Token = 13\n\t\tDD\t-27329\t; Index = 81 Token = 14\n\t\tDD\t-31533\t; Index = 81 Token = 15\n\t\tDD\t2312\t; Index = 82 Token = 0\n\t\tDD\t6937\t; Index = 82 Token = 1\n\t\tDD\t11562\t; Index = 82 Token = 2\n\t\tDD\t16187\t; Index = 82 Token = 3\n\t\tDD\t20812\t; Index = 82 Token = 4\n\t\tDD\t25437\t; Index = 82 Token = 5\n\t\tDD\t30062\t; Index = 82 Token = 6\n\t\tDD\t34687\t; Index = 82 Token = 7\n\t\tDD\t-2312\t; Index = 82 Token = 8\n\t\tDD\t-6937\t; Index = 82 Token = 9\n\t\tDD\t-11562\t; Index = 82 Token = 10\n\t\tDD\t-16187\t; Index = 82 Token = 11\n\t\tDD\t-20812\t; Index = 82 Token = 12\n\t\tDD\t-25437\t; Index = 82 Token = 13\n\t\tDD\t-30062\t; Index = 82 Token = 14\n\t\tDD\t-34687\t; Index = 82 Token = 15\n\t\tDD\t2543\t; Index = 83 Token = 0\n\t\tDD\t7630\t; Index = 83 Token = 1\n\t\tDD\t12718\t; Index = 83 Token = 2\n\t\tDD\t17805\t; Index = 83 Token = 3\n\t\tDD\t22893\t; Index = 83 Token = 4\n\t\tDD\t27980\t; Index = 83 Token = 5\n\t\tDD\t33068\t; Index = 83 Token = 6\n\t\tDD\t38155\t; Index = 83 Token = 7\n\t\tDD\t-2543\t; Index = 83 Token = 8\n\t\tDD\t-7630\t; Index = 83 Token = 9\n\t\tDD\t-12718\t; Index = 83 Token = 10\n\t\tDD\t-17805\t; Index = 83 Token = 11\n\t\tDD\t-22893\t; Index = 83 Token = 12\n\t\tDD\t-27980\t; Index = 83 Token = 13\n\t\tDD\t-33068\t; Index = 83 Token = 14\n\t\tDD\t-38155\t; Index = 83 Token = 15\n\t\tDD\t2798\t; Index = 84 Token = 0\n\t\tDD\t8394\t; Index = 84 Token = 1\n\t\tDD\t13990\t; Index = 84 Token = 2\n\t\tDD\t19586\t; Index = 84 Token = 3\n\t\tDD\t25183\t; Index = 84 Token = 4\n\t\tDD\t30779\t; Index = 84 Token = 5\n\t\tDD\t36375\t; Index = 84 Token = 6\n\t\tDD\t41971\t; Index = 84 Token = 7\n\t\tDD\t-2798\t; Index = 84 Token = 8\n\t\tDD\t-8394\t; Index = 84 Token = 9\n\t\tDD\t-13990\t; Index = 84 Token = 10\n\t\tDD\t-19586\t; Index = 84 Token = 11\n\t\tDD\t-25183\t; Index = 84 Token = 12\n\t\tDD\t-30779\t; Index = 84 Token = 13\n\t\tDD\t-36375\t; Index = 84 Token = 14\n\t\tDD\t-41971\t; Index = 84 Token = 15\n\t\tDD\t3077\t; Index = 85 Token = 0\n\t\tDD\t9232\t; Index = 85 Token = 1\n\t\tDD\t15388\t; Index = 85 Token = 2\n\t\tDD\t21543\t; Index = 85 Token = 3\n\t\tDD\t27700\t; Index = 85 Token = 4\n\t\tDD\t33855\t; Index = 85 Token = 5\n\t\tDD\t40011\t; Index = 85 Token = 6\n\t\tDD\t46166\t; Index = 85 Token = 7\n\t\tDD\t-3077\t; Index = 85 Token = 8\n\t\tDD\t-9232\t; Index = 85 Token = 9\n\t\tDD\t-15388\t; Index = 85 Token = 10\n\t\tDD\t-21543\t; Index = 85 Token = 11\n\t\tDD\t-27700\t; Index = 85 Token = 12\n\t\tDD\t-33855\t; Index = 85 Token = 13\n\t\tDD\t-40011\t; Index = 85 Token = 14\n\t\tDD\t-46166\t; Index = 85 Token = 15\n\t\tDD\t3385\t; Index = 86 Token = 0\n\t\tDD\t10156\t; Index = 86 Token = 1\n\t\tDD\t16928\t; Index = 86 Token = 2\n\t\tDD\t23699\t; Index = 86 Token = 3\n\t\tDD\t30471\t; Index = 86 Token = 4\n\t\tDD\t37242\t; Index = 86 Token = 5\n\t\tDD\t44014\t; Index = 86 Token = 6\n\t\tDD\t50785\t; Index = 86 Token = 7\n\t\tDD\t-3385\t; Index = 86 Token = 8\n\t\tDD\t-10156\t; Index = 86 Token = 9\n\t\tDD\t-16928\t; Index = 86 Token = 10\n\t\tDD\t-23699\t; Index = 86 Token = 11\n\t\tDD\t-30471\t; Index = 86 Token = 12\n\t\tDD\t-37242\t; Index = 86 Token = 13\n\t\tDD\t-44014\t; Index = 86 Token = 14\n\t\tDD\t-50785\t; Index = 86 Token = 15\n\t\tDD\t3724\t; Index = 87 Token = 0\n\t\tDD\t11172\t; Index = 87 Token = 1\n\t\tDD\t18621\t; Index = 87 Token = 2\n\t\tDD\t26069\t; Index = 87 Token = 3\n\t\tDD\t33518\t; Index = 87 Token = 4\n\t\tDD\t40966\t; Index = 87 Token = 5\n\t\tDD\t48415\t; Index = 87 Token = 6\n\t\tDD\t55863\t; Index = 87 Token = 7\n\t\tDD\t-3724\t; Index = 87 Token = 8\n\t\tDD\t-11172\t; Index = 87 Token = 9\n\t\tDD\t-18621\t; Index = 87 Token = 10\n\t\tDD\t-26069\t; Index = 87 Token = 11\n\t\tDD\t-33518\t; Index = 87 Token = 12\n\t\tDD\t-40966\t; Index = 87 Token = 13\n\t\tDD\t-48415\t; Index = 87 Token = 14\n\t\tDD\t-55863\t; Index = 87 Token = 15\n\t\tDD\t4095\t; Index = 88 Token = 0\n\t\tDD\t12286\t; Index = 88 Token = 1\n\t\tDD\t20478\t; Index = 88 Token = 2\n\t\tDD\t28669\t; Index = 88 Token = 3\n\t\tDD\t36862\t; Index = 88 Token = 4\n\t\tDD\t45053\t; Index = 88 Token = 5\n\t\tDD\t53245\t; Index = 88 Token = 6\n\t\tDD\t61436\t; Index = 88 Token = 7\n\t\tDD\t-4095\t; Index = 88 Token = 8\n\t\tDD\t-12286\t; Index = 88 Token = 9\n\t\tDD\t-20478\t; Index = 88 Token = 10\n\t\tDD\t-28669\t; Index = 88 Token = 11\n\t\tDD\t-36862\t; Index = 88 Token = 12\n\t\tDD\t-45053\t; Index = 88 Token = 13\n\t\tDD\t-53245\t; Index = 88 Token = 14\n\t\tDD\t-61436\t; Index = 88 Token = 15\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/DIPTHONG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\nint Dip_Text(char const *source, char *dest);\nint UnDip_Text(char const *source, char *dest);\nchar *Extract_String(void const *data, int string);\nvoid Fixup_Text(char const *source, char *dest);\nextern char Common[];\nextern char Dipthong[16][8];\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/DRAWBUFF.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#ifndef DRAWBUFF_H\n#define DRAWBUFF_H\n\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\nclass GraphicViewPortClass;\nclass GraphicBufferClass;\n/*=========================================================================*/\n/* Define functions which have not under-gone name mangling\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern \"C\" {\n\t/*======================================================================*/\n\t/* Externs for all of the common functions between the video buffer\t\t*/\n\t/*\t\tclass and the graphic buffer class.\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\t long __cdecl Buffer_Size_Of_Region(void *thisptr, int w, int h);\n\n\t void\t__cdecl Buffer_Put_Pixel(void * thisptr, int x, int y, unsigned char color);\n\t int\t__cdecl Buffer_Get_Pixel(void * thisptr, int x, int y);\n\t void\t__cdecl Buffer_Clear(void *thisptr, unsigned char color);\n\t long\t__cdecl Buffer_To_Buffer(void *thisptr, int x, int y, int w, int h, void *buff, long size);\n\t long __cdecl Buffer_To_Page(int x, int y, int w, int h, void *Buffer, void *view);\n\t BOOL\t__cdecl Linear_Blit_To_Linear(\tvoid *thisptr, void * dest, int x_pixel, int y_pixel, int dx_pixel,\n\t\t\t \t\t\t\t\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans);\n\t BOOL __cdecl Linear_Scale_To_Linear(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\n\n\t LONG __cdecl Buffer_Print(void *thisptr, const char *str, int x, int y, int fcolor, int bcolor);\n\n\t/*======================================================================*/\n\t/* Externs for all of the graphic buffer class only functions\t\t\t\t*/\n\t/*======================================================================*/\n\t VOID __cdecl Buffer_Draw_Line(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color);\n\t VOID __cdecl Buffer_Fill_Rect(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color);\n\t VOID __cdecl Buffer_Remap(void * thisptr, int sx, int sy, int width, int height, void *remap);\n\t VOID __cdecl Buffer_Fill_Quad(void * thisptr, VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\t \tint x2, int y2, int x3, int y3, int color);\n\t void __cdecl Buffer_Draw_Stamp(void const *thisptr, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap);\n\t void __cdecl Buffer_Draw_Stamp_Clip(void const *thisptr, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int ,int,int,int);\n\t void * __cdecl Get_Font_Palette_Ptr ( void );\n}\n\nextern GraphicViewPortClass *LogicPage;\nextern BOOL AllowHardwareBlitFills;\n#endif\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/DRAWBUFF.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : DRAWBUFF.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 16, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n; Externs from REGIONSZ.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Size_Of_Region\t:NEAR\n\n; Externs from GETPIX.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Get_Pixel          \t:NEAR\n\n; Externs from PUTPIX.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Put_Pixel \t\t:NEAR\n\n; Externs from CLEAR.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Clear\t          \t:NEAR\n\n; Externs from BITBLIT.ASM module of the DRAWBUFF library\nGLOBAL C Linear_Blit_To_Linear\t\t:NEAR\n\n; Externs from TOBUFF.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_To_Buffer\t\t:NEAR\n\n; Externs from TOPAGE.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_To_Page\t\t:NEAR\n\n; Externs from SCALE.ASM module of the DRAWBUFF library\nGLOBAL C Linear_Scale_To_Linear \t:NEAR\n\n; Externs from TXTPRNT.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Print\t\t\t:NEAR\n\n\n;*-------------------------------------------------------------------------*\n;* Define Buffer only assembly GLOBALS\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n\n; Externs from DRAWLINE.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Draw_Line:NEAR\n\n; Externs from FILLQUAD.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Fill_Quad \t\t:NEAR\n\n; Externs from FILLRECT.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Fill_Rect \t\t:NEAR\n\n; Externs from REMAP.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Remap      \t\t:NEAR\n\n; Externs from STAMP.ASM module of the DRAWBUFF library\nGLOBAL C Buffer_Draw_Stamp \t\t:NEAR\n\nGLOBAL C get_clip\t \t   : NEAR\n\nstruc  RECTANGLE\n\t\t  x0\tdd\t?\n\t\t  y0 dd\t?\n\t\t  x1\tdd\t?\n\t\t  y1 dd ?\nends \t RECTANGLE\n\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/EXTERNS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 Example                          *\n *                                                                         *\n *                    File Name : EXTERNS.H                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\nextern char\tNoTimer;\nextern char\tNoKeyBoard;\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/FILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library - Filio header stuff.            *\n *                                                                         *\n *                    File Name : FILE.H                                 \t*\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : September 13, 1993                       *\n *                                                                         *\n *                  Last Update : April 11, 1994\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FILE_H\n#define FILE_H\n\n#ifndef FILETEMP_H\n// This should be removed once the library is all intacked.\n#include \"filetemp.h\"\n#endif\n\n/*=========================================================================*/\n/* File IO system defines and enumerations\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#define\tXMAXPATH\t80\n\n/*\n**\tThese are the Open_File, Read_File, and Seek_File constants.\n*/\n#ifndef READ\n#define READ\t\t\t\t\t\t1\t// Read access.\n#endif\n#ifndef WRITE\n#define WRITE\t\t\t\t\t\t2\t// Write access.\n#endif\n#ifndef SEEK_SET\n#define SEEK_SET\t\t\t\t\t0\t// Seek from start of file.\n#define SEEK_CUR\t\t\t\t\t1\t// Seek relative from current location.\n#define SEEK_END\t\t\t\t\t2\t// Seek from end of file.\n#endif\n\n\ntypedef enum {\n\tFILEB_PROCESSED=8,// Was the packed file header of this file processed?\n\tFILEB_PRELOAD,\t\t// Scan for and make file resident at WWDOS_Init time?\n\tFILEB_RESIDENT,\t// Make resident at Open_File time?\n\tFILEB_FLUSH,\t\t// Un-resident at Close_File time?\n\tFILEB_PACKED,\t\t// Is this file packed?\n\tFILEB_KEEP,\t\t\t// Don't ever flush this resident file?\n\tFILEB_PRIORITY,\t// Flush this file last?\n\n\tFILEB_LAST\n} FileFlags_Type;\n\n#define\tFILEF_NONE\t\t\t0\n#define\tFILEF_PROCESSED\t(1<<FILEB_PROCESSED)\n#define\tFILEF_PRELOAD\t\t(1<<FILEB_PRELOAD)\n#define\tFILEF_RESIDENT\t\t(1<<FILEB_RESIDENT)\n#define\tFILEF_FLUSH\t\t\t(1<<FILEB_FLUSH)\n#define\tFILEF_PACKED\t\t(1<<FILEB_PACKED)\n#define\tFILEF_KEEP\t\t\t(1<<FILEB_KEEP)\n#define\tFILEF_PRIORITY\t\t(1<<FILEB_PRIORITY)\n\n/*\n** These errors are returned by WWDOS_Init().  All errors encountered are\n** or'd together so there may be more then one error returned.  Not all\n** errors are fatal, such as the cache errors.\n*/\ntypedef enum {\n\tFI_SUCCESS\t\t\t\t\t\t= 0x00,\n\tFI_CACHE_TOO_BIG\t\t\t\t= 0x01,\n\tFI_CACHE_ALREADY_INIT\t\t= 0x02,\n\tFI_FILEDATA_FILE_NOT_FOUND\t= 0x04,\n\tFI_FILEDATA_TOO_BIG\t\t\t= 0x08,\n \tFI_SEARCH_PATH_NOT_FOUND\t= 0x10,\n \tFI_STARTUP_PATH_NOT_FOUND\t= 0x20,\n\tFI_NO_CACHE_FOR_PRELOAD\t\t= 0x40,\n\tFI_FILETABLE_NOT_INIT\t\t= 0x80,\n} FileInitErrorType;\n\n\n/*\n**\tThese are the errors that are detected by the File I/O system and\n**\tpassed to the io error routine.\n*/\n//lint -strong(AJX,FileErrorType)\ntypedef enum {\n\tCANT_CREATE_FILE,\n\tBAD_OPEN_MODE,\n\tCOULD_NOT_OPEN,\n\tTOO_MANY_FILES,\n\tCLOSING_NON_HANDLE,\n\tREADING_NON_HANDLE,\n\tWRITING_NON_HANDLE,\n\tSEEKING_NON_HANDLE,\n\tSEEKING_BAD_OFFSET,\n\tWRITING_RESIDENT,\n\tUNKNOWN_INDEX,\n\tDID_NOT_CLOSE,\n\tFATAL_ERROR,\n\tFILE_NOT_LISTED,\n\tFILE_LENGTH_MISMATCH,\n\tINTERNAL_ERROR,\n\tMAKE_RESIDENT_ZERO_SIZE,\n\tRESIDENT_SORT_FAILURE,\n\n\tNUMBER_OF_ERRORS\t\t\t\t/* MAKE SURE THIS IS THE LAST ENTRY */\n} FileErrorType;\n\n// This is here tempararaly until library is put together.\n//extern WORD __cdecl ( __cdecl IO_Error)(FileErrorType error, BYTE const *filename);\nextern short (*Open_Error)(FileErrorType, BYTE const *);\n\n/*=========================================================================*/\n/* File IO system structures\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//lint -strong(AJX,FileDataType)\ntypedef struct {\n\tchar\t*Name;\t\t// File name (include sub-directory but not volume).\n\tlong\tSize;\t\t\t// File size (0=indeterminate).\n\tvoid\t*Ptr;\t\t\t// Resident file pointer.\n\tlong\tStart;\t\t// Starting offset in DOS handle file.\n\tunsigned char\tDisk;\t\t\t// Disk number location.\n\tunsigned char\tOpenCount;\t// Count of open locks on resident file.\n\tunsigned short\tFlag;\t\t\t// File control flags.\n} FileDataType;\n\n\n/*=========================================================================*/\n/* FIle IO system globals.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n// These are cpp errors in funtions declarations\tJULIO JEREZ\n\n// extern FileDataType __cdecl FileData[];\n// extern BYTE __cdecl ExecPath[XMAXPATH + 1];\n// extern BYTE __cdecl DataPath[XMAXPATH + 1];\n// extern BYTE __cdecl StartPath[XMAXPATH + 1];\n// extern BOOL __cdecl UseCD;\n\n// The correct syntax is  NO TYPE MODIFIER APPLY TO DATA DECLARATIONS\nextern FileDataType FileData[];\nextern char ExecPath[XMAXPATH + 1];\nextern char DataPath[XMAXPATH + 1];\nextern char StartPath[XMAXPATH + 1];\nextern BOOL UseCD;\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILEINIT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid __cdecl WWDOS_Shutdown(void);\nFileInitErrorType __cdecl WWDOS_Init(unsigned long cachesize, char *filedata, char *cdpath);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILE.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Open_File(char const *file_name, int mode);\nvoid __cdecl Close_File(int handle);\nlong __cdecl Read_File(int handle, void *buf, unsigned long bytes);\nint __cdecl Load_File ( const char *file_name , void *load_addr);\nlong __cdecl Write_File(int handle, void const *buf, unsigned long bytes);\nunsigned long __cdecl Seek_File(int handle, long offset, int starting);\nint __cdecl File_Exists(char const *file_name);\nunsigned long __cdecl File_Size(int handle);\nBOOL __cdecl Is_Handle_Valid(int handle, FileErrorType error, char const *name);\nint __cdecl Open_File_With_Recovery( char const *file_name, unsigned int mode );\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILECACH.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid Unfragment_File_Cache(void);\nBOOL __cdecl Make_File_Resident(char const *filename);\nint __cdecl Flush_Unused_File_Cache(int flush_keeps);\nBOOL __cdecl Free_Resident_File(char const *file);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILECHNG.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Create_File(char const *file_name);\nint __cdecl Delete_File(char const *file_name);\nBOOL __cdecl Change_File_Size(int handle, unsigned long new_size);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILEINFO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Get_DOS_Handle(int fh);\nint __cdecl Free_Handles(void);\nint __cdecl Find_Disk_Number(char const *file_name);\nint __cdecl Set_File_Flags(char const *filename, int flags);\nint __cdecl Clear_File_Flags(char const *filename, int flags);\nint __cdecl Get_File_Flags(char const *filename);\nBOOL __cdecl Multi_Drive_Search(BOOL on);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FINDFILE.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Find_File(char const *file_name);\nint __cdecl Find_File_Index(char const *filename);\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FFIRST.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#include <dos.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern int __cdecl Find_First(unsigned char *fname, unsigned int mode, struct find_t *ffblk);\nextern int __cdecl Find_Next(struct find_t *ffblk);\n\n#ifdef __cplusplus\n}\n#endif\n\n\n\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/FILEPCX.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : iff                                      *\n;*                                                                         *\n;*                    File Name : FILEPCX.H                                *\n;*                                                                         *\n;*                   Programmer : Julio R. Jerez                           *\n;*                                                                         *\n;*                   Start Date : May 2, 1995                              *\n;*                                                                         *\n;*                  Last Update : May 2, 1995   [JRJ]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* GraphicBufferClass* Read_PCX_File (char* name, BYTE* palette,void *buff, long size);\n;* GraphicBufferClass* Read_PCX_File (char* name, BYTE* palette, BufferClass& Buff); \n;* int Write_PCX_File (char* name, GraphicViewPortClass& pic, BYTE* palette );*\n;*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n#include <gbuffer.h>\n#include <string.h>\n#include <buffer.h>\n#include\t<file.h>\n\n#ifndef PCX_H\n#define PCX_H\n\n\ntypedef\tstruct {\n\t\t\t\t\t\t  char\tred ;\n\t\t\t\t\t\t  char\tgreen ;\n\t\t\t\t\t\t  char\tblue ;\n\t\t\t\t\t} RGB ;\n\ntypedef\tstruct\t{\n\t\t\t\t\t\t  char      id ;\n\t\t\t\t\t\t  char\t   version ;\n\t\t\t\t\t\t  char\t   encoding ;\n\t\t\t\t\t\t  char\t   pixelsize ;\n\t\t\t\t\t\t  short \t   x ;\n\t\t\t\t\t\t  short\t\ty ;\n\t\t\t\t\t\t  short     width ;\n\t\t\t\t\t\t  short\t\theight ;\n\t\t\t\t\t\t  short \t   xres ;\n\t\t\t\t\t\t  short\t\tyres ;\n\t\t\t\t\t\t  RGB       ega_palette [ 16 ] ;\n\t\t\t\t\t\t  char\t   nothing ;\n\t\t\t\t\t\t  char      color_planes ;\n\t\t\t\t\t\t  short \t\tbyte_per_line ;\n\t\t\t\t\t\t  short \t \tpalette_type ;\n\t\t\t\t\t\t  char\t   filler [ 58 ] ;\n\t\t\t\t\t\t} PCX_HEADER ;\n\nGraphicBufferClass* Read_PCX_File (char* name, char* palette= NULL,void *buff=NULL, long size=0);\nGraphicBufferClass* Read_PCX_File (char* name, BufferClass& Buff,char* palette= NULL) ;\nint Write_PCX_File (char* name, GraphicViewPortClass& pic, unsigned char* palette );\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/FILETEMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Temp header for file routines.           *\n *                                                                         *\n *                    File Name : FILETEMP.H                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 20, 1994                           *\n *                                                                         *\n *                  Last Update : April 20, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FILETEMP_H\n#define FILETEMP_H\n\n/////////////////////////////////////////////////////////////////////\n// THIS DOES NOT BELONG HERE.  IT WAS PUT HERE JUST TO GET THE THING\n// TO COMPILE.  ONCE THE BUFFER AND PAGE SYSTEMS ARE PUT IN, THESE\n// WILL NEED TO BE TAKEN OUT AND MODS MADE TO ANY FUNCTION USING BuffType.\n// SKB 4/20/94.\n\n\n\n/*=========================================================================*/\n/* Defines and such that must go into wwstd.h\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n// Look at FileErrorType below for the IO_Error function.\n//extern WORD __cdecl ( __cdecl IO_Error)(FileErrorType error, BYTE const *filename);\nVOID __cdecl Prog_End(VOID);\nextern WORD Hard_Error_Occured;\n\n\n\n//////////////////////// END OF DON'T BELONG //////////////////////////////////\n\n#endif //FILETEMP_H\n\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/FONT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Font and text print 32 bit library       *\n *                                                                         *\n *                    File Name : FONT.H                                   *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : June 27, 1994                            *\n *                                                                         *\n *                  Last Update : June 29, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   VVPC::Text_Print -- Text print into a virtual viewport.               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FONT_H\n#define FONT_H\n\n#ifndef GBUFFER_H\n#include <gbuffer.h>\n#endif\n\n\n//////////////////////////////////////// Defines //////////////////////////////////////////\n\n// defines for font header, offsets to block offsets\n\n#define FONTINFOBLOCK\t\t\t4\n#define FONTOFFSETBLOCK\t\t\t6\n#define FONTWIDTHBLOCK\t\t\t8\n#define FONTDATABLOCK\t\t\t10\n#define FONTHEIGHTBLOCK\t\t\t12\n\n// defines for font info block\n\n#define FONTINFOMAXHEIGHT\t\t4\n#define FONTINFOMAXWIDTH\t\t5\n\n//////////////////////////////////////// Prototypes //////////////////////////////////////////\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SET_FONT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid  * __cdecl Set_Font(void const *fontptr);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FONT.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Char_Pixel_Width(char chr);\nunsigned int __cdecl String_Pixel_Width(char const *string);\nvoid __cdecl Get_Next_Text_Print_XY(GraphicViewPortClass& vp, unsigned long offset, INT *x, INT *y);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOADFONT.CPP\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid * __cdecl Load_Font(char  const *name);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TEXTPRNT.ASM\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\nvoid __cdecl Set_Font_Palette_Range(void const *palette, INT start_idx, INT end_idx);\n\n\n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n\n\n\n\n\n//////////////////////////////////////// External varables ///////////////////////////////////////\nextern \"C\" int FontXSpacing;\nextern \"C\" int FontYSpacing;\nextern char FontWidth ;\nextern char FontHeight;\nextern char *FontWidthBlockPtr;\n\n\nextern \"C\" void const *FontPtr;\n\n\n\n\n#endif // FONT_H\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/FUNCTION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SOUNDIO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort Decompress_Frame(void * source, void * dest, short size);\nint __cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback);\nint __cdecl Stream_Sample(void *buffer, long size, BOOL (*callback);\nint __cdecl File_Stream_Sample(char const *filename);\nint __cdecl File_Stream_Sample_Vol(char const *filename, int volume);\nvoid __cdecl _saveregs _loadds Sound_Callback(void);\nvoid __cdecl far _saveregs _loadds maintenance_callback(void);\nvoid  __cdecl Load_Sample(char const *filename);\nlong __cdecl Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);\nlong __cdecl Sample_Read(int fh, void *buffer, long size);\nvoid __cdecl Free_Sample(void const *sample);\nBOOL __cdecl Sound_Init(int sfx, int score, int sample);\nvoid far VQA_TimerCallback(void);\nBOOL Audio_Init(int sample, int address, int inter, int dma);\nvoid __cdecl Sound_End(void);\nvoid __cdecl Stop_Sample(int handle);\nBOOL __cdecl Sample_Status(int handle);\nBOOL __cdecl Is_Sample_Playing(void const * sample);\nvoid __cdecl Stop_Sample_Playing(void const * sample);\nint __cdecl Play_Sample(void const *sample);\nint __cdecl Play_Sample_Vol(void const *sample, int priority, int volume);\nint __cdecl Set_Sound_Vol(int volume);\nint __cdecl Set_Score_Vol(int volume);\nvoid __cdecl Fade_Sample(int handle, int ticks);"
  },
  {
    "path": "WIN32LIB/INCLUDE/GBUFFER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : GBUFFER.H                                *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 26, 1994                             *\n *                                                                         *\n *                  Last Update : October 9, 1995   []                     *\n *                                                                         *\n ***************************************************************************\n *                                                                         *\n *\tThis module contains the definition for the graphic buffer class.  The\t*\n * primary functionality of the graphic buffer class is handled by inline\t*\n * functions that make a call through function pointers to the correct\t\t*\n * routine.  This has two benefits:\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t1) C++ name mangling is not a big deal since the function pointers\t*\n *\t\t   point to functions in standard C format.\t\t\t\t\t\t\t\t\t*\n *\t\t2) The function pointers can be changed when we set a different\t\t*\n *       graphic mode.  This allows us to have both supervga and mcga\t\t*\n *\t\t\troutines present in memory at once.\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * In the basic library, these functions point to stub routines which just\t*\n * return.  This makes a product that just uses a graphic buffer take the\t*\n * minimum amount of code space.  For programs that require MCGA or VESA\t*\n * support, all that is necessary to do is link either the MCGA or VESA\t\t*\n * specific libraries in, previous to WWLIB32.  The linker will then \t\t*\n * overide the the necessary stub functions automatically.\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * In addition, there are helpful inline function calls for parameter\t\t*\n * ellimination.  This header file gives the defintion for all\t\t\t\t\t*\n * GraphicViewPort and GraphicBuffer classes.  \t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Terminology:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tBuffer Class - A class which consists of a pointer to an allocated\t\t*\n *\t\tbuffer and the size of the buffer that was allocated.\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tGraphic ViewPort - The Graphic ViewPort defines a window into a \t\t\t*\n *\t\tGraphic Buffer.  This means that although a Graphic Buffer \t\t\t\t*\n *\t\trepresents linear memory, this may not be true with a Graphic\t\t\t*\n *\t\tViewport.  All low level functions that act directly on a graphic\t\t*\n *\t\tviewport are included within this class.  This includes but is not\t*\n *\t\tlimited to most of the functions which can act on a Video Viewport\t*\n *\t\tVideo Buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Graphic Buffer - A Graphic Buffer is an instance of an allocated buffer\t*\n *\t\tused to represent a rectangular region of graphics memory.\t\t\t\t*\n *\t\tThe HidBuff\tand BackBuff are excellent examples of a Graphic Buffer.\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Below is a tree which shows the relationship of the VideoBuffer and \t\t*\n * Buffer classes to the GraphicBuffer class:\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t  BUFFER.H\t\t\t\t GBUFFER.H\t\t\t  BUFFER.H\t\t\t\t VBUFFER.H\t*\n *  ----------          ----------         ----------          ----------\t*\n * |  Buffer  |        | Graphic  |       |  Buffer  |        |  Video   |\t*\n * |  Class   |        | ViewPort |       |  Class   |        | ViewPort |\t*\n *  ----------          ----------         ----------          ----------\t*\n *            \\        /                             \\        /\t\t\t\t*\n *             \\      /                               \\      /\t\t\t\t\t*\n *            ----------                             ----------\t\t\t\t*\n *           |  Graphic |                           |  Video   |\t\t\t\t*\n *           |  Buffer  |                           |  Buffer  |\t\t\t\t*\n *            ----------                             ---------- \t\t\t\t*\n *\t  \t\t\t  GBUFFER.H\t\t\t                       VBUFFER.H\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   GBC::GraphicBufferClass -- inline constructor for GraphicBufferClass  *\n *   GVPC::Remap -- Short form to remap an entire graphic view port        *\n *   GVPC::Get_XPos -- Returns x offset for a graphic viewport class       *\n *   GVPC::Get_Ypos -- Return y offset in a GraphicViewPortClass           *\n *   VVPC::Get_XPos -- Get the x pos of the VP on the Video                *\n *   VVPC::Get_YPos -- Get the y pos of the VP on the video                *\n *   GBC::Get_Graphic_Buffer -- Get the graphic buffer of the VP.          *\n *   GVPC::Draw_Line -- Stub function to draw line in Graphic Viewport Class*\n *   GVPC::Fill_Rect -- Stub function to fill rectangle in a GVPC          *\n *   GVPC::Remap -- Stub function to remap a GVPC                          *\n *   GVPC::Print -- stub func to print a text string                       *\n *   GVPC::Print -- Stub function to print an integer                      *\n *   GVPC::Print -- Stub function to print a short to a graphic viewport   *\n *   GVPC::Print -- stub function to print a long on a graphic view port   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n\n#define WIN32_LEAN_AND_MEAN\n#include <ddraw.h>\n\n\n#ifndef GBUFFER_H\n#define GBUFFER_H\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n#ifndef DRAWBUFF_H\n#include \"drawbuff.h\"\n#endif\n\n//#ifndef BUFFER_H\n#include \"buffer.h\"\n//#endif\n\n#ifndef WINDOWS_H\n#include \"ww_win.h\"\n#endif\n#include <stdlib.h>\n\n#include \"iconcach.h\"\n\n\n\n#ifndef FUNCTION_H\n\n#pragma off (unreferenced)\n\n#ifndef BITMAPCLASS\n#define BITMAPCLASS\nclass BitmapClass\n{\n\tpublic:\n\t\tBitmapClass(int w, int h, unsigned char * data) :\n\t\t\tWidth(w), Height(h), Data(data) {};\n\n\t\tint Width;\n\t\tint Height;\n\t\tunsigned char * Data;\n};\n\nclass TPoint2D\n{\n\tpublic:\n\t\tTPoint2D(int xx, int yy) : x(xx), y(yy) {};\n\t\tTPoint2D(void) : x(0), y(0) {};\n\n\t\tint x;\n\t\tint y;\n};\n#endif\n\n#pragma on (unreferenced)\n#endif\n\n\n//////////////////////////////////////////////////////////////////////////\n//\n// Defines for direct draw\n//\n//\nextern\tLPDIRECTDRAW\tDirectDrawObject;\t//pointer to direct draw object\nextern\tHWND\t\t\tMainWindow;\t\t\t//handle to programs main window\n\n/*\n** Pointer to function to call if we detect a focus loss\n*/\nextern\tvoid (*Gbuffer_Focus_Loss_Function)(void);\n\nenum GBC_Enum {\n\tGBC_NONE\t\t\t\t= 0,\n\tGBC_VIDEOMEM\t\t= 1,\n\tGBC_VISIBLE\t\t\t= 2,\n};\n\n#define\tNOT_LOCKED\t\tNULL\n\n/*=========================================================================*/\n/* Define the screen width and height to make portability to other modules\t*/\n/*\t\teasier.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tDEFAULT_SCREEN_WIDTH\t\t320\n#define\tDEFAULT_SCREEN_HEIGHT\t200\n\n/*=========================================================================*/\n/* Let the compiler know that a GraphicBufferClass exists so that it can\t*/\n/*\t\tkeep a pointer to it in a VideoViewPortClass.\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nclass GraphicViewPortClass;\nclass GraphicBufferClass;\nclass VideoViewPortClass;\nclass VideoBufferClass;\n\nGraphicViewPortClass *Set_Logic_Page(GraphicViewPortClass *ptr);\nGraphicViewPortClass *Set_Logic_Page(GraphicViewPortClass &ptr);\n\n/*=========================================================================*/\n/* GraphicViewPortClass - Holds viewport information on a viewport which\t*/\n/*\t\thas been attached to a GraphicBuffer.  A viewport is effectively a\t*/\n/*\t\trectangular subset of the full buffer which is used for clipping and\t*/\n/*\t\tthe like.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tchar\t  \t*Buffer\t-\t\tis the offset to view port buffer\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis the width of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis the height of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis add value to go from the end of a line\t*/\n/*\t\t\t\t\t\t\t\t\t\t\tto the beginning of the next line\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\tx offset into its associated VideoBuffer\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\ty offset into its associated VideoBuffer\t*/\n/*=========================================================================*/\nclass GraphicViewPortClass {\n\tpublic:\n\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tGraphicViewPortClass(GraphicBufferClass* graphic_buff, int x, int y, int w, int h);\n\t\tGraphicViewPortClass();\n\t\t~GraphicViewPortClass();\n\n\t\t/*===================================================================*/\n\t\t/* define functions to get at the private data members\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\tGet_Offset(void);\n\t\tint\tGet_Height(void);\n\t\tint\tGet_Width(void);\n\t\tint\tGet_XAdd(void);\n\t\tint\tGet_XPos(void);\n\t\tint\tGet_YPos(void);\n\t\tint\tGet_Pitch(void);\n\t\tinline BOOL\tGet_IsDirectDraw(void);\n\t\tGraphicBufferClass\t*Get_Graphic_Buffer(void);\n\n\t\t/*===================================================================*/\n\t\t/* Define a function which allows us to change a video viewport on\t*/\n\t\t/*\t\tthe fly.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBOOL Change(int x, int y, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the set of common graphic functions that are supported by\t*/\n\t\t/*\t\tboth Graphic ViewPorts and VideoViewPorts.\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\tSize_Of_Region(int w, int h);\n\t\tvoid\tPut_Pixel(int x, int y, unsigned char color);\n\t\tint\tGet_Pixel(int x, int y);\n\t\tvoid\tClear(unsigned char color = 0);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, void *buff, long size);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, BufferClass *buff);\n\t\tlong\tTo_Buffer(BufferClass *buff);\n\t\tHRESULT\tBlit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel,\n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tHRESULT\tBlit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tHRESULT\tBlit(\tGraphicViewPortClass& dest, BOOL trans = FALSE);\n\t\tHRESULT\tBlit(\tVideoViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel,\n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tHRESULT\tBlit(\tVideoViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tHRESULT\tBlit(\tVideoViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, char *remap);\n\t\tunsigned long\tPrint(char const *string, int x_pixel, int y_pixel, int fcolor, int bcolor);\n\t\tunsigned long\tPrint(short num, int x_pixel, int y_pixel, int fcol, int bcol);\n\t\tunsigned long\tPrint(int num, int x_pixel, int y_pixel, int fcol, int bcol);\n\t\tunsigned long\tPrint(long num, int x_pixel, int y_pixel, int fcol, int bcol);\n\n\t\t/*===================================================================*/\n\t\t/* Define the list of graphic functions which work only with a \t\t*/\n\t\t/*\t\tgraphic buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Draw_Line(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Draw_Rect(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Fill_Rect(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Fill_Quad(VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\tint x2, int y2, int x3, int y3, int color);\n\t\tVOID Remap(int sx, int sy, int width, int height, VOID *remap);\n\t\tVOID Remap(VOID *remap);\n\t\tvoid Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap);\n\t\tvoid Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int clip_window);\n\n//\tThis doesnt seem to exist anywhere?? - Steve T 9/26/95 6:05PM\n//\t\tVOID Grey_Out_Region(int x, int y, int width, int height, int color);\n\n\t\t//\n\t\t// New members to lock and unlock the direct draw video memory\n\t\t//\n\t\tinline BOOL \tLock ();\n\t\tinline BOOL \tUnlock();\n\t\tinline int\t\tGet_LockCount();\n\n\t\t// Member to blit using direct draw access to hardware blitter\n\t\tHRESULT DD_Linear_Blit_To_Linear ( GraphicViewPortClass &dest, int source_x, int source_y, int dest_x, int dest_y, int width\t, int height, BOOL mask );\n\n\t\t/*===================================================================*/\n\t\t/* Define functions to attach the viewport to a graphicbuffer\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Attach(GraphicBufferClass *graphic_buff, int x, int y, int w, int h);\n\t\tvoid Attach(GraphicBufferClass *video_buff, int w, int h);\n\n\tprotected:\n\n\t\t/*===================================================================*/\n\t\t/* Define the data used by a GraphicViewPortClass\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\t\t\t\t\tOffset;\t\t\t// offset to graphic page\n\t\tint\t\t\t\t\t\tWidth;\t\t\t// width of graphic page\n\t\tint\t\t\t\t\t\tHeight;\t\t\t// height of graphic page\n\t\tint\t\t\t\t\t\tXAdd;\t\t\t// xadd for graphic page (0)\n\t\tint\t\t\t\t\t\tXPos;\t\t\t// x offset in relation to graphicbuff\n\t\tint\t\t\t\t\t\tYPos;\t\t\t// y offset in relation to graphicbuff\n\t\tlong\t\t\t\t\tPitch;\t\t\t//Distance from one line to the next\n\t\tGraphicBufferClass\t\t*GraphicBuff;\t// related graphic buff\n\t\tBOOL\t\t\t\t\tIsDirectDraw;\t//Flag to let us know if it is a direct draw surface\n\t\tint\t\t\t\t\t\tLockCount;\t\t// Count for stacking locks if non-zero the buffer\n};                                              //   is a locked DD surface\n\n/*=========================================================================*/\n/* GraphicBufferClass - A GraphicBuffer refers to an actual instance of an\t*/\n/*\t\tallocated buffer.  The GraphicBuffer may be drawn to directly \t\t\t*/\n/*\t\tbecuase it inherits a ViewPort which represents its physcial size.\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tBYTE\t  \t*Buffer\t-\t\tis the offset to graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis the width of graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis the height of graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis the xadd of graphic buffer\t\t\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\twill be 0 because it is graphicbuff\t\t\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\twill be 0 because it is graphicbuff\t\t\t*/\n/*\t\t\tlong\tPitch\t\t-\t\tmodulo of buffer for reading and writing\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tBOOL\tIsDirectDraw - \t\tflag if its a direct draw surface\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nclass GraphicBufferClass : public GraphicViewPortClass, public BufferClass {\n\n\tpublic:\n\t\tGraphicBufferClass(int w, int h, GBC_Enum flags);\n\t\tGraphicBufferClass(int w, int h,\tvoid *buffer, long size);\n\t\tGraphicBufferClass(int w, int h, void *buffer = 0);\n\t\tGraphicBufferClass(void);\n\t\t~GraphicBufferClass();\n\n\t\tvoid DD_Init(GBC_Enum flags);\n\t\tvoid Init(int w, int h, void *buffer, long size, GBC_Enum flags);\n\t\tvoid Un_Init(void);\n\t\tvoid GraphicBufferClass::Attach_DD_Surface (GraphicBufferClass * attach_buffer);\n\t\tBOOL Lock(void);\n\t\tBOOL Unlock(void);\n\n\t\tvoid Scale_Rotate(BitmapClass &bmp,TPoint2D const &pt,long scale,unsigned char angle);\n\n\t\t// Member to get a pointer to a direct draw surface\n\t\tLPDIRECTDRAWSURFACE Get_DD_Surface ( void );\n\n\tprotected:\n\t\tLPDIRECTDRAWSURFACE\tVideoSurfacePtr;\t\t//Pointer to the related direct draw surface\n\t\tDDSURFACEDESC\t\t\tVideoSurfaceDescription;//Description of the said surface\n\n};\n\n\n\ninline int GraphicViewPortClass::Get_LockCount(void)\n{\n\treturn (LockCount);\n}\n\n\n\n/***********************************************************************************************\n * GVPC::Get_IsDirectDraw -- provide read access to the IsDirectDraw flag                      *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   IsDirectDraw                                                                      *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/29/95 1:02PM ST : Created                                                             *\n *=============================================================================================*/\ninline BOOL GraphicViewPortClass::Get_IsDirectDraw(void)\n{\n\treturn (IsDirectDraw);\n}\n\n\n\n/***********************************************************************************************\n * GBC::Get_DD_Surface -- returns a pointer to the buffer direct draw surface                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   ptr to direct draw surface                                                        *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/29/95 9:43AM ST : Created                                                              *\n *=============================================================================================*/\ninline LPDIRECTDRAWSURFACE GraphicBufferClass::Get_DD_Surface ( void )\n{\n\treturn ( VideoSurfacePtr );\n\n}\n\n\n\n/***********************************************************************************************\n * GVPC::Lock -- lock the graphics buffer for reading or writing                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   TRUE if surface was successfully locked                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09-19-95 12:33pm ST : Created                                                             *\n *   10/09/1995     : Moved actually functionality to GraphicBuffer                            *\n *=============================================================================================*/\ninline BOOL GraphicViewPortClass::Lock(void)\n{\n\tBOOL lock = GraphicBuff->Lock();\n\tif ( !lock ) return(FALSE);\n\n\tif (this != GraphicBuff) {\n\t\tAttach(GraphicBuff, XPos, YPos,  Width, Height);\n\t}\n\treturn(TRUE);\n}\n\n/***********************************************************************************************\n * GVPC::Unlock -- unlock the video buffer                                                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   TRUE if surface was successfully unlocked                                         *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09-19-95 02:20pm ST : Created                                                             *\n *   10/09/1995     : Moved actually functionality to GraphicBuffer                            *\n *=============================================================================================*/\ninline BOOL GraphicViewPortClass::Unlock(void)\n{\n\tBOOL unlock = GraphicBuff->Unlock();\n\tif (!unlock) return(FALSE);\n\tif (this != GraphicBuff && IsDirectDraw && !GraphicBuff->LockCount) {\n\t\tOffset = 0;\n\t}\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * GVPC::GET_OFFSET -- Get offset for virtual view port class instance     *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long the offset for the virtual viewport instance           *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long GraphicViewPortClass::Get_Offset(void)\n{\n\treturn(Offset);\n}\n\n/***************************************************************************\n * GVPC::GET_HEIGHT -- Gets the height of a virtual viewport instance      *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the height of the virtual viewport instance            *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_Height(void)\n{\n\treturn(Height);\n}\n\n/***************************************************************************\n * GVPC::GET_WIDTH -- Get the width of a virtual viewport instance\t\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the width of the virtual viewport instance             *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_Width(void)\n{\n\treturn(Width);\n}\n\n\n/***************************************************************************\n * GVPC::GET_XADD -- Get the X add offset for virtual viewport instance    *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the xadd for a virtual viewport instance               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_XAdd(void)\n{\n\treturn(XAdd);\n}\n/***************************************************************************\n * GVPC::GET_XPOS -- Get the x pos of the VP on the Video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_XPos(void)\n{\n\treturn(XPos);\n}\n\n\n/***************************************************************************\n * GVPC::GET_YPOS -- Get the y pos of the VP on the video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_YPos(void)\n{\n\treturn(YPos);\n}\n\n/***************************************************************************\n * GVPC::GET_GRAPHIC_BUFFER -- Get the graphic buffer of the VP.            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline GraphicBufferClass *GraphicViewPortClass::Get_Graphic_Buffer(void)\n{\n\treturn (GraphicBuff);\n}\n\n/***************************************************************************\n * GVPC::SIZE_OF_REGION -- stub to call curr graphic mode Size_Of_Region\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/01/1995 BWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::Size_Of_Region(int w, int h)\n{\n\treturn Buffer_Size_Of_Region(this, w, h);\n}\n\n\n/***************************************************************************\n * GVPC::PUT_PIXEL -- stub to call curr graphic mode Put_Pixel\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tGraphicViewPortClass::Put_Pixel(int x, int y, unsigned char color)\n{\n\n\tif (Lock()){\n\t\tBuffer_Put_Pixel(this, x, y, color);\n\t}\n\tUnlock();\n\n\n}\n\n/***************************************************************************\n * GVPC::GET_PIXEL -- stub to call curr graphic mode Get_Pixel          \t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline int\tGraphicViewPortClass::Get_Pixel(int x, int y)\n{\n\tint\t\treturn_code=0;\n\n\tif (Lock()){\n\t\treturn_code=(Buffer_Get_Pixel(this, x, y));\n\t}\n\tUnlock();\n\treturn(return_code);\n\n}\n\n/***************************************************************************\n * GVPC::CLEAR -- stub to call curr graphic mode Clear\t                  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tGraphicViewPortClass::Clear(unsigned char color)\n{\n\tif (Lock()){\n\t\tBuffer_Clear(this, color);\n\t}\n\tUnlock();\n\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 1 to call curr graphic mode To_Buffer\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(int x, int y, int w, int h, void *buff, long size)\n{\n\tlong\treturn_code=0;\n\tif (Lock()){\n\t\treturn_code = (Buffer_To_Buffer(this, x, y, w, h, buff, size));\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 2 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(int x, int y, int w, int h, BufferClass *buff)\n{\n\tlong\treturn_code=0;\n\tif (Lock()){\n\t\treturn_code = (Buffer_To_Buffer(this, x, y, w, h, buff->Get_Buffer(), buff->Get_Size()));\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 3 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(BufferClass *buff)\n{\n\tlong\treturn_code=0;\n\tif (Lock()){\n\t\treturn_code = (Buffer_To_Buffer(this, 0, 0, Width, Height, buff->Get_Buffer(), buff->Get_Size()));\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 1 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline HRESULT\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel,\n\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans)\n{\n\tHRESULT\t\treturn_code=0;\n\n\tif ( IsDirectDraw && dest.IsDirectDraw ){\n\treturn(DD_Linear_Blit_To_Linear( dest, XPos+x_pixel, YPos+y_pixel\n\t\t\t\t\t\t\t\t, dest.Get_XPos()+dx_pixel, dest.Get_YPos()+dy_pixel\n\t\t\t\t\t\t\t\t, pixel_width, pixel_height, trans));\n\t} else {\n\n\t\tif (Lock()){\n\t\t\tif (dest.Lock()){\n\t\t\t\treturn_code=(Linear_Blit_To_Linear(this, &dest, x_pixel, y_pixel\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t, dx_pixel, dy_pixel\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t, pixel_width, pixel_height, trans));\n\t\t\t}\n\t\t\tdest.Unlock();\n\t\t}\n\t\tUnlock();\n\t}\n\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::BLIT -- Stub 2 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline HRESULT\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans)\n{\n\tHRESULT\t\treturn_code=0;\n\n\n\tif ( IsDirectDraw && dest.IsDirectDraw ){\n\treturn(DD_Linear_Blit_To_Linear( dest, XPos, YPos\n\t\t\t\t\t\t\t\t, dest.Get_XPos()+dx, dest.Get_YPos()+dy\n\t\t\t\t\t\t\t\t, Width, Height, trans));\n\t} else {\n\n\t\tif (Lock()){\n\t\t\tif (dest.Lock()){\n\t\t\t\treturn_code=(Linear_Blit_To_Linear(this, &dest, 0, 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t, dx, dy\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t, Width, Height, trans));\n\t\t\t}\n\t\t\tdest.Unlock();\n\t\t}\n\t\tUnlock();\n\t}\n\n\treturn (return_code);\n\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 3 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline HRESULT\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, BOOL trans)\n{\n\tHRESULT\t\treturn_code=0;\n\n\n\tif ( IsDirectDraw && dest.IsDirectDraw ){\n\treturn(DD_Linear_Blit_To_Linear( dest, XPos, YPos\n\t\t\t\t\t\t\t\t, dest.Get_XPos(), dest.Get_YPos()\n\t\t\t\t\t\t\t\t, MAX( Width, dest.Get_Width())\n\t\t\t\t\t\t\t\t, MAX( Height, dest.Get_Height())\n\t\t\t\t\t\t\t\t, trans));\n\t} else {\n\n\t\tif (Lock()){\n\t\t\tif (dest.Lock()){\n\t\t\t\treturn_code=(Linear_Blit_To_Linear(this, &dest, 0, 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t, 0, 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t, Width, Height, trans));\n\t\t\t}\n\t\t\tdest.Unlock();\n\t\t}\n\t\tUnlock();\n\t}\n\n\treturn (return_code);\n\n}\n\n\n/***************************************************************************\n * GVPC::SCALE -- stub 1 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans, char *remap)\n{\n\tBOOL\treturn_code=0;\n\tif (Lock()){\n\t\tif (dest.Lock()){\n\t\t\treturn_code = (Linear_Scale_To_Linear(this, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, trans, remap));\n\t\t}\n\t\tdest.Unlock();\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 2 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap)\n{\n\tBOOL\treturn_code=0;\n\tif (Lock()){\n\t\tif (dest.Lock()){\n\t\t\treturn_code = (Linear_Scale_To_Linear(this, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, FALSE, remap));\n\t\t}\n\t\tdest.Unlock();\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 3 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, BOOL trans, char *remap)\n{\n\tBOOL\treturn_code=0;\n\tif (Lock()){\n\t\tif (dest.Lock()){\n\t\t\treturn_code = (Linear_Scale_To_Linear(this,\t&dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), trans, remap));\n\t\t}\n\t\tdest.Unlock();\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 4 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, char *remap)\n{\n\tBOOL\treturn_code=0;\n\tif (Lock()){\n\t\tif (dest.Lock()){\n\t\t\treturn_code = (Linear_Scale_To_Linear(this, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), FALSE, remap));\n\t\t}\n\t\tdest.Unlock();\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n/***************************************************************************\n * GVPC::PRINT -- stub func to print a text string                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/17/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(char const *str, int x, int y, int fcol, int bcol)\n{\n\tunsigned long\treturn_code=0;\n\tif (Lock()){\n\t\treturn_code = (Buffer_Print(this, str, x, y, fcol, bcol));\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::PRINT -- Stub function to print an integer                        *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(int num, int x, int y, int fcol, int bcol)\n{\n\tchar str[17];\n\n\tunsigned long\treturn_code=0;\n\tif (Lock()){\n\t\treturn_code = (Buffer_Print(this, itoa(num, str, 10), x, y, fcol, bcol));\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::PRINT -- Stub function to print a short to a graphic viewport     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(short num, int x, int y, int fcol, int bcol)\n{\n\tchar str[17];\n\n\tunsigned long\treturn_code=0;\n\tif (Lock()){\n\t\treturn_code = (Buffer_Print(this, itoa(num, str, 10), x, y, fcol, bcol));\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::PRINT -- stub function to print a long on a graphic view port     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(long num, int x, int y, int fcol, int bcol)\n{\n\tchar str[33];\n\n\tunsigned long\treturn_code=0;\n\tif (Lock()){\n\t\treturn_code = (Buffer_Print(this, ltoa(num, str,10), x, y, fcol, bcol));\n\t}\n\tUnlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * GVPC::DRAW_STAMP -- stub function to draw a tile on a graphic view port *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline void GraphicViewPortClass::Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap)\n{\n\tif (Lock()){\n\t\tBuffer_Draw_Stamp(this, icondata, icon, x_pixel, y_pixel, remap);\n\t}\n\tUnlock();\n}\n\n\n\n/***************************************************************************\n * GVPC::DRAW_STAMP -- stub function to draw a tile on a graphic view port *\n *                     This version clips the tile to a window             *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *    07/31/1995 BWG : Created.                                            *\n *=========================================================================*/\nextern BOOL IconCacheAllowed;\ninline void GraphicViewPortClass::Draw_Stamp(void const * icondata, int icon, int x_pixel, int y_pixel, void const * remap, int clip_window)\n{\n\tint\tcache_index=-1;\n\n   int drewit = 0;\n\tif (IconCacheAllowed){\n\t\tif (IsDirectDraw){\n\t\t\tif (!remap){\n\t\t\t\tcache_index = Is_Icon_Cached(icondata,icon);\n\t\t\t}\n\n\t\t\tif (cache_index != -1){\n\t\t\t\tif (CachedIcons[cache_index].Get_Is_Cached()  ){\n\t\t\t\t\tCachedIcons[cache_index].Draw_It (GraphicBuff->Get_DD_Surface() , x_pixel, y_pixel,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[clip_window][WINDOWX] + XPos,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[clip_window][WINDOWY] +YPos,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[clip_window][WINDOWWIDTH],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[clip_window][WINDOWHEIGHT]);\n\t\t\t\t\tCachedIconsDrawn++;\n               drewit = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n   if (drewit == 0) {\n\t\tif (Lock()){\n\t\t\tUnCachedIconsDrawn++;\n\t\t\tBuffer_Draw_Stamp_Clip(this, icondata, icon, x_pixel, y_pixel, remap, WindowList[clip_window][WINDOWX], WindowList[clip_window][WINDOWY], WindowList[clip_window][WINDOWWIDTH], WindowList[clip_window][WINDOWHEIGHT]);\n\t\t}\n   }\n\tUnlock();\n}\n\n\n/***************************************************************************\n * GVPC::DRAW_LINE -- Stub function to draw line in Graphic Viewport Class *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Draw_Line(int sx, int sy, int dx, int dy, unsigned char color)\n{\n\tif (Lock()){\n\t\tBuffer_Draw_Line(this, sx, sy, dx, dy, color);\n\t}\n\tUnlock();\n}\n\n/***************************************************************************\n * GVPC::FILL_RECT -- Stub function to fill rectangle in a GVPC            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Fill_Rect(int sx, int sy, int dx, int dy, unsigned char color)\n{\n\tif (  AllowHardwareBlitFills\n\t\t\t&& IsDirectDraw\n\t\t\t&& ( (dx-sx) * (dy-sy) >= (32*32) )\n\t\t\t&& GraphicBuff->Get_DD_Surface()->GetBltStatus(DDGBS_CANBLT) == DD_OK){\n\t\tDDBLTFX\tblit_effects;\n\t\tRECT\tdest_rectangle;\n\n\t\tdest_rectangle.left\t=sx+XPos;\n\t\tdest_rectangle.top\t=sy+YPos;\n\t\tdest_rectangle.right\t=dx+XPos;\n\t\tdest_rectangle.bottom=dy+YPos;\n\n\t\tif (dest_rectangle.left<XPos){\n\t\t\tdest_rectangle.left=XPos;\n\t\t}\n\n\t\tif (dest_rectangle.right >= Width + XPos){\n\t\t\tdest_rectangle.right = Width +XPos -1;\n\t\t}\n\n\t\tif (dest_rectangle.top<YPos){\n\t\t\tdest_rectangle.top=YPos;\n\t\t}\n\n\t\tif (dest_rectangle.bottom >= Height + YPos){\n\t\t\tdest_rectangle.bottom = Height + YPos -1;\n\t\t}\n\n\t\tif (dest_rectangle.left >= dest_rectangle.right)  return;\n\t\tif (dest_rectangle.top  >= dest_rectangle.bottom) return;\n\n\t\tdest_rectangle.right++;\n\t\tdest_rectangle.bottom++;\n\n\t\tblit_effects.dwSize=sizeof(blit_effects);\n\t\tblit_effects.dwFillColor = color;\n\t\tGraphicBuff->Get_DD_Surface()->Blt(&dest_rectangle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tDDBLT_WAIT | DDBLT_ASYNC | DDBLT_COLORFILL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&blit_effects);\n\t} else {\n\t\tif (Lock()){\n\t\t\tBuffer_Fill_Rect(this, sx, sy, dx, dy, color);\n\t\t\tUnlock();\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * GVPC::REMAP -- Stub function to remap a GVPC                            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Remap(int sx, int sy, int width, int height, VOID *remap)\n{\n\tif (Lock()){\n\t\tBuffer_Remap(this, sx, sy, width, height, remap);\n\t}\n\tUnlock();\n}\n\n\ninline VOID GraphicViewPortClass::Fill_Quad(VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\tint x2, int y2, int x3, int y3, int color)\n{\n\tif (Lock()){\n\t\tBuffer_Fill_Quad(this, span_buff, x0, y0, x1, y1, x2, y2, x3, y3, color);\n\t}\n\tUnlock();\n}\n\n/***************************************************************************\n * GVPC::REMAP -- Short form to remap an entire graphic view port          *\n *                                                                         *\n * INPUT:\t\tBYTE * to the remap table to use\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Remap(VOID *remap)\n{\n\tif (Lock()){\n\t\tBuffer_Remap(this, 0, 0, Width, Height, remap);\n\t}\n\tUnlock();\n}\n\ninline int GraphicViewPortClass::Get_Pitch(void)\n{\n\treturn(Pitch);\n}\n/*=========================================================================*/\n/* The following BufferClass functions are defined here because they act\t*/\n/*\t\ton graphic viewports.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n\n/***************************************************************************\n * BUFFER_TO_PAGE -- Generic 'c' callable form of Buffer_To_Page           *\n *                                                                         *\n * INPUT: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/12/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long Buffer_To_Page(int x, int y, int w, int h, void *Buffer, GraphicViewPortClass &view)\n{\n\tlong\treturn_code=0;\n\tif (view.Lock()){\n\t\treturn_code = (Buffer_To_Page(x, y, w, h, Buffer, &view));\n\t}\n\tview.Unlock();\n\treturn ( return_code );\n}\n\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t*\n *\t\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t*\n *\t\t\t\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int w, int h, GraphicViewPortClass &view)\n{\n\tlong\treturn_code=0;\n\tif (view.Lock()){\n\t\treturn_code = (Buffer_To_Page(0, 0, w, h, Buffer, &view));\n\t}\n\tview.Unlock();\n\treturn ( return_code );\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport.  width and height are assumed to be the\t\t\t*\n *\t\t\t\t\t\tviewport's width and height.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(GraphicViewPortClass &view)\n{\n\tlong\treturn_code=0;\n\tif (view.Lock()){\n\t\treturn_code = (Buffer_To_Page(0, 0, view.Get_Width(), view.Get_Height(), Buffer, &view));\n\t}\n\tview.Unlock();\n\treturn ( return_code );\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable x, y, w, h *\n *                                                                         *\n * INPUT:\tint\tx\t\t\t- x pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\ty\t\t\t- y pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t\t*\n *\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t\t*\n *\t\t\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\tnone                                                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int x, int y, int w, int h, GraphicViewPortClass &view)\n{\n\tlong\treturn_code=0;\n\tif (view.Lock()){\n\t\treturn_code = (Buffer_To_Page(x, y, w, h, Buffer, &view));\n\t}\n\tview.Unlock();\n\treturn ( return_code );\n}\n\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/GBUFFER.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 Bit Library\t\t   *\n;*                                                                         *\n;*                    File Name : GBUFFER.INC                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : May 26, 1994                             *\n;*                                                                         *\n;*                  Last Update : May 26, 1994   [PWG]                     *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n;******************************************************************************\n; Much testing was done to determine that only when there are 14 or more bytes\n; being copied does it speed the time it takes to do copies in this algorithm.\n; For this reason and because 1 and 2 byte copies crash, is the special case\n; used.  SKB 4/21/94.  Tested on 486 66mhz.  Copied by PWG 6/7/04.\nOPTIMAL_BYTE_COPY\tequ\t14\n\nSTRUC GraphicViewPort\nGVPOffset\t\tDD\t\t?\t\t; offset to virtual viewport\nGVPWidth\t\t\tDD\t\t?\t\t; width of virtual viewport\nGVPHeight\t\tDD\t\t?\t\t; height of virtual viewport\nGVPXAdd\t\t\tDD\t\t?\t\t; x mod to get to next line\nGVPXPos\t\t\tDD\t\t?\t\t; x pos relative to Graphic Buff\nGVPYPos\t\t\tDD\t\t?\t\t; y pos relative to Graphic Buff\nGVPPitch\t\tdd\t\t?\t\t; modulo of graphic view port\nGVPBuffPtr\t\tDD\t\t?\t\t; ptr to associated Graphic Buff\nENDS"
  },
  {
    "path": "WIN32LIB/INCLUDE/ICONCACH.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***             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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Drawbuff - Westwood win95 library                            *\n *                                                                                             *\n *                    File Name : Iconcach.H                                                   *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : November 8th, 1995                                           *\n *                                                                                             *\n *                  Last Update : November 16th, 1995 [ST]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview: This file cantains definition of the IconCacheClass and associated non member     *\n *           function prototypes.                                                              *\n *                                                                                             *\n * Functions:                                                                                  *\n *  IconCacheClass::Get_Is_Cached -- member to allow access to private IsCached flag           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\n\n#ifndef\tICONCACH_H\n#define\tICONCACH_H\n\n#include\t<tile.h>\n\n#define\tICON_WIDTH\t\t\t24\t\t\t// Icons must be this width to be cached\n#define\tICON_HEIGHT\t\t\t24\t\t\t// Icons must be this height to be cached\n#define\tMAX_CACHED_ICONS\t500\t\t// Maximum number of icons that can be cached\n#define\tMAX_ICON_SETS\t\t100\t\t// Maximum number of icon sets that can be registered\n#define\tMAX_LOOKUP_ENTRIES 3000\t\t// Size of icon index table\n\n\n/*\n** IconCacheClass for tracking individual icons cached into video memory\n**\n** Use Register_Icon_Set to identify a set of icons as cachable. Once registered, the icons\n** will be cached automatically when drawn.\n** Use Invalidate_Cached_Icons at the end of icon drawing to release the video memory used by the\n** caching system.\n** Restore_Cached_Icons may be used to reload the icons into video memory after a focus loss.\n**\n*/\n\nclass IconCacheClass {\n\n\tpublic:\n\n\t\tIconCacheClass (void);\t\t\t\t\t// class constructor\n\t\t~IconCacheClass (void);\t\t\t\t\t// class destructor\n\n\t\tvoid Restore(void);\t\t\t\t\t\t// restore the surface\n\t\tBOOL Cache_It (void * icon_ptr);\t\t// Cache the icon to video memory\n\t\tvoid Uncache_It (void);\t\t\t\t\t// Restore the video memory and flag the icon as uncached\n\t\tvoid Draw_It (LPDIRECTDRAWSURFACE dest_surface , int x_pixel, int y_pixel, int window_left , int window_top , int window_width , int window_height);\n\t\tinline BOOL Get_Is_Cached(void);\t\t// Return the IsCached member\n\n\t\tint\t\t\t\t\t\tTimesDrawn;\t\t// counter of times cached icon has been drawn\n\t\tint\t\t\t\t\t\tTimesFailed;\t// counter of times cached icon has failed to draw\n\n\n\tprivate:\n\n\t\tLPDIRECTDRAWSURFACE\tCacheSurface;\t// Ptr to direct draw surface where icon resides\n\t\tBOOL\t\t\t\t\t\tIsCached;\t\t// Flag to say whether an icon is cached\n\t\tBOOL\t\t\t\t\t\tSurfaceLost;\t// Flag to indicate that our icons surface has been lost\n\t\tint\t\t\t\t\t\tDrawFrequency;\t// Number of times icon has been drawn\n\t\tvoid\t\t\t\t\t\t*IconSource;\t// Ptr to original icon data in system memory\n\n};\n\n\n\n/*\n** Structure to keep track of registered icon sets\n**\n*/\n\ntypedef struct tIconSetType{\n\tIControl_Type\t*IconSetPtr;\t\t\t\t// Ptr to icon set data\n\tint\t\t\t\tIconListOffset;\t\t\t// Offset into icon index table for this icon set\n}IconSetType;\n\n\nextern\tIconCacheClass\tCachedIcons[MAX_CACHED_ICONS];\n\nextern void Invalidate_Cached_Icons (void);\nextern void Restore_Cached_Icons (void);\nextern void Register_Icon_Set (void *icon_data , BOOL pre_cache);\n\n//\n// Prototypes for assembly language procedures in STMPCACH.ASM\n//\nextern \"C\" void Clear_Icon_Pointers (void);\nextern \"C\" void Cache_Copy_Icon (void const *icon_ptr ,void * , int);\nextern \"C\" int Is_Icon_Cached (void const *icon_data , int icon);\nextern \"C\" int Get_Icon_Index (void *icon_ptr);\nextern \"C\" int Get_Free_Index (void);\nextern \"C\" BOOL Cache_New_Icon (int icon_index, void *icon_ptr);\nextern \"C\" int Get_Free_Cache_Slot(void);\n\n\nextern\tint\tCachedIconsDrawn;\nextern\tint\tUnCachedIconsDrawn;\n\n\n/***********************************************************************************************\n * ICC::Get_Is_Cached -- member to allow access to the private IsCached flag                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   IsCached                                                                          *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:42AM ST : Created                                                             *\n *=============================================================================================*/\ninline BOOL IconCacheClass::Get_Is_Cached (void)\n{\n\treturn (IsCached);\n}\n\n\n\n\n\n#endif\t//ICONCACH_H\n\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/IFF.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the FILEIO Library               *\n *                                                                         *\n *                    File Name : IFF.H                                    *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 20, 1994                           *\n *                                                                         *\n *                  Last Update : April 20, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef IFF_H\n#define IFF_H\n\n#ifndef GBUFFER_H\n#include <gbuffer.h>\n#endif\n\n#ifndef MISC_H\n#include <misc.h>\t\t// This is needed fro Reverse_WORD and _LONG\n#endif\n\n#ifndef MEMFLAGS_H\n#include <memflag.h>\t// This is needed for MemoryFlagType.\n#endif\n\n#define LZW_SUPPORTED\t\t\tFALSE\n\n/*=========================================================================*/\n/* Iff and Load Picture system defines and enumerations\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#define \tMAKE_ID(a,b,c,d)\t\t\t((long) ((long) d << 24) | ((long) c << 16) | ((long) b <<  8) | (long)(a))\n#define\tIFFize_WORD(a)\t\t\tReverse_Word(a)\n#define\tIFFize_LONG(a)\t\t\tReverse_Long(a)\n\n\n//lint -strong(AJX,PicturePlaneType)\ntypedef enum {\n\tBM_AMIGA,\t// Bit plane format (8K per bitplane).\n\tBM_MCGA,\t\t// Byte per pixel format (64K).\n\n\tBM_DEFAULT=BM_MCGA\t// Default picture format.\n} PicturePlaneType;\n\n/*\n**\tThis is the compression type code.  This value is used in the compressed\n**\tfile header to indicate the method of compression used.  Note that the\n**\tLZW method may not be supported.\n*/\n//lint -strong(AJX,CompressionType)\ntypedef enum {\n\tNOCOMPRESS,\t\t// No compression (raw data).\n\tLZW12,\t\t\t// LZW 12 bit codes.\n\tLZW14,\t\t\t// LZW 14 bit codes.\n\tHORIZONTAL,\t\t// Run length encoding (RLE).\n\tLCW\t\t\t\t// Westwood proprietary compression.\n} CompressionType;\n\n/*\n**\tCompressed blocks of data must start with this header structure.\n**\tNote that disk based compressed files have an additional two\n**\tleading bytes that indicate the size of the entire file.\n*/\n//lint -strong(AJX,CompHeaderType)\ntypedef struct {\n\tchar\tMethod;\t\t// Compression method (CompressionType).\n\tchar\tpad;\t\t\t// Reserved pad byte (always 0).\n\tlong\tSize;\t\t\t// Size of the uncompressed data.\n\tshort\tSkip;\t\t\t// Number of bytes to skip before data.\n} CompHeaderType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: IFF.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Open_Iff_File(char const *filename);\nvoid __cdecl Close_Iff_File(int fh);\nunsigned long __cdecl Get_Iff_Chunk_Size(int fh, long id);\nunsigned long __cdecl Read_Iff_Chunk(int fh, long id, void *buffer, unsigned long maxsize);\nvoid __cdecl Write_Iff_Chunk(int file, long id, void *buffer, long length);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOADPICT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Load_Picture(char const *filename, BufferClass& scratchbuf, BufferClass& destbuf, unsigned char *palette=NULL, PicturePlaneType format=BM_DEFAULT);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOAD.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nunsigned long __cdecl Load_Data(char const *name, void *ptr, unsigned long size);\nunsigned long __cdecl Write_Data(char const *name, void *ptr, unsigned long size);\nvoid * __cdecl Load_Alloc_Data(char const *name, MemoryFlagType flags);\nunsigned long __cdecl Load_Uncompress(char const *file, BufferClass& uncomp_buff, BufferClass& dest_buff, void *reserved_data=NULL);\nunsigned long __cdecl Uncompress_Data(void const *src, void *dst);\nvoid __cdecl Set_Uncomp_Buffer(int buffer_segment, int size_of_buffer);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WRITELBM.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nPUBLIC BOOL Write_LBM_File(int lbmhandle, BufferClass& buff, int bitplanes, unsigned char *palette);\n\n\n\n/*========================= Assembly Functions ============================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*=========================================================================*/\n/* The following prototypes are for the file: PACK2PLN.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern void __cdecl Pack_2_Plane(void *buffer, void * pageptr, int planebit);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LCWCOMP.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern unsigned long __cdecl LCW_Compress(void *source, void *dest, unsigned long length);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LCWUNCMP.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern unsigned long __cdecl LCW_Uncompress(void *source, void *dest, unsigned long length);\n\n#ifdef __cplusplus\n}\n#endif\n/*=========================================================================*/\n\n\n\n#endif //IFF_H\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/INDEXTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* wIndexTable - ADPCM Lookup table for indexes\n;****************************************************************************\n\n\t\talign\t4\n\nwIndexTable\tDW\t0\t* 2\t; Index = 0 Token = 0\n\t\tDW\t0\t* 2\t; Index = 0 Token = 1\n\t\tDW\t0\t* 2\t; Index = 0 Token = 2\n\t\tDW\t0\t* 2\t; Index = 0 Token = 3\n\t\tDW\t32\t* 2\t; Index = 0 Token = 4\n\t\tDW\t64\t* 2\t; Index = 0 Token = 5\n\t\tDW\t96\t* 2\t; Index = 0 Token = 6\n\t\tDW\t128\t* 2\t; Index = 0 Token = 7\n\t\tDW\t0\t* 2\t; Index = 0 Token = 8\n\t\tDW\t0\t* 2\t; Index = 0 Token = 9\n\t\tDW\t0\t* 2\t; Index = 0 Token = 10\n\t\tDW\t0\t* 2\t; Index = 0 Token = 11\n\t\tDW\t32\t* 2\t; Index = 0 Token = 12\n\t\tDW\t64\t* 2\t; Index = 0 Token = 13\n\t\tDW\t96\t* 2\t; Index = 0 Token = 14\n\t\tDW\t128\t* 2\t; Index = 0 Token = 15\n\t\tDW\t0\t* 2\t; Index = 1 Token = 0\n\t\tDW\t0\t* 2\t; Index = 1 Token = 1\n\t\tDW\t0\t* 2\t; Index = 1 Token = 2\n\t\tDW\t0\t* 2\t; Index = 1 Token = 3\n\t\tDW\t48\t* 2\t; Index = 1 Token = 4\n\t\tDW\t80\t* 2\t; Index = 1 Token = 5\n\t\tDW\t112\t* 2\t; Index = 1 Token = 6\n\t\tDW\t144\t* 2\t; Index = 1 Token = 7\n\t\tDW\t0\t* 2\t; Index = 1 Token = 8\n\t\tDW\t0\t* 2\t; Index = 1 Token = 9\n\t\tDW\t0\t* 2\t; Index = 1 Token = 10\n\t\tDW\t0\t* 2\t; Index = 1 Token = 11\n\t\tDW\t48\t* 2\t; Index = 1 Token = 12\n\t\tDW\t80\t* 2\t; Index = 1 Token = 13\n\t\tDW\t112\t* 2\t; Index = 1 Token = 14\n\t\tDW\t144\t* 2\t; Index = 1 Token = 15\n\t\tDW\t16\t* 2\t; Index = 2 Token = 0\n\t\tDW\t16\t* 2\t; Index = 2 Token = 1\n\t\tDW\t16\t* 2\t; Index = 2 Token = 2\n\t\tDW\t16\t* 2\t; Index = 2 Token = 3\n\t\tDW\t64\t* 2\t; Index = 2 Token = 4\n\t\tDW\t96\t* 2\t; Index = 2 Token = 5\n\t\tDW\t128\t* 2\t; Index = 2 Token = 6\n\t\tDW\t160\t* 2\t; Index = 2 Token = 7\n\t\tDW\t16\t* 2\t; Index = 2 Token = 8\n\t\tDW\t16\t* 2\t; Index = 2 Token = 9\n\t\tDW\t16\t* 2\t; Index = 2 Token = 10\n\t\tDW\t16\t* 2\t; Index = 2 Token = 11\n\t\tDW\t64\t* 2\t; Index = 2 Token = 12\n\t\tDW\t96\t* 2\t; Index = 2 Token = 13\n\t\tDW\t128\t* 2\t; Index = 2 Token = 14\n\t\tDW\t160\t* 2\t; Index = 2 Token = 15\n\t\tDW\t32\t* 2\t; Index = 3 Token = 0\n\t\tDW\t32\t* 2\t; Index = 3 Token = 1\n\t\tDW\t32\t* 2\t; Index = 3 Token = 2\n\t\tDW\t32\t* 2\t; Index = 3 Token = 3\n\t\tDW\t80\t* 2\t; Index = 3 Token = 4\n\t\tDW\t112\t* 2\t; Index = 3 Token = 5\n\t\tDW\t144\t* 2\t; Index = 3 Token = 6\n\t\tDW\t176\t* 2\t; Index = 3 Token = 7\n\t\tDW\t32\t* 2\t; Index = 3 Token = 8\n\t\tDW\t32\t* 2\t; Index = 3 Token = 9\n\t\tDW\t32\t* 2\t; Index = 3 Token = 10\n\t\tDW\t32\t* 2\t; Index = 3 Token = 11\n\t\tDW\t80\t* 2\t; Index = 3 Token = 12\n\t\tDW\t112\t* 2\t; Index = 3 Token = 13\n\t\tDW\t144\t* 2\t; Index = 3 Token = 14\n\t\tDW\t176\t* 2\t; Index = 3 Token = 15\n\t\tDW\t48\t* 2\t; Index = 4 Token = 0\n\t\tDW\t48\t* 2\t; Index = 4 Token = 1\n\t\tDW\t48\t* 2\t; Index = 4 Token = 2\n\t\tDW\t48\t* 2\t; Index = 4 Token = 3\n\t\tDW\t96\t* 2\t; Index = 4 Token = 4\n\t\tDW\t128\t* 2\t; Index = 4 Token = 5\n\t\tDW\t160\t* 2\t; Index = 4 Token = 6\n\t\tDW\t192\t* 2\t; Index = 4 Token = 7\n\t\tDW\t48\t* 2\t; Index = 4 Token = 8\n\t\tDW\t48\t* 2\t; Index = 4 Token = 9\n\t\tDW\t48\t* 2\t; Index = 4 Token = 10\n\t\tDW\t48\t* 2\t; Index = 4 Token = 11\n\t\tDW\t96\t* 2\t; Index = 4 Token = 12\n\t\tDW\t128\t* 2\t; Index = 4 Token = 13\n\t\tDW\t160\t* 2\t; Index = 4 Token = 14\n\t\tDW\t192\t* 2\t; Index = 4 Token = 15\n\t\tDW\t64\t* 2\t; Index = 5 Token = 0\n\t\tDW\t64\t* 2\t; Index = 5 Token = 1\n\t\tDW\t64\t* 2\t; Index = 5 Token = 2\n\t\tDW\t64\t* 2\t; Index = 5 Token = 3\n\t\tDW\t112\t* 2\t; Index = 5 Token = 4\n\t\tDW\t144\t* 2\t; Index = 5 Token = 5\n\t\tDW\t176\t* 2\t; Index = 5 Token = 6\n\t\tDW\t208\t* 2\t; Index = 5 Token = 7\n\t\tDW\t64\t* 2\t; Index = 5 Token = 8\n\t\tDW\t64\t* 2\t; Index = 5 Token = 9\n\t\tDW\t64\t* 2\t; Index = 5 Token = 10\n\t\tDW\t64\t* 2\t; Index = 5 Token = 11\n\t\tDW\t112\t* 2\t; Index = 5 Token = 12\n\t\tDW\t144\t* 2\t; Index = 5 Token = 13\n\t\tDW\t176\t* 2\t; Index = 5 Token = 14\n\t\tDW\t208\t* 2\t; Index = 5 Token = 15\n\t\tDW\t80\t* 2\t; Index = 6 Token = 0\n\t\tDW\t80\t* 2\t; Index = 6 Token = 1\n\t\tDW\t80\t* 2\t; Index = 6 Token = 2\n\t\tDW\t80\t* 2\t; Index = 6 Token = 3\n\t\tDW\t128\t* 2\t; Index = 6 Token = 4\n\t\tDW\t160\t* 2\t; Index = 6 Token = 5\n\t\tDW\t192\t* 2\t; Index = 6 Token = 6\n\t\tDW\t224\t* 2\t; Index = 6 Token = 7\n\t\tDW\t80\t* 2\t; Index = 6 Token = 8\n\t\tDW\t80\t* 2\t; Index = 6 Token = 9\n\t\tDW\t80\t* 2\t; Index = 6 Token = 10\n\t\tDW\t80\t* 2\t; Index = 6 Token = 11\n\t\tDW\t128\t* 2\t; Index = 6 Token = 12\n\t\tDW\t160\t* 2\t; Index = 6 Token = 13\n\t\tDW\t192\t* 2\t; Index = 6 Token = 14\n\t\tDW\t224\t* 2\t; Index = 6 Token = 15\n\t\tDW\t96\t* 2\t; Index = 7 Token = 0\n\t\tDW\t96\t* 2\t; Index = 7 Token = 1\n\t\tDW\t96\t* 2\t; Index = 7 Token = 2\n\t\tDW\t96\t* 2\t; Index = 7 Token = 3\n\t\tDW\t144\t* 2\t; Index = 7 Token = 4\n\t\tDW\t176\t* 2\t; Index = 7 Token = 5\n\t\tDW\t208\t* 2\t; Index = 7 Token = 6\n\t\tDW\t240\t* 2\t; Index = 7 Token = 7\n\t\tDW\t96\t* 2\t; Index = 7 Token = 8\n\t\tDW\t96\t* 2\t; Index = 7 Token = 9\n\t\tDW\t96\t* 2\t; Index = 7 Token = 10\n\t\tDW\t96\t* 2\t; Index = 7 Token = 11\n\t\tDW\t144\t* 2\t; Index = 7 Token = 12\n\t\tDW\t176\t* 2\t; Index = 7 Token = 13\n\t\tDW\t208\t* 2\t; Index = 7 Token = 14\n\t\tDW\t240\t* 2\t; Index = 7 Token = 15\n\t\tDW\t112\t* 2\t; Index = 8 Token = 0\n\t\tDW\t112\t* 2\t; Index = 8 Token = 1\n\t\tDW\t112\t* 2\t; Index = 8 Token = 2\n\t\tDW\t112\t* 2\t; Index = 8 Token = 3\n\t\tDW\t160\t* 2\t; Index = 8 Token = 4\n\t\tDW\t192\t* 2\t; Index = 8 Token = 5\n\t\tDW\t224\t* 2\t; Index = 8 Token = 6\n\t\tDW\t256\t* 2\t; Index = 8 Token = 7\n\t\tDW\t112\t* 2\t; Index = 8 Token = 8\n\t\tDW\t112\t* 2\t; Index = 8 Token = 9\n\t\tDW\t112\t* 2\t; Index = 8 Token = 10\n\t\tDW\t112\t* 2\t; Index = 8 Token = 11\n\t\tDW\t160\t* 2\t; Index = 8 Token = 12\n\t\tDW\t192\t* 2\t; Index = 8 Token = 13\n\t\tDW\t224\t* 2\t; Index = 8 Token = 14\n\t\tDW\t256\t* 2\t; Index = 8 Token = 15\n\t\tDW\t128\t* 2\t; Index = 9 Token = 0\n\t\tDW\t128\t* 2\t; Index = 9 Token = 1\n\t\tDW\t128\t* 2\t; Index = 9 Token = 2\n\t\tDW\t128\t* 2\t; Index = 9 Token = 3\n\t\tDW\t176\t* 2\t; Index = 9 Token = 4\n\t\tDW\t208\t* 2\t; Index = 9 Token = 5\n\t\tDW\t240\t* 2\t; Index = 9 Token = 6\n\t\tDW\t272\t* 2\t; Index = 9 Token = 7\n\t\tDW\t128\t* 2\t; Index = 9 Token = 8\n\t\tDW\t128\t* 2\t; Index = 9 Token = 9\n\t\tDW\t128\t* 2\t; Index = 9 Token = 10\n\t\tDW\t128\t* 2\t; Index = 9 Token = 11\n\t\tDW\t176\t* 2\t; Index = 9 Token = 12\n\t\tDW\t208\t* 2\t; Index = 9 Token = 13\n\t\tDW\t240\t* 2\t; Index = 9 Token = 14\n\t\tDW\t272\t* 2\t; Index = 9 Token = 15\n\t\tDW\t144\t* 2\t; Index = 10 Token = 0\n\t\tDW\t144\t* 2\t; Index = 10 Token = 1\n\t\tDW\t144\t* 2\t; Index = 10 Token = 2\n\t\tDW\t144\t* 2\t; Index = 10 Token = 3\n\t\tDW\t192\t* 2\t; Index = 10 Token = 4\n\t\tDW\t224\t* 2\t; Index = 10 Token = 5\n\t\tDW\t256\t* 2\t; Index = 10 Token = 6\n\t\tDW\t288\t* 2\t; Index = 10 Token = 7\n\t\tDW\t144\t* 2\t; Index = 10 Token = 8\n\t\tDW\t144\t* 2\t; Index = 10 Token = 9\n\t\tDW\t144\t* 2\t; Index = 10 Token = 10\n\t\tDW\t144\t* 2\t; Index = 10 Token = 11\n\t\tDW\t192\t* 2\t; Index = 10 Token = 12\n\t\tDW\t224\t* 2\t; Index = 10 Token = 13\n\t\tDW\t256\t* 2\t; Index = 10 Token = 14\n\t\tDW\t288\t* 2\t; Index = 10 Token = 15\n\t\tDW\t160\t* 2\t; Index = 11 Token = 0\n\t\tDW\t160\t* 2\t; Index = 11 Token = 1\n\t\tDW\t160\t* 2\t; Index = 11 Token = 2\n\t\tDW\t160\t* 2\t; Index = 11 Token = 3\n\t\tDW\t208\t* 2\t; Index = 11 Token = 4\n\t\tDW\t240\t* 2\t; Index = 11 Token = 5\n\t\tDW\t272\t* 2\t; Index = 11 Token = 6\n\t\tDW\t304\t* 2\t; Index = 11 Token = 7\n\t\tDW\t160\t* 2\t; Index = 11 Token = 8\n\t\tDW\t160\t* 2\t; Index = 11 Token = 9\n\t\tDW\t160\t* 2\t; Index = 11 Token = 10\n\t\tDW\t160\t* 2\t; Index = 11 Token = 11\n\t\tDW\t208\t* 2\t; Index = 11 Token = 12\n\t\tDW\t240\t* 2\t; Index = 11 Token = 13\n\t\tDW\t272\t* 2\t; Index = 11 Token = 14\n\t\tDW\t304\t* 2\t; Index = 11 Token = 15\n\t\tDW\t176\t* 2\t; Index = 12 Token = 0\n\t\tDW\t176\t* 2\t; Index = 12 Token = 1\n\t\tDW\t176\t* 2\t; Index = 12 Token = 2\n\t\tDW\t176\t* 2\t; Index = 12 Token = 3\n\t\tDW\t224\t* 2\t; Index = 12 Token = 4\n\t\tDW\t256\t* 2\t; Index = 12 Token = 5\n\t\tDW\t288\t* 2\t; Index = 12 Token = 6\n\t\tDW\t320\t* 2\t; Index = 12 Token = 7\n\t\tDW\t176\t* 2\t; Index = 12 Token = 8\n\t\tDW\t176\t* 2\t; Index = 12 Token = 9\n\t\tDW\t176\t* 2\t; Index = 12 Token = 10\n\t\tDW\t176\t* 2\t; Index = 12 Token = 11\n\t\tDW\t224\t* 2\t; Index = 12 Token = 12\n\t\tDW\t256\t* 2\t; Index = 12 Token = 13\n\t\tDW\t288\t* 2\t; Index = 12 Token = 14\n\t\tDW\t320\t* 2\t; Index = 12 Token = 15\n\t\tDW\t192\t* 2\t; Index = 13 Token = 0\n\t\tDW\t192\t* 2\t; Index = 13 Token = 1\n\t\tDW\t192\t* 2\t; Index = 13 Token = 2\n\t\tDW\t192\t* 2\t; Index = 13 Token = 3\n\t\tDW\t240\t* 2\t; Index = 13 Token = 4\n\t\tDW\t272\t* 2\t; Index = 13 Token = 5\n\t\tDW\t304\t* 2\t; Index = 13 Token = 6\n\t\tDW\t336\t* 2\t; Index = 13 Token = 7\n\t\tDW\t192\t* 2\t; Index = 13 Token = 8\n\t\tDW\t192\t* 2\t; Index = 13 Token = 9\n\t\tDW\t192\t* 2\t; Index = 13 Token = 10\n\t\tDW\t192\t* 2\t; Index = 13 Token = 11\n\t\tDW\t240\t* 2\t; Index = 13 Token = 12\n\t\tDW\t272\t* 2\t; Index = 13 Token = 13\n\t\tDW\t304\t* 2\t; Index = 13 Token = 14\n\t\tDW\t336\t* 2\t; Index = 13 Token = 15\n\t\tDW\t208\t* 2\t; Index = 14 Token = 0\n\t\tDW\t208\t* 2\t; Index = 14 Token = 1\n\t\tDW\t208\t* 2\t; Index = 14 Token = 2\n\t\tDW\t208\t* 2\t; Index = 14 Token = 3\n\t\tDW\t256\t* 2\t; Index = 14 Token = 4\n\t\tDW\t288\t* 2\t; Index = 14 Token = 5\n\t\tDW\t320\t* 2\t; Index = 14 Token = 6\n\t\tDW\t352\t* 2\t; Index = 14 Token = 7\n\t\tDW\t208\t* 2\t; Index = 14 Token = 8\n\t\tDW\t208\t* 2\t; Index = 14 Token = 9\n\t\tDW\t208\t* 2\t; Index = 14 Token = 10\n\t\tDW\t208\t* 2\t; Index = 14 Token = 11\n\t\tDW\t256\t* 2\t; Index = 14 Token = 12\n\t\tDW\t288\t* 2\t; Index = 14 Token = 13\n\t\tDW\t320\t* 2\t; Index = 14 Token = 14\n\t\tDW\t352\t* 2\t; Index = 14 Token = 15\n\t\tDW\t224\t* 2\t; Index = 15 Token = 0\n\t\tDW\t224\t* 2\t; Index = 15 Token = 1\n\t\tDW\t224\t* 2\t; Index = 15 Token = 2\n\t\tDW\t224\t* 2\t; Index = 15 Token = 3\n\t\tDW\t272\t* 2\t; Index = 15 Token = 4\n\t\tDW\t304\t* 2\t; Index = 15 Token = 5\n\t\tDW\t336\t* 2\t; Index = 15 Token = 6\n\t\tDW\t368\t* 2\t; Index = 15 Token = 7\n\t\tDW\t224\t* 2\t; Index = 15 Token = 8\n\t\tDW\t224\t* 2\t; Index = 15 Token = 9\n\t\tDW\t224\t* 2\t; Index = 15 Token = 10\n\t\tDW\t224\t* 2\t; Index = 15 Token = 11\n\t\tDW\t272\t* 2\t; Index = 15 Token = 12\n\t\tDW\t304\t* 2\t; Index = 15 Token = 13\n\t\tDW\t336\t* 2\t; Index = 15 Token = 14\n\t\tDW\t368\t* 2\t; Index = 15 Token = 15\n\t\tDW\t240\t* 2\t; Index = 16 Token = 0\n\t\tDW\t240\t* 2\t; Index = 16 Token = 1\n\t\tDW\t240\t* 2\t; Index = 16 Token = 2\n\t\tDW\t240\t* 2\t; Index = 16 Token = 3\n\t\tDW\t288\t* 2\t; Index = 16 Token = 4\n\t\tDW\t320\t* 2\t; Index = 16 Token = 5\n\t\tDW\t352\t* 2\t; Index = 16 Token = 6\n\t\tDW\t384\t* 2\t; Index = 16 Token = 7\n\t\tDW\t240\t* 2\t; Index = 16 Token = 8\n\t\tDW\t240\t* 2\t; Index = 16 Token = 9\n\t\tDW\t240\t* 2\t; Index = 16 Token = 10\n\t\tDW\t240\t* 2\t; Index = 16 Token = 11\n\t\tDW\t288\t* 2\t; Index = 16 Token = 12\n\t\tDW\t320\t* 2\t; Index = 16 Token = 13\n\t\tDW\t352\t* 2\t; Index = 16 Token = 14\n\t\tDW\t384\t* 2\t; Index = 16 Token = 15\n\t\tDW\t256\t* 2\t; Index = 17 Token = 0\n\t\tDW\t256\t* 2\t; Index = 17 Token = 1\n\t\tDW\t256\t* 2\t; Index = 17 Token = 2\n\t\tDW\t256\t* 2\t; Index = 17 Token = 3\n\t\tDW\t304\t* 2\t; Index = 17 Token = 4\n\t\tDW\t336\t* 2\t; Index = 17 Token = 5\n\t\tDW\t368\t* 2\t; Index = 17 Token = 6\n\t\tDW\t400\t* 2\t; Index = 17 Token = 7\n\t\tDW\t256\t* 2\t; Index = 17 Token = 8\n\t\tDW\t256\t* 2\t; Index = 17 Token = 9\n\t\tDW\t256\t* 2\t; Index = 17 Token = 10\n\t\tDW\t256\t* 2\t; Index = 17 Token = 11\n\t\tDW\t304\t* 2\t; Index = 17 Token = 12\n\t\tDW\t336\t* 2\t; Index = 17 Token = 13\n\t\tDW\t368\t* 2\t; Index = 17 Token = 14\n\t\tDW\t400\t* 2\t; Index = 17 Token = 15\n\t\tDW\t272\t* 2\t; Index = 18 Token = 0\n\t\tDW\t272\t* 2\t; Index = 18 Token = 1\n\t\tDW\t272\t* 2\t; Index = 18 Token = 2\n\t\tDW\t272\t* 2\t; Index = 18 Token = 3\n\t\tDW\t320\t* 2\t; Index = 18 Token = 4\n\t\tDW\t352\t* 2\t; Index = 18 Token = 5\n\t\tDW\t384\t* 2\t; Index = 18 Token = 6\n\t\tDW\t416\t* 2\t; Index = 18 Token = 7\n\t\tDW\t272\t* 2\t; Index = 18 Token = 8\n\t\tDW\t272\t* 2\t; Index = 18 Token = 9\n\t\tDW\t272\t* 2\t; Index = 18 Token = 10\n\t\tDW\t272\t* 2\t; Index = 18 Token = 11\n\t\tDW\t320\t* 2\t; Index = 18 Token = 12\n\t\tDW\t352\t* 2\t; Index = 18 Token = 13\n\t\tDW\t384\t* 2\t; Index = 18 Token = 14\n\t\tDW\t416\t* 2\t; Index = 18 Token = 15\n\t\tDW\t288\t* 2\t; Index = 19 Token = 0\n\t\tDW\t288\t* 2\t; Index = 19 Token = 1\n\t\tDW\t288\t* 2\t; Index = 19 Token = 2\n\t\tDW\t288\t* 2\t; Index = 19 Token = 3\n\t\tDW\t336\t* 2\t; Index = 19 Token = 4\n\t\tDW\t368\t* 2\t; Index = 19 Token = 5\n\t\tDW\t400\t* 2\t; Index = 19 Token = 6\n\t\tDW\t432\t* 2\t; Index = 19 Token = 7\n\t\tDW\t288\t* 2\t; Index = 19 Token = 8\n\t\tDW\t288\t* 2\t; Index = 19 Token = 9\n\t\tDW\t288\t* 2\t; Index = 19 Token = 10\n\t\tDW\t288\t* 2\t; Index = 19 Token = 11\n\t\tDW\t336\t* 2\t; Index = 19 Token = 12\n\t\tDW\t368\t* 2\t; Index = 19 Token = 13\n\t\tDW\t400\t* 2\t; Index = 19 Token = 14\n\t\tDW\t432\t* 2\t; Index = 19 Token = 15\n\t\tDW\t304\t* 2\t; Index = 20 Token = 0\n\t\tDW\t304\t* 2\t; Index = 20 Token = 1\n\t\tDW\t304\t* 2\t; Index = 20 Token = 2\n\t\tDW\t304\t* 2\t; Index = 20 Token = 3\n\t\tDW\t352\t* 2\t; Index = 20 Token = 4\n\t\tDW\t384\t* 2\t; Index = 20 Token = 5\n\t\tDW\t416\t* 2\t; Index = 20 Token = 6\n\t\tDW\t448\t* 2\t; Index = 20 Token = 7\n\t\tDW\t304\t* 2\t; Index = 20 Token = 8\n\t\tDW\t304\t* 2\t; Index = 20 Token = 9\n\t\tDW\t304\t* 2\t; Index = 20 Token = 10\n\t\tDW\t304\t* 2\t; Index = 20 Token = 11\n\t\tDW\t352\t* 2\t; Index = 20 Token = 12\n\t\tDW\t384\t* 2\t; Index = 20 Token = 13\n\t\tDW\t416\t* 2\t; Index = 20 Token = 14\n\t\tDW\t448\t* 2\t; Index = 20 Token = 15\n\t\tDW\t320\t* 2\t; Index = 21 Token = 0\n\t\tDW\t320\t* 2\t; Index = 21 Token = 1\n\t\tDW\t320\t* 2\t; Index = 21 Token = 2\n\t\tDW\t320\t* 2\t; Index = 21 Token = 3\n\t\tDW\t368\t* 2\t; Index = 21 Token = 4\n\t\tDW\t400\t* 2\t; Index = 21 Token = 5\n\t\tDW\t432\t* 2\t; Index = 21 Token = 6\n\t\tDW\t464\t* 2\t; Index = 21 Token = 7\n\t\tDW\t320\t* 2\t; Index = 21 Token = 8\n\t\tDW\t320\t* 2\t; Index = 21 Token = 9\n\t\tDW\t320\t* 2\t; Index = 21 Token = 10\n\t\tDW\t320\t* 2\t; Index = 21 Token = 11\n\t\tDW\t368\t* 2\t; Index = 21 Token = 12\n\t\tDW\t400\t* 2\t; Index = 21 Token = 13\n\t\tDW\t432\t* 2\t; Index = 21 Token = 14\n\t\tDW\t464\t* 2\t; Index = 21 Token = 15\n\t\tDW\t336\t* 2\t; Index = 22 Token = 0\n\t\tDW\t336\t* 2\t; Index = 22 Token = 1\n\t\tDW\t336\t* 2\t; Index = 22 Token = 2\n\t\tDW\t336\t* 2\t; Index = 22 Token = 3\n\t\tDW\t384\t* 2\t; Index = 22 Token = 4\n\t\tDW\t416\t* 2\t; Index = 22 Token = 5\n\t\tDW\t448\t* 2\t; Index = 22 Token = 6\n\t\tDW\t480\t* 2\t; Index = 22 Token = 7\n\t\tDW\t336\t* 2\t; Index = 22 Token = 8\n\t\tDW\t336\t* 2\t; Index = 22 Token = 9\n\t\tDW\t336\t* 2\t; Index = 22 Token = 10\n\t\tDW\t336\t* 2\t; Index = 22 Token = 11\n\t\tDW\t384\t* 2\t; Index = 22 Token = 12\n\t\tDW\t416\t* 2\t; Index = 22 Token = 13\n\t\tDW\t448\t* 2\t; Index = 22 Token = 14\n\t\tDW\t480\t* 2\t; Index = 22 Token = 15\n\t\tDW\t352\t* 2\t; Index = 23 Token = 0\n\t\tDW\t352\t* 2\t; Index = 23 Token = 1\n\t\tDW\t352\t* 2\t; Index = 23 Token = 2\n\t\tDW\t352\t* 2\t; Index = 23 Token = 3\n\t\tDW\t400\t* 2\t; Index = 23 Token = 4\n\t\tDW\t432\t* 2\t; Index = 23 Token = 5\n\t\tDW\t464\t* 2\t; Index = 23 Token = 6\n\t\tDW\t496\t* 2\t; Index = 23 Token = 7\n\t\tDW\t352\t* 2\t; Index = 23 Token = 8\n\t\tDW\t352\t* 2\t; Index = 23 Token = 9\n\t\tDW\t352\t* 2\t; Index = 23 Token = 10\n\t\tDW\t352\t* 2\t; Index = 23 Token = 11\n\t\tDW\t400\t* 2\t; Index = 23 Token = 12\n\t\tDW\t432\t* 2\t; Index = 23 Token = 13\n\t\tDW\t464\t* 2\t; Index = 23 Token = 14\n\t\tDW\t496\t* 2\t; Index = 23 Token = 15\n\t\tDW\t368\t* 2\t; Index = 24 Token = 0\n\t\tDW\t368\t* 2\t; Index = 24 Token = 1\n\t\tDW\t368\t* 2\t; Index = 24 Token = 2\n\t\tDW\t368\t* 2\t; Index = 24 Token = 3\n\t\tDW\t416\t* 2\t; Index = 24 Token = 4\n\t\tDW\t448\t* 2\t; Index = 24 Token = 5\n\t\tDW\t480\t* 2\t; Index = 24 Token = 6\n\t\tDW\t512\t* 2\t; Index = 24 Token = 7\n\t\tDW\t368\t* 2\t; Index = 24 Token = 8\n\t\tDW\t368\t* 2\t; Index = 24 Token = 9\n\t\tDW\t368\t* 2\t; Index = 24 Token = 10\n\t\tDW\t368\t* 2\t; Index = 24 Token = 11\n\t\tDW\t416\t* 2\t; Index = 24 Token = 12\n\t\tDW\t448\t* 2\t; Index = 24 Token = 13\n\t\tDW\t480\t* 2\t; Index = 24 Token = 14\n\t\tDW\t512\t* 2\t; Index = 24 Token = 15\n\t\tDW\t384\t* 2\t; Index = 25 Token = 0\n\t\tDW\t384\t* 2\t; Index = 25 Token = 1\n\t\tDW\t384\t* 2\t; Index = 25 Token = 2\n\t\tDW\t384\t* 2\t; Index = 25 Token = 3\n\t\tDW\t432\t* 2\t; Index = 25 Token = 4\n\t\tDW\t464\t* 2\t; Index = 25 Token = 5\n\t\tDW\t496\t* 2\t; Index = 25 Token = 6\n\t\tDW\t528\t* 2\t; Index = 25 Token = 7\n\t\tDW\t384\t* 2\t; Index = 25 Token = 8\n\t\tDW\t384\t* 2\t; Index = 25 Token = 9\n\t\tDW\t384\t* 2\t; Index = 25 Token = 10\n\t\tDW\t384\t* 2\t; Index = 25 Token = 11\n\t\tDW\t432\t* 2\t; Index = 25 Token = 12\n\t\tDW\t464\t* 2\t; Index = 25 Token = 13\n\t\tDW\t496\t* 2\t; Index = 25 Token = 14\n\t\tDW\t528\t* 2\t; Index = 25 Token = 15\n\t\tDW\t400\t* 2\t; Index = 26 Token = 0\n\t\tDW\t400\t* 2\t; Index = 26 Token = 1\n\t\tDW\t400\t* 2\t; Index = 26 Token = 2\n\t\tDW\t400\t* 2\t; Index = 26 Token = 3\n\t\tDW\t448\t* 2\t; Index = 26 Token = 4\n\t\tDW\t480\t* 2\t; Index = 26 Token = 5\n\t\tDW\t512\t* 2\t; Index = 26 Token = 6\n\t\tDW\t544\t* 2\t; Index = 26 Token = 7\n\t\tDW\t400\t* 2\t; Index = 26 Token = 8\n\t\tDW\t400\t* 2\t; Index = 26 Token = 9\n\t\tDW\t400\t* 2\t; Index = 26 Token = 10\n\t\tDW\t400\t* 2\t; Index = 26 Token = 11\n\t\tDW\t448\t* 2\t; Index = 26 Token = 12\n\t\tDW\t480\t* 2\t; Index = 26 Token = 13\n\t\tDW\t512\t* 2\t; Index = 26 Token = 14\n\t\tDW\t544\t* 2\t; Index = 26 Token = 15\n\t\tDW\t416\t* 2\t; Index = 27 Token = 0\n\t\tDW\t416\t* 2\t; Index = 27 Token = 1\n\t\tDW\t416\t* 2\t; Index = 27 Token = 2\n\t\tDW\t416\t* 2\t; Index = 27 Token = 3\n\t\tDW\t464\t* 2\t; Index = 27 Token = 4\n\t\tDW\t496\t* 2\t; Index = 27 Token = 5\n\t\tDW\t528\t* 2\t; Index = 27 Token = 6\n\t\tDW\t560\t* 2\t; Index = 27 Token = 7\n\t\tDW\t416\t* 2\t; Index = 27 Token = 8\n\t\tDW\t416\t* 2\t; Index = 27 Token = 9\n\t\tDW\t416\t* 2\t; Index = 27 Token = 10\n\t\tDW\t416\t* 2\t; Index = 27 Token = 11\n\t\tDW\t464\t* 2\t; Index = 27 Token = 12\n\t\tDW\t496\t* 2\t; Index = 27 Token = 13\n\t\tDW\t528\t* 2\t; Index = 27 Token = 14\n\t\tDW\t560\t* 2\t; Index = 27 Token = 15\n\t\tDW\t432\t* 2\t; Index = 28 Token = 0\n\t\tDW\t432\t* 2\t; Index = 28 Token = 1\n\t\tDW\t432\t* 2\t; Index = 28 Token = 2\n\t\tDW\t432\t* 2\t; Index = 28 Token = 3\n\t\tDW\t480\t* 2\t; Index = 28 Token = 4\n\t\tDW\t512\t* 2\t; Index = 28 Token = 5\n\t\tDW\t544\t* 2\t; Index = 28 Token = 6\n\t\tDW\t576\t* 2\t; Index = 28 Token = 7\n\t\tDW\t432\t* 2\t; Index = 28 Token = 8\n\t\tDW\t432\t* 2\t; Index = 28 Token = 9\n\t\tDW\t432\t* 2\t; Index = 28 Token = 10\n\t\tDW\t432\t* 2\t; Index = 28 Token = 11\n\t\tDW\t480\t* 2\t; Index = 28 Token = 12\n\t\tDW\t512\t* 2\t; Index = 28 Token = 13\n\t\tDW\t544\t* 2\t; Index = 28 Token = 14\n\t\tDW\t576\t* 2\t; Index = 28 Token = 15\n\t\tDW\t448\t* 2\t; Index = 29 Token = 0\n\t\tDW\t448\t* 2\t; Index = 29 Token = 1\n\t\tDW\t448\t* 2\t; Index = 29 Token = 2\n\t\tDW\t448\t* 2\t; Index = 29 Token = 3\n\t\tDW\t496\t* 2\t; Index = 29 Token = 4\n\t\tDW\t528\t* 2\t; Index = 29 Token = 5\n\t\tDW\t560\t* 2\t; Index = 29 Token = 6\n\t\tDW\t592\t* 2\t; Index = 29 Token = 7\n\t\tDW\t448\t* 2\t; Index = 29 Token = 8\n\t\tDW\t448\t* 2\t; Index = 29 Token = 9\n\t\tDW\t448\t* 2\t; Index = 29 Token = 10\n\t\tDW\t448\t* 2\t; Index = 29 Token = 11\n\t\tDW\t496\t* 2\t; Index = 29 Token = 12\n\t\tDW\t528\t* 2\t; Index = 29 Token = 13\n\t\tDW\t560\t* 2\t; Index = 29 Token = 14\n\t\tDW\t592\t* 2\t; Index = 29 Token = 15\n\t\tDW\t464\t* 2\t; Index = 30 Token = 0\n\t\tDW\t464\t* 2\t; Index = 30 Token = 1\n\t\tDW\t464\t* 2\t; Index = 30 Token = 2\n\t\tDW\t464\t* 2\t; Index = 30 Token = 3\n\t\tDW\t512\t* 2\t; Index = 30 Token = 4\n\t\tDW\t544\t* 2\t; Index = 30 Token = 5\n\t\tDW\t576\t* 2\t; Index = 30 Token = 6\n\t\tDW\t608\t* 2\t; Index = 30 Token = 7\n\t\tDW\t464\t* 2\t; Index = 30 Token = 8\n\t\tDW\t464\t* 2\t; Index = 30 Token = 9\n\t\tDW\t464\t* 2\t; Index = 30 Token = 10\n\t\tDW\t464\t* 2\t; Index = 30 Token = 11\n\t\tDW\t512\t* 2\t; Index = 30 Token = 12\n\t\tDW\t544\t* 2\t; Index = 30 Token = 13\n\t\tDW\t576\t* 2\t; Index = 30 Token = 14\n\t\tDW\t608\t* 2\t; Index = 30 Token = 15\n\t\tDW\t480\t* 2\t; Index = 31 Token = 0\n\t\tDW\t480\t* 2\t; Index = 31 Token = 1\n\t\tDW\t480\t* 2\t; Index = 31 Token = 2\n\t\tDW\t480\t* 2\t; Index = 31 Token = 3\n\t\tDW\t528\t* 2\t; Index = 31 Token = 4\n\t\tDW\t560\t* 2\t; Index = 31 Token = 5\n\t\tDW\t592\t* 2\t; Index = 31 Token = 6\n\t\tDW\t624\t* 2\t; Index = 31 Token = 7\n\t\tDW\t480\t* 2\t; Index = 31 Token = 8\n\t\tDW\t480\t* 2\t; Index = 31 Token = 9\n\t\tDW\t480\t* 2\t; Index = 31 Token = 10\n\t\tDW\t480\t* 2\t; Index = 31 Token = 11\n\t\tDW\t528\t* 2\t; Index = 31 Token = 12\n\t\tDW\t560\t* 2\t; Index = 31 Token = 13\n\t\tDW\t592\t* 2\t; Index = 31 Token = 14\n\t\tDW\t624\t* 2\t; Index = 31 Token = 15\n\t\tDW\t496\t* 2\t; Index = 32 Token = 0\n\t\tDW\t496\t* 2\t; Index = 32 Token = 1\n\t\tDW\t496\t* 2\t; Index = 32 Token = 2\n\t\tDW\t496\t* 2\t; Index = 32 Token = 3\n\t\tDW\t544\t* 2\t; Index = 32 Token = 4\n\t\tDW\t576\t* 2\t; Index = 32 Token = 5\n\t\tDW\t608\t* 2\t; Index = 32 Token = 6\n\t\tDW\t640\t* 2\t; Index = 32 Token = 7\n\t\tDW\t496\t* 2\t; Index = 32 Token = 8\n\t\tDW\t496\t* 2\t; Index = 32 Token = 9\n\t\tDW\t496\t* 2\t; Index = 32 Token = 10\n\t\tDW\t496\t* 2\t; Index = 32 Token = 11\n\t\tDW\t544\t* 2\t; Index = 32 Token = 12\n\t\tDW\t576\t* 2\t; Index = 32 Token = 13\n\t\tDW\t608\t* 2\t; Index = 32 Token = 14\n\t\tDW\t640\t* 2\t; Index = 32 Token = 15\n\t\tDW\t512\t* 2\t; Index = 33 Token = 0\n\t\tDW\t512\t* 2\t; Index = 33 Token = 1\n\t\tDW\t512\t* 2\t; Index = 33 Token = 2\n\t\tDW\t512\t* 2\t; Index = 33 Token = 3\n\t\tDW\t560\t* 2\t; Index = 33 Token = 4\n\t\tDW\t592\t* 2\t; Index = 33 Token = 5\n\t\tDW\t624\t* 2\t; Index = 33 Token = 6\n\t\tDW\t656\t* 2\t; Index = 33 Token = 7\n\t\tDW\t512\t* 2\t; Index = 33 Token = 8\n\t\tDW\t512\t* 2\t; Index = 33 Token = 9\n\t\tDW\t512\t* 2\t; Index = 33 Token = 10\n\t\tDW\t512\t* 2\t; Index = 33 Token = 11\n\t\tDW\t560\t* 2\t; Index = 33 Token = 12\n\t\tDW\t592\t* 2\t; Index = 33 Token = 13\n\t\tDW\t624\t* 2\t; Index = 33 Token = 14\n\t\tDW\t656\t* 2\t; Index = 33 Token = 15\n\t\tDW\t528\t* 2\t; Index = 34 Token = 0\n\t\tDW\t528\t* 2\t; Index = 34 Token = 1\n\t\tDW\t528\t* 2\t; Index = 34 Token = 2\n\t\tDW\t528\t* 2\t; Index = 34 Token = 3\n\t\tDW\t576\t* 2\t; Index = 34 Token = 4\n\t\tDW\t608\t* 2\t; Index = 34 Token = 5\n\t\tDW\t640\t* 2\t; Index = 34 Token = 6\n\t\tDW\t672\t* 2\t; Index = 34 Token = 7\n\t\tDW\t528\t* 2\t; Index = 34 Token = 8\n\t\tDW\t528\t* 2\t; Index = 34 Token = 9\n\t\tDW\t528\t* 2\t; Index = 34 Token = 10\n\t\tDW\t528\t* 2\t; Index = 34 Token = 11\n\t\tDW\t576\t* 2\t; Index = 34 Token = 12\n\t\tDW\t608\t* 2\t; Index = 34 Token = 13\n\t\tDW\t640\t* 2\t; Index = 34 Token = 14\n\t\tDW\t672\t* 2\t; Index = 34 Token = 15\n\t\tDW\t544\t* 2\t; Index = 35 Token = 0\n\t\tDW\t544\t* 2\t; Index = 35 Token = 1\n\t\tDW\t544\t* 2\t; Index = 35 Token = 2\n\t\tDW\t544\t* 2\t; Index = 35 Token = 3\n\t\tDW\t592\t* 2\t; Index = 35 Token = 4\n\t\tDW\t624\t* 2\t; Index = 35 Token = 5\n\t\tDW\t656\t* 2\t; Index = 35 Token = 6\n\t\tDW\t688\t* 2\t; Index = 35 Token = 7\n\t\tDW\t544\t* 2\t; Index = 35 Token = 8\n\t\tDW\t544\t* 2\t; Index = 35 Token = 9\n\t\tDW\t544\t* 2\t; Index = 35 Token = 10\n\t\tDW\t544\t* 2\t; Index = 35 Token = 11\n\t\tDW\t592\t* 2\t; Index = 35 Token = 12\n\t\tDW\t624\t* 2\t; Index = 35 Token = 13\n\t\tDW\t656\t* 2\t; Index = 35 Token = 14\n\t\tDW\t688\t* 2\t; Index = 35 Token = 15\n\t\tDW\t560\t* 2\t; Index = 36 Token = 0\n\t\tDW\t560\t* 2\t; Index = 36 Token = 1\n\t\tDW\t560\t* 2\t; Index = 36 Token = 2\n\t\tDW\t560\t* 2\t; Index = 36 Token = 3\n\t\tDW\t608\t* 2\t; Index = 36 Token = 4\n\t\tDW\t640\t* 2\t; Index = 36 Token = 5\n\t\tDW\t672\t* 2\t; Index = 36 Token = 6\n\t\tDW\t704\t* 2\t; Index = 36 Token = 7\n\t\tDW\t560\t* 2\t; Index = 36 Token = 8\n\t\tDW\t560\t* 2\t; Index = 36 Token = 9\n\t\tDW\t560\t* 2\t; Index = 36 Token = 10\n\t\tDW\t560\t* 2\t; Index = 36 Token = 11\n\t\tDW\t608\t* 2\t; Index = 36 Token = 12\n\t\tDW\t640\t* 2\t; Index = 36 Token = 13\n\t\tDW\t672\t* 2\t; Index = 36 Token = 14\n\t\tDW\t704\t* 2\t; Index = 36 Token = 15\n\t\tDW\t576\t* 2\t; Index = 37 Token = 0\n\t\tDW\t576\t* 2\t; Index = 37 Token = 1\n\t\tDW\t576\t* 2\t; Index = 37 Token = 2\n\t\tDW\t576\t* 2\t; Index = 37 Token = 3\n\t\tDW\t624\t* 2\t; Index = 37 Token = 4\n\t\tDW\t656\t* 2\t; Index = 37 Token = 5\n\t\tDW\t688\t* 2\t; Index = 37 Token = 6\n\t\tDW\t720\t* 2\t; Index = 37 Token = 7\n\t\tDW\t576\t* 2\t; Index = 37 Token = 8\n\t\tDW\t576\t* 2\t; Index = 37 Token = 9\n\t\tDW\t576\t* 2\t; Index = 37 Token = 10\n\t\tDW\t576\t* 2\t; Index = 37 Token = 11\n\t\tDW\t624\t* 2\t; Index = 37 Token = 12\n\t\tDW\t656\t* 2\t; Index = 37 Token = 13\n\t\tDW\t688\t* 2\t; Index = 37 Token = 14\n\t\tDW\t720\t* 2\t; Index = 37 Token = 15\n\t\tDW\t592\t* 2\t; Index = 38 Token = 0\n\t\tDW\t592\t* 2\t; Index = 38 Token = 1\n\t\tDW\t592\t* 2\t; Index = 38 Token = 2\n\t\tDW\t592\t* 2\t; Index = 38 Token = 3\n\t\tDW\t640\t* 2\t; Index = 38 Token = 4\n\t\tDW\t672\t* 2\t; Index = 38 Token = 5\n\t\tDW\t704\t* 2\t; Index = 38 Token = 6\n\t\tDW\t736\t* 2\t; Index = 38 Token = 7\n\t\tDW\t592\t* 2\t; Index = 38 Token = 8\n\t\tDW\t592\t* 2\t; Index = 38 Token = 9\n\t\tDW\t592\t* 2\t; Index = 38 Token = 10\n\t\tDW\t592\t* 2\t; Index = 38 Token = 11\n\t\tDW\t640\t* 2\t; Index = 38 Token = 12\n\t\tDW\t672\t* 2\t; Index = 38 Token = 13\n\t\tDW\t704\t* 2\t; Index = 38 Token = 14\n\t\tDW\t736\t* 2\t; Index = 38 Token = 15\n\t\tDW\t608\t* 2\t; Index = 39 Token = 0\n\t\tDW\t608\t* 2\t; Index = 39 Token = 1\n\t\tDW\t608\t* 2\t; Index = 39 Token = 2\n\t\tDW\t608\t* 2\t; Index = 39 Token = 3\n\t\tDW\t656\t* 2\t; Index = 39 Token = 4\n\t\tDW\t688\t* 2\t; Index = 39 Token = 5\n\t\tDW\t720\t* 2\t; Index = 39 Token = 6\n\t\tDW\t752\t* 2\t; Index = 39 Token = 7\n\t\tDW\t608\t* 2\t; Index = 39 Token = 8\n\t\tDW\t608\t* 2\t; Index = 39 Token = 9\n\t\tDW\t608\t* 2\t; Index = 39 Token = 10\n\t\tDW\t608\t* 2\t; Index = 39 Token = 11\n\t\tDW\t656\t* 2\t; Index = 39 Token = 12\n\t\tDW\t688\t* 2\t; Index = 39 Token = 13\n\t\tDW\t720\t* 2\t; Index = 39 Token = 14\n\t\tDW\t752\t* 2\t; Index = 39 Token = 15\n\t\tDW\t624\t* 2\t; Index = 40 Token = 0\n\t\tDW\t624\t* 2\t; Index = 40 Token = 1\n\t\tDW\t624\t* 2\t; Index = 40 Token = 2\n\t\tDW\t624\t* 2\t; Index = 40 Token = 3\n\t\tDW\t672\t* 2\t; Index = 40 Token = 4\n\t\tDW\t704\t* 2\t; Index = 40 Token = 5\n\t\tDW\t736\t* 2\t; Index = 40 Token = 6\n\t\tDW\t768\t* 2\t; Index = 40 Token = 7\n\t\tDW\t624\t* 2\t; Index = 40 Token = 8\n\t\tDW\t624\t* 2\t; Index = 40 Token = 9\n\t\tDW\t624\t* 2\t; Index = 40 Token = 10\n\t\tDW\t624\t* 2\t; Index = 40 Token = 11\n\t\tDW\t672\t* 2\t; Index = 40 Token = 12\n\t\tDW\t704\t* 2\t; Index = 40 Token = 13\n\t\tDW\t736\t* 2\t; Index = 40 Token = 14\n\t\tDW\t768\t* 2\t; Index = 40 Token = 15\n\t\tDW\t640\t* 2\t; Index = 41 Token = 0\n\t\tDW\t640\t* 2\t; Index = 41 Token = 1\n\t\tDW\t640\t* 2\t; Index = 41 Token = 2\n\t\tDW\t640\t* 2\t; Index = 41 Token = 3\n\t\tDW\t688\t* 2\t; Index = 41 Token = 4\n\t\tDW\t720\t* 2\t; Index = 41 Token = 5\n\t\tDW\t752\t* 2\t; Index = 41 Token = 6\n\t\tDW\t784\t* 2\t; Index = 41 Token = 7\n\t\tDW\t640\t* 2\t; Index = 41 Token = 8\n\t\tDW\t640\t* 2\t; Index = 41 Token = 9\n\t\tDW\t640\t* 2\t; Index = 41 Token = 10\n\t\tDW\t640\t* 2\t; Index = 41 Token = 11\n\t\tDW\t688\t* 2\t; Index = 41 Token = 12\n\t\tDW\t720\t* 2\t; Index = 41 Token = 13\n\t\tDW\t752\t* 2\t; Index = 41 Token = 14\n\t\tDW\t784\t* 2\t; Index = 41 Token = 15\n\t\tDW\t656\t* 2\t; Index = 42 Token = 0\n\t\tDW\t656\t* 2\t; Index = 42 Token = 1\n\t\tDW\t656\t* 2\t; Index = 42 Token = 2\n\t\tDW\t656\t* 2\t; Index = 42 Token = 3\n\t\tDW\t704\t* 2\t; Index = 42 Token = 4\n\t\tDW\t736\t* 2\t; Index = 42 Token = 5\n\t\tDW\t768\t* 2\t; Index = 42 Token = 6\n\t\tDW\t800\t* 2\t; Index = 42 Token = 7\n\t\tDW\t656\t* 2\t; Index = 42 Token = 8\n\t\tDW\t656\t* 2\t; Index = 42 Token = 9\n\t\tDW\t656\t* 2\t; Index = 42 Token = 10\n\t\tDW\t656\t* 2\t; Index = 42 Token = 11\n\t\tDW\t704\t* 2\t; Index = 42 Token = 12\n\t\tDW\t736\t* 2\t; Index = 42 Token = 13\n\t\tDW\t768\t* 2\t; Index = 42 Token = 14\n\t\tDW\t800\t* 2\t; Index = 42 Token = 15\n\t\tDW\t672\t* 2\t; Index = 43 Token = 0\n\t\tDW\t672\t* 2\t; Index = 43 Token = 1\n\t\tDW\t672\t* 2\t; Index = 43 Token = 2\n\t\tDW\t672\t* 2\t; Index = 43 Token = 3\n\t\tDW\t720\t* 2\t; Index = 43 Token = 4\n\t\tDW\t752\t* 2\t; Index = 43 Token = 5\n\t\tDW\t784\t* 2\t; Index = 43 Token = 6\n\t\tDW\t816\t* 2\t; Index = 43 Token = 7\n\t\tDW\t672\t* 2\t; Index = 43 Token = 8\n\t\tDW\t672\t* 2\t; Index = 43 Token = 9\n\t\tDW\t672\t* 2\t; Index = 43 Token = 10\n\t\tDW\t672\t* 2\t; Index = 43 Token = 11\n\t\tDW\t720\t* 2\t; Index = 43 Token = 12\n\t\tDW\t752\t* 2\t; Index = 43 Token = 13\n\t\tDW\t784\t* 2\t; Index = 43 Token = 14\n\t\tDW\t816\t* 2\t; Index = 43 Token = 15\n\t\tDW\t688\t* 2\t; Index = 44 Token = 0\n\t\tDW\t688\t* 2\t; Index = 44 Token = 1\n\t\tDW\t688\t* 2\t; Index = 44 Token = 2\n\t\tDW\t688\t* 2\t; Index = 44 Token = 3\n\t\tDW\t736\t* 2\t; Index = 44 Token = 4\n\t\tDW\t768\t* 2\t; Index = 44 Token = 5\n\t\tDW\t800\t* 2\t; Index = 44 Token = 6\n\t\tDW\t832\t* 2\t; Index = 44 Token = 7\n\t\tDW\t688\t* 2\t; Index = 44 Token = 8\n\t\tDW\t688\t* 2\t; Index = 44 Token = 9\n\t\tDW\t688\t* 2\t; Index = 44 Token = 10\n\t\tDW\t688\t* 2\t; Index = 44 Token = 11\n\t\tDW\t736\t* 2\t; Index = 44 Token = 12\n\t\tDW\t768\t* 2\t; Index = 44 Token = 13\n\t\tDW\t800\t* 2\t; Index = 44 Token = 14\n\t\tDW\t832\t* 2\t; Index = 44 Token = 15\n\t\tDW\t704\t* 2\t; Index = 45 Token = 0\n\t\tDW\t704\t* 2\t; Index = 45 Token = 1\n\t\tDW\t704\t* 2\t; Index = 45 Token = 2\n\t\tDW\t704\t* 2\t; Index = 45 Token = 3\n\t\tDW\t752\t* 2\t; Index = 45 Token = 4\n\t\tDW\t784\t* 2\t; Index = 45 Token = 5\n\t\tDW\t816\t* 2\t; Index = 45 Token = 6\n\t\tDW\t848\t* 2\t; Index = 45 Token = 7\n\t\tDW\t704\t* 2\t; Index = 45 Token = 8\n\t\tDW\t704\t* 2\t; Index = 45 Token = 9\n\t\tDW\t704\t* 2\t; Index = 45 Token = 10\n\t\tDW\t704\t* 2\t; Index = 45 Token = 11\n\t\tDW\t752\t* 2\t; Index = 45 Token = 12\n\t\tDW\t784\t* 2\t; Index = 45 Token = 13\n\t\tDW\t816\t* 2\t; Index = 45 Token = 14\n\t\tDW\t848\t* 2\t; Index = 45 Token = 15\n\t\tDW\t720\t* 2\t; Index = 46 Token = 0\n\t\tDW\t720\t* 2\t; Index = 46 Token = 1\n\t\tDW\t720\t* 2\t; Index = 46 Token = 2\n\t\tDW\t720\t* 2\t; Index = 46 Token = 3\n\t\tDW\t768\t* 2\t; Index = 46 Token = 4\n\t\tDW\t800\t* 2\t; Index = 46 Token = 5\n\t\tDW\t832\t* 2\t; Index = 46 Token = 6\n\t\tDW\t864\t* 2\t; Index = 46 Token = 7\n\t\tDW\t720\t* 2\t; Index = 46 Token = 8\n\t\tDW\t720\t* 2\t; Index = 46 Token = 9\n\t\tDW\t720\t* 2\t; Index = 46 Token = 10\n\t\tDW\t720\t* 2\t; Index = 46 Token = 11\n\t\tDW\t768\t* 2\t; Index = 46 Token = 12\n\t\tDW\t800\t* 2\t; Index = 46 Token = 13\n\t\tDW\t832\t* 2\t; Index = 46 Token = 14\n\t\tDW\t864\t* 2\t; Index = 46 Token = 15\n\t\tDW\t736\t* 2\t; Index = 47 Token = 0\n\t\tDW\t736\t* 2\t; Index = 47 Token = 1\n\t\tDW\t736\t* 2\t; Index = 47 Token = 2\n\t\tDW\t736\t* 2\t; Index = 47 Token = 3\n\t\tDW\t784\t* 2\t; Index = 47 Token = 4\n\t\tDW\t816\t* 2\t; Index = 47 Token = 5\n\t\tDW\t848\t* 2\t; Index = 47 Token = 6\n\t\tDW\t880\t* 2\t; Index = 47 Token = 7\n\t\tDW\t736\t* 2\t; Index = 47 Token = 8\n\t\tDW\t736\t* 2\t; Index = 47 Token = 9\n\t\tDW\t736\t* 2\t; Index = 47 Token = 10\n\t\tDW\t736\t* 2\t; Index = 47 Token = 11\n\t\tDW\t784\t* 2\t; Index = 47 Token = 12\n\t\tDW\t816\t* 2\t; Index = 47 Token = 13\n\t\tDW\t848\t* 2\t; Index = 47 Token = 14\n\t\tDW\t880\t* 2\t; Index = 47 Token = 15\n\t\tDW\t752\t* 2\t; Index = 48 Token = 0\n\t\tDW\t752\t* 2\t; Index = 48 Token = 1\n\t\tDW\t752\t* 2\t; Index = 48 Token = 2\n\t\tDW\t752\t* 2\t; Index = 48 Token = 3\n\t\tDW\t800\t* 2\t; Index = 48 Token = 4\n\t\tDW\t832\t* 2\t; Index = 48 Token = 5\n\t\tDW\t864\t* 2\t; Index = 48 Token = 6\n\t\tDW\t896\t* 2\t; Index = 48 Token = 7\n\t\tDW\t752\t* 2\t; Index = 48 Token = 8\n\t\tDW\t752\t* 2\t; Index = 48 Token = 9\n\t\tDW\t752\t* 2\t; Index = 48 Token = 10\n\t\tDW\t752\t* 2\t; Index = 48 Token = 11\n\t\tDW\t800\t* 2\t; Index = 48 Token = 12\n\t\tDW\t832\t* 2\t; Index = 48 Token = 13\n\t\tDW\t864\t* 2\t; Index = 48 Token = 14\n\t\tDW\t896\t* 2\t; Index = 48 Token = 15\n\t\tDW\t768\t* 2\t; Index = 49 Token = 0\n\t\tDW\t768\t* 2\t; Index = 49 Token = 1\n\t\tDW\t768\t* 2\t; Index = 49 Token = 2\n\t\tDW\t768\t* 2\t; Index = 49 Token = 3\n\t\tDW\t816\t* 2\t; Index = 49 Token = 4\n\t\tDW\t848\t* 2\t; Index = 49 Token = 5\n\t\tDW\t880\t* 2\t; Index = 49 Token = 6\n\t\tDW\t912\t* 2\t; Index = 49 Token = 7\n\t\tDW\t768\t* 2\t; Index = 49 Token = 8\n\t\tDW\t768\t* 2\t; Index = 49 Token = 9\n\t\tDW\t768\t* 2\t; Index = 49 Token = 10\n\t\tDW\t768\t* 2\t; Index = 49 Token = 11\n\t\tDW\t816\t* 2\t; Index = 49 Token = 12\n\t\tDW\t848\t* 2\t; Index = 49 Token = 13\n\t\tDW\t880\t* 2\t; Index = 49 Token = 14\n\t\tDW\t912\t* 2\t; Index = 49 Token = 15\n\t\tDW\t784\t* 2\t; Index = 50 Token = 0\n\t\tDW\t784\t* 2\t; Index = 50 Token = 1\n\t\tDW\t784\t* 2\t; Index = 50 Token = 2\n\t\tDW\t784\t* 2\t; Index = 50 Token = 3\n\t\tDW\t832\t* 2\t; Index = 50 Token = 4\n\t\tDW\t864\t* 2\t; Index = 50 Token = 5\n\t\tDW\t896\t* 2\t; Index = 50 Token = 6\n\t\tDW\t928\t* 2\t; Index = 50 Token = 7\n\t\tDW\t784\t* 2\t; Index = 50 Token = 8\n\t\tDW\t784\t* 2\t; Index = 50 Token = 9\n\t\tDW\t784\t* 2\t; Index = 50 Token = 10\n\t\tDW\t784\t* 2\t; Index = 50 Token = 11\n\t\tDW\t832\t* 2\t; Index = 50 Token = 12\n\t\tDW\t864\t* 2\t; Index = 50 Token = 13\n\t\tDW\t896\t* 2\t; Index = 50 Token = 14\n\t\tDW\t928\t* 2\t; Index = 50 Token = 15\n\t\tDW\t800\t* 2\t; Index = 51 Token = 0\n\t\tDW\t800\t* 2\t; Index = 51 Token = 1\n\t\tDW\t800\t* 2\t; Index = 51 Token = 2\n\t\tDW\t800\t* 2\t; Index = 51 Token = 3\n\t\tDW\t848\t* 2\t; Index = 51 Token = 4\n\t\tDW\t880\t* 2\t; Index = 51 Token = 5\n\t\tDW\t912\t* 2\t; Index = 51 Token = 6\n\t\tDW\t944\t* 2\t; Index = 51 Token = 7\n\t\tDW\t800\t* 2\t; Index = 51 Token = 8\n\t\tDW\t800\t* 2\t; Index = 51 Token = 9\n\t\tDW\t800\t* 2\t; Index = 51 Token = 10\n\t\tDW\t800\t* 2\t; Index = 51 Token = 11\n\t\tDW\t848\t* 2\t; Index = 51 Token = 12\n\t\tDW\t880\t* 2\t; Index = 51 Token = 13\n\t\tDW\t912\t* 2\t; Index = 51 Token = 14\n\t\tDW\t944\t* 2\t; Index = 51 Token = 15\n\t\tDW\t816\t* 2\t; Index = 52 Token = 0\n\t\tDW\t816\t* 2\t; Index = 52 Token = 1\n\t\tDW\t816\t* 2\t; Index = 52 Token = 2\n\t\tDW\t816\t* 2\t; Index = 52 Token = 3\n\t\tDW\t864\t* 2\t; Index = 52 Token = 4\n\t\tDW\t896\t* 2\t; Index = 52 Token = 5\n\t\tDW\t928\t* 2\t; Index = 52 Token = 6\n\t\tDW\t960\t* 2\t; Index = 52 Token = 7\n\t\tDW\t816\t* 2\t; Index = 52 Token = 8\n\t\tDW\t816\t* 2\t; Index = 52 Token = 9\n\t\tDW\t816\t* 2\t; Index = 52 Token = 10\n\t\tDW\t816\t* 2\t; Index = 52 Token = 11\n\t\tDW\t864\t* 2\t; Index = 52 Token = 12\n\t\tDW\t896\t* 2\t; Index = 52 Token = 13\n\t\tDW\t928\t* 2\t; Index = 52 Token = 14\n\t\tDW\t960\t* 2\t; Index = 52 Token = 15\n\t\tDW\t832\t* 2\t; Index = 53 Token = 0\n\t\tDW\t832\t* 2\t; Index = 53 Token = 1\n\t\tDW\t832\t* 2\t; Index = 53 Token = 2\n\t\tDW\t832\t* 2\t; Index = 53 Token = 3\n\t\tDW\t880\t* 2\t; Index = 53 Token = 4\n\t\tDW\t912\t* 2\t; Index = 53 Token = 5\n\t\tDW\t944\t* 2\t; Index = 53 Token = 6\n\t\tDW\t976\t* 2\t; Index = 53 Token = 7\n\t\tDW\t832\t* 2\t; Index = 53 Token = 8\n\t\tDW\t832\t* 2\t; Index = 53 Token = 9\n\t\tDW\t832\t* 2\t; Index = 53 Token = 10\n\t\tDW\t832\t* 2\t; Index = 53 Token = 11\n\t\tDW\t880\t* 2\t; Index = 53 Token = 12\n\t\tDW\t912\t* 2\t; Index = 53 Token = 13\n\t\tDW\t944\t* 2\t; Index = 53 Token = 14\n\t\tDW\t976\t* 2\t; Index = 53 Token = 15\n\t\tDW\t848\t* 2\t; Index = 54 Token = 0\n\t\tDW\t848\t* 2\t; Index = 54 Token = 1\n\t\tDW\t848\t* 2\t; Index = 54 Token = 2\n\t\tDW\t848\t* 2\t; Index = 54 Token = 3\n\t\tDW\t896\t* 2\t; Index = 54 Token = 4\n\t\tDW\t928\t* 2\t; Index = 54 Token = 5\n\t\tDW\t960\t* 2\t; Index = 54 Token = 6\n\t\tDW\t992\t* 2\t; Index = 54 Token = 7\n\t\tDW\t848\t* 2\t; Index = 54 Token = 8\n\t\tDW\t848\t* 2\t; Index = 54 Token = 9\n\t\tDW\t848\t* 2\t; Index = 54 Token = 10\n\t\tDW\t848\t* 2\t; Index = 54 Token = 11\n\t\tDW\t896\t* 2\t; Index = 54 Token = 12\n\t\tDW\t928\t* 2\t; Index = 54 Token = 13\n\t\tDW\t960\t* 2\t; Index = 54 Token = 14\n\t\tDW\t992\t* 2\t; Index = 54 Token = 15\n\t\tDW\t864\t* 2\t; Index = 55 Token = 0\n\t\tDW\t864\t* 2\t; Index = 55 Token = 1\n\t\tDW\t864\t* 2\t; Index = 55 Token = 2\n\t\tDW\t864\t* 2\t; Index = 55 Token = 3\n\t\tDW\t912\t* 2\t; Index = 55 Token = 4\n\t\tDW\t944\t* 2\t; Index = 55 Token = 5\n\t\tDW\t976\t* 2\t; Index = 55 Token = 6\n\t\tDW\t1008\t* 2\t; Index = 55 Token = 7\n\t\tDW\t864\t* 2\t; Index = 55 Token = 8\n\t\tDW\t864\t* 2\t; Index = 55 Token = 9\n\t\tDW\t864\t* 2\t; Index = 55 Token = 10\n\t\tDW\t864\t* 2\t; Index = 55 Token = 11\n\t\tDW\t912\t* 2\t; Index = 55 Token = 12\n\t\tDW\t944\t* 2\t; Index = 55 Token = 13\n\t\tDW\t976\t* 2\t; Index = 55 Token = 14\n\t\tDW\t1008\t* 2\t; Index = 55 Token = 15\n\t\tDW\t880\t* 2\t; Index = 56 Token = 0\n\t\tDW\t880\t* 2\t; Index = 56 Token = 1\n\t\tDW\t880\t* 2\t; Index = 56 Token = 2\n\t\tDW\t880\t* 2\t; Index = 56 Token = 3\n\t\tDW\t928\t* 2\t; Index = 56 Token = 4\n\t\tDW\t960\t* 2\t; Index = 56 Token = 5\n\t\tDW\t992\t* 2\t; Index = 56 Token = 6\n\t\tDW\t1024\t* 2\t; Index = 56 Token = 7\n\t\tDW\t880\t* 2\t; Index = 56 Token = 8\n\t\tDW\t880\t* 2\t; Index = 56 Token = 9\n\t\tDW\t880\t* 2\t; Index = 56 Token = 10\n\t\tDW\t880\t* 2\t; Index = 56 Token = 11\n\t\tDW\t928\t* 2\t; Index = 56 Token = 12\n\t\tDW\t960\t* 2\t; Index = 56 Token = 13\n\t\tDW\t992\t* 2\t; Index = 56 Token = 14\n\t\tDW\t1024\t* 2\t; Index = 56 Token = 15\n\t\tDW\t896\t* 2\t; Index = 57 Token = 0\n\t\tDW\t896\t* 2\t; Index = 57 Token = 1\n\t\tDW\t896\t* 2\t; Index = 57 Token = 2\n\t\tDW\t896\t* 2\t; Index = 57 Token = 3\n\t\tDW\t944\t* 2\t; Index = 57 Token = 4\n\t\tDW\t976\t* 2\t; Index = 57 Token = 5\n\t\tDW\t1008\t* 2\t; Index = 57 Token = 6\n\t\tDW\t1040\t* 2\t; Index = 57 Token = 7\n\t\tDW\t896\t* 2\t; Index = 57 Token = 8\n\t\tDW\t896\t* 2\t; Index = 57 Token = 9\n\t\tDW\t896\t* 2\t; Index = 57 Token = 10\n\t\tDW\t896\t* 2\t; Index = 57 Token = 11\n\t\tDW\t944\t* 2\t; Index = 57 Token = 12\n\t\tDW\t976\t* 2\t; Index = 57 Token = 13\n\t\tDW\t1008\t* 2\t; Index = 57 Token = 14\n\t\tDW\t1040\t* 2\t; Index = 57 Token = 15\n\t\tDW\t912\t* 2\t; Index = 58 Token = 0\n\t\tDW\t912\t* 2\t; Index = 58 Token = 1\n\t\tDW\t912\t* 2\t; Index = 58 Token = 2\n\t\tDW\t912\t* 2\t; Index = 58 Token = 3\n\t\tDW\t960\t* 2\t; Index = 58 Token = 4\n\t\tDW\t992\t* 2\t; Index = 58 Token = 5\n\t\tDW\t1024\t* 2\t; Index = 58 Token = 6\n\t\tDW\t1056\t* 2\t; Index = 58 Token = 7\n\t\tDW\t912\t* 2\t; Index = 58 Token = 8\n\t\tDW\t912\t* 2\t; Index = 58 Token = 9\n\t\tDW\t912\t* 2\t; Index = 58 Token = 10\n\t\tDW\t912\t* 2\t; Index = 58 Token = 11\n\t\tDW\t960\t* 2\t; Index = 58 Token = 12\n\t\tDW\t992\t* 2\t; Index = 58 Token = 13\n\t\tDW\t1024\t* 2\t; Index = 58 Token = 14\n\t\tDW\t1056\t* 2\t; Index = 58 Token = 15\n\t\tDW\t928\t* 2\t; Index = 59 Token = 0\n\t\tDW\t928\t* 2\t; Index = 59 Token = 1\n\t\tDW\t928\t* 2\t; Index = 59 Token = 2\n\t\tDW\t928\t* 2\t; Index = 59 Token = 3\n\t\tDW\t976\t* 2\t; Index = 59 Token = 4\n\t\tDW\t1008\t* 2\t; Index = 59 Token = 5\n\t\tDW\t1040\t* 2\t; Index = 59 Token = 6\n\t\tDW\t1072\t* 2\t; Index = 59 Token = 7\n\t\tDW\t928\t* 2\t; Index = 59 Token = 8\n\t\tDW\t928\t* 2\t; Index = 59 Token = 9\n\t\tDW\t928\t* 2\t; Index = 59 Token = 10\n\t\tDW\t928\t* 2\t; Index = 59 Token = 11\n\t\tDW\t976\t* 2\t; Index = 59 Token = 12\n\t\tDW\t1008\t* 2\t; Index = 59 Token = 13\n\t\tDW\t1040\t* 2\t; Index = 59 Token = 14\n\t\tDW\t1072\t* 2\t; Index = 59 Token = 15\n\t\tDW\t944\t* 2\t; Index = 60 Token = 0\n\t\tDW\t944\t* 2\t; Index = 60 Token = 1\n\t\tDW\t944\t* 2\t; Index = 60 Token = 2\n\t\tDW\t944\t* 2\t; Index = 60 Token = 3\n\t\tDW\t992\t* 2\t; Index = 60 Token = 4\n\t\tDW\t1024\t* 2\t; Index = 60 Token = 5\n\t\tDW\t1056\t* 2\t; Index = 60 Token = 6\n\t\tDW\t1088\t* 2\t; Index = 60 Token = 7\n\t\tDW\t944\t* 2\t; Index = 60 Token = 8\n\t\tDW\t944\t* 2\t; Index = 60 Token = 9\n\t\tDW\t944\t* 2\t; Index = 60 Token = 10\n\t\tDW\t944\t* 2\t; Index = 60 Token = 11\n\t\tDW\t992\t* 2\t; Index = 60 Token = 12\n\t\tDW\t1024\t* 2\t; Index = 60 Token = 13\n\t\tDW\t1056\t* 2\t; Index = 60 Token = 14\n\t\tDW\t1088\t* 2\t; Index = 60 Token = 15\n\t\tDW\t960\t* 2\t; Index = 61 Token = 0\n\t\tDW\t960\t* 2\t; Index = 61 Token = 1\n\t\tDW\t960\t* 2\t; Index = 61 Token = 2\n\t\tDW\t960\t* 2\t; Index = 61 Token = 3\n\t\tDW\t1008\t* 2\t; Index = 61 Token = 4\n\t\tDW\t1040\t* 2\t; Index = 61 Token = 5\n\t\tDW\t1072\t* 2\t; Index = 61 Token = 6\n\t\tDW\t1104\t* 2\t; Index = 61 Token = 7\n\t\tDW\t960\t* 2\t; Index = 61 Token = 8\n\t\tDW\t960\t* 2\t; Index = 61 Token = 9\n\t\tDW\t960\t* 2\t; Index = 61 Token = 10\n\t\tDW\t960\t* 2\t; Index = 61 Token = 11\n\t\tDW\t1008\t* 2\t; Index = 61 Token = 12\n\t\tDW\t1040\t* 2\t; Index = 61 Token = 13\n\t\tDW\t1072\t* 2\t; Index = 61 Token = 14\n\t\tDW\t1104\t* 2\t; Index = 61 Token = 15\n\t\tDW\t976\t* 2\t; Index = 62 Token = 0\n\t\tDW\t976\t* 2\t; Index = 62 Token = 1\n\t\tDW\t976\t* 2\t; Index = 62 Token = 2\n\t\tDW\t976\t* 2\t; Index = 62 Token = 3\n\t\tDW\t1024\t* 2\t; Index = 62 Token = 4\n\t\tDW\t1056\t* 2\t; Index = 62 Token = 5\n\t\tDW\t1088\t* 2\t; Index = 62 Token = 6\n\t\tDW\t1120\t* 2\t; Index = 62 Token = 7\n\t\tDW\t976\t* 2\t; Index = 62 Token = 8\n\t\tDW\t976\t* 2\t; Index = 62 Token = 9\n\t\tDW\t976\t* 2\t; Index = 62 Token = 10\n\t\tDW\t976\t* 2\t; Index = 62 Token = 11\n\t\tDW\t1024\t* 2\t; Index = 62 Token = 12\n\t\tDW\t1056\t* 2\t; Index = 62 Token = 13\n\t\tDW\t1088\t* 2\t; Index = 62 Token = 14\n\t\tDW\t1120\t* 2\t; Index = 62 Token = 15\n\t\tDW\t992\t* 2\t; Index = 63 Token = 0\n\t\tDW\t992\t* 2\t; Index = 63 Token = 1\n\t\tDW\t992\t* 2\t; Index = 63 Token = 2\n\t\tDW\t992\t* 2\t; Index = 63 Token = 3\n\t\tDW\t1040\t* 2\t; Index = 63 Token = 4\n\t\tDW\t1072\t* 2\t; Index = 63 Token = 5\n\t\tDW\t1104\t* 2\t; Index = 63 Token = 6\n\t\tDW\t1136\t* 2\t; Index = 63 Token = 7\n\t\tDW\t992\t* 2\t; Index = 63 Token = 8\n\t\tDW\t992\t* 2\t; Index = 63 Token = 9\n\t\tDW\t992\t* 2\t; Index = 63 Token = 10\n\t\tDW\t992\t* 2\t; Index = 63 Token = 11\n\t\tDW\t1040\t* 2\t; Index = 63 Token = 12\n\t\tDW\t1072\t* 2\t; Index = 63 Token = 13\n\t\tDW\t1104\t* 2\t; Index = 63 Token = 14\n\t\tDW\t1136\t* 2\t; Index = 63 Token = 15\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 0\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 1\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 2\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 3\n\t\tDW\t1056\t* 2\t; Index = 64 Token = 4\n\t\tDW\t1088\t* 2\t; Index = 64 Token = 5\n\t\tDW\t1120\t* 2\t; Index = 64 Token = 6\n\t\tDW\t1152\t* 2\t; Index = 64 Token = 7\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 8\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 9\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 10\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 11\n\t\tDW\t1056\t* 2\t; Index = 64 Token = 12\n\t\tDW\t1088\t* 2\t; Index = 64 Token = 13\n\t\tDW\t1120\t* 2\t; Index = 64 Token = 14\n\t\tDW\t1152\t* 2\t; Index = 64 Token = 15\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 0\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 1\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 2\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 3\n\t\tDW\t1072\t* 2\t; Index = 65 Token = 4\n\t\tDW\t1104\t* 2\t; Index = 65 Token = 5\n\t\tDW\t1136\t* 2\t; Index = 65 Token = 6\n\t\tDW\t1168\t* 2\t; Index = 65 Token = 7\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 8\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 9\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 10\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 11\n\t\tDW\t1072\t* 2\t; Index = 65 Token = 12\n\t\tDW\t1104\t* 2\t; Index = 65 Token = 13\n\t\tDW\t1136\t* 2\t; Index = 65 Token = 14\n\t\tDW\t1168\t* 2\t; Index = 65 Token = 15\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 0\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 1\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 2\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 3\n\t\tDW\t1088\t* 2\t; Index = 66 Token = 4\n\t\tDW\t1120\t* 2\t; Index = 66 Token = 5\n\t\tDW\t1152\t* 2\t; Index = 66 Token = 6\n\t\tDW\t1184\t* 2\t; Index = 66 Token = 7\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 8\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 9\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 10\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 11\n\t\tDW\t1088\t* 2\t; Index = 66 Token = 12\n\t\tDW\t1120\t* 2\t; Index = 66 Token = 13\n\t\tDW\t1152\t* 2\t; Index = 66 Token = 14\n\t\tDW\t1184\t* 2\t; Index = 66 Token = 15\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 0\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 1\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 2\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 3\n\t\tDW\t1104\t* 2\t; Index = 67 Token = 4\n\t\tDW\t1136\t* 2\t; Index = 67 Token = 5\n\t\tDW\t1168\t* 2\t; Index = 67 Token = 6\n\t\tDW\t1200\t* 2\t; Index = 67 Token = 7\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 8\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 9\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 10\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 11\n\t\tDW\t1104\t* 2\t; Index = 67 Token = 12\n\t\tDW\t1136\t* 2\t; Index = 67 Token = 13\n\t\tDW\t1168\t* 2\t; Index = 67 Token = 14\n\t\tDW\t1200\t* 2\t; Index = 67 Token = 15\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 0\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 1\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 2\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 3\n\t\tDW\t1120\t* 2\t; Index = 68 Token = 4\n\t\tDW\t1152\t* 2\t; Index = 68 Token = 5\n\t\tDW\t1184\t* 2\t; Index = 68 Token = 6\n\t\tDW\t1216\t* 2\t; Index = 68 Token = 7\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 8\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 9\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 10\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 11\n\t\tDW\t1120\t* 2\t; Index = 68 Token = 12\n\t\tDW\t1152\t* 2\t; Index = 68 Token = 13\n\t\tDW\t1184\t* 2\t; Index = 68 Token = 14\n\t\tDW\t1216\t* 2\t; Index = 68 Token = 15\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 0\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 1\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 2\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 3\n\t\tDW\t1136\t* 2\t; Index = 69 Token = 4\n\t\tDW\t1168\t* 2\t; Index = 69 Token = 5\n\t\tDW\t1200\t* 2\t; Index = 69 Token = 6\n\t\tDW\t1232\t* 2\t; Index = 69 Token = 7\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 8\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 9\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 10\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 11\n\t\tDW\t1136\t* 2\t; Index = 69 Token = 12\n\t\tDW\t1168\t* 2\t; Index = 69 Token = 13\n\t\tDW\t1200\t* 2\t; Index = 69 Token = 14\n\t\tDW\t1232\t* 2\t; Index = 69 Token = 15\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 0\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 1\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 2\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 3\n\t\tDW\t1152\t* 2\t; Index = 70 Token = 4\n\t\tDW\t1184\t* 2\t; Index = 70 Token = 5\n\t\tDW\t1216\t* 2\t; Index = 70 Token = 6\n\t\tDW\t1248\t* 2\t; Index = 70 Token = 7\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 8\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 9\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 10\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 11\n\t\tDW\t1152\t* 2\t; Index = 70 Token = 12\n\t\tDW\t1184\t* 2\t; Index = 70 Token = 13\n\t\tDW\t1216\t* 2\t; Index = 70 Token = 14\n\t\tDW\t1248\t* 2\t; Index = 70 Token = 15\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 0\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 1\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 2\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 3\n\t\tDW\t1168\t* 2\t; Index = 71 Token = 4\n\t\tDW\t1200\t* 2\t; Index = 71 Token = 5\n\t\tDW\t1232\t* 2\t; Index = 71 Token = 6\n\t\tDW\t1264\t* 2\t; Index = 71 Token = 7\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 8\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 9\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 10\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 11\n\t\tDW\t1168\t* 2\t; Index = 71 Token = 12\n\t\tDW\t1200\t* 2\t; Index = 71 Token = 13\n\t\tDW\t1232\t* 2\t; Index = 71 Token = 14\n\t\tDW\t1264\t* 2\t; Index = 71 Token = 15\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 0\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 1\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 2\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 3\n\t\tDW\t1184\t* 2\t; Index = 72 Token = 4\n\t\tDW\t1216\t* 2\t; Index = 72 Token = 5\n\t\tDW\t1248\t* 2\t; Index = 72 Token = 6\n\t\tDW\t1280\t* 2\t; Index = 72 Token = 7\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 8\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 9\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 10\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 11\n\t\tDW\t1184\t* 2\t; Index = 72 Token = 12\n\t\tDW\t1216\t* 2\t; Index = 72 Token = 13\n\t\tDW\t1248\t* 2\t; Index = 72 Token = 14\n\t\tDW\t1280\t* 2\t; Index = 72 Token = 15\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 0\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 1\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 2\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 3\n\t\tDW\t1200\t* 2\t; Index = 73 Token = 4\n\t\tDW\t1232\t* 2\t; Index = 73 Token = 5\n\t\tDW\t1264\t* 2\t; Index = 73 Token = 6\n\t\tDW\t1296\t* 2\t; Index = 73 Token = 7\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 8\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 9\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 10\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 11\n\t\tDW\t1200\t* 2\t; Index = 73 Token = 12\n\t\tDW\t1232\t* 2\t; Index = 73 Token = 13\n\t\tDW\t1264\t* 2\t; Index = 73 Token = 14\n\t\tDW\t1296\t* 2\t; Index = 73 Token = 15\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 0\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 1\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 2\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 3\n\t\tDW\t1216\t* 2\t; Index = 74 Token = 4\n\t\tDW\t1248\t* 2\t; Index = 74 Token = 5\n\t\tDW\t1280\t* 2\t; Index = 74 Token = 6\n\t\tDW\t1312\t* 2\t; Index = 74 Token = 7\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 8\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 9\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 10\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 11\n\t\tDW\t1216\t* 2\t; Index = 74 Token = 12\n\t\tDW\t1248\t* 2\t; Index = 74 Token = 13\n\t\tDW\t1280\t* 2\t; Index = 74 Token = 14\n\t\tDW\t1312\t* 2\t; Index = 74 Token = 15\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 0\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 1\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 2\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 3\n\t\tDW\t1232\t* 2\t; Index = 75 Token = 4\n\t\tDW\t1264\t* 2\t; Index = 75 Token = 5\n\t\tDW\t1296\t* 2\t; Index = 75 Token = 6\n\t\tDW\t1328\t* 2\t; Index = 75 Token = 7\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 8\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 9\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 10\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 11\n\t\tDW\t1232\t* 2\t; Index = 75 Token = 12\n\t\tDW\t1264\t* 2\t; Index = 75 Token = 13\n\t\tDW\t1296\t* 2\t; Index = 75 Token = 14\n\t\tDW\t1328\t* 2\t; Index = 75 Token = 15\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 0\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 1\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 2\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 3\n\t\tDW\t1248\t* 2\t; Index = 76 Token = 4\n\t\tDW\t1280\t* 2\t; Index = 76 Token = 5\n\t\tDW\t1312\t* 2\t; Index = 76 Token = 6\n\t\tDW\t1344\t* 2\t; Index = 76 Token = 7\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 8\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 9\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 10\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 11\n\t\tDW\t1248\t* 2\t; Index = 76 Token = 12\n\t\tDW\t1280\t* 2\t; Index = 76 Token = 13\n\t\tDW\t1312\t* 2\t; Index = 76 Token = 14\n\t\tDW\t1344\t* 2\t; Index = 76 Token = 15\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 0\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 1\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 2\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 3\n\t\tDW\t1264\t* 2\t; Index = 77 Token = 4\n\t\tDW\t1296\t* 2\t; Index = 77 Token = 5\n\t\tDW\t1328\t* 2\t; Index = 77 Token = 6\n\t\tDW\t1360\t* 2\t; Index = 77 Token = 7\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 8\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 9\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 10\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 11\n\t\tDW\t1264\t* 2\t; Index = 77 Token = 12\n\t\tDW\t1296\t* 2\t; Index = 77 Token = 13\n\t\tDW\t1328\t* 2\t; Index = 77 Token = 14\n\t\tDW\t1360\t* 2\t; Index = 77 Token = 15\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 0\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 1\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 2\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 3\n\t\tDW\t1280\t* 2\t; Index = 78 Token = 4\n\t\tDW\t1312\t* 2\t; Index = 78 Token = 5\n\t\tDW\t1344\t* 2\t; Index = 78 Token = 6\n\t\tDW\t1376\t* 2\t; Index = 78 Token = 7\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 8\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 9\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 10\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 11\n\t\tDW\t1280\t* 2\t; Index = 78 Token = 12\n\t\tDW\t1312\t* 2\t; Index = 78 Token = 13\n\t\tDW\t1344\t* 2\t; Index = 78 Token = 14\n\t\tDW\t1376\t* 2\t; Index = 78 Token = 15\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 0\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 1\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 2\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 3\n\t\tDW\t1296\t* 2\t; Index = 79 Token = 4\n\t\tDW\t1328\t* 2\t; Index = 79 Token = 5\n\t\tDW\t1360\t* 2\t; Index = 79 Token = 6\n\t\tDW\t1392\t* 2\t; Index = 79 Token = 7\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 8\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 9\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 10\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 11\n\t\tDW\t1296\t* 2\t; Index = 79 Token = 12\n\t\tDW\t1328\t* 2\t; Index = 79 Token = 13\n\t\tDW\t1360\t* 2\t; Index = 79 Token = 14\n\t\tDW\t1392\t* 2\t; Index = 79 Token = 15\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 0\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 1\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 2\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 3\n\t\tDW\t1312\t* 2\t; Index = 80 Token = 4\n\t\tDW\t1344\t* 2\t; Index = 80 Token = 5\n\t\tDW\t1376\t* 2\t; Index = 80 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 80 Token = 7\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 8\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 9\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 10\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 11\n\t\tDW\t1312\t* 2\t; Index = 80 Token = 12\n\t\tDW\t1344\t* 2\t; Index = 80 Token = 13\n\t\tDW\t1376\t* 2\t; Index = 80 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 80 Token = 15\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 0\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 1\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 2\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 3\n\t\tDW\t1328\t* 2\t; Index = 81 Token = 4\n\t\tDW\t1360\t* 2\t; Index = 81 Token = 5\n\t\tDW\t1392\t* 2\t; Index = 81 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 81 Token = 7\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 8\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 9\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 10\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 11\n\t\tDW\t1328\t* 2\t; Index = 81 Token = 12\n\t\tDW\t1360\t* 2\t; Index = 81 Token = 13\n\t\tDW\t1392\t* 2\t; Index = 81 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 81 Token = 15\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 0\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 1\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 2\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 3\n\t\tDW\t1344\t* 2\t; Index = 82 Token = 4\n\t\tDW\t1376\t* 2\t; Index = 82 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 7\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 8\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 9\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 10\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 11\n\t\tDW\t1344\t* 2\t; Index = 82 Token = 12\n\t\tDW\t1376\t* 2\t; Index = 82 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 15\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 0\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 1\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 2\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 3\n\t\tDW\t1360\t* 2\t; Index = 83 Token = 4\n\t\tDW\t1392\t* 2\t; Index = 83 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 7\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 8\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 9\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 10\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 11\n\t\tDW\t1360\t* 2\t; Index = 83 Token = 12\n\t\tDW\t1392\t* 2\t; Index = 83 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 15\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 0\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 1\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 2\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 3\n\t\tDW\t1376\t* 2\t; Index = 84 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 7\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 8\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 9\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 10\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 11\n\t\tDW\t1376\t* 2\t; Index = 84 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 15\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 0\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 1\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 2\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 3\n\t\tDW\t1392\t* 2\t; Index = 85 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 7\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 8\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 9\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 10\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 11\n\t\tDW\t1392\t* 2\t; Index = 85 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 15\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 0\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 1\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 2\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 7\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 8\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 9\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 10\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 15\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 0\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 1\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 2\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 7\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 8\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 9\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 10\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 15\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 0\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 1\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 2\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 7\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 8\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 9\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 10\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 15\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/KEYBOARD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Keyboard Library                                    *\n *                                                                                             *\n *                    File Name : KEYBOARD.H                                                   *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 10/16/95                                                     *\n *                                                                                             *\n *                  Last Update : October 16, 1995 [PWG]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef KEYBOARD_H\n#define KEYBOARD_H\n \n#include <WWSTD.H>\n\ntypedef enum {\n\tWWKEY_SHIFT_BIT\t= 0x100,\n\tWWKEY_CTRL_BIT\t\t= 0x200,\n\tWWKEY_ALT_BIT\t\t= 0x400,\n\tWWKEY_RLS_BIT\t\t= 0x800,\n\tWWKEY_VK_BIT\t\t= 0x1000,\n\tWWKEY_DBL_BIT\t\t= 0x2000,\n\tWWKEY_BTN_BIT\t\t= 0x8000,\n} WWKey_Type;\n\nclass WWKeyboardClass\n{\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tWWKeyboardClass();\n\n\t\t/*===================================================================*/\n\t\t/* Define the functions which work with the Keyboard Class\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBOOL \tCheck(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for meta key\n\t\tint \tGet(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// gets a meta key from the keybuffer\n\t\tBOOL \tPut(int key);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// dumps a key into the keybuffer\n\t\tBOOL\tPut_Key_Message(\tUINT vk_key, BOOL release = FALSE, \t\t// handles keyboard related message\n\t\t\t\t\t\t\t\t\t\tBOOL dbl = FALSE);\t\t\t\t\t\t\t//   and mouse clicks and dbl clicks\n\t\tint \tCheck_Num(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for a keynum key\n\t\tint \tGet_VK(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// gets keynum key from key buff\n\t\tint \tCheck_ACII(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for an ascii key\n\t\tint \tGet_ASCII(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// gets an ascii key from keybuff\n\t\tint \tCheck_Bits(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for key w/ bits\n\t\tint \tGet_Bits(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// get key from keybuff w/ bits\n\t\tint \tTo_ASCII(int num);\t\t\t\t\t\t\t\t\t\t\t\t\t// converts keynum to ascii value\n\t\tint \tOption_On(int option);\t\t\t\t\t\t\t\t\t\t\t\t// turns specified option on\n\t\tint \tOption_Off(int option);\t\t\t\t\t\t\t\t\t\t\t\t// turns specified option off\n\t\tvoid \tClear(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// clears all keys from keybuffer\n\t\tint \tDown(int key);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// tests to see if a key is down\n\t\tvoid\tAI(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// messaging logic for key manager\n\n\t\t/*===================================================================*/\n\t\t/* Define the main hook for the message processing loop.\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tvoid Message_Handler(HWND hwnd, UINT message, UINT wParam, LONG lParam);\n\n\t\t/*===================================================================*/\n\t\t/* Define public routines which can be used on keys in general.\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl);\n\t\tBOOL Is_Mouse_Key(int key);\n\n\n\t\t/*===================================================================*/\n\t\t/* Define the public access variables which are used with the\t\t\t*/\n\t\t/*   Keyboard Class.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tint\t\t\t\tMouseQX;\n\t\tint\t\t\t\tMouseQY;\n\n\t\tunsigned char\tVKRemap[256];\t\t// gives vk for any ascii char\n\tprivate:\n\t\t/*===================================================================*/\n\t\t/* Define the private access functions which are used by keyboard\t\t*/\n\t\t/*===================================================================*/\n\t\tint  Buff_Get(void);\n\n\n\t\t/*===================================================================*/\n\t\t/* Define the private access variables which are used with the\t\t\t*/\n\t\t/*   Keyboard Class.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tunsigned char\tAsciiRemap[2048];\t// remap for shft/ctrl/alt key combos\n\t\tunsigned short Buffer[256];\t\t// buffer which holds actual keypresses\n\t\tunsigned char  ToggleKeys[256];\t// determines toggles which affect key\n\t\tlong\t\t\t\tHead;\t\t\t\t\t// the head position in keyboard buffer\n\t\tlong\t\t\t\tTail;\t\t\t\t\t// the tail position in keyboard buffer\n\t\tint\t\t\t\tMState;\n\t\tint\t\t\t\tConditional;\n\t\tHANDLE\t\t\tCurrentCursor;\n};\n\n\n#define\tVK_NONE\t\t\t\t  0x00\n#define\tVK_LBUTTON          0x01\n#define\tVK_RBUTTON          0x02\n#define\tVK_CANCEL           0x03\n#define\tVK_MBUTTON          0x04\n#define\tVK_NONE_05\t\t\t  0x05\n#define\tVK_NONE_06\t\t\t  0x06\n#define\tVK_NONE_07\t\t\t  0x07\n#define\tVK_BACK             0x08\n#define\tVK_TAB              0x09\n#define\tVK_NONE_0A\t\t\t  0x0A\n#define\tVK_NONE_0B\t\t\t  0x0B\n#define\tVK_CLEAR            0x0C\n#define\tVK_RETURN           0x0D\n#define\tVK_NONE_0E\t\t\t  0x0E\n#define\tVK_NONE_0F\t\t\t  0x0F\n#define\tVK_SHIFT            0x10\n#define\tVK_CONTROL          0x11\n#define\tVK_MENU             0x12\n#define\tVK_PAUSE            0x13\n#define\tVK_CAPITAL          0x14\n#define\tVK_NONE_15\t\t\t  0x15\n#define\tVK_NONE_16\t\t\t  0x16\n#define\tVK_NONE_17\t\t\t  0x17\n#define\tVK_NONE_18\t\t\t  0x18\n#define\tVK_NONE_19\t\t\t  0x19\n#define\tVK_NONE_1A\t\t\t  0x1A\n#define\tVK_ESCAPE           0x1B\n#define\tVK_NONE_1C\t\t\t  0x1C\n#define\tVK_NONE_1D\t\t\t  0x1D\n#define\tVK_NONE_1E\t\t\t  0x1E\n#define\tVK_NONE_1F\t\t\t  0x1F\n#define\tVK_SPACE            0x20\n#define\tVK_PRIOR            0x21\n#define\tVK_NEXT             0x22\n#define\tVK_END              0x23\n#define\tVK_HOME             0x24\n#define\tVK_LEFT             0x25\n#define\tVK_UP               0x26\n#define\tVK_RIGHT            0x27\n#define\tVK_DOWN             0x28\n#define\tVK_SELECT           0x29\n#define\tVK_PRINT            0x2A\n#define\tVK_EXECUTE          0x2B\n#define\tVK_SNAPSHOT         0x2C\n#define\tVK_INSERT           0x2D\n#define\tVK_DELETE           0x2E\n#define\tVK_HELP             0x2F\n#define\tVK_0\t\t\t\t\t  0x30\n#define\tVK_1\t\t\t\t\t  0x31\n#define\tVK_2\t\t\t\t\t  0x32\n#define\tVK_3\t\t\t\t\t  0x33\n#define\tVK_4\t\t\t\t\t  0x34\n#define\tVK_5\t\t\t\t\t  0x35\n#define\tVK_6\t\t\t\t\t  0x36\n#define\tVK_7\t\t\t\t\t  0x37\n#define\tVK_8\t\t\t\t\t  0x38\n#define\tVK_9\t\t\t\t\t  0x39\n#define\tVK_NONE_3B\t\t\t  0x3B\n#define\tVK_NONE_3C\t\t\t  0x3C\n#define\tVK_NONE_3D\t\t\t  0x3D\n#define\tVK_NONE_3E\t\t\t  0x3E\n#define\tVK_NONE_3F\t\t\t  0x3F\n#define\tVK_NONE_40\t\t\t  0x40\n#define\tVK_A\t\t\t\t\t  0x41\n#define\tVK_B\t\t\t\t\t  0x42\n#define\tVK_C\t\t\t\t\t  0x43\n#define\tVK_D\t\t\t\t\t  0x44\n#define\tVK_E\t\t\t\t\t  0x45\n#define\tVK_F\t\t\t\t\t  0x46\n#define\tVK_G\t\t\t\t\t  0x47\n#define\tVK_H\t\t\t\t\t  0x48\n#define\tVK_I\t\t\t\t\t  0x49\n#define\tVK_J\t\t\t\t\t  0x4A\n#define\tVK_K\t\t\t\t\t  0x4B\n#define\tVK_L\t\t\t\t\t  0x4C\n#define\tVK_M\t\t\t\t\t  0x4D\n#define\tVK_N\t\t\t\t\t  0x4E\n#define\tVK_O\t\t\t\t\t  0x4F\n#define\tVK_P\t\t\t\t\t  0x50\n#define\tVK_Q\t\t\t\t\t  0x51\n#define\tVK_R\t\t\t\t\t  0x52\n#define\tVK_S\t\t\t\t\t  0x53\n#define\tVK_T\t\t\t\t\t  0x54\n#define\tVK_U\t\t\t\t\t  0x55\n#define\tVK_V\t\t\t\t\t  0x56\n#define\tVK_W\t\t\t\t\t  0x57\n#define\tVK_X\t\t\t\t\t  0x58\n#define\tVK_Y\t\t\t\t\t  0x59\n#define\tVK_Z\t\t\t\t\t  0x5A\n#define\tVK_NONE_5B\t\t\t  0x5B\n#define\tVK_NONE_5C\t\t\t  0x5C\n#define\tVK_NONE_5D\t\t\t  0x5D\n#define\tVK_NONE_5E\t\t\t  0x5E\n#define\tVK_NONE_5F\t\t\t  0x5F\n#define\tVK_NUMPAD0          0x60\n#define\tVK_NUMPAD1          0x61\n#define\tVK_NUMPAD2          0x62\n#define\tVK_NUMPAD3          0x63\n#define\tVK_NUMPAD4          0x64\n#define\tVK_NUMPAD5          0x65\n#define\tVK_NUMPAD6          0x66\n#define\tVK_NUMPAD7          0x67\n#define\tVK_NUMPAD8          0x68\n#define\tVK_NUMPAD9          0x69\n#define\tVK_MULTIPLY         0x6A\n#define\tVK_ADD              0x6B\n#define\tVK_SEPARATOR        0x6C\n#define\tVK_SUBTRACT         0x6D\n#define\tVK_DECIMAL          0x6E\n#define\tVK_DIVIDE           0x6F\n#define\tVK_F1               0x70\n#define\tVK_F2               0x71\n#define\tVK_F3               0x72\n#define\tVK_F4               0x73\n#define\tVK_F5               0x74\n#define\tVK_F6               0x75\n#define\tVK_F7               0x76\n#define\tVK_F8               0x77\n#define\tVK_F9               0x78\n#define\tVK_F10              0x79\n#define\tVK_F11              0x7A\n#define\tVK_F12              0x7B\n#define\tVK_F13              0x7C\n#define\tVK_F14              0x7D\n#define\tVK_F15              0x7E\n#define\tVK_F16              0x7F\n#define\tVK_F17              0x80\n#define\tVK_F18              0x81\n#define\tVK_F19              0x82\n#define\tVK_F20              0x83\n#define\tVK_F21              0x84\n#define\tVK_F22              0x85\n#define\tVK_F23              0x86\n#define\tVK_F24              0x87\n#define\tVK_NONE_88          0x88\n#define\tVK_NONE_89          0x89\n#define\tVK_NONE_8A          0x8A\n#define\tVK_NONE_8B          0x8B\n#define\tVK_NONE_8C          0x8C\n#define\tVK_NONE_8D          0x8D\n#define\tVK_NONE_8E          0x8E\n#define\tVK_NONE_8F          0x8F\n#define\tVK_NUMLOCK          0x90\n#define\tVK_SCROLL           0x91\n#define\tVK_NONE_92\t\t\t  0x92\n#define\tVK_NONE_93\t\t\t  0x93\n#define\tVK_NONE_94\t\t\t  0x94\n#define\tVK_NONE_95\t\t\t  0x95\n#define\tVK_NONE_96\t\t\t  0x96\n#define\tVK_NONE_97\t\t\t  0x97\n#define\tVK_NONE_98\t\t\t  0x98\n#define\tVK_NONE_99\t\t\t  0x99\n#define\tVK_NONE_9A\t\t\t  0x9A\n#define\tVK_NONE_9B\t\t\t  0x9B\n#define\tVK_NONE_9C\t\t\t  0x9C\n#define\tVK_NONE_9D\t\t\t  0x9D\n#define\tVK_NONE_9E\t\t\t  0x9E\n#define\tVK_NONE_9F\t\t\t  0x9F\n#define\tVK_NONE_A0\t\t\t  0xA0\n#define\tVK_NONE_A1\t\t\t  0xA1\n#define\tVK_NONE_A2\t\t\t  0xA2\n#define\tVK_NONE_A3\t\t\t  0xA3\n#define\tVK_NONE_A4\t\t\t  0xA4\n#define\tVK_NONE_A5\t\t\t  0xA5\n#define\tVK_NONE_A6\t\t\t  0xA6\n#define\tVK_NONE_A7\t\t\t  0xA7\n#define\tVK_NONE_A8\t\t\t  0xA8\n#define\tVK_NONE_A9\t\t\t  0xA9\n#define\tVK_NONE_AA\t\t\t  0xAA\n#define\tVK_NONE_AB\t\t\t  0xAB\n#define\tVK_NONE_AC\t\t\t  0xAC\n#define\tVK_NONE_AD\t\t\t  0xAD\n#define\tVK_NONE_AE\t\t\t  0xAE\n#define\tVK_NONE_AF\t\t\t  0xAF\n#define\tVK_NONE_B0\t\t\t  0xB0\n#define\tVK_NONE_B1\t\t\t  0xB1\n#define\tVK_NONE_B2\t\t\t  0xB2\n#define\tVK_NONE_B3\t\t\t  0xB3\n#define\tVK_NONE_B4\t\t\t  0xB4\n#define\tVK_NONE_B5\t\t\t  0xB5\n#define\tVK_NONE_B6\t\t\t  0xB6\n#define\tVK_NONE_B7\t\t\t  0xB7\n#define\tVK_NONE_B8\t\t\t  0xB8\n#define\tVK_NONE_B9\t\t\t  0xB9\n#define\tVK_NONE_BA\t\t\t  0xBA\n#define\tVK_NONE_BB\t\t\t  0xBB\n#define\tVK_NONE_BC\t\t\t  0xBC\n#define\tVK_NONE_BD\t\t\t  0xBD\n#define\tVK_NONE_BE\t\t\t  0xBE\n#define\tVK_NONE_BF\t\t\t  0xBF\n#define\tVK_NONE_C0\t\t\t  0xC0\n#define\tVK_NONE_C1\t\t\t  0xC1\n#define\tVK_NONE_C2\t\t\t  0xC2\n#define\tVK_NONE_C3\t\t\t  0xC3\n#define\tVK_NONE_C4\t\t\t  0xC4\n#define\tVK_NONE_C5\t\t\t  0xC5\n#define\tVK_NONE_C6\t\t\t  0xC6\n#define\tVK_NONE_C7\t\t\t  0xC7\n#define\tVK_NONE_C8\t\t\t  0xC8\n#define\tVK_NONE_C9\t\t\t  0xC9\n#define\tVK_NONE_CA\t\t\t  0xCA\n#define\tVK_NONE_CB\t\t\t  0xCB\n#define\tVK_NONE_CC\t\t\t  0xCC\n#define\tVK_NONE_CD\t\t\t  0xCD\n#define\tVK_NONE_CE\t\t\t  0xCE\n#define\tVK_NONE_CF\t\t\t  0xCF\n#define\tVK_NONE_D0\t\t\t  0xD0\n#define\tVK_NONE_D1\t\t\t  0xD1\n#define\tVK_NONE_D2\t\t\t  0xD2\n#define\tVK_NONE_D3\t\t\t  0xD3\n#define\tVK_NONE_D4\t\t\t  0xD4\n#define\tVK_NONE_D5\t\t\t  0xD5\n#define\tVK_NONE_D6\t\t\t  0xD6\n#define\tVK_NONE_D7\t\t\t  0xD7\n#define\tVK_NONE_D8\t\t\t  0xD8\n#define\tVK_NONE_D9\t\t\t  0xD9\n#define\tVK_NONE_DA\t\t\t  0xDA\n#define\tVK_NONE_DB\t\t\t  0xDB\n#define\tVK_NONE_DC\t\t\t  0xDC\n#define\tVK_NONE_DD\t\t\t  0xDD\n#define\tVK_NONE_DE\t\t\t  0xDE\n#define\tVK_NONE_DF\t\t\t  0xDF\n#define\tVK_NONE_E0\t\t\t  0xE0\n#define\tVK_NONE_E1\t\t\t  0xE1\n#define\tVK_NONE_E2\t\t\t  0xE2\n#define\tVK_NONE_E3\t\t\t  0xE3\n#define\tVK_NONE_E4\t\t\t  0xE4\n#define\tVK_NONE_E5\t\t\t  0xE5\n#define\tVK_NONE_E6\t\t\t  0xE6\n#define\tVK_NONE_E7\t\t\t  0xE7\n#define\tVK_NONE_E8\t\t\t  0xE8\n#define\tVK_NONE_E9\t\t\t  0xE9\n#define\tVK_NONE_EA\t\t\t  0xEA\n#define\tVK_NONE_EB\t\t\t  0xEB\n#define\tVK_NONE_EC\t\t\t  0xEC\n#define\tVK_NONE_ED\t\t\t  0xED\n#define\tVK_NONE_EE\t\t\t  0xEE\n#define\tVK_NONE_EF\t\t\t  0xEF\n#define\tVK_NONE_F0\t\t\t  0xF0\n#define\tVK_NONE_F1\t\t\t  0xF1\n#define\tVK_NONE_F2\t\t\t  0xF2\n#define\tVK_NONE_F3\t\t\t  0xF3\n#define\tVK_NONE_F4\t\t\t  0xF4\n#define\tVK_NONE_F5\t\t\t  0xF5\n#define\tVK_NONE_F6\t\t\t  0xF6\n#define\tVK_NONE_F7\t\t\t  0xF7\n#define\tVK_NONE_F8\t\t\t  0xF8\n#define\tVK_NONE_F9\t\t\t  0xF9\n#define\tVK_NONE_FA\t\t\t  0xFA\n#define\tVK_NONE_FB\t\t\t  0xFB\n#define\tVK_NONE_FC\t\t\t  0xFC\n#define\tVK_NONE_FD\t\t\t  0xFD\n#define\tVK_NONE_FE\t\t\t  0xFE\n#define\tVK_NONE_FF\t\t\t  0xFF\n\n#define\tVK_UPLEFT\t\t\t  VK_HOME\n#define\tVK_UPRIGHT\t\t\t  VK_PRIOR\n#define\tVK_DOWNLEFT\t\t\t  VK_END\n#define\tVK_DOWNRIGHT\t\t  VK_NEXT\n#define\tVK_ALT\t\t\t\t  VK_MENU\n\nenum {\n\t//\n\t// Define all the KA types as variations of the VK types.  This is\n\t// so the KA functions will work properly under windows 95.\n\t//\n\tKA_NONE\t\t\t\t= 0,\n\tKA_MORE \t\t\t\t= 1,\n\tKA_SETBKGDCOL \t\t= 2,\n\tKA_SETFORECOL \t\t= 6,\n\tKA_FORMFEED \t\t= 12,\n\tKA_SPCTAB \t\t\t= 20,\n\tKA_SETX \t\t\t\t= 25,\n\tKA_SETY \t\t\t\t= 26,\n\n\tKA_SPACE\t\t\t\t= 32,\t\t\t\t\t/*   */\n\tKA_EXCLAMATION,\t\t\t\t\t\t\t/* ! */\n\tKA_DQUOTE,\t\t\t\t\t\t\t\t\t/* \" */\n\tKA_POUND,\t\t\t\t\t\t\t\t\t/* # */\n\tKA_DOLLAR,\t\t\t\t\t\t\t\t\t/* $ */\n\tKA_PERCENT,\t\t\t\t\t\t\t\t\t/* % */\n\tKA_AMPER,\t\t\t\t\t\t\t\t\t/* & */\n\tKA_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKA_LPAREN,\t\t\t\t\t\t\t\t\t/* ( */\n\tKA_RPAREN,\t\t\t\t\t\t\t\t\t/* ) */\n\tKA_ASTERISK,\t\t\t\t\t\t\t\t/* * */\n\tKA_PLUS,\t\t\t\t\t\t\t\t\t\t/* + */\n\tKA_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKA_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKA_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKA_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKA_0, KA_1, KA_2, KA_3, KA_4, KA_5, KA_6, KA_7, KA_8, KA_9,\n\tKA_COLON,\t\t\t\t\t\t\t\t\t/* : */\n\tKA_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKA_LESS_THAN,\t\t\t\t\t\t\t\t/* < */\n\tKA_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\tKA_GREATER_THAN,\t\t\t\t\t\t\t/* > */\n\tKA_QUESTION,\t\t\t\t\t\t\t\t/* ? */\n\n\tKA_AT,\t\t\t\t\t\t\t\t\t\t/* @ */\n\tKA_A,\t\t\t\t\t\t\t\t\t\t\t/* A */\n\tKA_B,\t\t\t\t\t\t\t\t\t\t\t/* B */\n\tKA_C,\t\t\t\t\t\t\t\t\t\t\t/* C */\n\tKA_D,\t\t\t\t\t\t\t\t\t\t\t/* D */\n\tKA_E,\t\t\t\t\t\t\t\t\t\t\t/* E */\n\tKA_F,\t\t\t\t\t\t\t\t\t\t\t/* F */\n\tKA_G,\t\t\t\t\t\t\t\t\t\t\t/* G */\n\tKA_H,\t\t\t\t\t\t\t\t\t\t\t/* H */\n\tKA_I,\t\t\t\t\t\t\t\t\t\t\t/* I */\n\tKA_J,\t\t\t\t\t\t\t\t\t\t\t/* J */\n\tKA_K,\t\t\t\t\t\t\t\t\t\t\t/* K */\n\tKA_L,\t\t\t\t\t\t\t\t\t\t\t/* L */\n\tKA_M,\t\t\t\t\t\t\t\t\t\t\t/* M */\n\tKA_N,\t\t\t\t\t\t\t\t\t\t\t/* N */\n\tKA_O,\t\t\t\t\t\t\t\t\t\t\t/* O */\n\n\tKA_P,\t\t\t\t\t\t\t\t\t\t\t/* P */\n\tKA_Q,\t\t\t\t\t\t\t\t\t\t\t/* Q */\n\tKA_R,\t\t\t\t\t\t\t\t\t\t\t/* R */\n\tKA_S,\t\t\t\t\t\t\t\t\t\t\t/* S */\n\tKA_T,\t\t\t\t\t\t\t\t\t\t\t/* T */\n\tKA_U,\t\t\t\t\t\t\t\t\t\t\t/* U */\n\tKA_V,\t\t\t\t\t\t\t\t\t\t\t/* V */\n\tKA_W,\t\t\t\t\t\t\t\t\t\t\t/* W */\n\tKA_X,\t\t\t\t\t\t\t\t\t\t\t/* X */\n\tKA_Y,\t\t\t\t\t\t\t\t\t\t\t/* Y */\n\tKA_Z,\t\t\t\t\t\t\t\t\t\t\t/* Z */\n\tKA_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKA_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\tKA_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKA_CARROT,\t\t\t\t\t\t\t\t\t/* ^ */\n\tKA_UNDERLINE,\t\t\t\t\t\t\t\t/* _ */\n\n\tKA_GRAVE,\t\t\t\t\t\t\t\t\t/* ` */\n\tKA_a,\t\t\t\t\t\t\t\t\t\t\t/* a */\n\tKA_b,\t\t\t\t\t\t\t\t\t\t\t/* b */\n\tKA_c,\t\t\t\t\t\t\t\t\t\t\t/* c */\n\tKA_d,\t\t\t\t\t\t\t\t\t\t\t/* d */\n\tKA_e,\t\t\t\t\t\t\t\t\t\t\t/* e */\n\tKA_f,\t\t\t\t\t\t\t\t\t\t\t/* f */\n\tKA_g,\t\t\t\t\t\t\t\t\t\t\t/* g */\n\tKA_h,\t\t\t\t\t\t\t\t\t\t\t/* h */\n\tKA_i,\t\t\t\t\t\t\t\t\t\t\t/* i */\n\tKA_j,\t\t\t\t\t\t\t\t\t\t\t/* j */\n\tKA_k,\t\t\t\t\t\t\t\t\t\t\t/* k */\n\tKA_l,\t\t\t\t\t\t\t\t\t\t\t/* l */\n\tKA_m,\t\t\t\t\t\t\t\t\t\t\t/* m */\n\tKA_n,\t\t\t\t\t\t\t\t\t\t\t/* n */\n\tKA_o,\t\t\t\t\t\t\t\t\t\t\t/* o */\n\n\tKA_p,\t\t\t\t\t\t\t\t\t\t\t/* p */\n\tKA_q,\t\t\t\t\t\t\t\t\t\t\t/* q */\n\tKA_r,\t\t\t\t\t\t\t\t\t\t\t/* r */\n\tKA_s,\t\t\t\t\t\t\t\t\t\t\t/* s */\n\tKA_t,\t\t\t\t\t\t\t\t\t\t\t/* t */\n\tKA_u,\t\t\t\t\t\t\t\t\t\t\t/* u */\n\tKA_v,\t\t\t\t\t\t\t\t\t\t\t/* v */\n\tKA_w,\t\t\t\t\t\t\t\t\t\t\t/* w */\n\tKA_x,\t\t\t\t\t\t\t\t\t\t\t/* x */\n\tKA_y,\t\t\t\t\t\t\t\t\t\t\t/* y */\n\tKA_z,\t\t\t\t\t\t\t\t\t\t\t/* z */\n\tKA_LBRACE,\t\t\t\t\t\t\t\t\t/* { */\n\tKA_BAR,\t\t\t\t\t\t\t\t\t\t/* | */\n\tKA_RBRACE,\t\t\t\t\t\t\t\t\t/* ] */\n\tKA_TILDA,\t\t\t\t\t\t\t\t\t/* ~ */\n\n\tKA_ESC \t\t\t\t= VK_ESCAPE | WWKEY_VK_BIT,\n\tKA_EXTEND \t\t\t= VK_ESCAPE | WWKEY_VK_BIT,\n\tKA_RETURN \t\t\t= VK_RETURN | WWKEY_VK_BIT,\n\tKA_BACKSPACE \t\t= VK_BACK | WWKEY_VK_BIT,\n\tKA_TAB \t\t\t\t= VK_TAB  | WWKEY_VK_BIT,\n\tKA_DELETE\t\t\t= VK_DELETE | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* <DELETE> */\n\tKA_INSERT\t\t\t= VK_INSERT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* <INSERT> */\n\tKA_PGDN\t\t\t\t= VK_NEXT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <PAGE DOWN> */\n\tKA_DOWNRIGHT \t\t= VK_NEXT | WWKEY_VK_BIT,\n\tKA_DOWN\t\t\t\t= VK_DOWN | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <DOWN ARROW> */\n\tKA_END\t\t\t\t= VK_END | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <END> */\n\tKA_DOWNLEFT \t\t= VK_END | WWKEY_VK_BIT,\n\tKA_RIGHT\t\t\t\t= VK_RIGHT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* <RIGHT ARROW> */\n\tKA_KEYPAD5\t\t\t= VK_SELECT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* NUMERIC KEY PAD <5> */\n\tKA_LEFT\t\t\t\t= VK_LEFT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ARROW> */\n\tKA_PGUP\t\t\t\t= VK_PRIOR | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <PAGE UP> */\n\tKA_UPRIGHT \t\t\t= VK_PRIOR | WWKEY_VK_BIT,\n\tKA_UP\t\t\t\t\t= VK_UP | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <UP ARROW> */\n\tKA_HOME\t\t\t\t= VK_HOME | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <HOME> */\n\tKA_UPLEFT \t\t\t= VK_HOME | WWKEY_VK_BIT,\n\tKA_F12\t\t\t\t= VK_F12 | WWKEY_VK_BIT,\n\tKA_F11\t\t\t\t= VK_F11 | WWKEY_VK_BIT,\n\tKA_F10\t\t\t\t= VK_F10 | WWKEY_VK_BIT,\n\tKA_F9 \t\t\t\t= VK_F9 | WWKEY_VK_BIT,\n\tKA_F8\t\t\t\t\t= VK_F8 | WWKEY_VK_BIT,\n\tKA_F7\t\t\t\t\t= VK_F7 | WWKEY_VK_BIT,\n\tKA_F6\t\t\t\t\t= VK_F6 | WWKEY_VK_BIT,\n\tKA_F5\t\t\t\t\t= VK_F5 | WWKEY_VK_BIT,\n\tKA_F4\t\t\t\t\t= VK_F4 | WWKEY_VK_BIT,\n\tKA_F3\t\t\t\t\t= VK_F3 | WWKEY_VK_BIT,\n\tKA_F2\t\t\t\t\t= VK_F2 | WWKEY_VK_BIT,\n\tKA_F1\t\t\t\t\t= VK_F1 | WWKEY_VK_BIT,\n\tKA_LMOUSE \t \t\t= VK_LBUTTON | WWKEY_VK_BIT,\n\tKA_RMOUSE \t \t\t= VK_RBUTTON | WWKEY_VK_BIT,\n\n\tKA_SHIFT_BIT \t\t= WWKEY_SHIFT_BIT,\n\tKA_CTRL_BIT  \t\t= WWKEY_CTRL_BIT,\n\tKA_ALT_BIT   \t\t= WWKEY_ALT_BIT,\n\tKA_RLSE_BIT  \t\t= WWKEY_RLS_BIT,\n\n\t//\n\t// Define all the KN types as variations of the KA types.  This is\n\t// so the KN functions will work properly under windows 95.\n\t//\n\tKN_NONE\t\t\t\t= 0,\n\tKN_GRAVE \t\t\t= KA_GRAVE,\n\tKN_1 \t\t\t\t\t= KA_1,\n\tKN_2 \t\t\t\t\t= KA_2,\n\tKN_3 \t\t\t\t\t= KA_3,\n\tKN_4 \t\t\t\t\t= KA_4,\n\tKN_5 \t\t\t\t\t= KA_5,\n\tKN_6 \t\t\t\t\t= KA_6,\n\tKN_7 \t\t\t\t\t= KA_7,\n\tKN_8 \t\t\t\t\t= KA_8,\n\tKN_9 \t\t\t\t\t= KA_9,\n\tKN_0 \t\t\t\t\t= KA_0,\n\tKN_MINUS \t\t\t= KA_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKN_EQUAL \t\t\t= KA_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\n\tKN_BACKSPACE\t\t= KA_BACKSPACE,\n\n\tKN_TAB\t\t\t\t= KA_TAB,\t\t\t\t\t\t\t\t\t\t/* <TAB> */\n\tKN_Q \t\t\t\t\t= KA_q,\n\tKN_W \t\t\t\t\t= KA_w,\n\tKN_E \t\t\t\t\t= KA_e,\n\tKN_R \t\t\t\t\t= KA_r,\n\tKN_T \t\t\t\t\t= KA_t,\n\tKN_Y \t\t\t\t\t= KA_y,\n\tKN_U \t\t\t\t\t= KA_u,\n\tKN_I \t\t\t\t\t= KA_i,\n\tKN_O \t\t\t\t\t= KA_o,\n\tKN_P \t\t\t\t\t= KA_p,\n\tKN_LBRACKET\t\t\t= KA_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKN_RBRACKET\t\t\t= KA_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKN_BACKSLASH\t\t= KA_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\n\n\tKN_A \t\t\t\t\t= KA_a,\n\tKN_S \t\t\t\t\t= KA_s,\n\tKN_D \t\t\t\t\t= KA_d,\n\tKN_F \t\t\t\t\t= KA_f,\n\tKN_G \t\t\t\t\t= KA_g,\n\tKN_H \t\t\t\t\t= KA_h,\n\tKN_J \t\t\t\t\t= KA_j,\n\tKN_K \t\t\t\t\t= KA_k,\n\tKN_L \t\t\t\t\t= KA_l,\n\tKN_SEMICOLON \t\t= KA_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKN_SQUOTE \t\t\t= KA_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKN_BACKSLASH2 \t\t= KA_BACKSLASH,\n\tKN_RETURN \t\t\t= KA_RETURN,\n\tKN_Z \t\t\t\t\t= KA_z,\n\tKN_X \t\t\t\t\t= KA_x,\n\tKN_C \t\t\t\t\t= KA_c,\n\tKN_V \t\t\t\t\t= KA_v,\n\tKN_B \t\t\t\t\t= KA_b,\n\tKN_N \t\t\t\t\t= KA_n,\n\tKN_M \t\t\t\t\t= KA_m,\n\tKN_COMMA \t\t\t= KA_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKN_PERIOD \t\t\t= KA_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKN_SLASH \t\t\t= KA_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\tKN_SPACE \t\t\t= KA_SPACE,\n\tKN_LMOUSE\t\t\t= KA_LMOUSE,\n\tKN_RMOUSE\t\t\t= KA_RMOUSE,\n\n\tKN_HOME\t\t\t\t= KA_HOME,\t\t\t\t\t\t\t\t\t\t/* num key pad 7 */\n\tKN_UPLEFT\t\t\t= KA_UPLEFT,\n\tKN_LEFT\t\t\t\t= KA_LEFT,\t\t\t\t\t\t\t\t\t\t/* num key pad 4 */\n\tKN_END\t\t\t\t= KA_END,\t\t\t\t\t\t\t\t\t\t/* num key pad 1 */\n\tKN_DOWNLEFT\t\t\t= KA_DOWNLEFT,\n\n\tKN_KEYPAD_SLASH\t= KA_SLASH,\t\t\t\t\t\t\t\t\t\t\t\t/* num key pad / */\n\tKN_UP\t\t\t\t\t= KA_UP,\t\t\t\t\t\t\t\t\t\t\t/* num key pad 8 */\n\tKN_CENTER\t\t\t= KA_KEYPAD5,\t\t\t\t\t\t\t\t\t/* num key pad 5 */\n\tKN_DOWN\t\t\t\t= KA_DOWN,\t\t\t\t\t\t\t\t\t\t/* num key pad 2 */\n\tKN_INSERT\t\t\t= KA_INSERT,\t\t\t\t\t\t\t\t\t/* num key pad 0 */\n\tKN_KEYPAD_ASTERISK= KA_ASTERISK,\t\t\t\t\t\t\t\t\t/* num key pad * */\n\tKN_PGUP\t\t\t\t= KA_PGUP,\t\t\t\t\t\t\t\t\t\t/* num key pad 9 */\n\tKN_UPRIGHT\t\t\t= KA_UPRIGHT,\n\tKN_RIGHT\t\t\t\t= KA_RIGHT,\t\t\t\t\t\t\t\t\t/* num key pad 6 */\n\tKN_PGDN\t\t\t\t= KA_PGDN,\t\t\t\t\t\t\t\t\t\t/* num key pad 3 */\n\tKN_DOWNRIGHT\t\t= KA_DOWNRIGHT,\n\tKN_DELETE\t\t\t= KA_DELETE,\t\t\t\t\t\t\t\t\t/* num key pad . */\n\n\tKN_KEYPAD_MINUS\t= KA_MINUS,\t\t\t\t\t\t\t/* num key pad - */\n\tKN_KEYPAD_PLUS\t\t= KA_PLUS,\t\t\t\t\t\t\t/* num key pad + */\n\n\n\tKN_KEYPAD_RETURN\t= KA_RETURN,\t\t\t\t\t\t\t/* num key pad <ENTER> */\n\n\tKN_ESC\t\t\t\t= KA_ESC,\n\tKN_F1\t\t\t\t\t= KA_F1,\n\tKN_F2\t\t\t\t\t= KA_F2,\n\tKN_F3\t\t\t\t\t= KA_F3,\n\tKN_F4\t\t\t\t\t= KA_F4,\n\tKN_F5\t\t\t\t\t= KA_F5,\n\tKN_F6\t\t\t\t\t= KA_F6,\n\tKN_F7\t\t\t\t\t= KA_F7,\n\tKN_F8\t\t\t\t\t= KA_F8,\n\tKN_F9\t\t\t\t\t= KA_F9,\n\tKN_F10\t\t\t\t= KA_F10,\n\tKN_F11\t\t\t\t= KA_F11,\n\tKN_F12\t\t\t\t= KA_F12,\n\n\tKN_PRNTSCRN\t\t\t= VK_PRINT | WWKEY_VK_BIT,\n\tKN_CAPSLOCK\t\t\t= VK_CAPITAL | WWKEY_VK_BIT,\n\tKN_SCROLLLOCK\t\t= VK_SCROLL | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t/* <SCROLL LOCK> */\n\tKN_PAUSE\t\t\t\t= VK_PAUSE | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* <PAUSE> */\n\tKN_LSHIFT\t\t\t= VK_SHIFT | WWKEY_VK_BIT,\n\tKN_RSHIFT\t\t\t= VK_SHIFT | WWKEY_VK_BIT,\n\tKN_LCTRL\t\t\t\t= VK_CONTROL | WWKEY_VK_BIT,\n\tKN_RCTRL\t\t\t\t= VK_CONTROL | WWKEY_VK_BIT,\n\tKN_LALT\t\t\t\t= VK_MENU | WWKEY_VK_BIT,\n\tKN_RALT\t\t\t\t= VK_MENU | WWKEY_VK_BIT,\n\tKN_E_INSERT\t\t\t= VK_INSERT | WWKEY_VK_BIT,\n\tKN_E_DELETE \t\t= VK_DELETE | WWKEY_VK_BIT,\n\tKN_E_LEFT\t\t\t= VK_LEFT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <LEFT ARROW> */\n\tKN_E_HOME\t\t\t= VK_HOME | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <HOME> */\n\tKN_E_END\t\t\t\t= VK_END | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <END> */\n\tKN_E_UP\t\t\t\t= VK_UP | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* extended <UP ARROW> */\n\tKN_E_DOWN\t\t\t= VK_DOWN | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <DOWN ARROW> */\n\tKN_E_PGUP\t\t\t= VK_PRIOR | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <PAGE UP> */\n\tKN_E_PGDN   \t\t= VK_NEXT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <PAGE DOWN> */\n\tKN_E_RIGHT\t\t\t= VK_RIGHT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <RIGHT ARROW> */\n\tKN_NUMLOCK\t\t\t= VK_NUMLOCK | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* <NUM LOCK> */\n\n\tKN_SHIFT_BIT \t\t= WWKEY_SHIFT_BIT,\n\tKN_CTRL_BIT  \t\t= WWKEY_CTRL_BIT | WWKEY_VK_BIT,\n\tKN_ALT_BIT   \t\t= WWKEY_ALT_BIT | WWKEY_VK_BIT,\n\tKN_RLSE_BIT  \t\t= WWKEY_RLS_BIT,\n\tKN_BUTTON    \t\t= WWKEY_BTN_BIT,\n};\n\n\nextern WWKeyboardClass *_Kbd;\n\n\n/*\n** The following routines provide some compatability with the old westwood\n** library.\n*/\nint Check_Key(void);\nint Check_Key_Num(void);\nint Get_Key_Num(void);\nint Get_Key(void);\nint KN_To_KA(int key);\nvoid Clear_KeyBuffer(void);\nint Key_Down(int key);\nint KN_To_VK(int key);\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/KEYBOARD.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : KEYBOARD.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 12, 1994                            *\n;*                                                                         *\n;*                  Last Update : July 12, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Contains all the defines used by the keyboard interrupt for assembly    *\n;*   includes.                                                             *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nTRUE\t\tEQU\t1\t\t\t; numerical true\nFALSE\t\tEQU\t0\t\t\t; numerical false\nDEBUG\t\tEQU\t1\n\nMAX_X_PIXEL\t\tEQU\t319\nMAX_Y_PIXEL\t\tEQU\t199\n\n\nKN_RESERVED1\t\tEQU\t14\nKN_RESERVED2\t\tEQU\t45\nKN_RESERVED3\t\tEQU\t56\n\n\n; these two are reserved for AMIGA open and close.\nKN_LCOMM\t\tEQU\t59\nKN_RCOMM\t\tEQU\t63\n\nKN_LMOUSE\t\tEQU\t65\nKN_RMOUSE\t\tEQU\t66\nKN_JBUTTON1\t\tEQU\t67\nKN_JBUTTON2\t\tEQU\t68\nKN_J_UP\t\t\tEQU\t69\nKN_J_RIGHT\t\tEQU\t70\nKN_J_DOWN\t\tEQU\t71\nKN_J_LEFT\t\tEQU\t72\n\nKN_LEFT\t\t\tEQU\t92\nKN_UPLEFT\t\tEQU\t91\nKN_UP\t\t\tEQU\t96\nKN_UPRIGHT\t\tEQU\t101\nKN_RIGHT\t\tEQU\t102\nKN_DOWNRIGHT\t\tEQU\t103\nKN_DOWN\t\t\tEQU\t98\nKN_DOWNLEFT\t\tEQU\t93\nKN_CENTER\t\tEQU\t97\n\nKN_INSERT\t\tEQU\t99\nKN_DELETE\t\tEQU\t104\n\nKN_RETURN\t\tEQU\t43\nKN_SPACE\t\tEQU\t61\nKN_KEYPAD_RETURN\tEQU\t108\n\n\n; these two are reserved for AMIGA K left and right paren\nKN_KLPAREN\t\tEQU\t87\nKN_KRPAREN\t\tEQU\t88\n\n\nKN_NUMLOCK\t\tEQU\t90\n\nKN_SCROLLOCK\t\tEQU\t125\t\t; key ignored by the logging system\n\nKN_MOUSE_MOVE\tEQU\t45\t; Indicate a mouse move (for playback of logged data)\n\n; ----------------------------------------------------------------\n; flags used in Keyflags to customize keystroke interrupt.\n\nREPEATON\tEQU\t0001H\t; 1:all makes into buffer, 0:only 1st make\nTRACKEXT\tEQU\t0002H\t; 1:Home != keypad Home, 0:Home=keypad Home\nFILTERONLY\tEQU\t0004H\t; 1:Normal BIOS operation with filter\nCTRLSON\t\tEQU\t0008H\t; 1:pass scroll lock sequence into BIOS\nCTRLALTTURBO\tEQU\t0010H\t; 1:Allow turbo up and down in application\nCTRLCON\t\tEQU\t0020H\t; 1:pass stop code to BIOS\nSCROLLLOCKON\tEQU\t0040H\t; 1:pass scroll lock key into BIOS\nPAUSEON\t\tEQU\t0080H\t; 1:pass the pause key and seq to BIOS\nBREAKON\t\tEQU\t0100H\t; 1:pass the ctrl break seq to BIOS\nNONUMLOCK\tEQU\t0200H\t; 1:do NOT remap keypad to numbers\nTASKSWITCHABLE\tEQU\t0400H\t; 1:allows task switching keys thru ALT-TAB,\n\t\t\t\t;   ALT-ESC,CTRL-ESC\nPASSBREAKS\tEQU\t0800H\t; 1:Pass all break codes to keyboard buffer.\nKEYMOUSE\tEQU\t1000H\t; 1:Numeric keypad moves mouse\nSIMLBUTTON\tEQU\t2000H\t; 1:have space and enter keys simulate Left\nDEBUGINT\tEQU\t4000H\t;   mouse button when KEYMOUSE is set\n\n\nSHIFTPRESS\tEQU\t001H\t; bit 0 for shift key pressed\nCTRLPRESS\tEQU\t002H\t; bit 1 for ctrl key pressed\nALTPRESS\tEQU\t004H\t; bit 2 for alt key pressed\nKEYRELEASE\tEQU\t008H\t; bit 3 for key released\nNOTKEYRELEASE\tEQU\t0F7H\t; not of key released\n\nCAPSLOCK\tEQU\t00001H\t; bit 0 for caps locked\nNUMLOCK\tEQU\t00002H\t; bit 1 for num locked\n\n\n\nCLEARISR\tEQU\t020H\t; value to clear In Service Register\nDOS\t\tEQU \t021H\nINTCHIP0\tEQU\t020H\t; 8259 interrupt chip controller 0\nKEYCTRL\t\tEQU\t061H\t; control bits for KB sense data\nKEYDATA\t\tEQU\t060H\t; keyboard scan code port\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/KEYSTRUC.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : KEYSTRUC.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 13, 1994                            *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nSTRUC\tKeyboardType\n\tSoundOn\t\t\tDW\t?\t; toggled by alt S\n\tMusicOn\t\t\tDW\t?\t; toggled by alt M\n\tKeyFlags\t\t\tDD\t?\t; all but repeat for now\n\tBreak\t\t\t\tDW\t?\n\tKeyMouseMove\tDB\t6  DUP(?)\n\tScreenEdge\t\tDW\t18 DUP (?)\n\tBits\t\t\t\tDB\t8  DUP (?)\n\tCondPassKey\t\tDW\t17 DUP (?) \n\tCondPassCond\tDW\t17 DUP (?)\n\tEscRoutine\t\tDD\t?\n\tExtCodes\t\t\tDB\t16 DUP (?)\n\tExtNums\t\t\tDB\t16 DUP (?)\n\tExtRemap\t\t\tDB\t16 DUP (?)\n\tExtRemapEnd\t\tDB\t?\n\tExtKeyboard\t\tDB\t?\n\tKeyBuffer\t\tDW\t128 DUP(?) ; set to empty\n\tKeyBufferHead\tDD\t?\t; set to first entry\n\tKeyBufferTail\tDD\t?\t; set to head for empty buffer\n\tKeyLock\t\t\tDW\t?\t; num and caps lock bits\n\tKeyNums\t\t\tDB\t89 DUP (?)\n\tKeysCapsLock\tDB\t16 DUP (?)\n\tKeysNumLock\t\tDB\t16 DUP (?)\n\tKeysUpDown\t\tDB\t16 DUP (?)\n\tKeyStream\t\tDB\t16 DUP (?)\n\tPassCount\t\tDW\t?\n\tKeyStreamIndex\tDW\t?\n\tLastKeyE0\t\tDB\t?\n\tLastKeyE1\t\tDB\t?\n\tPassAlways\t\tDB\t10 DUP (?)\n\tPassAlwaysEnd\tDB\t?\t\t; invalid code to END PassAlways\n\tCtrlFlags\t\tDB\t?\n\tBuffer\t\t\tDW\t?\n\tTime\t\t\t\tDW\t?\n\tXYAdjust\t\t\tDB\t26 DUP (?)\n\tEdgeConv\t\t\tDW\t16 DUP (?)\n\tMouseUpdate\t\tDW\t?\n\tMouseX\t\t\tDD\t?\n\tLocalMouseX\t\tDW\t?\n\tMouseY\t\t\tDD\t?\n\tLocalMouseY\t\tDW\t?\n\tIsExtKey\t\t\tDB\t?\n\tExtIndex\t\t\tDW\t?\n\n\tKeyOldRMI\t\t\tDD\t?\t; The origianl RM interrupt seg:off.\n\tKeyOldPMIOffset\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tKeyOldPMISelector\tDD\t?\t; The original PM interrupt segment.\n\n\tKeyCodeOffset\t\t\tDW\t?\t; Offset of the code in the RM stuff.\n\tCallKeyRMIntOffset\tDW\t?\t; Offset of function to call DOS timer interrupt.\n\tCallKeyRMIntAddr\t\tDD\t?\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedKeyInt\t\t\tDD\t?\t; did Protected mode pass this through?\n\n\tBrkOldRMI\t\t\t\tDD\t?\t; The origianl RM interrupt seg:off.\n\tBrkOldPMIOffset\t\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tBrkOldPMISelector\t\tDD\t?\t; The original PM interrupt segment.\n\n\tBrkCodeOffset\t\t\tDW\t?\t; Offset of the code in the RM stuff.\n\tCallBrkRMIntOffset\tDW\t?\t; Offset of function to call DOS timer interrupt.\n\tCallBrkRMIntAddr\t\tDD\t?\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedBrkInt\t\t\tDD\t?\t; did Protected mode pass this through?\n\tKeyIntDisabled\t\t\tDD\t?\n\n\tDbgOldPMIOffset\t\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tDbgOldPMISelector\t\tDD\t?\t; The original PM interrupt segment.\n\n\t;---------------------------------------------------------------------------\n\t; Begin definition of Mouse Specific Variables for real mode\n\t;---------------------------------------------------------------------------\n\tButton\t\t\t\tDB\t?\t; current value of the mouse button\n\tMDisabled\t\t\tDB\t?\t; Is the mouse driver disabled\n\tMInput\t\t\t\tDB\t?\t; Defaults to mouse input allowed.\n\tAdjust\t\t\t\tDW\t?\t; flag to adjust coordinates if necessary\n\tMouseStepX\t\t\tDW\t?\t; step values if the mouse moves at\n\tMouseStepY\t\t\tDW\t?\t;   more than one pixel at a time\n\tMouseOffsetX\t\tDW\t?\t; Fractional step values used if a mouse\n\tMouseOffsetY\t\tDW\t?\t;   moves at less than one pixel at a time\n\tMState\t\t\t\tDD\t?\t; Tracks if mouse is hidden (TRUE) or not (FALSE)\n\tMouseXOld     \t\tDW\t?\t; Holds last MouseX and MouseY to determine if \n\tMouseYOld     \t\tDW\t?\t;   mouse needs to be redrawn\n\tMCState\t\t\t\tDW\t?\t; Tracks if mouse conditional hidden (TRUE) or not\n\tMouseCXLeft\t\t\tDD\t?\t; Conditional hide mouse left x position\n\tMouseCYUpper\t\tDD\t?\t; Conditional hide mouse top y position\n\tMouseCXRight\t\tDD\t?\t; Conditional hide mouse right x position\n\tMouseCYLower\t\tDD\t?\t; Conditional hide mouse lower y position\n\tMouseCursor   \t\tDD\t?\t; Pointer to the mouse cursor to draw\n\tMouseCursorSize\tDW\t?\t; Size of mouse cursor draw area\n\tMouseBuffer   \t\tDD\t?\t; Pointer to buffer mouse is saved in\n\tMouseXHot     \t\tDD\t?\t; Offset to mouse's x hot spot\n\tMouseYHot     \t\tDD\t?\t; Offset to mouse's y hot spot\n\tMouseBuffX\t\t\tDD\t?\t; X position background was saved at\n\tMouseBuffY\t\t\tDD\t?\t; Y position background was saved at\n\tMouseBuffW\t\t\tDD\t?\t; Width of the region saved for mouse\n\tMouseBuffH\t\t\tDD\t?\t; Height of the region saved for mouse\n\tMouseWidth\t\t\tDD\t?\t; Mouse cursor theoretical width\n\tMouseHeight\t\t\tDD\t?\t; Mouse cursor theoretical height\n\tMouseCodeOffset\tDW\t?\t; Offset to the real mode code offset\n\tMouseRight\t\t\tDD\t?\t; Right hand side of the screen\n\tMouseBottom\t\t\tDD\t?\t; Bottom of the screen\n\n\n\tShadowPtr\t\t\tdw\t?\n\tDrawMousePtr \t\tdw\t?\n\n\tVGAMouseDraw\t\tdw\t?\n\tVGAMouseShadow\t\tdw\t?\n\n\tVESAMouseDraw\t\tdw\t?\n\tVESAMouseShadow\tdw\t?\n\n\tVesaPtr\t\t\t\tdd ?\t\n\tVesaBankTable\t   DD\t8 dup (?)\n\tAdjust_XPos\t\t\tdd ?\n\tAdjust_YPos\t\t\tdd ?\n\n\nENDS\n\n; InitFlags that are set to have a fully functional interrupt.\nIF_ALLOC_RM\t\t\tequ\t1\t\t; Allocation of RM was successful.\nIF_SET_VECTORS\t\tequ\t2\t\t; Vectors have been set.\nIF_LOCKED_PM_CODE\tequ\t4\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t8\t\t; Locked PM code for DPMI.\nIF_RATE_CHANGE\t\tequ\t10\t\t; Timer rate was changed.\nIF_FUNCTIONAL\t\tequ\t20\t\t; Timer is in and functional.\nIF_LOCKED_RM_CODE\tequ\t40\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/MCGAPRIM.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : MCGAPRIM.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 16, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n; Externs from REGIONSZ.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Size_Of_Region\t:NEAR\n\n; Externs from GETPIX.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Get_Pixel          \t:NEAR\n\n; Externs from VGETPIX.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Get_Pixel          \t:NEAR\n\n; Externs from PUTPIX.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Put_Pixel \t\t:NEAR\n\n; Externs from VPUTTPIX.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Put_Pixel \t\t:NEAR\n\n; Externs from CLEAR.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Clear\t          \t:NEAR\n\n; Externs from VCLEAR.ASM module of the MCGA/SVGAPRIM library\nGLOBAL Vesa_Clear\t\t\t:NEAR\n; Externs from BITBLIT.ASM module of the MCGAPRIM library\nGLOBAL Linear_Blit_To_Linear\t\t:NEAR\n\n; Externs from VBITBLIT.ASM module of the MCGA/SVGAPRIM library\nGLOBAL Linear_Blit_To_Vesa\t\t:NEAR\nGLOBAL Vesa_Blit_To_Linear\t\t:NEAR\nGLOBAL Vesa_Blit_To_Vesa\t\t:NEAR\n\n; Externs from TOBUFF.ASM module of the MCGAPRIM library\nGLOBAL MCGA_To_Buffer\t\t:NEAR\n\n; Externs from VTOBUFF.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_To_Buffer\t\t:NEAR\n\n; Externs from TOPAGE.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Buffer_To_Page\t\t:NEAR\n\n; Externs from VTOPAGE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Buffer_To_Page\t\t:NEAR\n\n; Externs from SCALE.ASM module of the MCGAPRIM library\nGLOBAL Linear_Scale_To_Linear \t:NEAR\n\n; Externs from VSCALE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Linear_Scale_To_Vesa \t\t:NEAR\nGLOBAL Vesa_Scale_To_Linear\t\t:NEAR\nGLOBAL Vesa_Scale_To_Vesa \t\t:NEAR\n\n; Externs from TXTPRNT.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Print\t\t\t:NEAR\n\n; Externs from VTXTPRNT.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Print\t\t\t:NEAR\n\n;*-------------------------------------------------------------------------*\n;* Define MCGA only assembly GLOBALS\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n\n; Externs from DRAWLINE.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Draw_Line \t\t:NEAR\n\n; Externs from FILLQUAD.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Fill_Quad \t\t:NEAR\n\n; Externs from FILLRECT.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Fill_Rect \t\t:NEAR\n\n; Externs from REMAP.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Remap      \t\t:NEAR\n\n; Externs from STAMP.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Draw_Stamp \t\t:NEAR\n\nGLOBAL get_clip\t \t   : NEAR\n\nstruc  RECTANGLE\n\t\t  x0\tdd\t?\n\t\t  y0 dd\t?\n\t\t  x1\tdd\t?\n\t\t  y1 dd ?\nends \t RECTANGLE\n\n\n\n\u001a\n\u001a"
  },
  {
    "path": "WIN32LIB/INCLUDE/MEMFLAG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory System                            *\n *                                                                         *\n *                    File Name : MEMFLAG.H                                *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : April 4, 1994                            *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef MEMFLAG_H\n#define MEMFLAG_H\n// Memory Flags\n/*\n**\tMemory allocation flags.  These are the flags that are passed into Alloc\n**\tin order to control the type of memory allocated.\n*/\ntypedef enum {\n\tMEM_NORMAL = 0x0000,\t\t// Default memory (normal).\n\tMEM_NEW\t  = 0x0001,\t\t// Called by the operator new and was overloaded.\n\tMEM_CLEAR  = 0x0002,\t\t// Clear memory before returning.\n\tMEM_REAL   = 0x0004,\t\t// Clear memory before returning.\n\tMEM_TEMP   = 0x0008,\t\t// Clear memory before returning.\n\tMEM_LOCK   = 0x0010,\t\t// Lock the memory that we allocated\n} MemoryFlagType;\n\n\n/*\n** Prototypes for VMPAGEIN.ASM\n*/\nextern \"C\"{\n\tvoid __cdecl Force_VM_Page_In (void *buffer, int length);\n}\n\n/*=========================================================================*/\n/* The following prototypes are for the file: ALLOC.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid * operator new(size_t size, MemoryFlagType flag);\nvoid * operator new[] (size_t size, MemoryFlagType flag);\nvoid\t*Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags);\nvoid\tFree(void const *pointer);\nvoid\tDPMI_Lock(VOID const *ptr, long const size);\nvoid\tDPMI_Unlock(void const *ptr, long const size);\nvoid\t*Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes);\nlong\tRam_Free(MemoryFlagType flag);\nlong\tHeap_Size(MemoryFlagType flag);\nlong\tTotal_Ram_Free(MemoryFlagType flag);\n\n#pragma option -Jgd\n\ninline void * operator new(size_t size, MemoryFlagType flag)\n{\n\treturn(Alloc(size, flag));\n}\ninline void * operator new[] (size_t size, MemoryFlagType flag)\n{\n\treturn(Alloc(size, flag));\n}\n\n#pragma option -Jgd\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MEM_COPY.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern \"C\" {\n\tvoid __cdecl Mem_Copy(void const *source, void *dest, unsigned long bytes_to_copy);\n}\n\n\ninline void *Add_Long_To_Pointer(void const *ptr, long size)\n{\n \treturn ((void *) ( (char const *) ptr + size));\n}\n\nextern void (*Memory_Error)(void);\nextern void (*Memory_Error_Exit)(char *string);\n\nextern unsigned long MinRam;\t\t// Record of least memory at worst case.\nextern unsigned long MaxRam;\t\t// Record of total allocated at worst case.\n\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/MISC.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : 32 bit library                           *\n *                                                                         *\n *                    File Name : MISC.H                                   *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MISC_H\n#define MISC_H\n\n#define WIN32_LEAN_AND_MEAN\t// eliminates unecessary definitions in windows.h\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#include <windows.h>\n#include <windowsx.h>\n#include <ddraw.h>\n\nextern\tLPDIRECTDRAWSURFACE\tPaletteSurface;\n\n/*========================= C++ Routines ==================================*/\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DDRAW.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid \t\tProcess_DD_Result(HRESULT result, int display_ok_msg);\nBOOL \t\tSet_Video_Mode(HWND hwnd, int w, int h, int bits_per_pixel);\nvoid \t\tReset_Video_Mode(void);\nunsigned \tGet_Free_Video_Memory(void);\nvoid \t\tWait_Blit(void);\nunsigned \tGet_Video_Hardware_Capabilities(void);\n\nextern \"C\" void Wait_Vert_Blank(void);\nextern \"C\" void Set_DD_Palette (void *palette);\n\n/*\n** Pointer to function to call if we detect a focus loss\n*/\nextern\tvoid (*Misc_Focus_Loss_Function)(void);\n/*\n** Pointer to function to call if we detect a surface restore\n*/\nextern\tvoid (*Misc_Focus_Restore_Function)(void);\n\n\n/*\n *  Flags returned by Get_Video_Hardware_Capabilities\n */\n/* Hardware blits supported? */\n#define\tVIDEO_BLITTER\t\t\t\t\t1\n\n/* Hardware blits asyncronous? */\n#define\tVIDEO_BLITTER_ASYNC  \t\t2\n\n/* Can palette changes be synced to vertical refresh? */\n#define\tVIDEO_SYNC_PALETTE\t\t\t4\n\n/* Is the video cards memory bank switched? */\n#define\tVIDEO_BANK_SWITCHED\t\t\t8\n\n/* Can the blitter do filled rectangles? */\n#define\tVIDEO_COLOR_FILL\t\t\t\t16\n\n/* Is there no hardware assistance avaailable at all? */\n#define\tVIDEO_NO_HARDWARE_ASSIST\t32\n\n\n\n/*\n * Definition of surface monitor class\n *\n * This class keeps track of all the graphic buffers we generate in video memory so they\n *  can be restored after a focus switch.\n*/\n\n#define\tMAX_SURFACES\t20\n\nclass SurfaceMonitorClass {\n\n\tpublic:\n\n\t\tSurfaceMonitorClass();\n\n\t\tvoid\tAdd_DD_Surface (LPDIRECTDRAWSURFACE);\n\t\tvoid\tRemove_DD_Surface (LPDIRECTDRAWSURFACE);\n\t\tBOOL\tGot_Surface_Already (LPDIRECTDRAWSURFACE);\n\t\tvoid\tRestore_Surfaces (void);\n\t\tvoid\tSet_Surface_Focus ( BOOL in_focus );\n\t\tvoid\tRelease(void);\n\n\t\tBOOL\tSurfacesRestored;\n\n\tprivate:\n\n\t\tLPDIRECTDRAWSURFACE\tSurface[MAX_SURFACES];\n\t\tBOOL\t\t\t\t\t\tInFocus;\n\n};\n\nextern\tSurfaceMonitorClass\tAllSurfaces;\t\t\t\t//List of all direct draw surfaces\n\n\n/*=========================================================================*/\n/* The following variables are declared in: DDRAW.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nextern\tLPDIRECTDRAW\tDirectDrawObject;\nextern\tLPDIRECTDRAW2\tDirectDraw2Interface;\nextern\tHWND\t\t\t\tMainWindow;\nextern BOOL \t\t\t\tSystemToVideoBlits;\nextern BOOL\t\t\t\tVideoToSystemBlits;\nextern BOOL\t\t\t\tSystemToSystemBlits;\nextern BOOL\t\t\t\tOverlappedVideoBlits;\t// Can video driver blit overlapped regions?\n\n/*=========================================================================*/\n/* The following prototypes are for the file: EXIT.CPP\t\t\t\t\t\t\t*/\n/* Prog_End Must be supplied by the user program in startup.cpp\t\t\t\t*/\n/*=========================================================================*/\nVOID __cdecl Prog_End(VOID);\nVOID __cdecl Exit(INT errorval, const BYTE *message, ...);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DELAY.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Delay(int duration);\nvoid Vsync(void);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FINDARGV.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nBYTE  __cdecl Find_Argv(BYTE const *str);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LIB.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nchar *Find_Argv(char const *str);\nvoid Mono_Mem_Dump(void const *databuf, int bytes, int y);\nvoid Convert_RGB_To_HSV(unsigned int r, unsigned int g, unsigned int b, unsigned int *h, unsigned int *s, unsigned int *v);\nvoid Convert_HSV_To_RGB(unsigned int h, unsigned int s, unsigned int v, unsigned int *r, unsigned int *g, unsigned int *b);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: VERSION.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nBYTE  __cdecl Version(VOID);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: IRANDOM.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nint IRandom(int minval, int maxval);\n\n\n/*========================= Assembly Routines ==============================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*=========================================================================*/\n/* The following prototypes are for the file: RANDOM.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nunsigned char __cdecl Random(void);\nint __cdecl Get_Random_Mask(int maxval);\n\n/*=========================================================================*/\n/* The following prototype is for the file: SHAKESCR.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid __cdecl Shake_Screen(int shakes);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: REVERSE.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nlong __cdecl Reverse_Long(long number);\nshort __cdecl Reverse_Short(short number);\nlong __cdecl Swap_Long(long number);\n#if (0)\n/*=========================================================================*/\n/* The following prototype is for the file: FACING8.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Desired_Facing8(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FACING16.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Desired_Facing16(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FACINGFF.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Desired_Facing256(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FADING.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#endif\n\nvoid * __cdecl Build_Fading_Table(void const *palette, void const *dest, long int color, long int frac);\n/*=========================================================================*/\n/* The following prototype is for the file: CRC.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nlong __cdecl Calculate_CRC(void *buffer, long length);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DETPROC.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern WORD __cdecl  Processor(void);\nextern WORD __cdecl Operating_System(void);\nextern unsigned long random ( unsigned long mod )  ;\n//extern void  randomize ( void ) ;\n\nextern int __cdecl Clip_Rect ( int * x , int * y , int * dw , int * dh ,\n\t       \t   \t\t\t int width , int height ) ;\nextern int __cdecl Confine_Rect ( int * x , int * y , int dw , int dh ,\n\t      \t      \t\t\t int width , int height ) ;\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: OPSYS.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern WORD OperationgSystem;\n\n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n\n#endif // MISC_H\n\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/MODEMREG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#ifndef WIN32\n#define WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#endif\t//WIN32\n#include <windows.h>\n\n\n\nclass ModemRegistryEntryClass {\n\n\tpublic:\n\n\t\tModemRegistryEntryClass (int modem_number);\n\t\t~ModemRegistryEntryClass (void);\n\n\n\t\tchar *Get_Modem_Name (void) { return (ModemName); }\n\n\t\tchar *Get_Modem_Device_Name (void) { return (ModemDeviceName); }\n\n\t\tchar *Get_Modem_Error_Correction_Enable (void) { return (ErrorCorrectionEnable); }\n\n\t\tchar *Get_Modem_Error_Correction_Disable (void) { return (ErrorCorrectionDisable); }\n\n\t\tchar *Get_Modem_Compression_Enable (void) { return (CompressionEnable); }\n\n\t\tchar *Get_Modem_Compression_Disable (void) { return (CompressionDisable); }\n\n\t\tchar *Get_Modem_Hardware_Flow_Control (void) { return (HardwareFlowControl); }\n\n\t\tchar *Get_Modem_No_Flow_Control (void) { return (HardwareFlowControl); }\n\n\tprivate:\n\n\t\tchar *ModemName;\n\t\tchar *ModemDeviceName;\n\t\tchar *ErrorCorrectionEnable;\n\t\tchar *ErrorCorrectionDisable;\n\t\tchar *CompressionEnable;\n\t\tchar *CompressionDisable;\n\t\tchar *HardwareFlowControl;\n\t\tchar *NoFlowControl;\n\n};\n\n\n\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/MONO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\monoc.h_v   2.16   06 Sep 1995 16:29:02   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               *** \n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MONO.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 2, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 2, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MONOC_H\n#define MONOC_H\n\n\nclass MonoClass {\n\t\t/*\n\t\t**\tThis is a private structure that is used to control which characters\n\t\t**\tare used when a box is drawn. Line drawing on the monochrome screen is\n\t\t**\treally made up of characters. This specifies which characters to use.\n\t\t*/\n\t\ttypedef struct {\n\t\t\tchar\tUpperLeft;\n\t\t\tchar\tTopEdge;\n\t\t\tchar\tUpperRight;\n\t\t\tchar\tRightEdge;\n\t\t\tchar\tBottomRight;\n\t\t\tchar\tBottomEdge;\n\t\t\tchar\tBottomLeft;\n\t\t\tchar\tLeftEdge;\n\t\t} BoxDataType;\n\n\t\t/*\n\t\t**\tEach cell is constructed of the actual character that is displayed and the\n\t\t**\tattribute to use. This character pair is located at every position on the\n\t\t**\tdisplay (80 x 25). Since this cell pair can be represented by a \"short\"\n\t\t**\tinteger, certain speed optimizations are taken in the monochrome drawing\n\t\t**\tcode.\n\t\t*/\n\t\ttypedef struct {\n\t\t\tchar Character;\t\t\t// Character to display.\n\t\t\tchar Attribute;\t\t\t// Attribute.\n\t\t} CellType;\n\n\t\t/*\n\t\t**\tThese private constants are used in the various monochrome operations.\n\t\t*/\n\t\tenum MonoClassPortEnums {\n\t\t\tCONTROL_PORT=0x03B4,\t\t\t// CRTC control register.\n\t\t\tDATA_PORT=0x03B5,\t\t\t\t// CRTC data register.\n\t\t\tCOLUMNS=80,\t\t\t\t\t\t// Number of columns.\n\t\t\tLINES=25,\t\t\t\t\t\t// Number of lines.\n\t\t\tSIZE_OF_PAGE=LINES*COLUMNS*sizeof(CellType),\t// Entire page size.\n\t\t\tDEFAULT_ATTRIBUTE=0x02\t\t// Normal white on black color attribute.\n\t\t};\n\n\tpublic:\n\t\tenum MonoClassPageEnums {\n\t\t\tMAX_MONO_PAGES=16,\t// Maximum RAM pages on mono card.\n\t\t\tSEGMENT=0xB000  \t\t// Monochrome screen segment.\n\t\t};\n\n\t\t/*\n\t\t**\tThese are the various box styles that may be used.\n\t\t*/\n\t\ttypedef enum BoxStyleType {\n\t\t\tSINGLE,\t\t\t\t// Single thickness.\n\t\t\tDOUBLE_HORZ,\t\t// Double thick on the horizontal axis.\n\t\t\tDOUBLE_VERT,\t\t// Double thick on the vertical axis.\n\t\t\tDOUBLE,\t\t\t\t// Double thickness.\n\n\t\t\tCOUNT\n\t\t} BoxStyleType;\n\n\t\tMonoClass(void);\n\t\t~MonoClass(void);\n\n\t\tstatic void Enable(void) {Enabled = 1;};\n\t\tstatic void Disable(void) {Enabled = 0;};\n\t\tstatic int Is_Enabled(void) {return Enabled;};\n\t\tstatic MonoClass * Get_Current(void) {return PageUsage[0];};\n\n\t\tvoid Draw_Box(int x, int y, int w, int h, char attrib=DEFAULT_ATTRIBUTE, BoxStyleType thick=SINGLE);\n\t\tvoid Set_Default_Attribute(char attrib) {Attrib = attrib;};\n\t\tvoid Clear(void);\n\t\tvoid Set_Cursor(int x, int y);\n\t\tvoid Print(char const *text);\n\t\tvoid Print(int text);\n\t\tvoid Printf(char const *text, ...);\n\t\tvoid Printf(int text, ...);\n\t\tvoid Text_Print(char const *text, int x, int y, char attrib=DEFAULT_ATTRIBUTE);\n\t\tvoid Text_Print(int text, int x, int y, char attrib=DEFAULT_ATTRIBUTE);\n\t\tvoid View(void);\n\t\tint Get_X(void) const {return X;};\n\t\tint Get_Y(void) const {return Y;};\n\n\t\t/*\n\t\t**\tHandles deep copies for the mono class objects. This performs what is essentially\n\t\t**\ta screen copy.\n\t\t*/\n\t\tMonoClass & operator = (MonoClass const & );\n\n\t\t/*\n\t\t**\tThis merely makes a duplicate of the mono object into a newly created mono\n\t\t**\tobject.\n\t\t*/\n\t\tMonoClass (MonoClass const &);\n\n\tprivate:\n\t\tchar\tX;\t\t\t\t\t// Cursor X position.\n\t\tchar\tY;\t\t\t\t\t// Cursor Y position.\n\t\tchar\tAttrib;\t\t\t// Normal attribute to use if none specified.\n\t\tchar\tPage;\t\t\t\t// The current page to write to.\n\n\t\t/*\n\t\t**\tHelper functions to help with display operations.\n\t\t*/\n\t\tint Offset(int x=0, int y=0) const {return (SIZE_OF_PAGE*Page) + sizeof(CellType)*(x + (y*COLUMNS));};\n\t\tvoid Scroll(int lines);\n\t\tvoid Store_Cell(CellType &cell, int x, int y) {\n\t\t\t*(CellType *)((long)MonoSegment + Offset(x, y)) = cell;\n\t\t};\n\n\t\t/*\n\t\t**\tThis is the segment/selector of the monochrome screen.\n\t\t*/\n\t\tstatic void * MonoSegment;\n\n\t\t/*\n\t\t** This the the arrays of characters used for drawing boxes.\n\t\t*/\n\t\tstatic BoxDataType const CharData[4];\n\n\t\t/*\n\t\t**\tThis array contains pointers to the monochrome objects that are assigned\n\t\t**\tto each of the monochrome pages. As the monochrome pages are made visible,\n\t\t**\tthey can be shuffled around between the actual locations. The first entry\n\t\t**\tin this table is the one that is visible.\n\t\t*/\n\t\tstatic MonoClass * PageUsage[MAX_MONO_PAGES];\n\n\t\t/*\n\t\t**\tIf this is true, then monochrome output is allowed. It defaults to false\n\t\t**\tso that monochrome output must be explicitly enabled.\n\t\t*/\n\t\tstatic int Enabled;\n};\n\nvoid Mono_Set_Cursor(int x, int y);\nint Mono_Printf(char const *string, ...);\nvoid Mono_Clear_Screen(void);\nvoid Mono_Text_Print(void const *text, int x, int y, int attrib);\nvoid Mono_Draw_Rect(int x, int y, int w, int h, int attrib, int thick);\nvoid Mono_Print(void const *text);\nint Mono_X(void);\nint Mono_Y(void);\n\n#endif\n\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/MOUSE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood 32 Bit Library                                      *\n *                                                                                             *\n *                    File Name : MOUSE.H                                                      *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 12/12/95                                                     *\n *                                                                                             *\n *                  Last Update : December 12, 1995 [PWG]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WW_MOUSE_H\n#define WW_MOUSE_H\n\n#include <gbuffer.h>\n\nclass WWMouseClass {\n\tpublic:\n\t\tWWMouseClass(GraphicViewPortClass *scr, int mouse_max_width, int mouse_max_height);\n\t\t~WWMouseClass();\n\t\tvoid *Set_Cursor(int xhotspot, int yhotspot, void *cursor);\n\t\tvoid Process_Mouse(void);\n\t\tvoid Hide_Mouse(void);\n\t\tvoid Show_Mouse(void);\n\t\tvoid Conditional_Hide_Mouse(int x1, int y1, int x2, int y2);\n\t\tvoid Conditional_Show_Mouse(void);\n\t\tint Get_Mouse_State(void);\n\t\tint Get_Mouse_X(void);\n\t\tint Get_Mouse_Y(void);\n\t\tvoid Get_Mouse_XY(int &x, int &y);\n\t\t//\n\t\t// The following two routines can be used to render the mouse onto a graphicbuffer\n\t\t// other than the hidpage.\n\t\t//\n\t\tvoid Draw_Mouse(GraphicViewPortClass *scr);\n\t\tvoid Erase_Mouse(GraphicViewPortClass *scr, int forced = FALSE);\n\n\t\tvoid Block_Mouse(GraphicBufferClass *buffer);\n\t\tvoid Unblock_Mouse(GraphicBufferClass *buffer);\n\t\tvoid Set_Cursor_Clip(void);\n\t\tvoid Clear_Cursor_Clip(void);\n\n\tprivate:\n\t\tenum \t{\n\t\t\tCONDHIDE\t\t= 1,\n\t\t\tCONDHIDDEN \t= 2,\n\t\t};\n\t\tvoid Low_Hide_Mouse(void);\n\t\tvoid Low_Show_Mouse(int x, int y);\n\n\t\tchar\t\t\t\t\t\t*MouseCursor;\t// pointer to the mouse cursor in memory\n\t\tint\t\t\t\t\t\tMouseXHot;\t\t// X hot spot of the current mouse cursor\n\t\tint\t\t\t\t\t\tMouseYHot;\t\t// Y hot spot of the current mouse cursor\n\t\tint\t\t\t\t\t\tCursorWidth;\t// width of the mouse cursor in pixels\n\t\tint\t\t\t\t\t\tCursorHeight;\t// height of the mouse cursor in pixels\n\n\t\tchar\t\t\t\t\t\t*MouseBuffer;\t// pointer to background buffer in memory\n\t\tint\t\t\t\t\t\tMouseBuffX;\t\t// pixel x mouse buffer was preserved at\n\t\tint\t\t\t\t\t\tMouseBuffY;\t\t// pixel y mouse buffer was preserved at\n\t\tint\t\t\t\t\t\tMaxWidth;\t\t// maximum width of mouse background buffer\n\t\tint\t\t\t\t\t\tMaxHeight;\t\t// maximum height of mouse background buffer\n\n\t\tint\t\t\t\t\t\tMouseCXLeft;\t// left x pos if conditional hide mouse in effect\n\t\tint\t\t\t\t\t\tMouseCYUpper;\t// upper y pos if conditional hide mouse in effect\n\t\tint\t\t\t\t\t\tMouseCXRight;\t// right x pos if conditional hide mouse in effect\n\t\tint\t\t\t\t\t\tMouseCYLower;\t// lower y pos if conditional hide mouse in effect\n\t\tchar\t\t\t\t\t\tMCFlags;\t\t\t// conditional hide mouse flags\n\t\tchar\t\t\t\t\t\tMCCount;\t\t\t// nesting count for conditional hide mouse\n\n\t\tGraphicViewPortClass\t*Screen;\t\t\t// pointer to the surface mouse was init'd with\n\t\tchar *\t\t\t\t\tPrevCursor;\t\t// pointer to previous cursor shape\n\t\tint\t\t\t\t\t\tMouseUpdate;\n\t\tint\t\t\t\t\t\tState;\n\n\t\tchar\t\t\t\t\t\t*EraseBuffer;\t// Buffer which holds background to restore to hidden page\n\t\tint\t\t\t\t\t\tEraseBuffX;\t\t// X position of the hidden page background\n\t\tint\t\t\t\t\t\tEraseBuffY;\t\t// Y position of the hidden page background\n\t\tint\t\t\t\t\t\tEraseBuffHotX;\t// X position of the hidden page background\n\t\tint\t\t\t\t\t\tEraseBuffHotY;\t// Y position of the hidden page background\n\n\t\tint\t\t\t\t\t\tEraseFlags;\t\t// Records whether mutex has been released\n\n\t\tCRITICAL_SECTION\t\tMouseCriticalSection;  // Control for mouse re-enterancy\n\t\tunsigned\t\t\t\t\tTimerHandle;\n\n};\n\nextern \"C\" {\n\t void __cdecl Mouse_Shadow_Buffer(void *thisptr, GraphicViewPortClass *srcdst, void *buffer, int x, int y, int hotx, int hoty, int store);\n\t void __cdecl Draw_Mouse(void *thisptr, GraphicViewPortClass *srcdst, int x, int y);\n\t void * __cdecl ASM_Set_Mouse_Cursor(void * thisptr, int hotspotx, int hotspoty, VOID *cursor);\n};\n\nvoid Hide_Mouse(void);\nvoid Show_Mouse(void);\nvoid Conditional_Hide_Mouse(int x1, int y1, int x2, int y2);\nvoid Conditional_Show_Mouse(void);\nint Get_Mouse_State(void);\nvoid *Set_Mouse_Cursor(int hotx, int hoty, void *cursor);\nint Get_Mouse_X(void);\nint Get_Mouse_Y(void);\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/MOUSE.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;*********************************************************************************************** \n;*                                                                                             * \n;*                 Project Name : Westwood 32 bit Library                                      * \n;*                                                                                             * \n;*                    File Name : MOUSE.INC                                                    * \n;*                                                                                             * \n;*                   Programmer : Philip W. Gorrow                                             * \n;*                                                                                             * \n;*                   Start Date : 12/12/95                                                     * \n;*                                                                                             * \n;*                  Last Update : December 12, 1995 [PWG]                                      * \n;*                                                                                             * \n;*---------------------------------------------------------------------------------------------* \n;* Functions:                                                                                  * \n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nSTRUC MouseType\nMouseCursor\t\tDD\t\t?\t\t\t; pointer to the mouse cursor in memory\nMouseXHot\t\tDD\t\t?\t\t\t; X hot spot of the current mouse cursor\nMouseYHot\t\tDD\t\t?\t\t\t; Y hot spot of the current mouse cursor\nCursorWidth\t\tDD\t\t?\t\t\t; Width of mouse cursor in pixels\nCursorHeight\tDD\t\t?\t\t\t; Height of the mouse cursor in pixels\n\nMouseBuffer\t\tDD\t\t?\t\t\t; pointer to background buffer in memory\nMouseBuffX\t\tDD\t\t?\t\t\t; pixel x mouse buffer was preserved at\nMouseBuffY\t\tDD\t\t?\t\t\t; pixel y mouse buffer was preserved at\nMaxWidth\t\t\tDD\t\t?\t\t\t; Maximum possible width of the background buffer\nMaxHeight\t\tDD\t\t?\t\t\t; Maximum possible height of the background buffer\n\nMouseCXLeft\t\tDD\t\t?\t\t\t; left hand x position if conditional hide mouse in effect\nMouseCYUpper\tDD\t\t?\t\t\t; upper y position if conditional hide mouse in effect\nMouseCXRight\tDD\t\t?\t\t\t; right hand x position if conditional hide mouse in effect\nMouseCYLower\tDD\t\t?\t\t\t; lower y position if conditional hide mouse in effect\nMCFlags\t\t\tDB\t\t?\t\t\t; conditional hide mouse flags\nMCCount\t\t\tDB\t\t?\t\t\t; nesting count for conditional hide mouse\n\nScreen\t\t\tDD\t\t?\t\t\t; pointer to the surface mouse was init'd with\nPrevCursor\t\tDD\t\t?\t\t\t; pointer to the prev cursor shape\nMouseUpdate\t\tDD\t\t?\t\t\t; is the mouse being currently updated\nState\t\t\t\tDD\t\t?\n\nEraseBuffer\t\tDD\t\t?\nEraseBuffX\t\tDD\t\t?\nEraseBuffY\t\tDD\t\t?\nEraseBuffHotX\tDD\t\t?\nEraseBuffHotY\tDD\t\t?\nEraseFlags\t\tDD\t\t?\nENDS\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/NYBBTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* bNybbleTablexxxx - ADPCM Lookup table for nybbles\n;****************************************************************************\n\n\t\talign\t4\n\nbNybbleTableLow\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\n\t\talign 4\n\nbNybbleTableHigh\tDB\t00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2\n\t\tDB\t01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2\n\t\tDB\t02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2\n\t\tDB\t03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2\n\t\tDB\t04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2\n\t\tDB\t05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2\n\t\tDB\t06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2\n\t\tDB\t07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2\n\t\tDB\t08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2\n\t\tDB\t09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2\n\t\tDB\t0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2\n\t\tDB\t0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2\n\t\tDB\t0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2\n\t\tDB\t0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2\n\t\tDB\t0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2\n\t\tDB\t0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/PALETTE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Palette 32bit Library.                   *\n;*                                                                         *\n;*                    File Name : PALETTE.H                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : April 25, 1994                           *\n;*                                                                         *\n;*                  Last Update : April 27, 1994 [BRR]\t\t\t\t\t\t\t*\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef PALETTE_H\n#define PALETTE_H\n\n#include <gbuffer.h>\n/*\n********************************* Constants *********************************\n*/\n#define RGB_BYTES\t\t\t3\n#define PALETTE_SIZE\t\t256\n#define PALETTE_BYTES\t768\n\n/*\n******************************** Prototypes *********************************\n*/\n/*\n-------------------------------- Palette.cpp --------------------------------\n*/\nvoid __cdecl Set_Palette(void *palette);\nvoid __cdecl Set_Palette_Color(void *palette, int color, void *data);\nvoid Fade_Palette_To(void *palette1, unsigned int delay, void (*callback)() );\n\n/*\n-------------------------------- loadpal.cpp --------------------------------\n*/\nvoid __cdecl Load_Palette(char *palette_file_name, void *palette_pointer);\n\n/*\n------------------------------- morphpal.cpp --------------------------------\n*/\nvoid __cdecl Morph_Palette (void *src_palette, void *dst_palette, unsigned int delay,\n\tvoid *callback);\n\n/*\n---------------------------------- pal.asm ----------------------------------\n*/\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern void __cdecl Set_Palette_Range(void *palette);\nextern BOOL __cdecl Bump_Color(void *palette, int changable, int target);\n\n#ifdef __cplusplus\n}\n#endif\nextern \"C\" extern unsigned char  CurrentPalette[];\t\t/* in pal.asm */\n\n\n#endif // PALETTE_H\n\n/***************************** End of palette.h ****************************/\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/PLAYCD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB\t  \t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : PLAYCD.H\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : STEVE WETHERILL\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Start Date : 5/13/94\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : June 4, 1994   [SW]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*/\n\n#ifndef PLAYCD_H\n#define PLAYCD_H\n\n\n#ifdef NOT_FOR_WIN95\n/* ==================================================================== */\n/* Defines */\n/* ==================================================================== */\n\n#define\tCHLEFT\t0\n#define\tCHRIGHT\t1\n#define\tCHBOTH\t2\n\n#define\tAUDIO_START_MIN\t1\n#define\tAUDIO_START_SEC  44\n\ntypedef struct {\n\t\t\t\t\t  unsigned short seg ;\n \t\t\t\t\t  unsigned short sel ;\n\t\t\t\t\t} SEGSEL ;\n\n\n\n\nextern \"C\" int  DPMI_real_alloc ( UINT , SEGSEL * , USHORT * ) ;\nextern \"C\" int  DPMI_real_free ( SEGSEL  ) ;\nextern \"C\" void DPMI_real_intr ( int , union REGS * , struct SREGS * );\nextern \"C\" void DPMI_real_call ( void * funct , union REGS * , struct SREGS * );\n\n\n\n\n/* ==================================================================== */\n/* Data structures */\n/* ==================================================================== */\n\n// Audio Track Info request block\n\nstruct\tTinfoType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tTrInfo;\n\tUBYTE\t\tTrack;\n\tULONG\t\tStart;\n\tUBYTE\t\tTrCtrl;\n};\n\n// Audio Track Status Control Block\n\nstruct\tStatType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tStatInfo;\n\tUWORD\t\tStat;\n\tULONG\t\tStart;\n\tULONG\t\tEnd;\n\t};\n\n// Audio Track Volume control block\n\nstruct\tVolmType\t{\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tTrInfo;\n\tUBYTE\t\tIn0;\n\tUBYTE\t\tVol0;\n\tUBYTE\t\tIn1;\n\tUBYTE\t\tVol1;\n\tUBYTE\t\tIn2;\n\tUBYTE\t\tVol2;\n\tUBYTE\t\tIn3;\n\tUBYTE\t\tVol3;\n\t};\n\n// Audio Track Play request block\n\nstruct\tPlayType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tAddrMd;\n\tULONG\t\tStart;\n\tULONG\t\tCntSect;\n\t};\n\n\n// Audio Track Stop request block\n\nstruct\tStopType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\t};\n\n#endif\t//NOT_FOR_WIN95\n\n/***************************************************************************\n * GetCDClass -- object which will return logical CD drive\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/04/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n\n#define MAX_CD_DRIVES 26\n#define NO_CD_DRIVE -1\n\nclass\tGetCDClass {\n\nprotected:\n\n\tint\tCDDrives[MAX_CD_DRIVES];\t//Array containing CD drive letters\n\tint\tCDCount;\t\t\t\t\t\t\t//Number of available CD drives\n\tint\tCDIndex;\n\npublic:\n\n\n\tGetCDClass(VOID);\t\t\t\t\t// This is the default constructor\n\t~GetCDClass(VOID);\t\t\t\t// This is the destructor\n\n\tinline\tint\tGet_First_CD_Drive(void);\n\tinline\tint\tGet_Next_CD_Drive(void);\n\tinline\tint\tGet_Number_Of_Drives(void) {return (CDCount);};\n\n};\n\n\n\n/***********************************************************************************************\n * GCDC::Get_Next_CD_Drive -- return the logical drive number of the next CD drive             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Logical drive number of a cd drive or -1 if none                                  *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/21/96 3:50PM ST : Created                                                              *\n *=============================================================================================*/\ninline int GetCDClass::Get_Next_CD_Drive(void)\n{\n\tif (CDCount){\n\t\tif (CDIndex == CDCount) CDIndex = 0;\n\t\treturn (CDDrives[CDIndex++]);\n\t}else{\n\t\treturn (-1);\n\t}\n}\n\n\n\n/***************************************************************************\n * GCDC::Get_First_CD_Drive -- return the number of the first CD drive     *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * OUTPUT:                                                                 *\n *\t\t\tlogical drive number \t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *   12/4/95    ST : fixed for Win95                                       *\n *=========================================================================*/\ninline int GetCDClass::Get_First_CD_Drive(void)\n{\n\tCDIndex = 0;\n\treturn (Get_Next_CD_Drive());\n}\n\n\n\n\n\n\n/***************************************************************************\n * RedBookClass -- adds red book functionality\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tthis class inherits from GetCDClass and adds red book play functionality*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/04/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n\n#ifdef NOT_FOR_WIN95\nclass RedBookClass : public GetCDClass {\n\nprivate:\n\n\tSEGSEL\t\tTinfo_addrp;\n\tSEGSEL\t\tStat_addrp;\n\tSEGSEL\t\tStop_addrp;\n\tSEGSEL\t\tVolm_addrp;\n\tSEGSEL  \t   Play_addrp;\n\n\tStopType \tStop;\n\tPlayType\t\tPlay;\n\tVolmType\t\tVolm;\n\tStatType\t\tStat;\n\tTinfoType\tTinfo;\n\npublic:\n\n\tRedBookClass(VOID);\t\t\t\t\t// This is the default constructor\n\t~RedBookClass(VOID);\t\t\t\t\t// This is the destructor\n\n\tULONG\tRedToHS(ULONG i);\n\tULONG MSFtoRed(UBYTE m, UBYTE s, UBYTE f);\n\tVOID  FullCDVolume(UBYTE chan);\n\tVOID  PlayTrack(UWORD track);\n\tVOID  Play_CD_MSL(UWORD min_sec, UWORD len);\n\tVOID  PlayMSF(UBYTE startM, UBYTE startS, UBYTE startF,\n\t\t\t\tUBYTE endM, UBYTE endS, UBYTE endF, UBYTE chan);\n\tUWORD CheckCDMusic(VOID);\n\tVOID  StopCDMusic(VOID);\n\n};\n\n#endif\t//NOT_FOR_WIN95\n/***************************** End of Playcd.h ****************************/\n\n#endif // PLAYCD_H\n\u001a\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/PROFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Library profiler                                             *\n *                                                                                             *\n *                    File Name : PROFILE.H                                                    *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 11/17/95                                                     *\n *                                                                                             *\n *                  Last Update : November 20th 1995 [ST]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *                                                                                             *\n *  New System                                                                                 *\n * ~~~~~~~~~~~                                                                                 *\n *                                                                                             *\n *  The new profiler system creates a seperate thread and then starts a timer off there. The   *\n *  timer in the second thread uses GetThreadContext to sample the IP address of each user     *\n *  thread. This system has the advantage of being able to sample what is happening in all the *\n *  threads we own not just the main thread. Another advantage is that it doesnt require a     *\n *  major recompilation.                                                                       *\n *  The disadvantage is that we dont really know what is going on when the IP is outside the   *\n *  scope of our threads - We could be in direct draw, direct sound or even something like the *\n *  VMM and there is no way to tell.                                                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n *  Old System                                                                                 *\n * ~~~~~~~~~~~                                                                                 *\n *                                                                                             *\n *  The profiler works by using the function prologue and epilogue hooks available in Watcom   *\n *  to register the current functions address in a global variable and then sampling the       *\n *  contents of the variable using a windows timer which runs at up to 1000 samples per second.*\n *                                                                                             *\n *  Compile the code to be sampled with the -ep and -ee flags to enable the prologue (__PRO)   *\n *  and epilogue (__EPI) calls to be generated.                                                *\n *  At the beginning of the section to be profiled (just before main loop normally) call the   *\n *  Start_Profiler function to start sampling. At the end of the section, call Stop_Profiler   *\n *  which will stop the timer and write the profile data to disk in the PROFILE.BIN file.      *\n *                                                                                             *\n *  Use PROFILE.EXE to view the results of the session.                                        *\n *                                                                                             *\n *  The addition of prologue and epilogue code will slow down the product and the profiler     *\n *  allocates a huge buffer for data so it should not be linked in unless it is going to be    *\n *  used.                                                                                      *\n *                                                                                             *\n *  The advantage of the prologue/epilogue approach is that all samples represent valid        *\n *  addresses within our code so we get valid results we can use even when the IP is in system *\n *  code.                                                                                      *\n *                                                                                             *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#define\tMAX_PROFILE_TIME\t60*1\t\t//1 minute(s) @ 14.4 Mb per hour\n#define\tPROFILE_RATE\t\t1000\t//samples per sec (max 1000)\n\n\n/*\n * Defines for choosing between the old and new profiler system\n *\n*/\n\n#define\tOLD_PROFILE_SYSTEM\t1\n#define\tNEW_PROFILE_SYSTEM\t2\n\n//#define\tPROFILE_SYSTEM\t\t\tOLD_PROFILE_SYSTEM\n#define\tPROFILE_SYSTEM\t\t\tNEW_PROFILE_SYSTEM\n\n\n\nextern \"C\"{\n\tvoid __cdecl Profile_Init(void);\n\tvoid __cdecl Profile_End(void);\n\tvoid __cdecl Start_Profiler(void);\n\tvoid __cdecl Stop_Profiler(void);\n}\n\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/PROFILE.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\n;USE_PROFILER\t=1\n\n\nmacro\tprologue\nIfdef USE_PROFILER\n\t\tglobal\t__PRO:near\n\n\t\tcall\t\t__PRO\nendif ;USE_PROFILER\nendm\n\n\n\nmacro epilogue\nifdef USE_PROFILER\n\t\tglobal\t__EPI:near\n\n\t\tpush\t\tebp\n\t\tcall\t\t__EPI\n\t\tpop\t\t\tebp\nendif ;USE_PROFILER\nendm\n\n\n\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/RAWFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\rawfile.h_v   2.15   06 Sep 1995 16:29:30   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Library                                             *\n *                                                                                             *\n *                    File Name : RAWFILE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 18, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RawFileClass::File_Name -- Returns with the filename associate with the file object.      *\n *   RawFileClass::RawFileClass -- Default constructor for a file object.                      *\n *   RawFileClass::Is_Open -- Checks to see if the file is open or not.                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef RAWFILE_H\n#define RAWFILE_H\n\n#ifndef WIN32\n#define WIN32 1\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#endif\n#include <windows.h>\n\n//#include\t<wwlib32.h>\n#include\t<limits.h>\n#include\t<errno.h>\n#include\t<windows.h>\n//#include\t<algo.h>\n#include\t\"wwfile.h\"\n\n#ifdef NEVER\n\t/*\n\t**\tThis is a duplicate of the error numbers. The error handler for the RawFileClass handles\n\t**\tthese errors. If the error routine is overridden and additional errors are defined, then\n\t**\tuse numbers starting with 100. Note that these errors here are listed in numerical order.\n\t**\tThese errors are defined in the standard header file \"ERRNO.H\".\n\t*/\n\tEZERO,\t\t\t\t// Non-error.\n\tEINVFNC,\t\t\t\t// Invalid function number.\n\tENOFILE,\t\t\t\t// File not found.\n\tENOENT=ENOFILE,\t// No such file or directory.\n\tENOPATH,\t\t\t\t// Path not found.\n\tEMFILE,\t\t\t\t// Too many open files.\n\tEACCES,\t\t\t\t// Permission denied.\n\tEBADF,\t\t\t\t// Bad file number.\n\tECONTR,\t\t\t\t// Memory blocks destroyed.\n\tENOMEM,\t\t\t\t// Not enough core memory.\n\tEINVMEM,\t\t\t\t// Invalid memory block address.\n\tEINVENV,\t\t\t\t// Invalid environment.\n\tEINVFMT,\t\t\t\t// Invalid format.\n\tEINVACC,\t\t\t\t// Invalid access code.\n\tEINVDAT,\t\t\t\t// Invalid data.\n\tEFAULT,\t\t\t\t// Unknown error.\n\tEINVDRV,\t\t\t\t// Invalid drive specified.\n\tENODEV=EINVDRV,\t// No such device.\n\tECURDIR,\t\t\t\t// Attempt to remove CurDir.\n\tENOTSAM,\t\t\t\t// Not same device.\n\tENMFILE,\t\t\t\t// No more files.\n\tEINVAL,\t\t\t\t// Invalid argument.\n\tE2BIG,\t\t\t\t// Argument list too long.\n\tENOEXEC,\t\t\t\t// exec format error.\n\tEXDEV,\t\t\t\t// Cross-device link.\n\tENFILE,\t\t\t\t// Too many open files.\n\tECHILD,\t\t\t\t// No child process.\n\tENOTTY,\t\t\t\t// not used\n\tETXTBSY,\t\t\t\t// not used\n\tEFBIG,\t\t\t\t// not used\n\tENOSPC,\t\t\t\t// No space left on device.\n\tESPIPE,\t\t\t\t// Illegal seek.\n\tEROFS,\t\t\t\t// Read-only file system.\n\tEMLINK,\t\t\t\t// not used\n\tEPIPE,\t\t\t\t// Broken pipe.\n\tEDOM,\t\t\t\t\t// Math argument.\n\tERANGE,\t\t\t\t// Result too large.\n\tEEXIST,\t\t\t\t// File already exists.\n\tEDEADLOCK,\t\t\t// Locking violation.\n\tEPERM,\t\t\t\t// Operation not permitted.\n\tESRCH,\t\t\t\t// not used\n\tEINTR,\t\t\t\t// Interrupted function call.\n\tEIO,\t\t\t\t\t// Input/output error.\n\tENXIO,\t\t\t\t// No such device or address.\n\tEAGAIN,\t\t\t\t// Resource temporarily unavailable.\n\tENOTBLK,\t\t\t\t// not used\n\tEBUSY,\t\t\t\t// Resource busy.\n\tENOTDIR,\t\t\t\t// not used\n\tEISDIR,\t\t\t\t// not used\n\tEUCLEAN,\t\t\t\t// not used\n#endif\n\n/*\n**\tThis is the definition of the raw file class. It is derived from the abstract base FileClass\n**\tand handles the interface to the low level DOS routines. This is the first class in the\n**\tchain of derived file classes that actually performs a useful function. With this class,\n**\tI/O is possible. More sophisticated features, such as packed files, CD-ROM support,\n**\tfile caching, and XMS/EMS memory support, are handled by derived classes.\n**\n**\tOf particular importance is the need to override the error routine if more sophisticated\n**\terror handling is required. This is more than likely if greater functionality is derived\n**\tfrom this base class.\n*/\nclass RawFileClass : public FileClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tThis is a record of the access rights used to open the file. These rights are\n\t\t**\tused if the file object is duplicated.\n\t\t*/\n\t\tint Rights;\n\n\t\tRawFileClass(char const *filename);\n\t\tRawFileClass(void);\n\t\tRawFileClass (RawFileClass const & f);\n\t\tRawFileClass & operator = (RawFileClass const & f);\n\t\tvirtual ~RawFileClass(void) {if (Allocated && Filename) free((char *)Filename);};\n\n\t\tvirtual char const * File_Name(void) const;\n\t\tvirtual char const * Set_Name(char const *filename);\n\t\tvirtual int Create(void);\n\t\tvirtual int Delete(void);\n\t\tvirtual int Is_Available(int forced=false);\n\t\tvirtual int Is_Open(void) const;\n\t\tvirtual int Open(char const *filename, int rights=READ);\n\t\tvirtual int Open(int rights=READ);\n\t\tvirtual long Read(void *buffer, long size);\n\t\tvirtual long Seek(long pos, int dir=SEEK_CUR);\n\t\tvirtual long Size(void);\n\t\tvirtual long Write(void const *buffer, long size);\n\t\tvirtual void Close(void);\n\t\tvirtual void Error(int error, int canretry = false, char const * filename=NULL);\n\t\tvirtual void Set_Buffer_Size(int size);\n\n\n\tprotected:\n\n\t\t/*\n\t\t**\tThis function returns the largest size a low level DOS read or write may\n\t\t**\tperform. Larger file transfers are performed in chunks of this size or less.\n\t\t*/\n\t\tlong Transfer_Block_Size(void) {return (long)((unsigned)UINT_MAX)-16L;};\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is the low level DOS handle. A -1 indicates an empty condition.\n\t\t*/\n\t\tint Handle;\n\n\t\t/*\n\t\t**\tThis points to the filename as a NULL terminated string. It may point to either a\n\t\t**\tconstant or an allocated string as indicated by the \"Allocated\" flag.\n\t\t*/\n\t\tchar const * const Filename;\n\n\t\t/*\n\t\t**\tFilenames that were assigned as part of the construction process\n\t\t**\tare not allocated. It is assumed that the filename string is a\n\t\t**\tconstant in that case and thus making duplication unnecessary.\n\t\t**\tThis value will be non-zero if the filename has be allocated\n\t\t**\t(using strdup()).\n\t\t*/\n\t\tunsigned Allocated:1;\n};\n\n\n/***********************************************************************************************\n * RawFileClass::File_Name -- Returns with the filename associate with the file object.        *\n *                                                                                             *\n *    Use this routine to determine what filename is associated with this file object. If no   *\n *    filename has yet been assigned, then this routing will return NULL.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the file name associated with this file object or NULL   *\n *          if one doesn't exist.                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n;*   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline char const * RawFileClass::File_Name(void) const\n{\n\treturn Filename;\n}\n\n/***********************************************************************************************\n * RawFileClass::RawFileClass -- Default constructor for a file object.                        *\n *                                                                                             *\n *    This constructs a null file object. A null file object has no file handle or filename    *\n *    associated with it. In order to use a file object created in this fashion it must be     *\n *    assigned a name and then opened.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n;*   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline RawFileClass::RawFileClass(void) : Filename(0)\n{\n\tHandle = -1;\n\tAllocated = false;\n}\n\n/***********************************************************************************************\n * RawFileClass::Is_Open -- Checks to see if the file is open or not.                          *\n *                                                                                             *\n *    Use this routine to determine if the file is open. It returns true if it is.             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file open?                                                            *\n *                                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n;*   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int RawFileClass::Is_Open(void) const\n{\n\treturn (Handle != -1);\n}\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/SHAPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32                                  *\n *                                                                         *\n *                    File Name : SHAPE.H                                  *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : May 25, 1994                             *\n *                                                                         *\n *                  Last Update : September 14, 1994   [IML]               *\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef SHAPE_H\n#define SHAPE_H\n\n#ifndef GBUFFER_H\n#include \"gbuffer.h\"\n#endif\n/*\n*********************************** Types ***********************************\n*/\n/*\n--------------------------- Shape creation flags ----------------------------\n*/\ntypedef enum {\n\tMAKESHAPE_NORMAL\t = 0x0000,\t// 256-color compressed shape\n\tMAKESHAPE_COMPACT  = 0x0001,\t// 16-color shape (with built-in color table)\n\tMAKESHAPE_NOCOMP\t = 0x0002,\t// Uncompressed shape\n\tMAKESHAPE_VARIABLE =\t0x0004\t// <16-color shape\n} MakeShapeFlags_Type;\n\n/*---------------------------------------------------------------------------\nShape drawing flags:\n- The low byte is for coordinate transformations.\n- The high byte is for drawing effects.\n---------------------------------------------------------------------------*/\ntypedef enum {\n\tSHAPE_NORMAL \t\t\t= 0x0000,\t\t// Standard shape\n\tSHAPE_HORZ_REV \t\t= 0x0001,\t\t// Flipped horizontally\n\tSHAPE_VERT_REV \t\t= 0x0002,\t\t// Flipped vertically\n\tSHAPE_SCALING \t\t\t= 0x0004,\t\t// Scaled (WORD scale_x, WORD scale_y)\n\tSHAPE_VIEWPORT_REL \t= 0x0010,\t\t// Coords are window-relative\n\tSHAPE_WIN_REL \t\t\t= 0x0010,\t\t// Coordinates are window relative instead of absolute.\n\tSHAPE_CENTER \t\t\t= 0x0020,\t\t// Coords are based on shape's center pt\n\tSHAPE_FADING \t\t\t= 0x0100,\t\t// Fading effect (void * fading_table,\n\t\t\t\t\t\t\t\t\t\t\t\t\t//  WORD fading_num)\n\tSHAPE_PREDATOR \t\t= 0x0200,\t\t// Transparent warping effect\n\tSHAPE_COMPACT \t\t\t= 0x0400,\t\t// Never use this bit\n\tSHAPE_PRIORITY \t\t= 0x0800,\t\t// Use priority system when drawing\n\tSHAPE_GHOST\t\t\t\t= 0x1000,\t\t// Shape is drawn ghosted\n\tSHAPE_SHADOW\t\t\t= 0x2000,\n\tSHAPE_PARTIAL  \t\t= 0x4000,\n\tSHAPE_COLOR \t\t\t= 0x8000\t\t\t// Remap the shape's colors\n\t\t\t\t\t\t\t\t\t\t\t\t\t//  (void * color_table)\n} ShapeFlags_Type;\n\n/*\n------------------------------- Shape header --------------------------------\n*/\ntypedef struct {\n\tunsigned short\t\tShapeType;\t\t\t// 0 = normal, 1 = 16 colors,\n\t\t\t\t\t\t\t\t\t\t//  2 = uncompressed, 4 = \t<16 colors\n\tunsigned char\t\tHeight;\t\t\t\t// Height of the shape in scan lines\n\tunsigned short\t\tWidth;\t\t\t\t// Width of the shape in bytes\n\tunsigned char\t\tOriginalHeight;\t// Original height of shape in scan lines\n\tunsigned short\t\tShapeSize;\t\t\t// Size of the shape, including header\n\tunsigned short\t\tDataLength;\t\t\t// Size of the uncompressed shape (just data)\n\tunsigned char\t\tColortable[16];\t// Optional color table for compact shape\n} Shape_Type;\n\n/*\n------------------------------- Shape block ---------------------------------\n*/\ntypedef struct {\n\tunsigned short\t\tNumShapes;\t\t\t// number of shapes in the block\n\tlong\t\tOffsets[];\t\t\t// array of offsets to shape data\n\t\t\t\t\t\t\t\t\t\t//  (offsets within the shape block, with\n\t\t\t\t\t\t\t\t\t\t//  0 being the first offset value, not the\n\t\t\t\t\t\t\t\t\t\t//  start of the shape block)\n} ShapeBlock_Type;\n\n\n/*\n******************************** Prototypes *********************************\n*/\n\n/*\n-------------------------------- prioinit.c ---------------------------------\n*/\n\nextern \"C\" {\nextern void  *MaskPage;\nextern void  *BackGroundPage;\nextern long  _ShapeBufferSize;\nextern char  *_ShapeBuffer;\n}\n\n\nvoid __cdecl Init_Priority_System (GraphicBufferClass *mask,\n\t\t\t\t\t\t\t\t\t\t\tGraphicBufferClass *back);\n\n\n/*\n-------------------------------- drawshp.asm --------------------------------\n*/\n\nextern \"C\" {\nint Draw_Shape(GraphicViewPortClass *gvp, void const *shape, LONG x, LONG y, LONG flags, ...);\n}\n\n/*\n---------------------------------- shape.c ----------------------------------\n*/\nshort __cdecl Get_Shape_Data(void const *shape, int data);\nint __cdecl Extract_Shape_Count(void const *buffer);\nvoid * __cdecl Extract_Shape(void const *buffer, int shape);\nint __cdecl Restore_Shape_Height(void *shape);\nint __cdecl Set_Shape_Height(void const *shape, int newheight);\n\nextern \"C\" {\nint __cdecl Get_Shape_Width(void const *shape);\nint __cdecl Get_Shape_Height(void const *shape);\nint __cdecl Get_Shape_Original_Height(void const *shape);\nint __cdecl Get_Shape_Uncomp_Size(void const *shape);\n}\n\n\n/*\n------------------------------- setshape.asm --------------------------------\n*/\nextern \"C\" {\nvoid __cdecl Set_Shape_Buffer(void const *buffer, int size);\n}\n/*\n------------------------------- shapeinf.asm --------------------------------\n*/\nint __cdecl Get_Shape_Flags(void const *shape);\nint  __cdecl Get_Shape_Size(void const *shape);\nint  __cdecl Get_Shape_Scaled_Width(void const *shape, int scale);\nint  __cdecl Get_Shape_Scaled_Height(void const *shape, int scale);\n\n#endif // SHAPE_H\n\n/****************************** End of shape.h *****************************/\n\u001a\n\u001a\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/SHAPE.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : WWLIB32                                  *\n;*                                                                         *\n;*                    File Name : SHAPE.INC                                *\n;*                                                                         *\n;*                   Programmer : Scott Bowen\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : May 25, 1994                             *\n;*                                                                         *\n;*                  Last Update : September 14, 1994   [IML]               *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;****************************** Equates ************************************\n;\n\n\n\n\n\n\n;............................ Shape Types ..................................\n;\nTRUE\tequ\t1\t\t\t; Boolean 'true' value\nFALSE\tequ\t0\t\t\t; Boolean 'false' value\n\nMAKESHAPE_NORMAL\t\tEQU\t0\t; 256-color compressed shape\nMAKESHAPE_COMPACT\t\tEQU\t1\t; 16-color shape (built-in color table)\nMAKESHAPE_NOCOMP\t\tEQU\t2\t; non-wwcomped shape\nMAKESHAPE_VARIABLE\tEQU\t4\t; <16-color shape with variable #\n\t\t\t\t\t; of colors (ColorTable[0] = # of colors)\n; old names:\n;COLOR_SHAPE\t\tEQU\t1\t; flag which determines a color shape\n;NORM_SHAPE\t\t\tEQU\t2\t; flag that indicates non wwcomped shp\n;NORM_SHAPE_16\t\tEQU\t4\t; flag that tells us if we have a variable sized table\n\t\t\t\t\t;  variable sized table\n;\n;...........................................................................\n; Drawing flags:\n; The low byte is for coordinate transformations.\n; The high byte is for drawing effects.\n;...........................................................................\n;\nSHAPE_NORMAL\t\t\tEQU\t0000h\t; no options; just a copy\nSHAPE_HORZ_REV\t\t\tEQU\t0001h\t; reverse horizontally\nSHAPE_VERT_REV\t\t\tEQU\t0002h\t; reverse vertically\nSHAPE_SCALING\t\t\tEQU\t0004h\t; scale\nSHAPE_VIEWPORT_REL\tEQU\t0010h\t; viewport-relative coordinates\nSHAPE_CENTER\t\t\tEQU\t0020h\t; use centered coordinates\nSHAPE_FADING\t\t\tEQU\t0100h\t; fading effect shape\nSHAPE_PREDATOR\t\t\tEQU\t0200h\t; predator effect shape\nSHAPE_COMPACT\t\t\tEQU\t0400h\t; shape is in 16 colors\nSHAPE_PRIORITY\t\t\tEQU\t0800h\t; priority draw shape\nSHAPE_GHOST\t\t\t\tEQU\t1000h\t; ghosting effect\nSHAPE_SHADOW\t\t\tEQU\t2000h\t; shadow effect\nSHAPE_PARTIAL\t\t\tEQU\t4000h\t; partial predator effect\nSHAPE_COLOR\t\t\t\tEQU\t8000h\t; use alternative color table effect\n\nSHAPE_EFFECTS\t\t\tEQU    03F00h\t; shape effect flags\n\n;\n;.......................... Shadow Effect ..................................\n;\nSHADOW_COL\t\tEQU\t00FFh\t; magic number for shadows\n\n;......................... Priority System .................................\n;\nCLEAR_UNUSED_BITS  \tEQU\t0007h\t; and with 0000-0111 to clear\n\t\t\t\t\t;  non-walkable high bit and\n\t\t\t\t\t;  scaling id bits\nNON_WALKABLE_BIT  \tEQU\t0080h\t; and with 1000-0000 to clear all\n\t\t\t\t\t;  but non-walkable bit\n;\n;......................... Predator Effect .................................\n;\nPRED_MASK\t\tEQU\t0007h\t; mask used for predator pixel puts\n\n;---------------------------------------------------------------------------\n; This table is a list of the local stack variables in the function\n; Draw_Shape.  Many other functions in other modules access these variables\n; on the stack.  Since the BP is not changed when these other functions are\n; called by Draw_Shape (possibly indirectly), they can also access these\n; stack varibles.  When adding or removing from the table, one must be very\n; careful to change the offsets.\n;---------------------------------------------------------------------------\n;.......................... proc addresses .................................\nLSkipRout\tEQU DWORD PTR ebp - 04h\t\t;DWORD  pointer to the skip routine\nRSkipRout\tEQU DWORD PTR ebp - 08h\t\t;DWORD  pointer to the skip routine\nDrawRout\tEQU DWORD PTR ebp - 0Ch\t\t\t;DWORD  pointer to the draw routine\n;........................ optional arguments ...............................\nColorTable\tEQU DWORD PTR ebp - 10h\t\t;DWORD\tptr to the shapes color table\nFadingTable\tEQU DWORD PTR ebp - 14h\t\t;DWORD  ptr to the fading table\n\nFadingNum\tEQU DWORD PTR ebp - 18h\t\t;DWORD  number of times to fade\nIsTranslucent\tEQU DWORD PTR ebp - 1Ch\t;DWORD\tptr to is_translucent table\nTranslucent\tEQU DWORD PTR ebp - 20h\t\t;DWORD\tptr to actual translucent tbl\nPriLevel\tEQU BYTE  PTR ebp - 24h\t\t\t;BYTE\tpriority level of the object\nScaleX\t\tEQU DWORD PTR ebp - 28h\t\t;DWORD  the x increment to scale by\nScaleY\t\tEQU DWORD PTR ebp - 2Ch\t\t;DWORD  the y increment to scale by\nShadowingTable\tEQU DWORD PTR ebp - 30h\t;DWORD\tptr to the shadowing table\n;........................ Shape header values ..............................\nShapeType\tEQU DWORD PTR ebp - 34h \t;DWORD\tshape type\nShapeWidth\tEQU DWORD PTR ebp - 38h \t;DWORD\tshape's unscaled width\nShapeHeight\tEQU DWORD PTR ebp - 3Ch \t;DWORD\tshape's unscaled height\nUncompDataLen\tEQU DWORD PTR ebp - 40h ;DWORD\tuncompressed data length\nShapeData\tEQU DWORD PTR ebp - 44h \t;DWORD\tpointer to shape data\n;...................... Scaled shape dimensions ............................\nScaledWidth\tEQU DWORD PTR ebp - 48h \t;DWORD\tshape's scaled width\nScaledHeight\tEQU DWORD PTR ebp - 4Ch ;DWORD\tshape's scaled height\n;...................... Pixel clipping variables ...........................\nLeftClipPixels\tEQU DWORD PTR ebp - 50h ;DWORD\t# left-clipped pixels\nRightClipPixels\tEQU DWORD PTR ebp - 54h ;DWORD\t# right-clipped pixels\nTopClipPixels\tEQU DWORD PTR ebp - 58h ;DWORD\t# top-clipped pixels\nBotClipPixels\tEQU DWORD PTR ebp - 5Ch ;DWORD\t# bottom-clipped pixels\nPixelWidth\tEQU DWORD PTR ebp - 60h \t;DWORD\tdrawable area in pixels\nPixelHeight\tEQU DWORD PTR ebp - 64h \t;DWORD\tdrawable area in pixels\n;......................... Drawing variables ...............................\nNumColors\tEQU DWORD PTR ebp - 68h ;DWORD\t# colors for 16-color shapes\nStartDraw\tEQU DWORD PTR ebp - 6Ch ;DWORD\toffset of drawing start pos\nNextLine\tEQU DWORD PTR ebp - 70h ;DWORD\toffset of next drawing line\nLeftClipBytes\tEQU DWORD PTR ebp - 74h ;DWORD\t# left-clipped bytes\nXTotal\t\tEQU DWORD PTR ebp - 78h ;DWORD\taccumulated x-pixels\nXTotalInit\tEQU DWORD PTR ebp - 7Ch ;DWORD\tinitial roundoff for XTotal\nYTotal\t\tEQU DWORD PTR ebp - 80h ;DWORD\taccumulated y-pixels\nHeightCount\tEQU DWORD PTR ebp - 84h ;DWORD\tht counter for drawing lines\nLineStart\tEQU DWORD PTR ebp - 88h ;DWORD\taddress of start of line\nWidthCount\tEQU DWORD PTR ebp - 8Ch ;DWORD\tcounts down # bytes skipped\nStashReg\tEQU DWORD PTR ebp - 90h \t;DWORD\ttemp variable for draw routines\nMaskAdjust\tEQU DWORD PTR ebp - 94h ;DWORD  priority buffer offset\nBackAdjust\tEQU DWORD PTR ebp - 98h ;DWORD  background buffer offset\nStashECX\tEQU DWORD PTR ebp - 9Ch \t;DWORD  temp variable for ECX register\nStashEDX\tEQU DWORD PTR ebp -0A0h \t;DWORD  temp variable for EDX register\n\nLocal_Size\tEQU 00A4h\t\t; Amt of data on stack: 4+last offset\n\n;****************************** Declarations *******************************\n;---------------------------------------------------------------------------\n; Global variables used by the shape routines, defined in drawshp.asm\n;---------------------------------------------------------------------------\nGLOBAL C ShapeBuffer:DWORD\nGLOBAL C ShapeBufferSize:DWORD\nGLOBAL C _MaskPage:DWORD\nGLOBAL C _BackGroundPage:DWORD\nGLOBAL C PredCount:DWORD\nGLOBAL C PredTable:BYTE\nGLOBAL C PredValue:DWORD\nGLOBAL C PartialPred:DWORD\nGLOBAL C PartialCount:DWORD\nGLOBAL C Flags:DWORD\n\n;---------------------------------------------------------------------------\n; External tables that are defined in ds_table.asm.\n;---------------------------------------------------------------------------\nGLOBAL LSkipTable:DWORD\nGLOBAL RSkipTable:DWORD\nGLOBAL DrawTable:DWORD\n\n;------------------------------------------------------------------------------\n; Public functions, declared in the order they appear in the function tables.\n;--------------------------------------------------------------------------------\nGLOBAL\tC Not_Supported:NEAR\n;\tLSkipTable:\nGLOBAL Left_Skip:NEAR\t\t\t\t\t\t; ds_ls\nGLOBAL Left_Reverse_Skip:NEAR\t\t\t\t; ds_lrs\nGLOBAL Left_Skip:NEAR\t\t\t\t\t\t; ds_ls\nGLOBAL Left_Reverse_Skip:NEAR\t\t\t\t; ds_lrs\nGLOBAL Left_Scale_Skip:NEAR\t\t\t\t; ds_lss\nGLOBAL Left_Scale_Reverse_Skip:NEAR\t\t; ds_lsrs\nGLOBAL Left_Scale_Skip:NEAR\t\t\t\t; ds_lss\nGLOBAL Left_Scale_Reverse_Skip:NEAR\t\t; ds_lsrs\n\n;\tRSkipTable:\nGLOBAL Right_Skip:NEAR\t\t\t\t\t   ; ds_rs\nGLOBAL Right_Reverse_Skip:NEAR\t\t\t; ds_rrs\nGLOBAL Right_Skip:NEAR\t\t\t\t\t   ; ds_rs\nGLOBAL Right_Reverse_Skip:NEAR\t\t\t; ds_rrs\nGLOBAL Right_Scale_Skip:NEAR\t\t\t\t; ds_rss\nGLOBAL Right_Scale_Reverse_Skip:NEAR\t; ds_rsrs\nGLOBAL Right_Scale_Skip:NEAR\t\t\t\t; ds_rss\nGLOBAL Right_Scale_Reverse_Skip:NEAR\t; ds_rsrs\n\n;\tDrawTable:\nGLOBAL Draw_Normal:NEAR\t\t\t\t\t; ds_dn\nGLOBAL Draw_Reverse:NEAR\t\t\t\t; ds_dr\nGLOBAL Draw_Normal:NEAR\t\t\t\t\t; ds_dn\nGLOBAL Draw_Reverse:NEAR\t\t\t\t; ds_dr\nGLOBAL Draw_Scale:NEAR\t\t\t\t\t; ds_ds\nGLOBAL Draw_Scale_Reverse:NEAR\t\t; ds_dsr\nGLOBAL Draw_Scale:NEAR\t\t\t\t\t; ds_ds\nGLOBAL Draw_Scale_Reverse:NEAR\t\t; ds_dsr\n\n\n;************************* End of shape.inc ********************************\n\u001a\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/SOS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sos.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces\n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DEFINED\n#define  _SOS_DEFINED\n#include \"sosdefs.h\"\n\n#pragma pack(4)\n\n// error definition for sound operating system\n#define  _SOS_ERR          -1\n\n// number of drivers allowed to be open at one time\n#define  _SOS_MAX_DRIVERS  5\n\n// structure definition for the capabilities\ntypedef struct _tagCAPABILITIES\n{\n   BYTE  szDeviceName[ 32 ];  // device name\n   WORD  wDeviceVersion;      // device version\n   WORD  wBitsPerSample;      // bits per sound sample\n   WORD  wChannels;           // stereo/mono sound card\n   WORD  wMinRate;            // minimum rate\n   WORD  wMaxRate;            // maximum rate\n   WORD  wMixerOnBoard;       // board contains mixer\n   WORD  wMixerFlags;         // mixer capabilities\n   WORD  wFlags;              // miscellaneous flags\n   short far * lpPortList;         // list of usable ports\n   short far * lpDMAList;          // list of usable dma channels\n   short far * lpIRQList;          // list of usable irq channels\n   short far * lpRateList;         // list of usable rates, -1 if any in min to max\n   WORD  fBackground;         // foreground or background driver\n   WORD  wDeviceID;           // ID for the device\n   WORD  wTimerID;            // ID for the timer\n\n} _SOS_CAPABILITIES;\n\n// far pointer to the device capabilities structure\ntypedef _SOS_CAPABILITIES far *  LPSOSDEVICECAPS;\n\n// flag types for driver\n#define  _FLAGS_SIGNED              0x8000\n\n// devices that can be loaded\n#define  _SOUND_BLASTER_8_MONO      0xe000\n#define  _SOUND_BLASTER_8_ST        0xe001\n#define  _SBPRO_8_ST                _SOUND_BLASTER_8_ST\n#define  _SBPRO_8_MONO              0xe00f\n#define  _SOUND_MASTER_II_8_MONO    0xe002\n#define  _MV_PAS_8_MONO             0xe003\n#define  _MV_PAS_16_MONO            0xe004\n#define  _MV_PAS_8_ST               0xe005\n#define  _MV_PAS_16_ST              0xe006\n#define  _ADLIB_GOLD_8_ST           0xe007\n#define  _ADLIB_GOLD_16_ST          0xe008\n#define  _ADLIB_GOLD_8_MONO         0xe009\n#define  _ADLIB_GOLD_16_MONO        0xe00a\n#define  _MICROSOFT_8_MONO          0xe00b\n#define  _MICROSOFT_8_ST            0xe00c\n#define  _MICROSOFT_16_MONO         0xe00d\n#define  _MICROSOFT_16_ST           0xe00e\n#define  _SOUND_SOURCE_8_MONO_PC    0xe010\n#define  _SOUND_SOURCE_8_MONO_TANDY 0xe011\n#define  _GENERAL_PORT_8_MONO       0xe012\n#define  _GENERAL_PORT_8_MONO_R     0xe013\n#define  _SIERRA_8_MONO             0xe014\n#define  _SB16_8_MONO               0xe015\n#define  _SB16_8_ST                 0xe016\n#define  _SB16_16_MONO              0xe017\n#define  _SB16_16_ST                0xe018\n#define  _ESS_AUDIODRIVE_8_MONO     0xe019\n#define  _ESS_AUDIODRIVE_8_ST       0xe01a\n#define  _ESS_AUDIODRIVE_16_MONO    0xe01b\n#define  _ESS_AUDIODRIVE_16_ST      0xe01c\n#define  _SOUNDSCAPE_8_MONO         0xe01d\n#define  _SOUNDSCAPE_8_ST           0xe01e\n#define  _SOUNDSCAPE_16_MONO        0xe01f\n#define  _SOUNDSCAPE_16_ST          0xe020\n#define  _RAP10_8_MONO              0xe021\n#define  _RAP10_16_MONO             0xe022\n#define  _GUS_8_MONO                0xe023\n#define  _GUS_8_ST                  0xe024\n#define  _GUS_16_MONO               0xe025\n#define  _GUS_16_ST                 0xe026\n#define  _GUS_MAX_8_MONO            0xe027\n#define  _GUS_MAX_8_ST              0xe028\n#define  _GUS_MAX_16_MONO           0xe029\n#define  _GUS_MAX_16_ST             0xe02a\n#define  _WAVEJAMMER_8_MONO         0xe02b\n#define  _WAVEJAMMER_8_ST           0xe02c\n#define  _WAVEJAMMER_16_MONO        0xe02d\n#define  _WAVEJAMMER_16_ST          0xe02e\n#define  _TEMPOCS_8_MONO            0xe02f\n#define  _TEMPOCS_8_ST              0xe030\n#define  _TEMPOCS_16_MONO           0xe031\n#define  _TEMPOCS_16_ST             0xe032\n#define  _WAVEJAMMERCD_8_MONO       0xe033\n#define  _WAVEJAMMERCD_8_ST         0xe034\n#define  _WAVEJAMMERCD_16_MONO      0xe035\n#define  _WAVEJAMMERCD_16_ST        0xe036\n#define  _SOUND_BLASTER_8_MONO_R    0xe050\n#define  _MICROSOFT_8_MONO_R        0xe051\n#define  _SOUND_MASTER_II_8_MONO_R  0xe052\n#define  _ADLIB_GOLD_8_MONO_R       0xe053\n#define  _MV_PAS_8_MONO_R           0xe054\n#define  _RAP10_8_MONO_R            0xe058\n#define  _RAP10_16_MONO_R           0xe059\n#define  _SB16_8_MONO_R             0xe05a\n#define  _SB16_8_ST_R               0xe05b\n#define  _SB16_16_MONO_R            0xe05c\n#define  _SB16_16_ST_R              0xe05d\n#define  _MV_PAS_16_MONO_R          0xe060\n#define  _SOUNDSCAPE_8_MONO_R       0xe061\n#define  _SOUNDSCAPE_8_ST_R         0xe062\n#define  _SOUNDSCAPE_16_MONO_R      0xe063\n#define  _SOUNDSCAPE_16_ST_R        0xe064\n#define  _ESS_AUDIODRIVE_8_MONO_R   0xe065\n#define  _ESS_AUDIODRIVE_8_ST_R     0xe066\n#define  _ESS_AUDIODRIVE_16_MONO_R  0xe067\n#define  _ESS_AUDIODRIVE_16_ST_R    0xe068\n#define  _SPEECH_THING_8_MONO       0xe090\n#define  _YAMAHA_8_MONO             0xe106\n#define  _INT_SPEAKER_8_MONO        0xe107\n\n// call indexes for the loadable drivers\nenum\n{\n   _DRV_INIT,\n   _DRV_UNINIT,\n   _DRV_SETRATE,\n   _DRV_SETACTION,\n   _DRV_START,\n   _DRV_STOP,\n   _DRV_PAUSE,\n   _DRV_RESUME,\n   _DRV_CAPABILITIES,\n   _DRV_PLAY_FOREGROUND,\n   _DRV_GET_FILL_INFO,\n   _DRV_GET_CALL_FUNCTIONS,\n   _DRV_SET_CALL_FUNCTIONS\n};\n\n// fill info\ntypedef  struct   _tagFillInfo\n         {\n\n            LPSTR lpFillHandler;                   // pointer to fill handler\n            LPWORD lpDMAFillCount;                 // pointer to dma count\n            LPSTR lpSampleList;                    // pointer to sample list\n            LPWORD lpDMAMasterVolume;              // pointer to dma count\n\n         } _SOS_FILL_INFO;\n\n// caps info structure\ntypedef  struct   _tagCapsInfo\n         {\n\n            LPSTR    lpPortList;                   // pointer to port list\n            LPSTR    lpDMAList;                    // pointer to DMA list\n            LPSTR    lpIRQList;                    // pointer to IRQ list\n            LPSTR    lpRateList;                   // pointer to rate list\n\n         } _SOS_CAPS_INFO;\n\n// maximum number of available voice\n#define  _MAX_VOICES    32\n\n// structure definition\ntypedef  struct   _tagSAMPLE\n{\n   LPSTR    samplePtr;                 // pointer to data buffer\n   LPSTR    sampleData;                // pointer to active data\n   LPSTR    sampleLoopPtr;             // pointer for loop back\n\n   WORD     sampleLength;              // length of sample\n   WORD     sampleIndex;               // index into sample\n   WORD     sampleLoopLength;          // length of loop\n\n   WORD     sampleBytesLeft;           // bytes left to play in sample\n\n   WORD     sampleLoopPoint;           // byte count for loop point\n   WORD     sampleLoopEndLength;       // length of remaining chunk\n\n   short    sampleFlags;               // control sample\n   short    sampleVolume;              // volume control\n   short    sampleID;                  // sample ID\n\n   short    sampleChannel;             // channel to play sample on\n   short    sampleLoopCount;           // loop count\n   short    sampleLastFill;            // last fill position\n   VOID ( far __cdecl * sampleCallback )( WORD, WORD, WORD ); // callback function for sample\n\n   WORD     samplePitchAdd;\n   short    samplePitchFraction;\n\n   short    samplePort;                // port to use for non-dma digitized\n\n   WORD     sampleTotalBytes;\n   WORD     sampleByteLength;\n\n   short    samplePanLocation;\n   short    samplePanSpeed;\n   short    samplePanDirection;\n   short    samplePanStart;\n   short    samplePanEnd;\n\n   short    sampleDelayBytes;\n   short    sampleDelayRepeat;\n\n   WORD     sampleADPCMPredicted;\n   short    sampleADPCMIndex;\n\n   short    sampleRootNoteMIDI;\n\n   WORD  sampleTemp1;\n\n} _SOS_SAMPLE;\n\n// enumeration for left or right channel\nenum\n{\n   _LEFT_CHANNEL,\n   _RIGHT_CHANNEL,\n   _CENTER_CHANNEL,\n   _INTERLEAVED\n};\n\n// enumeration for foreground and background\nenum\n{\n   _FOREGROUND,\n   _BACKGROUND\n};\n\n// defines for the sample flags\n#define  _ACTIVE           0x8000\n#define  _LOOPING          0x4000\n#define  _FIRST_TIME       0x2000\n#define  _PENDING_RELEASE  0x1000\n#define  _CONTINUE_BLOCK   0x0800\n#define  _PITCH_SHIFT      0x0400\n#define  _PANNING          0x0200\n#define  _VOLUME           0x0100\n#define  _TRANSLATE16TO8   0x0080\n#define  _STAGE_LOOP       0x0040\n#define  _TRANSLATE8TO16   0x0020\n#define  _STEREOTOMONO     0x0010\n\n// defines for the wParam flags\n#define  _SINGLE_SAMPLE 0x01\n\n#define  _SOS_DCAPS_AUTO_REINIT     0x01\n#define  _SOS_DCAPS_MPU_401         0x02\n#define  _SOS_DCAPS_OPL2            0x04\n#define  _SOS_DCAPS_OPL3            0x08\n#define  _SOS_DCAPS_OPL4            0x10\n#define  _SOS_DCAPS_WAVETABLE       0x20\n#define  _SOS_DCAPS_DL_SAMPLES      0x40\n#define  _SOS_DCAPS_FIFO_DEVICE     0x80\n#define  _SOS_DCAPS_ENV_NEEDED      0x100\n#define  _SOS_DCAPS_PSEUDO_DMA1     0x200\n#define  _SOS_DCAPS_SIGNED_DATA     0x8000\n\n// file header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // number of drivers in the file\n   WORD  wDrivers;\n\n   // offset of first driver\n   WORD  lOffset;\n\n   // size of the file\n   WORD  lFileSize;\n\n} _FILEHEADER;\n\n// driver header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // offset of next driver\n   WORD  lNextDriver;\n\n   // size of current driver\n   WORD  wSize;\n\n   // id for the current device\n   WORD  wDeviceID;\n\n   // id for the type of DOS extender\n   WORD  wExtenderType;\n\n} _DRIVERHEADER;\n\n// device hardware information\ntypedef struct\n{\n   // port to be used\n   WORD  wPort;\n\n   // irq to use\n   WORD  wIRQ;\n\n   // dma channel to se\n   WORD  wDMA;\n\n   // extra parameter\n   WORD  wParam;\n\n} _SOS_HARDWARE;\n\n// structure definition for start sample\ntypedef struct\n{\n   // pointer to sample\n   LPSTR lpSamplePtr;\n\n   // size of the sample\n   WORD  dwSampleSize;\n\n   // number of times to loop the sample -1 is infinite\n   WORD  wLoopCount;\n\n   // channel to play sample on\n   WORD  wChannel;\n\n   // volume to play sample at\n   WORD wVolume;\n\n   // id for the sample\n   WORD  wSampleID;\n\n   // far pointer to the callback function\n   VOID ( far __cdecl *lpCallback )( WORD, WORD, WORD );\n\n   // port to use if driver is a non-dma background driver\n   WORD  wSamplePort;\n\n   // flags field\n   WORD  wSampleFlags;\n\n   // total length of sample including loops, etc..\n   WORD     dwSampleByteLength;\n\n   // loop point for the sample\n   WORD  dwSampleLoopPoint;\n   WORD  dwSampleLoopLength;\n\n   // pitch shifting components\n   WORD     dwSamplePitchAdd;\n   WORD    wSamplePitchFraction;\n\n   // pan components\n   WORD    wSamplePanLocation;\n   WORD    wSamplePanSpeed;\n   WORD    wSamplePanDirection;\n   WORD    wSamplePanStart;\n   WORD    wSamplePanEnd;\n\n   // delay parts\n   WORD    wSampleDelayBytes;\n   WORD    wSampleDelayRepeat;\n\n   // compression components\n   WORD     dwSampleADPCMPredicted;\n   WORD    wSampleADPCMIndex;\n\n   // root note for pitch shifting\n   WORD    wSampleRootNoteMIDI;\n\n   // filler for future upgrades\n   WORD  dwSampleTemp1;\n   WORD  dwSampleTemp2;\n   WORD  dwSampleTemp3;\n\n} _SOS_START_SAMPLE;\n\n// structure for initializing a driver\ntypedef struct\n{\n   WORD  wBufferSize;\n   LPSTR lpBuffer;\n   BOOL  wAllocateBuffer;\n   WORD  wSampleRate;\n   WORD  wParam;\n   LONG  dwParam;\n   VOID ( far *lpFillHandler )( VOID );\n   LPSTR lpDriverMemory;\n   LPSTR lpDriverMemoryCS;\n   LPSTR lpTimerMemory;\n   LPSTR lpTimerMemoryCS;\n   WORD  wTimerID;\n   WORD  wPhysical;\n\n} _SOS_INIT_DRIVER;\n\n// define for the timer types to use\n#define  _SOS_NORMAL_TIMER          0x00\n\n// enumeration for the timer types\nenum\n{\n   _TIMER_8_MONO   =     0x1000,\n   _TIMER_8_ST,\n   _TIMER_16_MONO,\n   _TIMER_16_ST,\n   _TIMER_8_MONO_ULAW,\n   _TIMER_8_ST_ULAW,\n   _TIMER_16_MONO_ULAW,\n   _TIMER_16_ST_ULAW,\n   _TIMER_8_MONO_REC,\n   _TIMER_8_MONO_ULAW_REC,\n   _TIMER_UNDEFINED_1,\n   _TIMER_UNDEFINED_2,\n   _TIMER_UNDEFINED_3,\n   _TIMER_UNDEFINED_4,\n   _TIMER_UNDEFINED_5,\n   _TIMER_UNDEFINED_6,\n   _TIMER_UNDEFINED_7,\n   _TIMER_UNDEFINED_8,\n   _TIMER_UNDEFINED_9,\n   _TIMER_UNDEFINED_A,\n   _TIMER_UNDEFINED_B,\n   _TIMER_UNDEFINED_C,\n   _TIMER_UNDEFINED_D,\n   _TIMER_UNDEFINED_E,\n   _TIMER_UNDEFINED_F,\n   _TIMER_UNDEFINED_10,\n   _TIMER_UNDEFINED_11,\n   _TIMER_UNDEFINED_12,\n   _TIMER_UNDEFINED_13,\n   _TIMER_UNDEFINED_14,\n   _TIMER_UNDEFINED_15,\n   _TIMER_UNDEFINED_16,\n   _TIMER_8_SOUND_SOURCE,\n   _TIMER_8_SOUND_SOURCE_TANDY,\n   _TIMER_8_GENERAL_PORT,\n   _TIMER_8_GENERAL_PORT_REC\n};\n\n// define for no slots available\n#define  _ERR_NO_SLOTS ( WORD )-1\n\n// error codes for the system\nenum\n{\n   _ERR_NO_ERROR,\n   _ERR_DRIVER_NOT_LOADED,\n   _ERR_INVALID_POINTER,\n   _ERR_DETECT_INITIALIZED,\n   _ERR_FAIL_ON_FILE_OPEN,\n   _ERR_MEMORY_FAIL,\n   _ERR_INVALID_DRIVER_ID,\n   _ERR_NO_DRIVER_FOUND,\n   _ERR_DETECTION_FAILURE,\n   _ERR_DRIVER_LOADED,\n   _ERR_INVALID_HANDLE,\n   _ERR_NO_HANDLES,\n   _ERR_PAUSED,\n   _ERR_NOT_PAUSED,\n   _ERR_INVALID_DATA,\n   _ERR_DRV_FILE_FAIL,\n   _ERR_INVALID_PORT,\n   _ERR_INVALID_IRQ,\n   _ERR_INVALID_DMA,\n   _ERR_INVALID_DMA_IRQ\n};\n\n// maximum number of timer events that can be registered\n#define  _TIMER_MAX_EVENTS    0x10\n\n// flags for the debugging system\n#define  _SOS_DEBUG_NORMAL       0x0000\n#define  _SOS_DEBUG_NO_TIMER     0x0001\n#define  _SOS_TIMER_DPMI         0x0002\n\n// define for types of DOS extenders\n#define  _SOS_RATIONAL           0x8000\n#define  _SOS_FLASHTECK          0x4000\n\n// defines for the types of timers for different\n// dos extenders\n#define  _SOS_TIMER_NEAR         0x8000\n#define  _SOS_TIMER_FAR          0x4000\n\n// values for callback information\nenum\n{\n   _SAMPLE_PROCESSED,\n   _SAMPLE_LOOPING,\n   _SAMPLE_DONE\n};\n\n// define for special 18.2 callback rate to dos\n#define  _TIMER_DOS_RATE   0xff00\n\n#pragma pack()\n\n#pragma aux int_3 = \"int 3\"\n\n#pragma pack( 1 )\ntypedef struct\n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned       segment;\n\tunsigned short\tnumber_available;\n\tunsigned short number_used;\n\tunsigned       page0;\n\n} EVDS_STRUCT;\n\ntypedef struct\n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned short segment;\n\tunsigned short\tID;\n\tunsigned       physical;\n\n} VDS_STRUCT;\n\n#pragma pack()\n\n#include \"sosdata.h\"\n#include \"sosfnct.h\"\n\n#endif"
  },
  {
    "path": "WIN32LIB/INCLUDE/SOSCOMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*  File              : soscomp.h\n*  Date Created      : 6/1/94\n*  Description       :\n*\n*  Programmer(s)     : Nick Skrepetos\n*  Last Modification : 10/1/94 - 11:37:9 AM\n*  Additional Notes  : Modified by Denzil E. Long, Jr.\n*\n*****************************************************************************\n*            Copyright (c) 1994,  HMI, Inc.  All Rights Reserved            *\n****************************************************************************/\n\n#ifndef  _SOS_COMPRESS\n#define  _SOS_COMPRESS\n\n/* compression types */\nenum {\n\t_ADPCM_TYPE_1,\n\t};\n\n/* define compression structure */\ntypedef struct _tagCOMPRESS_INFO {\n\tchar       *lpSource;\n\tchar       *lpDest;\n\tunsigned long dwCompSize;\n\tunsigned long dwUnCompSize;\n\tunsigned long dwSampleIndex;\n\tlong          dwPredicted;\n\tlong          dwDifference;\n\tshort         wCodeBuf;\n\tshort         wCode;\n\tshort         wStep;\n\tshort         wIndex;\n\n\tunsigned long dwSampleIndex2; //added BP for channel 2\n\tlong          dwPredicted2;   //added BP for channel 2\n\tlong          dwDifference2; \t//added BP for channel 2\n\tshort         wCodeBuf2; \t\t//added BP for channel 2\n\tshort         wCode2; \t\t\t//added BP for channel 2\n\tshort         wStep2; \t\t\t//added BP for channel 2\n\tshort         wIndex2; \t\t\t//added BP for channel 2\n\tshort         wBitSize;\n\tshort\t\t\t  wChannels;\t\t//added BP for # of channels\n\t} _SOS_COMPRESS_INFO;\n\n/* compressed file type header */\ntypedef struct _tagCOMPRESS_HEADER {\n\tunsigned long dwType;              // type of compression\n\tunsigned long dwCompressedSize;    // compressed file size\n\tunsigned long dwUnCompressedSize;  // uncompressed file size\n\tunsigned long dwSourceBitSize;     // original bit size\n\tchar          szName[16];          // file type, for error checking\n\t} _SOS_COMPRESS_HEADER;\n\n/* Prototypes */\nextern \"C\" {\n\tvoid __cdecl sosCODECInitStream(_SOS_COMPRESS_INFO *);\n\tunsigned long __cdecl sosCODECCompressData(_SOS_COMPRESS_INFO *,\tunsigned long);\n\tunsigned long __cdecl sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);\n\tunsigned long __cdecl General_sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);\n}\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/SOSDATA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdata.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces\n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DATA\n#define  _SOS_DATA\n\n#include <stddef.h>\n\n#pragma pack(4)\nextern   WORD     _sosDIGIData_Start;\nextern   WORD     _sosDIGIData_End;\nextern   WORD     _wSOSDriverLinear[];\nextern   WORD     _wSOSTimerLinear[];\nextern   LPSTR    _lpSOSDriver[];\nextern   LPSTR    _lpSOSTimer[];\nextern   LPSTR    _lpSOSDriverCS[];\nextern   LPSTR    _lpSOSTimerCS[];\nextern   BOOL     _wSOSDriverLoaded[];\nextern   BOOL     _wSOSTimerLoaded[];\nextern   BOOL     _wSOSDriverInitialized[];\nextern   WORD     _wSOSOutputRate[];\nextern   WORD     _wSOSDMABuffersize[];\nextern   LONG     _dwSOSDMABufferPhysical[];\nextern   LPSTR    _lpSOSDMABuffer[];\nextern   BOOL     _wTimerUsed;\nextern   VOID ( far *_lpSOSFillHandler[] )( VOID );\nextern   WORD     _wSOSTimerType[];\nextern   WORD     _wSOSDriverType[];\nextern   _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ];\nextern   LPWORD      _lpSOSDMAIrqCount[];\nextern   LPWORD      _lpSOSDMAFillCount[];\nextern   WORD        _wSOSTmrNextCount;\nextern   VOID ( interrupt far *_lpSOSOldTimer )( VOID );\nextern   WORD     _wSOSDriverID[];\nextern   _SOS_CAPABILITIES _sSOSDriverCaps[];\nextern   WORD        _wSOSDMAPortList[];\nextern   BYTE        _bSOSDMAChannel[];\nextern   _SOS_INIT_DRIVER     _sSOSDIGIInitDriver[];\nextern   BYTE  _pSOSDriverPath[];\nextern   BYTE  _pSOSTempDriverPath[];\nextern   BOOL  _wTIMERUsed;\nextern   WORD  _wTIMERValue;\nextern   VOID ( far * _lpTIMEREvents[] )( VOID );\nextern   WORD _wTIMEREventRate[];\nextern   WORD _dwTIMEREventFraction[];\nextern   WORD _dwTIMEREventFractionCurrent[];\nextern   BYTE  _bSOSMIDITimerSongHandler[];\nextern   BYTE  _bSOSMIDISongHandle;\nextern   WORD  _wSOSTimerMemHandle[];\nextern   WORD  _wSOSDriverMemHandle[];\nextern   WORD  _wSOSRealSeg[];\n\nextern   _FILEHEADER    _sDETFileHeader;\nextern   _DRIVERHEADER  _sDETDriverHeader;\nextern   _FILEHEADER    sLOADFileHeader;\nextern   _DRIVERHEADER  sLOADDriverHeader;\nextern   BOOL           _wDETInitialized;\nextern   WORD           _wDETLinear;\nextern   LPSTR          _lpDETDriverBuffer;\nextern   LPSTR          _lpDETDriverBufferCS;\nextern   WORD           _hDETFile;\nextern   DWORD          _dwDETDriverIndex;\nextern   WORD           _wDETDriverIndexCur;\nextern   WORD           _wDETMemHandle;\nextern   LPSOSDEVICECAPS _lpDETDeviceCaps;\nextern   _SOS_CAPABILITIES _sDETCaps;\nextern   PSTR _pSOSErrorStrings[];\nextern   BOOL _wSOSBufferAllocated[];\nextern   BOOL _wSOSSystemInitialized;\nextern   VDS_STRUCT _sSOSVDSInfo;\nextern   _SOS_FILL_INFO _sSOSFillInfo;\nextern   WORD    _wSOSTimerEventIndex;\nextern   WORD  _wSOSTimerEntered;\nextern   WORD  _wSOSDriverSize[];\nextern   WORD  _wSOSTimerSize[];\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nextern   WORD  _sosDIGIData1_Start;\nextern   WORD  _sosDIGIData1_End;\nextern   WORD  _sosDIGIData2_Start;\nextern   WORD  _sosDIGIData2_End;\nextern   BYTE  _bTIMERInstalled;\nextern   BYTE  _bTIMERDPMI;\nextern   WORD  wDetectPort;\nextern   WORD  wDetectIRQ;\nextern   WORD  wDetectDMA;\nextern   WORD  wDetectParam;\n#ifdef __cplusplus\n}\n#endif\n\n#pragma pack()\n\n#endif\n\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/SOSDEFS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdefs.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces\n                            All Rights Reserved\n****************************************************************************/\n\n\n#ifndef  _SOSDEFS_DEFINED\n#define  _SOSDEFS_DEFINED\n\n#undef   _TRUE\n#undef   _FALSE\n#undef   _NULL\nenum\n      {\n         _FALSE,\n         _TRUE\n      };\n\n#define  _NULL  0\n\n#ifndef  VOID\n#define  VOID           void\n#endif\ntypedef  int            BOOL;\ntypedef  unsigned int   UINT;\ntypedef  unsigned char  BYTE;\ntypedef  unsigned       WORD;\n#ifndef  LONG\ntypedef  signed long    LONG;\n#endif\ntypedef  unsigned long  DWORD;\n\ntypedef  BYTE  *        PBYTE;\ntypedef  char near *    PSTR;\ntypedef  WORD  *        PWORD;\ntypedef  LONG  *        PLONG;\ntypedef  VOID  *        PVOID;\n\ntypedef  BYTE  far   *  LPBYTE;\ntypedef  BYTE  far   *  LPSTR;\ntypedef  WORD  far   *  LPWORD;\ntypedef  LONG  far   *  LPLONG;\ntypedef  VOID  far   *  LPVOID;\n\ntypedef  BYTE  huge  *  HPBYTE;\ntypedef  BYTE  huge  *  HPSTR;\ntypedef  WORD  huge  *  HPWORD;\ntypedef  LONG  huge  *  HPLONG;\ntypedef  VOID  huge  *  HPVOID;\n\ntypedef  unsigned       HANDLE;\n\n#endif\n\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/SOSFNCT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosfnct.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces\n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_FUNCTIONS\n#define  _SOS_FUNCTIONS\n\n#pragma pack(4)\n\nWORD sosDIGILockMemory          (  VOID  );\nWORD sosDIGIUnLockMemory        (  VOID  );\nWORD sosDIGIInitSystem           (  LPSTR, WORD  );\nWORD sosDIGIUnInitSystem         (  VOID  );\nWORD sosDIGIInitDriver           (  WORD, _SOS_HARDWARE far *,\n                                    _SOS_INIT_DRIVER far *, WORD far *   );\nWORD sosDIGIUnInitDriver         (  WORD, BOOL, BOOL  );\nWORD sosDIGILoadDriver          (  WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD sosDIGIUnLoadDriver         (  WORD  );\nWORD sosDIGIGetDeviceCaps        (  WORD, LPSOSDEVICECAPS  );\n\n#ifdef PHARLAP\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#else\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#endif\n\nWORD sosDIGIStopSample           (  WORD, WORD  );\nWORD sosDIGISamplesPlaying       (  WORD  );\nBOOL sosDIGISampleDone           (  WORD, WORD  );\nBOOL sosDIGISampleFilling        (  WORD, WORD  );\nWORD sosDIGIStartSample          (  WORD, _SOS_START_SAMPLE far *  );\nWORD sosDIGIContinueSample       (  WORD, WORD, _SOS_START_SAMPLE far * );\n\n\nWORD  sosDIGIDetectInit          (  LPSTR  );\nWORD  sosDIGIDetectUnInit        (  VOID  );\nWORD  sosDIGIDetectFindHardware  (  WORD, _SOS_CAPABILITIES far *, WORD far * );\nWORD  sosDIGIDetectFindFirst     (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectFindNext      (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectGetSettings   (  _SOS_HARDWARE far *  );\nWORD  sosDIGIDetectGetCaps       (  WORD, _SOS_CAPABILITIES far *  );\nWORD  sosDIGIDetectVerifySettings(  _SOS_HARDWARE far *  );\nPSTR  sosGetErrorString          (  WORD  );\n\nWORD  sosDIGILoadTimer           (  WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD  sosDIGIUnLoadTimer         (  WORD  );\n\nWORD  sosTIMERRegisterEvent      ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle );\nWORD  sosTIMERInitSystem               (  WORD, WORD  );\nWORD  sosTIMERUnInitSystem             (  WORD  );\nWORD  sosTIMERSetRate                  (  WORD  );\nWORD  sosTIMERRemoveEvent              (  WORD );\nWORD  sosTIMERAlterEventRate           (  WORD, WORD  );\nWORD  sosTIMERGetEventRate             (  WORD  );\nVOID far sosTIMEROldHandler            (  VOID  );\nVOID far sosTIMERHandler               (  VOID  );\n\n// functions in soscntl.c\nWORD  sosDIGISetSampleVolume     ( WORD, WORD, WORD );\nWORD  sosDIGIGetSampleVolume     ( WORD, WORD );\nWORD  sosDIGISetChannel          ( WORD, WORD, WORD );\nWORD  sosDIGIGetChannel          ( WORD, WORD );\nWORD  sosDIGIGetBytesProcessed   ( WORD, WORD );\nWORD  sosDIGIGetLoopCount        ( WORD, WORD );\nWORD  sosDIGISetPanLocation      ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanLocation      ( WORD, WORD );\nDWORD sosDIGISetPitch            ( WORD, WORD, DWORD );\nDWORD sosDIGIGetPitch            ( WORD, WORD );\nWORD  sosDIGIGetDMAPosition      ( WORD );\nWORD  sosDIGISetPanSpeed         ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanSpeed         ( WORD, WORD );\nWORD  sosDIGIGetSampleID         ( WORD, WORD );\nWORD  sosDIGIGetSampleHandle     ( WORD, WORD );\nWORD  sosDIGISetMasterVolume     ( WORD, WORD );\n#ifdef PHARLAP\nVOID  sosFreeVDSPage          ( unsigned short, unsigned short, DWORD );\nWORD  sosAllocVDSPage         ( unsigned short *, unsigned short *, DWORD * );\n#else\nWORD  sosAllocVDSPage            ( LPSTR *, WORD *, WORD * );\nVOID  sosFreeVDSPage             ( WORD, WORD, LONG );\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef PHARLAP\nextern   int   __cdecl sosRealFree          ( int );\nextern   BOOL  __cdecl  _sos_read( WORD, LPSTR, WORD, WORD * );\nextern   int   __cdecl sosRealAlloc( int, int *, int * );\nextern   void  __cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD );\nextern   int   __cdecl sosGetCS( VOID );\nextern   int   __cdecl sosGetES( VOID );\n#else\nextern   int   __cdecl sosRealAlloc         ( int, int *, int * );\nextern   int   __cdecl sosRealFree          ( int );\n#endif\n\n// sos driver functions\nextern   WORD  __cdecl sosDRVLockMemory     ( DWORD, DWORD );\nextern   WORD  __cdecl sosDRVUnLockMemory   ( DWORD, DWORD );\nextern   void  __cdecl sosDRVGetCapsInfo    ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  __cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  __cdecl sosDRVGetCapsPtr     ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  __cdecl sosDRVInit           ( LPSTR, LPSTR, int, int, int, int, int, int );\nextern   void  __cdecl sosDRVStart          ( LPSTR, LPSTR, int, int );\nextern   void  __cdecl sosDRVSetRate        ( LPSTR, LPSTR, int );\nextern   void  __cdecl sosDRVSetAction      ( LPSTR, LPSTR );\nextern   void  __cdecl sosDRVStop           ( LPSTR, LPSTR );\nextern   void  __cdecl sosDRVUnInit         ( LPSTR, LPSTR );\nextern   void  __cdecl sosDRVGetFillInfo    ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * );\nextern   void  __cdecl sosFillSampleStructs ( PSTR, LPSTR );\nextern   WORD  __cdecl sosDetDRVExist       ( LPSTR, LPSTR );\nextern   WORD  __cdecl sosDetDRVGetSettings ( LPSTR, LPSTR );\nextern   WORD  __cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR );\nextern   WORD  __cdecl sosDIGIInitForWindows( WORD );\nextern   WORD  __cdecl sosDIGIUnInitForWindows( WORD );\nextern   LPSTR __cdecl sosAllocateFarMem      ( WORD, PSTR, WORD * );\nextern   LPSTR __cdecl sosCreateAliasCS       ( LPSTR );\nextern   VOID  __cdecl sosFreeSelector        ( LPSTR, DWORD );\nextern   LPSTR __cdecl sosMAKEDOSPtr          ( PSTR );\nextern   VOID  __cdecl sosDetDRVSetEnvString  ( DWORD, PSTR );\nextern   PSTR  __cdecl sosDetDRVGetEnvString  ( DWORD );\nextern   VOID  __cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR );\nextern   VOID  __cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR );\nextern   WORD  __cdecl sosDRVGetFreeMemory     ( VOID );\nextern   WORD  __cdecl sosDRVAllocVDSStruct    ( WORD, WORD *, WORD * );\nextern   WORD  __cdecl sosDRVFreeVDSStruct     ( WORD, WORD );\nextern   WORD  __cdecl sosDRVIsWindowsActive   ( VOID );\nextern   WORD  __cdecl sosDRVVDSGetBuffer    ( WORD );\nextern   WORD  __cdecl sosDRVVDSFreeBuffer   ( WORD );\nextern   WORD  __cdecl getDS( VOID );\nextern   WORD  __cdecl sosDRVMakeDMASelector   ( WORD );\nextern   WORD  __cdecl sosDRVFreeDMASelector   ( WORD );\n\n\nextern   void  __cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) );\nextern   void  __cdecl sosTIMERDRVUnInit( void );\nextern   void  __cdecl sosTIMERDRVHandler( void );\nextern   void  __cdecl sosTIMERDRVFHandler( void );\nextern   void  __cdecl sosTIMERDRVEnable( void );\nextern   void  __cdecl sosTIMERDRVDisable( void );\nextern   void  __cdecl sosTIMERDRVCallOld( void );\nextern   void  __cdecl sosTIMERDRVSetRate( WORD );\nextern   void  __cdecl sosDIGITimer_Start( void );\nextern   void  __cdecl sosDIGITimer_End( void );\nextern   void  __cdecl sosDIGIDrv_Start( void );\nextern   void  __cdecl sosDIGIDrv_End( void );\n#ifdef __cplusplus\n}\n#endif\n\n// external functions for handling system initialization and\n// uninitialization\nWORD  sosEXDIGInitDriver               (  WORD, WORD, WORD, LPSTR,\n                                          _SOS_HARDWARE far *, WORD *  );\nWORD  sosEXDIGIUnInitDriver            (  VOID  );\n\nWORD  sosEXDETFindDriver               (  WORD, LPSTR, _SOS_HARDWARE far *,\n                                          _SOS_CAPABILITIES far *  );\n\n// memory locking prototypes\nVOID  sosDIGICaps_Start( VOID );\nVOID  sosDIGICaps_End( VOID );\nVOID  sosDIGIErr_Start( VOID );\nVOID  sosDIGIErr_End( VOID );\nVOID  sosDIGITmr_Start( VOID );\nVOID  sosDIGITmr_End( VOID );\nVOID  sosDIGIStart_Start( VOID );\nVOID  sosDIGIStart_End( VOID );\nVOID  sosDIGIPlyng_Start( VOID );\nVOID  sosDIGIPlyng_End( VOID );\nVOID  sosDIGIRate_Start( VOID );\nVOID  sosDIGIRate_End( VOID );\nVOID  sosDIGIDone_Start( VOID );\nVOID  sosDIGIDone_End( VOID );\nVOID  sosDIGIDetec_Start( VOID );\nVOID  sosDIGIDetec_End( VOID );\nVOID  sosDIGIInit_Start( VOID );\nVOID  sosDIGIInit_End( VOID );\nVOID  sosDIGILoad_Start( VOID );\nVOID  sosDIGILoad_End( VOID );\nVOID  sosDIGICntl_Start( VOID );\nVOID  sosDIGICntl_End( VOID );\n\n#pragma pack()\n\n#endif\n\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/SOSRES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosres.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#define  _SOS_RESOURCE\n#ifndef  _SOS_RESOURCE\n#define  _SOS_RESOURCE\n\n// structure for resource file header\ntypedef struct\n{\n   // file version\n   WORD     wVersion;\n\n   // file size\n   LONG     dwFileSize;\n\n   // number of resources in file\n   WORD     wResCount;\n\n   // offset of resource data from top of file\n   LONG     dwResOffset;\n\n   // offset of sync track from top of file\n   LONG     dwSyncTrackOffset;\n\n}  _RES_FILE_HEADER;\n\n// structure for resource block header\ntypedef struct\n{\n   // resource id\n   WORD     wID;\n\n   // resource type\n   WORD     wResType;\n\n   // offset of next block\n   LONG     dwNextBlock; \n\n   // size of the current resource information\n   LONG     dwResSize;\n\n   // rate to play block at\n   WORD     wBlockRate;\n\n   // id for the sync track to use\n   WORD     wSyncTrackID;\n\n}  _RES_BLOCK_HEADER;\n\n// structure for sync mark tag\ntypedef struct _tagSYNCMARK\n{\n   // ID of the type of mark being used\n   WORD  wID;\n\n   // location in data of sync mark\n   LONG  dwSyncOffset;\n\n   // length of sync block\n   LONG  dwSyncSize;\n\n   // start sample data\n   _SOS_START_SAMPLE sampleData;\n    \n} _RES_SYNCMARK;\n\ntypedef union\n{\n   // structure for sync mark tag\n   _RES_SYNCMARK  syncMark; \n\n} _RES_TAG;\n\n// union for filter information for prepareWave\ntypedef union\n{\n   // filter type\n   WORD     wFilterID;\n\n   // structure for volume\n   struct   volume \n   {\n      WORD  wVolume;\n   };\n\n   // structure for delay\n   struct   delay\n   {  \n      WORD  wDelaySamples;\n   };\n\n} _SOS_FILTER; \n\n \n#endif\n\n\u001a"
  },
  {
    "path": "WIN32LIB/INCLUDE/SOUND.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : SOUND.H                                  *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : September 1, 1993                        *\n *                                                                         *\n *                  Last Update : September 1, 1993   [JLB]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SOUND_H\n#define SOUND_H\n\n//#define\tHMI_DRIVER\tTRUE\n//#include\t\"sos.h\"\n#include\t\"soscomp.h\"\n#include \"dsound.h\"\n\n/*\n**\tMaximum number of sound effects that may run at once.\n*/\n#define\tMAX_SFX\t\t5\n\n/*\n** Size of temp HMI low memory staging buffer.\n*/\n#define\tSECONDARY_BUFFER_SIZE\t\t(1024*32)\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/SOUNDINT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDINT.H                               *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 23, 1995   [PWG]                    *\n *                                                                         *\n * This file is the include file for the Westwood Sound Sytem defines and  *\n * routines that are handled in an interrupt.\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"sound.h\"\n\n/*\n** Defines for true and false.  These are included because we do not allow\n** the sound int to include any of the westwood standard headers.  If we\n** did, there might be too much temptation to call another library function.\n** this would be bad, because then that function would not be locked.\n*/\n#define\tFALSE\t\t0\n#define\tTRUE\t\t1\n\n/*\n** Define the different type of sound compression avaliable to the westwood\n** library.\n*/\ntypedef enum {\n\tSCOMP_NONE=0,\t\t\t// No compression -- raw data.\n\tSCOMP_WESTWOOD=1,\t\t// Special sliding window delta compression.\n\tSCOMP_SONARC=33,\t\t// Sonarc frame compression.\n\tSCOMP_SOS=99\t\t\t// SOS frame compression.\n} SCompressType;\n\n/*\n**\tThis is the safety overrun margin for the sonarc compressed\n** data frames.  This value should be equal the maximum 'order' times\n**\tthe maximum number of bytes per sample.  It should be evenly divisible\n**\tby 16 to aid paragraph alignment.\n*/\n#define\tSONARC_MARGIN\t\t\t\t32\n\n\n/*\n** Define the sample control structure which helps us to handle feeding\n** data to the sound interrupt.\n*/\n#pragma pack(1);\ntypedef struct {\n\t/*\n\t**\tThis flags whether this sample structure is active or not.\n\t*/\n\tunsigned Active;\n\t//unsigned Active:1;\n\n\t/*\n\t**\tThis flags whether the sample is loading or has been started.\n\t*/\n\t//unsigned Loading:1;\n\tunsigned Loading;\n\n\t/*\n\t**\tThis semaphore ensures that simultaneous update of this structure won't\n\t**\toccur.  This is necessary since both interrupt and regular code can modify\n\t**\tthis structure.\n\t*/\n\t//unsigned DontTouch:1;\n\tunsigned DontTouch;\n\n\t/*\n\t**\tIf this sample is really to be considered a score rather than\n\t**\ta sound effect, then special rules apply.  These largely fall into\n\t**\tthe area of volume control.\n\t*/\n\t//unsigned IsScore:1;\n\tunsigned IsScore;\n\n\t/*\n\t**\tThis is the original sample pointer. It is used to control the sample based on\n\t**\tpointer rather than handle. The handle method is necessary when more than one\n\t**\tsample could be playing simultaneously. The pointer method is necessary when\n\t**\tthe dealing with a sample that may have stopped behind the programmer's back and\n\t**\tthis occurance is not otherwise determinable.  It is also used in\n\t** conjunction with original size to unlock a sample which has been DPMI\n\t** locked.\n\t*/\n\tvoid const *Original;\n\tlong OriginalSize;\n\n\t/*\n\t**\tThese are pointers to the double buffers.\n\t*/\n\tLPDIRECTSOUNDBUFFER PlayBuffer;\n\n\t/*\n\t** Variable to keep track of the playback rate of this buffer\n\t*/\n\tint\tPlaybackRate;\n\n\t/*\n\t** Variable to keep track of the sample type ( 8 or 16 bit ) of this buffer\n\t*/\n\tint\tBitSize;\n\n\t/*\n\t** Variable to keep track of the stereo ability of this buffer\n\t*/\n\tint\tStereo;\n\n\t/*\n\t**\tThe number of bytes in the buffer that has been filled but is not\n\t**\tyet playing.  This value is normally the size of the buffer,\n\t**\texcept for the case of the last bit of the sample.\n\t*/\n\tLONG DataLength;\n\n\t/*\n\t**\tThis is the buffer index for the low buffer that\n\t**\thas been filled with data but not yet being\n\t**\tplayed.\n\t*/\n//\tshort int Index;\n\n\t/*\n\t**\tPointer into the play buffer for writing the next\n\t**  chunk of sample to\n\t**\n\t*/\n\tVOID *DestPtr;\n\n\t/*\n\t**\tThis flag indicates that there is more source data\n\t**  to copy to the play buffer\n\t**\n\t*/\n\tBOOL MoreSource;\n\n\t/*\n\t**\tThis flag indicates that the entire sample fitted inside the\n\t** direct sound secondary buffer\n\t**\n\t*/\n\tBOOL OneShot;\n\n\t/*\n\t**\tPointer to the sound data that has not yet been copied\n\t**\tto the playback buffers.\n\t*/\n\tVOID *Source;\n\n\t/*\n\t**\tThis is the number of bytes remaining in the source data as\n\t**\tpointed to by the \"Source\" element.\n\t*/\n\tLONG Remainder;\n\n\t/*\n\t**\tObject to use with Enter/LeaveCriticalSection\n\t**\n\t*/\n\tCRITICAL_SECTION AudioCriticalSection;\n\n\t/*\n\t**\tSamples maintain a priority which is used to determine\n\t**\twhich sounds live or die when the maximum number of\n\t**\tsounds are being played.\n\t*/\n\tint Priority;\n\n\t/*\n\t**\tThis is the handle as returned by sosDIGIStartSample function.\n\t*/\n\tshort int Handle;\n\n\t/*\n\t**\tThis is the current volume of the sample as it is being played.\n\t*/\n\tint Volume;\n\tint Reducer;\t\t// Amount to reduce volume per tick.\n\n\t/*\n\t**\tThis is the compression that the sound data is using.\n\t*/\n\tSCompressType Compression;\n\tshort int TrailerLen;\t\t\t\t\t\t// Number of trailer bytes in buffer.\n\tBYTE Trailer[SONARC_MARGIN];\t\t// Maximum number of 'order' samples needed.\n\n\n\tDWORD Pitch;\n\tWORD Flags;\n\n\t/*\n\t**\tThis flag indicates whether this sample needs servicing.\n\t**\tServicing entails filling one of the empty low buffers.\n\t*/\n\tshort int Service;\n\n\t/*\n\t**\tThis flag is TRUE when the sample has stopped playing,\n\t**\tBUT there is more data available.  The sample must be\n\t**\trestarted upon filling the low buffer.\n\t*/\n\tBOOL Restart;\n\n\t/*\n\t**\tStreaming control handlers.\n\t*/\n\tBOOL (*Callback)(short int id, short int *odd, VOID **buffer, LONG *size);\n\tVOID\t*QueueBuffer;\t// Pointer to continued sample data.\n\tLONG\tQueueSize;\t\t// Size of queue buffer attached.\n\tshort int\tOdd;\t\t\t\t// Block number tracker (0..StreamBufferCount-1).\n\tint\tFilePending;\t// Number of buffers already filled ahead.\n\tlong\tFilePendingSize;\t// Number of bytes in last filled buffer.\n\n\t/*\n\t**\tThe file variables are used when streaming directly off of the\n\t**\thard drive.\n\t*/\n\tint\tFileHandle;\t\t// Streaming file handle (ERROR = not in use).\n\tVOID\t*FileBuffer;\t// Temporary streaming buffer (allowed to be freed).\n\t/*\n\t** The following structure is used if the sample if compressed using\n\t** the sos 16 bit compression Codec.\n\t*/\n\n\t_SOS_COMPRESS_INFO sosinfo;\n\n\n} SampleTrackerType;\n\n\ntypedef struct LockedData {\n\tunsigned int \t\tDigiHandle; \t\t\t// = -1;\n\tBOOL \t\t\t\t\tServiceSomething;\t\t// = FALSE;\n\tlong \t\t\t\t\tMagicNumber; \t\t\t// = 0xDEAF;\n\tVOID \t\t\t\t\t*UncompBuffer;\t\t\t// = NULL;\n\tlong \t\t\t\t\tStreamBufferSize; \t// = (2*SECONDARY_BUFFER_SIZE)+128;\n\tshort \t\t\t\tStreamBufferCount; \t// = 32;\n\tSampleTrackerType SampleTracker[MAX_SFX];\n\tunsigned int\t\tSoundVolume;\n\tunsigned int\t\tScoreVolume;\n\tBOOL\t\t\t\t\t_int;\n} LockedDataType;\n\nextern LockedDataType LockedData;\n#pragma pack(4);\n\nvoid Init_Locked_Data(void);\nlong Simple_Copy(void ** source, long * ssize, void ** alternate, long * altsize, void **dest, long size);\nlong Sample_Copy(SampleTrackerType *st, void ** source, long * ssize, void ** alternate, long * altsize, void * dest, long size, SCompressType scomp, void * trailer, short int *trailersize);\nVOID far __cdecl maintenance_callback(VOID);\nVOID __cdecl far DigiCallback(unsigned int driverhandle, unsigned int callsource, unsigned int sampleid);\nvoid far HMI_TimerCallback(void);\nvoid *Audio_Add_Long_To_Pointer(void const *ptr, long size);\nvoid\tDPMI_Unlock(VOID const *ptr, long const size);\nextern \"C\" {\n\tvoid __cdecl Audio_Mem_Set(void const *ptr, unsigned char value, long size);\n//\tvoid\tMem_Copy(void *source, void *dest, unsigned long bytes_to_copy);\n\tlong  __cdecl Decompress_Frame(void * source, void * dest, long size);\n\tint\t__cdecl Decompress_Frame_Lock(void);\n\tint\t__cdecl Decompress_Frame_Unlock(void);\n\tint\t__cdecl sosCODEC_Lock(void);\n\tint\t__cdecl sosCODEC_Unlock(void);\n\tvoid\t__GETDS(void);\n}\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/STAMP.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; This is the control structure at the start of a loaded icon set.  It must match\n; the structure in ICONSET.C!  This structure MUST be a multiple of 16 bytes long.\n\nifdef NO_WAY_THIS_WILL_BE_DEFINED_HAHAHAHA\n\n\tSTRUC\tIControl_Type\nWidth\t\tDW\t?\t; Width in pixels (per icon).\nHeight\t\tDW\t?\t; Height in pixels (per icon).\nCount\t\tDW\t?\t; Number of icons in this set.\nAllocated\tDW\t?\t; Was this iconset allocated?\nSize\t\tDD\t?\t; Size of entire iconset memory block.\nIcons\t\tDD\t?\t; Offset from buffer start to icon data.\nPalettes\tDD\t?\t; Offset from buffer start to palette data.\nRemaps\t\tDD\t?\t; Offset from buffer start to remap index data.\nTransFlag\tDD\t?\t; Offset for transparency flag data.\nMap\t\tDD\t?\t; Icon map offset.\n\tENDS\n\nelse\n\n\n\tSTRUC\tIControl_Type\n\nWidth\t\tDW\t?\t; Width in pixels (per icon).\nHeight\t\tDW\t?\t; Height in pixels (per icon).\nCount\t\tDW\t?\t; Number of icons in this set.\nAllocated\tDW\t?\t; Was this iconset allocated?\nMapWidth\tDW\t?\nMapHeight\tDW\t?\nSize\t\tDD\t?\t; Size of entire iconset memory block.\nIcons\t\tDD\t?\t; Offset from buffer start to icon data.\nPalettes\tDD\t?\t; Offset from buffer start to palette data.\nRemaps\t\tDD\t?\t; Offset from buffer start to remap index data.\nTransFlag\tDD\t?\t; Offset for transparency flag data.\nColorMap\tDD\t?\nMap\t\tDD\t?\t; Icon map offset.\n\tENDS\n\nendif\n\nICON256\tEQU\t1\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/STRUCTS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 Examples                         *\n *                                                                         *\n *                    File Name : STRUCTS.H                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/SVGAPRIM.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : SVGAPRIM.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : December 8, 1994                         *\n;*                                                                         *\n;*                  Last Update : December 8, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n\n; Externs from VIDEO.CPP module of the VIDEO library\nGLOBAL BankTable\t\t\t:DWORD\nGLOBAL VesaFunc\t\t\t:DWORD\nGLOBAL XRes\t\t\t\t\t:DWORD\nGLOBAL YRes\t\t\t\t\t:DWORD\nGLOBAL CurrentMode\t\t:DWORD\nglobal cpu_video_page\t:dword\nglobal cpu_page_limit   :dword\n\n\n; Externs from VESA.ASM module of the SVGAPRIM library\nGLOBAL Vesa_Asm_Set_Win\t\t:NEAR\nGLOBAL Vesa_Asm_Next_Win\t\t:NEAR\n\n; Externs from VGETPIX.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Get_Pixel          \t:NEAR\n\n; Externs from VPUTTPIX.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Put_Pixel \t\t:NEAR\n\n\n; Externs from VCLEAR.ASM module of the MCGA/SVGAPRIM library\nGLOBAL Vesa_Clear\t\t\t:NEAR\n\n; Externs from VBITBLIT.ASM module of the MCGA/SVGAPRIM library\nGLOBAL Linear_Blit_To_Vesa\t\t:NEAR\nGLOBAL Vesa_Blit_To_Linear\t\t:NEAR\nGLOBAL Vesa_Blit_To_Vesa\t\t:NEAR\n\n; Externs from VTOBUFF.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_To_Buffer\t\t:NEAR\n\n; Externs from VTOPAGE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Buffer_To_Page\t\t:NEAR\n\n; Externs from VSCALE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Linear_Scale_To_Vesa \t\t:NEAR\nGLOBAL Vesa_Scale_To_Linear\t\t:NEAR\nGLOBAL Vesa_Scale_To_Vesa \t\t:NEAR\n\n\n; Externs from VSCALE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Print\t \t\t:NEAR\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/TILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the TILE Library                 *\n *                                                                         *\n *                    File Name : TILE.H                                   *\n *                                                                         *\n *                   Programmer : Barry W. Green                           *\n *                                                                         *\n *                   Start Date : February 2, 1995                         *\n *                                                                         *\n *                  Last Update : February 2, 1995 [BWG]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TILE_H\n#define TILE_H\n\n/*=========================================================================*/\n/* The following prototypes are for the file: ICONSET.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid * Load_Icon_Set(char const *filename, void *iconsetptr, long buffsize);\nvoid Free_Icon_Set(void const *iconset);\nlong Get_Icon_Set_Size(void const *iconset);\nint Get_Icon_Set_Width(void const *iconset);\nint Get_Icon_Set_Height(void const *iconset);\nvoid * Get_Icon_Set_Icondata(void const *iconset);\nvoid * Get_Icon_Set_Trans(void const *iconset);\nvoid * Get_Icon_Set_Remapdata(void const *iconset);\nvoid * Get_Icon_Set_Palettedata(void const *iconset);\nint Get_Icon_Set_Count(void const *iconset);\nvoid * Get_Icon_Set_Map(void const *iconset);\n#if (0)\n/*\n** This is the control structure at the start of a loaded icon set.  It must match\n** the structure in WWLIB.I!  This structure MUST be a multiple of 16 bytes long.\n*/\ntypedef struct {\n\tshort\tWidth;\t\t\t// Width of icons (pixels).\n\tshort\tHeight;\t\t\t// Height of icons (pixels).\n\tshort\tCount;\t\t\t// Number of (logical) icons in this set.\n//\tBOOL\tAllocated;\t\t// Was this iconset allocated?\n\tshort\tAllocated;\t\t// Was this iconset allocated?\n\tlong\tSize;\t\t\t\t// Size of entire iconset memory block.\n\tunsigned char *Icons;\t\t\t// Offset from buffer start to icon data.\n\tlong\tPalettes;\t\t// Offset from buffer start to palette data.\n\tlong\tRemaps;\t\t\t// Offset from buffer start to remap index data.\n\tlong\tTransFlag;\t\t// Offset for transparency flag table.\n\tunsigned char *Map;\t\t\t\t// Icon map offset (if present).\n} IControl_Type;\n#endif\t//(0)\n\ntypedef struct {\n\tshort\tWidth;\t\t\t// Width of icons (pixels).\n\tshort\tHeight;\t\t\t// Height of icons (pixels).\n\tshort\tCount;\t\t\t// Number of (logical) icons in this set.\n\tshort\tAllocated;\t\t// Was this iconset allocated?\n\tshort MapWidth;\t\t// Width of map (in icons).\n\tshort MapHeight;\t\t// Height of map (in icons).\n\tlong\tSize;\t\t\t\t// Size of entire iconset memory block.\n\tlong\tIcons;\t\t\t// Offset from buffer start to icon data.\n//\tunsigned char * Icons;\t// Offset from buffer start to icon data.\n\tlong\tPalettes;\t\t// Offset from buffer start to palette data.\n\tlong\tRemaps;\t\t\t// Offset from buffer start to remap index data.\n\tlong\tTransFlag;\t\t// Offset for transparency flag table.\n\tlong\tColorMap;\t\t// Offset for color control value table.\n\tlong\tMap;\t\t\t\t// Icon map offset (if present).\n//\tunsigned char * Map;\t\t\t\t// Icon map offset (if present).\n} IControl_Type;\n\n\n#endif //TILE_H\n\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/TIMER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Timer Class Functions                    *\n *                                                                         *\n *                    File Name : TIMER.H                                  *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : July 6, 1994                             *\n *                                                                         *\n *                  Last Update : July 12, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TIMER_H\n#define TIMER_H\n\n\n#ifndef WIN32\n#define WIN32 1\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#endif\n#include <windows.h>\n#include <windowsx.h>\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TIMERA.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// Externs /////////////////////////////////////////////\nextern BOOL \t\tTimerSystemOn;\nextern\tHANDLE\tTimerThreadHandle;\t\t//Handle of timer thread\nextern\tint\t\tInTimerCallback;\t\t\t//true if we are currently in a callback\n\n\n/*=========================================================================*/\ntypedef enum BaseTimerEnum {\n\tBT_SYSTEM,\t\t\t// System timer (60 / second).\n\tBT_USER\t\t\t\t// User controllable timer (? / second).\n} BaseTimerEnum;\n\nclass TimerClass {\n \tpublic:\n\t\t// Constructor.  Timers set before low level init has been done will not\n\t\t// be able to be 'Started' or 'on' until timer system is in place.\n\t\tTimerClass(BaseTimerEnum timer=BT_SYSTEM, BOOL start=FALSE);\n\n\t\t// No destructor.\n\t\t~TimerClass(void){}\n\n\t\t//\n\t\tlong Set(long value, BOOL start=TRUE);\t// Set initial timer value.\n\t\tlong Stop(void);\t\t\t\t// Pause timer.\n\t\tlong Start(void);\t\t\t\t// Resume timer.\n\t\tlong Reset(BOOL start=TRUE);\t// Reset timer to zero.\n\t\tlong Time(void);\t\t\t\t// Fetch current timer value.\n\n\tprotected:\n\t\tlong Started;\t\t\t\t\t// Time last started (0 == not paused).\n\t\tlong Accumulated;\t\t\t\t//\tTotal accumulated ticks.\n\n\tprivate:\n//\t\tlong (*Get_Ticks)(void);\t// System timer fetch.\n\t\tBaseTimerEnum\tTickType;\n\t\tlong Get_Ticks (void);\n};\n\n\ninline long TimerClass::Reset(BOOL start)\n{\n\treturn(Set(0, start));\n}\n\n\nclass CountDownTimerClass : private TimerClass {\n\tpublic:\n\t\t// Constructor.  Timers set before low level init has been done will not\n\t\t// be able to be 'Started' or 'on' until timer system is in place.\n\t\tCountDownTimerClass(BaseTimerEnum timer, long set, int on=FALSE);\n\t\tCountDownTimerClass(BaseTimerEnum timer=BT_SYSTEM, int on=FALSE);\n\n\t\t// No destructor.\n\t\t~CountDownTimerClass(void){}\n\n\t\t// Public functions\n\t\tlong Set(long set, BOOL start=TRUE);\t// Set count down value.\n\t\tlong Reset(BOOL start=TRUE);\t// Reset timer to zero.\n\t\tlong Stop(void);\t\t\t// Pause timer.\n\t\tlong Start(void);\t\t\t// Resume timer.\n\t\tlong Time(void);\t\t\t// Fetch current count down value.\n\n\tprotected:\n\t\tlong DelayTime;\t\t\t// Ticks remaining before countdown timer expires.\n};\n\ninline long CountDownTimerClass::Stop(void)\n{\n\tTimerClass::Stop();\n\treturn(Time());\n}\n\ninline long CountDownTimerClass::Start(void)\n{\n\tTimerClass::Start();\n\treturn(Time());\n}\n\ninline long CountDownTimerClass::Reset(BOOL start)\n{\n\treturn (TimerClass::Reset(start));\n}\n\n\n\n\nclass WinTimerClass {\n\n\tpublic:\n\t\tWinTimerClass ( UINT freq=60 , BOOL partial=0 );\n\t\t~WinTimerClass();\n\n\t\tvoid \t\tUpdate_Tick_Count ( void );\n\t\tunsigned\tGet_System_Tick_Count ( void );\n\t\tunsigned\tGet_User_Tick_Count ( void );\n\n\tprivate:\n\n\t\tunsigned\t\tTimerHandle;\t//Handle for windows timer event\n\t\tunsigned\t\tFrequency;\t\t//Frequency of our windows timer in ticks per second\n\n\t\tunsigned\t\tTrueRate;\t\t//True rate of clock. (only use word)\n\t\tunsigned\t\tSysTicks;\t\t//Tick count of timer.\n\t\tunsigned\t\tUserTicks;\t\t//Tick count of timer.\n\t\tunsigned\t\tUserRate;\t\t//Desired rate of timer.\n\n\n};\n\n\nextern\tWinTimerClass\t*WindowsTimer;\n\n\n\n\n\n\n\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// externs  //////////////////////////////////////////\n#ifndef FUNCTION_H\nextern TimerClass\t\t\t\t\tTickCount;\n#endif\nextern CountDownTimerClass\t\tCountDown;\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// Prototypes //////////////////////////////////////////\n\nextern \"C\" {\n\tlong __cdecl Get_System_Tick_Count(void);\n\tlong __cdecl Get_User_Tick_Count(void);\n\tvoid far __cdecl Timer_Interrupt_Func(void);\n//\tlong Get_Num_Interrupts(unsigned int realmode);\n\tvoid __cdecl Disable_Timer_Interrupt(void);\n\tvoid __cdecl Enable_Timer_Interrupt(void);\n}\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TIMER.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nBOOL __cdecl Init_Timer_System(unsigned int freq, int partial = FALSE);\nBOOL __cdecl Remove_Timer_System(VOID);\n\n\n#endif // TIMER_H\n\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/VIDEO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : 32 bit library                           *\n *                                                                         *\n *                    File Name : VIDEO.H                                  *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef VIDEO_H\n#define VIDEO_H\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n/*=========================================================================*/\n/*\tThe machine can be in one of the following graphic modes.  The global\t*/\n/*\tGraphicMode is set to one of these values.\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tCGA_MODE\t\t\t\t\t4\t\t\t// DOS 320x200 4 color mode\n#define\tTGA_MODE\t\t\t\t\t9\t\t\t// TANDY 320x200 16 color mode\n#define\tEGA_MODE\t\t\t\t\t13\t\t\t// DOS 320x200 16 color mode\n#define\tMCGA_MODE\t\t\t\t0x13\t\t// DOS 320x200 256 color mode\n#define\tVGA_MODE\t\t\t\t\t0x13\t\t// DOS 320x200 256 color mode\n#define\tEEGA_MODE\t\t\t\t14\t\t\t// DOS 640x400 16 color mode\n#define\tETGA_MODE\t\t\t\t9\t\t\t// TANDY 640x400 16 color mode\n#define\tHGA_MODE\t\t\t\t\t7\t\t\t// DOS 768x400 2 color mode\n#define\tTXT_MODE\t\t\t\t\t3\t\t\t// DOS plain old color text mode\n#define\tVESA_640X400_256\t\t0x100\t\t// VESA 640x400 256 color mode\n#define\tVESA_640X480_256\t\t0x101\t\t// VESA 640x480 256 color mode\n#define\tVESA_800X600_256\t\t0x103\t\t// VESA 800x600 256 color mode\n#define\tVESA_1024X768_256\t\t0x105\t\t//\tVESA 1024x768 256 color mode\n#define\tVESA_1280X400_256\t\t0x107\t\t// VESA 1280x400 256 color mode\n#define\tVESA_TEXT_80X60\t\t0x108\t\t// VESA 80x60 text mode\n#define\tVESA_TEXT_132X25\t\t0x109\t\t// VESA 132x25 text mode\n#define\tVESA_TEXT_132X60\t\t0x10C\t\t// VESA 132x60 text mode\n#define\tRESET_MODE\t\t\t\t-1\n#define\tUNINITIALIZED_MODE\t-1\n#define\tVESA_MIN \t\t\t\tVESA_640X400_256\n#define\tVESA_MAX\t\t\t\t\tVESA_TEXT_132X60\n\n/*=========================================================================*/\n/* Define the maximum number of bank entries\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tMAX_BANK_ENTRIES\t\t((1280L*1024L)/65536L)\n\n\n/*=========================================================================*\n * VesaInfoType - General info about this VESA implementation\t\t\t\t\t*\n *                (Filled in by VESA BIOS Function 0)\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Signature    - Will always be 'VESA'\t\t\t\t\t\t\t\t\t\t\t\t*\n * Version      - Version #\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OEMString    - OEM ID string\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Capabilities - Not defined by VESA yet\t\t\t\t\t\t\t\t\t\t\t\t*\n * AvailModes   - List of available modes; terminated with -1 (0xffff)\t\t*\n * TotalMemory  - ???\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Reserved     - Pads structure to 256 bytes total\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n#ifdef NOT_FOR_WIN95\ntypedef struct {\n\tchar    Signature[4];\n\tshort   Version;\n\tREALPTR OEMString;\n\tlong    Capabilities;\n\tREALPTR AvailModes;\n\tshort   TotalMemory;\n\tchar    Reserved[236];\n} VesaInfoType;\n\n#endif //NOT_FOR_WIN95\n\n/*=========================================================================*\n * VesaModeInfoType - Info about this VESA mode\t\t\t\t\t\t\t\t\t\t*\n *                    (Filled in by VESA BIOS Function 1)\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Attributes       - bit 0: 1 = mode is supported\t\t\t\t\t\t\t\t\t*\n *                    bit 1: 1 = optional info available\t\t\t\t\t\t\t*\n *                    bit 2: 1 = std BIOS output funcs valid in this mode\t*\n *                    bit 3: 0 = monochrome, 1 = color\t\t\t\t\t\t\t*\n *                    bit 4: 0 = text mode, 1 = graphics\t\t\t\t\t\t\t*\n * WinA_Attributes  - bit 0 = win exists, bit 1=readable, bit 2= writable\t*\n * WinB_Attributes  - bit 0 = win exists, bit 1=readable, bit 2= writable\t*\n * WinGranularity   - smallest address boundary window can be placed upon;\t*\n *                    size is in KB (ie 64, 32, 4)\t\t\t\t\t\t\t\t\t*\n * WinSize          - size of windows in KB (ie 64, 32)\t\t\t\t\t\t\t*\n * WinA_Segment     - location of Window A in CPU space (usually 0xa000)\t*\n * WinB_Segment     - location of Window B in CPU space (usually 0xb000)\t*\n * WinFunc          - address of window-setting function (This is provided *\n *                    as an alternative to Int 10 for speed.)\t\t\t\t\t*\n * BytesPerScanline - # bytes per scan line\t\t\t\t\t\t\t\t\t\t\t*\n * \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Optional info (available if bit 1 of Attributes is set):\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * XRes             - X-resolution\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * YRes             - Y-resolution\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * XCharSize        - Horizontal size of char cell\t\t\t\t\t\t\t\t\t*\n * YCharSize        - Vertical size of char cell\t\t\t\t\t\t\t\t\t*\n * NumPlanes        - # of memory planes (???)\t\t\t\t\t\t\t\t\t\t*\n * BitsPerPixel     - # bites per pixel\t\t\t\t\t\t\t\t\t\t\t\t*\n * NumBanks         - # of banks (ie planes)\t\t\t\t\t\t\t\t\t\t\t*\n * MemoryModel      - 00h = Text mode\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                    01h = CGA mode\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                    02h = Hercules\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                    03h = 4 plane planar mode\t\t\t\t\t\t\t\t\t\t*\n *                    04h = packed pixel mode (1 byte/pixel)\t\t\t\t\t*\n *                    05h = non-chain 4, 256-color mode\t\t\t\t\t\t\t*\n *                    06-0Fh = \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                    10-FFh = OEM-specific\t\t\t\t\t\t\t\t\t\t\t*\n * BankSize         - Bank size in KB\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n#ifdef NOT_FOR_WIN95\ntypedef struct {\n\tshort   Attributes;\n\tchar    WinA_Attributes;\n\tchar    WinB_Attributes;\n\tshort   WinGranularity;\n\tshort   WinSize;\n\tshort   WinA_Segment;\n\tshort   WinB_Segment;\n\tREALPTR WinFunc;\n\tshort   BytesPerScanline;\n\tshort   XRes;\n\tshort   YRes;\n\tchar    XCharSize;\n\tchar    YCharSize;\n\tchar    NumPlanes;\n\tchar    BitsPerPixel;\n\tchar    NumBanks;\n\tchar    MemoryModel;\n\tchar    BankSize;\n\tchar    NumInputPages;\n\tchar    Reserved;\n\tchar    RedMaskSize;\n\tchar    RedFieldPosition;\n\tchar    GreenMaskSize;\n\tchar    GreenFieldPosition;\n\tchar    BlueMaskSize;\n\tchar    BlueFieldPosition;\n\tchar    RsvdMaskSize;\n\tchar    RsvdFieldPosition;\n\tchar    DirectColorModeInfo;\n\tchar    pad[216];\n} VesaModeInfoType;\n\nextern REALPTR\t VesaFunc;\n\n#endif //NOT_FOR_WIN95\n\n\nextern \"C\" {\nextern\tint\tGraphicMode;\nextern\tlong\tXRes;\nextern\tlong\tYRes;\n\nextern long\t\t BankTable [];\nextern unsigned long RMVesaVector ;\nextern unsigned long RMVesaRegs ;\n}\n\n/*=========================================================================*/\n/* The following prototypes are for the file: VIDEO.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern \"C\" int Set_Video_Mode(int mode);\nint Get_Video_Mode(void);\nvoid Update_Video_Mode (void) ;\nvoid Vesa_Info(void);\nvoid Vesa_Set_Window(long grain_num);\nint Get_Original_Video_Mode(void);\nvoid Set_Original_Video_Mode(int mode);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: INITDLAY.CPP\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\nextern VOID Init_Delay(VOID);\nextern BOOL VertBlank;\n\n/*=========================================================================*/\n/* The following prototypes are for the file: VERTBLNK.ASM\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\nextern \"C\" {\n\textern WORD Get_Vert_Blank(VOID);\n\textern VOID Wait_Vert_Blank(BOOL blank);\n}\n\n/*=========================================================================*/\n\n#endif // VIDEO_H"
  },
  {
    "path": "WIN32LIB/INCLUDE/WINCOMM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer/ WW Library                                *\n *                                                                                             *\n *                    File Name : WINCOMM.H                                                    *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 1/10/96                                                      *\n *                                                                                             *\n *                  Last Update : January 10th 1996 [ST]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *                                                                                             *\n *   These classes was created to replace the greenleaf comms functions used in C&C DOS with   *\n *  WIN32 API calls.                                                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef WIN32\n#define\tWIN32\n#define\t_WIN32\n#endif\t//WIN32\n#include <windows.h>\n\ntypedef enum WinCommDialMethodType {\n\tWC_TOUCH_TONE = 0,\n\tWC_PULSE\n} WinCommDialMethodType;\n\n\n\n#define\tCOMMSUCCESS\t\t0\n#define \tASTIMEOUT      -10\n#define\tCOMMUSERABORT\t-16\n\n\n/*\n** The size of our serial buffer within the class.\n**\n** !!!!!! THIS MUST BE  A POWER OF 2 !!!!!!\n**\n*/\n#define SIZE_OF_WINDOWS_SERIAL_BUFFER 2048\n\n\n\n/*\n** WinModemClass.\n**\n** This class provides access to modems under Win95. The functions are designed to be more or less\n** drop in replacements for the Grenleaf comms functions.\n*/\n\nclass WinModemClass\n{\n\n\tpublic:\n\n\t\t\t\t\tWinModemClass (void);\t\t//WinModemClass Contructor\n\t\tvirtual\t~WinModemClass (void);\t\t//WinModemClass Destructor\n\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Serial port open should be called to get a handle to the COM port\n\t\t\t\t\t** This needs to be called first as other class members rely on the handle\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: PortOpenGreenleafFast\n\t\t\t\t\t*/\n\t\t//virtual\tHANDLE\tSerial_Port_Open (int port, int baud, int parity, int wordlen, int stopbits);\n\t\tvirtual\tHANDLE\tSerial_Port_Open (char *device_name, int baud, int parity, int wordlen, int stopbits, int flowcontrol);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** This function releases the COM port handle and should be called after\n\t\t\t\t\t** communications have finished\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: PortClose\n\t\t\t\t\t*/\n\t\t\t\t\tvoid\t\tSerial_Port_Close (void);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** This member copies any bytes from the internal class serial buffer\n\t\t\t\t\t** into your user buffer.\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: ReadBuffer\n\t\t\t\t\t*/\n\t\t\t\t\tint\t\tRead_From_Serial_Port (unsigned char *dest_ptr, int buffer_len);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Write chars to the serial port\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: WriteBuffer\n\t\t\t\t\t*/\n\t\t\t\t\tvoid\t\tWrite_To_Serial_Port (unsigned char *buffer, int length);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Wait for the outgoing buffer to empty\n\t\t\t\t\t*/\n\t\t\t\t\tvoid\t\tWait_For_Serial_Write (void);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Set the dial type to DIAL_TOUCH_TONE or DIAL_PULSE\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: HMSetDiallingMethod\n\t\t\t\t\t*/\n\t\tvirtual\tvoid\t\tSet_Modem_Dial_Type (WinCommDialMethodType method);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Get the status of the modem control lines\n\t\t\t\t\t** Possible flags are: CTS_SET DSR_SET RI_SET & CD_SET\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: GetModemStatus\n\t\t\t\t\t*/\n\t\tvirtual\tunsigned\tGet_Modem_Status (void);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Set the DTR line to the given state\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: SetDtr\n\t\t\t\t\t*/\n\t\tvirtual\tvoid\t\tSet_Serial_DTR (BOOL state);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Get the result code from the modem after issuing an 'AT' command\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: HMInputLine\n\t\t\t\t\t*/\n\t\tvirtual\tint\t\tGet_Modem_Result (int delay, char *buffer, int buffer_len);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Issue a dial command to the modem.\n\t\t\t\t\t** Use Set_Modem_Dial_Type to select pulse or tone dial\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: HMDial\n\t\t\t\t\t*/\n\t\tvirtual\tvoid\t\tDial_Modem (char *dial_number);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Send a command to the modem. This is usually an 'AT' command.\n\t\t\t\t\t** Function will optionally retry until 'OK' is received.\n\t\t\t\t\t*/\n\t\tvirtual\tint\t\tSend_Command_To_Modem (char *command, char terminator, char *buffer, int buflen, int delay, int retries);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Sets a pointer to a function that will be called for each incoming serial char\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: HMSetUpEchoRoutine\n\t\t\t\t\t*/\n\t\tvirtual\tvoid\t\tSet_Echo_Function (void(*func)(char c));\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Sets a pointer to a function that will be called if ESC is pressed during a dial\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: HMSetUpAbortKey\n\t\t\t\t\t*/\n\t\tvirtual\tvoid\t\tSet_Abort_Function (int (*func)(void));\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Member to allow access to the serial port handle\n\t\t\t\t\t*/\n\t\t\t\t\tHANDLE\tGet_Port_Handle(void);\n\n\t\t/*\n\t\t** Status vars for debugging purposes\n\t\t*/\n\t\tint FramingErrors;\n\t\tint IOErrors;\n\t\tint BufferOverruns;\n\t\tint InBufferOverflows;\n\t\tint ParityErrors;\n\t\tint OutBufferOverflows;\n\t\tint InQueue;\n\t\tint OutQueue;\n\n\t\t/*\n\t\t** Modem send result codes\n\t\t*/\n\t\tenum SendModemEnum {\n\t\t\tMODEM_CMD_TIMEOUT = 0,\n\t\t\tMODEM_CMD_OK,\n\t\t\tMODEM_CMD_0,\n\t\t\tMODEM_CMD_ERROR\n\t\t};\n\n\n\t\t/*\n\t\t** Enums for modem status flags\n\t\t*/\n\t\tenum {\n\t\t\tCTS_SET  = 0x10,\n\t\t\tDSR_SET  = 0x20,\n          RI_SET   = 0x40,\n          CD_SET   = 0x80\n       };\n\n\n\tprotected:\n\n\n\t\t/*\n\t\t** Copy incoming data from the windows file buffer into the internal class buffer\n\t\t*/\n\t\tBOOL\t\t\t\t\t\t\tRead_Serial_Chars(void);\n\n\t\t/*\n\t\t** Pointer to the internal class circular buffer for incoming data\n\t\t*/\n\t\tunsigned char\t\t\t\t*SerialBuffer;\n\n\t\t/*\n\t\t** Overlap object for asyncronous reads from the serial port\n\t\t*/\n\t\tOVERLAPPED\t\t\t\t\tReadOverlap;\n\n\t\t/*\n\t\t** Overlap object for asyncronous writes to the serial port\n\t\t*/\n\t\tOVERLAPPED\t\t\t\t\tWriteOverlap;\n\n\t\t/*\n\t\t** Flag that there is no outstanding incoming data in the windows buffer\n\t\t*/\n\t\tBOOL\t\t\t\t\t\t\tWaitingForSerialCharRead;\n\n\t\t/*\n\t\t** Flag that we are waiting for the last write to port operation to complete\n\t\t*/\n\t\tBOOL\t\t\t\t\t\t\tWaitingForSerialCharWrite;\n\n\t\t/*\n\t\t** Head and Tail pointers for our internal serial buffer\n\t\t*/\n\t\tint\t\t\t\t\t\t\tSerialBufferReadPtr;\n\t\tint\t\t\t\t\t\t\tSerialBufferWritePtr;\n\n\t\t/*\n\t\t** Windows handle to the COM port device\n\t\t*/\n\t\tHANDLE\t\t\t\t\t\tPortHandle;\n\n\t\t/*\n\t\t** Dialing method - DIAL_TOUCH_TONE or DIAL_PULSE\n\t\t*/\n\t\tWinCommDialMethodType\tDialingMethod;\n\n\t\t/*\n\t\t** Pointer to function for echoing incoming data - can be NULL\n\t\t*/\n\t\tvoid \t\t\t\t\t\t\t(*EchoFunction)(char c);\n\n\t\t/*\n\t\t** Pointer to function for aborting when ESC pressed - can be NULL\n\t\t*/\n\t\tint\t\t\t\t\t\t\t(*AbortFunction)(void);\n\n\t\t/*\n\t\t** Serial buffer for asyncronous reads\n\t\t*/\n\t\tchar\t\t\t\t\t\t\tTempSerialBuffer[SIZE_OF_WINDOWS_SERIAL_BUFFER];\n};\n\n\n\n\n\n\n\n\n\n\n/*\n** WinNullModemClass.\n**\n** This class provides access to serial ports under Win95. The functions are designed to be more or less\n** drop in replacements for the Grenleaf comms functions.\n**\n** This class just overloads the WinModemClass members that arent required for direct serial communications\n** via a 'null modem' cable.\n*/\nclass WinNullModemClass : public WinModemClass\n{\n\n\tpublic:\n\n\t\tvirtual\tinline\tvoid\t\tSet_Modem_Dial_Type (int){};\n\t\tvirtual\tinline\tunsigned\tGet_Modem_Status (void){return (0);};\n\t\tvirtual\tinline\tvoid\t\tSet_Serial_DTR (BOOL){};\n\t\tvirtual\tinline\tint\t\tGet_Modem_Result (int, char*, int){return(0);};\n\t\tvirtual\tinline\tvoid\t\tDial_Modem (char*){};\n\t\tvirtual\tinline\tint\t\tSend_Command_To_Modem (char*, char, char*, int, int, int){return (0);};\n\t\tvirtual\tinline\tvoid\t\tSet_Echo_Function (void(*)(char)){};\n\t\tvirtual\tinline\tvoid\t\tSet_Abort_Function (int(*)(void)){};\n\n};\n\n\nextern WinModemClass *SerialPort;\n\n\n\n\n\n\n\n\n\n//\n//\n// This bit swiped from the SDK because its not in the Watcom headers yet\n//\n//\n\n/************************************************************************\n*                                                                       *\n*   mcx.h -- This module defines the 32-Bit Windows MCX APIs            *\n*                                                                       *\n*   Copyright (c) 1990-1995, Microsoft Corp. All rights reserved.       *\n*                                                                       *\n************************************************************************/\n\n#ifndef _MCX_H_\n#define _MCX_H_\n\ntypedef struct _MODEMDEVCAPS {\n    DWORD   dwActualSize;\n    DWORD   dwRequiredSize;\n    DWORD   dwDevSpecificOffset;\n    DWORD   dwDevSpecificSize;\n\n    // product and version identification\n    DWORD   dwModemProviderVersion;\n    DWORD   dwModemManufacturerOffset;\n    DWORD   dwModemManufacturerSize;\n    DWORD   dwModemModelOffset;\n    DWORD   dwModemModelSize;\n    DWORD   dwModemVersionOffset;\n    DWORD   dwModemVersionSize;\n\n    // local option capabilities\n    DWORD   dwDialOptions;          // bitmap of supported values\n    DWORD   dwCallSetupFailTimer;   // maximum in seconds\n    DWORD   dwInactivityTimeout;    // maximum in seconds\n    DWORD   dwSpeakerVolume;        // bitmap of supported values\n    DWORD   dwSpeakerMode;          // bitmap of supported values\n    DWORD   dwModemOptions;         // bitmap of supported values\n    DWORD   dwMaxDTERate;           // maximum value in bit/s\n    DWORD   dwMaxDCERate;           // maximum value in bit/s\n\n    // Variable portion for proprietary expansion\n    BYTE    abVariablePortion [1];\n} MODEMDEVCAPS, *PMODEMDEVCAPS, *LPMODEMDEVCAPS;\n\ntypedef struct _MODEMSETTINGS {\n    DWORD   dwActualSize;\n    DWORD   dwRequiredSize;\n    DWORD   dwDevSpecificOffset;\n    DWORD   dwDevSpecificSize;\n\n    // static local options (read/write)\n    DWORD   dwCallSetupFailTimer;       // seconds\n    DWORD   dwInactivityTimeout;        // seconds\n    DWORD   dwSpeakerVolume;            // level\n    DWORD   dwSpeakerMode;              // mode\n    DWORD   dwPreferredModemOptions;    // bitmap\n\n    // negotiated options (read only) for current or last call\n    DWORD   dwNegotiatedModemOptions;   // bitmap\n    DWORD   dwNegotiatedDCERate;        // bit/s\n\n    // Variable portion for proprietary expansion\n    BYTE    abVariablePortion [1];\n} MODEMSETTINGS, *PMODEMSETTINGS, *LPMODEMSETTINGS;\n\n// Dial Options\n#define DIALOPTION_BILLING  0x00000040  // Supports wait for bong \"$\"\n#define DIALOPTION_QUIET    0x00000080  // Supports wait for quiet \"@\"\n#define DIALOPTION_DIALTONE 0x00000100  // Supports wait for dial tone \"W\"\n\n// SpeakerVolume for MODEMDEVCAPS\n#define MDMVOLFLAG_LOW      0x00000001\n#define MDMVOLFLAG_MEDIUM   0x00000002\n#define MDMVOLFLAG_HIGH     0x00000004\n\n// SpeakerVolume for MODEMSETTINGS\n#define MDMVOL_LOW          0x00000000\n#define MDMVOL_MEDIUM       0x00000001\n#define MDMVOL_HIGH         0x00000002\n\n// SpeakerMode for MODEMDEVCAPS\n#define MDMSPKRFLAG_OFF         0x00000001\n#define MDMSPKRFLAG_DIAL        0x00000002\n#define MDMSPKRFLAG_ON          0x00000004\n#define MDMSPKRFLAG_CALLSETUP   0x00000008\n\n// SpeakerMode for MODEMSETTINGS\n#define MDMSPKR_OFF         0x00000000\n#define MDMSPKR_DIAL        0x00000001\n#define MDMSPKR_ON          0x00000002\n#define MDMSPKR_CALLSETUP   0x00000003\n\n// Modem Options\n#define MDM_COMPRESSION      0x00000001\n#define MDM_ERROR_CONTROL    0x00000002\n#define MDM_FORCED_EC        0x00000004\n#define MDM_CELLULAR         0x00000008\n#define MDM_FLOWCONTROL_HARD 0x00000010\n#define MDM_FLOWCONTROL_SOFT 0x00000020\n#define MDM_CCITT_OVERRIDE   0x00000040\n#define MDM_SPEED_ADJUST     0x00000080\n#define MDM_TONE_DIAL        0x00000100\n#define MDM_BLIND_DIAL       0x00000200\n#define MDM_V23_OVERRIDE     0x00000400\n\n#endif /* _MCX_H_ */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/WSA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WSA 32bit LIbrary                        *\n *                                                                         *\n *                    File Name : WSA.H                                    *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : May 23, 1994                             *\n *                                                                         *\n *                  Last Update : May 25, 1994   [SKB]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Open_Animation -- file name and flags, system allocates buffer.       *\n *   Open_Animation -- file name, flags, palette, system allocates buffer. *\n *   Open_Animation -- file_name, graphic buffer, flags.                   *\n *   Open_Animation -- file name, bufferclass, flags, palette.             *\n *   Open_Animation -- filename, ptr, size, flags, no palette.             *\n *   Animate_Frame -- Animate a frame to a page with magic colors.         *\n *   Animate_Frame -- Animate a frame to a viewport with magic colors.     *\n *   Animate_Frame -- Animate a frame to a page.                           *\n *   Animate_Frame -- Animate a frame to a viewport.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WSA_H\n#define WSA_H\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n#ifndef GBUFFER_H\n#include \"gbuffer.h\"\n#endif\n\n//lint -strong(AJX,WSAType)\ntypedef enum {\n\tWSA_NORMAL,\t\t\t\t\t\t\t\t// Normal WSA animation\n\tWSA_GHOST\t \t= 0x1000,\t\t\t// Or'd with the above flags to get ghosting\n\tWSA_PRIORITY2 \t= 0x2000,\t\t\t// Copy using a priority (or in the priority)\n\tWSA_TRANS    \t= 0x4000,\t\t\t// Copy frame, ignoring transparent colors\n\tWSA_PRIORITY \t= 0x8000\t\t\t\t// Copy using a priority (or in the priority)\n} WSAType;\n\n\n//lint -strong(AJX,WSAOpenType)\ntypedef enum {\n\tWSA_OPEN_FROM_MEM\t\t= 0x0000,\t// Try to load entire anim into memory.\n\tWSA_OPEN_INDIRECT\t\t= 0x0000,\t// First animate to internal buffer, then copy to page/viewport.\n\tWSA_OPEN_FROM_DISK\t= 0x0001,\t// Force the animation to be disk based.\n\tWSA_OPEN_DIRECT\t\t= 0x0002,\t// Animate directly to page or viewport.\n\n\t// These next two have been added for the 32 bit library to give a better idea of what is\n\t// happening.  You may want to animate directly to the destination or indirectly to the\n\t// destination by using the animations buffer.  Indirecly is best if the dest is a seenpage\n\t// and the animation is not linear or if the destination is modified between frames.\n\tWSA_OPEN_TO_PAGE  = WSA_OPEN_DIRECT ,\n\tWSA_OPEN_TO_BUFFER= WSA_OPEN_INDIRECT ,\n\n} WSAOpenType;\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WSA.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid * __cdecl Open_Animation(char const *file_name, char *user_buffer, long user_buffer_size, WSAOpenType user_flags, unsigned char *palette=NULL);\nvoid __cdecl Close_Animation( void *handle );\nBOOL __cdecl Animate_Frame(void *handle, GraphicViewPortClass& view,\n                         int frame_number, int x_pixel=0, int y_pixel=0,\n                         WSAType flags_and_prio = WSA_NORMAL, void *magic_cols=NULL, void *magic=NULL);\nint __cdecl Get_Animation_Frame_Count(void *handle);\nBOOL __cdecl Animate_Frame(void *handle, VideoViewPortClass& view,\n                         int frame_number, int x_pixel=0, int y_pixel=0,\n                         WSAType flags_and_prio = WSA_NORMAL, void *magic_cols=NULL, void *magic=NULL);\nint __cdecl Get_Animation_Frame_Count(void *handle);\nint __cdecl Get_Animation_X(void const *handle);\nint __cdecl Get_Animation_Y(void const *handle);\nint __cdecl Get_Animation_Width(void const *handle);\nint __cdecl Get_Animation_Height(void const *handle);\nint __cdecl Get_Animation_Palette(void const *handle);\nunsigned long __cdecl Get_Animation_Size(void const *handle);\n\n\n/***************************************************************************\n * OPEN_ANIMATION -- file name, flags, palette, system allocates buffer.   *\n *                                                                         *\n *                                                                         *\n * INPUT:   char *file_name - name of file to open.                        *\n *          WSAOpenType user_flags - flags on how to open.                 *\n *          unsigned char *palette - pointer to a palette buffer to fill.          *\n *                                                                         *\n * OUTPUT:  void *pointer to animation data.  Must be used for all \t\t\t*\n *               other WSA calls.                                          *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/24/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline void  * __cdecl Open_Animation(char *file_name, WSAOpenType user_flags, unsigned char *palette=NULL)\n{\n\treturn (Open_Animation(file_name, NULL, 0L, user_flags,  palette));\n}\n\n\n/***************************************************************************\n * OPEN_ANIMATION -- file_name, bufferclass, flags. \t\t\t\t\t\t\t\t*\n *                                                                         *\n *                                                                         *\n * INPUT:   char *file_name - name of file to open.                        *\n *          GraphicBufferClass - pointer to a buffer.                      *\n *          WSAOpenType user_flags - flags on how to open.                 *\n *          unsigned char *palette - pointer to a palette buffer to fill.          *\n *                                                                         *\n * OUTPUT:  void *pointer to animation data.  Must be used for all \t\t\t*\n *               other WSA calls.                                          *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/24/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline void * __cdecl Open_Animation(char *file_name, BufferClass& buffer, WSAOpenType user_flags,  unsigned char *palette=NULL)\n{\n\treturn (Open_Animation(file_name, (char *)buffer.Get_Buffer(), buffer.Get_Size(), user_flags, palette));\n}\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LP_ASM.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n\nextern \"C\" {\nunsigned int __cdecl Apply_XOR_Delta(char *source_ptr, char *delta_ptr);\nvoid  __cdecl Apply_XOR_Delta_To_Page_Or_Viewport(void *target, void *delta, int width, int nextrow, int copy);\n}\n\n\n\n#endif // WSA_H\n\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/WWFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\wwfile.h_v   2.14   06 Sep 1995 16:30:00   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Library                                             *\n *                                                                                             *\n *                    File Name : WWFILE.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : August 8, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWFILE_H\n#define WWFILE_H\n\n#include\t<stdio.h>\n\n#ifndef READ\n#define\tREAD\t_READ\n#endif\n#ifndef WRITE\n#define\tWRITE\t_WRITE\n#endif\n\nclass FileClass\n{\n\tpublic:\n\t\tvirtual ~FileClass(void) {};\n\t\tvirtual char const * File_Name(void) const = 0;\n\t\tvirtual char const * Set_Name(char const *filename) = 0;\n\t\tvirtual int Create(void) = 0;\n\t\tvirtual int Delete(void) = 0;\n\t\tvirtual int Is_Available(int forced=false) = 0;\n\t\tvirtual int Is_Open(void) const = 0;\n\t\tvirtual int Open(char const *filename, int rights=READ) = 0;\n\t\tvirtual int Open(int rights=READ) = 0;\n\t\tvirtual long Read(void *buffer, long size) = 0;\n\t\tvirtual long Seek(long pos, int dir=SEEK_CUR) = 0;\n\t\tvirtual long Size(void) = 0;\n\t\tvirtual long Write(void const *buffer, long size) = 0;\n\t\tvirtual void Close(void) = 0;\n\n\t\toperator char const * () {return File_Name();};\n};\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/WWLIB32.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 User include file                *\n *                                                                         *\n *                    File Name : WWLIB32.H                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWLIB32_H\n#define WWLIB32_H\n\n#include <gbuffer.h>\n#include <wwstd.h>\n#include <drawbuff.h>\n#include <buffer.h>\n#include <font.h>\n#include <iff.h>\n#include <misc.h>\n#include <mono.h>\n#include <tile.h>\n#include <wwmem.h>\n#include <keyboard.h>\n#include <mouse.h>\n#include <file.h>\n#include <rawfile.h>\n\n#include <audio.h>\n#include <dipthong.h>\n#include <palette.h>\n#include <playcd.h>\n#include <shape.h>\n#include <timer.h>\n#include <ww_win.h>\n#include <wsa.h>\n#include <profile.h>\n\n\n\n#endif // WWLIB32_H\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/WWMEM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory System                            *\n *                                                                         *\n *                    File Name : MEM.H                                    *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : April 4, 1994                            *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWMEM_H\n#define WWMEM_H\n\n#include \"wwstd.h\"\n#include \"new.h\"\n#include \"memflag.h\"\n\n// Defines\n//==============\n\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MEM.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint  Mem_Init(void *buffer, long size);\nvoid *Mem_Alloc(void *poolptr, long lsize, unsigned long id);\nint  Mem_Free(void *poolptr, void *buffer);\nvoid Mem_Reference(void *node);\nvoid Mem_Lock_Block(void *node);\nvoid Mem_In_Use(void *node);\nvoid *Mem_Find(void *poolptr, unsigned long id);\nunsigned long Mem_Get_ID(void *node);\nvoid *Mem_Find_Oldest(void *poolptr);\nvoid *Mem_Free_Oldest(void *poolptr);\nlong Mem_Pool_Size(void *poolptr);\nlong Mem_Avail(void *poolptr);\nlong Mem_Largest_Avail(void *poolptr);\nvoid Mem_Cleanup(void *poolptr);\n\n\n#endif\n\u001a\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/WWMEM.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Memory System                            *\n;*                                                                         *\n;*                    File Name : WWMEM.INC                                *\n;*                                                                         *\n;*                   Programmer : Ian M. Leslie                            *\n;*                                                                         *\n;*                   Start Date : August 11, 1994                          *\n;*                                                                         *\n;*                  Last Update : August 17, 1994   [IML]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nMEM_NORMAL EQU 0000h\t\t; Default memory (normal).\nMEM_NEW\t   EQU 0001h\t\t; Called by the operator new and was overloaded.\nMEM_CLEAR  EQU 0002h \t\t;\n\nGLOBAL\t\t@Alloc$qul14MemoryFlagType:PROC\nGLOBAL\t\t@Free$qpv:PROC\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/WWSTD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : wwstd.h                                  *\n *                                                                         *\n *                    File Name : WWLIB.H                                  *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : March 1, 1994                            *\n *                                                                         *\n *                  Last Update : March 1, 1994   []                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#define\tWWSTD_H\n\n\n//\n// Win 95 includes\n//\n\n#ifndef WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#define WIN32 1\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <windowsx.h>\n#endif\n\n\n// Note: SKB 4/11/94\n// Before this library is done, this needs to be able to be set to TRUE.\n// Once it is, the FALSE parts should be removed from the source code.\n#define LIB_EXTERNS_RESOLVED FALSE\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <dos.h>\n#include <bios.h>\n\n//================================\n\n// TRUE and FALSE are defined in pltypes.h\n\n#ifndef IBM\n#define IBM\t\t\t\tTRUE\n#endif\n\n#ifndef AMIGA\n#define AMIGA\t\t\tFALSE\n#endif\n\n#ifndef\tSEGA\n#define\tSEGA\t\t\tFALSE\n#endif\n\n/*\n**\tCommon constants used in normal code.\n*/\n#define WW_ERROR\t\t-1\n\n#ifdef NULL\n#undef\tNULL\n#endif\n\n#ifndef NULL\n#define NULL\t\t0L\n#endif\n\n#ifdef VOID\n#undef VOID\n#endif\n\n#define PRIVATE\t\tstatic\n#define PUBLIC\t\t\t/* Routines & data don't have a specifier */\n\n#ifdef __cplusplus\n#define\t__CPPARGS\t...\n#else\n#define\t__CPPARGS\n#endif\n\n// This macro will get the size (in elements) of the specified array.\n#ifdef GET_SIZE\n#undef GET_SIZE\n#endif\n#define GET_SIZE(a)\t\t\t\t\t((sizeof(a) / sizeof(*a)))\n\n#pragma option -Jg\n// Returns the absolute value of the number.\n#ifdef ABS\n#undef ABS\n#endif\ntemplate<class T> T ABS(T a)\n{\n\treturn (a < 0) ? -a : a;\n}\nint ABS(int);\nlong ABS(long);\n\n// Returns the minimum of the two numbers.\n#ifdef MIN\n#undef MIN\n#endif\ntemplate<class T> T MIN(T a, T b)\n{\n\treturn (b < a) ? b : a;\n};\nshort MIN(short, short);\nint MIN(int, int);\nlong MIN(long, long);\n\n// Returns the maximum of the two numbers.\n#ifdef MAX\n#undef MAX\n#endif\ntemplate<class T> T MAX(T a, T b)\n{\n\treturn (b > a) ? b : a;\n};\nshort MAX(short, short);\nint MAX(int, int);\nlong MAX(long, long);\n#pragma option -Jgd\n\n// Returns the low word of a long\n#define\tLOW_WORD(a)\t\t((unsigned short)((long)(a) & 0x0000FFFFL))\n\n// Returns the high word of a long\n#define\tHIGH_WORD(a)\t((unsigned long)(a) >> 16)\n\n// Merges to shorts to become a long\n#define\tMAKE_LONG(a,b) (((long)(a) << 16) | (long)((b)&0x0000FFFFL))\n\n/*\n** Macro allows our routines to act like\n** sprintf etc..\n*/\n#ifdef AssembleTo\n#undef AssembleTo\n#endif\n\n#define AssembleTo(dest,fmt)\\\n{\\\n\tva_list argptr;\\\n\tif (fmt != (dest))\\\n\t\t{\\\n\t\tva_start (argptr, fmt);\\\n\t\tvsprintf ((dest), fmt, argptr);\\\n\t\tva_end (argptr);\\\n\t\t}\\\n}\n\n// type definitions\n//=======================================\ntypedef void \tVOID;\n\n//==================================================\n// Pharlape defines these for use so we use their\n// typedefs!\n//\t\ttypedef\tunsigned char\tBOOL;\n//\t\ttypedef signed long\t\tLONG;\n//\t\ttypedef unsigned long\tULONG;\n//==================================================\n#ifndef PRIVATE\n#define  PRIVATE\tstatic\n#endif\n\n// The purpose of the INT and UINT is for efficiency.  It says that while a short int (16 bit)\n// has enough precision, it is more efficient to pass in an int (32 bits).  For efficiency, most\n// WORD and UWORD should be an INT or UINT, especially on the stack and structures that will\n// not be in large arrays.  When size efficiency is more important then speed, use WORD UWORD.\n\n#define\tVOID\t\tvoid\n\n#pragma\twarn -eas\n#define\tTRUE\t\t1\n#define\tFALSE\t\t0\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ comittee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n//#define\ttrue\t\t1\n//#define\tfalse\t\t0\n\n#define\tBOOL\t\tint\t\t\t\t\t// 32 bits for speed. use CHAR for size optimizations.\n#if(0)\n#ifndef HMI_DRIVER\n#define\tINT\t\tint\n#define\tUINT\t\tunsigned int\n#define\tBYTE\t\tchar\n#define\tUBYTE\t\tunsigned char\n#define  UCHAR\t   unsigned char\n#define\tWORD\t\tsigned \tshort\n#define\tUWORD\t\tunsigned short\n#define  USHORT\tunsigned short\n\n#define\tLONG\t\tsigned \tlong\n#define\tULONG\t\tunsigned long\n#define  REALPTR\tunsigned long\n\n#define\tFARPTR  char far *\n\n#endif\n#endif\n\n/*\n**\tThe type of processor running on this system as\n**\treturned by Processor().\n*/\n#define\tPROC_80386\t\t0\n#define\tPROC_80486\t\t1\n#define\tPROC_PENTIUM\t2\n\n\n// Inline Routines\n//\n//\n// These Template functions are generally used\n// by classes when they havce over loaded > and <.\n//\n#ifdef __cplusplus\ntemplate<class T> T Min(T a, T b)\n{\n\treturn (a<b ? a : b);\n}\n\ntemplate<class T> inline  T Max(T a, T b)\n{\n\treturn (a>b ? a : b);\n}\n\ntemplate<class T> T Abs(T a)\n{\n\treturn ((a<0) ? -(a) : a);\n}\n\ntemplate<class T> VOID minimize(T &a, T b)\n{\n\tif( b<a )\n\t\ta=b;\n}\n\ntemplate<class T> VOID maximize(T &a, T b)\n{\n\tif( b>a )\n\t\ta=b;\n}\n#endif\n\n/*\n**\tMacros that control bit settings in a variable.\n*/\n#define Bit_Flags_On(a,b)\t\t\ta |= (b)\n#define Bit_Flags_Off(a,b)\t\t\ta &= (~(b))\n#define Bit_Flags_Value(a,b)\t\t(a & (b))\n#define Bit_Flags_Flip(a,b)\t\ta ^= (b)\n\n// Template replacements for the user defines above\n#ifdef __cplusplus\ntemplate<class T> VOID BitFlagsOn(T &a, T b)\n{\n\ta |= (b);\n}\n\ntemplate<class T> VOID BitFlagsOff(T &a, T b)\n{\n\ta &= (~(b));\n}\n\ntemplate<class T> T BitFlagsValue(T a, T b)\n{\n\treturn (a & (b));\n}\n\ntemplate<class T> VOID BitFlagsFlip(T &a, T b)\n{\n\ta ^= (b);\n}\n#endif\n\ntypedef enum {\n\tTBLACK,\n\tPURPLE,\n\tCYAN,\n\tGREEN,\n\tLTGREEN,\n\tYELLOW,\n\tPINK,\n\tBROWN,\n\tRED,\n\tLTCYAN,\n\tLTBLUE,\n\tBLUE,\n\tBLACK,\n\tGREY,\n\tLTGREY,\n\tWHITE,\n\tCOLOR_PADDING=0x1000\n} ColorType;\n\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/INCLUDE/WW_WIN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the WINDOWS Library              *\n *                                                                         *\n *                    File Name : WINDOWS.H                                *\n *                                                                         *\n *                   Programmer : Barry W. Green                           *\n *                                                                         *\n *                   Start Date : February 16, 1995                        *\n *                                                                         *\n *                  Last Update : February 16, 1995 [BWG]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WINDOWS_H\n#define WINDOWS_H\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WINHIDE.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Window_Hide_Mouse(int window);\nvoid Window_Show_Mouse(void);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WINDOWS.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Standard_More_Prompt(char const *prompt, int space, int fcolor, int bcolor);\nvoid Set_More_Prompt(char const *prompt, int space, int fcolor, int bcolor);\nvoid Set_More_On(void);\nvoid Set_More_Off(void);\nint Change_Window(int windnum);\nint Change_New_Window(int windnum);\nvoid New_Window(void);\nvoid Window_Int_Print(int num);\nvoid Window_Print(char const string[], ...);\n\n/*\n**\tThe WindowList[][8] array contains the following elements.  Use these\n**\tdefines when accessing the WindowList.\n*/\ntypedef enum {\n\tWINDOWX,\t\t\t// X byte position of left edge.\n\tWINDOWY,\t\t\t// Y pixel position of top edge.\n\tWINDOWWIDTH,\t// Width in bytes of the window.\n\tWINDOWHEIGHT,\t// Height in pixels of the window.\n\tWINDOWFCOL,\t\t// Default foreground color.\n\tWINDOWBCOL,\t\t// Default background color.\n\tWINDOWCURSORX,\t// Current cursor X position (in rows).\n\tWINDOWCURSORY,\t// Current cursor Y position (in lines).\n\tWINDOWPADDING=0x1000\n} WindowIndexType;\n\nextern int WindowList[][8];\nextern int WindowColumns;\nextern int WindowLines;\nextern int WindowWidth;\nextern unsigned int WinB;\nextern unsigned int WinC;\nextern unsigned int WinX;\nextern unsigned int WinY;\nextern unsigned int WinCx;\nextern unsigned int WinCy;\nextern unsigned int WinH;\nextern unsigned int WinW;\nextern unsigned int Window;\n\nextern int MoreOn;\nextern char *TXT_MoreText;\n\nextern void (*Window_More_Ptr)(char const *, int, int, int);\n\n#endif //WINDOWS_H\n\n\u001a"
  },
  {
    "path": "WIN32LIB/INCLUDE/_FILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library - Filio header stuff.            *\n;*                                                                         *\n;*                    File Name : FILE.H                                 \t*\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : September 13, 1993                       *\n;*                                                                         *\n;*                  Last Update : April 11, 1994\t\t\t\t\t\t\t\t\t*\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FILE_H\n#include \"file.h\"\n#endif\n\n#ifndef _FILE_H\n#define _FILE_H\n\n\n/*=========================================================================*/\n/* Fileio defines\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#define\tLIB_CDROM TRUE\n\n#define MODE_OLDFILE\t\t\t\t(O_RDONLY | O_BINARY)\n#define MODE_NEWFILE\t\t\t\t(O_WRONLY | O_BINARY | O_CREAT | O_TRUNC)\n#define MODE_READWRITE\t\t\t(O_RDWR   | O_BINARY)\n\n#define FILEOPENERROR\t\t\t-1\n#define FILEOPEN(f,m)\t\t\tibm_open(f, m, (((UWORD) m) == MODE_OLDFILE) ? S_IREAD : (S_IREAD | S_IWRITE))\n\n#define FILECLOSE(fd)\t\t\tibm_close(fd)\n#define FILEREAD(f,b,n)\t\t\tibm_read(f,b,(WORD)(n))\n#define FILEWRITE(f,b,n)\t\tibm_write(f,b,(WORD)(n))\n#define FILESEEK(f,b,n)\t\t\tibm_lseek(f, b, n)\n#define FILEDELETE(f)\t\t\tibm_unlink(f)\n#define CHANGEDIR(p)\t\t\t\tibm_chdir(p)\n\n#define FILENAMESIZE\t\t\t\t13\n#define IO_CHUNK_SIZE\t\t\t0xfff0UL\n\n/* \n**\tMaximum number of file handles \n*/\n#define TABLE_MAX\t\t\t20\n\n \n/*=========================================================================*/\n/* The file handle table */\n/*=========================================================================*/\ntypedef struct {\n\tBOOL\t\t\t\t\t\tEmpty;\t\t// Is this handle empty?\n\tWORD\t\t\t\t\t\tHandle;\t\t// DOS file handle (0 = resident).\n\tLONG\t\t\t\t\t\tPos;\t\t\t// Current file position.\n\tLONG\t\t\t\t\t\tStart;\t\t// Offset of file from pointer.\n\tWORD\t\t\t\t\t\tIndex;\t\t// FileData[] index.\n\tWORD\t\t\t\t\t\tMode;\t\t\t// Access mode (WW).\n\tBYTE\t\t\t\t\t\t*Name;\t\t// File name pointer.\n} FileHandleType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILEIO.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD ibm_getdisk(VOID);\nWORD ibm_setdisk(WORD drive);\nWORD ibm_close(WORD handle);\nWORD ibm_unlink(BYTE const *name);\nLONG ibm_lseek(WORD handle, LONG offset, WORD where);\nUWORD ibm_read(WORD handle, VOID *ptr, UWORD bytes);\nUWORD ibm_write(WORD handle, VOID *ptr, UWORD bytes);\nWORD ibm_open(BYTE const *name, UWORD mode, WORD attrib);\nWORD ibm_chdir(BYTE const *path);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILELIB.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD cdecl Do_Open_Error(FileErrorType errormsgnum, BYTE const *file_name);\nVOID cdecl Do_IO_Error(FileErrorType errormsgnum, BYTE const *filename);\nLONG cdecl Read_File_With_Recovery( WORD handle, VOID *buf, UWORD bytes );\nWORD cdecl Open_File_With_Recovery( BYTE const *file_name, UWORD mode );\nBOOL cdecl Cache_File(WORD index, WORD file_handle);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DEVICES.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Get_Devices(VOID);\nextern WORD Is_Device_Real(WORD device);\n\n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DEVTABLE.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Init_Device_Table(BYTE *table);\nextern WORD Max_Device(VOID);\n\n\n#ifdef __cplusplus\n}\n#endif\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: HARDERR.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Install_Hard_Error_Handler(VOID);\nextern VOID Remove_Hard_Error_Handler(VOID);\n\n#ifdef __cplusplus\n}\n#endif\n\n\n/*=========================================================================*/\n/* Globale variables in the fileio system.\t\t\t\t\t\t               */\n/*=========================================================================*/\n\nextern BYTE CallingDOSInt;\t\t\t\t\t \nextern \"C\" extern BYTE MaxDevice,DefaultDrive;\nextern BYTE MultiDriveSearch;\t\nextern FileDataType *FileDataPtr;\nextern FileHandleType FileHandleTable[TABLE_MAX];\nextern UWORD NumFiles;\t\t\t\t\t\t\t \t// Number of files, except PAK, in file table.\nextern UWORD NumPAKFiles;\t\t\t\t\t\t\t// Number of PAK files in filetable.\nextern VOID *FileCacheHeap;\t\t\t\t\t\t// Pointer to the cache in memory.\nextern WORD DiskNumber;\t\t\t\t\t\t \nextern WORD MaxDirNum;\n\n\n/*=========================================================================*/\n\t \n\n\n#endif // _FILE_H\n\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/KEYBOARD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Keyboard Library                                    *\n *                                                                                             *\n *                    File Name : KEYBOARD.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 10/16/95                                                     *\n *                                                                                             *\n *                  Last Update : October 26, 1995   []                    *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                         *\n *   WWKeyboardClass::Get -- Logic to get a metakey from the buffer                            *\n *   WWKeyboardClass::Check -- Checks to see if a key is in the buffer                         *\n *   WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer    *\n *   WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer               *\n *   WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels           *\n *   WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels           *\n *   WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars       *\n *   Check_Key -- compatability routine for old 32 bit library             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"keyboard.h\"\n#include \"timer.h\"\n#include \"mono.h\"\n\nvoid Message_Loop(void);\n\nWWKeyboardClass *_Kbd;\n\n/***********************************************************************************************\n * WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class                *\n *                                                                                             *\n * INPUT:\t\tnone\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * OUTPUT:     none\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nWWKeyboardClass::WWKeyboardClass(void)\n{\n\t_Kbd = this;\n\t//\n\t// Initialize the keyboard remap table for our system (note it would be bad if someone\n\t// switched keyboard modes after this happened.\n\t//\n\tmemset(VKRemap, 0, 256);\n\tmemset(AsciiRemap, 0, 2048);\n\tfor (short lp = 31; lp < 255; lp ++) {\n\t\tif (isprint(lp)) {\n\t\t\tint vk_key = VkKeyScan((unsigned char)lp);\n\t\t\tif (vk_key > 0 && vk_key < 2048) {\n\t\t\t\tAsciiRemap[vk_key] = (unsigned char)lp;\n\t\t\t\tVKRemap[lp] \t = (unsigned char)(vk_key & 0xFF);\n\t\t\t}\n\t\t}\n\t}\n\n\t//\n\t// Build a remap table of the different keys which are affected by the caps lock and\n\t// the num lock.\n\t//\n\tmemset(ToggleKeys, 0, 256);\n\tfor (lp = 0; lp < 255; lp++ ) {\n\t\tif (isalpha(lp) && isupper(lp)) {\n\t\t\tToggleKeys[lp] = 1;\n\t\t}\n\t\tif (lp >= VK_NUMPAD0 && lp <= VK_DIVIDE) {\n\t\t\tToggleKeys[lp] = 2;\n\t\t}\n\t}\n\n\t//\n\t// Our buffer should start devoid of keys.\n\t//\n\tmemset(Buffer, 0, 256);\n\tHead\t\t\t\t= 0;\n\tTail\t\t\t\t= 0;\n\n\t//\n\t// There should be no starting queued mouse events for us to have to worry\n\t// about.\n\t//\n\tMouseQX\t\t\t= 0;\n\tMouseQY\t\t\t= 0;\n\tMState\t\t\t= 0;\n\tConditional\t\t= 0;\n\tCurrentCursor\t= NULL;\n}\n\n/***********************************************************************************************\n * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer                 *\n *                                                                                             *\n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     int\t\t- the key value that was pulled from buffer (includes bits)\t\t\t\t  *                                                                                *\n *                                                                                             *\n * WARNINGS:   If the key was a mouse event MouseQX and MouseQY will be updated                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nint WWKeyboardClass::Buff_Get(void)\n{\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t\t\t// wait for key in buffer\n\tint \ttemp\t\t= Buffer[Head];\t\t\t\t\t\t// get key out of the buffer\n\tint   newhead\t= Head;\t\t\t\t\t\t\t\t\t// save off head for manipulation\n\tif (Is_Mouse_Key(temp)) {\t\t\t\t\t\t\t\t// if key is a mouse then\n\t\tMouseQX\t= Buffer[(Head + 1) & 255];\t\t\t//\t\tget the x and y pos\n\t\tMouseQY\t= Buffer[(Head + 2) & 255];\t\t\t//\t\tfrom the buffer\n\t\tnewhead += 3;\t\t  \t\t\t\t\t\t\t\t\t//\t\tadjust head forward\n\t} else {\n\t\tnewhead += 1;\t\t  \t\t\t\t\t\t\t\t\t//\t\tadjust head forward\n\t}\n\tnewhead\t&= 255;\n\tHead\t\t = newhead;\n\treturn(temp);\n}\n\nBOOL WWKeyboardClass::Is_Mouse_Key(int key)\n{\n\tkey &= 0xFF;\n\treturn (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Check -- Checks to see if a key is in the buffer                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nBOOL WWKeyboardClass::Check(void)\n{\n\tMessage_Loop();\n\tunsigned short temp;\t\t\t\t\t\t\t\t\t\t\t// store temp holding spot for key\n\tif (Head == Tail) return(FALSE);\t\t\t\t\t\t\t// if no keys in buff then get out\n\ttemp = Buffer[Head];\t\t\t\t\t\t\t\t\t\t\t// get key out of the buffer\n\treturn(temp);\t\t\t\t\t\t\t\t\t\t\t\t\t// send it back to main program\n}\n\n/***********************************************************************************************\n * WWKeyboardClass::Get -- Logic to get a metakey from the buffer                              *\n *                                                                                             *\n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     int\t\t- the meta key taken from the buffer.\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:\tThis routine will not return until a keypress is received\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nint WWKeyboardClass::Get(void)\n{\n\tint temp,bits;\t\t\t\t\t\t\t\t\t\t// store temp holding spot for key\n\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t// wait for key in buffer\n\ttemp = Buff_Get();\t\t\t\t\t\t\t\t// get key from the buffer\n\n\tbits = temp & 0xFF00;\t\t\t\t\t\t\t// save of keyboard bits\n\n\tif (!(bits & WWKEY_VK_BIT)) {\t\t\t\t\t// if its not a virtual key\n\t\ttemp = AsciiRemap[temp&0x1FF] | bits;\t//   convert to ascii equivalent\n\t}\n\treturn(temp);\t\t\t\t\t\t\t// return the key that we pulled out\n}\n\n/***********************************************************************************************\n * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                           *\n *                                                                                             *\n * INPUT:\t\tint\t \t- the key to insert into the buffer          \t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     bool\t\t- true if key is sucessfuly inserted.\t\t\t\t\t\t\t              *\n *                                                                                             *\n * WARNINGS:   none\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nBOOL WWKeyboardClass::Put(int key)\n{\n\tint\ttemp\t\t= (Tail + 1) & 255;\n\tif (temp != Head)\n\t{\n\t\tBuffer[Tail]\t= (short)key;\n\n\t\t//\n\t\t// Critical Line\n\t\t//\n\t\tTail\t\t\t\t= temp;\n\t\treturn(TRUE);\n\t}\n\treturn(FALSE);\n}\n/***********************************************************************************************\n * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nWWKeyboardClass::Put_Key_Message(UINT vk_key, BOOL release, BOOL dbl)\n{\n\tint bits = 0;\n\t//\n\t// Get the status of all of the different keyboard modifiers.  Note, only pay attention\n\t// to numlock and caps lock if we are dealing with a key that is affected by them.  Note\n\t// that we do not want to set the shift, ctrl and alt bits for Mouse keypresses as this\n\t// would be incompatible with the dos version.\n\t//\n\tif (vk_key != VK_LBUTTON && vk_key != VK_MBUTTON && vk_key != VK_RBUTTON) \t{\n\t\tint\tshift\t\t= (GetKeyState(VK_SHIFT) & 0xFF00) \t\t!= 0;\n\t\tint\tctrl \t\t= (GetKeyState(VK_CONTROL) & 0xFF00) \t!= 0;\n\t\tint\talt \t\t= (GetKeyState(VK_MENU) & 0xFF00) \t\t!= 0;\n\t\tint\tcaps\t\t= ((GetKeyState(VK_CAPITAL) & 0x00FF) \t!= 0) && (ToggleKeys[vk_key] == 1);\n\t\tint\tnums\t\t= ((GetKeyState(VK_NUMLOCK) & 0x00FF) \t!= 0) && (ToggleKeys[vk_key] == 2);\n\n\t\t//\n\t\t// Set the proper bits for whatever the key we got is.\n\t\t//\n\t\tif (shift || caps || nums) {\n\t\t\tbits |= WWKEY_SHIFT_BIT;\n\t\t}\n\t\tif (ctrl) {\n\t\t\tbits |= WWKEY_CTRL_BIT;\n\t\t}\n\t\tif (alt) {\n\t\t\tbits |= WWKEY_ALT_BIT;\n\t\t}\n\t\t}\n\tif (!AsciiRemap[vk_key|bits]) {\n\t\tbits |= WWKEY_VK_BIT;\n\t}\n\tif (release) {\n\t\tbits |= WWKEY_RLS_BIT;\n\t}\n\tif (dbl) {\n\t\tbits |= WWKEY_DBL_BIT;\n\t}\n\t//\n\t// Finally use the put command to enter the key into the keyboard\n\t// system.\n\t//\n\treturn(Put(vk_key|bits));\n}\n\nvoid WWKeyboardClass::Clear(void)\n{\n\tHead = Tail;\n}\n\nint WWKeyboardClass::To_ASCII(int key)\n{\n\tif ( key && WWKEY_RLS_BIT)\n\t  return(KN_NONE);\n\treturn(key);\n}\n\nWWKeyboardClass::Down(int key)\n{\n\treturn(GetAsyncKeyState(key&0xFF));\n}\n\nVOID WWKeyboardClass::Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl)\n{\n\tshift = (key & WWKEY_SHIFT_BIT)\t!= 0;\n\tctrl\t= (key & WWKEY_CTRL_BIT)\t!= 0;\n\talt\t= (key & WWKEY_ALT_BIT)\t\t!= 0;\n\trls\t= (key & WWKEY_RLS_BIT)\t\t!= 0;\n\tdbl\t= (key & WWKEY_DBL_BIT)\t\t!= 0;\n\tkey\t= (key & 0xFF);\n\n}\n\n\nextern \"C\" {\n\tvoid __cdecl Stop_Execution (void);\n}\n\n#pragma off(unreferenced)\nvoid WWKeyboardClass::Message_Handler(HWND , UINT message, UINT wParam, LONG lParam)\n{\n\tswitch (message) {\n\t\tcase WM_SYSKEYDOWN:\n\t\tcase WM_KEYDOWN:\n\t\t\tif ( wParam==VK_SCROLL ){\n\t\t\t\tStop_Execution();\n\t\t\t} else {\n\t\t\t\tPut_Key_Message(wParam);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WM_SYSKEYUP:\n\t\tcase WM_KEYUP:\n\t\t\tPut_Key_Message(wParam, TRUE);\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_LBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONUP:\n\t\t\tPut_Key_Message(VK_LBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_LBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_MBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONUP:\n\t\t\tPut_Key_Message(VK_MBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_MBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_RBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONUP:\n\t\t\tPut_Key_Message(VK_RBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_RBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\t\tcase WM_MOUSEMOVE:\n\t\t\tif (CurrentCursor)\n\t\t\t\tSetCursor(CurrentCursor);\n\t\t\tbreak;\n\t}\n}\n#pragma on(unreferenced)\n\n\n\n\nvoid Message_Loop(void)\n{\n\n\tMSG\tmsg;\n\n\twhile (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE )) {\n\t  \tif( !GetMessage( &msg, NULL, 0, 0 ) ){\n\t\t\treturn;\n\t\t}\n\t\tTranslateMessage(&msg);\n\t\tDispatchMessage(&msg);\n\t}\n\n\n\n\n}\n\n\n\n/***************************************************************************\n * CHECK_KEY -- compatability routine for old 32 bit library               *\n *                                                                         *\n * This routine checks to see if there is a key in the keyboard buffer     *\n * and returns it to the sender if there is.  It does not remove the key\t*\n * from the buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     The key that was pressed.                                   *\n *                                                                         *\n * WARNINGS:   You must declare a WWKeyboardClass object before calling    *\n *\t\t\t\t\tthis routine.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/26/1995     : Created.                                             *\n *=========================================================================*/\nint Check_Key(void)\n{\n\tif (!_Kbd) return(KA_NONE);\n\treturn(_Kbd->Check() & ~WWKEY_SHIFT_BIT);\n}\n\nvoid Clear_KeyBuffer(void)\n{\n\tif (!_Kbd) return;\n\t_Kbd->Clear();\n}\n\nint Check_Key_Num(void)\n{\n\tif (!_Kbd) return(KN_NONE);\n\tint key\t\t= _Kbd->Check();\n\tint flags\t= key & 0xFF00;\n\tkey\t\t   = key & 0x00FF;\n\n\tif (isupper(key)) {\n\t\tkey = tolower(key);\n\t\tif ( !flags & WWKEY_VK_BIT ) {\n\t\t\tflags |= WWKEY_SHIFT_BIT;\n\t\t}\n\t}\n\n\treturn(key | flags);\n}\n\nint Get_Key_Num(void)\n{\n\tif (!_Kbd) return(KN_NONE);\n\tint key\t\t= _Kbd->Get();\n\tint flags\t= key & 0xFF00;\n\tkey\t\t   = key & 0x00FF;\n\n\tif (isupper(key)) {\n\t\tkey = tolower(key);\n\t\tif ( !flags & WWKEY_VK_BIT ) {\n\t\t\tflags |= WWKEY_SHIFT_BIT;\n\t\t}\n\t}\n\treturn(key | flags);\n}\n\nint KN_To_KA(int key)\n{\n\tif ( key & WWKEY_RLS_BIT) {\n\t\treturn(KA_NONE);\n\t}\n\tif (!(key & WWKEY_VK_BIT)) {\n\t\tint flags = key & 0xFF00;\n\t\tkey\t\t = key & 0x00FF;\n\t\tif (flags & WWKEY_SHIFT_BIT) {\n\t\t\tkey\t\t= toupper(key);\n\t\t\tflags\t  &= ~WWKEY_SHIFT_BIT;\n\t\t}\n\t}else{\n\t\t/*\n\t\t** If its a numeric keypad key then fix it up\n\t\t*/\n\t\tif ((key & 0xff) >=VK_NUMPAD0 && (key & 0xff) <=VK_NUMPAD9){\n\t\t\tkey = (key & 0xff) - VK_NUMPAD0 + KA_0;\n\t\t}\n\t}\n\treturn(key);\n}\n\nint KN_To_VK(int key)\n{\n\tif (!_Kbd) return(KN_NONE);\n\tif ( key & WWKEY_RLS_BIT) {\n\t\treturn(VK_NONE);\n\t}\n\n\tint flags = key & 0xFF00;\n\tif (!(flags & WWKEY_VK_BIT)) {\n\t\tkey \t\t = _Kbd->VKRemap[key & 0x00FF] | flags;\n\t}\n\tkey &= ~WWKEY_VK_BIT;\n\treturn(key);\n}\n\nint Key_Down(int key)\n{\n\tif (!_Kbd) return(FALSE);\n\treturn(_Kbd->Down(key));\n}\n\nint Get_Key(void)\n{\n\tint retval;\n\n\tif (!_Kbd) return(KN_NONE);\n\tretval = _Kbd->Get() & ~WWKEY_SHIFT_BIT;\n\tif (retval & WWKEY_RLS_BIT) {\n\t\tretval = KN_NONE;\n\t}\n\treturn(retval);\n}\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/KEYBOARD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Keyboard Library                                    *\n *                                                                                             *\n *                    File Name : KEYBOARD.H                                                   *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 10/16/95                                                     *\n *                                                                                             *\n *                  Last Update : October 16, 1995 [PWG]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef KEYBOARD_H\n#define KEYBOARD_H\n \n#include <WWSTD.H>\n\ntypedef enum {\n\tWWKEY_SHIFT_BIT\t= 0x100,\n\tWWKEY_CTRL_BIT\t\t= 0x200,\n\tWWKEY_ALT_BIT\t\t= 0x400,\n\tWWKEY_RLS_BIT\t\t= 0x800,\n\tWWKEY_VK_BIT\t\t= 0x1000,\n\tWWKEY_DBL_BIT\t\t= 0x2000,\n\tWWKEY_BTN_BIT\t\t= 0x8000,\n} WWKey_Type;\n\nclass WWKeyboardClass\n{\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tWWKeyboardClass();\n\n\t\t/*===================================================================*/\n\t\t/* Define the functions which work with the Keyboard Class\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBOOL \tCheck(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for meta key\n\t\tint \tGet(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// gets a meta key from the keybuffer\n\t\tBOOL \tPut(int key);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// dumps a key into the keybuffer\n\t\tBOOL\tPut_Key_Message(\tUINT vk_key, BOOL release = FALSE, \t\t// handles keyboard related message\n\t\t\t\t\t\t\t\t\t\tBOOL dbl = FALSE);\t\t\t\t\t\t\t//   and mouse clicks and dbl clicks\n\t\tint \tCheck_Num(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for a keynum key\n\t\tint \tGet_VK(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// gets keynum key from key buff\n\t\tint \tCheck_ACII(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for an ascii key\n\t\tint \tGet_ASCII(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// gets an ascii key from keybuff\n\t\tint \tCheck_Bits(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for key w/ bits\n\t\tint \tGet_Bits(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// get key from keybuff w/ bits\n\t\tint \tTo_ASCII(int num);\t\t\t\t\t\t\t\t\t\t\t\t\t// converts keynum to ascii value\n\t\tint \tOption_On(int option);\t\t\t\t\t\t\t\t\t\t\t\t// turns specified option on\n\t\tint \tOption_Off(int option);\t\t\t\t\t\t\t\t\t\t\t\t// turns specified option off\n\t\tvoid \tClear(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// clears all keys from keybuffer\n\t\tint \tDown(int key);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// tests to see if a key is down\n\t\tvoid\tAI(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// messaging logic for key manager\n\n\t\t/*===================================================================*/\n\t\t/* Define the main hook for the message processing loop.\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tvoid Message_Handler(HWND hwnd, UINT message, UINT wParam, LONG lParam);\n\n\t\t/*===================================================================*/\n\t\t/* Define public routines which can be used on keys in general.\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl);\n\t\tBOOL Is_Mouse_Key(int key);\n\n\n\t\t/*===================================================================*/\n\t\t/* Define the public access variables which are used with the\t\t\t*/\n\t\t/*   Keyboard Class.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tint\t\t\t\tMouseQX;\n\t\tint\t\t\t\tMouseQY;\n\n\t\tunsigned char\tVKRemap[256];\t\t// gives vk for any ascii char\n\tprivate:\n\t\t/*===================================================================*/\n\t\t/* Define the private access functions which are used by keyboard\t\t*/\n\t\t/*===================================================================*/\n\t\tint  Buff_Get(void);\n\n\n\t\t/*===================================================================*/\n\t\t/* Define the private access variables which are used with the\t\t\t*/\n\t\t/*   Keyboard Class.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tunsigned char\tAsciiRemap[2048];\t// remap for shft/ctrl/alt key combos\n\t\tunsigned short Buffer[256];\t\t// buffer which holds actual keypresses\n\t\tunsigned char  ToggleKeys[256];\t// determines toggles which affect key\n\t\tlong\t\t\t\tHead;\t\t\t\t\t// the head position in keyboard buffer\n\t\tlong\t\t\t\tTail;\t\t\t\t\t// the tail position in keyboard buffer\n\t\tint\t\t\t\tMState;\n\t\tint\t\t\t\tConditional;\n\t\tHANDLE\t\t\tCurrentCursor;\n};\n\n\n#define\tVK_NONE\t\t\t\t  0x00\n#define\tVK_LBUTTON          0x01\n#define\tVK_RBUTTON          0x02\n#define\tVK_CANCEL           0x03\n#define\tVK_MBUTTON          0x04\n#define\tVK_NONE_05\t\t\t  0x05\n#define\tVK_NONE_06\t\t\t  0x06\n#define\tVK_NONE_07\t\t\t  0x07\n#define\tVK_BACK             0x08\n#define\tVK_TAB              0x09\n#define\tVK_NONE_0A\t\t\t  0x0A\n#define\tVK_NONE_0B\t\t\t  0x0B\n#define\tVK_CLEAR            0x0C\n#define\tVK_RETURN           0x0D\n#define\tVK_NONE_0E\t\t\t  0x0E\n#define\tVK_NONE_0F\t\t\t  0x0F\n#define\tVK_SHIFT            0x10\n#define\tVK_CONTROL          0x11\n#define\tVK_MENU             0x12\n#define\tVK_PAUSE            0x13\n#define\tVK_CAPITAL          0x14\n#define\tVK_NONE_15\t\t\t  0x15\n#define\tVK_NONE_16\t\t\t  0x16\n#define\tVK_NONE_17\t\t\t  0x17\n#define\tVK_NONE_18\t\t\t  0x18\n#define\tVK_NONE_19\t\t\t  0x19\n#define\tVK_NONE_1A\t\t\t  0x1A\n#define\tVK_ESCAPE           0x1B\n#define\tVK_NONE_1C\t\t\t  0x1C\n#define\tVK_NONE_1D\t\t\t  0x1D\n#define\tVK_NONE_1E\t\t\t  0x1E\n#define\tVK_NONE_1F\t\t\t  0x1F\n#define\tVK_SPACE            0x20\n#define\tVK_PRIOR            0x21\n#define\tVK_NEXT             0x22\n#define\tVK_END              0x23\n#define\tVK_HOME             0x24\n#define\tVK_LEFT             0x25\n#define\tVK_UP               0x26\n#define\tVK_RIGHT            0x27\n#define\tVK_DOWN             0x28\n#define\tVK_SELECT           0x29\n#define\tVK_PRINT            0x2A\n#define\tVK_EXECUTE          0x2B\n#define\tVK_SNAPSHOT         0x2C\n#define\tVK_INSERT           0x2D\n#define\tVK_DELETE           0x2E\n#define\tVK_HELP             0x2F\n#define\tVK_0\t\t\t\t\t  0x30\n#define\tVK_1\t\t\t\t\t  0x31\n#define\tVK_2\t\t\t\t\t  0x32\n#define\tVK_3\t\t\t\t\t  0x33\n#define\tVK_4\t\t\t\t\t  0x34\n#define\tVK_5\t\t\t\t\t  0x35\n#define\tVK_6\t\t\t\t\t  0x36\n#define\tVK_7\t\t\t\t\t  0x37\n#define\tVK_8\t\t\t\t\t  0x38\n#define\tVK_9\t\t\t\t\t  0x39\n#define\tVK_NONE_3B\t\t\t  0x3B\n#define\tVK_NONE_3C\t\t\t  0x3C\n#define\tVK_NONE_3D\t\t\t  0x3D\n#define\tVK_NONE_3E\t\t\t  0x3E\n#define\tVK_NONE_3F\t\t\t  0x3F\n#define\tVK_NONE_40\t\t\t  0x40\n#define\tVK_A\t\t\t\t\t  0x41\n#define\tVK_B\t\t\t\t\t  0x42\n#define\tVK_C\t\t\t\t\t  0x43\n#define\tVK_D\t\t\t\t\t  0x44\n#define\tVK_E\t\t\t\t\t  0x45\n#define\tVK_F\t\t\t\t\t  0x46\n#define\tVK_G\t\t\t\t\t  0x47\n#define\tVK_H\t\t\t\t\t  0x48\n#define\tVK_I\t\t\t\t\t  0x49\n#define\tVK_J\t\t\t\t\t  0x4A\n#define\tVK_K\t\t\t\t\t  0x4B\n#define\tVK_L\t\t\t\t\t  0x4C\n#define\tVK_M\t\t\t\t\t  0x4D\n#define\tVK_N\t\t\t\t\t  0x4E\n#define\tVK_O\t\t\t\t\t  0x4F\n#define\tVK_P\t\t\t\t\t  0x50\n#define\tVK_Q\t\t\t\t\t  0x51\n#define\tVK_R\t\t\t\t\t  0x52\n#define\tVK_S\t\t\t\t\t  0x53\n#define\tVK_T\t\t\t\t\t  0x54\n#define\tVK_U\t\t\t\t\t  0x55\n#define\tVK_V\t\t\t\t\t  0x56\n#define\tVK_W\t\t\t\t\t  0x57\n#define\tVK_X\t\t\t\t\t  0x58\n#define\tVK_Y\t\t\t\t\t  0x59\n#define\tVK_Z\t\t\t\t\t  0x5A\n#define\tVK_NONE_5B\t\t\t  0x5B\n#define\tVK_NONE_5C\t\t\t  0x5C\n#define\tVK_NONE_5D\t\t\t  0x5D\n#define\tVK_NONE_5E\t\t\t  0x5E\n#define\tVK_NONE_5F\t\t\t  0x5F\n#define\tVK_NUMPAD0          0x60\n#define\tVK_NUMPAD1          0x61\n#define\tVK_NUMPAD2          0x62\n#define\tVK_NUMPAD3          0x63\n#define\tVK_NUMPAD4          0x64\n#define\tVK_NUMPAD5          0x65\n#define\tVK_NUMPAD6          0x66\n#define\tVK_NUMPAD7          0x67\n#define\tVK_NUMPAD8          0x68\n#define\tVK_NUMPAD9          0x69\n#define\tVK_MULTIPLY         0x6A\n#define\tVK_ADD              0x6B\n#define\tVK_SEPARATOR        0x6C\n#define\tVK_SUBTRACT         0x6D\n#define\tVK_DECIMAL          0x6E\n#define\tVK_DIVIDE           0x6F\n#define\tVK_F1               0x70\n#define\tVK_F2               0x71\n#define\tVK_F3               0x72\n#define\tVK_F4               0x73\n#define\tVK_F5               0x74\n#define\tVK_F6               0x75\n#define\tVK_F7               0x76\n#define\tVK_F8               0x77\n#define\tVK_F9               0x78\n#define\tVK_F10              0x79\n#define\tVK_F11              0x7A\n#define\tVK_F12              0x7B\n#define\tVK_F13              0x7C\n#define\tVK_F14              0x7D\n#define\tVK_F15              0x7E\n#define\tVK_F16              0x7F\n#define\tVK_F17              0x80\n#define\tVK_F18              0x81\n#define\tVK_F19              0x82\n#define\tVK_F20              0x83\n#define\tVK_F21              0x84\n#define\tVK_F22              0x85\n#define\tVK_F23              0x86\n#define\tVK_F24              0x87\n#define\tVK_NONE_88          0x88\n#define\tVK_NONE_89          0x89\n#define\tVK_NONE_8A          0x8A\n#define\tVK_NONE_8B          0x8B\n#define\tVK_NONE_8C          0x8C\n#define\tVK_NONE_8D          0x8D\n#define\tVK_NONE_8E          0x8E\n#define\tVK_NONE_8F          0x8F\n#define\tVK_NUMLOCK          0x90\n#define\tVK_SCROLL           0x91\n#define\tVK_NONE_92\t\t\t  0x92\n#define\tVK_NONE_93\t\t\t  0x93\n#define\tVK_NONE_94\t\t\t  0x94\n#define\tVK_NONE_95\t\t\t  0x95\n#define\tVK_NONE_96\t\t\t  0x96\n#define\tVK_NONE_97\t\t\t  0x97\n#define\tVK_NONE_98\t\t\t  0x98\n#define\tVK_NONE_99\t\t\t  0x99\n#define\tVK_NONE_9A\t\t\t  0x9A\n#define\tVK_NONE_9B\t\t\t  0x9B\n#define\tVK_NONE_9C\t\t\t  0x9C\n#define\tVK_NONE_9D\t\t\t  0x9D\n#define\tVK_NONE_9E\t\t\t  0x9E\n#define\tVK_NONE_9F\t\t\t  0x9F\n#define\tVK_NONE_A0\t\t\t  0xA0\n#define\tVK_NONE_A1\t\t\t  0xA1\n#define\tVK_NONE_A2\t\t\t  0xA2\n#define\tVK_NONE_A3\t\t\t  0xA3\n#define\tVK_NONE_A4\t\t\t  0xA4\n#define\tVK_NONE_A5\t\t\t  0xA5\n#define\tVK_NONE_A6\t\t\t  0xA6\n#define\tVK_NONE_A7\t\t\t  0xA7\n#define\tVK_NONE_A8\t\t\t  0xA8\n#define\tVK_NONE_A9\t\t\t  0xA9\n#define\tVK_NONE_AA\t\t\t  0xAA\n#define\tVK_NONE_AB\t\t\t  0xAB\n#define\tVK_NONE_AC\t\t\t  0xAC\n#define\tVK_NONE_AD\t\t\t  0xAD\n#define\tVK_NONE_AE\t\t\t  0xAE\n#define\tVK_NONE_AF\t\t\t  0xAF\n#define\tVK_NONE_B0\t\t\t  0xB0\n#define\tVK_NONE_B1\t\t\t  0xB1\n#define\tVK_NONE_B2\t\t\t  0xB2\n#define\tVK_NONE_B3\t\t\t  0xB3\n#define\tVK_NONE_B4\t\t\t  0xB4\n#define\tVK_NONE_B5\t\t\t  0xB5\n#define\tVK_NONE_B6\t\t\t  0xB6\n#define\tVK_NONE_B7\t\t\t  0xB7\n#define\tVK_NONE_B8\t\t\t  0xB8\n#define\tVK_NONE_B9\t\t\t  0xB9\n#define\tVK_NONE_BA\t\t\t  0xBA\n#define\tVK_NONE_BB\t\t\t  0xBB\n#define\tVK_NONE_BC\t\t\t  0xBC\n#define\tVK_NONE_BD\t\t\t  0xBD\n#define\tVK_NONE_BE\t\t\t  0xBE\n#define\tVK_NONE_BF\t\t\t  0xBF\n#define\tVK_NONE_C0\t\t\t  0xC0\n#define\tVK_NONE_C1\t\t\t  0xC1\n#define\tVK_NONE_C2\t\t\t  0xC2\n#define\tVK_NONE_C3\t\t\t  0xC3\n#define\tVK_NONE_C4\t\t\t  0xC4\n#define\tVK_NONE_C5\t\t\t  0xC5\n#define\tVK_NONE_C6\t\t\t  0xC6\n#define\tVK_NONE_C7\t\t\t  0xC7\n#define\tVK_NONE_C8\t\t\t  0xC8\n#define\tVK_NONE_C9\t\t\t  0xC9\n#define\tVK_NONE_CA\t\t\t  0xCA\n#define\tVK_NONE_CB\t\t\t  0xCB\n#define\tVK_NONE_CC\t\t\t  0xCC\n#define\tVK_NONE_CD\t\t\t  0xCD\n#define\tVK_NONE_CE\t\t\t  0xCE\n#define\tVK_NONE_CF\t\t\t  0xCF\n#define\tVK_NONE_D0\t\t\t  0xD0\n#define\tVK_NONE_D1\t\t\t  0xD1\n#define\tVK_NONE_D2\t\t\t  0xD2\n#define\tVK_NONE_D3\t\t\t  0xD3\n#define\tVK_NONE_D4\t\t\t  0xD4\n#define\tVK_NONE_D5\t\t\t  0xD5\n#define\tVK_NONE_D6\t\t\t  0xD6\n#define\tVK_NONE_D7\t\t\t  0xD7\n#define\tVK_NONE_D8\t\t\t  0xD8\n#define\tVK_NONE_D9\t\t\t  0xD9\n#define\tVK_NONE_DA\t\t\t  0xDA\n#define\tVK_NONE_DB\t\t\t  0xDB\n#define\tVK_NONE_DC\t\t\t  0xDC\n#define\tVK_NONE_DD\t\t\t  0xDD\n#define\tVK_NONE_DE\t\t\t  0xDE\n#define\tVK_NONE_DF\t\t\t  0xDF\n#define\tVK_NONE_E0\t\t\t  0xE0\n#define\tVK_NONE_E1\t\t\t  0xE1\n#define\tVK_NONE_E2\t\t\t  0xE2\n#define\tVK_NONE_E3\t\t\t  0xE3\n#define\tVK_NONE_E4\t\t\t  0xE4\n#define\tVK_NONE_E5\t\t\t  0xE5\n#define\tVK_NONE_E6\t\t\t  0xE6\n#define\tVK_NONE_E7\t\t\t  0xE7\n#define\tVK_NONE_E8\t\t\t  0xE8\n#define\tVK_NONE_E9\t\t\t  0xE9\n#define\tVK_NONE_EA\t\t\t  0xEA\n#define\tVK_NONE_EB\t\t\t  0xEB\n#define\tVK_NONE_EC\t\t\t  0xEC\n#define\tVK_NONE_ED\t\t\t  0xED\n#define\tVK_NONE_EE\t\t\t  0xEE\n#define\tVK_NONE_EF\t\t\t  0xEF\n#define\tVK_NONE_F0\t\t\t  0xF0\n#define\tVK_NONE_F1\t\t\t  0xF1\n#define\tVK_NONE_F2\t\t\t  0xF2\n#define\tVK_NONE_F3\t\t\t  0xF3\n#define\tVK_NONE_F4\t\t\t  0xF4\n#define\tVK_NONE_F5\t\t\t  0xF5\n#define\tVK_NONE_F6\t\t\t  0xF6\n#define\tVK_NONE_F7\t\t\t  0xF7\n#define\tVK_NONE_F8\t\t\t  0xF8\n#define\tVK_NONE_F9\t\t\t  0xF9\n#define\tVK_NONE_FA\t\t\t  0xFA\n#define\tVK_NONE_FB\t\t\t  0xFB\n#define\tVK_NONE_FC\t\t\t  0xFC\n#define\tVK_NONE_FD\t\t\t  0xFD\n#define\tVK_NONE_FE\t\t\t  0xFE\n#define\tVK_NONE_FF\t\t\t  0xFF\n\n#define\tVK_UPLEFT\t\t\t  VK_HOME\n#define\tVK_UPRIGHT\t\t\t  VK_PRIOR\n#define\tVK_DOWNLEFT\t\t\t  VK_END\n#define\tVK_DOWNRIGHT\t\t  VK_NEXT\n#define\tVK_ALT\t\t\t\t  VK_MENU\n\nenum {\n\t//\n\t// Define all the KA types as variations of the VK types.  This is\n\t// so the KA functions will work properly under windows 95.\n\t//\n\tKA_NONE\t\t\t\t= 0,\n\tKA_MORE \t\t\t\t= 1,\n\tKA_SETBKGDCOL \t\t= 2,\n\tKA_SETFORECOL \t\t= 6,\n\tKA_FORMFEED \t\t= 12,\n\tKA_SPCTAB \t\t\t= 20,\n\tKA_SETX \t\t\t\t= 25,\n\tKA_SETY \t\t\t\t= 26,\n\n\tKA_SPACE\t\t\t\t= 32,\t\t\t\t\t/*   */\n\tKA_EXCLAMATION,\t\t\t\t\t\t\t/* ! */\n\tKA_DQUOTE,\t\t\t\t\t\t\t\t\t/* \" */\n\tKA_POUND,\t\t\t\t\t\t\t\t\t/* # */\n\tKA_DOLLAR,\t\t\t\t\t\t\t\t\t/* $ */\n\tKA_PERCENT,\t\t\t\t\t\t\t\t\t/* % */\n\tKA_AMPER,\t\t\t\t\t\t\t\t\t/* & */\n\tKA_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKA_LPAREN,\t\t\t\t\t\t\t\t\t/* ( */\n\tKA_RPAREN,\t\t\t\t\t\t\t\t\t/* ) */\n\tKA_ASTERISK,\t\t\t\t\t\t\t\t/* * */\n\tKA_PLUS,\t\t\t\t\t\t\t\t\t\t/* + */\n\tKA_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKA_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKA_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKA_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKA_0, KA_1, KA_2, KA_3, KA_4, KA_5, KA_6, KA_7, KA_8, KA_9,\n\tKA_COLON,\t\t\t\t\t\t\t\t\t/* : */\n\tKA_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKA_LESS_THAN,\t\t\t\t\t\t\t\t/* < */\n\tKA_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\tKA_GREATER_THAN,\t\t\t\t\t\t\t/* > */\n\tKA_QUESTION,\t\t\t\t\t\t\t\t/* ? */\n\n\tKA_AT,\t\t\t\t\t\t\t\t\t\t/* @ */\n\tKA_A,\t\t\t\t\t\t\t\t\t\t\t/* A */\n\tKA_B,\t\t\t\t\t\t\t\t\t\t\t/* B */\n\tKA_C,\t\t\t\t\t\t\t\t\t\t\t/* C */\n\tKA_D,\t\t\t\t\t\t\t\t\t\t\t/* D */\n\tKA_E,\t\t\t\t\t\t\t\t\t\t\t/* E */\n\tKA_F,\t\t\t\t\t\t\t\t\t\t\t/* F */\n\tKA_G,\t\t\t\t\t\t\t\t\t\t\t/* G */\n\tKA_H,\t\t\t\t\t\t\t\t\t\t\t/* H */\n\tKA_I,\t\t\t\t\t\t\t\t\t\t\t/* I */\n\tKA_J,\t\t\t\t\t\t\t\t\t\t\t/* J */\n\tKA_K,\t\t\t\t\t\t\t\t\t\t\t/* K */\n\tKA_L,\t\t\t\t\t\t\t\t\t\t\t/* L */\n\tKA_M,\t\t\t\t\t\t\t\t\t\t\t/* M */\n\tKA_N,\t\t\t\t\t\t\t\t\t\t\t/* N */\n\tKA_O,\t\t\t\t\t\t\t\t\t\t\t/* O */\n\n\tKA_P,\t\t\t\t\t\t\t\t\t\t\t/* P */\n\tKA_Q,\t\t\t\t\t\t\t\t\t\t\t/* Q */\n\tKA_R,\t\t\t\t\t\t\t\t\t\t\t/* R */\n\tKA_S,\t\t\t\t\t\t\t\t\t\t\t/* S */\n\tKA_T,\t\t\t\t\t\t\t\t\t\t\t/* T */\n\tKA_U,\t\t\t\t\t\t\t\t\t\t\t/* U */\n\tKA_V,\t\t\t\t\t\t\t\t\t\t\t/* V */\n\tKA_W,\t\t\t\t\t\t\t\t\t\t\t/* W */\n\tKA_X,\t\t\t\t\t\t\t\t\t\t\t/* X */\n\tKA_Y,\t\t\t\t\t\t\t\t\t\t\t/* Y */\n\tKA_Z,\t\t\t\t\t\t\t\t\t\t\t/* Z */\n\tKA_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKA_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\tKA_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKA_CARROT,\t\t\t\t\t\t\t\t\t/* ^ */\n\tKA_UNDERLINE,\t\t\t\t\t\t\t\t/* _ */\n\n\tKA_GRAVE,\t\t\t\t\t\t\t\t\t/* ` */\n\tKA_a,\t\t\t\t\t\t\t\t\t\t\t/* a */\n\tKA_b,\t\t\t\t\t\t\t\t\t\t\t/* b */\n\tKA_c,\t\t\t\t\t\t\t\t\t\t\t/* c */\n\tKA_d,\t\t\t\t\t\t\t\t\t\t\t/* d */\n\tKA_e,\t\t\t\t\t\t\t\t\t\t\t/* e */\n\tKA_f,\t\t\t\t\t\t\t\t\t\t\t/* f */\n\tKA_g,\t\t\t\t\t\t\t\t\t\t\t/* g */\n\tKA_h,\t\t\t\t\t\t\t\t\t\t\t/* h */\n\tKA_i,\t\t\t\t\t\t\t\t\t\t\t/* i */\n\tKA_j,\t\t\t\t\t\t\t\t\t\t\t/* j */\n\tKA_k,\t\t\t\t\t\t\t\t\t\t\t/* k */\n\tKA_l,\t\t\t\t\t\t\t\t\t\t\t/* l */\n\tKA_m,\t\t\t\t\t\t\t\t\t\t\t/* m */\n\tKA_n,\t\t\t\t\t\t\t\t\t\t\t/* n */\n\tKA_o,\t\t\t\t\t\t\t\t\t\t\t/* o */\n\n\tKA_p,\t\t\t\t\t\t\t\t\t\t\t/* p */\n\tKA_q,\t\t\t\t\t\t\t\t\t\t\t/* q */\n\tKA_r,\t\t\t\t\t\t\t\t\t\t\t/* r */\n\tKA_s,\t\t\t\t\t\t\t\t\t\t\t/* s */\n\tKA_t,\t\t\t\t\t\t\t\t\t\t\t/* t */\n\tKA_u,\t\t\t\t\t\t\t\t\t\t\t/* u */\n\tKA_v,\t\t\t\t\t\t\t\t\t\t\t/* v */\n\tKA_w,\t\t\t\t\t\t\t\t\t\t\t/* w */\n\tKA_x,\t\t\t\t\t\t\t\t\t\t\t/* x */\n\tKA_y,\t\t\t\t\t\t\t\t\t\t\t/* y */\n\tKA_z,\t\t\t\t\t\t\t\t\t\t\t/* z */\n\tKA_LBRACE,\t\t\t\t\t\t\t\t\t/* { */\n\tKA_BAR,\t\t\t\t\t\t\t\t\t\t/* | */\n\tKA_RBRACE,\t\t\t\t\t\t\t\t\t/* ] */\n\tKA_TILDA,\t\t\t\t\t\t\t\t\t/* ~ */\n\n\tKA_ESC \t\t\t\t= VK_ESCAPE | WWKEY_VK_BIT,\n\tKA_EXTEND \t\t\t= VK_ESCAPE | WWKEY_VK_BIT,\n\tKA_RETURN \t\t\t= VK_RETURN | WWKEY_VK_BIT,\n\tKA_BACKSPACE \t\t= VK_BACK | WWKEY_VK_BIT,\n\tKA_TAB \t\t\t\t= VK_TAB  | WWKEY_VK_BIT,\n\tKA_DELETE\t\t\t= VK_DELETE | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* <DELETE> */\n\tKA_INSERT\t\t\t= VK_INSERT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* <INSERT> */\n\tKA_PGDN\t\t\t\t= VK_NEXT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <PAGE DOWN> */\n\tKA_DOWNRIGHT \t\t= VK_NEXT | WWKEY_VK_BIT,\n\tKA_DOWN\t\t\t\t= VK_DOWN | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <DOWN ARROW> */\n\tKA_END\t\t\t\t= VK_END | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <END> */\n\tKA_DOWNLEFT \t\t= VK_END | WWKEY_VK_BIT,\n\tKA_RIGHT\t\t\t\t= VK_RIGHT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* <RIGHT ARROW> */\n\tKA_KEYPAD5\t\t\t= VK_SELECT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* NUMERIC KEY PAD <5> */\n\tKA_LEFT\t\t\t\t= VK_LEFT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ARROW> */\n\tKA_PGUP\t\t\t\t= VK_PRIOR | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <PAGE UP> */\n\tKA_UPRIGHT \t\t\t= VK_PRIOR | WWKEY_VK_BIT,\n\tKA_UP\t\t\t\t\t= VK_UP | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <UP ARROW> */\n\tKA_HOME\t\t\t\t= VK_HOME | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <HOME> */\n\tKA_UPLEFT \t\t\t= VK_HOME | WWKEY_VK_BIT,\n\tKA_F12\t\t\t\t= VK_F12 | WWKEY_VK_BIT,\n\tKA_F11\t\t\t\t= VK_F11 | WWKEY_VK_BIT,\n\tKA_F10\t\t\t\t= VK_F10 | WWKEY_VK_BIT,\n\tKA_F9 \t\t\t\t= VK_F9 | WWKEY_VK_BIT,\n\tKA_F8\t\t\t\t\t= VK_F8 | WWKEY_VK_BIT,\n\tKA_F7\t\t\t\t\t= VK_F7 | WWKEY_VK_BIT,\n\tKA_F6\t\t\t\t\t= VK_F6 | WWKEY_VK_BIT,\n\tKA_F5\t\t\t\t\t= VK_F5 | WWKEY_VK_BIT,\n\tKA_F4\t\t\t\t\t= VK_F4 | WWKEY_VK_BIT,\n\tKA_F3\t\t\t\t\t= VK_F3 | WWKEY_VK_BIT,\n\tKA_F2\t\t\t\t\t= VK_F2 | WWKEY_VK_BIT,\n\tKA_F1\t\t\t\t\t= VK_F1 | WWKEY_VK_BIT,\n\tKA_LMOUSE \t \t\t= VK_LBUTTON | WWKEY_VK_BIT,\n\tKA_RMOUSE \t \t\t= VK_RBUTTON | WWKEY_VK_BIT,\n\n\tKA_SHIFT_BIT \t\t= WWKEY_SHIFT_BIT,\n\tKA_CTRL_BIT  \t\t= WWKEY_CTRL_BIT,\n\tKA_ALT_BIT   \t\t= WWKEY_ALT_BIT,\n\tKA_RLSE_BIT  \t\t= WWKEY_RLS_BIT,\n\n\t//\n\t// Define all the KN types as variations of the KA types.  This is\n\t// so the KN functions will work properly under windows 95.\n\t//\n\tKN_NONE\t\t\t\t= 0,\n\tKN_GRAVE \t\t\t= KA_GRAVE,\n\tKN_1 \t\t\t\t\t= KA_1,\n\tKN_2 \t\t\t\t\t= KA_2,\n\tKN_3 \t\t\t\t\t= KA_3,\n\tKN_4 \t\t\t\t\t= KA_4,\n\tKN_5 \t\t\t\t\t= KA_5,\n\tKN_6 \t\t\t\t\t= KA_6,\n\tKN_7 \t\t\t\t\t= KA_7,\n\tKN_8 \t\t\t\t\t= KA_8,\n\tKN_9 \t\t\t\t\t= KA_9,\n\tKN_0 \t\t\t\t\t= KA_0,\n\tKN_MINUS \t\t\t= KA_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKN_EQUAL \t\t\t= KA_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\n\tKN_BACKSPACE\t\t= KA_BACKSPACE,\n\n\tKN_TAB\t\t\t\t= KA_TAB,\t\t\t\t\t\t\t\t\t\t/* <TAB> */\n\tKN_Q \t\t\t\t\t= KA_q,\n\tKN_W \t\t\t\t\t= KA_w,\n\tKN_E \t\t\t\t\t= KA_e,\n\tKN_R \t\t\t\t\t= KA_r,\n\tKN_T \t\t\t\t\t= KA_t,\n\tKN_Y \t\t\t\t\t= KA_y,\n\tKN_U \t\t\t\t\t= KA_u,\n\tKN_I \t\t\t\t\t= KA_i,\n\tKN_O \t\t\t\t\t= KA_o,\n\tKN_P \t\t\t\t\t= KA_p,\n\tKN_LBRACKET\t\t\t= KA_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKN_RBRACKET\t\t\t= KA_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKN_BACKSLASH\t\t= KA_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\n\n\tKN_A \t\t\t\t\t= KA_a,\n\tKN_S \t\t\t\t\t= KA_s,\n\tKN_D \t\t\t\t\t= KA_d,\n\tKN_F \t\t\t\t\t= KA_f,\n\tKN_G \t\t\t\t\t= KA_g,\n\tKN_H \t\t\t\t\t= KA_h,\n\tKN_J \t\t\t\t\t= KA_j,\n\tKN_K \t\t\t\t\t= KA_k,\n\tKN_L \t\t\t\t\t= KA_l,\n\tKN_SEMICOLON \t\t= KA_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKN_SQUOTE \t\t\t= KA_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKN_BACKSLASH2 \t\t= KA_BACKSLASH,\n\tKN_RETURN \t\t\t= KA_RETURN,\n\tKN_Z \t\t\t\t\t= KA_z,\n\tKN_X \t\t\t\t\t= KA_x,\n\tKN_C \t\t\t\t\t= KA_c,\n\tKN_V \t\t\t\t\t= KA_v,\n\tKN_B \t\t\t\t\t= KA_b,\n\tKN_N \t\t\t\t\t= KA_n,\n\tKN_M \t\t\t\t\t= KA_m,\n\tKN_COMMA \t\t\t= KA_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKN_PERIOD \t\t\t= KA_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKN_SLASH \t\t\t= KA_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\tKN_SPACE \t\t\t= KA_SPACE,\n\tKN_LMOUSE\t\t\t= KA_LMOUSE,\n\tKN_RMOUSE\t\t\t= KA_RMOUSE,\n\n\tKN_HOME\t\t\t\t= KA_HOME,\t\t\t\t\t\t\t\t\t\t/* num key pad 7 */\n\tKN_UPLEFT\t\t\t= KA_UPLEFT,\n\tKN_LEFT\t\t\t\t= KA_LEFT,\t\t\t\t\t\t\t\t\t\t/* num key pad 4 */\n\tKN_END\t\t\t\t= KA_END,\t\t\t\t\t\t\t\t\t\t/* num key pad 1 */\n\tKN_DOWNLEFT\t\t\t= KA_DOWNLEFT,\n\n\tKN_KEYPAD_SLASH\t= KA_SLASH,\t\t\t\t\t\t\t\t\t\t\t\t/* num key pad / */\n\tKN_UP\t\t\t\t\t= KA_UP,\t\t\t\t\t\t\t\t\t\t\t/* num key pad 8 */\n\tKN_CENTER\t\t\t= KA_KEYPAD5,\t\t\t\t\t\t\t\t\t/* num key pad 5 */\n\tKN_DOWN\t\t\t\t= KA_DOWN,\t\t\t\t\t\t\t\t\t\t/* num key pad 2 */\n\tKN_INSERT\t\t\t= KA_INSERT,\t\t\t\t\t\t\t\t\t/* num key pad 0 */\n\tKN_KEYPAD_ASTERISK= KA_ASTERISK,\t\t\t\t\t\t\t\t\t/* num key pad * */\n\tKN_PGUP\t\t\t\t= KA_PGUP,\t\t\t\t\t\t\t\t\t\t/* num key pad 9 */\n\tKN_UPRIGHT\t\t\t= KA_UPRIGHT,\n\tKN_RIGHT\t\t\t\t= KA_RIGHT,\t\t\t\t\t\t\t\t\t/* num key pad 6 */\n\tKN_PGDN\t\t\t\t= KA_PGDN,\t\t\t\t\t\t\t\t\t\t/* num key pad 3 */\n\tKN_DOWNRIGHT\t\t= KA_DOWNRIGHT,\n\tKN_DELETE\t\t\t= KA_DELETE,\t\t\t\t\t\t\t\t\t/* num key pad . */\n\n\tKN_KEYPAD_MINUS\t= KA_MINUS,\t\t\t\t\t\t\t/* num key pad - */\n\tKN_KEYPAD_PLUS\t\t= KA_PLUS,\t\t\t\t\t\t\t/* num key pad + */\n\n\n\tKN_KEYPAD_RETURN\t= KA_RETURN,\t\t\t\t\t\t\t/* num key pad <ENTER> */\n\n\tKN_ESC\t\t\t\t= KA_ESC,\n\tKN_F1\t\t\t\t\t= KA_F1,\n\tKN_F2\t\t\t\t\t= KA_F2,\n\tKN_F3\t\t\t\t\t= KA_F3,\n\tKN_F4\t\t\t\t\t= KA_F4,\n\tKN_F5\t\t\t\t\t= KA_F5,\n\tKN_F6\t\t\t\t\t= KA_F6,\n\tKN_F7\t\t\t\t\t= KA_F7,\n\tKN_F8\t\t\t\t\t= KA_F8,\n\tKN_F9\t\t\t\t\t= KA_F9,\n\tKN_F10\t\t\t\t= KA_F10,\n\tKN_F11\t\t\t\t= KA_F11,\n\tKN_F12\t\t\t\t= KA_F12,\n\n\tKN_PRNTSCRN\t\t\t= VK_PRINT | WWKEY_VK_BIT,\n\tKN_CAPSLOCK\t\t\t= VK_CAPITAL | WWKEY_VK_BIT,\n\tKN_SCROLLLOCK\t\t= VK_SCROLL | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t/* <SCROLL LOCK> */\n\tKN_PAUSE\t\t\t\t= VK_PAUSE | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* <PAUSE> */\n\tKN_LSHIFT\t\t\t= VK_SHIFT | WWKEY_VK_BIT,\n\tKN_RSHIFT\t\t\t= VK_SHIFT | WWKEY_VK_BIT,\n\tKN_LCTRL\t\t\t\t= VK_CONTROL | WWKEY_VK_BIT,\n\tKN_RCTRL\t\t\t\t= VK_CONTROL | WWKEY_VK_BIT,\n\tKN_LALT\t\t\t\t= VK_MENU | WWKEY_VK_BIT,\n\tKN_RALT\t\t\t\t= VK_MENU | WWKEY_VK_BIT,\n\tKN_E_INSERT\t\t\t= VK_INSERT | WWKEY_VK_BIT,\n\tKN_E_DELETE \t\t= VK_DELETE | WWKEY_VK_BIT,\n\tKN_E_LEFT\t\t\t= VK_LEFT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <LEFT ARROW> */\n\tKN_E_HOME\t\t\t= VK_HOME | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <HOME> */\n\tKN_E_END\t\t\t\t= VK_END | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <END> */\n\tKN_E_UP\t\t\t\t= VK_UP | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* extended <UP ARROW> */\n\tKN_E_DOWN\t\t\t= VK_DOWN | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <DOWN ARROW> */\n\tKN_E_PGUP\t\t\t= VK_PRIOR | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <PAGE UP> */\n\tKN_E_PGDN   \t\t= VK_NEXT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <PAGE DOWN> */\n\tKN_E_RIGHT\t\t\t= VK_RIGHT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <RIGHT ARROW> */\n\tKN_NUMLOCK\t\t\t= VK_NUMLOCK | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* <NUM LOCK> */\n\n\tKN_SHIFT_BIT \t\t= WWKEY_SHIFT_BIT,\n\tKN_CTRL_BIT  \t\t= WWKEY_CTRL_BIT | WWKEY_VK_BIT,\n\tKN_ALT_BIT   \t\t= WWKEY_ALT_BIT | WWKEY_VK_BIT,\n\tKN_RLSE_BIT  \t\t= WWKEY_RLS_BIT,\n\tKN_BUTTON    \t\t= WWKEY_BTN_BIT,\n};\n\n\nextern WWKeyboardClass *_Kbd;\n\n\n/*\n** The following routines provide some compatability with the old westwood\n** library.\n*/\nint Check_Key(void);\nint Check_Key_Num(void);\nint Get_Key_Num(void);\nint Get_Key(void);\nint KN_To_KA(int key);\nvoid Clear_KeyBuffer(void);\nint Key_Down(int key);\nint KN_To_VK(int key);\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = keyboard\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\t\t\t\t\tkeyboard.obj\t\t&\n\t\t\t\t\tmouse.obj\t\t\t&\n\t\t\t\t\twwmouse.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = keyboard\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t   keyboard.obj\t\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) \n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n -+keyboard.obj\n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = keyboard\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\t\t\t\t\tkeyboard.obj\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WWLIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include \n\t copy *.inc $(%WIN32LIB)\\include \n\t copy *.cpp $(%WIN32LIB)\\srcdebug \n\t copy *.asm $(%WIN32LIB)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/MOUSE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood 32 bit Library                                      *\n *                                                                                             *\n *                    File Name : MOUSE.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 12/12/95                                                     *\n *                                                                                             *\n *                  Last Update : December 12, 1995 [PWG]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   WWMouseClass::WWMouseClass -- Constructor for the Mouse Class                                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"mouse.h\"\n#include <mmsystem.h>\n\nstatic WWMouseClass *_Mouse=NULL;\nvoid CALLBACK Process_Mouse( UINT event_id, UINT res1 , DWORD user, DWORD  res2, DWORD  res3 );\nextern BOOL GameInFocus;\n\n\n/***********************************************************************************************\n * MOUSECLASS::MOUSECLASS -- Constructor for the Mouse Class                                   *\n *                                                                                             *\n * INPUT:\t\tGraphicViewPortClass * screen - pointer to screen mouse is created for\t\t\t\t *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/12/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nWWMouseClass::WWMouseClass(GraphicViewPortClass *scr, int mouse_max_width, int mouse_max_height)\n{\n\tMouseCursor \t= new char[mouse_max_width * mouse_max_height];\n\tMouseXHot\t\t= 0;\n\tMouseYHot\t\t= 0;\n\tCursorWidth\t\t= 0;\n\tCursorHeight\t= 0;\n\n\tMouseBuffer\t\t= new char[mouse_max_width * mouse_max_height];\n\tMouseBuffX\t\t= -1;\n\tMouseBuffY  \t= -1;\n\tMaxWidth\t\t\t= mouse_max_width;\n\tMaxHeight\t\t= mouse_max_height;\n\n\tMouseCXLeft\t\t= 0;\n\tMouseCYUpper\t= 0;\n\tMouseCXRight\t= 0;\n\tMouseCYLower\t= 0;\n\tMCFlags\t\t\t= 0;\n\tMCCount\t\t\t= 0;\n\n\tScreen\t\t\t= scr;\n\tPrevCursor\t\t= NULL;\n\tMouseUpdate\t\t= 0;\n\tState\t\t\t\t= 1;\n\ttimeBeginPeriod ( 1000/ 60);\n\n\tInitializeCriticalSection (&MouseCriticalSection);\n\t//\n\t// Install the timer callback event handler\n\t//\n\n\tEraseBuffer\t\t= new char[mouse_max_width * mouse_max_height];\n\tEraseBuffX\t\t= -1;\n\tEraseBuffY  \t= -1;\n\tEraseBuffHotX\t= -1;\n\tEraseBuffHotY\t= -1;\n\tEraseFlags\t\t= FALSE;\n\n\t_Mouse\t\t\t= this;\n\tTimerHandle = timeSetEvent( 1000/60 , 1 , ::Process_Mouse, 0 , TIME_PERIODIC);\n\n\t/*\n\t** Force the windows mouse pointer to stay withing the graphic view port region\n\t*/\n\tSet_Cursor_Clip();\n}\n\nWWMouseClass::~WWMouseClass()\n{\n\tMouseUpdate++;\n\n\tif (MouseCursor) delete[] MouseCursor;\n\tif (MouseBuffer) delete[] MouseBuffer;\n\tif (TimerHandle) {\n\t\ttimeKillEvent(TimerHandle);\n\t}\n\ttimeEndPeriod (1000/60);\n\tDeleteCriticalSection(&MouseCriticalSection);\n\n\t/*\n\t** Free up the windows mouse pointer movement\n\t*/\n\tClear_Cursor_Clip();\n}\n\n\nvoid Block_Mouse(GraphicBufferClass *buffer)\n{\n\tif (_Mouse){\n\t\t_Mouse->Block_Mouse(buffer);\n\t}\n}\n\n\nvoid Unblock_Mouse(GraphicBufferClass *buffer)\n{\n\tif (_Mouse){\n\t\t_Mouse->Unblock_Mouse(buffer);\n\t}\n}\n\n\n\nvoid WWMouseClass::Block_Mouse(GraphicBufferClass *buffer)\n{\n\tif (buffer == Screen->Get_Graphic_Buffer()){\n\t\tEnterCriticalSection(&MouseCriticalSection);\n\t}\n}\n\n\nvoid WWMouseClass::Unblock_Mouse(GraphicBufferClass *buffer)\n{\n\tif (buffer == Screen->Get_Graphic_Buffer()){\n\t\tLeaveCriticalSection(&MouseCriticalSection);\n\t}\n}\n\n\n\n\n\nvoid WWMouseClass::Set_Cursor_Clip(void)\n{\n\n\tif (Screen){\n\t\tRECT\tregion;\n\n\t\tregion.left\t\t= 0;\n\t\tregion.top \t\t= 0;\n\t\tregion.right\t= Screen->Get_Width();\n\t\tregion.bottom\t= Screen->Get_Height();\n\n\t\tClipCursor(&region);\n\t}\n}\n\n\n\nvoid WWMouseClass::Clear_Cursor_Clip(void)\n{\n\tClipCursor(NULL);\n}\n\n\n\nvoid WWMouseClass::Process_Mouse(void)\n{\n\tPOINT \tpt;\t\t\t\t\t// define a structure to hold current cursor pos\n\n\t//\n\t// If the mouse is currently hidden or it has not been installed, then we\n\t// have no need to redraw the mouse.\n\t//\n\tif (!Screen || !_Mouse || State > 0 || MouseUpdate || EraseFlags || !GameInFocus)\n\t\treturn;\n\n\t//\n\t// Make sure there are no conflicts with other\n\t// threads that may try and lock the screen buffer\n\t//\n\t//Block_Mouse(Screen->Get_Graphic_Buffer());\n\n\t//\n\t// If the screen is already locked by another thread then just exit\n\t//\n\tif (Screen->Get_LockCount()!=0){\n\t\t//Unblock_Mouse(Screen->Get_Graphic_Buffer());\n\t\treturn;\n\t}\n\n\t//\n\t// Get the mouse's current real cursor position\n\t//\n\tGetCursorPos(&pt);\t\t\t// get the current cursor position\n\t//\n\t// If the mouse has moved then we are responsible to redraw the mouse\n\t//\n\tif (pt.x != MouseBuffX || pt.y != MouseBuffY) {\n\t\t//\n\t\t// If we can't lock the surface we need to draw to, we cannot update\n\t\t// the mouse.\n\t\t//\n\t\tif (Screen->Lock()) \t{\n\t\t\t//\n\t\t\t// Erase the old mouse by dumping the mouses shadow buff\n\t\t\t//   to the screen (if its position had ever been recorded).\n\t\t\t//\n\t\t\tLow_Hide_Mouse();\n\n\t\t\t//\n\t\t\t// Verify that the mouse has not gone into a conditional hiden area\n\t\t\t// If it has, mark it as being in one.\n\t\t\t//\n\t\t\tif (MCFlags & CONDHIDE && pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {\n\t\t\t\tMCFlags |= CONDHIDDEN;\n\t\t\t}\n\n\t\t\t//\n\t\t\t// Show the mouse if we are allowed to.\n\t\t\t//\n\t\t\tif (!(MCFlags & CONDHIDDEN)) \t{\n\t\t\t\tLow_Show_Mouse(pt.x, pt.y);\n\t\t\t}\n\t\t\t//\n\t\t\t// Finally unlock the destination surface as we have sucessfully\n\t\t\t// updated the mouse.\n\t\t\t//\n\t\t\tScreen->Unlock();\n\t\t}\n\t}\n\n\t//\n\t// Allow other threads to lock the screen again\n\t//\n\t//Unblock_Mouse(Screen->Get_Graphic_Buffer());\n}\n\nvoid *WWMouseClass::Set_Cursor(int xhotspot, int yhotspot, void *cursor)\n{\n\t//\n\t// If the pointer to the cursor we got is invalid, or its the same as the\n\t// currently set cursor then just return.\n\tif (!cursor || cursor == PrevCursor)\n\t\treturn(cursor);\n\n\t//\n\t// Wait until we have exclusive access to our data\n\t//\n\tMouseUpdate++;\n\t//\n\t// Since we are updating the mouse we need to hide the cursor so we\n\t// do not get some sort of weird transformation.\n\t//\n\tHide_Mouse();\n\t//\n\t// Now convert the shape to a mouse cursor with the given hotspots and\n\t// set it as our current mouse.\n\t//\n\tvoid *retval = ASM_Set_Mouse_Cursor(this, xhotspot, yhotspot, cursor);\n\t//\n\t// Show the mouse which will force it to appear with the new shape we\n\t// have assigned.\n\t//\n\tShow_Mouse();\n\t//\n\t// We are done updating the mouse cursor so on to bigger and better things.\n\t//\n\tMouseUpdate--;\n\t//\n\t// Return the previous mouse cursor which as conveniantly passed back by\n\t// Asm_Set_Mouse_Cursor.\n\t//\n\treturn(retval);\n}\n\nvoid WWMouseClass::Low_Hide_Mouse()\n{\n\tif (!State) {\n\t\tif (MouseBuffX != -1 || MouseBuffY != -1) {\n\t\t\tif (Screen->Lock()){\n\t\t\t\tMouse_Shadow_Buffer(this, Screen, MouseBuffer, MouseBuffX, MouseBuffY, MouseXHot, MouseYHot, 0);\n\t\t\t\tScreen->Unlock();\n\t\t\t}\n\t\t}\n\t\tMouseBuffX = -1;\n\t\tMouseBuffY = -1;\n\t}\n\tState++;\n}\nvoid WWMouseClass::Hide_Mouse()\n{\n\tMouseUpdate++;\n\tLow_Hide_Mouse();\n\tMouseUpdate--;\n}\n\n\nvoid WWMouseClass::Low_Show_Mouse(int x, int y)\n{\n\t//\n\t// If the mouse is already visible then just ignore the problem.\n\t//\n\tif (State == 0) return;\n\t//\n\t// Make the mouse a little bit more visible\n\t//\n\tState--;\n\n\t//\n\t//\tIf the mouse is completely visible then draw it at its current\n\t// position.\n\t//\n\tif (!State)\t{\n\t\t//\n\t\t// Try to lock the screen til we sucessfully get a lock.\n\t\t//\n\t\tif (Screen->Lock()){\n\t\t\t//\n\t\t\t// Save off the area behind the mouse.\n\t\t\t//\n\t\t\tMouse_Shadow_Buffer(this, Screen, MouseBuffer, x, y, MouseXHot, MouseYHot, 1);\n\t\t\t//\n\t\t\t// Draw the mouse in its new location\n\t\t\t//\n\t\t\t::Draw_Mouse(this, Screen, x, y);\n\t\t\t//\n\t\t\t// Save off the positions that we saved the buffer from\n\t\t\t//\n\t\t\tMouseBuffX = x;\n\t\t\tMouseBuffY = y;\n\t\t\t//\n\t\t\t// Unlock the screen and lets get moving.\n\t\t\t//\n\t\t\tScreen->Unlock();\n\t\t}\n\t}\n}\n\nvoid WWMouseClass::Show_Mouse()\n{\n\tPOINT\tpt;\n\tGetCursorPos(&pt);\n\n\tMouseUpdate++;\n\tLow_Show_Mouse(pt.x, pt.y);\n\tMouseUpdate--;\n}\n\nvoid WWMouseClass::Conditional_Hide_Mouse(int x1, int y1, int x2, int y2)\n{\n\tPOINT\tpt;\n\n\tMouseUpdate++;\n\n\t//\n\t// First of all, adjust all the coordinates so that they handle\n\t// the fact that the hotspot is not necessarily the upper left\n\t// corner of the mouse.\n\t//\n\tx1 -= (CursorWidth - MouseXHot);\n\tx1  = MAX(0, x1);\n\ty1 -= (CursorHeight - MouseYHot);\n\ty1  = MAX(0, y1);\n\tx2  += MouseXHot;\n\tx2  = MIN(x2, Screen->Get_Width());\n\ty2  += MouseYHot;\n\ty2  = MIN(y2, Screen->Get_Height());\n\n\t// The mouse could be in one of four conditions.\n\t// 1) The mouse is visible and no conditional hide has been specified.\n\t// \t(perform normal region checking with possible hide)\n\t// 2) The mouse is hidden and no conditional hide as been specified.\n\t// \t(record region and do nothing)\n\t// 3) The mouse is visible and a conditional region has been specified\n\t// \t(expand region and perform check with possible hide).\n\t// 4) The mouse is already hidden by a previous conditional.\n\t// \t(expand region and do nothing)\n\t//\n\t// First: Set or expand the region according to the specified parameters\n\tif (!MCCount) {\n\t\tMouseCXLeft\t\t= x1;\n\t\tMouseCYUpper\t= y1;\n\t\tMouseCXRight\t= x2;\n\t\tMouseCYLower\t= y2;\n\t} else {\n\t\tMouseCXLeft\t\t= MIN(x1, MouseCXLeft);\n\t\tMouseCYUpper\t= MIN(y1, MouseCYUpper);\n\t\tMouseCXRight\t= MAX(x2, MouseCXRight);\n\t\tMouseCYLower\t= MAX(y2, MouseCYLower);\n\t}\n\t//\n\t// If the mouse isn't already hidden, then check its location against\n\t// the hiding region and hide if necessary.\n\t//\n\tif (!(MCFlags & CONDHIDDEN)) {\n\t\tGetCursorPos(&pt);\n\t\tif (MouseBuffX >= MouseCXLeft && MouseBuffX <= MouseCXRight && MouseBuffY >= MouseCYUpper && MouseBuffY <= MouseCYLower) {\n\t\t\tLow_Hide_Mouse();\n\t\t\tMCFlags |= CONDHIDDEN;\n\t\t}\n\t}\n\t//\n\t// Record the fact that a conditional hide was called and then exit\n\t//\n\t//\n\tMCFlags |= CONDHIDE;\n\tMCCount++;\n\tMouseUpdate--;\n\n}\nvoid WWMouseClass::Conditional_Show_Mouse(void)\n{\n\tMouseUpdate++;\n\n\t//\n\t// if there are any nested hides then dec the count\n\t//\n\tif (MCCount) {\n\t\tMCCount--;\n\t\t//\n\t\t// If the mouse is now not hidden and it had actually been\n\t\t// hidden before then display it.\n\t\t//\n\t\tif (!MCCount) {\n\t\t\tif (MCFlags & CONDHIDDEN) {\n\t\t\t\tShow_Mouse();\n\t\t\t}\n\t\t\tMCFlags = 0;\n\t\t}\n\t}\n\n\tMouseUpdate--;\n}\n\n\nvoid WWMouseClass::Draw_Mouse(GraphicViewPortClass *scr)\n{\n\tPOINT pt;\n\n\tif (State != 0) return;\n\tMouseUpdate++;\n\t//\n\t//\tGet the position that the mouse is currently located at\n\t//\n\tGetCursorPos(&pt);\n\tif (MCFlags & CONDHIDE && pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {\n\t\tHide_Mouse();\n\t\tMCFlags |= CONDHIDDEN;\n\t} else {\n\t\t//\n\t\t// If the mouse is already visible then just ignore the problem.\n\t\t//\n\t\tEraseFlags = TRUE;\n\n\t\t//\n\t\t// Try to lock the screen  - dont do video stuff if we cant.\n\t\t//\n\t\tif (scr->Lock()){\n\t\t\t//\n\t\t\t// Save off the area behind the mouse into two different buffers, one\n\t\t\t// which will be used to restore the mouse and the other which will\n\t\t\t// be used to restore the hidden surface when we get a chance.\n\t\t\t//\n\t\t\tMouse_Shadow_Buffer(this, scr, EraseBuffer, pt.x, pt.y, MouseXHot, MouseYHot, 1);\n\t\t\tmemcpy(MouseBuffer, EraseBuffer, MaxWidth * MaxHeight);\n\t\t\t//\n\t\t\t// Draw the mouse in its new location\n\t\t\t//\n\t\t\t::Draw_Mouse(this, scr, pt.x, pt.y);\n\t\t\t//\n\t\t\t// Save off the positions that we saved the buffer from\n\t\t\t//\n\t\t\tEraseBuffX \t\t= pt.x;\n\t\t\tMouseBuffX \t\t= pt.x;\n\t\t\tEraseBuffY \t\t= pt.y;\n\t\t\tMouseBuffY \t\t= pt.y;\n\t\t\tEraseBuffHotX\t= MouseXHot;\n\t\t\tEraseBuffHotY\t= MouseYHot;\n\t\t\t//\n\t\t\t// Unlock the screen and lets get moving.\n\t\t\t//\n\t\t\tscr->Unlock();\n\t\t}\n\t}\n\n\tMouseUpdate--;\n}\n\nvoid WWMouseClass::Erase_Mouse(GraphicViewPortClass *scr, int forced)\n{\n\t//\n\t// If we are forcing the redraw of a mouse we already managed to\n\t// restore then just get outta here.\n\t//\n\tif (forced && EraseBuffX == -1 && EraseBuffY == -1) return;\n\n\tMouseUpdate++;\n\n\t//\n\t// If this is not a forced call, only update the mouse is we can legally\n\t//\tlock the buffer.\n\t//\n\tif (!forced) {\n#if(0)\n\t\tif (scr->Lock()) {\n\t\t\t//\n\t\t\t// If the surface has not already been restore then restore it and erase the\n\t\t\t// restoration coordinates so we don't accidentally do it twice.\n\t\t\t//\n\t\t\tif (EraseBuffX != -1 || EraseBuffY != -1) {\n\t\t\t\tMouse_Shadow_Buffer(this, scr, EraseBuffer, EraseBuffX, EraseBuffY, 0);\n\t\t\t\tEraseBuffX = -1;\n\t\t\t\tEraseBuffY = -1;\n\t\t\t}\n\t\t\t//\n\t\t\t// We are done writing to the buffer so unlock it.\n\t\t\t//\n\t\t\tscr->Unlock();\n\t\t}\n#endif\n\t} else\t{\n\t\t\t//\n\t\t\t// If the surface has not already been restore then restore it and erase the\n\t\t\t// restoration coordinates so we don't accidentally do it twice.\n\t\t\t//\n\t\t\tif (EraseBuffX != -1 || EraseBuffY != -1) {\n\t\t\t\tif (scr->Lock()){\n\t\t\t\t\tMouse_Shadow_Buffer(this, scr, EraseBuffer, EraseBuffX, EraseBuffY, EraseBuffHotX, EraseBuffHotY, 0);\n\t\t\t\t\tscr->Unlock();\n\t\t\t\t}\n\t\t\t\tEraseBuffX = -1;\n\t\t\t\tEraseBuffY = -1;\n\t\t\t}\n\t}\n\tMouseUpdate--;\n  \tEraseFlags = FALSE;\n}\n\nint WWMouseClass::Get_Mouse_State(void)\n{\n\treturn(State);\n}\n/***********************************************************************************************\n * WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels             *\n *                                                                                             *\n * INPUT:\t\tnone                                                                            *\n *                                                                                             *\n * OUTPUT:     int\t\t- returns the mouses current x position in pixels                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nint WWMouseClass::Get_Mouse_X(void)\n{\n\tPOINT \tpt;\n\tGetCursorPos(&pt);\n\treturn(pt.x);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels             *\n *                                                                                             *\n * INPUT:\t\tnone                                                                            *\n *                                                                                             *\n * OUTPUT:     int\t\t- returns the mouses current y position in pixels                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nint WWMouseClass::Get_Mouse_Y(void)\n{\n\tPOINT \tpt;\n\tGetCursorPos(&pt);\n\treturn(pt.y);\n}\n\n/***********************************************************************************************\n * WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars         *\n *                                                                                             *\n * INPUT:\t\tint &x\t\t- variable to return the mouses x position in pixels                *\n *\t\t\t\t\tint &y\t\t- variable to return the mouses y position in pixels\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     none - output is via reference variables                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid WWMouseClass::Get_Mouse_XY(int &x, int &y)\n{\n\tPOINT \tpt;\n\n\tGetCursorPos(&pt);\n\tx = pt.x;\n\ty = pt.y;\n}\n\n#pragma off(unreferenced)\n\nvoid CALLBACK Process_Mouse( UINT event_id, UINT res1 , DWORD user, DWORD  res2, DWORD  res3 )\n{\n\tstatic\tBOOL\tin_mouse_callback = false;\n\n\tif (_Mouse && !in_mouse_callback) {\n\t\tin_mouse_callback = TRUE;\n\t\t_Mouse->Process_Mouse();\n\t\tin_mouse_callback = FALSE;\n\t}\n}\n#pragma on(unreferenced)\n\nvoid Hide_Mouse(void)\n{\n\tif (!_Mouse) return;\n\t_Mouse->Hide_Mouse();\n}\n\nvoid Show_Mouse(void)\n{\n\tif (!_Mouse) return;\n\t_Mouse->Show_Mouse();\n}\n\nvoid Conditional_Hide_Mouse(int x1, int y1, int x2, int y2)\n{\n\tif (!_Mouse) return;\n\t_Mouse->Conditional_Hide_Mouse(x1, y1, x2, y2);\n}\n\nvoid Conditional_Show_Mouse(void)\n{\n\tif (!_Mouse) return;\n\t_Mouse->Conditional_Show_Mouse();\n}\n\nint Get_Mouse_State(void)\n{\n\tif (!_Mouse) return(0);\n\treturn(_Mouse->Get_Mouse_State());\n}\n\nvoid *Set_Mouse_Cursor(int hotx, int hoty, void *cursor)\n{\n\tif (!_Mouse) return(0);\n\treturn(_Mouse->Set_Cursor(hotx,hoty,cursor));\n}\n\nint Get_Mouse_X(void)\n{\n\tif (!_Mouse) return(0);\n\treturn(_Mouse->Get_Mouse_X());\n}\n\nint Get_Mouse_Y(void)\n{\n\tif (!_Mouse) return(0);\n\treturn(_Mouse->Get_Mouse_Y());\n}\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/MOUSE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood 32 Bit Library                                      *\n *                                                                                             *\n *                    File Name : MOUSE.H                                                      *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 12/12/95                                                     *\n *                                                                                             *\n *                  Last Update : December 12, 1995 [PWG]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WW_MOUSE_H\n#define WW_MOUSE_H\n\n#include <gbuffer.h>\n\nclass WWMouseClass {\n\tpublic:\n\t\tWWMouseClass(GraphicViewPortClass *scr, int mouse_max_width, int mouse_max_height);\n\t\t~WWMouseClass();\n\t\tvoid *Set_Cursor(int xhotspot, int yhotspot, void *cursor);\n\t\tvoid Process_Mouse(void);\n\t\tvoid Hide_Mouse(void);\n\t\tvoid Show_Mouse(void);\n\t\tvoid Conditional_Hide_Mouse(int x1, int y1, int x2, int y2);\n\t\tvoid Conditional_Show_Mouse(void);\n\t\tint Get_Mouse_State(void);\n\t\tint Get_Mouse_X(void);\n\t\tint Get_Mouse_Y(void);\n\t\tvoid Get_Mouse_XY(int &x, int &y);\n\t\t//\n\t\t// The following two routines can be used to render the mouse onto a graphicbuffer\n\t\t// other than the hidpage.\n\t\t//\n\t\tvoid Draw_Mouse(GraphicViewPortClass *scr);\n\t\tvoid Erase_Mouse(GraphicViewPortClass *scr, int forced = FALSE);\n\n\t\tvoid Block_Mouse(GraphicBufferClass *buffer);\n\t\tvoid Unblock_Mouse(GraphicBufferClass *buffer);\n\t\tvoid Set_Cursor_Clip(void);\n\t\tvoid Clear_Cursor_Clip(void);\n\n\tprivate:\n\t\tenum \t{\n\t\t\tCONDHIDE\t\t= 1,\n\t\t\tCONDHIDDEN \t= 2,\n\t\t};\n\t\tvoid Low_Hide_Mouse(void);\n\t\tvoid Low_Show_Mouse(int x, int y);\n\n\t\tchar\t\t\t\t\t\t*MouseCursor;\t// pointer to the mouse cursor in memory\n\t\tint\t\t\t\t\t\tMouseXHot;\t\t// X hot spot of the current mouse cursor\n\t\tint\t\t\t\t\t\tMouseYHot;\t\t// Y hot spot of the current mouse cursor\n\t\tint\t\t\t\t\t\tCursorWidth;\t// width of the mouse cursor in pixels\n\t\tint\t\t\t\t\t\tCursorHeight;\t// height of the mouse cursor in pixels\n\n\t\tchar\t\t\t\t\t\t*MouseBuffer;\t// pointer to background buffer in memory\n\t\tint\t\t\t\t\t\tMouseBuffX;\t\t// pixel x mouse buffer was preserved at\n\t\tint\t\t\t\t\t\tMouseBuffY;\t\t// pixel y mouse buffer was preserved at\n\t\tint\t\t\t\t\t\tMaxWidth;\t\t// maximum width of mouse background buffer\n\t\tint\t\t\t\t\t\tMaxHeight;\t\t// maximum height of mouse background buffer\n\n\t\tint\t\t\t\t\t\tMouseCXLeft;\t// left x pos if conditional hide mouse in effect\n\t\tint\t\t\t\t\t\tMouseCYUpper;\t// upper y pos if conditional hide mouse in effect\n\t\tint\t\t\t\t\t\tMouseCXRight;\t// right x pos if conditional hide mouse in effect\n\t\tint\t\t\t\t\t\tMouseCYLower;\t// lower y pos if conditional hide mouse in effect\n\t\tchar\t\t\t\t\t\tMCFlags;\t\t\t// conditional hide mouse flags\n\t\tchar\t\t\t\t\t\tMCCount;\t\t\t// nesting count for conditional hide mouse\n\n\t\tGraphicViewPortClass\t*Screen;\t\t\t// pointer to the surface mouse was init'd with\n\t\tchar *\t\t\t\t\tPrevCursor;\t\t// pointer to previous cursor shape\n\t\tint\t\t\t\t\t\tMouseUpdate;\n\t\tint\t\t\t\t\t\tState;\n\n\t\tchar\t\t\t\t\t\t*EraseBuffer;\t// Buffer which holds background to restore to hidden page\n\t\tint\t\t\t\t\t\tEraseBuffX;\t\t// X position of the hidden page background\n\t\tint\t\t\t\t\t\tEraseBuffY;\t\t// Y position of the hidden page background\n\t\tint\t\t\t\t\t\tEraseBuffHotX;\t// X position of the hidden page background\n\t\tint\t\t\t\t\t\tEraseBuffHotY;\t// Y position of the hidden page background\n\n\t\tint\t\t\t\t\t\tEraseFlags;\t\t// Records whether mutex has been released\n\n\t\tCRITICAL_SECTION\t\tMouseCriticalSection;  // Control for mouse re-enterancy\n\t\tunsigned\t\t\t\t\tTimerHandle;\n\n};\n\nextern \"C\" {\n\t void __cdecl Mouse_Shadow_Buffer(void *thisptr, GraphicViewPortClass *srcdst, void *buffer, int x, int y, int hotx, int hoty, int store);\n\t void __cdecl Draw_Mouse(void *thisptr, GraphicViewPortClass *srcdst, int x, int y);\n\t void * __cdecl ASM_Set_Mouse_Cursor(void * thisptr, int hotspotx, int hotspoty, VOID *cursor);\n};\n\nvoid Hide_Mouse(void);\nvoid Show_Mouse(void);\nvoid Conditional_Hide_Mouse(int x1, int y1, int x2, int y2);\nvoid Conditional_Show_Mouse(void);\nint Get_Mouse_State(void);\nvoid *Set_Mouse_Cursor(int hotx, int hoty, void *cursor);\nint Get_Mouse_X(void);\nint Get_Mouse_Y(void);\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/MOUSE.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;*********************************************************************************************** \n;*                                                                                             * \n;*                 Project Name : Westwood 32 bit Library                                      * \n;*                                                                                             * \n;*                    File Name : MOUSE.INC                                                    * \n;*                                                                                             * \n;*                   Programmer : Philip W. Gorrow                                             * \n;*                                                                                             * \n;*                   Start Date : 12/12/95                                                     * \n;*                                                                                             * \n;*                  Last Update : December 12, 1995 [PWG]                                      * \n;*                                                                                             * \n;*---------------------------------------------------------------------------------------------* \n;* Functions:                                                                                  * \n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nSTRUC MouseType\nMouseCursor\t\tDD\t\t?\t\t\t; pointer to the mouse cursor in memory\nMouseXHot\t\tDD\t\t?\t\t\t; X hot spot of the current mouse cursor\nMouseYHot\t\tDD\t\t?\t\t\t; Y hot spot of the current mouse cursor\nCursorWidth\t\tDD\t\t?\t\t\t; Width of mouse cursor in pixels\nCursorHeight\tDD\t\t?\t\t\t; Height of the mouse cursor in pixels\n\nMouseBuffer\t\tDD\t\t?\t\t\t; pointer to background buffer in memory\nMouseBuffX\t\tDD\t\t?\t\t\t; pixel x mouse buffer was preserved at\nMouseBuffY\t\tDD\t\t?\t\t\t; pixel y mouse buffer was preserved at\nMaxWidth\t\t\tDD\t\t?\t\t\t; Maximum possible width of the background buffer\nMaxHeight\t\tDD\t\t?\t\t\t; Maximum possible height of the background buffer\n\nMouseCXLeft\t\tDD\t\t?\t\t\t; left hand x position if conditional hide mouse in effect\nMouseCYUpper\tDD\t\t?\t\t\t; upper y position if conditional hide mouse in effect\nMouseCXRight\tDD\t\t?\t\t\t; right hand x position if conditional hide mouse in effect\nMouseCYLower\tDD\t\t?\t\t\t; lower y position if conditional hide mouse in effect\nMCFlags\t\t\tDB\t\t?\t\t\t; conditional hide mouse flags\nMCCount\t\t\tDB\t\t?\t\t\t; nesting count for conditional hide mouse\n\nScreen\t\t\tDD\t\t?\t\t\t; pointer to the surface mouse was init'd with\nPrevCursor\t\tDD\t\t?\t\t\t; pointer to the prev cursor shape\nMouseUpdate\t\tDD\t\t?\t\t\t; is the mouse being currently updated\nState\t\t\t\tDD\t\t?\n\nEraseBuffer\t\tDD\t\t?\nEraseBuffX\t\tDD\t\t?\nEraseBuffY\t\tDD\t\t?\nEraseBuffHotX\tDD\t\t?\nEraseBuffHotY\tDD\t\t?\nEraseFlags\t\tDD\t\t?\nENDS\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/KEYBOARD.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : KEYBOARD.ASM                             *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 15, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Get_RM_Timer_Address -- Return address of real mode code for copy.    *\n;*   Get_RM_Keyboard_Size -- return size of real mode timer code.          *\n;*   Check_Key -- checks queue for key (make)                              *\n;*   Check_Key_Num -- Checks if key in queue, return key num               *\n;*   Get_Key_Num -- Returns the next key num in ax                         *\n;*   KN_To_KA -- Translates a key num to an ASCII key                      *\n;*   Low_Get_Key -- low level get key returns key num and bits             *\n;*   Convert_Num_To_ASCII -- Assembly routine converts keynum to ASCII key *\n;*   KeyNum_Translate -- Performs a lowlevel xlate to a keycode            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\n;*\tKeyboard driver -- 80386 Protected Mode Assembly portion\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   \n;***************************************************************************\n;\n; ----------------------------------------------------------------\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\n;WARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Make some general equates for easy compatability\n;---------------------------------------------------------------------------\nPROT_INT_ENABLE\tEQU\t1\t\t; if false protected int just calls real mode int\n\nDPMI_INTR\tEQU\t31h\t\nIRQ1INTNUM\tEQU\t09h\t\t; IRQ1 interrupt vector number.\nBRKINTNUM\tEQU\t23h\t\t; Crtl-C (Break) interrupt vector number\nDBGINTNUM\tEQU\t3h\t\t; Debug interrupt vector number\nDOS_SYS_CALL\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nLOCK_PAGES\tEQU\t5\t\t; Lock pages subfunction using DX_MEM_MGT\nUNLOCK_PAGES\tEQU\t6\t\t; Unlock pages subfunction using DX_MEM_MGT\nCLEARISR\tEQU\t020H\t; value to clear In Service Register\nINTCHIP0\tEQU\t020H\t; 8259 interrupt chip controller 0\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\n\tINCLUDE \"keyboard.inc\"\n\tINCLUDE \"keystruc.inc\"\n\tINCLUDE \"mcgaprim.inc\"\n\n\tGLOBAL\t RealModePtr:DWORD\n\n\tGLOBAL\t Install_Keyboard_Interrupt:NEAR\n\tGLOBAL\t Get_RM_Keyboard_Address:Near\n\tGLOBAL\t Get_RM_Keyboard_Size:Near\n\tGLOBAL\t Remove_Keyboard_Interrupt:NEAR\n\tGLOBAL\t Check_Key_Num:NEAR\n\tGLOBAL\t Get_Key_Num:NEAR\n\tGLOBAL\t KN_To_KA:NEAR\n\tGLOBAL\t KeyNum_Translate:NEAR\n\tGLOBAL\t Check_Key:NEAR\n\tGLOBAL\t Get_Key:NEAR\n\tGLOBAL\t Keyboard_Attributes_On:NEAR\n\tGLOBAL\t Clear_KeyBuffer:NEAR\n\tGLOBAL\t Key_Down:NEAR\n\tGLOBAL\t Keyboard_Attributes_Off:NEAR\n\tGLOBAL\t Check_Key_Bits:NEAR\n\tGLOBAL\t Get_Key_Bits:NEAR\n\tGLOBAL\t Key_Satisfied:NEAR\n\tGLOBAL\t Stuff_Key_WORD:NEAR\n\tGLOBAL\t Stuff_Key_Num:NEAR\n\tGLOBAL\t MouseQX:DWORD\n\tGLOBAL\t MouseQY:DWORD\n;DBG\n\tGLOBAL   Keyboard_Interrupt:NEAR\n\n\n\tDATASEG\n; For the current time we will just include the real mode stuff\n; into the protected mode code and then copy it down.  The C side of\n; this will handle this method or reading it off of disk in the real\n; method.\n\nLABEL \tRealBinStart\tBYTE\ninclude \"keyireal.ibn\"\nLABEL\tRealBinEnd\tBYTE\n\nLABEL\tLockedDataStart\tBYTE\t\nRMVector\tDD\t0\nRealModeSel\tDD\t0\nRealModePtr\tDD\t0\t\t; Pointer to real mode memory.\nRealModeSize\tDD\t0\t\t; Pointer to real mode memory.\nLABEL\tLockedDataEnd\tBYTE\n\n\n\nAscii\tDB\t0,\"`1234567890-=\",0,8,9,\"qwertyuiop[]\\\",0,\"asdfghjkl;'\"\n\tDB\t0,13,0,45,\"zxcvbnm,./\",0,0,0,0,0,\" \"\n\nShift\tDB\t0,\"~!@#$%^&*()_+\",0,8,9,\"QWERTYUIOP{}|\",0,\"ASDFGHJKL:\",22H\n\tDB\t0,13,0,45,\"ZXCVBNM<>?\",0,0,0,0,0,\" \"\n\nAlpha_Lower\tDB\t0\n\tDB\t\"~!@#$%^&*()_+\",0,8,9,\"qwertyuiop{}|\",0,\"asdfghjkl:\",22H\n\tDB\t0,13,0,45,\"zxcvbnm<>?\",0,0,0,0,0,\" \"\n\nAlpha_Shift\tDB\t0\n\tDB\t\"`1234567890-=\",0,8,9,\"QWERTYUIOP[]\\\",0,\"ASDFGHJKL;'\"\n\tDB\t0,13,0,45,\"ZXCVBNM,./\",0,0,0,0,0,\" \"\n\nEdit\tDB\t0AEH,0ADH,000H,000H,0B5H,0B9H,0B1H,000H,0B8H,0B0H,0B7H,0AFH\n\tDB\t000H,000H,0B3H,000H,0B9H,0B5H,0B1H,000H, \"/\",0B8H,0B4H,0B0H\n\tDB\t0AEH, \"*\",0B7H,0B3H,0AFH,0ADH, \"-\", \"+\",000H,00DH,000H\n\nNumPad\tDB\t0,\"741\",0,\"/8520*963.-+\",0,13,0\n\n\nGetKeyLock\tDW\t0\t; snap shot of num and caps lock bits\nInitFlags\tDW\t0\nMouseQX\t\tDD\t0\nMouseQY\t\tDD\t0\n\n\tCODESEG\n;***************************************************************************\n;* GET_RM_TIMER_ADDRESS -- Return address of real mode code for copy.      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      VOID * to the address of the real mode timer               *\n;*                                                                         *\n;* PROTO:\tVOID\t*Get_RM_Keyboard_Address(VOID);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Address C Near\n\n\tmov\teax, OFFSET RealBinStart\n\tret\n\n\tENDP\n\n;***************************************************************************\n;* GET_RM_KEYBOARD_SIZE -- return size of real mode timer code.            *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      LONG size of the real mode timer code                      *\n;*                                                                         *\n;* PROTO:\tLONG\tGet_RM_Keyboard_Size(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Size C Near\n\n\tmov\teax, OFFSET RealBinEnd - OFFSET RealBinStart\n\tret\n\n\tENDP\n;***************************************************************************\n;* INSTALL_KEYBOARD_INTERRUPT -- Installs the keyboard interrupt           *\n;*                                                                         *\n;* INPUT:\tint rm_ptr  - ptr to the real mode handler\t\t   *\t   *\n;*\t\tint rm_size - size of the real mode handler\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Install_Keyboard_Interrupt(int rm_ptr, int rm_size);  *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tInstall_Keyboard_Interrupt C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\tARG\trm_ptr:DWORD\n\tARG\trm_size:DWORD\n\n\t; Are they attempting to set timer again?\n\tcmp\t[RealModePtr],0\n\tjnz\t??error\n\n\t; Make sure all flags are cleared.\n\tcmp\t[InitFlags],0\n\tjnz\t??error\n\n\n\t; Before setting the interrupt vectors, the code needs to be locked\n\t; for DPMI compatability.  Any code or data accessed must be lockded\n\t; so that no page faults accure during an interrupt.\n\t; First lock the code, then the data.  The stack will already be locked.\n\t; The real mode code is also already locked be default.\n\t; To lock a page set up registers :\n\t; AX = 0600h\n\t; BX:CX\t= starting linear address of memory block\n\t; SI:DI = size of region\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_CODE\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_DATA\n\n\t; now allocate real mode memory and copy the rm binary down to it.\n\tmov\teax,0100h\t; set function number\n\tmov\tebx,[rm_size]\t\t; get size of RM binary.\n\tmov\t[RealModeSize],ebx\n\tadd\tebx,15\t\t\t; round up \n\tshr\tebx,4\t\t\t; convert to pages.\n\tint\tDPMI_INTR\t \t; do call.\n\tjc\t??error\t\t \t; check for error.\n\tor\t[InitFlags],IF_ALLOC_RM ; set successful\n\tmov\t[RealModeSel],edx\n\tshl\teax,4\t\t\t; convert segment to offset.\n\tmov\t[RealModePtr],eax\t; save offset to global variable.\n\n\t; now lock the real mode memory that we allocated\n\tmov\teax,0600h\t\t; function number.\n\tmov\tecx,[RealModePtr]\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_RM_CODE\n\n\n\n\t; set up source and destination pointers for the copy.\n\tmov\teax,[RealModePtr];\t; set up our dest pointer\n\tmov\tesi,[rm_ptr]\t\t; Set up our source pointer.\n\tmov\tedi,eax\t\t\t; put it into esi for copy.\n\tmov\tecx,[rm_size]\n\trep\tmovsb\t\t\t; write RM bin to RM memory.\n\n\t; restore esi to point to data and initialize some of it.\n\tmov\tesi,[RealModePtr]\n\tmov\teax,esi\n\tshl\teax,12\t\t\t\t\t\t; make seg in high eax.\n\tmov\tax,[(KeyboardType PTR esi).CallKeyRMIntOffset]\t; create RM addr of call chain.\n\tmov\t[(KeyboardType PTR esi).CallKeyRMIntAddr],eax\t; save it for use in PM int.\n\nIF NOT PROT_INT_ENABLE\n       ; Chain the Real Keyboard interrupt to any avilable\n       ; Interrupt vector so We make sure that the Real Mode\n       ; Keyboard Interrupt service get called at debuging time\n       ; of the library.\n\n       mov\tedi , eax\n       mov\tbl , 060h\n       mov\tbh , 6\n       mov\teax , 200h\n ??find:\n       int\tDPMI_INTR\n       jc\t??error\n       or\tcx,dx\n       jz\t??found\n       inc\tbl\n       dec\tbh\n       jnz\t??find\n       jmp\t??error\n ??found:\n       movzx\tebx , bl\n       mov\t[ byte ptr RMVector ] , bl\n       mov\t[ 4 * ebx ] , edi\nENDIF\n\n\n\n\t;-------------------------------------------------------\n\t; Initialize all of the keyboard specific information\n\t;-------------------------------------------------------\n\txor\teax,eax\t\t\t; clear the high bits of eax\n\tmov\tal,[417H]\t\t; get keyboard status flags\n\ttest\teax,040H \t\t; caps lock active?\n\tje \tshort ??nocap\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\n\n??nocap:\n\ttest\teax,020H\t\t\t; num lock active?\n\tje\tshort ??nonumlock\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\n\n??nonumlock:\n\ttest\teax,002H\t\t\t; is left shift key down?\n\tje\tshort ??noleftshift\t\t; try the right\n\tor\t[(KeyboardType PTR esi+5).KeysUpDown],010H\n\n??noleftshift:\n\tand\teax,001H\t\t\t; get right shift bit\n\tshl\teax,9\t\t\t; put it into the proper position (shl al,1 mov ah,al)\n\tmov\tal,[418H]\t\t; get alt and ctrl bits\n\tshl\tal,2\t\t\t; put in proper position\n\tshl\tal,1\n\tand\tal,00CH\t\t\t; only alt and ctrl bits\n\tor\tah,al\t\t\t; put them ah for Keys+7 later\n\tmov\tal,[496H]\t\t; get extended keys\n\ttest\tal,008H\t\t\t; check for right alt key\n\tje\tshort ??noralt\n\tor\tah,040H\n??noralt:\n\tmov\t[(KeyboardType PTR esi+7).KeysUpDown],ah\n\ttest\tal,004H\t\t\t; test for right ctrl\n\tje \tshort ??norctrl\n\tor\t[(KeyboardType PTR esi+8).KeysUpDown],001h\n??norctrl:\n\ttest\tal,002H\t\t\t; last code E0?\n\tje short ??noe0\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],001h\n??noe0:\n\ttest\tal,001H\t\t\t; last code E1?\n\tje short ??noe1\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],002h\n??noe1:\n\t;==========================================================================\n\t; Get the protected mode interrupt vector keyboard.\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).KeyOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).KeyOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 2503, cl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).KeyOldRMI],ecx\n\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt Keyboard\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Keyboard_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt Keyboard\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).KeyCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the break interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\t\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).BrkOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).BrkOldPMISelector],ecx\t; save selector.\n\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector - for the break interrupt\n\t; input ax = 0200, bl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).BrkOldRMI],ecx\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Break_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).BrkCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\nIF DEBUG\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the Debug interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\t\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,DBGINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).DbgOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).DbgOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Debug_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\nENDIF\n\n\t; we have finished with success.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n??exit:\n\tret\n\tENDP\tInstall_Keyboard_Interrupt\n\n;***************************************************************************\n;* REMOVE_INTERRUPT -- Removes keyboard interrupt and restores chain\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Remove_Interrupt(VOID)                                *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tRemove_Keyboard_Interrupt C NEAR \n\tUSES\tebx,ecx,edx\n\n\t; verifie that the keyboard was previosly install\n\t; this is here in case of a page fault crash\n\tmov\tesi,[RealModePtr]\n\ttest    esi,esi\n\tjz      ??error\n\n\ttest\t[InitFlags],IF_SET_VECTORS\n\tjz\t??vectors_not_set\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tedx,[(KeyboardType esi).KeyOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[(KeyboardType esi).KeyOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).KeyOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\n\t; disengage Control Break Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tedx,[(KeyboardType esi).BrkOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[(KeyboardType esi).BrkOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).BrkOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\nIF DEBUG\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tecx,[(KeyboardType esi).DbgOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).DbgOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\nENDIF\n\nIF NOT PROT_INT_ENABLE\n       ; Clean up the Users interrupt table\n        mov\teax , 201h\n       mov\tbl , [ byte ptr RMVector ]\n       xor\tecx , ecx\n       xor\tedx , edx\n       int\tDPMI_INTR\n       jc\t??error\nENDIF\n\n\n??vectors_not_set:\n\t; now free up the real mode memory.\n\ttest\t[InitFlags],IF_LOCKED_RM_CODE\n\tjz\t??rm_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,[RealModePtr]\t\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t\t; edx will have size of region in bytes.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??rm_not_locked:\n\ttest\t[InitFlags],IF_ALLOC_RM\n\tjz\t??mem_not_allocated\n\tmov\teax , 0101h\n\tmov\tedx,[ RealModeSel ] \t\t; get physical address of real mode buffer.\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n??mem_not_allocated:\n\n\t; Now we can unlock all stuff needed for the interrupt.  \n\t; Unlock Code\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??code_not_locked:\n\n\t; Unlock data\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??data_not_locked:\n\n\t; we have finished with success.\n\tmov\t[RealModePtr],0\t\t; To say we can do it again sometime.\n\tmov\t[InitFlags],0\t\t; To say we can do it again sometime.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n\tret\n\tENDP\tRemove_Keyboard_Interrupt\n\n\n;***************************************************************************\n;* CHECK_KEY_NUM -- Checks if key in queue, return key num                 *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      Keynum of the key that was pressed, FALSE otherwise        *\n;*\n;* PROTO:\tINT Check_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Num C NEAR \n\tUSES\tebx,esi\n\tpushf\t\t\t\t\t; save off the flags\n\tcli\t\t\t\t\t; disable interrupts\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t\t\n\txor\teax,[(KeyboardType PTR esi).KeyBufferTail]\t\t\n\tor\teax,eax\t\t\t\t; check to see if head == tail\n\tjz\tshort ??fini\t\t\t; if so we are done\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t; get the head\n\tmov\tax,[(KeyboardType PTR esi+eax).KeyBuffer]\t; get key num\n\n??fini:\n\tsti\n\tpopf\n\tret\n\n\tENDP\tCheck_Key_Num\n\n;***************************************************************************\n;* GET_KEY_NUM -- Returns the next key num in ax                           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      WORD key flags are in the high byte of return word, key    *\n;*\t\t  num is in the low byte.\n;*                                                                         *\n;* PROTO:\tWORD Get_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Num C NEAR\n\tUSES\tesi,edi\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n??wait:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t\t; get the head\n\tcmp\teax,[(KeyboardType PTR esi).KeyBufferTail]\t\t; get the head\n\tjne\tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??wait\n\n??getkey:\n\tcall\tLow_Get_Key\n\tsti\t\t\t\t; enable interrupts\n\tret\n\n\tENDP\tGet_Key_Num\n\n;***************************************************************************\n;* KN_TO_KA -- Translates a key num to an ASCII key                        *\n;*                                                                         *\n;* INPUT:\tWORD the keynum to translate                               *\n;*                                                                         *\n;* OUTPUT:      WORD the ASCII key that is returned                        *\n;*                                                                         *\n;* PROTO:\tINT KN_To_KA(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tKN_To_KA C NEAR\n\tARG\tkeynum:DWORD\n\n\tmov\teax,[keynum]\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\tret\n\n\tENDP\tKN_To_KA\n\n\n;***************************************************************************\n;* LOW_GET_KEY -- low level get key returns key num and bits               *\n;*                                                                         *\n;* INPUT:\tAX - index into the buffer                                 *\n;*                                                                         *\n;* OUTPUT:      AX - key num with bits                                     *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tLow_Get_Key C NEAR \n\tUSES\tebx,esi,edi\n\n\tmov\tedi,eax\t\t\t\t; save off value in ax\n\n; We should set up both DS & ES because we are a low level function\n; and don't know who might have called us or what the registers\n; currently are.\n\n; No reason to set DS & ES.\n; This is not a hardware interrupt and if the funtion is being called\n; from within a hardware interrupt then DS and ES will be preset to\n; DGROUP _DATA\n\t\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tcmp\tal,KN_LMOUSE\n\tjb \tshort ??cont\n\tcmp\tal,KN_RMOUSE\n\tja \tshort ??chkjoy\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t; 128 word circular buffer\n\n\tmov\t[MouseQX],eax\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\t[MouseQY],eax\n\n\tpop\teax\t\t\t; restore keynum for return\n\n\tjmp\tshort ??cont\n\n??chkjoy:\n\tcmp\tal,KN_JBUTTON2\t\t; mouse button before joystick button\n\tja \tshort ??cont\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tpop\teax\t\t\t; restore keynum for return\n??cont:\n\tmov\t[(KeyboardType PTR esi).KeyBufferHead],edi\t; set the head\n\n??out:\n\tret\n\n\tENDP\tLow_Get_Key\n\n;***************************************************************************\n;* CONVERT_NUM_TO_ASCII -- Assembly routine converts keynum to ASCII key   *\n;*                                                                         *\n;* INPUT:\tEAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - holds the key num bits                        *\n;*\t\t\tAL - holds the key num value\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      EAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - hold the key bits                             *\n;*\t\t\tAL - holds the ASCII key value\t\t\t   *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* WARNINGS:    GetKeyLock must be set prior to calling this function\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tConvert_Num_To_ASCII C NEAR \n\tUSES\tebx,ecx,esi,edi\n\n\t;*===================================================================\n\t;* Force all breaks to be thrown out.\n\t;*===================================================================\n\ttest\teax,08000h\t\t; If it is a button number\n\tjne\tshort ??button\t\t;  don't process it\n\n\ttest\tah,KEYRELEASE\t\t; If it is not key release\n\tje\tshort ??ok\t\t;  then go process it\n\n??button:\n\txor\teax,eax\t\t\t; no ascii value for a button\n\tret\n\n??ok:\n\t;*===================================================================\n\t;* ES points to the DOSMEM selector, esi is the offset of the \n\t;*   protected mode structure.\n\t;*===================================================================\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\n\t;*===================================================================\n\t;* Start dealing with the keys.\t\t\t\t\t  \n\t;*===================================================================\n\tcmp\tal,110\t\t\t; is it esc\n\tje\t??esc\t\t\t; if so then deal with it\n\n;??chkext:\n\tcmp\tal,62\t\t\t; is it extended?\n\tjae\tshort ??extended\t; its extended so return ext code\n\n\tmov\tebx,eax\t\t\t; get an index\n\tand\tebx,03FH\t\t; only 0-63 allowed\n\ttest\tah,1\t\t\t; if not, test for shift\n\tjnz\tshort ??shifted\t\t; if shifted get shift value\n\n\t;*===================================================================\n\t;* Here when we have an unshifted ascii key\n\t;*===================================================================\n\tmov\tal,[Ascii+ebx]\t\t; get the ascii code for this number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_lowered:\n\tmov\tal,[Alpha_Lower+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_shifted:\n\tmov\tal,[Alpha_Shift+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* Shift'ed character\n\t;*===================================================================\n??shifted:\n\tmov\tal,[Shift+ebx] \t\t; get ascii shift code for number\n\n??ctrlkey:\n\ttest\tah,2\t\t\t; is it ctrl?\n\tjz \tshort ??jexit\t\t; izf not skip ctrl check\n\n\tmov\tedi,ebx\t\t\t; get index\n\tand\tedi,7\t\t\t; only bits 0-7\n\n\tmov\tcl,[(KeyboardType PTR esi+edi).Bits]\n\n\tshr\tebx,3\t\t\t; div by 8 for byte offset\n\ttest\t[(KeyboardType PTR esi+ebx).KeysCapsLock],cl\t\n\tje \tshort ??jexit\n\tand\tal,01FH\t\t\t; force to ctrl value\n\n??jexit:\n\tjmp short ??exit\n\n??extended:\n\tcmp\tal,75\t\t\t; if less than insert\n\tjb \tshort ??special\n\tcmp\tal,110\t\t\t; if >= esc\n\tjae \tshort ??funckey\n\n??editkeys:\n\txor\tebx,ebx\n\tmov\tbl,al\n\tsub\tebx,75\t\t\t; get value from 0-34\n\ttest\t[(KeyboardType PTR esi).KeyFlags],NONUMLOCK\n\tjne \tshort ??no_numpad\n\ttest\t[GetKeyLock],NUMLOCK\t; look at the snap shot of bits\n\tjne \tshort ??numpad\n\n??no_numpad:\n\tmov\tal,[Edit+ebx] \t\t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??numpad:\n\tsub\tebx,15\t\t\t; adjust to numpad entries\n\tmov\tal,[NumPad+ebx] \t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??funckey:\n\tcmp\tal,112\t\t\t; if less than function keys\n\tjb \tshort ??extout\n\tcmp\tal,121\t\t\t; if greater than function keys 1-10\n\tja \tshort ??extout\n\tmov\tbl,al\n\tsub\tbl,112\t\t\t; get value 0-9\n\tmov\tbh,0C5H\t\t\t; function key 1 no shift-ctrl-alt\n\ttest\tah,7\t\t\t; any shift-ctrl-alt\n\tje\tshort ??funcadj\n\tmov\tbh,098H\t\t\t; function key 1 alt\n\ttest\tah,ALTPRESS\t\t; (highest prescendence)\n\tjne \tshort ??funcadj\n\tmov\tbh,0A2H\t\t\t; function key 1 ctrl (next highest)\n\ttest\tah,CTRLPRESS\n\tjne\tshort ??funcadj\n\tmov\tbh,0ACH\t\t\t; function key 1 shift (lowest)\n\n??funcadj:\n\tsub\tbh,bl\t\t\t; adjust function key to a\n\tmov\tal,bh\t\t\t; shift/no shift etc\n\tjmp\tshort ??exit\n\n??special:\n\tcmp\tal,65\t\t\t; if less than specials\n\tjb\tshort ??extout\n\n\tadd\tal,133\t\t\t; make value between 198-207 or\n\tjmp\tshort ??exit\t\t; 0C6H-0CFH\n\t\n??extout:\n\tor\tal,080H\n\tjmp\tshort ??exit\n\n??esc:\n\tmov\tal,01BH\n\n??exit:\n\tret\n\tENDP\tConvert_Num_To_ASCII\n\n;***************************************************************************\n;* CHECK_KEY -- checks for ASCII keys sitting in the keybuffer             *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      INT the ASCII sequence for the key that was pressed        *\n;*                                                                         *\n;* PROTO:\tINT Check_Key(VOID);                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key C NEAR\n\tUSES\tebx,edi,esi\n\n\tpushf\n\tcld\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tcmp\tal,KN_LMOUSE\t\t; check if it is a mouse or joystick\n\tjb\tshort ??contget\n\tcmp\tal,KN_JBUTTON2\n\tja\tshort ??contget\n\tadd\tsi,4\t\t\t; get rid of the x and y values\n\n??contget:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\teax,eax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\tsti\t\t\t\t; enable interrupts\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tcall\tnear ptr Convert_Num_To_ASCII\n\t\t\t\t\t; AX has ASCII code with bits\n\n\txor\tah,ah\t\t\t; clear key bits\n??exit:\n\tpopf\n\tret\n\tENDP\tCheck_Key\n\n\n;***************************************************************************\n;* GET_KEY -- Gets the next available ASCII keystroke.\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      AH - hold the key bits                                     *\n;*\t\tAL - holds the ASCII key value\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tINT Get_Key(VOID);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key C NEAR \n\tUSES \tebx,ecx,edi\n\n\tcld\t\t\t\t; clear the direction flag for speed\n\n\t; Check_Key had to be copied because of enable and disable of ints\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\t\t\t\t\t; AX has key num code with bits\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\txor\tah,ah\n\tret\n\n\tENDP\tGet_Key\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_ON -- Sets the specified keyflags on                *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned on                 *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are on                       *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_On(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_On C NEAR\n\tUSES\tesi,edi\n\tARG\tbits:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tor\t[(KeyboardType PTR esi).KeyFlags],eax\n\n\t; Only do this if in playback or record mode.\n\ttest\teax,PASSBREAKS\n\tje\tshort ??fini\n\n\txor\teax,eax\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).KeysUpDown\n\tmov\t[edi],eax\n\tmov\t[edi+4],eax\n\tmov\t[edi+8],eax\n\tmov\t[edi+12],eax\n??fini:\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\n\tret\n\tENDP\tKeyboard_Attributes_On\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_OFF -- Sets the specified keyflags off              *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned off                *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are off                      *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_Off(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_Off C NEAR\n\tUSES\tesi\n\tARG\tbits:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tnot\teax\n\tand\t[(KeyboardType PTR esi).KeyFlags],eax\n\txor\teax,eax\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\n\tret \n\n\tENDP\tKeyboard_Attributes_Off\n;***************************************************************************\n;* CLEAR_KEYBUFFER -- Clears keystrokes out of the key buffer              *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Clear_KeyBuffer(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tClear_KeyBuffer C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tcli\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\tsti\n\n\tret\n\n\tENDP\tClear_KeyBuffer\n\n;***************************************************************************\n;* KEY_DOWN -- tests the status of a keyboard key                          *\n;*                                                                         *\n;* INPUT:\tINT the key num to check                                   *\n;*                                                                         *\n;* OUTPUT:      INT zero if the key is up, none zero if the key is down    *\n;*                                                                         *\n;* PROTO:\tINT Key_Down(INT key);\t\t\t\t   \t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Down C NEAR\n\tUSES\tebx,ecx,edi,esi\n\tARG\tkey:DWORD\n\n\tpush\t[key]\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\txor\tah,ah\t\t\t\t; Always ignore the control bits.\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tedi,eax\n\tshr\tedi,3\n\tmov\tcl,al\n\tand\tcl,0111b\n\tmov\tal,01b\n\tshl\tal,cl\n\tand\tal,[(KeyboardType PTR esi+edi).KeysUpDown]\n\tret\n\n\tENDP\tKey_Down\n\n;***************************************************************************\n;* CHECK_KEY_BITS -- checks ascii key in key buff with shift,ctrl,alt bits *\n;*                                                                         *\n;* INPUT:\tnone \t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set     *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Bits C NEAR\n\tUSES\tebx,ecx,edi,esi\n\n\tpushf\t\t\t\t\t; save off the direction flag\n\tcld\t\t\t\t\t; we will go forward\n\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n??playback:\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\t;------ If there is a NULL in the keyboard buffer, we must NOT treat it\n\t;\tas a valid ASCII value because the calling code will falsely\n\t;\tassume that the NULL return value indicates an empty buffer.\n\tor\tal,al\n\tje\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\tax,ax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tCheck_Key_Bits\n;***************************************************************************\n;* GET_KEY_BITS -- Gets ascii key in key buff with shift,ctrl,alt bits     *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set\t   *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Bits C NEAR \n\tUSES\tebx,ecx,edi\n\n\tcld\n\n\t; Check_Key_Bits was copied because of enable and disable of interrupts\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\tret\n\n\tENDP\tGet_Key_Bits\n\n;***************************************************************************\n;* KEY_SATISFIED -- checks to see if the given key is satisfied            *\n;*                                                                         *\n;* INPUT:   INT the key flags/number to check                          \t   *\n;*                                                                         *\n;* OUTPUT:  INT 0 if the key is not satisfied, !0 if the key is satisfied  *\n;*                                                                         *\n;* PROTO:   VOID Key_Satisfied(INT key);                                    *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Satisfied C NEAR\n\tUSES\tebx,ecx,esi,edi\n\tARG\tkey:DWORD\n\n\tmov\teax,[key]\n\tmov\tebx,eax\t\t\t; save key code\n\tpush\teax\n\tcall\tKey_Down\t\t; see it its even down\n\tadd\tesp,4\n\tcmp\teax,0\n\tje\t??out\t\t\t; if not it can't be satisfied\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,ebx\t\t\t; if so, restore code\n\txor\tah,ah\t\t\t; clear out flags area\n\tmov\tedi,eax\t\t\t; set as an index\n\tshr\tedi,3\t\t\t; div by 8 for bytes\n\tmov\tch,1h\t\t\t; set a bit for mask\n\tmov\tcl,al\t\t\t; get the code number\n\tand\tcl,7\t\t\t; get the actual bit this code is\n\tshl\tch,cl\t\t\t; move bit into mask position\n\n; now test the ctrl,alt and shift bits\n\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],04h\t; is the left ctrl down?\n\tjne \tshort ??ctrlon\t\t; if so, ctrl is on\n\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],01h\t; is the right ctrl down?\n\tje \tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n??ctrlon:\n\tor\tah,02h\t\t\t; or on the ctrl bit in flags\n??ctrloff:\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],50h\t; is either alt key down?\n\tje \tshort ??altoff\n\tor\tah,04h\t\t\t; or on the alt bit in flags\n??altoff:\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],10h\t; is the left shift down?\n\tjne \tshort ??shifton\t\t; if so the sift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],02h\t; is the right shift down?\n\tje \tshort ??shiftoff\t\t; if not then neither shift is down\n??shifton:\n\tor\tah,01h\t\t\t; or on the shift bit in flags\n??shiftoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje \tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje \tshort ??capsoff\t\t; its not effected\n\txor\tah,1h\t\t\t; toggle the shift flag\n??capsoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t\t; is the num lock key on?\n\tje \tshort ??numlockoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje \tshort ??numlockoff\t\t; if not effected skip toggle\n\txor\tah,1h\t\t\t; toggle the shift flag if effected\n\n??numlockoff:\n\tmov\tal,0ffh\t\t\t; set to match by default\n\tcmp\tah,bh\t\t\t; if flags match return !0\n\tje \tshort ??out\t\t\t; just exit\n\txor\teax,eax\t\t\t; otherwise, clear all bits FALSE\n\n??out:\n\tor\teax,eax\n\tret\n\n\tENDP\tKey_Satisfied\n\n\n;***************************************************************************\n;* Interrupt routines start here - Interrupts must be within the Locked \n;*   code area for DPMI compatability.\n;***************************************************************************\n\n\n\n\nLABEL \tLockedCodeStart\tBYTE\n\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Performs a lowlevel xlate to a keycode              *\n;*                                                                         *\n;* INPUT:\tWORD the code that needs to be translated                  *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated code                                   *\n;*                                                                         *\n;* PROTO:\tINT KeyNum_Translate(INT keynum);                          *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyNum_Translate C NEAR \n\tUSES \tebx,ecx,esi,edi\n\tARG\tkeycode:DWORD\n\n;*===================================================================\n;* ES points to the DOSMEM selector, esi is the offset of the \n;*   protected mode structure.\n;*===================================================================\n\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\tmov\teax,[keycode]\n\ttest\t[(KeyboardType PTR esi).KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\n\tmov\tecx,OFFSET ((KeyboardType PTR 0).ExtRemap)- OFFSET((KeyboardType PTR 0).ExtNums)\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtNums\n\tadd\tedi,esi\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).ExtRemapEnd\n\tdec\tedi\n\tsub\tedi,ecx\n\tmov\tal,[edi]\n??fini:\n\tret\n\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(INT code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_WORD C NEAR\n\tUSES\tebx,esi,edi\n\tARG\tcode:WORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\tedi,eax\n\tadd\teax,2\n\tand\teax,0FFh\t\t\t; New KeyBufferTail value.\n\tcmp\t[(KeyboardType PTR esi).KeyBufferHead],eax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[(KeyboardType PTR esi+edi).KeyBuffer],bx\t\t; Record the keystroke.\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\n\tret\n\n??noroom:\n\tmov\teax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_Num C NEAR\n\tUSES\tebx,ecx,edx,edi,esi\n\tARG\tkeycode:DWORD\n\tLOCAL\ttail:DWORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n; for the moment we do not check for the interrupt flag\n;\tmov\teax,2534h \t\t; function to get the interrupt status\n;\tint\t21\t\t\t; eax = interrupt status\n;\tpush\teax\t\t\t; save the result on the stack\n\n\tpushf\t\t\t\t; store off the flags\n\tcli\t\t\t\t; disable interrupts\n\n; We need to set the data segment because we might be being called\n; from within an interrupt\n; Soo, if that is the case then DS & ES point to DGROUP _DATA \n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\teax,[(KeyboardType PTR esi).MouseX]\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\teax,[(KeyboardType PTR esi).MouseY]\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],ax\n\n??cando:\n\tmov\teax,[keycode]\t\t; get the code\n\tor\teax,eax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[(KeyboardType PTR esi).Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[(KeyboardType PTR esi).Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\txor\tebx,ebx\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tebx,1\t\t\t; double for WORD index\n\tmov\tax,[WORD PTR ((KeyboardType PTR esi+ebx).XYAdjust)]\n\n\tmovsx\tebx,ah\n\tmovsx\teax,al\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tedx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tedx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tebx,edx\t\t\t; add speed for y index\n\tmov\tbl,[(KeyboardType PTR esi+ebx).KeyMouseMove] \t; get speed for y delta\n\tmovsx\tebx,bl\n\txchg\tebx,edx\t\t\t; save mouse y delta\n\tadd\tebx,eax\t\t\t; add speed for x index\n\tmov\tal,[(KeyboardType PTR esi+ebx).KeyMouseMove]\t; get speed for x delta\n\tmovsx\teax,al\n\txchg\tebx,edx\t\t\t; restore mouse y delta\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tebx,011b\t\t\t; Y = 1, 0, 3\n\tand\teax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tebx,011b\t\t\t; Y = 3, 0, 1\n\tand\teax,011b\t\t\t; X = 3, 0, 1\n\tshl\tebx,2\n\tor\tebx,eax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tebx,1\n\tmovzx\tebx,[(KeyboardType PTR esi+ebx).EdgeConv]\n\tshl\tebx,2\n\tmov\tax,[(KeyboardType PTR esi+ebx).ScreenEdge]\t; New absolute X\n\tmov\tbx,[(KeyboardType PTR esi+ebx+2).ScreenEdge] ; New absolute Y\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\teax,eax\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tebx,ebx\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseX],ax\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseY],bx\n\tcmp\t[(KeyboardType PTR esi).MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n; PWG: ARRGGGHHHH!\n;\tcall\tLow_Hide_Mouse\n;\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\teax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],eax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tedi,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\t[tail],edi\t\t; Safety record.\n\n\t; Record the base keycode (if there is room).\n\tcwde\t\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\teax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tmovzx\teax,[(KeyboardType esi).LocalMouseX]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tmovzx\teax,[(KeyboardType esi).LocalMouseY]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tebx,0101h\t\t; Bit control tools.\n\tmov\teax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[(KeyboardType PTR esi).KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[(KeyboardType esi).KeyBufferTail],edi\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tmov\tcl,3\n\tshr\tedi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[(KeyboardType esi+edi).KeysUpDown]\n\tje\tshort ??notalready\n\ttest\t[(KeyboardType PTR esi).KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\tedx,[tail]\n\tmov\t[(KeyboardType esi).KeyBufferTail],edx\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[(KeyboardType esi+edi).KeysUpDown],bh\t; Force key bit to zero.\n\tor\t[(KeyboardType esi+edi).KeysUpDown],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\teax,1\n\tjmp\tshort ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\teax,[tail]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\t\t\t; Signal an error.\n\n??exit:\n\tsti\n\tpopf\n\n;\tpopf\n;\tpop\tebx\n;\tor\tebx,ebx\n;\tjz\t??final_exit\n;\tsti\n\n??final_exit:\n\tret\n\n\tENDP\tStuff_Key_Num\n\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles break interrupt for protected mode           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBreak_Interrupt C NEAR\n\n\tiret\n\tENDP\tBreak_Interrupt\n\nIF DEBUG\n;***************************************************************************\n;* DEBUG_INTERRUPT -- Handles debug (INT 3) interrupt for protected mode   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tDebug_Interrupt C NEAR\n\n\t;*==================================================================\n\t;* Setup fake Interrupt entry sequence so that we can execute our\n\t;*   code and then IRET painlessly into the debuggers interrupt\n\t;*   handler.\n\t;*==================================================================\n\tpushfd\t\t\t; Step 1\n\tsub\tesp,8\t\t; Step 2\n\tpush\tebp\t\t; Step 3\n\tmov\tebp,esp\t\t; Set up a stack frame to know where to poke address.\n\n\t;*==================================================================\n\t;* Preserve all of the registers that we intend to use.\n\t;*=======================================Dbg========================\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n\tmov\tax , _DATA\n\tmov\tds , ax\n\tmov\tes , ax\n\tinc\t[BYTE PTR 0B0000h]\n\n\t;*==================================================================\n\t;* Setup the pointers to the real mode data and the protected mode\n\t;*   data and selectors.\n\t;*==================================================================\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t;*==================================================================\n\t;* Do the deed.\n\t;*==================================================================\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\n\t;*==================================================================\n\t;* Now get the address of the real debug handler and poke it into\n\t;*   the stack so we can IRET to it.\n\t;*==================================================================\n\tmov\teax,[(KeyboardType PTR esi).DbgOldPMIOffset]\t; Get orig offset.\n\tmov\tebx,[(KeyboardType PTR esi).DbgOldPMISelector]\t; Get orig selector.\n\tmov\t[ss:ebp+4],eax\t\t\t\t\t; Poke offset.\n\tmov\t[ss:ebp+8],ebx\t\t\t\t\t; Poke selector.\n\n\t;*==================================================================\n\t;* Restore the stack so it looks like we just did an IRET entry\n\t;*==================================================================\n\tpop\tfs gs es ds\n\tpopad\n\tpop\tebp\n\n\t;*==================================================================\n\t;* This iret should go directly to the real debugger handler\n\t;*\tpainlessly and effectively.\n\t;*==================================================================\n\tiretd\n\n\tENDP\tDebug_Interrupt\nENDIF\n\n\n\nIF PROT_INT_ENABLE\n\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Handles input that comes from the keyboard        *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Interrupt C NEAR\n\n\t; This routine will do what it needs to, \n\t; then it will decide if the old vector should be called.\n\t; if so, it calls it and never returns to this function.\n\t; if not, we do our own return.\n\t; the method for doing this is found in:\n\t; \"Phar Lap  TNT DOS-Extender Reference Manual, First Addition, p. 142\"\n\t; It says:\n\t; 1 - Execute a PUSHFD to save the current flags.\n\t; 2 - Dec the stack ptr by 8 bytes to save room for the addr of orig handler\n\t; 3 - Push register I use.\n\t; 4 - Do any processing.\n\t; 5 - Put the address of the original handler in the reserved slot.\n\t; 6 - Pop saved register values\n\t; 7 - Execute an IRETD to transfer control to original handler.\n\tpushfd\t\t\t; Step 1\n\tsub\tesp,8\t\t; Step 2\n\tpush\tebp\t\t; Step 3\n\tmov\tebp,esp\t\t; Set up a stack frame to know where to poke address.\n\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n; this is the part of the interrupt that set the segment registers\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\t\n\tmov\tedx,[(KeyboardType PTR esi).KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[(KeyboardType PTR esi).KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\ttest\t[BYTE PTR 417H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR 417H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR 496H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tebx,0101H\t\t; set key to a make by default \n\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\t;\n\t; New CODE to montior key stream\n\t;\n\txor\tebx,ebx\n\tmov\tbx,[(KeyboardType PTR esi).KeyStreamIndex]\n\tmov\t[(KeyboardType PTR esi+ebx).KeyStream],al\n\tinc\tebx\n\tand\tebx,15\n\tmov\t[(KeyboardType PTR esi).KeyStreamIndex],bx\n\tmov\tebx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[(KeyboardType PTR esi).LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[(KeyboardType PTR esi).LastKeyE1]\t\t; yes, dec the count\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[(KeyboardType PTR esi).IsExtKey],TRUE\t; it is an extended key\n\n\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtCodes\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).ExtNums-OFFSET (KeyboardType PTR 0).ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\n\tmov\tal,[(OFFSET (KeyboardType PTR 0).ExtNums - OFFSET (KeyboardType PTR 0).ExtCodes) - 1 + edi] ; get the match\n\tmov\t[(KeyboardType PTR esi).IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tedi,eax\t\t\t; use code as an index\n\tand\tedi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[(KeyboardType PTR esi+edi).KeyNums]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[(KeyboardType PTR esi).ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\teax\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\n;------\tSet the shift bit if necessary.\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tshr\tedi,3\n\tmov\tebx,eax\n\tand\tebx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[(KeyboardType PTR esi+ebx).Bits]\t\t; get the bit to test\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[(KeyboardType PTR esi).CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\n\t\t\t\t\t; keyboard buffer.\n\n\tmov\tecx,eax\n\txor\teax,eax\n\tmov\tax,cx\n\nIF DEBUG\n\tcmp\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\n\tinc\t[BYTE PTR 0B0002h]\n\n\tcmp\teax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\teax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\teax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\t\n\tcmp\teax,125\n\tjne\t??not_toggle\n\n\tinc\t[BYTE PTR 0B0000h]\n\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjmp\t??absorbcode\nENDIF\n\n??not_toggle:\n\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\teax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\teax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\teax,0230h\n\tje\tshort ??breaker\n\tcmp\teax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[(KeyboardType PTR esi).Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n;\tcmp\tax,0420H\t\t; is this an alt s\n;\tjne\tshort ??checkmusic\t; toggle the Sound variable\n;\tpush\tax\n;\tmov\tax,[SoundOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??checkmusic:\n;\tcmp\tax,0434H\t\t; is this an alt m\n;\tjne\tshort ??esc\t\t; toggle the Music variable\n;\tpush\tax\n;\tmov\tax,[MusicOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??esc:\n\n\tpush\teax\n\tcall\tStuff_Key_Num\n\tpop\teax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[(KeyboardType PTR esi).EscRoutine],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\teax\n\tcall\t[(KeyboardType PTR esi).EscRoutine]\n\tpop\teax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tedi,OFFSET (KeyboardType PTR 0).PassAlways\t; get offset to table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd - OFFSET (KeyboardType PTR 0).PassAlways) ; get number of pass always CDY JLB MOD 7/11 was \n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tedi,OFFSET (KeyboardType PTR 0).CondPassKey\t; get offset to cond key table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).CondPassCond-OFFSET (KeyboardType PTR 0).CondPassKey) ; get number of entries\n\tshr\tecx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(OFFSET (KeyboardType PTR 0).CondPassCond - OFFSET (KeyboardType PTR 0).CondPassKey) - 2 + edi]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tedx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\tinc\t[(KeyboardType PTR esi).PassCount]\n\n\t; Step 5.\n\t; Now it is time to set up for the call by returning by poking\n\t; the old interupt handle address in.\n\tmov\t[(KeyboardType PTR esi).PMIssuedKeyInt],1\t\t; Make it TRUE\n\tmov\teax,[(KeyboardType PTR esi).KeyOldPMIOffset]\t; Get orig offset.\n\tmov\tebx,[(KeyboardType PTR esi).KeyOldPMISelector]\t; Get orig selector.\n\tmov\t[ss:ebp+4],eax\t\t\t\t\t; Poke offset.\n\tmov\t[ss:ebp+8],ebx\t\t\t\t\t; Poke selector.\n\n\t; Step 6.\n\tpop\tfs gs es ds\n\tpopad\n\tpop\tebp\n\n\t; Step 7.\n\tiretd\n\n??absorbcode:\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tal,[496h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[496h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\n\tpop\tfs gs es ds\n\tpopad\n\n\tpop\tebp  \n\tadd\tesp,8\n\tpopfd\n\tiret\t\n\n\tENDP\tKeyboard_Interrupt\n\nELSE\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Stub for the keyboard interrupt call real mode    *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\n \nDATASEG\nSTRUC\tRealModeCallStruc\n\t_EDI  DD\t0\n\t_ESI  DD\t0\n\t_EBP  DD\t0\n\t      DD        0\n\t_EBX  DD\t0\n\t_EDX  DD\t0\n\t_ECX  DD\t0\n\t_EAX  DD        0\n\tFLAGS DW\t0\n\t_ES   DW\t0\n\t_DS   DW\t0\n\t_FS   DW\t0\n\t_GS   DW\t0\n\t_IP   DW\t0\n\t_CS   DW\t0\n\t_SP   DW\t0\n\t_SS   DW\t0\n\t      dd\t0\n\t      dd\t0\n  nothing     dd\t0\t\nENDS \n\nRMDS RealModeCallStruc  <>\n\nCODESEG\n\nPROC\tKeyboard_Interrupt\tNear\n\n; This option of the keyboard interrupt handle will not be\n; available at this moment because the light version of Rational System DOS\n; Extender do not allow a DPMI real mode call which is\n; DMPI INT 31h funtion 0301h\n\n\tpushad\t\n\tpush\tfs gs es ds\n\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\n\tlea\tedi , [ RMDS ]\n\tlea\tecx , [ RMDS . nothing ]\n\tsub\tecx , edi\n\txor\teax , eax\n\tshr\tecx , 2\n\trep\tstosd\n\t\n\tmov\teax , 0300h\n\tmov\tbl , [ byte ptr RMVector ]\n\txor\tbh , bh\n\txor\tcx , cx\n\tlea\tedi , [RMDS]\n\tint\tDPMI_INTR\n\n; this is here only for testing to make sure\n; that a real mode interrupt is bieng issued. \nmov\tax , _DATA\nmov\tes , ax\nmov\tds , ax\nmov [ byte ptr 0b0000h + 10 * 80 + 40 ] , 040h\njc\t??error\nmov [ byte ptr 0b0000h + 10 * 80 + 42 ] , 041h\n\n??error:\n\tpop\tds es gs fs\n\tpopad\t\n\tiretd\n\tENDP\n\nENDIF\n\nLABEL \tLockedCodeEnd\t\tBYTE\n\n;***************************************************************************\n;* End of File.\t\t\t\t\t\t\t\t   *\n;***************************************************************************\nEND\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/KEYBOARD.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Keyboard Library                                    *\n *                                                                                             *\n *                    File Name : KEYBOARD.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 10/16/95                                                     *\n *                                                                                             *\n *                  Last Update : October 26, 1995   []                    *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                         *\n *   WWKeyboardClass::Get -- Logic to get a metakey from the buffer                            *\n *   WWKeyboardClass::Check -- Checks to see if a key is in the buffer                         *\n *   WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer    *\n *   WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer               *\n *   WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels           *\n *   WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels           *\n *   WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars       *\n *   Check_Key -- compatability routine for old 32 bit library             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"keyboard.h\"\n\nvoid Message_Loop(void);\n\nWWKeyboardClass *_Kbd;\n\n/***********************************************************************************************\n * WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class                *\n *                                                                                             *\n * INPUT:\t\tnone\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * OUTPUT:     none\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nWWKeyboardClass::WWKeyboardClass(void)\n{\n\t_Kbd = this;\n\t//\n\t// Initialize the keyboard remap table for our system (note it would be bad if someone\n\t// switched keyboard modes after this happened.\n\t//\n\tmemset(VKRemap, 0, 256);\n\tmemset(AsciiRemap, 0, 2048);\n\tfor (short lp = 31; lp < 255; lp ++) {\n!----- Conflict 1 - Base File: C:\\TEMP\\KEYBOARD.CPP( *** PARENT *** )\n!----- File 1: D:\\WIN32LIB\\KEYBOARD\\KEYBOARD.CPP( *** Primary *** )\n\t\tint vk_key = VkKeyScan((unsigned char)lp);\n!----- File 2: I:\\WIN32LIB\\KEYBOARD\\KEYBOARD.CPP( *** Secondary *** )\n\t\tint vk_key = (int)VkKeyScan((TCHAR)lp);\n!----- End Conflict\n\t\tif (vk_key > 0 && vk_key < 2048) {\n\t\t\tAsciiRemap[vk_key] = (unsigned char)lp;\n\t\t\tVKRemap[lp] \t = (unsigned char)(vk_key & 0xFF);\n\t\t}\n\t}\n\n\t//\n\t// Build a remap table of the different keys which are affected by the caps lock and\n\t// the num lock.\n\t//\n\tmemset(ToggleKeys, 0, 256);\n\tfor (lp = 0; lp < 255; lp++ ) {\n\t\tif (isalpha(lp) && isupper(lp)) {\n\t\t\tToggleKeys[lp] = 1;\n\t\t}\n\t\tif (lp >= VK_NUMPAD0 && lp <= VK_DIVIDE) {\n\t\t\tToggleKeys[lp] = 2;\n\t\t}\n\t}\n\n\t//\n\t// Our buffer should start devoid of keys.\n\t//\n\tmemset(Buffer, 0, 256);\n\tHead\t\t\t\t= 0;\n\tTail\t\t\t\t= 0;\n\n\t//\n\t// There should be no starting queued mouse events for us to have to worry\n\t// about.\n\t//\n\tMouseQX\t\t\t= 0;\n\tMouseQY\t\t\t= 0;\n\tMState\t\t\t= 0;\n\tConditional\t\t= 0;\n\tCurrentCursor\t= NULL;\n}\n\n/***********************************************************************************************\n * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer                 *\n *                                                                                             *\n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     int\t\t- the key value that was pulled from buffer (includes bits)\t\t\t\t  *                                                                                *\n *                                                                                             *\n * WARNINGS:   If the key was a mouse event MouseQX and MouseQY will be updated                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nint WWKeyboardClass::Buff_Get(void)\n{\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t\t\t// wait for key in buffer\n\tint \ttemp\t\t= Buffer[Head];\t\t\t\t\t\t// get key out of the buffer\n\tint   newhead\t= Head;\t\t\t\t\t\t\t\t\t// save off head for manipulation\n\tif (Is_Mouse_Key(temp)) {\t\t\t\t\t\t\t\t// if key is a mouse then\n\t\tMouseQX\t= Buffer[Head+1];\t\t\t\t\t\t\t//\t\tget the x and y pos\n\t\tMouseQY\t= Buffer[Head+2];\t\t\t\t\t\t\t//\t\tfrom the buffer\n\t\tnewhead += 3;\t\t  \t\t\t\t\t\t\t\t\t//\t\tadjust head forward\n\t} else {\n\t\tnewhead += 1;\t\t  \t\t\t\t\t\t\t\t\t//\t\tadjust head forward\n\t}\n\tnewhead\t&= 255;\n\tHead\t\t = newhead;\n\treturn(temp);\n}\n\nBOOL WWKeyboardClass::Is_Mouse_Key(int key)\n{\n\tkey &= 0xFF;\n\treturn (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Check -- Checks to see if a key is in the buffer                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nBOOL WWKeyboardClass::Check(void)\n{\n\tMessage_Loop();\n\tunsigned short temp;\t\t\t\t\t\t\t\t\t\t\t// store temp holding spot for key\n\tif (Head == Tail) return(FALSE);\t\t\t\t\t\t\t// if no keys in buff then get out\n\ttemp = Buffer[Head];\t\t\t\t\t\t\t\t\t\t\t// get key out of the buffer\n\treturn(temp);\t\t\t\t\t\t\t\t\t\t\t\t\t// send it back to main program\n}\n\n/***********************************************************************************************\n * WWKeyboardClass::Get -- Logic to get a metakey from the buffer                              *\n *                                                                                             *\n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     int\t\t- the meta key taken from the buffer.\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:\tThis routine will not return until a keypress is received\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nint WWKeyboardClass::Get(void)\n{\n\tint temp,bits;\t\t\t\t\t\t\t\t\t\t// store temp holding spot for key\n\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t// wait for key in buffer\n\ttemp = Buff_Get();\t\t\t\t\t\t\t\t// get key from the buffer\n\n\tbits = temp & 0xFF00;\t\t\t\t\t\t\t// save of keyboard bits\n\n\tif (!(bits & WWKEY_VK_BIT)) {\t\t\t\t\t// if its not a virtual key\n\t\ttemp = AsciiRemap[temp&0x1FF] | bits;\t//   convert to ascii equivalent\n\t}\n\treturn(temp);\t\t\t\t\t\t\t// return the key that we pulled out\n}\n\n/***********************************************************************************************\n * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                           *\n *                                                                                             *\n * INPUT:\t\tint\t \t- the key to insert into the buffer          \t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     bool\t\t- true if key is sucessfuly inserted.\t\t\t\t\t\t\t              *\n *                                                                                             *\n * WARNINGS:   none\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nBOOL WWKeyboardClass::Put(int key)\n{\n\tint\ttemp\t\t= (Tail + 1) & 255;\n\tif (temp != Head)\n\t{\n\t\tBuffer[Tail]\t= (short)key;\n\n\t\t//\n\t\t// Critical Line\n\t\t//\n\t\tTail\t\t\t\t= temp;\n\t\treturn(TRUE);\n\t}\n\treturn(FALSE);\n}\n/***********************************************************************************************\n * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nWWKeyboardClass::Put_Key_Message(UINT vk_key, BOOL release, BOOL dbl)\n{\n\tint bits = 0;\n\t//\n\t// Get the status of all of the different keyboard modifiers.  Note, only pay attention\n\t// to numlock and caps lock if we are dealing with a key that is affected by them.\n\t//\n\tint\tshift\t\t= (GetKeyState(VK_SHIFT) & 0xFF00) \t\t!= 0;\n\tint\tctrl \t\t= (GetKeyState(VK_CONTROL) & 0xFF00) \t!= 0;\n\tint\talt \t\t= (GetKeyState(VK_MENU) & 0xFF00) \t\t!= 0;\n\tint\tcaps\t\t= ((GetKeyState(VK_CAPITAL) & 0x00FF) \t!= 0) && (ToggleKeys[vk_key] == 1);\n\tint\tnums\t\t= ((GetKeyState(VK_NUMLOCK) & 0x00FF) \t!= 0) && (ToggleKeys[vk_key] == 2);\n\n\t//\n\t// Set the proper bits for whatever the key we got is.\n\t//\n\tif (shift || caps || nums) {\n\t\tbits |= WWKEY_SHIFT_BIT;\n\t}\n\tif (ctrl) {\n\t\tbits |= WWKEY_CTRL_BIT;\n\t}\n\tif (alt) {\n\t\tbits |= WWKEY_ALT_BIT;\n\t}\n\tif (!AsciiRemap[vk_key|bits]) {\n\t\tbits |= WWKEY_VK_BIT;\n\t}\n\tif (release) {\n\t\tbits |= WWKEY_RLS_BIT;\n\t}\n\tif (dbl) {\n\t\tbits |= WWKEY_DBL_BIT;\n\t}\n\t//\n\t// Finally use the put command to enter the key into the keyboard\n\t// system.\n\t//\n\treturn(Put(vk_key|bits));\n}\n\nvoid WWKeyboardClass::Clear(void)\n{\n\tHead = Tail;\n}\n\nint WWKeyboardClass::To_ASCII(int key)\n{\n\treturn(key);\n}\n\nWWKeyboardClass::Down(int key)\n{\n\treturn(GetAsyncKeyState(key&0xFF));\n}\n\nVOID WWKeyboardClass::Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl)\n{\n\tshift = (key & WWKEY_SHIFT_BIT)\t!= 0;\n\tctrl\t= (key & WWKEY_CTRL_BIT)\t!= 0;\n\talt\t= (key & WWKEY_ALT_BIT)\t\t!= 0;\n\trls\t= (key & WWKEY_RLS_BIT)\t\t!= 0;\n\tdbl\t= (key & WWKEY_DBL_BIT)\t\t!= 0;\n\tkey\t= (key & 0xFF);\n\n}\n\n\nextern \"C\" {\n\tvoid __cdecl Stop_Execution (void);\n}\n\n#pragma off(unreferenced)\nvoid WWKeyboardClass::Message_Handler(HWND , UINT message, UINT wParam, LONG lParam)\n{\n\tswitch (message) {\n\t\tcase WM_SYSKEYDOWN:\n\t\tcase WM_KEYDOWN:\n\t\t\tif ( wParam==VK_SCROLL ){\n\t\t\t\tStop_Execution();\n\t\t\t} else {\n\t\t\t\tPut_Key_Message(wParam);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WM_SYSKEYUP:\n\t\tcase WM_KEYUP:\n\t\t\tPut_Key_Message(wParam, TRUE);\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_LBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONUP:\n\t\t\tPut_Key_Message(VK_LBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_LBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_MBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONUP:\n\t\t\tPut_Key_Message(VK_MBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_MBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_RBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONUP:\n\t\t\tPut_Key_Message(VK_RBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_RBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\t\tcase WM_MOUSEMOVE:\n\t\t\tif (CurrentCursor)\n\t\t\t\tSetCursor(CurrentCursor);\n\t\t\tbreak;\n\t}\n}\n#pragma on(unreferenced)\n\n\n\nextern BOOL GameInFocus;\n\nvoid Message_Loop(void)\n{\n\tMSG msg;\n\n\tdo {\n\n\t\twhile (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE )) {\n\t  \t\tif( !GetMessage( &msg, NULL, 0, 0 ) ){\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tTranslateMessage(&msg);\n\t\t\tDispatchMessage(&msg);\n\t\t}\n\t} while (!GameInFocus);\n}\n\n\n/***************************************************************************\n * CHECK_KEY -- compatability routine for old 32 bit library               *\n *                                                                         *\n * This routine checks to see if there is a key in the keyboard buffer     *\n * and returns it to the sender if there is.  It does not remove the key\t*\n * from the buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     The key that was pressed.                                   *\n *                                                                         *\n * WARNINGS:   You must declare a WWKeyboardClass object before calling    *\n *\t\t\t\t\tthis routine.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/26/1995     : Created.                                             *\n *=========================================================================*/\nint Check_Key(void)\n{\n\tif (!_Kbd) return(KA_NONE);\n\treturn(_Kbd->Check() & ~WWKEY_SHIFT_BIT);\n}\n\nvoid Clear_KeyBuffer(void)\n{\n\tif (!_Kbd) return;\n\t_Kbd->Clear();\n}\n\nint Check_Key_Num(void)\n{\n\tif (!_Kbd) return(KN_NONE);\n\tint key\t\t= _Kbd->Check();\n\tint flags\t= key & 0xFF00;\n\tkey\t\t   = key & 0x00FF;\n\tif (isupper(key)) {\n\t\tkey = tolower(key);\n\t\tflags |= WWKEY_SHIFT_BIT;\n\t}\n\n\treturn(key | flags);\n}\n\nint Get_Key_Num(void)\n{\n\tif (!_Kbd) return(KN_NONE);\n\tint key\t\t= _Kbd->Get();\n\tint flags\t= key & 0xFF00;\n\tkey\t\t   = key & 0x00FF;\n\tif (isupper(key)) {\n\t\tkey = tolower(key);\n\t\tflags |= WWKEY_SHIFT_BIT;\n\t}\n\n\treturn(key | flags);\n}\n\nint KN_To_KA(int key)\n{\n\tif (!(key & WWKEY_VK_BIT)) {\n\t\tint flags = key & 0xFF00;\n\t\tkey\t\t = key & 0x00FF;\n\t\tif (flags & WWKEY_SHIFT_BIT) {\n\t\t\tkey\t\t= toupper(key);\n\t\t\tflags\t  &= ~WWKEY_SHIFT_BIT;\n\t\t}\n\t}\n\treturn(key);\n}\n\nint Key_Down(int key)\n{\n\tif (!_Kbd) return(FALSE);\n\treturn(_Kbd->Down(key));\n}\n\nint Get_Key(void)\n{\n\tif (!_Kbd) return(KN_NONE);\n\treturn(_Kbd->Get() & ~WWKEY_SHIFT_BIT);\n}\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/KEYBOARD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Keyboard Library                                    *\n *                                                                                             *\n *                    File Name : KEYBOARD.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 10/16/95                                                     *\n *                                                                                             *\n *                  Last Update : October 26, 1995   []                    *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                         *\n *   WWKeyboardClass::Get -- Logic to get a metakey from the buffer                            *\n *   WWKeyboardClass::Check -- Checks to see if a key is in the buffer                         *\n *   WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer    *\n *   WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer               *\n *   WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels           *\n *   WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels           *\n *   WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars       *\n *   Check_Key -- compatability routine for old 32 bit library             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"keyboard.h\"\n\nvoid Message_Loop(void);\n\nWWKeyboardClass *_Kbd;\n\n/***********************************************************************************************\n * WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class                *\n *                                                                                             *\n * INPUT:\t\tnone\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * OUTPUT:     none\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nWWKeyboardClass::WWKeyboardClass(void)\n{\n\t_Kbd = this;\n\t//\n\t// Initialize the keyboard remap table for our system (note it would be bad if someone\n\t// switched keyboard modes after this happened.\n\t//\n\tmemset(VKRemap, 0, 256);\n\tmemset(AsciiRemap, 0, 2048);\n\tfor (short lp = 31; lp < 255; lp ++) {\n\t\tint vk_key = VkKeyScan((unsigned char)lp);\n\t\tif (vk_key > 0 && vk_key < 2048) {\n\t\t\tAsciiRemap[vk_key] = (unsigned char)lp;\n\t\t\tVKRemap[lp] \t = (unsigned char)(vk_key & 0xFF);\n\t\t}\n\t}\n\n\t//\n\t// Build a remap table of the different keys which are affected by the caps lock and\n\t// the num lock.\n\t//\n\tmemset(ToggleKeys, 0, 256);\n\tfor (lp = 0; lp < 255; lp++ ) {\n\t\tif (isalpha(lp) && isupper(lp)) {\n\t\t\tToggleKeys[lp] = 1;\n\t\t}\n\t\tif (lp >= VK_NUMPAD0 && lp <= VK_DIVIDE) {\n\t\t\tToggleKeys[lp] = 2;\n\t\t}\n\t}\n\n\t//\n\t// Our buffer should start devoid of keys.\n\t//\n\tmemset(Buffer, 0, 256);\n\tHead\t\t\t\t= 0;\n\tTail\t\t\t\t= 0;\n\n\t//\n\t// There should be no starting queued mouse events for us to have to worry\n\t// about.\n\t//\n\tMouseQX\t\t\t= 0;\n\tMouseQY\t\t\t= 0;\n\tMState\t\t\t= 0;\n\tConditional\t\t= 0;\n\tCurrentCursor\t= NULL;\n}\n\n/***********************************************************************************************\n * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer                 *\n *                                                                                             *\n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     int\t\t- the key value that was pulled from buffer (includes bits)\t\t\t\t  *                                                                                *\n *                                                                                             *\n * WARNINGS:   If the key was a mouse event MouseQX and MouseQY will be updated                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nint WWKeyboardClass::Buff_Get(void)\n{\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t\t\t// wait for key in buffer\n\tint \ttemp\t\t= Buffer[Head];\t\t\t\t\t\t// get key out of the buffer\n\tint   newhead\t= Head;\t\t\t\t\t\t\t\t\t// save off head for manipulation\n\tif (Is_Mouse_Key(temp)) {\t\t\t\t\t\t\t\t// if key is a mouse then\n\t\tMouseQX\t= Buffer[Head+1];\t\t\t\t\t\t\t//\t\tget the x and y pos\n\t\tMouseQY\t= Buffer[Head+2];\t\t\t\t\t\t\t//\t\tfrom the buffer\n\t\tnewhead += 3;\t\t  \t\t\t\t\t\t\t\t\t//\t\tadjust head forward\n\t} else {\n\t\tnewhead += 1;\t\t  \t\t\t\t\t\t\t\t\t//\t\tadjust head forward\n\t}\n\tnewhead\t&= 255;\n\tHead\t\t = newhead;\n\treturn(temp);\n}\n\nBOOL WWKeyboardClass::Is_Mouse_Key(int key)\n{\n\tkey &= 0xFF;\n\treturn (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Check -- Checks to see if a key is in the buffer                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nBOOL WWKeyboardClass::Check(void)\n{\n\tMessage_Loop();\n\tunsigned short temp;\t\t\t\t\t\t\t\t\t\t\t// store temp holding spot for key\n\tif (Head == Tail) return(FALSE);\t\t\t\t\t\t\t// if no keys in buff then get out\n\ttemp = Buffer[Head];\t\t\t\t\t\t\t\t\t\t\t// get key out of the buffer\n\treturn(temp);\t\t\t\t\t\t\t\t\t\t\t\t\t// send it back to main program\n}\n\n/***********************************************************************************************\n * WWKeyboardClass::Get -- Logic to get a metakey from the buffer                              *\n *                                                                                             *\n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     int\t\t- the meta key taken from the buffer.\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:\tThis routine will not return until a keypress is received\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nint WWKeyboardClass::Get(void)\n{\n\tint temp,bits;\t\t\t\t\t\t\t\t\t\t// store temp holding spot for key\n\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t// wait for key in buffer\n\ttemp = Buff_Get();\t\t\t\t\t\t\t\t// get key from the buffer\n\n\tbits = temp & 0xFF00;\t\t\t\t\t\t\t// save of keyboard bits\n\n\tif (!(bits & WWKEY_VK_BIT)) {\t\t\t\t\t// if its not a virtual key\n\t\ttemp = AsciiRemap[temp&0x1FF] | bits;\t//   convert to ascii equivalent\n\t}\n\treturn(temp);\t\t\t\t\t\t\t// return the key that we pulled out\n}\n\n/***********************************************************************************************\n * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                           *\n *                                                                                             *\n * INPUT:\t\tint\t \t- the key to insert into the buffer          \t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     bool\t\t- true if key is sucessfuly inserted.\t\t\t\t\t\t\t              *\n *                                                                                             *\n * WARNINGS:   none\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nBOOL WWKeyboardClass::Put(int key)\n{\n\tint\ttemp\t\t= (Tail + 1) & 255;\n\tif (temp != Head)\n\t{\n\t\tBuffer[Tail]\t= (short)key;\n\n\t\t//\n\t\t// Critical Line\n\t\t//\n\t\tTail\t\t\t\t= temp;\n\t\treturn(TRUE);\n\t}\n\treturn(FALSE);\n}\n/***********************************************************************************************\n * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nWWKeyboardClass::Put_Key_Message(UINT vk_key, BOOL release, BOOL dbl)\n{\n\tint bits = 0;\n\t//\n\t// Get the status of all of the different keyboard modifiers.  Note, only pay attention\n\t// to numlock and caps lock if we are dealing with a key that is affected by them.\n\t//\n\tint\tshift\t\t= (GetKeyState(VK_SHIFT) & 0xFF00) \t\t!= 0;\n\tint\tctrl \t\t= (GetKeyState(VK_CONTROL) & 0xFF00) \t!= 0;\n\tint\talt \t\t= (GetKeyState(VK_MENU) & 0xFF00) \t\t!= 0;\n\tint\tcaps\t\t= ((GetKeyState(VK_CAPITAL) & 0x00FF) \t!= 0) && (ToggleKeys[vk_key] == 1);\n\tint\tnums\t\t= ((GetKeyState(VK_NUMLOCK) & 0x00FF) \t!= 0) && (ToggleKeys[vk_key] == 2);\n\n\t//\n\t// Set the proper bits for whatever the key we got is.\n\t//\n\tif (shift || caps || nums) {\n\t\tbits |= WWKEY_SHIFT_BIT;\n\t}\n\tif (ctrl) {\n\t\tbits |= WWKEY_CTRL_BIT;\n\t}\n\tif (alt) {\n\t\tbits |= WWKEY_ALT_BIT;\n\t}\n\tif (!AsciiRemap[vk_key|bits]) {\n\t\tbits |= WWKEY_VK_BIT;\n\t}\n\tif (release) {\n\t\tbits |= WWKEY_RLS_BIT;\n\t}\n\tif (dbl) {\n\t\tbits |= WWKEY_DBL_BIT;\n\t}\n\t//\n\t// Finally use the put command to enter the key into the keyboard\n\t// system.\n\t//\n\treturn(Put(vk_key|bits));\n}\n\nvoid WWKeyboardClass::Clear(void)\n{\n\tHead = Tail;\n}\n\nint WWKeyboardClass::To_ASCII(int key)\n{\n\treturn(key);\n}\n\nWWKeyboardClass::Down(int key)\n{\n\treturn(GetAsyncKeyState(key&0xFF));\n}\n\nVOID WWKeyboardClass::Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl)\n{\n\tshift = (key & WWKEY_SHIFT_BIT)\t!= 0;\n\tctrl\t= (key & WWKEY_CTRL_BIT)\t!= 0;\n\talt\t= (key & WWKEY_ALT_BIT)\t\t!= 0;\n\trls\t= (key & WWKEY_RLS_BIT)\t\t!= 0;\n\tdbl\t= (key & WWKEY_DBL_BIT)\t\t!= 0;\n\tkey\t= (key & 0xFF);\n\n}\n\n\nextern \"C\" {\n\tvoid __cdecl Stop_Execution (void);\n}\n\n#pragma off(unreferenced)\nvoid WWKeyboardClass::Message_Handler(HWND , UINT message, UINT wParam, LONG lParam)\n{\n\tswitch (message) {\n\t\tcase WM_SYSKEYDOWN:\n\t\tcase WM_KEYDOWN:\n\t\t\tif ( wParam==VK_SCROLL ){\n\t\t\t\tStop_Execution();\n\t\t\t} else {\n\t\t\t\tPut_Key_Message(wParam);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WM_SYSKEYUP:\n\t\tcase WM_KEYUP:\n\t\t\tPut_Key_Message(wParam, TRUE);\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_LBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONUP:\n\t\t\tPut_Key_Message(VK_LBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_LBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_MBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONUP:\n\t\t\tPut_Key_Message(VK_MBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_MBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_RBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONUP:\n\t\t\tPut_Key_Message(VK_RBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_RBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\t\tcase WM_MOUSEMOVE:\n\t\t\tif (CurrentCursor)\n\t\t\t\tSetCursor(CurrentCursor);\n\t\t\tbreak;\n\t}\n}\n#pragma on(unreferenced)\n\n\n\nextern BOOL GameInFocus;\n\nvoid Message_Loop(void)\n{\n\tMSG msg;\n\n\tdo {\n\n\t\twhile (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE )) {\n\t  \t\tif( !GetMessage( &msg, NULL, 0, 0 ) ){\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tTranslateMessage(&msg);\n\t\t\tDispatchMessage(&msg);\n\t\t}\n\t} while (!GameInFocus);\n}\n\n\n/***************************************************************************\n * CHECK_KEY -- compatability routine for old 32 bit library               *\n *                                                                         *\n * This routine checks to see if there is a key in the keyboard buffer     *\n * and returns it to the sender if there is.  It does not remove the key\t*\n * from the buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     The key that was pressed.                                   *\n *                                                                         *\n * WARNINGS:   You must declare a WWKeyboardClass object before calling    *\n *\t\t\t\t\tthis routine.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/26/1995     : Created.                                             *\n *=========================================================================*/\nint Check_Key(void)\n{\n\tif (!_Kbd) return(KA_NONE);\n\treturn(_Kbd->Check() & ~WWKEY_SHIFT_BIT);\n}\n\nvoid Clear_KeyBuffer(void)\n{\n\tif (!_Kbd) return;\n\t_Kbd->Clear();\n}\n\nint Check_Key_Num(void)\n{\n\tif (!_Kbd) return(KN_NONE);\n\tint key\t\t= _Kbd->Check();\n\tint flags\t= key & 0xFF00;\n\tkey\t\t   = key & 0x00FF;\n\tif (isupper(key)) {\n\t\tkey = tolower(key);\n\t\tflags |= WWKEY_SHIFT_BIT;\n\t}\n\n\treturn(key | flags);\n}\n\nint Get_Key_Num(void)\n{\n\tif (!_Kbd) return(KN_NONE);\n\tint key\t\t= _Kbd->Get();\n\tint flags\t= key & 0xFF00;\n\tkey\t\t   = key & 0x00FF;\n\tif (isupper(key)) {\n\t\tkey = tolower(key);\n\t\tflags |= WWKEY_SHIFT_BIT;\n\t}\n\n\treturn(key | flags);\n}\n\nint KN_To_KA(int key)\n{\n\tif (!(key & WWKEY_VK_BIT)) {\n\t\tint flags = key & 0xFF00;\n\t\tkey\t\t = key & 0x00FF;\n\t\tif (flags & WWKEY_SHIFT_BIT) {\n\t\t\tkey\t\t= toupper(key);\n\t\t\tflags\t  &= ~WWKEY_SHIFT_BIT;\n\t\t}\n\t}\n\treturn(key);\n}\n\nint Key_Down(int key)\n{\n\tif (!_Kbd) return(FALSE);\n\treturn(_Kbd->Down(key));\n}\n\nint Get_Key(void)\n{\n\tif (!_Kbd) return(KN_NONE);\n\treturn(_Kbd->Get() & ~WWKEY_SHIFT_BIT);\n}\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/KEYBOARD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Keyboard Library                                    *\n *                                                                                             *\n *                    File Name : KEYBOARD.H                                                   *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 10/16/95                                                     *\n *                                                                                             *\n *                  Last Update : October 16, 1995 [PWG]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include <WWSTD.H>\n\ntypedef enum {\n\tWWKEY_SHIFT_BIT\t= 0x100,\n\tWWKEY_CTRL_BIT\t\t= 0x200,\n\tWWKEY_ALT_BIT\t\t= 0x400,\n\tWWKEY_RLS_BIT\t\t= 0x800,\n\tWWKEY_VK_BIT\t\t= 0x1000,\n\tWWKEY_DBL_BIT\t\t= 0x2000,\n\tWWKEY_BTN_BIT\t\t= 0x8000,\n} WWKey_Type;\n\nclass WWKeyboardClass\n{\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tWWKeyboardClass();\n\n\t\t/*===================================================================*/\n\t\t/* Define the functions which work with the Keyboard Class\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBOOL \tCheck(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for meta key\n\t\tint \tGet(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// gets a meta key from the keybuffer\n\t\tBOOL \tPut(int key);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// dumps a key into the keybuffer\n\t\tBOOL\tPut_Key_Message(\tUINT vk_key, BOOL release = FALSE, \t\t// handles keyboard related message\n\t\t\t\t\t\t\t\t\t\tBOOL dbl = FALSE);\t\t\t\t\t\t\t//   and mouse clicks and dbl clicks\n\t\tint \tCheck_Num(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for a keynum key\n\t\tint \tGet_VK(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// gets keynum key from key buff\n\t\tint \tCheck_ACII(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for an ascii key\n\t\tint \tGet_ASCII(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// gets an ascii key from keybuff\n\t\tint \tCheck_Bits(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for key w/ bits\n\t\tint \tGet_Bits(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// get key from keybuff w/ bits\n\t\tint \tTo_ASCII(int num);\t\t\t\t\t\t\t\t\t\t\t\t\t// converts keynum to ascii value\n\t\tint \tOption_On(int option);\t\t\t\t\t\t\t\t\t\t\t\t// turns specified option on\n\t\tint \tOption_Off(int option);\t\t\t\t\t\t\t\t\t\t\t\t// turns specified option off\n\t\tvoid \tClear(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// clears all keys from keybuffer\n\t\tint \tDown(int key);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// tests to see if a key is down\n\t\tvoid\tAI(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// messaging logic for key manager\n\n\t\t/*===================================================================*/\n\t\t/* Define the main hook for the message processing loop.\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tvoid Message_Handler(HWND hwnd, UINT message, UINT wParam, LONG lParam);\n\n\t\t/*===================================================================*/\n\t\t/* Define public routines which can be used on keys in general.\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl);\n\t\tBOOL Is_Mouse_Key(int key);\n\n\n\t\t/*===================================================================*/\n\t\t/* Define the public access variables which are used with the\t\t\t*/\n\t\t/*   Keyboard Class.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tint\t\t\t\tMouseQX;\n\t\tint\t\t\t\tMouseQY;\n\n\tprivate:\n\t\t/*===================================================================*/\n\t\t/* Define the private access functions which are used by keyboard\t\t*/\n\t\t/*===================================================================*/\n\t\tint  Buff_Get(void);\n\n\n\t\t/*===================================================================*/\n\t\t/* Define the private access variables which are used with the\t\t\t*/\n\t\t/*   Keyboard Class.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tunsigned char\tAsciiRemap[2048];\t// remap for shft/ctrl/alt key combos\n\t\tunsigned char\tVKRemap[256];\t\t// gives vk for any ascii char\n\t\tunsigned short Buffer[256];\t\t// buffer which holds actual keypresses\n\t\tunsigned char  ToggleKeys[256];\t// determines toggles which affect key\n\t\tlong\t\t\t\tHead;\t\t\t\t\t// the head position in keyboard buffer\n\t\tlong\t\t\t\tTail;\t\t\t\t\t// the tail position in keyboard buffer\n\t\tint\t\t\t\tMState;\n\t\tint\t\t\t\tConditional;\n\t\tHANDLE\t\t\tCurrentCursor;\n};\n\n\n#define\tVK_NONE\t\t\t\t  0x00\n#define\tVK_LBUTTON          0x01\n#define\tVK_RBUTTON          0x02\n#define\tVK_CANCEL           0x03\n#define\tVK_MBUTTON          0x04\n#define\tVK_NONE_05\t\t\t  0x05\n#define\tVK_NONE_06\t\t\t  0x06\n#define\tVK_NONE_07\t\t\t  0x07\n#define\tVK_BACK             0x08\n#define\tVK_TAB              0x09\n#define\tVK_NONE_0A\t\t\t  0x0A\n#define\tVK_NONE_0B\t\t\t  0x0B\n#define\tVK_CLEAR            0x0C\n#define\tVK_RETURN           0x0D\n#define\tVK_NONE_0E\t\t\t  0x0E\n#define\tVK_NONE_0F\t\t\t  0x0F\n#define\tVK_SHIFT            0x10\n#define\tVK_CONTROL          0x11\n#define\tVK_MENU             0x12\n#define\tVK_PAUSE            0x13\n#define\tVK_CAPITAL          0x14\n#define\tVK_NONE_15\t\t\t  0x15\n#define\tVK_NONE_16\t\t\t  0x16\n#define\tVK_NONE_17\t\t\t  0x17\n#define\tVK_NONE_18\t\t\t  0x18\n#define\tVK_NONE_19\t\t\t  0x19\n#define\tVK_NONE_1A\t\t\t  0x1A\n#define\tVK_ESCAPE           0x1B\n#define\tVK_NONE_1C\t\t\t  0x1C\n#define\tVK_NONE_1D\t\t\t  0x1D\n#define\tVK_NONE_1E\t\t\t  0x1E\n#define\tVK_NONE_1F\t\t\t  0x1F\n#define\tVK_SPACE            0x20\n#define\tVK_PRIOR            0x21\n#define\tVK_NEXT             0x22\n#define\tVK_END              0x23\n#define\tVK_HOME             0x24\n#define\tVK_LEFT             0x25\n#define\tVK_UP               0x26\n#define\tVK_RIGHT            0x27\n#define\tVK_DOWN             0x28\n#define\tVK_SELECT           0x29\n#define\tVK_PRINT            0x2A\n#define\tVK_EXECUTE          0x2B\n#define\tVK_SNAPSHOT         0x2C\n#define\tVK_INSERT           0x2D\n#define\tVK_DELETE           0x2E\n#define\tVK_HELP             0x2F\n#define\tVK_0\t\t\t\t\t  0x30\n#define\tVK_1\t\t\t\t\t  0x31\n#define\tVK_2\t\t\t\t\t  0x32\n#define\tVK_3\t\t\t\t\t  0x33\n#define\tVK_4\t\t\t\t\t  0x34\n#define\tVK_5\t\t\t\t\t  0x35\n#define\tVK_6\t\t\t\t\t  0x36\n#define\tVK_7\t\t\t\t\t  0x37\n#define\tVK_8\t\t\t\t\t  0x38\n#define\tVK_9\t\t\t\t\t  0x39\n#define\tVK_NONE_3B\t\t\t  0x3B\n#define\tVK_NONE_3C\t\t\t  0x3C\n#define\tVK_NONE_3D\t\t\t  0x3D\n#define\tVK_NONE_3E\t\t\t  0x3E\n#define\tVK_NONE_3F\t\t\t  0x3F\n#define\tVK_NONE_40\t\t\t  0x40\n#define\tVK_A\t\t\t\t\t  0x41\n#define\tVK_B\t\t\t\t\t  0x42\n#define\tVK_C\t\t\t\t\t  0x43\n#define\tVK_D\t\t\t\t\t  0x44\n#define\tVK_E\t\t\t\t\t  0x45\n#define\tVK_F\t\t\t\t\t  0x46\n#define\tVK_G\t\t\t\t\t  0x47\n#define\tVK_H\t\t\t\t\t  0x48\n#define\tVK_I\t\t\t\t\t  0x49\n#define\tVK_J\t\t\t\t\t  0x4A\n#define\tVK_K\t\t\t\t\t  0x4B\n#define\tVK_L\t\t\t\t\t  0x4C\n#define\tVK_M\t\t\t\t\t  0x4D\n#define\tVK_N\t\t\t\t\t  0x4E\n#define\tVK_O\t\t\t\t\t  0x4F\n#define\tVK_P\t\t\t\t\t  0x50\n#define\tVK_Q\t\t\t\t\t  0x51\n#define\tVK_R\t\t\t\t\t  0x52\n#define\tVK_S\t\t\t\t\t  0x53\n#define\tVK_T\t\t\t\t\t  0x54\n#define\tVK_U\t\t\t\t\t  0x55\n#define\tVK_V\t\t\t\t\t  0x56\n#define\tVK_W\t\t\t\t\t  0x57\n#define\tVK_X\t\t\t\t\t  0x58\n#define\tVK_Y\t\t\t\t\t  0x59\n#define\tVK_Z\t\t\t\t\t  0x5A\n#define\tVK_NONE_5B\t\t\t  0x5B\n#define\tVK_NONE_5C\t\t\t  0x5C\n#define\tVK_NONE_5D\t\t\t  0x5D\n#define\tVK_NONE_5E\t\t\t  0x5E\n#define\tVK_NONE_5F\t\t\t  0x5F\n#define\tVK_NUMPAD0          0x60\n#define\tVK_NUMPAD1          0x61\n#define\tVK_NUMPAD2          0x62\n#define\tVK_NUMPAD3          0x63\n#define\tVK_NUMPAD4          0x64\n#define\tVK_NUMPAD5          0x65\n#define\tVK_NUMPAD6          0x66\n#define\tVK_NUMPAD7          0x67\n#define\tVK_NUMPAD8          0x68\n#define\tVK_NUMPAD9          0x69\n#define\tVK_MULTIPLY         0x6A\n#define\tVK_ADD              0x6B\n#define\tVK_SEPARATOR        0x6C\n#define\tVK_SUBTRACT         0x6D\n#define\tVK_DECIMAL          0x6E\n#define\tVK_DIVIDE           0x6F\n#define\tVK_F1               0x70\n#define\tVK_F2               0x71\n#define\tVK_F3               0x72\n#define\tVK_F4               0x73\n#define\tVK_F5               0x74\n#define\tVK_F6               0x75\n#define\tVK_F7               0x76\n#define\tVK_F8               0x77\n#define\tVK_F9               0x78\n#define\tVK_F10              0x79\n#define\tVK_F11              0x7A\n#define\tVK_F12              0x7B\n#define\tVK_F13              0x7C\n#define\tVK_F14              0x7D\n#define\tVK_F15              0x7E\n#define\tVK_F16              0x7F\n#define\tVK_F17              0x80\n#define\tVK_F18              0x81\n#define\tVK_F19              0x82\n#define\tVK_F20              0x83\n#define\tVK_F21              0x84\n#define\tVK_F22              0x85\n#define\tVK_F23              0x86\n#define\tVK_F24              0x87\n#define\tVK_NONE_88          0x88\n#define\tVK_NONE_89          0x89\n#define\tVK_NONE_8A          0x8A\n#define\tVK_NONE_8B          0x8B\n#define\tVK_NONE_8C          0x8C\n#define\tVK_NONE_8D          0x8D\n#define\tVK_NONE_8E          0x8E\n#define\tVK_NONE_8F          0x8F\n#define\tVK_NUMLOCK          0x90\n#define\tVK_SCROLL           0x91\n#define\tVK_NONE_92\t\t\t  0x92\n#define\tVK_NONE_93\t\t\t  0x93\n#define\tVK_NONE_94\t\t\t  0x94\n#define\tVK_NONE_95\t\t\t  0x95\n#define\tVK_NONE_96\t\t\t  0x96\n#define\tVK_NONE_97\t\t\t  0x97\n#define\tVK_NONE_98\t\t\t  0x98\n#define\tVK_NONE_99\t\t\t  0x99\n#define\tVK_NONE_9A\t\t\t  0x9A\n#define\tVK_NONE_9B\t\t\t  0x9B\n#define\tVK_NONE_9C\t\t\t  0x9C\n#define\tVK_NONE_9D\t\t\t  0x9D\n#define\tVK_NONE_9E\t\t\t  0x9E\n#define\tVK_NONE_9F\t\t\t  0x9F\n#define\tVK_NONE_A0\t\t\t  0xA0\n#define\tVK_NONE_A1\t\t\t  0xA1\n#define\tVK_NONE_A2\t\t\t  0xA2\n#define\tVK_NONE_A3\t\t\t  0xA3\n#define\tVK_NONE_A4\t\t\t  0xA4\n#define\tVK_NONE_A5\t\t\t  0xA5\n#define\tVK_NONE_A6\t\t\t  0xA6\n#define\tVK_NONE_A7\t\t\t  0xA7\n#define\tVK_NONE_A8\t\t\t  0xA8\n#define\tVK_NONE_A9\t\t\t  0xA9\n#define\tVK_NONE_AA\t\t\t  0xAA\n#define\tVK_NONE_AB\t\t\t  0xAB\n#define\tVK_NONE_AC\t\t\t  0xAC\n#define\tVK_NONE_AD\t\t\t  0xAD\n#define\tVK_NONE_AE\t\t\t  0xAE\n#define\tVK_NONE_AF\t\t\t  0xAF\n#define\tVK_NONE_B0\t\t\t  0xB0\n#define\tVK_NONE_B1\t\t\t  0xB1\n#define\tVK_NONE_B2\t\t\t  0xB2\n#define\tVK_NONE_B3\t\t\t  0xB3\n#define\tVK_NONE_B4\t\t\t  0xB4\n#define\tVK_NONE_B5\t\t\t  0xB5\n#define\tVK_NONE_B6\t\t\t  0xB6\n#define\tVK_NONE_B7\t\t\t  0xB7\n#define\tVK_NONE_B8\t\t\t  0xB8\n#define\tVK_NONE_B9\t\t\t  0xB9\n#define\tVK_NONE_BA\t\t\t  0xBA\n#define\tVK_NONE_BB\t\t\t  0xBB\n#define\tVK_NONE_BC\t\t\t  0xBC\n#define\tVK_NONE_BD\t\t\t  0xBD\n#define\tVK_NONE_BE\t\t\t  0xBE\n#define\tVK_NONE_BF\t\t\t  0xBF\n#define\tVK_NONE_C0\t\t\t  0xC0\n#define\tVK_NONE_C1\t\t\t  0xC1\n#define\tVK_NONE_C2\t\t\t  0xC2\n#define\tVK_NONE_C3\t\t\t  0xC3\n#define\tVK_NONE_C4\t\t\t  0xC4\n#define\tVK_NONE_C5\t\t\t  0xC5\n#define\tVK_NONE_C6\t\t\t  0xC6\n#define\tVK_NONE_C7\t\t\t  0xC7\n#define\tVK_NONE_C8\t\t\t  0xC8\n#define\tVK_NONE_C9\t\t\t  0xC9\n#define\tVK_NONE_CA\t\t\t  0xCA\n#define\tVK_NONE_CB\t\t\t  0xCB\n#define\tVK_NONE_CC\t\t\t  0xCC\n#define\tVK_NONE_CD\t\t\t  0xCD\n#define\tVK_NONE_CE\t\t\t  0xCE\n#define\tVK_NONE_CF\t\t\t  0xCF\n#define\tVK_NONE_D0\t\t\t  0xD0\n#define\tVK_NONE_D1\t\t\t  0xD1\n#define\tVK_NONE_D2\t\t\t  0xD2\n#define\tVK_NONE_D3\t\t\t  0xD3\n#define\tVK_NONE_D4\t\t\t  0xD4\n#define\tVK_NONE_D5\t\t\t  0xD5\n#define\tVK_NONE_D6\t\t\t  0xD6\n#define\tVK_NONE_D7\t\t\t  0xD7\n#define\tVK_NONE_D8\t\t\t  0xD8\n#define\tVK_NONE_D9\t\t\t  0xD9\n#define\tVK_NONE_DA\t\t\t  0xDA\n#define\tVK_NONE_DB\t\t\t  0xDB\n#define\tVK_NONE_DC\t\t\t  0xDC\n#define\tVK_NONE_DD\t\t\t  0xDD\n#define\tVK_NONE_DE\t\t\t  0xDE\n#define\tVK_NONE_DF\t\t\t  0xDF\n#define\tVK_NONE_E0\t\t\t  0xE0\n#define\tVK_NONE_E1\t\t\t  0xE1\n#define\tVK_NONE_E2\t\t\t  0xE2\n#define\tVK_NONE_E3\t\t\t  0xE3\n#define\tVK_NONE_E4\t\t\t  0xE4\n#define\tVK_NONE_E5\t\t\t  0xE5\n#define\tVK_NONE_E6\t\t\t  0xE6\n#define\tVK_NONE_E7\t\t\t  0xE7\n#define\tVK_NONE_E8\t\t\t  0xE8\n#define\tVK_NONE_E9\t\t\t  0xE9\n#define\tVK_NONE_EA\t\t\t  0xEA\n#define\tVK_NONE_EB\t\t\t  0xEB\n#define\tVK_NONE_EC\t\t\t  0xEC\n#define\tVK_NONE_ED\t\t\t  0xED\n#define\tVK_NONE_EE\t\t\t  0xEE\n#define\tVK_NONE_EF\t\t\t  0xEF\n#define\tVK_NONE_F0\t\t\t  0xF0\n#define\tVK_NONE_F1\t\t\t  0xF1\n#define\tVK_NONE_F2\t\t\t  0xF2\n#define\tVK_NONE_F3\t\t\t  0xF3\n#define\tVK_NONE_F4\t\t\t  0xF4\n#define\tVK_NONE_F5\t\t\t  0xF5\n#define\tVK_NONE_F6\t\t\t  0xF6\n#define\tVK_NONE_F7\t\t\t  0xF7\n#define\tVK_NONE_F8\t\t\t  0xF8\n#define\tVK_NONE_F9\t\t\t  0xF9\n#define\tVK_NONE_FA\t\t\t  0xFA\n#define\tVK_NONE_FB\t\t\t  0xFB\n#define\tVK_NONE_FC\t\t\t  0xFC\n#define\tVK_NONE_FD\t\t\t  0xFD\n#define\tVK_NONE_FE\t\t\t  0xFE\n#define\tVK_NONE_FF\t\t\t  0xFF\n\n#define\tVK_UPLEFT\t\t\t  VK_HOME\n#define\tVK_UPRIGHT\t\t\t  VK_PRIOR\n#define\tVK_DOWNLEFT\t\t\t  VK_END\n#define\tVK_DOWNRIGHT\t\t  VK_NEXT\n#define\tVK_ALT\t\t\t\t  VK_MENU\n\nenum {\n\t//\n\t// Define all the KA types as variations of the VK types.  This is\n\t// so the KA functions will work properly under windows 95.\n\t//\n\tKA_NONE\t\t\t\t= 0,\n\tKA_MORE \t\t\t\t= 1,\n\tKA_SETBKGDCOL \t\t= 2,\n\tKA_SETFORECOL \t\t= 6,\n\tKA_FORMFEED \t\t= 12,\n\tKA_SPCTAB \t\t\t= 20,\n\tKA_SETX \t\t\t\t= 25,\n\tKA_SETY \t\t\t\t= 26,\n\n\tKA_SPACE\t\t\t\t= 32,\t\t\t\t\t/*   */\n\tKA_EXCLAMATION,\t\t\t\t\t\t\t/* ! */\n\tKA_DQUOTE,\t\t\t\t\t\t\t\t\t/* \" */\n\tKA_POUND,\t\t\t\t\t\t\t\t\t/* # */\n\tKA_DOLLAR,\t\t\t\t\t\t\t\t\t/* $ */\n\tKA_PERCENT,\t\t\t\t\t\t\t\t\t/* % */\n\tKA_AMPER,\t\t\t\t\t\t\t\t\t/* & */\n\tKA_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKA_LPAREN,\t\t\t\t\t\t\t\t\t/* ( */\n\tKA_RPAREN,\t\t\t\t\t\t\t\t\t/* ) */\n\tKA_ASTERISK,\t\t\t\t\t\t\t\t/* * */\n\tKA_PLUS,\t\t\t\t\t\t\t\t\t\t/* + */\n\tKA_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKA_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKA_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKA_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKA_0, KA_1, KA_2, KA_3, KA_4, KA_5, KA_6, KA_7, KA_8, KA_9,\n\tKA_COLON,\t\t\t\t\t\t\t\t\t/* : */\n\tKA_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKA_LESS_THAN,\t\t\t\t\t\t\t\t/* < */\n\tKA_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\tKA_GREATER_THAN,\t\t\t\t\t\t\t/* > */\n\tKA_QUESTION,\t\t\t\t\t\t\t\t/* ? */\n\n\tKA_AT,\t\t\t\t\t\t\t\t\t\t/* @ */\n\tKA_A,\t\t\t\t\t\t\t\t\t\t\t/* A */\n\tKA_B,\t\t\t\t\t\t\t\t\t\t\t/* B */\n\tKA_C,\t\t\t\t\t\t\t\t\t\t\t/* C */\n\tKA_D,\t\t\t\t\t\t\t\t\t\t\t/* D */\n\tKA_E,\t\t\t\t\t\t\t\t\t\t\t/* E */\n\tKA_F,\t\t\t\t\t\t\t\t\t\t\t/* F */\n\tKA_G,\t\t\t\t\t\t\t\t\t\t\t/* G */\n\tKA_H,\t\t\t\t\t\t\t\t\t\t\t/* H */\n\tKA_I,\t\t\t\t\t\t\t\t\t\t\t/* I */\n\tKA_J,\t\t\t\t\t\t\t\t\t\t\t/* J */\n\tKA_K,\t\t\t\t\t\t\t\t\t\t\t/* K */\n\tKA_L,\t\t\t\t\t\t\t\t\t\t\t/* L */\n\tKA_M,\t\t\t\t\t\t\t\t\t\t\t/* M */\n\tKA_N,\t\t\t\t\t\t\t\t\t\t\t/* N */\n\tKA_O,\t\t\t\t\t\t\t\t\t\t\t/* O */\n\n\tKA_P,\t\t\t\t\t\t\t\t\t\t\t/* P */\n\tKA_Q,\t\t\t\t\t\t\t\t\t\t\t/* Q */\n\tKA_R,\t\t\t\t\t\t\t\t\t\t\t/* R */\n\tKA_S,\t\t\t\t\t\t\t\t\t\t\t/* S */\n\tKA_T,\t\t\t\t\t\t\t\t\t\t\t/* T */\n\tKA_U,\t\t\t\t\t\t\t\t\t\t\t/* U */\n\tKA_V,\t\t\t\t\t\t\t\t\t\t\t/* V */\n\tKA_W,\t\t\t\t\t\t\t\t\t\t\t/* W */\n\tKA_X,\t\t\t\t\t\t\t\t\t\t\t/* X */\n\tKA_Y,\t\t\t\t\t\t\t\t\t\t\t/* Y */\n\tKA_Z,\t\t\t\t\t\t\t\t\t\t\t/* Z */\n\tKA_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKA_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\tKA_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKA_CARROT,\t\t\t\t\t\t\t\t\t/* ^ */\n\tKA_UNDERLINE,\t\t\t\t\t\t\t\t/* _ */\n\n\tKA_GRAVE,\t\t\t\t\t\t\t\t\t/* ` */\n\tKA_a,\t\t\t\t\t\t\t\t\t\t\t/* a */\n\tKA_b,\t\t\t\t\t\t\t\t\t\t\t/* b */\n\tKA_c,\t\t\t\t\t\t\t\t\t\t\t/* c */\n\tKA_d,\t\t\t\t\t\t\t\t\t\t\t/* d */\n\tKA_e,\t\t\t\t\t\t\t\t\t\t\t/* e */\n\tKA_f,\t\t\t\t\t\t\t\t\t\t\t/* f */\n\tKA_g,\t\t\t\t\t\t\t\t\t\t\t/* g */\n\tKA_h,\t\t\t\t\t\t\t\t\t\t\t/* h */\n\tKA_i,\t\t\t\t\t\t\t\t\t\t\t/* i */\n\tKA_j,\t\t\t\t\t\t\t\t\t\t\t/* j */\n\tKA_k,\t\t\t\t\t\t\t\t\t\t\t/* k */\n\tKA_l,\t\t\t\t\t\t\t\t\t\t\t/* l */\n\tKA_m,\t\t\t\t\t\t\t\t\t\t\t/* m */\n\tKA_n,\t\t\t\t\t\t\t\t\t\t\t/* n */\n\tKA_o,\t\t\t\t\t\t\t\t\t\t\t/* o */\n\n\tKA_p,\t\t\t\t\t\t\t\t\t\t\t/* p */\n\tKA_q,\t\t\t\t\t\t\t\t\t\t\t/* q */\n\tKA_r,\t\t\t\t\t\t\t\t\t\t\t/* r */\n\tKA_s,\t\t\t\t\t\t\t\t\t\t\t/* s */\n\tKA_t,\t\t\t\t\t\t\t\t\t\t\t/* t */\n\tKA_u,\t\t\t\t\t\t\t\t\t\t\t/* u */\n\tKA_v,\t\t\t\t\t\t\t\t\t\t\t/* v */\n\tKA_w,\t\t\t\t\t\t\t\t\t\t\t/* w */\n\tKA_x,\t\t\t\t\t\t\t\t\t\t\t/* x */\n\tKA_y,\t\t\t\t\t\t\t\t\t\t\t/* y */\n\tKA_z,\t\t\t\t\t\t\t\t\t\t\t/* z */\n\tKA_LBRACE,\t\t\t\t\t\t\t\t\t/* { */\n\tKA_BAR,\t\t\t\t\t\t\t\t\t\t/* | */\n\tKA_RBRACE,\t\t\t\t\t\t\t\t\t/* ] */\n\tKA_TILDA,\t\t\t\t\t\t\t\t\t/* ~ */\n\n\tKA_ESC \t\t\t\t= VK_ESCAPE | WWKEY_VK_BIT,\n\tKA_EXTEND \t\t\t= VK_ESCAPE | WWKEY_VK_BIT,\n\tKA_RETURN \t\t\t= VK_RETURN | WWKEY_VK_BIT,\n\tKA_BACKSPACE \t\t= VK_BACK | WWKEY_VK_BIT,\n\tKA_TAB \t\t\t\t= VK_TAB  | WWKEY_VK_BIT,\n\tKA_DELETE\t\t\t= VK_DELETE | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* <DELETE> */\n\tKA_INSERT\t\t\t= VK_INSERT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* <INSERT> */\n\tKA_PGDN\t\t\t\t= VK_NEXT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <PAGE DOWN> */\n\tKA_DOWNRIGHT \t\t= VK_NEXT | WWKEY_VK_BIT,\n\tKA_DOWN\t\t\t\t= VK_DOWN | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <DOWN ARROW> */\n\tKA_END\t\t\t\t= VK_END | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <END> */\n\tKA_DOWNLEFT \t\t= VK_END | WWKEY_VK_BIT,\n\tKA_RIGHT\t\t\t\t= VK_RIGHT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* <RIGHT ARROW> */\n\tKA_KEYPAD5\t\t\t= VK_SELECT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* NUMERIC KEY PAD <5> */\n\tKA_LEFT\t\t\t\t= VK_LEFT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ARROW> */\n\tKA_PGUP\t\t\t\t= VK_PRIOR | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <PAGE UP> */\n\tKA_UPRIGHT \t\t\t= VK_PRIOR | WWKEY_VK_BIT,\n\tKA_UP\t\t\t\t\t= VK_UP | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <UP ARROW> */\n\tKA_HOME\t\t\t\t= VK_HOME | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* <HOME> */\n\tKA_UPLEFT \t\t\t= VK_HOME | WWKEY_VK_BIT,\n\tKA_F12\t\t\t\t= VK_F12 | WWKEY_VK_BIT,\n\tKA_F11\t\t\t\t= VK_F11 | WWKEY_VK_BIT,\n\tKA_F10\t\t\t\t= VK_F10 | WWKEY_VK_BIT,\n\tKA_F9 \t\t\t\t= VK_F9 | WWKEY_VK_BIT,\n\tKA_F8\t\t\t\t\t= VK_F8 | WWKEY_VK_BIT,\n\tKA_F7\t\t\t\t\t= VK_F7 | WWKEY_VK_BIT,\n\tKA_F6\t\t\t\t\t= VK_F6 | WWKEY_VK_BIT,\n\tKA_F5\t\t\t\t\t= VK_F5 | WWKEY_VK_BIT,\n\tKA_F4\t\t\t\t\t= VK_F4 | WWKEY_VK_BIT,\n\tKA_F3\t\t\t\t\t= VK_F3 | WWKEY_VK_BIT,\n\tKA_F2\t\t\t\t\t= VK_F2 | WWKEY_VK_BIT,\n\tKA_F1\t\t\t\t\t= VK_F1 | WWKEY_VK_BIT,\n\tKA_LMOUSE \t \t\t= VK_LBUTTON | WWKEY_VK_BIT,\n\tKA_RMOUSE \t \t\t= VK_RBUTTON | WWKEY_VK_BIT,\n\n\tKA_SHIFT_BIT \t\t= WWKEY_SHIFT_BIT,\n\tKA_CTRL_BIT  \t\t= WWKEY_CTRL_BIT,\n\tKA_ALT_BIT   \t\t= WWKEY_ALT_BIT,\n\tKA_RLSE_BIT  \t\t= WWKEY_RLS_BIT,\n\n\t//\n\t// Define all the KN types as variations of the KA types.  This is\n\t// so the KN functions will work properly under windows 95.\n\t//\n\tKN_NONE\t\t\t\t= 0,\n\tKN_GRAVE \t\t\t= KA_GRAVE,\n\tKN_1 \t\t\t\t\t= KA_1,\n\tKN_2 \t\t\t\t\t= KA_2,\n\tKN_3 \t\t\t\t\t= KA_3,\n\tKN_4 \t\t\t\t\t= KA_4,\n\tKN_5 \t\t\t\t\t= KA_5,\n\tKN_6 \t\t\t\t\t= KA_6,\n\tKN_7 \t\t\t\t\t= KA_7,\n\tKN_8 \t\t\t\t\t= KA_8,\n\tKN_9 \t\t\t\t\t= KA_9,\n\tKN_0 \t\t\t\t\t= KA_0,\n\tKN_MINUS \t\t\t= KA_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKN_EQUAL \t\t\t= KA_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\n\tKN_BACKSPACE\t\t= KA_BACKSPACE,\n\n\tKN_TAB\t\t\t\t= KA_TAB,\t\t\t\t\t\t\t\t\t\t/* <TAB> */\n\tKN_Q \t\t\t\t\t= KA_q,\n\tKN_W \t\t\t\t\t= KA_w,\n\tKN_E \t\t\t\t\t= KA_e,\n\tKN_R \t\t\t\t\t= KA_r,\n\tKN_T \t\t\t\t\t= KA_t,\n\tKN_Y \t\t\t\t\t= KA_y,\n\tKN_U \t\t\t\t\t= KA_u,\n\tKN_I \t\t\t\t\t= KA_i,\n\tKN_O \t\t\t\t\t= KA_o,\n\tKN_P \t\t\t\t\t= KA_p,\n\tKN_LBRACKET\t\t\t= KA_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKN_RBRACKET\t\t\t= KA_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKN_BACKSLASH\t\t= KA_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\n\n\tKN_A \t\t\t\t\t= KA_a,\n\tKN_S \t\t\t\t\t= KA_s,\n\tKN_D \t\t\t\t\t= KA_d,\n\tKN_F \t\t\t\t\t= KA_f,\n\tKN_G \t\t\t\t\t= KA_g,\n\tKN_H \t\t\t\t\t= KA_h,\n\tKN_J \t\t\t\t\t= KA_j,\n\tKN_K \t\t\t\t\t= KA_k,\n\tKN_L \t\t\t\t\t= KA_l,\n\tKN_SEMICOLON \t\t= KA_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKN_SQUOTE \t\t\t= KA_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKN_BACKSLASH2 \t\t= KA_BACKSLASH,\n\tKN_RETURN \t\t\t= KA_RETURN,\n\tKN_Z \t\t\t\t\t= KA_z,\n\tKN_X \t\t\t\t\t= KA_x,\n\tKN_C \t\t\t\t\t= KA_c,\n\tKN_V \t\t\t\t\t= KA_v,\n\tKN_B \t\t\t\t\t= KA_b,\n\tKN_N \t\t\t\t\t= KA_n,\n\tKN_M \t\t\t\t\t= KA_m,\n\tKN_COMMA \t\t\t= KA_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKN_PERIOD \t\t\t= KA_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKN_SLASH \t\t\t= KA_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\tKN_SPACE \t\t\t= KA_SPACE,\n\tKN_LMOUSE\t\t\t= KA_LMOUSE,\n\tKN_RMOUSE\t\t\t= KA_RMOUSE,\n\n\tKN_HOME\t\t\t\t= KA_HOME,\t\t\t\t\t\t\t\t\t\t/* num key pad 7 */\n\tKN_UPLEFT\t\t\t= KA_UPLEFT,\n\tKN_LEFT\t\t\t\t= KA_LEFT,\t\t\t\t\t\t\t\t\t\t/* num key pad 4 */\n\tKN_END\t\t\t\t= KA_END,\t\t\t\t\t\t\t\t\t\t/* num key pad 1 */\n\tKN_DOWNLEFT\t\t\t= KA_DOWNLEFT,\n\n\tKN_KEYPAD_SLASH\t= KA_SLASH,\t\t\t\t\t\t\t\t\t\t\t\t/* num key pad / */\n\tKN_UP\t\t\t\t\t= KA_UP,\t\t\t\t\t\t\t\t\t\t\t/* num key pad 8 */\n\tKN_CENTER\t\t\t= KA_KEYPAD5,\t\t\t\t\t\t\t\t\t/* num key pad 5 */\n\tKN_DOWN\t\t\t\t= KA_DOWN,\t\t\t\t\t\t\t\t\t\t/* num key pad 2 */\n\tKN_INSERT\t\t\t= KA_INSERT,\t\t\t\t\t\t\t\t\t/* num key pad 0 */\n\tKN_KEYPAD_ASTERISK= KA_ASTERISK,\t\t\t\t\t\t\t\t\t/* num key pad * */\n\tKN_PGUP\t\t\t\t= KA_PGUP,\t\t\t\t\t\t\t\t\t\t/* num key pad 9 */\n\tKN_UPRIGHT\t\t\t= KA_UPRIGHT,\n\tKN_RIGHT\t\t\t\t= KA_RIGHT,\t\t\t\t\t\t\t\t\t/* num key pad 6 */\n\tKN_PGDN\t\t\t\t= KA_PGDN,\t\t\t\t\t\t\t\t\t\t/* num key pad 3 */\n\tKN_DOWNRIGHT\t\t= KA_DOWNRIGHT,\n\tKN_DELETE\t\t\t= KA_DELETE,\t\t\t\t\t\t\t\t\t/* num key pad . */\n\n\tKN_KEYPAD_MINUS\t= KA_MINUS,\t\t\t\t\t\t\t/* num key pad - */\n\tKN_KEYPAD_PLUS\t\t= KA_PLUS,\t\t\t\t\t\t\t/* num key pad + */\n\n\n\tKN_KEYPAD_RETURN\t= KA_RETURN,\t\t\t\t\t\t\t/* num key pad <ENTER> */\n\n\tKN_ESC\t\t\t\t= KA_ESC,\n\tKN_F1\t\t\t\t\t= KA_F1,\n\tKN_F2\t\t\t\t\t= KA_F2,\n\tKN_F3\t\t\t\t\t= KA_F3,\n\tKN_F4\t\t\t\t\t= KA_F4,\n\tKN_F5\t\t\t\t\t= KA_F5,\n\tKN_F6\t\t\t\t\t= KA_F6,\n\tKN_F7\t\t\t\t\t= KA_F7,\n\tKN_F8\t\t\t\t\t= KA_F8,\n\tKN_F9\t\t\t\t\t= KA_F9,\n\tKN_F10\t\t\t\t= KA_F10,\n\tKN_F11\t\t\t\t= KA_F11,\n\tKN_F12\t\t\t\t= KA_F12,\n\n\tKN_PRNTSCRN\t\t\t= VK_PRINT | WWKEY_VK_BIT,\n\tKN_CAPSLOCK\t\t\t= VK_CAPITAL | WWKEY_VK_BIT,\n\tKN_SCROLLLOCK\t\t= VK_SCROLL | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t/* <SCROLL LOCK> */\n\tKN_PAUSE\t\t\t\t= VK_PAUSE | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* <PAUSE> */\n\tKN_LSHIFT\t\t\t= VK_SHIFT | WWKEY_VK_BIT,\n\tKN_RSHIFT\t\t\t= VK_SHIFT | WWKEY_VK_BIT,\n\tKN_LCTRL\t\t\t\t= VK_CONTROL | WWKEY_VK_BIT,\n\tKN_RCTRL\t\t\t\t= VK_CONTROL | WWKEY_VK_BIT,\n\tKN_LALT\t\t\t\t= VK_MENU | WWKEY_VK_BIT,\n\tKN_RALT\t\t\t\t= VK_MENU | WWKEY_VK_BIT,\n\tKN_E_INSERT\t\t\t= VK_INSERT | WWKEY_VK_BIT,\n\tKN_E_DELETE \t\t= VK_DELETE | WWKEY_VK_BIT,\n\tKN_E_LEFT\t\t\t= VK_LEFT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <LEFT ARROW> */\n\tKN_E_HOME\t\t\t= VK_HOME | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <HOME> */\n\tKN_E_END\t\t\t\t= VK_END | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <END> */\n\tKN_E_UP\t\t\t\t= VK_UP | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t\t/* extended <UP ARROW> */\n\tKN_E_DOWN\t\t\t= VK_DOWN | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <DOWN ARROW> */\n\tKN_E_PGUP\t\t\t= VK_PRIOR | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <PAGE UP> */\n\tKN_E_PGDN   \t\t= VK_NEXT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <PAGE DOWN> */\n\tKN_E_RIGHT\t\t\t= VK_RIGHT | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* extended <RIGHT ARROW> */\n\tKN_NUMLOCK\t\t\t= VK_NUMLOCK | WWKEY_VK_BIT,\t\t\t\t\t\t\t\t\t/* <NUM LOCK> */\n\n\tKN_SHIFT_BIT \t\t= WWKEY_SHIFT_BIT,\n\tKN_CTRL_BIT  \t\t= WWKEY_CTRL_BIT,\n\tKN_ALT_BIT   \t\t= WWKEY_ALT_BIT,\n\tKN_RLSE_BIT  \t\t= WWKEY_RLS_BIT,\n\tKN_BUTTON    \t\t= WWKEY_BTN_BIT,\n};\n\n\nextern WWKeyboardClass *_Kbd;\n\n\n/*\n** The following routines provide some compatability with the old westwood\n** library.\n*/\nint Check_Key(void);\nint Check_Key_Num(void);\nint Get_Key_Num(void);\nint Get_Key(void);\nint KN_To_KA(int key);\nvoid Clear_KeyBuffer(void);\nint Key_Down(int key);\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/KEYBOARD.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : KEYBOARD.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 12, 1994                            *\n;*                                                                         *\n;*                  Last Update : July 12, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Contains all the defines used by the keyboard interrupt for assembly    *\n;*   includes.                                                             *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nTRUE\t\tEQU\t1\t\t\t; numerical true\nFALSE\t\tEQU\t0\t\t\t; numerical false\nDEBUG\t\tEQU\t1\n\nMAX_X_PIXEL\t\tEQU\t319\nMAX_Y_PIXEL\t\tEQU\t199\n\n\nKN_RESERVED1\t\tEQU\t14\nKN_RESERVED2\t\tEQU\t45\nKN_RESERVED3\t\tEQU\t56\n\n\n; these two are reserved for AMIGA open and close.\nKN_LCOMM\t\tEQU\t59\nKN_RCOMM\t\tEQU\t63\n\nKN_LMOUSE\t\tEQU\t65\nKN_RMOUSE\t\tEQU\t66\nKN_JBUTTON1\t\tEQU\t67\nKN_JBUTTON2\t\tEQU\t68\nKN_J_UP\t\t\tEQU\t69\nKN_J_RIGHT\t\tEQU\t70\nKN_J_DOWN\t\tEQU\t71\nKN_J_LEFT\t\tEQU\t72\n\nKN_LEFT\t\t\tEQU\t92\nKN_UPLEFT\t\tEQU\t91\nKN_UP\t\t\tEQU\t96\nKN_UPRIGHT\t\tEQU\t101\nKN_RIGHT\t\tEQU\t102\nKN_DOWNRIGHT\t\tEQU\t103\nKN_DOWN\t\t\tEQU\t98\nKN_DOWNLEFT\t\tEQU\t93\nKN_CENTER\t\tEQU\t97\n\nKN_INSERT\t\tEQU\t99\nKN_DELETE\t\tEQU\t104\n\nKN_RETURN\t\tEQU\t43\nKN_SPACE\t\tEQU\t61\nKN_KEYPAD_RETURN\tEQU\t108\n\n\n; these two are reserved for AMIGA K left and right paren\nKN_KLPAREN\t\tEQU\t87\nKN_KRPAREN\t\tEQU\t88\n\n\nKN_NUMLOCK\t\tEQU\t90\n\nKN_SCROLLOCK\t\tEQU\t125\t\t; key ignored by the logging system\n\nKN_MOUSE_MOVE\tEQU\t45\t; Indicate a mouse move (for playback of logged data)\n\n; ----------------------------------------------------------------\n; flags used in Keyflags to customize keystroke interrupt.\n\nREPEATON\tEQU\t0001H\t; 1:all makes into buffer, 0:only 1st make\nTRACKEXT\tEQU\t0002H\t; 1:Home != keypad Home, 0:Home=keypad Home\nFILTERONLY\tEQU\t0004H\t; 1:Normal BIOS operation with filter\nCTRLSON\t\tEQU\t0008H\t; 1:pass scroll lock sequence into BIOS\nCTRLALTTURBO\tEQU\t0010H\t; 1:Allow turbo up and down in application\nCTRLCON\t\tEQU\t0020H\t; 1:pass stop code to BIOS\nSCROLLLOCKON\tEQU\t0040H\t; 1:pass scroll lock key into BIOS\nPAUSEON\t\tEQU\t0080H\t; 1:pass the pause key and seq to BIOS\nBREAKON\t\tEQU\t0100H\t; 1:pass the ctrl break seq to BIOS\nNONUMLOCK\tEQU\t0200H\t; 1:do NOT remap keypad to numbers\nTASKSWITCHABLE\tEQU\t0400H\t; 1:allows task switching keys thru ALT-TAB,\n\t\t\t\t;   ALT-ESC,CTRL-ESC\nPASSBREAKS\tEQU\t0800H\t; 1:Pass all break codes to keyboard buffer.\nKEYMOUSE\tEQU\t1000H\t; 1:Numeric keypad moves mouse\nSIMLBUTTON\tEQU\t2000H\t; 1:have space and enter keys simulate Left\n\t\t\t\t;   mouse button when KEYMOUSE is set\n\n\nSHIFTPRESS\tEQU\t001H\t; bit 0 for shift key pressed\nCTRLPRESS\tEQU\t002H\t; bit 1 for ctrl key pressed\nALTPRESS\tEQU\t004H\t; bit 2 for alt key pressed\nKEYRELEASE\tEQU\t008H\t; bit 3 for key released\nNOTKEYRELEASE\tEQU\t0F7H\t; not of key released\n\nCAPSLOCK\tEQU\t00001H\t; bit 0 for caps locked\nNUMLOCK\tEQU\t00002H\t; bit 1 for num locked\n\n\n\nCLEARISR\tEQU\t020H\t; value to clear In Service Register\nDOS\t\tEQU \t021H\nINTCHIP0\tEQU\t020H\t; 8259 interrupt chip controller 0\nKEYCTRL\t\tEQU\t061H\t; control bits for KB sense data\nKEYDATA\t\tEQU\t060H\t; keyboard scan code port\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/KEYIPROT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : KEYINTR.ASM                              *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   KeyNum_Translate -- Translates the given keynum to ???                *\n;*   Install_Interrupt -- Installs the keyboard interrupt                  *\n;*   Stuff_Key_Word -- Stuffs a word of data into keyboard buffer          *\n;*   Stuff_Key_Num -- Stuffs a key num code into the circular buffer       *\n;*   Remove_Interrupt -- Removes the keyboard interrupt and restores the chai*\n;*   Keystroke_Interrupt -- Handles input that comes from the keyboard     *\n;*   Break_Interrupt -- Handles the break key interrupt                    *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tKeyboard driver -- 8086 Assembly portion;\t\t\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   *\n;***************************************************************************\n\n;---------------------------------------------------------------------------\n; Set the assembly directives\n;---------------------------------------------------------------------------\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386N\t\t\t\t; use 386 real mode instructions\nMODEL TINY\t\t\t; code must be tiny so it fits\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keyboard.inc\"\n\nCODESEG\n\n\nSoundOn\t\tDW\t1\t; toggled by alt S\nMusicOn\t\tDW\t1\t; toggled by alt M\nKeyFlags\tDW\tREPEATON+CTRLALTTURBO\t; all but repeat for now\n\n\nBreak\t\tDW\t0\n\nKeyMouseMove\tDB\t-1,0,1\n\t\tDB\t-16,0,16\n\nScreenEdge\tDW\t320/2,0\t\t; North\n\t\tDW\t319,0\t\t; North-East\n\t\tDW\t319,138/2\t; East\n\t\tDW\t319,137\t\t; South-East\n\t\tDW\t320/2,137\t; South\n\t\tDW\t0,137\t\t; South-West\n\t\tDW\t0,138/2\t\t; West\n\t\tDW\t0,0\t\t; North-West\n\t\tDW\t320/2,138/2\t; Center\n\n\nBits\t\tDB\t01H,02H,04H,08H,10H,20H,40H,80H\n\nCondPassKey\tDW\t0220H, 0320H, 060CH, 070DH, 066AH\n\t\tDW\t0669H, 0230H, 0330H, 007DH, 017DH\n\t\tDW\t025AH, 035AH, 0200H, 0410H, 046EH\n\t\tDW\t026EH, 007CH\n\nCondPassCond\tDW\tCTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO\n\t\tDW\tCTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON\n\t\tDW\tPAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE\n\t\tDW\tTASKSWITCHABLE, BREAKON\n\nEscRoutine\tDD\t0\t; vector to execute on esc key press (0=none)\n\n; Extended raw keycodes to be converted to Westwood keycodes.\nExtCodes\tDB\t038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H\n\t\tDB\t051H,04DH,035H,01CH,037H\n\t\tDB\t046H\n; The matching Westwood keycodes.\nExtNums\t\tDB\t62,  64,  75,  76,  79,  80,  81,  83,  84,  85\n\t\tDB\t86,  89,  95, 108, 124,  0\n; If extended mapping is disabled, then these codes really are...\nExtRemap\tDB\t60,  58,  99, 104,  92,  91,  93,  96,  98, 101\n\t\tDB\t103, 102, 55,  43, 124,  0\nExtRemapEnd\tDB\t0\n\nExtKeyboard\tDB\t0\t; flag for 101/102-key keyboard\n\n\nKeyBuffer\tDW\t128 DUP(0) ; set to empty\nKeyBufferHead\tDW\t0\t; set to first entry\nKeyBufferTail\tDW\t0\t; set to head for empty buffer\nKeyLock\t\tDW\t0\t; num and caps lock bits\nKeyNums\t\tDB\t127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016\n\t\tDB\t017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032\n\t\tDB\t033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049\n\t\tDB\t050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116\n\t\tDB\t117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093\n\t\tDB\t098,103,099,104,127,127,127,122,123\n\nKeysCapsLock\tDB\t0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0\nKeysNumLock\tDB\t0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0\nKeysUpDown\tDB\t16 DUP(0) ; set to all keys up\nKeyStream\tDB\t16 DUP(0) ; set to all keys up\nPassCount\tDW\t0\nKeyStreamIndex\tDW\t0\nLastKeyE0\tDB\t0\nLastKeyE1\tDB\t0\n\n;\n; Westwood key number values of keys to pass through\n;\n;\t\t\tCAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT,\n;\t\t\tRIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN\nPassAlways\tDB\t30, 44, 57, 58, 60, 62, 64, 90, 128, 128\nPassAlwaysEnd\tDB\t128\t\t; invalid code to END PassAlways\nCtrlFlags\tDB\t0\n\nBuffer\t\tDW\t?\nTime\t\tDW\t?\n\nADJUST\t= 1\t\t\t; do not modify DRD\n\nXYAdjust\tDB\t-ADJUST, -ADJUST\t; 91 -> upleft\n\t\tDB\t-ADJUST,  0\t\t; 92 -> left\n\t\tDB\t-ADJUST,  ADJUST\t; 93 -> downleft\n\t\tDB\t 0,  0\t\t\t; 94 illegal\n\t\tDB\t 0,  0\t\t\t; 95 illegal\n\t\tDB\t 0, -ADJUST\t\t; 96 -> up\n\t\tDB\t 0,  0\t\t\t; 97 illegal (center)\n\t\tDB\t 0,  ADJUST\t\t; 98 -> down\n\t\tDB\t 0,  0\t\t\t; 99 illegal\n\t\tDB\t 0,  0\t\t\t; 100 illegal\n\t\tDB\t ADJUST, -ADJUST\t; 101 -> upright\n\t\tDB\t ADJUST,  0\t\t; 102 -> right\n\t\tDB\t ADJUST,  ADJUST\t; 103 -> downright\nEdgeConv\tDW\t8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7\n\nMouseUpdate\t\tDW\t0\nMouseX\t\t\tDW\t0\nLocalMouseX\t\tDW\t0\nMouseY\t\t\tDW\t0\nLocalMouseY\t\tDW\t0\nButton\t\t\tDW\t0\nIsExtKey\t\tDB\t0\nExtIndex\t\tDW\t0\n\nOldRMI\t\t\tDD\t0\t; The origianl RM interrupt seg:off.\nOldPMIOffset\t\tDD\t0\t; The origianl PM interrupt offset\t\t\nOldPMISelector\t\tDD\t0\t; The original PM interrupt segment.\n\nCodeOffset\t\tDW\tRM_Keystroke_Interrupt\t; Offset of the code in the RM stuff.\nCallRMIntOffset\t\tDW\tCall_Interrupt_Chain\t\t; Offset of function to call DOS timer interrupt.\nCallRMIntAddr\t\tDD\t0\t; PM address of CallRealIntOffset for speed.\n\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Translates the given keynum to ???                  *\n;*                                                                         *\n;* INPUT:\tUWORD the keynum to translate\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated keynum                                 *\n;*                                                                         *\n;* PROTO:\tUWORD KeyNum_Translate(UWORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tKeyNum_Translate:FAR\n\tPROC\tKeyNum_Translate C FAR \n\tUSES\tcx,di,es,ds\n\tARG\tkeycode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\tmov\tes,ax\t\t\t\t; set es up for scansb\n\n\tmov\tax,[keycode]\n\ttest\t[KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\tmov\tcx,ExtRemap-ExtNums\n\tmov\tdi,OFFSET ExtNums\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tdi,OFFSET ExtRemapEnd\n\tdec\tdi\n\tsub\tdi,cx\n\tmov\tal,[es:di]\n??fini:\n\tret\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(WORD code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_WORD:FAR\n\tPROC\tStuff_Key_WORD C FAR \n\tUSES\tsi,bx,ds\n\tARG\tcode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\tax,[KeyBufferTail]\n\tmov\tsi,ax\n\tadd\tax,2\n\tand\tax,0FFh\t\t\t\t; New KeyBufferTail value.\n\tcmp\t[KeyBufferHead],ax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[KeyBuffer+si],bx\t\t; Record the keystroke.\n\tmov\t[KeyBufferTail],ax\n\txor\tax,ax\n\tret\n\n??noroom:\n\tmov\tax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(WORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_Num:FAR\n\tPROC\tStuff_Key_Num C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds\n\tARG\tkeycode:WORD\n\tLOCAL\ttail:WORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n\tpushf\n\tcli\t\t\t\t; disable interrupts\n\n\t; Abort key recognition if in record mode and unable\n\t; to output key due to simultaneous DOS operation.\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\tax,[MouseX]\n\tmov\t[LocalMouseX],ax\n\tmov\tax,[MouseY]\n\tmov\t[LocalMouseY],ax\n\n??cando:\n\tmov\tax,[keycode]\t\t; get the code\n\tor\tax,ax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tbx,1\t\t\t; double for WORD index\n\tadd\tbx,OFFSET XYAdjust\n\tmov\tax,[bx]\t\t\t; get x,y add value\n\n\tmov\tbl,ah\n\tcbw\n\txchg\tax,bx\n\tcbw\n\txchg\tax,bx\t\t\t; AX = mouse x delta, BX = mouse y delta\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tdx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tdx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tbx,dx\t\t\t; add speed for y index\n\tmov\tbl,[KeyMouseMove+bx] \t; get speed for y delta\n\txchg\tax,bx\t\t\t; swap with ax to extend sign\n\tcbw\n\txchg\tax,bx\n\txchg\tbx,dx\t\t\t; save mouse y delta\n\tadd\tbx,ax\t\t\t; add speed for x index\n\tmov\tal,[KeyMouseMove+bx]\t; get speed for x delta\n\tcbw\n\txchg\tbx,dx\t\t\t; restore mouse y delta\n\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tbx,011b\t\t\t; Y = 1, 0, 3\n\tand\tax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tbx,011b\t\t\t; Y = 3, 0, 1\n\tand\tax,011b\t\t\t; X = 3, 0, 1\n\tshl\tbx,1\n\tshl\tbx,1\n\tor\tbx,ax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tbx,1\n\tmov\tbx,[EdgeConv+bx]\n\tshl\tbx,1\n\tshl\tbx,1\n\tmov\tax,[ScreenEdge+bx]\t; New absolute X\n\tmov\tbx,[ScreenEdge+bx+2] ; New absolute Y\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\tax,ax\n\tmov\t[LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tbx,bx\n\tmov\t[LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\tmov\t[MouseX],ax\n\tmov\t[MouseY],bx\n\tcmp\t[MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n; PWG: ARRGGGHHHH!\n;\tcall\tLow_Hide_Mouse\n;\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\tax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],ax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tsi,[KeyBufferTail]\n\tmov\t[tail],si\t\t; Safety record.\n\tmov\tdi,[KeyBufferHead]\n\n\t; Record the base keycode (if there is room).\n\tpush\tax\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\tax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tpush\t[LocalMouseX]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tpush\t[LocalMouseY]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tbx,0101h\t\t; Bit control tools.\n\tmov\tax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tmov\tcl,3\n\tshr\tdi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[KeysUpDown+di]\n\tje\tshort ??notalready\n\ttest\t[KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\t[KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[KeysUpDown+di],bh\t; Force key bit to zero.\n\tor\t[KeysUpDown+di],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\tax,1\n\tjmp short ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\tax,[tail]\n\tmov\t[KeyBufferTail],ax\n\txor\tax,ax\t\t\t; Signal an error.\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tStuff_Key_Num\n;***********************************************************\n\n\n\n;***************************************************************************\n;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard       *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Keystroke_Interrupt\n\tGLOBAL\tC Keystroke_Interrupt:FAR\n\tPROC\tKeystroke_Interrupt C FAR \n\nIF 0\n\tpush\tax\n\tinc\tax\n\tpop\tax\n\tiret\n\nELSE\n\tpush\tax\n\tpush\tbx\n\tpush\tcx\n\tpush\tdi\n\tpush\tds\n\tpush\tdx\n\tpush\tes\n\tpush\tsi\n\tcld\n\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tds,ax\n\tmov\tdx,[KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\tmov\tax,040H\t\t\t; BIOS segment\n\tmov\tes,ax\t\t\t; put in es\n\ttest\t[BYTE PTR es:017H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR es:017H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR es:096H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tes,ax\n\n\tcld\t\t\t\t; clear direction flag for strings\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tbx,0101H\t\t; set key to a make by default\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\n\t;\n\t; New CODE to montior key stream\n\t;\n\tmov\tbx,[KeyStreamIndex]\n\tmov\t[KeyStream+bx],al\n\tinc\tbx\n\tand\tbx,15\n\tmov\t[KeyStreamIndex],bx\n\tmov\tbx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[LastKeyE1]\t\t; yes, dec the count\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[IsExtKey],TRUE\t; it is an extended key\n\tmov\tdi,OFFSET ExtCodes\t; get offset of extended codes table\n\tmov\tcx,(ExtNums-ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\tmov\tal,[(ExtNums - ExtCodes) - 1 + di] ; get the match\n\tmov\t[IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tdi,ax\t\t\t; use code as an index\n\tand\tdi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[KeyNums+di]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[KeysUpDown+8],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[KeysUpDown+7],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[KeysUpDown + 7],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\tax\n\tcall\tKeyNum_Translate\n\tadd\tsp,2\n\n;------\tSet the shift bit if necessary.\n\ttest\t[KeysUpDown+5],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[KeysUpDown+7],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tshr\tdi,1\n\tshr\tdi,1\n\tshr\tdi,1\n\tmov\tbx,ax\n\tand\tbx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[Bits+bx]\t\t; get the bit to test\n\ttest\t[KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[KeysCapsLock+di]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[KeysNumLock+di]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\n\t\t\t\t\t; keyboard buffer.\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\tax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\tax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\tax,0230h\n\tje\tshort ??breaker\n\tcmp\tax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n\tcmp\tax,0420H\t\t; is this an alt s\n\tjne\tshort ??checkmusic\t; toggle the Sound variable\n\tpush\tax\n\tmov\tax,[SoundOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??checkmusic:\n\tcmp\tax,0434H\t\t; is this an alt m\n\tjne\tshort ??esc\t\t; toggle the Music variable\n\tpush\tax\n\tmov\tax,[MusicOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??esc:\n\n\tpush\tax\n\tcall\tStuff_Key_Num\n\tpop\tax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\tax\n\tcall\t[EscRoutine]\n\tpop\tax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tdi,OFFSET PassAlways\t; get offset to table\n\tmov\tcx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1\n\trepne\tscasb\t\t\t; look for a match\n\tor\tcx,cx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n\n\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tdi,OFFSET CondPassKey\t; get offset to cond key table\n\tmov\tcx,(CondPassCond-CondPassKey) ; get number of entries\n\tshr\tcx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(CondPassCond - CondPassKey) - 2 + di]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tdx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n;***********************************************************\n\tpushf\n;\tpush\tdi\n;\tpush\tes\n\t\n\tmov\tax,0B000h\n\tmov\tes,ax\n\tinc\t[BYTE PTR es:0]\n\n;\tpop\tes\n;\tpop\tdi\n\tpopf\n;***********************************************************\n\n??passcode:\n\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tinc\t[cs:PassCount]\n\tjmp\t[cs:OldRMI]\n\n??absorbcode:\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tax,040h\t\t\t\t; BIOS paragraph is always @ 040h\n\tmov\tes,ax\t\t\t\t; put in es as BIOS paragraph\n\tmov\tal,[es:96h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[es:96h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tiret\t\nENDIF\n\n\tENDP\tKeystroke_Interrupt\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles the break key interrupt                      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Break_Interrupt:FAR\n\tPROC\tBreak_Interrupt C FAR\n\n\tiret\t\n\n\tENDP\tBreak_Interrupt\n\n;**************************************************************************\n;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nCall_Interrupt_Chain:\nIF 0\n\tpushf\n\tpush\tax\n\tpush\tdi\n\tpush\tes\n\n\tmov\tax,0B000h\t\t; ES:DI = Mono RAM address.\n\tmov\tes,ax\n\t\t\n\tmov\tal,'A'\n\tmov\tah,2\n\tand\tdi,63\n\n\tstosw\n\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\tmov\tal,CLEARISR\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t; 8259 interrupt chip controller 0\n\n\n\tpop\tes\n\tpop\tdi\n\tpop\tax\n\tpopf\nENDIF\n\tpushf\n\tcall\tKeystroke_Interrupt ;[OldRMI]\n\tretf\n\nSTACK\t   ; Don't really need this\n\n;***********************************************************\nEND\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/KEYIREAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*\t\t\t\t  (Mouse Routines)\n;*                                                                         *\n;*                    File Name : KEYIREAL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Philip W. Gorrow                         *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;* This file sort of breaks the standard of keeping all of the keyboard    *\n;* and mouse routines isolated.  This is done because the mouse and\t   *\n;* the keyboard share data, and the best way to do this is to put\t   *\n;* them in the same segment.  This should probably be split into several   *\n;* include files to help make the code clearer once it is finally put\t   *\n;* together.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   KeyNum_Translate -- Translates extended keynums to normal keynums\t   *\n;*   Stuff_Key_Word -- Stuffs a word of data into keyboard buffer          *\n;*   Stuff_Key_Num -- Stuffs a key num code into the circular buffer       *\n;*   Keystroke_Interrupt -- Real mode handler of input from the keyboard   *\n;*   Break_Interrupt -- Handles the break key interrupt                    *\n;*   Call_Interrupt_Chain -- Function PM calls to call RM interrupt chain  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tKeyboard driver -- 8086 Assembly portion;\t\t\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   *\n;***************************************************************************\n\n;---------------------------------------------------------------------------\n; Set the assembly directives\n;---------------------------------------------------------------------------\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386N\t\t\t\t; use 386 real mode instructions\nMODEL TINY\t\t\t; code must be tiny so it fits\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keyboard.inc\"\n\nCONDHIDE\t\tEQU\t08000H\t\t; bit for testing conditional region\nCONDHIDDEN\t\tEQU\t04000H\t\t; bit for testing conditional hidden\nRESTORE_VISIBLE_PAGE\tEQU\t0\nSTORE_VISIBLE_PAGE\tEQU\t1\n\n\nGLOBAL\tset_vesa_page \t:near\nGLOBAL\tset_vesa_window :near\nGLOBAL\tget_vesa_window :near\nGLOBAL\tnext_vesa_page\t:near\n\nECHOON\tequ 0\n;---------------------------------------------------------------------------\n; WARNING!!!!  All of the following code segment variables are shared by\n;   the protected mode interrupt.  Do not change these unless you make the\n;   proper changes to KEYSTRUC.INC.  If you do not know what you are doing,\n;   find someone who does!!!\n;---------------------------------------------------------------------------\nCODESEG\n\n;---------------------------------------------------------------------------\n; Begin definition of Keyboard specific variables\n;---------------------------------------------------------------------------\nSoundOn\t\tDW\t1\t; toggled by alt S\nMusicOn\t\tDW\t1\t; toggled by alt M\nKeyFlags\tDD\tREPEATON+CTRLALTTURBO\t; all but repeat for now\n\n\nBreak\t\tDW\t0\n\nKeyMouseMove\tDB\t-1,0,1\n\t\tDB\t-16,0,16\n\nScreenEdge\tDW\t320/2,0\t\t; North\n\t\tDW\t319,0\t\t; North-East\n\t\tDW\t319,138/2\t; East\n\t\tDW\t319,137\t\t; South-East\n\t\tDW\t320/2,137\t; South\n\t\tDW\t0,137\t\t; South-West\n\t\tDW\t0,138/2\t\t; West\n\t\tDW\t0,0\t\t; North-West\n\t\tDW\t320/2,138/2\t; Center\n\n\nBits\t\tDB\t01H,02H,04H,08H,10H,20H,40H,80H\n\nCondPassKey\tDW\t0220H, 0320H, 060CH, 070DH, 066AH\n\t\tDW\t0669H, 0230H, 0330H, 007DH, 017DH\n\t\tDW\t025AH, 035AH, 0200H, 0410H, 046EH\n\t\tDW\t026EH, 007CH\n\nCondPassCond\tDW\tCTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO\n\t\tDW\tCTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON\n\t\tDW\tPAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE\n\t\tDW\tTASKSWITCHABLE, BREAKON\n\nEscRoutine\tDD\t0\t; vector to execute on esc key press (0=none)\n\n; Extended raw keycodes to be converted to Westwood keycodes.\nExtCodes\tDB\t038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H\n\t\tDB\t051H,04DH,035H,01CH,037H\n\t\tDB\t046H\n; The matching Westwood keycodes.\nExtNums\t\tDB\t62,  64,  75,  76,  79,  80,  81,  83,  84,  85\n\t\tDB\t86,  89,  95, 108, 124,  0\n; If extended mapping is disabled, then these codes really are...\nExtRemap\tDB\t60,  58,  99, 104,  92,  91,  93,  96,  98, 101\n\t\tDB\t103, 102, 55,  43, 124,  0\nExtRemapEnd\tDB\t0\n\nExtKeyboard\tDB\t0\t; flag for 101/102-key keyboard\n\n\nKeyBuffer\tDW\t128 DUP(0) ; set to empty\nKeyBufferHead\tDD\t0\t; set to first entry\nKeyBufferTail\tDD\t0\t; set to head for empty buffer\nKeyLock\t\tDW\t0\t; num and caps lock bits\nKeyNums\t\tDB\t127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016\n\t\tDB\t017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032\n\t\tDB\t033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049\n\t\tDB\t050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116\n\t\tDB\t117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093\n\t\tDB\t098,103,099,104,127,127,127,122,123\n\nKeysCapsLock\tDB\t0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0\nKeysNumLock\tDB\t0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0\nKeysUpDown\tDB\t16 DUP(0) ; set to all keys up\nKeyStream\tDB\t16 DUP(0) ; set to all keys up\nPassCount\tDW\t0\nKeyStreamIndex\tDW\t0\nLastKeyE0\tDB\t0\nLastKeyE1\tDB\t0\n\n;\n; Westwood key number values of keys to pass through\n;\n;\t\t\tCAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT,\n;\t\t\tRIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN\nPassAlways\tDB\t30, 44, 57, 58, 60, 62, 64, 90, 128, 128\nPassAlwaysEnd\tDB\t128\t\t; invalid code to END PassAlways\nCtrlFlags\tDB\t0\n\nBuffer\t\tDW\t?\nTime\t\tDW\t?\n\nADJUST\t= 1\t\t\t; do not modify DRD\n\nXYAdjust\tDB\t-ADJUST, -ADJUST\t; 91 -> upleft\n\t\tDB\t-ADJUST,  0\t\t; 92 -> left\n\t\tDB\t-ADJUST,  ADJUST\t; 93 -> downleft\n\t\tDB\t 0,  0\t\t\t; 94 illegal\n\t\tDB\t 0,  0\t\t\t; 95 illegal\n\t\tDB\t 0, -ADJUST\t\t; 96 -> up\n\t\tDB\t 0,  0\t\t\t; 97 illegal (center)\n\t\tDB\t 0,  ADJUST\t\t; 98 -> down\n\t\tDB\t 0,  0\t\t\t; 99 illegal\n\t\tDB\t 0,  0\t\t\t; 100 illegal\n\t\tDB\t ADJUST, -ADJUST\t; 101 -> upright\n\t\tDB\t ADJUST,  0\t\t; 102 -> right\n\t\tDB\t ADJUST,  ADJUST\t; 103 -> downright\n\tEdgeConv\t\tDW\t8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7\n\tMouseUpdate\t\tDW\t0\n\tMouseX\t\t\tDW\t0,0\n\tLocalMouseX\t\tDW\t0\n\tMouseY\t\t\tDW\t0,0\n\tLocalMouseY\t\tDW\t0\n\tIsExtKey\t\tDB\t0\n\tExtIndex\t\tDW\t0\n\n\tKeyOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tKeyOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\t\t\n\tKeyOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tKeyCodeOffset\t\tDW\tRM_Keystroke_Interrupt\t; Offset of the code in the RM stuff.\n\tCallKeyRMIntOffset\tDW\tCall_Interrupt_Chain\t; Offset of function to call DOS timer interrupt.\n\tCallKeyRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedKeyInt\t\tDD\t0\n\n\tBrkOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tBrkOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\t\t\n\tBrkOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tBrkCodeOffset\t\tDW\tRM_Break_Interrupt\t; Offset of the code in the RM stuff.\n\tCallBrkRMIntOffset\tDW\t0\n\tCallBrkRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedBrkInt\t\tDD\t0\n\tKeyIntDisabled\t\tDD\t0\n\n\tDbgOldPMIOffset\t\tDD\t0\t; The origianl PM interrupt offset\t\t\n\tDbgOldPMISelector\tDD\t0\t; The original PM interrupt segment.\n\n;---------------------------------------------------------------------------\n; Begin definition of Mouse Specific Variables for real mode\n;---------------------------------------------------------------------------\nButton\t\t\tDB\t0\t; current value of the mouse button\nMDisabled\t\tDB\t0\t; Is the mouse driver disabled\nMInput\t\t\tDB\t1\t; Defaults to mouse input allowed.\nAdjust\t\t\tDW\t0\t; flag to adjust coordinates if necessary\nMouseStepX\t\tDW\t0\t; step values if the mouse moves at\nMouseStepY\t\tDW\t0\t;   more than one pixel at a time\nMouseOffsetX\t\tDW\t0\t; Fractional step values used if a mouse\nMouseOffsetY\t\tDW\t0\t;   moves at less than one pixel at a time\nMState\t\t\tDW\t0,0\t; Tracks if mouse is hidden (TRUE) or not (FALSE)\nMouseXOld     \t\tDW\t0\t; Holds last MouseX and MouseY to determine if \nMouseYOld     \t\tDW\t0\t;   mouse needs to be redrawn\nMCState\t\t\tDW\t0\t; Tracks if mouse conditional hidden (TRUE) or not\nMouseCXLeft\t\tDW\t0,0\t; Conditional hide mouse left x position\nMouseCYUpper\t\tDW\t0,0\t; Conditional hide mouse top y position\nMouseCXRight\t\tDW\t0,0\t; Conditional hide mouse right x position\nMouseCYLower\t\tDW\t0,0\t; Conditional hide mouse lower y position\nMouseCursor   \t\tDD\t0\t; Pointer to the mouse cursor to draw\nMouseCursorSize\t\tDW\t0\t; Pointer to buffer mouse is saved in\nMouseBuffer   \t\tDD\t0\t; Pointer to buffer mouse is saved in\nMouseXHot     \t\tDW\t0,0\t; Offset to mouse's x hot spot\nMouseYHot     \t\tDW\t0,0\t; Offset to mouse's y hot spot\nMouseBuffX\t\tDW\t0,0\t; X position background was saved at\nMouseBuffY\t\tDW\t0,0\t; Y position background was saved at\nMouseBuffW\t\tDW\t0,0\t; Width of the region saved for mouse\nMouseBuffH\t\tDW\t0,0\t; Height of the region saved for mouse\nMouseWidth\t\tDW\t0,0\t; Mouse cursor theoretical width\nMouseHeight\t\tDW\t0,0\t; Mouse cursor theoretical height\nMouseCodeOffset\t\tDW\tRM_Mouse_Interrupt\t; Offset of the code in the RM stuff.\nMouseRight\t\tDW\t0,0\nMouseBottom\t\tDW\t0,0\n\n\nShadowPtr\t\tdw\t0\nDrawMousePtr \t\tdw\t0\n\nVGAMouseDraw\t\tdw\tVGA_Draw_Mouse\nVGAMouseShadow\t\tdw\tVGA_Mouse_Shadow_Buffer\n\nVESAMouseDraw\t\tdw\tVESA_Draw_Mouse\nVESAMouseShadow\t\tdw\tVESA_Mouse_Shadow_Buffer\n\nVesaPtr\t\t\tdd\t0\t\nbanktable\t\tdd      8 dup ( 0 )\nAdjust_XPos\t\tdw \t0 , 0\nAdjust_YPos\t\tdw \t0 , 0 \n\n\n\n\n\ncurrent_page\t\tdw\t0\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Translates extended keynums to normal keynums\t   *\n;*                                                                         *\n;* INPUT:\tUWORD the keynum to translate\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated keynum                                 *\n;*                                                                         *\n;* PROTO:\tUWORD KeyNum_Translate(UWORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tKeyNum_Translate:FAR\n\tPROC\tKeyNum_Translate C FAR \n\tUSES\tcx,di,es,ds\n\tARG\tkeycode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\tmov\tes,ax\t\t\t\t; set es up for scansb\n\n\tmov\tax,[keycode]\n\ttest\t[WORD PTR KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\tmov\tcx,ExtRemap-ExtNums\n\tmov\tdi,OFFSET ExtNums\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tdi,OFFSET ExtRemapEnd\n\tdec\tdi\n\tsub\tdi,cx\n\tmov\tal,[es:di]\n??fini:\n\tret\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(WORD code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_WORD:FAR\n\tPROC\tStuff_Key_WORD C FAR \n\tUSES\tsi,bx,ds\n\tARG\tcode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\tax,[WORD PTR KeyBufferTail]\n\tmov\tsi,ax\n\tadd\tax,2\n\tand\tax,0FFh\t\t\t\t; New KeyBufferTail value.\n\tcmp\t[WORD PTR KeyBufferHead],ax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[KeyBuffer+si],bx\t\t; Record the keystroke.\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\n\tret\n\n??noroom:\n\tmov\tax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(WORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_Num:FAR\n\tPROC\tStuff_Key_Num C FAR \n\tUSES\tbx,cx,dx,di,si,ds\n\tARG\tkeycode:WORD\n\tLOCAL\ttail:WORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n\tpushf\n\tcli\t\t\t\t; disable interrupts\n\n\t; Abort key recognition if in record mode and unable\n\t; to output key due to simultaneous DOS operation.\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\tax,[MouseX]\n\tmov\t[LocalMouseX],ax\n\tmov\tax,[MouseY]\n\tmov\t[LocalMouseY],ax\n\n??cando:\n\tmov\tax,[keycode]\t\t; get the code\n\tor\tax,ax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[WORD PTR KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[WORD PTR KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tbx,1\t\t\t; double for WORD index\n\tadd\tbx,OFFSET XYAdjust\n\tmov\tax,[bx]\t\t\t; get x,y add value\n\n\tmov\tbl,ah\n\tcbw\n\txchg\tax,bx\n\tcbw\n\txchg\tax,bx\t\t\t; AX = mouse x delta, BX = mouse y delta\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tdx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tdx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tbx,dx\t\t\t; add speed for y index\n\tmov\tbl,[KeyMouseMove+bx] \t; get speed for y delta\n\txchg\tax,bx\t\t\t; swap with ax to extend sign\n\tcbw\n\txchg\tax,bx\n\txchg\tbx,dx\t\t\t; save mouse y delta\n\tadd\tbx,ax\t\t\t; add speed for x index\n\tmov\tal,[KeyMouseMove+bx]\t; get speed for x delta\n\tcbw\n\txchg\tbx,dx\t\t\t; restore mouse y delta\n\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tbx,011b\t\t\t; Y = 1, 0, 3\n\tand\tax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tbx,011b\t\t\t; Y = 3, 0, 1\n\tand\tax,011b\t\t\t; X = 3, 0, 1\n\tshl\tbx,1\n\tshl\tbx,1\n\tor\tbx,ax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tbx,1\n\tmov\tbx,[EdgeConv+bx]\n\tshl\tbx,1\n\tshl\tbx,1\n\tmov\tax,[ScreenEdge+bx]\t; New absolute X\n\tmov\tbx,[ScreenEdge+bx+2] ; New absolute Y\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\tax,ax\n\tmov\t[LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tbx,bx\n\tmov\t[LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\tmov\t[MouseX],ax\n\tmov\t[MouseY],bx\n\tcmp\t[MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n\n\tcall\tLow_Hide_Mouse\n\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\tax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],ax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tsi,[WORD KeyBufferTail]\n\tmov\t[tail],si\t\t; Safety record.\n\tmov\tdi,[WORD PTR KeyBufferHead]\n\n\t; Record the base keycode (if there is room).\n\tpush\tax\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\tax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tpush\t[LocalMouseX]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tpush\t[LocalMouseY]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tbx,0101h\t\t; Bit control tools.\n\tmov\tax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[WORD PTR KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tmov\tcl,3\n\tshr\tdi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[KeysUpDown+di]\n\tje\tshort ??notalready\n\ttest\t[WORD PTR KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[KeysUpDown+di],bh\t; Force key bit to zero.\n\tor\t[KeysUpDown+di],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\tax,1\n\tjmp short ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\tax,[tail]\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\t\t\t; Signal an error.\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tStuff_Key_Num\n;***********************************************************\n\n\n\n;***************************************************************************\n;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard       *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Keystroke_Interrupt\n\tGLOBAL\tC Keystroke_Interrupt:FAR\n\tPROC\tKeystroke_Interrupt C FAR \n\nIF 0\n\tpush\tax\n\tinc\tax\n\tpop\tax\n\tiret\n\nELSE\n\tpush\tax\n\tpush\tbx\n\tpush\tcx\n\tpush\tdi\n\tpush\tds\n\tpush\tdx\n\tpush\tes\n\tpush\tsi\n\tcld\n\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tds,ax\n\n\n\n\tcmp\t[WORD PTR PMIssuedKeyInt],0; Check to see if PM made Int call.\n\tmov\t[WORD PTR PMIssuedKeyInt],0; Make it false.\t\t\n\tjne\t??passcode\t; if so, just call Int Chain.\n\n\n\tmov\tdx,[WORD PTR KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\tmov\tax,040H\t\t\t; BIOS segment\n\tmov\tes,ax\t\t\t; put in es\n\ttest\t[BYTE PTR es:017H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR es:017H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR es:096H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tes,ax\n\n\tcld\t\t\t\t; clear direction flag for strings\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tbx,0101H\t\t; set key to a make by default\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\n\t;\n\t; New CODE to montior key stream\n\t;\n\tmov\tbx,[KeyStreamIndex]\n\tmov\t[KeyStream+bx],al\n\tinc\tbx\n\tand\tbx,15\n\tmov\t[KeyStreamIndex],bx\n\tmov\tbx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[LastKeyE1]\t\t; yes, dec the count\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[IsExtKey],TRUE\t; it is an extended key\n\tmov\tdi,OFFSET ExtCodes\t; get offset of extended codes table\n\tmov\tcx,(ExtNums-ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\tmov\tal,[(ExtNums - ExtCodes) - 1 + di] ; get the match\n\tmov\t[IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tdi,ax\t\t\t; use code as an index\n\tand\tdi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[KeyNums+di]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[KeysUpDown+8],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[KeysUpDown+7],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[KeysUpDown + 7],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\tax\n\tcall\tKeyNum_Translate\n\tadd\tsp,2\n\n;------\tSet the shift bit if necessary.\n\ttest\t[KeysUpDown+5],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[KeysUpDown+7],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tshr\tdi,1\n\tshr\tdi,1\n\tshr\tdi,1\n\tmov\tbx,ax\n\tand\tbx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[Bits+bx]\t\t; get the bit to test\n\ttest\t[KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[KeysCapsLock+di]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[KeysNumLock+di]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\n\t\t\t\t\t; keyboard buffer.\nIF DEBUG\n\tcmp\t[KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\tcmp\tax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\tax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\tax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\t\n\tcmp\tax,125\n\tjne\t??not_toggle\n\tmov\t[KeyIntDisabled],1\n\tjmp\t??absorbcode\nENDIF\n\n??not_toggle:\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\tax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\tax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\tax,0230h\n\tje\tshort ??breaker\n\tcmp\tax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n\tcmp\tax,0420H\t\t; is this an alt s\n\tjne\tshort ??checkmusic\t; toggle the Sound variable\n\tpush\tax\n\tmov\tax,[SoundOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??checkmusic:\n\tcmp\tax,0434H\t\t; is this an alt m\n\tjne\tshort ??esc\t\t; toggle the Music variable\n\tpush\tax\n\tmov\tax,[MusicOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??esc:\n\n\tpush\tax\n\tcall\tStuff_Key_Num\n\tpop\tax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\tax\n\tcall\t[EscRoutine]\n\tpop\tax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tdi,OFFSET PassAlways\t; get offset to table\n\tmov\tcx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1\n\trepne\tscasb\t\t\t; look for a match\n\tor\tcx,cx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n\n\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tdi,OFFSET CondPassKey\t; get offset to cond key table\n\tmov\tcx,(CondPassCond-CondPassKey) ; get number of entries\n\tshr\tcx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(CondPassCond - CondPassKey) - 2 + di]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tdx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tinc\t[cs:PassCount]\n\tjmp\t[cs:KeyOldRMI]\n\n??absorbcode:\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tax,040h\t\t\t\t; BIOS paragraph is always @ 040h\n\tmov\tes,ax\t\t\t\t; put in es as BIOS paragraph\n\tmov\tal,[es:96h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[es:96h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tiret\t\nENDIF\n\n\tENDP\tKeystroke_Interrupt\n\n;***************************************************************************\n;* Break interrupt routines begin here!\n;***************************************************************************\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles the break key interrupt                      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Break_Interrupt\n\tGLOBAL\tC Break_Interrupt:FAR\n\tPROC\tBreak_Interrupt C FAR\n\n\n\tpushf\n\tpush\tax\n\tpush\tes\n\n\tmov\tax,0B000h\t\t; ES:DI = Mono RAM address.\n\tmov\tes,ax\n\tinc\t[BYTE PTR es:0]\n\t\t\n\n\tpop\tes\n\tpop\tax\n\tpopf\n\n\n\tiret\t\n\n\tENDP\tBreak_Interrupt\n\n;**************************************************************************\n;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                                  *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nCall_Interrupt_Chain:\n\tpushf\n\tcall\tKeystroke_Interrupt ;[KeyOldRMI]\n\tretf\n\n;----------------------------------------------------------------------------\n; LOW_HIDE_MOUSE:\n;\n; This function hides the mouse cursor on the screen if it was shown.  It \n; will not hide the mouse if it is already hidden.\n;\n; PROTOTYPE:\n;\n;\tVOID Low_Hide_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Hide_Mouse:FAR\n\tPROC\tLow_Hide_Mouse C FAR \n\tUSES\tax,bx,cx,dx,ds\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n   \tcmp\t[MDisabled],0\t\t; check if mouse is disabled\n\tjne\tshort ??end\n\n   \tcmp\t[MState],0\t\t; check if it was hidden before\n\tjne\tshort ??endnodraw\t\t; no need to hide again\n\n;------\tMove the saved graphic buffer to the seenpage to hide the mouse.\n;\tcall\tBuffer_To_Page C,[buffx],[buffy],[buffw],[buffh],[MouseBuffer],SEENPAGE\n\tmov\tax,RESTORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tRecord that the mouse has been hidden.\n??endnodraw:\n\tadd\t[MState],1\n\tadc\t[MState],0\n\n??end:\n\tret\n\n\tENDP\tLow_Hide_Mouse\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; LOW_SHOW_MOUSE:\n;\n; This function displays the mouse cursor on the screen if it was hidden.\n;\n; PROTOTYPE:\n;\tVOID Low_Show_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Show_Mouse:FAR\n\tPROC\tLow_Show_Mouse C FAR \n\tUSES \tax,bx,cx,dx,si,di,ds,es\n\tLOCAL\tmousex:WORD\t\t; Draw X position.\n\tLOCAL\tmousey:WORD\t\t; Draw Y position.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n;-----\tDon't show the mouse if it is not hidden, disabled.\n\tcmp\t[MDisabled],0\t\t; is the mouse disabled\n\tjne\t??exit\t\t\t; if so then exit\n\n\tcmp\t[MState],0\t\t; is the mouse already visible\n       \tje\t??exit\t\t\t; if so then exit\n\n\tdec\t[MState]\n\tcmp\t[MState],0\t\t; can the mouse be shown\n       \tjne\tshort ??exit\n\n;------\tDetermine the drawing position of the mouse.\n\tmov\tcx,[MouseWidth]\t\t; Theoretical buffer width (pixel).\n\tmov\tdx,[MouseHeight]\t; Theoretical buffer height (pixel).\n\n\tmov\tax,[MouseX]\n;\tsub\tax,[MouseXHot]\n\tmov\t[mousex],ax\t\t; Draw X pixel.\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??xnotneg\n;\tadd\tcx,ax\t\t\t; Reduce width accordingly.\n;\tmov\tax,0\n??xnotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n\tmov\tbx,[MouseY]\n;\tsub\tbx,[MouseYHot]\n\tmov\t[mousey],bx\t\t; Draw Y pixel.\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??ynotneg\n;\tadd\tdx,bx\t\t\t; Reduce height of mouse accordingly.\n;\tmov\tbx,0\n??ynotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n;------\tDetermine the theoretical coordinates and dimensions of the\n;\tarea the mouse shape will be rendered upon.\n\tmov\t[MouseBuffX],ax\n\tmov\t[MouseBuffY],bx\n\tmov\t[MouseBuffW],cx\n\tmov\t[MouseBuffH],dx\n\n;------\tMove the area that will be drawn upon, to the graphic buffer.\n\tmov\tax,STORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tDraw the mouse shape to the seenpage.\n\tpush\t[mousey]\n\tpush\t[mousex]\n\tpush\tcs\n\tcall\t[ DrawMousePtr ]\n\tadd\tsp,4\n??exit:\n\tret\n\n\tENDP\tLow_Show_Mouse\n\n;----------------------------------------------------------------------------\n;----------------------------------------------------------------------------\n\tGLOBAL\tC Mouse_KeyNum:FAR\n\tPROC\tMouse_KeyNum C FAR \n\tUSES\tbx\n\tARG\tstate:WORD\t\t; Current mouse state.\n\tLOCAL\tkeynum:WORD\t\t; Determined keynum.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\t[keynum],KN_MOUSE_MOVE\t; Presume just a mouse move.\n\tmov\tbx,[state]\n\tmov\tax,bx\n\txor\tbl,[Button]\t\t; Bits of state change.\n\tje\tshort ??fini\n\tmov\t[Button],al\t\t; Record new mouse state.\n\n\ttest\tbl,0010b\n\tje\tshort ??notright\n\tmov\t[keynum],KN_RMOUSE\n\ttest\tal,0010b\n\tjne\tshort ??notright\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notright:\n\n; DRD\n; note:  the left mouse button has priority over the right mouse button\n; this should be changed at a later date to process them independently\n\n\ttest\tbl,0001b\n\tje\tshort ??notleft\n\tmov\t[keynum],KN_LMOUSE\n\ttest\tal,0001b\n\tjne\tshort ??notleft\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notleft:\n\n??fini:\n\tmov\tax,[keynum]\n\tret\n\n\tENDP\tMouse_KeyNum\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; MOUSE_INT:\n;\n; This routine is called automatically when the Mouse_Int is installed.  It\n; automatically updates the global variables stored in the code segment so\n; that the mouse information is automatically known at all times.\n;\n; INPUTS (from int):\tAX = condition mask ( bit 0 == cursor position chg,\n;\t\t\t\t\t      bit 1 == left button press,\n;\t\t\t\t\t      bit 2 == left button release,\n;\t\t\t\t\t      bit 3 == right button press,\n;\t\t\t\t\t      bit 4 == right button release,\n;\t\t\t\t\t      5-15  == not used )\n;\t\t\tBX = button state   ( bit 0 == left button down,\n;\t\t\t\t\t      bit 1 == right button down,\n;                                             bit 2 == middle button down.\n;\t\t\t\t\t      3-15  == not used )\n;\t\t\tCX = cursor coordinate (horizontal axis)\n;\t\t\tDX = cursor coordinate (vertical axis)\n;\t\t\tDI = horizontal mouse count (mickeys)\n;\t\t\tSI = vertical mouse count (mickeys)\n;\n; RETURNS:\t\tnone\n;\n; MODIFIES:\t\tmodifies the variables _Button, _ButtonChange,\n;\t\t\t_MouseX,_MouseY,_ButtonLatch\n;\n; PROTOTYPE:\n;\tThis routine is called from an interrupt.\n;----------------------------------------------------------------------------\nlabel RM_Mouse_Interrupt\n\tPROC\tMouse_Int C FAR \n\tUSES\tax,bx,cx,dx,ds,si,es,di\n\tLOCAL\tcond:WORD\t\t; Local copy of mouse event.\n\tLOCAL\tstate:WORD\t\t; Local copy of button state.\n\n\n;------\tCurrent mouse state button flag globals update.\n\tmov\t[state],bx\n\tmov\t[cond],ax\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n;------\tProcess the mouse interrupt only if the mouse is enabled (whether\n;\tpresent or not).\n\tcmp\t[MDisabled],0\n\tjne\t??exit\n\n\n\tcmp\t[MInput],0\n\tje\t??exit\n\n\n\n;------ This was added because of missing mouse presses and\n;\treleases during a mouse update.\n\tmov\tax,[cond]\n\tand\tax,0001EH \t; bits for left and right press and release\n\tjne\tshort ??dopress_release\n\n\tcmp\t[MouseUpdate],0 ; if mouse move and mouse updating exit\n\tjne\t??exit\n\n??dopress_release:\n\n;------\tIn EEGA mode mouse X coordinates as 0..639.  Make adjustment\n;\tto keep within 0..319 range.\n\tcmp\t[Adjust],1\t\t; if the x coordinate is returned\n\tjne\tshort ??noadjust\t; incorrectly then\n\tshr\tcx,1\t\t\t; adjust x coord from 640 pixel screen\n??noadjust:\n\n\n; scale mouse posX and PosY\n;\tcmp\t[Adjust_XPos] , 0\n;\tjz\tshort ??no_scaleX\n;\tpush\tdx\n;\tmov\tax , [MouseRight]\n;\timul\tcx\n;\tidiv\t[Adjust_XPos]\n;\tmov\tcx , ax\n;\tpop\tdx\n??no_scaleX:\n;\tcmp\t[Adjust_YPos] , 0\n;\tjz\tshort ??no_scaleY\n;\tmov\tax , [MouseBottom]\n;\timul\tdx\n;\tidiv\t[Adjust_YPos]\n;\tmov\tdx , ax\n??no_scaleY:\n\n;------\tKeep mouse within screen bounds.\n\tcmp\tcx,[MouseRight]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundX_ok\t\t; force it to stay at least one pixel\n\tmov\tcx,[MouseRight]\t\t\t; on the screen\n\tdec\tcx\n??boundX_ok:\n\tcmp\tdx,[MouseBottom]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundY_ok\t\t; force it to stay at least one pixel\n\tmov\tdx,[MouseBottom]\t\t\t; on the screen\n\tdec\tdx\n??boundY_ok:\n\n\tIF 0\n;------\tRemap the middle button to equal the right button.\n\ttest\tbx,04h\n\tje\t??noremap\n\tor\tbx,0010b\t\t; Set the right button bit.\n??noremap:\n\tENDIF\n\n\tmov\t[MouseX],cx\t\t; and store in mouse x\n\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\ttest\t[KeyFlags],KEYMOUSE\n\tjne\tshort ??nostuffit\n\n\tcall\tMouse_KeyNum C,[state]\t; Convert mouse state to key number code.\n\tcall\tStuff_Key_Num C,ax\t; Record mouse keynumber code.\n??nostuffit:\n\n\n\n;------ The check for Mouse in the middle of updating CAN NOT BE MOVED\n;\tany farther up because mouse presses and releases will be LOST!!\n \tcmp\t[MouseUpdate],0\n\tjne\t??exit\n;??jexit:\n;\tjmp\t??exit\n\n\nchristopher:\n??chkxy:\n\n;------\tSignal that no mouse updating can occur at this time.\n;\tcmp\t[_MouseUpdate],0\n;\tjne\t??exit\n;\tmov\t[_MouseUpdate],1\n\n;------\tPerform any X movement grid adjustment.\n\tcmp\t[MouseStepX],0\t\t; are we stepping on the X?\n\tje\tshort ??no_x_step\t\t; no x\n\tmov\tax,cx\t\t\t; get current x_pixel\n\tmov\tcx,dx\t\t\t; save dx - it is trashed by idiv\n\tsub\tax,[MouseOffsetX]\t; get offset difference\n\tmov\tbx,[MouseStepX]\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step X\n\timul\tbx\t\t\t; ax = div * Step X\n\tadd\tax,[MouseOffsetX]\t; normalize to region offset\n\tmov\tdx,cx\t\t\t; restore dx (new MouseY)\n\tmov\tcx,ax\t\t\t; set cx (new MouseX)\n??no_x_step:\n\n;------\tPerform any Y movement grid adjustment.\n\tcmp\t[MouseStepY],0\t\t; are we stepping on the Y\n\tje\tshort ??no_step\t\t; no y\n\tmov\tax,dx\t\t\t; get current y_pixel\n\tsub\tax,[MouseOffsetY]\t; get offset difference\n\tmov\tbx,[MouseStepY]\t\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step Y\n\timul\tbx\t\t\t; ax = div * Step Y\n\tadd\tax,[MouseOffsetY]\t; normalize to region offset\n\tmov\tdx,ax\t\t\t; set dx (new MouseY)\n??no_step:\n\n;------ Here is where we store the new MouseX and MouseY values\n;\tmov\t[MouseX],cx\t\t; and store in mouse x\n;\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\n;------\tIf the mouse is hidden or its position hasn't changed, then\n;\tperform no action.\n\tcmp\t[MState],0\n\tjne\tshort ??updateend\n\tcmp\t[MouseXOld],cx\n\tjne\tshort ??doit\n\tcmp\t[MouseYOld],dx\n\tje\tshort ??updateend\n??doit:\n\n;------\tAt this point we KNOW the mouse has moved.\n\tmov\tax,[MCState]\n\tand\tax,CONDHIDE+CONDHIDDEN\n\tcmp\tax,CONDHIDE+CONDHIDDEN\n\tje\tshort ??condcheck\t\t; If already hidden.\n\n;------\tWe know that the mouse is visible, we must hide it\n;\tbefore we update its position.\n\tcall\tLow_Hide_Mouse\n\n;------\tConditional region check goes here.  If the mouse falls within the \n;\tconditional region, it gets marked as hidden and no other processing\n;\toccurs.\n\ttest\t[MCState],CONDHIDE\n\tje\tshort ??condok\n\n??condcheck:\n\tcmp\tcx,[MouseCXLeft]\t\t; check adjusted x region\n\tjb\tshort ??condok\n\tcmp\tcx,[MouseCXRight]\n\tja\tshort ??condok\n\tcmp\tdx,[MouseCYUpper]\t; check adjusted y region\n\tjb\tshort ??condok\n\tcmp\tdx,[MouseCYLower]\n\tja\tshort ??condok\n\n\tor\t[MCState],CONDHIDDEN\t; flag as conditional hidden\n\tjmp short ??updateend\n\n;------\tThe mouse coordinates and flags pass all of the tests, proceed\n;\twith rendering the mouse.\n??condok:\n\tcall\tLow_Show_Mouse\n\n;------\tFinal clean up and exit.\n??updateend:\n\tmov\t[MouseXOld],cx\n\tmov\t[MouseYOld],dx\n\n??exit:\n\tret\n\tENDP\tMouse_Int\n\n\n\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VGA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVGA_Mouse_Shadow_Buffer C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\tpush\tbp\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tbp , cx\n??restore_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 10\nmov es, ax\nmov al , 'V'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tsi,di\t\t\t\t\t; xchg the source and the dest\n\tmov\tbp , cx\n\tpush\tes\t\t\t\t\t; need to swap es and ds but\n\tpush\tds\t\t\t\t\t;   cant xchg so pop them on the\n\tpop\tes\t\t\t\t\t;   stack and pop them off the\n\tpop\tds\t\t\t\t\t;   wrong way intentionally.\n??store_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,dx\t\t\t\t\t; move past right clipped pixels\n\tadd\tdi,bx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 12\nmov es, ax\nmov al , 'G'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tret\n\n\tENDP\tVGA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n\n\tGLOBAL\tC VGA_Draw_Mouse:FAR\n\tPROC\tVGA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tbx , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , bx\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tbx , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , bx\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 14\nmov es, ax\nmov al , 'A'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tret\nENDP\tVGA_Draw_Mouse\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VESA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVESA_Mouse_Shadow_Buffer C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\t\n\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??restore_loop:\n\tmov\tah,al\n??res_inner_loop:\n\tmov\tch , [si]\n\tmov\t[es:di],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??res_same_page\n\tcall\tnext_vesa_page\n ??res_same_page:\n \tdec\tah\n\tjnz\t??res_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??res_same_page1\n\tcall\tnext_vesa_page\n ??res_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 10\nmov es,ax\nmov al ,'v'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tjmp\t??out\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\tmov\tah,al\n??store_inner_loop:\n\tmov\tch , [es:di]\n\tmov\t[si],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??store_same_page\n\tcall\tnext_vesa_page\n ??store_same_page:\n \tdec\tah\n\tjnz\t??store_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??store_same_page1\n\tcall\tnext_vesa_page\n ??store_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_entry\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 14\nmov es,ax\nmov al ,'e'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\n\tmov\tdx , [ app_vesa_window ] \n\tcall\tset_vesa_window\n\tret\n\n\tENDP\tVESA_Mouse_Shadow_Buffer\n\n\n\n;***************************************************************************\n\n\tGLOBAL\tC VESA_Draw_Mouse:FAR\n\tPROC\tVESA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\tlocal\tapp_vesa_window : word\n\n   \n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tsi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tjnz\t??same_page\n\tcall\tnext_vesa_page\n ??same_page:\n \tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??same_page1\n\tcall\tnext_vesa_page\n ??same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 14\nmov es, ax\nmov al , 's'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nmov di , 10 * 80 + 16\nmov al , 'a'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tmov\tdx , [ app_vesa_window ] \n\tcall\tset_vesa_window\n\tret\n\n\nENDP\tVESA_Draw_Mouse\n\n\n\n;************************************************************************\n\nPROC\tget_vesa_window C near\nuses\tax,bx\n\tmov\tax , 04f05h\n\tmov\tbh , 1\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\t\n\n;************************************************************************\n\nPROC\tset_vesa_window C near\nuses\tax,bx,dx\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]  \t\n\tret\nENDP\t\n\n\n;***************************************************************************\n\nPROC\tset_vesa_page C near\nUSES\tax,bx,dx\n\n\tmov\tbx , dx\n\tshl\tbx , 2\n\tmov\t[ cs: current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tset_vesa_page\n\nPROC\tnext_vesa_page C near\nUSES\tax,bx,dx\n\tmov\tbx , [ cs: current_page ]\n\tadd\tbx , 4\n\tmov\t[ cs:current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n       \tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tnext_vesa_page\n\n\n\n;***********************************************************\nEND\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/KEYIREAL.IBN",
    "content": "\tDB  001h,000h,001h,000h,011h,000h,000h,000h,000h,000h,0FFh,000h,001h,0F0h,000h\n\tDB  010h,0A0h,000h,000h,000h,03Fh,001h,000h,000h,03Fh,001h,045h,000h,03Fh,001h\n\tDB  089h,000h,0A0h,000h,089h,000h,000h,000h,089h,000h,000h,000h,045h,000h,000h\n\tDB  000h,000h,000h,0A0h,000h,045h,000h,001h,002h,004h,008h,010h,020h,040h,080h\n\tDB  020h,002h,020h,003h,00Ch,006h,00Dh,007h,06Ah,006h,069h,006h,030h,002h,030h\n\tDB  003h,07Dh,000h,07Dh,001h,05Ah,002h,05Ah,003h,000h,002h,010h,004h,06Eh,004h\n\tDB  06Eh,002h,07Ch,000h,008h,000h,008h,000h,010h,000h,010h,000h,010h,000h,010h\n\tDB  000h,020h,000h,020h,000h,040h,000h,040h,000h,080h,000h,080h,000h,000h,001h\n\tDB  000h,004h,000h,004h,000h,004h,000h,001h,000h,000h,000h,000h,038h,01Dh,052h\n\tDB  053h,04Bh,047h,04Fh,048h,050h,049h,051h,04Dh,035h,01Ch,037h,046h,03Eh,040h\n\tDB  04Bh,04Ch,04Fh,050h,051h,053h,054h,055h,056h,059h,05Fh,06Ch,07Ch,000h,03Ch\n\tDB  03Ah,063h,068h,05Ch,05Bh,05Dh,060h,062h,065h,067h,066h,037h,02Bh,07Ch,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,07Fh,06Eh\n\tDB  002h,003h,004h,005h,006h,007h,008h,009h,00Ah,00Bh,00Ch,00Dh,00Fh,010h,011h\n\tDB  012h,013h,014h,015h,016h,017h,018h,019h,01Ah,01Bh,01Ch,02Bh,03Ah,01Fh,020h\n\tDB  021h,022h,023h,024h,025h,026h,027h,028h,029h,001h,02Ch,01Dh,02Eh,02Fh,030h\n\tDB  031h,032h,033h,034h,035h,036h,037h,039h,064h,03Ch,03Dh,01Eh,070h,071h,072h\n\tDB  073h,074h,075h,076h,077h,078h,079h,05Ah,07Dh,05Bh,060h,065h,069h,05Ch,061h\n\tDB  066h,06Ah,05Dh,062h,067h,063h,068h,07Fh,07Fh,07Fh,07Ah,07Bh,000h,000h,0FEh\n\tDB  087h,0FFh,0C0h,01Fh,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,038h,0EFh,001h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,01Eh,02Ch,039h,03Ah,03Ch,03Eh,040h,05Ah\n\tDB  080h,080h,080h,000h,000h,000h,000h,000h,0FFh,0FFh,0FFh,000h,0FFh,001h,000h\n\tDB  000h,000h,000h,000h,0FFh,000h,000h,000h,001h,000h,000h,000h,000h,001h,0FFh\n\tDB  001h,000h,001h,001h,008h,000h,002h,000h,008h,000h,006h,000h,004h,000h,003h\n\tDB  000h,008h,000h,005h,000h,008h,000h,008h,000h,008h,000h,008h,000h,000h,000h\n\tDB  001h,000h,008h,000h,007h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,018h,006h,07Ch,008h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,06Bh\n\tDB  008h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,001h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,06Eh\n\tDB  009h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,0E4h,00Bh\n\tDB  090h,00Ah,095h,00Eh,01Ch,00Dh,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,0C8h,000h,000h,000h,051h,057h,006h,01Eh\n\tDB  08Ch,0C8h,08Eh,0D8h,08Eh,0C0h,08Bh,046h,006h,0F7h,006h,004h,000h,002h,000h\n\tDB  075h,013h,0B9h,010h,000h,0BFh,094h,000h,0F2h,0AEh,0E3h,009h,0BFh,0B4h,000h\n\tDB  04Fh,02Bh,0F9h,026h,08Ah,005h,01Fh,007h,05Fh,059h,0C9h,0CBh,0C8h,000h,000h\n\tDB  000h,056h,053h,01Eh,08Ch,0C8h,08Eh,0D8h,0A1h,0BAh,001h,08Bh,0F0h,005h,002h\n\tDB  000h,025h,0FFh,000h,039h,006h,0B6h,001h,074h,011h,08Bh,05Eh,006h,089h,09Ch\n\tDB  0B6h,000h,0A3h,0BAh,001h,033h,0C0h,01Fh,05Bh,05Eh,0C9h,0CBh,0B8h,001h,000h\n\tDB  01Fh,05Bh,05Eh,0C9h,0CBh,0C8h,004h,000h,000h,053h,051h,052h,057h,056h,01Eh\n\tDB  09Ch,0FAh,08Ch,0C8h,08Eh,0D8h,0A1h,0ABh,002h,0A3h,0AFh,002h,0A1h,0B1h,002h\n\tDB  0A3h,0B5h,002h,08Bh,046h,006h,00Bh,0C0h,075h,003h,0E9h,0F7h,001h,0F7h,006h\n\tDB  004h,000h,000h,010h,00Fh,084h,03Ah,001h,0F6h,0C4h,004h,00Fh,085h,033h,001h\n\tDB  0F7h,006h,004h,000h,000h,020h,074h,00Ch,03Ch,02Bh,074h,00Ch,03Ch,03Dh,074h\n\tDB  008h,03Ch,06Ch,074h,004h,03Ch,063h,075h,016h,0B0h,041h,080h,00Eh,0F6h,002h\n\tDB  001h,0F6h,0C4h,008h,00Fh,084h,00Ah,001h,080h,026h,0F6h,002h,0FEh,0E9h,002h\n\tDB  001h,03Ch,068h,075h,016h,0B0h,042h,080h,00Eh,0F6h,002h,002h,0F6h,0C4h,008h\n\tDB  00Fh,084h,0F0h,000h,080h,026h,0F6h,002h,0FDh,0E9h,0E8h,000h,0F6h,0C4h,008h\n\tDB  00Fh,085h,0E4h,000h,03Ch,061h,074h,01Eh,03Ch,05Bh,00Fh,082h,0DAh,000h,03Ch\n\tDB  067h,00Fh,087h,0D4h,000h,03Ch,05Dh,076h,00Eh,03Ch,065h,073h,00Ah,03Ch,060h\n\tDB  074h,006h,03Ch,062h,00Fh,085h,0C2h,000h,08Ah,0ECh,032h,0E4h,02Ch,05Bh,08Bh\n\tDB  0D8h,0D1h,0E3h,081h,0C3h,06Fh,002h,08Bh,007h,08Ah,0DCh,098h,093h,098h,093h\n\tDB  0F6h,0C5h,002h,075h,021h,0BAh,001h,000h,0F6h,0C5h,001h,074h,003h,083h,0C2h\n\tDB  003h,003h,0DAh,08Ah,09Fh,00Ah,000h,093h,098h,093h,087h,0DAh,003h,0D8h,08Ah\n\tDB  087h,00Ah,000h,098h,087h,0DAh,0EBh,034h,083h,0E3h,003h,025h,003h,000h,083h\n\tDB  0E3h,003h,025h,003h,000h,0D1h,0E3h,0D1h,0E3h,00Bh,0D8h,0D1h,0E3h,08Bh,09Fh\n\tDB  089h,002h,0D1h,0E3h,0D1h,0E3h,08Bh,087h,010h,000h,08Bh,09Fh,012h,000h,0A3h\n\tDB  0AFh,002h,089h,01Eh,0B5h,002h,0A1h,0AFh,002h,08Bh,01Eh,0B5h,002h,0EBh,02Fh\n\tDB  001h,006h,0AFh,002h,079h,005h,033h,0C0h,0A3h,0AFh,002h,001h,01Eh,0B5h,002h\n\tDB  079h,006h,033h,0DBh,089h,01Eh,0B5h,002h,0A1h,0AFh,002h,08Bh,01Eh,0B5h,002h\n\tDB  03Dh,03Fh,001h,07Eh,003h,0B8h,03Fh,001h,081h,0FBh,0C7h,000h,07Eh,003h,0BBh\n\tDB  0C7h,000h,0A3h,0AFh,002h,089h,01Eh,0B5h,002h,0A3h,0ABh,002h,089h,01Eh,0B1h\n\tDB  002h,083h,03Eh,0A9h,002h,000h,075h,008h,00Eh,0E8h,030h,003h,00Eh,0E8h,05Fh\n\tDB  003h,0B8h,02Dh,000h,089h,046h,006h,08Bh,036h,0BAh,001h,089h,076h,0FEh,08Bh\n\tDB  03Eh,0B6h,001h,050h,00Eh,0E8h,051h,0FEh,083h,0C4h,002h,00Bh,0C0h,075h,011h\n\tDB  08Bh,046h,006h,03Ch,02Dh,074h,00Dh,03Ch,041h,074h,009h,03Ch,042h,074h,005h\n\tDB  0EBh,029h,0E9h,080h,000h,0FFh,036h,0AFh,002h,00Eh,0E8h,02Eh,0FEh,083h,0C4h\n\tDB  002h,00Bh,0C0h,075h,0EEh,083h,046h,0FCh,002h,0FFh,036h,0B5h,002h,00Eh,0E8h\n\tDB  01Bh,0FEh,083h,0C4h,002h,00Bh,0C0h,075h,0DBh,083h,046h,0FCh,002h,0BBh,001h\n\tDB  001h,08Bh,046h,006h,03Ch,02Dh,074h,01Bh,03Ch,07Fh,074h,017h,0F6h,0C4h,008h\n\tDB  074h,016h,032h,0DBh,0F7h,006h,004h,000h,000h,008h,075h,00Ch,03Ch,041h,074h\n\tDB  008h,03Ch,042h,074h,004h,089h,036h,0BAh,001h,08Bh,0F8h,083h,0E7h,07Fh,0B1h\n\tDB  003h,0D3h,0EFh,08Ah,0C8h,080h,0E1h,007h,0D3h,0E3h,0F6h,0D7h,084h,09Dh,039h\n\tDB  002h,074h,00Ch,0F7h,006h,004h,000h,001h,000h,075h,004h,089h,036h,0BAh,001h\n\tDB  020h,0BDh,039h,002h,008h,09Dh,039h,002h,0B8h,001h,000h,0EBh,008h,08Bh,046h\n\tDB  0FEh,0A3h,0BAh,001h,033h,0C0h,09Dh,01Fh,05Eh,05Fh,05Ah,059h,05Bh,0C9h,0CBh\n\tDB  050h,053h,051h,057h,01Eh,052h,006h,056h,0FCh,08Ch,0C8h,08Eh,0D8h,083h,03Eh\n\tDB  0CEh,002h,000h,0C7h,006h,0CEh,002h,000h,000h,00Fh,085h,0FDh,001h,08Bh,016h\n\tDB  004h,000h,083h,026h,0BEh,001h,0FCh,0B8h,040h,000h,08Eh,0C0h,026h,0F6h,006h\n\tDB  017h,000h,040h,074h,005h,083h,00Eh,0BEh,001h,001h,026h,0F6h,006h,017h,000h\n\tDB  020h,074h,005h,083h,00Eh,0BEh,001h,002h,0C6h,006h,0B5h,000h,001h,026h,0F6h\n\tDB  006h,096h,000h,010h,075h,005h,0C6h,006h,0B5h,000h,000h,08Ch,0C8h,08Eh,0C0h\n\tDB  0FCh,032h,0E4h,0BBh,001h,001h,0E4h,060h,08Bh,01Eh,05Bh,002h,088h,087h,049h\n\tDB  002h,043h,083h,0E3h,00Fh,089h,01Eh,05Bh,002h,0BBh,001h,001h,03Ch,0E1h,075h\n\tDB  005h,0C6h,006h,05Eh,002h,003h,080h,03Eh,05Eh,002h,000h,074h,00Fh,0FEh,00Eh\n\tDB  05Eh,002h,0F7h,0C2h,080h,000h,00Fh,085h,088h,001h,0E9h,097h,001h,03Ch,0E0h\n\tDB  075h,008h,0C6h,006h,05Dh,002h,001h,0E9h,079h,001h,0A8h,080h,074h,007h,032h\n\tDB  0DBh,024h,07Fh,080h,0CCh,008h,080h,03Eh,05Dh,002h,000h,074h,023h,0C6h,006h\n\tDB  05Dh,002h,000h,0C6h,006h,0B7h,002h,001h,0BFh,084h,000h,0B9h,010h,000h,0F2h\n\tDB  0AEh,0E3h,002h,0EBh,003h,0E9h,060h,001h,08Ah,045h,00Fh,0C6h,006h,0B7h,002h\n\tDB  000h,0EBh,011h,03Ch,07Ah,075h,004h,0B0h,080h,0EBh,009h,08Bh,0F8h,083h,0E7h\n\tDB  07Fh,08Ah,085h,0C0h,001h,0F6h,006h,041h,002h,001h,075h,01Bh,0F6h,006h,040h\n\tDB  002h,004h,074h,017h,03Ch,05Ah,075h,010h,080h,03Eh,0B5h,000h,001h,074h,009h\n\tDB  0F7h,0C2h,080h,000h,075h,003h,0E9h,023h,001h,080h,0CCh,002h,0F6h,006h,040h\n\tDB  002h,050h,074h,003h,080h,0CCh,004h,050h,00Eh,0E8h,059h,0FCh,083h,0C4h,002h\n\tDB  0F6h,006h,03Eh,002h,010h,075h,007h,0F6h,006h,040h,002h,002h,074h,003h,080h\n\tDB  0CCh,001h,08Bh,0F8h,083h,0E7h,07Fh,0D1h,0EFh,0D1h,0EFh,0D1h,0EFh,08Bh,0D8h\n\tDB  083h,0E3h,07Fh,080h,0E3h,007h,08Ah,0AFh,034h,000h,0F7h,006h,0BEh,001h,001h\n\tDB  000h,074h,009h,084h,0ADh,019h,002h,074h,003h,080h,0F4h,001h,0F7h,006h,0BEh\n\tDB  001h,002h,000h,074h,009h,084h,0ADh,029h,002h,074h,003h,080h,0F4h,001h,088h\n\tDB  026h,06Ah,002h,066h,083h,03Eh,0EAh,002h,001h,075h,01Bh,03Dh,073h,000h,074h\n\tDB  00Ah,03Dh,076h,000h,072h,00Eh,03Dh,078h,000h,077h,009h,066h,0C7h,006h,0EAh\n\tDB  002h,000h,000h,000h,000h,0E9h,08Bh,000h,03Dh,07Dh,000h,075h,00Ch,066h,0C7h\n\tDB  006h,0EAh,002h,001h,000h,000h,000h,0E9h,08Ch,000h,03Dh,068h,006h,074h,075h\n\tDB  03Dh,04Ch,006h,074h,070h,03Dh,030h,002h,074h,005h,03Dh,07Eh,002h,075h,006h\n\tDB  0C7h,006h,008h,000h,001h,000h,03Dh,020h,004h,075h,00Ch,050h,0A1h,000h,000h\n\tDB  035h,001h,000h,050h,083h,0C4h,002h,058h,03Dh,034h,004h,075h,00Ch,050h,0A1h\n\tDB  002h,000h,035h,001h,000h,050h,083h,0C4h,002h,058h,050h,00Eh,0E8h,0FAh,0FBh\n\tDB  058h,03Ch,06Eh,075h,00Dh,083h,03Eh,082h,000h,000h,074h,006h,050h,0FFh,01Eh\n\tDB  080h,000h,058h,0BFh,05Fh,002h,0B9h,00Ah,000h,0F2h,0AEh,00Bh,0C9h,075h,01Bh\n\tDB  0BFh,03Ch,000h,0B9h,022h,000h,0D1h,0E9h,0F2h,0AFh,0E3h,009h,08Bh,05Dh,020h\n\tDB  023h,0DAh,074h,002h,0EBh,006h,0F7h,0C2h,004h,000h,074h,012h,05Eh,007h,05Ah\n\tDB  01Fh,05Fh,059h,05Bh,058h,02Eh,0FFh,006h,059h,002h,02Eh,0FFh,02Eh,0BAh,002h\n\tDB  0E4h,061h,08Ah,0E0h,00Ch,080h,0E6h,061h,086h,0E0h,0E6h,061h,0B8h,040h,000h\n\tDB  08Eh,0C0h,026h,0A0h,096h,000h,024h,0FDh,026h,0A2h,096h,000h,0B0h,020h,0E6h\n\tDB  020h,05Eh,007h,05Ah,01Fh,05Fh,059h,05Bh,058h,0CFh,09Ch,050h,006h,0B8h,000h\n\tDB  0B0h,08Eh,0C0h,026h,0FEh,006h,000h,000h,007h,058h,09Dh,0CFh,09Ch,00Eh,0E8h\n\tDB  097h,0FDh,0CBh,050h,053h,051h,052h,01Eh,08Ch,0C8h,08Eh,0D8h,080h,03Eh,0F7h\n\tDB  002h,000h,075h,01Dh,083h,03Eh,003h,003h,000h,075h,00Ch,0B8h,000h,000h,050h\n\tDB  00Eh,0FFh,016h,051h,003h,083h,0C4h,002h,083h,006h,003h,003h,001h,083h,016h\n\tDB  003h,003h,000h,01Fh,05Ah,059h,05Bh,058h,0CBh,0C8h,004h,000h,000h,050h,053h\n\tDB  051h,052h,056h,057h,01Eh,006h,08Ch,0C8h,08Eh,0D8h,080h,03Eh,0F7h,002h,000h\n\tDB  075h,050h,083h,03Eh,003h,003h,000h,074h,049h,0FFh,00Eh,003h,003h,083h,03Eh\n\tDB  003h,003h,000h,075h,03Eh,08Bh,00Eh,03Fh,003h,08Bh,016h,043h,003h,0A1h,0ABh\n\tDB  002h,089h,046h,0FEh,08Bh,01Eh,0B1h,002h,089h,05Eh,0FCh,0A3h,02Fh,003h,089h\n\tDB  01Eh,033h,003h,089h,00Eh,037h,003h,089h,016h,03Bh,003h,0B8h,001h,000h,050h\n\tDB  00Eh,0FFh,016h,051h,003h,083h,0C4h,002h,0FFh,076h,0FCh,0FFh,076h,0FEh,00Eh\n\tDB  0FFh,016h,053h,003h,083h,0C4h,004h,007h,01Fh,05Fh,05Eh,05Ah,059h,05Bh,058h\n\tDB  0C9h,0CBh,0C8h,002h,000h,000h,053h,08Ch,0C8h,08Eh,0D8h,0C7h,046h,0FEh,02Dh\n\tDB  000h,08Bh,05Eh,006h,08Bh,0C3h,032h,01Eh,0F6h,002h,074h,029h,0A2h,0F6h,002h\n\tDB  0F6h,0C3h,002h,074h,00Eh,0C7h,046h,0FEh,042h,000h,0A8h,002h,075h,005h,081h\n\tDB  04Eh,0FEh,000h,008h,0F6h,0C3h,001h,074h,00Eh,0C7h,046h,0FEh,041h,000h,0A8h\n\tDB  001h,075h,005h,081h,04Eh,0FEh,000h,008h,08Bh,046h,0FEh,05Bh,0C9h,0CBh,0C8h\n\tDB  004h,000h,000h,050h,053h,051h,052h,01Eh,056h,006h,057h,089h,05Eh,0FCh,089h\n\tDB  046h,0FEh,08Ch,0C8h,08Eh,0D8h,080h,03Eh,0F7h,002h,000h,00Fh,085h,0F9h,000h\n\tDB  080h,03Eh,0F8h,002h,000h,00Fh,084h,0F0h,000h,08Bh,046h,0FEh,025h,01Eh,000h\n\tDB  075h,009h,083h,03Eh,0A9h,002h,000h,00Fh,085h,0DFh,000h,083h,03Eh,0F9h,002h\n\tDB  001h,075h,002h,0D1h,0E9h,03Bh,00Eh,049h,003h,072h,005h,08Bh,00Eh,049h,003h\n\tDB  049h,03Bh,016h,04Dh,003h,072h,005h,08Bh,016h,04Dh,003h,04Ah,089h,00Eh,0ABh\n\tDB  002h,089h,016h,0B1h,002h,066h,0F7h,006h,004h,000h,000h,010h,000h,000h,075h\n\tDB  012h,0FFh,076h,0FCh,00Eh,0E8h,046h,0FFh,083h,0C4h,002h,050h,00Eh,0E8h,00Ah\n\tDB  0FAh,083h,0C4h,002h,083h,03Eh,0A9h,002h,000h,00Fh,085h,092h,000h,083h,03Eh\n\tDB  0FBh,002h,000h,074h,019h,08Bh,0C1h,08Bh,0CAh,02Bh,006h,0FFh,002h,08Bh,01Eh\n\tDB  0FBh,002h,099h,0F7h,0FBh,0F7h,0EBh,003h,006h,0FFh,002h,08Bh,0D1h,08Bh,0C8h\n\tDB  083h,03Eh,0FDh,002h,000h,074h,015h,08Bh,0C2h,02Bh,006h,001h,003h,08Bh,01Eh\n\tDB  0FDh,002h,099h,0F7h,0FBh,0F7h,0EBh,003h,006h,001h,003h,08Bh,0D0h,083h,03Eh\n\tDB  003h,003h,000h,075h,047h,039h,00Eh,007h,003h,075h,006h,039h,016h,009h,003h\n\tDB  074h,03Bh,0A1h,00Bh,003h,025h,000h,0C0h,03Dh,000h,0C0h,074h,00Ch,00Eh,0E8h\n\tDB  030h,0FEh,0F7h,006h,00Bh,003h,000h,080h,074h,020h,03Bh,00Eh,00Dh,003h,072h\n\tDB  01Ah,03Bh,00Eh,015h,003h,077h,014h,03Bh,016h,011h,003h,072h,00Eh,03Bh,016h\n\tDB  019h,003h,077h,008h,081h,00Eh,00Bh,003h,000h,040h,0EBh,004h,00Eh,0E8h,037h\n\tDB  0FEh,089h,00Eh,007h,003h,089h,016h,009h,003h,05Fh,007h,05Eh,01Fh,05Ah,059h\n\tDB  05Bh,058h,0C9h,0CBh,0C8h,00Ch,000h,000h,050h,053h,051h,052h,057h,056h,01Eh\n\tDB  006h,08Ch,0C8h,08Eh,0D8h,0FCh,0A1h,02Fh,003h,08Bh,01Eh,033h,003h,02Bh,006h\n\tDB  027h,003h,02Bh,01Eh,02Bh,003h,089h,046h,0FEh,089h,05Eh,0FCh,003h,006h,037h\n\tDB  003h,003h,01Eh,03Bh,003h,089h,046h,0FAh,089h,05Eh,0F8h,0C7h,046h,0F6h,000h\n\tDB  000h,0A1h,023h,003h,089h,046h,0F4h,033h,0C0h,033h,0D2h,08Bh,04Eh,0FEh,08Bh\n\tDB  05Eh,0FAh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh\n\tDB  0FAh,02Bh,00Eh,049h,003h,02Bh,01Eh,049h,003h,049h,04Bh,003h,0C9h,013h,0C0h\n\tDB  003h,0DBh,013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,003h,0C9h,013h,0C0h,003h\n\tDB  0DBh,013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,02Bh,00Eh,04Dh,003h,02Bh,01Eh\n\tDB  04Dh,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,034h,005h,080h\n\tDB  0F2h,005h,08Ah,0E0h,084h,0D0h,00Fh,085h,0AEh,000h,00Ah,0C2h,074h,040h,0F6h\n\tDB  0C4h,008h,074h,00Dh,08Bh,05Eh,0FEh,0F7h,0DBh,089h,05Eh,0F6h,0C7h,046h,0FEh\n\tDB  000h,000h,0F6h,0C4h,002h,074h,013h,052h,08Bh,046h,0FCh,0F7h,0D8h,0F7h,026h\n\tDB  037h,003h,001h,046h,0F4h,0C7h,046h,0FCh,000h,000h,05Ah,0F6h,0C2h,004h,074h\n\tDB  006h,0A1h,049h,003h,089h,046h,0FAh,0F6h,0C2h,001h,074h,006h,0A1h,04Dh,003h\n\tDB  089h,046h,0F8h,0B8h,000h,0A0h,08Eh,0C0h,08Bh,046h,0FCh,0F7h,026h,049h,003h\n\tDB  08Bh,016h,049h,003h,08Bh,0F8h,003h,07Eh,0FEh,08Bh,01Eh,03Fh,003h,0C5h,036h\n\tDB  023h,003h,08Bh,076h,0F4h,003h,076h,0F6h,08Bh,046h,0FAh,08Bh,04Eh,0F8h,02Bh\n\tDB  046h,0FEh,07Eh,03Ch,02Bh,04Eh,0FCh,07Eh,037h,02Bh,0D0h,02Bh,0D8h,055h,083h\n\tDB  07Eh,006h,000h,075h,018h,08Bh,0E9h,08Bh,0C8h,0F3h,0A4h,003h,0F3h,003h,0FAh\n\tDB  04Dh,075h,0F5h,05Dh,007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,087h\n\tDB  0F7h,08Bh,0E9h,006h,01Eh,007h,01Fh,08Bh,0C8h,0F3h,0A4h,003h,0F2h,003h,0FBh\n\tDB  04Dh,075h,0F5h,05Dh,007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,0C8h\n\tDB  00Ch,000h,000h,050h,053h,051h,052h,057h,056h,01Eh,006h,08Ch,0C8h,08Eh,0D8h\n\tDB  08Bh,046h,006h,08Bh,05Eh,008h,02Bh,006h,027h,003h,02Bh,01Eh,02Bh,003h,089h\n\tDB  046h,0FEh,089h,05Eh,0FCh,003h,006h,03Fh,003h,003h,01Eh,043h,003h,089h,046h\n\tDB  0FAh,089h,05Eh,0F8h,0C7h,046h,0F6h,000h,000h,0C4h,006h,01Dh,003h,089h,046h\n\tDB  0F4h,033h,0C0h,033h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,003h,0C9h,013h,0C0h\n\tDB  003h,0DBh,013h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,02Bh,00Eh,049h,003h,02Bh\n\tDB  01Eh,049h,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh\n\tDB  0FCh,08Bh,05Eh,0F8h,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FCh\n\tDB  08Bh,05Eh,0F8h,02Bh,00Eh,04Dh,003h,02Bh,01Eh,04Dh,003h,049h,04Bh,003h,0C9h\n\tDB  013h,0C0h,003h,0DBh,013h,0D2h,034h,005h,080h,0F2h,005h,08Ah,0E0h,084h,0D0h\n\tDB  00Fh,085h,093h,000h,00Ah,0C2h,074h,042h,0F6h,0C4h,008h,074h,00Dh,08Bh,05Eh\n\tDB  0FEh,0F7h,0DBh,089h,05Eh,0F6h,0C7h,046h,0FEh,000h,000h,0F6h,0C4h,002h,074h\n\tDB  013h,052h,08Bh,046h,0FCh,0F7h,0D8h,0F7h,026h,03Fh,003h,001h,046h,0F4h,0C7h\n\tDB  046h,0FCh,000h,000h,05Ah,0F6h,0C2h,004h,074h,007h,08Bh,01Eh,049h,003h,089h\n\tDB  05Eh,0FAh,0F6h,0C2h,001h,074h,007h,08Bh,01Eh,04Dh,003h,089h,05Eh,0F8h,08Bh\n\tDB  046h,0FCh,0F7h,026h,049h,003h,08Bh,016h,049h,003h,08Bh,0F8h,003h,07Eh,0FEh\n\tDB  08Bh,01Eh,03Fh,003h,08Bh,076h,0F4h,003h,076h,0F6h,0B8h,000h,0A0h,08Eh,0D8h\n\tDB  08Bh,046h,0FAh,08Bh,04Eh,0F8h,02Bh,046h,0FEh,07Eh,023h,02Bh,04Eh,0FCh,07Eh\n\tDB  01Eh,02Bh,0D0h,02Bh,0D8h,08Ah,0E0h,026h,08Ah,02Ch,066h,046h,00Ah,0EDh,074h\n\tDB  002h,088h,02Dh,047h,0FEh,0CCh,075h,0F0h,003h,0F3h,003h,0FAh,0FEh,0C9h,075h\n\tDB  0E6h,007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,0C8h,00Ch,000h,000h\n\tDB  050h,053h,051h,052h,057h,056h,01Eh,006h,08Ch,0C8h,08Eh,0D8h,0E8h,0B7h,002h\n\tDB  089h,056h,0F2h,0FCh,0A1h,02Fh,003h,08Bh,01Eh,033h,003h,02Bh,006h,027h,003h\n\tDB  02Bh,01Eh,02Bh,003h,089h,046h,0FEh,089h,05Eh,0FCh,003h,006h,037h,003h,003h\n\tDB  01Eh,03Bh,003h,089h,046h,0FAh,089h,05Eh,0F8h,0C7h,046h,0F6h,000h,000h,0A1h\n\tDB  023h,003h,089h,046h,0F4h,033h,0C0h,033h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh\n\tDB  003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,02Bh\n\tDB  00Eh,049h,003h,02Bh,01Eh,049h,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh\n\tDB  013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,003h,0C9h,013h,0C0h,003h,0DBh,013h\n\tDB  0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,02Bh,00Eh,04Dh,003h,02Bh,01Eh,04Dh,003h\n\tDB  049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,034h,005h,080h,0F2h,005h\n\tDB  08Ah,0E0h,084h,0D0h,00Fh,085h,0C7h,000h,00Ah,0C2h,074h,040h,0F6h,0C4h,008h\n\tDB  074h,00Dh,08Bh,05Eh,0FEh,0F7h,0DBh,089h,05Eh,0F6h,0C7h,046h,0FEh,000h,000h\n\tDB  0F6h,0C4h,002h,074h,013h,052h,08Bh,046h,0FCh,0F7h,0D8h,0F7h,026h,037h,003h\n\tDB  001h,046h,0F4h,0C7h,046h,0FCh,000h,000h,05Ah,0F6h,0C2h,004h,074h,006h,0A1h\n\tDB  049h,003h,089h,046h,0FAh,0F6h,0C2h,001h,074h,006h,0A1h,04Dh,003h,089h,046h\n\tDB  0F8h,0B8h,000h,0A0h,08Eh,0C0h,08Bh,046h,0FCh,0F7h,026h,049h,003h,003h,046h\n\tDB  0FEh,083h,0D2h,000h,08Bh,0F8h,0E8h,0F1h,001h,08Bh,016h,049h,003h,08Bh,01Eh\n\tDB  03Fh,003h,0C5h,036h,023h,003h,08Bh,076h,0F4h,003h,076h,0F6h,08Bh,046h,0FAh\n\tDB  08Bh,04Eh,0F8h,02Bh,046h,0FEh,07Eh,04Fh,02Bh,04Eh,0FCh,07Eh,04Ah,02Bh,0D0h\n\tDB  02Bh,0D8h,083h,07Eh,006h,000h,075h,021h,08Ah,0E0h,08Ah,02Ch,026h,088h,02Dh\n\tDB  046h,047h,075h,003h,0E8h,0D9h,001h,0FEh,0CCh,075h,0F0h,003h,0F3h,003h,0FAh\n\tDB  073h,003h,0E8h,0CCh,001h,0FEh,0C9h,075h,0E1h,0EBh,01Fh,08Ah,0E0h,026h,08Ah\n\tDB  02Dh,088h,02Ch,046h,047h,075h,003h,0E8h,0B8h,001h,0FEh,0CCh,075h,0F0h,003h\n\tDB  0F3h,003h,0FAh,073h,003h,0E8h,0ABh,001h,0FEh,0C9h,075h,0E1h,08Bh,056h,0F2h\n\tDB  0E8h,06Ch,001h,007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,0C8h,00Eh\n\tDB  000h,000h,050h,053h,051h,052h,057h,056h,01Eh,006h,08Ch,0C8h,08Eh,0D8h,0E8h\n\tDB  03Eh,001h,089h,056h,0F2h,08Bh,046h,006h,08Bh,05Eh,008h,02Bh,006h,027h,003h\n\tDB  02Bh,01Eh,02Bh,003h,089h,046h,0FEh,089h,05Eh,0FCh,003h,006h,03Fh,003h,003h\n\tDB  01Eh,043h,003h,089h,046h,0FAh,089h,05Eh,0F8h,0C7h,046h,0F6h,000h,000h,0C4h\n\tDB  006h,01Dh,003h,089h,046h,0F4h,033h,0C0h,033h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh\n\tDB  0FAh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh\n\tDB  02Bh,00Eh,049h,003h,02Bh,01Eh,049h,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h\n\tDB  0DBh,013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,003h,0C9h,013h,0C0h,003h,0DBh\n\tDB  013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,02Bh,00Eh,04Dh,003h,02Bh,01Eh,04Dh\n\tDB  003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,034h,005h,080h,0F2h\n\tDB  005h,08Ah,0E0h,084h,0D0h,00Fh,085h,0A0h,000h,00Ah,0C2h,074h,040h,0F6h,0C4h\n\tDB  008h,074h,00Dh,08Bh,05Eh,0FEh,0F7h,0DBh,089h,05Eh,0F6h,0C7h,046h,0FEh,000h\n\tDB  000h,0F6h,0C4h,002h,074h,013h,052h,08Bh,046h,0FCh,0F7h,0D8h,0F7h,026h,03Fh\n\tDB  003h,001h,046h,0F4h,0C7h,046h,0FCh,000h,000h,05Ah,0F6h,0C2h,004h,074h,006h\n\tDB  0A1h,049h,003h,089h,046h,0FAh,0F6h,0C2h,001h,074h,006h,0A1h,04Dh,003h,089h\n\tDB  046h,0F8h,08Bh,046h,0FCh,0F7h,026h,049h,003h,003h,046h,0FEh,083h,0D2h,000h\n\tDB  08Bh,0F8h,0E8h,07Eh,000h,08Bh,016h,049h,003h,08Bh,01Eh,03Fh,003h,08Bh,076h\n\tDB  0F4h,003h,076h,0F6h,0B8h,000h,0A0h,08Eh,0D8h,08Bh,046h,0FAh,08Bh,04Eh,0F8h\n\tDB  02Bh,046h,0FEh,07Eh,02Ch,02Bh,04Eh,0FCh,07Eh,027h,02Bh,0D0h,02Bh,0D8h,08Ah\n\tDB  0E0h,026h,08Ah,02Ch,046h,00Ah,0EDh,074h,002h,088h,02Dh,047h,075h,003h,0E8h\n\tDB  067h,000h,0FEh,0CCh,075h,0ECh,003h,0F3h,003h,0FAh,073h,003h,0E8h,05Ah,000h\n\tDB  0FEh,0C9h,075h,0DDh,08Bh,056h,0F2h,0E8h,01Bh,000h,007h,01Fh,05Eh,05Fh,05Ah\n\tDB  059h,05Bh,058h,0C9h,0CBh,050h,053h,0B8h,005h,04Fh,0B7h,001h,0B3h,000h,02Eh\n\tDB  0FFh,01Eh,05Dh,003h,05Bh,058h,0C3h,050h,053h,052h,0B8h,005h,04Fh,0B7h,000h\n\tDB  0B3h,000h,02Eh,0FFh,01Eh,05Dh,003h,05Ah,05Bh,058h,0C3h,050h,053h,052h,08Bh\n\tDB  0DAh,0C1h,0E3h,002h,02Eh,089h,01Eh,089h,003h,02Eh,08Bh,097h,061h,003h,0B8h\n\tDB  005h,04Fh,0B7h,000h,0B3h,000h,02Eh,0FFh,01Eh,05Dh,003h,05Ah,05Bh,058h,0C3h\n\tDB  050h,053h,052h,02Eh,08Bh,01Eh,089h,003h,083h,0C3h,004h,02Eh,089h,01Eh,089h\n\tDB  003h,02Eh,08Bh,097h,061h,003h,0B8h,005h,04Fh,0B7h,000h,0B3h,000h,02Eh,0FFh\n\tDB  01Eh,05Dh,003h,05Ah,05Bh,058h,0C3h\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/KEYSTRUC.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : KEYSTRUC.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 13, 1994                            *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nSTRUC\tKeyboardType\n\tSoundOn\t\t\tDW\t?\t; toggled by alt S\n\tMusicOn\t\t\tDW\t?\t; toggled by alt M\n\tKeyFlags\t\t\tDD\t?\t; all but repeat for now\n\tBreak\t\t\t\tDW\t?\n\tKeyMouseMove\tDB\t6  DUP(?)\n\tScreenEdge\t\tDW\t18 DUP (?)\n\tBits\t\t\t\tDB\t8  DUP (?)\n\tCondPassKey\t\tDW\t17 DUP (?) \n\tCondPassCond\tDW\t17 DUP (?)\n\tEscRoutine\t\tDD\t?\n\tExtCodes\t\t\tDB\t16 DUP (?)\n\tExtNums\t\t\tDB\t16 DUP (?)\n\tExtRemap\t\t\tDB\t16 DUP (?)\n\tExtRemapEnd\t\tDB\t?\n\tExtKeyboard\t\tDB\t?\n\tKeyBuffer\t\tDW\t128 DUP(?) ; set to empty\n\tKeyBufferHead\tDD\t?\t; set to first entry\n\tKeyBufferTail\tDD\t?\t; set to head for empty buffer\n\tKeyLock\t\t\tDW\t?\t; num and caps lock bits\n\tKeyNums\t\t\tDB\t89 DUP (?)\n\tKeysCapsLock\tDB\t16 DUP (?)\n\tKeysNumLock\t\tDB\t16 DUP (?)\n\tKeysUpDown\t\tDB\t16 DUP (?)\n\tKeyStream\t\tDB\t16 DUP (?)\n\tPassCount\t\tDW\t?\n\tKeyStreamIndex\tDW\t?\n\tLastKeyE0\t\tDB\t?\n\tLastKeyE1\t\tDB\t?\n\tPassAlways\t\tDB\t10 DUP (?)\n\tPassAlwaysEnd\tDB\t?\t\t; invalid code to END PassAlways\n\tCtrlFlags\t\tDB\t?\n\tBuffer\t\t\tDW\t?\n\tTime\t\t\t\tDW\t?\n\tXYAdjust\t\t\tDB\t26 DUP (?)\n\tEdgeConv\t\t\tDW\t16 DUP (?)\n\tMouseUpdate\t\tDW\t?\n\tMouseX\t\t\tDD\t?\n\tLocalMouseX\t\tDW\t?\n\tMouseY\t\t\tDD\t?\n\tLocalMouseY\t\tDW\t?\n\tIsExtKey\t\t\tDB\t?\n\tExtIndex\t\t\tDW\t?\n\n\tKeyOldRMI\t\t\tDD\t?\t; The origianl RM interrupt seg:off.\n\tKeyOldPMIOffset\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tKeyOldPMISelector\tDD\t?\t; The original PM interrupt segment.\n\n\tKeyCodeOffset\t\t\tDW\t?\t; Offset of the code in the RM stuff.\n\tCallKeyRMIntOffset\tDW\t?\t; Offset of function to call DOS timer interrupt.\n\tCallKeyRMIntAddr\t\tDD\t?\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedKeyInt\t\t\tDD\t?\t; did Protected mode pass this through?\n\n\tBrkOldRMI\t\t\t\tDD\t?\t; The origianl RM interrupt seg:off.\n\tBrkOldPMIOffset\t\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tBrkOldPMISelector\t\tDD\t?\t; The original PM interrupt segment.\n\n\tBrkCodeOffset\t\t\tDW\t?\t; Offset of the code in the RM stuff.\n\tCallBrkRMIntOffset\tDW\t?\t; Offset of function to call DOS timer interrupt.\n\tCallBrkRMIntAddr\t\tDD\t?\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedBrkInt\t\t\tDD\t?\t; did Protected mode pass this through?\n\tKeyIntDisabled\t\t\tDD\t?\n\n\tDbgOldPMIOffset\t\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tDbgOldPMISelector\t\tDD\t?\t; The original PM interrupt segment.\n\n\t;---------------------------------------------------------------------------\n\t; Begin definition of Mouse Specific Variables for real mode\n\t;---------------------------------------------------------------------------\n\tButton\t\t\t\tDB\t?\t; current value of the mouse button\n\tMDisabled\t\t\tDB\t?\t; Is the mouse driver disabled\n\tMInput\t\t\t\tDB\t?\t; Defaults to mouse input allowed.\n\tAdjust\t\t\t\tDW\t?\t; flag to adjust coordinates if necessary\n\tMouseStepX\t\t\tDW\t?\t; step values if the mouse moves at\n\tMouseStepY\t\t\tDW\t?\t;   more than one pixel at a time\n\tMouseOffsetX\t\tDW\t?\t; Fractional step values used if a mouse\n\tMouseOffsetY\t\tDW\t?\t;   moves at less than one pixel at a time\n\tMState\t\t\t\tDD\t?\t; Tracks if mouse is hidden (TRUE) or not (FALSE)\n\tMouseXOld     \t\tDW\t?\t; Holds last MouseX and MouseY to determine if \n\tMouseYOld     \t\tDW\t?\t;   mouse needs to be redrawn\n\tMCState\t\t\t\tDW\t?\t; Tracks if mouse conditional hidden (TRUE) or not\n\tMouseCXLeft\t\t\tDD\t?\t; Conditional hide mouse left x position\n\tMouseCYUpper\t\tDD\t?\t; Conditional hide mouse top y position\n\tMouseCXRight\t\tDD\t?\t; Conditional hide mouse right x position\n\tMouseCYLower\t\tDD\t?\t; Conditional hide mouse lower y position\n\tMouseCursor   \t\tDD\t?\t; Pointer to the mouse cursor to draw\n\tMouseCursorSize\tDW\t?\t; Size of mouse cursor draw area\n\tMouseBuffer   \t\tDD\t?\t; Pointer to buffer mouse is saved in\n\tMouseXHot     \t\tDD\t?\t; Offset to mouse's x hot spot\n\tMouseYHot     \t\tDD\t?\t; Offset to mouse's y hot spot\n\tMouseBuffX\t\t\tDD\t?\t; X position background was saved at\n\tMouseBuffY\t\t\tDD\t?\t; Y position background was saved at\n\tMouseBuffW\t\t\tDD\t?\t; Width of the region saved for mouse\n\tMouseBuffH\t\t\tDD\t?\t; Height of the region saved for mouse\n\tMouseWidth\t\t\tDD\t?\t; Mouse cursor theoretical width\n\tMouseHeight\t\t\tDD\t?\t; Mouse cursor theoretical height\n\tMouseCodeOffset\tDW\t?\t; Offset to the real mode code offset\n\tMouseRight\t\t\tDD\t?\t; Right hand side of the screen\n\tMouseBottom\t\t\tDD\t?\t; Bottom of the screen\n\n\n\tShadowPtr\t\t\tdw\t?\n\tDrawMousePtr \t\tdw\t?\n\n\tVGAMouseDraw\t\tdw\t?\n\tVGAMouseShadow\t\tdw\t?\n\n\tVESAMouseDraw\t\tdw\t?\n\tVESAMouseShadow\tdw\t?\n\n\tVesaPtr\t\t\t\tdd ?\t\n\tVesaBankTable\t   DD\t8 dup (?)\n\tAdjust_XPos\t\t\tdd ?\n\tAdjust_YPos\t\t\tdd ?\n\n\nENDS\n\n; InitFlags that are set to have a fully functional interrupt.\nIF_ALLOC_RM\t\t\tequ\t1\t\t; Allocation of RM was successful.\nIF_SET_VECTORS\t\tequ\t2\t\t; Vectors have been set.\nIF_LOCKED_PM_CODE\tequ\t4\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t8\t\t; Locked PM code for DPMI.\nIF_RATE_CHANGE\t\tequ\t10\t\t; Timer rate was changed.\nIF_FUNCTIONAL\t\tequ\t20\t\t; Timer is in and functional.\nIF_LOCKED_RM_CODE\tequ\t40\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = keyboard\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\t\t\t\t\tkeyboard.obj\t\t&\n\t\t\t\t\tmouse.obj\t\t\t&\n\t\t\t\t\twwmouse.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/MAKEFILE.BAK",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = keyboard\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\t\t\t\t\tkeyboard.obj\t\t&\n\t\t\t\t\tmouse.obj\t\t\t&\n\t\t\t\t\twwmouse.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = keyboard\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t   keyboard.obj\t\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) \n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n -+keyboard.obj\n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = keyboard\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\t\t\t\t\tkeyboard.obj\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WWLIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include \n\t copy *.inc $(%WIN32LIB)\\include \n\t copy *.cpp $(%WIN32LIB)\\srcdebug \n\t copy *.asm $(%WIN32LIB)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/MOUSE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*\t\t\t\t  (Mouse Routines)\t\t\t   *\n;*                                                                         *\n;*                    File Name : MOUSE.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : August 26, 1994                          *\n;*                                                                         *\n;*                  Last Update : November 3, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Install_Mouse -- Initializes mouse driver and verifies mouse exists   *\n;*   Remove_Mouse -- uninstalls the mouse interrupt by disabling the call  *\n;*   Get_Mouse_X -- Returns the mouses x pixel position                    *\n;*   Get_Mouse_Y -- Returns the mouse's y pixel position                   *\n;*   Get_Mouse_Button -- Gets the values of the mouse button               *\n;*   Set_Mouse_Cursor -- Sets the shape to be used as the mouse.           *\n;*   Low_Hide_Mouse -- Low-level routine which hides the mouse\t\t   *\n;*   Low_Show_Mouse -- Low level routine which shows the mouse\t\t   *\n;*   Mouse_Shadow_Buffer -- Handles storing and restoring the mouse buffer *\n;*   Draw_Mouse -- Handles drawing the mouse cursor\t\t\t   *\n;*   Hide_Mouse -- Hides mouse cursor on screen if it was show             *\n;*   Show_Mouse -- Display mouse cursor on screen if it was hidden         *\n;*   Conditional_Hide_Mouse -- Hides mouse if its with given region        *\n;*   Conditional_Show_Mouse -- shows mouse if it was conditionally hidden  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\n;WARN\t\t\t\t; generate all warnings we can\n;JUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keystruc.inc\"\nINCLUDE \"shape.inc\"\ninclude \"svgaprim.inc\"\n\nDOS_SYS_CALL\t\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nRESTORE_VISIBLE_PAGE\tEQU\t0\nSTORE_VISIBLE_PAGE\tEQU\t1\nCONDHIDE\t\tEQU\t08000H\t\t; bit for testing conditional region\nCONDHIDDEN\t\tEQU\t04000H\t\t; bit for testing conditional hidden\n;---------------------------------------------------------------------------\n; Define any data which needs to be global...\n;---------------------------------------------------------------------------\n\nGLOBAL\tRealModePtr:DWORD\nGLOBAL\tMInstalled:DWORD\nGLOBAL\tMouseBuffer:DWORD\nGLOBAL\tLCW_Uncompress:NEAR\n\nGLOBAL\tGet_Shape_Uncomp_Size     :NEAR\nGLOBAL\tGet_Shape_Width      \t  :NEAR\nGLOBAL\tGet_Shape_Original_Height :NEAR\nGLOBAL  Size_Of_Region\t\t  :NEAR\nGLOBAL\t_ShapeBuffer\t\t  :DWORD\n\nGLOBAL  XRes\t: dword\nGLOBAL  YRes\t: dword\n\n\nGLOBAL\tVesaFunc : dword\nGLOBAL\tVesa_XRes : near\nGLOBAL\tVesa_YRes : near\n\n\n\n\n\nDPMI_INTR\tEQU\t31h\t\n\n\nSTRUC DPMI_REGS\n       _edi  dd ?\n       _esi  dd ?\t\n       _ebp  dd ?\t\n       \t     dd ?\n       _ebx  dd ?\t\n       _edx  dd ?\t\n       _ecx  dd ?\t\n       _eax  dd ?\t\n       Flags dw ?\n       _es   dw ?\n       _ds   dw ?\n       _fs   dw ?\n       _gs   dw ?\n       _ip   dw ?\n       _cs   dw ?\n       _sp   dw ?\n       _ss   dw ?\n       \t     dd ?\n\t     dd ?\n  nothing    dd ?\t\t\t\nENDS\n\n\n\n;---------------------------------------------------------------------------\n; Now lets handle any data in the data segment\n;---------------------------------------------------------------------------\n\tDATASEG\n\nRealInt\t\tDPMI_REGS <>\t; structure to call a real mode int\nMInstalled\tDD\t0\t\t; is the mouse installed?\nMouseCursor\tDD\t0\nMouseBuffer\tDD\t0\nBufferWidth\tDD\t0\nBufferHeight\tDD\t0\nBufferSize\tDD\t0\nPrevMousePtr\tDD\t0\nMouseBufferSel\tDD\t0\n\n\nDraw_Mouse\t\tdd\tVGA_Draw_Mouse\nMouse_Shadow_Buffer\tdd\tVGA_Mouse_Shadow_Buffer\n\n;---------------------------------------------------------------------------\n; Time to write some code\n;---------------------------------------------------------------------------\n\tCODESEG\n\n;***************************************************************************\n;* INSTALL_MOUSE -- Initializes mouse driver and verifies mouse connected  *\n;*                                                                         *\n;* First check the mouse interupt to see if the vector is pointing to zero *\n;* page.  If it is not then make sure it is not pointing to an IRET.  If   *\n;* not call the mouse reset to verify that the hardware is attached.\t   *\n;*                                                                         *\n;* INPUT:\tint mouse_max_width  - the max width of the mouse cursor   *\n;*\t\tint mouse_max_height - the max height of the mouse cursor  *\n;*\t\tint screen_width     - width of the physical screen\t   *\n;*\t\tint screen_height    - height of the physical screen\t   *\n;*                                                                         *\n;* OUTPUT:      TRUE is mouse driver is initialized, FALSE if unable to    *\n;*\t\tinitialize mouse driver.\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tint Install_Mouse(\tint mouse_max_width,\t\t   *\n;*\t\t\t\t\tint mouse_max_height,\t\t   *\n;*\t\t\t\t\tint screen_width,\t\t   *\n;*\t\t\t\t\tint screen_height);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/26/1994 PWG : Created.                                             *\n;*=========================================================================*\nGLOBAL\tInstall_Mouse:NEAR\nPROC\tInstall_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tARG\tmouse_max_width:DWORD\n\tARG\tmouse_max_height:DWORD\n\tARG\tscreen_width:DWORD\n\tARG\tscreen_height:DWORD\n\n\n\t;*=========================================================================*\n\t;* Initialize all of the general mouse variables\n\t;*=========================================================================*\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\ttest\tesi , esi\t\t\t; mouse driver should be install\n\tjz \t??exit\t\t\t\t; after keyboard interrup is install\n\tmov\teax , [ XRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseX],eax\t; set the mouses x coordinate to 160\n\tmov\teax , [ YRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseY],eax\t; set the mouses y coordinate to 100\n\tmov\t[(KeyboardType esi).MState],1\t; flag the mouse as hidden\n\tmov\t[(KeyboardType esi).MCState],0\t; turn off conditional region\n\tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi).MouseRight],eax\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi).MouseBottom],eax\n\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 0200, bl = number of interrupt to get\n\t; output cf error, cx,dx= address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,033h\t\t\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\t\t\t; no mouse driver present\n\n\t;*=========================================================================*\n\t;* If the interupt vector is pointing to 0000:0000h, there is no mouse\n\t;*=========================================================================*\n\tor\tcx,dx\t\t\n\tjz\tshort ??nomouse\n\n\tand\tedx , 0ffffh\n\tand\tecx , 0ffffh\n\tshl\tecx,4\n\tadd\tecx,edx\n\n\t;*=========================================================================*\n\t;* If the first instruction is an IRET, there is no mouse\n\t;*=========================================================================*\n\n\tcmp\t[byte ptr ecx],0CFH\t; is this an IRET\n\tjne\tshort ??mouse_buff\t; if it isnt then reset the mouse\n\n??nomouse:\n\tmov\teax,FALSE\t\t\t\t; flag no mouse driver\n\tmov\t[MInstalled],FALSE\t\t\t; flag no mouse driver\n    \tjmp\t??exit\t\t\t\t\t; exit\n\n??mouse_buff:\n\t;*=========================================================================*\n\t;* Allocate two real mode memory buffers for the mouse cursor and the \n\t;*\tmouse shadow\n\t;*=========================================================================*\n\tmov\teax,[mouse_max_width]\t       \t; get the is max width\n\tmov\t[BufferWidth],eax\t       \t; save it off for set cursor\n\tmov\tedx,[mouse_max_height]\t       \t; get the max height\n\tmov\t[BufferHeight],edx\t       \t; save it off for set cursor\n\tmul\tedx\t\t\t       \t; size = max_width * max_height\n\tadd\teax,22\t\t\t       \t; add width/height(8) + para align(15)\n\tand\tal, 0f0h\t\t       \t; now size is even paragraphs\n\tmov\t[BufferSize],eax\t       \t; store off the buffer size\n\tshl\teax,1\t\t\t       \t; make two of them\n\n \tmov\tebx,eax\t\t\t\t; get size of RM binary.\n\tmov\tecx,eax\t\t\t\t; ecx will use it later.\n\tadd\tebx,15\t\t\t\t; round up \n\tshr\tebx,4\t\t\t\t; convert to pages.\n\tmov\teax,0100h\t\t\t; alloc real buffer\n\tint\tDPMI_INTR\t \t\t; do call.\n\tjc\t??error\t\t \t\t; check for error.\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tmov\t[MouseBufferSel], edx\n\tshl\teax , 16\n\tmov\t[(KeyboardType esi).MouseCursor],eax\t; store off the real mode segment\n\tmov\tedx,eax\t\t\t\t\t; get the buffer position\n\tadd\tedx,[BufferSize]\t\t\t; add in the buffer size\n\tmov\t[(KeyboardType esi).MouseBuffer],edx\t; store off the real mode segment\n\tshr\teax,12\t\t\t\t\t; convert the seg/off to 32 bit offset\n\tmov\tedx,eax\n\tadd\tedx,[BufferSize]\n\tmov\t[MouseCursor],eax\t\t\t; store it off in the mouse buffer\n\tmov\t[MouseBuffer],edx\t\t\t; store it off in the mouse buffer\n\n\tmov\teax,0600h\t\t\t\t; function number.\n\tmov\tecx,[MouseCursor]\t\t\t; ecx must have start of memory.\n\tmov\tedi,[BufferSize]\n\tshl\tedi,1\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n       \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n\n??begin:\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\t; Reset mouse thru int 33h funtion 0\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\txor\tecx , ecx\n\tmov\t[RealInt . _eax ] , 0\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\tmov\teax ,[RealInt . _eax]\n\tcmp\tax,-1\t\t\t\t\t; was the mouse attached to system\n      \tjne\t??nomouse\t\t\t\t; if not exit out of the routine\n\t\n\tmov\t[(KeyboardType esi).Adjust],0\t\t; assume we do not need to adjust mouse\n\n;***************************************************************************\n; Set the Vesa Parameters \n\n\tmov\teax , [ VesaFunc ]\n\ttest\teax , eax\n\tjz\t??set_vga_mouse\n\tmov\t[(KeyboardType esi). VesaPtr ] , eax\n\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VESA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VESA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n \tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi). MouseRight ] , eax\n\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi). MouseBottom ] , eax\n\n\tlea\tedi , [(KeyboardType esi). VesaBankTable]\n\tlea\tesi , [ BankTable ]\n\tmov\tecx , 8\n\trep\tmovsd\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tjmp\t??end_vesa\n\n??set_vga_mouse:\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VGA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VGA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n??end_vesa:\n\tcall \tReset_Mouse \n\tmov\teax , TRUE\n\tret\n\n??error:\n\tmov\teax,FALSE\n??exit:\n\tret\n\tENDP\tInstall_Mouse\n\n;***************************************************************************\n;* ResET_MOUSE -- Reset mouse to a new graphif mode\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* reset mouse driver funtions to a a currently graphic mode\t\t   *\t\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;* PROTO:\tReset_Mouse ( void ) \t\t\t\t\t   *\t\n;*\t\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/26/1994 JRJ : Created.                                             *\n;*=========================================================================*\nGLOBAL\tReset_Mouse:NEAR\nPROC\tReset_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\n\t;*=========================================================================*\n\t;* Initialize all of the general mouse variables\n\t;*=========================================================================*\n\tmov\tesi , [RealModePtr]\t\t; get offset of real mode data start\n\ttest\tesi , esi\n\tjz\t??exit\n\tmov\teax , [ XRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseX],eax\t; set the mouses x coordinate to 160\n\tmov\teax , [ YRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseY],eax\t; set the mouses y coordinate to 100\n\tmov\t[(KeyboardType esi).MState],1\t; flag the mouse as hidden\n\tmov\t[(KeyboardType esi).MCState],0\t; turn off conditional region\n\tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi).MouseRight],eax\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi).MouseBottom],eax\n\n\n\tmov\t[(KeyboardType esi).Adjust],0\t\t; assume we do not need to adjust mouse\n\n;***************************************************************************\n; Set the Vesa Parameters \n\n\tmov\teax , [ VesaFunc ]\n\ttest\teax , eax\n\tjz\t??set_vga_mouse\n\tmov\t[(KeyboardType esi). VesaPtr ] , eax\n\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VESA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VESA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n \tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi). MouseRight ] , eax\n\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi). MouseBottom ] , eax\n\n\tlea\tedi , [(KeyboardType esi). VesaBankTable]\n\tlea\tesi , [ BankTable ]\n\tmov\tecx , 8\n\trep\tmovsd\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tjmp\t??end_vesa\n\n??set_vga_mouse:\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VGA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VGA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n\n??end_vesa:\n       ; S Mickey/pixel Ratio cursor limits \n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 8\n\tmov\tedx , 16\n\tmov\t[RealInt . _eax ] , 0fh\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\t; Set Min/Max X pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 0\t \n\tmov\tedx , [ XRes ]\n\tcmp\tedx , 320\n\tjne\t??set_it\n\tshl\tedx , 1\n\tmov\t[(KeyboardType esi).Adjust],1\n\n??set_it:\n;\tdec\tedx\n\tmov\t[RealInt . _eax ] , 7\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\t; Set Min/Max Y pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 0\n\tmov\tedx , [ YRes ]\n\tdec\tedx\n\tmov\t[RealInt . _eax ] , 8\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\nIF 0\n\t; Check for scale factors in X and Y pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , [ XRes ]\n\tmov\tedx , [ YRes ]\n\tsub\tecx , 8\n\tsub  \tedx , 16\n\tmov\t[RealInt . _eax ] , 4\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\t; Read mouse position thru int 33 funtion 3\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\txor\tecx , ecx\n\tmov\t[RealInt . _eax ] , 3\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\tmov\tecx ,[RealInt . _ecx]\n\tmov\tedx ,[RealInt . _edx]\n\n      ; compute Scale values X Y for different vendor mouse driver if nessesary\n\tadd \tecx , 8\n\tadd\tedx , 16\n\tcmp\tecx , [ XRes ]\n\tmov\t[(KeyboardType esi).Adjust_XPos],0\n\tjz\t??No_scaleX\n\tmov\t[(KeyboardType esi).Adjust_XPos],ecx\n??No_scaleX:\n\tcmp\tedx , [ YRes ]\n\tmov\t[(KeyboardType esi).Adjust_YPos],0\n\tjz\t??No_scaleY\n\tmov\t[(KeyboardType esi).Adjust_YPos],edx\n??No_scaleY:\t\nENDIF\n\n\tmov\tecx, [ XRes ]\t\t\t\t; set the mouses x coordinate to 160\n\tmov\tedx, [ YRes ]\t\t\t\t; set the mouses x coordinate to 160\n\tcmp\t[(KeyboardType esi).Adjust],1\n\tje\t??no_ecx_shift\n\tshr\tecx , 1\n??no_ecx_shift:\n\tshr\tedx , 1\n\tmov\t[MInstalled],TRUE\t\t\t; set the fact that mouse is installed\n\tmov\t[(KeyboardType esi).MDisabled],TRUE\t; disable mouse until the overlay is loaded\n\n\t; Set new Mouse position any way\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\t[RealInt . _eax ] , 4\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\tcall\tClear_RM_regs\n\tmov\teax, 0300h\n\tmov\tebx ,33h\t\t\t\t; mouse is in 33h\n\tmov\tecx,0\t\t\t\t\t; any mouse condition generates int\n\tmov\tedx,[RealModePtr]\t\t\t; get real mode memory address\n\tshr\tedx,4\t\t\t\t\t; convert it to a segment\n\tmov\t[RealInt. _es],dx\t\t\t; store it in the real mode es\n\tmovzx\tedx,[(KeyboardType PTR esi).MouseCodeOffset] ; Get address of code\n\tmov\t[RealInt._edx],edx\t\t\t; set edx to offset of code\n\tmov\t[RealInt._eax],12\t\t\t; set eax to set interrupt routine\n\tmov\t[RealInt._ecx],31\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n??installed:\n\tmov\teax,TRUE  \t\t\t\t; return TRUE if all is well\n\tmov\t[(KeyboardType esi).MDisabled],FALSE\t; no 32 bit overlays installed\n\tje\t??exit\n\n??error:\n\tmov\teax,FALSE\n\n??exit:\n\tret\n\tENDP\tReset_Mouse\n\n\n\n;***************************************************************************\n;* REMOVE_MOUSE -- uninstalls the mouse interrupt by disabling the call\t   *\n;*                                                                         *\n;* This routine will uninstall the mouse interrupt.  It does this by\t   *\n;* simply disabling the call condition.  The interrupt itself is still\t   *\n;* present, just uncalled until dos removes it at program termination.\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Remove_Mouse(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tRemove_Mouse:NEAR\n\tPROC\tRemove_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\t\n\n\tcall\tClear_RM_regs\n\tcmp \t[MInstalled],FALSE\t; check to see if mouse installed\n\tje\t??exit\t\t\t; if not then no need to remove it\n\n\tmov\t[MInstalled],FALSE\t; Force to NOT-Installed.\n\n;;PWG\tcmp \t[_MSWIFTDevice],1\t; check to see if SWIFT device installed\n;;PWG\tje\tshort ??prevSWIFT\t\t; if so use previous SWIFT event handler\n\n\tmov\tebx , 033h\n\tmov\tedx,[RealModePtr]\t\t\t; get real mode memory address\n\ttest\tedx,edx\t\t\t\t\t; check that the memory block is valid\n\tjz\t??exit\n\n\tshr\tedx,4\t\t\t\t\t; convert it to a segment\n\tmov\t[RealInt._es],dx\t\t\t; store it in the real mode es\n\txor\tedx,edx\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\tmov\tdx,[(KeyboardType PTR esi).MouseCodeOffset] ; Get address of code\n\tmov\t[RealInt._edx],edx\t\t\t; set edx to offset of code\n\tmov\t[RealInt._eax],12\t\t\t; set eax to set interrupt routine\n\tmov\t[RealInt._ecx],0\n\tmov\tecx,0\t\t\t\t\t; no mouse condition generates an int\n\tmov\teax,0300h\n\tlea\tedi,[RealInt]\n\tint\tDPMI_INTR\n\n\tmov\teax,0601h\t\t\t\t; function number.\n\tmov\tecx,[MouseCursor]\t\t\t; ecx must have start of memory.\n\tmov\tedi,[BufferSize]\n\tshl\tedi,1\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n       \tint\tDPMI_INTR\t\t\t; do call.\n\n\n\t; Deallocate real memory buffer\n\tmov\tedx ,[MouseBufferSel]\n\ttest\tdx ,dx\n\tjz\t??exit\n\tmov\teax ,0101h\n\tint\tDPMI_INTR\n\n??exit:\n\tret\n\tENDP\tRemove_Mouse\n\n\n;***************************************************************************\n\nGLOBAL\tClear_RM_regs :NEAR\nPROC\tClear_RM_regs  NEAR \n\n\tpush\teax\n\tpush\tecx\n\tpush\tedi\n\tlea\tedi , [ RealInt ]\n\tlea\tecx , [ RealInt . nothing ]\n\tsub\tecx , edi\n\txor\teax , eax\n\tshr\tecx , 2\n\trep\tstosd\n\tpop\tedi\n\tpop\tecx\n\tpop\teax\n\tret\nENDP\tClear_RM_regs\n\n\n;***************************************************************************\n;* GET_MOUSE_X -- Returns the mouses x pixel position                      *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse x position in pixels\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_X(void);                                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_X:NEAR\n\tPROC\tGet_Mouse_X C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MouseX]\n\tret\n\n\tENDP\tGet_Mouse_X\n\n;***************************************************************************\n;* GET_MOUSE_STATE -- Returns the current mouse state\t\t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse's current state\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_State(void);                                 *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_State:NEAR\n\tPROC\tGet_Mouse_State C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MState]\n\tret\n\n\tENDP\tGet_Mouse_State\n\n;***************************************************************************\n;* GET_MOUSE_X -- Returns the mouses x pixel position                      *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse x position in pixels\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_X(void);                                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_Disabled:NEAR\n\tPROC\tGet_Mouse_Disabled C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmovzx\teax,[(KeyboardType esi).MDisabled]\n\tret\n\n\tENDP\tGet_Mouse_Disabled\n\t\t\t\t  \n;***************************************************************************\n;* GET_MOUSE_Y -- Returns the mouse's y pixel position                     *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:       none\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      int - the mouses y position in pixels                      *\n;*                                                                         *\n;* PROTO:\tint Get_Mouse_Y(void);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_Y:NEAR\n\tPROC\tGet_Mouse_Y C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MouseY]\n\tret\n\n\tENDP\tGet_Mouse_Y\n\n;***************************************************************************\n;* GET_MOUSE_BUTTON -- Gets the values of the mouse button                 *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_Button:NEAR\n\tPROC\tGet_Mouse_Button C NEAR \n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\n\txor\teax,eax\n\tmov\tal,[(KeyboardType esi).Button]\n\tret\n\n\tENDP\tGet_Mouse_Button\n\n;***************************************************************************\n;* SET_MOUSE_CURSOR -- Sets the shape to be used as the mouse.             *\n;*                                                                         *\n;*    This will inform the system of the shape desired as the mouse        *\n;*    cursor.                                                              *\n;*                                                                         *\n;* INPUT:    xhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           yhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           cursor      -- Shape to use as the new mouse shape.           *\n;*                                                                         *\n;* OUTPUT:   Returns with a pointer to the original mouse shape.           *\n;*                                                                         *\n;* PROTO:\tVOID  *Set_Mouse_Cursor(\tint  xhotspot, \t\t   *\n;*\t\t\t\t\t\tint  yhotspot, \t\t   *\n;*\t\t\t\t\t\tvoid *cursor);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   02/13/1992 JLB : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tSet_Mouse_Cursor:NEAR\n\tPROC\tSet_Mouse_Cursor C NEAR \n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\txhotspot:DWORD\t\t\t\t; the x hot spot of the mouse\n\tARG\tyhotspot:DWORD\t\t\t\t; the y hot spot of the mouse\n\tARG\tcursor:DWORD\t\t\t\t; ptr to the new mouse cursor\n\n\tLOCAL\tdatasize:DWORD\n\tLOCAL\tstype:WORD\n\tLOCAL\tswidth:DWORD\t\t; Shape width.\n\tLOCAL\tsheight:DWORD\t\t; Shape height.\n\tLOCAL\tssize:DWORD\t\t; Size of raw shape.\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\n\t;-------------------------------------------------------------------\n\t; Make sure the mouse is Enabled and Installed before continuing\n\t;-------------------------------------------------------------------\n\tmov\teax,[cursor]\n\tcmp\teax,0\t\t\t; if the mouse cursor is in zero page\n\tje\t??exit\t\t\t; it is completely invalid\n\n\tcmp\teax,[PrevMousePtr]\n\tje \t??exit\n\n\tcmp\t[(KeyboardType esi).MDisabled],FALSE\t; make sure the mouse is not disabled\n\tjne\t??exit\t\t\t; if it is not then give it a try\n\n\t;-------------------------------------------------------------------\n\t; We need to wait if a mouse interrupt is in progress.  Once the\n\t; interrupt is finished flag that it is occuring so that it will\n\t; not attempt to draw the mouse while we are changing the cursor.\n\t;-------------------------------------------------------------------\n??try:\n\tinc\t[(KeyboardType esi).MouseUpdate] ; flag that mouse can not be drawn\n\n\t;-------------------------------------------------------------------\n\t; If the mouse is currently on the screen hide it.\n\t;-------------------------------------------------------------------\n\tcall\tLow_Hide_Mouse\n\n\t;-------------------------------------------------------------------\n\t; Calculate the size of the buffer needed.\n\t;-------------------------------------------------------------------\n\tpush\t[cursor]\n\tcall\tGet_Shape_Uncomp_Size\n\tpop\tedx\n\tmov\t[datasize],eax\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Width\n\tpop\tedx\n\tmov\t[swidth],eax\n\tcmp\teax,[BufferWidth]\n\tjg\t??end\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Original_Height\n\tpop\tedx\n\tmov\t[sheight],eax\n\tcmp\teax,[BufferHeight]\n\tjg\t??end\n\n\n\tmov\tebx,[sheight]\n\tmov\teax,[swidth]\n\timul\tebx,eax\n\n??copy_mouse:\n\tmov\tesi,[cursor]\t\t\t; set esi to point to mouse shape\n\tmov\tax,[esi]\t\t\t; get the shape type byte\n\tmov\t[stype],ax\t\t\t; save off the shape type\n\ttest\tax,MAKESHAPE_NOCOMP\t\t; is it marked as no compression?\n\tje\t??comp_shape\t\t\t; if not go to the comped shape code\n\tmov\tedi,[MouseCursor]\t\t; set edi to point to mouse buffer\n??copy_type:\n\n\ttest\t[stype],MAKESHAPE_COMPACT\t; if the shape a 16 color shape?\n\tjne\t??16_color_copy\t\t\t; if it is then go handle it\n\n??normal_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed NORMAL shapes just get run-length uncompressed\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t\t; find size of shape in pixels\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes \n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??norm_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??norm_trans\t\t\t; if its a zero its transparent\n\tmov\t[edi],al\t\t\t; write out the pixel to dest\n\tinc\tedi\t\t\t\t; move to next dest position\n\tdec\tedx\t\t\t\t; we have now written another pix\n\tjnz\t??norm_unrle\t\t\t; if more to write then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are all done\n\n??norm_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\n\tjnz\t??norm_unrle\t\t\t; if more to do then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are done\n\n??16_color_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed 16 color shapes just get remaped and UN-RLE'd\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\tebx,esi\t\t\t\t; save of position of remap\n\tadd\tesi,16\t\t\t\t; move past remap table\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t; load up the height\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes \n\txor\teax,eax\t\t\t\t; clear high of lookup variable\n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??16_color_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??16_color_trans\t\t; if its a zero its transparent\n\tmov\tal,[ebx+eax]\t\t\t; remap the pixel from 16 color table\n\tmov\t[edi],al\t\t\t; store it out to the dest address\n\tinc\tedi\t\t\t\t; move to next dest address\n\tdec\tedx\t\t\t\t; we have now written a pixel\n\tjnz\t??16_color_unrle\n\tjmp\t??done_copy\n??16_color_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\t\t\t\t; subtract off count ahead of time\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\t\t\t\t; or edx to test for zero\n\tjnz\t??16_color_unrle\t\t\n\tjmp\t??done_copy\n\n\t;-------------------------------------------------------------------\n\t; Deal with the compressed shape by copying it into the shape\n\t;   staging buffer.\n\t;-------------------------------------------------------------------\n??comp_shape:\n\tmov\tedi,[_ShapeBuffer]\t; get a pointer to ShapeBuffer\n\tmov\tax,[esi]\t\t; load in the shape type\n\tadd\tesi,2\t\t\t; increment the shape pointer\n\tor\tax,MAKESHAPE_NOCOMP\t; make the shape as uncompressed\n\tmov\t[stype],ax\t\t; save off the shape type\n\tmov\t[edi],ax\t\t; write out uncompressed shape\n\tadd\tedi,2\n\n\t;-------------------------------------------------------------------\n\t; Process the shape header information and copy it over to the new\n\t;   location.\n\t;-------------------------------------------------------------------\n\tmov\tecx,4 \t\t\t; transfer height, width, org and\n\ttest\teax,MAKESHAPE_COMPACT\t; is it a 16 color shape?\n\tje\t??copy_head\t\t; no - don't worry about it\n\tadd\tecx,8\t\t\t; otherwise adjust ecx for header\n??copy_head:\n\trep\tmovsw\t\t\t; copy the necessary bytes\n\t\n\tmov \teax,[datasize]\t\t; get uncompressed length\n\tpush\teax\t\t\t; push as third param\n\tpush\tedi\t\t\t; push the destination offset\n\tpush\tesi\t\t\t; push the source offset\n\tcall\tLCW_Uncompress\t\t; do the uncompress\n\tpop\teax\n\tpop\teax\n\tpop\teax\n\tmov\tesi,[_ShapeBuffer]\n\tmov\tedi,[MouseCursor]\t\t; set edi to point to mouse buffer\n\tjmp\t??copy_type\n\n??done_copy:\n\tmov\tesi,[RealModePtr]\t; get offset of real mode data start\n\n\tmov\teax,[xhotspot]\t\t; get the mouse cursors x hotspot\n\tmov\t[(KeyboardType esi).MouseXHot],eax\n\tmov\teax,[yhotspot]\t\t; get the mouse cursors y hotspot\n\tmov\t[(KeyboardType esi).MouseYHot],eax\n\n\tmov\tebx,[sheight]\t\t; get shape height\n\tmov\t[(KeyboardType esi).MouseHeight],ebx\n\tmov\tebx,[swidth]\n\tmov\t[(KeyboardType esi).MouseWidth],ebx\n\n??error:\n\tcall\tLow_Show_Mouse\n\n\t;-------------------------------------------------------------------\n\t; Final cleanup and exit.\n\t;-------------------------------------------------------------------\n??end:\n\tdec\t[(KeyboardType esi).MouseUpdate]\t\t; we are done modifying the cursor\n??exit:\n\tpush\t[cursor]\n\tpush\t[PrevMousePtr]\n\tpop\teax\n\tpop\t[PrevMousePtr]\n\tret\t\t\t\t; and return back to the world\n\n\tENDP\tSet_Mouse_Cursor\n\n\n;***************************************************************************\n;* LOW_HIDE_MOUSE -- Low-level routine which hides the mouse\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Low_Hide_Mouse:NEAR\n\tPROC\tLow_Hide_Mouse C NEAR \n\tUSES\teax,ebx,esi\n\n\tmov\tebx,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\n\t;*=========================================================================*\n\t;* Is the mouse disabled or hidden?\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType ebx).MDisabled],0 \t; is the mouse disabled?\n\tjne\tshort ??end\n\n   \tcmp\t[(KeyboardType ebx).MState],0 \t; is the mouse hidden?\n\tjne\tshort ??endnodraw\t\t\t; no need to hide again\n\n\t;*=========================================================================*\n\t;* Take care of restoring the mouse cursor\n\t;*=========================================================================*\n\tmov\teax,RESTORE_VISIBLE_PAGE\n\tpush\teax\n\tcall\t[ Mouse_Shadow_Buffer]\n\tpop\teax\n\t;*=========================================================================*\n\t;* The mouse is now hidden -- again.\n\t;*=========================================================================*\n??endnodraw:\n\tadd\t[(KeyboardType ebx).MState],1\n\tadc\t[(KeyboardType ebx).MState],0\n\n??end:\n\tret\n\tENDP\tLow_Hide_Mouse\n\n;***************************************************************************\n;* LOW_SHOW_MOUSE -- Low level routine which shows the mouse\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Low_Show_Mouse:NEAR\n\tPROC\tLow_Show_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tLOCAL\tmousex:DWORD\n\tLOCAL\tmousey:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\n\t;*=========================================================================*\n\t;* Don't show the mouse if it is not hidden or it is disabled\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType esi).MDisabled],0\t; is the mouse disabled\n\tjne\t??exit\t\t\t\t\t; if so then exit\n\n\tcmp\t[(KeyboardType esi).MState],0\t; is the mouse already visible\n       \tje\t??exit\t\t\t\t\t; if so then exit\n\n\t;*=========================================================================*\n\t;* Don't show the mouse if it was hidden multiple times\n\t;*=========================================================================*\n\tdec\t[(KeyboardType esi).MState]\t\t; show the mouse one level\n\tcmp\t[(KeyboardType esi).MState],0\t; can the mouse be shown\n       \tjne\tshort ??exit\n\n\t;*=========================================================================*\n\t;* Determine the theoretcial drawing position of the mouse\n\t;*=========================================================================*\n\tmov\tecx,[(KeyboardType esi).MouseWidth]\t\t; Theoretical buffer width (pixel).\n\tmov\tedx,[(KeyboardType esi).MouseHeight]\t; Theoretical buffer height (pixel).\n\tmov\teax,[(KeyboardType esi).MouseX]\n\tmov\t[mousex],eax\t\t; Draw X pixel.\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\tmov\tebx,[(KeyboardType esi).MouseY]\n\tmov\t[mousey],ebx\t\t; Draw Y pixel.\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\t;*=========================================================================*\n\t;* Determine the theoretical coordinates and dimensions of the\n\t;*\tarea the mouse shape will be rendered upon.\n\t;*=========================================================================*\n\tmov\t[(KeyboardType esi).MouseBuffX],eax\n\tmov\t[(KeyboardType esi).MouseBuffY],ebx\n\tmov\t[(KeyboardType esi).MouseBuffW],ecx\n\tmov\t[(KeyboardType esi).MouseBuffH],edx\n\n;------\tMove the area that will be drawn upon, to the graphic buffer.\n\tmov\teax,STORE_VISIBLE_PAGE\n\tpush\teax\n\tcall\t[ Mouse_Shadow_Buffer ]\n\tpop\teax\n\n;------\tDraw the mouse shape to the seenpage.\n\tpush\t[mousey]\n\tpush\t[mousex]\n\tcall\t[ Draw_Mouse ]\n\tpop\teax\n\tpop\teax\n??exit:\n\tret\n\tENDP\tLow_Show_Mouse\n\n;***************************************************************************\n;* HIDE_MOUSE -- Hides mouse cursor on screen if it was show               *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Hide_Mouse(void);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tHide_Mouse:NEAR\n\tPROC\tHide_Mouse C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Mark us as updating the mouse and then run and do the update\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\t; were drawing the mouse\n\tcall\tLow_Hide_Mouse\t\t\t\t; make the function call\n\tdec\t[(KeyboardType esi).MouseUpdate]\t; were done drawing mouse\n\tret\n\t\n\tENDP\tHide_Mouse\n\n;----------------------------------------------------------------------------\n\n\n;***************************************************************************\n;* SHOW_MOUSE -- Display mouse cursor on screen if it was hidden           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Show_Mouse(void)                                      *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tShow_Mouse:NEAR\n\tPROC\tShow_Mouse C NEAR \n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Mark us as updating the mouse and then run and do the update\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\t; were drawing the mouse\n\tcall\tLow_Show_Mouse\t\t\t\t; make the function call\n\tdec\t[(KeyboardType esi).MouseUpdate]\t; were done drawing mouse\n\tret\n\tENDP\tShow_Mouse\n\n;***************************************************************************\n;* CONDITIONAL_HIDE_MOUSE -- Hides mouse if its with given region          *\n;*                                                                         *\n;* INPUT:\tint sx_pixel - the left-most pixel position of the region  *\n;*\t\tint sy_pixel - the upper-most pixel position of the region *\n;*\t\tint dx_pixel - the right most pixel position of the region *\n;*\t\tint dy_pixel - the lower most pixel position of the region *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Conditional_Hide_Mouse(\tint sx_pixel, \t\t   *\n;*\t\t\t\t\t\tint sy_pixel,\t\t   *\n;*\t\t\t\t\t\tint dx_pixel,\t\t   *\n;*\t\t\t\t\t\tint dy_pixel);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tConditional_Hide_Mouse:NEAR\n\tPROC\tConditional_Hide_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tARG\tsx_pixel:DWORD\t\t\t\t; left x pixel pos\n\tARG     sy_pixel:DWORD\t\t\t\t; upper y pixel pos\n\tARG\tdx_pixel:DWORD\t\t\t\t; right x pixel pos\n\tARG\tdy_pixel:DWORD\t\t\t\t; lower y pixel pos\n\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Widen region leftward by amount mouse shape spills to the right of\n\t;* its hot point.  Limited to the left edge of the screen.\n\t;*=========================================================================*\n\tmov\teax,[(KeyboardType esi).MouseWidth]\t\n\tsub\teax,[(KeyboardType esi).MouseXHot]\t\n\tneg\teax\t\t\t\t\t\n\tadd\teax,[sx_pixel]\n\tjns\tshort ??noleftlimit\n\txor\teax,eax\n??noleftlimit:\n\t;*=========================================================================*\n\t;* Widen region upward by amount mouse shape spills below the\n\t;* mouse's hot point.  Limited by the top edge of the screen.\n\t;*=========================================================================*\n\tmov\tebx,[(KeyboardType esi).MouseHeight]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\tneg\tebx\n\tadd\tebx,[sy_pixel]\n\tjns\tshort ??notoplimit\n\txor\tebx,ebx\n??notoplimit:\n\t;*=========================================================================*\n\t;* Widen region rightward by amount mouse shape spills to the\n\t;* left of its hot point.  Limited by the right edge of the\n\t;* screen.\n\t;*=========================================================================*\n\tmov\tecx,[dx_pixel]\n\tadd\tecx,[(KeyboardType esi).MouseXHot]\n\tcmp\tecx,[(KeyboardType esi).MouseRight]\n\tjb\tshort ??norightlimit\n\tmov\tecx,[(KeyboardType esi).MouseRight]\n\tdec\tecx\n??norightlimit:\n\t;*=========================================================================*\n\t;* Widen region downward by amout the mouse shape extends above\n\t;* its hot point.  Limited to the bottom of the screen.\n\t;*=========================================================================*\n\tmov\tedx,[dy_pixel]\n\tadd\tedx,[(KeyboardType esi).MouseYHot]\n\tcmp\tedx,[(KeyboardType esi).MouseBottom]\n\tjb\tshort ??nobottomlimit\n\tmov\tedx,[(KeyboardType esi).MouseBottom]\n\tdec\tedx\n\n??nobottomlimit:\n\tinc\t[(KeyboardType esi).MouseUpdate]\t\t; don't let interrupt scrag variables\n\n\t;*=========================================================================*\n\t;* The mouse could be in one of four conditions.\n\t;* 1) The mouse is visible and no conditional hide has been specified.\n\t;* \t(perform normal region checking with possible hide)\n\t;* 2) The mouse is hidden and no conditional hide as been specified.\n\t;* \t(record region and do nothing)\n\t;* 3) The mouse is visible and a conditional region has been specified\n\t;* \t(expand region and perform check with possible hide).\n\t;* 4) The mouse is already hidden by a previous conditional.\n\t;* \t(expand region and do nothing)\n\t;*\n\t;* First: Set or expand the region according to the specified parameters\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType esi).MCState],0\n\tjne\tshort ??expand\n\tmov\t[(KeyboardType esi).MouseCXLeft],eax\n\tmov\t[(KeyboardType esi).MouseCYUpper],ebx\n\tmov\t[(KeyboardType esi).MouseCXRight],ecx\n\tmov\t[(KeyboardType esi).MouseCYLower],edx\n\tjmp\t??noylower\n??expand:\n\n\t;*=========================================================================*\n\t;* Expand the clipping rectangle.\n\t;*=========================================================================*\n\tcmp\teax,[(KeyboardType esi).MouseCXLeft]\n\tjb\tshort ??noxleft\n\tmov\t[(KeyboardType esi).MouseCXLeft],eax\n??noxleft:\n\tcmp\tebx,[(KeyboardType esi).MouseCYUpper]\n\tjb\tshort ??noyupper\n\tmov\t[(KeyboardType esi).MouseCYUpper],ebx\n??noyupper:\n\tcmp\tecx,[(KeyboardType esi).MouseCXRight]\n\tja\tshort ??noxright\n\tmov\t[(KeyboardType esi).MouseCXRight],ecx\n??noxright:\n\tcmp\tedx,[(KeyboardType esi).MouseCYLower]\n\tja\tshort ??noylower\n\tmov\t[(KeyboardType esi).MouseCYLower],edx\n??noylower:\n\t;*=========================================================================*\n\t;* If the mouse isn't already hidden, then check its location against\n\t;* the hiding region and hide if necessary.\n\t;*=========================================================================*\n\ttest\t[(KeyboardType esi).MCState],CONDHIDDEN\n\tjne\tshort ??nohide\n\n\tmov\teax,[(KeyboardType esi).MouseX]\n\tmov\tebx,[(KeyboardType esi).MouseY]\n\tcmp\teax,[(KeyboardType esi).MouseCXLeft]\n\tjb\tshort ??nohide\n\tcmp\teax,[(KeyboardType esi).MouseCXRight]\n\tja\tshort ??nohide\n\tcmp\tebx,[(KeyboardType esi).MouseCYUpper]\n\tjb\tshort ??nohide\n\tcmp\tebx,[(KeyboardType esi).MouseCYLower]\n\tja\tshort ??nohide\n\n\t;*=========================================================================*\n\t;* The mouse falls within the region for hiding, so hide it.\n\t;*=========================================================================*\n\n\tcall\tLow_Hide_Mouse\t\t\t\t; make the function call\n\tor\t[(KeyboardType esi).MCState],CONDHIDDEN\n??nohide:\n\n\t;*=========================================================================*\n\t;* Record the fact that a Conditional_Hide_Mouse was\n\t;* called and then exit.\n\t;*=========================================================================*\n\tor\t[(KeyboardType esi).MCState],CONDHIDE\n\tadd\t[BYTE PTR (KeyboardType esi).MCState],1\n\tadc\t[BYTE PTR (KeyboardType esi).MCState],0\n\tdec\t[(KeyboardType esi).MouseUpdate]\n\tret\n\n\tENDP\tConditional_Hide_Mouse\n\n;***************************************************************************\n;* CONDITIONAL_SHOW_MOUSE -- shows mouse if it was conditionally hidden    *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Conditional_Show_Mouse(void);                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tConditional_Show_Mouse:NEAR\n\tPROC\tConditional_Show_Mouse C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]    ; get the real mode offset\n\n\t;*=========================================================================*\n\t; Notify the interrupt that we are updating the mouse\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\n\n\tmov\tax,[(KeyboardType esi).MCState]\n\tcmp\tal,0\n\tje\tshort ??exit\t\t\t; if no more nesting clear cond\n\n\t;*=========================================================================*\n\t;* Decrement the conditional hide counter.\n\t;*=========================================================================*\n\tdec\tal\n\n\t;*=========================================================================*\n\t;* If there are more conditional levels to undo, then just abort the show.\n\t;*=========================================================================*\n\tjne\tshort ??exit\n\n\t;*=========================================================================*\n\t;* Yup, the mouse should be show, but only if it was previously hidden.\n\t;*=========================================================================*\n\ttest\tax,CONDHIDDEN\t\t\t; was it hidden by interrupt??\n\tje\tshort ??exit1\t\t\t; or initial check for level 0\n\n\tcall\tLow_Show_Mouse\n\n??exit1:\n\tmov\tax,0\n\n??exit:\n\tmov\t[(KeyboardType esi).MCState],ax\n\tdec\t[(KeyboardType esi).MouseUpdate]\n\tret\n\tENDP\tConditional_Show_Mouse\n\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VGA_Mouse_Shadow_Buffer:NEAR\n\tPROC\tVGA_Mouse_Shadow_Buffer C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tstore:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\n\tmov\tesi,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[(KeyboardType esi).MouseBuffX]\n\tmov\tebx,[(KeyboardType esi).MouseBuffY]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseBuffW]\n\tadd\tebx,[(KeyboardType esi).MouseBuffH]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseBuffer ]\n\tmov\t[ buffy0 ] , eax\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseBuffW]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseBuffW]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\tpush\tebp\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tebp , ecx\n??restore_loop:\n\tmov\tecx,eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi,ebx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tesi,edi\t\t\t\t\t; xchg the source and the dest\n\tmov\tebp , ecx\n??store_loop:\n\tmov\tecx,eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi,edx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,ebx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n??out:\n\tret\n\tENDP\tVGA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n;* DRAW_MOUSE -- Handles drawing the mouse cursor\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tVGA_Draw_Mouse:NEAR\n\tPROC\tVGA_Draw_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tmousex:DWORD\n\tARG\tmousey:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\n\n\tmov\tesi,[RealModePtr]    \t; get 32 bit offset of dos data\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[mousex]\n\tmov\tebx,[mousey]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseWidth]\n\tadd\tebx,[(KeyboardType esi).MouseHeight]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , eax\n\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseWidth]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseWidth]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch ,[esi]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[edi],ch\n??inc_edi:\n\tinc\tedi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tesi,ebx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t\t\t\t; adjust dest to next line\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\tret\n\n\tENDP\tVGA_Draw_Mouse\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VESA_Mouse_Shadow_Buffer:NEAR\n\tPROC\tVESA_Mouse_Shadow_Buffer C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tstore:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\tlocal\tvesa_linear : dword\n\n\tmov\teax , [ cpu_video_page ]\n\tmov\t[ vesa_linear ] ,  eax\n\n\tmov\tesi,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[(KeyboardType esi).MouseBuffX]\n\tmov\tebx,[(KeyboardType esi).MouseBuffY]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseBuffW]\n\tadd\tebx,[(KeyboardType esi).MouseBuffH]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseBuffer ]\n\tmov\t[ buffy0 ] , eax\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseBuffW]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\tcall\tVesa_Asm_Set_Win\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseBuffW]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\n\tmov\t[ tempreg ] , ebx\n??restore__top_loop:\n\tmov\tah,al\n??restore__inner_loop:\n\tmov\tch ,[esi]\n\tmov\t[edi],ch\n\tinc\tesi\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??restore__in_range\n\tadd\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??restore__in_range:\n\tdec\tah\n\tjnz\t??restore__inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??restore__in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??restore__in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore__top_loop\t\t\t\t; if more to do, do it\n\tjmp\t??out\t\t\t\t\t; get the heck outta the routine\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\tmov\t[ tempreg ] , ebx\n??store_top_loop:\n\tmov\tah,al\n??store_inner_loop:\n\tmov\tch ,[edi]\n\tmov\t[esi],ch\n\tinc\tesi\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??store_in_range\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??store_in_range:\n\tdec\tah\n\tjnz\t??store_inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??store_in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??store_in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_top_loop\t\t\t\t; if more to do, do it\n\n??out:\n\tmov\tedi , [ vesa_linear ]\n\tadd\tedi , 0a0000h\n\tcall\tVesa_Asm_Set_Win\n\n\tret\n\tENDP\tVESA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n;* DRAW_MOUSE -- Handles drawing the mouse cursor\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tVESA_Draw_Mouse:NEAR\n\tPROC\tVESA_Draw_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tmousex:DWORD\n\tARG\tmousey:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\tlocal\ttempreg : dword\n\tlocal\tvesa_linear : dword\n\n\tmov\teax , [ cpu_video_page ]\n\tmov\t[ vesa_linear ] ,  eax\n\n\tmov\tesi,[RealModePtr]    \t; get 32 bit offset of dos data\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[mousex]\n\tmov\tebx,[mousey]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseWidth]\n\tadd\tebx,[(KeyboardType esi).MouseHeight]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , eax\n\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseWidth]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\tcall\tVesa_Asm_Set_Win\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseWidth]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\t[ tempreg ] , ebx\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch ,[esi]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[edi],ch\n??inc_edi:\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??in_range\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??in_range:\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n\n??out:\n\tmov\tedi , [ vesa_linear ]\n\tadd\tedi , 0a0000h\n\tcall\tVesa_Asm_Set_Win\n\n\tret\n\n\tENDP\tVESA_Draw_Mouse\n\n\n;----------------------------------------------------------------------------\nEND\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/MOUSE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*********************************************************************************************** \n *                                                                                             * \n *                 Project Name : Westwood 32 bit Library                                      * \n *                                                                                             * \n *                    File Name : MOUSE.CPP                                                    * \n *                                                                                             * \n *                   Programmer : Philip W. Gorrow                                             * \n *                                                                                             * \n *                   Start Date : 12/12/95                                                     * \n *                                                                                             * \n *                  Last Update : December 12, 1995 [PWG]                                      * \n *                                                                                             * \n *---------------------------------------------------------------------------------------------* \n * Functions:                                                                                  * \n *   WWMouseClass::WWMouseClass -- Constructor for the Mouse Class                                 * \n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"mouse.h\"\n#include <mmsystem.h>\n\nstatic WWMouseClass *_Mouse=NULL;\nvoid CALLBACK Process_Mouse( UINT event_id, UINT res1 , DWORD user, DWORD  res2, DWORD  res3 );\n\n/*********************************************************************************************** \n * MOUSECLASS::MOUSECLASS -- Constructor for the Mouse Class                                   * \n *                                                                                             * \n * INPUT:\t\tGraphicBufferClass * screen - pointer to screen mouse is created for\t\t\t\t  *                                                                                      * \n *                                                                                             * \n * OUTPUT:     none                                                                            * \n *                                                                                             * \n * HISTORY:                                                                                    * \n *   12/12/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nWWMouseClass::WWMouseClass(GraphicBufferClass *scr, int mouse_max_width, int mouse_max_height)\n{\n\tMouseCursor \t= new char[mouse_max_width * mouse_max_height];\n\tMouseXHot\t\t= 0;\n\tMouseYHot\t\t= 0;\n\tCursorWidth\t\t= 0;\n\tCursorHeight\t= 0;\n\n\tMouseBuffer\t\t= new char[mouse_max_width * mouse_max_height];\n\tMouseBuffX\t\t= -1;\n\tMouseBuffY  \t= -1;\n\tMaxWidth\t\t\t= mouse_max_width;\n\tMaxHeight\t\t= mouse_max_height;\n\n\tMouseCXLeft\t\t= 0;\n\tMouseCYUpper\t= 0;\n\tMouseCXRight\t= 0;\n\tMouseCYLower\t= 0;\n\tMCFlags\t\t\t= 0;\n\tMCCount\t\t\t= 0;\n\n\tScreen\t\t\t= scr;\n\tPrevCursor\t\t= NULL;\n\tMouseUpdate\t\t= 0;\n\tState\t\t\t\t= 1;  \n\ttimeBeginPeriod ( 1000/ 60);\n\n\tMutexObject\t\t= CreateMutex(NULL, FALSE, \"WWLIB32MOUSEMUTEX\");\n\t//\n\t// Install the timer callback event handler\n\t//\n\n\tEraseBuffer\t\t= new char[mouse_max_width * mouse_max_height];\n\tEraseBuffX\t\t= -1;\n\tEraseBuffY  \t= -1;\n\tEraseBuffHotX\t= -1;\n\tEraseBuffHotY\t= -1;\n\tEraseFlags\t\t= FALSE;\n\n\t_Mouse\t\t\t= this;\n\tTimerHandle = timeSetEvent( 1000/60 , 1 , ::Process_Mouse, 0 , TIME_PERIODIC);\n}\n\nWWMouseClass::~WWMouseClass()\n{\n\tWaitForSingleObject(MutexObject, INFINITE);\n\tMouseUpdate++;\n\n\tif (MouseCursor) delete[] MouseCursor;\n\tif (MouseBuffer) delete[] MouseBuffer;\n\tif (TimerHandle) {\n\t\ttimeKillEvent(TimerHandle);\n\t}\n\ttimeEndPeriod (1);\n\tReleaseMutex(MutexObject);\n}\n\nvoid WWMouseClass::Process_Mouse(void)\n{\n\tPOINT \tpt;\t\t\t\t\t// define a structure to hold current cursor pos\n\n\t//\n\t// If the mouse is currently hidden or it has not been installed, then we \n\t// have no need to redraw the mouse.  \n\t//\n\tif (!_Mouse || State > 0 || MouseUpdate || EraseFlags)\n\t\treturn;\n\n\t//\n\t// Wait until we have exclusive access to our data\n\t//\n\tWaitForSingleObject(MutexObject, INFINITE);\n\t\n\t//\n\t// Get the mouse's current real cursor position\n\t//\n\tGetCursorPos(&pt);\t\t\t// get the current cursor position\n\t//\n\t// If the mouse has moved then we are responsible to redraw the mouse\n\t//\n\tif (pt.x != MouseBuffX || pt.y != MouseBuffY) {\n\t\tif (!EraseFlags) {\n\t\t\t//\n\t\t\t// If we can't lock the surface we need to draw to, we cannot update\n\t\t\t// the mouse.\n\t\t\t//\n\t\t\tif (Screen->Lock()) \t{\n\t\t\t\t//\n\t\t\t\t// Erase the old mouse by dumping the mouses shadow buff\n\t\t\t\t//   to the screen (if its position had ever been recorded).\n\t\t\t\t//\n\t\t\t\tLow_Hide_Mouse();\n\n\t\t\t\t//\n\t\t\t\t// Verify that the mouse has not gone into a conditional hiden area\n\t\t\t\t// If it has, mark it as being in one.\n\t\t\t\t//\n\t\t\t\tif (MCFlags & CONDHIDE && pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {\n\t\t\t\t\tMCFlags |= CONDHIDDEN;\n\t\t\t\t}\n\n\t\t\t\t//\n\t\t\t\t// Show the mouse if we are allowed to.\n\t\t\t\t//\n\t\t\t\tif (!(MCFlags & CONDHIDDEN)) \t{\n\t\t\t\t\tLow_Show_Mouse(pt.x, pt.y);\n\t\t\t\t}\n\t\t\t\t//\n\t\t\t\t// Finally unlock the destination surface as we have sucessfully\n\t\t\t\t// updated the mouse.\n\t\t\t\t//\n\t\t\t\tScreen->Unlock();\n\t\t\t}\n\t\t} else {\n\t\t\tif (MCFlags & CONDHIDE && pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {\n\t\t\t\tMCFlags |= CONDHIDDEN;\n\t\t\t\tState++;\n\t\t\t}\n\t\t}\n\t}\n\tReleaseMutex(MutexObject);\n}\n\nvoid *WWMouseClass::Set_Cursor(int xhotspot, int yhotspot, void *cursor) \n{\n\t//\n\t// If the pointer to the cursor we got is invalid, or its the same as the\n\t// currently set cursor then just return.\n\tif (!cursor || cursor == PrevCursor) \n\t\treturn(cursor);\n\n\t//\n\t// Wait until we have exclusive access to our data\n\t//\n\tWaitForSingleObject(MutexObject, INFINITE);\n\tMouseUpdate++;\n\t//\n\t// Since we are updating the mouse we need to hide the cursor so we\n\t// do not get some sort of weird transformation.\n\t//\n\tHide_Mouse();\n\t//\n\t// Now convert the shape to a mouse cursor with the given hotspots and\n\t// set it as our current mouse.\n\t//\n\tvoid *retval = ASM_Set_Mouse_Cursor(this, xhotspot, yhotspot, cursor);\n\t//\n\t// Show the mouse which will force it to appear with the new shape we\n\t// have assigned.\n\t//\n\tShow_Mouse();\n\t//\n\t// We are done updating the mouse cursor so on to bigger and better things.\n\t//\n\tMouseUpdate--;\n\t//\n\t// Inform Windows that we are done using the exclusive data we requested.\n\t//\n\tReleaseMutex(MutexObject);\n\t//\n\t// Return the previous mouse cursor which as conveniantly passed back by\n\t// Asm_Set_Mouse_Cursor.\n\t//\n\treturn(retval);\n}\t\n\nvoid WWMouseClass::Low_Hide_Mouse()\n{\n\tif (!State) {\n\t\twhile (!Screen->Lock()) {}\n\t\tif (MouseBuffX != -1 || MouseBuffY != -1) {\n\t\t\tMouse_Shadow_Buffer(this, Screen, MouseBuffer, MouseBuffX, MouseBuffY, MouseXHot, MouseYHot, 0);\n\t\t}\n\t\tMouseBuffX = -1;\n\t\tMouseBuffY = -1;\n\t\tScreen->Unlock();\n\t}\n\tState++;\n}\nvoid WWMouseClass::Hide_Mouse()\n{\n\t//\n\t// Wait until we have exclusive access to our data\n\t//\n\tWaitForSingleObject(MutexObject, INFINITE);\n\tMouseUpdate++;\n\tLow_Hide_Mouse();\n\tMouseUpdate--;\n\tReleaseMutex(MutexObject);\n}\n\n\nvoid WWMouseClass::Low_Show_Mouse(int x, int y)\n{\n\t//\n\t// If the mouse is already visible then just ignore the problem.\n\t//\n\tif (State == 0) return;\n\t//\n\t// Make the mouse a little bit more visible\n\t//\n\tState--;\n\n\t//\n\t//\tIf the mouse is completely visible then draw it at its current\n\t// position.\n\t//\n\tif (!State)\t{\n\t\t//\n\t\t// Try to lock the screen til we sucessfully get a lock.\n\t\t//\n\t\twhile (!Screen->Lock()) {}\n\t\t//\n\t\t// Save off the area behind the mouse.\n\t\t//\n\t\tMouse_Shadow_Buffer(this, Screen, MouseBuffer, x, y, MouseXHot, MouseYHot, 1);\n\t\t//\n\t\t// Draw the mouse in its new location\n\t\t//\n\t\t::Draw_Mouse(this, Screen, x, y);\n\t\t//\n\t\t// Save off the positions that we saved the buffer from\n\t\t//\n\t\tMouseBuffX = x;\n\t\tMouseBuffY = y;\n\t\t//\n\t\t// Unlock the screen and lets get moving.\n\t\t//\n\t\tScreen->Unlock();\t\t\n\t}\n}\n\nvoid WWMouseClass::Show_Mouse()\n{\n\tPOINT\tpt;\n\tGetCursorPos(&pt);\n\n\t//\n\t// Wait until we have exclusive access to our data\n\t//\n\tWaitForSingleObject(MutexObject, INFINITE);\n\tMouseUpdate++;\n\tLow_Show_Mouse(pt.x, pt.y);\n\tMouseUpdate--;\n\tReleaseMutex(MutexObject);\n}\n\nvoid WWMouseClass::Conditional_Hide_Mouse(int x1, int y1, int x2, int y2)\n{\n\tPOINT\tpt;\n\n\t//\n\t// Wait until we have exclusive access to our data\n\t//\n\tWaitForSingleObject(MutexObject, INFINITE);\n\tMouseUpdate++;\n\n\t//\n\t// First of all, adjust all the coordinates so that they handle\n\t// the fact that the hotspot is not necessarily the upper left\n\t// corner of the mouse.\n\t//\n\tx1 -= (CursorWidth - MouseXHot);\n\tx1  = MAX(0, x1);\n\ty1 -= (CursorHeight - MouseYHot);\n\ty1  = MAX(0, y1);\n\tx2  += MouseXHot;\n\tx2  = MIN(x2, Screen->Get_Width());\n\ty2  += MouseYHot;\n\ty2  = MIN(y2, Screen->Get_Height());\n\n\t// The mouse could be in one of four conditions.\n\t// 1) The mouse is visible and no conditional hide has been specified.\n\t// \t(perform normal region checking with possible hide)\n\t// 2) The mouse is hidden and no conditional hide as been specified.\n\t// \t(record region and do nothing)\n\t// 3) The mouse is visible and a conditional region has been specified\n\t// \t(expand region and perform check with possible hide).\n\t// 4) The mouse is already hidden by a previous conditional.\n\t// \t(expand region and do nothing)\n\t//\n\t// First: Set or expand the region according to the specified parameters\n\tif (!MCCount) {\n\t\tMouseCXLeft\t\t= x1;\n\t\tMouseCYUpper\t= y1;\n\t\tMouseCXRight\t= x2;\n\t\tMouseCYLower\t= y2;\n\t} else {\n\t\tMouseCXLeft\t\t= MIN(x1, MouseCXLeft);\n\t\tMouseCYUpper\t= MIN(y1, MouseCYUpper);\n\t\tMouseCXRight\t= MAX(x2, MouseCXRight);\n\t\tMouseCYLower\t= MAX(y2, MouseCYLower);\n\t}\n\t//\n\t// If the mouse isn't already hidden, then check its location against\n\t// the hiding region and hide if necessary.\n\t//\n\tif (!(MCFlags & CONDHIDDEN)) {\n\t\tGetCursorPos(&pt);\n\t\tif (pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {\n\t\t\tHide_Mouse();\n\t\t\tMCFlags |= CONDHIDDEN;\n\t\t}\n\t}\n\t//\n\t// Record the fact that a conditional hide was called and then exit\n\t//\n\t//\n\tMCFlags |= CONDHIDE;\n\tMCCount++;\n\tMouseUpdate--;\n\tReleaseMutex(MutexObject);\n\n}\nvoid WWMouseClass::Conditional_Show_Mouse(void)\n{\n\t//\n\t// Wait until we have exclusive access to our data\n\t//\n\tWaitForSingleObject(MutexObject, INFINITE);\n\tMouseUpdate++;\n\n\t//\n\t// if there are any nested hides then dec the count\n\t//\n\tif (MCCount) {\n\t\tMCCount--;\n\t\t//\n\t\t// If the mouse is now not hidden and it had actually been\n\t\t// hidden before then display it.\n\t\t//\n\t\tif (!MCCount) {\n\t\t\tif (MCFlags & CONDHIDDEN) {\n\t\t\t\tShow_Mouse();\n\t\t\t}\n\t\t\tMCFlags = 0;\n\t\t}\n\t}\n\n\tMouseUpdate--;\n\tReleaseMutex(MutexObject);\n}\n\n\nvoid WWMouseClass::Draw_Mouse(GraphicBufferClass *scr)\n{\n\tPOINT pt;\n\n\tif (State != 0) return;\n\t//\n\t// Wait until we have exclusive access to our data\n\t//\n\tWaitForSingleObject(MutexObject, INFINITE);\n\tMouseUpdate++;\n\t//\n\t//\tGet the position that the mouse is currently located at\n\t//\n\tGetCursorPos(&pt);\n\tif (MCFlags & CONDHIDE && pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {\n\t\tHide_Mouse();\n\t\tMCFlags |= CONDHIDDEN;\n\t} else {\n\t\t//\n\t\t// If the mouse is already visible then just ignore the problem.\n\t\t//\n\t\tEraseFlags = TRUE;\n\n\t\t//\n\t\t// Try to lock the screen til we sucessfully get a lock.\n\t\t//\n\t\twhile (!scr->Lock()) {}\n\t\t//\n\t\t// Save off the area behind the mouse into two different buffers, one\n\t\t// which will be used to restore the mouse and the other which will\n\t\t// be used to restore the hidden surface when we get a chance.\n\t\t//\n\t\tMouse_Shadow_Buffer(this, scr, EraseBuffer, pt.x, pt.y, MouseXHot, MouseYHot, 1);\n\t\tmemcpy(MouseBuffer, EraseBuffer, MaxWidth * MaxHeight);\n\t\t//\n\t\t// Draw the mouse in its new location\n\t\t//\n\t\t::Draw_Mouse(this, scr, pt.x, pt.y);\n\t\t//\n\t\t// Save off the positions that we saved the buffer from\n\t\t//\n\t\tEraseBuffX \t\t= pt.x;\n\t\tMouseBuffX \t\t= pt.x;\n\t\tEraseBuffY \t\t= pt.y;\n\t\tMouseBuffY \t\t= pt.y;\n\t\tEraseBuffHotX\t= MouseXHot;\n\t\tEraseBuffHotY\t= MouseYHot;\n\t\t//\n\t\t// Unlock the screen and lets get moving.\n\t\t//\n\t\tscr->Unlock();\n\t}\n\n\tMouseUpdate--;\n\tReleaseMutex(MutexObject);\n}\n\nvoid WWMouseClass::Erase_Mouse(GraphicBufferClass *scr, int forced)\n{\n//\tif (!EraseFlags) return;\n//\tif (State != 0) return;\n\n\t//\n\t// If we are forcing the redraw of a mouse we already managed to\n\t// restore then just get outta here.\n\t//\n\tif (forced && EraseBuffX == -1 && EraseBuffY == -1) return;\n\n\t//\n\t// If we don't own the Mutex Object, then we need to because we may\n\t// update the mouse.\n\t//\n\tWaitForSingleObject(MutexObject, INFINITE);\n\tMouseUpdate++;\n\n\t//\n\t// If this is not a forced call, only update the mouse is we can legally\n\t//\tlock the buffer.\n\t//\n\tif (!forced) {\n#if(0)\n\t\tif (scr->Lock()) {\n\t\t\t//\n\t\t\t// If the surface has not already been restore then restore it and erase the \n\t\t\t// restoration coordinates so we don't accidentally do it twice.\n\t\t\t//\n\t\t\tif (EraseBuffX != -1 || EraseBuffY != -1) {\n\t\t\t\tMouse_Shadow_Buffer(this, scr, EraseBuffer, EraseBuffX, EraseBuffY, 0);\n\t\t\t\tEraseBuffX = -1;\n\t\t\t\tEraseBuffY = -1;\n\t\t\t}\n\t\t\t//\n\t\t\t// We are done writing to the buffer so unlock it.\n\t\t\t//\n\t\t\tscr->Unlock();\n\t\t}\n#endif\n\t} else\t{\n\t\t//\n\t\t// If this is a forced call then wait til we are allowed to update the buffer\n\t\t//\n\t\twhile (!scr->Lock()) {}\n\t\t//\n\t\t// If the surface has not already been restore then restore it and erase the \n\t\t// restoration coordinates so we don't accidentally do it twice.\n\t\t//\n\t\tif (EraseBuffX != -1 || EraseBuffY != -1) {\n\t\t\tMouse_Shadow_Buffer(this, scr, EraseBuffer, EraseBuffX, EraseBuffY, EraseBuffHotX, EraseBuffHotY, 0);\n\t\t}\n\t\t//\n\t\t// We are done writing to the buffer so unlock it.\n\t\t//\n\t\tscr->Unlock();\n\t}\n\tMouseUpdate--;\n\tReleaseMutex(MutexObject);\n  \tEraseFlags = FALSE;\n}\n\nint WWMouseClass::Get_Mouse_State(void)\n{\n\treturn(State);\n}\n/***********************************************************************************************\n * WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels             *\n *                                                                                             *\n * INPUT:\t\tnone                                                                            *\n *                                                                                             *\n * OUTPUT:     int\t\t- returns the mouses current x position in pixels                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nint WWMouseClass::Get_Mouse_X(void)\n{\n\tPOINT \tpt;\n\tGetCursorPos(&pt);\n\treturn(pt.x);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels             *\n *                                                                                             *\n * INPUT:\t\tnone                                                                            *\n *                                                                                             *\n * OUTPUT:     int\t\t- returns the mouses current y position in pixels                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nint WWMouseClass::Get_Mouse_Y(void)\n{\n\tPOINT \tpt;\n\tGetCursorPos(&pt);\n\treturn(pt.y);\n}\n\n/***********************************************************************************************\n * WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars         *\n *                                                                                             *\n * INPUT:\t\tint &x\t\t- variable to return the mouses x position in pixels                *\n *\t\t\t\t\tint &y\t\t- variable to return the mouses y position in pixels\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     none - output is via reference variables                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid WWMouseClass::Get_Mouse_XY(int &x, int &y)\n{\n\tPOINT \tpt;\n\n\tGetCursorPos(&pt);\n\tx = pt.x;\n\ty = pt.y;\n}\n\n#pragma off(unreferenced)\nvoid CALLBACK Process_Mouse( UINT event_id, UINT res1 , DWORD user, DWORD  res2, DWORD  res3 )\n{\n\tif (_Mouse) {\n\t\t_Mouse->Process_Mouse();\n\t}\n}\n#pragma on(unreferenced)\n\nvoid Hide_Mouse(void)\n{\n\tif (!_Mouse) return;\n\t_Mouse->Hide_Mouse();\n}\n\t\nvoid Show_Mouse(void)\n{\n\tif (!_Mouse) return;\n\t_Mouse->Show_Mouse();\n}\n\nvoid Conditional_Hide_Mouse(int x1, int y1, int x2, int y2)\n{\n\tif (!_Mouse) return;\n\t_Mouse->Conditional_Hide_Mouse(x1, y1, x2, y2);\n}\n\nvoid Conditional_Show_Mouse(void)\n{\n\tif (!_Mouse) return;\n\t_Mouse->Conditional_Show_Mouse();\n}\n\nint Get_Mouse_State(void)\n{\n\tif (!_Mouse) return(0);\n\treturn(_Mouse->Get_Mouse_State());\n}\n\nvoid *Set_Mouse_Cursor(int hotx, int hoty, void *cursor)\n{\n\tif (!_Mouse) return(0);\n\treturn(_Mouse->Set_Cursor(hotx,hoty,cursor));\n}\n\nint Get_Mouse_X(void)\n{\n\tif (!_Mouse) return(0);\n\treturn(_Mouse->Get_Mouse_X());\n}\n\nint Get_Mouse_Y(void)\n{\n\tif (!_Mouse) return(0);\n\treturn(_Mouse->Get_Mouse_Y());\n}\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/MOUSE.CPP.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*********************************************************************************************** \n *                                                                                             * \n *                 Project Name : Westwood 32 bit Library                                      * \n *                                                                                             * \n *                    File Name : MOUSE.CPP                                                    * \n *                                                                                             * \n *                   Programmer : Philip W. Gorrow                                             * \n *                                                                                             * \n *                   Start Date : 12/12/95                                                     * \n *                                                                                             * \n *                  Last Update : December 12, 1995 [PWG]                                      * \n *                                                                                             * \n *---------------------------------------------------------------------------------------------* \n * Functions:                                                                                  * \n *   WWMouseClass::WWMouseClass -- Constructor for the Mouse Class                                 * \n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"mouse.h\"\n#include <mmsystem.h>\n\nstatic WWMouseClass *_Mouse=NULL;\nvoid CALLBACK Process_Mouse( UINT event_id, UINT res1 , DWORD user, DWORD  res2, DWORD  res3 );\n\n/*********************************************************************************************** \n * MOUSECLASS::MOUSECLASS -- Constructor for the Mouse Class                                   * \n *                                                                                             * \n * INPUT:\t\tGraphicBufferClass * screen - pointer to screen mouse is created for\t\t\t\t  *                                                                                      * \n *                                                                                             * \n * OUTPUT:     none                                                                            * \n *                                                                                             * \n * HISTORY:                                                                                    * \n *   12/12/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nWWMouseClass::WWMouseClass(GraphicBufferClass *scr, int mouse_max_width, int mouse_max_height)\n{\n\tMouseCursor \t= new char[mouse_max_width * mouse_max_height];\n\tMouseXHot\t\t= 0;\n\tMouseYHot\t\t= 0;\n\tCursorWidth\t\t= 0;\n\tCursorHeight\t= 0;\n\n\tMouseBuffer\t\t= new char[mouse_max_width * mouse_max_height];\n\tMouseBuffX\t\t= -1;\n\tMouseBuffY  \t= -1;\n\tMaxWidth\t\t\t= mouse_max_width;\n\tMaxHeight\t\t= mouse_max_height;\n\n\tMouseCXLeft\t\t= 0;\n\tMouseCYUpper\t= 0;\n\tMouseCXRight\t= 0;\n\tMouseCYLower\t= 0;\n\tMCFlags\t\t\t= 0;\n\tMCCount\t\t\t= 0;\n\n\tScreen\t\t\t= scr;\n\tPrevCursor\t\t= NULL;\n\tMouseUpdate\t\t= 0;\n\tState\t\t\t\t= 1;  \n\ttimeBeginPeriod ( 1000/ 60);\n\n\tMutexObject\t\t= CreateMutex(NULL, FALSE, \"WWLIB32MOUSEMUTEX\");\n\t//\n\t// Install the timer callback event handler\n\t//\n\n\tEraseBuffer\t\t= new char[mouse_max_width * mouse_max_height];\n\tEraseBuffX\t\t= -1;\n\tEraseBuffY  \t= -1;\n\tEraseFlags\t\t= FALSE;\n\n\t_Mouse\t\t\t= this;\n\tTimerHandle = timeSetEvent( 1000/60 , 1 , ::Process_Mouse, 0 , TIME_PERIODIC);\n}\n\nWWMouseClass::~WWMouseClass()\n{\n\tWaitForSingleObject(MutexObject, INFINITE);\n\tMouseUpdate++;\n\n\tif (MouseCursor) delete[] MouseCursor;\n\tif (MouseBuffer) delete[] MouseBuffer;\n\tif (TimerHandle) {\n\t\ttimeKillEvent(TimerHandle);\n\t}\n\ttimeEndPeriod (1);\n\tReleaseMutex(MutexObject);\n}\n\nvoid WWMouseClass::Process_Mouse(void)\n{\n\tPOINT \tpt;\t\t\t\t\t// define a structure to hold current cursor pos\n\n\t//\n\t// If the mouse is currently hidden or it has not been installed, then we \n\t// have no need to redraw the mouse.  \n\t//\n\tif (!_Mouse || State > 0 || MouseUpdate || EraseFlags)\n\t\treturn;\n\n\t//\n\t// Wait until we have exclusive access to our data\n\t//\n\tWaitForSingleObject(MutexObject, INFINITE);\n\t\n\t//\n\t// Get the mouse's current real cursor position\n\t//\n\tGetCursorPos(&pt);\t\t\t// get the current cursor position\n\t//\n\t// If the mouse has moved then we are responsible to redraw the mouse\n\t//\n\tif (pt.x != MouseBuffX || pt.y != MouseBuffY) {\n\t\tif (!EraseFlags) {\n\t\t\t//\n\t\t\t// If we can't lock the surface we need to draw to, we cannot update\n\t\t\t// the mouse.\n\t\t\t//\n\t\t\tif (Screen->Lock()) \t{\n\t\t\t\t//\n\t\t\t\t// Erase the old mouse by dumping the mouses shadow buff\n\t\t\t\t//   to the screen (if its position had ever been recorded).\n\t\t\t\t//\n\t\t\t\tLow_Hide_Mouse();\n\n\t\t\t\t//\n\t\t\t\t// Verify that the mouse has not gone into a conditional hiden area\n\t\t\t\t// If it has, mark it as being in one.\n\t\t\t\t//\n\t\t\t\tif (MCFlags & CONDHIDE && pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {\n\t\t\t\t\tMCFlags |= CONDHIDDEN;\n\t\t\t\t}\n\n\t\t\t\t//\n\t\t\t\t// Show the mouse if we are allowed to.\n\t\t\t\t//\n\t\t\t\tif (!(MCFlags & CONDHIDDEN)) \t{\n\t\t\t\t\tLow_Show_Mouse(pt.x, pt.y);\n\t\t\t\t}\n\t\t\t\t//\n\t\t\t\t// Finally unlock the destination surface as we have sucessfully\n\t\t\t\t// updated the mouse.\n\t\t\t\t//\n\t\t\t\tScreen->Unlock();\n\t\t\t}\n\t\t} else {\n\t\t\tif (MCFlags & CONDHIDE && pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {\n\t\t\t\tMCFlags |= CONDHIDDEN;\n\t\t\t\tState++;\n\t\t\t}\n\t\t}\n\t}\n\tReleaseMutex(MutexObject);\n}\n\nvoid *WWMouseClass::Set_Cursor(int xhotspot, int yhotspot, void *cursor) \n{\n\t//\n\t// If the pointer to the cursor we got is invalid, or its the same as the\n\t// currently set cursor then just return.\n\tif (!cursor || cursor == PrevCursor) \n\t\treturn(cursor);\n\n\t//\n\t// Wait until we have exclusive access to our data\n\t//\n\tWaitForSingleObject(MutexObject, INFINITE);\n\tMouseUpdate++;\n\t//\n\t// Since we are updating the mouse we need to hide the cursor so we\n\t// do not get some sort of weird transformation.\n\t//\n\tHide_Mouse();\n\t//\n\t// Now convert the shape to a mouse cursor with the given hotspots and\n\t// set it as our current mouse.\n\t//\n\tvoid *retval = ASM_Set_Mouse_Cursor(this, xhotspot, yhotspot, cursor);\n\t//\n\t// Show the mouse which will force it to appear with the new shape we\n\t// have assigned.\n\t//\n\tShow_Mouse();\n\t//\n\t// We are done updating the mouse cursor so on to bigger and better things.\n\t//\n\tMouseUpdate--;\n\t//\n\t// Inform Windows that we are done using the exclusive data we requested.\n\t//\n\tReleaseMutex(MutexObject);\n\t//\n\t// Return the previous mouse cursor which as conveniantly passed back by\n\t// Asm_Set_Mouse_Cursor.\n\t//\n\treturn(retval);\n}\t\n\nvoid WWMouseClass::Low_Hide_Mouse()\n{\n\tif (!State) {\n\t\twhile (!Screen->Lock()) {}\n\t\tif (MouseBuffX != -1 || MouseBuffY != -1) {\n\t\t\tMouse_Shadow_Buffer(this, Screen, MouseBuffer, MouseBuffX, MouseBuffY, 0);\n\t\t}\n\t\tMouseBuffX = -1;\n\t\tMouseBuffY = -1;\n\t\tScreen->Unlock();\n\t}\n\tState++;\n}\nvoid WWMouseClass::Hide_Mouse()\n{\n\t//\n\t// Wait until we have exclusive access to our data\n\t//\n\tWaitForSingleObject(MutexObject, INFINITE);\n\tMouseUpdate++;\n\tLow_Hide_Mouse();\n\tMouseUpdate--;\n\tReleaseMutex(MutexObject);\n}\n\n\nvoid WWMouseClass::Low_Show_Mouse(int x, int y)\n{\n\t//\n\t// If the mouse is already visible then just ignore the problem.\n\t//\n\tif (State == 0) return;\n\t//\n\t// Make the mouse a little bit more visible\n\t//\n\tState--;\n\n\t//\n\t//\tIf the mouse is completely visible then draw it at its current\n\t// position.\n\t//\n\tif (!State)\t{\n\t\t//\n\t\t// Try to lock the screen til we sucessfully get a lock.\n\t\t//\n\t\twhile (!Screen->Lock()) {}\n\t\t//\n\t\t// Save off the area behind the mouse.\n\t\t//\n\t\tMouse_Shadow_Buffer(this, Screen, MouseBuffer, x, y, 1);\n\t\t//\n\t\t// Draw the mouse in its new location\n\t\t//\n\t\t::Draw_Mouse(this, Screen, x, y);\n\t\t//\n\t\t// Save off the positions that we saved the buffer from\n\t\t//\n\t\tMouseBuffX = x;\n\t\tMouseBuffY = y;\n\t\t//\n\t\t// Unlock the screen and lets get moving.\n\t\t//\n\t\tScreen->Unlock();\t\t\n\t}\n}\n\nvoid WWMouseClass::Show_Mouse()\n{\n\tPOINT\tpt;\n\tGetCursorPos(&pt);\n\n\t//\n\t// Wait until we have exclusive access to our data\n\t//\n\tWaitForSingleObject(MutexObject, INFINITE);\n\tMouseUpdate++;\n\tLow_Show_Mouse(pt.x, pt.y);\n\tMouseUpdate--;\n\tReleaseMutex(MutexObject);\n}\n\nvoid WWMouseClass::Conditional_Hide_Mouse(int x1, int y1, int x2, int y2)\n{\n\tPOINT\tpt;\n\n\t//\n\t// Wait until we have exclusive access to our data\n\t//\n\tWaitForSingleObject(MutexObject, INFINITE);\n\tMouseUpdate++;\n\n\t//\n\t// First of all, adjust all the coordinates so that they handle\n\t// the fact that the hotspot is not necessarily the upper left\n\t// corner of the mouse.\n\t//\n\tx1 -= (CursorWidth - MouseXHot);\n\tx1  = MAX(0, x1);\n\ty1 -= (CursorHeight - MouseYHot);\n\ty1  = MAX(0, y1);\n\tx2  += MouseXHot;\n\tx2  = MIN(x2, Screen->Get_Width());\n\ty2  += MouseYHot;\n\ty2  = MIN(y2, Screen->Get_Height());\n\n\t// The mouse could be in one of four conditions.\n\t// 1) The mouse is visible and no conditional hide has been specified.\n\t// \t(perform normal region checking with possible hide)\n\t// 2) The mouse is hidden and no conditional hide as been specified.\n\t// \t(record region and do nothing)\n\t// 3) The mouse is visible and a conditional region has been specified\n\t// \t(expand region and perform check with possible hide).\n\t// 4) The mouse is already hidden by a previous conditional.\n\t// \t(expand region and do nothing)\n\t//\n\t// First: Set or expand the region according to the specified parameters\n\tif (!MCCount) {\n\t\tMouseCXLeft\t\t= x1;\n\t\tMouseCYUpper\t= y1;\n\t\tMouseCXRight\t= x2;\n\t\tMouseCYLower\t= y2;\n\t} else {\n\t\tMouseCXLeft\t\t= MIN(x1, MouseCXLeft);\n\t\tMouseCYUpper\t= MIN(y1, MouseCYUpper);\n\t\tMouseCXRight\t= MAX(x2, MouseCXRight);\n\t\tMouseCYLower\t= MAX(y2, MouseCYLower);\n\t}\n\t//\n\t// If the mouse isn't already hidden, then check its location against\n\t// the hiding region and hide if necessary.\n\t//\n\tif (!(MCFlags & CONDHIDDEN)) {\n\t\tGetCursorPos(&pt);\n\t\tif (pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {\n\t\t\tHide_Mouse();\n\t\t\tMCFlags |= CONDHIDDEN;\n\t\t}\n\t}\n\t//\n\t// Record the fact that a conditional hide was called and then exit\n\t//\n\t//\n\tMCFlags |= CONDHIDE;\n\tMCCount++;\n\tMouseUpdate--;\n\tReleaseMutex(MutexObject);\n\n}\nvoid WWMouseClass::Conditional_Show_Mouse(void)\n{\n\t//\n\t// Wait until we have exclusive access to our data\n\t//\n\tWaitForSingleObject(MutexObject, INFINITE);\n\tMouseUpdate++;\n\n\t//\n\t// if there are any nested hides then dec the count\n\t//\n\tif (MCCount) {\n\t\tMCCount--;\n\t\t//\n\t\t// If the mouse is now not hidden and it had actually been\n\t\t// hidden before then display it.\n\t\t//\n\t\tif (!MCCount) {\n\t\t\tif (MCFlags & CONDHIDDEN) {\n\t\t\t\tShow_Mouse();\n\t\t\t}\n\t\t\tMCFlags = 0;\n\t\t}\n\t}\n\n\tMouseUpdate--;\n\tReleaseMutex(MutexObject);\n}\n\n\nvoid WWMouseClass::Draw_Mouse(GraphicBufferClass *scr)\n{\n\tPOINT pt;\n\n\tif (State != 0) return;\n\t//\n\t// Wait until we have exclusive access to our data\n\t//\n\tWaitForSingleObject(MutexObject, INFINITE);\n\tMouseUpdate++;\n\t//\n\t//\tGet the position that the mouse is currently located at\n\t//\n\tGetCursorPos(&pt);\n\tif (MCFlags & CONDHIDE) {\n\t\tif (pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {\n\t\t\tHide_Mouse();\n\t\t\tMCFlags |= CONDHIDDEN;\n\t\t}\n\t} else {\n\t\t//\n\t\t// If the mouse is already visible then just ignore the problem.\n\t\t//\n\t\tEraseFlags = TRUE;\n\n\t\t//\n\t\t// Try to lock the screen til we sucessfully get a lock.\n\t\t//\n\t\twhile (!scr->Lock()) {}\n\t\t//\n\t\t// Save off the area behind the mouse into two different buffers, one\n\t\t// which will be used to restore the mouse and the other which will\n\t\t// be used to restore the hidden surface when we get a chance.\n\t\t//\n\t\tMouse_Shadow_Buffer(this, scr, EraseBuffer, pt.x, pt.y, 1);\n\t\tmemcpy(MouseBuffer, EraseBuffer, MaxWidth * MaxHeight);\n\t\t//\n\t\t// Draw the mouse in its new location\n\t\t//\n\t\t::Draw_Mouse(this, scr, pt.x, pt.y);\n\t\t//\n\t\t// Save off the positions that we saved the buffer from\n\t\t//\n\t\tEraseBuffX = pt.x;\n\t\tMouseBuffX = pt.x;\n\t\tEraseBuffY = pt.y;\n\t\tMouseBuffY = pt.y;\n\t\t//\n\t\t// Unlock the screen and lets get moving.\n\t\t//\n\t\tscr->Unlock();\n\t}\n\n\tMouseUpdate--;\n\tReleaseMutex(MutexObject);\n}\n\nvoid WWMouseClass::Erase_Mouse(GraphicBufferClass *scr, int forced)\n{\n\tif (!EraseFlags) return;\n//\tif (State != 0) return;\n\n\t//\n\t// If we are forcing the redraw of a mouse we already managed to\n\t// restore then just get outta here.\n\t//\n\tif (forced && EraseBuffX == -1 && EraseBuffY == -1) return;\n\n\t//\n\t// If we don't own the Mutex Object, then we need to because we may\n\t// update the mouse.\n\t//\n\tWaitForSingleObject(MutexObject, INFINITE);\n\tMouseUpdate++;\n\n\t//\n\t// If this is not a forced call, only update the mouse is we can legally\n\t//\tlock the buffer.\n\t//\n\tif (!forced) {\n#if(0)\n\t\tif (scr->Lock()) {\n\t\t\t//\n\t\t\t// If the surface has not already been restore then restore it and erase the \n\t\t\t// restoration coordinates so we don't accidentally do it twice.\n\t\t\t//\n\t\t\tif (EraseBuffX != -1 || EraseBuffY != -1) {\n\t\t\t\tMouse_Shadow_Buffer(this, scr, EraseBuffer, EraseBuffX, EraseBuffY, 0);\n\t\t\t\tEraseBuffX = -1;\n\t\t\t\tEraseBuffY = -1;\n\t\t\t}\n\t\t\t//\n\t\t\t// We are done writing to the buffer so unlock it.\n\t\t\t//\n\t\t\tscr->Unlock();\n\t\t}\n#endif\n\t} else\t{\n\t\t//\n\t\t// If this is a forced call then wait til we are allowed to update the buffer\n\t\t//\n\t\twhile (!scr->Lock()) {}\n\t\t//\n\t\t// If the surface has not already been restore then restore it and erase the \n\t\t// restoration coordinates so we don't accidentally do it twice.\n\t\t//\n\t\tif (EraseBuffX != -1 || EraseBuffY != -1) {\n\t\t\tMouse_Shadow_Buffer(this, scr, EraseBuffer, EraseBuffX, EraseBuffY, 0);\n\t\t\tEraseBuffX = -1;\n\t\t\tEraseBuffY = -1;\n\t\t}\n\t\t//\n\t\t// We are done writing to the buffer so unlock it.\n\t\t//\n\t\tscr->Unlock();\n\t}\n\tMouseUpdate--;\n\tReleaseMutex(MutexObject);\n\tEraseFlags = FALSE;\n}\n\nint WWMouseClass::Get_Mouse_State(void)\n{\n\treturn(State);\n}\n/***********************************************************************************************\n * WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels             *\n *                                                                                             *\n * INPUT:\t\tnone                                                                            *\n *                                                                                             *\n * OUTPUT:     int\t\t- returns the mouses current x position in pixels                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nint WWMouseClass::Get_Mouse_X(void)\n{\n\tPOINT \tpt;\n\tGetCursorPos(&pt);\n\treturn(pt.x);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels             *\n *                                                                                             *\n * INPUT:\t\tnone                                                                            *\n *                                                                                             *\n * OUTPUT:     int\t\t- returns the mouses current y position in pixels                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nint WWMouseClass::Get_Mouse_Y(void)\n{\n\tPOINT \tpt;\n\tGetCursorPos(&pt);\n\treturn(pt.y);\n}\n\n/***********************************************************************************************\n * WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars         *\n *                                                                                             *\n * INPUT:\t\tint &x\t\t- variable to return the mouses x position in pixels                *\n *\t\t\t\t\tint &y\t\t- variable to return the mouses y position in pixels\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     none - output is via reference variables                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid WWMouseClass::Get_Mouse_XY(int &x, int &y)\n{\n\tPOINT \tpt;\n\n\tGetCursorPos(&pt);\n\tx = pt.x;\n\ty = pt.y;\n}\n\n#pragma off(unreferenced)\nvoid CALLBACK Process_Mouse( UINT event_id, UINT res1 , DWORD user, DWORD  res2, DWORD  res3 )\n{\n\tif (_Mouse) {\n\t\t_Mouse->Process_Mouse();\n\t}\n}\n#pragma on(unreferenced)\n\nvoid Hide_Mouse(void)\n{\n\tif (!_Mouse) return;\n\t_Mouse->Hide_Mouse();\n}\n\t\nvoid Show_Mouse(void)\n{\n\tif (!_Mouse) return;\n\t_Mouse->Show_Mouse();\n}\n\nvoid Conditional_Hide_Mouse(int x1, int y1, int x2, int y2)\n{\n\tif (!_Mouse) return;\n\t_Mouse->Conditional_Hide_Mouse(x1, y1, x2, y2);\n}\n\nvoid Conditional_Show_Mouse(void)\n{\n\tif (!_Mouse) return;\n\t_Mouse->Conditional_Show_Mouse();\n}\n\nint Get_Mouse_State(void)\n{\n\tif (!_Mouse) return(0);\n\treturn(_Mouse->Get_Mouse_State());\n}\n\nvoid *Set_Mouse_Cursor(int hotx, int hoty, void *cursor)\n{\n\tif (!_Mouse) return(0);\n\treturn(_Mouse->Set_Cursor(hotx,hoty,cursor));\n}\n\nint Get_Mouse_X(void)\n{\n\tif (!_Mouse) return(0);\n\treturn(_Mouse->Get_Mouse_X());\n}\n\nint Get_Mouse_Y(void)\n{\n\tif (!_Mouse) return(0);\n\treturn(_Mouse->Get_Mouse_Y());\n}\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/MOUSE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*********************************************************************************************** \n *                                                                                             * \n *                 Project Name : Westwood 32 Bit Library                                      * \n *                                                                                             * \n *                    File Name : MOUSE.H                                                      * \n *                                                                                             * \n *                   Programmer : Philip W. Gorrow                                             * \n *                                                                                             * \n *                   Start Date : 12/12/95                                                     * \n *                                                                                             * \n *                  Last Update : December 12, 1995 [PWG]                                      * \n *                                                                                             * \n *---------------------------------------------------------------------------------------------* \n * Functions:                                                                                  * \n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WW_MOUSE_H\n#define WW_MOUSE_H\n\n#include <gbuffer.h>\n\nclass WWMouseClass {\n\tpublic:\n\t\tWWMouseClass(GraphicBufferClass *scr, int mouse_max_width, int mouse_max_height);\n\t\t~WWMouseClass();\n\t\tvoid *Set_Cursor(int xhotspot, int yhotspot, void *cursor);\n\t\tvoid Process_Mouse(void);\n\t\tvoid Hide_Mouse(void);\n\t\tvoid Show_Mouse(void);\n\t\tvoid Conditional_Hide_Mouse(int x1, int y1, int x2, int y2);\n\t\tvoid Conditional_Show_Mouse(void);\n\t\tint Get_Mouse_State(void);\n\t\tint Get_Mouse_X(void);\n\t\tint Get_Mouse_Y(void);\n\t\tvoid Get_Mouse_XY(int &x, int &y);\n\t\t//\n\t\t// The following two routines can be used to render the mouse onto a graphicbuffer\n\t\t// other than the hidpage.\n\t\t//\n\t\tvoid Draw_Mouse(GraphicBufferClass *scr);\n\t\tvoid Erase_Mouse(GraphicBufferClass *scr, int forced = FALSE);\n\n\tprivate:\n\t\tenum \t{\n\t\t\tCONDHIDE\t\t= 1,\n\t\t\tCONDHIDDEN \t= 2,\n\t\t};\n\t\tvoid Low_Hide_Mouse(void);\n\t\tvoid Low_Show_Mouse(int x, int y);\n\n\t\tchar\t\t\t\t\t\t*MouseCursor;\t// pointer to the mouse cursor in memory\n\t\tint\t\t\t\t\t\tMouseXHot;\t\t// X hot spot of the current mouse cursor\n\t\tint\t\t\t\t\t\tMouseYHot;\t\t// Y hot spot of the current mouse cursor\n\t\tint\t\t\t\t\t\tCursorWidth;\t// width of the mouse cursor in pixels\n\t\tint\t\t\t\t\t\tCursorHeight;\t// height of the mouse cursor in pixels\n\n\t\tchar\t\t\t\t\t\t*MouseBuffer;\t// pointer to background buffer in memory\n\t\tint\t\t\t\t\t\tMouseBuffX;\t\t// pixel x mouse buffer was preserved at\n\t\tint\t\t\t\t\t\tMouseBuffY;\t\t// pixel y mouse buffer was preserved at\n\t\tint\t\t\t\t\t\tMaxWidth;\t\t// maximum width of mouse background buffer\n\t\tint\t\t\t\t\t\tMaxHeight;\t\t// maximum height of mouse background buffer\n\n\t\tint\t\t\t\t\t\tMouseCXLeft;\t// left x pos if conditional hide mouse in effect\n\t\tint\t\t\t\t\t\tMouseCYUpper;\t// upper y pos if conditional hide mouse in effect\n\t\tint\t\t\t\t\t\tMouseCXRight;\t// right x pos if conditional hide mouse in effect\n\t\tint\t\t\t\t\t\tMouseCYLower;\t// lower y pos if conditional hide mouse in effect\n\t\tchar\t\t\t\t\t\tMCFlags;\t\t\t// conditional hide mouse flags\n\t\tchar\t\t\t\t\t\tMCCount;\t\t\t// nesting count for conditional hide mouse\n\n\t\tGraphicBufferClass\t*Screen;\t\t\t// pointer to the surface mouse was init'd with\n\t\tchar *\t\t\t\t\tPrevCursor;\t\t// pointer to previous cursor shape\n\t\tint\t\t\t\t\t\tMouseUpdate;\n\t\tint\t\t\t\t\t\tState;\n\n\t\tchar\t\t\t\t\t\t*EraseBuffer;\t// Buffer which holds background to restore to hidden page\n\t\tint\t\t\t\t\t\tEraseBuffX;\t\t// X position of the hidden page background\n\t\tint\t\t\t\t\t\tEraseBuffY;\t\t// Y position of the hidden page background\n\t\tint\t\t\t\t\t\tEraseBuffHotX;\t// X position of the hidden page background\n\t\tint\t\t\t\t\t\tEraseBuffHotY;\t// Y position of the hidden page background\n\n\t\tint\t\t\t\t\t\tEraseFlags;\t\t// Records whether mutex has been released\n\n\t\tHANDLE\t\t\t\t\tMutexObject;\t// Handle the Mutex Object created when mouse is\n\t\tunsigned\t\t\t\t\tTimerHandle;\n\n};\n\nextern \"C\" {\n\t void __cdecl Mouse_Shadow_Buffer(void *thisptr, GraphicBufferClass *srcdst, void *buffer, int x, int y, int hotx, int hoty, int store);\n\t void __cdecl Draw_Mouse(void *thisptr, GraphicBufferClass *srcdst, int x, int y);\n\t void __cdecl *ASM_Set_Mouse_Cursor(void * thisptr, int hotspotx, int hotspoty, VOID *cursor);\n};\n\nvoid Hide_Mouse(void);\nvoid Show_Mouse(void);\nvoid Conditional_Hide_Mouse(int x1, int y1, int x2, int y2);\nvoid Conditional_Show_Mouse(void);\nint Get_Mouse_State(void);\nvoid *Set_Mouse_Cursor(int hotx, int hoty, void *cursor);\nint Get_Mouse_X(void);\nint Get_Mouse_Y(void);\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/MOUSE.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;*********************************************************************************************** \n;*                                                                                             * \n;*                 Project Name : Westwood 32 bit Library                                      * \n;*                                                                                             * \n;*                    File Name : MOUSE.INC                                                    * \n;*                                                                                             * \n;*                   Programmer : Philip W. Gorrow                                             * \n;*                                                                                             * \n;*                   Start Date : 12/12/95                                                     * \n;*                                                                                             * \n;*                  Last Update : December 12, 1995 [PWG]                                      * \n;*                                                                                             * \n;*---------------------------------------------------------------------------------------------* \n;* Functions:                                                                                  * \n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nSTRUC MouseType\nMouseCursor\t\tDD\t\t?\t\t\t; pointer to the mouse cursor in memory\nMouseXHot\t\tDD\t\t?\t\t\t; X hot spot of the current mouse cursor\nMouseYHot\t\tDD\t\t?\t\t\t; Y hot spot of the current mouse cursor\nCursorWidth\t\tDD\t\t?\t\t\t; Width of mouse cursor in pixels\nCursorHeight\tDD\t\t?\t\t\t; Height of the mouse cursor in pixels\n\nMouseBuffer\t\tDD\t\t?\t\t\t; pointer to background buffer in memory\nMouseBuffX\t\tDD\t\t?\t\t\t; pixel x mouse buffer was preserved at\nMouseBuffY\t\tDD\t\t?\t\t\t; pixel y mouse buffer was preserved at\nMaxWidth\t\t\tDD\t\t?\t\t\t; Maximum possible width of the background buffer\nMaxHeight\t\tDD\t\t?\t\t\t; Maximum possible height of the background buffer\n\nMouseCXLeft\t\tDD\t\t?\t\t\t; left hand x position if conditional hide mouse in effect\nMouseCYUpper\tDD\t\t?\t\t\t; upper y position if conditional hide mouse in effect\nMouseCXRight\tDD\t\t?\t\t\t; right hand x position if conditional hide mouse in effect\nMouseCYLower\tDD\t\t?\t\t\t; lower y position if conditional hide mouse in effect\nMCFlags\t\t\tDB\t\t?\t\t\t; conditional hide mouse flags\nMCCount\t\t\tDB\t\t?\t\t\t; nesting count for conditional hide mouse\n\nScreen\t\t\tDD\t\t?\t\t\t; pointer to the surface mouse was init'd with\nPrevCursor\t\tDD\t\t?\t\t\t; pointer to the prev cursor shape\nMouseUpdate\t\tDD\t\t?\t\t\t; is the mouse being currently updated\nState\t\t\t\tDD\t\t?\n\nEraseBuffer\t\tDD\t\t?\nEraseBuffX\t\tDD\t\t?\nEraseBuffY\t\tDD\t\t?\nEraseBuffHotX\tDD\t\t?\nEraseBuffHotY\tDD\t\t?\nEraseFlags\t\tDD\t\t?\nENDS\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/PAGFAULT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : PAGFAULT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Julio R Jerez \t                   *\n;*                                                                         *\n;*                   \t   Date : April 25,1995                            *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;\n; Here are prototypes for the routines defined within this module:\n; VOID Install_Page_Fault_Handle (void) ;\n;\n; ----------------------------------------------------------------\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Make some general equates for easy compatability\n;---------------------------------------------------------------------------\nDPMI_INTR\t EQU\t31h  \nPAGE_FAULT\t equ\t0eh\nRESET_VIDEO_MODE  equ\t-1\n\nGLOBAL\t Install_Page_Fault_Handle : NEAR\nGLOBAL\t Set_Video_Mode\t\t   : NEAR\t\t\nGLOBAL\t Remove_Mouse\t\t   : NEAR\nGLOBAL\t Remove_Keyboard_Interrupt : NEAR\nGLOBAL\t Remove_Timer_Interrupt\t   : NEAR\t\n\nDATASEG\n\tOld_Page_Fault_handle DF ?\n\tPage_Fault_SS \tDD\t?\n\tPage_Fault_ESP\tDD\t?\n\nCODESEG\n;***************************************************************************\n;* INSTALL_PAGE_FAULT_HANDLE -- Installs new page fault handle             *\n;*\tThis function will install a new page fault handle \t\t   *\n;*\tso in the event that we have a program crash thi handle will\t   *\n;*\tremove all interrupts and then will chain to the default Page\t   *\n;*\tFault handle\t\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Install_Page_Fault_Handle( void);  \t\t   *\n;*                                                                         *\n;* HISTORY:  04/25/96 Created                                              *\n;*=========================================================================*\n\tPROC\tInstall_Page_Fault_Handle C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tmov\teax,0202h \t; get address of exception handle\n\tmov\tbl,PAGE_FAULT\n\tint\tDPMI_INTR\n\tjc\t??exit\t\t; not action is taken \n\n\t; save addrees of default handle\n\tmov\t[dword ptr Old_Page_Fault_handle],edx\n\tmov\t[word ptr  Old_Page_Fault_handle+4],cx\n\n\t; redirect default handle to a new Page Fault Handle\n\tmov eax,0203h\t\t\n\tmov bl,PAGE_FAULT\n\tmov cx,cs\n\tlea edx,[Page_Fault_Handle]\n\tint DPMI_INTR \n\n  ??exit:\n\tret\n\tENDP\tInstall_Page_Fault_Handle\n\n\n;***************************************************************************\n;* PAGE_FAULT_HANDLE --  This           \t\t   \t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* HISTORY:  04/25/96 Created                                              *\n;*=========================================================================*\nPROC\tPage_Fault_Handle far \n\n\t; preserve used  registers\n\tpush\teax\n\tpush\tebx\n\t; save Page Fault satck frame\n\tmov\tax,ss\t\n\tmov\t[Page_Fault_SS],eax\n\tmov\t[Page_Fault_ESP],esp\n\n\t; retrieve application original stack frame\n\tmov eax , [ esp + ( 6 + 2 ) * 4 ] \n\tmov ebx , [ esp + ( 7 + 2 ) * 4 ]\n\tmov ss , bx\n\tmov esp , eax\n\n\t; set video mode to standard text mode\n\tpush\tRESET_VIDEO_MODE\n\tcall \tSet_Video_Mode\n\tpop\teax\n\tcall \tRemove_Mouse\n\tcall \tRemove_Keyboard_Interrupt\n\tcall\tRemove_Timer_Interrupt\n\n\t; restore Page Fault stack frame\n\tmov\teax,[Page_Fault_SS]\n\tmov \tss , ax\n\tmov\tesp, [Page_Fault_ESP]\n\n\t; restore used registers and chain to default Page Fault Handle\n\tpop\tebx\n\tpop\teax\n\tjmp\t[fword Old_Page_Fault_handle]\n\n\tENDP\tPage_Fault_Handle\n\n\n;***************************************************************************\n;* End of File.\t\t\t\t\t\t\t\t   *\n;***************************************************************************\nEND\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/WWMOUSE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : BITBLIT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Philip W. Gorrow\t\t\t   *\n;*                                                                         *\n;*                   Start Date : December 12, 1995                        *\n;*                                                                         *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \"drawbuff.inc\"\nINCLUDE \"gbuffer.inc\"\nINCLUDE \"shape.inc\"\nINCLUDE \".\\mouse.inc\"\n\nGLOBAL\tC LCW_Uncompress:NEAR\nGLOBAL\tC Get_Shape_Uncomp_Size     :NEAR\nGLOBAL\tC Get_Shape_Width      \t  :NEAR\nGLOBAL\tC Get_Shape_Original_Height :NEAR\nGLOBAL\t_ShapeBuffer\t\t  :DWORD\n\nCODESEG\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tMouseClass *\t\t- pointer to mouse class data\t   *\n;*\t\tGraphicBufferClass *\t- screen to draw the mouse on\t   *\n;*\t\tint x\t\t\t- x position to store the mouse at *\n;*\t\tint y\t\t\t- y position to store the mouse at *\n;*\t\tint store\t\t- whether to store buffer or save  *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* Note: The x and y that this routine expects to receive are based on\t   *\n;*       the mouse cursor position.  This routine automatically adjusts\t   *\n;*\t for hot spot, so that adjustment should not be made prior to\t   *\n;*\t this point.\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tvoid Mouse_Shadow_Buffer(GraphicBufferClass *src/dest,\t   *\n;*\t\t\t\t\tvoid *buffer\n;*\t\t\t\t\tint x_pixel,\t\t\t   *\n;*\t\t\t\t\tint y_pixel,\t\t\t   *\n;*\t\t\t\t\tint store);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Mouse_Shadow_Buffer:NEAR\n\tPROC\tMouse_Shadow_Buffer C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\n\tARG\tthis:\t\tDWORD\n\tARG\tsrc_dst_obj:\tDWORD\n\tARG\tbuffer:DWORD\n\tARG\tx:\t\tDWORD\n\tARG\ty:\t\tDWORD\n\tARG\thotx:\t\tDWORD\n\tARG\thoty:\t\tDWORD\n\tARG\tstore:\t\tDWORD\n\n\tlocal\tx0: \t\tdword\n\tlocal\ty0: \t\tdword\n\tlocal\tx1: \t\tdword\n\tlocal\ty1: \t\tdword\n\tlocal\tbuffx0: \tdword\n\tlocal\tbuffy0: \tdword\n\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tesi, [this]\t\t\t; get offset to mouse data\n\tmov\tedi, [src_dst_obj]\t\t; get offset to mouse data\n\n\tmov\teax, [x]\n\tmov\tebx, [y]\n\tsub\teax, [hotx]\n\tsub\tebx, [hoty]\n\n\tmov\t[x0], eax  \n\tmov\t[y0], ebx  \n\tadd\teax, [(MouseType esi).CursorWidth]\n\tadd\tebx, [(MouseType esi).CursorHeight]\n\tmov\t[x1], eax  \n\tmov\t[y1], ebx  \n\n\tmov\t[buffx0], 0\n\tmov\teax, [buffer]\n\tmov\t[buffy0], eax\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\n\txor \teax, eax\n\txor \tedx, edx\n\n\tmov\tecx, [x0]  \n\tmov\tebx, [x1]  \n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [x0]  \n\tmov\tebx, [x1]  \n\tsub\tecx, [(GraphicViewPort edi).GVPWidth]\n\tsub\tebx, [(GraphicViewPort edi).GVPWidth]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [y0]  \n\tmov\tebx, [y1]  \n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [y0]  \n\tmov\tebx, [y1]  \n\tsub\tecx, [(GraphicViewPort edi).GVPHeight]\n\tsub\tebx, [(GraphicViewPort edi).GVPHeight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\txor\tal, 5\n\txor\tdl, 5\n\tmov\tah, al\n\ttest\tdl, al\n\tjnz\t??out\n\tor\tal, dl\n\tjz\t??not_clip\n\n\ttest\tah, 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx, [x0]\n\tneg\tebx\n\tmov\t[buffx0], ebx\n\tmov\t[x0], 0\n\n??scr_left_ok:\n\ttest\tah, 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx, [y0]\n\tneg\tebx\n\timul\tebx, [(MouseType esi).CursorWidth]\n\tadd\t[buffy0], ebx\n\tmov\t[y0], 0\n\n??scr_bottom_ok:\n\ttest\tdl, 0100b\n\tjz\t??scr_right_ok\n\tmov\teax, [(GraphicViewPort edi).GVPWidth]  ; get width into register\n\tmov\t[x1], eax\n??scr_right_ok:\n\ttest\tdl, 0001b\n\tjz\t??not_clip\n\tmov\teax, [(GraphicViewPort edi).GVPHeight]  ; get width into register\n\tmov\t[y1], eax\n\n??not_clip:\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax, [y0]\n\tmov\tedx, [(GraphicViewPort edi).GVPWidth]\n\tadd\tedx, [(GraphicViewPort edi).GVPXAdd]\n\tadd\tedx, [(GraphicViewPort edi).GVPPitch]\n\timul\teax, edx\n\tadd\teax, [x0]\n\tmov\tedi, [(GraphicViewPort edi).GVPOffset]\n\tadd\tedi, eax\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx, [(MouseType esi).CursorWidth]\t; turn this into an offset\n\tmov\tesi, [buffy0]\t\t\t; edx points to source\n\tadd\tesi, [buffx0]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax, [x1]\n\tmov\tecx, [y1]\n\tsub\teax, [x0]\n\tjle\t??out\n\tsub\tecx, [y0]\n\tjle\t??out\n\n\tsub\tedx, eax\n\tsub\tebx, eax\t\n\tpush\tebp\n\tcmp\t[store], 1\t\t\t\t\t; are we storing page?\n\tje\t\t??store_entry\t\t\t\t; if so go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tebp, ecx\n??restore_loop:\n\tmov\tecx, eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi, ebx\t\t\t\t; move past right clipped pixels\n\tadd\tedi, edx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tesi, edi\t\t\t\t\t; xchg the source and the dest\n\tmov\tebp, ecx\n??store_loop:\n\tmov\tecx, eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi, edx\t\t\t\t; move past right clipped pixels\n\tadd\tedi, ebx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n??out:\n\tret\n\tENDP\tMouse_Shadow_Buffer\n\n;***************************************************************************\n;* DRAW_MOUSE -- Handles drawing the mouse cursor\t\t\t   *\n;*                                                                         *\n;* INPUT:\tMouseClass *\t\t- pointer to mouse class data\t   *\n;*\t\tGraphicBufferClass *\t- screen to draw the mouse on\t   *\n;*\t\tint x\t\t\t- x position to store the mouse at *\n;*\t\tint y\t\t\t- y position to store the mouse at *\n;*                                                                         *\n;* Note: The x and y that this routine expects to receive are based on\t   *\n;*       the mouse cursor position.  This routine automatically adjusts\t   *\n;*\t for hot spot, so that adjustment should not be made prior to\t   *\n;*\t this point.\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* PROTO:       void Draw_Mouse(\tMouseClass * mouse_data,\t   *\n;*\t\t\t\t\tGraphicBufferClass *destination,   *\n;*\t\t\t\t\tint x_pixel,\t\t\t   *\n;* \t\t\t\t\tint y_pixel);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Draw_Mouse:NEAR\n\tPROC\tDraw_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\n\tARG\tthis:DWORD\n\tARG\tdest:DWORD\n\tARG\tmousex:DWORD\n\tARG\tmousey:DWORD\n\n\tlocal\tx0:dword\n\tlocal\ty0:dword\n\tlocal\tx1:dword\n\tlocal\ty1:dword\n\tlocal\tbuffx0:dword\n\tlocal\tbuffy0:dword\n\n\n\tmov\tesi, [this]    \t; get 32 bit offset to mouse data\n\tmov\tedi, [dest]\t; get 32 bit offset to dest buffer\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax, [mousex]\n\tmov\tebx, [mousey]\n\tsub\teax, [(MouseType esi).MouseXHot]\n\tsub\tebx, [(MouseType esi).MouseYHot]\n\n\tmov\t[x0], eax  \n\tmov\t[y0], ebx  \n\tadd\teax,[(MouseType esi).CursorWidth]\n\tadd\tebx,[(MouseType esi).CursorHeight]\n\tmov\t[x1], eax  \n\tmov\t[y1], ebx  \n\n\tmov\t[buffx0], 0\n\tmov\teax, [(MouseType esi).MouseCursor]\n\tmov\t[buffy0], eax\n\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\txor \teax, eax\n\txor \tedx, edx\n\n\tmov\tecx, [x0]  \n\tmov\tebx, [x1]  \n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [x0]  \n\tmov\tebx, [x1]  \n\tsub\tecx, [(GraphicViewPort edi).GVPWidth]\n\tsub\tebx, [(GraphicViewPort edi).GVPWidth]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [y0]  \n\tmov\tebx, [y1]  \n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [y0]  \n\tmov\tebx, [y1]  \n\tsub\tecx, [(GraphicViewPort edi).GVPHeight]\n\tsub\tebx, [(GraphicViewPort edi).GVPHeight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\txor\tal, 5\n\txor\tdl, 5\n\tmov\tah, al\n\ttest\tdl, al\n\tjnz\t??out\n\tor\tal, dl\n\tjz\t??not_clip\n\n\ttest\tah, 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx, [x0]\n\tneg\tebx\n\tmov\t[buffx0], ebx\n\tmov\t[x0], 0\n\n??scr_left_ok:\n\ttest\tah, 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx, [y0]\n\tneg\tebx\n\timul\tebx, [(MouseType esi).CursorWidth]\n\tadd\t[buffy0], ebx\n\tmov\t[y0], 0\n\n??scr_bottom_ok:\n\ttest\tdl, 0100b\n\tjz\t??scr_right_ok\n\tmov\teax, [(GraphicViewPort edi).GVPWidth]  ; get width into register\n\tmov\t[x1] , eax\n??scr_right_ok:\n\ttest\tdl, 0001b\n\tjz\t??not_clip\n\tmov\teax, [(GraphicViewPort edi).GVPHeight]  ; get width into register\n\tmov\t[y1] , eax\n\n??not_clip:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax, [y0]\n\tmov\tedx, [(GraphicViewPort edi).GVPWidth]\n\tadd\tedx, [(GraphicViewPort edi).GVPXAdd]\n\tadd\tedx, [(GraphicViewPort edi).GVPPitch]\n\timul\teax, edx\n\tadd\teax, [x0]\n\tmov\tedi, [(GraphicViewPort edi).GVPOffset]\n\tadd\tedi, eax\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx, [(MouseType esi).CursorWidth]\t; turn this into an offset\n\tmov\tesi, [buffy0]\t\t\t; edx points to source\n\tadd\tesi, [buffx0]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax, [x1]\n\tmov\tecx, [y1]\n\tsub\teax, [x0]\n\tjle\t??out\n\tsub\tecx, [y0]\n\tjle\t??out\n\n\tsub\tedx, eax\n\tsub\tebx, eax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah, al\n??inner_loop:\n\tmov\tch, [esi]\n\tinc\tesi\n\tor\tch, ch\n\tjz\t??inc_edi\n\tmov\t[edi], ch\n??inc_edi:\n\tinc\tedi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tesi, ebx      \t\t\t; move past right clipped pixels\n\tadd\tedi, edx      \t\t\t; adjust dest to next line\n\tdec\tcl\t      \t\t\t; decrement number of rows to do\n\tjnz\t??top_loop    \t\t\t; if more to do, do it\n??out:\n\tret\n\n\tENDP\tDraw_Mouse\n;***************************************************************************\n;* SET_MOUSE_CURSOR -- Sets the shape to be used as the mouse.             *\n;*                                                                         *\n;*    This will inform the system of the shape desired as the mouse        *\n;*    cursor.                                                              *\n;*                                                                         *\n;* INPUT:    xhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           yhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           cursor      -- Shape to use as the new mouse shape.           *\n;*                                                                         *\n;* OUTPUT:   Returns with a pointer to the original mouse shape.           *\n;*                                                                         *\n;* PROTO:\tVOID  *Set_Mouse_Cursor(\tint  xhotspot, \t\t   *\n;*\t\t\t\t\t\tint  yhotspot, \t\t   *\n;*\t\t\t\t\t\tvoid *cursor);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   02/13/1992 JLB : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC ASM_Set_Mouse_Cursor:NEAR\n\tPROC\tASM_Set_Mouse_Cursor C NEAR \n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\tthis:DWORD\t\t\t\t; pointer to mouse cursor struct\n\tARG\txhotspot:DWORD\t\t\t\t; the x hot spot of the mouse\n\tARG\tyhotspot:DWORD\t\t\t\t; the y hot spot of the mouse\n\tARG\tcursor:DWORD\t\t\t\t; ptr to the new mouse cursor\n\n\tLOCAL\tdatasize:DWORD\n\tLOCAL\tstype:WORD\n\tLOCAL\tswidth:DWORD\t\t; Shape width.\n\tLOCAL\tsheight:DWORD\t\t; Shape height.\n\tLOCAL\tssize:DWORD\t\t; Size of raw shape.\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\tmov\tesi,[this]\t\t\t; get offset of real mode data start\n\n\t;-------------------------------------------------------------------\n\t; Calculate the size of the buffer needed.\n\t;-------------------------------------------------------------------\n\tpush\t[cursor]\n\tcall\tGet_Shape_Uncomp_Size\n\tpop\tedx\n\tmov\t[datasize],eax\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Width\n\tpop\tedx\n\tmov\t[swidth],eax\n\tcmp\teax,[(MouseType esi).MaxWidth]\n\tjg\t??end\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Original_Height\n\tpop\tedx\n\tmov\t[sheight],eax\n\tcmp\teax,[(MouseType esi).MaxHeight]\n\tjg\t??end\n\n\n\tmov\tebx,[sheight]\n\tmov\teax,[swidth]\n\timul\tebx,eax\n\n??copy_mouse:\n\tmov\tedi,[(MouseType esi).MouseCursor]\t\t; set edi to point to mouse buffer\n\tmov\tesi,[cursor]\t\t\t; set esi to point to mouse shape\n\tmov\tax,[esi]\t\t\t; get the shape type byte\n\tmov\t[stype],ax\t\t\t; save off the shape type\n\ttest\tax,MAKESHAPE_NOCOMP\t\t; is it marked as no compression?\n\tje\t??comp_shape\t\t\t; if not go to the comped shape code\n\n??copy_type:\n\n\ttest\t[stype],MAKESHAPE_COMPACT\t; if the shape a 16 color shape?\n\tjne\t??16_color_copy\t\t\t; if it is then go handle it\n\n??normal_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed NORMAL shapes just get run-length uncompressed\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t\t; find size of shape in pixels\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes \n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??norm_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??norm_trans\t\t\t; if its a zero its transparent\n\tmov\t[edi],al\t\t\t; write out the pixel to dest\n\tinc\tedi\t\t\t\t; move to next dest position\n\tdec\tedx\t\t\t\t; we have now written another pix\n\tjnz\t??norm_unrle\t\t\t; if more to write then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are all done\n\n??norm_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\n\tjnz\t??norm_unrle\t\t\t; if more to do then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are done\n\n??16_color_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed 16 color shapes just get remaped and UN-RLE'd\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\tebx,esi\t\t\t\t; save of position of remap\n\tadd\tesi,16\t\t\t\t; move past remap table\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t; load up the height\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes \n\txor\teax,eax\t\t\t\t; clear high of lookup variable\n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??16_color_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??16_color_trans\t\t; if its a zero its transparent\n\tmov\tal,[ebx+eax]\t\t\t; remap the pixel from 16 color table\n\tmov\t[edi],al\t\t\t; store it out to the dest address\n\tinc\tedi\t\t\t\t; move to next dest address\n\tdec\tedx\t\t\t\t; we have now written a pixel\n\tjnz\t??16_color_unrle\n\tjmp\t??done_copy\n??16_color_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\t\t\t\t; subtract off count ahead of time\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\t\t\t\t; or edx to test for zero\n\tjnz\t??16_color_unrle\t\t\n\tjmp\t??done_copy\n\n\t;-------------------------------------------------------------------\n\t; Deal with the compressed shape by copying it into the shape\n\t;   staging buffer.\n\t;-------------------------------------------------------------------\n??comp_shape:\n\tmov\tedi,[ShapeBuffer]\t; get a pointer to ShapeBuffer\n\tmov\tax,[esi]\t\t; load in the shape type\n\tadd\tesi,2\t\t\t; increment the shape pointer\n\tor\tax,MAKESHAPE_NOCOMP\t; make the shape as uncompressed\n\tmov\t[stype],ax\t\t; save off the shape type\n\tmov\t[edi],ax\t\t; write out uncompressed shape\n\tadd\tedi,2\n\n\t;-------------------------------------------------------------------\n\t; Process the shape header information and copy it over to the new\n\t;   location.\n\t;-------------------------------------------------------------------\n\tmov\tecx,4 \t\t\t; transfer height, width, org and\n\ttest\teax,MAKESHAPE_COMPACT\t; is it a 16 color shape?\n\tje\t??copy_head\t\t; no - don't worry about it\n\tadd\tecx,8\t\t\t; otherwise adjust ecx for header\n??copy_head:\n\trep\tmovsw\t\t\t; copy the necessary bytes\n\t\n\tmov \teax,[datasize]\t\t; get uncompressed length\n\tpush\teax\t\t\t; push as third param\n\tpush\tedi\t\t\t; push the destination offset\n\tpush\tesi\t\t\t; push the source offset\n\tcall\tLCW_Uncompress\t\t; do the uncompress\n\tpop\teax\n\tpop\teax\n\tpop\teax\n\tmov\tesi,[this]\n\tmov\tedi,[(MouseType esi).MouseCursor]\t\t; set edi to point to mouse buffer\n\tmov\tesi,[ShapeBuffer]\n\tjmp\t??copy_type\n\n??done_copy:\n\tmov\tesi,[this]\t; get offset of real mode data start\n\n\tmov\teax,[xhotspot]\t\t; get the mouse cursors x hotspot\n\tmov\t[(MouseType esi).MouseXHot],eax\n\tmov\teax,[yhotspot]\t\t; get the mouse cursors y hotspot\n\tmov\t[(MouseType esi).MouseYHot],eax\n\n\tmov\tebx,[sheight]\t\t; get shape height\n\tmov\t[(MouseType esi).CursorHeight],ebx\n\tmov\tebx,[swidth]\n\tmov\t[(MouseType esi).CursorWidth],ebx\n\n\t;-------------------------------------------------------------------\n\t; Final cleanup and exit.\n\t;-------------------------------------------------------------------\n??end:\n\tpush\t[cursor]\n\tpush\t[(MouseType esi).PrevCursor]\n\tpop\teax\n\tpop\t[(MouseType esi).PrevCursor]\n\tret\t\t\t\t; and return back to the world\n\n\tENDP\tASM_Set_Mouse_Cursor\n\nEND\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLD/WWMOUSE.ASM.BAK",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : BITBLIT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Philip W. Gorrow\t\t\t   *\n;*                                                                         *\n;*                   Start Date : December 12, 1995                        *\n;*                                                                         *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \"drawbuff.inc\"\nINCLUDE \"gbuffer.inc\"\nINCLUDE \"shape.inc\"\nINCLUDE \".\\mouse.inc\"\n\nGLOBAL\tC LCW_Uncompress:NEAR\nGLOBAL\tC Get_Shape_Uncomp_Size     :NEAR\nGLOBAL\tC Get_Shape_Width      \t  :NEAR\nGLOBAL\tC Get_Shape_Original_Height :NEAR\nGLOBAL\t_ShapeBuffer\t\t  :DWORD\n\nCODESEG\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tMouseClass *\t\t- pointer to mouse class data\t   *\n;*\t\tGraphicBufferClass *\t- screen to draw the mouse on\t   *\n;*\t\tint x\t\t\t- x position to store the mouse at *\n;*\t\tint y\t\t\t- y position to store the mouse at *\n;*\t\tint store\t\t- whether to store buffer or save  *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* Note: The x and y that this routine expects to receive are based on\t   *\n;*       the mouse cursor position.  This routine automatically adjusts\t   *\n;*\t for hot spot, so that adjustment should not be made prior to\t   *\n;*\t this point.\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tvoid Mouse_Shadow_Buffer(GraphicBufferClass *src/dest,\t   *\n;*\t\t\t\t\tint x_pixel,\t\t\t   *\n;*\t\t\t\t\tint y_pixel,\t\t\t   *\n;*\t\t\t\t\tint store);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Mouse_Shadow_Buffer:NEAR\n\tPROC\tMouse_Shadow_Buffer C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\n\tARG\tthis:\t\tDWORD\n\tARG\tsrc_dst_obj:\tDWORD\n\tARG\tx:\t\tDWORD\n\tARG\ty:\t\tDWORD\n\tARG\tstore:\t\tDWORD\n\n\tlocal\tx0: \t\tdword\n\tlocal\ty0: \t\tdword\n\tlocal\tx1: \t\tdword\n\tlocal\ty1: \t\tdword\n\tlocal\tbuffx0: \tdword\n\tlocal\tbuffy0: \tdword\n\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tesi, [this]\t\t\t; get offset to mouse data\n\tmov\tedi, [src_dst_obj]\t\t; get offset to mouse data\n\n\tmov\teax, [x]\n\tmov\tebx, [y]\n\tsub\teax, [(MouseType esi).MouseXHot]\n\tsub\tebx, [(MouseType esi).MouseYHot]\n\n\tmov\t[x0], eax  \n\tmov\t[y0], ebx  \n\tadd\teax, [(MouseType esi).CursorWidth]\n\tadd\tebx, [(MouseType esi).CursorHeight]\n\tmov\t[x1], eax  \n\tmov\t[y1], ebx  \n\n\tmov\t[buffx0], 0\n\tmov\teax, [(MouseType esi).MouseBuffer]\n\tmov\t[buffy0], eax\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\n\txor \teax, eax\n\txor \tedx, edx\n\n\tmov\tecx, [x0]  \n\tmov\tebx, [x1]  \n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [x0]  \n\tmov\tebx, [x1]  \n\tsub\tecx, [(GraphicViewPort edi).GVPWidth]\n\tsub\tebx, [(GraphicViewPort edi).GVPWidth]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [y0]  \n\tmov\tebx, [y1]  \n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [y0]  \n\tmov\tebx, [y1]  \n\tsub\tecx, [(GraphicViewPort edi).GVPHeight]\n\tsub\tebx, [(GraphicViewPort edi).GVPHeight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\txor\tal, 5\n\txor\tdl, 5\n\tmov\tah, al\n\ttest\tdl, al\n\tjnz\t??out\n\tor\tal, dl\n\tjz\t??not_clip\n\n\ttest\tah, 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx, [x0]\n\tneg\tebx\n\tmov\t[buffx0], ebx\n\tmov\t[x0], 0\n\n??scr_left_ok:\n\ttest\tah, 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx, [y0]\n\tneg\tebx\n\timul\tebx, [(MouseType esi).CursorWidth]\n\tadd\t[buffy0], ebx\n\tmov\t[y0], 0\n\n??scr_bottom_ok:\n\ttest\tdl, 0100b\n\tjz\t??scr_right_ok\n\tmov\teax, [(GraphicViewPort edi).GVPWidth]  ; get width into register\n\tmov\t[x1], eax\n??scr_right_ok:\n\ttest\tdl, 0001b\n\tjz\t??not_clip\n\tmov\teax, [(GraphicViewPort edi).GVPHeight]  ; get width into register\n\tmov\t[y1], eax\n\n??not_clip:\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax, [y0]\n\tmov\tedx, [(GraphicViewPort edi).GVPWidth]\n\tadd\tedx, [(GraphicViewPort edi).GVPXAdd]\n\tadd\tedx, [(GraphicViewPort edi).GVPPitch]\n\timul\teax, edx\n\tadd\teax, [x0]\n\tmov\tedi, [(GraphicViewPort edi).GVPOffset]\n\tadd\tedi, eax\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx, [(MouseType esi).CursorWidth]\t; turn this into an offset\n\tmov\tesi, [buffy0]\t\t\t; edx points to source\n\tadd\tesi, [buffx0]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax, [x1]\n\tmov\tecx, [y1]\n\tsub\teax, [x0]\n\tjle\t??out\n\tsub\tecx, [y0]\n\tjle\t??out\n\n\tsub\tedx, eax\n\tsub\tebx, eax\t\n\tpush\tebp\n\tcmp\t[store], 1\t\t\t\t\t; are we storing page?\n\tje\t\t??store_entry\t\t\t\t; if so go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tebp, ecx\n??restore_loop:\n\tmov\tecx, eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi, ebx\t\t\t\t; move past right clipped pixels\n\tadd\tedi, edx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tesi, edi\t\t\t\t\t; xchg the source and the dest\n\tmov\tebp, ecx\n??store_loop:\n\tmov\tecx, eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi, edx\t\t\t\t; move past right clipped pixels\n\tadd\tedi, ebx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n??out:\n\tret\n\tENDP\tMouse_Shadow_Buffer\n\n;***************************************************************************\n;* DRAW_MOUSE -- Handles drawing the mouse cursor\t\t\t   *\n;*                                                                         *\n;* INPUT:\tMouseClass *\t\t- pointer to mouse class data\t   *\n;*\t\tGraphicBufferClass *\t- screen to draw the mouse on\t   *\n;*\t\tint x\t\t\t- x position to store the mouse at *\n;*\t\tint y\t\t\t- y position to store the mouse at *\n;*                                                                         *\n;* Note: The x and y that this routine expects to receive are based on\t   *\n;*       the mouse cursor position.  This routine automatically adjusts\t   *\n;*\t for hot spot, so that adjustment should not be made prior to\t   *\n;*\t this point.\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* PROTO:       void Draw_Mouse(\tMouseClass * mouse_data,\t   *\n;*\t\t\t\t\tGraphicBufferClass *destination,   *\n;*\t\t\t\t\tint x_pixel,\t\t\t   *\n;* \t\t\t\t\tint y_pixel);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Draw_Mouse:NEAR\n\tPROC\tDraw_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\n\tARG\tthis:DWORD\n\tARG\tdest:DWORD\n\tARG\tmousex:DWORD\n\tARG\tmousey:DWORD\n\n\tlocal\tx0:dword\n\tlocal\ty0:dword\n\tlocal\tx1:dword\n\tlocal\ty1:dword\n\tlocal\tbuffx0:dword\n\tlocal\tbuffy0:dword\n\n\n\tmov\tesi, [this]    \t; get 32 bit offset to mouse data\n\tmov\tedi, [dest]\t; get 32 bit offset to dest buffer\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax, [mousex]\n\tmov\tebx, [mousey]\n\tsub\teax, [(MouseType esi).MouseXHot]\n\tsub\tebx, [(MouseType esi).MouseYHot]\n\n\tmov\t[x0], eax  \n\tmov\t[y0], ebx  \n\tadd\teax,[(MouseType esi).CursorWidth]\n\tadd\tebx,[(MouseType esi).CursorHeight]\n\tmov\t[x1], eax  \n\tmov\t[y1], ebx  \n\n\tmov\t[buffx0], 0\n\tmov\teax, [(MouseType esi).MouseCursor]\n\tmov\t[buffy0], eax\n\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\txor \teax, eax\n\txor \tedx, edx\n\n\tmov\tecx, [x0]  \n\tmov\tebx, [x1]  \n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [x0]  \n\tmov\tebx, [x1]  \n\tsub\tecx, [(GraphicViewPort edi).GVPWidth]\n\tsub\tebx, [(GraphicViewPort edi).GVPWidth]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [y0]  \n\tmov\tebx, [y1]  \n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [y0]  \n\tmov\tebx, [y1]  \n\tsub\tecx, [(GraphicViewPort edi).GVPHeight]\n\tsub\tebx, [(GraphicViewPort edi).GVPHeight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\txor\tal, 5\n\txor\tdl, 5\n\tmov\tah, al\n\ttest\tdl, al\n\tjnz\t??out\n\tor\tal, dl\n\tjz\t??not_clip\n\n\ttest\tah, 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx, [x0]\n\tneg\tebx\n\tmov\t[buffx0], ebx\n\tmov\t[x0], 0\n\n??scr_left_ok:\n\ttest\tah, 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx, [y0]\n\tneg\tebx\n\timul\tebx, [(MouseType esi).CursorWidth]\n\tadd\t[buffy0], ebx\n\tmov\t[y0], 0\n\n??scr_bottom_ok:\n\ttest\tdl, 0100b\n\tjz\t??scr_right_ok\n\tmov\teax, [(GraphicViewPort edi).GVPWidth]  ; get width into register\n\tmov\t[x1] , eax\n??scr_right_ok:\n\ttest\tdl, 0001b\n\tjz\t??not_clip\n\tmov\teax, [(GraphicViewPort edi).GVPHeight]  ; get width into register\n\tmov\t[y1] , eax\n\n??not_clip:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax, [y0]\n\tmov\tedx, [(GraphicViewPort edi).GVPWidth]\n\tadd\tedx, [(GraphicViewPort edi).GVPXAdd]\n\tadd\tedx, [(GraphicViewPort edi).GVPPitch]\n\timul\teax, edx\n\tadd\teax, [x0]\n\tmov\tedi, [(GraphicViewPort edi).GVPOffset]\n\tadd\tedi, eax\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx, [(MouseType esi).CursorWidth]\t; turn this into an offset\n\tmov\tesi, [buffy0]\t\t\t; edx points to source\n\tadd\tesi, [buffx0]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax, [x1]\n\tmov\tecx, [y1]\n\tsub\teax, [x0]\n\tjle\t??out\n\tsub\tecx, [y0]\n\tjle\t??out\n\n\tsub\tedx, eax\n\tsub\tebx, eax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah, al\n??inner_loop:\n\tmov\tch, [esi]\n\tinc\tesi\n\tor\tch, ch\n\tjz\t??inc_edi\n\tmov\t[edi], ch\n??inc_edi:\n\tinc\tedi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tesi, ebx      \t\t\t; move past right clipped pixels\n\tadd\tedi, edx      \t\t\t; adjust dest to next line\n\tdec\tcl\t      \t\t\t; decrement number of rows to do\n\tjnz\t??top_loop    \t\t\t; if more to do, do it\n??out:\n\tret\n\n\tENDP\tDraw_Mouse\n;***************************************************************************\n;* SET_MOUSE_CURSOR -- Sets the shape to be used as the mouse.             *\n;*                                                                         *\n;*    This will inform the system of the shape desired as the mouse        *\n;*    cursor.                                                              *\n;*                                                                         *\n;* INPUT:    xhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           yhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           cursor      -- Shape to use as the new mouse shape.           *\n;*                                                                         *\n;* OUTPUT:   Returns with a pointer to the original mouse shape.           *\n;*                                                                         *\n;* PROTO:\tVOID  *Set_Mouse_Cursor(\tint  xhotspot, \t\t   *\n;*\t\t\t\t\t\tint  yhotspot, \t\t   *\n;*\t\t\t\t\t\tvoid *cursor);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   02/13/1992 JLB : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC ASM_Set_Mouse_Cursor:NEAR\n\tPROC\tASM_Set_Mouse_Cursor C NEAR \n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\tthis:DWORD\t\t\t\t; pointer to mouse cursor struct\n\tARG\txhotspot:DWORD\t\t\t\t; the x hot spot of the mouse\n\tARG\tyhotspot:DWORD\t\t\t\t; the y hot spot of the mouse\n\tARG\tcursor:DWORD\t\t\t\t; ptr to the new mouse cursor\n\n\tLOCAL\tdatasize:DWORD\n\tLOCAL\tstype:WORD\n\tLOCAL\tswidth:DWORD\t\t; Shape width.\n\tLOCAL\tsheight:DWORD\t\t; Shape height.\n\tLOCAL\tssize:DWORD\t\t; Size of raw shape.\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\tmov\tesi,[this]\t\t\t; get offset of real mode data start\n\n\t;-------------------------------------------------------------------\n\t; Calculate the size of the buffer needed.\n\t;-------------------------------------------------------------------\n\tpush\t[cursor]\n\tcall\tGet_Shape_Uncomp_Size\n\tpop\tedx\n\tmov\t[datasize],eax\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Width\n\tpop\tedx\n\tmov\t[swidth],eax\n\tcmp\teax,[(MouseType esi).MaxWidth]\n\tjg\t??end\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Original_Height\n\tpop\tedx\n\tmov\t[sheight],eax\n\tcmp\teax,[(MouseType esi).MaxHeight]\n\tjg\t??end\n\n\n\tmov\tebx,[sheight]\n\tmov\teax,[swidth]\n\timul\tebx,eax\n\n??copy_mouse:\n\tmov\tedi,[(MouseType esi).MouseCursor]\t\t; set edi to point to mouse buffer\n\tmov\tesi,[cursor]\t\t\t; set esi to point to mouse shape\n\tmov\tax,[esi]\t\t\t; get the shape type byte\n\tmov\t[stype],ax\t\t\t; save off the shape type\n\ttest\tax,MAKESHAPE_NOCOMP\t\t; is it marked as no compression?\n\tje\t??comp_shape\t\t\t; if not go to the comped shape code\n\n??copy_type:\n\n\ttest\t[stype],MAKESHAPE_COMPACT\t; if the shape a 16 color shape?\n\tjne\t??16_color_copy\t\t\t; if it is then go handle it\n\n??normal_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed NORMAL shapes just get run-length uncompressed\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t\t; find size of shape in pixels\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes \n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??norm_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??norm_trans\t\t\t; if its a zero its transparent\n\tmov\t[edi],al\t\t\t; write out the pixel to dest\n\tinc\tedi\t\t\t\t; move to next dest position\n\tdec\tedx\t\t\t\t; we have now written another pix\n\tjnz\t??norm_unrle\t\t\t; if more to write then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are all done\n\n??norm_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\n\tjnz\t??norm_unrle\t\t\t; if more to do then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are done\n\n??16_color_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed 16 color shapes just get remaped and UN-RLE'd\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\tebx,esi\t\t\t\t; save of position of remap\n\tadd\tesi,16\t\t\t\t; move past remap table\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t; load up the height\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes \n\txor\teax,eax\t\t\t\t; clear high of lookup variable\n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??16_color_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??16_color_trans\t\t; if its a zero its transparent\n\tmov\tal,[ebx+eax]\t\t\t; remap the pixel from 16 color table\n\tmov\t[edi],al\t\t\t; store it out to the dest address\n\tinc\tedi\t\t\t\t; move to next dest address\n\tdec\tedx\t\t\t\t; we have now written a pixel\n\tjnz\t??16_color_unrle\n\tjmp\t??done_copy\n??16_color_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\t\t\t\t; subtract off count ahead of time\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\t\t\t\t; or edx to test for zero\n\tjnz\t??16_color_unrle\t\t\n\tjmp\t??done_copy\n\n\t;-------------------------------------------------------------------\n\t; Deal with the compressed shape by copying it into the shape\n\t;   staging buffer.\n\t;-------------------------------------------------------------------\n??comp_shape:\n\tmov\tedi,[ShapeBuffer]\t; get a pointer to ShapeBuffer\n\tmov\tax,[esi]\t\t; load in the shape type\n\tadd\tesi,2\t\t\t; increment the shape pointer\n\tor\tax,MAKESHAPE_NOCOMP\t; make the shape as uncompressed\n\tmov\t[stype],ax\t\t; save off the shape type\n\tmov\t[edi],ax\t\t; write out uncompressed shape\n\tadd\tedi,2\n\n\t;-------------------------------------------------------------------\n\t; Process the shape header information and copy it over to the new\n\t;   location.\n\t;-------------------------------------------------------------------\n\tmov\tecx,4 \t\t\t; transfer height, width, org and\n\ttest\teax,MAKESHAPE_COMPACT\t; is it a 16 color shape?\n\tje\t??copy_head\t\t; no - don't worry about it\n\tadd\tecx,8\t\t\t; otherwise adjust ecx for header\n??copy_head:\n\trep\tmovsw\t\t\t; copy the necessary bytes\n\t\n\tmov \teax,[datasize]\t\t; get uncompressed length\n\tpush\teax\t\t\t; push as third param\n\tpush\tedi\t\t\t; push the destination offset\n\tpush\tesi\t\t\t; push the source offset\n\tcall\tLCW_Uncompress\t\t; do the uncompress\n\tpop\teax\n\tpop\teax\n\tpop\teax\n\tmov\tesi,[this]\n\tmov\tedi,[(MouseType esi).MouseCursor]\t\t; set edi to point to mouse buffer\n\tmov\tesi,[ShapeBuffer]\n\tjmp\t??copy_type\n\n??done_copy:\n\tmov\tesi,[this]\t; get offset of real mode data start\n\n\tmov\teax,[xhotspot]\t\t; get the mouse cursors x hotspot\n\tmov\t[(MouseType esi).MouseXHot],eax\n\tmov\teax,[yhotspot]\t\t; get the mouse cursors y hotspot\n\tmov\t[(MouseType esi).MouseYHot],eax\n\n\tmov\tebx,[sheight]\t\t; get shape height\n\tmov\t[(MouseType esi).CursorHeight],ebx\n\tmov\tebx,[swidth]\n\tmov\t[(MouseType esi).CursorWidth],ebx\n\n\t;-------------------------------------------------------------------\n\t; Final cleanup and exit.\n\t;-------------------------------------------------------------------\n??end:\n\tpush\t[cursor]\n\tpush\t[(MouseType esi).PrevCursor]\n\tpop\teax\n\tpop\t[(MouseType esi).PrevCursor]\n\tret\t\t\t\t; and return back to the world\n\n\tENDP\tASM_Set_Mouse_Cursor\n\nEND\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLDTEST/KEYBOARD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*********************************************************************************************** \n *                                                                                             * \n *                 Project Name : Westwood Keyboard Library                                    * \n *                                                                                             * \n *                    File Name : KEYBOARD.CPP                                                 * \n *                                                                                             * \n *                   Programmer : Philip W. Gorrow                                             * \n *                                                                                             * \n *                   Start Date : 10/16/95                                                     * \n *                                                                                             * \n *                  Last Update : October 17, 1995 [PWG]                                       * \n *                                                                                             * \n *---------------------------------------------------------------------------------------------* \n * Functions:                                                                                  * \n *   WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                         * \n *   WWKeyboardClass::Get -- Logic to get a metakey from the buffer                            * \n *   WWKeyboardClass::Check -- Checks to see if a key is in the buffer                         * \n *   WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer    * \n *   WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer               * \n *   WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels           * \n *   WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels           * \n *   WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars       * \n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"keyboard.h\"\n\n/*********************************************************************************************** \n * WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class                * \n *                                                                                             * \n * INPUT:\t\tnone\t\t\t\t\t\t\t                                                        *\n *                                                                                             * \n * OUTPUT:     none\t\t\t\t\t\t\t                                                        *\n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/16/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nWWKeyboardClass::WWKeyboardClass(void)\n{\n\t//\n\t// Initialize the keyboard remap table for our system (note it would be bad if someone\n\t// switched keyboard modes after this happened.\n\t//\n\tmemset(VKRemap, 0, 2048);\n\tmemset(AsciiRemap, 0, 256);\n\tfor (short lp = 1; lp < 255; lp ++) {\n\t\tint vk_key = VkKeyScan(lp);\n\t\tif (vk_key > 0 && vk_key < 2048) {\n\t\t\tAsciiRemap[vk_key] = lp;\n\t\t\tVKRemap[vk_key] \t = vk_key & 0xFF;\n\t\t}\n\t}\n\n\t//\n\t// Build a remap table of the different keys which are affected by the caps lock and\n\t// the num lock.\n\t//\n\tmemset(ToggleKeys, 0, 256);\n\tfor (lp = 0; lp < 255; lp++ ) {\n\t\tif (isalpha(lp) && isupper(lp)) {\n\t\t\tToggleKeys[lp] = 1;\n\t\t}\n\t\tif (lp >= VK_NUMPAD0 && lp <= VK_DIVIDE) {\n\t\t\tToggleKeys[lp] = 2;\n\t\t}\n\t}\n\n\t//\n\t// Our buffer should start devoid of keys.\n\t//\n\tmemset(Buffer, 0, 256);\n\tHead\t\t= 0;\n\tTail\t\t= 0;\n\n\t//\n\t// There should be no starting queued mouse events for us to have to worry\n\t// about.\n\t//\n\tMouseQX\t= 0;\n\tMouseQY\t= 0;\n}\n\n/*********************************************************************************************** \n * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer                 * \n *                                                                                             * \n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             * \n * OUTPUT:     int\t\t- the key value that was pulled from buffer (includes bits)\t\t\t\t  *                                                                                * \n *                                                                                             * \n * WARNINGS:   If the key was a mouse event MouseQX and MouseQY will be updated                *\n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/17/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nint WWKeyboardClass::Buff_Get(void)\n{\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t\t\t// wait for key in buffer\n\tint \ttemp\t\t= Buffer[Head];\t\t\t\t\t\t// get key out of the buffer\n\tint   newhead\t= Head;\t\t\t\t\t\t\t\t\t// save off head for manipulation\n\tif (Is_Mouse_Key(temp)) {\t\t\t\t\t\t\t\t// if key is a mouse then\n\t\tMouseQX\t= Buffer[Head+1];\t\t\t\t\t\t\t//\t\tget the x and y pos\n\t\tMouseQY\t= Buffer[Head+2];\t\t\t\t\t\t\t//\t\tfrom the buffer\n\t\tnewhead += 3;\t\t  \t\t\t\t\t\t\t\t\t//\t\tadjust head forward\n\t} else {\n\t\tnewhead += 1;\t\t  \t\t\t\t\t\t\t\t\t//\t\tadjust head forward\n\t}\n\tnewhead\t&= 255;\n\tHead\t\t = newhead;\n\treturn(temp);\n}\n\nBOOL WWKeyboardClass::Is_Mouse_Key(int key)\n{\n\tkey &= 0xFF;\n\treturn (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON);\n}\n\n\n/*********************************************************************************************** \n * WWKeyboardClass::Check -- Checks to see if a key is in the buffer                           * \n *                                                                                             * \n * INPUT:                                                                                      * \n *                                                                                             * \n * OUTPUT:                                                                                     * \n *                                                                                             * \n * WARNINGS:                                                                                   * \n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/16/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nBOOL WWKeyboardClass::Check(void)\n{\n\tunsigned short temp;\t\t\t\t\t\t\t\t\t\t\t// store temp holding spot for key\n\tif (Head == Tail) return(FALSE);\t\t\t\t\t\t\t// if no keys in buff then get out\n\ttemp = Buffer[Head];\t\t\t\t\t\t\t\t\t\t\t// get key out of the buffer\n\treturn(temp);\t\t\t\t\t\t\t\t\t\t\t\t\t// send it back to main program\n}\t\n\n/*********************************************************************************************** \n * WWKeyboardClass::Get -- Logic to get a metakey from the buffer                              * \n *                                                                                             * \n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             * \n * OUTPUT:     int\t\t- the meta key taken from the buffer.\t\t\t\t\t\t\t\t\t\t\t  * \n *                                                                                             * \n * WARNINGS:\tThis routine will not return until a keypress is received\t\t\t\t\t\t\t  *\n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/16/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nint WWKeyboardClass::Get(void)\n{\n\tint temp,bits;\t\t\t\t\t\t\t\t\t\t// store temp holding spot for key\n\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t// wait for key in buffer\n\ttemp = Buff_Get();\t\t\t\t\t\t\t\t// get key from the buffer\n\n\tbits = temp & 0xFF00;\t\t\t\t\t\t\t// save of keyboard bits\n\t\n\tif (!(bits & WWKEY_VK_BIT)) {\t\t\t\t\t// if its not a virtual key\n\t\ttemp = AsciiRemap[temp&0x1FF] | bits;\t//   convert to ascii equivalent\n\t}\n\treturn(temp);\t\t\t\t\t\t\t// return the key that we pulled out\n}\t\n\n/*********************************************************************************************** \n * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                           * \n *                                                                                             * \n * INPUT:\t\tint\t \t- the key to insert into the buffer          \t\t\t\t\t\t\t\t  *\n *                                                                                             * \n * OUTPUT:     bool\t\t- true if key is sucessfuly inserted.\t\t\t\t\t\t\t              *\n *                                                                                             * \n * WARNINGS:   none\t\t\t\t\t\t\t                                                        *\n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/16/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nBOOL WWKeyboardClass::Put(int key)\n{\n\tint\ttemp\t\t= (Tail + 1) & 255;\n\tif (temp != Head) \n\t{\n\t\tBuffer[Tail]\t= key;\n\n\t\t//\n\t\t// Critical Line\n\t\t//\n\t\tTail\t\t\t\t= temp;\n\t\treturn(TRUE);\n\t}\n\treturn(FALSE);\n}\n/*********************************************************************************************** \n * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer      * \n *                                                                                             * \n * INPUT:                                                                                      * \n *                                                                                             * \n * OUTPUT:                                                                                     * \n *                                                                                             * \n * WARNINGS:                                                                                   * \n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/16/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nWWKeyboardClass::Put_Key_Message(UINT vk_key, BOOL release, BOOL dbl)\n{\n\tint bits = 0;\n\t//\n\t// Get the status of all of the different keyboard modifiers.  Note, only pay attention\n\t// to numlock and caps lock if we are dealing with a key that is affected by them.\n\t//\n\tint\tshift\t\t= (GetKeyState(VK_SHIFT) & 0xFF00) \t\t!= 0;\n\tint\tctrl \t\t= (GetKeyState(VK_CONTROL) & 0xFF00) \t!= 0;\n\tint\talt \t\t= (GetKeyState(VK_MENU) & 0xFF00) \t\t!= 0;\n\tint\tcaps\t\t= ((GetKeyState(VK_CAPITAL) & 0x00FF) \t!= 0) && (ToggleKeys[vk_key] == 1);\n\tint\tnums\t\t= ((GetKeyState(VK_NUMLOCK) & 0x00FF) \t!= 0) && (ToggleKeys[vk_key] == 2);\n\n\t//\n\t// Set the proper bits for whatever the key we got is.\n\t//\n\tif (shift || caps || nums) {\n\t\tbits |= WWKEY_SHIFT_BIT;\n\t}\n\tif (ctrl) {\n\t\tbits |= WWKEY_CTRL_BIT;\n\t}\n\tif (alt) {\n\t\tbits |= WWKEY_ALT_BIT;\n\t}\n\tif (!AsciiRemap[vk_key|bits]) {\n\t\tbits |= WWKEY_VK_BIT;\n\t}\n\tif (release) {\n\t\tbits |= WWKEY_RLS_BIT;\n\t}\n\tif (dbl) {\n\t\tbits |= WWKEY_DBL_BIT;\n\t}\n\t//\n\t// Finally use the put command to enter the key into the keyboard\n\t// system.\n\t//\n\treturn(Put(vk_key|bits));\n}\t\n\nVOID WWKeyboardClass::Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl)\n{\n\tshift = (key & WWKEY_SHIFT_BIT)\t!= 0;\n\tctrl\t= (key & WWKEY_CTRL_BIT)\t!= 0;\n\talt\t= (key & WWKEY_ALT_BIT)\t\t!= 0;\n\trls\t= (key & WWKEY_RLS_BIT)\t\t!= 0;\n\tdbl\t= (key & WWKEY_DBL_BIT)\t\t!= 0;\n\tkey\t= (key & 0xFF);\n\n}\t\n\n#pragma argsused\nvoid WWKeyboardClass::Message_Handler(HWND hwnd, UINT message, UINT wParam, LONG lParam)\n{\n\tswitch (message) {\n\t\tcase WM_SYSKEYDOWN:\n\t\tcase WM_KEYDOWN:\n\t\t\tPut_Key_Message(wParam);\n\t\t\tbreak;\n\n\t\tcase WM_SYSKEYUP:\n\t\tcase WM_KEYUP:\n\t\t\tPut_Key_Message(wParam, TRUE);\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_LBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONUP:\n\t\t\tPut_Key_Message(VK_LBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_LBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_MBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONUP:\n\t\t\tPut_Key_Message(VK_MBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_MBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_RBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONUP:\n\t\t\tPut_Key_Message(VK_RBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_RBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\t}\n}\t\n\n/*********************************************************************************************** \n * WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels             * \n *                                                                                             * \n * INPUT:\t\tnone                                                                            * \n *                                                                                             * \n * OUTPUT:     int\t\t- returns the mouses current x position in pixels                      * \n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/17/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nint WWKeyboardClass::Get_Mouse_X(void)\n{\n\tPOINT \tpt;\n\tGetCursorPos(&pt);\n\treturn(pt.x);\n}\t\nvoid WWKeyboardClass::Clear(void)\n{\n\tHead = Tail;\n}\n\n\n/*********************************************************************************************** \n * WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels             * \n *                                                                                             * \n * INPUT:\t\tnone                                                                            * \n *                                                                                             * \n * OUTPUT:     int\t\t- returns the mouses current y position in pixels                      * \n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/17/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nint WWKeyboardClass::Get_Mouse_Y(void)\n{\n\tPOINT \tpt;\n\tGetCursorPos(&pt);\n\treturn(pt.y);\n}\t\n\n/*********************************************************************************************** \n * WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars         * \n *                                                                                             * \n * INPUT:\t\tint &x\t\t- variable to return the mouses x position in pixels                *\n *\t\t\t\t\tint &y\t\t- variable to return the mouses y position in pixels\t\t\t\t\t  *\n *                                                                                             * \n * OUTPUT:     none - output is via reference variables                                        *\n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/17/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nvoid WWKeyboardClass::Get_Mouse_XY(int &x, int &y)\n{\n\tPOINT \tpt;\n\n\tGetCursorPos(&pt);\n\tx = pt.x;\n\ty = pt.y;\n}\t"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLDTEST/KEYBOARD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*********************************************************************************************** \n *                                                                                             * \n *                 Project Name : Westwood Keyboard Library                                    * \n *                                                                                             * \n *                    File Name : KEYBOARD.H                                                   * \n *                                                                                             * \n *                   Programmer : Philip W. Gorrow                                             * \n *                                                                                             * \n *                   Start Date : 10/16/95                                                     * \n *                                                                                             * \n *                  Last Update : October 16, 1995 [PWG]                                       * \n *                                                                                             * \n *---------------------------------------------------------------------------------------------* \n * Functions:                                                                                  * \n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include <WWSTD.H>\n\ntypedef enum {\n\tWWKEY_SHIFT_BIT\t= 0x100,\n\tWWKEY_CTRL_BIT\t\t= 0x200,\n\tWWKEY_ALT_BIT\t\t= 0x400,\n\tWWKEY_VK_BIT\t\t= 0x800,\t\n\tWWKEY_RLS_BIT\t\t= 0x1000,\t\n\tWWKEY_DBL_BIT\t\t= 0x2000,\t\n\tWWKEY_BTN_BIT\t\t= 0x4000,\t\n} WWKey_Type;\n\n#define\tVK_NONE\t\t\t\t  0x00\n#define\tVK_LBUTTON          0x01\n#define\tVK_RBUTTON          0x02\n#define\tVK_CANCEL           0x03\n#define\tVK_MBUTTON          0x04\n#define\tVK_NONE_05\t\t\t  0x05\n#define\tVK_NONE_06\t\t\t  0x06\n#define\tVK_NONE_07\t\t\t  0x07\n#define\tVK_BACK             0x08\n#define\tVK_TAB              0x09\n#define\tVK_NONE_0A\t\t\t  0x0A\n#define\tVK_NONE_0B\t\t\t  0x0B\n#define\tVK_CLEAR            0x0C\n#define\tVK_RETURN           0x0D\n#define\tVK_NONE_0E\t\t\t  0x0E\n#define\tVK_NONE_0F\t\t\t  0x0F\n#define\tVK_SHIFT            0x10\n#define\tVK_CONTROL          0x11\n#define\tVK_MENU             0x12\n#define\tVK_PAUSE            0x13\n#define\tVK_CAPITAL          0x14\n#define\tVK_NONE_15\t\t\t  0x15\n#define\tVK_NONE_16\t\t\t  0x16\n#define\tVK_NONE_17\t\t\t  0x17\n#define\tVK_NONE_18\t\t\t  0x18\n#define\tVK_NONE_19\t\t\t  0x19\n#define\tVK_NONE_1A\t\t\t  0x1A\n#define\tVK_ESCAPE           0x1B\n#define\tVK_NONE_1C\t\t\t  0x1C\n#define\tVK_NONE_1D\t\t\t  0x1D\n#define\tVK_NONE_1E\t\t\t  0x1E\n#define\tVK_NONE_1F\t\t\t  0x1F\n#define\tVK_SPACE            0x20\n#define\tVK_PRIOR            0x21\n#define\tVK_NEXT             0x22\n#define\tVK_END              0x23\n#define\tVK_HOME             0x24\n#define\tVK_LEFT             0x25\n#define\tVK_UP               0x26\n#define\tVK_RIGHT            0x27\n#define\tVK_DOWN             0x28\n#define\tVK_SELECT           0x29\n#define\tVK_PRINT            0x2A\n#define\tVK_EXECUTE          0x2B\n#define\tVK_SNAPSHOT         0x2C\n#define\tVK_INSERT           0x2D\n#define\tVK_DELETE           0x2E\n#define\tVK_HELP             0x2F\n#define\tVK_0\t\t\t\t\t  0x30\n#define\tVK_1\t\t\t\t\t  0x31\n#define\tVK_2\t\t\t\t\t  0x32\n#define\tVK_3\t\t\t\t\t  0x33\n#define\tVK_4\t\t\t\t\t  0x34\n#define\tVK_5\t\t\t\t\t  0x35\n#define\tVK_6\t\t\t\t\t  0x36\n#define\tVK_7\t\t\t\t\t  0x37\n#define\tVK_8\t\t\t\t\t  0x38\n#define\tVK_9\t\t\t\t\t  0x39\n#define\tVK_NONE_3B\t\t\t  0x3B\n#define\tVK_NONE_3C\t\t\t  0x3C\n#define\tVK_NONE_3D\t\t\t  0x3D\n#define\tVK_NONE_3E\t\t\t  0x3E\n#define\tVK_NONE_3F\t\t\t  0x3F\n#define\tVK_NONE_40\t\t\t  0x40\n#define\tVK_A\t\t\t\t\t  0x41\n#define\tVK_B\t\t\t\t\t  0x42\n#define\tVK_C\t\t\t\t\t  0x43\n#define\tVK_D\t\t\t\t\t  0x44\n#define\tVK_E\t\t\t\t\t  0x45\n#define\tVK_F\t\t\t\t\t  0x46\n#define\tVK_G\t\t\t\t\t  0x47\n#define\tVK_H\t\t\t\t\t  0x48\n#define\tVK_I\t\t\t\t\t  0x49\n#define\tVK_J\t\t\t\t\t  0x4A\n#define\tVK_K\t\t\t\t\t  0x4B\n#define\tVK_L\t\t\t\t\t  0x4C\n#define\tVK_M\t\t\t\t\t  0x4D\n#define\tVK_N\t\t\t\t\t  0x4E\n#define\tVK_O\t\t\t\t\t  0x4F\n#define\tVK_P\t\t\t\t\t  0x50\n#define\tVK_Q\t\t\t\t\t  0x51\n#define\tVK_R\t\t\t\t\t  0x52\n#define\tVK_S\t\t\t\t\t  0x53\n#define\tVK_T\t\t\t\t\t  0x54\n#define\tVK_U\t\t\t\t\t  0x55\n#define\tVK_V\t\t\t\t\t  0x56\n#define\tVK_W\t\t\t\t\t  0x57\n#define\tVK_X\t\t\t\t\t  0x58\n#define\tVK_Y\t\t\t\t\t  0x59\n#define\tVK_Z\t\t\t\t\t  0x5A\n#define\tVK_NONE_5B\t\t\t  0x5B\n#define\tVK_NONE_5C\t\t\t  0x5C\n#define\tVK_NONE_5D\t\t\t  0x5D\n#define\tVK_NONE_5E\t\t\t  0x5E\n#define\tVK_NONE_5F\t\t\t  0x5F\n#define\tVK_NUMPAD0          0x60\n#define\tVK_NUMPAD1          0x61\n#define\tVK_NUMPAD2          0x62\n#define\tVK_NUMPAD3          0x63\n#define\tVK_NUMPAD4          0x64\n#define\tVK_NUMPAD5          0x65\n#define\tVK_NUMPAD6          0x66\n#define\tVK_NUMPAD7          0x67\n#define\tVK_NUMPAD8          0x68\n#define\tVK_NUMPAD9          0x69\n#define\tVK_MULTIPLY         0x6A\n#define\tVK_ADD              0x6B\n#define\tVK_SEPARATOR        0x6C\n#define\tVK_SUBTRACT         0x6D\n#define\tVK_DECIMAL          0x6E\n#define\tVK_DIVIDE           0x6F\n#define\tVK_F1               0x70\n#define\tVK_F2               0x71\n#define\tVK_F3               0x72\n#define\tVK_F4               0x73\n#define\tVK_F5               0x74\n#define\tVK_F6               0x75\n#define\tVK_F7               0x76\n#define\tVK_F8               0x77\n#define\tVK_F9               0x78\n#define\tVK_F10              0x79\n#define\tVK_F11              0x7A\n#define\tVK_F12              0x7B\n#define\tVK_F13              0x7C\n#define\tVK_F14              0x7D\n#define\tVK_F15              0x7E\n#define\tVK_F16              0x7F\n#define\tVK_F17              0x80\n#define\tVK_F18              0x81\n#define\tVK_F19              0x82\n#define\tVK_F20              0x83\n#define\tVK_F21              0x84\n#define\tVK_F22              0x85\n#define\tVK_F23              0x86\n#define\tVK_F24              0x87\n#define\tVK_NONE_88          0x88\n#define\tVK_NONE_89          0x89\n#define\tVK_NONE_8A          0x8A\n#define\tVK_NONE_8B          0x8B\n#define\tVK_NONE_8C          0x8C\n#define\tVK_NONE_8D          0x8D\n#define\tVK_NONE_8E          0x8E\n#define\tVK_NONE_8F          0x8F\n#define\tVK_NUMLOCK          0x90\n#define\tVK_SCROLL           0x91\n#define\tVK_NONE_92\t\t\t  0x92\n#define\tVK_NONE_93\t\t\t  0x93\n#define\tVK_NONE_94\t\t\t  0x94\n#define\tVK_NONE_95\t\t\t  0x95\n#define\tVK_NONE_96\t\t\t  0x96\n#define\tVK_NONE_97\t\t\t  0x97\n#define\tVK_NONE_98\t\t\t  0x98\n#define\tVK_NONE_99\t\t\t  0x99\n#define\tVK_NONE_9A\t\t\t  0x9A\n#define\tVK_NONE_9B\t\t\t  0x9B\n#define\tVK_NONE_9C\t\t\t  0x9C\n#define\tVK_NONE_9D\t\t\t  0x9D\n#define\tVK_NONE_9E\t\t\t  0x9E\n#define\tVK_NONE_9F\t\t\t  0x9F\n#define\tVK_NONE_A0\t\t\t  0xA0\n#define\tVK_NONE_A1\t\t\t  0xA1\n#define\tVK_NONE_A2\t\t\t  0xA2\n#define\tVK_NONE_A3\t\t\t  0xA3\n#define\tVK_NONE_A4\t\t\t  0xA4\n#define\tVK_NONE_A5\t\t\t  0xA5\n#define\tVK_NONE_A6\t\t\t  0xA6\n#define\tVK_NONE_A7\t\t\t  0xA7\n#define\tVK_NONE_A8\t\t\t  0xA8\n#define\tVK_NONE_A9\t\t\t  0xA9\n#define\tVK_NONE_AA\t\t\t  0xAA\n#define\tVK_NONE_AB\t\t\t  0xAB\n#define\tVK_NONE_AC\t\t\t  0xAC\n#define\tVK_NONE_AD\t\t\t  0xAD\n#define\tVK_NONE_AE\t\t\t  0xAE\n#define\tVK_NONE_AF\t\t\t  0xAF\n#define\tVK_NONE_B0\t\t\t  0xB0\n#define\tVK_NONE_B1\t\t\t  0xB1\n#define\tVK_NONE_B2\t\t\t  0xB2\n#define\tVK_NONE_B3\t\t\t  0xB3\n#define\tVK_NONE_B4\t\t\t  0xB4\n#define\tVK_NONE_B5\t\t\t  0xB5\n#define\tVK_NONE_B6\t\t\t  0xB6\n#define\tVK_NONE_B7\t\t\t  0xB7\n#define\tVK_NONE_B8\t\t\t  0xB8\n#define\tVK_NONE_B9\t\t\t  0xB9\n#define\tVK_NONE_BA\t\t\t  0xBA\n#define\tVK_NONE_BB\t\t\t  0xBB\n#define\tVK_NONE_BC\t\t\t  0xBC\n#define\tVK_NONE_BD\t\t\t  0xBD\n#define\tVK_NONE_BE\t\t\t  0xBE\n#define\tVK_NONE_BF\t\t\t  0xBF\n#define\tVK_NONE_C0\t\t\t  0xC0\n#define\tVK_NONE_C1\t\t\t  0xC1\n#define\tVK_NONE_C2\t\t\t  0xC2\n#define\tVK_NONE_C3\t\t\t  0xC3\n#define\tVK_NONE_C4\t\t\t  0xC4\n#define\tVK_NONE_C5\t\t\t  0xC5\n#define\tVK_NONE_C6\t\t\t  0xC6\n#define\tVK_NONE_C7\t\t\t  0xC7\n#define\tVK_NONE_C8\t\t\t  0xC8\n#define\tVK_NONE_C9\t\t\t  0xC9\n#define\tVK_NONE_CA\t\t\t  0xCA\n#define\tVK_NONE_CB\t\t\t  0xCB\n#define\tVK_NONE_CC\t\t\t  0xCC\n#define\tVK_NONE_CD\t\t\t  0xCD\n#define\tVK_NONE_CE\t\t\t  0xCE\n#define\tVK_NONE_CF\t\t\t  0xCF\n#define\tVK_NONE_D0\t\t\t  0xD0\n#define\tVK_NONE_D1\t\t\t  0xD1\n#define\tVK_NONE_D2\t\t\t  0xD2\n#define\tVK_NONE_D3\t\t\t  0xD3\n#define\tVK_NONE_D4\t\t\t  0xD4\n#define\tVK_NONE_D5\t\t\t  0xD5\n#define\tVK_NONE_D6\t\t\t  0xD6\n#define\tVK_NONE_D7\t\t\t  0xD7\n#define\tVK_NONE_D8\t\t\t  0xD8\n#define\tVK_NONE_D9\t\t\t  0xD9\n#define\tVK_NONE_DA\t\t\t  0xDA\n#define\tVK_NONE_DB\t\t\t  0xDB\n#define\tVK_NONE_DC\t\t\t  0xDC\n#define\tVK_NONE_DD\t\t\t  0xDD\n#define\tVK_NONE_DE\t\t\t  0xDE\n#define\tVK_NONE_DF\t\t\t  0xDF\n#define\tVK_NONE_E0\t\t\t  0xE0\n#define\tVK_NONE_E1\t\t\t  0xE1\n#define\tVK_NONE_E2\t\t\t  0xE2\n#define\tVK_NONE_E3\t\t\t  0xE3\n#define\tVK_NONE_E4\t\t\t  0xE4\n#define\tVK_NONE_E5\t\t\t  0xE5\n#define\tVK_NONE_E6\t\t\t  0xE6\n#define\tVK_NONE_E7\t\t\t  0xE7\n#define\tVK_NONE_E8\t\t\t  0xE8\n#define\tVK_NONE_E9\t\t\t  0xE9\n#define\tVK_NONE_EA\t\t\t  0xEA\n#define\tVK_NONE_EB\t\t\t  0xEB\n#define\tVK_NONE_EC\t\t\t  0xEC\n#define\tVK_NONE_ED\t\t\t  0xED\n#define\tVK_NONE_EE\t\t\t  0xEE\n#define\tVK_NONE_EF\t\t\t  0xEF\n#define\tVK_NONE_F0\t\t\t  0xF0\n#define\tVK_NONE_F1\t\t\t  0xF1\n#define\tVK_NONE_F2\t\t\t  0xF2\n#define\tVK_NONE_F3\t\t\t  0xF3\n#define\tVK_NONE_F4\t\t\t  0xF4\n#define\tVK_NONE_F5\t\t\t  0xF5\n#define\tVK_NONE_F6\t\t\t  0xF6\n#define\tVK_NONE_F7\t\t\t  0xF7\n#define\tVK_NONE_F8\t\t\t  0xF8\n#define\tVK_NONE_F9\t\t\t  0xF9\n#define\tVK_NONE_FA\t\t\t  0xFA\n#define\tVK_NONE_FB\t\t\t  0xFB\n#define\tVK_NONE_FC\t\t\t  0xFC\n#define\tVK_NONE_FD\t\t\t  0xFD\n#define\tVK_NONE_FE\t\t\t  0xFE\n#define\tVK_NONE_FF\t\t\t  0xFF\n\n#define\tVK_UPLEFT\t\t\t  VK_HOME\n#define\tVK_UPRIGHT\t\t\t  VK_PRIOR\t\t\t\n#define\tVK_DOWNLEFT\t\t\t  VK_END\n#define\tVK_DOWNRIGHT\t\t  VK_NEXT\n#define\tVK_ALT\t\t\t\t  VK_MENU\n\ntypedef enum {\n\tKA_CTRL_AT = 0,\n\tKA_CTRL_A,\n\tKA_MORE = KA_CTRL_A,\n\tKA_CTRL_B,\n\tKA_SETBKGDCOL = KA_CTRL_B,\n\tKA_CTRL_C,\n\tKA_CTRL_D,\n\tKA_CTRL_E,\n\tKA_CTRL_F,\n\tKA_SETFORECOL = KA_CTRL_F,\n\tKA_CTRL_G,\n\tKA_CTRL_H,\n\tKA_BACKSPACE = KA_CTRL_H,\n\tKA_CTRL_I,\n\tKA_TAB = KA_CTRL_I,\n\tKA_CTRL_J,\n\tKA_CTRL_K,\n\tKA_CTRL_L,\n\tKA_FORMFEED = KA_CTRL_L,\n\tKA_CTRL_M,\n\tKA_RETURN = KA_CTRL_M,\n\tKA_CTRL_N,\n\n\tKA_CTRL_O,\n\tKA_CTRL_P,\n\tKA_CTRL_Q,\n\tKA_CTRL_R,\n\tKA_CTRL_S,\n\tKA_SPCTAB = KA_CTRL_S,\n\tKA_CTRL_T,\n\tKA_CTRL_U,\n\tKA_CTRL_V,\n\tKA_CTRL_W,\n\tKA_CTRL_X,\n\tKA_SETX = KA_CTRL_X,\n\tKA_CTRL_Y,\n\tKA_SETY = KA_CTRL_Y,\n\tKA_CTRL_Z,\n\tKA_CTRL_LBRACKET,\n\tKA_ESC = KA_CTRL_LBRACKET,\n\tKA_EXTEND = KA_ESC,\n\tKA_CTRL_BACKSLASH,\n\tKA_CTRL_RBRACKET,\n\tKA_LITERAL = KA_CTRL_RBRACKET,\n\tKA_CTRL_CARROT,\n\tKA_CTRL_UNDERLINE,\n\n\tKA_SPACE,\t\t\t\t\t\t\t\t\t/*   */\n\tKA_EXCLAMATION,\t\t\t\t\t\t\t/* ! */\n\tKA_DQUOTE,\t\t\t\t\t\t\t\t\t/* \" */\n\tKA_POUND,\t\t\t\t\t\t\t\t\t/* # */\n\tKA_DOLLAR,\t\t\t\t\t\t\t\t\t/* $ */\n\tKA_PERCENT,\t\t\t\t\t\t\t\t\t/* % */\n\tKA_AMPER,\t\t\t\t\t\t\t\t\t/* & */\n\tKA_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKA_LPAREN,\t\t\t\t\t\t\t\t\t/* ( */\n\tKA_RPAREN,\t\t\t\t\t\t\t\t\t/* ) */\n\tKA_ASTERISK,\t\t\t\t\t\t\t\t/* * */\n\tKA_PLUS,\t\t\t\t\t\t\t\t\t\t/* + */\n\tKA_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKA_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKA_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKA_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKA_0, KA_1, KA_2, KA_3, KA_4, KA_5, KA_6, KA_7, KA_8, KA_9,\n\tKA_COLON,\t\t\t\t\t\t\t\t\t/* : */\n\tKA_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKA_LESS_THAN,\t\t\t\t\t\t\t\t/* < */\n\tKA_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\tKA_GREATER_THAN,\t\t\t\t\t\t\t/* > */\n\tKA_QUESTION,\t\t\t\t\t\t\t\t/* ? */\n\n\tKA_AT,\t\t\t\t\t\t\t\t\t\t/* @ */\n\tKA_A,\t\t\t\t\t\t\t\t\t\t\t/* A */\n\tKA_B,\t\t\t\t\t\t\t\t\t\t\t/* B */\n\tKA_C,\t\t\t\t\t\t\t\t\t\t\t/* C */\n\tKA_D,\t\t\t\t\t\t\t\t\t\t\t/* D */\n\tKA_E,\t\t\t\t\t\t\t\t\t\t\t/* E */\n\tKA_F,\t\t\t\t\t\t\t\t\t\t\t/* F */\n\tKA_G,\t\t\t\t\t\t\t\t\t\t\t/* G */\n\tKA_H,\t\t\t\t\t\t\t\t\t\t\t/* H */\n\tKA_I,\t\t\t\t\t\t\t\t\t\t\t/* I */\n\tKA_J,\t\t\t\t\t\t\t\t\t\t\t/* J */\n\tKA_K,\t\t\t\t\t\t\t\t\t\t\t/* K */\n\tKA_L,\t\t\t\t\t\t\t\t\t\t\t/* L */\n\tKA_M,\t\t\t\t\t\t\t\t\t\t\t/* M */\n\tKA_N,\t\t\t\t\t\t\t\t\t\t\t/* N */\n\tKA_O,\t\t\t\t\t\t\t\t\t\t\t/* O */\n\n\tKA_P,\t\t\t\t\t\t\t\t\t\t\t/* P */\n\tKA_Q,\t\t\t\t\t\t\t\t\t\t\t/* Q */\n\tKA_R,\t\t\t\t\t\t\t\t\t\t\t/* R */\n\tKA_S,\t\t\t\t\t\t\t\t\t\t\t/* S */\n\tKA_T,\t\t\t\t\t\t\t\t\t\t\t/* T */\n\tKA_U,\t\t\t\t\t\t\t\t\t\t\t/* U */\n\tKA_V,\t\t\t\t\t\t\t\t\t\t\t/* V */\n\tKA_W,\t\t\t\t\t\t\t\t\t\t\t/* W */\n\tKA_X,\t\t\t\t\t\t\t\t\t\t\t/* X */\n\tKA_Y,\t\t\t\t\t\t\t\t\t\t\t/* Y */\n\tKA_Z,\t\t\t\t\t\t\t\t\t\t\t/* Z */\n\tKA_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKA_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\tKA_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKA_CARROT,\t\t\t\t\t\t\t\t\t/* ^ */\n\tKA_UNDERLINE,\t\t\t\t\t\t\t\t/* _ */\n\n\tKA_GRAVE,\t\t\t\t\t\t\t\t\t/* ` */\n\tKA_a,\t\t\t\t\t\t\t\t\t\t\t/* a */\n\tKA_b,\t\t\t\t\t\t\t\t\t\t\t/* b */\n\tKA_c,\t\t\t\t\t\t\t\t\t\t\t/* c */\n\tKA_d,\t\t\t\t\t\t\t\t\t\t\t/* d */\n\tKA_e,\t\t\t\t\t\t\t\t\t\t\t/* e */\n\tKA_f,\t\t\t\t\t\t\t\t\t\t\t/* f */\n\tKA_g,\t\t\t\t\t\t\t\t\t\t\t/* g */\n\tKA_h,\t\t\t\t\t\t\t\t\t\t\t/* h */\n\tKA_i,\t\t\t\t\t\t\t\t\t\t\t/* i */\n\tKA_j,\t\t\t\t\t\t\t\t\t\t\t/* j */\n\tKA_k,\t\t\t\t\t\t\t\t\t\t\t/* k */\n\tKA_l,\t\t\t\t\t\t\t\t\t\t\t/* l */\n\tKA_m,\t\t\t\t\t\t\t\t\t\t\t/* m */\n\tKA_n,\t\t\t\t\t\t\t\t\t\t\t/* n */\n\tKA_o,\t\t\t\t\t\t\t\t\t\t\t/* o */\n\n\tKA_p,\t\t\t\t\t\t\t\t\t\t\t/* p */\n\tKA_q,\t\t\t\t\t\t\t\t\t\t\t/* q */\n\tKA_r,\t\t\t\t\t\t\t\t\t\t\t/* r */\n\tKA_s,\t\t\t\t\t\t\t\t\t\t\t/* s */\n\tKA_t,\t\t\t\t\t\t\t\t\t\t\t/* t */\n\tKA_u,\t\t\t\t\t\t\t\t\t\t\t/* u */\n\tKA_v,\t\t\t\t\t\t\t\t\t\t\t/* v */\n\tKA_w,\t\t\t\t\t\t\t\t\t\t\t/* w */\n\tKA_x,\t\t\t\t\t\t\t\t\t\t\t/* x */\n\tKA_y,\t\t\t\t\t\t\t\t\t\t\t/* y */\n\tKA_z,\t\t\t\t\t\t\t\t\t\t\t/* z */\n\tKA_LBRACE,\t\t\t\t\t\t\t\t\t/* { */\n\tKA_BAR,\t\t\t\t\t\t\t\t\t\t/* | */\n\tKA_RBRACE,\t\t\t\t\t\t\t\t\t/* ] */\n\tKA_TILDA,\t\t\t\t\t\t\t\t\t/* ~ */\n\tKA_DEL,\t\t\t\t\t\t\t\t\t\t/* not used */\n\n\tKA_ALT_F10 = 143,\n\tKA_ALT_F9,    KA_ALT_F8,   KA_ALT_F7,   KA_ALT_F6,   KA_ALT_F5,\n\tKA_ALT_F4,    KA_ALT_F3,   KA_ALT_F2,   KA_ALT_F1,\n\n\tKA_CTRL_F10,  KA_CTRL_F9,  KA_CTRL_F8,  KA_CTRL_F7,  KA_CTRL_F6,\n\tKA_CTRL_F5,   KA_CTRL_F4,  KA_CTRL_F3,  KA_CTRL_F2,  KA_CTRL_F1,\n\n\tKA_SHIFT_F10, KA_SHIFT_F9, KA_SHIFT_F8, KA_SHIFT_F7, KA_SHIFT_F6,\n\tKA_SHIFT_F5,  KA_SHIFT_F4, KA_SHIFT_F3, KA_SHIFT_F2, KA_SHIFT_F1,\n\n\tKA_DELETE,\t\t\t\t\t\t\t\t\t/* <DELETE> */\n\tKA_INSERT,\t\t\t\t\t\t\t\t\t/* <INSERT> */\n\tKA_PGDN,\t\t\t\t\t\t\t\t\t\t/* <PAGE DOWN> */\n\tKA_DOWNRIGHT = KA_PGDN,\n\tKA_DOWN,\t\t\t\t\t\t\t\t\t\t/* <DOWN ARROW> */\n\tKA_END,\t\t\t\t\t\t\t\t\t\t/* <END> */\n\tKA_DOWNLEFT = KA_END,\n\n\tKA_RESERVED1,\n\n\tKA_RIGHT,\t\t\t\t\t\t\t\t\t/* <RIGHT ARROW> */\n\tKA_KEYPAD5,\t\t\t\t\t\t\t\t\t/* NUMERIC KEY PAD <5> */\n\tKA_LEFT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ARROW> */\n\n\tKA_RESERVED2,\n\n\tKA_PGUP,\t\t\t\t\t\t\t\t\t\t/* <PAGE UP> */\n\tKA_UPRIGHT = KA_PGUP,\n\tKA_UP,\t\t\t\t\t\t\t\t\t\t/* <UP ARROW> */\n\tKA_HOME,\t\t\t\t\t\t\t\t\t\t/* <HOME> */\n\tKA_UPLEFT = KA_HOME,\n\t\n\tKA_RESERVED3,\n\tKA_RESERVED4,\n\n\tKA_F10, KA_F9, KA_F8, KA_F7, KA_F6, KA_F5, KA_F4, KA_F3, KA_F2, KA_F1,\n\n\tKA_LMOUSE,\n\tKA_RMOUSE,\n\tKA_JBUTTON1,\n\tKA_JBUTTON2,\n\tKA_J_UP,\n\tKA_J_RIGHT,\n\tKA_J_DOWN,\n\tKA_J_LEFT,\n\n\tKA_SHIFT_BIT = 0x0100,\n\tKA_CTRL_BIT  = 0x0200,\n\tKA_ALT_BIT   = 0x0400,\n\tKA_RLSE_BIT  = 0x0800,\n\tKA_LCOMM_BIT = 0x1000,\t\t\t\t\t/* Amiga Left Comm key\t*/\n\tKA_RCOMM_BIT = 0x2000\t\t\t\t\t/* Amiga Right Comm key\t*/\n} KA_Type;\n\n\n\nclass WWKeyboardClass \n{\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tWWKeyboardClass();\n//\t\t~WWKeyboardClass();\n\n\t\t/*===================================================================*/\n\t\t/* Define the functions which work with the Keyboard Class\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBOOL \tCheck(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for meta key\n\t\tint \tGet(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// gets a meta key from the keybuffer\n\t\tBOOL \tPut(int key);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// dumps a key into the keybuffer\n\t\tBOOL\tPut_Key_Message(\tUINT vk_key, BOOL release = FALSE, \t\t// handles keyboard related message\n\t\t\t\t\t\t\t\t\t\tBOOL dbl = FALSE);\t\t\t\t\t\t\t//   and mouse clicks and dbl clicks\n\t\tint \tCheck_Num(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for a keynum key\n\t\tint \tGet_Num(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// gets keynum key from key buff\n\t\tint \tCheck_ACII(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for an ascii key\n\t\tint \tGet_ASCII(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// gets an ascii key from keybuff\n\t\tint \tCheck_Bits(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for key w/ bits\n\t\tint \tGet_Bits(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// get key from keybuff w/ bits\n\t\tint \tTo_ASCII(int num);\t\t\t\t\t\t\t\t\t\t\t\t\t// converts keynum to ascii value\n\t\tint \tOption_On(int option);\t\t\t\t\t\t\t\t\t\t\t\t// turns specified option on\n\t\tint \tOption_Off(int option);\t\t\t\t\t\t\t\t\t\t\t\t// turns specified option off\n\t\tvoid \tClear(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// clears all keys from keybuffer\n\t\tint \tDown(int key);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// tests to see if a key is down\n\t\tvoid\tAI(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// messaging logic for key manager\n\n\t\t/*===================================================================*/\n\t\t/* Define the main hook for the message processing loop.\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tvoid Message_Handler(HWND hwnd, UINT message, UINT wParam, LONG lParam);\n\n\t\t/*===================================================================*/\n\t\t/* Define public routines which can be used on keys in general.\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl);\n\t\tBOOL Is_Mouse_Key(int key);\n\n\t\t/*===================================================================*/\n\t\t/* Routines to sneak through and get the mouses position.\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tint\tGet_Mouse_X(void);\n\t\tint\tGet_Mouse_Y(void);\n\t\tvoid\tGet_Mouse_XY(int &x, int &y);\n\n\t\t/*===================================================================*/\n\t\t/* Define the public access variables which are used with the\t\t\t*/\n\t\t/*   Keyboard Class.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tint\t\t\t\tMouseQX;\t\t\t\t  \n\t\tint\t\t\t\tMouseQY;\n\n\tprivate:\n\t\t/*===================================================================*/\n\t\t/* Define the private access functions which are used by keyboard\t\t*/\n\t\t/*===================================================================*/\n\t\tint  Buff_Get(void);\n\n\n\t\t/*===================================================================*/\n\t\t/* Define the private access variables which are used with the\t\t\t*/\n\t\t/*   Keyboard Class.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tunsigned char\tAsciiRemap[2048];\t// remap for shft/ctrl/alt key combos\n\t\tunsigned char\tVKRemap[256];\t\t// gives vk for any ascii char\n\t\tunsigned short Buffer[256];\t\t// buffer which holds actual keypresses\n\t\tunsigned char  ToggleKeys[256];\t// determines toggles which affect key\n\t\tlong\t\t\t\tHead;\t\t\t\t\t// the head position in keyboard buffer\n\t\tlong\t\t\t\tTail;\t\t\t\t\t// the tail position in keyboard buffer\n};\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLDTEST/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .EXE makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 20, 1995  \t                   \t\t*\n#*                                                                         *\n#*                  Last Update : \t\t\t                   \t\t\t\t\t*\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the executable program you're building \t   \t\t*\n#* PROJ_LIBS\t= Westwood libraries to link your EXE to \t           \t\t\t*\n#* OBJECTS\t= list of objects in your current working directory\t   \t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t= full pathname of your working directory\t\t   \t\t\t\t\t*\n#* .xxx:\t= full pathname where various file types live\t\t   \t\t\t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n#---------------------------------------------------------------------------\n# PROJ_NAME = library name\n# PROJ_DIR = directory containing source & objects\n#---------------------------------------------------------------------------\nPROJ_NAME   = test\nPROJ_DIR    = $(WIN32LIB)\\keyboard\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS =  \t\\\n\t\t\t\t$(PROJ_NAME).obj\n\n!if 0\nPROJ_LIBS =\t\\\n\t\t\t   drawbuff.lib\t\\\n\t\t\t   win32lib.lib\n!else\nPROJ_LIBS =\t\\\n\t\t\t   drawbuff.lib\t\\\n\t\t\t\tmem.lib\t\t\t\\\n\t\t\t\tmisc.lib\t\t\t\\\n\t\t\t\tiff.lib\t\t\t\\\n\t\t\t\trawfile.lib\t\t\\\n\t\t\t\ttile.lib\t\t\t\\\n\t\t\t\tfont.lib\n!endif\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n# If LIB & INCLUDE are already defined, they are used in addition to the\n# WWLIB32 lib & include; otherwise, they're constructed from\n# BCDIR\n#---------------------------------------------------------------------------\n\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj:\n\t$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n.lbm.cps:\n\t$(WIN32LIB)\\\\TOOLS\\WWCOMP $*.lbm $*.cps\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(PROJ_NAME).exe\n\n#---------------------------------------------------------------------------\n# Build the EXE\n#---------------------------------------------------------------------------\n$(PROJ_NAME).exe: $(OBJECTS) $(PROJ_LIBS)\n\t $(LINK_CMD) @&&|\n$(LINK_CFG) +\n$(COMPILER)\\\\LIB\\\\c0w32.obj+\n$(OBJECTS)\n$<,$*\n$(PROJ_LIBS) +\nimport32.lib +\ncw32i.lib\n$*.def\n|\n\n$(PROJ_LIBS):\n\techo updating base library $^@\n\tcd ..\n\tmake\n\tcd $(PROJ_DIR)\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLDTEST/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .EXE makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 20, 1995  \t                   \t\t*\n#*                                                                         *\n#*                  Last Update : \t\t\t                   \t\t\t\t\t*\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the executable program you're building \t   \t\t*\n#* PROJ_LIBS\t= Westwood libraries to link your EXE to \t           \t\t\t*\n#* OBJECTS\t= list of objects in your current working directory\t   \t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t= full pathname of your working directory\t\t   \t\t\t\t\t*\n#* .xxx:\t= full pathname where various file types live\t\t   \t\t\t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n#---------------------------------------------------------------------------\n# PROJ_NAME = library name\n# PROJ_DIR = directory containing source & objects\n#---------------------------------------------------------------------------\nPROJ_NAME   = test\nPROJ_DIR    = $(WIN32LIB)\\keyboard\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS =  \t\\\n\t\t\t\t$(PROJ_NAME).obj\t\\\n\t\t\t\tkeyboard.obj\n\n!if 0\nPROJ_LIBS =\t\\\n\t\t\t   drawbuff.lib\t\\\n\t\t\t   win32lib.lib\n!else\nPROJ_LIBS =\t\\\n\t\t\t   drawbuff.lib\t\\\n\t\t\t\tmem.lib\t\t\t\\\n\t\t\t\tmisc.lib\t\t\t\\\n\t\t\t\tiff.lib\t\t\t\\\n\t\t\t\trawfile.lib\t\t\\\n\t\t\t\ttile.lib\t\t\t\\\n\t\t\t\tfont.lib\t\t\t\n!endif\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n# If LIB & INCLUDE are already defined, they are used in addition to the\n# WWLIB32 lib & include; otherwise, they're constructed from\n# BCDIR \n#---------------------------------------------------------------------------\n\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n.lbm.cps:\n\t$(WIN32LIB)\\\\TOOLS\\WWCOMP $*.lbm $*.cps\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(PROJ_NAME).exe\n\n#---------------------------------------------------------------------------\n# Build the EXE\n#---------------------------------------------------------------------------\n$(PROJ_NAME).exe: $(OBJECTS) $(PROJ_LIBS) \n\t $(LINK_CMD) @&&|\n$(LINK_CFG) +\n$(COMPILER)\\\\LIB\\\\c0w32.obj+\n$(OBJECTS)\n$<,$*\n$(PROJ_LIBS) +\nimport32.lib +\ncw32i.lib\n$*.def\n|\n\n$(PROJ_LIBS):\t\t\n\techo updating base library $^@\n\tcd ..\n\tmake\n\tcd $(PROJ_DIR)\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLDTEST/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .EXE makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 20, 1995  \t                   \t\t*\n#*                                                                         *\n#*                  Last Update : \t\t\t                   \t\t\t\t\t*\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the executable program you're building \t   \t\t*\n#* PROJ_LIBS\t= Westwood libraries to link your EXE to \t           \t\t\t*\n#* OBJECTS\t= list of objects in your current working directory\t   \t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t= full pathname of your working directory\t\t   \t\t\t\t\t*\n#* .xxx:\t= full pathname where various file types live\t\t   \t\t\t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n#---------------------------------------------------------------------------\n# PROJ_NAME = library name\n# PROJ_DIR = directory containing source & objects\n#---------------------------------------------------------------------------\nPROJ_NAME   = test\nPROJ_DIR    = $(WIN32LIB)\\keyboard\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS =  \t\\\n\t\t\t\t$(PROJ_NAME).obj\n\n!if 0\nPROJ_LIBS =\t\\\n\t\t\t   drawbuff.lib\t\\\n\t\t\t   win32lib.lib\n!else\nPROJ_LIBS =\t\\\n\t\t\t   drawbuff.lib\t\\\n\t\t\t\tmem.lib\t\t\t\\\n\t\t\t\tmisc.lib\t\t\t\\\n\t\t\t\tiff.lib\t\t\t\\\n\t\t\t\trawfile.lib\t\t\\\n\t\t\t\ttile.lib\t\t\t\\\n\t\t\t\tfont.lib\t\t\t\n!endif\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n# If LIB & INCLUDE are already defined, they are used in addition to the\n# WWLIB32 lib & include; otherwise, they're constructed from\n# BCDIR \n#---------------------------------------------------------------------------\n\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n.lbm.cps:\n\t$(WIN32LIB)\\\\TOOLS\\WWCOMP $*.lbm $*.cps\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(PROJ_NAME).exe\n\n#---------------------------------------------------------------------------\n# Build the EXE\n#---------------------------------------------------------------------------\n$(PROJ_NAME).exe: $(OBJECTS) $(PROJ_LIBS) \n\t $(LINK_CMD) @&&|\n$(LINK_CFG) +\n$(COMPILER)\\\\LIB\\\\c0w32.obj+\n$(OBJECTS)\n$<,$*\n$(PROJ_LIBS) +\nimport32.lib +\ncw32i.lib\n$*.def\n|\n\n$(PROJ_LIBS):\t\t\n\techo updating base library $^@\n\tcd ..\n\tmake\n\tcd $(PROJ_DIR)\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLDTEST/TEST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***             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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Keyboard Test Program                              \t\t\t  *\n *                                                                                             *\n *                    File Name : TEST.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Phil Gorrow                                                  *\n *                                                                                             *\n *                   Start Date : October 10, 1995                                             *\n *                                                                                             *\n *                  Last Update : October 16, 1995 [PWG]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *  WndProc\t\t\t-- Callback procedure for main window                                      *\n *  WinMain \t\t-- Program entry point                                                     *\n *   Init_Keyboard_Remap_Table -- initializes the keyboard remap table     *\n *   WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard* \n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <misc.h>\n#include <stdio.h>\n#include \"keyboard.h\"\n\n#define\tNAME\t\t\t\"DRAWBUFF test\"\n#define\tTITLE\t\t\t\"DRAWBUFF library test\"\nBOOL Running = TRUE;\nHANDLE ThreadHandle;\nBOOL MessageLoopThread = FALSE;\n#define\tMODE_WIDTH\t640\t\t\t\t\t\t// Width in pixels of required video mode\n#define\tMODE_HEIGHT\t400\t\t\t\t\t\t// Height in pixels of required video mode\nvoid Message_Loop(void);\nHANDLE ActiveEvent;\nWWKeyboardClass Kbd;\n#if(0)\n#define\tVK_NONE_00\t\t\t  0x00\n#define\tVK_LBUTTON          0x01\n#define\tVK_RBUTTON          0x02\n#define\tVK_CANCEL           0x03\n#define\tVK_MBUTTON          0x04\n#define\tVK_NONE_05\t\t\t  0x05\n#define\tVK_NONE_06\t\t\t  0x06\n#define\tVK_NONE_07\t\t\t  0x07\n#define\tVK_BACK             0x08\n#define\tVK_TAB              0x09\n#define\tVK_NONE_0A\t\t\t  0x0A\n#define\tVK_NONE_0B\t\t\t  0x0B\n#define\tVK_CLEAR            0x0C\n#define\tVK_RETURN           0x0D\n#define\tVK_NONE_0E\t\t\t  0x0E\n#define\tVK_NONE_0F\t\t\t  0x0F\n#define\tVK_SHIFT            0x10\n#define\tVK_CONTROL          0x11\n#define\tVK_MENU             0x12\n#define\tVK_PAUSE            0x13\n#define\tVK_CAPITAL          0x14\n#define\tVK_NONE_15\t\t\t  0x15\n#define\tVK_NONE_16\t\t\t  0x16\n#define\tVK_NONE_17\t\t\t  0x17\n#define\tVK_NONE_18\t\t\t  0x18\n#define\tVK_NONE_19\t\t\t  0x19\n#define\tVK_NONE_1A\t\t\t  0x1A\n#define\tVK_ESCAPE           0x1B\n#define\tVK_NONE_1C\t\t\t  0x1C\n#define\tVK_NONE_1D\t\t\t  0x1D\n#define\tVK_NONE_1E\t\t\t  0x1E\n#define\tVK_NONE_1F\t\t\t  0x1F\n#define\tVK_SPACE            0x20\n#define\tVK_PRIOR            0x21\n#define\tVK_NEXT             0x22\n#define\tVK_END              0x23\n#define\tVK_HOME             0x24\n#define\tVK_LEFT             0x25\n#define\tVK_UP               0x26\n#define\tVK_RIGHT            0x27\n#define\tVK_DOWN             0x28\n#define\tVK_SELECT           0x29\n#define\tVK_PRINT            0x2A\n#define\tVK_EXECUTE          0x2B\n#define\tVK_SNAPSHOT         0x2C\n#define\tVK_INSERT           0x2D\n#define\tVK_DELETE           0x2E\n#define\tVK_HELP             0x2F\n#define\tVK_0\t\t\t\t\t  0x30\n#define\tVK_1\t\t\t\t\t  0x31\n#define\tVK_2\t\t\t\t\t  0x32\n#define\tVK_3\t\t\t\t\t  0x33\n#define\tVK_4\t\t\t\t\t  0x34\n#define\tVK_5\t\t\t\t\t  0x35\n#define\tVK_6\t\t\t\t\t  0x36\n#define\tVK_7\t\t\t\t\t  0x37\n#define\tVK_8\t\t\t\t\t  0x38\n#define\tVK_9\t\t\t\t\t  0x39\n#define\tVK_0\t\t\t\t\t  0x3A\n#define\tVK_NONE_3B\t\t\t  0x3B\n#define\tVK_NONE_3C\t\t\t  0x3C\n#define\tVK_NONE_3D\t\t\t  0x3D\n#define\tVK_NONE_3E\t\t\t  0x3E\n#define\tVK_NONE_3F\t\t\t  0x3F\n#define\tVK_NONE_40\t\t\t  0x40\n#define\tVK_A\t\t\t\t\t  0x41\n#define\tVK_B\t\t\t\t\t  0x42\n#define\tVK_C\t\t\t\t\t  0x43\n#define\tVK_D\t\t\t\t\t  0x44\n#define\tVK_E\t\t\t\t\t  0x45\n#define\tVK_F\t\t\t\t\t  0x46\n#define\tVK_G\t\t\t\t\t  0x47\n#define\tVK_H\t\t\t\t\t  0x48\n#define\tVK_I\t\t\t\t\t  0x49\n#define\tVK_J\t\t\t\t\t  0x4A\n#define\tVK_K\t\t\t\t\t  0x4B\n#define\tVK_L\t\t\t\t\t  0x4C\n#define\tVK_M\t\t\t\t\t  0x4D\n#define\tVK_N\t\t\t\t\t  0x4E\n#define\tVK_O\t\t\t\t\t  0x4F\n#define\tVK_P\t\t\t\t\t  0x50\n#define\tVK_Q\t\t\t\t\t  0x51\n#define\tVK_R\t\t\t\t\t  0x52\n#define\tVK_S\t\t\t\t\t  0x53\n#define\tVK_T\t\t\t\t\t  0x54\n#define\tVK_U\t\t\t\t\t  0x55\n#define\tVK_V\t\t\t\t\t  0x56\n#define\tVK_W\t\t\t\t\t  0x57\n#define\tVK_X\t\t\t\t\t  0x58\n#define\tVK_Y\t\t\t\t\t  0x59\n#define\tVK_Z\t\t\t\t\t  0x5A\n#define\tVK_NONE_5B\t\t\t  0x5B\n#define\tVK_NONE_5C\t\t\t  0x5C\n#define\tVK_NONE_5D\t\t\t  0x5D\n#define\tVK_NONE_5E\t\t\t  0x5E\n#define\tVK_NONE_5F\t\t\t  0x5F\n#define\tVK_NUMPAD0          0x60\n#define\tVK_NUMPAD1          0x61\n#define\tVK_NUMPAD2          0x62\n#define\tVK_NUMPAD3          0x63\n#define\tVK_NUMPAD4          0x64\n#define\tVK_NUMPAD5          0x65\n#define\tVK_NUMPAD6          0x66\n#define\tVK_NUMPAD7          0x67\n#define\tVK_NUMPAD8          0x68\n#define\tVK_NUMPAD9          0x69\n#define\tVK_MULTIPLY         0x6A\n#define\tVK_ADD              0x6B\n#define\tVK_SEPARATOR        0x6C\n#define\tVK_SUBTRACT         0x6D\n#define\tVK_DECIMAL          0x6E\n#define\tVK_DIVIDE           0x6F\n#define\tVK_F1               0x70\n#define\tVK_F2               0x71\n#define\tVK_F3               0x72\n#define\tVK_F4               0x73\n#define\tVK_F5               0x74\n#define\tVK_F6               0x75\n#define\tVK_F7               0x76\n#define\tVK_F8               0x77\n#define\tVK_F9               0x78\n#define\tVK_F10              0x79\n#define\tVK_F11              0x7A\n#define\tVK_F12              0x7B\n#define\tVK_F13              0x7C\n#define\tVK_F14              0x7D\n#define\tVK_F15              0x7E\n#define\tVK_F16              0x7F\n#define\tVK_F17              0x80\n#define\tVK_F18              0x81\n#define\tVK_F19              0x82\n#define\tVK_F20              0x83\n#define\tVK_F21              0x84\n#define\tVK_F22              0x85\n#define\tVK_F23              0x86\n#define\tVK_F24              0x87\n#define\tVK_NONE_88          0x88\n#define\tVK_NONE_89          0x89\n#define\tVK_NONE_8A          0x8A\n#define\tVK_NONE_8B          0x8B\n#define\tVK_NONE_8C          0x8C\n#define\tVK_NONE_8D          0x8D\n#define\tVK_NONE_8E          0x8E\n#define\tVK_NONE_8F          0x8F\n#define\tVK_NUMLOCK          0x90\n#define\tVK_SCROLL           0x91\n#define\tVK_NONE_92\t\t\t  0x92\n#define\tVK_NONE_93\t\t\t  0x93\n#define\tVK_NONE_94\t\t\t  0x94\n#define\tVK_NONE_95\t\t\t  0x95\n#define\tVK_NONE_96\t\t\t  0x96\n#define\tVK_NONE_97\t\t\t  0x97\n#define\tVK_NONE_98\t\t\t  0x98\n#define\tVK_NONE_99\t\t\t  0x99\n#define\tVK_NONE_9A\t\t\t  0x9A\n#define\tVK_NONE_9B\t\t\t  0x9B\n#define\tVK_NONE_9C\t\t\t  0x9C\n#define\tVK_NONE_9D\t\t\t  0x9D\n#define\tVK_NONE_9E\t\t\t  0x9E\n#define\tVK_NONE_9F\t\t\t  0x9F\n#define\tVK_NONE_A0\t\t\t  0xA0\n#define\tVK_NONE_A1\t\t\t  0xA1\n#define\tVK_NONE_A2\t\t\t  0xA2\n#define\tVK_NONE_A3\t\t\t  0xA3\n#define\tVK_NONE_A4\t\t\t  0xA4\n#define\tVK_NONE_A5\t\t\t  0xA5\n#define\tVK_NONE_A6\t\t\t  0xA6\n#define\tVK_NONE_A7\t\t\t  0xA7\n#define\tVK_NONE_A8\t\t\t  0xA8\n#define\tVK_NONE_A9\t\t\t  0xA9\n#define\tVK_NONE_AA\t\t\t  0xAA\n#define\tVK_NONE_AB\t\t\t  0xAB\n#define\tVK_NONE_AC\t\t\t  0xAC\n#define\tVK_NONE_AD\t\t\t  0xAD\n#define\tVK_NONE_AE\t\t\t  0xAE\n#define\tVK_NONE_AF\t\t\t  0xAF\n#define\tVK_NONE_B0\t\t\t  0xB0\n#define\tVK_NONE_B1\t\t\t  0xB1\n#define\tVK_NONE_B2\t\t\t  0xB2\n#define\tVK_NONE_B3\t\t\t  0xB3\n#define\tVK_NONE_B4\t\t\t  0xB4\n#define\tVK_NONE_B5\t\t\t  0xB5\n#define\tVK_NONE_B6\t\t\t  0xB6\n#define\tVK_NONE_B7\t\t\t  0xB7\n#define\tVK_NONE_B8\t\t\t  0xB8\n#define\tVK_NONE_B9\t\t\t  0xB9\n#define\tVK_NONE_BA\t\t\t  0xBA\n#define\tVK_NONE_BB\t\t\t  0xBB\n#define\tVK_NONE_BC\t\t\t  0xBC\n#define\tVK_NONE_BD\t\t\t  0xBD\n#define\tVK_NONE_BE\t\t\t  0xBE\n#define\tVK_NONE_BF\t\t\t  0xBF\n#define\tVK_NONE_C0\t\t\t  0xC0\n#define\tVK_NONE_C1\t\t\t  0xC1\n#define\tVK_NONE_C2\t\t\t  0xC2\n#define\tVK_NONE_C3\t\t\t  0xC3\n#define\tVK_NONE_C4\t\t\t  0xC4\n#define\tVK_NONE_C5\t\t\t  0xC5\n#define\tVK_NONE_C6\t\t\t  0xC6\n#define\tVK_NONE_C7\t\t\t  0xC7\n#define\tVK_NONE_C8\t\t\t  0xC8\n#define\tVK_NONE_C9\t\t\t  0xC9\n#define\tVK_NONE_CA\t\t\t  0xCA\n#define\tVK_NONE_CB\t\t\t  0xCB\n#define\tVK_NONE_CC\t\t\t  0xCC\n#define\tVK_NONE_CD\t\t\t  0xCD\n#define\tVK_NONE_CE\t\t\t  0xCE\n#define\tVK_NONE_CF\t\t\t  0xCF\n#define\tVK_NONE_D0\t\t\t  0xD0\n#define\tVK_NONE_D1\t\t\t  0xD1\n#define\tVK_NONE_D2\t\t\t  0xD2\n#define\tVK_NONE_D3\t\t\t  0xD3\n#define\tVK_NONE_D4\t\t\t  0xD4\n#define\tVK_NONE_D5\t\t\t  0xD5\n#define\tVK_NONE_D6\t\t\t  0xD6\n#define\tVK_NONE_D7\t\t\t  0xD7\n#define\tVK_NONE_D8\t\t\t  0xD8\n#define\tVK_NONE_D9\t\t\t  0xD9\n#define\tVK_NONE_DA\t\t\t  0xDA\n#define\tVK_NONE_DB\t\t\t  0xDB\n#define\tVK_NONE_DC\t\t\t  0xDC\n#define\tVK_NONE_DD\t\t\t  0xDD\n#define\tVK_NONE_DE\t\t\t  0xDE\n#define\tVK_NONE_DF\t\t\t  0xDF\n#define\tVK_NONE_E0\t\t\t  0xE0\n#define\tVK_NONE_E1\t\t\t  0xE1\n#define\tVK_NONE_E2\t\t\t  0xE2\n#define\tVK_NONE_E3\t\t\t  0xE3\n#define\tVK_NONE_E4\t\t\t  0xE4\n#define\tVK_NONE_E5\t\t\t  0xE5\n#define\tVK_NONE_E6\t\t\t  0xE6\n#define\tVK_NONE_E7\t\t\t  0xE7\n#define\tVK_NONE_E8\t\t\t  0xE8\n#define\tVK_NONE_E9\t\t\t  0xE9\n#define\tVK_NONE_EA\t\t\t  0xEA\n#define\tVK_NONE_EB\t\t\t  0xEB\n#define\tVK_NONE_EC\t\t\t  0xEC\n#define\tVK_NONE_ED\t\t\t  0xED\n#define\tVK_NONE_EE\t\t\t  0xEE\n#define\tVK_NONE_EF\t\t\t  0xEF\n#define\tVK_NONE_F0\t\t\t  0xF0\n#define\tVK_NONE_F1\t\t\t  0xF1\n#define\tVK_NONE_F2\t\t\t  0xF2\n#define\tVK_NONE_F3\t\t\t  0xF3\n#define\tVK_NONE_F4\t\t\t  0xF4\n#define\tVK_NONE_F5\t\t\t  0xF5\n#define\tVK_NONE_F6\t\t\t  0xF6\n#define\tVK_NONE_F7\t\t\t  0xF7\n#define\tVK_NONE_F8\t\t\t  0xF8\n#define\tVK_NONE_F9\t\t\t  0xF9\n#define\tVK_NONE_FA\t\t\t  0xFA\n#define\tVK_NONE_FB\t\t\t  0xFB\n#define\tVK_NONE_FC\t\t\t  0xFC\n#define\tVK_NONE_FD\t\t\t  0xFD\n#define\tVK_NONE_FE\t\t\t  0xFE\n#define\tVK_NONE_FF\t\t\t  0xFF\n#endif\n\nchar *VK_Name[] = {\n\t\"VK_NONE_00\",\n\t\"VK_LBUTTON\",\n\t\"VK_RBUTTON\",\n\t\"VK_CANCEL\",\n\t\"VK_MBUTTON\",\n\t\"VK_NONE_05\",\n\t\"VK_NONE_06\",\n\t\"VK_NONE_07\",\n\t\"VK_BACK\",\n\t\"VK_TAB\",\n\t\"VK_NONE_0A\",\n\t\"VK_NONE_0B\",\n\t\"VK_CLEAR\",\n\t\"VK_RETURN\",\n\t\"VK_NONE_0E\",\n\t\"VK_NONE_0F\",\n\t\"VK_SHIFT\",\n\t\"VK_CONTROL\",\n\t\"VK_MENU\",\n\t\"VK_PAUSE\",\n\t\"VK_CAPITAL\",\n\t\"VK_NONE_15\",\n\t\"VK_NONE_16\",\n\t\"VK_NONE_17\",\n\t\"VK_NONE_18\",\n\t\"VK_NONE_19\",\n\t\"VK_NONE_1A\",\n\t\"VK_ESCAPE\",\n\t\"VK_NONE_1C\",\n\t\"VK_NONE_1D\",\n\t\"VK_NONE_1E\",\n\t\"VK_NONE_1F\",\n\t\"VK_SPACE\",\n\t\"VK_PRIOR\",\n\t\"VK_NEXT\",\n\t\"VK_END\",\n\t\"VK_HOME\",\n\t\"VK_LEFT\",\n\t\"VK_UP\",\n\t\"VK_RIGHT\",\n\t\"VK_DOWN\",\n\t\"VK_SELECT\",\n\t\"VK_PRINT\",\n\t\"VK_EXECUTE\",\n\t\"VK_SNAPSHOT\",\n\t\"VK_INSERT\",\n\t\"VK_DELETE\",\n\t\"VK_HELP\",\n\t\"VK_0\",\n\t\"VK_1\",\n\t\"VK_2\",\n\t\"VK_3\",\n\t\"VK_4\",\n\t\"VK_5\",\n\t\"VK_6\",\n\t\"VK_7\",\n\t\"VK_8\",\n\t\"VK_9\",\n\t\"VK_0\",\n\t\"VK_NONE_3B\",\n\t\"VK_NONE_3C\",\n\t\"VK_NONE_3D\",\n\t\"VK_NONE_3E\",\n\t\"VK_NONE_3F\",\n\t\"VK_NONE_40\",\n\t\"VK_A\",\n\t\"VK_B\",\n\t\"VK_C\",\n\t\"VK_D\",\n\t\"VK_E\",\n\t\"VK_F\",\n\t\"VK_G\",\n\t\"VK_H\",\n\t\"VK_I\",\n\t\"VK_J\",\n\t\"VK_K\",\n\t\"VK_L\",\n\t\"VK_M\",\n\t\"VK_N\",\n\t\"VK_O\",\n\t\"VK_P\",\n\t\"VK_Q\",\n\t\"VK_R\",\n\t\"VK_S\",\n\t\"VK_T\",\n\t\"VK_U\",\n\t\"VK_V\",\n\t\"VK_W\",\n\t\"VK_X\",\n\t\"VK_Y\",\n\t\"VK_Z\",\n\t\"VK_NONE_5B\",\n\t\"VK_NONE_5C\",\n\t\"VK_NONE_5D\",\n\t\"VK_NONE_5E\",\n\t\"VK_NONE_5F\",\n\t\"VK_NUMPAD0\",\n\t\"VK_NUMPAD1\",\n\t\"VK_NUMPAD2\",\n\t\"VK_NUMPAD3\",\n\t\"VK_NUMPAD4\",\n\t\"VK_NUMPAD5\",\n\t\"VK_NUMPAD6\",\n\t\"VK_NUMPAD7\",\n\t\"VK_NUMPAD8\",\n\t\"VK_NUMPAD9\",\n\t\"VK_MULTIPLY\",\n\t\"VK_ADD\",\n\t\"VK_SEPARATOR\",\n\t\"VK_SUBTRACT\",\n\t\"VK_DECIMAL\",\n\t\"VK_DIVIDE\",\n\t\"VK_F1\",\n\t\"VK_F2\",\n\t\"VK_F3\",\n\t\"VK_F4\",\n\t\"VK_F5\",\n\t\"VK_F6\",\n\t\"VK_F7\",\n\t\"VK_F8\",\n\t\"VK_F9\",\n\t\"VK_F10\",\n\t\"VK_F11\",\n\t\"VK_F12\",\n\t\"VK_F13\",\n\t\"VK_F14\",\n\t\"VK_F15\",\n\t\"VK_F16\",\n\t\"VK_F17\",\n\t\"VK_F18\",\n\t\"VK_F19\",\n\t\"VK_F20\",\n\t\"VK_F21\",\n\t\"VK_F22\",\n\t\"VK_F23\",\n\t\"VK_F24\",\n\t\"VK_NONE_88\",\n\t\"VK_NONE_89\",\n\t\"VK_NONE_8A\",\n\t\"VK_NONE_8B\",\n\t\"VK_NONE_8C\",\n\t\"VK_NONE_8D\",\n\t\"VK_NONE_8E\",\n\t\"VK_NONE_8F\",\n\t\"VK_NUMLOCK\",\n\t\"VK_SCROLL\",\n\t\"VK_NONE_92\",\n\t\"VK_NONE_93\",\n\t\"VK_NONE_94\",\n\t\"VK_NONE_95\",\n\t\"VK_NONE_96\",\n\t\"VK_NONE_97\",\n\t\"VK_NONE_98\",\n\t\"VK_NONE_99\",\n\t\"VK_NONE_9A\",\n\t\"VK_NONE_9B\",\n\t\"VK_NONE_9C\",\n\t\"VK_NONE_9D\",\n\t\"VK_NONE_9E\",\n\t\"VK_NONE_9F\",\n\t\"VK_NONE_A0\",\n\t\"VK_NONE_A1\",\n\t\"VK_NONE_A2\",\n\t\"VK_NONE_A3\",\n\t\"VK_NONE_A4\",\n\t\"VK_NONE_A5\",\n\t\"VK_NONE_A6\",\n\t\"VK_NONE_A7\",\n\t\"VK_NONE_A8\",\n\t\"VK_NONE_A9\",\n\t\"VK_NONE_AA\",\n\t\"VK_NONE_AB\",\n\t\"VK_NONE_AC\",\n\t\"VK_NONE_AD\",\n\t\"VK_NONE_AE\",\n\t\"VK_NONE_AF\",\n\t\"VK_NONE_B0\",\n\t\"VK_NONE_B1\",\n\t\"VK_NONE_B2\",\n\t\"VK_NONE_B3\",\n\t\"VK_NONE_B4\",\n\t\"VK_NONE_B5\",\n\t\"VK_NONE_B6\",\n\t\"VK_NONE_B7\",\n\t\"VK_NONE_B8\",\n\t\"VK_NONE_B9\",\n\t\"VK_NONE_BA\",\n\t\"VK_NONE_BB\",\n\t\"VK_NONE_BC\",\n\t\"VK_NONE_BD\",\n\t\"VK_NONE_BE\",\n\t\"VK_NONE_BF\",\n\t\"VK_NONE_C0\",\n\t\"VK_NONE_C1\",\n\t\"VK_NONE_C2\",\n\t\"VK_NONE_C3\",\n\t\"VK_NONE_C4\",\n\t\"VK_NONE_C5\",\n\t\"VK_NONE_C6\",\n\t\"VK_NONE_C7\",\n\t\"VK_NONE_C8\",\n\t\"VK_NONE_C9\",\n\t\"VK_NONE_CA\",\n\t\"VK_NONE_CB\",\n\t\"VK_NONE_CC\",\n\t\"VK_NONE_CD\",\n\t\"VK_NONE_CE\",\n\t\"VK_NONE_CF\",\n\t\"VK_NONE_D0\",\n\t\"VK_NONE_D1\",\n\t\"VK_NONE_D2\",\n\t\"VK_NONE_D3\",\n\t\"VK_NONE_D4\",\n\t\"VK_NONE_D5\",\n\t\"VK_NONE_D6\",\n\t\"VK_NONE_D7\",\n\t\"VK_NONE_D8\",\n\t\"VK_NONE_D9\",\n\t\"VK_NONE_DA\",\n\t\"VK_NONE_DB\",\n\t\"VK_NONE_DC\",\n\t\"VK_NONE_DD\",\n\t\"VK_NONE_DE\",\n\t\"VK_NONE_DF\",\n\t\"VK_NONE_E0\",\n\t\"VK_NONE_E1\",\n\t\"VK_NONE_E2\",\n\t\"VK_NONE_E3\",\n\t\"VK_NONE_E4\",\n\t\"VK_NONE_E5\",\n\t\"VK_NONE_E6\",\n\t\"VK_NONE_E7\",\n\t\"VK_NONE_E8\",\n\t\"VK_NONE_E9\",\n\t\"VK_NONE_EA\",\n\t\"VK_NONE_EB\",\n\t\"VK_NONE_EC\",\n\t\"VK_NONE_ED\",\n\t\"VK_NONE_EE\",\n\t\"VK_NONE_EF\",\n\t\"VK_NONE_F0\",\n\t\"VK_NONE_F1\",\n\t\"VK_NONE_F2\",\n\t\"VK_NONE_F3\",\n\t\"VK_NONE_F4\",\n\t\"VK_NONE_F5\",\n\t\"VK_NONE_F6\",\n\t\"VK_NONE_F7\",\n\t\"VK_NONE_F8\",\n\t\"VK_NONE_F9\",\n\t\"VK_NONE_FA\",\n\t\"VK_NONE_FB\",\n\t\"VK_NONE_FC\",\n\t\"VK_NONE_FD\",\n\t\"VK_NONE_FE\",\n\t\"VK_NONE_FF\",\n};\n\nchar *_keyname[] = {\n\t\"KN_NONE\",\n\t\"KN_GRAVE\",\n\t\"KN_1\",\n\t\"KN_2\",\n\t\"KN_3\",\n\t\"KN_4\",\n\t\"KN_5\",\n\t\"KN_6\",\n\t\"KN_7\",\n\t\"KN_8\",\n\t\"KN_9\",\n\t\"KN_0\",\n\t\"KN_MINUS\",\n\t\"KN_EQUAL\",\n\t\"KN_RESERVED1\",\n\t\"KN_BACKSPACE\",\n\t\"KN_TAB\",\n\t\"KN_Q\",\n\t\"KN_W\",\n\t\"KN_E\",\n\t\"KN_R\",\n\t\"KN_T\",\n\t\"KN_Y\",\n\t\"KN_U\",\n\t\"KN_I\",\n\t\"KN_O\",\n\t\"KN_P\",\n\t\"KN_LBRACKET\",\n\t\"KN_RBRACKET\",\n\t\"KN_BACKSLASH\",\n\t\"KN_CAPSLOCK\",\n\t\"KN_A\",\n\t\"KN_S\",\n\t\"KN_D\",\n\t\"KN_F\",\n\t\"KN_G\",\n\t\"KN_H\",\n\t\"KN_J\",\n\t\"KN_K\",\n\t\"KN_L\",\n\t\"KN_SEMICOLON\",\n\t\"KN_SQUOTE\",\n\t\"KN_BACKSLASH2\",\n\t\"KN_RETURN\",\n\t\"KN_LSHIFT\",\n\t\"KN_MOUSE_MOVE\",\n\t\"KN_Z\",\n\t\"KN_X\",\n\t\"KN_C\",\n\t\"KN_V\",\n\t\"KN_B\",\n\t\"KN_N\",\n\t\"KN_M\",\n\t\"KN_COMMA\",\t\t\t\t\t\t\t\t\n\t\"KN_PERIOD\",\n\t\"KN_SLASH\",\n\t\"KN_RESERVED3\",\n\t\"KN_RSHIFT\",\n\t\"KN_LCTRL\",\n\t\"KN_LCOMM\",\n\t\"KN_LALT\",\n\t\"KN_SPACE\",\n\t\"KN_RALT\",\n\t\"KN_RCOMM\",\n\t\"KN_RCTRL\",\n\t\"KN_LMOUSE\",\n\t\"KN_RMOUSE\",\n\t\"KN_JBUTTON1\",\n\t\"KN_JBUTTON2\",\n\t\"KN_J_UP\",\n\t\"KN_J_RIGHT\",\n\t\"KN_J_DOWN\",\n\t\"KN_J_LEFT\",\n\t\"KN_SPECIAL9\",\n\t\"KN_SPECIAL10\",\n\t\"KN_E_INSERT\",\n\t\"KN_E_DELETE\",\n\t\"KN_RESERVED4\",\n\t\"KN_RESERVED5\",\n\t\"KN_E_LEFT\",\n\t\"KN_E_HOME\",\n\t\"KN_E_END\",\n\t\"KN_RESERVED6\",\n\t\"KN_E_UP\",\n\t\"KN_E_DOWN\",\n\t\"KN_E_PGUP\",\n\t\"KN_E_PGDN\",\n\t\"KN_K_LPAREN\",\n\t\"KN_K_RPAREN\",\n\t\"KN_E_RIGHT\",\n\t\"KN_NUMLOCK\",\n\t\"KN_HOME\",\n\t\"KN_UPLEFT/KN_HOME\",\n\t\"KN_LEFT\",\n\t\"KN_END\",\n\t\"KN_DOWNLEFT/KN_END\",\n\t\"KN_RESERVED7\",\n\t\"KN_KEYPAD_SLASH\",\t\t\t\t\t\t \n\t\"KN_UP\",\t\t\t\t\t\t\t\t\t \n\t\"KN_CENTER\",\t\t\t\t\t\t\t\t \n\t\"KN_DOWN\",\t\t\t\t\t\t\t\t\t \n\t\"KN_INSERT\",\t\t\t\t\t\t\t\t \n\t\"KN_KEYPAD_ASTERISK\",\t\t\t\t\t \n\t\"KN_PGUP\",\t\t\t\t\t\t\t\t\t \n\t\"KN_UPRIGHT/KN_PGUP\",\n\t\"KN_RIGHT\",\t\t\t\t\t\t\t\t \n\t\"KN_PGDN\",\t\t\t\t\t\t\t\t\t \n\t\"KN_DOWNRIGHT/KN_PGDN\",\n\t\"KN_DELETE\",\t\t\t\t\t\t\t\t \n\t\"KN_KEYPAD_MINUS\",\t\t\t\t\t\t \n\t\"KN_KEYPAD_PLUS\",\t\t\t\t\t\t \n\t\"KN_RESERVED8\",\n\t\"KN_KEYPAD_RETURN\",\t\t\t\t\t\t \n\t\"KN_RESERVED9\",\n\t\"KN_ESC\",\n\t\"KN_HELP\",\t\t\t\t\t\t\t\t\t\t\n\t\"KN_F1\",\n\t\"KN_F2\",\n\t\"KN_F3\",\n\t\"KN_F4\",\n\t\"KN_F5\",\n\t\"KN_F6\",\n\t\"KN_F7\",\n\t\"KN_F8\",\n\t\"KN_F9\",\n\t\"KN_F10\",\n\t\"KN_F11\",\n\t\"KN_F12\",\n\t\"KN_PRNTSCRN\",\t\t\t\t\t\t\t\t\n\t\"KN_SCROLLLOCK\",\t\t\t\t\t\t\t\t\n\t\"KN_PAUSE\"\n};\nchar *_steve_translate[]={\n\t\t\"?\",\n\t\t\"ESC-27\",\n\t\t\"1\",\n\t\t\"2\",\n\t\t\"3\",\n\t\t\"4\",\n\t\t\"5\",\n\t\t\"6\",\n\t\t\"7\",\n\t\t\"8\",\n\t\t\"9\",\n\t\t\"0\",\n\t\t\"-\",\n\t\t\"=\",\n\t\t\"BACKSPACE\",\n\t\t\"TAB\",\n\t\t\"q\",\n\t\t\"w\",\n\t\t\"e\",\n\t\t\"r\",\n\t\t\"t\",\n\t\t\"y\",\n\t\t\"u\",\n\t\t\"i\",\n\t\t\"o\",\n\t\t\"p\",\n\t\t\"[\",\n\t\t\"]\",\n\t\t\"return\",\n\t\t\"?\",\n\t\t\"a\",\n\t\t\"s\",\n\t\t\"d\",\n\t\t\"f\",\n\t\t\"g\",\n\t\t\"h\",\n\t\t\"j\",\n\t\t\"k\",\n\t\t\"l\",\n\t\t\";\",\n\t\t\"'\",\n\t\t\"ESC-27\",\n\t\t\"?\",\n\t\t\"\\\\\",\n\t\t\"z\",\n\t\t\"x\",\n\t\t\"c\",\n\t\t\"v\",\n\t\t\"b\",\n\t\t\"n\",\n\t\t\"m\",\n\t\t\",\",\n\t\t\".\",\n\t\t\"/\",\n\t\t\"?\",\n\t\t\"*\",\n\t\t\"?\",\n\t\t\" \",\n\t\t\"?\",\n\t\t\"f1-127\",\n\t\t\"127\",\n\t\t\"?\",\n\t\t\"?\",\n\t\t\"?\",\n\t\t\"?\",\n\t\t\"?\",\n\t\t\"?\",\n\t\t\"?\",\n\t\t\"?\",\n\t\t\"?\",\n\t\t\"?\",\n\t\t\"7\",\n\t\t\"8\",\n\t\t\"9\",\n\t\t\"-\",\n\t\t\"4\",\n\t\t\"5\",\n\t\t\"6\",\n\t\t\"+\",\n\t\t\"1\",\n\t\t\"2\",\n\t\t\"3\",\n\t\t\"?\",\n\t\t\"?\",\n\t\t\"?\",\n\t\t\"?\",\n\t\t\"?\",\n\t\t\"?\",\n\t\t\"F12\",\n};\nstatic short   cxChar, cxCaps, cyChar;\n\n/***********************************************************************************************\n * WndProc -- windows message callback                                                         *\n *                                                                                             *\n *   Pilfered from a windows example program - HELLOWIN.C                                      *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Standard Windoze callback parameters                                              *\n *                                                                                             *\n * OUTPUT:   long                                                                              *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 1:39PM ST : Pilfered                                                             *\n *=============================================================================================*/\n\nlong FAR PASCAL _export WndProc (HWND hwnd, UINT message, UINT wParam, LONG lParam)\n{\n\tHDC\t\t\t\thdc;\n\tPAINTSTRUCT\t\tps;\n\tstatic int\t\tline \t= 1;\n\tchar \t\t\t\tbuffer[100];\n\tTEXTMETRIC\t\ttm;\n\tRECT\t\t\t\trect;\n\tint\t\t\t\ttransition;\n\tint\t\t\t\tprevious;\n\tint\t\t\t\tcontext;\n\tint\t\t\t\textended;\n\tint\t\t\t\toem;\n\tint\t\t\t\trep;\n\tint\t\t\t\tshift,ctrl,alt,caps,nums;\n\tint\t\t\t\tvk_key;\n\tBYTE\t\t\t\tremaptbl[256];\n\tWORD\t\t\t\tkey;\n\tchar\t\t\t\tsrcstr[2];\n\tchar\t\t\t\tdststr[2];\n\n\tswitch (message) {\n\t\tcase WM_SYSKEYDOWN:\n\t\tcase WM_SYSKEYUP:\n\t\t\tKbd.Message_Handler(hwnd, message, wParam, lParam);\n\t\t\tbreak;\n\n\t\tcase WM_KEYDOWN:\n\t\tcase WM_KEYUP:\n\t\tcase WM_LBUTTONDOWN:\n\t\tcase WM_LBUTTONUP:\n\t\tcase WM_LBUTTONDBLCLK:\n\t\tcase WM_MBUTTONDOWN:\n\t\tcase WM_MBUTTONUP:\n\t\tcase WM_MBUTTONDBLCLK:\n\t\tcase WM_RBUTTONDOWN:\n\t\tcase WM_RBUTTONUP:\n\t\tcase WM_RBUTTONDBLCLK:\n\t\t\tKbd.Message_Handler(hwnd, message, wParam, lParam);\n//\t\t\tMessage_Loop();\n\t\t\treturn(0);\n\n\t\tcase WM_CREATE:\n\t\t\thdc = GetDC(hwnd);\n\t\t\tGetTextMetrics(hdc, &tm);\n\t\t\tcxChar = tm.tmAveCharWidth;\n\t\t\tcxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2;\n\t\t\tcyChar = tm.tmHeight + tm.tmExternalLeading;\n\t\t\tReleaseDC(hwnd, hdc);\n\t\t\treturn(0);\n\n\n  \t\tcase WM_PAINT:\n\t\t\thdc = BeginPaint(hwnd, &ps);\n\t\t\tGetTextMetrics(hdc, &tm);\n\t\t\tEndPaint(hwnd, &ps);\n\t\t\treturn(0);\n\n//\t\tcase WM_CLOSE:\n\t\tcase WM_DESTROY:\n\t\t\tRunning = FALSE;\n\t\t\tWaitForSingleObject(ThreadHandle, INFINITE);\n\t\t\tPostQuitMessage (0);\n\t\t\tReset_Video_Mode();\n\t\t\treturn(0);\n\t\tcase WM_ACTIVATEAPP:\n\t\t\tif ((BOOL)wParam)\t{\n\t\t\t\tSetEvent(ActiveEvent);\n\t\t\t} else {\n\t\t\t\tResetEvent(ActiveEvent);\t\t\t\t\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n\tif (line == 23) {\n\t\tInvalidateRect(hwnd, NULL, TRUE);\n\t\tline = 1;\n\t}\n\n\treturn DefWindowProc (hwnd, message, wParam, lParam) ;\n}\n\nvoid Message_Loop(void)\n{\n\tint\t\t\t\t\tkey,shift,ctrl,alt,rls,dbl;\n\tchar\t\t\t\t\tbuffer[255];\n\tHDC\t\t\t\thdc;\n\tstatic int\t\t\t\tline=0;\n\n\twhile (Running) {\n\t\tWaitForSingleObject(ActiveEvent, INFINITE);\n\t\tif (Kbd.Check()) {\n\t\t\tint key = Kbd.Get();\n\t\t\tif (key & WWKEY_VK_BIT) {\n\t\t\t\tKbd.Split(key, shift, ctrl, alt,rls,dbl);\n\t\t\t\tif (!Kbd.Is_Mouse_Key(key)) {\n\t\t\t\t\tsprintf(buffer, \"Key (VK) = %d (%s)  shift = %d  control = %d  menu = %d  rls = %d  dbl = %d\", key, VK_Name[key], shift, ctrl, alt, rls, dbl);\n\t\t\t\t\tif (key == 27)\t{\n\t\t\t\t\t\tPostMessage (MainWindow, WM_DESTROY,0,0);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(buffer, \"Mouse = %d @ (%d,%d) shift = %d  control = %d  menu = %d\", key, Kbd.MouseQX, Kbd.MouseQY, shift, ctrl, alt);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tKbd.Split(key, shift, ctrl, alt, rls, dbl);\n\t\t\t\tsprintf(buffer, \"Key (ACSII) = %d (%c)  shift = %d  control = %d  menu = %d  rls = %d  dbl = %d\", key, key, shift, ctrl, alt, rls, dbl);\n\t\t\t}\n\t\t\thdc = GetDC(MainWindow);\n\t\t\tTextOut(hdc, cxChar, cyChar * (line + 1), buffer, lstrlen(buffer));\n\t\t\tsprintf(buffer, \"Mouses current status:  x = %3d,  y = %3d\", Kbd.Get_Mouse_X(), Kbd.Get_Mouse_Y());\n\t\t\tTextOut(hdc, cxChar, cyChar * (1), buffer, lstrlen(buffer));\n\t\t\tline++;\n\t\t\tif (line == 23) {\n\t\t\t\tInvalidateRect(MainWindow, NULL, TRUE);\n\t\t\t\tline = 1;\n\t\t\t}\n\t\t\tReleaseDC(MainWindow, hdc);\n\t\t}\n\t}\n\n}\t\n\n/***********************************************************************************************\n * WinMain -- Program entry point                                                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Standard Windows startup parameters                                               *\n *                                                                                             *\n * OUTPUT:   msg.wParam                                                                        *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 1:28PM ST : Created                                                              *\n *=============================================================================================*/\n\nint PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,\n\t\t\t\t\t\t  LPSTR /*lpszCmdParam*/, int nCmdShow)\n{\n\tHWND        \t\thwnd ;\n\tWNDCLASS    \t\twndclass ;\n\tMSG         \t\tmsg ;\n\tint\t\t\t\t\ti,j,k;\n\tint\t\t\t\t\tkey,shift,ctrl,alt,rls,dbl;\n\tchar\t\t\t\t\tbuffer[255];\n\tHDC\t\t\t\thdc;\n\n\t//\n\t// Register the window class\n\t//\n\n\tif (!hPrevInstance)\n\t\t{\n\t\twndclass.style         = CS_HREDRAW | CS_VREDRAW ;\n\t\twndclass.lpfnWndProc   = WndProc ;\n\t\twndclass.cbClsExtra    = 0 ;\n\t\twndclass.cbWndExtra    = 0 ;\n\t\twndclass.hInstance     = hInstance ;\n\t\twndclass.hIcon         = LoadIcon (hInstance, IDI_APPLICATION) ;\n\t\twndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;\n\t\twndclass.hbrBackground = GetStockObject(WHITE_BRUSH);\n\t\twndclass.lpszMenuName  = NULL;\n\t\twndclass.lpszClassName = NAME;\n\n\t\tRegisterClass (&wndclass) ;\n\t}\n\n\n\t//\n\t// Create our main window\n\t//\n\thwnd = MainWindow = CreateWindowEx (\n\t\t\t\t\t\t\tWS_EX_TOPMOST,\n\t\t\t\t\t\t\tNAME,\n\t\t\t\t\t\t\tTITLE,\n\t\t\t\t\t\t\tWS_POPUP | WS_MAXIMIZE,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tMODE_WIDTH,\n\t\t\t\t\t\t\tMODE_HEIGHT,\n\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\thInstance,\n\t\t\t\t\t\t\tNULL );\n\n\tShowWindow (hwnd, nCmdShow) ;\n\tUpdateWindow (hwnd) ;\n\tSetFocus (hwnd);\n\n\tSet_Video_Mode( MainWindow , MODE_WIDTH , MODE_HEIGHT , 8 );\n//\tShowWindow (hwnd, nCmdShow) ;\n//\tUpdateWindow (hwnd) ;\n//\tSetFocus (hwnd);\n\t\t\t\t\t\t\t\t// (Dangerous  if Windoze can change the handle)\n\n//\tSet_Video_Mode( MainWindow , MODE_WIDTH , MODE_HEIGHT , 8 );\n#if(TRUE)\n\tDWORD threadid;\n\tActiveEvent = CreateEvent(NULL, TRUE, TRUE, \"Active Event\");\n\tThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Message_Loop, NULL, 0, &threadid);\n\tif (!ThreadHandle)\t{\n\t\tDWORD error = GetLastError();\n\t\tsprintf(buffer, \"Last Error was equal to %d\", error);\n\t\tMessageBox(hwnd, buffer,\"Error\",MB_ICONEXCLAMATION|MB_OK);\n\t\treturn(0);\n\t}\n#endif\n\n\twhile (1) {\n\t\tif (!GetMessage(&msg, NULL, 0, 0)) {\n\t\t\tbreak;\n\t\t}\n\t\tTranslateMessage(&msg);\n\t\tDispatchMessage(&msg);\n\t}\n\n\treturn(0);\n//\treturn msg.wParam;\n}\n\n\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/OLDTEST/TEST.DEF",
    "content": "IMPORTS\n\tDirectDrawCreate=DDRAW.DirectDrawCreate\n\tDirectSoundCreate=DSOUND.DirectSoundCreate\n\tDirectPlayEnumerate=DPLAY.DirectPlayEnumerate\n\tDirectPlayCreate=DPLAY.DirectPlayCreate\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/TEST/HOLD.DEF",
    "content": "IMPORTS\n\tDirectDrawCreate=DDRAW.DirectDrawCreate\n\tDirectSoundCreate=DSOUND.DirectSoundCreate\n\tDirectPlayEnumerate=DPLAY.DirectPlayEnumerate\n\tDirectPlayCreate=DPLAY.DirectPlayCreate\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/TEST/KEYBOARD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*********************************************************************************************** \n *                                                                                             * \n *                 Project Name : Westwood Keyboard Library                                    * \n *                                                                                             * \n *                    File Name : KEYBOARD.CPP                                                 * \n *                                                                                             * \n *                   Programmer : Philip W. Gorrow                                             * \n *                                                                                             * \n *                   Start Date : 10/16/95                                                     * \n *                                                                                             * \n *                  Last Update : October 17, 1995 [PWG]                                       * \n *                                                                                             * \n *---------------------------------------------------------------------------------------------* \n * Functions:                                                                                  * \n *   WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                         * \n *   WWKeyboardClass::Get -- Logic to get a metakey from the buffer                            * \n *   WWKeyboardClass::Check -- Checks to see if a key is in the buffer                         * \n *   WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer    * \n *   WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer               * \n *   WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels           * \n *   WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels           * \n *   WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars       * \n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"keyboard.h\"\n\n/*********************************************************************************************** \n * WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class                * \n *                                                                                             * \n * INPUT:\t\tnone\t\t\t\t\t\t\t                                                        *\n *                                                                                             * \n * OUTPUT:     none\t\t\t\t\t\t\t                                                        *\n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/16/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nWWKeyboardClass::WWKeyboardClass(void)\n{\n\t//\n\t// Initialize the keyboard remap table for our system (note it would be bad if someone\n\t// switched keyboard modes after this happened.\n\t//\n\tmemset(VKRemap, 0, 2048);\n\tmemset(AsciiRemap, 0, 256);\n\tfor (short lp = 1; lp < 255; lp ++) {\n\t\tint vk_key = VkKeyScan(lp);\n\t\tif (vk_key > 0 && vk_key < 2048) {\n\t\t\tAsciiRemap[vk_key] = lp;\n\t\t\tVKRemap[vk_key] \t = vk_key & 0xFF;\n\t\t}\n\t}\n\n\t//\n\t// Build a remap table of the different keys which are affected by the caps lock and\n\t// the num lock.\n\t//\n\tmemset(ToggleKeys, 0, 256);\n\tfor (lp = 0; lp < 255; lp++ ) {\n\t\tif (isalpha(lp) && isupper(lp)) {\n\t\t\tToggleKeys[lp] = 1;\n\t\t}\n\t\tif (lp >= VK_NUMPAD0 && lp <= VK_DIVIDE) {\n\t\t\tToggleKeys[lp] = 2;\n\t\t}\n\t}\n\n\t//\n\t// Our buffer should start devoid of keys.\n\t//\n\tmemset(Buffer, 0, 256);\n\tHead\t\t= 0;\n\tTail\t\t= 0;\n\n\t//\n\t// There should be no starting queued mouse events for us to have to worry\n\t// about.\n\t//\n\tMouseQX\t= 0;\n\tMouseQY\t= 0;\n}\n\n/*********************************************************************************************** \n * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer                 * \n *                                                                                             * \n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             * \n * OUTPUT:     int\t\t- the key value that was pulled from buffer (includes bits)\t\t\t\t  *                                                                                * \n *                                                                                             * \n * WARNINGS:   If the key was a mouse event MouseQX and MouseQY will be updated                *\n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/17/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nint WWKeyboardClass::Buff_Get(void)\n{\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t\t\t// wait for key in buffer\n\tint \ttemp\t\t= Buffer[Head];\t\t\t\t\t\t// get key out of the buffer\n\tint   newhead\t= Head;\t\t\t\t\t\t\t\t\t// save off head for manipulation\n\tif (Is_Mouse_Key(temp)) {\t\t\t\t\t\t\t\t// if key is a mouse then\n\t\tMouseQX\t= Buffer[Head+1];\t\t\t\t\t\t\t//\t\tget the x and y pos\n\t\tMouseQY\t= Buffer[Head+2];\t\t\t\t\t\t\t//\t\tfrom the buffer\n\t\tnewhead += 3;\t\t  \t\t\t\t\t\t\t\t\t//\t\tadjust head forward\n\t} else {\n\t\tnewhead += 1;\t\t  \t\t\t\t\t\t\t\t\t//\t\tadjust head forward\n\t}\n\tnewhead\t&= 255;\n\tHead\t\t = newhead;\n\treturn(temp);\n}\n\nBOOL WWKeyboardClass::Is_Mouse_Key(int key)\n{\n\tkey &= 0xFF;\n\treturn (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON);\n}\n\n\n/*********************************************************************************************** \n * WWKeyboardClass::Check -- Checks to see if a key is in the buffer                           * \n *                                                                                             * \n * INPUT:                                                                                      * \n *                                                                                             * \n * OUTPUT:                                                                                     * \n *                                                                                             * \n * WARNINGS:                                                                                   * \n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/16/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nBOOL WWKeyboardClass::Check(void)\n{\n\tunsigned short temp;\t\t\t\t\t\t\t\t\t\t\t// store temp holding spot for key\n\tif (Head == Tail) return(FALSE);\t\t\t\t\t\t\t// if no keys in buff then get out\n\ttemp = Buffer[Head];\t\t\t\t\t\t\t\t\t\t\t// get key out of the buffer\n\treturn(temp);\t\t\t\t\t\t\t\t\t\t\t\t\t// send it back to main program\n}\t\n\n/*********************************************************************************************** \n * WWKeyboardClass::Get -- Logic to get a metakey from the buffer                              * \n *                                                                                             * \n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             * \n * OUTPUT:     int\t\t- the meta key taken from the buffer.\t\t\t\t\t\t\t\t\t\t\t  * \n *                                                                                             * \n * WARNINGS:\tThis routine will not return until a keypress is received\t\t\t\t\t\t\t  *\n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/16/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nint WWKeyboardClass::Get(void)\n{\n\tint temp,bits;\t\t\t\t\t\t\t\t\t\t// store temp holding spot for key\n\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t// wait for key in buffer\n\ttemp = Buff_Get();\t\t\t\t\t\t\t\t// get key from the buffer\n\n\tbits = temp & 0xFF00;\t\t\t\t\t\t\t// save of keyboard bits\n\t\n\tif (!(bits & WWKEY_VK_BIT)) {\t\t\t\t\t// if its not a virtual key\n\t\ttemp = AsciiRemap[temp&0x1FF] | bits;\t//   convert to ascii equivalent\n\t}\n\treturn(temp);\t\t\t\t\t\t\t// return the key that we pulled out\n}\t\n\n/*********************************************************************************************** \n * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                           * \n *                                                                                             * \n * INPUT:\t\tint\t \t- the key to insert into the buffer          \t\t\t\t\t\t\t\t  *\n *                                                                                             * \n * OUTPUT:     bool\t\t- true if key is sucessfuly inserted.\t\t\t\t\t\t\t              *\n *                                                                                             * \n * WARNINGS:   none\t\t\t\t\t\t\t                                                        *\n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/16/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nBOOL WWKeyboardClass::Put(int key)\n{\n\tint\ttemp\t\t= (Tail + 1) & 255;\n\tif (temp != Head) \n\t{\n\t\tBuffer[Tail]\t= key;\n\n\t\t//\n\t\t// Critical Line\n\t\t//\n\t\tTail\t\t\t\t= temp;\n\t\treturn(TRUE);\n\t}\n\treturn(FALSE);\n}\n/*********************************************************************************************** \n * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer      * \n *                                                                                             * \n * INPUT:                                                                                      * \n *                                                                                             * \n * OUTPUT:                                                                                     * \n *                                                                                             * \n * WARNINGS:                                                                                   * \n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/16/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nWWKeyboardClass::Put_Key_Message(UINT vk_key, BOOL release, BOOL dbl)\n{\n\tint bits = 0;\n\t//\n\t// Get the status of all of the different keyboard modifiers.  Note, only pay attention\n\t// to numlock and caps lock if we are dealing with a key that is affected by them.\n\t//\n\tint\tshift\t\t= (GetKeyState(VK_SHIFT) & 0xFF00) \t\t!= 0;\n\tint\tctrl \t\t= (GetKeyState(VK_CONTROL) & 0xFF00) \t!= 0;\n\tint\talt \t\t= (GetKeyState(VK_MENU) & 0xFF00) \t\t!= 0;\n\tint\tcaps\t\t= ((GetKeyState(VK_CAPITAL) & 0x00FF) \t!= 0) && (ToggleKeys[vk_key] == 1);\n\tint\tnums\t\t= ((GetKeyState(VK_NUMLOCK) & 0x00FF) \t!= 0) && (ToggleKeys[vk_key] == 2);\n\n\t//\n\t// Set the proper bits for whatever the key we got is.\n\t//\n\tif (shift || caps || nums) {\n\t\tbits |= WWKEY_SHIFT_BIT;\n\t}\n\tif (ctrl) {\n\t\tbits |= WWKEY_CTRL_BIT;\n\t}\n\tif (alt) {\n\t\tbits |= WWKEY_ALT_BIT;\n\t}\n\tif (!AsciiRemap[vk_key|bits]) {\n\t\tbits |= WWKEY_VK_BIT;\n\t}\n\tif (release) {\n\t\tbits |= WWKEY_RLS_BIT;\n\t}\n\tif (dbl) {\n\t\tbits |= WWKEY_DBL_BIT;\n\t}\n\t//\n\t// Finally use the put command to enter the key into the keyboard\n\t// system.\n\t//\n\treturn(Put(vk_key|bits));\n}\t\n\nVOID WWKeyboardClass::Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl)\n{\n\tshift = (key & WWKEY_SHIFT_BIT)\t!= 0;\n\tctrl\t= (key & WWKEY_CTRL_BIT)\t!= 0;\n\talt\t= (key & WWKEY_ALT_BIT)\t\t!= 0;\n\trls\t= (key & WWKEY_RLS_BIT)\t\t!= 0;\n\tdbl\t= (key & WWKEY_DBL_BIT)\t\t!= 0;\n\tkey\t= (key & 0xFF);\n\n}\t\n\n#pragma argsused\nvoid WWKeyboardClass::Message_Handler(HWND hwnd, UINT message, UINT wParam, LONG lParam)\n{\n\tswitch (message) {\n\t\tcase WM_SYSKEYDOWN:\n\t\tcase WM_KEYDOWN:\n\t\t\tPut_Key_Message(wParam);\n\t\t\tbreak;\n\n\t\tcase WM_SYSKEYUP:\n\t\tcase WM_KEYUP:\n\t\t\tPut_Key_Message(wParam, TRUE);\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_LBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONUP:\n\t\t\tPut_Key_Message(VK_LBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_LBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_MBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONUP:\n\t\t\tPut_Key_Message(VK_MBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_MBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_RBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONUP:\n\t\t\tPut_Key_Message(VK_RBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_RBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\t}\n}\t\n\n/*********************************************************************************************** \n * WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels             * \n *                                                                                             * \n * INPUT:\t\tnone                                                                            * \n *                                                                                             * \n * OUTPUT:     int\t\t- returns the mouses current x position in pixels                      * \n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/17/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nint WWKeyboardClass::Get_Mouse_X(void)\n{\n\tPOINT \tpt;\n\tGetCursorPos(&pt);\n\treturn(pt.x);\n}\t\nvoid WWKeyboardClass::Clear(void)\n{\n\tHead = Tail;\n}\n\n\n/*********************************************************************************************** \n * WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels             * \n *                                                                                             * \n * INPUT:\t\tnone                                                                            * \n *                                                                                             * \n * OUTPUT:     int\t\t- returns the mouses current y position in pixels                      * \n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/17/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nint WWKeyboardClass::Get_Mouse_Y(void)\n{\n\tPOINT \tpt;\n\tGetCursorPos(&pt);\n\treturn(pt.y);\n}\t\n\n/*********************************************************************************************** \n * WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars         * \n *                                                                                             * \n * INPUT:\t\tint &x\t\t- variable to return the mouses x position in pixels                *\n *\t\t\t\t\tint &y\t\t- variable to return the mouses y position in pixels\t\t\t\t\t  *\n *                                                                                             * \n * OUTPUT:     none - output is via reference variables                                        *\n *                                                                                             * \n * HISTORY:                                                                                    * \n *   10/17/1995 PWG : Created.                                                                 * \n *=============================================================================================*/\nvoid WWKeyboardClass::Get_Mouse_XY(int &x, int &y)\n{\n\tPOINT \tpt;\n\n\tGetCursorPos(&pt);\n\tx = pt.x;\n\ty = pt.y;\n}\t"
  },
  {
    "path": "WIN32LIB/KEYBOARD/TEST/KEYBOARD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*********************************************************************************************** \n *                                                                                             * \n *                 Project Name : Westwood Keyboard Library                                    * \n *                                                                                             * \n *                    File Name : KEYBOARD.H                                                   * \n *                                                                                             * \n *                   Programmer : Philip W. Gorrow                                             * \n *                                                                                             * \n *                   Start Date : 10/16/95                                                     * \n *                                                                                             * \n *                  Last Update : October 16, 1995 [PWG]                                       * \n *                                                                                             * \n *---------------------------------------------------------------------------------------------* \n * Functions:                                                                                  * \n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include <WWSTD.H>\n\ntypedef enum {\n\tWWKEY_SHIFT_BIT\t= 0x100,\n\tWWKEY_CTRL_BIT\t\t= 0x200,\n\tWWKEY_ALT_BIT\t\t= 0x400,\n\tWWKEY_VK_BIT\t\t= 0x800,\t\n\tWWKEY_RLS_BIT\t\t= 0x1000,\t\n\tWWKEY_DBL_BIT\t\t= 0x2000,\t\n\tWWKEY_BTN_BIT\t\t= 0x4000,\t\n} WWKey_Type;\n\n#define\tVK_NONE\t\t\t\t  0x00\n#define\tVK_LBUTTON          0x01\n#define\tVK_RBUTTON          0x02\n#define\tVK_CANCEL           0x03\n#define\tVK_MBUTTON          0x04\n#define\tVK_NONE_05\t\t\t  0x05\n#define\tVK_NONE_06\t\t\t  0x06\n#define\tVK_NONE_07\t\t\t  0x07\n#define\tVK_BACK             0x08\n#define\tVK_TAB              0x09\n#define\tVK_NONE_0A\t\t\t  0x0A\n#define\tVK_NONE_0B\t\t\t  0x0B\n#define\tVK_CLEAR            0x0C\n#define\tVK_RETURN           0x0D\n#define\tVK_NONE_0E\t\t\t  0x0E\n#define\tVK_NONE_0F\t\t\t  0x0F\n#define\tVK_SHIFT            0x10\n#define\tVK_CONTROL          0x11\n#define\tVK_MENU             0x12\n#define\tVK_PAUSE            0x13\n#define\tVK_CAPITAL          0x14\n#define\tVK_NONE_15\t\t\t  0x15\n#define\tVK_NONE_16\t\t\t  0x16\n#define\tVK_NONE_17\t\t\t  0x17\n#define\tVK_NONE_18\t\t\t  0x18\n#define\tVK_NONE_19\t\t\t  0x19\n#define\tVK_NONE_1A\t\t\t  0x1A\n#define\tVK_ESCAPE           0x1B\n#define\tVK_NONE_1C\t\t\t  0x1C\n#define\tVK_NONE_1D\t\t\t  0x1D\n#define\tVK_NONE_1E\t\t\t  0x1E\n#define\tVK_NONE_1F\t\t\t  0x1F\n#define\tVK_SPACE            0x20\n#define\tVK_PRIOR            0x21\n#define\tVK_NEXT             0x22\n#define\tVK_END              0x23\n#define\tVK_HOME             0x24\n#define\tVK_LEFT             0x25\n#define\tVK_UP               0x26\n#define\tVK_RIGHT            0x27\n#define\tVK_DOWN             0x28\n#define\tVK_SELECT           0x29\n#define\tVK_PRINT            0x2A\n#define\tVK_EXECUTE          0x2B\n#define\tVK_SNAPSHOT         0x2C\n#define\tVK_INSERT           0x2D\n#define\tVK_DELETE           0x2E\n#define\tVK_HELP             0x2F\n#define\tVK_0\t\t\t\t\t  0x30\n#define\tVK_1\t\t\t\t\t  0x31\n#define\tVK_2\t\t\t\t\t  0x32\n#define\tVK_3\t\t\t\t\t  0x33\n#define\tVK_4\t\t\t\t\t  0x34\n#define\tVK_5\t\t\t\t\t  0x35\n#define\tVK_6\t\t\t\t\t  0x36\n#define\tVK_7\t\t\t\t\t  0x37\n#define\tVK_8\t\t\t\t\t  0x38\n#define\tVK_9\t\t\t\t\t  0x39\n#define\tVK_NONE_3B\t\t\t  0x3B\n#define\tVK_NONE_3C\t\t\t  0x3C\n#define\tVK_NONE_3D\t\t\t  0x3D\n#define\tVK_NONE_3E\t\t\t  0x3E\n#define\tVK_NONE_3F\t\t\t  0x3F\n#define\tVK_NONE_40\t\t\t  0x40\n#define\tVK_A\t\t\t\t\t  0x41\n#define\tVK_B\t\t\t\t\t  0x42\n#define\tVK_C\t\t\t\t\t  0x43\n#define\tVK_D\t\t\t\t\t  0x44\n#define\tVK_E\t\t\t\t\t  0x45\n#define\tVK_F\t\t\t\t\t  0x46\n#define\tVK_G\t\t\t\t\t  0x47\n#define\tVK_H\t\t\t\t\t  0x48\n#define\tVK_I\t\t\t\t\t  0x49\n#define\tVK_J\t\t\t\t\t  0x4A\n#define\tVK_K\t\t\t\t\t  0x4B\n#define\tVK_L\t\t\t\t\t  0x4C\n#define\tVK_M\t\t\t\t\t  0x4D\n#define\tVK_N\t\t\t\t\t  0x4E\n#define\tVK_O\t\t\t\t\t  0x4F\n#define\tVK_P\t\t\t\t\t  0x50\n#define\tVK_Q\t\t\t\t\t  0x51\n#define\tVK_R\t\t\t\t\t  0x52\n#define\tVK_S\t\t\t\t\t  0x53\n#define\tVK_T\t\t\t\t\t  0x54\n#define\tVK_U\t\t\t\t\t  0x55\n#define\tVK_V\t\t\t\t\t  0x56\n#define\tVK_W\t\t\t\t\t  0x57\n#define\tVK_X\t\t\t\t\t  0x58\n#define\tVK_Y\t\t\t\t\t  0x59\n#define\tVK_Z\t\t\t\t\t  0x5A\n#define\tVK_NONE_5B\t\t\t  0x5B\n#define\tVK_NONE_5C\t\t\t  0x5C\n#define\tVK_NONE_5D\t\t\t  0x5D\n#define\tVK_NONE_5E\t\t\t  0x5E\n#define\tVK_NONE_5F\t\t\t  0x5F\n#define\tVK_NUMPAD0          0x60\n#define\tVK_NUMPAD1          0x61\n#define\tVK_NUMPAD2          0x62\n#define\tVK_NUMPAD3          0x63\n#define\tVK_NUMPAD4          0x64\n#define\tVK_NUMPAD5          0x65\n#define\tVK_NUMPAD6          0x66\n#define\tVK_NUMPAD7          0x67\n#define\tVK_NUMPAD8          0x68\n#define\tVK_NUMPAD9          0x69\n#define\tVK_MULTIPLY         0x6A\n#define\tVK_ADD              0x6B\n#define\tVK_SEPARATOR        0x6C\n#define\tVK_SUBTRACT         0x6D\n#define\tVK_DECIMAL          0x6E\n#define\tVK_DIVIDE           0x6F\n#define\tVK_F1               0x70\n#define\tVK_F2               0x71\n#define\tVK_F3               0x72\n#define\tVK_F4               0x73\n#define\tVK_F5               0x74\n#define\tVK_F6               0x75\n#define\tVK_F7               0x76\n#define\tVK_F8               0x77\n#define\tVK_F9               0x78\n#define\tVK_F10              0x79\n#define\tVK_F11              0x7A\n#define\tVK_F12              0x7B\n#define\tVK_F13              0x7C\n#define\tVK_F14              0x7D\n#define\tVK_F15              0x7E\n#define\tVK_F16              0x7F\n#define\tVK_F17              0x80\n#define\tVK_F18              0x81\n#define\tVK_F19              0x82\n#define\tVK_F20              0x83\n#define\tVK_F21              0x84\n#define\tVK_F22              0x85\n#define\tVK_F23              0x86\n#define\tVK_F24              0x87\n#define\tVK_NONE_88          0x88\n#define\tVK_NONE_89          0x89\n#define\tVK_NONE_8A          0x8A\n#define\tVK_NONE_8B          0x8B\n#define\tVK_NONE_8C          0x8C\n#define\tVK_NONE_8D          0x8D\n#define\tVK_NONE_8E          0x8E\n#define\tVK_NONE_8F          0x8F\n#define\tVK_NUMLOCK          0x90\n#define\tVK_SCROLL           0x91\n#define\tVK_NONE_92\t\t\t  0x92\n#define\tVK_NONE_93\t\t\t  0x93\n#define\tVK_NONE_94\t\t\t  0x94\n#define\tVK_NONE_95\t\t\t  0x95\n#define\tVK_NONE_96\t\t\t  0x96\n#define\tVK_NONE_97\t\t\t  0x97\n#define\tVK_NONE_98\t\t\t  0x98\n#define\tVK_NONE_99\t\t\t  0x99\n#define\tVK_NONE_9A\t\t\t  0x9A\n#define\tVK_NONE_9B\t\t\t  0x9B\n#define\tVK_NONE_9C\t\t\t  0x9C\n#define\tVK_NONE_9D\t\t\t  0x9D\n#define\tVK_NONE_9E\t\t\t  0x9E\n#define\tVK_NONE_9F\t\t\t  0x9F\n#define\tVK_NONE_A0\t\t\t  0xA0\n#define\tVK_NONE_A1\t\t\t  0xA1\n#define\tVK_NONE_A2\t\t\t  0xA2\n#define\tVK_NONE_A3\t\t\t  0xA3\n#define\tVK_NONE_A4\t\t\t  0xA4\n#define\tVK_NONE_A5\t\t\t  0xA5\n#define\tVK_NONE_A6\t\t\t  0xA6\n#define\tVK_NONE_A7\t\t\t  0xA7\n#define\tVK_NONE_A8\t\t\t  0xA8\n#define\tVK_NONE_A9\t\t\t  0xA9\n#define\tVK_NONE_AA\t\t\t  0xAA\n#define\tVK_NONE_AB\t\t\t  0xAB\n#define\tVK_NONE_AC\t\t\t  0xAC\n#define\tVK_NONE_AD\t\t\t  0xAD\n#define\tVK_NONE_AE\t\t\t  0xAE\n#define\tVK_NONE_AF\t\t\t  0xAF\n#define\tVK_NONE_B0\t\t\t  0xB0\n#define\tVK_NONE_B1\t\t\t  0xB1\n#define\tVK_NONE_B2\t\t\t  0xB2\n#define\tVK_NONE_B3\t\t\t  0xB3\n#define\tVK_NONE_B4\t\t\t  0xB4\n#define\tVK_NONE_B5\t\t\t  0xB5\n#define\tVK_NONE_B6\t\t\t  0xB6\n#define\tVK_NONE_B7\t\t\t  0xB7\n#define\tVK_NONE_B8\t\t\t  0xB8\n#define\tVK_NONE_B9\t\t\t  0xB9\n#define\tVK_NONE_BA\t\t\t  0xBA\n#define\tVK_NONE_BB\t\t\t  0xBB\n#define\tVK_NONE_BC\t\t\t  0xBC\n#define\tVK_NONE_BD\t\t\t  0xBD\n#define\tVK_NONE_BE\t\t\t  0xBE\n#define\tVK_NONE_BF\t\t\t  0xBF\n#define\tVK_NONE_C0\t\t\t  0xC0\n#define\tVK_NONE_C1\t\t\t  0xC1\n#define\tVK_NONE_C2\t\t\t  0xC2\n#define\tVK_NONE_C3\t\t\t  0xC3\n#define\tVK_NONE_C4\t\t\t  0xC4\n#define\tVK_NONE_C5\t\t\t  0xC5\n#define\tVK_NONE_C6\t\t\t  0xC6\n#define\tVK_NONE_C7\t\t\t  0xC7\n#define\tVK_NONE_C8\t\t\t  0xC8\n#define\tVK_NONE_C9\t\t\t  0xC9\n#define\tVK_NONE_CA\t\t\t  0xCA\n#define\tVK_NONE_CB\t\t\t  0xCB\n#define\tVK_NONE_CC\t\t\t  0xCC\n#define\tVK_NONE_CD\t\t\t  0xCD\n#define\tVK_NONE_CE\t\t\t  0xCE\n#define\tVK_NONE_CF\t\t\t  0xCF\n#define\tVK_NONE_D0\t\t\t  0xD0\n#define\tVK_NONE_D1\t\t\t  0xD1\n#define\tVK_NONE_D2\t\t\t  0xD2\n#define\tVK_NONE_D3\t\t\t  0xD3\n#define\tVK_NONE_D4\t\t\t  0xD4\n#define\tVK_NONE_D5\t\t\t  0xD5\n#define\tVK_NONE_D6\t\t\t  0xD6\n#define\tVK_NONE_D7\t\t\t  0xD7\n#define\tVK_NONE_D8\t\t\t  0xD8\n#define\tVK_NONE_D9\t\t\t  0xD9\n#define\tVK_NONE_DA\t\t\t  0xDA\n#define\tVK_NONE_DB\t\t\t  0xDB\n#define\tVK_NONE_DC\t\t\t  0xDC\n#define\tVK_NONE_DD\t\t\t  0xDD\n#define\tVK_NONE_DE\t\t\t  0xDE\n#define\tVK_NONE_DF\t\t\t  0xDF\n#define\tVK_NONE_E0\t\t\t  0xE0\n#define\tVK_NONE_E1\t\t\t  0xE1\n#define\tVK_NONE_E2\t\t\t  0xE2\n#define\tVK_NONE_E3\t\t\t  0xE3\n#define\tVK_NONE_E4\t\t\t  0xE4\n#define\tVK_NONE_E5\t\t\t  0xE5\n#define\tVK_NONE_E6\t\t\t  0xE6\n#define\tVK_NONE_E7\t\t\t  0xE7\n#define\tVK_NONE_E8\t\t\t  0xE8\n#define\tVK_NONE_E9\t\t\t  0xE9\n#define\tVK_NONE_EA\t\t\t  0xEA\n#define\tVK_NONE_EB\t\t\t  0xEB\n#define\tVK_NONE_EC\t\t\t  0xEC\n#define\tVK_NONE_ED\t\t\t  0xED\n#define\tVK_NONE_EE\t\t\t  0xEE\n#define\tVK_NONE_EF\t\t\t  0xEF\n#define\tVK_NONE_F0\t\t\t  0xF0\n#define\tVK_NONE_F1\t\t\t  0xF1\n#define\tVK_NONE_F2\t\t\t  0xF2\n#define\tVK_NONE_F3\t\t\t  0xF3\n#define\tVK_NONE_F4\t\t\t  0xF4\n#define\tVK_NONE_F5\t\t\t  0xF5\n#define\tVK_NONE_F6\t\t\t  0xF6\n#define\tVK_NONE_F7\t\t\t  0xF7\n#define\tVK_NONE_F8\t\t\t  0xF8\n#define\tVK_NONE_F9\t\t\t  0xF9\n#define\tVK_NONE_FA\t\t\t  0xFA\n#define\tVK_NONE_FB\t\t\t  0xFB\n#define\tVK_NONE_FC\t\t\t  0xFC\n#define\tVK_NONE_FD\t\t\t  0xFD\n#define\tVK_NONE_FE\t\t\t  0xFE\n#define\tVK_NONE_FF\t\t\t  0xFF\n\n#define\tVK_UPLEFT\t\t\t  VK_HOME\n#define\tVK_UPRIGHT\t\t\t  VK_PRIOR\t\t\t\n#define\tVK_DOWNLEFT\t\t\t  VK_END\n#define\tVK_DOWNRIGHT\t\t  VK_NEXT\n#define\tVK_ALT\t\t\t\t  VK_MENU\n\ntypedef enum {\n\tKA_CTRL_AT = 0,\n\tKA_CTRL_A,\n\tKA_MORE = KA_CTRL_A,\n\tKA_CTRL_B,\n\tKA_SETBKGDCOL = KA_CTRL_B,\n\tKA_CTRL_C,\n\tKA_CTRL_D,\n\tKA_CTRL_E,\n\tKA_CTRL_F,\n\tKA_SETFORECOL = KA_CTRL_F,\n\tKA_CTRL_G,\n\tKA_CTRL_H,\n\tKA_BACKSPACE = KA_CTRL_H,\n\tKA_CTRL_I,\n\tKA_TAB = KA_CTRL_I,\n\tKA_CTRL_J,\n\tKA_CTRL_K,\n\tKA_CTRL_L,\n\tKA_FORMFEED = KA_CTRL_L,\n\tKA_CTRL_M,\n\tKA_RETURN = KA_CTRL_M,\n\tKA_CTRL_N,\n\n\tKA_CTRL_O,\n\tKA_CTRL_P,\n\tKA_CTRL_Q,\n\tKA_CTRL_R,\n\tKA_CTRL_S,\n\tKA_SPCTAB = KA_CTRL_S,\n\tKA_CTRL_T,\n\tKA_CTRL_U,\n\tKA_CTRL_V,\n\tKA_CTRL_W,\n\tKA_CTRL_X,\n\tKA_SETX = KA_CTRL_X,\n\tKA_CTRL_Y,\n\tKA_SETY = KA_CTRL_Y,\n\tKA_CTRL_Z,\n\tKA_CTRL_LBRACKET,\n\tKA_ESC = KA_CTRL_LBRACKET,\n\tKA_EXTEND = KA_ESC,\n\tKA_CTRL_BACKSLASH,\n\tKA_CTRL_RBRACKET,\n\tKA_LITERAL = KA_CTRL_RBRACKET,\n\tKA_CTRL_CARROT,\n\tKA_CTRL_UNDERLINE,\n\n\tKA_SPACE,\t\t\t\t\t\t\t\t\t/*   */\n\tKA_EXCLAMATION,\t\t\t\t\t\t\t/* ! */\n\tKA_DQUOTE,\t\t\t\t\t\t\t\t\t/* \" */\n\tKA_POUND,\t\t\t\t\t\t\t\t\t/* # */\n\tKA_DOLLAR,\t\t\t\t\t\t\t\t\t/* $ */\n\tKA_PERCENT,\t\t\t\t\t\t\t\t\t/* % */\n\tKA_AMPER,\t\t\t\t\t\t\t\t\t/* & */\n\tKA_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKA_LPAREN,\t\t\t\t\t\t\t\t\t/* ( */\n\tKA_RPAREN,\t\t\t\t\t\t\t\t\t/* ) */\n\tKA_ASTERISK,\t\t\t\t\t\t\t\t/* * */\n\tKA_PLUS,\t\t\t\t\t\t\t\t\t\t/* + */\n\tKA_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKA_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKA_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKA_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKA_0, KA_1, KA_2, KA_3, KA_4, KA_5, KA_6, KA_7, KA_8, KA_9,\n\tKA_COLON,\t\t\t\t\t\t\t\t\t/* : */\n\tKA_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKA_LESS_THAN,\t\t\t\t\t\t\t\t/* < */\n\tKA_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\tKA_GREATER_THAN,\t\t\t\t\t\t\t/* > */\n\tKA_QUESTION,\t\t\t\t\t\t\t\t/* ? */\n\n\tKA_AT,\t\t\t\t\t\t\t\t\t\t/* @ */\n\tKA_A,\t\t\t\t\t\t\t\t\t\t\t/* A */\n\tKA_B,\t\t\t\t\t\t\t\t\t\t\t/* B */\n\tKA_C,\t\t\t\t\t\t\t\t\t\t\t/* C */\n\tKA_D,\t\t\t\t\t\t\t\t\t\t\t/* D */\n\tKA_E,\t\t\t\t\t\t\t\t\t\t\t/* E */\n\tKA_F,\t\t\t\t\t\t\t\t\t\t\t/* F */\n\tKA_G,\t\t\t\t\t\t\t\t\t\t\t/* G */\n\tKA_H,\t\t\t\t\t\t\t\t\t\t\t/* H */\n\tKA_I,\t\t\t\t\t\t\t\t\t\t\t/* I */\n\tKA_J,\t\t\t\t\t\t\t\t\t\t\t/* J */\n\tKA_K,\t\t\t\t\t\t\t\t\t\t\t/* K */\n\tKA_L,\t\t\t\t\t\t\t\t\t\t\t/* L */\n\tKA_M,\t\t\t\t\t\t\t\t\t\t\t/* M */\n\tKA_N,\t\t\t\t\t\t\t\t\t\t\t/* N */\n\tKA_O,\t\t\t\t\t\t\t\t\t\t\t/* O */\n\n\tKA_P,\t\t\t\t\t\t\t\t\t\t\t/* P */\n\tKA_Q,\t\t\t\t\t\t\t\t\t\t\t/* Q */\n\tKA_R,\t\t\t\t\t\t\t\t\t\t\t/* R */\n\tKA_S,\t\t\t\t\t\t\t\t\t\t\t/* S */\n\tKA_T,\t\t\t\t\t\t\t\t\t\t\t/* T */\n\tKA_U,\t\t\t\t\t\t\t\t\t\t\t/* U */\n\tKA_V,\t\t\t\t\t\t\t\t\t\t\t/* V */\n\tKA_W,\t\t\t\t\t\t\t\t\t\t\t/* W */\n\tKA_X,\t\t\t\t\t\t\t\t\t\t\t/* X */\n\tKA_Y,\t\t\t\t\t\t\t\t\t\t\t/* Y */\n\tKA_Z,\t\t\t\t\t\t\t\t\t\t\t/* Z */\n\tKA_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKA_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\tKA_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKA_CARROT,\t\t\t\t\t\t\t\t\t/* ^ */\n\tKA_UNDERLINE,\t\t\t\t\t\t\t\t/* _ */\n\n\tKA_GRAVE,\t\t\t\t\t\t\t\t\t/* ` */\n\tKA_a,\t\t\t\t\t\t\t\t\t\t\t/* a */\n\tKA_b,\t\t\t\t\t\t\t\t\t\t\t/* b */\n\tKA_c,\t\t\t\t\t\t\t\t\t\t\t/* c */\n\tKA_d,\t\t\t\t\t\t\t\t\t\t\t/* d */\n\tKA_e,\t\t\t\t\t\t\t\t\t\t\t/* e */\n\tKA_f,\t\t\t\t\t\t\t\t\t\t\t/* f */\n\tKA_g,\t\t\t\t\t\t\t\t\t\t\t/* g */\n\tKA_h,\t\t\t\t\t\t\t\t\t\t\t/* h */\n\tKA_i,\t\t\t\t\t\t\t\t\t\t\t/* i */\n\tKA_j,\t\t\t\t\t\t\t\t\t\t\t/* j */\n\tKA_k,\t\t\t\t\t\t\t\t\t\t\t/* k */\n\tKA_l,\t\t\t\t\t\t\t\t\t\t\t/* l */\n\tKA_m,\t\t\t\t\t\t\t\t\t\t\t/* m */\n\tKA_n,\t\t\t\t\t\t\t\t\t\t\t/* n */\n\tKA_o,\t\t\t\t\t\t\t\t\t\t\t/* o */\n\n\tKA_p,\t\t\t\t\t\t\t\t\t\t\t/* p */\n\tKA_q,\t\t\t\t\t\t\t\t\t\t\t/* q */\n\tKA_r,\t\t\t\t\t\t\t\t\t\t\t/* r */\n\tKA_s,\t\t\t\t\t\t\t\t\t\t\t/* s */\n\tKA_t,\t\t\t\t\t\t\t\t\t\t\t/* t */\n\tKA_u,\t\t\t\t\t\t\t\t\t\t\t/* u */\n\tKA_v,\t\t\t\t\t\t\t\t\t\t\t/* v */\n\tKA_w,\t\t\t\t\t\t\t\t\t\t\t/* w */\n\tKA_x,\t\t\t\t\t\t\t\t\t\t\t/* x */\n\tKA_y,\t\t\t\t\t\t\t\t\t\t\t/* y */\n\tKA_z,\t\t\t\t\t\t\t\t\t\t\t/* z */\n\tKA_LBRACE,\t\t\t\t\t\t\t\t\t/* { */\n\tKA_BAR,\t\t\t\t\t\t\t\t\t\t/* | */\n\tKA_RBRACE,\t\t\t\t\t\t\t\t\t/* ] */\n\tKA_TILDA,\t\t\t\t\t\t\t\t\t/* ~ */\n\tKA_DEL,\t\t\t\t\t\t\t\t\t\t/* not used */\n\n\tKA_ALT_F10 = 143,\n\tKA_ALT_F9,    KA_ALT_F8,   KA_ALT_F7,   KA_ALT_F6,   KA_ALT_F5,\n\tKA_ALT_F4,    KA_ALT_F3,   KA_ALT_F2,   KA_ALT_F1,\n\n\tKA_CTRL_F10,  KA_CTRL_F9,  KA_CTRL_F8,  KA_CTRL_F7,  KA_CTRL_F6,\n\tKA_CTRL_F5,   KA_CTRL_F4,  KA_CTRL_F3,  KA_CTRL_F2,  KA_CTRL_F1,\n\n\tKA_SHIFT_F10, KA_SHIFT_F9, KA_SHIFT_F8, KA_SHIFT_F7, KA_SHIFT_F6,\n\tKA_SHIFT_F5,  KA_SHIFT_F4, KA_SHIFT_F3, KA_SHIFT_F2, KA_SHIFT_F1,\n\n\tKA_DELETE,\t\t\t\t\t\t\t\t\t/* <DELETE> */\n\tKA_INSERT,\t\t\t\t\t\t\t\t\t/* <INSERT> */\n\tKA_PGDN,\t\t\t\t\t\t\t\t\t\t/* <PAGE DOWN> */\n\tKA_DOWNRIGHT = KA_PGDN,\n\tKA_DOWN,\t\t\t\t\t\t\t\t\t\t/* <DOWN ARROW> */\n\tKA_END,\t\t\t\t\t\t\t\t\t\t/* <END> */\n\tKA_DOWNLEFT = KA_END,\n\n\tKA_RESERVED1,\n\n\tKA_RIGHT,\t\t\t\t\t\t\t\t\t/* <RIGHT ARROW> */\n\tKA_KEYPAD5,\t\t\t\t\t\t\t\t\t/* NUMERIC KEY PAD <5> */\n\tKA_LEFT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ARROW> */\n\n\tKA_RESERVED2,\n\n\tKA_PGUP,\t\t\t\t\t\t\t\t\t\t/* <PAGE UP> */\n\tKA_UPRIGHT = KA_PGUP,\n\tKA_UP,\t\t\t\t\t\t\t\t\t\t/* <UP ARROW> */\n\tKA_HOME,\t\t\t\t\t\t\t\t\t\t/* <HOME> */\n\tKA_UPLEFT = KA_HOME,\n\t\n\tKA_RESERVED3,\n\tKA_RESERVED4,\n\n\tKA_F10, KA_F9, KA_F8, KA_F7, KA_F6, KA_F5, KA_F4, KA_F3, KA_F2, KA_F1,\n\n\tKA_LMOUSE,\n\tKA_RMOUSE,\n\tKA_JBUTTON1,\n\tKA_JBUTTON2,\n\tKA_J_UP,\n\tKA_J_RIGHT,\n\tKA_J_DOWN,\n\tKA_J_LEFT,\n\n\tKA_SHIFT_BIT = 0x0100,\n\tKA_CTRL_BIT  = 0x0200,\n\tKA_ALT_BIT   = 0x0400,\n\tKA_RLSE_BIT  = 0x0800,\n\tKA_LCOMM_BIT = 0x1000,\t\t\t\t\t/* Amiga Left Comm key\t*/\n\tKA_RCOMM_BIT = 0x2000\t\t\t\t\t/* Amiga Right Comm key\t*/\n} KA_Type;\n\n\n\nclass WWKeyboardClass \n{\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tWWKeyboardClass();\n//\t\t~WWKeyboardClass();\n\n\t\t/*===================================================================*/\n\t\t/* Define the functions which work with the Keyboard Class\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBOOL \tCheck(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for meta key\n\t\tint \tGet(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// gets a meta key from the keybuffer\n\t\tBOOL \tPut(int key);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// dumps a key into the keybuffer\n\t\tBOOL\tPut_Key_Message(\tUINT vk_key, BOOL release = FALSE, \t\t// handles keyboard related message\n\t\t\t\t\t\t\t\t\t\tBOOL dbl = FALSE);\t\t\t\t\t\t\t//   and mouse clicks and dbl clicks\n\t\tint \tCheck_Num(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for a keynum key\n\t\tint \tGet_Num(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// gets keynum key from key buff\n\t\tint \tCheck_ACII(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for an ascii key\n\t\tint \tGet_ASCII(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// gets an ascii key from keybuff\n\t\tint \tCheck_Bits(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// checks keybuff for key w/ bits\n\t\tint \tGet_Bits(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t// get key from keybuff w/ bits\n\t\tint \tTo_ASCII(int num);\t\t\t\t\t\t\t\t\t\t\t\t\t// converts keynum to ascii value\n\t\tint \tOption_On(int option);\t\t\t\t\t\t\t\t\t\t\t\t// turns specified option on\n\t\tint \tOption_Off(int option);\t\t\t\t\t\t\t\t\t\t\t\t// turns specified option off\n\t\tvoid \tClear(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// clears all keys from keybuffer\n\t\tint \tDown(int key);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// tests to see if a key is down\n\t\tvoid\tAI(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// messaging logic for key manager\n\n\t\t/*===================================================================*/\n\t\t/* Define the main hook for the message processing loop.\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tvoid Message_Handler(HWND hwnd, UINT message, UINT wParam, LONG lParam);\n\n\t\t/*===================================================================*/\n\t\t/* Define public routines which can be used on keys in general.\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl);\n\t\tBOOL Is_Mouse_Key(int key);\n\n\t\t/*===================================================================*/\n\t\t/* Routines to sneak through and get the mouses position.\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tint\tGet_Mouse_X(void);\n\t\tint\tGet_Mouse_Y(void);\n\t\tvoid\tGet_Mouse_XY(int &x, int &y);\n\n\t\t/*===================================================================*/\n\t\t/* Define the public access variables which are used with the\t\t\t*/\n\t\t/*   Keyboard Class.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tint\t\t\t\tMouseQX;\t\t\t\t  \n\t\tint\t\t\t\tMouseQY;\n\n\tprivate:\n\t\t/*===================================================================*/\n\t\t/* Define the private access functions which are used by keyboard\t\t*/\n\t\t/*===================================================================*/\n\t\tint  Buff_Get(void);\n\n\n\t\t/*===================================================================*/\n\t\t/* Define the private access variables which are used with the\t\t\t*/\n\t\t/*   Keyboard Class.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tunsigned char\tAsciiRemap[2048];\t// remap for shft/ctrl/alt key combos\n\t\tunsigned char\tVKRemap[256];\t\t// gives vk for any ascii char\n\t\tunsigned short Buffer[256];\t\t// buffer which holds actual keypresses\n\t\tunsigned char  ToggleKeys[256];\t// determines toggles which affect key\n\t\tlong\t\t\t\tHead;\t\t\t\t\t// the head position in keyboard buffer\n\t\tlong\t\t\t\tTail;\t\t\t\t\t// the tail position in keyboard buffer\n};\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/TEST/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .EXE makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 20, 1995  \t                   \t\t*\n#*                                                                         *\n#*                  Last Update : \t\t\t                   \t\t\t\t\t*\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the executable program you're building \t   \t\t*\n#* PROJ_LIBS\t= Westwood libraries to link your EXE to \t           \t\t\t*\n#* OBJECTS\t= list of objects in your current working directory\t   \t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t= full pathname of your working directory\t\t   \t\t\t\t\t*\n#* .xxx:\t= full pathname where various file types live\t\t   \t\t\t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n#---------------------------------------------------------------------------\n# PROJ_NAME = library name\n# PROJ_DIR = directory containing source & objects\n#---------------------------------------------------------------------------\nPROJ_NAME\t= TEST\nPROJ_DIR\t\t= $(%WIN32LIB)\\keyboard\\TEST\nLIB_DIR\t\t= $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t   \t&\n\t$(PROJ_NAME).obj\t&\n\ttestasm.obj\n\nCPS_FILES = \t\t\t&\n\ttest1.cps\t\t&\n\ttest2.cps\n\n\nPROJ_LIBS = \t\t\t&\n\t    keyboard.lib\t&\n\t    win32lib.lib\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t $(PROJ_DIR)\n.c:   \t $(PROJ_DIR)\n.cpp:\t $(PROJ_DIR)\n.h:   \t $(PROJ_DIR)\n.obj:\t $(PROJ_DIR)\n.lib:\t $(%WIN32LIB)\\lib\n.exe:\t $(PROJ_DIR)\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n# If LIB & INCLUDE are already defined, they are used in addition to the\n# WWLIB32 lib & include; otherwise, they're constructed from\n# BCDIR\n#---------------------------------------------------------------------------\n\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB386\\NT\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(PROJ_NAME).exe\n\n#---------------------------------------------------------------------------\n# Build the EXE\n#---------------------------------------------------------------------------\n$(PROJ_NAME).exe: $(OBJECTS)  $(PROJ_NAME).lnk $(PROJ_LIBS) $(CPS_FILES)\n\t $(LINK_CMD) $(LINK_CFG) name $^@ @$(PROJ_NAME).lnk\n\n\n$(PROJ_LIBS):\n\techo updating base library $^@\n\tcd ..\n\twmake\n\tcd $(PROJ_DIR)\n\n\n$(PROJ_NAME).lnk : $(OBJECTS)\n       %create $^@\n       for %index in ($(OBJECTS))  do %append $^@ file %index\n       for %index in ($(PROJ_LIBS)) do %append $^@ library $(LIB_DIR)\\%index\n\t\t %append $^@ library $(LIB_DIR)\\ddraw.lib\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/TEST/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .EXE makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 20, 1995  \t                   \t\t*\n#*                                                                         *\n#*                  Last Update : \t\t\t                   \t\t\t\t\t*\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the executable program you're building \t   \t\t*\n#* PROJ_LIBS\t= Westwood libraries to link your EXE to \t           \t\t\t*\n#* OBJECTS\t= list of objects in your current working directory\t   \t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t= full pathname of your working directory\t\t   \t\t\t\t\t*\n#* .xxx:\t= full pathname where various file types live\t\t   \t\t\t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n#---------------------------------------------------------------------------\n# PROJ_NAME = library name\n# PROJ_DIR = directory containing source & objects\n#---------------------------------------------------------------------------\nPROJ_NAME   = test\nPROJ_DIR    = $(WIN32LIB)\\drawbuff\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS =  \t\\\n\t\t\t\t$(PROJ_NAME).obj\n\nCPS_FILES = \\\n\t\t\t\ttest1.cps\t\t\\\n\t\t\t\ttest2.cps\n!if 0\nPROJ_LIBS =\t\\\n\t\t\t   drawbuff.lib\t\\\n\t\t\t   win32lib.lib\n!else\nPROJ_LIBS =\t\\\n\t\t\t   drawbuff.lib\t\\\n\t\t\t\tmem.lib\t\t\t\\\n\t\t\t\tmisc.lib\t\t\t\\\n\t\t\t\tiff.lib\t\t\t\\\n\t\t\t\trawfile.lib\t\t\\\n\t\t\t\ttile.lib\t\t\t\\\n\t\t\t\tfont.lib\t\t\t\n!endif\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n# If LIB & INCLUDE are already defined, they are used in addition to the\n# WWLIB32 lib & include; otherwise, they're constructed from\n# BCDIR \n#---------------------------------------------------------------------------\n\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n.lbm.cps:\n\t$(WIN32LIB)\\\\TOOLS\\WWCOMP $*.lbm $*.cps\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(PROJ_NAME).exe $(CPS_FILES)\n\n#---------------------------------------------------------------------------\n# Build the EXE\n#---------------------------------------------------------------------------\n$(PROJ_NAME).exe: $(OBJECTS) $(PROJ_LIBS) \n\t $(LINK_CMD) @&&|\n$(LINK_CFG) +\n$(COMPILER)\\\\LIB\\\\c0w32.obj+\n$(OBJECTS)\n$<,$*\n$(PROJ_LIBS) +\nimport32.lib +\ncw32i.lib\n$*.def\n|\n\n$(PROJ_LIBS):\t\t\n\techo updating base library $^@\n\tcd ..\n\tmake\n\tcd $(PROJ_DIR)\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/TEST/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .EXE makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 20, 1995  \t                   \t\t*\n#*                                                                         *\n#*                  Last Update : \t\t\t                   \t\t\t\t\t*\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the executable program you're building \t   \t\t*\n#* PROJ_LIBS\t= Westwood libraries to link your EXE to \t           \t\t\t*\n#* OBJECTS\t= list of objects in your current working directory\t   \t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t= full pathname of your working directory\t\t   \t\t\t\t\t*\n#* .xxx:\t= full pathname where various file types live\t\t   \t\t\t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n#---------------------------------------------------------------------------\n# PROJ_NAME = library name\n# PROJ_DIR = directory containing source & objects\n#---------------------------------------------------------------------------\nPROJ_NAME\t= TEST\nPROJ_DIR\t\t= $(%WIN32LIB)\\drawbuff\\TEST\nLIB_DIR\t\t= $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t   \t&\n\t$(PROJ_NAME).obj\n\nCPS_FILES = \t\t\t&\n\ttest1.cps\t\t&\n\ttest2.cps\n\nPROJ_LIBS =\t&\n\t\t\t   drawbuff.lib\t&\n\t\t\t\tmem.lib\t\t\t&\n\t\t\t\tmisc.lib\t\t\t&\n\t\t\t\tiff.lib\t\t\t&\n\t\t\t\trawfile.lib\t\t&\n\t\t\t\ttile.lib\t\t\t&\n\t\t\t\tfont.lib\t\t\t\n#PROJ_LIBS = \t\t\t&\n#\t    drawbuff.lib\t&\n#\t    win32lib.lib\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t $(PROJ_DIR)\n.c:   \t $(PROJ_DIR)\n.cpp:\t $(PROJ_DIR)\n.h:   \t $(PROJ_DIR)\n.obj:\t $(PROJ_DIR)\n.lib:\t $(%WIN32LIB)\\lib\n.exe:\t $(PROJ_DIR)\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n# If LIB & INCLUDE are already defined, they are used in addition to the\n# WWLIB32 lib & include; otherwise, they're constructed from\n# BCDIR \n#---------------------------------------------------------------------------\n\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB386\\NT\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(PROJ_NAME).exe \n\n#---------------------------------------------------------------------------\n# Build the EXE\n#---------------------------------------------------------------------------\n$(PROJ_NAME).exe: $(OBJECTS)  $(PROJ_NAME).lnk $(PROJ_LIBS) $(CPS_FILES)\n\t $(LINK_CMD) $(LINK_CFG) name $^@ @$(PROJ_NAME).lnk\n\n\n$(PROJ_LIBS):\t\t\n\techo updating base library $^@\n\tcd ..\n\twmake\n\tcd $(PROJ_DIR)\n\n\n$(PROJ_NAME).lnk : $(OBJECTS)\n       %create $^@\n       for %index in ($(OBJECTS))  do %append $^@ file %index\n       for %index in ($(PROJ_LIBS)) do %append $^@ library $(LIB_DIR)\\%index\n\t\t %append $^@ library $(LIB_DIR)\\ddraw.lib\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/TEST/TEST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***             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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : GraphicBufferClass Test Program                              *\n *                                                                                             *\n *                    File Name : DRAWTEST.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : September 25, 1995                                           *\n *                                                                                             *\n *                  Last Update : September 27, 1995 [ST]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *  WinMain \t\t-- Program entry point                                                     *\n *  WndProc\t\t\t-- Callback procedure for main window                                      *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\n#define WIN32\n#define WIN32_LEAN_AND_MEAN\n#include <wwlib32.h>\n#include\t<direct.h>\n#include \"..\\mouse.h\"\n#define NAME \"KEYBOARD/MOUSE test\"\n#define TITLE \"KEYBOARD/MOUSE library test\"\n\n\n//\n// Misc globals for testing\n//\nBOOL\t\t\tAllDone = FALSE;\t\t\t\t\t// Flag that we should exit\n\n#define\tMODE_WIDTH\t640\t\t\t\t\t\t// Width in pixels of required video mode\n#define\tMODE_HEIGHT\t400\t\t\t\t\t\t// Height in pixels of required video mode\n\nint\t\t\t\tScreenWidth=MODE_WIDTH;\n\n\n\nGraphicBufferClass\t*ScreenBuffer=NULL;\t\t// Global pointer to screen GraphicBufferClass\nGraphicBufferClass   *HidBuffer = NULL;\nGraphicBufferClass\tSysMemPage(320,200);\t\t// page in real memory\nWWMouseClass\t\t\t*Mouse=NULL;\t\t\t\t// Global pointer to mouse information\nWinTimerClass\t\t\t*WindowsTimer=NULL;\nPALETTEENTRY\t\t\tpe[256];\t\t\t\t\t\t// DD Palette entries\nunsigned char\t\t\tPalette[256*3];\t\t\t// Place to load palette to\nextern LPDIRECTDRAWPALETTE\tPalettePtr;\t\t\t// Pointer to direct draw palette object\n\n//\n// Prototypes\n//\nlong FAR PASCAL _export WndProc (HWND, UINT, UINT, LONG) ;\n\n//\n// Externs\n//\nextern\tLPDIRECTDRAW\tDirectDrawObject;\nextern\tHWND\t\t\tMainWindow;\nVOID\t\t*ShapeFile;\nint\t \tCurrentShape;\n\n\n\n/***********************************************************************************************\n * WinMain -- Program entry point                                                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Standard Windows startup parameters                                               *\n *                                                                                             *\n * OUTPUT:   msg.wParam                                                                        *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 1:28PM ST : Created                                                              *\n *=============================================================================================*/\n#pragma off(unreferenced)\nint PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,\n\t\t\t\t\t\t  LPSTR lpszCmdParam, int nCmdShow)\n{\n\tstatic char \tszAppName[] = \"HelloWin\" ;\n\tHWND        \thwnd ;\n\tMSG         \tmsg ;\n\tWNDCLASS    \twndclass ;\n\tchar\t\t\t\tpath_to_exe[132];\n\tchar\t\t\t\tdrive[_MAX_DRIVE];\n\tchar\t\t\t\tpath[_MAX_PATH];\n\tunsigned \t\tdrivecount;\n\tunsigned \t\tolddrive;\n\tchar\t\t\t\toldpath[PATH_MAX];\n\n\t/*\n\t** Get a path to the executable and make sure that we are pointing\n\t** at the location our datafiles are located at.\n\t*/\n\tGetModuleFileName (hInstance, &path_to_exe[0], 132);\n\tgetcwd(oldpath, sizeof(oldpath));\n\t_dos_getdrive(&olddrive);\n\n\n\t_splitpath(path_to_exe, drive, path, NULL, NULL);\n\tif (!drive[0]) {\n\t\tdrive[0] = (char)(('A' + olddrive)-1);\n\t}\n\tif (!path[0]) {\n\t\tstrcpy(path, \".\");\n\t}\n\t_dos_setdrive(toupper((drive[0])-'A')+1, &drivecount);\n\tif (path[strlen(path)-1] == '\\\\') {\n\t\tpath[strlen(path)-1] = '\\0';\n\t}\n\tchdir(path);\n\n\n\t//\n\t// Register the window class\n\t//\n\n\tif (!hPrevInstance)\n\t\t{\n\t\twndclass.style         = CS_HREDRAW | CS_VREDRAW ;\n\t\twndclass.lpfnWndProc   = WndProc ;\n\t\twndclass.cbClsExtra    = 0 ;\n\t\twndclass.cbWndExtra    = 0 ;\n\t\twndclass.hInstance     = hInstance ;\n\t\twndclass.hIcon         = LoadIcon (hInstance, IDI_APPLICATION) ;\n\t\twndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;\n\t\twndclass.hbrBackground = NULL;\n\t\twndclass.lpszMenuName  = NULL;\n\t\twndclass.lpszClassName = NAME;\n\n\t\tRegisterClass (&wndclass) ;\n\t}\n\n\n\t//\n\t// Create our main window\n\t//\n\thwnd = CreateWindowEx (\n\t\t\t\t\t\t\tWS_EX_TOPMOST,\n\t\t\t\t\t\t\tNAME,\n\t\t\t\t\t\t\tTITLE,\n\t\t\t\t\t\t\tWS_POPUP | WS_MAXIMIZE,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tMODE_WIDTH,\n\t\t\t\t\t\t\tMODE_HEIGHT,\n\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\thInstance,\n\t\t\t\t\t\t\tNULL );\n\n\tShowWindow (hwnd, nCmdShow) ;\n\tUpdateWindow (hwnd) ;\n\tSetFocus (hwnd);\n\tMainWindow=hwnd;\t\t\t//Save the handle to our main window\n\t\t\t\t\t\t\t\t// (Dangerous  if Windoze can change the handle)\n\n\n\n\n\n\t// Set the video mode\n\tSet_Video_Mode( MainWindow , MODE_WIDTH , MODE_HEIGHT , 8 );\n\tSet_Shape_Buffer(new unsigned char[5000], 5000);\n\t//\n\t// Create the GraphicBufferClass that will be the screen buffer\n\t//\n\tScreenBuffer = new GraphicBufferClass ( MODE_WIDTH , MODE_HEIGHT , (GBC_Enum)(GBC_VIDEOMEM | GBC_VISIBLE));\n\tHidBuffer = new GraphicBufferClass ( MODE_WIDTH , MODE_HEIGHT , (GBC_Enum)(GBC_VIDEOMEM));\n\tShowCursor (FALSE);\n\tMouse = new WWMouseClass(ScreenBuffer,32,32);\n\n\t//\n\t// Load up the picture and display it on the scene page\n\t//\n\n\tLoad_Picture(\"TITLE.CPS\", SysMemPage, SysMemPage, Palette, BM_DEFAULT);\n\tFontPtr = Load_Font(\"font.fnt\");\n\n\tShapeFile = Load_Alloc_Data(\"MOUSE.SHP\", MEM_NORMAL);\n\tCurrentShape = 0;\n\tMouse->Set_Cursor(0,0,Extract_Shape(ShapeFile,CurrentShape));\n\tSet_Palette(Palette);\n\tSysMemPage.Scale(*HidBuffer);\n\tMouse->Show_Mouse();\n\tWindowsTimer = new WinTimerClass(60,FALSE);\n\n\t//\n\t// Get rid of the windows cursor\n\t//\n\n\tAllDone = FALSE;\n\n\t//\n\t// Windows message loop\n\t//\n\tint count = 0;\n\tchar temp[100];\n\tCountDownTimerClass timer(BT_SYSTEM, 0);\n\ttimer.Set(60);\n\ttimer.Start();\n\twhile ( ! AllDone ){\n\t\tif (timer.Time() == 0) {\n\t\t\tsprintf(temp,\"%d frames per second\",count);\n\t\t\tMouse->Erase_Mouse(HidBuffer, TRUE);\n\t\t\tHidBuffer->Print(temp,0,0,255,1);\n\t\t\tcount = 0;\n\t\t\ttimer.Set(60);\n\t\t\ttimer.Start();\n\t\t} else {\n\t\t\tcount++;\n\t\t\tMouse->Erase_Mouse(HidBuffer, TRUE);\n\t\t}\n\t\tMouse->Draw_Mouse(HidBuffer);\n\t\tHidBuffer->Blit(*ScreenBuffer);\n\t\tMouse->Erase_Mouse(HidBuffer, FALSE);\n\n\t\tif( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ){\n\t\t\tif( !GetMessage( &msg, NULL, 0, 0 ) ){\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tTranslateMessage(&msg);\n\t\t\tDispatchMessage(&msg);\n\t\t}\n\n\t}\n\tdelete Mouse;\n\treturn msg.wParam;\n}\n\n#pragma on(unreferenced)\n\n\n\n/***********************************************************************************************\n * WndProc -- windows message callback                                                         *\n *                                                                                             *\n *   Pilfered from a windows example program - HELLOWIN.C                                      *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Standard Windoze callback parameters                                              *\n *                                                                                             *\n * OUTPUT:   long                                                                              *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/27/95 1:39PM ST : Pilfered                                                             *\n *=============================================================================================*/\n\nlong FAR PASCAL _export WndProc (HWND hwnd, UINT message, UINT wParam,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  LONG lParam)\n {\n\tstatic int condhide = 0;\n\tswitch (message){\n\n\n//\t\tcase WM_MOUSEMOVE:\n//\t\t\tif (Mouse)\n//\t\t\t\tMouse->Process_Mouse();\n//\t\t\tbreak;\n\n\t\tcase WM_LBUTTONDOWN:\n\t\t\tif (Mouse) \t\t\t{\n\t\t\t\tMouse->Set_Cursor(0,0,Extract_Shape(ShapeFile,++CurrentShape));\n\t\t\t\tif (CurrentShape>160) CurrentShape = 0;\n\t\t\t}\n\t\t\t\t\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONDOWN:\n\t\t\tif (condhide) \t{\n\t\t\t\tMouse->Show_Mouse();\n\t\t\t\tMouse->Conditional_Show_Mouse();\n\t\t\t\tMouse->Conditional_Show_Mouse();\n\t\t\t\tcondhide = FALSE;\n\t\t\t} else {\n\t\t\t\tMouse->Hide_Mouse();\n\t\t\t\tMouse->Conditional_Hide_Mouse(0,0,320,200);\n\t\t\t\tMouse->Conditional_Hide_Mouse(0,0,320,200);\n\t\t\t\tcondhide = TRUE;\n\t\t\t}\n\t\t\tbreak;\n\n\n\t\tcase WM_ACTIVATEAPP:\n\t\t\tif ((BOOL)wParam) {\n\t\t\t\tif (ScreenBuffer) {\n\t\t\t\t\tScreenBuffer->Get_DD_Surface()->Restore();\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WM_DESTROY:\n\t\t\t//\n\t\t\t// Tidy up\n\t\t\t//\n\n\t\t\tdelete ScreenBuffer;\n\t\t\tdelete Mouse;\n\n\t\t\tif ( DirectDrawObject ){\n\t\t\t\tReset_Video_Mode();\n\t\t\t}\n\n\t\t\tAllDone = TRUE;\n\t\t\tPostQuitMessage (0) ;\n\t\t\treturn(0);\n\t}\n\n\treturn DefWindowProc (hwnd, message, wParam, lParam) ;\n}\n\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/TEST/TEST.DEF",
    "content": "IMPORTS\n\tDirectDrawCreate=DDRAW.DirectDrawCreate\n\tDirectSoundCreate=DSOUND.DirectSoundCreate\n\tDirectPlayEnumerate=DPLAY.DirectPlayEnumerate\n\tDirectPlayCreate=DPLAY.DirectPlayCreate\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/TEST/TESTASM.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\nIDEAL\nP386\nMODEL USE32 FLAT\njumps\n\n\tcodeseg\n\n\tmasm\n;\n; Change a DAC colour register directly\n;\n; register number in al\n;\n; bh=red bl=green cl=blue\n;\n\nset_dac_col proc near\n\t\tpushad\n\t\tcli\n\t\tpush\teax\n\t\tmov\tdx,03dah\n\t\tin\tal,dx\n\t\tjmp\t@@1\n@@1:\t\tmov\tdx,03c8h\n\t\tpop\teax\n\t\tout\tdx,al\n\t\tjmp\t@@2\n@@2:\t\tinc\tdl\n\t\tmov\tal,bh\n\t\tout\tdx,al\n\t\tjmp\t@@3\n@@3:\t\tmov\tal,bl\n\t\tout\tdx,al\n\t\tjmp\t@@4\n@@4:\t\tmov\tal,cl\n\t\tout\tdx,al\n\t\tjmp\t@@5\n@@5:\t\tsti\n\t\tpopad\n\t\tret\nset_dac_col endp\n\n\tideal\n\n\nglobal\tSet_Palette_Register_:near\n\n\nproc Set_Palette_Register_ near\n\n\t\tpushad\n\t\tand\tcl,63\n\t\tmov\tbh,dl\n\t\tand\tbh,63\n\t\tand\tbl,63\n\t\tcall\tset_dac_col\n\t\tpopad\n\t\tret\n\nendp Set_Palette_Register_\n\nend\n"
  },
  {
    "path": "WIN32LIB/KEYBOARD/WWMOUSE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : BITBLIT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Philip W. Gorrow\t\t\t   *\n;*                                                                         *\n;*                   Start Date : December 12, 1995                        *\n;*                                                                         *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \"drawbuff.inc\"\nINCLUDE \"gbuffer.inc\"\nINCLUDE \"shape.inc\"\nINCLUDE \".\\mouse.inc\"\n\nGLOBAL\tC LCW_Uncompress:NEAR\nGLOBAL\tC Get_Shape_Uncomp_Size     :NEAR\nGLOBAL\tC Get_Shape_Width      \t  :NEAR\nGLOBAL\tC Get_Shape_Original_Height :NEAR\nGLOBAL\t_ShapeBuffer\t\t  :DWORD\n\nCODESEG\n\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tMouseClass *\t\t- pointer to mouse class data\t   *\n;*\t\tGraphicBufferClass *\t- screen to draw the mouse on\t   *\n;*\t\tint x\t\t\t- x position to store the mouse at *\n;*\t\tint y\t\t\t- y position to store the mouse at *\n;*\t\tint store\t\t- whether to store buffer or save  *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* Note: The x and y that this routine expects to receive are based on\t   *\n;*       the mouse cursor position.  This routine automatically adjusts\t   *\n;*\t for hot spot, so that adjustment should not be made prior to\t   *\n;*\t this point.\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tvoid Mouse_Shadow_Buffer(GraphicBufferClass *src/dest,\t   *\n;*\t\t\t\t\tvoid *buffer\n;*\t\t\t\t\tint x_pixel,\t\t\t   *\n;*\t\t\t\t\tint y_pixel,\t\t\t   *\n;*\t\t\t\t\tint store);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Mouse_Shadow_Buffer:NEAR\n\tPROC\tMouse_Shadow_Buffer C NEAR\n\tUSES\teax,ebx,ecx,edx,edi,esi\n\n\tARG\tthis:\t\tDWORD\n\tARG\tsrc_dst_obj:\tDWORD\n\tARG\tbuffer:DWORD\n\tARG\tx:\t\tDWORD\n\tARG\ty:\t\tDWORD\n\tARG\thotx:\t\tDWORD\n\tARG\thoty:\t\tDWORD\n\tARG\tstore:\t\tDWORD\n\n\tlocal\tx0: \t\tdword\n\tlocal\ty0: \t\tdword\n\tlocal\tx1: \t\tdword\n\tlocal\ty1: \t\tdword\n\tlocal\tbuffx0: \tdword\n\tlocal\tbuffy0: \tdword\n\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tesi, [this]\t\t\t; get offset to mouse data\n\tmov\tedi, [src_dst_obj]\t\t; get offset to mouse data\n\n\tmov\teax, [x]\n\tmov\tebx, [y]\n\tsub\teax, [hotx]\n\tsub\tebx, [hoty]\n\n\tmov\t[x0], eax\n\tmov\t[y0], ebx\n\tadd\teax, [(MouseType esi).CursorWidth]\n\tadd\tebx, [(MouseType esi).CursorHeight]\n\tmov\t[x1], eax\n\tmov\t[y1], ebx\n\n\tmov\t[buffx0], 0\n\tmov\teax, [buffer]\n\tmov\t[buffy0], eax\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\n\txor \teax, eax\n\txor \tedx, edx\n\n\tmov\tecx, [x0]\n\tmov\tebx, [x1]\n\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [x0]\n\tmov\tebx, [x1]\n\tsub\tecx, [(GraphicViewPort edi).GVPWidth]\n\tsub\tebx, [(GraphicViewPort edi).GVPWidth]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [y0]\n\tmov\tebx, [y1]\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [y0]\n\tmov\tebx, [y1]\n\tsub\tecx, [(GraphicViewPort edi).GVPHeight]\n\tsub\tebx, [(GraphicViewPort edi).GVPHeight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\txor\tal, 5\n\txor\tdl, 5\n\tmov\tah, al\n\ttest\tdl, al\n\tjnz\t??out\n\tor\tal, dl\n\tjz\t??not_clip\n\n\ttest\tah, 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx, [x0]\n\tneg\tebx\n\tmov\t[buffx0], ebx\n\tmov\t[x0], 0\n\n??scr_left_ok:\n\ttest\tah, 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx, [y0]\n\tneg\tebx\n\timul\tebx, [(MouseType esi).CursorWidth]\n\tadd\t[buffy0], ebx\n\tmov\t[y0], 0\n\n??scr_bottom_ok:\n\ttest\tdl, 0100b\n\tjz\t??scr_right_ok\n\tmov\teax, [(GraphicViewPort edi).GVPWidth]  ; get width into register\n\tmov\t[x1], eax\n??scr_right_ok:\n\ttest\tdl, 0001b\n\tjz\t??not_clip\n\tmov\teax, [(GraphicViewPort edi).GVPHeight]  ; get width into register\n\tmov\t[y1], eax\n\n??not_clip:\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax, [y0]\n\tmov\tedx, [(GraphicViewPort edi).GVPWidth]\n\tadd\tedx, [(GraphicViewPort edi).GVPXAdd]\n\tadd\tedx, [(GraphicViewPort edi).GVPPitch]\n\timul\teax, edx\n\tadd\teax, [x0]\n\tmov\tedi, [(GraphicViewPort edi).GVPOffset]\n\tadd\tedi, eax\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx, [(MouseType esi).CursorWidth]\t; turn this into an offset\n\tmov\tesi, [buffy0]\t\t\t; edx points to source\n\tadd\tesi, [buffx0]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax, [x1]\n\tmov\tecx, [y1]\n\tsub\teax, [x0]\n\tjle\t??out\n\tsub\tecx, [y0]\n\tjle\t??out\n\n\tsub\tedx, eax\n\tsub\tebx, eax\n\tpush\tebp\n\tcmp\t[store], 1\t\t\t\t\t; are we storing page?\n\tje\t\t??store_entry\t\t\t\t; if so go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tebp, ecx\n??restore_loop:\n\tmov\tecx, eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi, ebx\t\t\t\t; move past right clipped pixels\n\tadd\tedi, edx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tesi, edi\t\t\t\t\t; xchg the source and the dest\n\tmov\tebp, ecx\n\n??store_loop:\n\tmov\tecx, eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi, edx\t\t\t\t; move past right clipped pixels\n\tadd\tedi, ebx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n??out:\n\tret\n\tENDP\tMouse_Shadow_Buffer\n\n;***************************************************************************\n;* DRAW_MOUSE -- Handles drawing the mouse cursor\t\t\t   *\n;*                                                                         *\n;* INPUT:\tMouseClass *\t\t- pointer to mouse class data\t   *\n;*\t\tGraphicBufferClass *\t- screen to draw the mouse on\t   *\n;*\t\tint x\t\t\t- x position to store the mouse at *\n;*\t\tint y\t\t\t- y position to store the mouse at *\n;*                                                                         *\n;* Note: The x and y that this routine expects to receive are based on\t   *\n;*       the mouse cursor position.  This routine automatically adjusts\t   *\n;*\t for hot spot, so that adjustment should not be made prior to\t   *\n;*\t this point.\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* PROTO:       void Draw_Mouse(\tMouseClass * mouse_data,\t   *\n;*\t\t\t\t\tGraphicBufferClass *destination,   *\n;*\t\t\t\t\tint x_pixel,\t\t\t   *\n;* \t\t\t\t\tint y_pixel);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Draw_Mouse:NEAR\n\tPROC\tDraw_Mouse C NEAR\n\tUSES\teax,ebx,ecx,edx,edi,esi\n\n\tARG\tthis:DWORD\n\tARG\tdest:DWORD\n\tARG\tmousex:DWORD\n\tARG\tmousey:DWORD\n\n\tlocal\tx0:dword\n\tlocal\ty0:dword\n\tlocal\tx1:dword\n\tlocal\ty1:dword\n\tlocal\tbuffx0:dword\n\tlocal\tbuffy0:dword\n\n\n\tmov\tesi, [this]    \t; get 32 bit offset to mouse data\n\tmov\tedi, [dest]\t; get 32 bit offset to dest buffer\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax, [mousex]\n\tmov\tebx, [mousey]\n\tsub\teax, [(MouseType esi).MouseXHot]\n\tsub\tebx, [(MouseType esi).MouseYHot]\n\n\tmov\t[x0], eax\n\tmov\t[y0], ebx\n\tadd\teax,[(MouseType esi).CursorWidth]\n\tadd\tebx,[(MouseType esi).CursorHeight]\n\tmov\t[x1], eax\n\tmov\t[y1], ebx\n\n\tmov\t[buffx0], 0\n\tmov\teax, [(MouseType esi).MouseCursor]\n\tmov\t[buffy0], eax\n\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\txor \teax, eax\n\txor \tedx, edx\n\n\tmov\tecx, [x0]\n\tmov\tebx, [x1]\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [x0]\n\tmov\tebx, [x1]\n\tsub\tecx, [(GraphicViewPort edi).GVPWidth]\n\tsub\tebx, [(GraphicViewPort edi).GVPWidth]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [y0]\n\tmov\tebx, [y1]\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [y0]\n\tmov\tebx, [y1]\n\tsub\tecx, [(GraphicViewPort edi).GVPHeight]\n\tsub\tebx, [(GraphicViewPort edi).GVPHeight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\txor\tal, 5\n\txor\tdl, 5\n\tmov\tah, al\n\ttest\tdl, al\n\tjnz\t??out\n\tor\tal, dl\n\tjz\t??not_clip\n\n\ttest\tah, 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx, [x0]\n\tneg\tebx\n\tmov\t[buffx0], ebx\n\tmov\t[x0], 0\n\n??scr_left_ok:\n\ttest\tah, 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx, [y0]\n\tneg\tebx\n\timul\tebx, [(MouseType esi).CursorWidth]\n\tadd\t[buffy0], ebx\n\tmov\t[y0], 0\n\n??scr_bottom_ok:\n\ttest\tdl, 0100b\n\tjz\t??scr_right_ok\n\tmov\teax, [(GraphicViewPort edi).GVPWidth]  ; get width into register\n\tmov\t[x1] , eax\n??scr_right_ok:\n\ttest\tdl, 0001b\n\tjz\t??not_clip\n\tmov\teax, [(GraphicViewPort edi).GVPHeight]  ; get width into register\n\tmov\t[y1] , eax\n\n??not_clip:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax, [y0]\n\tmov\tedx, [(GraphicViewPort edi).GVPWidth]\n\tadd\tedx, [(GraphicViewPort edi).GVPXAdd]\n\tadd\tedx, [(GraphicViewPort edi).GVPPitch]\n\timul\teax, edx\n\tadd\teax, [x0]\n\tmov\tedi, [(GraphicViewPort edi).GVPOffset]\n\tadd\tedi, eax\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx, [(MouseType esi).CursorWidth]\t; turn this into an offset\n\tmov\tesi, [buffy0]\t\t\t; edx points to source\n\tadd\tesi, [buffx0]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax, [x1]\n\tmov\tecx, [y1]\n\tsub\teax, [x0]\n\tjle\t??out\n\tsub\tecx, [y0]\n\tjle\t??out\n\n\tsub\tedx, eax\n\tsub\tebx, eax\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah, al\n??inner_loop:\n\tmov\tch, [esi]\n\tinc\tesi\n\ttest\tch, ch\n\tjz\t??inc_edi\n\tmov\t[edi], ch\n??inc_edi:\n\tinc\tedi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tesi, ebx      \t\t\t; move past right clipped pixels\n\tadd\tedi, edx      \t\t\t; adjust dest to next line\n\tdec\tcl\t      \t\t\t; decrement number of rows to do\n\tjnz\t??top_loop    \t\t\t; if more to do, do it\n??out:\n\tret\n\n\tENDP\tDraw_Mouse\n;***************************************************************************\n;* SET_MOUSE_CURSOR -- Sets the shape to be used as the mouse.             *\n;*                                                                         *\n;*    This will inform the system of the shape desired as the mouse        *\n;*    cursor.                                                              *\n;*                                                                         *\n;* INPUT:    xhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           yhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           cursor      -- Shape to use as the new mouse shape.           *\n;*                                                                         *\n;* OUTPUT:   Returns with a pointer to the original mouse shape.           *\n;*                                                                         *\n;* PROTO:\tVOID  *Set_Mouse_Cursor(\tint  xhotspot, \t\t   *\n;*\t\t\t\t\t\tint  yhotspot, \t\t   *\n;*\t\t\t\t\t\tvoid *cursor);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   02/13/1992 JLB : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC ASM_Set_Mouse_Cursor:NEAR\n\tPROC\tASM_Set_Mouse_Cursor C NEAR\n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\tthis:DWORD\t\t\t\t; pointer to mouse cursor struct\n\tARG\txhotspot:DWORD\t\t\t\t; the x hot spot of the mouse\n\tARG\tyhotspot:DWORD\t\t\t\t; the y hot spot of the mouse\n\tARG\tcursor:DWORD\t\t\t\t; ptr to the new mouse cursor\n\n\tLOCAL\tdatasize:DWORD\n\tLOCAL\tstype:WORD\n\tLOCAL\tswidth:DWORD\t\t; Shape width.\n\tLOCAL\tsheight:DWORD\t\t; Shape height.\n\tLOCAL\tssize:DWORD\t\t; Size of raw shape.\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\tmov\tesi,[this]\t\t\t; get offset of real mode data start\n\n\t;-------------------------------------------------------------------\n\t; Calculate the size of the buffer needed.\n\t;-------------------------------------------------------------------\n\tpush\t[cursor]\n\tcall\tGet_Shape_Uncomp_Size\n\tpop\tedx\n\tmov\t[datasize],eax\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Width\n\tpop\tedx\n\tmov\t[swidth],eax\n\tcmp\teax,[(MouseType esi).MaxWidth]\n\tjg\t??end\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Original_Height\n\tpop\tedx\n\tmov\t[sheight],eax\n\tcmp\teax,[(MouseType esi).MaxHeight]\n\tjg\t??end\n\n\n\tmov\tebx,[sheight]\n\tmov\teax,[swidth]\n\timul\tebx,eax\n\n??copy_mouse:\n\tmov\tedi,[(MouseType esi).MouseCursor]\t\t; set edi to point to mouse buffer\n\tmov\tesi,[cursor]\t\t\t; set esi to point to mouse shape\n\tmov\tax,[esi]\t\t\t; get the shape type byte\n\tmov\t[stype],ax\t\t\t; save off the shape type\n\ttest\tax,MAKESHAPE_NOCOMP\t\t; is it marked as no compression?\n\tje\t??comp_shape\t\t\t; if not go to the comped shape code\n\n??copy_type:\n\n\ttest\t[stype],MAKESHAPE_COMPACT\t; if the shape a 16 color shape?\n\tjne\t??16_color_copy\t\t\t; if it is then go handle it\n\n??normal_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed NORMAL shapes just get run-length uncompressed\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t\t; find size of shape in pixels\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes\n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??norm_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??norm_trans\t\t\t; if its a zero its transparent\n\tmov\t[edi],al\t\t\t; write out the pixel to dest\n\tinc\tedi\t\t\t\t; move to next dest position\n\tdec\tedx\t\t\t\t; we have now written another pix\n\tjnz\t??norm_unrle\t\t\t; if more to write then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are all done\n\n??norm_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\n\tjnz\t??norm_unrle\t\t\t; if more to do then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are done\n\n??16_color_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed 16 color shapes just get remaped and UN-RLE'd\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\tebx,esi\t\t\t\t; save of position of remap\n\tadd\tesi,16\t\t\t\t; move past remap table\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t; load up the height\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes\n\txor\teax,eax\t\t\t\t; clear high of lookup variable\n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??16_color_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??16_color_trans\t\t; if its a zero its transparent\n\tmov\tal,[ebx+eax]\t\t\t; remap the pixel from 16 color table\n\tmov\t[edi],al\t\t\t; store it out to the dest address\n\tinc\tedi\t\t\t\t; move to next dest address\n\tdec\tedx\t\t\t\t; we have now written a pixel\n\tjnz\t??16_color_unrle\n\tjmp\t??done_copy\n??16_color_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\t\t\t\t; subtract off count ahead of time\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\t\t\t\t; or edx to test for zero\n\tjnz\t??16_color_unrle\n\tjmp\t??done_copy\n\n\t;-------------------------------------------------------------------\n\t; Deal with the compressed shape by copying it into the shape\n\t;   staging buffer.\n\t;-------------------------------------------------------------------\n??comp_shape:\n\tmov\tedi,[ShapeBuffer]\t; get a pointer to ShapeBuffer\n\tmov\tax,[esi]\t\t; load in the shape type\n\tadd\tesi,2\t\t\t; increment the shape pointer\n\tor\tax,MAKESHAPE_NOCOMP\t; make the shape as uncompressed\n\tmov\t[stype],ax\t\t; save off the shape type\n\tmov\t[edi],ax\t\t; write out uncompressed shape\n\tadd\tedi,2\n\n\t;-------------------------------------------------------------------\n\t; Process the shape header information and copy it over to the new\n\t;   location.\n\t;-------------------------------------------------------------------\n\tmov\tecx,4 \t\t\t; transfer height, width, org and\n\ttest\teax,MAKESHAPE_COMPACT\t; is it a 16 color shape?\n\tje\t??copy_head\t\t; no - don't worry about it\n\tadd\tecx,8\t\t\t; otherwise adjust ecx for header\n??copy_head:\n\trep\tmovsw\t\t\t; copy the necessary bytes\n\n\tmov \teax,[datasize]\t\t; get uncompressed length\n\tpush\teax\t\t\t; push as third param\n\tpush\tedi\t\t\t; push the destination offset\n\tpush\tesi\t\t\t; push the source offset\n\tcall\tLCW_Uncompress\t\t; do the uncompress\n\tpop\teax\n\tpop\teax\n\tpop\teax\n\tmov\tesi,[this]\n\tmov\tedi,[(MouseType esi).MouseCursor]\t\t; set edi to point to mouse buffer\n\tmov\tesi,[ShapeBuffer]\n\tjmp\t??copy_type\n\n??done_copy:\n\tmov\tesi,[this]\t; get offset of real mode data start\n\n\tmov\teax,[xhotspot]\t\t; get the mouse cursors x hotspot\n\tmov\t[(MouseType esi).MouseXHot],eax\n\tmov\teax,[yhotspot]\t\t; get the mouse cursors y hotspot\n\tmov\t[(MouseType esi).MouseYHot],eax\n\n\tmov\tebx,[sheight]\t\t; get shape height\n\tmov\t[(MouseType esi).CursorHeight],ebx\n\tmov\tebx,[swidth]\n\tmov\t[(MouseType esi).CursorWidth],ebx\n\n\t;-------------------------------------------------------------------\n\t; Final cleanup and exit.\n\t;-------------------------------------------------------------------\n??end:\n\tpush\t[cursor]\n\tpush\t[(MouseType esi).PrevCursor]\n\tpop\teax\n\tpop\t[(MouseType esi).PrevCursor]\n\tret\t\t\t\t; and return back to the world\n\n\tENDP\tASM_Set_Mouse_Cursor\n\nEND\n"
  },
  {
    "path": "WIN32LIB/MAKE.BAT",
    "content": "SET WATCOM=D:\\RADVD\\SOURCE\\CODE\\WATCOM\n..\\CODE\\WMAKE WIN32=1\n"
  },
  {
    "path": "WIN32LIB/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* LIBS\t\t= list of all component libraries\t\t\t   \t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* NOTE: For this makefile to work, each library directory MUST have the   *\n#*\tsame name as its library.\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* \"make install\" installs the library on your drive\t\t\t   \t\t\t\t*\n#* \"make update\" updates all source files in your slice\t\t\t   \t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#*\tTo install or update just one library you may type:\t\t   \t\t\t\t*\n#*\t\t \"make -DLIBS=misc.lib install\"\t\t\t\t   \t\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#***************************************************************************\n\n!ifndef %WIN32LIB\nWIN32LIB=.\n!else\nWIN32LIB=$(%WIN32LIB)\n!endif\n\n!ifndef %WIN32VCS\nWIN32VCS=.\n!else\nWIN32VCS=$(%WIN32VCS)\n!endif\n\n\n#===========================================================================\n# User-defined section: list each library in this macro\n#\tNOTE: These are some order dependencies:\n#\t1. The directory MISC must always be made first.\n#\t2. The directory VIDEO must be made before the SYSTEM directory.\n#===========================================================================\nLIB_NAME = win32lib\nLIB_DIR  = $(WIN32LIB)\\lib\n\n#---------------------------------------------------------------------------\n# LIBS macro: a list of all component libraries\n#\t\"make LIBS=xxxx.lib [target]\" makes/installs/updates only that library\n#---------------------------------------------------------------------------\n\nLIBS = \t\t\t&\n\t\t\t\t\taudio.lib\t\t&\n\t\t\t\t\tdipthong.lib\t&\n\t\t\t\t\tdrawbuff.lib\t&\n\t\t\t\t\tfont.lib    \t&\n\t\t\t\t\tiff.lib\t    \t&\n\t\t\t\t\tkeyboard.lib\t&\n\t\t\t\t\tmem.lib\t    \t&\n\t\t\t\t\tmisc.lib    \t&\n\t\t\t\t\tmono.lib    \t&\n\t\t\t\t\tpalette.lib \t&\n\t\t\t\t\tshape.lib\t\t&\n\t\t\t\t\ttile.lib \t\t&\n\t\t\t\t\ttimer.lib \t\t&\n\t\t\t\t\tww_win.lib \t\t&\n\t\t\t\t\twsa.lib\t  \t\t&\n\t\t\t\t\tprofile.lib    &\n\t\t\t\t\tplaycd.lib\t&\n\t\t\t\t\twincomm.lib\n\nLIB_INSTALL =\t&\n\t\t\t\t\taudio.ins\t\t&\n\t\t\t\t\tdipthong.ins\t&\n\t\t\t\t\tdrawbuff.ins\t&\n\t\t\t\t\tfont.ins    \t&\n\t\t\t\t\tiff.ins\t    \t&\n\t\t\t\t\tkeyboard.ins\t&\n\t\t\t\t\tmem.ins\t    \t&\n\t\t\t\t\tmisc.ins    \t&\n\t\t\t\t\tmono.ins    \t&\n\t\t\t\t\tpalette.ins \t&\n\t\t\t\t\trawfile.ins\t\t&\n\t\t\t\t\tshape.ins\t\t&\n\t\t\t\t\ttile.ins \t\t&\n\t\t\t\t\ttimer.ins \t\t&\n\t\t\t\t\tww_win.ins \t\t&\n\t\t\t\t\twsa.ins\t  \t\t&\n\t\t\t\t\tprofile.ins\t\t&\n\t\t\t\t\tplaycd.ins\t\t&\n\t\t\t\t\twincomm.ins\n\n\n\nLIB_UPDATE =\t&\n\t\t\t\t\taudio.upd\t\t&\n\t\t\t\t\tdipthong.upd\t&\n\t\t\t\t\tdrawbuff.upd\t&\n\t\t\t\t\tfont.upd    \t&\n\t\t\t\t\tiff.upd\t    \t&\n\t\t\t\t\tkeyboard.upd\t&\n\t\t\t\t\tmem.upd\t    \t&\n\t\t\t\t\tmisc.upd    \t&\n\t\t\t\t\tmono.upd    \t&\n\t\t\t\t\tpalette.upd \t&\n\t\t\t\t\trawfile.upd\t\t&\n\t\t\t\t\tshape.upd\t\t&\n\t\t\t\t\ttile.upd \t\t&\n\t\t\t\t\ttimer.upd \t\t&\n\t\t\t\t\tww_win.upd \t\t&\n\t\t\t\t\twsa.upd\t  \t\t&\n\t\t\t\t\tprofile.upd\t\t&\n\t\t\t\t\tplaycd.upd\t\t&\n\t\t\t\t\twincomm.upd\n\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.lib: $(WIN32LIB)\\lib\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n# LIB_CMD:\tlibrary command\n# LIB_CFG:\tlibrary configuration file\n# VCS_UPDATE:\tversion control update command; this command should update\n# \t\tall relevant files in a given directory with read-only\n#\t\tcopies from the archive\n#---------------------------------------------------------------------------\n!include $(WIN32LIB)\\project.cfg\nLIB_CMD = ..\\code\\watcom\\binnt\\wlib\nVCS_UPDATE = update\n\n#---------------------------------------------------------------------------\n# If you like to have this makefile switch to the mono screen automatically,\n# you will need to do a \"set MONO=Y\" or to anything you like.\n#---------------------------------------------------------------------------\n!ifdef %MONO\n.BEFORE\n\tmode mono\n\n.AFTER\n\tmode co80\n\n.ERROR\n\tmode co80\n!endif\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(LIB_NAME).lib .SYMBOLIC\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(LIB_NAME).lib: $(LIBS) libs.lbc\n\t$(LIB_CMD) $(LIB_CFG) $^@ @libs.lbc\n\n\n#---------------------------------------------------------------------------\n# This construct tells make how to make all component libraries\n# The commands get executed for every item in the macro.\n#\tThe macro $: extracts only the directory name from the macro item.\n#---------------------------------------------------------------------------\n$(LIBS):\n\techo Making $^&...\n\tcd $^&\n\twmake\n\tcd ..\n\n#---------------------------------------------------------------------------\n# Libs is librarian response file that is only genarated if any of the \n# sublibrary in the golbal variable LIBS was updated.\n#---------------------------------------------------------------------------\nlibs.lbc : $(LIBS)\n\t   %create $^@\n\t   for %index in ($(LIBS)) do %append $^@ +$(LIB_DIR)\\%index\n\n\n#---------------------------------------------------------------------------\n# \"make install\" installs the library on your drive\n#---------------------------------------------------------------------------\ninstall:  install_dirs $(LIB_INSTALL) .SYMBOLIC\n\techo Compiling library...\n \twmake\n\techo Library installation complete.\n\n#---------------------------------------------------------------------------\n# At installation time, this target makes all non-library directories\n#\tThis is a dependency for 'install'\n#---------------------------------------------------------------------------\ninstall_dirs: .SYMBOLIC\n\techo Making directories...\n\tmkdir example\n\tmkdir include\n\tmkdir lib   \n\tmkdir srcdebug\n\tmkdir tools\n\tcd tools  \n\tcopy $(%WWVCS)\\tools\\vcs.cfg\n\t$(VCS_UPDATE) \n\tcd..   \n\tcopy $(%WWVCS)\\vcs.cfg\n\t$(VCS_UPDATE) \n\tcd example \n\tcopy $(%WWVCS)\\example\\vcs.cfg \n\t$(VCS_UPDATE) \n\tcd ..\n\n\n#---------------------------------------------------------------------------\n# This target installs all library directories\n#\tThis is a dependency for 'install'\n#---------------------------------------------------------------------------\n$(LIB_INSTALL):\t.SYMBOLIC\n\techo Installing $^&...\n\tmd $^&\n\tcd $^&\n\tcopy $(%WWVCS)\\$^&\\vcs.cfg \n\t$(VCS_UPDATE) \n\tcopy *.h ..\\include\n\tcopy *.inc ..\\include\n\tcd ..\n\n\n\n\n\n#---------------------------------------------------------------------------\n# \"make update\" updates all source files in your slice\n#---------------------------------------------------------------------------\nupdate: $(LIB_UPDATE) .SYMBOLIC\n\techo Library updated.\n\n\n#---------------------------------------------------------------------------\n# This target updates all library directories\n#\tThis is a dependency for 'updates'\n#---------------------------------------------------------------------------\n$(LIB_UPDATE): .SYMBOLIC\n\techo Updating $^&...\n\tcd $^&\n\t$(VCS_UPDATE) \n\tcopy *.h ..\\include\n\tcopy *.inc ..\\include \n\tcd ..\n"
  },
  {
    "path": "WIN32LIB/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* LIBS\t\t= list of all component libraries\t\t\t   \t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* NOTE: For this makefile to work, each library directory MUST have the   *\n#*\tsame name as its library.\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* \"make install\" installs the library on your drive\t\t\t   \t\t\t\t*\n#* \"make update\" updates all source files in your slice\t\t\t   \t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#*\tTo install or update just one library you may type:\t\t   \t\t\t\t*\n#*\t\t \"make -DLIBS=misc.lib install\"\t\t\t\t   \t\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: list each library in this macro\n#\tNOTE: These are some order dependencies:\n#\t1. The directory MISC must always be made first.\n#\t2. The directory VIDEO must be made before the SYSTEM directory.\n#===========================================================================\nLIB_NAME    = win32lib\nLIB_DIR     = $(WIN32LIB)\\lib\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# LIBS macro: a list of all component libraries\n#\t\"make LIBS=xxxx.lib [target]\" makes/installs/updates only that library\n#---------------------------------------------------------------------------\n\nLIBS = \t\t\t\\\n\t\t\t\t\taudio.lib\t\t\\\n\t\t\t\t\tdipthong.lib\t\\\n\t\t\t\t\tdrawbuff.lib\t\\\n\t\t\t\t\tfont.lib    \t\\\n\t\t\t\t\tiff.lib\t    \t\\\n\t\t\t\t\tkeyboard.lib\t\\\n\t\t\t\t\tmem.lib\t    \t\\\n\t\t\t\t\tmisc.lib    \t\\\n\t\t\t\t\tmono.lib    \t\\\n\t\t\t\t\tpalette.lib    \t\\\n\t\t\t\t\trawfile.lib\t\t\\\n\t\t\t\t\ttile.lib \t\t\\\n\t\t\t\t\ttimer.lib \t\t\\\n\t\t\t\t\tww_win.lib \t\t\\\n\t\t\t\t\twsa.lib\n\nLIB_INSTALL = \t\\\n\t\t\t\t\taudio.ins\t\t\\\n\t\t\t\t\tdipthong.ins\t\\\n\t\t\t\t\tdrawbuff.ins\t\\\n\t\t\t\t\tfont.ins    \t\\\n\t\t\t\t\tiff.ins\t    \t\\\n\t\t\t\t\tkeyboard.ins\t\\\n\t\t\t\t\tmem.ins\t    \t\\\n\t\t\t\t\tmisc.ins    \t\\\n\t\t\t\t\tmono.ins    \t\\\n\t\t\t\t\tpalette.ins    \t\\\n\t\t\t\t\trawfile.ins\t\t\\\n\t\t\t\t\ttile.ins \t\t\\\n\t\t\t\t\ttimer.ins \t\t\\\n\t\t\t\t\tww_win.ins \t\t\\\n\t\t\t\t\twsa.ins\n\nLIB_UPDATE = \t\\\n\t\t\t\t\taudio.upd\t\t\\\n\t\t\t\t\tdipthong.upd\t\\\n\t\t\t\t\tdrawbuff.upd\t\\\n\t\t\t\t\tfont.upd    \t\\\n\t\t\t\t\tiff.upd\t    \t\\\n\t\t\t\t\tkeyboard.upd\t\\\n\t\t\t\t\tmem.upd\t    \t\\\n\t\t\t\t\tmisc.upd    \t\\\n\t\t\t\t\tmono.upd    \t\\\n\t\t\t\t\tpalette.upd    \t\\\n\t\t\t\t\trawfile.upd\t\t\\\n\t\t\t\t\ttile.upd \t\t\\\n\t\t\t\t\ttimer.upd \t\t\\\n\t\t\t\t\tww_win.upd \t\t\\\n\t\t\t\t\twsa.upd\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.lib\t=\t$(WIN32LIB)\\\\lib\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n# LIB_CMD:\tlibrary command\n# LIB_CFG:\tlibrary configuration file\n# VCS_UPDATE:\tversion control update command; this command should update\n# \t\tall relevant files in a given directory with read-only\n#\t\tcopies from the archive\n#---------------------------------------------------------------------------\nLIB_CMD\t\t= tlib\nVCS_UPDATE\t= update\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(LIB_NAME).lib\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_NAME).lib: $(LIBS)\n\tdel $<\n\t$(LIB_CMD) $< $(LIB_CFG)  @&&|\n +$(WIN32LIB)\\\\lib\\\\audio.lib\t\t\t&\n+$(WIN32LIB)\\\\lib\\\\dipthong.lib\t\t&\n+$(WIN32LIB)\\\\lib\\\\drawbuff.lib\t\t&\n+$(WIN32LIB)\\\\lib\\\\font.lib \t\t\t&\n+$(WIN32LIB)\\\\lib\\\\iff.lib\t    \t\t&\n+$(WIN32LIB)\\\\lib\\\\keyboard.lib\t\t&\n+$(WIN32LIB)\\\\lib\\\\mem.lib\t    \t\t&\n+$(WIN32LIB)\\\\lib\\\\misc.lib    \t\t&\n+$(WIN32LIB)\\\\lib\\\\mono.lib    \t\t&\n+$(WIN32LIB)\\\\lib\\\\palette.lib    \t\t&\n+$(WIN32LIB)\\\\lib\\\\rawfile.lib    \t&\n+$(WIN32LIB)\\\\lib\\\\tile.lib \t\t\t&\n+$(WIN32LIB)\\\\lib\\\\timer.lib \t\t\t&\n+$(WIN32LIB)\\\\lib\\\\ww_win.lib \t\t&\n+$(WIN32LIB)\\\\lib\\\\wsa.lib\n|\n\n#---------------------------------------------------------------------------\n# This construct tells make how to make all component libraries\n# The commands get executed for every item in the macro.\n#\tThe macro $: extracts only the directory name from the macro item.\n#---------------------------------------------------------------------------\n$(LIBS):\n\techo Making $^&...\n\tcd $^&\n\tmake\n\tcd ..\n\n#---------------------------------------------------------------------------\n# \"make install\" installs the library on your drive\n#---------------------------------------------------------------------------\ninstall:  install_dirs $(LIB_INSTALL) .SYMBOLIC\n\techo Compiling library...\n \twmake\n\techo Library installation complete.\n\n#---------------------------------------------------------------------------\n# At installation time, this target makes all non-library directories\n#\tThis is a dependency for 'install'\n#---------------------------------------------------------------------------\ninstall_dirs: .SYMBOLIC\n\techo Making directories...\n\tmkdir example\n\tmkdir include\n\tmkdir lib\n\tmkdir srcdebug\n\tmkdir tools\n\tcd tools\n\tcopy $(%WWVCS)\\tools\\vcs.cfg\n\t$(VCS_UPDATE)\n\tcd..\n\tcopy $(%WWVCS)\\vcs.cfg\n\t$(VCS_UPDATE)\n\tcd example\n\tcopy $(%WWVCS)\\example\\vcs.cfg\n\t$(VCS_UPDATE)\n\tcd ..\n\n\n#---------------------------------------------------------------------------\n# This target installs all library directories\n#\tThis is a dependency for 'install'\n#---------------------------------------------------------------------------\n$(LIB_INSTALL):\t.SYMBOLIC\n\techo Installing $^&...\n\tmd $^&\n\tcd $^&\n\tcopy $(%WWVCS)\\$^&\\vcs.cfg\n\t$(VCS_UPDATE)\n\tcopy *.h ..\\include\n\tcopy *.inc ..\\include\n\tcd ..\n\n\n\n\n\n#---------------------------------------------------------------------------\n# \"make update\" updates all source files in your slice\n#---------------------------------------------------------------------------\nupdate: $(LIB_UPDATE) .SYMBOLIC\n\techo Library updated.\n\n\n#---------------------------------------------------------------------------\n# This target updates all library directories\n#\tThis is a dependency for 'updates'\n#---------------------------------------------------------------------------\n$(LIB_UPDATE): .SYMBOLIC\n\techo Updating $^&...\n\tcd $^&\n\t$(VCS_UPDATE)\n\tcopy *.h ..\\include\n\tcopy *.inc ..\\include\n\tcd .."
  },
  {
    "path": "WIN32LIB/MAKE_EXE.MAK",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .EXE makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 20, 1995  \t                   *\n#*                                                                         *\n#*                  Last Update : \t\t\t                   *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*                                                                         *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the executable program you're building \t   *\n#* PROJ_LIBS\t= Westwood libraries to link your EXE to \t           *\n#* OBJECTS\t= list of objects in your current working directory\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .xxx:\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n#---------------------------------------------------------------------------\n# PROJ_NAME = library name\n# PROJ_DIR = directory containing source & objects\n#---------------------------------------------------------------------------\nPROJ_NAME\t= TEST\nPROJ_DIR\t= $(%WWFLAT)\\MEM\\TEST\nLIB_DIR\t        = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t   \t&\n\t$(PROJ_NAME).obj\t&\n\tobject0.obj\t\t&\n\tobject1.obj\t\t\n\nPROJ_LIBS = \t\t\t&\n\t    lib1.lib\t\t&\n\t    lib2.lib\t\t&\n\t    wwflat32.lib\n\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t $(PROJ_DIR)\n.c:   \t $(PROJ_DIR)\n.cpp:\t $(PROJ_DIR)\n.h:   \t $(PROJ_DIR)\n.obj:\t $(PROJ_DIR)\n.lib:\t $(%WWFLAT)\\lib\n.exe:\t $(PROJ_DIR)\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n# If LIB & INCLUDE are already defined, they are used in addition to the\n# WWLIB32 lib & include; otherwise, they're constructed from\n# BCDIR \n#---------------------------------------------------------------------------\n\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(PROJ_NAME).exe \n\n#---------------------------------------------------------------------------\n# Build the EXE\n#---------------------------------------------------------------------------\n$(PROJ_NAME).exe: $(OBJECTS)  $(PROJ_NAME).lnk $(PROJ_LIBS)\n\t $(LINK_CMD) $(LINK_CFG) system dos4g name $^@ @$(PROJ_NAME).lnk\n\n\n$(PROJ_LIBS):\t\t\n\techo updating base library $^@\n\tcd ..\n\twmake\n\tcd $(PROJ_DIR)\n\n\n$(PROJ_NAME).lnk : $(OBJECTS)\n       %create $^@\n       for %index in ($(OBJECTS))  do %append $^@ file %index\n       for %index in ($(PROJ_LIBS)) do %append $^@ library $(LIB_DIR)\\%index\n\n#**************************** End of makefile ******************************\n\n\n"
  },
  {
    "path": "WIN32LIB/MAKE_LIB.MAK",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : jan 24, 1995\t                           *\n#*                                                                         *\n#*                  Last Update : \t\t\t                   *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = project_name\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tobject1.obj  \t&\n\tobject2.obj  \t&\n\tobject3.obj \n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WWLIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/MEM/ALLOC.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : ALLOC.CPP                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : February 1, 1992                         *\n *                                                                         *\n *                  Last Update : March 9, 1995 [JLB]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Alloc -- Allocates system RAM.                                        *\n *   Ram_Free -- Determines the largest free chunk of RAM.                 *\n *   Free -- Free an Alloc'ed block of RAM.                                *\n *   Resize_Alloc -- Change the size of an allocated block.                *\n *   Heap_Size -- Size of the heap we have.                                *\n *   Total_Ram_Free -- Total amount of free RAM.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <malloc.h>\n#include <string.h>\n#include <stdlib.h>\n#include <dos.h>\n#include <bios.h>\n\n\n#ifndef WWMEM_H\n#include \"wwmem.h\"\n#endif\n\n\nextern \"C\" unsigned long Largest_Mem_Block ( void ) ;\n\n/*\n** Define the equates necessary to call a DPMI interrupt.\n*/\n#define\tDPMI_INT\t\t\t\t\t\t\t\t\t0x0031\n#define\tDPMI_LOCK_MEM\t\t\t\t\t\t\t0x0600\n#define\tDPMI_UNLOCK_MEM\t\t\t\t\t\t0x0601\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\nunsigned long MinRam=0L;\t\t// Record of least memory at worst case.\nunsigned long MaxRam=0L;\t\t// Record of total allocated at worst case.\nstatic unsigned long TotalRam = 0L;\nstatic unsigned long Memory_Calls = 0L;\n\nvoid (*Memory_Error)(void) = NULL;\nextern void (*Memory_Error_Exit)(char *string)=NULL;\n\n\n//#define MEM_CHECK\n\n#ifdef MEM_CHECK\nextern \"C\"{\n\textern void __cdecl Int3(void);\n}\n#endif\t//MEM_CHECK\n\n/***************************************************************************\n * DPMI_LOCK -- handles locking a block of DPMI memory                     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n#include\"mono.h\"\nvoid DPMI_Lock(VOID const *, long const )\n{\n}\n\n/***************************************************************************\n * DPMI_UNLOCK -- Handles unlocking a locked block of DPMI                 *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid DPMI_Unlock(void const *, long const )\n{\n}\n\n/***************************************************************************\n * Alloc -- Allocates system RAM.                                          *\n *                                                                         *\n *    This is the basic RAM allocation function.  It is used for all       *\n *    memory allocations needed by the system or the main program.         *\n *                                                                         *\n * INPUT:   bytes_to_alloc -- LONG value of the number of bytes to alloc.  *\n *                                                                         *\n *          flags          -- Memory allocation control flags.             *\n *             MEM_NORMAL: No special flags.                               *\n *             MEM_CLEAR:  Zero out memory block.                        \t*\n *             MEM_NEW:\t\tCalled by a new.                                *\n *                                                                         *\n * OUTPUT:  Returns with pointer to allocated block.  If NULL was returned *\n *          it indicates a failure to allocate.  Note: NULL will never be  *\n *          returned if the standard library allocation error routine is   *\n *          used.                                                          *\n *                                                                         *\n * WARNINGS:   If you replace the standard memory allocation error routine *\n *             and make it so that Alloc CAN return with a NULL, be sure   *\n *             and check for this in your code.                            *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Documented.                                          *\n *   08/09/1993 JLB : Updated with EMS memory support.                     *\n *   04/28/1994 JAW : Updated to 32bit Protected mode.                     *\n *   03/09/1995 JLB : Fixed                                                *\n *   09/28/1995 ST  : Simplified for win95                                                                      *\n *=========================================================================*/\nvoid *Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags)\n{\n\n#ifdef WIN32\n\n\tvoid\t*mem_ptr;\n\n#ifdef MEM_CHECK\n\tbytes_to_alloc += 32;\n#endif\t//MEM_CHECK\n\n\tmem_ptr = malloc ( bytes_to_alloc );\n\n\tif ( !mem_ptr && Memory_Error ){\n\t\tMemory_Error();\n\t}\n\n\tif ( mem_ptr && ( flags & MEM_CLEAR ) ){\n\t\tmemset ( mem_ptr , 0 , bytes_to_alloc );\n\t}\n\n#ifdef MEM_CHECK\n\tmem_ptr = (void*)((char*)mem_ptr + 16);\n\tunsigned long *magic_ptr =(unsigned long*) ( ((char *)mem_ptr) - 16 );\n\t*magic_ptr++ = (unsigned long)mem_ptr;\n\t*magic_ptr++ = (unsigned long)mem_ptr;\n\t*magic_ptr++ = (unsigned long)mem_ptr;\n\t*magic_ptr \t = bytes_to_alloc - 32;\n\tmagic_ptr = (unsigned long*) ( ((char*)mem_ptr) + bytes_to_alloc - 32 );\n\t*magic_ptr++ = (unsigned long)mem_ptr;\n\t*magic_ptr++ = (unsigned long)mem_ptr;\n\t*magic_ptr++ = (unsigned long)mem_ptr;\n\t*magic_ptr \t = (unsigned long)mem_ptr;\n#endif\t//MEM_CHECK\n\n\tMemory_Calls++;\n\treturn ( mem_ptr );\n\n#else\n\n\n\n\tunion REGS\t\tregs ;\n\tstruct SREGS \tsregs ;\n\tunsigned char *retval=NULL;\t// Pointer to allocated block.\n\tunsigned long\toriginal_size;\t// Original allocation size.\n\tunsigned long\tbytesfree;\t\t// Number of free bytes.\n\tlong \t\t\t\t*longptr=NULL;\t// Pointer used to store selector\n\n\t/*\n\t** Save the original allocated space size so that we can clear the\n\t** exact amount of RAM if they specified MEM_CLEAR.\n\t*/\n\toriginal_size = bytes_to_alloc;\n\n\t/*\n\t** Reserve one byte for the header of the memory we allocated.\n\t** We will store the flags variable there for later use.\n\t*/\n\tbytes_to_alloc += (flags & MEM_LOCK) ? 5 : 1;\n\n\t/*\n\t**\tInitialize the total ram available value.\n\t*/\n\tif (!TotalRam) {\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\t}\n\n\n\t// Try to allocate the memory out of the protected mode memory\n\t// chain if we did not require a real mode allocation.  If this\n\t// fails we will have to try to allocate it out of real mode memory.\n\t// Real mode memory is a last resort because some types of applications\n\t// require real mode memory.\n\tif (!(flags & MEM_REAL)) {\n\t\tretval = (unsigned char*)malloc(bytes_to_alloc);\n\t}\n\n\t// Try to allocate the memory out of the real mode memory using DPMI\n\t// service 0x100.  Note that retval will be null if we are requesting\n\t// real mode memory so that we do not have to explicitly check for the\n\t// real mode flag.  Remember we need to reserve room for the dos\n\t// selector value at the beginning of our allocated block so rather than\n\t// adding fifteen and rounding, we need to add 19 and round.\n\tif (!retval) {\n\t\tflags = (MemoryFlagType)(flags | MEM_REAL);\n\t\tregs.x.eax = 0x100;\n\t\tregs.x.ebx = (bytes_to_alloc + 19) >> 4;\n\t\tif (regs.x.ebx & 0xFFFF0000) {\n\t\t\tretval = NULL;\n\t\t} else {\n\t\t\tsegread ( & sregs ) ;\n\t\t\tint386x ( 0x31 , & regs, & regs , & sregs\t) ;\n\t\t\tif (regs.x.cflag)\n\t\t\t\tretval = NULL;\n\t\t\telse {\n\t\t\t\tlongptr\t\t= (long *)(((regs.x.eax & 0xFFFF) << 4)+ 1);\n\t\t\t\t*longptr++\t= regs.x.edx & 0xFFFF;\n\t\t\t\tretval\t\t= (unsigned char *)longptr;\n\t\t\t}\n\t\t}\n\t}\n\n\t// If the alloc failed then we need to signify a memory error.\n\tif (retval == NULL) {\n\t\tif(Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\n\t}\n\n\t// If the memory needs to be DPMI locked then we should store the\n\t// original size in the header before we store the flags.\n\tif (flags & MEM_LOCK) {\n\t\tlongptr\t\t= (long *)retval;\n\t\t*longptr++\t= original_size;\n\t\tretval\t\t= (unsigned char *)longptr;\n\t}\n\n\n\t// Now that we know the alloc was sucessful (and for an extra byte\n\t// more than the user wanted) we need to stick in the memory flags.\n\t*retval++ \t\t= flags;\n\n\t// If the memory needed to be DPMI locked then set it up so it\n\t// is locked.\n\tif (flags & MEM_LOCK) {\n\t\tDPMI_Lock(retval, original_size);\n\n\t}\n\n\n\t/* Clear the space if they wanted it clear */\n\n\tif (flags & MEM_CLEAR) {\n\t\tunsigned char\t*ptr;\t\t// Working memory block pointer.\n\n\t\tptr = retval;\n\t\tmemset(ptr, '\\0', original_size);\n\t}\n\n\tbytesfree = Total_Ram_Free(MEM_NORMAL);\n\tif (bytesfree < MinRam) {\n\t\tMinRam = bytesfree;\n\t}\n\tif (TotalRam-bytesfree > MaxRam) {\n\t\tMaxRam = TotalRam-bytesfree;\n\t}\n\n\tMemory_Calls++;\n\n\treturn(retval);\n\n#endif\n}\n\n\n/***************************************************************************\n * Free -- Free an Alloc'ed block of RAM.                                  *\n *                                                                         *\n * FUNCTION:                                                               *\n *                                                                         *\n * INPUT:       A pointer to a block of RAM from Alloc.                    *\n *                                                                         *\n * OUTPUT:      None.                                                      *\n *                                                                         *\n * WARNINGS:    Don't use this for an Alloc_Block'ed RAM block.            *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/25/1990     : Created.                                             *\n ***************************************************************************/\n#ifdef WIN32\n\nvoid Free(void const *pointer)\n{\n\n\tif ( pointer ){\n\n#ifdef MEM_CHECK\n\n\t\tunsigned long\t*magic_ptr = (unsigned long*) ( ((char*)pointer) - 16 );\n\n\t\tif (*magic_ptr++ != (unsigned long)pointer ||\n\t\t \t*magic_ptr++ != (unsigned long)pointer ||\n\t\t \t*magic_ptr++ != (unsigned long)pointer ){\n\t\t \tInt3();\n\t\t}\n\n\t\tmagic_ptr = (unsigned long*) ( ((char*)pointer) + *magic_ptr );\n\n\t\tif (*magic_ptr++ != (unsigned long)pointer ||\n\t\t \t*magic_ptr++ != (unsigned long)pointer ||\n\t\t \t*magic_ptr++ != (unsigned long)pointer ||\n\t\t \t*magic_ptr++ != (unsigned long)pointer ){\n\t\t \tInt3();\n\t\t}\n\n\t\tpointer = (void*) (((char*)pointer)-16);\n#endif\t//MEM_CHECK\n\n\t\tfree ( (void*)pointer );\n\t\tMemory_Calls--;\n\t}\n\n#else\n\nvoid Free(void const *pointer)\n{\n\n\tunion REGS\t\tregs ;\n\tstruct SREGS \tsregs ;\n\n\n\tif (pointer) {\n\t\t/*\n\t\t** Get a pointer to the flags that we stored off.\n\t\t*/\n\t\tchar *byteptr\t= ((char *)pointer) - 1;\n\n\t\t/*\n\t\t** Check to see if this was locked me and if it was unlock it.\n\t\t*/\n\t\tif (*byteptr & MEM_LOCK) {\n\t\t\tlong *longptr = ((long *)byteptr) - 1;\n\t\t\tDPMI_Unlock(pointer, *longptr);\n\t\t\tpointer = (void *)longptr;\n\t\t} else\n\t\t\tpointer = (void *)byteptr;\n\n\n\t\t// If the pointer is a real mode pointer than it will point to the\n\t\t// first megabyte of system memory.  If it does than we need to\n\t\t// use DPMI to free it.\n\t\tif (*byteptr & MEM_REAL) {\n\t\t\tregs.x.eax\t= 0x101;\n\t\t\tregs.x.edx\t= *(((long *)pointer) - 1);\n\t\t\tsegread ( & sregs ) ;\n\t\t\tint386x(0x31, &regs, &regs, &sregs);\n\t\t} else {\n\t\t\tfree((void *)pointer);\n\t\t}\n\t\tMemory_Calls--;\n\t}\n\n#endif\n}\n\n\n\n/***************************************************************************\n * Resize_Alloc -- Change the size of an allocated block.                  *\n *                                                                         *\n *    This routine will take a previously allocated block and change its   *\n *    size without unnecessarily altering its contents.                    *\n *                                                                         *\n * INPUT:   pointer  -- Pointer to the original memory allocation.         *\n *                                                                         *\n *          new_size -- Size in bytes that it will be converted to.        *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the new allocation.                  *\n *                                                                         *\n * WARNINGS:   ???                                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/01/1992 JLB : Commented.                                           *\n *=========================================================================*/\nvoid *Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes)\n{\n\n\tunsigned long *temp;\n\n\ttemp = (unsigned long*)original_ptr;\n\n\t/* ReAlloc the space */\n\ttemp = (unsigned long *)realloc(temp, new_size_in_bytes);\n\tif (temp == NULL) {\n\t\tif(Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\n\t}\n\n\treturn(temp);\n}\n\n\n/***************************************************************************\n * Ram_Free -- Determines the largest free chunk of RAM.                   *\n *                                                                         *\n *    Use this routine to determine the largest free chunk of available    *\n *    RAM for allocation.  It also performs a check of the memory chain.   *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  Returns with the size of the largest free chunk of RAM.        *\n *                                                                         *\n * WARNINGS:   This does not return the TOTAL memory free, only the        *\n *             largest free chunk.                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Commented.                                           *\n *=========================================================================*/\nlong Ram_Free(MemoryFlagType)\n{\n//\treturn(_memmax());\n#if(0)\n\tMEMORYSTATUS\tmem_info;\n\tmem_info.dwLength=sizeof(mem_info);\n\tGlobalMemoryStatus(&mem_info);\n\treturn ( mem_info.dwAvailPhys );\n#endif\n\treturn ( 64*1024*1024 );\n}\n\n\n/***************************************************************************\n * Heap_Size -- Size of the heap we have.                                  *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Heap_Size(MemoryFlagType )\n{\n\tif (!TotalRam) {\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\t}\n\treturn(TotalRam);\n}\n\n\n/***************************************************************************\n * Total_Ram_Free -- Total amount of free RAM.                             *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *   03/09/1995 JLB : Uses prerecorded heap size maximum.                  *\n *=========================================================================*/\nlong Total_Ram_Free(MemoryFlagType )\n{\n#if(0)\n\tMEMORYSTATUS\tmem_info;\n\tmem_info.dwLength=sizeof(mem_info);\n\tGlobalMemoryStatus(&mem_info);\n\treturn ( mem_info.dwAvailPhys );\n#endif\n\n\treturn ( 64*1024*1024 );\n}\n\n"
  },
  {
    "path": "WIN32LIB/MEM/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = mem\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR\t    = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\nCC_CFG += /zm\t\t\t\t\t\t\t\t\t# Each routine to be in its own segment.\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\talloc.obj  \t&\n\tmem.obj  \t&\n\tnewdel.obj  \t&\n\tmem_copy.obj\t&\n\tvmpagein.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/MEM/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = mem\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t   alloc.obj\t\t\\\n   \t\t\tmem.obj\t\t\t\\\n   \t\t\tnewdel.obj\t\t\\\n   \t\t\tmem_copy.obj\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) \n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n -+alloc.obj\t\t&\n-+mem.obj\t\t\t&\n-+newdel.obj\t\t&\n-+mem_copy.obj\t\n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/MEM/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = mem\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR\t    = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\nCC_CFG += /zm\t\t\t\t\t\t\t\t\t# Each routine to be in its own segment.\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\talloc.obj  \t&\n\tmem.obj  \t&\n\tnewdel.obj  \t&\n\tmem_copy.obj \n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include \n\t copy *.inc $(%WIN32LIB)\\include \n\t copy *.cpp $(%WIN32LIB)\\srcdebug \n\t copy *.asm $(%WIN32LIB)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/MEM/MEM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : MEM.C                                    *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : March 31, 1993                           *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Mem_Free -- Free a block of memory from system.                       *\n *   Mem_Alloc -- Allocate a block of memory from the special memory pool. *\n *   Mem_Init -- Initialize the private memory allocation pool.            *\n *   Mem_Reference -- Updates the reference time for the specified memory blo*\n *   Mem_Find -- Returns with pointer to specified memory block.           *\n *   Mem_Find_Oldest -- Returns with the memory block with the oldest time st*\n *   Mem_Free_Oldest -- Find and free the oldest memory block.             *\n *   Mem_Avail -- Returns the amount of free memory available in the cache.*\n *   Mem_Cleanup -- Performes a garbage collection on the memory cache.    *\n *   MemNode_Unlink -- Unlinks a node from the cache.                      *\n *   MemNode_Insert -- Inserts a node into a cache chain.                  *\n *   Mem_Largest_Avail -- Largest free block available.                    *\n *   Mem_Lock_Block -- Locks a block so that it cannot be moved in cleanup.*\n *   Mem_In_Use -- Makes it so a block will never be returned as oldest*\n *   Mem_Pool_Size -- Returns total amount of memory in pool.              *\n *   Mem_Get_ID -- Returns ID of node.                                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"wwmem.h\"\n#include <timer.h>\n\n#include\t<stddef.h>\n#include\t<mem.h>\n\n#define DEBUG_FILL FALSE\n\n////////////////////////////////////////////////////////////////////////////\n\n\n\n/*******************************************************************************\n** A allocated block may have one of three meanings in the Time field.  The first\n** is the time stamp of the last time it was referenced.  The other two values\n** are defined below.  MEM_BLOCK_IN_USE means that it will never be returned as the\n** oldest since there is no valid time stamp.  LOCKED_BLOCK has the same meaning as\n** MEM_BLOCK_IN_USE with the added feature that the block will not be moved in a\n** Mem_Cleanup().  Therefore, there may be some fragmentation after the cleanup\n** if any blocks are LOCKED.  It would be good practice to seldomly lock blocks,\n** for instance, only when a sample is being played.\n** WARNING: If these values change to anything else, logic will need to be changed\n**          in Mem_Find_Oldest since it relies on these being small values.\n*/\n#define MEM_BLOCK_IN_USE\t0x00\n#define MEM_BLOCK_LOCKED\t0x01\n\n/*\n**\tEach block of memory in the pool is headed by this structure.\n*/\ntypedef struct MemChain {\n\tstruct MemChain\t*Next;\t// Pointer to next memory chain node.\n\tstruct MemChain\t*Prev;\t// Pointer to previous memory chain node.\n\tunsigned long\t\tID;\t\t// ID number of block.\n\tunsigned short\t\tTime;\t\t// TickCount of latest reference.\n\tunsigned long\t\tSize;\t\t// Size of memory block (in paragraphs).\n} MemChain_Type;\n\n\n/*\n**\tHolding tank memory management data.\n*/\ntypedef struct MemPool {\n\tMemChain_Type\t*FreeChain;\t// Pointer to first node in free chain.\n\tMemChain_Type\t*UsedChain;\t// Pointer to first node in used chain.\n\tunsigned long\tFreeMem;\t\t// Current amount of free ram (in paragraphs).\n\tunsigned long\tTotalMem;\t// Total quantity of memory.\n\tlong\t\t\t\tpad2;\n} MemPool_Type;\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE void MemNode_Unlink(MemPool_Type *pool, int freechain, MemChain_Type *node);\nPRIVATE void MemNode_Insert(MemPool_Type *pool, int freechain, MemChain_Type *node, unsigned int size, unsigned long id, int merge);\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * Mem_Init -- Initialize the private memory allocation pool.              *\n *                                                                         *\n *    This routine is used to initialize the private memory allocation     *\n *    pool.                                                                *\n *                                                                         *\n * INPUT:   buffer   -- Pointer to the buffer that is the allocation pool. *\n *                                                                         *\n *          size     -- Size of the buffer in bytes.                       *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Was it initialized successfully?                   *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nint Mem_Init(void *buffer, long size)\n{\n\tMemChain_Type\t*mem;\t\t\t// Working memory chain node.\n\tMemPool_Type\t*pool;\t\t// Memory pool control structure.\n\n\t/*\n\t**\tThe buffer is rounded down to the nearest paragraph.\n\t*/\n\tsize = size & 0xFFFFFFF0L;\n\n\tif (!buffer || !size) return(FALSE);\n\n\t/*\n\t**\tInitialize the pool control structure.\n\t*/\n\tpool = (MemPool_Type *)buffer;\n\tpool->FreeMem = (size - sizeof(MemPool_Type)) >> 4;\n\tpool->UsedChain = NULL;\n\tpool->TotalMem = pool->FreeMem;\n\tmem = pool->FreeChain = (MemChain_Type *) (pool + 1);\n\n\t/*\n\t**\tInitialize the free memory chain.\n\t*/\n\tmem->Next = NULL;\n\tmem->Prev = NULL;\n\tmem->Size = pool->FreeMem;\n\tmem->ID = -1;\n\tmem->Time = 0;\n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * Mem_Alloc -- Allocate a block of memory from the special memory pool.   *\n *                                                                         *\n *    This routine will allocate a block of memory from the special        *\n *    memory allocation pool.                                              *\n *                                                                         *\n * INPUT:   poolptr\t-- Pointer to the memory pool base address.           *\n *                                                                         *\n *          size  -- The size of the memory block to allocate.             *\n *                                                                         *\n *          id    -- ID number to give this memory block.                  *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the allocated block.  If there was   *\n *          insufficient room, then NULL is returned.                      *\n *                                                                         *\n * WARNINGS:   Be sure to check for the NULL return case.                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Alloc(void *poolptr, long lsize, unsigned long id)\n{\n\tMemPool_Type\t*pool;\n\tMemChain_Type\t*node;\t\t\t// Pointer to current memory node.\n\tunsigned int\tremainder=0;\t// Remaining bytes that are still free.\n\tint\t\t\t\tfound;\n\tint\t\t\t\tsize;\t\t\t\t// Paragraph size of allocation.\n\n\n\t/*\n\t**\tIf there is no free memory then the allocation will\n\t**\talways fail.\n\t*/\n\tif (!poolptr || !lsize) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tAllocations are forced to be paragraph sized.\n\t*/\n\tlsize += sizeof(MemChain_Type);\t// Account for header.\n\tlsize = (lsize + 0x0FL) & 0xFFFFFFF0L;\n\tsize = (int)(lsize >> 4);\n\n\t/*\n\t**\tIf the total free is less than the size of the desired allocation,\n\t**\tthen we KNOW that an allocation will fail -- just return.\n\t*/\n\tif (pool->TotalMem < size) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tWalk down free chain looking for the first block that will\n\t**\taccomodate the allocation.\n\t*/\n\tnode = pool->FreeChain;\n\tfound = FALSE;\n\twhile (!found && node) {\n\n\t\t/*\n\t\t**\tFetch free memory chunk block and see if it is big enough.\n\t\t*/\n\t\tif (node->Size >= size) {\n\t\t\tfound = TRUE;\n\t\t\tbreak;\n\t\t}\n\t\tnode = node->Next;\n\t}\n\tif (!found) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tDetermine if this allocation would split the block.\n\t*/\n\tremainder = node->Size - size;\n\n\t/*\n\t**\tIf only a very small free chunk would remain, just tack it on\n\t**\tto the current allocation.\n\t*/\n\tif (remainder <= 2) {\n\t\tremainder = 0;\n\t\tsize = node->Size;\n\t}\n\n\t/*\n\t**\tRemove the primary block from the free memory list.\n\t*/\n\tMemNode_Unlink(pool, TRUE, node);\n\n\t/*\n\t**\tIf a smaller block remains, then link it back into\n\t**\tthe free memory list.\n\t*/\n\tif (remainder) {\n\t\tMemNode_Insert(pool, TRUE, (MemChain_Type *)Add_Long_To_Pointer(node, (long)size << 4), remainder, -1, FALSE);\n\t}\n\n\t/*\n\t**\tLink in the allocated node into the used memory list.\n\t*/\n\tMemNode_Insert(pool, FALSE, node, size, id, FALSE);\n\n\t/*\n\t**\tReflect the change to the total free count.\n\t*/\n\tpool->FreeMem -= size;\n\n\t/*\n\t**\tReturn a pointer to the block of allocated memory just past\n\t**\tthe header.\n\t*/\n\n#if DEBUG_FILL\n\tmemset(node + 1, id, (size-1) << 4);\n#endif\n\treturn((void *) (node + 1));\n}\n\n\n/***************************************************************************\n * Mem_Free -- Free a block of memory from system.                         *\n *                                                                         *\n *    This routine will free a block of memory from the special memory     *\n *    buffer.                                                              *\n *                                                                         *\n * INPUT:   poolptr\t-- Pointer to the memory pool base address.           *\n *                                                                         *\n *          buffer   -- Pointer to memory block to free.                   *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Was the deallocation successful?                   *\n *                                                                         *\n * WARNINGS:   Be sure to only pass in to this routine a buffer that was   *\n *             returned from Mem_Alloc().                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nint Mem_Free(void *poolptr, void *buffer)\n{\n\tMemPool_Type\t*pool;\t\t\t// pointer to structure.\n\tMemChain_Type\t*node;\t\t\t// Copy of current memory node.\n\tunsigned int\tsize;\t\t\t\t// Size of the block being freed.\n\n\t/*\n\t**\tOne can't free what isn't there.\n\t*/\n\tif (!buffer || !poolptr) {\n\t\treturn(FALSE);\n\t}\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tThe node pointer is actually back a bit from the \"normal\" pointer.\n\t*/\n\tnode = (MemChain_Type *) buffer;\n\tnode--;\n\n\t/*\n\t**\tGet pointer to actual allocated node and unlink it from the used\n\t**\tmemory chain.\n\t*/\n\tsize = node->Size;\n\tMemNode_Unlink(pool, FALSE, node);\n\tMemNode_Insert(pool, TRUE, node, size, -1, TRUE);\n\n\t/*\n\t**\tReflect the new free memory into the total memory count.\n\t*/\n\tpool->FreeMem += size;\n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * Mem_Reference -- Updates the reference time for the specified memory blo*\n *                                                                         *\n *    This routine is used to update the memory reference time for the     *\n *    specified memory node.  Typically, this is called every time a       *\n *    memory block is used in order to make sure the memory block time     *\n *    tracking (Last Recently Used) system works properly.                 *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   The node pointer must be valid.  For maximum safety this    *\n *             routine should be called right after Mem_Find().            *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid Mem_Reference(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node;\n\tnodeptr--;\n\n\tnodeptr->Time = (unsigned short)(TickCount.Time() >> 4);\n\n}\n\n\n/***************************************************************************\n * MEM_LOCK_BLOCK -- Locks a block so that it cannot be moved in cleanup.  *\n * \tBy marking a memory block in use, the memory system will never return*\n *    it as the oldest memory block.  It also makes it so that the block\t*\n *    will never be moved during a Cleanup process.                        *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:  \tIf one or more blocks are locked in a heap, Mem_Avail might *\n *             not equal Mem_Largest_Avail after a call to Mem_Cleanup.    *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid Mem_Lock_Block(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node;\n\tnodeptr--;\n\tnodeptr->Time = MEM_BLOCK_LOCKED;\n}\n\n\n/***************************************************************************\n * MEM_IN_USE -- Makes it so a block will never be returned as oldest\t\t*\n * \tBy marking a memory block in use, the memory system will never return*\n *    it as the oldest memory block.  It still can be moved in the Cleanup *\n *    code.                                                                *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS: Mem_Find_Oldest() will return NULL if only IN_USE blocks are  *\n *           in memory.                                                    *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid Mem_In_Use(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node - 1;\n\tnodeptr->Time = MEM_BLOCK_IN_USE;\n}\n\n\n/***************************************************************************\n * Mem_Find -- Returns with pointer to specified memory block.             *\n *                                                                         *\n *    Use this routine to convert a memory ID value into an actual memory  *\n *    pointer.  It sweeps through all of the 'cached' memory blocks and    *\n *    returns with the matching block pointer.                             *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache block.                 *\n *                                                                         *\n *          id       -- The ID of the block desired.                       *\n *                                                                         *\n * OUTPUT:  Returns with the pointer to the memory block.  If NULL is      *\n *          returned then the desired block is not in the memory cache.    *\n *                                                                         *\n * WARNINGS:   This routine may return NULL if the memory block is not     *\n *             present in the cache.                                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Find(void *poolptr, unsigned long id)\n{\n\tMemPool_Type\t*pool;\t\t\t// pointer to structure.\n\tMemChain_Type\t*node;\t\t\t// Working node structure.\n\n\tif (!poolptr) return(NULL);\n\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t** Cannot free a node that is not on the UsedChain list.\n\t*/\n\tif (!pool->UsedChain) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tSweep through entire allocation chain to find\n\t**\tthe one with the matching ID.\n\t*/\n\tnode = pool->UsedChain;\n\twhile (node) {\n\n\t\tif (node->ID == id) {\n\t\t\treturn(node + 1);\n\t\t}\n\t\tnode = node->Next;\n\t}\n\treturn(NULL);\n}\n\n\n/***************************************************************************\n * MEM_GET_ID -- Returns ID of node.                                       *\n *                                                                         *\n * INPUT:  void *node - pointer to node. \t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT: The ID of the node that was supplied by user during Mem_Alloc().*\n *                                                                         *\n * WARNINGS: pointer to node must be one that Mem_Alloc or                \t*\n *           Mem_Find returned.                                           **\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nunsigned long Mem_Get_ID(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return (0L);\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node - 1;\n\treturn (nodeptr->ID);\n}\n\n\n/***************************************************************************\n * Mem_Find_Oldest -- Returns with the memory block with the oldest time st*\n *                                                                         *\n *    Use this routine to find the memory block with the oldest time stamp *\n *    value.  Typically, this is used when freeing memory blocks in the    *\n *    cache in order to make room for a new memory block.                  *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns with the pointer to the oldest memory block.  If NULL  *\n *          is returned, then the memory cache is empty.                   *\n *                                                                         *\n * WARNINGS:   This routine could return NULL.                             *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *   04/15/1994 SKB : Handle time wrap, locked blocks, and no_refenece blocks*\n *=========================================================================*/\nvoid *Mem_Find_Oldest(void *poolptr)\n{\n\tMemChain_Type\t*node; \t\t\t\t// Working node pointer.\n\tMemChain_Type\t*oldnode;\t\t\t// Pointer to oldest block.\n\tunsigned int\toldtime;\t\t\t\t// Time of oldest block.\n\tunsigned int\tbasetime;\t\t\t// Time to mark our base time with.\n\tunsigned int\ttime;\t\t\t\t\t// basetime + time of node.\n\n\tif (!poolptr) return(NULL);\n\n\t/*\n\t**\tSweep through entire allocation chain to find\n\t**\tthe oldest referenced memory block.\n\t*/\n\toldnode = NULL;\n\toldtime = 0;\n\tnode = ((MemPool_Type*) poolptr)->UsedChain;\n\n  basetime = (unsigned int)(TickCount.Time() >> 4);\n\n\twhile (node) {\n\n\t\t/*\n\t\t** Don't allow MEM_BLOCK_IN_USE or MEM_BLOCK_LOCKED to be returned.\n\t\t*/\n\t\tif (node->Time > MEM_BLOCK_LOCKED) {\n\n\t\t\t/*\n\t\t\t** Adjust time for wrap around (after about 5 hrs).\n\t\t\t** times less then the base time will wrap up high while\n\t\t\t** and times greater then base time will then be lower since\n\t\t\t** any time greater has been on the thing a long time.\n\t\t\t*/\n\t\t\ttime = node->Time - basetime ;\n\n\t\t\tif (time < oldtime || !oldnode) {\n\t\t\t\toldtime = time;\n\t\t\t\toldnode = node;\n\t\t\t}\n\t\t}\n\t\tnode = node->Next;\n\t}\n\n\t/*\n\t**\tReturn with the value that matches the pointer that\n\t**\twas allocated by the system previously.\n\t*/\n\tif (oldnode) {\n\t\toldnode++;\n\t}\n\treturn(oldnode);\n}\n\n\n/***************************************************************************\n * Mem_Free_Oldest -- Find and free the oldest memory block.               *\n *                                                                         *\n *    This routine is used to free the oldest memory block in the memory   *\n *    cache.  This routine is typcially used in order to create more room  *\n *    in the cache for a new allocation.                                   *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns with the node that it freed.  Although this node is    *\n *          is no longer valid, it may be used to mark that pointer as     *\n *          invalid in the main code.                                      *\n *                                                                         *\n * WARNINGS:   If this routine returns NULL, then no memory was freed.     *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Free_Oldest(void *poolptr)\n{\n\tMemChain_Type\t*node;\t\t// Copy of pointer to oldest node.\n\n\tif (!poolptr) return(NULL);\n\tnode = (MemChain *) Mem_Find_Oldest(poolptr);\n\tif (Mem_Free(poolptr, node)) {\n\t\treturn(node);\n\t}\n\treturn(NULL);\n}\n\n/***************************************************************************\n * MEM_POOL_SIZE -- Returns total amount of memory in pool.                *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  long total size of pool. i.e. largest possible allocation if   *\n *          no memory was allocated.                                       *\n *                                                                         *\n * WARNINGS: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Mem_Pool_Size(void *poolptr)\n{\n\tMemPool_Type\t*pool;\t\t\t// Memory pool control structure.\n\tlong\t\t\t\tmemtotal;\t\t// Total amount of memory free.\n\n\tif (!poolptr) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\tmemtotal = ((long)pool->TotalMem) << 4;\n\tmemtotal -= sizeof(MemChain_Type);\n\tmemtotal = MAX(memtotal, (long)0);\n\treturn(memtotal);\n}\n\n/***************************************************************************\n * Mem_Avail -- Returns the amount of free memory available in the cache.  *\n *                                                                         *\n *    This routine examines the memory cache and returns the amount of     *\n *    free memory available.  This memory total MAY be fragmented but      *\n *    after Mem_Cleanup() is called, an allocation of the amount returned  *\n *    by this function is guaranteed.                                      *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns the largest allocation possible from the memory cache. *\n *                                                                         *\n * WARNINGS:   The value returned may represent the FRAGMENTED total       *\n *             amount of memory free in the cache.                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nlong Mem_Avail(void *poolptr)\n{\n\tMemPool_Type\t*pool;\t\t// Memory pool control structure.\n\tlong\t\t\t\tmemtotal;\t// Total amount of memory free.\n\n\tif (!poolptr) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\tmemtotal = ((long)pool->FreeMem) << 4;\n\tmemtotal -= sizeof(MemChain_Type);\n\t//memtotal -= sizeof(MemChain_Type) + 15;\n\tmemtotal = MAX(memtotal, (long)0);\n\treturn(memtotal);\n}\n\n\n/***************************************************************************\n * MEM_LARGEST_AVAIL -- Largest free block available.                      *\n * \tThis routine examines the free node list to find the largest block   *\n *\t\tavailable.  User can Mem_Alloc() this return size successfully.      *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns largest allocation currently possible from the cache. \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Mem_Largest_Avail(void *poolptr)\n{\n\tMemChain_Type\t*node;\t\t\t// Pointer to current memory node.\n\tunsigned int\tsize;\n\tlong\t\t\t\ttruesize;\n\n\t/*\n\t** Make sure that it is a buffer.\n\t*/\n\tif (!poolptr) return(NULL);\n\n\t/*\n\t** Go through the entire free chain looking for the largest block.\n\t*/\n\tnode = ((MemPool_Type *)poolptr)->FreeChain;\n\tsize = 0;\n\twhile (node) {\n\n\t\t/*\n\t\t**\tFetch free memory chunk block and see if it is big enough.\n\t\t*/\n\t\tif (node->Size >= size) {\n\t\t\tsize = node->Size;\n\t\t}\n\t\tnode = node->Next;\n\t}\n\n\ttruesize = (long)size << 4;\n\ttruesize -= sizeof(MemChain_Type);\n\ttruesize = MAX(truesize, 0L);\n\treturn (truesize);\n}\n\n\n/***************************************************************************\n * Mem_Cleanup -- Performs a garbage collection on the memory cache.       *\n *                                                                         *\n *    This routine is used to coalesce all adjacent free blocks of         *\n *    memory in the specified cache.  As a result, all previous pointers   *\n *    provided by Mem_Find() are invalidated.  This routine consumes a     *\n *    fair amount of time and should be called as infrequently as          *\n *    possible.                                                            *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine takes a significant amount of time!            *\n *             If there are locked block in memory, the pool may still     *\n *             be fragmented.                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Updated for low memory caches.                       *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid Mem_Cleanup(void *poolptr)\n{\n\tMemPool_Type\t*pool;  \t// Memory pool control structure.\n\tMemChain_Type\t*free,\t// Pointer to first free area.\n\t\t\t\t\t\t*cur;\t\t// Pointer to first used block that is after free.\n\tunsigned long\tsize;\n\tunsigned long\tfreesize;// Size of free heap at the end of the block.\n\n\tif (!poolptr) return;\n\n\t/*\n\t**\tFetch working copy of pool control structure.\n\t*/\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tBasic parameter and condition legality checks.  If the memory pool\n\t**\thas no free space, no free blocks, or no allocated blocks, then\n\t**\tmemory cleanup is unnecessary -- just exit.\n\t*/\n\tif (!pool->FreeMem || !pool->FreeChain || !pool->UsedChain) return;\n\n\tfreesize = pool->FreeMem;\n\tfree = pool->FreeChain;\n\tpool->FreeChain = NULL;\n\tcur = pool->UsedChain;\n\twhile (TRUE) {\n\n\t\t/*\n\t\t** Setup pointers so that free points to the first free block and cur\n\t\t** points to the next used block after the free block.\n\t\t*/\n\t\twhile (cur < free && cur) {\n\t \t\tcur = cur->Next;\n\t\t}\n\n\t\t// All used blocks are at the front of the free.  We are done.\n\t\tif (!cur) {\n\t \t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t** Do not allow a locked block to be moved.\n\t\t*/\n\t\tif (cur->Time == MEM_BLOCK_LOCKED) {\n\t\t\t/*\n\t\t\t** Figure the size of the new free block that we are creating.\n\t\t\t** Subtract off the total block size.\n\t\t\t** Add the node to the free list.\n\t\t\t*/\n\t\t\tsize = (char *) cur - (char  *) free;\n\t\t\tsize >>= 4;\n\t\t \tfreesize -= size;\n\t\t\tMemNode_Insert(pool, TRUE, free, (unsigned int) size, -1, FALSE);\n\n\t\t\t/*\n\t\t\t** Time to find a new free position to start working from.\n\t\t\t** Cur will be in the position just following.\n\t\t\t*/\n\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, (unsigned long)cur->Size << 4);\n\t\t\tcur = cur->Next;\n\t\t\twhile (free == cur) {\n\t\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, (unsigned long)cur->Size << 4);\n\t\t\t\tcur = cur->Next;\n\t\t\t}\n\n\t\t\t// All used blocks are at the front of the free.  We are done.\n\t\t\tif (!cur) {\n\t\t\t \tbreak;\n\t\t\t}\n\t\t} else {\n\n\t\t\t// Copy the block up.\n\t\t\tsize = (unsigned long)cur->Size << 4;\n\t\t\tMem_Copy(cur, free, size);\n\t\t\tcur = free;\n\n\t\t\t// Change pointers of surrounding blocks.\n\t\t\tif (cur->Next) {\n\t\t \t\tcur->Next->Prev = cur;\n\t\t\t}\n\t\t\tif (cur->Prev) {\n\t\t \t\tcur->Prev->Next = cur;\n\t\t\t} else {\n\t\t \t\tpool->UsedChain = cur;\n\t\t\t}\n\n\t\t\t// Change to next new free area.\n\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, size);\n\t\t}\n\t}\n\n\t/*\n\t**\tNow build the single free chunk.\n\t*/\n\tMemNode_Insert(pool, TRUE, free, freesize, -1, FALSE);\n}\n\n\n/***************************************************************************\n * MemNode_Unlink -- Unlinks a node from the cache.                        *\n *                                                                         *\n *    A private routine the actually unlinks a memory block from the       *\n *    memory cache.  It doesn't perform a complete update of the memory    *\n *    cache.                                                               *\n *                                                                         *\n * INPUT:   pool     -- Pointer to the memory cache header (copy in real   *\n *                      memory).                                           *\n *                                                                         *\n *          freechain-- Is the block part of the free memory chain?        *\n *                                                                         *\n *          node     -- Pointer to the node that will be unlinked.         *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine doesn't update memory totals.  It is a support *\n *             function.                                                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nPRIVATE void MemNode_Unlink(MemPool_Type *pool, int freechain, MemChain_Type *node)\n{\n\tMemChain_Type\t*other; \t\t// Copy of node data to unlink.\n\tMemChain_Type\t**chain;\t\t// A pointer to one of the chains pointer.\n\n\t/*\n\t**\tCheck for parameter validity.\n\t*/\n\tif (!pool || !node) return;\n\n\t/*\n\t**\tSetup working pointer for the particular chain desired.\n\t*/\n\tif (freechain) {\n\t\tchain = &pool->FreeChain;\n\t} else {\n\t\tchain = &pool->UsedChain;\n\t}\n\n\t/*\n\t**\tMake adjustments to the previous node.  If the pointer\n\t**\tto the previous node is NULL then this indicates the\n\t**\tfirst node in the list and thus the chain pointer needs\n\t**\tto be updated instead.\n\t*/\n\tif (node->Prev) {\n\t\tother = node->Prev;\n\t\tother->Next = node->Next;\n\t} else {\n\t\t*chain = node->Next;\n\t}\n\n\tif (node->Next) {\n\t\tother = node->Next;\n\t\tother->Prev = node->Prev;\n\t}\n}\n\n\n/***************************************************************************\n * MemNode_Insert -- Inserts a node into a cache chain.                    *\n *                                                                         *\n *    This routine is used to add a node to a cache chain.  Since nodes    *\n *    do not contain double links, they must be placed in sequence.        *\n *                                                                         *\n * INPUT:   pool     -- Pointer to memory pool (must be in real memory).   *\n *                                                                         *\n *          freechain-- Is the node to be inserted into the free chain?    *\n *                                                                         *\n *          node     -- Pointer to the node to insert.                     *\n *                                                                         *\n *          size     -- Size of the memory block (in paragraphs).          *\n *                                                                         *\n *          id       -- The ID number to associate with this block.        *\n *                                                                         *\n *          merge    -- Merge inserted block with adjacent blocks.         *\n *                                                                         *\n * OUTPUT:  return                                                         *\n *                                                                         *\n * WARNINGS:   This is a support routine.                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void MemNode_Insert(MemPool_Type *pool, int freechain, MemChain_Type *node, unsigned int size, unsigned long id, int merge)\n{\n\tMemChain_Type \t**chain;\t\t\t// Pointer to chain that will be linked.\n\tMemChain_Type \t*prev,\t\t\t// Successor node pointer.\n\t\t\t\t\t\t*next;\t\t\t// Predecessor node pointer.\n\tint\t\t\t\tdoit=TRUE;\t\t// Link the node into the list.\n\n\n\t/*\n\t**\tDetermine if the parameters are valid.\n\t*/\n\tif (!pool || !node || !size) return;\n\n\t/*\n\t**\tSetup working pointer for the particular chain desired.\n\t*/\n\tif (freechain) {\n\t\tchain = &pool->FreeChain;\n\t} else {\n\t\tchain = &pool->UsedChain;\n\t}\n\n\t/*\n\t**\tHandle the \"no node in list\" condition (easiest).\n\t*/\n\tif (!*chain) {\n\t\tnode->Next = NULL;\n\t\tnode->Prev = NULL;\n\t\tnode->Size = size;\n\t\tnode->Time = (unsigned short)(TickCount.Time() >> 4);\n\t\tnode->ID = id;\n\t\t*chain = node;\n\t\treturn;\n\t}\n\n\t/*\n\t**\tSweep through the memory chain looking for a likely spot\n\t**\tto insert the new node.  It will stop with \"next\" pointing\n\t**\tto the node to come after the block to be inserted and \"prev\"\n\t** will point to the node right before.\n\t*/\n\tprev = NULL;\n\tnext = *chain;\n\twhile (next && (next < node)) {\n\n\t\t/*\n\t\t**\tMove up the memory chain.\n\t\t*/\n\t\tprev = next;\n\t\tnext = next->Next;\n\t}\n\n\t/*\n\t**\tCoallescing of adjacent blocks (if requested).\n\t*/\n\tif (merge) {\n\n\t\t/*\n\t\t**\tIf the previous block is touching the block to insert\n\t\t**\tthen merely adjust the size of the previous block and\n\t\t**\tthat is all that is necessary.\n\t\t*/\n\t\tif (prev) {\n\t\t\tif (((char *)prev + ((long)prev->Size << 4)) == ((char *) node)) {\n\t\t\t\tprev->Size += size;\n\t\t\t\tsize = prev->Size;\n\t\t\t\tnode = prev;\n\t\t\t\tprev = prev->Prev;\n\t\t\t\tdoit = FALSE;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf the following block is touching the block to insert\n\t\t**\tthen remove the following block and increase the size of\n\t\t**\tthe original insertion block by the size of the other\n\t\t**\tblock.\n\t\t*/\n\t\tif (next) {\n\t\t\tif (((char *)node + ((long)size << 4)) == (char *)next) {\n\n\t\t\t\tif (!doit) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the node was already merged with the previous block\n\t\t\t\t\t**\tthen merely increase the previous block's size\n\t\t\t\t\t**\tand adjust it's next pointer appropriately.\n\t\t\t\t\t*/\n\t\t\t\t\tnode->Size += next->Size;\n\t\t\t\t\tnode->Next = next->Next;\n\t\t\t\t\tnext = next->Next;\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIncrease the size of the current block and adjust\n\t\t\t\t\t**\tthe \"next\" pointer so that it gets fixed up\n\t\t\t\t\t**\taccordingly.\n\t\t\t\t\t*/\n\t\t\t\t\tsize += next->Size;\n\t\t\t\t\tnext = next->Next;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n#if DEBUG_FILL\n\tif (doit) {\n\t\tmemset(node + 1, 0xFF, (size - 1) << 4);\n\t} else {\n\t\tmemset(node + 1, 0xFF, (node->Size - 1) << 4);\n\t}\n#endif\n\n\t/*\n\t**\tFixup the node pointers.\n\t*/\n\tif (prev) {\n\t\tprev->Next = node;\n\t}else{\n\t\t*chain = node;\n\t}\n\n\tif (next) {\n\t \tnext->Prev = node;\n\t}\n\n\tif (doit) {\n\t\tnode->Prev = prev;\n\t\tnode->Next = next;\n\t\tnode->Size = size;\n\t\tnode->Time = (unsigned short)(TickCount.Time() >> 4);\n\t\tnode->ID = id;\n\t}\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/MEM/MEMFLAG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory System                            *\n *                                                                         *\n *                    File Name : MEMFLAG.H                                *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : April 4, 1994                            *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef MEMFLAG_H\n#define MEMFLAG_H\n// Memory Flags\n/*\n**\tMemory allocation flags.  These are the flags that are passed into Alloc\n**\tin order to control the type of memory allocated.\n*/\ntypedef enum {\n\tMEM_NORMAL = 0x0000,\t\t// Default memory (normal).\n\tMEM_NEW\t  = 0x0001,\t\t// Called by the operator new and was overloaded.\n\tMEM_CLEAR  = 0x0002,\t\t// Clear memory before returning.\n\tMEM_REAL   = 0x0004,\t\t// Clear memory before returning.\n\tMEM_TEMP   = 0x0008,\t\t// Clear memory before returning.\n\tMEM_LOCK   = 0x0010,\t\t// Lock the memory that we allocated\n} MemoryFlagType;\n\n\n/*\n** Prototypes for VMPAGEIN.ASM\n*/\nextern \"C\"{\n\tvoid __cdecl Force_VM_Page_In (void *buffer, int length);\n}\n\n/*=========================================================================*/\n/* The following prototypes are for the file: ALLOC.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid * operator new(size_t size, MemoryFlagType flag);\nvoid * operator new[] (size_t size, MemoryFlagType flag);\nvoid\t*Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags);\nvoid\tFree(void const *pointer);\nvoid\tDPMI_Lock(VOID const *ptr, long const size);\nvoid\tDPMI_Unlock(void const *ptr, long const size);\nvoid\t*Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes);\nlong\tRam_Free(MemoryFlagType flag);\nlong\tHeap_Size(MemoryFlagType flag);\nlong\tTotal_Ram_Free(MemoryFlagType flag);\n\n#pragma option -Jgd\n\ninline void * operator new(size_t size, MemoryFlagType flag)\n{\n\treturn(Alloc(size, flag));\n}\ninline void * operator new[] (size_t size, MemoryFlagType flag)\n{\n\treturn(Alloc(size, flag));\n}\n\n#pragma option -Jgd\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MEM_COPY.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern \"C\" {\n\tvoid __cdecl Mem_Copy(void const *source, void *dest, unsigned long bytes_to_copy);\n}\n\n\ninline void *Add_Long_To_Pointer(void const *ptr, long size)\n{\n \treturn ((void *) ( (char const *) ptr + size));\n}\n\nextern void (*Memory_Error)(void);\nextern void (*Memory_Error_Exit)(char *string);\n\nextern unsigned long MinRam;\t\t// Record of least memory at worst case.\nextern unsigned long MaxRam;\t\t// Record of total allocated at worst case.\n\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/MEM/MEM_COPY.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : MEM_COPY.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott Bowen\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : September 8, 1994\t[IML]              *\n;*                  Ported to watcom c32 : 01/03/96     [JRJ]                                                                        *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Mem_Copy -- Copies from one pointer to another.                       *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nLOCALS ??\n\n\n;******************************************************************************\n; Much testing was done to determine that only when there are 14 or more bytes\n; being copied does it speed the time it takes to do copies in this algorithm.\n; For this reason and because 1 and 2 byte copies crash, is the special case\n; used.  SKB 4/21/94.  Tested on 486 66mhz.\nOPTIMAL_BYTE_COPY\tequ\t14\n\n\n;******************************************************************************\n; External declares so these functions can be called\n;\nGLOBAL \tC Mem_Copy\t: NEAR\nGLOBAL  C Largest_Mem_Block : near\n\nCODESEG\n\n\n;***************************************************************************\n;* MEM_COPY -- Copies from one pointer to another.                         *\n;* This routine copies bytes from source to dest.  It takes care of\t   *\n;* overlapped memory, and unsigned long copies.\t\t\t\t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/18/1994 SKB : Created.                                             *\n;*=========================================================================*\n; void Mem_Copy(void *source, void *dest, unsigned long bytes_to_copy);\n\n\nPROC Mem_Copy \tC near\n\tUSES\tecx , esi , edi , ebx\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tbytes:DWORD\n\n;********************************* Setup ******************************************\n\tcld\n\tmov\tesi,[source]\n\tmov\tedi,[dest]\n\tmov\tecx,[bytes]\t; get number of bytes to copy.\n\n     ; check pointers for singularities\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tje\t??done\t\t; No sence in copying the same pointer.\n\tor\tesi,0\n\tjz\t??done\n\tor\tedi,0\n\tjz\t??done\n\n\tcmp\tecx,OPTIMAL_BYTE_COPY  ; see notes above about equate.\n\tjge\t??normal      \t       ; If >= MAX(2,OPTIMAL_BYTE_COPY), do normal dword copy.\n\n;******************************** Special case <= 2 *******************************\n;\n; This section must be called for bytes <= 2 since the other case will crash.  It\n; optionally uses OPTIMAL_BYTE_COPY for the cut off point.  This is because after\n; extensive testing, it was proved that only at that point (14 or more bytes) does\n; it become quicker to use the dword copy method.\n\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tjge\t??do_move\t; if source greater do forward copy.\n\tlea\tesi,[esi+ecx-1]\n\tstd\t\t\t; Opps, wrong, force the pointers to decrement.\n\tlea\tedi,[edi+ecx-1]\n??do_move:\n\trep\tmovsb\t\t; move the one or two bytes.\n\tcld\n??done:\n\tret\n\n;************************** back or forth, that is the question *******************\n\n??normal:\n\tmov\tebx,ecx\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tjge\t??forward\t; if source greater do forward copy.\n\n;********************************* Backward ***************************************\n??backward:\n\tlea\tecx,[edi+ebx]\n\tstd\n\tlea\tedi,[edi+ebx-1]\n\tand\tecx,3\t\t; Get non aligned bytes.\n\tlea\tesi,[esi+ebx-1]\n\tsub\tebx,ecx\t\t; remove that from the total size to be copied later.\n\trep\tmovsb\t\t; do the copy.\n\tsub\tesi,3\n\tmov\tecx,ebx\t\t; Get number of bytes left.\n \tsub\tedi,3\n\tshr\tecx,2\t\t; Do 4 bytes at a time.\n\trep\tmovsd\t\t; do the dword copy.\n\tmov\tecx,ebx\n\tadd\tesi,3\n\tadd\tedi,3\n\tand\tecx,03h\n\trep\tmovsb\t\t; finnish the remaining bytes.\n\tcld\n\tret\n\n;********************************* Forward ***************************************\n??forward:\n\tcld\n\tmov\tecx,edi\t\t; get destination pointer.\n\tneg\tecx\n\tand\tecx,3\t\t; Get non aligned bytes.\n\tsub\tebx,ecx\t\t; remove that from the total size to be copied later.\n\trep\tmovsb\t\t; do the copy.\n\tmov\tecx,ebx\t\t; Get number of bytes left.\n\tshr\tecx,2\t\t; Do 4 bytes at a time.\n\trep\tmovsd\t\t; do the dword copy.\n\tmov\tecx, ebx\n\tand\tecx,03h\n\trep\tmovsb\t\t; finnish the remaining bytes.\n\tret\n\nENDP\tMem_Copy\nIF 0\nPROC Largest_Mem_Block \tC near\n\tuses\tesi , edi , ebx , ecx , edx\n\tlocal\tmem_struct : dword : 16\n\n\tmov\teax , 0500h\n\tlea\tedi , [ mem_struct ]\n\tint\t31h\n\tmov\teax , [ mem_struct ]\n\n\tret\nENDP Largest_Mem_Block\nENDIF\nEND\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/MEM/MSVC/ALLOC.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : ALLOC.CPP                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : February 1, 1992                         *\n *                                                                         *\n *                  Last Update : March 9, 1995 [JLB]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Alloc -- Allocates system RAM.                                        *\n *   Ram_Free -- Determines the largest free chunk of RAM.                 *\n *   Free -- Free an Alloc'ed block of RAM.                                *\n *   Resize_Alloc -- Change the size of an allocated block.                *\n *   Heap_Size -- Size of the heap we have.                                *\n *   Total_Ram_Free -- Total amount of free RAM.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <malloc.h>\n#include <string.h>\n#include <stdlib.h>\n#include <dos.h>\n#include <io.h>\n\n\n\n#ifndef WWMEM_H\n#include \"wwmem.h\"\n#endif\n\n\nextern \"C\" unsigned long Largest_Mem_Block ( void ) ;\n\n/*\n** Define the equates necessary to call a DPMI interrupt.\n*/\n#define\tDPMI_INT\t\t\t\t\t\t\t\t\t0x0031\n#define\tDPMI_LOCK_MEM\t\t\t\t\t\t\t0x0600\n#define\tDPMI_UNLOCK_MEM\t\t\t\t\t\t0x0601\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\nunsigned long MinRam=0L;\t\t// Record of least memory at worst case.\nunsigned long MaxRam=0L;\t\t// Record of total allocated at worst case.\nstatic unsigned long TotalRam = 0L;\nstatic unsigned long Memory_Calls = 0L;\n\t\t\nvoid (*Memory_Error)(void) = NULL;\n\n/***************************************************************************\n * DPMI_LOCK -- handles locking a block of DPMI memory                     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n#include\"mono.h\"\nvoid DPMI_Lock(VOID const *ptr, long const size)\n{\n#ifdef cuts\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\n\t/*\n\t** Lock memory\n\t** AX = 0x600\n\t** BX:CX = starting linear address of memory to lock\n\t** SI:DI = size of region to lock (in bytes)\n\t** - If Failure, carry flag is set.\n\t*/\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_LOCK_MEM;\n\tregs.x.ebx = ((long)ptr & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000ffff);\n\tregs.x.esi = ((long)size & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n//\tif (regs.x.cflag) {\n//\t}\n#if(0)\n\tchar *temp = (char *)ptr;\n\tchar hold;\n\tfor (int lp = 0; lp < size; lp += 2048) {\n\t\thold = *temp;\n\t\ttemp += 2048;\n\t}\n#endif\n\n#endif\n}\n\n/***************************************************************************\n * DPMI_UNLOCK -- Handles unlocking a locked block of DPMI                 *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid DPMI_Unlock(void const *ptr, long const size)\n{\n\n#ifdef cuts\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\n\t/*\n\t** Unlock the memory\n\t*/\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_UNLOCK_MEM;\t\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = ((long)ptr & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000ffff);\n\tregs.x.esi = ((long)size & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n//\tif (regs.x.cflag) {\n//\t}\n\n#endif\n\n}\n\n/***************************************************************************\n * Alloc -- Allocates system RAM.                                          *\n *                                                                         *\n *    This is the basic RAM allocation function.  It is used for all       *\n *    memory allocations needed by the system or the main program.         *\n *                                                                         *\n * INPUT:   bytes_to_alloc -- LONG value of the number of bytes to alloc.  *\n *                                                                         *\n *          flags          -- Memory allocation control flags.             *\n *             MEM_NORMAL: No special flags.                               *\n *             MEM_CLEAR:  Zero out memory block.                        \t*\n *             MEM_NEW:\t\tCalled by a new.                                *\n *                                                                         *\n * OUTPUT:  Returns with pointer to allocated block.  If NULL was returned *\n *          it indicates a failure to allocate.  Note: NULL will never be  *\n *          returned if the standard library allocation error routine is   *\n *          used.                                                          *\n *                                                                         *\n * WARNINGS:   If you replace the standard memory allocation error routine *\n *             and make it so that Alloc CAN return with a NULL, be sure   *\n *             and check for this in your code.                            *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Documented.                                          *\n *   08/09/1993 JLB : Updated with EMS memory support.                     *\n *   04/28/1994 JAW : Updated to 32bit Protected mode.                     *\n *   03/09/1995 JLB : Fixed                                                * \n *=========================================================================*/\nvoid *Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags)\n{\n//\tunion REGS\t\tregs ;\n//\tstruct SREGS \tsregs ;\n\tunsigned char *retval=NULL;\t// Pointer to allocated block.\n\tunsigned long\toriginal_size;\t// Original allocation size.\n\tunsigned long\tbytesfree;\t\t// Number of free bytes.\n\tlong \t\t\t\t*longptr=NULL;\t// Pointer used to store selector\n\n\t/* \n\t** Save the original allocated space size so that we can clear the\n\t** exact amount of RAM if they specified MEM_CLEAR.\n\t*/\n\toriginal_size = bytes_to_alloc;\n\n\t/*\n\t** Reserve one byte for the header of the memory we allocated.\n\t** We will store the flags variable there for later use.\n\t*/\n\tbytes_to_alloc += (flags & MEM_LOCK) ? 5 : 1;\n\n\t/*\n\t**\tInitialize the total ram available value.\n\t*/\n\tif (!TotalRam) {\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\t}\n\n\n\t// Try to allocate the memory out of the protected mode memory\n\t// chain if we did not require a real mode allocation.  If this \n\t// fails we will have to try to allocate it out of real mode memory.\n\t// Real mode memory is a last resort because some types of applications\n\t// require real mode memory.\n\tif (!(flags & MEM_REAL)) {\n\t\tretval = (unsigned char*)malloc(bytes_to_alloc);\n\t}\n\n#ifdef cuts\n\t// Try to allocate the memory out of the real mode memory using DPMI\n\t// service 0x100.  Note that retval will be null if we are requesting\n\t// real mode memory so that we do not have to explicitly check for the\n\t// real mode flag.  Remember we need to reserve room for the dos \n\t// selector value at the beginning of our allocated block so rather than\n\t// adding fifteen and rounding, we need to add 19 and round.\n\tif (!retval) {\n\t\tflags = (MemoryFlagType)(flags | MEM_REAL);\n\t\tregs.x.eax = 0x100;\n\t\tregs.x.ebx = (bytes_to_alloc + 19) >> 4;\n\t\tif (regs.x.ebx & 0xFFFF0000) {\n\t\t\tretval = NULL;\n\t\t} else {\n\t\t\tsegread ( & sregs ) ;\n\t\t\tint386x ( 0x31 , & regs, & regs , & sregs\t) ;\n\t\t\tif (regs.x.cflag)\n\t\t\t\tretval = NULL;\n\t\t\telse {\n\t\t\t\tlongptr\t\t= (long *)(((regs.x.eax & 0xFFFF) << 4)+ 1);\n\t\t\t\t*longptr++\t= regs.x.edx & 0xFFFF;\n\t\t\t\tretval\t\t= (unsigned char *)longptr;\n\t\t\t}\n\t\t}\n\t}\n\n#endif\n\n\t// If the alloc failed then we need to signify a memory error.\n\tif (retval == NULL) {\n\t\tif(Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\t\t\n\t}\n\n\t// If the memory needs to be DPMI locked then we should store the\n\t// original size in the header before we store the flags.\n\tif (flags & MEM_LOCK) {\n\t\tlongptr\t\t= (long *)retval;\n\t\t*longptr++\t= original_size;\n\t\tretval\t\t= (unsigned char *)longptr;\n\t}\n\n\n\t// Now that we know the alloc was sucessful (and for an extra byte\n\t// more than the user wanted) we need to stick in the memory flags.\n\t*retval++ \t\t= flags;\n\n\t// If the memory needed to be DPMI locked then set it up so it\n\t// is locked.\n\tif (flags & MEM_LOCK) {\n\t\tDPMI_Lock(retval, original_size);\n\t\t\n\t}\n\n\n\t/* Clear the space if they wanted it clear */\n\n\tif (flags & MEM_CLEAR) {\n\t\tunsigned char\t*ptr;\t\t// Working memory block pointer.\n\n\t\tptr = retval;\n\t\tmemset(ptr, '\\0', original_size);\n\t}\n\n\tbytesfree = Total_Ram_Free(MEM_NORMAL);\n\tif (bytesfree < MinRam) {\n\t\tMinRam = bytesfree;\n\t}\n\tif (TotalRam-bytesfree > MaxRam) {\n\t\tMaxRam = TotalRam-bytesfree;\n\t}\n\n\tMemory_Calls++;\n\n\treturn(retval);\n}\n\n\n/***************************************************************************\n * Free -- Free an Alloc'ed block of RAM.                                  *\n *                                                                         *\n * FUNCTION:                                                               *\n *                                                                         *\n * INPUT:       A pointer to a block of RAM from Alloc.                    *\n *                                                                         *\n * OUTPUT:      None.                                                      *\n *                                                                         *\n * WARNINGS:    Don't use this for an Alloc_Block'ed RAM block.            *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/25/1990     : Created.                                             *\n ***************************************************************************/\nvoid Free(void const *pointer)\n{\n//\tunion REGS\t\tregs ;\n//\tstruct SREGS \tsregs ;\n\n\n\tif (pointer) {\n\t\t/*\n\t\t** Get a pointer to the flags that we stored off.\n\t\t*/\n\t\tchar *byteptr\t= ((char *)pointer) - 1;\n\n\t\t/*\n\t\t** Check to see if this was locked me and if it was unlock it.\n\t\t*/\n\t\tif (*byteptr & MEM_LOCK) {\n\t\t\tlong *longptr = ((long *)byteptr) - 1;\n\t\t\tDPMI_Unlock(pointer, *longptr);\n\t\t\tpointer = (void *)longptr;\n\t\t} else\n\t\t\tpointer = (void *)byteptr;\n\t\t\n\n\t\t// If the pointer is a real mode pointer than it will point to the\n\t\t// first megabyte of system memory.  If it does than we need to \n\t\t// use DPMI to free it.\n//\t\tif (*byteptr & MEM_REAL) {\n//\t\t\tregs.x.eax\t= 0x101;\n//\t\t\tregs.x.edx\t= *(((long *)pointer) - 1);\n//\t\t\tsegread ( & sregs ) ;\n//\t\t\tint386x(0x31, &regs, &regs, &sregs);\n//\t\t} else {\n\t\t\tfree((void *)pointer);\n//\t\t}\n\t\tMemory_Calls--;\n\t}\n}\n\n\n/***************************************************************************\n * Resize_Alloc -- Change the size of an allocated block.                  *\n *                                                                         *\n *    This routine will take a previously allocated block and change its   *\n *    size without unnecessarily altering its contents.                    *\n *                                                                         *\n * INPUT:   pointer  -- Pointer to the original memory allocation.         *\n *                                                                         *\n *          new_size -- Size in bytes that it will be converted to.        *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the new allocation.                  *\n *                                                                         *\n * WARNINGS:   ???                                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/01/1992 JLB : Commented.                                           *\n *=========================================================================*/\nvoid *Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes)\n{\n\n\tunsigned long *temp;\n\tunsigned long diff, flags;\n\n\ttemp = (unsigned long*)original_ptr;\n\n\t/* ReAlloc the space */\n\ttemp = (unsigned long *)realloc(temp, new_size_in_bytes);\n\tif (temp == NULL) {\n\t\tif(Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\t\t\n\t}\t\t\t   \n\n\treturn(temp);\n}\n\n\n/***************************************************************************\n * Ram_Free -- Determines the largest free chunk of RAM.                   *\n *                                                                         *\n *    Use this routine to determine the largest free chunk of available    *\n *    RAM for allocation.  It also performs a check of the memory chain.   *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  Returns with the size of the largest free chunk of RAM.        *\n *                                                                         *\n * WARNINGS:   This does not return the TOTAL memory free, only the        *\n *             largest free chunk.                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Commented.                                           *\n *=========================================================================*/\nlong Ram_Free(MemoryFlagType)\n{\n//\treturn(_memmax());\n\treturn Largest_Mem_Block();\n}\n\n\n/***************************************************************************\n * Heap_Size -- Size of the heap we have.                                  *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Heap_Size(MemoryFlagType )\n{\n\tif (!TotalRam) {\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\t}\n\treturn(TotalRam);\n}\n\n\n/***************************************************************************\n * Total_Ram_Free -- Total amount of free RAM.                             *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *   03/09/1995 JLB : Uses prerecorded heap size maximum.                  * \n *=========================================================================*/\nlong Total_Ram_Free(MemoryFlagType )\n{\n//\treturn(_memavl());\n\treturn Largest_Mem_Block () ;\n}\n\n"
  },
  {
    "path": "WIN32LIB/MEM/MSVC/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 24, 1994                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = mem\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR\t    = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\nCC_CFG += /zm\t\t\t\t\t\t\t\t\t# Each routine to be in its own segment.\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\talloc.obj  \t&\n\tmem.obj  \t&\n\tnewdel.obj  \t&\n\tmem_copy.obj \n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/MEM/MSVC/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 24, 1994                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = mem\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR\t    = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\nCC_CFG += /zm\t\t\t\t\t\t\t\t\t# Each routine to be in its own segment.\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\talloc.obj  \t&\n\tmem.obj  \t&\n\tnewdel.obj  \t&\n\tmem_copy.obj \n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/MEM/MSVC/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 24, 1994                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = mem\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR\t    = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\nCC_CFG += /zm\t\t\t\t\t\t\t\t\t# Each routine to be in its own segment.\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\talloc.obj  \t&\n\tmem.obj  \t&\n\tnewdel.obj  \t&\n\tmem_copy.obj \n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/MEM/MSVC/MEM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : MEM.C                                    *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : March 31, 1993                           *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Mem_Free -- Free a block of memory from system.                       *\n *   Mem_Alloc -- Allocate a block of memory from the special memory pool. *\n *   Mem_Init -- Initialize the private memory allocation pool.            *\n *   Mem_Reference -- Updates the reference time for the specified memory blo*\n *   Mem_Find -- Returns with pointer to specified memory block.           *\n *   Mem_Find_Oldest -- Returns with the memory block with the oldest time st*\n *   Mem_Free_Oldest -- Find and free the oldest memory block.             *\n *   Mem_Avail -- Returns the amount of free memory available in the cache.*\n *   Mem_Cleanup -- Performes a garbage collection on the memory cache.    *\n *   MemNode_Unlink -- Unlinks a node from the cache.                      *\n *   MemNode_Insert -- Inserts a node into a cache chain.                  *\n *   Mem_Largest_Avail -- Largest free block available.                    *\n *   Mem_Lock_Block -- Locks a block so that it cannot be moved in cleanup.*\n *   Mem_In_Use -- Makes it so a block will never be returned as oldest*\n *   Mem_Pool_Size -- Returns total amount of memory in pool.              *\n *   Mem_Get_ID -- Returns ID of node.                                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <wwstd.h>\n#include \"wwmem.h\"\n#include <timer.h>\n\n#include\t<stddef.h>\n#include\t<memory.h>\n\n#define DEBUG_FILL FALSE\n\n////////////////////////////////////////////////////////////////////////////\n\n\n\n/*******************************************************************************\n** A allocated block may have one of three meanings in the Time field.  The first\n** is the time stamp of the last time it was referenced.  The other two values\n** are defined below.  MEM_BLOCK_IN_USE means that it will never be returned as the\n** oldest since there is no valid time stamp.  LOCKED_BLOCK has the same meaning as\n** MEM_BLOCK_IN_USE with the added feature that the block will not be moved in a \n** Mem_Cleanup().  Therefore, there may be some fragmentation after the cleanup\n** if any blocks are LOCKED.  It would be good practice to seldomly lock blocks,\n** for instance, only when a sample is being played.\n** WARNING: If these values change to anything else, logic will need to be changed\n**          in Mem_Find_Oldest since it relies on these being small values.\n*/\n#define MEM_BLOCK_IN_USE\t0x00\n#define MEM_BLOCK_LOCKED\t0x01\n\n/*\n**\tEach block of memory in the pool is headed by this structure.\n*/\ntypedef struct MemChain {\n\tstruct MemChain\t*Next;\t// Pointer to next memory chain node.\n\tstruct MemChain\t*Prev;\t// Pointer to previous memory chain node.\n\tunsigned long\t\tID;\t\t// ID number of block.\n\tunsigned short\t\tTime;\t\t// TickCount of latest reference.\n\tunsigned short\t\tSize;\t\t// Size of memory block (in paragraphs).\n} MemChain_Type;\n\n\n/*\n**\tHolding tank memory management data.\n*/\ntypedef struct MemPool {\n\tMemChain_Type\t*FreeChain;\t// Pointer to first node in free chain.\n\tMemChain_Type\t*UsedChain;\t// Pointer to first node in used chain.\n\tunsigned short\tFreeMem;\t\t// Current amount of free ram (in paragraphs).\n\tunsigned short\tTotalMem;\t// Total quantity of memory.\n\tlong\t\t\t\tpad2;\n} MemPool_Type;\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE void MemNode_Unlink(MemPool_Type *pool, int freechain, MemChain_Type *node);\nPRIVATE void MemNode_Insert(MemPool_Type *pool, int freechain, MemChain_Type *node, unsigned int size, unsigned long id, int merge);\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * Mem_Init -- Initialize the private memory allocation pool.              *\n *                                                                         *\n *    This routine is used to initialize the private memory allocation     *\n *    pool.                                                                *\n *                                                                         *\n * INPUT:   buffer   -- Pointer to the buffer that is the allocation pool. *\n *                                                                         *\n *          size     -- Size of the buffer in bytes.                       *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Was it initialized successfully?                   *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nint Mem_Init(void *buffer, long size)\n{\n\tMemChain_Type\t*mem;\t\t\t// Working memory chain node.\n\tMemPool_Type\t*pool;\t\t// Memory pool control structure.\n\n\t/*\n\t**\tThe buffer is rounded down to the nearest paragraph.\n\t*/\n\tsize = size & 0xFFFFFFF0L;\n\n\tif (!buffer || !size) return(FALSE);\n\n\t/*\n\t**\tInitialize the pool control structure.\n\t*/\n\tpool = (MemPool_Type *)buffer;\n\tpool->FreeMem = (size - sizeof(MemPool_Type)) >> 4;\n\tpool->UsedChain = NULL;\n\tpool->TotalMem = pool->FreeMem;\n\tmem = pool->FreeChain = (MemChain_Type *) (pool + 1);\n\n\t/*\n\t**\tInitialize the free memory chain.\n\t*/\n\tmem->Next = NULL;\n\tmem->Prev = NULL;\n\tmem->Size = pool->FreeMem;\n\tmem->ID = -1;\n\tmem->Time = 0;\n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * Mem_Alloc -- Allocate a block of memory from the special memory pool.   *\n *                                                                         *\n *    This routine will allocate a block of memory from the special        *\n *    memory allocation pool.                                              *\n *                                                                         *\n * INPUT:   poolptr\t-- Pointer to the memory pool base address.           *\n *                                                                         *\n *          size  -- The size of the memory block to allocate.             *\n *                                                                         *\n *          id    -- ID number to give this memory block.                  *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the allocated block.  If there was   *\n *          insufficient room, then NULL is returned.                      *\n *                                                                         *\n * WARNINGS:   Be sure to check for the NULL return case.                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Alloc(void *poolptr, long lsize, unsigned long id)\n{\n\tMemPool_Type\t*pool;\n\tMemChain_Type\t*node;\t\t\t// Pointer to current memory node.\n\tunsigned int\tremainder=0;\t// Remaining bytes that are still free.\n\tint\t\t\t\tfound;\n\tint\t\t\t\tsize;\t\t\t\t// Paragraph size of allocation.\n\n\n\t/*\n\t**\tIf there is no free memory then the allocation will\n\t**\talways fail.\n\t*/\n\tif (!poolptr || !lsize) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\t\t\n\t/*\n\t**\tAllocations are forced to be paragraph sized.\n\t*/\n\tlsize += sizeof(MemChain_Type);\t// Account for header.\n\tlsize = (lsize + 0x0FL) & 0xFFFFFFF0L;\n\tsize = (int)(lsize >> 4);\n\n\t/*\n\t**\tIf the total free is less than the size of the desired allocation,\n\t**\tthen we KNOW that an allocation will fail -- just return.\n\t*/\n\tif (pool->TotalMem < size) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tWalk down free chain looking for the first block that will\n\t**\taccomodate the allocation.\n\t*/\n\tnode = pool->FreeChain;\n\tfound = FALSE;\n\twhile (!found && node) {\n\n\t\t/*\n\t\t**\tFetch free memory chunk block and see if it is big enough.\n\t\t*/\n\t\tif (node->Size >= size) {\n\t\t\tfound = TRUE;\n\t\t\tbreak;\n\t\t}\n\t\tnode = node->Next;\n\t}\n\tif (!found) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tDetermine if this allocation would split the block.\n\t*/\n\tremainder = node->Size - size;\n\n\t/*\n\t**\tIf only a very small free chunk would remain, just tack it on\n\t**\tto the current allocation.\n\t*/\n\tif (remainder <= 2) {\n\t\tremainder = 0;\n\t\tsize = node->Size;\n\t}\n\n\t/*\n\t**\tRemove the primary block from the free memory list.\n\t*/\n\tMemNode_Unlink(pool, TRUE, node);\n\n\t/*\n\t**\tIf a smaller block remains, then link it back into\n\t**\tthe free memory list.\n\t*/\n\tif (remainder) {\n\t\tMemNode_Insert(pool, TRUE, (MemChain_Type *)Add_Long_To_Pointer(node, (long)size << 4), remainder, -1, FALSE);\n\t}\n\n\t/*\n\t**\tLink in the allocated node into the used memory list.\n\t*/\n\tMemNode_Insert(pool, FALSE, node, size, id, FALSE);\n\n\t/*\n\t**\tReflect the change to the total free count.\n\t*/\n\tpool->FreeMem -= size;\n\n\t/*\n\t**\tReturn a pointer to the block of allocated memory just past\n\t**\tthe header.\n\t*/\n\n#if DEBUG_FILL\n\tmemset(node + 1, id, (size-1) << 4);\n#endif\n\treturn((void *) (node + 1));\n}\t\n\n\n/***************************************************************************\n * Mem_Free -- Free a block of memory from system.                         *\n *                                                                         *\n *    This routine will free a block of memory from the special memory     *\n *    buffer.                                                              *\n *                                                                         *\n * INPUT:   poolptr\t-- Pointer to the memory pool base address.           *\n *                                                                         *\n *          buffer   -- Pointer to memory block to free.                   *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Was the deallocation successful?                   *\n *                                                                         *\n * WARNINGS:   Be sure to only pass in to this routine a buffer that was   *\n *             returned from Mem_Alloc().                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nint Mem_Free(void *poolptr, void *buffer)\n{\n\tMemPool_Type\t*pool;\t\t\t// pointer to structure.\n\tMemChain_Type\t*node;\t\t\t// Copy of current memory node.\n\tunsigned int\tsize;\t\t\t\t// Size of the block being freed.\n\n\t/*\n\t**\tOne can't free what isn't there.\n\t*/\n\tif (!buffer || !poolptr) {\n\t\treturn(FALSE);\n\t}\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tThe node pointer is actually back a bit from the \"normal\" pointer.\n\t*/\n\tnode = (MemChain_Type *) buffer;\n\tnode--;\n\n\t/*\n\t**\tGet pointer to actual allocated node and unlink it from the used\n\t**\tmemory chain.\n\t*/\t\n\tsize = node->Size;\n\tMemNode_Unlink(pool, FALSE, node);\n\tMemNode_Insert(pool, TRUE, node, size, -1, TRUE);\n\n\t/*\n\t**\tReflect the new free memory into the total memory count.\n\t*/\n\tpool->FreeMem += size;\n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * Mem_Reference -- Updates the reference time for the specified memory blo*\n *                                                                         *\n *    This routine is used to update the memory reference time for the     *\n *    specified memory node.  Typically, this is called every time a       *\n *    memory block is used in order to make sure the memory block time     *\n *    tracking (Last Recently Used) system works properly.                 *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   The node pointer must be valid.  For maximum safety this    *\n *             routine should be called right after Mem_Find().            *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid Mem_Reference(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node;\t\t\t  \n\tnodeptr--;\n\n\tnodeptr->Time = (unsigned short)GetTickCount() >> 8;\n\n}\n\n\n/***************************************************************************\n * MEM_LOCK_BLOCK -- Locks a block so that it cannot be moved in cleanup.  *\n * \tBy marking a memory block in use, the memory system will never return*\n *    it as the oldest memory block.  It also makes it so that the block\t*\n *    will never be moved during a Cleanup process.                        *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:  \tIf one or more blocks are locked in a heap, Mem_Avail might *\n *             not equal Mem_Largest_Avail after a call to Mem_Cleanup.    *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid Mem_Lock_Block(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node;\n\tnodeptr--;\n\tnodeptr->Time = MEM_BLOCK_LOCKED;\n}\n\n\n/***************************************************************************\n * MEM_IN_USE -- Makes it so a block will never be returned as oldest\t\t*\n * \tBy marking a memory block in use, the memory system will never return*\n *    it as the oldest memory block.  It still can be moved in the Cleanup *\n *    code.                                                                *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS: Mem_Find_Oldest() will return NULL if only IN_USE blocks are  *\n *           in memory.                                                    *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid Mem_In_Use(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node - 1;\n\tnodeptr->Time = MEM_BLOCK_IN_USE;\n}\n\n\n/***************************************************************************\n * Mem_Find -- Returns with pointer to specified memory block.             *\n *                                                                         *\n *    Use this routine to convert a memory ID value into an actual memory  *\n *    pointer.  It sweeps through all of the 'cached' memory blocks and    *\n *    returns with the matching block pointer.                             *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache block.                 *\n *                                                                         *\n *          id       -- The ID of the block desired.                       *\n *                                                                         *\n * OUTPUT:  Returns with the pointer to the memory block.  If NULL is      *\n *          returned then the desired block is not in the memory cache.    *\n *                                                                         *\n * WARNINGS:   This routine may return NULL if the memory block is not     *\n *             present in the cache.                                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Find(void *poolptr, unsigned long id)\n{\n\tMemPool_Type\t*pool;\t\t\t// pointer to structure.\n\tMemChain_Type\t*node;\t\t\t// Working node structure.\n\n\tif (!poolptr) return(NULL);\n\n\tpool = (MemPool_Type *) poolptr;\n\t\t\n\t/* \n\t** Cannot free a node that is not on the UsedChain list.\n\t*/\n\tif (!pool->UsedChain) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tSweep through entire allocation chain to find\n\t**\tthe one with the matching ID.\n\t*/\n\tnode = pool->UsedChain;\n\twhile (node) {\n\t\t\n\t\tif (node->ID == id) {\n\t\t\treturn(node + 1);\n\t\t}\n\t\tnode = node->Next;\n\t}\n\treturn(NULL);\n}\n\n\n/***************************************************************************\n * MEM_GET_ID -- Returns ID of node.                                       *\n *                                                                         *\n * INPUT:  void *node - pointer to node. \t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT: The ID of the node that was supplied by user during Mem_Alloc().*\n *                                                                         *\n * WARNINGS: pointer to node must be one that Mem_Alloc or                \t*\n *           Mem_Find returned.                                           **\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nunsigned long Mem_Get_ID(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return (0L);\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node - 1;\n\treturn (nodeptr->ID);\n}\n\n\n/***************************************************************************\n * Mem_Find_Oldest -- Returns with the memory block with the oldest time st*\n *                                                                         *\n *    Use this routine to find the memory block with the oldest time stamp *\n *    value.  Typically, this is used when freeing memory blocks in the    *\n *    cache in order to make room for a new memory block.                  *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns with the pointer to the oldest memory block.  If NULL  *\n *          is returned, then the memory cache is empty.                   *\n *                                                                         *\n * WARNINGS:   This routine could return NULL.                             *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *   04/15/1994 SKB : Handle time wrap, locked blocks, and no_refenece blocks*\n *=========================================================================*/\nvoid *Mem_Find_Oldest(void *poolptr)\n{\n\tMemChain_Type\t*node; \t\t\t\t// Working node pointer.\n\tMemChain_Type\t*oldnode;\t\t\t// Pointer to oldest block.\n\tunsigned int\toldtime;\t\t\t\t// Time of oldest block.\n\tunsigned int\tbasetime;\t\t\t// Time to mark our base time with.\n\tunsigned int\ttime;\t\t\t\t\t// basetime + time of node.\n\n\tif (!poolptr) return(NULL);\n\n\t/*\n\t**\tSweep through entire allocation chain to find\n\t**\tthe oldest referenced memory block.\n\t*/\n\toldnode = NULL;\n\toldtime = 0;\n\tnode = ((MemPool_Type*) poolptr)->UsedChain;\n\n  basetime = (unsigned int)(GetTickCount() >> 8);\n\n\twhile (node) {\n\n\t\t/*\n\t\t** Don't allow MEM_BLOCK_IN_USE or MEM_BLOCK_LOCKED to be returned.\n\t\t*/\n\t\tif (node->Time > MEM_BLOCK_LOCKED) {\n\n\t\t\t/*\n\t\t\t** Adjust time for wrap around (after about 5 hrs).\n\t\t\t** times less then the base time will wrap up high while\n\t\t\t** and times greater then base time will then be lower since\n\t\t\t** any time greater has been on the thing a long time.\n\t\t\t*/\n\t\t\ttime = node->Time - basetime ;\n\n\t\t\tif (time < oldtime || !oldnode) {\n\t\t\t\toldtime = time;\n\t\t\t\toldnode = node;\n\t\t\t}\n\t\t}\n\t\tnode = node->Next;\n\t}\n\n\t/*\n\t**\tReturn with the value that matches the pointer that\n\t**\twas allocated by the system previously.\n\t*/\n\tif (oldnode) {\n\t\toldnode++;\n\t}\n\treturn(oldnode);\n}\n\n\n/***************************************************************************\n * Mem_Free_Oldest -- Find and free the oldest memory block.               *\n *                                                                         *\n *    This routine is used to free the oldest memory block in the memory   *\n *    cache.  This routine is typcially used in order to create more room  *\n *    in the cache for a new allocation.                                   *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns with the node that it freed.  Although this node is    *\n *          is no longer valid, it may be used to mark that pointer as     *\n *          invalid in the main code.                                      *\n *                                                                         *\n * WARNINGS:   If this routine returns NULL, then no memory was freed.     *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Free_Oldest(void *poolptr)\n{\n\tMemChain_Type\t*node;\t\t// Copy of pointer to oldest node.\n\n\tif (!poolptr) return(NULL);\n\tnode = (MemChain *) Mem_Find_Oldest(poolptr);\n\tif (Mem_Free(poolptr, node)) {\n\t\treturn(node);\n\t}\n\treturn(NULL);\n}\n\n/***************************************************************************\n * MEM_POOL_SIZE -- Returns total amount of memory in pool.                *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  long total size of pool. i.e. largest possible allocation if   *\n *          no memory was allocated.                                       *\n *                                                                         *\n * WARNINGS: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Mem_Pool_Size(void *poolptr)\n{\n\tMemPool_Type\t*pool;\t\t\t// Memory pool control structure.\n\tlong\t\t\t\tmemtotal;\t\t// Total amount of memory free.\n\n\tif (!poolptr) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\tmemtotal = ((long)pool->TotalMem) << 4;\n\tmemtotal -= sizeof(MemChain_Type);\n\tmemtotal = __max(memtotal, (long)0);\n\treturn(memtotal);\n}\n\n/***************************************************************************\n * Mem_Avail -- Returns the amount of free memory available in the cache.  *\n *                                                                         *\n *    This routine examines the memory cache and returns the amount of     *\n *    free memory available.  This memory total MAY be fragmented but      *\n *    after Mem_Cleanup() is called, an allocation of the amount returned  *\n *    by this function is guaranteed.                                      *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns the largest allocation possible from the memory cache. *\n *                                                                         *\n * WARNINGS:   The value returned may represent the FRAGMENTED total       *\n *             amount of memory free in the cache.                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nlong Mem_Avail(void *poolptr)\n{\n\tMemPool_Type\t*pool;\t\t// Memory pool control structure.\n\tlong\t\t\t\tmemtotal;\t// Total amount of memory free.\n\n\tif (!poolptr) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\tmemtotal = ((long)pool->FreeMem) << 4;\n\tmemtotal -= sizeof(MemChain_Type);\n\t//memtotal -= sizeof(MemChain_Type) + 15;\n\tmemtotal = __max(memtotal, (long)0);\n\treturn(memtotal);\n}\n\n\n/***************************************************************************\n * MEM_LARGEST_AVAIL -- Largest free block available.                      *\n * \tThis routine examines the free node list to find the largest block   *\n *\t\tavailable.  User can Mem_Alloc() this return size successfully.      *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns largest allocation currently possible from the cache. \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Mem_Largest_Avail(void *poolptr)\n{\n\tMemChain_Type\t*node;\t\t\t// Pointer to current memory node.\n\tunsigned int\tsize;\n\tlong\t\t\t\ttruesize;\t\n\n\t/*\n\t** Make sure that it is a buffer.\n\t*/\n\tif (!poolptr) return(NULL);\n\n\t/*\n\t** Go through the entire free chain looking for the largest block.\n\t*/\n\tnode = ((MemPool_Type *)poolptr)->FreeChain;\n\tsize = 0;\n\twhile (node) {\n\n\t\t/*\n\t\t**\tFetch free memory chunk block and see if it is big enough.\n\t\t*/\n\t\tif (node->Size >= size) {\n\t\t\tsize = node->Size;\n\t\t}\n\t\tnode = node->Next;\n\t}\n\n\ttruesize = (long)size << 4;\n\ttruesize -= sizeof(MemChain_Type);\n\ttruesize = __max(truesize, 0L);\n\treturn (truesize);\n}\n\n\n/***************************************************************************\n * Mem_Cleanup -- Performs a garbage collection on the memory cache.       *\n *                                                                         *\n *    This routine is used to coalesce all adjacent free blocks of         *\n *    memory in the specified cache.  As a result, all previous pointers   *\n *    provided by Mem_Find() are invalidated.  This routine consumes a     *\n *    fair amount of time and should be called as infrequently as          *\n *    possible.                                                            *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine takes a significant amount of time!            *\n *             If there are locked block in memory, the pool may still     *\n *             be fragmented.                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Updated for low memory caches.                       *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid Mem_Cleanup(void *poolptr)\n{\n\tMemPool_Type\t*pool;  \t// Memory pool control structure.\n\tMemChain_Type\t*free,\t// Pointer to first free area.\n\t\t\t\t\t\t*cur;\t\t// Pointer to first used block that is after free.\n\tunsigned long\tsize;\n\tunsigned long\tfreesize;// Size of free heap at the end of the block.\n\n\tif (!poolptr) return;\n\n\t/*\n\t**\tFetch working copy of pool control structure.\n\t*/\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tBasic parameter and condition legality checks.  If the memory pool\n\t**\thas no free space, no free blocks, or no allocated blocks, then \n\t**\tmemory cleanup is unnecessary -- just exit.\n\t*/\n\tif (!pool->FreeMem || !pool->FreeChain || !pool->UsedChain) return;\n\n\tfreesize = pool->FreeMem;\n\tfree = pool->FreeChain;\n\tpool->FreeChain = NULL;\n\tcur = pool->UsedChain;\n\twhile (TRUE) {\n\n\t\t/*\n\t\t** Setup pointers so that free points to the first free block and cur\n\t\t** points to the next used block after the free block.\n\t\t*/\n\t\twhile (cur < free && cur) {\n\t \t\tcur = cur->Next;\n\t\t}\n\n\t\t// All used blocks are at the front of the free.  We are done.\n\t\tif (!cur) {\n\t \t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t** Do not allow a locked block to be moved.\n\t\t*/\n\t\tif (cur->Time == MEM_BLOCK_LOCKED) {\n\t\t\t/* \n\t\t\t** Figure the size of the new free block that we are creating.\n\t\t\t** Subtract off the total block size.\n\t\t\t** Add the node to the free list.\n\t\t\t*/\n\t\t\tsize = (char *) cur - (char  *) free;\n\t\t\tsize >>= 4;\n\t\t \tfreesize -= size;\n\t\t\tMemNode_Insert(pool, TRUE, free, (unsigned int) size, -1, FALSE);\n\n\t\t\t/*\n\t\t\t** Time to find a new free position to start working from.\n\t\t\t** Cur will be in the position just following.\n\t\t\t*/\n\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, (unsigned long)cur->Size << 4);\n\t\t\tcur = cur->Next;\n\t\t\twhile (free == cur) {\n\t\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, (unsigned long)cur->Size << 4);\n\t\t\t\tcur = cur->Next;\n\t\t\t}\n\n\t\t\t// All used blocks are at the front of the free.  We are done.\n\t\t\tif (!cur) {\n\t\t\t \tbreak;\n\t\t\t}\n\t\t} else {\n\n\t\t\t// Copy the block up.\n\t\t\tsize = (unsigned long)cur->Size << 4;\n\t\t\tMem_Copy(cur, free, size);\n\t\t\tcur = free;\n\n\t\t\t// Change pointers of surrounding blocks.\n\t\t\tif (cur->Next) {\n\t\t \t\tcur->Next->Prev = cur;\n\t\t\t}\n\t\t\tif (cur->Prev) {\n\t\t \t\tcur->Prev->Next = cur;\n\t\t\t} else {\n\t\t \t\tpool->UsedChain = cur;\n\t\t\t}\n\n\t\t\t// Change to next new free area.\n\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, size);\n\t\t}\n\t}\n\n\t/*\n\t**\tNow build the single free chunk.\n\t*/\n\tMemNode_Insert(pool, TRUE, free, freesize, -1, FALSE);\n}\n\n\n/***************************************************************************\n * MemNode_Unlink -- Unlinks a node from the cache.                        *\n *                                                                         *\n *    A private routine the actually unlinks a memory block from the       *\n *    memory cache.  It doesn't perform a complete update of the memory    *\n *    cache.                                                               *\n *                                                                         *\n * INPUT:   pool     -- Pointer to the memory cache header (copy in real   *\n *                      memory).                                           *\n *                                                                         *\n *          freechain-- Is the block part of the free memory chain?        *\n *                                                                         *\n *          node     -- Pointer to the node that will be unlinked.         *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine doesn't update memory totals.  It is a support *\n *             function.                                                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nPRIVATE void MemNode_Unlink(MemPool_Type *pool, int freechain, MemChain_Type *node)\n{\n\tMemChain_Type\t*other; \t\t// Copy of node data to unlink.\n\tMemChain_Type\t**chain;\t\t// A pointer to one of the chains pointer.\n\n\t/*\n\t**\tCheck for parameter validity.\n\t*/\n\tif (!pool || !node) return;\n\t\n\t/*\n\t**\tSetup working pointer for the particular chain desired.\n\t*/\t\n\tif (freechain) {\n\t\tchain = &pool->FreeChain;\n\t} else {\n\t\tchain = &pool->UsedChain;\n\t}\n\t\n\t/*\n\t**\tMake adjustments to the previous node.  If the pointer\n\t**\tto the previous node is NULL then this indicates the\n\t**\tfirst node in the list and thus the chain pointer needs\n\t**\tto be updated instead.\n\t*/\n\tif (node->Prev) {\n\t\tother = node->Prev;\n\t\tother->Next = node->Next;\n\t} else {\n\t\t*chain = node->Next;\n\t}\n\n\tif (node->Next) {\n\t\tother = node->Next;\n\t\tother->Prev = node->Prev;\n\t}\n}\n\n\n/***************************************************************************\n * MemNode_Insert -- Inserts a node into a cache chain.                    *\n *                                                                         *\n *    This routine is used to add a node to a cache chain.  Since nodes    *\n *    do not contain double links, they must be placed in sequence.        *\n *                                                                         *\n * INPUT:   pool     -- Pointer to memory pool (must be in real memory).   *\n *                                                                         *\n *          freechain-- Is the node to be inserted into the free chain?    *\n *                                                                         *\n *          node     -- Pointer to the node to insert.                     *\n *                                                                         *\n *          size     -- Size of the memory block (in paragraphs).          *\n *                                                                         *\n *          id       -- The ID number to associate with this block.        *\n *                                                                         *\n *          merge    -- Merge inserted block with adjacent blocks.         *\n *                                                                         *\n * OUTPUT:  return                                                         *\n *                                                                         *\n * WARNINGS:   This is a support routine.                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void MemNode_Insert(MemPool_Type *pool, int freechain, MemChain_Type *node, unsigned int size, unsigned long id, int merge)\n{\n\tMemChain_Type \t**chain;\t\t\t// Pointer to chain that will be linked.\n\tMemChain_Type \t*prev,\t\t\t// Successor node pointer.\n\t\t\t\t\t\t*next;\t\t\t// Predecessor node pointer.\n\tint\t\t\t\tdoit=TRUE;\t\t// Link the node into the list.\n\n\n\t/*\n\t**\tDetermine if the parameters are valid.\n\t*/\n\tif (!pool || !node || !size) return;\n\n\t/*\n\t**\tSetup working pointer for the particular chain desired.\n\t*/\t\n\tif (freechain) {\n\t\tchain = &pool->FreeChain;\n\t} else {\n\t\tchain = &pool->UsedChain;\n\t}\n\n\t/*\n\t**\tHandle the \"no node in list\" condition (easiest).\n\t*/\n\tif (!*chain) {\n\t\tnode->Next = NULL;\n\t\tnode->Prev = NULL;\n\t\tnode->Size = size;\n\t\tnode->Time = (unsigned short)(GetTickCount() >> 8);\n\t\tnode->ID = id;\n\t\t*chain = node;\n\t\treturn;\n\t}\n\n\t/*\n\t**\tSweep through the memory chain looking for a likely spot\n\t**\tto insert the new node.  It will stop with \"next\" pointing\n\t**\tto the node to come after the block to be inserted and \"prev\"\n\t** will point to the node right before.\n\t*/\n\tprev = NULL;\n\tnext = *chain;\n\twhile (next && (next < node)) {\n\n\t\t/*\n\t\t**\tMove up the memory chain.\n\t\t*/\n\t\tprev = next;\n\t\tnext = next->Next;\n\t}\n\n\t/*\n\t**\tCoallescing of adjacent blocks (if requested).\n\t*/\n\tif (merge) {\n\t\t\n\t\t/*\n\t\t**\tIf the previous block is touching the block to insert\n\t\t**\tthen merely adjust the size of the previous block and\n\t\t**\tthat is all that is necessary.\n\t\t*/\n\t\tif (prev) {\n\t\t\tif (((char *)prev + ((long)prev->Size << 4)) == ((char *) node)) {\n\t\t\t\tprev->Size += size;\n\t\t\t\tsize = prev->Size;\n\t\t\t\tnode = prev;\n\t\t\t\tprev = prev->Prev;\n\t\t\t\tdoit = FALSE;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf the following block is touching the block to insert\n\t\t**\tthen remove the following block and increase the size of\n\t\t**\tthe original insertion block by the size of the other\n\t\t**\tblock.\n\t\t*/\n\t\tif (next) {\n\t\t\tif (((char *)node + ((long)size << 4)) == (char *)next) {\n\t\t\t\t\n\t\t\t\tif (!doit) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the node was already merged with the previous block\n\t\t\t\t\t**\tthen merely increase the previous block's size\n\t\t\t\t\t**\tand adjust it's next pointer appropriately.\n\t\t\t\t\t*/\n\t\t\t\t\tnode->Size += next->Size;\n\t\t\t\t\tnode->Next = next->Next;\n\t\t\t\t\tnext = next->Next;\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIncrease the size of the current block and adjust\n\t\t\t\t\t**\tthe \"next\" pointer so that it gets fixed up\n\t\t\t\t\t**\taccordingly.\n\t\t\t\t\t*/\n\t\t\t\t\tsize += next->Size;\n\t\t\t\t\tnext = next->Next;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n#if DEBUG_FILL\n\tif (doit) {\n\t\tmemset(node + 1, 0xFF, (size - 1) << 4);\n\t} else {\n\t\tmemset(node + 1, 0xFF, (node->Size - 1) << 4);\n\t}\n#endif\n\n\t/*\n\t**\tFixup the node pointers.\n\t*/\n\tif (prev) {\n\t\tprev->Next = node;\n\t}else{\n\t\t*chain = node;\n\t}\n\n\tif (next) {\n\t \tnext->Prev = node;\n\t}\n\n\tif (doit) {\n\t\tnode->Prev = prev;\n\t\tnode->Next = next;\n\t\tnode->Size = size;\n\t\tnode->Time = (unsigned short)(GetTickCount() >> 8);\n\t\tnode->ID = id;\n\t}\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/MEM/MSVC/MEM.MAK",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Static Library\" 0x0104\n\n!IF \"$(CFG)\" == \"\"\nCFG=Win32 Debug\n!MESSAGE No configuration specified.  Defaulting to Win32 Debug.\n!ENDIF \n\n!IF \"$(CFG)\" != \"Win32 Release\" && \"$(CFG)\" != \"Win32 Debug\"\n!MESSAGE Invalid configuration \"$(CFG)\" specified.\n!MESSAGE You can specify a configuration when running NMAKE on this makefile\n!MESSAGE by defining the macro CFG on the command line.  For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"mem.mak\" CFG=\"Win32 Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"Win32 Release\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \"Win32 Debug\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \n!ERROR An invalid configuration is specified.\n!ENDIF \n\n################################################################################\n# Begin Project\n# PROP Target_Last_Scanned \"Win32 Debug\"\nCPP=cl.exe\n\n!IF  \"$(CFG)\" == \"Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"WinRel\"\n# PROP BASE Intermediate_Dir \"WinRel\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"WinRel\"\n# PROP Intermediate_Dir \"WinRel\"\nOUTDIR=.\\WinRel\nINTDIR=.\\WinRel\n\nALL : $(OUTDIR)/mem.lib $(OUTDIR)/mem.bsc\n\n$(OUTDIR) : \n    if not exist $(OUTDIR)/nul mkdir $(OUTDIR)\n\n# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /FR /c\n# ADD CPP /nologo /W3 /GX /YX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /FR /c\nCPP_PROJ=/nologo /W3 /GX /YX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\"\\\n /FR$(INTDIR)/ /Fp$(OUTDIR)/\"mem.pch\" /Fo$(INTDIR)/ /c \nCPP_OBJS=.\\WinRel/\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nBSC32_FLAGS=/nologo /o$(OUTDIR)/\"mem.bsc\" \nBSC32_SBRS= \\\n\t$(INTDIR)/NEWDEL.SBR \\\n\t$(INTDIR)/ALLOC.SBR \\\n\t$(INTDIR)/MEM.SBR\n\n$(OUTDIR)/mem.bsc : $(OUTDIR)  $(BSC32_SBRS)\n    $(BSC32) @<<\n  $(BSC32_FLAGS) $(BSC32_SBRS)\n<<\n\nLIB32=lib.exe\n# ADD BASE LIB32 /NOLOGO\n# ADD LIB32 /NOLOGO\nLIB32_FLAGS=/NOLOGO /OUT:$(OUTDIR)\\\"mem.lib\" \nDEF_FLAGS=\nDEF_FILE=\nLIB32_OBJS= \\\n\t$(INTDIR)/NEWDEL.OBJ \\\n\t$(INTDIR)/ALLOC.OBJ \\\n\t$(INTDIR)/MEM.OBJ \\\n\t.\\MEM_COPY.OBJ\n\n$(OUTDIR)/mem.lib : $(OUTDIR)  $(DEF_FILE) $(LIB32_OBJS)\n    $(LIB32) @<<\n  $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)\n<<\n\n!ELSEIF  \"$(CFG)\" == \"Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"WinDebug\"\n# PROP BASE Intermediate_Dir \"WinDebug\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"WinDebug\"\n# PROP Intermediate_Dir \"WinDebug\"\nOUTDIR=.\\WinDebug\nINTDIR=.\\WinDebug\n\nALL : $(OUTDIR)/mem.lib $(OUTDIR)/mem.bsc\n\n$(OUTDIR) : \n    if not exist $(OUTDIR)/nul mkdir $(OUTDIR)\n\n# ADD BASE CPP /nologo /W3 /GX /Z7 /YX /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /FR /c\n# ADD CPP /nologo /W3 /GX /Z7 /YX /Od /I \"c:\\wwlib32\\include\" /D \"_DEBUG\" /D \"_WINDOWS\" /FR /c\nCPP_PROJ=/nologo /W3 /GX /Z7 /YX /Od /I \"c:\\wwlib32\\include\" /D \"_DEBUG\" /D\\\n \"_WINDOWS\" /FR$(INTDIR)/ /Fp$(OUTDIR)/\"mem.pch\" /Fo$(INTDIR)/ /c \nCPP_OBJS=.\\WinDebug/\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nBSC32_FLAGS=/nologo /o$(OUTDIR)/\"mem.bsc\" \nBSC32_SBRS= \\\n\t$(INTDIR)/NEWDEL.SBR \\\n\t$(INTDIR)/ALLOC.SBR \\\n\t$(INTDIR)/MEM.SBR\n\n$(OUTDIR)/mem.bsc : $(OUTDIR)  $(BSC32_SBRS)\n    $(BSC32) @<<\n  $(BSC32_FLAGS) $(BSC32_SBRS)\n<<\n\nLIB32=lib.exe\n# ADD BASE LIB32 /NOLOGO\n# ADD LIB32 /NOLOGO\nLIB32_FLAGS=/NOLOGO /OUT:$(OUTDIR)\\\"mem.lib\" \nDEF_FLAGS=\nDEF_FILE=\nLIB32_OBJS= \\\n\t$(INTDIR)/NEWDEL.OBJ \\\n\t$(INTDIR)/ALLOC.OBJ \\\n\t$(INTDIR)/MEM.OBJ \\\n\t.\\MEM_COPY.OBJ\n\n$(OUTDIR)/mem.lib : $(OUTDIR)  $(DEF_FILE) $(LIB32_OBJS)\n    $(LIB32) @<<\n  $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)\n<<\n\n!ENDIF \n\n.c{$(CPP_OBJS)}.obj:\n   $(CPP) $(CPP_PROJ) $<  \n\n.cpp{$(CPP_OBJS)}.obj:\n   $(CPP) $(CPP_PROJ) $<  \n\n.cxx{$(CPP_OBJS)}.obj:\n   $(CPP) $(CPP_PROJ) $<  \n\n################################################################################\n# Begin Group \"Source Files\"\n\n################################################################################\n# Begin Source File\n\nSOURCE=.\\MEM_COPY.ASM\n# End Source File\n################################################################################\n# Begin Source File\n\nSOURCE=.\\NEWDEL.CPP\nDEP_NEWDE=\\\n\t.\\WWMEM.H\\\n\t\\wwlib32\\include\\wwstd.h\\\n\t.\\MEMFLAG.H\n\n$(INTDIR)/NEWDEL.OBJ :  $(SOURCE)  $(DEP_NEWDE) $(INTDIR)\n\n# End Source File\n################################################################################\n# Begin Source File\n\nSOURCE=.\\ALLOC.CPP\nDEP_ALLOC=\\\n\t.\\WWMEM.H\\\n\t\\wwlib32\\include\\mono.h\\\n\t\\wwlib32\\include\\wwstd.h\\\n\t.\\MEMFLAG.H\n\n$(INTDIR)/ALLOC.OBJ :  $(SOURCE)  $(DEP_ALLOC) $(INTDIR)\n\n# End Source File\n################################################################################\n# Begin Source File\n\nSOURCE=.\\MEM.CPP\nDEP_MEM_C=\\\n\t\\wwlib32\\include\\wwstd.h\\\n\t.\\WWMEM.H\\\n\t\\wwlib32\\include\\timer.h\\\n\t.\\MEMFLAG.H\n\n$(INTDIR)/MEM.OBJ :  $(SOURCE)  $(DEP_MEM_C) $(INTDIR)\n\n# End Source File\n################################################################################\n# Begin Source File\n\nSOURCE=.\\MEM_COPY.OBJ\n# End Source File\n# End Group\n# End Project\n################################################################################\n"
  },
  {
    "path": "WIN32LIB/MEM/MSVC/MEMFLAG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory System                            *\n *                                                                         *\n *                    File Name : MEMFLAG.H                                *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : April 4, 1994                            *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef MEMFLAG_H\n#define MEMFLAG_H\n// Memory Flags\n/*\n**\tMemory allocation flags.  These are the flags that are passed into Alloc\n**\tin order to control the type of memory allocated.\n*/\ntypedef enum {\n\tMEM_NORMAL = 0x0000,\t\t// Default memory (normal).\n\tMEM_NEW\t  = 0x0001,\t\t// Called by the operator new and was overloaded.\n\tMEM_CLEAR  = 0x0002,\t\t// Clear memory before returning.\n\tMEM_REAL   = 0x0004,\t\t// Clear memory before returning.\n\tMEM_TEMP   = 0x0008,\t\t// Clear memory before returning.\n\tMEM_LOCK   = 0x0010,\t\t// Lock the memory that we allocated\n} MemoryFlagType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: ALLOC.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid\t*Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags);\nvoid\tFree(void const *pointer);\nvoid\tDPMI_Lock(VOID const *ptr, long const size);\nvoid\tDPMI_Unlock(void const *ptr, long const size);\nvoid\t*Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes);\nlong\tRam_Free(MemoryFlagType flag);\nlong\tHeap_Size(MemoryFlagType flag);\nlong\tTotal_Ram_Free(MemoryFlagType flag);\n\n\ninline void * operator new(size_t size, MemoryFlagType flag) \n{\n\treturn(Alloc(size, flag));\n}\n//inline void * operator new[] (size_t size, MemoryFlagType flag)\n//{\n//\treturn(Alloc(size, flag));\n//}\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MEM_COPY.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\textern void Mem_Copy(void *source, void *dest, unsigned long bytes_to_copy);\n\n#ifdef __cplusplus\n}\n#endif\n\n\ninline void *Add_Long_To_Pointer(void const *ptr, long size) \n{\n \treturn ((void *) ( (char const *) ptr + size));\n}\n\nextern void (*Memory_Error)(void);\n\nextern unsigned long MinRam;\t\t// Record of least memory at worst case.\nextern unsigned long MaxRam;\t\t// Record of total allocated at worst case.\n\n\n#endif\n\n\n"
  },
  {
    "path": "WIN32LIB/MEM/MSVC/MEM_COPY.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : MEM_COPY.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott Bowen\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : September 8, 1994\t[IML]              *\n;*                  Ported to watcom c32 : 01/03/96     [JRJ]                                                                        *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Mem_Copy -- Copies from one pointer to another.                       *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nLOCALS ??\n\n\n;******************************************************************************\n; Much testing was done to determine that only when there are 14 or more bytes\n; being copied does it speed the time it takes to do copies in this algorithm.\n; For this reason and because 1 and 2 byte copies crash, is the special case\n; used.  SKB 4/21/94.  Tested on 486 66mhz.\nOPTIMAL_BYTE_COPY\tequ\t14\n\n\n;******************************************************************************\n; External declares so these functions can be called\n;\nGLOBAL \tC Mem_Copy\t: NEAR\nGLOBAL  C Largest_Mem_Block : near\n\nCODESEG\n\n\n;***************************************************************************\n;* MEM_COPY -- Copies from one pointer to another.                         *\n;* This routine copies bytes from source to dest.  It takes care of\t   *\n;* overlapped memory, and unsigned long copies.\t\t\t\t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/18/1994 SKB : Created.                                             *\n;*=========================================================================*\n; void Mem_Copy(void *source, void *dest, unsigned long bytes_to_copy);\n\n\nPROC Mem_Copy \tC near\n\tUSES\tecx , esi , edi , ebx\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tbytes:DWORD\n\n;********************************* Setup ******************************************\n\tcld\n\tmov\tesi,[source]\n\tmov\tedi,[dest]\n\tmov\tecx,[bytes]\t; get number of bytes to copy.\n\n     ; check pointers for singularities\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tje\t??done\t\t; No sence in copying the same pointer.\n\tor\tesi,0\n\tjz\t??done\n\tor\tedi,0\n\tjz\t??done\n\n\tcmp\tecx,OPTIMAL_BYTE_COPY  ; see notes above about equate.\n\tjge\t??normal      \t       ; If >= MAX(2,OPTIMAL_BYTE_COPY), do normal dword copy.\n\n;******************************** Special case <= 2 *******************************\n;\n; This section must be called for bytes <= 2 since the other case will crash.  It\n; optionally uses OPTIMAL_BYTE_COPY for the cut off point.  This is because after\n; extensive testing, it was proved that only at that point (14 or more bytes) does\n; it become quicker to use the dword copy method.\n\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tjge\t??do_move\t; if source greater do forward copy.\n\tlea\tesi,[esi+ecx-1]\n\tstd\t\t\t; Opps, wrong, force the pointers to decrement.\n\tlea\tedi,[edi+ecx-1]\n??do_move:\n\trep\tmovsb\t\t; move the one or two bytes.\n\tcld\n??done:\n\tret\n\n;************************** back or forth, that is the question *******************\n\n??normal:\n\tmov\tebx,ecx\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tjge\t??forward\t; if source greater do forward copy.\n\n;********************************* Backward ***************************************\n??backward:\n\tlea\tecx,[edi+ebx]\n\tstd\n\tlea\tedi,[edi+ebx-1]\n\tand\tecx,3\t\t; Get non aligned bytes.\n\tlea\tesi,[esi+ebx-1]\n\tsub\tebx,ecx\t\t; remove that from the total size to be copied later.\n\trep\tmovsb\t\t; do the copy.\n\tsub\tesi,3\n\tmov\tecx,ebx\t\t; Get number of bytes left.\n \tsub\tedi,3\n\tshr\tecx,2\t\t; Do 4 bytes at a time.\n\trep\tmovsd\t\t; do the dword copy.\n\tmov\tecx,ebx\n\tadd\tesi,3\n\tadd\tedi,3\n\tand\tecx,03h\n\trep\tmovsb\t\t; finnish the remaining bytes.\n\tcld\n\tret\n\n;********************************* Forward ***************************************\n??forward:\n\tcld\n\tmov\tecx,edi\t\t; get destination pointer.\n\tneg\tecx\n\tand\tecx,3\t\t; Get non aligned bytes.\n\tsub\tebx,ecx\t\t; remove that from the total size to be copied later.\n\trep\tmovsb\t\t; do the copy.\n\tmov\tecx,ebx\t\t; Get number of bytes left.\n\tshr\tecx,2\t\t; Do 4 bytes at a time.\n\trep\tmovsd\t\t; do the dword copy.\n\tmov\tecx, ebx\n\tand\tecx,03h\n\trep\tmovsb\t\t; finnish the remaining bytes.\n\tret\n\nENDP\tMem_Copy\n\nPROC Largest_Mem_Block \tC near\n\tuses\tesi , edi , ebx , ecx , edx\n\tlocal\tmem_struct : dword : 16\n\n\tmov\teax , 0500h\n\tlea\tedi , [ mem_struct ]\n\tint\t31h\n\tmov\teax , [ mem_struct ]\n\n\tret\nENDP Largest_Mem_Block\n\nEND\n\n\n\u001a"
  },
  {
    "path": "WIN32LIB/MEM/MSVC/NEWDEL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory system.                           *\n *                                                                         *\n *                    File Name : NEWDEL.CPP                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : June 21, 1994                            *\n *                                                                         *\n *                  Last Update : October 20, 1994   [SKB]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   operator NEW -- Overides the global new function.                     *\n *   operator delete -- Overides the global delete function.               *\n *   operator NEW[] -- Overides the array version of new.                  *\n *   operator delete[] -- Overides the array version of delete[]           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwmem.h\"\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * OPERATOR NEW -- Overides the global new function.                       *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid * operator new(size_t size) \n{\n\treturn (Alloc((unsigned long) size, MEM_NEW));\n}\n\n\n/***************************************************************************\n * OPERATOR NEW[] -- Overides the array version of new.                    *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\n//void * operator new[](size_t size) \n//{\n//\treturn (Alloc((unsigned long) size, MEM_NEW));\n//}\n\n \n\n/***************************************************************************\n * OPERATOR DELETE -- Overides the global delete function.                 *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid operator delete(void *ptr) \n{\n\tFree(ptr);\n}\n\n/***************************************************************************\n * OPERATOR DELETE[] -- Overides the array version of delete[]           \t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/20/1994 SKB : Created.                                             *\n *=========================================================================*/\n//void operator delete[](void *ptr) \n//{\n//\tFree(ptr);\n//}\n\n\n\n"
  },
  {
    "path": "WIN32LIB/MEM/MSVC/WWMEM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory System                            *\n *                                                                         *\n *                    File Name : MEM.H                                    *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : April 4, 1994                            *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWMEM_H\n#define WWMEM_H\n\n#include \"wwstd.h\"\n#include \"new.h\"\n#include \"memflag.h\"\n\n// Defines\n//==============\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MEM.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint  Mem_Init(void *buffer, long size);\nvoid *Mem_Alloc(void *poolptr, long lsize, unsigned long id);\nint  Mem_Free(void *poolptr, void *buffer);\nvoid Mem_Reference(void *node);\nvoid Mem_Lock_Block(void *node);\nvoid Mem_In_Use(void *node);\nvoid *Mem_Find(void *poolptr, unsigned long id);\nunsigned long Mem_Get_ID(void *node);\nvoid *Mem_Find_Oldest(void *poolptr);\nvoid *Mem_Free_Oldest(void *poolptr);\nlong Mem_Pool_Size(void *poolptr);\nlong Mem_Avail(void *poolptr);\nlong Mem_Largest_Avail(void *poolptr);\nvoid Mem_Cleanup(void *poolptr);\n\n\n#endif\n\u001a\n"
  },
  {
    "path": "WIN32LIB/MEM/MSVC/WWMEM.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Memory System                            *\n;*                                                                         *\n;*                    File Name : WWMEM.INC                                *\n;*                                                                         *\n;*                   Programmer : Ian M. Leslie                            *\n;*                                                                         *\n;*                   Start Date : August 11, 1994                          *\n;*                                                                         *\n;*                  Last Update : August 17, 1994   [IML]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nMEM_NORMAL EQU 0000h\t\t; Default memory (normal).\nMEM_NEW\t   EQU 0001h\t\t; Called by the operator new and was overloaded.\nMEM_CLEAR  EQU 0002h \t\t;\n\nGLOBAL\t\t@Alloc$qul14MemoryFlagType:PROC\nGLOBAL\t\t@Free$qpv:PROC\n"
  },
  {
    "path": "WIN32LIB/MEM/NEWDEL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory system.                           *\n *                                                                         *\n *                    File Name : NEWDEL.CPP                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : June 21, 1994                            *\n *                                                                         *\n *                  Last Update : October 20, 1994   [SKB]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   operator NEW -- Overides the global new function.                     *\n *   operator delete -- Overides the global delete function.               *\n *   operator NEW[] -- Overides the array version of new.                  *\n *   operator delete[] -- Overides the array version of delete[]           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwmem.h\"\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * OPERATOR NEW -- Overides the global new function.                       *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid * operator new(size_t size) \n{\n\treturn (Alloc((unsigned long) size, MEM_NEW));\n}\n\n\n/***************************************************************************\n * OPERATOR NEW[] -- Overides the array version of new.                    *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid * operator new[](size_t size) \n{\n\treturn (Alloc((unsigned long) size, MEM_NEW));\n}\n \n\n/***************************************************************************\n * OPERATOR DELETE -- Overides the global delete function.                 *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid operator delete(void *ptr) \n{\n\tFree(ptr);\n}\n\n/***************************************************************************\n * OPERATOR DELETE[] -- Overides the array version of delete[]           \t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/20/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid operator delete[](void *ptr) \n{\n\tFree(ptr);\n}\n\n\n\n"
  },
  {
    "path": "WIN32LIB/MEM/OLDMEM/ALLOC.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : ALLOC.CPP                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : February 1, 1992                         *\n *                                                                         *\n *                  Last Update : March 9, 1995 [JLB]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Alloc -- Allocates system RAM.                                        *\n *   Ram_Free -- Determines the largest free chunk of RAM.                 *\n *   Free -- Free an Alloc'ed block of RAM.                                *\n *   Resize_Alloc -- Change the size of an allocated block.                *\n *   Heap_Size -- Size of the heap we have.                                *\n *   Total_Ram_Free -- Total amount of free RAM.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <malloc.h>\n#include <string.h>\n#include <stdlib.h>\n#include <dos.h>\n#include <bios.h>\n\n\n#ifndef WWMEM_H\n#include \"wwmem.h\"\n#endif\n\n\nextern \"C\" unsigned long Largest_Mem_Block ( void ) ;\n\n/*\n** Define the equates necessary to call a DPMI interrupt.\n*/\n#define\tDPMI_INT\t\t\t\t\t\t\t\t\t0x0031\n#define\tDPMI_LOCK_MEM\t\t\t\t\t\t\t0x0600\n#define\tDPMI_UNLOCK_MEM\t\t\t\t\t\t0x0601\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\nunsigned long MinRam=0L;\t\t// Record of least memory at worst case.\nunsigned long MaxRam=0L;\t\t// Record of total allocated at worst case.\nstatic unsigned long TotalRam = 0L;\nstatic unsigned long Memory_Calls = 0L;\n\t\t\nvoid (*Memory_Error)(void) = NULL;\n\n/***************************************************************************\n * DPMI_LOCK -- handles locking a block of DPMI memory                     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n#include\"mono.h\"\nvoid DPMI_Lock(VOID const *ptr, long const size)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\n\t/*\n\t** Lock memory\n\t** AX = 0x600\n\t** BX:CX = starting linear address of memory to lock\n\t** SI:DI = size of region to lock (in bytes)\n\t** - If Failure, carry flag is set.\n\t*/\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_LOCK_MEM;\n\tregs.x.ebx = ((long)ptr & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000ffff);\n\tregs.x.esi = ((long)size & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n//\tif (regs.x.cflag) {\n//\t}\n#if(0)\n\tchar *temp = (char *)ptr;\n\tchar hold;\n\tfor (int lp = 0; lp < size; lp += 2048) {\n\t\thold = *temp;\n\t\ttemp += 2048;\n\t}\n#endif\n\n}\n\n/***************************************************************************\n * DPMI_UNLOCK -- Handles unlocking a locked block of DPMI                 *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid DPMI_Unlock(void const *ptr, long const size)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\n\t/*\n\t** Unlock the memory\n\t*/\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_UNLOCK_MEM;\t\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = ((long)ptr & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000ffff);\n\tregs.x.esi = ((long)size & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n//\tif (regs.x.cflag) {\n//\t}\n\n}\n\n/***************************************************************************\n * Alloc -- Allocates system RAM.                                          *\n *                                                                         *\n *    This is the basic RAM allocation function.  It is used for all       *\n *    memory allocations needed by the system or the main program.         *\n *                                                                         *\n * INPUT:   bytes_to_alloc -- LONG value of the number of bytes to alloc.  *\n *                                                                         *\n *          flags          -- Memory allocation control flags.             *\n *             MEM_NORMAL: No special flags.                               *\n *             MEM_CLEAR:  Zero out memory block.                        \t*\n *             MEM_NEW:\t\tCalled by a new.                                *\n *                                                                         *\n * OUTPUT:  Returns with pointer to allocated block.  If NULL was returned *\n *          it indicates a failure to allocate.  Note: NULL will never be  *\n *          returned if the standard library allocation error routine is   *\n *          used.                                                          *\n *                                                                         *\n * WARNINGS:   If you replace the standard memory allocation error routine *\n *             and make it so that Alloc CAN return with a NULL, be sure   *\n *             and check for this in your code.                            *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Documented.                                          *\n *   08/09/1993 JLB : Updated with EMS memory support.                     *\n *   04/28/1994 JAW : Updated to 32bit Protected mode.                     *\n *   03/09/1995 JLB : Fixed                                                * \n *=========================================================================*/\nvoid *Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags)\n{\n\tunion REGS\t\tregs ;\n\tstruct SREGS \tsregs ;\n\tunsigned char *retval=NULL;\t// Pointer to allocated block.\n\tunsigned long\toriginal_size;\t// Original allocation size.\n\tunsigned long\tbytesfree;\t\t// Number of free bytes.\n\tlong \t\t\t\t*longptr=NULL;\t// Pointer used to store selector\n\n\t/* \n\t** Save the original allocated space size so that we can clear the\n\t** exact amount of RAM if they specified MEM_CLEAR.\n\t*/\n\toriginal_size = bytes_to_alloc;\n\n\t/*\n\t** Reserve one byte for the header of the memory we allocated.\n\t** We will store the flags variable there for later use.\n\t*/\n\tbytes_to_alloc += (flags & MEM_LOCK) ? 5 : 1;\n\n\t/*\n\t**\tInitialize the total ram available value.\n\t*/\n\tif (!TotalRam) {\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\t}\n\n\n\t// Try to allocate the memory out of the protected mode memory\n\t// chain if we did not require a real mode allocation.  If this \n\t// fails we will have to try to allocate it out of real mode memory.\n\t// Real mode memory is a last resort because some types of applications\n\t// require real mode memory.\n\tif (!(flags & MEM_REAL)) {\n\t\tretval = (unsigned char*)malloc(bytes_to_alloc);\n\t}\n\n\t// Try to allocate the memory out of the real mode memory using DPMI\n\t// service 0x100.  Note that retval will be null if we are requesting\n\t// real mode memory so that we do not have to explicitly check for the\n\t// real mode flag.  Remember we need to reserve room for the dos \n\t// selector value at the beginning of our allocated block so rather than\n\t// adding fifteen and rounding, we need to add 19 and round.\n\tif (!retval) {\n\t\tflags = (MemoryFlagType)(flags | MEM_REAL);\n\t\tregs.x.eax = 0x100;\n\t\tregs.x.ebx = (bytes_to_alloc + 19) >> 4;\n\t\tif (regs.x.ebx & 0xFFFF0000) {\n\t\t\tretval = NULL;\n\t\t} else {\n\t\t\tsegread ( & sregs ) ;\n\t\t\tint386x ( 0x31 , & regs, & regs , & sregs\t) ;\n\t\t\tif (regs.x.cflag)\n\t\t\t\tretval = NULL;\n\t\t\telse {\n\t\t\t\tlongptr\t\t= (long *)(((regs.x.eax & 0xFFFF) << 4)+ 1);\n\t\t\t\t*longptr++\t= regs.x.edx & 0xFFFF;\n\t\t\t\tretval\t\t= (unsigned char *)longptr;\n\t\t\t}\n\t\t}\n\t}\n\n\t// If the alloc failed then we need to signify a memory error.\n\tif (retval == NULL) {\n\t\tif(Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\t\t\n\t}\n\n\t// If the memory needs to be DPMI locked then we should store the\n\t// original size in the header before we store the flags.\n\tif (flags & MEM_LOCK) {\n\t\tlongptr\t\t= (long *)retval;\n\t\t*longptr++\t= original_size;\n\t\tretval\t\t= (unsigned char *)longptr;\n\t}\n\n\n\t// Now that we know the alloc was sucessful (and for an extra byte\n\t// more than the user wanted) we need to stick in the memory flags.\n\t*retval++ \t\t= flags;\n\n\t// If the memory needed to be DPMI locked then set it up so it\n\t// is locked.\n\tif (flags & MEM_LOCK) {\n\t\tDPMI_Lock(retval, original_size);\n\t\t\n\t}\n\n\n\t/* Clear the space if they wanted it clear */\n\n\tif (flags & MEM_CLEAR) {\n\t\tunsigned char\t*ptr;\t\t// Working memory block pointer.\n\n\t\tptr = retval;\n\t\tmemset(ptr, '\\0', original_size);\n\t}\n\n\tbytesfree = Total_Ram_Free(MEM_NORMAL);\n\tif (bytesfree < MinRam) {\n\t\tMinRam = bytesfree;\n\t}\n\tif (TotalRam-bytesfree > MaxRam) {\n\t\tMaxRam = TotalRam-bytesfree;\n\t}\n\n\tMemory_Calls++;\n\n\treturn(retval);\n}\n\n\n/***************************************************************************\n * Free -- Free an Alloc'ed block of RAM.                                  *\n *                                                                         *\n * FUNCTION:                                                               *\n *                                                                         *\n * INPUT:       A pointer to a block of RAM from Alloc.                    *\n *                                                                         *\n * OUTPUT:      None.                                                      *\n *                                                                         *\n * WARNINGS:    Don't use this for an Alloc_Block'ed RAM block.            *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/25/1990     : Created.                                             *\n ***************************************************************************/\nvoid Free(void const *pointer)\n{\n\tunion REGS\t\tregs ;\n\tstruct SREGS \tsregs ;\n\n\n\tif (pointer) {\n\t\t/*\n\t\t** Get a pointer to the flags that we stored off.\n\t\t*/\n\t\tchar *byteptr\t= ((char *)pointer) - 1;\n\n\t\t/*\n\t\t** Check to see if this was locked me and if it was unlock it.\n\t\t*/\n\t\tif (*byteptr & MEM_LOCK) {\n\t\t\tlong *longptr = ((long *)byteptr) - 1;\n\t\t\tDPMI_Unlock(pointer, *longptr);\n\t\t\tpointer = (void *)longptr;\n\t\t} else\n\t\t\tpointer = (void *)byteptr;\n\t\t\n\n\t\t// If the pointer is a real mode pointer than it will point to the\n\t\t// first megabyte of system memory.  If it does than we need to \n\t\t// use DPMI to free it.\n\t\tif (*byteptr & MEM_REAL) {\n\t\t\tregs.x.eax\t= 0x101;\n\t\t\tregs.x.edx\t= *(((long *)pointer) - 1);\n\t\t\tsegread ( & sregs ) ;\n\t\t\tint386x(0x31, &regs, &regs, &sregs);\n\t\t} else {\n\t\t\tfree((void *)pointer);\n\t\t}\n\t\tMemory_Calls--;\n\t}\n}\n\n\n/***************************************************************************\n * Resize_Alloc -- Change the size of an allocated block.                  *\n *                                                                         *\n *    This routine will take a previously allocated block and change its   *\n *    size without unnecessarily altering its contents.                    *\n *                                                                         *\n * INPUT:   pointer  -- Pointer to the original memory allocation.         *\n *                                                                         *\n *          new_size -- Size in bytes that it will be converted to.        *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the new allocation.                  *\n *                                                                         *\n * WARNINGS:   ???                                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/01/1992 JLB : Commented.                                           *\n *=========================================================================*/\nvoid *Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes)\n{\n\n\tunsigned long *temp;\n\tunsigned long diff, flags;\n\n\ttemp = (unsigned long*)original_ptr;\n\n\t/* ReAlloc the space */\n\ttemp = (unsigned long *)realloc(temp, new_size_in_bytes);\n\tif (temp == NULL) {\n\t\tif(Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\t\t\n\t}\t\t\t   \n\n\treturn(temp);\n}\n\n\n/***************************************************************************\n * Ram_Free -- Determines the largest free chunk of RAM.                   *\n *                                                                         *\n *    Use this routine to determine the largest free chunk of available    *\n *    RAM for allocation.  It also performs a check of the memory chain.   *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  Returns with the size of the largest free chunk of RAM.        *\n *                                                                         *\n * WARNINGS:   This does not return the TOTAL memory free, only the        *\n *             largest free chunk.                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Commented.                                           *\n *=========================================================================*/\nlong Ram_Free(MemoryFlagType)\n{\n//\treturn(_memmax());\n\treturn Largest_Mem_Block();\n}\n\n\n/***************************************************************************\n * Heap_Size -- Size of the heap we have.                                  *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Heap_Size(MemoryFlagType )\n{\n\tif (!TotalRam) {\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\t}\n\treturn(TotalRam);\n}\n\n\n/***************************************************************************\n * Total_Ram_Free -- Total amount of free RAM.                             *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *   03/09/1995 JLB : Uses prerecorded heap size maximum.                  * \n *=========================================================================*/\nlong Total_Ram_Free(MemoryFlagType )\n{\n//\treturn(_memavl());\n\treturn Largest_Mem_Block () ;\n}\n\n"
  },
  {
    "path": "WIN32LIB/MEM/OLDMEM/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 24, 1994                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = mem\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR\t    = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\nCC_CFG += /zm\t\t\t\t\t\t\t\t\t# Each routine to be in its own segment.\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\talloc.obj  \t&\n\tmem.obj  \t&\n\tnewdel.obj  \t&\n\tmem_copy.obj \n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/MEM/OLDMEM/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 24, 1994                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = mem\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR\t    = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\nCC_CFG += /zm\t\t\t\t\t\t\t\t\t# Each routine to be in its own segment.\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\talloc.obj  \t&\n\tmem.obj  \t&\n\tnewdel.obj  \t&\n\tmem_copy.obj \n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/MEM/OLDMEM/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 24, 1994                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = mem\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR\t    = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\nCC_CFG += /zm\t\t\t\t\t\t\t\t\t# Each routine to be in its own segment.\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\talloc.obj  \t&\n\tmem.obj  \t&\n\tnewdel.obj  \t&\n\tmem_copy.obj \n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/MEM/OLDMEM/MEM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : MEM.C                                    *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : March 31, 1993                           *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Mem_Free -- Free a block of memory from system.                       *\n *   Mem_Alloc -- Allocate a block of memory from the special memory pool. *\n *   Mem_Init -- Initialize the private memory allocation pool.            *\n *   Mem_Reference -- Updates the reference time for the specified memory blo*\n *   Mem_Find -- Returns with pointer to specified memory block.           *\n *   Mem_Find_Oldest -- Returns with the memory block with the oldest time st*\n *   Mem_Free_Oldest -- Find and free the oldest memory block.             *\n *   Mem_Avail -- Returns the amount of free memory available in the cache.*\n *   Mem_Cleanup -- Performes a garbage collection on the memory cache.    *\n *   MemNode_Unlink -- Unlinks a node from the cache.                      *\n *   MemNode_Insert -- Inserts a node into a cache chain.                  *\n *   Mem_Largest_Avail -- Largest free block available.                    *\n *   Mem_Lock_Block -- Locks a block so that it cannot be moved in cleanup.*\n *   Mem_In_Use -- Makes it so a block will never be returned as oldest*\n *   Mem_Pool_Size -- Returns total amount of memory in pool.              *\n *   Mem_Get_ID -- Returns ID of node.                                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"wwmem.h\"\n#include <timer.h>\n\n#include\t<stddef.h>\n#include\t<mem.h>\n\n#define DEBUG_FILL FALSE\n\n////////////////////////////////////////////////////////////////////////////\n\n\n\n/*******************************************************************************\n** A allocated block may have one of three meanings in the Time field.  The first\n** is the time stamp of the last time it was referenced.  The other two values\n** are defined below.  MEM_BLOCK_IN_USE means that it will never be returned as the\n** oldest since there is no valid time stamp.  LOCKED_BLOCK has the same meaning as\n** MEM_BLOCK_IN_USE with the added feature that the block will not be moved in a \n** Mem_Cleanup().  Therefore, there may be some fragmentation after the cleanup\n** if any blocks are LOCKED.  It would be good practice to seldomly lock blocks,\n** for instance, only when a sample is being played.\n** WARNING: If these values change to anything else, logic will need to be changed\n**          in Mem_Find_Oldest since it relies on these being small values.\n*/\n#define MEM_BLOCK_IN_USE\t0x00\n#define MEM_BLOCK_LOCKED\t0x01\n\n/*\n**\tEach block of memory in the pool is headed by this structure.\n*/\ntypedef struct MemChain {\n\tstruct MemChain\t*Next;\t// Pointer to next memory chain node.\n\tstruct MemChain\t*Prev;\t// Pointer to previous memory chain node.\n\tunsigned long\t\tID;\t\t// ID number of block.\n\tunsigned short\t\tTime;\t\t// TickCount of latest reference.\n\tunsigned short\t\tSize;\t\t// Size of memory block (in paragraphs).\n} MemChain_Type;\n\n\n/*\n**\tHolding tank memory management data.\n*/\ntypedef struct MemPool {\n\tMemChain_Type\t*FreeChain;\t// Pointer to first node in free chain.\n\tMemChain_Type\t*UsedChain;\t// Pointer to first node in used chain.\n\tunsigned short\tFreeMem;\t\t// Current amount of free ram (in paragraphs).\n\tunsigned short\tTotalMem;\t// Total quantity of memory.\n\tlong\t\t\t\tpad2;\n} MemPool_Type;\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE void MemNode_Unlink(MemPool_Type *pool, int freechain, MemChain_Type *node);\nPRIVATE void MemNode_Insert(MemPool_Type *pool, int freechain, MemChain_Type *node, unsigned int size, unsigned long id, int merge);\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * Mem_Init -- Initialize the private memory allocation pool.              *\n *                                                                         *\n *    This routine is used to initialize the private memory allocation     *\n *    pool.                                                                *\n *                                                                         *\n * INPUT:   buffer   -- Pointer to the buffer that is the allocation pool. *\n *                                                                         *\n *          size     -- Size of the buffer in bytes.                       *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Was it initialized successfully?                   *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nint Mem_Init(void *buffer, long size)\n{\n\tMemChain_Type\t*mem;\t\t\t// Working memory chain node.\n\tMemPool_Type\t*pool;\t\t// Memory pool control structure.\n\n\t/*\n\t**\tThe buffer is rounded down to the nearest paragraph.\n\t*/\n\tsize = size & 0xFFFFFFF0L;\n\n\tif (!buffer || !size) return(FALSE);\n\n\t/*\n\t**\tInitialize the pool control structure.\n\t*/\n\tpool = (MemPool_Type *)buffer;\n\tpool->FreeMem = (size - sizeof(MemPool_Type)) >> 4;\n\tpool->UsedChain = NULL;\n\tpool->TotalMem = pool->FreeMem;\n\tmem = pool->FreeChain = (MemChain_Type *) (pool + 1);\n\n\t/*\n\t**\tInitialize the free memory chain.\n\t*/\n\tmem->Next = NULL;\n\tmem->Prev = NULL;\n\tmem->Size = pool->FreeMem;\n\tmem->ID = -1;\n\tmem->Time = 0;\n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * Mem_Alloc -- Allocate a block of memory from the special memory pool.   *\n *                                                                         *\n *    This routine will allocate a block of memory from the special        *\n *    memory allocation pool.                                              *\n *                                                                         *\n * INPUT:   poolptr\t-- Pointer to the memory pool base address.           *\n *                                                                         *\n *          size  -- The size of the memory block to allocate.             *\n *                                                                         *\n *          id    -- ID number to give this memory block.                  *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the allocated block.  If there was   *\n *          insufficient room, then NULL is returned.                      *\n *                                                                         *\n * WARNINGS:   Be sure to check for the NULL return case.                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Alloc(void *poolptr, long lsize, unsigned long id)\n{\n\tMemPool_Type\t*pool;\n\tMemChain_Type\t*node;\t\t\t// Pointer to current memory node.\n\tunsigned int\tremainder=0;\t// Remaining bytes that are still free.\n\tint\t\t\t\tfound;\n\tint\t\t\t\tsize;\t\t\t\t// Paragraph size of allocation.\n\n\n\t/*\n\t**\tIf there is no free memory then the allocation will\n\t**\talways fail.\n\t*/\n\tif (!poolptr || !lsize) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\t\t\n\t/*\n\t**\tAllocations are forced to be paragraph sized.\n\t*/\n\tlsize += sizeof(MemChain_Type);\t// Account for header.\n\tlsize = (lsize + 0x0FL) & 0xFFFFFFF0L;\n\tsize = (int)(lsize >> 4);\n\n\t/*\n\t**\tIf the total free is less than the size of the desired allocation,\n\t**\tthen we KNOW that an allocation will fail -- just return.\n\t*/\n\tif (pool->TotalMem < size) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tWalk down free chain looking for the first block that will\n\t**\taccomodate the allocation.\n\t*/\n\tnode = pool->FreeChain;\n\tfound = FALSE;\n\twhile (!found && node) {\n\n\t\t/*\n\t\t**\tFetch free memory chunk block and see if it is big enough.\n\t\t*/\n\t\tif (node->Size >= size) {\n\t\t\tfound = TRUE;\n\t\t\tbreak;\n\t\t}\n\t\tnode = node->Next;\n\t}\n\tif (!found) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tDetermine if this allocation would split the block.\n\t*/\n\tremainder = node->Size - size;\n\n\t/*\n\t**\tIf only a very small free chunk would remain, just tack it on\n\t**\tto the current allocation.\n\t*/\n\tif (remainder <= 2) {\n\t\tremainder = 0;\n\t\tsize = node->Size;\n\t}\n\n\t/*\n\t**\tRemove the primary block from the free memory list.\n\t*/\n\tMemNode_Unlink(pool, TRUE, node);\n\n\t/*\n\t**\tIf a smaller block remains, then link it back into\n\t**\tthe free memory list.\n\t*/\n\tif (remainder) {\n\t\tMemNode_Insert(pool, TRUE, (MemChain_Type *)Add_Long_To_Pointer(node, (long)size << 4), remainder, -1, FALSE);\n\t}\n\n\t/*\n\t**\tLink in the allocated node into the used memory list.\n\t*/\n\tMemNode_Insert(pool, FALSE, node, size, id, FALSE);\n\n\t/*\n\t**\tReflect the change to the total free count.\n\t*/\n\tpool->FreeMem -= size;\n\n\t/*\n\t**\tReturn a pointer to the block of allocated memory just past\n\t**\tthe header.\n\t*/\n\n#if DEBUG_FILL\n\tmemset(node + 1, id, (size-1) << 4);\n#endif\n\treturn((void *) (node + 1));\n}\t\n\n\n/***************************************************************************\n * Mem_Free -- Free a block of memory from system.                         *\n *                                                                         *\n *    This routine will free a block of memory from the special memory     *\n *    buffer.                                                              *\n *                                                                         *\n * INPUT:   poolptr\t-- Pointer to the memory pool base address.           *\n *                                                                         *\n *          buffer   -- Pointer to memory block to free.                   *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Was the deallocation successful?                   *\n *                                                                         *\n * WARNINGS:   Be sure to only pass in to this routine a buffer that was   *\n *             returned from Mem_Alloc().                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nint Mem_Free(void *poolptr, void *buffer)\n{\n\tMemPool_Type\t*pool;\t\t\t// pointer to structure.\n\tMemChain_Type\t*node;\t\t\t// Copy of current memory node.\n\tunsigned int\tsize;\t\t\t\t// Size of the block being freed.\n\n\t/*\n\t**\tOne can't free what isn't there.\n\t*/\n\tif (!buffer || !poolptr) {\n\t\treturn(FALSE);\n\t}\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tThe node pointer is actually back a bit from the \"normal\" pointer.\n\t*/\n\tnode = (MemChain_Type *) buffer;\n\tnode--;\n\n\t/*\n\t**\tGet pointer to actual allocated node and unlink it from the used\n\t**\tmemory chain.\n\t*/\t\n\tsize = node->Size;\n\tMemNode_Unlink(pool, FALSE, node);\n\tMemNode_Insert(pool, TRUE, node, size, -1, TRUE);\n\n\t/*\n\t**\tReflect the new free memory into the total memory count.\n\t*/\n\tpool->FreeMem += size;\n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * Mem_Reference -- Updates the reference time for the specified memory blo*\n *                                                                         *\n *    This routine is used to update the memory reference time for the     *\n *    specified memory node.  Typically, this is called every time a       *\n *    memory block is used in order to make sure the memory block time     *\n *    tracking (Last Recently Used) system works properly.                 *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   The node pointer must be valid.  For maximum safety this    *\n *             routine should be called right after Mem_Find().            *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid Mem_Reference(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node;\n\tnodeptr--;\n\n\tnodeptr->Time = (unsigned short)(TickCount.Time() >> 4);\n\n}\n\n\n/***************************************************************************\n * MEM_LOCK_BLOCK -- Locks a block so that it cannot be moved in cleanup.  *\n * \tBy marking a memory block in use, the memory system will never return*\n *    it as the oldest memory block.  It also makes it so that the block\t*\n *    will never be moved during a Cleanup process.                        *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:  \tIf one or more blocks are locked in a heap, Mem_Avail might *\n *             not equal Mem_Largest_Avail after a call to Mem_Cleanup.    *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid Mem_Lock_Block(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node;\n\tnodeptr--;\n\tnodeptr->Time = MEM_BLOCK_LOCKED;\n}\n\n\n/***************************************************************************\n * MEM_IN_USE -- Makes it so a block will never be returned as oldest\t\t*\n * \tBy marking a memory block in use, the memory system will never return*\n *    it as the oldest memory block.  It still can be moved in the Cleanup *\n *    code.                                                                *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS: Mem_Find_Oldest() will return NULL if only IN_USE blocks are  *\n *           in memory.                                                    *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid Mem_In_Use(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node - 1;\n\tnodeptr->Time = MEM_BLOCK_IN_USE;\n}\n\n\n/***************************************************************************\n * Mem_Find -- Returns with pointer to specified memory block.             *\n *                                                                         *\n *    Use this routine to convert a memory ID value into an actual memory  *\n *    pointer.  It sweeps through all of the 'cached' memory blocks and    *\n *    returns with the matching block pointer.                             *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache block.                 *\n *                                                                         *\n *          id       -- The ID of the block desired.                       *\n *                                                                         *\n * OUTPUT:  Returns with the pointer to the memory block.  If NULL is      *\n *          returned then the desired block is not in the memory cache.    *\n *                                                                         *\n * WARNINGS:   This routine may return NULL if the memory block is not     *\n *             present in the cache.                                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Find(void *poolptr, unsigned long id)\n{\n\tMemPool_Type\t*pool;\t\t\t// pointer to structure.\n\tMemChain_Type\t*node;\t\t\t// Working node structure.\n\n\tif (!poolptr) return(NULL);\n\n\tpool = (MemPool_Type *) poolptr;\n\t\t\n\t/* \n\t** Cannot free a node that is not on the UsedChain list.\n\t*/\n\tif (!pool->UsedChain) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tSweep through entire allocation chain to find\n\t**\tthe one with the matching ID.\n\t*/\n\tnode = pool->UsedChain;\n\twhile (node) {\n\t\t\n\t\tif (node->ID == id) {\n\t\t\treturn(node + 1);\n\t\t}\n\t\tnode = node->Next;\n\t}\n\treturn(NULL);\n}\n\n\n/***************************************************************************\n * MEM_GET_ID -- Returns ID of node.                                       *\n *                                                                         *\n * INPUT:  void *node - pointer to node. \t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT: The ID of the node that was supplied by user during Mem_Alloc().*\n *                                                                         *\n * WARNINGS: pointer to node must be one that Mem_Alloc or                \t*\n *           Mem_Find returned.                                           **\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nunsigned long Mem_Get_ID(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return (0L);\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node - 1;\n\treturn (nodeptr->ID);\n}\n\n\n/***************************************************************************\n * Mem_Find_Oldest -- Returns with the memory block with the oldest time st*\n *                                                                         *\n *    Use this routine to find the memory block with the oldest time stamp *\n *    value.  Typically, this is used when freeing memory blocks in the    *\n *    cache in order to make room for a new memory block.                  *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns with the pointer to the oldest memory block.  If NULL  *\n *          is returned, then the memory cache is empty.                   *\n *                                                                         *\n * WARNINGS:   This routine could return NULL.                             *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *   04/15/1994 SKB : Handle time wrap, locked blocks, and no_refenece blocks*\n *=========================================================================*/\nvoid *Mem_Find_Oldest(void *poolptr)\n{\n\tMemChain_Type\t*node; \t\t\t\t// Working node pointer.\n\tMemChain_Type\t*oldnode;\t\t\t// Pointer to oldest block.\n\tunsigned int\toldtime;\t\t\t\t// Time of oldest block.\n\tunsigned int\tbasetime;\t\t\t// Time to mark our base time with.\n\tunsigned int\ttime;\t\t\t\t\t// basetime + time of node.\n\n\tif (!poolptr) return(NULL);\n\n\t/*\n\t**\tSweep through entire allocation chain to find\n\t**\tthe oldest referenced memory block.\n\t*/\n\toldnode = NULL;\n\toldtime = 0;\n\tnode = ((MemPool_Type*) poolptr)->UsedChain;\n\n  basetime = (unsigned int)(TickCount.Time() >> 4);\n\n\twhile (node) {\n\n\t\t/*\n\t\t** Don't allow MEM_BLOCK_IN_USE or MEM_BLOCK_LOCKED to be returned.\n\t\t*/\n\t\tif (node->Time > MEM_BLOCK_LOCKED) {\n\n\t\t\t/*\n\t\t\t** Adjust time for wrap around (after about 5 hrs).\n\t\t\t** times less then the base time will wrap up high while\n\t\t\t** and times greater then base time will then be lower since\n\t\t\t** any time greater has been on the thing a long time.\n\t\t\t*/\n\t\t\ttime = node->Time - basetime ;\n\n\t\t\tif (time < oldtime || !oldnode) {\n\t\t\t\toldtime = time;\n\t\t\t\toldnode = node;\n\t\t\t}\n\t\t}\n\t\tnode = node->Next;\n\t}\n\n\t/*\n\t**\tReturn with the value that matches the pointer that\n\t**\twas allocated by the system previously.\n\t*/\n\tif (oldnode) {\n\t\toldnode++;\n\t}\n\treturn(oldnode);\n}\n\n\n/***************************************************************************\n * Mem_Free_Oldest -- Find and free the oldest memory block.               *\n *                                                                         *\n *    This routine is used to free the oldest memory block in the memory   *\n *    cache.  This routine is typcially used in order to create more room  *\n *    in the cache for a new allocation.                                   *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns with the node that it freed.  Although this node is    *\n *          is no longer valid, it may be used to mark that pointer as     *\n *          invalid in the main code.                                      *\n *                                                                         *\n * WARNINGS:   If this routine returns NULL, then no memory was freed.     *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Free_Oldest(void *poolptr)\n{\n\tMemChain_Type\t*node;\t\t// Copy of pointer to oldest node.\n\n\tif (!poolptr) return(NULL);\n\tnode = (MemChain *) Mem_Find_Oldest(poolptr);\n\tif (Mem_Free(poolptr, node)) {\n\t\treturn(node);\n\t}\n\treturn(NULL);\n}\n\n/***************************************************************************\n * MEM_POOL_SIZE -- Returns total amount of memory in pool.                *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  long total size of pool. i.e. largest possible allocation if   *\n *          no memory was allocated.                                       *\n *                                                                         *\n * WARNINGS: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Mem_Pool_Size(void *poolptr)\n{\n\tMemPool_Type\t*pool;\t\t\t// Memory pool control structure.\n\tlong\t\t\t\tmemtotal;\t\t// Total amount of memory free.\n\n\tif (!poolptr) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\tmemtotal = ((long)pool->TotalMem) << 4;\n\tmemtotal -= sizeof(MemChain_Type);\n\tmemtotal = MAX(memtotal, (long)0);\n\treturn(memtotal);\n}\n\n/***************************************************************************\n * Mem_Avail -- Returns the amount of free memory available in the cache.  *\n *                                                                         *\n *    This routine examines the memory cache and returns the amount of     *\n *    free memory available.  This memory total MAY be fragmented but      *\n *    after Mem_Cleanup() is called, an allocation of the amount returned  *\n *    by this function is guaranteed.                                      *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns the largest allocation possible from the memory cache. *\n *                                                                         *\n * WARNINGS:   The value returned may represent the FRAGMENTED total       *\n *             amount of memory free in the cache.                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nlong Mem_Avail(void *poolptr)\n{\n\tMemPool_Type\t*pool;\t\t// Memory pool control structure.\n\tlong\t\t\t\tmemtotal;\t// Total amount of memory free.\n\n\tif (!poolptr) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\tmemtotal = ((long)pool->FreeMem) << 4;\n\tmemtotal -= sizeof(MemChain_Type);\n\t//memtotal -= sizeof(MemChain_Type) + 15;\n\tmemtotal = MAX(memtotal, (long)0);\n\treturn(memtotal);\n}\n\n\n/***************************************************************************\n * MEM_LARGEST_AVAIL -- Largest free block available.                      *\n * \tThis routine examines the free node list to find the largest block   *\n *\t\tavailable.  User can Mem_Alloc() this return size successfully.      *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns largest allocation currently possible from the cache. \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Mem_Largest_Avail(void *poolptr)\n{\n\tMemChain_Type\t*node;\t\t\t// Pointer to current memory node.\n\tunsigned int\tsize;\n\tlong\t\t\t\ttruesize;\t\n\n\t/*\n\t** Make sure that it is a buffer.\n\t*/\n\tif (!poolptr) return(NULL);\n\n\t/*\n\t** Go through the entire free chain looking for the largest block.\n\t*/\n\tnode = ((MemPool_Type *)poolptr)->FreeChain;\n\tsize = 0;\n\twhile (node) {\n\n\t\t/*\n\t\t**\tFetch free memory chunk block and see if it is big enough.\n\t\t*/\n\t\tif (node->Size >= size) {\n\t\t\tsize = node->Size;\n\t\t}\n\t\tnode = node->Next;\n\t}\n\n\ttruesize = (long)size << 4;\n\ttruesize -= sizeof(MemChain_Type);\n\ttruesize = MAX(truesize, 0L);\n\treturn (truesize);\n}\n\n\n/***************************************************************************\n * Mem_Cleanup -- Performs a garbage collection on the memory cache.       *\n *                                                                         *\n *    This routine is used to coalesce all adjacent free blocks of         *\n *    memory in the specified cache.  As a result, all previous pointers   *\n *    provided by Mem_Find() are invalidated.  This routine consumes a     *\n *    fair amount of time and should be called as infrequently as          *\n *    possible.                                                            *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine takes a significant amount of time!            *\n *             If there are locked block in memory, the pool may still     *\n *             be fragmented.                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Updated for low memory caches.                       *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid Mem_Cleanup(void *poolptr)\n{\n\tMemPool_Type\t*pool;  \t// Memory pool control structure.\n\tMemChain_Type\t*free,\t// Pointer to first free area.\n\t\t\t\t\t\t*cur;\t\t// Pointer to first used block that is after free.\n\tunsigned long\tsize;\n\tunsigned long\tfreesize;// Size of free heap at the end of the block.\n\n\tif (!poolptr) return;\n\n\t/*\n\t**\tFetch working copy of pool control structure.\n\t*/\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tBasic parameter and condition legality checks.  If the memory pool\n\t**\thas no free space, no free blocks, or no allocated blocks, then \n\t**\tmemory cleanup is unnecessary -- just exit.\n\t*/\n\tif (!pool->FreeMem || !pool->FreeChain || !pool->UsedChain) return;\n\n\tfreesize = pool->FreeMem;\n\tfree = pool->FreeChain;\n\tpool->FreeChain = NULL;\n\tcur = pool->UsedChain;\n\twhile (TRUE) {\n\n\t\t/*\n\t\t** Setup pointers so that free points to the first free block and cur\n\t\t** points to the next used block after the free block.\n\t\t*/\n\t\twhile (cur < free && cur) {\n\t \t\tcur = cur->Next;\n\t\t}\n\n\t\t// All used blocks are at the front of the free.  We are done.\n\t\tif (!cur) {\n\t \t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t** Do not allow a locked block to be moved.\n\t\t*/\n\t\tif (cur->Time == MEM_BLOCK_LOCKED) {\n\t\t\t/* \n\t\t\t** Figure the size of the new free block that we are creating.\n\t\t\t** Subtract off the total block size.\n\t\t\t** Add the node to the free list.\n\t\t\t*/\n\t\t\tsize = (char *) cur - (char  *) free;\n\t\t\tsize >>= 4;\n\t\t \tfreesize -= size;\n\t\t\tMemNode_Insert(pool, TRUE, free, (unsigned int) size, -1, FALSE);\n\n\t\t\t/*\n\t\t\t** Time to find a new free position to start working from.\n\t\t\t** Cur will be in the position just following.\n\t\t\t*/\n\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, (unsigned long)cur->Size << 4);\n\t\t\tcur = cur->Next;\n\t\t\twhile (free == cur) {\n\t\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, (unsigned long)cur->Size << 4);\n\t\t\t\tcur = cur->Next;\n\t\t\t}\n\n\t\t\t// All used blocks are at the front of the free.  We are done.\n\t\t\tif (!cur) {\n\t\t\t \tbreak;\n\t\t\t}\n\t\t} else {\n\n\t\t\t// Copy the block up.\n\t\t\tsize = (unsigned long)cur->Size << 4;\n\t\t\tMem_Copy(cur, free, size);\n\t\t\tcur = free;\n\n\t\t\t// Change pointers of surrounding blocks.\n\t\t\tif (cur->Next) {\n\t\t \t\tcur->Next->Prev = cur;\n\t\t\t}\n\t\t\tif (cur->Prev) {\n\t\t \t\tcur->Prev->Next = cur;\n\t\t\t} else {\n\t\t \t\tpool->UsedChain = cur;\n\t\t\t}\n\n\t\t\t// Change to next new free area.\n\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, size);\n\t\t}\n\t}\n\n\t/*\n\t**\tNow build the single free chunk.\n\t*/\n\tMemNode_Insert(pool, TRUE, free, freesize, -1, FALSE);\n}\n\n\n/***************************************************************************\n * MemNode_Unlink -- Unlinks a node from the cache.                        *\n *                                                                         *\n *    A private routine the actually unlinks a memory block from the       *\n *    memory cache.  It doesn't perform a complete update of the memory    *\n *    cache.                                                               *\n *                                                                         *\n * INPUT:   pool     -- Pointer to the memory cache header (copy in real   *\n *                      memory).                                           *\n *                                                                         *\n *          freechain-- Is the block part of the free memory chain?        *\n *                                                                         *\n *          node     -- Pointer to the node that will be unlinked.         *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine doesn't update memory totals.  It is a support *\n *             function.                                                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nPRIVATE void MemNode_Unlink(MemPool_Type *pool, int freechain, MemChain_Type *node)\n{\n\tMemChain_Type\t*other; \t\t// Copy of node data to unlink.\n\tMemChain_Type\t**chain;\t\t// A pointer to one of the chains pointer.\n\n\t/*\n\t**\tCheck for parameter validity.\n\t*/\n\tif (!pool || !node) return;\n\t\n\t/*\n\t**\tSetup working pointer for the particular chain desired.\n\t*/\t\n\tif (freechain) {\n\t\tchain = &pool->FreeChain;\n\t} else {\n\t\tchain = &pool->UsedChain;\n\t}\n\t\n\t/*\n\t**\tMake adjustments to the previous node.  If the pointer\n\t**\tto the previous node is NULL then this indicates the\n\t**\tfirst node in the list and thus the chain pointer needs\n\t**\tto be updated instead.\n\t*/\n\tif (node->Prev) {\n\t\tother = node->Prev;\n\t\tother->Next = node->Next;\n\t} else {\n\t\t*chain = node->Next;\n\t}\n\n\tif (node->Next) {\n\t\tother = node->Next;\n\t\tother->Prev = node->Prev;\n\t}\n}\n\n\n/***************************************************************************\n * MemNode_Insert -- Inserts a node into a cache chain.                    *\n *                                                                         *\n *    This routine is used to add a node to a cache chain.  Since nodes    *\n *    do not contain double links, they must be placed in sequence.        *\n *                                                                         *\n * INPUT:   pool     -- Pointer to memory pool (must be in real memory).   *\n *                                                                         *\n *          freechain-- Is the node to be inserted into the free chain?    *\n *                                                                         *\n *          node     -- Pointer to the node to insert.                     *\n *                                                                         *\n *          size     -- Size of the memory block (in paragraphs).          *\n *                                                                         *\n *          id       -- The ID number to associate with this block.        *\n *                                                                         *\n *          merge    -- Merge inserted block with adjacent blocks.         *\n *                                                                         *\n * OUTPUT:  return                                                         *\n *                                                                         *\n * WARNINGS:   This is a support routine.                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void MemNode_Insert(MemPool_Type *pool, int freechain, MemChain_Type *node, unsigned int size, unsigned long id, int merge)\n{\n\tMemChain_Type \t**chain;\t\t\t// Pointer to chain that will be linked.\n\tMemChain_Type \t*prev,\t\t\t// Successor node pointer.\n\t\t\t\t\t\t*next;\t\t\t// Predecessor node pointer.\n\tint\t\t\t\tdoit=TRUE;\t\t// Link the node into the list.\n\n\n\t/*\n\t**\tDetermine if the parameters are valid.\n\t*/\n\tif (!pool || !node || !size) return;\n\n\t/*\n\t**\tSetup working pointer for the particular chain desired.\n\t*/\t\n\tif (freechain) {\n\t\tchain = &pool->FreeChain;\n\t} else {\n\t\tchain = &pool->UsedChain;\n\t}\n\n\t/*\n\t**\tHandle the \"no node in list\" condition (easiest).\n\t*/\n\tif (!*chain) {\n\t\tnode->Next = NULL;\n\t\tnode->Prev = NULL;\n\t\tnode->Size = size;\n\t\tnode->Time = (unsigned short)(TickCount.Time() >> 4);\n\t\tnode->ID = id;\n\t\t*chain = node;\n\t\treturn;\n\t}\n\n\t/*\n\t**\tSweep through the memory chain looking for a likely spot\n\t**\tto insert the new node.  It will stop with \"next\" pointing\n\t**\tto the node to come after the block to be inserted and \"prev\"\n\t** will point to the node right before.\n\t*/\n\tprev = NULL;\n\tnext = *chain;\n\twhile (next && (next < node)) {\n\n\t\t/*\n\t\t**\tMove up the memory chain.\n\t\t*/\n\t\tprev = next;\n\t\tnext = next->Next;\n\t}\n\n\t/*\n\t**\tCoallescing of adjacent blocks (if requested).\n\t*/\n\tif (merge) {\n\t\t\n\t\t/*\n\t\t**\tIf the previous block is touching the block to insert\n\t\t**\tthen merely adjust the size of the previous block and\n\t\t**\tthat is all that is necessary.\n\t\t*/\n\t\tif (prev) {\n\t\t\tif (((char *)prev + ((long)prev->Size << 4)) == ((char *) node)) {\n\t\t\t\tprev->Size += size;\n\t\t\t\tsize = prev->Size;\n\t\t\t\tnode = prev;\n\t\t\t\tprev = prev->Prev;\n\t\t\t\tdoit = FALSE;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf the following block is touching the block to insert\n\t\t**\tthen remove the following block and increase the size of\n\t\t**\tthe original insertion block by the size of the other\n\t\t**\tblock.\n\t\t*/\n\t\tif (next) {\n\t\t\tif (((char *)node + ((long)size << 4)) == (char *)next) {\n\t\t\t\t\n\t\t\t\tif (!doit) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the node was already merged with the previous block\n\t\t\t\t\t**\tthen merely increase the previous block's size\n\t\t\t\t\t**\tand adjust it's next pointer appropriately.\n\t\t\t\t\t*/\n\t\t\t\t\tnode->Size += next->Size;\n\t\t\t\t\tnode->Next = next->Next;\n\t\t\t\t\tnext = next->Next;\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIncrease the size of the current block and adjust\n\t\t\t\t\t**\tthe \"next\" pointer so that it gets fixed up\n\t\t\t\t\t**\taccordingly.\n\t\t\t\t\t*/\n\t\t\t\t\tsize += next->Size;\n\t\t\t\t\tnext = next->Next;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n#if DEBUG_FILL\n\tif (doit) {\n\t\tmemset(node + 1, 0xFF, (size - 1) << 4);\n\t} else {\n\t\tmemset(node + 1, 0xFF, (node->Size - 1) << 4);\n\t}\n#endif\n\n\t/*\n\t**\tFixup the node pointers.\n\t*/\n\tif (prev) {\n\t\tprev->Next = node;\n\t}else{\n\t\t*chain = node;\n\t}\n\n\tif (next) {\n\t \tnext->Prev = node;\n\t}\n\n\tif (doit) {\n\t\tnode->Prev = prev;\n\t\tnode->Next = next;\n\t\tnode->Size = size;\n\t\tnode->Time = (unsigned short)(TickCount.Time() >> 4);\n\t\tnode->ID = id;\n\t}\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/MEM/OLDMEM/MEMFLAG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory System                            *\n *                                                                         *\n *                    File Name : MEMFLAG.H                                *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : April 4, 1994                            *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef MEMFLAG_H\n#define MEMFLAG_H\n// Memory Flags\n/*\n**\tMemory allocation flags.  These are the flags that are passed into Alloc\n**\tin order to control the type of memory allocated.\n*/\ntypedef enum {\n\tMEM_NORMAL = 0x0000,\t\t// Default memory (normal).\n\tMEM_NEW\t  = 0x0001,\t\t// Called by the operator new and was overloaded.\n\tMEM_CLEAR  = 0x0002,\t\t// Clear memory before returning.\n\tMEM_REAL   = 0x0004,\t\t// Clear memory before returning.\n\tMEM_TEMP   = 0x0008,\t\t// Clear memory before returning.\n\tMEM_LOCK   = 0x0010,\t\t// Lock the memory that we allocated\n} MemoryFlagType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: ALLOC.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid\t*Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags);\nvoid\tFree(void const *pointer);\nvoid\tDPMI_Lock(VOID const *ptr, long const size);\nvoid\tDPMI_Unlock(void const *ptr, long const size);\nvoid\t*Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes);\nlong\tRam_Free(MemoryFlagType flag);\nlong\tHeap_Size(MemoryFlagType flag);\nlong\tTotal_Ram_Free(MemoryFlagType flag);\n\n\ninline void * operator new(size_t size, MemoryFlagType flag) \n{\n\treturn(Alloc(size, flag));\n}\ninline void * operator new[] (size_t size, MemoryFlagType flag)\n{\n\treturn(Alloc(size, flag));\n}\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MEM_COPY.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\textern void Mem_Copy(void *source, void *dest, unsigned long bytes_to_copy);\n\n#ifdef __cplusplus\n}\n#endif\n\n\ninline void *Add_Long_To_Pointer(void const *ptr, long size) \n{\n \treturn ((void *) ( (char const *) ptr + size));\n}\n\nextern void (*Memory_Error)(void);\n\nextern unsigned long MinRam;\t\t// Record of least memory at worst case.\nextern unsigned long MaxRam;\t\t// Record of total allocated at worst case.\n\n\n#endif\n\n\n"
  },
  {
    "path": "WIN32LIB/MEM/OLDMEM/MEM_COPY.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : MEM_COPY.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott Bowen\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : September 8, 1994\t[IML]              *\n;*                  Ported to watcom c32 : 01/03/96     [JRJ]                                                                        *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Mem_Copy -- Copies from one pointer to another.                       *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nLOCALS ??\n\n\n;******************************************************************************\n; Much testing was done to determine that only when there are 14 or more bytes\n; being copied does it speed the time it takes to do copies in this algorithm.\n; For this reason and because 1 and 2 byte copies crash, is the special case\n; used.  SKB 4/21/94.  Tested on 486 66mhz.\nOPTIMAL_BYTE_COPY\tequ\t14\n\n\n;******************************************************************************\n; External declares so these functions can be called\n;\nGLOBAL \tMem_Copy\t: NEAR\nGLOBAL  Largest_Mem_Block : near\n\nCODESEG\n\n\n;***************************************************************************\n;* MEM_COPY -- Copies from one pointer to another.                         *\n;* This routine copies bytes from source to dest.  It takes care of\t   *\n;* overlapped memory, and unsigned long copies.\t\t\t\t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/18/1994 SKB : Created.                                             *\n;*=========================================================================*\n; void Mem_Copy(void *source, void *dest, unsigned long bytes_to_copy);\n\n\nPROC Mem_Copy \tC near \n\tUSES\tecx , esi , edi , ebx\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tbytes:DWORD\n\t\t\n;********************************* Setup ******************************************\n\tcld\n\tmov\tesi,[source]\n\tmov\tedi,[dest]\n\tmov\tecx,[bytes]\t; get number of bytes to copy.\t\n\n     ; check pointers for singularities\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tje\t??done\t\t; No sence in copying the same pointer.\t\n\tor\tesi,0\n\tjz\t??done\n\tor\tedi,0\n\tjz\t??done\n\n\tcmp\tecx,OPTIMAL_BYTE_COPY  ; see notes above about equate.\n\tjge\t??normal      \t       ; If >= MAX(2,OPTIMAL_BYTE_COPY), do normal dword copy.\n\n;******************************** Special case <= 2 *******************************\n;\n; This section must be called for bytes <= 2 since the other case will crash.  It\n; optionally uses OPTIMAL_BYTE_COPY for the cut off point.  This is because after\n; extensive testing, it was proved that only at that point (14 or more bytes) does\n; it become quicker to use the dword copy method.\n\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tjge\t??do_move\t; if source greater do forward copy.\n\tlea\tesi,[esi+ecx-1]\n\tstd\t\t\t; Opps, wrong, force the pointers to decrement.\n\tlea\tedi,[edi+ecx-1]\n??do_move:\n\trep\tmovsb\t\t; move the one or two bytes.\n\tcld\n??done:\n\tret\n\n;************************** back or forth, that is the question *******************\n\n??normal:\n\tmov\tebx,ecx\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tjge\t??forward\t; if source greater do forward copy.\n\n;********************************* Backward ***************************************\n??backward:\n\tlea\tecx,[edi+ebx]\n\tstd\n\tlea\tedi,[edi+ebx-1]\n\tand\tecx,3\t\t; Get non aligned bytes.\n\tlea\tesi,[esi+ebx-1]\n\tsub\tebx,ecx\t\t; remove that from the total size to be copied later.\n\trep\tmovsb\t\t; do the copy.\n\tsub\tesi,3\n\tmov\tecx,ebx\t\t; Get number of bytes left.\n \tsub\tedi,3\n\tshr\tecx,2\t\t; Do 4 bytes at a time.\n\trep\tmovsd\t\t; do the dword copy.\n\tmov\tecx,ebx\n\tadd\tesi,3\n\tadd\tedi,3\n\tand\tecx,03h\n\trep\tmovsb\t\t; finnish the remaining bytes.\n\tcld\n\tret\n\n;********************************* Forward ***************************************\n??forward:\n\tcld\n\tmov\tecx,edi\t\t; get destination pointer.\t\n\tneg\tecx\n\tand\tecx,3\t\t; Get non aligned bytes.\n\tsub\tebx,ecx\t\t; remove that from the total size to be copied later.\n\trep\tmovsb\t\t; do the copy.\n\tmov\tecx,ebx\t\t; Get number of bytes left.\n\tshr\tecx,2\t\t; Do 4 bytes at a time.\n\trep\tmovsd\t\t; do the dword copy.\n\tmov\tecx, ebx\n\tand\tecx,03h\n\trep\tmovsb\t\t; finnish the remaining bytes.\n\tret\n\nENDP\tMem_Copy\n\nPROC Largest_Mem_Block \tC near \n\tuses\tesi , edi , ebx , ecx , edx\n\tlocal\tmem_struct : dword : 16\n\n\tmov\teax , 0500h\n\tlea\tedi , [ mem_struct ]\n\tint\t31h\n\tmov\teax , [ mem_struct ]\n\n\tret\nENDP Largest_Mem_Block\n\nEND\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/MEM/OLDMEM/NEWDEL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory system.                           *\n *                                                                         *\n *                    File Name : NEWDEL.CPP                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : June 21, 1994                            *\n *                                                                         *\n *                  Last Update : October 20, 1994   [SKB]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   operator NEW -- Overides the global new function.                     *\n *   operator delete -- Overides the global delete function.               *\n *   operator NEW[] -- Overides the array version of new.                  *\n *   operator delete[] -- Overides the array version of delete[]           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwmem.h\"\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * OPERATOR NEW -- Overides the global new function.                       *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid * operator new(size_t size) \n{\n\treturn (Alloc((unsigned long) size, MEM_NEW));\n}\n\n\n/***************************************************************************\n * OPERATOR NEW[] -- Overides the array version of new.                    *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid * operator new[](size_t size) \n{\n\treturn (Alloc((unsigned long) size, MEM_NEW));\n}\n \n\n/***************************************************************************\n * OPERATOR DELETE -- Overides the global delete function.                 *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid operator delete(void *ptr) \n{\n\tFree(ptr);\n}\n\n/***************************************************************************\n * OPERATOR DELETE[] -- Overides the array version of delete[]           \t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/20/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid operator delete[](void *ptr) \n{\n\tFree(ptr);\n}\n\n\n\n"
  },
  {
    "path": "WIN32LIB/MEM/OLDMEM/WWMEM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory System                            *\n *                                                                         *\n *                    File Name : MEM.H                                    *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : April 4, 1994                            *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWMEM_H\n#define WWMEM_H\n\n#include \"wwstd.h\"\n#include \"new.h\"\n#include \"memflag.h\"\n\n// Defines\n//==============\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MEM.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint  Mem_Init(void *buffer, long size);\nvoid *Mem_Alloc(void *poolptr, long lsize, unsigned long id);\nint  Mem_Free(void *poolptr, void *buffer);\nvoid Mem_Reference(void *node);\nvoid Mem_Lock_Block(void *node);\nvoid Mem_In_Use(void *node);\nvoid *Mem_Find(void *poolptr, unsigned long id);\nunsigned long Mem_Get_ID(void *node);\nvoid *Mem_Find_Oldest(void *poolptr);\nvoid *Mem_Free_Oldest(void *poolptr);\nlong Mem_Pool_Size(void *poolptr);\nlong Mem_Avail(void *poolptr);\nlong Mem_Largest_Avail(void *poolptr);\nvoid Mem_Cleanup(void *poolptr);\n\n\n#endif\n\u001a\n"
  },
  {
    "path": "WIN32LIB/MEM/OLDMEM/WWMEM.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Memory System                            *\n;*                                                                         *\n;*                    File Name : WWMEM.INC                                *\n;*                                                                         *\n;*                   Programmer : Ian M. Leslie                            *\n;*                                                                         *\n;*                   Start Date : August 11, 1994                          *\n;*                                                                         *\n;*                  Last Update : August 17, 1994   [IML]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nMEM_NORMAL EQU 0000h\t\t; Default memory (normal).\nMEM_NEW\t   EQU 0001h\t\t; Called by the operator new and was overloaded.\nMEM_CLEAR  EQU 0002h \t\t;\n\nGLOBAL\t\t@Alloc$qul14MemoryFlagType:PROC\nGLOBAL\t\t@Free$qpv:PROC\n"
  },
  {
    "path": "WIN32LIB/MEM/VMPAGEIN.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : VMPAGEIN.ASM                             *\n;*                                                                         *\n;*                   Programmer : Steve Tall\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : March 8th, 1996\t[ST]               *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*  Force_VM_Page_In -- forces a buffer to be paged in under win95         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\t\tIDEAL\n\t\tP386\n\t\tMODEL USE32 FLAT\n\n\n\t\tLOCALS ??\n\n\nGLOBAL\t\tC Force_VM_Page_In:near\n\nCODESEG\n\n\n;***************************************************************************\n;* Force_VM_Page_In -- forces a buffer to be paged in under win95          *\n;*                                                                         *\n;*                                                                         *\n;* INPUT: ptr to start of buffer                                           *\n;*        length of buffer                                                 *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* Prototype:                                                              *\n;*  void Force_VM_Page_In (void *buffer, int length);                      *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   3/8/96 4:18PM ST : Created.                                           *\n;*=========================================================================*\n\n\nproc\t\tForce_VM_Page_In C near\n\t\tUSES\teax,ecx,edx,edi\n\t\tARG\tbuffer_start:dword\n\t\tARG\tbuffer_length:dword\n\n\t\tmov\tecx,[buffer_length]\n\t\txor\tal,al\n\t\ttest\tecx,ecx\n\t\tmov\tedx,4096\n\t\tjz\t??out\n\n\t\tmov\tedi,[buffer_start]\n\n\n??next_page:\tadd\t[edi],al\n\t\tadd\tedi,edx\n\t\tsub\tecx,edx\n\t\tjg\t??next_page\n\n??out:\t\tret\n\nendp\t\tForce_VM_Page_In\n\nEND\n"
  },
  {
    "path": "WIN32LIB/MEM/WWMEM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory System                            *\n *                                                                         *\n *                    File Name : MEM.H                                    *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : April 4, 1994                            *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWMEM_H\n#define WWMEM_H\n\n#include \"wwstd.h\"\n#include \"new.h\"\n#include \"memflag.h\"\n\n// Defines\n//==============\n\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MEM.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint  Mem_Init(void *buffer, long size);\nvoid *Mem_Alloc(void *poolptr, long lsize, unsigned long id);\nint  Mem_Free(void *poolptr, void *buffer);\nvoid Mem_Reference(void *node);\nvoid Mem_Lock_Block(void *node);\nvoid Mem_In_Use(void *node);\nvoid *Mem_Find(void *poolptr, unsigned long id);\nunsigned long Mem_Get_ID(void *node);\nvoid *Mem_Find_Oldest(void *poolptr);\nvoid *Mem_Free_Oldest(void *poolptr);\nlong Mem_Pool_Size(void *poolptr);\nlong Mem_Avail(void *poolptr);\nlong Mem_Largest_Avail(void *poolptr);\nvoid Mem_Cleanup(void *poolptr);\n\n\n#endif\n\u001a\n"
  },
  {
    "path": "WIN32LIB/MEM/WWMEM.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Memory System                            *\n;*                                                                         *\n;*                    File Name : WWMEM.INC                                *\n;*                                                                         *\n;*                   Programmer : Ian M. Leslie                            *\n;*                                                                         *\n;*                   Start Date : August 11, 1994                          *\n;*                                                                         *\n;*                  Last Update : August 17, 1994   [IML]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nMEM_NORMAL EQU 0000h\t\t; Default memory (normal).\nMEM_NEW\t   EQU 0001h\t\t; Called by the operator new and was overloaded.\nMEM_CLEAR  EQU 0002h \t\t;\n\nGLOBAL\t\t@Alloc$qul14MemoryFlagType:PROC\nGLOBAL\t\t@Free$qpv:PROC\n"
  },
  {
    "path": "WIN32LIB/MISC/CLIPRECT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Support Library                          *\n;*                                                                         *\n;*                    File Name : cliprect.asm                             *\n;*                                                                         *\n;*                   Programmer : Julio R Jerez                            *\n;*                                                                         *\n;*                   Start Date : Mar, 2 1995                              *\n;*                                                                         *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* int Clip_Rect ( int * x , int * y , int * dw , int * dh , \t\t   *\n;*\t       \t   int width , int height ) ;          \t\t\t   *\n;* int Confine_Rect ( int * x , int * y , int * dw , int * dh , \t   *\n;*\t       \t      int width , int height ) ;          \t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\t C Clip_Rect\t:NEAR\nGLOBAL\t C Confine_Rect\t:NEAR\n\nCODESEG\n\n;***************************************************************************\n;* Clip_Rect -- clip a given rectangle against a given window\t\t   *\n;*                                                                         *\n;* INPUT:   &x , &y , &w , &h  -> Pointer to rectangle being clipped       *\n;*          width , height     -> dimension of clipping window             *\n;*                                                                         *\n;* OUTPUT: a) Zero if the rectangle is totally contained by the \t   *\n;*\t      clipping window.\t\t\t\t\t\t   *\n;*\t   b) A negative value if the rectangle is totally outside the     *\n;*            the clipping window\t\t\t\t\t   *\n;*\t   c) A positive value if the rectangle\twas clipped against the\t   *\n;*\t      clipping window, also the values pointed by x, y, w, h will  *\n;*\t      be modified to new clipped values\t \t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*   05/03/1995 JRJ : added comment                                        *\n;*=========================================================================*\n; int Clip_Rect (int* x, int* y, int* dw, int* dh, int width, int height);          \t\t\t   *\n\n\tPROC\tClip_Rect C near\n\tuses\tebx,ecx,edx,esi,edi\n\targ\tx:dword\n\targ\ty:dword\n\targ\tw:dword\n\targ\th:dword\n\targ\twidth:dword\n\targ\theight:dword\n\n;This Clipping algorithm is a derivation of the very well known\n;Cohen-Sutherland Line-Clipping test. Due to its simplicity and efficiency\n;it is probably the most commontly implemented algorithm both in software\n;and hardware for clipping lines, rectangles, and convex polygons against\n;a rectagular clipping window. For reference see\n;\"COMPUTER GRAPHICS principles and practice by Foley, Vandam, Feiner, Hughes\n; pages 113 to 177\".\n; Briefly consist in computing the Sutherland code for both end point of\n; the rectangle to find out if the rectangle is:\n; - trivially accepted (no further clipping test, return the oroginal data)\n; - trivially rejected (return with no action, return error code)\n; - retangle must be iteratively clipped again edges of the clipping window\n;   and return the clipped rectangle\n\n\t; get all four pointer into regisnters\n\tmov\tesi,[x]\t\t; esi = pointer to x\n\tmov\tedi,[y]\t\t; edi = pointer to x\n\tmov\teax,[w]\t\t; eax = pointer to dw\n\tmov\tebx,[h]\t\t; ebx = pointer to dh\n\n\t; load the actual data into reg\n\tmov\tesi,[esi]\t; esi = x0\n\tmov\tedi,[edi]\t; edi = y0\n\tmov\teax,[eax]\t; eax = dw\n\tmov\tebx,[ebx]\t; ebx = dh\n\n\t; create a wire frame of the type [x0,y0] , [x1,y1]\n\tadd\teax,esi\t\t; eax = x1 = x0 + dw\n\tadd\tebx,edi\t\t; ebx = y1 = y0 + dh\n\n\t; we start we suthenland code0 and code1 set to zero\n\txor \tecx,ecx\t\t; cl = sutherland boolean code0\n\txor \tedx,edx\t\t; dl = sutherland boolean code0\n\n\t; now we start computing the to suthenland boolean code for x0 , x1\n\tshld\tecx,esi,1\t; bit3 of code0 = sign bit of (x0 - 0)\n\tshld\tedx,eax,1 \t; bit3 of code1 = sign bit of (x1 - 0)\n\tsub\tesi,[width]\t; get the difference (x0 - (width + 1))\n\tsub\teax,[width]\t; get the difference (x1 - (width + 1))\n\tdec\tesi\n\tdec\teax\n\tshld\tecx,esi,1\t; bit2 of code0 = sign bit of (x0 - (width + 1))\n\tshld\tedx,eax,1\t; bit2 of code1 = sign bit of (x0 - (width + 1))\n\n\t; now we start computing the to suthenland boolean code for y0 , y1\n\tshld\tecx,edi,1   \t; bit1 of code0 = sign bit of (y0 - 0)\n\tshld\tedx,ebx,1\t; bit1 of code1 = sign bit of (y0 - 0)\n\tsub\tedi,[height]\t; get the difference (y0 - (height + 1))\n\tsub\tebx,[height]\t; get the difference (y1 - (height + 1))\n\tdec\tedi\n\tdec\tebx\n\tshld\tecx,edi,1\t; bit0 of code0 = sign bit of (y0 - (height + 1))\n\tshld\tedx,ebx,1\t; bit0 of code1 = sign bit of (y1 - (height + 1))\n\n\t; Bit 2 and 0 of cl and bl are complemented\n\txor\tcl,5\t\t; reverse bit2 and bit0 in code0\n\txor\tdl,5 \t\t; reverse bit2 and bit0 in code1\n\n\t; now perform the rejection test\n\tmov\teax,-1\t\t; set return code to false\n\tmov\tbl,cl \t\t; save code0 for future use\n\ttest\tdl,cl  \t\t; if any two pair of bit in code0 and code1 is set\n\tjnz\t??clip_out\t; then rectangle is outside the window\n\n\t; now perform the aceptance test\n\txor\teax,eax\t\t; set return code to true\n\tor\tbl,dl\t\t; if all pair of bits in code0 and code1 are reset\n\tjz\t??clip_out\t; then rectangle is insize the window.\t\t\t\t\t\t\t\t      '\n\n\t; we need to clip the rectangle iteratively\n\tmov\teax,-1\t\t; set return code to false\n\ttest\tcl,1000b\t; if bit3 of code0 is set then the rectangle\n\tjz\t??left_ok\t; spill out the left edge of the window\n\tmov\tedi,[x]\t\t; edi = a pointer to x0\n\tmov\tebx,[w]\t\t; ebx = a pointer to dw\n\tmov\tesi,[edi]\t; esi = x0\n\tmov\t[dword ptr edi],0 ; set x0 to 0 \"this the left edge value\"\n\tadd\t[ebx],esi\t; adjust dw by x0, since x0 must be negative\n\n??left_ok:\n\ttest\tcl,0010b\t; if bit1 of code0 is set then the rectangle\n\tjz\t??bottom_ok\t; spill out the bottom edge of the window\n\tmov\tedi,[y]\t\t; edi = a pointer to y0\n\tmov\tebx,[h]\t\t; ebx = a pointer to dh\n\tmov\tesi,[edi]\t; esi = y0\n\tmov\t[dword ptr edi],0 ; set y0 to 0 \"this the bottom edge value\"\n\tadd\t[ebx],esi\t; adjust dh by y0, since y0 must be negative\n\n??bottom_ok:\n\ttest\tdl,0100b\t; if bit2 of code1 is set then the rectangle\n\tjz\t??right_ok\t; spill out the right edge of the window\n\tmov\tedi,[w] \t; edi = a pointer to dw\n\tmov\tesi,[x]\t\t; esi = a pointer to x\n\tmov\tebx,[width]\t; ebx = the width of the window\n\tsub\tebx,[esi] \t; the new dw is the difference (width-x0)\n\tmov\t[edi],ebx\t; adjust dw to (width - x0)\n\tjle\t??clip_out\t; if (width-x0) = 0 then the clipped retangle\n\t\t\t\t; has no width we are done\n??right_ok:\n\ttest\tdl,0001b\t; if bit0 of code1 is set then the rectangle\n\tjz\t??clip_ok\t; spill out the top edge of the window\n\tmov\tedi,[h] \t; edi = a pointer to dh\n\tmov\tesi,[y]\t\t; esi = a pointer to y0\n\tmov\tebx,[height]\t; ebx = the height of the window\n\tsub\tebx,[esi] \t; the new dh is the difference (height-y0)\n\tmov\t[edi],ebx\t; adjust dh to (height-y0)\n\tjle\t??clip_out\t; if (width-x0) = 0 then the clipped retangle\n\t\t\t\t; has no width we are done\n??clip_ok:\n\tmov\teax,1  \t; signal the calling program that the rectangle was modify\n??clip_out:\n\tret\n\tENDP\tClip_Rect\n\n\n;***************************************************************************\n;* Confine_Rect -- clip a given rectangle against a given window\t   *\n;*                                                                         *\n;* INPUT:   &x,&y,w,h    -> Pointer to rectangle being clipped       *\n;*          width,height     -> dimension of clipping window             *\n;*                                                                         *\n;* OUTPUT: a) Zero if the rectangle is totally contained by the \t   *\n;*\t      clipping window.\t\t\t\t\t\t   *\n;*\t   c) A positive value if the rectangle\twas shifted in position    *\n;*\t      to fix inside the clipping window, also the values pointed   *\n;*\t      by x, y, will adjusted to a new values\t \t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*  NOTE:  this function make not attempt to verify if the rectangle is\t   *\n;*\t   bigger than the clipping window and at the same time wrap around*\n;*\t   it. If that is the case the result is meaningless\t\t   *\n;*=========================================================================*\n; int Confine_Rect (int* x, int* y, int dw, int dh, int width, int height);          \t\t\t   *\n\n\tPROC\tConfine_Rect C near\n\tuses\tebx, esi,edi\n\targ\tx:dword\n\targ\ty:dword\n\targ\tw:dword\n\targ\th:dword\n\targ\twidth :dword\n\targ\theight:dword\n\n\txor\teax,eax\n\tmov\tebx,[x]\n\tmov\tedi,[w]\n\n\tmov\tesi,[ebx]\n\tadd\tedi,[ebx]\n\n\tsub\tedi,[width]\n\tneg\tesi\n\tdec\tedi\n\n\ttest\tesi,edi\n\tjl\t??x_axix_ok\n\tmov\teax,1\n\n\ttest\tesi,esi\n\tjl\t??shift_right\n\tmov\t[dword ptr ebx],0\n\tjmp\t??x_axix_ok\n??shift_right:\n\tinc\tedi\n\tsub\t[ebx],edi\n??x_axix_ok:\n\tmov\tebx,[y]\n\tmov\tedi,[h]\n\n\tmov\tesi,[ebx]\n\tadd\tedi,[ebx]\n\n\tsub\tedi,[height]\n\tneg\tesi\n\tdec\tedi\n\n\ttest\tesi,edi\n\tjl\t??confi_out\n\tmov\teax,1\n\n\ttest\tesi,esi\n\tjl\t??shift_top\n\tmov\t[dword ptr ebx],0\n\tret\n??shift_top:\n\tinc\tedi\n\tsub\t[ebx],edi\n??confi_out:\n\tret\n\n\tENDP\tConfine_Rect\n\n \tEND\n"
  },
  {
    "path": "WIN32LIB/MISC/CRC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : CRC.ASM                                  *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : June 12, 1992                            *\n;*                                                                         *\n;*                  Last Update : February 10, 1995 [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\tC Calculate_CRC\t:NEAR\n\n\tCODESEG\n\n; LONG Calculate_CRC(VOID *buffer, LONG length);\n\tPROC\tCalculate_CRC C near\n\tUSES \tesi\n\n\tARG\tbuffer:DWORD\n\tARG\tlength:DWORD\n\n\tLOCAL\tcrc:DWORD\n\n\t; Load pointer to data block.\n\tmov\t[crc],0\n\tpushad\n\tmov\tesi,[buffer]\n\tcld\n\n\t; Clear CRC to default (NULL) value.\n\txor\tebx,ebx\n\n\t; Fetch the length of the data block to CRC.\n\tmov\tecx,[length]\n\tjecxz\tshort ??fini\n\n\t; Prepare the length counters.\n\tmov\tedx,ecx\n\tand\tdl,011b\n\tshr\tecx,2\n\n\t; Perform the bulk of the CRC scanning.\n\tjecxz\tshort ??remainder\n??accumloop:\n\tlodsd\n\trol\tebx,1\n\tadd\tebx,eax\n\tloop\t??accumloop\n\n\t; Handle the remainder bytes.\n??remainder:\n\tor\tdl,dl\n\tjz\tshort ??fini\n\tmov\tecx,edx\n\txor\teax,eax\n\n\tand \tecx,0FFFFh\n\tpush\tecx\n??nextbyte:\n\tlodsb\n\tror\teax,8\n\tloop\t??nextbyte\n\tpop\tecx\n\tneg\tecx\n\tadd\tecx,4\n\tshl\tecx,3\n\tror\teax,cl\n\n;??nextbyte:\n;\tshl\teax,8\n;\tlodsb\n;\tloop\t??nextbyte\n\trol\tebx,1\n\tadd\tebx,eax\n\n??fini:\n\tmov\t[crc],ebx\n\tpopad\n\tmov\teax,[crc]\n\tret\n\n\tENDP\tCalculate_CRC\n\n\tEND"
  },
  {
    "path": "WIN32LIB/MISC/DDRAW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Win32 Library                   *\n *                                                                         *\n *                    File Name : DDRAW.CPP                                *\n *                                                                         *\n *                   Programmer : Philip W. Gorrow                         *\n *                                                                         *\n *                   Start Date : October 10, 1995                         *\n *                                                                         *\n *                  Last Update : October 10, 1995   []                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n#include \"misc.h\"\n#include <gbuffer.h>\n#include <palette.h>\n\n\nLPDIRECTDRAW\t\tDirectDrawObject=NULL;\t// Pointer to the direct draw object\nLPDIRECTDRAW2\tDirectDraw2Interface = NULL;  \t// Pointer to direct draw 2 interface\n\nHWND\t\t\tMainWindow;\t\t\t\t\t// Handle to programs main window\n\t\t\t\t\t\t\t\t\t\t\t\t// this is passed to SetCooperativeLevel\n\t\t\t\t\t\t\t\t\t\t\t\t// so DirectDraw knows which window is ours\n\n\nPALETTEENTRY\t\t\t\tPaletteEntries[256];\t\t// 256 windows palette entries\nLPDIRECTDRAWPALETTE\tPalettePtr;\t\t\t\t\t// Pointer to direct draw palette object\nBOOL\t\t\t\t\t\tFirstPaletteSet=FALSE;\t// Is this the first time 'Set_Palette' has been called?\nLPDIRECTDRAWSURFACE\tPaletteSurface=NULL;\nSurfaceMonitorClass\tAllSurfaces;\t\t\t\t//List of all direct draw surfaces\nBOOL\t\t\t\t\t\tCanVblankSync = TRUE;\n\nBOOL\t\t\t\t\t\tSystemToVideoBlits =FALSE;\t// Does hardware support system mem to video mem blits?\nBOOL\t\t\t\t\t\tVideoToSystemBlits =FALSE;\t// Does hardware support video mem to system mem blits?\nBOOL\t\t\t\t\t\tSystemToSystemBlits = FALSE; \t// Does hardware support system mem to system mem blits?\nBOOL\t\t\t\t\t\tOverlappedVideoBlits = TRUE;\t// Can video driver blit overlapped regions?\n\n/*\n** Function to call if we detect focus loss\n*/\nextern\tvoid (*Misc_Focus_Loss_Function)(void) = NULL;\nextern\tvoid (*Misc_Focus_Restore_Function)(void) = NULL;\n\n\n/***********************************************************************************************\n * Process_DD_Result -- Does a message box based on the result of a DD command                 *\n *                                                                                             *\n * INPUT:\t\tHRESULT result\t\t\t\t- the result returned from the direct draw command\t\t  *\n *             int     display_ok_msg\t- should a message be displayed if command ok\t\t\t  *                                                                                      *\n *                                                                                             *\n * OUTPUT:\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/27/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid Process_DD_Result(HRESULT result, int display_ok_msg)\n{\n\tswitch (result) {\n\t\tcase DD_OK:\n\t\t\tif (display_ok_msg) {\n\t\t\t\tMessageBox(MainWindow, \"Direct Draw request went ok.\", \"Note\", MB_ICONEXCLAMATION|MB_OK);\n         }\n\t\t\tbreak;\n\t\tcase DDERR_ALREADYINITIALIZED:\n\t\t\tMessageBox(MainWindow, \"This object is already initialized \",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_BLTFASTCANTCLIP:\n\t\t\tMessageBox(MainWindow, \"Return if a clipper object is attached to the source surface passed into a BltFast call.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_CANNOTATTACHSURFACE:\n\t\t\tMessageBox(MainWindow, \"This surface can not be attached to the requested surface.\t\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_CANNOTDETACHSURFACE:\n\t\t\tMessageBox(MainWindow, \"This surface can not be detached from the requested surface.\t\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_CANTCREATEDC:\n\t\t\tMessageBox(MainWindow, \"Windows can not create any more DCs\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_CANTDUPLICATE:\n\t\t\tMessageBox(MainWindow, \"Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_CANTLOCKSURFACE:\n\t\t\tMessageBox(MainWindow, \"Unable to lock surface because no driver exists which can supply a pointer to the surface.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_CLIPPERISUSINGHWND:\n\t\t\tMessageBox(MainWindow, \"An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_COLORKEYNOTSET:\n\t\t\tMessageBox(MainWindow, \"No src color key specified for this operation.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_CURRENTLYNOTAVAIL:\n\t\t\tMessageBox(MainWindow, \"Support is currently not available.\t\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_DIRECTDRAWALREADYCREATED:\n\t\t\tMessageBox(MainWindow, \"A DirectDraw object representing this driver has already been created for this process.\t\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_EXCEPTION:\n\t\t\tMessageBox(MainWindow, \"An exception was encountered while performing the requested operation.\t\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_EXCLUSIVEMODEALREADYSET:\n\t\t\tMessageBox(MainWindow, \"An attempt was made to set the cooperative level when it was already set to exclusive.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_GENERIC:\n\t\t\tMessageBox(MainWindow, \"Generic failure.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_HEIGHTALIGN:\n\t\t\tMessageBox(MainWindow, \"Height of rectangle provided is not a multiple of reqd alignment.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_HWNDALREADYSET:\n\t\t\tMessageBox(MainWindow, \"The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or palettes created.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_HWNDSUBCLASSED:\n\t\t\tMessageBox(MainWindow, \"HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring state.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_IMPLICITLYCREATED:\n\t\t\tMessageBox(MainWindow, \"This surface can not be restored because it is an implicitly created surface.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INCOMPATIBLEPRIMARY:\n\t\t\tMessageBox(MainWindow, \"Unable to match primary surface creation request with existing primary surface.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDCAPS:\n\t\t\tMessageBox(MainWindow, \"One or more of the caps bits passed to the callback are incorrect.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDCLIPLIST:\n\t\t\tMessageBox(MainWindow, \"DirectDraw does not support the provided cliplist.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDDIRECTDRAWGUID:\n\t\t\tMessageBox(MainWindow, \"The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDMODE:\n\t\t\tMessageBox(MainWindow, \"DirectDraw does not support the requested mode.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDOBJECT:\n\t\t\tMessageBox(MainWindow, \"DirectDraw received a pointer that was an invalid DIRECTDRAW object.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDPARAMS:\n\t\t\tMessageBox(MainWindow, \"One or more of the parameters passed to the function are incorrect.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDPIXELFORMAT:\n\t\t\tMessageBox(MainWindow, \"The pixel format was invalid as specified.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDPOSITION:\n\t\t\tMessageBox(MainWindow, \"Returned when the position of the overlay on the destination is no longer legal for that destination.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDRECT:\n\t\t\tMessageBox(MainWindow, \"Rectangle provided was invalid.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\n\t\tcase DDERR_INVALIDSURFACETYPE:\n\t\t\tMessageBox(MainWindow, \"The requested action could not be performed because the surface was of the wrong type.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_LOCKEDSURFACES:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because one or more surfaces are locked.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NO3D:\n\t\t\tMessageBox(MainWindow, \"There is no 3D present.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOALPHAHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no alpha accleration hardware present or available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n#if(0)\n\t\tcase DDERR_NOANTITEARHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no hardware support for synchronizing blts to avoid tearing.\t\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n#endif\n\t\tcase DDERR_NOBLTHW:\n\t\t\tMessageBox(MainWindow, \"No blter hardware present.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n#if(0)\n\t\tcase DDERR_NOBLTQUEUEHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no hardware support for asynchronous blting.\t\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n#endif\n\t\tcase DDERR_NOCLIPLIST:\n\t\t\tMessageBox(MainWindow, \"No cliplist available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOCLIPPERATTACHED:\n\t\t\tMessageBox(MainWindow, \"No clipper object attached to surface object.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOCOLORCONVHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no color conversion hardware present or available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOCOLORKEY:\n\t\t\tMessageBox(MainWindow, \"Surface doesn't currently have a color key\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOCOLORKEYHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no hardware support of the destination color key.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOCOOPERATIVELEVELSET:\n\t\t\tMessageBox(MainWindow, \"Create function called without DirectDraw object method SetCooperativeLevel being called.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NODC:\n\t\t\tMessageBox(MainWindow, \"No DC was ever created for this surface.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NODDROPSHW:\n\t\t\tMessageBox(MainWindow, \"No DirectDraw ROP hardware.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NODIRECTDRAWHW:\n\t\t\tMessageBox(MainWindow, \"A hardware-only DirectDraw object creation was attempted but the driver did not support any hardware.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NODIRECTDRAWSUPPORT:\n\t\t\tMessageBox(MainWindow, \"No DirectDraw support possible with current display driver.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOEMULATION:\n\t\t\tMessageBox(MainWindow, \"Software emulation not available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOEXCLUSIVEMODE:\n\t\t\tMessageBox(MainWindow, \"Operation requires the application to have exclusive mode but the application does not have exclusive mode.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOFLIPHW:\n\t\t\tMessageBox(MainWindow, \"Flipping visible surfaces is not supported.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOGDI:\n\t\t\tMessageBox(MainWindow, \"There is no GDI present.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOHWND:\n\t\t\tMessageBox(MainWindow, \"Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOMIRRORHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no hardware present or available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOOVERLAYDEST:\n\t\t\tMessageBox(MainWindow, \"Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on to establish a destination.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOOVERLAYHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no overlay hardware present or available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOPALETTEATTACHED:\n\t\t\tMessageBox(MainWindow, \"No palette object attached to this surface.\t\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOPALETTEHW:\n\t\t\tMessageBox(MainWindow, \"No hardware support for 16 or 256 color palettes.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NORASTEROPHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no appropriate raster op hardware present or available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOROTATIONHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no rotation hardware present or available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOSTRETCHHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no hardware support for stretching.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOT4BITCOLOR:\n\t\t\tMessageBox(MainWindow, \"DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOT4BITCOLORINDEX:\n\t\t\tMessageBox(MainWindow, \"DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOT8BITCOLOR:\n\t\t\tMessageBox(MainWindow, \"DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOTAOVERLAYSURFACE:\n\t\t\tMessageBox(MainWindow, \"Returned when an overlay member is called for a non-overlay surface.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOTEXTUREHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no texture mapping hardware present or available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOTFLIPPABLE:\n\t\t\tMessageBox(MainWindow, \"An attempt has been made to flip a surface that is not flippable.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOTFOUND:\n\t\t\tMessageBox(MainWindow, \"Requested item was not found.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOTLOCKED:\n\t\t\tMessageBox(MainWindow, \"Surface was not locked.  An attempt to unlock a surface that was not locked at all, or by this process, has been attempted.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOTPALETTIZED:\n\t\t\tMessageBox(MainWindow, \"The surface being used is not a palette-based surface.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOVSYNCHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no hardware support for vertical blank synchronized operations.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOZBUFFERHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no hardware support for zbuffer blting.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOZOVERLAYHW:\n\t\t\tMessageBox(MainWindow, \"Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_OUTOFCAPS:\n\t\t\tMessageBox(MainWindow, \"The hardware needed for the requested operation has already been allocated.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_OUTOFMEMORY:\n\t\t\tMessageBox(MainWindow, \"DirectDraw does not have enough memory to perform the operation.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_OUTOFVIDEOMEMORY:\n\t\t\tMessageBox(MainWindow, \"DirectDraw does not have enough memory to perform the operation.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_OVERLAYCANTCLIP:\n\t\t\tMessageBox(MainWindow, \"The hardware does not support clipped overlays.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_OVERLAYCOLORKEYONLYONEACTIVE:\n\t\t\tMessageBox(MainWindow, \"Can only have ony color key active at one time for overlays.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_OVERLAYNOTVISIBLE:\n\t\t\tMessageBox(MainWindow, \"Returned when GetOverlayPosition is called on a hidden overlay.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_PALETTEBUSY:\n\t\t\tMessageBox(MainWindow, \"Access to this palette is being refused because the palette is already locked by another thread.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_PRIMARYSURFACEALREADYEXISTS:\n\t\t\tMessageBox(MainWindow, \"This process already has created a primary surface.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_REGIONTOOSMALL:\n\t\t\tMessageBox(MainWindow, \"Region passed to Clipper::GetClipList is too small.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_SURFACEALREADYATTACHED:\n\t\t\tMessageBox(MainWindow, \"This surface is already attached to the surface it is being attached to.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_SURFACEALREADYDEPENDENT:\n\t\t\tMessageBox(MainWindow, \"This surface is already a dependency of the surface it is being made a dependency of.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_SURFACEBUSY:\n\t\t\tMessageBox(MainWindow, \"Access to this surface is being refused because the surface is already locked by another thread.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_SURFACEISOBSCURED:\n\t\t\tMessageBox(MainWindow, \"Access to surface refused because the surface is obscured.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_SURFACELOST:\n\t\t\tMessageBox(MainWindow, \"Access to this surface is being refused because the surface memory is gone. The DirectDrawSurface object representing this surface should have Restore called on it.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_SURFACENOTATTACHED:\n\t\t\tMessageBox(MainWindow, \"The requested surface is not attached.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_TOOBIGHEIGHT:\n\t\t\tMessageBox(MainWindow, \"Height requested by DirectDraw is too large.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_TOOBIGSIZE:\n\t\t\tMessageBox(MainWindow, \"Size requested by DirectDraw is too large --\tthe individual height and width are OK.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_TOOBIGWIDTH:\n\t\t\tMessageBox(MainWindow, \"Width requested by DirectDraw is too large.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_UNSUPPORTED:\n\t\t\tMessageBox(MainWindow, \"Action not supported.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_UNSUPPORTEDFORMAT:\n\t\t\tMessageBox(MainWindow, \"FOURCC format requested is unsupported by DirectDraw.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_UNSUPPORTEDMASK:\n\t\t\tMessageBox(MainWindow, \"Bitmask in the pixel format requested is unsupported by DirectDraw.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_VERTICALBLANKINPROGRESS:\n\t\t\tMessageBox(MainWindow, \"Vertical blank is in progress.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_WASSTILLDRAWING:\n\t\t\tMessageBox(MainWindow, \"Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is incomplete.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_WRONGMODE:\n\t\t\tMessageBox(MainWindow, \"This surface can not be restored because it was created in a different mode.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_XALIGN:\n\t\t\tMessageBox(MainWindow, \"Rectangle provided was not horizontally aligned on required boundary.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tchar string[256];\n\t\t\tsprintf (string, \"Unrecognised Direct Draw result code: %d\", result & 0xffff);\n\t\t\tMessageBox(MainWindow, string,\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t}\n}\n\n\n\n/***********************************************************************************************\n * Check_Overlapped_Blit_Capability -- See if video driver supports blitting overlapped regions*\n *                                                                                             *\n *  We will check for this by drawing something to a video page and blitting it over itself.   *\n * If we end up with the top line repeating then overlapped region blits dont work.            *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/7/96 5:06PM ST : Created                                                               *\n *=============================================================================================*/\nvoid Check_Overlapped_Blit_Capability(void)\n{\n\n\t/*\n\t** Assume we can until we find out otherwise\n\t*/\n\tOverlappedVideoBlits = TRUE;\n\n\tGraphicBufferClass test_buffer;\n\n\ttest_buffer.Init (64, 64, NULL, 0, (GBC_Enum)GBC_VIDEOMEM);\n\n\ttest_buffer.Clear();\n\n\t/*\n\t** Plot a pixel in the top left corner of the buffer.\n\t*/\n\ttest_buffer.Put_Pixel(0, 0, 255);\n\n\t/*\n\t** Blit the buffer down by one line. If we end up with a vertical strip of pixel 255's then\n\t** overlapped blits dont work\n\t*/\n\n\ttest_buffer.Blit(test_buffer, 0, 0, 0, 1, test_buffer.Get_Width(), test_buffer.Get_Height()-1);\n\n\tif (test_buffer.Get_Pixel (0 ,5) == 255) OverlappedVideoBlits = FALSE;\n}\n\n\n\n/***********************************************************************************************\n * Set_Video_Mode -- Initializes Direct Draw and sets the required Video Mode                  *\n *                                                                                             *\n * INPUT:  \t\tint width   \t\t\t- the width of the video mode in pixels\t\t\t\t\t\t  *\n *\t\t\t\t\tint height           - the height of the video mode in pixels                   *\n *\t\t\t\t\tint bits_per_pixel\t- the number of bits per pixel the video mode supports     *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/26/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nBOOL Set_Video_Mode(HWND hwnd, int w, int h, int bits_per_pixel)\n{\n\tHRESULT result;\n\t//\n\t// If there is not currently a direct draw object then we need to define one.\n\t//\n\tif ( DirectDrawObject == NULL ){\n\t\t//MessageBox(MainWindow, \"In Set_Video_Mode. About to call DirectDrawCreate.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\tresult = DirectDrawCreate(NULL, &DirectDrawObject, NULL);\n\t\tProcess_DD_Result(result, FALSE);\n\t\tif (result == DD_OK){\n\t\t\tif (w==320){\n\t\t\t\tresult = DirectDrawObject->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX);\n\t\t\t} else {\n\t\t\t\t//MessageBox(MainWindow, \"In Set_Video_Mode. About to call SetCooperativeLevel.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\t\tresult = DirectDrawObject->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);\n\t\t\t}\n\t\t\tProcess_DD_Result(result, FALSE);\n\t\t}else{\n\t\t\treturn (FALSE);\n\t\t}\n\t}\n\n\t//\n\t// Set the required display mode with 8 bits per pixel\n\t//\n\t//MessageBox(MainWindow, \"In Set_Video_Mode. About to call call SetDisplayMode.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\tresult = DirectDrawObject->SetDisplayMode ( w , h , bits_per_pixel );\n\tif (result != DD_OK){\n//\t\tProcess_DD_Result(result, FALSE);\n\t\tDirectDrawObject->Release();\n\t\tDirectDrawObject = NULL;\n\t\treturn(FALSE);\n\t}\n\n\t//\n\t// Create a direct draw palette object\n\t//\n\t//MessageBox(MainWindow, \"In Set_Video_Mode. About to call CreatePalette.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\tresult = DirectDrawObject->CreatePalette( DDPCAPS_8BIT | DDPCAPS_ALLOW256, &PaletteEntries[0] , &PalettePtr ,NULL);\n\tProcess_DD_Result(result, FALSE);\n\tif (result != DD_OK){\n\t\treturn (FALSE);\n\t}\n\n\tCheck_Overlapped_Blit_Capability();\n\n\t//MessageBox(MainWindow, \"In Set_Video_Mode. About to return success.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n#if (0)\n\t/*\n\t** Find out if DirectX 2 extensions are available\n\t*/\n\tresult = DirectDrawObject->QueryInterface (IID_IDirectDraw2, (LPVOID*)&DirectDraw2Interface);\n\tSystemToVideoBlits = FALSE;\n\tVideoToSystemBlits = FALSE;\n\tSystemToSystemBlits= FALSE;\n\tif (result != DD_OK){\n\t\tDirectDraw2Interface = NULL;\n\t}else{\n\t\tDDCAPS capabilities;\n\t\tDDCAPS emulated_capabilities;\n\n\t\tmemset ((char*)&capabilities, 0, sizeof(capabilities));\n\t\tmemset ((char*)&emulated_capabilities, 0, sizeof(emulated_capabilities));\n\t\tcapabilities.dwSize = sizeof (capabilities);\n\t\temulated_capabilities.dwSize = sizeof (emulated_capabilities);\n\n\t\tDirectDrawObject->GetCaps (&capabilities, &emulated_capabilities);\n\n\t\tif (capabilities.dwCaps & DDCAPS_CANBLTSYSMEM){\n\t\t\tSystemToVideoBlits = (capabilities.dwSVBCaps & DDCAPS_BLT) ? TRUE : FALSE;\n\t\t\tVideoToSystemBlits = (capabilities.dwVSBCaps & DDCAPS_BLT) ? TRUE : FALSE;\n\t\t\tSystemToSystemBlits = (capabilities.dwSSBCaps & DDCAPS_BLT) ? TRUE : FALSE;\n\t\t}\n\t}\n#endif\t//(0)\n\n\t//MessageBox(MainWindow, \"In Set_Video_Mode. About to return success.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\n\treturn (TRUE);\n\n}\n\n/***********************************************************************************************\n * Reset_Video_Mode -- Resets video mode and deletes Direct Draw Object                        *\n *                                                                                             *\n * INPUT:\t\tnone                                                                            *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/26/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid Reset_Video_Mode(void)\n{\n\tHRESULT result;\n\n\t//\n\t// If a direct draw object has been declared and a video mode has been set\n\t// then reset the video mode and release the direct draw object.\n\t//\n\tif ( DirectDrawObject ) {\n\t\tresult = DirectDrawObject->RestoreDisplayMode();\n\t\tProcess_DD_Result(result, FALSE);\n\t\tresult = DirectDrawObject->Release();\n\t\tProcess_DD_Result(result, FALSE);\n\n\t\tDirectDrawObject = NULL;\n\t}\n}\n\n\n\n\n/***********************************************************************************************\n * Get_Free_Video_Memory -- returns amount of free video memory                                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   bytes of available video RAM                                                      *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/29/95 12:52PM ST : Created                                                            *\n *=============================================================================================*/\nunsigned int Get_Free_Video_Memory(void)\n{\n\n\tDDCAPS\tvideo_capabilities;\n\n\tif (DirectDrawObject){\n\n\t\tvideo_capabilities.dwSize = sizeof (video_capabilities);\n\n\t\t//MessageBox(MainWindow, \"In Get_Free_Video_Memory. About to call GetCaps\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\tif (DD_OK == DirectDrawObject->GetCaps (&video_capabilities , NULL)){\n\t\t\tchar string [256];\n\t\t\tsprintf (string, \"In Get_Free_Video_Memory. About to return %d bytes\",video_capabilities.dwVidMemFree);\n\t\t\t//MessageBox(MainWindow, string,\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\treturn (video_capabilities.dwVidMemFree);\n\t\t}\n\t}\n\n\t//MessageBox(MainWindow, \"In Get_Free_Video_Memory. About to return failure\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\treturn (0);\n}\n\n\n\n\n/***********************************************************************************************\n * Get_Video_Hardware_Caps -- returns bitmask of direct draw video hardware support            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   hardware flags                                                                    *\n *                                                                                             *\n * WARNINGS: Must call Set_Video_Mode 1st to create the direct draw object                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/12/96 9:14AM ST : Created                                                              *\n *=============================================================================================*/\nunsigned Get_Video_Hardware_Capabilities(void)\n{\n\tDDCAPS\tvideo_capabilities;\n\tunsigned\tvideo;\n\n\t/*\n\t** Fail if the direct draw object has not been initialised\n\t*/\n\tif (!DirectDrawObject) return (0);\n\n\t/*\n\t** Get the capabilities of the direct draw object\n\t*/\n\tvideo_capabilities.dwSize = sizeof(video_capabilities);\n\t//MessageBox(MainWindow, \"In Get_Video_Hardware_Capabilities. About to call GetCaps\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\tHRESULT result = DirectDrawObject->GetCaps (&video_capabilities, NULL);\n\tif (result != DD_OK){\n\t\tProcess_DD_Result(result, FALSE);\n\t\treturn (0);\n\t}\n\n\t/*\n\t** Set flags to indicate the presence of the features we are interested in\n\t*/\n\tvideo = 0;\n\n\t/* Hardware blits supported? */\n\tif (video_capabilities.dwCaps & DDCAPS_BLT) \t\t\t\tvideo |= VIDEO_BLITTER;\n\n\t/* Hardware blits asyncronous? */\n\tif (video_capabilities.dwCaps & DDCAPS_BLTQUEUE) \t\tvideo |= VIDEO_BLITTER_ASYNC;\n\n\t/* Can palette changes be synced to vertical refresh? */\n\tif (video_capabilities.dwCaps & DDCAPS_PALETTEVSYNC) \tvideo |= VIDEO_SYNC_PALETTE;\n\n\t/* Is the video cards memory bank switched? */\n\tif (video_capabilities.dwCaps & DDCAPS_BANKSWITCHED) \tvideo |= VIDEO_BANK_SWITCHED;\n\n\t/* Can the blitter do filled rectangles? */\n\tif (video_capabilities.dwCaps & DDCAPS_BLTCOLORFILL)\tvideo |= VIDEO_COLOR_FILL;\n\n\t/* Is there no hardware assistance avaailable at all? */\n\tif (video_capabilities.dwCaps & DDCAPS_NOHARDWARE) \tvideo |= VIDEO_NO_HARDWARE_ASSIST;\n\n\t//MessageBox(MainWindow, \"In Get_Video_Hardware_Capabilities. About to return success.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\treturn (video);\n}\n\n\n\n\n/***********************************************************************************************\n * Wait_Vert_Blank -- Waits for the start (leading edge) of a vertical blank                   *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *=============================================================================================*/\nextern int ScreenWidth;\nvoid Wait_Vert_Blank(void)\n{\n\tif( ScreenWidth!=320 && CanVblankSync){\n\t\tHRESULT result = DirectDrawObject->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);\n\t\tif (result == E_NOTIMPL){\n\t\t\tCanVblankSync = FALSE;\n\t\t\treturn;\n\t\t}\n\t\tProcess_DD_Result(result, FALSE);\n\t}\n}\n\n\n\n\n\n/***********************************************************************************************\n * Set_Palette -- set a direct draw palette                                                    *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to 768 rgb palette bytes                                                      *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/11/95 3:33PM ST : Created                                                             *\n *=============================================================================================*/\nvoid Set_DD_Palette ( void *palette )\n{\n\n\t/*\n\t** Trap null ptr\n\t*/\n\tif (!palette) return;\n\n\tint\tj;\n\tint\tk;\n\tchar\t*palette_get;\n\n\tif ( DirectDrawObject && PaletteSurface ){\n\n\t\tk=0;\n\n\t\tpalette_get = (char*)palette;\n\n\t\tfor( j=0 ; j<768 ; j+=3 )\n\t\t{\n\t\t\tPaletteEntries[k].peRed = (unsigned char)((*palette_get++)<<2);\n\t\t\tPaletteEntries[k].peGreen = (unsigned char)((*palette_get++)<<2);\n\t\t\tPaletteEntries[k].peBlue = (unsigned char)((*palette_get++)<<2);\n\t\t\tk++;\n\t\t}\n\n\t\tif ( !FirstPaletteSet ){\n\t\t\t//MessageBox(MainWindow, \"In Set_DD_Palette. About to call SetPalette\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tPaletteSurface->SetPalette( PalettePtr );\n\t\t\tFirstPaletteSet=TRUE;\n\t\t}\n\n\t\t//MessageBox(MainWindow, \"In Set_DD_Palette. About to call SetEntries\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\tPalettePtr->SetEntries( 0 , 0 , 256 , &PaletteEntries[0] );\n\t}\n\t//MessageBox(MainWindow, \"Leaving Set_DD_Palette\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\n}\n\n\n\n\n\n/***********************************************************************************************\n * Wait_Blit -- waits for the DirectDraw blitter to become idle                                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07-25-95 03:53pm ST : Created                                                             *\n *=============================================================================================*/\n\nvoid Wait_Blit (void)\n{\n\tHRESULT\treturn_code;\n\n\tdo {\n\t\treturn_code=PaletteSurface->GetBltStatus (DDGBS_ISBLTDONE);\n\t} while (return_code != DD_OK && return_code != DDERR_SURFACELOST);\n\n}\n\n\n\n/***********************************************************************************************\n * SMC::SurfaceMonitorClass -- constructor for surface monitor class                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/3/95 3:23PM ST : Created                                                              *\n *=============================================================================================*/\n\nSurfaceMonitorClass::SurfaceMonitorClass(void)\n{\n\tfor (int i=0 ; i<MAX_SURFACES ; i++)\n\t{\n\t\tSurface[i]=NULL;\n\t}\n\tInFocus=FALSE;\n\tSurfacesRestored=FALSE;\n}\n\n\n/***********************************************************************************************\n * SMC::Add_DD_Surface -- add a new surface to the list                                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to surface                                                                    *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *                 11/3/95 3:24PM ST : Created                                                 *\n *=============================================================================================*/\nvoid SurfaceMonitorClass::Add_DD_Surface (LPDIRECTDRAWSURFACE new_surface)\n{\n\tif ( !Got_Surface_Already (new_surface) ){\n\t\tfor (int i=0 ; i<MAX_SURFACES ; i++)\n\t\t{\n\t\t\tif ( Surface[i]==NULL ){\n\t\t\t\tSurface[i]=new_surface;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * SMC::Remove_DD_Surface -- remove a direct draw surface from the list                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to Surface                                                                    *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/3/95 3:25PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid SurfaceMonitorClass::Remove_DD_Surface (LPDIRECTDRAWSURFACE old_surface)\n{\n\tfor (int i=0 ; i<MAX_SURFACES ; i++)\n\t{\n\t\tif ( Surface[i]==old_surface ){\n\t\t\tSurface[i]=NULL;\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * SMC::Got_Surface_Already -- check if a surface is already in the list                       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to surface                                                                    *\n *                                                                                             *\n * OUTPUT:   True if surface is in list                                                        *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/3/95 3:25PM ST : Created                                                              *\n *=============================================================================================*/\n\nBOOL SurfaceMonitorClass::Got_Surface_Already (LPDIRECTDRAWSURFACE test_surface)\n{\n\tfor (int i=0 ; i<MAX_SURFACES ; i++)\n\t{\n\t\tif ( Surface[i]==test_surface ){\n\t\t\treturn(TRUE);\n\t\t}\n\t}\n\treturn (FALSE);\n}\n\n/***********************************************************************************************\n * SMC::Restore_Surfaces -- restore the direct draw surfaces in the list                       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/3/95 3:26PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid SurfaceMonitorClass::Restore_Surfaces (void)\n{\n\tif (InFocus){\n\t\t/*\n\t\t** Call restore for each Direct Draw surface\n\t\t*/\n\t\tfor (int i=0 ; i<MAX_SURFACES ; i++)\n\t\t{\n\t\t\tif ( Surface[i] ){\n\t\t\t\tif (Surface[i]->Restore() != DD_OK){\n\t\t\t\t\tif (Misc_Focus_Loss_Function){\n\t\t\t\t\t\tMisc_Focus_Loss_Function();\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** PWG/ST: Now that we know all the surfaces are restored call\n\t\t** the function pointer to notify the program that it has\n\t\t** happened.  This function pointer is used to clear the pages,\n\t\t** etc.\n\t\t*/\n\t\tif (Misc_Focus_Restore_Function){\n\t\t\tMisc_Focus_Restore_Function();\n\t\t}\n\n\t\tSurfacesRestored = TRUE;\n\n\t\t/*\n\t\t** Restore the palette\n\t\t*/\n\t\tSet_DD_Palette (CurrentPalette);\n\t}\n}\n\n\n/***********************************************************************************************\n * SMC::Set_Surface_Focus -- set the InFocus flag to the given state                           *\n *                                                                                             *\n *  The InFocus flag is used to keep track of whether our application is currently in focus.   *\n *  We dont want to be restoring video surfaces when we are supposed to be running in the      *\n *  background.                                                                                *\n *                                                                                             *\n * INPUT:    bool in focus                                                                     *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/6/95 12:21PM ST : Created                                                             *\n *=============================================================================================*/\n\nvoid SurfaceMonitorClass::Set_Surface_Focus ( BOOL in_focus )\n{\n\tInFocus=in_focus;\n}\n\n\n\n\n/***********************************************************************************************\n * SMC::Release -- releases all direct draw surfaces                                           *\n *                                                                                             *\n *  Call this at the end of the game before called RestoreDisplayMode                          *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/6/96 12:23PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid SurfaceMonitorClass::Release(void)\n{\n\t/*\n\t** Call release for each Direct Draw surface\n\t*/\n\tfor (int i=0 ; i<MAX_SURFACES ; i++)\n\t{\n\t\tif ( Surface[i] ){\n\t\t\tSurface[i]->Release();\n\t\t\tSurface[i] = 0;\n\t\t}\n\t}\n\n}\n\n"
  },
  {
    "path": "WIN32LIB/MISC/DELAY.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : DELAY.C                                  *\n *                                                                         *\n *                   Programmer : Christopher Yates                        *\n *                                                                         *\n *                  Last Update : 27 March, 1991   [CY]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"wwstd.h\"\n#include <timer.h>\n\nvoid Delay(int duration)\n{\n\tunsigned long count;\n\tTimerClass timer(BT_SYSTEM,TRUE);\n\n\twhile (duration--) {\n\t\tcount = timer.Time() + 1L;\n\t\twhile (count >= timer.Time()) {\n\t\t\t;\n\t\t}\n\t}\n\n#if(FALSE)\n\twhile (duration--)\n\t\tWait_Vert_Blank(VertBlank);\n#endif\n}\n\n#if(FALSE)\nvoid Vsync()\n{\n\tWait_Vert_Blank(VertBlank);\n}\n#endif\n\u001a"
  },
  {
    "path": "WIN32LIB/MISC/DETPROC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/system/rcs/detproc.asm 1.1 1994/04/18 09:13:53 jeff_wilson Exp $\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : PROC.ASM                                 *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : May 11, 1993                             *\n;*                                                                         *\n;*                  Last Update : May 11, 1993   [JLB]                     *\n;*                                                                         *\n;*  Converted to 32Bit -- JAW                                              *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL \t      \tC Processor          :NEAR\n\n\nPROC_80386\tequ\t0\nPROC_80486\tequ\t1\nPROC_80586\tequ\t2\n\nDATASEG\ncpu_id_586\tdw\t0\n\nCODESEG\n\nPROC\tProcessor C near\n\tUSES ebx\n\tLOCAL\tptype:WORD\n\n\tpushfd\n\n; At least a 386 -- check for 486.\n\tmov\t[WORD PTR ptype],PROC_80386\t; 80386\n\tpushfd\n\tpop\teax\n\tmov\tebx,eax\n\txor\teax,40000h\n\tpush\teax\n\tpopfd\n\tpushfd\n\tpop\teax\n\txor\teax,ebx\n\tje\tshort ??fini\n\n; At least a 486 -- check for 586(Pentium)\n\tmov\t[ptype],PROC_80486\t; 80486\n\n\t; Some machines have a problem with this fLAG\n\t; and thus make us think they are a 586 but they are\n\t; really a 486. A possible way around this is to\n\t; capture the Illegal instruction vector, then  do\n\t; an instruction only available on the 586.\n\n\t; for now this is just commented out\n\tpushfd\n\tpop\teax\n\tmov\tebx,eax\n\txor\teax,200000h\n\tpush\teax\n\tpopfd\n\tpushfd\n\tpop\teax\n\txor\teax,ebx\n\tje\tshort ??fini\n\n; At least a 586(Pentium) -- check for higher.\n\tmov\t[ptype],PROC_80586\t; 80486\n;\tmov\teax,1\n;\tDW\t0fA2h\t\t; CPUID opcode.\n;\tshr\tax,8\n;\tand\tax,0fh\n;\tinc\tax\n;\tinc\tax\n;\tmov\t[cpu_id_586],ax\n\n; Final cleanup and exit.\n??fini:\n\tpopfd\n\tsub\teax,eax\n\tmov\tax,[ptype]\n\tret\n\nENDP\tProcessor\n\nEND"
  },
  {
    "path": "WIN32LIB/MISC/EXIT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 library source                   *\n *                                                                         *\n *                    File Name : EXIT.CPP                                 *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Exit -- Exit routine with message.                                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"misc.h\"\n\n#include <stdio.h>\n\n#include <stdlib.h>\n#include <stdarg.h>\n#include <time.h>\n\n\n\n\n/***************************************************************************\n * EXIT -- Exit routine with message.                                      *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/03/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid __cdecl Exit(INT errorval, const char *message, ...)\n{\n\tva_list\t\targptr;\n\tchar\t\terrstring[256];\n\n\tProg_End();\n\n\tif (message && *message) {\n\t\tva_start (argptr, message);\n\t\tvsprintf ((char *)errstring, (const char *)message, argptr);\n\t\tva_end (argptr);\n\t\tprintf(errstring);\n\t}\n\n\t::exit(errorval);\n\n}\n\nvoid randomize\t( void )\n{\n  srand ( time ( NULL ) ) ;\n}\n\n#if(0)\nunsigned long\trandom ( unsigned long mod )\n{\n  return rand () * mod / RAND_MAX ;\n}\n#endif\n"
  },
  {
    "path": "WIN32LIB/MISC/FACING16.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/source/rcs/./facing16.asm 1.10 1994/05/20 15:32:36 joe_bostic Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Support Library                          *\n;*                                                                         *\n;*                    File Name : FACING16.ASM                             *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : May 8, 1991                              *\n;*                                                                         *\n;*                  Last Update : February 6, 1995  [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Desired_Facing16 -- Converts coordinates into a facing number.        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\t C Desired_Facing16\t:NEAR\n;\tINCLUDE\t\"wwlib.i\"\n\n\tDATASEG\n\n; 16 direction desired facing lookup table.  Build the index according\n; to the following bits:\n;\n; bit 4 = Is y2 < y1?\n; bit 3 = Is x2 < x1?\n; bit 2 = Is the ABS(x2-x1) < ABS(y2-y1)?\n; bit 1 = Is the lesser absolute difference very close to zero?\n; bit 0 = Is the lesser absolute difference very close to the greater dist?\nNewFacing16\tDB\t 3, 2, 4,-1, 1, 2,0,-1\n\t\tDB\t13,14,12,-1,15,14,0,-1\n\t\tDB\t 5, 6, 4,-1, 7, 6,8,-1\n\t\tDB\t11,10,12,-1, 9,10,8,-1\n\n\tCODESEG\n\n;***************************************************************************\n;* DESIRED_FACING16 -- Converts coordinates into a facing number.          *\n;*                                                                         *\n;*      This converts coordinates into a desired facing number that ranges *\n;*      from 0 to 15 (0 equals North and going clockwise).                 *\n;*                                                                         *\n;* INPUT:       x1,y1   -- Position of origin point.                       *\n;*                                                                         *\n;*              x2,y2   -- Position of target.                             *\n;*                                                                         *\n;* OUTPUT:      Returns desired facing as a number from 0 to 255 but       *\n;*              accurate to 22.5 degree increments.                        *\n;*                                                                         *\n;* WARNINGS:    If the two coordinates are the same, then -1 will be       *\n;*              returned.  It is up to you to handle this case.            *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/14/1991 JLB : Created.                                             *\n;*=========================================================================*\n; long Desired_Facing16(long x1, long y1, long x2, long y2);\n\n\tPROC\tDesired_Facing16 C near\n\tUSES\tebx, ecx, edx\n\n\tARG\tx1:DWORD\n\tARG\ty1:DWORD\n\tARG\tx2:DWORD\n\tARG\ty2:DWORD\n\n\txor\tebx,ebx\t\t\t; Index byte (built).\n\n\t; Determine Y axis difference.\n\tmov\tedx,[y1]\n\tmov\tecx,[y2]\n\tsub\tedx,ecx\t\t\t; DX = Y axis (signed).\n\tjns\tshort ??absy\n\tinc\tebx\t\t\t; Set the signed bit.\n\tneg\tedx\t\t\t; ABS(y)\n??absy:\n\n\t; Determine X axis difference.\n\tshl\tebx,1\n\tmov\teax,[x1]\n\tmov\tecx,[x2]\n\tsub\tecx,eax\t\t\t; CX = X axis (signed).\n\tjns\tshort ??absx\n\tinc\tebx\t\t\t; Set the signed bit.\n\tneg\tecx\t\t\t; ABS(x)\n??absx:\n\n\t; Determine the greater axis.\n\tcmp\tecx,edx\n\tjb\tshort ??dxisbig\n\txchg\tecx,edx\n??dxisbig:\n\trcl\tebx,1\t\t\t; Y > X flag bit.\n\n\t; Determine the closeness or farness of lesser axis.\n\tmov\teax,edx\n\tinc\teax\t\t\t; Round up.\n\tshr\teax,1\n\tinc\teax\t\t\t; Round up.\n\tshr\teax,1\t\t\t; 1/4 of greater axis.\n\n\tcmp\tecx,eax\n\trcl\tebx,1\t\t\t; Very close to major axis bit.\n\n\tsub\tedx,eax\n\tcmp\tedx,ecx\n\trcl\tebx,1\t\t\t; Very far from major axis bit.\n\n\txor\teax,eax\n\tmov\tal,[NewFacing16+ebx]\n\n\t; Normalize to 0..FF range.\n\tshl\teax,4\n\n\tret\n\n\tENDP\tDesired_Facing16\n\n\tEND\n\n\n\u001a"
  },
  {
    "path": "WIN32LIB/MISC/FACING8.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Support Library                          *\n;*                                                                         *\n;*                    File Name : FACING8.ASM                              *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : May 8, 1991                              *\n;*                                                                         *\n;*                  Last Update : February 6, 1995  [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Desired_Facing8 -- Determines facing to reach a position.             *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nGLOBAL\t C Desired_Facing8\t:NEAR\n;\tINCLUDE\t\"wwlib.i\"\n\n\tDATASEG\n\n; 8 direction desired facing lookup table.  Build the index according\n; to the following bits:\n;\n; bit 3 = Is y2 < y1?\n; bit 2 = Is x2 < x1?\n; bit 1 = Is the ABS(x2-x1) < ABS(y2-y1)?\n; bit 0 = Is the facing closer to a major axis?\nNewFacing8\tDB\t1,2,1,0,7,6,7,0,3,2,3,4,5,6,5,4\n\n\tCODESEG\n\n;***************************************************************************\n;* DESIRED_FACING8 -- Determines facing to reach a position.               *\n;*                                                                         *\n;*    This routine will return with the most desirable facing to reach     *\n;*    one position from another.  It is accurate to a resolution of 0 to   *\n;*    7.                                                                   *\n;*                                                                         *\n;* INPUT:       x1,y1   -- Position of origin point.                       *\n;*                                                                         *\n;*              x2,y2   -- Position of target.                             *\n;*                                                                         *\n;* OUTPUT:      Returns desired facing as a number from 0..255 with an     *\n;*              accuracy of 32 degree increments.                          *\n;*                                                                         *\n;* WARNINGS:    If the two coordinates are the same, then -1 will be       *\n;*              returned.  It is up to you to handle this case.            *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1991 JLB : Documented.                                          *\n;*   08/08/1991 JLB : Same position check.                                 *\n;*   08/14/1991 JLB : New algorithm                                        *\n;*   02/06/1995 BWG : Convert to 32-bit                                    *\n;*=========================================================================*\n; long Desired_Facing8(long x1, long y1, long x2, long y2);\n\n\tPROC\tDesired_Facing8 C near\n\tUSES\tebx, ecx, edx\n\n\tARG\tx1:DWORD\n\tARG\ty1:DWORD\n\tARG\tx2:DWORD\n\tARG\ty2:DWORD\n\n\txor\tebx,ebx\t\t\t; Index byte (built).\n\n\t; Determine Y axis difference.\n\tmov\tedx,[y1]\n\tmov\tecx,[y2]\n\tsub\tedx,ecx\t\t\t; DX = Y axis (signed).\n\tjns\tshort ??absy\n\tinc\tebx\t\t\t; Set the signed bit.\n\tneg\tedx\t\t\t; ABS(y)\n??absy:\n\n\t; Determine X axis difference.\n\tshl\tebx,1\n\tmov\teax,[x1]\n\tmov\tecx,[x2]\n\tsub\tecx,eax\t\t\t; CX = X axis (signed).\n\tjns\tshort ??absx\n\tinc\tebx\t\t\t; Set the signed bit.\n\tneg\tecx\t\t\t; ABS(x)\n??absx:\n\n\t; Determine the greater axis.\n\tcmp\tecx,edx\n\tjb\tshort ??dxisbig\n\txchg\tecx,edx\n??dxisbig:\n\trcl\tebx,1\t\t\t; Y > X flag bit.\n\n\t; Determine the closeness or farness of lesser axis.\n\tmov\teax,edx\n\tinc\teax\t\t\t; Round up.\n\tshr\teax,1\n\n\tcmp\tecx,eax\n\trcl\tebx,1\t\t\t; Close to major axis bit.\n\n\txor\teax,eax\n\tmov\tal,[NewFacing8+ebx]\n\n\t; Normalize to 0..FF range.\n\tshl\teax,5\n\n\tret\n\n\tENDP\tDesired_Facing8\n\n\n\tEND\n"
  },
  {
    "path": "WIN32LIB/MISC/FACINGFF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Support Library                          *\n;*                                                                         *\n;*                    File Name : FACINGFF.ASM                             *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : May 8, 1991                              *\n;*                                                                         *\n;*                  Last Update : February 6, 1995  [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Desired_Facing256 -- Determines facing to reach a position.           *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\tC Desired_Facing256\t:NEAR\n;\tINCLUDE\t\"wwlib.i\"\nINCLUDE \"..\\include\\gbuffer.inc\"\n\n\tCODESEG\n\n;***************************************************************************\n;* Desired_Facing256 -- Desired facing algorithm 0..255 resolution.        *\n;*                                                                         *\n;*    This is a desired facing algorithm that has a resolution of 0        *\n;*    through 255.                                                         *\n;*                                                                         *\n;* INPUT:   srcx,srcy   -- Source coordinate.                              *\n;*                                                                         *\n;*          dstx,dsty   -- Destination coordinate.                         *\n;*                                                                         *\n;* OUTPUT:  Returns with the desired facing to face the destination        *\n;*          coordinate from the position of the source coordinate.  North  *\n;*          is 0, East is 64, etc.                                         *\n;*                                                                         *\n;* WARNINGS:   This routine is slower than the other forms of desired      *\n;*             facing calculation.  Use this routine when accuracy is      *\n;*             required.                                                   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   12/24/1991 JLB : Adapted.                                             *\n;*=========================================================================*/\n; LONG cdecl Desired_Facing256(LONG srcx, LONG srcy, LONG dstx, LONG dsty)\n\tPROC\tDesired_Facing256 C near\n\tUSES\tebx, ecx, edx\n\n\tARG\tsrcx:DWORD\n\tARG\tsrcy:DWORD\n\tARG\tdstx:DWORD\n\tARG\tdsty:DWORD\n\n\txor\tebx,ebx\t\t\t; Facing number.\n\n\t; Determine absolute X delta and left/right direction.\n\tmov\tecx,[dstx]\n\tsub\tecx,[srcx]\n\tjge\tshort ??xnotneg\n\tneg\tecx\n\tmov\tebx,11000000b\t\t; Set bit 7 and 6 for leftward.\n??xnotneg:\n\n\t; Determine absolute Y delta and top/bottom direction.\n\tmov\teax,[srcy]\n\tsub\teax,[dsty]\n\tjge\tshort ??ynotneg\n\txor\tebx,01000000b\t\t; Complement bit 6 for downward.\n\tneg\teax\n??ynotneg:\n\n\t; Set DX=64 for quadrants 0 and 2.\n\tmov\tedx,ebx\n\tand\tedx,01000000b\n\txor\tedx,01000000b\n\n\t; Determine if the direction is closer to the Y axis and make sure that\n\t; CX holds the larger of the two deltas.  This is in preparation for the\n\t; divide.\n\tcmp\teax,ecx\n\tjb\tshort ??gotaxis\n\txchg\teax,ecx\n\txor\tedx,01000000b\t\t; Closer to Y axis so make DX=64 for quad 0 and 2.\n??gotaxis:\n\n\t; If closer to the X axis then add 64 for quadrants 0 and 2.  If\n\t; closer to the Y axis then add 64 for quadrants 1 and 3.  Determined\n\t; add value is in DX and save on stack.\n\tpush\tedx\n\n\t; Make sure that the division won't overflow.  Reduce precision until\n\t; the larger number is less than 256 if it appears that an overflow\n\t; will occur.  If the high byte of the divisor is not zero, then this\n\t; guarantees no overflow, so just abort shift operation.\n\ttest\teax,0FFFFFF00h\n\tjnz\tshort ??nooverflow\n??again:\n\ttest\tecx,0FFFFFF00h\n\tjz\tshort ??nooverflow\n\tshr\tecx,1\n\tshr\teax,1\n\tjmp\tshort ??again\n??nooverflow:\n\n\t; Make sure that the division won't underflow (divide by zero).  If\n\t; this would occur, then set the quotient to $FF and skip divide.\n\tor\tecx,ecx\n\tjnz\tshort ??nounderflow\n\tmov\teax,0FFFFFFFFh\n\tjmp\tshort ??divcomplete\n\n\t; Derive a pseudo angle number for the octant.  The angle is based\n\t; on $00 = angle matches long axis, $00 = angle matches $FF degrees.\n??nounderflow:\n\txor\tedx,edx\n\tshld\tedx,eax,8\t; shift high byte of eax into dl\n\tshl\teax,8\n\tdiv\tecx\n??divcomplete:\n\n\t; Integrate the 5 most significant bits into the angle index.  If DX\n\t; is not zero, then it is 64.  This means that the dividend must be negated\n\t; before it is added into the final angle value.\n\tshr\teax,3\n\tpop\tedx\n\tor\tedx,edx\n\tje\tshort ??noneg\n\tdec\tedx\n\tneg\teax\n??noneg:\n\tadd\teax,edx\n\tadd\teax,ebx\n\tand\teax,0FFH\n\tret\n\n\tENDP\tDesired_Facing256\n\n\n\n\tEND"
  },
  {
    "path": "WIN32LIB/MISC/FADING.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : FADING.ASM                               *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : August 20, 1993                          *\n;*                                                                         *\n;*                  Last Update : August 20, 1993   [JLB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\tC Build_Fading_Table\t:NEAR\n\n\tCODESEG\n\n;***********************************************************\n; BUILD_FADING_TABLE\n;\n; void *Build_Fading_Table(void *palette, void *dest, long int color, long int frac);\n;\n; This routine will create the fading effect table used to coerce colors\n; from toward a common value.  This table is used when Fading_Effect is\n; active.\n;\n; Bounds Checking: None\n;*\n\tPROC\tBuild_Fading_Table C near\n\tUSES\tebx, ecx, edi, esi\n\tARG\tpalette:DWORD\n\tARG\tdest:DWORD\n\tARG\tcolor:DWORD\n\tARG\tfrac:DWORD\n\n\tLOCAL\tmatchvalue:DWORD\t; Last recorded match value.\n\tLOCAL\ttargetred:BYTE\t\t; Target gun red.\n\tLOCAL\ttargetgreen:BYTE\t; Target gun green.\n\tLOCAL\ttargetblue:BYTE\t\t; Target gun blue.\n\tLOCAL\tidealred:BYTE\n\tLOCAL\tidealgreen:BYTE\n\tLOCAL\tidealblue:BYTE\n\tLOCAL\tmatchcolor:BYTE\t\t; Tentative match color.\n\n\tcld\n\n\t; If the source palette is NULL, then just return with current fading table pointer.\n\tcmp\t[palette],0\n\tje\t??fini\n\tcmp\t[dest],0\n\tje\t??fini\n\n\t; Fractions above 255 become 255.\n\tmov\teax,[frac]\n\tcmp\teax,0100h\n\tjb\tshort ??ok\n\tmov\t[frac],0FFh\n??ok:\n\n\t; Record the target gun values.\n\tmov\tesi,[palette]\n\tmov\tebx,[color]\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tlodsb\n\tmov\t[targetred],al\n\tlodsb\n\tmov\t[targetgreen],al\n\tlodsb\n\tmov\t[targetblue],al\n\n\t; Main loop.\n\txor\tebx,ebx\t\t\t; Remap table index.\n\n\t; Transparent black never gets remapped.\n\tmov\tedi,[dest]\n\tmov\t[edi],bl\n\tinc\tedi\n\n\t; EBX = source palette logical number (1..255).\n\t; EDI = running pointer into dest remap table.\n??mainloop:\n\tinc\tebx\n\tmov\tesi,[palette]\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\n\tmov\tedx,[frac]\n\tshr\tedx,1\n\t; new = orig - ((orig-target) * fraction);\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetred]\t\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\tax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealred],dh\t\t; preserve ideal color gun value.\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetgreen]\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\tax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealgreen],dh\t\t; preserve ideal color gun value.\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetblue]\t\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\tax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealblue],dh\t\t; preserve ideal color gun value.\n\n\t; Sweep through the entire existing palette to find the closest\n\t; matching color.  Never matches with color 0.\n\n\tmov\teax,[color]\n\tmov\t[matchcolor],al\t\t; Default color (self).\n\tmov\t[matchvalue],-1\t\t; Ridiculous match value init.\n\tmov\tecx,255\n\n\tmov\tesi,[palette]\t\t; Pointer to original palette.\n\tadd\tesi,3\n\n\t; BH = color index.\n\tmov\tbh,1\n??innerloop:\n\n\t; Recursion through the fading table won't work if a color is allowed\n\t; to remap to itself.  Prevent this from occuring.\n\tadd\tesi,3\n\tcmp\tbh,bl\n\tje\tshort ??notclose\n\tsub\tesi,3\n\n\txor\tedx,edx\t\t\t; Comparison value starts null.\n\tmov\teax,edx\n\t; Build the comparison value based on the sum of the differences of the color\n\t; guns squared.\n\tlodsb\n\tsub\tal,[idealred]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\n\tlodsb\n\tsub\tal,[idealgreen]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\n\tlodsb\n\tsub\tal,[idealblue]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\tjz\tshort ??perfect\t\t; If perfect match found then quit early.\n\n\tcmp\tedx,[matchvalue]\n\tja\tshort ??notclose\n\tmov\t[matchvalue],edx\t; Record new possible color.\n\tmov\t[matchcolor],bh\n??notclose:\n\tinc\tbh\t\t\t; Checking color index.\n\tloop\t??innerloop\n\tmov\tbh,[matchcolor]\n??perfect:\n\tmov\t[matchcolor],bh\n\txor\tbh,bh\t\t\t; Make BX valid main index again.\n\n\t; When the loop exits, we have found the closest match.\n\tmov\tal,[matchcolor]\n\tstosb\n\tcmp\tebx,255\n\tjne\t??mainloop\n\n??fini:\n\tmov\teax,[dest]\n\tret\n\n\tENDP\tBuild_Fading_Table\n\n\n\tEND"
  },
  {
    "path": "WIN32LIB/MISC/FINDARGV.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/wwlib32/misc/rcs/findargv.cpp 1.2 1994/04/22 10:29:28 scott_bowen Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : findargv \t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : findargv.C                               *\n *                                                                         *\n *                   Programmer : Jeff Wilson\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Start Date : January 14, 1993                         *\n *                                                                         *\n *                  Last Update : May 20, 1993   [PWG]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Find_Argv -- Checks to see if string is in arguement              \t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"wwstd.h\"\n#include <dos.h>\n#include <stdio.h>\n#include <string.h>\n#include <process.h>\n\n\n\n\n/***************************************************************************\n * Find_Argv -- Checks to see if string is in arguement                \t\t*\n *                                                                         *\n * INPUT: char *str - string to search for.                                *\n *                                                                         *\n * OUTPUT: NULL if not found else pointer to string.                       *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/14/1993  SB : Created.                                             *\n *=========================================================================*/\n\n//static char command [ 256 ] ;\n#pragma on (argsused)\nchar * __cdecl Find_Argv(char const)\n{\n\treturn (NULL);\n\n\n#ifdef NOT_FOR_WIN95\nchar * __cdecl Find_Argv(char const *str)\n{\n\tchar   * ptr ;\n\tstatic   startup_flag = 0 ;\n\n\tif ( ! startup_flag )\n\t{\n\t  startup_flag = 1 ;\n\t  getcmd ( command )\t;\n\t}\n\n\tif ( ! strlen(str) ) return NULL ;\n\treturn strstr ( command , str ) ;\n#endif\n}\n\n\n\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/MISC/IRANDOM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : IRANDOM.C                                *\n *                                                                         *\n *                   Programmer : Barry W. Green                           *\n *                                                                         *\n *                  Last Update : 10 Feb, 1995     [BWG]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <stdlib.h>\n#include <time.h>\n#include \"misc.h\"\n\n\n\n\n\n\n/* IRANDOM ----------------------------------------------------------\n\n   IRandom returns a random value between min and max inclusive.\n\n   INPUTS:\tint min and int max\n\n   RETURNS:\tint random number\n*/\n\nint IRandom(int minval, int maxval)\n{\n\tint num,mask;\n\n\t// Keep minval and maxval straight.\n\tif (minval > maxval) {\n\t\tminval ^= maxval;\n\t\tmaxval ^= minval;\n\t\tminval ^= maxval;\n\t}\n\n\tmask = Get_Random_Mask(maxval - minval);\n\n\twhile( (num = (rand() & mask) + minval) > maxval ) ;\n\treturn(num);\n}\n\u001a\n"
  },
  {
    "path": "WIN32LIB/MISC/LIB.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./lib.c 1.16 1994/05/20 15:34:33 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library Routines                         *\n *                                                                         *\n *                    File Name : LIB.C                                    *\n *                                                                         *\n *                   Programmer : Scott Bowen                              *\n *                                                                         *\n *                   Start Date : January 14, 1993                         *\n *                                                                         *\n *                  Last Update : May 20, 1993   [PWG]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Add_Long_To_Pointer -- Pointer arithmatic when pointer could be XMS.  *\n *   Find_Argv -- Checks to see if string is in arguement              \t\t*\n *   Mono_Mem_Dump -- Dumps memory to mono monitor with hex and char.      *\n *   Convert_HSV_To_RGB -- Converts HSV cordinates to RGB values           *\n *   Convert_RGB_To_HSV -- Converts RGB to RSV coordinates.                *\n *   Set_Search_Drives -- Sets up the CDRom and HardDrive paths.           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include <dos.h>\n#include <stdio.h>\n#include <string.h>\n#include \"misc.h\"\n\n//PRIVATE unsigned Divide_With_Round(unsigned num, unsigned den);\n\n\n/***************************************************************************\n * Divide_With_Round -- Divides integers and round to nearest integer.     *\n *                                                                         *\n * INPUT:         int numberator.                                         *\n *                int denominator.                                        *\n *                                                                         *\n * OUTPUT:        Returns value rounded.                                   *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/13/1992  SB : Created.                                             *\n *=========================================================================*/\nstatic unsigned Divide_With_Round(unsigned num, unsigned den)\n{\n\t// return num/den + (0 ro 1).  1 if the remainder is more than half the denominator.\n\treturn( (num / den) + (unsigned)((num % den) >= ((den + 1) >> 1)) );\n}\n\n#define HSV_BASE 255 // This is used to get a little better persion on HSV conversion.\n#define RGB_BASE 63  // Not 64, this is really the max value.\n\n\n/***************************************************************************\n * Convert_RGB_To_HSV -- Converts RGB to RSV coordinates.                  *\n *                                                                         *\n * INPUT:      int r,g, and b values.                                     *\n *             int *h, *s, and *v pointers.                              \t*\n *                                                                         *\n * OUTPUT:     Assigns values to *h, *s, and *v.                           *\n *                                                                         *\n * WARNINGS:   The reason we use a different base for HSV then RGB is      *\n *             because we loose alot of persision by not using floating    *\n *             point.  Using the same base value (63) made it so that      *\n *             about 50% of the time one RGB value would be one different  *\n *             then the original if you went from RGB to HSV to RGB.       *\n *             Using 255 drop it down to about 9% of the time we get an    *\n *             off value.  To get it perfect, we would have to make the    *\n *             HSV base larger - but then you need to do all calculations  *\n *             in long instead of unsigned int.                                   *\n * HISTORY:                                                                *\n *   02/11/1992  SB : Created.                                             *\n *=========================================================================*/\nvoid Convert_RGB_To_HSV(unsigned int r, unsigned int g, unsigned int b, unsigned int *h, unsigned int *s, unsigned int *v)\n{\n \tunsigned int m, r1, g1, b1, tmp;\n\n\t// Convert RGB base to HSV base.\n\tr = Divide_With_Round((r * HSV_BASE), RGB_BASE);\n\tg = Divide_With_Round((g * HSV_BASE), RGB_BASE);\n\tb = Divide_With_Round((b * HSV_BASE), RGB_BASE);\n\n\t// Set hue to default.\n\t*h = 0;\n\n\t// Set v = Max(r,g,b) to find dominant primary color.\n\t*v = (r > g) ? r : g;\n\tif (b > *v) *v = b;\n\n\t// Set m = min(r,g,b) to find amount of white.\n\tm = (r < g) ? r : g;\n\tif (b < m) m = b;\n\n\t// Determine the normalized saturation.\n\tif (*v != 0) {\n\t\t*s = Divide_With_Round( (*v - m) * HSV_BASE ,*v);\n\t} else {\n\t\t*s = 0;\n\t}\n\n\tif (*s != 0) {\n\t\ttmp = *v - m;\n\t \tr1 = Divide_With_Round( (*v - r) * HSV_BASE, tmp);\n\t \tg1 = Divide_With_Round( (*v - g) * HSV_BASE, tmp);\n\t \tb1 = Divide_With_Round( (*v - b) * HSV_BASE, tmp);\n\n\t\t// Find effect of second most predominant color.\n\t\t// In which section of the hexagon of colors does the color lie?\n\t\tif ((*v) == r) {\n\t\t \tif (m == g) {\n\t\t\t\t*h = 5 * HSV_BASE + b1;\n\t\t\t} else {\n\t\t\t\t*h = 1 * HSV_BASE - g1;\n\t\t\t}\n\t\t} else {\n\t\t\tif ((*v) == g) {\n\t\t\t \tif (m == b) {\n\t\t\t\t\t*h = 1 * HSV_BASE + r1;\n\t\t\t\t} else {\n\t\t\t\t\t*h = 3 * HSV_BASE - b1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// *v == b\n\t\t\t \tif (m == r) {\n\t\t\t\t\t*h = 3 * HSV_BASE + g1;\n\t\t\t\t} else {\n\t\t\t\t\t\n\t\t\t\t\t*h = 5 * HSV_BASE - r1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Divide by six and round.\n\t\t*h = Divide_With_Round(*h, 6);\n\t}\n}\n\n/***************************************************************************\n * Convert_HSV_To_RGB -- Converts HSV cordinates to RGB values             *\n *                                                                         *\n * INPUT:      int h,s, and v coordinates                                 *\n *             int *r, *g, and *b pointers.                              \t*\n *                                                                         *\n * OUTPUT:     Assigns values to *r, *g, and *b.                           *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/11/1992  SB : Created.                                             *\n *=========================================================================*/\nvoid Convert_HSV_To_RGB(unsigned int h, unsigned int s, unsigned int v, unsigned int *r, unsigned int *g, unsigned int *b)\n{\n\tunsigned int i;\t\t\t\t// Integer part.\n\tunsigned int f;\t\t\t\t// Fractional or remainder part.  f/HSV_BASE gives fraction.\n\tunsigned int tmp;\t\t\t// Tempary variable to help with calculations.\n\tunsigned int values[7];\t// Possible rgb values.  Don't use zero.\n\n\n\th *= 6;\n\tf = h % HSV_BASE;\n\n\t// Set up possible red, green and blue values.\n\tvalues[1] =\t\n\tvalues[2] = v;\n\n\t//\n\t// The following lines of code change \n\t//\tvalues[3] = (v * (HSV_BASE - ( (s * f) / HSV_BASE) )) / HSV_BASE;\n\t//\tvalues[4] = values[5] = (v * (HSV_BASE - s)) / HSV_BASE;\n\t// values[6] = (v * (HSV_BASE - (s * (HSV_BASE - f)) / HSV_BASE)) / HSV_BASE;\n\t// so that the are rounded divides.\n\t//\n\n\ttmp = Divide_With_Round(s * f, HSV_BASE);\n\tvalues[3] = Divide_With_Round(v * (HSV_BASE - tmp), HSV_BASE);\n\n\tvalues[4] = \n\tvalues[5] = Divide_With_Round(v * (HSV_BASE - s), HSV_BASE);\n\n\ttmp = HSV_BASE - Divide_With_Round(s * (HSV_BASE - f),  HSV_BASE);\n\tvalues[6] = Divide_With_Round(v * tmp, HSV_BASE);\n\n\n\t// This should not be rounded.\n\ti = h / HSV_BASE;\n\n\ti += (i > 4) ? -4 : 2;\n\t*r = Divide_With_Round(values[i] * RGB_BASE, HSV_BASE);\n\n\ti += (i > 4) ? -4 : 2;\n\t*b = Divide_With_Round(values[i] * RGB_BASE, HSV_BASE);\n\n\ti += (i > 4) ? -4 : 2;\n\t*g = Divide_With_Round(values[i] * RGB_BASE, HSV_BASE);\n} \n"
  },
  {
    "path": "WIN32LIB/MISC/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = misc\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t\t&\n\tcrc.obj\t\t\t&\n\tddraw.obj\t\t&\n\tdelay.obj\t\t&\n\tdetproc.obj  \t&\n\tfacing8.obj    &\n\tfacing16.obj   &\n\tfacingFF.obj   &\n\tfading.obj   \t&\n\tfindargv.obj \t&\n\tirandom.obj \t&\n\tlib.obj\t\t\t&\n\topsys.obj    \t&\n\trandom.obj    \t&\n\treverse.obj\t\t&\n\tshakescr.obj\t&\n\tcliprect.obj\t&\n\texit.obj\t\t\t&\n\tversion.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\tmake\n\tcd ..\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/MISC/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = misc\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t\tcrc.obj\t\t\t\\\n\t\t\t\tddraw.obj\t\t\\\n\t\t\t\tdelay.obj\t\t\\\n\t\t\t\tdetproc.obj  \t\\\n\t\t\t\tfacing8.obj    \\\n\t\t\t\tfacing16.obj   \\\n\t\t\t\tfacingFF.obj   \\\n\t\t\t\tfading.obj   \t\\\n\t\t\t\tfindargv.obj \t\\\n\t\t\t\tirandom.obj \t\\\n\t\t\t\tlib.obj\t\t\t\\\n\t\t\t\topsys.obj    \t\\\n\t\t\t\trandom.obj    \t\\\n\t\t\t\treverse.obj\t\t\\\n\t\t\t\tshakescr.obj\t\\\n\t\t\t\texit.obj     \t\\\n\t\t\t\tcliprect.obj\t\\\n\t\t\t\tversion.obj\n\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) wwlib32.h\n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n +-crc.obj\t\t\t&\n+-ddraw.obj\t\t\t&\n+-delay.obj\t\t\t&\n+-detproc.obj  \t&\n+-exit.obj     \t&\n+-facing8.obj\t\t&\n+-facing16.obj\t\t&\n+-facingFF.obj\t\t&\n+-fading.obj\t\t&\n+-findargv.obj\t\t&\n+-irandom.obj\t\t&\n+-lib.obj\t\t\t&\n+-opsys.obj\t\t\t&\n+-random.obj\t\t&\n+-reverse.obj\t\t&\n+-shakescr.obj\t\t&\n+-cliprect.obj\t\t&\n+-version.obj\n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/MISC/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = misc\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t\t&\n\tcrc.obj\t\t\t&\n\tddraw.obj\t\t&\n\tdelay.obj\t\t&\n\tdetproc.obj  \t&\n\tfacing8.obj    &\n\tfacing16.obj   &\n\tfacingFF.obj   &\n\tfading.obj   \t&\n\tfindargv.obj \t&\n\tirandom.obj \t&\n\tlib.obj\t\t\t&\n\topsys.obj    \t&\n\trandom.obj    \t&\n\treverse.obj\t\t&\n\tshakescr.obj\t&\n\tcliprect.obj\t&\n\texit.obj\t\t\t&\n\tversion.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include \n\t copy *.inc $(%WIN32LIB)\\include \n\t copy *.cpp $(%WIN32LIB)\\srcdebug \n\t copy *.asm $(%WIN32LIB)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\tmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/MISC/MISC.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : 32 bit library                           *\n *                                                                         *\n *                    File Name : MISC.H                                   *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MISC_H\n#define MISC_H\n\n#define WIN32_LEAN_AND_MEAN\t// eliminates unecessary definitions in windows.h\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#include <windows.h>\n#include <windowsx.h>\n#include <ddraw.h>\n\nextern\tLPDIRECTDRAWSURFACE\tPaletteSurface;\n\n/*========================= C++ Routines ==================================*/\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DDRAW.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid \t\tProcess_DD_Result(HRESULT result, int display_ok_msg);\nBOOL \t\tSet_Video_Mode(HWND hwnd, int w, int h, int bits_per_pixel);\nvoid \t\tReset_Video_Mode(void);\nunsigned \tGet_Free_Video_Memory(void);\nvoid \t\tWait_Blit(void);\nunsigned \tGet_Video_Hardware_Capabilities(void);\n\nextern \"C\" void Wait_Vert_Blank(void);\nextern \"C\" void Set_DD_Palette (void *palette);\n\n/*\n** Pointer to function to call if we detect a focus loss\n*/\nextern\tvoid (*Misc_Focus_Loss_Function)(void);\n/*\n** Pointer to function to call if we detect a surface restore\n*/\nextern\tvoid (*Misc_Focus_Restore_Function)(void);\n\n\n/*\n *  Flags returned by Get_Video_Hardware_Capabilities\n */\n/* Hardware blits supported? */\n#define\tVIDEO_BLITTER\t\t\t\t\t1\n\n/* Hardware blits asyncronous? */\n#define\tVIDEO_BLITTER_ASYNC  \t\t2\n\n/* Can palette changes be synced to vertical refresh? */\n#define\tVIDEO_SYNC_PALETTE\t\t\t4\n\n/* Is the video cards memory bank switched? */\n#define\tVIDEO_BANK_SWITCHED\t\t\t8\n\n/* Can the blitter do filled rectangles? */\n#define\tVIDEO_COLOR_FILL\t\t\t\t16\n\n/* Is there no hardware assistance avaailable at all? */\n#define\tVIDEO_NO_HARDWARE_ASSIST\t32\n\n\n\n/*\n * Definition of surface monitor class\n *\n * This class keeps track of all the graphic buffers we generate in video memory so they\n *  can be restored after a focus switch.\n*/\n\n#define\tMAX_SURFACES\t20\n\nclass SurfaceMonitorClass {\n\n\tpublic:\n\n\t\tSurfaceMonitorClass();\n\n\t\tvoid\tAdd_DD_Surface (LPDIRECTDRAWSURFACE);\n\t\tvoid\tRemove_DD_Surface (LPDIRECTDRAWSURFACE);\n\t\tBOOL\tGot_Surface_Already (LPDIRECTDRAWSURFACE);\n\t\tvoid\tRestore_Surfaces (void);\n\t\tvoid\tSet_Surface_Focus ( BOOL in_focus );\n\t\tvoid\tRelease(void);\n\n\t\tBOOL\tSurfacesRestored;\n\n\tprivate:\n\n\t\tLPDIRECTDRAWSURFACE\tSurface[MAX_SURFACES];\n\t\tBOOL\t\t\t\t\t\tInFocus;\n\n};\n\nextern\tSurfaceMonitorClass\tAllSurfaces;\t\t\t\t//List of all direct draw surfaces\n\n\n/*=========================================================================*/\n/* The following variables are declared in: DDRAW.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nextern\tLPDIRECTDRAW\tDirectDrawObject;\nextern\tLPDIRECTDRAW2\tDirectDraw2Interface;\nextern\tHWND\t\t\t\tMainWindow;\nextern BOOL \t\t\t\tSystemToVideoBlits;\nextern BOOL\t\t\t\tVideoToSystemBlits;\nextern BOOL\t\t\t\tSystemToSystemBlits;\nextern BOOL\t\t\t\tOverlappedVideoBlits;\t// Can video driver blit overlapped regions?\n\n/*=========================================================================*/\n/* The following prototypes are for the file: EXIT.CPP\t\t\t\t\t\t\t*/\n/* Prog_End Must be supplied by the user program in startup.cpp\t\t\t\t*/\n/*=========================================================================*/\nVOID __cdecl Prog_End(VOID);\nVOID __cdecl Exit(INT errorval, const BYTE *message, ...);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DELAY.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Delay(int duration);\nvoid Vsync(void);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FINDARGV.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nBYTE  __cdecl Find_Argv(BYTE const *str);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LIB.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nchar *Find_Argv(char const *str);\nvoid Mono_Mem_Dump(void const *databuf, int bytes, int y);\nvoid Convert_RGB_To_HSV(unsigned int r, unsigned int g, unsigned int b, unsigned int *h, unsigned int *s, unsigned int *v);\nvoid Convert_HSV_To_RGB(unsigned int h, unsigned int s, unsigned int v, unsigned int *r, unsigned int *g, unsigned int *b);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: VERSION.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nBYTE  __cdecl Version(VOID);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: IRANDOM.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nint IRandom(int minval, int maxval);\n\n\n/*========================= Assembly Routines ==============================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*=========================================================================*/\n/* The following prototypes are for the file: RANDOM.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nunsigned char __cdecl Random(void);\nint __cdecl Get_Random_Mask(int maxval);\n\n/*=========================================================================*/\n/* The following prototype is for the file: SHAKESCR.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid __cdecl Shake_Screen(int shakes);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: REVERSE.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nlong __cdecl Reverse_Long(long number);\nshort __cdecl Reverse_Short(short number);\nlong __cdecl Swap_Long(long number);\n#if (0)\n/*=========================================================================*/\n/* The following prototype is for the file: FACING8.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Desired_Facing8(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FACING16.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Desired_Facing16(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FACINGFF.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Desired_Facing256(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FADING.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#endif\n\nvoid * __cdecl Build_Fading_Table(void const *palette, void const *dest, long int color, long int frac);\n/*=========================================================================*/\n/* The following prototype is for the file: CRC.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nlong __cdecl Calculate_CRC(void *buffer, long length);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DETPROC.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern WORD __cdecl  Processor(void);\nextern WORD __cdecl Operating_System(void);\nextern unsigned long random ( unsigned long mod )  ;\n//extern void  randomize ( void ) ;\n\nextern int __cdecl Clip_Rect ( int * x , int * y , int * dw , int * dh ,\n\t       \t   \t\t\t int width , int height ) ;\nextern int __cdecl Confine_Rect ( int * x , int * y , int dw , int dh ,\n\t      \t      \t\t\t int width , int height ) ;\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: OPSYS.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern WORD OperationgSystem;\n\n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n\n#endif // MISC_H\n\n"
  },
  {
    "path": "WIN32LIB/MISC/OPSYS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/system/rcs/opsys.asm 1.1 1994/04/18 09:14:12 jeff_wilson Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Operating System Flags                   *\n;*                                                                         *\n;*                    File Name : OPSYS.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott Bowen                              *\n;*                                                                         *\n;*                   Start Date : January 26, 1993                         *\n;*                                                                         *\n;*                  Last Update : January 26, 1993   [SB]                  *\n;*                                                                         *\n;* Updated to 32bit protected mode JAW\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Operating_System -- Determines what the operating system is.          *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL             C Operating_System         :NEAR\nGLOBAL             C OperatingSystem          :WORD\n\nDOS\t\tequ\t1\nWIN31STD\tequ\t2\nWIN31ENH\tequ\t3\nWIN30ENH\tequ\t4\nWIN30STD\tequ\t5\nWIN30REAL\tequ\t6\n\nDATASEG\n\nOperatingSystem\tdw\t0\n\n\nCODESEG\n\n;***************************************************************************\n;* Operating_System -- Determines what the operating system is.            *\n;*                                                                         *\n;* INPUT:   NONE.                                                          *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/26/1993  SB : Created.                                             *\n;*=========================================================================*\nPROC\tOperating_System C near\n\tUSES ebx,ecx,edx,es,edi\n\n\n\t; Check for Windows 3.1\n\tmov\teax,160Ah\t\t; WIN31CHECK\n\tint\t2fh\n\tor\tax,ax\n\tjz\tshort RunningUnderWin31\n\n\t;check for Windows 3.0 enhanced mode\n\tmov \teax,1600h\t\t; WIN386CHECK\n\tint\t2fh\n\tmov\tbl,al\n\tmov\teax,WIN30ENH\n\ttest\tbl,7fh\n\tjnz\tshort Exit\n\n\t;check for 3.0 WINOLDAP\n\tmov\teax,4680h\t\t; IS_WINOLDAP_ACTIVE\n\tint\t2fh\n\tor\teax,eax\n\tjnz\tshort NotRunningUnderWin\n\n\t; rule out MS-DOS 5.0 task switcher\n\tmov\teax,4b02h\t\t; detect switcher\n\tpush\tebx\n\tpush\tes\n\tpush\tedi\n\txor\tebx,ebx\n\tmov\tedi,ebx\n\tmov\tes,bx\n\tint\t2fh\n\tpop\tedi\n\tpop\tes\n\tpop\tebx\n\tor\teax,eax\n\tjz\tshort NotRunningUnderWin\t; MS-DOS 5.0 task switcher found.\n\n\t; check for standrd mode Windows 3.0\n\tmov\teax,1605h\t\t;PMODE_START\n\tint\t2fh\n\tmov\teax,WIN30STD\n\tcmp\tecx,-1\n\tjz\tshort Exit\n\n\t;check for real mode Windows 3.0\n\tmov\teax,1606h\t\t; PMODE_STOP\n\tint\t2fh\n\tmov\teax,WIN30REAL\n\tjmp\tSHORT Exit\n\nRunningUnderWin31:\n\t; At this point: CX == 3 means Windows 3.1 enhanced mode.\n\t;                CX == 2 means Windows 3.1 standard mode.\n\tmov\teax,WIN31STD\n\tcmp\tecx,2\n\tje\tshort Exit\n\n\tmov\teax,WIN31ENH\n\tjmp\tSHORT Exit\n\nNotRunningUnderWin:\n\tmov\teax,DOS\n\nExit:\n\tmov [WORD PTR OperatingSystem], ax\n\tret\n\nENDP\tOperating_System\n\n\n\n;----------------------------------------------------------------------------\n\nEND"
  },
  {
    "path": "WIN32LIB/MISC/RANDOM.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library routine                          *\n;*                                                                         *\n;*                    File Name : RANDOM.ASM                               *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : 20 August, 1990   [CY]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n;*  UBYTE Random(VOID);                                                    *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGlobal C Random\t\t:NEAR\nGlobal C Get_Random_Mask\t:NEAR\nGlobal C RandNumb\t\t:DWORD\n\n\tDATASEG\n\nRandNumb\tDD\t12349876H\n\n\tCODESEG\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; UBYTE Random(VOID);\n; int Get_Random_Mask(int maxval);\n;\n; ----------------------------------------------------------------\n\n;-----------------------------------------------------------------\n; RANDOM\n;\n; UBYTE Random(VOID);\n;\n;*\n\n\tPROC\tRandom C near\n\tUSES\tesi\n\n\tlea\tesi, [RandNumb]\t\t; get offset in segment of RandNumb\n\txor\teax,eax\n\tmov\tal,[esi]\n\tshr\tal,1\t\t\t; shift right 1 bit (bit0 in carry)\n\tshr\tal,1\n\trcl\t[BYTE PTR esi+2],1\t; rcl byte 3 of RandNumb\n\trcl\t[BYTE PTR esi+1],1 \t; rcl byte 2 of RandNumb\n\tcmc\t\t\t\t; complement carry\n\tsbb\tal,[esi]\t\t; sbb byte 1 of RandNumb\n\tshr\tal,1\t\t\t; sets carry\n\trcr\t[BYTE PTR esi],1 \t; rcr byte 1 of RandNumb\n\tmov\tal,[esi]\t\t; reload byte 1 of RandNumb\n\txor\tal,[esi+1]\t\t; xor with byte 2 of RandNumb\n\n\tret\n\n\tENDP\tRandom\n\n\n;-----------------------------------------------------------------\n; GET_RANDOM_MASK - returns an AND value that is large enough that it\n; encloses the 'maxval' parameter.\n;\n; int Get_Random_Mask(int maxval);\n;\n;*\n\n\tPROC\tGet_Random_Mask C near\n\tUSES\tecx\n\tARG\tmaxval:DWORD\n\n; This function takes as a parameter a maximum value, for example, 61.  It\n; then tries to create an AND mask that is big enough to enclose that number.\n; For our example case, that AND mask would be 0x3F.  It does this by scanning\n; for the highest bit in the number, then making an all-1's mask from that\n; bit position down to bit 0.\n\tbsr\tecx,[maxval]\t\t; put bit position of highest bit in ecx\n\tmov\teax,1\t\t\t; set one bit on in eax\n\tjz\t??invalid\t\t; if BSR shows maxval==0, return eax=1\n\tinc\tecx\t\t\t; get one bit higher than count showed\n\tshl\teax,cl\t\t\t; move our EAX bit into position\n\tdec\teax\t\t\t; dec it to create the mask.\n??invalid:\n\tret\n\tENDP\tGet_Random_Mask\n;----------------------------------------------------------------------------\n\n\tEND\n"
  },
  {
    "path": "WIN32LIB/MISC/REVERSE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/misc/rcs/reverse.asm 1.3 1994/04/25 12:22:45 scott_bowen Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : REVERSE.ASM                              *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : April 20, 1994   [SKB]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n; LONG Reverse_Long(LONG number);                                          *\n; WORD Reverse_Short(WORD number);\t\t\t\t\t   *\n; LONG Swap_LONG(LONG number);\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\t C Reverse_Short\t:NEAR\nGLOBAL\t C Swap_Long\t:NEAR\nGLOBAL\t C Reverse_Long\t:NEAR\n\nCODESEG\n\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; LONG Reverse_LONG(LONG number);\n; WORD Reverse_Short(WORD number);\n; LONG Swap_LONG(LONG number);\n;\n; ----------------------------------------------------------------\n\n;-----------------------------------------------------------------\n;\n; REVERSE_LONG\n;\n; LONG Reverse_LONG(LONG number);\n;\n;*\n\tPROC\tReverse_Long C near\n\tARG\tnumber:DWORD\n\nIF 1\n\tmov\teax,[DWORD PTR number]\n\txchg\tal,ah\n\tror\teax,16\n\txchg\tal,ah\nELSE\n\n\t; This is old 16 bit code.\n\tmov\tax,[WORD PTR number]\n\tmov\tdx,[WORD PTR number+2]\n\txchg\tah,dl\n\txchg\tal,dh\nENDIF\n\n\tret\n\n\tENDP\tReverse_Long\n\n;-----------------------------------------------------------------\n\n;-----------------------------------------------------------------\n;\n; REVERSE_WORD\n;\n; WORD Reverse_Short(WORD number);\n;\n;*\n\tPROC\tReverse_Short C near\n\tARG\tnumber:WORD\n\n\tmov\tax,[number]\n\txchg\tah,al\n\tret\n\n\tENDP\tReverse_Short\n\n;-----------------------------------------------------------------\n\n\n;-----------------------------------------------------------------\n;\n; SWAP_Long\n;\n; Long Swap_Long(Long number);\n;\n;*\n\tPROC\tSwap_Long C near\n\tARG\tnumber:DWORD\n\nIF 1\n\t; 32 bit code.\n    \tmov\teax,[DWORD PTR number]\n\tror\teax,16\nELSE\n\t; 16 bit code.\n\tmov\tax,[WORD PTR number+2]\n\tmov\tdx,[WORD PTR number]\nENDIF\n\n\tret\n\n\n\tENDP\tSwap_Long\n\n;-----------------------------------------------------------------\n\n\tEND\n\u001a\n"
  },
  {
    "path": "WIN32LIB/MISC/SHAKESCR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : SHAKESCR.ASM                             *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : August 19, 1993                          *\n;*                                                                         *\n;*                  Last Update : February 10, 1995 [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\tC Shake_Screen\t:NEAR\n\n\tCODESEG\n\n;***********************************************************\n; SHAKE_SCREEN\n;\n; VOID Shake_Screen(int shakes);\n;\n; This routine shakes the screen the number of times indicated.\n;\n; Bounds Checking: None\n;\n;*\n\tPROC\tShake_Screen C near\n\tUSES\tecx, edx\n\n\tARG\tshakes:DWORD\n ret\n\n\tmov\tecx,[shakes]\n\n;;; push es\n;;; mov ax,40h\n;;; mov es,ax\n;;; mov dx,[es:63h]\n;;; pop es\n\tmov\teax,[0463h]\t\t; get CRTC I/O port\n\tmov\tdx,ax\n\tadd\tdl,6\t\t\t; video status port\n\n??top_loop:\n\n??start_retrace:\n\tin\tal,dx\n\ttest\tal,8\n\tjz\t??start_retrace\n\n??end_retrace:\n\tin\tal,dx\n\ttest\tal,8\n\tjnz\t??end_retrace\n\n\tcli\n\tsub\tdl,6\t\t\t; dx = 3B4H or 3D4H\n\n\tmov\tah,01\t\t\t; top word of start address\n\tmov\tal,0Ch\n\tout\tdx,al\n\txchg\tah,al\n\tinc\tdx\n\tout\tdx,al\n\txchg\tah,al\n\tdec\tdx\n\n\tmov\tah,040h\t\t\t; bottom word = 40 (140h)\n\tinc\tal\n\tout\tdx,al\n\txchg\tah,al\n\tinc\tdx\n\tout\tdx,al\n\txchg\tah,al\n\n\tsti\n\tadd\tdl,5\n\n??start_retrace2:\n\tin\tal,dx\n\ttest\tal,8\n\tjz\t??start_retrace2\n\n??end_retrace2:\n\tin\tal,dx\n\ttest\tal,8\n\tjnz\t??end_retrace2\n\n??start_retrace3:\n\tin\tal,dx\n\ttest\tal,8\n\tjz\t??start_retrace3\n\n??end_retrace3:\n\tin\tal,dx\n\ttest\tal,8\n\tjnz\t??end_retrace3\n\n\tcli\n\tsub\tdl,6\t\t\t; dx = 3B4H or 3D4H\n\n\tmov\tah,0\n\tmov\tal,0Ch\n\tout\tdx,al\n\txchg\tah,al\n\tinc\tdx\n\tout\tdx,al\n\txchg\tah,al\n\tdec\tdx\n\n\tmov\tah,0\n\tinc\tal\n\tout\tdx,al\n\txchg\tah,al\n\tinc\tdx\n\tout\tdx,al\n\txchg\tah,al\n\n\tsti\n\tadd\tdl,5\n\n\tloop\t??top_loop\n\n\tret\n\n\tENDP\tShake_Screen\n\n;***********************************************************\n\n\tEND\n"
  },
  {
    "path": "WIN32LIB/MISC/VERSION.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : VERSION.C                                *\n *                                                                         *\n *                   Programmer : Christopher Yates                        *\n *                                                                         *\n *                  Last Update : July 26, 1991   [JLB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Version -- Returns with current library version text.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwstd.h\"\n\n\n\nPRIVATE char *version = \"Westwood Studios - 32 Bit Library Version \"\n\t__DATE__\n\t\"\\r\\n\";\n\n/***************************************************************************\n * VERSION -- Returns with current library version text.                   *\n *                                                                         *\n *    Use this routine to determine the current library version.  The      *\n *    version text contains the date that it was created.                  *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  Returns pointer to version text.                               *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/26/1991 JLB : Created.                                             *\n *=========================================================================*/\nchar * __cdecl Version(void)\n{\n\treturn(version);\n}\n"
  },
  {
    "path": "WIN32LIB/MISC/WWLIB32.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 User include file                *\n *                                                                         *\n *                    File Name : WWLIB32.H                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWLIB32_H\n#define WWLIB32_H\n\n#include <gbuffer.h>\n#include <wwstd.h>\n#include <drawbuff.h>\n#include <buffer.h>\n#include <font.h>\n#include <iff.h>\n#include <misc.h>\n#include <mono.h>\n#include <tile.h>\n#include <wwmem.h>\n#include <keyboard.h>\n#include <mouse.h>\n#include <file.h>\n#include <rawfile.h>\n\n#include <audio.h>\n#include <dipthong.h>\n#include <palette.h>\n#include <playcd.h>\n#include <shape.h>\n#include <timer.h>\n#include <ww_win.h>\n#include <wsa.h>\n#include <profile.h>\n\n\n\n#endif // WWLIB32_H\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/MISC/WWSTD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : wwstd.h                                  *\n *                                                                         *\n *                    File Name : WWLIB.H                                  *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : March 1, 1994                            *\n *                                                                         *\n *                  Last Update : March 1, 1994   []                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#define\tWWSTD_H\n\n\n//\n// Win 95 includes\n//\n\n#ifndef WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#define WIN32 1\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <windowsx.h>\n#endif\n\n\n// Note: SKB 4/11/94\n// Before this library is done, this needs to be able to be set to TRUE.\n// Once it is, the FALSE parts should be removed from the source code.\n#define LIB_EXTERNS_RESOLVED FALSE\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <dos.h>\n#include <bios.h>\n\n//================================\n\n// TRUE and FALSE are defined in pltypes.h\n\n#ifndef IBM\n#define IBM\t\t\t\tTRUE\n#endif\n\n#ifndef AMIGA\n#define AMIGA\t\t\tFALSE\n#endif\n\n#ifndef\tSEGA\n#define\tSEGA\t\t\tFALSE\n#endif\n\n/*\n**\tCommon constants used in normal code.\n*/\n#define WW_ERROR\t\t-1\n\n#ifdef NULL\n#undef\tNULL\n#endif\n\n#ifndef NULL\n#define NULL\t\t0L\n#endif\n\n#ifdef VOID\n#undef VOID\n#endif\n\n#define PRIVATE\t\tstatic\n#define PUBLIC\t\t\t/* Routines & data don't have a specifier */\n\n#ifdef __cplusplus\n#define\t__CPPARGS\t...\n#else\n#define\t__CPPARGS\n#endif\n\n// This macro will get the size (in elements) of the specified array.\n#ifdef GET_SIZE\n#undef GET_SIZE\n#endif\n#define GET_SIZE(a)\t\t\t\t\t((sizeof(a) / sizeof(*a)))\n\n#pragma option -Jg\n// Returns the absolute value of the number.\n#ifdef ABS\n#undef ABS\n#endif\ntemplate<class T> T ABS(T a)\n{\n\treturn (a < 0) ? -a : a;\n}\nint ABS(int);\nlong ABS(long);\n\n// Returns the minimum of the two numbers.\n#ifdef MIN\n#undef MIN\n#endif\ntemplate<class T> T MIN(T a, T b)\n{\n\treturn (b < a) ? b : a;\n};\nshort MIN(short, short);\nint MIN(int, int);\nlong MIN(long, long);\n\n// Returns the maximum of the two numbers.\n#ifdef MAX\n#undef MAX\n#endif\ntemplate<class T> T MAX(T a, T b)\n{\n\treturn (b > a) ? b : a;\n};\nshort MAX(short, short);\nint MAX(int, int);\nlong MAX(long, long);\n#pragma option -Jgd\n\n// Returns the low word of a long\n#define\tLOW_WORD(a)\t\t((unsigned short)((long)(a) & 0x0000FFFFL))\n\n// Returns the high word of a long\n#define\tHIGH_WORD(a)\t((unsigned long)(a) >> 16)\n\n// Merges to shorts to become a long\n#define\tMAKE_LONG(a,b) (((long)(a) << 16) | (long)((b)&0x0000FFFFL))\n\n/*\n** Macro allows our routines to act like\n** sprintf etc..\n*/\n#ifdef AssembleTo\n#undef AssembleTo\n#endif\n\n#define AssembleTo(dest,fmt)\\\n{\\\n\tva_list argptr;\\\n\tif (fmt != (dest))\\\n\t\t{\\\n\t\tva_start (argptr, fmt);\\\n\t\tvsprintf ((dest), fmt, argptr);\\\n\t\tva_end (argptr);\\\n\t\t}\\\n}\n\n// type definitions\n//=======================================\ntypedef void \tVOID;\n\n//==================================================\n// Pharlape defines these for use so we use their\n// typedefs!\n//\t\ttypedef\tunsigned char\tBOOL;\n//\t\ttypedef signed long\t\tLONG;\n//\t\ttypedef unsigned long\tULONG;\n//==================================================\n#ifndef PRIVATE\n#define  PRIVATE\tstatic\n#endif\n\n// The purpose of the INT and UINT is for efficiency.  It says that while a short int (16 bit)\n// has enough precision, it is more efficient to pass in an int (32 bits).  For efficiency, most\n// WORD and UWORD should be an INT or UINT, especially on the stack and structures that will\n// not be in large arrays.  When size efficiency is more important then speed, use WORD UWORD.\n\n#define\tVOID\t\tvoid\n\n#pragma\twarn -eas\n#define\tTRUE\t\t1\n#define\tFALSE\t\t0\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ comittee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n//#define\ttrue\t\t1\n//#define\tfalse\t\t0\n\n#define\tBOOL\t\tint\t\t\t\t\t// 32 bits for speed. use CHAR for size optimizations.\n#if(0)\n#ifndef HMI_DRIVER\n#define\tINT\t\tint\n#define\tUINT\t\tunsigned int\n#define\tBYTE\t\tchar\n#define\tUBYTE\t\tunsigned char\n#define  UCHAR\t   unsigned char\n#define\tWORD\t\tsigned \tshort\n#define\tUWORD\t\tunsigned short\n#define  USHORT\tunsigned short\n\n#define\tLONG\t\tsigned \tlong\n#define\tULONG\t\tunsigned long\n#define  REALPTR\tunsigned long\n\n#define\tFARPTR  char far *\n\n#endif\n#endif\n\n/*\n**\tThe type of processor running on this system as\n**\treturned by Processor().\n*/\n#define\tPROC_80386\t\t0\n#define\tPROC_80486\t\t1\n#define\tPROC_PENTIUM\t2\n\n\n// Inline Routines\n//\n//\n// These Template functions are generally used\n// by classes when they havce over loaded > and <.\n//\n#ifdef __cplusplus\ntemplate<class T> T Min(T a, T b)\n{\n\treturn (a<b ? a : b);\n}\n\ntemplate<class T> inline  T Max(T a, T b)\n{\n\treturn (a>b ? a : b);\n}\n\ntemplate<class T> T Abs(T a)\n{\n\treturn ((a<0) ? -(a) : a);\n}\n\ntemplate<class T> VOID minimize(T &a, T b)\n{\n\tif( b<a )\n\t\ta=b;\n}\n\ntemplate<class T> VOID maximize(T &a, T b)\n{\n\tif( b>a )\n\t\ta=b;\n}\n#endif\n\n/*\n**\tMacros that control bit settings in a variable.\n*/\n#define Bit_Flags_On(a,b)\t\t\ta |= (b)\n#define Bit_Flags_Off(a,b)\t\t\ta &= (~(b))\n#define Bit_Flags_Value(a,b)\t\t(a & (b))\n#define Bit_Flags_Flip(a,b)\t\ta ^= (b)\n\n// Template replacements for the user defines above\n#ifdef __cplusplus\ntemplate<class T> VOID BitFlagsOn(T &a, T b)\n{\n\ta |= (b);\n}\n\ntemplate<class T> VOID BitFlagsOff(T &a, T b)\n{\n\ta &= (~(b));\n}\n\ntemplate<class T> T BitFlagsValue(T a, T b)\n{\n\treturn (a & (b));\n}\n\ntemplate<class T> VOID BitFlagsFlip(T &a, T b)\n{\n\ta ^= (b);\n}\n#endif\n\ntypedef enum {\n\tTBLACK,\n\tPURPLE,\n\tCYAN,\n\tGREEN,\n\tLTGREEN,\n\tYELLOW,\n\tPINK,\n\tBROWN,\n\tRED,\n\tLTCYAN,\n\tLTBLUE,\n\tBLUE,\n\tBLACK,\n\tGREY,\n\tLTGREY,\n\tWHITE,\n\tCOLOR_PADDING=0x1000\n} ColorType;\n\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/MONO/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = mono\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tmono.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\t$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/MONO/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = mono\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t   mono.obj\t\t\t\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) \n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n -+mono.obj\t\t\t\n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/MONO/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = mono\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tmono.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include \n\t copy *.inc $(%WIN32LIB)\\include \n\t copy *.cpp $(%WIN32LIB)\\srcdebug \n\t copy *.asm $(%WIN32LIB)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/MONO/MONO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\monoc.cpv   2.12   06 Sep 1995 16:37:54   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***             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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MONO.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 2, 1994                                                 *\n *                                                                                             *\n *                  Last Update : October 17, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   MonoClass::Clear -- Clears the monochrome screen object.                                  *\n *   MonoClass::Draw_Box -- Draws a box using the IBM linedraw characters.                     *\n *   MonoClass::MonoClass -- The default constructor for monochrome screen object.             *\n *   MonoClass::operator = -- Handles making one mono object have the same imagery as another. *\n *   MonoClass::Print -- Prints the text string at the current cursor coordinates.             *\n *   MonoClass::Printf -- Prints a formatted string to the monochrome screen.                  *\n *   MonoClass::Scroll -- Scroll the monochrome screen up by the specified lines.              *\n *   MonoClass::Set_Cursor -- Sets the monochrome cursor to the coordinates specified.         *\n *   MonoClass::Text_Print -- Prints text to the monochrome object at coordinates indicated.   *\n *   MonoClass::View -- Brings the mono object to the main display.                            *\n *   MonoClass::~MonoClass -- The default destructor for a monochrome screen object.           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n//#pragma inline\n#include\t\"mono.h\"\n\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<dos.h>\n#include\t<mem.h>\n#include\t<stdarg.h>\n#include\t<string.h>\n\n\nextern void output(short port, short data);\n#pragma aux output parm [dx] [ax] =\t\t\\\n\t\t\"out\tdx,al\"\t\t\\\n\t\t\"inc\tdx\"\t\t\t\\\n\t\t\"mov\tal,ah\"\t\t\\\n\t\t\"out\tdx,al\"\n\nint MonoClass::Enabled = 0;\nMonoClass * MonoClass::PageUsage[MonoClass::MAX_MONO_PAGES] = {0,0,0,0,0,0,0,0};\nvoid * MonoClass::MonoSegment = (void*)0x000b0000;\n\n/*\n**\tThese are the IBM linedraw characters.\n*/\nMonoClass::BoxDataType const MonoClass::CharData[MonoClass::COUNT] = {\n\t{0xDA,0xC4,0xBF,0xB3,0xD9,0xC4,0xC0,0xB3},\t// Single line\n\t{0xD5,0xCD,0xB8,0xB3,0xBE,0xCD,0xD4,0xB3},\t// Double horz.\n\t{0xD6,0xC4,0xB7,0xBA,0xBD,0xC4,0xD3,0xBA},\t// Double vert.\n\t{0xC9,0xCD,0xBB,0xBA,0xBC,0xCD,0xC8,0xBA}\t\t// Double horz and vert.\n};\n\n\n/***********************************************************************************************\n * MonoClass::MonoClass -- The default constructor for monochrome screen object.               *\n *                                                                                             *\n *    This is the constructor for monochrome screen objects. It handles allocating a free      *\n *    monochrome page. If there are no more pages available, then this is a big error. The     *\n *    page allocated may not be the visible one. Call the View function in order to bring      *\n *    it to the displayed page.                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nMonoClass::MonoClass(void)\n{\n\tint\tindex;\n\n\tAttrib = DEFAULT_ATTRIBUTE;\t\t// Normal text color.\n\tX = Y = 0;\n\tfor (index = 0; index < MAX_MONO_PAGES; index++) {\n\t\tif (!PageUsage[index]) {\n\t\t\tPageUsage[index] = this;\n\t\t\tPage = (char)index;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (index == MAX_MONO_PAGES) {\n\t\t// Major error message should pop up here!\n\t\tdelete this;\n\t}\n}\n\n\n/***********************************************************************************************\n * MonoClass::~MonoClass -- The default destructor for a monochrome screen object.             *\n *                                                                                             *\n *    This is the default destructor for a monochrome screen object.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nMonoClass::~MonoClass(void)\n{\n\tPageUsage[Page] = 0;\n}\n\n\n/***********************************************************************************************\n * MonoClass::Draw_Box -- Draws a box using the IBM linedraw characters.                       *\n *                                                                                             *\n *    Use this routine to draw a box to the monochrome screen. The IBM line draw characters    *\n *    are used to give the it a fancy appearance. There are several line draw modes supported. *\n *                                                                                             *\n * INPUT:   x,y      -- The coordinates of the upper left corner of the box.                   *\n *                                                                                             *\n *          w,y      -- The width and height (respectively) to make the box.                   *\n *                                                                                             *\n *          attrib   -- The text attribute to use when drawing the box outline characters.     *\n *                                                                                             *\n *          thick    -- The thickness style to use. Examine the BoxStyleType enum for          *\n *                      elaboration on the supported styles.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The interior of the box is NOT cleared by this routine. It is advised that this *\n *             area be cleared before the box is drawn.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Draw_Box(int x, int y, int w, int h, char attrib, BoxStyleType thick)\n{\n\tCellType\tcell;\n\tchar\toldattrib = Attrib;\n\n\tif (!Enabled || !w || !h) return;\n\n\tcell.Attribute = attrib;\n\n\t/*\n\t**\tDraw the horizontal lines.\n\t*/\n\tfor (int xpos = 0; xpos < w-2; xpos++) {\n\t\tcell.Character = CharData[thick].TopEdge;\n\t\tStore_Cell(cell, x+xpos+1, y);\n\t\tcell.Character = CharData[thick].BottomEdge;\n\t\tStore_Cell(cell, x+xpos+1, y+h-1);\n\t}\n\n\t/*\n\t**\tDraw the vertical lines.\n\t*/\n\tfor (int ypos = 0; ypos < h-2; ypos++) {\n\t\tcell.Character = CharData[thick].LeftEdge;\n\t\tStore_Cell(cell, x, y+ypos+1);\n\t\tcell.Character = CharData[thick].RightEdge;\n\t\tStore_Cell(cell, x+w-1, y+ypos+1);\n\t}\n\n\t/*\n\t**\tDraw the four corners.\n\t*/\n\tif (w > 1 && h > 1) {\n\t\tcell.Character = CharData[thick].UpperLeft;\n\t\tStore_Cell(cell, x, y);\n\t\tcell.Character = CharData[thick].UpperRight;\n\t\tStore_Cell(cell, x+w-1, y);\n\t\tcell.Character = CharData[thick].BottomRight;\n\t\tStore_Cell(cell, x+w-1, y+h-1);\n\t\tcell.Character = CharData[thick].BottomLeft;\n\t\tStore_Cell(cell, x, y+h-1);\n\t}\n\n\tAttrib = oldattrib;\n}\n\n\n/***********************************************************************************************\n * MonoClass::Set_Cursor -- Sets the monochrome cursor to the coordinates specified.           *\n *                                                                                             *\n *    Use this routine to set the monochrome's cursor position to the coordinates specified.   *\n *    This is the normal way of controlling where the next Print or Printf will output the     *\n *    text to.                                                                                 *\n *                                                                                             *\n * INPUT:   x,y   -- The coordinate to position the monochrome cursor. 0,0 is the upper left   *\n *                   corner.                                                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Set_Cursor(int x, int y)\n{\n#if(0)\n\tint\tpos = (y*COLUMNS)+x;\n\n\tif (!Enabled) return;\n\n\tX = (char)(x%COLUMNS);\n\tY = (char)(y%LINES);\n\n\tif (Page == 0) {\n\t\t_DX = CONTROL_PORT;\n\t\t_AX = (short)(0x0E|(pos&0xFF00));\n\t\tasm {\n\t\t\tout\tdx,al\n\t\t\tinc\tdx\n\t\t\tmov\tal,ah\n\t\t\tout\tdx,al\n\t\t}\n\n\t\t_DX = CONTROL_PORT;\n\t\t_AX = (short)(0x0F|(pos<<8));\n\t\tasm {\n\t\t\tout\tdx,al\n\t\t\tinc\tdx\n\t\t\tmov\tal,ah\n\t\t\tout\tdx,al\n\t\t}\n\n\t}\n#else\n\tint\tpos = (y*COLUMNS)+x;\n\n\tif (!Enabled) return;\n\n\tX = (char)(x%COLUMNS);\n\tY = (char)(y%LINES);\n\n\tif (Page == 0) {\n\t\toutput(CONTROL_PORT,\n\t\t\t(short)0x0E|(short)(pos&0xFF00));\n\t\toutput(CONTROL_PORT,\n\t\t\t(short)0x0F|(short)(pos<<8));\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * MonoClass::Clear -- Clears the monochrome screen object.                                    *\n *                                                                                             *\n *    This routine will fill the monochrome screen object with spaces. It is clearing the      *\n *    screen of data, making it free for output. The cursor is positioned at the upper left    *\n *    corner of the screen by this routine.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Clear(void)\n{\n\tCellType\tcell;\n\n\tif (!Enabled) return;\n\n\tSet_Cursor(0, 0);\n\n\tcell.Attribute = Attrib;\n\tcell.Character = ' ';\n\n\tfor (int y = 0; y < LINES; y++) {\n\t\tfor (int x = 0; x < COLUMNS; x++) {\n\t\t\tStore_Cell(cell, x, y);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MonoClass::Scroll -- Scroll the monochrome screen up by the specified lines.                *\n *                                                                                             *\n *    Use this routine to scroll the monochrome screen up by the number of lines specified.    *\n *    This routine is typically called by the printing functions so that the monochrome screen *\n *    behaves in the expected manner -- printing at the bottom of the screen scrolls it up     *\n *    to make room for new text.                                                               *\n *                                                                                             *\n * INPUT:   lines -- The number of lines to scroll the monochrome screen.                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Scroll(int lines)\n{\n\tCellType\tcell;\n\n\tif (!Enabled || lines <= 0) return;\n\n\tmemmove( (void*)((long)MonoSegment + Offset(0, 0)),\n\t\t\t\t(void*)((long)MonoSegment + Offset(0, lines)),\n\t\t\t\t(LINES-lines)*COLUMNS*sizeof(CellType));\n\n\n\tY--;\n\tcell.Attribute = Attrib;\n\tcell.Character = ' ';\n\n\tfor (int l = LINES-lines; l < LINES; l++) {\n\t\tfor (int index = 0; index < COLUMNS; index++) {\n\t\t\tStore_Cell(cell, index, l);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MonoClass::Printf -- Prints a formatted string to the monochrome screen.                    *\n *                                                                                             *\n *    Use this routine to output a formatted string, using the standard formatting options,    *\n *    to the monochrome screen object's current cursor position.                               *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text to print.                                             *\n *                                                                                             *\n *          ...   -- Any optional parameters to supply in formatting the text.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The total formatted text length must not exceed 255 characters.                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Printf(char const *text, ...)\n{\n\tva_list\tva;\n\t/*\n\t**\tThe buffer object is placed at the end of the local variable list\n\t**\tso that if the sprintf happens to spill past the end, it isn't likely\n\t**\tto trash anything (important). The buffer is then manually truncated\n\t**\tto maximum allowed size before being printed.\n\t*/\n\tchar buffer[256];\n\n\tif (!Enabled) return;\n\n\tva_start(va, text);\n\tvsprintf(buffer, text, va);\n\tbuffer[sizeof(buffer)-1] = '\\0';\n\n\tPrint(buffer);\n\tva_end(va);\n}\n\n\n#ifdef NEVER\nvoid MonoClass::Printf(int text, ...)\n{\n\tva_list\tva;\n\t/*\n\t**\tThe buffer object is placed at the end of the local variable list\n\t**\tso that if the sprintf happens to spill past the end, it isn't likely\n\t**\tto trash anything (important). The buffer is then manually truncated\n\t**\tto maximum allowed size before being printed.\n\t*/\n\tchar buffer[256];\n\n\tif (!Enabled) return;\n\n\tva_start(va, text);\n\tvsprintf(buffer, Text_String(text), va);\n\tbuffer[sizeof(buffer)-1] = '\\0';\n\n\tPrint(buffer);\n\tva_end(va);\n}\n#endif\n\n\n/***********************************************************************************************\n * MonoClass::Print -- Prints the text string at the current cursor coordinates.               *\n *                                                                                             *\n *    Use this routine to output the specified text string at the monochrome object's current  *\n *    text coordinate position.                                                                *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the string to print.                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Print(char const *ptr)\n{\n\tchar startcol = X;\n\tchar const * text;\n\tCellType\tcell;\n\n\tif (!ptr || !Enabled) return;\n\n\ttext = ptr;\n\tcell.Attribute = Attrib;\n\twhile (*text) {\n\n\t\t/*\n\t\t**\tSometimes the character string is used for cursor control instead\n\t\t**\tof plain text output. Check for this case.\n\t\t*/\n\t\tswitch (*text) {\n\n\t\t\t/*\n\t\t\t**\tThe \"return\" code behaves as it did in the old C library\n\t\t\t**\tmono system. That is, it returns the cursor position to\n\t\t\t**\tthe next line but at the starting column of the print.\n\t\t\t*/\n\t\t\tcase '\\r':\n\t\t\t\tX = startcol;\n\t\t\t\tY++;\n\t\t\t\tScroll(Y-(LINES-1));\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tThe \"newline\" code behaves like the console newline character.\n\t\t\t**\tThat is, it moves the cursor down one line and at the first\n\t\t\t**\tcolumn.\n\t\t\t*/\n\t\t\tcase '\\n':\n\t\t\t\tX = 0;\n\t\t\t\tY++;\n\t\t\t\tScroll(Y-(LINES-1));\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tAll other characters are output directly and the cursor moves\n\t\t\t**\trightward to match. If the cursor wraps past the right\n\t\t\t**\tedge is it moved to the next now down at left margin. If the\n\t\t\t**\tcursor goes off the bottom of the display, the display is scrolled\n\t\t\t**\tupward a line.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\tcell.Character = *text;\n\t\t\t\tStore_Cell(cell, X, Y);\n\n\t\t\t\tX++;\n\t\t\t\tif (X >= COLUMNS) {\n\t\t\t\t\tX = 0;\n\t\t\t\t\tY++;\n\n\t\t\t\t\tif (Y > (LINES-1)) {\n\t\t\t\t\t\tScroll(Y-(LINES-1));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t}\n\t\ttext++;\n\t}\n\n\tSet_Cursor(X, Y);\n}\n\n\n/***********************************************************************************************\n * MonoClass::Text_Print -- Prints text to the monochrome object at coordinates indicated.     *\n *                                                                                             *\n *    Use this routine to output text to the monochrome object at the X and Y coordinates      *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text string to display.                                    *\n *                                                                                             *\n *          x,y   -- The X and Y character coordinates to start the printing at.               *\n *                                                                                             *\n *          attrib-- Optional parameter that specifies what text attribute code to use.        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Text_Print(char const *text, int x, int y, char attrib)\n{\n\tchar\toldx = X;\n\tchar\toldy = Y;\n\tchar\toldattrib = Attrib;\n\n\tX = (char)x;\n\tY = (char)y;\n\tAttrib = attrib;\n\tPrint(text);\n\tAttrib = oldattrib;\n\tSet_Cursor(oldx, oldy);\n}\n\n#ifdef NEVER\nvoid MonoClass::Text_Print(int text, int x, int y, char attrib)\n{\n\tchar\toldx = X;\n\tchar\toldy = Y;\n\tchar\toldattrib = Attrib;\n\n\tif (text != TXT_NONE) {\n\t\tX = (char)x;\n\t\tY = (char)y;\n\t\tAttrib = attrib;\n\t\tPrint(Text_String(text));\n\t\tAttrib = oldattrib;\n\t\tSet_Cursor(oldx, oldy);\n\t}\n}\n\nvoid MonoClass::Print(int text)\n{\n\tPrint(Text_String(text));\n}\n#endif\n\n\n/***********************************************************************************************\n * MonoClass::operator = -- Handles making one mono object have the same imagery as another.   *\n *                                                                                             *\n *    The assignment operator will handle copying the imagery from one monochrome object to    *\n *    another. Use this routine in to make two monochrome class objects visually identical.    *\n *                                                                                             *\n * INPUT:   src   -- A reference to the source (right side) monochrome object.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nMonoClass & MonoClass::operator = (MonoClass const & src)\n{\n\tmemcpy((void*)((long)MonoSegment + src.Offset(0, 0)), (void*)((long)MonoSegment + Offset(0, 0)), SIZE_OF_PAGE);\n\tSet_Cursor(src.X, src.Y);\n\treturn(*this);\n}\n\n\n/***********************************************************************************************\n * MonoClass::View -- Brings the mono object to the main display.                              *\n *                                                                                             *\n *    Use this routine to display the mono object on the monochrome screen. It is possible     *\n *    that the mono object exists on some background screen memory. Calling this routine will  *\n *    perform the necessary memory swapping to bring the data to the front. The mono object    *\n *    that was currently being viewed is not destroyed by this function. It is merely moved    *\n *    off to some background page. It can be treated normally, except that is just isn't       *\n *    visible.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::View(void)\n{\n\tMonoClass *displace;\t\t// The page that is being displaced.\n\n\tif (Get_Current() == this) return;\n\n\t/*\n\t**\tIf the visible page is already assigned to a real monochrome page\n\t**\tobject, then it must be swapped with the new one.\n\t*/\n\tdisplace = Get_Current();\n\tif (displace) {\n\t\tchar temp[SIZE_OF_PAGE];\n\n\t\tmemcpy(&temp[0], MonoSegment, SIZE_OF_PAGE);\n\t\tmemcpy(MonoSegment, (void*)((long)MonoSegment + Offset(0, 0)), SIZE_OF_PAGE);\n\t\tmemcpy((void*)((long)MonoSegment + Offset(0, 0)), &temp[0], SIZE_OF_PAGE);\n\n\t\tdisplace->Page = Page;\n\n\t} else {\n\n\t\t/*\n\t\t**\tJust copy the new page over since the display page is not assigned\n\t\t**\tto a real monochrome page object.\n\t\t*/\n\t\tmemcpy(MonoSegment, (void*)((long)MonoSegment + Offset(0, 0)), SIZE_OF_PAGE);\n\t}\n\tPageUsage[Page] = displace;\n\tPageUsage[0] = this;\n\tPage = 0;\n\n\tSet_Cursor(X, Y);\n}\n\n\n\n/************************************************************************************\n**\tThis is the set of C wrapper functions that access the MonoClass support routines.\n**\tSince the C interface doesn't have the ability to write to non-visible pages, it\n**\twill just blast the output to whichever mono page is currently visible. If there is\n**\tno mono class object that is visible, then one will be created -- BUT NOT FREED.\n**\tTypically, this is ok, since the C interface will create only one MonoClass object\n**\tand the system supports up to 8.\n*/\nvoid Mono_Set_Cursor(int x, int y)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Set_Cursor(x, y);\n\t}\n}\n\nint Mono_Printf(char const *string, ...)\n{\n\tva_list\tva;\n\tchar buffer[256];\n\n\tbuffer[0] = '\\0';\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\n\t\tva_start(va, string);\n\t\tvsprintf(buffer, string, va);\n\n\t\tmono->Print(buffer);\n\n\t\tva_end(va);\n\t}\n\treturn((short)strlen(buffer));\n}\n\n\nvoid Mono_Clear_Screen(void)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Clear();\n\t}\n}\n\nvoid Mono_Text_Print(void const *text, int x, int y, int attrib)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Text_Print((const char*)text, x, y, (char)attrib);\n\t}\n}\n\nvoid Mono_Draw_Rect(int x, int y, int w, int h, int attrib, int thick)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Draw_Box(x, y, w, h, (char)attrib, (MonoClass::BoxStyleType)thick);\n\t}\n}\n\nvoid Mono_Print(void const *text)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Print((const char*)text);\n\t}\n}\n\nint Mono_X(void)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\treturn(short)mono->Get_X();\n\t}\n\treturn(0);\n}\n\nint Mono_Y(void)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\treturn(short)mono->Get_X();\n\t}\n\treturn(0);\n}\n\n\nvoid Mono_Put_Char(char , int )\n{\n}\n\nvoid Mono_Scroll(int )\n{\n}\n\nvoid Mono_View_Page(int )\n{\n}\n\n\n#ifdef NEVER\nint Mono_Printf(int string, ...)\n{\n\tva_list\tva;\n\tchar buffer[256];\n\n\tbuffer[0] = '\\0';\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\n\t\tva_start(va, string);\n\t\tvsprintf(buffer, Text_String(string), va);\n\n\t\tmono->Print(buffer);\n\n\t\tva_end(va);\n\t}\n\treturn((short)strlen(buffer));\n}\n#endif\n\n"
  },
  {
    "path": "WIN32LIB/MONO/MONO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\monoc.h_v   2.16   06 Sep 1995 16:29:02   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               *** \n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MONO.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 2, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 2, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MONOC_H\n#define MONOC_H\n\n\nclass MonoClass {\n\t\t/*\n\t\t**\tThis is a private structure that is used to control which characters\n\t\t**\tare used when a box is drawn. Line drawing on the monochrome screen is\n\t\t**\treally made up of characters. This specifies which characters to use.\n\t\t*/\n\t\ttypedef struct {\n\t\t\tchar\tUpperLeft;\n\t\t\tchar\tTopEdge;\n\t\t\tchar\tUpperRight;\n\t\t\tchar\tRightEdge;\n\t\t\tchar\tBottomRight;\n\t\t\tchar\tBottomEdge;\n\t\t\tchar\tBottomLeft;\n\t\t\tchar\tLeftEdge;\n\t\t} BoxDataType;\n\n\t\t/*\n\t\t**\tEach cell is constructed of the actual character that is displayed and the\n\t\t**\tattribute to use. This character pair is located at every position on the\n\t\t**\tdisplay (80 x 25). Since this cell pair can be represented by a \"short\"\n\t\t**\tinteger, certain speed optimizations are taken in the monochrome drawing\n\t\t**\tcode.\n\t\t*/\n\t\ttypedef struct {\n\t\t\tchar Character;\t\t\t// Character to display.\n\t\t\tchar Attribute;\t\t\t// Attribute.\n\t\t} CellType;\n\n\t\t/*\n\t\t**\tThese private constants are used in the various monochrome operations.\n\t\t*/\n\t\tenum MonoClassPortEnums {\n\t\t\tCONTROL_PORT=0x03B4,\t\t\t// CRTC control register.\n\t\t\tDATA_PORT=0x03B5,\t\t\t\t// CRTC data register.\n\t\t\tCOLUMNS=80,\t\t\t\t\t\t// Number of columns.\n\t\t\tLINES=25,\t\t\t\t\t\t// Number of lines.\n\t\t\tSIZE_OF_PAGE=LINES*COLUMNS*sizeof(CellType),\t// Entire page size.\n\t\t\tDEFAULT_ATTRIBUTE=0x02\t\t// Normal white on black color attribute.\n\t\t};\n\n\tpublic:\n\t\tenum MonoClassPageEnums {\n\t\t\tMAX_MONO_PAGES=16,\t// Maximum RAM pages on mono card.\n\t\t\tSEGMENT=0xB000  \t\t// Monochrome screen segment.\n\t\t};\n\n\t\t/*\n\t\t**\tThese are the various box styles that may be used.\n\t\t*/\n\t\ttypedef enum BoxStyleType {\n\t\t\tSINGLE,\t\t\t\t// Single thickness.\n\t\t\tDOUBLE_HORZ,\t\t// Double thick on the horizontal axis.\n\t\t\tDOUBLE_VERT,\t\t// Double thick on the vertical axis.\n\t\t\tDOUBLE,\t\t\t\t// Double thickness.\n\n\t\t\tCOUNT\n\t\t} BoxStyleType;\n\n\t\tMonoClass(void);\n\t\t~MonoClass(void);\n\n\t\tstatic void Enable(void) {Enabled = 1;};\n\t\tstatic void Disable(void) {Enabled = 0;};\n\t\tstatic int Is_Enabled(void) {return Enabled;};\n\t\tstatic MonoClass * Get_Current(void) {return PageUsage[0];};\n\n\t\tvoid Draw_Box(int x, int y, int w, int h, char attrib=DEFAULT_ATTRIBUTE, BoxStyleType thick=SINGLE);\n\t\tvoid Set_Default_Attribute(char attrib) {Attrib = attrib;};\n\t\tvoid Clear(void);\n\t\tvoid Set_Cursor(int x, int y);\n\t\tvoid Print(char const *text);\n\t\tvoid Print(int text);\n\t\tvoid Printf(char const *text, ...);\n\t\tvoid Printf(int text, ...);\n\t\tvoid Text_Print(char const *text, int x, int y, char attrib=DEFAULT_ATTRIBUTE);\n\t\tvoid Text_Print(int text, int x, int y, char attrib=DEFAULT_ATTRIBUTE);\n\t\tvoid View(void);\n\t\tint Get_X(void) const {return X;};\n\t\tint Get_Y(void) const {return Y;};\n\n\t\t/*\n\t\t**\tHandles deep copies for the mono class objects. This performs what is essentially\n\t\t**\ta screen copy.\n\t\t*/\n\t\tMonoClass & operator = (MonoClass const & );\n\n\t\t/*\n\t\t**\tThis merely makes a duplicate of the mono object into a newly created mono\n\t\t**\tobject.\n\t\t*/\n\t\tMonoClass (MonoClass const &);\n\n\tprivate:\n\t\tchar\tX;\t\t\t\t\t// Cursor X position.\n\t\tchar\tY;\t\t\t\t\t// Cursor Y position.\n\t\tchar\tAttrib;\t\t\t// Normal attribute to use if none specified.\n\t\tchar\tPage;\t\t\t\t// The current page to write to.\n\n\t\t/*\n\t\t**\tHelper functions to help with display operations.\n\t\t*/\n\t\tint Offset(int x=0, int y=0) const {return (SIZE_OF_PAGE*Page) + sizeof(CellType)*(x + (y*COLUMNS));};\n\t\tvoid Scroll(int lines);\n\t\tvoid Store_Cell(CellType &cell, int x, int y) {\n\t\t\t*(CellType *)((long)MonoSegment + Offset(x, y)) = cell;\n\t\t};\n\n\t\t/*\n\t\t**\tThis is the segment/selector of the monochrome screen.\n\t\t*/\n\t\tstatic void * MonoSegment;\n\n\t\t/*\n\t\t** This the the arrays of characters used for drawing boxes.\n\t\t*/\n\t\tstatic BoxDataType const CharData[4];\n\n\t\t/*\n\t\t**\tThis array contains pointers to the monochrome objects that are assigned\n\t\t**\tto each of the monochrome pages. As the monochrome pages are made visible,\n\t\t**\tthey can be shuffled around between the actual locations. The first entry\n\t\t**\tin this table is the one that is visible.\n\t\t*/\n\t\tstatic MonoClass * PageUsage[MAX_MONO_PAGES];\n\n\t\t/*\n\t\t**\tIf this is true, then monochrome output is allowed. It defaults to false\n\t\t**\tso that monochrome output must be explicitly enabled.\n\t\t*/\n\t\tstatic int Enabled;\n};\n\nvoid Mono_Set_Cursor(int x, int y);\nint Mono_Printf(char const *string, ...);\nvoid Mono_Clear_Screen(void);\nvoid Mono_Text_Print(void const *text, int x, int y, int attrib);\nvoid Mono_Draw_Rect(int x, int y, int w, int h, int attrib, int thick);\nvoid Mono_Print(void const *text);\nint Mono_X(void);\nint Mono_Y(void);\n\n#endif\n\n"
  },
  {
    "path": "WIN32LIB/MOVIE/MAKE.BAT",
    "content": "SET WATCOM=D:\\RADVD\\SOURCE\\WAT11\n..\\..\\code\\wmake\n"
  },
  {
    "path": "WIN32LIB/MOVIE/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#* $Header$\n#***********************************************************************************************\n#***              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               ***\n#***********************************************************************************************\n#*                                                                                             *\n#*                 Project Name : Command & Conquer                                            *\n#*                                                                                             *\n#*                    File Name : MAKEFILE                                                     *\n#*                                                                                             *\n#*                   Programmer : Joe L. Bostic                                                *\n#*                                                                                             *\n#*                   Start Date : 03/02/95                                                     *\n#*                                                                                             *\n#*                  Last Update : March 2, 1995 [JLB]                                          *\n#*                                                                                             *\n#*---------------------------------------------------------------------------------------------*\n#* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n.SILENT\n.OPTIMIZE\n.ERASE\n\n#---------------------------------------------------------------------------\n# Working values depending on what target executable will be created.\n#---------------------------------------------------------------------------\nOBJ=obj\nCC=..\\..\\WAT11\\BINNT\\wpp386\nLIB=..\\..\\WATCOM\\BINNT\\wlib\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#  These paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.cpp:  .\n.h:    .\n.obj:  $(OBJ)\n\n\n#===========================================================================\n# Compiler and assembler flags.\n#===========================================================================\nCC_CFG = /d0                            # No debugging information\nCC_CFG += /DWIN32=1\nCC_CFG += /D_WIN32\nCC_CFG += /i=..\\..\\dxmedia\\include\nCC_CFG += /i=..\\..\\dxmedia\\classes\\base\nCC_CFG += /i=..\\..\\dxsdk\\inc\nCC_CFG += /i=..\\..\\wat11\\h\\nt                # NT include directory.\nCC_CFG += /i=..\\..\\wat11\\H                   # Normal Watcom include directory.\nCC_CFG += /bt=NT\nCC_CFG += /otxan\nCC_CFG += /5r                           # Pentium optimized register calling conventions.\nCC_CFG += /of+                          # Generate traceable stack frames.\nCC_CFG += /zp1                          # Pack structures on byte boundary.\nCC_CFG += /s                            # Remove stack check calls.\nCC_CFG += /j                            # char is now signed.\nCC_CFG += /fhq\nCC_CFG += /we                           # Treat all warnings as errors.\nCC_CFG += /w8                           # Most warnings enabled.\nCC_CFG += /ri                           # char and shorts are returned as int.\nCC_CFG += /zq                           # Operate quietly.\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj: .AUTODEPEND\n\techo Compiling $<\n\t*$(CC) $(CC_CFG) -fo$(OBJ)\\$^. $<\n\n.cpp.obj: .AUTODEPEND\n\techo Compiling $<\n\t*$(CC) $(CC_CFG) -fo$(OBJ)\\$^. $<\n\n#---------------------------------------------------------------------------\n# Object modules.\n#---------------------------------------------------------------------------\nOBJECTS = &\n\tmovie.obj\n\n############################################################################\n# If there is an abnormal termination in make process (e.g., error in compile).\n.ERROR\n\n\n#############################################################################\n# Default target\nall: mpeg.lib\n\n\n#############################################################################\n# Builds the MPEG.LIB file.\nmpeg.lib: $(OBJECTS) mpeg.lnk\n\t$(LIB) -c $^@ @mpeg.lnk\n\nmpeg.lnk: makefile\n\t%create $^@\n\tfor %index in ($(OBJECTS))  do %append $^@ -+ $(OBJ)\\%index\n"
  },
  {
    "path": "WIN32LIB/MOVIE/MOVIE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n* FILE\n*     Movie.cpp\n*\n* DESCRIPTION\n*     Movie playback using DirectShow Multimedia streaming and DirectDraw\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     May 27, 1998\n*\n****************************************************************************/\n\n#include \"movie.h\"\n#include <mmstream.h>\n#include <streams.h>\n#include <amstream.h>\n#include <ddstream.h>\n#include <stdio.h>\n\n// We declare these variables global because RA doesn't like the DirectXMedia\n// header files.\nIDirectDraw* gDDraw = NULL;\nIGraphBuilder* gGB = NULL;\nIMultiMediaStream* gMMStream = NULL;\nIMediaStream* gVideoStream = NULL;\nIDirectDrawMediaStream* gDDStream = NULL;\nIDirectDrawStreamSample* gDDSample = NULL;\n\n\n/****************************************************************************\n*\n* NAME\n*     Movie - Constructor\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nMovie::Movie(IDirectDraw* dd)\n\t{\n\tmPlaying = false;\n\n\tClose();\n\n\tgDDraw = dd;\n\n\t// Initialize COM library\n\tCoInitialize(NULL);\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     ~Movie - Destructor\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nMovie::~Movie()\n\t{\n\t// Release all\n\tClose();\n\n\t// Release COM library\n\tCoUninitialize();\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     Open\n*\n* DESCRIPTION\n*\n* INPUTS\n*     Name - Name of movie\n*\n* RESULT\n*\n****************************************************************************/\n\nbool Movie::Open(const char* name)\n\t{\n\tWCHAR wFile[MAX_PATH];\n\tIAMMultiMediaStream* amStream;\n\tDDSURFACEDESC ddsd;\n\t\n\tClose();\n\n\t//-------------------------------------------------------------------------\n\t// CREATE FILTER GRAPH FOR FILE TYPE\n\t//-------------------------------------------------------------------------\n\tif (FAILED(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,\n\t\t\tIID_IGraphBuilder, (void **)&gGB)))\n\t\t{\n\t\tMessageBox(GetDesktopWindow(), \"Couldn't create a CLSID_FilterGraph object.\\n\",\n\t\t\t\t\"DirectMedia\", MB_ICONSTOP|MB_OK);\n\t\treturn false;\n\t\t}\n\n\t//-------------------------------------------------------------------------\n\t// CREATE MULTIMEDIA STREAM\n\t//-------------------------------------------------------------------------\n\tif (FAILED(CoCreateInstance(CLSID_AMMultiMediaStream, NULL,\n\t\t\tCLSCTX_INPROC_SERVER, IID_IAMMultiMediaStream, (void**)&amStream)))\n\t\t{\n\t\tClose();\n\t\tMessageBox(GetDesktopWindow(), \"Couldn't create a CLSID_MultiMediaStream object.\\n\",\n\t\t\t\t\"DirectMedia\", MB_ICONSTOP|MB_OK);\n\t\treturn false;\n\t\t}\n\n\t// Initialize stream for reading\n\tif (FAILED(amStream->Initialize(STREAMTYPE_READ, 0, gGB)))\n\t\t{\n\t\tamStream->Release();\n\t\tClose();\n\t\tMessageBox(GetDesktopWindow(), \"Couldn't initialize MultiMediaStream object.\\n\",\n\t\t\t\t\"DirectMedia\", MB_ICONSTOP|MB_OK);\n\t\treturn false;\n\t\t}\n\n\t// We want video\n\tif (FAILED(amStream->AddMediaStream(gDDraw, &MSPID_PrimaryVideo, 0, NULL)))\n\t\t{\n\t\tamStream->Release();\n\t\tClose();\n\t\tMessageBox(GetDesktopWindow(), \"Couldn't add primary video stream.\\n\",\n\t\t\t\t\"DirectMedia\", MB_ICONSTOP|MB_OK);\n\t\treturn false;\n\t\t}\n\n\t// We want audio\n\tif (FAILED(amStream->AddMediaStream(NULL, &MSPID_PrimaryAudio,\n\t\t\tAMMSF_ADDDEFAULTRENDERER, NULL)))\n\t\t{\n\t\tamStream->Release();\n\t\tClose();\n\t\tMessageBox(GetDesktopWindow(), \"Couldn't add primary audio stream.\\n\",\n\t\t\t\t\"DirectMedia\", MB_ICONSTOP|MB_OK);\n\t\treturn false;\n\t\t}\n\n\tgMMStream = amStream;\n\n\t// Convert the filename\n\tMultiByteToWideChar(CP_ACP,0,name,-1,wFile,sizeof(wFile)/sizeof(wFile[0]));\n\n\tif (FAILED(gGB->RenderFile(wFile, NULL)))\n\t\t{\n\t\tClose();\n\t\tMessageBox(GetDesktopWindow(), \"Couldn't build filter graph.\\n\",\n\t\t\t\t\"DirectMedia\", MB_ICONSTOP|MB_OK);\n\t\treturn false;\n\t\t}\n\n\t// Get video stream\n \tif (FAILED(gMMStream->GetMediaStream(MSPID_PrimaryVideo, &gVideoStream)))\n\t\t{\n\t\tClose();\n\t\tMessageBox(GetDesktopWindow(), \"Couldn't obtain video stream.\\n\",\n\t\t\t\t\"DirectMedia\", MB_ICONSTOP|MB_OK);\n\t\treturn false;\n\t\t}\n\n \tif (FAILED(gVideoStream->QueryInterface(IID_IDirectDrawMediaStream,\n\t\t\t(void **)&gDDStream)))\n\t\t{\n\t\tClose();\n\t\tMessageBox(GetDesktopWindow(), \"Couldn't obtain video stream interface.\\n\",\n\t\t\t\t\"DirectMedia\", MB_ICONSTOP|MB_OK);\n\t\treturn false;\n\t\t}\n\n \tddsd.dwSize = sizeof(ddsd);\n \tgDDStream->GetFormat(&ddsd, NULL, NULL, NULL);\n\tmHeight = ddsd.dwHeight;\n\tmWidth = ddsd.dwWidth;\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nvoid Movie::Close(void)\n\t{\n\t// Stop currently playing movie\n\tif ((gMMStream != NULL) && (mPlaying == true))\n\t\t{\n\t\tgMMStream->SetState(STREAMSTATE_STOP);\n\t\tmPlaying = false;\n\t\t}\n\n\t// Release video sample\n\tif (gDDSample)\n\t\t{\n\t\tgDDSample->Release();\n\t\tgDDSample = NULL;\n\t\t}\n\n\t// Release DirectDrawMediaStream interface\n\tif (gDDStream)\n\t\t{\n\t\tgDDStream->Release();\n\t\tgDDStream = NULL;\n\t\t}\n\n\t// Release video stream\n\tif (gVideoStream)\n\t\t{\n\t\tgVideoStream->Release();\n\t\tgVideoStream = NULL;\n\t\t}\n\n\t// Release multimedia stream\n\tif (gMMStream)\n\t\t{\n\t\tgMMStream->Release();\n\t\tgMMStream = NULL;\n\t\t}\n\n\t// Release filter graph\n\tif (gGB)\n\t\t{\n\t\tgGB->Release();\n\t\tgGB = NULL;\n\t\t}\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     Play\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nbool Movie::Play(IDirectDrawSurface* surface)\n\t{\n\tRECT rect;\n\n\trect.top = rect.left = 0;\n\trect.bottom = mHeight;\n\trect.right = mWidth;\n\n \tif (FAILED(gDDStream->CreateSample(surface, &rect, 0, &gDDSample)))\n\t\t{\n\t\treturn false;\n\t\t}\n\n\tgMMStream->SetState(STREAMSTATE_RUN);\n\tmPlaying = true;\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     Update\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nbool Movie::Update(void)\n\t{\n\t// Update each frame\n\tif (gDDSample->Update(0, NULL, NULL, 0) != S_OK)\n\t\t{\n\t\tgMMStream->SetState(STREAMSTATE_STOP);\t\t\n\t\treturn false;\n\t\t}\n\n\treturn true;\n\t}\n"
  },
  {
    "path": "WIN32LIB/MOVIE/MOVIE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef _MOVIE_H_\n#define _MOVIE_H_\n/****************************************************************************\n*\n* FILE\n*     Movie.h\n*\n* DESCRIPTION\n*     Movie playback using DirectShow Multimedia streaming and DirectDraw\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     May 27, 1998\n*\n****************************************************************************/\n\n#include <ddraw.h>\n\nclass Movie\n\t{\n\tpublic:\n\t\tMovie(IDirectDraw* dd);\n\t\t~Movie();\n\n\t\tbool Open(const char* name);\n\t\tbool Play(IDirectDrawSurface* surface);\n\t\tbool Update(void);\n\t\tvoid Close(void);\n\n\t\tbool IsPlaying(void) const\n\t\t\t{return mPlaying;}\n\n\t\tDWORD GetWidth(void) const\n\t\t\t{return mWidth;}\n\n\t\tDWORD GetHeight(void) const\n\t\t\t{return mHeight;}\n\n\tprotected:\n\t\tDWORD mWidth;\n\t\tDWORD mHeight;\n\t\tbool mPlaying;\n\t};\n\n#endif // _MOVIE_H_\n"
  },
  {
    "path": "WIN32LIB/PALETTE/LOADPAL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Load_Palette                             *\n *                                                                         *\n *                    File Name : LOADPAL.CPP                              *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 25, 1994                           *\n *                                                                         *\n *                  Last Update : April 27, 1994   [BR]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Note: This module contains dependencies upon the file I/O system,\t\t\t*\n * specifically Load_Data().\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *\t  Load_Palette -- Loads a palette file into the given palette buffer.\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n/*\n********************************* Includes **********************************\n*/\n#include <wwstd.h>\n#include \"wwstd.h\"\n#include \"iff.h\"\n#include \"palette.h\"\n\n/*\n********************************* Constants *********************************\n*/\n\n/*\n********************************** Globals **********************************\n*/\n\n/*\n******************************** Prototypes *********************************\n*/\n\n/***************************************************************************\n *\tLoad_Palette -- Loads a palette file into the given palette buffer.\t\t*\n *                                                                         *\n * INPUT:      \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tBYTE * file_name \t\t\t- name of the file to load.\t\t\t\t\t\t*\n *\t\tBYTE * palette_pointer\t- pointer to palette buffer.\t      \t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:     \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tnone                                                        \t\t\t*\n *                                                                         *\n * WARNINGS:   \t                                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/20/1991 BS : Created.                                              *\n *   04/27/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nvoid __cdecl Load_Palette(char *palette_file_name, void *palette_pointer)\n{\n\t#if(IBM)\n\t\tLoad_Data(palette_file_name, palette_pointer, 768);\n\t#else\n\t\tLoad_Data(palette_file_name, palette_pointer, (ULONG)(2<<BIT_PLANES));\n\t#endif\n}\n\n/**************************** End of loadpal.cpp ***************************/\n"
  },
  {
    "path": "WIN32LIB/PALETTE/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = palette\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tloadpal.obj\t&\n\tmorphpal.obj\t&\n\tpalette.obj\t&\n\tpal.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/PALETTE/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = palette\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t\tloadpal.obj\t\t\\\n\t\t\t\tmorphpal.obj\t\\\n\t\t\t\tpalette.obj\t\t\\\n\t\t\t\tpal.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) \n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n -+loadpal.obj\t\t&\n-+morphpal.obj\t\t&\n-+palette.obj\t\t&\n-+pal.obj\n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/PALETTE/MORPHPAL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : wwlib32                                  *\n *                                                                         *\n *                    File Name : PALTOPAL.CPP                             *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : May 2, 1994                              *\n *                                                                         *\n *                  Last Update : May 2, 1994   [BR]                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Morph_Palette -- morphs a palette from source to destination          *\n *   Palette_To_Palette -- morph src palette to a dst palette              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n/*\n********************************* Includes **********************************\n*/\n#include \"wwstd.h\"\n#include \"palette.h\"\n#include \"timer.h\"\n\n/*\n********************************* Constants *********************************\n*/\n#define SCALE(a,b,c) (((((long)(a)<<8) / (long)(b) ) * (unsigned long)(c)) >>8)\n\n\n/*\n********************************** Globals **********************************\n*/\n\n/*\n******************************** Prototypes *********************************\n*/\n\nPRIVATE int __cdecl Palette_To_Palette(void *src_palette, void *dst_palette, unsigned long current_time, unsigned long delay);\n\n\n/***************************************************************************\n * Morph_Palette -- morphs a palette from source to destination            *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tvoid *src_pal\t- starting palette\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tvoid *dst_pal\t- ending palette\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tunsigned int delay\t- time delay in 60ths of a second\t\t\t\t\t\t\t*\n *\t\tvoid *callback\t- user-defined callback, NULL if none\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/02/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid cdecl Morph_Palette (void *src_pal, void *dst_pal, unsigned int delay,\n\tvoid (*callback) (void) )\n{\n\tint\tresult;\n\tunsigned long\tpal_start = TickCount.Time();\n\textern void   (*cb_ptr) ( void ) ;\t// callback function pointer\n\n//\t(void *)cb_ptr = callback;\n\tcb_ptr = callback ;\n\n\t/*===================================================================*/\n\t/* Make sure that we don't go too fast but also make sure we keep\t\t*/\n\t/*\t\tprocessing the morph palette if we have one.\t\t\t\t\t\t\t*/\n\t/*===================================================================*/\n\twhile (1) {\n\t\tif (src_pal && dst_pal) {\n\t\t\tresult = Palette_To_Palette (src_pal, dst_pal,\n\t\t\t\t(TickCount.Time() - pal_start), (unsigned long)delay);\n\t\t\tif (!result)\n\t\t\t\tbreak;\n\n\t\t\tif (callback) {\n\t\t\t\t(*cb_ptr)();\n\t\t\t}\n\t\t}\n\t}\n\n\treturn;\n\n}\t/* end of Morph_Palette */\n\n\n/***************************************************************************\n * Palette_To_Palette -- morph src palette to a dst palette                *\n *                                                                         *\n * Creates & sets a palette that's in-between 'src_palette' & \t\t\t\t\t*\n * 'dst_palette'; how close it is to dst_palette is based on how close \t\t*\n * 'current_time' is to 'delay'.  'current_time' & 'delay' are based on\t\t*\n * 0 being the start time.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:               void *src_palette =  palette we want to morph from *\n *                      void *dst_palette =  palette we want to morph to   *\n *                      long current_time =  time we started morph pal\t\t*\n *                      long delay         = time we want the morph to take*\n *                                                                         *\n * OUTPUT:\t\t\t\t\tint if the time had elapsed and no chages were\t\t*\n *\t\t\t\t\t\t\t\t\t  necessary this routine returns FALSE\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t  otherwise it will always return TRUE (this\t\t*\n *\t\t\t\t\t\t\t\t\t  was necessary to detect the end of the ice\t\t*\n *\t\t\t\t\t\t\t\t\t  effect.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/24/1993  MC : Created.                                             *\n *=========================================================================*/\nPRIVATE int cdecl Palette_To_Palette(void *src_palette, void *dst_palette,\n\tunsigned long current_time, unsigned long delay)\n{\n\tchar\tcolour;\n\tchar\tdiff;\n\tint\tchgval;\n\tint\tlp;\n\tint\tchange;\n\tstatic char  palette[768];\n\tchar\t*src_pal = (char*)src_palette;\n\tchar\t*dst_pal = (char*)dst_palette;\n\n\t/*======================================================================*/\n\t/* Loop through each RGB value attempting to change it to the correct\t*/\n\t/*\t\tcolor.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tfor (change = lp = 0; lp < 768; lp++) {\n\t\tif (current_time < delay ) {\n\t\t\tdiff\t\t= dst_pal[lp] & (char)63;\n\t\t\tdiff\t  -= src_pal[lp] & (char)63;\n\t\t\tif (diff)\n\t\t\t\tchange = TRUE;\n\t\t\tchgval\t= SCALE(diff, delay, current_time);\n\t\t\tcolour \t= src_pal[lp] & (char)63;\n\t\t\tcolour\t+=(char)chgval;\n\t\t}\n\t\telse {\n\t\t\tcolour = dst_pal[lp] & (char)63;\n\t\t\tchange = FALSE;\n\t\t}\n\t\tpalette[lp] = colour;\n\t}\n\t/*======================================================================*/\n\t/* Set the palette to the color that we created.\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tSet_Palette(palette);\n\treturn(change);\n\n}\t/* end of Palette_To_Palette */\n\n\n/*************************** End of morphpal.cpp ***************************/\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/PALETTE/PAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : PAL.ASM                                  *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : May 30, 1992                             *\n;*                                                                         *\n;*                  Last Update : April 27, 1994   [BR]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Set_Palette_Range -- Sets changed values in the palette.              *\n;*   Bump_Color -- adjusts specified color in specified palette            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************** Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;include \"keyboard.inc\"\nFALSE = 0\nTRUE  = 1\n\n;****************************** Declarations ********************************\nGLOBAL \t\tC Set_Palette_Range:NEAR\nGLOBAL \t\tC Bump_Color:NEAR\nGLOBAL  \tC CurrentPalette:BYTE:768\nGLOBAL\t\tC PaletteTable:byte:1024\n\n\n;********************************** Data ************************************\nLOCALS ??\n\n\tDATASEG\n\nCurrentPalette\tDB\t768 DUP(255)\t; copy of current values of DAC regs\nPaletteTable\tDB\t1024 DUP(0)\n\nIFNDEF LIB_EXTERNS_RESOLVED\nVertBlank\tDW\t0\t\t; !!!! this should go away\nENDIF\n\n\n;********************************** Code ************************************\n\tCODESEG\n\n\n\nIF 1\n;***************************************************************************\n;* SET_PALETTE_RANGE -- Sets a palette range to the new pal                *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:\tThis routine is optimized for changing a small number of   *\n;*\t\tcolors in the palette.\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/07/1995 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tSet_Palette_Range C NEAR\n\tARG\tpalette:DWORD\n\n\tGLOBAL\tSet_DD_Palette_:near\n\tGLOBAL\tWait_Vert_Blank_:near\n\n\tpushad\n\tmov\tesi,[palette]\n\tmov\tecx,768/4\n\tmov\tedi,offset CurrentPalette\n\tcld\n\trep\tmovsd\n\t;call\tWait_Vert_Blank_\n\tmov\teax,[palette]\n\tcall\tSet_DD_Palette_\n\tpopad\n\tret\n\n\nifdef NOT_FOR_WIN95\n\tUSES\teax,ebx,ecx,edx,edi,esi\n\n\tcld\n\n\t;*=================================================================*/\n\t;* Set up pointers to begin making palette comparison\t\t   */\n\t;*=================================================================*/\n\tmov\tesi, [palette]\n\tmov\tedi, OFFSET CurrentPalette\n\tmov\tebx, OFFSET PaletteTable\n\tmov\tecx, 0\n\n??loop_top:\n\tmov\teax,[esi]\t\t\t; read a dword from palette source\n\tmov\tedx,[edi]\t\t\t; read a dword from compare palette\n\tand\teax,00FFFFFFh\t\t\t; palette entrys are only 3 bytes\n\tand\tedx,00FFFFFFh\t\t\t;   long so and of extra\n\tcmp\teax,edx\t\t\t\t; if they are not the same then\n\tjne\t??set_table\t\t\t;   add them into the table\n\tadd\tesi,3\n\tadd\tedi,3\n\tinc\tcl\t\t\t\t; adjust to next palette entry\n\tjnz\t??loop_top\t\t\t; if we dont wrap to zero we have more\n\tjmp\t??set_pal\t\t\t; so now go set the palette\n??set_table:\n\tshl\teax,8\t\t\t\t; shift bgr value up register\n\tmov\tal,cl\t\t\t\t; store which palette entry num\n\tmov\t[ebx],eax\n\tadd\tebx,4\n\tmovsw\t\t\t\t\t; copy the three gun values into\n\tmovsb\t\t\t\t\t;  the shadow palette.  Use movsb\n\tinc\tcl\t\t\t\t; adjust to next palette entry\n\tjnz\t??loop_top\t\t\t; if we dont wrap to zero we have more\n\n??set_pal:\n\tmov\tesi,ebx\n\tmov\tebx,OFFSET PaletteTable\n\tsub\tesi,ebx\t\t\t\t; if ebx didn't change there\n\tjz\t??exit\t\t\t\t;   is nothing to set\n\tshr\tesi,2\t\t\t\t; find how many entrys\n\n\tmov\teax,[ebx]\n\n\tmovzx\tecx,al\t\t\t\t; we are currently on entry 0\n\tadd\tebx,4\n\n\t; Tell DAC of the color gun to start setting.\n\tmov\tedx,03C8h\n\tout\tdx,al\t\t; First color set.\n\n\t; Set the colors only during a VSync.\n\tmov\tedx,03DAh\t; CRTC register.\n\n\tpush\tebx\n\tmov\tbx,[VertBlank]\n\tand\tbl,001h\n\tshl\tbl,3\n\n??in_vbi:\n\tin\tal,dx\t\t\t\t; read CRTC status\n\tand\tal,008h\t\t\t\t; only vertical sync bit\n\txor\tal,bl\n\tje\t??in_vbi\t\t\t; in vertical sync\n\n??out_vbi:\n\tin\tal,dx\t\t\t\t; read CRTC status\n\tand\tal,008h\t\t\t\t; only vertical sync bit\n\txor\tal,bl\n\tjne\t??out_vbi\t\t\t; not in vertical sync\n\tpop\tebx\n\t; Update the DAC data register.\n\tmov\tdx,03C9h\n\n;**************** Time Critical Section Start ******************\n\tcli\n??loop:\n\tshr\teax,8\t\t; shift down the red gun value\n\tout\tdx,al\t\t; write it to the video card\n\tjmp\t$ + 2\t\t; force cache to flush, to create a time\n\tshr\teax,8\t\t; shift down the blue gun value\n\tout\tdx,al\t\t; write it to the video card\n\tjmp\t$ + 2\t\t; force cache to flush, to create a time\n\tshr\teax,8\t\t; shift down the blue gun value\n\tout\tdx,al\t\t; write the green value to video card\n\tjmp\t$ + 2\t\t; force cache to flush, to create a time\n\tinc\tecx\t\t; move edx to next palette entry\n\n\tmov\teax,[ebx]\t; get next value to set\n\tadd\tebx,4\t\t;  and post increment the palette value\n\tcmp\tal,cl\t\t; check if DAC position already correct\n\tje\t??correct_pos\n\n\tmov\tedx,03C8h\t; Tell DAC of the color gun to start setting.\n\tout\tdx,al\t\t; First color set.\n\tmov\tdx,03C9h\n\n??correct_pos:\n\tdec\tesi\n\tjnz\t??loop\n\tsti\n;***************** Time Critical Section End *******************\n??exit:\n\tret\nendif\t;NOT_FOR_WIN95\n\n\tENDP\tSet_Palette_Range\nELSE\n;***************************************************************************\n;* Set_Palette_Range -- Sets changed values in the palette.                *\n;*                                                                         *\n;* INPUT: \t\t\t\t\t\t\t\t   *\n;*\tVOID *palette - pointer to the new palette.                        *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*\tnone\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/25/1994 SKB : Created.                                             *\n;*   04/27/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\n; VOID cdecl Set_Palette_Range(VOID *palette);\n\tPROC Set_Palette_Range\tC NEAR\n\tUSES eax,ebx,ecx,edx,edi,esi\n\tARG\tpalette:DWORD\n\tLOCAL\tremain:DWORD\t; 32-bit: converted to LONG\n\n\tcld\n\n\tmov\tbx,[VertBlank]\n\tand\tbl,001h\n\tshl\tbl,3\n\n\t; Make a copy of the palette passed in.\n\tmov\tedi,OFFSET CurrentPalette\n\tmov\tesi,[palette]\n\tmov\t[remain],768\n\n\t; Search for differences between the current palette and the\n\t; new palette.  When a difference is found, output a block\n\t; of color registers and keep scanning.\n??bodyloop:\n\tmov\tecx,[remain]\n\n\trepe\tcmpsb\t\t; Search for differences.\n\tje\tshort ??exit\n\tdec\tesi\n\tdec\tedi\n\tinc\tecx\n\n\tmov\tedx,0\t\t; clear EDX\n\tmov\teax,ecx\n\tmov\tecx,3\n\tdiv\tecx\t\t; EAX = # of colors to set, EDX = Fraction.\n\tor\tedx,edx\n\tjz\tshort ??nofrac\n\tneg\tedx\n\tadd\tedx,3\t\t; Back offset skip needed.\n\tinc\teax\t\t; Fractional color rounds up to whole color to set.\n??nofrac:\n\n\t; Set CX to be the number of color guns to set.\n\tmov\tecx,eax\t\t; Colors * 3 bytes per color.\n\tadd\tecx,eax\n\tadd\tecx,eax\n\n\t; Chop this DAC dump short if necessary in order to reduce\n\t; sparkling.\n\tmov\t[remain],0\n\tcmp\tecx,86*3\t; Number of color guns to set per vert retrace\n\tjbe\tshort ??ok\n\tsub\tecx,86*3\n\tmov\t[remain],ecx\n\tmov\tecx,86*3\n??ok:\n\n\t; Adjust the palette offsets back to point to the RED color gun.\n\tsub\tesi,edx\n\tsub\tedi,edx\n\n\t; Determine the color number to start setting.\n\tneg\teax\n\tadd\teax,256\t\t; AX = Color to start setting (0..255).\n\n\t; Tell DAC of the color gun to start setting.\n\tmov\tedx,03C8h\n\tout\tdx,al\t\t; First color set.\n\n\t; Set the colors only during a VSync.\n\tmov\tedx,03DAh\t; CRTC register.\n\n??in_vbi:\n\tin\tal,dx\t\t; read CRTC status\n\tand\tal,008h\t\t; only vertical sync bit\n\txor\tal,bl\n\tje\t??in_vbi\t; in vertical sync\n\n??out_vbi:\n\tin\tal,dx\t\t; read CRTC status\n\tand\tal,008h\t\t; only vertical sync bit\n\txor\tal,bl\n\tjne\t??out_vbi\t; not in vertical sync\n\n;??wait:\n;\tin\tal,dx\n;\ttest\tal,01000b\n;\tjnz\t??wait\n\n;??retrace:\n;\tin\tal,dx\n;\ttest\tal,01000b\n;\tjz\t??retrace\n\n\t; Update the DAC data register.\n\tmov\tdx,03C9h\n\n;**************** Time Critical Section Start ******************\n\tpushf\n\tcli\n??loop:\n\tlodsb\n\tstosb\n\tout\tdx,al\n\tjmp\t$ + 2\t\t; force cache to flush, to create a time\n\t\t\t\t;  delay to give DAC time to get value\n\tloop\t??loop\n\tpopf\n;***************** Time Critical Section End *******************\n\n\tcmp\t[remain],0\n\tjnz\t??bodyloop\n\n??exit:\n\tret\n\n\tENDP\tSet_Palette_Range\nENDIF\n\n\n\n;***************************************************************************\n;* Bump_Color -- adjusts specified color in specified palette              *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*\tVOID *palette\t- palette to modify\t\t\t\t   *\n;*\tWORD changable\t- color # to change\t\t\t\t   *\n;*\tWORD target\t- color to bend toward\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/27/1994 BR : Converted to 32-bit.                                  *\n;*=========================================================================*\n; BOOL cdecl Bump_Color(VOID *palette, WORD changable, WORD target);\nPROC Bump_Color C NEAR\n\tUSES ebx,ecx,edi,esi\n\tARG\tpal:DWORD, color:WORD, desired:WORD\n\tLOCAL\tchanged:WORD\t\t; Has palette changed?\n\n\tmov\tedi,[pal]\t\t; Original palette pointer.\n\tmov\tesi,edi\n\tmov\teax,0\n\tmov\tax,[color]\n\tadd\tedi,eax\n\tadd\tedi,eax\n\tadd\tedi,eax\t\t\t; Offset to changable color.\n\tmov\tax,[desired]\n\tadd\tesi,eax\n\tadd\tesi,eax\n\tadd\tesi,eax\t\t\t; Offset to target color.\n\n\tmov\t[changed],FALSE\t\t; Presume no change.\n\tmov\tecx,3\t\t\t; Three color guns.\n\n\t; Check the color gun.\n??colorloop:\n\tmov\tal,[BYTE PTR esi]\n\tsub\tal,[BYTE PTR edi]\t; Carry flag is set if subtraction needed.\n\tjz\tshort ??gotit\n\tmov\t[changed],TRUE\n\tinc\t[BYTE PTR edi]\t\t; Presume addition.\n\tjnc\tshort ??gotit\t\t; oops, subtraction needed so dec twice.\n\tdec\t[BYTE PTR edi]\n\tdec\t[BYTE PTR edi]\n??gotit:\n\tinc\tedi\n\tinc\tesi\n\tloop\t??colorloop\n\n\tmov\tax,[changed]\n\tret\n\n\tENDP\tBump_Color\n\n\tEND\n\n;*************************** End of pal.asm ********************************\n\u001a\n"
  },
  {
    "path": "WIN32LIB/PALETTE/PALETTE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : PALETTE.C\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : BILL STOKES\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Start Date : 6/20/91\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : August 2, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Note: This module contains dependencies upon the video system,\t\t\t\t*\n * specifically Get_Video_Mode().\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Set_Palette -- sets the current palette\t\t\t\t\t\t\t\t\t\t\t*\n *   Set_Palette_Color -- Set a color number in a palette to the data.     *\n *\t  Fade_Palette_To -- Fades the current palette into another\t\t\t\t\t*\n *   Determine_Bump_Rate -- determines desired bump rate for fading        *\n *   Bump_Palette -- increments the palette one step, for fading           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n/*\n********************************* Includes **********************************\n*/\n#include <mem.h>\n#include \"wwstd.h\"\n#include \"palette.h\"\n#include \"timer.h\"\n\n/*\n********************************* Constants *********************************\n*/\n\n/*\n********************************** Globals **********************************\n*/\nextern \"C\" extern unsigned char  CurrentPalette[];\t\t/* in pal.asm */\n\n/*\n******************************** Prototypes *********************************\n*/\n\nPRIVATE void __cdecl Determine_Bump_Rate(void *palette, int delay, short *ticks, short *rate);\nPRIVATE BOOL __cdecl Bump_Palette(void *palette1, unsigned int step);\n\n/*\n******************************** Code *********************************\n*/\n\n/***************************************************************************\n * Set_Palette -- sets the current palette\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tvoid *palette\t\t- palette to set\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/25/1994 SKB : Created.                                             *\n *   04/27/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nvoid __cdecl Set_Palette(void *palette)\n{\n\n\t#if(IBM)\n\t\tSet_Palette_Range(palette);\n\t#else\n\t\tCopy_Palette(palette,CurrentPalette);\n   \tLoadRGB4(&Main_Screen->ViewPort,palette,32L);\n\t   LoadRGB4(AltVPort,palette,32L);\n\t#endif\n\n}\t/* end of Set_Palette */\n\n\n/***************************************************************************\n * Set_Palette_Color -- Set a color number in a palette to the data.       *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tvoid *palette\t- palette to set color in\t\t\t\t\t\t\t\t\t\t*\n *\t\tint color\t\t- which color index to set\t\t\t\t\t\t\t\t\t\t*\n *\t\tvoid *data\t\t- RGB data for color\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/25/1994 SKB : Created.                                             *\n *   04/27/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nvoid __cdecl Set_Palette_Color(void *palette, int color, void *data)\n{\n\t/*\n\t---------------------- Return if 'palette' is NULL -----------------------\n\t*/\n\tif (!palette) return;\n\n\t/*\n\t------------------- Change the color & set the palette -------------------\n\t*/\n\t#if(IBM)\n\t\tmemcpy(&((unsigned char *)palette)[color * RGB_BYTES], data, RGB_BYTES);\n\t\tSet_Palette_Range(palette);\n\t#else\n\t\tpalette[color] = *(unsigned short*)data;\n\t\tSet_Palette(palette);\n\t#endif\n\n}\t/* end of Set_Palette */\n\n\n/***************************************************************************\n *\tFade_Palette_To -- Fades the current palette into another\t\t\t\t\t*\n *                                                                         *\n * This will allow the palette to fade from current palette into the \t\t*\n * palette that was passed in.  This can be used to fade in and fade out.\t*\n *                                                                         *\n * INPUT:      \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *    char  *palette1 - this is the palette to fade to.           \t\t\t*\n *\t\tunsigned int delay\t\t -\tfade with this timer count down\t\t\t\t\t\t\t*\n *\t\tvoid *callback  - user-defined callback function\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/20/1991  BS : Created.                                             *\n *=========================================================================*/\nvoid Fade_Palette_To(void *palette1, unsigned int delay, void (*callback)() )\n{\n\tBOOL\tchanged;\t// Flag that palette has changed this tick.\n\tshort\tjump;\t\t// Gun values to jump per palette set.\n\tunsigned long\ttimer;\t\t// Tick count timer used for timing.\n\tshort\tticksper;\t// The ticks (fixed point) per bit jump.\n\tint\ttickaccum;\n\n\n\textern void (*cb_ptr)(void);\t// callback function pointer\n\n//\t(void *)cb_ptr = callback;\n\tcb_ptr = callback;\n\n\t/*\n\t---------------------- Return if 'palette1' is NULL ----------------------\n\t*/\n\tif (!palette1)\n\t\treturn;\n\n\t/*\n\t--------------------------- Get the bump rate ----------------------------\n\t*/\n\tDetermine_Bump_Rate(palette1, delay, &ticksper, &jump);\n\n\ttickaccum = 0;\t\t\t\t\t\t\t// init accumulated elapsed time\n\ttimer = TickCount.Time(); \t\t\t\t// timer = current time\n\tdo {\n\t\tchanged = FALSE;\n\n\t\ttickaccum += ticksper;\t\t\t// tickaccum = time of next change * 256\n\t\ttimer += (tickaccum >> 8);\t\t// timer = time of next change (rounded)\n\t\ttickaccum &= 0x0FF;\t\t\t\t// shave off high byte, keep roundoff bits\n\n\t\tchanged = Bump_Palette(palette1, jump);\t// increment palette\n\n\t\t/*\n\t\t.................. Wait for time increment to elapse ..................\n\t\t*/\n\t\tif (changed) {\n\t\t\twhile (TickCount.Time() < timer) {\n\t\t\t\t/*\n\t\t\t\t................. Update callback while waiting .................\n\t\t\t\t*/\n\t\t\t\tif (callback) {\n#if LIB_EXTERNS_RESOLVED\n\t\t\t\t\tSound_Callback();\t\t// should be removed!\n#endif\n\t\t\t\t\t(*cb_ptr)();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n#if LIB_EXTERNS_RESOLVED\n\t\tSound_Callback();\t\t// should be removed!\n#endif\n\t\tif (callback) {\n\t\t\t(*cb_ptr)();\n\t\t}\n\t} while (changed);\n\n}\t/* end of Fade_Palette_To */\n\n\n/***************************************************************************\n * Determine_Bump_Rate -- determines desired bump rate for fading          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tunsigned char *palette\t- palette to fade to\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tint delay\t\t- desired time delay in 60ths of a second\t\t\t\t\t*\n *\t\tshort *ticks\t\t- output: loop ticks per color jump\t\t\t\t\t\t\t*\n *\t\tshort *rate\t\t- output: color gun increment rate\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/27/1994 BR : Converted to 32-bit                                   *\n *   08/02/1994 SKB : Made private                                         *\n *=========================================================================*/\nPRIVATE void __cdecl Determine_Bump_Rate(void *palette, int delay, short *ticks,\n\tshort *rate)\n{\n\tint gun1;\t\t// Palette 1 gun value.\n\tint gun2;\t\t// Palette 2 gun value.\n\tint diff;\t\t// Maximum color gun difference.\n\tint tp;\t\t\t// Temporary tick accumulator.\n\tint index;\t\t// Color gun working index.\n\tlong t;\t\t\t// Working tick intermediate value.\n\tint adiff;\t\t// Absolute difference between guns.\n\n\t/*\n\t------------------------ Find max gun difference -------------------------\n\t*/\n\tdiff = 0;\n\tfor (index = 0; index < PALETTE_BYTES; index++) {\n\t\tgun1 = ((unsigned char *)palette)[index];\n\t\tgun2 = CurrentPalette[index];\n\t\tadiff = ABS(gun1-gun2);\n\t\tdiff = MAX(diff, adiff);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tticks = (total time delay ) / (max gun diff)\n\tThe value is computed based on (delay * 256), for fixed-point math;\n\tthe lower bits represent the leftover from the division;  'ticks' is\n\treturned still shifted, so the low bits can be used to accumulate the\n\ttime more accurately; the caller must shift the accumulated value down\n\t8 bits to determine the actual elapsed time!\n\t------------------------------------------------------------------------*/\n\tt = ((long)delay) << 8;\n\tif (diff) {\n\t\tt /= diff;\n\t\tt = MIN((long)t, (long)0x7FFF);\n\t}\n\t*ticks = (short)t;\n\n\t/*------------------------------------------------------------------------\n\tAdjust the color gun rate value if the time to fade is faster than can\n\treasonably be performed given the palette change, ie if (ticks>>8)==0,\n\tand thus less than 1/60 of a second\n\t------------------------------------------------------------------------*/\n\ttp = *ticks;\n\t*rate = 1;\n\twhile (*rate <= diff && *ticks < 256) {\n\t\t*ticks += tp;\n\t\t*rate += 1;\n\t}\n\n}\t/* end of Determine_Bump_Rate */\n\n\n/***************************************************************************\n * Bump_Palette -- increments the palette one step, for fading             *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tpalette1\t\t- palette to fade towards\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tstep\t\t\t- max step amount, determined by Determine_Bump_Rate\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tFALSE = no change, TRUE = changed\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/27/1994 BR : Created.                                              *\n *   08/02/1994 SKB : Made private                                         *\n *=========================================================================*/\n#if(IBM)\nPRIVATE BOOL __cdecl Bump_Palette(void *palette1, unsigned int step)\n{\n\tBOOL\tchanged=FALSE;\t\t\t\t// Flag that palette has changed this tick.\n\tint\tindex;\t\t\t\t\t\t// Index to DAC register gun.\n\tint\tgun1,gun2;\t\t\t\t\t// Palette 1 gun value.\n\tunsigned char\tpalette[PALETTE_BYTES];\t// copy of current palette\n\n\t/*\n\t---------------------- Return if 'palette1' is NULL ----------------------\n\t*/\n\tif (!palette1)\n\t\treturn (FALSE);\n\n\n\t/*\n\t------------------------ Copy the current palette ------------------------\n\t*/\n\tmemcpy(palette, CurrentPalette, 768);\n\n\t/*\n\t----------------------- Loop through palette bytes -----------------------\n\t*/\n\tfor (index = 0; index < PALETTE_BYTES; index++) {\n\t\tgun1 = ((unsigned char *)palette1)[index];\n\t\tgun2 = palette[index];\n\n\t\t/*\n\t\t............. If the colors match, go on to the next one ..............\n\t\t*/\n\t\tif (gun1 == gun2) continue;\n\n\t\tchanged = TRUE;\n\n\t\t/*\n\t\t.................. Increment current palette's color ..................\n\t\t*/\n\t\tif (gun2 < gun1) {\n\t\t\tgun2 += step;\n\t\t\tgun2 = MIN(gun2, gun1);\t\t// make sure we didn't overshoot it\n\t\t}\n\t\t/*\n\t\t.................. Decrement current palette's color ..................\n\t\t*/\n\t\telse {\n\t\t\tgun2 -= step;\n\t\t\tgun2 = MAX(gun2, gun1);\t\t// make sure we didn't overshoot it\n\t\t}\n\n\t\tpalette[index] = (unsigned char)gun2;\n\t}\n\n\t/*\n\t----------------- Set current palette to the new palette -----------------\n\t*/\n\tif (changed) {\n\t\tSet_Palette(&palette[0]);\n\t}\n\n\treturn (changed);\n\n}\t/* end of Bump_Palette */\n\n#else\n\n\t/* This is already implemented in asm on the Amiga */\n\n#endif\n\nvoid (*cb_ptr)(void);\t// callback function pointer\n\n/**************************** End of palette.cpp ***************************/\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/PALETTE/PALETTE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Palette 32bit Library.                   *\n;*                                                                         *\n;*                    File Name : PALETTE.H                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : April 25, 1994                           *\n;*                                                                         *\n;*                  Last Update : April 27, 1994 [BRR]\t\t\t\t\t\t\t*\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef PALETTE_H\n#define PALETTE_H\n\n#include <gbuffer.h>\n/*\n********************************* Constants *********************************\n*/\n#define RGB_BYTES\t\t\t3\n#define PALETTE_SIZE\t\t256\n#define PALETTE_BYTES\t768\n\n/*\n******************************** Prototypes *********************************\n*/\n/*\n-------------------------------- Palette.cpp --------------------------------\n*/\nvoid __cdecl Set_Palette(void *palette);\nvoid __cdecl Set_Palette_Color(void *palette, int color, void *data);\nvoid Fade_Palette_To(void *palette1, unsigned int delay, void (*callback)() );\n\n/*\n-------------------------------- loadpal.cpp --------------------------------\n*/\nvoid __cdecl Load_Palette(char *palette_file_name, void *palette_pointer);\n\n/*\n------------------------------- morphpal.cpp --------------------------------\n*/\nvoid __cdecl Morph_Palette (void *src_palette, void *dst_palette, unsigned int delay,\n\tvoid *callback);\n\n/*\n---------------------------------- pal.asm ----------------------------------\n*/\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern void __cdecl Set_Palette_Range(void *palette);\nextern BOOL __cdecl Bump_Color(void *palette, int changable, int target);\n\n#ifdef __cplusplus\n}\n#endif\nextern \"C\" extern unsigned char  CurrentPalette[];\t\t/* in pal.asm */\n\n\n#endif // PALETTE_H\n\n/***************************** End of palette.h ****************************/\n"
  },
  {
    "path": "WIN32LIB/PLAYCD/GETCD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : GETCD.CPP\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : STEVE WETHERILL BASED ON JOE BOSTIC CODE *\n *                                                                         *\n *                   Start Date : 5/13/94\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : June 4, 1994   [SW]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *\t\tGetCDClass::GetCDClass\t--\tdefault constructor                       *\n *\t\tGetCDClass::~GetCDClass\t--\tdestructor                                *\n *\t\tGetCDClass::GetCDDrive\t--\treturns the logical CD drive              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <dos.h>\n\n#include \"wwstd.h\"\n#include \"playcd.h\"\n#include \"wwmem.h\"\n\n\n/***************************************************************************\n * GetCDClass -- default constructor\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *       none \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone                          \t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW   : Created.                                            *\n *   12/4/95    ST   : fixed for Win95                                     *\n *=========================================================================*/\n\nGetCDClass::GetCDClass(VOID)\n{\n\tchar\tpath[]={\"a:\\\\\"};\n\n\tCDCount = 0;\n\tCDIndex = 0;\n\n\t/*\n\t** Set all CD drive placeholders to empty\n\t*/\n\tmemset (CDDrives, NO_CD_DRIVE, MAX_CD_DRIVES);\n\n\n\tfor (char i='c' ; i<='z' ; i++){\n\t\tpath[0]=i;\n\t\tif (GetDriveType (path) == DRIVE_CDROM){\n\t\t\tCDDrives[CDCount++] = (int) (i-'a');\n\t\t}\n\t}\n\n\t/*\n\t**\tCatch the case when there are NO CD-ROM drives available\n\t*/\n\tif (CDCount == 0) {\n\t\tfor (char i='a' ; i<='b' ; i++){\n\t\t\tpath[0]=i;\n\t\t\tif (GetDriveType (path) == DRIVE_CDROM){\n\t\t\t\tCDDrives[CDCount++] = (int) (i-'a');\n\t\t\t}\n\t\t}\n\t}\n}\n\n/***************************************************************************\n * GetCDClass -- destructor                                                *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW: Created.                                               *\n *   12/4/95    ST: fixed for Win95                                        *\n *=========================================================================*/\n\nGetCDClass::~GetCDClass(VOID)\n{\n//\tif(cdDrive_addrp.seg)\n//\t\tDPMI_real_free(cdDrive_addrp);\t\t// free up those conventional buffers\n}\n\n/* ==================================================================== */\n\n"
  },
  {
    "path": "WIN32LIB/PLAYCD/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = playcd\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n        getcd.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WWLIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\n#**************************** End of makefile ******************************\n"
  },
  {
    "path": "WIN32LIB/PLAYCD/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 27, 1995                           *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = playcd\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tgetcd.obj\t&\n\tredbook.obj\t&\n\tplaycd.obj\n\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/PLAYCD/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 27, 1995                           *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = playcd\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tgetcd.obj\t&\n\tredbook.obj\t&\n\tplaycd.obj\n\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/PLAYCD/PLAYCD.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nLOCALS ??\n\n\nDPMI_INTR equ\t031h\n\nGLOBAL \tDPMI_real_alloc   : near\nGLOBAL  DPMI_real_free    : near\nGLOBAL  DPMI_real_intr    : near\nGLOBAL  DPMI_real_call    : near\n\n\nSTRUC SEGSEL\n\t  segmen  dw ?\n \t  select  dw ?\nENDS\n\nSTRUC REGS \n\t_eax   dd ?\n\t_ebx   dd ?\n\t_ecx   dd ?\n\t_edx   dd ?\n\t_esi   dd ?\n\t_edi   dd ?\n\t_cflag dd ?\nENDS\n\nSTRUC SREGS \n\t_es  dw ?\n\t_cs  dw ?\n\t_ss  dw ?\n\t_ds  dw ?\n        _fs  dw ?\n\t_gs  dw ?\nENDS\n\nSTRUC DPMI_REGS\n       _edi  dd ?\n       _esi  dd ?\t\n       _ebp  dd ?\t\n       \t     dd ?\n       _ebx  dd ?\t\n       _edx  dd ?\t\n       _ecx  dd ?\t\n       _eax  dd ?\t\n       Flags dw ?\n       _es   dw ?\n       _ds   dw ?\n       _fs   dw ?\n       _gs   dw ?\n       _ip   dw ?\n       _cs   dw ?\n       _sp   dw ?\n       _ss   dw ?\n       \t     dd ?\n\t     dd\t?\n   size_ref  db\t?\t\nENDS\n    \n    \nCODESEG\n\n; int  DPMI_real_alloc ( UINT , SEGREG * , USHORT * ) ;\n\nPROC DPMI_real_alloc C near \n\tUSES\tebx , edx\n\tARG\tparagra        : DWORD\n\tARG\tblk_segptr    : DWORD\n\tARG\tlargest_blkptr : DWORD\n\n\tmov\teax, 0100h\n\tmov\tebx, [paragra]\n\tint\tDPMI_INTR\n\n\tjnc\t??dpmi_succed\n\tmov\tebx, [largest_blkptr]\n\tmov\t[ word ptr ebx ] , bx\n\tmovzx\teax , al\n \tret\n\n??dpmi_succed:\n\tmov\tebx, [blk_segptr]\n\tmov\t[(type SEGSEL ptr ebx). segmen ] , ax\n\tmov\t[(type SEGSEL ptr ebx). select ] , dx\n\txor\teax , eax\n\tret\n\t\t\nENDP DPMI_real_alloc\t\n\n\n;**************************************************************************\n; int  DPMI_real_free ( UINT ) ;\n\nPROC DPMI_real_free C near \n\tUSES\teax , edx\n\tARG\tblk_selec  : DWORD\n\n\tmov\teax, 0101h\n\tmov\tedx, [blk_selec]\n\tshr\tedx , 16\n\tint\tDPMI_INTR\n \tret\nENDP DPMI_real_free\t\n\n\nPROC DPMI_real_intr C near \n\tUSES\teax , ebx , ecx , edx , edi , esi \n\tARG\tvector  : dword\n\tARG     regs_ptr: dword\n\tARG     sreg_ptr: dword\n\n\tLOCAL\tregblk : DPMI_REGS\n\n\tlea\tedi , [ regblk ]\n\txor\teax , eax\n\tlea\tecx , [ regblk . size_ref ]\n\tsub\tecx , edi\n\tshr\tecx , 2\n\trep\tstosd\n\n  \tmov\tebx , [ regs_ptr ]\n\tmov\teax , [ (type REGS ptr ebx) . _eax ] \n\tmov\t[ regblk . _eax ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _ebx ] \n\tmov\t[ regblk . _ebx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _ecx ] \n\tmov\t[ regblk . _ecx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _edx ] \n\tmov\t[ regblk . _edx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _esi ] \n\tmov\t[ regblk . _esi ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _edi ] \n\tmov\t[ regblk . _edi ] , eax\n\n\n  \tmov\tebx , [ sreg_ptr ]\n\tmov\tax , [ (type SREGS ptr ebx) . _es ] \n\tmov\t[ regblk . _es ] , ax\n\n\tmov\tax , [ (type SREGS ptr ebx) . _ds ] \n\tmov\t[ regblk . _ds ] , ax\n\n\tmov\teax , 0300h\n\tmov\tebx , [ vector ]\n\txor     bh , bh\n\txor \tecx , ecx\n\tlea\tedi , [ regblk ]\n\n\tint\tDPMI_INTR\n\n  \tmov\tebx , [ regs_ptr ]\n\tmov\teax , [ regblk . _eax ] \n\tmov\t[ (type REGS ptr ebx) . _eax ] , eax\n\n\tmov\teax , [ regblk . _ebx ] \n\tmov\t[ (type REGS ptr ebx) . _ebx ] , eax\n\n\tmov\teax , [ regblk . _ecx ] \n\tmov\t[ (type REGS ptr ebx) . _ecx ] , eax\n\n\tmov\teax , [ regblk . _edx ] \n\tmov\t[ (type REGS ptr ebx) . _edx ] , eax\n\n\tmov\teax , [ regblk . _esi ] \n\tmov\t[ (type REGS ptr ebx) . _esi ] , eax\n\n\tmov\teax , [ regblk . _edi ] \n\tmov\t[ (type REGS ptr ebx) . _edi ] , eax\n\n\n  \tmov\tebx , [ sreg_ptr ]\n\tmov\tax , [ regblk . _es ] \n\tmov\t[ (type SREGS ptr ebx) . _es ] , ax\n\n\tmov\tax , [ regblk . _ds ] \n\tmov\t[ (type SREGS ptr ebx) . _ds ] , ax\n\n \tret\nENDP DPMI_real_intr\t\n\n\nPROC DPMI_real_call C near \n\tUSES\teax , ebx , ecx , edx , edi , esi \n\tARG\tvector  : dword\n\tARG     regs_ptr: dword\n\tARG     sreg_ptr: dword\n\n\tLOCAL\tregblk : DPMI_REGS\n\n\n\tlea\tedi , [ regblk ]\n\txor\tal , al\n\tlea\tecx , [ regblk . size_ref ]\n\tsub\tecx , edi\n\trep\tmovsb\n\n\n  \tmov\tebx , [ regs_ptr ]\n\tmov\teax , [ (type REGS ptr ebx) . _eax ] \n\tmov\t[ regblk . _eax ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _ebx ] \n\tmov\t[ regblk . _ebx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _ecx ] \n\tmov\t[ regblk . _ecx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _edx ] \n\tmov\t[ regblk . _edx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _esi ] \n\tmov\t[ regblk . _esi ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _edi ] \n\tmov\t[ regblk . _edi ] , eax\n\n\n  \tmov\tebx , [ sreg_ptr ]\n\tmov\tax , [ (type SREGS ptr ebx) . _es ] \n\tmov\t[ regblk . _es ] , ax\n\n\tmov\tax , [ (type SREGS ptr ebx) . _ds ] \n\tmov\t[ regblk . _ds ] , ax\n\n;\tmov\teax , 0300h\n;\tmov\tebx , [ vector ]\n;\txor     bh , bh\n;\txor \tecx , ecx\n;\tlea\tedi , [ regblk ]\n\n;\tint\tDPMI_INTR\n\n  \tmov\tebx , [ regs_ptr ]\n\tmov\teax , [ regblk . _eax ] \n\tmov\t[ (type REGS ptr ebx) . _eax ] , eax\n\tmov\teax , [ regblk . _ebx ] \n\tmov\t[ (type REGS ptr ebx) . _ebx ] , eax\n\tmov\teax , [ regblk . _ecx ] \n\tmov\t[ (type REGS ptr ebx) . _ecx ] , eax\n\tmov\teax , [ regblk . _edx ] \n\tmov\t[ (type REGS ptr ebx) . _edx ] , eax\n\n\tmov\teax , [ regblk . _esi ] \n\tmov\t[ (type REGS ptr ebx) . _esi ] , eax\n\tmov\teax , [ regblk . _edi ] \n\tmov\t[ (type REGS ptr ebx) . _edi ] , eax\n\n\n  \tmov\tebx , [ sreg_ptr ]\n\tmov\tax , [ regblk . _es ] \n\tmov\t[ (type SREGS ptr ebx) . _es ] , ax\n\n\tmov\tax , [ regblk . _ds ] \n\tmov\t[ (type SREGS ptr ebx) . _ds ] , ax\n\n \tret\nENDP DPMI_real_call\n\nEND\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/PLAYCD/PLAYCD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB\t  \t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : PLAYCD.H\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : STEVE WETHERILL\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Start Date : 5/13/94\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : June 4, 1994   [SW]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*/\n\n#ifndef PLAYCD_H\n#define PLAYCD_H\n\n\n#ifdef NOT_FOR_WIN95\n/* ==================================================================== */\n/* Defines */\n/* ==================================================================== */\n\n#define\tCHLEFT\t0\n#define\tCHRIGHT\t1\n#define\tCHBOTH\t2\n\n#define\tAUDIO_START_MIN\t1\n#define\tAUDIO_START_SEC  44\n\ntypedef struct {\n\t\t\t\t\t  unsigned short seg ;\n \t\t\t\t\t  unsigned short sel ;\n\t\t\t\t\t} SEGSEL ;\n\n\n\n\nextern \"C\" int  DPMI_real_alloc ( UINT , SEGSEL * , USHORT * ) ;\nextern \"C\" int  DPMI_real_free ( SEGSEL  ) ;\nextern \"C\" void DPMI_real_intr ( int , union REGS * , struct SREGS * );\nextern \"C\" void DPMI_real_call ( void * funct , union REGS * , struct SREGS * );\n\n\n\n\n/* ==================================================================== */\n/* Data structures */\n/* ==================================================================== */\n\n// Audio Track Info request block\n\nstruct\tTinfoType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tTrInfo;\n\tUBYTE\t\tTrack;\n\tULONG\t\tStart;\n\tUBYTE\t\tTrCtrl;\n};\n\n// Audio Track Status Control Block\n\nstruct\tStatType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tStatInfo;\n\tUWORD\t\tStat;\n\tULONG\t\tStart;\n\tULONG\t\tEnd;\n\t};\n\n// Audio Track Volume control block\n\nstruct\tVolmType\t{\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tTrInfo;\n\tUBYTE\t\tIn0;\n\tUBYTE\t\tVol0;\n\tUBYTE\t\tIn1;\n\tUBYTE\t\tVol1;\n\tUBYTE\t\tIn2;\n\tUBYTE\t\tVol2;\n\tUBYTE\t\tIn3;\n\tUBYTE\t\tVol3;\n\t};\n\n// Audio Track Play request block\n\nstruct\tPlayType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tAddrMd;\n\tULONG\t\tStart;\n\tULONG\t\tCntSect;\n\t};\n\n\n// Audio Track Stop request block\n\nstruct\tStopType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\t};\n\n#endif\t//NOT_FOR_WIN95\n\n/***************************************************************************\n * GetCDClass -- object which will return logical CD drive\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/04/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n\n#define MAX_CD_DRIVES 26\n#define NO_CD_DRIVE -1\n\nclass\tGetCDClass {\n\nprotected:\n\n\tint\tCDDrives[MAX_CD_DRIVES];\t//Array containing CD drive letters\n\tint\tCDCount;\t\t\t\t\t\t\t//Number of available CD drives\n\tint\tCDIndex;\n\npublic:\n\n\n\tGetCDClass(VOID);\t\t\t\t\t// This is the default constructor\n\t~GetCDClass(VOID);\t\t\t\t// This is the destructor\n\n\tinline\tint\tGet_First_CD_Drive(void);\n\tinline\tint\tGet_Next_CD_Drive(void);\n\tinline\tint\tGet_Number_Of_Drives(void) {return (CDCount);};\n\n};\n\n\n\n/***********************************************************************************************\n * GCDC::Get_Next_CD_Drive -- return the logical drive number of the next CD drive             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Logical drive number of a cd drive or -1 if none                                  *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/21/96 3:50PM ST : Created                                                              *\n *=============================================================================================*/\ninline int GetCDClass::Get_Next_CD_Drive(void)\n{\n\tif (CDCount){\n\t\tif (CDIndex == CDCount) CDIndex = 0;\n\t\treturn (CDDrives[CDIndex++]);\n\t}else{\n\t\treturn (-1);\n\t}\n}\n\n\n\n/***************************************************************************\n * GCDC::Get_First_CD_Drive -- return the number of the first CD drive     *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * OUTPUT:                                                                 *\n *\t\t\tlogical drive number \t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *   12/4/95    ST : fixed for Win95                                       *\n *=========================================================================*/\ninline int GetCDClass::Get_First_CD_Drive(void)\n{\n\tCDIndex = 0;\n\treturn (Get_Next_CD_Drive());\n}\n\n\n\n\n\n\n/***************************************************************************\n * RedBookClass -- adds red book functionality\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tthis class inherits from GetCDClass and adds red book play functionality*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/04/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n\n#ifdef NOT_FOR_WIN95\nclass RedBookClass : public GetCDClass {\n\nprivate:\n\n\tSEGSEL\t\tTinfo_addrp;\n\tSEGSEL\t\tStat_addrp;\n\tSEGSEL\t\tStop_addrp;\n\tSEGSEL\t\tVolm_addrp;\n\tSEGSEL  \t   Play_addrp;\n\n\tStopType \tStop;\n\tPlayType\t\tPlay;\n\tVolmType\t\tVolm;\n\tStatType\t\tStat;\n\tTinfoType\tTinfo;\n\npublic:\n\n\tRedBookClass(VOID);\t\t\t\t\t// This is the default constructor\n\t~RedBookClass(VOID);\t\t\t\t\t// This is the destructor\n\n\tULONG\tRedToHS(ULONG i);\n\tULONG MSFtoRed(UBYTE m, UBYTE s, UBYTE f);\n\tVOID  FullCDVolume(UBYTE chan);\n\tVOID  PlayTrack(UWORD track);\n\tVOID  Play_CD_MSL(UWORD min_sec, UWORD len);\n\tVOID  PlayMSF(UBYTE startM, UBYTE startS, UBYTE startF,\n\t\t\t\tUBYTE endM, UBYTE endS, UBYTE endF, UBYTE chan);\n\tUWORD CheckCDMusic(VOID);\n\tVOID  StopCDMusic(VOID);\n\n};\n\n#endif\t//NOT_FOR_WIN95\n/***************************** End of Playcd.h ****************************/\n\n#endif // PLAYCD_H\n\u001a\n"
  },
  {
    "path": "WIN32LIB/PLAYCD/REDBOOK.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB\t  \t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : REDBOOK.CPP\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : STEVE WETHERILL (FROM SCOTT BOWEN CODE)  *\n *                                                                         *\n *                   Start Date : 5/13/94\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : June 4, 1994   [SW]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *\t\tRedBookClass::~RedBookClass(VOID)\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tRedBookClass::RedToHS(ULONG i)\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tRedBookClass::MSFtoRed(UBYTE m, UBYTE s, UBYTE f)\t\t\t\t\t\t\t*\n *\t\tRedBookClass::FullCDVolume(UBYTE chan)\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tRedBookClass::PlayTrack(UWORD track)\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tRedBookClass::Play_CD_MSL(UWORD min_sec, UWORD len)\t\t\t\t\t\t*\n *\t\tRedBookClass::PlayMSF(UBYTE startM, UBYTE startS, UBYTE startF,\t\t*\n * \t\t\t  \t\t\t\tUBYTE endM, UBYTE endS, UBYTE endF, UBYTE chan)\t\t*\n *\t\tRedBookClass::CheckCDMusic(VOID)\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tRedBookClass::StopCDMusic(VOID)\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <dos.h>\n\n#include \"wwstd.h\"\n#include \"playcd.h\"\n#include \"wwmem.h\"\n\n\n/***************************************************************************\n * RedBookClass -- default constructor\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *      \tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *\t\tcalls GetCDDrive()\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * HISTORY:                                                                *\n *   05/25/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n\nRedBookClass::RedBookClass(VOID)\n\t: GetCDClass()\t\t\t// call the base constructor\n\n{\n\tSEGSEL tmpadr ;\n\n\ttmpadr = cdDrive_addrp;\n\tmemset ( this  , 0 , sizeof ( RedBookClass )\t) ;\n\tcdDrive_addrp = tmpadr ;\n\n\tStop.Length\t\t=\t13;\n\tStop.Command\t=\t133;\n\n\tTinfo.Length\t=\t26;\n\tTinfo.Command\t=\t3;\n\tTinfo.CntTrns\t=\t7;\n\tTinfo.TrInfo\t=\t11;\n\n\tPlay.Length\t\t=\t22;\n\tPlay.Command\t=\t132;\n\tPlay.AddrMd\t\t=\t1;\n\t\n\tVolm.Length\t\t=\t26;\n\tVolm.Command\t=\t12;\n\tVolm.CntTrns\t=\t9;\n\tVolm.TrInfo\t\t=\t3;\n\tVolm.In1\t\t\t=\t1;\n\tVolm.In2\t\t\t=\t2;\n\tVolm.In3\t\t\t=\t3;\n\t\n\tStat.Length\t\t=\t26;\n\tStat.Command\t=\t3;\n\tStat.CntTrns\t=\t11;\n\tStat.StatInfo\t=\t15;\n\t\t\t\t\t\t\t\n\tif\t(DPMI_real_alloc(sizeof(TinfoType)/16+1, &Tinfo_addrp, &largestp))\n\t\texit(1);\n\n\tif\t(DPMI_real_alloc(sizeof(StatType)/16+1, &Stat_addrp, &largestp))\n\t\texit(1);\n\n\tif\t(DPMI_real_alloc(sizeof(VolmType)/16+1, &Volm_addrp, &largestp))\n\t\texit(1);\n\n\tif\t(DPMI_real_alloc(sizeof(PlayType)/16+1, &Play_addrp, &largestp))\n\t\texit(1);\n\n\tif\t(DPMI_real_alloc(sizeof(StopType)/16+1, &Stop_addrp, &largestp))\n\t\texit(1);\n\n\tGetCDDrive();\n\n}\n\n/***************************************************************************\n * REDBOOKCLASS -- destructor                                              *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *=========================================================================*/\n\nRedBookClass::~RedBookClass(VOID)\n{\n\tif(Tinfo_addrp.seg)\n\t\tDPMI_real_free(Tinfo_addrp);\t\t// free up those conventional buffers\n\n\tif(Stat_addrp.seg)\n\t\tDPMI_real_free(Stat_addrp);\n\n\tif(Volm_addrp.seg)\n\t\tDPMI_real_free(Volm_addrp);\n\n\tif(Play_addrp.seg)\n\t\tDPMI_real_free(Play_addrp);\n\n\tif(Stop_addrp.seg)\n\t\tDPMI_real_free(Stop_addrp);\n}\n\n/***************************************************************************\n * REDTOHS -- RedBook to High-Sierra conversion                            *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tULONG\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:    \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tULONG\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n\nULONG RedBookClass::RedToHS(ULONG i)\n{\n\treturn( ((i>>16) & 0xFF) * 60 * 75) + ( ((i>>8) & 0xFF) * 75) + (i & 0xFF);\n}\n\n/***************************************************************************\n * MSFTORED -- Minute, Second, Frame to RedBook conversion                 *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *   \t\tUBYTE\tminute\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * \t\tUBYTE\tsecond\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t  \t\tUBYTE\tframe\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:          \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tULONG\tRedBook\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *=========================================================================*/\n\nULONG  RedBookClass::MSFtoRed(UBYTE m, UBYTE s, UBYTE f)\n{\n\treturn( ((ULONG)m << 16) + ((ULONG)s << 8) + (ULONG)f );\n}\n\n/***************************************************************************\n * FULLCDVOLUME -- set full volume                                         *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tUBYTE channel\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\tCHLEFT\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\tCHRIGHT\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\tCHBOTH\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *    \t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *=========================================================================*/\n\nVOID  RedBookClass::FullCDVolume(UBYTE chan)\n{\n\n\tVolm.Vol0 = Volm.Vol1 = Volm.Vol2 = Volm.Vol3 = 255;\n\n\tVolm.TrnsAdOff = offsetof\t(VolmType, TrInfo);\n\tVolm.TrnsAdSeg = Volm_addrp.seg;\n\n\tif(chan == CHLEFT)\n\t{\n//\t\tVolm.In0 = 0;\n//\t\tVolm.In1 = 3;\n//\t\tVolm.In2 = 3;\n//\t\tVolm.In3 = 3;\n\t\tVolm.Vol1 = 0;\n\t}\n\telse if(chan == CHRIGHT)\n\t{\n//\t\tVolm.In0 = 3;\n//\t\tVolm.In1 = 1;\n//\t\tVolm.In2 = 3;\n//\t\tVolm.In3 = 3;\n\t\tVolm.Vol0 = 0;\n\t}\n\telse\t\t\t/* both channels */\n\t{\n\t\tVolm.In0 = 0;\n\t\tVolm.In1 = 1;\n\t\tVolm.In2 = 2;\n\t\tVolm.In3 = 3;\n\t}\n\n//\tWriteRealMem(REALPTR(Volm_addrp) << 16, &Volm, sizeof(VolmType));\n\tMem_Copy ( &Volm , (void *) ( Volm_addrp.seg << 4 ) , sizeof(VolmType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = 0x0000;\n\tsregs.es   = Volm_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs, & sregs);\n\n//\tReadRealMem(&Volm, REALPTR(Volm_addrp) << 16, sizeof(VolmType));\n\tMem_Copy ( (void *) ( Volm_addrp . seg << 4 ), &Volm ,sizeof(VolmType));\n}\n\n\n\n/***************************************************************************\n * PLAYTRACK -- play a track                                               *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n * \t\tUWORD\ttrack\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *=========================================================================*/\n\nVOID  RedBookClass::PlayTrack(UWORD track)\n{\n\n\tStopCDMusic();\n\n\tTinfo.Track = track;\n\n\tTinfo.TrnsAdOff = offsetof\t(TinfoType, TrInfo);\n\tTinfo.TrnsAdSeg = Tinfo_addrp.seg;\n\n//\tWriteRealMem(REALPTR(Tinfo_addrp) << 16, &Tinfo, sizeof(TinfoType));\n\tMem_Copy ( &Tinfo , (void *) ( Tinfo_addrp.seg << 4 ) , sizeof(TinfoType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx\t= cdDrive[0];\n\tregs.x.ebx = 0x0000;\n\tsregs.es \t= Tinfo_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs, &sregs);\t\t// gets start time of track in Tinfo.Start\n\n//\tReadRealMem(&Tinfo, REALPTR(Tinfo_addrp) << 16, sizeof(TinfoType));\n\tMem_Copy ( (void *) ( Tinfo_addrp.seg << 4 ) , &Tinfo, sizeof(TinfoType));\n\n\n\n\n\tPlay.Start = Tinfo.Start;\n\tTinfo.Track++;\n\n\tTinfo.TrnsAdOff = offsetof\t(TinfoType, TrInfo);\n\tTinfo.TrnsAdSeg = Tinfo_addrp.seg;\n\n//\tWriteRealMem(REALPTR(Tinfo_addrp) << 16, &Tinfo, sizeof(TinfoType));\n\tMem_Copy ( &Tinfo , (void *) ( Tinfo_addrp.seg << 4 ) , sizeof(TinfoType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = 0x0000;\n\tsregs.es  = Tinfo_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs , &sregs);\t\t// gets start time of following track in Tinfo.Start\n\n//\tReadRealMem(&Tinfo, REALPTR(Tinfo_addrp) << 16, sizeof(TinfoType));\n\tMem_Copy ( (void *) ( Tinfo_addrp.seg << 4 ) , &Tinfo, sizeof(TinfoType));\n\n\n\n\tPlay.CntSect  = RedToHS(Tinfo.Start) - RedToHS(Play.Start) - 1;\n\n//\tWriteRealMem(REALPTR(Play_addrp) << 16, &Play, sizeof(PlayType));\n\tMem_Copy ( &Play , (void *) ( Play_addrp.seg << 4 ) , sizeof(PlayType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = 0x0000;\n\tsregs.es \t= Play_addrp.seg;\n\n  \tDPMI_real_intr(0x2F, &regs, &sregs);\n\n//\tReadRealMem(&Play, REALPTR(Play_addrp) << 16, sizeof(PlayType));\n\tMem_Copy ( (void *) ( Play_addrp.seg << 4 ) , &Play, sizeof(PlayType));\n\n\n\tFullCDVolume(CHBOTH);\n}\n\n\n/***************************************************************************\n * PLAY_CD_MSL -- play cd from start min_sec for len                       *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tUWORD\tmin_sec\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUWORD\tLen\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *=========================================================================*/\n\n\nVOID  RedBookClass::Play_CD_MSL(UWORD min_sec, UWORD len) \n{\n\tUWORD startM, startS, startF;\n\tUWORD endM, endS, endF;\n\n\tif (!len)\n\t\treturn;\n\n\tendM = startM = (min_sec >> 8) + AUDIO_START_MIN;\n\tendS = startS = (min_sec & 0xFF) + AUDIO_START_SEC;\n\tstartF = endF = 0;\n\n\twhile (len > 59) {\n\t\tendM++;\n\t\tlen -= 60;\n\t}\n\n\tendS += len;\n\tif (endS > 59) {\n\t\tendM++;\n\t\tendS -= 60;\n\t}\n\n\tPlayMSF((UBYTE) startM, (UBYTE)startS, (UBYTE)startF, (UBYTE)endM, (UBYTE)endS, (UBYTE)endF, 2 /* chan */);\n}\n\n\n/***************************************************************************\n * PlayMSF -- Play Minute, Second, Frame to Minute, Second, Frame\t\t\t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tUBYTE\tstartM\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tstartS\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tstartF\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *    \tUBYTE\tendM\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tendS\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tendF\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tchan\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/27/1994 SW : Created.                                              *\n *=========================================================================*/\n\n\nVOID  RedBookClass::PlayMSF(UBYTE startM, UBYTE startS, UBYTE startF, UBYTE endM, UBYTE endS, UBYTE endF, UBYTE chan)\n{\n\n\tPlay.Start = MSFtoRed(startM, startS, startF);\n\tPlay.CntSect  = RedToHS(MSFtoRed(endM, endS, endF)) - RedToHS(Play.Start) - 1;\n\n//\tWriteRealMem(REALPTR(Play_addrp) << 16, &Play, sizeof(PlayType));\n\tMem_Copy ( &Play , (void *) ( Play_addrp.seg << 4 ) , sizeof(PlayType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = offsetof (PlayType, Length);\n\tsregs.es \t= Play_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs, &sregs);\n\n//\tReadRealMem(&Play, REALPTR(Play_addrp) << 16, sizeof(PlayType));\n\tMem_Copy ( (void *) ( Play_addrp.seg << 4 ) , &Play, sizeof(PlayType));\n\n\tFullCDVolume(chan);\n\n}\n\n/***************************************************************************\n * CheckCDMusic -- Check for CD playing\t\t\t\t\t   \t\t\t\t\t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tUBYTE\tstartM\t\t\t  \t\t\t\t\t\t\t\t\t\t \t\t\t\t\t*\n *\t\t\tUBYTE\tstartS\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tstartF\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t*\n *    \tUBYTE\tendM\t\t\t\t  \t\t\t\t\t\t\t\t\t\t \t\t\t\t\t*\n *\t\t\tUBYTE\tendS\t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tendF\t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tchan\t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                             \t\t\t\t\t\t\t*\n *\t\t\tUWORD\tTRUE if playing else FALSE                 \t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/27/1994 SW : Created.                                              *\n *=========================================================================*/\n\n\nUWORD  RedBookClass::CheckCDMusic(VOID)\n{\n\t\n\tStat.TrnsAdOff = offsetof\t(StatType, StatInfo);\n\tStat.TrnsAdSeg = Stat_addrp.seg;\n\n//\tWriteRealMem(REALPTR(Stat_addrp) << 16, &Stat, sizeof(StatType));\n\tMem_Copy ( &Stat , (void *) ( Stat_addrp.seg << 4 ) , sizeof(StatType));\n\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = offsetof (StatType, Length);\n\tregs.x.eax = 0x1510;\n\tsregs.es \t= Stat_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs, &sregs);\n\n//\tReadRealMem(&Stat, REALPTR(Stat_addrp) << 16, sizeof(StatType));\n\tMem_Copy ( (void *) ( Stat_addrp.seg << 4 ) , &Stat, sizeof(StatType));\n\n\treturn (Stat.Status&0x200);\n}\n\n/***************************************************************************\n * STOPCDMUSIC -- stop CD playing                                          *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone\t\t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/27/1994  SW : Created.                                             *\n *=========================================================================*/\n\nVOID  RedBookClass::StopCDMusic(VOID)\n{\n\n//\tWriteRealMem(REALPTR(Stop_addrp) << 16, &Stop, sizeof(StopType));\n\tMem_Copy ( &Stop , (void *) ( Stop_addrp.seg << 4 ) , sizeof(StopType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = offsetof (StopType, Length);\n\tsregs.es \t= Stop_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs, &sregs);\n\n//\tReadRealMem(&Stop, REALPTR(Stop_addrp) << 16, sizeof(StopType));\n\tMem_Copy ( (void *) ( Stop_addrp.seg << 4 ) , &Stop, sizeof(StopType));\n\n}\n\n"
  },
  {
    "path": "WIN32LIB/PROFILE/APROFILE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Profiler                                 *\n;*                                                                         *\n;*                    File Name : APROFILE.ASM                             *\n;*                                                                         *\n;*                   Programmer : Steve Tall\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : November 17th, 1995\t\t\t   *\n;*                                                                         *\n;*                  Last Update : November 20th, 1995   [ST]               *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   __PRO -- must be called at the beginning of each function             *\n;*   __EPI -- must be called at the end of each function\t           *\n;*   Copy_CHL -- initialise the profiler asm data                          *\n;*   Profiler_Callback -- windows callback for millisecond timer           *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\n\n\t\tp386\n\t\tmodel\tflat\n\t\tideal\n\t\tjumps\n\n\nMAX_PROFILE_TIME = 60*1\t\t;1 minute(s)\nPROFILE_RATE\t = 1000\t\t;1000 samples per sec\n\n\n;\n; Externs\n;\n;\nglobal\t\tC ProfileFunctionAddress:dword\nglobal\t\tC ProfilePtr:dword\nglobal\t\tC ProfileList:dword\nglobal\t\tC Stop_Profiler:near\nglobal\t\tNew_Profiler_Callback_:near\nglobal\t\tOld_Profiler_Callback_:near\nglobal\t\tC Profile_Init:near\nglobal\t\tC Profile_End:near\nglobal\t\t___begtext:near\nglobal\t\tBaseAddress:dword\nglobal\t\t__PRO:near\nglobal\t\t__EPI:near\nglobal\t\tMyStack:dword\nglobal\t\tMyStackPtr:dword\nglobal\t\tProAddress:dword\nglobal\t\tEpiAddress:dword\n\n\n\t\tcodeseg\n\n\n;*********************************************************************************************\n;* __PRO -- registers the current procedure                                                  *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      none                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*  Assumes that ss:Esp points to return address in function to be registered                *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   11/20/95 4:39PM ST : Created.                                                           *\n;*===========================================================================================*\n\nproc\t\t__PRO near\n\n\t\tjmp\t[ProAddress]\n; safe version of prologue code\nPro_Start:\tpush\teax\n\t\tmov\teax,[MyStackPtr]\n\t\tpush\t[ProfileFunctionAddress]\n\t\tpop\t[eax*4+MyStack]\n\t\tinc\t[MyStackPtr]\n\t\tpop\teax\n\t\tpush\t[dword ss:esp]\n\t\tpop\t[ProfileFunctionAddress]\nPro_End:\tret\n\n; unsafe (but much faster) prologue code\n;\t\tpop\t[ProfileFunctionAddress]\n;\t\tjmp\t[ProfileFunctionAddress]\n\nendp\t\t__PRO\n\n\n;*********************************************************************************************\n;* __EPI -- Registers the privious procedure as current again                                *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      none                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*  Assumes that calling procedure will pop ebp immediately on return so we dont have to     *\n;*  preserve it.                                                                             *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   11/20/95 4:42PM ST : Created.                                                           *\n;*===========================================================================================*\n\nproc\t\t__EPI near\n\n\t\tjmp\t[EpiAddress]\n; Safe version of epilogue code. Uncomment the push and pop for ultimate safety\nEpi_Start:\tdec\t[MyStackPtr]\n;\t\tpush\tebp\n\t\tmov\tebp,[MyStackPtr]\n\t\tmov\tebp,[ebp*4+MyStack]\n\t\tmov\t[ProfileFunctionAddress],ebp\n;\t\tpop\tebp\nEpi_End:\tret\n\n; Unsafe (but much faster) epilogue code. Makes lots of assumptions.\n;\t\tpush\t[dword esp+8]\n;\t\tpop\t[ProfileFunctionAddress]\n;\t\tret\n\nendp\t\t__EPI\n\n\n\n;*********************************************************************************************\n;* Profile_Init -- Initialises the .asm data required for profile session                    *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      none                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*   Assumes that '___begtext' is the first label in the code segment and that its           *\n;*   address is within 15 bytes of the start of the code segment                             *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   11/20/95 4:44PM ST : Created.                                                           *\n;*===========================================================================================*\n\nproc\t\tProfile_Init C near\n\n\t\tmov\teax,offset ___begtext\n\t\tand\teax,0fffffff0h\n\t\tmov\t[BaseAddress],eax\n\t\t;mov\t[MyStackPtr],0\n\t\tmov\t[ProfileList],PROFILE_RATE\n\t\tmov\t[ProfilePtr],1\n\t\tmov\t[ProAddress],offset Pro_Start\n\t\tmov\t[EpiAddress],offset Epi_Start\n\t\tret\n\nendp\t\tProfile_Init\n\n\n\n\n\n;*********************************************************************************************\n;* Profile_End -- disables the __PRO and __EPI procedures                                    *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      none                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   11/20/95 4:44PM ST : Created.                                                           *\n;*===========================================================================================*\n\nproc\t\tProfile_End C near\n\n\t\tmov\t[ProAddress],offset Pro_End\n\t\tmov\t[EpiAddress],offset Epi_End\n\t\tret\n\nendp\t\tProfile_End\n\n\n\n\n\n\n;*********************************************************************************************\n;* New_Profiler_Callback -- Windows callback used to register function hits                  *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      none                                                                         *\n;*                                                                                           *\n;* Note:                                                                                     *\n;*   The frequency that this is called depends on MAX_PROFILE_RATE defined here and in       *\n;*   profile.h                                                                               *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   11/20/95 4:47PM ST : Created.                                                           *\n;*===========================================================================================*\nproc\t\tNew_Profiler_Callback_ near\n\n\t\tpush\teax\n\t\tpush\tesi\n\t\tmov\tesi,[ProfilePtr]\n\t\tcmp\tesi,MAX_PROFILE_TIME*PROFILE_RATE\n\t\tjge\t@@out\n\t\tmov\teax,[ProfileFunctionAddress]\n\t\tsub\teax,[BaseAddress]\n\t\tmov\t[ProfileList+esi*4],eax\n\t\tinc\t[ProfilePtr]\n\t\tpop\tesi\n\t\tpop\teax\n\t\tret\n\n@@out:\t\tcall\tStop_Profiler\n\t\tpop\tesi\n\t\tpop\teax\n\t\tret\n\nendp\t\tNew_Profiler_Callback_\n\n\n\n;*********************************************************************************************\n;* Old_Profiler_Callback -- Windows callback used to register function hits                  *\n;*                                                                                           *\n;* INPUT:\tWindows timer callback stuff - not used                                      *\n;*                                                                                           *\n;* OUTPUT:      none                                                                         *\n;*                                                                                           *\n;* Note:                                                                                     *\n;*   The frequency that this is called depends on MAX_PROFILE_RATE defined here and in       *\n;*   profile.h                                                                               *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   11/20/95 4:47PM ST : Created.                                                           *\n;*===========================================================================================*\n\nproc\t\tOld_Profiler_Callback_ near\n\n\t\tpush\teax\n\t\tpush\tesi\n\t\tmov\tesi,[ProfilePtr]\n\t\tcmp\tesi,MAX_PROFILE_TIME*PROFILE_RATE\n\t\tjge\t@@out\n\t\tmov\teax,[ProfileFunctionAddress]\n\t\tsub\teax,[BaseAddress]\n\t\tmov\t[ProfileList+esi*4],eax\n\t\tinc\t[ProfilePtr]\n\t\tpop\tesi\n\t\tpop\teax\n\t\tret\t14h\n\n@@out:\t\tcall\tStop_Profiler\n\t\tpop\tesi\n\t\tpop\teax\n\t\tret\t14h\n\nendp\t\tOld_Profiler_Callback_\n\n\n\n\t\tdataseg\n\t\talign\t4\n\nProfileFunctionAddress\tdd\t0\t\t;Ptr to function we are currently in\nBaseAddress\t\tdd\t0\t\t;Address of the code segment start\nMyStackPtr\t\tdd\t0\t\t;offset into my stack table\nProAddress\t\tdd\tPro_Start\t;jmp ptr for __PRO procedure\nEpiAddress\t\tdd\tEpi_Start\t;jmp ptr for __EPI procedure\n\nlabel MyStack dword\t\t\t;my stack table\n\t\t\tdd\t16*1024 dup (?)\n\nend\n"
  },
  {
    "path": "WIN32LIB/PROFILE/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = profile\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n        wprofile.obj     &\n\taprofile.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WWLIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\n#**************************** End of makefile ******************************\n"
  },
  {
    "path": "WIN32LIB/PROFILE/PROFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Library profiler                                             *\n *                                                                                             *\n *                    File Name : PROFILE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 11/17/95                                                     *\n *                                                                                             *\n *                  Last Update : November 20th 1995 [ST]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *  The profiler works by using the function prologue and epilogue hooks available in Watcom                                                                                           *\n *  to register the current functions address in a global variable and then sampling the                                                                                           *\n *  contents of the variable using a windows timer which runs at up to 1000 samples per second.                                                                       *\n *                                                                                             *\n *  Compile the code to be sampled with the -ep and -ee flags to enable the prologue (__PRO)                                                                                           *\n *  and epilogue (__EPI) calls to be generated.                                                                                           *\n *  At the beginning of the section to be profiled (just before main loop normally) call the                                                                                           *\n *  Start_Profiler function to start sampling. At the end of the section, call Stop_Profiler                                                                                           *\n *  which will stop the timer and write the profile data to disk in the PROFILE.BIN file.                                                                                           *\n *  Use                                                                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *  Start_Profiler -- initialises the profiler data and starts gathering data                  *\n *  Stop_Profiler -- stops the timer and writes the profile data to disk                       *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#define WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#include <windows.h>\n#include <windowsx.h>\n\n#include <wwstd.h>\n#include <rawfile.h>\n#include <file.h>\n#include \"profile.h\"\n\nextern \"C\"{\nunsigned\tProfileList\t[PROFILE_RATE*60*MAX_PROFILE_TIME];\nunsigned\tProfilePtr;\n}\n\nextern \"C\" void Profiler_Callback ( UINT, UINT , DWORD, DWORD, DWORD );\n\nunsigned\tProfilerEvent;\n\nvoid Start_Profiler (void)\n{\n\tmemset (&ProfileList[0],-1,PROFILE_RATE*60*MAX_PROFILE_TIME*4);\n\tCopy_CHK();\n\tProfilerEvent = timeSetEvent (1000/PROFILE_RATE , 1 , (void CALLBACK (UINT,UINT,DWORD,DWORD,DWORD))Profiler_Callback , 0 , TIME_PERIODIC);\n}\n\nvoid Stop_Profiler (void)\n{\n\tif (ProfilerEvent){\n\t\ttimeKillEvent(ProfilerEvent);\n\t\tProfilerEvent=NULL;\n\n\t\tint handle = Open_File ( \"profile.bin\" , WRITE );\n\t\tif (handle != WW_ERROR){\n\t\t\tWrite_File (handle , &ProfileList[0] , ProfilePtr*4);\n\t\t\tClose_File (handle);\n\t\t}\n\t}\n}\n\n\n"
  },
  {
    "path": "WIN32LIB/PROFILE/PROFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Library profiler                                             *\n *                                                                                             *\n *                    File Name : PROFILE.H                                                    *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 11/17/95                                                     *\n *                                                                                             *\n *                  Last Update : November 20th 1995 [ST]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *                                                                                             *\n *  New System                                                                                 *\n * ~~~~~~~~~~~                                                                                 *\n *                                                                                             *\n *  The new profiler system creates a seperate thread and then starts a timer off there. The   *\n *  timer in the second thread uses GetThreadContext to sample the IP address of each user     *\n *  thread. This system has the advantage of being able to sample what is happening in all the *\n *  threads we own not just the main thread. Another advantage is that it doesnt require a     *\n *  major recompilation.                                                                       *\n *  The disadvantage is that we dont really know what is going on when the IP is outside the   *\n *  scope of our threads - We could be in direct draw, direct sound or even something like the *\n *  VMM and there is no way to tell.                                                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n *  Old System                                                                                 *\n * ~~~~~~~~~~~                                                                                 *\n *                                                                                             *\n *  The profiler works by using the function prologue and epilogue hooks available in Watcom   *\n *  to register the current functions address in a global variable and then sampling the       *\n *  contents of the variable using a windows timer which runs at up to 1000 samples per second.*\n *                                                                                             *\n *  Compile the code to be sampled with the -ep and -ee flags to enable the prologue (__PRO)   *\n *  and epilogue (__EPI) calls to be generated.                                                *\n *  At the beginning of the section to be profiled (just before main loop normally) call the   *\n *  Start_Profiler function to start sampling. At the end of the section, call Stop_Profiler   *\n *  which will stop the timer and write the profile data to disk in the PROFILE.BIN file.      *\n *                                                                                             *\n *  Use PROFILE.EXE to view the results of the session.                                        *\n *                                                                                             *\n *  The addition of prologue and epilogue code will slow down the product and the profiler     *\n *  allocates a huge buffer for data so it should not be linked in unless it is going to be    *\n *  used.                                                                                      *\n *                                                                                             *\n *  The advantage of the prologue/epilogue approach is that all samples represent valid        *\n *  addresses within our code so we get valid results we can use even when the IP is in system *\n *  code.                                                                                      *\n *                                                                                             *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#define\tMAX_PROFILE_TIME\t60*1\t\t//1 minute(s) @ 14.4 Mb per hour\n#define\tPROFILE_RATE\t\t1000\t//samples per sec (max 1000)\n\n\n/*\n * Defines for choosing between the old and new profiler system\n *\n*/\n\n#define\tOLD_PROFILE_SYSTEM\t1\n#define\tNEW_PROFILE_SYSTEM\t2\n\n//#define\tPROFILE_SYSTEM\t\t\tOLD_PROFILE_SYSTEM\n#define\tPROFILE_SYSTEM\t\t\tNEW_PROFILE_SYSTEM\n\n\n\nextern \"C\"{\n\tvoid __cdecl Profile_Init(void);\n\tvoid __cdecl Profile_End(void);\n\tvoid __cdecl Start_Profiler(void);\n\tvoid __cdecl Stop_Profiler(void);\n}\n\n"
  },
  {
    "path": "WIN32LIB/PROFILE/PROFILE.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\n;USE_PROFILER\t=1\n\n\nmacro\tprologue\nIfdef USE_PROFILER\n\t\tglobal\t__PRO:near\n\n\t\tcall\t\t__PRO\nendif ;USE_PROFILER\nendm\n\n\n\nmacro epilogue\nifdef USE_PROFILER\n\t\tglobal\t__EPI:near\n\n\t\tpush\t\tebp\n\t\tcall\t\t__EPI\n\t\tpop\t\t\tebp\nendif ;USE_PROFILER\nendm\n\n\n\n"
  },
  {
    "path": "WIN32LIB/PROFILE/UTIL/PROFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Library profiler                                             *\n *                                                                                             *\n *                    File Name : PROFILE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 11/17/95                                                     *\n *                                                                                             *\n *                  Last Update : November 20th 1995 [ST]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *   Uses a map file to match addresses of functions in the sample file with their names       *\n *                                                                                             *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *  Start_Profiler -- initialises the profiler data and starts gathering data                  *\n *  Stop_Profiler -- stops the timer and writes the profile data to disk                       *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include <string.h>\n#include <stdio.h>\n#include <sys\\types.h>\n#include <sys\\stat.h>\n#include <fcntl.h>\n#include <malloc.h>\n#include <io.h>\n#include <conio.h>\n\n#define bool int\n#define true 1\n#define false 0\n#define NAME_TABLE_SIZE 1000000\t\t\t\t\t//Storage space for function names\n#define SAMPLE_START 1\t\t\t\t\t\t\t\t//Offset (in dwords) of sample data in sample file\n\n\n/*\n** Function prototypes\n*/\nvoid Print_My_Name(void);\nvoid Print_Usage(void);\nint\t Load_File(char *file_name , unsigned *file_ptr , unsigned mode);\nbool Extract_Function_Addresses(void);\nunsigned Get_Hex (char string[] , int length);\nchar *Search_For_Char (char character , char buffer_ptr[] , int buffer_length);\nchar *Search_For_String (char *string , char *buffer_ptr , int buffer_length);\nvoid Map_Profiler_Hits (void);\nvoid Sort_Functions(void);\nvoid Sort_Functions_Again(void);\nvoid Output_Profile(void);\n\nchar\t\t*SampleFile;\t\t\t\t\t\t\t\t//Ptr to sample file name\nchar\t\t*MapFile;\t\t\t\t\t\t\t\t\t//Ptr to map file name\nunsigned\t*SampleFileBuffer;\t\t\t\t\t\t//Ptr to buffer that sample file is loaded in to\nchar\t\t*MapFileBuffer;\t\t\t\t\t\t\t//Ptr to buffer that map file is loaded in to\nunsigned\tSampleFileLength;\t\t\t\t\t\t\t//Length of sample file\nunsigned\tMapFileLength;\t\t\t\t\t\t\t\t//Length of map file\nchar\t\tFunctionNames[NAME_TABLE_SIZE];\t\t//Buffer to store function names in\nchar\t\t*FunctionNamePtr=&FunctionNames[0];\t//Ptr to end of last function name in buffer\nint\t\t\tTotalFunctions;\t\t\t\t\t\t\t//Total number of functions extracted from map file\nint\t\t\tSampleRate;\t\t\t\t\t\t\t\t\t//Number of samples/sec that data was collected at\nunsigned\tEndCodeSegment;\t\t\t\t\t\t\t//Length of the sampled programs code segments\n\n/*\n** Structure for collating function data\n*/\ntypedef struct tFunction {\n\tunsigned\tFunctionAddress;\t\t\t\t\t\t//Address of function relative to start of code seg\n\tchar\t\t*FunctionName;\t\t\t\t\t\t\t//Ptr to name of function in FunctionNames buffer\n\tint\t\tHits;\t\t\t\t\t\t\t\t\t\t//Number of times function was 'hit' when sampling\n} Function;\n\nFunction\tFunctionList[10000];\t\t\t\t\t\t//max 10,000 functions in map file.\n\n\n\n\n/***********************************************************************************************\n * main -- program entry point                                                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    argc , argv                                                                       *\n *                                                                                             *\n * OUTPUT:   0                                                                                 *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:21PM ST : Created                                                             *\n *=============================================================================================*/\n\nint main(int argc, char *argv[])\n\n{\n\tPrint_My_Name();\t\t\t\t\t\t\t\t// print the programs name\n\n\n\t/*\n\t** If the arguments dont make sense then print the usage\n\t*/\n\tif (argc!=3 ||\n\t\t\t!strcmpi(argv[1],\"/?\") ||\n\t\t\t!strcmpi(argv[1],\"/h\") ||\n\t\t\t!strcmpi(argv[1],\"/help\") ||\n\t\t\t!strcmpi(argv[1],\"-?\") ||\n\t\t\t!strcmpi(argv[1],\"-h\") ||\n\t\t\t!strcmpi(argv[1],\"-help\") ||\n\t\t\t!strcmpi(argv[1],\"?\") ||\n\t\t\t!strcmpi(argv[1],\"h\") ||\n\t\t\t!strcmpi(argv[1],\"help\")){\n\t\tPrint_Usage();\n\t\treturn(0);\n\t}\n\n\t/*\n\t** Get the names of the files to load\n\t*/\n\tSampleFile=argv[1];\n\tMapFile=argv[2];\n\n\t/*\n\t** Load the profile sample file\n\t*/\n\tSampleFileLength = Load_File (SampleFile , (unsigned*)&SampleFileBuffer , O_BINARY);\n\tif (!SampleFileLength) return(0);\n\n\t/*\n\t** The sample rate is the 1st dword in the file\n\t*/\n\tSampleRate=*SampleFileBuffer;\n\n\t/*\n\t** Load the .map file\n\t*/\n\tMapFileLength = Load_File (MapFile , (unsigned*)&MapFileBuffer , O_BINARY);\n\tif (!MapFileLength){\n\t\tfree (SampleFileBuffer);\n\t\treturn(0);\n\t}\n\n\t/*\n\t** Get the function names from the map file\n\t*/\n\tcprintf (\"Extracting function data from map file.\\n\");\n\tif (!Extract_Function_Addresses()){\n\t\tcprintf (\"Error parsing .MAP file - aborting\\n\\n\");\n\t\treturn (0);\n\t}\n\n\t/*\n\t** Sort the functions into address order to make it easier to map the functions\n\t*/\n\tcprintf (\"Sorting function list by address\");\n\tSort_Functions();\n\n\t/*\n\t** Map the addresses in the sample file to the function addresses\n\t*/\n\tcprintf (\"\\nMapping profiler hits to functions\");\n\tMap_Profiler_Hits();\n\n\t/*\n\t** Sort the functions into order of usage for output\n\t*/\n\tcprintf (\"\\nSorting function list by activity\");\n\tSort_Functions_Again();\n\tcprintf (\"\\n\\n\");\n\n\t/*\n\t** Print the function usage statistics\n\t*/\n\tOutput_Profile();\n\n\t/*\n\t** Cleanup and out\n\t*/\n\tfree (SampleFileBuffer);\n\tfree (MapFileBuffer);\n\treturn(0);\n}\n\n\n\n/***********************************************************************************************\n * Print_My_Name -- print the programs name and version                                        *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:25PM ST : Created                                                             *\n *=============================================================================================*/\n\nvoid Print_My_Name(void)\n{\n\tcprintf(\"Westwood profile data analyzer.\\n\");\n\tcprintf(\"V 1.0 - 11/17/95\\n\");\n\tcprintf(\"Programmer - Steve Tall.\\n\\n\");\n}\n\n\n/***********************************************************************************************\n * Print_Usage -- print the instructions                                                       *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:26PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Print_Usage (void)\n{\n\tcprintf(\"Usage: PROFILE <sample_file> <map_file)\\n\\n\");\n}\n\n\n/***********************************************************************************************\n * File_Error -- display a file error message                                                  *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    name of file error occurred on                                                    *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:26PM ST : Created                                                             *\n *=============================================================================================*/\n\nvoid File_Error (char *file_name)\n{\n\tcprintf (\"Error reading file:%s - aborting\\n\",file_name);\n}\n\n\n/***********************************************************************************************\n * Memory_Error -- display an out of memory message                                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:27PM ST : Created                                                             *\n *=============================================================================================*/\n\nvoid Memory_Error (void)\n{\n\tcprintf (\"Error - insufficient memory - aborting\\n\");\n}\n\n\n/***********************************************************************************************\n * Load_File -- load an entire file into memory                                                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    File name                                                                         *\n *           address to load at                                                                *\n *           read mode (text or binary)                                                        *\n *                                                                                             *\n * OUTPUT:   number of bytes read                                                              *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:27PM ST : Created                                                             *\n *=============================================================================================*/\n\nint Load_File(char *file_name , unsigned *load_addr , unsigned mode)\n{\n\tint\t\thandle;\n\tunsigned file_length;\n\tvoid\t\t*buffer;\n\n\thandle=open (file_name , O_RDONLY | mode);\n\n\tif (handle==-1){\n\t\tFile_Error(file_name);\n\t\treturn (false);\n\t}\n\n\tfile_length = filelength(handle);\n\n\tif (file_length==-1) return (false);\n\n\tbuffer = malloc (file_length+10);\n\n\tif (!buffer){\n\t\tMemory_Error();\n\t\treturn (false);\n\t}\n\n\tif (read (handle , buffer , file_length)!=file_length){\n\t\tFile_Error(file_name);\n\t\tfree(buffer);\n\t\treturn (false);\n\t}\n\n\tclose (handle);\n\t*load_addr = (unsigned)buffer;\n\treturn (file_length);\n}\n\n\n\n\n\n\n/***********************************************************************************************\n * Map_Profiler_Hits -- map function hits from sample file to functions in map file            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: Map file functions must be sorted into address order 1st                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:28PM ST : Created                                                             *\n *=============================================================================================*/\n\nvoid Map_Profiler_Hits (void)\n{\n\tunsigned\t*samples=(unsigned*)SampleFileBuffer;\n\tunsigned\tfunction_hit;\n\n\tfor (int i=SAMPLE_START ; i<SampleFileLength/4 ; i++){\n\n\t\tfunction_hit=*(samples+i);\n\t\tif (1023==(1023 & i)){\n\t\t\tcprintf (\".\");\n\t\t}\n\n\n\t\tfor (int j=TotalFunctions-1 ; j>=0 ; j--){\n\t\t\tif (FunctionList[j].FunctionAddress < function_hit){\n\t\t\t\tFunctionList[j].Hits++;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n}\n\n\n/***********************************************************************************************\n * Sort_Functions -- hideous bubble sort of functions into address order                       *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:29PM ST : Created                                                             *\n *=============================================================================================*/\n\nvoid Sort_Functions (void)\n{\n\tFunction\taddress_swap;\n\n\tif (TotalFunctions>1){\n\n\t\tfor (int outer=0 ; outer <TotalFunctions ; outer++){\n\n\t\t\taddress_swap.FunctionAddress=0;\n\n\t\t\tif (127==(127 & outer)){\n\t\t\t\tcprintf (\".\");\n\t\t\t}\n\n\t\t\tfor (int inner=0 ; inner < TotalFunctions-1 ; inner++){\n\n\t\t\t\tif (FunctionList[inner].FunctionAddress > FunctionList[inner+1].FunctionAddress ){\n\n\t\t\t\t\tmemcpy (&address_swap , &FunctionList[inner] , sizeof(Function));\n\t\t\t\t\tmemcpy (&FunctionList[inner] , &FunctionList[inner+1] , sizeof(Function));\n\t\t\t\t\tmemcpy (&FunctionList[inner+1] , &address_swap , sizeof(Function));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!address_swap.FunctionAddress) break;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Sort_Functions -- hideous bubble sort of functions into usage order                         *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:29PM ST : Created                                                             *\n *=============================================================================================*/\n\nvoid Sort_Functions_Again (void)\n{\n\tFunction\taddress_swap;\n\n\tif (TotalFunctions>1){\n\n\t\tfor (int outer=0 ; outer <TotalFunctions ; outer++){\n\n\t\t\taddress_swap.FunctionAddress=0;\n\n\t\t\tif (127==(127 & outer)){\n\t\t\t\tcprintf (\".\");\n\t\t\t}\n\n\t\t\tfor (int inner=0 ; inner < TotalFunctions-1 ; inner++){\n\n\t\t\t\tif (FunctionList[inner].Hits < FunctionList[inner+1].Hits ){\n\n\t\t\t\t\tmemcpy (&address_swap , &FunctionList[inner] , sizeof(Function));\n\t\t\t\t\tmemcpy (&FunctionList[inner] , &FunctionList[inner+1] , sizeof(Function));\n\t\t\t\t\tmemcpy (&FunctionList[inner+1] , &address_swap , sizeof(Function));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!address_swap.FunctionAddress) break;\n\t\t}\n\t}\n}\n\n\n\n\n/***********************************************************************************************\n * Output_Profile -- output the function data to the screen                                    *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:31PM ST : Created                                                             *\n *=============================================================================================*/\n\nvoid Output_Profile(void)\n{\n\tdouble\t\t\tperiod=(((double)SampleFileLength/(double)4) - (double)SAMPLE_START) / (double)SampleRate;\n\tdouble\t\t\tpercentage;\n\n\tprintf ( \"\\n  Profile information from %s and %s.\\n\\n\",SampleFile,MapFile);\n\n\tprintf ( \"Samples collected:%d\\n\" , SampleFileLength/4-SAMPLE_START);\n\tprintf ( \"Sample rate      :%d samples per second\\n\",SampleRate);\n\tprintf ( \"Sample period    :%f seconds\\n\\n\\n\" , period);\n\n\tprintf ( \"Hits   %%        Function\\n\");\n\tprintf ( \"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\\n\");\n\n\tfor (int i=0 ; i<TotalFunctions ; i++){\n\n\t\tif (FunctionList[i].Hits){\n\n\t\t\tpercentage= ((double)FunctionList[i].Hits*(double)100) / ((double)SampleFileLength/(double)4-(double)SAMPLE_START);\n\n\t\t\tprintf (\"%-6d %-3.3f%% %s\\n\",FunctionList[i].Hits , percentage , FunctionList[i].FunctionName);\n\t\t}\n\n\t}\n}\n\n\n\n\n/***********************************************************************************************\n * Extract_Function_Addresses -- gets the addresses of all global functions from a map file    *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: true if successfully extracted                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:31PM ST : Created                                                             *\n *=============================================================================================*/\n\nbool Extract_Function_Addresses(void)\n{\n\tchar\t\t*map_ptr;\n\tchar\t\t*segment_ptr;\n\tchar\t\t*end_str_ptr;\n\tunsigned\tchars_left=MapFileLength;\n\tint\t\tfunction_name_length;\n\tunsigned\tend_of_last_code_segment;\n\tunsigned\tcode_segment_start;\n\tunsigned\tcode_segment_size;\n\tchar\t\tunknown[]={\"Windows API or system code.\"};\n\n\t/*\n\t** Clear out the list of functions\n\t*/\n\tmemset (&FunctionNames[0] , 0 , NAME_TABLE_SIZE);\n\n\t/*\n\t** Search for the 'Segments' header in the memory map\n\t*/\n\tsegment_ptr = Search_For_String (\"Segments\" , MapFileBuffer , chars_left);\n\tif (!segment_ptr) return (false);\n\tchars_left = MapFileLength - ( (unsigned)segment_ptr - (unsigned)MapFileBuffer );\n\tsegment_ptr = Search_For_String (\"+-----\" , segment_ptr , chars_left);\n\tsegment_ptr +=2;\n\tchars_left = MapFileLength - ( (unsigned)segment_ptr - (unsigned)MapFileBuffer );\n\n\t/*\n\t** Get the length of the segment section by searching for the start of the next section\n\t*/\n\tend_str_ptr = Search_For_String (\"+-----\" , segment_ptr , chars_left);\n\tif (end_str_ptr){\n\t\tchars_left = end_str_ptr - segment_ptr;\n\t} else {\n\t\treturn (false);\n\t}\n\n\tEndCodeSegment = 0;\n\n\t/*\n\t** Find the end of the last code segment\n\t*/\n\tdo {\n\t\t/*\n\t\t** Search for a code segment identifier\n\t\t*/\n\t\tchars_left = end_str_ptr - segment_ptr;\n\t\tsegment_ptr = Search_For_String (\"CODE\" , segment_ptr , chars_left);\n\t\tif (!segment_ptr) break;\t\t//No more code segments so break\n\n\t\t/*\n\t\t**  Search for the segment address which should always be 0001\n\t\t*/\n\t\tchars_left = end_str_ptr - segment_ptr;\n\t\tsegment_ptr = Search_For_String (\"0001:\" , segment_ptr , chars_left);\n\t\tif (!segment_ptr) return (false);\t//Couldnt find the segment address - must be a problem so abort\n\n\t\t/*\n\t\t** Get the start address and length of the segment\n\t\t*/\n\t\tcode_segment_start = Get_Hex(segment_ptr+5,8);\n\t\tcode_segment_size = Get_Hex(segment_ptr+16,8);\n\n\t\t/*\n\t\t** If this segment ends higher in memory than the previous highest then\n\t\t** we have a new last segment\n\t\t*/\n\t\tif (code_segment_start+code_segment_size > EndCodeSegment){\n\t\t\tEndCodeSegment = code_segment_start+code_segment_size;\n\t\t}\n\n\t\tchars_left = end_str_ptr - segment_ptr;\n\t\tsegment_ptr = Search_For_Char ( 13 , segment_ptr , chars_left );\n\t\tchars_left = end_str_ptr - segment_ptr;\n\n\t} while (chars_left > 0);\n\n\n\n\tchars_left=MapFileLength;\n\t/*\n\t** Search for the 'Memory Map' segment of the map file\n\t*/\n\tmap_ptr = Search_For_String (\"Memory Map\" , MapFileBuffer , chars_left);\n\tif (!map_ptr){\n\t\treturn (false);\n\t}\n\tchars_left = MapFileLength - ( (unsigned)map_ptr - (unsigned)MapFileBuffer );\n\n\t/*\n\t** Get the length of the memory map segment by searching for the start of the next segment\n\t*/\n\tend_str_ptr = Search_For_String (\"+-----\" , map_ptr , chars_left);\n\tif (end_str_ptr){\n\t\tMapFileLength = ((unsigned)MapFileBuffer + MapFileLength) - (unsigned)end_str_ptr;\n\t}\n\tchars_left = MapFileLength - ( (unsigned)map_ptr - (unsigned)MapFileBuffer );\n\n\t/*\n\t** Reset the total number of functions found\n\t*/\n\tTotalFunctions = 0;\n\n\t/*\n\t**\n\t** Find each occurrence of 0001: as all the functions we want are in the 1st segment\n\t**\n\t*/\n\tdo {\n\t\t/*\n\t\t**  Find '0001:'\n\t\t*/\n\t\tmap_ptr = Search_For_String (\"0001:\" , map_ptr , chars_left);\n\t\tif (!map_ptr){\n\t\t\tbreak;\n\t\t}\n\t\tchars_left = MapFileLength - ( (unsigned)map_ptr - (unsigned)MapFileBuffer );\n\n\t\t/*\n\t\t** Skip the '0001:' portion of the address and get the hext offset of the function\n\t\t*/\n\t\tmap_ptr+=5;\n\t\tFunctionList[TotalFunctions].FunctionAddress=Get_Hex(map_ptr,8);\n\n\t\t/*\n\t\t** Skip to the function name and get its length by searching for the end of the line\n\t\t*/\n\t\tmap_ptr+=10;\n\t\tchars_left = MapFileLength - ( (unsigned)map_ptr - (unsigned)MapFileBuffer );\n\t\tend_str_ptr = Search_For_Char (13 , map_ptr , chars_left);\n\t\tif (!end_str_ptr){\n\t\t\tbreak;\n\t\t}\n\t\tfunction_name_length = (unsigned)end_str_ptr - (unsigned)map_ptr;\n\n\t\t/*\n\t\t** Copy the function name into the name list and keep a pointer to it\n\t\t*/\n\t\tmemcpy (FunctionNamePtr , map_ptr , function_name_length);\n\t\tFunctionList[TotalFunctions].FunctionName = FunctionNamePtr;\n\t\tFunctionNamePtr += function_name_length+1;\t\t//Leave an extra 0 on the end as a terminator\n\t\tFunctionList[TotalFunctions].Hits = 0;\t\t\t\t//We dont yet know how many times we hit it\n\t\tTotalFunctions++;\n\n\t} while (1);\n\n\n\t/*\n\t** Add in a dummy function at the highest address to represent unknown code hits\n\t*/\n\tFunctionList[TotalFunctions].FunctionAddress = EndCodeSegment;\n\tmemcpy (FunctionNamePtr , &unknown , sizeof (unknown));\n\tFunctionList[TotalFunctions].FunctionName = FunctionNamePtr;\n\tFunctionNamePtr += sizeof (unknown);\n\tFunctionList[TotalFunctions].Hits = 0;\n\tTotalFunctions++;\n\n\treturn (true);\n}\n\n\n\n\n/***********************************************************************************************\n * Get_Hex -- nasty function to convert an ascii hex number to an unsigned int                 *\n *            I'm sure there must be a lovely 'c' way of doing this but I dont know what it is *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to ascii hex string , number of digits in string                              *\n *                                                                                             *\n * OUTPUT:   value of hex string                                                               *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:39PM ST : Created                                                             *\n *=============================================================================================*/\n\nunsigned Get_Hex (char string[] , int length)\n{\n\tunsigned\thex_val=0;\n\tint\t\tmultiplier=1;\n\tchar\t\thex_char;\n\n\tfor (int i=0 ; i<length ; i++){\n\t\thex_char=string[length-1-i];\n\n\t\tswitch (hex_char){\n\t\t\tcase  '0':\n\t\t\t\thex_char=0;\n\t\t\t\tbreak;\n\n\t\t\tcase  '1':\n\t\t\t\thex_char=1;\n\t\t\t\tbreak;\n\n\t\t\tcase  '2':\n\t\t\t\thex_char=2;\n\t\t\t\tbreak;\n\n\t\t\tcase  '3':\n\t\t\t\thex_char=3;\n\t\t\t\tbreak;\n\n\t\t\tcase  '4':\n\t\t\t\thex_char=4;\n\t\t\t\tbreak;\n\n\t\t\tcase  '5':\n\t\t\t\thex_char=5;\n\t\t\t\tbreak;\n\n\t\t\tcase  '6':\n\t\t\t\thex_char=6;\n\t\t\t\tbreak;\n\n\t\t\tcase  '7':\n\t\t\t\thex_char=7;\n\t\t\t\tbreak;\n\n\t\t\tcase  '8':\n\t\t\t\thex_char=8;\n\t\t\t\tbreak;\n\n\t\t\tcase  '9':\n\t\t\t\thex_char=9;\n\t\t\t\tbreak;\n\n\t\t\tcase  'A':\n\t\t\t\thex_char=10;\n\t\t\t\tbreak;\n\n\t\t\tcase  'B':\n\t\t\t\thex_char=11;\n\t\t\t\tbreak;\n\n\t\t\tcase  'C':\n\t\t\t\thex_char=12;\n\t\t\t\tbreak;\n\n\t\t\tcase  'D':\n\t\t\t\thex_char=13;\n\t\t\t\tbreak;\n\n\t\t\tcase  'E':\n\t\t\t\thex_char=14;\n\t\t\t\tbreak;\n\n\t\t\tcase  'F':\n\t\t\t\thex_char=15;\n\t\t\t\tbreak;\n\n\t\t\tcase  'a':\n\t\t\t\thex_char=10;\n\t\t\t\tbreak;\n\n\t\t\tcase  'b':\n\t\t\t\thex_char=11;\n\t\t\t\tbreak;\n\n\t\t\tcase  'c':\n\t\t\t\thex_char=12;\n\t\t\t\tbreak;\n\n\t\t\tcase  'd':\n\t\t\t\thex_char=13;\n\t\t\t\tbreak;\n\n\t\t\tcase  'e':\n\t\t\t\thex_char=14;\n\t\t\t\tbreak;\n\n\t\t\tcase  'f':\n\t\t\t\thex_char=15;\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\thex_val += hex_char * multiplier;\n\t\tmultiplier = multiplier<<4;\n\t}\n\treturn (hex_val);\n}\n\n\n\n/***********************************************************************************************\n * Search_For_Char -- search through ascii data for a particular character                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    character                                                                         *\n *           ptr to buffer                                                                     *\n *           length of buffer                                                                  *\n *                                                                                             *\n * OUTPUT:   ptr to char in buffer or NULL if not found                                        *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:41PM ST : Created                                                             *\n *=============================================================================================*/\n\nchar *Search_For_Char (char character , char buffer_ptr[] , int buffer_length)\n{\n\n\tfor ( unsigned i=0 ; i<buffer_length ; i++){\n\n\t\tif (buffer_ptr[i]==character){\n\t\t\treturn ((char*) (unsigned)buffer_ptr+i);\n\t\t}\n\t}\n\treturn (NULL);\n}\n\n\n\n/***********************************************************************************************\n * Search_For_String -- search for a string of chars within a buffer                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    string                                                                            *\n *           ptr to buffer to search in                                                        *\n *           length of buffer                                                                  *\n *                                                                                             *\n * OUTPUT:   ptr to string in buffer or NULL if not found                                      *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:42PM ST : Created                                                             *\n *=============================================================================================*/\n\nchar *Search_For_String (char *string , char *buffer_ptr , int buffer_length)\n{\n\tint\tj;\n\tint\tstring_length=strlen(string);\n\n\tfor (int i=0 ; i<buffer_length-string_length ; i++){\n\n\t\tfor (j=0 ; j<string_length ; j++){\n\t\t\tif ( *(string+j) != *(buffer_ptr+i+j)) break;\n\t\t}\n\t\tif (j==string_length) return buffer_ptr+i;\n\t}\n\n\treturn (NULL);\n\n}\n\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/PROFILE/WPROFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Library profiler                                             *\n *                                                                                             *\n *                    File Name : WPROFILE.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 11/17/95                                                     *\n *                                                                                             *\n *                  Last Update : November 20th 1995 [ST]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *                                                                                             *\n *  New System                                                                                 *\n * ~~~~~~~~~~~                                                                                 *\n *                                                                                             *\n *  The new profiler system creates a seperate thread and then starts a timer off there. The   *\n *  timer in the second thread uses GetThreadContext to sample the IP address of each user     *\n *  thread. This system has the advantage of being able to sample what is happening in all the *\n *  threads we own not just the main thread. Another advantage is that it doesnt require a     *\n *  major recompilation.                                                                       *\n *  The disadvantage is that we dont really know what is going on when the IP is outside the   *\n *  scope of our threads - We could be in direct draw, direct sound or even something like the *\n *  VMM and there is no way to tell.                                                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n *  Old System                                                                                 *\n * ~~~~~~~~~~~                                                                                 *\n *                                                                                             *\n *  The profiler works by using the function prologue and epilogue hooks available in Watcom   *\n *  to register the current functions address in a global variable and then sampling the       *\n *  contents of the variable using a windows timer which runs at up to 1000 samples per second.*\n *                                                                                             *\n *  Compile the code to be sampled with the -ep and -ee flags to enable the prologue (__PRO)   *\n *  and epilogue (__EPI) calls to be generated.                                                *\n *  At the beginning of the section to be profiled (just before main loop normally) call the   *\n *  Start_Profiler function to start sampling. At the end of the section, call Stop_Profiler   *\n *  which will stop the timer and write the profile data to disk in the PROFILE.BIN file.      *\n *                                                                                             *\n *  Use PROFILE.EXE to view the results of the session.                                        *\n *                                                                                             *\n *  The addition of prologue and epilogue code will slow down the product and the profiler     *\n *  allocates a huge buffer for data so it should not be linked in unless it is going to be    *\n *  used.                                                                                      *\n *                                                                                             *\n *  The advantage of the prologue/epilogue approach is that all samples represent valid        *\n *  addresses within our code so we get valid results we can use even when the IP is in system *\n *  code.                                                                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *  Start_Profiler -- initialises the profiler data and starts gathering data                  *\n *  Stop_Profiler -- stops the timer and writes the profile data to disk                       *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#define WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#include <windows.h>\n#include <windowsx.h>\n#include <wwstd.h>\n#include <rawfile.h>\n#include <file.h>\n#include \"profile.h\"\n#include <vdmdbg.h>\n#include <timer.h>\n\n#define PROFILE\n\nextern \"C\"{\n#ifdef PROFILE\nunsigned\tProfileList\t[PROFILE_RATE*MAX_PROFILE_TIME];\n#else\nunsigned\tProfileList\t[2];\n#endif\nunsigned\tProfilePtr;\n}\n\nextern \"C\" void Old_Profiler_Callback ( UINT, UINT , DWORD, DWORD, DWORD );\nextern \"C\" void New_Profiler_Callback (void);\nextern \"C\" {\n\textern unsigned ProfileFunctionAddress;\n}\n\nunsigned long\tProfilerEvent;\t\t//Handle for profiler callback\nunsigned long\tProfilerThread;\t//Handle for profiler thread\n\n\nHANDLE\t\tCCThreadHandle;\nCONTEXT\tThreadContext;\n\n\n#if (PROFILE_SYSTEM == NEW_PROFILE_SYSTEM)\n\n/***********************************************************************************************\n * Thread_Callback -- gets the IP address of our thread and registers it                       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Windows timer callback parms - not used                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/2/96 6:37AM ST : Created                                                               *\n *=============================================================================================*/\n\nvoid CALLBACK Thread_Callback (UINT,UINT,DWORD,DWORD,DWORD)\n{\n\tThreadContext.ContextFlags = VDMCONTEXT_CONTROL;\n\tif (!InTimerCallback){\n\t\tGetThreadContext ( CCThreadHandle , &ThreadContext );\n\t}else{\n\t\tGetThreadContext (TimerThreadHandle , &ThreadContext);\n\t}\n\n\tProfileFunctionAddress = ThreadContext.Eip;\n\tNew_Profiler_Callback();\n}\n\n\n/***********************************************************************************************\n * Profile_Thread -- this is the thread our profiler runs in. It just starts off a timer and   *\n *                   then buggers off into an infinite message loop. We shouldnt get messages  *\n *                   here as this isnt our primary thread                                      *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/2/96 6:39AM ST : Created                                                               *\n *=============================================================================================*/\nvoid Profile_Thread (void)\n{\n\tMSG msg;\n\tProfilerEvent = timeSetEvent (1000/PROFILE_RATE , 1 , Thread_Callback , 0 , TIME_PERIODIC);\n\t//ProfilerEvent = timeSetEvent (100 , 1 , Thread_Callback , 0 , TIME_ONESHOT);\n\tdo  {\n\t\tGetMessage(&msg,NULL,0,0);\n\t} while(1);\n}\n\n#endif //(PROFILE_SYSTEM == OLD_PROFILE_SYSTEM)\n\n\n/***********************************************************************************************\n * Start_Profiler -- initialises the profiler system and starts sampling                       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: There may be a pause when sampling starts as Win95 does some VMM stuff            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:12PM ST : Created                                                             *\n *=============================================================================================*/\n\nvoid __cdecl Start_Profiler (void)\n{\n#ifdef PROFILE\n\tif (!ProfilerEvent){\n\t\tmemset (&ProfileList[0],-1,PROFILE_RATE*MAX_PROFILE_TIME*4);\n\t}\n\n\tProfile_Init();\n\n\tif (!ProfilerEvent){\n\n#if (PROFILE_SYSTEM == OLD_PROFILE_SYSTEM)\n\t\t/*\n\t\t** Old profile system - just set up a timer to monitor the global variable based on\n\t\t** the last place __PRO was called from\n\t\t*/\n\t\tProfilerEvent = timeSetEvent (1000/PROFILE_RATE , 1 , (void CALLBACK (UINT,UINT,DWORD,DWORD,DWORD))Old_Profiler_Callback , 0 , TIME_PERIODIC);\n#else\n\t\t/*\n\t\t** New profile system - create a second thread that will do all the profiling\n\t\t** using GetThreadContext\n\t\t*/\n\t\tif ( DuplicateHandle( GetCurrentProcess(), GetCurrentThread() , GetCurrentProcess() ,&CCThreadHandle , 0 , TRUE , DUPLICATE_SAME_ACCESS) ){\n\t\t\tProfilerEvent= (unsigned)CreateThread(NULL,2048,(LPTHREAD_START_ROUTINE)&Profile_Thread,NULL,0,&ProfilerThread);\n\t\t}\n#endif\n\n\t}\n\n#else\n\tProfilerEvent = 0;\n#endif\n\n}\n\n\n\n/***********************************************************************************************\n * Stop_Profiler -- stops the sampling timer and writes the colledted data to disk             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: Writes to file PROFILE.BIN                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:13PM ST : Created                                                             *\n *=============================================================================================*/\n\nvoid __cdecl Stop_Profiler (void)\n{\n\tif (ProfilerEvent){\n\n#if (PROFILE_SYSTEM == OLD_PROFILE_SYSTEM)\n\t\t//\n\t\t// Old system - just remove the timer event\n\t\t//\n\t\ttimeKillEvent(ProfilerEvent);\n#else\n\t\t//\n\t\t// New system - kill the profiling thread\n\t\t//\n\t\tTerminateThread((HANDLE)ProfilerThread,0);\n#endif\n\n\t\tProfilerEvent=NULL;\n\n\t\tProfile_End();\n\n\t\tint handle = Open_File ( \"profile.bin\" , WRITE );\n\t\tif (handle != WW_ERROR){\n\t\t\tWrite_File (handle , &ProfileList[0] , ProfilePtr*4);\n\t\t\tClose_File (handle);\n\t\t}\n\t}\n}\n\n\n"
  },
  {
    "path": "WIN32LIB/PROJECT.CFG",
    "content": ".SILENT\n.OPTIMIZE\n.ERASE\n#***************************************************************************\n# development configuration switches\n#CC_CFG         = -bt=nt /i=$(%WIN32LIB)\\include -W3 -d2 -orilt /4 -s -j -DNUMEGA=1\n#CC_CFG          = -bt=nt /i=$(%WIN32LIB)\\include -W3 -d2 -od /4 -s -j -DNUMEGA=1\nASM_CFG\t\t= /i. /i$(%WIN32LIB)\\include /zi /t /m /w+ /jJUMPS /ml\nLIB_CFG   \t= /b /n /n\nLINK_CFG  \t= debug codeview system nt_win option stack=64k  op map\n#ASM_CFG\t\t= /i. /i$(%WIN32LIB)\\include /zd /t /m /w+ /jJUMPS /ml\n#LIB_CFG   \t= /b /n /n\n#LINK_CFG  \t= option stack=32k debug all\n\n#***************************************************************************\n# Release configuration switches\n\nCC_CFG   = /i=$(%WIN32LIB)\\include /W3 /d1 /otxan /s /4 /j\n#ASM_CFG\t  = /i$(%WIN32LIB)\\include /zd /t /m /w+ /jJUMPS /ml\n#LIB_CFG   = /b /n /n\n#LINK_CFG  = option stack=32k debug all\n\n"
  },
  {
    "path": "WIN32LIB/RAWFILE/CCFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\ccfile.cpv   2.20   27 Sep 1995 12:45:16   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***             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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CCFILE.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : March 20, 1995 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CCFileClass::CCFileClass -- Default constructor for file object.                          *\n *   CCFileClass::CCFileClass -- Filename based constructor for C&C file.                      *\n *   CCFileClass::Close -- Closes the file.                                                    *\n *   CCFileClass::Is_Available -- Checks for existence of file on disk or in mixfile.          *\n *   CCFileClass::Is_Open -- Determines if the file is open.                                   *\n *   CCFileClass::Open -- Opens a file from either the mixfile system or the rawfile system.   *\n *   CCFileClass::Read -- Reads data from the file.                                            *\n *   CCFileClass::Seek -- Moves the current file pointer in the file.                          *\n *   CCFileClass::Size -- Determines the size of the file.                                     *\n *   CCFileClass::Write -- Writes data to the file (non mixfile files only).                   *\n *   CCFileClass::Error -- Handles displaying a file error message.                            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n#include\t<direct.h>\n#include\t<fcntl.h>\n#include\t<io.h>\n#include\t<dos.h>\n#include\t<errno.h>\n#include\t<share.h>\n#include\t\"ccfile.h\"\n\n\n/***********************************************************************************************\n * CCFileClass::Error -- Handles displaying a file error message.                              *\n *                                                                                             *\n *    Display an error message as indicated. If it is allowed to retry, then pressing a key    *\n *    will return from this function. Otherwise, it will exit the program with \"exit()\".       *\n *                                                                                             *\n * INPUT:   error    -- The error number (same as the DOSERR.H error numbers).                 *\n *                                                                                             *\n *          canretry -- Can this routine exit normally so that retrying can occur? If this is  *\n *                      false, then the program WILL exit in this routine.                     *\n *                                                                                             *\n *          filename -- Optional filename to report with this error. If no filename is         *\n *                      supplied, then no filename is listed in the error message.             *\n *                                                                                             *\n * OUTPUT:  none, but this routine might not return at all if the \"canretry\" parameter is      *\n *          false or the player pressed ESC.                                                   *\n *                                                                                             *\n * WARNINGS:   This routine may not return at all. It handles being in text mode as well as    *\n *             if in a graphic mode.                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CCFileClass::Error(int , int , char const * )\n{\n\tif (!Force_CD_Available(RequiredCD)) {\n\t\tProg_End();\n\t\texit(EXIT_FAILURE);\n\t}\n}\n\n\n/***********************************************************************************************\n * CCFileClass::CCFileClass -- Filename based constructor for C&C file.                        *\n *                                                                                             *\n *    Use this constructor for a file when the filename is known at construction time.         *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the filename to use for this file object.                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The filename pointer is presumed to be inviolate throughout the duration of     *\n *             the file object. If this is not guaranteed, then use the default constructor    *\n *             and then set the name manually.                                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCCFileClass::CCFileClass(char const *filename)\n{\n\tSet_Name(filename);\n\tFromDisk = false;\n\tPointer = 0;\n\tPosition = 0;\n\tLength = 0;\n\tStart = 0;\n}\n\n\n/***********************************************************************************************\n * CCFileClass::CCFileClass -- Default constructor for file object.                            *\n *                                                                                             *\n *    This is the default constructor for a C&C file object.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCCFileClass::CCFileClass(void) : CDFileClass()\n{\n\tFromDisk = false;\n\tPointer = 0;\n\tPosition = 0;\n\tLength = 0;\n\tStart = 0;\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Write -- Writes data to the file (non mixfile files only).                     *\n *                                                                                             *\n *    This routine will write data to the file, but NOT to a file that is part of a mixfile.   *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that holds the data to be written.               *\n *                                                                                             *\n *          size     -- The number of bytes to write.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually written.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCFileClass::Write(void const *buffer, long size)\n{\n\n\t/*\n\t**\tIf this is part of a mixfile, then writing is not allowed. Error out with a fatal\n\t**\tmessage.\n\t*/\n\tif (Pointer || FromDisk) {\n\t\tError(EACCES, false, File_Name());\n\t}\n\n\treturn(CDFileClass::Write(buffer, size));\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Read -- Reads data from the file.                                              *\n *                                                                                             *\n *    This routine determines if the file is part of the mixfile system. If it is, then        *\n *    the file is copied from RAM if it is located there. Otherwise it is read from disk       *\n *    according to the correct position of the file within the parent mixfile.                 *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer to place the read data.                          *\n *                                                                                             *\n *          size     -- The number of bytes to read.                                           *\n *                                                                                             *\n * OUTPUT:  Returns the actual number of bytes read (this could be less than requested).       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCFileClass::Read(void *buffer, long size)\n{\n\tint opened = false;\n\n\tif (!Is_Open()) {\n\t\tif (Open()) {\n\t\t\topened = true;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the file is part of a loaded mixfile, then a mere copy is\n\t**\tall that is required for the read.\n\t*/\n\tif (Pointer) {\n\t\tlong\tmaximum = Length - Position;\n\n\t\tsize = MIN(maximum, size);\n\t\tif (size) {\n\t\t\tMem_Copy(Add_Long_To_Pointer(Pointer, Position), buffer, size);\n\t\t\tPosition += size;\n\t\t}\n\t\tif (opened) Close();\n\t\treturn(size);\n\t}\n\n\t/*\n\t**\tIf the file is part of a mixfile, but the mixfile is located\n\t**\ton disk, then a special read operation is necessary.\n\t*/\n\tif (FromDisk) {\n\t\tlong\tmaximum = Length - Position;\n\n\t\tsize = MIN(maximum, size);\n\t\tif (size > 0) {\n\t\t\tCDFileClass::Seek(Start + Position, SEEK_SET);\n\t\t\tsize = CDFileClass::Read(buffer, size);\n\t\t\tPosition += size;\n\t\t}\n\t\tif (opened) Close();\n\t\treturn(size);\n\t}\n\n\tlong s = CDFileClass::Read(buffer, size);\n\tif (opened) Close();\n\treturn(s);\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Seek -- Moves the current file pointer in the file.                            *\n *                                                                                             *\n *    This routine will change the current file pointer to the position specified. It follows  *\n *    the same rules the a normal Seek() does, but if the file is part of the mixfile system,  *\n *    then only the position value needs to be updated.                                        *\n *                                                                                             *\n * INPUT:   pos      -- The position to move the file to relative to the position indicated    *\n *                      by the \"dir\" parameter.                                                *\n *                                                                                             *\n *          dir      -- The direction to affect the position change against. This can be       *\n *                      either SEEK_CUR, SEEK_END, or SEEK_SET.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the position of the new location.                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCFileClass::Seek(long pos, int dir)\n{\n\tif (Pointer || FromDisk) {\n\t\tswitch (dir) {\n\t\t\tcase SEEK_END:\n\t\t\t\tPosition = Length;\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_SET:\n\t\t\t\tPosition = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_CUR:\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\tPosition += pos;\n\t\tif (Position < 0) Position = 0;\n\t\tif (Position > Length) Position = Length;\n\t\treturn(Position);\n\t}\n\treturn(CDFileClass::Seek(pos, dir));\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Size -- Determines the size of the file.                                       *\n *                                                                                             *\n *    If the file is part of the mixfile system, then the size of the file is already          *\n *    determined and available. Otherwise, go to the low level system to find the file         *\n *    size.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the size of the file in bytes.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCFileClass::Size(void)\n{\n\tif (Pointer || FromDisk) return(Length);\n\n\treturn(CDFileClass::Size());\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Is_Available -- Checks for existence of file on disk or in mixfile.            *\n *                                                                                             *\n *    This routine will examine the mixfile system looking for the file. If the file could     *\n *    not be found there, then the disk is examined directly.                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file available for opening?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CCFileClass::Is_Available(int )\n{\n\tif (MixFileClass::Offset(File_Name())) {\n\t\treturn(true);\n\t}\n\treturn(CDFileClass::Is_Available());\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Is_Open -- Determines if the file is open.                                     *\n *                                                                                             *\n *    A mixfile is open if there is a pointer to the mixfile data. In absence of this,         *\n *    the the file is open if the file handle is valid.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file open?                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CCFileClass::Is_Open(void) const\n{\n\n\t/*\n\t**\tIf the file is part of a cached file, then return that it is opened. A closed file\n\t**\tdoesn't have a valid pointer.\n\t*/\n\tif (Pointer) return(true);\n\treturn(CDFileClass::Is_Open());\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Close -- Closes the file.                                                      *\n *                                                                                             *\n *    If this is a mixfile file, then only the pointers need to be adjusted.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CCFileClass::Close(void)\n{\n\tFromDisk = false;\n\tPointer = 0;\n\tPosition = 0;\t\t\t\t// Starts at beginning offset.\n\tStart = 0;\n\tLength = 0;\n\tCDFileClass::Close();\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Open -- Opens a file from either the mixfile system or the rawfile system.     *\n *                                                                                             *\n *    This routine will open the specified file. It examines the mixfile system to find a      *\n *    match. If one is found then the file is \"opened\" in a special cached way. Otherwise      *\n *    it is opened as a standard DOS file.                                                     *\n *                                                                                             *\n * INPUT:   rights   -- The access rights desired.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened successfully?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CCFileClass::Open(int rights)\n{\n\t/*\n\t**\tAlways close the file if it was open.\n\t*/\n\tClose();\n\n\t/*\n\t**\tPerform a preliminary check to see if the specified file\n\t**\texists on the disk. If it does, then open this file regardless\n\t**\tof whether it also exists in RAM. This is slower, but allows\n\t**\tupgrade files to work.\n\t*/\n\tif ((rights & WRITE) || CDFileClass::Is_Available()) {\n\t\treturn(CDFileClass::Open(rights));\n\t}\n\n\t/*\n\t**\tCheck to see if file is part of a mixfile and that mixfile is currently loaded\n\t**\tinto RAM.\n\t*/\n\tMixFileClass *mixfile = 0;\n\tif (MixFileClass::Offset(File_Name(), &Pointer, &mixfile, &Start, &Length)) {\n\n\t\t/*\n\t\t**\tIf the mixfile is located on disk, then fake out the file system to read from\n\t\t**\tthe mixfile, but think it is reading from a solitary file.\n\t\t*/\n\t\tif (!Pointer) {\n\t\t\tlong\tstart = Start;\n\t\t\tlong\tlength = Length;\n\n\t\t\t/*\n\t\t\t**\tThis is a legitimate open to the file. All access to the file through this\n\t\t\t**\tfile object will be appropriately adjusted for mixfile support however. Also\n\t\t\t**\tnote that the filename attached to this object is NOT the same as the file\n\t\t\t**\tattached to the file handle.\n\t\t\t*/\n\t\t\tchar const * dupfile = strdup(File_Name());\n\t\t\tOpen(mixfile->Filename, READ);\n\t\t\tSearching(false);\t\t\t\t// Disable multi-drive search.\n\t\t\tSet_Name(dupfile);\n\t\t\tfree((void *)dupfile);\n\t\t\tStart = start;\n\t\t\tLength = length;\n\t\t\tFromDisk = true;\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tThe file cannot be found in any mixfile, so it must reside as\n\t\t** an individual file on the disk. Or else it is just plain missing.\n\t\t*/\n\t\treturn(CDFileClass::Open(rights));\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************\n** Backward compatibility section.\n*/\n//extern \"C\" {\n\nstatic CCFileClass Handles[10];\n\n#ifdef NEVER\nbool __cdecl Set_Search_Drives(BYTE const *)\n{\n\tCCFileClass::Set_Search_Path(path);\n\treturn(true);\n}\n#endif\n\nWORD __cdecl Open_File(BYTE const *file_name, WORD mode)\n{\n\tfor (int index = 0; index < sizeof(Handles)/sizeof(Handles[0]); index++) {\n\t\tif (!Handles[index].Is_Open()) {\n\t\t\tif (Handles[index].Open(file_name, mode)) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn(ERROR);\n}\n\nVOID __cdecl Close_File(WORD handle)\n{\n\tif (handle != ERROR && Handles[handle].Is_Open()) {\n\t\tHandles[handle].Close();\n\t}\n}\n\nLONG __cdecl Read_File(WORD handle, VOID *buf, ULONG bytes)\n{\n\tif (handle != ERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Read(buf, bytes));\n\t}\n\treturn(0);\n}\n\nLONG __cdecl Write_File(WORD handle, VOID const *buf, ULONG bytes)\n{\n\tif (handle != ERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Write(buf, bytes));\n\t}\n\treturn(0);\n}\n\nWORD __cdecl Find_File(BYTE const *file_name)\n{\n\tCCFileClass file(file_name);\n\treturn(file.Is_Available());\n}\n\n#ifdef NEVER\nWORD __cdecl Delete_File(BYTE const *file_name)\n{\n\treturn(CCFileClass(file_name).Delete());\n}\n\nWORD __cdecl Create_File(BYTE const *file_name)\n{\n\treturn(CCFileClass(file_name).Create());\n}\n\nULONG __cdecl Load_Data(BYTE const *name, VOID *ptr, ULONG size)\n{\n\treturn(CCFileClass(name).Read(ptr, size));\n}\n#endif\n\nVOID * __cdecl Load_Alloc_Data(BYTE const *name, WORD )\n{\n\tCCFileClass file(name);\n\n\treturn(Load_Alloc_Data(file));\n}\n\nULONG __cdecl File_Size(WORD handle)\n{\n\tif (handle != ERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Size());\n\t}\n\treturn(0);\n}\n\n#ifdef NEVER\nULONG __cdecl Write_Data(BYTE const *name, VOID const *ptr, ULONG size)\n{\n\treturn(CCFileClass(name).Write(ptr, size));\n}\n#endif\n\nULONG __cdecl Seek_File(WORD handle, LONG offset, WORD starting)\n{\n\tif (handle != ERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Seek(offset, starting));\n\t}\n\treturn(0);\n}\n\n#ifdef NEVER\nbool __cdecl Multi_Drive_Search(bool on)\n{\n//\treturn(CCFileClass::Multi_Drive_Search(on));\n\treturn(on);\n}\n\nVOID __cdecl WWDOS_Init(VOID)\n{\n}\n\nVOID __cdecl WWDOS_Shutdown(VOID)\n{\n}\n\nWORD __cdecl Find_Disk_Number(BYTE const *)\n{\n\treturn(0);\n}\n#endif\n\n//ULONG cdecl Load_Uncompress(BYTE const *file, BuffType uncomp_buff, BuffType dest_buff, VOID *reserved_data)\n//{\n//\treturn(Load_Uncompress(CCFileClass(file), uncomp_buff, dest_buff, reserved_data));\n//\treturn(CCFileClass(file).Load_Uncompress(uncomp_buff, dest_buff, reserved_data));\n//}\nextern \"C\" {\nint MaxDevice;\nint DefaultDrive;\nchar CallingDOSInt;\n\n}\n\n\nvoid Unfragment_File_Cache(void)\n{\n}\n\n\n"
  },
  {
    "path": "WIN32LIB/RAWFILE/FILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library - Filio header stuff.            *\n *                                                                         *\n *                    File Name : FILE.H                                 \t*\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : September 13, 1993                       *\n *                                                                         *\n *                  Last Update : April 11, 1994\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FILE_H\n#define FILE_H\n\n#ifndef FILETEMP_H\n// This should be removed once the library is all intacked.\n#include \"filetemp.h\"\n#endif\n\n/*=========================================================================*/\n/* File IO system defines and enumerations\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#define\tXMAXPATH\t80\n\n/*\n**\tThese are the Open_File, Read_File, and Seek_File constants.\n*/\n#ifndef READ\n#define READ\t\t\t\t\t\t1\t// Read access.\n#endif\n#ifndef WRITE\n#define WRITE\t\t\t\t\t\t2\t// Write access.\n#endif\n#ifndef SEEK_SET\n#define SEEK_SET\t\t\t\t\t0\t// Seek from start of file.\n#define SEEK_CUR\t\t\t\t\t1\t// Seek relative from current location.\n#define SEEK_END\t\t\t\t\t2\t// Seek from end of file.\n#endif\n\n\ntypedef enum {\n\tFILEB_PROCESSED=8,// Was the packed file header of this file processed?\n\tFILEB_PRELOAD,\t\t// Scan for and make file resident at WWDOS_Init time?\n\tFILEB_RESIDENT,\t// Make resident at Open_File time?\n\tFILEB_FLUSH,\t\t// Un-resident at Close_File time?\n\tFILEB_PACKED,\t\t// Is this file packed?\n\tFILEB_KEEP,\t\t\t// Don't ever flush this resident file?\n\tFILEB_PRIORITY,\t// Flush this file last?\n\n\tFILEB_LAST\n} FileFlags_Type;\n\n#define\tFILEF_NONE\t\t\t0\n#define\tFILEF_PROCESSED\t(1<<FILEB_PROCESSED)\n#define\tFILEF_PRELOAD\t\t(1<<FILEB_PRELOAD)\n#define\tFILEF_RESIDENT\t\t(1<<FILEB_RESIDENT)\n#define\tFILEF_FLUSH\t\t\t(1<<FILEB_FLUSH)\n#define\tFILEF_PACKED\t\t(1<<FILEB_PACKED)\n#define\tFILEF_KEEP\t\t\t(1<<FILEB_KEEP)\n#define\tFILEF_PRIORITY\t\t(1<<FILEB_PRIORITY)\n\n/*\n** These errors are returned by WWDOS_Init().  All errors encountered are\n** or'd together so there may be more then one error returned.  Not all\n** errors are fatal, such as the cache errors.\n*/\ntypedef enum {\n\tFI_SUCCESS\t\t\t\t\t\t= 0x00,\n\tFI_CACHE_TOO_BIG\t\t\t\t= 0x01,\n\tFI_CACHE_ALREADY_INIT\t\t= 0x02,\n\tFI_FILEDATA_FILE_NOT_FOUND\t= 0x04,\n\tFI_FILEDATA_TOO_BIG\t\t\t= 0x08,\n \tFI_SEARCH_PATH_NOT_FOUND\t= 0x10,\n \tFI_STARTUP_PATH_NOT_FOUND\t= 0x20,\n\tFI_NO_CACHE_FOR_PRELOAD\t\t= 0x40,\n\tFI_FILETABLE_NOT_INIT\t\t= 0x80,\n} FileInitErrorType;\n\n\n/*\n**\tThese are the errors that are detected by the File I/O system and\n**\tpassed to the io error routine.\n*/\n//lint -strong(AJX,FileErrorType)\ntypedef enum {\n\tCANT_CREATE_FILE,\n\tBAD_OPEN_MODE,\n\tCOULD_NOT_OPEN,\n\tTOO_MANY_FILES,\n\tCLOSING_NON_HANDLE,\n\tREADING_NON_HANDLE,\n\tWRITING_NON_HANDLE,\n\tSEEKING_NON_HANDLE,\n\tSEEKING_BAD_OFFSET,\n\tWRITING_RESIDENT,\n\tUNKNOWN_INDEX,\n\tDID_NOT_CLOSE,\n\tFATAL_ERROR,\n\tFILE_NOT_LISTED,\n\tFILE_LENGTH_MISMATCH,\n\tINTERNAL_ERROR,\n\tMAKE_RESIDENT_ZERO_SIZE,\n\tRESIDENT_SORT_FAILURE,\n\n\tNUMBER_OF_ERRORS\t\t\t\t/* MAKE SURE THIS IS THE LAST ENTRY */\n} FileErrorType;\n\n// This is here tempararaly until library is put together.\n//extern WORD __cdecl ( __cdecl IO_Error)(FileErrorType error, BYTE const *filename);\nextern short (*Open_Error)(FileErrorType, BYTE const *);\n\n/*=========================================================================*/\n/* File IO system structures\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//lint -strong(AJX,FileDataType)\ntypedef struct {\n\tchar\t*Name;\t\t// File name (include sub-directory but not volume).\n\tlong\tSize;\t\t\t// File size (0=indeterminate).\n\tvoid\t*Ptr;\t\t\t// Resident file pointer.\n\tlong\tStart;\t\t// Starting offset in DOS handle file.\n\tunsigned char\tDisk;\t\t\t// Disk number location.\n\tunsigned char\tOpenCount;\t// Count of open locks on resident file.\n\tunsigned short\tFlag;\t\t\t// File control flags.\n} FileDataType;\n\n\n/*=========================================================================*/\n/* FIle IO system globals.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n// These are cpp errors in funtions declarations\tJULIO JEREZ\n\n// extern FileDataType __cdecl FileData[];\n// extern BYTE __cdecl ExecPath[XMAXPATH + 1];\n// extern BYTE __cdecl DataPath[XMAXPATH + 1];\n// extern BYTE __cdecl StartPath[XMAXPATH + 1];\n// extern BOOL __cdecl UseCD;\n\n// The correct syntax is  NO TYPE MODIFIER APPLY TO DATA DECLARATIONS\nextern FileDataType FileData[];\nextern char ExecPath[XMAXPATH + 1];\nextern char DataPath[XMAXPATH + 1];\nextern char StartPath[XMAXPATH + 1];\nextern BOOL UseCD;\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILEINIT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid __cdecl WWDOS_Shutdown(void);\nFileInitErrorType __cdecl WWDOS_Init(unsigned long cachesize, char *filedata, char *cdpath);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILE.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Open_File(char const *file_name, int mode);\nvoid __cdecl Close_File(int handle);\nlong __cdecl Read_File(int handle, void *buf, unsigned long bytes);\nint __cdecl Load_File ( const char *file_name , void *load_addr);\nlong __cdecl Write_File(int handle, void const *buf, unsigned long bytes);\nunsigned long __cdecl Seek_File(int handle, long offset, int starting);\nint __cdecl File_Exists(char const *file_name);\nunsigned long __cdecl File_Size(int handle);\nBOOL __cdecl Is_Handle_Valid(int handle, FileErrorType error, char const *name);\nint __cdecl Open_File_With_Recovery( char const *file_name, unsigned int mode );\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILECACH.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid Unfragment_File_Cache(void);\nBOOL __cdecl Make_File_Resident(char const *filename);\nint __cdecl Flush_Unused_File_Cache(int flush_keeps);\nBOOL __cdecl Free_Resident_File(char const *file);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILECHNG.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Create_File(char const *file_name);\nint __cdecl Delete_File(char const *file_name);\nBOOL __cdecl Change_File_Size(int handle, unsigned long new_size);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILEINFO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Get_DOS_Handle(int fh);\nint __cdecl Free_Handles(void);\nint __cdecl Find_Disk_Number(char const *file_name);\nint __cdecl Set_File_Flags(char const *filename, int flags);\nint __cdecl Clear_File_Flags(char const *filename, int flags);\nint __cdecl Get_File_Flags(char const *filename);\nBOOL __cdecl Multi_Drive_Search(BOOL on);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FINDFILE.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint __cdecl Find_File(char const *file_name);\nint __cdecl Find_File_Index(char const *filename);\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FFIRST.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#include <dos.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern int __cdecl Find_First(unsigned char *fname, unsigned int mode, struct find_t *ffblk);\nextern int __cdecl Find_Next(struct find_t *ffblk);\n\n#ifdef __cplusplus\n}\n#endif\n\n\n\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/RAWFILE/FILETEMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Temp header for file routines.           *\n *                                                                         *\n *                    File Name : FILETEMP.H                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 20, 1994                           *\n *                                                                         *\n *                  Last Update : April 20, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FILETEMP_H\n#define FILETEMP_H\n\n/////////////////////////////////////////////////////////////////////\n// THIS DOES NOT BELONG HERE.  IT WAS PUT HERE JUST TO GET THE THING\n// TO COMPILE.  ONCE THE BUFFER AND PAGE SYSTEMS ARE PUT IN, THESE\n// WILL NEED TO BE TAKEN OUT AND MODS MADE TO ANY FUNCTION USING BuffType.\n// SKB 4/20/94.\n\n\n\n/*=========================================================================*/\n/* Defines and such that must go into wwstd.h\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n// Look at FileErrorType below for the IO_Error function.\n//extern WORD __cdecl ( __cdecl IO_Error)(FileErrorType error, BYTE const *filename);\nVOID __cdecl Prog_End(VOID);\nextern WORD Hard_Error_Occured;\n\n\n\n//////////////////////// END OF DON'T BELONG //////////////////////////////////\n\n#endif //FILETEMP_H\n\n"
  },
  {
    "path": "WIN32LIB/RAWFILE/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = rawfile\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t\t&\n   rawfile.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WWLIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/RAWFILE/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = rawfile\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t   rawfile.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) \n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n -+rawfile\n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/RAWFILE/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = rawfile\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t\t&\n   rawfile.obj\t\t\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WWLIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include \n\t copy *.inc $(%WIN32LIB)\\include \n\t copy *.cpp $(%WIN32LIB)\\srcdebug \n\t copy *.asm $(%WIN32LIB)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/RAWFILE/RAWFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\rawfile.cpv   2.17   06 Sep 1995 16:38:30   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***             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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Library                                             *\n *                                                                                             *\n *                    File Name : RAWFILE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 18, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RawFileClass::Close -- Perform a closure of the file.                                     *\n *   RawFileClass::Create -- Creates an empty file.                                            *\n *   RawFileClass::Delete -- Deletes the file object from the disk.                            *\n *   RawFileClass::Error -- Handles displaying a file error message.                           *\n *   RawFileClass::Is_Available -- Checks to see if the specified file is available to open.   *\n *   RawFileClass::Open -- Assigns name and opens file in one operation.                       *\n *   RawFileClass::Open -- Opens the file object with the rights specified.                    *\n *   RawFileClass::RawFileClass -- Simple constructor for a file object.                       *\n *   RawFileClass::Read -- Reads the specified number of bytes into a memory buffer.           *\n *   RawFileClass::Seek -- Reposition the file pointer as indicated.                           *\n *   RawFileClass::Set_Name -- Manually sets the name for a file object.                       *\n *   RawFileClass::Size -- Determines size of file (in bytes).                                 *\n *   RawFileClass::Write -- Writes the specified data to the buffer specified.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n #define\ttrue\t1\n #define\tfalse\t0\n\n#define\tWIN32\n#define\t_WIN32\n#include \t<windows.h>\n\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<string.h>\n#include\t<direct.h>\n#include\t<fcntl.h>\n#include\t<io.h>\n#include\t<dos.h>\n#include\t<share.h>\n#include\t<sys\\stat.h>\n#include\t<wwstd.h>\n\n//#include \"wwlib32.h\"\n//#include\t\"compat.h\"\n#include\t\"rawfile.h\"\n\n\n/***********************************************************************************************\n * RawFileClass::Error -- Handles displaying a file error message.                             *\n *                                                                                             *\n *    Display an error message as indicated. If it is allowed to retry, then pressing a key    *\n *    will return from this function. Otherwise, it will exit the program with \"exit()\".       *\n *                                                                                             *\n * INPUT:   error    -- The error number (same as the DOSERR.H error numbers).                 *\n *                                                                                             *\n *          canretry -- Can this routine exit normally so that retrying can occur? If this is  *\n *                      false, then the program WILL exit in this routine.                     *\n *                                                                                             *\n *          filename -- Optional filename to report with this error. If no filename is         *\n *                      supplied, then no filename is listed in the error message.             *\n *                                                                                             *\n * OUTPUT:  none, but this routine might not return at all if the \"canretry\" parameter is      *\n *          false or the player pressed ESC.                                                   *\n *                                                                                             *\n * WARNINGS:   This routine may not return at all. It handles being in text mode as well as    *\n *             if in a graphic mode.                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\n#pragma argsused\n//void RawFileClass::Error(int error, int canretry, char const * filename)\nvoid RawFileClass::Error(int error, int , char const *)\n{\n\tchar buffer[256];\n\n\twsprintf(buffer, \"File Error #%d\", error);\n///////\tMessageBox(NULL, buffer, \"Error\", MB_OK);\n\n#ifdef NEVER\n\tchar\tmessage[256];\t\t\t\t// Staging buffer for error message string.\n\n\t/*\n\t**\tBuild the complete text of the error message. This text is used in either the graphic\n\t**\tmode or the text mode version.\n\t*/\n#ifdef GERMAN\n\tstrcpy(message, \"DATEIFEHLER\");\n#else\n#ifdef FRENCH\n\tstrcpy(message, \"ERREUR DE FICHIER\");\n#else\n\tstrcpy(message, \"FILE ERROR\");\n#endif\n#endif\n\tif (filename) {\n\t\tstrcat(message, \"(\");\n\t\tstrcat(message, filename);\n\t\tstrcat(message, \")\");\n\t}\n\tstrcat(message, \": \");\n//BG: Borland only\tstrcat(message, _sys_errlist[error]);\n\tstrcat(message, strerror(error) );\n\tstrcat(message, \". \");\n\n\t/*\n\t**\tIf it can't properly handle displaying the error message in the\n\t**\tcurrent graphic mode, then this forces the error to become non\n\t**\trecoverable. Go into text mode and proceed.\n\t*/\n\tif (!FontPtr && GraphicMode != TXT_MODE) {\n\t\tSet_Video_Mode(RESET_MODE);\n\t\tcanretry = false;\n\t\tGraphicMode = TXT_MODE;\n\t}\n\n\t/*\n\t**\tAdd the text explaining the valid actions to take.\n\t*/\n\tif (canretry) {\n\t\tif (GraphicMode == TXT_MODE) strcat(message, \"\\n\");\n#ifdef GERMAN\n\t\tstrcat(message, \" Beliebige Taste drcken fr erneuten Versuch.\");\n\t\tif (GraphicMode == TXT_MODE) strcat(message, \"\\n\");\n\t\tstrcat(message, \" <ESC> drcken, um das Programm zu verlassen.\");\n#else\n#ifdef FRENCH\n\t\tstrcat(message, \" Appuyez sur une touche pour recommencer.\");\n\t\tif (GraphicMode == TXT_MODE) strcat(message, \"\\n\");\n\t\tstrcat(message, \" Appuyez sur Echap pour quitter le programme.\");\n#else\n\t\tstrcat(message, \" Press any key to retry.\");\n\t\tif (GraphicMode == TXT_MODE) strcat(message, \"\\n\");\n\t\tstrcat(message, \" Press <ESC> to exit program.\");\n#endif\n#endif\n\t\tif (GraphicMode == TXT_MODE) strcat(message, \"\\n\");\n\t} else {\n\t\tif (GraphicMode == TXT_MODE) strcat(message, \"\\n\");\n#ifdef GERMAN\n\t\tstrcat(message, \" Beliebige Taste drcken, um das Programm zu verlassen.\");\n#else\n#ifdef FRENCH\n\t\tstrcat(message, \" Appuyez sur une touche pour quitter le programme.\");\n#else\n\t\tstrcat(message, \" Press any key to exit program.\");\n#endif\n#endif\n\t\tif (GraphicMode == TXT_MODE) strcat(message, \"\\n\");\n\t}\n\n\t/*\n\t**\tIn text mode, the error handler is very simple. It just prints the error message\n\t**\tto the screen and waits for a response.\n\t*/\n\tif (GraphicMode == TXT_MODE) {\n\t\tint\tinput;\n\n\t\t/*\n\t\t**\tDisplay the error message and wait for a response.\n\t\t*/\n\t\tprintf(message);\n\t\tKeyboard::Clear();\n\t\tinput = Keyboard::Get();\n\n\t\t/*\n\t\t**\tCheck for input. If the ESC key was pressed or if retrying is not allowed,\n\t\t**\tthen exit the program. Otherwise, return from this routine for a retry\n\t\t**\tattempt.\n\t\t*/\n\t\tif (input == KN_ESC || !canretry) {\n\t\t\tProg_End();\n\t\t\texit(EXIT_FAILURE);\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tThe graphic mode version of the error handler will display a simple message\n\t\t**\tbox on the screen. If the palette is black at this point, then the error will\n\t\t**\tbe invisible. For more thorough and pleasing results, you should replace this\n\t\t**\tvirtual function with one of your own, that is more aware of the environment\n\t\t**\tin which is exists.\n\t\t*/\n\t\tvoid\t\t\t*background;\t\t// Pointer to background saving buffer.\n\t\tGraphicBufferClass * \toldpage;\t\t\t\t// Copy of old logic page.\n\t\tint\t\t\toldwindow;\t\t\t// Copy of old window number.\n\t\tvoid const\t*oldfont;\t\t\t// Copy of old font pointer.\n\t\tint\t\t\toldspacing;\t\t\t// Old font X spacing.\n\n\t\t/*\n\t\t**\tSetup display in preparation for printing the error message.\n\t\t*/\n\t\toldpage = Set_Logic_Page(SeenBuff);\n\t\toldwindow = Change_Window(ErrorWindow);\n\t\toldfont = Set_Font(FontPtr);\n\t\toldspacing = FontXSpacing; FontXSpacing = 0;\n\t\tHide_Mouse();\n\n\t\t/*\n\t\t**\tTry to allocate a storage buffer for the background to the\n\t\t**\terror window.\n\t\t*/\n\t\tbackground = new char [Size_Of_Region(WinW<<3, WinH)];\n\n\t\t/*\n\t\t**\tIf there is memory for the background storage, then save the\n\t\t**\tscreen image area to that buffer.\n\t\t*/\n\t\tif (background) {\n\t\t\tSeenPage.To_Buffer(WinX<<3, WinY, WinW<<3, WinH, background, Size_Of_Region(WinW<<3, WinH));\n\t\t}\n\n\t\t/*\n\t\t**\tDraw a rudimentary box.\n\t\t*/\n\t\tNew_Window();\n\t\tLogicPage->Draw_Rect(WinX<<3, WinY, (WinX+WinW)<<3, WinY+WinH, WinC);\n\n\t\t/*\n\t\t** shrinks window down one byte in all directions.\n\t\t*/\n\t\tWindowList[Window][WINDOWX] += 1;\n\t\tWindowList[Window][WINDOWY] += 1<<3;\n\t\tWindowList[Window][WINDOWWIDTH] -= 1<<1;\n\t\tWindowList[Window][WINDOWHEIGHT] -= 1<<4;\n\t\tChange_Window(Window);\n\t\tWinCx = WinCy = 0;\n\n\t\tWindow_Print(message);\n\t\tKeyboard::Clear();\n\n\t\t/*\n\t\t**\tCheck for input. If the ESC key was pressed or if retrying is not allowed,\n\t\t**\tthen exit the program. Otherwise, return from this routine for a retry\n\t\t**\tattempt.\n\t\t*/\n\t\tint input = Keyboard::Get();\n\t\tif (input == KN_ESC || !canretry) {\n\t\t\tProg_End();\n\t\t\texit(EXIT_FAILURE);\n\t\t}\n\n\t\t/*\n\t\t**\tRestore the window back to its original size.\n\t\t*/\n\t\tWindowList[Window][WINDOWX] -= 1;\n\t\tWindowList[Window][WINDOWY] -= 1<<3;\n\t\tWindowList[Window][WINDOWWIDTH] += 1<<1;\n\t\tWindowList[Window][WINDOWHEIGHT] += 1<<4;\n\t\tChange_Window(Window);\n\t\tWinCx = WinCy = 0;\n\n\t\t/*\n\t\t**\tIf the background was saved off, then restore it.\n\t\t*/\n\t\tif (background) {\n\t\t\tBuffer_To_Page(WinX<<3, WinY, WinW<<3, WinH, background, SeenPage);\n\t\t\tdelete [] background;\n\t\t}\n\n\t\t/*\n\t\t**\tRestore the system global settings to original values.\n\t\t*/\n\t\tShow_Mouse();\n\t\tChange_Window(oldwindow);\n\t\tSet_Font(oldfont);\n\t\tSet_Logic_Page(oldpage);\n\t\tFontXSpacing = oldspacing;\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * RawFileClass::RawFileClass -- Simple constructor for a file object.                         *\n *                                                                                             *\n *    This constructor is called when a file object is created with a supplied filename, but   *\n *    not opened at the same time. In this case, an assumption is made that the supplied       *\n *    filename is a constant string. A duplicate of the filename string is not created since   *\n *    it would be wasteful in that case.                                                       *\n *                                                                                             *\n * INPUT:   filename -- The filename to assign to this file object.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nRawFileClass::RawFileClass(char const *filename) : Filename(filename)\n{\n\tHandle = -1;\n\tAllocated = false;\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Set_Name -- Manually sets the name for a file object.                         *\n *                                                                                             *\n *    This routine will set the name for the file object to the name specified. This name is   *\n *    duplicated in free store. This allows the supplied name to be a temporarily constructed  *\n *    text string. Setting the name in this fashion doesn't affect the closed or opened state  *\n *    of the file.                                                                             *\n *                                                                                             *\n * INPUT:   filename -- The filename to assign to this file object.                            *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocated copy of this filename. This pointer is     *\n *          guaranteed to remain valid for the duration of this file object or until the name  *\n *          is changed -- whichever is sooner.                                                 *\n *                                                                                             *\n * WARNINGS:   Because of the allocation this routine must perform, memory could become        *\n *             fragmented.                                                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * RawFileClass::Set_Name(char const *filename)\n{\n\tif (Filename && Allocated) {\n// Heap_Dump_Check( \"Before raw free\" );\n\t\tfree((char *)Filename);\n// Heap_Dump_Check( \"After raw free\" );\n\t\t((char *&)Filename) = 0;\n\t\tAllocated = false;\n\t}\n\n\tif (!filename) return(NULL);\n\n// Heap_Dump_Check( \"Before raw strdup\" );\n\t((char *&)Filename) = strdup(filename);\n// Heap_Dump_Check( \"After raw strdup\" );\n\tif (!Filename) {\n\t\tError(ENOMEM, false, filename);\n\t}\n\tAllocated = true;\n\treturn(Filename);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Open -- Assigns name and opens file in one operation.                         *\n *                                                                                             *\n *    This routine will assign the specified filename to the file object and open it at the    *\n *    same time. If the file object was already open, then it will be closed first. If the     *\n *    file object was previously assigned a filename, then it will be replaced with the new    *\n *    name. Typically, this routine is used when an anonymous file object has been crated and  *\n *    now it needs to be assigned a name and opened.                                           *\n *                                                                                             *\n * INPUT:   filename -- The filename to assign to this file object.                            *\n *                                                                                             *\n *          rights   -- The open file access rights to use.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened? The return value of this is moot, since the open file   *\n *          is designed to never return unless it succeeded.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Open(char const *filename, int rights)\n{\n\tSet_Name(filename);\n\treturn(Open(rights));\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Open -- Opens the file object with the rights specified.                      *\n *                                                                                             *\n *    This routine is used to open the specified file object with the access rights indicated. *\n *    This only works if the file has already been assigned a filename. It is guaranteed, by   *\n *    the error handler, that this routine will always return with success.                    *\n *                                                                                             *\n * INPUT:   rights   -- The file access rights to use when opening this file. This is a        *\n *                      combination of READ and/or WRITE bit flags.                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened successfully? This will always return true by reason of  *\n *          the error handler.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Open(int rights)\n{\n\tClose();\n\n\t/*\n\t**\tVerify that there is a filename associated with this file object. If not, then this is a\n\t**\tbig error condition.\n\t*/\n\tif (!Filename) {\n\t\tError(ENOENT, false);\n\t}\n\n\t/*\n\t**\tRecord the access rights used for this open call. These rights will be used if the\n\t**\tfile object is duplicated.\n\t*/\n\tRights = rights;\n\n\t/*\n\t**\tRepetatively try to open the file. Abort if a fatal error condition occurs.\n\t*/\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tTry to open the file according to the access rights specified.\n\t\t*/\n//\t\tHard_Error_Occured = 0;\n\t\tswitch (rights) {\n\n\t\t\t/*\n\t\t\t**\tIf the access rights are not recognized, then report this as\n\t\t\t**\tan invalid access code.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\terrno = EINVAL;\n\t\t\t\tbreak;\n\n\t\t\tcase READ:\n\t\t\t\tHandle = (int)mmioOpen((char*)Filename, NULL, MMIO_READ);\n\t\t\t\t//Handle = open(Filename, O_RDONLY|O_BINARY);\n\t\t\t\tbreak;\n\n\t\t\tcase WRITE:\n\t\t\t\tHandle = (int)mmioOpen((char*)Filename, NULL, MMIO_WRITE | MMIO_CREATE);\n\t\t\t\t//Handle = open(Filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY , S_IWRITE);\n\t\t\t\tbreak;\n\n\t\t\tcase READ|WRITE:\n\t\t\t\tHandle = (int)mmioOpen((char*)Filename, NULL, MMIO_READWRITE);\n\t\t\t\t//Handle = open(Filename, O_RDWR|O_CREAT|O_BINARY);\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tIf the handle indicates the file is not open, then this is an error condition.\n\t\t**\tFor the case of the file cannot be found, then allow a retry. All other cases\n\t\t**\tare fatal.\n\t\t*/\n\t\tif (Handle == 0) {\n\n//\t\t\tError(errno, false, Filename);\t\t//this kills windoze!!!!    ST - 9/28/95 5:33PM\n#ifdef NEVER\n\t\t\t/*\n\t\t\t**\tIf this flag is set, then some hard error occurred. Just assume that the error\n\t\t\t**\tis probably a removed CD-ROM and allow a retry.\n\t\t\t*/\n\t\t\tif (Hard_Error_Occured) {\n\t\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\t} else {\n\t\t\t\tif (errno == ENOENT) {\n\t\t\t\t\tError(ENOENT, true, Filename);\n\t\t\t\t} else {\n\t\t\t\t\tError(errno, false, Filename);\n\t\t\t\t}\n\t\t\t}\n#endif\n\t\t\tcontinue;\n\t\t}\n\t\tbreak;\n\t}\n\treturn(true);\n}\n\n\n\n\nvoid RawFileClass::Set_Buffer_Size (int size)\n{\n\tif (Handle){\n\t\tmmioSetBuffer((HMMIO)Handle, NULL, size, 0);\n\t}\n}\n\n\n\n\n/***********************************************************************************************\n * RawFileClass::Is_Available -- Checks to see if the specified file is available to open.     *\n *                                                                                             *\n *    This routine will examine the disk system to see if the specified file can be opened     *\n *    or not. Use this routine before opening a file in order to make sure that is available   *\n *    or to perform other necessary actions.                                                   *\n *                                                                                             *\n * INPUT:   force -- Should this routine keep retrying until the file becomes available? If    *\n *                   in this case it doesn't become available, then the program will abort.    *\n *                                                                                             *\n * OUTPUT:  bool; Is the file available to be opened?                                          *\n *                                                                                             *\n * WARNINGS:   Depending on the parameter passed in, this routine may never return.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Is_Available(int forced)\n{\n\tint\tfile;\t\t// Working file handle.\n\tint\topen_failed;\n\t/*\n\t**\tIf the file is already open, then is must have already passed the availability check.\n\t**\tReturn true in this case.\n\t*/\n\tif (Is_Open()) return(true);\n\n\t/*\n\t**\tIf this is a forced check, then go through the normal open channels, since those\n\t**\tchannels ensure that the file must exist.\n\t*/\n\tif (forced) {\n\t\tRawFileClass::Open(READ);\n\t\tRawFileClass::Close();\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tPerform a raw open of the file. If this open fails for ANY REASON, including a missing\n\t**\tCD-ROM, this routine will return a failure condition. In all but the missing file\n\t**\tcondition, go through the normal error recover channels.\n\t*/\n\tfor (;;) {\n\n//\t\tHard_Error_Occured = 0;\n\t\tfile = open(Filename, O_RDONLY|O_BINARY);\n\t\topen_failed = (file == -1);\n\n\t\t/*\n\t\t**\tIf DOS reports that everything is just fine except that the file is not present,\n\t\t**\tthen return with this fact. Any other case will fall through to the error handler\n\t\t**\troutine.\n\t\t*/\n\t\tif (open_failed && errno == ENOENT) return(false);\n\n\t\t/*\n\t\t** If we got an access error it could be because there is no cd in\n\t\t** the drive.  Call the error handler but allow a continue if it\n\t\t** returns.\n\t\t*/\n\t\tif (open_failed && errno == EACCES) {\n\t\t\tError(errno, true, Filename);\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tIf the file could not be found, then return with this information. If a more\n\t\t**\tserious error occurred, then display the error message and abort.\n\t\t*/\n//\t\tif (Hard_Error_Occured) {\n//\t\t\tError(Hard_Error_Occured, true, Filename);\n//\t\t\tcontinue;\n//\t\t} else {\n\t\t\tif (open_failed) {\n\t\t\t\t/*\n\t\t\t\t**\tAn unhandled error condition is fatal. Display the error message and then\n\t\t\t\t**\tabort.\n\t\t\t\t*/\n\t\t\t\tError(errno, false, Filename);\n\t\t\t}\n//\t\t}\n\t\tif (!open_failed) break;\n\t}\n\n\t/*\n\t**\tSince the file could be opened, then close it and return that the file exists.\n\t*/\n\tif (close(file)) {\n\t\tError(errno, false, Filename);\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Close -- Perform a closure of the file.                                       *\n *                                                                                             *\n *    Close the file object. In the rare case of an error, handle it as appropriate.           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Some rare error conditions may cause this routine to abort the program.         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RawFileClass::Close(void)\n{\n\n\t/*\n\t**\tIf the file is open, then close it. If the file is already closed, then just return. This\n\t**\tisn't considered an error condition.\n\t*/\n\tif (Is_Open()) {\n\n\t\tfor (;;) {\n\t\t\t/*\n\t\t\t**\tClose the file. If there was an error in the close operation -- abort.\n\t\t\t*/\n//\t\t\tHard_Error_Occured = 0;\n\t\t\tif (mmioClose((HMMIO)Handle, 0)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tBy definition, this error can only be a bad file handle. This a fatal condition\n\t\t\t\t**\tof course, so abort with an error message.\n\t\t\t\t*/\n\t\t\t\tError(errno, false, Filename);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIn the condition (if it is even possible) of a hard error occurring, then\n\t\t\t**\tassume it is the case of missing media. Display an error message and try\n\t\t\t**\tagain if indicated.\n\t\t\t*/\n//\t\t\tif (Hard_Error_Occured) {\n//\t\t\t\tError(Hard_Error_Occured, true, Filename);\n//\t\t\t\tcontinue;\n//\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tAt this point the file must have been closed. Mark the file as empty and return.\n\t\t*/\n\t\tHandle = -1;\n\t}\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Read -- Reads the specified number of bytes into a memory buffer.             *\n *                                                                                             *\n *    This routine will read the specified number of bytes and place the data into the buffer  *\n *    indicated. It is legal to call this routine with a request for more bytes than are in    *\n *    the file. This condition can result in fewer bytes being read than requested. Determine  *\n *    this by examining the return value.                                                      *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer to read data into. If NULL is passed, no read    *\n *                      is performed.                                                          *\n *                                                                                             *\n *          size     -- The number of bytes to read. If NULL is passed, then no read is        *\n *                      performed.                                                             *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes read into the buffer. If this number is less      *\n *          than requested, it indicates that the file has been exhausted.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Read(void *buffer, long size)\n{\n\tlong\tbytesread = 0;\t\t\t// Running count of the number of bytes read into the buffer.\n\tint\topened = false;\t\t// Was the file opened by this routine?\n\tint\treadresult;\n\n\t/*\n\t**\tIf the file isn't opened, open it. This serves as a convenience\n\t**\tfor the programmer.\n\t*/\n\tif (!Is_Open()) {\n\n\t\t/*\n\t\t**\tThe error check here is moot. Open will never return unless it succeeded.\n\t\t*/\n\t\tif (!Open(READ)) {\n\t\t\treturn(0);\n\t\t}\n\t\topened = true;\n\t}\n\n\t/*\n\t**\tRead the file in convenient chunk sizes. When the actual number\n\t**\tof bytes read does not match the desired, then assume that the file\n\t**\tis exhausted and bail. This loop was adjusted to take into\n\t**\tconsideration the fact that \"read\" returns a SIGNED value whereas\n\t**\tit takes an UNSIGNED value as the byte count.\n\t*/\n\twhile (size) {\n\t\tunsigned\tdesired;\t\t// Bytes desired to be read this pass.\n\t\tunsigned actual;\t\t// Actual number of bytes read.\n\n\t\t/*\n\t\t**\tBreak the read request into chunks no bigger than the low level DOS read\n\t\t**\tcan handle.\n\t\t*/\n\t\tdesired = size;\n\n//\t\tHard_Error_Occured = 0;\n\t\treadresult = 0;\n\t\tactual = mmioRead((HMMIO)Handle, (char*)buffer, desired);\n\t\t//actual = read(Handle, buffer, desired);\n\t\tif (actual != desired) readresult = errno;\n\n\t\t/*\n\t\t**\tIf a hard error occurred, then assume that it is the case of the CD-ROM or\n\t\t**\tfloppy media having been removed. Display the error and retry as directed.\n\t\t*/\n//\t\tif (Hard_Error_Occured) {\n//\t\t\tError(Hard_Error_Occured, true, Filename);\n//\t\t\tcontinue;\t\t\t// Not technically needed, but to be consistent...\n//\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf negative one is returned from the read operation, then this indicates\n\t\t\t**\teither a bad file number or invalid access. These are fatal conditions, so\n\t\t\t**\tdisplay the error and then abort.\n\t\t\t*/\n\t\t\tif (readresult != 0) {\n\t\t\t\tError(errno, false, Filename);\n\t\t\t}// else {\n\n\t\t\t\t/*\n\t\t\t\t**\tNo error occurred during the read. Adjust the pointers and size counters and\n\t\t\t\t**\tloop again if more data is needed to be read.\n\t\t\t\t*/\n\t\t\t\tbuffer = (void *) ((long)buffer + actual);\n\t\t\t\tbytesread += actual;\n\t\t\t\tsize -= actual;\n\t\t\t\tif (actual != desired) break;\t\t// No more data?\n\t\t\t//}\n//\t\t}\n\t}\n\n\t/*\n\t**\tClose the file if it was opened by this routine and return\n\t**\tthe actual number of bytes read into the buffer.\n\t*/\n\tif (opened) Close();\n\treturn(bytesread);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Write -- Writes the specified data to the buffer specified.                   *\n *                                                                                             *\n *    This routine will write the data specified to the file.                                  *\n *                                                                                             *\n * INPUT:   buffer   -- The buffer that holds the data to write.                               *\n *                                                                                             *\n *          size     -- The number of bytes to write to the file.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes written to the file. This routine catches the     *\n *          case of a disk full condition, so this routine will always return with the number  *\n *          matching the size request.                                                         *\n *                                                                                             *\n * WARNINGS:   A fatal file condition could cause this routine to never return.                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Write(void const *buffer, long size)\n{\n\tlong\tbytesread = 0;\n\tint\topened = false;\t\t// Was the file manually opened?\n\tint\twriteresult;\n\n\t/*\n\t**\tCheck to open status of the file. If the file is open, then merely write to\n\t**\tit. Otherwise, open the file for writing and then close the file when the\n\t**\toutput is finished.\n\t*/\n\tif (!Is_Open()) {\n\t\tif (!Open(WRITE)) {\n\t\t\treturn(0);\n\t\t}\n\t\topened = true;\n\t}\n\n\t/*\n\t**\tWrite the data to the file in chunks no bigger than what the low level DOS write\n\t**\tcan handle.\n\t*/\n\twhile (size) {\n\t\tunsigned\tdesired;\t\t// Bytes desired to be write this pass.\n\t\tunsigned actual;\t\t// Actual number of bytes written.\n\n//\t\tHard_Error_Occured = 0;\n//\t\tdesired = (unsigned)MIN(size, Transfer_Block_Size());\n\t\tdesired = size;\n\t\twriteresult = 0;\n\t\tactual = mmioWrite((HMMIO)Handle, (char*)buffer, desired);\n\t\t//actual = write(Handle, buffer, desired);\n\t\tif (actual != desired) writeresult = errno;\n\n\t\t/*\n\t\t**\tIf a hard error occurred, then assume it is the case of the media being\n\t\t**\tremoved. Print the error message an retry as directed.\n\t\t*/\n//\t\tif (Hard_Error_Occured) {\n//\t\t\tError(Hard_Error_Occured, true, Filename);\n//\t\t\tcontinue;\t\t\t// Not technically needed, but to be consistent...\n//\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf negative one is returned by the DOS read, then this indicates a bad file\n\t\t\t**\thandle or invalid access. Either condition is fatal -- display error condition\n\t\t\t**\tand abort.\n\t\t\t*/\n\t\t\tif (writeresult != 0) {\n\t\t\t\tError(errno, false, Filename);\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tA successful write occurred. Update pointers and byte counter as appropriate.\n\t\t\t\t*/\n\t\t\t\tbuffer = (void *)((long)buffer + actual);\n\t\t\t\tbytesread += actual;\n\t\t\t\tsize -= actual;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the actual bytes written is less than requested, assume this is a case of\n\t\t\t\t**\tthe disk being full. Consider this a fatal error condition.\n\t\t\t\t*/\n\t\t\t\tif (actual != desired) {\n\t\t\t\t\tError(ENOSPC, false, Filename);\n\t\t\t\t}\n\t\t\t}\n//\t\t}\n\t}\n\n\t/*\n\t**\tIf this routine had to open the file, then close it before returning.\n\t*/\n\tif (opened) {\n\t\tClose();\n\t}\n\n\t/*\n\t**\tReturn with the number of bytes written. This will always be the number of bytes\n\t**\trequested, since the case of the disk being full is caught by this routine.\n\t*/\n\treturn(bytesread);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Seek -- Reposition the file pointer as indicated.                             *\n *                                                                                             *\n *    Use this routine to move the filepointer to the position indicated. It can move either   *\n *    relative to current position or absolute from the beginning or ending of the file. This  *\n *    routine will only return if it successfully performed the seek.                          *\n *                                                                                             *\n * INPUT:   pos   -- The position to seek to. This is interpreted as relative to the position  *\n *                   indicated by the \"dir\" parameter.                                         *\n *                                                                                             *\n *          dir   -- The relative position to relate the seek to. This can be either SEEK_SET  *\n *                   for the beginning of the file, SEEK_CUR for the current position, or      *\n *                   SEEK_END for the end of the file.                                         *\n *                                                                                             *\n * OUTPUT:  This routine returns the position that the seek ended up at.                       *\n *                                                                                             *\n * WARNINGS:   If there was a file error, then this routine might never return.                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Seek(long pos, int dir)\n{\n\t/*\n\t**\tIf the file isn't opened, then this is a fatal error condition.\n\t*/\n\tif (!Is_Open()) {\n\t\tError(EBADF, false, Filename);\n\t}\n\n\t/*\n\t**\tKeep trying to seek until a non-retry condition occurs.\n\t*/\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tPerform the low level seek on the file.\n\t\t*/\n//\t\tHard_Error_Occured = 0;\n\t\tpos = mmioSeek((HMMIO)Handle, pos, dir);\n\t\t//pos = lseek(Handle, pos, dir);\n\n\t\t/*\n\t\t**\tIf a hard error occurred, then assume that it is the case of removed media. Display\n\t\t**\terror message and retry.\n\t\t*/\n//\t\tif (Hard_Error_Occured) {\n//\t\t\tError(Hard_Error_Occured, true, Filename);\n//\t\t\tcontinue;\n//\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tA negative one indicates a fatal error with the seek operation. Display error\n\t\t\t**\tcondition and then abort.\n\t\t\t*/\n\t\t\tif (pos == -1) {\n\t\t\t\tError(errno, false, Filename);\n\t\t\t}\n//\t\t}\n\t\tbreak;\n\t}\n\n\t/*\n\t**\tReturn with the new position of the file. This will range between zero and the number of\n\t**\tbytes the file contains.\n\t*/\n\treturn(pos);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Size -- Determines size of file (in bytes).                                   *\n *                                                                                             *\n *    Use this routine to determine the size of the file. The file must exist or this is an    *\n *    error condition.                                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes in the file.                                      *\n *                                                                                             *\n * WARNINGS:   This routine handles error conditions and will not return unless the file       *\n *             exists and can successfully be queried for file length.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Size(void)\n{\n\tlong\tsize = 0;\n\tint\thandle = 0;\n\n\t/*\n\t**\tIf the file is open, then proceed normally.\n\t*/\n\tif (Is_Open()) {\n\n\t\t/*\n\t\t**\tRepetitively try to determine the file size until a fatal error condition or success\n\t\t**\tis achieved.\n\t\t*/\n\t\tfor (;;) {\n//\t\t\tHard_Error_Occured = 0;\n\n\t\t\thandle = open(Filename, O_RDONLY|O_BINARY);\n\t\t\tif (handle > 0){\n\t\t\t\tsize = filelength(handle);\n\t\t\t\tclose(handle);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf a hard error occurred, then assume it is the case of removed media. Display an\n\t\t\t**\terror condition and allow retry.\n\t\t\t*/\n//\t\t\tif (Hard_Error_Occured) {\n//\t\t\t\tError(Hard_Error_Occured, true, Filename);\n//\t\t\t\tcontinue;\n//\t\t\t} else {\n\t\t\t\tif (size == -1) {\n\t\t\t\t\tError(errno, false, Filename);\n\t\t\t\t}\n//\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tIf the file wasn't open, then open the file and call this routine again. Count on\n\t\t**\tthe fact that the open function must succeed.\n\t\t*/\n\t\tif (Open()) {\n\t\t\tsize = Size();\n\n\t\t\t/*\n\t\t\t**\tSince we needed to open the file we must remember to close the file when the\n\t\t\t**\tsize has been determined.\n\t\t\t*/\n\t\t\tClose();\n\t\t}\n\t}\n\treturn(size);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Create -- Creates an empty file.                                              *\n *                                                                                             *\n *    This routine will create an empty file from the file object. The file object's filename  *\n *    must already have been assigned before this routine will function.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the file successfully created? This routine will always return true.     *\n *                                                                                             *\n * WARNINGS:   A fatal error condition could occur with this routine. Especially if the disk   *\n *             is full or a read-only media was selected.                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Create(void)\n{\n\tClose();\n\tif (Open(WRITE)) {\n\t\tClose();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Delete -- Deletes the file object from the disk.                              *\n *                                                                                             *\n *    This routine will delete the file object from the disk. If the file object doesn't       *\n *    exist, then this routine will return as if it had succeeded (since the effect is the     *\n *    same).                                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the file deleted? If the file was already missing, the this value will   *\n *                be false.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Delete(void)\n{\n\t/*\n\t**\tIf the file was open, then it must be closed first.\n\t*/\n\tClose();\n\n\t/*\n\t**\tIf there is no filename associated with this object, then this indicates a fatal error\n\t**\tcondition. Report this and abort.\n\t*/\n\tif (!Filename) {\n\t\tError(ENOENT, false);\n\t}\n\n\t/*\n\t**\tRepetitively try to delete the file if possible. Either return with success, or\n\t**\tabort the program with an error.\n\t*/\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tIf the file is already missing, then return with this fact. No action is necessary.\n\t\t**\tThis can occur as this section loops if the file exists on a floppy and the floppy\n\t\t**\twas removed, the file deleted on another machine, and then the floppy was\n\t\t**\treinserted. Admittedly, this is a rare case, but is handled here.\n\t\t*/\n\t\tif (!Is_Available()) {\n\t\t\treturn(false);\n\t\t}\n\n//\t\tHard_Error_Occured = 0;\n\t\tif (remove(Filename) == -1) {\n\n\t\t\t/*\n\t\t\t**\tIf a hard error occurred, then assume that the media has been removed. Display\n\t\t\t**\terror message and retry as directed.\n\t\t\t*/\n//\t\t\tif (Hard_Error_Occured) {\n//\t\t\t\tError(Hard_Error_Occured, true, Filename);\n//\t\t\t\tcontinue;\n//\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf at this point, DOS says the file doesn't exist, then just exit with this\n\t\t\t**\tfact. It should have been caught earlier, but in any case, this is a legal\n\t\t\t**\tcondition.\n\t\t\t*/\n\t\t\tif (errno == ENOENT) break;\n\n\t\t\t/*\n\t\t\t**\tThe only way it can reach this point is if DOS indicates that access is denied\n\t\t\t**\ton the file. This occurs when trying to delete a file on a read-only media such\n\t\t\t**\tas a CD-ROM. Report this as a fatal error and then abort.\n\t\t\t*/\n\t\t\tError(errno, false, Filename);\n\t\t}\n\t\tbreak;\n\t}\n\n\t/*\n\t**\tDOS reports that the file was successfully deleted. Return with this fact.\n\t*/\n\treturn(true);\n}\n\n\n\n\n\n\n//extern \"C\" {\n\n#define\tMAX_HANDLES\t10\nstatic RawFileClass Handles[MAX_HANDLES];\n\n#ifdef NEVER\nbool __cdecl Set_Search_Drives(BYTE const *)\n{\n\tRawFileClass::Set_Search_Path(path);\n\treturn(true);\n}\n#endif\n\n\n\nint __cdecl Open_File(char const *file_name, int mode)\n{\n\tfor (int index = 0; index < MAX_HANDLES; index++) {\n\t\tif (!Handles[index].Is_Open()) {\n\t\t\tif (Handles[index].Open(file_name,mode)) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn(WW_ERROR);\n}\n\nVOID __cdecl Close_File(int handle)\n{\n\tif (handle != WW_ERROR && Handles[handle].Is_Open()) {\n\t\tHandles[handle].Close();\n\t}\n}\n\nLONG __cdecl Read_File(int handle, VOID *buf, ULONG bytes)\n{\n\tif (handle != WW_ERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Read(buf, bytes));\n\t}\n\treturn(0);\n}\n\nLONG __cdecl Write_File(int handle, VOID const *buf, ULONG bytes)\n{\n\tif (handle != WW_ERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Write(buf, bytes));\n\t}\n\treturn(0);\n}\n\nint __cdecl Find_File(char const *file_name)\n{\n\tRawFileClass file(file_name);\n\treturn(file.Is_Available());\n}\n\n#ifdef NEVER\nint __cdecl Delete_File(BYTE const *file_name)\n{\n\treturn(RawFileClass(file_name).Delete());\n}\n\nint __cdecl Create_File(BYTE const *file_name)\n{\n\treturn(RawFileClass(file_name).Create());\n}\n\nULONG __cdecl Load_Data(BYTE const *name, VOID *ptr, ULONG size)\n{\n\treturn(RawFileClass(name).Read(ptr, size));\n}\n\nVOID * __cdecl Load_Alloc_Data(char const *name, int )\n{\n\tRawFileClass file(name);\n\n\treturn(Load_Alloc_Data(file));\n}\n#endif\n\nULONG __cdecl File_Size(int handle)\n{\n\tif (handle != WW_ERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Size());\n\t}\n\treturn(0);\n}\n\n#ifdef NEVER\nULONG __cdecl Write_Data(BYTE const *name, VOID const *ptr, ULONG size)\n{\n\treturn(RawFileClass(name).Write(ptr, size));\n}\n#endif\n\nULONG __cdecl Seek_File(int handle, LONG offset, int starting)\n{\n\tif (handle != WW_ERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Seek(offset, starting));\n\t}\n\treturn(0);\n}\n\n#ifdef NEVER\nbool __cdecl Multi_Drive_Search(bool on)\n{\n//\treturn(RawFileClass::Multi_Drive_Search(on));\n\treturn(on);\n}\n\nVOID __cdecl WWDOS_Init(VOID)\n{\n}\n\nVOID __cdecl WWDOS_Shutdown(VOID)\n{\n}\n\nint __cdecl Find_Disk_Number(BYTE const *)\n{\n\treturn(0);\n}\n#endif\n\n\n\n\n/***********************************************************************************************\n * Load_File -- load an entire file into memory                                                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    File name                                                                         *\n *           Load address                                                                      *\n *                                                                                             *\n * OUTPUT:   bytes loaded                                                                      *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/28/95 5:09PM ST : Created                                                              *\n *=============================================================================================*/\n\nint __cdecl Load_File ( const char *file_name , void *load_addr )\n{\n\tint\t\tbytes_read=0;\n\tint\t\thandle;\n\n\thandle=Open_File ( file_name , READ );\n\n\tif ( handle>=0 ){\n\t\tbytes_read = Read_File ( handle , load_addr , File_Size ( handle ) );\n\t\tClose_File ( handle );\n\t}\n\treturn ( bytes_read );\n}\n\n\n\n\n//ULONG cdecl Load_Uncompress(BYTE const *file, BuffType uncomp_buff, BuffType dest_buff, VOID *reserved_data)\n//{\n//\treturn(Load_Uncompress(RawFileClass(file), uncomp_buff, dest_buff, reserved_data));\n//\treturn(RawFileClass(file).Load_Uncompress(uncomp_buff, dest_buff, reserved_data));\n//}\nextern \"C\" {\nint MaxDevice;\nint DefaultDrive;\nchar CallingDOSInt;\n\n}\n\n\nvoid Unfragment_File_Cache(void)\n{\n}\n"
  },
  {
    "path": "WIN32LIB/RAWFILE/RAWFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\rawfile.h_v   2.15   06 Sep 1995 16:29:30   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Library                                             *\n *                                                                                             *\n *                    File Name : RAWFILE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 18, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RawFileClass::File_Name -- Returns with the filename associate with the file object.      *\n *   RawFileClass::RawFileClass -- Default constructor for a file object.                      *\n *   RawFileClass::Is_Open -- Checks to see if the file is open or not.                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef RAWFILE_H\n#define RAWFILE_H\n\n#define WIN32 1\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#include <windows.h>\n\n//#include\t<wwlib32.h>\n#include\t<limits.h>\n#include\t<errno.h>\n#include\t<windows.h>\n//#include\t<algo.h>\n#include\t\"wwfile.h\"\n\n#ifdef NEVER\n\t/*\n\t**\tThis is a duplicate of the error numbers. The error handler for the RawFileClass handles\n\t**\tthese errors. If the error routine is overridden and additional errors are defined, then\n\t**\tuse numbers starting with 100. Note that these errors here are listed in numerical order.\n\t**\tThese errors are defined in the standard header file \"ERRNO.H\".\n\t*/\n\tEZERO,\t\t\t\t// Non-error.\n\tEINVFNC,\t\t\t\t// Invalid function number.\n\tENOFILE,\t\t\t\t// File not found.\n\tENOENT=ENOFILE,\t// No such file or directory.\n\tENOPATH,\t\t\t\t// Path not found.\n\tEMFILE,\t\t\t\t// Too many open files.\n\tEACCES,\t\t\t\t// Permission denied.\n\tEBADF,\t\t\t\t// Bad file number.\n\tECONTR,\t\t\t\t// Memory blocks destroyed.\n\tENOMEM,\t\t\t\t// Not enough core memory.\n\tEINVMEM,\t\t\t\t// Invalid memory block address.\n\tEINVENV,\t\t\t\t// Invalid environment.\n\tEINVFMT,\t\t\t\t// Invalid format.\n\tEINVACC,\t\t\t\t// Invalid access code.\n\tEINVDAT,\t\t\t\t// Invalid data.\n\tEFAULT,\t\t\t\t// Unknown error.\n\tEINVDRV,\t\t\t\t// Invalid drive specified.\n\tENODEV=EINVDRV,\t// No such device.\n\tECURDIR,\t\t\t\t// Attempt to remove CurDir.\n\tENOTSAM,\t\t\t\t// Not same device.\n\tENMFILE,\t\t\t\t// No more files.\n\tEINVAL,\t\t\t\t// Invalid argument.\n\tE2BIG,\t\t\t\t// Argument list too long.\n\tENOEXEC,\t\t\t\t// exec format error.\n\tEXDEV,\t\t\t\t// Cross-device link.\n\tENFILE,\t\t\t\t// Too many open files.\n\tECHILD,\t\t\t\t// No child process.\n\tENOTTY,\t\t\t\t// not used\n\tETXTBSY,\t\t\t\t// not used\n\tEFBIG,\t\t\t\t// not used\n\tENOSPC,\t\t\t\t// No space left on device.\n\tESPIPE,\t\t\t\t// Illegal seek.\n\tEROFS,\t\t\t\t// Read-only file system.\n\tEMLINK,\t\t\t\t// not used\n\tEPIPE,\t\t\t\t// Broken pipe.\n\tEDOM,\t\t\t\t\t// Math argument.\n\tERANGE,\t\t\t\t// Result too large.\n\tEEXIST,\t\t\t\t// File already exists.\n\tEDEADLOCK,\t\t\t// Locking violation.\n\tEPERM,\t\t\t\t// Operation not permitted.\n\tESRCH,\t\t\t\t// not used\n\tEINTR,\t\t\t\t// Interrupted function call.\n\tEIO,\t\t\t\t\t// Input/output error.\n\tENXIO,\t\t\t\t// No such device or address.\n\tEAGAIN,\t\t\t\t// Resource temporarily unavailable.\n\tENOTBLK,\t\t\t\t// not used\n\tEBUSY,\t\t\t\t// Resource busy.\n\tENOTDIR,\t\t\t\t// not used\n\tEISDIR,\t\t\t\t// not used\n\tEUCLEAN,\t\t\t\t// not used\n#endif\n\n/*\n**\tThis is the definition of the raw file class. It is derived from the abstract base FileClass\n**\tand handles the interface to the low level DOS routines. This is the first class in the\n**\tchain of derived file classes that actually performs a useful function. With this class,\n**\tI/O is possible. More sophisticated features, such as packed files, CD-ROM support,\n**\tfile caching, and XMS/EMS memory support, are handled by derived classes.\n**\n**\tOf particular importance is the need to override the error routine if more sophisticated\n**\terror handling is required. This is more than likely if greater functionality is derived\n**\tfrom this base class.\n*/\nclass RawFileClass : public FileClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tThis is a record of the access rights used to open the file. These rights are\n\t\t**\tused if the file object is duplicated.\n\t\t*/\n\t\tint Rights;\n\n\t\tRawFileClass(char const *filename);\n\t\tRawFileClass(void);\n\t\tRawFileClass (RawFileClass const & f);\n\t\tRawFileClass & operator = (RawFileClass const & f);\n\t\tvirtual ~RawFileClass(void) {if (Allocated && Filename) free((char *)Filename);};\n\n\t\tvirtual char const * File_Name(void) const;\n\t\tvirtual char const * Set_Name(char const *filename);\n\t\tvirtual int Create(void);\n\t\tvirtual int Delete(void);\n\t\tvirtual int Is_Available(int forced=false);\n\t\tvirtual int Is_Open(void) const;\n\t\tvirtual int Open(char const *filename, int rights=READ);\n\t\tvirtual int Open(int rights=READ);\n\t\tvirtual long Read(void *buffer, long size);\n\t\tvirtual long Seek(long pos, int dir=SEEK_CUR);\n\t\tvirtual long Size(void);\n\t\tvirtual long Write(void const *buffer, long size);\n\t\tvirtual void Close(void);\n\t\tvirtual void Error(int error, int canretry = false, char const * filename=NULL);\n\t\tvirtual void Set_Buffer_Size(int size);\n\n\n\tprotected:\n\n\t\t/*\n\t\t**\tThis function returns the largest size a low level DOS read or write may\n\t\t**\tperform. Larger file transfers are performed in chunks of this size or less.\n\t\t*/\n\t\tlong Transfer_Block_Size(void) {return (long)((unsigned)UINT_MAX)-16L;};\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is the low level DOS handle. A -1 indicates an empty condition.\n\t\t*/\n\t\tint Handle;\n\n\t\t/*\n\t\t**\tThis points to the filename as a NULL terminated string. It may point to either a\n\t\t**\tconstant or an allocated string as indicated by the \"Allocated\" flag.\n\t\t*/\n\t\tchar const * const Filename;\n\n\t\t/*\n\t\t**\tFilenames that were assigned as part of the construction process\n\t\t**\tare not allocated. It is assumed that the filename string is a\n\t\t**\tconstant in that case and thus making duplication unnecessary.\n\t\t**\tThis value will be non-zero if the filename has be allocated\n\t\t**\t(using strdup()).\n\t\t*/\n\t\tunsigned Allocated:1;\n};\n\n\n/***********************************************************************************************\n * RawFileClass::File_Name -- Returns with the filename associate with the file object.        *\n *                                                                                             *\n *    Use this routine to determine what filename is associated with this file object. If no   *\n *    filename has yet been assigned, then this routing will return NULL.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the file name associated with this file object or NULL   *\n *          if one doesn't exist.                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n;*   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline char const * RawFileClass::File_Name(void) const\n{\n\treturn Filename;\n}\n\n/***********************************************************************************************\n * RawFileClass::RawFileClass -- Default constructor for a file object.                        *\n *                                                                                             *\n *    This constructs a null file object. A null file object has no file handle or filename    *\n *    associated with it. In order to use a file object created in this fashion it must be     *\n *    assigned a name and then opened.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n;*   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline RawFileClass::RawFileClass(void) : Filename(0)\n{\n\tHandle = -1;\n\tAllocated = false;\n}\n\n/***********************************************************************************************\n * RawFileClass::Is_Open -- Checks to see if the file is open or not.                          *\n *                                                                                             *\n *    Use this routine to determine if the file is open. It returns true if it is.             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file open?                                                            *\n *                                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n;*   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int RawFileClass::Is_Open(void) const\n{\n\treturn (Handle != -1);\n}\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/RAWFILE/WWFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\wwfile.h_v   2.14   06 Sep 1995 16:30:00   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Library                                             *\n *                                                                                             *\n *                    File Name : WWFILE.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : August 8, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWFILE_H\n#define WWFILE_H\n\n#include\t<stdio.h>\n\n#ifndef READ\n#define\tREAD\t_READ\n#endif\n#ifndef WRITE\n#define\tWRITE\t_WRITE\n#endif\n\nclass FileClass\n{\n\tpublic:\n\t\tvirtual ~FileClass(void) {};\n\t\tvirtual char const * File_Name(void) const = 0;\n\t\tvirtual char const * Set_Name(char const *filename) = 0;\n\t\tvirtual int Create(void) = 0;\n\t\tvirtual int Delete(void) = 0;\n\t\tvirtual int Is_Available(int forced=false) = 0;\n\t\tvirtual int Is_Open(void) const = 0;\n\t\tvirtual int Open(char const *filename, int rights=READ) = 0;\n\t\tvirtual int Open(int rights=READ) = 0;\n\t\tvirtual long Read(void *buffer, long size) = 0;\n\t\tvirtual long Seek(long pos, int dir=SEEK_CUR) = 0;\n\t\tvirtual long Size(void) = 0;\n\t\tvirtual long Write(void const *buffer, long size) = 0;\n\t\tvirtual void Close(void) = 0;\n\n\t\toperator char const * () {return File_Name();};\n};\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/REBUILD.BAT",
    "content": "global /i del *.obj\ndel /y lib\nwmake\n"
  },
  {
    "path": "WIN32LIB/SHAPE/DRAWSHP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : WWLIB32                                  *\n;*                                                                         *\n;*                    File Name : DRAWSHP.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : April 13, 1992                           *\n;*                                                                         *\n;*                  Last Update : September 14, 1994   [IML]               *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Draw_Shape -- Draws a shape at given buffer coordinates and clips     *\n;*   Not_Supported -- Replacement function for Draw_Shape routines not used*\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n; this struct is here to remove the hardwire way of programing\n; implemented in the funtion Draw_Shape in ian image of \n\nSTRUC\tVVPC_IMAGE\n   \t\tOff  \tdd  ?  \n\t\tWidth  \tdd  ?  \n\t\tHeight  dd  ?  \n  \t\tPage    dd  ?  \nENDS\n\n\n\nSTRUC GVPC_IMAGE \n\t\t vvpc\t\tVVPC_IMAGE\t<>\n\t\t Xpos\t\tdd\t   \t?\n\t\t Ypos\t\tdd\t   \t?\n\t\t GraphicBuff\tdd\t   \t?\nENDS\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;****************************** Declarations ********************************\nGLOBAL\t Draw_Shape:NEAR\nGLOBAL\t LCW_Uncompress:NEAR\nGLOBAL\t_ShapeBuffer:DWORD\nGLOBAL\t_ShapeBufferSize:DWORD\n\nGLOBAL\tMaskPage\t       : dword\nGLOBAL\tBackGroundPage\t       : dword\n\n\n;********************************* Data ************************************\n\tDATASEG\n;---------------------------------------------------------------------------\n; Shape buffer & its size, set by Set_Shape_Buffer()\n;---------------------------------------------------------------------------\n_ShapeBuffer\t\tDD\t0\n_ShapeBufferSize\tDD\t0\n\n;---------------------------------------------------------------------------\n; Address of MaskPage & BackGroundPage, set by Init_Priority_System()\n;---------------------------------------------------------------------------\nMaskPage\t\tDD\t0\nBackGroundPage\t\tDD\t0\n\n;---------------------------------------------------------------------------\n; Predator effect variables \n;---------------------------------------------------------------------------\nPredCount\tDD\t0\nPredTable\tDB\t1, 3, 2, 5, 4, 3, 2, 1\nPredValue\tDD\t1\nPartialPred\tDD\t0\t; partially faded predator effect value\nPartialCount\tDD\t0\n\n;---------------------------------------------------------------------------\n; 32 bit versions of 16 bit stack variables\n;---------------------------------------------------------------------------\nFlags\t\tDD\t?\t; globally accessible copy of flags\n\nviewport_ptr\tDD\t?\t; pointer to upper-left corner of viewport \nviewport_width\tDD\t?\t; viewport width\nviewport_height DD\t?\t; viewport height\nviewport_yadd\tDD\t?\t; viewport y add\nviewport_x\tDD\t?\t; viewport x-coord\nviewport_y\tDD\t?\t; viewport y-coord\nbuff_ptr\tDD\t?\t; pointer to buffer containing viewport\n\n;********************************* Code ************************************\n\tCODESEG\n\n\n;***************************************************************************\n;* Draw_Shape -- Draws a shape at given buffer coordinates and clips       *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*  DWORD\tgvp_ptr\t\t; pointer to graphic viewport info\t   *\n;*  DWORD\tshape_ptr\t; the shape pointer to draw\t\t   *\n;*  DWORD\tdraw_x\t\t; x-coord of hotspot in viewport\t   *\n;*  DWORD\tdraw_y\t\t; y-coord of hotspot in viewport\t   *\n;*  DWORD\tflags\t\t; the flags for drawing the shape\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* Optional Arguments: If the following flags are used, the given args\t   *\n;* MUST be present.  Note that, if more than one one set of args is used,  *\n;* they must appear in this order (alphabetical).\t\t\t   *\n;*  SHAPE_COLOR:\tDWORD color_table (256 bytes)\t\t\t   *\n;*  SHAPE_FADING:\tDWORD fade_table (256 bytes), DWORD fade_count\t   *\n;*  SHAPE_GHOST:\tDWORD is_translucent tbl, DWORD translucent tbl    *\n;*  SHAPE_PARTIAL:\tDWORD predator partial_value (0-255)\t\t   *\n;*  SHAPE_PRIORITY:\tDWORD priority_level\t\t\t\t   *\n;*  SHAPE_SCALING:\tDWORD x_scale, WORD y_scale\t\t\t   *\n;*  SHAPE_SHADOW:\tDWORD shadowing_table (256 bytes)\t\t   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*  none.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:\t\t\t\t\t\t\t\t   *\n;*  none.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;*\t\t\t\t\t\t\t\t\t   *\n;* File Organization:\t\t\t\t\t\t\t   *\n;* drawshp.asm : this file\t\t\t\t\t\t   *\n;* shape.inc   : main shape header file; contains declarations for all\t   *\n;* \t\t  globals, procedures and constants\t\t\t   *\n;* ds_table.asm: contains the procedure address tables for LSkipRout,\t   *\n;*\t\t  RSkipRout, DrawRout, & PixelRout\t\t\t   *\n;* ds_l*.asm   : left-skip routines\t\t\t\t\t   *\n;* ds_r*.asm   : right-skip routines\t\t\t\t\t   *\n;* ds_d*.asm   : drawing routines\t\t\t\t\t   *\n;* \t\t\t\t\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* Shape format:\t\t\t\t\t\t\t   *\n;* Header:\t\t\t\t\t\t\t\t   *\n;*   UWORD  SType (0=normal, 1=16-color, 2=uncompressed, 4=variable-color) *\n;*   UBYTE  Height\t\t\t\t\t\t\t   *\n;*   UWORD  Width\t\t\t\t\t\t\t   *\n;*   UBYTE  unmodified height\t\t\t\t\t\t   *\n;*   UWORD  size of shape in memory, including this header\t\t   *\n;*   UWORD  uncompressed data size\t\t\t\t\t   *\n;* Normal Shape:\t\t\t\t\t\t\t   *\n;*   UBYTE  [compressed] Shape data\t\t\t\t\t   *\n;* 16-color shape:\t\t\t\t\t\t\t   *\n;*   UBYTE  16-color table\t\t\t\t\t\t   *\n;*   UBYTE  [compressed] Shape data\t\t\t\t\t   *\n;* variable-color shape:\t\t\t\t\t\t   *\n;*   UBYTE  # colors\t\t\t\t\t\t\t   *\n;*   UBYTE  color table (variable-length)\t\t\t\t   *\n;*   UBYTE  [compressed] Shape data\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* Uncompressed shape data format:\t\t\t\t\t   *\n;* Data is stored as a bitmap, with 0's treated as a special case.  Every  *\n;* 0 byte is followed by a repetition count byte.  Every scan line is\t   *\n;* compressed separately.  Thus, the following bitmap results in the\t   *\n;* following shape data:\t\t\t\t\t\t   *\n;*\t0 0 0 5 6 7 0 0 0 0\t\t\t\t\t\t   *\n;*\t0 0 0 5 6 7 0 0 0 0\t\t\t\t\t\t   *\n;*\t0 0 0 5 6 7 0 0 0 0\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\t0 3 5 6 7 0 4\t\t\t\t\t\t\t   *\n;*\t0 3 5 6 7 0 4\t\t\t\t\t\t\t   *\n;*\t0 3 5 6 7 0 4\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* How scaling is handled:\t\t\t\t\t\t   *\n;*  Scaling is done by accumulating the x & y scale values.  When the high *\n;*  byte of the accumulated value is set, the pixel (for x-scaling) or\t   *\n;*  the line (for y-scaling) is drawn.  The high byte is then cleared,\t   *\n;*  and the low byte is left so roundoffs continue to accumulate.\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* Drawing Procedures:\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\n;*                                                                         *\n;*  RSkipRout: skips given # bytes of data on the right-hand side of a\t   *\n;*  shape.  Just has to handle changing the current byte offset in the \t   *\n;*  shape data buffer, since the draw routine knows where the left-hand\t   *\n;*  side of the drawable region is.  The routine may skip more bytes than  *\n;*  it was told if it encounters a run of 0's, but it's assumed that a\t   *\n;*  run of 0's will never go past the right edge of a shape.\t\t   *\n;*    Input:\t\t\t\t\t\t\t\t   *\n;*\t\tECX - number of uncompressed bytes to skip\t\t   *\n;*\t\tESI - shape buffer data address\t\t\t\t   *\n;*    Output:\t\t\t\t\t\t\t\t   *\n;* \t\tECX - negative # bytes overrun, or 0\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\n;*                                                                         *\n;*  LSkipRout: skips given # bytes of data on the left-hand side of a\t   *\n;*  shape.  This routine must update the shape data byte offset, and it\t   *\n;*  must properly update the current drawing position due to scaling, so   *\n;*  it's a little more involved than the RSkip routine.  The routine may   *\n;*  skip more bytes than it's told if it encounters a run of 0's.  If this *\n;*  happens, the draw routine must take these extra bytes into \t\t   *\n;*  consideration.\t\t\t\t\t\t\t   *\n;*    Input:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape (source) buffer data address\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = shape's width in bytes\t\t\t   *\n;*    Output:\t\t\t\t\t\t\t\t   *\n;* \t\tECX - negative # pixels (not bytes) overrun, or 0\t   *\n;*\t\tEDX - accumulated XTotal value at new pixel location\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) overrun\t\t   *\n;*\t\t[WidthCount] - decremented by # bytes skipped\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\n;*\t\t\t\t\t\t\t\t\t   *\n;*  DrawRout: draws one row of pixels, handles scaling, reversal and \t   *\n;*\t      any per pixel effects like predator, shadow etc.\t\t   *\n;*  EDX must be set up as follows:\t\t\t\t\t   *\n;*  - No scaling: 0\t\t\t\t\t\t\t   *\n;*  - No left-clipping: 0\t\t\t\t\t\t   *\n;*  - Left clipping, but no overrun: set to computed initial value for\t   *\n;*    that viewport coordinate\t\t\t\t\t\t   *\n;*  - Left clipping, with overrun: set to XTotal value for that coordinate *\n;*  In any case, only the low byte of DL should contain data; the current  *\n;*  byte in the shapebuffer should always be the first drawable pixel,\t   *\n;*  even if it's partially clipped (in which case DL will contain data).   *\n;*    Input:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of pixels (not bytes) to draw\t\t   *\n;*\t\tEDX = XTotal initializer value\t\t\t\t   *\n;*\t\tESI = shape (source) buffer address\t\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = remaining bytes on the line\t\t   *\n;*    Output:\t\t\t\t\t\t\t\t   *\n;*\t\tESI - updated to current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) drawn/skipped\t   *\n;*\t\t[WidthCount] - decremented by # bytes (not pixels) drawn   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* Algorithm:\t\t\t\t\t\t\t\t   *\n;* - Initialize globals\t\t\t\t\t\t\t   *\n;* - Pull optional arguments off the stack\t\t\t\t   *\n;* - Set up drawing procedure pointers based on drawing flags\t\t   *\n;* - Read the values from the shape header\t\t\t\t   *\n;* - Compute the shape's scaled width & height\t\t\t\t   *\n;* - Adjust the shape's drawing coordinates based on centering & \t   *\n;*   viewport-relative flag settings\t\t\t\t\t   *\n;* - Compute the clipped areas of the shape\t\t\t\t   *\n;* - Compute the number of drawn pixels horizontally & vertically\t   *\n;* - Compute the starting drawing offset in the viewport\t\t   *\n;* - Draw the shape\t\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/13/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   05/26/1994 BR  : Converted to 32-bit, restructured quite a bit.\t   *\n;*   08/09/1994 IML : Added C++ style interface. Various optimizations.\t   *\t\n;*   09/06/1994 IML : Ammendments for integration of p_* and ds_* routines.*\n;*   09/14/1994 IML : Now handles LCW compression.\t\t\t   *\t\t\n;*=========================================================================*\nPROC\tDraw_Shape C NEAR \t\n\tUSES eax,ebx,ecx,edx,edi,esi\n\n\t;--------------------------------------------------------------------\n\t; Arguments:\n\t;--------------------------------------------------------------------\n\tARG\tgvp_ptr:DWORD\t\t; pointer to graphic viewport info\n\tARG\tshape_ptr:DWORD\t\t; the shape pointer to draw\n\tARG\tdraw_x:DWORD\t\t; the destination x pixel\n\tARG\tdraw_y:DWORD\t\t; the destination y pixel\n\tARG\tflags:DWORD\t\t; the flags for drawing the shape\n\nIF FALSE\n\t;--------------------------------------------------------------------\n\t; Define the local stack variables that Draw_Shape needs. These \n\t; parameters are defined in shape.inc.  They're included here \n\t; just for reference.\n\t;--------------------------------------------------------------------\n\t;\n\t;...................... proc addresses ..............................\n\t;\n\tLOCAL\tLSkipRout:DWORD\t\t; pointer to the skip routine\n\tLOCAL\tRSkipRout:DWORD\t\t; pointer to the skip routine\n\tLOCAL\tDrawRout:DWORD\t\t; pointer to the draw routine\n\t;\n\t;.................... optional arguments ............................\n\t;\n\tLOCAL\tColorTable:DWORD\t; ptr to the shapes color table\n\tLOCAL\tFadingTable:DWORD\t; extracted fading table pointer\n\tLOCAL\tFadingNum:DWORD\t\t; get the number of times to fade\n\tLOCAL\tIsTranslucent:DWORD\t; ptr to \"are we translucent?\" tbl\n\tLOCAL\tTranslucent:DWORD\t; ptr to \"ok we are translucent!\" tbl\n\tLOCAL\tPriLevel:BYTE\t\t; the priority level of the object\n\tLOCAL\tScaleX:DWORD\t\t; the x increment to scale by\n\tLOCAL\tScaleY:DWORD\t\t; the y increment to scale by\n\tLOCAL\tShadowingTable:DWORD\t; ptr to the shadowing table\n\t;\n\t;.................... Shape header values ...........................\n\t;\n\tLOCAL\tShapeType:DWORD\t\t; shape type\n\tLOCAL\tShapeWidth:DWORD\t; shape's unscaled width\n\tLOCAL\tShapeHeight:DWORD\t; shape's unscaled height\n\tLOCAL\tUncompDataLen:DWORD\t; uncompressed data length\n\tLOCAL\tShapeData:DWORD\t\t; pointer to [compressed] shape data\n\t;\n\t;.................. Scaled shape dimensions .........................\n\t;\n\tLOCAL\tScaledWidth:DWORD\t; shape's scaled width\n\tLOCAL\tScaledHeight:DWORD\t; shape's scaled height\n\t;\n\t;.................. Pixel clipping variables ........................\n\t;\n\tLOCAL\tLeftClipPixels:DWORD\t; # left-clipped pixels\n\tLOCAL\tRightClipPixels:DWORD\t; # right-clipped pixels\n\tLOCAL\tTopClipPixels:DWORD\t; # top-clipped pixels\n\tLOCAL\tBotClipPixels:DWORD\t; # bottom-clipped pixels\n\tLOCAL\tPixelWidth:DWORD\t; width of drawable area in pixels\n\tLOCAL\tPixelHeight:DWORD\t; height of drawable area in pixels\n\t;\n\t;..................... Drawing variables ............................\n\t;\n\tLOCAL\tNumColors:DWORD\t\t; # colors for 16-color shapes\n\tLOCAL\tStartDraw:DWORD\t\t; ptr to starting draw position\n\tLOCAL\tNextLine:DWORD\t\t; offset of next drawing line\n\tLOCAL\tLeftClipBytes:DWORD\t; # left-clipped bytes\n\tLOCAL\tXTotal:DWORD\t\t; accumulated x-pixels for scaling\n\tLOCAL\tXTotalInit:DWORD\t; initial roundoff bits for XTotal\n\tLOCAL\tYTotal:DWORD\t\t; accumulated y-pixels for scaling\n\tLOCAL\tHeightCount:DWORD\t; height counter for drawing lines\n\tLOCAL\tLineStart:DWORD\t\t; address of start of line\n\tLOCAL\tWidthCount:DWORD\t; counts down # bytes skipped\n\tLOCAL\tStashReg:DWORD\t\t; temp variable for draw routines\n\tLOCAL\tMaskAdjust:DWORD\t; priority buffer offset\n\tLOCAL\tBackAdjust:DWORD\t; background buffer offset\n\tLOCAL\tStashECX:DWORD\t\t; temp variable for ECX register\n\tLOCAL\tStashEDX:DWORD\t\t; temp variable for EDX register\n\nENDIF\n\n\t;====================================================================\n\t; Initialization:\n\t; - allocate space for globals\n\t; - validate shape pointer\n\t; - set SHAPE_COMPACT flag if needed\n\t;====================================================================\n\t;--------------------------------------------------------------------\n\t; Allocate stack space for our local variables.\n\t;--------------------------------------------------------------------\n\tLOCAL\tLocal_Stack:BYTE:Local_Size\n\n\t;--------------------------------------------------------------------\n\t; Make sure the shape pointer is not NULL\n\t;--------------------------------------------------------------------\n\tcmp\t[shape_ptr],0\t\t\t; compare shape ptr value to NULL\n\tjnz\t??valid_shp\t\t\t; if non-zero, it's valid\n\tjmp\t??exit\t\t\t\t; otherwise get the heck outta here\n\n\t;--------------------------------------------------------------------\n\t; Move gvp info into local variables\n\t;--------------------------------------------------------------------\n??valid_shp:\n\tmov\tedi,[gvp_ptr]\t\t\t\t\t; get pointer to graphic viewport info\n\tmov\tesi, [(type GVPC_IMAGE  ptr edi). vvpc . Off ] ; extract viewport pointer\n\tmov\t[viewport_ptr],esi\n\tmov\tebx,[(type GVPC_IMAGE ptr edi) . vvpc . Width ]\t; extract viewport width\n\tmov\t[viewport_width],ebx\t\t\t\n\tmov\teax,[(type GVPC_IMAGE ptr edi) . vvpc . Height ]\t; extract viewport height\n\tmov\t[viewport_height],eax\t\t\t\t\n\tmov\tecx,[(type GVPC_IMAGE ptr edi) . vvpc . Page ]\t; calculate y add value\n\tadd\tecx,ebx\n\tmov\t[viewport_yadd],ecx\n\tmov\teax,[(type GVPC_IMAGE ptr edi) . Xpos ]\t\t; extract viewport x-coord\n\tmov\t[viewport_x],eax\n\tmov\teax, [(type GVPC_IMAGE ptr edi) . Ypos ]\t; extract viewport y-coord\n\tmov\t[viewport_y],eax\n\tmul\tecx\t\t\t\t; calculate buffer pointer\n\tadd\teax,[viewport_x]\n\tsub\tesi,eax\n\tmov\t[buff_ptr],esi\n\n\n\t;--------------------------------------------------------------------\n\t; If this shape is a compact shape, set that bit in the flags arg\n\t;--------------------------------------------------------------------\n\tmov\tedi,[shape_ptr]\t\t\t; check for compact shape flag\n\ttest\t[BYTE PTR edi],MAKESHAPE_COMPACT\t \n\t\t\t\t\t\t\t\n\tjz\t??do_args\t\t\t; if not process flags as is\n\tor\t[flags],SHAPE_COMPACT\t\t; mark it as a compact shape\n\n\t;====================================================================\n\t; Pull off optional arguments:\n\t; EDI is used as an offset from the 'flags' parameter, to point\n\t; to the optional argument currently being processed.\n\t;====================================================================\n??do_args:\n\tmov\tedi,4\t \t\t\t; optional params start past flags\n\n\t;--------------------------------------------------------------------\n\t; Initialize optional argument values:\n\t;--------------------------------------------------------------------\n\tmov\t[ColorTable],0\t\t\t; default = NULL\n\tmov\t[FadingTable],0\t\t\t; default = NULL\n\tmov\t[FadingNum],0\t\t\t; default = no fading\n\tmov\t[IsTranslucent],0\t\t; default = NULL\n\tmov\t[Translucent],0\t\t\t; default = NULL\n\tmov\t[PriLevel],0\t\t\t; default = no priority\n\tmov\t[ScaleX],100h\t\t\t; default = unity X scaling\n\tmov\t[ScaleY],100h\t\t\t; default = unity Y scaling\n\tmov\t[ShadowingTable],0\t\t; default = NULL\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_COLOR: DWORD color_table[256]\n\t;--------------------------------------------------------------------\n??color:\n\ttest\t[flags],SHAPE_COLOR \t\t; does it have a color table\n\tjz\t??fading \t\t\t; if not skip to fading \n\tor\t[flags],SHAPE_COMPACT\t\t; mark it as a compact shape\n\t\t\t\t\t\t;  (for remapping purposes only)\n\tmov\teax,[flags + edi]\n\tmov\t[ColorTable],eax\t\t; save address of color table\n\tadd\tedi,4\t\t\t\t; point to next optional argument\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_FADING: DWORD fade_table[256], DWORD fade_count\n\t;--------------------------------------------------------------------\n??fading:\n\ttest\t[flags],SHAPE_FADING\t\t; are we fading this shape\n\tjz\t??ghost\t\t\t\t; skip to ghosting check\n\tmov\teax,[flags + edi]\n\tmov\t[FadingTable],eax\t\t; save address of fading tbl\n\n\tmov\teax,[flags + edi + 4]\t\t; get fade num\n\n\tadd\tedi,8\t\t\t\t; next argument\n\tcmp\teax,0\t\t\t\t; check if it's 0\n\tjnz\t??set_fading\t\t\t; if not, store fade num\n\tand\t[flags],NOT SHAPE_FADING\t; otherwise, don't fade\n\n??set_fading:\n\tmov\t[FadingNum],eax\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_GHOST: DWORD is_translucent tbl, DWORD translucent tbl\n\t;--------------------------------------------------------------------\n??ghost:\n\ttest\t[flags],SHAPE_GHOST\t\t; are we ghosting this shape\n\tjz\t??init_predator\t\t\t; skip to predator check\n\tmov\teax,[flags + edi]\n\tmov\t[IsTranslucent],eax\t\t; save ptr to is_trans. tbl\n\tmov\teax,[flags + edi + 4]\n\tmov\t[Translucent],eax\t\t; save ptr to translucent tbl\n\tadd\tedi,8\t\t\t\t; next argument\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_PREDATOR: Initialize the predator effect variables\n\t;--------------------------------------------------------------------\n??init_predator:\n\ttest\t[flags],SHAPE_PREDATOR\t\t; is predator effect on\n\tjz\t??partial\t\t\t; if not skip to partial \n\tinc\t[PredCount]\t\t\t; the pred table is byte aligned\n\tand\t[PredCount],PRED_MASK\t\t; keep entries within bounds\n\tmov\teax,[PredCount]\t\t \n\tmov\tal,[BYTE PTR PredTable + eax]\n\tmov\t[PredValue],eax\t\t\t; put the pred value cs\n\tmov\t[PartialCount],0\t\t; clear the partial count\n\tmov\t[PartialPred],100h\t\t; init partial to off\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_PARTIAL: DWORD partial_pred_value (0-255)\n\t;--------------------------------------------------------------------\n??partial:\n\ttest\t[flags],SHAPE_PARTIAL\t\t; is this a partial pred?\n\tjz\t??priority\t\t\t; if not check priority\n\tmov\teax,[flags + edi]\t\t; pull the partial value\n\tmov\t[PartialPred],eax\t\t; store it off\n\tadd\tedi,4\t\t\t\t; next argument\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_PRIORITY: DWORD priority_level\n\t;--------------------------------------------------------------------\n??priority:\n\ttest\t[flags],SHAPE_PRIORITY\t\t; is this a priority draw\n\tjz\t??scale\t\t\t\t; if not skip to scale\n\tmov\teax,[flags + edi]\n\tmov\t[PriLevel],al\t\t\t; store priority level\n\tadd\tedi,4\t\t\t\t; next argument\n\tmov\teax,[MaskPage]\t\t\t; calculate priority buffer\n\tsub\teax,[buff_ptr]\t\t\t;  offset\n\tmov\t[MaskAdjust],eax\n\tmov\teax,[BackGroundPage]\t\t; calculate background buffer\n\tsub\teax,[buff_ptr]\t\t\t;  offset\n\tmov\t[BackAdjust],eax\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_SCALING: DWORD x_scale, WORD y_scale\n\t;--------------------------------------------------------------------\n??scale:\n\ttest\t[flags],SHAPE_SCALING\t\t; are we scaling this shape.\n\tjz\t??shadow\t\t\t; if not then skip scale y value\n\tmov\teax,[flags + edi]\t\n\tmov\t[ScaleX],eax\n\tmov\teax,[flags + edi + 4]\t\n\tmov\t[ScaleY],eax\n\tadd\tedi,8\t\t\t\t; next argument\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_SHADOW: DWORD shadow_table[256]\n\t;--------------------------------------------------------------------\n??shadow:\n\ttest\t[flags],SHAPE_SHADOW\t\t; are we ghosting this shape\n\tjz\tshort ??get_header\t\t; if not then skip\n\tmov\teax,[flags + edi]\n\tmov\t[ShadowingTable],eax\t\t; save address of shadow table \n\tadd\tedi,4\t\t\t\t; next argument\n\n\n??get_header:\t\n\t;====================================================================\n\t; Get Shape header values\n\t;====================================================================\n\tmov\tesi,[shape_ptr]\t\t\t; prepare to read header\n\tmovzx\teax,[WORD PTR esi]\n\tmov\t[ShapeType],eax\t\t\t; extract shape type\n\tmovzx\teax,[BYTE PTR esi + 2]\n\tmov\t[ShapeHeight],eax\n\tmovzx\teax,[WORD PTR esi + 3]\t\t; extract shape height\n\tmov\t[ShapeWidth],eax\n\tmovzx\teax,[WORD PTR esi + 8]\t\t; extract uncompressed data length\n\tmov\t[UncompDataLen],eax\n\tadd\tesi,10\t\t\t\t; reposition index\n\n\t;--------------------------------------------------------------------\n\t; Now get NumColors, ColorTable address, & data pointer:\n\t; <16-color shape:\n\t;   shape.Colortable[0] = # colors\n\t;   shape data is after that many colors\n\t; 16-color shape:\n\t;   shape.Colortable[] contains colors\n\t;   shape data is after those colors\n\t; default 256-color shape:\n\t;   shape data starts at shape.Colortable[0]\n\t; Note: ColorTable is set only if flags & SHAPE_COLOR is 0; otherwise,\n\t;   the color table was passed in & we already have a pointer to it\n\t;--------------------------------------------------------------------\n\t;\n\t;....................... <16-color shape: ...........................\n\t;\n\ttest\t[ShapeType],MAKESHAPE_VARIABLE\n\tjz\t??check_16\n\tmovzx\teax,[BYTE PTR esi]\t\t; read # colors\n\tmov\t[NumColors],eax\t\t\t; save # colors\n\tinc\tesi\n\ttest\t[flags],SHAPE_COLOR\t\t; don't set ColorTable if\n\tjnz\t??norm_get_data_addr\t\t;  it was passed in\n\tmov\t[ColorTable],esi\t\t; save color table pointer\n\n??norm_get_data_addr:\n\tadd\tesi,[NumColors]\t\t\t; skip past color data\n\tmov\t[ShapeData],esi\t\t\t; set data address\n\tjmp\t??setup_procs\n\n\t;....................... 16-color shape: ............................\n??check_16:\n\ttest\t[ShapeType],MAKESHAPE_COMPACT\n\tjz\t??256_get_data_addr\n\tmov\t[NumColors],16\t\t\t; save # colors\n\ttest\t[flags],SHAPE_COLOR\t\t; don't set ColorTable if\n\tjnz\t??16_get_data_addr\t\t;  it was passed in\n\tmov\t[ColorTable],esi\t\t; save color table pointer\n\n??16_get_data_addr:\n\tadd\tesi,[NumColors]\t\t\t; skip past color data\n\tmov\t[ShapeData],esi\t\t\t; set data address\n\tjmp\t??setup_procs\n\t;\n\t;....................... 256-color shape: ...........................\n\t;\n??256_get_data_addr:\n\tmov\t[ShapeData],esi\t\t\t; set data address\n\n\t;====================================================================\n\t; Set up the drawing procedure addresses\n\t;====================================================================\n\t;--------------------------------------------------------------------\n\t; This code uses HORZ_REV, VERT_REV, & SCALING flags as an \n\t; offset into the LSkipTable, RSkipTable, and DrawTable.  These\n\t; flags combined have values from 00h-07h, so each table must have\n\t; at least 8 entries.\n\t;--------------------------------------------------------------------\n??setup_procs:\n\tmov\tebx,[flags]\t\t; load flags value\n\tand\tebx,07h\t\t\t; clip high bits\n\tadd\tebx,ebx\t\t\t; mult by 4 to get DWORD offset\n\tadd\tebx,ebx\n\tmov\teax,[LSkipTable + ebx]\t; get table value\n\tmov\t[LSkipRout],eax\t\t; store it in the function pointer\n\tmov\teax,[RSkipTable + ebx]\t; get table value\n\tmov\t[RSkipRout],eax\t\t; store it in the function pointer\n\tmov\teax,[DrawTable + ebx]\t; get table value\n\tmov\t[DrawRout],eax\t\t; store it in the function pointer\n\n??compute_scalevals:\n\t;====================================================================\n\t; Now compute scaled width & height.  If the shape scales down to 0 \n\t; either horizontally or vertically, exit.\n\t;====================================================================\n\ttest\t[flags],SHAPE_SCALING\t; skip if no scaling\n\tjz\t??no_scaling\n\t;\n\t;........................ scaled width: .............................\n\t;\n\tmov\teax,[ShapeWidth]\t; get byte width\n\tmov\tebx,[ScaleX]\t\t; prepare for register mul\n\tmul\tebx\t\t\t; EDX:EAX = result\n\tshrd\teax,edx,8\t\t; EAX = result rounded down\n\tor\teax,eax\n\tjz\t??exit\t\t\t; exit if EAX is 0\n\tmov\t[ScaledWidth],eax\t; save the scaled width\n\t;\n\t;........................ scaled height: ............................\n\t;\n\tmov\teax,[ShapeHeight]\t; get byte height\n\tmov\tebx,[ScaleY]\t\t; prepare for register mul\n\tmul\tebx\t\t\t; EDX:EAX = result\n\tshrd\teax,edx,8\t\t; EAX = result rounded down\n\tor\teax,eax\n\tjz\t??exit\t\t\t; exit if EAX is 0\n\tmov\t[ScaledHeight],eax\t; save the scaled height\n\tjmp\t??handle_centering\n\t;\n\t;......................... no scaling: ..............................\n\t;\n??no_scaling:\n\tmov\teax,[ShapeWidth]\n\tmov\t[ScaledWidth],eax\t; pixel width = byte width\n\tmov\teax,[ShapeHeight]\n\tmov\t[ScaledHeight],eax\t; pixel height = byte height\n\n\t;====================================================================\n\t; Allow for SHAPE_CENTER by adjusting the draw_x & draw_y arguments:\n\t; draw_x -= ScaledWidth / 2\n\t; draw_y -= ScaledHeight / 2\n\t;====================================================================\n??handle_centering:\n\t;\n\t;........................ adjust draw_x .............................\n\t;\n\ttest\t[flags],SHAPE_CENTER\t; skip if not centered\n\tjz\t??handle_vp_rel\n\tmov\teax,[draw_x]\t\t; load in draw_x\n\tmov\tedx,[ScaledWidth]\t; load in ScaledWidth\n\tshr\tedx,1\t\t\t; divide it by 2\n\tsub\teax,edx\t\t\t; subract it from eax\n\tmov\t[draw_x],eax\t\t; store it back into draw_x\n\t;\n\t;........................ adjust draw_y .............................\n\t;\n\tmov\teax,[draw_y]\t\t; load in draw_y\n\tmov\tedx,[ScaledHeight]\t; load in ScaledHeight\n\tshr\tedx,1\t\t\t; divide it by 2\n\tsub\teax,edx\t\t\t; subract it from eax\n\tmov\t[draw_y],eax\t\t; store it back into draw_y\n\n\t;====================================================================\n\t; Allow for SHAPE_VIEWPORT_REL by adjusting draw_x & draw_y by the \n\t; viewport's coordinates\n\t;====================================================================\n??handle_vp_rel:\n\ttest\t[flags],SHAPE_VIEWPORT_REL\t; skip if not vp-relative\n\tjz\t??compute_horz_clip\n\tmov\teax,[viewport_x]\n\tadd\t[draw_x],eax\t\t\t; draw_x += viewport_x\n\tmov\teax,[viewport_y]\n\tadd\t[draw_y],eax\t\t\t; draw_y += viewport_y\n\n\t;====================================================================\n\t; Now that we have the scaled size and adjusted x & y drawing\n\t; coordinates, we can compute the clipped areas of the shape:\n\t;   LeftClipPixels =\tviewport_x - draw_x\n\t;\t- if negative, set to 0\n\t;   RightClipPixels =\t(draw_x + ScaledWidth) - \n\t;\t\t\t\t(viewport_x + viewport_width)\n\t;\t- if negative, set to 0\n\t;\n\t;   TopClipPixels =\tviewport_y - draw_y\n\t;\t- if negative, set to 0\n\t;   BotClipPixels =\t(draw_y + ScaledHeight) -\n\t;\t\t\t\t(viewport_y + viewport_height)\n\t;\t- if negative, set to 0\n\t;====================================================================\n??compute_horz_clip:\n\t;\n\t;...................... left-clipped pixels .........................\n\t;\n\tmov\teax,[viewport_x]\n\tsub\teax,[draw_x]\t\t; EAX = viewport_x - draw_x\n\tjge\t??set_left_clip\n\tmov\teax,0\t\t\t; if EAX<0, set to 0\n??set_left_clip:\n\tmov\t[LeftClipPixels],eax\t; store # left-clipped pixels\n\t;\n\t;...................... right-clipped pixels ........................\n\t;\n\tmov\teax,[draw_x]\n\tadd\teax,[ScaledWidth]\t; EAX = draw_x + ScaledWidth\n\tmov\tedx,[viewport_x]\n\tadd\tedx,[viewport_width]\t; EDX = viewport_x + viewport_width\n\tsub\teax,edx\n\tjge\t??set_right_clip\n\tmov\teax,0\t\t\t; if EAX<0, set to 0\n??set_right_clip:\n\tmov\t[RightClipPixels],eax\t; store # right-clipped pixels\n\t;\n\t;...................... top-clipped pixels ..........................\n\t;\n??compute_vert_clip:\n\tmov\teax,[viewport_y]\n\tsub\teax,[draw_y]\t\t; EAX = viewport_y - draw_y\n\tjge\t??set_top_clip\n\tmov\teax,0\t\t\t; if EAX<0, set to 0\n??set_top_clip:\n\tmov\t[TopClipPixels],eax\t; store # top-clipped pixels\n\t;\n\t;.................... bottom-clipped pixels .........................\n\t;\n\tmov\teax,[draw_y]\n\tadd\teax,[ScaledHeight]\t; EAX = draw_y + ScaledHeight\n\tmov\tedx,[viewport_y]\n\tadd\tedx,[viewport_height]\t; EDX = viewport_y + viewport_height\n\tsub\teax,edx\n\tjge\t??set_bottom_clip\n\tmov\teax,0\t\t\t; if EAX<0, set to 0\n??set_bottom_clip:\n\tmov\t[BotClipPixels],eax\t; store # bottom-clipped pixels\n\n\t;====================================================================\n\t; Now compute the number of pixels actually drawn, horizontally and\n\t; vertically; exit if either is <= 0\n\t;====================================================================\n??compute_drawn_pixels:\n\t;\n\t;.................... pixel width of drawn area .....................\n\t;\n\tmov\teax,[ScaledWidth]\t; get total width in pixels\n\tsub\teax,[LeftClipPixels]\t; subtract off left-clipped pixels\n\tsub\teax,[RightClipPixels]\t; subtract off right-clipped pixels\n\tjle\t??exit\t\t\t; exit if no horizontal pixels drawn\n\tmov\t[PixelWidth],eax\t; store drawn pixel width\n\t;\n\t;.................... pixel height of drawn area ....................\n\t;\n\tmov\teax,[ScaledHeight]\t; get total height in pixels\n\tsub\teax,[TopClipPixels]\t; subtract off top-clipped pixels\n\tsub\teax,[BotClipPixels]\t; subtract off bottom-clipped pixels\n\tjle\t??exit\t\t\t; exit if no horizontal pixels drawn\n\tmov\t[PixelHeight],eax\t; store drawn pixel height\n\n\t;====================================================================\n\t; So, we're actually going to draw something; if (ShapeType & \n\t; MAKESHAPE_NOCOMP == 0) decompress the shape data into _ShapeBuffer:\n\t; LCW_Uncompress(ShapeData, _ShapeBuffer, UncompDataLen);\n\t;\tshape.DataLength\n\t;\t&_ShapeBuffer\n\t;\t&(shape's data)\n\t; - otherwise the shape data is already uncompressed\n\t;====================================================================\n\ttest\t[ShapeType],MAKESHAPE_NOCOMP\n\tjnz\t??uncompressed\n\n\tmov\teax,[UncompDataLen]\n\tpush\teax\t\t\t; push arg 3\n\tmov\teax,[_ShapeBuffer]\n\tpush\teax\t\t\t; push arg 2\n\tmov\teax,[ShapeData]\n\tpush\teax\t\t\t; push arg 1\n\tcall\tLCW_Uncompress\t\t; call routine\n\tadd\tesp,12\t\t\t; restore stack\n\tmov\teax,[_ShapeBuffer]\n\tmov\t[ShapeData],eax\n\tjmp\t??copy_flags\n\n??uncompressed:\n;\tmov\teax,[ShapeData]\t\t; set up pointer to shape data\n;\tmov\t[_ShapeBuffer],eax\n\n\n\t;--------------------------------------------------------------------\n\t; Set the global Flags variable\n\t;--------------------------------------------------------------------\n??copy_flags:\n\tmov\teax,[flags]\n\tmov\t[Flags],eax\t\t\n\n\t;====================================================================\n\t; Now compute the actual buffer offset where drawing (not skipping)\n\t; will begin\n\t;====================================================================\n\t;--------------------------------------------------------------------\n\t; First, compute the x & y offsets of the shape's clipped upper-left \n\t; corner,  relative to the viewport's upper-left corner:\n\t; x-offset = draw_x + LeftClipPixels - viewport_x\n\t; y-offset = draw_y + TopClipPixels - viewport_y\n\t;--------------------------------------------------------------------\n\tmov\tebx,[draw_x]\n\tadd\tebx,[LeftClipPixels]\n\tsub\tebx,[viewport_x]\t; EBX = viewport x-offset\n\n\tmov\teax,[draw_y]\n\tadd\teax,[TopClipPixels]\n\tsub\teax,[viewport_y]\t; EAX = viewport y-offset\n\n\t;--------------------------------------------------------------------\n\t; Then, adjust the viewport offsets due to horizontal & vertical\n\t; reversal:\n\t; if HORZ_REV, x-offset += (PixelWidth - 1)\n\t; if VERT_REV, y-offset += (PixelHeight - 1)\n\t;--------------------------------------------------------------------\n\t;\n\t;................. Adjust for horizontal reversal ...................\n\t;\n\ttest\t[flags],SHAPE_HORZ_REV\n\tjz\t??adjust_vert_offset\n\tadd\tebx,[PixelWidth]\n\tdec\tebx\t\t\t; EBX = true x-offset\n\t;\n\t;................ Swap LeftClip & RightClip pixels ..................\n\t;\n\tmov\tedx,[LeftClipPixels]\t; exchange left & right-clipped pixels\n\txchg\tedx,[RightClipPixels]\n\tmov\t[LeftClipPixels],edx\n\n\t;\n\t;.................. Adjust for vertical reversal ....................\n\t;\n??adjust_vert_offset:\n\ttest\t[flags],SHAPE_VERT_REV\n\tjz\t??adjust_pointer\n\tadd\teax,[PixelHeight]\n\tdec\teax\t\t\t; EAX = true y-offset\n\t;\n\t;.................. Swap TopClip & BotClip pixels ...................\n\t;\n\tmov\tedx,[TopClipPixels]\n\txchg\tedx,[BotClipPixels]\n\tmov\t[TopClipPixels],edx\n\n\t;--------------------------------------------------------------------\n\t; Now, adjust the starting position pointer:\n\t;--------------------------------------------------------------------\n??adjust_pointer:\t;!!!!!!! convert to register mul for speed !!!!!!!!\n\tadd\tebx,[viewport_ptr]\t; add initial ptr to x-offset\n\tmul\t[viewport_yadd]\t\t; convert y-offset (EAX) to bytes\n\tadd\tebx,eax\t\t\t; add those bytes in\n\tmov\t[StartDraw],ebx\t\t; store the starting pointer\n\n\t;--------------------------------------------------------------------\n\t; Finally, if VERT_REV, negate yadd to move up not down:\n\t;--------------------------------------------------------------------\n\ttest\t[flags],SHAPE_VERT_REV\n\tjz\t??init_xtotal\n\tneg\t[viewport_yadd]\t\t; move up, not down\n\n\t;====================================================================\n\t; Initialize the horizontal scale accumulation value:\n\t;   If there are any left-clipped pixels, the scale accumulator will\n\t;   have to be initialized with the value it >would< have by stepping\n\t;   over that many pixels.  This initial value can be computed by\n\t;   dividing the # of left-clipped pixels by the x-scale value itself,\n\t;   picking off the remainder from this division & negating it.  This\n\t;   sets the low byte of the remainder to the correct accumulation\n\t;   value (the high bytes will be garbage).\n\t;   (The alternative to this approach would be to multiply the\n\t;   scale factor by the # clipped bytes, which is the result of the\n\t;   division; however, negating the remainder is much faster than\n\t;   the multiply would be.)\n\t;====================================================================\n??init_xtotal:\n\tmov\tedx,0\t\t\t; prepare for divide\n\tmov\teax,[LeftClipPixels]\t; get # left-clipped pixels\n\tshl\teax,8\t\t\t; multiply by 100h\n\tmov\tebx,[ScaleX]\t\t; load ScaleX value\n\tdiv\tbx\t\t\t; 16-bit div: AX = rslt, DX = rem\n\tmov\t[LeftClipBytes],eax\t; save # left-clipped bytes\n\tneg\tedx\t\t\t; generate roundoff bits\n\tand\tedx,0Fh\t\t\t; only save low byte\n\tmov\t[XTotalInit],edx\t; save initial roundoff value\n\n\t;====================================================================\n\t; Initialize drawing variables:\n\t;====================================================================\n\tmov\tesi,[ShapeData]\t\t; ESI = shape buffer starting point\n\tmov\tedi,[StartDraw]\t\t; EDI = drawing address\n\tmov\t[YTotal],0\t\t; initialize accumulated scale\n\n\t;====================================================================\n\t; Clip the top-clipped lines. The object here is to set ESI to the \n\t; first drawable line in the _ShapeBuffer, and YTotal to: \n\t;   high byte = # times to draw that line, \n\t;   low byte = roundoff bits\n\t;\n\t; - Initialize values (ESI, HeightCount, YTotal)\n\t; - Skip loop if no top lines to clip\n\t; - Loop:\n\t;   - save this line's byte position in _ShapeBuffer, in case we\n\t;     overrun\n\t;   - call RSkipRout with ECX set to # bytes to skip (one row)\n\t;   - accumulate ScaleY into YTotal\n\t;   - if high byte is non-zero, there are that many drawn lines:\n\t;     - decrement HeightCount by that many lines\n\t;     - clear the high byte in YTotal, but keep the roundoff bits\n\t;     - if HeightCount > 0, loop again to clip more lines\n\t;     - if HeightCount is 0, start drawing:\n\t;\t- ESI points to first non-clipped line in _ShapeBuffer\n\t;\t- YTotal contains 0 in high byte, roundoff bits in low byte\n\t;     - otherwise, we've clipped too many lines:\n\t;\t- put ESI back to the line we just clipped\n\t;\t- set high byte of YTotal to # lines overrun\n\t;\t- subtract ScaleY from YTotal, to set it up for drawing loop\n\t;====================================================================\n\t;\n\t;..................... skip if nothing to clip ......................\n\t;\n\tmov\teax,[TopClipPixels]\n\tcmp\teax,0\t\t\t; see if any top-clipped pixels\n\tjz\t??draw_loop\t\t; if not, skip this\n\tmov\t[HeightCount],eax\t; save off # lines to clip\n\n??clip_y_loop:\n\t;\n\t;...................... skip this row of bytes ......................\n\t;\n\tmov\t[LineStart],esi\t\t; save this line's byte position\n\tmov\tecx,[ShapeWidth]\t; set up ECX for RSkipRout\n\tcall\t[RSkipRout]\t\t; skip 'ShapeWidth' bytes\n\t;\n\t;............... see if this row would have been drawn ..............\n\t;\n\tmov\teax,[ScaleY]\n\tadd\t[YTotal],eax\t\t; accumulate scale factor\n\ttest\t[YTotal],0FF00h\t\t; check to see if we draw the line\n\tjz\t??clip_y_loop\t\t; if not loop again\n\t;\n\t;...................... decrement HeightCount .......................\n\t;\n\tmov\teax,0\t\t\t; clear EAX\n\txchg\tal,[BYTE PTR YTotal+1]\t; get # lines, clear it in YTotal\n\tsub\t[HeightCount],eax\t; subtract # drawn lines from HtCt\n\tjg\t??clip_y_loop\t\t; if more lines remain, loop again\n\tjns\t??draw_loop\t\t; is exactly 0; we're done clipping\n\t;\n\t;....................... adjust for overrun .........................\n\t;\n\tmov\tesi,[LineStart]\t\t; point ESI back to this line\n\tmov\teax,[HeightCount]\n\tneg\teax\t\t\t; EAX = # lines overrun\n\tshl\teax,8\t\t\t; multiply by 100h\n\tadd\teax,[YTotal]\t\t; add in roundoff bits\n\tsub\teax,[ScaleY]\t\t; adjust down by y-scale\n\tmov\t[YTotal],eax\t\t; store in YTotal\n\n\t;====================================================================\n\t; The drawing loop (at long last!):\n\t; - Accumulate YTotal; if high byte is 0, skip this row of bytes & \n\t;   loop again\n\t; - Skip left-clipped pixels:\n\t;   - If we've skipped all the bytes on the line, just go to the\n\t;     next line\n\t; - Draw middle pixels:\n\t;   - Add the shape's pixel width to ECX (which could be negative \n\t;     if we left-skipped into the drawable area)\n\t;   - If ECX is still 0, there are no pixels to draw\n\t;   - Otherwise, leave ECX as is & draw the pixels\n\t; - Skip right-clipped pixels:\n\t;   - Add # right-clipped pixels to ECX (which could be negative if\n\t;     the draw routine  uncompressed 0's into the right-clipped \n\t;     region)\n\t;   - if ECX > 0, skip the remaining bytes\n\t; - Go to the next line:\n\t;   - point EDI to the start of the next line in the viewport\n\t;   - decrement the height counter, exit if it's 0\n\t;   - decrement YTotal's high byte\n\t;     - if it's 0, go to the loop top\n\t;     - otherwise, reset ESI to this line's start & redraw the line,\n\t;       starting at left-clipped pixels\n\t;       (NOTE: why not start drawing at middle pixels??????????)\n\t;====================================================================\n??draw_loop:\n\t;\n\t;................... accumulate YTotal & test it ....................\n\t;\n\tmov\teax,[ScaleY]\t\t; get y scaling factor\n\tadd\t[YTotal],eax\t\t; accumulate YTotal\n\ttest\t[YTotal],0FF00h\t\t; see if we need to draw anything\n\tjnz  \t??draw_line\t\t; draw this line\n\t;\n\t;......................... skip this line ...........................\n\t;\n\tmov\tecx,[ShapeWidth]\t; load shape's width in bytes\n\tcall\t[RSkipRout]\t\t; skip this row & loop again\n\tjmp\t??draw_loop\n\n\t;\n\t;--------------------- start drawing this line ----------------------\n\t;\n??draw_line:\n\tmov\t[LineStart],esi\t\t; save current byte position\n\t;....................................................................\n\t; Skip left-clipped pixels:\n\t; - initialize [WidthCount] to total shape width in bytes\n\t; - set ECX to # >bytes< to clip\n\t; When LSkipRout returns: \n\t;\t- ECX will contain # >pixels< overrun\n\t;\t- EDX will contain the XTotal init value\n\t;\t- [WidthCount] will be decremented by total bytes skipped\n\t;....................................................................\n??draw_left:\n\tmov\teax,[ShapeWidth]\t; load shape width\n\tmov\t[WidthCount],eax\t; set up for LSkipRout\n\tmov\tecx,[LeftClipBytes]\t; bytes, not pixels!\n\tcall\t[LSkipRout]\t\t; skip the bytes\n\tcmp\t[WidthCount],0\n\tjz\t??next_line\t\t; The whole line was 0's\n\t;....................................................................\n\t; Draw middle pixels:\n\t; - add PixelWidth to ECX (which may be negative)\n\t; - if ECX is 0, don't bother drawing\n\t; When DrawRout returns:\n\t;\t- ECX will contain # >pixels< overrun\n\t;\t- [WidthCount] will be decremented by # bytes drawn\n\t;....................................................................\n??draw_middle:\n\tadd\tecx,[PixelWidth]\t; since ECX could overrun, add width\n\tjle\t??draw_right\t\t; if ECX<=0, no middle pixels to draw\n\tcall\t[DrawRout]\t\t; draw the pixels\n\t;\n\t;................... skip past right-clipped pixels .................\n\t;\n??draw_right:\n\tmov\tecx,[WidthCount]\t; ECX = remaining # bytes\n\tjecxz\t??next_line\t\t; don't bother if no bytes remain\n\tcall\t[RSkipRout]\t\t; skip right-clipped bytes\n\t;\n\t;----------------------- go to the next line ------------------------\n\t;\n??next_line:\n\t;\n\t;................. adjust EDI to start of next line .................\n\t;\n\tmov\teax,[viewport_yadd]\t; get yadd\n\tadd\t[StartDraw],eax\t\t; add it to this line's position\n\tmov\tedi,[StartDraw]\t\t; EDI = next line\n\t;\n\t;................. decrement our pixel row counter ..................\n\t;\n\tdec\t[PixelHeight]\t\t; count down a line\n\tjz\t??exit\t\t\t; we're done!\n\t;\n\t;.................. decrement YTotal's high byte ....................\n\t;\n\tdec\t[BYTE PTR YTotal + 1]\t; decrement high byte\n\tjz\t??draw_loop\t\t; draw next line if 0\n\t;\n\t;....................... re-draw this line ..........................\n\t;\n\tmov\tesi,[LineStart]\t\t; reset to this line's start\n\tjmp\t??draw_left\t\t; redraw this line\n\n??exit:\n\tret\n\n\tENDP\tDraw_Shape\n\n\n;***************************************************************************\n;* Not_Supported -- Replacement function for Draw_Shape routines not used. *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*\tnone.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*\tnone.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*\tnone.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/24/1993 SKB : Created.                                             *\n;*=========================================================================*\nPROC\tNot_Supported NOLANGUAGE NEAR\n\n\tret\n\n\tENDP Not_Supported \n\n\tEND\n\n;************************** End of drawshp.asm *****************************\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SHAPE/DS_DN.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_DN.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : September 6, 1994   [IML]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Draw_Normal -- Draws a normal row of pixels to the viewport           *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Draw_Normal -- Draws a normal row of pixels to the viewport             *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of pixels (not bytes) to draw\t\t   *\n;*\t\tEDX = XTotal initializer value\t\t\t\t   *\n;*\t\tESI = shape (source) buffer address\t\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = remaining bytes on the line\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;*\t\tESI - updated to current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) drawn/skipped\t   *\n;*\t\t[WidthCount] - bytes remaining on the line\t\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR  : Converted to 32-bit.\t\t\t\t   *\n;*   08/09/1994 IML : Optimized for 32-bit.                                *\n;*   09/06/1994 IML : Integrated p_* and ds_* routines.\t\t\t   *\n;*=========================================================================*\nPROC\tDraw_Normal NOLANGUAGE NEAR\n\n\tmov\t[StashEDX],edx\t\t\t; save edx\n\tmov\tedx,[Flags]\n\tmov\teax,0\t\t\t\t; init to zero\n\tsub\t[WidthCount],ecx\t\t; decrement bytes remaining by pixels\n\t\t\t\t\t\t;   to draw\n\t\t\t\t\t\t\n\t;--------------------------------------------------------------------\n\t; Drawing Loop:\n\t; - Get a data byte\n\t; - If it's a 0, handle the run:\n\t;\t- get repetition value\n\t;\t- add it to EDI\n\t;\t- subtract it from [WidthCount]\n\t;\t- subtract it from ECX\n\t;\t- if ECX>0, draw again, else exit\n\t; - Otherwise:\n\t;\t- draw the pixel\n\t;\t- increment EDI to next pixel location\n\t;\t- decrement [WidthCount]\n\t;\t- loop until ECX is 0\n\t;--------------------------------------------------------------------\n\ttest\tedx,SHAPE_EFFECTS\t\t; are any effects flags set?\n\tjnz\tshort ??general_draw_continue\t;   if so use the general purpose loop\n\n\n\t;--------------------------------------------------------------------\n\t; Extra fast draw loop for shapes with no flags set.\n\t;--------------------------------------------------------------------\n??fast_draw_loop:\n\tmov\tal,[esi]\t\t\t; get a byte of the source\n\tinc\tesi\n\tor\teax,eax\t\t\t\t; is the byte a transparent run?\n\tjz\tshort ??fast_is_run\t\t;   if yes then handle the run\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\tinc\tedi\t\t\t\t; point to next viewport pixel\n\tdec\tecx\t\t\t\t; any source pixels left?\n\tjnz\tshort ??fast_draw_loop\t\t;   if not then go home\n\tjmp\t??out\n\n??fast_is_run:\n\tmov\tal,[esi]\n\tinc\tesi\n\tadd\tedi,eax\t\t\t\t; move the viewport pointer\n\tsub\tecx,eax\t\t\t\t; chop down the width to do\n\tjg\tshort ??fast_draw_loop\t\t; while more to do, loop back up\n\tjmp\t??out\n\n\n\t;--------------------------------------------------------------------\n\t; General purpose draw loop for shapes with one or more flags set.\n\t;--------------------------------------------------------------------\n??general_draw_loop:\n\ttest\tedx,SHAPE_FADING\t\t; if fading is enabled test for\n\tjz\tshort ??no_fading_draw_loop\t;   transparency\n\tor\teax,eax\n\tjz\tshort ??is_transparent\n\n??no_fading_draw_loop:\t\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\n??is_transparent:\n\tinc\tedi\t\t\t\t; point to next viewport pixel\n\tdec\tecx\t\t\t\t; any source pixels left?\n\tjz\t??out\t\t\t\t;   if not then go home\n\n??general_draw_continue:\n\tmov\tal,[esi]\t\t\t; get a byte of the source\n\tinc\tesi\n\tor\teax,eax\t\t\t\t; is the byte a transparent run?\n\tjz\t??general_is_run\t\t;   if yes then handle the run\n\t\n??test_priority:\n\ttest\tedx,SHAPE_PRIORITY\t\t\n\tjnz\tshort ??priority\n\n??test_predator:\n\ttest\tedx,SHAPE_PREDATOR\n\tjnz\tshort ??predator\n\n??test_compact:\n\ttest\tedx,SHAPE_COMPACT\n\tjnz\t??compact\n\n??test_shadow:\n\ttest\tedx,SHAPE_SHADOW\n\tjnz\t??shadow\n\n??test_translucency:\n\ttest\tedx,SHAPE_GHOST\n\tjz\tshort ??test_fading\n\n\tmov\tebx,[IsTranslucent]\t\t; is it a translucent color?\n\tmov\tbh,[BYTE PTR ebx + eax]\n\tor\tbh,bh\n\tjs\tshort ??test_fading\n\n\tand\tebx,0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tmov\tal,[edi]\t\t\t; mov pixel at destination to al\n\tadd\tebx,[Translucent]\t\t; get the ptr to it!\n\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; get new pixel in al\n\tjmp\tshort ??test_fading\n\n??test_fading:\n\ttest\tedx,SHAPE_FADING\n\tjnz\t??fading\n\tjmp\tshort ??general_draw_loop\n\n??priority:\t\n\tmov\tebx,[MaskAdjust]\t\t; get mask page\toffset\n\tmov\tbl,[BYTE PTR ebx + edi]\t\t; get mask value  \n\n\tand\tbl,CLEAR_UNUSED_BITS\t\t; clear unused bits\n\n\tcmp\t[PriLevel],bl\t\t\t; are we in front of\n\tjge\tshort ??test_predator\t\t;  background?\n\n\tmov\tebx,[BackAdjust]\t\t; get background page offset\n\tmov\tal,[BYTE PTR ebx + edi]\t\t; get background pixel\n\tjmp\t??general_draw_loop\n\n??predator:\n\tmov\tebx,[PartialCount]\n\tadd\tebx,[PartialPred]\t\n\tor\tbh,bh\n\tjnz\tshort ??draw_pred\t\t; is this a predator pixel?\n\tmov\t[PartialCount],ebx\n\tjmp\tshort ??test_compact\n\n??draw_pred:\n\txor\tbh,bh\n\tmov\t[PartialCount],ebx\n\tmov\tebx,[PredValue]\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\tmov\tal,[edi + ebx]\t\t\t;  viewport address\n\tjmp\t??general_draw_loop\n\n??compact:\n\tmov\tebx,[ColorTable]\t\t; get the address of the color table\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; convert it into the proper byte\n\tjmp\t??test_shadow\n\n??shadow:\n\tcmp\tal,SHADOW_COL\n\tjne\t??test_translucency\t\t; is the table value a magic number?\n\n\tmov\tal,[edi]\t\t\t; get the destination color and\n\tmov\tebx,[ShadowingTable]\t\t;  index into the shadow table\n\tmov\tal,[BYTE PTR ebx + eax]\n\tjmp\t??general_draw_loop\t\t\t\n\n??fading:\n\tmov\t[StashECX],ecx\t\t\t; preserve ecx for later\n\tmov\tebx,[FadingTable]\t\t; run color through fading table\n\tmov\tecx,[FadingNum]\n\n??fade_loop:\n\tmov\tal, [BYTE PTR ebx + eax]\n\tdec\tecx\n\tjnz\tshort ??fade_loop\n\n\tmov\tecx,[StashECX]\t\t\t; restore ecx for main draw loop\n\tjmp\t??general_draw_loop\t\t\t\n\n??general_is_run:\n\tmov\tal,[esi]\n\tinc\tesi\n\tadd\tedi,eax\t\t\t\t; move the viewport pointer\n\tsub\tecx,eax\t\t\t\t; chop down the width to do\n\tjg\t??general_draw_continue\t\t; while more to do, loop back up\n\n??out:\t\n\tadd\t[WidthCount],ecx\t\t; adjust for source ending in a run\n\tmov\tedx,[StashEDX]\n\tret\t\n\n\tENDP\tDraw_Normal\n\n\tEND\n\n;**************************** End of ds_dn.asm *****************************\n"
  },
  {
    "path": "WIN32LIB/SHAPE/DS_DR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_DR.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : September 6, 1994   [IML]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Draw_Reverse -- Draws a reversed row of pixels to the viewport        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Draw_Reverse -- Draws a reversed row of pixels to the viewport          *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of pixels (not bytes) to draw\t\t   *\n;*\t\tEDX = XTotal initializer value\t\t\t\t   *\n;*\t\tESI = shape (source) buffer address\t\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = remaining bytes on the line\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;*\t\tESI - updated to current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) drawn/skipped\t   *\n;*\t\t[WidthCount] - bytes remaining on the line\t\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR  : Converted to 32-bit.\t\t\t\t   *\t\n;*   08/09/1994 IML : Optimized for 32-bit.\t\t\t\t   *\n;*   09/06/1994 IML : Integrated p_* and ds_* routines.\t\t\t   *\n;*=========================================================================*\nPROC\tDraw_Reverse NOLANGUAGE NEAR\n\n\tmov\t[StashEDX],edx\t\t\t; save edx\n\tmov\tedx,[Flags]\t\t\t\n\tmov\teax,0\t\t\t\t; init to zero\n\tsub\t[WidthCount],ecx\t\t; decrement bytes remaining by pixels\n\t\t\t\t\t\t;   to draw\n\n\t;--------------------------------------------------------------------\n\t; Drawing Loop:\n\t; - Get a data byte\n\t; - If it's a 0, handle the run:\n\t;\t- get repetition value\n\t;\t- subtract it from EDI\n\t;\t- subtract it from [WidthCount]\n\t;\t- subtract it from ECX\n\t;\t- if ECX>0, draw again, else exit\n\t; - Otherwise:\n\t;\t- draw the pixel\n\t;\t- increment EDI to next pixel location\n\t;\t- decrement [WidthCount]\n\t;\t- loop until ECX is 0\n\t;--------------------------------------------------------------------\n\ttest\tedx,SHAPE_EFFECTS\t\t; are any effects flags set?\n\tjnz\tshort ??general_draw_continue\t;   if so use the general purpose loop\n\n\n\t;--------------------------------------------------------------------\n\t; Extra fast draw loop for shapes with no flags set.\n\t;--------------------------------------------------------------------\n??fast_draw_loop:\n\tmov\tal,[esi]\t\t\t; get a byte of the source\n\tinc\tesi\n\tor\teax,eax\t\t\t\t; is the byte a transparent run?\n\tjz\tshort ??fast_is_run\t\t;   if yes then handle the run\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\tdec\tedi\t\t\t\t; point to next viewport pixel\n\tdec\tecx\t\t\t\t; any source pixels left?\n\tjnz\tshort ??fast_draw_loop\t\t;   if not then go home\n\tjmp\t??out\n\n??fast_is_run:\n\tmov\tal,[esi]\n\tinc\tesi\n\tsub\tedi,eax\t\t\t\t; move the viewport pointer\n\tsub\tecx,eax\t\t\t\t; chop down the width to do\n\tjg\tshort ??fast_draw_loop\t\t; while more to do, loop back up\n\tjmp\t??out\n\n\n\t;--------------------------------------------------------------------\n\t; General purpose draw loop for shapes with one or more flags set.\n\t;--------------------------------------------------------------------\n??general_draw_loop:\n\ttest\tedx,SHAPE_FADING\t\t; if fading is enabled test for\n\tjz\tshort ??no_fading_draw_loop\t;   transparency\n\tor\teax,eax\n\tjz\tshort ??is_transparent\n\n??no_fading_draw_loop:\t\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\n??is_transparent:\n\tdec\tedi\t\t\t\t; point to next viewport pixel\n\tdec\tecx\t\t\t\t; any source pixels left?\n\tjz\t??out\t\t\t\t;   if not then go home\n\n??general_draw_continue:\n\tmov\tal,[esi]\t\t\t; get a byte of the source\n\tinc\tesi\n\tor\teax,eax\t\t\t\t; is the byte a transparent run?\n\tjz\t??general_is_run\t\t;   if yes then handle the run\n\t\n??test_priority:\n\ttest\tedx,SHAPE_PRIORITY\t\t\n\tjnz\tshort ??priority\n\n??test_predator:\n\ttest\tedx,SHAPE_PREDATOR\n\tjnz\tshort ??predator\n\n??test_compact:\n\ttest\tedx,SHAPE_COMPACT\n\tjnz\t??compact\n\n??test_shadow:\n\ttest\tedx,SHAPE_SHADOW\n\tjnz\t??shadow\n\n??test_translucency:\n\ttest\tedx,SHAPE_GHOST\n\tjz\tshort ??test_fading\n\n\tmov\tebx,[IsTranslucent]\t\t; is it a translucent color?\n\tmov\tbh,[BYTE PTR ebx + eax]\n\tor\tbh,bh\n\tjs\tshort ??test_fading\t\t\n\n\tand\tebx,0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tmov\tal,[edi]\t\t\t; mov pixel at destination to al\n\tadd\tebx,[Translucent]\t\t; get the ptr to it!\n\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; get new pixel in al\n\n??test_fading:\n\ttest\tedx,SHAPE_FADING\n\tjnz\t??fading\n\tjmp\tshort ??general_draw_loop\n\n??priority:\t\n\tmov\tebx,[MaskAdjust]\t\t; get mask page\toffset\n\tmov\tbl,[BYTE PTR ebx + edi]\t\t; get mask value  \n\n\tand\tbl,CLEAR_UNUSED_BITS\t\t; clear unused bits\n\n\tcmp\t[PriLevel],bl\t\t\t; are we in front of\n\tjge\tshort ??test_predator\t\t;  background?\n\n\tmov\tebx,[BackAdjust]\t\t; get background page offset\n\tmov\tal,[BYTE PTR ebx + edi]\t\t; get background pixel\n\tjmp\t??general_draw_loop\n\n??predator:\n\tmov\tebx,[PartialCount]\n\tadd\tebx,[PartialPred]\t\n\tor\tbh,bh\n\tjnz\tshort ??draw_pred\t\t; is this a predator pixel?\n\tmov\t[PartialCount],ebx\n\tjmp\tshort ??test_compact\n\n??draw_pred:\n\txor\tbh,bh\n\tmov\t[PartialCount],ebx\n\tmov\tebx,[PredValue]\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\tmov\tal,[edi + ebx]\t\t\t;  viewport address\n\tjmp\t??general_draw_loop\n\n??compact:\n\tmov\tebx,[ColorTable]\t\t; get the address of the color table\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; convert it into the proper byte\n\tjmp\t??test_shadow\n\n??shadow:\n\tcmp\tal,SHADOW_COL\n\tjne\t??test_translucency\t\t; is the table value a magic number?\n\n\tmov\tal,[edi]\t\t\t; get the destination color and\n\tmov\tebx,[ShadowingTable]\t\t;  index into the shadow table\n\tmov\tal,[BYTE PTR ebx + eax]\n\tjmp\t??general_draw_loop\t\t\t\n\n??fading:\n\tmov\t[StashECX],ecx\t\t\t; preserve ecx for later\n\tmov\tebx,[FadingTable]\t\t; run color through fading table\n\tmov\tecx,[FadingNum]\n\n??fade_loop:\n\tmov\tal, [BYTE PTR ebx + eax]\n\tdec\tecx\n\tjnz\tshort ??fade_loop\n\n\tmov\tecx,[StashECX]\t\t\t; restore ecx for main draw loop\n\tjmp\t??general_draw_loop\t\t\t\n\n??general_is_run:\n\tmov\tal,[esi]\n\tinc\tesi\n\tsub\tedi,eax\t\t\t\t; move the viewport pointer\n\tsub\tecx,eax\t\t\t\t; chop down the width to do\n\tjg\t??general_draw_continue\t\t\t; while more to do, loop back up\n\n??out:\t\n\tadd\t[WidthCount],ecx\t\t; adjust for source ending in a run\n\tmov\tedx,[StashEDX]\n\tret\t\n\n\tENDP\tDraw_Reverse\n\n\n\tEND\n\n;**************************** End of ds_dr.asm *****************************\n"
  },
  {
    "path": "WIN32LIB/SHAPE/DS_DS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_DS.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : September 6, 1994   [IML]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Draw_Scale -- Draws a scaled row of pixels to the viewport            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Draw_Scale -- Draws a scaled row of pixels to the viewport              *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of pixels (not bytes) to draw\t\t   *\n;*\t\tEDX = XTotal initializer value\t\t\t\t   *\n;*\t\tESI = shape (source) buffer address\t\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = remaining bytes on the line\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;*\t\tESI - updated to current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) drawn/skipped\t   *\n;*\t\t[WidthCount] - bytes remaining on the line\t\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR  : Converted to 32-bit.                                 *\n;*   08/09/1994 IML : Optimized for 32-bit.\t\t\t\t   *\n;*   09/06/1994 IML : Integrated p_* and ds_* routines.\t\t\t   *\n;*=========================================================================*\nPROC\tDraw_Scale NOLANGUAGE NEAR\n\n\tmov\teax,0\t\t\t\t; init to 0\n\ttest\t[Flags],SHAPE_EFFECTS\n\tjnz\tshort ??general_draw_continue\n\tjmp\tshort ??fast_draw_continue\n\n\n\t;--------------------------------------------------------------------\n\t; Extra fast draw loop for shapes with no flags set.\n\t;--------------------------------------------------------------------\n\t\n\t;--------------------------------------------------------------------\n\t; Load a new byte:\n\t; - read the byte into AL\n\t; - if it's a run, deal with it\n\t; - otherwise, \n\t;\t- decrement [WidthCount]\n\t;\t- update EDX with [ScaleX]\n\t;\t- see if it's drawable (upon proc entry, it won't be)\n\t;\t\t- yes: draw a pixel\n\t;\t\t- no : load a new byte\n\t;--------------------------------------------------------------------\n??fast_draw_loop:\n\tmov\tal,[esi]\t\t\t; get the next pixel from the source\n\tinc\tesi\n\tor\teax,eax\n\tjz\tshort ??fast_is_run\t\t; deal with a run\n\tdec\t[WidthCount]\t\t\t; count down # bytes processed\n\tadd\tedx,[ScaleX]\t\t\t; add in the scale value\n\n??fast_draw_continue:\n\tor\tdh,dh\t\t\t\t; are there any pixels to draw?\n\tjz\tshort ??fast_draw_loop\n\n\n\t;--------------------------------------------------------------------\n\t; Draw one pixel:\n\t; - draw the pixel\n\t; - increment destination pointer\n\t; - decrement high byte of EDX (X-scale accumulator)\n\t; - loop (while ECX>0) to see if it's drawable\n\t;--------------------------------------------------------------------\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\tinc\tedi\t\t\t\t; increment the destination index\n\tdec\tdh\t\t\t\t; decrement the pixels to write\n\tdec\tecx\n\tjnz\tshort ??fast_draw_continue\n\tjmp\t??out\t\t\t\t; get the heck outta here\n\n\n\t;--------------------------------------------------------------------\n\t; Handle a run:\n\t; - Get the run repetition value\n\t; - subract it from [WidthCount]\n\t; - multiply it by [ScaleX]\n\t; - put high bytes from mul into EAX, low byte into DL (roundoff bits)\n\t; - add high bytes (# pixels) to EDI\n\t; - subtract them from ECX\n\t; - clear EAX\n\t; - if ECX>0, go get next byte\n\t;--------------------------------------------------------------------\n??fast_is_run:\n\tmov\tal,[esi]\t\t\t; get number of repeated values\n\tinc\tesi\n\tsub\t[WidthCount],eax\t\t; adjust the remaining byte width\n\tmov\tebx,edx\t\t\t\t; preserve dx for the multiply\n\tmul\t[ScaleX]\t\t\t; EDX:EAX = # pixels + roundoff bits\n\tadd\teax,ebx\t\t\t\t; add in the current x-total\n\tmov\tedx,eax\t\t\t\t; (assume EDX is empty)\n\tshr\teax,8\t\t\t\t; EAX = # pixels skipped\n\tand\tedx,00FFh\t\t\t; keep only low byte\n\tadd\tedi,eax\t\t\t\t; add to EDI\n     \tsub\tecx,eax\t\t\t\t; subtract it from ECX\n\tmov\teax,0\t\t\t\t; clear EAX\n\tor\tecx,ecx\n\tjg\tshort ??fast_draw_loop\t\t; if more to draw, process new byte\n\tjmp\t??out\n\n\n\t;--------------------------------------------------------------------\n\t; General purpose draw loop for shapes with one or more flags set.\n\t;--------------------------------------------------------------------\n\n\t;--------------------------------------------------------------------\n\t; Load a new byte:\n\t; - read the byte into AL\n\t; - if it's a run, deal with it\n\t; - otherwise, \n\t;\t- decrement [WidthCount]\n\t;\t- update EDX with [ScaleX]\n\t;\t- see if it's drawable (upon proc entry, it won't be)\n\t;\t\t- yes: draw a pixel\n\t;\t\t- no : load a new byte\n\t;--------------------------------------------------------------------\n??general_draw_loop:\n\tmov\tal,[esi]\t\t\t; get the next pixel from the source\n\tinc\tesi\n\tor\teax,eax\n\tjz\t??general_is_run\t\t; deal with a run\n\tdec\t[WidthCount]\t\t\t; count down # bytes processed\n\tadd\tedx,[ScaleX]\t\t\t; add in the scale value\n\n??general_draw_continue:\n\tor\tdh,dh\t\t\t\t; are there any pixels to draw?\n\tjz\tshort ??general_draw_loop\n\n\t;--------------------------------------------------------------------\n\t; Draw one pixel:\n\t; - draw the pixel\n\t; - increment destination pointer\n\t; - decrement high byte of EDX (X-scale accumulator)\n\t; - loop (while ECX>0) to see if it's drawable\n\t;--------------------------------------------------------------------\n??draw:\n\tmov\t[StashReg],eax\t\t\t; save eax\n\tmov\t[StashEDX],edx\t\t\t; save edx\n\tmov\tedx,[Flags]\n\n??test_priority:\n\ttest\tedx,SHAPE_PRIORITY\t\t\n\tjnz\tshort ??priority\n\n??test_predator:\n\ttest\tedx,SHAPE_PREDATOR\n\tjnz\tshort ??predator\n\n??test_compact:\n\ttest\tedx,SHAPE_COMPACT\n\tjnz\t??compact\n\n??test_shadow:\n\ttest\tedx,SHAPE_SHADOW\n\tjnz\t??shadow\n\n??test_translucency:\n\ttest\tedx,SHAPE_GHOST\n\tjnz\t??translucency\n\n??test_fading:\n\ttest\tedx,SHAPE_FADING\n\tjnz\t??fading\n\n\n??test_transparency:\t\n\ttest\tedx,SHAPE_FADING\t\t; if fading is enabled test for\n\tjz\tshort ??no_fading_draw_loop\t;   transparency\n\tor\teax,eax\n\tjz\tshort ??is_transparent\n\n??no_fading_draw_loop:\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\t\n??is_transparent:\n\tmov\teax,[StashReg]\t\t\t; restore eax\n\tmov\tedx,[StashEDX]\t\t\t; restore edx\n\tinc\tedi\t\t\t\t; increment the destination index\n\tdec\tdh\t\t\t\t; decrement the pixels to write\n\tdec\tecx\n\tjnz\t??general_draw_continue\n\tjmp\t??out\t\t\t\t; get the heck outta here\n\n??priority:\t\n\tmov\tebx,[MaskAdjust]\t\t; get mask page\toffset\n\tmov\tbl,[BYTE PTR ebx + edi]\t\t; get mask value  \n\n\tand\tbl,CLEAR_UNUSED_BITS\t\t; clear unused bits\n\n\tcmp\t[PriLevel],bl\t\t\t; are we in front of\n\tjge\tshort ??test_predator\t\t;  background?\n\n\tmov\tebx,[BackAdjust]\t\t; get background page offset\n\tmov\tal,[BYTE PTR ebx + edi]\t\t; get background pixel\n\tjmp\tshort ??test_transparency\n\n??predator:\n\tmov\tebx,[PartialCount]\n\tadd\tebx,[PartialPred]\t\n\tor\tbh,bh\n\tjnz\tshort ??draw_pred\t\t; is this a predator pixel?\n\tmov\t[PartialCount],ebx\n\tjmp\t??test_compact\n\n??draw_pred:\n\txor\tbh,bh\n\tmov\t[PartialCount],ebx\n\tmov\tebx,[PredValue]\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\tmov\tal,[edi + ebx]\t\t\t;  viewport address\n\tjmp\tshort ??test_transparency\n\n??compact:\n\tmov\tebx,[ColorTable]\t\t; get the address of the color table\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; convert it into the proper byte\n\tjmp\t??test_shadow\n\n??shadow:\n\tcmp\tal,SHADOW_COL\n\tjne\t??test_translucency\t\t; is the table value a magic number?\n\n\tmov\tal,[edi]\t\t\t; get the destination color and\n\tmov\tebx,[ShadowingTable]\t\t;  index into the shadow table\n\tmov\tal,[BYTE PTR ebx + eax]\n\tjmp\t??test_transparency\t\t\t\n\n??fading:\n\tmov\t[StashECX],ecx\t\t\t; preserve ecx for later\n\tmov\tebx,[FadingTable]\t\t; run color through fading table\n\tmov\tecx,[FadingNum]\n\n??fade_loop:\n\tmov\tal, [BYTE PTR ebx + eax]\n\tdec\tecx\n\tjnz\tshort ??fade_loop\n\n\tmov\tecx,[StashECX]\t\t\t; restore ecx for main draw loop\n\tjmp\t??test_transparency\n\n??translucency:\n\tmov\tebx,[IsTranslucent]\t\t; is it a translucent color?\n\tmov\tbh,[BYTE PTR ebx + eax]\n\tor\tbh,bh\n\tjs\t??test_fading\n\n\tand\tebx,0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tmov\tal,[edi]\t\t\t; mov pixel at destination to al\n\tadd\tebx,[Translucent]\t\t; get the ptr to it!\n\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; get new pixel in al\n\tjmp\t??test_fading\n\n\n\t;--------------------------------------------------------------------\n\t; Handle a run:\n\t; - Get the run repetition value\n\t; - subract it from [WidthCount]\n\t; - multiply it by [ScaleX]\n\t; - put high bytes from mul into EAX, low byte into DL (roundoff bits)\n\t; - add high bytes (# pixels) to EDI\n\t; - subtract them from ECX\n\t; - clear EAX\n\t; - if ECX>0, go get next byte\n\t;--------------------------------------------------------------------\n??general_is_run:\n\tmov\tal,[esi]\t\t\t; get number of repeated values\n\tinc\tesi\n\tsub\t[WidthCount],eax\t\t; adjust the remaining byte width\n\tmov\tebx,edx\t\t\t\t; preserve dx for the multiply\n\tmul\t[ScaleX]\t\t\t; EDX:EAX = # pixels + roundoff bits\n\tadd\teax,ebx\t\t\t\t; add in the current x-total\n\tmov\tedx,eax\t\t\t\t; (assume EDX is empty)\n\tshr\teax,8\t\t\t\t; EAX = # pixels skipped\n\tand\tedx,00FFh\t\t\t; keep only low byte\n\tadd\tedi,eax\t\t\t\t; add to EDI\n     \tsub\tecx,eax\t\t\t\t; subtract it from ECX\n\tmov\teax,0\t\t\t\t; clear EAX\n\tor\tecx,ecx\n\tjg\t??general_draw_loop\t\t; if more to draw, process new byte\n\n??out:\n\tret\t\t\t\t\t; lets get out of here\n\n\tENDP\tDraw_Scale\n\n\tEND\n\n;**************************** End of ds_ds.asm ******************************\n"
  },
  {
    "path": "WIN32LIB/SHAPE/DS_DSR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_DSR.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : September 6, 1994   [IML]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Draw_Scale_Reverse -- Draws a scaled row of pixels to the viewport    *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;*******p********************************************************************\n;* Draw_Scale_Reverse -- Draws a scaled row of pixels to the viewport      *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of pixels (not bytes) to draw\t\t   *\n;*\t\tEDX = XTotal initializer value\t\t\t\t   *\n;*\t\tESI = shape (source) buffer address\t\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = remaining bytes on the line\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;*\t\tESI - updated to current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) drawn/skipped\t   *\n;*\t\t[WidthCount] - bytes remaining on the line\t\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR  : Converted to 32-bit.                                 *\n;*   08/09/1994 IML : Optimized for 32-bit\t\t\t\t   *\n;*   09/06/1994 IML : Integrated p_* and ds_* routines.\t\t\t   *\n;*=========================================================================*\nPROC\tDraw_Scale_Reverse NOLANGUAGE NEAR\n\n\tmov\teax,0\t\t\t\t; init to 0\n\ttest\t[Flags],SHAPE_EFFECTS\n\tjnz\tshort ??general_draw_continue\n\tjmp\tshort ??fast_draw_continue\n\n\n\t;--------------------------------------------------------------------\n\t; Extra fast draw loop for shapes with no flags set.\n\t;--------------------------------------------------------------------\n\t\n\t;--------------------------------------------------------------------\n\t; Load a new byte:\n\t; - read the byte into AL\n\t; - if it's a run, deal with it\n\t; - otherwise, \n\t;\t- decrement [WidthCount]\n\t;\t- update EDX with [ScaleX]\n\t;\t- see if it's drawable (upon proc entry, it won't be)\n\t;\t\t- yes: draw a pixel\n\t;\t\t- no : load a new byte\n\t;--------------------------------------------------------------------\n??fast_draw_loop:\n\tmov\tal,[esi]\t\t\t; get the next pixel from the source\n\tinc\tesi\n\tor\teax,eax\n\tjz\tshort ??fast_is_run\t\t; deal with a run\n\tdec\t[WidthCount]\t\t\t; count down # bytes processed\n\tadd\tedx,[ScaleX]\t\t\t; add in the scale value\n\n??fast_draw_continue:\n\tor\tdh,dh\t\t\t\t; are there any pixels to draw?\n\tjz\tshort ??fast_draw_loop\n\n\n\t;--------------------------------------------------------------------\n\t; Draw one pixel:\n\t; - draw the pixel\n\t; - increment destination pointer\n\t; - decrement high byte of EDX (X-scale accumulator)\n\t; - loop (while ECX>0) to see if it's drawable\n\t;--------------------------------------------------------------------\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\tdec\tedi\t\t\t\t; decrement the destination index\n\tdec\tdh\t\t\t\t; decrement the pixels to write\n\tdec\tecx\n\tjnz\tshort ??fast_draw_continue\n\tjmp\t??out\t\t\t\t; get the heck outta here\n\n\n\t;--------------------------------------------------------------------\n\t; Handle a run:\n\t; - Get the run repetition value\n\t; - subract it from [WidthCount]\n\t; - multiply it by [ScaleX]\n\t; - put high bytes from mul into EAX, low byte into DL (roundoff bits)\n\t; - add high bytes (# pixels) to EDI\n\t; - subtract them from ECX\n\t; - clear EAX\n\t; - if ECX>0, go get next byte\n\t;--------------------------------------------------------------------\n??fast_is_run:\n\tmov\tal,[esi]\t\t\t; get number of repeated values\n\tinc\tesi\n\tsub\t[WidthCount],eax\t\t; adjust the remaining byte width\n\tmov\tebx,edx\t\t\t\t; preserve dx for the multiply\n\tmul\t[ScaleX]\t\t\t; EDX:EAX = # pixels + roundoff bits\n\tadd\teax,ebx\t\t\t\t; add in the current x-total\n\tmov\tedx,eax\t\t\t\t; (assume EDX is empty)\n\tshr\teax,8\t\t\t\t; EAX = # pixels skipped\n\tand\tedx,00FFh\t\t\t; keep only low byte\n\tsub\tedi,eax\t\t\t\t; sub from EDI\n     \tsub\tecx,eax\t\t\t\t; subtract it from ECX\n\tmov\teax,0\t\t\t\t; clear EAX\n\tor\tecx,ecx\n\tjg\tshort ??fast_draw_loop\t\t; if more to draw, process new byte\n\tjmp\t??out\n\n\n\t;--------------------------------------------------------------------\n\t; General purpose draw loop for shapes with one or more flags set.\n\t;--------------------------------------------------------------------\n\n\t;--------------------------------------------------------------------\n\t; Load a new byte:\n\t; - read the byte into AL\n\t; - if it's a run, deal with it\n\t; - otherwise, \n\t;\t- decrement [WidthCount]\n\t;\t- update EDX with [ScaleX]\n\t;\t- see if it's drawable (upon proc entry, it won't be)\n\t;\t\t- yes: draw a pixel\n\t;\t\t- no : load a new byte\n\t;--------------------------------------------------------------------\n??general_draw_loop:\n\tmov\tal,[esi]\t\t\t; get the next pixel from the source\n\tinc\tesi\n\tor\teax,eax\n\tjz\t??general_is_run\t\t; deal with a run\n\tdec\t[WidthCount]\t\t\t; count down # bytes processed\n\tadd\tedx,[ScaleX]\t\t\t; add in the scale value\n\n??general_draw_continue:\n\tor\tdh,dh\t\t\t\t; are there any pixels to draw?\n\tjz\tshort ??general_draw_loop\n\n\t;--------------------------------------------------------------------\n\t; Draw one pixel:\n\t; - draw the pixel\n\t; - increment destination pointer\n\t; - decrement high byte of EDX (X-scale accumulator)\n\t; - loop (while ECX>0) to see if it's drawable\n\t;--------------------------------------------------------------------\n??draw:\n\tmov\t[StashReg],eax\t\t\t; save eax\n\tmov\t[StashEDX],edx\t\t\t; save edx\n\tmov\tedx,[Flags]\n\n??test_priority:\n\ttest\tedx,SHAPE_PRIORITY\t\t\n\tjnz\tshort ??priority\n\n??test_predator:\n\ttest\tedx,SHAPE_PREDATOR\n\tjnz\tshort ??predator\n\n??test_compact:\n\ttest\tedx,SHAPE_COMPACT\n\tjnz\t??compact\n\n??test_shadow:\n\ttest\tedx,SHAPE_SHADOW\n\tjnz\t??shadow\n\n??test_translucency:\n\ttest\tedx,SHAPE_GHOST\n\tjnz\t??translucency\n\n??test_fading:\n\ttest\tedx,SHAPE_FADING\n\tjnz\t??fading\n\n??test_transparency:\t\n\ttest\tedx,SHAPE_FADING\t\t; if fading is enabled test for\n\tjz\tshort ??no_fading_draw_loop\t;   transparency\n\tor\teax,eax\n\tjz\tshort ??is_transparent\n\n??no_fading_draw_loop:\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\t\n??is_transparent:\n\tmov\teax,[StashReg]\t\t\t; restore eax\n\tmov\tedx,[StashEDX]\t\t\t; restore edx\n\tdec\tedi\t\t\t\t; decrement the destination index\n\tdec\tdh\t\t\t\t; decrement the pixels to write\n\tdec\tecx\n\tjnz\t??general_draw_continue\n\tjmp\t??out\t\t\t\t; get the heck outta here\n\n??priority:\t\n\tmov\tebx,[MaskAdjust]\t\t; get mask page\toffset\n\tmov\tbl,[BYTE PTR ebx + edi]\t\t; get mask value  \n\n\tand\tbl,CLEAR_UNUSED_BITS\t\t; clear unused bits\n\n\tcmp\t[PriLevel],bl\t\t\t; are we in front of\n\tjge\tshort ??test_predator\t\t;  background?\n\n\tmov\tebx,[BackAdjust]\t\t; get background page offset\n\tmov\tal,[BYTE PTR ebx + edi]\t\t; get background pixel\n\tjmp\tshort ??test_transparency\n\n??predator:\n\tmov\tebx,[PartialCount]\n\tadd\tebx,[PartialPred]\t\n\tor\tbh,bh\n\tjnz\tshort ??draw_pred\t\t; is this a predator pixel?\n\tmov\t[PartialCount],ebx\n\tjmp\t??test_compact\n\n??draw_pred:\n\txor\tbh,bh\n\tmov\t[PartialCount],ebx\n\tmov\tebx,[PredValue]\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\tmov\tal,[edi + ebx]\t\t\t;  viewport address\n\tjmp\tshort ??test_transparency\n\n??compact:\n\tmov\tebx,[ColorTable]\t\t; get the address of the color table\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; convert it into the proper byte\n\tjmp\t??test_shadow\n\n??shadow:\n\tcmp\tal,SHADOW_COL\n\tjne\t??test_translucency\t\t; is the table value a magic number?\n\n\tmov\tal,[edi]\t\t\t; get the destination color and\n\tmov\tebx,[ShadowingTable]\t\t;  index into the shadow table\n\tmov\tal,[BYTE PTR ebx + eax]\n\tjmp\t??test_transparency\t\t\t\n\n??fading:\n\tmov\t[StashECX],ecx\t\t\t; preserve ecx for later\n\tmov\tebx,[FadingTable]\t\t; run color through fading table\n\tmov\tecx,[FadingNum]\n\n??fade_loop:\n\tmov\tal, [BYTE PTR ebx + eax]\n\tdec\tecx\n\tjnz\tshort ??fade_loop\n\n\tmov\tecx,[StashECX]\t\t\t; restore ecx for main draw loop\n\tjmp\t??test_transparency\n\n??translucency:\n\tmov\tebx,[IsTranslucent]\t\t; is it a translucent color?\n\tmov\tbh,[BYTE PTR ebx + eax]\n\tor\tbh,bh\n\tjs\t??test_fading\n\n\tand\tebx,0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tmov\tal,[edi]\t\t\t; mov pixel at destination to al\n\tadd\tebx,[Translucent]\t\t; get the ptr to it!\n\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; get new pixel in al\n\tjmp\t??test_fading\n\n\n\t;--------------------------------------------------------------------\n\t; Handle a run:\n\t; - Get the run repetition value\n\t; - subract it from [WidthCount]\n\t; - multiply it by [ScaleX]\n\t; - put high bytes from mul into EAX, low byte into DL (roundoff bits)\n\t; - add high bytes (# pixels) to EDI\n\t; - subtract them from ECX\n\t; - clear EAX\n\t; - if ECX>0, go get next byte\n\t;--------------------------------------------------------------------\n??general_is_run:\n\tmov\tal,[esi]\t\t\t; get number of repeated values\n\tinc\tesi\n\tsub\t[WidthCount],eax\t\t; adjust the remaining byte width\n\tmov\tebx,edx\t\t\t\t; preserve dx for the multiply\n\tmul\t[ScaleX]\t\t\t; EDX:EAX = # pixels + roundoff bits\n\tadd\teax,ebx\t\t\t\t; add in the current x-total\n\tmov\tedx,eax\t\t\t\t; (assume EDX is empty)\n\tshr\teax,8\t\t\t\t; EAX = # pixels skipped\n\tand\tedx,00FFh\t\t\t; keep only low byte\n\tsub\tedi,eax\t\t\t\t; sub from EDI\n     \tsub\tecx,eax\t\t\t\t; subtract it from ECX\n\tmov\teax,0\t\t\t\t; clear EAX\n\tor\tecx,ecx\n\tjg\t??general_draw_loop\t\t; if more to draw, process new byte\n\n??out:\n\tret\t\t\t\t\t; lets get out of here\n\n\n\tENDP\tDraw_Scale_Reverse\n\t\n\tEND\n\n;*************************** End of ds_dsr.asm ******************************\n"
  },
  {
    "path": "WIN32LIB/SHAPE/DS_LRS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_LRS.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 2, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Left_Reverse_Skip -- Skips bytes in a data stream\t\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Left_Reverse_Skip -- Skips bytes in a data stream\t\t\t   *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape (source) buffer data address\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = shape's width\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX - negative # pixels overrun, or 0\t\t\t   *\n;*\t\tEDX - XTotal initializer value (0 since there's no scaling)*\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\tEDI - decremented by # pixels overrun\t\t\t   *\n;*\t\t[WidthCount] - decremented by # bytes skipped\t\t   *\n;*                                                                         *\n;* WARNINGS:\tnone                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   05/28/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tLeft_Reverse_Skip NOLANGUAGE NEAR\n\n\tsub \t[WidthCount],ecx\t; we process ECX bytes of real width\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out\t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tadd\tedi,ecx\t\t\t; decrement EDI by overrun pixels\n\tadd\t[WidthCount],ecx\t; adjust by # bytes overrun\n\tmov\tedx,0\t\t\t; no scaling, so clear EDX\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tLeft_Reverse_Skip\n\n\tEND\n\n;*************************** End of ds_lrs.asm *****************************\n\u001a"
  },
  {
    "path": "WIN32LIB/SHAPE/DS_LS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_LS.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 2, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Left_Skip -- Skips bytes in a data stream\t\t\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Left_Skip -- Skips bytes in a data stream\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape (source) buffer data address\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = shape's width\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX - negative # pixels overrun, or 0\t\t\t   *\n;*\t\tEDX - XTotal initializer value (0 since there's no scaling)*\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\tEDI - incremented by # pixels overrun\t\t\t   *\n;*\t\t[WidthCount] - decremented by # bytes skipped\t\t   *\n;*                                                                         *\n;* WARNINGS:\tnone                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tLeft_Skip NOLANGUAGE NEAR\n\n\tsub \t[WidthCount],ecx\t; we process ECX bytes of real width\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out\t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tsub\tedi,ecx\t\t\t; increment EDI by overrun pixels\n\tadd\t[WidthCount],ecx\t; adjust by # bytes overrun\n\tmov\tedx,0\t\t\t; no scaling, so clear EDX\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tLeft_Skip\n\n\tEND\n\n;**************************** End of ds_ls.asm *****************************\n\u001a"
  },
  {
    "path": "WIN32LIB/SHAPE/DS_LSRS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_LSRS.ASM                              *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 2, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Left_Scale_Reverse_Skip -- Skips past a scaled row of pixels          *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Left_Scale_Reverse_Skip -- Skips past a scaled row of pixels            *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape (source) buffer data address\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = shape's width\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX - negative # pixels (not bytes) overrun, or 0\t   *\n;*\t\tEDX - XTotal initializer value\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\tEDI - decremented by # pixels (not bytes) overrun\t   *\n;*\t\t[WidthCount] - decremented by # bytes skipped\t\t   *\n;*                                                                         *\n;* The value returned in EDX reflects what XTotal's accumulated value \t   *\n;* should be at the new pixel location.  If no bytes are overrun, this\t   *\n;* will be whatever is stored in [XTotalInit] (which will be 0 if no\t   *\n;* pixels are left-clipped).\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:\tnone                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/20/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tLeft_Scale_Reverse_Skip NOLANGUAGE NEAR\n\n\tsub \t[WidthCount],ecx\t; we process ECX bytes of real width\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjcxz\t??getrem\t\t; exit if no bytes to skip\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\tshort ??on_run\t\t; if it is a run then deal with it\n\n\t;--------------------------------------------------------------------\n\t; Default exit point: store default x-scale bits & exit\n\t;--------------------------------------------------------------------\n??getrem:\n\tmov\tedx,[XTotalInit]\t; store out the remainder\n\tjmp\tshort ??out \t\t; we're done, get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\tjz\t??getrem\t\t; exactly enough bytes; exit\n\n\t;--------------------------------------------------------------------\n\t; Overrun exit point: ECX is negative by the # of bytes overrun.\n\t; - adjust [WidthCount] by # of overrun bytes\n\t; - compute the remainder at the new location (EDX)\n\t; - compute the number of destination pixels to skip (ECX)\n\t; - adjust EDI by # of overrun bytes\n\t;--------------------------------------------------------------------\n\t;\n\t;............... adjust [WidthCount] by overrun bytes ...............\n\t;\n\tadd\t[WidthCount],ecx\t; adjust overrun in bytes\n\t;\n\t;................. put x-scale roundoff bits in EDX .................\n\t;\n\tmov\teax,ecx\t\t\t; get the number of bytes we overran\n\tneg\teax\t\t\t; negate it since overun is negative\n\tadd\teax,[LeftClipBytes]\t; add the number of bytes we leftclip\n\tmul \t[ScaleX]\t\t; convert to pixels plus roundoff bits\n\tmov\tedx,0\t\t\t; clear EDX\n\tmov\tdl,al\t\t\t; DL = x-scaling roundoff bits\n\t;\n\t;................ put negative overrun pixels in ECX ................\n\t;\n\tshr\teax,8\t\t\t; EAX = total # left pixels\n\tsub\teax,[LeftClipPixels]\t; EAX = # pixels overrun\n\tmov\tecx,eax\t\t\t; store # overrun pixels\n\tneg\tecx\t\t\t; make it negative\n\t;\n\t;................ adjust dest ptr by overrun pixels .................\n\t;\n\tsub\tesi,eax\t\t\t; decrement ESI (EDI) by overrun pixels\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tLeft_Scale_Reverse_Skip\n\n\tEND\n\n;**************************** End of ds_lsrs.asm ****************************\n\u001a"
  },
  {
    "path": "WIN32LIB/SHAPE/DS_LSS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_LSS.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 2, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Left_Scale_Skip -- Skips past a scaled row of pixels on left side     *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Left_Scale_Skip -- Skips past a scaled row of pixels on left side       *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape (source) buffer data address\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = shape's width\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX - negative # pixels (not bytes) overrun, or 0\t   *\n;*\t\tEDX - XTotal initializer value\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\tEDI - incremented by # pixels (not bytes) overrun\t   *\n;*\t\t[WidthCount] - decremented by # bytes skipped\t\t   *\n;*                                                                         *\n;* The value returned in EDX reflects what XTotal's accumulated value \t   *\n;* should be at the new pixel location.  If no bytes are overrun, this\t   *\n;* will be whatever is stored in [XTotalInit] (which will be 0 if no\t   *\n;* pixels are left-clipped).\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:\tnone                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/08/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tLeft_Scale_Skip NOLANGUAGE NEAR\n\n\tsub \t[WidthCount],ecx\t; we process ECX bytes of real width\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjcxz\t??getrem\t\t; exit if no bytes to skip\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\tshort ??on_run\t\t; if it is a run then deal with it\n\n\t;--------------------------------------------------------------------\n\t; Default exit point: store default x-scale bits & exit\n\t;--------------------------------------------------------------------\n??getrem:\n\tmov\tedx,[XTotalInit]\t; store out the remainder\n\tjmp\tshort ??out \t\t; we're done, get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\tjz\t??getrem\t\t; exactly enough bytes; exit\n\n\t;--------------------------------------------------------------------\n\t; Overrun exit point: ECX is negative by the # of bytes overrun.\n\t; - adjust [WidthCount] by # of overrun bytes\n\t; - compute the remainder at the new location (EDX)\n\t; - compute the number of destination pixels to skip (ECX)\n\t; - adjust EDI by # of overrun bytes\n\t;--------------------------------------------------------------------\n\t;\n\t;............... adjust [WidthCount] by overrun bytes ...............\n\t;\n\tadd\t[WidthCount],ecx\t; adjust overrun in bytes\n\t;\n\t;................. put x-scale roundoff bits in EDX .................\n\t;\n\tmov\teax,ecx\t\t\t; get the number of bytes we overran\n\tneg\teax\t\t\t; negate it since overun is negative\n\tadd\teax,[LeftClipBytes]\t; add the number of bytes we leftclip\n\tmul \t[ScaleX]\t\t; convert to pixels plus roundoff bits\n\tmov\tedx,0\t\t\t; clear EDX\n\tmov\tdl,al\t\t\t; DL = x-scaling roundoff bits\n\t;\n\t;................ put negative overrun pixels in ECX ................\n\t;\n\tshr\teax,8\t\t\t; EAX = total # left pixels\n\tsub\teax,[LeftClipPixels]\t; EAX = # pixels overrun\n\tmov\tecx,eax\t\t\t; store # overrun pixels\n\tneg\tecx\t\t\t; make it negative\n\t;\n\t;................ adjust dest ptr by overrun pixels .................\n\t;\n\tadd\tesi,eax\t\t\t; increment ESI (EDI) by overrun pixels\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tLeft_Scale_Skip\n\n\tEND\n\n;**************************** End of ds_lss.asm *****************************\n\u001a"
  },
  {
    "path": "WIN32LIB/SHAPE/DS_RRS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_RRS.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : May 28, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Right_Reverse_Skip -- Skips bytes in a data stream\t\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Right_Reverse_Skip -- Skips bytes in a data stream\t\t\t   *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape buffer data address\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*                                                                         *\n;* WARNINGS:\tThis routine may overrun the number of requested bytes\t   *\n;*\t\tif it encounters a run of 0's; however, it's assumed that  *\n;*\t\tthe shape data will never contain a run that goes past the *\n;*\t\tright-hand edge of the shape.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   05/28/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tRight_Reverse_Skip NOLANGUAGE NEAR\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out\t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tRight_Reverse_Skip\n\n\tEND\n\n;**************************** End of ds_rrs.asm ****************************\n\u001a"
  },
  {
    "path": "WIN32LIB/SHAPE/DS_RS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_RS.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : May 28, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Right_Skip -- Skips bytes in a data stream\t\t\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Right_Skip -- Skips bytes in a data stream\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape buffer data address\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*                                                                         *\n;* WARNINGS:\tThis routine may overrun the number of requested bytes\t   *\n;*\t\tif it encounters a run of 0's; however, it's assumed that  *\n;*\t\tthe shape data will never contain a run that goes past the *\n;*\t\tright-hand edge of the shape.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   05/28/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tRight_Skip NOLANGUAGE NEAR\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out\t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tRight_Skip\n\n\tEND\n\n;**************************** End of ds_rs.asm ******************************\n\u001a"
  },
  {
    "path": "WIN32LIB/SHAPE/DS_RSRS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_RSRS.ASM                              *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 1, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Right_Scale_Reverse_Skip -- Skips past a scaled row of pixels         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Right_Scale_Reverse_Skip -- Skips past a scaled row of pixels           *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape buffer data address\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*                                                                         *\n;* WARNINGS:\tThis routine may overrun the number of requested bytes\t   *\n;*\t\tif it encounters a run of 0's; however, it's assumed that  *\n;*\t\tthe shape data will never contain a run that goes past the *\n;*\t\tright-hand edge of the shape.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/20/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/01/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tRight_Scale_Reverse_Skip NOLANGUAGE NEAR\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out \t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tRight_Scale_Reverse_Skip\n\n\tEND\n\n;*************************** End of ds_rsrs.asm ****************************\n\u001a"
  },
  {
    "path": "WIN32LIB/SHAPE/DS_RSS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_RSS.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 1, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Right_Scale_Skip -- Skips past a scaled row of pixels on right side   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Right_Scale_Skip -- Skips past a scaled row of pixels on the right side *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape buffer data address\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*                                                                         *\n;* WARNINGS:\tThis routine may overrun the number of requested bytes\t   *\n;*\t\tif it encounters a run of 0's; however, it's assumed that  *\n;*\t\tthe shape data will never contain a run that goes past the *\n;*\t\tright-hand edge of the shape.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/20/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/01/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tRight_Scale_Skip NOLANGUAGE NEAR\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out \t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tRight_Scale_Skip\n\n\tEND\n\n;*************************** End of ds_rss.asm *****************************\n\u001a"
  },
  {
    "path": "WIN32LIB/SHAPE/DS_TABLE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_TABLE.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 20, 1993                          *\n;*                                                                         *\n;*                  Last Update : September 6, 1994   [IML]                *\n;*                                                                         *\n;* This module sets up a table of procedure addresses for combinations of  *\n;* NORMAL, HORZ_REV and SCALING\tflags.\t\t\t\t\t   *\t\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************** Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;******************************** Equates **********************************\n;*=========================================================================*/\n;* The following are defines used to control what functions are linked\t   *\n;* in for Draw_Shape.\t\t\t\t\t\t\t   *\n;*=========================================================================*/\nUSE_NORMAL\tEQU\tTRUE\nUSE_HORZ_REV \tEQU\tTRUE\nUSE_VERT_REV \tEQU\tTRUE\nUSE_SCALING \tEQU\tTRUE\n\n\n;---------------------------------------------------------------------------\n;\n; Use a macro to make code a little cleaner.\n; The parameter varname is optional.\n; Syntax to use macro is :\n;  WANT equ expression\n;  USE func [,varname]\n; If the 'varname' is defined, a table declaration is created like:\n;\tGLOBAL\tTableName:DWORD\n; Then, the table entry is created:\n;  If WANT is true, the table entry is created for the given function:\n;\tvarname\tDD\tfunc\n;  If WANT is not TRUE, a Not_Supported entry is put in the table:\n;\tvarname\tDD\tNot_Supported\n; The resulting tables look like:\n;\n;\tGLOBAL\tExampTable:DWORD\n;\tExampTable\tDD\troutine1\n;\t\t\tDD\troutine2\n;\t\t\tDD\troutine3\n;\t\t\t...\n; Thus, each table is an array of function pointers.\n;\n;---------------------------------------------------------------------------\nMACRO USE func, varname\n IFNB <varname>\n\tGLOBAL\tvarname:DWORD\n ENDIF\n IF WANT\n  varname \tDD\tfunc\n ELSE\n  varname\tDD\tNot_Supported\n ENDIF\nENDM\n\n\n;---------------------------------------------------------------------------\n; Data Segment Tables:\n; This code uses the USE macro to set up tables of function addresses.\n; The tables have the following format:\n; Tables defined are:\n;\tLSkipTable\n;\tRSkipTable\n;\tDrawTable\n;---------------------------------------------------------------------------\n\n\tDATASEG\n\n;---------------------------------------------------------------------------\n\nWANT\tequ \t<TRUE>\nUSE\tLeft_Skip, LSkipTable\n\nWANT\tequ \t<TRUE>\nUSE\tLeft_Reverse_Skip\n\nWANT\tequ \t<TRUE>\nUSE\tLeft_Skip\n\nWANT\tequ \t<TRUE>\nUSE\tLeft_Reverse_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tLeft_Scale_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tLeft_Scale_Reverse_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tLeft_Scale_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tLeft_Scale_Reverse_Skip\n;---------------------------------------------------------------------------\n\nWANT\tequ \t<TRUE>\nUSE\tRight_Skip, RSkipTable\n\nWANT\tequ \t<TRUE>\nUSE\tRight_Reverse_Skip\n\nWANT\tequ \t<TRUE>\nUSE\tRight_Skip\n\nWANT\tequ \t<TRUE>\nUSE\tRight_Reverse_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tRight_Scale_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tRight_Scale_Reverse_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tRight_Scale_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tRight_Scale_Reverse_Skip\n;---------------------------------------------------------------------------\n\nWANT\tequ \t<TRUE>\nUSE\tDraw_Normal, DrawTable\n\nWANT\tequ \t<TRUE>\nUSE\tDraw_Reverse\n\nWANT\tequ \t<TRUE>\nUSE\tDraw_Normal\n\nWANT\tequ \t<TRUE>\nUSE\tDraw_Reverse\n\nWANT\tequ \t<USE_SCALING>\nUSE\tDraw_Scale\n\nWANT\tequ \t<USE_SCALING>\nUSE\tDraw_Scale_Reverse\n\nWANT\tequ \t<USE_SCALING>\nUSE\tDraw_Scale\n\nWANT\tequ \t<USE_SCALING>\nUSE\tDraw_Scale_Reverse\n;---------------------------------------------------------------------------\n\n;---------------------------------------------------------------------------\n\tEND\n\n;************************** End of ds_table.asm ****************************\n"
  },
  {
    "path": "WIN32LIB/SHAPE/GETSHAPE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : GETSHAPE.CPP                             *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : April 5, 1992                            *\n *                                                                         *\n *                  Last Update : May 25, 1994   [BR]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Get_Shape_Size -- Fetch the size of the shape in memory.              *\n *   Get_Shape_Uncomp_Size -- gets shape's uncompressed size in bytes\t\t*\n *   Get_Shape_Data -- retrieves a shape's special prefix data\t\t\t\t\t*\n *   Extract_Shape_Count -- returns # of shapes in the given shape block\t*\n *   Extract_Shape -- Gets pointer to shape in given shape block\t\t\t\t*\n *   Get_Shape_Width -- gets shape width in pixels\t\t\t\t\t\t\t\t\t*\n *   Get_Shape_Height -- gets shape height in pixels\t\t\t\t\t\t\t\t*\n *   Set_Shape_Height -- modifies shape's height\t\t\t\t\t\t\t\t\t*\n *   Restore_Shape_Height -- restores a shape to its original height\t\t\t*\n *   Get_Shape_Original_Height -- gets shape's unmodified height\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n/*\n********************************* Includes **********************************\n*/\n#include \"wwstd.h\"\n#include\t\"shape.h\"\n\n\n/***************************************************************************\n * Get_Shape_Size -- Fetch the size of the shape in memory.                *\n *                                                                         *\n * The shape size returned includes both the shape header & its data.\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * INPUT:                                                                  *\n *\tshape\t\tpointer to shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * shape's size in memory\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n * none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint cdecl Get_Shape_Size(VOID const *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\n\t/*\n\t------------------------- Return if NULL pointer -------------------------\n\t*/\n\tif (!shape) \n\t\treturn(0);\n\n\t/*\n\t-------------------------- Returns shape's size --------------------------\n\t*/\n\treturn (shp->ShapeSize);\n\n}\t/* end of Get_Shape_Size */\n\n\n/***************************************************************************\n * Get_Shape_Uncomp_Size -- gets shape's uncompressed size in bytes\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\tshape\t\tpointer to shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\tshape's size in bytes when uncompressed\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n * none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint Get_Shape_Uncomp_Size(VOID const *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\n\treturn (shp->DataLength);\n\n}\t/* end of Get_Shape_Uncomp_Size */\n\n\n/***************************************************************************\n * Get_Shape_Data -- retrieves a shape's special prefix data\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * MAKESHPS.EXE can store special data values along with a shape.  These\t*\n * values are inserted in the shape table >before< the shape's header.\t\t*\n * So, this routine uses the 'data' parameter as a negative index from\t\t*\n * the given shape pointer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\tshape\t\tpointer to shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * data\t\tindex of WORD data value to get\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * data value\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\tThe shape pointer must be a pointer into a shape table created by\t\t\t*\n * MAKESHPS.EXE; it >cannot< be a pointer to shape returned by Make_Shape!\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nWORD cdecl Get_Shape_Data(VOID const *shape, WORD data)\n{\n\tWORD *word_ptr = (WORD *)shape;\n\tWORD retval;\n\n\tretval = *(word_ptr - (data+1));\n\n\treturn (retval);\n\n}\t/* end of Get_Shape_Data */\n\n\n/***************************************************************************\n * Extract_Shape_Count -- returns # of shapes in the given shape block\t\t*\n *                                                                         *\n * The # of shapes in a shape block is the first WORD in the block, so\t\t*\n * this is the value returned.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * INPUT:                                                                  *\n * buffer\tpointer to shape block, created with MAKESHPS.EXE\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * # shapes in the block\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint cdecl Extract_Shape_Count(VOID const *buffer)\n{\n\tShapeBlock_Type *block = (ShapeBlock_Type *)buffer;\n\n\treturn (block->NumShapes);\n\n}\t/* end of Extract_Shape_Count */\n\n\n/***************************************************************************\n * Extract_Shape -- Gets pointer to shape in given shape block\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n * buffer\tpointer to shape block, created with MAKESHPS.EXE\t\t\t\t\t*\n * shape\t\tindex of shape to get\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * pointer to shape in the shape block\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nVOID * cdecl Extract_Shape(VOID const *buffer, int shape)\n{\n\tShapeBlock_Type *block = (ShapeBlock_Type*) buffer;\n\tint numshapes;\t\t// Number of shapes\n\tlong offset;\t\t\t// Offset of shape data, from start of block\n\tchar *bytebuf = (char*) buffer;\n\n\t/*\n\t----------------------- Return if invalid argument -----------------------\n\t*/\n\tif (!buffer || shape < 0 || shape >= block->NumShapes)\n\t\treturn(NULL);\n\n\toffset = block->Offsets[shape];\n\n\treturn(bytebuf + 2 + offset);\n\n}\t/* end of Extract_Shape */\n\n\n/***************************************************************************\n * Get_Shape_Width -- gets shape width in pixels\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n * shape\t\tpointer to a shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\tshape width in pixels\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n * none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint Get_Shape_Width(VOID const *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\n\treturn (shp->Width);\n\n}\t/* end of Get_Shape_Width */\n\n\n/***************************************************************************\n * Get_Shape_Height -- gets shape height in pixels\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n * shape\t\tpointer to a shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * shape height in pixels\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n * none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint Get_Shape_Height(VOID const *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\n\treturn (shp->Height);\n\n}\t/* end of Get_Shape_Height */\n\n\n/***************************************************************************\n * Set_Shape_Height -- modifies shape's height\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The new height must be shorter than the original height.  This effect\t*\n * chops off the lower portion of the shape, like it's sinking into the\t\t*\n * ground.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * INPUT:                                                                  *\n * shape\t\t\tpointer to a shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * newheight\tnew shape height\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * old shape height\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n * none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint cdecl Set_Shape_Height(VOID const *shape, WORD newheight)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\tWORD oldheight;\n\n\toldheight = shp->Height;\n\tshp->Height = newheight;\n\n\treturn(oldheight);\n\n}\t/* end of Set_Shape_Height */\n\n\n/***************************************************************************\n * Restore_Shape_Height -- restores a shape to its original height\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n * shape\t\tpointer to a shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * old shape height\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint cdecl Restore_Shape_Height(VOID *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\tWORD oldheight;\n\n\toldheight = shp->Height;\n\tshp->Height = shp->OriginalHeight;\n\n\treturn(oldheight);\n\n}\t/* end of Restore_Shape_Height */\n\n\n/***************************************************************************\n * Get_Shape_Original_Height -- gets shape's unmodified height\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\tshape\t\tpointer to a shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * shape's unmodified height\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint Get_Shape_Original_Height(VOID const *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\t\n\treturn (shp->OriginalHeight);\n\n}\t/* end of Get_Shape_Original_Height */\n\n\n/************************* end of getshape.cpp *****************************/\n\n"
  },
  {
    "path": "WIN32LIB/SHAPE/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = shape\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tgetshape.obj \t&\n\tshape.obj\n#\tprioinit.obj \t&\n#\tdrawshp.obj \t&\n#\tds_dn.obj \t&\n#\tds_dr.obj \t&\n#\tds_ds.obj \t&\n#\tds_dsr.obj \t&\n#\tds_lrs.obj \t&\n#\tds_ls.obj \t&\n#\tds_lsrs.obj \t&\n#\tds_lss.obj \t&\n#\tds_rrs.obj \t&\n#\tds_rs.obj \t&\n#\tds_rsrs.obj \t&\n#\tds_rss.obj \t&\n#\tds_table.obj\t&\n#\tsetshape.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/SHAPE/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 25, 1995\t                           *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = shape\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tgetshape.obj \t&\n\tprioinit.obj \t&\n\tdrawshp.obj \t&\n\tds_dn.obj \t&\n\tds_dr.obj \t&\n\tds_ds.obj \t&\n\tds_dsr.obj \t&\n\tds_lrs.obj \t&\n\tds_ls.obj \t&\n\tds_lsrs.obj \t&\n\tds_lss.obj \t&\n\tds_rrs.obj \t&\n\tds_rs.obj \t&\n\tds_rsrs.obj \t&\n\tds_rss.obj \t&\n\tds_table.obj\t&\n\tsetshape.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/SHAPE/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 25, 1995\t                           *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = shape\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tgetshape.obj \t&\n\tprioinit.obj \t&\n\tdrawshp.obj \t&\n\tds_dn.obj \t&\n\tds_dr.obj \t&\n\tds_ds.obj \t&\n\tds_dsr.obj \t&\n\tds_lrs.obj \t&\n\tds_ls.obj \t&\n\tds_lsrs.obj \t&\n\tds_lss.obj \t&\n\tds_rrs.obj \t&\n\tds_rs.obj \t&\n\tds_rsrs.obj \t&\n\tds_rss.obj \t&\n\tds_table.obj\t&\n\tsetshape.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/SHAPE/PRIOINIT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory system.                           *\n *                                                                         *\n *                    File Name : PRIOINIT.CPP                             *\n *                                                                         *\n *                   Programmer : Ian M. Leslie                            *\n *                                                                         *\n *                   Start Date : August 9, 1993                           *\n *                                                                         *\n *                  Last Update : August 9, 1994   [IML]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   INIT_PRIORITY_SYSTEM -- \tSets the buffer addresses for the priority   *\n *   \t\t\t\t\t\t\t\t\tsystem.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"shape.h\"\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * Init_Priority_System -- set the buffer addresses for the priority\t\t   *\n *   \t\t\t\t\t\t\t\tsystem.                       \t\t\t\t\t\t*\n *                                                                         *\n * INPUT:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tmask - pointer\tto priority buffer class\t\t\t\t\t\t\t\t\t\t*\n *\t\tback - pointer to background buffer class\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   08/09/1994 IML : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n *=========================================================================*/\n\nVOID cdecl Init_Priority_System (GraphicBufferClass *mask,\n\t\t\t\t\t\t\t\t\t\t\tGraphicBufferClass *back)\n{\n MaskPage = mask->Get_Buffer();\n BackGroundPage = back->Get_Buffer();\n}\n\n\n/************************** end of prioinit.cpp ****************************/\n"
  },
  {
    "path": "WIN32LIB/SHAPE/SETSHAPE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : WWLIB32                                  *\n;*                                                                         *\n;*                    File Name : SETSHAPE.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : October 26, 1994                         *\n;*                                                                         *\n;*                  Last Update : October 26, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Set_Shape_Buffer -- Sets the shape buffer to the given pointer        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\nCODESEG\n\n;***************************************************************************\n;* SET_SHAPE_BUFFER -- Sets the shape buffer to the given pointer          *\n;*                                                                         *\n;* This routine will set the shape buffer to the given value and make sure *\n;* that the system does not try to compress any shapes that will be larger *\n;* than the shape buffer.\t\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tvoid * - pointer to the shape buffer                       *\n;*\t\tint    - size of the buffer which has been passed in\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       VOID *Set_Shape_Bufer(void *buffer, int size);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/26/1994 PWG : Created.                                             *\n;*=========================================================================*\nGLOBAL\tSet_Shape_Buffer:NEAR\n\nPROC\tSet_Shape_Buffer C near \n\tUSES\teax\n\n\tARG\tbuff:DWORD\n\tARG\tsize:DWORD\n\n\tmov\teax,[size]\n\tmov\t[_ShapeBufferSize],eax\n\n\tmov\teax,[buff]\n\tmov\t[_ShapeBuffer],eax\n\tret\n\n\tENDP\tSet_Shape_Buffer\nEND\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SHAPE/SHAPE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : WWLIB32                                  *\n;*                                                                         *\n;*                    File Name : SHAPE.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : April 13, 1992                           *\n;*                                                                         *\n;*                  Last Update : September 14, 1994   [IML]               *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Draw_Shape -- Draws a shape at given buffer coordinates and clips     *\n;*   Not_Supported -- Replacement function for Draw_Shape routines not used*\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"shape.inc\"\n\nglobal\tC ShapeBuffer\t\t:dword\nglobal\tC ShapeBufferSize\t:dword\nglobal\tC _ShapeBuffer\t\t:dword\nglobal\tC _ShapeBufferSize\t:dword\nglobal\tC Set_Shape_Buffer\t:near\n\nDATASEG\nlabel\tShapeBuffer\tdword\n_ShapeBuffer\t\tdd\t0\n\nlabel\tShapeBufferSize\tdword\n_ShapeBufferSize\tdd\t0\n\nCODESEG\n\n;***************************************************************************\n;* SET_SHAPE_BUFFER -- Sets the shape buffer to the given pointer          *\n;*                                                                         *\n;* This routine will set the shape buffer to the given value and make sure *\n;* that the system does not try to compress any shapes that will be larger *\n;* than the shape buffer.\t\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tvoid * - pointer to the shape buffer                       *\n;*\t\tint    - size of the buffer which has been passed in\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       VOID *Set_Shape_Bufer(void *buffer, int size);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/26/1994 PWG : Created.                                             *\n;*=========================================================================*\nGLOBAL\tC Set_Shape_Buffer:NEAR\n\nPROC\tSet_Shape_Buffer C near\n\tUSES\teax\n\n\tARG\tbuff:DWORD\n\tARG\tsize:DWORD\n\n\tmov\teax,[size]\n\tmov\t[_ShapeBufferSize],eax\n\n\tmov\teax,[buff]\n\tmov\t[_ShapeBuffer],eax\n\tret\n\n\tENDP\tSet_Shape_Buffer\nEND\n\n"
  },
  {
    "path": "WIN32LIB/SHAPE/SHAPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32                                  *\n *                                                                         *\n *                    File Name : SHAPE.H                                  *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : May 25, 1994                             *\n *                                                                         *\n *                  Last Update : September 14, 1994   [IML]               *\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef SHAPE_H\n#define SHAPE_H\n\n#ifndef GBUFFER_H\n#include \"gbuffer.h\"\n#endif\n/*\n*********************************** Types ***********************************\n*/\n/*\n--------------------------- Shape creation flags ----------------------------\n*/\ntypedef enum {\n\tMAKESHAPE_NORMAL\t = 0x0000,\t// 256-color compressed shape\n\tMAKESHAPE_COMPACT  = 0x0001,\t// 16-color shape (with built-in color table)\n\tMAKESHAPE_NOCOMP\t = 0x0002,\t// Uncompressed shape\n\tMAKESHAPE_VARIABLE =\t0x0004\t// <16-color shape\n} MakeShapeFlags_Type;\n\n/*---------------------------------------------------------------------------\nShape drawing flags:\n- The low byte is for coordinate transformations.\n- The high byte is for drawing effects.\n---------------------------------------------------------------------------*/\ntypedef enum {\n\tSHAPE_NORMAL \t\t\t= 0x0000,\t\t// Standard shape\n\tSHAPE_HORZ_REV \t\t= 0x0001,\t\t// Flipped horizontally\n\tSHAPE_VERT_REV \t\t= 0x0002,\t\t// Flipped vertically\n\tSHAPE_SCALING \t\t\t= 0x0004,\t\t// Scaled (WORD scale_x, WORD scale_y)\n\tSHAPE_VIEWPORT_REL \t= 0x0010,\t\t// Coords are window-relative\n\tSHAPE_WIN_REL \t\t\t= 0x0010,\t\t// Coordinates are window relative instead of absolute.\n\tSHAPE_CENTER \t\t\t= 0x0020,\t\t// Coords are based on shape's center pt\n\tSHAPE_FADING \t\t\t= 0x0100,\t\t// Fading effect (void * fading_table,\n\t\t\t\t\t\t\t\t\t\t\t\t\t//  WORD fading_num)\n\tSHAPE_PREDATOR \t\t= 0x0200,\t\t// Transparent warping effect\n\tSHAPE_COMPACT \t\t\t= 0x0400,\t\t// Never use this bit\n\tSHAPE_PRIORITY \t\t= 0x0800,\t\t// Use priority system when drawing\n\tSHAPE_GHOST\t\t\t\t= 0x1000,\t\t// Shape is drawn ghosted\n\tSHAPE_SHADOW\t\t\t= 0x2000,\n\tSHAPE_PARTIAL  \t\t= 0x4000,\n\tSHAPE_COLOR \t\t\t= 0x8000\t\t\t// Remap the shape's colors\n\t\t\t\t\t\t\t\t\t\t\t\t\t//  (void * color_table)\n} ShapeFlags_Type;\n\n/*\n------------------------------- Shape header --------------------------------\n*/\ntypedef struct {\n\tunsigned short\t\tShapeType;\t\t\t// 0 = normal, 1 = 16 colors,\n\t\t\t\t\t\t\t\t\t\t//  2 = uncompressed, 4 = \t<16 colors\n\tunsigned char\t\tHeight;\t\t\t\t// Height of the shape in scan lines\n\tunsigned short\t\tWidth;\t\t\t\t// Width of the shape in bytes\n\tunsigned char\t\tOriginalHeight;\t// Original height of shape in scan lines\n\tunsigned short\t\tShapeSize;\t\t\t// Size of the shape, including header\n\tunsigned short\t\tDataLength;\t\t\t// Size of the uncompressed shape (just data)\n\tunsigned char\t\tColortable[16];\t// Optional color table for compact shape\n} Shape_Type;\n\n/*\n------------------------------- Shape block ---------------------------------\n*/\ntypedef struct {\n\tunsigned short\t\tNumShapes;\t\t\t// number of shapes in the block\n\tlong\t\tOffsets[];\t\t\t// array of offsets to shape data\n\t\t\t\t\t\t\t\t\t\t//  (offsets within the shape block, with\n\t\t\t\t\t\t\t\t\t\t//  0 being the first offset value, not the\n\t\t\t\t\t\t\t\t\t\t//  start of the shape block)\n} ShapeBlock_Type;\n\n\n/*\n******************************** Prototypes *********************************\n*/\n\n/*\n-------------------------------- prioinit.c ---------------------------------\n*/\n\nextern \"C\" {\nextern void  *MaskPage;\nextern void  *BackGroundPage;\nextern long  _ShapeBufferSize;\nextern char  *_ShapeBuffer;\n}\n\n\nvoid __cdecl Init_Priority_System (GraphicBufferClass *mask,\n\t\t\t\t\t\t\t\t\t\t\tGraphicBufferClass *back);\n\n\n/*\n-------------------------------- drawshp.asm --------------------------------\n*/\n\nextern \"C\" {\nint Draw_Shape(GraphicViewPortClass *gvp, void const *shape, LONG x, LONG y, LONG flags, ...);\n}\n\n/*\n---------------------------------- shape.c ----------------------------------\n*/\nshort __cdecl Get_Shape_Data(void const *shape, int data);\nint __cdecl Extract_Shape_Count(void const *buffer);\nvoid * __cdecl Extract_Shape(void const *buffer, int shape);\nint __cdecl Restore_Shape_Height(void *shape);\nint __cdecl Set_Shape_Height(void const *shape, int newheight);\n\nextern \"C\" {\nint __cdecl Get_Shape_Width(void const *shape);\nint __cdecl Get_Shape_Height(void const *shape);\nint __cdecl Get_Shape_Original_Height(void const *shape);\nint __cdecl Get_Shape_Uncomp_Size(void const *shape);\n}\n\n\n/*\n------------------------------- setshape.asm --------------------------------\n*/\nextern \"C\" {\nvoid __cdecl Set_Shape_Buffer(void const *buffer, int size);\n}\n/*\n------------------------------- shapeinf.asm --------------------------------\n*/\nint __cdecl Get_Shape_Flags(void const *shape);\nint  __cdecl Get_Shape_Size(void const *shape);\nint  __cdecl Get_Shape_Scaled_Width(void const *shape, int scale);\nint  __cdecl Get_Shape_Scaled_Height(void const *shape, int scale);\n\n#endif // SHAPE_H\n\n/****************************** End of shape.h *****************************/\n\u001a\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SHAPE/SHAPE.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : WWLIB32                                  *\n;*                                                                         *\n;*                    File Name : SHAPE.INC                                *\n;*                                                                         *\n;*                   Programmer : Scott Bowen\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : May 25, 1994                             *\n;*                                                                         *\n;*                  Last Update : September 14, 1994   [IML]               *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;****************************** Equates ************************************\n;\n\n\n\n\n\n\n;............................ Shape Types ..................................\n;\nTRUE\tequ\t1\t\t\t; Boolean 'true' value\nFALSE\tequ\t0\t\t\t; Boolean 'false' value\n\nMAKESHAPE_NORMAL\t\tEQU\t0\t; 256-color compressed shape\nMAKESHAPE_COMPACT\t\tEQU\t1\t; 16-color shape (built-in color table)\nMAKESHAPE_NOCOMP\t\tEQU\t2\t; non-wwcomped shape\nMAKESHAPE_VARIABLE\tEQU\t4\t; <16-color shape with variable #\n\t\t\t\t\t; of colors (ColorTable[0] = # of colors)\n; old names:\n;COLOR_SHAPE\t\tEQU\t1\t; flag which determines a color shape\n;NORM_SHAPE\t\t\tEQU\t2\t; flag that indicates non wwcomped shp\n;NORM_SHAPE_16\t\tEQU\t4\t; flag that tells us if we have a variable sized table\n\t\t\t\t\t;  variable sized table\n;\n;...........................................................................\n; Drawing flags:\n; The low byte is for coordinate transformations.\n; The high byte is for drawing effects.\n;...........................................................................\n;\nSHAPE_NORMAL\t\t\tEQU\t0000h\t; no options; just a copy\nSHAPE_HORZ_REV\t\t\tEQU\t0001h\t; reverse horizontally\nSHAPE_VERT_REV\t\t\tEQU\t0002h\t; reverse vertically\nSHAPE_SCALING\t\t\tEQU\t0004h\t; scale\nSHAPE_VIEWPORT_REL\tEQU\t0010h\t; viewport-relative coordinates\nSHAPE_CENTER\t\t\tEQU\t0020h\t; use centered coordinates\nSHAPE_FADING\t\t\tEQU\t0100h\t; fading effect shape\nSHAPE_PREDATOR\t\t\tEQU\t0200h\t; predator effect shape\nSHAPE_COMPACT\t\t\tEQU\t0400h\t; shape is in 16 colors\nSHAPE_PRIORITY\t\t\tEQU\t0800h\t; priority draw shape\nSHAPE_GHOST\t\t\t\tEQU\t1000h\t; ghosting effect\nSHAPE_SHADOW\t\t\tEQU\t2000h\t; shadow effect\nSHAPE_PARTIAL\t\t\tEQU\t4000h\t; partial predator effect\nSHAPE_COLOR\t\t\t\tEQU\t8000h\t; use alternative color table effect\n\nSHAPE_EFFECTS\t\t\tEQU    03F00h\t; shape effect flags\n\n;\n;.......................... Shadow Effect ..................................\n;\nSHADOW_COL\t\tEQU\t00FFh\t; magic number for shadows\n\n;......................... Priority System .................................\n;\nCLEAR_UNUSED_BITS  \tEQU\t0007h\t; and with 0000-0111 to clear\n\t\t\t\t\t;  non-walkable high bit and\n\t\t\t\t\t;  scaling id bits\nNON_WALKABLE_BIT  \tEQU\t0080h\t; and with 1000-0000 to clear all\n\t\t\t\t\t;  but non-walkable bit\n;\n;......................... Predator Effect .................................\n;\nPRED_MASK\t\tEQU\t0007h\t; mask used for predator pixel puts\n\n;---------------------------------------------------------------------------\n; This table is a list of the local stack variables in the function\n; Draw_Shape.  Many other functions in other modules access these variables\n; on the stack.  Since the BP is not changed when these other functions are\n; called by Draw_Shape (possibly indirectly), they can also access these\n; stack varibles.  When adding or removing from the table, one must be very\n; careful to change the offsets.\n;---------------------------------------------------------------------------\n;.......................... proc addresses .................................\nLSkipRout\tEQU DWORD PTR ebp - 04h\t\t;DWORD  pointer to the skip routine\nRSkipRout\tEQU DWORD PTR ebp - 08h\t\t;DWORD  pointer to the skip routine\nDrawRout\tEQU DWORD PTR ebp - 0Ch\t\t\t;DWORD  pointer to the draw routine\n;........................ optional arguments ...............................\nColorTable\tEQU DWORD PTR ebp - 10h\t\t;DWORD\tptr to the shapes color table\nFadingTable\tEQU DWORD PTR ebp - 14h\t\t;DWORD  ptr to the fading table\n\nFadingNum\tEQU DWORD PTR ebp - 18h\t\t;DWORD  number of times to fade\nIsTranslucent\tEQU DWORD PTR ebp - 1Ch\t;DWORD\tptr to is_translucent table\nTranslucent\tEQU DWORD PTR ebp - 20h\t\t;DWORD\tptr to actual translucent tbl\nPriLevel\tEQU BYTE  PTR ebp - 24h\t\t\t;BYTE\tpriority level of the object\nScaleX\t\tEQU DWORD PTR ebp - 28h\t\t;DWORD  the x increment to scale by\nScaleY\t\tEQU DWORD PTR ebp - 2Ch\t\t;DWORD  the y increment to scale by\nShadowingTable\tEQU DWORD PTR ebp - 30h\t;DWORD\tptr to the shadowing table\n;........................ Shape header values ..............................\nShapeType\tEQU DWORD PTR ebp - 34h \t;DWORD\tshape type\nShapeWidth\tEQU DWORD PTR ebp - 38h \t;DWORD\tshape's unscaled width\nShapeHeight\tEQU DWORD PTR ebp - 3Ch \t;DWORD\tshape's unscaled height\nUncompDataLen\tEQU DWORD PTR ebp - 40h ;DWORD\tuncompressed data length\nShapeData\tEQU DWORD PTR ebp - 44h \t;DWORD\tpointer to shape data\n;...................... Scaled shape dimensions ............................\nScaledWidth\tEQU DWORD PTR ebp - 48h \t;DWORD\tshape's scaled width\nScaledHeight\tEQU DWORD PTR ebp - 4Ch ;DWORD\tshape's scaled height\n;...................... Pixel clipping variables ...........................\nLeftClipPixels\tEQU DWORD PTR ebp - 50h ;DWORD\t# left-clipped pixels\nRightClipPixels\tEQU DWORD PTR ebp - 54h ;DWORD\t# right-clipped pixels\nTopClipPixels\tEQU DWORD PTR ebp - 58h ;DWORD\t# top-clipped pixels\nBotClipPixels\tEQU DWORD PTR ebp - 5Ch ;DWORD\t# bottom-clipped pixels\nPixelWidth\tEQU DWORD PTR ebp - 60h \t;DWORD\tdrawable area in pixels\nPixelHeight\tEQU DWORD PTR ebp - 64h \t;DWORD\tdrawable area in pixels\n;......................... Drawing variables ...............................\nNumColors\tEQU DWORD PTR ebp - 68h ;DWORD\t# colors for 16-color shapes\nStartDraw\tEQU DWORD PTR ebp - 6Ch ;DWORD\toffset of drawing start pos\nNextLine\tEQU DWORD PTR ebp - 70h ;DWORD\toffset of next drawing line\nLeftClipBytes\tEQU DWORD PTR ebp - 74h ;DWORD\t# left-clipped bytes\nXTotal\t\tEQU DWORD PTR ebp - 78h ;DWORD\taccumulated x-pixels\nXTotalInit\tEQU DWORD PTR ebp - 7Ch ;DWORD\tinitial roundoff for XTotal\nYTotal\t\tEQU DWORD PTR ebp - 80h ;DWORD\taccumulated y-pixels\nHeightCount\tEQU DWORD PTR ebp - 84h ;DWORD\tht counter for drawing lines\nLineStart\tEQU DWORD PTR ebp - 88h ;DWORD\taddress of start of line\nWidthCount\tEQU DWORD PTR ebp - 8Ch ;DWORD\tcounts down # bytes skipped\nStashReg\tEQU DWORD PTR ebp - 90h \t;DWORD\ttemp variable for draw routines\nMaskAdjust\tEQU DWORD PTR ebp - 94h ;DWORD  priority buffer offset\nBackAdjust\tEQU DWORD PTR ebp - 98h ;DWORD  background buffer offset\nStashECX\tEQU DWORD PTR ebp - 9Ch \t;DWORD  temp variable for ECX register\nStashEDX\tEQU DWORD PTR ebp -0A0h \t;DWORD  temp variable for EDX register\n\nLocal_Size\tEQU 00A4h\t\t; Amt of data on stack: 4+last offset\n\n;****************************** Declarations *******************************\n;---------------------------------------------------------------------------\n; Global variables used by the shape routines, defined in drawshp.asm\n;---------------------------------------------------------------------------\nGLOBAL C ShapeBuffer:DWORD\nGLOBAL C ShapeBufferSize:DWORD\nGLOBAL C _MaskPage:DWORD\nGLOBAL C _BackGroundPage:DWORD\nGLOBAL C PredCount:DWORD\nGLOBAL C PredTable:BYTE\nGLOBAL C PredValue:DWORD\nGLOBAL C PartialPred:DWORD\nGLOBAL C PartialCount:DWORD\nGLOBAL C Flags:DWORD\n\n;---------------------------------------------------------------------------\n; External tables that are defined in ds_table.asm.\n;---------------------------------------------------------------------------\nGLOBAL LSkipTable:DWORD\nGLOBAL RSkipTable:DWORD\nGLOBAL DrawTable:DWORD\n\n;------------------------------------------------------------------------------\n; Public functions, declared in the order they appear in the function tables.\n;--------------------------------------------------------------------------------\nGLOBAL\tC Not_Supported:NEAR\n;\tLSkipTable:\nGLOBAL Left_Skip:NEAR\t\t\t\t\t\t; ds_ls\nGLOBAL Left_Reverse_Skip:NEAR\t\t\t\t; ds_lrs\nGLOBAL Left_Skip:NEAR\t\t\t\t\t\t; ds_ls\nGLOBAL Left_Reverse_Skip:NEAR\t\t\t\t; ds_lrs\nGLOBAL Left_Scale_Skip:NEAR\t\t\t\t; ds_lss\nGLOBAL Left_Scale_Reverse_Skip:NEAR\t\t; ds_lsrs\nGLOBAL Left_Scale_Skip:NEAR\t\t\t\t; ds_lss\nGLOBAL Left_Scale_Reverse_Skip:NEAR\t\t; ds_lsrs\n\n;\tRSkipTable:\nGLOBAL Right_Skip:NEAR\t\t\t\t\t   ; ds_rs\nGLOBAL Right_Reverse_Skip:NEAR\t\t\t; ds_rrs\nGLOBAL Right_Skip:NEAR\t\t\t\t\t   ; ds_rs\nGLOBAL Right_Reverse_Skip:NEAR\t\t\t; ds_rrs\nGLOBAL Right_Scale_Skip:NEAR\t\t\t\t; ds_rss\nGLOBAL Right_Scale_Reverse_Skip:NEAR\t; ds_rsrs\nGLOBAL Right_Scale_Skip:NEAR\t\t\t\t; ds_rss\nGLOBAL Right_Scale_Reverse_Skip:NEAR\t; ds_rsrs\n\n;\tDrawTable:\nGLOBAL Draw_Normal:NEAR\t\t\t\t\t; ds_dn\nGLOBAL Draw_Reverse:NEAR\t\t\t\t; ds_dr\nGLOBAL Draw_Normal:NEAR\t\t\t\t\t; ds_dn\nGLOBAL Draw_Reverse:NEAR\t\t\t\t; ds_dr\nGLOBAL Draw_Scale:NEAR\t\t\t\t\t; ds_ds\nGLOBAL Draw_Scale_Reverse:NEAR\t\t; ds_dsr\nGLOBAL Draw_Scale:NEAR\t\t\t\t\t; ds_ds\nGLOBAL Draw_Scale_Reverse:NEAR\t\t; ds_dsr\n\n\n;************************* End of shape.inc ********************************\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/ALLOC.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : ALLOC.CPP                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : February 1, 1992                         *\n *                                                                         *\n *                  Last Update : March 9, 1995 [JLB]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Alloc -- Allocates system RAM.                                        *\n *   Ram_Free -- Determines the largest free chunk of RAM.                 *\n *   Free -- Free an Alloc'ed block of RAM.                                *\n *   Resize_Alloc -- Change the size of an allocated block.                *\n *   Heap_Size -- Size of the heap we have.                                *\n *   Total_Ram_Free -- Total amount of free RAM.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <malloc.h>\n#include <string.h>\n#include <stdlib.h>\n#include <dos.h>\n#include <bios.h>\n\n\n#ifndef WWMEM_H\n#include \"wwmem.h\"\n#endif\n\n\nextern \"C\" unsigned long Largest_Mem_Block ( void ) ;\n\n/*\n** Define the equates necessary to call a DPMI interrupt.\n*/\n#define\tDPMI_INT\t\t\t\t\t\t\t\t\t0x0031\n#define\tDPMI_LOCK_MEM\t\t\t\t\t\t\t0x0600\n#define\tDPMI_UNLOCK_MEM\t\t\t\t\t\t0x0601\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\nunsigned long MinRam=0L;\t\t// Record of least memory at worst case.\nunsigned long MaxRam=0L;\t\t// Record of total allocated at worst case.\nstatic unsigned long TotalRam = 0L;\nstatic unsigned long Memory_Calls = 0L;\n\nvoid (*Memory_Error)(void) = NULL;\nextern void (*Memory_Error_Exit)(char *string)=NULL;\n\n\n//#define MEM_CHECK\n\n#ifdef MEM_CHECK\nextern \"C\"{\n\textern void __cdecl Int3(void);\n}\n#endif\t//MEM_CHECK\n\n/***************************************************************************\n * DPMI_LOCK -- handles locking a block of DPMI memory                     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n#include\"mono.h\"\nvoid DPMI_Lock(VOID const *, long const )\n{\n}\n\n/***************************************************************************\n * DPMI_UNLOCK -- Handles unlocking a locked block of DPMI                 *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid DPMI_Unlock(void const *, long const )\n{\n}\n\n/***************************************************************************\n * Alloc -- Allocates system RAM.                                          *\n *                                                                         *\n *    This is the basic RAM allocation function.  It is used for all       *\n *    memory allocations needed by the system or the main program.         *\n *                                                                         *\n * INPUT:   bytes_to_alloc -- LONG value of the number of bytes to alloc.  *\n *                                                                         *\n *          flags          -- Memory allocation control flags.             *\n *             MEM_NORMAL: No special flags.                               *\n *             MEM_CLEAR:  Zero out memory block.                        \t*\n *             MEM_NEW:\t\tCalled by a new.                                *\n *                                                                         *\n * OUTPUT:  Returns with pointer to allocated block.  If NULL was returned *\n *          it indicates a failure to allocate.  Note: NULL will never be  *\n *          returned if the standard library allocation error routine is   *\n *          used.                                                          *\n *                                                                         *\n * WARNINGS:   If you replace the standard memory allocation error routine *\n *             and make it so that Alloc CAN return with a NULL, be sure   *\n *             and check for this in your code.                            *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Documented.                                          *\n *   08/09/1993 JLB : Updated with EMS memory support.                     *\n *   04/28/1994 JAW : Updated to 32bit Protected mode.                     *\n *   03/09/1995 JLB : Fixed                                                *\n *   09/28/1995 ST  : Simplified for win95                                                                      *\n *=========================================================================*/\nvoid *Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags)\n{\n\n#ifdef WIN32\n\n\tvoid\t*mem_ptr;\n\n#ifdef MEM_CHECK\n\tbytes_to_alloc += 32;\n#endif\t//MEM_CHECK\n\n\tmem_ptr = malloc ( bytes_to_alloc );\n\n\tif ( !mem_ptr && Memory_Error ){\n\t\tMemory_Error();\n\t}\n\n\tif ( mem_ptr && ( flags & MEM_CLEAR ) ){\n\t\tmemset ( mem_ptr , 0 , bytes_to_alloc );\n\t}\n\n#ifdef MEM_CHECK\n\tmem_ptr = (void*)((char*)mem_ptr + 16);\n\tunsigned long *magic_ptr =(unsigned long*) ( ((char *)mem_ptr) - 16 );\n\t*magic_ptr++ = (unsigned long)mem_ptr;\n\t*magic_ptr++ = (unsigned long)mem_ptr;\n\t*magic_ptr++ = (unsigned long)mem_ptr;\n\t*magic_ptr \t = bytes_to_alloc - 32;\n\tmagic_ptr = (unsigned long*) ( ((char*)mem_ptr) + bytes_to_alloc - 32 );\n\t*magic_ptr++ = (unsigned long)mem_ptr;\n\t*magic_ptr++ = (unsigned long)mem_ptr;\n\t*magic_ptr++ = (unsigned long)mem_ptr;\n\t*magic_ptr \t = (unsigned long)mem_ptr;\n#endif\t//MEM_CHECK\n\n\tMemory_Calls++;\n\treturn ( mem_ptr );\n\n#else\n\n\n\n\tunion REGS\t\tregs ;\n\tstruct SREGS \tsregs ;\n\tunsigned char *retval=NULL;\t// Pointer to allocated block.\n\tunsigned long\toriginal_size;\t// Original allocation size.\n\tunsigned long\tbytesfree;\t\t// Number of free bytes.\n\tlong \t\t\t\t*longptr=NULL;\t// Pointer used to store selector\n\n\t/*\n\t** Save the original allocated space size so that we can clear the\n\t** exact amount of RAM if they specified MEM_CLEAR.\n\t*/\n\toriginal_size = bytes_to_alloc;\n\n\t/*\n\t** Reserve one byte for the header of the memory we allocated.\n\t** We will store the flags variable there for later use.\n\t*/\n\tbytes_to_alloc += (flags & MEM_LOCK) ? 5 : 1;\n\n\t/*\n\t**\tInitialize the total ram available value.\n\t*/\n\tif (!TotalRam) {\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\t}\n\n\n\t// Try to allocate the memory out of the protected mode memory\n\t// chain if we did not require a real mode allocation.  If this\n\t// fails we will have to try to allocate it out of real mode memory.\n\t// Real mode memory is a last resort because some types of applications\n\t// require real mode memory.\n\tif (!(flags & MEM_REAL)) {\n\t\tretval = (unsigned char*)malloc(bytes_to_alloc);\n\t}\n\n\t// Try to allocate the memory out of the real mode memory using DPMI\n\t// service 0x100.  Note that retval will be null if we are requesting\n\t// real mode memory so that we do not have to explicitly check for the\n\t// real mode flag.  Remember we need to reserve room for the dos\n\t// selector value at the beginning of our allocated block so rather than\n\t// adding fifteen and rounding, we need to add 19 and round.\n\tif (!retval) {\n\t\tflags = (MemoryFlagType)(flags | MEM_REAL);\n\t\tregs.x.eax = 0x100;\n\t\tregs.x.ebx = (bytes_to_alloc + 19) >> 4;\n\t\tif (regs.x.ebx & 0xFFFF0000) {\n\t\t\tretval = NULL;\n\t\t} else {\n\t\t\tsegread ( & sregs ) ;\n\t\t\tint386x ( 0x31 , & regs, & regs , & sregs\t) ;\n\t\t\tif (regs.x.cflag)\n\t\t\t\tretval = NULL;\n\t\t\telse {\n\t\t\t\tlongptr\t\t= (long *)(((regs.x.eax & 0xFFFF) << 4)+ 1);\n\t\t\t\t*longptr++\t= regs.x.edx & 0xFFFF;\n\t\t\t\tretval\t\t= (unsigned char *)longptr;\n\t\t\t}\n\t\t}\n\t}\n\n\t// If the alloc failed then we need to signify a memory error.\n\tif (retval == NULL) {\n\t\tif(Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\n\t}\n\n\t// If the memory needs to be DPMI locked then we should store the\n\t// original size in the header before we store the flags.\n\tif (flags & MEM_LOCK) {\n\t\tlongptr\t\t= (long *)retval;\n\t\t*longptr++\t= original_size;\n\t\tretval\t\t= (unsigned char *)longptr;\n\t}\n\n\n\t// Now that we know the alloc was sucessful (and for an extra byte\n\t// more than the user wanted) we need to stick in the memory flags.\n\t*retval++ \t\t= flags;\n\n\t// If the memory needed to be DPMI locked then set it up so it\n\t// is locked.\n\tif (flags & MEM_LOCK) {\n\t\tDPMI_Lock(retval, original_size);\n\n\t}\n\n\n\t/* Clear the space if they wanted it clear */\n\n\tif (flags & MEM_CLEAR) {\n\t\tunsigned char\t*ptr;\t\t// Working memory block pointer.\n\n\t\tptr = retval;\n\t\tmemset(ptr, '\\0', original_size);\n\t}\n\n\tbytesfree = Total_Ram_Free(MEM_NORMAL);\n\tif (bytesfree < MinRam) {\n\t\tMinRam = bytesfree;\n\t}\n\tif (TotalRam-bytesfree > MaxRam) {\n\t\tMaxRam = TotalRam-bytesfree;\n\t}\n\n\tMemory_Calls++;\n\n\treturn(retval);\n\n#endif\n}\n\n\n/***************************************************************************\n * Free -- Free an Alloc'ed block of RAM.                                  *\n *                                                                         *\n * FUNCTION:                                                               *\n *                                                                         *\n * INPUT:       A pointer to a block of RAM from Alloc.                    *\n *                                                                         *\n * OUTPUT:      None.                                                      *\n *                                                                         *\n * WARNINGS:    Don't use this for an Alloc_Block'ed RAM block.            *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/25/1990     : Created.                                             *\n ***************************************************************************/\n#ifdef WIN32\n\nvoid Free(void const *pointer)\n{\n\n\tif ( pointer ){\n\n#ifdef MEM_CHECK\n\n\t\tunsigned long\t*magic_ptr = (unsigned long*) ( ((char*)pointer) - 16 );\n\n\t\tif (*magic_ptr++ != (unsigned long)pointer ||\n\t\t \t*magic_ptr++ != (unsigned long)pointer ||\n\t\t \t*magic_ptr++ != (unsigned long)pointer ){\n\t\t \tInt3();\n\t\t}\n\n\t\tmagic_ptr = (unsigned long*) ( ((char*)pointer) + *magic_ptr );\n\n\t\tif (*magic_ptr++ != (unsigned long)pointer ||\n\t\t \t*magic_ptr++ != (unsigned long)pointer ||\n\t\t \t*magic_ptr++ != (unsigned long)pointer ||\n\t\t \t*magic_ptr++ != (unsigned long)pointer ){\n\t\t \tInt3();\n\t\t}\n\n\t\tpointer = (void*) (((char*)pointer)-16);\n#endif\t//MEM_CHECK\n\n\t\tfree ( (void*)pointer );\n\t\tMemory_Calls--;\n\t}\n\n#else\n\nvoid Free(void const *pointer)\n{\n\n\tunion REGS\t\tregs ;\n\tstruct SREGS \tsregs ;\n\n\n\tif (pointer) {\n\t\t/*\n\t\t** Get a pointer to the flags that we stored off.\n\t\t*/\n\t\tchar *byteptr\t= ((char *)pointer) - 1;\n\n\t\t/*\n\t\t** Check to see if this was locked me and if it was unlock it.\n\t\t*/\n\t\tif (*byteptr & MEM_LOCK) {\n\t\t\tlong *longptr = ((long *)byteptr) - 1;\n\t\t\tDPMI_Unlock(pointer, *longptr);\n\t\t\tpointer = (void *)longptr;\n\t\t} else\n\t\t\tpointer = (void *)byteptr;\n\n\n\t\t// If the pointer is a real mode pointer than it will point to the\n\t\t// first megabyte of system memory.  If it does than we need to\n\t\t// use DPMI to free it.\n\t\tif (*byteptr & MEM_REAL) {\n\t\t\tregs.x.eax\t= 0x101;\n\t\t\tregs.x.edx\t= *(((long *)pointer) - 1);\n\t\t\tsegread ( & sregs ) ;\n\t\t\tint386x(0x31, &regs, &regs, &sregs);\n\t\t} else {\n\t\t\tfree((void *)pointer);\n\t\t}\n\t\tMemory_Calls--;\n\t}\n\n#endif\n}\n\n\n\n/***************************************************************************\n * Resize_Alloc -- Change the size of an allocated block.                  *\n *                                                                         *\n *    This routine will take a previously allocated block and change its   *\n *    size without unnecessarily altering its contents.                    *\n *                                                                         *\n * INPUT:   pointer  -- Pointer to the original memory allocation.         *\n *                                                                         *\n *          new_size -- Size in bytes that it will be converted to.        *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the new allocation.                  *\n *                                                                         *\n * WARNINGS:   ???                                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/01/1992 JLB : Commented.                                           *\n *=========================================================================*/\nvoid *Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes)\n{\n\n\tunsigned long *temp;\n\n\ttemp = (unsigned long*)original_ptr;\n\n\t/* ReAlloc the space */\n\ttemp = (unsigned long *)realloc(temp, new_size_in_bytes);\n\tif (temp == NULL) {\n\t\tif(Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\n\t}\n\n\treturn(temp);\n}\n\n\n/***************************************************************************\n * Ram_Free -- Determines the largest free chunk of RAM.                   *\n *                                                                         *\n *    Use this routine to determine the largest free chunk of available    *\n *    RAM for allocation.  It also performs a check of the memory chain.   *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  Returns with the size of the largest free chunk of RAM.        *\n *                                                                         *\n * WARNINGS:   This does not return the TOTAL memory free, only the        *\n *             largest free chunk.                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Commented.                                           *\n *=========================================================================*/\nlong Ram_Free(MemoryFlagType)\n{\n//\treturn(_memmax());\n#if(0)\n\tMEMORYSTATUS\tmem_info;\n\tmem_info.dwLength=sizeof(mem_info);\n\tGlobalMemoryStatus(&mem_info);\n\treturn ( mem_info.dwAvailPhys );\n#endif\n\treturn ( 64*1024*1024 );\n}\n\n\n/***************************************************************************\n * Heap_Size -- Size of the heap we have.                                  *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Heap_Size(MemoryFlagType )\n{\n\tif (!TotalRam) {\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\t}\n\treturn(TotalRam);\n}\n\n\n/***************************************************************************\n * Total_Ram_Free -- Total amount of free RAM.                             *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *   03/09/1995 JLB : Uses prerecorded heap size maximum.                  *\n *=========================================================================*/\nlong Total_Ram_Free(MemoryFlagType )\n{\n#if(0)\n\tMEMORYSTATUS\tmem_info;\n\tmem_info.dwLength=sizeof(mem_info);\n\tGlobalMemoryStatus(&mem_info);\n\treturn ( mem_info.dwAvailPhys );\n#endif\n\n\treturn ( 64*1024*1024 );\n}\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/APROFILE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Profiler                                 *\n;*                                                                         *\n;*                    File Name : APROFILE.ASM                             *\n;*                                                                         *\n;*                   Programmer : Steve Tall\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : November 17th, 1995\t\t\t   *\n;*                                                                         *\n;*                  Last Update : November 20th, 1995   [ST]               *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   __PRO -- must be called at the beginning of each function             *\n;*   __EPI -- must be called at the end of each function\t           *\n;*   Copy_CHL -- initialise the profiler asm data                          *\n;*   Profiler_Callback -- windows callback for millisecond timer           *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\n\n\t\tp386\n\t\tmodel\tflat\n\t\tideal\n\t\tjumps\n\n\nMAX_PROFILE_TIME = 60*1\t\t;1 minute(s)\nPROFILE_RATE\t = 1000\t\t;1000 samples per sec\n\n\n;\n; Externs\n;\n;\nglobal\t\tC ProfileFunctionAddress:dword\nglobal\t\tC ProfilePtr:dword\nglobal\t\tC ProfileList:dword\nglobal\t\tC Stop_Profiler:near\nglobal\t\tNew_Profiler_Callback_:near\nglobal\t\tOld_Profiler_Callback_:near\nglobal\t\tC Profile_Init:near\nglobal\t\tC Profile_End:near\nglobal\t\t___begtext:near\nglobal\t\tBaseAddress:dword\nglobal\t\t__PRO:near\nglobal\t\t__EPI:near\nglobal\t\tMyStack:dword\nglobal\t\tMyStackPtr:dword\nglobal\t\tProAddress:dword\nglobal\t\tEpiAddress:dword\n\n\n\t\tcodeseg\n\n\n;*********************************************************************************************\n;* __PRO -- registers the current procedure                                                  *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      none                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*  Assumes that ss:Esp points to return address in function to be registered                *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   11/20/95 4:39PM ST : Created.                                                           *\n;*===========================================================================================*\n\nproc\t\t__PRO near\n\n\t\tjmp\t[ProAddress]\n; safe version of prologue code\nPro_Start:\tpush\teax\n\t\tmov\teax,[MyStackPtr]\n\t\tpush\t[ProfileFunctionAddress]\n\t\tpop\t[eax*4+MyStack]\n\t\tinc\t[MyStackPtr]\n\t\tpop\teax\n\t\tpush\t[dword ss:esp]\n\t\tpop\t[ProfileFunctionAddress]\nPro_End:\tret\n\n; unsafe (but much faster) prologue code\n;\t\tpop\t[ProfileFunctionAddress]\n;\t\tjmp\t[ProfileFunctionAddress]\n\nendp\t\t__PRO\n\n\n;*********************************************************************************************\n;* __EPI -- Registers the privious procedure as current again                                *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      none                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*  Assumes that calling procedure will pop ebp immediately on return so we dont have to     *\n;*  preserve it.                                                                             *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   11/20/95 4:42PM ST : Created.                                                           *\n;*===========================================================================================*\n\nproc\t\t__EPI near\n\n\t\tjmp\t[EpiAddress]\n; Safe version of epilogue code. Uncomment the push and pop for ultimate safety\nEpi_Start:\tdec\t[MyStackPtr]\n;\t\tpush\tebp\n\t\tmov\tebp,[MyStackPtr]\n\t\tmov\tebp,[ebp*4+MyStack]\n\t\tmov\t[ProfileFunctionAddress],ebp\n;\t\tpop\tebp\nEpi_End:\tret\n\n; Unsafe (but much faster) epilogue code. Makes lots of assumptions.\n;\t\tpush\t[dword esp+8]\n;\t\tpop\t[ProfileFunctionAddress]\n;\t\tret\n\nendp\t\t__EPI\n\n\n\n;*********************************************************************************************\n;* Profile_Init -- Initialises the .asm data required for profile session                    *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      none                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*   Assumes that '___begtext' is the first label in the code segment and that its           *\n;*   address is within 15 bytes of the start of the code segment                             *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   11/20/95 4:44PM ST : Created.                                                           *\n;*===========================================================================================*\n\nproc\t\tProfile_Init C near\n\n\t\tmov\teax,offset ___begtext\n\t\tand\teax,0fffffff0h\n\t\tmov\t[BaseAddress],eax\n\t\t;mov\t[MyStackPtr],0\n\t\tmov\t[ProfileList],PROFILE_RATE\n\t\tmov\t[ProfilePtr],1\n\t\tmov\t[ProAddress],offset Pro_Start\n\t\tmov\t[EpiAddress],offset Epi_Start\n\t\tret\n\nendp\t\tProfile_Init\n\n\n\n\n\n;*********************************************************************************************\n;* Profile_End -- disables the __PRO and __EPI procedures                                    *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      none                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   11/20/95 4:44PM ST : Created.                                                           *\n;*===========================================================================================*\n\nproc\t\tProfile_End C near\n\n\t\tmov\t[ProAddress],offset Pro_End\n\t\tmov\t[EpiAddress],offset Epi_End\n\t\tret\n\nendp\t\tProfile_End\n\n\n\n\n\n\n;*********************************************************************************************\n;* New_Profiler_Callback -- Windows callback used to register function hits                  *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      none                                                                         *\n;*                                                                                           *\n;* Note:                                                                                     *\n;*   The frequency that this is called depends on MAX_PROFILE_RATE defined here and in       *\n;*   profile.h                                                                               *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   11/20/95 4:47PM ST : Created.                                                           *\n;*===========================================================================================*\nproc\t\tNew_Profiler_Callback_ near\n\n\t\tpush\teax\n\t\tpush\tesi\n\t\tmov\tesi,[ProfilePtr]\n\t\tcmp\tesi,MAX_PROFILE_TIME*PROFILE_RATE\n\t\tjge\t@@out\n\t\tmov\teax,[ProfileFunctionAddress]\n\t\tsub\teax,[BaseAddress]\n\t\tmov\t[ProfileList+esi*4],eax\n\t\tinc\t[ProfilePtr]\n\t\tpop\tesi\n\t\tpop\teax\n\t\tret\n\n@@out:\t\tcall\tStop_Profiler\n\t\tpop\tesi\n\t\tpop\teax\n\t\tret\n\nendp\t\tNew_Profiler_Callback_\n\n\n\n;*********************************************************************************************\n;* Old_Profiler_Callback -- Windows callback used to register function hits                  *\n;*                                                                                           *\n;* INPUT:\tWindows timer callback stuff - not used                                      *\n;*                                                                                           *\n;* OUTPUT:      none                                                                         *\n;*                                                                                           *\n;* Note:                                                                                     *\n;*   The frequency that this is called depends on MAX_PROFILE_RATE defined here and in       *\n;*   profile.h                                                                               *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   11/20/95 4:47PM ST : Created.                                                           *\n;*===========================================================================================*\n\nproc\t\tOld_Profiler_Callback_ near\n\n\t\tpush\teax\n\t\tpush\tesi\n\t\tmov\tesi,[ProfilePtr]\n\t\tcmp\tesi,MAX_PROFILE_TIME*PROFILE_RATE\n\t\tjge\t@@out\n\t\tmov\teax,[ProfileFunctionAddress]\n\t\tsub\teax,[BaseAddress]\n\t\tmov\t[ProfileList+esi*4],eax\n\t\tinc\t[ProfilePtr]\n\t\tpop\tesi\n\t\tpop\teax\n\t\tret\t14h\n\n@@out:\t\tcall\tStop_Profiler\n\t\tpop\tesi\n\t\tpop\teax\n\t\tret\t14h\n\nendp\t\tOld_Profiler_Callback_\n\n\n\n\t\tdataseg\n\t\talign\t4\n\nProfileFunctionAddress\tdd\t0\t\t;Ptr to function we are currently in\nBaseAddress\t\tdd\t0\t\t;Address of the code segment start\nMyStackPtr\t\tdd\t0\t\t;offset into my stack table\nProAddress\t\tdd\tPro_Start\t;jmp ptr for __PRO procedure\nEpiAddress\t\tdd\tEpi_Start\t;jmp ptr for __EPI procedure\n\nlabel MyStack dword\t\t\t;my stack table\n\t\t\tdd\t16*1024 dup (?)\n\nend\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/AUDUNCMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Audio Library            *\n;*                                                                         *\n;*                    File Name : AUDUNCMP.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : March 14, 1995                           *\n;*                                                                         *\n;*                  Last Update : June 26, 1995   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Decompress_Frame_Lock -- locks the JLB audio decompression code       *\n;*   Decompress_Frame_Unlock -- Unlocks the JLB audio compression code     *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\nDPMI_INTR\t\tequ\t31h\n\nLABEL \tLockedCodeStart\tBYTE\n\nCODE_2BIT\tEQU\t0\nCODE_4BIT\tEQU\t1\nCODE_RAW\tEQU\t2\nCODE_SILENCE\tEQU\t3\nMAGICNUMBER\tEQU\t00000DEAFh\nMAGICNUMBER2\tEQU\t0BABEBABEh\n\n_2bitdecode\tDB\t-2,-1,0,1\n_4bitdecode\tDB\t-9,-8,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,8\n\n\n;***************************************************************************\n;* DECOMPRESS_FRAME -- Uncompresses a WW compressed audio frame            *\n;*                                                                         *\n;* INPUT:\tvoid * source - pointer to encoded audio data              *\n;*\t\tvoid * dest   - pointer to decompression area\t\t   *\n;*\t\tlong size     - the maximum size of destination buffer\t   *\n;*                                                                         *\n;* OUTPUT:      long - the number of bytes we uncompressed                 *\n;*                                                                         *\n;* PROTO:\tlong Decompress_Frame(void *, void *, long);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/14/1995 PWG : Created.                                             *\n;*=========================================================================*\n\n\tGLOBAL\tC Decompress_Frame:NEAR\n\tPROC\tDecompress_Frame C NEAR USES ebx ecx edx esi edi\n\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tcount:DWORD\n\n\tLOCAL\tprevious:BYTE\n\tLOCAL\tincount:DWORD\n\n\tpushfd\n\tcld\n\tmov\t[incount],0\t;Bytes read from source\n\n\n;\tSource, Dest and count must be valid.\n\n\tcmp\t[source],0\n\tje\t??fini\n\n\tcmp\t[dest],0\n\tje\t??fini\n\n\tcmp\t[count],0\n\tje\t??fini\n\n\tmov\tesi,[source]\t;Pointer to source data.\n\tmov\tedi,[dest]\t;Pointer to destination data.\n\tmov\tecx,[count]\t;Number of bytes to fill dest buffer.\n\tmov\tdl,080h\t;Previous sample (starting value).\n\n??mainloop:\n\tcmp\tecx,0\t;If dest full then exit\n\tjle\t??fini\n\n\txor\teax,eax\n\tmov\tal,[esi]\t;Get code byte\n\tinc\t[incount]\n\tinc\tesi\n\tshl\teax,2\t;AH contains code.\n\tshr\tal,2\t;AL contains sub-code data.\n\n\tcmp\tah,CODE_RAW\t;Raw sequence?\n\tjne\tshort ??try4bit\n\n;\tThe code contains either a 5 bit delta or a count of\n;\traw samples to dump out.\n\n\ttest\tal,00100000b\n\tje\tshort ??justraw\n\n;\tThe lower 5 bits are actually a signed delta.\n;\tSign extend the delta and add it to the stream.\n\n\tshl\tal,3\n\tsar\tal,3\n\tadd\tdl,al\n\tmov\t[edi],dl\n\tdec\tecx\n\tinc\tedi\n\tjmp\t??mainloop\n\n;\tThe lower 5 bits hold a count of the number of raw\n;\tsamples that follow this code. Dump these samples to\n;\tthe output buffer.\n\n??justraw:\n\tmov\tebx,ecx\n\txor\tah,ah\n\tinc\tal\n\tmov\tecx,eax\n\tshr\tecx,1\n\trep\tmovsw\n\tadc\tecx,ecx\n\trep\tmovsb\n\tmov\tecx,ebx\n\tadd\t[incount],eax\n\tsub\tecx,eax\n\tdec\tedi\n\tmov\tdl,[edi]\t;Set \"previous\" value.\n\tinc\tedi\n\tjmp\t??mainloop\n\n;\tCheck to see if this is a 4 bit delta code sequence.\n\n??try4bit:\n\tinc\tal\t;Following codes use AL+1\n\tcmp\tah,CODE_4BIT\n\tjne\tshort ??try2bit\n\n;\tA sequence of 4bit deltas follow. AL equals the\n;\tnumber of nibble packed delta bytes to process.\n\n??bit4loop:\n\tmov\tah,[esi]\t;Fetch nibble packed delta codes\n\tmov\tbl,ah\n\tinc\t[incount]\n\tinc\tesi\n\n;\tAdd first delta to 'previous' sample already in DL.\n\n\tand\tebx,00001111b\n\tadd\tdl,[_4bitdecode+ebx]\n\tpushfd\n\tcmp\t[_4bitdecode+ebx],0\n\tjl\tshort ??neg1\n\n\tpopfd\n\tjnc\tshort ??ok1\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok1\n\n??neg1:\n\tpopfd\n\tjc\tshort ??ok1\n\n\txor\tdl,dl\n\n??ok1:\n\tmov\tdh,dl\t;DH now holds new 'previous' sample.\n\tmov\tbl,ah\n\tshr\tbl,4\n\tadd\tdh,[_4bitdecode+ebx]\n\tpushfd\n\tcmp\t[_4bitdecode+ebx],0\n\tjl\tshort ??neg2\n\n\tpopfd\n\tjnc\tshort ??ok2\n\n\tmov\tdh,0FFh\n\tjmp\tshort ??ok2\n\n??neg2:\n\tpopfd\n\tjc\tshort ??ok2\n\n\txor\tdh,dh\n\n??ok2:\n\tmov\t[edi],dx\t;Output the two sample bytes\n\tsub\tecx,2\n\tadd\tedi,2\n\n;\tPut the correct 'previous' sample in DL where it belongs.\n\n\tmov\tdl,dh\n\n;\tIf there are more deltas to process then loop back.\n\n\tdec\tal\n\tjnz\tshort ??bit4loop\n\tjmp\t??mainloop\n\n;\tCheck to see if 2 bit deltas need to be processed.\n\n??try2bit:\n\tcmp\tah,CODE_2BIT\n\tjne\t??zerodelta\n\n;\tA sequence of 2bit deltas follow.  AL equals the number of\n;\tpacked delta bytes to process.\n\n??bit2loop:\n\tmov\tah,[esi]\t;Fetch packed delat codes\n\tinc\t[incount]\n\tinc\tesi\n\n;\tAdd first delta to 'previous' sample already in DL.\n\n\tmov\tbl,ah\n\tand\tebx,000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushfd\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg3\n\n\tpopfd\n\tjnc\tshort ??ok3\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok3\n\n??neg3:\n\tpopfd\n\tjc\tshort ??ok3\n\txor\tdl,dl\n\n??ok3:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,2\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushfd\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg4\n\n\tpopfd\n\tjnc\tshort ??ok4\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok4\n\n??neg4:\n\tpopfd\n\tjc\tshort ??ok4\n\n\txor\tdl,dl\n\n??ok4:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,4\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushfd\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg5\n\n\tpopfd\n\tjnc\tshort ??ok5\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok5\n\n??neg5:\n\tpopfd\n\tjc\tshort ??ok5\n\n\txor\tdl,dl\n\n??ok5:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,6\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushfd\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg6\n\n\tpopfd\n\tjnc\tshort ??ok6\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok6\n\n??neg6:\n\tpopfd\n\tjc\tshort ??ok6\n\n\txor\tdl,dl\n\n??ok6:\n\tror\tedx,8\n\tmov\t[edi],edx\t;Output two sample bytes\n\tsub\tecx,4\n\tadd\tedi,4\n\n;\tPut the correct 'previous' sample in DL where it belongs.\n\n\trol\tedx,8\n\n;\tIf there are more deltas to process then loop back.\n\n\tdec\tal\n\tjnz\t??bit2loop\n\tjmp\t??mainloop\n\n;\tThere is a run of zero deltas.  Zero deltas merely duplicate\n;\tthe 'previous' sample the requested number of times.\n\n??zerodelta:\n\txor\tebx,ebx\n\tmov\tbl,al\n\tmov\tal,dl\n\tsub\tecx,ebx\n\txchg\tecx,ebx\n\trep\tstosb\n\tmov\tecx,ebx\n\tjmp\t??mainloop\n\n??fini:\n\tpopfd\n\tmov\teax,[incount]\n\tret\n\n\tENDP\tDecompress_Frame\n\nLABEL \tLockedCodeEnd\tBYTE\n\n\n\n\n\n\tEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/BITBLIT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : BITBLIT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Julio R. Jerez                           *\n;*                                                                         *\n;*                   Start Date : Feb 6, 1995                              *\n;*                                                                         *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nCODESEG\n\n\tPROC\tLinear_Blit_To_Linear C near\n\tUSES\tebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG    \tthis_object :DWORD\t\t; this is a member function\n\tARG\tdest        :DWORD\t\t; what are we blitting to\n\tARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\tARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\tARG\tdest_x0     :dword\n\tARG\tdest_y0     :dword\n\tARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\tARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\tARG\ttrans       :DWORD\t\t\t; do we deal with transparents?\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tLOCAL\tdest_x1 : dword\n\tLOCAL\tdest_y1 : dword\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_ajust_width:DWORD\n        LOCAL\tsource_area :  dword\n        LOCAL\tdest_area :  dword\n\n;This Clipping algorithm is a derivation of the very well known\n;Cohen-Sutherland Line-Clipping test. Due to its simplicity and efficiency\n;it is probably the most commontly implemented algorithm both in software\n;and hardware for clipping lines, rectangles, and convex polygons against\n;a rectagular clipping window. For reference see\n;\"COMPUTER GRAPHICS principles and practice by Foley, Vandam, Feiner, Hughes\n; pages 113 to 177\".\n; Briefly consist in computing the Sutherland code for both end point of\n; the rectangle to find out if the rectangle is:\n; - trivially accepted (no further clipping test, display rectangle)\n; - trivially rejected (return with no action)\n; - retangle must be iteratively clipped again edges of the clipping window\n;   and the remaining retangle is display.\n\n; Clip Source Rectangle against source Window boundaries.\n\tmov  \tesi,[this_object]    ; get ptr to src\n\txor \tecx,ecx\t\t    ; Set sutherland code to zero\n\txor \tedx,edx\t\t    ; Set sutherland code to zero\n\n   ; compute the difference in the X axis and get the bit signs into ecx , edx\n\tmov\tedi,[(GraphicViewPort esi).GVPWidth]  ; get width into register\n\tmov\tebx,[x_pixel]\t    ; Get first end point x_pixel into register\n\tmov\teax,[x_pixel]\t    ; Get second end point x_pixel into register\n\tadd\tebx,[pixel_width]   ; second point x1_pixel = x + width\n\tshld\tecx, eax,1\t    ; the sign bit of x_pixel is sutherland code0 bit4\n\tmov\t[x1_pixel],ebx\t    ; save second for future use\n\tinc\tedi\t\t    ; move the right edge by one unit\n\tshld\tedx,ebx,1\t    ; the sign bit of x1_pixel is sutherland code0 bit4\n\tsub\teax,edi\t\t    ; compute the difference x0_pixel - width\n\tsub\tebx,edi\t\t    ; compute the difference x1_pixel - width\n\tshld\tecx,eax,1\t    ; the sign bit of the difference is sutherland code0 bit3\n\tshld\tedx,ebx,1\t    ; the sign bit of the difference is sutherland code0 bit3\n\n   ; the following code is just a repeticion of the above code\n   ; in the Y axis.\n\tmov\tedi,[(GraphicViewPort esi).GVPHeight] ; get height into register\n\tmov\tebx,[y_pixel]\n\tmov\teax,[y_pixel]\n\tadd\tebx,[pixel_height]\n\tshld\tecx,eax,1\n\tmov\t[y1_pixel ],ebx\n\tinc\tedi\n\tshld\tedx,ebx,1\n\tsub\teax,edi\n\tsub\tebx,edi\n\tshld\tecx,eax,1\n\tshld\tedx,ebx,1\n\n    ; Here we have the to Sutherland code into cl and dl\n\txor\tcl,5\t\t       ; bit 2 and 0 are complented, reverse then\n\txor\tdl,5\t\t       ; bit 2 and 0 are complented, reverse then\n\tmov\tal,cl\t\t       ; save code1 in case we have to clip iteratively\n\ttest\tdl,cl\t\t       ; if any bit in code0 and its counter bit\n\tjnz\t??real_out\t       ; in code1 is set then the rectangle in outside\n\tor\tal,dl\t\t       ; if all bit of code0 the counter bit in\n\tjz\t??clip_against_dest    ; in code1 is set to zero, then all\n\t\t\t\t       ; end points of the rectangle are\n\t\t\t\t       ; inside the clipping window\n\n     ; if we are here the polygon have to be clip iteratively\n\ttest\tcl,1000b\t       ; if bit 4 in code0 is set then\n\tjz\t??scr_left_ok\t       ; x_pixel is smaller than zero\n\tmov\t[x_pixel],0\t       ; set x_pixel to cero.\n\n??scr_left_ok:\n\ttest\tcl,0010b\t       ; if bit 2 in code0 is set then\n\tjz\t??scr_bottom_ok\t       ; y_pixel is smaller than zero\n\tmov\t[ y_pixel ],0\t       ; set y_pixel to cero.\n\n??scr_bottom_ok:\n\ttest\tdl,0100b\t       ; if bit 3 in code1 is set then\n\tjz\t??scr_right_ok\t       ; x1_pixel is greater than the width\n\tmov\teax,[(GraphicViewPort esi).GVPWidth] ; get width into register\n\tmov\t[ x1_pixel ],eax       ; set x1_pixel to width.\n??scr_right_ok:\n\ttest\tdl,0001b\t       ; if bit 0 in code1 is set then\n\tjz\t??clip_against_dest    ; y1_pixel is greater than the width\n\tmov\teax,[(GraphicViewPort esi).GVPHeight]  ; get height into register\n\tmov\t[ y1_pixel ],eax       ; set y1_pixel to height.\n\n; Clip Source Rectangle against destination Window boundaries.\n??clip_against_dest:\n\n   ; build the destination rectangle before clipping\n   ; dest_x1 = dest_x0 + ( x1_pixel - x_pixel )\n   ; dest_y1 = dest_y0 + ( y1_pixel - y_pixel )\n\tmov\teax,[dest_x0]\t     ; get dest_x0 into eax\n\tmov\tebx,[dest_y0]\t     ; get dest_y0 into ebx\n\tsub\teax,[x_pixel]\t     ; subtract x_pixel from eax\n\tsub\tebx,[y_pixel]\t     ; subtract y_pixel from ebx\n\tadd\teax,[x1_pixel]\t     ; add x1_pixel to eax\n\tadd\tebx,[y1_pixel]\t     ; add y1_pixel to ebx\n\tmov\t[dest_x1],eax\t     ; save eax into dest_x1\n\tmov\t[dest_y1],ebx\t     ; save eax into dest_y1\n\n\n  ; The followin code is a repeticion of the Sutherland clipping\n  ; descrived above.\n\tmov  \tesi,[dest]\t    ; get ptr to src\n\txor \tecx,ecx\n\txor \tedx,edx\n\tmov\tedi,[(GraphicViewPort esi).GVPWidth]  ; get width into register\n\tmov\teax,[dest_x0]\n\tmov\tebx,[dest_x1]\n\tshld\tecx,eax,1\n\tinc\tedi\n\tshld\tedx,ebx,1\n\tsub\teax,edi\n\tsub\tebx,edi\n\tshld\tecx,eax,1\n\tshld\tedx,ebx,1\n\n\tmov\tedi,[( GraphicViewPort esi) . GVPHeight ] ; get height into register\n\tmov\teax,[dest_y0]\n\tmov\tebx,[dest_y1]\n\tshld\tecx,eax,1\n\tinc\tedi\n\tshld\tedx,ebx,1\n\tsub\teax,edi\n\tsub\tebx,edi\n\tshld\tecx,eax,1\n\tshld\tedx,ebx,1\n\n\txor\tcl,5\n\txor\tdl,5\n\tmov\tal,cl\n\ttest\tdl,cl\n\tjnz\t??real_out\n\tor\tal,dl\n\tjz\t??do_blit\n\n\ttest\tcl,1000b\n\tjz\t??dest_left_ok\n\tmov\teax,[ dest_x0 ]\n\tmov\t[ dest_x0 ],0\n\tsub\t[ x_pixel ],eax\n\n??dest_left_ok:\n\ttest\tcl,0010b\n\tjz\t??dest_bottom_ok\n\tmov\teax,[ dest_y0 ]\n\tmov\t[ dest_y0 ],0\n\tsub\t[ y_pixel ],eax\n\n\n??dest_bottom_ok:\n\ttest\tdl,0100b\n\tjz\t??dest_right_ok\n\tmov\tebx,[ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\teax,[ dest_x1 ]\n\tmov\t[ dest_x1 ],ebx\n\tsub\teax,ebx\n\tsub\t[ x1_pixel ],eax\n\n??dest_right_ok:\n\ttest\tdl,0001b\n\tjz\t??do_blit\n\tmov\tebx,[ (GraphicViewPort esi) . GVPHeight ]  ; get width into register\n\tmov\teax,[ dest_y1 ]\n\tmov\t[ dest_y1 ],ebx\n\tsub\teax,ebx\n\tsub\t[ y1_pixel ],eax\n\n\n; Here is where\twe do the actual blit\n??do_blit:\n       cld\n       mov\tebx,[this_object]\n       mov\tesi,[(GraphicViewPort ebx).GVPOffset]\n       mov\teax,[(GraphicViewPort ebx).GVPXAdd]\n       add\teax,[(GraphicViewPort ebx).GVPWidth]\n       add\teax,[(GraphicViewPort ebx).GVPPitch]\n       mov\tecx,eax\n       mul\t[y_pixel]\n       add\tesi,[x_pixel]\n       mov\t[source_area],ecx\n       add\tesi,eax\n\n       add\tecx,[x_pixel ]\n       sub\tecx,[x1_pixel ]\n       mov\t[scr_ajust_width ],ecx\n\n       mov\tebx,[dest]\n       mov\tedi,[(GraphicViewPort ebx).GVPOffset]\n       mov\teax,[(GraphicViewPort ebx).GVPXAdd]\n       add\teax,[(GraphicViewPort ebx).GVPWidth]\n       add\teax,[(GraphicViewPort ebx).GVPPitch]\n       mov\tecx,eax\n       mul\t[ dest_y0 ]\n       add\tedi,[ dest_x0 ]\n       mov\t[ dest_area ],ecx\n       add\tedi,eax\n\n       mov\teax,[ dest_x1 ]\n       sub\teax,[ dest_x0 ]\n       jle\t??real_out\n       sub\tecx,eax\n       mov\t[ dest_ajust_width ],ecx\n\n       mov\tedx,[ dest_y1 ]\n       sub\tedx,[ dest_y0 ]\n       jle\t??real_out\n\n       cmp\tesi,edi\n       jz\t??real_out\n       jl\t??backupward_blit\n\n; ********************************************************************\n; Forward bitblit\n\n       test\t[ trans ],1\n       jnz\t??forward_Blit_trans\n\n\n; the inner loop is so efficient that\n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax,10\n       jl\t??forward_loop_bytes\n\n??forward_loop_dword:\n       mov\tecx,edi\n       mov\tebx,eax\n       neg\tecx\n       and\tecx,3\n       sub\tebx,ecx\n       rep\tmovsb\n       mov\tecx,ebx\n       shr\tecx,2\n       rep\tmovsd\n       mov\tecx,ebx\n       and\tecx,3\n       rep\tmovsb\n       add\tesi,[ scr_ajust_width ]\n       add\tedi,[ dest_ajust_width ]\n       dec\tedx\n       jnz\t??forward_loop_dword\n       ret\n\n??forward_loop_bytes:\n       mov\tecx,eax\n       rep\tmovsb\n       add\tesi,[ scr_ajust_width ]\n       add\tedi,[ dest_ajust_width ]\n       dec\tedx\n       jnz\t??forward_loop_bytes\n       ret\n\n??forward_Blit_trans:\n       mov\tecx,eax\n       and\tecx,01fh\n       lea\tecx,[ ecx + ecx * 4 ]\n       neg\tecx\n       shr\teax,5\n       lea\tecx,[ ??transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ],ecx\n\n??forward_loop_trans:\n       mov\tecx,eax\n       jmp\t[ y1_pixel ]\n??forward_trans_line:\n       REPT\t32\n       local\ttransp_pixel\n       \t\tmov\tbl,[ esi ]\n       \t\ttest\tbl,bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ],bl\n    \t    transp_pixel:\n       \t\tinc\tesi\n\t    \tinc\tedi\n\tENDM\n    ??transp_reference:\n       dec\tecx\n       jge\t??forward_trans_line\n       add\tesi,[ scr_ajust_width ]\n       add\tedi,[ dest_ajust_width ]\n       dec\tedx\n       jnz\t??forward_loop_trans\n       ret\n\n\n; ************************************************************************\n; backward bitblit\n\n??backupward_blit:\n\n\tmov\tebx,[ source_area ]\n\tdec\tedx\n\tadd\tesi,eax\n\timul    ebx,edx\n\tstd\n\tlea\tesi,[ esi + ebx - 1 ]\n\n\tmov\tebx,[ dest_area ]\n\tadd\tedi,eax\n\timul    ebx,edx\n\tlea\tedi,[ edi + ebx - 1]\n\n       test\t[ trans ],1\n       jnz\t??backward_Blit_trans\n\n        cmp\teax,15\n        jl\t??backward_loop_bytes\n\n??backward_loop_dword:\n\tpush\tedi\n\tpush\tesi\n\tlea\tecx,[edi+1]\n\tmov\tebx,eax\n\tand\tecx,3\t\t; Get non aligned bytes.\n\tsub\tebx,ecx\t\t; remove that from the total size to be copied later.\n\trep\tmovsb\t\t; do the copy.\n\tsub\tesi,3\n\tmov\tecx,ebx\t\t; Get number of bytes left.\n \tsub\tedi,3\n\tshr\tecx,2\t\t; Do 4 bytes at a time.\n\trep\tmovsd\t\t; do the dword copy.\n\tmov\tecx,ebx\n\tadd\tesi,3\n\tadd\tedi,3\n\tand\tecx,03h\n\trep\tmovsb\t\t; finnish the remaining bytes.\n\tpop\tesi\n\tpop\tedi\n        sub\tesi,[ source_area ]\n        sub\tedi,[ dest_area ]\n\tdec\tedx\n\tjge\t??backward_loop_dword\n\tcld\n\tret\n\n??backward_loop_bytes:\n\tpush\tedi\n\tmov\tecx,eax\t\t; remove that from the total size to be copied later.\n\tpush\tesi\n\trep\tmovsb\t\t; do the copy.\n\tpop\tesi\n\tpop\tedi\n        sub\tesi,[ source_area ]\n        sub\tedi,[ dest_area ]\n\tdec\tedx\n\tjge\t??backward_loop_bytes\n\tcld\n\tret\n\n??backward_Blit_trans:\n       mov\tecx,eax\n       and\tecx,01fh\n       lea\tecx,[ ecx + ecx * 4 ]\n       neg\tecx\n       shr\teax,5\n       lea\tecx,[ ??back_transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ],ecx\n\n??backward_loop_trans:\n       mov\tecx,eax\n       push\tedi\n       push\tesi\n       jmp\t[ y1_pixel ]\n??backward_trans_line:\n       REPT\t32\n       local\ttransp_pixel\n       \t\tmov\tbl,[ esi ]\n       \t\ttest\tbl,bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ],bl\n    \t    transp_pixel:\n       \t\tdec\tesi\n\t    \tdec\tedi\n\tENDM\n    ??back_transp_reference:\n       dec\tecx\n       jge\t??backward_trans_line\n       pop\tesi\n       pop\tedi\n       sub\tesi,[ source_area ]\n       sub\tedi,[ dest_area ]\n       dec\tedx\n       jge\t??backward_loop_trans\n       cld\n       ret\n\n??real_out:\n       ret\n       ENDP\tLinear_Blit_To_Linear\n\n\n\nEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/BUFFER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library                  *\n *                                                                         *\n *                    File Name : BUFFER.CPP                               *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 18, 1994                             *\n *                                                                         *\n *                  Last Update : June 1, 1994   [PWG]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   BC::BufferClass -- The default (void) constructor for a buffer class  *\n *   BC::~BufferClass -- The destructor for the buffer class               *\n *   BC::BufferClass -- The standard constructor for a buffer class        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BUFFER_H\n#include \"buffer.h\"\n#endif\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * BC::BufferClass -- The standard constructor for a buffer class          *\n *                                                                         *\n * INPUT:\t\tVOID *\tbuffer to which should be included in buffer class *\n *\t\t\t\t\tLONG\t\tsize of the buffer which we included\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     NONE                                                        *\n *                                                                         *\n * WARNINGS:   If the buffer passed to this function is equal to NULL,     *\n *\t\t\t\t\tthe buffer will be allocated using new.\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\nBufferClass::BufferClass(VOID *buffer, LONG size)\n{\n\tSize\t\t\t= size;\t\t\t\t\t\t\t\t// find size of physical buffer\n\n\tif (buffer) {\t\t\t\t\t\t\t\t\t\t// if buffer is specified\n\t\tBuffer\t\t\t= (BYTE *)buffer;\t\t\t//\t\tpoint to it and mark\n\t\tAllocated\t\t= FALSE;\t\t\t\t\t\t//\t\tit as user allocated\n\t} else {\n\t\tBuffer\t\t\t= new BYTE[Size];\t\t\t// otherwise allocate it and\n\t\tAllocated\t\t= TRUE;\t\t\t\t\t\t//\t\tmark it system alloced\n\t}\n}\n\n/***************************************************************************\n * BC::BufferClass -- constructor for BufferClass with size only    \t\t\t*\n *                                                                         *\n * INPUT:\t\tLONG the size of the buffer that needs to be allocated\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\nBufferClass::BufferClass(LONG size)\n{\n\tSize\t\t\t\t= size;\n\tBuffer\t\t\t= new BYTE[Size];\t\t\t// otherwise allocate it and\n\tAllocated\t\t= TRUE;\t\t\t\t\t\t//\t\tmark it system alloced\n}\n\n/***************************************************************************\n * BC::BufferClass -- The default (void) constructor for a buffer class    *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * NOTES:   \tThe primary function of this class is to be called by a     *\n *\t\t\t\t\tderived class which will fill in the values after the\t\t\t*\n *\t\t\t\t\tfact.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\nBufferClass::BufferClass(VOID)\n{\n\tBuffer\t\t= NULL;\n\tSize\t\t\t= 0;\n\tAllocated\t= FALSE;\n}\n\n/***************************************************************************\n * BC::~BUFFERCLASS -- The destructor for the buffer class                 *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\nBufferClass::~BufferClass(VOID)\n{\n\tif (Allocated) {\n\t\tdelete[] Buffer;\n\t}\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/BUFFGLBL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : BUFFGLBL.CPP                             *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : January 10, 1995                         *\n *                                                                         *\n *                  Last Update : January 10, 1995   [PWG]                 *\n *                                                                         *\n * This module holds the global fixup tables for the MCGA buffer class.    *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include \"gbuffer.h\"\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/*=========================================================================*/\n/* Globals required by GraphicBufferClass for function pointers.  These\t\t*/\n/*   pointers will be set to the proper function when set mode is called.\t*/\n/*=========================================================================*/\nBOOL (*GVPC_Blit_to_VVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nBOOL (*GVPC_Scale_To_VVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\n\n#ifdef not_any_more_it_doesnt\n/*=========================================================================*/\n/* Globals required by VideoBufferClass for function pointers.  These\t\t*/\n/*   pointers will be set to the proper function when set mode is called.\t*/\n/*=========================================================================*/\nvoid (*VVPC_Clear_Func)(void *, unsigned char);\nlong (*VVPC_To_Buffer_Func)(void *,int x, int y, int w, int h, void *buff, long size);\nvoid (*VVPC_Put_Pixel_Func)(void *,int x, int y, unsigned char color);\nint  (*VVPC_Get_Pixel_Func)(void *, int x, int y);\nlong (*VVPC_Buffer_To_Page)(int x, int y, int w, int h, void *Buffer, void *view);\nBOOL (*VVPC_Blit_to_GVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nBOOL (*VVPC_Blit_to_VVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nBOOL (*VVPC_Scale_To_GVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\nBOOL (*VVPC_Scale_To_VVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\nLONG (*VVPC_Print_Func)(\t\tvoid *, const char *, int, int, int, int);\nvoid (*VVPC_Draw_Stamp)(void *, void *, int, int, int, void *);\nlong (*VVPC_Size_Of_Region)(void *, int, int);\n\n#endif\t//not_any_more_it_doesnt\n\n/*=========================================================================*/\n/* We need to keep a pointer to the logic page hanging around somewhere\t\t*/\n/*=========================================================================*/\nGraphicViewPortClass\t*LogicPage;\n\nBOOL IconCacheAllowed = TRUE;\n\n/*\n** Pointer to a function we will call if we detect loss of focus\n*/\nvoid (*Gbuffer_Focus_Loss_Function)(void) = NULL;\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/CCFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\ccfile.cpv   2.20   27 Sep 1995 12:45:16   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***             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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CCFILE.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : March 20, 1995 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CCFileClass::CCFileClass -- Default constructor for file object.                          *\n *   CCFileClass::CCFileClass -- Filename based constructor for C&C file.                      *\n *   CCFileClass::Close -- Closes the file.                                                    *\n *   CCFileClass::Is_Available -- Checks for existence of file on disk or in mixfile.          *\n *   CCFileClass::Is_Open -- Determines if the file is open.                                   *\n *   CCFileClass::Open -- Opens a file from either the mixfile system or the rawfile system.   *\n *   CCFileClass::Read -- Reads data from the file.                                            *\n *   CCFileClass::Seek -- Moves the current file pointer in the file.                          *\n *   CCFileClass::Size -- Determines the size of the file.                                     *\n *   CCFileClass::Write -- Writes data to the file (non mixfile files only).                   *\n *   CCFileClass::Error -- Handles displaying a file error message.                            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n#include\t<direct.h>\n#include\t<fcntl.h>\n#include\t<io.h>\n#include\t<dos.h>\n#include\t<errno.h>\n#include\t<share.h>\n#include\t\"ccfile.h\"\n\n\n/***********************************************************************************************\n * CCFileClass::Error -- Handles displaying a file error message.                              *\n *                                                                                             *\n *    Display an error message as indicated. If it is allowed to retry, then pressing a key    *\n *    will return from this function. Otherwise, it will exit the program with \"exit()\".       *\n *                                                                                             *\n * INPUT:   error    -- The error number (same as the DOSERR.H error numbers).                 *\n *                                                                                             *\n *          canretry -- Can this routine exit normally so that retrying can occur? If this is  *\n *                      false, then the program WILL exit in this routine.                     *\n *                                                                                             *\n *          filename -- Optional filename to report with this error. If no filename is         *\n *                      supplied, then no filename is listed in the error message.             *\n *                                                                                             *\n * OUTPUT:  none, but this routine might not return at all if the \"canretry\" parameter is      *\n *          false or the player pressed ESC.                                                   *\n *                                                                                             *\n * WARNINGS:   This routine may not return at all. It handles being in text mode as well as    *\n *             if in a graphic mode.                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CCFileClass::Error(int , int , char const * )\n{\n\tif (!Force_CD_Available(RequiredCD)) {\n\t\tProg_End();\n\t\texit(EXIT_FAILURE);\n\t}\n}\n\n\n/***********************************************************************************************\n * CCFileClass::CCFileClass -- Filename based constructor for C&C file.                        *\n *                                                                                             *\n *    Use this constructor for a file when the filename is known at construction time.         *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the filename to use for this file object.                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The filename pointer is presumed to be inviolate throughout the duration of     *\n *             the file object. If this is not guaranteed, then use the default constructor    *\n *             and then set the name manually.                                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCCFileClass::CCFileClass(char const *filename)\n{\n\tSet_Name(filename);\n\tFromDisk = false;\n\tPointer = 0;\n\tPosition = 0;\n\tLength = 0;\n\tStart = 0;\n}\n\n\n/***********************************************************************************************\n * CCFileClass::CCFileClass -- Default constructor for file object.                            *\n *                                                                                             *\n *    This is the default constructor for a C&C file object.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCCFileClass::CCFileClass(void) : CDFileClass()\n{\n\tFromDisk = false;\n\tPointer = 0;\n\tPosition = 0;\n\tLength = 0;\n\tStart = 0;\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Write -- Writes data to the file (non mixfile files only).                     *\n *                                                                                             *\n *    This routine will write data to the file, but NOT to a file that is part of a mixfile.   *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that holds the data to be written.               *\n *                                                                                             *\n *          size     -- The number of bytes to write.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually written.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCFileClass::Write(void const *buffer, long size)\n{\n\n\t/*\n\t**\tIf this is part of a mixfile, then writing is not allowed. Error out with a fatal\n\t**\tmessage.\n\t*/\n\tif (Pointer || FromDisk) {\n\t\tError(EACCES, false, File_Name());\n\t}\n\n\treturn(CDFileClass::Write(buffer, size));\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Read -- Reads data from the file.                                              *\n *                                                                                             *\n *    This routine determines if the file is part of the mixfile system. If it is, then        *\n *    the file is copied from RAM if it is located there. Otherwise it is read from disk       *\n *    according to the correct position of the file within the parent mixfile.                 *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer to place the read data.                          *\n *                                                                                             *\n *          size     -- The number of bytes to read.                                           *\n *                                                                                             *\n * OUTPUT:  Returns the actual number of bytes read (this could be less than requested).       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCFileClass::Read(void *buffer, long size)\n{\n\tint opened = false;\n\n\tif (!Is_Open()) {\n\t\tif (Open()) {\n\t\t\topened = true;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the file is part of a loaded mixfile, then a mere copy is\n\t**\tall that is required for the read.\n\t*/\n\tif (Pointer) {\n\t\tlong\tmaximum = Length - Position;\n\n\t\tsize = MIN(maximum, size);\n\t\tif (size) {\n\t\t\tMem_Copy(Add_Long_To_Pointer(Pointer, Position), buffer, size);\n\t\t\tPosition += size;\n\t\t}\n\t\tif (opened) Close();\n\t\treturn(size);\n\t}\n\n\t/*\n\t**\tIf the file is part of a mixfile, but the mixfile is located\n\t**\ton disk, then a special read operation is necessary.\n\t*/\n\tif (FromDisk) {\n\t\tlong\tmaximum = Length - Position;\n\n\t\tsize = MIN(maximum, size);\n\t\tif (size > 0) {\n\t\t\tCDFileClass::Seek(Start + Position, SEEK_SET);\n\t\t\tsize = CDFileClass::Read(buffer, size);\n\t\t\tPosition += size;\n\t\t}\n\t\tif (opened) Close();\n\t\treturn(size);\n\t}\n\n\tlong s = CDFileClass::Read(buffer, size);\n\tif (opened) Close();\n\treturn(s);\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Seek -- Moves the current file pointer in the file.                            *\n *                                                                                             *\n *    This routine will change the current file pointer to the position specified. It follows  *\n *    the same rules the a normal Seek() does, but if the file is part of the mixfile system,  *\n *    then only the position value needs to be updated.                                        *\n *                                                                                             *\n * INPUT:   pos      -- The position to move the file to relative to the position indicated    *\n *                      by the \"dir\" parameter.                                                *\n *                                                                                             *\n *          dir      -- The direction to affect the position change against. This can be       *\n *                      either SEEK_CUR, SEEK_END, or SEEK_SET.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the position of the new location.                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCFileClass::Seek(long pos, int dir)\n{\n\tif (Pointer || FromDisk) {\n\t\tswitch (dir) {\n\t\t\tcase SEEK_END:\n\t\t\t\tPosition = Length;\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_SET:\n\t\t\t\tPosition = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_CUR:\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\tPosition += pos;\n\t\tif (Position < 0) Position = 0;\n\t\tif (Position > Length) Position = Length;\n\t\treturn(Position);\n\t}\n\treturn(CDFileClass::Seek(pos, dir));\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Size -- Determines the size of the file.                                       *\n *                                                                                             *\n *    If the file is part of the mixfile system, then the size of the file is already          *\n *    determined and available. Otherwise, go to the low level system to find the file         *\n *    size.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the size of the file in bytes.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCFileClass::Size(void)\n{\n\tif (Pointer || FromDisk) return(Length);\n\n\treturn(CDFileClass::Size());\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Is_Available -- Checks for existence of file on disk or in mixfile.            *\n *                                                                                             *\n *    This routine will examine the mixfile system looking for the file. If the file could     *\n *    not be found there, then the disk is examined directly.                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file available for opening?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CCFileClass::Is_Available(int )\n{\n\tif (MixFileClass::Offset(File_Name())) {\n\t\treturn(true);\n\t}\n\treturn(CDFileClass::Is_Available());\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Is_Open -- Determines if the file is open.                                     *\n *                                                                                             *\n *    A mixfile is open if there is a pointer to the mixfile data. In absence of this,         *\n *    the the file is open if the file handle is valid.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file open?                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CCFileClass::Is_Open(void) const\n{\n\n\t/*\n\t**\tIf the file is part of a cached file, then return that it is opened. A closed file\n\t**\tdoesn't have a valid pointer.\n\t*/\n\tif (Pointer) return(true);\n\treturn(CDFileClass::Is_Open());\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Close -- Closes the file.                                                      *\n *                                                                                             *\n *    If this is a mixfile file, then only the pointers need to be adjusted.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CCFileClass::Close(void)\n{\n\tFromDisk = false;\n\tPointer = 0;\n\tPosition = 0;\t\t\t\t// Starts at beginning offset.\n\tStart = 0;\n\tLength = 0;\n\tCDFileClass::Close();\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Open -- Opens a file from either the mixfile system or the rawfile system.     *\n *                                                                                             *\n *    This routine will open the specified file. It examines the mixfile system to find a      *\n *    match. If one is found then the file is \"opened\" in a special cached way. Otherwise      *\n *    it is opened as a standard DOS file.                                                     *\n *                                                                                             *\n * INPUT:   rights   -- The access rights desired.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened successfully?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CCFileClass::Open(int rights)\n{\n\t/*\n\t**\tAlways close the file if it was open.\n\t*/\n\tClose();\n\n\t/*\n\t**\tPerform a preliminary check to see if the specified file\n\t**\texists on the disk. If it does, then open this file regardless\n\t**\tof whether it also exists in RAM. This is slower, but allows\n\t**\tupgrade files to work.\n\t*/\n\tif ((rights & WRITE) || CDFileClass::Is_Available()) {\n\t\treturn(CDFileClass::Open(rights));\n\t}\n\n\t/*\n\t**\tCheck to see if file is part of a mixfile and that mixfile is currently loaded\n\t**\tinto RAM.\n\t*/\n\tMixFileClass *mixfile = 0;\n\tif (MixFileClass::Offset(File_Name(), &Pointer, &mixfile, &Start, &Length)) {\n\n\t\t/*\n\t\t**\tIf the mixfile is located on disk, then fake out the file system to read from\n\t\t**\tthe mixfile, but think it is reading from a solitary file.\n\t\t*/\n\t\tif (!Pointer) {\n\t\t\tlong\tstart = Start;\n\t\t\tlong\tlength = Length;\n\n\t\t\t/*\n\t\t\t**\tThis is a legitimate open to the file. All access to the file through this\n\t\t\t**\tfile object will be appropriately adjusted for mixfile support however. Also\n\t\t\t**\tnote that the filename attached to this object is NOT the same as the file\n\t\t\t**\tattached to the file handle.\n\t\t\t*/\n\t\t\tchar const * dupfile = strdup(File_Name());\n\t\t\tOpen(mixfile->Filename, READ);\n\t\t\tSearching(false);\t\t\t\t// Disable multi-drive search.\n\t\t\tSet_Name(dupfile);\n\t\t\tfree((void *)dupfile);\n\t\t\tStart = start;\n\t\t\tLength = length;\n\t\t\tFromDisk = true;\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tThe file cannot be found in any mixfile, so it must reside as\n\t\t** an individual file on the disk. Or else it is just plain missing.\n\t\t*/\n\t\treturn(CDFileClass::Open(rights));\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************\n** Backward compatibility section.\n*/\n//extern \"C\" {\n\nstatic CCFileClass Handles[10];\n\n#ifdef NEVER\nbool __cdecl Set_Search_Drives(BYTE const *)\n{\n\tCCFileClass::Set_Search_Path(path);\n\treturn(true);\n}\n#endif\n\nWORD __cdecl Open_File(BYTE const *file_name, WORD mode)\n{\n\tfor (int index = 0; index < sizeof(Handles)/sizeof(Handles[0]); index++) {\n\t\tif (!Handles[index].Is_Open()) {\n\t\t\tif (Handles[index].Open(file_name, mode)) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn(ERROR);\n}\n\nVOID __cdecl Close_File(WORD handle)\n{\n\tif (handle != ERROR && Handles[handle].Is_Open()) {\n\t\tHandles[handle].Close();\n\t}\n}\n\nLONG __cdecl Read_File(WORD handle, VOID *buf, ULONG bytes)\n{\n\tif (handle != ERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Read(buf, bytes));\n\t}\n\treturn(0);\n}\n\nLONG __cdecl Write_File(WORD handle, VOID const *buf, ULONG bytes)\n{\n\tif (handle != ERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Write(buf, bytes));\n\t}\n\treturn(0);\n}\n\nWORD __cdecl Find_File(BYTE const *file_name)\n{\n\tCCFileClass file(file_name);\n\treturn(file.Is_Available());\n}\n\n#ifdef NEVER\nWORD __cdecl Delete_File(BYTE const *file_name)\n{\n\treturn(CCFileClass(file_name).Delete());\n}\n\nWORD __cdecl Create_File(BYTE const *file_name)\n{\n\treturn(CCFileClass(file_name).Create());\n}\n\nULONG __cdecl Load_Data(BYTE const *name, VOID *ptr, ULONG size)\n{\n\treturn(CCFileClass(name).Read(ptr, size));\n}\n#endif\n\nVOID * __cdecl Load_Alloc_Data(BYTE const *name, WORD )\n{\n\tCCFileClass file(name);\n\n\treturn(Load_Alloc_Data(file));\n}\n\nULONG __cdecl File_Size(WORD handle)\n{\n\tif (handle != ERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Size());\n\t}\n\treturn(0);\n}\n\n#ifdef NEVER\nULONG __cdecl Write_Data(BYTE const *name, VOID const *ptr, ULONG size)\n{\n\treturn(CCFileClass(name).Write(ptr, size));\n}\n#endif\n\nULONG __cdecl Seek_File(WORD handle, LONG offset, WORD starting)\n{\n\tif (handle != ERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Seek(offset, starting));\n\t}\n\treturn(0);\n}\n\n#ifdef NEVER\nbool __cdecl Multi_Drive_Search(bool on)\n{\n//\treturn(CCFileClass::Multi_Drive_Search(on));\n\treturn(on);\n}\n\nVOID __cdecl WWDOS_Init(VOID)\n{\n}\n\nVOID __cdecl WWDOS_Shutdown(VOID)\n{\n}\n\nWORD __cdecl Find_Disk_Number(BYTE const *)\n{\n\treturn(0);\n}\n#endif\n\n//ULONG cdecl Load_Uncompress(BYTE const *file, BuffType uncomp_buff, BuffType dest_buff, VOID *reserved_data)\n//{\n//\treturn(Load_Uncompress(CCFileClass(file), uncomp_buff, dest_buff, reserved_data));\n//\treturn(CCFileClass(file).Load_Uncompress(uncomp_buff, dest_buff, reserved_data));\n//}\nextern \"C\" {\nint MaxDevice;\nint DefaultDrive;\nchar CallingDOSInt;\n\n}\n\n\nvoid Unfragment_File_Cache(void)\n{\n}\n\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/CLEAR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Clear the Full Graphics Buffer\t   *\n;*                                                                         *\n;*                    File Name : CLEAR.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : August 23, 1994   [SKB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   GVPC::Clear -- Clears a virtual viewport instance                     *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nCODESEG\n\n;***************************************************************************\n;* VVPC::CLEAR -- Clears a virtual viewport instance                       *\n;*                                                                         *\n;* INPUT:\tUBYTE the color (optional) to clear the view port to\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* NOTE:\tThis function is optimized to handle viewport with no XAdd *\n;*\t\tvalue.  It also handles DWORD aligning the destination\t   *\n;*\t\twhen speed can be gained by doing it.\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/07/1994 PWG : Created.                                             *\n;*   08/23/1994 SKB : Clear the direction flag to always go forward.       *\n;*=========================================================================*\n\tPROC\tBuffer_Clear C near\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tARG    \tthis_object:DWORD\t\t\t; this is a member function\n\tARG    \tcolor:BYTE\t\t\t\t; what color should we clear to\n\n\tcld \t\t \t\t\t\t; always go forward\n\n\tmov\tebx,[this_object]\t\t\t; get a pointer to viewport\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get the correct offset\n\tmov\tedx,[(GraphicViewPort ebx).GVPHeight]\t; ecx = height of viewport\n\tmov\tesi,[(GraphicViewPort ebx).GVPWidth]\t; edx = width of viewport\n\tpush\t[dword (GraphicViewPort ebx).GVPPitch]\t; extra pitch of direct draw surface\n\tmov\tebx,[(GraphicViewPort ebx).GVPXAdd]\t; esi = add for each line\n\tadd\tebx,[esp]\t\t\t\t; Yes, I know its nasty but\n\tadd\tesp,4\t\t\t\t\t;      it works!\n\n\t;*===================================================================\n\t; Convert the color byte to a DWORD for fast storing\n\t;*===================================================================\n\tmov\tal,[color]\t\t\t\t; get color to clear to\n\tmov\tah,al\t\t\t\t\t; extend across WORD\n\tmov\tecx,eax\t\t\t\t\t; extend across DWORD in\n\tshl\teax,16\t\t\t\t\t;   several steps\n\tmov\tax,cx\n\n\t;*===================================================================\n\t; Find out if we should bother to align the row.\n\t;*===================================================================\n\n\tcmp\tesi , OPTIMAL_BYTE_COPY\t\t\t; is it worth aligning them?\n\tjl\t??byte_by_byte\t\t\t\t;   if not then skip\n\n\t;*===================================================================\n\t; Figure out the alignment offset if there is any\n\t;*===================================================================\n\tpush\tebx\n??dword_aligned_loop:\n       mov\tecx , edi\n       mov\tebx , esi\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tstosb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tstosd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tstosb\n       add\tedi , [ esp ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??dword_aligned_loop\t\t\t\t; if more to do than do it\n       pop\teax\n       ret\n\n\t;*===================================================================\n\t; If not enough bytes to bother aligning copy each line across a byte\n\t;    at a time.\n\t;*===================================================================\n??byte_by_byte:\n\tmov\tecx,esi\t\t\t\t\t; get total width in bytes\n\trep\tstosb\t\t\t\t\t; store the width\n\tadd\tedi,ebx\t\t\t\t\t; handle the xadd\n\tdec\tedx\t\t\t\t\t; decrement the height\n\tjnz\t??byte_by_byte\t\t\t\t; if any left then next line\n??exit:\n\tret\n\tENDP\tBuffer_Clear\nEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/CLIPRECT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Support Library                          *\n;*                                                                         *\n;*                    File Name : cliprect.asm                             *\n;*                                                                         *\n;*                   Programmer : Julio R Jerez                            *\n;*                                                                         *\n;*                   Start Date : Mar, 2 1995                              *\n;*                                                                         *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* int Clip_Rect ( int * x , int * y , int * dw , int * dh , \t\t   *\n;*\t       \t   int width , int height ) ;          \t\t\t   *\n;* int Confine_Rect ( int * x , int * y , int * dw , int * dh , \t   *\n;*\t       \t      int width , int height ) ;          \t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\t C Clip_Rect\t:NEAR\nGLOBAL\t C Confine_Rect\t:NEAR\n\nCODESEG\n\n;***************************************************************************\n;* Clip_Rect -- clip a given rectangle against a given window\t\t   *\n;*                                                                         *\n;* INPUT:   &x , &y , &w , &h  -> Pointer to rectangle being clipped       *\n;*          width , height     -> dimension of clipping window             *\n;*                                                                         *\n;* OUTPUT: a) Zero if the rectangle is totally contained by the \t   *\n;*\t      clipping window.\t\t\t\t\t\t   *\n;*\t   b) A negative value if the rectangle is totally outside the     *\n;*            the clipping window\t\t\t\t\t   *\n;*\t   c) A positive value if the rectangle\twas clipped against the\t   *\n;*\t      clipping window, also the values pointed by x, y, w, h will  *\n;*\t      be modified to new clipped values\t \t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*   05/03/1995 JRJ : added comment                                        *\n;*=========================================================================*\n; int Clip_Rect (int* x, int* y, int* dw, int* dh, int width, int height);          \t\t\t   *\n\n\tPROC\tClip_Rect C near\n\tuses\tebx,ecx,edx,esi,edi\n\targ\tx:dword\n\targ\ty:dword\n\targ\tw:dword\n\targ\th:dword\n\targ\twidth:dword\n\targ\theight:dword\n\n;This Clipping algorithm is a derivation of the very well known\n;Cohen-Sutherland Line-Clipping test. Due to its simplicity and efficiency\n;it is probably the most commontly implemented algorithm both in software\n;and hardware for clipping lines, rectangles, and convex polygons against\n;a rectagular clipping window. For reference see\n;\"COMPUTER GRAPHICS principles and practice by Foley, Vandam, Feiner, Hughes\n; pages 113 to 177\".\n; Briefly consist in computing the Sutherland code for both end point of\n; the rectangle to find out if the rectangle is:\n; - trivially accepted (no further clipping test, return the oroginal data)\n; - trivially rejected (return with no action, return error code)\n; - retangle must be iteratively clipped again edges of the clipping window\n;   and return the clipped rectangle\n\n\t; get all four pointer into regisnters\n\tmov\tesi,[x]\t\t; esi = pointer to x\n\tmov\tedi,[y]\t\t; edi = pointer to x\n\tmov\teax,[w]\t\t; eax = pointer to dw\n\tmov\tebx,[h]\t\t; ebx = pointer to dh\n\n\t; load the actual data into reg\n\tmov\tesi,[esi]\t; esi = x0\n\tmov\tedi,[edi]\t; edi = y0\n\tmov\teax,[eax]\t; eax = dw\n\tmov\tebx,[ebx]\t; ebx = dh\n\n\t; create a wire frame of the type [x0,y0] , [x1,y1]\n\tadd\teax,esi\t\t; eax = x1 = x0 + dw\n\tadd\tebx,edi\t\t; ebx = y1 = y0 + dh\n\n\t; we start we suthenland code0 and code1 set to zero\n\txor \tecx,ecx\t\t; cl = sutherland boolean code0\n\txor \tedx,edx\t\t; dl = sutherland boolean code0\n\n\t; now we start computing the to suthenland boolean code for x0 , x1\n\tshld\tecx,esi,1\t; bit3 of code0 = sign bit of (x0 - 0)\n\tshld\tedx,eax,1 \t; bit3 of code1 = sign bit of (x1 - 0)\n\tsub\tesi,[width]\t; get the difference (x0 - (width + 1))\n\tsub\teax,[width]\t; get the difference (x1 - (width + 1))\n\tdec\tesi\n\tdec\teax\n\tshld\tecx,esi,1\t; bit2 of code0 = sign bit of (x0 - (width + 1))\n\tshld\tedx,eax,1\t; bit2 of code1 = sign bit of (x0 - (width + 1))\n\n\t; now we start computing the to suthenland boolean code for y0 , y1\n\tshld\tecx,edi,1   \t; bit1 of code0 = sign bit of (y0 - 0)\n\tshld\tedx,ebx,1\t; bit1 of code1 = sign bit of (y0 - 0)\n\tsub\tedi,[height]\t; get the difference (y0 - (height + 1))\n\tsub\tebx,[height]\t; get the difference (y1 - (height + 1))\n\tdec\tedi\n\tdec\tebx\n\tshld\tecx,edi,1\t; bit0 of code0 = sign bit of (y0 - (height + 1))\n\tshld\tedx,ebx,1\t; bit0 of code1 = sign bit of (y1 - (height + 1))\n\n\t; Bit 2 and 0 of cl and bl are complemented\n\txor\tcl,5\t\t; reverse bit2 and bit0 in code0\n\txor\tdl,5 \t\t; reverse bit2 and bit0 in code1\n\n\t; now perform the rejection test\n\tmov\teax,-1\t\t; set return code to false\n\tmov\tbl,cl \t\t; save code0 for future use\n\ttest\tdl,cl  \t\t; if any two pair of bit in code0 and code1 is set\n\tjnz\t??clip_out\t; then rectangle is outside the window\n\n\t; now perform the aceptance test\n\txor\teax,eax\t\t; set return code to true\n\tor\tbl,dl\t\t; if all pair of bits in code0 and code1 are reset\n\tjz\t??clip_out\t; then rectangle is insize the window.\t\t\t\t\t\t\t\t      '\n\n\t; we need to clip the rectangle iteratively\n\tmov\teax,-1\t\t; set return code to false\n\ttest\tcl,1000b\t; if bit3 of code0 is set then the rectangle\n\tjz\t??left_ok\t; spill out the left edge of the window\n\tmov\tedi,[x]\t\t; edi = a pointer to x0\n\tmov\tebx,[w]\t\t; ebx = a pointer to dw\n\tmov\tesi,[edi]\t; esi = x0\n\tmov\t[dword ptr edi],0 ; set x0 to 0 \"this the left edge value\"\n\tadd\t[ebx],esi\t; adjust dw by x0, since x0 must be negative\n\n??left_ok:\n\ttest\tcl,0010b\t; if bit1 of code0 is set then the rectangle\n\tjz\t??bottom_ok\t; spill out the bottom edge of the window\n\tmov\tedi,[y]\t\t; edi = a pointer to y0\n\tmov\tebx,[h]\t\t; ebx = a pointer to dh\n\tmov\tesi,[edi]\t; esi = y0\n\tmov\t[dword ptr edi],0 ; set y0 to 0 \"this the bottom edge value\"\n\tadd\t[ebx],esi\t; adjust dh by y0, since y0 must be negative\n\n??bottom_ok:\n\ttest\tdl,0100b\t; if bit2 of code1 is set then the rectangle\n\tjz\t??right_ok\t; spill out the right edge of the window\n\tmov\tedi,[w] \t; edi = a pointer to dw\n\tmov\tesi,[x]\t\t; esi = a pointer to x\n\tmov\tebx,[width]\t; ebx = the width of the window\n\tsub\tebx,[esi] \t; the new dw is the difference (width-x0)\n\tmov\t[edi],ebx\t; adjust dw to (width - x0)\n\tjle\t??clip_out\t; if (width-x0) = 0 then the clipped retangle\n\t\t\t\t; has no width we are done\n??right_ok:\n\ttest\tdl,0001b\t; if bit0 of code1 is set then the rectangle\n\tjz\t??clip_ok\t; spill out the top edge of the window\n\tmov\tedi,[h] \t; edi = a pointer to dh\n\tmov\tesi,[y]\t\t; esi = a pointer to y0\n\tmov\tebx,[height]\t; ebx = the height of the window\n\tsub\tebx,[esi] \t; the new dh is the difference (height-y0)\n\tmov\t[edi],ebx\t; adjust dh to (height-y0)\n\tjle\t??clip_out\t; if (width-x0) = 0 then the clipped retangle\n\t\t\t\t; has no width we are done\n??clip_ok:\n\tmov\teax,1  \t; signal the calling program that the rectangle was modify\n??clip_out:\n\tret\n\tENDP\tClip_Rect\n\n\n;***************************************************************************\n;* Confine_Rect -- clip a given rectangle against a given window\t   *\n;*                                                                         *\n;* INPUT:   &x,&y,w,h    -> Pointer to rectangle being clipped       *\n;*          width,height     -> dimension of clipping window             *\n;*                                                                         *\n;* OUTPUT: a) Zero if the rectangle is totally contained by the \t   *\n;*\t      clipping window.\t\t\t\t\t\t   *\n;*\t   c) A positive value if the rectangle\twas shifted in position    *\n;*\t      to fix inside the clipping window, also the values pointed   *\n;*\t      by x, y, will adjusted to a new values\t \t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*  NOTE:  this function make not attempt to verify if the rectangle is\t   *\n;*\t   bigger than the clipping window and at the same time wrap around*\n;*\t   it. If that is the case the result is meaningless\t\t   *\n;*=========================================================================*\n; int Confine_Rect (int* x, int* y, int dw, int dh, int width, int height);          \t\t\t   *\n\n\tPROC\tConfine_Rect C near\n\tuses\tebx, esi,edi\n\targ\tx:dword\n\targ\ty:dword\n\targ\tw:dword\n\targ\th:dword\n\targ\twidth :dword\n\targ\theight:dword\n\n\txor\teax,eax\n\tmov\tebx,[x]\n\tmov\tedi,[w]\n\n\tmov\tesi,[ebx]\n\tadd\tedi,[ebx]\n\n\tsub\tedi,[width]\n\tneg\tesi\n\tdec\tedi\n\n\ttest\tesi,edi\n\tjl\t??x_axix_ok\n\tmov\teax,1\n\n\ttest\tesi,esi\n\tjl\t??shift_right\n\tmov\t[dword ptr ebx],0\n\tjmp\t??x_axix_ok\n??shift_right:\n\tinc\tedi\n\tsub\t[ebx],edi\n??x_axix_ok:\n\tmov\tebx,[y]\n\tmov\tedi,[h]\n\n\tmov\tesi,[ebx]\n\tadd\tedi,[ebx]\n\n\tsub\tedi,[height]\n\tneg\tesi\n\tdec\tedi\n\n\ttest\tesi,edi\n\tjl\t??confi_out\n\tmov\teax,1\n\n\ttest\tesi,esi\n\tjl\t??shift_top\n\tmov\t[dword ptr ebx],0\n\tret\n??shift_top:\n\tinc\tedi\n\tsub\t[ebx],edi\n??confi_out:\n\tret\n\n\tENDP\tConfine_Rect\n\n \tEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/CRC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : CRC.ASM                                  *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : June 12, 1992                            *\n;*                                                                         *\n;*                  Last Update : February 10, 1995 [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\tC Calculate_CRC\t:NEAR\n\n\tCODESEG\n\n; LONG Calculate_CRC(VOID *buffer, LONG length);\n\tPROC\tCalculate_CRC C near\n\tUSES \tesi\n\n\tARG\tbuffer:DWORD\n\tARG\tlength:DWORD\n\n\tLOCAL\tcrc:DWORD\n\n\t; Load pointer to data block.\n\tmov\t[crc],0\n\tpushad\n\tmov\tesi,[buffer]\n\tcld\n\n\t; Clear CRC to default (NULL) value.\n\txor\tebx,ebx\n\n\t; Fetch the length of the data block to CRC.\n\tmov\tecx,[length]\n\tjecxz\tshort ??fini\n\n\t; Prepare the length counters.\n\tmov\tedx,ecx\n\tand\tdl,011b\n\tshr\tecx,2\n\n\t; Perform the bulk of the CRC scanning.\n\tjecxz\tshort ??remainder\n??accumloop:\n\tlodsd\n\trol\tebx,1\n\tadd\tebx,eax\n\tloop\t??accumloop\n\n\t; Handle the remainder bytes.\n??remainder:\n\tor\tdl,dl\n\tjz\tshort ??fini\n\tmov\tecx,edx\n\txor\teax,eax\n\n\tand \tecx,0FFFFh\n\tpush\tecx\n??nextbyte:\n\tlodsb\n\tror\teax,8\n\tloop\t??nextbyte\n\tpop\tecx\n\tneg\tecx\n\tadd\tecx,4\n\tshl\tecx,3\n\tror\teax,cl\n\n;??nextbyte:\n;\tshl\teax,8\n;\tlodsb\n;\tloop\t??nextbyte\n\trol\tebx,1\n\tadd\tebx,eax\n\n??fini:\n\tmov\t[crc],ebx\n\tpopad\n\tmov\teax,[crc]\n\tret\n\n\tENDP\tCalculate_CRC\n\n\tEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DDRAW.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Win32 Library                   *\n *                                                                         *\n *                    File Name : DDRAW.CPP                                *\n *                                                                         *\n *                   Programmer : Philip W. Gorrow                         *\n *                                                                         *\n *                   Start Date : October 10, 1995                         *\n *                                                                         *\n *                  Last Update : October 10, 1995   []                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n#include \"misc.h\"\n#include <gbuffer.h>\n#include <palette.h>\n\n\nLPDIRECTDRAW\t\tDirectDrawObject=NULL;\t// Pointer to the direct draw object\nLPDIRECTDRAW2\tDirectDraw2Interface = NULL;  \t// Pointer to direct draw 2 interface\n\nHWND\t\t\tMainWindow;\t\t\t\t\t// Handle to programs main window\n\t\t\t\t\t\t\t\t\t\t\t\t// this is passed to SetCooperativeLevel\n\t\t\t\t\t\t\t\t\t\t\t\t// so DirectDraw knows which window is ours\n\n\nPALETTEENTRY\t\t\t\tPaletteEntries[256];\t\t// 256 windows palette entries\nLPDIRECTDRAWPALETTE\tPalettePtr;\t\t\t\t\t// Pointer to direct draw palette object\nBOOL\t\t\t\t\t\tFirstPaletteSet=FALSE;\t// Is this the first time 'Set_Palette' has been called?\nLPDIRECTDRAWSURFACE\tPaletteSurface=NULL;\nSurfaceMonitorClass\tAllSurfaces;\t\t\t\t//List of all direct draw surfaces\nBOOL\t\t\t\t\t\tCanVblankSync = TRUE;\n\nBOOL\t\t\t\t\t\tSystemToVideoBlits =FALSE;\t// Does hardware support system mem to video mem blits?\nBOOL\t\t\t\t\t\tVideoToSystemBlits =FALSE;\t// Does hardware support video mem to system mem blits?\nBOOL\t\t\t\t\t\tSystemToSystemBlits = FALSE; \t// Does hardware support system mem to system mem blits?\nBOOL\t\t\t\t\t\tOverlappedVideoBlits = TRUE;\t// Can video driver blit overlapped regions?\n\n/*\n** Function to call if we detect focus loss\n*/\nextern\tvoid (*Misc_Focus_Loss_Function)(void) = NULL;\nextern\tvoid (*Misc_Focus_Restore_Function)(void) = NULL;\n\n\n/***********************************************************************************************\n * Process_DD_Result -- Does a message box based on the result of a DD command                 *\n *                                                                                             *\n * INPUT:\t\tHRESULT result\t\t\t\t- the result returned from the direct draw command\t\t  *\n *             int     display_ok_msg\t- should a message be displayed if command ok\t\t\t  *                                                                                      *\n *                                                                                             *\n * OUTPUT:\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/27/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid Process_DD_Result(HRESULT result, int display_ok_msg)\n{\n\tswitch (result) {\n\t\tcase DD_OK:\n\t\t\tif (display_ok_msg) {\n\t\t\t\tMessageBox(MainWindow, \"Direct Draw request went ok.\", \"Note\", MB_ICONEXCLAMATION|MB_OK);\n         }\n\t\t\tbreak;\n\t\tcase DDERR_ALREADYINITIALIZED:\n\t\t\tMessageBox(MainWindow, \"This object is already initialized \",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_BLTFASTCANTCLIP:\n\t\t\tMessageBox(MainWindow, \"Return if a clipper object is attached to the source surface passed into a BltFast call.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_CANNOTATTACHSURFACE:\n\t\t\tMessageBox(MainWindow, \"This surface can not be attached to the requested surface.\t\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_CANNOTDETACHSURFACE:\n\t\t\tMessageBox(MainWindow, \"This surface can not be detached from the requested surface.\t\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_CANTCREATEDC:\n\t\t\tMessageBox(MainWindow, \"Windows can not create any more DCs\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_CANTDUPLICATE:\n\t\t\tMessageBox(MainWindow, \"Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_CANTLOCKSURFACE:\n\t\t\tMessageBox(MainWindow, \"Unable to lock surface because no driver exists which can supply a pointer to the surface.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_CLIPPERISUSINGHWND:\n\t\t\tMessageBox(MainWindow, \"An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_COLORKEYNOTSET:\n\t\t\tMessageBox(MainWindow, \"No src color key specified for this operation.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_CURRENTLYNOTAVAIL:\n\t\t\tMessageBox(MainWindow, \"Support is currently not available.\t\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_DIRECTDRAWALREADYCREATED:\n\t\t\tMessageBox(MainWindow, \"A DirectDraw object representing this driver has already been created for this process.\t\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_EXCEPTION:\n\t\t\tMessageBox(MainWindow, \"An exception was encountered while performing the requested operation.\t\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_EXCLUSIVEMODEALREADYSET:\n\t\t\tMessageBox(MainWindow, \"An attempt was made to set the cooperative level when it was already set to exclusive.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_GENERIC:\n\t\t\tMessageBox(MainWindow, \"Generic failure.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_HEIGHTALIGN:\n\t\t\tMessageBox(MainWindow, \"Height of rectangle provided is not a multiple of reqd alignment.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_HWNDALREADYSET:\n\t\t\tMessageBox(MainWindow, \"The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or palettes created.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_HWNDSUBCLASSED:\n\t\t\tMessageBox(MainWindow, \"HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring state.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_IMPLICITLYCREATED:\n\t\t\tMessageBox(MainWindow, \"This surface can not be restored because it is an implicitly created surface.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INCOMPATIBLEPRIMARY:\n\t\t\tMessageBox(MainWindow, \"Unable to match primary surface creation request with existing primary surface.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDCAPS:\n\t\t\tMessageBox(MainWindow, \"One or more of the caps bits passed to the callback are incorrect.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDCLIPLIST:\n\t\t\tMessageBox(MainWindow, \"DirectDraw does not support the provided cliplist.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDDIRECTDRAWGUID:\n\t\t\tMessageBox(MainWindow, \"The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDMODE:\n\t\t\tMessageBox(MainWindow, \"DirectDraw does not support the requested mode.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDOBJECT:\n\t\t\tMessageBox(MainWindow, \"DirectDraw received a pointer that was an invalid DIRECTDRAW object.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDPARAMS:\n\t\t\tMessageBox(MainWindow, \"One or more of the parameters passed to the function are incorrect.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDPIXELFORMAT:\n\t\t\tMessageBox(MainWindow, \"The pixel format was invalid as specified.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDPOSITION:\n\t\t\tMessageBox(MainWindow, \"Returned when the position of the overlay on the destination is no longer legal for that destination.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_INVALIDRECT:\n\t\t\tMessageBox(MainWindow, \"Rectangle provided was invalid.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\n\t\tcase DDERR_INVALIDSURFACETYPE:\n\t\t\tMessageBox(MainWindow, \"The requested action could not be performed because the surface was of the wrong type.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_LOCKEDSURFACES:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because one or more surfaces are locked.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NO3D:\n\t\t\tMessageBox(MainWindow, \"There is no 3D present.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOALPHAHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no alpha accleration hardware present or available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n#if(0)\n\t\tcase DDERR_NOANTITEARHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no hardware support for synchronizing blts to avoid tearing.\t\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n#endif\n\t\tcase DDERR_NOBLTHW:\n\t\t\tMessageBox(MainWindow, \"No blter hardware present.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n#if(0)\n\t\tcase DDERR_NOBLTQUEUEHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no hardware support for asynchronous blting.\t\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n#endif\n\t\tcase DDERR_NOCLIPLIST:\n\t\t\tMessageBox(MainWindow, \"No cliplist available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOCLIPPERATTACHED:\n\t\t\tMessageBox(MainWindow, \"No clipper object attached to surface object.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOCOLORCONVHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no color conversion hardware present or available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOCOLORKEY:\n\t\t\tMessageBox(MainWindow, \"Surface doesn't currently have a color key\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOCOLORKEYHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no hardware support of the destination color key.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOCOOPERATIVELEVELSET:\n\t\t\tMessageBox(MainWindow, \"Create function called without DirectDraw object method SetCooperativeLevel being called.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NODC:\n\t\t\tMessageBox(MainWindow, \"No DC was ever created for this surface.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NODDROPSHW:\n\t\t\tMessageBox(MainWindow, \"No DirectDraw ROP hardware.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NODIRECTDRAWHW:\n\t\t\tMessageBox(MainWindow, \"A hardware-only DirectDraw object creation was attempted but the driver did not support any hardware.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NODIRECTDRAWSUPPORT:\n\t\t\tMessageBox(MainWindow, \"No DirectDraw support possible with current display driver.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOEMULATION:\n\t\t\tMessageBox(MainWindow, \"Software emulation not available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOEXCLUSIVEMODE:\n\t\t\tMessageBox(MainWindow, \"Operation requires the application to have exclusive mode but the application does not have exclusive mode.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOFLIPHW:\n\t\t\tMessageBox(MainWindow, \"Flipping visible surfaces is not supported.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOGDI:\n\t\t\tMessageBox(MainWindow, \"There is no GDI present.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOHWND:\n\t\t\tMessageBox(MainWindow, \"Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOMIRRORHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no hardware present or available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOOVERLAYDEST:\n\t\t\tMessageBox(MainWindow, \"Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on to establish a destination.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOOVERLAYHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no overlay hardware present or available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOPALETTEATTACHED:\n\t\t\tMessageBox(MainWindow, \"No palette object attached to this surface.\t\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOPALETTEHW:\n\t\t\tMessageBox(MainWindow, \"No hardware support for 16 or 256 color palettes.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NORASTEROPHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no appropriate raster op hardware present or available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOROTATIONHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no rotation hardware present or available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOSTRETCHHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no hardware support for stretching.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOT4BITCOLOR:\n\t\t\tMessageBox(MainWindow, \"DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOT4BITCOLORINDEX:\n\t\t\tMessageBox(MainWindow, \"DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOT8BITCOLOR:\n\t\t\tMessageBox(MainWindow, \"DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOTAOVERLAYSURFACE:\n\t\t\tMessageBox(MainWindow, \"Returned when an overlay member is called for a non-overlay surface.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOTEXTUREHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no texture mapping hardware present or available.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOTFLIPPABLE:\n\t\t\tMessageBox(MainWindow, \"An attempt has been made to flip a surface that is not flippable.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOTFOUND:\n\t\t\tMessageBox(MainWindow, \"Requested item was not found.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOTLOCKED:\n\t\t\tMessageBox(MainWindow, \"Surface was not locked.  An attempt to unlock a surface that was not locked at all, or by this process, has been attempted.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOTPALETTIZED:\n\t\t\tMessageBox(MainWindow, \"The surface being used is not a palette-based surface.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOVSYNCHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no hardware support for vertical blank synchronized operations.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOZBUFFERHW:\n\t\t\tMessageBox(MainWindow, \"Operation could not be carried out because there is no hardware support for zbuffer blting.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_NOZOVERLAYHW:\n\t\t\tMessageBox(MainWindow, \"Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_OUTOFCAPS:\n\t\t\tMessageBox(MainWindow, \"The hardware needed for the requested operation has already been allocated.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_OUTOFMEMORY:\n\t\t\tMessageBox(MainWindow, \"DirectDraw does not have enough memory to perform the operation.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_OUTOFVIDEOMEMORY:\n\t\t\tMessageBox(MainWindow, \"DirectDraw does not have enough memory to perform the operation.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_OVERLAYCANTCLIP:\n\t\t\tMessageBox(MainWindow, \"The hardware does not support clipped overlays.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_OVERLAYCOLORKEYONLYONEACTIVE:\n\t\t\tMessageBox(MainWindow, \"Can only have ony color key active at one time for overlays.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_OVERLAYNOTVISIBLE:\n\t\t\tMessageBox(MainWindow, \"Returned when GetOverlayPosition is called on a hidden overlay.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_PALETTEBUSY:\n\t\t\tMessageBox(MainWindow, \"Access to this palette is being refused because the palette is already locked by another thread.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_PRIMARYSURFACEALREADYEXISTS:\n\t\t\tMessageBox(MainWindow, \"This process already has created a primary surface.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_REGIONTOOSMALL:\n\t\t\tMessageBox(MainWindow, \"Region passed to Clipper::GetClipList is too small.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_SURFACEALREADYATTACHED:\n\t\t\tMessageBox(MainWindow, \"This surface is already attached to the surface it is being attached to.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_SURFACEALREADYDEPENDENT:\n\t\t\tMessageBox(MainWindow, \"This surface is already a dependency of the surface it is being made a dependency of.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_SURFACEBUSY:\n\t\t\tMessageBox(MainWindow, \"Access to this surface is being refused because the surface is already locked by another thread.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_SURFACEISOBSCURED:\n\t\t\tMessageBox(MainWindow, \"Access to surface refused because the surface is obscured.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_SURFACELOST:\n\t\t\tMessageBox(MainWindow, \"Access to this surface is being refused because the surface memory is gone. The DirectDrawSurface object representing this surface should have Restore called on it.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_SURFACENOTATTACHED:\n\t\t\tMessageBox(MainWindow, \"The requested surface is not attached.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_TOOBIGHEIGHT:\n\t\t\tMessageBox(MainWindow, \"Height requested by DirectDraw is too large.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_TOOBIGSIZE:\n\t\t\tMessageBox(MainWindow, \"Size requested by DirectDraw is too large --\tthe individual height and width are OK.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_TOOBIGWIDTH:\n\t\t\tMessageBox(MainWindow, \"Width requested by DirectDraw is too large.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_UNSUPPORTED:\n\t\t\tMessageBox(MainWindow, \"Action not supported.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_UNSUPPORTEDFORMAT:\n\t\t\tMessageBox(MainWindow, \"FOURCC format requested is unsupported by DirectDraw.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_UNSUPPORTEDMASK:\n\t\t\tMessageBox(MainWindow, \"Bitmask in the pixel format requested is unsupported by DirectDraw.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_VERTICALBLANKINPROGRESS:\n\t\t\tMessageBox(MainWindow, \"Vertical blank is in progress.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_WASSTILLDRAWING:\n\t\t\tMessageBox(MainWindow, \"Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is incomplete.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_WRONGMODE:\n\t\t\tMessageBox(MainWindow, \"This surface can not be restored because it was created in a different mode.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tcase DDERR_XALIGN:\n\t\t\tMessageBox(MainWindow, \"Rectangle provided was not horizontally aligned on required boundary.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tchar string[256];\n\t\t\tsprintf (string, \"Unrecognised Direct Draw result code: %d\", result & 0xffff);\n\t\t\tMessageBox(MainWindow, string,\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tbreak;\n\t}\n}\n\n\n\n/***********************************************************************************************\n * Check_Overlapped_Blit_Capability -- See if video driver supports blitting overlapped regions*\n *                                                                                             *\n *  We will check for this by drawing something to a video page and blitting it over itself.   *\n * If we end up with the top line repeating then overlapped region blits dont work.            *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/7/96 5:06PM ST : Created                                                               *\n *=============================================================================================*/\nvoid Check_Overlapped_Blit_Capability(void)\n{\n\n\t/*\n\t** Assume we can until we find out otherwise\n\t*/\n\tOverlappedVideoBlits = TRUE;\n\n\tGraphicBufferClass test_buffer;\n\n\ttest_buffer.Init (64, 64, NULL, 0, (GBC_Enum)GBC_VIDEOMEM);\n\n\ttest_buffer.Clear();\n\n\t/*\n\t** Plot a pixel in the top left corner of the buffer.\n\t*/\n\ttest_buffer.Put_Pixel(0, 0, 255);\n\n\t/*\n\t** Blit the buffer down by one line. If we end up with a vertical strip of pixel 255's then\n\t** overlapped blits dont work\n\t*/\n\n\ttest_buffer.Blit(test_buffer, 0, 0, 0, 1, test_buffer.Get_Width(), test_buffer.Get_Height()-1);\n\n\tif (test_buffer.Get_Pixel (0 ,5) == 255) OverlappedVideoBlits = FALSE;\n}\n\n\n\n/***********************************************************************************************\n * Set_Video_Mode -- Initializes Direct Draw and sets the required Video Mode                  *\n *                                                                                             *\n * INPUT:  \t\tint width   \t\t\t- the width of the video mode in pixels\t\t\t\t\t\t  *\n *\t\t\t\t\tint height           - the height of the video mode in pixels                   *\n *\t\t\t\t\tint bits_per_pixel\t- the number of bits per pixel the video mode supports     *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/26/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nBOOL Set_Video_Mode(HWND hwnd, int w, int h, int bits_per_pixel)\n{\n\tHRESULT result;\n\t//\n\t// If there is not currently a direct draw object then we need to define one.\n\t//\n\tif ( DirectDrawObject == NULL ){\n\t\t//MessageBox(MainWindow, \"In Set_Video_Mode. About to call DirectDrawCreate.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\tresult = DirectDrawCreate(NULL, &DirectDrawObject, NULL);\n\t\tProcess_DD_Result(result, FALSE);\n\t\tif (result == DD_OK){\n\t\t\tif (w==320){\n\t\t\t\tresult = DirectDrawObject->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX);\n\t\t\t} else {\n\t\t\t\t//MessageBox(MainWindow, \"In Set_Video_Mode. About to call SetCooperativeLevel.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\t\tresult = DirectDrawObject->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);\n\t\t\t}\n\t\t\tProcess_DD_Result(result, FALSE);\n\t\t}else{\n\t\t\treturn (FALSE);\n\t\t}\n\t}\n\n\t//\n\t// Set the required display mode with 8 bits per pixel\n\t//\n\t//MessageBox(MainWindow, \"In Set_Video_Mode. About to call call SetDisplayMode.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\tresult = DirectDrawObject->SetDisplayMode ( w , h , bits_per_pixel );\n\tif (result != DD_OK){\n//\t\tProcess_DD_Result(result, FALSE);\n\t\tDirectDrawObject->Release();\n\t\tDirectDrawObject = NULL;\n\t\treturn(FALSE);\n\t}\n\n\t//\n\t// Create a direct draw palette object\n\t//\n\t//MessageBox(MainWindow, \"In Set_Video_Mode. About to call CreatePalette.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\tresult = DirectDrawObject->CreatePalette( DDPCAPS_8BIT | DDPCAPS_ALLOW256, &PaletteEntries[0] , &PalettePtr ,NULL);\n\tProcess_DD_Result(result, FALSE);\n\tif (result != DD_OK){\n\t\treturn (FALSE);\n\t}\n\n\tCheck_Overlapped_Blit_Capability();\n\n\t//MessageBox(MainWindow, \"In Set_Video_Mode. About to return success.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n#if (0)\n\t/*\n\t** Find out if DirectX 2 extensions are available\n\t*/\n\tresult = DirectDrawObject->QueryInterface (IID_IDirectDraw2, (LPVOID*)&DirectDraw2Interface);\n\tSystemToVideoBlits = FALSE;\n\tVideoToSystemBlits = FALSE;\n\tSystemToSystemBlits= FALSE;\n\tif (result != DD_OK){\n\t\tDirectDraw2Interface = NULL;\n\t}else{\n\t\tDDCAPS capabilities;\n\t\tDDCAPS emulated_capabilities;\n\n\t\tmemset ((char*)&capabilities, 0, sizeof(capabilities));\n\t\tmemset ((char*)&emulated_capabilities, 0, sizeof(emulated_capabilities));\n\t\tcapabilities.dwSize = sizeof (capabilities);\n\t\temulated_capabilities.dwSize = sizeof (emulated_capabilities);\n\n\t\tDirectDrawObject->GetCaps (&capabilities, &emulated_capabilities);\n\n\t\tif (capabilities.dwCaps & DDCAPS_CANBLTSYSMEM){\n\t\t\tSystemToVideoBlits = (capabilities.dwSVBCaps & DDCAPS_BLT) ? TRUE : FALSE;\n\t\t\tVideoToSystemBlits = (capabilities.dwVSBCaps & DDCAPS_BLT) ? TRUE : FALSE;\n\t\t\tSystemToSystemBlits = (capabilities.dwSSBCaps & DDCAPS_BLT) ? TRUE : FALSE;\n\t\t}\n\t}\n#endif\t//(0)\n\n\t//MessageBox(MainWindow, \"In Set_Video_Mode. About to return success.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\n\treturn (TRUE);\n\n}\n\n/***********************************************************************************************\n * Reset_Video_Mode -- Resets video mode and deletes Direct Draw Object                        *\n *                                                                                             *\n * INPUT:\t\tnone                                                                            *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/26/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid Reset_Video_Mode(void)\n{\n\tHRESULT result;\n\n\t//\n\t// If a direct draw object has been declared and a video mode has been set\n\t// then reset the video mode and release the direct draw object.\n\t//\n\tif ( DirectDrawObject ) {\n\t\tresult = DirectDrawObject->RestoreDisplayMode();\n\t\tProcess_DD_Result(result, FALSE);\n\t\tresult = DirectDrawObject->Release();\n\t\tProcess_DD_Result(result, FALSE);\n\n\t\tDirectDrawObject = NULL;\n\t}\n}\n\n\n\n\n/***********************************************************************************************\n * Get_Free_Video_Memory -- returns amount of free video memory                                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   bytes of available video RAM                                                      *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/29/95 12:52PM ST : Created                                                            *\n *=============================================================================================*/\nunsigned int Get_Free_Video_Memory(void)\n{\n\n\tDDCAPS\tvideo_capabilities;\n\n\tif (DirectDrawObject){\n\n\t\tvideo_capabilities.dwSize = sizeof (video_capabilities);\n\n\t\t//MessageBox(MainWindow, \"In Get_Free_Video_Memory. About to call GetCaps\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\tif (DD_OK == DirectDrawObject->GetCaps (&video_capabilities , NULL)){\n\t\t\tchar string [256];\n\t\t\tsprintf (string, \"In Get_Free_Video_Memory. About to return %d bytes\",video_capabilities.dwVidMemFree);\n\t\t\t//MessageBox(MainWindow, string,\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\treturn (video_capabilities.dwVidMemFree);\n\t\t}\n\t}\n\n\t//MessageBox(MainWindow, \"In Get_Free_Video_Memory. About to return failure\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\treturn (0);\n}\n\n\n\n\n/***********************************************************************************************\n * Get_Video_Hardware_Caps -- returns bitmask of direct draw video hardware support            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   hardware flags                                                                    *\n *                                                                                             *\n * WARNINGS: Must call Set_Video_Mode 1st to create the direct draw object                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/12/96 9:14AM ST : Created                                                              *\n *=============================================================================================*/\nunsigned Get_Video_Hardware_Capabilities(void)\n{\n\tDDCAPS\tvideo_capabilities;\n\tunsigned\tvideo;\n\n\t/*\n\t** Fail if the direct draw object has not been initialised\n\t*/\n\tif (!DirectDrawObject) return (0);\n\n\t/*\n\t** Get the capabilities of the direct draw object\n\t*/\n\tvideo_capabilities.dwSize = sizeof(video_capabilities);\n\t//MessageBox(MainWindow, \"In Get_Video_Hardware_Capabilities. About to call GetCaps\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\tHRESULT result = DirectDrawObject->GetCaps (&video_capabilities, NULL);\n\tif (result != DD_OK){\n\t\tProcess_DD_Result(result, FALSE);\n\t\treturn (0);\n\t}\n\n\t/*\n\t** Set flags to indicate the presence of the features we are interested in\n\t*/\n\tvideo = 0;\n\n\t/* Hardware blits supported? */\n\tif (video_capabilities.dwCaps & DDCAPS_BLT) \t\t\t\tvideo |= VIDEO_BLITTER;\n\n\t/* Hardware blits asyncronous? */\n\tif (video_capabilities.dwCaps & DDCAPS_BLTQUEUE) \t\tvideo |= VIDEO_BLITTER_ASYNC;\n\n\t/* Can palette changes be synced to vertical refresh? */\n\tif (video_capabilities.dwCaps & DDCAPS_PALETTEVSYNC) \tvideo |= VIDEO_SYNC_PALETTE;\n\n\t/* Is the video cards memory bank switched? */\n\tif (video_capabilities.dwCaps & DDCAPS_BANKSWITCHED) \tvideo |= VIDEO_BANK_SWITCHED;\n\n\t/* Can the blitter do filled rectangles? */\n\tif (video_capabilities.dwCaps & DDCAPS_BLTCOLORFILL)\tvideo |= VIDEO_COLOR_FILL;\n\n\t/* Is there no hardware assistance avaailable at all? */\n\tif (video_capabilities.dwCaps & DDCAPS_NOHARDWARE) \tvideo |= VIDEO_NO_HARDWARE_ASSIST;\n\n\t//MessageBox(MainWindow, \"In Get_Video_Hardware_Capabilities. About to return success.\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\treturn (video);\n}\n\n\n\n\n/***********************************************************************************************\n * Wait_Vert_Blank -- Waits for the start (leading edge) of a vertical blank                   *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *=============================================================================================*/\nextern int ScreenWidth;\nvoid Wait_Vert_Blank(void)\n{\n\tif( ScreenWidth!=320 && CanVblankSync){\n\t\tHRESULT result = DirectDrawObject->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);\n\t\tif (result == E_NOTIMPL){\n\t\t\tCanVblankSync = FALSE;\n\t\t\treturn;\n\t\t}\n\t\tProcess_DD_Result(result, FALSE);\n\t}\n}\n\n\n\n\n\n/***********************************************************************************************\n * Set_Palette -- set a direct draw palette                                                    *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to 768 rgb palette bytes                                                      *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/11/95 3:33PM ST : Created                                                             *\n *=============================================================================================*/\nvoid Set_DD_Palette ( void *palette )\n{\n\n\t/*\n\t** Trap null ptr\n\t*/\n\tif (!palette) return;\n\n\tint\tj;\n\tint\tk;\n\tchar\t*palette_get;\n\n\tif ( DirectDrawObject && PaletteSurface ){\n\n\t\tk=0;\n\n\t\tpalette_get = (char*)palette;\n\n\t\tfor( j=0 ; j<768 ; j+=3 )\n\t\t{\n\t\t\tPaletteEntries[k].peRed = (unsigned char)((*palette_get++)<<2);\n\t\t\tPaletteEntries[k].peGreen = (unsigned char)((*palette_get++)<<2);\n\t\t\tPaletteEntries[k].peBlue = (unsigned char)((*palette_get++)<<2);\n\t\t\tk++;\n\t\t}\n\n\t\tif ( !FirstPaletteSet ){\n\t\t\t//MessageBox(MainWindow, \"In Set_DD_Palette. About to call SetPalette\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\t\tPaletteSurface->SetPalette( PalettePtr );\n\t\t\tFirstPaletteSet=TRUE;\n\t\t}\n\n\t\t//MessageBox(MainWindow, \"In Set_DD_Palette. About to call SetEntries\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\t\tPalettePtr->SetEntries( 0 , 0 , 256 , &PaletteEntries[0] );\n\t}\n\t//MessageBox(MainWindow, \"Leaving Set_DD_Palette\",\"Note\", MB_ICONEXCLAMATION|MB_OK);\n\n}\n\n\n\n\n\n/***********************************************************************************************\n * Wait_Blit -- waits for the DirectDraw blitter to become idle                                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07-25-95 03:53pm ST : Created                                                             *\n *=============================================================================================*/\n\nvoid Wait_Blit (void)\n{\n\tHRESULT\treturn_code;\n\n\tdo {\n\t\treturn_code=PaletteSurface->GetBltStatus (DDGBS_ISBLTDONE);\n\t} while (return_code != DD_OK && return_code != DDERR_SURFACELOST);\n\n}\n\n\n\n/***********************************************************************************************\n * SMC::SurfaceMonitorClass -- constructor for surface monitor class                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/3/95 3:23PM ST : Created                                                              *\n *=============================================================================================*/\n\nSurfaceMonitorClass::SurfaceMonitorClass(void)\n{\n\tfor (int i=0 ; i<MAX_SURFACES ; i++)\n\t{\n\t\tSurface[i]=NULL;\n\t}\n\tInFocus=FALSE;\n\tSurfacesRestored=FALSE;\n}\n\n\n/***********************************************************************************************\n * SMC::Add_DD_Surface -- add a new surface to the list                                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to surface                                                                    *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *                 11/3/95 3:24PM ST : Created                                                 *\n *=============================================================================================*/\nvoid SurfaceMonitorClass::Add_DD_Surface (LPDIRECTDRAWSURFACE new_surface)\n{\n\tif ( !Got_Surface_Already (new_surface) ){\n\t\tfor (int i=0 ; i<MAX_SURFACES ; i++)\n\t\t{\n\t\t\tif ( Surface[i]==NULL ){\n\t\t\t\tSurface[i]=new_surface;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * SMC::Remove_DD_Surface -- remove a direct draw surface from the list                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to Surface                                                                    *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/3/95 3:25PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid SurfaceMonitorClass::Remove_DD_Surface (LPDIRECTDRAWSURFACE old_surface)\n{\n\tfor (int i=0 ; i<MAX_SURFACES ; i++)\n\t{\n\t\tif ( Surface[i]==old_surface ){\n\t\t\tSurface[i]=NULL;\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * SMC::Got_Surface_Already -- check if a surface is already in the list                       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to surface                                                                    *\n *                                                                                             *\n * OUTPUT:   True if surface is in list                                                        *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/3/95 3:25PM ST : Created                                                              *\n *=============================================================================================*/\n\nBOOL SurfaceMonitorClass::Got_Surface_Already (LPDIRECTDRAWSURFACE test_surface)\n{\n\tfor (int i=0 ; i<MAX_SURFACES ; i++)\n\t{\n\t\tif ( Surface[i]==test_surface ){\n\t\t\treturn(TRUE);\n\t\t}\n\t}\n\treturn (FALSE);\n}\n\n/***********************************************************************************************\n * SMC::Restore_Surfaces -- restore the direct draw surfaces in the list                       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/3/95 3:26PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid SurfaceMonitorClass::Restore_Surfaces (void)\n{\n\tif (InFocus){\n\t\t/*\n\t\t** Call restore for each Direct Draw surface\n\t\t*/\n\t\tfor (int i=0 ; i<MAX_SURFACES ; i++)\n\t\t{\n\t\t\tif ( Surface[i] ){\n\t\t\t\tif (Surface[i]->Restore() != DD_OK){\n\t\t\t\t\tif (Misc_Focus_Loss_Function){\n\t\t\t\t\t\tMisc_Focus_Loss_Function();\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** PWG/ST: Now that we know all the surfaces are restored call\n\t\t** the function pointer to notify the program that it has\n\t\t** happened.  This function pointer is used to clear the pages,\n\t\t** etc.\n\t\t*/\n\t\tif (Misc_Focus_Restore_Function){\n\t\t\tMisc_Focus_Restore_Function();\n\t\t}\n\n\t\tSurfacesRestored = TRUE;\n\n\t\t/*\n\t\t** Restore the palette\n\t\t*/\n\t\tSet_DD_Palette (CurrentPalette);\n\t}\n}\n\n\n/***********************************************************************************************\n * SMC::Set_Surface_Focus -- set the InFocus flag to the given state                           *\n *                                                                                             *\n *  The InFocus flag is used to keep track of whether our application is currently in focus.   *\n *  We dont want to be restoring video surfaces when we are supposed to be running in the      *\n *  background.                                                                                *\n *                                                                                             *\n * INPUT:    bool in focus                                                                     *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/6/95 12:21PM ST : Created                                                             *\n *=============================================================================================*/\n\nvoid SurfaceMonitorClass::Set_Surface_Focus ( BOOL in_focus )\n{\n\tInFocus=in_focus;\n}\n\n\n\n\n/***********************************************************************************************\n * SMC::Release -- releases all direct draw surfaces                                           *\n *                                                                                             *\n *  Call this at the end of the game before called RestoreDisplayMode                          *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/6/96 12:23PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid SurfaceMonitorClass::Release(void)\n{\n\t/*\n\t** Call release for each Direct Draw surface\n\t*/\n\tfor (int i=0 ; i<MAX_SURFACES ; i++)\n\t{\n\t\tif ( Surface[i] ){\n\t\t\tSurface[i]->Release();\n\t\t\tSurface[i] = 0;\n\t\t}\n\t}\n\n}\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DELAY.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : DELAY.C                                  *\n *                                                                         *\n *                   Programmer : Christopher Yates                        *\n *                                                                         *\n *                  Last Update : 27 March, 1991   [CY]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"wwstd.h\"\n#include <timer.h>\n\nvoid Delay(int duration)\n{\n\tunsigned long count;\n\tTimerClass timer(BT_SYSTEM,TRUE);\n\n\twhile (duration--) {\n\t\tcount = timer.Time() + 1L;\n\t\twhile (count >= timer.Time()) {\n\t\t\t;\n\t\t}\n\t}\n\n#if(FALSE)\n\twhile (duration--)\n\t\tWait_Vert_Blank(VertBlank);\n#endif\n}\n\n#if(FALSE)\nvoid Vsync()\n{\n\tWait_Vert_Blank(VertBlank);\n}\n#endif\n\u001a"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DESCMGMT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Descriptor management                    *\n *                                                                         *\n *                    File Name : DESCMGMT.CPP                             *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : March 28, 1994                           *\n *                                                                         *\n *                  Last Update : March 28, 1994   []                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * MAP_SEGMENT_TO_ADDRESS -- Maps a physical address into a selector       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"descmgmt.h\"\n#include \"misc.h\"\n\n\n/***************************************************************************\n * MAP_SEGMENT_TO_ADDRESS -- Maps a physical address into a selector       *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT: selector UWORD The selector mapped to address. exit on error.   *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/25/1994  jaw: Created.                                             *\n *=========================================================================*/\n\nULONG Map_Segment_To_Address(ULONG address, ULONG length)\n{\t\t\t\t\t\t\t \t\t\t\t\n\n// this function is not longer needed by RATIONAL SYSTEM DOS4GW\n// linear addressing mode.\n// a> the first megabyte of memory is mapped to linear adress 0 - 0x10000h\n// b> all other addresses are linear offset from either ds: or es:\n\n/*\n\tUWORD segment;\n\tUWORD curDS;\n\tCD_DES desc;\n\tCD_DES cur_desc;\n\n\t// allocate a selector\n\tif(_dos_allocmem(0, &segment) != 0) {\n\t\tExit(1, \"Allocation of Descriptor.\\n\");\n\t}\n\n\t// get the data for this selector\n\tif(_dx_ldt_rd(segment, (UCHAR *)&desc) != 0) {\n\t\tExit(1, \"Reading Descriptor.\\n\");\n\t}\n\n\t// get the data for current data segment\n\tcurDS = GetDs();\n\tif(_dx_ldt_rd(curDS, (UCHAR *)&cur_desc) != 0) {\n\t\tExit(1, \"Reading Descriptor.\\n\");\n\t}\n\t\n\t// set limit\n\tdesc.limit0_15 \t\t= (USHORT)(length & 0xffff);\n\tdesc.limit16_19 \t= ((UCHAR)(length >> 16L)) | DOS_32;\n\n\t// set base address\n\tdesc.base0_15 \t\t= (USHORT)(address & 0xffff);\n\tdesc.base16_23\t\t= (UCHAR)((address >> 16) & 0xff);\n\tdesc.base24_31\t\t= (UCHAR)((address >> 24) & 0xff);\n\n\t// set rights mark as icurrent data segment\n\tdesc.arights \t\t= cur_desc.arights;\n\t\t\t\t\t\t\t \n\t// write to LDT selector\n\tif(_dx_ldt_wr(segment, (UCHAR *)&desc) != 0) {\n\t\tExit(1, \"Failed writing descriptor.\\n\");\n\t}\n\n\t// return selector number\n\treturn segment;\n */\n\n       if ( address & 0xfff0ffff ) \n\t    Exit ( 1 , \"Error mapping real address to lineal address.\\n\" ) ;\n\n       return address ;\n}\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DETPROC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/system/rcs/detproc.asm 1.1 1994/04/18 09:13:53 jeff_wilson Exp $\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : PROC.ASM                                 *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : May 11, 1993                             *\n;*                                                                         *\n;*                  Last Update : May 11, 1993   [JLB]                     *\n;*                                                                         *\n;*  Converted to 32Bit -- JAW                                              *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL \t      \tC Processor          :NEAR\n\n\nPROC_80386\tequ\t0\nPROC_80486\tequ\t1\nPROC_80586\tequ\t2\n\nDATASEG\ncpu_id_586\tdw\t0\n\nCODESEG\n\nPROC\tProcessor C near\n\tUSES ebx\n\tLOCAL\tptype:WORD\n\n\tpushfd\n\n; At least a 386 -- check for 486.\n\tmov\t[WORD PTR ptype],PROC_80386\t; 80386\n\tpushfd\n\tpop\teax\n\tmov\tebx,eax\n\txor\teax,40000h\n\tpush\teax\n\tpopfd\n\tpushfd\n\tpop\teax\n\txor\teax,ebx\n\tje\tshort ??fini\n\n; At least a 486 -- check for 586(Pentium)\n\tmov\t[ptype],PROC_80486\t; 80486\n\n\t; Some machines have a problem with this fLAG\n\t; and thus make us think they are a 586 but they are\n\t; really a 486. A possible way around this is to\n\t; capture the Illegal instruction vector, then  do\n\t; an instruction only available on the 586.\n\n\t; for now this is just commented out\n\tpushfd\n\tpop\teax\n\tmov\tebx,eax\n\txor\teax,200000h\n\tpush\teax\n\tpopfd\n\tpushfd\n\tpop\teax\n\txor\teax,ebx\n\tje\tshort ??fini\n\n; At least a 586(Pentium) -- check for higher.\n\tmov\t[ptype],PROC_80586\t; 80486\n;\tmov\teax,1\n;\tDW\t0fA2h\t\t; CPUID opcode.\n;\tshr\tax,8\n;\tand\tax,0fh\n;\tinc\tax\n;\tinc\tax\n;\tmov\t[cpu_id_586],ax\n\n; Final cleanup and exit.\n??fini:\n\tpopfd\n\tsub\teax,eax\n\tmov\tax,[ptype]\n\tret\n\nENDP\tProcessor\n\nEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DEVICES.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/system/rcs/devices.asm 1.2 1994/04/28 12:41:41 jeff_wilson Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : DEVICES.ASM                              *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : 12 December, 1990   [CY]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n; VOID Get_Devices(VOID);                                                  *\n; WORD Is_Device_Real(WORD drive);                                         *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\n;----------------------------------------------------------------------------\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL  \t    Get_Devices          :NEAR\nGLOBAL              Is_Device_Real       :NEAR\n\nGLOBAL              MaxDevice          \t :BYTE\nGLOBAL              DefaultDrive         :BYTE\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; VOID Get_Devices(VOID);\n; WORD Is_Device_Real(WORD drive);\n;\n; ----------------------------------------------------------------\n\nCODESEG\n\n;***********************************************************\n;\n; GET_DEVICES\n;\n; VOID Get_Devices(VOID);\n;\n; This routine establishes the default disk drive and the maximum drive\n; available in the current system.\n;\n;*\nDOS\tequ\t21h\n\nPROC\tGet_Devices C near \n\tUSES eax,ebx,edx\n\t\t   \n   \tsub\teax,eax\n\tmov\tah,25\t\t\t; get current drive service\n\tint\tDOS\t\t\t; drive returned in al\n\tmov\t[DefaultDrive],al\t; save it\n\tmov\tdl,al\n\tmov\tah,14\t\t\t; set current as current drive\n\tint\tDOS\n\tdec\tal\t\t\t; al = max drives, make it n - 1\n\txor\tah,ah\t\t\t; clear high byte\n\tmov\tedx,eax\t\t\t; use dx to go backward to find out\n\tsub\tebx,ebx\n\n??back_loop:\n\tmov\tbl,dl\t\t\t; find out about the drive in dl\n\tinc\tbl\n\tmov\teax,0440Eh \t\t; get the physical drive associated\n\tint\tDOS\t\t\t; with this letter\n\tjnc\tshort ??later\t\t; if c clear, no error\n\tcmp\tal,0Fh\t\t\t; was it invalid? (0Fh = invalid)\n\tjne\tshort ??later\t\t; yes, so LATER\n\tdec\tedx\n\tjmp\t??back_loop\t\t; try, try again\n\n??later:\n\tmov\teax,edx\t\t\t; restore ax\n\tmov\t[MaxDevice],al\t\t; save the max drive #\n\n\tret\n\nENDP\tGet_Devices\n\n;***************************************************************\n\n\n;***************************************************************\n;\n; IS_DEVICE_REAL\n;\n; WORD Is_Device_Real(WORD drive);\n;\n; This routine will tell whether or not a device is a true\n; phisical one.  Send it the drive # to check.\n;\n;*\nPROC\tIs_Device_Real C near \n\tUSES ebx,edx\n\tARG\tdrive:WORD\n\n\tsub\tedx,edx\n\tmov\tdx,[drive]\n\n??next_drive:\n\tpush\tebx\n\tmov\tbl,dl\t\t\t; find out about the drive in dl\n\tinc\tbl\n\tmov\teax,0440Eh \t\t; get the physical drive associated\n\tint\tDOS\t\t\t; with this letter\n\tpop\tebx\n\n\tjnc\tshort ??it_is_real\t; jump if no error\n\tcmp\tal,01\t\t\t; 1 = invalid command, \n\t\t\t\t\t; 0F = invalid device\n\tje\tshort ??real\t\t\t; 1? it is ok (RAM device)\n\tjmp\tshort ??invalid\t\t; 0Fh, it was not a device\n\n??it_is_real:\n\tcmp\tal,0\t\t\t; was it a fixed device?\n\tje\tshort ??real\t\t\t; yes, it's ok\n\tdec\tal\t\t\t; make it a drive #\n\tcmp\tal,dl\t\t\t; is it a valid drive?\n\tje\tshort ??real\n\n??invalid:\t\t\t\t; The device is invalid.\n\tmov\teax,0\n\tjmp\tshort ??out\t\t\t\n\n??real:\t\t\t\t\t; Return true, for valid device.\n\tmov\teax,1\n\t\t    \n??out:\n\tret\nENDP\tIs_Device_Real\n\n;***************************************************************\n\nEND\n\u001a"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DEVTABLE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/system/rcs/devtable.asm 1.2 1994/04/28 12:41:29 jeff_wilson Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : DEVTABLE.ASM                             *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : 12 December, 1990   [CY]                 *\n;*                                                                         *\n;* Updated to 32bit protected mode JAW\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n; VOID Init_Device_Table(BYTE *table);                                     *\n; WORD Max_Device(VOID);\t\t\t\t\t\t   *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nLOCALS ??\n\nDOS\tequ\t21h\n\nGLOBAL\t Max_Device\t\t\t:NEAR\nGLOBAL\t get_max_device \t\t:NEAR\nGLOBAL\t Init_Device_Table\t\t:NEAR\n\t\t\t\t\t \n\nCODESEG\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; VOID Init_Device_Table(BYTE *table);\n; WORD Max_Device(VOID);\n;\n; ----------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n;\n; WORD Max_Device(VOID);\n;\n\nPROC\tMax_Device C NEAR\n\t\n\tcall\tget_max_device\t\t; get max devices in ax\n\tret\n\nENDP\tMax_Device\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n;\n;\n; returns max devices in AX\n\nPROC\tget_max_device C NEAR \n\tUSES ebx,edx\n\t\n\tmov\tah,25\t\t\t; get current drive service\n\tint\tDOS\t\t\t; drive returned in al\n\tmov\tdl,al\n\tmov\tah,14\t\t\t; set current as current drive\n\tint\tDOS\n\tdec\tal\t\t\t; al = max drives, make it n - 1\n\txor\tah,ah\t\t\t; clear high byte\n\tsub\tedx,edx\n\tmov\tedx,eax\t\t\t; use dx to go backward to find out\n\t\t\t\t\t; if DOS is lying (down)\n\n??back_loop:\n\tpush\tds\n\tpush\tebx\n\tmov\tbl,dl\t\t\t; find out about the drive in dl\n\tinc\tbl\n\tmov\teax,0440Eh \t\t; get the physical drive associated\n\tint\tDOS\t\t\t; with this letter\n\tpop\tebx\n\tpop\tds\n\tjnc\tshort ??later\t\t; if c clear, no error\n\t\n\tcmp\tal,0Fh\t\t\t; was it invalid? (0Fh = invalid)\n\tjne\tshort ??later\t\t\t; yes, so LATER\n\t\n\tdec\tedx\n\tjmp\t??back_loop\t\t; try, try again\n\n??later:\n\tmov\teax,edx\t\t\t; restore ax\n\tret\n\nENDP\tget_max_device\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n;\n; VOID Init_Device_Table(BYTE *table);\n;\n\nPROC\tInit_Device_Table C NEAR \n\n\tUSES eax,ebx,edi,edx\n\tARG\ttable:DWORD\t   \t; Pointer to device table.\n\tLOCAL\tcurr_drive:BYTE\t   \t; Copy of current drive number.\n\n\tmov\tedi,[table]\n\n\tcall\tget_max_device\t\t; get max devices in ax\n\tadd\tedi,eax\n\tstd\n\tmov\t[curr_drive],al\t; save it\n\n??next_drive:\n\tmov\tdl,[curr_drive]\t; copy current drive #\n\tcmp\tdl,0FFh\t\t\t; are we done?\n\tje\tshort ??later\t\t\t; if so, later\n\n\tdec\t[curr_drive]\t\t; dec our local drive #\n\n\tpush\tds\n\tpush\tebx\n\tmov\tbl,dl\t\t\t; find out about the drive in dl\n\tinc\tbl\n\tmov\teax,0440Eh \t\t; get the physical drive associated\n\tint\tDOS\t\t\t; with this letter\n\tpop\tebx\n\tpop\tds\n\n\tjnc\tshort ??it_is_real\t\t; jump if no error\n\tcmp\tal,01\t\t\t; 1 = invalid command, \n\t\t\t\t\t; 0F = invalid device\n\tje\tshort ??set_as_current\t; 1? it is ok (RAM device)\n\tjmp\tshort ??invalid\t\t; 0Fh, it was not a device\n\n\n??it_is_real:\n\tcmp\tal,0\t\t\t; was it a fixed device?\n\tje\tshort ??set_as_current\t; yes, it's ok\n\t\n\tdec\tal\t\t\t; make it a drive #\n\tcmp\tal,dl\t\t\t; is it a valid drive?\n\tje\tshort ??set_as_current\n\n;\n; Device was logical and not active, so clear the entry\n;\n??invalid:\n\txor\tal,al\n\tstosb\n\tcmp\t[curr_drive],0\t\t; are we done checking?\n\tjge\t??next_drive\t   \t; no, go to next\n\t\n\tjmp\tshort ??later\n\n??set_as_current:\n\tmov\tal,1\n\tstosb\n\tcmp\tdl,0\t\t\t; are we before the A drive (invalid)\n\tjl\tshort ??later\t\t\t; yes, we are done checking\n\t\n\tjmp\t??next_drive\t\t; keep processing\n\n??later:\n\tcld\n\tret\n\nENDP\tInit_Device_Table\n\n;----------------------------------------------------------------------------\n\nEND\n\u001a"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DIPTHONG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./dipthong.c 1.15 1994/05/20 15:35:17 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : DIPTHONG.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : February 23, 1992                        *\n *                                                                         *\n *                  Last Update : February 13, 1995 [BWG]                  *\n *                                                                         *\n * DIGRAM or DIATOMIC encoding is the correct term for this method.        *\n * This is a fixed dictionary digram encoding optimized for English text.  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Extract_String -- Extracts a string pointer from a string data block. *\n *   UnDip_Text -- Undipthongs a text string into specified buffer.        *\n *   Dip_Text -- Compresses text by using dipthonging.                     *\n *   Fixup_Text -- Converts dipthonged foreign text into normal text.      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n//#include\t\"function.h\"\n//#include\t\"ems.h\"\n#include <keyboard.h>\n#include \"dipthong.h\"\n\n/***************************************************************************\n * Fixup_Text -- Converts dipthonged foreign text into normal text.        *\n *                                                                         *\n *    Takes text that has been processed (or undipped) to hold foriegn     *\n *    language character pairs (needed for Window_Print) and converts it   *\n *    so that Text_Print will print it properly.  Typically this would be  *\n *    used after text has been undipped but before it will be Text_Printed.*\n *    Text that is to be Window_Printed doesn't and mustn't have its text  *\n *    processed by this routine.                                           *\n *                                                                         *\n * INPUT:   source   -- Pointer to the source string to process.           *\n *                                                                         *\n *          dest     -- Destination buffer to hold the processed string.   *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine will only reduce the size of the string if it  *\n *             modifies it at all.  Because of this it is quite legal to   *\n *             pass the same pointers to this routine so that it will      *\n *             modify the string \"in place\".                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/13/1993 JLB : Created.                                             *\n *   10/06/1994 JLB : Handles source string in EMS.                        *\n *=========================================================================*/\nvoid Fixup_Text(char const *source, char *dest)\n{\n\tif (source && dest) {\n\t\tchar const \t*src;\n\t\tchar\t\t\ttemp;\n\n\t\tsrc = source;\n\t\twhile (*src) {\n\t\t\tif (*src == KA_EXTEND) {\n\t\t\t\tsrc++;\n\t\t\t\ttemp = *src++;\n\t\t\t\ttemp += 127;\n\t\t\t\t*dest++ = temp;\n\t\t\t} else {\n\t\t\t\t*dest++ = *src++;\n\t\t\t}\n\t\t}\n\t\t*dest = '\\0';\n\n\t}\n}\n\n\n/***************************************************************************\n * Dip_Text -- Compresses text by using dipthonging.                       *\n *                                                                         *\n *    This routine is used to compress text by using dipthonging.  Text    *\n *    that is compressed in this fashion usually is reduced in size by     *\n *    approximately 40%.                                                   *\n *                                                                         *\n * INPUT:   source   -- Pointer to the source string to compress.          *\n *                                                                         *\n *          dest     -- Pointer to the buffer that will hold the dipthong  *\n *                      text output.                                       *\n *                                                                         *\n * OUTPUT:  Returns the number of bytes output into the output buffer.     *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/13/1993 JLB : Created.                                             *\n *=========================================================================*/\nint Dip_Text(char const *source, char *dest)\n{\n\tunsigned char\tfirst,\t\t// First character in pair.\n\t\t\t\t\t\tnext;\t\t\t// Second character in pair.\n\tint\t\t\t\tcommon,\t\t// Common character index.\n\t\t\t\t\t\tdipthong;\t// Dipthong character index.\n\n\tunsigned long length=0;\t\t// Length of output string\n\n\tfirst = *source++;\n\tnext = *source;\n\twhile (first) {\n\n\t\tif (first > 127) {\n\n\t\t\t/*\n\t\t\t**\tCharacters greater than 127 cannot be dipthonged.  They must\n\t\t\t**\tbe preceeded with an extended character code.\n\t\t\t*/\n\t\t\t*dest++ = (char)KA_EXTEND;\n\t\t\tfirst -= 127;\n\t\t\tlength++;\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tNormal characters can be dipthonged.  First see if there is a\n\t\t\t**\tmatch in the Common table.\n\t\t\t*/\n\t\t\tfor (common = 0; common < 16; common++) {\n\t\t\t\tif (Common[common] == first) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCommon character found.  See if there is a matching\n\t\t\t\t\t**\tDipthong character.\n\t\t\t\t\t*/\n\t\t\t\t\tfor (dipthong = 0; dipthong < 8; dipthong++) {\n\t\t\t\t\t\tif (Dipthong[common][dipthong] == next) {\n\t\t\t\t\t\t\tfirst = (unsigned char) (common << 3);\n\t\t\t\t\t\t\tfirst |= (unsigned char)dipthong;\n\t\t\t\t\t\t\tfirst |= (unsigned char)0x80;\n\t\t\t\t\t\t\tsource++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tOutput the translated character to the destination buffer.\n\t\t*/\n\t\t*dest++ = first;\n\t\tlength++;\n\n\t\tfirst = *source++;\n\t\tnext = *source;\n\t}\n\n\t*dest = '\\0';\n\n\treturn(length);\n}\n\n\n/***************************************************************************\n * UnDip_Text -- Undipthongs a text string into specified buffer.          *\n *                                                                         *\n *    This routine is used to undipthong a text string and place the       *\n *    undipped text into the buffer specified.  Since dipthonged text is   *\n *    compressed, in order for the text to be used it must be undipped     *\n *    first.                                                               *\n *                                                                         *\n * INPUT:   source   -- Pointer to the dipped string.                      *\n *                                                                         *\n *          dest     -- Pointer to the destination buffer.                 *\n *                                                                         *\n * OUTPUT:  Returns the number of bytes placed into the destination        *\n *          buffer.                                                        *\n *                                                                         *\n * WARNINGS:   Be sure the destination buffer is big enough to hold the    *\n *             undipped text.                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/13/1993 JLB : Created.                                             *\n *   10/06/1994 JLB : Handles source string in EMS.                        *\n *=========================================================================*/\nint UnDip_Text(char const *source, char *dest)\n{\n\tint\tc;\t\t\t// Source input character.\n\tint\tcommon;\t// Common character index.\n\tint\tlen;\t\t// Length of output string.\n\tchar const *src;\n\n\tlen = 0;\t\t\t\t\t\t// Presume no translation.\n\n\t/*\n\t**\tSweep through the source text and dipthong it.\n\t*/\n\tsrc = source;\n\tc = *src++;\n\twhile (c) {\n\n\t\t/*\n\t\t**\tConvert a dipthong character into it's component\n\t\t**\tASCII characters.\n\t\t*/\n\t\tif (c & 0x80) {\n\t\t\tc &= 0x7F;\n\n\t\t\tcommon = (c & 0x78) >> 3;\n\n\t\t\t*dest++ = Common[common];\n\t\t\tlen++;\n\n\t\t\tc = Dipthong[common][c & 0x07];\n\t\t}\n\n\t\t*dest++ = (unsigned char)c;\n\t\tlen++;\n\n\t\tc = *src++;\n\t}\n\n\t/*\n\t**\tEnd the output text with a '\\0'.\n\t*/\n\t*dest++ = '\\0';\n\n\treturn(len);\n}\n\n\n/***************************************************************************\n * Extract_String -- Extracts a string pointer from a string data block.   *\n *                                                                         *\n *    This routine is used to find a pointer to the specified string       *\n *    inside a string block.  String data blocks are created with the      *\n *    TEXTMAKE utility.  The data block my reside in XMS or EMS memory,    *\n *    but of course the returned string pointer will also point to         *\n *    such memory.  In this case, the string must be placed in real        *\n *    memory before it can be used.                                        *\n *                                                                         *\n * INPUT:   data     -- Pointer to the string data block.                  *\n *                                                                         *\n *          string   -- The string number to extract (if < 0 then NULL     *\n *                      is returned).                                      *\n *                                                                         *\n * OUTPUT:  Returns with pointer to the string number specified.           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/13/1993 JLB : Created.                                             *\n *   08/13/1993 JLB : Handles EMS or XMS data pointer.                     *\n *=========================================================================*/\n\n#define TXT_GUEST \t\t\t\t\t4567+3\n#define TXT_LOGIN \t\t\t\t\t4567+4\n#define TXT_LOGIN_TO_INTERNET \t4567+5\n#define TXT_YOUR_HANDLE \t\t\t4567+6\n#define TXT_YOUR_PASSWORD \t\t4567+7\n#define TXT_INTERNET_HOST\t\t4567+8\n#define TXT_INTERNET_JOIN\t\t4567+9\n#define TXT_INTERNET_GAME_TYPE\t4567+10\n#define TXT_JOIN_INTERNET_GAME\t4567+11\n#define TXT_ENTER_IP_ADDRESS\t4567+12\n#define TXT_WINSOCK_CONNECTING\t\t\t\t\t\t\t4567+13\n#define TXT_WINSOCK_NOT_CONNECTING\t\t\t\t\t4567+14\n#define TXT_WINSOCK_UNABLE_TO_CONNECT_TO_SERVER\t4567+15\n#define TXT_WINSOCK_CONTACTING_SERVER\t\t\t\t4567+16\n#define TXT_WINSOCK_SERVER_ADDRESS_LOOKUP_FAILED\t4567+17\n#define TXT_WINSOCK_UNABLE_TO_ACCEPT_CLIENT\t\t4567+18\n#define TXT_WINSOCK_UNABLE_TO_CONNECT\t\t\t\t4567+19\n#define TXT_WINSOCK_CONNECTION_LOST\t\t\t\t\t4567+20\n#define TXT_WINSOCK_RESOLVING_HOST_ADDRESS\t\t\t4567+21\n\nstatic char InternetTxt[22][40]={\n\t\"Internet H2H\",\n\t\"Host Internet Game\",\n\t\"Join Internet Game\",\n\t\"Guest\",\n\t\"Login\",\n\t\"Login to Planet Westwood\",\n\t\"Planet Westwood Handle\",\n\t\"Planet Westwood Password\",\n\t\"Host Game\",\n\t\"Join Game\",\n\t\"Choose Type of Internet Game\",\n\t\"Join Internet Game\",\n\t\"Address of Host\",\n\t\"Connecting...\",\n\t\"Connection Error!\",\n\t\"Unable to connect to host!\",\n\t\"Connecting to host...\",\n\t\"Unable to resolve host address!\",\n\t\"Unable to accept client connection\",\n\t\"Unable to connect!\",\n\t\"Connection lost!\",\n\t\"Resolving address of host...\"\n};\n\nchar *Extract_String(void const *data, int string)\n{\n\tunsigned short int\tconst *ptr;\n\n\tif (!data || string < 0) return(NULL);\n\n\tif (string >= 4567) return (InternetTxt[string-4567]);\n\n\tptr = (unsigned short int const *)data;\n\treturn (((char*)data) + ptr[string]);\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DRAWLINE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : DRAWLINE.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 16, 1994                            *\n;*                                                                         *\n;*                  Last Update : August 30, 1994   [IML]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVC::Scale -- Scales a virtual viewport to another virtual viewport   *\n;*   Normal_Draw -- jump loc for drawing  scaled line of normal pixel      *\n;*   __DRAW_LINE -- Assembly routine to draw a line                        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n\n\n;***************************************************************************\n;* VVC::DRAW_LINE -- Scales a virtual viewport to another virtual viewport *\n;*                                                                         *\n;* INPUT:\tWORD sx_pixel \t- the starting x pixel position\t\t   *\n;*\t\tWORD sy_pixel\t- the starting y pixel position\t\t   *\n;*\t\tWORD dx_pixel\t- the destination x pixel position\t   *\n;*\t\tWORD dy_pixel   - the destination y pixel position\t   *\n;*\t\tWORD color      - the color of the line to draw\t\t   *\n;*                                                                         *\n;* Bounds Checking: Compares sx_pixel, sy_pixel, dx_pixel and dy_pixel\t   *\n;*       with the graphic viewport it has been assigned to.\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/16/1994 PWG : Created.                                             *\n;*   08/30/1994 IML : Fixed clipping bug.\t\t\t\t   *\n;*=========================================================================*\n\tPROC\tBuffer_Draw_Line C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\t;*==================================================================\n\t;* Define the arguements that the function takes.\n\t;*==================================================================\n\tARG\tthis_object:DWORD\t; associated graphic view port\n\tARG\tx1_pixel:DWORD\t\t; the start x pixel position\n\tARG\ty1_pixel:DWORD\t\t; the start y pixel position\n\tARG\tx2_pixel:DWORD\t\t; the dest x pixel position\n\tARG\ty2_pixel:DWORD\t\t; the dest y pixel position\n\tARG\tcolor:DWORD\t\t; the color we are drawing\n\n\t;*==================================================================\n\t;* Define the local variables that we will use on the stack\n\t;*==================================================================\n\tLOCAL\tclip_min_x:DWORD\n\tLOCAL\tclip_max_x:DWORD\n\tLOCAL\tclip_min_y:DWORD\n\tLOCAL\tclip_max_y:DWORD\n\tLOCAL\tclip_var:DWORD\n\tLOCAL\taccum:DWORD\n\tLOCAL\tbpr:DWORD\n\n\t;*==================================================================\n\t;* Take care of find the clip minimum and maximums\n\t;*==================================================================\n\tmov\tebx,[this_object]\n\txor\teax,eax\n\tmov\t[clip_min_x],eax\n\tmov\t[clip_min_y],eax\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\n\tmov\t[clip_max_x],eax\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\n\tadd\teax,[(GraphicViewPort ebx).GVPPitch]\n\tmov\t[bpr],eax\n\tmov\teax,[(GraphicViewPort ebx).GVPHeight]\n\tmov\t[clip_max_y],eax\n\n\t;*==================================================================\n\t;* Adjust max pixels as they are tested inclusively.\n\t;*==================================================================\n\tdec\t[clip_max_x]\n\tdec\t[clip_max_y]\n\n\t;*==================================================================\n\t;* Set the registers with the data for drawing the line\n\t;*==================================================================\n\tmov\teax,[x1_pixel]\t\t; eax = start x pixel position\n\tmov\tebx,[y1_pixel]\t\t; ebx = start y pixel position\n\tmov\tecx,[x2_pixel]\t\t; ecx = dest x pixel position\n\tmov\tedx,[y2_pixel]\t\t; edx = dest y pixel position\n\n\t;*==================================================================\n\t;* This is the section that \"pushes\" the line into bounds.\n\t;* I have marked the section with PORTABLE start and end to signify\n\t;* how much of this routine is 100% portable between graphics modes.\n\t;* It was just as easy to have variables as it would be for constants\n\t;* so the global vars ClipMaxX,ClipMinY,ClipMaxX,ClipMinY are used\n\t;* to clip the line (default is the screen)\n\t;* PORTABLE start\n\t;*==================================================================\n\n\tcmp\teax,[clip_min_x]\n\tjl\tshort ??clip_it\n\tcmp\teax,[clip_max_x]\n\tjg\tshort ??clip_it\n\tcmp\tebx,[clip_min_y]\n\tjl\tshort ??clip_it\n\tcmp\tebx,[clip_max_y]\n\tjg\tshort ??clip_it\n\tcmp\tecx,[clip_min_x]\n\tjl\tshort ??clip_it\n\tcmp\tecx,[clip_max_x]\n\tjg\tshort ??clip_it\n\tcmp\tedx,[clip_min_y]\n\tjl\tshort ??clip_it\n\tcmp\tedx,[clip_max_y]\n\tjle\tshort ??on_screen\n\n\t;*==================================================================\n\t;* Takes care off clipping the line.\n\t;*==================================================================\n??clip_it:\n\tcall\tNEAR PTR ??set_bits\n\txchg\teax,ecx\n\txchg\tebx,edx\n\tmov\tedi,esi\n\tcall\tNEAR PTR ??set_bits\n\tmov\t[clip_var],edi\n\tor\t[clip_var],esi\n\tjz\tshort ??on_screen\n\ttest\tedi,esi\n\tjne\tshort ??off_screen\n\tshl\tesi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+esi]\n\tjc\t??clip_it\n\txchg\teax,ecx\n\txchg\tebx,edx\n\tshl\tedi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+edi]\n\tjmp\t??clip_it\n\n??on_screen:\n\tjmp\t??draw_it\n\n??off_screen:\n\tjmp\t??out\n\n\t;*==================================================================\n\t;* Jump table for clipping conditions\n\t;*==================================================================\n??clip_tbl\tDD\t??nada,??a_up,??a_dwn,??nada\n\t\tDD\t??a_lft,??a_lft,??a_dwn,??nada\n\t\tDD\t??a_rgt,??a_up,??a_rgt,??nada\n\t\tDD\t??nada,??nada,??nada,??nada\n\n??nada:\n\tclc\n\tretn\n\n??a_up:\n\tmov\tesi,[clip_min_y]\n\tcall\tNEAR PTR ??clip_vert\n\tstc\n\tretn\n\n??a_dwn:\n\tmov\tesi,[clip_max_y]\n\tneg\tesi\n\tneg\tebx\n\tneg\tedx\n\tcall\tNEAR PTR ??clip_vert\n\tneg\tebx\n\tneg\tedx\n\tstc\n\tretn\n\n\t;*==================================================================\n\t;* xa'=xa+[(miny-ya)(xb-xa)/(yb-ya)]\n\t;*==================================================================\n??clip_vert:\n\tpush\tedx\n\tpush\teax\n\tmov\t[clip_var],edx\t\t; clip_var = yb\n\tsub\t[clip_var],ebx\t\t; clip_var = (yb-ya)\n\tneg\teax\t\t\t; eax=-xa\n\tadd\teax,ecx\t\t\t; (ebx-xa)\n\tmov\tedx,esi\t\t\t; edx=miny\n\tsub\tedx,ebx\t\t\t; edx=(miny-ya)\n\timul\tedx\n\tidiv\t[clip_var]\n\tpop\tedx\n\tadd\teax,edx\n\tpop\tedx\n\tmov\tebx,esi\n\tretn\n\n??a_lft:\n\tmov\tesi,[clip_min_x]\n\tcall\tNEAR PTR ??clip_horiz\n\tstc\n\tretn\n\n??a_rgt:\n\tmov\tesi,[clip_max_x]\n\tneg\teax\n\tneg\tecx\n\tneg\tesi\n\tcall\tNEAR PTR ??clip_horiz\n\tneg\teax\n\tneg\tecx\n\tstc\n\tretn\n\n\t;*==================================================================\n\t;* ya'=ya+[(minx-xa)(yb-ya)/(xb-xa)]\n\t;*==================================================================\n??clip_horiz:\n\tpush\tedx\n\tmov\t[clip_var],ecx\t\t; clip_var = xb\n\tsub\t[clip_var],eax\t\t; clip_var = (xb-xa)\n\tsub\tedx,ebx\t\t\t; edx = (yb-ya)\n\tneg\teax\t\t\t; eax = -xa\n\tadd\teax,esi\t\t\t; eax = (minx-xa)\n\timul\tedx\t\t\t; eax = (minx-xa)(yb-ya)\n\tidiv\t[clip_var]\t\t; eax = (minx-xa)(yb-ya)/(xb-xa)\n\tadd\tebx,eax\t\t\t; ebx = xa+[(minx-xa)(yb-ya)/(xb-xa)]\n\tpop\tedx\n\tmov\teax,esi\n\tretn\n\n\t;*==================================================================\n\t;* Sets the condition bits\n\t;*==================================================================\n??set_bits:\n\txor\tesi,esi\n\tcmp\tebx,[clip_min_y]\t; if y >= top its not up\n\tjge\tshort ??a_not_up\n\tor\tesi,1\n\n??a_not_up:\n\tcmp\tebx,[clip_max_y]\t; if y <= bottom its not down\n\tjle\tshort ??a_not_down\n\tor\tesi,2\n\n??a_not_down:\n\tcmp\teax,[clip_min_x]   \t; if x >= left its not left\n\tjge\tshort ??a_not_left\n\tor\tesi,4\n\n??a_not_left:\n\tcmp\teax,[clip_max_x]\t; if x <= right its not right\n\tjle\tshort ??a_not_right\n\tor\tesi,8\n\n??a_not_right:\n\tretn\n\n\t;*==================================================================\n\t;* Draw the line to the screen.\n\t;* PORTABLE end\n\t;*==================================================================\n??draw_it:\n\tsub\tedx,ebx\t\t\t; see if line is being draw down\n\tjnz\tshort ??not_hline\t; if not then its not a hline\n\tjmp\tshort ??hline\t\t; do special case h line\n\n??not_hline:\n\tjg\tshort ??down\t\t; if so there is no need to rev it\n\tneg\tedx\t\t\t; negate for actual pixel length\n\txchg\teax,ecx\t\t\t; swap x's to rev line draw\n\tsub\tebx,edx\t\t\t; get old edx\n\n??down:\n\tpush\tedx\n\tpush\teax\n\tmov\teax,[bpr]\n\tmul\tebx\n\tmov\tebx,eax\n\tmov\teax,[this_object]\n\tadd\tebx,[(GraphicViewPort eax).GVPOffset]\n\tpop\teax\n\tpop\tedx\n\n\tmov\tesi,1\t\t\t; assume a right mover\n\tsub\tecx,eax\t\t\t; see if line is right\n\tjnz\tshort ??not_vline\t; see if its a vertical line\n\tjmp\t??vline\n\n??not_vline:\n\tjg\tshort ??right\t\t; if so, the difference = length\n\n??left:\n\tneg\tecx\t\t\t; else negate for actual pixel length\n\tneg\tesi\t\t\t; negate counter to move left\n\n??right:\n\tcmp\tecx,edx\t\t\t; is it a horiz or vert line\n\tjge\tshort ??horiz\t\t; if ecx > edx then |x|>|y| or horiz\n\n??vert:\n\txchg\tecx,edx\t\t\t; make ecx greater and edx lesser\n\tmov\tedi,ecx\t\t\t; set greater\n\tmov\t[accum],ecx\t\t; set accumulator to 1/2 greater\n\tshr\t[accum],1\n\n\t;*==================================================================\n\t;* at this point ...\n\t;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;\n\t;* esi=adder; accum=accumulator\n\t;* in a vertical loop the adder is conditional and the inc constant\n\t;*==================================================================\n??vert_loop:\n\tadd\tebx,eax\n\tmov\teax,[color]\n\n??v_midloop:\n\tmov\t[ebx],al\n\tdec\tecx\n\tjl\t??out\n\tadd\tebx,[bpr]\n\tsub\t[accum],edx\t\t; sub the lesser\n\tjge\t??v_midloop\t\t; any line could be new\n\tadd\t[accum],edi\t\t; add greater for new accum\n\tadd\tebx,esi\t\t\t; next pixel over\n\tjmp\t??v_midloop\n\n??horiz:\n\tmov\tedi,ecx\t\t\t; set greater\n\tmov\t[accum],ecx\t\t; set accumulator to 1/2 greater\n\tshr\t[accum],1\n\n\t;*==================================================================\n\t;* at this point ...\n\t;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;\n\t;* esi=adder; accum=accumulator\n\t;* in a vertical loop the adder is conditional and the inc constant\n\t;*==================================================================\n??horiz_loop:\n\tadd\tebx,eax\n\tmov\teax,[color]\n\n??h_midloop:\n\tmov\t[ebx],al\n\tdec\tecx\t\t\t\t; dec counter\n\tjl\t??out\t\t\t\t; end of line\n\tadd\tebx,esi\n\tsub     [accum],edx\t\t\t; sub the lesser\n\tjge\t??h_midloop\n\tadd\t[accum],edi\t\t\t; add greater for new accum\n\tadd\tebx,[bpr]\t\t\t; goto next line\n\tjmp\t??h_midloop\n\n\t;*==================================================================\n\t;* Special case routine for horizontal line draws\n\t;*==================================================================\n??hline:\n\tcmp\teax,ecx\t\t\t; make eax < ecx\n\tjl\tshort ??hl_ac\n\txchg\teax,ecx\n\n??hl_ac:\n\tsub\tecx,eax\t\t\t; get len\n\tinc\tecx\n\n\tpush\tedx\n\tpush\teax\n\tmov\teax,[bpr]\n\tmul\tebx\n\tmov\tebx,eax\n\tmov\teax,[this_object]\n\tadd\tebx,[(GraphicViewPort eax).GVPOffset]\n\tpop\teax\n\tpop\tedx\n\tadd\tebx,eax\n\tmov\tedi,ebx\n\tcmp\tecx,15\n\tjg\t??big_line\n\tmov\tal,[byte color]\n\trep\tstosb\t\t\t; write as many words as possible\n\tjmp\tshort ??out\t\t; get outt\n\n\n??big_line:\n\tmov\tal,[byte color]\n\tmov\tah,al\n\tmov     ebx,eax\n\tshl\teax,16\n\tmov\tax,bx\n\ttest\tedi,3\n\tjz\t??aligned\n\tmov\t[edi],al\n\tinc\tedi\n\tdec\tecx\n\ttest\tedi,3\n\tjz\t??aligned\n\tmov\t[edi],al\n\tinc\tedi\n\tdec\tecx\n\ttest\tedi,3\n\tjz\t??aligned\n\tmov\t[edi],al\n\tinc\tedi\n\tdec\tecx\n\n??aligned:\n\tmov\tebx,ecx\n\tshr\tecx,2\n\trep\tstosd\n\tmov\tecx,ebx\n\tand\tecx,3\n\trep\tstosb\n\tjmp\t??out\n\n\n\t;*==================================================================\n\t;* a special case routine for vertical line draws\n\t;*==================================================================\n??vline:\n\tmov\tecx,edx\t\t\t; get length of line to draw\n\tinc\tecx\n\tadd\tebx,eax\n\tmov\teax,[color]\n\n??vl_loop:\n\tmov\t[ebx],al\t\t; store bit\n\tadd\tebx,[bpr]\n\tdec\tecx\n\tjnz\t??vl_loop\n\n??out:\n\tret\n\tENDP\tBuffer_Draw_Line\n\n\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DRAWRECT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : DRAWRECT.C                               *\n *                                                                         *\n *                   Programmer : Christopher Yates                        *\n *                                                                         *\n *                  Last Update : August 20, 1993   [JLB]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Draw_Rect -- Draws a rectangle to the LogicPage.                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"gbuffer.h\"\n\n/***************************************************************************\n * Draw_Rect -- Draws a rectangle to the LogicPage.                        *\n *                                                                         *\n *    This routine will draw a rectangle to the LogicPage.  The rectangle  *\n *    doesn't have to be aligned on the vertical or horizontal axis.  In   *\n *    fact, it doesn't even have to be a rectangle.  The \"square\" can be   *\n *    skewed.                                                              *\n *                                                                         *\n * INPUT:   x1_pixel, y1_pixel   -- One corner.                            *\n *                                                                         *\n *          x2_pixel, y2_pixel   -- The other corner.                      *\n *                                                                         *\n *          color                -- The color to draw the lines.           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   None, but the rectangle will be clipped to the current      *\n *             draw line clipping rectangle.                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/20/1993 JLB : Created.                                             *\n *=========================================================================*/\nVOID GraphicViewPortClass::Draw_Rect(int x1_pixel, int y1_pixel, int x2_pixel, int y2_pixel, unsigned char color)\n{\n\tLock();\n\tDraw_Line(x1_pixel, y1_pixel, x2_pixel, y1_pixel, color);\n\tDraw_Line(x1_pixel, y2_pixel, x2_pixel, y2_pixel, color);\n\tDraw_Line(x1_pixel, y1_pixel, x1_pixel, y2_pixel, color);\n\tDraw_Line(x2_pixel, y1_pixel, x2_pixel, y2_pixel, color);\n\tUnlock();\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DRAWSHP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : WWLIB32                                  *\n;*                                                                         *\n;*                    File Name : DRAWSHP.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : April 13, 1992                           *\n;*                                                                         *\n;*                  Last Update : September 14, 1994   [IML]               *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Draw_Shape -- Draws a shape at given buffer coordinates and clips     *\n;*   Not_Supported -- Replacement function for Draw_Shape routines not used*\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n; this struct is here to remove the hardwire way of programing\n; implemented in the funtion Draw_Shape in ian image of \n\nSTRUC\tVVPC_IMAGE\n   \t\tOff  \tdd  ?  \n\t\tWidth  \tdd  ?  \n\t\tHeight  dd  ?  \n  \t\tPage    dd  ?  \nENDS\n\n\n\nSTRUC GVPC_IMAGE \n\t\t vvpc\t\tVVPC_IMAGE\t<>\n\t\t Xpos\t\tdd\t   \t?\n\t\t Ypos\t\tdd\t   \t?\n\t\t GraphicBuff\tdd\t   \t?\nENDS\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;****************************** Declarations ********************************\nGLOBAL\t Draw_Shape:NEAR\nGLOBAL\t LCW_Uncompress:NEAR\nGLOBAL\t_ShapeBuffer:DWORD\nGLOBAL\t_ShapeBufferSize:DWORD\n\nGLOBAL\tMaskPage\t       : dword\nGLOBAL\tBackGroundPage\t       : dword\n\n\n;********************************* Data ************************************\n\tDATASEG\n;---------------------------------------------------------------------------\n; Shape buffer & its size, set by Set_Shape_Buffer()\n;---------------------------------------------------------------------------\n_ShapeBuffer\t\tDD\t0\n_ShapeBufferSize\tDD\t0\n\n;---------------------------------------------------------------------------\n; Address of MaskPage & BackGroundPage, set by Init_Priority_System()\n;---------------------------------------------------------------------------\nMaskPage\t\tDD\t0\nBackGroundPage\t\tDD\t0\n\n;---------------------------------------------------------------------------\n; Predator effect variables \n;---------------------------------------------------------------------------\nPredCount\tDD\t0\nPredTable\tDB\t1, 3, 2, 5, 4, 3, 2, 1\nPredValue\tDD\t1\nPartialPred\tDD\t0\t; partially faded predator effect value\nPartialCount\tDD\t0\n\n;---------------------------------------------------------------------------\n; 32 bit versions of 16 bit stack variables\n;---------------------------------------------------------------------------\nFlags\t\tDD\t?\t; globally accessible copy of flags\n\nviewport_ptr\tDD\t?\t; pointer to upper-left corner of viewport \nviewport_width\tDD\t?\t; viewport width\nviewport_height DD\t?\t; viewport height\nviewport_yadd\tDD\t?\t; viewport y add\nviewport_x\tDD\t?\t; viewport x-coord\nviewport_y\tDD\t?\t; viewport y-coord\nbuff_ptr\tDD\t?\t; pointer to buffer containing viewport\n\n;********************************* Code ************************************\n\tCODESEG\n\n\n;***************************************************************************\n;* Draw_Shape -- Draws a shape at given buffer coordinates and clips       *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*  DWORD\tgvp_ptr\t\t; pointer to graphic viewport info\t   *\n;*  DWORD\tshape_ptr\t; the shape pointer to draw\t\t   *\n;*  DWORD\tdraw_x\t\t; x-coord of hotspot in viewport\t   *\n;*  DWORD\tdraw_y\t\t; y-coord of hotspot in viewport\t   *\n;*  DWORD\tflags\t\t; the flags for drawing the shape\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* Optional Arguments: If the following flags are used, the given args\t   *\n;* MUST be present.  Note that, if more than one one set of args is used,  *\n;* they must appear in this order (alphabetical).\t\t\t   *\n;*  SHAPE_COLOR:\tDWORD color_table (256 bytes)\t\t\t   *\n;*  SHAPE_FADING:\tDWORD fade_table (256 bytes), DWORD fade_count\t   *\n;*  SHAPE_GHOST:\tDWORD is_translucent tbl, DWORD translucent tbl    *\n;*  SHAPE_PARTIAL:\tDWORD predator partial_value (0-255)\t\t   *\n;*  SHAPE_PRIORITY:\tDWORD priority_level\t\t\t\t   *\n;*  SHAPE_SCALING:\tDWORD x_scale, WORD y_scale\t\t\t   *\n;*  SHAPE_SHADOW:\tDWORD shadowing_table (256 bytes)\t\t   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*  none.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:\t\t\t\t\t\t\t\t   *\n;*  none.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;*\t\t\t\t\t\t\t\t\t   *\n;* File Organization:\t\t\t\t\t\t\t   *\n;* drawshp.asm : this file\t\t\t\t\t\t   *\n;* shape.inc   : main shape header file; contains declarations for all\t   *\n;* \t\t  globals, procedures and constants\t\t\t   *\n;* ds_table.asm: contains the procedure address tables for LSkipRout,\t   *\n;*\t\t  RSkipRout, DrawRout, & PixelRout\t\t\t   *\n;* ds_l*.asm   : left-skip routines\t\t\t\t\t   *\n;* ds_r*.asm   : right-skip routines\t\t\t\t\t   *\n;* ds_d*.asm   : drawing routines\t\t\t\t\t   *\n;* \t\t\t\t\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* Shape format:\t\t\t\t\t\t\t   *\n;* Header:\t\t\t\t\t\t\t\t   *\n;*   UWORD  SType (0=normal, 1=16-color, 2=uncompressed, 4=variable-color) *\n;*   UBYTE  Height\t\t\t\t\t\t\t   *\n;*   UWORD  Width\t\t\t\t\t\t\t   *\n;*   UBYTE  unmodified height\t\t\t\t\t\t   *\n;*   UWORD  size of shape in memory, including this header\t\t   *\n;*   UWORD  uncompressed data size\t\t\t\t\t   *\n;* Normal Shape:\t\t\t\t\t\t\t   *\n;*   UBYTE  [compressed] Shape data\t\t\t\t\t   *\n;* 16-color shape:\t\t\t\t\t\t\t   *\n;*   UBYTE  16-color table\t\t\t\t\t\t   *\n;*   UBYTE  [compressed] Shape data\t\t\t\t\t   *\n;* variable-color shape:\t\t\t\t\t\t   *\n;*   UBYTE  # colors\t\t\t\t\t\t\t   *\n;*   UBYTE  color table (variable-length)\t\t\t\t   *\n;*   UBYTE  [compressed] Shape data\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* Uncompressed shape data format:\t\t\t\t\t   *\n;* Data is stored as a bitmap, with 0's treated as a special case.  Every  *\n;* 0 byte is followed by a repetition count byte.  Every scan line is\t   *\n;* compressed separately.  Thus, the following bitmap results in the\t   *\n;* following shape data:\t\t\t\t\t\t   *\n;*\t0 0 0 5 6 7 0 0 0 0\t\t\t\t\t\t   *\n;*\t0 0 0 5 6 7 0 0 0 0\t\t\t\t\t\t   *\n;*\t0 0 0 5 6 7 0 0 0 0\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\t0 3 5 6 7 0 4\t\t\t\t\t\t\t   *\n;*\t0 3 5 6 7 0 4\t\t\t\t\t\t\t   *\n;*\t0 3 5 6 7 0 4\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* How scaling is handled:\t\t\t\t\t\t   *\n;*  Scaling is done by accumulating the x & y scale values.  When the high *\n;*  byte of the accumulated value is set, the pixel (for x-scaling) or\t   *\n;*  the line (for y-scaling) is drawn.  The high byte is then cleared,\t   *\n;*  and the low byte is left so roundoffs continue to accumulate.\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* Drawing Procedures:\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\n;*                                                                         *\n;*  RSkipRout: skips given # bytes of data on the right-hand side of a\t   *\n;*  shape.  Just has to handle changing the current byte offset in the \t   *\n;*  shape data buffer, since the draw routine knows where the left-hand\t   *\n;*  side of the drawable region is.  The routine may skip more bytes than  *\n;*  it was told if it encounters a run of 0's, but it's assumed that a\t   *\n;*  run of 0's will never go past the right edge of a shape.\t\t   *\n;*    Input:\t\t\t\t\t\t\t\t   *\n;*\t\tECX - number of uncompressed bytes to skip\t\t   *\n;*\t\tESI - shape buffer data address\t\t\t\t   *\n;*    Output:\t\t\t\t\t\t\t\t   *\n;* \t\tECX - negative # bytes overrun, or 0\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\n;*                                                                         *\n;*  LSkipRout: skips given # bytes of data on the left-hand side of a\t   *\n;*  shape.  This routine must update the shape data byte offset, and it\t   *\n;*  must properly update the current drawing position due to scaling, so   *\n;*  it's a little more involved than the RSkip routine.  The routine may   *\n;*  skip more bytes than it's told if it encounters a run of 0's.  If this *\n;*  happens, the draw routine must take these extra bytes into \t\t   *\n;*  consideration.\t\t\t\t\t\t\t   *\n;*    Input:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape (source) buffer data address\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = shape's width in bytes\t\t\t   *\n;*    Output:\t\t\t\t\t\t\t\t   *\n;* \t\tECX - negative # pixels (not bytes) overrun, or 0\t   *\n;*\t\tEDX - accumulated XTotal value at new pixel location\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) overrun\t\t   *\n;*\t\t[WidthCount] - decremented by # bytes skipped\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\n;*\t\t\t\t\t\t\t\t\t   *\n;*  DrawRout: draws one row of pixels, handles scaling, reversal and \t   *\n;*\t      any per pixel effects like predator, shadow etc.\t\t   *\n;*  EDX must be set up as follows:\t\t\t\t\t   *\n;*  - No scaling: 0\t\t\t\t\t\t\t   *\n;*  - No left-clipping: 0\t\t\t\t\t\t   *\n;*  - Left clipping, but no overrun: set to computed initial value for\t   *\n;*    that viewport coordinate\t\t\t\t\t\t   *\n;*  - Left clipping, with overrun: set to XTotal value for that coordinate *\n;*  In any case, only the low byte of DL should contain data; the current  *\n;*  byte in the shapebuffer should always be the first drawable pixel,\t   *\n;*  even if it's partially clipped (in which case DL will contain data).   *\n;*    Input:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of pixels (not bytes) to draw\t\t   *\n;*\t\tEDX = XTotal initializer value\t\t\t\t   *\n;*\t\tESI = shape (source) buffer address\t\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = remaining bytes on the line\t\t   *\n;*    Output:\t\t\t\t\t\t\t\t   *\n;*\t\tESI - updated to current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) drawn/skipped\t   *\n;*\t\t[WidthCount] - decremented by # bytes (not pixels) drawn   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* Algorithm:\t\t\t\t\t\t\t\t   *\n;* - Initialize globals\t\t\t\t\t\t\t   *\n;* - Pull optional arguments off the stack\t\t\t\t   *\n;* - Set up drawing procedure pointers based on drawing flags\t\t   *\n;* - Read the values from the shape header\t\t\t\t   *\n;* - Compute the shape's scaled width & height\t\t\t\t   *\n;* - Adjust the shape's drawing coordinates based on centering & \t   *\n;*   viewport-relative flag settings\t\t\t\t\t   *\n;* - Compute the clipped areas of the shape\t\t\t\t   *\n;* - Compute the number of drawn pixels horizontally & vertically\t   *\n;* - Compute the starting drawing offset in the viewport\t\t   *\n;* - Draw the shape\t\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/13/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   05/26/1994 BR  : Converted to 32-bit, restructured quite a bit.\t   *\n;*   08/09/1994 IML : Added C++ style interface. Various optimizations.\t   *\t\n;*   09/06/1994 IML : Ammendments for integration of p_* and ds_* routines.*\n;*   09/14/1994 IML : Now handles LCW compression.\t\t\t   *\t\t\n;*=========================================================================*\nPROC\tDraw_Shape C NEAR \t\n\tUSES eax,ebx,ecx,edx,edi,esi\n\n\t;--------------------------------------------------------------------\n\t; Arguments:\n\t;--------------------------------------------------------------------\n\tARG\tgvp_ptr:DWORD\t\t; pointer to graphic viewport info\n\tARG\tshape_ptr:DWORD\t\t; the shape pointer to draw\n\tARG\tdraw_x:DWORD\t\t; the destination x pixel\n\tARG\tdraw_y:DWORD\t\t; the destination y pixel\n\tARG\tflags:DWORD\t\t; the flags for drawing the shape\n\nIF FALSE\n\t;--------------------------------------------------------------------\n\t; Define the local stack variables that Draw_Shape needs. These \n\t; parameters are defined in shape.inc.  They're included here \n\t; just for reference.\n\t;--------------------------------------------------------------------\n\t;\n\t;...................... proc addresses ..............................\n\t;\n\tLOCAL\tLSkipRout:DWORD\t\t; pointer to the skip routine\n\tLOCAL\tRSkipRout:DWORD\t\t; pointer to the skip routine\n\tLOCAL\tDrawRout:DWORD\t\t; pointer to the draw routine\n\t;\n\t;.................... optional arguments ............................\n\t;\n\tLOCAL\tColorTable:DWORD\t; ptr to the shapes color table\n\tLOCAL\tFadingTable:DWORD\t; extracted fading table pointer\n\tLOCAL\tFadingNum:DWORD\t\t; get the number of times to fade\n\tLOCAL\tIsTranslucent:DWORD\t; ptr to \"are we translucent?\" tbl\n\tLOCAL\tTranslucent:DWORD\t; ptr to \"ok we are translucent!\" tbl\n\tLOCAL\tPriLevel:BYTE\t\t; the priority level of the object\n\tLOCAL\tScaleX:DWORD\t\t; the x increment to scale by\n\tLOCAL\tScaleY:DWORD\t\t; the y increment to scale by\n\tLOCAL\tShadowingTable:DWORD\t; ptr to the shadowing table\n\t;\n\t;.................... Shape header values ...........................\n\t;\n\tLOCAL\tShapeType:DWORD\t\t; shape type\n\tLOCAL\tShapeWidth:DWORD\t; shape's unscaled width\n\tLOCAL\tShapeHeight:DWORD\t; shape's unscaled height\n\tLOCAL\tUncompDataLen:DWORD\t; uncompressed data length\n\tLOCAL\tShapeData:DWORD\t\t; pointer to [compressed] shape data\n\t;\n\t;.................. Scaled shape dimensions .........................\n\t;\n\tLOCAL\tScaledWidth:DWORD\t; shape's scaled width\n\tLOCAL\tScaledHeight:DWORD\t; shape's scaled height\n\t;\n\t;.................. Pixel clipping variables ........................\n\t;\n\tLOCAL\tLeftClipPixels:DWORD\t; # left-clipped pixels\n\tLOCAL\tRightClipPixels:DWORD\t; # right-clipped pixels\n\tLOCAL\tTopClipPixels:DWORD\t; # top-clipped pixels\n\tLOCAL\tBotClipPixels:DWORD\t; # bottom-clipped pixels\n\tLOCAL\tPixelWidth:DWORD\t; width of drawable area in pixels\n\tLOCAL\tPixelHeight:DWORD\t; height of drawable area in pixels\n\t;\n\t;..................... Drawing variables ............................\n\t;\n\tLOCAL\tNumColors:DWORD\t\t; # colors for 16-color shapes\n\tLOCAL\tStartDraw:DWORD\t\t; ptr to starting draw position\n\tLOCAL\tNextLine:DWORD\t\t; offset of next drawing line\n\tLOCAL\tLeftClipBytes:DWORD\t; # left-clipped bytes\n\tLOCAL\tXTotal:DWORD\t\t; accumulated x-pixels for scaling\n\tLOCAL\tXTotalInit:DWORD\t; initial roundoff bits for XTotal\n\tLOCAL\tYTotal:DWORD\t\t; accumulated y-pixels for scaling\n\tLOCAL\tHeightCount:DWORD\t; height counter for drawing lines\n\tLOCAL\tLineStart:DWORD\t\t; address of start of line\n\tLOCAL\tWidthCount:DWORD\t; counts down # bytes skipped\n\tLOCAL\tStashReg:DWORD\t\t; temp variable for draw routines\n\tLOCAL\tMaskAdjust:DWORD\t; priority buffer offset\n\tLOCAL\tBackAdjust:DWORD\t; background buffer offset\n\tLOCAL\tStashECX:DWORD\t\t; temp variable for ECX register\n\tLOCAL\tStashEDX:DWORD\t\t; temp variable for EDX register\n\nENDIF\n\n\t;====================================================================\n\t; Initialization:\n\t; - allocate space for globals\n\t; - validate shape pointer\n\t; - set SHAPE_COMPACT flag if needed\n\t;====================================================================\n\t;--------------------------------------------------------------------\n\t; Allocate stack space for our local variables.\n\t;--------------------------------------------------------------------\n\tLOCAL\tLocal_Stack:BYTE:Local_Size\n\n\t;--------------------------------------------------------------------\n\t; Make sure the shape pointer is not NULL\n\t;--------------------------------------------------------------------\n\tcmp\t[shape_ptr],0\t\t\t; compare shape ptr value to NULL\n\tjnz\t??valid_shp\t\t\t; if non-zero, it's valid\n\tjmp\t??exit\t\t\t\t; otherwise get the heck outta here\n\n\t;--------------------------------------------------------------------\n\t; Move gvp info into local variables\n\t;--------------------------------------------------------------------\n??valid_shp:\n\tmov\tedi,[gvp_ptr]\t\t\t\t\t; get pointer to graphic viewport info\n\tmov\tesi, [(type GVPC_IMAGE  ptr edi). vvpc . Off ] ; extract viewport pointer\n\tmov\t[viewport_ptr],esi\n\tmov\tebx,[(type GVPC_IMAGE ptr edi) . vvpc . Width ]\t; extract viewport width\n\tmov\t[viewport_width],ebx\t\t\t\n\tmov\teax,[(type GVPC_IMAGE ptr edi) . vvpc . Height ]\t; extract viewport height\n\tmov\t[viewport_height],eax\t\t\t\t\n\tmov\tecx,[(type GVPC_IMAGE ptr edi) . vvpc . Page ]\t; calculate y add value\n\tadd\tecx,ebx\n\tmov\t[viewport_yadd],ecx\n\tmov\teax,[(type GVPC_IMAGE ptr edi) . Xpos ]\t\t; extract viewport x-coord\n\tmov\t[viewport_x],eax\n\tmov\teax, [(type GVPC_IMAGE ptr edi) . Ypos ]\t; extract viewport y-coord\n\tmov\t[viewport_y],eax\n\tmul\tecx\t\t\t\t; calculate buffer pointer\n\tadd\teax,[viewport_x]\n\tsub\tesi,eax\n\tmov\t[buff_ptr],esi\n\n\n\t;--------------------------------------------------------------------\n\t; If this shape is a compact shape, set that bit in the flags arg\n\t;--------------------------------------------------------------------\n\tmov\tedi,[shape_ptr]\t\t\t; check for compact shape flag\n\ttest\t[BYTE PTR edi],MAKESHAPE_COMPACT\t \n\t\t\t\t\t\t\t\n\tjz\t??do_args\t\t\t; if not process flags as is\n\tor\t[flags],SHAPE_COMPACT\t\t; mark it as a compact shape\n\n\t;====================================================================\n\t; Pull off optional arguments:\n\t; EDI is used as an offset from the 'flags' parameter, to point\n\t; to the optional argument currently being processed.\n\t;====================================================================\n??do_args:\n\tmov\tedi,4\t \t\t\t; optional params start past flags\n\n\t;--------------------------------------------------------------------\n\t; Initialize optional argument values:\n\t;--------------------------------------------------------------------\n\tmov\t[ColorTable],0\t\t\t; default = NULL\n\tmov\t[FadingTable],0\t\t\t; default = NULL\n\tmov\t[FadingNum],0\t\t\t; default = no fading\n\tmov\t[IsTranslucent],0\t\t; default = NULL\n\tmov\t[Translucent],0\t\t\t; default = NULL\n\tmov\t[PriLevel],0\t\t\t; default = no priority\n\tmov\t[ScaleX],100h\t\t\t; default = unity X scaling\n\tmov\t[ScaleY],100h\t\t\t; default = unity Y scaling\n\tmov\t[ShadowingTable],0\t\t; default = NULL\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_COLOR: DWORD color_table[256]\n\t;--------------------------------------------------------------------\n??color:\n\ttest\t[flags],SHAPE_COLOR \t\t; does it have a color table\n\tjz\t??fading \t\t\t; if not skip to fading \n\tor\t[flags],SHAPE_COMPACT\t\t; mark it as a compact shape\n\t\t\t\t\t\t;  (for remapping purposes only)\n\tmov\teax,[flags + edi]\n\tmov\t[ColorTable],eax\t\t; save address of color table\n\tadd\tedi,4\t\t\t\t; point to next optional argument\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_FADING: DWORD fade_table[256], DWORD fade_count\n\t;--------------------------------------------------------------------\n??fading:\n\ttest\t[flags],SHAPE_FADING\t\t; are we fading this shape\n\tjz\t??ghost\t\t\t\t; skip to ghosting check\n\tmov\teax,[flags + edi]\n\tmov\t[FadingTable],eax\t\t; save address of fading tbl\n\n\tmov\teax,[flags + edi + 4]\t\t; get fade num\n\n\tadd\tedi,8\t\t\t\t; next argument\n\tcmp\teax,0\t\t\t\t; check if it's 0\n\tjnz\t??set_fading\t\t\t; if not, store fade num\n\tand\t[flags],NOT SHAPE_FADING\t; otherwise, don't fade\n\n??set_fading:\n\tmov\t[FadingNum],eax\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_GHOST: DWORD is_translucent tbl, DWORD translucent tbl\n\t;--------------------------------------------------------------------\n??ghost:\n\ttest\t[flags],SHAPE_GHOST\t\t; are we ghosting this shape\n\tjz\t??init_predator\t\t\t; skip to predator check\n\tmov\teax,[flags + edi]\n\tmov\t[IsTranslucent],eax\t\t; save ptr to is_trans. tbl\n\tmov\teax,[flags + edi + 4]\n\tmov\t[Translucent],eax\t\t; save ptr to translucent tbl\n\tadd\tedi,8\t\t\t\t; next argument\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_PREDATOR: Initialize the predator effect variables\n\t;--------------------------------------------------------------------\n??init_predator:\n\ttest\t[flags],SHAPE_PREDATOR\t\t; is predator effect on\n\tjz\t??partial\t\t\t; if not skip to partial \n\tinc\t[PredCount]\t\t\t; the pred table is byte aligned\n\tand\t[PredCount],PRED_MASK\t\t; keep entries within bounds\n\tmov\teax,[PredCount]\t\t \n\tmov\tal,[BYTE PTR PredTable + eax]\n\tmov\t[PredValue],eax\t\t\t; put the pred value cs\n\tmov\t[PartialCount],0\t\t; clear the partial count\n\tmov\t[PartialPred],100h\t\t; init partial to off\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_PARTIAL: DWORD partial_pred_value (0-255)\n\t;--------------------------------------------------------------------\n??partial:\n\ttest\t[flags],SHAPE_PARTIAL\t\t; is this a partial pred?\n\tjz\t??priority\t\t\t; if not check priority\n\tmov\teax,[flags + edi]\t\t; pull the partial value\n\tmov\t[PartialPred],eax\t\t; store it off\n\tadd\tedi,4\t\t\t\t; next argument\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_PRIORITY: DWORD priority_level\n\t;--------------------------------------------------------------------\n??priority:\n\ttest\t[flags],SHAPE_PRIORITY\t\t; is this a priority draw\n\tjz\t??scale\t\t\t\t; if not skip to scale\n\tmov\teax,[flags + edi]\n\tmov\t[PriLevel],al\t\t\t; store priority level\n\tadd\tedi,4\t\t\t\t; next argument\n\tmov\teax,[MaskPage]\t\t\t; calculate priority buffer\n\tsub\teax,[buff_ptr]\t\t\t;  offset\n\tmov\t[MaskAdjust],eax\n\tmov\teax,[BackGroundPage]\t\t; calculate background buffer\n\tsub\teax,[buff_ptr]\t\t\t;  offset\n\tmov\t[BackAdjust],eax\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_SCALING: DWORD x_scale, WORD y_scale\n\t;--------------------------------------------------------------------\n??scale:\n\ttest\t[flags],SHAPE_SCALING\t\t; are we scaling this shape.\n\tjz\t??shadow\t\t\t; if not then skip scale y value\n\tmov\teax,[flags + edi]\t\n\tmov\t[ScaleX],eax\n\tmov\teax,[flags + edi + 4]\t\n\tmov\t[ScaleY],eax\n\tadd\tedi,8\t\t\t\t; next argument\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_SHADOW: DWORD shadow_table[256]\n\t;--------------------------------------------------------------------\n??shadow:\n\ttest\t[flags],SHAPE_SHADOW\t\t; are we ghosting this shape\n\tjz\tshort ??get_header\t\t; if not then skip\n\tmov\teax,[flags + edi]\n\tmov\t[ShadowingTable],eax\t\t; save address of shadow table \n\tadd\tedi,4\t\t\t\t; next argument\n\n\n??get_header:\t\n\t;====================================================================\n\t; Get Shape header values\n\t;====================================================================\n\tmov\tesi,[shape_ptr]\t\t\t; prepare to read header\n\tmovzx\teax,[WORD PTR esi]\n\tmov\t[ShapeType],eax\t\t\t; extract shape type\n\tmovzx\teax,[BYTE PTR esi + 2]\n\tmov\t[ShapeHeight],eax\n\tmovzx\teax,[WORD PTR esi + 3]\t\t; extract shape height\n\tmov\t[ShapeWidth],eax\n\tmovzx\teax,[WORD PTR esi + 8]\t\t; extract uncompressed data length\n\tmov\t[UncompDataLen],eax\n\tadd\tesi,10\t\t\t\t; reposition index\n\n\t;--------------------------------------------------------------------\n\t; Now get NumColors, ColorTable address, & data pointer:\n\t; <16-color shape:\n\t;   shape.Colortable[0] = # colors\n\t;   shape data is after that many colors\n\t; 16-color shape:\n\t;   shape.Colortable[] contains colors\n\t;   shape data is after those colors\n\t; default 256-color shape:\n\t;   shape data starts at shape.Colortable[0]\n\t; Note: ColorTable is set only if flags & SHAPE_COLOR is 0; otherwise,\n\t;   the color table was passed in & we already have a pointer to it\n\t;--------------------------------------------------------------------\n\t;\n\t;....................... <16-color shape: ...........................\n\t;\n\ttest\t[ShapeType],MAKESHAPE_VARIABLE\n\tjz\t??check_16\n\tmovzx\teax,[BYTE PTR esi]\t\t; read # colors\n\tmov\t[NumColors],eax\t\t\t; save # colors\n\tinc\tesi\n\ttest\t[flags],SHAPE_COLOR\t\t; don't set ColorTable if\n\tjnz\t??norm_get_data_addr\t\t;  it was passed in\n\tmov\t[ColorTable],esi\t\t; save color table pointer\n\n??norm_get_data_addr:\n\tadd\tesi,[NumColors]\t\t\t; skip past color data\n\tmov\t[ShapeData],esi\t\t\t; set data address\n\tjmp\t??setup_procs\n\n\t;....................... 16-color shape: ............................\n??check_16:\n\ttest\t[ShapeType],MAKESHAPE_COMPACT\n\tjz\t??256_get_data_addr\n\tmov\t[NumColors],16\t\t\t; save # colors\n\ttest\t[flags],SHAPE_COLOR\t\t; don't set ColorTable if\n\tjnz\t??16_get_data_addr\t\t;  it was passed in\n\tmov\t[ColorTable],esi\t\t; save color table pointer\n\n??16_get_data_addr:\n\tadd\tesi,[NumColors]\t\t\t; skip past color data\n\tmov\t[ShapeData],esi\t\t\t; set data address\n\tjmp\t??setup_procs\n\t;\n\t;....................... 256-color shape: ...........................\n\t;\n??256_get_data_addr:\n\tmov\t[ShapeData],esi\t\t\t; set data address\n\n\t;====================================================================\n\t; Set up the drawing procedure addresses\n\t;====================================================================\n\t;--------------------------------------------------------------------\n\t; This code uses HORZ_REV, VERT_REV, & SCALING flags as an \n\t; offset into the LSkipTable, RSkipTable, and DrawTable.  These\n\t; flags combined have values from 00h-07h, so each table must have\n\t; at least 8 entries.\n\t;--------------------------------------------------------------------\n??setup_procs:\n\tmov\tebx,[flags]\t\t; load flags value\n\tand\tebx,07h\t\t\t; clip high bits\n\tadd\tebx,ebx\t\t\t; mult by 4 to get DWORD offset\n\tadd\tebx,ebx\n\tmov\teax,[LSkipTable + ebx]\t; get table value\n\tmov\t[LSkipRout],eax\t\t; store it in the function pointer\n\tmov\teax,[RSkipTable + ebx]\t; get table value\n\tmov\t[RSkipRout],eax\t\t; store it in the function pointer\n\tmov\teax,[DrawTable + ebx]\t; get table value\n\tmov\t[DrawRout],eax\t\t; store it in the function pointer\n\n??compute_scalevals:\n\t;====================================================================\n\t; Now compute scaled width & height.  If the shape scales down to 0 \n\t; either horizontally or vertically, exit.\n\t;====================================================================\n\ttest\t[flags],SHAPE_SCALING\t; skip if no scaling\n\tjz\t??no_scaling\n\t;\n\t;........................ scaled width: .............................\n\t;\n\tmov\teax,[ShapeWidth]\t; get byte width\n\tmov\tebx,[ScaleX]\t\t; prepare for register mul\n\tmul\tebx\t\t\t; EDX:EAX = result\n\tshrd\teax,edx,8\t\t; EAX = result rounded down\n\tor\teax,eax\n\tjz\t??exit\t\t\t; exit if EAX is 0\n\tmov\t[ScaledWidth],eax\t; save the scaled width\n\t;\n\t;........................ scaled height: ............................\n\t;\n\tmov\teax,[ShapeHeight]\t; get byte height\n\tmov\tebx,[ScaleY]\t\t; prepare for register mul\n\tmul\tebx\t\t\t; EDX:EAX = result\n\tshrd\teax,edx,8\t\t; EAX = result rounded down\n\tor\teax,eax\n\tjz\t??exit\t\t\t; exit if EAX is 0\n\tmov\t[ScaledHeight],eax\t; save the scaled height\n\tjmp\t??handle_centering\n\t;\n\t;......................... no scaling: ..............................\n\t;\n??no_scaling:\n\tmov\teax,[ShapeWidth]\n\tmov\t[ScaledWidth],eax\t; pixel width = byte width\n\tmov\teax,[ShapeHeight]\n\tmov\t[ScaledHeight],eax\t; pixel height = byte height\n\n\t;====================================================================\n\t; Allow for SHAPE_CENTER by adjusting the draw_x & draw_y arguments:\n\t; draw_x -= ScaledWidth / 2\n\t; draw_y -= ScaledHeight / 2\n\t;====================================================================\n??handle_centering:\n\t;\n\t;........................ adjust draw_x .............................\n\t;\n\ttest\t[flags],SHAPE_CENTER\t; skip if not centered\n\tjz\t??handle_vp_rel\n\tmov\teax,[draw_x]\t\t; load in draw_x\n\tmov\tedx,[ScaledWidth]\t; load in ScaledWidth\n\tshr\tedx,1\t\t\t; divide it by 2\n\tsub\teax,edx\t\t\t; subract it from eax\n\tmov\t[draw_x],eax\t\t; store it back into draw_x\n\t;\n\t;........................ adjust draw_y .............................\n\t;\n\tmov\teax,[draw_y]\t\t; load in draw_y\n\tmov\tedx,[ScaledHeight]\t; load in ScaledHeight\n\tshr\tedx,1\t\t\t; divide it by 2\n\tsub\teax,edx\t\t\t; subract it from eax\n\tmov\t[draw_y],eax\t\t; store it back into draw_y\n\n\t;====================================================================\n\t; Allow for SHAPE_VIEWPORT_REL by adjusting draw_x & draw_y by the \n\t; viewport's coordinates\n\t;====================================================================\n??handle_vp_rel:\n\ttest\t[flags],SHAPE_VIEWPORT_REL\t; skip if not vp-relative\n\tjz\t??compute_horz_clip\n\tmov\teax,[viewport_x]\n\tadd\t[draw_x],eax\t\t\t; draw_x += viewport_x\n\tmov\teax,[viewport_y]\n\tadd\t[draw_y],eax\t\t\t; draw_y += viewport_y\n\n\t;====================================================================\n\t; Now that we have the scaled size and adjusted x & y drawing\n\t; coordinates, we can compute the clipped areas of the shape:\n\t;   LeftClipPixels =\tviewport_x - draw_x\n\t;\t- if negative, set to 0\n\t;   RightClipPixels =\t(draw_x + ScaledWidth) - \n\t;\t\t\t\t(viewport_x + viewport_width)\n\t;\t- if negative, set to 0\n\t;\n\t;   TopClipPixels =\tviewport_y - draw_y\n\t;\t- if negative, set to 0\n\t;   BotClipPixels =\t(draw_y + ScaledHeight) -\n\t;\t\t\t\t(viewport_y + viewport_height)\n\t;\t- if negative, set to 0\n\t;====================================================================\n??compute_horz_clip:\n\t;\n\t;...................... left-clipped pixels .........................\n\t;\n\tmov\teax,[viewport_x]\n\tsub\teax,[draw_x]\t\t; EAX = viewport_x - draw_x\n\tjge\t??set_left_clip\n\tmov\teax,0\t\t\t; if EAX<0, set to 0\n??set_left_clip:\n\tmov\t[LeftClipPixels],eax\t; store # left-clipped pixels\n\t;\n\t;...................... right-clipped pixels ........................\n\t;\n\tmov\teax,[draw_x]\n\tadd\teax,[ScaledWidth]\t; EAX = draw_x + ScaledWidth\n\tmov\tedx,[viewport_x]\n\tadd\tedx,[viewport_width]\t; EDX = viewport_x + viewport_width\n\tsub\teax,edx\n\tjge\t??set_right_clip\n\tmov\teax,0\t\t\t; if EAX<0, set to 0\n??set_right_clip:\n\tmov\t[RightClipPixels],eax\t; store # right-clipped pixels\n\t;\n\t;...................... top-clipped pixels ..........................\n\t;\n??compute_vert_clip:\n\tmov\teax,[viewport_y]\n\tsub\teax,[draw_y]\t\t; EAX = viewport_y - draw_y\n\tjge\t??set_top_clip\n\tmov\teax,0\t\t\t; if EAX<0, set to 0\n??set_top_clip:\n\tmov\t[TopClipPixels],eax\t; store # top-clipped pixels\n\t;\n\t;.................... bottom-clipped pixels .........................\n\t;\n\tmov\teax,[draw_y]\n\tadd\teax,[ScaledHeight]\t; EAX = draw_y + ScaledHeight\n\tmov\tedx,[viewport_y]\n\tadd\tedx,[viewport_height]\t; EDX = viewport_y + viewport_height\n\tsub\teax,edx\n\tjge\t??set_bottom_clip\n\tmov\teax,0\t\t\t; if EAX<0, set to 0\n??set_bottom_clip:\n\tmov\t[BotClipPixels],eax\t; store # bottom-clipped pixels\n\n\t;====================================================================\n\t; Now compute the number of pixels actually drawn, horizontally and\n\t; vertically; exit if either is <= 0\n\t;====================================================================\n??compute_drawn_pixels:\n\t;\n\t;.................... pixel width of drawn area .....................\n\t;\n\tmov\teax,[ScaledWidth]\t; get total width in pixels\n\tsub\teax,[LeftClipPixels]\t; subtract off left-clipped pixels\n\tsub\teax,[RightClipPixels]\t; subtract off right-clipped pixels\n\tjle\t??exit\t\t\t; exit if no horizontal pixels drawn\n\tmov\t[PixelWidth],eax\t; store drawn pixel width\n\t;\n\t;.................... pixel height of drawn area ....................\n\t;\n\tmov\teax,[ScaledHeight]\t; get total height in pixels\n\tsub\teax,[TopClipPixels]\t; subtract off top-clipped pixels\n\tsub\teax,[BotClipPixels]\t; subtract off bottom-clipped pixels\n\tjle\t??exit\t\t\t; exit if no horizontal pixels drawn\n\tmov\t[PixelHeight],eax\t; store drawn pixel height\n\n\t;====================================================================\n\t; So, we're actually going to draw something; if (ShapeType & \n\t; MAKESHAPE_NOCOMP == 0) decompress the shape data into _ShapeBuffer:\n\t; LCW_Uncompress(ShapeData, _ShapeBuffer, UncompDataLen);\n\t;\tshape.DataLength\n\t;\t&_ShapeBuffer\n\t;\t&(shape's data)\n\t; - otherwise the shape data is already uncompressed\n\t;====================================================================\n\ttest\t[ShapeType],MAKESHAPE_NOCOMP\n\tjnz\t??uncompressed\n\n\tmov\teax,[UncompDataLen]\n\tpush\teax\t\t\t; push arg 3\n\tmov\teax,[_ShapeBuffer]\n\tpush\teax\t\t\t; push arg 2\n\tmov\teax,[ShapeData]\n\tpush\teax\t\t\t; push arg 1\n\tcall\tLCW_Uncompress\t\t; call routine\n\tadd\tesp,12\t\t\t; restore stack\n\tmov\teax,[_ShapeBuffer]\n\tmov\t[ShapeData],eax\n\tjmp\t??copy_flags\n\n??uncompressed:\n;\tmov\teax,[ShapeData]\t\t; set up pointer to shape data\n;\tmov\t[_ShapeBuffer],eax\n\n\n\t;--------------------------------------------------------------------\n\t; Set the global Flags variable\n\t;--------------------------------------------------------------------\n??copy_flags:\n\tmov\teax,[flags]\n\tmov\t[Flags],eax\t\t\n\n\t;====================================================================\n\t; Now compute the actual buffer offset where drawing (not skipping)\n\t; will begin\n\t;====================================================================\n\t;--------------------------------------------------------------------\n\t; First, compute the x & y offsets of the shape's clipped upper-left \n\t; corner,  relative to the viewport's upper-left corner:\n\t; x-offset = draw_x + LeftClipPixels - viewport_x\n\t; y-offset = draw_y + TopClipPixels - viewport_y\n\t;--------------------------------------------------------------------\n\tmov\tebx,[draw_x]\n\tadd\tebx,[LeftClipPixels]\n\tsub\tebx,[viewport_x]\t; EBX = viewport x-offset\n\n\tmov\teax,[draw_y]\n\tadd\teax,[TopClipPixels]\n\tsub\teax,[viewport_y]\t; EAX = viewport y-offset\n\n\t;--------------------------------------------------------------------\n\t; Then, adjust the viewport offsets due to horizontal & vertical\n\t; reversal:\n\t; if HORZ_REV, x-offset += (PixelWidth - 1)\n\t; if VERT_REV, y-offset += (PixelHeight - 1)\n\t;--------------------------------------------------------------------\n\t;\n\t;................. Adjust for horizontal reversal ...................\n\t;\n\ttest\t[flags],SHAPE_HORZ_REV\n\tjz\t??adjust_vert_offset\n\tadd\tebx,[PixelWidth]\n\tdec\tebx\t\t\t; EBX = true x-offset\n\t;\n\t;................ Swap LeftClip & RightClip pixels ..................\n\t;\n\tmov\tedx,[LeftClipPixels]\t; exchange left & right-clipped pixels\n\txchg\tedx,[RightClipPixels]\n\tmov\t[LeftClipPixels],edx\n\n\t;\n\t;.................. Adjust for vertical reversal ....................\n\t;\n??adjust_vert_offset:\n\ttest\t[flags],SHAPE_VERT_REV\n\tjz\t??adjust_pointer\n\tadd\teax,[PixelHeight]\n\tdec\teax\t\t\t; EAX = true y-offset\n\t;\n\t;.................. Swap TopClip & BotClip pixels ...................\n\t;\n\tmov\tedx,[TopClipPixels]\n\txchg\tedx,[BotClipPixels]\n\tmov\t[TopClipPixels],edx\n\n\t;--------------------------------------------------------------------\n\t; Now, adjust the starting position pointer:\n\t;--------------------------------------------------------------------\n??adjust_pointer:\t;!!!!!!! convert to register mul for speed !!!!!!!!\n\tadd\tebx,[viewport_ptr]\t; add initial ptr to x-offset\n\tmul\t[viewport_yadd]\t\t; convert y-offset (EAX) to bytes\n\tadd\tebx,eax\t\t\t; add those bytes in\n\tmov\t[StartDraw],ebx\t\t; store the starting pointer\n\n\t;--------------------------------------------------------------------\n\t; Finally, if VERT_REV, negate yadd to move up not down:\n\t;--------------------------------------------------------------------\n\ttest\t[flags],SHAPE_VERT_REV\n\tjz\t??init_xtotal\n\tneg\t[viewport_yadd]\t\t; move up, not down\n\n\t;====================================================================\n\t; Initialize the horizontal scale accumulation value:\n\t;   If there are any left-clipped pixels, the scale accumulator will\n\t;   have to be initialized with the value it >would< have by stepping\n\t;   over that many pixels.  This initial value can be computed by\n\t;   dividing the # of left-clipped pixels by the x-scale value itself,\n\t;   picking off the remainder from this division & negating it.  This\n\t;   sets the low byte of the remainder to the correct accumulation\n\t;   value (the high bytes will be garbage).\n\t;   (The alternative to this approach would be to multiply the\n\t;   scale factor by the # clipped bytes, which is the result of the\n\t;   division; however, negating the remainder is much faster than\n\t;   the multiply would be.)\n\t;====================================================================\n??init_xtotal:\n\tmov\tedx,0\t\t\t; prepare for divide\n\tmov\teax,[LeftClipPixels]\t; get # left-clipped pixels\n\tshl\teax,8\t\t\t; multiply by 100h\n\tmov\tebx,[ScaleX]\t\t; load ScaleX value\n\tdiv\tbx\t\t\t; 16-bit div: AX = rslt, DX = rem\n\tmov\t[LeftClipBytes],eax\t; save # left-clipped bytes\n\tneg\tedx\t\t\t; generate roundoff bits\n\tand\tedx,0Fh\t\t\t; only save low byte\n\tmov\t[XTotalInit],edx\t; save initial roundoff value\n\n\t;====================================================================\n\t; Initialize drawing variables:\n\t;====================================================================\n\tmov\tesi,[ShapeData]\t\t; ESI = shape buffer starting point\n\tmov\tedi,[StartDraw]\t\t; EDI = drawing address\n\tmov\t[YTotal],0\t\t; initialize accumulated scale\n\n\t;====================================================================\n\t; Clip the top-clipped lines. The object here is to set ESI to the \n\t; first drawable line in the _ShapeBuffer, and YTotal to: \n\t;   high byte = # times to draw that line, \n\t;   low byte = roundoff bits\n\t;\n\t; - Initialize values (ESI, HeightCount, YTotal)\n\t; - Skip loop if no top lines to clip\n\t; - Loop:\n\t;   - save this line's byte position in _ShapeBuffer, in case we\n\t;     overrun\n\t;   - call RSkipRout with ECX set to # bytes to skip (one row)\n\t;   - accumulate ScaleY into YTotal\n\t;   - if high byte is non-zero, there are that many drawn lines:\n\t;     - decrement HeightCount by that many lines\n\t;     - clear the high byte in YTotal, but keep the roundoff bits\n\t;     - if HeightCount > 0, loop again to clip more lines\n\t;     - if HeightCount is 0, start drawing:\n\t;\t- ESI points to first non-clipped line in _ShapeBuffer\n\t;\t- YTotal contains 0 in high byte, roundoff bits in low byte\n\t;     - otherwise, we've clipped too many lines:\n\t;\t- put ESI back to the line we just clipped\n\t;\t- set high byte of YTotal to # lines overrun\n\t;\t- subtract ScaleY from YTotal, to set it up for drawing loop\n\t;====================================================================\n\t;\n\t;..................... skip if nothing to clip ......................\n\t;\n\tmov\teax,[TopClipPixels]\n\tcmp\teax,0\t\t\t; see if any top-clipped pixels\n\tjz\t??draw_loop\t\t; if not, skip this\n\tmov\t[HeightCount],eax\t; save off # lines to clip\n\n??clip_y_loop:\n\t;\n\t;...................... skip this row of bytes ......................\n\t;\n\tmov\t[LineStart],esi\t\t; save this line's byte position\n\tmov\tecx,[ShapeWidth]\t; set up ECX for RSkipRout\n\tcall\t[RSkipRout]\t\t; skip 'ShapeWidth' bytes\n\t;\n\t;............... see if this row would have been drawn ..............\n\t;\n\tmov\teax,[ScaleY]\n\tadd\t[YTotal],eax\t\t; accumulate scale factor\n\ttest\t[YTotal],0FF00h\t\t; check to see if we draw the line\n\tjz\t??clip_y_loop\t\t; if not loop again\n\t;\n\t;...................... decrement HeightCount .......................\n\t;\n\tmov\teax,0\t\t\t; clear EAX\n\txchg\tal,[BYTE PTR YTotal+1]\t; get # lines, clear it in YTotal\n\tsub\t[HeightCount],eax\t; subtract # drawn lines from HtCt\n\tjg\t??clip_y_loop\t\t; if more lines remain, loop again\n\tjns\t??draw_loop\t\t; is exactly 0; we're done clipping\n\t;\n\t;....................... adjust for overrun .........................\n\t;\n\tmov\tesi,[LineStart]\t\t; point ESI back to this line\n\tmov\teax,[HeightCount]\n\tneg\teax\t\t\t; EAX = # lines overrun\n\tshl\teax,8\t\t\t; multiply by 100h\n\tadd\teax,[YTotal]\t\t; add in roundoff bits\n\tsub\teax,[ScaleY]\t\t; adjust down by y-scale\n\tmov\t[YTotal],eax\t\t; store in YTotal\n\n\t;====================================================================\n\t; The drawing loop (at long last!):\n\t; - Accumulate YTotal; if high byte is 0, skip this row of bytes & \n\t;   loop again\n\t; - Skip left-clipped pixels:\n\t;   - If we've skipped all the bytes on the line, just go to the\n\t;     next line\n\t; - Draw middle pixels:\n\t;   - Add the shape's pixel width to ECX (which could be negative \n\t;     if we left-skipped into the drawable area)\n\t;   - If ECX is still 0, there are no pixels to draw\n\t;   - Otherwise, leave ECX as is & draw the pixels\n\t; - Skip right-clipped pixels:\n\t;   - Add # right-clipped pixels to ECX (which could be negative if\n\t;     the draw routine  uncompressed 0's into the right-clipped \n\t;     region)\n\t;   - if ECX > 0, skip the remaining bytes\n\t; - Go to the next line:\n\t;   - point EDI to the start of the next line in the viewport\n\t;   - decrement the height counter, exit if it's 0\n\t;   - decrement YTotal's high byte\n\t;     - if it's 0, go to the loop top\n\t;     - otherwise, reset ESI to this line's start & redraw the line,\n\t;       starting at left-clipped pixels\n\t;       (NOTE: why not start drawing at middle pixels??????????)\n\t;====================================================================\n??draw_loop:\n\t;\n\t;................... accumulate YTotal & test it ....................\n\t;\n\tmov\teax,[ScaleY]\t\t; get y scaling factor\n\tadd\t[YTotal],eax\t\t; accumulate YTotal\n\ttest\t[YTotal],0FF00h\t\t; see if we need to draw anything\n\tjnz  \t??draw_line\t\t; draw this line\n\t;\n\t;......................... skip this line ...........................\n\t;\n\tmov\tecx,[ShapeWidth]\t; load shape's width in bytes\n\tcall\t[RSkipRout]\t\t; skip this row & loop again\n\tjmp\t??draw_loop\n\n\t;\n\t;--------------------- start drawing this line ----------------------\n\t;\n??draw_line:\n\tmov\t[LineStart],esi\t\t; save current byte position\n\t;....................................................................\n\t; Skip left-clipped pixels:\n\t; - initialize [WidthCount] to total shape width in bytes\n\t; - set ECX to # >bytes< to clip\n\t; When LSkipRout returns: \n\t;\t- ECX will contain # >pixels< overrun\n\t;\t- EDX will contain the XTotal init value\n\t;\t- [WidthCount] will be decremented by total bytes skipped\n\t;....................................................................\n??draw_left:\n\tmov\teax,[ShapeWidth]\t; load shape width\n\tmov\t[WidthCount],eax\t; set up for LSkipRout\n\tmov\tecx,[LeftClipBytes]\t; bytes, not pixels!\n\tcall\t[LSkipRout]\t\t; skip the bytes\n\tcmp\t[WidthCount],0\n\tjz\t??next_line\t\t; The whole line was 0's\n\t;....................................................................\n\t; Draw middle pixels:\n\t; - add PixelWidth to ECX (which may be negative)\n\t; - if ECX is 0, don't bother drawing\n\t; When DrawRout returns:\n\t;\t- ECX will contain # >pixels< overrun\n\t;\t- [WidthCount] will be decremented by # bytes drawn\n\t;....................................................................\n??draw_middle:\n\tadd\tecx,[PixelWidth]\t; since ECX could overrun, add width\n\tjle\t??draw_right\t\t; if ECX<=0, no middle pixels to draw\n\tcall\t[DrawRout]\t\t; draw the pixels\n\t;\n\t;................... skip past right-clipped pixels .................\n\t;\n??draw_right:\n\tmov\tecx,[WidthCount]\t; ECX = remaining # bytes\n\tjecxz\t??next_line\t\t; don't bother if no bytes remain\n\tcall\t[RSkipRout]\t\t; skip right-clipped bytes\n\t;\n\t;----------------------- go to the next line ------------------------\n\t;\n??next_line:\n\t;\n\t;................. adjust EDI to start of next line .................\n\t;\n\tmov\teax,[viewport_yadd]\t; get yadd\n\tadd\t[StartDraw],eax\t\t; add it to this line's position\n\tmov\tedi,[StartDraw]\t\t; EDI = next line\n\t;\n\t;................. decrement our pixel row counter ..................\n\t;\n\tdec\t[PixelHeight]\t\t; count down a line\n\tjz\t??exit\t\t\t; we're done!\n\t;\n\t;.................. decrement YTotal's high byte ....................\n\t;\n\tdec\t[BYTE PTR YTotal + 1]\t; decrement high byte\n\tjz\t??draw_loop\t\t; draw next line if 0\n\t;\n\t;....................... re-draw this line ..........................\n\t;\n\tmov\tesi,[LineStart]\t\t; reset to this line's start\n\tjmp\t??draw_left\t\t; redraw this line\n\n??exit:\n\tret\n\n\tENDP\tDraw_Shape\n\n\n;***************************************************************************\n;* Not_Supported -- Replacement function for Draw_Shape routines not used. *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*\tnone.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*\tnone.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*\tnone.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/24/1993 SKB : Created.                                             *\n;*=========================================================================*\nPROC\tNot_Supported NOLANGUAGE NEAR\n\n\tret\n\n\tENDP Not_Supported \n\n\tEND\n\n;************************** End of drawshp.asm *****************************\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DS_DN.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_DN.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : September 6, 1994   [IML]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Draw_Normal -- Draws a normal row of pixels to the viewport           *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Draw_Normal -- Draws a normal row of pixels to the viewport             *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of pixels (not bytes) to draw\t\t   *\n;*\t\tEDX = XTotal initializer value\t\t\t\t   *\n;*\t\tESI = shape (source) buffer address\t\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = remaining bytes on the line\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;*\t\tESI - updated to current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) drawn/skipped\t   *\n;*\t\t[WidthCount] - bytes remaining on the line\t\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR  : Converted to 32-bit.\t\t\t\t   *\n;*   08/09/1994 IML : Optimized for 32-bit.                                *\n;*   09/06/1994 IML : Integrated p_* and ds_* routines.\t\t\t   *\n;*=========================================================================*\nPROC\tDraw_Normal NOLANGUAGE NEAR\n\n\tmov\t[StashEDX],edx\t\t\t; save edx\n\tmov\tedx,[Flags]\n\tmov\teax,0\t\t\t\t; init to zero\n\tsub\t[WidthCount],ecx\t\t; decrement bytes remaining by pixels\n\t\t\t\t\t\t;   to draw\n\t\t\t\t\t\t\n\t;--------------------------------------------------------------------\n\t; Drawing Loop:\n\t; - Get a data byte\n\t; - If it's a 0, handle the run:\n\t;\t- get repetition value\n\t;\t- add it to EDI\n\t;\t- subtract it from [WidthCount]\n\t;\t- subtract it from ECX\n\t;\t- if ECX>0, draw again, else exit\n\t; - Otherwise:\n\t;\t- draw the pixel\n\t;\t- increment EDI to next pixel location\n\t;\t- decrement [WidthCount]\n\t;\t- loop until ECX is 0\n\t;--------------------------------------------------------------------\n\ttest\tedx,SHAPE_EFFECTS\t\t; are any effects flags set?\n\tjnz\tshort ??general_draw_continue\t;   if so use the general purpose loop\n\n\n\t;--------------------------------------------------------------------\n\t; Extra fast draw loop for shapes with no flags set.\n\t;--------------------------------------------------------------------\n??fast_draw_loop:\n\tmov\tal,[esi]\t\t\t; get a byte of the source\n\tinc\tesi\n\tor\teax,eax\t\t\t\t; is the byte a transparent run?\n\tjz\tshort ??fast_is_run\t\t;   if yes then handle the run\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\tinc\tedi\t\t\t\t; point to next viewport pixel\n\tdec\tecx\t\t\t\t; any source pixels left?\n\tjnz\tshort ??fast_draw_loop\t\t;   if not then go home\n\tjmp\t??out\n\n??fast_is_run:\n\tmov\tal,[esi]\n\tinc\tesi\n\tadd\tedi,eax\t\t\t\t; move the viewport pointer\n\tsub\tecx,eax\t\t\t\t; chop down the width to do\n\tjg\tshort ??fast_draw_loop\t\t; while more to do, loop back up\n\tjmp\t??out\n\n\n\t;--------------------------------------------------------------------\n\t; General purpose draw loop for shapes with one or more flags set.\n\t;--------------------------------------------------------------------\n??general_draw_loop:\n\ttest\tedx,SHAPE_FADING\t\t; if fading is enabled test for\n\tjz\tshort ??no_fading_draw_loop\t;   transparency\n\tor\teax,eax\n\tjz\tshort ??is_transparent\n\n??no_fading_draw_loop:\t\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\n??is_transparent:\n\tinc\tedi\t\t\t\t; point to next viewport pixel\n\tdec\tecx\t\t\t\t; any source pixels left?\n\tjz\t??out\t\t\t\t;   if not then go home\n\n??general_draw_continue:\n\tmov\tal,[esi]\t\t\t; get a byte of the source\n\tinc\tesi\n\tor\teax,eax\t\t\t\t; is the byte a transparent run?\n\tjz\t??general_is_run\t\t;   if yes then handle the run\n\t\n??test_priority:\n\ttest\tedx,SHAPE_PRIORITY\t\t\n\tjnz\tshort ??priority\n\n??test_predator:\n\ttest\tedx,SHAPE_PREDATOR\n\tjnz\tshort ??predator\n\n??test_compact:\n\ttest\tedx,SHAPE_COMPACT\n\tjnz\t??compact\n\n??test_shadow:\n\ttest\tedx,SHAPE_SHADOW\n\tjnz\t??shadow\n\n??test_translucency:\n\ttest\tedx,SHAPE_GHOST\n\tjz\tshort ??test_fading\n\n\tmov\tebx,[IsTranslucent]\t\t; is it a translucent color?\n\tmov\tbh,[BYTE PTR ebx + eax]\n\tor\tbh,bh\n\tjs\tshort ??test_fading\n\n\tand\tebx,0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tmov\tal,[edi]\t\t\t; mov pixel at destination to al\n\tadd\tebx,[Translucent]\t\t; get the ptr to it!\n\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; get new pixel in al\n\tjmp\tshort ??test_fading\n\n??test_fading:\n\ttest\tedx,SHAPE_FADING\n\tjnz\t??fading\n\tjmp\tshort ??general_draw_loop\n\n??priority:\t\n\tmov\tebx,[MaskAdjust]\t\t; get mask page\toffset\n\tmov\tbl,[BYTE PTR ebx + edi]\t\t; get mask value  \n\n\tand\tbl,CLEAR_UNUSED_BITS\t\t; clear unused bits\n\n\tcmp\t[PriLevel],bl\t\t\t; are we in front of\n\tjge\tshort ??test_predator\t\t;  background?\n\n\tmov\tebx,[BackAdjust]\t\t; get background page offset\n\tmov\tal,[BYTE PTR ebx + edi]\t\t; get background pixel\n\tjmp\t??general_draw_loop\n\n??predator:\n\tmov\tebx,[PartialCount]\n\tadd\tebx,[PartialPred]\t\n\tor\tbh,bh\n\tjnz\tshort ??draw_pred\t\t; is this a predator pixel?\n\tmov\t[PartialCount],ebx\n\tjmp\tshort ??test_compact\n\n??draw_pred:\n\txor\tbh,bh\n\tmov\t[PartialCount],ebx\n\tmov\tebx,[PredValue]\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\tmov\tal,[edi + ebx]\t\t\t;  viewport address\n\tjmp\t??general_draw_loop\n\n??compact:\n\tmov\tebx,[ColorTable]\t\t; get the address of the color table\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; convert it into the proper byte\n\tjmp\t??test_shadow\n\n??shadow:\n\tcmp\tal,SHADOW_COL\n\tjne\t??test_translucency\t\t; is the table value a magic number?\n\n\tmov\tal,[edi]\t\t\t; get the destination color and\n\tmov\tebx,[ShadowingTable]\t\t;  index into the shadow table\n\tmov\tal,[BYTE PTR ebx + eax]\n\tjmp\t??general_draw_loop\t\t\t\n\n??fading:\n\tmov\t[StashECX],ecx\t\t\t; preserve ecx for later\n\tmov\tebx,[FadingTable]\t\t; run color through fading table\n\tmov\tecx,[FadingNum]\n\n??fade_loop:\n\tmov\tal, [BYTE PTR ebx + eax]\n\tdec\tecx\n\tjnz\tshort ??fade_loop\n\n\tmov\tecx,[StashECX]\t\t\t; restore ecx for main draw loop\n\tjmp\t??general_draw_loop\t\t\t\n\n??general_is_run:\n\tmov\tal,[esi]\n\tinc\tesi\n\tadd\tedi,eax\t\t\t\t; move the viewport pointer\n\tsub\tecx,eax\t\t\t\t; chop down the width to do\n\tjg\t??general_draw_continue\t\t; while more to do, loop back up\n\n??out:\t\n\tadd\t[WidthCount],ecx\t\t; adjust for source ending in a run\n\tmov\tedx,[StashEDX]\n\tret\t\n\n\tENDP\tDraw_Normal\n\n\tEND\n\n;**************************** End of ds_dn.asm *****************************\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DS_DR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_DR.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : September 6, 1994   [IML]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Draw_Reverse -- Draws a reversed row of pixels to the viewport        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Draw_Reverse -- Draws a reversed row of pixels to the viewport          *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of pixels (not bytes) to draw\t\t   *\n;*\t\tEDX = XTotal initializer value\t\t\t\t   *\n;*\t\tESI = shape (source) buffer address\t\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = remaining bytes on the line\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;*\t\tESI - updated to current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) drawn/skipped\t   *\n;*\t\t[WidthCount] - bytes remaining on the line\t\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR  : Converted to 32-bit.\t\t\t\t   *\t\n;*   08/09/1994 IML : Optimized for 32-bit.\t\t\t\t   *\n;*   09/06/1994 IML : Integrated p_* and ds_* routines.\t\t\t   *\n;*=========================================================================*\nPROC\tDraw_Reverse NOLANGUAGE NEAR\n\n\tmov\t[StashEDX],edx\t\t\t; save edx\n\tmov\tedx,[Flags]\t\t\t\n\tmov\teax,0\t\t\t\t; init to zero\n\tsub\t[WidthCount],ecx\t\t; decrement bytes remaining by pixels\n\t\t\t\t\t\t;   to draw\n\n\t;--------------------------------------------------------------------\n\t; Drawing Loop:\n\t; - Get a data byte\n\t; - If it's a 0, handle the run:\n\t;\t- get repetition value\n\t;\t- subtract it from EDI\n\t;\t- subtract it from [WidthCount]\n\t;\t- subtract it from ECX\n\t;\t- if ECX>0, draw again, else exit\n\t; - Otherwise:\n\t;\t- draw the pixel\n\t;\t- increment EDI to next pixel location\n\t;\t- decrement [WidthCount]\n\t;\t- loop until ECX is 0\n\t;--------------------------------------------------------------------\n\ttest\tedx,SHAPE_EFFECTS\t\t; are any effects flags set?\n\tjnz\tshort ??general_draw_continue\t;   if so use the general purpose loop\n\n\n\t;--------------------------------------------------------------------\n\t; Extra fast draw loop for shapes with no flags set.\n\t;--------------------------------------------------------------------\n??fast_draw_loop:\n\tmov\tal,[esi]\t\t\t; get a byte of the source\n\tinc\tesi\n\tor\teax,eax\t\t\t\t; is the byte a transparent run?\n\tjz\tshort ??fast_is_run\t\t;   if yes then handle the run\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\tdec\tedi\t\t\t\t; point to next viewport pixel\n\tdec\tecx\t\t\t\t; any source pixels left?\n\tjnz\tshort ??fast_draw_loop\t\t;   if not then go home\n\tjmp\t??out\n\n??fast_is_run:\n\tmov\tal,[esi]\n\tinc\tesi\n\tsub\tedi,eax\t\t\t\t; move the viewport pointer\n\tsub\tecx,eax\t\t\t\t; chop down the width to do\n\tjg\tshort ??fast_draw_loop\t\t; while more to do, loop back up\n\tjmp\t??out\n\n\n\t;--------------------------------------------------------------------\n\t; General purpose draw loop for shapes with one or more flags set.\n\t;--------------------------------------------------------------------\n??general_draw_loop:\n\ttest\tedx,SHAPE_FADING\t\t; if fading is enabled test for\n\tjz\tshort ??no_fading_draw_loop\t;   transparency\n\tor\teax,eax\n\tjz\tshort ??is_transparent\n\n??no_fading_draw_loop:\t\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\n??is_transparent:\n\tdec\tedi\t\t\t\t; point to next viewport pixel\n\tdec\tecx\t\t\t\t; any source pixels left?\n\tjz\t??out\t\t\t\t;   if not then go home\n\n??general_draw_continue:\n\tmov\tal,[esi]\t\t\t; get a byte of the source\n\tinc\tesi\n\tor\teax,eax\t\t\t\t; is the byte a transparent run?\n\tjz\t??general_is_run\t\t;   if yes then handle the run\n\t\n??test_priority:\n\ttest\tedx,SHAPE_PRIORITY\t\t\n\tjnz\tshort ??priority\n\n??test_predator:\n\ttest\tedx,SHAPE_PREDATOR\n\tjnz\tshort ??predator\n\n??test_compact:\n\ttest\tedx,SHAPE_COMPACT\n\tjnz\t??compact\n\n??test_shadow:\n\ttest\tedx,SHAPE_SHADOW\n\tjnz\t??shadow\n\n??test_translucency:\n\ttest\tedx,SHAPE_GHOST\n\tjz\tshort ??test_fading\n\n\tmov\tebx,[IsTranslucent]\t\t; is it a translucent color?\n\tmov\tbh,[BYTE PTR ebx + eax]\n\tor\tbh,bh\n\tjs\tshort ??test_fading\t\t\n\n\tand\tebx,0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tmov\tal,[edi]\t\t\t; mov pixel at destination to al\n\tadd\tebx,[Translucent]\t\t; get the ptr to it!\n\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; get new pixel in al\n\n??test_fading:\n\ttest\tedx,SHAPE_FADING\n\tjnz\t??fading\n\tjmp\tshort ??general_draw_loop\n\n??priority:\t\n\tmov\tebx,[MaskAdjust]\t\t; get mask page\toffset\n\tmov\tbl,[BYTE PTR ebx + edi]\t\t; get mask value  \n\n\tand\tbl,CLEAR_UNUSED_BITS\t\t; clear unused bits\n\n\tcmp\t[PriLevel],bl\t\t\t; are we in front of\n\tjge\tshort ??test_predator\t\t;  background?\n\n\tmov\tebx,[BackAdjust]\t\t; get background page offset\n\tmov\tal,[BYTE PTR ebx + edi]\t\t; get background pixel\n\tjmp\t??general_draw_loop\n\n??predator:\n\tmov\tebx,[PartialCount]\n\tadd\tebx,[PartialPred]\t\n\tor\tbh,bh\n\tjnz\tshort ??draw_pred\t\t; is this a predator pixel?\n\tmov\t[PartialCount],ebx\n\tjmp\tshort ??test_compact\n\n??draw_pred:\n\txor\tbh,bh\n\tmov\t[PartialCount],ebx\n\tmov\tebx,[PredValue]\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\tmov\tal,[edi + ebx]\t\t\t;  viewport address\n\tjmp\t??general_draw_loop\n\n??compact:\n\tmov\tebx,[ColorTable]\t\t; get the address of the color table\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; convert it into the proper byte\n\tjmp\t??test_shadow\n\n??shadow:\n\tcmp\tal,SHADOW_COL\n\tjne\t??test_translucency\t\t; is the table value a magic number?\n\n\tmov\tal,[edi]\t\t\t; get the destination color and\n\tmov\tebx,[ShadowingTable]\t\t;  index into the shadow table\n\tmov\tal,[BYTE PTR ebx + eax]\n\tjmp\t??general_draw_loop\t\t\t\n\n??fading:\n\tmov\t[StashECX],ecx\t\t\t; preserve ecx for later\n\tmov\tebx,[FadingTable]\t\t; run color through fading table\n\tmov\tecx,[FadingNum]\n\n??fade_loop:\n\tmov\tal, [BYTE PTR ebx + eax]\n\tdec\tecx\n\tjnz\tshort ??fade_loop\n\n\tmov\tecx,[StashECX]\t\t\t; restore ecx for main draw loop\n\tjmp\t??general_draw_loop\t\t\t\n\n??general_is_run:\n\tmov\tal,[esi]\n\tinc\tesi\n\tsub\tedi,eax\t\t\t\t; move the viewport pointer\n\tsub\tecx,eax\t\t\t\t; chop down the width to do\n\tjg\t??general_draw_continue\t\t\t; while more to do, loop back up\n\n??out:\t\n\tadd\t[WidthCount],ecx\t\t; adjust for source ending in a run\n\tmov\tedx,[StashEDX]\n\tret\t\n\n\tENDP\tDraw_Reverse\n\n\n\tEND\n\n;**************************** End of ds_dr.asm *****************************\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DS_DS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_DS.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : September 6, 1994   [IML]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Draw_Scale -- Draws a scaled row of pixels to the viewport            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Draw_Scale -- Draws a scaled row of pixels to the viewport              *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of pixels (not bytes) to draw\t\t   *\n;*\t\tEDX = XTotal initializer value\t\t\t\t   *\n;*\t\tESI = shape (source) buffer address\t\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = remaining bytes on the line\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;*\t\tESI - updated to current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) drawn/skipped\t   *\n;*\t\t[WidthCount] - bytes remaining on the line\t\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR  : Converted to 32-bit.                                 *\n;*   08/09/1994 IML : Optimized for 32-bit.\t\t\t\t   *\n;*   09/06/1994 IML : Integrated p_* and ds_* routines.\t\t\t   *\n;*=========================================================================*\nPROC\tDraw_Scale NOLANGUAGE NEAR\n\n\tmov\teax,0\t\t\t\t; init to 0\n\ttest\t[Flags],SHAPE_EFFECTS\n\tjnz\tshort ??general_draw_continue\n\tjmp\tshort ??fast_draw_continue\n\n\n\t;--------------------------------------------------------------------\n\t; Extra fast draw loop for shapes with no flags set.\n\t;--------------------------------------------------------------------\n\t\n\t;--------------------------------------------------------------------\n\t; Load a new byte:\n\t; - read the byte into AL\n\t; - if it's a run, deal with it\n\t; - otherwise, \n\t;\t- decrement [WidthCount]\n\t;\t- update EDX with [ScaleX]\n\t;\t- see if it's drawable (upon proc entry, it won't be)\n\t;\t\t- yes: draw a pixel\n\t;\t\t- no : load a new byte\n\t;--------------------------------------------------------------------\n??fast_draw_loop:\n\tmov\tal,[esi]\t\t\t; get the next pixel from the source\n\tinc\tesi\n\tor\teax,eax\n\tjz\tshort ??fast_is_run\t\t; deal with a run\n\tdec\t[WidthCount]\t\t\t; count down # bytes processed\n\tadd\tedx,[ScaleX]\t\t\t; add in the scale value\n\n??fast_draw_continue:\n\tor\tdh,dh\t\t\t\t; are there any pixels to draw?\n\tjz\tshort ??fast_draw_loop\n\n\n\t;--------------------------------------------------------------------\n\t; Draw one pixel:\n\t; - draw the pixel\n\t; - increment destination pointer\n\t; - decrement high byte of EDX (X-scale accumulator)\n\t; - loop (while ECX>0) to see if it's drawable\n\t;--------------------------------------------------------------------\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\tinc\tedi\t\t\t\t; increment the destination index\n\tdec\tdh\t\t\t\t; decrement the pixels to write\n\tdec\tecx\n\tjnz\tshort ??fast_draw_continue\n\tjmp\t??out\t\t\t\t; get the heck outta here\n\n\n\t;--------------------------------------------------------------------\n\t; Handle a run:\n\t; - Get the run repetition value\n\t; - subract it from [WidthCount]\n\t; - multiply it by [ScaleX]\n\t; - put high bytes from mul into EAX, low byte into DL (roundoff bits)\n\t; - add high bytes (# pixels) to EDI\n\t; - subtract them from ECX\n\t; - clear EAX\n\t; - if ECX>0, go get next byte\n\t;--------------------------------------------------------------------\n??fast_is_run:\n\tmov\tal,[esi]\t\t\t; get number of repeated values\n\tinc\tesi\n\tsub\t[WidthCount],eax\t\t; adjust the remaining byte width\n\tmov\tebx,edx\t\t\t\t; preserve dx for the multiply\n\tmul\t[ScaleX]\t\t\t; EDX:EAX = # pixels + roundoff bits\n\tadd\teax,ebx\t\t\t\t; add in the current x-total\n\tmov\tedx,eax\t\t\t\t; (assume EDX is empty)\n\tshr\teax,8\t\t\t\t; EAX = # pixels skipped\n\tand\tedx,00FFh\t\t\t; keep only low byte\n\tadd\tedi,eax\t\t\t\t; add to EDI\n     \tsub\tecx,eax\t\t\t\t; subtract it from ECX\n\tmov\teax,0\t\t\t\t; clear EAX\n\tor\tecx,ecx\n\tjg\tshort ??fast_draw_loop\t\t; if more to draw, process new byte\n\tjmp\t??out\n\n\n\t;--------------------------------------------------------------------\n\t; General purpose draw loop for shapes with one or more flags set.\n\t;--------------------------------------------------------------------\n\n\t;--------------------------------------------------------------------\n\t; Load a new byte:\n\t; - read the byte into AL\n\t; - if it's a run, deal with it\n\t; - otherwise, \n\t;\t- decrement [WidthCount]\n\t;\t- update EDX with [ScaleX]\n\t;\t- see if it's drawable (upon proc entry, it won't be)\n\t;\t\t- yes: draw a pixel\n\t;\t\t- no : load a new byte\n\t;--------------------------------------------------------------------\n??general_draw_loop:\n\tmov\tal,[esi]\t\t\t; get the next pixel from the source\n\tinc\tesi\n\tor\teax,eax\n\tjz\t??general_is_run\t\t; deal with a run\n\tdec\t[WidthCount]\t\t\t; count down # bytes processed\n\tadd\tedx,[ScaleX]\t\t\t; add in the scale value\n\n??general_draw_continue:\n\tor\tdh,dh\t\t\t\t; are there any pixels to draw?\n\tjz\tshort ??general_draw_loop\n\n\t;--------------------------------------------------------------------\n\t; Draw one pixel:\n\t; - draw the pixel\n\t; - increment destination pointer\n\t; - decrement high byte of EDX (X-scale accumulator)\n\t; - loop (while ECX>0) to see if it's drawable\n\t;--------------------------------------------------------------------\n??draw:\n\tmov\t[StashReg],eax\t\t\t; save eax\n\tmov\t[StashEDX],edx\t\t\t; save edx\n\tmov\tedx,[Flags]\n\n??test_priority:\n\ttest\tedx,SHAPE_PRIORITY\t\t\n\tjnz\tshort ??priority\n\n??test_predator:\n\ttest\tedx,SHAPE_PREDATOR\n\tjnz\tshort ??predator\n\n??test_compact:\n\ttest\tedx,SHAPE_COMPACT\n\tjnz\t??compact\n\n??test_shadow:\n\ttest\tedx,SHAPE_SHADOW\n\tjnz\t??shadow\n\n??test_translucency:\n\ttest\tedx,SHAPE_GHOST\n\tjnz\t??translucency\n\n??test_fading:\n\ttest\tedx,SHAPE_FADING\n\tjnz\t??fading\n\n\n??test_transparency:\t\n\ttest\tedx,SHAPE_FADING\t\t; if fading is enabled test for\n\tjz\tshort ??no_fading_draw_loop\t;   transparency\n\tor\teax,eax\n\tjz\tshort ??is_transparent\n\n??no_fading_draw_loop:\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\t\n??is_transparent:\n\tmov\teax,[StashReg]\t\t\t; restore eax\n\tmov\tedx,[StashEDX]\t\t\t; restore edx\n\tinc\tedi\t\t\t\t; increment the destination index\n\tdec\tdh\t\t\t\t; decrement the pixels to write\n\tdec\tecx\n\tjnz\t??general_draw_continue\n\tjmp\t??out\t\t\t\t; get the heck outta here\n\n??priority:\t\n\tmov\tebx,[MaskAdjust]\t\t; get mask page\toffset\n\tmov\tbl,[BYTE PTR ebx + edi]\t\t; get mask value  \n\n\tand\tbl,CLEAR_UNUSED_BITS\t\t; clear unused bits\n\n\tcmp\t[PriLevel],bl\t\t\t; are we in front of\n\tjge\tshort ??test_predator\t\t;  background?\n\n\tmov\tebx,[BackAdjust]\t\t; get background page offset\n\tmov\tal,[BYTE PTR ebx + edi]\t\t; get background pixel\n\tjmp\tshort ??test_transparency\n\n??predator:\n\tmov\tebx,[PartialCount]\n\tadd\tebx,[PartialPred]\t\n\tor\tbh,bh\n\tjnz\tshort ??draw_pred\t\t; is this a predator pixel?\n\tmov\t[PartialCount],ebx\n\tjmp\t??test_compact\n\n??draw_pred:\n\txor\tbh,bh\n\tmov\t[PartialCount],ebx\n\tmov\tebx,[PredValue]\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\tmov\tal,[edi + ebx]\t\t\t;  viewport address\n\tjmp\tshort ??test_transparency\n\n??compact:\n\tmov\tebx,[ColorTable]\t\t; get the address of the color table\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; convert it into the proper byte\n\tjmp\t??test_shadow\n\n??shadow:\n\tcmp\tal,SHADOW_COL\n\tjne\t??test_translucency\t\t; is the table value a magic number?\n\n\tmov\tal,[edi]\t\t\t; get the destination color and\n\tmov\tebx,[ShadowingTable]\t\t;  index into the shadow table\n\tmov\tal,[BYTE PTR ebx + eax]\n\tjmp\t??test_transparency\t\t\t\n\n??fading:\n\tmov\t[StashECX],ecx\t\t\t; preserve ecx for later\n\tmov\tebx,[FadingTable]\t\t; run color through fading table\n\tmov\tecx,[FadingNum]\n\n??fade_loop:\n\tmov\tal, [BYTE PTR ebx + eax]\n\tdec\tecx\n\tjnz\tshort ??fade_loop\n\n\tmov\tecx,[StashECX]\t\t\t; restore ecx for main draw loop\n\tjmp\t??test_transparency\n\n??translucency:\n\tmov\tebx,[IsTranslucent]\t\t; is it a translucent color?\n\tmov\tbh,[BYTE PTR ebx + eax]\n\tor\tbh,bh\n\tjs\t??test_fading\n\n\tand\tebx,0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tmov\tal,[edi]\t\t\t; mov pixel at destination to al\n\tadd\tebx,[Translucent]\t\t; get the ptr to it!\n\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; get new pixel in al\n\tjmp\t??test_fading\n\n\n\t;--------------------------------------------------------------------\n\t; Handle a run:\n\t; - Get the run repetition value\n\t; - subract it from [WidthCount]\n\t; - multiply it by [ScaleX]\n\t; - put high bytes from mul into EAX, low byte into DL (roundoff bits)\n\t; - add high bytes (# pixels) to EDI\n\t; - subtract them from ECX\n\t; - clear EAX\n\t; - if ECX>0, go get next byte\n\t;--------------------------------------------------------------------\n??general_is_run:\n\tmov\tal,[esi]\t\t\t; get number of repeated values\n\tinc\tesi\n\tsub\t[WidthCount],eax\t\t; adjust the remaining byte width\n\tmov\tebx,edx\t\t\t\t; preserve dx for the multiply\n\tmul\t[ScaleX]\t\t\t; EDX:EAX = # pixels + roundoff bits\n\tadd\teax,ebx\t\t\t\t; add in the current x-total\n\tmov\tedx,eax\t\t\t\t; (assume EDX is empty)\n\tshr\teax,8\t\t\t\t; EAX = # pixels skipped\n\tand\tedx,00FFh\t\t\t; keep only low byte\n\tadd\tedi,eax\t\t\t\t; add to EDI\n     \tsub\tecx,eax\t\t\t\t; subtract it from ECX\n\tmov\teax,0\t\t\t\t; clear EAX\n\tor\tecx,ecx\n\tjg\t??general_draw_loop\t\t; if more to draw, process new byte\n\n??out:\n\tret\t\t\t\t\t; lets get out of here\n\n\tENDP\tDraw_Scale\n\n\tEND\n\n;**************************** End of ds_ds.asm ******************************\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DS_DSR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_DSR.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : September 6, 1994   [IML]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Draw_Scale_Reverse -- Draws a scaled row of pixels to the viewport    *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;*******p********************************************************************\n;* Draw_Scale_Reverse -- Draws a scaled row of pixels to the viewport      *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of pixels (not bytes) to draw\t\t   *\n;*\t\tEDX = XTotal initializer value\t\t\t\t   *\n;*\t\tESI = shape (source) buffer address\t\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = remaining bytes on the line\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;*\t\tESI - updated to current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) drawn/skipped\t   *\n;*\t\t[WidthCount] - bytes remaining on the line\t\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR  : Converted to 32-bit.                                 *\n;*   08/09/1994 IML : Optimized for 32-bit\t\t\t\t   *\n;*   09/06/1994 IML : Integrated p_* and ds_* routines.\t\t\t   *\n;*=========================================================================*\nPROC\tDraw_Scale_Reverse NOLANGUAGE NEAR\n\n\tmov\teax,0\t\t\t\t; init to 0\n\ttest\t[Flags],SHAPE_EFFECTS\n\tjnz\tshort ??general_draw_continue\n\tjmp\tshort ??fast_draw_continue\n\n\n\t;--------------------------------------------------------------------\n\t; Extra fast draw loop for shapes with no flags set.\n\t;--------------------------------------------------------------------\n\t\n\t;--------------------------------------------------------------------\n\t; Load a new byte:\n\t; - read the byte into AL\n\t; - if it's a run, deal with it\n\t; - otherwise, \n\t;\t- decrement [WidthCount]\n\t;\t- update EDX with [ScaleX]\n\t;\t- see if it's drawable (upon proc entry, it won't be)\n\t;\t\t- yes: draw a pixel\n\t;\t\t- no : load a new byte\n\t;--------------------------------------------------------------------\n??fast_draw_loop:\n\tmov\tal,[esi]\t\t\t; get the next pixel from the source\n\tinc\tesi\n\tor\teax,eax\n\tjz\tshort ??fast_is_run\t\t; deal with a run\n\tdec\t[WidthCount]\t\t\t; count down # bytes processed\n\tadd\tedx,[ScaleX]\t\t\t; add in the scale value\n\n??fast_draw_continue:\n\tor\tdh,dh\t\t\t\t; are there any pixels to draw?\n\tjz\tshort ??fast_draw_loop\n\n\n\t;--------------------------------------------------------------------\n\t; Draw one pixel:\n\t; - draw the pixel\n\t; - increment destination pointer\n\t; - decrement high byte of EDX (X-scale accumulator)\n\t; - loop (while ECX>0) to see if it's drawable\n\t;--------------------------------------------------------------------\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\tdec\tedi\t\t\t\t; decrement the destination index\n\tdec\tdh\t\t\t\t; decrement the pixels to write\n\tdec\tecx\n\tjnz\tshort ??fast_draw_continue\n\tjmp\t??out\t\t\t\t; get the heck outta here\n\n\n\t;--------------------------------------------------------------------\n\t; Handle a run:\n\t; - Get the run repetition value\n\t; - subract it from [WidthCount]\n\t; - multiply it by [ScaleX]\n\t; - put high bytes from mul into EAX, low byte into DL (roundoff bits)\n\t; - add high bytes (# pixels) to EDI\n\t; - subtract them from ECX\n\t; - clear EAX\n\t; - if ECX>0, go get next byte\n\t;--------------------------------------------------------------------\n??fast_is_run:\n\tmov\tal,[esi]\t\t\t; get number of repeated values\n\tinc\tesi\n\tsub\t[WidthCount],eax\t\t; adjust the remaining byte width\n\tmov\tebx,edx\t\t\t\t; preserve dx for the multiply\n\tmul\t[ScaleX]\t\t\t; EDX:EAX = # pixels + roundoff bits\n\tadd\teax,ebx\t\t\t\t; add in the current x-total\n\tmov\tedx,eax\t\t\t\t; (assume EDX is empty)\n\tshr\teax,8\t\t\t\t; EAX = # pixels skipped\n\tand\tedx,00FFh\t\t\t; keep only low byte\n\tsub\tedi,eax\t\t\t\t; sub from EDI\n     \tsub\tecx,eax\t\t\t\t; subtract it from ECX\n\tmov\teax,0\t\t\t\t; clear EAX\n\tor\tecx,ecx\n\tjg\tshort ??fast_draw_loop\t\t; if more to draw, process new byte\n\tjmp\t??out\n\n\n\t;--------------------------------------------------------------------\n\t; General purpose draw loop for shapes with one or more flags set.\n\t;--------------------------------------------------------------------\n\n\t;--------------------------------------------------------------------\n\t; Load a new byte:\n\t; - read the byte into AL\n\t; - if it's a run, deal with it\n\t; - otherwise, \n\t;\t- decrement [WidthCount]\n\t;\t- update EDX with [ScaleX]\n\t;\t- see if it's drawable (upon proc entry, it won't be)\n\t;\t\t- yes: draw a pixel\n\t;\t\t- no : load a new byte\n\t;--------------------------------------------------------------------\n??general_draw_loop:\n\tmov\tal,[esi]\t\t\t; get the next pixel from the source\n\tinc\tesi\n\tor\teax,eax\n\tjz\t??general_is_run\t\t; deal with a run\n\tdec\t[WidthCount]\t\t\t; count down # bytes processed\n\tadd\tedx,[ScaleX]\t\t\t; add in the scale value\n\n??general_draw_continue:\n\tor\tdh,dh\t\t\t\t; are there any pixels to draw?\n\tjz\tshort ??general_draw_loop\n\n\t;--------------------------------------------------------------------\n\t; Draw one pixel:\n\t; - draw the pixel\n\t; - increment destination pointer\n\t; - decrement high byte of EDX (X-scale accumulator)\n\t; - loop (while ECX>0) to see if it's drawable\n\t;--------------------------------------------------------------------\n??draw:\n\tmov\t[StashReg],eax\t\t\t; save eax\n\tmov\t[StashEDX],edx\t\t\t; save edx\n\tmov\tedx,[Flags]\n\n??test_priority:\n\ttest\tedx,SHAPE_PRIORITY\t\t\n\tjnz\tshort ??priority\n\n??test_predator:\n\ttest\tedx,SHAPE_PREDATOR\n\tjnz\tshort ??predator\n\n??test_compact:\n\ttest\tedx,SHAPE_COMPACT\n\tjnz\t??compact\n\n??test_shadow:\n\ttest\tedx,SHAPE_SHADOW\n\tjnz\t??shadow\n\n??test_translucency:\n\ttest\tedx,SHAPE_GHOST\n\tjnz\t??translucency\n\n??test_fading:\n\ttest\tedx,SHAPE_FADING\n\tjnz\t??fading\n\n??test_transparency:\t\n\ttest\tedx,SHAPE_FADING\t\t; if fading is enabled test for\n\tjz\tshort ??no_fading_draw_loop\t;   transparency\n\tor\teax,eax\n\tjz\tshort ??is_transparent\n\n??no_fading_draw_loop:\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\t\n??is_transparent:\n\tmov\teax,[StashReg]\t\t\t; restore eax\n\tmov\tedx,[StashEDX]\t\t\t; restore edx\n\tdec\tedi\t\t\t\t; decrement the destination index\n\tdec\tdh\t\t\t\t; decrement the pixels to write\n\tdec\tecx\n\tjnz\t??general_draw_continue\n\tjmp\t??out\t\t\t\t; get the heck outta here\n\n??priority:\t\n\tmov\tebx,[MaskAdjust]\t\t; get mask page\toffset\n\tmov\tbl,[BYTE PTR ebx + edi]\t\t; get mask value  \n\n\tand\tbl,CLEAR_UNUSED_BITS\t\t; clear unused bits\n\n\tcmp\t[PriLevel],bl\t\t\t; are we in front of\n\tjge\tshort ??test_predator\t\t;  background?\n\n\tmov\tebx,[BackAdjust]\t\t; get background page offset\n\tmov\tal,[BYTE PTR ebx + edi]\t\t; get background pixel\n\tjmp\tshort ??test_transparency\n\n??predator:\n\tmov\tebx,[PartialCount]\n\tadd\tebx,[PartialPred]\t\n\tor\tbh,bh\n\tjnz\tshort ??draw_pred\t\t; is this a predator pixel?\n\tmov\t[PartialCount],ebx\n\tjmp\t??test_compact\n\n??draw_pred:\n\txor\tbh,bh\n\tmov\t[PartialCount],ebx\n\tmov\tebx,[PredValue]\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\tmov\tal,[edi + ebx]\t\t\t;  viewport address\n\tjmp\tshort ??test_transparency\n\n??compact:\n\tmov\tebx,[ColorTable]\t\t; get the address of the color table\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; convert it into the proper byte\n\tjmp\t??test_shadow\n\n??shadow:\n\tcmp\tal,SHADOW_COL\n\tjne\t??test_translucency\t\t; is the table value a magic number?\n\n\tmov\tal,[edi]\t\t\t; get the destination color and\n\tmov\tebx,[ShadowingTable]\t\t;  index into the shadow table\n\tmov\tal,[BYTE PTR ebx + eax]\n\tjmp\t??test_transparency\t\t\t\n\n??fading:\n\tmov\t[StashECX],ecx\t\t\t; preserve ecx for later\n\tmov\tebx,[FadingTable]\t\t; run color through fading table\n\tmov\tecx,[FadingNum]\n\n??fade_loop:\n\tmov\tal, [BYTE PTR ebx + eax]\n\tdec\tecx\n\tjnz\tshort ??fade_loop\n\n\tmov\tecx,[StashECX]\t\t\t; restore ecx for main draw loop\n\tjmp\t??test_transparency\n\n??translucency:\n\tmov\tebx,[IsTranslucent]\t\t; is it a translucent color?\n\tmov\tbh,[BYTE PTR ebx + eax]\n\tor\tbh,bh\n\tjs\t??test_fading\n\n\tand\tebx,0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tmov\tal,[edi]\t\t\t; mov pixel at destination to al\n\tadd\tebx,[Translucent]\t\t; get the ptr to it!\n\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; get new pixel in al\n\tjmp\t??test_fading\n\n\n\t;--------------------------------------------------------------------\n\t; Handle a run:\n\t; - Get the run repetition value\n\t; - subract it from [WidthCount]\n\t; - multiply it by [ScaleX]\n\t; - put high bytes from mul into EAX, low byte into DL (roundoff bits)\n\t; - add high bytes (# pixels) to EDI\n\t; - subtract them from ECX\n\t; - clear EAX\n\t; - if ECX>0, go get next byte\n\t;--------------------------------------------------------------------\n??general_is_run:\n\tmov\tal,[esi]\t\t\t; get number of repeated values\n\tinc\tesi\n\tsub\t[WidthCount],eax\t\t; adjust the remaining byte width\n\tmov\tebx,edx\t\t\t\t; preserve dx for the multiply\n\tmul\t[ScaleX]\t\t\t; EDX:EAX = # pixels + roundoff bits\n\tadd\teax,ebx\t\t\t\t; add in the current x-total\n\tmov\tedx,eax\t\t\t\t; (assume EDX is empty)\n\tshr\teax,8\t\t\t\t; EAX = # pixels skipped\n\tand\tedx,00FFh\t\t\t; keep only low byte\n\tsub\tedi,eax\t\t\t\t; sub from EDI\n     \tsub\tecx,eax\t\t\t\t; subtract it from ECX\n\tmov\teax,0\t\t\t\t; clear EAX\n\tor\tecx,ecx\n\tjg\t??general_draw_loop\t\t; if more to draw, process new byte\n\n??out:\n\tret\t\t\t\t\t; lets get out of here\n\n\n\tENDP\tDraw_Scale_Reverse\n\t\n\tEND\n\n;*************************** End of ds_dsr.asm ******************************\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DS_LRS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_LRS.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 2, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Left_Reverse_Skip -- Skips bytes in a data stream\t\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Left_Reverse_Skip -- Skips bytes in a data stream\t\t\t   *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape (source) buffer data address\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = shape's width\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX - negative # pixels overrun, or 0\t\t\t   *\n;*\t\tEDX - XTotal initializer value (0 since there's no scaling)*\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\tEDI - decremented by # pixels overrun\t\t\t   *\n;*\t\t[WidthCount] - decremented by # bytes skipped\t\t   *\n;*                                                                         *\n;* WARNINGS:\tnone                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   05/28/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tLeft_Reverse_Skip NOLANGUAGE NEAR\n\n\tsub \t[WidthCount],ecx\t; we process ECX bytes of real width\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out\t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tadd\tedi,ecx\t\t\t; decrement EDI by overrun pixels\n\tadd\t[WidthCount],ecx\t; adjust by # bytes overrun\n\tmov\tedx,0\t\t\t; no scaling, so clear EDX\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tLeft_Reverse_Skip\n\n\tEND\n\n;*************************** End of ds_lrs.asm *****************************\n\u001a"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DS_LS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_LS.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 2, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Left_Skip -- Skips bytes in a data stream\t\t\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Left_Skip -- Skips bytes in a data stream\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape (source) buffer data address\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = shape's width\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX - negative # pixels overrun, or 0\t\t\t   *\n;*\t\tEDX - XTotal initializer value (0 since there's no scaling)*\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\tEDI - incremented by # pixels overrun\t\t\t   *\n;*\t\t[WidthCount] - decremented by # bytes skipped\t\t   *\n;*                                                                         *\n;* WARNINGS:\tnone                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tLeft_Skip NOLANGUAGE NEAR\n\n\tsub \t[WidthCount],ecx\t; we process ECX bytes of real width\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out\t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tsub\tedi,ecx\t\t\t; increment EDI by overrun pixels\n\tadd\t[WidthCount],ecx\t; adjust by # bytes overrun\n\tmov\tedx,0\t\t\t; no scaling, so clear EDX\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tLeft_Skip\n\n\tEND\n\n;**************************** End of ds_ls.asm *****************************\n\u001a"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DS_LSRS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_LSRS.ASM                              *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 2, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Left_Scale_Reverse_Skip -- Skips past a scaled row of pixels          *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Left_Scale_Reverse_Skip -- Skips past a scaled row of pixels            *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape (source) buffer data address\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = shape's width\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX - negative # pixels (not bytes) overrun, or 0\t   *\n;*\t\tEDX - XTotal initializer value\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\tEDI - decremented by # pixels (not bytes) overrun\t   *\n;*\t\t[WidthCount] - decremented by # bytes skipped\t\t   *\n;*                                                                         *\n;* The value returned in EDX reflects what XTotal's accumulated value \t   *\n;* should be at the new pixel location.  If no bytes are overrun, this\t   *\n;* will be whatever is stored in [XTotalInit] (which will be 0 if no\t   *\n;* pixels are left-clipped).\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:\tnone                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/20/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tLeft_Scale_Reverse_Skip NOLANGUAGE NEAR\n\n\tsub \t[WidthCount],ecx\t; we process ECX bytes of real width\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjcxz\t??getrem\t\t; exit if no bytes to skip\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\tshort ??on_run\t\t; if it is a run then deal with it\n\n\t;--------------------------------------------------------------------\n\t; Default exit point: store default x-scale bits & exit\n\t;--------------------------------------------------------------------\n??getrem:\n\tmov\tedx,[XTotalInit]\t; store out the remainder\n\tjmp\tshort ??out \t\t; we're done, get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\tjz\t??getrem\t\t; exactly enough bytes; exit\n\n\t;--------------------------------------------------------------------\n\t; Overrun exit point: ECX is negative by the # of bytes overrun.\n\t; - adjust [WidthCount] by # of overrun bytes\n\t; - compute the remainder at the new location (EDX)\n\t; - compute the number of destination pixels to skip (ECX)\n\t; - adjust EDI by # of overrun bytes\n\t;--------------------------------------------------------------------\n\t;\n\t;............... adjust [WidthCount] by overrun bytes ...............\n\t;\n\tadd\t[WidthCount],ecx\t; adjust overrun in bytes\n\t;\n\t;................. put x-scale roundoff bits in EDX .................\n\t;\n\tmov\teax,ecx\t\t\t; get the number of bytes we overran\n\tneg\teax\t\t\t; negate it since overun is negative\n\tadd\teax,[LeftClipBytes]\t; add the number of bytes we leftclip\n\tmul \t[ScaleX]\t\t; convert to pixels plus roundoff bits\n\tmov\tedx,0\t\t\t; clear EDX\n\tmov\tdl,al\t\t\t; DL = x-scaling roundoff bits\n\t;\n\t;................ put negative overrun pixels in ECX ................\n\t;\n\tshr\teax,8\t\t\t; EAX = total # left pixels\n\tsub\teax,[LeftClipPixels]\t; EAX = # pixels overrun\n\tmov\tecx,eax\t\t\t; store # overrun pixels\n\tneg\tecx\t\t\t; make it negative\n\t;\n\t;................ adjust dest ptr by overrun pixels .................\n\t;\n\tsub\tesi,eax\t\t\t; decrement ESI (EDI) by overrun pixels\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tLeft_Scale_Reverse_Skip\n\n\tEND\n\n;**************************** End of ds_lsrs.asm ****************************\n\u001a"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DS_LSS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_LSS.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 2, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Left_Scale_Skip -- Skips past a scaled row of pixels on left side     *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Left_Scale_Skip -- Skips past a scaled row of pixels on left side       *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape (source) buffer data address\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = shape's width\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX - negative # pixels (not bytes) overrun, or 0\t   *\n;*\t\tEDX - XTotal initializer value\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\tEDI - incremented by # pixels (not bytes) overrun\t   *\n;*\t\t[WidthCount] - decremented by # bytes skipped\t\t   *\n;*                                                                         *\n;* The value returned in EDX reflects what XTotal's accumulated value \t   *\n;* should be at the new pixel location.  If no bytes are overrun, this\t   *\n;* will be whatever is stored in [XTotalInit] (which will be 0 if no\t   *\n;* pixels are left-clipped).\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:\tnone                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/08/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tLeft_Scale_Skip NOLANGUAGE NEAR\n\n\tsub \t[WidthCount],ecx\t; we process ECX bytes of real width\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjcxz\t??getrem\t\t; exit if no bytes to skip\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\tshort ??on_run\t\t; if it is a run then deal with it\n\n\t;--------------------------------------------------------------------\n\t; Default exit point: store default x-scale bits & exit\n\t;--------------------------------------------------------------------\n??getrem:\n\tmov\tedx,[XTotalInit]\t; store out the remainder\n\tjmp\tshort ??out \t\t; we're done, get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\tjz\t??getrem\t\t; exactly enough bytes; exit\n\n\t;--------------------------------------------------------------------\n\t; Overrun exit point: ECX is negative by the # of bytes overrun.\n\t; - adjust [WidthCount] by # of overrun bytes\n\t; - compute the remainder at the new location (EDX)\n\t; - compute the number of destination pixels to skip (ECX)\n\t; - adjust EDI by # of overrun bytes\n\t;--------------------------------------------------------------------\n\t;\n\t;............... adjust [WidthCount] by overrun bytes ...............\n\t;\n\tadd\t[WidthCount],ecx\t; adjust overrun in bytes\n\t;\n\t;................. put x-scale roundoff bits in EDX .................\n\t;\n\tmov\teax,ecx\t\t\t; get the number of bytes we overran\n\tneg\teax\t\t\t; negate it since overun is negative\n\tadd\teax,[LeftClipBytes]\t; add the number of bytes we leftclip\n\tmul \t[ScaleX]\t\t; convert to pixels plus roundoff bits\n\tmov\tedx,0\t\t\t; clear EDX\n\tmov\tdl,al\t\t\t; DL = x-scaling roundoff bits\n\t;\n\t;................ put negative overrun pixels in ECX ................\n\t;\n\tshr\teax,8\t\t\t; EAX = total # left pixels\n\tsub\teax,[LeftClipPixels]\t; EAX = # pixels overrun\n\tmov\tecx,eax\t\t\t; store # overrun pixels\n\tneg\tecx\t\t\t; make it negative\n\t;\n\t;................ adjust dest ptr by overrun pixels .................\n\t;\n\tadd\tesi,eax\t\t\t; increment ESI (EDI) by overrun pixels\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tLeft_Scale_Skip\n\n\tEND\n\n;**************************** End of ds_lss.asm *****************************\n\u001a"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DS_RRS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_RRS.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : May 28, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Right_Reverse_Skip -- Skips bytes in a data stream\t\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Right_Reverse_Skip -- Skips bytes in a data stream\t\t\t   *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape buffer data address\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*                                                                         *\n;* WARNINGS:\tThis routine may overrun the number of requested bytes\t   *\n;*\t\tif it encounters a run of 0's; however, it's assumed that  *\n;*\t\tthe shape data will never contain a run that goes past the *\n;*\t\tright-hand edge of the shape.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   05/28/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tRight_Reverse_Skip NOLANGUAGE NEAR\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out\t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tRight_Reverse_Skip\n\n\tEND\n\n;**************************** End of ds_rrs.asm ****************************\n\u001a"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DS_RS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_RS.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : May 28, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Right_Skip -- Skips bytes in a data stream\t\t\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Right_Skip -- Skips bytes in a data stream\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape buffer data address\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*                                                                         *\n;* WARNINGS:\tThis routine may overrun the number of requested bytes\t   *\n;*\t\tif it encounters a run of 0's; however, it's assumed that  *\n;*\t\tthe shape data will never contain a run that goes past the *\n;*\t\tright-hand edge of the shape.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   05/28/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tRight_Skip NOLANGUAGE NEAR\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out\t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tRight_Skip\n\n\tEND\n\n;**************************** End of ds_rs.asm ******************************\n\u001a"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DS_RSRS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_RSRS.ASM                              *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 1, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Right_Scale_Reverse_Skip -- Skips past a scaled row of pixels         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Right_Scale_Reverse_Skip -- Skips past a scaled row of pixels           *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape buffer data address\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*                                                                         *\n;* WARNINGS:\tThis routine may overrun the number of requested bytes\t   *\n;*\t\tif it encounters a run of 0's; however, it's assumed that  *\n;*\t\tthe shape data will never contain a run that goes past the *\n;*\t\tright-hand edge of the shape.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/20/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/01/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tRight_Scale_Reverse_Skip NOLANGUAGE NEAR\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out \t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tRight_Scale_Reverse_Skip\n\n\tEND\n\n;*************************** End of ds_rsrs.asm ****************************\n\u001a"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DS_RSS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_RSS.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 1, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Right_Scale_Skip -- Skips past a scaled row of pixels on right side   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Right_Scale_Skip -- Skips past a scaled row of pixels on the right side *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape buffer data address\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*                                                                         *\n;* WARNINGS:\tThis routine may overrun the number of requested bytes\t   *\n;*\t\tif it encounters a run of 0's; however, it's assumed that  *\n;*\t\tthe shape data will never contain a run that goes past the *\n;*\t\tright-hand edge of the shape.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/20/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/01/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tRight_Scale_Skip NOLANGUAGE NEAR\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out \t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tRight_Scale_Skip\n\n\tEND\n\n;*************************** End of ds_rss.asm *****************************\n\u001a"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/DS_TABLE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_TABLE.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 20, 1993                          *\n;*                                                                         *\n;*                  Last Update : September 6, 1994   [IML]                *\n;*                                                                         *\n;* This module sets up a table of procedure addresses for combinations of  *\n;* NORMAL, HORZ_REV and SCALING\tflags.\t\t\t\t\t   *\t\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************** Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;******************************** Equates **********************************\n;*=========================================================================*/\n;* The following are defines used to control what functions are linked\t   *\n;* in for Draw_Shape.\t\t\t\t\t\t\t   *\n;*=========================================================================*/\nUSE_NORMAL\tEQU\tTRUE\nUSE_HORZ_REV \tEQU\tTRUE\nUSE_VERT_REV \tEQU\tTRUE\nUSE_SCALING \tEQU\tTRUE\n\n\n;---------------------------------------------------------------------------\n;\n; Use a macro to make code a little cleaner.\n; The parameter varname is optional.\n; Syntax to use macro is :\n;  WANT equ expression\n;  USE func [,varname]\n; If the 'varname' is defined, a table declaration is created like:\n;\tGLOBAL\tTableName:DWORD\n; Then, the table entry is created:\n;  If WANT is true, the table entry is created for the given function:\n;\tvarname\tDD\tfunc\n;  If WANT is not TRUE, a Not_Supported entry is put in the table:\n;\tvarname\tDD\tNot_Supported\n; The resulting tables look like:\n;\n;\tGLOBAL\tExampTable:DWORD\n;\tExampTable\tDD\troutine1\n;\t\t\tDD\troutine2\n;\t\t\tDD\troutine3\n;\t\t\t...\n; Thus, each table is an array of function pointers.\n;\n;---------------------------------------------------------------------------\nMACRO USE func, varname\n IFNB <varname>\n\tGLOBAL\tvarname:DWORD\n ENDIF\n IF WANT\n  varname \tDD\tfunc\n ELSE\n  varname\tDD\tNot_Supported\n ENDIF\nENDM\n\n\n;---------------------------------------------------------------------------\n; Data Segment Tables:\n; This code uses the USE macro to set up tables of function addresses.\n; The tables have the following format:\n; Tables defined are:\n;\tLSkipTable\n;\tRSkipTable\n;\tDrawTable\n;---------------------------------------------------------------------------\n\n\tDATASEG\n\n;---------------------------------------------------------------------------\n\nWANT\tequ \t<TRUE>\nUSE\tLeft_Skip, LSkipTable\n\nWANT\tequ \t<TRUE>\nUSE\tLeft_Reverse_Skip\n\nWANT\tequ \t<TRUE>\nUSE\tLeft_Skip\n\nWANT\tequ \t<TRUE>\nUSE\tLeft_Reverse_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tLeft_Scale_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tLeft_Scale_Reverse_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tLeft_Scale_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tLeft_Scale_Reverse_Skip\n;---------------------------------------------------------------------------\n\nWANT\tequ \t<TRUE>\nUSE\tRight_Skip, RSkipTable\n\nWANT\tequ \t<TRUE>\nUSE\tRight_Reverse_Skip\n\nWANT\tequ \t<TRUE>\nUSE\tRight_Skip\n\nWANT\tequ \t<TRUE>\nUSE\tRight_Reverse_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tRight_Scale_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tRight_Scale_Reverse_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tRight_Scale_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tRight_Scale_Reverse_Skip\n;---------------------------------------------------------------------------\n\nWANT\tequ \t<TRUE>\nUSE\tDraw_Normal, DrawTable\n\nWANT\tequ \t<TRUE>\nUSE\tDraw_Reverse\n\nWANT\tequ \t<TRUE>\nUSE\tDraw_Normal\n\nWANT\tequ \t<TRUE>\nUSE\tDraw_Reverse\n\nWANT\tequ \t<USE_SCALING>\nUSE\tDraw_Scale\n\nWANT\tequ \t<USE_SCALING>\nUSE\tDraw_Scale_Reverse\n\nWANT\tequ \t<USE_SCALING>\nUSE\tDraw_Scale\n\nWANT\tequ \t<USE_SCALING>\nUSE\tDraw_Scale_Reverse\n;---------------------------------------------------------------------------\n\n;---------------------------------------------------------------------------\n\tEND\n\n;************************** End of ds_table.asm ****************************\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/EXIT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 library source                   *\n *                                                                         *\n *                    File Name : EXIT.CPP                                 *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Exit -- Exit routine with message.                                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"misc.h\"\n\n#include <stdio.h>\n\n#include <stdlib.h>\n#include <stdarg.h>\n#include <time.h>\n\n\n\n\n/***************************************************************************\n * EXIT -- Exit routine with message.                                      *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/03/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid __cdecl Exit(INT errorval, const char *message, ...)\n{\n\tva_list\t\targptr;\n\tchar\t\terrstring[256];\n\n\tProg_End();\n\n\tif (message && *message) {\n\t\tva_start (argptr, message);\n\t\tvsprintf ((char *)errstring, (const char *)message, argptr);\n\t\tva_end (argptr);\n\t\tprintf(errstring);\n\t}\n\n\t::exit(errorval);\n\n}\n\nvoid randomize\t( void )\n{\n  srand ( time ( NULL ) ) ;\n}\n\n#if(0)\nunsigned long\trandom ( unsigned long mod )\n{\n  return rand () * mod / RAND_MAX ;\n}\n#endif\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FACING16.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/source/rcs/./facing16.asm 1.10 1994/05/20 15:32:36 joe_bostic Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Support Library                          *\n;*                                                                         *\n;*                    File Name : FACING16.ASM                             *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : May 8, 1991                              *\n;*                                                                         *\n;*                  Last Update : February 6, 1995  [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Desired_Facing16 -- Converts coordinates into a facing number.        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\t C Desired_Facing16\t:NEAR\n;\tINCLUDE\t\"wwlib.i\"\n\n\tDATASEG\n\n; 16 direction desired facing lookup table.  Build the index according\n; to the following bits:\n;\n; bit 4 = Is y2 < y1?\n; bit 3 = Is x2 < x1?\n; bit 2 = Is the ABS(x2-x1) < ABS(y2-y1)?\n; bit 1 = Is the lesser absolute difference very close to zero?\n; bit 0 = Is the lesser absolute difference very close to the greater dist?\nNewFacing16\tDB\t 3, 2, 4,-1, 1, 2,0,-1\n\t\tDB\t13,14,12,-1,15,14,0,-1\n\t\tDB\t 5, 6, 4,-1, 7, 6,8,-1\n\t\tDB\t11,10,12,-1, 9,10,8,-1\n\n\tCODESEG\n\n;***************************************************************************\n;* DESIRED_FACING16 -- Converts coordinates into a facing number.          *\n;*                                                                         *\n;*      This converts coordinates into a desired facing number that ranges *\n;*      from 0 to 15 (0 equals North and going clockwise).                 *\n;*                                                                         *\n;* INPUT:       x1,y1   -- Position of origin point.                       *\n;*                                                                         *\n;*              x2,y2   -- Position of target.                             *\n;*                                                                         *\n;* OUTPUT:      Returns desired facing as a number from 0 to 255 but       *\n;*              accurate to 22.5 degree increments.                        *\n;*                                                                         *\n;* WARNINGS:    If the two coordinates are the same, then -1 will be       *\n;*              returned.  It is up to you to handle this case.            *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/14/1991 JLB : Created.                                             *\n;*=========================================================================*\n; long Desired_Facing16(long x1, long y1, long x2, long y2);\n\n\tPROC\tDesired_Facing16 C near\n\tUSES\tebx, ecx, edx\n\n\tARG\tx1:DWORD\n\tARG\ty1:DWORD\n\tARG\tx2:DWORD\n\tARG\ty2:DWORD\n\n\txor\tebx,ebx\t\t\t; Index byte (built).\n\n\t; Determine Y axis difference.\n\tmov\tedx,[y1]\n\tmov\tecx,[y2]\n\tsub\tedx,ecx\t\t\t; DX = Y axis (signed).\n\tjns\tshort ??absy\n\tinc\tebx\t\t\t; Set the signed bit.\n\tneg\tedx\t\t\t; ABS(y)\n??absy:\n\n\t; Determine X axis difference.\n\tshl\tebx,1\n\tmov\teax,[x1]\n\tmov\tecx,[x2]\n\tsub\tecx,eax\t\t\t; CX = X axis (signed).\n\tjns\tshort ??absx\n\tinc\tebx\t\t\t; Set the signed bit.\n\tneg\tecx\t\t\t; ABS(x)\n??absx:\n\n\t; Determine the greater axis.\n\tcmp\tecx,edx\n\tjb\tshort ??dxisbig\n\txchg\tecx,edx\n??dxisbig:\n\trcl\tebx,1\t\t\t; Y > X flag bit.\n\n\t; Determine the closeness or farness of lesser axis.\n\tmov\teax,edx\n\tinc\teax\t\t\t; Round up.\n\tshr\teax,1\n\tinc\teax\t\t\t; Round up.\n\tshr\teax,1\t\t\t; 1/4 of greater axis.\n\n\tcmp\tecx,eax\n\trcl\tebx,1\t\t\t; Very close to major axis bit.\n\n\tsub\tedx,eax\n\tcmp\tedx,ecx\n\trcl\tebx,1\t\t\t; Very far from major axis bit.\n\n\txor\teax,eax\n\tmov\tal,[NewFacing16+ebx]\n\n\t; Normalize to 0..FF range.\n\tshl\teax,4\n\n\tret\n\n\tENDP\tDesired_Facing16\n\n\tEND\n\n\n\u001a"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FACING8.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Support Library                          *\n;*                                                                         *\n;*                    File Name : FACING8.ASM                              *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : May 8, 1991                              *\n;*                                                                         *\n;*                  Last Update : February 6, 1995  [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Desired_Facing8 -- Determines facing to reach a position.             *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nGLOBAL\t C Desired_Facing8\t:NEAR\n;\tINCLUDE\t\"wwlib.i\"\n\n\tDATASEG\n\n; 8 direction desired facing lookup table.  Build the index according\n; to the following bits:\n;\n; bit 3 = Is y2 < y1?\n; bit 2 = Is x2 < x1?\n; bit 1 = Is the ABS(x2-x1) < ABS(y2-y1)?\n; bit 0 = Is the facing closer to a major axis?\nNewFacing8\tDB\t1,2,1,0,7,6,7,0,3,2,3,4,5,6,5,4\n\n\tCODESEG\n\n;***************************************************************************\n;* DESIRED_FACING8 -- Determines facing to reach a position.               *\n;*                                                                         *\n;*    This routine will return with the most desirable facing to reach     *\n;*    one position from another.  It is accurate to a resolution of 0 to   *\n;*    7.                                                                   *\n;*                                                                         *\n;* INPUT:       x1,y1   -- Position of origin point.                       *\n;*                                                                         *\n;*              x2,y2   -- Position of target.                             *\n;*                                                                         *\n;* OUTPUT:      Returns desired facing as a number from 0..255 with an     *\n;*              accuracy of 32 degree increments.                          *\n;*                                                                         *\n;* WARNINGS:    If the two coordinates are the same, then -1 will be       *\n;*              returned.  It is up to you to handle this case.            *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1991 JLB : Documented.                                          *\n;*   08/08/1991 JLB : Same position check.                                 *\n;*   08/14/1991 JLB : New algorithm                                        *\n;*   02/06/1995 BWG : Convert to 32-bit                                    *\n;*=========================================================================*\n; long Desired_Facing8(long x1, long y1, long x2, long y2);\n\n\tPROC\tDesired_Facing8 C near\n\tUSES\tebx, ecx, edx\n\n\tARG\tx1:DWORD\n\tARG\ty1:DWORD\n\tARG\tx2:DWORD\n\tARG\ty2:DWORD\n\n\txor\tebx,ebx\t\t\t; Index byte (built).\n\n\t; Determine Y axis difference.\n\tmov\tedx,[y1]\n\tmov\tecx,[y2]\n\tsub\tedx,ecx\t\t\t; DX = Y axis (signed).\n\tjns\tshort ??absy\n\tinc\tebx\t\t\t; Set the signed bit.\n\tneg\tedx\t\t\t; ABS(y)\n??absy:\n\n\t; Determine X axis difference.\n\tshl\tebx,1\n\tmov\teax,[x1]\n\tmov\tecx,[x2]\n\tsub\tecx,eax\t\t\t; CX = X axis (signed).\n\tjns\tshort ??absx\n\tinc\tebx\t\t\t; Set the signed bit.\n\tneg\tecx\t\t\t; ABS(x)\n??absx:\n\n\t; Determine the greater axis.\n\tcmp\tecx,edx\n\tjb\tshort ??dxisbig\n\txchg\tecx,edx\n??dxisbig:\n\trcl\tebx,1\t\t\t; Y > X flag bit.\n\n\t; Determine the closeness or farness of lesser axis.\n\tmov\teax,edx\n\tinc\teax\t\t\t; Round up.\n\tshr\teax,1\n\n\tcmp\tecx,eax\n\trcl\tebx,1\t\t\t; Close to major axis bit.\n\n\txor\teax,eax\n\tmov\tal,[NewFacing8+ebx]\n\n\t; Normalize to 0..FF range.\n\tshl\teax,5\n\n\tret\n\n\tENDP\tDesired_Facing8\n\n\n\tEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FACINGFF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Support Library                          *\n;*                                                                         *\n;*                    File Name : FACINGFF.ASM                             *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : May 8, 1991                              *\n;*                                                                         *\n;*                  Last Update : February 6, 1995  [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Desired_Facing256 -- Determines facing to reach a position.           *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\tC Desired_Facing256\t:NEAR\n;\tINCLUDE\t\"wwlib.i\"\nINCLUDE \"..\\include\\gbuffer.inc\"\n\n\tCODESEG\n\n;***************************************************************************\n;* Desired_Facing256 -- Desired facing algorithm 0..255 resolution.        *\n;*                                                                         *\n;*    This is a desired facing algorithm that has a resolution of 0        *\n;*    through 255.                                                         *\n;*                                                                         *\n;* INPUT:   srcx,srcy   -- Source coordinate.                              *\n;*                                                                         *\n;*          dstx,dsty   -- Destination coordinate.                         *\n;*                                                                         *\n;* OUTPUT:  Returns with the desired facing to face the destination        *\n;*          coordinate from the position of the source coordinate.  North  *\n;*          is 0, East is 64, etc.                                         *\n;*                                                                         *\n;* WARNINGS:   This routine is slower than the other forms of desired      *\n;*             facing calculation.  Use this routine when accuracy is      *\n;*             required.                                                   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   12/24/1991 JLB : Adapted.                                             *\n;*=========================================================================*/\n; LONG cdecl Desired_Facing256(LONG srcx, LONG srcy, LONG dstx, LONG dsty)\n\tPROC\tDesired_Facing256 C near\n\tUSES\tebx, ecx, edx\n\n\tARG\tsrcx:DWORD\n\tARG\tsrcy:DWORD\n\tARG\tdstx:DWORD\n\tARG\tdsty:DWORD\n\n\txor\tebx,ebx\t\t\t; Facing number.\n\n\t; Determine absolute X delta and left/right direction.\n\tmov\tecx,[dstx]\n\tsub\tecx,[srcx]\n\tjge\tshort ??xnotneg\n\tneg\tecx\n\tmov\tebx,11000000b\t\t; Set bit 7 and 6 for leftward.\n??xnotneg:\n\n\t; Determine absolute Y delta and top/bottom direction.\n\tmov\teax,[srcy]\n\tsub\teax,[dsty]\n\tjge\tshort ??ynotneg\n\txor\tebx,01000000b\t\t; Complement bit 6 for downward.\n\tneg\teax\n??ynotneg:\n\n\t; Set DX=64 for quadrants 0 and 2.\n\tmov\tedx,ebx\n\tand\tedx,01000000b\n\txor\tedx,01000000b\n\n\t; Determine if the direction is closer to the Y axis and make sure that\n\t; CX holds the larger of the two deltas.  This is in preparation for the\n\t; divide.\n\tcmp\teax,ecx\n\tjb\tshort ??gotaxis\n\txchg\teax,ecx\n\txor\tedx,01000000b\t\t; Closer to Y axis so make DX=64 for quad 0 and 2.\n??gotaxis:\n\n\t; If closer to the X axis then add 64 for quadrants 0 and 2.  If\n\t; closer to the Y axis then add 64 for quadrants 1 and 3.  Determined\n\t; add value is in DX and save on stack.\n\tpush\tedx\n\n\t; Make sure that the division won't overflow.  Reduce precision until\n\t; the larger number is less than 256 if it appears that an overflow\n\t; will occur.  If the high byte of the divisor is not zero, then this\n\t; guarantees no overflow, so just abort shift operation.\n\ttest\teax,0FFFFFF00h\n\tjnz\tshort ??nooverflow\n??again:\n\ttest\tecx,0FFFFFF00h\n\tjz\tshort ??nooverflow\n\tshr\tecx,1\n\tshr\teax,1\n\tjmp\tshort ??again\n??nooverflow:\n\n\t; Make sure that the division won't underflow (divide by zero).  If\n\t; this would occur, then set the quotient to $FF and skip divide.\n\tor\tecx,ecx\n\tjnz\tshort ??nounderflow\n\tmov\teax,0FFFFFFFFh\n\tjmp\tshort ??divcomplete\n\n\t; Derive a pseudo angle number for the octant.  The angle is based\n\t; on $00 = angle matches long axis, $00 = angle matches $FF degrees.\n??nounderflow:\n\txor\tedx,edx\n\tshld\tedx,eax,8\t; shift high byte of eax into dl\n\tshl\teax,8\n\tdiv\tecx\n??divcomplete:\n\n\t; Integrate the 5 most significant bits into the angle index.  If DX\n\t; is not zero, then it is 64.  This means that the dividend must be negated\n\t; before it is added into the final angle value.\n\tshr\teax,3\n\tpop\tedx\n\tor\tedx,edx\n\tje\tshort ??noneg\n\tdec\tedx\n\tneg\teax\n??noneg:\n\tadd\teax,edx\n\tadd\teax,ebx\n\tand\teax,0FFH\n\tret\n\n\tENDP\tDesired_Facing256\n\n\n\n\tEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FADING.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : FADING.ASM                               *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : August 20, 1993                          *\n;*                                                                         *\n;*                  Last Update : August 20, 1993   [JLB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\tC Build_Fading_Table\t:NEAR\n\n\tCODESEG\n\n;***********************************************************\n; BUILD_FADING_TABLE\n;\n; void *Build_Fading_Table(void *palette, void *dest, long int color, long int frac);\n;\n; This routine will create the fading effect table used to coerce colors\n; from toward a common value.  This table is used when Fading_Effect is\n; active.\n;\n; Bounds Checking: None\n;*\n\tPROC\tBuild_Fading_Table C near\n\tUSES\tebx, ecx, edi, esi\n\tARG\tpalette:DWORD\n\tARG\tdest:DWORD\n\tARG\tcolor:DWORD\n\tARG\tfrac:DWORD\n\n\tLOCAL\tmatchvalue:DWORD\t; Last recorded match value.\n\tLOCAL\ttargetred:BYTE\t\t; Target gun red.\n\tLOCAL\ttargetgreen:BYTE\t; Target gun green.\n\tLOCAL\ttargetblue:BYTE\t\t; Target gun blue.\n\tLOCAL\tidealred:BYTE\n\tLOCAL\tidealgreen:BYTE\n\tLOCAL\tidealblue:BYTE\n\tLOCAL\tmatchcolor:BYTE\t\t; Tentative match color.\n\n\tcld\n\n\t; If the source palette is NULL, then just return with current fading table pointer.\n\tcmp\t[palette],0\n\tje\t??fini\n\tcmp\t[dest],0\n\tje\t??fini\n\n\t; Fractions above 255 become 255.\n\tmov\teax,[frac]\n\tcmp\teax,0100h\n\tjb\tshort ??ok\n\tmov\t[frac],0FFh\n??ok:\n\n\t; Record the target gun values.\n\tmov\tesi,[palette]\n\tmov\tebx,[color]\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tlodsb\n\tmov\t[targetred],al\n\tlodsb\n\tmov\t[targetgreen],al\n\tlodsb\n\tmov\t[targetblue],al\n\n\t; Main loop.\n\txor\tebx,ebx\t\t\t; Remap table index.\n\n\t; Transparent black never gets remapped.\n\tmov\tedi,[dest]\n\tmov\t[edi],bl\n\tinc\tedi\n\n\t; EBX = source palette logical number (1..255).\n\t; EDI = running pointer into dest remap table.\n??mainloop:\n\tinc\tebx\n\tmov\tesi,[palette]\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\n\tmov\tedx,[frac]\n\tshr\tedx,1\n\t; new = orig - ((orig-target) * fraction);\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetred]\t\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\tax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealred],dh\t\t; preserve ideal color gun value.\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetgreen]\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\tax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealgreen],dh\t\t; preserve ideal color gun value.\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetblue]\t\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\tax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealblue],dh\t\t; preserve ideal color gun value.\n\n\t; Sweep through the entire existing palette to find the closest\n\t; matching color.  Never matches with color 0.\n\n\tmov\teax,[color]\n\tmov\t[matchcolor],al\t\t; Default color (self).\n\tmov\t[matchvalue],-1\t\t; Ridiculous match value init.\n\tmov\tecx,255\n\n\tmov\tesi,[palette]\t\t; Pointer to original palette.\n\tadd\tesi,3\n\n\t; BH = color index.\n\tmov\tbh,1\n??innerloop:\n\n\t; Recursion through the fading table won't work if a color is allowed\n\t; to remap to itself.  Prevent this from occuring.\n\tadd\tesi,3\n\tcmp\tbh,bl\n\tje\tshort ??notclose\n\tsub\tesi,3\n\n\txor\tedx,edx\t\t\t; Comparison value starts null.\n\tmov\teax,edx\n\t; Build the comparison value based on the sum of the differences of the color\n\t; guns squared.\n\tlodsb\n\tsub\tal,[idealred]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\n\tlodsb\n\tsub\tal,[idealgreen]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\n\tlodsb\n\tsub\tal,[idealblue]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\tjz\tshort ??perfect\t\t; If perfect match found then quit early.\n\n\tcmp\tedx,[matchvalue]\n\tja\tshort ??notclose\n\tmov\t[matchvalue],edx\t; Record new possible color.\n\tmov\t[matchcolor],bh\n??notclose:\n\tinc\tbh\t\t\t; Checking color index.\n\tloop\t??innerloop\n\tmov\tbh,[matchcolor]\n??perfect:\n\tmov\t[matchcolor],bh\n\txor\tbh,bh\t\t\t; Make BX valid main index again.\n\n\t; When the loop exits, we have found the closest match.\n\tmov\tal,[matchcolor]\n\tstosb\n\tcmp\tebx,255\n\tjne\t??mainloop\n\n??fini:\n\tmov\teax,[dest]\n\tret\n\n\tENDP\tBuild_Fading_Table\n\n\n\tEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FFIRST.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : First First\t\t\t\t   *\n;*                                                                         *\n;*                    File Name : FFIRST.ASM                               *\n;*                                                                         *\n;*                   Programmer : Jeff Wilson                              *\n;*                                                                         *\n;*                   Start Date : March 28, 1994                           *\n;*                                                                         *\n;*                  Last Update : April 15, 1994   []                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Find_First -- Find a file spec                                        *\n;*   Find_Next -- Find next file in sreach params                          *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nLOCALS ??\n\nGLOBAL             Find_First         :NEAR\nGLOBAL             Find_Next          :NEAR\n\t\t    \n;============================================================================\nCODESEG\n\n\n;***************************************************************************\n;* FIND_FIRST -- Find a file spec                                          *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*\tfile_name\t\tFile spec to find. Maybe a wildcard name   *\n;*      mode                    File type                                  *\n;*      ffblk                   file data block ptr to write info into     *\n;*                                                                         *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/15/1994  jaw: Created.                                             *\n;*=========================================================================*\n\nPROC Find_First \tC near \n     \tUSES ebx,ecx,edx,esi,edi,es,ds\n     \tARG file_name:DWORD,mode:WORD,ffblk:DWORD\n     \t   \n     \tmov\tedx,[file_name]\n     \tmov\tcx,[mode]\n     \t\t\n     \tmov\teax,4e00h\t\t;first firstg function\n     \t\n     \tint\t21h\n     \t\t\t\t\t;Find it?\n     \tjnc\t??found_it\t\t;=>yes\n     \t\n\t; ax holds the error code\n\t;insure high word of eax is clear\n\tor\teax,0ffffffffh\n\tjmp\t??exit\n\t\n??found_it:\n     \t; found something\n     \t;copy the DTA into the user block\n     \tmov\teax,2f00h\t;get DTA address\n     \tint\t21h\n     \t\n     \tmov\tax,es\t\t;switch selectors\n     \tmov\tdx,ds\n     \tmov\tds,ax\n     \tmov\tes,dx\n     \n     \tmov\tesi,ebx\n     \tmov\tedi,[ffblk]\n     \t\n\tadd\tesi,21\t\t;SKIP RESERVED\n\tadd\tedi,4\t\t;SKIP RESERVED\n\t\t \n\tsub\teax,eax\n\tmov\tal,[esi]\t;get attrib byte\n\tmov\t[es:edi+4],eax\n\tinc\tesi\n\t\n\t;get time\n\tmov\tax,[esi]\n\tadd\tesi,2\n\tmov\t[es:edi+8],ax\n\t\n\t;get date\n\tmov\tax,[esi]\n\tadd\tesi,2\n\tmov\t[es:edi+10],ax\n\t\n\t;get file size\n\tmov\teax,[esi]\n\tadd\tesi,4\n\tmov\t[es:edi],eax\n\t\n\tadd\tedi,12\n\t\t    \n     \tmov\tecx,13\n     \t\t    \n     \trep\tmovsb\t\t;copy the DTA name\n     \t\n     \tmov\tax,es\n     \tmov\tds,ax\n     \t\n \txor\teax,eax\n??exit:\t\n\tret\n;====================\nENDP Find_First\t\n\n\n\n;***************************************************************************\n;* FIND_NEXT -- Find next file in sreach params                            *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*              NONE                                                       *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/15/1994  jaw: Created.                                             *\n;*=========================================================================*\n     \nPROC Find_Next C near\n\tUSES ebx,ecx,edx,esi,edi,ds,es\n\t\n     \tARG ffblk:DWORD\n     \t    \n\tmov\teax,04f00h\t\t;Find Next function\n\t\n\tint 21h\n\t       \t\t\t\t;Find anything?\n     \tjnc\t??found_it\t\t;=>no\n     \t\n\t; ax holds the error code\n\t;insure high word of eax is clear\n\tor\teax,0ffffffffh\n\tjmp\t??exit\n\t\n??found_it:\n     \t; found something\n     \t;copy the DTA into the user block\n     \tmov\teax,2f00h\t\t;get DTA address\n     \tint\t21h\n     \t\n     \tmov\tax,es\t\t\t;switch selectors\n     \tmov\tdx,ds\n     \tmov\tds,ax\n     \tmov\tes,dx\n     \n     \tmov\tesi,ebx\n     \tmov\tedi,[ffblk]\n     \t\n\tadd\tesi,21\t\t\t;SKIP RESERVED\n\tadd\tedi,4\t\t\t;SKIP RESERVED\n\t\t \n\tsub\teax,eax\n\tmov\tal,[esi]\t\t;get attrib byte\n\tmov\t[es:edi+4],eax\n\tinc\tesi\n\t\n\t;get time\n\tmov\tax,[esi]\n\tadd\tesi,2\n\tmov\t[es:edi+8],ax\n\t\n\t;get date\n\tmov\tax,[esi]\n\tadd\tesi,2\n\tmov\t[es:edi+10],ax\n\t\n\t;get file size\n\tmov\teax,[esi]\n\tadd\tesi,4\n\tmov\t[es:edi],eax\n\t\n\tadd\tedi,12\n\t\t    \n     \tmov\tecx,13\n     \t\t    \n     \trep\tmovsb\t\t;copy the DTA name\n     \t\n     \tmov\tax,es\n     \tmov\tds,ax\n     \t\n\txor\teax,eax\n??exit:\t\n\tret\n\t\nENDP Find_Next\n\n\nEND\n\n\n\n\n\u001a\n\n\u001a\n\u001a\n\u001a"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FFIXSEL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Fix a selector                           *\n;*                                                                         *\n;*                    File Name : FFIXSEL.ASM                              *\n;*                                                                         *\n;*                   Programmer : Jeff Wilson                              *\n;*                                                                         *\n;*                   Start Date : March 28, 1994                           *\n;*                                                                         *\n;*                  Last Update : March 28, 1994   []                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   FixSelector -- Fix the Priviledge level of a selector                 *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nEXTRN\t\t   exit\t\t\t: near\nGLOBAL             FixSelector          :NEAR\n\n;============================================================================\nCODESEG\n\n;***************************************************************************\n;* FIXSELECTOR -- Fix the Priviledge level of a selector                   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:  sel          the selector to fix-up                             *\n;*                                                                         *\n;* OUTPUT: UWORD        The fixed up selector                              *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/28/1994  jaw  Created.                                             *\n;*=========================================================================*\n\nPROC FixSelector \tC near \n\n\tUSES ecx,edx\n\t      \n\tARG\tsel:WORD\n\t\t\n;  Copy the Table Bit and IOPL from the Current CS\n\n; Something is wrong the program should not be here unthe any circunstance\t\n;\tmovzx\tecx,[sel]\n;\txor\teax,eax\n;\tmov\tax,cs\n;\tand\tax,7\n;\tor\tax,cx\npush 0\ncall exit\n\t\n\tret\n;====================\nENDP FixSelector\t\n\n\n\nEND\n\n\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FGETCS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Get the code selector                    *\n;*                                                                         *\n;*                    File Name : FGETCS.ASM                               *\n;*                                                                         *\n;*                   Programmer : Jeff Wilson                              *\n;*                                                                         *\n;*                   Start Date : March 28, 1994                           *\n;*                                                                         *\n;*                  Last Update : March 28, 1994   []                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   GetCs -- Return the current Data selector.                            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nGLOBAL             GetCs          :NEAR\n\t\t       \n;============================================================================\nCODESEG\n\n;***************************************************************************\n;* GETCS -- Return the current Data selector.                              *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT: NONE                                                             *\n;*                                                                         *\n;* OUTPUT: UWORD        selector of the default code segment               *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/28/1994  jaw: Created.                                             *\n;*=========================================================================*\n\nPROC GetCs \tC near \n     \t\n\txor\teax,eax\n\tmov\tax,cs\n\tret\t   \n;====================\nENDP GetCs\t\n\t\n\nEND\n\n\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FGETDS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Get the data selector                    *\n;*                                                                         *\n;*                    File Name : FGETDS.ASM                               *\n;*                                                                         *\n;*                   Programmer : Jeff Wilson                              *\n;*                                                                         *\n;*                   Start Date : March 28, 1994                           *\n;*                                                                         *\n;*                  Last Update : March 28, 1994   []                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   GetDs -- Return the current Data selector.                            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nGLOBAL             GetDs          :NEAR\n\t\t    \n;============================================================================\nCODESEG\n\n;***************************************************************************\n;* GETDS -- Return the current Data selector.                              *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT: NONE                                                             *\n;*                                                                         *\n;* OUTPUT: UWORD        selector of the default data segment               *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/28/1994  jaw: Created.                                             *\n;*=========================================================================*\n\nPROC GetDs \tC near \n     \n\txor\teax,eax\n\tmov\tax,ds\n\tret\n;====================\nENDP GetDs\t\n\n\nEND\n\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FGETSEL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Get the Defines selectors\t\t   *\n;*                                                                         *\n;*                    File Name : FGETSEL.ASM                              *\n;*                                                                         *\n;*                   Programmer : Jeff Wilson                              *\n;*                                                                         *\n;*                   Start Date : March 28, 1994                           *\n;*                                                                         *\n;*                  Last Update : March 28, 1994   []                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   GetDefaultSelectors -- Return the current default selectors. \t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nGLOBAL      GetDefaultSelectors :NEAR\n\nGLOBAL \t    DataSelector\t:WORD\nGLOBAL \t    ScreenSelector\t:WORD\nGLOBAL \t    GraphicsSelector\t:WORD\nGLOBAL \t    PspSelector\t\t:WORD\nGLOBAL \t    EnvSelector\t\t:WORD\nGLOBAL \t    DosMemSelector\t:WORD\nGLOBAL \t    Fp1167Selector\t:WORD\nGLOBAL \t    FpWeitekSelector\t:WORD\nGLOBAL \t    FpCyrixSelector\t:WORD\nGLOBAL \t    CodeSelector\t:WORD\n\n\nDATASEG\n\n; It is very important that this section remain untouch\n; is not really needed by Rational System but is here to\n; keep compatibility with the TNT dos extender.\nDataSelector\t\tdw\t0\nScreenSelector\t\tdw\t0\nGraphicsSelector\tdw\t0\n\nPspSelector\t\tdw\t0\nEnvSelector\t\tdw\t0\nDosMemSelector\t\tdw\t0\n\nFp1167Selector\t\tdw\t0\nFpWeitekSelector\tdw\t0\nFpCyrixSelector\t\tdw\t0\n\nCodeSelector\t\tdw\t0\n\n\t\t    \n;============================================================================\nCODESEG\n\n;***************************************************************************\n;*  GetDefaultSelectors -- Setup the defaults selector values to have the  *\n;*    Correct Descriptor table and IOPL.\t\t\t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT: NONE                                                             *\n;*                                                                         *\n;* OUTPUT: \t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/28/1994  jaw: Created.                                             *\n;*=========================================================================*\n\nPROC GetDefaultSelectors \tC near \n\tUSES eax,esi,ecx\n\n\tlea\tedi,[DataSelector]\n\tlea\tecx,[CodeSelector]\n \tsub\tecx,edi\n\tshr\tecx,1\n\tmov\tax,ds\n\trep\tstosw\n\tmov\tax,cs\n\tmov\t[word ptr CodeSelector] , ax\n     \n\tret\t   \n;====================\nENDP GetDefaultSelectors\t\n     \n\nEND\n\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FGLOB2.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : FILEIO Library                           *\n *                                                                         *\n *                    File Name : FILEGLOB.C                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 11, 1994                           *\n *                                                                         *\n *                  Last Update : April 11, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"_file.h\"\n\n/* Global varaiables */\nWORD Hard_Error_Occured=0;\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library                                  *\n *                                                                         *\n *                    File Name : FILE.CPP                                 *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : September 13, 1993                       *\n *                                                                         *\n *                  Last Update : September 13, 1993   [SKB]               *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   File_Exists -- Searches for and FINDS the specified file.             *\n *   File_Size -- Determine the size of the specified file.                *\n *   Open_File -- Opens a file for access.                                 *\n *   Close_File -- Closes a file previously opened with Open_File.         *\n *   Seek_File -- Adjusts the position of the file pointer.                *\n *   Read_File -- Reads a block of data from a file.                       *\n *   Write_File -- Writes a block of data to a file.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#include <wwstd.h>\n#endif\t   \n\n#ifndef FILE_H\n#include \"_file.h\"\n#endif\n\n#ifndef WWMEM_H\n#include <wwmem.h>\n#endif\n\n\n#include <fcntl.h>\n#include <io.h>\n#include <sys\\stat.h>\n\n#define DEBUGPRINT FALSE\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * OPEN_FILE -- Opens a file for access.                                   *\n *                                                                         *\n *    This routine will open the specified file for access.  It functions  *\n *    in a similar manner to the regular DOS open command.                 *\n *                                                                         *\n * INPUT:   filename -- Pointer to the filename to open.                   *\n *                                                                         *\n *          mode     -- Access mode to use.                                *\n *             READ: A file opened for READ access, MUST be available.     *\n *                   This may cause a disk swap message to appear.         *\n *                                                                         *\n *             WRITE:A file opened for WRITE access (only), need not be    *\n *                   available.  If it can't be found, then it will be     *\n *                   created in the current directory.                     *\n *                                                                         *\n * OUTPUT:  Returns with the westwood file handle.  If ERROR is returned   *\n *          it means that the programmer took over the file error handler  *\n *          and signaled that an open access failure should not keep trying*\n *          for success.                                                   *\n *                                                                         *\n * WARNINGS:   If you take over the file error handling code, you must be  *\n *             sure to anticipate a possible ERROR value being returned.   *\n *             If you open a file for READ or READ|WRITE, then the file    *\n *             must previously exist.  To create a file for read and write *\n *             access, first open it for WRITE, then re-open it for        *\n *             read and write.                                             *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/11/1991 JLB : Created.                                             *\n *=========================================================================*/\nWORD cdecl Open_File(BYTE const *file_name, WORD mode)\n{\n\tWORD\t\t\t\t\t\t\tfile_handle;\t\t\t\t// Westwood file handle.\n\tWORD\t\t\t\t\t \t\thandle;\t\t\t\t\t\t// DOS file handle.\n\tUWORD\t\t\t\t \t\t\tlocal_mode;\t\t\t\t\t// DOS access mode number.\n\tWORD\t\t\t\t\t\t\tindex;\t\t\t\t\t\t// FileData index (if available).\n\tBOOL\t\t\t\t\t\t\timmediate;\t\t\t\t\t// Is the file immediately available?\n\tFileDataType\t\t\t\t*filedata;\t\t\t\t\t// Pointer to the current FileData.\n\tFileDataType\t\t\t\t*parent;\t\t\t\t\t\t// Pointer to the current FileData.\n\tFileHandleType\t\t\t\t*filehandletable;\t\t\t// Pointer to the current file handle.\n\n\tCallingDOSInt++;\n\n\n\t#if(DEBUGPRINT)\n\t\tMono_Printf(\"Open_File('%s')\\r\", file_name);\n\t#endif\n\n\t/*\n\t** Is there a slot in the FileHandleTable?  If not, then exit with\n\t**\ta file error.\n\t*/\n\tfilehandletable = FileHandleTable;\n\tfor (file_handle = 0; file_handle < TABLE_MAX; file_handle++, filehandletable++) {\n\t\tif (filehandletable->Empty) break;\n\t}\n\tif (file_handle == TABLE_MAX) {\n \t\tDo_IO_Error(TOO_MANY_FILES, file_name);\n\t}\n\n\t/*\n\t**\tFind the file in the FileTable (if it exists there).\n\t*/\n\tindex = Find_File_Index(file_name);\n\tfiledata = &FileDataPtr[index];\n\n\t// Start out looking at the start drive.\n\tibm_setdisk(*StartPath - 'A');\n\n\t/*\n\t**\tIf the file exists in the current directory, then by all\n\t**\tmeans, use that file instead of any corresponding pack\n\t**\tfile representation.  This is used as a means of\n\t**\toverriding packed files (quite handy).\n\t*/\n\timmediate = FALSE;\n\n\t/*\n\t**\tCheck the current directory by attempting to open with READ access.\n\t** Only check if the file is not already cached and it is a packed file.\n\t*/\n\tif ((index != ERROR) && (filedata->Flag & FILEF_PACKED) && (!filedata->Ptr)) \n\t{\n\t\tWORD\thandle2;\n\t\n\t\thandle2 = FILEOPEN(file_name, MODE_OLDFILE);\n\t\tif (handle2 != FILEOPENERROR) {\n\t\t\tFILECLOSE(handle2);\n\t\t\timmediate = TRUE;\n\t\t}\n\t}\n\n\n\t/*\n\t** Check to see if any WRITE permission is requested for the\n\t**\tfile.  If so, delete the file from RAM and mark it as non-resident.\n\t**\n\t**\tNOTE:\tIf the file is packed, we CAN NOT alter it in ANY way.\n\t**\t\t\tWe will return an ERROR to the user, and hope he/she is\n\t**\t\t\tsmart enough to handle it.\n\t*/\n\tif ((mode & WRITE) && index != ERROR && filedata->Ptr) {\n\t\tif(filedata->Flag & FILEF_PACKED) {\t\t// is file packed?\n\t\t\tMem_Free(FileCacheHeap, filedata->Ptr);\t\t\t\t\t\t\n\t\t\tfiledata->Ptr = NULL;\n\t\t} else {\t\t\t\t\t\t\t\t\t\t\t\t\t// file is packed\n\t\t\tDo_IO_Error(WRITING_RESIDENT, file_name);\n\t\t}\n\t}\n\n\t// If the file is cached already, then let us use it and leave.\n\tif (filedata->Ptr && index != ERROR) {\n\t\t/*\n\t\t**\tFile is resident.  Initialize the local table.\n\t\t*/\n\t\tfilehandletable->Index = index;\n\t\tfilehandletable->Empty = FALSE;\n\t\tfilehandletable->Pos = 0L;\n\t\tfilehandletable->Name = filedata->Name;\n\t\tfilehandletable->Handle = 0;\t// Resident flag.\n\t\tfilehandletable->Mode = mode;\n\n\t\t// If the cached file is packed and its parent is resident, then\n\t\t// add one to the parent open count.\n\t\tif (filedata->Flag & FILEF_PACKED) {\n\t\t\tparent = &FileDataPtr[filedata->Disk];\n\t\t}\n\t\telse {\n\t\t\tparent = NULL;\n\t\t}\n\n\t\tif (parent && (parent->Ptr == filedata->Ptr)) {\n\t\t\tfilehandletable->Start = filedata->Start;\n\t\t\tparent->OpenCount++;\n\t\t} else {\n\t\t\tfilehandletable->Start = 0;\n\t\t}\n\n\t\t// Mark the pointer in use so that it is never returned as the oldest\n\t\t// pointer location in memory.\n\t\tMem_In_Use(filedata->Ptr);\n\n\t} else {\n\t\t\n\t\t/*\n\t\t** At this time we determine if it is a packed file.  If so, the\n\t\t**\topening process takes a dramatically different turn.\n\t\t*/\n\t\tif (index != ERROR && (filedata->Flag & FILEF_PACKED) && !immediate && (mode & WRITE) == 0) {\n\n\t\t\t/*\n\t\t\t**\tThis is a packed file.  Perform recursive open process to reach\n\t\t\t**\tthe parent packed file.\n\t\t\t*/\n\t\t\tparent = &FileDataPtr[filedata->Disk];\n\t\t\tfile_handle = Open_File(parent->Name, mode);\n\n\t\t\t// Reread the parents information.\n\t\t\tparent = &FileDataPtr[filedata->Disk];\n\t\t\tfilehandletable = &FileHandleTable[file_handle];\n\n\t\t\t/*\n\t\t\t**\tProcess the packed file header.  Update the start offset for every\n\t\t\t**\tfile ellaborated in the packed file.  \n\t\t\t**\tException:  When a file is specified in the packed file and an\n\t\t\t**\t\t\t\t\tentry exists for it in the file table, BUT the entry\n\t\t\t**\t\t\t\t\tis not marked as packed, THEN ignore the packed version\n\t\t\t**\t\t\t\t\tof the file.\n\t\t\t*/\n\n\t\t\tif (FileData == FileDataPtr && \n\t\t\t    !(FileDataPtr[filehandletable->Index].Flag & FILEF_PROCESSED)) {\n\t\t\t\tLONG\toffset;\t\t\t\t\t// Offset of sub-file start.\n\t\t\t\tWORD\ti;\t\t\t\t\t\t\t// Sub-file FileData index.\n\t\t\t\tBYTE\tname[FILENAMESIZE];\t// Name of sub-file.\n\t\t\t\tFileDataType\t*cur=NULL;\t// Current entry in FileData.\n\t\t\t\tFileDataType\t*last=NULL;\t// Last entry in FileData.\n\n\n\t\t\t\t#if(DEBUGPRINT)\n\t\t\t\t\tMono_Printf(\"Processing packed file '%s'\\r\", FileDataPtr[filedata->Disk].Name); \n\t\t\t\t#endif\n\n\t\t\t\tRead_File(file_handle, &offset, (ULONG)sizeof(LONG));\n\t\t\t\twhile (offset) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDue to the fact that the embedded file name is of arbitrary\n\t\t\t\t\t**\tlength, we must read it in a byte at a time.  Reading stops\n\t\t\t\t\t**\twhen the terminating NULL is found.\n\t\t\t\t\t*/\n\t\t\t\t\ti=0;\n\t\t\t\t\tdo {\n\t\t\t\t\t\tRead_File(file_handle, &name[i], (ULONG)sizeof(name[0]));\n\t\t\t\t\t} while (name[i++]);\n\n\t\t\t\t\ti = Find_File_Index(name);\n\t\t\t\t\tif (i != ERROR) {\n\t\t\t\t\t\tcur = &FileDataPtr[i];\n\t\t\t\t\t\tif ((cur->Flag & FILEF_PACKED) && cur->Disk == filehandletable->Index) {\n\n\t\t\t\t\t\t\tcur->Start = offset + FileDataPtr[ filehandletable->Index ].Start;\n\t\t\t\t\t\t\tif (last != NULL) {\n\t\t\t\t\t\t\t\tlast->Size = cur->Start - last->Start;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tlast = cur;\t\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// ERROR: File specified in packed file has no table entry.\n\t\t\t\t\t\t// When this occurs, the embedded file is ignored.\n\t\t\t\t\t}\n\n\t\t\t\t\tRead_File(file_handle, &offset, (ULONG)sizeof(LONG));\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tFixup the size record of the last embedded file.\n\t\t\t\t*/\n\t\t\t\tif (last != NULL) {\n\t\t\t\t\tlast->Size = File_Size(file_handle) - last->Start;\n\t\t\t\t}\n\n\t\t\t\tFileDataPtr[filehandletable->Index].Flag |= FILEF_PROCESSED;\n\t\t\t}\n\n\t\t\t// if the parent is resident, the the child must have the same address.\n\t\t\tfiledata->Ptr = parent->Ptr;\n\n\t\t\t/*\n\t\t\t**\tSet starting position to start of embedded file.\n\t\t\t*/\n\t\t\tfilehandletable->Index = index;\n\t\t\tfilehandletable->Name = filedata->Name;\n\t\t\tfilehandletable->Start = filedata->Start;\n\n\t\t\tSeek_File(file_handle, NULL, SEEK_SET);\n\n\t\t\t// Attempt to cache the file if wanted, and room.\n\t\t\tCache_File(index, file_handle);\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tConvert the Westwood access mode into the system specific mode.\n\t\t\t*/\n\t\t\tlocal_mode = MODE_OLDFILE;\n\t\t\tswitch (mode) {\n\t\t\t\tcase READ:\n\t\t\t\t\tlocal_mode = MODE_OLDFILE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase READ | WRITE:\n\t\t\t\t\t#if(IBM)\n\t\t\t\t\t\tlocal_mode = MODE_READWRITE;\n\t\t\t\t\t#else\n\t\t\t\t\t\tlocal_mode = MODE_OLDFILE;\n\t\t\t\t\t#endif\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase WRITE:\n\t\t\t\t\tlocal_mode = MODE_NEWFILE;\n\t\t\t\t\tbreak;\n\n\n\t\t\t\tdefault:\n\t\t\t\t\tDo_IO_Error(BAD_OPEN_MODE, file_name);\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\t\t/*\n\t\t\t**\tThe file is disk based.  Perform the DOS open processing.\n\t\t\t*/\n\n\t\t\t/*\n\t\t\t**\tMake sure the file is available or the proper disk is inserted.\n\t\t\t** The file MUST exist if READ access is requested.  A mild attempt\n\t\t\t**\twill be made to find the file if open for WRITE only.\n\t\t\t*/\n\t\t\tif (mode & READ) {\n\t\t\t\tif (!File_Exists(file_name)) {\n\t\t\t\t\tCallingDOSInt--;\n\t\t\t\t\treturn(ERROR);\t\t\t/* Ignore the error */\n\t\t\t\t}\n\t\t\t} \n\n\n\t\t\t/*\n\t\t\t**\tRepetitively try to open the file until the error handler\n\t\t\t**\troutine indicates otherwise.\n\t\t\t*/\n\t\t\thandle = FILEOPENERROR;\n\t\t\tfor (;;) {\n\t\t\t\thandle = Open_File_With_Recovery( file_name, local_mode );\n\t\t\t\tif (handle != FILEOPENERROR) {\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tCHANGEDIR( DataPath );\n\t\t\t\t\tCHANGEDIR( StartPath );\n\t\t\t\t\tif (!Do_Open_Error(COULD_NOT_OPEN, file_name)) {\n\t\t\t\t\t\tCallingDOSInt--;\n\t\t\t\t\t\treturn(FILEOPENERROR);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tA file that is read off of disk cannot be part of\n\t\t\t**\ta pack file regardless of the bit settting.\n\t\t\t*/\n\t\t\tif (immediate && index != ERROR) {\n\t\t\t\tfiledata->Flag &= ~FILEF_PACKED;\n\t\t\t\tfiledata->Size = 0;\n\t\t\t}\n\n\t\t\tif (index != ERROR) {\n\n\t\t\t\t// The true file size is needed.\n\t\t\t\t// Go back to beginning of file.\n\t\t\t\tfiledata->Size = FILESEEK(handle, 0L, SEEK_END);\n\t\t\t\tFILESEEK(handle, 0L, SEEK_SET);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tInitialize the local file handle table.\n\t\t\t*/\n\t\t\tfilehandletable->Index = index;\n\t\t\tfilehandletable->Pos = 0L;\n\t\t\tfilehandletable->Start = 0L;\n\t\t\tfilehandletable->Empty = FALSE;\n\t\t\tfilehandletable->Handle = handle;\n\t\t\tfilehandletable->Mode = mode;\n\t\t\tif (index != ERROR) {\n\t\t\t\tfilehandletable->Name = filedata->Name;\n\t\t\t} else {\n\t\t\t\tfilehandletable->Name = NULL;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the file should be made resident, then do it at this time.\n\t\t\t**\tPerform all necessary adjustments to the file tables.\n\t\t\t*/\n\t\t\tif ((mode & WRITE) == 0) {\n\t\t\t\tCache_File(index, file_handle);\n\t\t\t}\n\t\t}\n\t}\n\n\t// If in the file table, increment the number of opens on this file.\n\tif (index != ERROR) {\n\t\tfiledata->OpenCount++;\n\t}\n\n\t/*\n\t**\tReturn with valid file handle.\n\t*/\n\tCallingDOSInt--;\n\treturn(file_handle);\n}\n\n\n/***************************************************************************\n * CLOSE_FILE -- Closes a file previously opened with Open_File.           *\n *                                                                         *\n *    Use this routine to close a file that was opened with Open_File.     *\n *    This is the only way to close a file that was opened with the        *\n *    Westwood file I/O system.                                            *\n *                                                                         *\n * INPUT:   handle   -- Westwood file handle.                              *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/11/1991 JLB : Created.                                             *\n *=========================================================================*/\nVOID cdecl Close_File(WORD handle)\n{\n\tWORD\t\t\t\tindex;\t\t\t\t\t// File data table index.\n\tBOOL\t\t\t\tflushed\t= FALSE;\t\t// If file flushed from cache, do change time stamp.\n\tBOOL\t\t\t\tstillopen;\n\tFileDataType\t*parent = NULL;\n\tFileDataType\t*filedata = NULL;\n\tVOID\t\t\t\t*memptr=NULL;\n\n\n\t#if(DEBUGPRINT)\n\t\tMono_Printf(\"Close_File(%d)\\r\", handle);\n\t#endif\n\n\n\t/*\n\t**\tCheck for file handle validity.\n\t*/\n\tif (!Is_Handle_Valid(handle, CLOSING_NON_HANDLE, NULL)) {\n\t\treturn;\n\t}\n\n\tCallingDOSInt++;\n\n\tindex = FileHandleTable[handle].Index;\n\tfiledata = &FileDataPtr[index];\n\n\t// Remove the OpenCount on the file.\n\tif (index != ERROR) {\n\n\t\tfiledata->OpenCount--;\n\t\tstillopen = filedata->OpenCount;\n\n\t\t// If this file packed in another, then decrement the parents open count.\n\t\tif (filedata->Flag & FILEF_PACKED) {\n\t\t\tparent = &FileDataPtr[filedata->Disk];\n\n\t\t\t// Do not dec OpenCount if the child was cached but not the parent.\n\t\t\tif (parent->Ptr == filedata->Ptr) {\n\t\t \t\tparent->OpenCount--;\n\t\t\t\tstillopen = parent->OpenCount;\n\t\t\t}\n\t\t}\n\t}\n\n\n\t// If the file was resident, then handle bookeeping.\n\tif (index != ERROR && filedata->Ptr) {\n\n\t\t// Get a pointer to the memory area for later use.\n\t\tmemptr = filedata->Ptr;\n\n\t\t// If file has a parent, and it is the cached file...\n\t\tif (parent && (parent->Ptr == filedata->Ptr)) {\n\n\t\t\t// The PAK'd file is closed just by setting the pointer.\n\t\t\tif (!filedata->OpenCount)\t{\n\t\t\t\tfiledata->Ptr = NULL;\n\t\t\t}\n\n\t\t\t// Uncache parent if no other sons are open and it should be flushed.\n\t\t\tif ((!parent->OpenCount) && (parent->Flag & FILEF_FLUSH)) {\n\t\t\t\tMem_Free(FileCacheHeap, parent->Ptr);\n\t\t\t\tparent->Ptr = NULL;\n\t\t\t\tflushed = TRUE;\n\t\t\t}\n\t\t}\n\t\t// Else should the file be flushed?  Only flush it if the flag says\n\t\t// so AND there are no other open counts on it.\n\t\telse if ((filedata->Flag & FILEF_FLUSH) && !filedata->OpenCount) {\n\t\t\tMem_Free(FileCacheHeap, filedata->Ptr);\n\t\t\tfiledata->Ptr = NULL;\n\t\t\tflushed = TRUE;\n\t\t}\n\n\t\t//\n\t\t// Set the time stamp on the close IF\n\t\t//     the file was not flush AND\n\t\t//     is not open AND \n\t\t//\t\t its time stamp should be changed by being a FILEF_KEEP|PROIORTY file.\n\t\t//\n\t\tif (!flushed && !stillopen && !(filedata->Flag & (FILEF_KEEP|FILEF_PRIORITY))) {\n\t\t\tMem_Reference(memptr);\n\t\t}\n\t} \n\t// Just a simple close will do.\n\telse \t{\n\t\tFILECLOSE(FileHandleTable[handle].Handle);\n\t}\n\n\t// The WWS handle is no longer being used.\n\tFileHandleTable[handle].Empty = TRUE;\n\n\tCallingDOSInt--;\n}\n\n\n\n/***************************************************************************\n * READ_FILE -- Reads a block of data from a file.                         *\n *                                                                         *\n *    This routine is used to read a block of data from a previously       *\n *    opened file.                                                         *\n *                                                                         *\n * INPUT:   handle   -- Westwood file handle returned from Open_File.      *\n *                                                                         *\n *          buf      -- Pointer to buffer to load the data into.           *\n *                                                                         *\n *          bytes    -- Number of bytes to load.                           *\n *                                                                         *\n * OUTPUT:  Returns with the number of bytes actually read from the file.  *\n *          If this number is less than the number requested, this         *\n *          indicates the end of the file.                                 *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/13/1991 JLB : Created.                                             *\n *=========================================================================*/\nLONG cdecl Read_File(WORD handle, VOID *buf, ULONG bytes)\n{\n\tWORD\t\t\t\t\tdoshandle;\t\t// DOS file handle.\n\tWORD\t\t\t\t\tfileindex;\t\t// File table index.\n\tLONG\t\t\t\t\tbytesread;\t\t// Accumulation of number of bytes read.\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\n\t#if(DEBUGPRINT)\n\t\tMono_Printf(\"Read_File(%d, %08lx, %ld)\\r\", handle, buf, bytes);\n\t#endif\n\n\t/*\n\t**\tThe handle must be valid or else it is an error.\n\t*/\n\tif (!buf || !bytes || !Is_Handle_Valid(handle, READING_NON_HANDLE, NULL)) {\n\t\treturn(NULL);\n\t}\n\n\tCallingDOSInt++;\n\n\t/*\n\t**\tPrepare some working variables.\n\t*/\n\tdoshandle = FileHandleTable[handle].Handle;\n\tfileindex = FileHandleTable[handle].Index;\n\n\n\t/*\n\t**\tLimit the number of bytes to read according to the size of the\n\t**\tfile.  If no file size is specified, then don't perform the check.\n\t*/\n\tif (fileindex != ERROR) {\n\t\tfiledata = &FileDataPtr[fileindex];\n\n\t\tif (filedata->Size) {\n\t\t\tbytes = MIN((ULONG)filedata->Size - FileHandleTable[handle].Pos, bytes);\n\t\t}\n\t}\n\n\t/*\n\t**\tStarts with no bytes being read in.\n\t*/\n\tbytesread = 0;\n\n\tif (bytes) {\n\n\t\tif (doshandle) {\n\t\t\t/*\n\t\t\t**\tPerform a DOS read of the file.  Read the file in chunks.\n\t\t\t*/\n\t\t\twhile (bytes) {\n\t\t\t\tLONG\tnumber;\t// Number of bytes read.\n\n\t\t\t\t/*\n\t\t\t\t**\tRead in a chunk of file data.\n\t\t\t\t*/\n\t\t\t\tHard_Error_Occured = 0;\n\t\t\t\tnumber = (LONG)FILEREAD(doshandle, buf, MIN(bytes, IO_CHUNK_SIZE));\n\n\t\t\t\t/*\n\t\t\t\t** if a hard error occurs, read its copy on a different directory\n\t\t\t\t*/\n\t\t\t\tif ( Hard_Error_Occured\t) {\n\t\t\t\t\tnumber = Read_File_With_Recovery( handle, buf, (UWORD)MIN(bytes, IO_CHUNK_SIZE));\n\t\t\t\t\tdoshandle = FileHandleTable[handle].Handle;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAdjust the remaining bytes to read counter and adjust the count\n\t\t\t\t**\tof the number of bytes actually read from the file.\n\t\t\t\t*/\n\t\t\t\tbytes -= number;\n\t\t\t\tbytesread += number;\n\n\t\t\t\t/*\n\t\t\t\t**\tAdjust the file position (manually).\n\t\t\t\t*/\n\t\t\t\tFileHandleTable[handle].Pos += number;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf less than requested bytes were read from the file, then \n\t\t\t\t** we KNOW that the reading loop must terminate.\n\t\t\t\t**\tWas there an error?\n\t\t\t\t*/\n\t\t\t\tif (number < IO_CHUNK_SIZE) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAdjust the destination pointer in anticipation of the next\n\t\t\t\t**\tfile read operation.\n\t\t\t\t*/\n\t\t\t\t// this is a BCC bug\n\t\t\t\t// (BYTE *)buf += number;\n\t\t\t\t buf = (BYTE* ) buf +  number;\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t#if (DEBUGPRINT)\n\t\t\t\tMono_Printf(\"Resident read '%s' %08lx[%ld].%ld\\r\", filedata->Name, (LONG)filedata->Start, FileHandleTable[handle].Pos, bytes);\n\t\t\t#endif\n\n\t\t\t/*\n\t\t\t**\tCopy the block of the file into the specified buffer.\n\t\t\t*/\n\t\t\tMem_Copy((VOID*)((LONG)filedata->Ptr + FileHandleTable[handle].Start + FileHandleTable[handle].Pos), buf, bytes);\n\t\t\tbytesread = bytes;\n\n\t\t\t/*\n\t\t\t**\tAdjust the file position (manually).\n\t\t\t*/\n\t\t\tFileHandleTable[handle].Pos += bytes;\n\t\t}\n\t}\n\n\t/*\n\t**\tReturn with the number of bytes read in from the file.\n\t*/\n\tCallingDOSInt--;\n\treturn(bytesread);\n}\n\n\n/***************************************************************************\n * WRITE_FILE -- Writes a block of data to a file.                         *\n *                                                                         *\n *    This routine will write a block of data to a file.  The file must    *\n *    have been previously opened with WRITE or READ|WRITE access.         *\n *    Writing cannot occur to a resident or packed file.                   *\n *                                                                         *\n * INPUT:   handle   -- File handle as returned by Open_File.              *\n *                                                                         *\n *          buf      -- Pointer to the buffer that holds the data to be    *\n *                      written out.                                       *\n *                                                                         *\n *          bytes    -- The number of bytes to write out.                  *\n *                                                                         *\n * OUTPUT:  Returns with the actual number of bytes written to the file.   *\n *                                                                         *\n * WARNINGS:   If the value returned from this function is less than the   *\n *             number of bytes requested to be written, then this          *\n *             indicates some kind of error NOT caught by the file I/O     *\n *             system.                                                     *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/13/1991 JLB : Created.                                             *\n *=========================================================================*/\nLONG cdecl Write_File(WORD handle, VOID const *buf, ULONG bytes)\n{\n\tWORD\t\t\t\t\tdoshandle;\t\t// DOS specific file handle.\n\tWORD\t\t\t\t\tfileindex;\t\t// FileData table index (if any).\n\tLONG\t\t\t\t\tbyteswritten;\t// Accumulated number of bytes written.\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\n\t#if(DEBUGPRINT)\n\t\tMono_Printf(\"Write_File(%d, %08lx, %ld)\\r\", handle, buf, bytes);\n\t#endif\n\n\t/*\n\t**\tCheck to make sure the file handle is valid.\n\t*/\n\tif (!Is_Handle_Valid(handle, WRITING_NON_HANDLE, NULL)) {\n\t\treturn(NULL);\n\t}\n\tdoshandle = FileHandleTable[handle].Handle;\n\tfileindex = FileHandleTable[handle].Index;\n\tfiledata = &FileDataPtr[fileindex];\n\n\t/*\n\t**\tWriting to a resident file is an error condition.\n\t*/\n\tif (!doshandle) {\n\t\tDo_IO_Error(WRITING_RESIDENT, filedata->Name);\n\t\treturn(NULL);\n\t}\n\n\tCallingDOSInt++;\n\n\t/*\n\t**\tPerform a DOS write of the data.  This write is performed in blocks.\n\t*/\n\tbyteswritten = NULL;\n\n\twhile (bytes) {\n\t\tLONG\toutbytes;\t\t// Number bytes written in one block.\n\n\t\t/*\n\t\t**\tWrite out one block of data.\n\t\t*/\n\t\toutbytes = FILEWRITE(doshandle, (void*)buf, MIN((LONG)bytes, IO_CHUNK_SIZE));\n\n\t\t/*\n\t\t**\tReduce the bytes remaining to output counter and adjust the\n\t\t**\tfile position.\n\t\t*/\n\t\tbytes -= outbytes;\n\t\tbyteswritten += outbytes;\n\t\tFileHandleTable[handle].Pos += outbytes;\n\n\t\t/*\n\t\t**\tIf NO bytes were written out, then this is some kind of unknown\n\t\t**\terror (possibly disk full?).\n\t\t*/\n\t\tif (!outbytes) {\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tPossible adjustment to the file's size.\n\t\t*/\n\t\tif (fileindex != ERROR) {\n\t\t\tfiledata->Size = MAX(filedata->Size, FileHandleTable[handle].Pos);\n\t\t}\n\n\t\t/*\n\t\t**\tAdjust the source pointer in anticipation of the next block write.\n\t\t*/\n\t\tbuf = (BYTE*)(((LONG)buf) + outbytes);\n\t}\n\n\t/*\n\t**\tReturn with the actual number of bytes written.\n\t*/\n\tCallingDOSInt--;\n\treturn (byteswritten);\n}\n\n\n/***************************************************************************\n * SEEK_FILE -- Adjusts the position of the file pointer.                  *\n *                                                                         *\n *    This routine adjusts the position of the file pointer.  Use this     *\n *    to control where the next Read_File or Write_File will occur.        *\n *                                                                         *\n * INPUT:   handle   -- File handle as returned by Open_File.              *\n *                                                                         *\n *          offset   -- Signed offset from indicated starting position.    *\n *                                                                         *\n *          starting -- SEEK_CUR:   Seeks from the current position.       *\n *                      SEEK_SET:   Seeks from the start of the file.      *\n *                      SEEK_END:   Seeks backward from the end.\t\t\t\t*\n *                                                                         *\n * OUTPUT:  Returns with the new file position.                            *\n *                                                                         *\n * WARNINGS:   Seeking past the end or before the beginning of the file    *\n *             is not allowed.                                             *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/13/1991 JLB : Created.                                             *\n *=========================================================================*/\nULONG cdecl Seek_File(WORD handle, LONG offset, WORD starting)\n{\n\tWORD\t\t\t\t\tdoshandle;\t// DOS specific file handle.\n\tWORD\t\t\t\t\tfileindex;\t// FileData index (if any).\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\n\t#if(DEBUGPRINT)\n\t\tMono_Printf(\"Seek_File(%d, %ld, %d)\\r\", handle, offset, starting);\n\t#endif\n\n\t/*\n\t**\tCheck to make sure that the file handle is valid.\n\t*/\n\tif (!Is_Handle_Valid(handle, SEEKING_NON_HANDLE, NULL)) {\n\t\treturn(NULL);\n\t}\n\n\tCallingDOSInt++;\n\n\tfileindex = FileHandleTable[handle].Index;\n\tdoshandle = FileHandleTable[handle].Handle;\n\tfiledata = &FileDataPtr[fileindex];\n\n\tif (!doshandle) {\n\n\t\t/*\n\t\t**\tResident file seek is merely an adjustment to the position value.\n\t\t*/\n\t\tswitch (starting) {\n\n\t\t\t/*\n\t\t\t**\tManually position from start of file.\n\t\t\t*/\n\t\t\tcase SEEK_SET:\n\t\t\t\toffset = MAX((long)0, offset);\t\t// Only positive offsets allowed.\n\t\t\t\tFileHandleTable[handle].Pos = NULL;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tPosition is relative to end of file.\n\t\t\t*/\n\t\t\tcase SEEK_END:\n\t\t\t\toffset = MIN((long)0, offset);\t\t// Only negative offsets allowed.\n\t\t\t\tFileHandleTable[handle].Pos = filedata->Size;\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_CUR:\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tDo_IO_Error(SEEKING_BAD_OFFSET, FileHandleTable[handle].Name);\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tPerform the resident file position adjustment.\n\t\t*/\n\t\tFileHandleTable[handle].Pos += offset;\n\n\t\tFileHandleTable[handle].Pos = MIN(FileHandleTable[handle].Pos,  filedata->Size-1);\n\t\tFileHandleTable[handle].Pos = MAX(FileHandleTable[handle].Pos,  (long)0);\n\n\t} else {\n\n\t\t/*\n\t\t**\tSpecial handling for packed file seeks.\n\t\t*/\n\t\tif (fileindex != ERROR && (filedata->Flag & FILEF_PACKED)) {\n\t\t\tswitch (starting) {\n\t\t\t\tcase SEEK_SET:\n\t\t\t\t\tFileHandleTable[handle].Pos = offset;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase SEEK_END:\n\t\t\t\t\t// Only negative offsets allowed.\n\t\t\t\t\t// Do not allow seeking past the beginning.\n\t\t\t\t\toffset = MIN(0L, offset);\t\t\n\t\t\t\t\tif (-offset > filedata->Size) {\n\t\t\t\t\t \tDo_IO_Error(SEEKING_BAD_OFFSET, FileHandleTable[handle].Name);\n\t\t\t\t\t}\n\t\t\t\t\tFileHandleTable[handle].Pos = filedata->Size + offset;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase SEEK_CUR:\n\t\t\t\t\tFileHandleTable[handle].Pos += offset;\n\t\t\t\t\tif (FileHandleTable[handle].Pos < 0) {\n\t\t\t\t\t\tFileHandleTable[handle].Pos = 0;\n\t\t\t\t\t}\n\t\t\t\t\tif (FileHandleTable[handle].Pos >= filedata->Size) {\n\t\t\t\t\t\tFileHandleTable[handle].Pos = filedata->Size;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tDo_IO_Error(SEEKING_BAD_OFFSET, FileHandleTable[handle].Name);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tFILESEEK(doshandle, FileHandleTable[handle].Pos+FileHandleTable[handle].Start, SEEK_SET);\n\t\t\tCallingDOSInt--;\n\t\t\treturn (FileHandleTable[handle].Pos);\n\t\t}\n\t\t/*\n\t\t**\tPerform the straight DOS seek.\n\t\t*/\n\t\tFileHandleTable[handle].Pos = FILESEEK(doshandle, offset, starting);\n\n\t\t/*\n\t\t**\tFile position does not recognize packed offset.\n\t\t*/\n\t\tif (fileindex != ERROR) {\n\t\t\tFileHandleTable[handle].Pos -= FileHandleTable[handle].Start;\n\t\t\t//SKB FileHandleTable[handle].Pos -= filedata->Start;\n\t\t}\n\t}\n\n\t/*\n\t**\tReturn with the current file position.\n\t*/\n\tCallingDOSInt--;\n\treturn (FileHandleTable[handle].Pos);\n}\n\n\n/***************************************************************************\n * FILE_EXISTS -- Searches for and FINDS the specified file.               *\n *                                                                         *\n *    This routine will scan the available drives and return when the file *\n *    is accessable.  This routine is used when the programmer MUST be     *\n *    sure of a file's existance before proceeding.  This process is       *\n *    automatically performed on a Open_File with READ access.             *\n *                                                                         *\n * INPUT:   file_name   -- Name of the file to check for.                  *\n *                                                                         *\n * OUTPUT:  Returns the disk number that the file exits on (A=1, B=2, etc) *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/14/1991 JLB : Created.                                             *\n *=========================================================================*/\nWORD cdecl File_Exists(BYTE const *file_name)\n{\n\t/*\n\t**\tIf the filename is invalid then it errors out.\n\t*/\n\tif (!file_name) return(FALSE);\n\t/*\n\t**\tContinually search for the file (prompting as needed).  Only return\n\t**\tupon success or error function control reasons.\n\t*/\n\twhile (!Find_File(file_name)) {\n\n\t\t/*\n\t\t**\tIf the file could not be found then request for proper disk.\n\t\t*/\n\t\tdo {\n\t\t\t//struct\tfind_t ffblk;\n\t\t\t//BYTE\t\tpath[MAXPATH];\n\t\t\t\n\t\t\tif (!Do_Open_Error(COULD_NOT_OPEN, file_name)) {\n\t\t\t\treturn(FALSE);\n\t\t\t}\n\t\t\tibm_setdisk(*DataPath - 'A');\n\n\t\t\t// Search for the volume ID so that the disk information get read in again.\n\t\t\t//_dos_findfirst(\"*.*\", _A_VOLID, &ffblk);\n\t\t} while (CHANGEDIR( DataPath ));\n\t}\n\treturn (TRUE);\n}\n\n\n/***************************************************************************\n * FILE_SIZE -- Determine the size of the specified file.                  *\n *                                                                         *\n *    This routine will return with the size of the file specified by the  *\n *    file handle passed in.                                               *\n *                                                                         *\n * INPUT:   handle   -- Westwood file handle.                              *\n *                                                                         *\n * OUTPUT:  Returns with the size of the file in bytes.                    *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1991 JLB : Created.                                             *\n *=========================================================================*/\nULONG cdecl File_Size(WORD handle)\n{\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\n\n\tif (FileHandleTable[handle].Index != ERROR) {\n\t\tfiledata = &FileDataPtr[FileHandleTable[handle].Index];\n\t\t\n\t\tif (filedata->Size) {\n\t\t\treturn(filedata->Size);\n\t\t}\n\t}\n\treturn (filelength(FileHandleTable[handle].Handle));\n}\n\n\n/***************************************************************************\n * IS_HANDLE_VALID -- Determines validity of the specified file handle.    *\n *                                                                         *\n *    Use this routine to determine if a file handle is valid or not.  It  *\n *    checks to see if it falls within legal limits and does in fact       *\n *    reference an open file.  This routine will call the error handler    *\n *    with the specified error number if the handle is not valid.          *\n *                                                                         *\n * INPUT:   handle   -- Handle to check for validity.                      *\n *                                                                         *\n *          error    -- Error number to use when calling the IO_Error      *\n *                      handler.                                           *\n *                                                                         *\n *          name     -- The file name (if known).                          *\n *                                                                         *\n * OUTPUT:  Returns with the file table index, if one exists for this      *\n *          file.                                                          *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/13/1991 JLB : Created.                                             *\n *=========================================================================*/\nBOOL cdecl Is_Handle_Valid(WORD handle, FileErrorType error, BYTE const *name)\n{\n\t/*\n\t**\tThe handle must be valid or else it is an error.\n\t*/\n\tif (handle < 0 || handle >= TABLE_MAX) {\n\t\t/*\n\t\t**\tERROR: Invalid file handle.\n\t\t*/\n\t\tDo_IO_Error(error, name);\n\t}\n\n\t/*\n\t**\tAn unused file handle causes an error.\n\t*/\n\tif (FileHandleTable[handle].Empty) {\n\t\tDo_IO_Error(error, name);\n\t}\n\n\treturn (TRUE);\n}\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FILECACH.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library - File Caching routines          *\n *                                                                         *\n *                    File Name : FILECACH.CPP                             *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : September 13, 1993                       *\n *                                                                         *\n *                  Last Update : April 18, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Make_File_Resident -- Makes a file resident even if not flaged so.    *\n *   Flush_Unused_File_Cache -- Flushes the file cache of any non opened fi*\n *   Free_Resident_File -- Free the given file if it is resident.          *\n *   Unfragment_File_Cache -- Does a garbage collection on the file heap.  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWSTD_H\n#include <wwstd.h>\n#endif\t   \n\n#ifndef _FILE_H\n#include \"_file.h\"\n#endif\n\n#ifndef WWMEM_H\n#include <wwmem.h>\n#endif\n\n#include <string.h>\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n/***************************************************************************\n * UNFRAGMENT_FILE_CACHE -- Does a garbage collection on the file heap.    *\n *                                                                         *\n * INPUT:    NONE.                                                         *\n *                                                                         *\n * OUTPUT:   NONE.                                                         *\n *                                                                         *\n * WARNINGS: Can be a lengthy process.                                     *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nVOID Unfragment_File_Cache(VOID)\n{\n\tFileDataType\t*filedata;\n\tFileDataType\t*parent;\n\tUWORD\t\t\t\tidx;\n\n\n\t// Let the memory system clean up the file heap.\n\tMem_Cleanup(FileCacheHeap);\n\n\t// Now get our pointers back.\n\t// Start after the parent PAK files since we will need to check our pointers\n\t// with them.\n\tfiledata = &FileDataPtr[NumPAKFiles];\n\tfor (idx = NumPAKFiles; idx < NumPAKFiles; idx++, filedata++) {\n\twhile (filedata->Name) {\n\n\t\t// Only process files that are in the file cache.\n\t\tif (filedata->Ptr) {\n\n\t\t\t// Is a inner PAK file?\n\t\t\tif (filedata->Flag & FILEF_PACKED) {\n\n\t\t\t\tparent = &FileDataPtr[filedata->Disk];\n\n\t\t\t\t// Is it just a copied pointer of the parent?\n\t\t\t\tif (parent->Ptr == filedata->Ptr) {\t\n\t\t\t\t\tfiledata->Ptr = Mem_Find(FileCacheHeap, filedata->Disk);\n\t\t\t\t}\n\t\t\t\telse \n\t\t\t\t\tfiledata->Ptr = Mem_Find(FileCacheHeap, idx);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t \tfiledata->Ptr = Mem_Find(FileCacheHeap, idx);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Now that the children have been taken care of, let us do the parents.\n\tfor (filedata = FileDataPtr, idx = 0; idx < NumPAKFiles; idx++, filedata++) {\n\n\t\t// Only process files that are in the file cache.\n\t\tif (filedata->Ptr) {\n\t\t \tfiledata->Ptr = Mem_Find(FileCacheHeap, idx);\n\t\t}\n\t}\n}\n\n/***************************************************************************\n * MAKE_FILE_RESIDENT -- Makes a file resident even if not flaged so.      *\n *                                                                         *\n * INPUT:  BYTE *filename - name of file to be made resident.              *\n *                                                                         *\n * OUTPUT: BOOL if successful.  could fail in not enouph RAM or not found. *\n *                                                                         *\n * WARNINGS: File must be in FileData table.                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/13/1993 SKB : Created.                                             *\n *=========================================================================*/\nBOOL Make_File_Resident(BYTE const *filename)\n{\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\tFileDataType\t\thold;\t\t\t\t// Hold buffer for record (DO NOT ACCESS DIRECTLY)\n\tWORD\t\t\t\t\tfileindex;\n\tWORD\t\t\t\t\toldflag;\n\tWORD\t\t\t\t\thandle;\n\n\tfileindex = Find_File_Index(filename);\n\n\t//\tif the file is not in the table, we can't make it resident\n\tif (fileindex == ERROR) return(FALSE);\n\n\t// Get a pointer for quicker pointer action.\n\tfiledata = &FileDataPtr[fileindex];\n\n\t// Change the flags for a moment.\n\toldflag = filedata->Flag;\n\tfiledata->Flag |= FILEF_RESIDENT;\n\tfiledata->Flag &= ~FILEF_FLUSH;\n\n\t// Make the file resident.\n\thandle = Open_File(filename, READ);\n\tClose_File(handle);\n\n\t// Set flags back to normal.\n\tfiledata->Flag = oldflag;\n\n\treturn(TRUE);\n}\n\n/***************************************************************************\n * Flush_Unused_File_Cache -- Flushes the file cache of any non opened files.     *\n *                                                                         *\n * INPUT:     WORD flush_keep - TRUE to flush even files marked FILEF_KEEP.*\n *                                                                         *\n * OUTPUT:    WORD Number of file flushed.                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/23/1993  SB : Created.                                             *\n *=========================================================================*/\nWORD Flush_Unused_File_Cache(WORD flush_keeps) \n{\n\tWORD\t\t\t\tindex;\n\tWORD\t\t\t\tfreed = 0;\n\tFileDataType\t*filedata = NULL;\n\tFileDataType\thold;\t\t\t\t// Hold buffer for record (DO NOT ACCESS DIRECTLY)\n\n\t// Loop throuph the file table looking for files that could be freed.\n\tindex = 0;\n\tfiledata = &FileDataPtr[index];;\n\twhile (filedata->Name && strlen(filedata->Name)) {\n\n\t\tif (filedata->Ptr && !filedata->OpenCount && \n\t\t    (flush_keeps || !(filedata->Flag & FILEF_KEEP)) ) {\n\n\t\t\tMem_Free(FileCacheHeap, filedata->Ptr);\n\t\t\tfiledata->Ptr = NULL;\n\t\t\tfreed++;\n\t\t}\n\t\tindex++;\n\t\tfiledata = &FileDataPtr[index];;\n\t}\n\treturn (freed);\n}\n\n/***************************************************************************\n * FREE_RESIDENT_FILE -- Free the given file if it is resident.            *\n *                                                                         *\n * INPUT:      BYTE *file to free                                          *\n *                                                                         *\n * OUTPUT:     TRUE if file was free'd, FALSE otherwise                    *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/22/1992  CY : Created.                                             *\n *=========================================================================*/\nBOOL cdecl Free_Resident_File(BYTE const *file)\n{\n\tWORD\t\t\t\t\tfileindex;\n\tBOOL\t\t\t\t\toldflag;\t\t\t// Previous file flag.\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\tFileDataType\t\thold;\t\t\t\t// Hold buffer for record (DO NOT ACCESS DIRECTLY)\n\n\n\t//\tif the file is not in the table, we can't free it\n\tif ((fileindex = Find_File_Index(file)) == ERROR) {\n\t\treturn(FALSE);\n\t}\n\n\t// get a pointer for quicker calculations.\n\tfiledata = &FileDataPtr[fileindex];\n\n\t// If it isn't resident, don't try to Free it\n\tif (filedata->Ptr == NULL) {\n\t\treturn(TRUE);\n\t}\n\n\t// Change the flags for a moment.\n\toldflag = filedata->Flag;\n\tfiledata->Flag &= ~(FILEF_RESIDENT|FILEF_KEEP);\n\tfiledata->Flag |= FILEF_FLUSH;\n\n\t// Get the file out of Memory if it was there.\n\tClose_File(Open_File(file, READ));\n\n\t// Set flags back to original.\n\tfiledata->Flag = oldflag;\n\n\treturn(TRUE);\n}\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FILECHNG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library - File functions.                *\n *                                                                         *\n *                    File Name : FILECHNG.CPP                             *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : September 13, 1993                       *\n *                                                                         *\n *                  Last Update : September 13, 1993   [SKB]               *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Delete_File -- Deletes the file from the disk.                        *\n *   Create_File -- Creates an empty file on disk.                         *\n *   Change_File_Size -- Change the size of a writting file.               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n#ifndef _FILE_H\n#include \"_file.h\"\n#endif\n\n#ifndef WWMEM_H\n#include <wwmem.h>\n#endif\n\n#include <io.h>\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * CREATE_FILE -- Creates an empty file on disk.                           *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/24/1992 JLB : Created.                                             *\n *=========================================================================*/\nWORD cdecl Create_File(BYTE const *file_name)\n{\n\tWORD fd;\n\n\tif (!file_name) return(FALSE);\n\n\tfd = Open_File(file_name, WRITE);\n\tif (fd != ERROR) {\n\t\tClose_File(fd);\n\t\treturn(TRUE);\n\t}\n\treturn(FALSE);\n}\n\n\n/***************************************************************************\n * DELETE_FILE -- Deletes the file from the disk.                          *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/24/1992 JLB : Created.                                             *\n *=========================================================================*/\nWORD cdecl Delete_File(BYTE const *file_name)\n{\n\tWORD\t\t\t\t\tindex;\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\tFileDataType\t\thold;\t\t\t\t// Hold buffer for record (DO NOT ACCESS DIRECTLY)\n\n\tif (!file_name) return(FALSE);\n\n\tCallingDOSInt++;\n\n\tibm_setdisk(*StartPath - 'A');\n\n\tindex = Find_File_Index(file_name);\n\tfiledata = &FileDataPtr[index];\n\n\tif (index != ERROR && filedata->Ptr) {\n\t\tMem_Free(FileCacheHeap, filedata->Ptr);\n\t\tfiledata->Ptr = NULL;\n\t}\n\n\tindex = !FILEDELETE(file_name);\n\tCallingDOSInt--;\n\treturn(index);\n}\n\n\n\n/***************************************************************************\n * CHANGE_FILE_SIZE -- Change the size of a writting file.                 *\n *                                                                         *\n * INPUT:   WORD handle - handle of file.                                  *\n *          ULONG new_size - size of new handle.                           *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/13/1993 SKB : Created.                                             *\n *=========================================================================*/\nBOOL cdecl Change_File_Size(WORD handle, ULONG new_size)\n{\n\tWORD entry;\n\n\tif (Is_Handle_Valid(handle, WRITING_NON_HANDLE, NULL)) {\n\t\tentry = Get_DOS_Handle(handle);\n\t\tif (entry != ERROR) {\n\t\t\treturn(chsize(entry, new_size) != ERROR);\n\t\t}\n\t}\n\treturn(FALSE);\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FILEDATA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : File IO System LIbrary                   *\n *                                                                         *\n *                    File Name : FILEDATA.CPP                             *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 11, 1994                           *\n *                                                                         *\n *                  Last Update : April 11, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n#ifndef _FILE_H\n#include \"_file.h\"\n#endif\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/* \n\tstructure for FileDataType is:\n\n\tBYTE *filename:\tinitialize to actual file name on disk.\n\tLONG size:\t\t\tinitialize to actual file size on disk.\n\tBYTE *ptr:\t\t\tinitialize to a 0L below.\n\tWORD disk:\t\t\twhich floppy disk number (1+) file resides on.\n\tLONG pos:\t\t\tinitialize to a 0L below.\t\t\t\t\n\tUBYTE priority:\tfile priorities can be from 0 to 127. (127 = highest)\n \t\t\t\t\t\t\tif you want the file to be attempted to be made\n\t\t\t\t\t\t\tresident at runtime, add 128 to the file priority\n\t\t\t\t\t\t\tto set the high bit. even though the files\n\t\t\t\t\t\t\tpriority will appear to be 128 to 255, it will\n\t\t\t\t\t\t\tstill remain 0 to 127.\n*/\t\n\nFileDataType FileData[] = {\n\t{ \t\"\",               0L, \t\t0L, \t0, 0L,\t0\t\t\t}\n\t/* Must have an empty entry!!! */\n};\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FILEGLOB.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : FILEIO Library                           *\n *                                                                         *\n *                    File Name : FILEGLOB.C                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 11, 1994                           *\n *                                                                         *\n *                  Last Update : April 11, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#include <wwstd.h>\n#endif\t   \n\n#ifndef FILE_H\n#include \"_file.h\"\n#endif\n\n#include <process.h>\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/* Global varaiables */\nBYTE ExecPath[XMAXPATH + 1];\nBYTE DataPath[XMAXPATH + 1];\nBYTE StartPath[XMAXPATH + 1];\nBOOL UseCD;\n\n/* File System only Global varaiables */\nBYTE CallingDOSInt;\t\t\t\t\t\t\t\t\t// Indicate we are performing a DOS function\nBYTE MaxDevice,DefaultDrive;\t\t\t\t\t\t\nBYTE MultiDriveSearch = TRUE;\t\t\t\t\t\t// Multiple drive search flag\nFileDataType *FileDataPtr = NULL;\nFileHandleType FileHandleTable[TABLE_MAX];\nUWORD NumFiles;\t\t\t\t\t\t\t\t\t\t// Number of files, except PAK, in file table.\nUWORD NumPAKFiles;\t\t\t\t\t\t\t\t\t// Number of PAK files in filetable.\nVOID *FileCacheHeap = NULL;\t\t\t\t\t\t// Pointer to the cache in memory.\nWORD DiskNumber;\t\t\t\t\t\t\t\t\t\t// Where file was found (-1 == current directory).\nWORD MaxDirNum = 0;\n\n\nWORD (*Open_Error)(FileErrorType, BYTE const *) = NULL;\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FILEINFO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library - Fileio information functions.  *\n *                                                                         *\n *                    File Name : FILE.CPP                             \t\t*\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : September 13, 1993                       *\n *                                                                         *\n *                  Last Update : April 19, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Get_DOS_Handle -- Fetches system specific DOS file handle.            *\n *   Find_Disk_Number -- Determine disk a file resides upon.               *\n *   Set_File_Flags -- Sets flags for file if FileData table.              *\n *   Get_File_Flags -- Gets the flags on a file in the FileData table.     *\n *   Free_Handles -- Returns number of free file handles in WW system.     *\n *   Multi_Drive_Search -- Turns Multi search drive on and off.            *\n *   Clear_File_Flags -- Clears flags specified for file.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n#ifndef _FILE_H\n#include \"_file.h\"\n#endif\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * GET_DOS_HANDLE -- Fetches system specific DOS file handle.              *\n *                                                                         *\n *    This routine will return with the system specific DOS file handle.   *\n *    On the IBM, this is a WORD, on the Amiga, it is a LONG (BPTR).  Use  *\n *    this routine with caution, because the value returned is NOT         *\n *    portable.                                                            *\n *                                                                         *\n * INPUT:   fh -- Westwood file system handle.                             *\n *                                                                         *\n * OUTPUT:  Returns with the system DOS file handle (WORD or LONG).        *\n *                                                                         *\n * WARNINGS:   If you pass in an invalid file handle, or a file handle     *\n *             that references a resident file, then the ERROR code is     *\n *             returned.  Be SURE to check for this.                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/21/1991 JLB : Created.                                             *\n *   11/09/1991 JLB : Checks for illegal file handle passed in.            *\n *=========================================================================*/\nWORD cdecl Get_DOS_Handle(WORD fh)\n{\n\t/*\n\t**\tIf an illegal file handle is passed in then always abort.\n\t*/\n\tif (fh >= 0 && fh < TABLE_MAX) {\n\t\tif (!FileHandleTable[fh].Empty || FileHandleTable[fh].Handle) {\n\t\t\treturn(FileHandleTable[fh].Handle);\n\t\t}\n\n\t\t/*\n\t\t**\tIf it falls through here, then the file must be resident.  It is\n\t\t**\tillegal to get a DOS handle to a resident file.\n\t\t*/\n\t}\n\treturn(FILEOPENERROR);\n}\n\n/***************************************************************************\n * FREE_HANDLES -- Returns number of free file handles in WW system.       *\n *                                                                         *\n * INPUT:    NONE.                                                         *\n *                                                                         *\n * OUTPUT:   NONE.                                                         *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/13/1993 SKB : Created.                                             *\n *=========================================================================*/\nWORD cdecl Free_Handles(VOID)\n{\n\tWORD\tcount;\t\t// Count of the number of free file handles.\n\tWORD\tindex;\t\t// Working file handle index var.\n\t\n\tcount = 0;\n\tfor (index = 0; index < TABLE_MAX; index++) {\n\t\tif (FileHandleTable[index].Empty) count++;\n\t}\n\treturn(count);\n}\n\n\n\n/***************************************************************************\n * FIND_DISK_NUMBER -- Determine disk a file resides upon.                 *\n *                                                                         *\n *    This routine will determine the disk number that the specified       *\n *    file resides upon.  It determines this by scanning through the       *\n *    FileData table.  If the specified file is a packed file, then it     *\n *    will reference the parent packed file to determine the disk number.  *\n *                                                                         *\n * INPUT:   file_name   -- Pointer to the file name to check.              *\n *                                                                         *\n * OUTPUT:  Returns with the disk number that the file resides upon.  If   *\n *          ERROR is returned, then the file does not exist in the         *\n *          FileTable.  The number returned is 0=A, 1=B, etc.              *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1991 JLB : Created.                                             *\n *=========================================================================*/\nWORD cdecl Find_Disk_Number(BYTE const *file_name)\n{\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\tWORD\t\t\t\t\tindex;\t// FileTable index.\n\n\tindex = Find_File_Index(file_name);\n\n\tif (index != ERROR) {\n\t\t\n\t\tfiledata = &FileDataPtr[index];\n\n\t\tif (filedata->Flag & FILEF_PACKED) {\n\t\t\treturn (Find_Disk_Number(FileDataPtr[filedata->Disk].Name));\n\t\t}\n\t\treturn(filedata->Disk);\n\t}\n\treturn (index);\n}\n\n\n\n\n\n/***************************************************************************\n * SET_FILE_FLAGS -- Sets flags for file if FileData table.                *\n *                                                                         *\n * INPUT:  BYTE *filename - file to modify.                                *\n *         WORD flags - flags to set in file.                              *\n *                                                                         *\n * OUTPUT: WORD - if file found in FileData table.                         *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/04/1993 SKB : Created.                                             *\n *=========================================================================*/\nWORD cdecl Set_File_Flags(BYTE const *filename, WORD flags)\n{\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\tWORD\t\t\t\t\tindex;\t// FileTable index.\n\n\tindex = Find_File_Index(filename);\n\n\tif (index != ERROR) {\n\t\tfiledata = &FileDataPtr[index];\n\t\tfiledata->Flag |= flags;\n\t\treturn (TRUE);\n\t}\n\n\treturn (FALSE);\n}\n\n\n/***************************************************************************\n * CLEAR_FILE_FLAGS -- Clears flags specified for file.                    *\n *                                                                         *\n * INPUT:  BYTE *filename - file to modify.                                *\n *         WORD flags - flags to set in file.                              *\n *                                                                         *\n * OUTPUT: WORD - if file found in FileData table.                         *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1994 SKB : Created.                                             *\n *=========================================================================*/\nWORD cdecl Clear_File_Flags(BYTE const *filename, WORD flags)\n{\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\tWORD\t\t\t\t\tindex;\t// FileTable index.\n\n\tindex = Find_File_Index(filename);\n\n\tif (index != ERROR) {\n\t\tfiledata = &FileDataPtr[index];\n\t\tfiledata->Flag &= ~flags;\n\t\treturn (TRUE);\n\t}\n\n\treturn (FALSE);\n}\n\n\n\n/***************************************************************************\n * GET_FILE_FLAGS -- Gets the flags on a file in the FileData table.       *\n *                                                                         *\n *                                                                         *\n * INPUT:  BYTE *filename - file to modify.                                *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * OUTPUT: WORD - if file found in FileData table.                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/04/1993 SKB : Created.                                             *\n *=========================================================================*/\nWORD cdecl Get_File_Flags(BYTE const *filename)\n{\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\tWORD\t\t\t\t\tindex;\t// FileTable index.\n\n\tindex = Find_File_Index(filename);\n\n\tif (index != ERROR) {\n\t\tfiledata = &FileDataPtr[index];\n\t\treturn (filedata->Flag);\n\t}\n\treturn (FALSE);\n}\n\n\n/***************************************************************************\n * MULTI_DRIVE_SEARCH -- Turns Multi search drive on and off.              *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/13/1993 SKB : Created.                                             *\n *=========================================================================*/\nBOOL cdecl Multi_Drive_Search(BOOL on)\n{\n\tBOOL\told;\n\n\tHard_Error_Occured = 0;\n\told = MultiDriveSearch;\n\tMultiDriveSearch = on;\n\treturn(old);\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FILEINIT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library - Fileio init routines.          *\n *                                                                         *\n *                    File Name : FILEINIT.C                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : September 13, 1993                       *\n *                                                                         *\n *                  Last Update : April 19, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   WWDOS_Init -- Initialize the fileio WWS fileio system.                *\n *   WWDOS_Shutdown -- Clean up any things that needs to be to exit game.  *\n *   Init_FileData_Table -- Initializes or reads in FileData Table.        *\n *   Sort_FileData_Table -- Sorts the FileData table that is in memory.    *\n *   Preload_Files -- Loads files marked with FILEF_PRELOAD into cache.    *\n *   Init_File_Cache -- Initializes and allocs the file cache heap.        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n#ifndef _FILE_H\n#include \"_file.h\"\n#endif\n\n#ifndef WWMEM_H\n#include <wwmem.h>\n#endif\n\n#ifndef MISC_H\n#include <misc.h>\n#endif\n\n#include <direct.h>\n#include <search.h>\n#include <string.h>\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE FileInitErrorType cdecl Init_File_Cache(ULONG cachesize);\nPRIVATE FileInitErrorType cdecl Init_FileData_Table(BYTE const *filename);\nPRIVATE FileInitErrorType cdecl Set_Search_Drives( BYTE *cdpath );\nPRIVATE FileInitErrorType cdecl Preload_Files(VOID);\nPRIVATE int QSort_Comp_Func(const void *p1, const void *p2);\nPRIVATE VOID Sort_FileData_Table(VOID);\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n/***************************************************************************\n * WWDOS_INIT -- Initialize the fileio WWS fileio system.                  *\n *                                                                         *\n *                                                                         *\n * INPUT:   ULONG cachesize - size wanted for the cache.                   *\n *          BYTE *filedat - NULL or name of filedata table file.           *\n *          BYTE *cdpath - NULL or secondary search path on a CD.          *\n *                                                                         *\n * OUTPUT:  Returns all errors encountered or'd together.\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:  User should call the WWDOS_Init function for all file \t\t\t*\n *            initialization.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1994 SKB : Created.                                             *\n *=========================================================================*/\nFileInitErrorType cdecl WWDOS_Init(ULONG cachesize, BYTE *filedata, BYTE *cdpath)\n{\n//\tFileInitErrorType errors;\n\tunsigned errors ;\n\t\n\t// This has not been completed yet, when it is, uncomment it and add errors.\n\tInstall_Hard_Error_Handler () ;\n\tGet_Devices();\n\n\tif (cachesize) {\t\n\t\terrors = Init_File_Cache(cachesize);\n\t} else {\n\t \terrors = FI_SUCCESS;\n\t}\n\n\n\terrors = errors | Init_FileData_Table(filedata);\n\n\terrors = errors | Set_Search_Drives(cdpath);\n\n\terrors = errors | Preload_Files();\n\n\n\treturn ( FileInitErrorType ) errors ;\n}\n\n/***************************************************************************\n * WWDOS_SHUTDOWN -- Clean up any things that needs to be in file syste to *\n *                   exit game.    \t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                   One could shut down the file system and open it back  *\n *                   up with a different size cache or filetable.          *\n *                                                                         *\n * INPUT:   NONE.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:  NONE.                                                          *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1994 SKB : Created.                                             *\n *=========================================================================*/\nVOID cdecl WWDOS_Shutdown(VOID)\n{\n\tFileDataType\t\t\t*filedata;\t\t\t\t\t// Pointer to the current FileData.\n\tWORD\t\t\t\t\t\tfile_handle;\n\tFileHandleType\t\t  \t*filehandletable;\t\t\t// Pointer to the current file handle.\n\n\t// Close all open files.\n\tfilehandletable = FileHandleTable;\n\tfor (file_handle = 0; file_handle < TABLE_MAX; file_handle++, filehandletable++) {\n\t\tif (!filehandletable->Empty) {\n\t\t  \tClose_File(file_handle);\n\t\t}\n\t}\n\n\t// Free the file cache heap.\n\tif (FileCacheHeap) {\n\n\t\t// Get a pointer to the current filedata.\n\t\tif (FileDataPtr) {\n\t \t\tfiledata = FileDataPtr;\n\t\t} else {\n\t \t\tfiledata = FileData;\n\t\t}\n\n\t\twhile(filedata->Name && filedata->Name[0]) {\n\t\t\tfiledata->Ptr = NULL;\n\t\t\tfiledata++;\n\t\t}\n\n\t\tFree(FileCacheHeap);\n\t\tFileCacheHeap = NULL;\n\t}\n\n\t// Free up the file data.\n\tif (FileDataPtr != FileData) {\n\t\tFree(FileDataPtr);\n\t}\n\tFileDataPtr = NULL;\n\n\tchdir(StartPath);\n\tibm_setdisk(*StartPath - 'A');\n\n\t// This has not been completed yet, when it is, uncomment it and add errors.\n\tRemove_Hard_Error_Handler();\n}\n\n\n/***************************************************************************\n * INIT_FILE_CACHE -- Initializes and allocs the file cache heap.          *\n *                                                                         *\n * INPUT:  ULONG cachesize - size of heap cache..                          *\n *                                                                         *\n * OUTPUT: FileInitErrorType  error code.                                  *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1994 SKB : Created.                                             *\n *=========================================================================*/\nPRIVATE FileInitErrorType cdecl Init_File_Cache(ULONG cachesize)\n{\n\t// Allocate and initialize the file cache heap.\n\tif (FileCacheHeap) {\n \t \treturn (FI_CACHE_ALREADY_INIT);\n\t}\n\n\tif ((Ram_Free(MEM_NORMAL) >= cachesize)) {\n\t\tFileCacheHeap = Alloc(cachesize, MEM_NORMAL);\n\t\tMem_Init(FileCacheHeap, cachesize);\n\t}\n\n\tif (!FileCacheHeap) {\n\t \treturn (FI_CACHE_TOO_BIG);\n\t}\n\n\treturn (FI_SUCCESS);\n}\n\n\n\n\n/***************************************************************************\n * INIT_FILEDATA_TABLE -- Initializes or reads in FileData Table.          *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT: FileInitErrorType  error code.                                  *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/13/1993 SKB : Created.                                             *\n *=========================================================================*/\nPRIVATE FileInitErrorType cdecl Init_FileData_Table(BYTE const *filename)\n{\n\tWORD\t\t\t\t\tfd;\n\tULONG\t\t\t\t\tfsize;\n\tFileDataType\t\t*ptr;\n\tWORD \t\t\t\t\tindex;\n\tBYTE\t\t\t\t\tfname[13];\t\t\n\n\t/*\n\t**\tInialize the file handle table to reflect no files open.\n\t*/\n\tfor (index = 0; index < TABLE_MAX; index++) {\n\t\tFileHandleTable[index].Empty = TRUE;\n\t}\n\n\t// Set up our FileData ptr to be the initial FileData table.\n\tFileDataPtr = FileData;\n\n\t// Sort the filedata table.\n\t// This needs to be done even if we load it off disk since the initial file data\n\t// table might contain a filename.\n\tSort_FileData_Table();\n\n\t// If there is a file name, then the filedata table will be loaded from disk.\n\tif (filename) {\n\t\tif (!Find_File(filename)) {\n\t\t \treturn (FI_FILEDATA_FILE_NOT_FOUND);\n\t\t}\n\t\tfd = Open_File(filename, READ);\n\n\t\tfsize = File_Size(fd);\n\n\t\tif ((Ram_Free(MEM_NORMAL) < fsize)) {\n\t\t\tClose_File(fd);\n\t\t \treturn (FI_FILEDATA_TOO_BIG);\n\t\t}\n\n\t\t// Allocate some system memory.\n\t\t// Setup the new FileDataPtr and this time.\n\t\tFileDataPtr = ptr = (FileDataType *) Alloc(fsize, MEM_NORMAL);\n\n\t\t// Load the file up into  memory.\n\t\tRead_File(fd, FileDataPtr, fsize);\n\t\tClose_File(fd);\n\n\t\t// Process the filetable.  The filenames need their pointers adjusted.\n\t\t// At this time we will also count the number of files and number of PAK files.\n\t\tNumPAKFiles = NumFiles = 0;\n\n\t\t// Make sure that the file name will have a NUL at the end.\n\t\tfname[12] = 0;\n\t\twhile(TRUE) {\n\t\t\t// Have we reached the end of the list?\t\n\t\t\tif (!ptr->Name) break;\n\t\t \t\n\t\t\t// Adjust the name pointer to point the the correct area.\n\t\t\tptr->Name = (BYTE *)FileDataPtr + (LONG) ptr->Name;\n\n\t\t\t// Count up weather it is a PAK file or a normal file.\n\t\t\tif (!NumFiles && strstr((char *) ptr->Name, (char *)  \".PAK\")) {\n\t\t\t \tNumPAKFiles++;\n\n\t\t\t\t// Mark that it has been processed so that Open_File() will not do it.\n\t\t\t\tptr->Flag |= FILEF_PROCESSED;\n\n\t\t\t} else {\n\t\t\t\tNumFiles++;\n\t\t\t}\n\n\t\t\t// Next record.\n\t\t\tptr++;\n\t\t}\n\t}\n\n\treturn (FI_SUCCESS);\n}\n\n\n\n\n/***************************************************************************\n * Set_Search_Drives -- Sets up the CDRom and HardDrive paths.             *\n *                                                                         *\n * INPUT:    BYTE *cdpath - path of data files on a CD.\t\t\t\t\t\t\t*\n *           \t\t\t\t\t Should pass in NULL for non CD products.\t\t\t*\n *           \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT: FileInitErrorType  error code.                                  *\n *           Varibable defined:                                            *\n *               ExecPath = Full path of EXE file.                         *\n *               StartPath = Directory user started in.                    *\n *               DataPath = secondary search path (typically CD-ROM).      *\n *           Note: format of paths is \"C:\\PATH\"                           \t*\n *                                                                         *\n * WARNINGS: The cdpath may be overiden by a \"-CD<path>\" command line      *\n *           arguement that specifies another drive (HARD or CD) and path  *\n *           where the data resides.  Whenever a file is opened, it checks *\n *           the startup drive first, then the CD search path if the first *\n *           search was unsuccessful.                                      *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/14/1993  SB : Created.                                             *\n *   04/19/1994 SKB : Mods for 32 bit library.                             *\n *=========================================================================*/\nPRIVATE FileInitErrorType cdecl Set_Search_Drives( BYTE *cdpath )\n{\n\tBYTE *ptr;\n\n\n#if LIB_EXTERNS_RESOLVED \n\t// NOTE: THIS IS WRONG, THIS IS NOT THE WAY TO GET THE EXE's PATH.\n\t// Locate the executable.\t\n\tstrcpy(ExecPath, _argv[0]);\n\n\t// Find the very last '\\' on the path.\n\tptr = strrchr((char *) ExecPath, (int) '\\\\');\n#else\n\tptr = NULL;\n#endif\n\n\t// Remove the exe name to just have the path.\n\tif (ptr == NULL) {\n\t\t*ExecPath = 0;\n\t}\n\telse {\n\t \t*ptr = 0; \n\t}\n\n\t// Did the user specify a second path?\n\tptr = Find_Argv(\"-CD\");\n\n\t// If so, set the data path to that.\n\tif (ptr) {\n\t\tstrcpy(DataPath, ptr + 3);\n\t}\n\t// Otherwise check to see if there is a CD-Rom drive.\n\telse {\n\t\tif (cdpath && *cdpath) {\n\n#if LIB_EXTERNS_RESOLVED\n\t\t\tUseCD = GetCDDrive();\n#else\n\t\t\tUseCD = FALSE;\n#endif\n\t\t}\n\t\telse {\n\t\t \tUseCD = FALSE;\n\t\t}\n\n\t\t// If so, set the Drive to it and find out if any directories.\n\t\tif ( UseCD ) {\n\t\t\tstrcpy( DataPath, \"A:\" );\n\t\t\tstrcat( DataPath, cdpath);\n\t\t\t*DataPath = 'A'+UseCD;\n\t\t}\n\t\t// If not, set the Data path to the execacutable path.\n\t\telse {\n\t \t\tstrcpy(DataPath, ExecPath);\n\t\t}\n\t}\n\n\t// Finnally, set the starting path.\n\tgetcwd(StartPath, XMAXPATH);\n\n\t// Make sure they are all uppercase.\n\tstrupr(StartPath);\n\tstrupr(DataPath);\n\tstrupr(ExecPath);\n\n\t// Change directories to the secondary search path (DataPath).\n\tif (*DataPath && chdir(DataPath)) {\n\t\treturn (FI_SEARCH_PATH_NOT_FOUND);\n\t}\n\n\t// Lastley, Make sure we are in the startup directory.  This will overide\n\t// the secondary data path if they are on the same drive.\n\tif (chdir(StartPath)) {\n\t\treturn (FI_STARTUP_PATH_NOT_FOUND);\n\t}\n\n\treturn (FI_SUCCESS);\n}\n\n\n/***************************************************************************\n * PRELOAD_FILES -- Loads files marked with FILEF_PRELOAD into cache.      *\n *                                                                         *\n *                                                                         *\n * INPUT:  none.                                                           *\n *                                                                         *\n * OUTPUT: FileInitErrorType  error code.                                  *\n *                                                                         *\n * WARNINGS: The FileData must be initialized and the file heap initialized*\n *           in order for this to work.                                    *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1994 SKB : Created.                                             *\n *=========================================================================*/\nPRIVATE FileInitErrorType cdecl Preload_Files(VOID)\n{\n\tFileDataType\t*filedata;\t\t// Working file data table pointer.\n\tBOOL\t\t\t\toldflag;\t\t\t// Previous file flag.\n\n\tif (!FileDataPtr) {\n\t\treturn (FI_FILETABLE_NOT_INIT);\n\t}\n\n\tif (!FileCacheHeap) {\n\t\treturn (FI_NO_CACHE_FOR_PRELOAD);\n\t}\n\n\t/*\n\t**\tMake all files flagged to be made resident at startup, resident.\n\t*/\n\tfiledata = FileDataPtr;\n\n\twhile (filedata->Name && strlen(filedata->Name)) {\n\t\tif (filedata->Flag & FILEF_PRELOAD) {\n\n\t\t\toldflag = filedata->Flag;\n\t\t\tfiledata->Flag |= FILEF_RESIDENT;\t// Make it resident.\n\t\t\tfiledata->Flag &= ~FILEF_FLUSH;\t\t// Don't purge on Close_File.\n\n\t\t\tClose_File(Open_File(filedata->Name, READ));\n\n\t\t\tfiledata->Flag &= ~(FILEF_RESIDENT|FILEF_FLUSH);\t// Clear bits.\n\t\t\tfiledata->Flag |= oldflag & (FILEF_RESIDENT|FILEF_FLUSH);\t// Restore bits.\n\n\t\t}\n\t\tfiledata++;\n\t}\n\treturn (FI_SUCCESS);\n}\n\n\n\n/***************************************************************************\n * SORT_FILEDATA_TABLE -- Sorts the FileData table that is in memory.      *\n *                                                                         *\n * INPUT:  NONE                                                            *\n *                                                                         *\n * OUTPUT: NONE.                                                           *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/13/1993 SKB : Created.                                             *\n *=========================================================================*/\n\nPRIVATE int QSort_Comp_Func(const void *p1, const void *p2)\n{\n\treturn(strcmp(((FileDataType*)p1)->Name, ((FileDataType*)p2)->Name));\n}\nPRIVATE VOID Sort_FileData_Table(VOID)\n{\n\t/*\n\t**\tSort the filetable it but keep the pack file indexes correct.\n\t*/\n\n\t/*\n\t**\tThe number of pak files in the file table.\n\t*/\n\tNumPAKFiles = 0;\n\tstrupr(FileData[NumPAKFiles].Name);\n\twhile (strstr((char *) FileData[NumPAKFiles].Name, (char *) \".PAK\")) {\n\t\tstrupr(FileData[NumPAKFiles].Name);\n\t\tNumPAKFiles++;\n\t}\n\n\t/*\n\t**\tCount the remaining files within the file table.\n\t*/\n\tNumFiles = 0;\n\twhile(FileData[NumFiles+NumPAKFiles].Name && FileData[NumFiles+NumPAKFiles].Name[0]) {\n\t\tstrupr(FileData[NumFiles+NumPAKFiles].Name);\n\t\tNumFiles++;\n\t}\n\n\t/*\n\t**\tSort the file entries (past the pak files).\n\t*/\n\tif (NumFiles) {\n\t\tqsort(&FileData[NumPAKFiles], NumFiles, sizeof(FileDataType), QSort_Comp_Func);\n\t}\n}\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FILEIO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : FILEIO.C                                 *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : August 21, 1991                          *\n *                                                                         *\n *                  Last Update : September 13, 1993   [SKB]               *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n#ifndef _FILE_H\n#include \"_file.h\"\n#endif\n\n#include <dos.h>\n#include <direct.h>\n#include <io.h>\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\nWORD ibm_getdisk(VOID)\n{\n\tunsigned disk;\n\n\tCallingDOSInt++;\n  //\tdisk = getdisk();\n\t_dos_getdrive ( & disk ) ;\n\tCallingDOSInt--;\n\treturn(disk-1);\n}\n\nWORD ibm_setdisk(WORD drive)\n{\n//\tWORD disk;\n\tunsigned disk ;\n\n\tCallingDOSInt++;\n//\tdisk = setdisk(drive);\n\t_dos_setdrive ( drive+1 , & disk ) ;\n\tCallingDOSInt--;\n\treturn(disk);\n}\n\nWORD ibm_close(WORD handle)\n{\n\tWORD success;\n\n\tCallingDOSInt++;\n\tsuccess = close(handle);\n\tCallingDOSInt--;\n\treturn(success);\n}\n\nWORD ibm_unlink(BYTE const *name)\n{\n\tWORD success;\n\n\tCallingDOSInt++;\n\tsuccess = unlink(name);\n\tCallingDOSInt--;\n\treturn(success);\n}\n\nLONG ibm_lseek(WORD handle, LONG offset, WORD where)\n{\n\tLONG new_offset;\n\n\tCallingDOSInt++;\n\tnew_offset = lseek(handle, offset, where);\n\tCallingDOSInt--;\n\treturn(new_offset);\n}\n\nUWORD ibm_read(WORD handle, VOID *ptr, UWORD bytes)\n{\n\tUWORD bytes_read;\n\n\tCallingDOSInt++;\n\tbytes_read = read(handle, ptr, bytes);\n\tCallingDOSInt--;\n\treturn(bytes_read);\n}\n\nUWORD ibm_write(WORD handle, VOID *ptr, UWORD bytes)\n{\n\tUWORD bytes_written;\n\n\tCallingDOSInt++;\n\tbytes_written = write(handle, ptr, bytes);\n\tCallingDOSInt--;\n\treturn(bytes_written);\n}\n\nWORD ibm_open(BYTE const *name, UWORD mode, WORD attrib)\n{\n\tWORD handle;\n\n\tCallingDOSInt++;\n\thandle = open(name, mode, attrib);\n\tCallingDOSInt--;\n\treturn(handle);\n}\n\nWORD ibm_chdir(BYTE const *path)\n{\n\tWORD retval;\n\n\tCallingDOSInt++;\n\tretval = chdir(path);\n\tCallingDOSInt--;\n\treturn(retval);\n}\n\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FILELIB.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : FILEIO Library support routines.         *\n *                                                                         *\n *                    File Name : FILELIB.C                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 11, 1994                           *\n *                                                                         *\n *                  Last Update : April 11, 1994   [SKB]                   *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *  Notes: This file contains private functions to the fileio system.      *\n *         While these functions may be used by any module in the fileio   *\n *         system, they cannot be used by a user program.  For this reason *\n *         they are put into this module.                                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Cache_File -- Attempts to cache file in XMS if flags set.             *\n *   Do_IO_Error -- Performs a non-recoverable error message display.      *\n *   Do_Open_Error -- Does an error message that could return.             *\n *   Is_Handle_Valid -- Determines validity of the specified file handle.  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n#ifndef _FILE_H\n#include \"_file.h\"\n#endif\n\n#ifndef WWMEM_H\n#include <wwmem.h>\n#endif\n\n\n#include <fcntl.h>\n#include <io.h>\n#include <process.h>\n#include <sys\\stat.h>\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * DO_ERROR -- Does an error message that could return.               *\n *                                                                         *\n *    This routine displays a file error message and unless the player     *\n *    presses <ESC>, it will return.  If the player presses <ESC>, then    *\n *    it will terminate the program.                                       *\n *                                                                         *\n * INPUT:   error    -- Error message number.                              *\n *                                                                         *\n *          filename -- File name that the error occured on.               *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Should the process be repeated?                    *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/09/1991 JLB : Created.                                             *\n *=========================================================================*/\n#pragma argsused\nWORD cdecl Do_Open_Error(FileErrorType errormsgnum, BYTE const *file_name)\n{\n\tBYTE\t*ptr=NULL;\t\t// Working file name pointer (just name and extension).\n\n\t/*\n\t** Since the file name may include a path, we must extract the true\n\t** file name from the given string.\n\t*/\n\tif (file_name) {\n#if  LIB_EXTERNS_RESOLVED \n\t\tptr = strrchr((char *) file_name, (int) '\\\\');\n#else\n\t\tptr = NULL;\n#endif\t\t\n\t\tif (ptr) {\n\t\t\tptr++;\n\t\t} else {\n\t\t\tptr = (BYTE *) file_name;\n\t\t}\n\t}\n\n#if  LIB_EXTERNS_RESOLVED \n\tstrupr(ptr);\n\treturn (IO_Error(errormsgnum, ptr));\n#else\n\treturn(0);\n\t\n#endif\t\n\n}\n\n\n/***************************************************************************\n * DO_IO_ERROR -- Performs a non-recoverable error message display.        *\n *                                                                         *\n *    This routine will perform a non-recoverable file error message       *\n *    display.  It is called when an error is detected that has no         *\n *    recovery or retry process defined.                                   *\n *                                                                         *\n * INPUT:   errornum -- Error number detected.                             *\n *                                                                         *\n *          filename -- Name of the file that caused the error.            *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/09/1991 JLB : Created.                                             *\n *=========================================================================*/\n#pragma argsused\nVOID cdecl Do_IO_Error(FileErrorType errormsgnum, BYTE const *filename)\n{\n#if  LIB_EXTERNS_RESOLVED \n\t(VOID)IO_Error(errormsgnum, filename);\n#endif\n\t#if(TRUE)\n\tProg_End();\n\texit((int)errormsgnum);\n\t#else\n\tProgram_End();\n\t#endif\n}\n\n\n/***************************************************************************\n * Read_File_With_Recovery -- read the same file on another directory if an error    *\n *                  occurs.                                                *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/16/1993  QY : Created.                                             *\n *=========================================================================*/\nLONG cdecl Read_File_With_Recovery( WORD handle, VOID *buf, UWORD bytes )\n{\n\tWORD newhandle;\n\tLONG bytes_read;\n\n\tdo {\n\t\tHard_Error_Occured = 0;\n\n\t\t// Make sure we are in the right path.\n\t\tCHANGEDIR( DataPath );\n\n\t\t// open the same file\n\t\tnewhandle = Open_File( FileHandleTable[ handle ].Name, FileHandleTable[ handle ].Mode );\n\t   Seek_File( newhandle, FileHandleTable[ handle ].Pos, SEEK_SET );\n\n\t\t// dos close the old file\n\t\tFILECLOSE( FileHandleTable[ handle ].Handle );\n\n\t\t// copy FileHandleTable[ newhandle ] to FileHandleTable[ handle ]\n\t\tMem_Copy( &FileHandleTable[ newhandle ], &FileHandleTable[ handle ],\n \t\t         ( ULONG ) sizeof( FileHandleTable[ newhandle ] ) );\n\n\t\t// delete FileHandleTable[newhandle]\n\n\t\tFileHandleTable[ newhandle ].Empty = TRUE;\n\n\t\t// continue reading file \n\t\tbytes_read = ( LONG ) FILEREAD( FileHandleTable[ handle ].Handle, buf, bytes );\n\n\t\t// if still error, do it again; else return the number of bytes read\n\t\tif ( !Hard_Error_Occured ) {\n\t\t\treturn( bytes_read );\n\t\t}\n\t\tif (!Do_Open_Error(COULD_NOT_OPEN, FileHandleTable[ handle ].Name)) {\n\t\t\treturn(FALSE);\n\t\t}\n\n\t} while (CHANGEDIR( DataPath ));\n\n\treturn (NULL);\n}\n\n/***************************************************************************\n * Open_File_With_Recovery -- open the same file on another directory      *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/16/1993  QY : Created.                                             *\n *=========================================================================*/\nWORD cdecl Open_File_With_Recovery( BYTE const *file_name, UWORD mode )\n{\n\tWORD handle;\n\n\tHard_Error_Occured = FALSE;\n\thandle = FILEOPEN(file_name, mode);\n\n\t// Do not return if there was a HardError and Using a CD and we are looking at\n\t// the CD.\n\tif (!Hard_Error_Occured || !UseCD || (ibm_getdisk() != (*DataPath - 'A'))) {\n\t\treturn (handle);\n\t}\n\n#if DEBUGPRINT\n\tMono_Print(file_name); Mono_Print(\":OPENERROR  \");\n#endif\n\n\tHard_Error_Occured = 0;\n\n\t// It is possible that the CD has been poped out and put back in, let us\n\t// change there and then try again.\n\tibm_setdisk(*DataPath - 'A');\n\tCHANGEDIR( DataPath );\n\n\t// open the same file\n\thandle = FILEOPEN( file_name, mode );\n\n\t// if still error, do it again; else return the dos handle\n\tif ( !Hard_Error_Occured ) {\n\t\treturn( handle );\n\t}\n\t\t\n\tHard_Error_Occured = 0;\n\treturn (FILEOPENERROR);\n}\n\n\n/***************************************************************************\n * CACHE_FILE -- Attempts to cache file in XMS if flags set.               *\n *                                                                         *\n *                                                                         *\n * INPUT:    WORD index - the index of the file in the FileData table.     *\n *           WORD file_handle - WWS file handle of file.                   *\n *                                                                         *\n * OUTPUT:   BOOL : was it cached?                                         *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1993 SKB : Created.                                             *\n *=========================================================================*/\nBOOL cdecl Cache_File(WORD index, WORD file_handle)\n{\n\tLONG\t\t\t\tfilesize;\t\t// Size of the memory block needed.\n\tLONG\t\t\t\tfreecache; \t\t// Amount of free XMS.\n\tFileDataType\t*filedata = NULL;\n\tFileDataType\thold;\n\tFileHandleType\t*filehandletable;\n\tWORD\t\t\t\tflag;\t\t\t\t// Type of system memory to cache file.\n\tWORD\t\t\t\tfile;\n\n\t// Only files in the file table can be cached.\n\tif (index == ERROR) {\n\t \treturn FALSE;\n\t}\n\n\t// Setup our pointer to the file we may want to cache.\n\tfiledata = &FileDataPtr[index];\n\n\t// Should this be cached, and is it not yet cached?\n\tif ((filedata->Flag & (FILEF_RESIDENT|FILEF_PRELOAD)) && !filedata->Ptr) {\n\n\t\tfilesize = filedata->Size;\n\n\t\t/*\n\t\t**\tIf there is o room to cache the file, then turn off its cache file.\n\t\t*/\n\t\tif (filesize > Mem_Pool_Size(FileCacheHeap)) { \n\n\t\t\t// Remove resident flags so that it will not keep trying to cache itself \n\t\t\t// since there will never be enough room for it.\n\t\t\tfiledata->Flag &= ~(FILEF_PRELOAD|FILEF_KEEP|FILEF_RESIDENT|FILEF_FLUSH);\n\t\t\t\n\t\t\treturn FALSE;\n\t\t}\n\n\n\t\t// Go through freeing files until there is enouph space in the\n\t\t// memory pool.\n\t\twhile (filesize > Mem_Avail(FileCacheHeap)) {\n\t\t\tVOID  *node;\n\n\t\t\t// Get the oldest non used file pointer.\n\t\t\tnode = Mem_Find_Oldest(FileCacheHeap);\n\n\t\t\t// If non was found, sorry no room for the new file.\n\t\t\tif (!node) {\n\t\t\t\treturn (FALSE);\n\t\t\t}\n\n\t\t\t// Get a pointer to the structure for convenience.\n\t\t\tfiledata = &FileDataPtr[Mem_Get_ID(node)];\n\n\t\t\t// Free it from the heap and update the file system so it knows that\n\t\t\t// the file is no longer in memory.\n\t\t\tMem_Free(FileCacheHeap, filedata->Ptr);\n\t\t\tfiledata->Ptr = NULL;\n\t\t}\n\n\n\t\t// If there is not a big enough space we will have to take garbage\n\t\t// collection hit.  (OUCH!!!!!!)\n\t\tif (filesize > Mem_Largest_Avail(FileCacheHeap)) {\n\t\t\tUnfragment_File_Cache();\n\t\t}\n\n\t\t// Make sure we have a big enough space and if so, put the file into memory.\n\t\tif (filesize < Mem_Largest_Avail(FileCacheHeap)) {\n\n\t\t\t// Get some pointers to save code space and time.\n\t\t\tfilehandletable = &FileHandleTable[file_handle];\n\t\t\tfiledata = &FileDataPtr[index];\n\n\t\t\t// Alloc the buffer in our file cache, then read the file in.\n\t\t\tfiledata->Ptr = Mem_Alloc(FileCacheHeap, filesize, index);\n\n\t\t\t// Extra check - it should not fail.\n\t\t\tif (!filedata->Ptr) return(FALSE);\n\n\t\t\t// Mark it so that it never comes back as Oldest used.\n\t\t\tMem_In_Use(filedata->Ptr);\n\n\t\t\t// Get the file into memory.\n\t\t\tRead_File(file_handle, filedata->Ptr, filesize);\n\n\t\t\t// reset the read index from the above read.\n\t\t\tfilehandletable->Pos = 0L;\n\n\t\t\t// This makes caching inner pak file possible.  No longer is the\n\t\t\t// PAK'd file based off the parent file.\n\t\t\tfilehandletable->Start = 0;\t  \n\n\t\t\t// Close the parent file.  Remove it's open count.\n\t\t\tif (filedata->Flag & FILEF_PACKED) {\n\t\t\t\tFileDataType\tp_hold;\n\t\t\t\tFileDataType\t*parent;\n\n\t\t\t\tparent = &FileDataPtr[filedata->Disk];\n\t\t\t\tparent->OpenCount--;\n\t\t\t}\n\t\t\tFILECLOSE(filehandletable->Handle);\n\t\t\tfilehandletable->Handle = 0;\n\n\t\t\treturn (TRUE);\n\t\t}\t\n\t}\n\n\t// The file was not cached, let the caller know.\n\treturn (FALSE);\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FILESTUB.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : wwlib32                                  *\n *                                                                         *\n *                    File Name : FILESTUB.CPP                             *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : May 3, 1994                              *\n *                                                                         *\n *                  Last Update : May 3, 1994   [BR]                       *\n *                                                                         *\n * This module is a temorary stub that contains IO_Error.\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include \"wwstd.h\"\n#include \"file.h\"\n\nWORD Text_IO_Error(FileErrorType, BYTE const *){return FALSE;}\nWORD (*IO_Error)(FileErrorType, BYTE const *)   = Text_IO_Error;\n\n/************************* End of filestub.cpp *****************************/\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FILLQUAD.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : FILLQUAD.ASM                             *\n;*                                                                         *\n;*                   Programmer : Ian M. Leslie                            *\n;*                                                                         *\n;*                   Start Date : August 11, 1994                          *\n;*                                                                         *\n;*                  Last Update : August 30, 1994   [IML]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:\t\t\t\t\t\t\t\t   *\n;*\tFill_Quad -- Flood fills an arbitrary convex quadrilateral\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nSLOT_VACANT\tEQU\t80008000h\nNULL\t\tEQU\t0h\n\n\nCODESEG\n\n;***************************************************************************\n;* VVC::FILL_QUAD -- Flood fills an arbitrary convex quadrilateral\t   *\n;*                                                                         *\n;* INPUT:      \tDWORD this_object\t- associated graphic viewport\t\t   *\n;*\t\tDWORD span_buff - pointer to span array\t\t\t   *\n;*\t\tDWORD x0_pixel \t- the zeroth x pixel position\t\t   *\n;*\t       \tDWORD y0_pixel\t- the zeroth y pixel position\t\t   *\n;*\t       \tDWORD x1_pixel\t- the first x pixel position\t\t   *\n;*\t       \tDWORD y1_pixel  - the first y pixel position\t\t   *\n;*\t       \tDWORD x2_pixel\t- the second x pixel position\t\t   *\n;*\t       \tDWORD y2_pixel\t- the second y pixel position\t\t   *\n;*\t       \tDWORD x3_pixel\t- the third x pixel position\t\t   *\n;*\t       \tDWORD y3_pixel\t- the third y pixel position\t\t   *\n;*\t\tDWORD color     - the color of the quad to fill\t\t   *\n;*                                                                         *\n;* Bounds Checking: Compares quad points with the graphic viewport it \t   *\n;*\t\t    has been assigned to.\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* Rasterization Rules: FILL_QUAD is designed to be used within a quad\t   *\n;*\t\t\tmesh. There is no pixel overlapping or stitching   *\n;*\t\t\teffects at shared borders. FILL_QUAD is NOT\t   *\n;*                      recommended for isolated quads.                    *                                *\n;* HISTORY:                                                                *\n;*   08/11/1994 IML : Created.\t\t\t\t\t\t   *\n;*   08/26/1994 IML : Various optimizations.\t\t\t\t   *\n;*   08/30/1994 IML : Added rasterization rules for shared borders.\t   *\n;*=========================================================================*\n\tPROC\tBuffer_Fill_Quad C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\n\t;*==================================================================\n\t;* Define the arguments that the function takes.\n\t;*==================================================================\n\tARG\tthis_object:DWORD\t\t; associated graphic viewport\n\tARG\tspan_buff:DWORD\t\t; pointer to span array\n\tARG\tx0_pixel:DWORD\t\t; the zeroth x pixel position\n\tARG\ty0_pixel:DWORD\t\t; the zeroth y pixel position\n\tARG\tx1_pixel:DWORD\t\t; the first x pixel position\n\tARG\ty1_pixel:DWORD\t\t; the first y pixel position\n\tARG\tx2_pixel:DWORD\t\t; the second x pixel position\n\tARG\ty2_pixel:DWORD\t\t; the second y pixel position\n\tARG\tx3_pixel:DWORD\t\t; the third x pixel position\n\tARG\ty3_pixel:DWORD\t\t; the third y pixel position\n\tARG\tcolor:DWORD\t\t; the color of the quad\n\n\n\t;*==================================================================\n\t;* Define the local variables that we will use on the stack.\n\t;*==================================================================\n\tLOCAL\tclip_min_x:DWORD\t; boundary of viewport\n\tLOCAL\tclip_max_x:DWORD\t;\n\tLOCAL\tclip_min_y:DWORD\t;\n\tLOCAL\tclip_max_y:DWORD\t;\n\tLOCAL\tclip_var:DWORD\n\tLOCAL\tleft_clip_base:DWORD:2\t; storage for additional edges\n\tLOCAL\tleft_clip_index:DWORD\t;   generated by clipping\n\tLOCAL\tright_clip_base:DWORD:2\t;\n\tLOCAL\tright_clip_index:DWORD\t;\n\tLOCAL\tscanline_min:DWORD\t; vertical extent of quad\n\tLOCAL\tscanline_max:DWORD\n\tLOCAL\trealignment:DWORD\n\tLOCAL\tbpr:DWORD\t\t; bytes per row of associated buffer\n\n\n\t;*==================================================================\n\t;* Extract essential GraphicViewPort info.\n\t;*==================================================================\n\tmov\tebx,[this_object]\n\tmov\teax,[(GraphicViewPort ebx).GVPXPos]\n\tmov\t[clip_min_x],eax\n\tmov\teax,[(GraphicViewPort ebx).GVPYPos]\n\tmov\t[clip_min_y],eax\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\n\tmov\t[clip_max_x],eax\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\n\tadd\teax,[(GraphicViewPort ebx).GVPPitch]\n\tmov\t[bpr],eax\n\tmov\teax,[(GraphicViewPort ebx).GVPHeight]\n\tmov\t[clip_max_y],eax\n\n\n\t;*==================================================================\n\t;* Adjust top and right edges of viewport for rasterization rules.\n\t;*==================================================================\n\tdec\t[clip_max_y]\n\tdec\t[clip_min_y]\n\n\n\t;*==================================================================\n\t;* Find the vertical extent of the quad BEFORE clipping.\n\t;* y0_pixel = y0, y1_pixel = y1, y2_pixel = y2, y3_pixel = y3\n\t;*==================================================================\n\tmov\teax,[y0_pixel]\n\tcmp\teax,[y1_pixel]\n\tjle\tshort ??y1_not_smaller\n\tmov\teax,[y1_pixel]\n\n??y1_not_smaller:\n\tcmp\teax,[y2_pixel]\n\tjle\tshort ??y2_not_smaller\n\tmov\teax,[y2_pixel]\n\n??y2_not_smaller:\n\tcmp\teax,[y3_pixel]\n\tjle\tshort ??y3_not_smaller\n\tmov\teax,[y3_pixel]\n\n??y3_not_smaller:\n\tcmp\teax,[clip_min_y]\n\tjge\tshort ??no_clamp_min_min\n\tmov\teax,[clip_min_y]\n\n??no_clamp_min_min:\n\tcmp\teax,[clip_max_y]\n\tjle\tshort ??no_clamp_max_min\n\tmov\teax,[clip_max_y]\n\t\t\t\t\t; scanline_min = MIN (y0, y1, y2, y3)\n??no_clamp_max_min:\t\t\t; scanline_min = MAX (scanline_min, clip_min_y)\n\tmov\t[scanline_min],eax\t; scanline_min = MIN (scanline_min, clip_max_y)\n\n\tmov\teax,[y0_pixel]\n\tcmp\teax,[y1_pixel]\n\tjge\tshort ??y1_not_greater\n\tmov\teax,[y1_pixel]\n\n??y1_not_greater:\n\tcmp\teax,[y2_pixel]\n\tjge\tshort ??y2_not_greater\n\tmov\teax,[y2_pixel]\n\n??y2_not_greater:\n\tcmp\teax,[y3_pixel]\n\tjge\tshort ??y3_not_greater\n\tmov\teax,[y3_pixel]\n\n??y3_not_greater:\n\tcmp\teax,[clip_min_y]\n\tjge\tshort ??no_clamp_min_max\n\tmov\teax,[clip_min_y]\n\n??no_clamp_min_max:\n\tcmp\teax,[clip_max_y]\n\tjle\tshort ??no_clamp_max_max\n\tmov\teax,[clip_max_y]\n\t\t\t\t\t; scanline_max = MAX (y0, y1, y2, y3)\n??no_clamp_max_max:\t\t\t; scanline_max = MAX (scanline_max, clip_min_y)\n\tmov\t[scanline_max],eax\t; scanline_max = MIN (scanline_max, clip_max_y)\n\n\n\t;*==================================================================\n\t;* Initialize memory for spans.\n\t;*==================================================================\n\tsub\teax,[scanline_min]\n\tje\t??abort_fill_quad\t; don't render quads with zero height\n\tmov\tebx,eax\n\tmov\teax,[span_buff]\t\t; check span_buff for NULL ptr\n\tcmp\teax,NULL\n\tje\t??abort_fill_quad\n\tsal\tebx,2\n\n??span_initialize_loop:\n\tmov\t[DWORD PTR eax + ebx],SLOT_VACANT\n\tsub\tebx,4\n\tjl\tshort ??exit_span_initialize\n\tmov\t[DWORD PTR eax + ebx],SLOT_VACANT\n\tsub\tebx,4\n     \tjl\tshort ??exit_span_initialize\n\tmov\t[DWORD PTR eax + ebx],SLOT_VACANT\n\tsub\tebx,4\n     \tjl\tshort ??exit_span_initialize\n\tmov\t[DWORD PTR eax + ebx],SLOT_VACANT\n\tsub\tebx,4\n\tjge\tshort ??span_initialize_loop\n\n\n\t;*==================================================================\n\t;* Clip and scan convert the four edges defining the quad.\n\t;*==================================================================\n??exit_span_initialize:\n\tmov\t[left_clip_index],0\n\tmov\t[right_clip_index],0\n\n\tmov\teax,[x0_pixel]\n\tmov\tebx,[y0_pixel]\n\tmov\tecx,[x1_pixel]\n\tmov\tedx,[y1_pixel]\n\tcall\tNEAR PTR ??clip_and_scan_convert\n\tmov\teax,[x1_pixel]\n\tmov\tebx,[y1_pixel]\n\tmov\tecx,[x2_pixel]\n\tmov\tedx,[y2_pixel]\n\tcall\tNEAR PTR ??clip_and_scan_convert\n\tmov\teax,[x2_pixel]\n\tmov\tebx,[y2_pixel]\n\tmov\tecx,[x3_pixel]\n\tmov\tedx,[y3_pixel]\n\tcall\tNEAR PTR ??clip_and_scan_convert\n\tmov\teax,[x3_pixel]\n\tmov\tebx,[y3_pixel]\n\tmov\tecx,[x0_pixel]\n\tmov\tedx,[y0_pixel]\n\tcall\tNEAR PTR ??clip_and_scan_convert\n\n\n\t;*==================================================================\n\t;* Scan convert up to 2 additional left and right vertical edges\n\t;* generated by the clipping process.\n\t;*==================================================================\n\tcmp\t[left_clip_index],0\n\tje\tshort ??no_left_edge\n\tmov\teax,[clip_min_x]\n\tmov\tebx,[left_clip_base]\n\tmov\tecx,eax\n\tmov\tedx,[left_clip_base + 4]\n\tcall\tNEAR PTR ??scan_convert\n\n??no_left_edge:\n\tcmp\t[right_clip_index],0\n\tje\tshort ??no_right_edge\n\tmov\teax,[clip_max_x]\n\tmov\tebx,[right_clip_base]\n\tmov\tecx,eax\n\tmov\tedx,[right_clip_base + 4]\n\tcall\tNEAR PTR ??scan_convert\n\n\n\t;*==================================================================\n\t;* Fill the quad with specified color. Use DWORD copies where\n\t;* appropriate.\n\t;*==================================================================\n??no_right_edge:\n\tmov\teax,[this_object]\n\tmov\tedi,[(GraphicViewPort eax).GVPOffset]\n\tmov\teax,[scanline_min]\t\t; eax = scanline_min\n\n\tmov\tebx,[scanline_max]\n\tsub\tebx,[scanline_min]\t\t; ebx = span count\n\n\tmov\tesi,[span_buff]\t\t\t; esi = address of top span\n\n\tmul\t[bpr]\n\tadd\tedi,eax\t\t\t\t; edi = address of top scanline\n\t\t\t\t\t\t;  containing quad\n\tmov\tal,[BYTE PTR color]\t\t; extend pixel color into eax ready\n\tmov\tah,al\t\t\t\t;   for DWORD copies\n\tmov\tedx,eax\n\tshl\teax,16\n\tmov\tax,dx\n\n\tcld\t\t\t\t\t; only fill forwards\n\n\tjmp\t??skip_span\t\t\t; rasterization rule: don't\n\t\t\t\t\t\t;   render topmost span\n\n??quad_fill_loop:\n\tcmp\t[DWORD PTR esi],SLOT_VACANT\t; test for unused spans\tdue to clipping\n\tje\t??skip_span\n\txor\tecx,ecx\n\txor\tedx,edx\n\tmov\tcx,[WORD PTR esi]\n\tmov\tdx,[WORD PTR esi + 2]\n\tsub\tecx,edx\n\tpush\tedi\n\tjns\tshort ??not_negative_count\n\tadd\tedi,ecx\n\tneg\tecx\t\t\t\t; ecx = span width\n\n??not_negative_count:\n\tadd\tedi,edx\t\t\t\t; edi = address of start of span\n\tcmp\tecx,OPTIMAL_BYTE_COPY\t\t; does span width justify DWORD copies?\n\tjl\tshort ??byte_copy\n\tmov\tedx,ecx\n\tmov\tecx,edi\n\tand\tecx,3\t\t\t\t; if (ecx == 0) edi is already\n\tjz\tshort ??dword_copy_no_alignment\t;   DWORD aligned\n\txor\tecx,3\n\tinc\tecx\t\t\t\t; ecx = number of pixels before alignment\n\tsub\tedx,ecx\n\trep\tstosb\n\n??dword_copy_no_alignment:\n\tmov\tecx,edx\t\t\t\t; ecx = remaining pixels on span\n\tshr\tecx,2\t\t\t\t; copy (ecx / 4) DWORDS\n\trep\tstosd\n\tmov\tecx,edx\n\tand\tecx,3\t\t\t\t; ecx = remaining pixels on span\n\n??byte_copy:\n\trep\tstosb\t\t\t\t; byte copy remaining pixels on span\n\tpop\tedi\n\n??skip_span:\n\tadd\tedi,[bpr]\t\t\t; edi = address of start of next scanline\n\tadd\tesi,4\t\t\t\t; esi = address of next span\n\tdec\tebx\n\tjge\tshort ??quad_fill_loop\t\t; is span count >= 0?\n\n??abort_fill_quad:\n\tret\n\n\n\t;*==================================================================\n\t;* This is the section that \"pushes\" the edge into bounds.\n\t;* I have marked the section with PORTABLE start and end to signify\n\t;* how much of this routine is 100% portable between graphics modes.\n\t;* It was just as easy to have variables as it would be for constants\n\t;* so the global vars clip_min_x, clip_min_y, clip_max_x, clip_max_y\n\t;* are used to clip the edge (default is the screen).\n\t;* PORTABLE start.\n\t;*==================================================================\n\n\n\t;*==================================================================\n\t;* Clip an edge against the viewport.\n\t;*==================================================================\n??clip_and_scan_convert:\n\tcall\tNEAR PTR ??set_left_right_bits\n\txchg\teax,ecx\n\txchg\tebx,edx\n\tmov\tedi,esi\n\tcall\tNEAR PTR ??set_left_right_bits\n\tmov\t[clip_var],edi\n\tor\t[clip_var],esi\n\tjz\t??clip_up_down\t\t\t; trivial acceptance?\n\ttest\tedi,esi\n\tjne\t??exit\t\t\t\t; trivial rejection?\n\tshl\tesi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+esi]\n\txchg\teax,ecx\n\txchg\tebx,edx\n\tshl\tedi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+edi]\n\n??clip_up_down:\n\tcall\tNEAR PTR ??set_up_down_bits\n\txchg\teax,ecx\n\txchg\tebx,edx\n\tmov\tedi,esi\n\tcall\tNEAR PTR ??set_up_down_bits\n\tmov\t[clip_var],edi\n\tor\t[clip_var],esi\n\tjz\t??scan_convert\t\t\t; trivial acceptance?\n\ttest\tedi,esi\n\tjne\t??exit\t\t\t\t; trivial rejection?\n\tshl\tesi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+esi]\n\txchg\teax,ecx\n\txchg\tebx,edx\n\tshl\tedi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+edi]\n\tjmp\t??scan_convert\n\n\n\t;*==================================================================\n\t;* Subroutine table for clipping conditions.\n\t;*==================================================================\n??clip_tbl\tDD\t??nada,??a_lft,??a_rgt,??nada\n\t\tDD\t??a_up,??nada,??nada,??nada\n\t\tDD\t??a_dwn\n\n\n\t;*==================================================================\n\t;* Subroutines for clipping conditions.\n\t;*==================================================================\n??nada:\n\tretn\n\n??a_up:\n\tmov\tesi,[clip_min_y]\n\tcall\tNEAR PTR ??clip_vert\n\tretn\n\n??a_dwn:\n\tmov\tesi,[clip_max_y]\n\tcall\tNEAR PTR ??clip_vert\n\tretn\n\n??a_lft:\n\tmov\tesi,[clip_min_x]\n\tcall\tNEAR PTR ??clip_horiz\n\tpush\tebx\n\tmov\tesi,[left_clip_index]\n\tcmp\tebx,[clip_min_y]\n\tjge\t??no_left_min_clip\n\tmov\tebx,[clip_min_y]\n\n??no_left_min_clip:\n\tcmp\tebx,[clip_max_y]\n\tjle\t??no_left_max_clip\n\tmov\tebx,[clip_max_y]\n\n??no_left_max_clip:\n\tmov\t[left_clip_base + esi],ebx\t; a left edge will be generated\n\tmov\t[left_clip_index],4\t\t;   store off yb\n\tpop\tebx\n\tretn\n\n??a_rgt:\n\tmov\tesi,[clip_max_x]\n\tcall\tNEAR PTR ??clip_horiz\n\tpush\tebx\n\tmov\tesi,[right_clip_index]\n\tcmp\tebx,[clip_min_y]\n\tjge\t??no_right_min_clip\n\tmov\tebx,[clip_min_y]\n\n??no_right_min_clip:\n\tcmp\tebx,[clip_max_y]\n\tjle\t??no_right_max_clip\n\tmov\tebx,[clip_max_y]\n\n??no_right_max_clip:\n\tmov\t[right_clip_base + esi],ebx\t; a right edge will be generated\n\tmov\t[right_clip_index],4\t\t;   store off yb\n\tpop\tebx\n\tretn\n\n\n\t;*==================================================================\n\t;* Clip a line against a horizontal edge at clip_y.\n\t;* (eax,ebx) = (xa,ya), (ecx,edx) = (xb,yb)\n\t;* xa' = xa+[(clip_y-ya)(xb-xa)/(yb-ya)]\n\t;* ya' = clip_y\n\t;*==================================================================\n??clip_vert:\n\tpush\tedx\n\tpush\teax\n\tmov\t[clip_var],edx\t\t; clip_var = yb\n\tsub\t[clip_var],ebx\t\t; clip_var = (yb-ya)\n\tneg\teax\t\t\t; eax = -xa\n\tadd\teax,ecx\t\t\t; eax = (xb-xa)\n\tmov\tedx,esi\t\t\t; edx = clip_y\n\tsub\tedx,ebx\t\t\t; edx = (clip_y-ya)\n\timul\tedx\t\t\t; eax = (clip_y-ya)(xb-xa)\n\tidiv\t[clip_var]\t\t; eax = (clip_y-ya)(xb-xa)/(yb-ya)\n\tpop\tedx\n\tadd\teax,edx\t\t\t; eax = xa+[(clip_y-ya)(xb-xa)/(yb-ya)]\n\tpop\tedx\n\tmov\tebx,esi\t\t\t; ebx =\tclip_y\n\tretn\n\n\n\t;*==================================================================\n\t;* Clip a line against a vertical edge at clip_x.\n\t;* (eax,ebxx) = (xa,ya), (ecx,edxx) = (xb,yb)\n\t;* ya' = ya+[(clip_x-xa)(yb-ya)/(xb-xa)]\n\t;* xa' = clip_x\n\t;*==================================================================\n??clip_horiz:\n\tpush\tedx\n\tmov\t[clip_var],ecx\t\t; clip_var = xb\n\tsub\t[clip_var],eax\t\t; clip_var = (xb-xa)\n\tsub\tedx,ebx\t\t\t; edx = (yb-ya)\n\tneg\teax\t\t\t; eax = -xa\n\tadd\teax,esi\t\t\t; eax = (clip_x-xa)\n\timul\tedx\t\t\t; eax = (clip_x-xa)(yb-ya)\n\tidiv\t[clip_var]\t\t; eax = (clip_x-xa)(yb-ya)/(xb-xa)\n\tadd\tebx,eax\t\t\t; ebx = ya+[(clip_x-xa)(yb-ya)/(xb-xa)]\n\tpop\tedx\n\tmov\teax,esi\t\t\t; eax = clip_x\n\tretn\n\n\n\t;*==================================================================\n\t;* Set the condition bits for the subroutine table.\n\t;*==================================================================\n??set_left_right_bits:\n\txor\tesi,esi\n\tcmp\teax,[clip_min_x]   \t; if x >= left its not left\n\tjge\tshort ??a_not_left\n\tor\tesi,1\n\n??a_not_left:\n\tcmp\teax,[clip_max_x]\t; if x <= right its not right\n\tjle\tshort ??a_not_right\n\tor\tesi,2\n\n??a_not_right:\n\tretn\n\n??set_up_down_bits:\n\txor\tesi,esi\n\tcmp\tebx,[clip_min_y]\t; if y >= top its not up\n\tjge\tshort ??a_not_up\n\tor\tesi,4\n\n??a_not_up:\n\tcmp\tebx,[clip_max_y]\t; if y <= bottom its not down\n\tjle\tshort ??a_not_down\n\tor\tesi,8\n\n??a_not_down:\n\tretn\n\n\n\t;*==================================================================\n\t;* PORTABLE end.\n\t;*==================================================================\n\n\t;*==================================================================\n\t;* Scan convert an edge.\n\t;* (eax,ebx) = (xa,ya), (ecx,edx) = (xb,yb)\n\t;*==================================================================\n??scan_convert:\n\tcmp\tebx,edx\n\tje\t??exit\t\t       \t\t; if (ya == yb) don't scan convert\n\tjl\tshort ??no_swap\t\t\t; if (ya < yb)  swap vertices\n\txchg\teax,ecx\n\txchg\tebx,edx\n\n??no_swap:\n\tsub\tedx,ebx \t\t\t; edx = (yb - ya)\n\tsub\tebx,[scanline_min]\n\tsal\tebx,2\n\tadd\tebx,[span_buff]\t\t\t; ebx = span_buff + 4(ya - clip_min_y)\n\tsub\tecx,eax\t\t\t\t; ecx = (xb - xa)\n\tje\t??v_scan\t\t\t; if the edge is vertical use a\n\t\t\t\t\t\t;  special case routine\n\tpush\teax\n\tmov\teax,ecx\t\t\t\t; eax = (xb - xa)\n\tmov\tecx,edx\t\t\t\t; ecx = (yb - ya)\n\tsal\tedx,1\n\tmov\t[realignment],edx\t\t; realignment = 2(yb - ya)\n\tcwd\n\tidiv\tcx\n\tcwde\n\tmovsx\tedx,dx\n\tmov\tedi,eax\t\t\t\t; edi = (xb - xa) / (yb - ya)\n\tmov\tesi,edx\n\tmov\tedx,ecx\n\tpop\teax\t\t\t\t; eax = xa\n\tneg\tedx\t\t\t\t; edx = -(yb - ya)\n\tsal\tesi,1\t\t\t\t; esi = 2[(xb - xa) % (yb - ya)]\n\tjns\tshort ??r_scan\t\t\t; scan to the left or right?\n\tneg\tesi\n\n\t;*==================================================================\n\t;* Edge scan conversion DDA moving down and to the left.\n\t;* eax = xpos, ebx = span to reference\n\t;*==================================================================\n\tcmp\tebx,[span_buff]\n\tjg\t??l_scan_convert\n\n??l_scan_convert_loop:\n\tcmp\t[DWORD PTR ebx],SLOT_VACANT    ; if the left slot of span is\n\tjne\tshort ??l_next_slot\t       ;   vacant fill it with xpos\n\tmov\t[ebx],ax\n\n??l_next_slot:\n\tmov\t[ebx + 2],ax\t\t       ; otherwise fill the right slot\n\t\t\t\t\t       ;   with xpos\n??l_scan_convert:\n\tdec\tecx\n\tjl\tshort ??exit\n\tadd\tebx,4\n\tadd\teax,edi\n\tadd\tedx,esi\n\tjle\tshort ??l_scan_convert_loop\n\tdec\teax\n\tsub\tedx,[realignment]\n\tjmp\t??l_scan_convert_loop\n\n\n\t;*==================================================================\n\t;* Edge scan conversion DDA moving down and to the right.\n\t;* eax = xpos, ebx = span to reference\n\t;*==================================================================\n??r_scan:\n\tcmp\tebx,[span_buff]\n\tjg\t??r_scan_convert\n\n??r_scan_convert_loop:\n\tcmp\t[DWORD PTR ebx],SLOT_VACANT    ; if the left slot of span is\n\tjne\tshort ??r_next_slot\t       ;   vacant fill it with xpos\n\tmov\t[ebx],ax\n\n??r_next_slot:\n\tmov\t[ebx + 2],ax\t\t       ; otherwise fill the right slot\n\t\t\t\t\t       ;   with xpos\n??r_scan_convert:\n\tdec\tecx\n\tjl\tshort ??exit\n\tadd\tebx,4\n\tadd\teax,edi\n\tadd\tedx,esi\n\tjle\tshort ??r_scan_convert_loop\n\tinc\teax\n\tsub\tedx,[realignment]\n\tjmp\t??r_scan_convert_loop\n\n\n\t;*==================================================================\n\t;* Scan convert a vertical edge.\n\t;* eax = xpos, ebx = span to reference\n\t;*==================================================================\n??v_scan:\n\tcmp\tebx,[span_buff]\n\tjg\t??v_scan_convert\n\n??v_scan_convert_loop:\n\tcmp\t[DWORD PTR ebx],SLOT_VACANT   ; if the left slot of span is\n \tjne\tshort ??v_next_slot\t      ;   vacant fill it with xpos\n\tmov\t[ebx],ax\n\n??v_next_slot:\n\tmov\t[ebx + 2],ax\t\t      ; otherwise fill the right slot\n\t\t\t\t\t      ;   with xpos\n??v_scan_convert:\n\tadd\tebx,4\n\tdec\tedx\n\tjge\t??v_scan_convert_loop\n\n??exit:\n\tretn\n\n\tENDP\tBuffer_Fill_Quad\n\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FILLRECT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : GraphicViewPortClass\t\t\t   *\n;*                                                                         *\n;*                    File Name : CLEAR.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : June 7, 1994   [PWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   GVPC::Fill_Rect -- draws a filled rectangle to a graphics buffer      *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n;***************************************************************************\n;* GVPC::FILL_RECT -- Fills a rectangular region of a graphic view port\t   *\n;*                                                                         *\n;* INPUT:\tWORD the left hand x pixel position of region\t\t   *\n;*\t\tWORD the upper x pixel position of region\t\t   *\n;*\t\tWORD the right hand x pixel position of region\t\t   *\n;*\t\tWORD the lower x pixel position of region\t\t   *\n;*\t\tUBYTE the color (optional) to clear the view port to\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* NOTE:\tThis function is optimized to handle viewport with no XAdd *\n;*\t\tvalue.  It also handles DWORD aligning the destination\t   *\n;*\t\twhen speed can be gained by doing it.\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/07/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_Fill_Rect C near\n\tUSES\teax,ebx,ecx,edx,esi,edi,ebp\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG    \tthis_object:DWORD\t\t\t; this is a member function\n\tARG\tx1_pixel:WORD\n\tARG\ty1_pixel:WORD\n\tARG\tx2_pixel:WORD\n\tARG\ty2_pixel:WORD\n\tARG    \tcolor:BYTE\t\t\t; what color should we clear to\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL\tVPwidth:DWORD\t\t; the width of the viewport\n\tLOCAL\tVPheight:DWORD\t\t; the height of the viewport\n\tLOCAL\tVPxadd:DWORD\t\t; the additional x offset of viewport\n\tLOCAL\tVPbpr:DWORD\t\t; the number of bytes per row of viewport\n\n\t;*===================================================================\n\t;* save off the viewport characteristics on the stack\n\t;*===================================================================\n\tmov\tebx,[this_object]\t\t\t\t; get a pointer to viewport\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\t; get width from viewport\n\tmov\tecx,[(GraphicViewPort ebx).GVPHeight]\t; get height from viewport\n\tmov\tedx,[(GraphicViewPort ebx).GVPXAdd]\t; get xadd from viewport\n\tadd\tedx,[(GraphicViewPort ebx).GVPPitch]\t; extra pitch of direct draw surface\n\tmov\t[VPwidth],eax\t\t\t\t; store the width of locally\n\tmov\t[VPheight],ecx\n\tmov\t[VPxadd],edx\n\tadd\teax,edx\n\tmov\t[VPbpr],eax\n\n\t;*===================================================================\n\t;* move the important parameters into local registers\n\t;*===================================================================\n\tmovsx\teax,[x1_pixel]\n\tmovsx\tebx,[y1_pixel]\n\tmovsx\tecx,[x2_pixel]\n\tmovsx\tedx,[y2_pixel]\n\n\t;*===================================================================\n\t;* Convert the x2 and y2 pixel to a width and height\n\t;*===================================================================\n\tcmp\teax,ecx\n\tjl\t??no_swap_x\n\txchg\teax,ecx\n\n??no_swap_x:\n\tsub\tecx,eax\n\tcmp\tebx,edx\n\tjl\t??no_swap_y\n\txchg\tebx,edx\n??no_swap_y:\n\tsub\tedx,ebx\n\tinc\tecx\n\tinc\tedx\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\tcmp\teax, [VPwidth]\t\t\t; compare with the max\n\tjge\t??out\t\t\t\t; starts off screen, then later\n\tjb\tshort ??sx_done\t\t\t; if it's not negative, it's ok\n\n\t;------ Clip source X to left edge of screen.\n\tadd\tecx, eax\t\t\t; Reduce width (add in negative src X).\n\txor\teax, eax\t\t\t; Clip to left of screen.\n??sx_done:\n\n\t;*===================================================================\n\t;* Bounds check source Y.\n\t;*===================================================================\n\tcmp\tebx, [VPheight]\t\t\t; compare with the max\n\tjge\t??out\t\t\t\t; starts off screen, then later\n\tjb\tshort ??sy_done\t\t\t; if it's not negative, it's ok\n\n\t;------ Clip source Y to top edge of screen.\n\tadd\tedx, ebx\t\t\t; Reduce height (add in negative src Y).\n\txor\tebx, ebx\t\t\t; Clip to top of screen.\n\n??sy_done:\n\t;*===================================================================\n\t;* Bounds check width versus width of source and dest view ports\n\t;*===================================================================\n\tpush\tebx\t\t\t\t; save off ebx for later use\n\tmov\tebx,[VPwidth]\t\t\t; get the source width\n\tsub\tebx, eax\t\t\t; Maximum allowed pixel width (given coordinates).\n\tsub\tebx, ecx\t\t\t; Pixel width undershoot.\n\tjns\tshort ??width_ok\t\t; if not signed no adjustment necessary\n\tadd\tecx, ebx\t\t\t; Reduce width to screen limits.\n\n??width_ok:\n\tpop\tebx\t\t\t\t; restore ebx to old value\n\n\t;*===================================================================\n\t;* Bounds check height versus height of source view port\n\t;*===================================================================\n\tpush\teax\t\t\t\t; save of eax for later use\n\tmov\teax, [VPheight]\t\t\t; get the source height\n\tsub\teax, ebx\t\t\t; Maximum allowed pixel height (given coordinates).\n\tsub\teax, edx\t\t\t; Pixel height undershoot.\n\tjns\tshort ??height_ok\t\t; if not signed no adjustment necessary\n\tadd\tedx, eax\t\t\t; Reduce height to screen limits.\n??height_ok:\n\tpop\teax\t\t\t\t; restore eax to old value\n\n\t;*===================================================================\n\t;* Perform the last minute checks on the width and height\n\t;*===================================================================\n\tor\tecx,ecx\n\tjz\t??out\n\n\tor\tedx,edx\n\tjz\t??out\n\n\tcmp\tecx,[VPwidth]\n\tja\t??out\n\tcmp\tedx,[VPheight]\n\tja\t??out\n\n\t;*===================================================================\n\t;* Get the offset into the virtual viewport.\n\t;*===================================================================\n\txchg\tedi,eax\t\t\t; save off the contents of eax\n\txchg\tesi,edx\t\t\t;   and edx for size test\n\tmov\teax,ebx\t\t\t; move the y pixel into eax\n\tmul\t[VPbpr]\t\t\t; multiply by bytes per row\n\tadd\tedi,eax\t\t\t; add the result into the x position\n\tmov\tebx,[this_object]\n\tadd\tedi,[(GraphicViewPort ebx).GVPOffset]\n\n\tmov\tedx,esi\t\t\t; restore edx back to real value\n\tmov\teax,ecx\t\t\t; store total width in ecx\n\tsub\teax,[VPwidth]\t\t; modify xadd value to include clipped\n\tsub\t[VPxadd],eax\t\t;   width bytes (subtract a negative number)\n\n\t;*===================================================================\n\t; Convert the color byte to a DWORD for fast storing\n\t;*===================================================================\n\tmov\tal,[color]\t\t\t\t; get color to clear to\n\tmov\tah,al\t\t\t\t\t; extend across WORD\n\tmov\tebx,eax\t\t\t\t\t; extend across DWORD in\n\tshl\teax,16\t\t\t\t\t;   several steps\n\tmov\tax,bx\n\n\t;*===================================================================\n\t; If there is no row offset then adjust the width to be the size of\n\t;   the entire viewport and adjust the height to be 1\n\t;*===================================================================\n\tmov\tesi,[VPxadd]\n\tor\tesi,esi\t\t\t\t\t; set the flags for esi\n\tjnz\t??row_by_row_aligned\t\t\t;   and act on them\n\n\txchg\teax,ecx\t\t\t\t\t; switch bit pattern and width\n\tmul\tedx\t\t\t\t\t; multiply by edx to get size\n\txchg\teax,ecx\t\t\t\t\t; switch size and bit pattern\n\tmov\tedx,1\t\t\t\t\t; only 1 line off view port size to do\n\n\t;*===================================================================\n\t; Find out if we should bother to align the row.\n\t;*===================================================================\n??row_by_row_aligned:\n\tmov\tebp,ecx\t\t\t\t\t; width saved in ebp\n\tcmp\tecx,OPTIMAL_BYTE_COPY\t\t\t; is it worth aligning them?\n\tjl\t??row_by_row\t\t\t\t;   if not then skip\n\n\t;*===================================================================\n\t; Figure out the alignment offset if there is any\n\t;*===================================================================\n\tmov\tebx,edi\t\t\t\t\t; get output position\n\tand\tebx,3\t\t\t\t\t;   is there a remainder?\n\tjz\t??aligned_loop\t\t\t\t;   if not we are aligned\n\txor\tebx,3\t\t\t\t\t; find number of align bytes\n\tinc\tebx\t\t\t\t\t; this number is off by one\n\tsub\tebp,ebx\t\t\t\t\t; subtract from width\n\n\t;*===================================================================\n\t; Now that we have the alignment offset copy each row\n\t;*===================================================================\n??aligned_loop:\n\tmov\tecx,ebx\t\t\t\t\t; get number of bytes to align\n\trep\tstosb\t\t\t\t\t;   and move them over\n\tmov\tecx,ebp\t\t\t\t\t; get number of aligned bytes\n\tshr\tecx,2\t\t\t\t\t;   convert to DWORDS\n\trep\tstosd\t\t\t\t\t;   and move them over\n\tmov\tecx,ebp\t\t\t\t\t; get number of aligned bytes\n\tand\tecx,3\t\t\t\t\t;   find the remainder\n\trep\tstosb\t\t\t\t\t;   and move it over\n\tadd\tedi,esi\t\t\t\t\t; fix the line offset\n\tdec\tedx\t\t\t\t\t; decrement the height\n\tjnz\t??aligned_loop\t\t\t\t; if more to do than do it\n\tjmp\t??exit\t\t\t\t\t; we are all done\n\n\t;*===================================================================\n\t; If not enough bytes to bother aligning copy each line across a byte\n\t;    at a time.\n\t;*===================================================================\n??row_by_row:\n\tmov\tecx,ebp\t\t\t\t\t; get total width in bytes\n\trep\tstosb\t\t\t\t\t; store the width\n\tadd\tedi,esi\t\t\t\t\t; handle the xadd\n\tdec\tedx\t\t\t\t\t; decrement the height\n\tjnz\t??row_by_row\t\t\t\t; if any left then next line\n??out:\n??exit:\n\tret\n\tENDP\tBuffer_Fill_Rect\n\nEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FINDARGV.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/wwlib32/misc/rcs/findargv.cpp 1.2 1994/04/22 10:29:28 scott_bowen Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : findargv \t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : findargv.C                               *\n *                                                                         *\n *                   Programmer : Jeff Wilson\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Start Date : January 14, 1993                         *\n *                                                                         *\n *                  Last Update : May 20, 1993   [PWG]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Find_Argv -- Checks to see if string is in arguement              \t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"wwstd.h\"\n#include <dos.h>\n#include <stdio.h>\n#include <string.h>\n#include <process.h>\n\n\n\n\n/***************************************************************************\n * Find_Argv -- Checks to see if string is in arguement                \t\t*\n *                                                                         *\n * INPUT: char *str - string to search for.                                *\n *                                                                         *\n * OUTPUT: NULL if not found else pointer to string.                       *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/14/1993  SB : Created.                                             *\n *=========================================================================*/\n\n//static char command [ 256 ] ;\n#pragma on (argsused)\nchar * __cdecl Find_Argv(char const)\n{\n\treturn (NULL);\n\n\n#ifdef NOT_FOR_WIN95\nchar * __cdecl Find_Argv(char const *str)\n{\n\tchar   * ptr ;\n\tstatic   startup_flag = 0 ;\n\n\tif ( ! startup_flag )\n\t{\n\t  startup_flag = 1 ;\n\t  getcmd ( command )\t;\n\t}\n\n\tif ( ! strlen(str) ) return NULL ;\n\treturn strstr ( command , str ) ;\n#endif\n}\n\n\n\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FINDFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : FINDFILE.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : August 21, 1991                          *\n *                                                                         *\n *                  Last Update : September 29, 1993   [SKB]               *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Find_File_Index -- Finds the FileTable index number for a given file. *\n *   Find_File -- Checks if a file is immediatly available.                *\n *   Get_FileData -- Gets a pointer back to the correct file.              *\n *   Find_File -- Checks if a file is immediatly available.                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n#ifndef _FILE_H\n#include \"_file.h\"\n#endif\n\n#include <direct.h>\n#include <dos.h>\n#include <fcntl.h>\n#include <io.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <search.h>\n#include <sys\\stat.h>\n\n\n\n/***************************************************************************\n * FIND_FILE -- Checks if a file is immediatly available.                  *\n *                                                                         *\n *    Use this function to determine if a file is immediatly available.    *\n *    This routine will NOT request for the proper disk to be inserted     *\n *    if the file could not be found.  Use File_Exists for that feature.   *\n *    The Westwood file I/O system does NOT have to be initialized as      *\n *    a prerequisit to using this function.                                *\n *                                                                         *\n * INPUT:   file_name   -- Name of the file to check.                      *\n *                                                                         *\n * OUTPUT:  Returns the disk number that the file exits on (A=1, B=2, etc) *\n *                                                                         *\n * WARNINGS:   This sets the current drive to the drive that contains the  *\n *             specified file (if it is found).                            *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/14/1991 JLB : Created.                                             *\n *   03/14/1992 JLB : Modified for Amiga compatability.                    *\n *   01/11/1993 SKB : Modified for CD-ROM searches.                        *\n *=========================================================================*/\nWORD cdecl Find_File(BYTE const *file_name)\n{\n\tFileDataType\t*filedata = NULL;\n\tWORD\t\t\t\tindex;\t\t\t\t\t// File index (if any).\n\tWORD\t\t\t\tdisk;\t\t\t\t\t\t// Disk number of file (if in filetable).\n\t\n\t/*\n\t**\tIf the filename is invalid then it errors out as if the file wasn't\n\t**\tfound (naturally).\n\t*/\n\tif (!file_name) return(FALSE);\n\n\t/*\n\t**\tDetermine if the file has a file table entry.  If it does, then\n\t**\tspecial checks and processing must occur.\n\t** Also, if it is in memory, return with it.\n\t*/\n\tindex = Find_File_Index(file_name);\n\tfiledata = &FileDataPtr[index];\n\n\tif (index != ERROR) {\n\n\t\t// If the file is currently cached, return TRUE that it was found.\n\t\tif (filedata->Ptr) {\n\t\t\treturn (TRUE);\n\t\t}\n\t}\n\n\n\t/*\n\t**\tAlways check the current directory for the file.  Only if it can't\n\t**\tbe found are furthur measures required.\n\t*/\n\tDiskNumber = ERROR;\t\t// This indicates file exists in current directory.\n\n\t\t\n \t#if (LIB_CDROM)\n\t\tibm_setdisk(*StartPath - 'A');\n \t#endif\n\n\t/*\n\t**\tCheck the current directory by attempting to open with READ access.\n\t*/\n\t{\n\t\tWORD\thandle;\n\t\t\n\t\tCallingDOSInt++;\n\t\thandle = open(file_name, O_RDONLY | O_BINARY, S_IREAD);\n\t\tCallingDOSInt--;\n\t\tif (handle != ERROR) \n\t\t{\n\t\t   //\tWORD\td;\n\t\t\tunsigned d ;\n\n\t\t\tCallingDOSInt++;\n\t\t\tclose(handle);\n\t\t\t// d = getdisk();\n\t\t\t_dos_getdrive ( & d) ;\n\t\t\tCallingDOSInt--;\n\t\t\treturn(d);\n\t\t}\n\t}\n\t\n\t\t\n\tif (index != ERROR) {\n\n\t\tdisk = filedata->Disk;\n\t\t/*\n\t\t**\tIf the file is in a packed file, then search for the packed file\n\t\t**\tinstead of the specified one.\n\t\t*/\n\t\tif (index != ERROR && (filedata->Flag & FILEF_PACKED)) {\n\t\t\tfiledata = &FileDataPtr[disk];\n\t\t\treturn (Find_File(filedata->Name));\n\t\t}\n\n\t}\n\n\t/*\n\t**\tIt could not be found on the current drive, so search the other\n\t**\tdrives if allowed to do so.\n\t*/\n\tif (!MultiDriveSearch) {\n\t\treturn(FALSE);\n\t}\n\n#if (LIB_CDROM)\n\t// If we were unable to find the file on the hard drive, change\n\t// drives to the CD rom drive and see if it is there.\n\tibm_setdisk(*DataPath - 'A');\n \n\t{\n\t\tWORD\thandle;\n\t\t\n\t\tHard_Error_Occured = 0;\n\n\t  \thandle = Open_File_With_Recovery( file_name, MODE_OLDFILE );\n\n\t\tif (handle != FILEOPENERROR) {\n\t\t\tFILECLOSE(handle);\n\t\t\treturn(ibm_getdisk() + 1);\n\t\t}\n\t}\n\n\tibm_setdisk(*StartPath - 'A');\n\treturn (FALSE);\n#else\n\n\t{\n\t\tWORD\tstart_drive;\t// Original current drive number.\n\n\t\t/*\n\t\t**\tRecord the current drive for restoring later in case of failure.\n\t\t*/\n\t\tCallingDOSInt++;\n\t\tstart_drive = getdisk();\n\t\tCallingDOSInt--;\n\n\t\t/*\n\t\t**\tSweep backward from the last real drive to the first, looking for the\n\t\t**\tfile on each in turn.\n\t\t*/\n\t\tfor (index = MaxDevice; index != -1; index--) {\n\t\t\tif (Is_Device_Real(index)) {\n\t\t\t\tCallingDOSInt++;\n\t\t\t \tsetdisk(index);\n\t\t\t\tCallingDOSInt--;\n\n\t\t\t\t{\n\t\t\t\t\tWORD\thandle;\n\n\t\t\t\t\tCallingDOSInt++;\n\t\t\t\t\thandle = open(file_name, O_RDONLY | O_BINARY, S_IREAD);\n\t\t\t\t\tCallingDOSInt--;\n\t\t\t\t\tif (handle != ERROR) {\n\t\t\t\t\t\tCallingDOSInt++;\n\t\t\t\t\t\tclose(handle);\n\t\t\t\t\t\tCallingDOSInt--;\n\t\t\t\t\t\tDiskNumber = index+1;\n\t\t\t\t\t\treturn (DiskNumber);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tCallingDOSInt++;\n\t\tsetdisk(start_drive);\n\t\tCallingDOSInt--;\n\t}\n\t\n\treturn(FALSE);\n#endif\n\n}\n\n\n/***************************************************************************\n * FIND_FILE_INDEX -- Finds the FileTable index number for a given file.   *\n *                                                                         *\n *    This function searches the FileTable and returns with the index of   *\n *    the matching file.  If the file doesn't exist in the table, then     *\n *    ERROR is returned.  It does not care about case.                     *\n *                                                                         *\n * INPUT:   filename -- Pointer to the filename to check.                  *\n *                                                                         *\n * OUTPUT:  Returns with the index into the FileTable.  If the file does   *\n *          not exist in the file table, then ERROR is returned.           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/09/1991 JLB : Created.                                             *\n *   06/11/1993 JLB : Sorts and binary searches the file table.            *\n *=========================================================================*/\nPRIVATE int Comp_Func(const void *p1, const void *p2)\n{\n\treturn(strcmp((char *) ((FileDataType*)p1)->Name, (char *) ((FileDataType*)p2)->Name));\n}\nWORD cdecl Find_File_Index(BYTE const *filename)\n{\n\tFileDataType\t*filedata;\t\t\t// File entry pointer.\n\tFileDataType\tkey;\t\t\t\t\t// Working file data type var.\n\n\t/*\n\t**\tPerform a binary search on the presorted filetable.\n\t*/\n\tif (filename) {\n\n\t\tfiledata = NULL;\n\t\tkey.Name = (BYTE *) strupr((char *)filename);\n\t\tif (strstr((char *)key.Name, (char *)\".PAK\")) {\n\t\t\t\n\t\t\t/*\n\t\t\t** If the FileData table was not loaded from the disk then the PAK files are\n\t\t\t** not sorted so Perform a linear search for the pak files.\n\t\t\t** Otherwise the files are sorted so speed things up by doing a bsearch.\n\t\t\t*/\n\t\t\tif (FileData == FileDataPtr) {\n\t\t\t\tfiledata = (FileDataType *) lfind(&key, FileDataPtr, (size_t *) &NumPAKFiles, sizeof(FileDataType), Comp_Func);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfiledata = (FileDataType *)bsearch(&key, FileDataPtr, NumPAKFiles, sizeof(FileDataType), Comp_Func);\n\t\t\t}\n\n\t\t} else {\n\t\t\t\t\n\t\t\t/*\n\t\t\t**\tPerform a binary search for the regular files.\n\t\t\t*/\n\t\t\tfiledata = (FileDataType *)bsearch(&key, &FileDataPtr[NumPAKFiles], NumFiles, sizeof(FileDataType), Comp_Func);\n\t\t}\n\n\t\t// Return the element in the array if file was found in table.\n\t\tif (filedata) {\n\t\t\treturn (filedata - FileDataPtr);\n\t\t\t//return ((WORD)((((LONG)filedata) - ((LONG)FileDataPtr)) / sizeof(FileDataType)));\n\t\t}\n\t}\n\treturn(ERROR);\n}\n\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FONT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\t\t\t\t\t\t/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : FONT.C                                   *\n *                                                                         *\n *                   Programmer : David Dettmer                            *\n *                                                                         *\n *                  Last Update : July 20, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Char_Pixel_Width -- Return pixel width of a character.\t\t\t\t\t\t*\n *   String_Pixel_Width -- Return pixel width of a string of characters.   *\n *   Get_Next_Text_Print_XY -- Calculates X and Y given ret value from Text_P*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"font.h\"\n#include <malloc.h>\n#include <dos.h>\n#include <fcntl.h>\n#include <io.h>\n#include <sys\\stat.h>\n#include <string.h>\n#include <wwstd.h>\n\n\n/***************************************************************************\n * CHAR_PIXEL_WIDTH -- Return pixel width of a character.\t\t\t\t\t\t*\n *                                                                         *\n *    Retreives the pixel width of a character from the font width block.\t*\n *                                                                         *\n * INPUT:      Character.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     Pixel width of a string of characters.                      *\n *                                                                         *\n * WARNINGS:   Set_Font must have been called first.                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/31/1992 DRD : Created.                                             *\n *   06/30/1994 SKB : Converted to 32 bit library.                         *\n *=========================================================================*/\nint __cdecl Char_Pixel_Width(char chr)\n{\n\tint\twidth;\n\n\twidth = (unsigned char)*(FontWidthBlockPtr + (unsigned char)chr) + FontXSpacing;\n\n\treturn(width);\n}\n\n\n/***************************************************************************\n * STRING_PIXEL_WIDTH -- Return pixel width of a string of characters.     *\n *                                                                         *\n *    Calculates the pixel width of a string of characters.  This uses     *\n *\t\tthe font width block for the widths.\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:      Pointer to string of characters.                            *\n *                                                                         *\n * OUTPUT:     Pixel width of a string of characters.                      *\n *                                                                         *\n * WARNINGS:   Set_Font must have been called first.                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/30/1992 DRD : Created.                                             *\n *   01/31/1992 DRD : Use Char_Pixel_Width.                                *\n *   06/30/1994 SKB : Converted to 32 bit library.                         *\n *=========================================================================*/\nunsigned int __cdecl String_Pixel_Width(char const *string)\n{\n\tWORD\twidth;\t\t\t\t// Working accumulator of string width.\n\tWORD\tlargest = 0;\t\t// Largest recorded width of the string.\n\n\tif (!string) return(0);\n\n\twidth = 0;\n\twhile (*string) {\n\t\tif (*string == '\\r') {\n\t\t\tstring++;\n\t\t\tlargest = MAX(largest, width);\n\t\t\twidth = 0;\n\t\t} else {\n\t\t\twidth += Char_Pixel_Width(*string++);\t// add each char's width\n\t\t}\n\t}\n\tlargest = MAX(largest, width);\n\treturn(largest);\n}\n\n\n\n/***************************************************************************\n * GET_NEXT_TEXT_PRINT_XY -- Calculates X and Y given ret value from Text_P*\n *                                                                         *\n *                                                                         *\n * INPUT:   VVPC& vp - viewport that was printed to.                       *\n *          unsigned long offset - offset that Text_Print returned.                *\n *          INT *x - x return value.                                       *\n *          INT *y - y return value.                                       *\n *                                                                         *\n * OUTPUT:  x and y are set.                                               *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/20/1994 SKB : Created.                                             *\n *=========================================================================*/\nVOID __cdecl Get_Next_Text_Print_XY(GraphicViewPortClass& gp, unsigned long offset, INT *x, INT *y)\n{\n\tINT\tbuffwidth;\n\n\tif (offset) {\n\t\tbuffwidth = gp.Get_Width() + gp.Get_XAdd();\n\t\toffset -= gp.Get_Offset();\n\t\t*x = offset % buffwidth;\n\t\t*y = offset / buffwidth;\n\t} else {\n\t\t*x = *y = 0;\n\t}\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/FTPUTPIX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : GraphicViewPortClass\t\t\t   *\n;*                                                                         *\n;*                    File Name : GETPIXEL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : June 7, 1994   [PWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVPC::Buffer_Get_Pixel -- get the colour of a pixel at given coords   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n;***************************************************************************\n;* VVPC::GET_PIXEL -- Gets a pixel from the current view port\t\t   *\n;*                                                                         *\n;* INPUT:\tWORD the x pixel on the screen.\t\t\t\t   *\n;*\t\tWORD the y pixel on the screen.\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      UBYTE the pixel at the specified location\t\t   *\n;*                                                                         *\n;* WARNING:\tIf pixel is to be placed outside of the viewport then\t   *\n;*\t\tthis routine will abort.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/07/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_Get_Pixel C near\n\tUSES\tebx,ecx,edx,edi\n\n\tARG    \tthis_object:DWORD\t\t\t\t; this is a member function\n\tARG\tx_pixel:DWORD\t\t\t\t; x position of pixel to set\n\tARG\ty_pixel:DWORD\t\t\t\t; y position of pixel to set\n\n\t;*===================================================================\n\t; Get the viewport information and put bytes per row in ecx\n\t;*===================================================================\n\tmov\tebx,[this_object]\t\t\t\t; get a pointer to viewport\n\txor\teax,eax\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get the correct offset\n\tmov\tecx,[(GraphicViewPort ebx).GVPHeight]\t; edx = height of viewport\n\tmov\tedx,[(GraphicViewPort ebx).GVPWidth]\t; ecx = width of viewport\n\n\t;*===================================================================\n\t; Verify that the X pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[x_pixel]\t\t\t\t; find the x position\n\tcmp\teax,edx\t\t\t\t\t;   is it out of bounds\n\tjae\tshort ??exit\t\t\t\t; if so then get out\n\tadd\tedi,eax\t\t\t\t\t; otherwise add in offset\n\n\t;*===================================================================\n\t; Verify that the Y pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[y_pixel]\t\t\t\t; get the y position\n\tcmp\teax,ecx\t\t\t\t\t;  is it out of bounds\n\tjae\t??exit\t\t\t\t\t; if so then get out\n\tadd\tedx,[(GraphicViewPort ebx).GVPXAdd]\t; otherwise find bytes per row\n\tadd\tedx,[(GraphicViewPort ebx).GVPPitch]\t; otherwise find bytes per row\n\tmul\tedx\t\t\t\t\t; offset = bytes per row * y\n\tadd\tedi,eax\t\t\t\t\t; add it into the offset\n\n\t;*===================================================================\n\t; Write the pixel to the screen\n\t;*===================================================================\n\txor\teax,eax\t\t\t\t\t; clear the word\n\tmov\tal,[edi]\t\t\t\t; read in the pixel\n??exit:\n\tret\n\tENDP\tBuffer_Get_Pixel\n\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/GBUFFER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : GBUFFER.CPP                              *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 3, 1994                              *\n *                                                                         *\n *                  Last Update : October 9, 1995   []                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   VVPC::VirtualViewPort -- Default constructor for a virtual viewport   *\n *   VVPC:~VirtualViewPortClass -- Destructor for a virtual viewport       *\n *   VVPC::Clear -- Clears a graphic page to correct color                 *\n *   VBC::VideoBufferClass -- Lowlevel constructor for video buffer class  *\n *   GVPC::Change -- Changes position and size of a Graphic View Port      *\n *   VVPC::Change -- Changes position and size of a Video View Port      \t*\n *   Set_Logic_Page -- Sets LogicPage to new buffer                        *\n *   GBC::DD_Init -- Inits a direct draw surface for a GBC                 *\n *   GBC::Init -- Core function responsible for initing a GBC              *\n *   GBC::Lock -- Locks a Direct Draw Surface                              *\n *   GBC::Unlock -- Unlocks a direct draw surface                          *\n *   GBC::GraphicBufferClass -- Default constructor (requires explicit init)*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef GBUFFER_H\n#include \"gbuffer.h\"\n#include \"misc.h\"\n#endif\n#pragma inline\n\nint\t\tTotalLocks;\nBOOL \tAllowHardwareBlitFills = TRUE;\n\n\n//int\tCacheAllowed;\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n/***************************************************************************\n * GVPC::GRAPHICVIEWPORTCLASS -- Constructor for basic view port class     *\n *                                                   m                      *\n * INPUT:\t\tGraphicBufferClass * gbuffer\t- buffer to attach to\t\t\t*\n *\t\t\t\t\tint x\t\t\t\t\t\t\t\t- x offset into buffer\t\t\t*\n *\t\t\t\t\tint y\t\t\t\t\t\t\t\t- y offset into buffer\t\t\t*\n *\t\t\t\t\tint w\t\t\t\t\t\t\t\t- view port width in pixels   *\n *\t\t\t\t\tint h   \t\t\t\t\t\t\t- view port height in pixels\t*\n *                                                                         *\n * OUTPUT:     Constructors may not have a return value\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/09/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicViewPortClass::GraphicViewPortClass(GraphicBufferClass *gbuffer, int x, int y, int w, int h) :\n\tLockCount(0),\n\tGraphicBuff(NULL)\n{\n\tAttach(gbuffer, x, y, w, h);\n}\n\n/***************************************************************************\n * GVPC::GRAPHICVIEWPORTCLASS -- Default constructor for view port class   *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/09/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicViewPortClass::GraphicViewPortClass(void)\n{\n}\n\n/***************************************************************************\n * GVPC::~GRAPHICVIEWPORTCLASS -- Destructor for GraphicViewPortClass\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     A destructor may not return a value.                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/10/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicViewPortClass::~GraphicViewPortClass(void)\n{\n \tOffset\t\t\t= 0;\n\tWidth\t\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record width of Buffer\n\tHeight\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record height of Buffer\n\tXAdd\t\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XAdd of Buffer\n\tXPos\t\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XPos of Buffer\n\tYPos\t\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record YPos of Buffer\n\tPitch\t\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record width of Buffer\n\tIsDirectDraw\t= FALSE;\n\tLockCount\t\t= 0;\n\tGraphicBuff\t\t= NULL;\n}\n\n/***************************************************************************\n * GVPC::ATTACH -- Attaches a viewport to a buffer class                   *\n *                                                                         *\n * INPUT:\t\tGraphicBufferClass *g_buff\t- pointer to gbuff to attach to  *\n *\t\t\t\t\tint x                     - x position to attach to\t\t\t*\n *\t\t\t\t\tint y \t\t\t\t\t\t\t- y position to attach to\t\t\t*\n *\t\t\t\t\tint w\t\t\t\t\t\t\t- width of the view port\t\t\t*\n *\t\t\t\t\tint h\t\t\t\t\t\t\t- height of the view port\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/10/1994 PWG : Created.                                             *\n *=========================================================================*/\nvoid GraphicViewPortClass::Attach(GraphicBufferClass *gbuffer, int x, int y, int w, int h)\n{\n\t/*======================================================================*/\n\t/* Can not attach a Graphic View Port if it is actually the physical\t\t*/\n\t/*\t   representation of a Graphic Buffer.\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (this == Get_Graphic_Buffer())  {\n\t\treturn;\n\t}\n\n\t/*======================================================================*/\n\t/* Verify that the x and y coordinates are valid and placed within the\t*/\n\t/*\t\tphysical buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (x < 0) \t\t\t\t\t\t\t\t\t\t// you cannot place view port off\n\t\tx = 0;\t\t\t\t\t\t\t\t\t\t//\t\tthe left edge of physical buf\n\tif (x >= gbuffer->Get_Width())\t\t\t// you cannot place left edge off\n\t\tx = gbuffer->Get_Width() - 1;\t\t\t//\t\tthe right edge of physical buf\n\tif (y < 0) \t\t\t\t\t\t\t\t\t\t// you cannot place view port off\n\t\ty = 0;\t\t\t\t\t\t\t\t\t\t//\t\tthe top edge of physical buf\n\tif (y >= gbuffer->Get_Height()) \t\t\t// you cannot place view port off\n\t\ty = gbuffer->Get_Height() - 1;\t\t//\t\tbottom edge of physical buf\n\n\t/*======================================================================*/\n\t/* Adjust the width and height of necessary\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (x + w > gbuffer->Get_Width()) \t\t// if the x plus width is larger\n\t\tw = gbuffer->Get_Width() - x;\t\t\t//\t\tthan physical, fix width\n\n\tif (y + h > gbuffer->Get_Height()) \t\t// if the y plus height is larger\n\t\th = gbuffer->Get_Height() - y;\t\t//\t\tthan physical, fix height\n\n\t/*======================================================================*/\n\t/* Get a pointer to the top left edge of the buffer.\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n \tOffset \t\t= gbuffer->Get_Offset() + ((gbuffer->Get_Width()+gbuffer->Get_Pitch()) * y) + x;\n\n\t/*======================================================================*/\n\t/* Copy over all of the variables that we need to store.\t\t\t\t\t\t*/\n\t/*======================================================================*/\n \tXPos\t\t\t= x;\n \tYPos\t\t\t= y;\n \tXAdd\t\t\t= gbuffer->Get_Width() - w;\n \tWidth\t\t\t= w;\n \tHeight\t\t= h;\n\tPitch\t\t\t= gbuffer->Get_Pitch();\n \tGraphicBuff = gbuffer;\n\tIsDirectDraw= gbuffer->IsDirectDraw;\n}\n\n\n/***************************************************************************\n * GVPC::CHANGE -- Changes position and size of a Graphic View Port        *\n *                                                                         *\n * INPUT:   \tint the new x pixel position of the graphic view port      *\n *\t\t\t\t\tint the new y pixel position of the graphic view port\t\t*\n *\t\t\t\t\tint the new width of the viewport in pixels\t\t\t\t\t\t*\n *\t\t\t\t\tint the new height of the viewport in pixels\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:  \tBOOL whether the Graphic View Port could be sucessfully     *\n *\t\t\t\t      resized.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:   You may not resize a Graphic View Port which is derived \t\t*\n *\t\t\t\t\t\tfrom a Graphic View Port Buffer, \t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/14/1994 SKB : Created.                                             *\n *=========================================================================*/\nBOOL GraphicViewPortClass::Change(int x, int y, int w, int h)\n{\n\t/*======================================================================*/\n\t/* Can not change a Graphic View Port if it is actually the physical\t\t*/\n\t/*\t   representation of a Graphic Buffer.\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (this == Get_Graphic_Buffer())  {\n\t\treturn(FALSE);\n\t}\n\n\t/*======================================================================*/\n\t/* Since there is no allocated information, just re-attach it to the\t\t*/\n\t/*\t\texisting graphic buffer as if we were creating the\t\t\t\t\t\t*/\n\t/*\t\tGraphicViewPort.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tAttach(Get_Graphic_Buffer(), x, y, w, h);\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * GBC::DD_INIT -- Inits a direct draw surface for a GBC                   *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/09/1995     : Created.                                             *\n *=========================================================================*/\nvoid GraphicBufferClass::DD_Init(GBC_Enum flags)\n{\n\t//\n\t// Create the direct draw surface description\n\t//\n\tmemset (&VideoSurfaceDescription , 0 , sizeof ( VideoSurfaceDescription ));\n\n\tVideoSurfaceDescription.dwSize\t\t\t= sizeof( VideoSurfaceDescription );\n\tVideoSurfaceDescription.dwFlags \t\t\t= DDSD_CAPS;\n\tVideoSurfaceDescription.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;\n\n\n\tif (!(flags & GBC_VISIBLE)) {\n\t\tVideoSurfaceDescription.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;\n\t\tVideoSurfaceDescription.dwFlags \t\t  |=\tDDSD_HEIGHT | DDSD_WIDTH;\n\t\tVideoSurfaceDescription.dwHeight\t\t\t= Height;\n\t\tVideoSurfaceDescription.dwWidth\t\t\t= Width;\n\t}\n\n\t//\n\t// Need to set the DDSCAPS_MODEX  flag if we want a 320 wide mode\n\t//\n\tif ( Width == 320 ) {\n\t\tVideoSurfaceDescription.ddsCaps.dwCaps |= DDSCAPS_MODEX;\n\t}\n\n\t//\n\t// Call CreateSurface\n\t//\n\tDirectDrawObject->CreateSurface( &VideoSurfaceDescription , &VideoSurfacePtr , NULL);\n\tAllSurfaces.Add_DD_Surface (VideoSurfacePtr);\n\n\tif ( GBC_VISIBLE & flags ){\n\t\tPaletteSurface=VideoSurfacePtr;\n\t}\n\n\tAllocated\t\t= FALSE;\t\t\t//\teven if system alloced, dont flag it cuz\n\t\t\t\t\t\t\t\t\t\t\t//   we dont want it freed.\n\tIsDirectDraw\t= TRUE;\t\t\t//\tflag it as a video surface\n\tOffset\t\t\t= NOT_LOCKED;\t//\tflag it as unavailable for reading or writing\n\tLockCount\t\t= 0;\t\t\t\t//  surface is not locked\n}\n\n\nvoid GraphicBufferClass::Attach_DD_Surface (GraphicBufferClass * attach_buffer)\n{\n\tVideoSurfacePtr->AddAttachedSurface (attach_buffer->Get_DD_Surface());\n}\n\n\n/***************************************************************************\n * GBC::INIT -- Core function responsible for initing a GBC                *\n *                                                                         *\n * INPUT:\t\tint \t\t- the width in pixels of the GraphicBufferClass    *\n *\t\t\t\t\tint\t\t- the heigh in pixels of the GraphicBufferClass\t\t*\n *\t\t\t\t\tvoid *\t- pointer to user supplied buffer (system will\t\t*\n *\t\t\t\t\t\t\t\t  allocate space if buffer is NULL)\t\t\t\t\t\t*\n *\t\t\t\t\tlong\t\t- size of the user provided buffer\t\t\t\t\t\t*\n *\t\t\t\t\tGBC_Enum\t- flags if this is defined as a direct draw\t\t\t*\n *\t                       surface\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/09/1995     : Created.                                             *\n *=========================================================================*/\nvoid GraphicBufferClass::Init(int w, int h, void *buffer, long size, GBC_Enum flags)\n{\n\tSize\t\t\t= size;\t\t\t\t\t\t\t\t\t// find size of physical buffer\n\tWidth\t\t\t= w;\t\t\t\t\t\t\t\t\t\t// Record width of Buffer\n\tHeight\t\t= h;\t\t\t\t\t\t\t\t\t\t// Record height of Buffer\n\n\t//\n\t// If the surface we are creating is a direct draw object then\n\t//   we need to do a direct draw init.  Otherwise we will do\n\t//   a normal alloc.\n\t//\n\tif (flags & (GBC_VIDEOMEM | GBC_VISIBLE)) {\n\t\tDD_Init(flags);\n\t} else {\n\t\tif (buffer) {\t\t\t\t\t\t\t\t\t\t// if buffer is specified\n\t\t\tBuffer\t\t= (BYTE *)buffer;\t\t\t\t//\t\tpoint to it and mark\n\t\t\tAllocated\t= FALSE;\t\t\t\t\t\t\t//\t\tit as user allocated\n\t\t} else {\n\t\t\tif (!Size) Size = w*h;\n\t\t\tBuffer\t\t= new BYTE[Size];\t\t\t\t// otherwise allocate it and\n\t\t\tAllocated\t= TRUE;\t\t\t\t\t\t\t//\t\tmark it system alloced\n\t\t}\n\t\tOffset\t\t\t= (long)Buffer;\t\t\t\t// Get offset to the buffer\n\t\tIsDirectDraw\t= FALSE;\n\t}\n\n\tPitch\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record width of Buffer\n\tXAdd\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XAdd of Buffer\n\tXPos\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XPos of Buffer\n\tYPos\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record YPos of Buffer\n\tGraphicBuff\t= this;\t\t\t\t\t\t\t\t\t// Get a pointer to our self\n}\n\n\n/***********************************************************************************************\n * GBC::Un_Init -- releases the video surface belonging to this gbuffer                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/6/96 12:44PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid GraphicBufferClass::Un_Init (void)\n{\n\tif ( IsDirectDraw ){\n\n\t\tif ( VideoSurfacePtr ){\n\n\t\t\twhile ( LockCount ){\n\n\t\t\t\tif (VideoSurfacePtr->Unlock ( NULL ) == DDERR_SURFACELOST){\n\t\t\t\t\tif (Gbuffer_Focus_Loss_Function){\n\t\t\t\t\t\tGbuffer_Focus_Loss_Function();\n\t\t\t\t\t}\n\t\t\t\t\tAllSurfaces.Restore_Surfaces();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tAllSurfaces.Remove_DD_Surface (VideoSurfacePtr);\n\t\t\tVideoSurfacePtr->Release();\n\t\t\tVideoSurfacePtr = NULL;\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * GBC::GRAPHICBUFFERCLASS -- Default constructor (requires explicit init) *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/09/1995     : Created.                                             *\n *=========================================================================*/\nGraphicBufferClass::GraphicBufferClass(void)\n{\n\tGraphicBuff\t\t\t= this; \t\t\t\t\t\t\t// Get a pointer to our self\n\tVideoSurfacePtr\t= NULL;\n\tmemset(&VideoSurfaceDescription, 0, sizeof(DDSURFACEDESC));\n}\n\n\n/***************************************************************************\n * GBC::GRAPHICBUFFERCLASS -- Constructor for fixed size buffers           *\n *                                                                         *\n * INPUT:\t\tlong size\t\t- size of the buffer to create\t\t\t\t\t*\n *\t\t\t\t\tint w\t\t\t- width of buffer in pixels (default = 320)  *\n *\t\t\t\t\tint h\t\t\t- height of buffer in pixels (default = 200) *\n *\t\t\t\t\tvoid *buffer\t- a pointer to the buffer if any (optional)\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/13/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicBufferClass::GraphicBufferClass(int w, int h, void *buffer, long size)\n{\n\tInit(w, h, buffer, size, GBC_NONE);\n}\n/*=========================================================================*\n * GBC::GRAPHICBUFFERCLASS -- inline constructor for GraphicBufferClass\t\t*\n *                                                                         *\n * INPUT:\t\tint w\t\t\t- width of buffer in pixels (default = 320)  *\n *\t\t\t\t\tint h\t\t\t- height of buffer in pixels (default = 200) *\n *\t\t\t\t\tvoid *buffer\t- a pointer to the buffer if any (optional)\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicBufferClass::GraphicBufferClass(int w, int h, void *buffer)\n{\n\tInit(w, h, buffer, w * h, GBC_NONE);\n}\n\n/*====================================================================================*\n * GBC::GRAPHICBUFFERCLASS -- contructor for GraphicsBufferClass with special flags   *\n *                                                                                    *\n * INPUT:\t\tint w\t\t\t- width of buffer in pixels (default = 320)           *\n *\t\t\t\t\tint h\t\t\t- height of buffer in pixels (default = 200)      *\n *\t\t\t\t\tvoid *buffer\t- unused                                \t      *\n *               unsigned flags - flags for creation of special buffer types          *\n *                                GBC_VISIBLE - buffer is a visible screen surface    *\n *                                GBC_VIDEOMEM - buffer resides in video memory       *\n *                                                                                    *\n * OUTPUT:     none                                                                   *\n *                                                                                    *\n * HISTORY:                                                                           *\n *   09-21-95 04:19pm ST : Created                                                    *\n *====================================================================================*/\nGraphicBufferClass::GraphicBufferClass(int w, int h, GBC_Enum flags)\n{\n\tInit(w, h, NULL, w * h, flags);\n}\n\n/*=========================================================================*\n * GBC::~GRAPHICBUFFERCLASS -- Destructor for the graphic buffer class     *\n *                                                                         *\n *\tINPUT:\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicBufferClass::~GraphicBufferClass()\n{\n\n//\n// Release the direct draw surface if it exists\n//\n\tUn_Init();\n}\n\n\n\n/***************************************************************************\n * SET_LOGIC_PAGE -- Sets LogicPage to new buffer                          *\n *                                                                         *\n * INPUT:\t\tGraphicBufferClass * the buffer we are going to set         *\n *                                                                         *\n * OUTPUT:     GraphicBufferClass * the previous buffer type\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nGraphicViewPortClass *Set_Logic_Page(GraphicViewPortClass *ptr)\n{\n\tGraphicViewPortClass *old = LogicPage;\n\tLogicPage\t\t\t\t\t= ptr;\n\treturn(old);\n}\n\n/***************************************************************************\n * SET_LOGIC_PAGE -- Sets LogicPage to new buffer                          *\n *                                                                         *\n * INPUT:\t\tGraphicBufferClass & the buffer we are going to set         *\n *                                                                         *\n * OUTPUT:     GraphicBufferClass * the previous buffer type\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nGraphicViewPortClass *Set_Logic_Page(GraphicViewPortClass &ptr)\n{\n\tGraphicViewPortClass *old = LogicPage;\n\tLogicPage\t\t\t\t\t= &ptr;\n\treturn(old);\n}\n\n\n/***************************************************************************\n * GBC::LOCK -- Locks a Direct Draw Surface                                *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/09/1995     : Created.                                             *\n *   10/09/1995     : Code stolen from Steve Tall                          *\n *=========================================================================*/\nextern\tvoid Colour_Debug (int call_number);\nextern BOOL GameInFocus;\n\nextern void Block_Mouse(GraphicBufferClass *buffer);\nextern void Unblock_Mouse(GraphicBufferClass *buffer);\n\nBOOL GraphicBufferClass::Lock(void)\n{\n\tHRESULT\tresult;\n\tint\t\trestore_attempts=0;\n\n\t//\n\t// If its not a direct draw surface then the lock is always sucessful.\n\t//\n\tif (!IsDirectDraw) return(TRUE);\n\n\t/*\n\t** If the video surface pointer is null then return\n\t*/\n\tif (!VideoSurfacePtr) return (FALSE);\n\n\t/*\n\t** If we dont have focus then return failure\n\t*/\n\tif (!GameInFocus) return (FALSE);\n\n\n\tBlock_Mouse(this);\n\n\n\t//\n\t// If surface is already locked then inc the lock count and return true\n\t//\n\tif (LockCount){\n\t\tLockCount++;\n\t\tUnblock_Mouse(this);\n\t\treturn(TRUE);\n\t}\n\n\t//\n\t// If it isn't locked at all then we will have to request that Direct\n\t// Draw actually lock the surface.\n\t//\n\n\tif (VideoSurfacePtr){\n\t\twhile (!LockCount && restore_attempts<2) {\n\t\t\tresult = VideoSurfacePtr->Lock ( NULL\n\t\t\t\t\t\t\t\t\t\t, &(VideoSurfaceDescription)\n\t\t\t\t\t\t\t\t\t\t, DDLOCK_WAIT\n\t\t\t\t\t\t\t\t\t\t, NULL);\n\n\t\t\tswitch (result){\n\t\t\t\tcase DD_OK :\n\t\t\t\t\tOffset\t= (unsigned long)VideoSurfaceDescription.lpSurface;\n\t\t\t\t\tPitch\t\t= VideoSurfaceDescription.lPitch;\n\t\t\t\t\tPitch\t  -= Width;\n\t\t\t\t\tLockCount++;\t\t// increment count so we can track if\n\t\t\t\t\tTotalLocks++;\t\t// Total number of times we have locked (for debugging)\n\t\t\t\t\t//Colour_Debug (1);\n\t\t\t\t\tUnblock_Mouse(this);\n\t\t\t\t\treturn (TRUE);\t\t// we locked it multiple times.\n\n\t\t\t\tcase DDERR_SURFACELOST :\n\t\t\t\t\tif (Gbuffer_Focus_Loss_Function){\n\t\t\t\t\t\tGbuffer_Focus_Loss_Function();\n\t\t\t\t\t}\n\t\t\t\t\tAllSurfaces.Restore_Surfaces();\n\t\t\t\t\trestore_attempts++;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault :\n\t\t\t\t\tUnblock_Mouse(this);\n\t\t\t\t\treturn (FALSE);\n\t\t\t}\n\t\t}\n\t}\n\t//Colour_Debug(1);\n\tUnblock_Mouse(this);\n\treturn (FALSE);\t\t//Return false because we couldnt lock or restore the surface\n}\n\n/***************************************************************************\n * GBC::UNLOCK -- Unlocks a direct draw surface                            *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/09/1995     : Created.                                             *\n *   10/09/1995     : Code stolen from Steve Tall                          *\n *=========================================================================*/\n\n\nBOOL GraphicBufferClass::Unlock(void)\n{\n\t//\n\t// If there is no lock count or this is not a direct draw surface\n\t// then just return true as there is no harm done.\n\t//\n\tif (!(LockCount && IsDirectDraw)) {\n\t\treturn(TRUE);\n\t}\n\n\t//\n\t// If lock count is directly equal to one then we actually need to\n\t// unlock so just give it a shot.\n\t//\n\tif (LockCount == 1 && VideoSurfacePtr) {\n\t\tBlock_Mouse(this);\n\t\tif ( VideoSurfacePtr->Unlock ( NULL ) != DD_OK ){\n\t\t\tUnblock_Mouse(this);\n\t\t\treturn(FALSE);\n\t\t} else {\n\t\t\tOffset=NOT_LOCKED;\n\t\t\tLockCount--;\n\t\t\tUnblock_Mouse(this);\n\t\t\treturn(TRUE);\n\t\t}\n\t}\n\t//Colour_Debug (0);\n\tLockCount--;\n\treturn(TRUE);\n}\n\n\n/***********************************************************************************************\n * GVPC::DD_Linear_Blit_To_Linear -- blit using the hardware blitter                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    destination vvpc                                                                  *\n *           x coord to blit from                                                              *\n *           y coord to blit from                                                              *\n *           x coord to blit to                                                                *\n *           y coord to blit to                                                                *\n *           width to blit                                                                     *\n *           height to blit                                                                    *\n *                                                                                             *\n * OUTPUT:   DD_OK if successful                                                               *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09-22-95 11:05am ST : Created                                                             *\n *=============================================================================================*/\n\nHRESULT GraphicViewPortClass::DD_Linear_Blit_To_Linear (\n\t\t\t\t\t\t\t\t  GraphicViewPortClass &dest\n\t\t\t\t\t\t\t\t, int source_x\n\t\t\t\t\t\t\t\t, int source_y\n\t\t\t\t\t\t\t\t, int dest_x\n\t\t\t\t\t\t\t\t, int dest_y\n\t\t\t\t\t\t\t\t, int width\n\t\t\t\t\t\t\t\t, int height\n\t\t\t\t\t\t\t\t, BOOL mask )\n\n{\n\tRECT\tsource_rectangle;\n\tRECT\tdest_rectangle;\n\tint\t\tkey_source=0;\n\n\tif ( mask ){\n\t\tkey_source=DDBLT_KEYSRC;\n\t}\n\n\n\tsource_rectangle.left \t= source_x;\n\tsource_rectangle.top  \t= source_y;\n\tsource_rectangle.right\t= source_x+width;\n\tsource_rectangle.bottom\t= source_y+height;\n\n\tdest_rectangle.left \t= dest_x;\n\tdest_rectangle.top  \t= dest_y;\n\tdest_rectangle.right\t= dest_x+width;\n\tdest_rectangle.bottom\t= dest_y+height;\n\n   return (\tdest.GraphicBuff->Get_DD_Surface()->Blt ( &dest_rectangle,\n\t\t\t\t\t\t\t\t\t\t\t\tGraphicBuff->Get_DD_Surface(),\n\t\t\t\t\t\t\t\t\t\t\t\t&source_rectangle,\n\t\t\t\t\t\t\t\t\t\t\t\tkey_source | DDBLT_WAIT | DDBLT_ASYNC,\n\t\t\t\t\t\t\t\t\t\t\t\tNULL ) );\n}\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/GETCD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : GETCD.CPP\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : STEVE WETHERILL BASED ON JOE BOSTIC CODE *\n *                                                                         *\n *                   Start Date : 5/13/94\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : June 4, 1994   [SW]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *\t\tGetCDClass::GetCDClass\t--\tdefault constructor                       *\n *\t\tGetCDClass::~GetCDClass\t--\tdestructor                                *\n *\t\tGetCDClass::GetCDDrive\t--\treturns the logical CD drive              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <dos.h>\n\n#include \"wwstd.h\"\n#include \"playcd.h\"\n#include \"wwmem.h\"\n\n\n/***************************************************************************\n * GetCDClass -- default constructor\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *       none \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone                          \t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW   : Created.                                            *\n *   12/4/95    ST   : fixed for Win95                                     *\n *=========================================================================*/\n\nGetCDClass::GetCDClass(VOID)\n{\n\tchar\tpath[]={\"a:\\\\\"};\n\n\tCDCount = 0;\n\tCDIndex = 0;\n\n\t/*\n\t** Set all CD drive placeholders to empty\n\t*/\n\tmemset (CDDrives, NO_CD_DRIVE, MAX_CD_DRIVES);\n\n\n\tfor (char i='c' ; i<='z' ; i++){\n\t\tpath[0]=i;\n\t\tif (GetDriveType (path) == DRIVE_CDROM){\n\t\t\tCDDrives[CDCount++] = (int) (i-'a');\n\t\t}\n\t}\n\n\t/*\n\t**\tCatch the case when there are NO CD-ROM drives available\n\t*/\n\tif (CDCount == 0) {\n\t\tfor (char i='a' ; i<='b' ; i++){\n\t\t\tpath[0]=i;\n\t\t\tif (GetDriveType (path) == DRIVE_CDROM){\n\t\t\t\tCDDrives[CDCount++] = (int) (i-'a');\n\t\t\t}\n\t\t}\n\t}\n}\n\n/***************************************************************************\n * GetCDClass -- destructor                                                *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW: Created.                                               *\n *   12/4/95    ST: fixed for Win95                                        *\n *=========================================================================*/\n\nGetCDClass::~GetCDClass(VOID)\n{\n//\tif(cdDrive_addrp.seg)\n//\t\tDPMI_real_free(cdDrive_addrp);\t\t// free up those conventional buffers\n}\n\n/* ==================================================================== */\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/GETCLIP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : BITBLIT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Julio R. Jerez                           *\n;*                                                                         *\n;*                   Start Date : Feb 6, 1995                              *\n;*                                                                         *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\n; typedef struct {\n;\t\t     int x0 , y0 ;\n;\t\t     int x1 , y1 ;\n;\t\t } CLIP_WIN ;\n; Note for efficiency reasons x1 must be >= x0 and y1 >= y0\n; int get_clip ( CLIP_WIN * window , CLIP_WIN * sorce_rect ) ;\n\nCODESEG\n\n\tPROC\tget_clip C near\n\tUSES\teax , ebx\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG\twin\t    : dword\n\tARG     rect\t    : dword\n\n\n\tmov\tedi , [ rect ]\n\tmov  \tesi , [ win ]\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ (RECTANGLE edi) . x0 ]\n\tmov\tebx , [ (RECTANGLE edi) . x1 ]\n\tsub\tecx , [ (RECTANGLE esi) . x0 ]\n\tsub\tebx , [ (RECTANGLE esi) . x0 ]\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n;\tmov\tebx , [ (RECTANGLE esi) . x1 ]\n;\tinc\tebx\n;\tmov\t[ rect ] , ebx\n\tmov\tecx , [ (RECTANGLE edi) . x0 ]\n\tmov\tebx , [ (RECTANGLE edi) . x1 ]\n\tsub\tecx , [ (RECTANGLE esi) . x1 ]\n\tsub\tebx , [ (RECTANGLE esi) . x1 ]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ (RECTANGLE edi) . y0 ]\n\tmov\tebx , [ (RECTANGLE edi) . y1 ]\n\tsub\tecx , [ (RECTANGLE esi) . y0 ]\n\tsub\tebx , [ (RECTANGLE esi) . y0 ]\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n;\tmov\tebx , [ (RECTANGLE esi) . y1 ]\n;\tinc\tebx\n;\tmov\t[ rect ] , ebx\n\tmov\tecx , [ (RECTANGLE edi) . y0 ]\n\tmov\tebx , [ (RECTANGLE edi) . y1 ]\n\tsub\tecx , [ (RECTANGLE esi) . y1 ]\n\tsub\tebx , [ (RECTANGLE esi) . y1 ]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , dl\n\tret\n       ENDP\tget_clip\n\n\n\nEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/GETPIX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : GraphicViewPortClass\t\t\t   *\n;*                                                                         *\n;*                    File Name : GETPIXEL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : June 7, 1994   [PWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVPC::Buffer_Get_Pixel -- get the colour of a pixel at given coords   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n;***************************************************************************\n;* VVPC::GET_PIXEL -- Gets a pixel from the current view port\t\t   *\n;*                                                                         *\n;* INPUT:\tWORD the x pixel on the screen.\t\t\t\t   *\n;*\t\tWORD the y pixel on the screen.\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      UBYTE the pixel at the specified location\t\t   *\n;*                                                                         *\n;* WARNING:\tIf pixel is to be placed outside of the viewport then\t   *\n;*\t\tthis routine will abort.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/07/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_Get_Pixel C near\n\tUSES\tebx,ecx,edx,edi\n\n\tARG    \tthis_object:DWORD\t\t\t\t; this is a member function\n\tARG\tx_pixel:DWORD\t\t\t\t; x position of pixel to set\n\tARG\ty_pixel:DWORD\t\t\t\t; y position of pixel to set\n\n\t;*===================================================================\n\t; Get the viewport information and put bytes per row in ecx\n\t;*===================================================================\n\tmov\tebx,[this_object]\t\t\t\t; get a pointer to viewport\n\txor\teax,eax\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get the correct offset\n\tmov\tecx,[(GraphicViewPort ebx).GVPHeight]\t; edx = height of viewport\n\tmov\tedx,[(GraphicViewPort ebx).GVPWidth]\t; ecx = width of viewport\n\n\t;*===================================================================\n\t; Verify that the X pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[x_pixel]\t\t\t\t; find the x position\n\tcmp\teax,edx\t\t\t\t\t;   is it out of bounds\n\tjae\tshort ??exit\t\t\t\t; if so then get out\n\tadd\tedi,eax\t\t\t\t\t; otherwise add in offset\n\n\t;*===================================================================\n\t; Verify that the Y pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[y_pixel]\t\t\t\t; get the y position\n\tcmp\teax,ecx\t\t\t\t\t;  is it out of bounds\n\tjae\t??exit\t\t\t\t\t; if so then get out\n\tadd\tedx,[(GraphicViewPort ebx).GVPXAdd]\t; otherwise find bytes per row\n\tadd\tedx,[(GraphicViewPort ebx).GVPPitch]\t; otherwise find bytes per row\n\tmul\tedx\t\t\t\t\t; offset = bytes per row * y\n\tadd\tedi,eax\t\t\t\t\t; add it into the offset\n\n\t;*===================================================================\n\t; Write the pixel to the screen\n\t;*===================================================================\n\txor\teax,eax\t\t\t\t\t; clear the word\n\tmov\tal,[edi]\t\t\t\t; read in the pixel\n??exit:\n\tret\n\tENDP\tBuffer_Get_Pixel\n\nEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/GETSHAPE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : GETSHAPE.CPP                             *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : April 5, 1992                            *\n *                                                                         *\n *                  Last Update : May 25, 1994   [BR]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Get_Shape_Size -- Fetch the size of the shape in memory.              *\n *   Get_Shape_Uncomp_Size -- gets shape's uncompressed size in bytes\t\t*\n *   Get_Shape_Data -- retrieves a shape's special prefix data\t\t\t\t\t*\n *   Extract_Shape_Count -- returns # of shapes in the given shape block\t*\n *   Extract_Shape -- Gets pointer to shape in given shape block\t\t\t\t*\n *   Get_Shape_Width -- gets shape width in pixels\t\t\t\t\t\t\t\t\t*\n *   Get_Shape_Height -- gets shape height in pixels\t\t\t\t\t\t\t\t*\n *   Set_Shape_Height -- modifies shape's height\t\t\t\t\t\t\t\t\t*\n *   Restore_Shape_Height -- restores a shape to its original height\t\t\t*\n *   Get_Shape_Original_Height -- gets shape's unmodified height\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n/*\n********************************* Includes **********************************\n*/\n#include \"wwstd.h\"\n#include\t\"shape.h\"\n\n\n/***************************************************************************\n * Get_Shape_Size -- Fetch the size of the shape in memory.                *\n *                                                                         *\n * The shape size returned includes both the shape header & its data.\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * INPUT:                                                                  *\n *\tshape\t\tpointer to shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * shape's size in memory\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n * none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint cdecl Get_Shape_Size(VOID const *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\n\t/*\n\t------------------------- Return if NULL pointer -------------------------\n\t*/\n\tif (!shape) \n\t\treturn(0);\n\n\t/*\n\t-------------------------- Returns shape's size --------------------------\n\t*/\n\treturn (shp->ShapeSize);\n\n}\t/* end of Get_Shape_Size */\n\n\n/***************************************************************************\n * Get_Shape_Uncomp_Size -- gets shape's uncompressed size in bytes\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\tshape\t\tpointer to shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\tshape's size in bytes when uncompressed\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n * none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint Get_Shape_Uncomp_Size(VOID const *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\n\treturn (shp->DataLength);\n\n}\t/* end of Get_Shape_Uncomp_Size */\n\n\n/***************************************************************************\n * Get_Shape_Data -- retrieves a shape's special prefix data\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * MAKESHPS.EXE can store special data values along with a shape.  These\t*\n * values are inserted in the shape table >before< the shape's header.\t\t*\n * So, this routine uses the 'data' parameter as a negative index from\t\t*\n * the given shape pointer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\tshape\t\tpointer to shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * data\t\tindex of WORD data value to get\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * data value\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\tThe shape pointer must be a pointer into a shape table created by\t\t\t*\n * MAKESHPS.EXE; it >cannot< be a pointer to shape returned by Make_Shape!\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nWORD cdecl Get_Shape_Data(VOID const *shape, WORD data)\n{\n\tWORD *word_ptr = (WORD *)shape;\n\tWORD retval;\n\n\tretval = *(word_ptr - (data+1));\n\n\treturn (retval);\n\n}\t/* end of Get_Shape_Data */\n\n\n/***************************************************************************\n * Extract_Shape_Count -- returns # of shapes in the given shape block\t\t*\n *                                                                         *\n * The # of shapes in a shape block is the first WORD in the block, so\t\t*\n * this is the value returned.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * INPUT:                                                                  *\n * buffer\tpointer to shape block, created with MAKESHPS.EXE\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * # shapes in the block\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint cdecl Extract_Shape_Count(VOID const *buffer)\n{\n\tShapeBlock_Type *block = (ShapeBlock_Type *)buffer;\n\n\treturn (block->NumShapes);\n\n}\t/* end of Extract_Shape_Count */\n\n\n/***************************************************************************\n * Extract_Shape -- Gets pointer to shape in given shape block\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n * buffer\tpointer to shape block, created with MAKESHPS.EXE\t\t\t\t\t*\n * shape\t\tindex of shape to get\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * pointer to shape in the shape block\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nVOID * cdecl Extract_Shape(VOID const *buffer, int shape)\n{\n\tShapeBlock_Type *block = (ShapeBlock_Type*) buffer;\n\tint numshapes;\t\t// Number of shapes\n\tlong offset;\t\t\t// Offset of shape data, from start of block\n\tchar *bytebuf = (char*) buffer;\n\n\t/*\n\t----------------------- Return if invalid argument -----------------------\n\t*/\n\tif (!buffer || shape < 0 || shape >= block->NumShapes)\n\t\treturn(NULL);\n\n\toffset = block->Offsets[shape];\n\n\treturn(bytebuf + 2 + offset);\n\n}\t/* end of Extract_Shape */\n\n\n/***************************************************************************\n * Get_Shape_Width -- gets shape width in pixels\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n * shape\t\tpointer to a shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\tshape width in pixels\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n * none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint Get_Shape_Width(VOID const *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\n\treturn (shp->Width);\n\n}\t/* end of Get_Shape_Width */\n\n\n/***************************************************************************\n * Get_Shape_Height -- gets shape height in pixels\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n * shape\t\tpointer to a shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * shape height in pixels\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n * none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint Get_Shape_Height(VOID const *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\n\treturn (shp->Height);\n\n}\t/* end of Get_Shape_Height */\n\n\n/***************************************************************************\n * Set_Shape_Height -- modifies shape's height\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The new height must be shorter than the original height.  This effect\t*\n * chops off the lower portion of the shape, like it's sinking into the\t\t*\n * ground.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * INPUT:                                                                  *\n * shape\t\t\tpointer to a shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * newheight\tnew shape height\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * old shape height\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n * none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint cdecl Set_Shape_Height(VOID const *shape, WORD newheight)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\tWORD oldheight;\n\n\toldheight = shp->Height;\n\tshp->Height = newheight;\n\n\treturn(oldheight);\n\n}\t/* end of Set_Shape_Height */\n\n\n/***************************************************************************\n * Restore_Shape_Height -- restores a shape to its original height\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n * shape\t\tpointer to a shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * old shape height\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint cdecl Restore_Shape_Height(VOID *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\tWORD oldheight;\n\n\toldheight = shp->Height;\n\tshp->Height = shp->OriginalHeight;\n\n\treturn(oldheight);\n\n}\t/* end of Restore_Shape_Height */\n\n\n/***************************************************************************\n * Get_Shape_Original_Height -- gets shape's unmodified height\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\tshape\t\tpointer to a shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * shape's unmodified height\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint Get_Shape_Original_Height(VOID const *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\t\n\treturn (shp->OriginalHeight);\n\n}\t/* end of Get_Shape_Original_Height */\n\n\n/************************* end of getshape.cpp *****************************/\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/HARDERR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Hard/Critical Error Handler              *\n;*                                                                         *\n;*                    File Name : harderr.asm\t\t\t\t   *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen.\t\t\t   *\n;*                                                                         *\n;*                   Start Date : July  18, 1994                           *\n;*                                                                         *\n;*                  Last Update : July 26, 1994   [SKB]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Install_Hard_Error_Handler -- Setup for handling critical errors      *\n;*   Remove_Hard_Erroror_Handler -- Remove the critical error handler stuff*\n;*   Critical_Error_Handler -- Catch critical error interrupt.             *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nLOCALS ??\n\n;INCLUDE \"tntdos.inc\"\n\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////////// Equates ////////////////////////////////////////\nDOS_SYS_CALL\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nLOCK_PAGES\tEQU\t5\t\t; Lock pages subfunction using DX_MEM_MGT\nUNLOCK_PAGES\tEQU\t6\t\t; Unlock pages subfunction using DX_MEM_MGT\nCRITERR_INT_NUM EQU\t24h\n\nDISK_ERROR_BIT\tEQU\t01000000000000000b ; bit 7 of dh.\nDISK_ERROR\tEQU\t1\t\t; Value of Hard_Error_Occured if disk/floppy error.\nOTHER_ERROR\tEQU\t2\t\t; Value of Hard_Error_Occured if other type of error.\n\n;\n; Interrupt handler stack frame\n;\n_FLGS\tequ\t[DWORD PTR ebp+52]\t; 386|DOS-Extender flags\n_GS\tequ\t[WORD PTR ebp+48]\t; original GS\n_FS\tequ\t[WORD PTR ebp+44]\t; original FS\n_DS\tequ\t[WORD PTR ebp+40]\t; original DS\n_ES\tequ\t[WORD PTR ebp+36]\t; original ES\n_SS\tequ\t[WORD PTR ebp+32]\t; original SS\n_ESP\tequ\t[DWORD PTR ebp+28]\t; original ESP\n_EFLAGS\tequ\t[DWORD PTR ebp+24]\t; original EFLAGS\n_CS\tequ\t[DWORD PTR ebp+20]\t; original CS\n_EIP\tequ\t[DWORD PTR ebp+16]\t; original EIP\n_EBP\tequ\t[DWORD PTR ebp]\t\t; original EBP\n\n;\n; DOS critical error stack frame\n;\n_DOS_FLAGS equ\t[WORD PTR es:ebx+22]\t; interrupt stack frame from real\n_DOS_CS\tequ\t[WORD PTR es:ebx+20]\t; mode INT 21h\n_DOS_IP\tequ\t[WORD PTR es:ebx+18]\t;\n_DOS_ES\tequ\t[WORD PTR es:ebx+16]\t; regs at time INT 21h was issued\n_DOS_DS\tequ\t[WORD PTR es:ebx+14]\t\t; in real mode\n_DOS_BP\tequ\t[WORD PTR es:ebx+12]\t\t;\n_DOS_DI\tequ\t[WORD PTR es:ebx+10]\t\t;\n_DOS_SI\tequ\t[WORD PTR es:ebx+8]\t\t;\n_DOS_DX\tequ\t[WORD PTR es:ebx+6]\t\t;\n_DOS_CX\tequ\t[WORD PTR es:ebx+4]\t\t;\n_DOS_BX\tequ\t[WORD PTR es:ebx+2]\t\t;\n_DOS_AX\tequ\t[WORD PTR es:ebx]\t\t;\n\n\n; \n; Error codes put into Hard_Error_Code\n;\nDISK_WRITE_PROTECTED\tequ\t00h\nUNKOWN_DEVICE\t\tequ\t01h\nDRIVE_NOT_READY\t\tequ\t02h\nUNKOWN_COMMAND\t\tequ\t03h\nCRC_ERROR\t\tequ\t04h\nWRONG_DATA_LENGTH\tequ\t05h\nSEEK_ERROR\t\tequ\t06h\nUNKOWN_DEVICE_TYPE\tequ\t07h\nSECTOR_NOT_FOUND\tequ\t08h\nOUT_OF_PAPER\t\tequ\t09h\nWRITE_ERROR\t\tequ\t0Ah\nREAD_ERROR\t\tequ\t0Bh\nGENERAL_ERROR\t\tequ\t0Ch\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;/////////////////////////////////// Prototypes ///////////////////////////////////////\n\nGLOBAL\t Install_Hard_Error_Handler :NEAR\nGLOBAL\t Remove_Hard_Error_Handler  :NEAR\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////// Global/Local Data //////////////////////////////////\n\nDATASEG\n\nLABEL\tLockedDataStart\tBYTE\t\nHard_Error_Occured\tDB\t0\t; Hard disk error or other error.\nHard_Error_Code\t\tDB\t0\t; Error Code.\t\nLABEL\tLockedDataEnd\tBYTE\n\n\nOldRMI\t\tDD\t?\t; original real mode critical err vector\nOldPMIOffset\tDD\t?\t; original protected mode critical err vector\nOldPMISelector\tDD\t?     \t; original PM crit error selector.\n\nInitFlags\tDD\t0\t; Flags to indicate what has been initialized.\n\n; InitFlags that are set to have a fully functional interrupt.\nIF_SET_VECTORS\t\tequ\t1\t\t; Vectors have been set.\nIF_LOCKED_PM_CODE\tequ\t2\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t4\t\t; Locked PM data for DPMI.\nIF_FUNCTIONAL\t\tequ\t8\t\t; crit error is in and functional.\n\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////////// Code //////////////////////////////////////////\n\nCODESEG\n\n;***************************************************************************\n;* INSTALL_HARD_ERROR_HANDLER -- Setup for handling critical errors.         *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/26/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC Install_Hard_Error_Handler C near\n\tUSES eax,ebx,ecx,ds,es\n\tret\n\n\tENDP Install_Hard_Error_Handler\n\n\n;***************************************************************************\n;* REMOVE_HARD_ERROROR_HANDLER -- Remove the critical error handler stuff    *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/26/1994 SKB : Created.                                             *\n;*=========================================================================*\n\n\tPROC \tRemove_Hard_Error_Handler C near\n\tUSES \tebx,ecx,edx,ds,es\n;\n; Restore the original interrupt vectors and exit\n;\n\n\tret\n\n\tENDP Remove_Hard_Error_Handler\n\n\n;***************************************************************************\n;* Critical_Error_Handler -- Catch critical error interrupt.               *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/26/1994 SKB : Created.                                             *\n;*=========================================================================*\n\nLABEL \tLockedCodeStart\tBYTE\n\n\tPROC Critical_Error_Handler NEAR\n\n\tENDP Critical_Error_Handler\n\nLABEL \tLockedCodeEnd\t\tBYTE\n\nEND\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/ICONCACH.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***             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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Drawbuff - Westwood win95 library                            *\n *                                                                                             *\n *                    File Name : Iconcach.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : November 8th, 1995                                           *\n *                                                                                             *\n *                  Last Update : November 13th, 1995 [ST]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview: This file cantains members of the IconCacheClass and associated non member        *\n *           functions. All functions are to do with caching individual icons from icon sets   *\n *           into video memory to improve the speed of subsequent drawing                      *\n *                                                                                             *\n * Functions:                                                                                  *\n *  Cache_New_Icon -- Call the Cache_It member to cache a registered icon to video memory      *\n *  Invalidate_Cached_Icons -- Uncache all the icons                                           *\n *  Restore_Cached_Icons -- restore cached icons after a focus loss                            *\n *  Register_Icon_Set -- register an icon set as cachable                                      *\n *  Get_Free_Cache_Slot -- find an empty cache slot                                            *\n *  IconCacheClass::IconCacheClass -- IconCacheClass constructor                               *\n *  IconCacheClass::~IconCacheClass -- IconCacheClass destructor                               *\n *  IconCacheClass::Restore -- restore the icons surface and recache it                        *\n *  IconCacheClass::Cache_It -- cache an icon into video memory                                *\n *  IconCacheClass::Uncache_It -- restore the video memory used by a cached icon               *\n *  IconCacheClass::Draw_It -- use the blitter to draw the cached icon                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#define\tWIN32_LEAN_AND_MEAN\n#define\t_WIN32\n\n#include <windows.h>\n#include \"ddraw.h\"\n#include \"misc.h\"\n#include \"iconcach.h\"\n#include \"gbuffer.h\"\n\n\nstatic\tDDSURFACEDESC\tVideoSurfaceDescription;\n\nIconCacheClass\tCachedIcons[MAX_CACHED_ICONS];\n\nextern \"C\"{\nIconSetType\t\tIconSetList[MAX_ICON_SETS];\nshort\t\t\t\tIconCacheLookup[MAX_LOOKUP_ENTRIES];\n}\n\nint\t\tCachedIconsDrawn=0;\t\t//Counter of number of cache hits\nint\t\tUnCachedIconsDrawn=0;\t//Counter of number of cache misses\nBOOL\tCacheMemoryExhausted;\t//Flag set if we have run out of video RAM\n\n\n\n\n/***********************************************************************************************\n * Optimise_Video_Memory_Cache -- optimises usage of video memory                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   TRUE if memory was freed up                                                       *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/29/95 12:47PM ST : Created                                                            *\n *=============================================================================================*/\nBOOL Optimize_Video_Memory_Cache (void)\n{\n\n\tif (CacheMemoryExhausted &&\n\t\t(UnCachedIconsDrawn+CachedIconsDrawn > 1000) &&\n\t\tUnCachedIconsDrawn > CachedIconsDrawn){\n\n\t\tint\tcache_misses[MAX_CACHED_ICONS];\n\t\tint\tcache_hits[MAX_CACHED_ICONS];\n\t\tint\ttotal_cache_misses=0;\n\t\tint\ttotal_cache_hits=0;\n\t\tint\tcounter;\n\t\tint\ti;\n\t\tint\tj;\n\t\tint\ttemp;\n\t\tBOOL\tswapped;\n\n\t\t/*\n\t\t** make list of icons that have failed to cache more than 5 times\n\t\t*/\n\t\tfor (counter=0 ; counter<MAX_CACHED_ICONS ; counter++){\n\n\t\t\tif (CachedIcons[counter].TimesFailed>5){\n\t\t\t\tcache_misses[total_cache_misses++] = counter;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Make list of icons that have been drawn less than 3 times\n\t\t*/\n\t\tfor (counter=0 ; counter<MAX_CACHED_ICONS ; counter++){\n\n\t\t\tif (CachedIcons[counter].TimesDrawn<3){\n\t\t\t\tcache_hits[total_cache_hits++] = counter;\n\t\t\t}\n\t\t}\n\n\n\t\t/*\n\t\t** Sort drawn icons into order\n\t\t*/\n\t\tif (total_cache_hits > 1){\n\t\t\tfor (i = 0 ; i<total_cache_hits ; i++){\n\t\t\t\tswapped=FALSE;\n\t\t\t\tfor (j=0 ; j<total_cache_hits-1 ; j++){\n\n\t\t\t\t\tif (CachedIcons[cache_hits[j]].TimesDrawn > CachedIcons[cache_hits[j+1]].TimesDrawn){\n\t\t\t\t\t\ttemp=cache_hits[j];\n\t\t\t\t\t\tcache_hits[j]=cache_hits[j+1];\n\t\t\t\t\t\tcache_hits[j+1]=temp;\n\t\t\t\t\t\tswapped = TRUE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!swapped) break;\n\t\t\t}\n\t\t}\n\n\n\t\t/*\n\t\t** Uncache icons up to the number of failed icons\n\t\t*/\n\n\t\tfor (counter=0 ; counter<total_cache_misses && counter<total_cache_hits; counter++){\n\t\t\tCachedIcons[cache_hits[counter]].Uncache_It();\n\t\t}\n\n\t\tCacheMemoryExhausted=FALSE;\n\t\tCachedIconsDrawn=0;\n\t\tUnCachedIconsDrawn=0;\n\t\treturn (TRUE);\n\t}\n\treturn (FALSE);\n\n}\n\n\n\n\n\n/***********************************************************************************************\n * Cache_New_Icon -- cache a registered icon to video memory                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    icon_index -- index into registered icon table of icon to cache                   *\n *           icon_ptr -- ptr to icon data                                                      *\n *                                                                                             *\n * OUTPUT:   BOOL success                                                                      *\n *                                                                                             *\n * WARNINGS: icon must already have been registered and assigned an index                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:36AM ST : Created                                                             *\n *=============================================================================================*/\nBOOL Cache_New_Icon (int icon_index, void *icon_ptr)\n{\n\tif (!CacheMemoryExhausted){\n\t\treturn (CachedIcons[icon_index].Cache_It(icon_ptr));\n\t} else {\n\t\tCachedIcons[icon_index].TimesFailed++;\n\t\tif (Optimize_Video_Memory_Cache()){\n\t\t\treturn (CachedIcons[icon_index].Cache_It(icon_ptr));\n\t\t} else {\n\t\t\treturn (FALSE);\n\t\t}\n\t}\n}\n\n\n\n\n\n/***********************************************************************************************\n * Invalidat_Cached_Icons -- used to release any icons that have been cached                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:37AM ST : Created                                                             *\n *=============================================================================================*/\nvoid Invalidate_Cached_Icons (void)\n{\n\tfor (int i=0 ; i<MAX_CACHED_ICONS ; i++){\n\t\tCachedIcons[i].Uncache_It();\n\t}\n\n\tmemset (&IconCacheLookup[0] , -1 ,MAX_LOOKUP_ENTRIES*sizeof(IconCacheLookup[0]));\n\n\tfor (i=0 ; i<MAX_ICON_SETS ; i++){\n\t\tIconSetList[i].IconSetPtr=NULL;\n\t}\n\n\tCacheMemoryExhausted=FALSE;\n}\n\n\n\n\n/***********************************************************************************************\n * Restore_Cached_Icons -- re-cache icons into video memory after a loss of focus              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: Assumes that the pointers that were originally used to cache the icons            *\n *           are still valid.                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:38AM ST : Created                                                             *\n *=============================================================================================*/\nvoid Restore_Cached_Icons (void)\n{\n\tfor (int i=0 ; i<MAX_CACHED_ICONS ; i++){\n\t\tCachedIcons[i].Restore();\n\t}\n\tCacheMemoryExhausted=FALSE;\n}\n\n\n\n/***********************************************************************************************\n * Register_Icon_Set -- used to register an icon set as cachable                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    icon_data - ptr to icon set                                                       *\n *           pre_cache -- should we pre-cache the icon data?                                   *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:39AM ST : Created                                                             *\n *=============================================================================================*/\nvoid Register_Icon_Set (void *icon_data , BOOL pre_cache)\n{\n\n\tfor (int i=0 ; i<MAX_ICON_SETS ; i++){\n\t\tif (!IconSetList[i].IconSetPtr){\n\t\t\tIconSetList[i].IconSetPtr = (IControl_Type*)icon_data;\n\n\t\t\tif (i){\n\t\t\t\tIControl_Type *previous_set = IconSetList[i-1].IconSetPtr;\n\t\t\t\tIconSetList[i].IconListOffset = IconSetList[i-1].IconListOffset + ((int)previous_set->Count)*2;\n\t\t\t\tif (IconSetList[i].IconListOffset > MAX_LOOKUP_ENTRIES*2){\n\t\t\t\t\tIconSetList[i].IconSetPtr = NULL;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tIconSetList[i].IconListOffset = 0;\n\t\t\t}\n\n\t\t\tif (pre_cache){\n\t\t\t\tfor (i=0 ; i<256 ; i++){\n\t\t\t\t\tIs_Icon_Cached(icon_data,i);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n\n\n/***********************************************************************************************\n * Get_Free_Cache_Slot -- find a free slot in which to cache an icon                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   int - icon index                                                                  *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:40AM ST : Created                                                             *\n *=============================================================================================*/\nint Get_Free_Cache_Slot (void)\n{\n\tfor (int i=0 ; i<MAX_CACHED_ICONS ; i++){\n\t\tif (!CachedIcons[i].Get_Is_Cached()){\n\t\t\treturn (i);\n\t\t}\n\t}\n\treturn (-1);\n}\n\n\n\n/***********************************************************************************************\n * ICC::IconCacheClass -- constructor for icon cache class                                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:41AM ST : Created                                                             *\n *=============================================================================================*/\nIconCacheClass::IconCacheClass (void)\n{\n\tIsCached\t\t\t=FALSE;\n\tSurfaceLost\t\t=FALSE;\n\tDrawFrequency\t=0;\n\tCacheSurface\t=NULL;\n\tIconSource\t\t=NULL;\n}\n\n\n\n/***********************************************************************************************\n * ICC::~IconCacheClass -- destructor for icon cache class                                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:41AM ST : Created                                                             *\n *=============================================================================================*/\nIconCacheClass::~IconCacheClass (void)\n{\n\tif (IsCached && CacheSurface){\n\t\tCacheSurface->Release();\n\t}\n}\n\n\n\n\n/***********************************************************************************************\n * ICC::Restore -- Restores the icons video surface memory and reloads it based on the original*\n *                 icon pointer                                                                *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: Relies on the icons original pointer still being valie                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:43AM ST : Created                                                             *\n *=============================================================================================*/\nvoid IconCacheClass::Restore (void)\n{\n\tif (IsCached && CacheSurface){\n\t\tCacheSurface->Restore();\n\t\tif (IconSource){\n\t\t\tCache_It(IconSource);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * ICC::Cache_It -- allocate video memory and copy an icon to it                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    icon_ptr -- ptr to icon data                                                      *\n *                                                                                             *\n * OUTPUT:   bool -- success?                                                                  *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:44AM ST : Created                                                             *\n *=============================================================================================*/\nBOOL IconCacheClass::Cache_It (void *icon_ptr)\n{\n\tDDSCAPS\tsurface_capabilities;\n\tBOOL\t\treturn_value;\n\n\t/*\n\t** If we dont have a direct draw interface yet then just fail\n\t*/\n\tif (!DirectDrawObject) return(FALSE);\n\n\t/*\n\t** Set up the description of the surface we want to create\n\t*/\n\tmemset (&VideoSurfaceDescription , 0 , sizeof ( VideoSurfaceDescription ));\n\n\tVideoSurfaceDescription.dwSize\t\t\t= sizeof( VideoSurfaceDescription );\n\tVideoSurfaceDescription.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;\n\tVideoSurfaceDescription.dwFlags\t\t\t= DDSD_CAPS |\tDDSD_HEIGHT | DDSD_WIDTH;\n\tVideoSurfaceDescription.dwHeight\t\t\t= ICON_WIDTH;\n\tVideoSurfaceDescription.dwWidth\t\t\t= ICON_HEIGHT;\n\n\t/*\n\t** If this cache object doesnt already have a surface then create one\n\t*/\n\tif (!CacheSurface){\n\t\tif (DD_OK!=DirectDrawObject->CreateSurface( &VideoSurfaceDescription , &CacheSurface , NULL)){\n\t\t\tCacheMemoryExhausted = TRUE;\n\t\t\treturn(FALSE);\n\t\t}\n\n\t}\n\n\t/*\n\t** Make sure the surface we created isnt really in system memory\n\t*/\n\tif (DD_OK != CacheSurface->GetCaps(&surface_capabilities)){\n\t\treturn(FALSE);\n\t}\n\n\tif ((DDSCAPS_SYSTEMMEMORY & surface_capabilities.dwCaps) == DDSCAPS_SYSTEMMEMORY){\n\t\tCacheSurface->Release();\n\t\treturn(FALSE);\n\t}\n\n\treturn_value=FALSE;\n\t/*\n\t** Lock the surface so we can copy the icon to it\n\t*/\n\tif (DD_OK== CacheSurface->Lock ( NULL\n\t\t\t\t\t\t\t\t, &(VideoSurfaceDescription)\n\t\t\t\t\t\t\t\t, DDLOCK_WAIT\n\t\t\t\t\t\t\t\t, NULL)){\n\t\t/*\n\t\t** Copy the icon to the surface and flag that icon is cached\n\t\t*/\n\t\tCache_Copy_Icon (icon_ptr , VideoSurfaceDescription.lpSurface , VideoSurfaceDescription.lPitch);\n\t\tIsCached=TRUE;\n\t\tSurfaceLost=FALSE;\n\t\tIconSource=icon_ptr;\n\t\treturn_value=TRUE;\n\t}\n\tCacheSurface->Unlock(NULL);\n\treturn (return_value);\n}\n\n\n/***********************************************************************************************\n * ICC::Uncache_It -- release the video memory used to cache an icon                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:48AM ST : Created                                                             *\n *=============================================================================================*/\nvoid IconCacheClass::Uncache_It(void)\n{\n\n\tif (IsCached && CacheSurface){\n\t\tCacheSurface->Release();\n\t\tIsCached=FALSE;\n\t\tCacheSurface=NULL;\n\t\tIconSource=NULL;\n\t\tCacheMemoryExhausted=FALSE;\n\t}\n}\n\n\n\n/***********************************************************************************************\n * ICC::Draw_It -- use the blitter to draw a cached icon                                       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    surface to draw to                                                                *\n *           x coord to draw to (relative to window)                                           *\n *           y coord to draw to (relative to window)                                           *\n *           window left coord                                                                 *\n *           window top coord                                                                  *\n *           window width                                                                      *\n *           window height                                                                     *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/13/95 9:48AM ST : Created                                                             *\n *=============================================================================================*/\nvoid IconCacheClass::Draw_It (LPDIRECTDRAWSURFACE dest_surface , int x_pixel, int y_pixel, int window_left , int window_top , int window_width , int window_height)\n{\n\tRECT\t\tsource_rectangle;\n\tRECT\t\tdest_rectangle;\n\tint\t\tclip;\n\tHRESULT\treturn_code;\n\n\t/*\n\t** Set up the source and destination coordinates as required by direct draw\n\t*/\n\tsource_rectangle.left \t= 0;\n\tsource_rectangle.top  \t= 0;\n\tsource_rectangle.right\t= ICON_WIDTH;\n\tsource_rectangle.bottom\t= ICON_HEIGHT;\n\n\tdest_rectangle.left \t= window_left+x_pixel;\n\tdest_rectangle.top  \t= window_top+y_pixel;\n\tdest_rectangle.right\t= dest_rectangle.left+ICON_WIDTH;\n\tdest_rectangle.bottom\t= dest_rectangle.top+ICON_HEIGHT;\n\n\t/*\n\t** Clip the coordinates to the window\n\t*/\n\tif (dest_rectangle.left<window_left){\n\t\tsource_rectangle.left += window_left-dest_rectangle.left;\n\t\tdest_rectangle.left=window_left;\n\t}\n\n\tif (dest_rectangle.right>=window_left+window_width){\n\t\tclip = dest_rectangle.right-(window_left+window_width);\n\t\tsource_rectangle.right -= clip;\n\t\tdest_rectangle.right -= clip;\n\t}\n\n\tif (dest_rectangle.top<window_top){\n\t\tsource_rectangle.top += window_top-dest_rectangle.top;\n\t\tdest_rectangle.top=window_top;\n\t}\n\n\tif (dest_rectangle.bottom>=window_top+window_height){\n\t\tclip = dest_rectangle.bottom-(window_top+window_height);\n\t\tsource_rectangle.bottom -= clip;\n\t\tdest_rectangle.bottom -= clip;\n\t}\n\n\tif (source_rectangle.left>=source_rectangle.right){\n\t\treturn;\n\t}\n\n\tif (source_rectangle.top>=source_rectangle.bottom){\n\t\treturn;\n\t}\n\n\t/*\n\t** Do the blit\n\t*/\n\t\treturn_code = dest_surface->Blt (&dest_rectangle ,\n\t\t\t\t\t\t\t\t\t\t\t\t\tCacheSurface ,\n\t\t\t\t\t\t\t\t\t\t\t\t\t&source_rectangle ,\n\t\t\t\t\t\t\t\t\t\t\t\t\tDDBLT_WAIT |\n\t\t\t\t\t\t\t\t\t\t\t\t\tDDBLT_ASYNC ,\n\t\t\t\t\t\t\t\t\t\t\t\t\tNULL);\n\n\tif (return_code == DDERR_SURFACELOST && Gbuffer_Focus_Loss_Function){\n\t\tGbuffer_Focus_Loss_Function();\n\t}\n\n\tif ( return_code != DDERR_SURFACELOST && return_code != DD_OK ) {\n\t\tchar temp[100];\n\t\tsprintf(temp,\"DD Error code %d\\n\", return_code & 0xFFFF);\n\t\tOutputDebugString(temp);\n\t}\n\n\tTimesDrawn++;\n\n}\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/ICONSET.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library                                  *\n *                                                                         *\n *                    File Name : ICONSET.C                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : June 9, 1991                             *\n *                                                                         *\n *                  Last Update : September 15, 1993   [JLB]               *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Load_Icon_Set -- Loads an icons set and initializes it.               *\n *   Free_Icon_Set -- Frees allocations made by Load_Icon_Set().           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n//#include\t\"function.h\"\n\n#define\t\t_WIN32\n#define\t\tWIN32_LEAN_AND_MEAN\n\n#include\t<dos.h>\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<mem.h>\n#include\t<wwstd.h>\n#include\t<file.h>\n#include\t\"tile.h\"\n#include\t<iff.h>\n\n\n\nextern int Misc;\n\nvoid *  Load_Icon_Set(char const *filename, void *iconsetptr, long buffsize);\nvoid  Free_Icon_Set(void const *iconset);\nlong  Get_Icon_Set_Size(void const *iconset);\nint  Get_Icon_Set_Width(void const *iconset);\nint  Get_Icon_Set_Height(void const *iconset);\nvoid *  Get_Icon_Set_Icondata(void const *iconset);\nvoid *  Get_Icon_Set_Trans(void const *iconset);\nvoid *  Get_Icon_Set_Remapdata(void const *iconset);\nvoid *  Get_Icon_Set_Palettedata(void const *iconset);\nint  Get_Icon_Set_Count(void const *iconset);\nvoid *  Get_Icon_Set_Map(void const *iconset);\n\n\n//#define\tICON_PALETTE_BYTES\t16\n//#define\tICON_MAX\t\t\t\t\t256\n\n/***************************************************************************\n**\tThe terrain is rendered by using icons.  These are the buffers that hold\n**\tthe icon data, remap tables, and remap index arrays.\n*/\n//PRIVATE char *IconPalette = NULL;\t\t// MCGA only.\n//PRIVATE char *IconRemap = NULL;\t\t\t// MCGA only.\n\n#define\tFORM_RPAL\tMAKE_ID('R','P','A','L')\n#define\tFORM_RTBL\tMAKE_ID('R','T','B','L')\n#define\tFORM_SSET\tMAKE_ID('S','S','E','T')\n#define\tFORM_SINF\tMAKE_ID('S','I','N','F')\n#define\tFORM_ICON\tMAKE_ID('I','C','O','N')\n#define\tFORM_TRNS\tMAKE_ID('T','R','N','S')\n#define\tFORM_MAP\t\tMAKE_ID('M','A','P',' ')\n\n\n\n/***************************************************************************\n * LOAD_ICON_SET -- Loads an icons set and initializes it.                 *\n *                                                                         *\n *    This routine will load an IFF icon set from disk.  It handles all    *\n *    of the necessary allocations.                                        *\n *                                                                         *\n * INPUT:   filename -- Name of the icon file.                             *\n *                                                                         *\n *          buffer   -- Pointer to paragraph aligned buffer to hold data.  *\n *                                                                         *\n *          size     -- Size of the buffer (in bytes).                     *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   In EEGA mode the iconset buffer will be free because the    *\n *             icons will have been transferred to card ram.               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1991 JLB : Created.                                             *\n *   07/01/1991 JLB : Determines icon size from file.                      *\n *   07/15/1991 JLB : Load and uncompress onto the same buffer.            *\n *   09/15/1993 JLB : Added EMS support.                                   *\n *=========================================================================*/\nvoid *  Load_Icon_Set(char const *filename, void *iconsetptr, long buffsize)\n{\n\tint\tfh;\t\t\t\t// File handle of iconset.\n\tint\tbytespericon;\t// The number of bytes per icon.\n\tunsigned long\ticons=0;\t\t\t// Number of icons loaded.\n\tunsigned long\tsize;\t\t\t\t// Size of the icon chunk (raw).\n\n\tunsigned long\ttranssize;\n\tvoid\t*transptr=NULL;\n\n\tunsigned long\tmapsize;\t\t\t\t// Icon map chunk size.\n\tvoid\t*mapptr=NULL;\t\t// Icon map pointer.\n\tvoid\t*returnptr=NULL;\t// Iconset pointer returned by routine.\n\tBOOL\tallocated=FALSE;\t// Was the iconset block allocated?\n\tIControl_Type\t*idata=NULL;\t// Icon data loaded.\n\tlong\tid;\t\t\t\t// ID of file openned.\n\tstruct {\n\t\tchar\tWidth;\t\t// Width of icon in bytes.\n\t\tchar\tHeight;\t\t// Height of icon in bytes.\n\t\tchar\tFormat;\t\t// Graphic mode.\n\t\t\t\t\t\t\t\t//lint -esym(754,Format)\n\t\tchar\tBitplanes;\t// Number of bitplanes per icon.\n\t} sinf;\n\n\t/*\n\t**\tOpen the icon set for loading.  If it is not a legal icon set\n\t**\tdata file, then abort.\n\t*/\n\tfh = Open_Iff_File(filename);\n\tif (fh != WW_ERROR) {\n\t\tRead_File(fh, &id, sizeof(long));\n\t\tif (id == FORM_ICON) {\n\n\t\t\t/*\n\t\t\t**\tDetermine the size of the icons and set up the graphic\n\t\t\t**\tsystem accordingly.  Also get the sizes of the various\n\t\t\t**\tdata blocks that have to be loaded.\n\t\t\t*/\n\t\t\tRead_Iff_Chunk(fh, FORM_SINF, &sinf, sizeof(sinf));\n\t\t\tbytespericon = ((((int)sinf.Width)<<3)*(((int)sinf.Height)<<3)*(int)sinf.Bitplanes)>>3;\n\n\t\t\tsize = Get_Iff_Chunk_Size(fh,FORM_SSET);\n\t\t\t\ttranssize = Get_Iff_Chunk_Size(fh, FORM_TRNS);\n\t\t\tmapsize = Get_Iff_Chunk_Size(fh, FORM_MAP);\n\n\t\t\t/*\n\t\t\t**\tAllocate the icon buffer if one isn't provided.  First try EMS and\n\t\t\t**\tthen try conventional RAM.\n\t\t\t*/\n\t\t\tallocated = FALSE;\n\t\t\tif (!iconsetptr) {\n\t\t\t\t\tbuffsize = size + transsize + mapsize + sizeof(IControl_Type);\n\n\t\t\t\tMisc = buffsize;\n\t\t\t\ticonsetptr = Alloc(buffsize, MEM_NORMAL);\n\t\t\t\tallocated = (iconsetptr != NULL);\n\t\t\t}\n\n\t\t\tif (iconsetptr && (size+transsize+mapsize+sizeof(IControl_Type)) <= buffsize) {\n\n\t\t\t\tidata = (IControl_Type *)iconsetptr;\n\n\t\t\t\tmemset(idata, 0, sizeof(IControl_Type));\n\n\t\t\t\t/*\n\t\t\t\t**\tInitialize the iconset header structure.\n\t\t\t\t*/\n\t\t\t\tidata->Width = (short)(((short)sinf.Width)<<3);\n\t\t\t\tidata->Height = (short)(((short)sinf.Height)<<3);\n\t\t\t\tidata->Allocated = (short)allocated;\n\t\t\t\tidata->Icons = (long)iconsetptr + sizeof(IControl_Type);\n\t\t\t\tidata->Map = idata->Icons + size;\n\t\t\t\t\tidata->TransFlag = sizeof(IControl_Type) + size + mapsize;\n\t\t\t\tidata->Size = buffsize;\n\n\t\t\t\t\t{\n\t\t\t\t\t\tlong\tval;\n\n\t\t\t\t\t\tval = Read_Iff_Chunk(fh, FORM_SSET, Add_Long_To_Pointer(iconsetptr, sizeof(IControl_Type)), size);\n\t\t\t\t\t\ticons = (int)(val/(long)bytespericon);\n\t\t\t\t\t\tidata = (IControl_Type *)iconsetptr;\n\t\t\t\t\t}\n\n\t\t\t\tif (mapsize) {\n\t\t\t\t\ticons = mapsize;\n\t\t\t\t}\n\t\t\t\tidata->Count = (short)icons;\n\n\t\t\t\t/*\n\t\t\t\t**\tLimit buffer to only the size needed.  This is done AFTER loading of the\n\t\t\t\t**\traw icon data because it might have been compressed and thus need any\n\t\t\t\t**\textra space to perform an overlapped decompression.\n\t\t\t\t*/\n\t\t\t\t\tif (buffsize > size + transsize + mapsize + sizeof(IControl_Type)) {\n\t\t\t\t\t\tbuffsize = size + transsize + mapsize + sizeof(IControl_Type);\n\t\t\t\t\t}\n\n\t\t\t\t\ttransptr = Add_Long_To_Pointer(iconsetptr, idata->TransFlag);\n\t\t\t\t\tRead_Iff_Chunk(fh, FORM_TRNS, transptr, transsize);\n\t\t\t\t\tidata = (IControl_Type *)iconsetptr;\n\n\t\t\t\tmapptr = (void*)idata->Map;\n\t\t\t\tRead_Iff_Chunk(fh, FORM_MAP, mapptr, mapsize);\n\n\t\t\t\t/*\n\t\t\t\t**\tLet the graphic overlay know of the icon data.  This could involve\n\t\t\t\t**\ttranslation and other data manipulations.\n\t\t\t\t*/\n\t\t\t\t//Init_Stamps(iconsetptr);\n\n\t\t\t\treturnptr = iconsetptr;\n\t\t\t}\n\t\t}\n\t\tClose_Iff_File(fh);\n\t}\n\n\treturn (returnptr);\t\t// Return with icon pointer.\n}\n\n\n/***************************************************************************\n * FREE_ICON_SET -- Frees allocations made by Load_Icon_Set().             *\n *                                                                         *\n *    This routine is used to free up any allocations by Load_Icon_Set().  *\n *    Use this routine when a new icon set is to be loaded.                *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid  Free_Icon_Set(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tif (icontrol->Allocated) {\n\t\t\tFree((void *)iconset);\n\t\t}\n\t}\n}\n\n\nlong  Get_Icon_Set_Size(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tlong\t\t\t\tsize=0;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tsize = icontrol->Size;\n\t}\n\treturn(size);\n}\n\n\nint  Get_Icon_Set_Width(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tint\t\t\t\twidth=0;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\twidth = icontrol->Width;\n\t}\n\treturn(width);\n}\n\n\nint  Get_Icon_Set_Height(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tint\t\t\t\theight=0;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\theight = icontrol->Height;\n\t}\n\treturn(height);\n}\n\n\nvoid *  Get_Icon_Set_Icondata(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol)\n\t\treturn(Add_Long_To_Pointer(iconset, (LONG)icontrol->Icons));\n\treturn(NULL);\n}\n\nvoid *  Get_Icon_Set_Trans(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tvoid\t\t\t\t*ptr=NULL;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tptr = Add_Long_To_Pointer((void *)iconset, icontrol->TransFlag);\n\t}\n\treturn(ptr);\n}\n\n\nint  Get_Icon_Set_Count(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tint\t\t\t\tcount;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tcount = icontrol->Count;\n\t}\n\treturn(count);\n}\n\n\nvoid *  Get_Icon_Set_Map(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol)\n\t\treturn(Add_Long_To_Pointer(iconset, (LONG)icontrol->Map));\n\treturn(NULL);\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/IFF.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : IFF.C                                    *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : May 16, 1991                             *\n *                                                                         *\n *                  Last Update : April 19, 1994   [SKB]                   *\n *                                                                         *\n *                                                                         *\n * IFF reader code designed for loading pictures (ILBM or PBM).            *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Close_Iff_File -- Closes an IFF file handle.                          *\n *   Get_Iff_Chunk_Size -- Get the size of the given IFF chunk.            *\n *   Open_Iff_File -- Opens an IFF file for reading.                       *\n *   Read_Iff_Chunk -- Reads a chunk from an IFF file.                     *\n *   Write_Iff_Chunk -- Writes an IFF chuck out.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"iff.h\"\n#include \"file.h\"\n\n#define ID_FORM\t\t\tMAKE_ID('F','O','R','M')\n\n#ifdef MIN\n#undef MIN\n#endif\n\n/***************************************************************************\n * OPEN_IFF_FILE -- Opens an IFF file for reading.                         *\n *                                                                         *\n *    This function will open an IFF file for reading.  It will perform    *\n *    a the simple validity test of checking the first four bytes to make  *\n *    sure they are \"FORM\".  The value returned is the filehandle of the   *\n *    opened file.                                                         *\n *                                                                         *\n * INPUT:   filename - ASCII name of the IFF file to be opened.            *\n *                                                                         *\n * OUTPUT:  Returns the filehandle.  If there is an error or the file      *\n *          is not an IFF FORM then -1 will be returned.                   *\n *                                                                         *\n * WARNINGS:   You are responsible for error handling if this function     *\n *             returns -1 (not an IFF file).                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1991 JLB : Created.                                             *\n *   04/19/1994 SKB : Update to 32 bit library.                            *\n *=========================================================================*/\nint __cdecl Open_Iff_File(char const *filename)\n{\n\tint\tfh;\t\t// File handle.\n\tlong\ttype;\t\t// IFF file type.\n\n\n\t/* We want to be able to open the file for READ | WRITE, but we do not\n\t   want the Open_File to create it.  So check to see if it exists before\n\t\tthe Open_File */\n\n//\tfh = Open_File(filename, READ);\t\t// Open the source file for READ\n//\tClose_File(fh);\n\n\t//fh = Open_File(filename, READ | WRITE);\t// Open the source file again\n\tfh = Open_File(filename, READ);\t// Open the source file again\n\n\t//\tValidate that it is a FORM type.\n\n\tRead_File(fh, &type, 4L);\n\n\tif (type == ID_FORM) {\n\n\t\t//\tThe file is valid (so far).  Position the read so that the actual\n\t\t//\tIFF file type code can be read.\n\n\t\tSeek_File(fh, 4L, SEEK_CUR);\t\t// Skip the filesize bytes.\n\n\t} else {\n\n\t\t// This is NOT an IFF file.  Close the source file and return with\n\t\t//\tthe error code.\n\t\tClose_File(fh);\n\t\tfh = WW_ERROR;\n\t}\n\treturn fh;\n}\n\n\n/***************************************************************************\n * CLOSE_IFF_FILE -- Closes an IFF file handle.                            *\n *                                                                         *\n *    The routine will close the file that was opened with the             *\n *    Open_Iff_File() function.                                            *\n *                                                                         *\n * INPUT:   fh - File handle that was returned from Open_Iff_File().       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1991 JLB : Created.                                             *\n *   04/19/1994 SKB : Update to 32 bit library.                            *\n *=========================================================================*/\nvoid __cdecl Close_Iff_File(int fh)\n{\n\tif (fh != WW_ERROR) Close_File(fh);\n}\n\n\n/***************************************************************************\n * GET_IFF_CHUNK_SIZE -- Get the size of the given IFF chunk.              *\n *                                                                         *\n * INPUT:      int file handle to open IFF file, long id to get size of   *\n *                                                                         *\n * OUTPUT:     long size of the chunk or 0L if it was not found            *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/03/1991  CY : Created.                                             *\n *   04/19/1994 SKB : Update to 32 bit library.                            *\n *=========================================================================*/\nunsigned long __cdecl Get_Iff_Chunk_Size(int fh, long id)\n{\n\tlong\tform;\t\t\t\t\t// Chunk iff form name.\n\tlong\tchunksize;\t\t\t// Size of the chunk.\n\tchar\tfirst_iteration;\t// Check once the current chunk name\n\n\n\tfirst_iteration = TRUE;\n\n\tfor (;;) {\n\t\tif (Read_File(fh, &form, 4L) != 4L && !first_iteration) break;\n\n\n\t\tif (Read_File(fh, (char *) &chunksize, 4L) != 4L && !first_iteration) break;\n\n#if(IBM)\n\t\tchunksize = Reverse_Long(chunksize);\n#endif\n\n\t\tif (id == form) {\n\t\t\tSeek_File(fh, -8L, SEEK_CUR);\t\t\t// Seek back to the start of\n\t\t\treturn(chunksize);\t\t\t\t\t\t// the chunk & return size\n\t\t} else {\n\n\t\t\tif (first_iteration) {\n\t\t\t\tSeek_File(fh, 12L, SEEK_SET);\t\t// Start at beginning of file.\n\t\t\t\tfirst_iteration = FALSE;\t\t\t// Don't do this again\n\t\t\t} else {\n\n\t\t\t\t/* Otherwise, go to the next chunk in the file */\n\n\t\t\t\tchunksize = (chunksize + 1) & 0xFFFFFFFEL;\n\t\t\t\tSeek_File(fh, chunksize, SEEK_CUR);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(0L);\n}\n\n\n/***************************************************************************\n * READ_IFF_CHUNK -- Reads a chunk from an IFF file.                       *\n *                                                                         *\n *    Once an IFF file is opened, various chunks must be read from it.     *\n *    This routine will search through the IFF file and load in the        *\n *    specified chunk.  It will scan through the entire file when          *\n *    searching for the chunk.  It will load the FIRST chunk of the given  *\n *    type.                                                                *\n *                                                                         *\n * INPUT:   fh       - File handle of IFF file.                            *\n *                                                                         *\n *          id       - Chunk ID code.                                      *\n *                                                                         *\n *          buffer   - Pointer to buffer to load the chunk.                *\n *                                                                         *\n *          maxsize  - Maximum data bytes to read.                         *\n *                                                                         *\n * OUTPUT:     Returns with the number of bytes read from the chunk.       *\n *             If 0 is returned, this indicates that the chunk wasn't      *\n *             found.                                                      *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1991 JLB : Created.                                             *\n *   04/19/1994 SKB : Update to 32 bit library.                            *\n *=========================================================================*/\nunsigned long __cdecl Read_Iff_Chunk(int fh, long id, void *buffer, unsigned long maxsize)\n{\n\tlong\tform;\t\t\t\t\t// Chunk iff form name.\n\tunsigned long\tchunksize;\t\t\t// Size of the chunk.\n\tchar\tfirst_iteration;\t// Check once the current chunk name\n\n\tfirst_iteration = TRUE;\n\n\tfor (;;) {\n\t\tif (Read_File(fh, &form, 4L) != 4L && !first_iteration) break;\n\n\t\tif (Read_File(fh, (char *) &chunksize, 4L) != 4L && !first_iteration) break;\n\n#if(IBM)\n\t\tchunksize = Reverse_Long(chunksize);\n#endif\n\n\t\tif (id == form) {\n\n\t\t\tmaxsize = MIN(maxsize, chunksize);\n\t\t\tRead_File(fh, buffer, maxsize);\t\t// Read the buffer.\n\n\t\t\tchunksize = (chunksize + 1) & 0xFFFFFFFEL;\n\t\t\tif (maxsize < chunksize) {\n\t\t\t\tSeek_File(fh, chunksize - maxsize, SEEK_CUR);\n\t\t\t}\n\t\t\treturn(maxsize);\n\t\t} else {\n\n\t\t\tif (first_iteration) {\n\t\t\t\tSeek_File(fh, 12L, SEEK_SET);\t\t// Start at beginning of file.\n\t\t\t\tfirst_iteration = FALSE;\t\t\t// Don't do this again\n\n\t\t\t} else {\n\n\t\t\t\t/* Otherwise, go to the next chunk in the file */\n\n\t\t\t\tchunksize = (chunksize + 1) & 0xFFFFFFFEL;\n\t\t\t\tSeek_File(fh, chunksize, SEEK_CUR);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(0L);\n}\n\n\n\n/***************************************************************************\n * WRITE_IFF_CHUNK -- Writes an IFF chuck out.                             *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid __cdecl Write_Iff_Chunk(int file, long id, void *buffer, long length)\n{\n\tlong\tpos;\t\t// Current position in the IFF file.\n\tlong\toldpos;\t// Record of start of chunk offset.\n\tlong\tendpos;\t// end of file offset before we write our data\n\tlong\tvalue;\n\tBOOL\todd;\t\t// Is length odd?\n\tchar\tpad = 0;\t// Optional padding byte for even sized chunks.\n\n\t/*\n\t** Get the current end of file (before we write more data to the file)\n\t*/\n\tpos \t = Seek_File (file, 0L, SEEK_CUR);\n\tendpos = Seek_File (file, 0L, SEEK_END);\n\tSeek_File (file, pos, SEEK_SET);\n\n\tif (length) {\n\t\tvalue = id;\n\t\todd = (short)length & 0x01;\n\n\t\tWrite_File(file, &value, 4L);\n\t\toldpos = Seek_File(file, 0L, SEEK_CUR);\n\t\tWrite_File(file, &value, 4L);\n\t\tWrite_File(file, buffer, length);\n\t\tpos = Seek_File(file, 0L, SEEK_CUR);\n\t\tif (odd) {\n\t\t\tWrite_File(file, &pad, 1L);\n\t\t}\n\n\t\t/*\n\t\t**\tUpdate the chunk size long.\n\t\t*/\n\t\tSeek_File(file, oldpos, SEEK_SET);\n\t\tvalue = IFFize_LONG((pos - oldpos)-4);\n\t\tWrite_File(file, &value, 4L);\n\n\t\t/*\n\t\t**\tUpdate the file size LONG. if we are not just overwriting existing data\n\t\t*/\n\t\t// (MCC)\n\t\tif ( endpos < pos ) {\n\t\t\tSeek_File(file, 4L, SEEK_SET);\n\t\t\tvalue = IFFize_LONG((pos+odd) - 8);\n\t\t\tWrite_File(file, &value, 4L);\n\t\t}\n\n\t\t/*\n\t\t**\tReturn to end of file.\n\t\t*/\n\t\tSeek_File(file, 0L, SEEK_END);\n\t}\n}\n\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/INITDLAY.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : INITDLAY.C                               *\n *                                                                         *\n *                   Programmer : Barry Green                              *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Init_Delay -- I am not sure                                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwstd.h\"\n#include \"timer.h\"\n#include \"video.h\"\n\t\t   \t \nBOOL VertBlank;\n\n/***************************************************************************\n * INIT_DELAY -- I am not sure                                             *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/03/1994 SKB : Created.                                             *\n *=========================================================================*/\nVOID Init_Delay(VOID)\n{\t  \n\tWORD nz, nnz;\n\n\tnz = nnz = 0;\n\n\tCountDown.Set(15, TRUE); // set to  1/4 second and start it\n\t\n\tdo {\n\t\tif (Get_Vert_Blank())\n\t\t\tnnz++;\n\t\telse\n\t\t\tnz++;\n\t} while (CountDown.Time());\n\n\tVertBlank = (nnz > nz);\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/INITMONO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Initialize mono                          *\n *                                                                         *\n *                    File Name : INITMONO.CPP                             *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : March 28, 1994                           *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n#ifndef MONO_H\n#include \"mono.h\"\n#endif\n\n#ifndef DESCMGMT_H\n#include \"descmgmt.h\"\n#endif\n\n/***************************************************************************\n * INITIALIZE_MONO_SCREEN -- Initializes the Mono display data             *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/21/1994  jaw: Created.                                             *\n *========================================================================*/\n\t\t\t\t   \nint Initialize_Mono_Screen(void)\n{\t\t\t\t\t\t\t \n\t// get a valid selector to mono screen.\n//\tMap_Segment_To_Address(0x0b0000UL, 0x8000UL);\n\n\tMonoScreen = 0xb0000\t;\n\n\treturn (int)0;\n}\t\t\t\n\n\u001a\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/IRANDOM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : IRANDOM.C                                *\n *                                                                         *\n *                   Programmer : Barry W. Green                           *\n *                                                                         *\n *                  Last Update : 10 Feb, 1995     [BWG]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <stdlib.h>\n#include <time.h>\n#include \"misc.h\"\n\n\n\n\n\n\n/* IRANDOM ----------------------------------------------------------\n\n   IRandom returns a random value between min and max inclusive.\n\n   INPUTS:\tint min and int max\n\n   RETURNS:\tint random number\n*/\n\nint IRandom(int minval, int maxval)\n{\n\tint num,mask;\n\n\t// Keep minval and maxval straight.\n\tif (minval > maxval) {\n\t\tminval ^= maxval;\n\t\tmaxval ^= minval;\n\t\tminval ^= maxval;\n\t}\n\n\tmask = Get_Random_Mask(maxval - minval);\n\n\twhile( (num = (rand() & mask) + minval) > maxval ) ;\n\treturn(num);\n}\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/KEYBOARD.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : KEYBOARD.ASM                             *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 15, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Get_RM_Timer_Address -- Return address of real mode code for copy.    *\n;*   Get_RM_Keyboard_Size -- return size of real mode timer code.          *\n;*   Check_Key -- checks queue for key (make)                              *\n;*   Check_Key_Num -- Checks if key in queue, return key num               *\n;*   Get_Key_Num -- Returns the next key num in ax                         *\n;*   KN_To_KA -- Translates a key num to an ASCII key                      *\n;*   Low_Get_Key -- low level get key returns key num and bits             *\n;*   Convert_Num_To_ASCII -- Assembly routine converts keynum to ASCII key *\n;*   KeyNum_Translate -- Performs a lowlevel xlate to a keycode            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\n;*\tKeyboard driver -- 80386 Protected Mode Assembly portion\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\n;***************************************************************************\n;\n; ----------------------------------------------------------------\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\n;WARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Make some general equates for easy compatability\n;---------------------------------------------------------------------------\nPROT_INT_ENABLE\tEQU\t1\t\t; if false protected int just calls real mode int\n\nDPMI_INTR\tEQU\t31h\nIRQ1INTNUM\tEQU\t09h\t\t; IRQ1 interrupt vector number.\nBRKINTNUM\tEQU\t23h\t\t; Crtl-C (Break) interrupt vector number\nDBGINTNUM\tEQU\t3h\t\t; Debug interrupt vector number\nDOS_SYS_CALL\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nLOCK_PAGES\tEQU\t5\t\t; Lock pages subfunction using DX_MEM_MGT\nUNLOCK_PAGES\tEQU\t6\t\t; Unlock pages subfunction using DX_MEM_MGT\nCLEARISR\tEQU\t020H\t; value to clear In Service Register\nINTCHIP0\tEQU\t020H\t; 8259 interrupt chip controller 0\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\n\tINCLUDE \"keyboard.inc\"\n\tINCLUDE \"keystruc.inc\"\n\tINCLUDE \"drawbuff.inc\"\n\n\tGLOBAL C\t RealModePtr:DWORD\n\n\tGLOBAL C\t Install_Keyboard_Interrupt:NEAR\n\tGLOBAL C\t Get_RM_Keyboard_Address:Near\n\tGLOBAL C\t Get_RM_Keyboard_Size:Near\n\tGLOBAL C\t Remove_Keyboard_Interrupt:NEAR\n\tGLOBAL C\t Check_Key_Num:NEAR\n\tGLOBAL C\t Get_Key_Num:NEAR\n\tGLOBAL C\t KN_To_KA:NEAR\n\tGLOBAL C\t KeyNum_Translate:NEAR\n\tGLOBAL C\t Check_Key:NEAR\n\tGLOBAL C\t Get_Key:NEAR\n\tGLOBAL C\t Keyboard_Attributes_On:NEAR\n\tGLOBAL C\t Clear_KeyBuffer:NEAR\n\tGLOBAL C\t Key_Down:NEAR\n\tGLOBAL C\t Keyboard_Attributes_Off:NEAR\n\tGLOBAL C\t Check_Key_Bits:NEAR\n\tGLOBAL C\t Get_Key_Bits:NEAR\n\tGLOBAL C\t Key_Satisfied:NEAR\n\tGLOBAL C\t Stuff_Key_WORD:NEAR\n\tGLOBAL C\t Stuff_Key_Num:NEAR\n\tGLOBAL C\t MouseQX:DWORD\n\tGLOBAL C\t MouseQY:DWORD\n;DBG\n\tGLOBAL C   Keyboard_Interrupt:NEAR\n\n\n\tDATASEG\n; For the current time we will just include the real mode stuff\n; into the protected mode code and then copy it down.  The C side of\n; this will handle this method or reading it off of disk in the real\n; method.\n\nLABEL \tRealBinStart\tBYTE\ninclude \"keyireal.ibn\"\nLABEL\tRealBinEnd\tBYTE\n\nLABEL\tLockedDataStart\tBYTE\nRMVector\tDD\t0\nRealModeSel\tDD\t0\nRealModePtr\tDD\t0\t\t; Pointer to real mode memory.\nRealModeSize\tDD\t0\t\t; Pointer to real mode memory.\nLABEL\tLockedDataEnd\tBYTE\n\n\n\nAscii\tDB\t0,\"`1234567890-=\",0,8,9,\"qwertyuiop[]\\\",0,\"asdfghjkl;'\"\n\tDB\t0,13,0,45,\"zxcvbnm,./\",0,0,0,0,0,\" \"\n\nShift\tDB\t0,\"~!@#$%^&*()_+\",0,8,9,\"QWERTYUIOP{}|\",0,\"ASDFGHJKL:\",22H\n\tDB\t0,13,0,45,\"ZXCVBNM<>?\",0,0,0,0,0,\" \"\n\nAlpha_Lower\tDB\t0\n\tDB\t\"~!@#$%^&*()_+\",0,8,9,\"qwertyuiop{}|\",0,\"asdfghjkl:\",22H\n\tDB\t0,13,0,45,\"zxcvbnm<>?\",0,0,0,0,0,\" \"\n\nAlpha_Shift\tDB\t0\n\tDB\t\"`1234567890-=\",0,8,9,\"QWERTYUIOP[]\\\",0,\"ASDFGHJKL;'\"\n\tDB\t0,13,0,45,\"ZXCVBNM,./\",0,0,0,0,0,\" \"\n\nEdit\tDB\t0AEH,0ADH,000H,000H,0B5H,0B9H,0B1H,000H,0B8H,0B0H,0B7H,0AFH\n\tDB\t000H,000H,0B3H,000H,0B9H,0B5H,0B1H,000H, \"/\",0B8H,0B4H,0B0H\n\tDB\t0AEH, \"*\",0B7H,0B3H,0AFH,0ADH, \"-\", \"+\",000H,00DH,000H\n\nNumPad\tDB\t0,\"741\",0,\"/8520*963.-+\",0,13,0\n\n\nGetKeyLock\tDW\t0\t; snap shot of num and caps lock bits\nInitFlags\tDW\t0\nMouseQX\t\tDD\t0\nMouseQY\t\tDD\t0\n\n\tCODESEG\n;***************************************************************************\n;* GET_RM_TIMER_ADDRESS -- Return address of real mode code for copy.      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      VOID * to the address of the real mode timer               *\n;*                                                                         *\n;* PROTO:\tVOID\t*Get_RM_Keyboard_Address(VOID);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Address C Near\nifdef NOT_FOR_WIN95\n\n\tmov\teax, OFFSET RealBinStart\n\tret\nendif;ifdef NOT_FOR_WIN95\n\n\tENDP\n\n;***************************************************************************\n;* GET_RM_KEYBOARD_SIZE -- return size of real mode timer code.            *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      LONG size of the real mode timer code                      *\n;*                                                                         *\n;* PROTO:\tLONG\tGet_RM_Keyboard_Size(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Size C Near\n\nret\n\tmov\teax, OFFSET RealBinEnd - OFFSET RealBinStart\n\tret\n\n\tENDP\n;***************************************************************************\n;* INSTALL_KEYBOARD_INTERRUPT -- Installs the keyboard interrupt           *\n;*                                                                         *\n;* INPUT:\tint rm_ptr  - ptr to the real mode handler\t\t   *\t   *\n;*\t\tint rm_size - size of the real mode handler\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Install_Keyboard_Interrupt(int rm_ptr, int rm_size);  *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tInstall_Keyboard_Interrupt C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\tARG\trm_ptr:DWORD\n\tARG\trm_size:DWORD\n\nifdef NOT_FOR_WIN95\n\t; Are they attempting to set timer again?\n\tcmp\t[RealModePtr],0\n\tjnz\t??error\n\n\t; Make sure all flags are cleared.\n\tcmp\t[InitFlags],0\n\tjnz\t??error\n\n\n\t; Before setting the interrupt vectors, the code needs to be locked\n\t; for DPMI compatability.  Any code or data accessed must be lockded\n\t; so that no page faults accure during an interrupt.\n\t; First lock the code, then the data.  The stack will already be locked.\n\t; The real mode code is also already locked be default.\n\t; To lock a page set up registers :\n\t; AX = 0600h\n\t; BX:CX\t= starting linear address of memory block\n\t; SI:DI = size of region\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_CODE\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_DATA\n\n\t; now allocate real mode memory and copy the rm binary down to it.\n\tmov\teax,0100h\t; set function number\n\tmov\tebx,[rm_size]\t\t; get size of RM binary.\n\tmov\t[RealModeSize],ebx\n\tadd\tebx,15\t\t\t; round up\n\tshr\tebx,4\t\t\t; convert to pages.\n\tint\tDPMI_INTR\t \t; do call.\n\tjc\t??error\t\t \t; check for error.\n\tor\t[InitFlags],IF_ALLOC_RM ; set successful\n\tmov\t[RealModeSel],edx\n\tshl\teax,4\t\t\t; convert segment to offset.\n\tmov\t[RealModePtr],eax\t; save offset to global variable.\n\n\t; now lock the real mode memory that we allocated\n\tmov\teax,0600h\t\t; function number.\n\tmov\tecx,[RealModePtr]\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_RM_CODE\n\n\n\n\t; set up source and destination pointers for the copy.\n\tmov\teax,[RealModePtr];\t; set up our dest pointer\n\tmov\tesi,[rm_ptr]\t\t; Set up our source pointer.\n\tmov\tedi,eax\t\t\t; put it into esi for copy.\n\tmov\tecx,[rm_size]\n\trep\tmovsb\t\t\t; write RM bin to RM memory.\n\n\t; restore esi to point to data and initialize some of it.\n\tmov\tesi,[RealModePtr]\n\tmov\teax,esi\n\tshl\teax,12\t\t\t\t\t\t; make seg in high eax.\n\tmov\tax,[(KeyboardType PTR esi).CallKeyRMIntOffset]\t; create RM addr of call chain.\n\tmov\t[(KeyboardType PTR esi).CallKeyRMIntAddr],eax\t; save it for use in PM int.\n\nIF NOT PROT_INT_ENABLE\n       ; Chain the Real Keyboard interrupt to any avilable\n       ; Interrupt vector so We make sure that the Real Mode\n       ; Keyboard Interrupt service get called at debuging time\n       ; of the library.\n\n       mov\tedi , eax\n       mov\tbl , 060h\n       mov\tbh , 6\n       mov\teax , 200h\n ??find:\n       int\tDPMI_INTR\n       jc\t??error\n       or\tcx,dx\n       jz\t??found\n       inc\tbl\n       dec\tbh\n       jnz\t??find\n       jmp\t??error\n ??found:\n       movzx\tebx , bl\n       mov\t[ byte ptr RMVector ] , bl\n       mov\t[ 4 * ebx ] , edi\nENDIF\n\n\n\n\t;-------------------------------------------------------\n\t; Initialize all of the keyboard specific information\n\t;-------------------------------------------------------\n\txor\teax,eax\t\t\t; clear the high bits of eax\n\tmov\tal,[417H]\t\t; get keyboard status flags\n\ttest\teax,040H \t\t; caps lock active?\n\tje \tshort ??nocap\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\n\n??nocap:\n\ttest\teax,020H\t\t\t; num lock active?\n\tje\tshort ??nonumlock\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\n\n??nonumlock:\n\ttest\teax,002H\t\t\t; is left shift key down?\n\tje\tshort ??noleftshift\t\t; try the right\n\tor\t[(KeyboardType PTR esi+5).KeysUpDown],010H\n\n??noleftshift:\n\tand\teax,001H\t\t\t; get right shift bit\n\tshl\teax,9\t\t\t; put it into the proper position (shl al,1 mov ah,al)\n\tmov\tal,[418H]\t\t; get alt and ctrl bits\n\tshl\tal,2\t\t\t; put in proper position\n\tshl\tal,1\n\tand\tal,00CH\t\t\t; only alt and ctrl bits\n\tor\tah,al\t\t\t; put them ah for Keys+7 later\n\tmov\tal,[496H]\t\t; get extended keys\n\ttest\tal,008H\t\t\t; check for right alt key\n\tje\tshort ??noralt\n\tor\tah,040H\n??noralt:\n\tmov\t[(KeyboardType PTR esi+7).KeysUpDown],ah\n\ttest\tal,004H\t\t\t; test for right ctrl\n\tje \tshort ??norctrl\n\tor\t[(KeyboardType PTR esi+8).KeysUpDown],001h\n??norctrl:\n\ttest\tal,002H\t\t\t; last code E0?\n\tje short ??noe0\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],001h\n??noe0:\n\ttest\tal,001H\t\t\t; last code E1?\n\tje short ??noe1\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],002h\n??noe1:\n\t;==========================================================================\n\t; Get the protected mode interrupt vector keyboard.\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).KeyOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).KeyOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 2503, cl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).KeyOldRMI],ecx\n\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt Keyboard\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Keyboard_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt Keyboard\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).KeyCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the break interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).BrkOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).BrkOldPMISelector],ecx\t; save selector.\n\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector - for the break interrupt\n\t; input ax = 0200, bl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).BrkOldRMI],ecx\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Break_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).BrkCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\nIF DEBUG\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the Debug interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,DBGINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).DbgOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).DbgOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Debug_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\nENDIF\n\n\t; we have finished with success.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n??exit:\nendif ;NOT_FOR_WIN95\n\tret\n\tENDP\tInstall_Keyboard_Interrupt\n\n;***************************************************************************\n;* REMOVE_INTERRUPT -- Removes keyboard interrupt and restores chain\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Remove_Interrupt(VOID)                                *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tRemove_Keyboard_Interrupt C NEAR\n\tUSES\tebx,ecx,edx\n\nifdef NOT_FOR_WIN95\n\t; verifie that the keyboard was previosly install\n\t; this is here in case of a page fault crash\n\tmov\tesi,[RealModePtr]\n\ttest    esi,esi\n\tjz      ??error\n\n\ttest\t[InitFlags],IF_SET_VECTORS\n\tjz\t??vectors_not_set\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tedx,[(KeyboardType esi).KeyOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[(KeyboardType esi).KeyOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).KeyOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\n\t; disengage Control Break Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tedx,[(KeyboardType esi).BrkOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[(KeyboardType esi).BrkOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).BrkOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\nIF DEBUG\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tecx,[(KeyboardType esi).DbgOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).DbgOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\nENDIF\n\nIF NOT PROT_INT_ENABLE\n       ; Clean up the Users interrupt table\n        mov\teax , 201h\n       mov\tbl , [ byte ptr RMVector ]\n       xor\tecx , ecx\n       xor\tedx , edx\n       int\tDPMI_INTR\n       jc\t??error\nENDIF\n\n\n??vectors_not_set:\n\t; now free up the real mode memory.\n\ttest\t[InitFlags],IF_LOCKED_RM_CODE\n\tjz\t??rm_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,[RealModePtr]\t\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t\t; edx will have size of region in bytes.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??rm_not_locked:\n\ttest\t[InitFlags],IF_ALLOC_RM\n\tjz\t??mem_not_allocated\n\tmov\teax , 0101h\n\tmov\tedx,[ RealModeSel ] \t\t; get physical address of real mode buffer.\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n??mem_not_allocated:\n\n\t; Now we can unlock all stuff needed for the interrupt.\n\t; Unlock Code\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??code_not_locked:\n\n\t; Unlock data\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??data_not_locked:\n\n\t; we have finished with success.\n\tmov\t[RealModePtr],0\t\t; To say we can do it again sometime.\n\tmov\t[InitFlags],0\t\t; To say we can do it again sometime.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\nendif; NOT_FOR_WIN95\n\tret\n\tENDP\tRemove_Keyboard_Interrupt\n\n\n;***************************************************************************\n;* CHECK_KEY_NUM -- Checks if key in queue, return key num                 *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      Keynum of the key that was pressed, FALSE otherwise        *\n;*\n;* PROTO:\tINT Check_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Num C NEAR\n\tUSES\tebx,esi\nifdef NOT_FOR_WIN95\n\tpushf\t\t\t\t\t; save off the flags\n\tcli\t\t\t\t\t; disable interrupts\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\n\txor\teax,[(KeyboardType PTR esi).KeyBufferTail]\n\tor\teax,eax\t\t\t\t; check to see if head == tail\n\tjz\tshort ??fini\t\t\t; if so we are done\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t; get the head\n\tmov\tax,[(KeyboardType PTR esi+eax).KeyBuffer]\t; get key num\n\n??fini:\n\tsti\n\tpopf\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tCheck_Key_Num\n\n;***************************************************************************\n;* GET_KEY_NUM -- Returns the next key num in ax                           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      WORD key flags are in the high byte of return word, key    *\n;*\t\t  num is in the low byte.\n;*                                                                         *\n;* PROTO:\tWORD Get_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Num C NEAR\n\tUSES\tesi,edi\n\nifdef NOT_FOR_WIN95\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n??wait:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t\t; get the head\n\tcmp\teax,[(KeyboardType PTR esi).KeyBufferTail]\t\t; get the head\n\tjne\tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??wait\n\n??getkey:\n\tcall\tLow_Get_Key\n\tsti\t\t\t\t; enable interrupts\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tGet_Key_Num\n\n;***************************************************************************\n;* KN_TO_KA -- Translates a key num to an ASCII key                        *\n;*                                                                         *\n;* INPUT:\tWORD the keynum to translate                               *\n;*                                                                         *\n;* OUTPUT:      WORD the ASCII key that is returned                        *\n;*                                                                         *\n;* PROTO:\tINT KN_To_KA(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tKN_To_KA C NEAR\n\tARG\tkeynum:DWORD\n\nifdef NOT_FOR_WIN95\n\tmov\teax,[keynum]\n\tcall\tnear ptr Convert_Num_To_ASCII\n\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tKN_To_KA\n\n\n;***************************************************************************\n;* LOW_GET_KEY -- low level get key returns key num and bits               *\n;*                                                                         *\n;* INPUT:\tAX - index into the buffer                                 *\n;*                                                                         *\n;* OUTPUT:      AX - key num with bits                                     *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tLow_Get_Key C NEAR\n\tUSES\tebx,esi,edi\n\nifdef NOT_FOR_WIN95\n\tmov\tedi,eax\t\t\t\t; save off value in ax\n\n; We should set up both DS & ES because we are a low level function\n; and don't know who might have called us or what the registers\n; currently are.\n\n; No reason to set DS & ES.\n; This is not a hardware interrupt and if the funtion is being called\n; from within a hardware interrupt then DS and ES will be preset to\n; DGROUP _DATA\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tcmp\tal,KN_LMOUSE\n\tjb \tshort ??cont\n\tcmp\tal,KN_RMOUSE\n\tja \tshort ??chkjoy\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t; 128 word circular buffer\n\n\tmov\t[MouseQX],eax\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\t[MouseQY],eax\n\n\tpop\teax\t\t\t; restore keynum for return\n\n\tjmp\tshort ??cont\n\n??chkjoy:\n\tcmp\tal,KN_JBUTTON2\t\t; mouse button before joystick button\n\tja \tshort ??cont\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tpop\teax\t\t\t; restore keynum for return\n??cont:\n\tmov\t[(KeyboardType PTR esi).KeyBufferHead],edi\t; set the head\n\n??out:\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tLow_Get_Key\n\n;***************************************************************************\n;* CONVERT_NUM_TO_ASCII -- Assembly routine converts keynum to ASCII key   *\n;*                                                                         *\n;* INPUT:\tEAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - holds the key num bits                        *\n;*\t\t\tAL - holds the key num value\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      EAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - hold the key bits                             *\n;*\t\t\tAL - holds the ASCII key value\t\t\t   *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* WARNINGS:    GetKeyLock must be set prior to calling this function\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tConvert_Num_To_ASCII C NEAR\n\tUSES\tebx,ecx,esi,edi\n\nifdef NOT_FOR_WIN95\n\t;*===================================================================\n\t;* Force all breaks to be thrown out.\n\t;*===================================================================\n\ttest\teax,08000h\t\t; If it is a button number\n\tjne\tshort ??button\t\t;  don't process it\n\n\ttest\tah,KEYRELEASE\t\t; If it is not key release\n\tje\tshort ??ok\t\t;  then go process it\n\n??button:\n\txor\teax,eax\t\t\t; no ascii value for a button\n\tret\n\n??ok:\n\t;*===================================================================\n\t;* ES points to the DOSMEM selector, esi is the offset of the\n\t;*   protected mode structure.\n\t;*===================================================================\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\n\t;*===================================================================\n\t;* Start dealing with the keys.\n\t;*===================================================================\n\tcmp\tal,110\t\t\t; is it esc\n\tje\t??esc\t\t\t; if so then deal with it\n\n;??chkext:\n\tcmp\tal,62\t\t\t; is it extended?\n\tjae\tshort ??extended\t; its extended so return ext code\n\n\tmov\tebx,eax\t\t\t; get an index\n\tand\tebx,03FH\t\t; only 0-63 allowed\n\ttest\tah,1\t\t\t; if not, test for shift\n\tjnz\tshort ??shifted\t\t; if shifted get shift value\n\n\t;*===================================================================\n\t;* Here when we have an unshifted ascii key\n\t;*===================================================================\n\tmov\tal,[Ascii+ebx]\t\t; get the ascii code for this number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_lowered:\n\tmov\tal,[Alpha_Lower+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_shifted:\n\tmov\tal,[Alpha_Shift+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* Shift'ed character\n\t;*===================================================================\n??shifted:\n\tmov\tal,[Shift+ebx] \t\t; get ascii shift code for number\n\n??ctrlkey:\n\ttest\tah,2\t\t\t; is it ctrl?\n\tjz \tshort ??jexit\t\t; izf not skip ctrl check\n\n\tmov\tedi,ebx\t\t\t; get index\n\tand\tedi,7\t\t\t; only bits 0-7\n\n\tmov\tcl,[(KeyboardType PTR esi+edi).Bits]\n\n\tshr\tebx,3\t\t\t; div by 8 for byte offset\n\ttest\t[(KeyboardType PTR esi+ebx).KeysCapsLock],cl\n\tje \tshort ??jexit\n\tand\tal,01FH\t\t\t; force to ctrl value\n\n??jexit:\n\tjmp short ??exit\n\n??extended:\n\tcmp\tal,75\t\t\t; if less than insert\n\tjb \tshort ??special\n\tcmp\tal,110\t\t\t; if >= esc\n\tjae \tshort ??funckey\n\n??editkeys:\n\txor\tebx,ebx\n\tmov\tbl,al\n\tsub\tebx,75\t\t\t; get value from 0-34\n\ttest\t[(KeyboardType PTR esi).KeyFlags],NONUMLOCK\n\tjne \tshort ??no_numpad\n\ttest\t[GetKeyLock],NUMLOCK\t; look at the snap shot of bits\n\tjne \tshort ??numpad\n\n??no_numpad:\n\tmov\tal,[Edit+ebx] \t\t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??numpad:\n\tsub\tebx,15\t\t\t; adjust to numpad entries\n\tmov\tal,[NumPad+ebx] \t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??funckey:\n\tcmp\tal,112\t\t\t; if less than function keys\n\tjb \tshort ??extout\n\tcmp\tal,121\t\t\t; if greater than function keys 1-10\n\tja \tshort ??extout\n\tmov\tbl,al\n\tsub\tbl,112\t\t\t; get value 0-9\n\tmov\tbh,0C5H\t\t\t; function key 1 no shift-ctrl-alt\n\ttest\tah,7\t\t\t; any shift-ctrl-alt\n\tje\tshort ??funcadj\n\tmov\tbh,098H\t\t\t; function key 1 alt\n\ttest\tah,ALTPRESS\t\t; (highest prescendence)\n\tjne \tshort ??funcadj\n\tmov\tbh,0A2H\t\t\t; function key 1 ctrl (next highest)\n\ttest\tah,CTRLPRESS\n\tjne\tshort ??funcadj\n\tmov\tbh,0ACH\t\t\t; function key 1 shift (lowest)\n\n??funcadj:\n\tsub\tbh,bl\t\t\t; adjust function key to a\n\tmov\tal,bh\t\t\t; shift/no shift etc\n\tjmp\tshort ??exit\n\n??special:\n\tcmp\tal,65\t\t\t; if less than specials\n\tjb\tshort ??extout\n\n\tadd\tal,133\t\t\t; make value between 198-207 or\n\tjmp\tshort ??exit\t\t; 0C6H-0CFH\n\n??extout:\n\tor\tal,080H\n\tjmp\tshort ??exit\n\n??esc:\n\tmov\tal,01BH\n\n??exit:\nendif; NOT_FOR_WIN95\n\tret\n\tENDP\tConvert_Num_To_ASCII\n\n;***************************************************************************\n;* CHECK_KEY -- checks for ASCII keys sitting in the keybuffer             *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      INT the ASCII sequence for the key that was pressed        *\n;*                                                                         *\n;* PROTO:\tINT Check_Key(VOID);                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key C NEAR\n\tUSES\tebx,edi,esi\n\nifdef NOT_FOR_WIN95\n\tpushf\n\tcld\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tcmp\tal,KN_LMOUSE\t\t; check if it is a mouse or joystick\n\tjb\tshort ??contget\n\tcmp\tal,KN_JBUTTON2\n\tja\tshort ??contget\n\tadd\tsi,4\t\t\t; get rid of the x and y values\n\n??contget:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\teax,eax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\tsti\t\t\t\t; enable interrupts\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tcall\tnear ptr Convert_Num_To_ASCII\n\t\t\t\t\t; AX has ASCII code with bits\n\n\txor\tah,ah\t\t\t; clear key bits\n??exit:\n\tpopf\nendif; NOT_FOR_WIN95\n\tret\n\tENDP\tCheck_Key\n\n\n;***************************************************************************\n;* GET_KEY -- Gets the next available ASCII keystroke.\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      AH - hold the key bits                                     *\n;*\t\tAL - holds the ASCII key value\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tINT Get_Key(VOID);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key C NEAR\n\tUSES \tebx,ecx,edi\n\nifdef NOT_FOR_WIN95\n\tcld\t\t\t\t; clear the direction flag for speed\n\n\t; Check_Key had to be copied because of enable and disable of ints\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\t\t\t\t\t; AX has key num code with bits\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\txor\tah,ah\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tGet_Key\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_ON -- Sets the specified keyflags on                *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned on                 *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are on                       *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_On(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_On C NEAR\n\tUSES\tesi,edi\n\tARG\tbits:DWORD\n\nifdef NOT_FOR_WIN95\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tor\t[(KeyboardType PTR esi).KeyFlags],eax\n\n\t; Only do this if in playback or record mode.\n\ttest\teax,PASSBREAKS\n\tje\tshort ??fini\n\n\txor\teax,eax\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).KeysUpDown\n\tmov\t[edi],eax\n\tmov\t[edi+4],eax\n\tmov\t[edi+8],eax\n\tmov\t[edi+12],eax\n??fini:\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\nendif; NOT_FOR_WIN95\n\tret\n\tENDP\tKeyboard_Attributes_On\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_OFF -- Sets the specified keyflags off              *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned off                *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are off                      *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_Off(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_Off C NEAR\n\tUSES\tesi\n\tARG\tbits:DWORD\n\nifdef NOT_FOR_WIN95\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tnot\teax\n\tand\t[(KeyboardType PTR esi).KeyFlags],eax\n\txor\teax,eax\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tKeyboard_Attributes_Off\n;***************************************************************************\n;* CLEAR_KEYBUFFER -- Clears keystrokes out of the key buffer              *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Clear_KeyBuffer(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tClear_KeyBuffer C NEAR\n\tUSES\teax,esi\nifdef NOT_FOR_WIN95\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tcli\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\tsti\n\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tClear_KeyBuffer\n\n;***************************************************************************\n;* KEY_DOWN -- tests the status of a keyboard key                          *\n;*                                                                         *\n;* INPUT:\tINT the key num to check                                   *\n;*                                                                         *\n;* OUTPUT:      INT zero if the key is up, none zero if the key is down    *\n;*                                                                         *\n;* PROTO:\tINT Key_Down(INT key);\t\t\t\t   \t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Down C NEAR\n\tUSES\tebx,ecx,edi,esi\n\tARG\tkey:DWORD\n\nifdef NOT_FOR_WIN95\n\tpush\t[key]\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\txor\tah,ah\t\t\t\t; Always ignore the control bits.\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tedi,eax\n\tshr\tedi,3\n\tmov\tcl,al\n\tand\tcl,0111b\n\tmov\tal,01b\n\tshl\tal,cl\n\tand\tal,[(KeyboardType PTR esi+edi).KeysUpDown]\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tKey_Down\n\n;***************************************************************************\n;* CHECK_KEY_BITS -- checks ascii key in key buff with shift,ctrl,alt bits *\n;*                                                                         *\n;* INPUT:\tnone \t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set     *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Bits C NEAR\n\tUSES\tebx,ecx,edi,esi\n\nifdef NOT_FOR_WIN95\n\tpushf\t\t\t\t\t; save off the direction flag\n\tcld\t\t\t\t\t; we will go forward\n\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n??playback:\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\t;------ If there is a NULL in the keyboard buffer, we must NOT treat it\n\t;\tas a valid ASCII value because the calling code will falsely\n\t;\tassume that the NULL return value indicates an empty buffer.\n\tor\tal,al\n\tje\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\tax,ax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\n??exit:\n\tpopf\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tCheck_Key_Bits\n;***************************************************************************\n;* GET_KEY_BITS -- Gets ascii key in key buff with shift,ctrl,alt bits     *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set\t   *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Bits C NEAR\n\tUSES\tebx,ecx,edi\n\nifdef NOT_FOR_WIN95\n\tcld\n\n\t; Check_Key_Bits was copied because of enable and disable of interrupts\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\tret\n\nendif; NOT_FOR_WIN95\n\tENDP\tGet_Key_Bits\n\n;***************************************************************************\n;* KEY_SATISFIED -- checks to see if the given key is satisfied            *\n;*                                                                         *\n;* INPUT:   INT the key flags/number to check                          \t   *\n;*                                                                         *\n;* OUTPUT:  INT 0 if the key is not satisfied, !0 if the key is satisfied  *\n;*                                                                         *\n;* PROTO:   VOID Key_Satisfied(INT key);                                    *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Satisfied C NEAR\n\tUSES\tebx,ecx,esi,edi\n\tARG\tkey:DWORD\n\nifdef NOT_FOR_WIN95\n\tmov\teax,[key]\n\tmov\tebx,eax\t\t\t; save key code\n\tpush\teax\n\tcall\tKey_Down\t\t; see it its even down\n\tadd\tesp,4\n\tcmp\teax,0\n\tje\t??out\t\t\t; if not it can't be satisfied\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,ebx\t\t\t; if so, restore code\n\txor\tah,ah\t\t\t; clear out flags area\n\tmov\tedi,eax\t\t\t; set as an index\n\tshr\tedi,3\t\t\t; div by 8 for bytes\n\tmov\tch,1h\t\t\t; set a bit for mask\n\tmov\tcl,al\t\t\t; get the code number\n\tand\tcl,7\t\t\t; get the actual bit this code is\n\tshl\tch,cl\t\t\t; move bit into mask position\n\n; now test the ctrl,alt and shift bits\n\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],04h\t; is the left ctrl down?\n\tjne \tshort ??ctrlon\t\t; if so, ctrl is on\n\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],01h\t; is the right ctrl down?\n\tje \tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n??ctrlon:\n\tor\tah,02h\t\t\t; or on the ctrl bit in flags\n??ctrloff:\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],50h\t; is either alt key down?\n\tje \tshort ??altoff\n\tor\tah,04h\t\t\t; or on the alt bit in flags\n??altoff:\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],10h\t; is the left shift down?\n\tjne \tshort ??shifton\t\t; if so the sift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],02h\t; is the right shift down?\n\tje \tshort ??shiftoff\t\t; if not then neither shift is down\n??shifton:\n\tor\tah,01h\t\t\t; or on the shift bit in flags\n??shiftoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje \tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje \tshort ??capsoff\t\t; its not effected\n\txor\tah,1h\t\t\t; toggle the shift flag\n??capsoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t\t; is the num lock key on?\n\tje \tshort ??numlockoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje \tshort ??numlockoff\t\t; if not effected skip toggle\n\txor\tah,1h\t\t\t; toggle the shift flag if effected\n\n??numlockoff:\n\tmov\tal,0ffh\t\t\t; set to match by default\n\tcmp\tah,bh\t\t\t; if flags match return !0\n\tje \tshort ??out\t\t\t; just exit\n\txor\teax,eax\t\t\t; otherwise, clear all bits FALSE\n\n??out:\n\tor\teax,eax\nendif ;NOT_FOR_WIN95\n\tret\n\n\tENDP\tKey_Satisfied\n\n\n;***************************************************************************\n;* Interrupt routines start here - Interrupts must be within the Locked\n;*   code area for DPMI compatability.\n;***************************************************************************\n\n\n\n\nLABEL \tLockedCodeStart\tBYTE\nifdef cuts\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Performs a lowlevel xlate to a keycode              *\n;*                                                                         *\n;* INPUT:\tWORD the code that needs to be translated                  *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated code                                   *\n;*                                                                         *\n;* PROTO:\tINT KeyNum_Translate(INT keynum);                          *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyNum_Translate C NEAR\n\tUSES \tebx,ecx,esi,edi\n\tARG\tkeycode:DWORD\n\n;*===================================================================\n;* ES points to the DOSMEM selector, esi is the offset of the\n;*   protected mode structure.\n;*===================================================================\n\nifdef NOT_FOR_WIN95\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\tmov\teax,[keycode]\n\ttest\t[(KeyboardType PTR esi).KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\n\tmov\tecx,OFFSET ((KeyboardType PTR 0).ExtRemap)- OFFSET((KeyboardType PTR 0).ExtNums)\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtNums\n\tadd\tedi,esi\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).ExtRemapEnd\n\tdec\tedi\n\tsub\tedi,ecx\n\tmov\tal,[edi]\n??fini:\nendif ;NOT_FOR_WIN95\n\tret\n\n\tENDP\tKeyNum_Translate\nendif\n\tifdef cuts\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(INT code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_WORD C NEAR\n\tUSES\tebx,esi,edi\n\tARG\tcode:WORD\n\nifdef NOT_FOR_WIN95\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\tedi,eax\n\tadd\teax,2\n\tand\teax,0FFh\t\t\t; New KeyBufferTail value.\n\tcmp\t[(KeyboardType PTR esi).KeyBufferHead],eax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[(KeyboardType PTR esi+edi).KeyBuffer],bx\t\t; Record the keystroke.\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\n\tret\n\n??noroom:\n\tmov\teax,1\nendif ;NOT_FOR_WIN95\n\tret\n\n\tENDP\tStuff_Key_WORD\nendif\nifdef cuts\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_Num C NEAR\n\tUSES\tebx,ecx,edx,edi,esi\n\tARG\tkeycode:DWORD\n\tLOCAL\ttail:DWORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n; for the moment we do not check for the interrupt flag\n;\tmov\teax,2534h \t\t; function to get the interrupt status\n;\tint\t21\t\t\t; eax = interrupt status\n;\tpush\teax\t\t\t; save the result on the stack\n\nifdef NOT_FOR_WIN95\n\tpushf\t\t\t\t; store off the flags\n\tcli\t\t\t\t; disable interrupts\n\n; We need to set the data segment because we might be being called\n; from within an interrupt\n; Soo, if that is the case then DS & ES point to DGROUP _DATA\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\teax,[(KeyboardType PTR esi).MouseX]\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\teax,[(KeyboardType PTR esi).MouseY]\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],ax\n\n??cando:\n\tmov\teax,[keycode]\t\t; get the code\n\tor\teax,eax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[(KeyboardType PTR esi).Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[(KeyboardType PTR esi).Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\txor\tebx,ebx\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tebx,1\t\t\t; double for WORD index\n\tmov\tax,[WORD PTR ((KeyboardType PTR esi+ebx).XYAdjust)]\n\n\tmovsx\tebx,ah\n\tmovsx\teax,al\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tedx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tedx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tebx,edx\t\t\t; add speed for y index\n\tmov\tbl,[(KeyboardType PTR esi+ebx).KeyMouseMove] \t; get speed for y delta\n\tmovsx\tebx,bl\n\txchg\tebx,edx\t\t\t; save mouse y delta\n\tadd\tebx,eax\t\t\t; add speed for x index\n\tmov\tal,[(KeyboardType PTR esi+ebx).KeyMouseMove]\t; get speed for x delta\n\tmovsx\teax,al\n\txchg\tebx,edx\t\t\t; restore mouse y delta\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tebx,011b\t\t\t; Y = 1, 0, 3\n\tand\teax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tebx,011b\t\t\t; Y = 3, 0, 1\n\tand\teax,011b\t\t\t; X = 3, 0, 1\n\tshl\tebx,2\n\tor\tebx,eax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tebx,1\n\tmovzx\tebx,[(KeyboardType PTR esi+ebx).EdgeConv]\n\tshl\tebx,2\n\tmov\tax,[(KeyboardType PTR esi+ebx).ScreenEdge]\t; New absolute X\n\tmov\tbx,[(KeyboardType PTR esi+ebx+2).ScreenEdge] ; New absolute Y\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\teax,eax\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tebx,ebx\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseX],ax\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseY],bx\n\tcmp\t[(KeyboardType PTR esi).MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n; PWG: ARRGGGHHHH!\n;\tcall\tLow_Hide_Mouse\n;\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\teax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],eax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tedi,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\t[tail],edi\t\t; Safety record.\n\n\t; Record the base keycode (if there is room).\n\tcwde\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\teax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tmovzx\teax,[(KeyboardType esi).LocalMouseX]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tmovzx\teax,[(KeyboardType esi).LocalMouseY]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tebx,0101h\t\t; Bit control tools.\n\tmov\teax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[(KeyboardType PTR esi).KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[(KeyboardType esi).KeyBufferTail],edi\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tmov\tcl,3\n\tshr\tedi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[(KeyboardType esi+edi).KeysUpDown]\n\tje\tshort ??notalready\n\ttest\t[(KeyboardType PTR esi).KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\tedx,[tail]\n\tmov\t[(KeyboardType esi).KeyBufferTail],edx\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[(KeyboardType esi+edi).KeysUpDown],bh\t; Force key bit to zero.\n\tor\t[(KeyboardType esi+edi).KeysUpDown],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\teax,1\n\tjmp\tshort ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\teax,[tail]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\t\t\t; Signal an error.\n\n??exit:\n\tsti\n\tpopf\n\n;\tpopf\n;\tpop\tebx\n;\tor\tebx,ebx\n;\tjz\t??final_exit\n;\tsti\n\n??final_exit:\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tStuff_Key_Num\nendif\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles break interrupt for protected mode           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBreak_Interrupt C NEAR\n\n\tiret\n\tENDP\tBreak_Interrupt\n\nIF DEBUG\n;***************************************************************************\n;* DEBUG_INTERRUPT -- Handles debug (INT 3) interrupt for protected mode   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tDebug_Interrupt C NEAR\n\n\t;*==================================================================\n\t;* Setup fake Interrupt entry sequence so that we can execute our\n\t;*   code and then IRET painlessly into the debuggers interrupt\n\t;*   handler.\n\t;*==================================================================\nifdef NOT_FOR_WIN95\n\tpushfd\t\t\t; Step 1\n\tsub\tesp,8\t\t; Step 2\n\tpush\tebp\t\t; Step 3\n\tmov\tebp,esp\t\t; Set up a stack frame to know where to poke address.\n\n\t;*==================================================================\n\t;* Preserve all of the registers that we intend to use.\n\t;*=======================================Dbg========================\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n\tmov\tax , _DATA\n\tmov\tds , ax\n\tmov\tes , ax\n\tinc\t[BYTE PTR 0B0000h]\n\n\t;*==================================================================\n\t;* Setup the pointers to the real mode data and the protected mode\n\t;*   data and selectors.\n\t;*==================================================================\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t;*==================================================================\n\t;* Do the deed.\n\t;*==================================================================\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\n\t;*==================================================================\n\t;* Now get the address of the real debug handler and poke it into\n\t;*   the stack so we can IRET to it.\n\t;*==================================================================\n\tmov\teax,[(KeyboardType PTR esi).DbgOldPMIOffset]\t; Get orig offset.\n\tmov\tebx,[(KeyboardType PTR esi).DbgOldPMISelector]\t; Get orig selector.\n\tmov\t[ss:ebp+4],eax\t\t\t\t\t; Poke offset.\n\tmov\t[ss:ebp+8],ebx\t\t\t\t\t; Poke selector.\n\n\t;*==================================================================\n\t;* Restore the stack so it looks like we just did an IRET entry\n\t;*==================================================================\n\tpop\tfs gs es ds\n\tpopad\n\tpop\tebp\n\n\t;*==================================================================\n\t;* This iret should go directly to the real debugger handler\n\t;*\tpainlessly and effectively.\n\t;*==================================================================\nendif; NOT_FOR_WIN95\n\tiretd\n\n\tENDP\tDebug_Interrupt\nENDIF\n\n\n\nIF PROT_INT_ENABLE\n\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Handles input that comes from the keyboard        *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Interrupt C NEAR\n\n\t; This routine will do what it needs to,\n\t; then it will decide if the old vector should be called.\n\t; if so, it calls it and never returns to this function.\n\t; if not, we do our own return.\n\t; the method for doing this is found in:\n\t; \"Phar Lap  TNT DOS-Extender Reference Manual, First Addition, p. 142\"\n\t; It says:\n\t; 1 - Execute a PUSHFD to save the current flags.\n\t; 2 - Dec the stack ptr by 8 bytes to save room for the addr of orig handler\n\t; 3 - Push register I use.\n\t; 4 - Do any processing.\n\t; 5 - Put the address of the original handler in the reserved slot.\n\t; 6 - Pop saved register values\n\t; 7 - Execute an IRETD to transfer control to original handler.\nifdef NOT_FOR_WIN95\n\tpushfd\t\t\t; Step 1\n\tsub\tesp,8\t\t; Step 2\n\tpush\tebp\t\t; Step 3\n\tmov\tebp,esp\t\t; Set up a stack frame to know where to poke address.\n\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n; this is the part of the interrupt that set the segment registers\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tedx,[(KeyboardType PTR esi).KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\n\tand\t[(KeyboardType PTR esi).KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\ttest\t[BYTE PTR 417H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR 417H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR 496H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tebx,0101H\t\t; set key to a make by default\n\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\t;\n\t; New CODE to montior key stream\n\t;\n\txor\tebx,ebx\n\tmov\tbx,[(KeyboardType PTR esi).KeyStreamIndex]\n\tmov\t[(KeyboardType PTR esi+ebx).KeyStream],al\n\tinc\tebx\n\tand\tebx,15\n\tmov\t[(KeyboardType PTR esi).KeyStreamIndex],bx\n\tmov\tebx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[(KeyboardType PTR esi).LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[(KeyboardType PTR esi).LastKeyE1]\t\t; yes, dec the count\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[(KeyboardType PTR esi).IsExtKey],TRUE\t; it is an extended key\n\n\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtCodes\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).ExtNums-OFFSET (KeyboardType PTR 0).ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\n\tmov\tal,[(OFFSET (KeyboardType PTR 0).ExtNums - OFFSET (KeyboardType PTR 0).ExtCodes) - 1 + edi] ; get the match\n\tmov\t[(KeyboardType PTR esi).IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tedi,eax\t\t\t; use code as an index\n\tand\tedi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[(KeyboardType PTR esi+edi).KeyNums]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[(KeyboardType PTR esi).ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\teax\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\n;------\tSet the shift bit if necessary.\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tshr\tedi,3\n\tmov\tebx,eax\n\tand\tebx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[(KeyboardType PTR esi+ebx).Bits]\t\t; get the bit to test\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[(KeyboardType PTR esi).CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\n\t\t\t\t\t; keyboard buffer.\n\n\tmov\tecx,eax\n\txor\teax,eax\n\tmov\tax,cx\n\nIF DEBUG\n\tcmp\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\n\tinc\t[BYTE PTR 0B0002h]\n\n\tcmp\teax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\teax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\teax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\n\tcmp\teax,125\n\tjne\t??not_toggle\n\n\tinc\t[BYTE PTR 0B0000h]\n\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjmp\t??absorbcode\nENDIF\n\n??not_toggle:\n\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\teax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\teax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\teax,0230h\n\tje\tshort ??breaker\n\tcmp\teax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[(KeyboardType PTR esi).Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n;\tcmp\tax,0420H\t\t; is this an alt s\n;\tjne\tshort ??checkmusic\t; toggle the Sound variable\n;\tpush\tax\n;\tmov\tax,[SoundOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??checkmusic:\n;\tcmp\tax,0434H\t\t; is this an alt m\n;\tjne\tshort ??esc\t\t; toggle the Music variable\n;\tpush\tax\n;\tmov\tax,[MusicOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??esc:\n\n\tpush\teax\n\tcall\tStuff_Key_Num\n\tpop\teax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[(KeyboardType PTR esi).EscRoutine],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\teax\n\tcall\t[(KeyboardType PTR esi).EscRoutine]\n\tpop\teax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tedi,OFFSET (KeyboardType PTR 0).PassAlways\t; get offset to table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd - OFFSET (KeyboardType PTR 0).PassAlways) ; get number of pass always CDY JLB MOD 7/11 was\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tedi,OFFSET (KeyboardType PTR 0).CondPassKey\t; get offset to cond key table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).CondPassCond-OFFSET (KeyboardType PTR 0).CondPassKey) ; get number of entries\n\tshr\tecx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(OFFSET (KeyboardType PTR 0).CondPassCond - OFFSET (KeyboardType PTR 0).CondPassKey) - 2 + edi]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tedx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\tinc\t[(KeyboardType PTR esi).PassCount]\n\n\t; Step 5.\n\t; Now it is time to set up for the call by returning by poking\n\t; the old interupt handle address in.\n\tmov\t[(KeyboardType PTR esi).PMIssuedKeyInt],1\t\t; Make it TRUE\n\tmov\teax,[(KeyboardType PTR esi).KeyOldPMIOffset]\t; Get orig offset.\n\tmov\tebx,[(KeyboardType PTR esi).KeyOldPMISelector]\t; Get orig selector.\n\tmov\t[ss:ebp+4],eax\t\t\t\t\t; Poke offset.\n\tmov\t[ss:ebp+8],ebx\t\t\t\t\t; Poke selector.\n\n\t; Step 6.\n\tpop\tfs gs es ds\n\tpopad\n\tpop\tebp\n\n\t; Step 7.\n\tiretd\n\n??absorbcode:\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tal,[496h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[496h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\n\tpop\tfs gs es ds\n\tpopad\n\n\tpop\tebp\n\tadd\tesp,8\n\tpopfd\nendif;ifdef NOT_FOR_WIN95\n\tiret\n\n\tENDP\tKeyboard_Interrupt\n\nELSE\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Stub for the keyboard interrupt call real mode    *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\n\nDATASEG\nSTRUC\tRealModeCallStruc\n\t_EDI  DD\t0\n\t_ESI  DD\t0\n\t_EBP  DD\t0\n\t      DD        0\n\t_EBX  DD\t0\n\t_EDX  DD\t0\n\t_ECX  DD\t0\n\t_EAX  DD        0\n\tFLAGS DW\t0\n\t_ES   DW\t0\n\t_DS   DW\t0\n\t_FS   DW\t0\n\t_GS   DW\t0\n\t_IP   DW\t0\n\t_CS   DW\t0\n\t_SP   DW\t0\n\t_SS   DW\t0\n\t      dd\t0\n\t      dd\t0\n  nothing     dd\t0\nENDS\n\nRMDS RealModeCallStruc  <>\n\nCODESEG\n\nPROC\tKeyboard_Interrupt\tNear\n\n; This option of the keyboard interrupt handle will not be\n; available at this moment because the light version of Rational System DOS\n; Extender do not allow a DPMI real mode call which is\n; DMPI INT 31h funtion 0301h\n\nifdef NOT_FOR_WIN95\n\tpushad\n\tpush\tfs gs es ds\n\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\n\tlea\tedi , [ RMDS ]\n\tlea\tecx , [ RMDS . nothing ]\n\tsub\tecx , edi\n\txor\teax , eax\n\tshr\tecx , 2\n\trep\tstosd\n\n\tmov\teax , 0300h\n\tmov\tbl , [ byte ptr RMVector ]\n\txor\tbh , bh\n\txor\tcx , cx\n\tlea\tedi , [RMDS]\n\tint\tDPMI_INTR\n\n; this is here only for testing to make sure\n; that a real mode interrupt is bieng issued.\nmov\tax , _DATA\nmov\tes , ax\nmov\tds , ax\nmov [ byte ptr 0b0000h + 10 * 80 + 40 ] , 040h\njc\t??error\nmov [ byte ptr 0b0000h + 10 * 80 + 42 ] , 041h\n\n??error:\n\tpop\tds es gs fs\n\tpopad\nendif;ifdef NOT_FOR_WIN95\n\tiretd\n\tENDP\n\nENDIF\n\nLABEL \tLockedCodeEnd\t\tBYTE\n\n;***************************************************************************\n;* End of File.\t\t\t\t\t\t\t\t   *\n;***************************************************************************\nEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/KEYBOARD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Keyboard Library                                    *\n *                                                                                             *\n *                    File Name : KEYBOARD.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 10/16/95                                                     *\n *                                                                                             *\n *                  Last Update : October 26, 1995   []                    *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                         *\n *   WWKeyboardClass::Get -- Logic to get a metakey from the buffer                            *\n *   WWKeyboardClass::Check -- Checks to see if a key is in the buffer                         *\n *   WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer    *\n *   WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer               *\n *   WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels           *\n *   WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels           *\n *   WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars       *\n *   Check_Key -- compatability routine for old 32 bit library             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"keyboard.h\"\n#include \"timer.h\"\n#include \"mono.h\"\n\nvoid Message_Loop(void);\n\nWWKeyboardClass *_Kbd;\n\n/***********************************************************************************************\n * WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class                *\n *                                                                                             *\n * INPUT:\t\tnone\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * OUTPUT:     none\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nWWKeyboardClass::WWKeyboardClass(void)\n{\n\t_Kbd = this;\n\t//\n\t// Initialize the keyboard remap table for our system (note it would be bad if someone\n\t// switched keyboard modes after this happened.\n\t//\n\tmemset(VKRemap, 0, 256);\n\tmemset(AsciiRemap, 0, 2048);\n\tfor (short lp = 31; lp < 255; lp ++) {\n\t\tif (isprint(lp)) {\n\t\t\tint vk_key = VkKeyScan((unsigned char)lp);\n\t\t\tif (vk_key > 0 && vk_key < 2048) {\n\t\t\t\tAsciiRemap[vk_key] = (unsigned char)lp;\n\t\t\t\tVKRemap[lp] \t = (unsigned char)(vk_key & 0xFF);\n\t\t\t}\n\t\t}\n\t}\n\n\t//\n\t// Build a remap table of the different keys which are affected by the caps lock and\n\t// the num lock.\n\t//\n\tmemset(ToggleKeys, 0, 256);\n\tfor (lp = 0; lp < 255; lp++ ) {\n\t\tif (isalpha(lp) && isupper(lp)) {\n\t\t\tToggleKeys[lp] = 1;\n\t\t}\n\t\tif (lp >= VK_NUMPAD0 && lp <= VK_DIVIDE) {\n\t\t\tToggleKeys[lp] = 2;\n\t\t}\n\t}\n\n\t//\n\t// Our buffer should start devoid of keys.\n\t//\n\tmemset(Buffer, 0, 256);\n\tHead\t\t\t\t= 0;\n\tTail\t\t\t\t= 0;\n\n\t//\n\t// There should be no starting queued mouse events for us to have to worry\n\t// about.\n\t//\n\tMouseQX\t\t\t= 0;\n\tMouseQY\t\t\t= 0;\n\tMState\t\t\t= 0;\n\tConditional\t\t= 0;\n\tCurrentCursor\t= NULL;\n}\n\n/***********************************************************************************************\n * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer                 *\n *                                                                                             *\n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     int\t\t- the key value that was pulled from buffer (includes bits)\t\t\t\t  *                                                                                *\n *                                                                                             *\n * WARNINGS:   If the key was a mouse event MouseQX and MouseQY will be updated                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nint WWKeyboardClass::Buff_Get(void)\n{\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t\t\t// wait for key in buffer\n\tint \ttemp\t\t= Buffer[Head];\t\t\t\t\t\t// get key out of the buffer\n\tint   newhead\t= Head;\t\t\t\t\t\t\t\t\t// save off head for manipulation\n\tif (Is_Mouse_Key(temp)) {\t\t\t\t\t\t\t\t// if key is a mouse then\n\t\tMouseQX\t= Buffer[(Head + 1) & 255];\t\t\t//\t\tget the x and y pos\n\t\tMouseQY\t= Buffer[(Head + 2) & 255];\t\t\t//\t\tfrom the buffer\n\t\tnewhead += 3;\t\t  \t\t\t\t\t\t\t\t\t//\t\tadjust head forward\n\t} else {\n\t\tnewhead += 1;\t\t  \t\t\t\t\t\t\t\t\t//\t\tadjust head forward\n\t}\n\tnewhead\t&= 255;\n\tHead\t\t = newhead;\n\treturn(temp);\n}\n\nBOOL WWKeyboardClass::Is_Mouse_Key(int key)\n{\n\tkey &= 0xFF;\n\treturn (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Check -- Checks to see if a key is in the buffer                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nBOOL WWKeyboardClass::Check(void)\n{\n\tMessage_Loop();\n\tunsigned short temp;\t\t\t\t\t\t\t\t\t\t\t// store temp holding spot for key\n\tif (Head == Tail) return(FALSE);\t\t\t\t\t\t\t// if no keys in buff then get out\n\ttemp = Buffer[Head];\t\t\t\t\t\t\t\t\t\t\t// get key out of the buffer\n\treturn(temp);\t\t\t\t\t\t\t\t\t\t\t\t\t// send it back to main program\n}\n\n/***********************************************************************************************\n * WWKeyboardClass::Get -- Logic to get a metakey from the buffer                              *\n *                                                                                             *\n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     int\t\t- the meta key taken from the buffer.\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:\tThis routine will not return until a keypress is received\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nint WWKeyboardClass::Get(void)\n{\n\tint temp,bits;\t\t\t\t\t\t\t\t\t\t// store temp holding spot for key\n\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t// wait for key in buffer\n\ttemp = Buff_Get();\t\t\t\t\t\t\t\t// get key from the buffer\n\n\tbits = temp & 0xFF00;\t\t\t\t\t\t\t// save of keyboard bits\n\n\tif (!(bits & WWKEY_VK_BIT)) {\t\t\t\t\t// if its not a virtual key\n\t\ttemp = AsciiRemap[temp&0x1FF] | bits;\t//   convert to ascii equivalent\n\t}\n\treturn(temp);\t\t\t\t\t\t\t// return the key that we pulled out\n}\n\n/***********************************************************************************************\n * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                           *\n *                                                                                             *\n * INPUT:\t\tint\t \t- the key to insert into the buffer          \t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     bool\t\t- true if key is sucessfuly inserted.\t\t\t\t\t\t\t              *\n *                                                                                             *\n * WARNINGS:   none\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nBOOL WWKeyboardClass::Put(int key)\n{\n\tint\ttemp\t\t= (Tail + 1) & 255;\n\tif (temp != Head)\n\t{\n\t\tBuffer[Tail]\t= (short)key;\n\n\t\t//\n\t\t// Critical Line\n\t\t//\n\t\tTail\t\t\t\t= temp;\n\t\treturn(TRUE);\n\t}\n\treturn(FALSE);\n}\n/***********************************************************************************************\n * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nWWKeyboardClass::Put_Key_Message(UINT vk_key, BOOL release, BOOL dbl)\n{\n\tint bits = 0;\n\t//\n\t// Get the status of all of the different keyboard modifiers.  Note, only pay attention\n\t// to numlock and caps lock if we are dealing with a key that is affected by them.  Note\n\t// that we do not want to set the shift, ctrl and alt bits for Mouse keypresses as this\n\t// would be incompatible with the dos version.\n\t//\n\tif (vk_key != VK_LBUTTON && vk_key != VK_MBUTTON && vk_key != VK_RBUTTON) \t{\n\t\tint\tshift\t\t= (GetKeyState(VK_SHIFT) & 0xFF00) \t\t!= 0;\n\t\tint\tctrl \t\t= (GetKeyState(VK_CONTROL) & 0xFF00) \t!= 0;\n\t\tint\talt \t\t= (GetKeyState(VK_MENU) & 0xFF00) \t\t!= 0;\n\t\tint\tcaps\t\t= ((GetKeyState(VK_CAPITAL) & 0x00FF) \t!= 0) && (ToggleKeys[vk_key] == 1);\n\t\tint\tnums\t\t= ((GetKeyState(VK_NUMLOCK) & 0x00FF) \t!= 0) && (ToggleKeys[vk_key] == 2);\n\n\t\t//\n\t\t// Set the proper bits for whatever the key we got is.\n\t\t//\n\t\tif (shift || caps || nums) {\n\t\t\tbits |= WWKEY_SHIFT_BIT;\n\t\t}\n\t\tif (ctrl) {\n\t\t\tbits |= WWKEY_CTRL_BIT;\n\t\t}\n\t\tif (alt) {\n\t\t\tbits |= WWKEY_ALT_BIT;\n\t\t}\n\t\t}\n\tif (!AsciiRemap[vk_key|bits]) {\n\t\tbits |= WWKEY_VK_BIT;\n\t}\n\tif (release) {\n\t\tbits |= WWKEY_RLS_BIT;\n\t}\n\tif (dbl) {\n\t\tbits |= WWKEY_DBL_BIT;\n\t}\n\t//\n\t// Finally use the put command to enter the key into the keyboard\n\t// system.\n\t//\n\treturn(Put(vk_key|bits));\n}\n\nvoid WWKeyboardClass::Clear(void)\n{\n\tHead = Tail;\n}\n\nint WWKeyboardClass::To_ASCII(int key)\n{\n\tif ( key && WWKEY_RLS_BIT)\n\t  return(KN_NONE);\n\treturn(key);\n}\n\nWWKeyboardClass::Down(int key)\n{\n\treturn(GetAsyncKeyState(key&0xFF));\n}\n\nVOID WWKeyboardClass::Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl)\n{\n\tshift = (key & WWKEY_SHIFT_BIT)\t!= 0;\n\tctrl\t= (key & WWKEY_CTRL_BIT)\t!= 0;\n\talt\t= (key & WWKEY_ALT_BIT)\t\t!= 0;\n\trls\t= (key & WWKEY_RLS_BIT)\t\t!= 0;\n\tdbl\t= (key & WWKEY_DBL_BIT)\t\t!= 0;\n\tkey\t= (key & 0xFF);\n\n}\n\n\nextern \"C\" {\n\tvoid __cdecl Stop_Execution (void);\n}\n\n#pragma off(unreferenced)\nvoid WWKeyboardClass::Message_Handler(HWND , UINT message, UINT wParam, LONG lParam)\n{\n\tswitch (message) {\n\t\tcase WM_SYSKEYDOWN:\n\t\tcase WM_KEYDOWN:\n\t\t\tif ( wParam==VK_SCROLL ){\n\t\t\t\tStop_Execution();\n\t\t\t} else {\n\t\t\t\tPut_Key_Message(wParam);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WM_SYSKEYUP:\n\t\tcase WM_KEYUP:\n\t\t\tPut_Key_Message(wParam, TRUE);\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_LBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONUP:\n\t\t\tPut_Key_Message(VK_LBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_LBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_MBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONUP:\n\t\t\tPut_Key_Message(VK_MBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_MBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_RBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONUP:\n\t\t\tPut_Key_Message(VK_RBUTTON, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_RBUTTON, TRUE, TRUE);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\t\tcase WM_MOUSEMOVE:\n\t\t\tif (CurrentCursor)\n\t\t\t\tSetCursor(CurrentCursor);\n\t\t\tbreak;\n\t}\n}\n#pragma on(unreferenced)\n\n\n\n\nvoid Message_Loop(void)\n{\n\n\tMSG\tmsg;\n\n\twhile (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE )) {\n\t  \tif( !GetMessage( &msg, NULL, 0, 0 ) ){\n\t\t\treturn;\n\t\t}\n\t\tTranslateMessage(&msg);\n\t\tDispatchMessage(&msg);\n\t}\n\n\n\n\n}\n\n\n\n/***************************************************************************\n * CHECK_KEY -- compatability routine for old 32 bit library               *\n *                                                                         *\n * This routine checks to see if there is a key in the keyboard buffer     *\n * and returns it to the sender if there is.  It does not remove the key\t*\n * from the buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     The key that was pressed.                                   *\n *                                                                         *\n * WARNINGS:   You must declare a WWKeyboardClass object before calling    *\n *\t\t\t\t\tthis routine.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/26/1995     : Created.                                             *\n *=========================================================================*/\nint Check_Key(void)\n{\n\tif (!_Kbd) return(KA_NONE);\n\treturn(_Kbd->Check() & ~WWKEY_SHIFT_BIT);\n}\n\nvoid Clear_KeyBuffer(void)\n{\n\tif (!_Kbd) return;\n\t_Kbd->Clear();\n}\n\nint Check_Key_Num(void)\n{\n\tif (!_Kbd) return(KN_NONE);\n\tint key\t\t= _Kbd->Check();\n\tint flags\t= key & 0xFF00;\n\tkey\t\t   = key & 0x00FF;\n\n\tif (isupper(key)) {\n\t\tkey = tolower(key);\n\t\tif ( !flags & WWKEY_VK_BIT ) {\n\t\t\tflags |= WWKEY_SHIFT_BIT;\n\t\t}\n\t}\n\n\treturn(key | flags);\n}\n\nint Get_Key_Num(void)\n{\n\tif (!_Kbd) return(KN_NONE);\n\tint key\t\t= _Kbd->Get();\n\tint flags\t= key & 0xFF00;\n\tkey\t\t   = key & 0x00FF;\n\n\tif (isupper(key)) {\n\t\tkey = tolower(key);\n\t\tif ( !flags & WWKEY_VK_BIT ) {\n\t\t\tflags |= WWKEY_SHIFT_BIT;\n\t\t}\n\t}\n\treturn(key | flags);\n}\n\nint KN_To_KA(int key)\n{\n\tif ( key & WWKEY_RLS_BIT) {\n\t\treturn(KA_NONE);\n\t}\n\tif (!(key & WWKEY_VK_BIT)) {\n\t\tint flags = key & 0xFF00;\n\t\tkey\t\t = key & 0x00FF;\n\t\tif (flags & WWKEY_SHIFT_BIT) {\n\t\t\tkey\t\t= toupper(key);\n\t\t\tflags\t  &= ~WWKEY_SHIFT_BIT;\n\t\t}\n\t}else{\n\t\t/*\n\t\t** If its a numeric keypad key then fix it up\n\t\t*/\n\t\tif ((key & 0xff) >=VK_NUMPAD0 && (key & 0xff) <=VK_NUMPAD9){\n\t\t\tkey = (key & 0xff) - VK_NUMPAD0 + KA_0;\n\t\t}\n\t}\n\treturn(key);\n}\n\nint KN_To_VK(int key)\n{\n\tif (!_Kbd) return(KN_NONE);\n\tif ( key & WWKEY_RLS_BIT) {\n\t\treturn(VK_NONE);\n\t}\n\n\tint flags = key & 0xFF00;\n\tif (!(flags & WWKEY_VK_BIT)) {\n\t\tkey \t\t = _Kbd->VKRemap[key & 0x00FF] | flags;\n\t}\n\tkey &= ~WWKEY_VK_BIT;\n\treturn(key);\n}\n\nint Key_Down(int key)\n{\n\tif (!_Kbd) return(FALSE);\n\treturn(_Kbd->Down(key));\n}\n\nint Get_Key(void)\n{\n\tint retval;\n\n\tif (!_Kbd) return(KN_NONE);\n\tretval = _Kbd->Get() & ~WWKEY_SHIFT_BIT;\n\tif (retval & WWKEY_RLS_BIT) {\n\t\tretval = KN_NONE;\n\t}\n\treturn(retval);\n}\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/KEYIPROT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : KEYINTR.ASM                              *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   KeyNum_Translate -- Translates the given keynum to ???                *\n;*   Install_Interrupt -- Installs the keyboard interrupt                  *\n;*   Stuff_Key_Word -- Stuffs a word of data into keyboard buffer          *\n;*   Stuff_Key_Num -- Stuffs a key num code into the circular buffer       *\n;*   Remove_Interrupt -- Removes the keyboard interrupt and restores the chai*\n;*   Keystroke_Interrupt -- Handles input that comes from the keyboard     *\n;*   Break_Interrupt -- Handles the break key interrupt                    *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tKeyboard driver -- 8086 Assembly portion;\t\t\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   *\n;***************************************************************************\n\n;---------------------------------------------------------------------------\n; Set the assembly directives\n;---------------------------------------------------------------------------\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386N\t\t\t\t; use 386 real mode instructions\nMODEL TINY\t\t\t; code must be tiny so it fits\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keyboard.inc\"\n\nCODESEG\n\n\nSoundOn\t\tDW\t1\t; toggled by alt S\nMusicOn\t\tDW\t1\t; toggled by alt M\nKeyFlags\tDW\tREPEATON+CTRLALTTURBO\t; all but repeat for now\n\n\nBreak\t\tDW\t0\n\nKeyMouseMove\tDB\t-1,0,1\n\t\tDB\t-16,0,16\n\nScreenEdge\tDW\t320/2,0\t\t; North\n\t\tDW\t319,0\t\t; North-East\n\t\tDW\t319,138/2\t; East\n\t\tDW\t319,137\t\t; South-East\n\t\tDW\t320/2,137\t; South\n\t\tDW\t0,137\t\t; South-West\n\t\tDW\t0,138/2\t\t; West\n\t\tDW\t0,0\t\t; North-West\n\t\tDW\t320/2,138/2\t; Center\n\n\nBits\t\tDB\t01H,02H,04H,08H,10H,20H,40H,80H\n\nCondPassKey\tDW\t0220H, 0320H, 060CH, 070DH, 066AH\n\t\tDW\t0669H, 0230H, 0330H, 007DH, 017DH\n\t\tDW\t025AH, 035AH, 0200H, 0410H, 046EH\n\t\tDW\t026EH, 007CH\n\nCondPassCond\tDW\tCTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO\n\t\tDW\tCTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON\n\t\tDW\tPAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE\n\t\tDW\tTASKSWITCHABLE, BREAKON\n\nEscRoutine\tDD\t0\t; vector to execute on esc key press (0=none)\n\n; Extended raw keycodes to be converted to Westwood keycodes.\nExtCodes\tDB\t038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H\n\t\tDB\t051H,04DH,035H,01CH,037H\n\t\tDB\t046H\n; The matching Westwood keycodes.\nExtNums\t\tDB\t62,  64,  75,  76,  79,  80,  81,  83,  84,  85\n\t\tDB\t86,  89,  95, 108, 124,  0\n; If extended mapping is disabled, then these codes really are...\nExtRemap\tDB\t60,  58,  99, 104,  92,  91,  93,  96,  98, 101\n\t\tDB\t103, 102, 55,  43, 124,  0\nExtRemapEnd\tDB\t0\n\nExtKeyboard\tDB\t0\t; flag for 101/102-key keyboard\n\n\nKeyBuffer\tDW\t128 DUP(0) ; set to empty\nKeyBufferHead\tDW\t0\t; set to first entry\nKeyBufferTail\tDW\t0\t; set to head for empty buffer\nKeyLock\t\tDW\t0\t; num and caps lock bits\nKeyNums\t\tDB\t127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016\n\t\tDB\t017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032\n\t\tDB\t033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049\n\t\tDB\t050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116\n\t\tDB\t117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093\n\t\tDB\t098,103,099,104,127,127,127,122,123\n\nKeysCapsLock\tDB\t0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0\nKeysNumLock\tDB\t0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0\nKeysUpDown\tDB\t16 DUP(0) ; set to all keys up\nKeyStream\tDB\t16 DUP(0) ; set to all keys up\nPassCount\tDW\t0\nKeyStreamIndex\tDW\t0\nLastKeyE0\tDB\t0\nLastKeyE1\tDB\t0\n\n;\n; Westwood key number values of keys to pass through\n;\n;\t\t\tCAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT,\n;\t\t\tRIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN\nPassAlways\tDB\t30, 44, 57, 58, 60, 62, 64, 90, 128, 128\nPassAlwaysEnd\tDB\t128\t\t; invalid code to END PassAlways\nCtrlFlags\tDB\t0\n\nBuffer\t\tDW\t?\nTime\t\tDW\t?\n\nADJUST\t= 1\t\t\t; do not modify DRD\n\nXYAdjust\tDB\t-ADJUST, -ADJUST\t; 91 -> upleft\n\t\tDB\t-ADJUST,  0\t\t; 92 -> left\n\t\tDB\t-ADJUST,  ADJUST\t; 93 -> downleft\n\t\tDB\t 0,  0\t\t\t; 94 illegal\n\t\tDB\t 0,  0\t\t\t; 95 illegal\n\t\tDB\t 0, -ADJUST\t\t; 96 -> up\n\t\tDB\t 0,  0\t\t\t; 97 illegal (center)\n\t\tDB\t 0,  ADJUST\t\t; 98 -> down\n\t\tDB\t 0,  0\t\t\t; 99 illegal\n\t\tDB\t 0,  0\t\t\t; 100 illegal\n\t\tDB\t ADJUST, -ADJUST\t; 101 -> upright\n\t\tDB\t ADJUST,  0\t\t; 102 -> right\n\t\tDB\t ADJUST,  ADJUST\t; 103 -> downright\nEdgeConv\tDW\t8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7\n\nMouseUpdate\t\tDW\t0\nMouseX\t\t\tDW\t0\nLocalMouseX\t\tDW\t0\nMouseY\t\t\tDW\t0\nLocalMouseY\t\tDW\t0\nButton\t\t\tDW\t0\nIsExtKey\t\tDB\t0\nExtIndex\t\tDW\t0\n\nOldRMI\t\t\tDD\t0\t; The origianl RM interrupt seg:off.\nOldPMIOffset\t\tDD\t0\t; The origianl PM interrupt offset\nOldPMISelector\t\tDD\t0\t; The original PM interrupt segment.\n\nCodeOffset\t\tDW\tRM_Keystroke_Interrupt\t; Offset of the code in the RM stuff.\nCallRMIntOffset\t\tDW\tCall_Interrupt_Chain\t\t; Offset of function to call DOS timer interrupt.\nCallRMIntAddr\t\tDD\t0\t; PM address of CallRealIntOffset for speed.\n\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Translates the given keynum to ???                  *\n;*                                                                         *\n;* INPUT:\tUWORD the keynum to translate\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated keynum                                 *\n;*                                                                         *\n;* PROTO:\tUWORD KeyNum_Translate(UWORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL C\tKeyNum_Translate:FAR\n\tPROC\tKeyNum_Translate C FAR\n\tUSES\tcx,di,es,ds\n\tARG\tkeycode:WORD\nifdef NOT_FOR_WIN95\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\tmov\tes,ax\t\t\t\t; set es up for scansb\n\n\tmov\tax,[keycode]\n\ttest\t[KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\tmov\tcx,ExtRemap-ExtNums\n\tmov\tdi,OFFSET ExtNums\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tdi,OFFSET ExtRemapEnd\n\tdec\tdi\n\tsub\tdi,cx\n\tmov\tal,[es:di]\n??fini:\nendif ;NOT_FOR_WIN95\n\tret\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(WORD code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_WORD:FAR\n\tPROC\tStuff_Key_WORD C FAR\n\tUSES\tsi,bx,ds\n\tARG\tcode:WORD\n\nifdef NOT_FOR_WIN95\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\tax,[KeyBufferTail]\n\tmov\tsi,ax\n\tadd\tax,2\n\tand\tax,0FFh\t\t\t\t; New KeyBufferTail value.\n\tcmp\t[KeyBufferHead],ax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[KeyBuffer+si],bx\t\t; Record the keystroke.\n\tmov\t[KeyBufferTail],ax\n\txor\tax,ax\n\tret\n\n??noroom:\n\tmov\tax,1\nendif ; NOT_FOR_WIN95\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(WORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_Num:FAR\n\tPROC\tStuff_Key_Num C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds\n\tARG\tkeycode:WORD\n\tLOCAL\ttail:WORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\nifdef NOT_FOR_WIN95\n\tpushf\n\tcli\t\t\t\t; disable interrupts\n\n\t; Abort key recognition if in record mode and unable\n\t; to output key due to simultaneous DOS operation.\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\tax,[MouseX]\n\tmov\t[LocalMouseX],ax\n\tmov\tax,[MouseY]\n\tmov\t[LocalMouseY],ax\n\n??cando:\n\tmov\tax,[keycode]\t\t; get the code\n\tor\tax,ax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tbx,1\t\t\t; double for WORD index\n\tadd\tbx,OFFSET XYAdjust\n\tmov\tax,[bx]\t\t\t; get x,y add value\n\n\tmov\tbl,ah\n\tcbw\n\txchg\tax,bx\n\tcbw\n\txchg\tax,bx\t\t\t; AX = mouse x delta, BX = mouse y delta\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tdx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tdx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tbx,dx\t\t\t; add speed for y index\n\tmov\tbl,[KeyMouseMove+bx] \t; get speed for y delta\n\txchg\tax,bx\t\t\t; swap with ax to extend sign\n\tcbw\n\txchg\tax,bx\n\txchg\tbx,dx\t\t\t; save mouse y delta\n\tadd\tbx,ax\t\t\t; add speed for x index\n\tmov\tal,[KeyMouseMove+bx]\t; get speed for x delta\n\tcbw\n\txchg\tbx,dx\t\t\t; restore mouse y delta\n\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tbx,011b\t\t\t; Y = 1, 0, 3\n\tand\tax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tbx,011b\t\t\t; Y = 3, 0, 1\n\tand\tax,011b\t\t\t; X = 3, 0, 1\n\tshl\tbx,1\n\tshl\tbx,1\n\tor\tbx,ax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tbx,1\n\tmov\tbx,[EdgeConv+bx]\n\tshl\tbx,1\n\tshl\tbx,1\n\tmov\tax,[ScreenEdge+bx]\t; New absolute X\n\tmov\tbx,[ScreenEdge+bx+2] ; New absolute Y\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\tax,ax\n\tmov\t[LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tbx,bx\n\tmov\t[LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\tmov\t[MouseX],ax\n\tmov\t[MouseY],bx\n\tcmp\t[MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n; PWG: ARRGGGHHHH!\n;\tcall\tLow_Hide_Mouse\n;\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\tax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],ax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tsi,[KeyBufferTail]\n\tmov\t[tail],si\t\t; Safety record.\n\tmov\tdi,[KeyBufferHead]\n\n\t; Record the base keycode (if there is room).\n\tpush\tax\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\tax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tpush\t[LocalMouseX]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tpush\t[LocalMouseY]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tbx,0101h\t\t; Bit control tools.\n\tmov\tax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tmov\tcl,3\n\tshr\tdi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[KeysUpDown+di]\n\tje\tshort ??notalready\n\ttest\t[KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\t[KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[KeysUpDown+di],bh\t; Force key bit to zero.\n\tor\t[KeysUpDown+di],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\tax,1\n\tjmp short ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\tax,[tail]\n\tmov\t[KeyBufferTail],ax\n\txor\tax,ax\t\t\t; Signal an error.\n\n??exit:\n\tpopf\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tStuff_Key_Num\n;***********************************************************\n\n\n\n;***************************************************************************\n;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard       *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Keystroke_Interrupt\n\tGLOBAL\tC Keystroke_Interrupt:FAR\n\tPROC\tKeystroke_Interrupt C FAR\n\nifdef NOT_FOR_WIN95\nIF 0\n\tpush\tax\n\tinc\tax\n\tpop\tax\n\tiret\n\nELSE\n\tpush\tax\n\tpush\tbx\n\tpush\tcx\n\tpush\tdi\n\tpush\tds\n\tpush\tdx\n\tpush\tes\n\tpush\tsi\n\tcld\n\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tds,ax\n\tmov\tdx,[KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\n\tand\t[KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\tmov\tax,040H\t\t\t; BIOS segment\n\tmov\tes,ax\t\t\t; put in es\n\ttest\t[BYTE PTR es:017H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR es:017H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR es:096H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tes,ax\n\n\tcld\t\t\t\t; clear direction flag for strings\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tbx,0101H\t\t; set key to a make by default\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\n\t;\n\t; New CODE to montior key stream\n\t;\n\tmov\tbx,[KeyStreamIndex]\n\tmov\t[KeyStream+bx],al\n\tinc\tbx\n\tand\tbx,15\n\tmov\t[KeyStreamIndex],bx\n\tmov\tbx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[LastKeyE1]\t\t; yes, dec the count\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[IsExtKey],TRUE\t; it is an extended key\n\tmov\tdi,OFFSET ExtCodes\t; get offset of extended codes table\n\tmov\tcx,(ExtNums-ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\tmov\tal,[(ExtNums - ExtCodes) - 1 + di] ; get the match\n\tmov\t[IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tdi,ax\t\t\t; use code as an index\n\tand\tdi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[KeyNums+di]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[KeysUpDown+8],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[KeysUpDown+7],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[KeysUpDown + 7],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\tax\n\tcall\tKeyNum_Translate\n\tadd\tsp,2\n\n;------\tSet the shift bit if necessary.\n\ttest\t[KeysUpDown+5],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[KeysUpDown+7],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tshr\tdi,1\n\tshr\tdi,1\n\tshr\tdi,1\n\tmov\tbx,ax\n\tand\tbx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[Bits+bx]\t\t; get the bit to test\n\ttest\t[KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[KeysCapsLock+di]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[KeysNumLock+di]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\n\t\t\t\t\t; keyboard buffer.\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\tax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\tax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\tax,0230h\n\tje\tshort ??breaker\n\tcmp\tax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n\tcmp\tax,0420H\t\t; is this an alt s\n\tjne\tshort ??checkmusic\t; toggle the Sound variable\n\tpush\tax\n\tmov\tax,[SoundOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??checkmusic:\n\tcmp\tax,0434H\t\t; is this an alt m\n\tjne\tshort ??esc\t\t; toggle the Music variable\n\tpush\tax\n\tmov\tax,[MusicOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??esc:\n\n\tpush\tax\n\tcall\tStuff_Key_Num\n\tpop\tax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\tax\n\tcall\t[EscRoutine]\n\tpop\tax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tdi,OFFSET PassAlways\t; get offset to table\n\tmov\tcx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1\n\trepne\tscasb\t\t\t; look for a match\n\tor\tcx,cx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n\n\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tdi,OFFSET CondPassKey\t; get offset to cond key table\n\tmov\tcx,(CondPassCond-CondPassKey) ; get number of entries\n\tshr\tcx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(CondPassCond - CondPassKey) - 2 + di]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tdx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n;***********************************************************\n\tpushf\n;\tpush\tdi\n;\tpush\tes\n\n\tmov\tax,0B000h\n\tmov\tes,ax\n\tinc\t[BYTE PTR es:0]\n\n;\tpop\tes\n;\tpop\tdi\n\tpopf\n;***********************************************************\n\n??passcode:\n\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tinc\t[cs:PassCount]\n\tjmp\t[cs:OldRMI]\n\n??absorbcode:\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tax,040h\t\t\t\t; BIOS paragraph is always @ 040h\n\tmov\tes,ax\t\t\t\t; put in es as BIOS paragraph\n\tmov\tal,[es:96h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[es:96h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tiret\nENDIF\nendif ;NOT_FOR_WIN95\n\n\tENDP\tKeystroke_Interrupt\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles the break key interrupt                      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Break_Interrupt:FAR\n\tPROC\tBreak_Interrupt C FAR\n\n\tiret\n\n\tENDP\tBreak_Interrupt\n\n;**************************************************************************\n;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nCall_Interrupt_Chain:\nifdef NOT_FOR_WIN95\nIF 0\n\tpushf\n\tpush\tax\n\tpush\tdi\n\tpush\tes\n\n\tmov\tax,0B000h\t\t; ES:DI = Mono RAM address.\n\tmov\tes,ax\n\n\tmov\tal,'A'\n\tmov\tah,2\n\tand\tdi,63\n\n\tstosw\n\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\tmov\tal,CLEARISR\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t; 8259 interrupt chip controller 0\n\n\n\tpop\tes\n\tpop\tdi\n\tpop\tax\n\tpopf\nENDIF\n\tpushf\n\tcall\tKeystroke_Interrupt ;[OldRMI]\nendif; NOT_FOR_WIN95\n\tretf\n\nSTACK\t   ; Don't really need this\n\n;***********************************************************\nEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/KEYIREAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*\t\t\t\t  (Mouse Routines)\n;*                                                                         *\n;*                    File Name : KEYIREAL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Philip W. Gorrow                         *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;* This file sort of breaks the standard of keeping all of the keyboard    *\n;* and mouse routines isolated.  This is done because the mouse and\t   *\n;* the keyboard share data, and the best way to do this is to put\t   *\n;* them in the same segment.  This should probably be split into several   *\n;* include files to help make the code clearer once it is finally put\t   *\n;* together.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   KeyNum_Translate -- Translates extended keynums to normal keynums\t   *\n;*   Stuff_Key_Word -- Stuffs a word of data into keyboard buffer          *\n;*   Stuff_Key_Num -- Stuffs a key num code into the circular buffer       *\n;*   Keystroke_Interrupt -- Real mode handler of input from the keyboard   *\n;*   Break_Interrupt -- Handles the break key interrupt                    *\n;*   Call_Interrupt_Chain -- Function PM calls to call RM interrupt chain  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tKeyboard driver -- 8086 Assembly portion;\t\t\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   *\n;***************************************************************************\n\n;---------------------------------------------------------------------------\n; Set the assembly directives\n;---------------------------------------------------------------------------\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386N\t\t\t\t; use 386 real mode instructions\nMODEL TINY\t\t\t; code must be tiny so it fits\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keyboard.inc\"\n\nCONDHIDE\t\tEQU\t08000H\t\t; bit for testing conditional region\nCONDHIDDEN\t\tEQU\t04000H\t\t; bit for testing conditional hidden\nRESTORE_VISIBLE_PAGE\tEQU\t0\nSTORE_VISIBLE_PAGE\tEQU\t1\n\n\nGLOBAL\tset_vesa_page \t:near\nGLOBAL\tset_vesa_window :near\nGLOBAL\tget_vesa_window :near\nGLOBAL\tnext_vesa_page\t:near\n\nECHOON\tequ 0\n;---------------------------------------------------------------------------\n; WARNING!!!!  All of the following code segment variables are shared by\n;   the protected mode interrupt.  Do not change these unless you make the\n;   proper changes to KEYSTRUC.INC.  If you do not know what you are doing,\n;   find someone who does!!!\n;---------------------------------------------------------------------------\nCODESEG\n\n;---------------------------------------------------------------------------\n; Begin definition of Keyboard specific variables\n;---------------------------------------------------------------------------\nSoundOn\t\tDW\t1\t; toggled by alt S\nMusicOn\t\tDW\t1\t; toggled by alt M\nKeyFlags\tDD\tREPEATON+CTRLALTTURBO\t; all but repeat for now\n\n\nBreak\t\tDW\t0\n\nKeyMouseMove\tDB\t-1,0,1\n\t\tDB\t-16,0,16\n\nScreenEdge\tDW\t320/2,0\t\t; North\n\t\tDW\t319,0\t\t; North-East\n\t\tDW\t319,138/2\t; East\n\t\tDW\t319,137\t\t; South-East\n\t\tDW\t320/2,137\t; South\n\t\tDW\t0,137\t\t; South-West\n\t\tDW\t0,138/2\t\t; West\n\t\tDW\t0,0\t\t; North-West\n\t\tDW\t320/2,138/2\t; Center\n\n\nBits\t\tDB\t01H,02H,04H,08H,10H,20H,40H,80H\n\nCondPassKey\tDW\t0220H, 0320H, 060CH, 070DH, 066AH\n\t\tDW\t0669H, 0230H, 0330H, 007DH, 017DH\n\t\tDW\t025AH, 035AH, 0200H, 0410H, 046EH\n\t\tDW\t026EH, 007CH\n\nCondPassCond\tDW\tCTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO\n\t\tDW\tCTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON\n\t\tDW\tPAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE\n\t\tDW\tTASKSWITCHABLE, BREAKON\n\nEscRoutine\tDD\t0\t; vector to execute on esc key press (0=none)\n\n; Extended raw keycodes to be converted to Westwood keycodes.\nExtCodes\tDB\t038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H\n\t\tDB\t051H,04DH,035H,01CH,037H\n\t\tDB\t046H\n; The matching Westwood keycodes.\nExtNums\t\tDB\t62,  64,  75,  76,  79,  80,  81,  83,  84,  85\n\t\tDB\t86,  89,  95, 108, 124,  0\n; If extended mapping is disabled, then these codes really are...\nExtRemap\tDB\t60,  58,  99, 104,  92,  91,  93,  96,  98, 101\n\t\tDB\t103, 102, 55,  43, 124,  0\nExtRemapEnd\tDB\t0\n\nExtKeyboard\tDB\t0\t; flag for 101/102-key keyboard\n\n\nKeyBuffer\tDW\t128 DUP(0) ; set to empty\nKeyBufferHead\tDD\t0\t; set to first entry\nKeyBufferTail\tDD\t0\t; set to head for empty buffer\nKeyLock\t\tDW\t0\t; num and caps lock bits\nKeyNums\t\tDB\t127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016\n\t\tDB\t017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032\n\t\tDB\t033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049\n\t\tDB\t050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116\n\t\tDB\t117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093\n\t\tDB\t098,103,099,104,127,127,127,122,123\n\nKeysCapsLock\tDB\t0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0\nKeysNumLock\tDB\t0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0\nKeysUpDown\tDB\t16 DUP(0) ; set to all keys up\nKeyStream\tDB\t16 DUP(0) ; set to all keys up\nPassCount\tDW\t0\nKeyStreamIndex\tDW\t0\nLastKeyE0\tDB\t0\nLastKeyE1\tDB\t0\n\n;\n; Westwood key number values of keys to pass through\n;\n;\t\t\tCAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT,\n;\t\t\tRIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN\nPassAlways\tDB\t30, 44, 57, 58, 60, 62, 64, 90, 128, 128\nPassAlwaysEnd\tDB\t128\t\t; invalid code to END PassAlways\nCtrlFlags\tDB\t0\n\nBuffer\t\tDW\t?\nTime\t\tDW\t?\n\nADJUST\t= 1\t\t\t; do not modify DRD\n\nXYAdjust\tDB\t-ADJUST, -ADJUST\t; 91 -> upleft\n\t\tDB\t-ADJUST,  0\t\t; 92 -> left\n\t\tDB\t-ADJUST,  ADJUST\t; 93 -> downleft\n\t\tDB\t 0,  0\t\t\t; 94 illegal\n\t\tDB\t 0,  0\t\t\t; 95 illegal\n\t\tDB\t 0, -ADJUST\t\t; 96 -> up\n\t\tDB\t 0,  0\t\t\t; 97 illegal (center)\n\t\tDB\t 0,  ADJUST\t\t; 98 -> down\n\t\tDB\t 0,  0\t\t\t; 99 illegal\n\t\tDB\t 0,  0\t\t\t; 100 illegal\n\t\tDB\t ADJUST, -ADJUST\t; 101 -> upright\n\t\tDB\t ADJUST,  0\t\t; 102 -> right\n\t\tDB\t ADJUST,  ADJUST\t; 103 -> downright\n\tEdgeConv\t\tDW\t8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7\n\tMouseUpdate\t\tDW\t0\n\tMouseX\t\t\tDW\t0,0\n\tLocalMouseX\t\tDW\t0\n\tMouseY\t\t\tDW\t0,0\n\tLocalMouseY\t\tDW\t0\n\tIsExtKey\t\tDB\t0\n\tExtIndex\t\tDW\t0\n\n\tKeyOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tKeyOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\n\tKeyOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tKeyCodeOffset\t\tDW\tRM_Keystroke_Interrupt\t; Offset of the code in the RM stuff.\n\tCallKeyRMIntOffset\tDW\tCall_Interrupt_Chain\t; Offset of function to call DOS timer interrupt.\n\tCallKeyRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedKeyInt\t\tDD\t0\n\n\tBrkOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tBrkOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\n\tBrkOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tBrkCodeOffset\t\tDW\tRM_Break_Interrupt\t; Offset of the code in the RM stuff.\n\tCallBrkRMIntOffset\tDW\t0\n\tCallBrkRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedBrkInt\t\tDD\t0\n\tKeyIntDisabled\t\tDD\t0\n\n\tDbgOldPMIOffset\t\tDD\t0\t; The origianl PM interrupt offset\n\tDbgOldPMISelector\tDD\t0\t; The original PM interrupt segment.\n\n;---------------------------------------------------------------------------\n; Begin definition of Mouse Specific Variables for real mode\n;---------------------------------------------------------------------------\nButton\t\t\tDB\t0\t; current value of the mouse button\nMDisabled\t\tDB\t0\t; Is the mouse driver disabled\nMInput\t\t\tDB\t1\t; Defaults to mouse input allowed.\nAdjust\t\t\tDW\t0\t; flag to adjust coordinates if necessary\nMouseStepX\t\tDW\t0\t; step values if the mouse moves at\nMouseStepY\t\tDW\t0\t;   more than one pixel at a time\nMouseOffsetX\t\tDW\t0\t; Fractional step values used if a mouse\nMouseOffsetY\t\tDW\t0\t;   moves at less than one pixel at a time\nMState\t\t\tDW\t0,0\t; Tracks if mouse is hidden (TRUE) or not (FALSE)\nMouseXOld     \t\tDW\t0\t; Holds last MouseX and MouseY to determine if\nMouseYOld     \t\tDW\t0\t;   mouse needs to be redrawn\nMCState\t\t\tDW\t0\t; Tracks if mouse conditional hidden (TRUE) or not\nMouseCXLeft\t\tDW\t0,0\t; Conditional hide mouse left x position\nMouseCYUpper\t\tDW\t0,0\t; Conditional hide mouse top y position\nMouseCXRight\t\tDW\t0,0\t; Conditional hide mouse right x position\nMouseCYLower\t\tDW\t0,0\t; Conditional hide mouse lower y position\nMouseCursor   \t\tDD\t0\t; Pointer to the mouse cursor to draw\nMouseCursorSize\t\tDW\t0\t; Pointer to buffer mouse is saved in\nMouseBuffer   \t\tDD\t0\t; Pointer to buffer mouse is saved in\nMouseXHot     \t\tDW\t0,0\t; Offset to mouse's x hot spot\nMouseYHot     \t\tDW\t0,0\t; Offset to mouse's y hot spot\nMouseBuffX\t\tDW\t0,0\t; X position background was saved at\nMouseBuffY\t\tDW\t0,0\t; Y position background was saved at\nMouseBuffW\t\tDW\t0,0\t; Width of the region saved for mouse\nMouseBuffH\t\tDW\t0,0\t; Height of the region saved for mouse\nMouseWidth\t\tDW\t0,0\t; Mouse cursor theoretical width\nMouseHeight\t\tDW\t0,0\t; Mouse cursor theoretical height\nMouseCodeOffset\t\tDW\tRM_Mouse_Interrupt\t; Offset of the code in the RM stuff.\nMouseRight\t\tDW\t0,0\nMouseBottom\t\tDW\t0,0\n\n\nShadowPtr\t\tdw\t0\nDrawMousePtr \t\tdw\t0\n\nVGAMouseDraw\t\tdw\tVGA_Draw_Mouse\nVGAMouseShadow\t\tdw\tVGA_Mouse_Shadow_Buffer\n\nVESAMouseDraw\t\tdw\tVESA_Draw_Mouse\nVESAMouseShadow\t\tdw\tVESA_Mouse_Shadow_Buffer\n\nVesaPtr\t\t\tdd\t0\nbanktable\t\tdd      8 dup ( 0 )\nAdjust_XPos\t\tdw \t0 , 0\nAdjust_YPos\t\tdw \t0 , 0\n\n\t\talign 2\nKeyboard_App_Stack_ES\tdw 0\t\t; This the System Stack Offsset\nKeyboard_App_Stack_SS\tdw 0\t\t; This the System Stack Selector\nKeyboard_StackPointer\tdw 0DEADh\t; We Create a Local Application\nKeyboard_Stack\t\tdw 512 dup (0)\nKeyboard_StackStart\tdw 0\n\nMouse_State\t\tdw 0\t\t; Mouse Temp Variable\nMouse_Cond\t\tdw 0\t\t; Mouse Temp Variable\nMouse_App_Stack_ES\tdw 0\t\t; This the System Stack Offsset\nMouse_App_Stack_SS\tdw 0\t\t; This the System Stack Selector\nMouse_StackPointer\tdw 0DEADh\t; We Create a Local Application\nMouse_Stack\t\tdw 512 dup (0)\nMouse_StackStart\tdw 0\n\n\n\ncurrent_page\t\tdw\t0\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Translates extended keynums to normal keynums\t   *\n;*                                                                         *\n;* INPUT:\tUWORD the keynum to translate\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated keynum                                 *\n;*                                                                         *\n;* PROTO:\tUWORD KeyNum_Translate(UWORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tKeyNum_Translate:FAR\n\tPROC\tKeyNum_Translate C FAR\n\tUSES\tcx,di,es,ds\n\tARG\tkeycode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\tmov\tes,ax\t\t\t\t; set es up for scansb\n\n\tmov\tax,[keycode]\n\ttest\t[WORD PTR KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\tmov\tcx,ExtRemap-ExtNums\n\tmov\tdi,OFFSET ExtNums\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tdi,OFFSET ExtRemapEnd\n\tdec\tdi\n\tsub\tdi,cx\n\tmov\tal,[es:di]\n??fini:\n\tret\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(WORD code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_WORD:FAR\n\tPROC\tStuff_Key_WORD C FAR\n\tUSES\tsi,bx,ds\n\tARG\tcode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\tax,[WORD PTR KeyBufferTail]\n\tmov\tsi,ax\n\tadd\tax,2\n\tand\tax,0FFh\t\t\t\t; New KeyBufferTail value.\n\tcmp\t[WORD PTR KeyBufferHead],ax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[KeyBuffer+si],bx\t\t; Record the keystroke.\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\n\tret\n\n??noroom:\n\tmov\tax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(WORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_Num:FAR\n\tPROC\tStuff_Key_Num C FAR\n\tUSES\tbx,cx,dx,di,si,ds\n\tARG\tkeycode:WORD\n\tLOCAL\ttail:WORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n\tpushf\n\tcli\t\t\t\t; disable interrupts\n\n\t; Abort key recognition if in record mode and unable\n\t; to output key due to simultaneous DOS operation.\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\tax,[MouseX]\n\tmov\t[LocalMouseX],ax\n\tmov\tax,[MouseY]\n\tmov\t[LocalMouseY],ax\n\n??cando:\n\tmov\tax,[keycode]\t\t; get the code\n\tor\tax,ax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[WORD PTR KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[WORD PTR KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tbx,1\t\t\t; double for WORD index\n\tadd\tbx,OFFSET XYAdjust\n\tmov\tax,[bx]\t\t\t; get x,y add value\n\n\tmov\tbl,ah\n\tcbw\n\txchg\tax,bx\n\tcbw\n\txchg\tax,bx\t\t\t; AX = mouse x delta, BX = mouse y delta\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tdx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tdx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tbx,dx\t\t\t; add speed for y index\n\tmov\tbl,[KeyMouseMove+bx] \t; get speed for y delta\n\txchg\tax,bx\t\t\t; swap with ax to extend sign\n\tcbw\n\txchg\tax,bx\n\txchg\tbx,dx\t\t\t; save mouse y delta\n\tadd\tbx,ax\t\t\t; add speed for x index\n\tmov\tal,[KeyMouseMove+bx]\t; get speed for x delta\n\tcbw\n\txchg\tbx,dx\t\t\t; restore mouse y delta\n\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tbx,011b\t\t\t; Y = 1, 0, 3\n\tand\tax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tbx,011b\t\t\t; Y = 3, 0, 1\n\tand\tax,011b\t\t\t; X = 3, 0, 1\n\tshl\tbx,1\n\tshl\tbx,1\n\tor\tbx,ax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tbx,1\n\tmov\tbx,[EdgeConv+bx]\n\tshl\tbx,1\n\tshl\tbx,1\n\tmov\tax,[ScreenEdge+bx]\t; New absolute X\n\tmov\tbx,[ScreenEdge+bx+2] ; New absolute Y\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\tax,ax\n\tmov\t[LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tbx,bx\n\tmov\t[LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\tmov\t[MouseX],ax\n\tmov\t[MouseY],bx\n\tcmp\t[MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n\n\tcall\tLow_Hide_Mouse\n\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\tax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],ax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tsi,[WORD KeyBufferTail]\n\tmov\t[tail],si\t\t; Safety record.\n\tmov\tdi,[WORD PTR KeyBufferHead]\n\n\t; Record the base keycode (if there is room).\n\tpush\tax\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\tax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tpush\t[LocalMouseX]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tpush\t[LocalMouseY]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tbx,0101h\t\t; Bit control tools.\n\tmov\tax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[WORD PTR KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tmov\tcl,3\n\tshr\tdi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[KeysUpDown+di]\n\tje\tshort ??notalready\n\ttest\t[WORD PTR KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[KeysUpDown+di],bh\t; Force key bit to zero.\n\tor\t[KeysUpDown+di],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\tax,1\n\tjmp short ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\tax,[tail]\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\t\t\t; Signal an error.\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tStuff_Key_Num\n;***********************************************************\n\n\n\n;***************************************************************************\n;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard       *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Keystroke_Interrupt\n\tGLOBAL\tC Keystroke_Interrupt:FAR\n\tPROC\tKeystroke_Interrupt C FAR\n\nIF 0\n\tpush\tax\n\tinc\tax\n\tpop\tax\n\tiret\n\nELSE\n\tpush\tax\n\tpush\tbx\n\tpush\tcx\n\tpush\tdi\n\tpush\tds\n\tpush\tdx\n\tpush\tes\n\tpush\tsi\n\tcld\n\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tds,ax\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov cx, ss\t\t\t\t; get SS\n\tmov [Keyboard_App_Stack_ES], sp\t\t; Protect ES\n\tmov [Keyboard_App_Stack_SS], cx\t\t; Protect SS\n\tlea dx, [Keyboard_StackStart ]\t\t; Compute Local Stack size\n\tand dx, -2;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov sp, dx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n\tcmp\t[WORD PTR PMIssuedKeyInt],0; Check to see if PM made Int call.\n\tmov\t[WORD PTR PMIssuedKeyInt],0; Make it false.\n\tjne\t??passcode\t; if so, just call Int Chain.\n\n\n\tmov\tdx,[WORD PTR KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\n\tand\t[KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\tmov\tax,040H\t\t\t; BIOS segment\n\tmov\tes,ax\t\t\t; put in es\n\ttest\t[BYTE PTR es:017H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR es:017H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR es:096H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tes,ax\n\n\tcld\t\t\t\t; clear direction flag for strings\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tbx,0101H\t\t; set key to a make by default\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\n\t;\n\t; New CODE to montior key stream\n\t;\n\tmov\tbx,[KeyStreamIndex]\n\tmov\t[KeyStream+bx],al\n\tinc\tbx\n\tand\tbx,15\n\tmov\t[KeyStreamIndex],bx\n\tmov\tbx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[LastKeyE1]\t\t; yes, dec the count\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[IsExtKey],TRUE\t; it is an extended key\n\tmov\tdi,OFFSET ExtCodes\t; get offset of extended codes table\n\tmov\tcx,(ExtNums-ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\tmov\tal,[(ExtNums - ExtCodes) - 1 + di] ; get the match\n\tmov\t[IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tdi,ax\t\t\t; use code as an index\n\tand\tdi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[KeyNums+di]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[KeysUpDown+8],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[KeysUpDown+7],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[KeysUpDown + 7],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\tax\n\tcall\tKeyNum_Translate\n\tadd\tsp,2\n\n;------\tSet the shift bit if necessary.\n\ttest\t[KeysUpDown+5],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[KeysUpDown+7],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tshr\tdi,1\n\tshr\tdi,1\n\tshr\tdi,1\n\tmov\tbx,ax\n\tand\tbx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[Bits+bx]\t\t; get the bit to test\n\ttest\t[KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[KeysCapsLock+di]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[KeysNumLock+di]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\n\t\t\t\t\t; keyboard buffer.\n\ttest\tdx,DEBUGINT\n\tjz\t??not_toggle\n\n\nIF DEBUG\n\tcmp\t[KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\tcmp\tax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\tax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\tax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\n\tcmp\tax,125\n\tjne\t??not_toggle\n\tmov\t[KeyIntDisabled],1\n\tjmp\t??absorbcode\nENDIF\n\n??not_toggle:\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\tax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\tax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\tax,0230h\n\tje\tshort ??breaker\n\tcmp\tax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n\tcmp\tax,0420H\t\t; is this an alt s\n\tjne\tshort ??checkmusic\t; toggle the Sound variable\n\tpush\tax\n\tmov\tax,[SoundOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??checkmusic:\n\tcmp\tax,0434H\t\t; is this an alt m\n\tjne\tshort ??esc\t\t; toggle the Music variable\n\tpush\tax\n\tmov\tax,[MusicOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??esc:\n\n\tpush\tax\n\tcall\tStuff_Key_Num\n\tpop\tax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\tax\n\tcall\t[EscRoutine]\n\tpop\tax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tdi,OFFSET PassAlways\t; get offset to table\n\tmov\tcx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1\n\trepne\tscasb\t\t\t; look for a match\n\tor\tcx,cx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n\n\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tdi,OFFSET CondPassKey\t; get offset to cond key table\n\tmov\tcx,(CondPassCond-CondPassKey) ; get number of entries\n\tshr\tcx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(CondPassCond - CondPassKey) - 2 + di]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tdx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\n\tinc\t[cs:PassCount]\n\n;mov   ax , 0B000h\n;mov   es, ax\n;inc   [BYTE PTR es : 40h]\n\n\t; Now it is time to set up for the call to the System Keyboard\n\t; interrupt handler.\n\t; 1 -Restore System Stack Pointer Selector before exit Interrupt\n\t; 2- We Create a Returning Point from Interrupt by Push A\n \t;    Interupt Stack Frame into the Stack Pointer\n\t; 3- We make a Far jump to the interuupt handler\n\tcmp [Keyboard_StackPointer],0DEADh\n\tje  ??stackok\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n??stackok:\n\tcli\t\t\t\t       ; disable Interrupts\n\tmov dx, [Keyboard_App_Stack_SS]\n\tmov ss, dx\t\t\t       ; Get System Stack Selector\n\tmov sp, [Keyboard_App_Stack_ES]      ; Get System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n\tlea\tdx, [??Call_Back_Keyboard]   ; Get Return address offset\n \tpushf\t\t\t\t      ; push flags\n\tpush\tcs\t\t\t      ; push Code segment\n\tpush\tdx\t\t\t      ; push Offset\n\n\t; Now we need to simulate an interrup call by using ired\n\t; because we still want to come back here from the\n\t; Old Keyboard interrupt handle.\n\tpushf\n\tpush\t[word ptr KeyOldRMI + 2] \t; push orig segment.\n\tpush    [word ptr KeyOldRMI]   \t\t; push orig offset.\n\tiret\t \t\t        \t; call interrupt\n\n??absorbcode:\n\n;mov   ax , 0B000h\n;mov   es, ax\n;inc   [BYTE PTR es : 0h]\n\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tax,040h\t\t\t\t; BIOS paragraph is always @ 040h\n\tmov\tes,ax\t\t\t\t; put in es as BIOS paragraph\n\tmov\tal,[es:96h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[es:96h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\n\tcmp [Keyboard_StackPointer],0DEADh\n\tje  ??stackok2\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n??stackok2:\n\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov dx, [Keyboard_App_Stack_SS]\n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, dx\t\t\t       ; Get Syatem Stack Selector\n\tmov sp, [Keyboard_App_Stack_ES]        ; Get Syatem Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n??Call_Back_Keyboard:\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tiret\nENDIF\n\n\tENDP\tKeystroke_Interrupt\n\n;***************************************************************************\n;* Break interrupt routines begin here!\n;***************************************************************************\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles the break key interrupt                      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Break_Interrupt\n\tGLOBAL\tC Break_Interrupt:FAR\n\tPROC\tBreak_Interrupt C FAR\n\n\n\tpushf\n\tpush\tax\n\tpush\tes\n\n\tmov\tax,0B000h\t\t; ES:DI = Mono RAM address.\n\tmov\tes,ax\n\tinc\t[BYTE PTR es:0]\n\n\n\tpop\tes\n\tpop\tax\n\tpopf\n\n\n\tiret\n\n\tENDP\tBreak_Interrupt\n\n;**************************************************************************\n;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                                  *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nCall_Interrupt_Chain:\n\tpushf\n\tcall\tKeystroke_Interrupt ;[KeyOldRMI]\n\tretf\n\n;----------------------------------------------------------------------------\n; LOW_HIDE_MOUSE:\n;\n; This function hides the mouse cursor on the screen if it was shown.  It\n; will not hide the mouse if it is already hidden.\n;\n; PROTOTYPE:\n;\n;\tVOID Low_Hide_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Hide_Mouse:FAR\n\tPROC\tLow_Hide_Mouse C FAR\n\tUSES\tax,bx,cx,dx,ds\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n   \tcmp\t[MDisabled],0\t\t; check if mouse is disabled\n\tjne\tshort ??end\n\n   \tcmp\t[MState],0\t\t; check if it was hidden before\n\tjne\tshort ??endnodraw\t\t; no need to hide again\n\n;------\tMove the saved graphic buffer to the seenpage to hide the mouse.\n;\tcall\tBuffer_To_Page C,[buffx],[buffy],[buffw],[buffh],[MouseBuffer],SEENPAGE\n\tmov\tax,RESTORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tRecord that the mouse has been hidden.\n??endnodraw:\n\tadd\t[MState],1\n\tadc\t[MState],0\n\n??end:\n\tret\n\n\tENDP\tLow_Hide_Mouse\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; LOW_SHOW_MOUSE:\n;\n; This function displays the mouse cursor on the screen if it was hidden.\n;\n; PROTOTYPE:\n;\tVOID Low_Show_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Show_Mouse:FAR\n\tPROC\tLow_Show_Mouse C FAR\n\tUSES \tax,bx,cx,dx,si,di,ds,es\n\tLOCAL\tmousex:WORD\t\t; Draw X position.\n\tLOCAL\tmousey:WORD\t\t; Draw Y position.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n;-----\tDon't show the mouse if it is not hidden, disabled.\n\tcmp\t[MDisabled],0\t\t; is the mouse disabled\n\tjne\t??exit\t\t\t; if so then exit\n\n\tcmp\t[MState],0\t\t; is the mouse already visible\n       \tje\t??exit\t\t\t; if so then exit\n\n\tdec\t[MState]\n\tcmp\t[MState],0\t\t; can the mouse be shown\n       \tjne\tshort ??exit\n\n;------\tDetermine the drawing position of the mouse.\n\tmov\tcx,[MouseWidth]\t\t; Theoretical buffer width (pixel).\n\tmov\tdx,[MouseHeight]\t; Theoretical buffer height (pixel).\n\n\tmov\tax,[MouseX]\n;\tsub\tax,[MouseXHot]\n\tmov\t[mousex],ax\t\t; Draw X pixel.\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??xnotneg\n;\tadd\tcx,ax\t\t\t; Reduce width accordingly.\n;\tmov\tax,0\n??xnotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n\tmov\tbx,[MouseY]\n;\tsub\tbx,[MouseYHot]\n\tmov\t[mousey],bx\t\t; Draw Y pixel.\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??ynotneg\n;\tadd\tdx,bx\t\t\t; Reduce height of mouse accordingly.\n;\tmov\tbx,0\n??ynotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n;------\tDetermine the theoretical coordinates and dimensions of the\n;\tarea the mouse shape will be rendered upon.\n\tmov\t[MouseBuffX],ax\n\tmov\t[MouseBuffY],bx\n\tmov\t[MouseBuffW],cx\n\tmov\t[MouseBuffH],dx\n\n;------\tMove the area that will be drawn upon, to the graphic buffer.\n\tmov\tax,STORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tDraw the mouse shape to the seenpage.\n\tpush\t[mousey]\n\tpush\t[mousex]\n\tpush\tcs\n\tcall\t[ DrawMousePtr ]\n\tadd\tsp,4\n??exit:\n\tret\n\n\tENDP\tLow_Show_Mouse\n\n;----------------------------------------------------------------------------\n;----------------------------------------------------------------------------\n\tGLOBAL\tC Mouse_KeyNum:FAR\n\tPROC\tMouse_KeyNum C FAR\n\tUSES\tbx\n\tARG\tstate:WORD\t\t; Current mouse state.\n\tLOCAL\tkeynum:WORD\t\t; Determined keynum.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\t[keynum],KN_MOUSE_MOVE\t; Presume just a mouse move.\n\tmov\tbx,[state]\n\tmov\tax,bx\n\txor\tbl,[Button]\t\t; Bits of state change.\n\tje\tshort ??fini\n\tmov\t[Button],al\t\t; Record new mouse state.\n\n\ttest\tbl,0010b\n\tje\tshort ??notright\n\tmov\t[keynum],KN_RMOUSE\n\ttest\tal,0010b\n\tjne\tshort ??notright\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notright:\n\n; DRD\n; note:  the left mouse button has priority over the right mouse button\n; this should be changed at a later date to process them independently\n\n\ttest\tbl,0001b\n\tje\tshort ??notleft\n\tmov\t[keynum],KN_LMOUSE\n\ttest\tal,0001b\n\tjne\tshort ??notleft\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notleft:\n\n??fini:\n\tmov\tax,[keynum]\n\tret\n\n\tENDP\tMouse_KeyNum\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; MOUSE_INT:\n;\n; This routine is called automatically when the Mouse_Int is installed.  It\n; automatically updates the global variables stored in the code segment so\n; that the mouse information is automatically known at all times.\n;\n; INPUTS (from int):\tAX = condition mask ( bit 0 == cursor position chg,\n;\t\t\t\t\t      bit 1 == left button press,\n;\t\t\t\t\t      bit 2 == left button release,\n;\t\t\t\t\t      bit 3 == right button press,\n;\t\t\t\t\t      bit 4 == right button release,\n;\t\t\t\t\t      5-15  == not used )\n;\t\t\tBX = button state   ( bit 0 == left button down,\n;\t\t\t\t\t      bit 1 == right button down,\n;                                             bit 2 == middle button down.\n;\t\t\t\t\t      3-15  == not used )\n;\t\t\tCX = cursor coordinate (horizontal axis)\n;\t\t\tDX = cursor coordinate (vertical axis)\n;\t\t\tDI = horizontal mouse count (mickeys)\n;\t\t\tSI = vertical mouse count (mickeys)\n;\n; RETURNS:\t\tnone\n;\n; MODIFIES:\t\tmodifies the variables _Button, _ButtonChange,\n;\t\t\t_MouseX,_MouseY,_ButtonLatch\n;\n; PROTOTYPE:\n;\tThis routine is called from an interrupt.\n;----------------------------------------------------------------------------\nlabel RM_Mouse_Interrupt\n\tPROC\tMouse_Int C FAR\n\tUSES\tax,bx,cx,dx,ds,si,es,di\n\tLOCAL\tcond:WORD\t\t; Local copy of mouse event.\n\tLOCAL\tstate:WORD\t\t; Local copy of button state.\n\n\tmov\t[cs:Mouse_State],bx\n\tmov\t[cs:Mouse_Cond],ax\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov bx, ss\t\t\t\t; get SS\n\tmov [Mouse_App_Stack_ES], sp\t\t; Protect ES\n\tmov [Mouse_App_Stack_SS], bx\t\t; Protect SS\n\tlea bx, [Mouse_StackStart ]\t; Compute Local Stack size\n\tand bx, -2;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov sp, bx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n\n\n\tpush ax\n\tpush dx\n\n\tmov \tdx,3c8h\n\txor\tal,al\n\tout\tdx,al\n\tinc\tdx\n\tout\tdx,al\n\n\tmov\tdx,3c9h\n\tmov\tax,cx\n\tshr\tax,3\n\tout\tdx,al\n\tjmp\t??j1\n??j1:\txor\tal,al\n\tout\tdx,al\n\tjmp\t??j2\n??j2:\tout\tdx,al\n\tjmp\t??j3\n??j3:\n\n\tpop\tdx\n\tpop\tax\n\n\n\n;------\tProcess the mouse interrupt only if the mouse is enabled (whether\n;\tpresent or not).\n\tcmp\t[MDisabled],0\n\tjne\t??exit\n\n\tcmp\t[MInput],0\n\tje\t??exit\n\n\n;------ This was added because of missing mouse presses and\n;\treleases during a mouse update.\n\tmov\tax,[Mouse_Cond]\n\tand\tax,0001EH \t; bits for left and right press and release\n\tjne\tshort ??dopress_release\n\n\tcmp\t[MouseUpdate],0 ; if mouse move and mouse updating exit\n\tjne\t??exit\n\n??dopress_release:\n\n;------\tIn EEGA mode mouse X coordinates as 0..639.  Make adjustment\n;\tto keep within 0..319 range.\n\tcmp\t[Adjust],1\t\t; if the x coordinate is returned\n\tjne\tshort ??noadjust\t; incorrectly then\n\tshr\tcx,1\t\t\t; adjust x coord from 640 pixel screen\n??noadjust:\n\n\n; scale mouse posX and PosY\n;\tcmp\t[Adjust_XPos] , 0\n;\tjz\tshort ??no_scaleX\n;\tpush\tdx\n;\tmov\tax , [MouseRight]\n;\timul\tcx\n;\tidiv\t[Adjust_XPos]\n;\tmov\tcx , ax\n;\tpop\tdx\n??no_scaleX:\n;\tcmp\t[Adjust_YPos] , 0\n;\tjz\tshort ??no_scaleY\n;\tmov\tax , [MouseBottom]\n;\timul\tdx\n;\tidiv\t[Adjust_YPos]\n;\tmov\tdx , ax\n??no_scaleY:\n\n;------\tKeep mouse within screen bounds.\n\tcmp\tcx,[MouseRight]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundX_ok\t\t; force it to stay at least one pixel\n\tmov\tcx,[MouseRight]\t\t\t; on the screen\n\tdec\tcx\n??boundX_ok:\n\tcmp\tdx,[MouseBottom]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundY_ok\t\t; force it to stay at least one pixel\n\tmov\tdx,[MouseBottom]\t\t\t; on the screen\n\tdec\tdx\n??boundY_ok:\n\n\tIF 0\n;------\tRemap the middle button to equal the right button.\n\ttest\tbx,04h\n\tje\t??noremap\n\tor\tbx,0010b\t\t; Set the right button bit.\n??noremap:\n\tENDIF\n\n\tmov\t[MouseX],cx\t\t; and store in mouse x\n\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\ttest\t[KeyFlags],KEYMOUSE\n\tjne\tshort ??nostuffit\n\n\tcall\tMouse_KeyNum C,[Mouse_State]\t; Convert mouse state to key number code.\n\tcall\tStuff_Key_Num C,ax\t; Record mouse keynumber code.\n??nostuffit:\n\n\n\n;------ The check for Mouse in the middle of updating CAN NOT BE MOVED\n;\tany farther up because mouse presses and releases will be LOST!!\n \tcmp\t[MouseUpdate],0\n\tjne\t??exit\n;??jexit:\n;\tjmp\t??exit\n\n\nchristopher:\n??chkxy:\n\n;------\tSignal that no mouse updating can occur at this time.\n;\tcmp\t[_MouseUpdate],0\n;\tjne\t??exit\n;\tmov\t[_MouseUpdate],1\n\n;------\tPerform any X movement grid adjustment.\n\tcmp\t[MouseStepX],0\t\t; are we stepping on the X?\n\tje\tshort ??no_x_step\t\t; no x\n\tmov\tax,cx\t\t\t; get current x_pixel\n\tmov\tcx,dx\t\t\t; save dx - it is trashed by idiv\n\tsub\tax,[MouseOffsetX]\t; get offset difference\n\tmov\tbx,[MouseStepX]\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step X\n\timul\tbx\t\t\t; ax = div * Step X\n\tadd\tax,[MouseOffsetX]\t; normalize to region offset\n\tmov\tdx,cx\t\t\t; restore dx (new MouseY)\n\tmov\tcx,ax\t\t\t; set cx (new MouseX)\n??no_x_step:\n\n;------\tPerform any Y movement grid adjustment.\n\tcmp\t[MouseStepY],0\t\t; are we stepping on the Y\n\tje\tshort ??no_step\t\t; no y\n\tmov\tax,dx\t\t\t; get current y_pixel\n\tsub\tax,[MouseOffsetY]\t; get offset difference\n\tmov\tbx,[MouseStepY]\t\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step Y\n\timul\tbx\t\t\t; ax = div * Step Y\n\tadd\tax,[MouseOffsetY]\t; normalize to region offset\n\tmov\tdx,ax\t\t\t; set dx (new MouseY)\n??no_step:\n\n;------ Here is where we store the new MouseX and MouseY values\n;\tmov\t[MouseX],cx\t\t; and store in mouse x\n;\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\n;------\tIf the mouse is hidden or its position hasn't changed, then\n;\tperform no action.\n\tcmp\t[MState],0\n\tjne\tshort ??updateend\n\tcmp\t[MouseXOld],cx\n\tjne\tshort ??doit\n\tcmp\t[MouseYOld],dx\n\tje\tshort ??updateend\n??doit:\n\n;------\tAt this point we KNOW the mouse has moved.\n\tmov\tax,[MCState]\n\tand\tax,CONDHIDE+CONDHIDDEN\n\tcmp\tax,CONDHIDE+CONDHIDDEN\n\tje\tshort ??condcheck\t\t; If already hidden.\n\n;------\tWe know that the mouse is visible, we must hide it\n;\tbefore we update its position.\n\tcall\tLow_Hide_Mouse\n\n;------\tConditional region check goes here.  If the mouse falls within the\n;\tconditional region, it gets marked as hidden and no other processing\n;\toccurs.\n\ttest\t[MCState],CONDHIDE\n\tje\tshort ??condok\n\n??condcheck:\n\tcmp\tcx,[MouseCXLeft]\t\t; check adjusted x region\n\tjb\tshort ??condok\n\tcmp\tcx,[MouseCXRight]\n\tja\tshort ??condok\n\tcmp\tdx,[MouseCYUpper]\t; check adjusted y region\n\tjb\tshort ??condok\n\tcmp\tdx,[MouseCYLower]\n\tja\tshort ??condok\n\n\tor\t[MCState],CONDHIDDEN\t; flag as conditional hidden\n\tjmp short ??updateend\n\n;------\tThe mouse coordinates and flags pass all of the tests, proceed\n;\twith rendering the mouse.\n??condok:\n\tcall\tLow_Show_Mouse\n\n;------\tFinal clean up and exit.\n??updateend:\n\tmov\t[MouseXOld],cx\n\tmov\t[MouseYOld],dx\n\n??exit:\n\tcmp\t[Mouse_StackPointer],0DEADh\n\tje\t??mouse_stk_ok\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n\n??mouse_stk_ok:\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov ax, [Mouse_App_Stack_SS]\n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, ax\t\t\t       ; Get Syatem Stack Selector\n\tmov sp, [Mouse_App_Stack_ES]           ; Get Syatem Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\tret\n\tENDP\tMouse_Int\n\n\n\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VGA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVGA_Mouse_Shadow_Buffer C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax\n\tmov\t[ y0 ] , bx\n\n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax\n\tmov\t[ y1 ] , bx\n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]\n\tmov\tbx , [ x1 ]\n\tadd\tcx , cx\n\tadc\tax , ax\n\tadd\tbx , bx\n\tadc\tdx , dx\n\n\tmov\tcx , [ x0 ]\n\tmov\tbx , [ x1 ]\n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax\n\tadd\tbx , bx\n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]\n\tmov\tbx , [ y1 ]\n\tadd\tcx , cx\n\tadc\tax , ax\n\tadd\tbx , bx\n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]\n\tmov\tbx , [ y1 ]\n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax\n\tadd\tbx , bx\n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ]\n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\n\n\tpush\tbp\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tbp , cx\n??restore_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n\nIF  ECHOON\nmov ax , 0b000h\nmov di , 12 * 80 + 10\nmov es, ax\nmov al , 'V'\nmov [es:di],al\nmov al,2\nmov [es:di+1],al\nENDIF\n\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tsi,di\t\t\t\t\t; xchg the source and the dest\n\tmov\tbp , cx\n\tpush\tes\t\t\t\t\t; need to swap es and ds but\n\tpush\tds\t\t\t\t\t;   cant xchg so pop them on the\n\tpop\tes\t\t\t\t\t;   stack and pop them off the\n\tpop\tds\t\t\t\t\t;   wrong way intentionally.\n??store_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,dx\t\t\t\t\t; move past right clipped pixels\n\tadd\tdi,bx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n??out:\n\nIF  ECHOON\nmov ax , 0b000h\nmov di , 12 * 80 + 12\nmov es, ax\nmov al , 'G'\nmov [es:di],al\nmov al,2\nmov [es:di+1],al\nENDIF\n\tret\n\n\tENDP\tVGA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n\n\tGLOBAL\tC VGA_Draw_Mouse:FAR\n\tPROC\tVGA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax\n\tmov\t[ y0 ] , bx\n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax\n\tmov\t[ y1 ] , bx\n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]\n\tmov\tbx , [ x1 ]\n\tadd\tcx , cx\n\tadc\tax , ax\n\tadd\tbx , bx\n\tadc\tdx , dx\n\n\tmov\tcx , [ x0 ]\n\tmov\tbx , [ x1 ]\n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax\n\tadd\tbx , bx\n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]\n\tmov\tbx , [ y1 ]\n\tadd\tcx , cx\n\tadc\tax , ax\n\tadd\tbx , bx\n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]\n\tmov\tbx , [ y1 ]\n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax\n\tadd\tbx , bx\n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tbx , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , bx\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tbx , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , bx\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ]\n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h\nmov di , 12 * 80 + 14\nmov es, ax\nmov al , 'A'\nmov [es:di],al\nmov al,2\nmov [es:di+1],al\nENDIF\n\tret\nENDP\tVGA_Draw_Mouse\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VESA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVESA_Mouse_Shadow_Buffer C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax\n\tmov\t[ y0 ] , bx\n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax\n\tmov\t[ y1 ] , bx\n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]\n\tmov\tbx , [ x1 ]\n\tadd\tcx , cx\n\tadc\tax , ax\n\tadd\tbx , bx\n\tadc\tdx , dx\n\n\tmov\tcx , [ x0 ]\n\tmov\tbx , [ x1 ]\n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax\n\tadd\tbx , bx\n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]\n\tmov\tbx , [ y1 ]\n\tadd\tcx , cx\n\tadc\tax , ax\n\tadd\tbx , bx\n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]\n\tmov\tbx , [ y1 ]\n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax\n\tadd\tbx , bx\n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ]\n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\n\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\n\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??restore_loop:\n\tmov\tah,al\n??res_inner_loop:\n\tmov\tch , [si]\n\tmov\t[es:di],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??res_same_page\n\tcall\tnext_vesa_page\n ??res_same_page:\n \tdec\tah\n\tjnz\t??res_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??res_same_page1\n\tcall\tnext_vesa_page\n ??res_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\n\nIF  ECHOON\nmov ax , 0b000h\nmov di , 10 * 80 + 10\nmov es,ax\nmov al ,'v'\nmov [es:di],al\nmov al,2\nmov [es:di+1],al\nENDIF\n\tjmp\t??out\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\tmov\tah,al\n??store_inner_loop:\n\tmov\tch , [es:di]\n\tmov\t[si],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??store_same_page\n\tcall\tnext_vesa_page\n ??store_same_page:\n \tdec\tah\n\tjnz\t??store_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??store_same_page1\n\tcall\tnext_vesa_page\n ??store_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_entry\n??out:\n\nIF  ECHOON\nmov ax , 0b000h\nmov di , 10 * 80 + 14\nmov es,ax\nmov al ,'e'\nmov [es:di],al\nmov al,2\nmov [es:di+1],al\nENDIF\n\n\tmov\tdx , [ app_vesa_window ]\n\tcall\tset_vesa_window\n\tret\n\n\tENDP\tVESA_Mouse_Shadow_Buffer\n\n\n\n;***************************************************************************\n\n\tGLOBAL\tC VESA_Draw_Mouse:FAR\n\tPROC\tVESA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\tlocal\tapp_vesa_window : word\n\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax\n\tmov\t[ y0 ] , bx\n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax\n\tmov\t[ y1 ] , bx\n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]\n\tmov\tbx , [ x1 ]\n\tadd\tcx , cx\n\tadc\tax , ax\n\tadd\tbx , bx\n\tadc\tdx , dx\n\n\tmov\tcx , [ x0 ]\n\tmov\tbx , [ x1 ]\n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax\n\tadd\tbx , bx\n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]\n\tmov\tbx , [ y1 ]\n\tadd\tcx , cx\n\tadc\tax , ax\n\tadd\tbx , bx\n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]\n\tmov\tbx , [ y1 ]\n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax\n\tadd\tbx , bx\n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ]\n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tsi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tjnz\t??same_page\n\tcall\tnext_vesa_page\n ??same_page:\n \tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??same_page1\n\tcall\tnext_vesa_page\n ??same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h\nmov di , 10 * 80 + 14\nmov es, ax\nmov al , 's'\nmov [es:di],al\nmov al,2\nmov [es:di+1],al\nmov di , 10 * 80 + 16\nmov al , 'a'\nmov [es:di],al\nmov al,2\nmov [es:di+1],al\nENDIF\n\tmov\tdx , [ app_vesa_window ]\n\tcall\tset_vesa_window\n\tret\n\n\nENDP\tVESA_Draw_Mouse\n\n\n\n;************************************************************************\n\nPROC\tget_vesa_window C near\nuses\tax,bx\n\tmov\tax , 04f05h\n\tmov\tbh , 1\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\n\n;************************************************************************\n\nPROC\tset_vesa_window C near\nuses\tax,bx,dx\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\n\n\n;***************************************************************************\n\nPROC\tset_vesa_page C near\nUSES\tax,bx,dx\n\n\tmov\tbx , dx\n\tshl\tbx , 2\n\tmov\t[ cs: current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tset_vesa_page\n\nPROC\tnext_vesa_page C near\nUSES\tax,bx,dx\n\tmov\tbx , [ cs: current_page ]\n\tadd\tbx , 4\n\tmov\t[ cs:current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n       \tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tnext_vesa_page\n\n\n\n;***********************************************************\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/LCWCOMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/misc/rcs/lcwcomp.asm 1.1 1994/04/11 15:31:10 jeff_wilson Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library routine                          *\n;*                                                                         *\n;*                    File Name : COMPRESS.ASM                             *\n;*                                                                         *\n;*                   Programmer : Louis Castle                             *\n;*                                                                         *\n;*                  Last Update : 20 August, 1990   [CY]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n; ULONG LCW_Compress(BYTE *source,BYTE *dest, ULONG length);                *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL    LCW_Compress          :NEAR\n\nCODESEG\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; ULONG LCW_Compress(BYTE *source,BYTE *dest, ULONG length);\n;\n; ----------------------------------------------------------------\n\n\n\n;***********************************************************\n;\n; ULONG LCW_Compress(BYTE *source, BYTE *dest, ULONG length)\n;\n; returns the size of the compressed data in bytes\n;\n;*\nPROC\tLCW_Compress C near \n\tUSES ebx,ecx,edx,edi,esi\n\t\n\tARG\tsource:DWORD   \n\tARG\tdest:DWORD\n\tARG\tdatasize:DWORD\n\n\tLOCAL inlen:DWORD\n\tLOCAL a1stdest:DWORD\n\tLOCAL a1stsrc:DWORD\n\tLOCAL lenoff:DWORD\n\tLOCAL ndest:DWORD\n\tLOCAL count:DWORD\n\tLOCAL matchoff:DWORD\n\tLOCAL end_of_data:DWORD\n\n\n\tcld\n \tmov\tedi,[dest]\n \tmov\tesi,[source]\n \tmov\tedx,[datasize]\t\t; get length of data to compress\n\t\n;\tmov\tax,ds\n;\tmov\tes,ax\n\n;\n; compress data to the following codes in the format b = byte, w = word\n; n = byte code pulled from compressed data\n;   Bit field of n\t\tcommand\t\tdescription\n; n=0xxxyyyy,yyyyyyyy\t\tshort run\tback y bytes and run x+3\n; n=10xxxxxx,n1,n2,...,nx+1\tmed length\tcopy the next x+1 bytes\n; n=11xxxxxx,w1\t\t\tmed run\t\trun x+3 bytes from offset w1\n; n=11111111,w1,w2\t\tlong run\trun w1 bytes from offset w2\n; n=10000000\t\t\tend\t\tend of data reached\n;\n\tcld\t\t\t; make sure all string commands are forward\n\tmov\tebx,esi\n\tadd\tebx,edx\n\tmov\t[end_of_data],ebx\n\tmov\t[inlen],1\t; set the in-length flag\n\tmov\t[a1stdest],edi\t; save original dest offset for size calc\n\tmov\t[a1stsrc],esi\t; save offset of first byte of data\n\tmov\t[lenoff],edi\t; save the offset of the legth of this len\n\tsub\teax,eax\n\tmov\tal,081h\t\t; the first byte is always a len\n\tstosb\t\t\t; write out a len of 1\n\tlodsb\t\t\t; get the byte\n\tstosb\t\t\t; save it\n??loop:\n\tmov\t[ndest],edi\t; save offset of compressed data\n\tmov\tedi,[a1stsrc]\t; get the offset to the first byte of data\n\tmov\t[count],1\t; set the count of run to 0\n??searchloop:\n\tsub\teax,eax\n\tmov\tal,[esi]\t; get the current byte of data\n\tcmp\tal,[esi+64]\n\tjne\tshort ??notrunlength\n\t\n\tmov\tebx,edi\t\t \n\t\n\tmov\tedi,esi\n\tmov\tecx,[end_of_data]\n\tsub\tecx,edi\n   \trepe\tscasb\n\tdec\tedi\n\tmov\tecx,edi\n\tsub\tecx,esi\n\tcmp\tecx,65\n\tjb\tshort ??notlongenough\n\t\n\tmov\t[DWORD PTR inlen],0\t; clear the in-length flag\n\tmov\tesi,edi\n\tmov\tedi,[ndest]\t; get the offset of our compressed data\n\t\n\tmov\tah,al\n\tmov\tal,0FEh\n\tstosb\n\txchg\tecx,eax\n\tstosw\n\tmov\tal,ch\n\tstosb\n\t\n\tmov\t[ndest],edi\t; save offset of compressed data\n\tmov\tedi,ebx\n\tjmp\t??searchloop\n??notlongenough:\n\tmov\tedi,ebx\n??notrunlength:\n\n??oploop:\n\tmov\tecx,esi\t\t; get the address of the last byte +1\n\tsub\tecx,edi\t\t; get the total number of bytes left to comp\n\tjz\tshort ??searchdone\n\t\n\trepne\tscasb\t\t; look for a match\n\tjne\tshort ??searchdone\t; if we don't find one we're done\n\n\tmov\tebx,[count]\n\tmov\tah,[esi+ebx-1]\n\tcmp\tah,[edi+ebx-2]\n\n\tjne\t??oploop\n\n\tmov\tedx,esi\t\t; save this spot for the next search\n\tmov\tebx,edi\t\t; save this spot for the length calc\n\tdec\tedi\t\t; back up one for compare\n\tmov\tecx,[end_of_data]\t\t; get the end of data\n\tsub\tecx,esi\t\t; sub current source for max len\n\t\n\trepe\tcmpsb\t\t; see how many bytes match\n\n; start of change MH 9-24-91\n\tjne\tshort ??notend\t; if found mismatch then di - bx = match count\n\n\tinc\tedi\t\t; else cx = 0 and di + 1 - bx = match count\n\t\n??notend:\n; end of change MH 9-24-91\n\n\tmov\tesi,edx\t\t; restore si\n\tmov\teax,edi\t\t; get the dest\n\tsub\teax,ebx\t\t; sub the start for total bytes that match\n\tmov\tedi,ebx\t\t; restore dest\n\tcmp\teax,[count]\t; see if its better than before\n\tjb\t??searchloop\t; if not keep looking\n\t\n\tmov\t[count],eax\t; if so keep the count\n\tdec\tebx\t\t; back it up for the actual match offset\n\tmov\t[matchoff],ebx ; save the offset for later\n\tjmp\t??searchloop\t; loop until we searched it all\n\t\n??searchdone:\n\t\n\tmov\tecx,[count]\t; get the count of the longest run\n\tmov\tedi,[ndest]\t; get the offset of our compressed data\n\tcmp\tecx,2\t\t; see if its not enough run to matter\n\tjbe\tshort ??lenin\t\t; if its 0,1, or 2 its too small\n\t\n\tcmp\tecx,10\t\t; if not, see if it would fit in a short\n\tja\tshort ??medrun\t; if not, see if its a medium run\n\t\n\tmov\teax,esi\t\t; if its short get the current address\n\tsub\teax,[matchoff] ; sub the offset of the match\n\tcmp\teax,0FFFh\t; if its less than 12 bits its a short\n\tja\tshort ??medrun\t; if its not, its a medium\n\t\n??shortrun:\n\tsub\tebx,ebx\n\tmov\tbl,cl\t\t; get the length (3-10)\n\tsub\tbl,3\t\t; sub 3 for a 3 bit number 0-7\n\tshl\tbl,4\t\t; shift it left 4\n\tadd\tah,bl\t\t; add in the length for the high nibble\n\txchg\tah,al\t\t; reverse the bytes for a word store\n\tjmp\tshort ??srunnxt\t; do the run fixup code\n\n??medrun:\n\tcmp\tecx,64\t\t; see if its a short run\n\tja\tshort ??longrun\t; if not, oh well at least its long\n\t\n\tsub\tcl,3\t\t; back down 3 to keep it in 6 bits\n\tor\tcl,0C0h\t\t; the highest bits are always on\n\tmov\tal,cl\t\t; put it in al for the stosb\n\tstosb\t\t\t; store it\n\tjmp\tshort ??medrunnxt ; do the run fixup code\n\n??lenin:\n\tcmp\t[DWORD PTR inlen],0\t; is it doing a length?\n\tjnz\tshort ??len\t; if so, skip code\n\t\n??lenin1:\n\tmov\t[lenoff],edi\t; save the length code offset\n\tmov\tal,80h\t\t; set the length to 0\n\tstosb\t\t\t; save it\n\t\n??len:\n\tmov\tebx,[lenoff]\t; get the offset of the length code\n\tcmp\t[BYTE PTR ebx],0BFh\t; see if its maxed out\n\tje\t??lenin1\t; if so put out a new len code\n\t\n??stolen:\n\tinc\t[BYTE PTR ebx] ; inc the count code\n\tlodsb\t\t\t; get the byte\n\tstosb\t\t\t; store it\n\tmov\t[DWORD PTR inlen],1\t; we are now in a length so save it\n\tjmp\tshort ??nxt\t; do the next code\n\t\n??longrun:\n\tmov\tal,0ffh\t\t; its a long so set a code of FF\n\tstosb\t\t\t; store it\n\t\n\tmov\teax,[count]\t; send out the count\n\tstosw\t\t\t; store it\n??medrunnxt:\n\tmov\teax,[matchoff] ; get the offset\n\tsub\teax,[a1stsrc]\t; make it relative tot he start of data\n??srunnxt:\n\tstosw\t\t\t; store it\n; this code common to all runs\n\tadd\tesi,[count]\t; add in the length of the run to the source\n\tmov\t[DWORD PTR inlen],0\t; set the in leght flag to false\n\t\n;=======================================================================\t\n\n??nxt:\n\tcmp\tesi,[end_of_data]\t\t; see if we did the whole pic\n\tjae\tshort ??out\t\t; if so, cool! were done\n\t\n\tjmp\t??loop\n\t\n??out:\n\tmov\tax,080h\t\t; remember to send an end of data code\n\tstosb\t\t\t; store it\n\tmov\teax,edi\t\t; get the last compressed address\n\tsub\teax,[a1stdest]\t; sub the first for the compressed size\n\n\n\tret\n\nENDP\tLCW_Compress\n\n\nEND\n\u001a"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/LCWUNCMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/misc/rcs/lcwuncmp.asm 1.1 1994/04/11 15:31:21 jeff_wilson Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library routine                          *\n;*                                                                         *\n;*                    File Name : UNCOMP.ASM                               *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : 20 August, 1990   [CY]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length);\t\t   *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL            C LCW_Uncompress          :NEAR\n\nCODESEG\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length);\n;\n; ----------------------------------------------------------------\n\n\n\nPROC\tLCW_Uncompress C near\n\n\tUSES ebx,ecx,edx,edi,esi\n\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tlength:DWORD\n;LOCALS\n\tLOCAL a1stdest:DWORD\n\tLOCAL maxlen:DWORD\n\tLOCAL lastbyte:DWORD\n\tLOCAL lastcom:DWORD\n\tLOCAL lastcom1:DWORD\n\n\n\tmov\tedi,[dest]\n\tmov\tesi,[source]\n\tmov\tedx,[length]\n\n;\n;\n; uncompress data to the following codes in the format b = byte, w = word\n; n = byte code pulled from compressed data\n;   Bit field of n\t\tcommand\t\tdescription\n; n=0xxxyyyy,yyyyyyyy\t\tshort run\tback y bytes and run x+3\n; n=10xxxxxx,n1,n2,...,nx+1\tmed length\tcopy the next x+1 bytes\n; n=11xxxxxx,w1\t\t\tmed run\t\trun x+3 bytes from offset w1\n; n=11111111,w1,w2\t\tlong copy\tcopy w1 bytes from offset w2\n; n=11111110,w1,b1\t\tlong run\trun byte b1 for w1 bytes\n; n=10000000\t\t\tend\t\tend of data reached\n;\n\n\tmov\t[a1stdest],edi\n\tadd\tedx,edi\n\tmov\t[lastbyte],edx\n\tcld\t\t\t; make sure all lod and sto are forward\n\tmov\tebx,esi\t\t; save the source offset\n\n??loop:\n\tmov\teax,[lastbyte]\n\tsub\teax,edi\t\t; get the remaining byte to uncomp\n\tjz\tshort ??out\t\t; were done\n\n\tmov\t[maxlen],eax\t; save for string commands\n\tmov\tesi,ebx\t\t; mov in the source index\n\n\txor\teax,eax\n\tmov\tal,[esi]\n\tinc\tesi\n\ttest\tal,al\t\t; see if its a short run\n\tjs\tshort ??notshort\n\n\tmov\tecx,eax\t\t;put count nibble in cl\n\n\tmov\tah,al\t\t; put rel offset high nibble in ah\n\tand\tah,0Fh\t\t; only 4 bits count\n\n\tshr\tcl,4\t\t; get run -3\n\tadd\tecx,3\t\t; get actual run length\n\n\tcmp\tecx,[maxlen]\t; is it too big to fit?\n\tjbe\tshort ??rsok\t\t; if not, its ok\n\n\tmov\tecx,[maxlen]\t; if so, max it out so it dosen't overrun\n\n??rsok:\n\tmov\tal,[esi]\t; get rel offset low byte\n\tlea\tebx,[esi+1]\t; save the source offset\n\tmov\tesi,edi\t\t; get the current dest\n\tsub\tesi,eax\t\t; get relative offset\n\n\trep\tmovsb\n\n\tjmp\t??loop\n\n??notshort:\n\ttest\tal,40h\t\t; is it a length?\n\tjne\tshort ??notlength\t; if not it could be med or long run\n\n\tcmp\tal,80h\t\t; is it the end?\n\tje\tshort ??out\t\t; if so its over\n\n\tmov\tcl,al\t\t; put the byte in count register\n\tand\tecx,3Fh\t\t; and off the extra bits\n\n\tcmp\tecx,[maxlen]\t; is it too big to fit?\n\tjbe\tshort ??lenok\t\t; if not, its ok\n\n\tmov\tecx,[maxlen]\t; if so, max it out so it dosen't overrun\n\n??lenok:\n\trep movsb\n\n\tmov\tebx,esi\t\t; save the source offset\n\tjmp\t??loop\n\n??out:\n      \tmov\teax,edi\n\tsub\teax,[a1stdest]\n\tjmp\t??exit\n\n??notlength:\n\tmov\tcl,al\t\t; get the entire code\n\tand\tecx,3Fh\t\t; and off all but the size -3\n\tadd\tecx,3\t\t; add 3 for byte count\n\n\tcmp\tal,0FEh\n\tjne\tshort ??notrunlength\n\n\txor\tecx,ecx\n\tmov\tcx,[esi]\n\n\txor\teax,eax\n\tmov\tal,[esi+2]\n\tlea\tebx,[esi+3]\t;save the source offset\n\n\tcmp\tecx,[maxlen]\t; is it too big to fit?\n\tjbe\tshort ??runlenok\t\t; if not, its ok\n\n\tmov\tecx,[maxlen]\t; if so, max it out so it dosen't overrun\n\n??runlenok:\n\ttest\tecx,0ffe0h\n\tjnz\t??dont_use_stosb\n\trep\tstosb\n\tjmp\t??loop\n\n\n??dont_use_stosb:\n\tmov\tah,al\n\tmov\tedx,eax\n\tshl\teax,16\n\tor\teax,edx\n\n\ttest\tedi,3\n\tjz\t??aligned\n\n\tmov\t[edi],eax\n\tmov\tedx,edi\n\tand\tedi,0fffffffch\n\tlea\tedi,[edi+4]\n\tand\tedx,3\n\tdec\tdl\n\txor\tdl,3\n\tsub\tecx,edx\n\n??aligned:\n\tmov\tedx,ecx\n\tshr\tecx,2\n\trep\tstosd\n\n\tand\tedx,3\n\tjz\t??loop\n\tmov\tecx,edx\n\trep\tstosb\n\tjmp\t??loop\n\n\n\n\n\n\n??notrunlength:\n\tcmp\tal,0FFh\t\t; is it a long run?\n\tjne\tshort ??notlong\t; if not use the code as the size\n\n\txor     ecx,ecx\n\txor\teax,eax\n\tmov\tcx,[esi]\t; if so, get the size\n\tlea\tesi,[esi+2]\n\n??notlong:\n\tmov\tax,[esi]\t;get the real index\n\tadd\teax,[a1stdest]\t;add in the 1st index\n\tlea\tebx,[esi+2]\t;save the source offset\n\tcmp\tecx,[maxlen]\t;compare for overrun\n\tmov\tesi,eax\t\t;use eax as new source\n\tjbe\tshort ??runok\t; if not, its ok\n\n\tmov\tecx,[maxlen]\t; if so, max it out so it dosen't overrun\n\n??runok:\n\ttest\tecx,0ffe0h\n\tjnz\t??dont_use_movsb\n\trep\tmovsb\n\tjmp\t??loop\n\n\n\n\n??dont_use_movsb:\n\tlea\tedx,[edi+0fffffffch]\n\tcmp\tesi,edx\n\tja\t??use_movsb\n\n\ttest\tedi,3\n\tjz\t??aligned2\n\n\tmov\teax,[esi]\n\tmov\t[edi],eax\n\tmov\tedx,edi\n\tand\tedi,0fffffffch\n\tlea\tedi,[edi+4]\n\tand\tedx,3\n\tdec\tdl\n\txor\tdl,3\n\tsub\tecx,edx\n\tadd\tesi,edx\n\n??aligned2:\n\tmov\tedx,ecx\n\tshr\tecx,2\n\tand\tedx,3\n\trep\tmovsd\n\tmov\tecx,edx\n??use_movsb:\n\trep\tmovsb\n\tjmp\t??loop\n\n\n\n\n??exit:\n\tmov\teax,edi\n\tmov\tebx,[dest]\n\tsub\teax,ebx\n\n\tret\n\nENDP\tLCW_Uncompress\n\n;***********************************************************\n\n\n\tEND\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/LIB.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./lib.c 1.16 1994/05/20 15:34:33 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library Routines                         *\n *                                                                         *\n *                    File Name : LIB.C                                    *\n *                                                                         *\n *                   Programmer : Scott Bowen                              *\n *                                                                         *\n *                   Start Date : January 14, 1993                         *\n *                                                                         *\n *                  Last Update : May 20, 1993   [PWG]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Add_Long_To_Pointer -- Pointer arithmatic when pointer could be XMS.  *\n *   Find_Argv -- Checks to see if string is in arguement              \t\t*\n *   Mono_Mem_Dump -- Dumps memory to mono monitor with hex and char.      *\n *   Convert_HSV_To_RGB -- Converts HSV cordinates to RGB values           *\n *   Convert_RGB_To_HSV -- Converts RGB to RSV coordinates.                *\n *   Set_Search_Drives -- Sets up the CDRom and HardDrive paths.           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include <dos.h>\n#include <stdio.h>\n#include <string.h>\n#include \"misc.h\"\n\n//PRIVATE unsigned Divide_With_Round(unsigned num, unsigned den);\n\n\n/***************************************************************************\n * Divide_With_Round -- Divides integers and round to nearest integer.     *\n *                                                                         *\n * INPUT:         int numberator.                                         *\n *                int denominator.                                        *\n *                                                                         *\n * OUTPUT:        Returns value rounded.                                   *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/13/1992  SB : Created.                                             *\n *=========================================================================*/\nstatic unsigned Divide_With_Round(unsigned num, unsigned den)\n{\n\t// return num/den + (0 ro 1).  1 if the remainder is more than half the denominator.\n\treturn( (num / den) + (unsigned)((num % den) >= ((den + 1) >> 1)) );\n}\n\n#define HSV_BASE 255 // This is used to get a little better persion on HSV conversion.\n#define RGB_BASE 63  // Not 64, this is really the max value.\n\n\n/***************************************************************************\n * Convert_RGB_To_HSV -- Converts RGB to RSV coordinates.                  *\n *                                                                         *\n * INPUT:      int r,g, and b values.                                     *\n *             int *h, *s, and *v pointers.                              \t*\n *                                                                         *\n * OUTPUT:     Assigns values to *h, *s, and *v.                           *\n *                                                                         *\n * WARNINGS:   The reason we use a different base for HSV then RGB is      *\n *             because we loose alot of persision by not using floating    *\n *             point.  Using the same base value (63) made it so that      *\n *             about 50% of the time one RGB value would be one different  *\n *             then the original if you went from RGB to HSV to RGB.       *\n *             Using 255 drop it down to about 9% of the time we get an    *\n *             off value.  To get it perfect, we would have to make the    *\n *             HSV base larger - but then you need to do all calculations  *\n *             in long instead of unsigned int.                                   *\n * HISTORY:                                                                *\n *   02/11/1992  SB : Created.                                             *\n *=========================================================================*/\nvoid Convert_RGB_To_HSV(unsigned int r, unsigned int g, unsigned int b, unsigned int *h, unsigned int *s, unsigned int *v)\n{\n \tunsigned int m, r1, g1, b1, tmp;\n\n\t// Convert RGB base to HSV base.\n\tr = Divide_With_Round((r * HSV_BASE), RGB_BASE);\n\tg = Divide_With_Round((g * HSV_BASE), RGB_BASE);\n\tb = Divide_With_Round((b * HSV_BASE), RGB_BASE);\n\n\t// Set hue to default.\n\t*h = 0;\n\n\t// Set v = Max(r,g,b) to find dominant primary color.\n\t*v = (r > g) ? r : g;\n\tif (b > *v) *v = b;\n\n\t// Set m = min(r,g,b) to find amount of white.\n\tm = (r < g) ? r : g;\n\tif (b < m) m = b;\n\n\t// Determine the normalized saturation.\n\tif (*v != 0) {\n\t\t*s = Divide_With_Round( (*v - m) * HSV_BASE ,*v);\n\t} else {\n\t\t*s = 0;\n\t}\n\n\tif (*s != 0) {\n\t\ttmp = *v - m;\n\t \tr1 = Divide_With_Round( (*v - r) * HSV_BASE, tmp);\n\t \tg1 = Divide_With_Round( (*v - g) * HSV_BASE, tmp);\n\t \tb1 = Divide_With_Round( (*v - b) * HSV_BASE, tmp);\n\n\t\t// Find effect of second most predominant color.\n\t\t// In which section of the hexagon of colors does the color lie?\n\t\tif ((*v) == r) {\n\t\t \tif (m == g) {\n\t\t\t\t*h = 5 * HSV_BASE + b1;\n\t\t\t} else {\n\t\t\t\t*h = 1 * HSV_BASE - g1;\n\t\t\t}\n\t\t} else {\n\t\t\tif ((*v) == g) {\n\t\t\t \tif (m == b) {\n\t\t\t\t\t*h = 1 * HSV_BASE + r1;\n\t\t\t\t} else {\n\t\t\t\t\t*h = 3 * HSV_BASE - b1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// *v == b\n\t\t\t \tif (m == r) {\n\t\t\t\t\t*h = 3 * HSV_BASE + g1;\n\t\t\t\t} else {\n\t\t\t\t\t\n\t\t\t\t\t*h = 5 * HSV_BASE - r1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Divide by six and round.\n\t\t*h = Divide_With_Round(*h, 6);\n\t}\n}\n\n/***************************************************************************\n * Convert_HSV_To_RGB -- Converts HSV cordinates to RGB values             *\n *                                                                         *\n * INPUT:      int h,s, and v coordinates                                 *\n *             int *r, *g, and *b pointers.                              \t*\n *                                                                         *\n * OUTPUT:     Assigns values to *r, *g, and *b.                           *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/11/1992  SB : Created.                                             *\n *=========================================================================*/\nvoid Convert_HSV_To_RGB(unsigned int h, unsigned int s, unsigned int v, unsigned int *r, unsigned int *g, unsigned int *b)\n{\n\tunsigned int i;\t\t\t\t// Integer part.\n\tunsigned int f;\t\t\t\t// Fractional or remainder part.  f/HSV_BASE gives fraction.\n\tunsigned int tmp;\t\t\t// Tempary variable to help with calculations.\n\tunsigned int values[7];\t// Possible rgb values.  Don't use zero.\n\n\n\th *= 6;\n\tf = h % HSV_BASE;\n\n\t// Set up possible red, green and blue values.\n\tvalues[1] =\t\n\tvalues[2] = v;\n\n\t//\n\t// The following lines of code change \n\t//\tvalues[3] = (v * (HSV_BASE - ( (s * f) / HSV_BASE) )) / HSV_BASE;\n\t//\tvalues[4] = values[5] = (v * (HSV_BASE - s)) / HSV_BASE;\n\t// values[6] = (v * (HSV_BASE - (s * (HSV_BASE - f)) / HSV_BASE)) / HSV_BASE;\n\t// so that the are rounded divides.\n\t//\n\n\ttmp = Divide_With_Round(s * f, HSV_BASE);\n\tvalues[3] = Divide_With_Round(v * (HSV_BASE - tmp), HSV_BASE);\n\n\tvalues[4] = \n\tvalues[5] = Divide_With_Round(v * (HSV_BASE - s), HSV_BASE);\n\n\ttmp = HSV_BASE - Divide_With_Round(s * (HSV_BASE - f),  HSV_BASE);\n\tvalues[6] = Divide_With_Round(v * tmp, HSV_BASE);\n\n\n\t// This should not be rounded.\n\ti = h / HSV_BASE;\n\n\ti += (i > 4) ? -4 : 2;\n\t*r = Divide_With_Round(values[i] * RGB_BASE, HSV_BASE);\n\n\ti += (i > 4) ? -4 : 2;\n\t*b = Divide_With_Round(values[i] * RGB_BASE, HSV_BASE);\n\n\ti += (i > 4) ? -4 : 2;\n\t*g = Divide_With_Round(values[i] * RGB_BASE, HSV_BASE);\n} \n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/LOAD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/wwlib32/file/rcs/load.cpp 1.4 1994/04/22 12:42:21 scott_bowen Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : LOAD.C                                   *\n *                                                                         *\n *                   Programmer : Christopher Yates                        *\n *                                                                         *\n *                  Last Update : September 17, 1993   [JLB]               *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Load_Uncompress -- Load and uncompress the given file.                *\n *   Uncompress_Data -- Uncompress standard CPS buffer.                    *\n *   Load_Data -- Loads a data file from disk.                             *\n *   Load_Alloc_Data -- Loads and allocates buffer for a file.             *\n *   Write_Data -- Writes a block of data as a file to disk.               *\n *   Uncompress_Data -- Uncompresses data from one buffer to another.      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"iff.h\"\n#include \"file.h\"\n#include <misc.h>\n#include <wwstd.h>\n#include <dos.h>\n#include <wwmem.h>\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * LOAD_DATA -- Loads a data file from disk.                               *\n *                                                                         *\n *    This routine will load a data file from disk.  It does no translation*\n *    on the data.                                                         *\n *                                                                         *\n * INPUT:   name  -- Pointer to ASCII filename of the data file.           *\n *                                                                         *\n *          ptr   -- Buffer to load the data file into.                    *\n *                                                                         *\n *          size  -- Maximum size of the buffer (in bytes).                *\n *                                                                         *\n * OUTPUT:  Returns with the number of bytes read.                         *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/24/1991 JLB : Created.                                             *\n *=========================================================================*/\nunsigned long __cdecl Load_Data(char const *name, void *ptr, unsigned long size)\n{\n\tint fd;\n\n\tfd = Open_File(name, READ);\n\tsize = Read_File(fd, ptr, size);\n\tClose_File(fd);\n\treturn(size);\n}\n\n\n/***************************************************************************\n * WRITE_DATA -- Writes a block of data as a file to disk.                 *\n *                                                                         *\n *    This routine will write a block of data as a file to the disk.  It   *\n *    is the compliment of Load_Data.                                      *\n *                                                                         *\n * INPUT:   name     -- Name of the file to create.                        *\n *                                                                         *\n *          ptr      -- Pointer to the block of data to write.             *\n *                                                                         *\n *          size     -- Size of the data block to be written.              *\n *                                                                         *\n * OUTPUT:  Returns with the number of bytes actually written.             *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/05/1992 JLB : Created.                                             *\n *=========================================================================*/\nunsigned long __cdecl Write_Data(char const *name, void *ptr, unsigned long size)\n{\n\tint fd;\n\n\tfd = Open_File(name, WRITE);\n\tsize = Write_File(fd, ptr, size);\n\tClose_File(fd);\n\treturn(size);\n}\n\n\n/***************************************************************************\n * LOAD_ALLOC_DATA -- Loads and allocates buffer for a file.               *\n *                                                                         *\n *    The routine will allocate a buffer and load the specified file into  *\n *    it.  The kind of memory used for the buffer is determined by the     *\n *    memory allocation flags passed in.                                   *\n *                                                                         *\n * INPUT:   name  -- Name of the file to load.                             *\n *                                                                         *\n *          flags -- Memory allocation flags to use when allocating.       *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the buffer that contains the file's  *\n *          data.                                                          *\n *                                                                         *\n * WARNINGS:   A memory error could occur if regular memory flags are      *\n *             specified.  If XMS memory is specified, then this routine   *\n *             could likely return NULL.                                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/28/1992 JLB : Created.                                             *\n *=========================================================================*/\nvoid * __cdecl Load_Alloc_Data(char const *name, MemoryFlagType flags)\n{\n\tint\tfd;\t\t// Working file handle.\n\tunsigned long\tsize;\t\t// Size of the file to load.\n\tvoid\t*buffer;\t// Buffer to hold the file.\n\n\tfd = Open_File(name, READ);\n\tsize = File_Size(fd);\n\tbuffer = Alloc(size, flags);\n\tif (buffer) {\n\t\tRead_File(fd, buffer, size);\n\t}\n\tClose_File(fd);\n\treturn(buffer);\n}\n\n\n/***************************************************************************\n * LOAD_UNCOMPRESS -- Load and uncompress the given file.                  *\n *                                                                         *\n * INPUT:      char *\t\t\t\t\t- file name to uncompress \t\t\t\t\t*\n *\t\t\t\t\tGraphicBufferClass&\t- to load the source data into\t\t\t*\n *\t\t\t\t\tGraphicBufferClass&\t- for the picture\t\t\t\t\t\t\t\t*\n *             void *\t\t\t\t\t- ptr for header uncompressed data     *\n *                                                                         *\n * OUTPUT:     unsigned long size of uncompressed data                             *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/28/1991  CY : Created.                                             *\n *   06/26/1991 JLB : Handles load & uncompress to same buffer.            *\n *=========================================================================*/\nunsigned long __cdecl Load_Uncompress(char const *file, BufferClass& uncomp_buff, BufferClass& dest_buff, void *reserved_data)\n{\n\tint\tfd;\t\t\t\t// Source file handle.\n\tunsigned int\tisize=0;\t\t\t// Size of the file.\n\tunsigned int\tskipsize;\t\t// Size of the skip data bytes.\n\tvoid\t*uncomp_ptr;\t//\tSource buffer pointer.\n\tchar\t*newuncomp_ptr;\t// Adjusted source pointer.\n\n\n\tuncomp_ptr = uncomp_buff.Get_Buffer();\t\t// get a pointer to buffer\n\n\t/*======================================================================*/\n\t/* Read the file into the uncompression buffer.\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\n\tfd = Open_File(file, READ);\t\t\t\t\t// Open up the file to read from\n\tRead_File(fd, (char *) &isize,\t2L);\t\t// Read the file size\n\tRead_File(fd, uncomp_ptr, \t\t\t8L);\t\t// Read the header bytes in.\n\tisize -= 8; \t\t\t\t\t\t\t\t\t\t// Remaining data in file.\n\n\t/*======================================================================*/\n\t/* Check for and read in the skip data block.\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\n\tskipsize = *(((short *)uncomp_ptr) + 3);\n\n\tif (reserved_data && skipsize) {\n\t\tRead_File(fd, reserved_data, (unsigned long) skipsize);\n\t} else {\n\t\tSeek_File(fd, skipsize, SEEK_CUR);\n\t}\n\n\t*( ((short *)uncomp_ptr+3) )\t = 0;\t\t\t\t// K/O any skip value.\n\tisize \t\t\t\t\t\t\t-= skipsize;\n\n\t/*======================================================================*/\n\t/*\tIf the source and dest buffer are the same, we adjust the pointer so */\n\t/* that the compressed data is loaded into the end of the buffer.  In \t*/\n\t/* this way the uncompress code can write to the same buffer.\t\t\t\t*/\n\t/*======================================================================*/\n\tnewuncomp_ptr = (char *)Add_Long_To_Pointer(uncomp_buff.Get_Buffer(), uncomp_buff.Get_Size() - (isize+8L));\n\n\t/*======================================================================*/\n\t/*\tDuplicate the header bytes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tMem_Copy(uncomp_ptr,newuncomp_ptr,8);\n\n\t/*======================================================================*/\n\t/*\tRead in the main compressed part of the file.\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tRead_File(fd, newuncomp_ptr + 8, (unsigned long)isize);\n\tClose_File(fd);\n\n\t/*======================================================================*/\n\t/* Uncompress the file into the destination buffer (which may very well\t*/\n\t/*\t\tbe the source buffer).\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\treturn(Uncompress_Data(newuncomp_ptr, dest_buff.Get_Buffer()));\n}\n#if(0)\n/***************************************************************************\n * LOAD_UNCOMPRESS -- Load and uncompress the given file.                  *\n *                                                                         *\n * INPUT:      char *file name to uncompress, BuffType uncomp_buff to load *\n *             the source data into, BuffType dest_buff for the picture,   *\n *             void *reserved_data pointer for header uncompressed data    *\n *                                                                         *\n * OUTPUT:     unsigned long size of uncompressed data                             *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/28/1991  CY : Created.                                             *\n *   06/26/1991 JLB : Handles load & uncompress to same buffer.            *\n *=========================================================================*/\nunsigned long __cdecl Load_Uncompress(char const *file, BuffType uncomp_buff, BuffType dest_buff, void *reserved_data)\n{\n\tint\tfd;\t\t\t\t// Source file handle.\n\tunsigned int\tisize;\t\t\t// Size of the file.\n\tunsigned int\tskipsize;\t\t// Size of the skip data bytes.\n\tvoid\t*uncomp_ptr;\t//\tSource buffer pointer.\n\tchar\t*newuncomp_ptr;\t// Adjusted source pointer.\n\n\n\tuncomp_ptr = Get_Buff(uncomp_buff);\t\t/* Get pointer to uncomp buffer */\n\n\t/* Read the file into the uncomp_buff */\n\n\tfd = Open_File(file, READ);\n\tRead_File(fd, (char *) &isize, 2L);\t\t\t\t/* Read the file size \t\t*/\n\t#if(AMIGA)\n\t\tisize = Reverse_Word(isize);\n\t#endif\n\n\tRead_File(fd, uncomp_ptr, 8L);\t\t// Read the header bytes in.\n\tisize -= 8; \t\t\t\t\t\t\t\t// Remaining data in file.\n\n\t/*\n\t**\tCheck for and read in the skip data block.\n\t*/\n\n\tskipsize = *(((short*)uncomp_ptr) + 3);\n\t#if(AMIGA)\n\t\tskipsize = Reverse_Word(skipsize);\n\t#endif\n\n\tif (reserved_data && skipsize) {\n\t\tRead_File(fd, reserved_data, (unsigned long) skipsize);\n\t} else {\n\t\tSeek_File(fd, skipsize, SEEK_CUR);\n\t}\n\t*( ((short *)uncomp_ptr+3) ) = 0;\t\t// K/O any skip value.\n\tisize -= skipsize;\n\n\t/*\n\t**\tIf the source and dest buffer are the same, we\n\t**\tadjust the pointer so that the compressed data is\n\t**\tloaded into the end of the buffer.  In this way the\n\t**\tuncompress code can write to the same buffer.\n\t*/\n\t#if(IBM)\n\t\tnewuncomp_ptr = (char *)Add_Long_To_Pointer(Get_Buff(uncomp_buff), PageArraySize[uncomp_buff] - (isize+8L));\n\t#else\n\t\tnewuncomp_ptr = Get_Buff(uncomp_buff);\n\t\tnewuncomp_ptr += PageArraySize[uncomp_buff] - ((isize+10) & 0xFFFE);\n\t#endif\n\n\t/*\n\t**\tDuplicate the header bytes.\n\t*/\n\tMem_Copy(uncomp_ptr,newuncomp_ptr,8);\n\n\t/*\n\t**\tRead in the main compressed part of the file.\n\t*/\n\tRead_File(fd, newuncomp_ptr + 8, (unsigned long)isize);\n\tClose_File(fd);\n\n\treturn(Uncompress_Data(newuncomp_ptr, Get_Buff(dest_buff)));\n}\n\n#endif\n/***************************************************************************\n * Uncompress_Data -- Uncompresses data from one buffer to another.        *\n *                                                                         *\n *    This routine takes data from a compressed file (sans the first two   *\n *    size bytes) and uncompresses it to a destination buffer.  The source *\n *    data MUST have the CompHeaderType at its start.                      *\n *                                                                         *\n * INPUT:   src   -- Source compressed data pointer.                       *\n *                                                                         *\n *          dst   -- Destination (paragraph aligned) pointer.              *\n *                                                                         *\n * OUTPUT:  Returns with the size of the uncompressed data.                *\n *                                                                         *\n * WARNINGS:   If LCW compression is used, the destination buffer must     *\n *             be paragraph aligned.                                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/17/1993 JLB : Created.                                             *\n *=========================================================================*/\nunsigned long __cdecl Uncompress_Data(void const *src, void *dst)\n{\n\tunsigned int\t\t\t\t\tskip;\t\t\t// Number of leading data to skip.\n\tCompressionType\tmethod;\t\t// Compression method used.\n\tunsigned long\t\t\t\t\tuncomp_size=NULL;\n\n\tif (!src || !dst) return(NULL);\n\n\t/*\n\t**\tInterpret the data block header structure to determine\n\t**\tcompression method, size, and skip data amount.\n\t*/\n\tuncomp_size = ((CompHeaderType*)src)->Size;\n\t#if(AMIGA)\n\t\tuncomp_size = Reverse_Long(uncomp_size);\n\t#endif\n\tskip = ((CompHeaderType*)src)->Skip;\n\t#if(AMIGA)\n\t\tskip = Reverse_Word(skip);\n\t#endif\n\tmethod = (CompressionType) ((CompHeaderType*)src)->Method;\n\tsrc = Add_Long_To_Pointer((void *)src, (long)sizeof(CompHeaderType) + (long)skip);\n\n\tswitch (method) {\n\n\t\tdefault:\n\t\tcase NOCOMPRESS:\n\t\t\tMem_Copy((void *) src, dst, uncomp_size);\n\t\t\tbreak;\n\n\t\tcase HORIZONTAL:\n#if LIB_EXTERNS_RESOLVED\n\t\t\tRLE_Uncompress((void *) src, dst, uncomp_size);\n#endif\n\t\t\tbreak;\n\n\t\tcase LCW:\n\t\t\tLCW_Uncompress((void *) src, (void *) dst, (unsigned long) uncomp_size);\n\t\t\tbreak;\n\n\t}\n\n\treturn(uncomp_size);\n}\n\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/LOADFONT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : LOADFONT.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : September 6, 1991                        *\n *                                                                         *\n *                  Last Update : June 27, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Load_Font -- Loads a font from disk.                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"font.h\"\n#include <file.h>\n#include <wwmem.h>\n#include <wwstd.h>\n\n#if(IBM)\n#include <fcntl.h>\n#include <io.h>\n\n#include <errno.h>\n\nint FontXSpacing = 0;\nint FontYSpacing = 0;\nvoid const *FontPtr = NULL;\nchar FontWidth  = 8;\nchar FontHeight = 8;\n\n// only font.c and set_font.c use the following\nchar *FontWidthBlockPtr = NULL;\n\n\n\n/***************************************************************************\n * LOAD_FONT -- Loads a font from disk.                                    *\n *                                                                         *\n *    This loads a font from disk.  This function must be called as a    \t*\n *    precursor to calling Set_Font().  You need only call this function \t*\n *    once per desired font at the beginning of your code, but AFTER     \t*\n *    Prog_Init() is called.                                             \t*\n *                                                                         *\n * INPUT:      name  - Pointer to font name to use (eg. \"topaz.font\")    \t*\n *                                                                       \t*\n *             fontsize - Size in points of the font loaded.             \t*\n *                                                                       \t*\n * OUTPUT:     Pointer to font data or NULL if unable to load.           \t*\n *                                                                       \t*\n * WARNINGS:   Some system memory is grabbed by this routine.            \t*\n *                                                                       \t*\n * HISTORY:                                                                *\n *   4/10/91    BS  : 2.0 compatibily                                     \t*\n *   6/09/91    JLB : IBM and Amiga compatability.                        \t*\n *   11/27/1991 JLB : Uses file I/O routines for disk access.              *\n *   01/29/1992 DRD : Modified to use new font format.                     *\n *   02/01/1992 DRD : Added font file verification.                        *\n *   06/29/1994 SKB : modified for 32 bit library                          *\n *=========================================================================*/\nvoid * __cdecl Load_Font(char const *name)\n{\n\tchar\tvalid;\n\tint\t\tfh;\t\t// DOS file handle for font file.\n\tunsigned short\tsize;\t\t// Size of the data in the file (-2);\n\tchar\t*ptr = NULL;\t\t// Pointer to newly loaded font.\n\n\n\n\tfh=Open_File(name,READ);\n\tif ( fh>=0 ){\n\t\tif ( Read_File(fh, (char *) &size, 2) != 2) return(NULL);\n\n\t\tptr = (char *) Alloc(size , MEM_NORMAL );\n\t\t*(short *)ptr = size;\n\t\tRead_File(fh, ptr + 2, size - 2);\n\t\tClose_File(fh);\n\t} else {\n\t\treturn ((void*)errno);\n\t}\n\n\n\n#ifdef cuts\n\tif (Find_File(name)) {\n\t\tfh = Open_File(name, READ);\n\t\tif (Read_File(fh, (char *) &size, 2) != 2) return(NULL);\n\n\t\tptr = (char *) Alloc(size, MEM_NORMAL);\n\t\t*(short *)ptr = size;\n\t\tRead_File(fh, ptr + 2, size - 2);\n\t\tClose_File(fh);\n\t} else {\n\t\treturn (NULL);\n\t}\n#endif\n\n\t//\n\t// verify that the file loaded is a valid font file.\n\t//\n\n\tvalid = FALSE;\n\tif (*(ptr + 2) == 0) {\t\t// no compression\n\t\tif (*(ptr + 3) == 5) {\t\t// currently only 5 data blocks are used.\n\t\t\tvalid = TRUE;\n\t\t}\n\t}\n\n\tif ( !valid ) {\n\t\treturn (NULL);\n\t}\n\n   return(ptr);\n}\n\n#endif\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/LOADPAL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Load_Palette                             *\n *                                                                         *\n *                    File Name : LOADPAL.CPP                              *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 25, 1994                           *\n *                                                                         *\n *                  Last Update : April 27, 1994   [BR]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Note: This module contains dependencies upon the file I/O system,\t\t\t*\n * specifically Load_Data().\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *\t  Load_Palette -- Loads a palette file into the given palette buffer.\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n/*\n********************************* Includes **********************************\n*/\n#include <wwstd.h>\n#include \"wwstd.h\"\n#include \"iff.h\"\n#include \"palette.h\"\n\n/*\n********************************* Constants *********************************\n*/\n\n/*\n********************************** Globals **********************************\n*/\n\n/*\n******************************** Prototypes *********************************\n*/\n\n/***************************************************************************\n *\tLoad_Palette -- Loads a palette file into the given palette buffer.\t\t*\n *                                                                         *\n * INPUT:      \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tBYTE * file_name \t\t\t- name of the file to load.\t\t\t\t\t\t*\n *\t\tBYTE * palette_pointer\t- pointer to palette buffer.\t      \t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:     \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tnone                                                        \t\t\t*\n *                                                                         *\n * WARNINGS:   \t                                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/20/1991 BS : Created.                                              *\n *   04/27/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nvoid __cdecl Load_Palette(char *palette_file_name, void *palette_pointer)\n{\n\t#if(IBM)\n\t\tLoad_Data(palette_file_name, palette_pointer, 768);\n\t#else\n\t\tLoad_Data(palette_file_name, palette_pointer, (ULONG)(2<<BIT_PLANES));\n\t#endif\n}\n\n/**************************** End of loadpal.cpp ***************************/\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/LOADPCX.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : IFF                                      *\n *                                                                         *\n *                    File Name : LOADPCX.CPP                              *\n *                                                                         *\n *                   Programmer : Julio R. Jerez                           *\n *                                                                         *\n *                   Start Date : May 2, 1995                              *\n *                                                                         *\n *                  Last Update : May 3, 1995   [JRJ]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * GraphicBufferClass* Read_PCX_File (char* name, void *Buff, long size ); *\n * int Get_PCX_Palette (char * name, void& palette )\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include  <wwlib32.h>\n#include \"filepcx.h\"\n\n/***************************************************************************\n * READ_PCX_FILE -- read a pcx file into a Graphic Buffer                  *\n *                                                                         *\n *\tGraphicBufferClass* Read_PCX_File (char* name, char* palette ,void *Buff, long size );\t*\n *  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT: name is a NULL terminated string of the fromat [xxxx.pcx]        *\n *        palette is optional, if palette != NULL the the color palette of *\n *\t\t\t\t\t the pcx file will be place in the memory block pointed\t   *\n *               by palette.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t Buff is optinal, if Buff == NULL a new memory Buffer\t\t \t\t\t*\n *\t\t\t\t\t will be allocated, otherwise the file will be placed \t\t*\n *\t\t\t\t\t at location pointd by Buffer;\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tSize is the size in bytes of the memory block pointed by Buff\t\t*\n *\t\t\t\t  is also optional;\n *                                                                         *\n * OUTPUT: on succes a pointer to a GraphicBufferClass cointaining the     *\n *         pcx file, NULL othewise.                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1995 JRJ : Created.                                             *\n *=========================================================================*/\n\n#define\tPOOL_SIZE 2048\n#define\tREAD_CHAR()  *file_ptr++ ; \\\n\t\t\t\t\t\t\t if ( file_ptr\t>= & pool [ POOL_SIZE ]\t) { \\\n\t\t\t\t\t\t\t\t Read_File ( file_handle, pool , POOL_SIZE ) ; \\\n\t\t\t\t\t\t\t\t file_ptr = pool ; \\\n\t\t\t\t\t\t\t }\n\n\nGraphicBufferClass* Read_PCX_File(char* name, char* Palette, void *Buff, long Size)\n{\n  unsigned     i , j ;\n  unsigned     rle ;\n  unsigned     color ;\n  unsigned\t\tscan_pos ;\n  char\t\t * file_ptr ;\n  int\t\t\t\twidth\t;\n  int\t\t\t\theight ;\n  int \t      file_handle ;\n  char\t\t * buffer ;\n  PCX_HEADER   header ;\n  RGB  \t\t * pal ;\n  char \t\t\tpool [ POOL_SIZE ] ;\n  GraphicBufferClass * pic\t;\n\n  // Open file name\n  file_handle = Open_File ( name , READ ) ;\n  if ( file_handle == WW_ERROR ) return NULL ;\n\n  Read_File ( file_handle, & header , sizeof (PCX_HEADER)) ;\n  if ( header.id != 10 &&  header.version != 5 &&\n\t   header.pixelsize != 8 ) return NULL ;\n\n  width = header.width - header.x + 1 ;\n  height = header.height - header.y + 1 ;\n\n  if ( Buff ) {\n\t  buffer = ( char * ) Buff;\n\t  i = Size / width;\n\t  height = MIN ( i - 1, height);\n\t  pic = new GraphicBufferClass( width, height, buffer ,Size);\n\t  if ( !(pic && pic->Get_Buffer()))return NULL ;\n  } else {\n\t  pic = new GraphicBufferClass( width, height, NULL, width*(height+4));\n\t  if ( !(pic && pic->Get_Buffer()))return NULL ;\n  }\n\n  buffer = (char *) pic->Get_Buffer() ;\n  file_ptr = pool ;\n  Read_File ( file_handle, pool , POOL_SIZE ) ;\n\n  if ( header.byte_per_line != width )\n\t for ( scan_pos = j = 0 ; j < height ; j ++, scan_pos += width ) {\n      for ( i = 0 ; i < width ; ) {\n\t\t\t\t rle = READ_CHAR ();\n\t\t\t\t if ( rle > 192 ) {\n\t\t\t\t rle -= 192 ;\n\t\t\t\t color =\tREAD_CHAR (); ;\n\t\t \t\t memset ( buffer + scan_pos + i , color , rle ) ;\n\t\t \t\t i += rle ;\n\t        } else * ( buffer + scan_pos + i ++ ) = (char)rle ;\n\t    }\n\t\t if ( i == width )\n\t\t rle = READ_CHAR () ;\n//\t\t if ( rle > 192 ) rle = READ_CHAR ();\n    }\n\n\n  else for ( i = 0 ; i < width * height ; ) {\n\t\trle = READ_CHAR ();\n\t\trle &= 0xff;\n\t\tif ( rle > 192 ) {\n\t      rle -= 192 ;\n\t      color = READ_CHAR ();\n\t\t\tmemset ( buffer + i , color , rle ) ;\n\t      i += rle ;\n\t    }\telse * ( buffer + i ++ ) = (char)rle ;\n  }\n\n if ( Palette ) {\n\t  //Seek_File ( file_handle , - 256 * sizeof ( RGB ) , SEEK_END ) ;\n\t  Seek_File ( file_handle , 256 * sizeof ( RGB ) , SEEK_END ) ;\n\t  Read_File ( file_handle,\tPalette , 256L * sizeof ( RGB )) ;\n\n\t  pal = ( RGB * ) Palette ;\n\t  for ( i = 0 ; i < 256 ; i ++ ) {\n\t\t pal -> red >>= 2 ;\n\t\t pal -> green >>= 2 ;\n\t\t pal -> blue >>= 2 ;\n\t\t pal ++ ;\n\t  }\n  }\n Close_File (file_handle) ;\n return pic ;\n}\n\n/***************************************************************************\n * READ_PCX_FILE -- read a pcx file into a Graphic Buffer                  *\n *                                                                         *\n *\tGraphicBufferClass* Read_PCX_File (char* name, BufferClass& Buff,\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  char* palette)\t*\t\t\t*\n *  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT: name is a NULL terminated string of the fromat [xxxx.pcx]        *\n *\t\t\t Buff is a pointer to a BufferClass the will hold the pcx file \t*\n *\t\t\t\t\t at location pointd by Buffer;\t\t\t\t\t\t\t\t\t\t*\n *        palette is optional, if palette != NULL the the color palette of *\n *\t\t\t\t\t the pcx file will be place in the memory block pointed\t   *\n *               by palette.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT: on succes a pointer to a GraphicBufferClass cointaining the     *\n *         pcx file, NULL othewise.                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1995 JRJ : Created.                                             *\n *=========================================================================*/\n\nGraphicBufferClass* Read_PCX_File (char* name, BufferClass& Buff,char* palette)\n{\n  return Read_PCX_File(name, palette, (void*)Buff.Get_Buffer(), Buff.Get_Size());\n}"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/LOADPICT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/wwlib32/file/rcs/loadpict.cpp 1.1 1994/04/20 14:38:08 scott_bowen Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : IFFEXTRA.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : June 11, 1991                            *\n *                                                                         *\n *                  Last Update : April 20, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   ILBM_To_Amiga -- Convert ILBM to bitplane Amiga format.               *\n *   ILBM_To_MCGA -- Converts ILBM picture into MCGA format.               *\n *   PBM_To_Amiga -- Converts a PBM picture into Amiga format.             *\n *   Load_Picture -- Loads a picture file (CPS or LBM format).             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"iff.h\"\n#include \"file.h\"\n#include <wwmem.h>\t// For Alloc.\n\n#if(IBM)\n#include <mem.h>\n#endif\n\n// Since we are not currently using AMIGA, this has been put in to\n// give us back some code space.  If it is needed for a utility,\n// this module should be recompiled with that utility and set the\n// define to TRUE.\n#define\tMAKE_AMIGA_ART\tFALSE\n\n/*\n** An IFF picture file can have one of two formats:\n**\tILBM\t- InterLeaved Bit Map\n**\tPBM\t- Packed Bit Map\n*/\ntypedef enum {\n\tFORM_ILBM,\n\tFORM_PBM\n} IFFForm_Type;\n\n/*\n**\tThese are the various chunks that compose an IFF picture file.\n*/\n#define ID_FORM\t\t\tMAKE_ID('F','O','R','M')\n#define ID_ILBM\t\t\tMAKE_ID('I','L','B','M')\n#define ID_PBM \t\t\tMAKE_ID('P','B','M',' ')\n#define ID_CMAP \t\t\tMAKE_ID('C','M','A','P')\n#define ID_BODY \t\t\tMAKE_ID('B','O','D','Y')\n#define ID_BMHD \t\t\tMAKE_ID('B','M','H','D')\n\n\n/*\n**\tThe BMHD (Bit Map HeaDer) chunk in an IFF picture file contains the\n**\tinformation necessary to extract that picture from the BODY chunk.\n**\tIt also indicates the size and depth of the source art.\n*/\ntypedef struct {\n\tunsigned short\tW, H;\t\t\t\t// Raster width and height in pixels.\n\tshort \tX, Y;\t\t\t\t\t\t// Pixel postion for this image.\n\tchar\tBPlanes;\t\t\t\t\t\t// Number of bitplanes.\n\tunsigned char\tMasking;\t\t\t// Masking control byte.\n\t\t\t\t\t\t\t\t\t\t\t// 0 = No masking.\n\t\t\t\t\t\t\t\t\t\t\t//\t1 = Has a mask.\n\t\t\t\t\t\t\t\t\t\t\t//\t2 = Has transparent color.\n\t\t\t\t\t\t\t\t\t\t\t//\t3 = Lasso.\n\tunsigned char\tCompression;\t// Compression method.\n\t\t\t\t\t\t\t\t\t\t\t// 0 = No compression.\n\t\t\t\t\t\t\t\t\t\t\t// 1 = Byte run compression.\n\tchar\tpad;\n\tunsigned short\tTransparent;\t// Transparent color number.\n\tunsigned char\tXAspect,\t\t\t// Pixel aspect ratio of source art.\n\t\t\tYAspect;\n\tshort\tPageWidth, \t\t\t\t\t// Source 'page' size in pixels.\n\t\t\tPageHeight;\n} BitMapHeader_Type;\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE void __cdecl ILBM_To_MCGA(BufferClass& src, BufferClass& dest, int planes);\nPRIVATE void __cdecl ILBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes);\nPRIVATE void __cdecl PBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes);\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n/***************************************************************************\n * ILBM_TO_MCGA -- Converts ILBM picture into MCGA format.                 *\n *                                                                         *\n *    This converts an ILBM picture (typical of DPaint LBM files) and      *\n *    converts it to MCGA mode (byte per pixel).  This function would be   *\n *    used after the body of an ILBM picture is loaded.  Because the       *\n *    number of bitplanes can vary greatly, it is necessary to pass the    *\n *    bitplane count to this function.  The size (320 by 200) of the       *\n *    source picture is presumed.                                          *\n *                                                                         *\n * INPUT:   src   - Buffer number for source ILBM picture.                 *\n *                                                                         *\n *          dest  - Buffer number for place to put MCGA format.            *\n *                                                                         *\n *          planes- The number of bitplanes in the ILBM picture.           *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1991 JLB : Created.                                             *\n *   04/20/1994 SKB : Update to 32 bit library and make private.           *\n *=========================================================================*/\nPRIVATE void __cdecl ILBM_To_MCGA(BufferClass& src, BufferClass& dest, int planes)\n{\n\tchar\t*source;\t\t\t// Source pointer.\n\tchar\t*destination;\t// Destination pointer.\n\tint\tindex,j,i;\t\t// Working index values.\n\tint\tbplane;\t\t\t// Bit plane counter.\n\tchar\tbytes[8];\t\t// Byte array holding max bitplanes (8).\n\tchar\tvalue;\t\t\t// Composed byte(pixel) value.\n\n\tsource = (char *) src.Get_Buffer();\n\tdestination = (char *) dest.Get_Buffer();\n\n\tmemset(bytes, '\\0', 8);\t// Makes sure upper bits will be clear.\n\n\t// Each row is grouped and processed together.\n\n\tfor (index = 0; index < 200 /*bmhd.H*/; index++) {\n\n\t\t// Process each line in groups of 8 bytes.\n\n\t\tfor (j = 0; j < 40 /*(bmhd.W>>3)*/; j++) {\n\n\t\t\t// Get the bitplane bytes.\n\n\t\t\tfor (bplane = 0; bplane < planes /*bmhd.BPlanes*/; bplane++) {\n\t\t\t\tbytes[bplane] = *(source + (bplane * 40 /*(bmhd.W>>3)*/));\n\t\t\t}\n\t\t\tsource++;\n\n\t\t\t// Roll the bits out to create 8 pixels (by bytes).\n\t\t\tfor (i = 0; i < 8; i++) {\n\n\t\t\t\t// 8 bits per byte.\n\t\t\t\tvalue = 0;\n\t\t\t\tfor (bplane = planes - 1/*bmhd.BPlanes-1*/; bplane >= 0; bplane--) {\n\t\t\t\t\tvalue <<= 1;\t\t\t// Make room for next bit.\n\t\t\t\t\tif (bytes[bplane] & 0x80) value |= 1;\t// Set the bit.\n\t\t\t\t\tbytes[bplane] <<= 1;\n\t\t\t\t}\n\t\t\t\t*destination++ = value;\t// Output the pixel byte.\n\t\t\t}\n\t\t}\n\n\t\t// Advance to next scan line.\n\t\tsource += 40 /* (bmhd.W >> 3)*/ * (planes /* bmhd.BPlanes */ - 1);\n\t}\n}\n\n\n/***************************************************************************\n * ILBM_TO_AMIGA -- Convert ILBM to bitplane Amiga format.                 *\n *                                                                         *\n *    This converts an InterLeaved BitMap picture into Amiga bitplane      *\n *    format (8K per bitplane).  The data of an ILBM picture is controlled *\n *    by the number of bitplanes it contains.  The bitplane count is       *\n *    passed into this program.                                            *\n *                                                                         *\n * INPUT:   src   - Buffer number for source ILBM picture data.            *\n *                                                                         *\n *          dest  - Buffer number for destination Amiga picture data.      *\n *                                                                         *\n *          planes- The number of bitplanes in the source ILBM data.       *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   The amount of data placed into the destination buffer is    *\n *             controlled by the number of bitplanes specified.  It is     *\n *             8000 per bitplane.                                          *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/20/1991 JLB : Created.                                             *\n *   04/20/1994 SKB : Update to 32 bit library and make private.           *\n *   04/20/1994 SKB : #if out for main library.  Only used in utils maybe. *\n *=========================================================================*/\n#if MAKE_AMIGA_ART\nPRIVATE void __cdecl ILBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes)\n{\n\tint\trow;\t\t\t// Working row counter.\n\tint\tbp;\t\t\t// Working bitplane counter.\n\tchar\t*srcptr,\t\t// Source buffer pointer.\n\t\t\t*dstptr;\t\t// Destination buffer pointer.\n\n\tsrcptr = (char *) src.Get_Buffer();\t\t// Source buffer pointer.\n\tdstptr = (char *) dest.Get_Buffer();\t// Destination buffer pointer.\n\n\tfor (row = 0; row < 200; row++) {\n\t\tfor (bp = 0; bp < planes; bp++) {\n\t\t\tMem_Copy(srcptr,dstptr+(8000*bp),40);\n\t\t\tsrcptr += 40;\n\t\t}\n\t\tdstptr += 40;\n\t}\n}\n#endif\n\n\n/***************************************************************************\n * PBM_TO_AMIGA -- Converts a PBM picture into Amiga format.               *\n *                                                                         *\n *    This converts a PBM (Packed Bit Map) MCGA picture into Amiga         *\n *    bitplane format.  A PBM picture presumes 8 bitplanes, but this       *\n *    can be controlled by the 'plane' parameter passed in.                *\n *                                                                         *\n * INPUT:   src   - Buffer number for the source PBM data.                 *\n *                                                                         *\n *          dest  - Buffer number to place the Amiga format picture.       *\n *                                                                         *\n *          planes- The number of bitplanes to extract from the PBM source *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   The amount of data placed into the destination buffer is    *\n *             controlled by the number of bitplanes specified.  It is     *\n *             8000 per bitplane.                                          *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/20/1991 JLB : Created.                                             *\n *   04/20/1994 SKB : Update to 32 bit library and make private.           *\n *   04/20/1994 SKB : #if out for main library.  Only used in utils maybe. *\n *=========================================================================*/\n#if MAKE_AMIGA_ART\nPRIVATE void __cdecl PBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes)\n{\n\tint\trow,\t\t\t\t\t\t\t// Working row counter.\n\t\t\tcol,\t\t\t\t\t\t\t// Working column (by byte) counter.\n\t\t\tbit;\t\t\t\t\t\t\t// Working bitplane counter.\n\tunsigned char\t*destptr,\t\t// Destination byte pointer.\n\t\t\t\t\t\t*srcptr;\t\t\t// Source byte pointer.\n\tunsigned char\tvalue;\t\t\t// Working input MCGA pixel number.\n\n\n\tdestptr = (unsigned char *) dest.Get_Buffer();\n\tsrcptr = (unsigned char *) src.Get_Buffer();\n\n\tmemset(destptr, 0, 32000);\n\tmemset(destptr+32000, 0, 32000);\n\n\tfor (row = 0; row < 200; row++) {\n\n\t\tfor (col = 0; col < 320; col++) {\n\t\t\tvalue = *srcptr++;\n\n\t\t\tfor (bit = 0; bit < planes; bit++) {\n\t\t\t\tif (value & (0x01 << bit)) {\n\t\t\t\t\tdestptr[(short)((8000L * (long)bit) + (col>>3))] |= 0x80 >> (col & 0x07);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tdestptr += 40;\n\t}\n}\n#endif\n\n/***************************************************************************\n * LOAD_PICTURE -- Loads a picture file (CPS or LBM format).               *\n *                                                                         *\n *    This loads a picture file into a page buffer.  The loaded file will  *\n *    be in MCGA or Amiga mode as requested.  Supported source formats     *\n *    are CPS or all forms of IFF dpaint files.                            *\n *                                                                         *\n * INPUT:   filename    - Source filename.  The only files that are        *\n *                        processed as IFF are those files that end with   *\n *                        \".LBM\".                                          *\n *                                                                         *\n *          loadbuf     - Buffer type number for the temporary loading     *\n *                        buffer.  It will be trashed.                     *\n *                                                                         *\n *          destbuf     - Buffer type number for the picture to be placed. *\n *                                                                         *\n *          palette     - Palette buffer pointer.  If this value is NULL   *\n *                        then no palette is loaded.                       *\n *                                                                         *\n *          format      - Desired destination format.                      *\n *                      BM_AMIGA - Destination buffer will contain the     *\n *                                 picture in bitplane format (Amiga).     *\n *                                 The buffer will contain data equal to   *\n *                                 8K times the number of bit planes.      *\n *                                                                         *\n *                      BM_MCGA  - Destination buffer will contain the     *\n *                                 picture in MCGA format (byte per pixel).*\n *                                 The buffer will be 64K in size.         *\n *                                                                         *\n * OUTPUT:  int number of bitplanes read into the dest buffer\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1991 JLB : Created.                                             *\n *   05/20/1991 JLB : Handles Amiga and IBM destination formats.           *\n *=========================================================================*/\nint __cdecl Load_Picture(char const *filename, BufferClass& scratchbuf, BufferClass& destbuf, unsigned char *palette, PicturePlaneType format)\n{\n\tint\tfh;\t\t\t\t\t\t// Input file handle.\n\tlong\tifftype;\t\t\t\t\t// Iff form type.\n\tint\tcounter;\t\t\t\t\t// Count of the bytes decompressed.\n\tint\tvalue;\t\t\t\t\t// Working compression code value.\n\tint\tlen;\t\t\t\t\t\t// int sized length value.\n\tint\tindex;\t\t\t\t\t// Working index values.\n\tBitMapHeader_Type\tbmhd;\t\t// BMHD chunk data.\n\tIFFForm_Type\t   formtype; // ILBM, PBM.\n\tchar\t*src;\t\t\t\t\t\t // Working source body pointer.\n\tchar\t*dest;\t\t\t\t\t // Working destination body pointer.\n\n\n\t//len = strlen(filename);\n\t//strupr(filename);\n\n\tfh = Open_File(filename,READ);\n\tif (fh == WW_ERROR) return(FALSE);\n\tRead_File(fh,&ifftype,4L);\n\tClose_File(fh);\n\n\tif (ifftype != ID_FORM) {\n\t\treturn((int)Load_Uncompress(filename, scratchbuf, destbuf,  palette ) / 8000 ) ;\n\t} else {\n\n\t\tfh = Open_Iff_File(filename);\t// Opens and checks for IFF form.\n\t\tif (fh == WW_ERROR) return(FALSE);\n\n\t\tRead_File(fh, &ifftype, 4L);\n\t\tif (ifftype == ID_ILBM) {\n\t\t\tformtype = FORM_ILBM;\t\t\t\t// Inter-Leaved Bit Map.\n\t\t} else {\n\t\t\tif (ifftype == ID_PBM) {\n\t\t\t\tformtype = FORM_PBM;\t\t\t// Packed Bit Map.\n\t\t\t} else {\n\t\t\t\treturn FALSE;\t\t\t\t// Not a recognizable picture file.\n\t\t\t}\n\t\t}\n\n\t\t// Load the BMHD chunk.\n\t\tif (Read_Iff_Chunk(fh,ID_BMHD,(char*)&bmhd,sizeof(BitMapHeader_Type))) {\n\n\t\t\t#if(IBM)\n\t\t\t\t// Perform necessary IBM conversions to the data.\n\t\t\t\tbmhd.W = Reverse_Short(bmhd.W);\n\t\t\t\tbmhd.H = Reverse_Short(bmhd.H);\n\t\t\t\tbmhd.X = Reverse_Short(bmhd.X);\n\t\t\t\tbmhd.Y = Reverse_Short(bmhd.Y);\n\n\t\t\t\t// this is a mistake Xaspect and YAspect are char type\n\t\t\t\t// bmhd.XAspect = Reverse_Short(bmhd.XAspect);\n\t\t\t\t// bmhd.YAspect = Reverse_Short(bmhd.YAspect);\n\t\t\t\t  value = bmhd.XAspect\t;\n\t\t\t\t  bmhd.XAspect = bmhd.YAspect ;\n\t\t\t\t  bmhd.YAspect = ( unsigned char ) value ;\n\n\t\t\t\tbmhd.PageWidth = Reverse_Short(bmhd.PageWidth);\n\t\t\t\tbmhd.PageHeight = Reverse_Short(bmhd.PageHeight);\n\t\t\t#endif\n\n\t\t\tif (bmhd.Masking > 2) return FALSE;\t\t\t// Don't allow brushes.\n\t\t\tif (bmhd.Compression > 1) return FALSE;\t// Unknown compression.\n\n\t\t} else {\n\t\t\treturn FALSE;\t\t\t\t// Unable to read the required BMHD chunk.\n\t\t}\n\n\t\t// Load the palette if asked.\n\t\tif (palette)\n\t\t{\n\t\t\tint\tpbytes ;\t\t\t       \t// Number of CMAP bytes required.\n\t\t\tunsigned char\tcolor;\t\t\t// Palette color value.\n\t\t\tunsigned char *paletteptr;\t\t// Allocated buffer for palette conversions.\n\t\t\tunsigned char *source;\t\t  \t// Scratch source CMAP data pointer.\n\t\t\tunsigned char *dest2;\t\t  \t// Scratch destination palette pointer.\n\n\t\t\t//\tNumber of CMAP bytes that are needed.\n\t\t\tpbytes = (1 << bmhd.BPlanes) * 3;\n\n\t\t\t// Allocate the temporary palette buffer.\n\t\t\tpaletteptr = (unsigned char *)Alloc(pbytes, MEM_CLEAR);\n\t\t\tsource = paletteptr;\n\t\t\tdest2 = palette;\n\n\t\t\t//\tRead in only the bytes that are needed.\n\t\t\tpbytes = (int)Read_Iff_Chunk(fh, ID_CMAP, (char *) paletteptr, pbytes);\n\n\t\t\tif (pbytes) {\n\n\t\t\t\t/*\n\t\t\t\t** CMAP to machine specific palette conversion code.  Conversion\n\t\t\t\t**\tgoes from CMAP three bytes per color register to the machine\n\t\t\t\t**\tspecific form.\n\t\t\t\t*/\n\t\t\t\tswitch(format) {\n\t\t\t\t\tdefault:\n\t\t\t\t\tcase BM_MCGA:\n\t\t\t\t\t\t// Convert CMAP to IBM MCGA palette form.\n\t\t\t\t\t\tfor (index = 0; index < pbytes; index++) {\n\t\t\t\t\t\t\t*dest2++ = *source++ >> 2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n#if MAKE_AMIGA_ART\n\n\t\t\t\t\tcase BM_AMIGA:\n\t\t\t\t\t\t// Convert CMAP to Amiga nibble packed palette form.\n\t\t\t\t\t\tfor (index = 0; index < pbytes; index += 3) {\n\t\t\t\t\t\t\t*dest2++   = *(source++) >> 4;\n\t\t\t\t\t\t\tcolor \t = (*(source++) & 0xf0);\n\t\t\t\t\t\t\tcolor \t+= *(source++) >> 4;\n\t\t\t\t\t\t\t*dest2++\t = color;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n#endif\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tFree(paletteptr);\n\t\t}\n\n\n\t\t//\tLoad in BODY chunk.\n\t\tdest = (char *) scratchbuf.Get_Buffer();\n\t\tsrc  = (char *) destbuf.Get_Buffer();\n\n\t\tif (Read_Iff_Chunk(fh, ID_BODY, src, destbuf.Get_Size()))\n\t\t{\n\t\t\tfor (index = 0; index < (short)bmhd.H; index++)\n\t\t\t{\n\t\t\t   /* Height of source */\n\t\t\t\t//\tTransfer (possibly uncompress) one row of data.\n\t\t\t\t// PBM or ILBM reader. Bytes per row (all bitplanes).\n\n\t\t\t\tcounter = bmhd.BPlanes * (bmhd.W >> 3);\n\n\t\t\t\t//\tIf there is a mask then there is one more bitplane.\n\t\t\t\tif (bmhd.Masking == 1)\n\t\t\t\t\t\t\t\t\t\t\tcounter += bmhd.W >> 3 ;\n\n\t\t\t\tif (bmhd.Compression == 1)\n\t\t\t\t{\n\t\t\t\t   // The data is compressed.\n\t\t\t\t\t//\tDecompress one scanline (all bitplanes) at a time.\n\t\t\t\t\twhile (counter)\n\t\t\t\t\t{\n\t\t\t\t\t\tvalue = ( signed char ) *src++; \t\t\t// Decompression code.\n\t\t\t\t\t\tif (value == -128) continue;\t// NOOP code.\n\n\t\t\t\t\t\tif (value >= 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Copy N+1 bytes.\n\t\t\t\t\t\t\tlen = ((short) value) + 1;\n\n\t\t\t\t\t\t\t//\tIgnore the masking bitplane.\n\t\t\t\t\t\t\tif ( bmhd.Masking != 1 ||\n\t\t\t\t\t\t\t     (bmhd.Masking==1 && counter > ((short)bmhd.W >> 3) ) )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmemcpy(dest, src, len);\n\t\t\t\t\t\t\t\tdest += len;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcounter -= len;\n\t\t\t\t\t\t\tsrc += len;\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Replicate -N+1 bytes.\n\t\t\t\t\t\t\tlen = (-((short) value)) + 1;\n\t\t\t\t\t\t\tvalue = *src++;\n\n\t\t\t\t\t\t\t//\tIgnore the masking bitplane.\n\t\t\t\t\t\t\tif (bmhd.Masking != 1 || (bmhd.Masking==1 && counter > ((short)bmhd.W >> 3)))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmemset(dest,value,len);\n\t\t\t\t\t\t\t\tdest += len;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcounter -= len;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t   // Plain data is just copied.\n\t\t\t\t\tmemcpy(dest,src,counter);\n\t\t\t\t\tdest += counter;\n\t\t\t\t\tsrc += counter;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tPerform necessary conversions to the data in order to reach\n\t\t\t**\tthe desired format.\n\t\t\t*/\n\t\t\tswitch (format) {\n\t\t\t\tdefault:\n\t\t\t\tcase BM_MCGA:\t\t\t// Byte per pixel desired.\n\t\t\t\t\tif (formtype == FORM_ILBM) {\n\t\t\t\t\t\tILBM_To_MCGA(scratchbuf, destbuf, bmhd.BPlanes);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMem_Copy(scratchbuf.Get_Buffer(), destbuf.Get_Buffer(), 64000L);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n#if MAKE_AMIGA_ART\n\t\t\t\tcase BM_AMIGA:\t\t\t// Bitplane format desired.\n\t\t\t\t\tif (formtype == FORM_ILBM) {\n\t\t\t\t\t\tILBM_To_Amiga(scratchbuf, destbuf, bmhd.BPlanes);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tPBM_To_Amiga(scratchbuf, destbuf, bmhd.BPlanes);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n#endif\n\t\t\t}\n\t\t}\n\n\t\tClose_Iff_File(fh);\n\t}\n\n\treturn((short)bmhd.BPlanes);\t\t\t// Loaded the picture successfully.\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/MEM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : MEM.C                                    *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : March 31, 1993                           *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Mem_Free -- Free a block of memory from system.                       *\n *   Mem_Alloc -- Allocate a block of memory from the special memory pool. *\n *   Mem_Init -- Initialize the private memory allocation pool.            *\n *   Mem_Reference -- Updates the reference time for the specified memory blo*\n *   Mem_Find -- Returns with pointer to specified memory block.           *\n *   Mem_Find_Oldest -- Returns with the memory block with the oldest time st*\n *   Mem_Free_Oldest -- Find and free the oldest memory block.             *\n *   Mem_Avail -- Returns the amount of free memory available in the cache.*\n *   Mem_Cleanup -- Performes a garbage collection on the memory cache.    *\n *   MemNode_Unlink -- Unlinks a node from the cache.                      *\n *   MemNode_Insert -- Inserts a node into a cache chain.                  *\n *   Mem_Largest_Avail -- Largest free block available.                    *\n *   Mem_Lock_Block -- Locks a block so that it cannot be moved in cleanup.*\n *   Mem_In_Use -- Makes it so a block will never be returned as oldest*\n *   Mem_Pool_Size -- Returns total amount of memory in pool.              *\n *   Mem_Get_ID -- Returns ID of node.                                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"wwmem.h\"\n#include <timer.h>\n\n#include\t<stddef.h>\n#include\t<mem.h>\n\n#define DEBUG_FILL FALSE\n\n////////////////////////////////////////////////////////////////////////////\n\n\n\n/*******************************************************************************\n** A allocated block may have one of three meanings in the Time field.  The first\n** is the time stamp of the last time it was referenced.  The other two values\n** are defined below.  MEM_BLOCK_IN_USE means that it will never be returned as the\n** oldest since there is no valid time stamp.  LOCKED_BLOCK has the same meaning as\n** MEM_BLOCK_IN_USE with the added feature that the block will not be moved in a\n** Mem_Cleanup().  Therefore, there may be some fragmentation after the cleanup\n** if any blocks are LOCKED.  It would be good practice to seldomly lock blocks,\n** for instance, only when a sample is being played.\n** WARNING: If these values change to anything else, logic will need to be changed\n**          in Mem_Find_Oldest since it relies on these being small values.\n*/\n#define MEM_BLOCK_IN_USE\t0x00\n#define MEM_BLOCK_LOCKED\t0x01\n\n/*\n**\tEach block of memory in the pool is headed by this structure.\n*/\ntypedef struct MemChain {\n\tstruct MemChain\t*Next;\t// Pointer to next memory chain node.\n\tstruct MemChain\t*Prev;\t// Pointer to previous memory chain node.\n\tunsigned long\t\tID;\t\t// ID number of block.\n\tunsigned short\t\tTime;\t\t// TickCount of latest reference.\n\tunsigned long\t\tSize;\t\t// Size of memory block (in paragraphs).\n} MemChain_Type;\n\n\n/*\n**\tHolding tank memory management data.\n*/\ntypedef struct MemPool {\n\tMemChain_Type\t*FreeChain;\t// Pointer to first node in free chain.\n\tMemChain_Type\t*UsedChain;\t// Pointer to first node in used chain.\n\tunsigned long\tFreeMem;\t\t// Current amount of free ram (in paragraphs).\n\tunsigned long\tTotalMem;\t// Total quantity of memory.\n\tlong\t\t\t\tpad2;\n} MemPool_Type;\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE void MemNode_Unlink(MemPool_Type *pool, int freechain, MemChain_Type *node);\nPRIVATE void MemNode_Insert(MemPool_Type *pool, int freechain, MemChain_Type *node, unsigned int size, unsigned long id, int merge);\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * Mem_Init -- Initialize the private memory allocation pool.              *\n *                                                                         *\n *    This routine is used to initialize the private memory allocation     *\n *    pool.                                                                *\n *                                                                         *\n * INPUT:   buffer   -- Pointer to the buffer that is the allocation pool. *\n *                                                                         *\n *          size     -- Size of the buffer in bytes.                       *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Was it initialized successfully?                   *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nint Mem_Init(void *buffer, long size)\n{\n\tMemChain_Type\t*mem;\t\t\t// Working memory chain node.\n\tMemPool_Type\t*pool;\t\t// Memory pool control structure.\n\n\t/*\n\t**\tThe buffer is rounded down to the nearest paragraph.\n\t*/\n\tsize = size & 0xFFFFFFF0L;\n\n\tif (!buffer || !size) return(FALSE);\n\n\t/*\n\t**\tInitialize the pool control structure.\n\t*/\n\tpool = (MemPool_Type *)buffer;\n\tpool->FreeMem = (size - sizeof(MemPool_Type)) >> 4;\n\tpool->UsedChain = NULL;\n\tpool->TotalMem = pool->FreeMem;\n\tmem = pool->FreeChain = (MemChain_Type *) (pool + 1);\n\n\t/*\n\t**\tInitialize the free memory chain.\n\t*/\n\tmem->Next = NULL;\n\tmem->Prev = NULL;\n\tmem->Size = pool->FreeMem;\n\tmem->ID = -1;\n\tmem->Time = 0;\n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * Mem_Alloc -- Allocate a block of memory from the special memory pool.   *\n *                                                                         *\n *    This routine will allocate a block of memory from the special        *\n *    memory allocation pool.                                              *\n *                                                                         *\n * INPUT:   poolptr\t-- Pointer to the memory pool base address.           *\n *                                                                         *\n *          size  -- The size of the memory block to allocate.             *\n *                                                                         *\n *          id    -- ID number to give this memory block.                  *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the allocated block.  If there was   *\n *          insufficient room, then NULL is returned.                      *\n *                                                                         *\n * WARNINGS:   Be sure to check for the NULL return case.                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Alloc(void *poolptr, long lsize, unsigned long id)\n{\n\tMemPool_Type\t*pool;\n\tMemChain_Type\t*node;\t\t\t// Pointer to current memory node.\n\tunsigned int\tremainder=0;\t// Remaining bytes that are still free.\n\tint\t\t\t\tfound;\n\tint\t\t\t\tsize;\t\t\t\t// Paragraph size of allocation.\n\n\n\t/*\n\t**\tIf there is no free memory then the allocation will\n\t**\talways fail.\n\t*/\n\tif (!poolptr || !lsize) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tAllocations are forced to be paragraph sized.\n\t*/\n\tlsize += sizeof(MemChain_Type);\t// Account for header.\n\tlsize = (lsize + 0x0FL) & 0xFFFFFFF0L;\n\tsize = (int)(lsize >> 4);\n\n\t/*\n\t**\tIf the total free is less than the size of the desired allocation,\n\t**\tthen we KNOW that an allocation will fail -- just return.\n\t*/\n\tif (pool->TotalMem < size) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tWalk down free chain looking for the first block that will\n\t**\taccomodate the allocation.\n\t*/\n\tnode = pool->FreeChain;\n\tfound = FALSE;\n\twhile (!found && node) {\n\n\t\t/*\n\t\t**\tFetch free memory chunk block and see if it is big enough.\n\t\t*/\n\t\tif (node->Size >= size) {\n\t\t\tfound = TRUE;\n\t\t\tbreak;\n\t\t}\n\t\tnode = node->Next;\n\t}\n\tif (!found) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tDetermine if this allocation would split the block.\n\t*/\n\tremainder = node->Size - size;\n\n\t/*\n\t**\tIf only a very small free chunk would remain, just tack it on\n\t**\tto the current allocation.\n\t*/\n\tif (remainder <= 2) {\n\t\tremainder = 0;\n\t\tsize = node->Size;\n\t}\n\n\t/*\n\t**\tRemove the primary block from the free memory list.\n\t*/\n\tMemNode_Unlink(pool, TRUE, node);\n\n\t/*\n\t**\tIf a smaller block remains, then link it back into\n\t**\tthe free memory list.\n\t*/\n\tif (remainder) {\n\t\tMemNode_Insert(pool, TRUE, (MemChain_Type *)Add_Long_To_Pointer(node, (long)size << 4), remainder, -1, FALSE);\n\t}\n\n\t/*\n\t**\tLink in the allocated node into the used memory list.\n\t*/\n\tMemNode_Insert(pool, FALSE, node, size, id, FALSE);\n\n\t/*\n\t**\tReflect the change to the total free count.\n\t*/\n\tpool->FreeMem -= size;\n\n\t/*\n\t**\tReturn a pointer to the block of allocated memory just past\n\t**\tthe header.\n\t*/\n\n#if DEBUG_FILL\n\tmemset(node + 1, id, (size-1) << 4);\n#endif\n\treturn((void *) (node + 1));\n}\n\n\n/***************************************************************************\n * Mem_Free -- Free a block of memory from system.                         *\n *                                                                         *\n *    This routine will free a block of memory from the special memory     *\n *    buffer.                                                              *\n *                                                                         *\n * INPUT:   poolptr\t-- Pointer to the memory pool base address.           *\n *                                                                         *\n *          buffer   -- Pointer to memory block to free.                   *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Was the deallocation successful?                   *\n *                                                                         *\n * WARNINGS:   Be sure to only pass in to this routine a buffer that was   *\n *             returned from Mem_Alloc().                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nint Mem_Free(void *poolptr, void *buffer)\n{\n\tMemPool_Type\t*pool;\t\t\t// pointer to structure.\n\tMemChain_Type\t*node;\t\t\t// Copy of current memory node.\n\tunsigned int\tsize;\t\t\t\t// Size of the block being freed.\n\n\t/*\n\t**\tOne can't free what isn't there.\n\t*/\n\tif (!buffer || !poolptr) {\n\t\treturn(FALSE);\n\t}\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tThe node pointer is actually back a bit from the \"normal\" pointer.\n\t*/\n\tnode = (MemChain_Type *) buffer;\n\tnode--;\n\n\t/*\n\t**\tGet pointer to actual allocated node and unlink it from the used\n\t**\tmemory chain.\n\t*/\n\tsize = node->Size;\n\tMemNode_Unlink(pool, FALSE, node);\n\tMemNode_Insert(pool, TRUE, node, size, -1, TRUE);\n\n\t/*\n\t**\tReflect the new free memory into the total memory count.\n\t*/\n\tpool->FreeMem += size;\n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * Mem_Reference -- Updates the reference time for the specified memory blo*\n *                                                                         *\n *    This routine is used to update the memory reference time for the     *\n *    specified memory node.  Typically, this is called every time a       *\n *    memory block is used in order to make sure the memory block time     *\n *    tracking (Last Recently Used) system works properly.                 *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   The node pointer must be valid.  For maximum safety this    *\n *             routine should be called right after Mem_Find().            *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid Mem_Reference(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node;\n\tnodeptr--;\n\n\tnodeptr->Time = (unsigned short)(TickCount.Time() >> 4);\n\n}\n\n\n/***************************************************************************\n * MEM_LOCK_BLOCK -- Locks a block so that it cannot be moved in cleanup.  *\n * \tBy marking a memory block in use, the memory system will never return*\n *    it as the oldest memory block.  It also makes it so that the block\t*\n *    will never be moved during a Cleanup process.                        *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:  \tIf one or more blocks are locked in a heap, Mem_Avail might *\n *             not equal Mem_Largest_Avail after a call to Mem_Cleanup.    *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid Mem_Lock_Block(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node;\n\tnodeptr--;\n\tnodeptr->Time = MEM_BLOCK_LOCKED;\n}\n\n\n/***************************************************************************\n * MEM_IN_USE -- Makes it so a block will never be returned as oldest\t\t*\n * \tBy marking a memory block in use, the memory system will never return*\n *    it as the oldest memory block.  It still can be moved in the Cleanup *\n *    code.                                                                *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS: Mem_Find_Oldest() will return NULL if only IN_USE blocks are  *\n *           in memory.                                                    *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid Mem_In_Use(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node - 1;\n\tnodeptr->Time = MEM_BLOCK_IN_USE;\n}\n\n\n/***************************************************************************\n * Mem_Find -- Returns with pointer to specified memory block.             *\n *                                                                         *\n *    Use this routine to convert a memory ID value into an actual memory  *\n *    pointer.  It sweeps through all of the 'cached' memory blocks and    *\n *    returns with the matching block pointer.                             *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache block.                 *\n *                                                                         *\n *          id       -- The ID of the block desired.                       *\n *                                                                         *\n * OUTPUT:  Returns with the pointer to the memory block.  If NULL is      *\n *          returned then the desired block is not in the memory cache.    *\n *                                                                         *\n * WARNINGS:   This routine may return NULL if the memory block is not     *\n *             present in the cache.                                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Find(void *poolptr, unsigned long id)\n{\n\tMemPool_Type\t*pool;\t\t\t// pointer to structure.\n\tMemChain_Type\t*node;\t\t\t// Working node structure.\n\n\tif (!poolptr) return(NULL);\n\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t** Cannot free a node that is not on the UsedChain list.\n\t*/\n\tif (!pool->UsedChain) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tSweep through entire allocation chain to find\n\t**\tthe one with the matching ID.\n\t*/\n\tnode = pool->UsedChain;\n\twhile (node) {\n\n\t\tif (node->ID == id) {\n\t\t\treturn(node + 1);\n\t\t}\n\t\tnode = node->Next;\n\t}\n\treturn(NULL);\n}\n\n\n/***************************************************************************\n * MEM_GET_ID -- Returns ID of node.                                       *\n *                                                                         *\n * INPUT:  void *node - pointer to node. \t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT: The ID of the node that was supplied by user during Mem_Alloc().*\n *                                                                         *\n * WARNINGS: pointer to node must be one that Mem_Alloc or                \t*\n *           Mem_Find returned.                                           **\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nunsigned long Mem_Get_ID(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return (0L);\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node - 1;\n\treturn (nodeptr->ID);\n}\n\n\n/***************************************************************************\n * Mem_Find_Oldest -- Returns with the memory block with the oldest time st*\n *                                                                         *\n *    Use this routine to find the memory block with the oldest time stamp *\n *    value.  Typically, this is used when freeing memory blocks in the    *\n *    cache in order to make room for a new memory block.                  *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns with the pointer to the oldest memory block.  If NULL  *\n *          is returned, then the memory cache is empty.                   *\n *                                                                         *\n * WARNINGS:   This routine could return NULL.                             *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *   04/15/1994 SKB : Handle time wrap, locked blocks, and no_refenece blocks*\n *=========================================================================*/\nvoid *Mem_Find_Oldest(void *poolptr)\n{\n\tMemChain_Type\t*node; \t\t\t\t// Working node pointer.\n\tMemChain_Type\t*oldnode;\t\t\t// Pointer to oldest block.\n\tunsigned int\toldtime;\t\t\t\t// Time of oldest block.\n\tunsigned int\tbasetime;\t\t\t// Time to mark our base time with.\n\tunsigned int\ttime;\t\t\t\t\t// basetime + time of node.\n\n\tif (!poolptr) return(NULL);\n\n\t/*\n\t**\tSweep through entire allocation chain to find\n\t**\tthe oldest referenced memory block.\n\t*/\n\toldnode = NULL;\n\toldtime = 0;\n\tnode = ((MemPool_Type*) poolptr)->UsedChain;\n\n  basetime = (unsigned int)(TickCount.Time() >> 4);\n\n\twhile (node) {\n\n\t\t/*\n\t\t** Don't allow MEM_BLOCK_IN_USE or MEM_BLOCK_LOCKED to be returned.\n\t\t*/\n\t\tif (node->Time > MEM_BLOCK_LOCKED) {\n\n\t\t\t/*\n\t\t\t** Adjust time for wrap around (after about 5 hrs).\n\t\t\t** times less then the base time will wrap up high while\n\t\t\t** and times greater then base time will then be lower since\n\t\t\t** any time greater has been on the thing a long time.\n\t\t\t*/\n\t\t\ttime = node->Time - basetime ;\n\n\t\t\tif (time < oldtime || !oldnode) {\n\t\t\t\toldtime = time;\n\t\t\t\toldnode = node;\n\t\t\t}\n\t\t}\n\t\tnode = node->Next;\n\t}\n\n\t/*\n\t**\tReturn with the value that matches the pointer that\n\t**\twas allocated by the system previously.\n\t*/\n\tif (oldnode) {\n\t\toldnode++;\n\t}\n\treturn(oldnode);\n}\n\n\n/***************************************************************************\n * Mem_Free_Oldest -- Find and free the oldest memory block.               *\n *                                                                         *\n *    This routine is used to free the oldest memory block in the memory   *\n *    cache.  This routine is typcially used in order to create more room  *\n *    in the cache for a new allocation.                                   *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns with the node that it freed.  Although this node is    *\n *          is no longer valid, it may be used to mark that pointer as     *\n *          invalid in the main code.                                      *\n *                                                                         *\n * WARNINGS:   If this routine returns NULL, then no memory was freed.     *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Free_Oldest(void *poolptr)\n{\n\tMemChain_Type\t*node;\t\t// Copy of pointer to oldest node.\n\n\tif (!poolptr) return(NULL);\n\tnode = (MemChain *) Mem_Find_Oldest(poolptr);\n\tif (Mem_Free(poolptr, node)) {\n\t\treturn(node);\n\t}\n\treturn(NULL);\n}\n\n/***************************************************************************\n * MEM_POOL_SIZE -- Returns total amount of memory in pool.                *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  long total size of pool. i.e. largest possible allocation if   *\n *          no memory was allocated.                                       *\n *                                                                         *\n * WARNINGS: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Mem_Pool_Size(void *poolptr)\n{\n\tMemPool_Type\t*pool;\t\t\t// Memory pool control structure.\n\tlong\t\t\t\tmemtotal;\t\t// Total amount of memory free.\n\n\tif (!poolptr) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\tmemtotal = ((long)pool->TotalMem) << 4;\n\tmemtotal -= sizeof(MemChain_Type);\n\tmemtotal = MAX(memtotal, (long)0);\n\treturn(memtotal);\n}\n\n/***************************************************************************\n * Mem_Avail -- Returns the amount of free memory available in the cache.  *\n *                                                                         *\n *    This routine examines the memory cache and returns the amount of     *\n *    free memory available.  This memory total MAY be fragmented but      *\n *    after Mem_Cleanup() is called, an allocation of the amount returned  *\n *    by this function is guaranteed.                                      *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns the largest allocation possible from the memory cache. *\n *                                                                         *\n * WARNINGS:   The value returned may represent the FRAGMENTED total       *\n *             amount of memory free in the cache.                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nlong Mem_Avail(void *poolptr)\n{\n\tMemPool_Type\t*pool;\t\t// Memory pool control structure.\n\tlong\t\t\t\tmemtotal;\t// Total amount of memory free.\n\n\tif (!poolptr) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\tmemtotal = ((long)pool->FreeMem) << 4;\n\tmemtotal -= sizeof(MemChain_Type);\n\t//memtotal -= sizeof(MemChain_Type) + 15;\n\tmemtotal = MAX(memtotal, (long)0);\n\treturn(memtotal);\n}\n\n\n/***************************************************************************\n * MEM_LARGEST_AVAIL -- Largest free block available.                      *\n * \tThis routine examines the free node list to find the largest block   *\n *\t\tavailable.  User can Mem_Alloc() this return size successfully.      *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns largest allocation currently possible from the cache. \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Mem_Largest_Avail(void *poolptr)\n{\n\tMemChain_Type\t*node;\t\t\t// Pointer to current memory node.\n\tunsigned int\tsize;\n\tlong\t\t\t\ttruesize;\n\n\t/*\n\t** Make sure that it is a buffer.\n\t*/\n\tif (!poolptr) return(NULL);\n\n\t/*\n\t** Go through the entire free chain looking for the largest block.\n\t*/\n\tnode = ((MemPool_Type *)poolptr)->FreeChain;\n\tsize = 0;\n\twhile (node) {\n\n\t\t/*\n\t\t**\tFetch free memory chunk block and see if it is big enough.\n\t\t*/\n\t\tif (node->Size >= size) {\n\t\t\tsize = node->Size;\n\t\t}\n\t\tnode = node->Next;\n\t}\n\n\ttruesize = (long)size << 4;\n\ttruesize -= sizeof(MemChain_Type);\n\ttruesize = MAX(truesize, 0L);\n\treturn (truesize);\n}\n\n\n/***************************************************************************\n * Mem_Cleanup -- Performs a garbage collection on the memory cache.       *\n *                                                                         *\n *    This routine is used to coalesce all adjacent free blocks of         *\n *    memory in the specified cache.  As a result, all previous pointers   *\n *    provided by Mem_Find() are invalidated.  This routine consumes a     *\n *    fair amount of time and should be called as infrequently as          *\n *    possible.                                                            *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine takes a significant amount of time!            *\n *             If there are locked block in memory, the pool may still     *\n *             be fragmented.                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Updated for low memory caches.                       *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid Mem_Cleanup(void *poolptr)\n{\n\tMemPool_Type\t*pool;  \t// Memory pool control structure.\n\tMemChain_Type\t*free,\t// Pointer to first free area.\n\t\t\t\t\t\t*cur;\t\t// Pointer to first used block that is after free.\n\tunsigned long\tsize;\n\tunsigned long\tfreesize;// Size of free heap at the end of the block.\n\n\tif (!poolptr) return;\n\n\t/*\n\t**\tFetch working copy of pool control structure.\n\t*/\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tBasic parameter and condition legality checks.  If the memory pool\n\t**\thas no free space, no free blocks, or no allocated blocks, then\n\t**\tmemory cleanup is unnecessary -- just exit.\n\t*/\n\tif (!pool->FreeMem || !pool->FreeChain || !pool->UsedChain) return;\n\n\tfreesize = pool->FreeMem;\n\tfree = pool->FreeChain;\n\tpool->FreeChain = NULL;\n\tcur = pool->UsedChain;\n\twhile (TRUE) {\n\n\t\t/*\n\t\t** Setup pointers so that free points to the first free block and cur\n\t\t** points to the next used block after the free block.\n\t\t*/\n\t\twhile (cur < free && cur) {\n\t \t\tcur = cur->Next;\n\t\t}\n\n\t\t// All used blocks are at the front of the free.  We are done.\n\t\tif (!cur) {\n\t \t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t** Do not allow a locked block to be moved.\n\t\t*/\n\t\tif (cur->Time == MEM_BLOCK_LOCKED) {\n\t\t\t/*\n\t\t\t** Figure the size of the new free block that we are creating.\n\t\t\t** Subtract off the total block size.\n\t\t\t** Add the node to the free list.\n\t\t\t*/\n\t\t\tsize = (char *) cur - (char  *) free;\n\t\t\tsize >>= 4;\n\t\t \tfreesize -= size;\n\t\t\tMemNode_Insert(pool, TRUE, free, (unsigned int) size, -1, FALSE);\n\n\t\t\t/*\n\t\t\t** Time to find a new free position to start working from.\n\t\t\t** Cur will be in the position just following.\n\t\t\t*/\n\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, (unsigned long)cur->Size << 4);\n\t\t\tcur = cur->Next;\n\t\t\twhile (free == cur) {\n\t\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, (unsigned long)cur->Size << 4);\n\t\t\t\tcur = cur->Next;\n\t\t\t}\n\n\t\t\t// All used blocks are at the front of the free.  We are done.\n\t\t\tif (!cur) {\n\t\t\t \tbreak;\n\t\t\t}\n\t\t} else {\n\n\t\t\t// Copy the block up.\n\t\t\tsize = (unsigned long)cur->Size << 4;\n\t\t\tMem_Copy(cur, free, size);\n\t\t\tcur = free;\n\n\t\t\t// Change pointers of surrounding blocks.\n\t\t\tif (cur->Next) {\n\t\t \t\tcur->Next->Prev = cur;\n\t\t\t}\n\t\t\tif (cur->Prev) {\n\t\t \t\tcur->Prev->Next = cur;\n\t\t\t} else {\n\t\t \t\tpool->UsedChain = cur;\n\t\t\t}\n\n\t\t\t// Change to next new free area.\n\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, size);\n\t\t}\n\t}\n\n\t/*\n\t**\tNow build the single free chunk.\n\t*/\n\tMemNode_Insert(pool, TRUE, free, freesize, -1, FALSE);\n}\n\n\n/***************************************************************************\n * MemNode_Unlink -- Unlinks a node from the cache.                        *\n *                                                                         *\n *    A private routine the actually unlinks a memory block from the       *\n *    memory cache.  It doesn't perform a complete update of the memory    *\n *    cache.                                                               *\n *                                                                         *\n * INPUT:   pool     -- Pointer to the memory cache header (copy in real   *\n *                      memory).                                           *\n *                                                                         *\n *          freechain-- Is the block part of the free memory chain?        *\n *                                                                         *\n *          node     -- Pointer to the node that will be unlinked.         *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine doesn't update memory totals.  It is a support *\n *             function.                                                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nPRIVATE void MemNode_Unlink(MemPool_Type *pool, int freechain, MemChain_Type *node)\n{\n\tMemChain_Type\t*other; \t\t// Copy of node data to unlink.\n\tMemChain_Type\t**chain;\t\t// A pointer to one of the chains pointer.\n\n\t/*\n\t**\tCheck for parameter validity.\n\t*/\n\tif (!pool || !node) return;\n\n\t/*\n\t**\tSetup working pointer for the particular chain desired.\n\t*/\n\tif (freechain) {\n\t\tchain = &pool->FreeChain;\n\t} else {\n\t\tchain = &pool->UsedChain;\n\t}\n\n\t/*\n\t**\tMake adjustments to the previous node.  If the pointer\n\t**\tto the previous node is NULL then this indicates the\n\t**\tfirst node in the list and thus the chain pointer needs\n\t**\tto be updated instead.\n\t*/\n\tif (node->Prev) {\n\t\tother = node->Prev;\n\t\tother->Next = node->Next;\n\t} else {\n\t\t*chain = node->Next;\n\t}\n\n\tif (node->Next) {\n\t\tother = node->Next;\n\t\tother->Prev = node->Prev;\n\t}\n}\n\n\n/***************************************************************************\n * MemNode_Insert -- Inserts a node into a cache chain.                    *\n *                                                                         *\n *    This routine is used to add a node to a cache chain.  Since nodes    *\n *    do not contain double links, they must be placed in sequence.        *\n *                                                                         *\n * INPUT:   pool     -- Pointer to memory pool (must be in real memory).   *\n *                                                                         *\n *          freechain-- Is the node to be inserted into the free chain?    *\n *                                                                         *\n *          node     -- Pointer to the node to insert.                     *\n *                                                                         *\n *          size     -- Size of the memory block (in paragraphs).          *\n *                                                                         *\n *          id       -- The ID number to associate with this block.        *\n *                                                                         *\n *          merge    -- Merge inserted block with adjacent blocks.         *\n *                                                                         *\n * OUTPUT:  return                                                         *\n *                                                                         *\n * WARNINGS:   This is a support routine.                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void MemNode_Insert(MemPool_Type *pool, int freechain, MemChain_Type *node, unsigned int size, unsigned long id, int merge)\n{\n\tMemChain_Type \t**chain;\t\t\t// Pointer to chain that will be linked.\n\tMemChain_Type \t*prev,\t\t\t// Successor node pointer.\n\t\t\t\t\t\t*next;\t\t\t// Predecessor node pointer.\n\tint\t\t\t\tdoit=TRUE;\t\t// Link the node into the list.\n\n\n\t/*\n\t**\tDetermine if the parameters are valid.\n\t*/\n\tif (!pool || !node || !size) return;\n\n\t/*\n\t**\tSetup working pointer for the particular chain desired.\n\t*/\n\tif (freechain) {\n\t\tchain = &pool->FreeChain;\n\t} else {\n\t\tchain = &pool->UsedChain;\n\t}\n\n\t/*\n\t**\tHandle the \"no node in list\" condition (easiest).\n\t*/\n\tif (!*chain) {\n\t\tnode->Next = NULL;\n\t\tnode->Prev = NULL;\n\t\tnode->Size = size;\n\t\tnode->Time = (unsigned short)(TickCount.Time() >> 4);\n\t\tnode->ID = id;\n\t\t*chain = node;\n\t\treturn;\n\t}\n\n\t/*\n\t**\tSweep through the memory chain looking for a likely spot\n\t**\tto insert the new node.  It will stop with \"next\" pointing\n\t**\tto the node to come after the block to be inserted and \"prev\"\n\t** will point to the node right before.\n\t*/\n\tprev = NULL;\n\tnext = *chain;\n\twhile (next && (next < node)) {\n\n\t\t/*\n\t\t**\tMove up the memory chain.\n\t\t*/\n\t\tprev = next;\n\t\tnext = next->Next;\n\t}\n\n\t/*\n\t**\tCoallescing of adjacent blocks (if requested).\n\t*/\n\tif (merge) {\n\n\t\t/*\n\t\t**\tIf the previous block is touching the block to insert\n\t\t**\tthen merely adjust the size of the previous block and\n\t\t**\tthat is all that is necessary.\n\t\t*/\n\t\tif (prev) {\n\t\t\tif (((char *)prev + ((long)prev->Size << 4)) == ((char *) node)) {\n\t\t\t\tprev->Size += size;\n\t\t\t\tsize = prev->Size;\n\t\t\t\tnode = prev;\n\t\t\t\tprev = prev->Prev;\n\t\t\t\tdoit = FALSE;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf the following block is touching the block to insert\n\t\t**\tthen remove the following block and increase the size of\n\t\t**\tthe original insertion block by the size of the other\n\t\t**\tblock.\n\t\t*/\n\t\tif (next) {\n\t\t\tif (((char *)node + ((long)size << 4)) == (char *)next) {\n\n\t\t\t\tif (!doit) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the node was already merged with the previous block\n\t\t\t\t\t**\tthen merely increase the previous block's size\n\t\t\t\t\t**\tand adjust it's next pointer appropriately.\n\t\t\t\t\t*/\n\t\t\t\t\tnode->Size += next->Size;\n\t\t\t\t\tnode->Next = next->Next;\n\t\t\t\t\tnext = next->Next;\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIncrease the size of the current block and adjust\n\t\t\t\t\t**\tthe \"next\" pointer so that it gets fixed up\n\t\t\t\t\t**\taccordingly.\n\t\t\t\t\t*/\n\t\t\t\t\tsize += next->Size;\n\t\t\t\t\tnext = next->Next;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n#if DEBUG_FILL\n\tif (doit) {\n\t\tmemset(node + 1, 0xFF, (size - 1) << 4);\n\t} else {\n\t\tmemset(node + 1, 0xFF, (node->Size - 1) << 4);\n\t}\n#endif\n\n\t/*\n\t**\tFixup the node pointers.\n\t*/\n\tif (prev) {\n\t\tprev->Next = node;\n\t}else{\n\t\t*chain = node;\n\t}\n\n\tif (next) {\n\t \tnext->Prev = node;\n\t}\n\n\tif (doit) {\n\t\tnode->Prev = prev;\n\t\tnode->Next = next;\n\t\tnode->Size = size;\n\t\tnode->Time = (unsigned short)(TickCount.Time() >> 4);\n\t\tnode->ID = id;\n\t}\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/MEM_COPY.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : MEM_COPY.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott Bowen\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : September 8, 1994\t[IML]              *\n;*                  Ported to watcom c32 : 01/03/96     [JRJ]                                                                        *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Mem_Copy -- Copies from one pointer to another.                       *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nLOCALS ??\n\n\n;******************************************************************************\n; Much testing was done to determine that only when there are 14 or more bytes\n; being copied does it speed the time it takes to do copies in this algorithm.\n; For this reason and because 1 and 2 byte copies crash, is the special case\n; used.  SKB 4/21/94.  Tested on 486 66mhz.\nOPTIMAL_BYTE_COPY\tequ\t14\n\n\n;******************************************************************************\n; External declares so these functions can be called\n;\nGLOBAL \tC Mem_Copy\t: NEAR\nGLOBAL  C Largest_Mem_Block : near\n\nCODESEG\n\n\n;***************************************************************************\n;* MEM_COPY -- Copies from one pointer to another.                         *\n;* This routine copies bytes from source to dest.  It takes care of\t   *\n;* overlapped memory, and unsigned long copies.\t\t\t\t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/18/1994 SKB : Created.                                             *\n;*=========================================================================*\n; void Mem_Copy(void *source, void *dest, unsigned long bytes_to_copy);\n\n\nPROC Mem_Copy \tC near\n\tUSES\tecx , esi , edi , ebx\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tbytes:DWORD\n\n;********************************* Setup ******************************************\n\tcld\n\tmov\tesi,[source]\n\tmov\tedi,[dest]\n\tmov\tecx,[bytes]\t; get number of bytes to copy.\n\n     ; check pointers for singularities\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tje\t??done\t\t; No sence in copying the same pointer.\n\tor\tesi,0\n\tjz\t??done\n\tor\tedi,0\n\tjz\t??done\n\n\tcmp\tecx,OPTIMAL_BYTE_COPY  ; see notes above about equate.\n\tjge\t??normal      \t       ; If >= MAX(2,OPTIMAL_BYTE_COPY), do normal dword copy.\n\n;******************************** Special case <= 2 *******************************\n;\n; This section must be called for bytes <= 2 since the other case will crash.  It\n; optionally uses OPTIMAL_BYTE_COPY for the cut off point.  This is because after\n; extensive testing, it was proved that only at that point (14 or more bytes) does\n; it become quicker to use the dword copy method.\n\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tjge\t??do_move\t; if source greater do forward copy.\n\tlea\tesi,[esi+ecx-1]\n\tstd\t\t\t; Opps, wrong, force the pointers to decrement.\n\tlea\tedi,[edi+ecx-1]\n??do_move:\n\trep\tmovsb\t\t; move the one or two bytes.\n\tcld\n??done:\n\tret\n\n;************************** back or forth, that is the question *******************\n\n??normal:\n\tmov\tebx,ecx\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tjge\t??forward\t; if source greater do forward copy.\n\n;********************************* Backward ***************************************\n??backward:\n\tlea\tecx,[edi+ebx]\n\tstd\n\tlea\tedi,[edi+ebx-1]\n\tand\tecx,3\t\t; Get non aligned bytes.\n\tlea\tesi,[esi+ebx-1]\n\tsub\tebx,ecx\t\t; remove that from the total size to be copied later.\n\trep\tmovsb\t\t; do the copy.\n\tsub\tesi,3\n\tmov\tecx,ebx\t\t; Get number of bytes left.\n \tsub\tedi,3\n\tshr\tecx,2\t\t; Do 4 bytes at a time.\n\trep\tmovsd\t\t; do the dword copy.\n\tmov\tecx,ebx\n\tadd\tesi,3\n\tadd\tedi,3\n\tand\tecx,03h\n\trep\tmovsb\t\t; finnish the remaining bytes.\n\tcld\n\tret\n\n;********************************* Forward ***************************************\n??forward:\n\tcld\n\tmov\tecx,edi\t\t; get destination pointer.\n\tneg\tecx\n\tand\tecx,3\t\t; Get non aligned bytes.\n\tsub\tebx,ecx\t\t; remove that from the total size to be copied later.\n\trep\tmovsb\t\t; do the copy.\n\tmov\tecx,ebx\t\t; Get number of bytes left.\n\tshr\tecx,2\t\t; Do 4 bytes at a time.\n\trep\tmovsd\t\t; do the dword copy.\n\tmov\tecx, ebx\n\tand\tecx,03h\n\trep\tmovsb\t\t; finnish the remaining bytes.\n\tret\n\nENDP\tMem_Copy\nIF 0\nPROC Largest_Mem_Block \tC near\n\tuses\tesi , edi , ebx , ecx , edx\n\tlocal\tmem_struct : dword : 16\n\n\tmov\teax , 0500h\n\tlea\tedi , [ mem_struct ]\n\tint\t31h\n\tmov\teax , [ mem_struct ]\n\n\tret\nENDP Largest_Mem_Block\nENDIF\nEND\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/MODEMREG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer/ WW Library                                *\n *                                                                                             *\n *                    File Name : MODEMREG.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 10/18/96                                                     *\n *                                                                                             *\n *                  Last Update : October 18th 1996 [ST]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *                                                                                             *\n *   Functions for obtaining modem infommation from the Win95 registry                         *\n *                                                                                             *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *                                                                                             *\n * Search_Registry_Key -- Search a registry key and all its subkeys for a given value          *\n * MREC::ModemRegistryEntryClass -- Constructor for ModemRegistryEntryClass                    *\n * MREC::~ModemRegistryEntryClass -- Destructor.Free all the memory we allocated for modem info*\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\n\n\n#include \"modemreg.h\"\n#include <stdio.h>\n\n\nextern HKEY Get_Registry_Sub_Key (HKEY base_key, char *search_key, BOOL close);\n\n\n\n\n/***********************************************************************************************\n * Search_Registry_Key -- Search a registry key and all its subkeys for a given value          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    handle to key to search in                                                        *\n *           name of key to search for                                                         *\n *           value expected in key                                                             *\n *                                                                                             *\n * OUTPUT:   Handle to key containing value. Null if not found.                                *\n *                                                                                             *\n * WARNINGS: This function reenters itself.                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/18/96 4:01AM ST : Created                                                             *\n *=============================================================================================*/\nHKEY Search_Registry_Key (HKEY key_in, char *value_name, char *search_string)\n{\n\n\tint \ttop_key_index = 0;\t\t\t\t// Index of topmost key\n\tint \tretval;\t\t\t\t\t\t\t\t// Result of registry api calls\n\tHKEY\tnext_key;\t\t\t\t\t\t\t// handle of next key examine\n\tHKEY\tnext_search;\t\t\t\t\t\t// handle of next key to search\n\n\n\tchar\t\t\t\t*subkey_name = new char [256];\t\t\t// Area to contain result of key enumeration\n\tunsigned long\tsubkey_name_length = 256;\t\t\t\t\t// Length of enumeration result area\n\tFILETIME\t\t\tfiletime;\t\t\t\t\t\t\t\t\t\t// Time key was last touched. Not used.\n\tunsigned long\tvalue_type;\t\t\t\t\t\t\t\t\t\t// Type of data that is contained in a key.\n\tunsigned char\t*key_value = new unsigned char [256];\t// Area to return key values into\n\tunsigned long\tkey_value_length = 256;\t\t\t\t\t\t// Length of key value area\n\n\t/*\n\t** Scan through and enumerate all subkeys of this key. Exit the loop when there are\n\t** no more sub keys to enumerate.\n\t*/\n\tdo {\n\t\tsubkey_name_length = 256;\t\t\t// Has to be set each time through the loop\n\n\t\t/*\n\t\t** Get the next key\n\t\t*/\n\t\tretval = RegEnumKeyEx (key_in, top_key_index++, subkey_name, &subkey_name_length, NULL, NULL, NULL, &filetime);\n\n\t\tif ( retval == ERROR_SUCCESS ){\n\n\t\t\t/*\n\t\t\t** Get a handle to this key so we can search it.\n\t\t\t*/\n\t\t\tnext_key = Get_Registry_Sub_Key (key_in, subkey_name, FALSE);\n\n\t\t\tif (next_key){\n\n\t\t\t\tkey_value_length = 256;\t\t// Has to be set each time through the loop\n\n\t\t\t\tif ( RegQueryValueEx (next_key, value_name, NULL, &value_type, key_value, &key_value_length) == ERROR_SUCCESS){\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If this value is type string then do a compare with the value we are looking for\n\t\t\t\t\t*/\n\t\t\t\t\tif (value_type == REG_SZ && !strcmp ((char*)key_value, search_string)){\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** This is our man. Delete our workspace and return the key handle\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tdelete [] subkey_name;\n\t\t\t\t\t\tdelete [] key_value;\n\t\t\t\t\t\treturn (next_key);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** We didnt find our search value so search this key for more sub keys by reentering\n\t\t\t\t** this function with the handle of the subkey.\n\t\t\t\t*/\n\t\t\t\tnext_search = Search_Registry_Key (next_key, value_name, search_string);\n\t\t\t\tRegCloseKey (next_key);\n\n\t\t\t\t/*\n\t\t\t\t** If the value was found in a subkey then just return with the key handle.\n\t\t\t\t*/\n\t\t\t\tif (next_search){\n\t\t\t\t\tdelete [] subkey_name;\n\t\t\t\t\tdelete [] key_value;\n\t\t\t\t\treturn (next_search);\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t} while (retval == ERROR_SUCCESS);\n\n\t/*\n\t** Clean up and exit.\n\t*/\n\tdelete [] subkey_name;\n\tdelete [] key_value;\n\n\treturn (0);\n}\n\n\n\n/***********************************************************************************************\n * MREC::ModemRegistryEntryClass -- Constructor for ModemRegistryEntryClass                    *\n *                                                                                             *\n *  This function does all the work in the class. All the registry searching is done here      *\n *                                                                                             *\n * INPUT:    Modem number                                                                      *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/18/96 4:12AM ST : Created                                                             *\n *=============================================================================================*/\nModemRegistryEntryClass::ModemRegistryEntryClass (int modem_number)\n{\n\tHKEY\t\t\t\tkey;\n\tunsigned char\treturn_buf[256];\n\tDWORD\t\t\t\tretbuf_size = sizeof(return_buf);\n\n\tint\t\t\t\tpnp = 0;\t\t\t\t\t//Not a plug n pray modem\n\n\t/*\n\t** Initialise all the info we expect from the registry to NULL.\n\t** Any entries we cant find will just stay NULL.\n\t*/\n\tModemName = NULL;\n\tModemDeviceName = NULL;\n\tErrorCorrectionEnable = NULL;\n\tErrorCorrectionDisable = NULL;\n\tCompressionEnable = NULL;\n\tCompressionDisable = NULL;\n\tHardwareFlowControl = NULL;\n\tNoFlowControl = NULL;\n\n\n\t/*\n\t** Modem info is stored under\n\t** HKEY_LOCAL_MACHINE / System / CurrentControlSet / Services / Class / Modem / nnnn\n\t** where nnnn is a four digit modem number.\n\t*/\n\n\tkey = Get_Registry_Sub_Key (HKEY_LOCAL_MACHINE, \"System\", FALSE);\n\tif (!key) return;\n\n\tkey = Get_Registry_Sub_Key (key, \"CurrentControlSet\", TRUE);\n\tif (!key) return;\n\n\tkey = Get_Registry_Sub_Key (key, \"Services\", TRUE);\n\tif (!key) return;\n\n\tkey = Get_Registry_Sub_Key (key, \"Class\", TRUE);\n\tif (!key) return;\n\n\tkey = Get_Registry_Sub_Key (key, \"Modem\", TRUE);\n\tif (!key) return;\n\n\tchar which_modem[5];\n\tsprintf (which_modem, \"%04d\", modem_number);\n\n\t/*\n\t** Get a handle to the modem key if it exists. Then extract the info we need.\n\t*/\n\tkey = Get_Registry_Sub_Key (key, which_modem, TRUE);\n\tif (!key) return;\n\n\n\t/*\n\t** Get the name of the modem. This is what will be displayed in the modem list presented\n\t** to the user.\n\t*/\n\tif (RegQueryValueEx(key, \"Model\", NULL, NULL, return_buf, &retbuf_size) != ERROR_SUCCESS){\n\t\tRegCloseKey (key);\n\t\treturn;\n\t}\n\tModemName = new char [retbuf_size];\n\tmemcpy (ModemName, return_buf, retbuf_size);\n\n\t/*\n\t** Find out what COM port the modem is attached to. If this info isnt here, then its a\n\t** Plug n Pray modem. Set the flag so we know to do the pnp search later.\n\t*/\n\tretbuf_size = sizeof (return_buf);\n\tif (RegQueryValueEx(key, \"AttachedTo\", NULL, NULL, return_buf, &retbuf_size) != ERROR_SUCCESS){\n\t\t/*\n\t\t** Must be a plug n pray modem. Set the flag. We will look for the port later.\n\t\t*/\n\t\tpnp = 1;\n\t\tModemDeviceName = new char [strlen (ModemName)+1];\n\t\tstrcpy (ModemDeviceName, ModemName);\n\t}else{\n\t\tModemDeviceName = new char [retbuf_size];\n\t\tmemcpy (ModemDeviceName, return_buf, retbuf_size);\n\t}\n\n\n\t/*\n\t** The list of modem 'AT' commands is stored in the 'Settings'  key.\n\t*/\n\tkey = Get_Registry_Sub_Key (key, \"Settings\", TRUE);\n\tif (!key) return;\n\n\n\t/*\n\t** Extract the control strings for error control.\n\t*/\n\tretbuf_size = sizeof (return_buf);\n\tif (RegQueryValueEx(key, \"ErrorControl_On\", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){\n\t\tErrorCorrectionEnable = new char [retbuf_size];\n\t\tmemcpy (ErrorCorrectionEnable, return_buf, retbuf_size);\n\t}\n\n\tretbuf_size = sizeof (return_buf);\n\tif (RegQueryValueEx(key, \"ErrorControl_Off\", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){\n\t\tErrorCorrectionDisable = new char [retbuf_size];\n\t\tmemcpy (ErrorCorrectionDisable, return_buf, retbuf_size);\n\t}\n\n\t/*\n\t** Extract the control strings for data compression.\n\t*/\n\tretbuf_size = sizeof (return_buf);\n\tif (RegQueryValueEx(key, \"Compression_On\", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){\n\t\tCompressionEnable = new char [retbuf_size];\n\t\tmemcpy (CompressionEnable, return_buf, retbuf_size);\n\t}\n\n\tretbuf_size = sizeof (return_buf);\n\tif (RegQueryValueEx(key, \"Compression_Off\", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){\n\t\tCompressionDisable = new char [retbuf_size];\n\t\tmemcpy (CompressionDisable, return_buf, retbuf_size);\n\t}\n\n\t/*\n\t** Extract the control strings for hardware flow control.\n\t*/\n\tretbuf_size = sizeof (return_buf);\n\tif (RegQueryValueEx(key, \"FlowControl_Hard\", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){\n\t\tHardwareFlowControl = new char [retbuf_size];\n\t\tmemcpy (HardwareFlowControl, return_buf, retbuf_size);\n\t}\n\n\t/*\n\t** Extract the control strings for no flow control.\n\t*/\n\tretbuf_size = sizeof (return_buf);\n\tif (RegQueryValueEx(key, \"FlowControl_Off\", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){\n\t\tNoFlowControl = new char [retbuf_size];\n\t\tmemcpy (NoFlowControl, return_buf, retbuf_size);\n\t}\n\n\n\n\tRegCloseKey (key);\n\n\n\n\t/*\n\t** If this is a plug n pray modem then we need to search for the COM port it is\n\t** attached to.\n\t*/\n\tif (pnp){\n\n\t\t/*\n\t\t** The driver name in the HKEY_LOCAL_MACHINE / Enum section will be Modem\\nnnn where nnnn\n\t  \t** is a four digit modem number.\n\t\t*/\n\t\tchar search_string [256] = {\"Modem\\\\\"};\n\t\tstrcat (search_string, which_modem);\n\n\t\t/*\n\t\t** Search through all the registry entries under HKEY_LOCAL_MACHINE / Enum\n\t\t*/\n\t\tkey = Get_Registry_Sub_Key (HKEY_LOCAL_MACHINE, \"Enum\", FALSE);\n\t\tif (!key) return;\n\n\t\tHKEY newkey = Search_Registry_Key ( key, \"Driver\", search_string );\n\n\t\tif (newkey){\n\t\t\tretbuf_size = sizeof (return_buf);\n\n\t\t\t/*\n\t\t\t** Extract the PORTNAME value. This is the name of the port to use to communicate\n\t\t\t** with the modem.\n\t\t\t*/\n\t\t\tretbuf_size = sizeof (return_buf);\n\t\t\tif (RegQueryValueEx(newkey, \"PORTNAME\", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){\n\n\t\t\t\tif (ModemDeviceName) delete [] ModemDeviceName;\n\n\t\t\t\tModemDeviceName = new char [retbuf_size];\n\t\t\t\tmemcpy (ModemDeviceName, return_buf, retbuf_size);\n\t\t\t}\n\t\t}\n\t\tRegCloseKey (key);\n\t}\n\n}\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * MREC::~ModemRegistryEntryClass -- Destructor.Free all the memory we allocated for modem info*\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/18/96 11:39AM ST : Created                                                              *\n *=============================================================================================*/\nModemRegistryEntryClass::~ModemRegistryEntryClass (void)\n{\n\tif (ModemName) delete [] ModemName;\n\tif (ModemDeviceName) delete [] ModemDeviceName;\n\n\tif (ErrorCorrectionEnable) delete [] ErrorCorrectionEnable;\n\tif (ErrorCorrectionDisable) delete [] ErrorCorrectionDisable;\n\n\tif (CompressionEnable) delete [] CompressionEnable;\n\tif (CompressionDisable) delete [] CompressionDisable;\n\n\tif (HardwareFlowControl) delete [] HardwareFlowControl;\n\tif (NoFlowControl) delete [] NoFlowControl;\n}\n\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/MONO.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\u001b;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Mono Screen system                       *\n;*                                                                         *\n;*                    File Name : MONO.ASM                                 *\n;*                                                                         *\n;*                   Programmer : Jeff Wilson                              *\n;*                                                                         *\n;*                   Start Date : March 28, 1994                           *\n;*                                                                         *\n;*                  Last Update : September 8, 1994   [IML]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;GLOBAL              MonoScreen           :DWORD\n;GLOBAL              MonoEnabled          :DWORD\n;\n;GLOBAL C            Mono_Set_Cursor      :NEAR\n;GLOBAL C            Mono_Clear_Screen    :NEAR\n;GLOBAL C            Mono_Scroll          :NEAR\n;GLOBAL C            Mono_Put_Char        :NEAR\n;GLOBAL C            Mono_Draw_Rect       :NEAR\n;\n;GLOBAL C            _Mono_Text_Print     :NEAR\n;GLOBAL C            Mono_Text_Print      :NEAR\n;\n;GLOBAL C            Mono_Print           :NEAR\n;\n;GLOBAL C            Mono_View_Page       :NEAR\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nLOCALS ??\n\n\n;\n; External declares so these functions can be called\n;\nGLOBAL          MonoScreen              :DWORD\nGLOBAL          MonoEnabled             :DWORD  \n\nGLOBAL         Mono_Set_Cursor         :NEAR\t; done\nGLOBAL         Mono_Clear_Screen       :NEAR\t; done\nGLOBAL         Mono_Scroll             :NEAR\t; done\nGLOBAL         Mono_Put_Char           :NEAR\t; done\nGLOBAL         Mono_Draw_Rect          :NEAR\t; done\nGLOBAL        _Mono_Text_Print         :NEAR\t; done\nGLOBAL         Mono_Text_Print         :NEAR\t; done\nGLOBAL         Mono_Print              :NEAR \t; done\nGLOBAL         Mono_View_Page          :NEAR\t; done\n\n;\n; Equates used in this file\n;\nNULL =  0       ; null code\nCR   =  13      ; carriage return code\nCPL  =  80      ; characters per line\nLPS  =  25      ; lines per screen\n\n\nDATASEG\n\nMonoX           DD      0\nMonoY           DD      0\nMonoOff         DD      0\nMonoScreen      DD      0b0000h                 ;Deffault to Real mode!\nMonoEnabled     DD      0                       ; Is mono printing enabled?\n\n;====================================================================\n\nCharData        DB      0DAh,0C4h,0BFh,0B3h,0D9h,0C4h,0C0h,0B3h ; Single line\n                DB      0D5h,0CDh,0B8h,0B3h,0BEh,0CDh,0D4h,0B3h ; Double horz.\n                DB      0D6h,0C4h,0B7h,0BAh,0BDh,0C4h,0D3h,0BAh ; Double vert.\n                DB      0C9h,0CDh,0BBh,0BAh,0BCh,0CDh,0C8h,0BAh ; Double line.\n\n\n;               x,y,dist\nBoxData DB      1,0,0           ; Upper left corner.\n        DB      1,0,1           ; Top edge.\n        DB      0,1,0           ; Upper right corner.\n        DB      0,1,2           ; Right edge.\n        DB      -1,0,0          ; Bottom right corner.\n        DB      -1,0,1          ; Bottom edge.\n        DB      0,-1,0          ; Bottom left corner.\n        DB      0,-1,2          ; Left edge.\n        DB      0,0,-1          ; End of list.\n\n; Mono page segment layout array.\nPageMap DD      0,1,2,3,4,5,6,7\n\n;===================================================================\n\nCODESEG\n\n\n;***************************************************************************\n;* Map_Segment_To_Address_ -- Translate a 16bit Seg:Offset address to a    *\n;*                            Linear address.                              *                            \n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; int Map_Segment_To_Address ( unsigned seg , unsigned offset );\n\n\n\n;***************************************************************************\n;* MONO_SET_CURSOR -- Sets the mono cursor to specified coordinates.       *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; void Mono_Set_Cursor(int x, int y);\n\n\nPROC Mono_Set_Cursor    C near \n\n        USES eax , ebx , edx \n\n        ARG     xpos : DWORD\n        ARG     ypos : DWORD\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n\n;       mov     ax,cs\n;       and     ax,7\n;       or      ax,SS_DATA\n\n;       mov     ds,ax\n;       mov     es,ax\n\n;       sub     eax,eax\n\n        mov     eax,[ypos]\n;        mov     ah,CPL\n;        imul    ah\n  lea  eax , [ eax + 4 * eax ]   ; multiply by CPL\n  shl  eax , 4\n\n;       sub     ebx,ebx\n        mov     ebx,[xpos]\n        add     ebx,eax\n\n        ; Update cursor position.\n        mov     edx,03B4h\n\n        mov     al,0Eh                  ; High byte register set.\n        out     dx,al\n        inc     edx\n        mov     al,bh\n        out     dx,al                   ; Set high byte.\n\n        dec     edx\n        mov     al,0Fh                  ; Low byte register set.\n        out     dx,al\n        inc     edx\n        mov     al,bl\n        out     dx,al                   ; Set low byte.\n\n        ; Update the globals.\n        add     ebx,ebx\n        mov     [MonoOff],ebx\n        mov     eax,[xpos]\n        mov     [MonoX],eax\n        mov     eax,[ypos]\n        mov     [MonoY],eax\n\n??exit:\n        ret\n\nENDP    Mono_Set_Cursor\n\n\n;***************************************************************************\n;* MONO_CLEAR_SCREEN -- Clears the mono screen and homes cursor.           *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; void Mono_Clear_Screen(void);\n\nPROC Mono_Clear_Screen  C near \n        \n        USES eax , ecx , edi\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n\n;       mov     ax,cs\n;       and     ax,7\n;       or      ax,SS_DATA\n\n;       mov     ds,ax\n;       mov     es,ax\n\n;       mov     eax,[MonoScreen]        ; ES:DI = Mono RAM address.\n;       mov     es,ax\n;       sub     edi,edi\n   mov  edi , [ MonoScreen ]\n        mov     eax,02000200h           ; Clear leave attrib bit normal.\n        mov     ecx,8000h/4             ; Number of longs to clear.\n        rep     stosd                       ; Clear the mono screen.\n\n        push    0\n        push    0\n\n        call    Mono_Set_Cursor\n        add     esp , 8\n\n??exit:\n        ret\n\nENDP    Mono_Clear_Screen\n\n\n;***************************************************************************\n;* MONO_SCROLL -- Scroll the mono screen up specified lines.               *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; void Mono_Scroll(DWORD lines);\nPROC Mono_Scroll        C near \n\n        USES \teax , ebx , ecx , edx , edi , esi\n        ARG     lines : DWORD\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n\n;       mov     ax,cs\n;       and     ax,7\n;       or      ax,SS_DATA\n\n;       mov     ds,ax\n;       mov     es,ax\n\n;       xor     eax,eax                 ; clear eax so no need for sign extend\n        mov     eax, [lines]             ; get lines available\n        or      eax,eax                 ; any lines  to scroll?\n        je      short ??fini            ; =>NO\n\n        mov     ebx,eax                 ; set line counter\n                                                    \n        mov     edx,[MonoY]             ; get row count\n        ror     edx,16                  ; store it in high half of register\n        mov     dx,[WORD PTR MonoOff]   ; get column offset\n        ror     edx,16\n                     \n;        mov     eax,[MonoScreen]        ; get selector for mono screen\n;        push    ds                      ; save off data seg for later\n;        mov     ds,ax                   ; set data source register\n;        mov     es,ax                   ;  and extra source register\n\n        sub     eax,eax                 ; set to clear clear line\n        \n??looper:\n        mov     ecx,(80*24)             ; Number of words to move.\n\n ;      xor     edi,edi                 ; dst start at top of screen area\n ;      mov     esi,80*2                ; src start at next line down\n    mov edi , [ MonoScreen ]\n    lea esi , [ 80 * 2 + edi ]       \n        rep     movsw                   ; Scroll the screen upward.\n\n        dec     dx                      ; decrement Y counter\n        ror     edx,16                  ; switch to mono offset\n        sub     dx,80*2                 ; fix MonoOffset\n        ror     edx,16                  ; switch to y counter\n\n        mov     ecx,40                  ; Clear out the last line.\n        rep     stosd                   ;   by storing words across it\n        dec     ebx                     ; last line?\n\n        jne     ??looper                ; =>NO\n\n        ; reset data values\n  ;     pop     ds                      ; restore the ds segment\n        mov     [WORD PTR MonoY],dx     ; store of the mono y position\n        ror     edx,16                  ; switch to screen offset\n        mov     [WORD PTR MonoOff],dx   ; store of the mono offset\n                \n??fini:\n??exit:\n        ret\n\nENDP    Mono_Scroll\n\n\n;***************************************************************************\n;* MONO_PUT_CHAR -- Output a character to the mono screen.                 *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; void Mono_Put_Char(char character, int attrib=2);\n\nPROC Mono_Put_Char      C near \n\n        USES    eax , edi\n\n        ARG     character : BYTE\n        ARG     attrib    : DWORD\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n                       \n;       mov     ax,cs\n;       and     ax,7\n;       or      ax,SS_DATA\n\n;       mov     ds,ax\n\n        mov     edi,[MonoOff]\n;        mov     eax,[MonoScreen]\n;        mov     es,ax                   ; ES:DI = First character output pointer.\n   add edi , [ MonoScreen ]\n\n        ; Output character to monochrome monitor.\n        mov     al,[character]\n        mov     ah,[BYTE PTR attrib]\n;       stosw       \n        mov     [ edi ] , ax\n\n        ; Update cursor position.\n        inc     [MonoX]         ; X position moves.\n\n        mov     eax,[MonoY]\n        push    eax\n        mov     eax,[MonoX]\n        push    eax\n\n        call    Mono_Set_Cursor \n        add     esp,8\n\n??exit:\n        ret\n\nENDP    Mono_Put_Char\n\n\n;***************************************************************************\n;* MONO_DRAW_RECT -- Draw a rectangle using mono characters.               *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; void Mono_Draw_Rect(int x, int y, int w, int h, int attrib=2, int thick=0);\n\nPROC Mono_Draw_Rect     C near \n\n        USES eax , ebx , ecx , esi , edi\n\n        ARG     xpos:DWORD\n        ARG     ypos:DWORD\n        ARG     width:DWORD\n        ARG     height:DWORD\n        ARG     attrib:DWORD\n        ARG     thick:DWORD\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n\n;       mov     ax,cs\n;       and     ax,7\n;       or      ax,SS_DATA\n\n;       mov     ds,ax\n;       mov     es,ax\n\n        mov     esi,OFFSET BoxData\n        mov     edi,OFFSET CharData\n\n;       mov     cl,3\n;       sub     eax,eax\n        mov     eax,[thick]\n        and     eax,011b\n        shl     eax,3\n        add     edi,eax\n\n        ; Prep width and height.\n        cmp     [width],2\n        jb      ??fini\n\n        cmp     [height],2\n        jb      ??fini\n\n        sub     [width],2\n        sub     [height],2\n\n        ; Preserve cursor position for later restore.\n        mov     ecx,[MonoX]\n        push    ecx\n        mov     ecx,[MonoY]\n        push    ecx\n\n        ; Cursor starts at upper left corner.\n        mov     ecx,[ypos]\n        push    ecx\n        mov     ecx,[xpos]\n        push    ecx\n        call    Mono_Set_Cursor \n        add     esp,8\n\n??drawloop:\n        ; Determine the number of characters to output.\n        mov     ecx,[width]\n        cmp     [BYTE PTR esi+2],1\n        je      short ??gotlen\n\n        mov     ecx,[height]\n        cmp     [BYTE PTR esi+2],2\n        je      short ??gotlen\n\n        mov     ecx,1\n??gotlen:\n\n        jecxz   ??donerun\n\n??runloop:\n        sub     ebx,ebx\n        mov     bl,[BYTE PTR edi]\n\n;       mov     ebx,eax\n        sub     eax,eax\n        mov     al,[BYTE PTR attrib]\n        push    eax\n        push    ebx\n\n        call    Mono_Put_Char \n        add     esp,8\n\n        movsx   eax,[BYTE PTR esi+1]\n;       cbw\n        add     eax,[MonoY]\n        push    eax\n        movsx   eax,[BYTE PTR esi]\n;       cbw\n        add     eax,[MonoX]\n        dec     eax                     ; Undo cursor advance.\n        push    eax\n\n        call    Mono_Set_Cursor         ; Properly advance cursor.\n        add     esp,8\n\n        loop    ??runloop\n\n??donerun:\n\n        ; Advance to next control entry.\n        add     esi,3\n        inc     edi\n        cmp     [BYTE PTR esi+2],-1\n        jne     ??drawloop\n\n        ; Restore cursor to original position.\n        call    Mono_Set_Cursor\n        add     esp,8\n\n??fini:\n??exit:\n        ret\n\nENDP    Mono_Draw_Rect\n\n\n;***************************************************************************\n;* MONO_TEXT_PRINT -- Prints text to the mono screen at coordinates.       *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; void Mono_Text_Print(void *text, int x, int y, int attrib, int update);\n\nPROC _Mono_Text_Print   C near \n\n        USES eax,ebx,ecx,edx,edi,esi\n\n        ARG     text:DWORD\n        ARG     xpos:DWORD\n        ARG     ypos:DWORD\n        ARG     attrib:DWORD\n        ARG     update:DWORD\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n\n;       mov     ax,cs\n;       and     ax,7\n;       or      ax,SS_DATA\n\n;       mov     ds,ax\n;       mov     es,ax\n\n        ; Preserve cursor coordinates for later restoration.\n        mov     eax,[MonoY]\n        push    eax\n        mov     eax,[MonoX]\n        push    eax\n\n        cmp     [text],NULL\n        je      ??fini\n\n        mov     eax,[ypos]\n        push    eax\n        mov     eax,[xpos]\n        push    eax\n        call    Mono_Set_Cursor \n        add     esp,8\n\n        mov     esi,[text]\n\n??charloop:\n        xor     eax,eax\n        mov     al,[BYTE PTR esi]               ; Fetch character to output.\n        inc     esi\n\n        ; Stop processing on a NULL character.\n        or      eax,eax\n        je      short ??fini\n\n        ; Special processing for a '\\r' characters.\n        cmp     eax,CR\n        je      short ??cr\n\n        ; Output character to monochrome monitor.\n??normal:\n;       xor     ah,ah\n\n        mov     ebx,eax\n        mov     eax,[attrib]\n        push    eax\n        push    ebx\n        call    Mono_Put_Char \n        add     esp,8\n\n        ; Perform adjustments if wrapping past right margin.\n        cmp     [WORD PTR MonoX],CPL\n        jb      short ??nowrap\n\n        inc     [ypos]\n\n        mov     eax,[ypos]\n        push    eax\n;       sub     eax,eax\n        push    0\n        call    Mono_Set_Cursor \n        add     esp,8\n\n        jmp short ??nowrap\n\n        ; Move to start of next line.\n??cr:\n        inc     [ypos]\n\n        mov     eax,[ypos]\n        push    eax\n        mov     eax,[xpos]\n        push    eax\n        call    Mono_Set_Cursor \n        add     esp,8\n\n        ; Scroll the monochrome screen if necessary.\n??nowrap:\n        cmp     [MonoY],LPS\n        jb      short ??noscroll\n\n        push    1\n        call    Mono_Scroll \n        add     esp,4\n\n        dec     [ypos]\n\n??noscroll:\n        jmp short ??charloop\n\n??fini:\n        cmp     [update],0\n        jne     short ??noupdate\n\n        call    Mono_Set_Cursor\n??noupdate:\n        add     esp,8\n\n??exit:\n        ret\n\nENDP    _Mono_Text_Print\n\n;=====================================================================\n\nPROC Mono_Text_Print    C near \n        USES    eax\n        ARG     text:DWORD\n        ARG     xpos:DWORD\n        ARG     ypos:DWORD\n        ARG     attrib:DWORD\n\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n\n;       sub     eax,eax\n        push    0\n        mov     eax,[attrib]\n        push    eax\n        mov     eax,[ypos]\n        push    eax\n        mov     eax,[xpos]\n        push    eax\n        mov     eax,[text]\n        push    eax\n\n        call    _Mono_Text_Print \n        add     esp,20\n\n??exit:\n        ret\n\nENDP    Mono_Text_Print\n\n\n\n;***************************************************************************\n;* MONO_PRINT -- Prints text to the mono screen at current pos.            *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; void Mono_Print(void *text);\n\nPROC Mono_Print         C near \n        \n        USES eax\n\n        ARG     text:DWORD\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n\n;       mov     ax,cs\n;       and     ax,7\n;       or      ax,SS_DATA\n\n;       mov     ds,ax\n;       mov     es,ax\n\n;       mov     eax,1\n        push    1\n;       mov     eax,2\n        push    2\n        mov     eax,[MonoY]\n        push    eax\n        mov     eax,[MonoX]\n        push    eax\n        mov     eax,[text]\n        push    eax\n\n        call    _Mono_Text_Print \n        add     esp,20\n\n??exit:\n        ret\n\nENDP    Mono_Print\n\n;***************************************************************************\n;* Mono_View_Page -- page in a mono screen                                 *\n;*                                                                         *\n;*   Displays the specified page in displayable mono memory area.          *\n;*                                                                         *\n;* INPUT:  WORD page = which page of memory we will use for storage        *\n;*                                                                         *\n;* OUTPUT: old_page                                                        *\n;*                                                                         *\n;* WARNINGS:    none.                                                      *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; int cdecl Mono_View_Page(int page);\n\n\nPROC Mono_View_Page     C near \n\n        USES eax,ebx,ecx,edx,edi,esi\n\n        ARG     page:DWORD\n\n        LOCAL   oldpage:DWORD\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n\n        cld\n\n;       mov     ax,cs\n;       and     ax,7\n;       or      ax,SS_DATA\n\n;       mov     ds,ax\n;       mov     es,ax\n\n        ; Prepare the original page number for return to caller.\n        mov     ebx,[PageMap]\n        mov     [oldpage],ebx\n\n        ; If the desired page is already displayed, then don't do anything.\n        mov     eax,[page]\n        cmp     eax,ebx\n        je      short ??fini\n\n        ; Verify that page specified is legal.\n        cmp     eax,7\n        ja      short ??fini\n\n        ; Find where the logical page to display is actually located.\n        mov     ecx,8\n\n        mov     edi,OFFSET PageMap\n        repne   scasd\n        neg     ecx\n        add     ecx,7                   ; ECX = where desired page is located.\n\n        ; Swap the page ID bytes in the PageMap array.\n        sub     edi,4\n        mov     ebx,[PageMap]\n        mov     eax,[edi]\n        mov     [edi],ebx\n        mov     [PageMap],eax\n\n        ; Set DS and ES to point to each page.\n;        mov     eax,[MonoScreen]\n;        mov     ds,ax\n   mov esi , [ MonoScreen ]\n;        shl     ecx,8\n   shl ecx , 12\n;        add     ecx,edi                 ; NO Addition to selectors!\n   lea edi , [ esi + ecx ]\n\n;       mov     edi,ecx\n;       xor     esi,esi\n\n        ; Exchange the two pages.\n        mov     ecx,1000H/4\n\n??looper:\n        mov     edx,[edi]\n        mov     ebx,[esi]\n        mov     [edi],ebx\n        mov     [esi],edx\n        add     esi,4\n        add     edi,4\n        loop    ??looper\n\n        ; Return with the original page number.\n??fini:\n??exit:\n        mov     eax,[oldpage]\n        ret\n        \nENDP    Mono_View_Page\n\nEND\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/MONO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\monoc.cpv   2.12   06 Sep 1995 16:37:54   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***             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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MONO.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 2, 1994                                                 *\n *                                                                                             *\n *                  Last Update : October 17, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   MonoClass::Clear -- Clears the monochrome screen object.                                  *\n *   MonoClass::Draw_Box -- Draws a box using the IBM linedraw characters.                     *\n *   MonoClass::MonoClass -- The default constructor for monochrome screen object.             *\n *   MonoClass::operator = -- Handles making one mono object have the same imagery as another. *\n *   MonoClass::Print -- Prints the text string at the current cursor coordinates.             *\n *   MonoClass::Printf -- Prints a formatted string to the monochrome screen.                  *\n *   MonoClass::Scroll -- Scroll the monochrome screen up by the specified lines.              *\n *   MonoClass::Set_Cursor -- Sets the monochrome cursor to the coordinates specified.         *\n *   MonoClass::Text_Print -- Prints text to the monochrome object at coordinates indicated.   *\n *   MonoClass::View -- Brings the mono object to the main display.                            *\n *   MonoClass::~MonoClass -- The default destructor for a monochrome screen object.           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n//#pragma inline\n#include\t\"mono.h\"\n\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<dos.h>\n#include\t<mem.h>\n#include\t<stdarg.h>\n#include\t<string.h>\n\n\nextern void output(short port, short data);\n#pragma aux output parm [dx] [ax] =\t\t\\\n\t\t\"out\tdx,al\"\t\t\\\n\t\t\"inc\tdx\"\t\t\t\\\n\t\t\"mov\tal,ah\"\t\t\\\n\t\t\"out\tdx,al\"\n\nint MonoClass::Enabled = 0;\nMonoClass * MonoClass::PageUsage[MonoClass::MAX_MONO_PAGES] = {0,0,0,0,0,0,0,0};\nvoid * MonoClass::MonoSegment = (void*)0x000b0000;\n\n/*\n**\tThese are the IBM linedraw characters.\n*/\nMonoClass::BoxDataType const MonoClass::CharData[MonoClass::COUNT] = {\n\t{0xDA,0xC4,0xBF,0xB3,0xD9,0xC4,0xC0,0xB3},\t// Single line\n\t{0xD5,0xCD,0xB8,0xB3,0xBE,0xCD,0xD4,0xB3},\t// Double horz.\n\t{0xD6,0xC4,0xB7,0xBA,0xBD,0xC4,0xD3,0xBA},\t// Double vert.\n\t{0xC9,0xCD,0xBB,0xBA,0xBC,0xCD,0xC8,0xBA}\t\t// Double horz and vert.\n};\n\n\n/***********************************************************************************************\n * MonoClass::MonoClass -- The default constructor for monochrome screen object.               *\n *                                                                                             *\n *    This is the constructor for monochrome screen objects. It handles allocating a free      *\n *    monochrome page. If there are no more pages available, then this is a big error. The     *\n *    page allocated may not be the visible one. Call the View function in order to bring      *\n *    it to the displayed page.                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nMonoClass::MonoClass(void)\n{\n\tint\tindex;\n\n\tAttrib = DEFAULT_ATTRIBUTE;\t\t// Normal text color.\n\tX = Y = 0;\n\tfor (index = 0; index < MAX_MONO_PAGES; index++) {\n\t\tif (!PageUsage[index]) {\n\t\t\tPageUsage[index] = this;\n\t\t\tPage = (char)index;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (index == MAX_MONO_PAGES) {\n\t\t// Major error message should pop up here!\n\t\tdelete this;\n\t}\n}\n\n\n/***********************************************************************************************\n * MonoClass::~MonoClass -- The default destructor for a monochrome screen object.             *\n *                                                                                             *\n *    This is the default destructor for a monochrome screen object.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nMonoClass::~MonoClass(void)\n{\n\tPageUsage[Page] = 0;\n}\n\n\n/***********************************************************************************************\n * MonoClass::Draw_Box -- Draws a box using the IBM linedraw characters.                       *\n *                                                                                             *\n *    Use this routine to draw a box to the monochrome screen. The IBM line draw characters    *\n *    are used to give the it a fancy appearance. There are several line draw modes supported. *\n *                                                                                             *\n * INPUT:   x,y      -- The coordinates of the upper left corner of the box.                   *\n *                                                                                             *\n *          w,y      -- The width and height (respectively) to make the box.                   *\n *                                                                                             *\n *          attrib   -- The text attribute to use when drawing the box outline characters.     *\n *                                                                                             *\n *          thick    -- The thickness style to use. Examine the BoxStyleType enum for          *\n *                      elaboration on the supported styles.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The interior of the box is NOT cleared by this routine. It is advised that this *\n *             area be cleared before the box is drawn.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Draw_Box(int x, int y, int w, int h, char attrib, BoxStyleType thick)\n{\n\tCellType\tcell;\n\tchar\toldattrib = Attrib;\n\n\tif (!Enabled || !w || !h) return;\n\n\tcell.Attribute = attrib;\n\n\t/*\n\t**\tDraw the horizontal lines.\n\t*/\n\tfor (int xpos = 0; xpos < w-2; xpos++) {\n\t\tcell.Character = CharData[thick].TopEdge;\n\t\tStore_Cell(cell, x+xpos+1, y);\n\t\tcell.Character = CharData[thick].BottomEdge;\n\t\tStore_Cell(cell, x+xpos+1, y+h-1);\n\t}\n\n\t/*\n\t**\tDraw the vertical lines.\n\t*/\n\tfor (int ypos = 0; ypos < h-2; ypos++) {\n\t\tcell.Character = CharData[thick].LeftEdge;\n\t\tStore_Cell(cell, x, y+ypos+1);\n\t\tcell.Character = CharData[thick].RightEdge;\n\t\tStore_Cell(cell, x+w-1, y+ypos+1);\n\t}\n\n\t/*\n\t**\tDraw the four corners.\n\t*/\n\tif (w > 1 && h > 1) {\n\t\tcell.Character = CharData[thick].UpperLeft;\n\t\tStore_Cell(cell, x, y);\n\t\tcell.Character = CharData[thick].UpperRight;\n\t\tStore_Cell(cell, x+w-1, y);\n\t\tcell.Character = CharData[thick].BottomRight;\n\t\tStore_Cell(cell, x+w-1, y+h-1);\n\t\tcell.Character = CharData[thick].BottomLeft;\n\t\tStore_Cell(cell, x, y+h-1);\n\t}\n\n\tAttrib = oldattrib;\n}\n\n\n/***********************************************************************************************\n * MonoClass::Set_Cursor -- Sets the monochrome cursor to the coordinates specified.           *\n *                                                                                             *\n *    Use this routine to set the monochrome's cursor position to the coordinates specified.   *\n *    This is the normal way of controlling where the next Print or Printf will output the     *\n *    text to.                                                                                 *\n *                                                                                             *\n * INPUT:   x,y   -- The coordinate to position the monochrome cursor. 0,0 is the upper left   *\n *                   corner.                                                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Set_Cursor(int x, int y)\n{\n#if(0)\n\tint\tpos = (y*COLUMNS)+x;\n\n\tif (!Enabled) return;\n\n\tX = (char)(x%COLUMNS);\n\tY = (char)(y%LINES);\n\n\tif (Page == 0) {\n\t\t_DX = CONTROL_PORT;\n\t\t_AX = (short)(0x0E|(pos&0xFF00));\n\t\tasm {\n\t\t\tout\tdx,al\n\t\t\tinc\tdx\n\t\t\tmov\tal,ah\n\t\t\tout\tdx,al\n\t\t}\n\n\t\t_DX = CONTROL_PORT;\n\t\t_AX = (short)(0x0F|(pos<<8));\n\t\tasm {\n\t\t\tout\tdx,al\n\t\t\tinc\tdx\n\t\t\tmov\tal,ah\n\t\t\tout\tdx,al\n\t\t}\n\n\t}\n#else\n\tint\tpos = (y*COLUMNS)+x;\n\n\tif (!Enabled) return;\n\n\tX = (char)(x%COLUMNS);\n\tY = (char)(y%LINES);\n\n\tif (Page == 0) {\n\t\toutput(CONTROL_PORT,\n\t\t\t(short)0x0E|(short)(pos&0xFF00));\n\t\toutput(CONTROL_PORT,\n\t\t\t(short)0x0F|(short)(pos<<8));\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * MonoClass::Clear -- Clears the monochrome screen object.                                    *\n *                                                                                             *\n *    This routine will fill the monochrome screen object with spaces. It is clearing the      *\n *    screen of data, making it free for output. The cursor is positioned at the upper left    *\n *    corner of the screen by this routine.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Clear(void)\n{\n\tCellType\tcell;\n\n\tif (!Enabled) return;\n\n\tSet_Cursor(0, 0);\n\n\tcell.Attribute = Attrib;\n\tcell.Character = ' ';\n\n\tfor (int y = 0; y < LINES; y++) {\n\t\tfor (int x = 0; x < COLUMNS; x++) {\n\t\t\tStore_Cell(cell, x, y);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MonoClass::Scroll -- Scroll the monochrome screen up by the specified lines.                *\n *                                                                                             *\n *    Use this routine to scroll the monochrome screen up by the number of lines specified.    *\n *    This routine is typically called by the printing functions so that the monochrome screen *\n *    behaves in the expected manner -- printing at the bottom of the screen scrolls it up     *\n *    to make room for new text.                                                               *\n *                                                                                             *\n * INPUT:   lines -- The number of lines to scroll the monochrome screen.                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Scroll(int lines)\n{\n\tCellType\tcell;\n\n\tif (!Enabled || lines <= 0) return;\n\n\tmemmove( (void*)((long)MonoSegment + Offset(0, 0)),\n\t\t\t\t(void*)((long)MonoSegment + Offset(0, lines)),\n\t\t\t\t(LINES-lines)*COLUMNS*sizeof(CellType));\n\n\n\tY--;\n\tcell.Attribute = Attrib;\n\tcell.Character = ' ';\n\n\tfor (int l = LINES-lines; l < LINES; l++) {\n\t\tfor (int index = 0; index < COLUMNS; index++) {\n\t\t\tStore_Cell(cell, index, l);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MonoClass::Printf -- Prints a formatted string to the monochrome screen.                    *\n *                                                                                             *\n *    Use this routine to output a formatted string, using the standard formatting options,    *\n *    to the monochrome screen object's current cursor position.                               *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text to print.                                             *\n *                                                                                             *\n *          ...   -- Any optional parameters to supply in formatting the text.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The total formatted text length must not exceed 255 characters.                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Printf(char const *text, ...)\n{\n\tva_list\tva;\n\t/*\n\t**\tThe buffer object is placed at the end of the local variable list\n\t**\tso that if the sprintf happens to spill past the end, it isn't likely\n\t**\tto trash anything (important). The buffer is then manually truncated\n\t**\tto maximum allowed size before being printed.\n\t*/\n\tchar buffer[256];\n\n\tif (!Enabled) return;\n\n\tva_start(va, text);\n\tvsprintf(buffer, text, va);\n\tbuffer[sizeof(buffer)-1] = '\\0';\n\n\tPrint(buffer);\n\tva_end(va);\n}\n\n\n#ifdef NEVER\nvoid MonoClass::Printf(int text, ...)\n{\n\tva_list\tva;\n\t/*\n\t**\tThe buffer object is placed at the end of the local variable list\n\t**\tso that if the sprintf happens to spill past the end, it isn't likely\n\t**\tto trash anything (important). The buffer is then manually truncated\n\t**\tto maximum allowed size before being printed.\n\t*/\n\tchar buffer[256];\n\n\tif (!Enabled) return;\n\n\tva_start(va, text);\n\tvsprintf(buffer, Text_String(text), va);\n\tbuffer[sizeof(buffer)-1] = '\\0';\n\n\tPrint(buffer);\n\tva_end(va);\n}\n#endif\n\n\n/***********************************************************************************************\n * MonoClass::Print -- Prints the text string at the current cursor coordinates.               *\n *                                                                                             *\n *    Use this routine to output the specified text string at the monochrome object's current  *\n *    text coordinate position.                                                                *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the string to print.                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Print(char const *ptr)\n{\n\tchar startcol = X;\n\tchar const * text;\n\tCellType\tcell;\n\n\tif (!ptr || !Enabled) return;\n\n\ttext = ptr;\n\tcell.Attribute = Attrib;\n\twhile (*text) {\n\n\t\t/*\n\t\t**\tSometimes the character string is used for cursor control instead\n\t\t**\tof plain text output. Check for this case.\n\t\t*/\n\t\tswitch (*text) {\n\n\t\t\t/*\n\t\t\t**\tThe \"return\" code behaves as it did in the old C library\n\t\t\t**\tmono system. That is, it returns the cursor position to\n\t\t\t**\tthe next line but at the starting column of the print.\n\t\t\t*/\n\t\t\tcase '\\r':\n\t\t\t\tX = startcol;\n\t\t\t\tY++;\n\t\t\t\tScroll(Y-(LINES-1));\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tThe \"newline\" code behaves like the console newline character.\n\t\t\t**\tThat is, it moves the cursor down one line and at the first\n\t\t\t**\tcolumn.\n\t\t\t*/\n\t\t\tcase '\\n':\n\t\t\t\tX = 0;\n\t\t\t\tY++;\n\t\t\t\tScroll(Y-(LINES-1));\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tAll other characters are output directly and the cursor moves\n\t\t\t**\trightward to match. If the cursor wraps past the right\n\t\t\t**\tedge is it moved to the next now down at left margin. If the\n\t\t\t**\tcursor goes off the bottom of the display, the display is scrolled\n\t\t\t**\tupward a line.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\tcell.Character = *text;\n\t\t\t\tStore_Cell(cell, X, Y);\n\n\t\t\t\tX++;\n\t\t\t\tif (X >= COLUMNS) {\n\t\t\t\t\tX = 0;\n\t\t\t\t\tY++;\n\n\t\t\t\t\tif (Y > (LINES-1)) {\n\t\t\t\t\t\tScroll(Y-(LINES-1));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t}\n\t\ttext++;\n\t}\n\n\tSet_Cursor(X, Y);\n}\n\n\n/***********************************************************************************************\n * MonoClass::Text_Print -- Prints text to the monochrome object at coordinates indicated.     *\n *                                                                                             *\n *    Use this routine to output text to the monochrome object at the X and Y coordinates      *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text string to display.                                    *\n *                                                                                             *\n *          x,y   -- The X and Y character coordinates to start the printing at.               *\n *                                                                                             *\n *          attrib-- Optional parameter that specifies what text attribute code to use.        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Text_Print(char const *text, int x, int y, char attrib)\n{\n\tchar\toldx = X;\n\tchar\toldy = Y;\n\tchar\toldattrib = Attrib;\n\n\tX = (char)x;\n\tY = (char)y;\n\tAttrib = attrib;\n\tPrint(text);\n\tAttrib = oldattrib;\n\tSet_Cursor(oldx, oldy);\n}\n\n#ifdef NEVER\nvoid MonoClass::Text_Print(int text, int x, int y, char attrib)\n{\n\tchar\toldx = X;\n\tchar\toldy = Y;\n\tchar\toldattrib = Attrib;\n\n\tif (text != TXT_NONE) {\n\t\tX = (char)x;\n\t\tY = (char)y;\n\t\tAttrib = attrib;\n\t\tPrint(Text_String(text));\n\t\tAttrib = oldattrib;\n\t\tSet_Cursor(oldx, oldy);\n\t}\n}\n\nvoid MonoClass::Print(int text)\n{\n\tPrint(Text_String(text));\n}\n#endif\n\n\n/***********************************************************************************************\n * MonoClass::operator = -- Handles making one mono object have the same imagery as another.   *\n *                                                                                             *\n *    The assignment operator will handle copying the imagery from one monochrome object to    *\n *    another. Use this routine in to make two monochrome class objects visually identical.    *\n *                                                                                             *\n * INPUT:   src   -- A reference to the source (right side) monochrome object.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nMonoClass & MonoClass::operator = (MonoClass const & src)\n{\n\tmemcpy((void*)((long)MonoSegment + src.Offset(0, 0)), (void*)((long)MonoSegment + Offset(0, 0)), SIZE_OF_PAGE);\n\tSet_Cursor(src.X, src.Y);\n\treturn(*this);\n}\n\n\n/***********************************************************************************************\n * MonoClass::View -- Brings the mono object to the main display.                              *\n *                                                                                             *\n *    Use this routine to display the mono object on the monochrome screen. It is possible     *\n *    that the mono object exists on some background screen memory. Calling this routine will  *\n *    perform the necessary memory swapping to bring the data to the front. The mono object    *\n *    that was currently being viewed is not destroyed by this function. It is merely moved    *\n *    off to some background page. It can be treated normally, except that is just isn't       *\n *    visible.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::View(void)\n{\n\tMonoClass *displace;\t\t// The page that is being displaced.\n\n\tif (Get_Current() == this) return;\n\n\t/*\n\t**\tIf the visible page is already assigned to a real monochrome page\n\t**\tobject, then it must be swapped with the new one.\n\t*/\n\tdisplace = Get_Current();\n\tif (displace) {\n\t\tchar temp[SIZE_OF_PAGE];\n\n\t\tmemcpy(&temp[0], MonoSegment, SIZE_OF_PAGE);\n\t\tmemcpy(MonoSegment, (void*)((long)MonoSegment + Offset(0, 0)), SIZE_OF_PAGE);\n\t\tmemcpy((void*)((long)MonoSegment + Offset(0, 0)), &temp[0], SIZE_OF_PAGE);\n\n\t\tdisplace->Page = Page;\n\n\t} else {\n\n\t\t/*\n\t\t**\tJust copy the new page over since the display page is not assigned\n\t\t**\tto a real monochrome page object.\n\t\t*/\n\t\tmemcpy(MonoSegment, (void*)((long)MonoSegment + Offset(0, 0)), SIZE_OF_PAGE);\n\t}\n\tPageUsage[Page] = displace;\n\tPageUsage[0] = this;\n\tPage = 0;\n\n\tSet_Cursor(X, Y);\n}\n\n\n\n/************************************************************************************\n**\tThis is the set of C wrapper functions that access the MonoClass support routines.\n**\tSince the C interface doesn't have the ability to write to non-visible pages, it\n**\twill just blast the output to whichever mono page is currently visible. If there is\n**\tno mono class object that is visible, then one will be created -- BUT NOT FREED.\n**\tTypically, this is ok, since the C interface will create only one MonoClass object\n**\tand the system supports up to 8.\n*/\nvoid Mono_Set_Cursor(int x, int y)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Set_Cursor(x, y);\n\t}\n}\n\nint Mono_Printf(char const *string, ...)\n{\n\tva_list\tva;\n\tchar buffer[256];\n\n\tbuffer[0] = '\\0';\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\n\t\tva_start(va, string);\n\t\tvsprintf(buffer, string, va);\n\n\t\tmono->Print(buffer);\n\n\t\tva_end(va);\n\t}\n\treturn((short)strlen(buffer));\n}\n\n\nvoid Mono_Clear_Screen(void)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Clear();\n\t}\n}\n\nvoid Mono_Text_Print(void const *text, int x, int y, int attrib)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Text_Print((const char*)text, x, y, (char)attrib);\n\t}\n}\n\nvoid Mono_Draw_Rect(int x, int y, int w, int h, int attrib, int thick)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Draw_Box(x, y, w, h, (char)attrib, (MonoClass::BoxStyleType)thick);\n\t}\n}\n\nvoid Mono_Print(void const *text)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Print((const char*)text);\n\t}\n}\n\nint Mono_X(void)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\treturn(short)mono->Get_X();\n\t}\n\treturn(0);\n}\n\nint Mono_Y(void)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\treturn(short)mono->Get_X();\n\t}\n\treturn(0);\n}\n\n\nvoid Mono_Put_Char(char , int )\n{\n}\n\nvoid Mono_Scroll(int )\n{\n}\n\nvoid Mono_View_Page(int )\n{\n}\n\n\n#ifdef NEVER\nint Mono_Printf(int string, ...)\n{\n\tva_list\tva;\n\tchar buffer[256];\n\n\tbuffer[0] = '\\0';\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass *mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\n\t\tva_start(va, string);\n\t\tvsprintf(buffer, Text_String(string), va);\n\n\t\tmono->Print(buffer);\n\n\t\tva_end(va);\n\t}\n\treturn((short)strlen(buffer));\n}\n#endif\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/MONOPRNT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : MONOPRNT.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : October 12, 1993                         *\n *                                                                         *\n *                  Last Update : November 2, 1993   [JLB]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Mono_Printf -- Prints formated text to the monochrome screen.         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t<stdarg.h>\n#include\t<string.h>\n#include\t<stdio.h>\n#include \"mono.h\"\n\n/***************************************************************************\n * Mono_Printf -- Prints formated text to the monochrome screen.           *\n *                                                                         *\n *    This routine is used to print formatted text (similar to printf) to  *\n *    the monochrome screen.                                               *\n *                                                                         *\n * INPUT:   string   -- The string that is to be printed.                  *\n *                                                                         *\n *          ...      -- Any optional parameters that the string requires   *\n *                      to format properly.                                *\n *                                                                         *\n * OUTPUT:  Returns with the length of the string that it printed to the   *\n *          monochrome screen.                                             *\n *                                                                         *\n * WARNINGS:   The total length of the formatted string must not exceed    *\n *             255 bytes.                                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/02/1993 JLB : Created.                                             *\n *=========================================================================*/\nint Mono_Printf(char const *string, ...)\n{\n\tva_list\tva;\n\tchar\t\tbuffer[256];\n\n\tif (!MonoEnabled) return(0);\n\t\t\n\tva_start(va, string);\n\n\tvsprintf(buffer, string, va);\n\tMono_Print(buffer);\n\n\tva_end(va);\n\treturn(strlen(buffer));\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/MORPHPAL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : wwlib32                                  *\n *                                                                         *\n *                    File Name : PALTOPAL.CPP                             *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : May 2, 1994                              *\n *                                                                         *\n *                  Last Update : May 2, 1994   [BR]                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Morph_Palette -- morphs a palette from source to destination          *\n *   Palette_To_Palette -- morph src palette to a dst palette              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n/*\n********************************* Includes **********************************\n*/\n#include \"wwstd.h\"\n#include \"palette.h\"\n#include \"timer.h\"\n\n/*\n********************************* Constants *********************************\n*/\n#define SCALE(a,b,c) (((((long)(a)<<8) / (long)(b) ) * (unsigned long)(c)) >>8)\n\n\n/*\n********************************** Globals **********************************\n*/\n\n/*\n******************************** Prototypes *********************************\n*/\n\nPRIVATE int __cdecl Palette_To_Palette(void *src_palette, void *dst_palette, unsigned long current_time, unsigned long delay);\n\n\n/***************************************************************************\n * Morph_Palette -- morphs a palette from source to destination            *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tvoid *src_pal\t- starting palette\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tvoid *dst_pal\t- ending palette\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tunsigned int delay\t- time delay in 60ths of a second\t\t\t\t\t\t\t*\n *\t\tvoid *callback\t- user-defined callback, NULL if none\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/02/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid cdecl Morph_Palette (void *src_pal, void *dst_pal, unsigned int delay,\n\tvoid (*callback) (void) )\n{\n\tint\tresult;\n\tunsigned long\tpal_start = TickCount.Time();\n\textern void   (*cb_ptr) ( void ) ;\t// callback function pointer\n\n//\t(void *)cb_ptr = callback;\n\tcb_ptr = callback ;\n\n\t/*===================================================================*/\n\t/* Make sure that we don't go too fast but also make sure we keep\t\t*/\n\t/*\t\tprocessing the morph palette if we have one.\t\t\t\t\t\t\t*/\n\t/*===================================================================*/\n\twhile (1) {\n\t\tif (src_pal && dst_pal) {\n\t\t\tresult = Palette_To_Palette (src_pal, dst_pal,\n\t\t\t\t(TickCount.Time() - pal_start), (unsigned long)delay);\n\t\t\tif (!result)\n\t\t\t\tbreak;\n\n\t\t\tif (callback) {\n\t\t\t\t(*cb_ptr)();\n\t\t\t}\n\t\t}\n\t}\n\n\treturn;\n\n}\t/* end of Morph_Palette */\n\n\n/***************************************************************************\n * Palette_To_Palette -- morph src palette to a dst palette                *\n *                                                                         *\n * Creates & sets a palette that's in-between 'src_palette' & \t\t\t\t\t*\n * 'dst_palette'; how close it is to dst_palette is based on how close \t\t*\n * 'current_time' is to 'delay'.  'current_time' & 'delay' are based on\t\t*\n * 0 being the start time.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:               void *src_palette =  palette we want to morph from *\n *                      void *dst_palette =  palette we want to morph to   *\n *                      long current_time =  time we started morph pal\t\t*\n *                      long delay         = time we want the morph to take*\n *                                                                         *\n * OUTPUT:\t\t\t\t\tint if the time had elapsed and no chages were\t\t*\n *\t\t\t\t\t\t\t\t\t  necessary this routine returns FALSE\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t  otherwise it will always return TRUE (this\t\t*\n *\t\t\t\t\t\t\t\t\t  was necessary to detect the end of the ice\t\t*\n *\t\t\t\t\t\t\t\t\t  effect.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/24/1993  MC : Created.                                             *\n *=========================================================================*/\nPRIVATE int cdecl Palette_To_Palette(void *src_palette, void *dst_palette,\n\tunsigned long current_time, unsigned long delay)\n{\n\tchar\tcolour;\n\tchar\tdiff;\n\tint\tchgval;\n\tint\tlp;\n\tint\tchange;\n\tstatic char  palette[768];\n\tchar\t*src_pal = (char*)src_palette;\n\tchar\t*dst_pal = (char*)dst_palette;\n\n\t/*======================================================================*/\n\t/* Loop through each RGB value attempting to change it to the correct\t*/\n\t/*\t\tcolor.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tfor (change = lp = 0; lp < 768; lp++) {\n\t\tif (current_time < delay ) {\n\t\t\tdiff\t\t= dst_pal[lp] & (char)63;\n\t\t\tdiff\t  -= src_pal[lp] & (char)63;\n\t\t\tif (diff)\n\t\t\t\tchange = TRUE;\n\t\t\tchgval\t= SCALE(diff, delay, current_time);\n\t\t\tcolour \t= src_pal[lp] & (char)63;\n\t\t\tcolour\t+=(char)chgval;\n\t\t}\n\t\telse {\n\t\t\tcolour = dst_pal[lp] & (char)63;\n\t\t\tchange = FALSE;\n\t\t}\n\t\tpalette[lp] = colour;\n\t}\n\t/*======================================================================*/\n\t/* Set the palette to the color that we created.\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tSet_Palette(palette);\n\treturn(change);\n\n}\t/* end of Palette_To_Palette */\n\n\n/*************************** End of morphpal.cpp ***************************/\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/MOUSE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*\t\t\t\t  (Mouse Routines)\t\t\t   *\n;*                                                                         *\n;*                    File Name : MOUSE.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : August 26, 1994                          *\n;*                                                                         *\n;*                  Last Update : November 3, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Install_Mouse -- Initializes mouse driver and verifies mouse exists   *\n;*   Remove_Mouse -- uninstalls the mouse interrupt by disabling the call  *\n;*   Get_Mouse_X -- Returns the mouses x pixel position                    *\n;*   Get_Mouse_Y -- Returns the mouse's y pixel position                   *\n;*   Get_Mouse_Button -- Gets the values of the mouse button               *\n;*   Set_Mouse_Cursor -- Sets the shape to be used as the mouse.           *\n;*   Low_Hide_Mouse -- Low-level routine which hides the mouse\t\t   *\n;*   Low_Show_Mouse -- Low level routine which shows the mouse\t\t   *\n;*   Mouse_Shadow_Buffer -- Handles storing and restoring the mouse buffer *\n;*   Draw_Mouse -- Handles drawing the mouse cursor\t\t\t   *\n;*   Hide_Mouse -- Hides mouse cursor on screen if it was show             *\n;*   Show_Mouse -- Display mouse cursor on screen if it was hidden         *\n;*   Conditional_Hide_Mouse -- Hides mouse if its with given region        *\n;*   Conditional_Show_Mouse -- shows mouse if it was conditionally hidden  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\n;WARN\t\t\t\t; generate all warnings we can\n;JUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keystruc.inc\"\nINCLUDE \"shape.inc\"\ninclude \"drawbuff.inc\"\n\nDOS_SYS_CALL\t\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nRESTORE_VISIBLE_PAGE\tEQU\t0\nSTORE_VISIBLE_PAGE\tEQU\t1\nCONDHIDE\t\tEQU\t08000H\t\t; bit for testing conditional region\nCONDHIDDEN\t\tEQU\t04000H\t\t; bit for testing conditional hidden\n;---------------------------------------------------------------------------\n; Define any data which needs to be global...\n;---------------------------------------------------------------------------\n\nGLOBAL C\tRealModePtr:DWORD\nGLOBAL C\tMInstalled:DWORD\nGLOBAL C\tMouseBuffer:DWORD\nGLOBAL C\tLCW_Uncompress:NEAR\n\nGLOBAL C\tGet_Shape_Uncomp_Size     :NEAR\nGLOBAL C\tGet_Shape_Width      \t  :NEAR\nGLOBAL C\tGet_Shape_Original_Height :NEAR\nGLOBAL C  Size_Of_Region\t\t  :NEAR\nGLOBAL C\t_ShapeBuffer\t\t  :DWORD\n\nGLOBAL C  XRes\t: dword\nGLOBAL C  YRes\t: dword\n\n\nGLOBAL C\tVesaFunc : dword\nGLOBAL C\tVesa_XRes : near\nGLOBAL C\tVesa_YRes : near\n\n\n\n\n\nDPMI_INTR\tEQU\t31h\n\n\nSTRUC DPMI_REGS\n       _edi  dd ?\n       _esi  dd ?\n       _ebp  dd ?\n       \t     dd ?\n       _ebx  dd ?\n       _edx  dd ?\n       _ecx  dd ?\n       _eax  dd ?\n       Flags dw ?\n       _es   dw ?\n       _ds   dw ?\n       _fs   dw ?\n       _gs   dw ?\n       _ip   dw ?\n       _cs   dw ?\n       _sp   dw ?\n       _ss   dw ?\n       \t     dd ?\n\t     dd ?\n  nothing    dd ?\nENDS\n\n\n\n;---------------------------------------------------------------------------\n; Now lets handle any data in the data segment\n;---------------------------------------------------------------------------\n\tDATASEG\n\nRealInt\t\tDPMI_REGS <>\t; structure to call a real mode int\nMInstalled\tDD\t0\t\t; is the mouse installed?\nMouseCursor\tDD\t0\nMouseBuffer\tDD\t0\nBufferWidth\tDD\t0\nBufferHeight\tDD\t0\nBufferSize\tDD\t0\nPrevMousePtr\tDD\t0\nMouseBufferSel\tDD\t0\n\n\nDraw_Mouse\t\tdd\tVGA_Draw_Mouse\nMouse_Shadow_Buffer\tdd\tVGA_Mouse_Shadow_Buffer\n\n;---------------------------------------------------------------------------\n; Time to write some code\n;---------------------------------------------------------------------------\n\tCODESEG\n\n;***************************************************************************\n;* INSTALL_MOUSE -- Initializes mouse driver and verifies mouse connected  *\n;*                                                                         *\n;* First check the mouse interupt to see if the vector is pointing to zero *\n;* page.  If it is not then make sure it is not pointing to an IRET.  If   *\n;* not call the mouse reset to verify that the hardware is attached.\t   *\n;*                                                                         *\n;* INPUT:\tint mouse_max_width  - the max width of the mouse cursor   *\n;*\t\tint mouse_max_height - the max height of the mouse cursor  *\n;*\t\tint screen_width     - width of the physical screen\t   *\n;*\t\tint screen_height    - height of the physical screen\t   *\n;*                                                                         *\n;* OUTPUT:      TRUE is mouse driver is initialized, FALSE if unable to    *\n;*\t\tinitialize mouse driver.\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tint Install_Mouse(\tint mouse_max_width,\t\t   *\n;*\t\t\t\t\tint mouse_max_height,\t\t   *\n;*\t\t\t\t\tint screen_width,\t\t   *\n;*\t\t\t\t\tint screen_height);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/26/1994 PWG : Created.                                             *\n;*=========================================================================*\nGLOBAL C\tInstall_Mouse:NEAR\nPROC\tInstall_Mouse C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tARG\tmouse_max_width:DWORD\n\tARG\tmouse_max_height:DWORD\n\tARG\tscreen_width:DWORD\n\tARG\tscreen_height:DWORD\n\nifdef NOT_FOR_WIN95\n\t;*=========================================================================*\n\t;* Initialize all of the general mouse variables\n\t;*=========================================================================*\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\ttest\tesi , esi\t\t\t; mouse driver should be install\n\tjz \t??exit\t\t\t\t; after keyboard interrup is install\n\tmov\teax , [ XRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseX],eax\t; set the mouses x coordinate to 160\n\tmov\teax , [ YRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseY],eax\t; set the mouses y coordinate to 100\n\tmov\t[(KeyboardType esi).MState],1\t; flag the mouse as hidden\n\tmov\t[(KeyboardType esi).MCState],0\t; turn off conditional region\n\tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi).MouseRight],eax\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi).MouseBottom],eax\n\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 0200, bl = number of interrupt to get\n\t; output cf error, cx,dx= address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,033h\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\t\t\t; no mouse driver present\n\n\t;*=========================================================================*\n\t;* If the interupt vector is pointing to 0000:0000h, there is no mouse\n\t;*=========================================================================*\n\tor\tcx,dx\n\tjz\tshort ??nomouse\n\n\tand\tedx , 0ffffh\n\tand\tecx , 0ffffh\n\tshl\tecx,4\n\tadd\tecx,edx\n\n\t;*=========================================================================*\n\t;* If the first instruction is an IRET, there is no mouse\n\t;*=========================================================================*\n\n\tcmp\t[byte ptr ecx],0CFH\t; is this an IRET\n\tjne\tshort ??mouse_buff\t; if it isnt then reset the mouse\n\n??nomouse:\n\tmov\teax,FALSE\t\t\t\t; flag no mouse driver\n\tmov\t[MInstalled],FALSE\t\t\t; flag no mouse driver\n    \tjmp\t??exit\t\t\t\t\t; exit\n\n??mouse_buff:\n\t;*=========================================================================*\n\t;* Allocate two real mode memory buffers for the mouse cursor and the\n\t;*\tmouse shadow\n\t;*=========================================================================*\n\tmov\teax,[mouse_max_width]\t       \t; get the is max width\n\tmov\t[BufferWidth],eax\t       \t; save it off for set cursor\n\tmov\tedx,[mouse_max_height]\t       \t; get the max height\n\tmov\t[BufferHeight],edx\t       \t; save it off for set cursor\n\tmul\tedx\t\t\t       \t; size = max_width * max_height\n\tadd\teax,22\t\t\t       \t; add width/height(8) + para align(15)\n\tand\tal, 0f0h\t\t       \t; now size is even paragraphs\n\tmov\t[BufferSize],eax\t       \t; store off the buffer size\n\tshl\teax,1\t\t\t       \t; make two of them\n\n \tmov\tebx,eax\t\t\t\t; get size of RM binary.\n\tmov\tecx,eax\t\t\t\t; ecx will use it later.\n\tadd\tebx,15\t\t\t\t; round up\n\tshr\tebx,4\t\t\t\t; convert to pages.\n\tmov\teax,0100h\t\t\t; alloc real buffer\n\tint\tDPMI_INTR\t \t\t; do call.\n\tjc\t??error\t\t \t\t; check for error.\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tmov\t[MouseBufferSel], edx\n\tshl\teax , 16\n\tmov\t[(KeyboardType esi).MouseCursor],eax\t; store off the real mode segment\n\tmov\tedx,eax\t\t\t\t\t; get the buffer position\n\tadd\tedx,[BufferSize]\t\t\t; add in the buffer size\n\tmov\t[(KeyboardType esi).MouseBuffer],edx\t; store off the real mode segment\n\tshr\teax,12\t\t\t\t\t; convert the seg/off to 32 bit offset\n\tmov\tedx,eax\n\tadd\tedx,[BufferSize]\n\tmov\t[MouseCursor],eax\t\t\t; store it off in the mouse buffer\n\tmov\t[MouseBuffer],edx\t\t\t; store it off in the mouse buffer\n\n\tmov\teax,0600h\t\t\t\t; function number.\n\tmov\tecx,[MouseCursor]\t\t\t; ecx must have start of memory.\n\tmov\tedi,[BufferSize]\n\tshl\tedi,1\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n       \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n\n??begin:\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\t; Reset mouse thru int 33h funtion 0\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\txor\tecx , ecx\n\tmov\t[RealInt . _eax ] , 0\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\tmov\teax ,[RealInt . _eax]\n\tcmp\tax,-1\t\t\t\t\t; was the mouse attached to system\n      \tjne\t??nomouse\t\t\t\t; if not exit out of the routine\n\n\tmov\t[(KeyboardType esi).Adjust],0\t\t; assume we do not need to adjust mouse\n\n;***************************************************************************\n; Set the Vesa Parameters\n\n\tmov\teax , [ VesaFunc ]\n\ttest\teax , eax\n\tjz\t??set_vga_mouse\n\tmov\t[(KeyboardType esi). VesaPtr ] , eax\n\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VESA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VESA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n \tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi). MouseRight ] , eax\n\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi). MouseBottom ] , eax\n\n\tlea\tedi , [(KeyboardType esi). VesaBankTable]\n\tlea\tesi , [ BankTable ]\n\tmov\tecx , 8\n\trep\tmovsd\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tjmp\t??end_vesa\n\n??set_vga_mouse:\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VGA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VGA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n??end_vesa:\n\tcall \tReset_Mouse\n\tmov\teax , TRUE\n\tret\n\n??error:\n\tmov\teax,FALSE\n??exit:\nendif ; NOT_FOR_WIN95\n\tret\n\tENDP\tInstall_Mouse\n\n;***************************************************************************\n;* ResET_MOUSE -- Reset mouse to a new graphif mode\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* reset mouse driver funtions to a a currently graphic mode\t\t   *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;* PROTO:\tReset_Mouse ( void ) \t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/26/1994 JRJ : Created.                                             *\n;*=========================================================================*\nGLOBAL C\tReset_Mouse:NEAR\nPROC\tReset_Mouse C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\nifdef NOT_FOR_WIN95\n\t;*=========================================================================*\n\t;* Initialize all of the general mouse variables\n\t;*=========================================================================*\n\tmov\tesi , [RealModePtr]\t\t; get offset of real mode data start\n\ttest\tesi , esi\n\tjz\t??exit\n\tmov\teax , [ XRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseX],eax\t; set the mouses x coordinate to 160\n\tmov\teax , [ YRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseY],eax\t; set the mouses y coordinate to 100\n\tmov\t[(KeyboardType esi).MState],1\t; flag the mouse as hidden\n\tmov\t[(KeyboardType esi).MCState],0\t; turn off conditional region\n\tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi).MouseRight],eax\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi).MouseBottom],eax\n\n\n\tmov\t[(KeyboardType esi).Adjust],0\t\t; assume we do not need to adjust mouse\n\n;***************************************************************************\n; Set the Vesa Parameters\n\n\tmov\teax , [ VesaFunc ]\n\ttest\teax , eax\n\tjz\t??set_vga_mouse\n\tmov\t[(KeyboardType esi). VesaPtr ] , eax\n\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VESA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VESA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n \tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi). MouseRight ] , eax\n\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi). MouseBottom ] , eax\n\n\tlea\tedi , [(KeyboardType esi). VesaBankTable]\n\tlea\tesi , [ BankTable ]\n\tmov\tecx , 8\n\trep\tmovsd\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tjmp\t??end_vesa\n\n??set_vga_mouse:\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VGA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VGA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n\n??end_vesa:\n       ; S Mickey/pixel Ratio cursor limits\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 8\n\tmov\tedx , 16\n\tmov\t[RealInt . _eax ] , 0fh\n\tmov\t[RealInt . _ecx] , ecx\n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\t; Set Min/Max X pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 0\n\tmov\tedx , [ XRes ]\n\tcmp\tedx , 320\n\tjne\t??set_it\n\tshl\tedx , 1\n\tmov\t[(KeyboardType esi).Adjust],1\n\n??set_it:\n;\tdec\tedx\n\tmov\t[RealInt . _eax ] , 7\n\tmov\t[RealInt . _ecx] , ecx\n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\t; Set Min/Max Y pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 0\n\tmov\tedx , [ YRes ]\n\tdec\tedx\n\tmov\t[RealInt . _eax ] , 8\n\tmov\t[RealInt . _ecx] , ecx\n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\nIF 0\n\t; Check for scale factors in X and Y pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , [ XRes ]\n\tmov\tedx , [ YRes ]\n\tsub\tecx , 8\n\tsub  \tedx , 16\n\tmov\t[RealInt . _eax ] , 4\n\tmov\t[RealInt . _ecx] , ecx\n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\t; Read mouse position thru int 33 funtion 3\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\txor\tecx , ecx\n\tmov\t[RealInt . _eax ] , 3\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\tmov\tecx ,[RealInt . _ecx]\n\tmov\tedx ,[RealInt . _edx]\n\n      ; compute Scale values X Y for different vendor mouse driver if nessesary\n\tadd \tecx , 8\n\tadd\tedx , 16\n\tcmp\tecx , [ XRes ]\n\tmov\t[(KeyboardType esi).Adjust_XPos],0\n\tjz\t??No_scaleX\n\tmov\t[(KeyboardType esi).Adjust_XPos],ecx\n??No_scaleX:\n\tcmp\tedx , [ YRes ]\n\tmov\t[(KeyboardType esi).Adjust_YPos],0\n\tjz\t??No_scaleY\n\tmov\t[(KeyboardType esi).Adjust_YPos],edx\n??No_scaleY:\nENDIF\n\n\tmov\tecx, [ XRes ]\t\t\t\t; set the mouses x coordinate to 160\n\tmov\tedx, [ YRes ]\t\t\t\t; set the mouses x coordinate to 160\n\tcmp\t[(KeyboardType esi).Adjust],1\n\tje\t??no_ecx_shift\n\tshr\tecx , 1\n??no_ecx_shift:\n\tshr\tedx , 1\n\tmov\t[MInstalled],TRUE\t\t\t; set the fact that mouse is installed\n\tmov\t[(KeyboardType esi).MDisabled],TRUE\t; disable mouse until the overlay is loaded\n\n\t; Set new Mouse position any way\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\t[RealInt . _eax ] , 4\n\tmov\t[RealInt . _ecx] , ecx\n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\tcall\tClear_RM_regs\n\tmov\teax, 0300h\n\tmov\tebx ,33h\t\t\t\t; mouse is in 33h\n\tmov\tecx,0\t\t\t\t\t; any mouse condition generates int\n\tmov\tedx,[RealModePtr]\t\t\t; get real mode memory address\n\tshr\tedx,4\t\t\t\t\t; convert it to a segment\n\tmov\t[RealInt. _es],dx\t\t\t; store it in the real mode es\n\tmovzx\tedx,[(KeyboardType PTR esi).MouseCodeOffset] ; Get address of code\n\tmov\t[RealInt._edx],edx\t\t\t; set edx to offset of code\n\tmov\t[RealInt._eax],12\t\t\t; set eax to set interrupt routine\n\tmov\t[RealInt._ecx],31\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n??installed:\n\tmov\teax,TRUE  \t\t\t\t; return TRUE if all is well\n\tmov\t[(KeyboardType esi).MDisabled],FALSE\t; no 32 bit overlays installed\n\tje\t??exit\n\n??error:\n\tmov\teax,FALSE\n\n??exit:\nendif ;NOT_FOR_WIN95\n\n\tret\n\tENDP\tReset_Mouse\n\n\n\n;***************************************************************************\n;* REMOVE_MOUSE -- uninstalls the mouse interrupt by disabling the call\t   *\n;*                                                                         *\n;* This routine will uninstall the mouse interrupt.  It does this by\t   *\n;* simply disabling the call condition.  The interrupt itself is still\t   *\n;* present, just uncalled until dos removes it at program termination.\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Remove_Mouse(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL C\tRemove_Mouse:NEAR\n\tPROC\tRemove_Mouse C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\nifdef NOT_FOR_WIN95\n\tcall\tClear_RM_regs\n\tcmp \t[MInstalled],FALSE\t; check to see if mouse installed\n\tje\t??exit\t\t\t; if not then no need to remove it\n\n\tmov\t[MInstalled],FALSE\t; Force to NOT-Installed.\n\n;;PWG\tcmp \t[_MSWIFTDevice],1\t; check to see if SWIFT device installed\n;;PWG\tje\tshort ??prevSWIFT\t\t; if so use previous SWIFT event handler\n\n\tmov\tebx , 033h\n\tmov\tedx,[RealModePtr]\t\t\t; get real mode memory address\n\ttest\tedx,edx\t\t\t\t\t; check that the memory block is valid\n\tjz\t??exit\n\n\tshr\tedx,4\t\t\t\t\t; convert it to a segment\n\tmov\t[RealInt._es],dx\t\t\t; store it in the real mode es\n\txor\tedx,edx\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\tmov\tdx,[(KeyboardType PTR esi).MouseCodeOffset] ; Get address of code\n\tmov\t[RealInt._edx],edx\t\t\t; set edx to offset of code\n\tmov\t[RealInt._eax],12\t\t\t; set eax to set interrupt routine\n\tmov\t[RealInt._ecx],0\n\tmov\tecx,0\t\t\t\t\t; no mouse condition generates an int\n\tmov\teax,0300h\n\tlea\tedi,[RealInt]\n\tint\tDPMI_INTR\n\n\tmov\teax,0601h\t\t\t\t; function number.\n\tmov\tecx,[MouseCursor]\t\t\t; ecx must have start of memory.\n\tmov\tedi,[BufferSize]\n\tshl\tedi,1\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n       \tint\tDPMI_INTR\t\t\t; do call.\n\n\n\t; Deallocate real memory buffer\n\tmov\tedx ,[MouseBufferSel]\n\ttest\tdx ,dx\n\tjz\t??exit\n\tmov\teax ,0101h\n\tint\tDPMI_INTR\n\n??exit:\nendif ;NOT_FOR_WIN95\n\tret\n\tENDP\tRemove_Mouse\n\n\n;***************************************************************************\n\nGLOBAL C\tClear_RM_regs :NEAR\nPROC\tClear_RM_regs  NEAR\nifdef NOT_FOR_WIN95\n\tpush\teax\n\tpush\tecx\n\tpush\tedi\n\tlea\tedi , [ RealInt ]\n\tlea\tecx , [ RealInt . nothing ]\n\tsub\tecx , edi\n\txor\teax , eax\n\tshr\tecx , 2\n\trep\tstosd\n\tpop\tedi\n\tpop\tecx\n\tpop\teax\nendif; NOT_FOR_WIN95\n\tret\nENDP\tClear_RM_regs\n\n\n;***************************************************************************\n;* GET_MOUSE_X -- Returns the mouses x pixel position                      *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse x position in pixels\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_X(void);                                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL C\tGet_Mouse_X:NEAR\n\tPROC\tGet_Mouse_X C NEAR\n\tUSES\tesi\nifdef NOT_FOR_WIN95\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MouseX]\nendif;NOT_FOR_WIN95\n\tret\n\n\tENDP\tGet_Mouse_X\n\n;***************************************************************************\n;* GET_MOUSE_STATE -- Returns the current mouse state\t\t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse's current state\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_State(void);                                 *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL C\tGet_Mouse_State:NEAR\n\tPROC\tGet_Mouse_State C NEAR\n\tUSES\tesi\nifdef NOT_FOR_WIN95\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MState]\nendif;ifdef NOT_FOR_WIN95\n\tret\n\n\tENDP\tGet_Mouse_State\n\n;***************************************************************************\n;* GET_MOUSE_X -- Returns the mouses x pixel position                      *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse x position in pixels\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_X(void);                                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL C\tGet_Mouse_Disabled:NEAR\n\tPROC\tGet_Mouse_Disabled C NEAR\n\tUSES\tesi\nifdef NOT_FOR_WIN95\n\tmov\tesi,[RealModePtr]\n\tmovzx\teax,[(KeyboardType esi).MDisabled]\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tGet_Mouse_Disabled\n\n;***************************************************************************\n;* GET_MOUSE_Y -- Returns the mouse's y pixel position                     *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:       none\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      int - the mouses y position in pixels                      *\n;*                                                                         *\n;* PROTO:\tint Get_Mouse_Y(void);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL C\tGet_Mouse_Y:NEAR\n\tPROC\tGet_Mouse_Y C NEAR\n\tUSES\tesi\nifdef NOT_FOR_WIN95\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MouseY]\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tGet_Mouse_Y\n\n;***************************************************************************\n;* GET_MOUSE_BUTTON -- Gets the values of the mouse button                 *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL C\tGet_Mouse_Button:NEAR\n\tPROC\tGet_Mouse_Button C NEAR\n\tUSES\teax,esi\nifdef NOT_FOR_WIN95\n\tmov\tesi,[RealModePtr]\n\txor\teax,eax\n\tmov\tal,[(KeyboardType esi).Button]\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tGet_Mouse_Button\n\n;***************************************************************************\n;* SET_MOUSE_CURSOR -- Sets the shape to be used as the mouse.             *\n;*                                                                         *\n;*    This will inform the system of the shape desired as the mouse        *\n;*    cursor.                                                              *\n;*                                                                         *\n;* INPUT:    xhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           yhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           cursor      -- Shape to use as the new mouse shape.           *\n;*                                                                         *\n;* OUTPUT:   Returns with a pointer to the original mouse shape.           *\n;*                                                                         *\n;* PROTO:\tVOID  *Set_Mouse_Cursor(\tint  xhotspot, \t\t   *\n;*\t\t\t\t\t\tint  yhotspot, \t\t   *\n;*\t\t\t\t\t\tvoid *cursor);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   02/13/1992 JLB : Created.                                             *\n;*=========================================================================*\n\tGLOBAL C\tSet_Mouse_Cursor:NEAR\n\tPROC\tSet_Mouse_Cursor C NEAR\n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\txhotspot:DWORD\t\t\t\t; the x hot spot of the mouse\n\tARG\tyhotspot:DWORD\t\t\t\t; the y hot spot of the mouse\n\tARG\tcursor:DWORD\t\t\t\t; ptr to the new mouse cursor\n\n\tLOCAL\tdatasize:DWORD\n\tLOCAL\tstype:WORD\n\tLOCAL\tswidth:DWORD\t\t; Shape width.\n\tLOCAL\tsheight:DWORD\t\t; Shape height.\n\tLOCAL\tssize:DWORD\t\t; Size of raw shape.\nifdef NOT_FOR_WIN95\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\n\t;-------------------------------------------------------------------\n\t; Make sure the mouse is Enabled and Installed before continuing\n\t;-------------------------------------------------------------------\n\tmov\teax,[cursor]\n\tcmp\teax,0\t\t\t; if the mouse cursor is in zero page\n\tje\t??exit\t\t\t; it is completely invalid\n\n\tcmp\teax,[PrevMousePtr]\n\tje \t??exit\n\n\tcmp\t[(KeyboardType esi).MDisabled],FALSE\t; make sure the mouse is not disabled\n\tjne\t??exit\t\t\t; if it is not then give it a try\n\n\t;-------------------------------------------------------------------\n\t; We need to wait if a mouse interrupt is in progress.  Once the\n\t; interrupt is finished flag that it is occuring so that it will\n\t; not attempt to draw the mouse while we are changing the cursor.\n\t;-------------------------------------------------------------------\n??try:\n\tinc\t[(KeyboardType esi).MouseUpdate] ; flag that mouse can not be drawn\n\n\t;-------------------------------------------------------------------\n\t; If the mouse is currently on the screen hide it.\n\t;-------------------------------------------------------------------\n\tcall\tLow_Hide_Mouse\n\n\t;-------------------------------------------------------------------\n\t; Calculate the size of the buffer needed.\n\t;-------------------------------------------------------------------\n\tpush\t[cursor]\n\tcall\tGet_Shape_Uncomp_Size\n\tpop\tedx\n\tmov\t[datasize],eax\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Width\n\tpop\tedx\n\tmov\t[swidth],eax\n\tcmp\teax,[BufferWidth]\n\tjg\t??end\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Original_Height\n\tpop\tedx\n\tmov\t[sheight],eax\n\tcmp\teax,[BufferHeight]\n\tjg\t??end\n\n\n\tmov\tebx,[sheight]\n\tmov\teax,[swidth]\n\timul\tebx,eax\n\n??copy_mouse:\n\tmov\tesi,[cursor]\t\t\t; set esi to point to mouse shape\n\tmov\tax,[esi]\t\t\t; get the shape type byte\n\tmov\t[stype],ax\t\t\t; save off the shape type\n\ttest\tax,MAKESHAPE_NOCOMP\t\t; is it marked as no compression?\n\tje\t??comp_shape\t\t\t; if not go to the comped shape code\n\tmov\tedi,[MouseCursor]\t\t; set edi to point to mouse buffer\n??copy_type:\n\n\ttest\t[stype],MAKESHAPE_COMPACT\t; if the shape a 16 color shape?\n\tjne\t??16_color_copy\t\t\t; if it is then go handle it\n\n??normal_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed NORMAL shapes just get run-length uncompressed\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t\t; find size of shape in pixels\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes\n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??norm_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??norm_trans\t\t\t; if its a zero its transparent\n\tmov\t[edi],al\t\t\t; write out the pixel to dest\n\tinc\tedi\t\t\t\t; move to next dest position\n\tdec\tedx\t\t\t\t; we have now written another pix\n\tjnz\t??norm_unrle\t\t\t; if more to write then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are all done\n\n??norm_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\n\tjnz\t??norm_unrle\t\t\t; if more to do then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are done\n\n??16_color_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed 16 color shapes just get remaped and UN-RLE'd\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\tebx,esi\t\t\t\t; save of position of remap\n\tadd\tesi,16\t\t\t\t; move past remap table\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t; load up the height\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes\n\txor\teax,eax\t\t\t\t; clear high of lookup variable\n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??16_color_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??16_color_trans\t\t; if its a zero its transparent\n\tmov\tal,[ebx+eax]\t\t\t; remap the pixel from 16 color table\n\tmov\t[edi],al\t\t\t; store it out to the dest address\n\tinc\tedi\t\t\t\t; move to next dest address\n\tdec\tedx\t\t\t\t; we have now written a pixel\n\tjnz\t??16_color_unrle\n\tjmp\t??done_copy\n??16_color_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\t\t\t\t; subtract off count ahead of time\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\t\t\t\t; or edx to test for zero\n\tjnz\t??16_color_unrle\n\tjmp\t??done_copy\n\n\t;-------------------------------------------------------------------\n\t; Deal with the compressed shape by copying it into the shape\n\t;   staging buffer.\n\t;-------------------------------------------------------------------\n??comp_shape:\n\tmov\tedi,[_ShapeBuffer]\t; get a pointer to ShapeBuffer\n\tmov\tax,[esi]\t\t; load in the shape type\n\tadd\tesi,2\t\t\t; increment the shape pointer\n\tor\tax,MAKESHAPE_NOCOMP\t; make the shape as uncompressed\n\tmov\t[stype],ax\t\t; save off the shape type\n\tmov\t[edi],ax\t\t; write out uncompressed shape\n\tadd\tedi,2\n\n\t;-------------------------------------------------------------------\n\t; Process the shape header information and copy it over to the new\n\t;   location.\n\t;-------------------------------------------------------------------\n\tmov\tecx,4 \t\t\t; transfer height, width, org and\n\ttest\teax,MAKESHAPE_COMPACT\t; is it a 16 color shape?\n\tje\t??copy_head\t\t; no - don't worry about it\n\tadd\tecx,8\t\t\t; otherwise adjust ecx for header\n??copy_head:\n\trep\tmovsw\t\t\t; copy the necessary bytes\n\n\tmov \teax,[datasize]\t\t; get uncompressed length\n\tpush\teax\t\t\t; push as third param\n\tpush\tedi\t\t\t; push the destination offset\n\tpush\tesi\t\t\t; push the source offset\n\tcall\tLCW_Uncompress\t\t; do the uncompress\n\tpop\teax\n\tpop\teax\n\tpop\teax\n\tmov\tesi,[_ShapeBuffer]\n\tmov\tedi,[MouseCursor]\t\t; set edi to point to mouse buffer\n\tjmp\t??copy_type\n\n??done_copy:\n\tmov\tesi,[RealModePtr]\t; get offset of real mode data start\n\n\tmov\teax,[xhotspot]\t\t; get the mouse cursors x hotspot\n\tmov\t[(KeyboardType esi).MouseXHot],eax\n\tmov\teax,[yhotspot]\t\t; get the mouse cursors y hotspot\n\tmov\t[(KeyboardType esi).MouseYHot],eax\n\n\tmov\tebx,[sheight]\t\t; get shape height\n\tmov\t[(KeyboardType esi).MouseHeight],ebx\n\tmov\tebx,[swidth]\n\tmov\t[(KeyboardType esi).MouseWidth],ebx\n\n??error:\n\tcall\tLow_Show_Mouse\n\n\t;-------------------------------------------------------------------\n\t; Final cleanup and exit.\n\t;-------------------------------------------------------------------\n??end:\n\tdec\t[(KeyboardType esi).MouseUpdate]\t\t; we are done modifying the cursor\n??exit:\n\tpush\t[cursor]\n\tpush\t[PrevMousePtr]\n\tpop\teax\n\tpop\t[PrevMousePtr]\nendif; NOT_FOR_WIN95\n\tret\t\t\t\t; and return back to the world\n\n\tENDP\tSet_Mouse_Cursor\n\n\n;***************************************************************************\n;* LOW_HIDE_MOUSE -- Low-level routine which hides the mouse\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Low_Hide_Mouse:NEAR\n\tPROC\tLow_Hide_Mouse C NEAR\n\tUSES\teax,ebx,esi\nifdef NOT_FOR_WIN95\n\tmov\tebx,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\n\t;*=========================================================================*\n\t;* Is the mouse disabled or hidden?\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType ebx).MDisabled],0 \t; is the mouse disabled?\n\tjne\tshort ??end\n\n   \tcmp\t[(KeyboardType ebx).MState],0 \t; is the mouse hidden?\n\tjne\tshort ??endnodraw\t\t\t; no need to hide again\n\n\t;*=========================================================================*\n\t;* Take care of restoring the mouse cursor\n\t;*=========================================================================*\n\tmov\teax,RESTORE_VISIBLE_PAGE\n\tpush\teax\n\tcall\t[ Mouse_Shadow_Buffer]\n\tpop\teax\n\t;*=========================================================================*\n\t;* The mouse is now hidden -- again.\n\t;*=========================================================================*\n??endnodraw:\n\tadd\t[(KeyboardType ebx).MState],1\n\tadc\t[(KeyboardType ebx).MState],0\n\n??end:\nendif; NOT_FOR_WIN95\n\tret\n\tENDP\tLow_Hide_Mouse\n\n;***************************************************************************\n;* LOW_SHOW_MOUSE -- Low level routine which shows the mouse\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Low_Show_Mouse:NEAR\n\tPROC\tLow_Show_Mouse C NEAR\n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tLOCAL\tmousex:DWORD\n\tLOCAL\tmousey:DWORD\nifdef NOT_FOR_WIN95\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\n\t;*=========================================================================*\n\t;* Don't show the mouse if it is not hidden or it is disabled\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType esi).MDisabled],0\t; is the mouse disabled\n\tjne\t??exit\t\t\t\t\t; if so then exit\n\n\tcmp\t[(KeyboardType esi).MState],0\t; is the mouse already visible\n       \tje\t??exit\t\t\t\t\t; if so then exit\n\n\t;*=========================================================================*\n\t;* Don't show the mouse if it was hidden multiple times\n\t;*=========================================================================*\n\tdec\t[(KeyboardType esi).MState]\t\t; show the mouse one level\n\tcmp\t[(KeyboardType esi).MState],0\t; can the mouse be shown\n       \tjne\tshort ??exit\n\n\t;*=========================================================================*\n\t;* Determine the theoretcial drawing position of the mouse\n\t;*=========================================================================*\n\tmov\tecx,[(KeyboardType esi).MouseWidth]\t\t; Theoretical buffer width (pixel).\n\tmov\tedx,[(KeyboardType esi).MouseHeight]\t; Theoretical buffer height (pixel).\n\tmov\teax,[(KeyboardType esi).MouseX]\n\tmov\t[mousex],eax\t\t; Draw X pixel.\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\tmov\tebx,[(KeyboardType esi).MouseY]\n\tmov\t[mousey],ebx\t\t; Draw Y pixel.\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\t;*=========================================================================*\n\t;* Determine the theoretical coordinates and dimensions of the\n\t;*\tarea the mouse shape will be rendered upon.\n\t;*=========================================================================*\n\tmov\t[(KeyboardType esi).MouseBuffX],eax\n\tmov\t[(KeyboardType esi).MouseBuffY],ebx\n\tmov\t[(KeyboardType esi).MouseBuffW],ecx\n\tmov\t[(KeyboardType esi).MouseBuffH],edx\n\n;------\tMove the area that will be drawn upon, to the graphic buffer.\n\tmov\teax,STORE_VISIBLE_PAGE\n\tpush\teax\n\tcall\t[ Mouse_Shadow_Buffer ]\n\tpop\teax\n\n;------\tDraw the mouse shape to the seenpage.\n\tpush\t[mousey]\n\tpush\t[mousex]\n\tcall\t[ Draw_Mouse ]\n\tpop\teax\n\tpop\teax\n??exit:\nendif; NOT_FOR_WIN95\n\tret\n\tENDP\tLow_Show_Mouse\n\n;***************************************************************************\n;* HIDE_MOUSE -- Hides mouse cursor on screen if it was show               *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Hide_Mouse(void);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL C\tHide_Mouse:NEAR\n\tPROC\tHide_Mouse C NEAR\n\tUSES\teax,esi\nifdef NOT_FOR_WIN95\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Mark us as updating the mouse and then run and do the update\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\t; were drawing the mouse\n\tcall\tLow_Hide_Mouse\t\t\t\t; make the function call\n\tdec\t[(KeyboardType esi).MouseUpdate]\t; were done drawing mouse\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tHide_Mouse\n\n;----------------------------------------------------------------------------\n\n\n;***************************************************************************\n;* SHOW_MOUSE -- Display mouse cursor on screen if it was hidden           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Show_Mouse(void)                                      *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL C\tShow_Mouse:NEAR\n\tPROC\tShow_Mouse C NEAR\n\tUSES\teax,esi\nifdef NOT_FOR_WIN95\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Mark us as updating the mouse and then run and do the update\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\t; were drawing the mouse\n\tcall\tLow_Show_Mouse\t\t\t\t; make the function call\n\tdec\t[(KeyboardType esi).MouseUpdate]\t; were done drawing mouse\nendif;ifdef NOT_FOR_WIN95\n\tret\n\tENDP\tShow_Mouse\n\n;***************************************************************************\n;* CONDITIONAL_HIDE_MOUSE -- Hides mouse if its with given region          *\n;*                                                                         *\n;* INPUT:\tint sx_pixel - the left-most pixel position of the region  *\n;*\t\tint sy_pixel - the upper-most pixel position of the region *\n;*\t\tint dx_pixel - the right most pixel position of the region *\n;*\t\tint dy_pixel - the lower most pixel position of the region *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Conditional_Hide_Mouse(\tint sx_pixel, \t\t   *\n;*\t\t\t\t\t\tint sy_pixel,\t\t   *\n;*\t\t\t\t\t\tint dx_pixel,\t\t   *\n;*\t\t\t\t\t\tint dy_pixel);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL C\tConditional_Hide_Mouse:NEAR\n\tPROC\tConditional_Hide_Mouse C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tARG\tsx_pixel:DWORD\t\t\t\t; left x pixel pos\n\tARG     sy_pixel:DWORD\t\t\t\t; upper y pixel pos\n\tARG\tdx_pixel:DWORD\t\t\t\t; right x pixel pos\n\tARG\tdy_pixel:DWORD\t\t\t\t; lower y pixel pos\nifdef NOT_FOR_WIN95\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Widen region leftward by amount mouse shape spills to the right of\n\t;* its hot point.  Limited to the left edge of the screen.\n\t;*=========================================================================*\n\tmov\teax,[(KeyboardType esi).MouseWidth]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tneg\teax\n\tadd\teax,[sx_pixel]\n\tjns\tshort ??noleftlimit\n\txor\teax,eax\n??noleftlimit:\n\t;*=========================================================================*\n\t;* Widen region upward by amount mouse shape spills below the\n\t;* mouse's hot point.  Limited by the top edge of the screen.\n\t;*=========================================================================*\n\tmov\tebx,[(KeyboardType esi).MouseHeight]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\tneg\tebx\n\tadd\tebx,[sy_pixel]\n\tjns\tshort ??notoplimit\n\txor\tebx,ebx\n??notoplimit:\n\t;*=========================================================================*\n\t;* Widen region rightward by amount mouse shape spills to the\n\t;* left of its hot point.  Limited by the right edge of the\n\t;* screen.\n\t;*=========================================================================*\n\tmov\tecx,[dx_pixel]\n\tadd\tecx,[(KeyboardType esi).MouseXHot]\n\tcmp\tecx,[(KeyboardType esi).MouseRight]\n\tjb\tshort ??norightlimit\n\tmov\tecx,[(KeyboardType esi).MouseRight]\n\tdec\tecx\n??norightlimit:\n\t;*=========================================================================*\n\t;* Widen region downward by amout the mouse shape extends above\n\t;* its hot point.  Limited to the bottom of the screen.\n\t;*=========================================================================*\n\tmov\tedx,[dy_pixel]\n\tadd\tedx,[(KeyboardType esi).MouseYHot]\n\tcmp\tedx,[(KeyboardType esi).MouseBottom]\n\tjb\tshort ??nobottomlimit\n\tmov\tedx,[(KeyboardType esi).MouseBottom]\n\tdec\tedx\n\n??nobottomlimit:\n\tinc\t[(KeyboardType esi).MouseUpdate]\t\t; don't let interrupt scrag variables\n\n\t;*=========================================================================*\n\t;* The mouse could be in one of four conditions.\n\t;* 1) The mouse is visible and no conditional hide has been specified.\n\t;* \t(perform normal region checking with possible hide)\n\t;* 2) The mouse is hidden and no conditional hide as been specified.\n\t;* \t(record region and do nothing)\n\t;* 3) The mouse is visible and a conditional region has been specified\n\t;* \t(expand region and perform check with possible hide).\n\t;* 4) The mouse is already hidden by a previous conditional.\n\t;* \t(expand region and do nothing)\n\t;*\n\t;* First: Set or expand the region according to the specified parameters\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType esi).MCState],0\n\tjne\tshort ??expand\n\tmov\t[(KeyboardType esi).MouseCXLeft],eax\n\tmov\t[(KeyboardType esi).MouseCYUpper],ebx\n\tmov\t[(KeyboardType esi).MouseCXRight],ecx\n\tmov\t[(KeyboardType esi).MouseCYLower],edx\n\tjmp\t??noylower\n??expand:\n\n\t;*=========================================================================*\n\t;* Expand the clipping rectangle.\n\t;*=========================================================================*\n\tcmp\teax,[(KeyboardType esi).MouseCXLeft]\n\tjb\tshort ??noxleft\n\tmov\t[(KeyboardType esi).MouseCXLeft],eax\n??noxleft:\n\tcmp\tebx,[(KeyboardType esi).MouseCYUpper]\n\tjb\tshort ??noyupper\n\tmov\t[(KeyboardType esi).MouseCYUpper],ebx\n??noyupper:\n\tcmp\tecx,[(KeyboardType esi).MouseCXRight]\n\tja\tshort ??noxright\n\tmov\t[(KeyboardType esi).MouseCXRight],ecx\n??noxright:\n\tcmp\tedx,[(KeyboardType esi).MouseCYLower]\n\tja\tshort ??noylower\n\tmov\t[(KeyboardType esi).MouseCYLower],edx\n??noylower:\n\t;*=========================================================================*\n\t;* If the mouse isn't already hidden, then check its location against\n\t;* the hiding region and hide if necessary.\n\t;*=========================================================================*\n\ttest\t[(KeyboardType esi).MCState],CONDHIDDEN\n\tjne\tshort ??nohide\n\n\tmov\teax,[(KeyboardType esi).MouseX]\n\tmov\tebx,[(KeyboardType esi).MouseY]\n\tcmp\teax,[(KeyboardType esi).MouseCXLeft]\n\tjb\tshort ??nohide\n\tcmp\teax,[(KeyboardType esi).MouseCXRight]\n\tja\tshort ??nohide\n\tcmp\tebx,[(KeyboardType esi).MouseCYUpper]\n\tjb\tshort ??nohide\n\tcmp\tebx,[(KeyboardType esi).MouseCYLower]\n\tja\tshort ??nohide\n\n\t;*=========================================================================*\n\t;* The mouse falls within the region for hiding, so hide it.\n\t;*=========================================================================*\n\n\tcall\tLow_Hide_Mouse\t\t\t\t; make the function call\n\tor\t[(KeyboardType esi).MCState],CONDHIDDEN\n??nohide:\n\n\t;*=========================================================================*\n\t;* Record the fact that a Conditional_Hide_Mouse was\n\t;* called and then exit.\n\t;*=========================================================================*\n\tor\t[(KeyboardType esi).MCState],CONDHIDE\n\tadd\t[BYTE PTR (KeyboardType esi).MCState],1\n\tadc\t[BYTE PTR (KeyboardType esi).MCState],0\n\tdec\t[(KeyboardType esi).MouseUpdate]\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tConditional_Hide_Mouse\n\n;***************************************************************************\n;* CONDITIONAL_SHOW_MOUSE -- shows mouse if it was conditionally hidden    *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Conditional_Show_Mouse(void);                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL C\tConditional_Show_Mouse:NEAR\n\tPROC\tConditional_Show_Mouse C NEAR\n\tUSES\teax,esi\nifdef NOT_FOR_WIN95\n\tmov\tesi,[RealModePtr]    ; get the real mode offset\n\n\t;*=========================================================================*\n\t; Notify the interrupt that we are updating the mouse\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\n\n\tmov\tax,[(KeyboardType esi).MCState]\n\tcmp\tal,0\n\tje\tshort ??exit\t\t\t; if no more nesting clear cond\n\n\t;*=========================================================================*\n\t;* Decrement the conditional hide counter.\n\t;*=========================================================================*\n\tdec\tal\n\n\t;*=========================================================================*\n\t;* If there are more conditional levels to undo, then just abort the show.\n\t;*=========================================================================*\n\tjne\tshort ??exit\n\n\t;*=========================================================================*\n\t;* Yup, the mouse should be show, but only if it was previously hidden.\n\t;*=========================================================================*\n\ttest\tax,CONDHIDDEN\t\t\t; was it hidden by interrupt??\n\tje\tshort ??exit1\t\t\t; or initial check for level 0\n\n\tcall\tLow_Show_Mouse\n\n??exit1:\n\tmov\tax,0\n\n??exit:\n\tmov\t[(KeyboardType esi).MCState],ax\n\tdec\t[(KeyboardType esi).MouseUpdate]\nendif;ifdef NOT_FOR_WIN95\n\tret\n\tENDP\tConditional_Show_Mouse\n\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VGA_Mouse_Shadow_Buffer:NEAR\n\tPROC\tVGA_Mouse_Shadow_Buffer C NEAR\n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tstore:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\nifdef NOT_FOR_WIN95\n\tmov\tesi,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[(KeyboardType esi).MouseBuffX]\n\tmov\tebx,[(KeyboardType esi).MouseBuffY]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax\n\tmov\t[ y0 ] , ebx\n\tadd\teax,[(KeyboardType esi).MouseBuffW]\n\tadd\tebx,[(KeyboardType esi).MouseBuffH]\n\tmov\t[ x1 ] , eax\n\tmov\t[ y1 ] , ebx\n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseBuffer ]\n\tmov\t[ buffy0 ] , eax\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]\n\tmov\tebx , [ x1 ]\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]\n\tmov\tebx , [ x1 ]\n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]\n\tmov\tebx , [ y1 ]\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]\n\tmov\tebx , [ y1 ]\n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseBuffW]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseBuffW]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\n\tpush\tebp\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tebp , ecx\n??restore_loop:\n\tmov\tecx,eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi,ebx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tesi,edi\t\t\t\t\t; xchg the source and the dest\n\tmov\tebp , ecx\n??store_loop:\n\tmov\tecx,eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi,edx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,ebx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n??out:\nendif;ifdef NOT_FOR_WIN95\n\tret\n\tENDP\tVGA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n;* DRAW_MOUSE -- Handles drawing the mouse cursor\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL C\tVGA_Draw_Mouse:NEAR\n\tPROC\tVGA_Draw_Mouse C NEAR\n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tmousex:DWORD\n\tARG\tmousey:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\nifdef NOT_FOR_WIN95\n\tmov\tesi,[RealModePtr]    \t; get 32 bit offset of dos data\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[mousex]\n\tmov\tebx,[mousey]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax\n\tmov\t[ y0 ] , ebx\n\tadd\teax,[(KeyboardType esi).MouseWidth]\n\tadd\tebx,[(KeyboardType esi).MouseHeight]\n\tmov\t[ x1 ] , eax\n\tmov\t[ y1 ] , ebx\n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , eax\n\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]\n\tmov\tebx , [ x1 ]\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]\n\tmov\tebx , [ x1 ]\n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]\n\tmov\tebx , [ y1 ]\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]\n\tmov\tebx , [ y1 ]\n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseWidth]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseWidth]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch ,[esi]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[edi],ch\n??inc_edi:\n\tinc\tedi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tesi,ebx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t\t\t\t; adjust dest to next line\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tVGA_Draw_Mouse\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VESA_Mouse_Shadow_Buffer:NEAR\n\tPROC\tVESA_Mouse_Shadow_Buffer C NEAR\n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tstore:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\tlocal\tvesa_linear : dword\nifdef NOT_FOR_WIN95\n\tmov\teax , [ cpu_video_page ]\n\tmov\t[ vesa_linear ] ,  eax\n\n\tmov\tesi,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[(KeyboardType esi).MouseBuffX]\n\tmov\tebx,[(KeyboardType esi).MouseBuffY]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\n\tmov\t[ x0 ] , eax\n\tmov\t[ y0 ] , ebx\n\tadd\teax,[(KeyboardType esi).MouseBuffW]\n\tadd\tebx,[(KeyboardType esi).MouseBuffH]\n\tmov\t[ x1 ] , eax\n\tmov\t[ y1 ] , ebx\n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseBuffer ]\n\tmov\t[ buffy0 ] , eax\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]\n\tmov\tebx , [ x1 ]\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]\n\tmov\tebx , [ x1 ]\n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]\n\tmov\tebx , [ y1 ]\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]\n\tmov\tebx , [ y1 ]\n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseBuffW]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\tcall\tVesa_Asm_Set_Win\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseBuffW]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\n\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\n\tmov\t[ tempreg ] , ebx\n??restore__top_loop:\n\tmov\tah,al\n??restore__inner_loop:\n\tmov\tch ,[esi]\n\tmov\t[edi],ch\n\tinc\tesi\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ]\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??restore__in_range\n\tadd\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??restore__in_range:\n\tdec\tah\n\tjnz\t??restore__inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ]\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??restore__in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??restore__in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore__top_loop\t\t\t\t; if more to do, do it\n\tjmp\t??out\t\t\t\t\t; get the heck outta the routine\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\tmov\t[ tempreg ] , ebx\n??store_top_loop:\n\tmov\tah,al\n??store_inner_loop:\n\tmov\tch ,[edi]\n\tmov\t[esi],ch\n\tinc\tesi\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ]\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??store_in_range\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??store_in_range:\n\tdec\tah\n\tjnz\t??store_inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ]\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??store_in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??store_in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_top_loop\t\t\t\t; if more to do, do it\n\n??out:\n\tmov\tedi , [ vesa_linear ]\n\tadd\tedi , 0a0000h\n\tcall\tVesa_Asm_Set_Win\n\nendif; NOT_FOR_WIN95\n\tret\n\tENDP\tVESA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n;* DRAW_MOUSE -- Handles drawing the mouse cursor\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL C\tVESA_Draw_Mouse:NEAR\n\tPROC\tVESA_Draw_Mouse C NEAR\n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tmousex:DWORD\n\tARG\tmousey:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\tlocal\ttempreg : dword\n\tlocal\tvesa_linear : dword\nifdef NOT_FOR_WIN95\n\tmov\teax , [ cpu_video_page ]\n\tmov\t[ vesa_linear ] ,  eax\n\n\tmov\tesi,[RealModePtr]    \t; get 32 bit offset of dos data\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[mousex]\n\tmov\tebx,[mousey]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax\n\tmov\t[ y0 ] , ebx\n\tadd\teax,[(KeyboardType esi).MouseWidth]\n\tadd\tebx,[(KeyboardType esi).MouseHeight]\n\tmov\t[ x1 ] , eax\n\tmov\t[ y1 ] , ebx\n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , eax\n\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]\n\tmov\tebx , [ x1 ]\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]\n\tmov\tebx , [ x1 ]\n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]\n\tmov\tebx , [ y1 ]\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]\n\tmov\tebx , [ y1 ]\n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseWidth]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\tcall\tVesa_Asm_Set_Win\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseWidth]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\t[ tempreg ] , ebx\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch ,[esi]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[edi],ch\n??inc_edi:\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ]\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??in_range\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??in_range:\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ]\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n\n??out:\n\tmov\tedi , [ vesa_linear ]\n\tadd\tedi , 0a0000h\n\tcall\tVesa_Asm_Set_Win\n\nendif; NOT_FOR_WIN95\n\tret\n\n\tENDP\tVESA_Draw_Mouse\n\n\n;----------------------------------------------------------------------------\nEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/MOUSE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood 32 bit Library                                      *\n *                                                                                             *\n *                    File Name : MOUSE.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 12/12/95                                                     *\n *                                                                                             *\n *                  Last Update : December 12, 1995 [PWG]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   WWMouseClass::WWMouseClass -- Constructor for the Mouse Class                                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"mouse.h\"\n#include <mmsystem.h>\n\nstatic WWMouseClass *_Mouse=NULL;\nvoid CALLBACK Process_Mouse( UINT event_id, UINT res1 , DWORD user, DWORD  res2, DWORD  res3 );\nextern BOOL GameInFocus;\n\n\n/***********************************************************************************************\n * MOUSECLASS::MOUSECLASS -- Constructor for the Mouse Class                                   *\n *                                                                                             *\n * INPUT:\t\tGraphicViewPortClass * screen - pointer to screen mouse is created for\t\t\t\t *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/12/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nWWMouseClass::WWMouseClass(GraphicViewPortClass *scr, int mouse_max_width, int mouse_max_height)\n{\n\tMouseCursor \t= new char[mouse_max_width * mouse_max_height];\n\tMouseXHot\t\t= 0;\n\tMouseYHot\t\t= 0;\n\tCursorWidth\t\t= 0;\n\tCursorHeight\t= 0;\n\n\tMouseBuffer\t\t= new char[mouse_max_width * mouse_max_height];\n\tMouseBuffX\t\t= -1;\n\tMouseBuffY  \t= -1;\n\tMaxWidth\t\t\t= mouse_max_width;\n\tMaxHeight\t\t= mouse_max_height;\n\n\tMouseCXLeft\t\t= 0;\n\tMouseCYUpper\t= 0;\n\tMouseCXRight\t= 0;\n\tMouseCYLower\t= 0;\n\tMCFlags\t\t\t= 0;\n\tMCCount\t\t\t= 0;\n\n\tScreen\t\t\t= scr;\n\tPrevCursor\t\t= NULL;\n\tMouseUpdate\t\t= 0;\n\tState\t\t\t\t= 1;\n\ttimeBeginPeriod ( 1000/ 60);\n\n\tInitializeCriticalSection (&MouseCriticalSection);\n\t//\n\t// Install the timer callback event handler\n\t//\n\n\tEraseBuffer\t\t= new char[mouse_max_width * mouse_max_height];\n\tEraseBuffX\t\t= -1;\n\tEraseBuffY  \t= -1;\n\tEraseBuffHotX\t= -1;\n\tEraseBuffHotY\t= -1;\n\tEraseFlags\t\t= FALSE;\n\n\t_Mouse\t\t\t= this;\n\tTimerHandle = timeSetEvent( 1000/60 , 1 , ::Process_Mouse, 0 , TIME_PERIODIC);\n\n\t/*\n\t** Force the windows mouse pointer to stay withing the graphic view port region\n\t*/\n\tSet_Cursor_Clip();\n}\n\nWWMouseClass::~WWMouseClass()\n{\n\tMouseUpdate++;\n\n\tif (MouseCursor) delete[] MouseCursor;\n\tif (MouseBuffer) delete[] MouseBuffer;\n\tif (TimerHandle) {\n\t\ttimeKillEvent(TimerHandle);\n\t}\n\ttimeEndPeriod (1000/60);\n\tDeleteCriticalSection(&MouseCriticalSection);\n\n\t/*\n\t** Free up the windows mouse pointer movement\n\t*/\n\tClear_Cursor_Clip();\n}\n\n\nvoid Block_Mouse(GraphicBufferClass *buffer)\n{\n\tif (_Mouse){\n\t\t_Mouse->Block_Mouse(buffer);\n\t}\n}\n\n\nvoid Unblock_Mouse(GraphicBufferClass *buffer)\n{\n\tif (_Mouse){\n\t\t_Mouse->Unblock_Mouse(buffer);\n\t}\n}\n\n\n\nvoid WWMouseClass::Block_Mouse(GraphicBufferClass *buffer)\n{\n\tif (buffer == Screen->Get_Graphic_Buffer()){\n\t\tEnterCriticalSection(&MouseCriticalSection);\n\t}\n}\n\n\nvoid WWMouseClass::Unblock_Mouse(GraphicBufferClass *buffer)\n{\n\tif (buffer == Screen->Get_Graphic_Buffer()){\n\t\tLeaveCriticalSection(&MouseCriticalSection);\n\t}\n}\n\n\n\n\n\nvoid WWMouseClass::Set_Cursor_Clip(void)\n{\n\n\tif (Screen){\n\t\tRECT\tregion;\n\n\t\tregion.left\t\t= 0;\n\t\tregion.top \t\t= 0;\n\t\tregion.right\t= Screen->Get_Width();\n\t\tregion.bottom\t= Screen->Get_Height();\n\n\t\tClipCursor(&region);\n\t}\n}\n\n\n\nvoid WWMouseClass::Clear_Cursor_Clip(void)\n{\n\tClipCursor(NULL);\n}\n\n\n\nvoid WWMouseClass::Process_Mouse(void)\n{\n\tPOINT \tpt;\t\t\t\t\t// define a structure to hold current cursor pos\n\n\t//\n\t// If the mouse is currently hidden or it has not been installed, then we\n\t// have no need to redraw the mouse.\n\t//\n\tif (!Screen || !_Mouse || State > 0 || MouseUpdate || EraseFlags || !GameInFocus)\n\t\treturn;\n\n\t//\n\t// Make sure there are no conflicts with other\n\t// threads that may try and lock the screen buffer\n\t//\n\t//Block_Mouse(Screen->Get_Graphic_Buffer());\n\n\t//\n\t// If the screen is already locked by another thread then just exit\n\t//\n\tif (Screen->Get_LockCount()!=0){\n\t\t//Unblock_Mouse(Screen->Get_Graphic_Buffer());\n\t\treturn;\n\t}\n\n\t//\n\t// Get the mouse's current real cursor position\n\t//\n\tGetCursorPos(&pt);\t\t\t// get the current cursor position\n\t//\n\t// If the mouse has moved then we are responsible to redraw the mouse\n\t//\n\tif (pt.x != MouseBuffX || pt.y != MouseBuffY) {\n\t\t//\n\t\t// If we can't lock the surface we need to draw to, we cannot update\n\t\t// the mouse.\n\t\t//\n\t\tif (Screen->Lock()) \t{\n\t\t\t//\n\t\t\t// Erase the old mouse by dumping the mouses shadow buff\n\t\t\t//   to the screen (if its position had ever been recorded).\n\t\t\t//\n\t\t\tLow_Hide_Mouse();\n\n\t\t\t//\n\t\t\t// Verify that the mouse has not gone into a conditional hiden area\n\t\t\t// If it has, mark it as being in one.\n\t\t\t//\n\t\t\tif (MCFlags & CONDHIDE && pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {\n\t\t\t\tMCFlags |= CONDHIDDEN;\n\t\t\t}\n\n\t\t\t//\n\t\t\t// Show the mouse if we are allowed to.\n\t\t\t//\n\t\t\tif (!(MCFlags & CONDHIDDEN)) \t{\n\t\t\t\tLow_Show_Mouse(pt.x, pt.y);\n\t\t\t}\n\t\t\t//\n\t\t\t// Finally unlock the destination surface as we have sucessfully\n\t\t\t// updated the mouse.\n\t\t\t//\n\t\t\tScreen->Unlock();\n\t\t}\n\t}\n\n\t//\n\t// Allow other threads to lock the screen again\n\t//\n\t//Unblock_Mouse(Screen->Get_Graphic_Buffer());\n}\n\nvoid *WWMouseClass::Set_Cursor(int xhotspot, int yhotspot, void *cursor)\n{\n\t//\n\t// If the pointer to the cursor we got is invalid, or its the same as the\n\t// currently set cursor then just return.\n\tif (!cursor || cursor == PrevCursor)\n\t\treturn(cursor);\n\n\t//\n\t// Wait until we have exclusive access to our data\n\t//\n\tMouseUpdate++;\n\t//\n\t// Since we are updating the mouse we need to hide the cursor so we\n\t// do not get some sort of weird transformation.\n\t//\n\tHide_Mouse();\n\t//\n\t// Now convert the shape to a mouse cursor with the given hotspots and\n\t// set it as our current mouse.\n\t//\n\tvoid *retval = ASM_Set_Mouse_Cursor(this, xhotspot, yhotspot, cursor);\n\t//\n\t// Show the mouse which will force it to appear with the new shape we\n\t// have assigned.\n\t//\n\tShow_Mouse();\n\t//\n\t// We are done updating the mouse cursor so on to bigger and better things.\n\t//\n\tMouseUpdate--;\n\t//\n\t// Return the previous mouse cursor which as conveniantly passed back by\n\t// Asm_Set_Mouse_Cursor.\n\t//\n\treturn(retval);\n}\n\nvoid WWMouseClass::Low_Hide_Mouse()\n{\n\tif (!State) {\n\t\tif (MouseBuffX != -1 || MouseBuffY != -1) {\n\t\t\tif (Screen->Lock()){\n\t\t\t\tMouse_Shadow_Buffer(this, Screen, MouseBuffer, MouseBuffX, MouseBuffY, MouseXHot, MouseYHot, 0);\n\t\t\t\tScreen->Unlock();\n\t\t\t}\n\t\t}\n\t\tMouseBuffX = -1;\n\t\tMouseBuffY = -1;\n\t}\n\tState++;\n}\nvoid WWMouseClass::Hide_Mouse()\n{\n\tMouseUpdate++;\n\tLow_Hide_Mouse();\n\tMouseUpdate--;\n}\n\n\nvoid WWMouseClass::Low_Show_Mouse(int x, int y)\n{\n\t//\n\t// If the mouse is already visible then just ignore the problem.\n\t//\n\tif (State == 0) return;\n\t//\n\t// Make the mouse a little bit more visible\n\t//\n\tState--;\n\n\t//\n\t//\tIf the mouse is completely visible then draw it at its current\n\t// position.\n\t//\n\tif (!State)\t{\n\t\t//\n\t\t// Try to lock the screen til we sucessfully get a lock.\n\t\t//\n\t\tif (Screen->Lock()){\n\t\t\t//\n\t\t\t// Save off the area behind the mouse.\n\t\t\t//\n\t\t\tMouse_Shadow_Buffer(this, Screen, MouseBuffer, x, y, MouseXHot, MouseYHot, 1);\n\t\t\t//\n\t\t\t// Draw the mouse in its new location\n\t\t\t//\n\t\t\t::Draw_Mouse(this, Screen, x, y);\n\t\t\t//\n\t\t\t// Save off the positions that we saved the buffer from\n\t\t\t//\n\t\t\tMouseBuffX = x;\n\t\t\tMouseBuffY = y;\n\t\t\t//\n\t\t\t// Unlock the screen and lets get moving.\n\t\t\t//\n\t\t\tScreen->Unlock();\n\t\t}\n\t}\n}\n\nvoid WWMouseClass::Show_Mouse()\n{\n\tPOINT\tpt;\n\tGetCursorPos(&pt);\n\n\tMouseUpdate++;\n\tLow_Show_Mouse(pt.x, pt.y);\n\tMouseUpdate--;\n}\n\nvoid WWMouseClass::Conditional_Hide_Mouse(int x1, int y1, int x2, int y2)\n{\n\tPOINT\tpt;\n\n\tMouseUpdate++;\n\n\t//\n\t// First of all, adjust all the coordinates so that they handle\n\t// the fact that the hotspot is not necessarily the upper left\n\t// corner of the mouse.\n\t//\n\tx1 -= (CursorWidth - MouseXHot);\n\tx1  = MAX(0, x1);\n\ty1 -= (CursorHeight - MouseYHot);\n\ty1  = MAX(0, y1);\n\tx2  += MouseXHot;\n\tx2  = MIN(x2, Screen->Get_Width());\n\ty2  += MouseYHot;\n\ty2  = MIN(y2, Screen->Get_Height());\n\n\t// The mouse could be in one of four conditions.\n\t// 1) The mouse is visible and no conditional hide has been specified.\n\t// \t(perform normal region checking with possible hide)\n\t// 2) The mouse is hidden and no conditional hide as been specified.\n\t// \t(record region and do nothing)\n\t// 3) The mouse is visible and a conditional region has been specified\n\t// \t(expand region and perform check with possible hide).\n\t// 4) The mouse is already hidden by a previous conditional.\n\t// \t(expand region and do nothing)\n\t//\n\t// First: Set or expand the region according to the specified parameters\n\tif (!MCCount) {\n\t\tMouseCXLeft\t\t= x1;\n\t\tMouseCYUpper\t= y1;\n\t\tMouseCXRight\t= x2;\n\t\tMouseCYLower\t= y2;\n\t} else {\n\t\tMouseCXLeft\t\t= MIN(x1, MouseCXLeft);\n\t\tMouseCYUpper\t= MIN(y1, MouseCYUpper);\n\t\tMouseCXRight\t= MAX(x2, MouseCXRight);\n\t\tMouseCYLower\t= MAX(y2, MouseCYLower);\n\t}\n\t//\n\t// If the mouse isn't already hidden, then check its location against\n\t// the hiding region and hide if necessary.\n\t//\n\tif (!(MCFlags & CONDHIDDEN)) {\n\t\tGetCursorPos(&pt);\n\t\tif (MouseBuffX >= MouseCXLeft && MouseBuffX <= MouseCXRight && MouseBuffY >= MouseCYUpper && MouseBuffY <= MouseCYLower) {\n\t\t\tLow_Hide_Mouse();\n\t\t\tMCFlags |= CONDHIDDEN;\n\t\t}\n\t}\n\t//\n\t// Record the fact that a conditional hide was called and then exit\n\t//\n\t//\n\tMCFlags |= CONDHIDE;\n\tMCCount++;\n\tMouseUpdate--;\n\n}\nvoid WWMouseClass::Conditional_Show_Mouse(void)\n{\n\tMouseUpdate++;\n\n\t//\n\t// if there are any nested hides then dec the count\n\t//\n\tif (MCCount) {\n\t\tMCCount--;\n\t\t//\n\t\t// If the mouse is now not hidden and it had actually been\n\t\t// hidden before then display it.\n\t\t//\n\t\tif (!MCCount) {\n\t\t\tif (MCFlags & CONDHIDDEN) {\n\t\t\t\tShow_Mouse();\n\t\t\t}\n\t\t\tMCFlags = 0;\n\t\t}\n\t}\n\n\tMouseUpdate--;\n}\n\n\nvoid WWMouseClass::Draw_Mouse(GraphicViewPortClass *scr)\n{\n\tPOINT pt;\n\n\tif (State != 0) return;\n\tMouseUpdate++;\n\t//\n\t//\tGet the position that the mouse is currently located at\n\t//\n\tGetCursorPos(&pt);\n\tif (MCFlags & CONDHIDE && pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {\n\t\tHide_Mouse();\n\t\tMCFlags |= CONDHIDDEN;\n\t} else {\n\t\t//\n\t\t// If the mouse is already visible then just ignore the problem.\n\t\t//\n\t\tEraseFlags = TRUE;\n\n\t\t//\n\t\t// Try to lock the screen  - dont do video stuff if we cant.\n\t\t//\n\t\tif (scr->Lock()){\n\t\t\t//\n\t\t\t// Save off the area behind the mouse into two different buffers, one\n\t\t\t// which will be used to restore the mouse and the other which will\n\t\t\t// be used to restore the hidden surface when we get a chance.\n\t\t\t//\n\t\t\tMouse_Shadow_Buffer(this, scr, EraseBuffer, pt.x, pt.y, MouseXHot, MouseYHot, 1);\n\t\t\tmemcpy(MouseBuffer, EraseBuffer, MaxWidth * MaxHeight);\n\t\t\t//\n\t\t\t// Draw the mouse in its new location\n\t\t\t//\n\t\t\t::Draw_Mouse(this, scr, pt.x, pt.y);\n\t\t\t//\n\t\t\t// Save off the positions that we saved the buffer from\n\t\t\t//\n\t\t\tEraseBuffX \t\t= pt.x;\n\t\t\tMouseBuffX \t\t= pt.x;\n\t\t\tEraseBuffY \t\t= pt.y;\n\t\t\tMouseBuffY \t\t= pt.y;\n\t\t\tEraseBuffHotX\t= MouseXHot;\n\t\t\tEraseBuffHotY\t= MouseYHot;\n\t\t\t//\n\t\t\t// Unlock the screen and lets get moving.\n\t\t\t//\n\t\t\tscr->Unlock();\n\t\t}\n\t}\n\n\tMouseUpdate--;\n}\n\nvoid WWMouseClass::Erase_Mouse(GraphicViewPortClass *scr, int forced)\n{\n\t//\n\t// If we are forcing the redraw of a mouse we already managed to\n\t// restore then just get outta here.\n\t//\n\tif (forced && EraseBuffX == -1 && EraseBuffY == -1) return;\n\n\tMouseUpdate++;\n\n\t//\n\t// If this is not a forced call, only update the mouse is we can legally\n\t//\tlock the buffer.\n\t//\n\tif (!forced) {\n#if(0)\n\t\tif (scr->Lock()) {\n\t\t\t//\n\t\t\t// If the surface has not already been restore then restore it and erase the\n\t\t\t// restoration coordinates so we don't accidentally do it twice.\n\t\t\t//\n\t\t\tif (EraseBuffX != -1 || EraseBuffY != -1) {\n\t\t\t\tMouse_Shadow_Buffer(this, scr, EraseBuffer, EraseBuffX, EraseBuffY, 0);\n\t\t\t\tEraseBuffX = -1;\n\t\t\t\tEraseBuffY = -1;\n\t\t\t}\n\t\t\t//\n\t\t\t// We are done writing to the buffer so unlock it.\n\t\t\t//\n\t\t\tscr->Unlock();\n\t\t}\n#endif\n\t} else\t{\n\t\t\t//\n\t\t\t// If the surface has not already been restore then restore it and erase the\n\t\t\t// restoration coordinates so we don't accidentally do it twice.\n\t\t\t//\n\t\t\tif (EraseBuffX != -1 || EraseBuffY != -1) {\n\t\t\t\tif (scr->Lock()){\n\t\t\t\t\tMouse_Shadow_Buffer(this, scr, EraseBuffer, EraseBuffX, EraseBuffY, EraseBuffHotX, EraseBuffHotY, 0);\n\t\t\t\t\tscr->Unlock();\n\t\t\t\t}\n\t\t\t\tEraseBuffX = -1;\n\t\t\t\tEraseBuffY = -1;\n\t\t\t}\n\t}\n\tMouseUpdate--;\n  \tEraseFlags = FALSE;\n}\n\nint WWMouseClass::Get_Mouse_State(void)\n{\n\treturn(State);\n}\n/***********************************************************************************************\n * WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels             *\n *                                                                                             *\n * INPUT:\t\tnone                                                                            *\n *                                                                                             *\n * OUTPUT:     int\t\t- returns the mouses current x position in pixels                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nint WWMouseClass::Get_Mouse_X(void)\n{\n\tPOINT \tpt;\n\tGetCursorPos(&pt);\n\treturn(pt.x);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels             *\n *                                                                                             *\n * INPUT:\t\tnone                                                                            *\n *                                                                                             *\n * OUTPUT:     int\t\t- returns the mouses current y position in pixels                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nint WWMouseClass::Get_Mouse_Y(void)\n{\n\tPOINT \tpt;\n\tGetCursorPos(&pt);\n\treturn(pt.y);\n}\n\n/***********************************************************************************************\n * WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars         *\n *                                                                                             *\n * INPUT:\t\tint &x\t\t- variable to return the mouses x position in pixels                *\n *\t\t\t\t\tint &y\t\t- variable to return the mouses y position in pixels\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     none - output is via reference variables                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid WWMouseClass::Get_Mouse_XY(int &x, int &y)\n{\n\tPOINT \tpt;\n\n\tGetCursorPos(&pt);\n\tx = pt.x;\n\ty = pt.y;\n}\n\n#pragma off(unreferenced)\n\nvoid CALLBACK Process_Mouse( UINT event_id, UINT res1 , DWORD user, DWORD  res2, DWORD  res3 )\n{\n\tstatic\tBOOL\tin_mouse_callback = false;\n\n\tif (_Mouse && !in_mouse_callback) {\n\t\tin_mouse_callback = TRUE;\n\t\t_Mouse->Process_Mouse();\n\t\tin_mouse_callback = FALSE;\n\t}\n}\n#pragma on(unreferenced)\n\nvoid Hide_Mouse(void)\n{\n\tif (!_Mouse) return;\n\t_Mouse->Hide_Mouse();\n}\n\nvoid Show_Mouse(void)\n{\n\tif (!_Mouse) return;\n\t_Mouse->Show_Mouse();\n}\n\nvoid Conditional_Hide_Mouse(int x1, int y1, int x2, int y2)\n{\n\tif (!_Mouse) return;\n\t_Mouse->Conditional_Hide_Mouse(x1, y1, x2, y2);\n}\n\nvoid Conditional_Show_Mouse(void)\n{\n\tif (!_Mouse) return;\n\t_Mouse->Conditional_Show_Mouse();\n}\n\nint Get_Mouse_State(void)\n{\n\tif (!_Mouse) return(0);\n\treturn(_Mouse->Get_Mouse_State());\n}\n\nvoid *Set_Mouse_Cursor(int hotx, int hoty, void *cursor)\n{\n\tif (!_Mouse) return(0);\n\treturn(_Mouse->Set_Cursor(hotx,hoty,cursor));\n}\n\nint Get_Mouse_X(void)\n{\n\tif (!_Mouse) return(0);\n\treturn(_Mouse->Get_Mouse_X());\n}\n\nint Get_Mouse_Y(void)\n{\n\tif (!_Mouse) return(0);\n\treturn(_Mouse->Get_Mouse_Y());\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/NEWDEL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory system.                           *\n *                                                                         *\n *                    File Name : NEWDEL.CPP                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : June 21, 1994                            *\n *                                                                         *\n *                  Last Update : October 20, 1994   [SKB]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   operator NEW -- Overides the global new function.                     *\n *   operator delete -- Overides the global delete function.               *\n *   operator NEW[] -- Overides the array version of new.                  *\n *   operator delete[] -- Overides the array version of delete[]           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwmem.h\"\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * OPERATOR NEW -- Overides the global new function.                       *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid * operator new(size_t size) \n{\n\treturn (Alloc((unsigned long) size, MEM_NEW));\n}\n\n\n/***************************************************************************\n * OPERATOR NEW[] -- Overides the array version of new.                    *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid * operator new[](size_t size) \n{\n\treturn (Alloc((unsigned long) size, MEM_NEW));\n}\n \n\n/***************************************************************************\n * OPERATOR DELETE -- Overides the global delete function.                 *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid operator delete(void *ptr) \n{\n\tFree(ptr);\n}\n\n/***************************************************************************\n * OPERATOR DELETE[] -- Overides the array version of delete[]           \t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/20/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid operator delete[](void *ptr) \n{\n\tFree(ptr);\n}\n\n\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/OLSOSDEC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*          Copyright (c) 1994, HMI, INC. All Rights Reserved\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     soscodec.asm\n;*\n;* DESCRIPTION\n;*     HMI SOS ADPCM compression/decompression.\n;*\n;* PROGRAMMER\n;*     Nick Skrepetos\n;*     Denzil E. Long, Jr. (Fixed bugs, rewrote for watcom)\n;*\t   Bill Petro\t\t   (Added stereo support)\n;* DATE\n;*     Febuary 15, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\n\nDPMI_INTR\t\tequ\t31h\nIF_LOCKED_PM_CODE\tequ\t1h\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t2h\t\t; Locked PM code for DPMI.\n\n\tSTRUC\tsCompInfo\nlpSource\t\tDD\t?\t;Compressed data pointer\nlpDest\t\t\tDD\t?\t;Uncompressed data pointer\ndwCompSize\t\tDD\t?\t;Compressed size\ndwUnCompSize\t\tDD\t?\t;Uncompressed size\n\ndwSampleIndex\t\tDD\t?\t;Index into sample\ndwPredicted\t\tDD\t?\t;Next predicted value\ndwDifference\t\tDD\t?\t;Difference from last sample\nwCodeBuf\t\tDW\t?\t;Holds 2 nibbles for decompression\nwCode\t\t\tDW\t?\t;Current 4 bit code\nwStep\t\t\tDW\t?\t;Step value in table\nwIndex\t\t\tDW\t?\t;Index into step table\n\ndwSampleIndex2\t\tDD\t?\t;Index into sample\ndwPredicted2\t\tDD\t?\t;Next predicted value\ndwDifference2\t\tDD\t?\t;Difference from last sample\nwCodeBuf2 \t\tDW\t?\t;Holds 2 nibbles for decompression\nwCode2\t\t\tDW\t?\t;Current 4 bit code\nwStep2\t\t\tDW\t?\t;Step value in table\nwIndex2\t\tDW\t?\t;Index into step table\n\nwBitSize\t\tDW\t?\t;Bit size for decompression\nwChannels\t\tDW\t?    \t;number of channels\n\tENDS\tsCompInfo\n\n\tDATASEG\n\n\nInitFlags\tDD\t0\t\t; Flags to indicate what has been initialized.\n\n\nLABEL\tLockedDataStart\tBYTE\n\n;* Index table for stepping into step table\n\nwCODECIndexTab\tDW\t-1,-1,-1,-1,2,4,6,8\n\t\tDW\t-1,-1,-1,-1,2,4,6,8\n\n\n;Lookup table of replacement values\n;The actual sound value is replaced with an index to lookup in this table\n;The index only takes up a nibble(4bits) and represents an int(16bits)\n;Essentially:\n;Get a value\n;compare it with the value before it\n;find closest value in table and store the index into the table\n;if i'm going down then negitize it\n;go to next byte.\n\n;Theory for stereo:\n;1)handle stereo and mono in two seperate loops. cleaner...\n;start at byte 0 and skip every other byte(or word) both write and read\n;when we get done\n;\tset start byte to 1 and do it again\n\n\n\n\n;This table essentialy round off to closes values in 3 distinct bands\n; precalculated and optimized(i guess) for human hearing.\n\nwCODECStepTab\tDW\t7,  \t8,  \t9,   \t10,   \t11,  \t12,   \t13,14\n\tDW\t16, \t17, \t19, \t21,  \t23,   \t25,  \t28,   \t31\n\tDW\t34, \t37, \t41, \t45,  \t50,   \t55,  \t60,   \t66\n\tDW\t73, \t80, \t88, \t97,  \t107,  \t118, \t130,  \t143\n\tDW\t157,\t173,\t190,\t209, \t230,  \t253, \t279,  \t307\n\tDW\t337,\t371,\t408,\t449, \t494,  \t544, \t598,  \t658\n\tDW\t724,\t796,\t876,\t963, \t1060,\t1166,\t1282,\t1411\n\tDW\t1552,\t1707,\t1878,\t2066,\t2272,\t2499,\t2749,\t3024\n\tDW\t3327,\t3660,\t4026,\t4428,\t4871,\t5358,\t5894,\t6484\n\tDW\t7132,\t7845,\t8630,\t9493,\t10442,\t11487,\t12635,\t13899\n\tDW\t15289,\t16818,\t18500,\t20350,\t22385,\t24623,\t27086,\t29794\n\tDW\t32767\n\n;dwCODECByteIndex\t\tDD\t0 ; this is when to stop compressing\n;dwCODECTempStep\t\tDD\t0 ; tempory storage for step value\n;wCODECMask\t\t\tDW\t0 ; Current mask\n\nLABEL\tLockedDataEnd\tBYTE\n\n\n\tCODESEG\n\nLABEL\tLockedCodeStart\tBYTE\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECInitStream - Initialize compression stream.\n;*\n;* SYNOPSIS\n;*     sosCODECInitStream(CompInfo)\n;*\n;*     void sosCODECInitStream(_SOS_COMPRESS_INFO *);\n;*\n;* FUNCTION\n;*     Initialize compression stream for compression and decompression.\n;*\n;* INPUTS\n;*     CompInfo - Compression information structure.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC sosCODECInitStream:NEAR\n\tPROC\tsosCODECInitStream C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\n\tmov\teax,[sSOSInfo]\n\tmov\t[(sCompInfo eax).wIndex],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).wStep],7  \t\t; start with a step of 7\n\tmov\t[(sCompInfo eax).dwPredicted],0 \t; no predicted value\n\tmov\t[(sCompInfo eax).dwSampleIndex],0\t;start at head of index\n\tmov\t[(sCompInfo eax).wIndex2],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).wStep2],7  \t\t; start with a step of 7\n\tmov\t[(sCompInfo eax).dwPredicted2],0 \t; no predicted value\n\tmov\t[(sCompInfo eax).dwSampleIndex2],0 \t;start at head of index\n\tret\n\n\tENDP\tsosCODECInitStream\n\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECDecompressData - Decompress audio data.\n;*\n;* SYNOPSIS\n;*     Size = sosCODECDecompressData(CompInfo, NumBytes)\n;*\n;*     long sosCODECDecompressData(_SOS_COMPRESS_INFO *, long);\n;*\n;* FUNCTION\n;*     Decompress data from a 4:1 ADPCM compressed stream. The number of\n;*     bytes decompressed is returned.\n;*\n;* INPUTS\n;*     CompInfo - Compress information structure.\n;*     NumBytes - Number of bytes to compress.\n;*\n;* RESULT\n;*     Size - Size of decompressed data.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC General_sosCODECDecompressData:NEAR\n\tPROC\tGeneral_sosCODECDecompressData C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\tARG\twBytes:DWORD\n\n\tlocal\tdwCODECBytesProcessed:dword             ;bytes to decompress\n\tlocal\tdwCODECByteIndex:dword\t\t\t;this is when to stop compressing\n\t\t\t\t\t\t\t; these need to be local if the function is to be reenterant\n\tpush\tesi\n\tpush\tedi\n\tpush\tebx\n\tpush\tecx\n\tpush\tedx\n\n;*---------------------------------------------------------------------------\n;*\tInitialize\n;*---------------------------------------------------------------------------\n\n\tmov\tebx,[sSOSInfo]\n\tmov\teax,[wBytes]\n\tmov\t[dwCODECBytesProcessed],eax\n\tmov\t[(sCompInfo ebx).dwSampleIndex],0 \t;start at head of index\n\tmov\t[(sCompInfo ebx).dwSampleIndex2],0 \t;start at head of index\n\n\t\t\t\t\t\t\t;Check for 16 bit decompression\n\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??skipByteDivide\n\n\tshr\teax,1\t;Divide size by two\n\n??skipByteDivide:\n\tmov\t[dwCODECByteIndex],eax\n\tmov\tesi,[(sCompInfo ebx).lpSource]\n\tmov\tedi,[(sCompInfo ebx).lpDest]\n\tcmp\t[(sCompInfo ebx).wChannels],2\t\t;stereo check\n\tje\t??mainloopl\t\t\t\t;do left side first\n\n;\tDetermine if sample index is even or odd. This will determine\n;\tif we need to get a new token or not.\n\n;---------------------------------------------------------------------------\n;Main Mono Loop\n;---------------------------------------------------------------------------\n\n\n\n??mainloop:\n\ttest\t[(sCompInfo ebx).dwSampleIndex],1\t;odd ??\n\tje\tshort ??fetchToken\t\t\t; if so get new token\n\txor\teax,eax\t\t\t\t\t;else shift int codebuf\n\tmov\tax,[(sCompInfo ebx).wCodeBuf]\t\t;ored with Code\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\tjmp\tshort ??calcDifference\n\n??fetchToken:\n\txor\teax,eax\t\t\t\t\t;get a new token\n\tmov\tal,[esi]\t\t\t\t;put in codebuf\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\n\tinc\tesi\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\t\t;and then code\n\n??calcDifference:\n\tmov\t[(sCompInfo ebx).dwDifference],0\t;reset diff\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep]\t\t;cx is step value\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4\n\tadd\t[(sCompInfo ebx).dwDifference],ecx\t;Add wStep\n\n??no4:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no2:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no1:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8\n\tneg\t[(sCompInfo ebx).dwDifference]\t\t;Negate diff\n\n??no8:\n\t; add difference to predicted value.\n\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\n\tadd\teax,[(sCompInfo ebx).dwDifference]\n\n\t; make sure there is no under or  overflow.\n\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflow\n\tmov\teax,7FFFh\n\n??noOverflow:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflow\n\tmov\teax,0FFFF8000h\n\n??noUnderflow:\n\tmov\t[(sCompInfo ebx).dwPredicted],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bit\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,2\n\tjmp\tshort ??adjustIndex\n\n??output8Bit:\n\t; output 8 bit sample\n\n\txor\tah,80h\n\tmov\t[edi],ah\n\tinc\tedi\n\n??adjustIndex:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex],ax \t\t;check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex],8000h\n\tjb\tshort ??checkOverflow\n\tmov\t[(sCompInfo ebx).wIndex],0\t\t;reset index to zero\n\tjmp\tshort ??adjustStep\n\n??checkOverflow:\n\tcmp\t[(sCompInfo ebx).wIndex],88\t\t;check if wIndex > 88\n\tjbe\tshort ??adjustStep\n\tmov\t[(sCompInfo ebx).wIndex],88\t\t;reset index to 88\n\n??adjustStep:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex],1\n\tmov\t[(sCompInfo ebx).wStep],ax\n\n\t; decrement bytes processed and loop back.\n\n\tdec\t[dwCODECByteIndex]\n\tjne\t??mainloop\n\tjmp\t??exitout\n\n;--------------------------------------------------------------------------\n;Left Channel Start\n;--------------------------------------------------------------------------\n\n\n??mainloopl:\n\ttest\t[(sCompInfo ebx).dwSampleIndex],1\n\tje\tshort ??fetchTokenl\n\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCodeBuf]\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\tjmp\tshort ??calcDifferencel\n\n??fetchTokenl:\n\txor\teax,eax\n\tmov\tal,[esi]\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\n\tadd\tesi,2\t\t\t\t\t;2 for stereo\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\n??calcDifferencel:\n\t\t\t\t\t\t\t; reset difference\n\n\tmov\t[(sCompInfo ebx).dwDifference],0\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep]\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4l\n\tadd\t[(sCompInfo ebx).dwDifference],ecx\t;Add wStep\n\n??no4l:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2l\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no2l:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1l\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no1l:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8l\n\tneg\t[(sCompInfo ebx).dwDifference]\t\t;Negate diff\n\n??no8l:\n\t\t; add difference to predicted value.\n\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\n\tadd\teax,[(sCompInfo ebx).dwDifference]\n\n\t\t; make sure there is no under or  overflow.\n\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowl\n\tmov\teax,7FFFh\n\n??noOverflowl:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowl\n\tmov\teax,0FFFF8000h\n\n??noUnderflowl:\n\tmov\t[(sCompInfo ebx).dwPredicted],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bitl\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,4\t\t\t\t\t;4 for stereo\n\tjmp\tshort ??adjustIndexl\n\n??output8Bitl:\n\t; output 8 bit sample\n\n\txor\tah,80h\n\tmov\t[edi],ah\n\tadd\tedi,2\t\t\t\t\t;2 for stereo\n\n??adjustIndexl:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex],ax\n\t\t\t\t\t\t\t; check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex],8000h\n\tjb\tshort ??checkOverflowl\n\tmov\t[(sCompInfo ebx).wIndex],0\n\tjmp\tshort ??adjustStepl\t\t\t;reset index to zero\n\n\n??checkOverflowl:\n\n\tcmp\t[(sCompInfo ebx).wIndex],88\t\t; check if wIndex > 88\n\tjbe\tshort ??adjustStepl\n\tmov\t[(sCompInfo ebx).wIndex],88\t\t; reset index to 88\n\n??adjustStepl:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex],1\n\tmov\t[(sCompInfo ebx).wStep],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2\n\tjne\t??mainloopl\n;----------------------------------------------------------------------------\n; Right Side Setup\n;----------------------------------------------------------------------------\n\tmov\teax,[wBytes]\n\tmov\t[dwCODECBytesProcessed],eax\n\tmov\tesi,[(sCompInfo ebx).lpSource]\n\tmov\tedi,[(sCompInfo ebx).lpDest]\n\tinc\tesi\t\t\t\t\t; skip left channel\n\tinc\tedi\t\t\t\t     \t; skip left channel\n\tcmp\t[(sCompInfo ebx).wBitSize],16\t\t;16 bit ??\n\tje\tshort ??doByteDivide\n\tmov\t[dwCODECByteIndex],eax\n\tjmp  short ??mainloopr\n\n??doByteDivide:\n\tshr\teax,1 \t\t\t\t\t;Divide size by two\n\tinc\tedi   \t\t\t\t\t; 16 bit so skip 1 more\n\tmov\t[dwCODECByteIndex],eax\n\n\n;--------------------------------------------------------------------------\n;Right Channel Start\n;--------------------------------------------------------------------------\n\n\n??mainloopr:\n\ttest\t[(sCompInfo ebx).dwSampleIndex2],1\n\tje\tshort ??fetchTokenr\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCodeBuf2]\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode2],ax\n\tjmp\tshort ??calcDifferencer\n\n??fetchTokenr:\n\txor\teax,eax\n\tmov\tal,[esi]\n\tmov\t[(sCompInfo ebx).wCodeBuf2],ax\n\tadd\tesi,2\t\t\t\t     \t;2 for stereo\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode2],ax\n\n??calcDifferencer:\n\t\t\t\t\t\t\t; reset difference\n\n\tmov\t[(sCompInfo ebx).dwDifference2],0\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep2]\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4r\n\tadd\t[(sCompInfo ebx).dwDifference2],ecx\t;Add wStep\n\n??no4r:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2r\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\n??no2r:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1r\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\n??no1r:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8r\n\tneg\t[(sCompInfo ebx).dwDifference2]\t\t;Negate diff\n\n??no8r:\n\t; add difference to predicted value.\n\tmov\teax,[(sCompInfo ebx).dwPredicted2]\n\tadd\teax,[(sCompInfo ebx).dwDifference2]\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowr\n\tmov\teax,7FFFh\n\n??noOverflowr:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowr\n\tmov\teax,0FFFF8000h\n\n??noUnderflowr:\n\tmov\t[(sCompInfo ebx).dwPredicted2],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bitr\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,4\t\t\t\t\t;4 for stereo\t\t***\n\tjmp\tshort ??adjustIndexr\n\n??output8Bitr:\n\t\t\t\t\t\t\t; output 8 bit sample\n\txor\tah,80h\n\tmov\t[edi],ah\n\tadd\tedi,2\t\t\t\t\t;2 for stereo\n\n??adjustIndexr:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode2]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex2],ax\n\t\t\t\t\t\t\t; check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex2],8000h\n\tjb\tshort ??checkOverflowr\n\t\t\t\t\t\t\t; reset index to zero\n\tmov\t[(sCompInfo ebx).wIndex2],0\n\tjmp\tshort ??adjustStepr\n\n??checkOverflowr:\n\t\t\t\t\t\t\t; check if wIndex > 88\n\tcmp\t[(sCompInfo ebx).wIndex2],88\n\tjbe\tshort ??adjustStepr\n\tmov\t[(sCompInfo ebx).wIndex2],88\t\t; reset index to 88\n\n??adjustStepr:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex2]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex2],1\n\tmov\t[(sCompInfo ebx).wStep2],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2\n\tjne\t??mainloopr\n\n\n??exitout:\n;\t\tdon't think we need this but just in case i'll leave it here!!\n\n;\tmov\t[(sCompInfo ebx).lpSource],esi\n;\tmov\t[(sCompInfo ebx).lpDest],edi\n\t; set up return value for number of bytes processed.\n\tmov\teax,[dwCODECBytesProcessed]\n\tpop\tedx\n\tpop\tecx\n\tpop\tebx\n\tpop\tedi\n\tpop\tesi\n\tret\n\n\tENDP\tGeneral_sosCODECDecompressData\n\nLABEL\tLockedCodeEnd\tBYTE\n\n;***************************************************************************\n;* sosCODEC_LOCK -- locks the JLB audio decompression code\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is lock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:       BOOL sosCODEC_Lock(void);                         \t   *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC sosCODEC_Lock:NEAR\n\tPROC\tsosCODEC_Lock C NEAR USES ebx ecx edx esi edi\n\n\t;\n\t; Lock the code that is used by the sos decompression method.\n\t;\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n  \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags], IF_LOCKED_PM_CODE\n\n\t;\n\t; Lock the data used by the sos decompression method.\n\t;\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags], IF_LOCKED_PM_DATA\n\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\tENDP\tsosCODEC_Lock\n\n;***************************************************************************\n;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code       *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is unlock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:\tBOOL sosCODEC_Unlock(void);                        \t   *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC sosCODEC_Unlock:NEAR\n\tPROC\tsosCODEC_Unlock C NEAR USES ebx ecx edx esi edi\n\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\n??code_not_locked:\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??data_not_locked:\n\tmov\t[InitFlags],0\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\tENDP\tsosCODEC_Unlock\n\n\n\tEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/OPSYS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/system/rcs/opsys.asm 1.1 1994/04/18 09:14:12 jeff_wilson Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Operating System Flags                   *\n;*                                                                         *\n;*                    File Name : OPSYS.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott Bowen                              *\n;*                                                                         *\n;*                   Start Date : January 26, 1993                         *\n;*                                                                         *\n;*                  Last Update : January 26, 1993   [SB]                  *\n;*                                                                         *\n;* Updated to 32bit protected mode JAW\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Operating_System -- Determines what the operating system is.          *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL             C Operating_System         :NEAR\nGLOBAL             C OperatingSystem          :WORD\n\nDOS\t\tequ\t1\nWIN31STD\tequ\t2\nWIN31ENH\tequ\t3\nWIN30ENH\tequ\t4\nWIN30STD\tequ\t5\nWIN30REAL\tequ\t6\n\nDATASEG\n\nOperatingSystem\tdw\t0\n\n\nCODESEG\n\n;***************************************************************************\n;* Operating_System -- Determines what the operating system is.            *\n;*                                                                         *\n;* INPUT:   NONE.                                                          *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/26/1993  SB : Created.                                             *\n;*=========================================================================*\nPROC\tOperating_System C near\n\tUSES ebx,ecx,edx,es,edi\n\n\n\t; Check for Windows 3.1\n\tmov\teax,160Ah\t\t; WIN31CHECK\n\tint\t2fh\n\tor\tax,ax\n\tjz\tshort RunningUnderWin31\n\n\t;check for Windows 3.0 enhanced mode\n\tmov \teax,1600h\t\t; WIN386CHECK\n\tint\t2fh\n\tmov\tbl,al\n\tmov\teax,WIN30ENH\n\ttest\tbl,7fh\n\tjnz\tshort Exit\n\n\t;check for 3.0 WINOLDAP\n\tmov\teax,4680h\t\t; IS_WINOLDAP_ACTIVE\n\tint\t2fh\n\tor\teax,eax\n\tjnz\tshort NotRunningUnderWin\n\n\t; rule out MS-DOS 5.0 task switcher\n\tmov\teax,4b02h\t\t; detect switcher\n\tpush\tebx\n\tpush\tes\n\tpush\tedi\n\txor\tebx,ebx\n\tmov\tedi,ebx\n\tmov\tes,bx\n\tint\t2fh\n\tpop\tedi\n\tpop\tes\n\tpop\tebx\n\tor\teax,eax\n\tjz\tshort NotRunningUnderWin\t; MS-DOS 5.0 task switcher found.\n\n\t; check for standrd mode Windows 3.0\n\tmov\teax,1605h\t\t;PMODE_START\n\tint\t2fh\n\tmov\teax,WIN30STD\n\tcmp\tecx,-1\n\tjz\tshort Exit\n\n\t;check for real mode Windows 3.0\n\tmov\teax,1606h\t\t; PMODE_STOP\n\tint\t2fh\n\tmov\teax,WIN30REAL\n\tjmp\tSHORT Exit\n\nRunningUnderWin31:\n\t; At this point: CX == 3 means Windows 3.1 enhanced mode.\n\t;                CX == 2 means Windows 3.1 standard mode.\n\tmov\teax,WIN31STD\n\tcmp\tecx,2\n\tje\tshort Exit\n\n\tmov\teax,WIN31ENH\n\tjmp\tSHORT Exit\n\nNotRunningUnderWin:\n\tmov\teax,DOS\n\nExit:\n\tmov [WORD PTR OperatingSystem], ax\n\tret\n\nENDP\tOperating_System\n\n\n\n;----------------------------------------------------------------------------\n\nEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/PACK2PLN.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/file/rcs/pack2pln.asm 1.1 1994/04/22 18:07:46 scott_bowen Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : PACK2PLN.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen\t\t\t   *\n;*                                                                         *\n;*                   Start Date : November 20, 1991                        *\n;*                                                                         *\n;*                  Last Update : April 22, 1994   [SKB]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nLOCALS ??\n\n\n;******************************************************************************\n; External declares so these functions can be called\n;\nGLOBAL  \t\tPack_2_Plane:NEAR\n\n\tCODESEG\n\n;***************************************************************************\n;* PACK_2_PLANE -- packed to planar scanline conversion                    *\n;*                                                                         *\n;* INPUT:  BYTE *buffer (far) -- pointer to planar output buffer           *\n;*         BYTE *pageptr (far) -- pointer to current row in packed page    *\n;*         WORD planebit -- current bit used in plane -- use only low byte *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*         Return result in buffer.                                        *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/20/1991  SB : Created.                                             *\n;*   04/22/1994 SKB : Converted to 32 bit library.                         *\n;*=========================================================================*\n;\t\t\t\t\t\t\t\t\t   *\n;\tThis is the original function that is converted to asm\n;  \n;PRIVATE VOID Pack_2_Plane(UBYTE * buffer, BYTE * pageptr, BYTE planebit)\n;{\n;  WORD currbit=0x80;\t\t// current bit to be written to\n;  WORD pixel;\t  \t\t// current pixel in row used as a counter;\n;\n;  buffer--;\t\t\t// will be incremented at the start\n;  for (currbit = 0, pixel = 0; pixel < 320; pixel++) {\n;    if (!currbit) {\n;      currbit = 0x80;\t\t// reset bit 7\n;      buffer++;\t\t// go to next byte in buffer\n;      *buffer = 0;\t\t// clear byte so we only need to set bits needed\n;    }\n;  if (planebit & *pageptr++)\n;    *buffer |= currbit;\t// set bit in destination if plane was set is source\n;\n;  currbit >>= 1;\t\t// shift destination bit one right\n;  }\n;}\n\nPROC\tPack_2_Plane C NEAR \n\tUSES\tebx,ecx,esi,edi\n \tARG\tbuffer:DWORD\n\tARG\tpage:DWORD\n\tARG\tplanebit:WORD\n\n\n\tmov\tedi,[buffer]\n\tmov\tesi,[page]\n\n\tmov\tax,[planebit]\t\t; move bit set for current plane (planebit) to ax\n\t\t\t\t\t; the low byte will only be used\n\t      \n\tmov\tecx,320d\t      \t; set counter to 320 columns (320x200 picture)\n\tmov\tah,80h\t\t\t; set bit 7 of current_bit \n\tdec\tedi\t\t\t; this will get incremented at the start\n\n??top_loop:\t\t\t\t; while (columns left)\n\tcmp\tah,80h\t\t\t;   if current_bit is bit 7\n\tjnz\tshort ??same_dest\t\t\t\n\t\t\t\t\t;   Then\n\tinc\tedi\t\t\t;     buffer++  increment pointer\n\tmov\t[BYTE PTR edi],0\t;     *buffer = 0 \n\n??same_dest:\t\t\t\t;   EndIf\n\tmov\tbl,al\n\tand\tbl,[esi]\t\t;   if (planebit & *pageptr)\n\tjz\tshort ??no_set_bit\n\n\tor\t[BYTE PTR edi],ah     \t;     Then *buffer |= current_bit\n\n??no_set_bit:\n\tinc\tesi\t\t\t;   pageptr++\tgoto next in source byte\n\tror\tah,1\t\t\t;   rotate current_bit right one\n\tdec\tecx\t\t\t; \n\tjnz\t??top_loop\n\n\tret\n\n\tENDP\tPack_2_Plane\n\n\tEND\n\u001a"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/PAGFAULT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : PAGFAULT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Julio R Jerez \t                   *\n;*                                                                         *\n;*                   \t   Date : April 25,1995                            *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;\n; Here are prototypes for the routines defined within this module:\n; VOID Install_Page_Fault_Handle (void) ;\n;\n; ----------------------------------------------------------------\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Make some general equates for easy compatability\n;---------------------------------------------------------------------------\nDPMI_INTR\t EQU\t31h\nPAGE_FAULT\t equ\t0eh\nRESET_VIDEO_MODE  equ\t-1\n\nGLOBAL C\t Install_Page_Fault_Handle : NEAR\nGLOBAL C\t Set_Video_Mode\t\t   : NEAR\nGLOBAL C\t Remove_Mouse\t\t   : NEAR\nGLOBAL C\t Remove_Keyboard_Interrupt : NEAR\nGLOBAL C\t Remove_Timer_Interrupt\t   : NEAR\n\nDATASEG\n\tOld_Page_Fault_handle DF ?\n\tPage_Fault_SS \tDD\t?\n\tPage_Fault_ESP\tDD\t?\n\nCODESEG\n;***************************************************************************\n;* INSTALL_PAGE_FAULT_HANDLE -- Installs new page fault handle             *\n;*\tThis function will install a new page fault handle \t\t   *\n;*\tso in the event that we have a program crash thi handle will\t   *\n;*\tremove all interrupts and then will chain to the default Page\t   *\n;*\tFault handle\t\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Install_Page_Fault_Handle( void);  \t\t   *\n;*                                                                         *\n;* HISTORY:  04/25/96 Created                                              *\n;*=========================================================================*\n\tPROC\tInstall_Page_Fault_Handle C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tmov\teax,0202h \t; get address of exception handle\n\tmov\tbl,PAGE_FAULT\n\tint\tDPMI_INTR\n\tjc\t??exit\t\t; not action is taken\n\n\t; save addrees of default handle\n\tmov\t[dword ptr Old_Page_Fault_handle],edx\n\tmov\t[word ptr  Old_Page_Fault_handle+4],cx\n\n\t; redirect default handle to a new Page Fault Handle\n\tmov eax,0203h\n\tmov bl,PAGE_FAULT\n\tmov cx,cs\n\tlea edx,[Page_Fault_Handle]\n\tint DPMI_INTR\n\n  ??exit:\n\tret\n\tENDP\tInstall_Page_Fault_Handle\n\n\n;***************************************************************************\n;* PAGE_FAULT_HANDLE --  This           \t\t   \t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* HISTORY:  04/25/96 Created                                              *\n;*=========================================================================*\nPROC\tPage_Fault_Handle far\n\n\t; preserve used  registers\n\tpush\teax\n\tpush\tebx\n\t; save Page Fault satck frame\n\tmov\tax,ss\n\tmov\t[Page_Fault_SS],eax\n\tmov\t[Page_Fault_ESP],esp\n\n\t; retrieve application original stack frame\n\tmov eax , [ esp + ( 6 + 2 ) * 4 ]\n\tmov ebx , [ esp + ( 7 + 2 ) * 4 ]\n\tmov ss , bx\n\tmov esp , eax\n\n\t; set video mode to standard text mode\n\tpush\tRESET_VIDEO_MODE\n\tcall \tSet_Video_Mode\n\tpop\teax\n\tcall \tRemove_Mouse\n\tcall \tRemove_Keyboard_Interrupt\n\tcall\tRemove_Timer_Interrupt\n\n\t; restore Page Fault stack frame\n\tmov\teax,[Page_Fault_SS]\n\tmov \tss , ax\n\tmov\tesp, [Page_Fault_ESP]\n\n\t; restore used registers and chain to default Page Fault Handle\n\tpop\tebx\n\tpop\teax\n\tjmp\t[fword Old_Page_Fault_handle]\n\n\tENDP\tPage_Fault_Handle\n\n\n;***************************************************************************\n;* End of File.\t\t\t\t\t\t\t\t   *\n;***************************************************************************\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/PAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : PAL.ASM                                  *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : May 30, 1992                             *\n;*                                                                         *\n;*                  Last Update : April 27, 1994   [BR]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Set_Palette_Range -- Sets changed values in the palette.              *\n;*   Bump_Color -- adjusts specified color in specified palette            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************** Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;include \"keyboard.inc\"\nFALSE = 0\nTRUE  = 1\n\n;****************************** Declarations ********************************\nGLOBAL \t\tC Set_Palette_Range:NEAR\nGLOBAL \t\tC Bump_Color:NEAR\nGLOBAL  \tC CurrentPalette:BYTE:768\nGLOBAL\t\tC PaletteTable:byte:1024\n\n\n;********************************** Data ************************************\nLOCALS ??\n\n\tDATASEG\n\nCurrentPalette\tDB\t768 DUP(255)\t; copy of current values of DAC regs\nPaletteTable\tDB\t1024 DUP(0)\n\nIFNDEF LIB_EXTERNS_RESOLVED\nVertBlank\tDW\t0\t\t; !!!! this should go away\nENDIF\n\n\n;********************************** Code ************************************\n\tCODESEG\n\n\n\nIF 1\n;***************************************************************************\n;* SET_PALETTE_RANGE -- Sets a palette range to the new pal                *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:\tThis routine is optimized for changing a small number of   *\n;*\t\tcolors in the palette.\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/07/1995 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tSet_Palette_Range C NEAR\n\tARG\tpalette:DWORD\n\n\tGLOBAL\tSet_DD_Palette_:near\n\tGLOBAL\tWait_Vert_Blank_:near\n\n\tpushad\n\tmov\tesi,[palette]\n\tmov\tecx,768/4\n\tmov\tedi,offset CurrentPalette\n\tcld\n\trep\tmovsd\n\t;call\tWait_Vert_Blank_\n\tmov\teax,[palette]\n\tcall\tSet_DD_Palette_\n\tpopad\n\tret\n\n\nifdef NOT_FOR_WIN95\n\tUSES\teax,ebx,ecx,edx,edi,esi\n\n\tcld\n\n\t;*=================================================================*/\n\t;* Set up pointers to begin making palette comparison\t\t   */\n\t;*=================================================================*/\n\tmov\tesi, [palette]\n\tmov\tedi, OFFSET CurrentPalette\n\tmov\tebx, OFFSET PaletteTable\n\tmov\tecx, 0\n\n??loop_top:\n\tmov\teax,[esi]\t\t\t; read a dword from palette source\n\tmov\tedx,[edi]\t\t\t; read a dword from compare palette\n\tand\teax,00FFFFFFh\t\t\t; palette entrys are only 3 bytes\n\tand\tedx,00FFFFFFh\t\t\t;   long so and of extra\n\tcmp\teax,edx\t\t\t\t; if they are not the same then\n\tjne\t??set_table\t\t\t;   add them into the table\n\tadd\tesi,3\n\tadd\tedi,3\n\tinc\tcl\t\t\t\t; adjust to next palette entry\n\tjnz\t??loop_top\t\t\t; if we dont wrap to zero we have more\n\tjmp\t??set_pal\t\t\t; so now go set the palette\n??set_table:\n\tshl\teax,8\t\t\t\t; shift bgr value up register\n\tmov\tal,cl\t\t\t\t; store which palette entry num\n\tmov\t[ebx],eax\n\tadd\tebx,4\n\tmovsw\t\t\t\t\t; copy the three gun values into\n\tmovsb\t\t\t\t\t;  the shadow palette.  Use movsb\n\tinc\tcl\t\t\t\t; adjust to next palette entry\n\tjnz\t??loop_top\t\t\t; if we dont wrap to zero we have more\n\n??set_pal:\n\tmov\tesi,ebx\n\tmov\tebx,OFFSET PaletteTable\n\tsub\tesi,ebx\t\t\t\t; if ebx didn't change there\n\tjz\t??exit\t\t\t\t;   is nothing to set\n\tshr\tesi,2\t\t\t\t; find how many entrys\n\n\tmov\teax,[ebx]\n\n\tmovzx\tecx,al\t\t\t\t; we are currently on entry 0\n\tadd\tebx,4\n\n\t; Tell DAC of the color gun to start setting.\n\tmov\tedx,03C8h\n\tout\tdx,al\t\t; First color set.\n\n\t; Set the colors only during a VSync.\n\tmov\tedx,03DAh\t; CRTC register.\n\n\tpush\tebx\n\tmov\tbx,[VertBlank]\n\tand\tbl,001h\n\tshl\tbl,3\n\n??in_vbi:\n\tin\tal,dx\t\t\t\t; read CRTC status\n\tand\tal,008h\t\t\t\t; only vertical sync bit\n\txor\tal,bl\n\tje\t??in_vbi\t\t\t; in vertical sync\n\n??out_vbi:\n\tin\tal,dx\t\t\t\t; read CRTC status\n\tand\tal,008h\t\t\t\t; only vertical sync bit\n\txor\tal,bl\n\tjne\t??out_vbi\t\t\t; not in vertical sync\n\tpop\tebx\n\t; Update the DAC data register.\n\tmov\tdx,03C9h\n\n;**************** Time Critical Section Start ******************\n\tcli\n??loop:\n\tshr\teax,8\t\t; shift down the red gun value\n\tout\tdx,al\t\t; write it to the video card\n\tjmp\t$ + 2\t\t; force cache to flush, to create a time\n\tshr\teax,8\t\t; shift down the blue gun value\n\tout\tdx,al\t\t; write it to the video card\n\tjmp\t$ + 2\t\t; force cache to flush, to create a time\n\tshr\teax,8\t\t; shift down the blue gun value\n\tout\tdx,al\t\t; write the green value to video card\n\tjmp\t$ + 2\t\t; force cache to flush, to create a time\n\tinc\tecx\t\t; move edx to next palette entry\n\n\tmov\teax,[ebx]\t; get next value to set\n\tadd\tebx,4\t\t;  and post increment the palette value\n\tcmp\tal,cl\t\t; check if DAC position already correct\n\tje\t??correct_pos\n\n\tmov\tedx,03C8h\t; Tell DAC of the color gun to start setting.\n\tout\tdx,al\t\t; First color set.\n\tmov\tdx,03C9h\n\n??correct_pos:\n\tdec\tesi\n\tjnz\t??loop\n\tsti\n;***************** Time Critical Section End *******************\n??exit:\n\tret\nendif\t;NOT_FOR_WIN95\n\n\tENDP\tSet_Palette_Range\nELSE\n;***************************************************************************\n;* Set_Palette_Range -- Sets changed values in the palette.                *\n;*                                                                         *\n;* INPUT: \t\t\t\t\t\t\t\t   *\n;*\tVOID *palette - pointer to the new palette.                        *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*\tnone\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/25/1994 SKB : Created.                                             *\n;*   04/27/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\n; VOID cdecl Set_Palette_Range(VOID *palette);\n\tPROC Set_Palette_Range\tC NEAR\n\tUSES eax,ebx,ecx,edx,edi,esi\n\tARG\tpalette:DWORD\n\tLOCAL\tremain:DWORD\t; 32-bit: converted to LONG\n\n\tcld\n\n\tmov\tbx,[VertBlank]\n\tand\tbl,001h\n\tshl\tbl,3\n\n\t; Make a copy of the palette passed in.\n\tmov\tedi,OFFSET CurrentPalette\n\tmov\tesi,[palette]\n\tmov\t[remain],768\n\n\t; Search for differences between the current palette and the\n\t; new palette.  When a difference is found, output a block\n\t; of color registers and keep scanning.\n??bodyloop:\n\tmov\tecx,[remain]\n\n\trepe\tcmpsb\t\t; Search for differences.\n\tje\tshort ??exit\n\tdec\tesi\n\tdec\tedi\n\tinc\tecx\n\n\tmov\tedx,0\t\t; clear EDX\n\tmov\teax,ecx\n\tmov\tecx,3\n\tdiv\tecx\t\t; EAX = # of colors to set, EDX = Fraction.\n\tor\tedx,edx\n\tjz\tshort ??nofrac\n\tneg\tedx\n\tadd\tedx,3\t\t; Back offset skip needed.\n\tinc\teax\t\t; Fractional color rounds up to whole color to set.\n??nofrac:\n\n\t; Set CX to be the number of color guns to set.\n\tmov\tecx,eax\t\t; Colors * 3 bytes per color.\n\tadd\tecx,eax\n\tadd\tecx,eax\n\n\t; Chop this DAC dump short if necessary in order to reduce\n\t; sparkling.\n\tmov\t[remain],0\n\tcmp\tecx,86*3\t; Number of color guns to set per vert retrace\n\tjbe\tshort ??ok\n\tsub\tecx,86*3\n\tmov\t[remain],ecx\n\tmov\tecx,86*3\n??ok:\n\n\t; Adjust the palette offsets back to point to the RED color gun.\n\tsub\tesi,edx\n\tsub\tedi,edx\n\n\t; Determine the color number to start setting.\n\tneg\teax\n\tadd\teax,256\t\t; AX = Color to start setting (0..255).\n\n\t; Tell DAC of the color gun to start setting.\n\tmov\tedx,03C8h\n\tout\tdx,al\t\t; First color set.\n\n\t; Set the colors only during a VSync.\n\tmov\tedx,03DAh\t; CRTC register.\n\n??in_vbi:\n\tin\tal,dx\t\t; read CRTC status\n\tand\tal,008h\t\t; only vertical sync bit\n\txor\tal,bl\n\tje\t??in_vbi\t; in vertical sync\n\n??out_vbi:\n\tin\tal,dx\t\t; read CRTC status\n\tand\tal,008h\t\t; only vertical sync bit\n\txor\tal,bl\n\tjne\t??out_vbi\t; not in vertical sync\n\n;??wait:\n;\tin\tal,dx\n;\ttest\tal,01000b\n;\tjnz\t??wait\n\n;??retrace:\n;\tin\tal,dx\n;\ttest\tal,01000b\n;\tjz\t??retrace\n\n\t; Update the DAC data register.\n\tmov\tdx,03C9h\n\n;**************** Time Critical Section Start ******************\n\tpushf\n\tcli\n??loop:\n\tlodsb\n\tstosb\n\tout\tdx,al\n\tjmp\t$ + 2\t\t; force cache to flush, to create a time\n\t\t\t\t;  delay to give DAC time to get value\n\tloop\t??loop\n\tpopf\n;***************** Time Critical Section End *******************\n\n\tcmp\t[remain],0\n\tjnz\t??bodyloop\n\n??exit:\n\tret\n\n\tENDP\tSet_Palette_Range\nENDIF\n\n\n\n;***************************************************************************\n;* Bump_Color -- adjusts specified color in specified palette              *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*\tVOID *palette\t- palette to modify\t\t\t\t   *\n;*\tWORD changable\t- color # to change\t\t\t\t   *\n;*\tWORD target\t- color to bend toward\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/27/1994 BR : Converted to 32-bit.                                  *\n;*=========================================================================*\n; BOOL cdecl Bump_Color(VOID *palette, WORD changable, WORD target);\nPROC Bump_Color C NEAR\n\tUSES ebx,ecx,edi,esi\n\tARG\tpal:DWORD, color:WORD, desired:WORD\n\tLOCAL\tchanged:WORD\t\t; Has palette changed?\n\n\tmov\tedi,[pal]\t\t; Original palette pointer.\n\tmov\tesi,edi\n\tmov\teax,0\n\tmov\tax,[color]\n\tadd\tedi,eax\n\tadd\tedi,eax\n\tadd\tedi,eax\t\t\t; Offset to changable color.\n\tmov\tax,[desired]\n\tadd\tesi,eax\n\tadd\tesi,eax\n\tadd\tesi,eax\t\t\t; Offset to target color.\n\n\tmov\t[changed],FALSE\t\t; Presume no change.\n\tmov\tecx,3\t\t\t; Three color guns.\n\n\t; Check the color gun.\n??colorloop:\n\tmov\tal,[BYTE PTR esi]\n\tsub\tal,[BYTE PTR edi]\t; Carry flag is set if subtraction needed.\n\tjz\tshort ??gotit\n\tmov\t[changed],TRUE\n\tinc\t[BYTE PTR edi]\t\t; Presume addition.\n\tjnc\tshort ??gotit\t\t; oops, subtraction needed so dec twice.\n\tdec\t[BYTE PTR edi]\n\tdec\t[BYTE PTR edi]\n??gotit:\n\tinc\tedi\n\tinc\tesi\n\tloop\t??colorloop\n\n\tmov\tax,[changed]\n\tret\n\n\tENDP\tBump_Color\n\n\tEND\n\n;*************************** End of pal.asm ********************************\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/PALETTE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : PALETTE.C\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : BILL STOKES\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Start Date : 6/20/91\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : August 2, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Note: This module contains dependencies upon the video system,\t\t\t\t*\n * specifically Get_Video_Mode().\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Set_Palette -- sets the current palette\t\t\t\t\t\t\t\t\t\t\t*\n *   Set_Palette_Color -- Set a color number in a palette to the data.     *\n *\t  Fade_Palette_To -- Fades the current palette into another\t\t\t\t\t*\n *   Determine_Bump_Rate -- determines desired bump rate for fading        *\n *   Bump_Palette -- increments the palette one step, for fading           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n/*\n********************************* Includes **********************************\n*/\n#include <mem.h>\n#include \"wwstd.h\"\n#include \"palette.h\"\n#include \"timer.h\"\n\n/*\n********************************* Constants *********************************\n*/\n\n/*\n********************************** Globals **********************************\n*/\nextern \"C\" extern unsigned char  CurrentPalette[];\t\t/* in pal.asm */\n\n/*\n******************************** Prototypes *********************************\n*/\n\nPRIVATE void __cdecl Determine_Bump_Rate(void *palette, int delay, short *ticks, short *rate);\nPRIVATE BOOL __cdecl Bump_Palette(void *palette1, unsigned int step);\n\n/*\n******************************** Code *********************************\n*/\n\n/***************************************************************************\n * Set_Palette -- sets the current palette\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tvoid *palette\t\t- palette to set\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/25/1994 SKB : Created.                                             *\n *   04/27/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nvoid __cdecl Set_Palette(void *palette)\n{\n\n\t#if(IBM)\n\t\tSet_Palette_Range(palette);\n\t#else\n\t\tCopy_Palette(palette,CurrentPalette);\n   \tLoadRGB4(&Main_Screen->ViewPort,palette,32L);\n\t   LoadRGB4(AltVPort,palette,32L);\n\t#endif\n\n}\t/* end of Set_Palette */\n\n\n/***************************************************************************\n * Set_Palette_Color -- Set a color number in a palette to the data.       *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tvoid *palette\t- palette to set color in\t\t\t\t\t\t\t\t\t\t*\n *\t\tint color\t\t- which color index to set\t\t\t\t\t\t\t\t\t\t*\n *\t\tvoid *data\t\t- RGB data for color\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/25/1994 SKB : Created.                                             *\n *   04/27/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nvoid __cdecl Set_Palette_Color(void *palette, int color, void *data)\n{\n\t/*\n\t---------------------- Return if 'palette' is NULL -----------------------\n\t*/\n\tif (!palette) return;\n\n\t/*\n\t------------------- Change the color & set the palette -------------------\n\t*/\n\t#if(IBM)\n\t\tmemcpy(&((unsigned char *)palette)[color * RGB_BYTES], data, RGB_BYTES);\n\t\tSet_Palette_Range(palette);\n\t#else\n\t\tpalette[color] = *(unsigned short*)data;\n\t\tSet_Palette(palette);\n\t#endif\n\n}\t/* end of Set_Palette */\n\n\n/***************************************************************************\n *\tFade_Palette_To -- Fades the current palette into another\t\t\t\t\t*\n *                                                                         *\n * This will allow the palette to fade from current palette into the \t\t*\n * palette that was passed in.  This can be used to fade in and fade out.\t*\n *                                                                         *\n * INPUT:      \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *    char  *palette1 - this is the palette to fade to.           \t\t\t*\n *\t\tunsigned int delay\t\t -\tfade with this timer count down\t\t\t\t\t\t\t*\n *\t\tvoid *callback  - user-defined callback function\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/20/1991  BS : Created.                                             *\n *=========================================================================*/\nvoid Fade_Palette_To(void *palette1, unsigned int delay, void (*callback)() )\n{\n\tBOOL\tchanged;\t// Flag that palette has changed this tick.\n\tshort\tjump;\t\t// Gun values to jump per palette set.\n\tunsigned long\ttimer;\t\t// Tick count timer used for timing.\n\tshort\tticksper;\t// The ticks (fixed point) per bit jump.\n\tint\ttickaccum;\n\n\n\textern void (*cb_ptr)(void);\t// callback function pointer\n\n//\t(void *)cb_ptr = callback;\n\tcb_ptr = callback;\n\n\t/*\n\t---------------------- Return if 'palette1' is NULL ----------------------\n\t*/\n\tif (!palette1)\n\t\treturn;\n\n\t/*\n\t--------------------------- Get the bump rate ----------------------------\n\t*/\n\tDetermine_Bump_Rate(palette1, delay, &ticksper, &jump);\n\n\ttickaccum = 0;\t\t\t\t\t\t\t// init accumulated elapsed time\n\ttimer = TickCount.Time(); \t\t\t\t// timer = current time\n\tdo {\n\t\tchanged = FALSE;\n\n\t\ttickaccum += ticksper;\t\t\t// tickaccum = time of next change * 256\n\t\ttimer += (tickaccum >> 8);\t\t// timer = time of next change (rounded)\n\t\ttickaccum &= 0x0FF;\t\t\t\t// shave off high byte, keep roundoff bits\n\n\t\tchanged = Bump_Palette(palette1, jump);\t// increment palette\n\n\t\t/*\n\t\t.................. Wait for time increment to elapse ..................\n\t\t*/\n\t\tif (changed) {\n\t\t\twhile (TickCount.Time() < timer) {\n\t\t\t\t/*\n\t\t\t\t................. Update callback while waiting .................\n\t\t\t\t*/\n\t\t\t\tif (callback) {\n#if LIB_EXTERNS_RESOLVED\n\t\t\t\t\tSound_Callback();\t\t// should be removed!\n#endif\n\t\t\t\t\t(*cb_ptr)();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n#if LIB_EXTERNS_RESOLVED\n\t\tSound_Callback();\t\t// should be removed!\n#endif\n\t\tif (callback) {\n\t\t\t(*cb_ptr)();\n\t\t}\n\t} while (changed);\n\n}\t/* end of Fade_Palette_To */\n\n\n/***************************************************************************\n * Determine_Bump_Rate -- determines desired bump rate for fading          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tunsigned char *palette\t- palette to fade to\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tint delay\t\t- desired time delay in 60ths of a second\t\t\t\t\t*\n *\t\tshort *ticks\t\t- output: loop ticks per color jump\t\t\t\t\t\t\t*\n *\t\tshort *rate\t\t- output: color gun increment rate\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/27/1994 BR : Converted to 32-bit                                   *\n *   08/02/1994 SKB : Made private                                         *\n *=========================================================================*/\nPRIVATE void __cdecl Determine_Bump_Rate(void *palette, int delay, short *ticks,\n\tshort *rate)\n{\n\tint gun1;\t\t// Palette 1 gun value.\n\tint gun2;\t\t// Palette 2 gun value.\n\tint diff;\t\t// Maximum color gun difference.\n\tint tp;\t\t\t// Temporary tick accumulator.\n\tint index;\t\t// Color gun working index.\n\tlong t;\t\t\t// Working tick intermediate value.\n\tint adiff;\t\t// Absolute difference between guns.\n\n\t/*\n\t------------------------ Find max gun difference -------------------------\n\t*/\n\tdiff = 0;\n\tfor (index = 0; index < PALETTE_BYTES; index++) {\n\t\tgun1 = ((unsigned char *)palette)[index];\n\t\tgun2 = CurrentPalette[index];\n\t\tadiff = ABS(gun1-gun2);\n\t\tdiff = MAX(diff, adiff);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tticks = (total time delay ) / (max gun diff)\n\tThe value is computed based on (delay * 256), for fixed-point math;\n\tthe lower bits represent the leftover from the division;  'ticks' is\n\treturned still shifted, so the low bits can be used to accumulate the\n\ttime more accurately; the caller must shift the accumulated value down\n\t8 bits to determine the actual elapsed time!\n\t------------------------------------------------------------------------*/\n\tt = ((long)delay) << 8;\n\tif (diff) {\n\t\tt /= diff;\n\t\tt = MIN((long)t, (long)0x7FFF);\n\t}\n\t*ticks = (short)t;\n\n\t/*------------------------------------------------------------------------\n\tAdjust the color gun rate value if the time to fade is faster than can\n\treasonably be performed given the palette change, ie if (ticks>>8)==0,\n\tand thus less than 1/60 of a second\n\t------------------------------------------------------------------------*/\n\ttp = *ticks;\n\t*rate = 1;\n\twhile (*rate <= diff && *ticks < 256) {\n\t\t*ticks += tp;\n\t\t*rate += 1;\n\t}\n\n}\t/* end of Determine_Bump_Rate */\n\n\n/***************************************************************************\n * Bump_Palette -- increments the palette one step, for fading             *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tpalette1\t\t- palette to fade towards\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tstep\t\t\t- max step amount, determined by Determine_Bump_Rate\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tFALSE = no change, TRUE = changed\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/27/1994 BR : Created.                                              *\n *   08/02/1994 SKB : Made private                                         *\n *=========================================================================*/\n#if(IBM)\nPRIVATE BOOL __cdecl Bump_Palette(void *palette1, unsigned int step)\n{\n\tBOOL\tchanged=FALSE;\t\t\t\t// Flag that palette has changed this tick.\n\tint\tindex;\t\t\t\t\t\t// Index to DAC register gun.\n\tint\tgun1,gun2;\t\t\t\t\t// Palette 1 gun value.\n\tunsigned char\tpalette[PALETTE_BYTES];\t// copy of current palette\n\n\t/*\n\t---------------------- Return if 'palette1' is NULL ----------------------\n\t*/\n\tif (!palette1)\n\t\treturn (FALSE);\n\n\n\t/*\n\t------------------------ Copy the current palette ------------------------\n\t*/\n\tmemcpy(palette, CurrentPalette, 768);\n\n\t/*\n\t----------------------- Loop through palette bytes -----------------------\n\t*/\n\tfor (index = 0; index < PALETTE_BYTES; index++) {\n\t\tgun1 = ((unsigned char *)palette1)[index];\n\t\tgun2 = palette[index];\n\n\t\t/*\n\t\t............. If the colors match, go on to the next one ..............\n\t\t*/\n\t\tif (gun1 == gun2) continue;\n\n\t\tchanged = TRUE;\n\n\t\t/*\n\t\t.................. Increment current palette's color ..................\n\t\t*/\n\t\tif (gun2 < gun1) {\n\t\t\tgun2 += step;\n\t\t\tgun2 = MIN(gun2, gun1);\t\t// make sure we didn't overshoot it\n\t\t}\n\t\t/*\n\t\t.................. Decrement current palette's color ..................\n\t\t*/\n\t\telse {\n\t\t\tgun2 -= step;\n\t\t\tgun2 = MAX(gun2, gun1);\t\t// make sure we didn't overshoot it\n\t\t}\n\n\t\tpalette[index] = (unsigned char)gun2;\n\t}\n\n\t/*\n\t----------------- Set current palette to the new palette -----------------\n\t*/\n\tif (changed) {\n\t\tSet_Palette(&palette[0]);\n\t}\n\n\treturn (changed);\n\n}\t/* end of Bump_Palette */\n\n#else\n\n\t/* This is already implemented in asm on the Amiga */\n\n#endif\n\nvoid (*cb_ptr)(void);\t// callback function pointer\n\n/**************************** End of palette.cpp ***************************/\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/PLAYCD.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nLOCALS ??\n\n\nDPMI_INTR equ\t031h\n\nGLOBAL \tDPMI_real_alloc   : near\nGLOBAL  DPMI_real_free    : near\nGLOBAL  DPMI_real_intr    : near\nGLOBAL  DPMI_real_call    : near\n\n\nSTRUC SEGSEL\n\t  segmen  dw ?\n \t  select  dw ?\nENDS\n\nSTRUC REGS \n\t_eax   dd ?\n\t_ebx   dd ?\n\t_ecx   dd ?\n\t_edx   dd ?\n\t_esi   dd ?\n\t_edi   dd ?\n\t_cflag dd ?\nENDS\n\nSTRUC SREGS \n\t_es  dw ?\n\t_cs  dw ?\n\t_ss  dw ?\n\t_ds  dw ?\n        _fs  dw ?\n\t_gs  dw ?\nENDS\n\nSTRUC DPMI_REGS\n       _edi  dd ?\n       _esi  dd ?\t\n       _ebp  dd ?\t\n       \t     dd ?\n       _ebx  dd ?\t\n       _edx  dd ?\t\n       _ecx  dd ?\t\n       _eax  dd ?\t\n       Flags dw ?\n       _es   dw ?\n       _ds   dw ?\n       _fs   dw ?\n       _gs   dw ?\n       _ip   dw ?\n       _cs   dw ?\n       _sp   dw ?\n       _ss   dw ?\n       \t     dd ?\n\t     dd\t?\n   size_ref  db\t?\t\nENDS\n    \n    \nCODESEG\n\n; int  DPMI_real_alloc ( UINT , SEGREG * , USHORT * ) ;\n\nPROC DPMI_real_alloc C near \n\tUSES\tebx , edx\n\tARG\tparagra        : DWORD\n\tARG\tblk_segptr    : DWORD\n\tARG\tlargest_blkptr : DWORD\n\n\tmov\teax, 0100h\n\tmov\tebx, [paragra]\n\tint\tDPMI_INTR\n\n\tjnc\t??dpmi_succed\n\tmov\tebx, [largest_blkptr]\n\tmov\t[ word ptr ebx ] , bx\n\tmovzx\teax , al\n \tret\n\n??dpmi_succed:\n\tmov\tebx, [blk_segptr]\n\tmov\t[(type SEGSEL ptr ebx). segmen ] , ax\n\tmov\t[(type SEGSEL ptr ebx). select ] , dx\n\txor\teax , eax\n\tret\n\t\t\nENDP DPMI_real_alloc\t\n\n\n;**************************************************************************\n; int  DPMI_real_free ( UINT ) ;\n\nPROC DPMI_real_free C near \n\tUSES\teax , edx\n\tARG\tblk_selec  : DWORD\n\n\tmov\teax, 0101h\n\tmov\tedx, [blk_selec]\n\tshr\tedx , 16\n\tint\tDPMI_INTR\n \tret\nENDP DPMI_real_free\t\n\n\nPROC DPMI_real_intr C near \n\tUSES\teax , ebx , ecx , edx , edi , esi \n\tARG\tvector  : dword\n\tARG     regs_ptr: dword\n\tARG     sreg_ptr: dword\n\n\tLOCAL\tregblk : DPMI_REGS\n\n\tlea\tedi , [ regblk ]\n\txor\teax , eax\n\tlea\tecx , [ regblk . size_ref ]\n\tsub\tecx , edi\n\tshr\tecx , 2\n\trep\tstosd\n\n  \tmov\tebx , [ regs_ptr ]\n\tmov\teax , [ (type REGS ptr ebx) . _eax ] \n\tmov\t[ regblk . _eax ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _ebx ] \n\tmov\t[ regblk . _ebx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _ecx ] \n\tmov\t[ regblk . _ecx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _edx ] \n\tmov\t[ regblk . _edx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _esi ] \n\tmov\t[ regblk . _esi ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _edi ] \n\tmov\t[ regblk . _edi ] , eax\n\n\n  \tmov\tebx , [ sreg_ptr ]\n\tmov\tax , [ (type SREGS ptr ebx) . _es ] \n\tmov\t[ regblk . _es ] , ax\n\n\tmov\tax , [ (type SREGS ptr ebx) . _ds ] \n\tmov\t[ regblk . _ds ] , ax\n\n\tmov\teax , 0300h\n\tmov\tebx , [ vector ]\n\txor     bh , bh\n\txor \tecx , ecx\n\tlea\tedi , [ regblk ]\n\n\tint\tDPMI_INTR\n\n  \tmov\tebx , [ regs_ptr ]\n\tmov\teax , [ regblk . _eax ] \n\tmov\t[ (type REGS ptr ebx) . _eax ] , eax\n\n\tmov\teax , [ regblk . _ebx ] \n\tmov\t[ (type REGS ptr ebx) . _ebx ] , eax\n\n\tmov\teax , [ regblk . _ecx ] \n\tmov\t[ (type REGS ptr ebx) . _ecx ] , eax\n\n\tmov\teax , [ regblk . _edx ] \n\tmov\t[ (type REGS ptr ebx) . _edx ] , eax\n\n\tmov\teax , [ regblk . _esi ] \n\tmov\t[ (type REGS ptr ebx) . _esi ] , eax\n\n\tmov\teax , [ regblk . _edi ] \n\tmov\t[ (type REGS ptr ebx) . _edi ] , eax\n\n\n  \tmov\tebx , [ sreg_ptr ]\n\tmov\tax , [ regblk . _es ] \n\tmov\t[ (type SREGS ptr ebx) . _es ] , ax\n\n\tmov\tax , [ regblk . _ds ] \n\tmov\t[ (type SREGS ptr ebx) . _ds ] , ax\n\n \tret\nENDP DPMI_real_intr\t\n\n\nPROC DPMI_real_call C near \n\tUSES\teax , ebx , ecx , edx , edi , esi \n\tARG\tvector  : dword\n\tARG     regs_ptr: dword\n\tARG     sreg_ptr: dword\n\n\tLOCAL\tregblk : DPMI_REGS\n\n\n\tlea\tedi , [ regblk ]\n\txor\tal , al\n\tlea\tecx , [ regblk . size_ref ]\n\tsub\tecx , edi\n\trep\tmovsb\n\n\n  \tmov\tebx , [ regs_ptr ]\n\tmov\teax , [ (type REGS ptr ebx) . _eax ] \n\tmov\t[ regblk . _eax ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _ebx ] \n\tmov\t[ regblk . _ebx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _ecx ] \n\tmov\t[ regblk . _ecx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _edx ] \n\tmov\t[ regblk . _edx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _esi ] \n\tmov\t[ regblk . _esi ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _edi ] \n\tmov\t[ regblk . _edi ] , eax\n\n\n  \tmov\tebx , [ sreg_ptr ]\n\tmov\tax , [ (type SREGS ptr ebx) . _es ] \n\tmov\t[ regblk . _es ] , ax\n\n\tmov\tax , [ (type SREGS ptr ebx) . _ds ] \n\tmov\t[ regblk . _ds ] , ax\n\n;\tmov\teax , 0300h\n;\tmov\tebx , [ vector ]\n;\txor     bh , bh\n;\txor \tecx , ecx\n;\tlea\tedi , [ regblk ]\n\n;\tint\tDPMI_INTR\n\n  \tmov\tebx , [ regs_ptr ]\n\tmov\teax , [ regblk . _eax ] \n\tmov\t[ (type REGS ptr ebx) . _eax ] , eax\n\tmov\teax , [ regblk . _ebx ] \n\tmov\t[ (type REGS ptr ebx) . _ebx ] , eax\n\tmov\teax , [ regblk . _ecx ] \n\tmov\t[ (type REGS ptr ebx) . _ecx ] , eax\n\tmov\teax , [ regblk . _edx ] \n\tmov\t[ (type REGS ptr ebx) . _edx ] , eax\n\n\tmov\teax , [ regblk . _esi ] \n\tmov\t[ (type REGS ptr ebx) . _esi ] , eax\n\tmov\teax , [ regblk . _edi ] \n\tmov\t[ (type REGS ptr ebx) . _edi ] , eax\n\n\n  \tmov\tebx , [ sreg_ptr ]\n\tmov\tax , [ regblk . _es ] \n\tmov\t[ (type SREGS ptr ebx) . _es ] , ax\n\n\tmov\tax , [ regblk . _ds ] \n\tmov\t[ (type SREGS ptr ebx) . _ds ] , ax\n\n \tret\nENDP DPMI_real_call\n\nEND\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/PRIOINIT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory system.                           *\n *                                                                         *\n *                    File Name : PRIOINIT.CPP                             *\n *                                                                         *\n *                   Programmer : Ian M. Leslie                            *\n *                                                                         *\n *                   Start Date : August 9, 1993                           *\n *                                                                         *\n *                  Last Update : August 9, 1994   [IML]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   INIT_PRIORITY_SYSTEM -- \tSets the buffer addresses for the priority   *\n *   \t\t\t\t\t\t\t\t\tsystem.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"shape.h\"\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * Init_Priority_System -- set the buffer addresses for the priority\t\t   *\n *   \t\t\t\t\t\t\t\tsystem.                       \t\t\t\t\t\t*\n *                                                                         *\n * INPUT:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tmask - pointer\tto priority buffer class\t\t\t\t\t\t\t\t\t\t*\n *\t\tback - pointer to background buffer class\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   08/09/1994 IML : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n *=========================================================================*/\n\nVOID cdecl Init_Priority_System (GraphicBufferClass *mask,\n\t\t\t\t\t\t\t\t\t\t\tGraphicBufferClass *back)\n{\n MaskPage = mask->Get_Buffer();\n BackGroundPage = back->Get_Buffer();\n}\n\n\n/************************** end of prioinit.cpp ****************************/\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/PROFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Library profiler                                             *\n *                                                                                             *\n *                    File Name : PROFILE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 11/17/95                                                     *\n *                                                                                             *\n *                  Last Update : November 20th 1995 [ST]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *  The profiler works by using the function prologue and epilogue hooks available in Watcom                                                                                           *\n *  to register the current functions address in a global variable and then sampling the                                                                                           *\n *  contents of the variable using a windows timer which runs at up to 1000 samples per second.                                                                       *\n *                                                                                             *\n *  Compile the code to be sampled with the -ep and -ee flags to enable the prologue (__PRO)                                                                                           *\n *  and epilogue (__EPI) calls to be generated.                                                                                           *\n *  At the beginning of the section to be profiled (just before main loop normally) call the                                                                                           *\n *  Start_Profiler function to start sampling. At the end of the section, call Stop_Profiler                                                                                           *\n *  which will stop the timer and write the profile data to disk in the PROFILE.BIN file.                                                                                           *\n *  Use                                                                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *  Start_Profiler -- initialises the profiler data and starts gathering data                  *\n *  Stop_Profiler -- stops the timer and writes the profile data to disk                       *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#define WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#include <windows.h>\n#include <windowsx.h>\n\n#include <wwstd.h>\n#include <rawfile.h>\n#include <file.h>\n#include \"profile.h\"\n\nextern \"C\"{\nunsigned\tProfileList\t[PROFILE_RATE*60*MAX_PROFILE_TIME];\nunsigned\tProfilePtr;\n}\n\nextern \"C\" void Profiler_Callback ( UINT, UINT , DWORD, DWORD, DWORD );\n\nunsigned\tProfilerEvent;\n\nvoid Start_Profiler (void)\n{\n\tmemset (&ProfileList[0],-1,PROFILE_RATE*60*MAX_PROFILE_TIME*4);\n\tCopy_CHK();\n\tProfilerEvent = timeSetEvent (1000/PROFILE_RATE , 1 , (void CALLBACK (UINT,UINT,DWORD,DWORD,DWORD))Profiler_Callback , 0 , TIME_PERIODIC);\n}\n\nvoid Stop_Profiler (void)\n{\n\tif (ProfilerEvent){\n\t\ttimeKillEvent(ProfilerEvent);\n\t\tProfilerEvent=NULL;\n\n\t\tint handle = Open_File ( \"profile.bin\" , WRITE );\n\t\tif (handle != WW_ERROR){\n\t\t\tWrite_File (handle , &ProfileList[0] , ProfilePtr*4);\n\t\t\tClose_File (handle);\n\t\t}\n\t}\n}\n\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/PUTPIX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : GraphicViewPortClass\t\t\t   *\n;*                                                                         *\n;*                    File Name : PUTPIXEL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : June 8, 1994   [PWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVPC::Put_Pixel -- Puts a pixel on a virtual viewport                 *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n;***************************************************************************\n;* VVPC::PUT_PIXEL -- Puts a pixel on a virtual viewport                   *\n;*                                                                         *\n;* INPUT:\tWORD the x position for the pixel relative to the upper    *\n;*\t\t\tleft corner of the viewport\t\t\t   *\n;*\t\tWORD the y pos for the pixel relative to the upper left\t   *\n;*\t\t\tcorner of the viewport\t\t\t\t   *\n;*\t\tUBYTE the color of the pixel to write\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNING:\tIf pixel is to be placed outside of the viewport then\t   *\n;*\t\tthis routine will abort.\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/08/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_Put_Pixel C near\n\tUSES\teax,ebx,ecx,edx,edi\n\n\tARG    \tthis_object:DWORD\t\t\t\t; this is a member function\n\tARG\tx_pixel:DWORD\t\t\t\t; x position of pixel to set\n\tARG\ty_pixel:DWORD\t\t\t\t; y position of pixel to set\n\tARG    \tcolor:BYTE\t\t\t\t; what color should we clear to\n\n\t;*===================================================================\n\t; Get the viewport information and put bytes per row in ecx\n\t;*===================================================================\n\tmov\tebx,[this_object]\t\t\t\t; get a pointer to viewport\n\txor\teax,eax\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get the correct offset\n\tmov\tecx,[(GraphicViewPort ebx).GVPHeight]\t; edx = height of viewport\n\tmov\tedx,[(GraphicViewPort ebx).GVPWidth]\t; ecx = width of viewport\n\n\t;*===================================================================\n\t; Verify that the X pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[x_pixel]\t\t\t\t; find the x position\n\tcmp\teax,edx\t\t\t\t\t;   is it out of bounds\n\tjae\tshort ??exit\t\t\t\t; if so then get out\n\tadd\tedi,eax\t\t\t\t\t; otherwise add in offset\n\n\t;*===================================================================\n\t; Verify that the Y pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[y_pixel]\t\t\t\t; get the y position\n\tcmp\teax,ecx\t\t\t\t\t;  is it out of bounds\n\tjae\t??exit\t\t\t\t\t; if so then get out\n\tadd\tedx,[(GraphicViewPort ebx).GVPXAdd]\t; otherwise find bytes per row\n\tadd\tedx,[(GraphicViewPort ebx).GVPPitch]\t; add in direct draw pitch\n\tmul\tedx\t\t\t\t\t; offset = bytes per row * y\n\tadd\tedi,eax\t\t\t\t\t; add it into the offset\n\n\t;*===================================================================\n\t; Write the pixel to the screen\n\t;*===================================================================\n\tmov\tal,[color]\t\t\t\t; read in color value\n\tmov\t[edi],al\t\t\t\t; write it to the screen\n??exit:\n\tret\n\tENDP\tBuffer_Put_Pixel\n\nEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/RANDOM.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library routine                          *\n;*                                                                         *\n;*                    File Name : RANDOM.ASM                               *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : 20 August, 1990   [CY]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n;*  UBYTE Random(VOID);                                                    *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGlobal C Random\t\t:NEAR\nGlobal C Get_Random_Mask\t:NEAR\nGlobal C RandNumb\t\t:DWORD\n\n\tDATASEG\n\nRandNumb\tDD\t12349876H\n\n\tCODESEG\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; UBYTE Random(VOID);\n; int Get_Random_Mask(int maxval);\n;\n; ----------------------------------------------------------------\n\n;-----------------------------------------------------------------\n; RANDOM\n;\n; UBYTE Random(VOID);\n;\n;*\n\n\tPROC\tRandom C near\n\tUSES\tesi\n\n\tlea\tesi, [RandNumb]\t\t; get offset in segment of RandNumb\n\txor\teax,eax\n\tmov\tal,[esi]\n\tshr\tal,1\t\t\t; shift right 1 bit (bit0 in carry)\n\tshr\tal,1\n\trcl\t[BYTE PTR esi+2],1\t; rcl byte 3 of RandNumb\n\trcl\t[BYTE PTR esi+1],1 \t; rcl byte 2 of RandNumb\n\tcmc\t\t\t\t; complement carry\n\tsbb\tal,[esi]\t\t; sbb byte 1 of RandNumb\n\tshr\tal,1\t\t\t; sets carry\n\trcr\t[BYTE PTR esi],1 \t; rcr byte 1 of RandNumb\n\tmov\tal,[esi]\t\t; reload byte 1 of RandNumb\n\txor\tal,[esi+1]\t\t; xor with byte 2 of RandNumb\n\n\tret\n\n\tENDP\tRandom\n\n\n;-----------------------------------------------------------------\n; GET_RANDOM_MASK - returns an AND value that is large enough that it\n; encloses the 'maxval' parameter.\n;\n; int Get_Random_Mask(int maxval);\n;\n;*\n\n\tPROC\tGet_Random_Mask C near\n\tUSES\tecx\n\tARG\tmaxval:DWORD\n\n; This function takes as a parameter a maximum value, for example, 61.  It\n; then tries to create an AND mask that is big enough to enclose that number.\n; For our example case, that AND mask would be 0x3F.  It does this by scanning\n; for the highest bit in the number, then making an all-1's mask from that\n; bit position down to bit 0.\n\tbsr\tecx,[maxval]\t\t; put bit position of highest bit in ecx\n\tmov\teax,1\t\t\t; set one bit on in eax\n\tjz\t??invalid\t\t; if BSR shows maxval==0, return eax=1\n\tinc\tecx\t\t\t; get one bit higher than count showed\n\tshl\teax,cl\t\t\t; move our EAX bit into position\n\tdec\teax\t\t\t; dec it to create the mask.\n??invalid:\n\tret\n\tENDP\tGet_Random_Mask\n;----------------------------------------------------------------------------\n\n\tEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/RAWFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\rawfile.cpv   2.17   06 Sep 1995 16:38:30   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***             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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Library                                             *\n *                                                                                             *\n *                    File Name : RAWFILE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 18, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RawFileClass::Close -- Perform a closure of the file.                                     *\n *   RawFileClass::Create -- Creates an empty file.                                            *\n *   RawFileClass::Delete -- Deletes the file object from the disk.                            *\n *   RawFileClass::Error -- Handles displaying a file error message.                           *\n *   RawFileClass::Is_Available -- Checks to see if the specified file is available to open.   *\n *   RawFileClass::Open -- Assigns name and opens file in one operation.                       *\n *   RawFileClass::Open -- Opens the file object with the rights specified.                    *\n *   RawFileClass::RawFileClass -- Simple constructor for a file object.                       *\n *   RawFileClass::Read -- Reads the specified number of bytes into a memory buffer.           *\n *   RawFileClass::Seek -- Reposition the file pointer as indicated.                           *\n *   RawFileClass::Set_Name -- Manually sets the name for a file object.                       *\n *   RawFileClass::Size -- Determines size of file (in bytes).                                 *\n *   RawFileClass::Write -- Writes the specified data to the buffer specified.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n #define\ttrue\t1\n #define\tfalse\t0\n\n#define\tWIN32\n#define\t_WIN32\n#include \t<windows.h>\n\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<string.h>\n#include\t<direct.h>\n#include\t<fcntl.h>\n#include\t<io.h>\n#include\t<dos.h>\n#include\t<share.h>\n#include\t<sys\\stat.h>\n#include\t<wwstd.h>\n\n//#include \"wwlib32.h\"\n//#include\t\"compat.h\"\n#include\t\"rawfile.h\"\n\n\n/***********************************************************************************************\n * RawFileClass::Error -- Handles displaying a file error message.                             *\n *                                                                                             *\n *    Display an error message as indicated. If it is allowed to retry, then pressing a key    *\n *    will return from this function. Otherwise, it will exit the program with \"exit()\".       *\n *                                                                                             *\n * INPUT:   error    -- The error number (same as the DOSERR.H error numbers).                 *\n *                                                                                             *\n *          canretry -- Can this routine exit normally so that retrying can occur? If this is  *\n *                      false, then the program WILL exit in this routine.                     *\n *                                                                                             *\n *          filename -- Optional filename to report with this error. If no filename is         *\n *                      supplied, then no filename is listed in the error message.             *\n *                                                                                             *\n * OUTPUT:  none, but this routine might not return at all if the \"canretry\" parameter is      *\n *          false or the player pressed ESC.                                                   *\n *                                                                                             *\n * WARNINGS:   This routine may not return at all. It handles being in text mode as well as    *\n *             if in a graphic mode.                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\n#pragma argsused\n//void RawFileClass::Error(int error, int canretry, char const * filename)\nvoid RawFileClass::Error(int error, int , char const *)\n{\n\tchar buffer[256];\n\n\twsprintf(buffer, \"File Error #%d\", error);\n///////\tMessageBox(NULL, buffer, \"Error\", MB_OK);\n\n#ifdef NEVER\n\tchar\tmessage[256];\t\t\t\t// Staging buffer for error message string.\n\n\t/*\n\t**\tBuild the complete text of the error message. This text is used in either the graphic\n\t**\tmode or the text mode version.\n\t*/\n#ifdef GERMAN\n\tstrcpy(message, \"DATEIFEHLER\");\n#else\n#ifdef FRENCH\n\tstrcpy(message, \"ERREUR DE FICHIER\");\n#else\n\tstrcpy(message, \"FILE ERROR\");\n#endif\n#endif\n\tif (filename) {\n\t\tstrcat(message, \"(\");\n\t\tstrcat(message, filename);\n\t\tstrcat(message, \")\");\n\t}\n\tstrcat(message, \": \");\n//BG: Borland only\tstrcat(message, _sys_errlist[error]);\n\tstrcat(message, strerror(error) );\n\tstrcat(message, \". \");\n\n\t/*\n\t**\tIf it can't properly handle displaying the error message in the\n\t**\tcurrent graphic mode, then this forces the error to become non\n\t**\trecoverable. Go into text mode and proceed.\n\t*/\n\tif (!FontPtr && GraphicMode != TXT_MODE) {\n\t\tSet_Video_Mode(RESET_MODE);\n\t\tcanretry = false;\n\t\tGraphicMode = TXT_MODE;\n\t}\n\n\t/*\n\t**\tAdd the text explaining the valid actions to take.\n\t*/\n\tif (canretry) {\n\t\tif (GraphicMode == TXT_MODE) strcat(message, \"\\n\");\n#ifdef GERMAN\n\t\tstrcat(message, \" Beliebige Taste drcken fr erneuten Versuch.\");\n\t\tif (GraphicMode == TXT_MODE) strcat(message, \"\\n\");\n\t\tstrcat(message, \" <ESC> drcken, um das Programm zu verlassen.\");\n#else\n#ifdef FRENCH\n\t\tstrcat(message, \" Appuyez sur une touche pour recommencer.\");\n\t\tif (GraphicMode == TXT_MODE) strcat(message, \"\\n\");\n\t\tstrcat(message, \" Appuyez sur Echap pour quitter le programme.\");\n#else\n\t\tstrcat(message, \" Press any key to retry.\");\n\t\tif (GraphicMode == TXT_MODE) strcat(message, \"\\n\");\n\t\tstrcat(message, \" Press <ESC> to exit program.\");\n#endif\n#endif\n\t\tif (GraphicMode == TXT_MODE) strcat(message, \"\\n\");\n\t} else {\n\t\tif (GraphicMode == TXT_MODE) strcat(message, \"\\n\");\n#ifdef GERMAN\n\t\tstrcat(message, \" Beliebige Taste drcken, um das Programm zu verlassen.\");\n#else\n#ifdef FRENCH\n\t\tstrcat(message, \" Appuyez sur une touche pour quitter le programme.\");\n#else\n\t\tstrcat(message, \" Press any key to exit program.\");\n#endif\n#endif\n\t\tif (GraphicMode == TXT_MODE) strcat(message, \"\\n\");\n\t}\n\n\t/*\n\t**\tIn text mode, the error handler is very simple. It just prints the error message\n\t**\tto the screen and waits for a response.\n\t*/\n\tif (GraphicMode == TXT_MODE) {\n\t\tint\tinput;\n\n\t\t/*\n\t\t**\tDisplay the error message and wait for a response.\n\t\t*/\n\t\tprintf(message);\n\t\tKeyboard::Clear();\n\t\tinput = Keyboard::Get();\n\n\t\t/*\n\t\t**\tCheck for input. If the ESC key was pressed or if retrying is not allowed,\n\t\t**\tthen exit the program. Otherwise, return from this routine for a retry\n\t\t**\tattempt.\n\t\t*/\n\t\tif (input == KN_ESC || !canretry) {\n\t\t\tProg_End();\n\t\t\texit(EXIT_FAILURE);\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tThe graphic mode version of the error handler will display a simple message\n\t\t**\tbox on the screen. If the palette is black at this point, then the error will\n\t\t**\tbe invisible. For more thorough and pleasing results, you should replace this\n\t\t**\tvirtual function with one of your own, that is more aware of the environment\n\t\t**\tin which is exists.\n\t\t*/\n\t\tvoid\t\t\t*background;\t\t// Pointer to background saving buffer.\n\t\tGraphicBufferClass * \toldpage;\t\t\t\t// Copy of old logic page.\n\t\tint\t\t\toldwindow;\t\t\t// Copy of old window number.\n\t\tvoid const\t*oldfont;\t\t\t// Copy of old font pointer.\n\t\tint\t\t\toldspacing;\t\t\t// Old font X spacing.\n\n\t\t/*\n\t\t**\tSetup display in preparation for printing the error message.\n\t\t*/\n\t\toldpage = Set_Logic_Page(SeenBuff);\n\t\toldwindow = Change_Window(ErrorWindow);\n\t\toldfont = Set_Font(FontPtr);\n\t\toldspacing = FontXSpacing; FontXSpacing = 0;\n\t\tHide_Mouse();\n\n\t\t/*\n\t\t**\tTry to allocate a storage buffer for the background to the\n\t\t**\terror window.\n\t\t*/\n\t\tbackground = new char [Size_Of_Region(WinW<<3, WinH)];\n\n\t\t/*\n\t\t**\tIf there is memory for the background storage, then save the\n\t\t**\tscreen image area to that buffer.\n\t\t*/\n\t\tif (background) {\n\t\t\tSeenPage.To_Buffer(WinX<<3, WinY, WinW<<3, WinH, background, Size_Of_Region(WinW<<3, WinH));\n\t\t}\n\n\t\t/*\n\t\t**\tDraw a rudimentary box.\n\t\t*/\n\t\tNew_Window();\n\t\tLogicPage->Draw_Rect(WinX<<3, WinY, (WinX+WinW)<<3, WinY+WinH, WinC);\n\n\t\t/*\n\t\t** shrinks window down one byte in all directions.\n\t\t*/\n\t\tWindowList[Window][WINDOWX] += 1;\n\t\tWindowList[Window][WINDOWY] += 1<<3;\n\t\tWindowList[Window][WINDOWWIDTH] -= 1<<1;\n\t\tWindowList[Window][WINDOWHEIGHT] -= 1<<4;\n\t\tChange_Window(Window);\n\t\tWinCx = WinCy = 0;\n\n\t\tWindow_Print(message);\n\t\tKeyboard::Clear();\n\n\t\t/*\n\t\t**\tCheck for input. If the ESC key was pressed or if retrying is not allowed,\n\t\t**\tthen exit the program. Otherwise, return from this routine for a retry\n\t\t**\tattempt.\n\t\t*/\n\t\tint input = Keyboard::Get();\n\t\tif (input == KN_ESC || !canretry) {\n\t\t\tProg_End();\n\t\t\texit(EXIT_FAILURE);\n\t\t}\n\n\t\t/*\n\t\t**\tRestore the window back to its original size.\n\t\t*/\n\t\tWindowList[Window][WINDOWX] -= 1;\n\t\tWindowList[Window][WINDOWY] -= 1<<3;\n\t\tWindowList[Window][WINDOWWIDTH] += 1<<1;\n\t\tWindowList[Window][WINDOWHEIGHT] += 1<<4;\n\t\tChange_Window(Window);\n\t\tWinCx = WinCy = 0;\n\n\t\t/*\n\t\t**\tIf the background was saved off, then restore it.\n\t\t*/\n\t\tif (background) {\n\t\t\tBuffer_To_Page(WinX<<3, WinY, WinW<<3, WinH, background, SeenPage);\n\t\t\tdelete [] background;\n\t\t}\n\n\t\t/*\n\t\t**\tRestore the system global settings to original values.\n\t\t*/\n\t\tShow_Mouse();\n\t\tChange_Window(oldwindow);\n\t\tSet_Font(oldfont);\n\t\tSet_Logic_Page(oldpage);\n\t\tFontXSpacing = oldspacing;\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * RawFileClass::RawFileClass -- Simple constructor for a file object.                         *\n *                                                                                             *\n *    This constructor is called when a file object is created with a supplied filename, but   *\n *    not opened at the same time. In this case, an assumption is made that the supplied       *\n *    filename is a constant string. A duplicate of the filename string is not created since   *\n *    it would be wasteful in that case.                                                       *\n *                                                                                             *\n * INPUT:   filename -- The filename to assign to this file object.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nRawFileClass::RawFileClass(char const *filename) : Filename(filename)\n{\n\tHandle = -1;\n\tAllocated = false;\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Set_Name -- Manually sets the name for a file object.                         *\n *                                                                                             *\n *    This routine will set the name for the file object to the name specified. This name is   *\n *    duplicated in free store. This allows the supplied name to be a temporarily constructed  *\n *    text string. Setting the name in this fashion doesn't affect the closed or opened state  *\n *    of the file.                                                                             *\n *                                                                                             *\n * INPUT:   filename -- The filename to assign to this file object.                            *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocated copy of this filename. This pointer is     *\n *          guaranteed to remain valid for the duration of this file object or until the name  *\n *          is changed -- whichever is sooner.                                                 *\n *                                                                                             *\n * WARNINGS:   Because of the allocation this routine must perform, memory could become        *\n *             fragmented.                                                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * RawFileClass::Set_Name(char const *filename)\n{\n\tif (Filename && Allocated) {\n// Heap_Dump_Check( \"Before raw free\" );\n\t\tfree((char *)Filename);\n// Heap_Dump_Check( \"After raw free\" );\n\t\t((char *&)Filename) = 0;\n\t\tAllocated = false;\n\t}\n\n\tif (!filename) return(NULL);\n\n// Heap_Dump_Check( \"Before raw strdup\" );\n\t((char *&)Filename) = strdup(filename);\n// Heap_Dump_Check( \"After raw strdup\" );\n\tif (!Filename) {\n\t\tError(ENOMEM, false, filename);\n\t}\n\tAllocated = true;\n\treturn(Filename);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Open -- Assigns name and opens file in one operation.                         *\n *                                                                                             *\n *    This routine will assign the specified filename to the file object and open it at the    *\n *    same time. If the file object was already open, then it will be closed first. If the     *\n *    file object was previously assigned a filename, then it will be replaced with the new    *\n *    name. Typically, this routine is used when an anonymous file object has been crated and  *\n *    now it needs to be assigned a name and opened.                                           *\n *                                                                                             *\n * INPUT:   filename -- The filename to assign to this file object.                            *\n *                                                                                             *\n *          rights   -- The open file access rights to use.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened? The return value of this is moot, since the open file   *\n *          is designed to never return unless it succeeded.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Open(char const *filename, int rights)\n{\n\tSet_Name(filename);\n\treturn(Open(rights));\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Open -- Opens the file object with the rights specified.                      *\n *                                                                                             *\n *    This routine is used to open the specified file object with the access rights indicated. *\n *    This only works if the file has already been assigned a filename. It is guaranteed, by   *\n *    the error handler, that this routine will always return with success.                    *\n *                                                                                             *\n * INPUT:   rights   -- The file access rights to use when opening this file. This is a        *\n *                      combination of READ and/or WRITE bit flags.                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened successfully? This will always return true by reason of  *\n *          the error handler.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Open(int rights)\n{\n\tClose();\n\n\t/*\n\t**\tVerify that there is a filename associated with this file object. If not, then this is a\n\t**\tbig error condition.\n\t*/\n\tif (!Filename) {\n\t\tError(ENOENT, false);\n\t}\n\n\t/*\n\t**\tRecord the access rights used for this open call. These rights will be used if the\n\t**\tfile object is duplicated.\n\t*/\n\tRights = rights;\n\n\t/*\n\t**\tRepetatively try to open the file. Abort if a fatal error condition occurs.\n\t*/\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tTry to open the file according to the access rights specified.\n\t\t*/\n//\t\tHard_Error_Occured = 0;\n\t\tswitch (rights) {\n\n\t\t\t/*\n\t\t\t**\tIf the access rights are not recognized, then report this as\n\t\t\t**\tan invalid access code.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\terrno = EINVAL;\n\t\t\t\tbreak;\n\n\t\t\tcase READ:\n\t\t\t\tHandle = (int)mmioOpen((char*)Filename, NULL, MMIO_READ);\n\t\t\t\t//Handle = open(Filename, O_RDONLY|O_BINARY);\n\t\t\t\tbreak;\n\n\t\t\tcase WRITE:\n\t\t\t\tHandle = (int)mmioOpen((char*)Filename, NULL, MMIO_WRITE | MMIO_CREATE);\n\t\t\t\t//Handle = open(Filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY , S_IWRITE);\n\t\t\t\tbreak;\n\n\t\t\tcase READ|WRITE:\n\t\t\t\tHandle = (int)mmioOpen((char*)Filename, NULL, MMIO_READWRITE);\n\t\t\t\t//Handle = open(Filename, O_RDWR|O_CREAT|O_BINARY);\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tIf the handle indicates the file is not open, then this is an error condition.\n\t\t**\tFor the case of the file cannot be found, then allow a retry. All other cases\n\t\t**\tare fatal.\n\t\t*/\n\t\tif (Handle == 0) {\n\n//\t\t\tError(errno, false, Filename);\t\t//this kills windoze!!!!    ST - 9/28/95 5:33PM\n#ifdef NEVER\n\t\t\t/*\n\t\t\t**\tIf this flag is set, then some hard error occurred. Just assume that the error\n\t\t\t**\tis probably a removed CD-ROM and allow a retry.\n\t\t\t*/\n\t\t\tif (Hard_Error_Occured) {\n\t\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\t} else {\n\t\t\t\tif (errno == ENOENT) {\n\t\t\t\t\tError(ENOENT, true, Filename);\n\t\t\t\t} else {\n\t\t\t\t\tError(errno, false, Filename);\n\t\t\t\t}\n\t\t\t}\n#endif\n\t\t\tcontinue;\n\t\t}\n\t\tbreak;\n\t}\n\treturn(true);\n}\n\n\n\n\nvoid RawFileClass::Set_Buffer_Size (int size)\n{\n\tif (Handle){\n\t\tmmioSetBuffer((HMMIO)Handle, NULL, size, 0);\n\t}\n}\n\n\n\n\n/***********************************************************************************************\n * RawFileClass::Is_Available -- Checks to see if the specified file is available to open.     *\n *                                                                                             *\n *    This routine will examine the disk system to see if the specified file can be opened     *\n *    or not. Use this routine before opening a file in order to make sure that is available   *\n *    or to perform other necessary actions.                                                   *\n *                                                                                             *\n * INPUT:   force -- Should this routine keep retrying until the file becomes available? If    *\n *                   in this case it doesn't become available, then the program will abort.    *\n *                                                                                             *\n * OUTPUT:  bool; Is the file available to be opened?                                          *\n *                                                                                             *\n * WARNINGS:   Depending on the parameter passed in, this routine may never return.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Is_Available(int forced)\n{\n\tint\tfile;\t\t// Working file handle.\n\tint\topen_failed;\n\t/*\n\t**\tIf the file is already open, then is must have already passed the availability check.\n\t**\tReturn true in this case.\n\t*/\n\tif (Is_Open()) return(true);\n\n\t/*\n\t**\tIf this is a forced check, then go through the normal open channels, since those\n\t**\tchannels ensure that the file must exist.\n\t*/\n\tif (forced) {\n\t\tRawFileClass::Open(READ);\n\t\tRawFileClass::Close();\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tPerform a raw open of the file. If this open fails for ANY REASON, including a missing\n\t**\tCD-ROM, this routine will return a failure condition. In all but the missing file\n\t**\tcondition, go through the normal error recover channels.\n\t*/\n\tfor (;;) {\n\n//\t\tHard_Error_Occured = 0;\n\t\tfile = open(Filename, O_RDONLY|O_BINARY);\n\t\topen_failed = (file == -1);\n\n\t\t/*\n\t\t**\tIf DOS reports that everything is just fine except that the file is not present,\n\t\t**\tthen return with this fact. Any other case will fall through to the error handler\n\t\t**\troutine.\n\t\t*/\n\t\tif (open_failed && errno == ENOENT) return(false);\n\n\t\t/*\n\t\t** If we got an access error it could be because there is no cd in\n\t\t** the drive.  Call the error handler but allow a continue if it\n\t\t** returns.\n\t\t*/\n\t\tif (open_failed && errno == EACCES) {\n\t\t\tError(errno, true, Filename);\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tIf the file could not be found, then return with this information. If a more\n\t\t**\tserious error occurred, then display the error message and abort.\n\t\t*/\n//\t\tif (Hard_Error_Occured) {\n//\t\t\tError(Hard_Error_Occured, true, Filename);\n//\t\t\tcontinue;\n//\t\t} else {\n\t\t\tif (open_failed) {\n\t\t\t\t/*\n\t\t\t\t**\tAn unhandled error condition is fatal. Display the error message and then\n\t\t\t\t**\tabort.\n\t\t\t\t*/\n\t\t\t\tError(errno, false, Filename);\n\t\t\t}\n//\t\t}\n\t\tif (!open_failed) break;\n\t}\n\n\t/*\n\t**\tSince the file could be opened, then close it and return that the file exists.\n\t*/\n\tif (close(file)) {\n\t\tError(errno, false, Filename);\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Close -- Perform a closure of the file.                                       *\n *                                                                                             *\n *    Close the file object. In the rare case of an error, handle it as appropriate.           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Some rare error conditions may cause this routine to abort the program.         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RawFileClass::Close(void)\n{\n\n\t/*\n\t**\tIf the file is open, then close it. If the file is already closed, then just return. This\n\t**\tisn't considered an error condition.\n\t*/\n\tif (Is_Open()) {\n\n\t\tfor (;;) {\n\t\t\t/*\n\t\t\t**\tClose the file. If there was an error in the close operation -- abort.\n\t\t\t*/\n//\t\t\tHard_Error_Occured = 0;\n\t\t\tif (mmioClose((HMMIO)Handle, 0)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tBy definition, this error can only be a bad file handle. This a fatal condition\n\t\t\t\t**\tof course, so abort with an error message.\n\t\t\t\t*/\n\t\t\t\tError(errno, false, Filename);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIn the condition (if it is even possible) of a hard error occurring, then\n\t\t\t**\tassume it is the case of missing media. Display an error message and try\n\t\t\t**\tagain if indicated.\n\t\t\t*/\n//\t\t\tif (Hard_Error_Occured) {\n//\t\t\t\tError(Hard_Error_Occured, true, Filename);\n//\t\t\t\tcontinue;\n//\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tAt this point the file must have been closed. Mark the file as empty and return.\n\t\t*/\n\t\tHandle = -1;\n\t}\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Read -- Reads the specified number of bytes into a memory buffer.             *\n *                                                                                             *\n *    This routine will read the specified number of bytes and place the data into the buffer  *\n *    indicated. It is legal to call this routine with a request for more bytes than are in    *\n *    the file. This condition can result in fewer bytes being read than requested. Determine  *\n *    this by examining the return value.                                                      *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer to read data into. If NULL is passed, no read    *\n *                      is performed.                                                          *\n *                                                                                             *\n *          size     -- The number of bytes to read. If NULL is passed, then no read is        *\n *                      performed.                                                             *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes read into the buffer. If this number is less      *\n *          than requested, it indicates that the file has been exhausted.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Read(void *buffer, long size)\n{\n\tlong\tbytesread = 0;\t\t\t// Running count of the number of bytes read into the buffer.\n\tint\topened = false;\t\t// Was the file opened by this routine?\n\tint\treadresult;\n\n\t/*\n\t**\tIf the file isn't opened, open it. This serves as a convenience\n\t**\tfor the programmer.\n\t*/\n\tif (!Is_Open()) {\n\n\t\t/*\n\t\t**\tThe error check here is moot. Open will never return unless it succeeded.\n\t\t*/\n\t\tif (!Open(READ)) {\n\t\t\treturn(0);\n\t\t}\n\t\topened = true;\n\t}\n\n\t/*\n\t**\tRead the file in convenient chunk sizes. When the actual number\n\t**\tof bytes read does not match the desired, then assume that the file\n\t**\tis exhausted and bail. This loop was adjusted to take into\n\t**\tconsideration the fact that \"read\" returns a SIGNED value whereas\n\t**\tit takes an UNSIGNED value as the byte count.\n\t*/\n\twhile (size) {\n\t\tunsigned\tdesired;\t\t// Bytes desired to be read this pass.\n\t\tunsigned actual;\t\t// Actual number of bytes read.\n\n\t\t/*\n\t\t**\tBreak the read request into chunks no bigger than the low level DOS read\n\t\t**\tcan handle.\n\t\t*/\n\t\tdesired = size;\n\n//\t\tHard_Error_Occured = 0;\n\t\treadresult = 0;\n\t\tactual = mmioRead((HMMIO)Handle, (char*)buffer, desired);\n\t\t//actual = read(Handle, buffer, desired);\n\t\tif (actual != desired) readresult = errno;\n\n\t\t/*\n\t\t**\tIf a hard error occurred, then assume that it is the case of the CD-ROM or\n\t\t**\tfloppy media having been removed. Display the error and retry as directed.\n\t\t*/\n//\t\tif (Hard_Error_Occured) {\n//\t\t\tError(Hard_Error_Occured, true, Filename);\n//\t\t\tcontinue;\t\t\t// Not technically needed, but to be consistent...\n//\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf negative one is returned from the read operation, then this indicates\n\t\t\t**\teither a bad file number or invalid access. These are fatal conditions, so\n\t\t\t**\tdisplay the error and then abort.\n\t\t\t*/\n\t\t\tif (readresult != 0) {\n\t\t\t\tError(errno, false, Filename);\n\t\t\t}// else {\n\n\t\t\t\t/*\n\t\t\t\t**\tNo error occurred during the read. Adjust the pointers and size counters and\n\t\t\t\t**\tloop again if more data is needed to be read.\n\t\t\t\t*/\n\t\t\t\tbuffer = (void *) ((long)buffer + actual);\n\t\t\t\tbytesread += actual;\n\t\t\t\tsize -= actual;\n\t\t\t\tif (actual != desired) break;\t\t// No more data?\n\t\t\t//}\n//\t\t}\n\t}\n\n\t/*\n\t**\tClose the file if it was opened by this routine and return\n\t**\tthe actual number of bytes read into the buffer.\n\t*/\n\tif (opened) Close();\n\treturn(bytesread);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Write -- Writes the specified data to the buffer specified.                   *\n *                                                                                             *\n *    This routine will write the data specified to the file.                                  *\n *                                                                                             *\n * INPUT:   buffer   -- The buffer that holds the data to write.                               *\n *                                                                                             *\n *          size     -- The number of bytes to write to the file.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes written to the file. This routine catches the     *\n *          case of a disk full condition, so this routine will always return with the number  *\n *          matching the size request.                                                         *\n *                                                                                             *\n * WARNINGS:   A fatal file condition could cause this routine to never return.                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Write(void const *buffer, long size)\n{\n\tlong\tbytesread = 0;\n\tint\topened = false;\t\t// Was the file manually opened?\n\tint\twriteresult;\n\n\t/*\n\t**\tCheck to open status of the file. If the file is open, then merely write to\n\t**\tit. Otherwise, open the file for writing and then close the file when the\n\t**\toutput is finished.\n\t*/\n\tif (!Is_Open()) {\n\t\tif (!Open(WRITE)) {\n\t\t\treturn(0);\n\t\t}\n\t\topened = true;\n\t}\n\n\t/*\n\t**\tWrite the data to the file in chunks no bigger than what the low level DOS write\n\t**\tcan handle.\n\t*/\n\twhile (size) {\n\t\tunsigned\tdesired;\t\t// Bytes desired to be write this pass.\n\t\tunsigned actual;\t\t// Actual number of bytes written.\n\n//\t\tHard_Error_Occured = 0;\n//\t\tdesired = (unsigned)MIN(size, Transfer_Block_Size());\n\t\tdesired = size;\n\t\twriteresult = 0;\n\t\tactual = mmioWrite((HMMIO)Handle, (char*)buffer, desired);\n\t\t//actual = write(Handle, buffer, desired);\n\t\tif (actual != desired) writeresult = errno;\n\n\t\t/*\n\t\t**\tIf a hard error occurred, then assume it is the case of the media being\n\t\t**\tremoved. Print the error message an retry as directed.\n\t\t*/\n//\t\tif (Hard_Error_Occured) {\n//\t\t\tError(Hard_Error_Occured, true, Filename);\n//\t\t\tcontinue;\t\t\t// Not technically needed, but to be consistent...\n//\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf negative one is returned by the DOS read, then this indicates a bad file\n\t\t\t**\thandle or invalid access. Either condition is fatal -- display error condition\n\t\t\t**\tand abort.\n\t\t\t*/\n\t\t\tif (writeresult != 0) {\n\t\t\t\tError(errno, false, Filename);\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tA successful write occurred. Update pointers and byte counter as appropriate.\n\t\t\t\t*/\n\t\t\t\tbuffer = (void *)((long)buffer + actual);\n\t\t\t\tbytesread += actual;\n\t\t\t\tsize -= actual;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the actual bytes written is less than requested, assume this is a case of\n\t\t\t\t**\tthe disk being full. Consider this a fatal error condition.\n\t\t\t\t*/\n\t\t\t\tif (actual != desired) {\n\t\t\t\t\tError(ENOSPC, false, Filename);\n\t\t\t\t}\n\t\t\t}\n//\t\t}\n\t}\n\n\t/*\n\t**\tIf this routine had to open the file, then close it before returning.\n\t*/\n\tif (opened) {\n\t\tClose();\n\t}\n\n\t/*\n\t**\tReturn with the number of bytes written. This will always be the number of bytes\n\t**\trequested, since the case of the disk being full is caught by this routine.\n\t*/\n\treturn(bytesread);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Seek -- Reposition the file pointer as indicated.                             *\n *                                                                                             *\n *    Use this routine to move the filepointer to the position indicated. It can move either   *\n *    relative to current position or absolute from the beginning or ending of the file. This  *\n *    routine will only return if it successfully performed the seek.                          *\n *                                                                                             *\n * INPUT:   pos   -- The position to seek to. This is interpreted as relative to the position  *\n *                   indicated by the \"dir\" parameter.                                         *\n *                                                                                             *\n *          dir   -- The relative position to relate the seek to. This can be either SEEK_SET  *\n *                   for the beginning of the file, SEEK_CUR for the current position, or      *\n *                   SEEK_END for the end of the file.                                         *\n *                                                                                             *\n * OUTPUT:  This routine returns the position that the seek ended up at.                       *\n *                                                                                             *\n * WARNINGS:   If there was a file error, then this routine might never return.                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Seek(long pos, int dir)\n{\n\t/*\n\t**\tIf the file isn't opened, then this is a fatal error condition.\n\t*/\n\tif (!Is_Open()) {\n\t\tError(EBADF, false, Filename);\n\t}\n\n\t/*\n\t**\tKeep trying to seek until a non-retry condition occurs.\n\t*/\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tPerform the low level seek on the file.\n\t\t*/\n//\t\tHard_Error_Occured = 0;\n\t\tpos = mmioSeek((HMMIO)Handle, pos, dir);\n\t\t//pos = lseek(Handle, pos, dir);\n\n\t\t/*\n\t\t**\tIf a hard error occurred, then assume that it is the case of removed media. Display\n\t\t**\terror message and retry.\n\t\t*/\n//\t\tif (Hard_Error_Occured) {\n//\t\t\tError(Hard_Error_Occured, true, Filename);\n//\t\t\tcontinue;\n//\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tA negative one indicates a fatal error with the seek operation. Display error\n\t\t\t**\tcondition and then abort.\n\t\t\t*/\n\t\t\tif (pos == -1) {\n\t\t\t\tError(errno, false, Filename);\n\t\t\t}\n//\t\t}\n\t\tbreak;\n\t}\n\n\t/*\n\t**\tReturn with the new position of the file. This will range between zero and the number of\n\t**\tbytes the file contains.\n\t*/\n\treturn(pos);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Size -- Determines size of file (in bytes).                                   *\n *                                                                                             *\n *    Use this routine to determine the size of the file. The file must exist or this is an    *\n *    error condition.                                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes in the file.                                      *\n *                                                                                             *\n * WARNINGS:   This routine handles error conditions and will not return unless the file       *\n *             exists and can successfully be queried for file length.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Size(void)\n{\n\tlong\tsize = 0;\n\tint\thandle = 0;\n\n\t/*\n\t**\tIf the file is open, then proceed normally.\n\t*/\n\tif (Is_Open()) {\n\n\t\t/*\n\t\t**\tRepetitively try to determine the file size until a fatal error condition or success\n\t\t**\tis achieved.\n\t\t*/\n\t\tfor (;;) {\n//\t\t\tHard_Error_Occured = 0;\n\n\t\t\thandle = open(Filename, O_RDONLY|O_BINARY);\n\t\t\tif (handle > 0){\n\t\t\t\tsize = filelength(handle);\n\t\t\t\tclose(handle);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf a hard error occurred, then assume it is the case of removed media. Display an\n\t\t\t**\terror condition and allow retry.\n\t\t\t*/\n//\t\t\tif (Hard_Error_Occured) {\n//\t\t\t\tError(Hard_Error_Occured, true, Filename);\n//\t\t\t\tcontinue;\n//\t\t\t} else {\n\t\t\t\tif (size == -1) {\n\t\t\t\t\tError(errno, false, Filename);\n\t\t\t\t}\n//\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tIf the file wasn't open, then open the file and call this routine again. Count on\n\t\t**\tthe fact that the open function must succeed.\n\t\t*/\n\t\tif (Open()) {\n\t\t\tsize = Size();\n\n\t\t\t/*\n\t\t\t**\tSince we needed to open the file we must remember to close the file when the\n\t\t\t**\tsize has been determined.\n\t\t\t*/\n\t\t\tClose();\n\t\t}\n\t}\n\treturn(size);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Create -- Creates an empty file.                                              *\n *                                                                                             *\n *    This routine will create an empty file from the file object. The file object's filename  *\n *    must already have been assigned before this routine will function.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the file successfully created? This routine will always return true.     *\n *                                                                                             *\n * WARNINGS:   A fatal error condition could occur with this routine. Especially if the disk   *\n *             is full or a read-only media was selected.                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Create(void)\n{\n\tClose();\n\tif (Open(WRITE)) {\n\t\tClose();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Delete -- Deletes the file object from the disk.                              *\n *                                                                                             *\n *    This routine will delete the file object from the disk. If the file object doesn't       *\n *    exist, then this routine will return as if it had succeeded (since the effect is the     *\n *    same).                                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the file deleted? If the file was already missing, the this value will   *\n *                be false.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Delete(void)\n{\n\t/*\n\t**\tIf the file was open, then it must be closed first.\n\t*/\n\tClose();\n\n\t/*\n\t**\tIf there is no filename associated with this object, then this indicates a fatal error\n\t**\tcondition. Report this and abort.\n\t*/\n\tif (!Filename) {\n\t\tError(ENOENT, false);\n\t}\n\n\t/*\n\t**\tRepetitively try to delete the file if possible. Either return with success, or\n\t**\tabort the program with an error.\n\t*/\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tIf the file is already missing, then return with this fact. No action is necessary.\n\t\t**\tThis can occur as this section loops if the file exists on a floppy and the floppy\n\t\t**\twas removed, the file deleted on another machine, and then the floppy was\n\t\t**\treinserted. Admittedly, this is a rare case, but is handled here.\n\t\t*/\n\t\tif (!Is_Available()) {\n\t\t\treturn(false);\n\t\t}\n\n//\t\tHard_Error_Occured = 0;\n\t\tif (remove(Filename) == -1) {\n\n\t\t\t/*\n\t\t\t**\tIf a hard error occurred, then assume that the media has been removed. Display\n\t\t\t**\terror message and retry as directed.\n\t\t\t*/\n//\t\t\tif (Hard_Error_Occured) {\n//\t\t\t\tError(Hard_Error_Occured, true, Filename);\n//\t\t\t\tcontinue;\n//\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf at this point, DOS says the file doesn't exist, then just exit with this\n\t\t\t**\tfact. It should have been caught earlier, but in any case, this is a legal\n\t\t\t**\tcondition.\n\t\t\t*/\n\t\t\tif (errno == ENOENT) break;\n\n\t\t\t/*\n\t\t\t**\tThe only way it can reach this point is if DOS indicates that access is denied\n\t\t\t**\ton the file. This occurs when trying to delete a file on a read-only media such\n\t\t\t**\tas a CD-ROM. Report this as a fatal error and then abort.\n\t\t\t*/\n\t\t\tError(errno, false, Filename);\n\t\t}\n\t\tbreak;\n\t}\n\n\t/*\n\t**\tDOS reports that the file was successfully deleted. Return with this fact.\n\t*/\n\treturn(true);\n}\n\n\n\n\n\n\n//extern \"C\" {\n\n#define\tMAX_HANDLES\t10\nstatic RawFileClass Handles[MAX_HANDLES];\n\n#ifdef NEVER\nbool __cdecl Set_Search_Drives(BYTE const *)\n{\n\tRawFileClass::Set_Search_Path(path);\n\treturn(true);\n}\n#endif\n\n\n\nint __cdecl Open_File(char const *file_name, int mode)\n{\n\tfor (int index = 0; index < MAX_HANDLES; index++) {\n\t\tif (!Handles[index].Is_Open()) {\n\t\t\tif (Handles[index].Open(file_name,mode)) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn(WW_ERROR);\n}\n\nVOID __cdecl Close_File(int handle)\n{\n\tif (handle != WW_ERROR && Handles[handle].Is_Open()) {\n\t\tHandles[handle].Close();\n\t}\n}\n\nLONG __cdecl Read_File(int handle, VOID *buf, ULONG bytes)\n{\n\tif (handle != WW_ERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Read(buf, bytes));\n\t}\n\treturn(0);\n}\n\nLONG __cdecl Write_File(int handle, VOID const *buf, ULONG bytes)\n{\n\tif (handle != WW_ERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Write(buf, bytes));\n\t}\n\treturn(0);\n}\n\nint __cdecl Find_File(char const *file_name)\n{\n\tRawFileClass file(file_name);\n\treturn(file.Is_Available());\n}\n\n#ifdef NEVER\nint __cdecl Delete_File(BYTE const *file_name)\n{\n\treturn(RawFileClass(file_name).Delete());\n}\n\nint __cdecl Create_File(BYTE const *file_name)\n{\n\treturn(RawFileClass(file_name).Create());\n}\n\nULONG __cdecl Load_Data(BYTE const *name, VOID *ptr, ULONG size)\n{\n\treturn(RawFileClass(name).Read(ptr, size));\n}\n\nVOID * __cdecl Load_Alloc_Data(char const *name, int )\n{\n\tRawFileClass file(name);\n\n\treturn(Load_Alloc_Data(file));\n}\n#endif\n\nULONG __cdecl File_Size(int handle)\n{\n\tif (handle != WW_ERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Size());\n\t}\n\treturn(0);\n}\n\n#ifdef NEVER\nULONG __cdecl Write_Data(BYTE const *name, VOID const *ptr, ULONG size)\n{\n\treturn(RawFileClass(name).Write(ptr, size));\n}\n#endif\n\nULONG __cdecl Seek_File(int handle, LONG offset, int starting)\n{\n\tif (handle != WW_ERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Seek(offset, starting));\n\t}\n\treturn(0);\n}\n\n#ifdef NEVER\nbool __cdecl Multi_Drive_Search(bool on)\n{\n//\treturn(RawFileClass::Multi_Drive_Search(on));\n\treturn(on);\n}\n\nVOID __cdecl WWDOS_Init(VOID)\n{\n}\n\nVOID __cdecl WWDOS_Shutdown(VOID)\n{\n}\n\nint __cdecl Find_Disk_Number(BYTE const *)\n{\n\treturn(0);\n}\n#endif\n\n\n\n\n/***********************************************************************************************\n * Load_File -- load an entire file into memory                                                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    File name                                                                         *\n *           Load address                                                                      *\n *                                                                                             *\n * OUTPUT:   bytes loaded                                                                      *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/28/95 5:09PM ST : Created                                                              *\n *=============================================================================================*/\n\nint __cdecl Load_File ( const char *file_name , void *load_addr )\n{\n\tint\t\tbytes_read=0;\n\tint\t\thandle;\n\n\thandle=Open_File ( file_name , READ );\n\n\tif ( handle>=0 ){\n\t\tbytes_read = Read_File ( handle , load_addr , File_Size ( handle ) );\n\t\tClose_File ( handle );\n\t}\n\treturn ( bytes_read );\n}\n\n\n\n\n//ULONG cdecl Load_Uncompress(BYTE const *file, BuffType uncomp_buff, BuffType dest_buff, VOID *reserved_data)\n//{\n//\treturn(Load_Uncompress(RawFileClass(file), uncomp_buff, dest_buff, reserved_data));\n//\treturn(RawFileClass(file).Load_Uncompress(uncomp_buff, dest_buff, reserved_data));\n//}\nextern \"C\" {\nint MaxDevice;\nint DefaultDrive;\nchar CallingDOSInt;\n\n}\n\n\nvoid Unfragment_File_Cache(void)\n{\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/REDBOOK.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB\t  \t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : REDBOOK.CPP\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : STEVE WETHERILL (FROM SCOTT BOWEN CODE)  *\n *                                                                         *\n *                   Start Date : 5/13/94\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : June 4, 1994   [SW]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *\t\tRedBookClass::~RedBookClass(VOID)\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tRedBookClass::RedToHS(ULONG i)\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tRedBookClass::MSFtoRed(UBYTE m, UBYTE s, UBYTE f)\t\t\t\t\t\t\t*\n *\t\tRedBookClass::FullCDVolume(UBYTE chan)\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tRedBookClass::PlayTrack(UWORD track)\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tRedBookClass::Play_CD_MSL(UWORD min_sec, UWORD len)\t\t\t\t\t\t*\n *\t\tRedBookClass::PlayMSF(UBYTE startM, UBYTE startS, UBYTE startF,\t\t*\n * \t\t\t  \t\t\t\tUBYTE endM, UBYTE endS, UBYTE endF, UBYTE chan)\t\t*\n *\t\tRedBookClass::CheckCDMusic(VOID)\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tRedBookClass::StopCDMusic(VOID)\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <dos.h>\n\n#include \"wwstd.h\"\n#include \"playcd.h\"\n#include \"wwmem.h\"\n\n\n/***************************************************************************\n * RedBookClass -- default constructor\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *      \tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *\t\tcalls GetCDDrive()\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * HISTORY:                                                                *\n *   05/25/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n\nRedBookClass::RedBookClass(VOID)\n\t: GetCDClass()\t\t\t// call the base constructor\n\n{\n\tSEGSEL tmpadr ;\n\n\ttmpadr = cdDrive_addrp;\n\tmemset ( this  , 0 , sizeof ( RedBookClass )\t) ;\n\tcdDrive_addrp = tmpadr ;\n\n\tStop.Length\t\t=\t13;\n\tStop.Command\t=\t133;\n\n\tTinfo.Length\t=\t26;\n\tTinfo.Command\t=\t3;\n\tTinfo.CntTrns\t=\t7;\n\tTinfo.TrInfo\t=\t11;\n\n\tPlay.Length\t\t=\t22;\n\tPlay.Command\t=\t132;\n\tPlay.AddrMd\t\t=\t1;\n\t\n\tVolm.Length\t\t=\t26;\n\tVolm.Command\t=\t12;\n\tVolm.CntTrns\t=\t9;\n\tVolm.TrInfo\t\t=\t3;\n\tVolm.In1\t\t\t=\t1;\n\tVolm.In2\t\t\t=\t2;\n\tVolm.In3\t\t\t=\t3;\n\t\n\tStat.Length\t\t=\t26;\n\tStat.Command\t=\t3;\n\tStat.CntTrns\t=\t11;\n\tStat.StatInfo\t=\t15;\n\t\t\t\t\t\t\t\n\tif\t(DPMI_real_alloc(sizeof(TinfoType)/16+1, &Tinfo_addrp, &largestp))\n\t\texit(1);\n\n\tif\t(DPMI_real_alloc(sizeof(StatType)/16+1, &Stat_addrp, &largestp))\n\t\texit(1);\n\n\tif\t(DPMI_real_alloc(sizeof(VolmType)/16+1, &Volm_addrp, &largestp))\n\t\texit(1);\n\n\tif\t(DPMI_real_alloc(sizeof(PlayType)/16+1, &Play_addrp, &largestp))\n\t\texit(1);\n\n\tif\t(DPMI_real_alloc(sizeof(StopType)/16+1, &Stop_addrp, &largestp))\n\t\texit(1);\n\n\tGetCDDrive();\n\n}\n\n/***************************************************************************\n * REDBOOKCLASS -- destructor                                              *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *=========================================================================*/\n\nRedBookClass::~RedBookClass(VOID)\n{\n\tif(Tinfo_addrp.seg)\n\t\tDPMI_real_free(Tinfo_addrp);\t\t// free up those conventional buffers\n\n\tif(Stat_addrp.seg)\n\t\tDPMI_real_free(Stat_addrp);\n\n\tif(Volm_addrp.seg)\n\t\tDPMI_real_free(Volm_addrp);\n\n\tif(Play_addrp.seg)\n\t\tDPMI_real_free(Play_addrp);\n\n\tif(Stop_addrp.seg)\n\t\tDPMI_real_free(Stop_addrp);\n}\n\n/***************************************************************************\n * REDTOHS -- RedBook to High-Sierra conversion                            *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tULONG\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:    \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tULONG\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n\nULONG RedBookClass::RedToHS(ULONG i)\n{\n\treturn( ((i>>16) & 0xFF) * 60 * 75) + ( ((i>>8) & 0xFF) * 75) + (i & 0xFF);\n}\n\n/***************************************************************************\n * MSFTORED -- Minute, Second, Frame to RedBook conversion                 *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *   \t\tUBYTE\tminute\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * \t\tUBYTE\tsecond\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t  \t\tUBYTE\tframe\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:          \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tULONG\tRedBook\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *=========================================================================*/\n\nULONG  RedBookClass::MSFtoRed(UBYTE m, UBYTE s, UBYTE f)\n{\n\treturn( ((ULONG)m << 16) + ((ULONG)s << 8) + (ULONG)f );\n}\n\n/***************************************************************************\n * FULLCDVOLUME -- set full volume                                         *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tUBYTE channel\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\tCHLEFT\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\tCHRIGHT\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\tCHBOTH\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *    \t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *=========================================================================*/\n\nVOID  RedBookClass::FullCDVolume(UBYTE chan)\n{\n\n\tVolm.Vol0 = Volm.Vol1 = Volm.Vol2 = Volm.Vol3 = 255;\n\n\tVolm.TrnsAdOff = offsetof\t(VolmType, TrInfo);\n\tVolm.TrnsAdSeg = Volm_addrp.seg;\n\n\tif(chan == CHLEFT)\n\t{\n//\t\tVolm.In0 = 0;\n//\t\tVolm.In1 = 3;\n//\t\tVolm.In2 = 3;\n//\t\tVolm.In3 = 3;\n\t\tVolm.Vol1 = 0;\n\t}\n\telse if(chan == CHRIGHT)\n\t{\n//\t\tVolm.In0 = 3;\n//\t\tVolm.In1 = 1;\n//\t\tVolm.In2 = 3;\n//\t\tVolm.In3 = 3;\n\t\tVolm.Vol0 = 0;\n\t}\n\telse\t\t\t/* both channels */\n\t{\n\t\tVolm.In0 = 0;\n\t\tVolm.In1 = 1;\n\t\tVolm.In2 = 2;\n\t\tVolm.In3 = 3;\n\t}\n\n//\tWriteRealMem(REALPTR(Volm_addrp) << 16, &Volm, sizeof(VolmType));\n\tMem_Copy ( &Volm , (void *) ( Volm_addrp.seg << 4 ) , sizeof(VolmType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = 0x0000;\n\tsregs.es   = Volm_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs, & sregs);\n\n//\tReadRealMem(&Volm, REALPTR(Volm_addrp) << 16, sizeof(VolmType));\n\tMem_Copy ( (void *) ( Volm_addrp . seg << 4 ), &Volm ,sizeof(VolmType));\n}\n\n\n\n/***************************************************************************\n * PLAYTRACK -- play a track                                               *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n * \t\tUWORD\ttrack\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *=========================================================================*/\n\nVOID  RedBookClass::PlayTrack(UWORD track)\n{\n\n\tStopCDMusic();\n\n\tTinfo.Track = track;\n\n\tTinfo.TrnsAdOff = offsetof\t(TinfoType, TrInfo);\n\tTinfo.TrnsAdSeg = Tinfo_addrp.seg;\n\n//\tWriteRealMem(REALPTR(Tinfo_addrp) << 16, &Tinfo, sizeof(TinfoType));\n\tMem_Copy ( &Tinfo , (void *) ( Tinfo_addrp.seg << 4 ) , sizeof(TinfoType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx\t= cdDrive[0];\n\tregs.x.ebx = 0x0000;\n\tsregs.es \t= Tinfo_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs, &sregs);\t\t// gets start time of track in Tinfo.Start\n\n//\tReadRealMem(&Tinfo, REALPTR(Tinfo_addrp) << 16, sizeof(TinfoType));\n\tMem_Copy ( (void *) ( Tinfo_addrp.seg << 4 ) , &Tinfo, sizeof(TinfoType));\n\n\n\n\n\tPlay.Start = Tinfo.Start;\n\tTinfo.Track++;\n\n\tTinfo.TrnsAdOff = offsetof\t(TinfoType, TrInfo);\n\tTinfo.TrnsAdSeg = Tinfo_addrp.seg;\n\n//\tWriteRealMem(REALPTR(Tinfo_addrp) << 16, &Tinfo, sizeof(TinfoType));\n\tMem_Copy ( &Tinfo , (void *) ( Tinfo_addrp.seg << 4 ) , sizeof(TinfoType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = 0x0000;\n\tsregs.es  = Tinfo_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs , &sregs);\t\t// gets start time of following track in Tinfo.Start\n\n//\tReadRealMem(&Tinfo, REALPTR(Tinfo_addrp) << 16, sizeof(TinfoType));\n\tMem_Copy ( (void *) ( Tinfo_addrp.seg << 4 ) , &Tinfo, sizeof(TinfoType));\n\n\n\n\tPlay.CntSect  = RedToHS(Tinfo.Start) - RedToHS(Play.Start) - 1;\n\n//\tWriteRealMem(REALPTR(Play_addrp) << 16, &Play, sizeof(PlayType));\n\tMem_Copy ( &Play , (void *) ( Play_addrp.seg << 4 ) , sizeof(PlayType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = 0x0000;\n\tsregs.es \t= Play_addrp.seg;\n\n  \tDPMI_real_intr(0x2F, &regs, &sregs);\n\n//\tReadRealMem(&Play, REALPTR(Play_addrp) << 16, sizeof(PlayType));\n\tMem_Copy ( (void *) ( Play_addrp.seg << 4 ) , &Play, sizeof(PlayType));\n\n\n\tFullCDVolume(CHBOTH);\n}\n\n\n/***************************************************************************\n * PLAY_CD_MSL -- play cd from start min_sec for len                       *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tUWORD\tmin_sec\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUWORD\tLen\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *=========================================================================*/\n\n\nVOID  RedBookClass::Play_CD_MSL(UWORD min_sec, UWORD len) \n{\n\tUWORD startM, startS, startF;\n\tUWORD endM, endS, endF;\n\n\tif (!len)\n\t\treturn;\n\n\tendM = startM = (min_sec >> 8) + AUDIO_START_MIN;\n\tendS = startS = (min_sec & 0xFF) + AUDIO_START_SEC;\n\tstartF = endF = 0;\n\n\twhile (len > 59) {\n\t\tendM++;\n\t\tlen -= 60;\n\t}\n\n\tendS += len;\n\tif (endS > 59) {\n\t\tendM++;\n\t\tendS -= 60;\n\t}\n\n\tPlayMSF((UBYTE) startM, (UBYTE)startS, (UBYTE)startF, (UBYTE)endM, (UBYTE)endS, (UBYTE)endF, 2 /* chan */);\n}\n\n\n/***************************************************************************\n * PlayMSF -- Play Minute, Second, Frame to Minute, Second, Frame\t\t\t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tUBYTE\tstartM\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tstartS\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tstartF\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *    \tUBYTE\tendM\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tendS\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tendF\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tchan\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/27/1994 SW : Created.                                              *\n *=========================================================================*/\n\n\nVOID  RedBookClass::PlayMSF(UBYTE startM, UBYTE startS, UBYTE startF, UBYTE endM, UBYTE endS, UBYTE endF, UBYTE chan)\n{\n\n\tPlay.Start = MSFtoRed(startM, startS, startF);\n\tPlay.CntSect  = RedToHS(MSFtoRed(endM, endS, endF)) - RedToHS(Play.Start) - 1;\n\n//\tWriteRealMem(REALPTR(Play_addrp) << 16, &Play, sizeof(PlayType));\n\tMem_Copy ( &Play , (void *) ( Play_addrp.seg << 4 ) , sizeof(PlayType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = offsetof (PlayType, Length);\n\tsregs.es \t= Play_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs, &sregs);\n\n//\tReadRealMem(&Play, REALPTR(Play_addrp) << 16, sizeof(PlayType));\n\tMem_Copy ( (void *) ( Play_addrp.seg << 4 ) , &Play, sizeof(PlayType));\n\n\tFullCDVolume(chan);\n\n}\n\n/***************************************************************************\n * CheckCDMusic -- Check for CD playing\t\t\t\t\t   \t\t\t\t\t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tUBYTE\tstartM\t\t\t  \t\t\t\t\t\t\t\t\t\t \t\t\t\t\t*\n *\t\t\tUBYTE\tstartS\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tstartF\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t*\n *    \tUBYTE\tendM\t\t\t\t  \t\t\t\t\t\t\t\t\t\t \t\t\t\t\t*\n *\t\t\tUBYTE\tendS\t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tendF\t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tchan\t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                             \t\t\t\t\t\t\t*\n *\t\t\tUWORD\tTRUE if playing else FALSE                 \t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/27/1994 SW : Created.                                              *\n *=========================================================================*/\n\n\nUWORD  RedBookClass::CheckCDMusic(VOID)\n{\n\t\n\tStat.TrnsAdOff = offsetof\t(StatType, StatInfo);\n\tStat.TrnsAdSeg = Stat_addrp.seg;\n\n//\tWriteRealMem(REALPTR(Stat_addrp) << 16, &Stat, sizeof(StatType));\n\tMem_Copy ( &Stat , (void *) ( Stat_addrp.seg << 4 ) , sizeof(StatType));\n\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = offsetof (StatType, Length);\n\tregs.x.eax = 0x1510;\n\tsregs.es \t= Stat_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs, &sregs);\n\n//\tReadRealMem(&Stat, REALPTR(Stat_addrp) << 16, sizeof(StatType));\n\tMem_Copy ( (void *) ( Stat_addrp.seg << 4 ) , &Stat, sizeof(StatType));\n\n\treturn (Stat.Status&0x200);\n}\n\n/***************************************************************************\n * STOPCDMUSIC -- stop CD playing                                          *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone\t\t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/27/1994  SW : Created.                                             *\n *=========================================================================*/\n\nVOID  RedBookClass::StopCDMusic(VOID)\n{\n\n//\tWriteRealMem(REALPTR(Stop_addrp) << 16, &Stop, sizeof(StopType));\n\tMem_Copy ( &Stop , (void *) ( Stop_addrp.seg << 4 ) , sizeof(StopType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = offsetof (StopType, Length);\n\tsregs.es \t= Stop_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs, &sregs);\n\n//\tReadRealMem(&Stop, REALPTR(Stop_addrp) << 16, sizeof(StopType));\n\tMem_Copy ( (void *) ( Stop_addrp.seg << 4 ) , &Stop, sizeof(StopType));\n\n}\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/REGIONSZ.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB 32                                 *\n *                                                                         *\n *                    File Name : REGIONSZ.CPP                             *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : November 3, 1994                         *\n *                                                                         *\n *                  Last Update : November 3, 1994   [PWG]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Size_Of_Region -- Calculates the size of a given region               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * SIZE_OF_REGION -- Calculates the size of a given region                 *\n *                                                                         *\n * INPUT:\tint width  - the width of the region                           *\n *\t\t\t\tint height - the height of the region\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:  long - the size of the region                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/03/1994 PWG : Created.                                             *\n *=========================================================================*/\nlong Size_Of_Region(int width, int height)                                 \n{\n\treturn(width * height);\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/REMAP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : REMAP.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 1, 1994                             *\n;*                                                                         *\n;*                  Last Update : July 1, 1994   [PWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n\tPROC\tBuffer_Remap C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* Define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tthis_object:DWORD\n\tARG\tx0_pixel:DWORD\n\tARG\ty0_pixel:DWORD\n\tARG\tregion_width:DWORD\n\tARG\tregion_height:DWORD\n\tARG\tremap\t:DWORD\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tlocal\tx1_pixel  : DWORD\n\tlocal\ty1_pixel  : DWORD\n\tlocal\twin_width : dword\n\tlocal\tcounter_x : dword\n\n\n\tcmp\t[ remap ] , 0\n\tjz\t??real_out\n\n; Clip Source Rectangle against source Window boundaries.\n\tmov  \tesi , [ this_object ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\tebx , [ x0_pixel ]\n\tmov\teax , [ x0_pixel ]\n\tadd\tebx , [ region_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register\n\tmov\tebx , [ y0_pixel ]\n\tmov\teax , [ y0_pixel ]\n\tadd\tebx , [ region_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_remap\n\n\ttest\tcl , 1000b\n\tjz\t??scr_left_ok\n\tmov\t[ x0_pixel ] , 0\n\n??scr_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\t[ y0_pixel ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_remap\n\tmov\teax , [ (GraphicViewPort esi) . GVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n\n??do_remap:\n       cld\n       mov\tedi , [ (GraphicViewPort esi) . GVPOffset ]\n       mov\teax , [ (GraphicViewPort esi) . GVPXAdd ]\n       mov\tebx , [ x1_pixel ]\n       add\teax , [ (GraphicViewPort esi) . GVPWidth ]\n       add\teax , [ (GraphicViewPort esi) . GVPPitch ]\n       mov\tesi , eax\n       mul\t[ y0_pixel ]\n       add\tedi , [ x0_pixel ]\n       sub\tebx , [ x0_pixel ]\n       jle\t??real_out\n       add\tedi , eax\n       sub\tesi , ebx\n\n       mov\tecx , [ y1_pixel ]\n       sub\tecx , [ y0_pixel ]\n       jle\t??real_out\n       mov\teax , [ remap ]\n       mov\t[ counter_x ] , ebx\n       xor\tedx , edx\n\n??outer_loop:\n       mov\tebx , [ counter_x ]\n??inner_loop:\n       mov\tdl , [ edi ]\n       mov\tdl , [ eax + edx ]\n       mov\t[ edi ] , dl\n       inc\tedi\n       dec\tebx\n       jnz\t??inner_loop\n       add\tedi , esi\n       dec\tecx\n       jnz\t??outer_loop\n\n\n\n\n??real_out:\n\tret\n\n\tENDP\tBuffer_Remap\n\n\tEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/REVERSE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/misc/rcs/reverse.asm 1.3 1994/04/25 12:22:45 scott_bowen Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : REVERSE.ASM                              *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : April 20, 1994   [SKB]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n; LONG Reverse_Long(LONG number);                                          *\n; WORD Reverse_Short(WORD number);\t\t\t\t\t   *\n; LONG Swap_LONG(LONG number);\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\t C Reverse_Short\t:NEAR\nGLOBAL\t C Swap_Long\t:NEAR\nGLOBAL\t C Reverse_Long\t:NEAR\n\nCODESEG\n\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; LONG Reverse_LONG(LONG number);\n; WORD Reverse_Short(WORD number);\n; LONG Swap_LONG(LONG number);\n;\n; ----------------------------------------------------------------\n\n;-----------------------------------------------------------------\n;\n; REVERSE_LONG\n;\n; LONG Reverse_LONG(LONG number);\n;\n;*\n\tPROC\tReverse_Long C near\n\tARG\tnumber:DWORD\n\nIF 1\n\tmov\teax,[DWORD PTR number]\n\txchg\tal,ah\n\tror\teax,16\n\txchg\tal,ah\nELSE\n\n\t; This is old 16 bit code.\n\tmov\tax,[WORD PTR number]\n\tmov\tdx,[WORD PTR number+2]\n\txchg\tah,dl\n\txchg\tal,dh\nENDIF\n\n\tret\n\n\tENDP\tReverse_Long\n\n;-----------------------------------------------------------------\n\n;-----------------------------------------------------------------\n;\n; REVERSE_WORD\n;\n; WORD Reverse_Short(WORD number);\n;\n;*\n\tPROC\tReverse_Short C near\n\tARG\tnumber:WORD\n\n\tmov\tax,[number]\n\txchg\tah,al\n\tret\n\n\tENDP\tReverse_Short\n\n;-----------------------------------------------------------------\n\n\n;-----------------------------------------------------------------\n;\n; SWAP_Long\n;\n; Long Swap_Long(Long number);\n;\n;*\n\tPROC\tSwap_Long C near\n\tARG\tnumber:DWORD\n\nIF 1\n\t; 32 bit code.\n    \tmov\teax,[DWORD PTR number]\n\tror\teax,16\nELSE\n\t; 16 bit code.\n\tmov\tax,[WORD PTR number+2]\n\tmov\tdx,[WORD PTR number]\nENDIF\n\n\tret\n\n\n\tENDP\tSwap_Long\n\n;-----------------------------------------------------------------\n\n\tEND\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/SCALE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : SCALE.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 16, 1994                            *\n;*                                                                         *\n;*                  Last Update : June 21, 1994   [PWG]                    *\n;*                  New version : feb 12, 1995  [JRJ]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVC::Scale -- Scales a virtual viewport to another virtual viewport   *\n;*   Normal_Draw -- jump loc for drawing  scaled line of normal pixel      *\n;*   Normal_Remapped_Draw -- jump loc for draw scaled line of remap pixel  *\n;*   Transparent_Draw -- jump loc for scaled line of transparent pixels    *\n;*   Transparent_Remapped_Draw -- jump loc for scaled remap trans pixels   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n\n;***************************************************************************\n;* VVC::SCALE -- Scales a virtual viewport to another virtual viewport     *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/16/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tLinear_Scale_To_Linear C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* Define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tthis_object:DWORD\t\t; pointer to source view port\n\tARG\tdest:DWORD\t\t; pointer to destination view port\n\tARG\tsrc_x:DWORD\t\t; source x offset into view port\n\tARG\tsrc_y:DWORD\t\t; source y offset into view port\n\tARG\tdst_x:DWORD\t\t; dest x offset into view port\n\tARG\tdst_y:DWORD\t\t; dest y offset into view port\n\tARG\tsrc_width:DWORD\t\t; width of source rectangle\n\tARG\tsrc_height:DWORD\t; height of source rectangle\n\tARG\tdst_width:DWORD\t\t; width of dest rectangle\n\tARG\tdst_height:DWORD\t; width of dest height\n\tARG\ttrans:DWORD\t\t; is this transparent?\n\tARG\tremap:DWORD\t\t; pointer to table to remap source\n\n\t;*===================================================================\n\t;* Define local variables to hold the viewport characteristics\n\t;*===================================================================\n\tlocal\tsrc_x0 : dword\n\tlocal\tsrc_y0 : dword\n\tlocal\tsrc_x1 : dword\n\tlocal\tsrc_y1 : dword\n\n\tlocal\tdst_x0 : dword\n\tlocal\tdst_y0 : dword\n\tlocal\tdst_x1 : dword\n\tlocal\tdst_y1 : dword\n\n\tlocal\tsrc_win_width : dword\n\tlocal\tdst_win_width : dword\n\tlocal\tdy_intr : dword\n\tlocal\tdy_frac : dword\n\tlocal\tdy_acc  : dword\n\tlocal\tdx_frac : dword\n\n\tlocal\tcounter_x     : dword\n\tlocal\tcounter_y     : dword\n\tlocal\tremap_counter :dword\n\tlocal\tentry : dword\n\n\t;*===================================================================\n\t;* Check for scale error when to or from size 0,0\n\t;*===================================================================\n\tcmp\t[dst_width],0\n\tje\t??all_done\n\tcmp\t[dst_height],0\n\tje\t??all_done\n\tcmp\t[src_width],0\n\tje\t??all_done\n\tcmp\t[src_height],0\n\tje\t??all_done\n\n\tmov\teax , [ src_x ]\n\tmov\tebx , [ src_y ]\n\tmov\t[ src_x0 ] , eax\n\tmov\t[ src_y0 ] , ebx\n\tadd\teax , [ src_width ]\n\tadd\tebx , [ src_height ]\n\tmov\t[ src_x1 ] , eax\n\tmov\t[ src_y1 ] , ebx\n\n\tmov\teax , [ dst_x ]\n\tmov\tebx , [ dst_y ]\n\tmov\t[ dst_x0 ] , eax\n\tmov\t[ dst_y0 ] , ebx\n\tadd\teax , [ dst_width ]\n\tadd\tebx , [ dst_height ]\n\tmov\t[ dst_x1 ] , eax\n\tmov\t[ dst_y1 ] , ebx\n\n; Clip Source Rectangle against source Window boundaries.\n\tmov  \tesi , [ this_object ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\teax , [ src_x0 ]\n\tmov\tebx , [ src_x1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register\n\tmov\teax , [ src_y0 ]\n\tmov\tebx , [ src_y1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??all_done\n\tor\tal , dl\n\tjz\t??clip_against_dest\n\tmov\tbl , dl\n\ttest\tcl , 1000b\n\tjz\t??src_left_ok\n\txor\teax , eax\n\tmov\t[ src_x0 ] , eax\n\tsub\teax , [ src_x ]\n\timul\t[ dst_width ]\n\tidiv\t[ src_width ]\n\tadd\teax , [ dst_x ]\n\tmov\t[ dst_x0 ] , eax\n\n??src_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??src_bottom_ok\n\txor\teax , eax\n\tmov\t[ src_y0 ] , eax\n\tsub\teax , [ src_y ]\n\timul\t[ dst_height ]\n\tidiv\t[ src_height ]\n\tadd\teax , [ dst_y ]\n\tmov\t[ dst_y0 ] , eax\n\n??src_bottom_ok:\n\ttest\tbl , 0100b\n\tjz\t??src_right_ok\n\tmov\teax , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\t[ src_x1 ] , eax\n\tsub\teax , [ src_x ]\n\timul\t[ dst_width ]\n\tidiv\t[ src_width ]\n\tadd\teax , [ dst_x ]\n\tmov\t[ dst_x1 ] , eax\n\n??src_right_ok:\n\ttest\tbl , 0001b\n\tjz\t??clip_against_dest\n\tmov\teax , [ (GraphicViewPort esi) . GVPHeight ]  ; get width into register\n\tmov\t[ src_y1 ] , eax\n\tsub\teax , [ src_y ]\n\timul\t[ dst_height ]\n\tidiv\t[ src_height ]\n\tadd\teax , [ dst_y ]\n\tmov\t[ dst_y1 ] , eax\n\n; Clip destination Rectangle against source Window boundaries.\n??clip_against_dest:\n\tmov  \tesi , [ dest ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\teax , [ dst_x0 ]\n\tmov\tebx , [ dst_x1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register\n\tmov\teax , [ dst_y0 ]\n\tmov\tebx , [ dst_y1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??all_done\n\tor\tal , dl\n\tjz\t??do_scaling\n\tmov\tbl , dl\n\ttest\tcl , 1000b\n\tjz\t??dst_left_ok\n\txor\teax , eax\n\tmov\t[ dst_x0 ] , eax\n\tsub\teax , [ dst_x ]\n\timul\t[ src_width ]\n\tidiv\t[ dst_width ]\n\tadd\teax , [ src_x ]\n\tmov\t[ src_x0 ] , eax\n\n??dst_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dst_bottom_ok\n\txor\teax , eax\n\tmov\t[ dst_y0 ] , eax\n\tsub\teax , [ dst_y ]\n\timul\t[ src_height ]\n\tidiv\t[ dst_height ]\n\tadd\teax , [ src_y ]\n\tmov\t[ src_y0 ] , eax\n\n??dst_bottom_ok:\n\ttest\tbl , 0100b\n\tjz\t??dst_right_ok\n\tmov\teax , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\t[ dst_x1 ] , eax\n\tsub\teax , [ dst_x ]\n\timul\t[ src_width ]\n\tidiv\t[ dst_width ]\n\tadd\teax , [ src_x ]\n\tmov\t[ src_x1 ] , eax\n\n??dst_right_ok:\n\ttest\tbl , 0001b\n\tjz\t??do_scaling\n\n\tmov\teax , [ (GraphicViewPort esi) . GVPHeight ]  ; get width into register\n\tmov\t[ dst_y1 ] , eax\n\tsub\teax , [ dst_y ]\n\timul\t[ src_height ]\n\tidiv\t[ dst_height ]\n\tadd\teax , [ src_y ]\n\tmov\t[ src_y1 ] , eax\n\n??do_scaling:\n\n       cld\n       mov\tebx , [ this_object ]\n       mov\tesi , [ (GraphicViewPort ebx) . GVPOffset ]\n       mov\teax , [ (GraphicViewPort ebx) . GVPXAdd ]\n       add\teax , [ (GraphicViewPort ebx) . GVPWidth ]\n       add\teax , [ (GraphicViewPort ebx) . GVPPitch ]\n       mov\t[ src_win_width ] , eax\n       mul\t[ src_y0 ]\n       add\tesi , [ src_x0 ]\n       add\tesi , eax\n\n       mov\tebx , [ dest ]\n       mov\tedi , [ (GraphicViewPort ebx) . GVPOffset ]\n       mov\teax , [ (GraphicViewPort ebx) . GVPXAdd ]\n       add\teax , [ (GraphicViewPort ebx) . GVPWidth ]\n       add\teax , [ (GraphicViewPort ebx) . GVPPitch ]\n       mov\t[ dst_win_width ] , eax\n       mul\t[ dst_y0 ]\n       add\tedi , [ dst_x0 ]\n       add\tedi , eax\n\n       mov\teax , [ src_height ]\n       xor\tedx , edx\n       mov\tebx , [ dst_height ]\n       idiv\t[ dst_height ]\n       imul\teax , [ src_win_width ]\n       neg\tebx\n       mov\t[ dy_intr ] , eax\n       mov\t[ dy_frac ] , edx\n       mov\t[ dy_acc ]  , ebx\n\n       mov\teax , [ src_width ]\n       xor\tedx , edx\n       shl\teax , 16\n       idiv\t[ dst_width ]\n       xor\tedx , edx\n       shld\tedx , eax , 16\n       shl\teax , 16\n\n       mov\tecx , [ dst_y1 ]\n       mov\tebx , [ dst_x1 ]\n       sub\tecx , [ dst_y0 ]\n       jle\t??all_done\n       sub\tebx , [ dst_x0 ]\n       jle\t??all_done\n\n       mov\t[ counter_y ] , ecx\n\n       cmp\t[ trans ] , 0\n       jnz\t??transparency\n\n       cmp\t[ remap ] , 0\n       jnz\t??normal_remap\n\n; *************************************************************************\n; normal scale\n       mov\tecx , ebx\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 2 ]\n       shr\tebx , 5\n       neg\tecx\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??ref_point + ecx + ecx * 2 ]\n       mov\t[ entry ] , ecx\n\n ??outter_loop:\n       push\tesi\n       push\tedi\n       xor\tecx , ecx\n       mov\tebx , [ counter_x ]\n       jmp\t[ entry ]\n ??inner_loop:\n       REPT\t32\n\t       mov\tcl , [ esi ]\n\t       add\tecx , eax\n\t       adc\tesi , edx\n\t       mov\t[ edi ] , cl\n\t       inc\tedi\n       ENDM\n ??ref_point:\n       dec\tebx\n       jge\t??inner_loop\n\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??skip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??skip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??outter_loop\n\tret\n\n\n; *************************************************************************\n; normal scale with remap\n\n??normal_remap:\n       mov\tecx , ebx\n       mov\t[ dx_frac ], eax\n       and\tecx , 01fh\n       mov\teax , [ remap ]\n       shr\tebx , 5\n       imul\tecx , - 13\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??remapref_point + ecx ]\n       mov\t[ entry ] , ecx\n\n ??remapoutter_loop:\n       mov\tebx , [ counter_x ]\n       push\tesi\n       mov\t[ remap_counter ] , ebx\n       push\tedi\n       xor\tecx , ecx\n       xor\tebx , ebx\n       jmp\t[ entry ]\n ??remapinner_loop:\n       REPT\t32\n\t       mov\tbl , [ esi ]\n\t       add\tecx , [ dx_frac ]\n\t       adc\tesi , edx\n\t       mov\tcl , [ eax + ebx ]\n\t       mov\t[ edi ] , cl\n\t       inc\tedi\n       ENDM\n ??remapref_point:\n       dec\t[ remap_counter ]\n       jge\t??remapinner_loop\n\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??remapskip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??remapskip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??remapoutter_loop\n\tret\n\n\n;****************************************************************************\n; scale with trnsparency\n\n??transparency:\n       cmp\t[ remap ] , 0\n       jnz\t??trans_remap\n\n; *************************************************************************\n; normal scale with transparency\n       mov\tecx , ebx\n       and\tecx , 01fh\n       imul\tecx , -13\n       shr\tebx , 5\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??trans_ref_point + ecx ]\n       mov\t[ entry ] , ecx\n\n ??trans_outter_loop:\n       xor\tecx , ecx\n       push\tesi\n       push\tedi\n       mov\tebx , [ counter_x ]\n       jmp\t[ entry ]\n ??trans_inner_loop:\n       REPT\t32\n       local\ttrans_pixel\n\t       mov\tcl , [ esi ]\n\t       test\tcl , cl\n\t       jz\ttrans_pixel\n\t       mov\t[ edi ] , cl\n       trans_pixel:\n\t       add\tecx , eax\n\t       adc\tesi , edx\n\t       inc\tedi\n       ENDM\n ??trans_ref_point:\n       dec\tebx\n       jge\t??trans_inner_loop\n\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??trans_skip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??trans_skip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??trans_outter_loop\n\tret\n\n\n; *************************************************************************\n; normal scale with remap\n\n??trans_remap:\n       mov\tecx , ebx\n       mov\t[ dx_frac ], eax\n       and\tecx , 01fh\n       mov\teax , [ remap ]\n       shr\tebx , 5\n       imul\tecx , - 17\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??trans_remapref_point + ecx ]\n       mov\t[ entry ] , ecx\n\n ??trans_remapoutter_loop:\n       mov\tebx , [ counter_x ]\n       push\tesi\n       mov\t[ remap_counter ] , ebx\n       push\tedi\n       xor\tecx , ecx\n       xor\tebx , ebx\n       jmp\t[ entry ]\n ??trans_remapinner_loop:\n       REPT\t32\n       local\ttrans_pixel\n\t       mov\tbl , [ esi ]\n\t       test\tbl , bl\n\t       jz\ttrans_pixel\n\t       mov\tcl , [ eax + ebx ]\n\t       mov\t[ edi ] , cl\n\t  trans_pixel:\n\t       add\tecx , [ dx_frac ]\n\t       adc\tesi , edx\n\t       inc\tedi\n       ENDM\n ??trans_remapref_point:\n       dec\t[ remap_counter ]\n       jge\t??trans_remapinner_loop\n\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??trans_remapskip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??trans_remapskip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??trans_remapoutter_loop\n\tret\n\n\n\n\n\n??all_done:\n\tret\nendp\n\n\nEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/SETFPAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : 32 bit library Text Print                *\n;*                                                                         *\n;*                    File Name : TEXTPRNT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : July 2, 1994                             *\n;*                                                                         *\n;*                  Last Update : July 2, 1994   [SKB]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Text_Print -- Assembly text print routine.                            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nGLOBAL  C ColorXlat:BYTE\nGLOBAL\tC Set_Font_Palette_Range:NEAR\n\n\tCODESEG\n\n;***********************************************************\n; SET_FONT_PALETTE_RANGE\n;\n; VOID Set_Font_Palette_Range(VOID *palette, WORD start, WORD end);\n;\n; This routine changes the local Draw_Char color translation table\n; with the color numbers in palette.\n;\n; Bounds Checking: forces start and end to a range of 0-15\n;*\n\tPROC\tSet_Font_Palette_Range C near\n\tUSES\teax, ebx, ecx,edi,esi\n\tARG\tpalette:DWORD\n\tARG\tstart:DWORD\n\tARG\tendval:DWORD\n\n\tcld\n\n\tmov\tesi,[palette]\n\n\tmov\tebx,[start]\n\tand\tebx,0FH\t\t\t; value 0-15\n\n\tmov\tecx,[endval]\n\tand\tecx,0FH\t\t\t; value 0-15\n\n\tcmp\tecx,ebx\t\t\t; if end < start then exit\n\tjl\tshort ??exit\n\n\tsub\tecx,ebx\t\t\t; number of colors = end - start + 1\n\tinc\tecx\n\n\tmov\tedi,OFFSET ColorXlat\t; get start of xlat table\n\tadd\tedi,ebx\t\t\t; add starting offset\n\tshl\tebx,4\t\t\t; multiply start offset by 16\n\tadd\tebx,OFFSET ColorXlat\t; add start of xlat table\n\n; updates 0-15 for lonibble xlat\n; updates 0,16,32,...,240 for hinibble xlat\n\n??setpal:\n\tlodsb\t\t\t\t; get color number\n\tstosb\t\t\t\t; save color number for lonibble xlat\n\tmov\t[ebx],al\t\t; save color number for hinibble xlat\n\tadd\tebx,010H    \t\t; add 16 to index for hinibble offset\n\tdec\tecx\n\tjnz\t??setpal\n\n??exit:\n\tret\n\n\tENDP\tSet_Font_Palette_Range\n\n;***********************************************************\n\n\n;***********************************************************\n\n\tEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/SETSHAPE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : WWLIB32                                  *\n;*                                                                         *\n;*                    File Name : SETSHAPE.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : October 26, 1994                         *\n;*                                                                         *\n;*                  Last Update : October 26, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Set_Shape_Buffer -- Sets the shape buffer to the given pointer        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\nCODESEG\n\n;***************************************************************************\n;* SET_SHAPE_BUFFER -- Sets the shape buffer to the given pointer          *\n;*                                                                         *\n;* This routine will set the shape buffer to the given value and make sure *\n;* that the system does not try to compress any shapes that will be larger *\n;* than the shape buffer.\t\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tvoid * - pointer to the shape buffer                       *\n;*\t\tint    - size of the buffer which has been passed in\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       VOID *Set_Shape_Bufer(void *buffer, int size);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/26/1994 PWG : Created.                                             *\n;*=========================================================================*\nGLOBAL\tSet_Shape_Buffer:NEAR\n\nPROC\tSet_Shape_Buffer C near \n\tUSES\teax\n\n\tARG\tbuff:DWORD\n\tARG\tsize:DWORD\n\n\tmov\teax,[size]\n\tmov\t[_ShapeBufferSize],eax\n\n\tmov\teax,[buff]\n\tmov\t[_ShapeBuffer],eax\n\tret\n\n\tENDP\tSet_Shape_Buffer\nEND\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/SET_FONT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : SET_FONT.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : September 6, 1991                        *\n *                                                                         *\n *                  Last Update : June 29, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Set_Font -- Changes the default text printing font.                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"font.h\"\n#include <wwstd.h>\n\n\n\n/***************************************************************************\n * SET_FONT -- Changes the default text printing font.                     *\n *                                                                         *\n *    This routine will change the default text printing font for all      *\n *    text output.  It handles updating the system where necessary.        *\n *                                                                         *\n * INPUT:   fontptr  -- Pointer to the font to change to.                  *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the previous font.                   *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/06/1991 JLB : Created.                                             *\n *   09/17/1991 JLB : Fixed return value bug.                              *\n *   01/31/1992 DRD : Modified to use new font format.                     *\n *   06/29/1994 SKB : modified for 32 bit library                          *\n *=========================================================================*/\nvoid * __cdecl Set_Font(void const *fontptr)\n{\n\tvoid *oldfont;\n\tchar\tconst *blockptr;\n\n\toldfont = (void *) FontPtr;\n\n\tif (fontptr) {\n\t\tFontPtr    = (void *) fontptr;\n\n\t\t/*\n\t\t**\tInform the system about the new font.\n\t\t*/\n\n\t\tFontWidthBlockPtr = (char*)fontptr + *(unsigned short *)((char*)fontptr + FONTWIDTHBLOCK);\n\t\tblockptr  = (char*)fontptr + *(unsigned short *)((char*)fontptr + FONTINFOBLOCK);\n\t\tFontHeight = *(blockptr + FONTINFOMAXHEIGHT);\n\t\tFontWidth  = *(blockptr + FONTINFOMAXWIDTH);\n\t\t//Draw_Char_Setup();\n\n#if FALSE\n\t\tWindowLines = WinH / FontHeight;\n\t\tWindowWidth = WinW << 3;\n\t\tWindowColumns = WindowWidth / FontWidth;\n#endif\n\t}\n\n\treturn(oldfont);\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/SHADOW.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/source/rcs/./shadow.asm 1.9 1994/05/20 15:30:49 joe_bostic Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : SHADOW.ASM                               *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : February 28, 1995   [BG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n;* void Shadow_Blit(int xpix, int ypix, int width, int height, GVPC src, GVPC dst, void *shadowbuff);\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\nINCLUDE \".\\keystruc.inc\"\n\nGLOBAL\tC Shadow_Blit\t: NEAR\n\nGLOBAL\tC RealModePtr : DWORD\nGLOBAL\tC Hide_Mouse  : NEAR\nGLOBAL\tC Show_Mouse  : NEAR\n\n\tCODESEG\n\n; void Shadow_Blit(int xpix, int ypix, int width, int height, GVPC src, VBC dst, void *shadowbuff);\n; Warning: Shadow_Blit appears to be relatively stupid, in that while it is\n;\t   optimized to perform word or dword blits, it only does so if the\n;\t   entire region is word or dword-sized.  In other words, if you blit\n;\t   a region that is 200 pixels wide (clearly dword-sized), then it\n;\t   will use the dword loop.  However, if you blit a region that is\n;\t   201 pixels wide, the dumb thing will use the byte loop for the\n;\t   entire blit.\n\tPROC    Shadow_Blit C near\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tARG\tx:DWORD\n\tARG\ty:DWORD\n\tARG\tregion_width:DWORD\n\tARG\tregion_height:DWORD\n\tARG     srcpage:DWORD\n\tARG     dstpage:DWORD\n\tARG     shadow:DWORD\n\n\tLOCAL\tmodulo:DWORD\t\t; Row modulo\n\tLOCAL\thidemouse:DWORD\t\t; Was the mouse hidden?\n\tLOCAL\tdwordwidth:DWORD\n\tLOCAL\tbytewidth:DWORD\n\n\tcld                             ; Always move forward.\n\tmov\t[hidemouse],0\t\t; Presume mouse hasn't been hidden.\n\n; Fetch the segment of the seenpage.\n\tmov\tebx,[dstpage]\n\tmov\tebx,[(GraphicViewPort ebx).GVPOffset]\n\n\t; Determine if the mouse needs to be hidden at all.  If this happens to be\n\t; a shadow blit to non visible page (who knows why!?) then don't bother to\n\t; hide the mouse since it isn't necessary.\n;\tcmp\tebx,0A0000h\n;\tsetne\t[BYTE PTR hidemouse]\t; Flag that mouse need not be hidden.\n;\tjne\tshort ??itsok\n\tmov\tesi,[RealModePtr]\n\tcmp\t[(KeyboardType esi).MState],0\n\tje\tshort ??itsok\n\tmov\t[hidemouse],1\n\tcall\tHide_Mouse C\t\t; Hides mouse again (just to be sure).\n??itsok:\n\tmov\tedi,[srcpage]\n\tmov\tesi,[(GraphicViewPort edi).GVPOffset]\n\n\tmov\teax,[(GraphicViewPort edi).GVPWidth]\n\tadd\teax,[(GraphicViewPort edi).GVPXAdd]\n\tadd\teax,[(GraphicViewPort edi).GVPPitch]\n\tpush\teax\t\t\t; save width+xadd for later calc\n\tmov\tedx,[y]\n\tmul\tedx\n\tadd\teax,[x]\n\tadd\tesi,eax\n; At this point, esi points to the source page and ebx points to the dest page\n\tsub\tebx,esi\t\t\t; esi+ebx == dest page pointer\n\n\tmov\tedi,[shadow]             ; EDI points to shadow buffer.\n\n\tmov     ecx,[region_height]\t\t; get the height of the window in cx\n\n\tmov\tedx,[RealModePtr]\n\n\t; Calculate the row add module.\n\tpop\teax\t\t\t; restore width+xadd\n\tsub\teax,[region_width]\n\tmov\t[modulo],eax\n\n\tmov\teax,[region_width]\n\tshr\teax,2\n\tmov\t[dwordwidth],eax\n\tmov\teax,[region_width]\n\tand\teax,3\n\tmov\t[bytewidth],eax\n\n;---------------------------------------\n; DOUBLE WORD shadow blit if possible.\n;---------------------------------------\n??dloop_top:\n\tpush\tecx\n\tmov\tecx,[dwordwidth]\n\n??lcontinue:\n\trepe    cmpsd                   ; check the entire row for changed longs\n\tje      short ??loop_top\n\n\t; If this row would interfere with the mouse image, then hide it.\n\tcmp\t[hidemouse],0\n\tjnz\tshort ??dok\n\tmov\teax,[(KeyboardType edx).MouseY]\n\tsub\teax,[(KeyboardType edx).MouseYHot]\n\tcmp\teax,[y]\n\tjg\tshort ??dok\n\tadd\teax,[(KeyboardType edx).MouseHeight]\n\tcmp\teax,[y]\n\tjb\tshort ??dok\n\tmov\t[hidemouse],1\t\t; Manual hide of the mouse.\n\tcall\tHide_Mouse C\n??dok:\n\n\tmov     eax,[esi-4]\n\tmov     [ebx+esi-4],eax\t\t; Update destination page.\n\tmov     [edi-4],eax\t\t; Update shadow buffer.\n\tor\tecx,ecx\n\tjne     short ??lcontinue\n\n;---------------------------------------\n; Row loop start for BYTES.\n;---------------------------------------\n??loop_top:\n\tmov\tecx,[bytewidth]\n\n; Column loop start -- by bytes.\n??continue:\n\trepe    cmpsb                   ; check the entire row for changed longs\n\tje      short ??done_x\n\n\t; If this row would interfere with the mouse image, then hide it.\n\tcmp\t[hidemouse],0\n\tjnz\tshort ??bok\n\tmov\teax,[(KeyboardType edx).MouseY]\n\tsub\teax,[(KeyboardType edx).MouseYHot]\n\tcmp\teax,[y]\n\tjg\tshort ??bok\n\tadd\teax,[(KeyboardType edx).MouseHeight]\n\tcmp\teax,[y]\n\tjl\tshort ??bok\n\tmov\t[hidemouse],1\t\t; Manual hide of the mouse.\n\tcall\tHide_Mouse C\n??bok:\n\n\tmov     al,[esi-1]\n\tmov     [ebx+esi-1],al\t\t; Update destination page.\n\tmov     [edi-1],al\t\t; Update shadow buffer.\n\n\tor\tecx,ecx\n\tjne     short ??continue\n\n??done_x:\n\tinc\t[y]\n\tadd     esi,[modulo]\n\tpop     ecx\n\tdec\t\tecx\n    jnz\t\t??dloop_top\n\n??fini:\n\t; Re show the mouse if it was hidden by this routine.\n\tcmp\t[hidemouse],0\n\tje\tshort ??reallyfini\n\tcall\tShow_Mouse C\n??reallyfini:\n\tret\n\n\tENDP    Shadow_Blit\n\n\tEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/SHAKESCR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : SHAKESCR.ASM                             *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : August 19, 1993                          *\n;*                                                                         *\n;*                  Last Update : February 10, 1995 [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\tC Shake_Screen\t:NEAR\n\n\tCODESEG\n\n;***********************************************************\n; SHAKE_SCREEN\n;\n; VOID Shake_Screen(int shakes);\n;\n; This routine shakes the screen the number of times indicated.\n;\n; Bounds Checking: None\n;\n;*\n\tPROC\tShake_Screen C near\n\tUSES\tecx, edx\n\n\tARG\tshakes:DWORD\n ret\n\n\tmov\tecx,[shakes]\n\n;;; push es\n;;; mov ax,40h\n;;; mov es,ax\n;;; mov dx,[es:63h]\n;;; pop es\n\tmov\teax,[0463h]\t\t; get CRTC I/O port\n\tmov\tdx,ax\n\tadd\tdl,6\t\t\t; video status port\n\n??top_loop:\n\n??start_retrace:\n\tin\tal,dx\n\ttest\tal,8\n\tjz\t??start_retrace\n\n??end_retrace:\n\tin\tal,dx\n\ttest\tal,8\n\tjnz\t??end_retrace\n\n\tcli\n\tsub\tdl,6\t\t\t; dx = 3B4H or 3D4H\n\n\tmov\tah,01\t\t\t; top word of start address\n\tmov\tal,0Ch\n\tout\tdx,al\n\txchg\tah,al\n\tinc\tdx\n\tout\tdx,al\n\txchg\tah,al\n\tdec\tdx\n\n\tmov\tah,040h\t\t\t; bottom word = 40 (140h)\n\tinc\tal\n\tout\tdx,al\n\txchg\tah,al\n\tinc\tdx\n\tout\tdx,al\n\txchg\tah,al\n\n\tsti\n\tadd\tdl,5\n\n??start_retrace2:\n\tin\tal,dx\n\ttest\tal,8\n\tjz\t??start_retrace2\n\n??end_retrace2:\n\tin\tal,dx\n\ttest\tal,8\n\tjnz\t??end_retrace2\n\n??start_retrace3:\n\tin\tal,dx\n\ttest\tal,8\n\tjz\t??start_retrace3\n\n??end_retrace3:\n\tin\tal,dx\n\ttest\tal,8\n\tjnz\t??end_retrace3\n\n\tcli\n\tsub\tdl,6\t\t\t; dx = 3B4H or 3D4H\n\n\tmov\tah,0\n\tmov\tal,0Ch\n\tout\tdx,al\n\txchg\tah,al\n\tinc\tdx\n\tout\tdx,al\n\txchg\tah,al\n\tdec\tdx\n\n\tmov\tah,0\n\tinc\tal\n\tout\tdx,al\n\txchg\tah,al\n\tinc\tdx\n\tout\tdx,al\n\txchg\tah,al\n\n\tsti\n\tadd\tdl,5\n\n\tloop\t??top_loop\n\n\tret\n\n\tENDP\tShake_Screen\n\n;***********************************************************\n\n\tEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/SHAPE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : WWLIB32                                  *\n;*                                                                         *\n;*                    File Name : SHAPE.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : April 13, 1992                           *\n;*                                                                         *\n;*                  Last Update : September 14, 1994   [IML]               *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Draw_Shape -- Draws a shape at given buffer coordinates and clips     *\n;*   Not_Supported -- Replacement function for Draw_Shape routines not used*\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"shape.inc\"\n\nglobal\tC ShapeBuffer\t\t:dword\nglobal\tC ShapeBufferSize\t:dword\nglobal\tC _ShapeBuffer\t\t:dword\nglobal\tC _ShapeBufferSize\t:dword\nglobal\tC Set_Shape_Buffer\t:near\n\nDATASEG\nlabel\tShapeBuffer\tdword\n_ShapeBuffer\t\tdd\t0\n\nlabel\tShapeBufferSize\tdword\n_ShapeBufferSize\tdd\t0\n\nCODESEG\n\n;***************************************************************************\n;* SET_SHAPE_BUFFER -- Sets the shape buffer to the given pointer          *\n;*                                                                         *\n;* This routine will set the shape buffer to the given value and make sure *\n;* that the system does not try to compress any shapes that will be larger *\n;* than the shape buffer.\t\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tvoid * - pointer to the shape buffer                       *\n;*\t\tint    - size of the buffer which has been passed in\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       VOID *Set_Shape_Bufer(void *buffer, int size);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/26/1994 PWG : Created.                                             *\n;*=========================================================================*\nGLOBAL\tC Set_Shape_Buffer:NEAR\n\nPROC\tSet_Shape_Buffer C near\n\tUSES\teax\n\n\tARG\tbuff:DWORD\n\tARG\tsize:DWORD\n\n\tmov\teax,[size]\n\tmov\t[_ShapeBufferSize],eax\n\n\tmov\teax,[buff]\n\tmov\t[_ShapeBuffer],eax\n\tret\n\n\tENDP\tSet_Shape_Buffer\nEND\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/SOSCODEC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*          Copyright (c) 1994, HMI, INC. All Rights Reserved\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     soscodec.asm\n;*\n;* DESCRIPTION\n;*     HMI SOS ADPCM compression/decompression.\n;*\n;* PROGRAMMER\n;*     Nick Skrepetos\n;*     Denzil E. Long, Jr. (Fixed bugs, rewrote for watcom)\n;*     Bill Petro\t\t   (Added stereo support)\n;*     Jonathan Lanier\n;*\n;* DATE\n;*     Febuary 15, 1995\n;*\n;* LAST MODIFIED\n;*     08/07/95 [jdl] - Rewrote/optimized sosCODECDecompressData\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\nDPMI_INTR\t\tequ\t31h\nIF_LOCKED_PM_CODE\tequ\t1h\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t2h\t\t; Locked PM code for DPMI.\n\nSTRUC\tsCompInfo\nlpSource\t\tDD\t?\t;Compressed data pointer\nlpDest\t\t\tDD\t?\t;Uncompressed data pointer\ndwCompSize\t\tDD\t?\t;Compressed size\ndwUnCompSize\t\tDD\t?\t;Uncompressed size\n\ndwSampleIndex\t\tDD\t?\t;Index into sample\ndwPredicted\t\tDD\t?\t;Next predicted value\ndwDifference\t\tDD\t?\t;Difference from last sample\nwCodeBuf\t\tDW\t?\t;Holds 2 nibbles for decompression\nwCode\t\t\tDW\t?\t;Current 4 bit code\nwStep\t\t\tDW\t?\t;Step value in table\nwIndex\t\t\tDW\t?\t;Index into step table\n\ndwSampleIndex2\t\tDD\t?\t;Index into sample\ndwPredicted2\t\tDD\t?\t;Next predicted value\ndwDifference2\t\tDD\t?\t;Difference from last sample\nwCodeBuf2 \t\tDW\t?\t;Holds 2 nibbles for decompression\nwCode2\t\t\tDW\t?\t;Current 4 bit code\nwStep2\t\t\tDW\t?\t;Step value in table\nwIndex2\t\t\tDW\t?\t;Index into step table\n\nwBitSize\t\tDW\t?\t;Bit size for decompression\nwChannels\t\tDW\t?    \t;number of channels\nENDS\tsCompInfo\n\n\n\tDATASEG\n\n\nInitFlags\tDD\t0\t\t; Flags to indicate what has been initialized.\n\n\nLABEL\tLockedDataStart\tBYTE\n\n;* Index table for stepping into step table\n\nINCLUDE\t\t\"difftb.inc\"\nINCLUDE\t\t\"indextb.inc\"\nINCLUDE\t\t\"nybbtb.inc\"\n\nLABEL\tLockedDataEnd\tBYTE\n\n\tCODESEG\n\nLABEL\tLockedCodeStart\tBYTE\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECInitStream - Initialize compression stream.\n;*\n;* SYNOPSIS\n;*     sosCODECInitStream(CompInfo)\n;*\n;*     void sosCODECInitStream(_SOS_COMPRESS_INFO *);\n;*\n;* FUNCTION\n;*     Initialize compression stream for compression and decompression.\n;*\n;* INPUTS\n;*     CompInfo - Compression information structure.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tsosCODECInitStream:NEAR\n\tPROC\tsosCODECInitStream C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\n\tmov\teax,[sSOSInfo]\n\tmov\t[(sCompInfo eax).wIndex],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).dwPredicted],0 \t; no predicted value\n\tmov\t[(sCompInfo eax).wIndex2],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).dwPredicted2],0 \t; no predicted value\n\tret\n\n\tENDP\tsosCODECInitStream\n\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECDecompressData - Decompress audio data.\n;*\n;* SYNOPSIS\n;*     Size = sosCODECDecompressData(CompInfo, NumBytes)\n;*\n;*     long sosCODECDecompressData(_SOS_COMPRESS_INFO *, long);\n;*\n;* FUNCTION\n;*     Decompress data from a 4:1 ADPCM compressed stream. The number of\n;*     bytes decompressed is returned.\n;*\n;* INPUTS\n;*     CompInfo - Compress information structure.\n;*     NumBytes - Number of bytes to decompress.\n;*\n;* RESULT\n;*     Size - Size of decompressed data.\n;*\n;*\n;* NOTES\n;*     This routine has been optimized for pipelining on both\n;*     486 and Pentium processors.  Changing, inserting, or moving any\n;*     instructions will most likely slow down the code, in some cases by\n;*     as much as 20%.  It can burst-decompress 16384 samples in about\n;*     1940s on a Pentium 90Mhz, and about 3960s on a 486 66Mhz.\n;*     Instruction reordering could bring this down to below 1870s on\n;*     the Pentium, but this would cause a great degradation in 486\n;*     performance.  Since slow 486's are the reason this code was\n;*     written to be fast, it has been optimized for the Pentium only where\n;*     it would not degrade 486 performance.  So, be careful when changing\n;*     ANY of this code, because it is very carefully balanced...\n;****************************************************************************\n\n\tGLOBAL\tC sosCODECDecompressData:NEAR\n\tPROC\tsosCODECDecompressData C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\tARG\twBytes:DWORD\n\n\tpush\tesi\n\tpush\tedi\n\tpush\tebx\n\tpush\tecx\n\tpush\tedx\t\t\t;save all the regs\n\n\tmov\tebx,[sSOSInfo]\t\t;get base of sCompInfo struct\n\tmov\tcx,[(sCompInfo ebx).wBitSize] ;check the bit size\n\tmov\tdx,[(sCompInfo ebx).wChannels] ;check the number of channels\n;\n;\n; Determine the correct routine to use for decoding\n; (for now only ADPCM 4:1 Mono 16-bit is implemented)\n\tcmp\tcx,8\n\tjne\t??do16Bits\n\n??do8Bits:\n\tcmp\tdx,2\n\tjne\t??not8Stereo\n;\tjmp\t??decomp8Stereo\n\tjmp\t??byeBye\n\n??not8Stereo:\n\tcmp\tdx,1\n\tjne\t??byeBye\n;\tjmp\tdecomp8Mono\n\tjmp\t??byeBye\n\n??do16Bits:\n\tcmp\tcx,16\n\tjne\t??byeBye\n\n\tcmp\tdx,2\n\tjne\t??not16Stereo\n;\tjmp\t??decomp16Stereo\n\tjmp\t??byeBye\n\n??not16Stereo:\n\tcmp\tdx,1\n\tjne\t??byeBye\n\n\tpush\tebp\n;\n;\n; 16 bit ADPCM 4:1 Mono pre-loop initialization\n??decomp16Mono:\n\tpush\tebx\t\t\t;save struct base\n\txor\tedx,edx\t\t\t;clear index\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\t;get last sample\n\tmov\tdx,[(sCompInfo ebx).wIndex]\t;get last index value\n\tmov\tesi,[(sCompInfo ebx).lpSource]\t;get source address\n\tmov\tedi,[(sCompInfo ebx).lpDest]\t;get dest address\n\n\tmov\tebp,[wBytes]\t\t;get the number of dest. bytes\n\tcmp\tebp,16\t\t\t;less than 16? (less than 8 samples)\n\tjl\t??fixAlign16Mono0\t;if so, don't bother with alignment\n;\n;\n; Check to see if we need to fix an alignment problem on the source buffer\n; (non-aligned buffers are MUCH slower; if we're given a non-DWORD aligned\n; source address, we do as many samples as needed to get to the nearest\n; DWORD boundary, then finish the bulk as a DWORD-aligned decompress).\n\tmov\tebx,esi\t\t\t;get source address\n\tand\tebx,03h\t\t\t;check LSB\n\tjnz\t??fixalign16Mono\t;if non-zero, need to align for\n\t\t\t\t\t;warp speed\n??fixAlign16Mono0:\n\tpush\tebp\t\t\t;save for later\n\tshr\tebp,4\t\t\t;divide by 16 for 16-bit,\n\t\t\t\t\t;because we do 8 nybbles per loop,\n\t\t\t\t\t;and there are two samples per\n\t\t\t\t\t;byte, so there are n/16 iterations\n\t\t\t\t\t;required\n\txor\tebx,ebx\t\t\t;clear our nybble index\n\tor\tebp,ebp\t\t\t;set flags for EBP\n\tjmp\t??start16Mono\t\t;start with test... don't go if\n\t\t\t\t\t;we have zero bytes to do\n??fixalign16Mono:\n\tjmp\t[DWORD PTR dwMono16AlignJmpTable+ebx*4] ;do non-aligned first\n\n\talign\t4\n??fixAlign16Mono1:\n\tsub\tebp,12\t\t\t;adjust # of dest. bytes\n\tpush\tebp\t\t\t;save it\n\tshr\tebp,4\t\t\t;divide by 16 to get samples/8\n\txor\tebx,ebx\t\t\t;clear our nybble index\n\tinc\tebp\t\t\t;adjust ebp for loop\n\tjmp\t??finish16Mono6\t\t;borrow exit code to go through a\n\t\t\t\t\t;piece of a loop\n\talign\t4\n??fixAlign16Mono2:\n\tsub\tebp,8\t\t\t;adjust # of dest. bytes\n\tpush\tebp\t\t\t;save it\n\tshr\tebp,4\t\t\t;divide by 16 to get samples/8\n\txor\tebx,ebx\t\t\t;clear our nybble index\n\tinc\tebp\t\t\t;adjust ebp for loop\n\tjmp\t??finish16Mono4\t\t;borrow exit code to go through a\n\t\t\t\t\t;piece of a loop\n\talign\t4\n??fixAlign16Mono3:\n\tsub\tebp,4\t\t\t;adjust # of dest. bytes\n\tpush\tebp\t\t\t;save it\n\tshr\tebp,4\t\t\t;divide by 16 to get samples/8\n\txor\tebx,ebx\t\t\t;clear our nybble index\n\tinc\tebp\t\t\t;adjust ebp for loop\n\tjmp\t??finish16Mono2\t\t;borrow exit code to go through a\n\t\t\t\t\t;piece of a loop\n; \"The Loop\"\n;\n; Process 1st nybble\n\talign\t4\n??loop16Mono:\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix1Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix1Smp16MonoU\n??fixed1Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tmov\t[edi],ax\t\t;save the sample\n;\n;\n; Process 2nd nybble\n??finish7Smp16Mono:\n\tmov\tbl,ch\t\t\t;get next 2 nybbles in ebx\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix2Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix2Smp16MonoU\n??fixed2Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tmov\t[edi+02h],ax\t\t;save the sample\n\tshr\tecx,16\t\t\t;move top four nybbles into bottom\n;\n;\n; Process 3rd nybble\n??finish6Smp16Mono:\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix3Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix3Smp16MonoU\n??fixed3Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tmov\t[edi+04h],ax\t\t;save the sample\n;\n;\n; Process 4th nybble\n??finish5Smp16Mono:\n\tmov\tbl,cl\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix4Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix4Smp16MonoU\n??fixed4Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tmov\t[edi+06h],ax\t\t;save the sample\n;\n;\n; Process 5th nybble\n??finish4Smp16Mono:\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix5Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix5Smp16MonoU\n??fixed5Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tmov\t[edi+08h],ax\t\t;save the sample\n;\n;\n; Process 6th nybble\n??finish3Smp16Mono:\n\tmov\tbl,ch\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix6Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix6Smp16MonoU\n??fixed6Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tmov\t[edi+0Ah],ax\t\t;save the sample\n;\n;\n; Process 7th nybble\n??finish2Smp16Mono:\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix7Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix7Smp16MonoU\n??fixed7Smp16Mono:\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tmov\t[edi+0Ch],ax\t\t;save the sample\n;\n;\n; Process 8th nybble\n??finish1Smp16Mono:\n\tadd\teax,[dwDiffTable+edx*2]\t;add difference to prev. sample\n\tmov\tdx,[wIndexTable+edx]\t;adjust dx to next index base\n\tcmp\teax,00007FFFh\t\t;check for overflow\n\tjg\t??fix8Smp16MonoO\n\tcmp\teax,0FFFF8000h\t\t;check for underflow\n\tjl\t??fix8Smp16MonoU\n;\n;\n; Loop cleanup for next pass\n??fixed8Smp16Mono:\n\tmov\t[edi+0Eh],ax\t\t;save the sample\n\tadd\tesi,04h\t\t\t;bump esi to point to next longword\n\tadd\tedi,10h\t\t\t;incr. the destination buffer ptr\n\tdec\tebp\t\t\t;count down the number of samples/8\n??start16Mono:\n\tjng\t??cleanup16Mono\t\t;if done, clean up\n\tmov\tecx,[esi]\t\t;get 4 nybbles in one whack (whee!)\n\tmov\tbl,cl\t\t\t;get next 2 nybbles in ebx\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tjmp\t??loop16Mono\t\t;loop until done\n\n??cleanup16Mono:\n\tjnz\t??done16Mono\t\t;if ebp is non-zero, we're DONE\n\t\t\t\t\t;if exactly zero, finish the tail-end\n\t\t\t\t\t;of the conversion (may be a non-\n\t\t\t\t\t;multiple of 8 nybbles)\n;\n;\n; Loop cleanup for last (incomplete) pass\n\tpop\tecx\t\t\t;restore # of words\n\tshr\tecx,1\t\t\t;divide by two to get samples\n\tand\tecx,07h\t\t\t;get # of samples we missed\n\tjmp\t[DWORD PTR dwMono16JmpTable+ecx*4] ;go finish the job...\n;\n;\n; Structure cleanup\n??done16Mono:\n\tpop\tebx\t\t\t;restore struct base\n\tpop\tebp\t\t\t;restore stack frame pointer\n\tmov\t[(sCompInfo ebx).dwPredicted],eax ;save last sample\n\tmov\t[(sCompInfo ebx).wIndex],dx ;save last index value\n\tmov\teax,[wBytes]\t\t;get # of bytes we did\n??byeBye:\n\tpop\tedx\t\t\t;restore all the regs\n\tpop\tecx\n\tpop\tebx\n\tpop\tedi\n\tpop\tesi\n\tret\n;\n;\n; Jumps for -32768/+32767 bounds check go to these vvvv\n\talign\t4\n??fix1Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed1Smp16Mono\t;go back\n\n\talign\t4\n??fix1Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed1Smp16Mono\t;go back\n\n\talign\t4\n??fix2Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed2Smp16Mono\t;go back\n\n\talign\t4\n??fix2Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed2Smp16Mono\t;go back\n\n\talign\t4\n??fix3Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed3Smp16Mono\t;go back\n\n\talign\t4\n??fix3Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed3Smp16Mono\t;go back\n\n\talign\t4\n??fix4Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed4Smp16Mono\t;go back\n\n\talign\t4\n??fix4Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed4Smp16Mono\t;go back\n\n\talign\t4\n??fix5Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed5Smp16Mono\t;go back\n\n\talign\t4\n??fix5Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed5Smp16Mono\t;go back\n\n\talign\t4\n??fix6Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed6Smp16Mono\t;go back\n\n\talign\t4\n??fix6Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed6Smp16Mono\t;go back\n\n\talign\t4\n??fix7Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed7Smp16Mono\t;go back\n\n\talign\t4\n??fix7Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed7Smp16Mono\t;go back\n\n\talign\t4\n??fix8Smp16MonoO:\n\tmov\teax,00007FFFh\t\t;Overflow - truncate to +32767\n\tjmp\t??fixed8Smp16Mono\t;go back\n\n\talign\t4\n??fix8Smp16MonoU:\n\tmov\teax,0FFFF8000h\t\t;Underflow - truncate to -32768\n\tjmp\t??fixed8Smp16Mono\t;go back\n;\n;\n; Jump tables for cleanup after loop unroll point to these vvvv\n\talign\t4\n??finish16Mono1:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tch,[esi]\t\t;get 1 nybble (1 byte)\n\tshl\tch,4\t\t\t;move it over\n\tmov\tbl,ch\t\t\t;get nybble in ebx\n\tsub\tedi,0Eh\t\t\t;back edi up\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tjmp\t??finish1Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono2:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tch,[esi]\t\t;get 2 nybbles (1 byte)\n\tmov\tbl,ch\t\t\t;get nybbles in ebx\n\tsub\tedi,0Ch\t\t\t;back edi up\n\tsub\tesi,3\t\t\t;adjust esi (used for dword aligning)\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tjmp\t??finish2Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono3:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tcx,[esi]\t\t;get 3 nybbles (2 bytes)\n\tshl\tcx,4\t\t\t;move it over\n\tmov\tbl,cl\t\t\t;get nybbles in ebx\n\tsub\tedi,0Ah\t\t\t;back edi up\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tjmp\t??finish3Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono4:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tcx,[esi]\t\t;get 4 nybbles (2 bytes)\n\tmov\tbl,cl\t\t\t;get nybbles in ebx\n\tsub\tedi,08h\t\t\t;back edi up\n\tsub\tesi,2\t\t\t;adjust esi (used for dword aligning)\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tjmp\t??finish4Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono5:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tcl,[esi+2]\t\t;get 1 nybble (1 byte)\n\tshl\tecx,16\t\t\t;shift it over\n\tmov\tcx,[esi]\t\t;get 4 nybbles (2 bytes)\n\tmov\tbl,cl\t\t\t;get nybbles in ebx\n\tshr\tecx,4\t\t\t;move it over\n\tshl\tbl,4\t\t\t;move it over\n\tsub\tedi,06h\t\t\t;back edi up\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tjmp\t??finish5Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono6:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tcl,[esi+2]\t\t;get 2 nybbles (1 byte)\n\tshl\tecx,16\t\t\t;move it over\n\tmov\tcx,[esi]\t\t;get 4 nybbles (2 bytes)\n\tmov\tbl,cl\t\t\t;get nybbles in ebx\n\tshr\tecx,8\t\t\t;move it over\n\tsub\tesi,1\t\t\t;adjust esi (used for dword aligning)\n\tsub\tedi,04h\t\t\t;back edi up\n\tor\tdl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble\n\tjmp\t??finish6Smp16Mono\t;go finish it\n\n\talign\t4\n??finish16Mono7:\n\txor\tecx,ecx\t\t\t;clear nybble bucket\n\tmov\tecx,[esi]\t\t;get 7 nybbles (4 bytes)\n\tshl\tecx,4\t\t\t;move it over\n\tmov\tbl,cl\t\t\t;get nybbles in ebx\n\tsub\tedi,02h\t\t\t;back edi up\n\tor\tdl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble\n\tjmp\t??finish7Smp16Mono\t;go finish it\n;\n;\n; Jump Tables\n\t\t\talign 4\n\ndwMono16JmpTable\tDD\t??done16Mono\n\t\t\tDD\t??finish16Mono1\n\t\t\tDD\t??finish16Mono2\n\t\t\tDD\t??finish16Mono3\n\t\t\tDD\t??finish16Mono4\n\t\t\tDD\t??finish16Mono5\n\t\t\tDD\t??finish16Mono6\n\t\t\tDD\t??finish16Mono7\n\n\t\t\talign 4\ndwMono16AlignJmpTable\tDD\t??fixAlign16Mono0\n\t\t\tDD\t??fixAlign16Mono1\n\t\t\tDD\t??fixAlign16Mono2\n\t\t\tDD\t??fixAlign16Mono3\n\n\tENDP\tsosCODECDecompressData\n\nLABEL\tLockedCodeEnd\tBYTE\n\n;***************************************************************************\n;* sosCODEC_LOCK -- locks the JLB audio decompression code\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is lock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:       BOOL sosCODEC_Lock(void);                         \t   *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tsosCODEC_Lock:NEAR\n\tPROC\tsosCODEC_Lock C NEAR USES ebx ecx edx esi edi\n\n\t;\n\t; Lock the code that is used by the sos decompression method.\n\t;\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n  \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags], IF_LOCKED_PM_CODE\n\n\t;\n\t; Lock the data used by the sos decompression method.\n\t;\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags], IF_LOCKED_PM_DATA\n\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\tENDP\tsosCODEC_Lock\n\n;***************************************************************************\n;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code       *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is unlock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:\tBOOL sosCODEC_Unlock(void);                        \t   *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tsosCODEC_Unlock:NEAR\n\tPROC\tsosCODEC_Unlock C NEAR USES ebx ecx edx esi edi\n\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\n??code_not_locked:\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??data_not_locked:\n\tmov\t[InitFlags],0\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\tENDP\tsosCODEC_Unlock\n\n\tEND\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/SOUNDINT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDINT.CPP                             *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 28, 1995   [PWG]                    *\n *                                                                         *\n * This module contains all of the functions that are used within our      *\n * sound interrupt.  They are stored in a seperate module because memory\t*\n * around these functions must be locked or they will cause a read to\t\t*\n * be generated while in an interrupt.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Simple_Copy -- Copyies 1 or 2 source chuncks to a dest                *\n *   Sample_Copy -- Copies sound data from source format to raw format.    *\n *   DigiCallback -- Low level double buffering handler.                   *\n *   save_my_regs -- Inline function which will save assembly regs         *\n *   restore_my_regs -- Inline function which will restore saved registes  *\n *   Audio_Add_Long_To_Pointer -- Adds an offset to a ptr casted void      *\n *   Init_Locked_Data -- Initializes sound driver locked data              *\n *   Audio_Mem_Set -- Quick see routine to set memory to a value           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n#pragma pack(4)\n#define WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#include\t<windows.h>\n#include\t<windowsx.h>\n#include\t\"dsound.h\"\n#include\t<wwstd.h>\n#include \"soundint.h\"\n#include \"memflag.h\"\n#include \"audio.h\"\n\nextern\tDebugBuffer[];\n\n/***************************************************************************\n** All routines past this point must be locked for the sound driver to\t  **\n** function under a VCPI memory manager.  These locks are unnecessary if  **\n** the driver does not have to run under windows or does not use virtual  **\n** memory.                                                                **\n***************************************************************************/\n\n\n\n/***************************************************************************\n * SIMPLE_COPY -- Copyies 1 or 2 source chuncks to a dest                  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nlong Simple_Copy(void ** source, long * ssize, void ** alternate, long * altsize, void **dest, long size)\n{\n\n\n\tlong\tout = 0;\t\t// Number of bytes copied to the destination.\n\n\t/*\n\t**\tIt could happen that entering this routine, the source buffer\n\t**\thas been exhausted, but the alternate buffer is still valid.\n\t**\tMove the alternate into the primary position before proceeding.\n\t*/\n\tif (!(*ssize)) {\n\t\t*source = *alternate;\n\t\t*ssize = *altsize;\n\t\t*alternate = NULL;\n\t\t*altsize = 0;\n\t}\n\n\tif (*source && *ssize) {\n\t\tlong\ts;\t\t\t\t// Scratch length var.\n\n\t\t/*\n\t\t**\tCopy as much as possible from the primary source, but no\n\t\t**\tmore than the primary source has to offer.\n\t\t*/\n\t\ts = size;\n\t\tif (*ssize < s) s = *ssize;\n\t\tMem_Copy(*source, *dest, s);\n\t\t*source = Audio_Add_Long_To_Pointer(*source, s);\n\t\t*ssize -= s;\n\t\t*dest = Audio_Add_Long_To_Pointer(*dest, s);\n\t\tsize -= s;\n\t\tout += s;\n\n\t\t/*\n\t\t**\tIf the primary source was insufficient to fill the request, then\n\t\t**\tmove the alternate into the primary position and try again.\n\t\t*/\n\t\tif (size) {\n\t\t\t*source = *alternate;\n\t\t\t*ssize = *altsize;\n\t\t\t*alternate = 0;\n\t\t\t*altsize = 0;\n\t\t\tout += Simple_Copy(source, ssize, alternate, altsize, dest, size);\n\t\t}\n\t}\n\n\treturn(out);\n}\n\n/***********************************************************************************************\n * Sample_Copy -- Copies sound data from source format to raw format.                          *\n *                                                                                             *\n *    This routine is used to copy the sound data (possibly compressed) to the destination     *\n *    buffer in raw format.                                                                    *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the source data (possibly compressed).                      *\n *                                                                                             *\n *          dest     -- Pointer to the destination buffer.                                     *\n *                                                                                             *\n *          size     -- The size of the destination buffer.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes placed into the output buffer.  This is usually   *\n *          the number of bytes requested except in the case when the source is exhausted.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/03/1994 JLB : Created.                                                                 *\n *   09/04/1994 JLB : Revamped entirely.                                                       *\n *=============================================================================================*/\n#pragma argsused\nlong Sample_Copy(SampleTrackerType *st, void ** source, long * ssize, void ** alternate, long * altsize, void * dest, long size, SCompressType scomp, void * , short int *)\n{\n\n\tlong\ts;\n\tlong\tdatasize = 0;\t\t// Output bytes.\n\n\tswitch (scomp) {\n\t\tdefault:\n\n\t\tcase SCOMP_NONE:\n\t\t\tdatasize = Simple_Copy(source, ssize, alternate, altsize, &dest, size);\n\t\t\tbreak;\n\n\t\tcase SCOMP_WESTWOOD:\n\t\tcase SCOMP_SOS:\n\t\t\twhile (size > 0) {\n\n\t\t\t\t/*\n\t\t\t\t**\tThe block spans two buffers.  It must be copied down to\n\t\t\t\t**\ta staging area before it can be decompressed.\n\t\t\t\t*/\n\t\t\t\t{\n\t\t\t\t\tlong magic;\n\t\t\t\t\tunsigned short fsize;\n\t\t\t\t\tunsigned short dsize;\n\t\t\t\t\tvoid *fptr;\n\t\t\t\t\tvoid *dptr;\n\t\t\t\t\tvoid *mptr;\n\n\t\t\t\t\tfptr = &fsize;\n\t\t\t\t\tdptr = &dsize;\n\t\t\t\t\tmptr = &magic;\n\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &fptr, sizeof(fsize));\n\t\t\t\t\tif (s < sizeof(fsize)) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &dptr, sizeof(dsize));\n\t\t\t\t\tif (s < sizeof(dsize) || size < dsize) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &mptr, sizeof(magic));\n\t\t\t\t\tif (s < sizeof(magic) || magic != LockedData.MagicNumber) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the frame and uncompressed data size are identical, then this\n\t\t\t\t\t**\tindicates that the frame is not compressed.  Just copy it directly\n\t\t\t\t\t**\tto the destination buffer in this case.\n\t\t\t\t\t*/\n\t\t\t\t\tif (fsize == dsize) {\n\t\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &dest, fsize);\n\t\t\t\t\t\tif (s < dsize) {\n\t\t\t\t\t\t\treturn (datasize);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tThe frame was compressed, so copy it to the staging buffer, and then\n\t\t\t\t\t\t**\tuncompress it into the final destination buffer.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tfptr = LockedData.UncompBuffer;\n\t\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &fptr, fsize);\n\t\t\t\t\t\tif (s < fsize) {\n\t\t\t\t\t\t\treturn (datasize);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (scomp == SCOMP_WESTWOOD) {\n\t\t\t\t\t\t\tDecompress_Frame(LockedData.UncompBuffer, dest, dsize);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tst->sosinfo.lpSource = (char *)LockedData.UncompBuffer;\n\t\t\t\t\t\t\tst->sosinfo.lpDest\t = (char *)dest;\n\t\t\t\t\t\t\tif (st->sosinfo.wBitSize==16 && st->sosinfo.wChannels==1){\n\t\t\t\t\t\t\t\tsosCODECDecompressData(&st->sosinfo, dsize);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tGeneral_sosCODECDecompressData(&st->sosinfo, dsize);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdest = Audio_Add_Long_To_Pointer(dest, dsize);\n\t\t\t\t\t}\n\t\t\t\t\tdatasize += dsize;\n\t\t\t\t\tsize -= dsize;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak;\n\t}\n\treturn(datasize);\n}\n\n\n\n\n\n\nextern int Convert_HMI_To_Direct_Sound_Volume(int volume);\n\n/***********************************************************************************************\n * maintenance_callback -- routine to service the direct play secondary buffers                *\n *                         and other stuff..?                                                  *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *     ....Unknown                                                                             *\n *    10/17/95 10:15PM ST : tidied up a tad for direct sound                                   *\n *=============================================================================================*/\nVOID far __cdecl maintenance_callback(VOID)\n{\n\n\tint\t\t\t\t\tindex;\t\t\t\t//index used in for loop\n\tSampleTrackerType\t*st;\t\t\t\t\t//ptr to SampleTracker structure\n\tDWORD\t\t\t\t\tplay_cursor;\t\t//Position that direct sound is reading from\n\tDWORD\t\t\t\t\twrite_cursor;\t\t//Position in buffer that we can write to\n\tint\t\t\t \t\tbytes_copied;\t\t//Number of bytes copied into the buffer\n\tBOOL\t\t\t\t\twrite_more;\t\t\t//Flag to set if we need to write more into the buffer\n\tLPVOID\t\t\t\tplay_buffer_ptr;\t//Beginning of locked area of buffer\n\tLPVOID\t\t\t\tdummy_buffer_ptr;\t//Length of locked area in buffer\n\tDWORD\t\t\t\t\tlock_length1;\t\t//Beginning of second locked area in buffer\n\tDWORD\t\t\t\t\tlock_length2;\t\t//Length of second locked area in buffer\n\tHRESULT\t\t\t\treturn_code;\n\n\t//EnterCriticalSection(&GlobalAudioCriticalSection);\n\n\tst = &LockedData.SampleTracker[0];\n\tfor (index = 0; index < MAX_SFX; index++) {\n\n\t\tif (st->Active) {\n\n\t\t\t/*\n\t\t\t**\tGeneral service routine to handle moving small blocks from the\n\t\t\t**\tsource into the direct sound buffers.  If the source is\n\t\t\t**\tcompressed, then this will also uncompress it as the copy\n\t\t\t**\tis performed.\n\t\t\t*/\n\t\t\tif (st->Service && !st->DontTouch ) {\n\n\t\t\t\t//EnterCriticalSection (&st->AudioCriticalSection);\n\n\t\t\t\tst->DontTouch = TRUE;\n\n\t\t\t\t/*\n\t\t\t\t** Get the current position of the direct sound play cursor within the buffer\n\t\t\t\t*/\n\t\t\t\treturn_code = st->PlayBuffer->GetCurrentPosition ( &play_cursor , &write_cursor );\n\n\t\t\t\t/*\n\t\t\t\t** Check for unusual situations like a focus loss\n\t\t\t\t*/\n\t\t\t\tif (return_code != DS_OK){\n\t\t\t\t\tif (return_code == DSERR_BUFFERLOST){\n\t\t\t\t\t\tif (Audio_Focus_Loss_Function){\n\t\t\t\t\t\t\tAudio_Focus_Loss_Function();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\t\t//LeaveCriticalSection (&st->AudioCriticalSection);\n\t\t\t\t\treturn;\t\t//Our app has lost focus or something else nasty has happened\n\t\t\t\t}\t\t\t\t\t//so dont update the sound buffers\n\n\n\t\t\t\tif (st->MoreSource){\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If the direct sound read pointer is less than a quarter\n\t\t\t\t\t** of a buffer away from the end of the data then copy some\n\t\t\t\t\t** more.\n\t\t\t\t \t*/\n\t\t\t\t\twrite_more = FALSE;\n\n\t\t\t\t\tif ( play_cursor < (unsigned)st->DestPtr ){\n\t\t\t\t\t\tif ( (unsigned)st->DestPtr - (unsigned)play_cursor <= SECONDARY_BUFFER_SIZE/4 ){\n\t\t\t\t\t\t\twrite_more=TRUE;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t/* The only time that play_cursor can be greater than DestPtr is\n\t\t\t\t\t\t** if we wrote right to the end of the buffer last time and DestPtr\n\t\t\t\t\t\t** looped back to the beginning of the buffer.\n\t\t\t\t\t\t** That being the case, all we have to do is see if play_cursor is\n\t\t\t\t\t\t** within the last 25% of the buffer\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif ( ( (int)play_cursor > SECONDARY_BUFFER_SIZE*3/4) &&st->DestPtr==0 ){\n\t\t\t\t\t\t\twrite_more=TRUE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (write_more){\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Lock a 1/2 of the direct sound buffer so we can write to it\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif ( DS_OK== st->PlayBuffer->Lock (\t(DWORD)st->DestPtr ,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(DWORD)SECONDARY_BUFFER_SIZE/2,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&play_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&lock_length1,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&dummy_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&lock_length2,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t0 )){\n\n\t\t\t\t\t\t\tbytes_copied = Sample_Copy(\tst,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Source,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Remainder,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->QueueBuffer,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->QueueSize,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tplay_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tSECONDARY_BUFFER_SIZE/4,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tst->Compression,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Trailer[0],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->TrailerLen);\n\n\n\t\t\t\t\t\t\tif ( bytes_copied != (SECONDARY_BUFFER_SIZE/4) ){\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** We must have reached the end of the sample\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tst->MoreSource=FALSE;\n\t\t\t\t\t\t\t\tmemset (((char*)play_buffer_ptr)+bytes_copied ,\n\t\t\t\t\t\t\t\t\t\t0 ,\n\t\t\t\t\t\t\t\t\t\t(SECONDARY_BUFFER_SIZE/4)-bytes_copied);\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** Clear out an extra area in the buffer ahead of the play cursor\n\t\t\t\t\t\t\t\t** to give us a quiet period of grace in which to stop the buffer playing\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tif ( (unsigned)st->DestPtr == SECONDARY_BUFFER_SIZE*3/4 ){\n\t\t\t\t\t\t\t\t\tif ( dummy_buffer_ptr && lock_length2 ){\n\t\t\t\t\t\t\t\t\t\tmemset (dummy_buffer_ptr , 0 , lock_length2);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tmemset ((char*)play_buffer_ptr+SECONDARY_BUFFER_SIZE/4 , 0 , SECONDARY_BUFFER_SIZE/4);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**  Update our pointer into the direct sound buffer\n\t\t\t\t\t\t\t**\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tst->DestPtr = Audio_Add_Long_To_Pointer (st->DestPtr,bytes_copied);\n\n\t\t\t\t\t\t\tif ( (unsigned)st->DestPtr >= (unsigned)SECONDARY_BUFFER_SIZE ){\n\t\t\t\t\t\t\t\tst->DestPtr = Audio_Add_Long_To_Pointer (st->DestPtr,(long)-SECONDARY_BUFFER_SIZE);\n\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Unlock the direct sound buffer\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tst->PlayBuffer->Unlock(\tplay_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\t\tlock_length1,\n\t\t\t\t\t\t\t\t\t\t\t\t\tdummy_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\t\tlock_length2);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\t\t\t\t//write_more\n\n\t\t\t\t} else {\t\t\t//!more_source\n\n\t\t\t\t\t/*\n\t\t\t\t\t** no more source to write - check if the buffer play\n\t\t\t\t\t** has overrun the end of the sample and stop it if it has\n\t\t\t\t\t*/\n\t\t\t\t\tif ( ( (play_cursor >= (unsigned)st->DestPtr) && ( ((unsigned)play_cursor - (unsigned)st->DestPtr) <SECONDARY_BUFFER_SIZE/4) ) ||\n\t\t\t\t\t\t(!st->OneShot &&( (play_cursor < (unsigned)st->DestPtr) && ( ((unsigned)st->DestPtr - (unsigned)play_cursor) >(SECONDARY_BUFFER_SIZE*3/4) ) ))\t ){\n\t\t\t\t\t\t\tst->PlayBuffer->Stop();\n\t\t\t\t\t\t\tst->Service = FALSE;\n\t\t\t\t\t\t\tStop_Sample( index );\n\t\t\t\t\t}\n\t\t\t\t}\t\t\t\t\t//more_source\n\n\t\t\t\tst->DontTouch = FALSE;\n\n\t\t\t\t//LeaveCriticalSection (&st->AudioCriticalSection);\n\t\t\t}\n\t\t\t/*\n\t\t\t**\tFor file streamed samples, fill the queue pointer if needed.\n\t\t\t**\tThis allows for delays in calling the Sound_Callback function.\n\t\t\t*/\n\t\t\tif (!st->DontTouch && !st->QueueBuffer && st->FilePending) {\n\t\t\t\tst->QueueBuffer = Audio_Add_Long_To_Pointer(st->FileBuffer, (long)(st->Odd%LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t\t\t\tst->FilePending--;\n\t\t\t\tst->Odd++;\n\t\t\t\tif (!st->FilePending) {\n\t\t\t\t\tst->QueueSize = st->FilePendingSize;\n\t\t\t\t} else {\n\t\t\t\t\tst->QueueSize = LockedData.StreamBufferSize;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tAdvance to the next sample control structure.\n\t\t*/\n\t\tst++;\n\t}\n\n\n\tif (!LockedData._int) {\n\n\t\tLockedData._int++;\n\t\tst = &LockedData.SampleTracker[0];\n\t\tfor (index = 0; index < MAX_SFX; index++) {\n\n\t\t\t/*\n\t\t\t**\tIf there are any samples that require fading, then do so at this\n\t\t\t**\ttime.\n\t\t\t*/\n\t\t\tif (st->Active && st->Reducer && st->Volume) {\n\t\t\t\t//EnterCriticalSection (&st->AudioCriticalSection);\n\t\t\t\tif (st->Reducer >= st->Volume) {\n\t\t\t\t\tst->Volume = 0;\n\t\t\t\t} else {\n\t\t\t\t\tst->Volume -= st->Reducer;\n\t\t\t\t}\n\n\t\t\t\t//st->PlayBuffer->SetVolume (-( ( (32768-st->Volume)*1000) >>15 ) );\n\n\t\t\t\tif (st->IsScore){\n\t\t\t\t\tst->PlayBuffer->SetVolume ( Convert_HMI_To_Direct_Sound_Volume( ( LockedData.ScoreVolume*(st->Volume >>7))/256) );\n\t\t\t\t}else{\n\t\t\t\t\tst->PlayBuffer->SetVolume ( Convert_HMI_To_Direct_Sound_Volume( ( LockedData.SoundVolume*(st->Volume >>7))/256) );\n\t\t\t\t}\n\n\t\t\t\t//LeaveCriticalSection (&st->AudioCriticalSection);\n\t\t\t}\n\t\t\tst++;\n\t\t}\n\t\tLockedData._int--;\n\t}\n\n\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n}\n\n\n\n\n\n\n\n/***************************************************************************\n * ADD_LONG_TO_POINTER -- Adds an offset to a ptr casted void              *\n *                                                                         *\n * INPUT:\t\tvoid * ptr - the pointer to add to                            *\n *\t\t\t\t\tlong size  - the size to add to it\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:     void * ptr - the new location it will point to              *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n\nvoid *Audio_Add_Long_To_Pointer(void const *ptr, long size)\n{\n\treturn ((void *) ( (char const *) ptr + size));\n}\n\n/***************************************************************************\n * AUDIO_MEM_SET -- Quick see routine to set memory to a value             *\n *                                                                         *\n * INPUT:\t\tvoid const *  - the memory that needs to be set               *\n *\t\t\t\t\tunsigned char - the value to set the memory to\t\t\t\t  *\n *\t\t\t\t\tlong size     - how big an area to set\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:\t\tnone                                                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/28/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid Audio_Mem_Set(void const *ptr, unsigned char value, long size)\n{\n\tunsigned char *temp = (unsigned char *)ptr;\n\tfor (int lp = 0; lp < size; lp ++) {\n\t\t*temp++ = value;\n\t}\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/SOUNDIO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Id: soundio.cpp 1.41 1994/06/20 15:01:39 joe_bostic Exp $ */\n/***********************************************************************************************\n **             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             **\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Sound Library                                                *\n *                                                                                             *\n *                    File Name : SOUND.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 22, 1991                                                *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Load_Long_Sample -- Loads a sample into XMS for double buffer system.                     *\n *   Read_Long_Sample -- Loads/Processes/Formats/Builds offset.                                             *\n *   Save_Table_Entry -- Put an entry in the offset table.                                     *\n *   Play_Long_Sample -- Calls Init_Long_Sample and Start_Long_Sample.                         *\n *   Start_Long_Sample -- Starts a sample playing that has be initialized.                     *\n *   Get_Table_Entry -- Gets next entry in table.                                              *\n *   Long_Sample_Ticks -- Gets number of ticks in sample if in header.                         *\n *   Long_Sample_Status -- Returns the status of the sample.                                   *\n *   Find_Table_Entry -- Finds next entry in table that matches mask.                          *\n *   Get_Table_Start -- Returns a pointer to first entry in table.                             *\n *   Long_Sample_Ticks_Played -- Number of ticks since sample started.                         *\n *   Install_Sample_Driver_Callback -- Pokes callback function into JM driver                  *\n *   Stop_Long_Sample -- Stops current long sample from playing.                               *\n *   Long_Sample_Loaded_Size -- Max buffer size to load a long sample.                         *\n *   Sound_Callback -- Audio driver callback function.                                         *\n *   DigiCallback -- Low level double buffering handler.                                       *\n *   Load_Sample_Into_Buffer -- Loads a digitized sample into a buffer.                        *\n *   Stream_Sample -- Streams a sample directly from a file.                                   *\n *   Sample_Read -- Reads sample data from an openned file.                                    *\n *   Continue_Sample -- Tags another block of data onto the currently playing.                 *\n *   Sample_Copy -- Copies sound data from source format to raw format.                        *\n *   File_Stream_Preload -- Handles initial proload of a streaming samples bu*\n *   Sample_Length -- returns length of a sample in ticks                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nextern\tvoid Colour_Debug (int call_number);\n#pragma \tpack(4)\n\n#define WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n\n#include\t<windows.h>\n#include\t<windowsx.h>\n#include\t\"dsound.h\"\n\n#include\t<mem.h>\n#include\t<wwmem.h>\n#include\t\"soundint.h\"\n#include\t<stdio.h>\n#include\t<string.h>\n#include\t<direct.h>\n#include\t<stdlib.h>\n#include <process.h>\n#include\t<keyboard.h>\n#include\t<file.h>\n#include\t<bios.h>\n#include\t<timer.h>\n#include\t<math.h>\n#pragma\t\tpack(1)\n#include\t\"audio.h\"\n#pragma\t\tpack(4)\n\nLPDIRECTSOUNDBUFFER\tDumpBuffer;\nHANDLE\t\t\t\t\t\tSoundThreadHandle = NULL;\nBOOL\t\t\t\t\t\tSoundThreadActive = FALSE;\n\n/*\n**      If this is defined, then the streaming audio buffer will be filled\n**      to maximum whenever filling is to occur. If undefined, it will fill\n**      the streaming buffer in smaller chunks.\n*/\n#define SIMPLE_FILLING\n\n/*\n**      This is the number of times per sec that the maintenance callback gets called.\n*/\n#define MAINTENANCE_RATE                        40\t//30 times per sec plus a safety margin\n\n/*\n**      Size of the temporary buffer in XMS/EMS that direct file\n**      streaming of sounds will allocate.\n*/\n//#define STREAM_BUFFER_SIZE              (128L*1024L)\n#define STREAM_BUFFER_SIZE              (128L*1024L)\n\n/*\n** Define the number of \"StreamBufferSize\" blocks that are read in\n** at a minimum when the streaming sample load callback routine\n** is called.  We will IGNORE loads that are less that this in order\n** to avoid constant seeking on the CD.\n*/\n#define STREAM_CUSHION_BLOCKS   4\n\n\n/*\n**      This is the maximum size that a sonarc block can be.  All sonarc blocks\n**      must be either a multiple of this value or a binary root of this value.\n*/\n#define LARGEST_SONARC_BLOCK            2048\n\n\n//////////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////// structs ///////////////////////////////////////\n\n//void\t\t\t\t\t\t*DigiBuffer = NULL;\nstatic BOOL\t\t\t\tStartingFileStream = FALSE;\nint\t\t\t\t\t\tStreamLowImpact = FALSE;\nMemoryFlagType\t\t\tStreamBufferFlag = MEM_NORMAL;\nint\t\t\t\t\t\t\tMisc;\nSFX_Type\t\t\t\t\tSoundType;\nSample_Type\t\t\t\tSampleType;\nint\t\t\t\t\t\t\tReverseChannels = FALSE;\nLPDIRECTSOUND\t\t\tSoundObject;\t\t\t//Direct sound object\nLPDIRECTSOUNDBUFFER\tPrimaryBufferPtr;\t\t//Pointer to the  buffer that the\nunsigned\t\t\t\t\tSoundTimerHandle=0;\t//Windows Handle for sound timer\nWAVEFORMATEX\t\t\t\tDsBuffFormat;\t\t\t//format of direct sound buffer\nDSBUFFERDESC\t\t\t\tBufferDesc;\t\t\t\t//Buffer description for creating buffers\nWAVEFORMATEX\t\t\t\tPrimaryBuffFormat;\t//Copy of format of direct sound primary buffer\nDSBUFFERDESC\t\t\t\tPrimaryBufferDesc;\t//Copy of buffer description for re-creating primary buffer\nCRITICAL_SECTION\t\tGlobalAudioCriticalSection;\n/*\n** Function to call if we detect focus loss\n*/\nextern\tvoid (*Audio_Focus_Loss_Function)(void) = NULL;\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nstatic BOOL File_Callback(short id, short *odd, void **buffer, long *size);\nstatic int __cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback)(short id, short *odd, void **buffer, long *size), int volume, int handle);\nvoid CALLBACK Sound_Timer_Callback ( UINT, UINT, DWORD, DWORD, DWORD );\n//static int __cdecl Stream_Sample(void *buffer, long size, BOOL (*callback)(short id, short *odd, void **buffer, long *size));\nvoid Sound_Thread (void *);\nvolatile BOOL AudioDone;\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n// This callback is called whenever the queue buffer playback has begun\n// and another buffer is needed for queuing up.  Returns TRUE if there\n// is more data to read from the file.\nstatic BOOL File_Callback(short id, short *odd, void **buffer, long *size)\n{\n\tSampleTrackerType       *st;            // Pointer to sample playback control struct.\n\tvoid                    *ptr;           // Pointer to working portion of file buffer.\n\n\tif (id != -1) {\n\t\tst = &LockedData.SampleTracker[id];\n\t \tptr = st->FileBuffer;\n\t \tif (ptr) {\n\n\t \t  \t/*\n\t \t  \t** Move the next pending block into the primary\n\t \t  \t** position.  Do this only if the queue pointer is\n\t \t  \t** null.\n\t \t  \t*/\n\t\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t \t  \tst->DontTouch = TRUE;\n\t\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t \t  \tif (!*buffer && st->FilePending) {\n\t \t  \t\t*buffer = Add_Long_To_Pointer(ptr, (long)(*odd % LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t \t  \t\tst->FilePending--;\n\t \t  \t\t*odd = (short)(*odd + 1);\n\t \t  \t\tif (!st->FilePending) {\n\t \t  \t\t\t*size = st->FilePendingSize;\n\t \t  \t\t} else {\n\t \t  \t\t\t*size = LockedData.StreamBufferSize;\n\t \t  \t\t}\n\t \t  \t}\n\t\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t \t  \tst->DontTouch = FALSE;\n\t\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\tSound_Timer_Callback(0,0,0,0,0);\t//Shouldnt block as we are calling it from the same thread\n\n\t \t  \t/*\n\t \t  \t** If the file handle is still valid, then read in the next\n\t \t  \t** block and add it to the next pending slot available.\n\t \t  \t*/\n\t \t  \tif (st->FilePending <\n\t \t  \t\t(StreamLowImpact ? (LockedData.StreamBufferCount>>1) : ((LockedData.StreamBufferCount-3))) && st->FileHandle != WW_ERROR) {\n\n\n\t \t  \t\tint num_empty_buffers;\n\n#ifdef SIMPLE_FILLING\n\t\t\t\tnum_empty_buffers = (LockedData.StreamBufferCount-2) - st->FilePending;\n#else\n\n\t\t\t\t//\n\t\t\t\t// num_empty_buffers will be from 1 to StreamBufferCount\n\t\t\t\t//\n\t\t\t\tif (StreamLowImpact) {\n\t\t\t\t\tnum_empty_buffers = MIN((LockedData.StreamBufferCount >> 1)+STREAM_CUSHION_BLOCKS, (LockedData.StreamBufferCount - 2) - st->FilePending);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tnum_empty_buffers = (LockedData.StreamBufferCount - 2) - st->FilePending;\n\t\t\t\t}\n#endif\n\n\t\t\t\twhile (num_empty_buffers && (st->FileHandle != WW_ERROR)) {\n\t\t\t\t\tint     tofill;\n\t\t\t\t\tlong    psize;\n\n\t\t\t\t\ttofill = (*odd + st->FilePending) % LockedData.StreamBufferCount;\n\n\t\t\t\t\tptr = Add_Long_To_Pointer(st->FileBuffer, (long)tofill * (long)LockedData.StreamBufferSize);\n\t\t\t\t\tpsize = Read_File(st->FileHandle, ptr, LockedData.StreamBufferSize);\n\n\t\t\t\t \t/*\n\t\t\t\t \t**      If less than the requested amount of data was read, this\n\t\t\t\t \t**      indicates that the source file is exhausted.  Flag the source\n\t\t\t\t \t**      file as closed so that no further reading is attempted.\n\t\t\t\t \t*/\n\t\t\t\t \tif (psize != LockedData.StreamBufferSize) {\n\t\t\t\t \t\tClose_File(st->FileHandle);\n\t\t\t\t\t\tst->FileHandle = WW_ERROR;\n\t\t\t\t \t}\n\n                /*\n\t\t\t\t \t**      If any real data went into the pending buffer, then flag\n\t\t\t\t \t**      that this buffer is valid.\n                */\n\t\t\t\t \tif (psize) {\n\t\t\t\t\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\t\t\tst->DontTouch = TRUE;\n\t\t\t\t \t  \tst->FilePendingSize = psize;\n\t\t\t\t \t  \tst->FilePending++;\n\t\t\t\t \t  \tst->DontTouch = FALSE;\n\t\t\t\t\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\t\t\tSound_Timer_Callback(0,0,0,0,0);\t//Shouldnt block as we are calling it from the same thread\n\t\t\t\t \t}\n\t\t\t\t \tnum_empty_buffers--;\n\t\t\t\t}\n\n\t\t\t\t/*\n             **  After filling all pending buffers, check to see if the queue buffer\n\t\t\t\t**  is empty.  If so, then assign the first available pending buffer to the\n             **  queue.\n\t\t\t\t*/\n\t\t\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\tst->DontTouch = TRUE;\n             if (!st->QueueBuffer && st->FilePending) {\n\t\t\t\t\tst->QueueBuffer = Add_Long_To_Pointer(st->FileBuffer, (long)(st->Odd%LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t\t\t\t\tst->FilePending--;\n                st->Odd++;\n                if (!st->FilePending) {\n\t\t\t\t\t\tst->QueueSize = st->FilePendingSize;\n\t\t\t\t\t} else {\n                \tst->QueueSize = LockedData.StreamBufferSize;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tst->DontTouch = FALSE;\n\t\t\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\tSound_Timer_Callback(0,0,0,0,0);\t//Shouldnt block as we are calling it from the same thread\n\t\t\t}\n\n\t\t\t/*\n          **      If there are no more buffers that the callback routine\n\t\t\t**      can slot into the primary position, then signal that\n\t\t\t**      no furthur callbacks are needed.\n\t\t\t*/\n\t\t\tif (st->FilePending) {\n\t\t\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\treturn(TRUE);\n\t\t\t}\n\t\t}\n\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\n\t}\n  return(FALSE);\n}\n\n\n\n\n\n// Generic streaming sample playback initialization.\nstatic int __cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback)(short id, short *odd, void **buffer, long *size), int volume, int handle)\n{\n\tint\t\t\t\t\t\t\t\tplayid=-1;      // Sample play ID.\n\tSampleTrackerType               *st;                    // Working pointer to sample control structure.\n\tlong\t\t\t\t\t\t\toldsize;                // Copy of original sound size.\n\tAUDHeaderType                   header;\n\n\tif (buffer && size && LockedData.DigiHandle != -1) {\n\n\t\t/*\n\t \t** Start the first section of the sound playing.\n\t \t*/\n\t \tMem_Copy(buffer, &header, sizeof(header));\n\t \toldsize = header.Size;\n\t \theader.Size = size-sizeof(header);\n\t \tMem_Copy(&header, buffer, sizeof(header));\n\t \tplayid = Play_Sample_Handle(buffer, 0xFF, volume, 0x0, handle);\n\t \theader.Size = oldsize;\n\t \tMem_Copy(&header, buffer, sizeof(header));\n\n\t \t/*\n\t \t** If the sample actually started playing, then flag this\n\t \t** sample as a streaming type and signal for a callback\n\t \t** to occur.\n\t \t*/\n\t \tif (playid != -1) {\n\t \t\tst = &LockedData.SampleTracker[playid];\n\n\t \t\tst->Callback = callback;\n\t \t\tst->Odd = 0;\n//             ServiceSomething = TRUE;\n    \t}\n\t}\n\t\t  return (playid);\n}\n\n\n\n#if (0)\nstatic int __cdecl Stream_Sample(void *buffer, long size, BOOL (*callback)(short id, short *odd, void **buffer, long *size), int handle)\n{\n\treturn Stream_Sample_Vol(buffer, size, callback, 0xFF, handle);\n}\n#endif\n\n\n/***********************************************************************************************\n * File_Stream_Sample -- Streams a sample directly from a file.                                *\n *                                                                                             *\n *    This will take the file specified and play it directly from disk.                        *\n *    It performs this by allocating a temporary buffer in XMS/EMS and                         *\n *    then keeping this buffer filled by the Sound_Callback() routine.                         *\n *                                                                                             *\n * INPUT:   filename -- The name of the file to play.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the handle to the sound -- just like Play_Sample().                        *\n *                                                                                             *\n * WARNINGS:   The temporary buffer is allocated when this routine is                          *\n *             called and then freed when the sound is finished.  Keep                         *\n *             this in mind.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint File_Stream_Sample(char const *filename, BOOL real_time_start)\n{\n\treturn File_Stream_Sample_Vol(filename, 0xFF, real_time_start);\n}\n\n/***************************************************************************\n * FILE_STREAM_PRELOAD -- Handles initial proload of streaming samples     *\n *                                                                         *\n * This function is called before a sample which streams from disk is      *\n * started.  It can be called to either fill the buffer in small chunks    *\n * from the call back routine or to fill the entire buffer at once.  This  *\n * is wholely dependant on whether the Loading bit is set within the       *\n * sample tracker.                                                         *\n *                                                                         *\n * INPUT:LockedData.SampleTracker * to the header which tracks this samples*\n *                                                              processing.*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/05/1995 PWG : Created.                                             *\n *=========================================================================*/\n\nvoid File_Stream_Preload(int handle)\n{\n\tSampleTrackerType\t*st\t\t= &LockedData.SampleTracker[handle];\n\tint\t\t\t\t\tfh\t\t\t= st->FileHandle;\n\tint\t\t\t\t\tmaxnum\t= (LockedData.StreamBufferCount >> 1) + STREAM_CUSHION_BLOCKS;\n\tvoid\t\t\t\t\t*buffer\t= st->FileBuffer;\n\tint\t\t\t\t\tnum;\n\n\t/*\n    ** Figure just how much we need to load.  If we are doing the load in progress\n\t** then we will only load two blocks.\n\t*/\n    if (st->Loading) {\n    \tnum = st->FilePending + 2;\n       num = MIN(num, maxnum);\n    } else {\n\t\tnum = maxnum;\n\t}\n\n\t//EnterCriticalSection(&GlobalAudioCriticalSection);\n\n    /*\n    ** Loop through the blocks and load up the number we need.\n    */\n    for (int index = st->FilePending; index < num; index++) {\n\t\tlong s = Read_File(fh, Add_Long_To_Pointer(buffer, (long)index * (long)LockedData.StreamBufferSize), LockedData.StreamBufferSize);\n       if (s) {\n         \tst->FilePendingSize = s;\n\t  \t\tst->FilePending++;\n\t\t}\n\t\tif (s < LockedData.StreamBufferSize) break;\n    }\n\n\tSound_Timer_Callback(0,0,0,0,0);\t//Shouldnt block as we are calling it from the same thread\n\n\n\t/*\n\t** If the last block was incomplete (ie. it didn't completely fill the buffer) or\n\t** we have now filled up as much of the Streaming Buffer as we need to, then now is\n\t** the time to kick off the sample.\n\t*/\n\tif (st->FilePendingSize < LockedData.StreamBufferSize || index == maxnum) {\n\n\t\t/*\n\t\t** Actually start the sample playing, and don't worry about the file callback\n\t\t** it won't be called for a while.\n\t\t*/\n \t\tint old\t\t\t\t\t\t= LockedData.SoundVolume;\n\t\tint size\t\t\t\t\t\t= (st->FilePending == 1) ? st->FilePendingSize : LockedData.StreamBufferSize;\n\t\tLockedData.SoundVolume\t= LockedData.ScoreVolume;\n\t\tStartingFileStream\t\t= TRUE;\n\n\t\tStream_Sample_Vol(buffer, size, File_Callback, st->Volume, handle);\n\t\tStartingFileStream\t\t= FALSE;\n       LockedData.SoundVolume\t= old;\n\n\t\t/*\n\t\t** The Sample is finished loading (if it was loading in small pieces) so record that\n\t\t** so that it will now use the active logic in the file call back.\n\t\t*/\n\t\tst->Loading\t\t\t\t\t= FALSE;\n\n\t\t/*\n\t\t** Decrement the file pending because the first block is already playing thanks\n\t\t** to the play sample call above.\n\t\t*/\n\t\tst->FilePending--;\n\n\t\t/*\n\t\t** If File pending is now a zero, then we only preloaded one block and there\n\t\t** is nothing more to play.  So clear the sample tracing structure of the\n\t\t** information it no longer needs.\n\t\t*/\n\t\tif (!st->FilePending) {\n\t\t\tst->Odd\t\t\t\t\t= 0;\n          st->QueueBuffer\t\t= 0;\n\t\t\tst->QueueSize\t\t\t= 0;\n\t\t\tst->FilePendingSize\t= 0;\n          st->Callback\t\t\t= NULL;\n\t\t\tClose_File(fh);\n\t\t} else {\n\t\t\t/*\n\t\t\t** The QueueBuffer counts as an already played block so remove it from the total.\n          ** Note: We didn't remove it before because there might not have been one.\n          */\n          st->FilePending--;\n\n          /*\n          ** When we start loading we need to start past the first two blocks.  Why this\n          ** is called Odd, I haven't got the slightest.\n\t\t\t*/\n          st->Odd = 2;\n\n          /*\n          ** If the file pending size is less than the stream buffer, then the last block\n          ** we loaded was the last block period.  So close the file and reset the handle.\n          */\n          if (st->FilePendingSize != LockedData.StreamBufferSize) {\n\t\t\t\tClose_File(fh);\n             st->FileHandle = WW_ERROR;\n          }\n\n          /*\n          ** The Queue buffer needs to point at the next block to be processed.  The size\n          ** of the queue is dependant on how many more blocks there are.\n          */\n\t\t\tst->QueueBuffer = Add_Long_To_Pointer(buffer, LockedData.StreamBufferSize);\n\t\t\tif (!st->FilePending) {\n          \tst->QueueSize = st->FilePendingSize;\n          } else {\n          \tst->QueueSize = LockedData.StreamBufferSize;\n          }\n\t\t}\n\t}\n\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\n}\n\n\n\n\n\n\n\n/***********************************************************************************************\n * File_Stream_Sample_Vol -- Streams a sample directly from a file.                            *\n *                                                                                             *\n *    This will take the file specified and play it directly from disk.                        *\n *    It performs this by allocating a temporary buffer in XMS/EMS and                         *\n *    then keeping this buffer filled by the Sound_Callback() routine.                         *\n *                                                                                             *\n * INPUT:   filename -- The name of the file to play.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the handle to the sound -- just like Play_Sample().                        *\n *                                                                                             *\n * WARNINGS:   The temporary buffer is allocated when this routine is                          *\n *             called and then freed when the sound is finished.  Keep                         *\n *             this in mind.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *=============================================================================================*/\n\nint File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start)\n{\n\tstatic void     *buffer = NULL;\n\tSampleTrackerType       *st;\n\tint     fh;\n\tint     handle = -1;\n\tint     index;\n\n\tif (LockedData.DigiHandle != -1 && filename && Find_File(filename)) {\n\n\t/*\n\t**  Make sure all sample tracker structures point to the same\n\t**  upper memory buffer.  This allocation only occurs if at\n\t**  least one sample gets \"streamed\".\n\t*/\n\tif (!buffer) {\n\t\tbuffer = Alloc(LockedData.StreamBufferSize * LockedData.StreamBufferCount, (MemoryFlagType)(StreamBufferFlag | MEM_TEMP | MEM_LOCK));\n       for (index = 0; index < MAX_SFX; index++) {\n       \tLockedData.SampleTracker[index].FileBuffer = buffer;\n\t\t}\n\t}\n\t/*\n\t** If after trying to allocate the buffer we still fail then\n\t** we can stream this sample.\n\t*/\n\tif (!buffer) return(-1);\n\n\n    \t/*\n    \t** Lets see if we can sucessfully open up the file.  If we can't,\n    \t** then there is no point in going any farther.\n    \t*/\n    \tif ((fh = Open_File(filename, READ)) == -1) {\n \t \t\t\treturn (-1);\n    \t}\n\n\t\t/*\n\t\t** Reserve a handle so that we can fill in the sample tracker\n\t\t** with the needed information.  If we dont get valid handle then\n\t\t** we might as well give up.\n\t\t*/\n\t\tif ((unsigned)(handle = Get_Free_Sample_Handle(0xFF)) >= MAX_SFX) {\n \t\t\t\treturn(-1);\n\t\t}\n\n\t\t/*\n\t\t** Now lets get a pointer to the proper sample handler and start\n\t\t** our manipulations.\n\t\t*/\n\t\tst\t\t\t\t\t\t\t= &LockedData.SampleTracker[handle];\n\t\tst->IsScore\t\t\t\t= TRUE;\n\t\tst->FilePending\t\t= 0;\n\t\tst->FilePendingSize\t= 0;\n\t\tst->Loading\t\t\t\t= real_time_start;\n\t\tst->Volume\t\t\t\t= volume;\n\t\tst->FileHandle\t\t\t= fh;\n\n\t\t/*\n\t\t** Now that we have setup our initial data properly, let load up\n\t\t** the beginning of the sample we intend to stream.\n\t\t*/\n\t\tFile_Stream_Preload(handle);\n\t}\n\n\treturn (handle);\n}\n\n/***********************************************************************************************\n * Sound_Callback -- Audio driver callback function.                                           *\n *                                                                                             *\n *    Maintains the audio buffers.  This routine must be called at least                       *\n *    11 times per second or else audio glitches will occur.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If this routine is not called often enough then audio                           *\n *             glitches will occur.                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid __cdecl Sound_Callback(void)\n{\n\tint\t\t\t\t\tindex;\n    SampleTrackerType\t*st;\n\n    if (LockedData.DigiHandle != -1) {\n\n\t\t/*\n\t\t** Call the timer callback now as we may block it in this function\n\t\t*/\n\t\tSound_Timer_Callback(0,0,0,0,0);\n\n\t\tst = &LockedData.SampleTracker[0];\n\t\tfor (index = 0; index < MAX_SFX; index++) {\n\t\t\tif (st->Loading) {\n\t\t\t\tFile_Stream_Preload(index);\n\t\t\t} else {\n          \t/*\n          \t**  General service routine to handle moving small blocks from the\n          \t**  source into the low RAM staging buffers.\n          \t*/\n\n\t\t\t\tif (st->Active) {\n\n\t\t\t\t\t/*\n          \t\t**  Special check to see if the sample is a fading one AND\n          \t\t**  it has faded to silence, then stop it here.\n          \t\t*/\n          \t\tif (st->Reducer && !st->Volume) {\n\t\t\t\t\t\t//EnterCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\t\t\tStop_Sample(index);\n\t\t\t\t\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\t\t\t} else {\n\n          \t\t\t/*\n             \t\t**  Fill the queuebuffer if it is currently empty\n             \t\t**  and there is a callback function defined to fill it.\n             \t\t**\n             \t\t** PWG/CDY & CO: We should be down by at least two blocks\n\t\t\t\t\t\t**                                        before we bother with this\n             \t\t*/\n\n             \t\tif ((!st->QueueBuffer ||\n\t\t\t\t\t\t\t(st->FileHandle != WW_ERROR && st->FilePending < LockedData.StreamBufferCount-3)) &&\n\t\t\t\t \t\t\tst->Callback) {\n\n                \t\tif (!st->Callback((short)index, (short int *)&st->Odd, &st->QueueBuffer, &st->QueueSize)) {\n\t\t\t\t\t\t\t\tst->Callback = NULL;\n                \t\t}\n             \t\t}\n          \t\t}\n\n\t\t\t\t} else {\n\n          \t\t/*\n          \t\t** This catches the case where a streaming sample gets\n          \t\t** aborted prematurely because of failure to call the\n          \t\t** callback function frequently enough.  In this case, the\n          \t\t** sample will be flagged as inactive, but the file handle\n          \t\t** will not have been closed.\n          \t\t*/\n          \t\tif (st->FileHandle != WW_ERROR) {\n\t\t\t\t\t\t//EnterCriticalSection(&GlobalAudioCriticalSection);\n          \t\t\tClose_File(st->FileHandle);\n             \t\tst->FileHandle = WW_ERROR;\n\t\t\t\t\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n          \t\t}\n\t\t\t\t}\n\t\t\t}\n\n          /*\n          **      Advance to the next sample control structure.\n\t\t\t*/\n    \t\tst++;\n\t\t}\n\n    }\n}\n\n\n/***********************************************************************************************\n * Load_Sample -- Loads a digitized sample into RAM.                                           *\n *                                                                                             *\n *    This routine loads a digitized sample into RAM.                                          *\n *                                                                                             *\n * INPUT:   filename -- Name of the sound file to load.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the loaded sound file.  This pointer                     *\n *          is passed to Play_Sample when playback is desired.                                 *\n *                                                                                             *\n * WARNINGS:   If there is insufficient memory to load the sample, then                        *\n *             NULL will be returned.                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *   01/06/1994 JLB : HMI version.                                                             *\n *=============================================================================================*/\nvoid *Load_Sample(char const *filename)\n{\n\tvoid *buffer = NULL;\n\tlong    size;\n\tint     fh;\n\n\tif (LockedData.DigiHandle == -1 || !filename || !Find_File(filename)) {\n\t\treturn (NULL);\n\t}\n\n\tfh = Open_File(filename, READ);\n\tif (fh != WW_ERROR) {\n\t\tsize = File_Size(fh)+sizeof(AUDHeaderType);\n\t\tbuffer = Alloc(size, MEM_NORMAL);\n\n\t\tif (buffer) {\n\t\t\tSample_Read(fh, buffer, size);\n\t\t}\n\t\tClose_File(fh);\n\t\tMisc = size;\n\t}\n\treturn(buffer);\n}\n\n\n/***********************************************************************************************\n * Load_Sample_Into_Buffer -- Loads a digitized sample into a buffer.                          *\n *                                                                                             *\n *    This routine is used to load a digitized sample into a buffer                            *\n *    provided by the programmer.  This buffer can be in XMS or EMS.                           *\n *                                                                                             *\n * INPUT:   filename -- The filename to load.                                                  *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer to load into.                                    *\n *                                                                                             *\n *          size     -- The size of the buffer to load into.                                   *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually used in the buffer.                           *\n *                                                                                             *\n * WARNINGS:   This routine will not overflow the buffer provided.  This                       *\n *             means that the buffer must be big enough to hold the data                       *\n *             or else the sound will be cut short.                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Load_Sample_Into_Buffer(char const *filename, void *buffer, long size)\n{\n\tint     fh;\n\n\t/*\n\t**      Verify legality of parameters.\n\t*/\n\tif (!buffer || !size || LockedData.DigiHandle == -1 || !filename || !Find_File(filename)) {\n\t\treturn (NULL);\n\t}\n\n\tfh = Open_File(filename, READ);\n\tif (fh != WW_ERROR) {\n\t\tsize = Sample_Read(fh, buffer, size);\n       Close_File(fh);\n\t} else {\n\t\treturn(0);\n\t}\n\treturn(size);\n}\n\n\n/***********************************************************************************************\n * Sample_Read -- Reads sample data from an openned file.                                      *\n *                                                                                             *\n *    This routine reads a sample file.  It is presumed that the file is                       *\n *    already positioned at the start of the sample.  From this, it can                        *\n *    determine if it is a VOC or raw data and proceed accordingly.                            *\n *                                                                                             *\n * INPUT:   fh       -- File handle of already openned sample file.                            *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer to load data into.                               *\n *                                                                                             *\n *          size     -- The size of the buffer.                                                *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually used in the buffer.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Sample_Read(int fh, void *buffer, long size)\n{\n\n\tAUDHeaderType\tRawHeader;\n\tvoid    \t\t\t*outbuffer;\t\t\t\t// Pointer to start of raw data.\n\tlong    \t\t\tactual_bytes_read;\t// Actual bytes read in, including header\n\n/*\n** Conversion formula for TCrate and Hz rate.\n**\n** TC = 256 - 1m/rate\n** rate = 1m / (256-TC)\n*/\n\n\tif (!buffer || fh == WW_ERROR || size <= sizeof(RawHeader)) return(NULL);\n\n\tsize -= sizeof(RawHeader);\n\toutbuffer = Add_Long_To_Pointer(buffer, sizeof(RawHeader));\n  \tactual_bytes_read = Read_File(fh, &RawHeader, sizeof(RawHeader));\n\tactual_bytes_read +=Read_File(fh, outbuffer, MIN(size, RawHeader.Size));\n\tMem_Copy(&RawHeader, buffer, sizeof(RawHeader));\n\treturn(actual_bytes_read);\n}\n\n\n/***********************************************************************************************\n * Free_Sample -- Frees a previously loaded digitized sample.                                  *\n *                                                                                             *\n *    Use this routine to free the memory allocated by a previous call to                      *\n *    Load_Sample.                                                                             *\n *                                                                                             *\n * INPUT:   sample   -- Pointer to the sample to be freed.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Free_Sample(void const *sample)\n{\n\tif (sample) Free((void *)sample);\n}\n\n\n\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Sound_Timer_Callback -- windows timer callback for sound maintenance                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:01PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid CALLBACK Sound_Timer_Callback ( UINT, UINT, DWORD, DWORD, DWORD )\n{\n\t//if (!InTimerCallback){\n\t\t//InTimerCallback++;\n\t\t//Colour_Debug (5);\n\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t\tmaintenance_callback();\n\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t//Colour_Debug (0);\n\t\t//InTimerCallback--;\n\t//}\n}\n\nvoid Sound_Thread (void *)\n{\n\tDuplicateHandle (GetCurrentProcess(), GetCurrentThread() , GetCurrentProcess() ,&SoundThreadHandle , THREAD_ALL_ACCESS , TRUE , 0);\n\tSetThreadPriority (SoundThreadHandle, THREAD_PRIORITY_TIME_CRITICAL);\n\tSoundThreadActive = TRUE;\n\n\twhile (!AudioDone){\n\n\t\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\t\tmaintenance_callback();\n\t\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\tSleep(1000/40);\n\t}\n\n\tSoundThreadActive = FALSE;\n}\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Set_Primary_Buffer_Format -- set the format of the primary sound buffer                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   TRUE if successfully set                                                          *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    12/22/95 4:06PM ST : Created                                                             *\n *=============================================================================================*/\n\nBOOL Set_Primary_Buffer_Format(void)\n{\n\tif (SoundObject && PrimaryBufferPtr){\n\t\treturn (PrimaryBufferPtr->SetFormat ( &PrimaryBuffFormat ) == DS_OK);\n\t}\n\treturn (FALSE);\n}\n\n\n\n/***********************************************************************************************\n * Print_Sound_Error -- show error messages from failed sound initialisation                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    error text                                                                        *\n *           handle to window                                                                  *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    2/7/96 10:17AM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Print_Sound_Error(char *sound_error, HWND window)\n{\n\tMessageBox(window, sound_error, \"Command & Conquer\", MB_ICONEXCLAMATION|MB_OK);\n}\n\n\n\n/***********************************************************************************************\n * Audio_Init -- Initialise the sound system                                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    window - window to send callback messages to                                      *\n *           maximum bits_per_sample - 8 or 16                                                 *\n *           stereo - will stereo samples be played                                            *\n *           rate - maximum sample rate required                                               *\n *           reverse_channels                                                                  *\n *                                                                                             *\n * OUTPUT:   TRUE if correctly initialised                                                     *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   Unknown....                                                                               *\n *   08-24-95 10:01am ST : Modified for Windows 95 Direct Sound                                *\n *=============================================================================================*/\n\nBOOL Audio_Init( HWND window , int bits_per_sample, BOOL stereo , int rate , int reverse_channels)\n{\n\tint\tindex;\n\tint\tsample=1;\n\tshort old_bits_per_sample;\n\tshort old_block_align;\n\tlong\told_bytes_per_sec;\n\n\n\tInit_Locked_Data();\n\tmemset(&LockedData.SampleTracker[0], 0, sizeof(LockedData.SampleTracker));\n\n\tif ( !SoundObject ){\n\n\t\t/*\n\t\t**\tCreate the direct sound object\n\t\t*/\n\t\tif ( DirectSoundCreate (NULL,&SoundObject,NULL) !=DS_OK ) {\n\t\t\tPrint_Sound_Error(\"Warning - Unable to create Direct Sound Object\",window);\n\t\t\treturn (FALSE);\n\t\t}\n\n\t\t/*\n\t\t**\tGive ourselves exclusive access to it\n\t\t*/\n\t\tif ( SoundObject->SetCooperativeLevel( window, DSSCL_PRIORITY ) != DS_OK){\n\t\t\tPrint_Sound_Error(\"Warning - Unable to set Direct Sound cooperative level\",window);\n\t\t\tSoundObject->Release();\n\t\t\tSoundObject = NULL;\n\t\t\treturn (FALSE);\n\t\t}\n\n\t\t/*\n\t\t** Set up the primary buffer structure\n\t\t*/\n\t\tmemset (&BufferDesc , 0 , sizeof(DSBUFFERDESC));\n\t\tBufferDesc.dwSize=sizeof(DSBUFFERDESC);\n\t\tBufferDesc.dwFlags=DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;\n\n\t\t/*\n\t\t**\tSet up the primary buffer format\n\t\t*/\n\t\tmemset (&DsBuffFormat , 0 , sizeof(WAVEFORMATEX));\n\t\tDsBuffFormat.wFormatTag\t\t= WAVE_FORMAT_PCM;\n\t\tDsBuffFormat.nChannels\t\t= (unsigned short) (1 + stereo);\n\t\tDsBuffFormat.nSamplesPerSec\t= rate;\n\t\tDsBuffFormat.wBitsPerSample\t= (short) bits_per_sample;\n\t\tDsBuffFormat.nBlockAlign\t= (unsigned short)( (DsBuffFormat.wBitsPerSample/8) * DsBuffFormat.nChannels);\n\t\tDsBuffFormat.nAvgBytesPerSec= DsBuffFormat.nSamplesPerSec * DsBuffFormat.nBlockAlign;\n\t\tDsBuffFormat.cbSize = 0;\n\n\n\t\t/*\n\t\t** Make a copy of the primary buffer description so we can reset its format later\n\t\t*/\n\t\tmemcpy (&PrimaryBufferDesc , &BufferDesc , sizeof(DSBUFFERDESC));\n\t\tmemcpy (&PrimaryBuffFormat , &DsBuffFormat , sizeof(WAVEFORMATEX));\n\n\t\t/*\n\t\t**\tCreate the primary buffer object\n\t\t*/\n\t\tif ( SoundObject->CreateSoundBuffer (&PrimaryBufferDesc ,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&PrimaryBufferPtr ,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tNULL ) !=DS_OK ){\n\t\t\tPrint_Sound_Error(\"Warning - Unable to create Direct Sound primary buffer\",window);\n\t\t\tSoundObject->Release();\n\t\t\tSoundObject = NULL;\n\t\t\treturn (FALSE);\n\t\t}\n\n\t\t/*\n\t\t** Set the format of the primary sound buffer\n\t\t**\n\t\t*/\n\t\tif (!Set_Primary_Buffer_Format()){\n\n\t\t\t/*\n\t\t\t** If we failed to create a 16 bit primary buffer - try for an 8bit one\n\t\t\t*/\n\t\t\tif (DsBuffFormat.wBitsPerSample == 16){\n\t\t\t\t/*\n\t\t\t\t** Save the old values\n\t\t\t\t*/\n\t\t\t\told_bits_per_sample\t= DsBuffFormat.wBitsPerSample;\n\t\t\t\told_block_align\t\t= DsBuffFormat.nBlockAlign;\n\t\t\t\told_bytes_per_sec\t\t= DsBuffFormat.nAvgBytesPerSec;\n\n\t\t\t\t/*\n\t\t\t\t** Set up the 8-bit ones\n\t\t\t\t*/\n\t\t\t\tDsBuffFormat.wBitsPerSample\t= 8;\n\t\t\t\tDsBuffFormat.nBlockAlign\t= (unsigned short)( (DsBuffFormat.wBitsPerSample/8) * DsBuffFormat.nChannels);\n\t\t\t\tDsBuffFormat.nAvgBytesPerSec= DsBuffFormat.nSamplesPerSec * DsBuffFormat.nBlockAlign;\n\n\t\t\t\t/*\n\t\t\t\t** Make a copy of the primary buffer description so we can reset its format later\n\t\t\t\t*/\n\t\t\t\tmemcpy (&PrimaryBufferDesc , &BufferDesc , sizeof(DSBUFFERDESC));\n\t\t\t\tmemcpy (&PrimaryBuffFormat , &DsBuffFormat , sizeof(WAVEFORMATEX));\n\t\t\t}\n\n\t\t\tif (!Set_Primary_Buffer_Format()){\n\n\t\t\t\t/*\n\t\t\t\t** We failed to set any useful format so print up an error message and give up\n\t\t\t\t*/\n\t\t\t\tPrimaryBufferPtr->Release();\n\t\t\t\tPrimaryBufferPtr = NULL;\n\t\t\t\tSoundObject->Release();\n\t\t\t\tSoundObject = NULL;\n\n\t\t\t\tPrint_Sound_Error(\"Warning - Your sound card does not meet the products audio requirements\",window);\n\n\t\t\t\treturn (FALSE);\n\t\t\t}else{\n\n\t\t\t\t/*\n\t\t\t\t** OK, got an 8bit sound buffer. Not perfect but it will do\n\t\t\t\t** We still want 16 bit secondary buffers so restore those values\n\t\t\t\t*/\n\t\t\t\tDsBuffFormat.wBitsPerSample\t= old_bits_per_sample;\n\t\t\t\tDsBuffFormat.nBlockAlign\t\t= old_block_align;\n\t\t\t\tDsBuffFormat.nAvgBytesPerSec\t= old_bytes_per_sec;\n\t\t\t}\n\t\t}\n\n\n\t\t/*\n\t\t** Start the primary sound buffer playing\n\t\t**\n\t\t*/if ( PrimaryBufferPtr->Play(0,0,DSBPLAY_LOOPING) != DS_OK ){\n\t\t\tPrint_Sound_Error(\"Unable to play Direct Sound primary buffer\",window);\n\t\t\tPrimaryBufferPtr->Release();\n\t\t\tPrimaryBufferPtr = NULL;\n\t\t\tSoundObject->Release();\n\t\t\tSoundObject = NULL;\n\t\t\treturn (FALSE);\n\t\t}\n\n\t\tLockedData.DigiHandle=1;\n\n\n\t\t/*\n\t\t** Initialise the global critical section object for sound thread syncronisation\n\t\t*/\n\t\tInitializeCriticalSection(&GlobalAudioCriticalSection);\n\n\t\t/*\n\t\t** Initialise the Windows timer system to provide us with a callback\n\t\t**\n\t\t*/\n\t\tSoundTimerHandle = timeSetEvent ( 1000/MAINTENANCE_RATE , 1 , Sound_Timer_Callback , 0 , TIME_PERIODIC);\n\t\tAudioDone = FALSE;\n\t\t//_beginthread(&Sound_Thread, NULL, 16*1024, NULL);\n\n\t\t/*\n\t\t**\tDefine the format for the secondary sound buffers\n\t\t*/\n\t\tBufferDesc.dwFlags=DSBCAPS_CTRLVOLUME;\n\t\tBufferDesc.dwBufferBytes=SECONDARY_BUFFER_SIZE;\n\t\tBufferDesc.lpwfxFormat = (LPWAVEFORMATEX) &DsBuffFormat;\n\n\n\n\t\t/*\n    \t** Allocate a decompression buffer equal to the size of a SONARC frame\n\t\t** block.\n    \t*/\n    \tLockedData.UncompBuffer = Alloc(LARGEST_SONARC_BLOCK + 50, (MemoryFlagType)(MEM_NORMAL|MEM_CLEAR|MEM_LOCK));\n\n    \t/*\n    \t** Allocate once secondary direct sound buffer for each simultaneous sound effect\n\t\t**\n    \t*/\n\t\tfor (index = 0; index < MAX_SFX; index++) {\n\n\t\t\tSoundObject->CreateSoundBuffer (&BufferDesc , &LockedData.SampleTracker[index].PlayBuffer , NULL);\n\n\t\t\tLockedData.SampleTracker[index].PlaybackRate\t= rate;\n\t\t\tLockedData.SampleTracker[index].Stereo\t\t\t= (stereo) ? AUD_FLAG_STEREO : 0;\n\t\t\tLockedData.SampleTracker[index].BitSize \t\t= (bits_per_sample == 16) ? AUD_FLAG_16BIT : 0;\n\t\t\tLockedData.SampleTracker[index].FileHandle \t= WW_ERROR;\n\t\t\tLockedData.SampleTracker[index].QueueBuffer \t= NULL;\n\t\t\tInitializeCriticalSection (&LockedData.SampleTracker[index].AudioCriticalSection);\n\n\t\t}\n\n\t\tSoundType = (SFX_Type)sample;\n\t\tSampleType = (Sample_Type)sample;\n\t\tReverseChannels = reverse_channels;\n\n\t}\n\n\treturn(TRUE);\n}\n\n\n/***********************************************************************************************\n * Sound_End -- Uninitializes the sound driver.                                                *\n *                                                                                             *\n *    This routine will uninitialize the sound driver (if any was                              *\n *    installed).  This routine must be called at program termination                          *\n *    time.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/23/1991 JLB : Created.                                                                 *\n *   11/02/1995 ST  : Modified for Direct Sound                                                *\n *=============================================================================================*/\nvoid Sound_End(void)\n{\n\n\tint\tindex;\n\n\tif (SoundObject && PrimaryBufferPtr){\n\t\t/*\n\t\t** Stop all sounds and release the Direct Sound secondary sound buffers\n\t\t*/\n\t\tfor (index=0 ; index < MAX_SFX; index++){\n\t\t\tif ( LockedData.SampleTracker[index].PlayBuffer ){\n\t\t\t\tStop_Sample (index);\n\t\t\t\tLockedData.SampleTracker[index].PlayBuffer->Stop();\n\t\t\t\tLockedData.SampleTracker[index].PlayBuffer->Release();\n\t\t\t\tLockedData.SampleTracker[index].PlayBuffer = NULL;\n\t\t\t\tDeleteCriticalSection(&LockedData.SampleTracker[index].AudioCriticalSection);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Stop and release the direct sound primary buffer\n\t*/\n\tif (PrimaryBufferPtr){\n\t\tPrimaryBufferPtr->Stop();\n\t\tPrimaryBufferPtr->Release();\n\t\tPrimaryBufferPtr = NULL;\n\t}\n\n\t/*\n\t** Release the Direct Sound Object\n\t*/\n\tif (SoundObject){\n\t\tSoundObject->Release();\n\t\tSoundObject = NULL;\n\t}\n\n\n\tif (LockedData.UncompBuffer) {\n    \tFree(LockedData.UncompBuffer);\n\t\tLockedData.UncompBuffer = 0;\n\t}\n\n\t/*\n\t** Remove the Windows timer event we installed for the sound callback\n\t*/\n\tif (SoundTimerHandle){\n\t\ttimeKillEvent(SoundTimerHandle);\n\t\tSoundTimerHandle = 0;\n\t}\n\tAudioDone = TRUE;\n\n\t/*\n\t** Since the timer has stopped, we are finished with our global critical section.\n\t*/\n\tDeleteCriticalSection(&GlobalAudioCriticalSection);\n}\n\n\n\n\n/***********************************************************************************************\n * Stop_Sample -- Stops any currently playing sampled sound.                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1992 JLB : Created.                                                                 *\n *   11/2/95 4:09PM ST : Modified for Direct Sound                                             *\n *=============================================================================================*/\nvoid Stop_Sample(int handle)\n{\n\tif (LockedData.DigiHandle != -1 && (unsigned)handle < MAX_SFX) {\n\n\t\tEnterCriticalSection (&GlobalAudioCriticalSection);\n\n\t\tif (LockedData.SampleTracker[handle].Active || LockedData.SampleTracker[handle].Loading) {\n\n\t\t\tLockedData.SampleTracker[handle].Active = FALSE;\n\n\t\t\tif (!LockedData.SampleTracker[handle].IsScore) {\n          \tLockedData.SampleTracker[handle].Original = NULL;\n\t\t\t}\n\n\t\t\tLockedData.SampleTracker[handle].Priority = 0;\n\n\t\t\t/*\n          **  Stop the sample if it is playing.\n          */\n\t\t\tif (!LockedData.SampleTracker[handle].Loading) {\n\t\t\t\tLockedData.SampleTracker[handle].PlayBuffer->Stop();\n          }\n\n\t\t\tLockedData.SampleTracker[handle].Loading = FALSE;\n\n          /*\n\t\t\t**  If this is a streaming sample, then close the source file.\n          */\n\t\t\tif (LockedData.SampleTracker[handle].FileHandle != WW_ERROR) {\n\t\t\t\tClose_File(LockedData.SampleTracker[handle].FileHandle);\n\t\t\t\tLockedData.SampleTracker[handle].FileHandle = WW_ERROR;\n\t\t\t}\n\n\t\t\tLockedData.SampleTracker[handle].QueueBuffer = NULL;\n\t\t}\n\t\tLeaveCriticalSection (&GlobalAudioCriticalSection);\n\t}\n}\n\n\n/***********************************************************************************************\n * Sample_Status -- Queries the current playing sample status (if any).                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nBOOL Sample_Status(int handle)\n{\n\tDWORD\tstatus;\n\n\t/*\n\t** If its an invalid handle or we do not have a sound driver then\n\t** the sample in question is not playing.\n\t*/\n\tif (LockedData.DigiHandle == -1 || (unsigned)handle >= MAX_SFX) return(FALSE);\n\n\t/*\n\t** If the sample is loading, then for all intents and purposes the\n\t** sample is playing.\n\t*/\n\tif (LockedData.SampleTracker[handle].Loading) return(TRUE);\n\n\t/*\n\t** If the sample is not active, then it is not playing\n\t*/\n\tif (!LockedData.SampleTracker[handle].Active) return(FALSE);\n\n\t/*\n\t** If we made it this far, then the Sample is still playing if sos says\n\t** that it is.\n\t*/\n\tDumpBuffer = LockedData.SampleTracker[handle].PlayBuffer;\n\tif (LockedData.SampleTracker[handle].PlayBuffer->GetStatus( &status ) == DS_OK){\n\t\treturn ( (DSBSTATUS_PLAYING & status) || (DSBSTATUS_LOOPING & status) );\n\t}else{\n\t\treturn (TRUE);\n\t}\n}\n\n\n\n/***********************************************************************************************\n * Is_Sample_Playing -- returns the play state of a sample                                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to sample data                                                                *\n *                                                                                             *\n * OUTPUT:   TRUE if sample is currently playing                                               *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:11PM ST : Commented                                                            *\n *=============================================================================================*/\n\nBOOL Is_Sample_Playing(void const * sample)\n{\n\tint index;\n\n\t//EnterCriticalSection(&GlobalAudioCriticalSection);\n\n\tif (!sample) {\n\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\treturn FALSE;\n\t}\n\tfor (index = 0; index < MAX_SFX; index++) {\n\t\tif (LockedData.SampleTracker[index].Original == sample && Sample_Status(index)) {\n\t\t\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\t\t\treturn (TRUE);\n\t\t}\n\t}\n\t//LeaveCriticalSection(&GlobalAudioCriticalSection);\n\treturn (FALSE);\n}\n\n\n/***********************************************************************************************\n * Stop_Sample_Playing -- stops a playing sample                                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to sample data                                                                *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:13PM ST : Commented                                                            *\n *=============================================================================================*/\n\nvoid Stop_Sample_Playing(void const * sample)\n{\n\tint index;\n\n\tif (sample) {\n\t\tfor (index = 0; index < MAX_SFX; index++) {\n\t\t\tif (LockedData.SampleTracker[index].Original == sample) {\n\t\t\t\tStop_Sample(index);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n\n\n/***********************************************************************************************\n * Get_Free_Sample_Handle -- finds a free slot in which to play a new sample                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    priority of sample we want to play                                                *\n *                                                                                             *\n * OUTPUT:   Handle or -1 if none free                                                         *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:14PM ST : Added function header                                                *\n *=============================================================================================*/\n\nint Get_Free_Sample_Handle(int priority)\n{\n\tint     id;\n\n\t/*\n\t**      Find a free SFX holding buffer slot.\n\t*/\n\tfor (id = MAX_SFX - 1; id >= 0; id--) {\n\t\tif (!LockedData.SampleTracker[id].Active && !LockedData.SampleTracker[id].Loading) {\n\t\t\tif (!StartingFileStream && LockedData.SampleTracker[id].IsScore) {\n\t\t\t\tStartingFileStream = TRUE;      // Ensures only one channel is kept free for scores.\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (id < 0) {\n\t\tfor (id = 0; id < MAX_SFX; id++) {\n\t\t\tif (LockedData.SampleTracker[id].Priority <= priority) break;\n\t\t}\n\n\t\tif (id == MAX_SFX) {\n\t\t\treturn(-1);             // Cannot play!\n\t\t}\n\t\tStop_Sample(id);                                                        // This sample gets clobbered.\n\t}\n\n\tif (id == -1) {\n\t\treturn -1;\n\t}\n\n\tif (LockedData.SampleTracker[id].FileHandle != WW_ERROR) {\n\t\tClose_File(LockedData.SampleTracker[id].FileHandle);\n\t\tLockedData.SampleTracker[id].FileHandle = WW_ERROR;\n\t}\n\n\tif (LockedData.SampleTracker[id].Original && !LockedData.SampleTracker[id].IsScore) {\n\t\tLockedData.SampleTracker[id].Original = NULL;\n\t}\n\tLockedData.SampleTracker[id].IsScore = FALSE;\n\treturn(id);\n}\n\nint Play_Sample(void const *sample, int priority, int volume, signed short panloc)\n{\n\t\t  return(Play_Sample_Handle(sample, priority, volume, panloc, Get_Free_Sample_Handle(priority)));\n}\n\n\n\n\n\n/***********************************************************************************************\n * Attempt_Audio_Restore -- tries to restore the direct sound buffers                          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to direct sound buffer                                                        *\n *                                                                                             *\n * OUTPUT:   TRUE if buffer was successfully restored                                          *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/20/96 9:47AM ST : Created                                                              *\n *=============================================================================================*/\n\nBOOL Attempt_Audio_Restore (LPDIRECTSOUNDBUFFER sound_buffer)\n{\n\n\tint \treturn_code;\n\tDWORD\tplay_status;\n\tint\trestore_attempts=0;\n\n\t/*\n\t** Call the audio focus loss function if it has been set up\n\t*/\n\tif (Audio_Focus_Loss_Function){\n\t\tAudio_Focus_Loss_Function();\n\t}\n\n\t/*\n\t** Try to restore the sound buffer\n\t*/\n\tdo{\n\t\tRestore_Sound_Buffers();\n\t\treturn_code = sound_buffer->GetStatus ( &play_status );\n\n\t} while (restore_attempts++<2 && return_code == DSERR_BUFFERLOST);\n\n\treturn ((BOOL) ~(return_code == DSERR_BUFFERLOST));\n}\n\n\n\n/***********************************************************************************************\n * Convert_HMI_To_Direct_Sound_Volume -- Converts a linear volume value into an expotential    *\n *                                        value                                                *\n *                                                                                             *\n * This function converts a linear C&C volume in the range 0-255 (255 loudest) to a direct     *\n *  sound volume in the range 0 to -10000 (with 0 being the loadest)                           *\n *                                                                                             *\n * INPUT:    volume in range 0-255                                                             *\n *                                                                                             *\n * OUTPUT:   volume in range -10000 to 0                                                       *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * Note: The 27.685 value comes from 255 divided by the log of 10001                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/18/96 11:36AM ST : Created                                                             *\n *=============================================================================================*/\nint Convert_HMI_To_Direct_Sound_Volume(int volume)\n{\n\tif (volume == 0) return -10000;\n\tif (volume == 255) return 0;\n\n\tfloat vol = (float)volume;\n\tfloat retval = exp ( (255.0-vol)/27.68597374) -1;\n\treturn ((int)-retval);\n}\n\n\n\n\n\n/***********************************************************************************************\n * Play_Sample_Vol -- Plays a digitized sample.                                                *\n *                                                                                             *\n *    Use this routine to play a previously loaded digitized sample.                           *\n *                                                                                             *\n * INPUT:   sample   -- Sample pointer as returned from Load_Sample.                           *\n *                                                                                             *\n *          volume   -- The volume to play (0..255 with 255=loudest).                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *   05/24/1992 JLB : Volume support -- Soundblaster Pro                                       *\n *   04/22/1994 JLB : Multiple sample playback rates.                                          *\n *   11/02/1995 ST  : Windows Direct Sound support                                             *\n *=============================================================================================*/\nextern BOOL Any_Locked(void);\nint Play_Sample_Handle(void const *sample, int priority, int volume, signed short , int id)\n{\n\tAUDHeaderType                   RawHeader;\n\tSampleTrackerType               *st=NULL;       // Working pointer to sample tracker structure.\n\n\tLPVOID\t\t\t\tplay_buffer_ptr;\t\t//pointer to locked direct sound buffer\n\tLPVOID\t\t\t\tdummy_buffer_ptr;\t\t//dummy pointer to second area of locked direct sound buffer\n\tDWORD\t\t\t\t\tlock_length1;\n\tDWORD\t\t\t\t\tlock_length2;\n\tDWORD\t\t\t\t\tplay_status;\n\tHRESULT\t\t\t\treturn_code;\n\tint\t\t\t\t\tretries=0;\n\n\n\tif (Any_Locked()) return(0);\n\n\tst = &LockedData.SampleTracker[id];\n\t//EnterCriticalSection (&GlobalAudioCriticalSection);\n\n\tif (!sample || LockedData.DigiHandle == -1) {\n\t\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\treturn(-1);\n\t}\n\n\tif (id == -1) {\n\t\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\treturn -1;\n\t}\n\n\t/*\n\t**      Fetch the control bytes from the start of the sample data.\n\t*/\n\tMem_Copy((void *)sample, (void *)&RawHeader, sizeof(RawHeader));\n\n\t/*\n\t** Fudge the sample rate to 22k\n\t*/\n\tif (RawHeader.Rate <24000 && RawHeader.Rate >20000) RawHeader.Rate = 22050;\n\n\t/*\n\t**      Prepare the sample tracker structure for processing of this\n\t**      sample.  Fill the structure with data that can be determined\n\t**      before the sample is started.\n\t*/\n\tEnterCriticalSection(&GlobalAudioCriticalSection);\n\tst->Compression \t\t\t= (SCompressType) ((unsigned char)RawHeader.Compression);\n\tst->Original            = sample;\n\tst->OriginalSize        = RawHeader.Size + sizeof(RawHeader);\n\tst->Priority            = (short)priority;\n\tst->DontTouch           = TRUE;\n\tst->Odd\t\t\t\t\t\t= 0;\n\tst->Reducer             = 0;\n\tst->Restart             = FALSE;\n\tst->QueueBuffer \t\t\t= NULL;\n\tst->QueueSize           = NULL;\n\tst->TrailerLen  \t\t\t= 0;\n\tst->Remainder           = RawHeader.Size;\n\tst->Source              = Add_Long_To_Pointer((void *)sample, sizeof(RawHeader));\n\tst->Service             = FALSE;\n\tLeaveCriticalSection(&GlobalAudioCriticalSection);\n\n    /*\n\t ** If the code in question using HMI based compression then we need\n    ** to set up for uncompressing it.\n\t */\n    if (st->Compression == SCOMP_SOS) {\n\t\tst->sosinfo.wChannels    = (RawHeader.Flags & AUD_FLAG_STEREO) ? 2  : 1;\n\t\tst->sosinfo.wBitSize             = (RawHeader.Flags & AUD_FLAG_16BIT)  ? 16 : 8;\n\t\tst->sosinfo.dwCompSize   = RawHeader.Size;\n\t\tst->sosinfo.dwUnCompSize = RawHeader.Size * ( st->sosinfo.wBitSize / 4 );\n\t\tsosCODECInitStream(&st->sosinfo);\n\t}\n\n\t/*\n\t** If the sample rate , bits per sample or stereo capabilities of the buffer do not\n\t** match the sample then reallocate the direct sound buffer with the required capabilities\n\t*/\n\tif (  ( RawHeader.Rate != st->PlaybackRate ) ||\n\t\t\t( ( RawHeader.Flags & AUD_FLAG_16BIT ) != ( st->BitSize & AUD_FLAG_16BIT ) ) ||\n\t\t\t( ( RawHeader.Flags & AUD_FLAG_STEREO) != ( st->Stereo & AUD_FLAG_STEREO ) ) ) {\n\n\t\tst->Active=0;\n\t\tst->Service=0;\n\t\tst->MoreSource=0;\n\n\t\t/*\n\t\t** Stop the sound buffer playing\n\t\t*/\n\t\tDumpBuffer = st->PlayBuffer;\n\t\tdo {\n\t\t\treturn_code = st->PlayBuffer->GetStatus ( &play_status );\n\t\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t\t}\n\t\t}while (return_code == DSERR_BUFFERLOST);\n\n\t\tif (play_status & (DSBSTATUS_PLAYING | DSBSTATUS_LOOPING) ){\n\t\t\tst->PlayBuffer->Stop();\n\t\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t\t}\n\t\t}\n\n\t\tst->PlayBuffer->Release();\n\t\tst->PlayBuffer=NULL;\n\n\t\tDsBuffFormat.nSamplesPerSec\t= (unsigned short int) RawHeader.Rate;\n\t\tDsBuffFormat.nChannels\t\t\t= (RawHeader.Flags & AUD_FLAG_STEREO) ? 2 : 1 ;\n\t\tDsBuffFormat.wBitsPerSample\t= (RawHeader.Flags & AUD_FLAG_16BIT) ? 16 : 8 ;\n\t\tDsBuffFormat.nBlockAlign\t= (short) ((DsBuffFormat.wBitsPerSample/8) * DsBuffFormat.nChannels);\n\t\tDsBuffFormat.nAvgBytesPerSec= DsBuffFormat.nSamplesPerSec * DsBuffFormat.nBlockAlign;\n\n\t\t/*\n\t\t** Create the new sound buffer\n\t\t*/\n\t\treturn_code= SoundObject->CreateSoundBuffer (&BufferDesc , &st->PlayBuffer , NULL);\n\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t}\n\t\t/*\n\t\t** Just return if the create failed unexpectedly\n\t\t**\n\t\t** If we failed then flag the buffer as having an impossible format so it wont match\n\t\t** any sample. This will ensure that we try and create the buffer again next time its used.\n\t\t*/\n\t\tif (return_code!=DS_OK && return_code!=DSERR_BUFFERLOST){\n\t\t\tst->PlaybackRate = 0;\n\t\t\tst->Stereo = 0;\n\t\t\tst->BitSize = 0;\n\t\t\treturn(-1);\n\t\t}\n\n\t\t/*\n\t\t** Remember the format of the new buffer\n\t\t*/\n\t\tst->PlaybackRate \t= RawHeader.Rate;\n\t\tst->Stereo\t\t\t= RawHeader.Flags & AUD_FLAG_STEREO;\n\t\tst->BitSize \t\t= RawHeader.Flags & AUD_FLAG_16BIT;\n\t}\n\n\t/*\n\t**      Fill in 3/4 of the play buffer.\n\t*/\n\n\t//\n\t// Stop the sound buffer playing before we lock it\n\t//\n\tdo {\n\t\tDumpBuffer = st->PlayBuffer;\n\t\treturn_code = st->PlayBuffer->GetStatus ( &play_status );\n\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t}\n\t} while (return_code==DSERR_BUFFERLOST);\n\n\tif (play_status & (DSBSTATUS_PLAYING | DSBSTATUS_LOOPING) ){\n\t\tst->Active=0;\n\t\tst->Service=0;\n\t\tst->MoreSource=0;\n\t\tst->PlayBuffer->Stop();\n\t}\n\t//\n\t// Lock the direct sound buffer so we can write to it\n\t//\n\tdo {\n\t\treturn_code = st->PlayBuffer->Lock (\t0 ,\n\t\t\t\t\t\t\t\t\t\tSECONDARY_BUFFER_SIZE,\n\t\t\t\t\t\t\t\t\t\t&play_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t&lock_length1,\n\t\t\t\t\t\t\t\t\t\t&dummy_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t&lock_length2,\n\t\t\t\t\t\t\t\t\t\t0 );\n\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t}\n\t} while (return_code==DSERR_BUFFERLOST);\n\n\tif (return_code != DS_OK) {\n\t\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\treturn (-1);\n\t}\n\n\t//\n\t// Decompress the sample into the direct sound buffer\n\t//\n\tst->DestPtr=(void*)Sample_Copy ( \tst,\n\t\t\t\t\t\t\t\t&st->Source,\n\t\t\t\t\t\t\t\t&st->Remainder,\n\t\t\t\t\t\t\t\t&st->QueueBuffer,\n\t\t\t\t\t\t\t\t&st->QueueSize,\n\t\t\t\t\t\t\t\tplay_buffer_ptr,\n\t\t\t\t\t\t\t\tSECONDARY_BUFFER_SIZE*1/4,\n\t\t\t\t\t\t\t\tst->Compression,\n\t\t\t\t\t\t\t\t&st->Trailer[0],\n\t\t\t\t\t\t\t\t&st->TrailerLen);\n\n\tif ( st->DestPtr==(void*) (SECONDARY_BUFFER_SIZE*1/4) ){\n\n\t\t// Must be more data to copy so we dont need to zero the buffer\n\t\tst->MoreSource=TRUE;\n\t\tst->Service=TRUE;\n\t\tst->OneShot=FALSE;\n\t} else {\n\n\t\t// Whole sample is in the buffer so flag that we dont need to\n\t\t// copy more. Clear out the end of the buffer so that it\n\t\t// goes quiet if we play past the end\n\t\tst->MoreSource=FALSE;\n\t\tst->OneShot=TRUE;\n\t\tst->Service=TRUE;\t\t\t\t//We still need to service it so that we can stop it when\n\t\t\t\t\t\t\t\t\t\t\t// it plays past the end of the sample data\n\t\t//memset ( (char*)( (unsigned)play_buffer_ptr + (unsigned)st->DestPtr ), 0 , SECONDARY_BUFFER_SIZE - (unsigned)st->DestPtr );\n\t\tmemset ( (char*)( (unsigned)play_buffer_ptr + (unsigned)st->DestPtr ), 0 , SECONDARY_BUFFER_SIZE/4);\n\t}\n\n\tst->PlayBuffer->Unlock(\tplay_buffer_ptr,\n\t\t\t\t\t\t\tlock_length1,\n\t\t\t\t\t\t\tdummy_buffer_ptr,\n\t\t\t\t\t\t\tlock_length2);\n\n\n\t/*\n    **\n    **  Set the volume of the sample.\n    **\n    */\n\tst->Volume = (volume << 7);\n\tdo {\n\n\t\t//return_code = st->PlayBuffer->SetVolume ( Convert_HMI_To_Direct_Sound_Volume(volume));\n\t\tst->PlayBuffer->SetVolume ( Convert_HMI_To_Direct_Sound_Volume( ( LockedData.SoundVolume*volume)/256) );\n\t\t//return_code = st->PlayBuffer->SetVolume (- ( ( (32768- ( (st->Volume >> 8) *LockedData.SoundVolume) )\n\t\t//\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*1000) >>15 ) );\n\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t}\n\t} while (return_code==DSERR_BUFFERLOST);\n\n\n\t/*\n\t** Make sure the primary sound buffer is playing\n\t*/\n\tif (!Start_Primary_Sound_Buffer(FALSE)){\n\t\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\treturn(-1);\n\t}\n\n\n\t/*\n\t** Set the buffers play pointer to the beginning of the buffer\n\t*/\n\tdo {\n\t\treturn_code = st->PlayBuffer->SetCurrentPosition (0);\n\t\tif (return_code==DSERR_BUFFERLOST){\n\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t}\n\t} while (return_code==DSERR_BUFFERLOST);\n\n\n\t/*\n    ** Start the sample playing now.\n\t*/\n\tdo\n\t{\n\t\treturn_code = st->PlayBuffer->Play (0,0,DSBPLAY_LOOPING);\n\n\t\tswitch (return_code){\n\n\t\t\tcase DS_OK :\n\t\t\t\tEnterCriticalSection (&GlobalAudioCriticalSection);\n\t\t\t\tst->Active=TRUE;\n\t\t\t\tst->Handle=(short)id;\n\t\t\t\tst->DontTouch = FALSE;\n\t\t\t\tLeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\t\t\treturn (st->Handle);\n\n\t\t\tcase DSERR_BUFFERLOST :\n\t\t\t\tif (!Attempt_Audio_Restore(st->PlayBuffer)) return(-1);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tst->Active=FALSE;\n\t\t\t\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\t\t\t\treturn (st->Handle);\n\t\t}\n\n\t} while (return_code==DSERR_BUFFERLOST);\n\n\t//LeaveCriticalSection (&GlobalAudioCriticalSection);\n\treturn (st->Handle);\n}\n\n\n\n\n\n/***********************************************************************************************\n * Restore_Sound_Buffers -- restore the sound buffers                                          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/3/95 3:53PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Restore_Sound_Buffers ( void )\n{\n\n\tif (PrimaryBufferPtr){\n\t\tPrimaryBufferPtr->Restore();\n\t}\n\n\n\tfor ( int index = 0; index < MAX_SFX; index++) {\n\t\tif (LockedData.SampleTracker[index].PlayBuffer){\n\t\t\tLockedData.SampleTracker[index].PlayBuffer->Restore();\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Set_Sound_Vol -- sets the overall volume for sampled sounds                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    volume                                                                            *\n *                                                                                             *\n * OUTPUT:   the previous volume setting                                                       *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:19PM ST : Added function header                                                *\n *=============================================================================================*/\n\nint Set_Sound_Vol(int volume)\n{\n\tint old;\n \told = LockedData.SoundVolume;\n \tLockedData.SoundVolume = volume & 0xFF;\n\treturn(old);\n}\n\n\n/***********************************************************************************************\n * Set_Score_Vol -- sets the overall volume for music scores                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    volume                                                                            *\n *                                                                                             *\n * OUTPUT:   the previous volume setting                                                       *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:19PM ST : Added function header                                                *\n *=============================================================================================*/\nint Set_Score_Vol(int volume)\n{\n\tint old;\n\tSampleTrackerType\t*st;\t\t\t\t\t//ptr to SampleTracker structure\n\n\told = LockedData.ScoreVolume;\n\tLockedData.ScoreVolume = volume & 0xFF;\n\n\tfor (int index=0 ; index<MAX_SFX ; index++){\n\t\tst = &LockedData.SampleTracker[index];\n\n\t\tif (st->IsScore && st->Active){\n\t\t\t//st->PlayBuffer->SetVolume (- ( ( (32768- ( (st->Volume >> 8) *LockedData.ScoreVolume) )\n\t\t\t//\t\t\t\t\t\t\t\t\t\t\t\t\t\t*1000) >>15 ) );\n\n\t\t\t//st->PlayBuffer->SetVolume ( Convert_HMI_To_Direct_Sound_Volume ( st->Volume >>7 ) );\n\t\t\tst->PlayBuffer->SetVolume ( Convert_HMI_To_Direct_Sound_Volume( ( LockedData.ScoreVolume*(st->Volume >>7))/256) );\n\t\t}\n\t}\n\treturn(old);\n}\n\n\n\n/***********************************************************************************************\n * Fade_Sample -- Start a sample fading                                                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Sample handle                                                                     *\n *           fade rate                                                                         *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/2/95 4:21PM ST : Added function header                                                *\n *=============================================================================================*/\n\nvoid Fade_Sample(int handle, int ticks)\n{\n\tif (Sample_Status(handle)) {\n    \tif (!ticks || LockedData.SampleTracker[handle].Loading) {\n       \tStop_Sample(handle);\n\t\t\t} else {\n\t\t\t\tSampleTrackerType * st;\n\t\t\t\tst = &LockedData.SampleTracker[handle];\n\t\t\t\tst->Reducer = (short) ((st->Volume / ticks)+1);\n\t\t\t}\n\t}\n}\n\n\n\nint Get_Digi_Handle(void)\n{\n        return(LockedData.DigiHandle);\n}\n\n\n\n/***************************************************************************\n * SAMPLE_LENGTH -- returns length of a sample in ticks                    *\n *                                                                         *\n * INPUT:  void const *sample - pointer to the sample to get length of.    *\n *                                                                         *\n * OUTPUT: long - length of the sample in ticks (60/sec)                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/05/1995 PWG : Created.                                             *\n *=========================================================================*/\nlong Sample_Length(void const *sample)\n{\n\tAUDHeaderType\tRawHeader;\n\n\tif (!sample) return(0);\n\n\tMem_Copy((void *)sample, (void *)&RawHeader, sizeof(RawHeader));\n\n\tlong time = RawHeader.UncompSize;\n\n\t/*\n\t** If the sample is a 16 bit sample, then it will take only half\n\t** as long to play.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_16BIT) {\n\t\ttime >>= 1;\n\t}\n\n\t/*\n\t** If the sample is a stereo sample, then it will take only half\n\t** as long to play.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_STEREO) {\n\t\ttime >>= 1;\n\t}\n\n\tif (RawHeader.Rate/60) {\n\t\ttime /= (RawHeader.Rate/60);\n\t}\n\treturn(time);\n}\n\n\n\n/***********************************************************************************************\n * Start_Primary_Sound_Buffer -- start the primary sound buffer playing                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    2/1/96 12:28PM ST : Created                                                              *\n *=============================================================================================*/\nextern BOOL GameInFocus;\nBOOL Start_Primary_Sound_Buffer (BOOL forced)\n{\n\tDWORD status;\n\n\tif (PrimaryBufferPtr && GameInFocus){\n\t\tif (forced){\n\t\t\tPrimaryBufferPtr->Play(0,0,DSBPLAY_LOOPING);\n\t\t\treturn (TRUE);\n\t\t} else {\n\n\t\t\tif (PrimaryBufferPtr->GetStatus (&status) == DS_OK){\n\t\t\t\tif (! ((status & DSBSTATUS_PLAYING) || (status & DSBSTATUS_LOOPING))){\n\t\t\t\t\tPrimaryBufferPtr->Play(0,0,DSBPLAY_LOOPING);\n\t\t\t\t\treturn (TRUE);\n\t\t\t\t}else{\n\t\t\t\t\treturn (TRUE);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn (FALSE);\n}\n\n\n/***********************************************************************************************\n * Stop_Primary_Sound_Buffer -- stops the primary sound buffer from playing.                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: This stops all sound playback                                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    2/1/96 12:28PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Stop_Primary_Sound_Buffer (void)\n{\n\tif (PrimaryBufferPtr){\n\t\tPrimaryBufferPtr->Stop();\n\t\tPrimaryBufferPtr->Stop();\t      // Oh I\n\t\tPrimaryBufferPtr->Stop();\t\t\t// Hate Direct Sound\n\t\tPrimaryBufferPtr->Stop();\t\t\t// So much.....\n\t}\n\n\tfor ( int index = 0; index < MAX_SFX; index++) {\n\t\tStop_Sample(index);\n\t}\n\n}\n\n\nvoid Suspend_Audio_Thread(void)\n{\n\tif (SoundThreadActive){\n\t\t//SuspendThread(SoundThreadHandle);\n\t\ttimeKillEvent(SoundTimerHandle);\n\t\tSoundTimerHandle = NULL;\n\t\tSoundThreadActive = FALSE;\n\t}\n}\n\n\n\n\nvoid Resume_Audio_Thread(void)\n{\n\tif (!SoundThreadActive){\n\t\t//ResumeThread(SoundThreadHandle);\n\t\tSoundTimerHandle = timeSetEvent ( 1000/MAINTENANCE_RATE , 1 , Sound_Timer_Callback , 0 , TIME_PERIODIC);\n\t\tSoundThreadActive = TRUE;\n\t}\n}\n\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/SOUNDLCK.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDLCK.CPP                             *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 23, 1995   [PWG]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#define WIN32\n#include <windows.h>\n#include <windowsx.h>\n#include <objbase.h>\n#include \"dsound.h\"\n#include <mem.h>\n#include \"wwmem.h\"\n#include \"wwstd.h\"\n#include \"soundint.h\"\n\n\n\nLockedDataType LockedData;\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * INIT_LOCKED_DATA -- Initializes sound driver locked data                *\n *                                                                         *\n * INPUT:\t\tnone                                                          *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid Init_Locked_Data(void)\n{\n\n\t/*\n\t** Initialize all of the data elements that need to be locked.\n\t*/\n\tLockedData.DigiHandle\t\t\t= -1;\n\tLockedData.ServiceSomething\t= FALSE;\n\tLockedData.MagicNumber\t\t\t= 0xDEAF;\n\tLockedData.UncompBuffer\t\t\t= NULL;\n//\tLockedData.StreamBufferSize\t= (2*SECONDARY_BUFFER_SIZE)+128;\n\tLockedData.StreamBufferSize\t= (SECONDARY_BUFFER_SIZE/4)+128;\n\tLockedData.StreamBufferCount\t= 16;\n\tLockedData.SoundVolume\t\t\t= 255;\n\tLockedData.ScoreVolume\t\t\t= 255;\n\tLockedData._int\t\t\t\t\t= FALSE;\n\n\t#ifdef cuts\n\t/*\n\t** Lock the sound specific c functions that will cause us problems if\n\t** they are swapped out during an interrupt.\n\t*/\n\tDPMI_Lock(&LockedData,\t\t\t\t\t\t\t4096L);\n\tDPMI_Lock(Simple_Copy, \t\t\t\t\t\t\t4096L);\n\tDPMI_Lock(Sample_Copy, \t\t\t\t\t\t\t4096L);\n\tDPMI_Lock((void *)maintenance_callback, \t4096L);\n\tDPMI_Lock((void *)DigiCallback, \t\t\t\t4096L);\n\tDPMI_Lock((void *)HMI_TimerCallback, \t\t4096L);\n\tDPMI_Lock(Audio_Add_Long_To_Pointer,\t\t4096L);\n\tDPMI_Lock(DPMI_Unlock,\t\t\t\t\t\t\t4096L);\n\n\t/*\n\t** Lock the library functions that will cause us problems if they are\n\t** swapped out during an interrupt.\n\t*/\n\tDPMI_Lock(Mem_Copy,\t\t\t\t\t\t\t\t4096L);\n\tDPMI_Lock(Audio_Mem_Set,\t\t\t\t\t\t4096L);\n\tDPMI_Lock(__GETDS,\t\t\t\t\t\t\t\t4096L);\n\n\t/*\n\t** Finally lock the two assembly modules that need locking.  This can\n\t** be handled by calling the lock function that is local to thier module\n\t** swapped out during an interrupt.\n\t*/\n\tDecompress_Frame_Lock();\n\tsosCODEC_Lock();\n\n\t#endif\t//cuts\n}\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/STAMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : STAMP.ASM                                *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : August 23, 1993                          *\n;*                                                                         *\n;*                  Last Update : August 23, 1993   [JLB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nINCLUDE\t\"stamp.inc\"\n\nglobal\t\tC Init_Stamps:near\nglobal\t\tLastIconset:dword\nglobal\t\tMapPtr:dword\nglobal\t\tIconCount:dword\nglobal\t\tIconSize:dword\nglobal\t\tStampPtr:dword\n\n\tDATASEG\n\n\nLastIconset\tDD\t0\t; Pointer to last iconset initialized.\nStampPtr\tDD\t0\t; Pointer to icon data.\n\nIsTrans\t\tDD\t0\t; Pointer to transparent icon flag table.\n\nMapPtr\t\tDD\t0\t; Pointer to icon map.\nIconWidth\tDD\t0\t; Width of icon in pixels.\nIconHeight\tDD\t0\t; Height of icon in pixels.\nIconSize\tDD\t0\t; Number of bytes for each icon data.\nIconCount\tDD\t0\t; Number of icons in the set.\n\n\tEVEN\n\n\tCODESEG\n\n\nGLOBAL C\tBuffer_Draw_Stamp:near\nGLOBAL C\tBuffer_Draw_Stamp_Clip:near\n\n; 256 color icon system.\n\n;***********************************************************\n; INIT_STAMPS\n;\n; VOID cdecl Init_Stamps(VOID *icondata);\n;\n; This routine initializes the stamp data.\n; Bounds Checking: NONE\n;\n;*\n\tPROC\tInit_Stamps C near USES eax ebx edx edi\n\tARG\ticondata:DWORD\n\n\t; Verify legality of parameter.\n\tcmp\t[icondata],0\n\tje\tshort ??fini\n\n\t; Don't initialize if already initialized to this set (speed reasons).\n\tmov\tedi,[icondata]\n\tcmp\t[LastIconset],edi\n\tje\tshort ??fini\n\tmov\t[LastIconset],edi\n\n\t; Record number of icons in set.\n\tmovzx\teax,[(IControl_Type edi).Count]\n\tmov\t[IconCount],eax\n\n\t; Record width of icon.\n\tmovzx\teax,[(IControl_Type edi).Width]\n\tmov\t[IconWidth],eax\n\n\t; Record height of icon.\n\tmovzx\tebx,[(IControl_Type edi).Height]\n\tmov\t[IconHeight],ebx\n\n\t; Record size of icon (in bytes).\n\tmul\tebx\n\tmov\t[IconSize],eax\n\n\t; Record hard pointer to icon map data.\n\tmov\teax,[(IControl_Type edi).Map]\n\tadd\teax,edi\n\tmov\t[MapPtr],eax\n\n??nomap:\n\t; Record hard pointer to icon data.\n\tmov\teax,edi\n\tadd\teax,[(IControl_Type edi).Icons]\n\tmov\t[StampPtr],eax\n\n\t; Record the transparent table.\n\tmov\teax,edi\n\tadd\teax,[(IControl_Type edi).TransFlag]\n\tmov\t[IsTrans],eax\n\n??fini:\n\tret\n\n\tENDP\tInit_Stamps\n\n\n;***********************************************************\n\n\n;***********************************************************\n; DRAW_STAMP\n;\n; VOID cdecl Buffer_Draw_Stamp(VOID *icondata, WORD icon, WORD x_pixel, WORD y_pixel, VOID *remap);\n;\n; This routine renders the icon at the given coordinate.\n;\n; The remap table is a 256 byte simple pixel translation table to use when\n; drawing the icon.  Transparency check is performed AFTER the remap so it is possible to\n; remap valid colors to be invisible (for special effect reasons).\n; This routine is fastest when no remap table is passed in.\n;*\n\tPROC\tBuffer_Draw_Stamp C near\n\n\tARG\tthis_object:DWORD\t\t; this is a member function\n\tARG\ticondata:DWORD\t\t; Pointer to icondata.\n\tARG\ticon:DWORD\t\t; Icon number to draw.\n\tARG\tx_pixel:DWORD\t\t; X coordinate of icon.\n\tARG\ty_pixel:DWORD\t\t; Y coordinate of icon.\n\tARG\tremap:DWORD \t\t; Remap table.\n\n\tLOCAL\tmodulo:DWORD\t\t; Modulo to get to next row.\n\tLOCAL\tiwidth:DWORD\t\t; Icon width (here for speedy access).\n\tLOCAL\tdoremap:BYTE\t\t; Should remapping occur?\n\n\tpushad\n\tcmp\t[icondata],0\n\tje\t??out\n\n\t; Initialize the stamp data if necessary.\n\tmov\teax,[icondata]\n\tcmp\t[LastIconset],eax\n\tje\tshort ??noreset\n\tcall\tInit_Stamps C,eax\n??noreset:\n\n\t; Determine if the icon number requested is actually in the set.\n\t; Perform the logical icon to actual icon number remap if necessary.\n\tmov\tebx,[icon]\n\tcmp\t[MapPtr],0\n\tje\tshort ??notmap\n\tmov\tedi,[MapPtr]\n\tmov\tbl,[edi+ebx]\n??notmap:\n\tcmp\tebx,[IconCount]\n\tjae\t??out\n\tmov\t[icon],ebx\t\t; Updated icon number.\n\n\t; If the remap table pointer passed in is NULL, then flag this condition\n\t; so that the faster (non-remapping) icon draw loop will be used.\n\tcmp\t[remap],0\n\tsetne\t[doremap]\n\n\t; Get pointer to position to render icon. EDI = ptr to destination page.\n\tmov\tebx,[this_object]\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\n\tadd\teax,[(GraphicViewPort ebx).GVPPitch]\n\tpush\teax\t\t\t; save viewport full width for lower\n\tmul\t[y_pixel]\n\tadd\tedi,eax\n\tadd\tedi,[x_pixel]\n\n\t; Determine row modulo for advancing to next line.\n\tpop\teax\t\t\t; retrieve viewport width\n\tsub\teax,[IconWidth]\n\tmov\t[modulo],eax\n\n\t; Setup some working variables.\n\tmov\tecx,[IconHeight]\t; Row counter.\n\tmov\teax,[IconWidth]\n\tmov\t[iwidth],eax\t\t; Stack copy of byte width for easy BP access.\n\n\t; Fetch pointer to start of icon's data.  ESI = ptr to icon data.\n\tmov\teax,[icon]\n\tmul\t[IconSize]\n\tmov\tesi,[StampPtr]\n\tadd\tesi,eax\n\n\t; Determine whether simple icon draw is sufficient or whether the\n\t; extra remapping icon draw is needed.\n\tcmp\t[BYTE PTR doremap],0\n\tje\tshort ??istranscheck\n\n\t;************************************************************\n\t; Complex icon draw -- extended remap.\n\t; EBX = Palette pointer (ready for XLAT instruction).\n\t; EDI = Pointer to icon destination in page.\n\t; ESI = Pointer to icon data.\n\t; ECX = Number of pixel rows.\n;;;\tmov\tedx,[remap]\n mov ebx,[remap]\n\txor\teax,eax\n??xrowloop:\n\tpush\tecx\n\tmov\tecx,[iwidth]\n\n??xcolumnloop:\n\tlodsb\n;;;\tmov\tebx,edx\n;;;\tadd\tebx,eax\n;;;\tmov\tal,[ebx]\t\t; New real color to draw.\n xlatb\n\tor\tal,al\n\tjz\tshort ??xskip1\t\t; Transparency skip check.\n\tmov\t[edi],al\n??xskip1:\n\tinc\tedi\n\tloop\t??xcolumnloop\n\n\tpop\tecx\n\tadd\tedi,[modulo]\n\tloop\t??xrowloop\n\tjmp\tshort ??out\n\n\n\t;************************************************************\n\t; Check to see if transparent or generic draw is necessary.\n??istranscheck:\n\tmov\tebx,[IsTrans]\n\tadd\tebx,[icon]\n\tcmp\t[BYTE PTR ebx],0\n\tjne\tshort ??rowloop\n\n\t;************************************************************\n\t; Fast non-transparent icon draw routine.\n\t; ES:DI = Pointer to icon destination in page.\n\t; DS:SI = Pointer to icon data.\n\t; CX = Number of pixel rows.\n\tmov\tebx,ecx\n\tshr\tebx,2\n\tmov\tedx,[modulo]\n\tmov\teax,[iwidth]\n\tshr\teax,2\n??loop1:\n\tmov\tecx,eax\n\trep movsd\n\tadd\tedi,edx\n\n\tmov\tecx,eax\n\trep movsd\n\tadd\tedi,edx\n\n\tmov\tecx,eax\n\trep movsd\n\tadd\tedi,edx\n\n\tmov\tecx,eax\n\trep movsd\n\tadd\tedi,edx\n\n\tdec\tebx\n\tjnz\t??loop1\n\tjmp\tshort ??out\n\n\t;************************************************************\n\t; Transparent icon draw routine -- no extended remap.\n\t; ES:DI = Pointer to icon destination in page.\n\t; DS:SI = Pointer to icon data.\n\t; CX = Number of pixel rows.\n??rowloop:\n\tpush\tecx\n\tmov\tecx,[iwidth]\n\n??columnloop:\n\tlodsb\n\tor\tal,al\n\tjz\tshort ??skip1\t\t; Transparency check.\n\tmov\t[edi],al\n??skip1:\n\tinc\tedi\n\tloop\t??columnloop\n\n\tpop\tecx\n\tadd\tedi,[modulo]\n\tloop\t??rowloop\n\n\t; Cleanup and exit icon drawing routine.\n??out:\n\tpopad\n\tret\n\n\tENDP\tBuffer_Draw_Stamp\n\n\n\n\n;***********************************************************\n; DRAW_STAMP_CLIP\n;\n; VOID cdecl MCGA_Draw_Stamp_Clip(VOID *icondata, WORD icon, WORD x_pixel, WORD y_pixel, VOID *remap, LONG min_x, LONG min_y, LONG max_x, LONG max_y);\n;\n; This routine renders the icon at the given coordinate.\n;\n; The remap table is a 256 byte simple pixel translation table to use when\n; drawing the icon.  Transparency check is performed AFTER the remap so it is possible to\n; remap valid colors to be invisible (for special effect reasons).\n; This routine is fastest when no remap table is passed in.\n;*\n\tPROC\tBuffer_Draw_Stamp_Clip C near\n\n\tARG\tthis_object:DWORD\t; this is a member function\n\tARG\ticondata:DWORD\t\t; Pointer to icondata.\n\tARG\ticon:DWORD\t\t; Icon number to draw.\n\tARG\tx_pixel:DWORD\t\t; X coordinate of icon.\n\tARG\ty_pixel:DWORD\t\t; Y coordinate of icon.\n\tARG\tremap:DWORD \t\t; Remap table.\n\tARG\tmin_x:DWORD\t\t; Clipping rectangle boundary\n\tARG\tmin_y:DWORD\t\t; Clipping rectangle boundary\n\tARG\tmax_x:DWORD\t\t; Clipping rectangle boundary\n\tARG\tmax_y:DWORD\t\t; Clipping rectangle boundary\n\n\tLOCAL\tmodulo:DWORD\t\t; Modulo to get to next row.\n\tLOCAL\tiwidth:DWORD\t\t; Icon width (here for speedy access).\n\tLOCAL\tskip:DWORD\t\t; amount to skip per row of icon data\n\tLOCAL\tdoremap:BYTE\t\t; Should remapping occur?\n\n\tpushad\n\tcmp\t[icondata],0\n\tje\t??out2\n\n\t; Initialize the stamp data if necessary.\n\tmov\teax,[icondata]\n\tcmp\t[LastIconset],eax\n\tje\tshort ??noreset2\n\tcall\tInit_Stamps C,eax\n??noreset2:\n\n\t; Determine if the icon number requested is actually in the set.\n\t; Perform the logical icon to actual icon number remap if necessary.\n\tmov\tebx,[icon]\n\tcmp\t[MapPtr],0\n\tje\tshort ??notmap2\n\tmov\tedi,[MapPtr]\n\tmov\tbl,[edi+ebx]\n??notmap2:\n\tcmp\tebx,[IconCount]\n\tjae\t??out2\n\tmov\t[icon],ebx\t\t; Updated icon number.\n\n\t; Setup some working variables.\n\tmov\tecx,[IconHeight]\t; Row counter.\n\tmov\teax,[IconWidth]\n\tmov\t[iwidth],eax\t\t; Stack copy of byte width for easy BP access.\n\n\t; Fetch pointer to start of icon's data.  ESI = ptr to icon data.\n\tmov\teax,[icon]\n\tmul\t[IconSize]\n\tmov\tesi,[StampPtr]\n\tadd\tesi,eax\n\n\t; Update the clipping window coordinates to be valid maxes instead of width & height\n\t; , and change the coordinates to be window-relative\n\tmov\tebx,[min_x]\n\tadd\t[max_x],ebx\n\tadd\t[x_pixel],ebx\t\t; make it window-relative\n\tmov\tebx,[min_y]\n\tadd\t[max_y],ebx\n\tadd\t[y_pixel],ebx\t\t; make it window-relative\n\n\t; See if the icon is within the clipping window\n\t; First, verify that the icon position is less than the maximums\n\tmov\tebx,[x_pixel]\n\tcmp\tebx,[max_x]\n\tjge\t??out2\n\tmov\tebx,[y_pixel]\n\tcmp\tebx,[max_y]\n\tjge\t??out2\n\t; Now verify that the icon position is >= the minimums\n\tadd\tebx,[IconHeight]\n\tcmp\tebx,[min_y]\n\tjle\t??out2\n\tmov\tebx,[x_pixel]\n\tadd\tebx,[IconWidth]\n\tcmp\tebx,[min_x]\n\tjle\t??out2\n\n\t; Now, clip the x, y, width, and height variables to be within the\n\t; clipping rectangle\n\tmov\tebx,[x_pixel]\n\tcmp\tebx,[min_x]\n\tjge\t??nominxclip\n\t; x < minx, so must clip\n\tmov\tebx,[min_x]\n\tsub\tebx,[x_pixel]\n\tadd\tesi,ebx\t\t; source ptr += (minx - x)\n\tsub\t[iwidth],ebx\t; icon width -= (minx - x)\n\tmov\tebx,[min_x]\n\tmov\t[x_pixel],ebx\n\n??nominxclip:\n\tmov\teax,[IconWidth]\n\tsub\teax,[iwidth]\n\tmov\t[skip],eax\n\n\t; Check for x+width > max_x\n\tmov\teax,[x_pixel]\n\tadd\teax,[iwidth]\n\tcmp\teax,[max_x]\n\tjle\t??nomaxxclip\n\t; x+width is greater than max_x, so must clip width down\n\tmov\teax,[iwidth]\t; eax = old width\n\tmov\tebx,[max_x]\n\tsub\tebx,[x_pixel]\n\tmov\t[iwidth],ebx\t; iwidth = max_x - xpixel\n\tsub\teax,ebx\n\tadd\t[skip],eax\t; skip += (old width - iwidth)\n??nomaxxclip:\n\t; check if y < miny\n\tmov\teax,[min_y]\n\tcmp\teax,[y_pixel]\t; if(miny <= y_pixel), no clip needed\n\tjle\t??nominyclip\n\tsub\teax,[y_pixel]\n\tsub\tecx,eax\t\t; height -= (miny - y)\n\tmul\t[IconWidth]\n\tadd\tesi,eax\t\t; icon source ptr += (width * (miny - y))\n\tmov\teax,[min_y]\n\tmov\t[y_pixel],eax\t; y = miny\n??nominyclip:\n\t; check if (y+height) > max y\n\tmov\teax,[y_pixel]\n\tadd\teax,ecx\n\tcmp\teax,[max_y]\t; if (y + height <= max_y), no clip needed\n\tjle\t??nomaxyclip\n\tmov\tecx,[max_y]\t; height = max_y - y_pixel\n\tsub\tecx,[y_pixel]\n??nomaxyclip:\n\n\t; If the remap table pointer passed in is NULL, then flag this condition\n\t; so that the faster (non-remapping) icon draw loop will be used.\n\tcmp\t[remap],0\n\tsetne\t[doremap]\n\n\t; Get pointer to position to render icon. EDI = ptr to destination page.\n\tmov\tebx,[this_object]\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\n\tadd\teax,[(GraphicViewPort ebx).GVPPitch]\n\tpush\teax\t\t\t; save viewport full width for lower\n\tmul\t[y_pixel]\n\tadd\tedi,eax\n\tadd\tedi,[x_pixel]\n\n\t; Determine row modulo for advancing to next line.\n\tpop\teax\t\t\t; retrieve viewport width\n\tsub\teax,[iwidth]\n\tmov\t[modulo],eax\n\n\t; Determine whether simple icon draw is sufficient or whether the\n\t; extra remapping icon draw is needed.\n\tcmp\t[BYTE PTR doremap],0\n\tje\tshort ??istranscheck2\n\n\t;************************************************************\n\t; Complex icon draw -- extended remap.\n\t; EBX = Palette pointer (ready for XLAT instruction).\n\t; EDI = Pointer to icon destination in page.\n\t; ESI = Pointer to icon data.\n\t; ECX = Number of pixel rows.\n\tmov\tebx,[remap]\n\txor\teax,eax\n??xrowloopc:\n\tpush\tecx\n\tmov\tecx,[iwidth]\n\n??xcolumnloopc:\n\tlodsb\n\txlatb\n\tor\tal,al\n\tjz\tshort ??xskip1c\t\t; Transparency skip check.\n\tmov\t[edi],al\n??xskip1c:\n\tinc\tedi\n\tloop\t??xcolumnloopc\n\n\tpop\tecx\n\tadd\tedi,[modulo]\n add esi,[skip]\n\tloop\t??xrowloopc\n\tjmp\tshort ??out2\n\n\n\t;************************************************************\n\t; Check to see if transparent or generic draw is necessary.\n??istranscheck2:\n\tmov\tebx,[IsTrans]\n\tadd\tebx,[icon]\n\tcmp\t[BYTE PTR ebx],0\n\tjne\tshort ??rowloopc\n\n\t;************************************************************\n\t; Fast non-transparent icon draw routine.\n\t; ES:DI = Pointer to icon destination in page.\n\t; DS:SI = Pointer to icon data.\n\t; CX = Number of pixel rows.\n\tmov\tebx,ecx\n\tmov\tedx,[modulo]\n\tmov\teax,[iwidth]\n\n\t;\n\t; Optimise copy by dword aligning the destination\n\t;\n??loop1c:\n\tpush\teax\n rept 3\n\ttest\tedi,3\n\tjz\t??aligned\n\tmovsb\n\tdec\teax\n\tjz\t??finishedit\n endm\n??aligned:\n\tmov\tecx,eax\n\tshr\tecx,2\n\trep\tmovsd\n\tmov\tecx,eax\n\tand\tecx,3\n\trep\tmovsb\n\n??finishedit:\n\tadd\tedi,edx\n\tadd\tesi,[skip]\n\tpop\teax\n\n\tdec\tebx\n\tjnz\t??loop1c\n\tjmp\tshort ??out2\n\n\t;************************************************************\n\t; Transparent icon draw routine -- no extended remap.\n\t; ES:DI = Pointer to icon destination in page.\n\t; DS:SI = Pointer to icon data.\n\t; CX = Number of pixel rows.\n??rowloopc:\n\tpush\tecx\n\tmov\tecx,[iwidth]\n\n??columnloopc:\n\tlodsb\n\tor\tal,al\n\tjz\tshort ??skip1c\t\t; Transparency check.\n\tmov\t[edi],al\n??skip1c:\n\tinc\tedi\n\tloop\t??columnloopc\n\n\tpop\tecx\n\tadd\tedi,[modulo]\n add esi,[skip]\n\tloop\t??rowloopc\n\n\t; Cleanup and exit icon drawing routine.\n??out2:\n\tpopad\n\tret\n\n\tENDP\tBuffer_Draw_Stamp_Clip\n\n\tEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/STMPCACH.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : STAMP.ASM                                *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : August 23, 1993                          *\n;*                                                                         *\n;*                  Last Update : August 23, 1993   [JLB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nJUMPS\n\nMAX_CACHED_ICONS=300\nICON_WIDTH\t=24\nICON_HEIGHT\t=24\nMAX_ICON_SETS\t=100\n\n\nglobal\t\tC IconPointers:dword\nglobal\t\tC Init_Stamps:near\nglobal\t\tC IconCacheLookup:word\nglobal\t\tLastIconset:dword\nglobal\t\tMapPtr:dword\nglobal\t\tIconCount:dword\nglobal\t\tIconSize:dword\nglobal\t\tStampPtr:dword\nglobal\t\tIconEntry:dword\nglobal\t\tIconData:dword\n\nglobal\t\tClear_Icon_Pointers_:near\nglobal\t\tCache_Copy_Icon_:near\nglobal\t\tIs_Icon_Cached_:near\nglobal\t\tGet_Icon_Index_:near\nglobal\t\tGet_Free_Index_:near\nglobal\t\tCache_New_Icon_:near\nglobal\t\tIs_Stamp_Registered_:near\nglobal\t\tGet_Free_Cache_Slot_:near\n\n\n\t\tstruc\tIconSetType\n\n\t\tIconSetPtr\tdd\t?\n\t\tIconListOffset\tdd\t?\n\n\t\tends\n\nglobal\t\tC IconSetList:IconSetType\n\n\t\tcodeseg\n\n\n\n;************************************************************************************************\n;* Cache_Copy_Icon -- copy an icon to its video memory cache                                    *\n;*                                                                                              *\n;*                                                                                              *\n;* INPUT:\teax - ptr to icon_data                                                          *\n;*              edx - ptr to video surface                                                      *\n;*              ebx - pitch of video surface                                                    *\n;*                                                                                              *\n;* OUTPUT:      none                                                                            *\n;*                                                                                              *\n;* PROTO:       extern \"C\" Cache_Copy_Icon (void const *icon_ptr ,                              *\n;*\t\tVideoSurfaceDescription.lpSurface ,                                             *\n;*\t\tVideoSurfaceDescription.lPitch);\t\t\t\t\t\t*\n;*                                                                                              *\n;* HISTORY:                                                                                     *\n;*   11/8/95 3:16PM ST: Created                                                                 *\n;*==============================================================================================*\n\nproc\t\tCache_Copy_Icon_ near\n\t\tpushad\n\n\t\tmov\tesi,eax\n\t\tmov\tedi,edx\n\t\tsub\tebx,ICON_WIDTH\n\n\t\tmov\tdl,ICON_HEIGHT\t\t;icon height\n\n??each_line_lp:\tmov\tecx,ICON_WIDTH/4\n\t\trep\tmovsd\n\t\tlea\tedi,[edi+ebx]\n\t\tdec\tdl\n\t\tjnz\t??each_line_lp\n\n\t\tpopad\n\t\tret\n\nendp\t\tCache_Copy_Icon_\n\n\n\n\n\n;************************************************************************************************\n;* Is_Icon_Cached -- has an icon been cached? If not, is it cacheable?                          *\n;*                                                                                              *\n;*                                                                                              *\n;* INPUT:\teax - ptr to icon_data                                                          *\n;*              edx - icon number                                                               *\n;*                                                                                              *\n;* OUTPUT:      eax - index of cached icon or -1 if not cached                                  *\n;*                                                                                              *\n;* PROTO:       extern \"C\" int Is_Icon_Cached (void const *icon_data , int icon);               *\n;*                                                                                              *\n;* HISTORY:                                                                                     *\n;*   11/8/95 2:16PM ST: Created                                                                 *\n;*==============================================================================================*\n\nproc\t\tIs_Icon_Cached_ near\n\n\t\tmov\t[IconData],eax\t\t;save the icon data ptr for later\n\t\tpush\tedx\n\t\ttest\teax,eax\n\t\tje\t??out\n\n; Initialize the stamp data if necessary.\n\t\tcmp\t[LastIconset],eax\n\t\tje\tshort ??noreset\n\t\tcall\tInit_Stamps C,eax\n\n; Determine if the icon number requested is actually in the set.\n; Perform the logical icon to actual icon number remap if necessary.\n??noreset:\tcmp\t[MapPtr],0\n\t\tje\tshort ??notmap\n\t\tpush\tedi\n\t\tmov\tedi,[MapPtr]\n\t\tmov\tdl,[edi+edx]\n\t\tpop\tedi\n\n??notmap:\tcmp\tedx,[IconCount]\n\t\tjl\t??in_range\n\t\tpop\tedx\n\t\tmov\teax,-1\n\t\tret\n\n; See if the stamp is registered - if not then it cant be cached\n??in_range:\tmov\teax,[IconData]\n\t\tcall\tIs_Stamp_Registered_\n\t\tcmp\teax,-1\n\t\tjnz\t??got_entry\n\t\tpop\tedx\n\t\tret\n\n; Stamp is registered - if its cached already then just return the index\n??got_entry:\tmov\teax,[(IconSetType eax).IconListOffset]\n\t\tcmp\t[word eax+edx*2+IconCacheLookup],-1\n\t\tjz\t??not_cached\n\n; it is cached and [eax+edx] is the index\n\t\tmovzx\teax,[word eax+edx*2+IconCacheLookup]\n\t\tpop\tedx\n\t\tret\n\n\n\n;\n; The stamps set is registered but we havn't seen this stamp before\n; so try caching it\n;\n\n??not_cached:\tmov\t[IconEntry],eax\n\t\tadd\t[IconEntry],edx\n\t\tadd\t[IconEntry],edx\n\t\tcall\tGet_Free_Cache_Slot_\n\t\ttest\teax,eax\n\t\tjge\t??got_free_slot\n\t\tpop\tedx\t\t\t;eax is -1 here anyway\n\t\tret\n\n; We found a free caching slot so try caching the stamp into it\n??got_free_slot:imul\tedx,[IconSize]\n\t\tadd\tedx,[StampPtr]\n\t\tpush\teax\n\t\tcall\tCache_New_Icon_\t\t;takes icon index in eax, ptr to icon in edx\n\t\ttest\teax,eax\n\t\tjz\t??cache_failed\n\n\n; Success! Add the index into the table\n\t\tpop\teax\n\t\tmov\tedx,[IconEntry]\n\t\tmov\t[edx+IconCacheLookup],ax\n\t\tand\teax,0ffffh\n\t\tpop\tedx\n\t\tret\n\n; Couldnt cache the new Icon - return -1 to say icon isnt cached\n??cache_failed:\tpop\teax\n??out:\t\tpop\tedx\n\t\tmov\teax,-1\n\t\tret\n\n\nendp\t\tIs_Icon_Cached_\n\n\n\n\n\n\n\n;************************************************************************************************\n;* Is_Stamp_Registered -- has an icon's set been previously registered?                         *\n;*                                                                                              *\n;*                                                                                              *\n;* INPUT:\teax - ptr to icon_data                                                          *\n;*                                                                                              *\n;* OUTPUT:      eax - ptr to registration entry or -1 if not registered                         *\n;*                                                                                              *\n;* PROTO:       extern \"C\" int Is_Stamp_Registered (void const *icon_data);                     *\n;*                                                                                              *\n;* HISTORY:                                                                                     *\n;*   11/10/95 10:00AM ST: Created                                                               *\n;*==============================================================================================*\n\nproc\t\tIs_Stamp_Registered_\n\n\t\tpush\tedi\n\t\tpush\tecx\n\t\tmov\tedi,offset IconSetList\n\t\tmov\tecx,MAX_ICON_SETS\n\n??each_set_lp:\tcmp\teax,[edi]\n\t\tjz\t??got_icon_set\n\t\tadd\tedi,size IconSetType\n\t\tdec\tecx\n\t\tjnz\t??each_set_lp\n\t\tmov\teax,-1\n\t\tpop\tecx\n\t\tpop\tedi\n\t\tret\n\n??got_icon_set:\tmov\teax,edi\n\t\tpop\tecx\n\t\tpop\tedi\n\t\tret\n\nendp\t\tIs_Stamp_Registered_\n\n\n\n\n\n\n\n\t\tdataseg\n\n\nIconEntry\tdd\t0\t;Temporary pointer to icon index entry in table\nIconData\tdd\t0\t;Temporary ptr to icon set data\n\n\n\nend\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/SZREGION.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Calculate size of an MCGA region\t   *\n;*                                                                         *\n;*                    File Name : REGIONSZ.ASM                             *\n;*                                                                         *\n;*                   Programmer : Barry W. Green\t\t\t   *\n;*                                                                         *\n;*                   Start Date : March 1, 1995\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : March 1, 1995  [BWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVPC::Size_Of_Region - calculate graphic buffer region size           *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nGLOBAL\tBuffer_Size_Of_Region\t: NEAR\n\nCODESEG\n\n;***************************************************************************\n;* VVPC::Size_Of_Region - calculate buffer region size\t\t\t   *\n;*                                                                         *\n;* INPUT:\tDWORD the width of the region\t\t\t\t   *\n;*                                                                         *\n;*\t\tDWORD the height of the region\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      calculated size of the region (size = width * height)      *\n;*                                                                         *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   03/01/1995 BWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_Size_Of_Region C near\n\tUSES\tebx,ecx,edx\n\n\tARG    \tthis_object:DWORD\t\t\t; this is a member function\n\tARG\tregion_width:DWORD\t\t\t; width of region\n\tARG\tregion_height:DWORD\t\t\t; height of region\n\n\t;*===================================================================\n\t; Get the viewport information\n\t;*===================================================================\n\tmov\tebx,[this_object]\t\t\t\t; get a pointer to viewport\n\txor\teax,eax\n\tmov\tecx,[(GraphicViewPort ebx).GVPHeight]\t; ecx = height of viewport\n\tmov\tedx,[(GraphicViewPort ebx).GVPWidth]\t; edx = width of viewport\n\n\t;*===================================================================\n\t; Verify that the width is legal\n\t;*===================================================================\n\tmov\teax,[region_width]\t\t\t\t; find the width\n\tcmp\teax,edx\t\t\t\t\t; is it too wide?\n\tjb\tshort ??wok\t\t\t\t; if not, leave it alone\n\tmov\teax,edx\t\t\t\t\t; otherwise clip it\n\n\t;*===================================================================\n\t; Verify that the height is ok\n\t;*===================================================================\n??wok:\tmov\tebx,[region_height]\t\t\t; get the height\n\tcmp\tebx,ecx\t\t\t\t\t; is it too tall?\n\tjb\t??hok\t\t\t\t\t; if not, leave it alone\n\tmov\tebx,ecx\t\t\t\t\t; otherwise clip it\n\n\t;*===================================================================\n\t; Now multiply 'em to calculate the size of the region\n\t;*===================================================================\n??hok:\tmul\tebx\t\t\t\t\t; size = w * h\n\n\tret\n\tENDP\tBuffer_Size_Of_Region\n\n\tEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/TEST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <windowsx.h>\n#include \"audio.h\"\n\n\n\nint PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,\n                        LPSTR lpCmdLine, int nCmdShow)\n{\n\n\n\n\t\t\t \n\n\n\tFile_Stream_Sample_Vol(\"file\", 0, 0);\n\n\treturn (0);\n}"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/TEXTPRNT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : 32 bit library Text Print                *\n;*                                                                         *\n;*                    File Name : TEXTPRNT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : July 2, 1994                             *\n;*                                                                         *\n;*                  Last Update : July 2, 1994   [SKB]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Text_Print -- Assembly text print routine.                            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n\nGLOBAL\tFontPtr:DWORD\nGLOBAL\tText_Print:NEAR\n\n; The header of the font file looks like this:\n; \tUWORD\tFontLength;\t\t0\n; \tBYTE\tFontCompress;\t\t2\n;\tBYTE\tFontDataBlocks;\t\t3\n;\tUWORD\tInfoBlockOffset;\t4\n;\tUWORD\tOffsetBlockOffset;\t6\n;\tUWORD\tWidthBlockOffset;\t8\n;\tUWORD\tDataBlockOffset;\t10\n;\tUWORD\tHeightOffset;\t\t12\n; For this reason the following equates have these values:\nFONTINFOBLOCK\t\tEQU\t4\nFONTOFFSETBLOCK\t\tEQU\t6\nFONTWIDTHBLOCK\t\tEQU\t8\nFONTDATABLOCK\t\tEQU\t10\nFONTHEIGHTBLOCK\t\tEQU\t12\n\nFONTINFOMAXHEIGHT\tEQU\t4\nFONTINFOMAXWIDTH\tEQU\t5\n\nLOCALS ??\n\n\tDATASEG\n\nColorXlat\tDB\t000H,001H,002H,003H,004H,005H,006H,007H\n\t\tDB\t008H,009H,00AH,00BH,00CH,00DH,00EH,00FH\n\n\t\tDB\t001H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t002H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t003H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t004H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t005H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t006H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t007H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t008H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t009H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00AH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00BH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00CH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00DH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00EH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00FH\n\n\tCODESEG\n\n\n;***************************************************************************\n;* TEXT_PRINT -- Assembly text print routine.                              *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/28/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tText_Print C near\n\tUSES\tebx,ecx,edx,esi,edi\n\tARG\tvpselector:WORD\n\tARG\tvpoffset:DWORD\n\tARG\tvpwidth:DWORD\n\tARG\tvpheight:DWORD\n\tARG\tvpxadd:DWORD\n\tARG\tstring:DWORD\n\tARG\tx_pixel:DWORD\n\tARG\ty_pixel:DWORD\n\tARG\tfcolor:DWORD\n\tARG\tbcolor:DWORD\n\t\t\n\tLOCAL\tinfoblock:DWORD\t\t; pointer to info block\n\tLOCAL\toffsetblock:DWORD\t; pointer to offset block  (UWORD *)\n\tLOCAL\twidthblock:DWORD\t; pointer to width block   (BYTE  *)\n\tLOCAL\theightblock:DWORD\t; pointer to height block  (UWORD *)\n\n\tLOCAL\tcurline:DWORD\t\t; pointer to first column of current row.\n\tLOCAL\tbufferwidth:DWORD    \t; width of buffer (vpwidth + Xadd)\n\tLOCAL\tnextdraw:DWORD\t\t; bufferwidth - width of cur character.\n\tLOCAL\tstartdraw:DWORD\t\t; where next character will start being drawn.\n\n\tLOCAL\tchar:DWORD\t\t; current character value.\t\n\n\tLOCAL\tmaxheight:BYTE\t\t; max height of characters in font.\n\tLOCAL\tbottomblank:BYTE\t; amount of empty space below current character.\n\tLOCAL\tcharheight:BYTE\t\t; true height of current character.\n\n\n;-------------------------------- Where to draw -----------------------------------------------\n\t; Set up memory location to start drawing.\n\tmovzx\teax,[vpselector]\n\tmov\tes,ax\t\t\t; Set up selector to write to.\n\n\tmov\teax,[vpwidth]\t\t; get the width of the viewport\n\tadd\teax,[vpxadd]\t\t; add amount to add to get to left edge of next line.\t\n\tmov\t[bufferwidth],eax     \t; save it off for later use.\n\n\tmul\t[y_pixel]\t\t; multiply rowsize * y_pixel start.\n\tmov\tedi,[vpoffset]\t\t; get start of the viewport\n\tadd\tedi,eax\t\t\t; add x,y position to start of vp to get starting row address.\t\n\tmov\t[curline],edi\t\t; save 0,y address for line feed stuff.\n\tadd\tedi,[x_pixel]\t\t; add to get starting column in starting row.\n\tmov\t[startdraw],edi\t\t; save it off.\n\n\n;-------------------------------- Create block pointers ----------------------------------------\n\t; Get the pointer to the font.\n\t; We could check for NULL but why waste the time.\n\t; It is up to programmer to make sure it is set.\n\tmov\tesi,[FontPtr]\t\t; Get the font pointer\n\n\t; Set up some pointers to the different memory blocks.\n\t; esi (FontPtr) is added to each to get the true address of each block.\n\t; Many registers are used for P5 optimizations.\n\t; ebx is used for InfoBlock which is then used in the next section.\n\tmovzx\teax,[WORD PTR esi+FONTOFFSETBLOCK]\t; get offset to offset block\n\tmovzx\tebx,[WORD PTR esi+FONTINFOBLOCK]      \t; get offset to info block (must be ebx for height test)\n\tmovzx\tecx,[WORD PTR esi+FONTWIDTHBLOCK] \t; get offset to width block\n\tmovzx\tedx,[WORD PTR esi+FONTHEIGHTBLOCK]\t; get offset to height block\n\n\tadd\teax,esi\t\t\t\t; add offset of FontPtr to offset block  \n\tadd\tebx,esi\t\t\t\t; add offset of FontPtr to info block \n\tadd\tecx,esi\t\t\t\t; add offset of FontPtr to width block\n\tadd\tedx,esi\t\t\t\t; add offset of FontPtr to height block\n\n\tmov\t[offsetblock],eax\t\t; save offset to offset block\n\tmov\t[infoblock],ebx\t\t\t; save offset to info block\n\tmov\t[widthblock],ecx   \t\t; save offset to width block\n\tmov\t[heightblock],edx\t\t; save offset to height block\n\n;------------------------------------------ Test for fit ----------------------------------------------\n\t; Test to make sure the height of the max character will fit on this line\n\t; and and not fall out of the viewport.\n\t; remember we set ebx to FONTINFOBLOCK above.\n\tmovzx\teax,[BYTE PTR ebx + FONTINFOMAXHEIGHT]; get the max height in font.\n\tmov\t[maxheight],al\t\t\t; save it for later use.\n\tadd\teax,[y_pixel]\t\t\t; add current y_value.\n\tcmp\teax,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we're outa here.\n\n\tmov\t[y_pixel],eax\t\t\t; save for next line feed. y value for next line.\n\n\tcld\t\t\t\t\t; Make sure we are always forward copying.\n\n;------------------------ Set palette foreground and background ----------------------------------\n\tmov\teax,[fcolor]\t\t; foreground color\n\tmov\t[ColorXlat+1],al\n\tmov\t[ColorXlat+16],al\n\n\tmov\teax,[bcolor]\t\t; background color\n\tmov\t[ColorXlat],al\n\n;-------------------------------------------------------------------------------------------------\n;----------------------------------------- Main loop ----------------------------------------------\n\t; Now we go into the main loop of reading each character in the string and doing\n\t; something with it.\n??next_char:\n\t; while (*string++)\n\txor\teax,eax\t\t\t\t; zero out since we will just load al.\t\n\tmov\tesi,[string]\t\t\t; get address on next character.\t\n\tlodsb\t\t\t\t\t; load the character into al.\n\ttest\teax,0FFH\t\t\t; test to see if character is a NULL\n\tjz\t??done\t\t\t\t; character is NULL, get outa here.\n\n\tmov\tedi,[startdraw]\t\t\t; Load the starting address.\n\n\tmov\t[string],esi\t\t\t; save index into string. (incremented by lodsb)\t\n\t\n\tcmp\teax,13\t\t\t\t; is the character a line feed?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\n\tmov\t[char],eax\t\t\t; save the character off for later reference.\n\tmov\tebx,eax\t\t\t\t; save it in ebx for later use also.\n\n\tadd\teax,[widthblock]\t\t; figure address of width of character.\n\tmov\tecx,[x_pixel]\t\t\t; get current x_pixel.\n\tmovzx\tedx,[BYTE PTR eax]\t \t; get the width of the character in dl.\n\tadd\tecx,edx\t\t\t\t; add width of char to current x_pixel.\n\tadd\t[startdraw],edx\t\t\t; save start draw for next character.\n\n\tcmp\tecx,[vpwidth]\t\t\t; is the pixel greater then the vp width?\n\tjg\t??force_line_feed\t\t; if so, force a line feed.\n\n\tmov\t[x_pixel],ecx\t\t\t; save value of start of next character.\n\tmov\tecx,[bufferwidth]\t\t; get amount to next y same x (one row down)\n\tsub\tecx,edx\t\t\t\t; take the current width off.\n\tmov\t[nextdraw],ecx\t\t\t; save it to add to edi when done with a row.\n\n\t; At this point we got the character. It is now time to find out specifics\n\t; about drawing the darn thing.\n\t; ebx = char so they can be used as an indexes.\n\t; edx = width of character for loop later.\n\n\t; get offset of data for character into esi.\n\tshl\tebx,1\t\t\t\t; mult by 2 to later use as a WORD index.\n\tmov\tesi,[offsetblock]\t\t; get pointer to begining of offset block.\n\tadd\tesi,ebx\t\t\t\t; index into offset block.\t\n\tmovzx\tesi,[WORD PTR esi]\t\t; get true offset into data block from FontPtr.\n\tadd\tesi,[FontPtr]\t\t\t; Now add FontPtr address to get true address.\n\n\t; Get top and bottom blank sizes and the true height of the character.\n\tadd\tebx,[heightblock]\t\t; point ebx to element in height array.\n\tmov\tal,[ebx+1]\t\t\t; load the data height into dl.\n\tmov\tcl,[ebx]\t\t\t; load the first data row into cl.\n\tmov\tbl,[maxheight]\t\t\t; get the max height of characters.\n\tmov\t[charheight],al\t\t\t; get number of rows with data.\n\tadd\tal,cl\t\t\t\t; add the two heights.\n\tsub\tbl,al\t\t\t\t; subract topblank + char height from maxheight.\n\tmov\t[bottomblank],bl\t\t; save off the number of blank rows on the bottom.\n\t; leaving this section:\n\t; dl is still the width of the character.\n\t; cl is the height of the top blank area.\n\n\tmov\tebx,OFFSET ColorXlat\t\t; setup ebx for xlat commands.\n\tmov\tdh,dl\t\t\t\t; save the width of the character to restore each loop.\n\n\tcmp\tcl,0\t\t\t\t; is there any blank rows on top?\n\tjz\t??draw_char\t\t\t; if not go and draw the real character.\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjnz\t??loop_top\t\t\t; if not go and write the color\n\n;----------------------------------------- skip Top blank area ----------------------------------------\n\t; this case, the top is transparrent, but we need to increase our dest pointer to correct row.\n\tmovzx\teax,cl\t\t\t\t; get number of rows into eax;\n\tmov\tecx,edx\t\t\t\t; save width since edx will be destroyed by mul.\n\tmul\t[bufferwidth]\t\t\t; multiply that by the width of the buffer.\n\tmov\tedx,ecx\t\t\t\t; restore the width\n\tadd\tedi,eax\t\t\t\t; update the pointer.\t\n\tjmp\tshort ??draw_char\t\t; now go draw the character.\n\n;----------------------------------------- fill Top blank area ----------------------------------------\n\t; edi was set a long time ago.\n\t; al is the translated color\n??loop_top:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_top\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tdec\tcl\t\t\t\t; decrement or row count\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tjz\t??draw_char\t\t\t; we are done here, go draw the character.\n\tjmp\tshort ??loop_top\t\t; go back to top of loop.\n\n\n;----------------------------------------- Draw character ----------------------------------------------\n??draw_char:\n\tmovzx\tecx,[charheight]\t\t; get the height of character to count down rows.\n\ttest\tecx,ecx\t\t\t\t; is there any data? (blank would not have any)\n\tjz\t??next_char\t\t\t; if no data, go on to next character.\t\n\n??while_data:\n\tlodsb\t\t\t\t\t; get byte value from font data\n\tmov\tah,al\t\t\t\t; save hinibble\n\tand\teax,0F00FH\t       \t\t; mask of low nibble in al hi nibble in ah.\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiplo\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiplo:\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjz\tshort ??nextrow\t\t\t; check if done with width of char\n\n\tmov\tal,ah\t\t\t\t; restore to get\n\t; test the time difference between looking up in a large table when shr al,4 is not done as\n\t; compared to using only a 16 byte table when using the shr al,4\n\t;shr\tal,4\t\t\t\t; shift the hi nibble down to low nibble\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiphi\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiphi:\n\t\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\tshort ??while_data\t\t; check if done with width of char\n\n??nextrow:\n\tadd\tedi,[nextdraw]\t\t\t; go to next line.\n\tdec\tecx\t\t\t\t; decrement the number of rows to go\n\tmov\tdh,dl\t\t\t\t; restore our column count for row.\n\tjnz\t??while_data\t\t\t; more data for character.\n\n\t; Now it is time to setup for clearing out the bottom of the character.\n\tmovzx\tecx,[bottomblank]\t\t; get amount on bottom that is blank\n\tcmp\tecx,0\t\t\t\t; if there is no blank bottom...\n\tjz\t??next_char\t\t\t; then skip to go to next character\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjz\t??next_char\t\t\t; skip the top black section to let the background through\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\n;----------------------------------------- Blank below character -----------------------------------\n??loop_bottom:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_bottom\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tdec\tcl\t\t\t\t; decrement or row count\n\tjz\t??next_char\t\t\t; we are done here, go to the next character.\n\tjmp\tshort ??loop_bottom\t\t; go back to top of loop.\n\n;----------------------------------- end of next_char (main) loop ------------------------------------\n;-------------------------------------------------------------------------------------------------\n\n\n;----------------------------------- special case line feeds ----------------------------------------\n\n??force_line_feed:\t\n\t; decrement pointer *string so that it will be back at same character\n\t; when it goes through the loop.\n\tmov\teax,[string]\t\t\t; get string pointer.\n\tdec\teax\t\t\t\t; decrement it to point to previos char\n\tmov\t[string],eax\t\t\t; save it back off.\n\t; Now go into the line feed code.....\n\n??line_feed:\n\tmov\tedx,[y_pixel]\t\t\t; get the current y pixel value.\n\tmovzx\tecx,[maxheight]\t\t\t; get max height for later use.\n\tadd\tedx,ecx\t\t\t\t; add max height to y_pixel\n\tcmp\tedx,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we are outa here.\n\n\tmov\teax,[bufferwidth]      \t\t; get bytes to next line.\n\tmov\tedi,[curline]\t\t\t; get start of current line.\t\n\tmul\tecx\t\t\t\t; mult max height * next line.\t\n\n\tadd\tedi,eax\t\t\t\t; add adjustment to current line.\n\tadd\t[y_pixel],ecx\t\t\t; increment to our next y position.\n\tmov\t[curline],edi\t\t\t; save it off for next line_feed.\n\tmov\t[startdraw],edi\t\t\t; save it off so we know where to draw next char.w\n\n\tmov\t[x_pixel],0\t\t\t; zero out x_pixel\n\n\tjmp\t??next_char\n\n??overflow:\n\tmov\t[startdraw],0\t\t\t; Indicate that there is no valid next pos.\n??done:\n\tmov\teax,[startdraw]\t\t\t; return this so calling routine\n\tret\t\t\t\t\t; can figure out where to draw next.\n\t\t\n\tENDP\tText_Print\n\n\n\n;***********************************************************\n\n\tEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/TIMER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Temp timer for 32bit lib                 *\n *                                                                         *\n *                    File Name : TIMER.CPP                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : July 6, 1994                             *\n *                                                                         *\n *                  Last Update : May 3, 1995   [SKB]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   TC::Time -- Return the time on the timer.                             *\n *   TC::TimerClass -- Construct a timer class object.                     *\n *   TC::Stop -- Stop the timer.                                           *\n *   TC::Start -- Start a timer.                                           *\n *   TC::Set -- Set the time of a timer.                                   *\n *   TC::Reset -- Clear the timer.                                         *\n *   TimerClass::Time -- Get the current time of timer.                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"timer.H\"\n#include <stdio.h>\n#include <stdlib.h>\n\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////////// Code ////////////////////////////////////////\n\n/***************************************************************************\n * TC::TIMERCLASS -- Construct a timer class object.                       *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nTimerClass::TimerClass(BaseTimerEnum timer, BOOL on)\n{\n\tAccumulated = 0;\n\tStarted = 0;\n\n\tTickType=timer;\n\n\tif (on && TimerSystemOn) Start();\n}\n\n\n\n\n/***********************************************************************************************\n * TC:Get_Ticks -- return the number of ticks on the system or user timers                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   tick count                                                                        *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *              10/5/95 4:17PM ST : Created                                                    *\n *=============================================================================================*/\n\nlong TimerClass::Get_Ticks ( void )\n\n{\n\tif ( WindowsTimer ){\n\t\tswitch ( TickType ){\n\n\t\t \tcase BT_SYSTEM :\n\t\t\t\treturn ( WindowsTimer->Get_System_Tick_Count() );\n\n\t\t \tcase BT_USER :\n\t\t\t\treturn ( WindowsTimer->Get_User_Tick_Count() );\n\n\t\t}\n\t}\n\treturn 0;\n}\n\n\n\n/***************************************************************************\n * TIMERCLASS::TIME -- Get the current time of timer.                      *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1995 SKB : Created.                                             *\n *=========================================================================*/\nlong TimerClass::Time(void)\n{\n\tif (Started) {\n\t\tlong ticks = Get_Ticks();\n\t\tAccumulated += ticks - (Started-1);\n\t\tStarted = ticks+1;\n\t}\n\treturn(Accumulated);\n}\n\n\n/***************************************************************************\n * TC::STOP -- Stop the timer.                                             *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong TimerClass::Stop(void)\n{\n\tlong time = Time();\n\tStarted = 0;\n\treturn(time);\n}\n\n\n/***************************************************************************\n * TC::START -- Start a timer.                                             *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong TimerClass::Start(void)\n{\n\tif (!Started) {\n\t\tStarted = Get_Ticks()+1;\n\t}\n\treturn(Time());\n}\n\n\n/***************************************************************************\n * TC::SET -- Set the time of a timer.                                     *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:  long value to set timer at.                                     *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *   05/03/1995 SKB : If start return Start since it returns Time          *\n *=========================================================================*/\nlong TimerClass::Set(long value, BOOL start)\n{\n\tStarted = 0;\n\tAccumulated = value;\n\tif (start) return (Start());\n\treturn(Time());\n}"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/TIMERA.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Timer stuff                              *\n;*                                                                         *\n;*                    File Name : TIMERA.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : July 6, 1994                             *\n;*                                                                         *\n;*                  Last Update : March 14, 1995   [PWG]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Get_RM_Timer_Address -- Return address of real mode code for copy.    *\n;*   Get_RM_Timer_Size -- return size of real mode timer code.             *\n;*   Increment_Tick_Count -- Increments WW system timer.                   *\n;*   Timer_Interrupt -- Temp routine to mimic a timer system calling our.  *\n;*   Install_Timer_Interrupt -- Installs the timer interrupt routine.      *\n;*   Remove_Timer_Interrupt -- Removes the timer interrupt vectors.       **\n;*   Set_Timer_Frequency -- Set the frequency of the timer.                *\n;*   Set_Timer_Rate -- Set the rate of the timer.                          *\n;*   Get_System_Tick_Count -- Returns the system tick count.               *\n;*   Get_User_Tick_Count -- Get tick count of user clock.                  *\n;*   Increment_Timers -- Increments system and user timers.                *\n;*   Get_Num_Interrupts -- Returns the number of interrupts that have occured*\n;*   Timer_Interrupt_Func -- Handles core timer code                       *\n;*   Disable_Timer_Interrupt -- Disables at the hardware level             *\n;*   Enable_Timer_Interrupt -- Enables at the hardware level               *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nDPMI_INTR\tequ\t31h\t\nTRUE\t\tequ\t1\t\t\t; Boolean 'true' value\nFALSE\t\tequ\t0\t\t\t; Boolean 'false' value\n\nLOCALS ??\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////////// Equates ////////////////////////////////////////\n\nSYSTEM_TIMER_FREQ\tequ\t60\t; Frequency of system timer.\n\n;********************************************************************\n; There are two ways to call our interrupt chain in protected mode.  \n; The obvious way it to call the address that we replaced in the\n; PM interrupt chain.  This method is a little difficult but works and\n; should always work.\n\n\n;********************************************************************\n; The RM and PM interrupts can be installed at the same time or seperately.\n; Installing at the same time is the best method, the other method\n; can be used to faciliated debugging when you only want one or the other\n; called.  Both methods work.\n; -SKB July 21, 1994.\nINSTALL_SEPERATE\tequ\tFALSE\n\n\nINTCHIP0\tEQU\t20h\t\t; 8259 interrupt chip controller 0\nCLEARISR\tEQU\t20h\t\t; Value to write to 8259 to reenable interrupts.\nIRQ0INTNUM\tEQU\t08h\t\t; IRQ0 interrupt vector number.\nDOS_SYS_CALL\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nLOCK_PAGES\tEQU\t5\t\t; Lock pages subfunction using DX_MEM_MGT\nUNLOCK_PAGES\tEQU\t6\t\t; Unlock pages subfunction using DX_MEM_MGT\n\nTIMER_CONST\tEQU\t1193180\t\t; TIMER_CONST / FREQ = rate to set 8259 chip\n\nTIMERCMDREG\tEQU\t043H\t\t; timer command register port.\nTIMER0PORT\tEQU\t040H\t\t; timer channel 0 port\nTIMETYPE\tEQU\t036H\t\t; type of timer.\n\t;  36H = 0011 0110\t\t\t    \n\t;        --         select channel 0\t\t\t    \n\t;          --       read/load low byte then high byte for timer\t\t\t    \n\t;             ---   timer mode 3\t\t\t    \n\t;                -  0 - binary , 1 - BCD data\n\t\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////////// Structs ////////////////////////////////////////\n\n\n; Structure of memory in real mode handler.\n; This is at the very start of the real mode code.\n; This information may not change unless the real mode version is also changed.\n\nSTRUC TimerType\n; For speed, PM uses a DD while RM used DW\n; For speed, SysRate and SysError are DD in PM and are DW in real mode.\n\n\tTrueRate\t\tDD\t?\t; True rate of clock. (only use word)\n    \tSysTicks\t\tDD\t?\t; Tick count of timer.\n\tSysRate\t\t\tDD\t?\t; Desired rate of timer.\n\tSysError\t \tDD\t?\t; Amount of error in clock rate for desired frequency.\n\tSysCurRate\t \tDW\t?\t; Keeps track of when to increment timer.\n\tSysCurError\t\tDW\t?\t; Keeps track of amount of error in timer.\n\n    \tUserTicks\t\tDD\t?\t; Tick count of timer.\n\tUserRate\t \tDD\t?\t; Desired rate of timer.\n\tUserError\t \tDD\t?\t; Amount of error in clock rate for desired frequency.\n\tUserCurRate\t \tDW\t?\t; Keeps track of when to increment timer.\n\tUserCurError\t\tDW\t?\t; Keeps track of amount of error in timer.\n\n\tDosAdder\t\tDW\t? \t; amount to add to DosFraction each interrupt.\n\tDosFraction\t\tDW\t?\t; Call dos when overflowed.\n\n\tOldRMI\t\t\tDD\t?\t; The origianl RM interrupt seg:off.\n\tOldPMIOffset\t\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tOldPMISelector\t\tDD\t?\t; The original PM interrupt segment.\n\n\tCodeOffset\t\tDW\t?\t; Offset of the code in the RM stuff.\n\tCallRMIntOffset\t\tDW\t?\t; Offset of function to call DOS timer interrupt.\n\tCallRMIntAddr\t\tDD\t?\t; PM address of CallRealIntOffset for speed.\n\n\tPMIssuedInt\t\tDD\t0\t; PM signals RM to just call Int chain.\t\n\n; These are just used for information on testing.  When all is done, they can\n; be removed, but why?  The don't add too much proccessing time and can\n; be useful.\n\tNumPMInts\t\tDD\t?\t; Number of PM interrupts\n\tNumRMInts\t\tDD\t?\t; Number of RM interrupts.\n\nENDS\n\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;/////////////////////////////////// Prototypes //////////////////////////////////////\n\nGLOBAL\t \tGet_System_Tick_Count:NEAR\nGLOBAL\t \tGet_User_Tick_Count:NEAR\nGLOBAL\t \tGet_RM_Timer_Address:NEAR\nGLOBAL\t \tGet_RM_Timer_Size:NEAR\nGLOBAL\t \tSet_Timer_Frequency:NEAR\nGLOBAL\t \tTimer_Interrupt:NEAR\nGLOBAL\t \tInstall_Timer_Interrupt:NEAR\nGLOBAL\t \tRemove_Timer_Interrupt:NEAR\nGLOBAL\t \tGet_Num_Interrupts:NEAR\nGLOBAL\t\tTimer_Interrupt_Func:FAR\nGLOBAL\t\tDisable_Timer_Interrupt:NEAR\nGLOBAL\t\tEnable_Timer_Interrupt:NEAR\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;//////////////////////////////////////// Data ////////////////////////////////////////\n\tDATASEG\n\n; The current time we will just include the real mode stuff\n; into the protected mode code and then copy it down.  The C side of\n; this will handle this method or reading it off of disk in the real\n; method.\n\nLABEL \tRealBinStart\tBYTE\ninclude \"timereal.ibn\"\nLABEL\tRealBinEnd\tBYTE\n\n\n\n\nLABEL\tLockedDataStart\tBYTE\t\nRealModeSel\tDD\t0\nRealModePtr\tDD\t0\t\t; Pointer to real mode memory.\nRealModeSize\tDD\t0\t\t; Pointer to real mode memory.\nLABEL\tLockedDataEnd\tBYTE\n\n\t\nInitFlags\tDD\t0\t\t; Flags to indicate what has been initialized.\n\n; InitFlags that are set to have a fully functional interrupt.\nIF_ALLOC_RM\t\tequ\t1h\t\t; Allocation of RM was successful.\nIF_SET_VECTORS\t\tequ\t2h\t\t; Vectors have been set.\nIF_LOCKED_PM_CODE\tequ\t4h\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t8h\t\t; Locked PM code for DPMI.\nIF_RATE_CHANGE\t\tequ\t10h\t\t; Timer rate was changed.\nIF_FUNCTIONAL\t\tequ\t20h\t\t; Timer is in and functional.\nIF_LOCKED_RM_CODE\tequ\t40h\t\t; Timer is in and functional.\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;//////////////////////////////////////// Code ////////////////////////////////////////\n\n\tCODESEG\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;/////////////////////////////// Init routines ////////////////////////////////////////\n\n;***************************************************************************\n;* GET_RM_TIMER_ADDRESS -- Return address of real mode code for copy.      *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Timer_Address C Near\n\n\tmov\teax, OFFSET RealBinStart\n\tret\n\n\tENDP\n\n;***************************************************************************\n;* GET_RM_TIMER_SIZE -- return size of real mode timer code.               *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Timer_Size C Near\n\n\tmov\teax, OFFSET RealBinEnd - OFFSET RealBinStart\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* SET_TIMER_RATE -- Set the rate of the timer.                            *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:  ebx = rate to set timer were rate = 1193180 / freq              *\n;*                                                                         *\n;* OUTPUT: none                                                            *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 SKB : Created.                                             *\n;*=========================================================================*\nPROC\tSet_Timer_Rate Near\n\n\tpush\teax\n\tpushf\t\t\t\t\t; to save int enable flag\t\n\tcli\t\t\t\t\t; disable interupts while setting up swapper\n\n\tmov\tal,TIMETYPE\t\t\t; setup to modify timer 0\n\tout\tTIMERCMDREG,al\t\t\t; send command.\n\tmov\teax,ebx\t\t\t\t; get rate.\n\tout\tTIMER0PORT,al\t\t\t; output low byte\n\tmov\tal,ah\n\tout\tTIMER0PORT,al\t\t\t; output high byte\n\n\tsti\n\tpopf\t\t\t\t\t; get int enable flag.\n\tpop\teax\n\n\tret\nENDP\tSet_Timer_Rate\n\n;***************************************************************************\n;* SET_TIMER_FREQUENCY -- Set the frequency of the timer.                  *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:  INT Frequency of user timer.                                    *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\nPROC\tSet_Timer_Frequency C NEAR\n\tUSES\teax,ebx,ecx,edx\n\tARG\tfreq:DWORD\n\tLOCAL\tclockrate:DWORD\n\tLOCAL\tclockfreq:DWORD\n\n\ttest\t[InitFlags],IF_FUNCTIONAL\t; Is our timer system installed?\n\tjz\t??timer_not_installed\t\t; if not, this is not legal.\n\n\n\t; Find out the greater of the frequencies (user or system.)\n\t; Assign the True rate value based of of that.\n\t; store the max frequency in ecx.\n\tmov\tecx,[freq]\t\t\t; get user frequency.\n\tcmp\tecx,SYSTEM_TIMER_FREQ\t\t; compare it with system frequency\n\tjg\t??user_is_fastest\t\t; is user frequency faster?\n\tmov\tecx,SYSTEM_TIMER_FREQ\t\t; no, set clock freq to system frequency.\n??user_is_fastest:   \n\n\t; now get the rate that the clock will be set at.\n\t; ecx is still max frequency.\n\tmov\tesi,[RealModePtr]\n\n\tmov\teax,TIMER_CONST\t\t\t; get the clock constant value.\n\txor\tedx,edx\t\t\t\t; zero for divide.\n\tdiv\tecx\t\t\t\t; rate = TC/freq => eax = eax/ecx;\n\tmov\t[(TimerType PTR esi).TrueRate],eax ; Set our true rate.\n\tmov\tebx,eax\t\t\t\t; save for later. DO NOT USE UNTIL CALL\n\n\t; Set up variables to call DOS correctly.\n\t; When DosFraction overflows, DOS is called.\n\tmov\t[(TimerType PTR esi).DosAdder],ax\t; Init count to until call dos.\n\tmov\t[(TimerType PTR esi).DosFraction],0\t; init the fraction.\n\n\t; now set up the system timer.\n\tmov\tecx,SYSTEM_TIMER_FREQ\t\t\t; get frequency.\n\tmov\teax,TIMER_CONST\t\t\t\t; get constant for formula rate=C/freq.\n\txor\tedx,edx\t\t\t\t   \t; make sure zero for divide\n\tdiv\tecx\t\t\t\t\t; calculate rate\n\tmov\t[(TimerType PTR esi).SysCurRate],ax\t; Init current stuff.\n\tmov\t[(TimerType PTR esi).SysCurError],ax\t; Init current stuff.\n\tmov\t[(TimerType PTR esi).SysRate],eax\t; Save rate of timer\n\tmov\t[(TimerType PTR esi).SysError],edx\t; Save error of timer\n\t; Do not set SysTicks to zero since it always has the same frequency.  It\n\t; should be zero out only when the system clock is installed.\n\n\t; now set up the user timer.\n\tmov\tecx,[freq]\t\t\t\t; get frequency of user timer.\n\tmov\teax,TIMER_CONST\t\t\t\t; get constant for formula rate=C/freq.\n\txor\tedx,edx\t\t\t\t   \t; make sure zero for divide\n\tdiv\tecx\t\t\t\t\t; calculate rate\n\tmov\t[(TimerType PTR esi).UserCurRate],ax\t; Init current stuff.\n\tmov\t[(TimerType PTR esi).UserCurError],ax; Init current stuff.\n\tmov\t[(TimerType PTR esi).UserRate],eax\t; Save rate of timer\n\tmov\t[(TimerType PTR esi).UserError],edx\t; Save error of timer\n\tmov\t[(TimerType PTR esi).UserTicks],0\t; User timer sets to zero when freq change.\n\n\t; Call function to set the rate of the chip, ebx = rate from above.\n\tcall\tSet_Timer_Rate\n\n??timer_not_installed:\n\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* INSTALL_TIMER_Interrupt -- Installs the timer interrupt routine.        *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:  VOID * pointer to RM binary in PM memory.                       *\n;*         LONG Size of RM binary.                                         *\n;*         INT  frequency of user timer.                                   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tInstall_Timer_Interrupt C Near\n\tUSES\tebx,ecx,edx\n\tARG\trm_ptr:DWORD\n\tARG\trm_size:DWORD\n\tARG\tfreq:DWORD\n\tARG\tpartial:DWORD\n\n\t; Are they attempting to set timer again?\n\tcmp\t[RealModePtr],0\n\tjnz\t??error\n\n\t; Make sure all flags are cleared.\n\tcmp\t[InitFlags],0\n\tjnz\t??error\n\n\t; Before setting the interrupt vectors, the code needs to be locked\n\t; for DPMI compatability.  Any code or data accessed must be lockded\n\t; so that no page faults accure during an interrupt.\n\t; First lock the code, then the data.  The stack will already be locked.\n\t; The real mode code is also already locked be default.\n\t; To lock a page set up registers :\n\t; AX = 0600h\n\t; BX:CX\t= starting linear address of memory block\n\t; SI:DI = size of region\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_CODE\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_DATA\n\n\t; now allocate real mode memory and copy the rm binary down to it.\n\tmov\teax,0100h\t\t; set function number\n\tmov\tebx,[rm_size]\t\t; get size of RM binary.\n\tadd\tebx,15\t\t\t; round up \n\tshr\tebx,4\t\t\t; convert to pages.\n\tint\tDPMI_INTR\t \t; do call.\n\tjc\t??error\t\t \t; check for error.\n\tmov\t[ RealModeSel ]\t, edx\n\tshl\teax,4\t\t\t; convert segment to offset.\n\tmov\t[RealModePtr],eax\t; save offset to global variable.\n\n\t; now lock the real mode memory that we allocated, just in\n\t; case it needs to be.\n\n\tmov\teax,0600h\t \t; function number.\n\tmov\tecx,[RealModePtr]\t; ecx must have start of memory.\n\tmov\tedi,[rm_size]\t \t; edi will have size of region in bytes.\n\tmov\t[RealModeSize],edi\t; save off the size for the unlock\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_RM_CODE\n\n\n\t; set up source and destination pointers for the copy.\n\tmov\teax,[RealModePtr]\n\tmov\tesi,[rm_ptr]\t\t; Set up our source pointer.\n\tor\t[InitFlags],IF_ALLOC_RM ; set successful\n\tmov\tedi,eax\t\t\t; put it into esi for copy.\n\tmov\tecx,[rm_size]\n\trep\tmovsb\t\t\t; write RM bin to RM memory.\n\n\n\t; restore esi to point to data and initialize some of it.\n\tmov\tesi,[RealModePtr]\n\tmov\teax,esi\t\t\t\t\t\t; get real mode 32 offset.\n\tshl\teax,12\t\t\t\t\t\t; make seg in high eax.\n\tmov\tax,[(TimerType PTR esi).CallRMIntOffset]\t; create RM addr of call chain.\n\tmov\t[(TimerType PTR esi).CallRMIntAddr],eax\t\t; save it for use in PM int.\n\n\tcmp\t[partial],0\n\tjne\t??partial_exit\n\n\t;==========================================================================\n\t; Get the protected mode interrupt vector keyboard.\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t;==========================================================================\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,IRQ0INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(TimerType PTR esi).OldPMIOffset],edx\t ; save offset.\n\tmov\t[(TimerType PTR esi).OldPMISelector],ecx ; save selector.\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 2503, cl = number of interrupt to get\n\t; output cf error, CX:DX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,IRQ0INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(TimerType PTR esi).OldRMI],ecx\n\n\t;==========================================================================\n\t; only separate method of installation is posible. \n\t; Now it is time to set the Protected mode interrupt Keyboard\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\tmov\teax, 0205h\n\tmov\tbl,IRQ0INTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Timer_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt Keyboard\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,IRQ0INTNUM\n\tmov\tecx,[RealModePtr]     \t\t\t; get address of real code int hand.\n\tshr\tecx,4\t\t\t\t\t; put segment in hi word.\n\tmov\tdx,[(TimerType PTR esi).CodeOffset]  ; Get address of code\n\tint\tDPMI_INTR\t\t\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\t; now set the frequency.\n\tmov\teax,[freq]\n\tor\t[InitFlags],IF_FUNCTIONAL\n\tpush\teax\n\tcall\tNEAR Set_Timer_Frequency\n\tmov\t[(TimerType PTR esi).SysTicks],0\t; Only place SysTicks in inited.\n\tmov\t[(TimerType PTR esi).UserTicks],0\t; Timers start off on same foot.\n\tpop\teax\n\tor\t[InitFlags],IF_RATE_CHANGE\n\n\t; we have finished with success.\n??partial_exit:\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n\tret\t\t\n\n\tENDP\n\n\n;***************************************************************************\n;* REMOVE_TIMER_INTERRUPT -- Removes the timer interrupt vectors.         *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tRemove_Timer_Interrupt C NEAR\n\tUSES\tebx,ecx,edx\n\n\t; check if timer was previosly install\n\tmov\tesi,[RealModePtr]\n\ttest\tesi,esi\n\tjz\t??error\n\n\n\ttest\t[InitFlags],IF_SET_VECTORS\n\tjz\t??vectors_not_set\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt Keyboard\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;====================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,IRQ0INTNUM\n\tmov\tedx,[(TimerType esi).OldRMI]\t\t; get the RM address.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t\t\t; do call.\n\tjc\t??error\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ0INTNUM\n\tmov\tecx,[(TimerType esi).OldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(TimerType esi).OldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n??vectors_not_set:\n\n\t; Call function to set the rate of the chip, ebx = rate.\n\ttest\t[InitFlags],IF_RATE_CHANGE\t; was it changed?\t\n\tjz\t??rate_not_changed\n\tmov\tebx,0FFFFh\t\t\t; back to 18.2 time per second.\n\tcall\tSet_Timer_Rate\t\t\t; call function to set timer.\n??rate_not_changed:\n\t; now free up the real mode memory.\n\ttest\t[InitFlags],IF_LOCKED_RM_CODE\n\tjz\t??rm_not_locked\n\n\tmov\teax , 0601h\n\tmov\tecx, [RealModePtr]\n\tmov\tedi, [RealModeSize]\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??rm_not_locked:\n\ttest\t[InitFlags],IF_ALLOC_RM\n\tjz\t??mem_not_allocated\n\tmov\teax , 0101h\n\tmov\tedx,[ RealModeSel ] \t\t; get physical address of real mode buffer.\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\n??mem_not_allocated:\n\n\t; Now we can unlock all stuff needed for the interrupt.  \n\t; Unlock code\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??code_not_locked:\n\n\t; Unlock data\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??data_not_locked:\n\n\t; we have finished with success.\n\tmov\teax,1\t\t\t; signal success.\n\tmov\t[RealModePtr],0\t\t; To say we can do it again sometime.\n\tmov\t[InitFlags],0\t\t; To say we can do it again sometime.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n\tret\n\n\tENDP\t\n\n\n\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;/////////////////////////////// Access routines //////////////////////////////////////\n\n\n;***************************************************************************\n;* GET_NUM_INTERRUPTS -- Returns the number of interrupts that have occured*\n;*                                                                         *\n;* INPUT: TRUE - returns num RM ints.                                      *\n;*        FALSE - return num PM ints.                                      *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/12/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Num_Interrupts C Near\n\tUSES\tesi\n\tARG\trealmode:DWORD\n\n\tmov\tesi,[RealModePtr]\n\tcmp\t[realmode],0\n\tje\t??prot_mode\n\tmov\teax,[(TimerType PTR esi).NumRMInts]\n\tret\n??prot_mode:\n\tmov\teax,[(TimerType PTR esi).NumPMInts]\n\tret\n\n\tENDP\n\n;***************************************************************************\n;* GET_SYSTEM_TICK_COUNT -- Returns the system tick count.                 *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_System_Tick_Count C Near\n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(TimerType PTR esi).SysTicks]\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GET_USER_TICK_COUNT -- Get tick count of user clock.                    *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/12/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_User_Tick_Count C Near\n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(TimerType PTR esi).UserTicks]\n\tret\n\n\tENDP\n\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;/////////////////////////////// Interrupt routines ///////////////////////////////////\n\n; These macros are placed here to handle to duplicate code in 2 methods in\n; the Timer_Interrupt function.\n\n\nMACRO\tSET_DS_ESI_TO_RM\n\t; Sets DS : ES to point to DGROUP _DATA selector\n\t; Set esi to point to RealModePtr\n\t; Corrupts eax\n\n\tmov\tax , _DATA\n\tmov\tds , ax\n\tmov\tes , ax\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\nENDM\n\n\t\nMACRO\tINCREMENT_TIMERS\n\t; Expects ESI to point to real mode memory.\n\n\tinc\t[(TimerType PTR esi).NumPMInts]\t\t; For testing.\n\n\tmov\teax,[(TimerType PTR esi).TrueRate]\t; Get the rate of the PC clock.\n\tsub\t[(TimerType PTR esi).SysCurRate],ax\t; Sub from our rate counter.\n\tja\t??end_sys\t\t\t\t; If !below zero, do not inc.\n\tmov\tebx,[(TimerType PTR esi).SysRate]\t; Get rate of timer.\n\tmov\tecx,[(TimerType PTR esi).SysError]\t; Get amount of error.\n\tadd\t[(TimerType PTR esi).SysCurRate],bx\t; Add rate to the current.\n\tsub\t[(TimerType PTR esi).SysCurError],cx\t; Subtract err from error count.\n\tjb\t??error_adj_sys\t\t\t\t; If wrapped don't inc.\n\tinc\t[(TimerType PTR esi).SysTicks]\t; increment the timer.\n\tjmp\tshort ??end_sys\n??error_adj_sys:\n\tadd\t[(TimerType PTR esi).SysCurError],bx\t; reajust the error by timer rate.\n??end_sys:\n\tsub\t[(TimerType PTR esi).UserCurRate],ax ; Sub from our rate counter.\n\tja\t??end_user\t     \t\t\t; If !below zero, do not inc.\n\tmov\tebx,[(TimerType PTR esi).UserRate]\t; Get rate of timer.\n\tmov\tecx,[(TimerType PTR esi).UserError]\t; Get amount of error.\n\tadd\t[(TimerType PTR esi).UserCurRate],bx\t; Add rate to the current.\n\tsub\t[(TimerType PTR esi).UserCurError],cx; Subtract err from error count.\n\tjb\t??error_adj_user       \t\t\t; If wrapped don't inc.\n\tinc\t[(TimerType PTR esi).UserTicks]\t; increment the timer.\n\tjmp\tshort ??end_user\n??error_adj_user:\n\tadd\t[(TimerType PTR esi).UserCurError],bx; reajust the error by timer rate.\n??end_user:\n\nENDM\n\n\nMACRO\tENABLE_CLOCK_INT\n\t; Signal 8259 that we are done and that it can bug us again.\n\t; Corrupts al.\n\n\tmov\tal,CLEARISR\t; Signal EOI\n\tsti\t\t\t; enable interrupts.\n\tout\tINTCHIP0,al \t; 8259 interrupt chip controller 0\nENDM\n\nLABEL \tLockedCodeStart\tBYTE\n\n;***************************************************************************\n;* TIMER_INTERRUPT -- Temp routine to mimic a timer system calling ours     *\n;*   This is a temp routine to call our tick count routine.  It will be    *\n;*   replaced once another timer system is put in (such as HMI).           *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tTimer_Interrupt\tNear\n;////////////////////////////// Call prot mode interrupt vector ////////////////////////////////////////\n; This routine will do what it needs to, \n; then it will decide if the old vector should be called.\n; if so, it calls it and never returns to this function.\n; if not, we do our own return.\n; the method for doing this is found in:\n; \"Phar Lap  TNT DOS-Extender Reference Manual, First Addition, p. 142\"\n; It says:\n; 1 - Execute a PUSHFD to save the current flags.\n; 2 - Dec the stack ptr by 8 bytes to save room for the addr of orig handler\n; 3 - Push register I use.\n; 4 - Do any processing.\n; 5 - Put the address of the original handler in the reserved slot.\n; 6 - Pop saved register values\n; 7 - Execute an IRETD to transfer control to original handler.\n\n\tpushfd\t\t\t; Step 1\n\tsub\tesp,8\t\t; Step 2\n\tpush\tebp\t\t; Step 3\n\tmov\tebp,esp\t\t; Set up a stack frame to know where to poke address.\n\n\t; Step 3 continued.  Push used varables.\n\tpushad\n\tpush\tfs gs es ds\n\n\n\t; Step 4.  Now do processing before I chain.\n\t; Set up ds:esi to point at start of real memory block (data is first)\n\n\tcall far Timer_Interrupt_Func\n\n\tSET_DS_ESI_TO_RM\t\t\t; Set ds:esi to point to real mode stuff.\n\n\t; Now take care of calling the old DOS timer interrupt vector.\n\t; This must be the last operation of this module since if we call\n\t; DOS, we will never return.\n\tmov\tax,[(TimerType PTR ds:esi).DosAdder] \n\tadd\t[(TimerType PTR esi).DosFraction],ax\n\tjnc\t??no_dos_call\t\t\t\t\t; if not, skip the call.\n\n\t; Tell RM that we forced the int and not to update timers.\n\tmov\t[(TimerType PTR esi).PMIssuedInt],1\t\t; Make it TRUE\n\n\t; Step 5.\n\t; Now it is time to set up for the call by returning by poking\n\t; the old interrupt handle address in.\n\tmov\teax,[(TimerType PTR esi).OldPMIOffset]\t\t; Get orig offset.\n\tmov\tebx,[(TimerType PTR esi).OldPMISelector]\t; Get orig selector.\n\tmov\t[ss:ebp+4],eax\t\t\t\t\t; Poke offset.\n\tmov\t[ss:ebp+8],ebx\t\t\t\t\t; Poke selector.\n\n\t; Step 6.\n\tpop\tds es gs fs\n\tpopad\n\tpop\tebp  \n\n\t; Step 7.\n\tiretd\t\t\t\t; transfer control to original handler.\n\n??no_dos_call:\n\n\tENABLE_CLOCK_INT\n\n\t; Restore all registers.\n\tpop\tds es gs fs\n\tpopad\n\n\tpop\tebp  \n\tadd\tesp,8\n\tpopfd\t\n\n\tiretd\n;////////////////////////////// Call prot mode interrupt vector ////////////////////////////////////////\n;//////////////////////////////////////////////////////////////////////////////////////////////////////\n\tENDP\n\n\n\n;***************************************************************************\n;* TIMER_INTERRUPT_FUNC -- Handles core timer code                         *\n;*                                                                         *\n;* This function exists so that we can call it from the core HMI driver    *\n;* code when our timer interrupt has not been installed.\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/14/1995 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tTimer_Interrupt_Func C Far\n\tpushfd\t\t\t\t\t; save off the flags\n\tpushad\t\t\t\t\t; save off the main registers\n\tpush\tfs gs es ds\t\t\t; save off the seg registers\n\t\n\tSET_DS_ESI_TO_RM\t\t\t; Set ds:esi to point to real mode stuff.\n\tINCREMENT_TIMERS\t\t\t; Increment Westwoods timers\t\n\n\tpop\tds es gs fs\n\tpopad\n\tpopfd\n\tretf\n\tENDP\n\nLABEL \tLockedCodeEnd\t\tBYTE\n\n;***************************************************************************\n;* DISABLE_TIMER_INTERRUPT_ONLY -- Disables at the hardware level          *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/07/1995 DRD : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tDisable_Timer_Interrupt C Near\n\tpush\teax\n\tpushf\n\n\tsti\t\t\t; disable all interrupts if not disabled\n\tin\tal,021h\t\t; read interrupt Mask register bits 0-7\n\t\t\t\t; apply to irq's 0-7\n\t\t\t\t;   value 0 of enabled\n\t\t\t\t;   value 1 of disabled\n\tor\tal,001h\t\t; setup to disable irq 0\n\tout\t021h,al\t\t; disable irq 0\n\n\tpopf\t\t\t; possibly enable all interrupts (except 0)\n\tpop\teax\n\tretf\n\tENDP\n\n\n;***************************************************************************\n;* ENABLE_TIMER_INTERRUPT_ONLY -- Enables at the hardware level            *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/07/1995 DRD : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tEnable_Timer_Interrupt C Near\n\tpush\teax\n\tpushf\n\n\tsti\t\t\t; disable all interrupts if not disabled\n\tin\tal,021h\t\t; read interrupt Mask register bits 0-7\n\t\t\t\t; apply to irq's 0-7\n\t\t\t\t;   value 0 of enabled\n\t\t\t\t;   value 1 of disabled\n\tand\tal,0FEh\t\t; setup to enable irq 0\n\tout\t021h,al\t\t; enable irq 0\n\n\tpopf\t\t\t; possibly enable all interrupts\n\tpop\teax\n\tretf\n\tENDP\n\n\n\tEND\n\n\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/TIMERDWN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Temp timer for 32bit lib                 *\n *                                                                         *\n *                    File Name : TIMER.CPP                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : July 6, 1994                             *\n *                                                                         *\n *                  Last Update : July 12, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   CDTC::Time -- Return the time on the timer.                           *\n *   CDTC::Stop -- Stop the timer.                                         *\n *   CDTC::Start -- Start a timer.                                         *\n *   CDTC::DownTimerClass -- Construct a timer class object.               *\n *   CDTC::Set -- Set the time of a timer.                           \t\t*\n *   CDTC::Reset -- Clear the timer.                                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"timer.H\"\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////////// Defines /////////////////////////////////////\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////////// Code ////////////////////////////////////////\n\n\n/***************************************************************************\n * TC::CountDownTimerClass -- Construct a timer class object.              *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nCountDownTimerClass::CountDownTimerClass(BaseTimerEnum timer, long set, int on)\n\t\t\t\t\t\t\t:TimerClass(timer, on)\n{\n\tSet(set, on);\n}\n\nCountDownTimerClass::CountDownTimerClass(BaseTimerEnum timer, int on)\n\t\t\t\t\t\t\t:TimerClass(timer, FALSE)\n{\n\tDelayTime = 0;\n\tif (on) Start();\n}\n\n\n/***************************************************************************\n * CDTC::TIME -- Return the time on the timer.                             *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong CountDownTimerClass::Time()\n{\n\tlong ticks = DelayTime - TimerClass::Time();\n\n\tif (ticks < 0) {\n\t\tticks = 0;\n\t}\n\treturn(ticks);\n}\n\n\n/***************************************************************************\n * CDTC::SET -- Set the time of a timer.                             \t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:  ULONG value to set timer at.                                    *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong CountDownTimerClass::Set(long value, BOOL start)\n{\n\tDelayTime = value;\n\tTimerClass::Reset(start);\n\treturn(Time());\n}\n\n\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/TIMEREAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Timer interrupt for RM                   *\n;*                                                                         *\n;*                    File Name : TIMEREAL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : July 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : July 8, 1994   [SKB]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nMODEL TINY\nP386N\n\nLOCALS ??\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////////// Equates ////////////////////////////////////////\n\nINTCHIP0\tEQU\t20h\t\t; 8259 interrupt chip controller 0\nCLEARISR\tEQU\t20h\t\t; Value to write to 8259 to reenable interrupts.\n\nCODESEG\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////////// Data ////////////////////////////////////////\n; This information may not change unless the protected mode version is\n; also changed.\n; For speed, PM uses a DD while RM used DW\nTrueRate\t\tDW\t0\t; True rate of clock. (only use word)\nTrueRateNA\t\tDW\t0\t\t; used for speed in prot mode.\n\n; For speed, SysRate and SysError are DD in PM and are DW in real mode.\nSysTicks\t\tDD\t0\t; Tick count of timer.\nSysRate\t\t\tDD\t0\t; Desired rate of timer.\nSysError\t \tDD\t0\t; Amount of error in clock rate for desired frequency.\nSysCurRate\t \tDW\t0\t; Keeps track of when to increment timer.\nSysCurError\t\tDW\t0\t; Keeps track of amount of error in timer.\n\nUserTicks\t\tDD\t0\t; Tick count of timer.\nUserRate\t \tDD\t0\t; Desired rate of timer.\nUserError\t \tDD\t0\t; Amount of error in clock rate for desired frequency.\nUserCurRate\t \tDW\t0\t; Keeps track of when to increment timer.\nUserCurError\t\tDW\t0\t; Keeps track of amount of error in timer.\n\nDosAdder\t\tDW\t0 \t; amount to add to DosFraction each interrupt.\nDosFraction\t\tDW\t0\t; Call dos when overflowed.\n\nOldRMI\t\t\tDD\t0\t; The origianl RM interrupt seg:off.\nOldPMIOffset\t\tDD\t0\t; The origianl PM interrupt offset\t\t\nOldPMISelector\t\tDD\t0\t; The original PM interrupt segment.\n\nCodeOffset\t\tDW\tRM_Timer_Interrupt_Handler\t; Offset of the code in the RM stuff.\nCallRMIntOffset\t\tDW\tCall_Interrupt_Chain\t\t; Offset of function to call DOS timer interrupt.\nCallRMIntAddr\t\tDD\t0\t; PM address of CallRealIntOffset for speed.\n\nPMIssuedInt\t\tDD\t0\t; PM signals RM to just call Int chain.\t\n\n; These are just used for information on testing.  When all is done, they can\n; be removed, but why?  The don't add too much proccessing time and can\n; be useful.\nNumPMInts\t\tDD\t0\t; Number of PM interrupts\nNumRMInts\t\tDD\t0\t; Number of RM interrupts.\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////////// Code ////////////////////////////////////////\n\n\n; This is here for easy comparison with the PM version.\nMACRO INCREMENT_TIMERS\n\tinc\t[NumRMInts]\t\t; For testing.\n\n\n\t; At this point, increment the system and user timers.\n\tmov\tax,[TrueRate]\t\t; Get the rate of the PC clock.\n\n\tsub\t[SysCurRate],ax\t\t; Sub from our rate counter.\n\tja\t??end_sys\t\t\t; If !below zero, do not inc.\n\n\tmov\tbx,[WORD PTR SysRate]\t; Get rate of timer.\n\tmov\tdx,[WORD PTR SysError]\t; Get amount of error.\n\tadd\t[SysCurRate],bx\t\t; Add rate to the current.\n\n\tsub\t[SysCurError],dx\t; Subtract err from error count.\n\tjb\t??error_adj_sys\t\t; If !below 0, increment counter.\n\n\tinc\t[SysTicks]\t\t; increment the timer.\n\tjmp\tshort ??end_sys\t\t; don't modify SysCurError.\n??error_adj_sys:\n\tadd\t[SysCurError],bx\t; reajust the error by timer rate.\n??end_sys:\n\n\tsub\t[UserCurRate],ax\t; Sub from our rate counter.\n\tja\t??end_user\t\t; If !below zero, do not inc.\n\n\tmov\tbx,[WORD PTR UserRate]\t; Get rate of timer.\n\tmov\tdx,[WORD PTR UserError]\t; Get amount of error.\n\tadd\t[UserCurRate],bx\t; Add rate to the current.\n\n\tsub\t[UserCurError],dx\t; Subtract err from error count.\n\tjb\t??error_adj_user\t; If !below 0, increment counter.\n\n\tinc\t[UserTicks]\t\t; increment the timer.\n\tjmp\tshort ??end_user\t; don't modify UserCurError.\n??error_adj_user:\n\tadd\t[UserCurError],bx\t; reajust the error by timer rate.\n??end_user:\n\nENDM\n\n\n\n\n;**************************************************************************\n;* RM_INTERRUPT_HANDLER -- Called when processor interrupted in real mode. *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nlabel RM_Timer_Interrupt_Handler\nstart_RM_Timer_Interrupt_Handler:\n\n\tpush\tax\n\tpush\tbx\n\tpush\tdx\n\tpush\tds\n\n\tmov\tax,cs\t\t\t; Set data segment to code segment \n\tmov\tds,ax\t\t\t;   since data is in code seg.\n\n\tcmp\t[WORD PTR PMIssuedInt],0; Check to see if PM made Int call.\n\tmov\t[WORD PTR PMIssuedInt],0; Make it false.\t\t\n\tjne\t??call_int_chain\t; if so, just call Int Chain.\n\n\n\tINCREMENT_TIMERS\n\n\n\t; Now check to see if we should call the old timer handler.\n\tmov\tax,[DosAdder]\t\t; Get amount to add each tick.\n\tadd\t[DosFraction],ax      \t; add it to the fraction.\n\tjnc\t??no_int_chain\t      \t; Skip call if no overflow.\n\n??call_int_chain:\n\tpushf\t\t\t\t; Push flags for interrupt call.\n       \tcall\t[OldRMI]\t\t; chain the call.\n\n??no_int_chain:\n\tsti\n\tmov\tal,CLEARISR   \t\t; value to clear In Service Register\n\tmov\tdx,INTCHIP0\n\tout\tdx,al\t\t\t; 8259 interrupt chip controller 0\nexit1:\n\n\tpop\tds\n\tpop\tdx\n\tpop\tbx\n\tpop\tax\n\tiret\n\n\n\n;**************************************************************************\n;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nCall_Interrupt_Chain:\n\n\tpushf\n\tcall\t[OldRMI]\t\t;\n\tretf\n\nSTACK\t   ; Don't really need this\n\nEND\n\n\n\n\nIF 0\n; mono print stuff.\n\tpushf\n\tpush\tax\n\tpush\tdi\n\tpush\tes\n\n\tmov\tax,0B000h\t\t; ES:DI = Mono RAM address.\n\tmov\tes,ax\n\t\t\n\tmov\tal,'A'\n\tmov\tah,2\n\tand\tdi,63\n\n\tstosw\n\n\tpop\tes\n\tpop\tdi\n\tpop\tax\n\tpopf\nENDIF\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/TIMERINI.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Temp timer for 32bit lib                 *\n *                                                                         *\n *                    File Name : TIMERINI.CPP                             *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : July 6, 1994                             *\n *                                                                         *\n *                  Last Update : July 6, 1994   [SKB]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Init_Timer_System -- Initialize the WW timer system.                  *\n *   Remove_Timer_System -- Removes the timer system.                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include <mmsystem.h>\n#include \"timer.H\"\n#include <profile.h>\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////////// Defines /////////////////////////////////////\n\n#define COPY_FROM_MEM\tTRUE\n\n/////////////////////////////////////////////////////////////////////////////////\n////////////////////////////// timera.asm functions//////////////////////////////\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern BOOL Install_Timer_Interrupt(VOID *bin_ptr, UINT rm_size, UINT freq, BOOL partial);\nextern BOOL Remove_Timer_Interrupt(VOID);\n\n#ifdef __cplusplus\n}\n#endif\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////// Global Data /////////////////////////////////////\n\nBOOL\tTimerSystemOn\t= FALSE;\n\n// Global timers that the library or user can count on existing.\nTimerClass\t\t\t\t\tTickCount(BT_SYSTEM);\nCountDownTimerClass\t\tCountDown(BT_SYSTEM, 0);\n\n\n// Prototype for timer callback\nvoid CALLBACK Timer_Callback ( UINT event_id, UINT res1 , DWORD user, DWORD  res2, DWORD  res3 );\n\nHANDLE\tTimerThreadHandle = 0;\t\t//Handle of timer thread\nint\t\tInTimerCallback\t= 0;\t\t//Flag to say if we are in a timer callback\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////////// Code ////////////////////////////////////////\n\n\n\n\n\n/***************************************************************************\n * WinTimerClass::WinTimerClass -- Initialize the WW timer system.         *\n *                                                                         *\n *                                                                         *\n * INPUT: UINT : user timer frequency.\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/5/95 3:47PM : ST Created.                                          *\n *=========================================================================*/\nWinTimerClass::WinTimerClass (UINT freq, BOOL partial)\n{\n\tBOOL\t\tsuccess;\n\n\t//\n\t// Inform windows that we want a higher than normal\n\t// timer resolution\n\t//\n#ifdef __SW_EP\n\ttimeBeginPeriod(1000/PROFILE_RATE);\n\tFrequency = PROFILE_RATE;\n#else\n\ttimeBeginPeriod ( 1000/freq );\n\tFrequency = freq;\n#endif\n\n\n\t//\n\t// Install the timer callback event handler\n\t//\n\tTimerHandle = timeSetEvent ( 1000/freq , 1 , Timer_Callback , 0 , TIME_PERIODIC);\n\tTimerSystemOn = success = ( TimerHandle !=0 );\n\n\tif (success)  {\n\t\tif (!partial) {\n\t\t\tWindowsTimer=this;\n\t\t\tTickCount.Start();\n\t\t}\n\t}else{\n\t\tchar error_str [128];\n\t\tsprintf (error_str, \"Error - timer system failed to start. Error code %d\\n\", GetLastError());\n\t\tOutputDebugString(error_str);\n\t}\n}\n\n\n\n/***************************************************************************\n * WinTimerClass::~WinTimerClass -- Removes the timer system.              *\n *                                                                         *\n *                                                                         *\n * INPUT:   NONE.                                                          *\n *                                                                         *\n * OUTPUT:  BOOL was it removed successfuly                                *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/5/95 3:47PM : ST Created.                                          *\n *=========================================================================*/\nWinTimerClass::~WinTimerClass( void )\n{\n\n\tif ( TimerHandle ){\n\t\ttimeKillEvent ( TimerHandle );\n\t}\n\n\tTimerSystemOn = FALSE;\n\ttimeEndPeriod ( 1000/Frequency );\n}\n\n\n\n\n\n/***********************************************************************************************\n * Timer_Callback -- Main timer callback. Equivalent to a timer interrupt handler              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    uint timer ID                                                                     *\n *           uint reserved                                                                     *\n *           long 0 (application defined)                                                      *\n *           long reserved                                                                     *\n *           long reserved                                                                     *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/5/95 3:19PM ST : Created                                                              *\n *=============================================================================================*/\n\n\nvoid CALLBACK Timer_Callback (UINT , UINT , DWORD , DWORD , DWORD)\n{\n\t//CONTEXT\tcontext;\n\n\tInTimerCallback++;\n\tif (!TimerThreadHandle){\n\t\tDuplicateHandle (GetCurrentProcess(), GetCurrentThread() , GetCurrentProcess() ,&TimerThreadHandle , 0 , TRUE , DUPLICATE_SAME_ACCESS);\n\t}\n\n\n\tif (WindowsTimer) {\n\t\tWindowsTimer->Update_Tick_Count();\n\t}\n\tInTimerCallback--;\n}\n\n\n\n\n\n\n/***********************************************************************************************\n * WinTimerClass::Update_Tick_Count -- update westwood timers                                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/5/95 3:58PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid WinTimerClass::Update_Tick_Count ( void )\n{\n/*\n *\n *  Increment westwood timers\n *\n */\n\tSysTicks++;\n\tUserTicks++;\n\n}\n\n\n\n\n\n\n\n\n/*\n;***************************************************************************\n;* GET_NUM_INTERRUPTS -- Returns the number of interrupts that have occured*\n;*                                                                         *\n;* INPUT: TRUE - returns num RM ints.                                      *\n;*        FALSE - return num PM ints.                                      *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/12/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Num_Interrupts C Near\n\tUSES\tesi\n\tARG\trealmode:DWORD\n\n\tmov\tesi,[RealModePtr]\n\tcmp\t[realmode],0\n\tje\t??prot_mode\n\tmov\teax,[(TimerType PTR esi).NumRMInts]\n\tret\n??prot_mode:\n\tmov\teax,[(TimerType PTR esi).NumPMInts]\n\tret\n\n\tENDP\n  */\n\n\n\n\n/***********************************************************************************************\n * WinTimerClass::Get_System_Tick_Count -- returns the system tick count                       *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   tick count                                                                        *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/5/95 4:02PM ST : Created                                                              *\n *=============================================================================================*/\n\nunsigned WinTimerClass::Get_System_Tick_Count ( void )\n{\n\treturn ( SysTicks );\n}\n\n\n\n/***********************************************************************************************\n * WinTimerClass::Get_User_Tick_Count -- returns the user tick count                           *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   tick count                                                                        *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/5/95 4:02PM ST : Created                                                              *\n *=============================================================================================*/\n\nunsigned WinTimerClass::Get_User_Tick_Count ( void )\n{\n\treturn ( UserTicks );\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/TOBUFF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TOBUFFER.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                  Last Update : Feb 10, 1995   [jrj]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVC::TOBUFFER -- Copies a virtual viewport to a linear buffer         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\n\nTRANSP equ 0\n\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n\n;***************************************************************************\n;* VIVC::TOBUFFER -- Copies a virtual viewport to a linear buffer          *\n;*                                                                         *\n;* INPUT:\tBYTE *\tdest\t\t- buffer to copy to\t\t   *\n;*\t\t\tsize\t\t- size of the buffer to copy to\t   *\n;*\t\t\tx_pixel\t\t- x pixel on viewport to copy from *\n;*\t\t\ty_pixel \t- y pixel on viewport to copy from *\n;*\t\t\tpixel_width\t- the width of copy region\t   *\n;*\t\t\tpixel_height\t- the height of copy region\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    Coordinates and dimensions will be adjusted if they exceed *\n;*\t        the boundaries.  In the event that no adjustment is \t   *\n;*\t        possible this routine will abort.  If the size of the \t   *\n;*\t\tregion to copy exceeds the size passed in for the buffer   *\n;*\t\tthe routine will automatically abort.\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_To_Buffer C near\n\tUSES\tebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tthis_object:DWORD\t\t; this is a class member function\n\tARG\tx_pixel:DWORD\t\t; Page X pixel coordinate.\n\tARG\ty_pixel:DWORD\t\t; Page Y pixel coordinate.\n\tARG\tpixel_width:DWORD\t; Width of region in pixels.\n\tARG\tpixel_height:DWORD\t; Height of region in pixels.\n\tARG\tdest:DWORD\t\t; the buffer to copy to\n\tARG\tbuffer_size:DWORD\t; the size of the buffer\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tLOCAL\tdest_x1 : dword\n\tLOCAL\tdest_y1 : dword\n\tLOCAL\tdest_ajust_width:DWORD\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_area   :  dword\n\n; Clip dest Rectangle against source Window boundaries.\n\n\tmov\t[ dest_x1 ] , 0\n\tmov\t[ dest_y1 ] , 0\n\n\tmov  \tesi , [ this_object ]\t    ; get ptr to dest\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_blit\n\n\ttest\tcl , 1000b\n\tjz\t??scr_left_ok\n\tmov\teax , [ x_pixel ]\n\tneg\teax\n\tmov\t[ x_pixel ] , 0\n\tmov\t[ dest_x1 ] , eax\n\n??scr_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??scr_bottom_ok\n \tmov\teax , [ y_pixel ]\n\tneg\teax\n\tmov\t[ y_pixel ] , 0\n\tmov\t[ dest_y1 ] , eax\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\tmov\teax , [ (GraphicViewPort esi) . GVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n??do_blit:\n\n       cld\n\n       mov\teax , [ (GraphicViewPort esi) . GVPXAdd ]\n       add\teax , [ (GraphicViewPort esi) . GVPWidth ]\n       add\teax , [ (GraphicViewPort esi) . GVPPitch ]\n       mov\tesi , [ (GraphicViewPort esi) . GVPOffset ]\n\n       mov\tecx , eax\n       mul\t[ y_pixel ]\n       add\tesi , [ x_pixel ]\n       add\tesi , eax\n\n       add\tecx , [ x_pixel ]\n       sub\tecx , [ x1_pixel ]\n       mov\t[ scr_ajust_width ] , ecx\n\n       mov\tedi , [ dest ]\n       mov\teax , [ pixel_width ]\n       sub\teax , [ x1_pixel ]\n       add\teax , [ x_pixel ]\n       mov\t[ dest_ajust_width ] , eax\n\n       mov\teax , [ dest_y1 ]\n       mul \t[ pixel_width ]\n       add\teax , [ dest_x1 ]\n       add\tedi , eax\n\n       mov\tedx , [ y1_pixel ]\n       mov\teax , [ x1_pixel ]\n       sub\tedx , [ y_pixel ]\n       jle\t??real_out\n       sub\teax , [ x_pixel ]\n       jle\t??real_out\n\n       mov\tebx , [ pixel_width ]\n       imul\tebx , edx\n       cmp\tebx , [ buffer_size ]\n       jg\t??real_out\n\n\n; ********************************************************************\n; Forward bitblit only\n\nIF TRANSP\n       cmp\t[ transp ] , 0\n       jnz\t??forward_Blit_trans\nENDIF\n\n; the inner loop is so efficient that\n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10\n       jl\t??forward_loop_bytes\n\n??forward_loop_dword:\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\n       jnz\t??forward_loop_dword\n       ret\n\n??forward_loop_bytes:\n       mov\tecx , eax\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_bytes\n       ret\n\n\nIF  TRANSP\n\n??forward_Blit_trans:\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n??forward_loop_trans:\n       mov\tecx , eax\n       jmp\t[ y1_pixel ]\n??forward_trans_line:\n       REPT\t32\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tesi\n\t    \tinc\tedi\n\tENDM\n    ??transp_reference:\n       dec\tecx\n       jge\t??forward_trans_line\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\n       jnz\t??forward_loop_trans\n       ret\nENDIF\n\n??real_out:\n       ret\n\nENDP\tBuffer_To_Buffer\n\nEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/TOPAGE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TOPAGE.ASM                               *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : June 15, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Buffer_To_Page -- Copies a linear buffer to a virtual viewport\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nTRANSP\tequ  0\n\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nCODESEG\n\n;***************************************************************************\n;* VVC::TOPAGE -- Copies a linear buffer to a virtual viewport\t\t   *\n;*                                                                         *\n;* INPUT:\tWORD\tx_pixel\t\t- x pixel on viewport to copy from *\n;*\t\tWORD\ty_pixel \t- y pixel on viewport to copy from *\n;*\t\tWORD\tpixel_width\t- the width of copy region\t   *\n;*\t\tWORD\tpixel_height\t- the height of copy region\t   *\n;*\t\tBYTE *\tsrc\t\t- buffer to copy from\t\t   *\n;*\t\tVVPC *  dest\t\t- virtual viewport to copy to\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    Coordinates and dimensions will be adjusted if they exceed *\n;*\t        the boundaries.  In the event that no adjustment is \t   *\n;*\t        possible this routine will abort.  If the size of the \t   *\n;*\t\tregion to copy exceeds the size passed in for the buffer   *\n;*\t\tthe routine will automatically abort.\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_To_Page C near\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\tARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\tARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\tARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\tARG    \tsrc         :DWORD\t\t; this is a member function\n\tARG\tdest        :DWORD\t\t; what are we blitting to\n\n;\tARG\ttrans       :DWORD\t\t\t; do we deal with transparents?\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tlocal\tscr_x \t: dword\n\tlocal\tscr_y \t: dword\n\tLOCAL\tdest_ajust_width:DWORD\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_area   :  dword\n\n\tcmp\t[ src ] , 0\n\tjz\t??real_out\n\n\n; Clip dest Rectangle against source Window boundaries.\n\n\tmov\t[ scr_x ] , 0\n\tmov\t[ scr_y ] , 0\n\tmov  \tesi , [ dest ]\t    ; get ptr to dest\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_blit\n\n\ttest\tcl , 1000b\n\tjz\t??dest_left_ok\n\tmov\teax , [ x_pixel ]\n\tneg\teax\n\tmov\t[ x_pixel ] , 0\n\tmov\t[ scr_x ] , eax\n\n??dest_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dest_bottom_ok\n\tmov\teax , [ y_pixel ]\n\tneg\teax\n\tmov\t[ y_pixel ] , 0\n\tmov\t[ scr_y ] , eax\n\n??dest_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??dest_right_ok\n\tmov\teax , [ (GraphicViewPort esi) . GVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??dest_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\tmov\teax , [ (GraphicViewPort esi) . GVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n??do_blit:\n\n       cld\n\n       mov\teax , [ (GraphicViewPort esi) . GVPXAdd ]\n       add\teax , [ (GraphicViewPort esi) . GVPWidth ]\n       add\teax , [ (GraphicViewPort esi) . GVPPitch ]\n       mov\tedi , [ (GraphicViewPort esi) . GVPOffset ]\n\n       mov\tecx , eax\n       mul\t[ y_pixel ]\n       add\tedi , [ x_pixel ]\n       add\tedi , eax\n\n       add\tecx , [ x_pixel ]\n       sub\tecx , [ x1_pixel ]\n       mov\t[ dest_ajust_width ] , ecx\n\n\n       mov\tesi , [ src ]\n       mov\teax , [ pixel_width ]\n       sub\teax , [ x1_pixel ]\n       add\teax , [ x_pixel ]\n       mov\t[ scr_ajust_width ] , eax\n\n       mov\teax , [ scr_y ]\n       mul \t[ pixel_width ]\n       add\teax , [ scr_x ]\n       add\tesi , eax\n\n       mov\tedx , [ y1_pixel ]\n       mov\teax , [ x1_pixel ]\n\n       sub\tedx , [ y_pixel ]\n       jle\t??real_out\n       sub\teax , [ x_pixel ]\n       jle\t??real_out\n\n\n; ********************************************************************\n; Forward bitblit only\n\nIF TRANSP\n       test\t[ trans ] , 1\n       jnz\t??forward_Blit_trans\nENDIF\n\n\n; the inner loop is so efficient that\n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10\n       jl\t??forward_loop_bytes\n\n??forward_loop_dword:\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\n       jnz\t??forward_loop_dword\n       ret\n\n??forward_loop_bytes:\n       mov\tecx , eax\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_bytes\n       ret\n\nIF  TRANSP\n\n\n??forward_Blit_trans:\n\n\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n\n??forward_loop_trans:\n       mov\tecx , eax\n       jmp\t[ y1_pixel ]\n??forward_trans_line:\n       REPT\t32\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\tinc\tesi\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tedi\n\tENDM\n    ??transp_reference:\n       dec\tecx\n       jge\t??forward_trans_line\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\n       jnz\t??forward_loop_trans\n       ret\nENDIF\n\n??real_out:\n       ret\n\n\n\tENDP\tBuffer_To_Page\nEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/TST.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#undef _WINDOWS_16_\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#define WIN32\n#define __WIN32\n\n#include <windows.h>\n#include <windowsx.h>\n#include <ole2.h>\n\nmain\n{}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/TXTPRNT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TXTPRNT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 17, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 17, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Buffer_Print -- Assembly Buffer text print routine                    *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \".\\drawbuff.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n;*=========================================================================*\n;* Extern the font pointer which is defined by the font class\t\t   *\n;*=========================================================================*\nGLOBAL\tC FontPtr:DWORD\nGLOBAL\tC FontXSpacing:DWORD\nGLOBAL\tC FontYSpacing:DWORD\nGLOBAL\tC ColorXlat:BYTE\n\n;*=========================================================================*\n;* Define the necessary equates for structures and bounds checking\t   *\n;*=========================================================================*\n; The header of the font file looks like object:\n; \tUWORD\tFontLength;\t\t0\n; \tBYTE\tFontCompress;\t\t2\n;\tBYTE\tFontDataBlocks;\t\t3\n;\tUWORD\tInfoBlockOffset;\t4\n;\tUWORD\tOffsetBlockOffset;\t6\n;\tUWORD\tWidthBlockOffset;\t8\n;\tUWORD\tDataBlockOffset;\t10\n;\tUWORD\tHeightOffset;\t\t12\n; For this reason the following equates have these values:\nFONTINFOBLOCK\t\tEQU\t4\nFONTOFFSETBLOCK\t\tEQU\t6\nFONTWIDTHBLOCK\t\tEQU\t8\nFONTDATABLOCK\t\tEQU\t10\nFONTHEIGHTBLOCK\t\tEQU\t12\n\nFONTINFOMAXHEIGHT\tEQU\t4\nFONTINFOMAXWIDTH\tEQU\t5\n\n\nLOCALS ??\n;*=========================================================================*\n;* Define the color xlate table in the data segment\t\t\t   *\n;*=========================================================================*\n\tDATASEG\n\nColorXlat\tDB\t000H,001H,002H,003H,004H,005H,006H,007H\n\t\tDB\t008H,009H,00AH,00BH,00CH,00DH,00EH,00FH\n\n\t\tDB\t001H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t002H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t003H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t004H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t005H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t006H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t007H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t008H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t009H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00AH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00BH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00CH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00DH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00EH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00FH\n\n\tCODESEG\n\n\n;***************************************************************************\n;* Buffer_PRINT -- Assembly buffer text print routine                      *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/17/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_Print C near\n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\tthis_object:DWORD\n\tARG\tstring:DWORD\n\tARG\tx_pixel:DWORD\n\tARG\ty_pixel:DWORD\n\tARG\tfcolor:DWORD\n\tARG\tbcolor:DWORD\n\n\tLOCAL\tinfoblock:DWORD\t\t; pointer to info block\n\tLOCAL\toffsetblock:DWORD\t; pointer to offset block  (UWORD *)\n\tLOCAL\twidthblock:DWORD\t; pointer to width block   (BYTE  *)\n\tLOCAL\theightblock:DWORD\t; pointer to height block  (UWORD *)\n\n\tLOCAL\tcurline:DWORD\t\t; pointer to first column of current row.\n\tLOCAL\tbufferwidth:DWORD    \t; width of buffer (vpwidth + Xadd)\n\tLOCAL\tnextdraw:DWORD\t\t; bufferwidth - width of cur character.\n\tLOCAL\tstartdraw:DWORD\t\t; where next character will start being drawn.\n\n\tLOCAL\tchar:DWORD\t\t; current character value.\n\tlocal\tptr_string:dword\t\t; pointer to string\n\tLOCAL\tmaxheight:BYTE\t\t; max height of characters in font.\n\tLOCAL\tbottomblank:BYTE\t; amount of empty space below current character.\n\tLOCAL\tcharheight:BYTE\t\t; true height of current character.\n\tLOCAL\tvpwidth:DWORD\n\tLOCAL\tvpheight:DWORD\n\tLOCAL\toriginal_x:DWORD\t; Starting X position.\n\n\tmov\teax,[string]\t\t; check that the string is not NULL\n\tmov\t[ptr_string],eax\n\tcmp\teax,0\n\tjz\t??done\n\n;-------------------------------- Where to draw -----------------------------------------------\n\t; Set up memory location to start drawing.\n\tmov  \tebx,[this_object]\t\t\t\t; get a pointer to dest\n\tmov\teax,[(GraphicViewPort ebx).GVPHeight]\t; get height of viewport\n\tmov\t[vpheight],eax\t\t\t\t; save off height of viewport\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\t; get width of viewport\n\tmov\t[vpwidth],eax\t\t\t\t; save it off for later\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\t; add in xadd for bytes_per_line\n\tadd\teax,[(GraphicViewPort ebx).GVPPitch]\t; add in pitch of direct draw surface\n\tmov\t[bufferwidth],eax     \t\t\t; save it off for later use.\n\n\tmul\t[y_pixel]\t\t\t\t; multiply rowsize * y_pixel start.\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get start of the viewport\n\tadd\tedi,eax\t\t\t\t\t; add y position to start of vp\n\tmov\t[curline],edi\t\t\t\t; save 0,y address for line feed stuff.\n\tadd\tedi,[x_pixel]\t\t\t\t; add to get starting column in starting row.\n\tmov\t[startdraw],edi\t\t\t\t; save it off.\n\n\n\tmov\teax,[x_pixel]\n\tmov\t[original_x],eax\n\n;-------------------------------- Create block pointers ----------------------------------------\n\t; Get the pointer to the font.\n\t; We could check for NULL but why waste the time.\n\t; It is up to programmer to make sure it is set.\n\tmov\tesi,[FontPtr]\t\t; Get the font pointer\n\tor\tesi,esi\n\tjz\t??overflow\n\n\t; Set up some pointers to the different memory blocks.\n\t; esi (FontPtr) is added to each to get the true address of each block.\n\t; Many registers are used for P5 optimizations.\n\t; ebx is used for InfoBlock which is then used in the next section.\n\tmovzx\teax,[WORD PTR esi+FONTOFFSETBLOCK]\t; get offset to offset block\n\tmovzx\tebx,[WORD PTR esi+FONTINFOBLOCK]      \t; get offset to info block (must be ebx for height test)\n\tmovzx\tecx,[WORD PTR esi+FONTWIDTHBLOCK] \t; get offset to width block\n\tmovzx\tedx,[WORD PTR esi+FONTHEIGHTBLOCK]\t; get offset to height block\n\n\tadd\teax,esi\t\t\t\t; add offset of FontPtr to offset block\n\tadd\tebx,esi\t\t\t\t; add offset of FontPtr to info block\n\tadd\tecx,esi\t\t\t\t; add offset of FontPtr to width block\n\tadd\tedx,esi\t\t\t\t; add offset of FontPtr to height block\n\n\tmov\t[offsetblock],eax\t\t; save offset to offset block\n\tmov\t[infoblock],ebx\t\t\t; save offset to info block\n\tmov\t[widthblock],ecx   \t\t; save offset to width block\n\tmov\t[heightblock],edx\t\t; save offset to height block\n\n;------------------------------------------ Test for fit ----------------------------------------------\n\t; Test to make sure the height of the max character will fit on this line\n\t; and and not fall out of the viewport.\n\t; remember we set ebx to FONTINFOBLOCK above.\n\tmovzx\teax,[BYTE PTR ebx + FONTINFOMAXHEIGHT]; get the max height in font.\n\tmov\t[maxheight],al\t\t\t; save it for later use.\n\tadd\teax,[y_pixel]\t\t\t; add current y_value.\n\tcmp\teax,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we're outa here.\n\n\tmov\t[y_pixel],eax\t\t\t; save for next line feed. y value for next line.\n\n\tcld\t\t\t\t\t; Make sure we are always forward copying.\n\n;------------------------ Set palette foreground and background ----------------------------------\n\tmov\teax,[fcolor]\t\t; foreground color\n\tmov\t[ColorXlat+1],al\n\tmov\t[ColorXlat+16],al\n\n\tmov\teax,[bcolor]\t\t; background color\n\tmov\t[ColorXlat],al\n\n;-------------------------------------------------------------------------------------------------\n;----------------------------------------- Main loop ----------------------------------------------\n\t; Now we go into the main loop of reading each character in the string and doing\n\t; something with it.\n??next_char:\n\t; while (*string++)\n\txor\teax,eax\t\t\t\t; zero out since we will just load al.\n\tmov\tesi,[string]\t\t\t; get address on next character.\n\tlodsb\t\t\t\t\t; load the character into al.\n\ttest\teax,0FFH\t\t\t; test to see if character is a NULL\n\tjz\t??done\t\t\t\t; character is NULL, get outa here.\n\n\tmov\tedi,[startdraw]\t\t\t; Load the starting address.\n\n\tmov\t[string],esi\t\t\t; save index into string. (incremented by lodsb)\n\n\tcmp\tal,10\t\t\t\t; is the character a carry return?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\n\tcmp\tal,13\t\t\t\t; is the character a line feed?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\n\tmov\t[char],eax\t\t\t; save the character off for later reference.\n\tmov\tebx,eax\t\t\t\t; save it in ebx for later use also.\n\n\tadd\teax,[widthblock]\t\t; figure address of width of character.\n\tmov\tecx,[x_pixel]\t\t\t; get current x_pixel.\n\tmovzx\tedx,[BYTE PTR eax]\t \t; get the width of the character in dl.\n\tadd\tecx,edx\t\t\t\t; add width of char to current x_pixel.\n\tmov\teax,[FontXSpacing]\n\tadd\tecx,eax\n\tadd\t[startdraw],edx\t\t\t; save start draw for next character.\n\tadd\t[startdraw],eax\t\t\t; adjust for the font spacing value\n\n\tcmp\tecx,[vpwidth]\t\t\t; is the pixel greater then the vp width?\n\tjg\t??force_line_feed\t\t; if so, force a line feed.\n\n\tmov\t[x_pixel],ecx\t\t\t; save value of start of next character.\n\tmov\tecx,[bufferwidth]\t\t; get amount to next y same x (one row down)\n\tsub\tecx,edx\t\t\t\t; take the current width off.\n\tmov\t[nextdraw],ecx\t\t\t; save it to add to edi when done with a row.\n\n\t; At this point we got the character. It is now time to find out specifics\n\t; about drawing the darn thing.\n\t; ebx = char so they can be used as an indexes.\n\t; edx = width of character for loop later.\n\n\t; get offset of data for character into esi.\n\tshl\tebx,1\t\t\t\t; mult by 2 to later use as a WORD index.\n\tmov\tesi,[offsetblock]\t\t; get pointer to begining of offset block.\n\tadd\tesi,ebx\t\t\t\t; index into offset block.\n\tmovzx\tesi,[WORD PTR esi]\t\t; get true offset into data block from FontPtr.\n\tadd\tesi,[FontPtr]\t\t\t; Now add FontPtr address to get true address.\n\n\t; Get top and bottom blank sizes and the true height of the character.\n\tadd\tebx,[heightblock]\t\t; point ebx to element in height array.\n\tmov\tal,[ebx+1]\t\t\t; load the data height into dl.\n\tmov\tcl,[ebx]\t\t\t; load the first data row into cl.\n\tmov\tbl,[maxheight]\t\t\t; get the max height of characters.\n\tmov\t[charheight],al\t\t\t; get number of rows with data.\n\tadd\tal,cl\t\t\t\t; add the two heights.\n\tsub\tbl,al\t\t\t\t; subract topblank + char height from maxheight.\n\tmov\t[bottomblank],bl\t\t; save off the number of blank rows on the bottom.\n\t; leaving this section:\n\t; dl is still the width of the character.\n\t; cl is the height of the top blank area.\n\n\tmov\tebx,OFFSET ColorXlat\t\t; setup ebx for xlat commands.\n\tmov\tdh,dl\t\t\t\t; save the width of the character to restore each loop.\n\n\tcmp\tcl,0\t\t\t\t; is there any blank rows on top?\n\tjz\t??draw_char\t\t\t; if not go and draw the real character.\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjnz\t??loop_top\t\t\t; if not go and write the color\n\n;----------------------------------------- skip Top blank area ----------------------------------------\n\t; this case, the top is transparrent, but we need to increase our dest pointer to correct row.\n\tmovzx\teax,cl\t\t\t\t; get number of rows into eax;\n\tmov\tecx,edx\t\t\t\t; save width since edx will be destroyed by mul.\n\tmul\t[bufferwidth]\t\t\t; multiply that by the width of the buffer.\n\tmov\tedx,ecx\t\t\t\t; restore the width\n\tadd\tedi,eax\t\t\t\t; update the pointer.\n\tjmp\tshort ??draw_char\t\t; now go draw the character.\n\n;----------------------------------------- fill Top blank area ----------------------------------------\n\t; edi was set a long time ago.\n\t; al is the translated color\n??loop_top:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_top\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tdec\tcl\t\t\t\t; decrement or row count\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tjz\t??draw_char\t\t\t; we are done here, go draw the character.\n\tjmp\tshort ??loop_top\t\t; go back to top of loop.\n\n\n;----------------------------------------- Draw character ----------------------------------------------\n??draw_char:\n\tmovzx\tecx,[charheight]\t\t; get the height of character to count down rows.\n\ttest\tecx,ecx\t\t\t\t; is there any data? (blank would not have any)\n\tjz\t??next_char\t\t\t; if no data, go on to next character.\n\n??while_data:\n\tlodsb\t\t\t\t\t; get byte value from font data\n\tmov\tah,al\t\t\t\t; save hinibble\n\tand\teax,0F00FH\t       \t\t; mask of low nibble in al hi nibble in ah.\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiplo\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiplo:\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjz\tshort ??nextrow\t\t\t; check if done with width of char\n\n\tmov\tal,ah\t\t\t\t; restore to get\n\t; test the time difference between looking up in a large table when shr al,4 is not done as\n\t; compared to using only a 16 byte table when using the shr al,4\n\t;shr\tal,4\t\t\t\t; shift the hi nibble down to low nibble\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiphi\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiphi:\n\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\tshort ??while_data\t\t; check if done with width of char\n\n??nextrow:\n\tadd\tedi,[nextdraw]\t\t\t; go to next line.\n\tdec\tecx\t\t\t\t; decrement the number of rows to go\n\tmov\tdh,dl\t\t\t\t; restore our column count for row.\n\tjnz\t??while_data\t\t\t; more data for character.\n\n\t; Now it is time to setup for clearing out the bottom of the character.\n\tmovzx\tecx,[bottomblank]\t\t; get amount on bottom that is blank\n\tcmp\tecx,0\t\t\t\t; if there is no blank bottom...\n\tjz\t??next_char\t\t\t; then skip to go to next character\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjz\t??next_char\t\t\t; skip the top black section to let the background through\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\n;----------------------------------------- Blank below character -----------------------------------\n??loop_bottom:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_bottom\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tdec\tcl\t\t\t\t; decrement or row count\n\tjz\t??next_char\t\t\t; we are done here, go to the next character.\n\tjmp\tshort ??loop_bottom\t\t; go back to top of loop.\n\n;----------------------------------- end of next_char (main) loop ------------------------------------\n;-------------------------------------------------------------------------------------------------\n\n\n;----------------------------------- special case line feeds ----------------------------------------\n\n??force_line_feed:\n\t; decrement pointer *string so that it will be back at same character\n\t; when it goes through the loop.\n\tmov\teax,[string]\t\t\t; get string pointer.\n\tdec\teax\t\t\t\t; decrement it to point to previos char\n\tmov\t[string],eax\t\t\t; save it back off.\n\txor\teax,eax\n\t; Now go into the line feed code.....\n\n??line_feed:\n\tmov\tbl,al\n\tmov\tedx,[y_pixel]\t\t\t; get the current y pixel value.\n\tmovzx\tecx,[maxheight]\t\t\t; get max height for later use.\n\tadd\tecx,[FontYSpacing]\n\tadd\tedx,ecx\t\t\t\t; add max height to y_pixel\n\tcmp\tedx,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we are outa here.\n\n\tmov\teax,[bufferwidth]      \t\t; get bytes to next line.\n\tmov\tedi,[curline]\t\t\t; get start of current line.\n\tmul\tecx\t\t\t\t; mult max height * next line.\n\n\tadd\tedi,eax\t\t\t\t; add adjustment to current line.\n\tadd\t[y_pixel],ecx\t\t\t; increment to our next y position.\n;;; DRD\n\tmov\t[curline],edi\t\t\t; save it off for next line_feed.\n\n\t; Move the cursor to either the left edge of the screen\n\t; or the left margin of the print position depending\n\t; on whether <CR> or <LF> was specified. <CR> = left margin\n\t; <LF> = left edge of screen\n\txor\teax,eax\n\tcmp\tbl,10\n\tje\t??lfeed\n\tmov\teax,[original_x]\n??lfeed:\n\tmov\t[x_pixel],eax\t\t\t; zero out x_pixel\n\n\tadd\tedi,eax\n;;; DRD\tmov\t[curline],edi\t\t\t; save it off for next line_feed.\n\tmov\t[startdraw],edi\t\t\t; save it off so we know where to draw next char.w\n\n\tjmp\t??next_char\n\n??overflow:\n\tmov\t[startdraw],0\t\t\t; Indicate that there is no valid next pos.\n??done:\n\tmov\teax,[startdraw]\t\t\t; return this so calling routine\n\tret\t\t\t\t\t; can figure out where to draw next.\n\n\tENDP\tBuffer_Print\n\n;***************************************************************************\n;* GET_FONT_PALETTE_PTR -- Returns a pointer to the 256 byte font palette  *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tvoid *Get_Font_Palette_Ptr(void);                          *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   08/18/1995 PWG : Created.                                             *\n;*=========================================================================*\n\n\tGLOBAL C\tGet_Font_Palette_Ptr:NEAR\n\tPROC\tGet_Font_Palette_Ptr C near\n\tmov\teax, OFFSET ColorXlat\n\tret\n\tENDP\tGet_Font_Palette_Ptr\n\n\nEND\n\nEND"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VBITBLIT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VBITBLIT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Linear_Blit_To_Vesa -- copies graphic buffer to vesa screen           *\n;*   Vesa_Blit_To_Linear -- Copies vesa screen to graphic buffer           *\n;*   Vesa_Blit_To_Vesa -- Copies a section of vesa screen to vesa screen   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nGLOBAL\tLinear_Blit_To_Vesa\t\t:NEAR\nGLOBAL\tVesa_Blit_To_Linear\t\t:NEAR\nGLOBAL\tVesa_Blit_To_Vesa\t\t:NEAR\n\nCODESEG\n\n;***************************************************************************\n;* LINEAR_BLIT_TO_VESA -- copies graphic buffer to vesa screen             *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n      \tPROC\tLinear_Blit_To_Vesa C near \n\tret\n\tENDP\tLinear_Blit_To_Vesa\n\n;***************************************************************************\n;* VESA_BLIT_TO_LINEAR -- Copies vesa screen to graphic buffer             *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n      \tPROC\tVesa_Blit_To_Linear C near \n\tret\n\tENDP\tVesa_Blit_To_Linear\n\n;***************************************************************************\n;* VESA_BLIT_TO_VESA -- Copies a section of vesa screen to vesa screen     *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n      \tPROC\tVesa_Blit_To_Vesa C near \n\tret\n\tENDP\tVesa_Blit_To_Vesa\nEND\t\n\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VBUFFER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : VBUFFER.CPP                              *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : January 9, 1995                          *\n *                                                                         *\n *                  Last Update : January 9, 1995   [PWG]                  *\n *                                                                         *\n * This module contains the C++ class definitions for the video buffer     *\n * class.  This include routines for class creation and modification\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * VVPC::VideoViewPortClass -- Constructor for basic view port class     \t*\n * VVPC::VideoViewPortClass -- Default constructor for view port class\t\t*\n * VVPC::~VideoViewPortClass -- Destructor for GraphicViewPortClass\t\t\t*\n * VVPC::Attach -- Attaches a viewport to a buffer class                   *\n * VVPC::Change -- Changes position and size of a Video View Port   \t\t\t*\n * VBC::VideoBufferClass -- Default constuctor for video buffers\t\t\t\t*\n * VBC::VideoBufferClass -- Lowlevel constructor for video buffer class    *\n * VBC::~VideoBufferClass -- Destructor for the video buffer class      \t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"vbuffer.h\"\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * VVPC::VIDEOVIEWPORTCLASS -- Constructor for basic view port class     \t*\n *                                                                         *\n * INPUT:\t\tVideoBufferClass * vbuffer\t- buffer to attach to\t\t\t\t*\n *\t\t\t\t\tWORD x\t\t\t\t\t\t\t\t- x offset into buffer\t\t\t*\n *\t\t\t\t\tWORD y\t\t\t\t\t\t\t\t- y offset into buffer\t\t\t*\n *\t\t\t\t\tWORD w\t\t\t\t\t\t\t\t- view port width in pixels   *\n *\t\t\t\t\tWORD h   \t\t\t\t\t\t\t- view port height in pixels\t*\n *                                                                         *\n * OUTPUT:     Constructors may not have a return value\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/09/1994 PWG : Created.                                             *\n *=========================================================================*/\nVideoViewPortClass::VideoViewPortClass(VideoBufferClass *vbuffer, int x, int y, int w, int h)\n{\n\tAttach(vbuffer, x, y, w, h);\n}\n\n/***************************************************************************\n * VVPC::VIDEOVIEWPORTCLASS -- Default constructor for view port class   *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/09/1994 PWG : Created.                                             *\n *=========================================================================*/\nVideoViewPortClass::VideoViewPortClass(void)\n{\n}\n\n/***************************************************************************\n * VVPC::~VIDEOVIEWPORTCLASS -- Destructor for GraphicViewPortClass\t\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     A destructor may not return a value.                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/10/1994 PWG : Created.                                             *\n *=========================================================================*/\nVideoViewPortClass::~VideoViewPortClass(void)\n{\n}\n\n/***************************************************************************\n * VVPC::ATTACH -- Attaches a viewport to a buffer class                   *\n *                                                                         *\n * INPUT:\t\tGraphicBufferClass *g_buff\t- pointer to gbuff to attach to  *\n *\t\t\t\t\tWORD x                     - x position to attach to\t\t\t*\n *\t\t\t\t\tWORD y \t\t\t\t\t\t\t- y position to attach to\t\t\t*\n *\t\t\t\t\tWORD w\t\t\t\t\t\t\t- width of the view port\t\t\t*\n *\t\t\t\t\tWORD h\t\t\t\t\t\t\t- height of the view port\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/10/1994 PWG : Created.                                             *\n *=========================================================================*/\nvoid VideoViewPortClass::Attach(VideoBufferClass *vbuffer, int x, int y, int w, int h)\n{\n\t/*======================================================================*/\n\t/* Verify that the x and y coordinates are valid and placed within the\t*/\n\t/*\t\tphysical buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (x < 0) \t\t\t\t\t\t\t\t\t\t// you cannot place view port off\n\t\tx = 0;\t\t\t\t\t\t\t\t\t\t//\t\tthe left edge of physical buf\n\tif (x >= vbuffer->Get_Width())\t\t\t// you cannot place left edge off\n\t\tx = vbuffer->Get_Width() - 1;\t\t\t//\t\tthe right edge of physical buf\n\tif (y < 0) \t\t\t\t\t\t\t\t\t\t// you cannot place view port off\n\t\ty = 0;\t\t\t\t\t\t\t\t\t\t//\t\tthe top edge of physical buf\n\tif (y >= vbuffer->Get_Height()) \t\t\t// you cannot place view port off\n\t\ty = vbuffer->Get_Height() - 1;\t\t//\t\tbottom edge of physical buf\n\n\t/*======================================================================*/\n\t/* Adjust the width and height of necessary\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (x + w > vbuffer->Get_Width()) \t\t// if the x plus width is larger\n\t\tw = vbuffer->Get_Width() - x;\t\t\t//\t\tthan physical, fix width\n\n\tif (y + h > vbuffer->Get_Height()) \t\t// if the y plus height is larger\n\t\th = vbuffer->Get_Height() - y;\t\t//\t\tthan physical, fix height\n\n\t/*======================================================================*/\n\t/* Get a pointer to the top left edge of the buffer.\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n \tOffset \t\t= vbuffer->Get_Offset() + (vbuffer->Get_Width() * y) + x;\n\n\t/*======================================================================*/\n\t/* Copy over all of the variables that we need to store.\t\t\t\t\t\t*/\n\t/*======================================================================*/\n \tXPos\t\t\t= x;\n \tYPos\t\t\t= y;\n \tXAdd\t\t\t= vbuffer->Get_Width() - w;\n \tWidth\t\t\t= w;\n \tHeight\t\t= h;\n \tVideoBuff \t= vbuffer;\n}\n/***************************************************************************\n * VVPC::CHANGE -- Changes position and size of a Video View Port   \t\t\t*\n *                                                                  \t\t\t*\n * INPUT:   \tWORD the new x pixel position of the Video view port \t\t\t*\n *\t\t\t\t\tWORD the new y pixel position of the Video view port \t\t\t*\n *\t\t\t\t\tWORD the new width of the viewport in pixels\t\t\t  \t\t\t*\n *\t\t\t\t\tWORD the new height of the viewport in pixels\t\t  \t\t\t*\n *                                                                  \t\t\t*\n * OUTPUT:  \tBOOL whether the Video View Port could be sucessfully\t\t\t*\n *\t\t\t\t      resized.\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \t\t\t*\n *                                                                  \t\t\t*\n * WARNINGS:   You may not resize a Video View Port which is derived\t\t\t*\n *\t\t\t\t\t\tfrom a Video View Port Buffer, \t\t\t\t\t\t  \t\t\t*\n *                                                                  \t\t\t*\n * HISTORY:                                                         \t\t\t*\n *   09/14/1994 SKB : Created.                                      \t\t\t*\n *=========================================================================*/\nBOOL VideoViewPortClass::Change(int x, int y, int w, int h)\n{\n\t/*======================================================================*/\n\t/* Can not change a Video View Port if it is actually the physical\t\t*/\n\t/*\t   representation of a Video Buffer.\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (this == Get_Video_Buffer())  {\n\t\treturn(FALSE);\n\t}\n\n\t/*======================================================================*/\n\t/* Since there is no allocated information, just re-attach it to the\t\t*/\n\t/*\t\texisting Video buffer as if we were creating the\t\t\t\t\t\t*/\n\t/*\t\tVideoViewPort.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tAttach(Get_Video_Buffer(), x, y, w, h);\n\treturn(TRUE);\n}\n/***************************************************************************\n * VBC::VIDEOBUFFERCLASS -- Default constuctor for video buffers\t\t\t\t*\n *                                                                         *\n * INPUT:\t\tWORD w\t\t\t- width of buffer in pixels (default = 320)  *\n *\t\t\t\t\tWORD h\t\t\t- height of buffer in pixels (default = 200) *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/13/1994 PWG : Created.                                             *\n *=========================================================================*/\nVideoBufferClass::VideoBufferClass(int w, int h)\n{\n\tOffset\t\t= 0xa0000;\t\t\t\t\t\t\t\t// Get offset to the buffer\n\tWidth\t\t\t= w;\t\t\t\t\t\t\t\t\t\t// Record width of Buffer\n\tHeight\t\t= h;\t\t\t\t\t\t\t\t\t\t// Record height of Buffer\n\tXAdd\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XAdd of Buffer\n\tXPos\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XPos of Buffer\n\tYPos\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record YPos of Buffer\n\tVideoBuff\t= this;\t\t\t\t\t\t\t\t\t// Get a pointer to our self\n}\n\n/***************************************************************************\n * VBC::VIDEOBUFFERCLASS -- Lowlevel constructor for video buffer class    *\n *                                                                         *\n * INPUT:\t\tUWORD\t\tthe selector of the memory reference\t\t\t\t\t*\n *\t\t\t\t\tlong\t\tthe offset of the memory reference\t\t\t\t\t\t*\n *\t\t\t\t\tWORD\t\tthe width of the video buffer\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tWORD\t\tthe height of the video buffer\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\nVideoBufferClass::VideoBufferClass(unsigned short selector, long offset, int w, int h)\n{\n\tOffset\t\t= offset;\t\t\t\t\t\t\t\t// Get offset to the buffer\n\tWidth\t\t\t= w;\t\t\t\t\t\t\t\t\t\t// Record width of Buffer\n\tHeight\t\t= h;\t\t\t\t\t\t\t\t\t\t// Record height of Buffer\n\tXAdd\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XAdd of Buffer\n\tXPos\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XPos of Buffer\n\tYPos\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record YPos of Buffer\n\tVideoBuff\t= this;\t\t\t\t\t\t\t\t\t// Get a pointer to our self\n}\n/*=========================================================================*\n * VBC::~VIDEOBUFFERCLASS -- Destructor for the video buffer class      \t*\n *                                                                         *\n *\tINPUT:\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1994 PWG : Created.                                             *\n *=========================================================================*/\nVideoBufferClass::~VideoBufferClass()\n{\n}\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VCLEAR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Clear the Full Mcga Screen\t\t   *\n;*                                                                         *\n;*                    File Name : CLEAR.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : August 23, 1994   [SKB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVPC::Clear -- Clears a virtual viewport instance                     *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS  ??\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\nCODESEG\n\nPROC\tVesa_Clear C near \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tARG    \tthis:DWORD\t\t\t\t; this is a member function\n\tARG    \tcolor:BYTE\t\t\t\t; what color should we clear to\n\n\tcld \t\t \t\t\t\t; always go forward\n\n\tmov\tebx,[this]\t\t\t\t; get a pointer to viewport\n\tmov\tesi,[(GraphicViewPort ebx).GVPXAdd]\t; esi = add for each line\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get the correct offset\n\tpush\tesi\n\tmov\tedx,[(GraphicViewPort ebx).GVPHeight]\t; ecx = height of viewport\n\tmov\tesi,[(GraphicViewPort ebx).GVPWidth]\t; edx = width of viewport\n\n\n\t;*===================================================================\n\t; Convert the color byte to a DWORD for fast storing\n\t;*===================================================================\n\tmov\tal,[color]\t\t\t\t; get color to clear to\n\tmov\tah,al\t\t\t\t\t; extend across WORD\n\tmov\tecx,eax\t\t\t\t\t; extend across DWORD in\n\tshl\teax,16\t\t\t\t\t; several steps\n\tmov\tax,cx\t\t\n\n\tCall\tVesa_Asm_Set_Win\t\t\t; set the window\n\n\t;*===================================================================\n\t; Find out if we should bother to align the row.\n\t;*===================================================================\n\n??row_by_row_aligned:\n\tcmp\tesi , OPTIMAL_BYTE_COPY\t\t\t; is it worth aligning them?\n\tjl\t??row_by_row\t\t\t\t;   if not then skip\n\t\n\t;*===================================================================\n\t; Now that we have the alignment offset copy each row\n\t;*===================================================================\n\n\n??aligned_loop:\n       lea\tebx , [ edi + esi ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??in_range\n\n\n       xor\tecx , ecx\n       mov\tebx , esi\n       cmp\tedi , 0b0000h\n       jge\t??no_trailing\n       mov\tecx , 0b0000h\n       sub\tecx , edi \n       sub\tebx , ecx\n       rep\tstosb\n??no_trailing:  \n       add\tedi , [ cpu_video_page ]\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n\n       mov\tecx , ebx\n       rep\tstosb\n       add\tedi , [ esp ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??aligned_loop\t\t\t\t; if more to do than do it\n       pop\teax\n       ret\n\n??in_range:\n       mov\tecx , edi\n       mov\tebx , esi\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tstosb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tstosd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tstosb\n       add\tedi , [ esp ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??aligned_loop\t\t\t\t; if more to do than do it\n       pop\teax\n       ret\n\n\t;*===================================================================\n\t; If not enough bytes to bother aligning copy each line across a byte\n\t;    at a time.\n\t;*===================================================================\n??row_by_row:\n\n       lea\tebx , [ edi + esi ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       mov\tebx , esi \n       jl\t??in_range_bytes\n\n       xor\tecx , ecx\n       mov\tebx , esi\n       cmp\tedi , 0b0000h\n       jge \t??no_trailing_bytes\n       mov\tecx , 0b0000h\n       sub\tecx , edi \n       sub\tebx , ecx\n       rep\tstosb\n??no_trailing_bytes:  \n       add\tedi , [ cpu_video_page ]\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n\t\t\t\t\n??in_range_bytes:\n\n       mov\tecx , ebx\n       rep\tstosb\n       add\tedi , [ esp ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??row_by_row\t\t\t\t; if more to do than do it\n       pop\teax\n       ret\n\nENDP\tVesa_Clear\n\n\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VERSION.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : VERSION.C                                *\n *                                                                         *\n *                   Programmer : Christopher Yates                        *\n *                                                                         *\n *                  Last Update : July 26, 1991   [JLB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Version -- Returns with current library version text.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwstd.h\"\n\n\n\nPRIVATE char *version = \"Westwood Studios - 32 Bit Library Version \"\n\t__DATE__\n\t\"\\r\\n\";\n\n/***************************************************************************\n * VERSION -- Returns with current library version text.                   *\n *                                                                         *\n *    Use this routine to determine the current library version.  The      *\n *    version text contains the date that it was created.                  *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  Returns pointer to version text.                               *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/26/1991 JLB : Created.                                             *\n *=========================================================================*/\nchar * __cdecl Version(void)\n{\n\treturn(version);\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VERTBLNK.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/video/rcs/vertblnk.asm 1.1 1994/04/18 09:34:51 jeff_wilson Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library routine                          *\n;*                                                                         *\n;*                    File Name : VERTBLNK.ASM                             *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : 20 August, 1990   [CY]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n; WORD Get_Vert_Blank(VOID);                                               *\n; VOID Wait_Vert_Blank(VOID);\t\t\t\t\t\t   *\n; WORD get_vga_state (VOID) ;\n; VOID set_vga_mode (WORD) ;\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nLOCALS ??\n\nGLOBAL             Get_Vert_Blank       : NEAR\nGLOBAL             Wait_Vert_Blank      : NEAR\nGLOBAL\t\t   get_vga_state\t: NEAR\nGLOBAL\t\t   set_vga_mode\t\t: NEAR\n\n\nCODESEG\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; WORD Get_Vert_Blank(VOID);\n; VOID Wait_Vert_Blank(VOID);\n; WORD get_vga_state (VOID) ;\n; VOID set_vga_mode (WORD) ;\n\n;\n; ----------------------------------------------------------------\n\n;----------------------------------------------------------------------------\n\nPROC\tGet_Vert_Blank C near\n\tUSES edx\n\t\t\n\tmov\tdx,03DAH\t; CRTC status register\n\tin\tal,dx\n\tand\tal,008H\t\t; look at bit 3 vertical sync\n\txor\tah,ah\t\t; zero ah\n\tret\n\nENDP\tGet_Vert_Blank\n\n;----------------------------------------------------------------------------\n\n;----------------------------------------------------------------------------\nPROC\tWait_Vert_Blank C near\n\tUSES eax,ebx,edx\n\tARG\tblank:DWORD\n\n\tmov\tebx,[blank]\t; get vertical blank 0 or 1 for on\n\n\tmov\tedx,03DAH\t; CRTC status register\n\n\tand\tbl,01b\n\tshl\tbl,3\n\n??in_vbi:\n\tin\tal,dx\t\t\t; read CRTC status\n\tand\tal,008h\t\t\t; only vertical sync bit\n\txor\tal,bl\n\tje\t??in_vbi\t\t; in vertical sync\n\n??out_vbi:\n\tin\tal,dx\t\t\t; read CRTC status\n\tand\tal,008h\t\t\t; only vertical sync bit\n\txor\tal,bl\n\tjne\t??out_vbi\t\t; not in vertical sync\n\n\tret\n\nENDP\tWait_Vert_Blank\n\n;----------------------------------------------------------------------------\n\n; WORD get_vga_state (VOID) ;\n\nPROC\tget_vga_state C near\n\tUSES  ebx\n\tmov   eax,0f00h\n\tint   10h\n\tand   eax, 0ffh\n\tret\nENDP\tget_vga_state\n\n;----------------------------------------------------------------------------\n\n; VOID set_vga_mode (WORD) ;\n\nPROC   set_vga_mode C near\n\tARG   mode:dword\n\tmov   eax , [mode]\n\tand   eax , 0ffh\t\n\tint   10h\n\tret\nENDP   set_vga_mode\n\n\n\nEND\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VESA.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VESA.ASM                                 *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : December 8, 1994                         *\n;*                                                                         *\n;*                  Last Update : December 8, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Vesa_Asm_Set_Win -- Sets the current vesa window from Asm             *\n;*   Vesa_Asm_Next_Window -- Sets to the next vesa window                  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS  ??\n\nINCLUDE \"svgaprim.inc\"\n\nGLOBAL\tRMVesaVector\t: DWORD\nGLOBAL\tRMVesaRegs\t: DWORD\n\n\nDPMI_INTR\tEQU\t31h\t\n\nSTRUC DPMI_REGS\n       _edi  dd ?\n       _esi  dd ?\t\n       _ebp  dd ?\t\n       \t     dd ?\n       _ebx  dd ?\t\n       _edx  dd ?\t\n       _ecx  dd ?\t\n       _eax  dd ?\t\n       Flags dw ?\n       _es   dw ?\n       _ds   dw ?\n       _fs   dw ?\n       _gs   dw ?\n       _ip   dw ?\n       _cs   dw ?\n       _sp   dw ?\n       _ss   dw ?\n       \t     dd ?\t\nENDS\n\n\nDATASEG\n\ncpu_video_page\tdd           0h\ncpu_page_limit  dd\t0b0000h\nCurrentBank\tDD  \t     0h\t\t; current vesa bank  \nRealFunc\tDPMI_REGS   ?\t\t; structure to call a real mode int\n\n\n\tCODESEG\n\n\n;***************************************************************************\n;* VESA_ASM_SET_WIN -- Sets the current vesa window from Asm               *\n;*                                                                         *\n;* INPUT:\tedi - offset to set the window for                         *\n;*                                                                         *\n;* OUTPUT:      edi - adjusted offset for window                           *\n;*                                                                         *\n;* PROTO:\tvoid Vesa_Asm_Set_Win(void);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   12/08/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_Asm_Set_Win C near \n\n\tpush\teax\n\tpush\tedi\n\tpush\tecx\n\tpush\tebx\n\n\n\tmov\teax , edi\n\tand\teax , 0ffff0000h\n\tadd\teax , 010000h\n\tmov\t[ cpu_page_limit ] , eax\n\n\tlea\teax , [ edi - 0a0000h ]\n\tand\teax , 0ffff0000h\n\tmov\t[ cpu_video_page ] , eax\n\n\tshr\teax , 14\n\tcmp\teax , [ CurrentBank ]\n\tjz\t ??no_change\n\tmov\t[CurrentBank],eax\t\t; it will be new current bank\n\tmov\tebx , [ BankTable + eax ]\t; find gran value of new bank\n\n\tmov     edi , [ RMVesaRegs ]\t\t; clean up RMRegister bank\n\txor\teax , eax\n\tmov\tecx , 34h / 4\t\t\t; size of RMRegs Bank\n\trep\tstosd\n\n\tmov     edi , [ RMVesaRegs ]\n\tmov\t[(type DPMI_REGS ptr edi ) . _eax ] , 04f05h\n\tmov\t[(type DPMI_REGS ptr edi ) . _ebx ] , 0\n\tmov\t[(type DPMI_REGS ptr edi ) . _edx ] , ebx\n\n\tmov\teax , 0300h\n\txor\tecx , ecx\t\t\t; set amount to copy of stack\n\tmov\tebx , [ RMVesaVector]\t\t; set pointer to func to call\n\tint\tDPMI_INTR\t\t\t; make the call\n ??no_change:\n\tpop\tebx\n\tpop\tecx\n\tpop\tedi\n\tpop\teax\n\tand\tedi,0000ffffh\t\t\t; adjust edi to be 64k\n\tadd\tedi,0a0000h\n\tret\n\tENDP\tVesa_Asm_Set_Win\n\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VESAHOOK.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Vesa Hookup                              *\n;*                                                                         *\n;*                                                                         *\n;*                   Programmer : Julio R. Jerez                           *\n;*                                                                         *\n;*                   Start Date : Jan 31, 1995                             *\n;*                                                                         *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"svgaprim.inc\"\n\n\nDPMI_INTR equ 031h\n\n\nLOCALS ??\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;/////////////////////////////////// Prototypes //////////////////////////////////////\n\nGLOBAL\t  RMVesaVector    : DWORD\nGLOBAL\t  RMVesaRegs      : DWORD\t\nGLOBAL\t  RMVesaVectorSel : DWORD\nGLOBAL\t  Vesa_Hook    \t  : NEAR\nGLOBAL\t  Remove_Vesa \t  : NEAR\nGLOBAL\t  VesaFunc\t  : dword\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;//////////////////////////////////////// Data ////////////////////////////////////////\n\tDATASEG\n\n; The current time we will just include the real mode stuff\n; into the protected mode code and then copy it down.  The C side of\n; this will handle this method or reading it off of disk in the real\n; method.\n\nLABEL \tRealDataStart BYTE\ninclude \"VesaReal.ibn\"\nLABEL\tRealDataEnd BYTE\n\nRMVesaVectorSel DD\t0\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;//////////////////////////////////////// Code ////////////////////////////////////////\n\n\tCODESEG\n\nPROC\tVesa_Hook C Near\n\tUSES\tebx,ecx,edx,ecx,edi,esi\n\tARG\tvesa_ptr:DWORD\n\n\t; Are they attempting to set timer again?\n\tcmp\t[RMVesaVectorSel],0\n\tjnz\t??exit\n\n\t; now allocate real mode memory and copy the rm binary down to it.\n\tmov\teax,0100h\t\t; set function number\n\tlea\tebx , [RealDataEnd]\n\tsub\tebx , offset RealDataStart\n\tpush\tebx\n\n\tadd\tebx , 15 + 040h\n\tshr\tebx,4\t\t\t; convert to pages.\n\tint\tDPMI_INTR\t \t; do call.\n\tpop\tecx\n\tjc\t??error\t\t \t; check for error.\n\n\t; set up source and destination pointers for the copy.\n\tshl\tedx , 16\n\tmov\t[ RMVesaVectorSel ] , edx\n\tshl\teax,4\t\t\t; convert segment to offset.\n\n\tmov\tedi , ecx\n\txor\tesi , esi\n\n;\tpush\tecx\n;\tpush\teax\n;\tmov\tecx , eax\n;\tshld\tebx,ecx,16\n;\tmov\teax,0600h\t\t\t; function number.\n;   \tint\tDPMI_INTR\t\t\t; do call.\n;\tpop\teax\n;\tpop\tecx\n;\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n\tlea\tesi , [ RealDataStart]\n\tlea\tedi , [ eax + 040h ]\t; put it into esi for copy.\n\trep\tmovsb\t\t\t; write RM bin to RM memory.\n\n\tmov\tedx,[vesa_ptr]\t\t; Setup vesa funtion\n\tmov\t[ eax + 40h - 4 ] , edx\n\n\n       ; Chain the Real Vesa funcion interrupt to any avilable\n       ; Interrupt vector so We make sure that the Real Mode\n       ; Keyboard Interrupt service get called at debuging time\n       ; of the library.\n\n       mov\t[ RMVesaRegs ] , eax\n       shl\teax , 12\n       lea\tedi , [ eax + 040h ]  ; ofsset of VesaFunc\n       mov\tbl , 060h\n       mov\tbh , 6\n       mov\teax , 200h\n ??find:\n       int\tDPMI_INTR\n       jc\t??error\n       or\tcx,dx\n       jz\t??found\n       inc\tbl\n       dec\tbh\n       jnz\t??find\n       jmp\t??error\n ??found:\n       mov\teax , 0201h\t\n       mov\tedx , edi\n       shld\tecx , edx , 16\n       and\tebx , 0ffh\n       mov\t[ RMVesaVector ] , ebx\n       int\tDPMI_INTR\n       jc\t??error\n\n ??exit:\n       xor\teax,eax\t\t\t; signal an error.\n       ret\t       \n ??error:\t\n       mov \teax , -1 \n       ret\t\n      ENDP\n\n\n\nPROC\tRemove_Vesa C Near\n\tUSES\tebx,ecx,edx,ecx,edi,esi\n\tARG\tvesa_ptr:DWORD\n\n\n\t; Are they attempting to set timer again?\n\tmov     [VesaFunc],0\n\tcmp\t[RMVesaVectorSel],0\n\tjz\t??exit\n\n       mov\tebx , [ RMVesaVector ]\n       test\tebx , ebx\n       jz\t??exit\n       mov\teax , 0201h\t\n       xor\tedx , edx\n       xor\tecx , ecx \n       int\tDPMI_INTR\n       mov\t[ RMVesaVector ] , 0\n       jc\t??exit\n\n;       mov\teax , 0601h\n;       mov \tecx , [ RMVesaRegs ] \n;       shld\tebx , ecx , 16\n;       lea\tedi , [RealDataEnd]\n;       sub\tedi , offset RealDataStart\n;       add\tedi , 15 + 040h\n;       xor\tesi , esi\n;       int\tDPMI_INTR\n;       jc\t??exit\n\n\tmov\teax,0101h\t\t; set function number\n\tmov\tedx ,[RMVesaVectorSel]\n\ttest \tedx , edx\n\tjz\t??exit\n\tshr\tedx , 16\n\tint\tDPMI_INTR\t \t; do call.\n\tmov\t[RMVesaVectorSel],0\n??exit:\n       ret\t\n      ENDP\n\n\nEND\n\n\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VESAINFO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : VIDEO.C                                  *\n *                                                                         *\n *                   Programmer : David Dettmer                            *\n *                                                                         *\n *                  Last Update : January 12, 1995   [PWG]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Find_Video_Mode -- Converts a dos video mode to a WWLIB video mode    *\n *   Get_Video_Mode -- Returns the current video mode.                     *\n *   Set_Video_Mode -- Sets the requested video mode                       *\n *   Set_Lores_Function_Pointers -- Sets up the lowres function pointers   *\n *   Set_HiRes_Function_Pointers -- Sets the HiRes function pointers       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <dos.h>\n#include \"iostream.h\"\n#include \"video.h\"\n#include \"descmgmt.h\"\n#include \"mcgaprim.h\"\n#include \"gbuffer.h\"\n#include \"vbuffer.h\"\n#include \"wwmem.h\"\n\n#include \"playcd.h\"\n\n\n/***************************************************************************\n * VESA_INFO -- Debug routine which displays vesa info to stdout           *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1994 PWG : Created.                                             *\n *=========================================================================*/\nvoid Vesa_Info(int vesa_mode)\n{\n\tUINT         paras;\n\tUSHORT   \t longest ;\n   union REGS \t regs;\n   struct SREGS sregs;\n\tSEGSEL\t\t   VInfoSel ;\t\t\t \n\tVesaInfoType *\tVInfo ;\n\tSEGSEL\t\t \tModeInfoSel ;\n\tVesaModeInfoType * ModeInfo ;\t\t\t \n\tunsigned   temp ;\n\tshort\t\t* ptr ;\n\tchar       buff [ 256 ] ;\n\tshort mode_table [][4] = { { 0x100 , 640 , 400 , 256 }, \n\t\t\t\t\t  \t\t\t\t   { 0x101 , 640 , 480 , 256 },\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t   { 0x103 , 800 , 600 , 256 },\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t } ;\n\n\tcout << \"\\n\\nWWESTWOOD STUDIOS. Vesa Driver attributes.\\n\" ;\n\n\t// verifie that this is a standard VESA MODE\n\tif ( (vesa_mode < VESA_640X400_256) || ( vesa_mode > VESA_TEXT_132X60 )) {\n\t  cout << \"this is not a standard VESA mode\\n\" ;\n\t  return ;\n\t}\n\n\t// Compute size of VesaInfo structure in paragraphs \n\tparas = ( sizeof(VesaInfoType) + 15 ) >> 4 ;\n\t\n\t// Alloc real-mode memory for VESA structure. \n   if ( DPMI_real_alloc ( paras , & VInfoSel  , & longest ) ) return ;\n\tVInfo = ( VesaInfoType * ) ( VInfoSel . seg << 4 ) ;\n\n\t// Compute size of VesaModeInfo structure in paragraphs \n\tparas = ( sizeof(VesaModeInfoType) + 15 ) >> 4 ;\n\n\t//Alloc real-mode memory for VesaModeInfoType structure. \n   if ( DPMI_real_alloc ( paras , & ModeInfoSel , & longest ) ) \n\t{ \n\t\tDPMI_real_free\t( VInfoSel ) ;\n\t\treturn ;\n\t}\n\tModeInfo = ( VesaModeInfoType * ) ( ModeInfoSel . seg << 4 ) ;\n\n\t// Get Read Vesa Driver Vesa\n\tregs . x . eax = 0x4f00 ;\t\n\tregs . x . edi = 0 ;\n\tsregs . es = VInfoSel . seg ;\n   DPMI_real_intr ( 0x10 , & regs , & sregs );\n\n\tregs . x . eax &= 0xffff ;\n\tif ( regs . x . eax != 0x004F) {\n\t  cout << \"\\nNot Vesa Driver Present\\n\" ;\n\t  DPMI_real_free\t( ModeInfoSel ) ;\n  \t  DPMI_real_free\t( VInfoSel ) ;\n\t  return\t;\n\t}\n\n\ttemp = ( unsigned ) VInfo->AvailModes ;\n\tptr = ( short * ) ( ( ( temp & 0xffff0000 ) >> 12 ) + ( temp & 0xffff ) ) ;\n\tcout << \"Available Video Modes\\n\" ;\n\tfor ( ; * ptr != -1 ; ptr ++ ) \n\t for ( temp = 0 ; temp < 3 ; temp ++ )\t\n\t\t if ( * ptr == mode_table [ temp ] [ 0 ] ) {\n\t\t\tsprintf ( buff , \"%d\\t%d x %d x %d\\n\" ,  \n\t\t\t\t\t\t\t      mode_table [ temp ] [ 0 ],\n\t\t\t\t\t\t\t      mode_table [ temp ] [ 1 ],\n\t\t\t\t\t\t\t      mode_table [ temp ] [ 2 ],\n\t\t\t\t\t\t\t      mode_table [ temp ] [ 3 ] ) ;\n\t\t\tcout << buff ;\n\t\t }\n\n   // Get Info for this particular graphic mode\n  \tregs . x . eax = 0x4F01;\n  \tregs . x . ecx = vesa_mode;\n  \tregs . x . edi = 0 ;\n  \tsregs . es = ModeInfoSel . seg ;\n   DPMI_real_intr ( 0x10 , & regs , & sregs );\n\tregs . x . eax &= 0xffff ;\n\tif ( regs . x . eax != 0x004F) {\n\t  cout << \"\\nGraphic mode \" << vesa_mode << \" is not supported by this video card\\n\" ;\n\t  DPMI_real_free\t( ModeInfoSel ) ;\n  \t  DPMI_real_free\t( VInfoSel ) ;\n\t  return\t;\n\t}\n\n\tcout << \"\\nMode attributes\\n\" ;\n\ttemp = ( unsigned ) ModeInfo->Attributes ;\n\tif ( temp & 0x01 ) cout << \"\\tMode supported in hardware\\n\" ;\n\telse\t\t\t\t    cout << \"\\tMode is not supported in hardware\\n\" ;\n\tif ( temp & 0x20 ) cout << \"\\tMode is not VGA Windowed memory compatible\\n\" ;\n\telse\t\t\t\t    cout << \"\\tMode is VGA Windowed memory compatible\\n\" ;\n\n\tcout << \"Window A attributes\\n\" ;\n\ttemp = ( unsigned ) ModeInfo->WinA_Attributes; ;\n\tif ( temp & 0x02 ) cout << \"\\tWindow A is Readable\\n\" ;\n\telse\t\t\t\t    cout << \"\\tWindow A is not Readable\\n\" ;\n\tif ( temp & 0x04 ) cout << \"\\tWindow A is Writeable\\n\" ;\n\telse\t\t\t\t    cout << \"\\tWindow A is not Writeable\\n\" ;\n\tsprintf ( buff , \"%P\\n\" , ModeInfo->WinA_Segment ) ;\n\tcout << \"\\tWindow A segment address 0x\" << buff + 4 ;\n\n\n\n\tcout << \"Window B attributes\\n\" ;\n\ttemp = ( unsigned ) ModeInfo->WinB_Attributes; ;\n\tif ( temp & 0x02 ) cout << \"\\tWindow B is Readable\\n\" ;\n\telse\t\t\t\t    cout << \"\\tWindow B is not Readable\\n\" ;\n\tif ( temp & 0x04 ) cout << \"\\tWindow B is Writeable\\n\" ;\n\telse\t\t\t\t    cout << \"\\tWindow B is not Writeable\\n\" ;\n\tsprintf ( buff , \"%P\\n\" , ModeInfo->WinB_Segment ) ;\n\tcout << \"\\tWindow B segment address 0x\" << buff + 4 ;\n\n\tcout << \"Window shared attributes\\n\" ;\n\tcout << \"\\tWindow Granularity (KB) :\"\t<< ModeInfo->WinGranularity << \"\\n\" ;\n\tcout << \"\\tWindow Size (KB) : \" << ModeInfo->WinSize\t<< \"\\n\";\n\tcout << \"\\tNumber of Banks : \" << (long)ModeInfo->NumBanks << \"\\n\";\n\tcout << \"\\tBytes per ScanLine : \" << (long)ModeInfo->BytesPerScanline << \"\\n\";\n\tcout << \"\\tXResolution : \" << (long)ModeInfo->XRes << \"\\n\";\n\tcout << \"\\tYResolution : \" << (long)ModeInfo->YRes << \"\\n\";\n\tcout << \"\\tX Char Size : \" << (long)ModeInfo->XCharSize << \"\\n\";\n\tcout << \"\\tY Char Size : \" << (long)ModeInfo->YCharSize << \"\\n\";\n\tcout << \"\\tMemory Model : \" << (long)ModeInfo->MemoryModel << \"\\n\";\n\tcout << \"\\tNumber of planes : \" << (long)ModeInfo->NumPlanes << \"\\n\"\t;\n\tcout << \"\\tBits per pixels : \" << (long)ModeInfo->BitsPerPixel\t<< \"\\n\" ;\n\n\n/*\n\tcout\t<< \"Bttributes:                    \" << (long)ModeInfo.Bttributes\t\t\t<< \"\\n\"\n\t\t\t<< \"Win B Bttributes:              \" << (long)ModeInfo.WinB_Bttributes\t<< \"\\n\"\n\t\t\t<< \"Win B Bttributes:              \" << (long)ModeInfo.WinB_Bttributes\t<< \"\\n\"\n\t\t\t<< \"Win Granularity                \" << (long)ModeInfo.WinGranularity   << \"\\n\"\n\t\t\t<< \"Win Size:                      \" << (long)ModeInfo.WinSize\t\t\t\t<< \"\\n\"\n\t\t\t<< \"Win B Segment:                 \" << hex << (unsigned short)ModeInfo.WinB_Segment\t\t<< \"\\n\"\n\t\t\t<< \"Win B Segment:                 \" << (unsigned short)ModeInfo.WinB_Segment\t\t<< \"\\n\"\n\t\t\t<< \"Bytes per scan line:           \" << dec << (unsigned short)ModeInfo.BytesPerScanline\t<< \"\\n\"\n\t\t\t<< \"X resolution:                  \" << (long)ModeInfo.XRes\t\t\t\t\t<< \"\\n\"\n\t\t\t<< \"Y resolution:                  \" << (long)ModeInfo.YRes             << \"\\n\"\n\t\t\t<< \"X Char Size:                   \" << (long)ModeInfo.XCharSize        << \"\\n\"\n\t\t\t<< \"Y Char Size:                   \" << (long)ModeInfo.YCharSize        << \"\\n\"\n\t\t\t<< \"Number of planes:              \" << (long)ModeInfo.NumPlanes\t\t\t<< \"\\n\"\n\t\t\t<< \"Bits per pixels:               \" << (long)ModeInfo.BitsPerPixel\t\t<< \"\\n\"\n\t\t\t<< \"Number of Banks:               \" << (long)ModeInfo.NumBanks\t\t\t<< \"\\n\"\n\t\t\t<< \"Memory Model:                  \" << (long)ModeInfo.MemoryModel\t\t<< \"\\n\"\n\t\t\t<< \"Bank Size:                     \" << (long)ModeInfo.BankSize         << \"\\n\";\n*/\n  \tDPMI_real_free\t( ModeInfoSel ) ;\n  \tDPMI_real_free\t( VInfoSel ) ;\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VESAREAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Timer interrupt for RM                   *\n;*                                                                         *\n;*                    File Name : TIMEREAL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Julio R. Jerez                           *\n;*                                                                         *\n;*                   Start Date : jan 31 , 1995                            *\n;*                                                                         *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nMODEL TINY\nP386N\n\n\n\nLOCALS ??\n\nCODESEG\n;///////////////////////////////////// Code ////////////////////////////////////////\n\nlabel Vesa_Funcion_Call\nstart:\n \tcall\t[dword ptr cs: 40h - 4]\n\tiret\n\n\n\nEND\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VGETPIX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Clear the Full Mcga Screen\t\t   *\n;*                                                                         *\n;*                    File Name : GETPIXEL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : June 7, 1994   [PWG]                     *\n;*                                                                         *\t     \n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   GVPC::Get_Pixel -- Gets a pixel from the current graphic view port\t   *\n;*   VVPC::Get_Pixel -- Gets a pixel from the current view port\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\nCODESEG\n\n\n;***************************************************************************\n;* VVPC::GET_PIXEL -- Gets a pixel from the current view port\t\t   *\n;*                                                                         *\n;* INPUT:\tWORD the x pixel on the screen.\t\t\t\t   *\n;*\t\tWORD the y pixel on the screen.\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      UBYTE the pixel at the specified location\t\t   *\n;*                                                                         *\n;* WARNING:\tIf pixel is to be placed outside of the viewport then\t   *\n;*\t\tthis routine will abort.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/07/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_Get_Pixel C near \n\tUSES\tebx,ecx,edx,edi\n\n\tARG    \tthis:DWORD\t\t\t\t; this is a member function\n\tARG\tx_pixel:DWORD\t\t\t\t; x position of pixel to set\n\tARG\ty_pixel:DWORD\t\t\t\t; y position of pixel to set\n\n\t;*===================================================================\n\t; Get the viewport information and put bytes per row in ecx\n\t;*===================================================================\n\tmov\tebx,[this]\t\t\t\t; get a pointer to viewport\n\txor\teax,eax\t\t\t\t\t\n\tmov\tedi,[(VideoViewPort ebx).VIVPOffset]\t; get the correct offset\n\tmov\tecx,[(VideoViewPort ebx).VIVPHeight]\t; edx = height of viewport\n\tmov\tedx,[(VideoViewPort ebx).VIVPWidth]\t; ecx = width of viewport\n\n\t;*===================================================================\n\t; Verify that the X pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[x_pixel]\t\t\t\t; find the x position\n\tcmp\teax,edx\t\t\t\t\t;   is it out of bounds\n\tjae\tshort ??exit\t\t\t\t; if so then get out\n\tadd\tedi,eax\t\t\t\t\t; otherwise add in offset\n\n\t;*===================================================================\n\t; Verify that the Y pixel offset if legal\n\t;*===================================================================\t\n\tmov\teax,[y_pixel]\t\t\t\t; get the y position\n\tcmp\teax,ecx\t\t\t\t\t;  is it out of bounds\n\tjae\t??exit\t\t\t\t\t; if so then get out\n\tadd\tedx,[(VideoViewPort ebx).VIVPXAdd]\t; otherwise find bytes per row\n\tmul\tedx\t\t\t\t\t; offset = bytes per row * y\n\tadd\tedi,eax\t\t\t\t\t; add it into the offset\n\n\t;*===================================================================\n\t;* Figure out what bank we are in and set it, then adjust the\n\t;*   offset.\n\t;*===================================================================\n\n       call\tVesa_Asm_Set_Win\n\n\t;*===================================================================\n\t; Write the pixel to the screen\n\t;*===================================================================\n??in_range:\n\txor\teax,eax\t\t\t\t\t; clear the word\n\tmov\tal,[edi]\t\t\t\t; read in the pixel\n??exit:\n\tret\n\tENDP\tVesa_Get_Pixel\n\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VIDEO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : VIDEO.C                                  *\n *                                                                         *\n *                   Programmer : David Dettmer                            *\n *                                                                         *\n *                  Last Update : June 29, 1995   [PWG]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Find_Video_Mode -- Converts a dos video mode to a WWLIB video mode    *\n *   Get_Video_Mode -- Returns the current video mode.                     *\n *   Set_Video_Mode -- Sets the requested video mode                       *\n *   Set_Lores_Function_Pointers -- Sets up the lowres function pointers   *\n *   Set_HiRes_Function_Pointers -- Sets the HiRes function pointers       *\n *   Set_Original_Video_Mode -- sets mode to restore system to on exit     *\n *   Get_Original_Video_Mode -- Gets the original video mode value         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <dos.h>\n#include \"iostream.h\"\n#include \"video.h\"\n#include \"descmgmt.h\"\n#include \"mcgaprim.h\"\n#include \"gbuffer.h\"\n#include \"vbuffer.h\"\n#include \"wwmem.h\"\n\n#include \"playcd.h\"\n\nextern \"C\" int MInstalled ;\nextern \"C\" void Hide_Mouse(void);\nextern \"C\" void Show_Mouse(void);\n\nextern \"C\" void Reset_Mouse (void) ;\nextern \"C\" int  Vesa_Hook ( REALPTR function ) ;\nextern \"C\" void Remove_Vesa (void) ;\nextern \"C\" SEGSEL\t RMVesaVectorSel ;\nextern \"C\" REALPTR VesaFunc;\n\n/*=========================================================================*/\n/* Define the global variables that we require.\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nlong\t\t\t\tBankTable[MAX_BANK_ENTRIES];\nint\t\t\t\tGraphicMode\t\t\t\t= UNINITIALIZED_MODE;\nlong\t\t\t\tXRes\t\t\t\t\t\t= 0;\nlong\t\t\t\tYRes\t\t\t\t\t\t= 0;\nREALPTR\t\t\tVesaFunc;\nunsigned long \tRMVesaVector ;\nunsigned\tlong\tRMVesaRegs ;\n\n/*=========================================================================*\n * Private Varirables\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * VInfo      - Protected mode copy of VInfo structure.\t\t\t\t\t\t\t*\n * ModeInfo   - Protected mode copy of ModeInfo structure.\t\t\t\t\t\t*\n * rpModeInfo - Real ptr to ModeInfo structure in conventional memory.\t\t*\n * rpVInfo    - Real ptr to VInfo structure in conventional memory.\t\t\t*\n * _regs      - Registers used for calling software interrupts.\t\t\t\t*\n *=========================================================================*/\nPRIVATE void \t* rpModeInfo  \t= NULL;\nPRIVATE SEGSEL\trpModeInfoSel ;\nPRIVATE void \t* rpVInfo\t  \t= NULL;\nPRIVATE SEGSEL\trpVInfoSel\t  ;\n\nPRIVATE long\t\t\t\t\t_OriginalVideoMode\t= UNINITIALIZED_MODE;\nPRIVATE VesaInfoType \t\tVInfo;\nPRIVATE VesaModeInfoType\tModeInfo;\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE long Install_Vesa(void);\nPRIVATE long Vesa_Get_Mode_Info(long mode);\nPRIVATE long Vesa_Set_Mode(long mode);\nPRIVATE void Init_Bank_Table(void);\nPRIVATE VOID Set_LoRes_Function_Pointers(VOID);\nPRIVATE VOID Set_HiRes_Function_Pointers(VOID);\n\nextern \"C\" long Vesa_XRes(void);\nextern \"C\" long Vesa_YRes(void);\n\nextern \"C\" char CurrentPalette  [ 256 * 3 ]\t;\nextern \"C\" char PaletteTable\t  [ 1024 ] ;\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * GET_VIDEO_MODE -- Returns the current video mode.                       *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     returns the graphic mode as a WWLIB library define          *\n *                                                                         *\n * WARNINGS:\tnone                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1994     : Created.                                             *\n *=========================================================================*/\nint Get_Video_Mode(void)\t\t\t\n{\n  union REGS \t regs;\n\n\tif( GraphicMode == UNINITIALIZED_MODE ) \n\t{\t\t\n\t\tregs\t. x . eax = 0xf00 ;\t\t// get graphic mode\n\t\tint386 ( 0x10 , & regs , & regs ) ;\n\t\treturn ( regs . w . ax & 0xff ) ;\n\t}\n\treturn(GraphicMode);\t\t\t\t\t\t\t\t\t// return the graphic mode\n}\t\t   \n\n/***************************************************************************\n * Install_Vesa -- Initializes the vesa driver if it exists                *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     return -1 if error/VESA not supported.                      *\n *                                                                         *\n * WARNINGS:\tThis function will not work unless a vesa compatable driver *\n *\t\t\t\t\tis installed in either hardware or software.\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1994 PWG : Created.                                             *\n *=========================================================================*/\nPRIVATE long Install_Vesa(void)\n{\n\tUINT         paras;\n\tUSHORT   \t longest ;\n   union REGS \t regs;\n   struct SREGS sregs;\n\n\t/* Calculate size of VesaInfo structure in paragraphs */\n\tparas = ( sizeof(VesaInfoType) + 15 ) >> 4 ;\n\t\n\t/* Allocate real-mode memory for VESA structure. */\n   if ( DPMI_real_alloc ( paras , & rpVInfoSel  , & longest ) ) return - 1 ;\n\trpVInfo = ( void * ) ( rpVInfoSel . seg << 4 ) ;\n\n\t/* Calculate size of VesaModeInfo structure in paragraphs */\n\tparas = ( sizeof(VesaModeInfoType) + 15 ) >> 4 ;\n\n\t/* Allocate real-mode memory for VESA structure. */\n   if ( DPMI_real_alloc ( paras , & rpModeInfoSel , & longest ) ) \n\t{ \n\t\tRemove_Vesa();\n\t\treturn (-1);\n\t}\n\trpModeInfo = ( void * ) ( rpModeInfoSel . seg << 4 ) ;\n\n\t/* Clear the input buffer */\n\tmemset ( rpVInfo , 0 , sizeof ( VesaInfoType) ) ;\n\n\t\n\t/* Read Vesa information  */\n\tregs . x . eax = 0x4f00 ;\t\n\tregs . x . edi = 0 ;\n\tsregs . es = rpVInfoSel . seg ;\n   DPMI_real_intr ( 0x10 , & regs , & sregs );\n\n\tregs . x . eax &= 0xffff ;\n\tif ( regs . x . eax != 0x004F) return (-1);\n\tMem_Copy ( rpVInfo , & VInfo , sizeof(VesaInfoType)) ;\n\n\treturn 0;\n}\n\n\n/***************************************************************************\n * VESA_GET_MODE_INFO -- Gets info about specified video mode              *\n *                                                                         *\n * INPUT:\t\tlong - the mode we are requesting info about                *\n *                                                                         *\n * OUTPUT:     long - 0 if sucessful, -1 if failure                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1994 PWG : Created.                                             *\n *=========================================================================*/\nPRIVATE long Vesa_Get_Mode_Info(long mode)\n{\n   union REGS \t regs;\n   struct SREGS sregs;\n\n\tif (rpModeInfo ) \n\t{\n\t\t/* Clear the input buffer */\n\t\tmemset ( rpModeInfo, 0, sizeof(VesaModeInfoType));\n\n\t\t/* Set up function call */\n\t\tregs . x . eax = 0x4F01;\n\t\tregs . x . ecx = mode;\n\t\tregs . x . edi = 0 ;\n\t\tsregs . es = rpModeInfoSel . seg ;\n   \tDPMI_real_intr ( 0x10 , & regs , & sregs );\n\n\t\tregs . x . eax &= 0xffff ;\n\t\tif ( regs . x . eax == 0x004F)  \n\t\t{\n\t\t\tMem_Copy ( rpModeInfo , &ModeInfo , sizeof(VesaModeInfoType));\n\n\t\t// this part is only temporary until Phil get the documentation\n\t\t//\tfor DPMI funtion 0x301 simulate real call\n\t\t// in the mean time we will be making call to the vesa driver\n\t\t// thru a real interrupt\n\t\t  if ( Vesa_Hook ( ModeInfo . WinFunc ) ) return ( -1 ) ;\n\t\t  return (0);\n\t\t}\n\t} \n  return (-1);\n}\n\n/***************************************************************************\n * VESA_SET_MODE -- Sets the specified Vesa mode                           *\n *                                                                         *\n * INPUT:\t\tlong - the mode we wish to set                              *\n *                                                                         *\n * OUTPUT:\t\tlong - 0 if all is ok, -1 if we cannot set this mode        *\n *                                                                         *\n * WARNINGS:\tYou must call Install_Vesa before calling Vesa_Set_Mode     *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1994 PWG : Created.                                             *\n *=========================================================================*/\nPRIVATE long Vesa_Set_Mode(long mode)\n{\n   union REGS \t regs;\n   struct SREGS sregs;\n\n\t/* Get mode info */\n\tif ( Vesa_Get_Mode_Info(mode) ) return (-1) ;\n\n\tif ((ModeInfo.Attributes & 0x01) == 0) return (-1);\n\n\t/* Set vesa VIDEO MODE */\n\tregs . x . eax = 0x4F02;\t\t\t\t// \n\tregs . x . ebx = mode;\n\tint386 ( 0x10 , & regs , & regs ) ;\n//\tdelay ( 1000 ) ;\n\n\tif ( VInfo . Capabilities & 1 ) \n\t{\n\t\t/* Set DAC to 6 bit per color register */ \n\t\tregs . x . eax = 0x4F08;\t\t\t\t \n\t\tregs . h . bl  = 0;\n\t\tregs . h . bh = 6 ;\n\t\tint386 ( 0x10 , & regs , & regs ) ;\n//\t\tdelay ( 1000 ) ;\n\t}\n\n\tregs . x . eax &= 0xffff ;\n\tif ( regs . x . eax != 0x004F) return (-1);\n\n\tInit_Bank_Table();\n\treturn (0);\n\n}\n\n/***************************************************************************\n * VESA_XRES -- Returns horizontal resolution of vesa mode                 *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long - the horizontal resolution of vesa mode               *\n *                                                                         *\n * WARNINGS:\tYou must call Install_Vesa and Vesa_Set_Mode before calling *\n *\t\t\t\t\tVesa_XRes().\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1994 PWG : Created.                                             *\n *=========================================================================*/\nlong Vesa_XRes(void)\n{\n\treturn ((long)ModeInfo.XRes);\n}\n\n/***************************************************************************\n * VESA_YRES -- Returns vertical resolution of a vesa mode                 *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long - the horizontal resolution of vesa mode               *\n *                                                                         *\n * WARNINGS:\tYou must call Install_Vesa and Vesa_Set_Mode before calling *\n *\t\t\t\t\tVesa_XRes().\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1994 PWG : Created.                                             *\n *=========================================================================*/\nlong Vesa_YRes(void)\n{\n\treturn ((long)ModeInfo.YRes);\n}\n\n/***************************************************************************\n * INIT_BANK_TABLE -- Initializes the values in the bank table             *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/02/1994 PWG : Created.                                             *\n *=========================================================================*/\nPRIVATE void Init_Bank_Table(void)\n{\n\tlong\tsize,bankval;\n\tint\tnum_banks,lp;\n\tunion REGS \t regs;\n   struct SREGS sregs;\n\n\n\tsize\t\t\t= Vesa_XRes() * Vesa_YRes();\t// get video mode size\n\tnum_banks\t= size / 65536;\t\t\t\t\t// get number of banks\n\n\tif (size % 65536) \t\t\t\t\t\t\t\t// adjust number of banks if\n\t\tnum_banks++;\t\t\t\t\t\t\t\t\t//   they dont break evenly\n\n\tbankval\t= 64 / ModeInfo.WinGranularity;\n\tVesaFunc\t= ModeInfo.WinFunc;\n\n\tfor (lp = 0; lp < num_banks; lp++) \n\t\tBankTable[lp] = lp * bankval;\n\n\n\tregs . x . eax = 0x4F05;\t\t\t\t// Reset Vesa to Point to Bank 0\n\tregs . x . ebx = 0x0000;\n\tregs . x . edx = 0x0000;\n\tint386 ( 0x10 , & regs , & regs ) ;\n\n}\n\n/***************************************************************************\n * SET_MODE -- Used to set a graphic mode                             \t\t*\n *                                                                         *\n * INPUT:\tint  - the mode that we are setting                            *\n *                                                                         *\n * OUTPUT:  int  - FALSE if failure, TRUE otherwise                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1994 PWG : Created.                                             *\n *=========================================================================*/\nint Set_Video_Mode(int mode)\n{\n\tunion   REGS inregs,outregs;\n\tstatic  first_time = 0 ;\n\tint\t  oldmode ;\n \n\t/*======================================================================*/\n\t/* If this is the first time we have set the mode we need to store\t\t*/\n\t/*\t\tof the original mode.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif ( ! first_time ) {\n\t\tfirst_time = 1 ;\n      Set_Original_Video_Mode(Get_Video_Mode());\n  }\n \n\t/*======================================================================*/\n\t/* If the mode we are trying to set is mode zero than we are actually\t*/\n\t/*\t\ttrying to restore the system to its original video mode.\t\t\t\t*/\n\t/*======================================================================*/\n\tif (mode == RESET_MODE) \n\t\tmode \t= Get_Original_Video_Mode();\t// set mode properly\n\n\tif (mode == GraphicMode)\t\t\t  \t// if mode already correct\n\t\treturn(TRUE);\t\t\t\t\t\t  \t//\t\tget out of here\n\n\toldmode = GraphicMode ;\n\tGraphicMode\t= mode ;\n\n\t/**********************************************************************/\n\t/* make sure the mouse is term off before any change */\n\t/*********************************************************************/\n\tif ( MInstalled == TRUE ) Hide_Mouse () ;\n\n\n\t/* clear color palette */\n\tmemset ( CurrentPalette  , 255 , sizeof ( CurrentPalette ) ) ;\n\tmemset ( PaletteTable  , 0 , sizeof ( PaletteTable ) ) ;\n\n\t/*======================================================================*/\n\t/* If we are currently in a vesa mode, free it up so that we can do it\t*/\n\t/*\t\tagain.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif ((oldmode >= VESA_MIN) && (oldmode <= VESA_MAX)) \n\t\tRemove_Vesa();\n\n\n\t/*======================================================================*/\n\t/* If we are requesting a vesa mode, than use the vesa calls to handle\t*/\n\t/*\t\tit.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif ( GraphicMode >= VESA_MIN && GraphicMode <= VESA_MAX) \n\t{\n\t\tinregs . x . eax = MCGA_MODE;\n\t\tint386 ( 0x10 , &inregs , &outregs);\n//\t\tdelay ( 1000 ) ;\n\n\t\tif ( Install_Vesa () != 0 ) {\n\t\t\t\tSet_Video_Mode(oldmode);\n\t\t\t\treturn(FALSE);\n\t  \t}\n\n\t\tif (Vesa_Set_Mode(GraphicMode) != 0) \n\t\t{\n\t\t\tSet_Video_Mode(oldmode);\n\t\t\treturn(FALSE);\n\t\t}\n\t\tXRes = Vesa_XRes();\n\t\tYRes = Vesa_YRes();\n\t\tSet_HiRes_Function_Pointers();\n\t} \n\telse \n\t{\n\t\t/*===================================================================*/\n\t\t/* If not a vesa mode, then handle that as well.\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tinregs . x . eax = GraphicMode ;\n\t\tint386( 0x10, &inregs, &outregs);\n//\t\tdelay ( 1000 ) ;\n\n\t\tif ( GraphicMode == \tMCGA_MODE ) {\n\t\t\tXRes = 320;\n\t\t\tYRes = 200;\n\t\t\tSet_LoRes_Function_Pointers();\n\t\t}\n\t}\n\tif (  MInstalled == TRUE ) {\n\t\tReset_Mouse () ;\n\t\tShow_Mouse () ;\n\t}\n\treturn(TRUE);\n}\n/***************************************************************************\n * VESA_INFO -- Debug routine which displays vesa info to stdout           *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   Must call Install_Vesa before attempting to get the vesa\t\t*\n *\t\t\t\t\tinfo.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1994 PWG : Created.                                             *\n *=========================================================================*/\nvoid Vesa_Info(void)\n{\n\tcout\t<< \"Attributes:                    \" << (long)ModeInfo.Attributes\t\t\t<< \"\\n\"\n\t\t\t<< \"Win A Attributes:              \" << (long)ModeInfo.WinA_Attributes\t<< \"\\n\"\n\t\t\t<< \"Win B Attributes:              \" << (long)ModeInfo.WinB_Attributes\t<< \"\\n\"\n\t\t\t<< \"Win Granularity                \" << (long)ModeInfo.WinGranularity   << \"\\n\"\n\t\t\t<< \"Win Size:                      \" << (long)ModeInfo.WinSize\t\t\t\t<< \"\\n\"\n\t\t\t<< \"Win A Segment:                 \" << hex << (unsigned short)ModeInfo.WinA_Segment\t\t<< \"\\n\"\n\t\t\t<< \"Win B Segment:                 \" << (unsigned short)ModeInfo.WinB_Segment\t\t<< \"\\n\"\n\t\t\t<< \"Bytes per scan line:           \" << dec << (unsigned short)ModeInfo.BytesPerScanline\t<< \"\\n\"\n\t\t\t<< \"X resolution:                  \" << (long)ModeInfo.XRes\t\t\t\t\t<< \"\\n\"\n\t\t\t<< \"Y resolution:                  \" << (long)ModeInfo.YRes             << \"\\n\"\n\t\t\t<< \"X Char Size:                   \" << (long)ModeInfo.XCharSize        << \"\\n\"\n\t\t\t<< \"Y Char Size:                   \" << (long)ModeInfo.YCharSize        << \"\\n\"\n\t\t\t<< \"Number of planes:              \" << (long)ModeInfo.NumPlanes\t\t\t<< \"\\n\"\n\t\t\t<< \"Bits per pixels:               \" << (long)ModeInfo.BitsPerPixel\t\t<< \"\\n\"\n\t\t\t<< \"Number of Banks:               \" << (long)ModeInfo.NumBanks\t\t\t<< \"\\n\"\n\t\t\t<< \"Memory Model:                  \" << (long)ModeInfo.MemoryModel\t\t<< \"\\n\"\n\t\t\t<< \"Bank Size:                     \" << (long)ModeInfo.BankSize         << \"\\n\";\n}\n\n\n/***************************************************************************\n * VESA_SET_WINDOW -- Sets given vesa window to given grain                *\n *                                                                         *\n * INPUT:\t\tint window\t- 0 for window A, 1 for window B                *\n *\t\t\t\t\tint grain   - the granularity point for window\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/05/1994 PWG : Created.                                             *\n *=========================================================================*/\nvoid Vesa_Set_Window(long grain_num)\n{\n    union REGS \t regs;\n    struct SREGS sregs;\n\n\tregs . x . eax = 0x4f05 ;\n\tregs . x . ebx = 0 ;\n\tregs . x . edx = grain_num;\n//\tDPMI_real_call ( ModeInfo.WinFunc , & regs , & sregs ) ;\n\tDPMI_real_intr ( VesaFunc , & regs , & sregs ) ;\n\n}\n\n\n/***************************************************************************\n * SET_LORES_FUNCTION_POINTERS -- Sets up the lowres function pointers     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/12/1995 PWG : Created.                                             *\n *=========================================================================*/\nPRIVATE VOID Set_LoRes_Function_Pointers(VOID)\n{\n\tVVPC_Clear_Func\t\t\t= MCGA_Clear;\n\tVVPC_To_Buffer_Func\t\t= MCGA_To_Buffer;\n\tVVPC_Put_Pixel_Func\t\t= MCGA_Put_Pixel;\n\tVVPC_Get_Pixel_Func\t\t= MCGA_Get_Pixel;\n\tGVPC_Blit_to_VVPC_Func\t= Linear_Blit_To_Linear;\n\tVVPC_Blit_to_GVPC_Func\t= Linear_Blit_To_Linear;\n\tVVPC_Blit_to_VVPC_Func\t= Linear_Blit_To_Linear;\n\tVVPC_Buffer_To_Page\t\t= MCGA_Buffer_To_Page;\n\tGVPC_Scale_To_VVPC\t\t= Linear_Scale_To_Linear;\n\tVVPC_Scale_To_GVPC\t\t= Linear_Scale_To_Linear;\n\tVVPC_Scale_To_VVPC\t\t= Linear_Scale_To_Linear;\n\tVVPC_Print_Func\t\t\t= MCGA_Print;\n}\n/***************************************************************************\n * SET_HIRES_FUNCTION_POINTERS -- Sets the HiRes function pointers         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/12/1995 PWG : Created.                                             *\n *=========================================================================*/\nPRIVATE VOID Set_HiRes_Function_Pointers(VOID)\n{\n\tVVPC_Clear_Func\t\t\t= Vesa_Clear;\n\tVVPC_To_Buffer_Func\t\t= Vesa_To_Buffer;\n\tVVPC_Put_Pixel_Func\t\t= Vesa_Put_Pixel;\n\tVVPC_Get_Pixel_Func\t\t= Vesa_Get_Pixel;\n\tGVPC_Blit_to_VVPC_Func\t= Linear_Blit_To_Vesa;\n\tVVPC_Blit_to_GVPC_Func\t= Vesa_Blit_To_Linear;\n\tVVPC_Blit_to_VVPC_Func\t= Vesa_Blit_To_Vesa;\n\tVVPC_Buffer_To_Page\t\t= Vesa_Buffer_To_Page;\n\tGVPC_Scale_To_VVPC\t\t= Linear_Scale_To_Vesa;\n\tVVPC_Scale_To_GVPC\t\t= Vesa_Scale_To_Linear;\n\tVVPC_Scale_To_VVPC\t\t= Vesa_Scale_To_Vesa;\n\tVVPC_Print_Func\t\t\t= Vesa_Print;\n}\n\n/***************************************************************************\n * Update_Video_Mode -- used to reprogram the current graphic mode afte    *\n * \t\t\t\t\t\t\ta task swicthing from windows\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   03/18/94 JRJ : Created.                                               *\n *=========================================================================*/\nvoid Update_Video_Mode (void) \n{\n\tunion   REGS inregs,outregs;\n\n\t/* clear color palette */\n\tmemset ( CurrentPalette  , 255 , sizeof ( CurrentPalette ) ) ;\n\tmemset ( PaletteTable  , 0 , sizeof ( PaletteTable ) ) ;\n\n \n\t/**********************************************************************/\n\t/* make sure the mouse is term off before any change */\n\t/*********************************************************************/\n\tif ( MInstalled == TRUE ) \n\t\t\t\t\t\t\t\tHide_Mouse () ;\n\n\t/*======================================================================*/\n\t/* If we are requesting a vesa mode, than use the vesa calls to handle\t*/\n\t/*\t\tit.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif ( GraphicMode >= VESA_MIN && GraphicMode <= VESA_MAX) {\n\t\tinregs . x . eax = MCGA_MODE;\n\t\tint386 ( 0x10 , &inregs , &outregs);\n\t\tVesa_Set_Mode(GraphicMode);  \n\t} \n\telse {\n\t\t/*===================================================================*/\n\t\t/* If not a vesa mode, then handle that as well.\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tinregs . x . eax = GraphicMode ;\n\t\tint386( 0x10, &inregs, &outregs);\n\t}\n\tif (  MInstalled == TRUE ) {\n\t\tReset_Mouse () ;\n\t\tShow_Mouse () ;\n\t}\n}\n\n\n/***************************************************************************\n * SET_ORIGINAL_VIDEO_MODE -- sets mode to restore system to on exit       *\n *                                                                         *\n * INPUT:\t\tint video mode number                                       *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/29/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid Set_Original_Video_Mode(int mode)\n{\n\t_OriginalVideoMode = mode;\n}\n\n\n/***************************************************************************\n * GET_ORIGINAL_VIDEO_MODE -- Gets the original video mode value           *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     int the video mode set when we entered                      *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/29/1995 PWG : Created.                                             *\n *=========================================================================*/\n\nint Get_Original_Video_Mode(void)\n{\n\treturn(_OriginalVideoMode);\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VLBTOVE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : BITBLIT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : December 13, 1994   [PWG]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\nTRANSP   equ 0\n\nCODESEG\n\n\n;***************************************************************************\n;* GVC::BLIT -- Copies a buffer to a graphic page non-linearly             *\n;*                                                                         *\n;* NOTE:\t\tAll coordinate values are expressed in pixels      *\n;*                                                                         *\n;* INPUT:\tVideoViewPortClass *dest -   Video View Port to copy to    *\n;*\t\tWORD src_x\t     \t   - Src x position to copy from   *\n;*\t\tWORD src_y\t\t   - Src y position to copy from   *\n;*\t\tWORD dst_x\t\t   - Dest x position to copy to\t   *\n;*\t\tWORD dst_y\t\t   - Dest y position to copy to\t   *\n;*\t\tWORD w\t\t\t   - Width of region to copy\t   *\n;*\t\tWORD h\t\t\t   - Height of region to copy\t   *\n;*                                                                         *\n;* OUTPUT:     none                                                        *\n;*                                                                         *\n;* WARNINGS:   Coordinates and dimensions will be adjusted if they exceed  *\n;*\t       the boundaries.  In the event that no adjustment is \t   *\n;*\t       possible this routine will abort.\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   05/11/1994 PWG : Created.                                             *\n;*   08/05/1994 PWG : Fixed clipping problem                               *\n;*=========================================================================*\n\tPROC\tLinear_Blit_To_Vesa C near \n\tUSES\tebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG    \tthis        :DWORD\t\t; this is a member function\n\tARG\tdest        :DWORD\t\t; what are we blitting to\n\tARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\tARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\tARG\tdest_x0     :dword\n\tARG\tdest_y0     :dword\n\tARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\tARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\tARG\ttrans       :DWORD\t\t\t; do we deal with transparents?\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tLOCAL\tdest_x1 : dword\n\tLOCAL\tdest_y1 : dword\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_ajust_width:DWORD\n        LOCAL\tsource_area :  dword\n        LOCAL\tdest_area :  dword\n\n; Clip Source Rectangle against source Window boundaries.\n\tmov  \tesi , [ this ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??clip_against_dest\n\n\ttest\tcl , 1000b\n\tjz\t??scr_left_ok\n\tmov\t[ x_pixel ] , 0\n\n??scr_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\t[ y_pixel ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??clip_against_dest\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n\n; Clip Source Rectangle against destination Window boundaries.\n??clip_against_dest:\n\n\tmov\teax , [ dest_x0 ]\n\tmov\tebx , [ dest_y0 ]\n\tsub\teax , [ x_pixel ]\n\tsub\tebx , [ y_pixel ]\n\tadd\teax , [ x1_pixel ]\n\tadd\tebx , [ y1_pixel ]\n\tmov\t[ dest_x1 ] , eax\n\tmov\t[ dest_y1 ] , ebx\n\n\tmov  \tesi , [ dest ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ dest_x0 ]\n\tmov\tebx , [ dest_x1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\teax , [ dest_y0 ]\n\tmov\tebx , [ dest_y1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_blit\n\n\ttest\tcl , 1000b\n\tjz\t??dest_left_ok\n\tmov\teax , [ dest_x0 ]\n\tmov\t[ dest_x0 ] , 0\n\tsub\t[ x_pixel ] , eax\n\n??dest_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dest_bottom_ok\n\tmov\teax , [ dest_y0 ]\n\tmov\t[ dest_y0 ] , 0\n\tsub\t[ y_pixel ] , eax\n\n\n??dest_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??dest_right_ok\n\tmov\tebx , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ dest_x1 ]\n\tmov\t[ dest_x1 ] , ebx\n\tsub\teax , ebx\n\tsub\t[ x1_pixel ] , eax\n\n??dest_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\tmov\tebx , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\teax , [ dest_y1 ]\n\tmov\t[ dest_y1 ] , ebx\n\tsub\teax , ebx\n\tsub\t[ y1_pixel ] , eax\n\n??do_blit:\n\n       cld\t\n       mov\tebx , [ this ]\n       mov\tesi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\tecx , eax\n       mul\t[ y_pixel ]\n       add\tesi , [ x_pixel ]\n       mov\t[ source_area ] , ecx\n       add\tesi , eax\n\n       add\tecx , [ x_pixel ]\n       sub\tecx , [ x1_pixel ]\n       mov\t[ scr_ajust_width ] , ecx\n\n       mov\tebx , [ dest ]\n       mov\tedi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\tecx , eax\n       mul\t[ dest_y0 ]\n       add\tedi , [ dest_x0 ]\n       mov\t[ dest_area ] , ecx\n       add\tedi , eax\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n\n       mov\teax , [ dest_x1 ]\n       sub\teax , [ dest_x0 ]\n       jz\t??real_out\n       sub\tecx , eax\n       mov\t[ dest_ajust_width ] , ecx\n\n       mov\tedx , [ dest_y1 ]\n       sub\tedx , [ dest_y0 ]\n       jz\t??real_out\n\n\n; ********************************************************************       \n; Forward bitblit only\n\nIF TRANSP\n       test\t[ trans ] , 1\n       jnz\t??forward_Blit_trans\nENDIF\n\n\n; the inner loop is so efficient that \n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10        \n       jl\t??forward_loop_bytes\n\n??forward_loop_dword:\n       lea\tebx , [ edi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??in_range\n\n       xor\tecx , ecx\n       mov\tebx , eax\n       cmp\tedi , 0b0000h\n       jge\t??no_trailing\n       mov\tecx , 0b0000h\n       sub\tecx , edi \n       sub\tebx , ecx\n       rep\tmovsb\n??no_trailing:  \n       add\tedi , [ cpu_video_page ]\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_dword\n       ret\n\n??in_range:\n\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_dword\n       ret\n\n??forward_loop_bytes:\n       lea\tebx , [ edi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       mov\tebx , eax\n       jl\t??in_range_bytes\n\n       xor\tecx , ecx\n       cmp\tedi , 0b0000h\n       jge\t??no_trailing_bytes\n       mov\tecx , 0b0000h\n       sub\tecx , edi \n       sub\tebx , ecx\n       rep\tmovsb\n??no_trailing_bytes:  \n       add\tedi , [ cpu_video_page ]\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n??in_range_bytes:\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_bytes\n       ret\n\nIF\tTRANSP\n\n??forward_Blit_trans:\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\t\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n??forward_loop_trans:\n       mov\tecx , eax \n       jmp\t[ y1_pixel ]\n??forward_trans_line:\n       REPT\t32\t\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tesi\n\t    \tinc\tedi\n\tENDM\n    ??transp_reference:\n       dec\tecx \n       jge\t??forward_trans_line\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_trans\n       ret\nENDIF\n\n??real_out:\n       ret\nENDP\tLinear_Blit_To_Vesa\n\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VMPAGEIN.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : VMPAGEIN.ASM                             *\n;*                                                                         *\n;*                   Programmer : Steve Tall\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : March 8th, 1996\t[ST]               *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*  Force_VM_Page_In -- forces a buffer to be paged in under win95         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\t\tIDEAL\n\t\tP386\n\t\tMODEL USE32 FLAT\n\n\n\t\tLOCALS ??\n\n\nGLOBAL\t\tC Force_VM_Page_In:near\n\nCODESEG\n\n\n;***************************************************************************\n;* Force_VM_Page_In -- forces a buffer to be paged in under win95          *\n;*                                                                         *\n;*                                                                         *\n;* INPUT: ptr to start of buffer                                           *\n;*        length of buffer                                                 *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* Prototype:                                                              *\n;*  void Force_VM_Page_In (void *buffer, int length);                      *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   3/8/96 4:18PM ST : Created.                                           *\n;*=========================================================================*\n\n\nproc\t\tForce_VM_Page_In C near\n\t\tUSES\teax,ecx,edx,edi\n\t\tARG\tbuffer_start:dword\n\t\tARG\tbuffer_length:dword\n\n\t\tmov\tecx,[buffer_length]\n\t\txor\tal,al\n\t\ttest\tecx,ecx\n\t\tmov\tedx,4096\n\t\tjz\t??out\n\n\t\tmov\tedi,[buffer_start]\n\n\n??next_page:\tadd\t[edi],al\n\t\tadd\tedi,edx\n\t\tsub\tecx,edx\n\t\tjg\t??next_page\n\n??out:\t\tret\n\nendp\t\tForce_VM_Page_In\n\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VPUTPIX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Clear the Full Mcga Screen\t\t   *\n;*                                                                         *\n;*                    File Name : PUTPIXEL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : June 8, 1994   [PWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   GVPC::Put_Pixel -- Puts a pixel on a graphic viewport                 *\n;*   VIVPC::Put_Pixel -- Puts a pixel on a virtual viewport                *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\n\tCODESEG\n\n;***************************************************************************\n;* VIVPC::PUT_PIXEL -- Puts a pixel on a video viewport                    *\n;*                                                                         *\n;* INPUT:\tWORD the x position for the pixel relative to the upper    *\n;*\t\t\tleft corner of the viewport\t\t\t   *\n;*\t\tWORD the y pos for the pixel relative to the upper left\t   *\n;*\t\t\tcorner of the viewport\t\t\t\t   *\n;*\t\tUBYTE the color of the pixel to write\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNING:\tIf pixel is to be placed outside of the viewport then\t   *\n;*\t\tthis routine will abort.\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/08/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_Put_Pixel C near \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\n\tARG    \tthis:DWORD\t\t\t\t; this is a member function\n\tARG\tx_pixel:DWORD\t\t\t\t; x position of pixel to set\n\tARG\ty_pixel:DWORD\t\t\t\t; y position of pixel to set\n\tARG    \tcolor:BYTE\t\t\t\t; what color should we clear to\n\n\t;*===================================================================\n\t; Get the viewport information and put bytes per row in ecx\n\t;*===================================================================\n\tmov\tebx,[this]\t\t\t\t; get a pointer to viewport\n\tmov\tedi,[(VideoViewPort ebx).VIVPOffset]\t; get the correct offset\n\tmov\tecx,[(VideoViewPort ebx).VIVPHeight]\t; edx = height of viewport\n\tmov\tedx,[(VideoViewPort ebx).VIVPWidth]\t; ecx = width of viewport\n\n\t;*===================================================================\n\t; Verify that the X pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[x_pixel]\t\t\t\t; find the x position\n\tcmp\teax,edx\t\t\t\t\t;   is it out of bounds\n\tjae\tshort ??exit\t\t\t\t; if so then get out\n\tadd\tedi,eax\t\t\t\t\t; otherwise add in offset\n\n\t;*===================================================================\n\t; Verify that the Y pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[y_pixel]\t\t\t\t; get the y position\n\tcmp\teax,ecx\t\t\t\t\t;  is it out of bounds\n\tjae\t??exit\t\t\t\t\t; if so then get out\n\tadd\tedx,[(VideoViewPort ebx).VIVPXAdd]\t; otherwise find bytes per row\n\tmul\tedx\t\t\t\t\t; offset = bytes per row * y\n\tadd\tedi,eax\t\t\t\t\t; add it into the offset\n\n\t;*===================================================================\n\t;* Figure out what bank we are in and set it, then adjust the\n\t;*   offset.\n\t;*===================================================================\n       call\tVesa_Asm_Set_Win\n\n\t;*===================================================================\n\t; Write the pixel to the screen\n\t;*===================================================================\n\tmov\tal,[color]\t\t\t\t; read in color value\n\tmov\t[edi],al\t\t\t\t; write it to the screen\n??exit:\n\tret\n\tENDP\tVesa_Put_Pixel\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VSCALE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VSCALE.ASM                               *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 16, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Vesa_Scale_To_Vesa -- Scales a vesa viewport to a vesa viewport       *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\nCODESEG\n\n\n;***************************************************************************\n;* VESA_SCALE_TO_VESA -- Scales a vesa viewport to a vesa viewport         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_Scale_To_Vesa C near\n\tret\n\tENDP\tVesa_Scale_To_Vesa\n\n\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VSCALE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Testing memory.                          *\n *                                                                         *\n *                    File Name : TEST.CPP                                 *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 14, 1994                           *\n *                                                                         *\n *                  Last Update : January 18, 1995   [PWG]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n*/\n#include <mcgaprim.h>\n#include <gbuffer.h>\n#include <vbuffer.h>\n\n//VideoBufferClass\t\tSeenPage(640,480);\n//GraphicBufferClass \tHidBuff;\n//GraphicBufferClass \tBackBuff;\n\nint Vesa_Scale_To_Vesa ( void * scr,  void * dst, \n\t\t\t\t\t\t\t\t int src_x  , int src_y  , int dst_x , int dst_y , \n\t\t\t\t\t\t\t\t int src_wd , int src_hg , int dst_wd, int dst_hg, \n\t\t\t\t\t\t\t\t BOOL trans , char * remap )\n{\n  int\t   area ;\n  int    width , height ;\n  char * temp ;\n\n  VideoViewPortClass * scr1 = ( VideoViewPortClass * ) scr ;\n\n  width  = src_wd - src_x ;\n  height = src_hg - src_y ;\n  area = width * height ;\n  temp = ( char * ) malloc ( area ) ;\n  if ( ! temp ) return 0 ;\n\n  scr1 -> To_Buffer ( 0, 0, width , height , temp, area );\n  GraphicBufferClass tempbuffer ( area , width , height , temp ) ;\n\n\n  tempbuffer . Scale ( * scr1 , \n                       0, 0, dst_x, dst_y, \n                       width, height , dst_wd, dst_hg , \n\t\t\t\t\t\t\t  trans , remap );\n\n\n  free ( temp ) ;\n  return 0 ;\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VSCLTOVE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VSCALE.ASM                               *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 16, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Linear_Scale_To_Vesa -- Scales a graphic viewport to a vesa viewport  *\n;*   Vesa_Scale_To_Linear -- Scales a Vesa viewport to a graphic viewport  *\n;*   Vesa_Scale_To_Vesa -- Scales a vesa viewport to a vesa viewport       *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\nGLOBAL \tVesa_Asm_Set_Win   : near\t\t\t\nGLOBAL\tcpu_video_page     : dword\nGLOBAL\tcpu_page_limit     : dword\n\n\nCODESEG\n\n\n;***************************************************************************\n;* LINEAR_SCALE_TO_VESA -- Scales a graphic viewport to a vesa viewport\t   *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tLinear_Scale_To_Vesa C near\n\n\t;*===================================================================\n\t;* Define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tthis:DWORD\t\t; pointer to source view port\n\tARG\tdest:DWORD\t\t; pointer to destination view port\n\tARG\tsrc_x:DWORD\t\t; source x offset into view port\n\tARG\tsrc_y:DWORD\t\t; source y offset into view port\n\tARG\tdst_x:DWORD\t\t; dest x offset into view port\n\tARG\tdst_y:DWORD\t\t; dest y offset into view port\n\tARG\tsrc_width:DWORD\t\t; width of source rectangle\n\tARG\tsrc_height:DWORD\t; height of source rectangle\n\tARG\tdst_width:DWORD\t\t; width of dest rectangle\n\tARG\tdst_height:DWORD\t; width of dest height\n\tARG\ttrans:DWORD\t\t; is this transparent?\n\tARG\tremap:DWORD\t\t; pointer to table to remap source\n\n\t;*===================================================================\n\t;* Define local variables to hold the viewport characteristics\n\t;*===================================================================\n\tlocal\tsrc_x0 : dword\n\tlocal\tsrc_y0 : dword\n\tlocal\tsrc_x1 : dword\n\tlocal\tsrc_y1 : dword\n\n\tlocal\tdst_x0 : dword\n\tlocal\tdst_y0 : dword\n\tlocal\tdst_x1 : dword\n\tlocal\tdst_y1 : dword\n\n\tlocal\tsrc_win_width : dword\n\tlocal\tdst_win_width : dword\n\tlocal\tdy_intr : dword\n\tlocal\tdy_frac : dword\n\tlocal\tdy_acc  : dword\n\tlocal\tdx_frac : dword\n\tlocal\tdx_intr : dword\n\n\tlocal\tscan_line     : dword\t\n\tlocal\tcounter_x     : dword\n\tlocal\tcounter_y     : dword\n\tlocal\tremap_counter :dword\n\tlocal\tentry : dword\n\n\n\t;*===================================================================\n\t;* Check for scale error when to or from size 0,0\n\t;*===================================================================\n\tcmp\t[dst_width],0\n\tje\t??all_done\n\tcmp\t[dst_height],0\n\tje\t??all_done\n\tcmp\t[src_width],0\n\tje\t??all_done\n\tcmp\t[src_height],0\n\tje\t??all_done\n\n\tmov\teax , [ src_x ]\n\tmov\tebx , [ src_y ]\n\tmov\t[ src_x0 ] , eax \n\tmov\t[ src_y0 ] , ebx \n\tadd\teax , [ src_width ]\n\tadd\tebx , [ src_height ]\n\tmov\t[ src_x1 ] , eax \n\tmov\t[ src_y1 ] , ebx \n\n\tmov\teax , [ dst_x ]\n\tmov\tebx , [ dst_y ]\n\tmov\t[ dst_x0 ] , eax \n\tmov\t[ dst_y0 ] , ebx \n\tadd\teax , [ dst_width ]\n\tadd\tebx , [ dst_height ]\n\tmov\t[ dst_x1 ] , eax \n\tmov\t[ dst_y1 ] , ebx \n\n; Clip Source Rectangle against source Window boundaries.\n\tmov  \tesi , [ this ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ src_x0 ]\n\tmov\tebx , [ src_x1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\teax , [ src_y0 ]\n\tmov\tebx , [ src_y1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??all_done\n\tor\tal , dl\n\tjz\t??clip_against_dest\n\tmov\tbl , dl\n\ttest\tcl , 1000b\n\tjz\t??src_left_ok\n\txor\teax , eax\n\tmov\t[ src_x0 ] , eax\n\tsub\teax , [ src_x ]\n\timul\t[ dst_width ]\n\tidiv\t[ src_width ]\n\tadd\teax , [ dst_x ]\n\tmov\t[ dst_x0 ] , eax\n\n??src_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??src_bottom_ok\n\txor\teax , eax\n\tmov\t[ src_y0 ] , eax\n\tsub\teax , [ src_y ]\n\timul\t[ dst_height ]\n\tidiv\t[ src_height ]\n\tadd\teax , [ dst_y ]\n\tmov\t[ dst_y0 ] , eax\n\n??src_bottom_ok:\n\ttest\tbl , 0100b\n\tjz\t??src_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ src_x1 ] , eax\n\tsub\teax , [ src_x ]\n\timul\t[ dst_width ]\n\tidiv\t[ src_width ]\n\tadd\teax , [ dst_x ]\n\tmov\t[ dst_x1 ] , eax\n\n??src_right_ok:\n\ttest\tbl , 0001b\n\tjz\t??clip_against_dest\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ src_y1 ] , eax\n\tsub\teax , [ src_y ]\n\timul\t[ dst_height ]\n\tidiv\t[ src_height ]\n\tadd\teax , [ dst_y ] \n\tmov\t[ dst_y1 ] , eax\n\n; Clip destination Rectangle against source Window boundaries.\n??clip_against_dest:\n\tmov  \tesi , [ dest ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ dst_x0 ]\n\tmov\tebx , [ dst_x1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\teax , [ dst_y0 ]\n\tmov\tebx , [ dst_y1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??all_done\n\tor\tal , dl\n\tjz\t??do_scaling\n\tmov\tbl , dl\n\ttest\tcl , 1000b\n\tjz\t??dst_left_ok\n\txor\teax , eax\n\tmov\t[ dst_x0 ] , eax\n\tsub\teax , [ dst_x ]\n\timul\t[ src_width ]\n\tidiv\t[ dst_width ]\n\tadd\teax , [ src_x ]\n\tmov\t[ src_x0 ] , eax\n\n??dst_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dst_bottom_ok\n\txor\teax , eax\n\tmov\t[ dst_y0 ] , eax\n\tsub\teax , [ dst_y ]\n\timul\t[ src_height ]\n\tidiv\t[ dst_height ]\n\tadd\teax , [ src_y ]\n\tmov\t[ src_y0 ] , eax\n\n??dst_bottom_ok:\n\ttest\tbl , 0100b\n\tjz\t??dst_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ dst_x1 ] , eax\n\tsub\teax , [ dst_x ]\n\timul\t[ src_width ]\n\tidiv\t[ dst_width ]\n\tadd\teax , [ src_x ]\n\tmov\t[ src_x1 ] , eax\n\n??dst_right_ok:\n\ttest\tbl , 0001b\n\tjz\t??do_scaling\n\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ dst_y1 ] , eax\n\tsub\teax , [ dst_y ]\n\timul\t[ src_height ]\n\tidiv\t[ dst_height ]\n\tadd\teax , [ src_y ]\n\tmov\t[ src_y1 ] , eax\n\n??do_scaling:\n\n       cld\t\n       mov\tebx , [ this ]\n       mov\tesi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\t[ src_win_width ] , eax\n       mul\t[ src_y0 ]\n       add\tesi , [ src_x0 ]\n       add\tesi , eax\n\n       mov\tebx , [ dest ]\n       mov\tedi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\t[ dst_win_width ] , eax\n       mul\t[ dst_y0 ]\n       add\tedi , [ dst_x0 ]\n       add\tedi , eax\n       call\tVesa_Asm_Set_Win\t\t\t; set the window\n\n       mov\teax , [ src_height ]\n       xor\tedx , edx\n       mov\tebx , [ dst_height ]\n       idiv\t[ dst_height ]\n       imul\teax , [ src_win_width ]\n       neg\tebx\n       mov\t[ dy_intr ] , eax\n       mov\t[ dy_frac ] , edx\n       mov\t[ dy_acc ]  , ebx\n\n       mov\teax , [ src_width ]\n       xor\tedx , edx\n       shl\teax , 16\n       idiv\t[ dst_width ]\n       xor\tedx , edx\n       shld\tedx , eax , 16\n       shl\teax , 16\n\n       mov\tecx , [ dst_y1 ]\n       mov\tebx , [ dst_x1 ]\n       sub\tecx , [ dst_y0 ]\n       jz\t??all_done\n       sub\tebx , [ dst_x0 ]\n       jz\t??all_done\n\n       mov\t[ counter_y ] , ecx\n       mov\t[ scan_line ] , ebx\n\n       cmp\t[ trans ] , 0\n       jnz\t??transparency\n\n       cmp\t[ remap ] , 0\n       jnz\t??normal_remap\n\n; *************************************************************************\n; normal scale\n       mov\tecx , ebx\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 2 ]\n       shr\tebx , 5\n       neg\tecx\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??ref_point + ecx + ecx * 2 ]\n       mov\t[ entry ] , ecx\n\n ??outter_loop:\n       mov\tebx , [ scan_line ]\n       push\tesi\n       add\tebx , edi \n       xor\tecx , ecx\n       add\tebx , [ cpu_video_page ]\n       push\tedi\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??in_range\n       mov\tebx , [ scan_line ]\n       jmp      ??trailing_entry \n  ??trailing_bytes: \n       mov\tcl , [ esi ]\n       add\tecx , eax\n       adc\tesi , edx\n       mov\t[ edi ] , cl\n       inc\tedi\n       dec\tebx\n  ??trailing_entry: \n       cmp\tedi , 0b0000h\n       jl\t??trailing_bytes\n       add\tedi , [ cpu_video_page ]\n       call\tVesa_Asm_Set_Win\t\t\t; set the window\n??end_of_scanline:\n       mov\tcl , [ esi ]\n       add\tecx , eax\n       adc\tesi , edx\n       mov\t[ edi ] , cl\n       inc\tedi\n       dec\tebx\n       jg\t??end_of_scanline\n       sub\t[ dword ptr esp ] , 010000h\n       jmp\t??next_line\n\n??in_range:\n       mov\tebx , [ counter_x ]\n       jmp\t[ entry ]\n ??inner_loop:\n       REPT\t32\t\n\t       mov\tcl , [ esi ]\n\t       add\tecx , eax\n\t       adc\tesi , edx\n\t       mov\t[ edi ] , cl\n\t       inc\tedi\n       ENDM\n ??ref_point:\n       dec\tebx\n       jge\t??inner_loop\n  ??next_line:\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??skip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??skip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??outter_loop\n\tret\n\n\n; *************************************************************************\n; normal scale with remap\n\n??normal_remap:\t\n       mov\tecx , ebx\n       mov\t[ dx_frac ] , eax\n       mov\t[ dx_intr ] , edx\n\n       and\tecx , 01fh\n       mov\teax , [ remap ]\n       shr\tebx , 5\n       imul\tecx , - 13\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??remapref_point + ecx ]\n       mov\t[ entry ] , ecx\n\n ??remapoutter_loop:\n       mov\tebx , [ scan_line ]\n       push\tesi\n       add\tebx , edi \n       xor\tecx , ecx\n       add\tebx , [ cpu_video_page ]\n       push\tedi\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??remap_in_range\n       mov\tedx , [ scan_line ]\n       xor\tebx , ebx\n       jmp    ??remap_trailing_entry \n ??remap_trailing_bytes: \n       mov\tbl , [ esi ]\n       add\tecx , [ dx_frac ]\n       adc\tesi , [ dx_intr ]\n       mov\tcl , [ eax + ebx ]\n       mov\t[ edi ] , cl\n       inc\tedi\n       dec\tedx\n ??remap_trailing_entry:\n       cmp\tedi , 0b0000h\n       jl\t??remap_trailing_bytes\n??remap_no_trailing:  \n       add\tedi , [ cpu_video_page ]\n       call\tVesa_Asm_Set_Win\t\t\t; set the window\n??remap_end_of_scanline:\n       mov\tbl , [ esi ]\n       add\tecx , [ dx_frac ]\n       adc\tesi , [ dx_intr ]\n       mov\tcl , [ eax + ebx ] \n       mov\t[ edi ] , cl\n       inc\tedi\n       dec\tedx\n       jg\t??remap_end_of_scanline\n       sub\t[ dword ptr esp ] , 010000h\n       jmp\t??remap_next_line\n??remap_in_range:\n       mov\tebx , [ counter_x ]\n       push\tesi\n       mov\t[ remap_counter ] , ebx\n       push\tedi\n       mov\tedx , [ dx_intr ]\n       xor\tecx , ecx\n       xor\tebx , ebx\n       jmp\t[ entry ]\n ??remapinner_loop:\n       REPT\t32\t\n\t       mov\tbl , [ esi ]\n\t       add\tecx , [ dx_frac ]\n\t       adc\tesi , edx\n\t       mov\tcl , [ eax + ebx ]\n\t       mov\t[ edi ] , cl\n\t       inc\tedi\n       ENDM\n ??remapref_point:\n       dec\t[ remap_counter ] \n       jge\t??remapinner_loop\n ??remap_next_line:\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??remapskip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??remapskip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??remapoutter_loop\n\tret\n\n\n;****************************************************************************\n; scale with transparency\n\n??transparency:\n       cmp\t[ remap ] , 0\n       jnz\t??trans_remap\n\n; *************************************************************************\n; normal scale with transparency\n       mov\tecx , ebx\n       and\tecx , 01fh\n       imul\tecx , -13\n       shr\tebx , 5\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??tr_ref_point + ecx ]\n       mov\t[ entry ] , ecx\n\n ??tr_outter_loop:\n       mov\tebx , [ scan_line ]\n       push\tesi\n       add\tebx , edi \n       xor\tecx , ecx\n       add\tebx , [ cpu_video_page ]\n       push\tedi\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??tr_in_range\n\n       mov\tebx , [ scan_line ]\n       jmp     ??tr_trailing_entry \n  ??tr_trailing_bytes: \n       mov\tcl , [ esi ]\n       test\tcl , cl\n       jz\t??tr_skip\n      mov\t[ edi ] , cl\n   ??tr_skip:\n       add\tecx , eax\n       adc\tesi , edx\n       inc\tedi\n       dec\tebx\n  ??tr_trailing_entry: \n       cmp\tedi , 0b0000h\n       jl\t??tr_trailing_bytes\n       add\tedi , [ cpu_video_page ]\n       call\tVesa_Asm_Set_Win\t\t\t; set the window\n??tr_end_of_scanline:\n       mov\tcl , [ esi ]\n       test\tcl , cl\n       jz\t??tr_skip1\n       mov\t[ edi ] , cl\n   ??tr_skip1:\n       add\tecx , eax\n       adc\tesi , edx\n       inc\tedi\n       dec\tebx\n       jg\t??tr_end_of_scanline\n       sub\t[ dword ptr esp ] , 010000h\n       jmp\t??tr_next_line\n\n??tr_in_range:\n       mov\tebx , [ counter_x ]\n       jmp\t[ entry ]\n ??tr_inner_loop:\n       REPT\t32\t\n       local\tskip\n\t       mov\tcl , [ esi ]\n\t       test\tcl , cl\n\t       jz\tskip\n\t       mov\t[ edi ] , cl\n\t    skip:\n\t       add\tecx , eax\n\t       adc\tesi , edx\n\t       inc\tedi\n       ENDM\n ??tr_ref_point:\n       dec\tebx\n       jge\t??tr_inner_loop\n  ??tr_next_line:\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??tr_skip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??tr_skip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??tr_outter_loop\n\tret\n\n\n\n; *************************************************************************\n; normal scale with remap and transparency\n\n??trans_remap:\t\n       mov\tecx , ebx\n       mov\t[ dx_frac ], eax\n       mov\t[ dx_intr ] , edx\n\n       and\tecx , 01fh\n       mov\teax , [ remap ]\n       shr\tebx , 5\n       imul\tecx , - 17\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??trans_remapref_point + ecx ]\n       mov\t[ entry ] , ecx\n\n ??trans_remapoutter_loop:\n       mov\tebx , [ scan_line ]\n       push\tesi\n       add\tebx , edi \n       xor\tecx , ecx\n       add\tebx , [ cpu_video_page ]\n       push\tedi\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??trans_remap_in_range\n       mov\tedx , [ scan_line ]\n       xor\tebx , ebx\n       jmp    ??trans_remap_trailing_bytes1 \n  ??trans_remap_trailing_bytes: \n       mov\tbl , [ esi ]\n       test\tbl , bl\n       jz\t??trans_remp\n       mov\tcl , [ eax + ebx ]\n       mov\t[ edi ] , cl\n    ??trans_remp:\n       add\tecx , [ dx_frac ]\n       adc\tesi , [ dx_intr ]\n       inc\tedi\n       dec\tedx\n  ??trans_remap_trailing_bytes1: \n       cmp\tedi , 0b0000h\n       jl\t??trans_remap_trailing_bytes\n??trans_remap_no_trailing:  \n       add\tedi , [ cpu_video_page ]\n       call\tVesa_Asm_Set_Win\t\t\t; set the window\n??trans_remap_end_of_scanline:\n       mov\tbl , [ esi ]\n       test\tbl , bl\n       jz\t??trans_remp1\n       mov\tcl , [ eax + ebx ]\n       mov\t[ edi ] , cl\n   ??trans_remp1:\n       add\tecx , [ dx_frac ]\n       adc\tesi , [ dx_intr ]\n       inc\tedi\n       dec\tedx\n       jg\t??trans_remap_end_of_scanline\n       sub\t[ dword ptr esp ] , 010000h\n       jmp\t??trans_remap_next_line\n\n??trans_remap_in_range:\n       mov\tebx , [ counter_x ]\n       push\tesi\n       mov\t[ remap_counter ] , ebx\n       push\tedi\n       mov\tedx , [ dx_intr ]\n       xor\tecx , ecx\n       xor\tebx , ebx\n       jmp\t[ entry ]\n ??trans_remapinner_loop:\n       REPT\t32\t\n       local\tskip\n\t       mov\tbl , [ esi ]\n\t       test\tbl , bl\n\t       jz\tskip\n\t       mov\tcl , [ eax + ebx ]\n\t       mov\t[ edi ] , cl\n\t  skip:\n\n\t       add\tecx , [ dx_frac ]\n\t       adc\tesi , edx\n\t       inc\tedi\n       ENDM\n ??trans_remapref_point:\n       dec\t[ remap_counter ] \n       jge\t??trans_remapinner_loop\n ??trans_remap_next_line:\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??trans_remapskip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??trans_remapskip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??trans_remapoutter_loop\n\tret\n\n??all_done:\n\tret\n\n\tENDP\tLinear_Scale_To_Vesa\n\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VTOBUFF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TOBUFFER.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : June 15, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVC::TOBUFFER -- Copies a virtual viewport to a linear buffer         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\n\nTRANSP equ 0\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\nCODESEG\n\n\n;***************************************************************************\n;* VIVC::TOBUFFER -- Copies a virtual viewport to a linear buffer          *\n;*                                                                         *\n;* INPUT:\tBYTE *\tdest\t\t- buffer to copy to\t\t   *\n;*\t\t\tsize\t\t- size of the buffer to copy to\t   *\n;*\t\t\tx_pixel\t\t- x pixel on viewport to copy from *\n;*\t\t\ty_pixel \t- y pixel on viewport to copy from *\n;*\t\t\tpixel_width\t- the width of copy region\t   *\n;*\t\t\tpixel_height\t- the height of copy region\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    Coordinates and dimensions will be adjusted if they exceed *\n;*\t        the boundaries.  In the event that no adjustment is \t   *\n;*\t        possible this routine will abort.  If the size of the \t   *\n;*\t\tregion to copy exceeds the size passed in for the buffer   *\n;*\t\tthe routine will automatically abort.\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_To_Buffer C near \n\tUSES\tebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tthis:DWORD\t\t; this is a class member function\n\tARG\tx_pixel:DWORD\t\t; Page X pixel coordinate.\n\tARG\ty_pixel:DWORD\t\t; Page Y pixel coordinate.\n\tARG\tpixel_width:DWORD\t; Width of region in pixels.\n\tARG\tpixel_height:DWORD\t; Height of region in pixels.\n\tARG\tdest:DWORD\t\t; the buffer to copy to\n\tARG\tsize:DWORD\t\t; the size of the buffer\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tLOCAL\tdest_x1 : dword\n\tLOCAL\tdest_y1 : dword\n\tLOCAL\tdest_ajust_width:DWORD\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_area   :  dword\n\n; Clip dest Rectangle against source Window boundaries.\n\tmov\t[ dest_x1 ] , 0\n\tmov\t[ dest_y1 ] , 0\n\n\tmov  \tesi , [ this ]\t    ; get ptr to dest\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_blit\n\t\t\t    \n\ttest\tcl , 1000b\n\tjz\t??scr_left_ok\n\tmov\teax , [ x_pixel ] \n\tneg\teax\n\tmov\t[ x_pixel ] , 0\n\tmov\t[ dest_x1 ] , eax\n\n??scr_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??scr_bottom_ok\n \tmov\teax , [ y_pixel ] \n\tneg\teax\n\tmov\t[ y_pixel ] , 0\n\tmov\t[ dest_y1 ] , eax\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n??do_blit:\n\n       cld\t\n\n       mov\teax , [ (VideoViewPort esi) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort esi) . VIVPWidth ]\n       mov\tedi , [ (VideoViewPort esi) . VIVPOffset ]\n\n       mov\tecx , eax\n       mul\t[ y_pixel ]\n       add\tedi , [ x_pixel ]\n       add\tedi , eax\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n       mov\tesi , edi\n\n       add\tecx , [ x_pixel ]\n       sub\tecx , [ x1_pixel ]\n       mov\t[ scr_ajust_width ] , ecx\n\n       mov\tedi , [ dest ]\n       mov\teax , [ pixel_width ]\n       sub\teax , [ x1_pixel ]\n       add\teax , [ x_pixel ]\n       mov\t[ dest_ajust_width ] , eax\n\n       mov\teax , [ dest_y1 ]\n       mul \t[ pixel_width ]\n       add\teax , [ dest_x1 ]\n       add\tedi , eax\n\n       mov\tedx , [ y1_pixel ]\n       sub\tedx , [ y_pixel ]\n       jz\t??real_out\n\n       mov\teax , [ x1_pixel ]\n       sub\teax , [ x_pixel ]\n       jz\t??real_out\n\n       mov\tebx , [ pixel_width ]\n       imul\tebx , edx\n       cmp\tebx , [ size ]\n       jg\t??real_out\t\t\n\n\n; ********************************************************************       \n; Forward bitblit only\n\nIF  TRANSP\n       test\t[ trans ] , 1\n       jnz\t??forward_Blit_trans\nENDIF\n\n\n; the inner loop is so efficient that \n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10        \n       jl\t??forward_loop_bytes\n\n??forward_loop_dword:\n\n       lea\tebx , [ esi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??in_range\n\n       xor\tecx , ecx\n       cmp\tesi , 0b0000h\n       mov\tebx , eax\n       jge\t??no_trailing\n       mov\tecx , 0b0000h\n       sub\tecx , esi \n       sub\tebx , ecx\n       rep\tmovsb\n??no_trailing:  \n       add\tesi , [ cpu_video_page ]\n       xchg\tedi , esi\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n       xchg\tedi , esi\n\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_dword\n       ret\n\n??in_range:\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_dword\n       ret\n\n??forward_loop_bytes:\n       lea\tebx , [ esi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       mov\tebx , eax\n       jl\t??in_range_bytes\n\n       xor\tecx , ecx\n       cmp\tesi , 0b0000h\n       jge\t??no_trailing_bytes\n       mov\tecx , 0b0000h\n       sub\tecx , esi \n       sub\tebx , ecx\n       rep\tmovsb\n??no_trailing_bytes:  \n       add\tesi , [ cpu_video_page ]\n       xchg\tedi , esi\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n       xchg\tedi , esi\n??in_range_bytes:\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_bytes\n       ret\n\n\n\nIF  TRANSP\n\n\n??forward_Blit_trans:\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\t\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n??forward_loop_trans:\n       mov\tecx , eax \n       jmp\t[ y1_pixel ]\n??forward_trans_line:\n       REPT\t32\t\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tesi\n\t    \tinc\tedi\n\tENDM\n    ??transp_reference:\n       dec\tecx \n       jge\t??forward_trans_line\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_trans\n       ret\nENDIF\n\n??real_out:\n       ret\n\nENDP\tVesa_To_Buffer\nEND\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VTOPAGE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TOPAGE.ASM                               *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : December 9, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Buffer_To_Page(GVC) -- Copies a linear buffer to a graphic viewport   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nTRANSP\tequ  0\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\nCODESEG\n\n;***************************************************************************\n;* VVC::TOPAGE -- Copies a linear buffer to a virtual viewport\t\t   *\n;*                                                                         *\n;* INPUT:\tWORD\tx_pixel\t\t- x pixel on viewport to copy from *\n;*\t\tWORD\ty_pixel \t- y pixel on viewport to copy from *\n;*\t\tWORD\tpixel_width\t- the width of copy region\t   *\n;*\t\tWORD\tpixel_height\t- the height of copy region\t   *\n;*\t\tBYTE *\tsrc\t\t- buffer to copy from\t\t   *\n;*\t\tVVPC *  dest\t\t- virtual viewport to copy to\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    Coordinates and dimensions will be adjusted if they exceed *\n;*\t        the boundaries.  In the event that no adjustment is \t   *\n;*\t        possible this routine will abort.  If the size of the \t   *\n;*\t\tregion to copy exceeds the size passed in for the buffer   *\n;*\t\tthe routine will automatically abort.\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/15/1994 PWG : Created.                                             *\n;*   12/09/1994 PWG : Made SVGA Modifications                              *\n;*=========================================================================*\n\tPROC\tVesa_Buffer_To_Page C near \n\tUSES\tebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\tARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\tARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\tARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\tARG    \tsrc         :DWORD\t\t; this is a member function\n\tARG\tdest        :DWORD\t\t; what are we blitting to\n\n;\tARG\ttrans       :DWORD\t\t\t; do we deal with transparents?\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tLOCAL\tscr_x1 : dword\n\tLOCAL\tscr_y1 : dword\n\tLOCAL\tdest_ajust_width:DWORD\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_area   :  dword\n\n\tcmp\t[ src ] , 0\n\tjz\t??real_out\n\n\n; Clip dest Rectangle against source Window boundaries.\n\n\tmov\t[ scr_x1 ] , 0 \n\tmov\t[ scr_y1 ] , 0 \n\tmov  \tesi , [ dest ]\t    ; get ptr to dest\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_blit\n\n\ttest\tcl , 1000b\n\tjz\t??dest_left_ok\n\tmov\teax , [ x_pixel ]\n\tneg\teax \n\tmov\t[ x_pixel ] , 0\n\tmov\t[ scr_x1 ] , eax\n\n??dest_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dest_bottom_ok\n\tmov\teax , [ y_pixel ]\n\tneg\teax \n\tmov\t[ y_pixel ] , 0\n\tmov\t[ scr_y1 ] , eax\n\n??dest_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??dest_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??dest_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n??do_blit:\n\n       cld\t\n\n       mov\teax , [ (VideoViewPort esi) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort esi) . VIVPWidth ]\n       mov\tedi , [ (VideoViewPort esi) . VIVPOffset ]\n\n       mov\tecx , eax\n       mul\t[ y_pixel ]\n       add\tedi , [ x_pixel ]\n       add\tedi , eax\n       call\tVesa_Asm_Set_Win\t\t\t; set the window\n\n\n       add\tecx , [ x_pixel ]\n       sub\tecx , [ x1_pixel ]\n       mov\t[ dest_ajust_width ] , ecx\n\n\n       mov\tesi , [ src ]\n       mov\teax , [ pixel_width ]\n       sub\teax , [ x1_pixel ]\n       add\teax , [ x_pixel ]\n       mov\t[ scr_ajust_width ] , eax\n\n       mov\teax , [ scr_y1 ]\n       mul \t[ pixel_width ]\n       add\teax , [ scr_x1 ]\n       add\tesi , eax\n\n\n       mov\tedx , [ y1_pixel ]\n       sub\tedx , [ y_pixel ]\n       jz\t??real_out\n\n       mov\teax , [ x1_pixel ]\n       sub\teax , [ x_pixel ]\n       jz\t??real_out\n\n\n; ********************************************************************       \n; Forward bitblit only\n\nIF TRANSP\n       test\t[ trans ] , 1\n       jnz\t??forward_Blit_trans\nENDIF\n\n\n; the inner loop is so efficient that \n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10        \n       jl\t??forward_loop_bytes\n\n??forward_loop_dword:\n\n       lea\tebx , [ edi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??in_range\n\n       xor\tecx , ecx\n       mov\tebx , eax\n       cmp\tedi , 0b0000h\n       jge\t??no_trailing\n       mov\tecx , 0b0000h\n       sub\tecx , edi \n       sub\tebx , ecx\n       rep\tmovsb\n??no_trailing:  \n       add\tedi , [ cpu_video_page ]\n       call\tVesa_Asm_Set_Win\t\t\t; set the window\n\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_dword\n       ret\n\n??in_range:\n\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_dword\n       ret\n\n??forward_loop_bytes:\n       lea\tebx , [ edi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       mov\tebx , eax\n       jl\t??in_range_bytes\n\n       xor\tecx , ecx\n       cmp\tedi , 0b0000h\n       jge\t??no_trailing_bytes\n       mov\tecx , 0b0000h\n       sub\tecx , edi \n       sub\tebx , ecx\n       rep\tmovsb\n??no_trailing_bytes:  \n       add\tedi , [ cpu_video_page ]\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n??in_range_bytes:\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_bytes\n       ret\n\nIF  TRANSP\n\n\n??forward_Blit_trans:\n\n\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\t\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n\n??forward_loop_trans:\n       mov\tecx , eax \n       jmp\t[ y1_pixel ]\n??forward_trans_line:\n       REPT\t32\t\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tesi\n\t    \tinc\tedi\n\tENDM\n    ??transp_reference:\n       dec\tecx \n       jge\t??forward_trans_line\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_trans\n       ret\nENDIF\n\n??real_out:\n       ret\n\n\n\tENDP\tVesa_Buffer_To_Page\nEND\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VTXTPRNT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TXTPRNT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 17, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 17, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VESA_Print -- Assembly VESA text print routine                        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n;*=========================================================================*\n;* Extern the font pointer which is defined by the font class\t\t   *\n;*=========================================================================*\n\tGLOBAL\tFontPtr:DWORD\n\tGLOBAL\tColorXlat:BYTE\n\n;*=========================================================================*\n;* Define the necessary equates for structures and bounds checking\t   *\n;*=========================================================================*\n; The header of the font file looks like this:\n; \tUWORD\tFontLength;\t\t0\n; \tBYTE\tFontCompress;\t\t2\n;\tBYTE\tFontDataBlocks;\t\t3\n;\tUWORD\tInfoBlockOffset;\t4\n;\tUWORD\tOffsetBlockOffset;\t6\n;\tUWORD\tWidthBlockOffset;\t8\n;\tUWORD\tDataBlockOffset;\t10\n;\tUWORD\tHeightOffset;\t\t12\n; For this reason the following equates have these values:\nFONTINFOBLOCK\t\tEQU\t4\nFONTOFFSETBLOCK\t\tEQU\t6\nFONTWIDTHBLOCK\t\tEQU\t8\nFONTDATABLOCK\t\tEQU\t10\nFONTHEIGHTBLOCK\t\tEQU\t12\n\nFONTINFOMAXHEIGHT\tEQU\t4\nFONTINFOMAXWIDTH\tEQU\t5\n\n\nLOCALS ??\n;*=========================================================================*\n;* Define the color xlate table in the data segment\t\t\t   *\n;*=========================================================================*\n\n\tCODESEG\n\n\n;***************************************************************************\n;* VESA_PRINT -- Assembly VESA text print routine                          *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/17/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_Print C near\n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\tthis:DWORD\n\tARG\tstring:DWORD\t \n\tARG\tx_pixel:DWORD\n\tARG\ty_pixel:DWORD\n\tARG\tfcolor:DWORD\n\tARG\tbcolor:DWORD\n\t\t\n\tLOCAL\tinfoblock:DWORD\t\t; pointer to info block\n\tLOCAL\toffsetblock:DWORD\t; pointer to offset block  (UWORD *)\n\tLOCAL\twidthblock:DWORD\t; pointer to width block   (BYTE  *)\n\tLOCAL\theightblock:DWORD\t; pointer to height block  (UWORD *)\n\n\tLOCAL\tcurline:DWORD\t\t; pointer to first column of current row.\n\tlocal\tptr_string:dword\t; pointer to string\n\tLOCAL\tbufferwidth:DWORD    \t; width of buffer (vpwidth + Xadd)\n\tLOCAL\tnextdraw:DWORD\t\t; bufferwidth - width of cur character.\n\tLOCAL\tstartdraw:DWORD\t\t; where next character will start being drawn.\n\n\tLOCAL\tchar:DWORD\t\t; current character value.\t\n\n\tLOCAL\tmaxheight:BYTE\t\t; max height of characters in font.\n\tLOCAL\tbottomblank:BYTE\t; amount of empty space below current character.\n\tLOCAL\tcharheight:BYTE\t\t; true height of current character.\n\tLOCAL\tvpwidth:DWORD\n\tLOCAL\tvpheight:DWORD\n\tLOCAL\tremainder:DWORD\n\tLOCAL\tfullwidth:DWORD\n\tLOCAL\tcurrwidth:DWORD\n\n\n;-------------------------------- Where to draw -----------------------------------------------\n\t; Set up memory location to start drawing.\n\tmov  \tebx,[this]\t\t\t\t; get a pointer to dest\n\tmov\teax,[(GraphicViewPort ebx).GVPHeight]\t; get height of viewport\n\tmov\t[vpheight],eax\t\t\t\t; save off height of viewport\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\t; get width of viewport\n\tmov\t[vpwidth],eax\t\t\t\t; save it off for later\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\t; add in xadd for bytes_per_line\n\tmov\t[bufferwidth],eax     \t\t\t; save it off for later use.\n\n\tmul\t[y_pixel]\t\t\t\t; multiply rowsize * y_pixel start.\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get start of the viewport\n\tadd\tedi,eax\t\t\t\t\t; add y position to start of vp \n\tmov\t[curline],edi\t\t\t\t; save 0,y address for line feed stuff.\n\tadd\tedi,[x_pixel]\t\t\t\t; add to get starting column in starting row.\n\n\tmov\t[startdraw],edi\t\t\t\t; save it off.\n\n\n;-------------------------------- Create block pointers ----------------------------------------\n\t; Get the pointer to the font.\n\t; We could check for NULL but why waste the time.\n\t; It is up to programmer to make sure it is set.\n\tmov\tesi,[FontPtr]\t\t; Get the font pointer\n\tor\tesi,esi\n\tjz\t??done\n\n\t; Set up some pointers to the different memory blocks.\n\t; esi (FontPtr) is added to each to get the true address of each block.\n\t; Many registers are used for P5 optimizations.\n\t; ebx is used for InfoBlock which is then used in the next section.\n\tmovzx\teax,[WORD PTR esi+FONTOFFSETBLOCK]\t; get offset to offset block\n\tmovzx\tebx,[WORD PTR esi+FONTINFOBLOCK]      \t; get offset to info block (must be ebx for height test)\n\tmovzx\tecx,[WORD PTR esi+FONTWIDTHBLOCK] \t; get offset to width block\n\tmovzx\tedx,[WORD PTR esi+FONTHEIGHTBLOCK]\t; get offset to height block\n\n\tadd\teax,esi\t\t\t\t; add offset of FontPtr to offset block  \n\tadd\tebx,esi\t\t\t\t; add offset of FontPtr to info block \n\tadd\tecx,esi\t\t\t\t; add offset of FontPtr to width block\n\tadd\tedx,esi\t\t\t\t; add offset of FontPtr to height block\n\n\tmov\t[offsetblock],eax\t\t; save offset to offset block\n\tmov\t[infoblock],ebx\t\t\t; save offset to info block\n\tmov\t[widthblock],ecx   \t\t; save offset to width block\n\tmov\t[heightblock],edx\t\t; save offset to height block\n\n;------------------------------------------ Test for fit ----------------------------------------------\n\t; Test to make sure the height of the max character will fit on this line\n\t; and and not fall out of the viewport.\n\t; remember we set ebx to FONTINFOBLOCK above.\n\tmovzx\teax,[BYTE PTR ebx + FONTINFOMAXHEIGHT]; get the max height in font.\n\tmov\t[maxheight],al\t\t\t; save it for later use.\n\tadd\teax,[y_pixel]\t\t\t; add current y_value.\n\tcmp\teax,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??done\t\t\t; if so, we're outa here.\n\n\tmov\t[y_pixel],eax\t\t\t; save for next line feed. y value for next line.\n\n\tcld\t\t\t\t\t; Make sure we are always forward copying.\n\n;------------------------ Set palette foreground and background ----------------------------------\n\tmov\teax,[fcolor]\t\t; foreground color\n\tmov\t[ColorXlat+1],al\n\tmov\t[ColorXlat+16],al\n\n\tmov\teax,[bcolor]\t\t; background color\n\tmov\t[ColorXlat],al\n\n;-------------------------------------------------------------------------------------------------\n;----------------------------------------- Main loop ----------------------------------------------\n\t; Now we go into the main loop of reading each character in the string and doing\n\t; something with it.\n??next_char:\n\t; while (*string++)\n\txor\teax,eax\t\t\t\t; zero out since we will just load al.\t\n\tmov\tesi,[string]\t\t\t; get address on next character.\t\n\tlodsb\t\t\t\t\t; load the character into al.\n\ttest\teax,0FFH\t\t\t; test to see if character is a NULL\n\tjz\t??done\t\t\t\t; character is NULL, get outa here.\n\tmov\tedi,[startdraw]\t\t\t; Load the starting address.\n\n\tmov\t[string],esi\t\t\t; save index into string. (incremented by lodsb)\t\n\n\tcmp\teax,10\t\t\t\t; is the character a line feed?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\t\n\tcmp\teax,13\t\t\t\t; is the character a line feed?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\n\tmov\t[char],eax\t\t\t; save the character off for later reference.\n\tmov\tebx,eax\t\t\t\t; save it in ebx for later use also.\n\n\tadd\teax,[widthblock]\t\t; figure address of width of character.\n\tmov\tecx,[x_pixel]\t\t\t; get current x_pixel.\n\tmovzx\tedx,[BYTE PTR eax]\t \t; get the width of the character in dl.\n\tadd\tecx,edx\t\t\t\t; add width of char to current x_pixel.\n\tadd\t[startdraw],edx\t\t\t; save start draw for next character.\n\n\tcmp\tecx,[vpwidth]\t\t\t; is the pixel greater then the vp width?\n\tjg\t??force_line_feed\t\t; if so, force a line feed.\n\n\tmov\t[x_pixel],ecx\t\t\t; save value of start of next character.\n\tmov\tecx,[bufferwidth]\t\t; get amount to next y same x (one row down)\n\tsub\tecx,edx\t\t\t\t; take the current width off.\n\tmov\t[nextdraw],ecx\t\t\t; save it to add to edi when done with a row.\n\n\t; At this point we got the character. It is now time to find out specifics\n\t; about drawing the darn thing.\n\t; ebx = char so they can be used as an indexes.\n\t; edx = width of character for loop later.\n\n\t; get offset of data for character into esi.\n\tshl\tebx,1\t\t\t\t; mult by 2 to later use as a WORD index.\n\tmov\tesi,[offsetblock]\t\t; get pointer to begining of offset block.\n\tadd\tesi,ebx\t\t\t\t; index into offset block.\t\n\tmovzx\tesi,[WORD PTR esi]\t\t; get true offset into data block from FontPtr.\n\tadd\tesi,[FontPtr]\t\t\t; Now add FontPtr address to get true address.\n\n\t; Get top and bottom blank sizes and the true height of the character.\n\tadd\tebx,[heightblock]\t\t; point ebx to element in height array.\n\tmov\tal,[ebx+1]\t\t\t; load the data height into dl.\n\tmov\tcl,[ebx]\t\t\t; load the first data row into cl.\n\tmov\tbl,[maxheight]\t\t\t; get the max height of characters.\n\tmov\t[charheight],al\t\t\t; get number of rows with data.\n\tadd\tal,cl\t\t\t\t; add the two heights.\n\tsub\tbl,al\t\t\t\t; subract topblank + char height from maxheight.\n\tmov\t[bottomblank],bl\t\t; save off the number of blank rows on the bottom.\n\t; leaving this section:\n\t; dl is still the width of the character.\n\t; cl is the height of the top blank area.\n\n\tmov\tebx,OFFSET ColorXlat\t\t; setup ebx for xlat commands.\n\tmov\tdh,dl\t\t\t\t; save the width of the character to restore each loop.\n\tcall\tVesa_Asm_Set_Win\t\t; adjust edi & vesa page\n\n\tcmp\tcl,0\t\t\t\t; is there any blank rows on top?\n\tjz\t??draw_char\t\t\t; if not go and draw the real character.\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjnz\t??loop_top\t\t\t; if not go and write the color\n\n;----------------------------------------- skip Top blank area ----------------------------------------\n\t; this case, the top is transparrent, but we need to increase our dest pointer to correct row.\n\tmovzx\teax,cl\t\t\t\t; get number of rows into eax;\n\tmov\tecx,edx\t\t\t\t; save width since edx will be destroyed by mul.\n\tmul\t[bufferwidth]\t\t\t; multiply that by the width of the buffer.\n\tmov\tedx,ecx\t\t\t\t; restore the width\n\tadd\tedi,eax\t\t\t\t; update the pointer.\t\n\tcmp\tedi,0b0000h\t\t\t; have we gone over win edge\n\tjl\t??draw_char\t\t\t; if not keep writing to window\n        add\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\t\t; instead switch to next window\n\tjmp\tshort ??draw_char\t\t; now go draw the character.\n\n;----------------------------------------- fill Top blank area ----------------------------------------\n\n??loop_top:\n\tstosb\t\t\t\t\t; store the value\n\tcmp\tedi,0b0000h\t\t\t; have we gone over win edge\n\tjl\t??top_no_window_change\t\t; if not keep writing to window\n        add\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\t\t; instead switch to next window\n??top_no_window_change:\n\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_top\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\tcmp\tedi,0b0000h\t\t\t; have we gone over win edge\n\tjl\t??top2_no_window_change\t; if not keep writing to window\n        add\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\t\t; instead switch to next window\n\n??top2_no_window_change:\n\n\tdec\tcl\t\t\t\t; decrement or row count\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tjz\t??draw_char\t\t\t; we are done here, go draw the character.\n\tjmp\tshort ??loop_top\t\t; go back to top of loop.\n;----------------------------------------- Draw character ----------------------------------------------\n??draw_char:\n\tmovzx\tecx,[charheight]\t\t; get the height of character to count down rows.\n\ttest\tecx,ecx\t\t\t\t; is there any data? (blank would not have any)\n\tjz\t??next_char\t\t\t; if no data, go on to next character.\t\n\n\n??while_data:\n\tlodsb\t\t\t\t\t; get byte value from font data\n\tmov\tah,al\t\t\t\t; save hinibble\n\tand\teax,0F00FH\t       \t\t; mask of low nibble in al hi nibble in ah.\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiplo\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiplo:\n\tinc\tedi\n\tcmp\tedi,0b0000h\t\t\t; have we gone over win edge\n\tjl\t??lo_no_window_change\t\t; if not keep writing to window\n        add\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\t\t; instead switch to next window\n??lo_no_window_change:\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjz\tshort ??nextrow\t\t\t; check if done with width of char\n\n\tmov\tal,ah\t\t\t\t; restore to get\n\t; test the time difference between looking up in a large table when shr al,4 is not done as\n\t; compared to using only a 16 byte table when using the shr al,4\n\t;shr\tal,4\t\t\t\t; shift the hi nibble down to low nibble\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiphi\t\t\t; skip over write\n\tmov\t[edi],al\t\t\t; write it out\n??skiphi:\n\tinc\tedi\n\tcmp\tedi,0b0000h\t\t\t; have we gone over win edge\n\tjl\t??hi_no_window_change\t\t; if not keep writing to window\n        add\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\t\t; instead switch to next window\n??hi_no_window_change:\n\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\tshort ??while_data\t\t; check if done with width of char\n\n??nextrow:\n\tadd\tedi,[nextdraw]\t\t\t; go to next line.\n\tcmp\tedi,0b0000h\t\t\t; have we gone over win edge\n\tjl\t??next_row_no_window_change\t; if not keep writing to window\n        add\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\t\t; instead switch to next window\n??next_row_no_window_change:\n\tdec\tecx\t\t\t\t; decrement the number of rows to go\n\tmov\tdh,dl\t\t\t\t; restore our column count for row.\n\tjnz\t??while_data\t\t\t; more data for character.\n\n\t; Now it is time to setup for clearing out the bottom of the character.\n\tmovzx\tecx,[bottomblank]\t\t; get amount on bottom that is blank\n\tcmp\tecx,0\t\t\t\t; if there is no blank bottom...\n\tjz\t??next_char\t\t\t; then skip to go to next character\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjz\t??next_char\t\t\t; skip the top black section to let the background through\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\n;----------------------------------------- Blank below character -----------------------------------\n??loop_bottom:\n\tstosb\t\t\t\t\t; store the value\n\tcmp\tedi,0b0000h\t\t\t; have we gone over win edge\n\tjl\t??bottom_no_window_change\t; if not keep writing to window\n        add\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\t\t; instead switch to next window\n??bottom_no_window_change:\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_bottom\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\tcmp\tedi,0b0000h\t\t\t; have we gone over win edge\n\tjl\t??bottom2_no_window_change\t; if not keep writing to window\n        add\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\t\t; instead switch to next window\n??bottom2_no_window_change:\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tdec\tcl\t\t\t\t; decrement or row count\n\tjz\t??next_char\t\t\t; we are done here, go to the next character.\n\tjmp\tshort ??loop_bottom\t\t; go back to top of loop.\n\n;----------------------------------- end of next_char (main) loop ------------------------------------\n;-------------------------------------------------------------------------------------------------\n\n;----------------------------------- special case line feeds ----------------------------------------\n; JRJ 05/01/95 This is the problem However made this change introduced\n; a error in the code, this function is not supposed to handle\n; Text wrapping\n??force_line_feed:\t\n\t; decrement pointer *string so that it will be back at same character\n\t; when it goes through the loop.\n\tdec\t[dword ptr string]\t\t  ; overflow by one charater\n\tjmp\t??done\n\n\n??line_feed:\n\tmov\tedx,[y_pixel]\t\t\t; get the current y pixel value.\n\tmovzx\tecx,[maxheight]\t\t\t; get max height for later use.\n\tadd\tedx,ecx\t\t\t\t; add max height to y_pixel\n\tcmp\tedx,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??done\t\t\t; if so, we are outa here.\n\n\tmov\teax,[bufferwidth]      \t\t; get bytes to next line.\n\tmov\tedi,[curline]\t\t\t; get start of current line.\t\n\tmul\tecx\t\t\t\t; mult max height * next line.\t\n\n\tadd\tedi,eax\t\t\t\t; add adjustment to current line.\n\tadd\t[y_pixel],ecx\t\t\t; increment to our next y position.\n\tmov\t[curline],edi\t\t\t; save it off for next line_feed.\n\tmov\t[startdraw],edi\t\t\t; save it off so we know where to draw next char.w\n\n\tmov\t[x_pixel],0\t\t\t; zero out x_pixel\n\n\tjmp\t??next_char\n??done:\n\tmov\teax,[string]\t\t\t; return the number of charaters \n\tsub\teax,[ptr_string]\t\t; printed\n\tret\t\t\t\t\t\n\t\t\n\tENDP\tVesa_Print\n\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VVBLIT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : BITBLIT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : December 13, 1994   [PWG]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\nTRANSP\tequ  0 \n\nPOOLSIZE equ\t8000\n\nCODESEG\n\n\tPROC\tVesa_Blit_To_Vesa C near \n\tUSES\tebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG    \tthis        :DWORD\t\t; this is a member function\n\tARG\tdest        :DWORD\t\t; what are we blitting to\n\tARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\tARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\tARG\tdest_x0     :dword\n\tARG\tdest_y0     :dword\n\tARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\tARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\tARG\ttrans       :DWORD\t\t\t; do we deal with transparents?\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tLOCAL\tdest_x1 : dword\n\tLOCAL\tdest_y1 : dword\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_ajust_width:DWORD\n        LOCAL\tsource_area :  dword\n        LOCAL\tdest_area :  dword\n\tlocal\ttotal_lines  : dword\n\tlocal\tcount_dy     : dword\n\tlocal\tmem_page     : dword\n\tlocal   vesa_page    : dword\n\tlocal\tmem_pool     : byte : POOLSIZE\n\n; Clip Source Rectangle against source Window boundaries.\n\tmov  \tesi , [ this ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??clip_against_dest\n\n\ttest\tcl , 1000b\n\tjz\t??scr_left_ok\n\tmov\t[ x_pixel ] , 0\n\n??scr_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\t[ y_pixel ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??clip_against_dest\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n\n; Clip Source Rectangle against destination Window boundaries.\n??clip_against_dest:\n\n\tmov\teax , [ dest_x0 ]\n\tmov\tebx , [ dest_y0 ]\n\tsub\teax , [ x_pixel ]\n\tsub\tebx , [ y_pixel ]\n\tadd\teax , [ x1_pixel ]\n\tadd\tebx , [ y1_pixel ]\n\tmov\t[ dest_x1 ] , eax\n\tmov\t[ dest_y1 ] , ebx\n\n\tmov  \tesi , [ dest ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ dest_x0 ]\n\tmov\tebx , [ dest_x1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\teax , [ dest_y0 ]\n\tmov\tebx , [ dest_y1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_blit\n\n\ttest\tcl , 1000b\n\tjz\t??dest_left_ok\n\tmov\teax , [ dest_x0 ]\n\tmov\t[ dest_x0 ] , 0\n\tsub\t[ x_pixel ] , eax\n\n??dest_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dest_bottom_ok\n\tmov\teax , [ dest_y0 ]\n\tmov\t[ dest_y0 ] , 0\n\tsub\t[ y_pixel ] , eax\n\n\n??dest_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??dest_right_ok\n\tmov\tebx , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ dest_x1 ]\n\tmov\t[ dest_x1 ] , ebx\n\tsub\teax , ebx\n\tsub\t[ x1_pixel ] , eax\n\n??dest_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\tmov\tebx , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\teax , [ dest_y1 ]\n\tmov\t[ dest_y1 ] , ebx\n\tsub\teax , ebx\n\tsub\t[ y1_pixel ] , eax\n\n??do_blit:\n\n       cld\t\n       mov\tebx , [ this ]\n       mov\tesi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\tecx , eax\n       mul\t[ y_pixel ]\n       add\tesi , [ x_pixel ]\n       mov\t[ source_area ] , ecx\n       add\tesi , eax\n\n       add\tecx , [ x_pixel ]\n       sub\tecx , [ x1_pixel ]\n       mov\t[ scr_ajust_width ] , ecx\n\n       mov\tebx , [ dest ]\n       mov\tedi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\tecx , eax\n       mul\t[ dest_y0 ]\n       add\tedi , [ dest_x0 ]\n       mov\t[ dest_area ] , ecx\n       add\tedi , eax\n\n       mov\teax , [ dest_x1 ]\n       sub\teax , [ dest_x0 ]\n       jz\t??real_out\n       sub\tecx , eax\n       mov\t[ dest_ajust_width ] , ecx\n\n       mov\tedx , [ dest_y1 ]\n       sub\tedx , [ dest_y0 ]\n       jz\t??real_out\n\n       push\teax\n       mov\t[ mem_page ] , 0\n       mov\t[ vesa_page ] , 0\n\n       mov\t[ total_lines ] , edx\t\n       mov\teax , POOLSIZE\n       xor\tedx , edx\n       idiv\t[ dword ptr esp ]\n       mov\t[ count_dy ] , eax\n       pop\teax\n\n; **************************************************************************\n; check direction of motions\n       cmp\tesi , edi\n       jl\t??backupward_blit\n\n       ret\n\n;***********************************************************************\n; Backupward blit\n\n??back_mem_loop:\n       push\tedi\n       lea\tedi , [ mem_pool ]\n       mov\tedx , [ count_dy ]\n       call\t??vesa_to_memory\n       pop\tedi\n\n       push\tesi\n       lea\tesi , [ mem_pool ]\n       mov\tedx , [ count_dy ]\n       call\t??memory_to_vesa\n       pop\tesi\n\n??backupward_blit:\n       mov\tedx , [ total_lines ]\n       sub\tedx , [ count_dy ]\n       mov\t[ total_lines ]\t, edx\n       jg\t??back_mem_loop\n\n       add\tedx , [ count_dy ]\n       push\tedi\n       push\tedx\n       lea\tedi , [ mem_pool ]\n       call\t??vesa_to_memory\n       pop\tedx\n       pop\tedi\n\n       push\tesi\n       lea\tesi , [ mem_pool ]\n       call\t??memory_to_vesa\n       pop\tesi\n       ret\n\n\n\n??real_out:\n       ret\n\n\n\n\n; ********************************************************************       \n; Move Vesa video page to memory buffer\n\n??vesa_to_memory:\n\n       xchg\tedi , esi\n       add\tedi , [ mem_page ]\n       call\tVesa_Asm_Set_Win  \n       xchg\tedi , esi\n\nIF  TRANSP\n       test\t[ trans ] , 1\n       jnz\t??tomem_forward_Blit_trans\nENDIF\n\n\n; the inner loop is so efficient that \n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10        \n       jl\t??tomem_forward_loop_bytes\n\n??tomem_forward_loop_dword:\n\n       lea\tebx , [ esi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??tomem_in_range\n\n       xor\tecx , ecx\n       mov\tebx , eax\n       cmp\tesi , 0b0000h\n       jge\t??tomem_no_trailing\n       mov\tecx , 0b0000h\n       sub\tecx , esi \n       sub\tebx , ecx\n       rep\tmovsb\n??tomem_no_trailing:  \n       add\tesi , [ cpu_video_page ]\n       xchg\tedi , esi\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n       xchg\tedi , esi\n\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??tomem_forward_loop_dword\n       mov\tedx , [ cpu_video_page ] \n       mov\t[ mem_page ] , edx \t\t\t\n       retn\n\n??tomem_in_range:\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       dec\tedx \n       jnz\t??tomem_forward_loop_dword\n       mov\tedx , [ cpu_video_page ] \n       mov\t[ mem_page ] , edx \t\t\t\n       retn\n\n??tomem_forward_loop_bytes:\n       lea\tebx , [ esi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       mov\tebx , eax\n       jl\t??tomem_in_range_bytes\n\n       xor\tecx , ecx\n       cmp\tesi , 0b0000h\n       jge\t??tomem_no_trailing_bytes\n       mov\tecx , 0b0000h\n       sub\tecx , esi \n       sub\tebx , ecx\n       rep\tmovsb\n??tomem_no_trailing_bytes:  \n       add\tesi , [ cpu_video_page ]\n       xchg\tedi , esi\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n       xchg\tedi , esi\n??tomem_in_range_bytes:\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??tomem_forward_loop_bytes\n       mov\tedx , [ cpu_video_page ] \n       mov\t[ mem_page ] , edx \t\t\t\n       retn\n\nIF  TRANSP\n??tomem_forward_Blit_trans:\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\t\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??tomem_transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n??tomem_forward_loop_trans:\n       mov\tecx , eax \n       jmp\t[ y1_pixel ]\n??tomem_forward_trans_line:\n       REPT\t32\t\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\tinc\tesi\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tedi\n\tENDM\n    ??tomem_transp_reference:\n       dec\tecx \n       jge\t??tomem_forward_trans_line\n       add\tesi , [ scr_ajust_width ]\n       dec\tedx \n       jnz\t??tomem_forward_loop_trans\n       mov\tedx , [ cpu_video_page ] \n       mov\t[ mem_page ] , edx \t\t\t\n       retn\nENDIF\n\n\n\n\n\n;*************************************************************************\n; copy from memory to vesa page\n\n??memory_to_vesa:\n       add\tedi , [ vesa_page ]\n       Call\tVesa_Asm_Set_Win  \n\nIF TRANSP\n       test\t[ trans ] , 1\n       jnz\t??tovesa_forward_Blit_trans\nENDIF\n\n\n; the inner loop is so efficient that \n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10        \n       jl\t??tovesa_forward_loop_bytes\n\n??tovesa_forward_loop_dword:\n\n       lea\tebx , [ edi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??tovesa_in_range\n\n       xor\tecx , ecx\n       cmp\tedi , 0b0000h\n       mov\tebx , eax\n       jge\t??tovesa_no_trailing\n       mov\tecx , 0b0000h\n       sub\tecx , edi \n       sub\tebx , ecx\n       rep\tmovsb\n??tovesa_no_trailing:  \n       add\tedi , [ cpu_video_page ]\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??tovesa_forward_loop_dword\n       mov\tedx , [ cpu_video_page ] \n       mov\t[ vesa_page ] , edx \n       retn\n\n??tovesa_in_range:\n\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??tovesa_forward_loop_dword\n       mov\tedx , [ cpu_video_page ] \n       mov\t[ vesa_page ] , edx \n       retn\n\n??tovesa_forward_loop_bytes:\n       lea\tebx , [ edi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       mov\tebx , eax\n       jl\t??tovesa_in_range_bytes\n\n       xor\tecx , ecx\n       cmp\tedi , 0b0000h\n       jge\t??tovesa_no_trailing_bytes\n       mov\tecx , 0b0000h\n       sub\tecx , edi \n       sub\tebx , ecx\n       rep\tmovsb\n??tovesa_no_trailing_bytes:  \n       add\tedi , [ cpu_video_page ]\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n??tovesa_in_range_bytes:\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??tovesa_forward_loop_bytes\n       mov\tedx , [ cpu_video_page ] \n       mov\t[ vesa_page ] , edx \n       retn\n\nIF  TRANSP\n\n\n??tovesa_forward_Blit_trans:\n\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\t\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??tovesa_transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n??tovesa_forward_loop_trans:\n       mov\tecx , eax \n       jmp\t[ y1_pixel ]\n??tovesa_forward_trans_line:\n       REPT\t32\t\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tesi\n\t    \tinc\tedi\n\tENDM\n    ??tovesa_transp_reference:\n       dec\tecx \n       jge\t??tovesa_forward_trans_line\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??tovesa_forward_loop_trans\n       mov\tedx , [ cpu_video_page ] \n       mov\t[ vesa_page ] , edx \n       retn\nENDIF\n\n\nENDP\tVesa_Blit_To_Vesa\n\n\n\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VVETOLB.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : BITBLIT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : December 13, 1994   [PWG]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\nTRANSP   equ 0\n\nCODESEG\n\n\n;***************************************************************************\n;* GVC::BLIT -- Copies a buffer to a graphic page non-linearly             *\n;*                                                                         *\n;* NOTE:\t\tAll coordinate values are expressed in pixels      *\n;*                                                                         *\n;* INPUT:\tVirtualViewPortClass *dest - Virtual View Port to copy to  *\n;*\t\tWORD src_x\t     \t   - Src x position to copy from   *\n;*\t\tWORD src_y\t\t   - Src y position to copy from   *\n;*\t\tWORD dst_x\t\t   - Dest x position to copy to\t   *\n;*\t\tWORD dst_y\t\t   - Dest y position to copy to\t   *\n;*\t\tWORD w\t\t\t   - Width of region to copy\t   *\n;*\t\tWORD h\t\t\t   - Height of region to copy\t   *\n;*                                                                         *\n;* OUTPUT:     none                                                        *\n;*                                                                         *\n;* WARNINGS:   Coordinates and dimensions will be adjusted if they exceed  *\n;*\t       the boundaries.  In the event that no adjustment is \t   *\n;*\t       possible this routine will abort.\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   05/11/1994 PWG : Created.                                             *\n;*   08/05/1994 PWG : Fixed clipping problem                               *\n;*=========================================================================*\n\tPROC\tVesa_Blit_To_Linear C near \n\tUSES\tebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG    \tthis        :DWORD\t\t; this is a member function\n\tARG\tdest        :DWORD\t\t; what are we blitting to\n\tARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\tARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\tARG\tdest_x0     :dword\n\tARG\tdest_y0     :dword\n\tARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\tARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\tARG\ttrans       :DWORD\t\t; do we deal with transparents?\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tLOCAL\tdest_x1 : dword\n\tLOCAL\tdest_y1 : dword\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_ajust_width:DWORD\n        LOCAL\tsource_area :  dword\n        LOCAL\tdest_area :  dword\n\n; Clip Source Rectangle against source Window boundaries.\n\tmov  \tesi , [ this ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??clip_against_dest\n\n\ttest\tcl , 1000b\n\tjz\t??scr_left_ok\n\tmov\t[ x_pixel ] , 0\n\n??scr_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\t[ y_pixel ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??clip_against_dest\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n\n; Clip Source Rectangle against destination Window boundaries.\n??clip_against_dest:\n\n\tmov\teax , [ dest_x0 ]\n\tmov\tebx , [ dest_y0 ]\n\tsub\teax , [ x_pixel ]\n\tsub\tebx , [ y_pixel ]\n\tadd\teax , [ x1_pixel ]\n\tadd\tebx , [ y1_pixel ]\n\tmov\t[ dest_x1 ] , eax\n\tmov\t[ dest_y1 ] , ebx\n\n\tmov  \tesi , [ dest ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ dest_x0 ]\n\tmov\tebx , [ dest_x1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\teax , [ dest_y0 ]\n\tmov\tebx , [ dest_y1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_blit\n\n\ttest\tcl , 1000b\n\tjz\t??dest_left_ok\n\tmov\teax , [ dest_x0 ]\n\tmov\t[ dest_x0 ] , 0\n\tsub\t[ x_pixel ] , eax\n\n??dest_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dest_bottom_ok\n\tmov\teax , [ dest_y0 ]\n\tmov\t[ dest_y0 ] , 0\n\tsub\t[ y_pixel ] , eax\n\n\n??dest_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??dest_right_ok\n\tmov\tebx , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ dest_x1 ]\n\tmov\t[ dest_x1 ] , ebx\n\tsub\teax , ebx\n\tsub\t[ x1_pixel ] , eax\n\n??dest_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\tmov\tebx , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\teax , [ dest_y1 ]\n\tmov\t[ dest_y1 ] , ebx\n\tsub\teax , ebx\n\tsub\t[ y1_pixel ] , eax\n\n??do_blit:\n\n       cld\t\n       mov\tebx , [ this ]\n       mov\tedi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\tecx , eax\n       mul\t[ y_pixel ]\n       add\tedi , [ x_pixel ]\n       mov\t[ source_area ] , ecx\n       add\tedi , eax\n       call\tVesa_Asm_Set_Win\t\t\t; set the window\n       mov\tesi , edi\n\n       add\tecx , [ x_pixel ]\n       sub\tecx , [ x1_pixel ]\n       mov\t[ scr_ajust_width ] , ecx\n\n       mov\tebx , [ dest ]\n       mov\tedi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\tecx , eax\n       mul\t[ dest_y0 ]\n       add\tedi , [ dest_x0 ]\n       mov\t[ dest_area ] , ecx\n       add\tedi , eax\n\n       mov\teax , [ dest_x1 ]\n       sub\teax , [ dest_x0 ]\n       jz\t??real_out\n       sub\tecx , eax\n       mov\t[ dest_ajust_width ] , ecx\n\n       mov\tedx , [ dest_y1 ]\n       sub\tedx , [ dest_y0 ]\n       jz\t??real_out\n\n; ********************************************************************       \n; Forward bitblit only\n\nIF TRANSP\n       test\t[ trans ] , 1\n       jnz\t??forward_Blit_trans\nENDIF\n\n\n; the inner loop is so efficient that \n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10        \n       jl\t??forward_loop_bytes\n\n??forward_loop_dword:\n       lea\tebx , [ esi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??in_range\n\n       xor\tecx , ecx\n       mov\tebx , eax\n       cmp\tesi , 0b0000h\n       jge\t??no_trailing\n       mov\tecx , 0b0000h\n       sub\tecx , esi \n       sub\tebx , ecx\n       rep\tmovsb\n??no_trailing:  \n       add\tesi , [ cpu_video_page ]\n       xchg\tedi , esi\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n       xchg\tedi , esi\n\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_dword\n       ret\n\n??in_range:\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_dword\n       ret\n\n??forward_loop_bytes:\n       lea\tebx , [ esi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       mov\tebx , eax\n       jl\t??in_range_bytes\n\n       xor\tecx , ecx\n       cmp\tesi , 0b0000h\n       jge\t??no_trailing_bytes\n       mov\tecx , 0b0000h\n       sub\tecx , esi \n       sub\tebx , ecx\n       rep\tmovsb\n??no_trailing_bytes:  \n       add\tesi , [ cpu_video_page ]\n       xchg\tedi , esi\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n       xchg\tedi , esi\n??in_range_bytes:\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_bytes\n       ret\n\nIF TRANSP\n\n??forward_Blit_trans:\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\t\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n??forward_loop_trans:\n       mov\tecx , eax \n       jmp\t[ y1_pixel ]\n??forward_trans_line:\n       REPT\t32\t\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tesi\n\t    \tinc\tedi\n\tENDM\n    ??transp_reference:\n       dec\tecx \n       jge\t??forward_trans_line\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_trans\n       ret\nENDIF\n\n??real_out:\n       ret\n\n\nENDP\tVesa_Blit_To_Linear\n\n\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VVETOSCL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VSCALE.ASM                               *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 16, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Vesa_Scale_To_Linear -- Scales a Vesa viewport to a graphic viewport  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\nCODESEG\n;***************************************************************************\n;* VESA_SCALE_TO_LINEAR -- Scales a Vesa viewport to a graphic viewport    *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_Scale_To_Linear C near\n\tret\n\tENDP\tVesa_Scale_To_Linear\n\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/VVETOSCL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Testing memory.                          *\n *                                                                         *\n *                    File Name : TEST.CPP                                 *\n *                                                                         *\n *                   Programmer : Julio Jerez                              *\n *                                                                         *\n *                   Start Date : Feb 13, 1995                             *\n *                                                                         *\n *                                                                         *\n *-------------------------------------------------------------------------*\n*/\n#include <mcgaprim.h>\n#include <gbuffer.h>\n#include <vbuffer.h>\n\nint Vesa_Scale_To_Linear ( void * scr,  void * dst, \n\t\t\t\t\t\t\t\t\tint src_x  , int src_y  , int dst_x , int dst_y , \n\t\t\t\t\t\t\t\t\tint src_wd , int src_hg , int dst_wd, int dst_hg, \n\t\t\t\t\t\t\t\t\tBOOL trans , char * remap )\n{\n  int\t   area ;\n  int    width , height ;\n  char * temp ;\n\n  VideoViewPortClass * scr1 = ( VideoViewPortClass * ) scr ;\n\n  width  = src_wd - src_x ;\n  height = src_hg - src_y ;\n  area = width * height ;\n  temp = ( char * ) malloc ( area ) ;\n  if ( ! temp ) return 0 ;\n\n  scr1 -> To_Buffer ( 0, 0, width , height , temp, area );\n  GraphicBufferClass tempbuffer ( area , width , height , temp ) ;\n\n  Linear_Scale_To_Linear ( & tempbuffer , dst , \n  \t\t\t\t\t\t\t\t\t  0 , 0 , dst_x , dst_y ,\n  \t\t\t\t\t\t\t\t\t  width , height , dst_wd , dst_hg ,\n\t\t\t\t\t\t\t\t\t  trans , remap ) ;\n\n  free ( temp ) ;\n  return 0 ;\n}\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/WINCOMM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer/ WW Library                                *\n *                                                                                             *\n *                    File Name : WINCOMM.H                                                    *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 1/10/96                                                      *\n *                                                                                             *\n *                  Last Update : January 10th 1996 [ST]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *                                                                                             *\n *   Functions for WinModemClass & WinNullModemClass                                           *\n *                                                                                             *\n *   These classes was created to replace the greenleaf comms functions used in C&C DOS with   *\n *  WIN32 API calls.                                                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\n//#include \"function.h\"\n#include \t\"wincomm.h\"\n#include\t\"timer.h\"\n#include\t\"keyboard.h\"\n#include\t\"misc.h\"\n#include <io.h>\n#include <sys\\types.h>\n#include <sys\\stat.h>\n#include <fcntl.h>\n\n\n/*\n** Define this to log modem activity to disk.\n*/\n//#define LOG_MODEM\n\n/*\n** Object represents a serial port\n*/\nWinModemClass\t*SerialPort = NULL;\n\n\n\n/***********************************************************************************************\n * WMC::WinModemClass -- WinModemClass constructor                                             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:14PM ST : Created                                                              *\n *=============================================================================================*/\n\nWinModemClass::WinModemClass(void)\n{\n\t/*\n\t** Allocate memory for our internal circular serial input buffer\n\t*/\n\tSerialBuffer = new unsigned char [SIZE_OF_WINDOWS_SERIAL_BUFFER];\n\n\t/*\n\t** Initialise the serial buffer pointers\n\t*/\n\tSerialBufferReadPtr\t= 0;\n\tSerialBufferWritePtr\t= 0;\n\n\t/*\n\t** Clear the waiting flags\n\t*/\n\tWaitingForSerialCharRead\t= FALSE;\n\tWaitingForSerialCharWrite\t= FALSE;\n\n\t/*\n\t** No default abort or echo function\n\t*/\n\tAbortFunction = NULL;\n\tEchoFunction  = NULL;\n\n\n\t/*\n\t** Clear the running error count\n\t*/\n\tFramingErrors=0;\n\tIOErrors=0;\n\tBufferOverruns=0;\n\tInBufferOverflows=0;\n\tParityErrors=0;\n\tOutBufferOverflows=0;\n\n\t/*\n\t** We havnt opened a port yet so...\n\t*/\n\tPortHandle = 0;\n}\n\n\n\n/***********************************************************************************************\n * WMC::~WinModemClass -- destructor for WinModemClass                                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:15PM ST : Created                                                              *\n *=============================================================================================*/\n\nWinModemClass::~WinModemClass(void)\n{\n\t/*\n\t** Close the port\n\t*/\n\tif (PortHandle){\n\t\tSerial_Port_Close();\n\t}\n\n\t/*\n\t** Free the serial buffer\n\t*/\n\tif (SerialBuffer){\n\t\tdelete [] SerialBuffer;\n\t}\n}\n\n\n\n/***********************************************************************************************\n * Get_Registry_Sub_Key -- search a registry key for a sub-key                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    handle of key to search                                                           *\n *           text to search for                                                                *\n *           true if old key should be closed when new key opened                              *\n *                                                                                             *\n * OUTPUT:   handle to the key we found or 0                                                   *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/12/96 2:11PM ST : Created                                                              *\n *=============================================================================================*/\n\nHKEY Get_Registry_Sub_Key (HKEY base_key, char *search_key, BOOL close)\n{\n\n\tchar\t\tclass_string[1024];\n\tDWORD\t\tstring_size = 1024;\n\tDWORD\t\tnum_sub_keys;\n\tDWORD\t\tlongest_sub_key_name;\n\tDWORD\t\tlongest_class_string;\n\tDWORD\t\tnum_value_entries;\n\tDWORD\t\tlongest_value_name_length;\n\tDWORD\t\tlongest_value_data_length;\n\tDWORD\t\tsecurity_descriptor_length;\n\tFILETIME\tlast_write_time;\n\tHKEY\t\tresult_key;\n\tDWORD\t\tsub_key_buffer_size;\n\n\tchar\t\t*sub_key_buffer;\n\tchar\t\t*sub_key_class;\n\n\n\tif (RegQueryInfoKey (base_key,\n\t\t\t\t\t\t\t&class_string[0],\n\t\t\t\t\t\t\t&string_size,\n\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t&num_sub_keys,\n\t\t\t\t\t\t\t&longest_sub_key_name,\n\t\t\t\t\t\t\t&longest_class_string,\n\t\t\t\t\t\t\t&num_value_entries,\n\t\t\t\t\t\t\t&longest_value_name_length,\n\t\t\t\t\t\t\t&longest_value_data_length,\n\t\t\t\t\t\t\t&security_descriptor_length,\n\t\t\t\t\t\t\t&last_write_time) != ERROR_SUCCESS) return (0);\n\n\tsub_key_buffer_size = longest_sub_key_name+16;\n\tsub_key_buffer = new char [sub_key_buffer_size];\n\tsub_key_class\t= new char [longest_class_string+1];\n\n\tfor (int key_num=0 ; key_num<num_sub_keys ; key_num++){\n\n\t\t*sub_key_buffer = 0;\n\t\tlongest_sub_key_name = sub_key_buffer_size;\n\t\tRegEnumKeyEx(base_key,\n\t\t\t\t\t\tkey_num,\n\t\t\t\t\t\tsub_key_buffer,\n\t\t\t\t\t\t&longest_sub_key_name,\n\t\t\t\t\t\tNULL,\n\t\t\t\t\t\tsub_key_class,\n\t\t\t\t\t\t&longest_class_string,\n\t\t\t\t\t\t&last_write_time);\n\n\t\tif (!stricmp(search_key, sub_key_buffer)){\n\n\t\t\tif (RegOpenKeyEx(\tbase_key,\n\t\t\t\t\t\t\t\t\tsub_key_buffer,\n\t\t\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t\t\tKEY_READ,\n\t\t\t\t\t\t\t\t\t&result_key) == ERROR_SUCCESS){\n\n\t\t\t\tif (close){\n\t\t\t\t\tRegCloseKey(base_key);\n\t\t\t\t}\n\t\t\t\tdelete [] sub_key_buffer;\n\t\t\t\tdelete [] sub_key_class;\n\t\t\t\treturn (result_key);\n\t\t\t}\n\t\t}\n\n\t}\n\n\tif (close){\n\t\tRegCloseKey(base_key);\n\t}\n\tdelete [] sub_key_buffer;\n\tdelete [] sub_key_class;\n\treturn (0);\n}\n\n\n\n/***********************************************************************************************\n * Get_Modem_Name_From_Registry -- retrieve the name of the installed modem from the registry  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    buffer to put the name in                                                         *\n *           length of buffer                                                                  *\n *                                                                                             *\n * OUTPUT:   TRUE if modem was found in the registry                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/12/96 2:13PM ST : Created                                                              *\n *=============================================================================================*/\nBOOL Get_Modem_Name_From_Registry(char *buffer, int buffer_len)\n{\n\tHKEY\tkey;\n\tchar\tmodem_name[256];\n\tDWORD\tmodem_name_size = 256;\n\n\tkey = Get_Registry_Sub_Key (HKEY_LOCAL_MACHINE, \"Enum\", FALSE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"Root\", TRUE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"Modem\", TRUE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"0000\", TRUE);\n\tif (!key) return (FALSE);\n\n\tif (RegQueryValueEx(key, \"FriendlyName\", NULL, NULL, (unsigned char*)&modem_name[0], &modem_name_size) != ERROR_SUCCESS){\n\t\tRegCloseKey(key);\n\t\treturn (FALSE);\n\t}\n\n\tRegCloseKey(key);\n\tmemcpy (buffer, modem_name, min(buffer_len, modem_name_size));\n\treturn (TRUE);\n}\n\n\n\n\n\n\n\n#ifdef cuts\n\n/***********************************************************************************************\n * WMC::Serial_Port_Open -- opens a com port for asyncronous read/write and gets a handle to it*\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Com port \t- 0=com1, 1=com2 etc.                                                 *\n *           baud rate \t- bits per second                                                     *\n *           parity \t\t- true or false                                                       *\n *           word length\t- 5 to 8 bits                                                         *\n *           stop bits\t- 0=1 stop bit, 1=1.5 & 2=2                                           *\n *                                                                                             *\n * OUTPUT:   Handle to port                                                                    *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:17PM ST : Created                                                              *\n *=============================================================================================*/\n\n//VOID FAR PASCAL lineCallbackFunc(DWORD hDevice, DWORD dwMsg,\n//    DWORD dwCallbackInstance, DWORD dwParam1, DWORD dwParam2,\n//   DWORD dwParam3)\n\nVOID FAR PASCAL lineCallbackFunc(DWORD ,DWORD ,DWORD ,DWORD ,DWORD ,DWORD);\n\nextern HINSTANCE ProgramInstance;\n\nHANDLE\tWinModemClass::Serial_Port_Open (int com, int baud, int parity, int wordlen, int stopbits)\n{\n\tHANDLE\t\t\tcom_handle;\t\t\t//temporary storage for the port handle\n\tDCB\t\t\t\tdevice_control;\t//device control block\n\tCOMMTIMEOUTS\ttimeouts;\t\t\t//timeout values\n\tchar\t\t\t\tmodem_name[256];\t//name of modem\n\tchar\t\t\t\tdevice_name[266]={\"\\\\\\\\.\\\\\"};\t//device name to open\n\tDWORD\t\t\t\tconfig_size = 2048;\n\tchar\t\t\t\tconfig[2048];\n\tCOMMCONFIG\t\t*modem_config = (COMMCONFIG*)&config[0];\n\tMODEMDEVCAPS\t*modem_caps;\n\tint\t\t\t\ttemp;\n\tBOOL\t\t\t\tfound_modem;\n\n\t/*\n\t** Map for com port values to device names\n\t*/\n\tstatic char com_ids[8][5]={\n\t\t\"COM1\",\n\t\t\"COM2\",\n\t\t\"COM3\",\n\t\t\"COM4\",\n\t\t\"COM5\",\n\t\t\"COM6\",\n\t\t\"COM7\",\n\t\t\"COM8\"\n\t};\n\n\n\tHLINEAPP \tapp_line_handle;\n\tDWORD\t\t\tnum_devices;\n\n\tlineInitialise (&app_line_handle, ProgramInstance, &lineCallbackFunc, NULL, &num_devices);\n\n\n\n\n\n\n\tfound_modem = TRUE;\n\n\tif (!Get_Modem_Name_From_Registry(modem_name, 256)){\n\t\tstrcpy(modem_name, com_ids[com]);\n\t\tfound_modem = FALSE;\n\t}\n\n\tstrcat(device_name, modem_name);\n\n\n\tPortHandle = 0;\n\n\t/*\n\t** Open the com port for asyncronous reads/writes\n\t*/\n\tcom_handle = CreateFile (device_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);\n\n\tif (com_handle == INVALID_HANDLE_VALUE) return (com_handle);\n\n\tPortHandle = com_handle;\n\n\t/*\n\t** Set the size of the windows communication buffers\n\t*/\n\tSetupComm(com_handle, 2048, 2048);\n\n\n\t/*\n\t** Create an event object for asyncronous reads\n\t*/\n\tReadOverlap.Internal \t\t= 0;\n\tReadOverlap.InternalHigh\t= 0;\n\tReadOverlap.Offset\t\t\t= 0;\n\tReadOverlap.OffsetHigh\t\t= 0;\n\tReadOverlap.hEvent\t\t\t= CreateEvent (NULL, TRUE, TRUE, NULL);\n\n\t/*\n\t** Create an event object for asyncronous writes\n\t*/\n\tWriteOverlap.Internal \t\t= 0;\n\tWriteOverlap.InternalHigh\t= 0;\n\tWriteOverlap.Offset\t\t\t= 0;\n\tWriteOverlap.OffsetHigh\t\t= 0;\n\tWriteOverlap.hEvent\t\t\t= CreateEvent (NULL, TRUE, TRUE, NULL);\n\n\tif (!found_modem){\n\t\t/*\n\t\t** Get the current state of the com port as a basis for our device control block\n\t\t*/\n\t\tGetCommState (com_handle , &device_control);\n\n\t\t/*\n\t\t** Communications settings\n\t\t*/\n\t\tdevice_control.BaudRate = baud;\n\t\tdevice_control.fParity \t= parity;\n\t\tdevice_control.ByteSize = wordlen;\n\t\tdevice_control.StopBits\t= stopbits-1;\n\n\t\t/*\n\t\t** Misc settings for flow control etc.\n\t\t*/\n\t\tdevice_control.fBinary\t\t\t= TRUE;\t\t\t\t\t\t\t// Binary mode data transfer\n\t\tdevice_control.fOutxCtsFlow \t= TRUE;  \t\t\t\t\t\t// CTS flow control\n\t\tdevice_control.fRtsControl\t\t= RTS_CONTROL_HANDSHAKE;\t// RTS flow control\n\t\tdevice_control.fErrorChar\t\t= FALSE;\t\t\t\t\t\t\t// Dont put an error char into our input stream\n\t\tdevice_control.fOutxDsrFlow\t= FALSE;\t\t\t\t\t\t\t// No DSR flow control\n\t\tdevice_control.fDtrControl\t\t= DTR_CONTROL_ENABLE;\t\t// Enable control of DTR line\n\t\tdevice_control.fOutX\t\t\t\t= FALSE;\t\t\t\t\t\t\t// No XON/XOF flow control\n\t\tdevice_control.fInX\t\t\t\t= FALSE;\t\t\t\t\t\t\t// No XON/XOF flow control\n\t\tdevice_control.fAbortOnError\t= FALSE;\t\t\t\t\t\t\t// Device continues to send after an error\n\n\t\t/*\n\t\t** Pass the device settings to windows\n\t\t*/\n\t\tif (SetCommState (com_handle , &device_control) != TRUE){\n\t\t\tSerial_Port_Close();\n\t\t\treturn (INVALID_HANDLE_VALUE);\n\t\t}\n\t}else{\n\n\t\t/*\n\t\t** If we are talking to a modem device then turn off compression and error correction\n\t\t*/\n\t\tGetCommConfig(PortHandle ,modem_config, &config_size);\n\n\t\tif (modem_config->dwProviderSubType == PST_MODEM){\n\t\t\ttemp = modem_config->dwProviderOffset;\n\t\t\ttemp += (int)modem_config;\n\t\t\tmodem_caps = (MODEMDEVCAPS*)temp;\n\t\t\tmodem_caps->dwModemOptions &= ~(\tMDM_COMPRESSION |\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tMDM_ERROR_CONTROL |\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tMDM_FLOWCONTROL_HARD);\n\t\t\tSetCommConfig(PortHandle, modem_config ,(unsigned)config_size);\n\t\t}\n\t}\n\n\n\t/*\n\t** Set the device timeouts\n\t*/\n\ttimeouts.ReadIntervalTimeout \t\t\t= 10000;\t//10 seconds between incoming packets\n\ttimeouts.ReadTotalTimeoutMultiplier = 0;\t\t//disable total timeouts\n\ttimeouts.ReadTotalTimeoutConstant\t= 0;\t\t//disable total timeouts\n    timeouts.WriteTotalTimeoutMultiplier= 0;\t\t//disable total timeouts\n    timeouts.WriteTotalTimeoutConstant\t= 0;\t\t//disable total timeouts\n\n\tif (SetCommTimeouts(com_handle, &timeouts) !=TRUE){\n\t\tSerial_Port_Close();\n\t\treturn (INVALID_HANDLE_VALUE);\n\t}\n\n\treturn (com_handle);\n}\n#endif\n\n\n\n\n\n/***********************************************************************************************\n * WMC::Serial_Port_Open -- opens a com port for asyncronous read/write and gets a handle to it*\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Com port \t- 0=com1, 1=com2 etc.                                                 *\n *           baud rate \t- bits per second                                                     *\n *           parity \t\t- true or false                                                       *\n *           word length\t- 5 to 8 bits                                                         *\n *           stop bits\t- 0=1 stop bit, 1=1.5 & 2=2                                           *\n *           flow control- 0 = none, 1 = hardware                                              *\n *                                                                                             *\n * OUTPUT:   Handle to port                                                                    *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:17PM ST : Created                                                              *\n *=============================================================================================*/\nHANDLE\tWinModemClass::Serial_Port_Open (char *device_name, int baud, int parity, int wordlen, int stopbits, int flowcontrol)\n{\n\tHANDLE\t\t\tcom_handle;\t\t\t//temporary storage for the port handle\n\tDCB\t\t\t\tdevice_control;\t//device control block\n\tCOMMTIMEOUTS\ttimeouts;\t\t\t//timeout values\n#if (0)\n\t/*\n\t** Map for com port values to device names\n\t*/\n\tstatic char com_ids[8][5]={\n\t\t\"COM1\",\n\t\t\"COM2\",\n\t\t\"COM3\",\n\t\t\"COM4\",\n\t\t\"COM5\",\n\t\t\"COM6\",\n\t\t\"COM7\",\n\t\t\"COM8\"\n\t};\n#endif\t//(0)\n\n\tint\terrorval;\n\tchar\terrortxt[128];\n\n\tchar devname[266]={\"\\\\\\\\.\\\\\"};\t//device name to open\n\tstrcat (devname, device_name);\n\n\tPortHandle = 0;\n\n\t/*\n\t** Open the com port for asyncronous reads/writes\n\t*/\n\t//com_handle = CreateFile (&com_ids[com][0], GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);\n\tcom_handle = CreateFile (devname, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);\n\n\tif (com_handle == INVALID_HANDLE_VALUE) return (com_handle);\n\n\tPortHandle = com_handle;\n\n\t/*\n\t** Set the size of the windows communication buffers\n\t*/\n\tSetupComm(com_handle, SIZE_OF_WINDOWS_SERIAL_BUFFER, SIZE_OF_WINDOWS_SERIAL_BUFFER);\n\n\t/*\n\t** Reset any read or write operation and purge the buffers\n\t*/\n\tPurgeComm (PortHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);\n\n\t/*\n\t** Create an event object for asyncronous reads\n\t*/\n\tReadOverlap.Internal \t\t= 0;\n\tReadOverlap.InternalHigh\t= 0;\n\tReadOverlap.Offset\t\t\t= 0;\n\tReadOverlap.OffsetHigh\t\t= 0;\n\tReadOverlap.hEvent\t\t\t= CreateEvent (NULL, TRUE, TRUE, NULL);\n\n\t/*\n\t** Create an event object for asyncronous writes\n\t*/\n\tWriteOverlap.Internal \t\t= 0;\n\tWriteOverlap.InternalHigh\t= 0;\n\tWriteOverlap.Offset\t\t\t= 0;\n\tWriteOverlap.OffsetHigh\t\t= 0;\n\tWriteOverlap.hEvent\t\t\t= CreateEvent (NULL, TRUE, TRUE, NULL);\n\n\n\t/*\n\t** Get the current state of the com port as a basis for our device control block\n\t*/\n\tif (GetCommState (com_handle , &device_control)){\n\n\t\t/*\n\t\t** Communications settings\n\t\t*/\n\t\tdevice_control.BaudRate = baud;\n\t\tdevice_control.fParity \t= parity;\n\t\tdevice_control.ByteSize = (char)wordlen;\n\t\tdevice_control.StopBits\t= (char)(stopbits-1);\n\n\t\t/*\n\t\t** Misc settings for flow control etc.\n\t\t*/\n\t\tdevice_control.fBinary\t\t\t= TRUE;\t\t\t\t\t\t\t// Binary mode data transfer\n\t\tdevice_control.fOutxCtsFlow \t= TRUE;  \t\t\t\t\t\t// CTS flow control\n\t\tdevice_control.fRtsControl\t\t= RTS_CONTROL_HANDSHAKE;\t// RTS flow control\n\t\tdevice_control.fErrorChar\t\t= FALSE;\t\t\t\t\t\t\t// Dont put an error char into our input stream\n\t\tdevice_control.fOutxDsrFlow\t= FALSE;\t\t\t\t\t\t\t// No DSR flow control\n\t\tdevice_control.fDtrControl\t\t= DTR_CONTROL_ENABLE;\t\t// Enable control of DTR line\n\t\tdevice_control.fOutX\t\t\t\t= FALSE;\t\t\t\t\t\t\t// No XON/XOF flow control\n\t\tdevice_control.fInX\t\t\t\t= FALSE;\t\t\t\t\t\t\t// No XON/XOF flow control\n\t\tdevice_control.fAbortOnError\t= FALSE;\t\t\t\t\t\t\t// Device continues to send after an error\n\n\t\t/*\n\t\t** Disable hardware flow control if required\n\t\t*/\n\t\tif (!flowcontrol){\n\t\t\tdevice_control.fOutxCtsFlow \t= FALSE;  \t\t\t\t\t// CTS flow control\n\t\t\tdevice_control.fRtsControl\t\t= RTS_CONTROL_DISABLE;\t// RTS flow control\n\t\t}\n\n\t\t/*\n\t\t** Pass the device settings to windows\n\t\t*/\n\t\tif ( !SetCommState (com_handle , &device_control)){\n\t\t\terrorval = GetLastError();\n\t\t\tsprintf (errortxt, \"RA95 -- SetCommState returned error code %d.\\n\", errorval);\n\t\t\tOutputDebugString (errortxt);\n\t\t\t//Serial_Port_Close();\n\t\t\t//return (INVALID_HANDLE_VALUE);\n\t\t}\n\t}else{\n\t\terrorval = GetLastError();\n\t\tsprintf (errortxt, \"RA95 -- GetCommState returned error code %d.\\n\", errorval);\n\t\tOutputDebugString (errortxt);\n\t}\n\n\n\n\t/*\n\t** Set the device timeouts\n\t*/\n\ttimeouts.ReadIntervalTimeout \t\t\t= 1000;\t//1 second between incoming bytes will time-out the read\n\ttimeouts.ReadTotalTimeoutMultiplier = 0;\t\t//disable per byte timeouts\n\ttimeouts.ReadTotalTimeoutConstant\t= 3000;\t//Read operations time out after 3 secs if no data received\n    timeouts.WriteTotalTimeoutMultiplier= 500;\t//Allow 1/2 ms between each char write\n    timeouts.WriteTotalTimeoutConstant\t= 1000;\t//Write operations time out after 1 sec + 1/2 sec per char if data wasnt sent\n\n\tif ( !SetCommTimeouts(com_handle, &timeouts) ){\n\t\terrorval = GetLastError();\n\t\tsprintf (errortxt, \"RA95 -- SetCommTimeouts returned error code %d.\\n\", errorval);\n\t\tOutputDebugString (errortxt);\n\t\t//Serial_Port_Close();\n\t\t//return (INVALID_HANDLE_VALUE);\n\t}\n\n\treturn (com_handle);\n}\n\n\n\n\n\n/***********************************************************************************************\n * WMC::Set_Modem_Dial_Type -- sets dial type to WC_TOUCH_TONE or WC_PULSE                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    WC_TOUCH_TONE or WC_PULSE                                                         *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:22PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid WinModemClass::Set_Modem_Dial_Type(WinCommDialMethodType method)\n{\n\tDialingMethod = method;\n}\n\n\n\n\n/***********************************************************************************************\n * WMC::Get_Modem_Status -- gets the status of the modem control lines                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Modem status. Any of the following bits CTS_SET, DSR_SET, RI_SET or CD_SET        *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:24PM ST : Created                                                              *\n *=============================================================================================*/\n\nunsigned WinModemClass::Get_Modem_Status(void)\n{\n\tDWORD\t\tmodem_stat = 0;\n\tunsigned\tlong return_stat = 0;\n\n\t/*\n\t** Get the modem status\n\t*/\n\tGetCommModemStatus(PortHandle, &modem_stat);\n\n\t/*\n\t** Translate the windows status flags to greenleaf flags\n\t*/\n\tif (MS_CTS_ON  & modem_stat) return_stat |= CTS_SET;\n\tif (MS_DSR_ON  & modem_stat) return_stat |= DSR_SET;\n\tif (MS_RING_ON & modem_stat) return_stat |= RI_SET;\n\tif (MS_RLSD_ON & modem_stat) return_stat |= CD_SET;\n\n\treturn (return_stat);\n\n}\n\n\n\n/***********************************************************************************************\n * WMC::Set_Serial_DTR -- set the state of the modems DTR control line                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    state - true or false                                                             *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:25PM ST : Created                                                              *\n *=============================================================================================*/\nvoid WinModemClass::Set_Serial_DTR(BOOL state)\n{\n\tif (state){\n\t\tEscapeCommFunction(PortHandle, SETDTR);\n\t}else{\n\t\tEscapeCommFunction(PortHandle, CLRDTR);\n\t}\n}\n\n\n\n\n\n/***********************************************************************************************\n * WMC::Serial_Port_Close -- close the port and free the port handle                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:26PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid WinModemClass::Serial_Port_Close (void)\n{\n\tif (PortHandle){\n\t\tCloseHandle(PortHandle);\n\t\tPortHandle = 0;\n\t}\n}\n\n\n\n/***********************************************************************************************\n * WMC::Read_Serial_Chars -- copys chars from the windows serial buffer to the class buffer    *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   TRUE if any chars read                                                            *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:26PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Smart_Printf( char *format, ... );\nBOOL WinModemClass::Read_Serial_Chars (void)\n{\n\tDWORD\tbytes_read;\t\t\t\t//amount of data read this time\n\tBOOL\tread_result;\t\t\t//result of ReadFile\n\tBOOL\toverlap_result;\t\t//result of GetOverlappedResult\n\tDWORD\ttotal_bytes_read=0;\t//total amount of data read\n\tint\tbytes_to_read;\n\tint\ti;\n\n\t/*\n\t** Are we were still waiting for the last read operation to finish?\n\t*/\n\tif (WaitingForSerialCharRead){\n\n\t\t/*\n\t\t** Check the result of the last read operation\n\t\t*/\n\t\tbytes_read = 0;\n\t\toverlap_result = GetOverlappedResult(PortHandle, &ReadOverlap, &bytes_read, FALSE);\n\n\t\t/*\n\t\t** If we got a good result from GetOverlappedResult and data was read then move it\n\t\t**  to our circular buffer\n\t\t*/\n\t\tif (overlap_result){\n\t\t\tWaitingForSerialCharRead = FALSE;\t//Flag that we are no longer waiting for a read\n\n\t\t\tif (bytes_read){\n\t\t\t\tfor (i=0 ; i<bytes_read ; i++){\n\t\t\t\t\t*(SerialBuffer + SerialBufferWritePtr++) = TempSerialBuffer[i];\n\t\t\t\t\tSerialBufferWritePtr &= SIZE_OF_WINDOWS_SERIAL_BUFFER - 1;\n\t\t\t\t}\n\t\t\t\ttotal_bytes_read += bytes_read;\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t** No chars were read since last time so just return\n\t\t\t*/\n\t\t\tif (GetLastError() == ERROR_IO_INCOMPLETE){\n\t\t\t\treturn (FALSE);\n\t\t\t}\n\t\t}\n\n\t}\n\n\n\t/*\n\t**\n\t** There is no outstanding read to wait for so try a new read\n\t**\n\t*/\n\n\t/*\n\t** Clear the event object\n\t*/\n\tResetEvent(ReadOverlap.hEvent);\n\n\n\t/*\n\t**\n\t** Clear any communications errors and get the number of bytes in the in buffer\n\t**\n\t*/\n\tDWORD \terror;\n\tCOMSTAT\tstatus;\n\n\tbytes_to_read = 1;\n\n\tif (ClearCommError(PortHandle, &error,\t&status)){\n\n\t\tInQueue \t= status.cbInQue;\n\t\tOutQueue\t= status.cbOutQue;\n\n\t\tif (error){\n\t\t\tif (CE_FRAME & error)\tFramingErrors++;\n\t\t\tif (CE_IOE & error) \t\tIOErrors++;\n\t\t\tif (CE_OVERRUN & error) BufferOverruns++;\n\t\t\tif (CE_RXOVER & error)  InBufferOverflows++;\n\t\t\tif (CE_RXPARITY & error)ParityErrors++;\n\t\t\tif (CE_TXFULL & error)  OutBufferOverflows++;\n\t\t\tbytes_to_read = 0;\n\t\t}else{\n\t\t\tbytes_to_read = min(status.cbInQue, SIZE_OF_WINDOWS_SERIAL_BUFFER);\n\t\t}\n\t}\n\n\tif (!bytes_to_read) bytes_to_read++;\n\n\n\t/*\n\t**\n\t** Start reading bytes\n\t**\n\t*/\n\n\tdo{\n\t\t/*\n\t\t** Try a read operation\n\t\t*/\n\t\tbytes_read = 0;\n\t\tread_result = ReadFile(PortHandle ,TempSerialBuffer ,bytes_to_read ,&bytes_read, &ReadOverlap);\n\n\t\tif (!read_result){\n\n\t\t\t/*\n\t\t\t** Read failed\n\t\t\t*/\n\t\t\tif (GetLastError() == ERROR_IO_PENDING){\n\n\t\t\t\t/*\n\t\t\t\t** But it threaded in the background OK so flag that we must wait for it to finish\n\t\t\t\t*/\n\t\t\t\tWaitingForSerialCharRead = TRUE;\n\t\t\t}\n\n\t\t}else{\n\n\t\t\t/*\n\t\t\t** Read was successful - copy to our circular buffer and try reading again\n\t\t\t*/\n\t\t\tif (bytes_read){\n\t\t\t\tfor (i=0 ; i<bytes_read ; i++){\n\t\t\t\t\t*(SerialBuffer + SerialBufferWritePtr++) = TempSerialBuffer[i];\n\t\t\t\t\tSerialBufferWritePtr &= SIZE_OF_WINDOWS_SERIAL_BUFFER - 1;\n\t\t\t\t}\n\t\t\t\ttotal_bytes_read += bytes_read;\n\t\t\t}\n\t\tbytes_to_read = 1;\n\t\t}\n\n\t} while (read_result == TRUE);\n\n\treturn ((BOOL)total_bytes_read);\n}\n\n\n\n\n\n\n\n/***********************************************************************************************\n * WMC::Read_From_Serial_Port -- retrieves chars from the internal class circular buffer which *\n *                               is filled from the windows serial buffer                      *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    buffer to copy to                                                                 *\n *           size of buffer                                                                    *\n *                                                                                             *\n * OUTPUT:   number of chars copied                                                            *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:27PM ST : Created                                                              *\n *=============================================================================================*/\n\nint WinModemClass::Read_From_Serial_Port (unsigned char *dest_ptr, int buffer_len)\n{\n\tint\tbytes_read;\n\tint\tbytes_to_copy = 0;\n\tunsigned char *original_dest = dest_ptr;\n\n\t/*\n\t** Get any outstanding data from the windows serial buffer into our class' circular buffer\n\t*/\n\tbytes_read = Read_Serial_Chars();\n\n\tif (bytes_read){\n\n\t\t/*\n\t\t** Calculate how many bytes should be copied to the user buffer\n\t\t*/\n\t\tbytes_to_copy = SerialBufferWritePtr - SerialBufferReadPtr;\n\t\tif (bytes_to_copy <0 ) bytes_to_copy += SIZE_OF_WINDOWS_SERIAL_BUFFER;\n\t\tif (bytes_to_copy>buffer_len) bytes_to_copy = buffer_len;\n\n\t\t/*\n\t\t** Loop to copy the data from the internal class buffer to the users buffer\n\t\t*/\n\t\tfor (int i=0 ; i<bytes_to_copy ; i++){\n\n\t\t\t/*\n\t\t\t** Call the users echo function if required\n\t\t\t*/\n\t\t\tif (EchoFunction && *(SerialBuffer + SerialBufferReadPtr) !=13 ){\n\t\t\t\tEchoFunction(*(SerialBuffer + SerialBufferReadPtr));\n\t\t\t}\n\n\t\t\t*dest_ptr++ = *(SerialBuffer + SerialBufferReadPtr++);\n\t\t\tSerialBufferReadPtr &= SIZE_OF_WINDOWS_SERIAL_BUFFER-1;\n\t\t}\n\t}\n\n#ifdef LOG_MODEM\n\n\tif (bytes_read){\n\n\t\tchar *outstr = new char[bytes_read+1];\n\t\tmemcpy (outstr, original_dest, bytes_read);\n\t\toutstr[bytes_read] = 0;\n\t\tOutputDebugString (outstr);\n\n\t\tint\thandle;\n\n\t\thandle = open(\"COMMLOG.TXT\",O_WRONLY | O_CREAT | O_APPEND | O_TEXT);\n\n\t\tif (handle != -1){\n\t\t\twrite(handle, original_dest, bytes_read);\n\t\t\tclose(handle);\n\t\t}\n\t}\n#endif\t//LOG_MODEM\n\n\n\treturn(bytes_to_copy);\n}\n\n\n\n\n/***********************************************************************************************\n * WMC::Wait_For_Serial_Write -- waits for output buffer to empty                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:29PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid WinModemClass::Wait_For_Serial_Write()\n{\n\tDWORD\t\t\t\t\t\tbytes_written;\n\tBOOL\t\t\t\t\t\toverlap_result;\n\tBOOL \t\t\t\t\t\twait_send;\n\tCountDownTimerClass\ttimer;\n\n\tif (WaitingForSerialCharWrite){\n\n\t\ttimer.Set(60*5);\n\n\t\t/*\n\t\t** Wait until the overlapped port write is finished\n\t\t*/\n\t\tdo{\n\t\t\twait_send = FALSE;\n\t\t\toverlap_result = GetOverlappedResult(PortHandle, &WriteOverlap, &bytes_written, FALSE);\n\n\t\t\tif (!overlap_result){\n\t\t\t\tif (GetLastError() == ERROR_IO_INCOMPLETE){\n\t\t\t\t\twait_send = TRUE;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}while(wait_send && timer.Time());\n\n\t\tWaitingForSerialCharWrite = FALSE;\n\t}\n\n\tResetEvent(WriteOverlap.hEvent);\n}\n\n\n\n\n/***********************************************************************************************\n * WMC::Write_To_Serial_Port -- writes data to the serial port                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to data                                                                       *\n *           bytes to write                                                                    *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:29PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid WinModemClass::Write_To_Serial_Port (unsigned char *buffer, int length)\n{\n\tDWORD\tbytes_written;\n\tBOOL\twrite_result;\n\n\n#ifdef LOG_MODEM\n\n\tif (length){\n\n\t\tchar *outstr = new char[length+1];\n\t\tmemcpy (outstr, buffer, length);\n\t\toutstr[length] = 0;\n\t\tOutputDebugString (outstr);\n\n\t\tint\thandle;\n\n\t\thandle = open(\"COMMLOG.TXT\",O_WRONLY | O_CREAT | O_APPEND | O_TEXT);\n\n\t\tif (handle != -1){\n\t\t\twrite(handle, buffer, length);\n\t\t\tclose(handle);\n\t\t}\n\t}\n#endif\t//LOG_MODEM\n\n\n\n\t/*\n\t** Wait for the end of the last write operation\n\t*/\n\tWait_For_Serial_Write();\n\n\t/*\n\t** Write the data to the port\n\t*/\n\twrite_result = WriteFile (PortHandle, buffer, length, &bytes_written, &WriteOverlap);\n\n\tif (!write_result){\n\t\tif (GetLastError() == ERROR_IO_PENDING){\n\t\t\tWaitingForSerialCharWrite = TRUE;\n\t\t}\n\t}\n\n}\n\n\n\n\n/***********************************************************************************************\n * WMC::Get_Modem_Result -- gets the result code from the modem after issuing an 'AT' command  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    delay for result time-out                                                         *\n *           ptr to buffer to receive modem result                                             *\n *           length of buffer                                                                  *\n *                                                                                             *\n * OUTPUT:   un-elapsed delay                                                                  *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:30PM ST : Created                                                              *\n *=============================================================================================*/\n\nextern void CCDebugString (char*);\n\nint WinModemClass::Get_Modem_Result(int delay, char *buffer, int buffer_len)\n{\n\n\tCountDownTimerClass\ttimer;\n\tint\t\t\t\t\t\tdest_ptr;\n\tchar\t\t\t\t\t\t*cr_ptr;\n\tchar\t\t\t\t\t\t*lf_ptr;\n\tint\t\t\t\t\t\tcopy_bytes;\n\n\t//OutputDebugString (\"Wincomm - In Get_Modem_Result\\n\");\n\n\tchar abuffer [128];\n\tsprintf (abuffer, \"Wincomm - delay = %d, buffer = %p, buffer_len = %d.\\n\", delay, buffer, buffer_len);\n\t//OutputDebugString (abuffer);\n\n\t//OutputDebugString (\"Wincomm - About to clear input buffer.\\n\");\n\tmemset(buffer, 0 ,buffer_len);\n\tdest_ptr = 0;\n\n\t/*\n\t** Loop to parse data from the modem and discard any echoed 'AT' commands or spurious LF\n\t** and CR characters.\n\t**\n\t*/\n\n\t//OutputDebugString (\"Wincomm - Entering do loop.\\n\");\n\tdo{\n\t\tcr_ptr \t= NULL;\t\t\t//Set the result pointer to NULL\n\t\t//OutputDebugString (\"Wincomm - About to set timer.\\n\");\n\t\ttimer.Set(delay/16);\t\t//Set and start the timer\n\n\t\t/*\n\t\t** Keep reading from the serial port until...\n\t\t**    1. we time out\n\t\t**    2. the user abort by pressing ESC\n\t\t**    3. the supplied buffer fills up\n\t\t**    4. there is an app switch\n\t\t** or 5. we get a CR character from the modem\n\t\t*/\n\t\t//OutputDebugString (\"Wincomm - About to enter inner do loop.\\n\");\n\t\tdo{\n\t\t\tif (AbortFunction){// &&\n\t\t\t\t //_Kbd->Check()) {\n\n\t\t\t\t//OutputDebugString (\"Wincomm - About to call abort function.\\n\");\n\t\t\t\tint abort = AbortFunction();\n\t\t\t\tsprintf (abuffer ,\"Wincomm - About function returned %d.\\n\", abort);\n\t\t\t\t//OutputDebugString (abuffer);\n\t\t\t\tif (abort != COMMSUCCESS) return (abort);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If we had lost focus then abort\n\t\t\t*/\n\t\t\tif (AllSurfaces.SurfacesRestored){\n\t\t\t\t//OutputDebugString (\"Wincomm - Aborting due to loss of focus.\\n\");\n\t\t\t\treturn (0);\n\t\t\t}\n\n\t\t\t//OutputDebugString (\"Wincomm - About to call Read_From_Serial_Port.\\n\");\n\t\t\tdest_ptr += Read_From_Serial_Port((unsigned char*)(buffer + dest_ptr), (int)buffer_len-dest_ptr);\n\t\t\tsprintf (abuffer, \"Wincomm - End of inner do loop. Time is %d.\\n\", timer.Time());\n\t\t\t//OutputDebugString (abuffer);\n\t\t} while (timer.Time() &&\n\t\t\t\t\tdest_ptr < buffer_len &&\n\t\t\t\t\t!strchr (buffer, 13) );\n\n\t\t//OutputDebugString (\"Wincomm - Exited inner do loop.\\n\");\n\n\n\t\t/*\n\t\t** We need to discard this result if it is just an echo of the 'AT' command we sent\n\t\t*/\n\t\tcr_ptr = strstr(buffer,\"AT\");\n\t\tif (cr_ptr){\n\t\t\tif (*buffer == 'A' && *(buffer+1) == 'T' && strchr(buffer,13)){\n\t\t\t\t//OutputDebugString (\"Wincomm - Discarding command echo.\\n\");\n\t\t\t\tcr_ptr = strchr(buffer,13);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** If it wasnt an AT echo then strip off any leading CR/LF characters\n\t\t*/\n\t\tif (!cr_ptr && (*buffer==13 || *buffer==10)){\n\t\t\tcr_ptr = strchr(buffer,13);\n\t\t\tlf_ptr = strchr(buffer,10);\n\t\t\tif (!cr_ptr || (lf_ptr && lf_ptr < cr_ptr)){\n\t\t\t\t//OutputDebugString (\"Wincomm - Stripping CR/LF.\\n\");\n\t\t\t\tcr_ptr = strchr(buffer,10);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Copy the good stuff at the end of the buffer over the 'AT' or CR/LF chars\n\t\t*/\n\t\tif (cr_ptr){\n\t\t\t//OutputDebugString (\"Wincomm - Copying over start of buffer.\\n\");\n\t\t\twhile(*cr_ptr == 13 || *cr_ptr == 10){\n\t\t\t\tcr_ptr++;\n\t\t\t}\n\n\t\t\tif (cr_ptr != buffer){\n\t\t\t\tcopy_bytes = (int)cr_ptr - (int)buffer;\n\t\t\t\tmemcpy(buffer, cr_ptr, buffer_len - copy_bytes);\n\t\t\t\tdest_ptr -= copy_bytes;\n\t\t\t}\n\t\t}\n\n\t\t//OutputDebugString (\"Wincomm - End of outer do loop.\\n\");\n\t}while(cr_ptr);\n\n\n\t/*\n\t** Terminate the string at the first CR character as this is what Greenleaf does\n\t*/\n\tif (strchr(buffer, 13)){\n\t\t//OutputDebugString (\"Truncating result string.\\n\");\n\t\t*(strchr(buffer, 13)) = 0;\n\t}\n\n\t//sprintf (abuffer, \"Wincomm - returning remaining delay of %d.\\n\", timer.Time());\n\t//OutputDebugString (abuffer);\n\treturn (timer.Time());\n}\n\n\n\n\n/***********************************************************************************************\n * WMC::Dial_Modem -- issue an 'ATD' command to the modem                                      *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    string - number to dial                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: Use Set_Modem_Dial_Type to choose pulse or tone dialling                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:32PM ST : Created                                                              *\n *=============================================================================================*/\nvoid WinModemClass::Dial_Modem(char *dial_number)\n{\n\tchar\tdial_string[80];\n\n\t/*\n\t** Create the dial command to send to the modem\n\t*/\n\tstrcpy (dial_string, \"ATD\");\n\tif (DialingMethod == WC_TOUCH_TONE){\n\t\tstrcat(dial_string, \"T\");\n\t}else{\n\t\tstrcat(dial_string, \"P\");\n\t}\n\n\t/*\n\t** Stick a carriage return on the end\n\t*/\n\tstrcat (dial_string, dial_number);\n\tstrcat (dial_string, \"\\r\");\n\n\t/*\n\t** Write the dial command to the serial port and wait for the write to complete\n\t*/\n\tWrite_To_Serial_Port ((unsigned char*)dial_string, strlen(dial_string));\n\tWait_For_Serial_Write();\n}\n\n\n\n\n\n/***********************************************************************************************\n * WMC::Send_Command_To_Modem -- send an 'AT' command to the modem and await a response        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    command string                                                                    *\n *           terminator byte (usually \"\\r\")                                                    *\n *           ptr to buffer to receive modem result code                                        *\n *           length of buffer                                                                  *\n *           timeout delay for waiting for result                                              *\n *           number of times to retry the command                                              *\n *                                                                                             *\n * OUTPUT:   result code                                                                       *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:33PM ST : Created                                                              *\n *=============================================================================================*/\n\nint WinModemClass::Send_Command_To_Modem(char *command, char terminator, char *buffer, int buflen, int delay, int retries)\n{\n\n\tint\t\t\t\ttimes;\n\tunsigned\tchar\ttmp_string[80];\n\tchar\t\t\t\ttmp_buff[80];\n\tchar\t\t\t\tterm_string[2];\n\tint\t\t\t\ttime;\n\n\t/*\n\t** Build the terminator string\n\t*/\n\tterm_string[0]\t= terminator;\n\tterm_string[1]\t= 0;\n\n\t/*\n\t** Create the command from the supplied command and terminator\n\t*/\n\tstrcpy((char*)tmp_string, command);\n\tstrcat((char*)tmp_string, term_string);\n\n\n\t/*\n\t** Flush out any pending characters from the port\n\t*/\n\tunsigned char\tnothing_buff[80];\n\tRead_From_Serial_Port(nothing_buff,80);\n\tSleep (100);\n\tRead_From_Serial_Port(nothing_buff,80);\n\n\n\tfor (times = 0 ; times<retries; times++){\n\n\t\t/*\n\t\t** Write the command to the serial port\n\t\t*/\n//Smart_Printf(\"%s\",tmp_string);\n\t\tWrite_To_Serial_Port (tmp_string, strlen((char*)tmp_string));\n\t\tWait_For_Serial_Write();\n\n\t\t//Delay(120);\n\n\t\t/*\n\t\t** Wait for the result of the command from the modem\n\t\t*/\n\t\tmemset(tmp_buff, 0, 80);\n\t\ttime = Get_Modem_Result(delay, tmp_buff, 80);\n//Smart_Printf(\"%s%s\",tmp_buff,\"\\r\");\n\n\t\t/*\n\t\t** If it is a pretty standard result then just return\n\t\t*/\n\t\tif (!strcmp(tmp_buff,\"0\")) return (MODEM_CMD_0);\n\t\tif (strstr(tmp_buff,\"OK\")) return (MODEM_CMD_OK);\n\t\tif (strstr(tmp_buff,\"ERROR\")) return (MODEM_CMD_ERROR);\n\n\t\t/*\n\t\t** If the result was a 3 digit number then copy it to the users buffer and return OK\n\t\t*/\n\t\tif (strlen(tmp_buff)==3){\n\t\t\tif ( (tmp_buff[0] >= '0' && tmp_buff[0] <='9') &&\n\t\t\t\t  (tmp_buff[1] >= '0' && tmp_buff[1] <='9') &&\n\t\t\t\t  (tmp_buff[2] >= '0' && tmp_buff[2] <='9')) {\n\t\t\t\tstrncpy(buffer, tmp_buff, MIN(buflen, 80));\n\t\t\t\treturn (MODEM_CMD_OK);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** It was a non-standard(ish) result so copy it to the users buffer\n\t\t*/\n\t\tstrncpy(buffer, tmp_buff, MIN(buflen, 80));\n\n\t\t/*\n\t\t** Spurious write for no apparent reason. Well it was there in the DOS version so...\n\t\t*/\n\t\tSleep (100);\n\t\tWrite_To_Serial_Port((unsigned char*)\"\\r\",1);\n\t\tWait_For_Serial_Write();\n\t\tSleep (100);\n\t}\n\n\treturn (ASTIMEOUT);\n}\n\n\n\n/***********************************************************************************************\n * WMC::Set_Echo_Function -- set up the echo function pointer                                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to echo function                                                              *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:35PM ST : Created                                                              *\n *=============================================================================================*/\nvoid WinModemClass::Set_Echo_Function( void ( *func )( char c) )\n{\n\tEchoFunction = func;\n}\n\n\n\n/***********************************************************************************************\n * WMC::Set_Abort_Function -- set up the abort function pointer                                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to abort function                                                             *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:35PM ST : Created                                                              *\n *=============================================================================================*/\nvoid WinModemClass::Set_Abort_Function(int (*func)(void))\n{\n\tAbortFunction = func;\n}\n\n\n/***********************************************************************************************\n * WMC::Get_Port_Handle -- returns a handle to the communications port                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Com port handle                                                                   *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/23/96 1:25PM ST : Created                                                              *\n *=============================================================================================*/\nHANDLE\tWinModemClass::Get_Port_Handle(void)\n{\n\treturn (PortHandle);\n}\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/WINDOWS.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./windows.c 1.12 1994/05/20 15:35:25 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : WINDOWS.C                                *\n *                                                                         *\n *                   Programmer : Everyone                                 *\n *                                                                         *\n *                  Last Update : February 3, 1992   [DRD]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Change_New_Window -- Combined Change_Window and New_Window.           *\n *   Change_Window -- Changes the 'current' window in the system.          *\n *   Fetch_Char -- Gets one undipthonged char from input.                  *\n *   Flush_Line -- Outputs the accumulate text line to screen.             *\n *   In_Char -- Stores (un-dipped) character(s) from input to buffer.      *\n *   New_Window -- Clears the current window to the background color.      *\n *   Set_More_Off -- Turns the 'more' prompting off.                       *\n *   Set_More_On -- Turns the 'more' prompting on.                         *\n *   Set_More_Prompt -- Adjusts the more prompt text for default routine   *\n *   Standard_More_Prompt -- Default more prompt code for Window_Print     *\n *   Window_Int_Print -- Prints an integer to the window.                  *\n *   Window_Print -- Displays and wraps text into a window.                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <ctype.h>\n#include <stdlib.h>\n#include <string.h>\n#include\t<stdio.h>\n#include\t<stdarg.h>\n#include <wwstd.h>\n#include \"ww_win.h\"\n#include <keyboard.h>\n#include\t<font.h>\n#include <dipthong.h>\n\nPRIVATE void Scroll_Window(void);\nPRIVATE void Flush_Line(void);\nPRIVATE void In_Char(char *str);\nPRIVATE char Fetch_Char(void);\n\n\nPRIVATE int ScrollCounter = 0;\t//\tCount of the lines displayed before a pause.\nPRIVATE char Line[84];\t// Staging line buffer.\nPRIVATE int Pos;\t\t\t// Char Position of next free character.\nPRIVATE int PPos;\t\t// Pixel position of next free character.\nPRIVATE int WPos;\t\t// Char position in window.\nPRIVATE char *MainSource;\nPRIVATE char *AltSource;\nPRIVATE char Char[2];\nPRIVATE char Stack;\nPRIVATE char WordWrapFlag = FALSE;\t// flag for a word wrap.\n\nPRIVATE int MoreSpace = 7;\nPRIVATE int MoreFColor = 0;\nPRIVATE int MoreBColor = 0;\n\n\nint WindowColumns=40;\nint WindowLines=25;\nint WindowWidth=40;\nunsigned int WinB=0;\nunsigned int WinC=1;\nunsigned int WinX=0;\nunsigned int WinY=0;\nunsigned int WinCx=0;\nunsigned int WinCy=0;\nunsigned int WinH=25;\nunsigned int WinW=40;\nunsigned int Window=0;\n\nint MoreOn = TRUE;\nchar *TXT_MoreText = \"--More--\";\nvoid (*Window_More_Ptr)(char const *,int,int,int) = Standard_More_Prompt;\n\nextern GraphicViewPortClass *LogicPage;\n/***************************************************************************\n * STANDARD_MORE_PROMPT -- Default more prompt code for Window_Print       *\n *                                                                         *\n *    This is the standard \"<more>\" prompting code that is used by         *\n *    Window_Print when a page is full of text and a pause is desired      *\n *    before the next page of text is printed.  This function is called    *\n *    through the Window_More_Ptr global.                                  *\n *                                                                         *\n * INPUT:   prompt   -- Pointer to ASCII text that will be window printed  *\n *                      at the right margin.                               *\n *                                                                         *\n *          space    -- The number of spaces to allow for the 'more' text. *\n *                                                                         *\n *          fcolor   -- The foreground color to use for the 'more' text.   *\n *                                                                         *\n *          bcolor   -- The background oclor to use for the 'more' text.   *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/29/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Standard_More_Prompt(char const *prompt, int space, int fcolor, int bcolor)\n{\n\tint\tx, y, moresize;\n\n\tmoresize = (space - 1) * (FontWidth+FontXSpacing);\n\tx = ((WinX+WinW) << 3) - moresize;\n\t//y = WinY + ((WinH/FontHeight)-1)*FontHeight;\n\ty = WinY + (WinCy-1) * (FontHeight+FontYSpacing);\n\n\t// Default \"more\" prompter.\n\tLogicPage->Print(prompt, x, y, fcolor ? fcolor : WindowList[Window][WINDOWBCOL], bcolor ? bcolor : WindowList[Window][WINDOWFCOL]);\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Show_Mouse();\n//BG\t}\n\n\t// PWG - have to figure out how to do this in windows library\n\n//\tClear_KeyBuffer();\n//\tGet_Key();\n\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Hide_Mouse(Window);\n//BG\t}\n\n\t// Erase the more prompt prompt.\n\t//\tText_Print(prompt, x, y, WinB, WinB);\n\tLogicPage->Fill_Rect(x, y, x + moresize - 1, y + (FontHeight+FontYSpacing) - 1, (unsigned char)WinB);\n}\n\n\n/***************************************************************************\n * SET_MORE_PROMPT -- Adjusts the more prompt text for default routine     *\n *                                                                         *\n *    Use this routine to control the text of the \"<MORE>\" prompt that     *\n *    the default more prompt routine uses.  This can be useful for        *\n *    foreign language translations.                                       *\n *                                                                         *\n * INPUT:   prompt   -- Pointer to ASCII text that will be window printed  *\n *                      at the right margin.                               *\n *                                                                         *\n *          space    -- The number of spaces to allow for the 'more' text. *\n *                                                                         *\n *          fcolor   -- The foreground color to use for the 'more' text.   *\n *                                                                         *\n *          bcolor   -- The background color to use for the 'more' text.   *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/29/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Set_More_Prompt(char const *prompt, int space, int fcolor, int bcolor)\n{\n\tif (prompt) {\n\t\tTXT_MoreText = (char*)prompt;\n\t\tMoreSpace = space;\n\t\tMoreFColor = fcolor;\n\t\tMoreBColor = bcolor;\n\t}\n\telse {\n\t\tTXT_MoreText = \"<MORE>\";\n\t\tMoreSpace = 7;\n\t\tMoreFColor = MoreBColor = 0;\n\t}\n}\n\n\n/***************************************************************************\n * SET_MORE_ON -- Turns the 'more' prompting on.                           *\n *                                                                         *\n *    Use this routine to turn on the 'more' prompting that Window_Print   *\n *    does.  If you have a custom more function pointer, then that         *\n *    routine will be called, otherwise the library default 'more' prompt  *\n *    will be utilized.                                                    *\n *                                                                         *\n * INPUT:      none                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Set_More_On(void)\n{\n\tMoreOn = TRUE;\n\tScrollCounter = 0;\n}\n\n\n/***************************************************************************\n * SET_MORE_OFF -- Turns the 'more' prompting off.                         *\n *                                                                         *\n *    This routine will turn the 'more' prompting that Window_Print does   *\n *    off.                                                                 *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Set_More_Off(void)\n{\n\tMoreOn = FALSE;\n}\n\n\n/***************************************************************************\n * CHANGE_WINDOW -- Changes the 'current' window in the system.            *\n *                                                                         *\n *    Use this routine to change the 'current' window.  The current window *\n *    is used in Window_Print and some other graphic output routines.      *\n *                                                                         *\n * INPUT:   windnum  -- The window number to change to.                    *\n *                                                                         *\n * OUTPUT:  Returns with the previously current window.                    *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nint Change_Window(int windnum)\n{\n\tint\toldwindow;\n\tint\t*data;\n\n\toldwindow = Window;\n\tWindow = windnum;\n\tdata = &WindowList[windnum][0];\n\n\tWinX = *data++;\n\tWinY = *data++;\n\tWinW = *data++;\n\tWinH = *data++;\n\tWinC = *data++;\n\tWinB = *data++;\n\tWinCx = *data++;\n\tWinCy = *data++;\n\tScrollCounter = 0;\n\tWPos = WinCx / (FontWidth+FontXSpacing);\n\tWindowLines = (WinH-FontYSpacing) / (FontHeight+FontYSpacing);\n\tWindowWidth = WinW << 3;\n\tWindowColumns = WindowWidth / (FontWidth+FontXSpacing);\n\treturn (oldwindow);\n}\n\n\n/***************************************************************************\n * CHANGE_NEW_WINDOW -- Combined Change_Window and New_Window.             *\n *                                                                         *\n *    This is a combo-routine.  It merely combines the Change_Window       *\n *    with the New_Window routines.  It will save some (small) code if     *\n *    you use this routine instead of the two function calls.              *\n *                                                                         *\n * INPUT:   window   -- Window number to change to and clear.              *\n *                                                                         *\n * OUTPUT:  Returns with the previously current window.                    *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nint Change_New_Window(int windnum)\n{\n\tint\toldwindow;\n\n\toldwindow = Change_Window(windnum);\n\tNew_Window();\n\treturn(oldwindow);\n}\n\n\n/***************************************************************************\n * NEW_WINDOW -- Clears the current window to the background color.        *\n *                                                                         *\n *    This routine clears the current window to the background color.  It  *\n *    is used in preparation to Window_Print because it ensures a clean    *\n *    'slate' for the text.                                                *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid New_Window(void)\n{\n\tint\tx,y,w,h;\n\n\tx = WinX << 3;\n\ty = WinY;\n\tw = (WinX + WinW) << 3;\n\th = WinY + WinH;\n\n\tLogicPage->Fill_Rect(x, y, w - 1, h - 1, (unsigned char)WinB);\n\n\tWinCx = WPos = 0;\n\tWinCy = 0;\n\tScrollCounter = 0;\n}\n\n\n/***************************************************************************\n * WINDOW_INT_PRINT -- Prints an integer to the window.                    *\n *                                                                         *\n *    Use this routine to print an integer to the window.  This routine    *\n *    as all other Window printing routines will handle word wrap.         *\n *                                                                         *\n * INPUT:   num   -- The integer to convert to ASCII and print.            *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Window_Int_Print(int num)\n{\n\tWindow_Print(\"%d\", num);\n}\n\n\n/***************************************************************************\n * WINDOW_PRINT -- Displays and wraps text into a window.                  *\n *                                                                         *\n *    This is the general purpos text output routine that will handle      *\n *    word wrap within a window.  It is useful for displaying arbitrary    *\n *    text.  This routine will handle dipthonged text and as such it       *\n *    can be quite useful in saving memory.                                *\n *                                                                         *\n * INPUT:   string   -- String to print.  This can be of ANY length and    *\n *                      can even contain some formatting codes.  The       *\n *                      codes supported are:                               *\n *                                                                         *\n *             KA_SETX        Forces the cursor X position to the value    *\n *                            specified.                                   *\n *                                                                         *\n *             KA_SETY        Forces the cursor Y position to the value    *\n *                            specified.                                   *\n *                                                                         *\n *             KA_MORE        Causes an immediate \"<MORE>\" prompt          *\n *                            regardless of the scroll situation.          *\n *                                                                         *\n *             KA_RETURN      Breaks line and continues output at the      *\n *                            left edge of following line.                 *\n *                                                                         *\n *                                                                         *\n *             KA_FORMFEED    Clears the window and continues printing at  *\n *                            the upper left corner.                       *\n *                                                                         *\n *             KA_SETBKGDCOL  Set the background color with the color      *\n *                            specified by the following byte.             *\n *                                                                         *\n *                                                                         *\n *             KA_SETFORECOL  Set the foreground color with the color      *\n *                            specified by the following byte.             *\n *                                                                         *\n *             KA_TAB         Move the cursor over to the next tabstop.    *\n *                            Tabstops are set every 8 columns.            *\n *                                                                         *\n *             KA_SPCTAB      Insert spaces until the cursor is positioned *\n *                            at the next tabstop.                         *\n *                                                                         *\n *             %s             Replace the \"%s\" with the text pointed to    *\n *                            by the pointer argument passed to the        *\n *                            routine (follows same method a printf).      *\n *                                                                         *\n *             %d             Replace the \"%d\" with an integer ASCII       *\n *                            number of the int passed to the routine.    *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *   07/29/1991 JLB : Added MORE, SETX, and SETY                           *\n *=========================================================================*/\nvoid Window_Print(char const string[], ...)\n{\n\tint\t\toldcx, x, y;\t// Scratch variables.\n\tchar\t\tc;\t\t\t\t\t// Current character.\n\tchar\t\tbuffer[10];\t\t// Working %d buffer.\n\tint\t\told_c, old_b;\t// Original window colors.\n\tva_list\targ;\t\t\t\t// Argument list var.\n\n\n\tva_start(arg, string);\n\n\tWordWrapFlag = FALSE;\t\t\t// initialize word wrap flag.\n\tPos = PPos = 0;\n\tLine[0] = '\\0';\n\tChar[0] = Char[1] = 0;\n\tMainSource = (char*)&string[0];\n\tAltSource = NULL;\n\told_c = WinC;\n\told_b = WinB;\n\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Hide_Mouse(Window);\n//BG\t}\n\n\twhile (TRUE) {\n\n\t\tc = Fetch_Char();\n\n\t\tif (!c) break;\t// Exit on NULL character.\n\n\t\t/*\n\t\t**\tSubstitution commands only work if not already expanding a\n\t\t**\tstring.\n\t\t*/\n\t\tif (!AltSource) {\n\t\t\tif (c == '%') {\n\t\t \t\tswitch(tolower(Char[0])) {\n\t\t\t\t\tcase 's':\n\t\t\t\t\t\tAltSource = va_arg(arg, char*);\n\t\t\t\t\t\tif (AltSource) {\n\t\t\t\t\t\t\tStack = Char[1];\n\t\t\t\t\t\t\tChar[0] = Char[1] = '\\0';\n\t\t\t\t\t\t\tc = Fetch_Char();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'd':\n\t\t\t\t\t\tAltSource = buffer;\n\t\t\t\t\t\tsprintf(buffer, \"%d\", va_arg(arg, int));\n\t\t\t\t\t\tStack = Char[1];\n\t\t\t\t\t\tChar[0] = Char[1] = '\\0';\n\t\t\t\t\t\tc = Fetch_Char();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tswitch(c) {\n\n#if(FALSE)\n\t// these are the positions of foreign language characters\n\t\t\t/*\n\t\t\t** These are characters that shouldn't be window printed because\n\t\t\t**\tthey are currently reserved.\n\t\t\t*/\n\t\t\tcase KA_CTRL_C:\n\t\t\tcase KA_CTRL_D:\n\t\t\tcase KA_CTRL_E:\n\t\t\tcase KA_CTRL_G:\n\t\t\tcase KA_CTRL_J:\n\t\t\tcase KA_CTRL_K:\n\t\t\tcase KA_CTRL_N:\n\t\t\tcase KA_CTRL_O:\n\t\t\tcase KA_CTRL_P:\n\t\t\tcase KA_CTRL_Q:\n\t\t\tcase KA_CTRL_R:\n\t\t\tcase KA_CTRL_T:\n\t\t\tcase KA_CTRL_U:\n\t\t\tcase KA_CTRL_V:\n\t\t\tcase KA_CTRL_W:\n\t\t\tcase KA_CTRL_Z:\n\t\t\tcase KA_CTRL_BACKSLASH:\n\t\t\tcase KA_CTRL_CARROT:\n\t\t\tcase KA_CTRL_UNDERLINE:\n\t\t\t\tbreak;\n#endif\n\t\t\t/*\n\t\t\t**\tForce cursor column to specified X value.\n\t\t\t*/\n\t\t\tcase KA_SETX:\n\t\t\t\tFlush_Line();\n\t\t\t\tWPos  = Fetch_Char();\n\t\t\t\tWPos  = MAX(0, WPos);\n\n\t\t\t\t// WPos is max width char position\n\n\t\t\t\tWPos  = MIN(WindowColumns-1, WPos);\n\t\t\t\tWinCx = WPos * (FontWidth+FontXSpacing);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tForce the cursor to specified Y value.\n\t\t\t*/\n\t\t\tcase KA_SETY:\n\t\t\t\tFlush_Line();\n\t\t\t\tWinCy = Fetch_Char();\n\t\t\t\t//WinCy = MAX(0, WinCy);\n\t\t\t\tWinCy = MIN((long)WindowLines-1, (long)WinCy);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tForce a \"<MORE>\" prompt.\n\t\t\t*/\n\t\t\tcase KA_MORE:\n\t\t\t\tFlush_Line();\n\t\t\t\tif (Window_More_Ptr) {\n//BG\t\t\t\t\tif (LogicPage == SEENPAGE) Window_Show_Mouse();\n\t\t\t\t\tWindow_More_Ptr(TXT_MoreText, MoreSpace, MoreFColor, MoreBColor);\n//BG\t\t\t\t\tif (LogicPage == SEENPAGE) Window_Hide_Mouse(Window);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tClear and home the window cursor.  This is the same\n\t\t\t**\tas New_Window().\n\t\t\t*/\n\t\t\tcase KA_FORMFEED:\n\t\t\t\tNew_Window();\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tMove cursor to start of next line.\n\t\t\t*/\n\t\t\tcase KA_RETURN:\n\t\t\t\tFlush_Line();\n\t\t\t\tScrollCounter++;\n\t\t\t\tWinCx = 0;\n\n#if(FALSE)\n\t\t\t\tif (WinCy >= WindowLines-1) {\n\t\t\t\t\tScroll_Window();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tWinCy++;\n\t\t\t\t}\n#else\n\t  \t\t\tWinCy++;\n#endif\n\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tSet the background color.\n\t\t\t*/\n\t\t\tcase KA_SETBKGDCOL:\n\t\t\t\tFlush_Line();\n\t\t\t\tWinB = Fetch_Char();\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tSet the foreground color.\n\t\t\t*/\n\t\t\tcase KA_SETFORECOL:\n\t\t\t\tFlush_Line();\n\t\t\t\tWinC = Fetch_Char();\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tMove cursor to next column.\n\t\t\t*/\n\t\t\tcase KA_TAB:\n\t\t\t\tFlush_Line();\n\t\t\t\tWPos = ((WPos + 8) & 0xFFF8) - 1;\n\t\t\t\tif (WPos >= WindowColumns) {\n\t\t\t\t\tWPos = 0;\n\t\t\t\t}\n\t\t\t\tWinCx = WPos * (FontWidth+FontXSpacing);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tTab to specified column but add spaces.\n\t\t\t*/\n\t\t\tcase KA_SPCTAB:\n\t\t\t\tFlush_Line();\n\t\t\t\toldcx = WinCx;\n\t\t\t\tx = WinX << 3;\n\t\t\t\ty = WinY + (WinCy * (FontHeight+FontYSpacing));\n\t\t\t\tWPos = ((WPos + 8) & 0xFFF8) - 1;\n\n\t\t\t\tif (WPos >= WindowColumns) {\n\t\t\t\t\tWinCx = WPos = 0;\n\n\t\t\t\t\t// Fill_Rect instead of printing spaces\n\n\t\t\t\t\tLogicPage->Fill_Rect(x + oldcx, y,\n\t\t\t\t\t\t\t\tx + WindowWidth - 1, y + (FontHeight+FontYSpacing) - 1, (unsigned char)WinB);\n\n\t\t\t\t\tScrollCounter++;\n\t\t  \t\t\tWinCy++;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tWinCx = WPos * (FontWidth+FontXSpacing);\n\n\t\t\t\t\t// Fill_Rect instead of printing spaces\n\n\t\t\t\t\tLogicPage->Fill_Rect(x + oldcx, y,\n\t\t\t\t\t\t\t\tx + WinCx - 1, y + (FontHeight+FontYSpacing) - 1, (unsigned char)WinB);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tnext character is a extended value 1-127, but 128 is added\n\t\t\t** for a value 129-255\n\t\t\t*/\n\t\t\tcase KA_EXTEND:\n\t\t\t\tc = 127;\n\n\t\t\t// NOTE: this falls thru to the default case DO NOT MOVE!!!!!\n\n\n\t\t\t/*\n\t\t\t**\tnext character is a literal value 1-127, except 13\n\t\t\t*/\n//\t\t\tcase KA_LITERAL:\n//\t\t\t\tif (c != (char) 127) {\t// check if fell thru from extend case\n//\t\t\t\t\tc = 0;\t\t\t\t\t// set to zero for literal case\n//\t\t\t\t}\n//\t\t\t\tc += Fetch_Char();\n\n\t\t\t// NOTE: this falls thru to the default case DO NOT MOVE!!!!!\n\n\n\t\t\t/*\n\t\t\t**\tNormal character output.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\tPPos += Char_Pixel_Width(c);\t// get pixel location of next char\n\t\t\t\tLine[Pos++] = c;\n\t\t\t\tLine[Pos] = '\\0';\n\n\t\t\t\tif (WinCx + PPos > WindowWidth) {\n\t\t\t\t\tFlush_Line();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is text still pending, then display it before exiting.\n\t*/\n\tif (Pos) Flush_Line();\n\n\t/*\n\t**\tRecord changes in the cursor position.\n\t*/\n\tWindowList[Window][WINDOWCURSORX] = WinCx;\n\tWindowList[Window][WINDOWCURSORY] = WinCy;\n\n\t/*\n\t**\tRestore the window colors to their original values.\n\t*/\n\tWindowList[Window][WINDOWFCOL] = WinC = old_c;\n\tWindowList[Window][WINDOWBCOL] = WinB = old_b;\n\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Show_Mouse();\n//BG\t}\n\n\tva_end(arg);\n}\n\n\n/***************************************************************************\n * SCROLL_WINDOW -- Scrolls the text window up one line.                   *\n *                                                                         *\n *    This will scroll the text window up one line.  It will handle any    *\n *    pausing for \"more\" if the MoreOn flag is set.                        *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine assumes that the LogicPage is the SEENPAGE.    *\n *             If this is not the case, the program may appear to hang     *\n *             if a \"more\" prompt is generated.                            *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void Scroll_Window(void)\n{\n\tint\ty;\t\t// Top pixel row of bottom line of window.\n\n\t/*\n\t**\tPossibly prompt for more text.\n\t*/\n\tif (ScrollCounter >= WindowLines-1 && MoreOn) {\n\t\tScrollCounter = 0;\n\n\t\tif (Window_More_Ptr) {\n//BG\t\t\tif (LogicPage == SEENPAGE) Window_Show_Mouse();\n\t\t\tWindow_More_Ptr(TXT_MoreText, MoreSpace, MoreFColor, MoreBColor);\n//BG\t\t\tif (LogicPage == SEENPAGE) Window_Hide_Mouse(Window);\n\t\t}\n\t}\n\n\t/*\n\t**\tScroll the window up one line.\n\t*/\n\ty = ((WinH / (FontHeight+FontYSpacing)) - 1) * (FontHeight+FontYSpacing);\n\tLogicPage->Blit(*LogicPage,WinX<<3, WinY + (FontHeight+FontYSpacing), WinX<<3, WinY, WinW<<3, WinH - (FontHeight+FontYSpacing) );\n\tLogicPage->Fill_Rect(WinX<<3,\n\t\t\t\tWinY + y,\n\t\t\t\t((WinX+WinW)<<3) - 1,\n\t\t\t\tWinY + WinH - 1,\n\t\t\t\t(unsigned char)WinB);\n}\n\n\n/***************************************************************************\n * FLUSH_LINE -- Outputs the accumulate text line to screen.               *\n *                                                                         *\n *    This will display the accumlated text line to the screen.  It will   *\n *    handle breaking the text line at an appropriate position.            *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void Flush_Line(void)\n{\n\tint\tbreakit, breaksize, breakwidth;\n\tint\tx, y;\t\t\t\t\t// Coordinates of text print.\n\tint\tbreakpoint;\t\t\t// Point to break the line (if possible).\n\tchar\tbreakchar;\t\t\t// Break replace character.\n\tint\tindex;\t\t\t\t// Backward moving index var.\n\n\t/*\n\t** There could be a held <CR> and this is implied by the cursor Y position\n\t** beyond the bottom of the window.  If this is the case, then scroll the\n\t**\twindow and proceed with the line flush.\n\t*/\n\twhile (WinCy >= WindowLines /*&& Pos > 0*/) {\n\t\tScroll_Window();\n\t\tif (WinCy >= WindowLines) WinCy--;\n\t}\n\t//if (WinCy >= WindowLines) WinCy = WindowLines-1;\n\n\tx = (WinX<<3) + WinCx;\n\ty = WinY + (WinCy*(FontHeight+FontYSpacing));\n\n\tbreakwidth = WindowWidth;\n//\tif (ScrollCounter >= WindowLines - 1 && MoreOn) {\n//\t\tbreakwidth -= (MoreSpace * (FontWidth+FontXSpacing));\t\t// use maximum font width\n//\t}\n\n\t/*\n\t**\tTry to break the line at the last space IF the line has reached the edge\n\t**\tof the window.\n\t*/\n\tbreakpoint = Pos;\n\tbreaksize = PPos;\n\tif (WinCx + breaksize > breakwidth) {\n\n\t\t/*\n\t\t**\tSince the text WILL spill past the edge of the window, determine the\n\t\t**\tpoint where the break should occur.  If this line is ready for the <MORE>\n\t\t**\tprompt, then breaking must account for the <MORE> text.\n\t\t*/\n\t\tif (ScrollCounter >= WindowLines - 1 && MoreOn) {\n\t\t\tbreakwidth -= (MoreSpace * (FontWidth+FontXSpacing));\t\t// use maximum font width\n\t\t}\n\t\tbreakwidth -= WinCx;\n\n\t\tbreakit = 0;\n\t\tfor (index = breakpoint - 1; index > 0; index--) {\n\t\t\tbreakchar = Line[index];\n\t\t\tbreaksize -= Char_Pixel_Width(breakchar);\n\n\t\t\t// only once, find largest text that can fit on the line\n\t\t\tif (!breakit) {\n\t\t\t\t// was this the char that went past the right edge\n\t\t\t\tif (breaksize <= breakwidth) {\n\t\t\t\t\tbreakit = index;\t// save this position if there is no spaces\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// after largest text is found then look for a space to break on\n\t\t\tif (breakit && breakchar == KA_SPACE) {\n\t\t\t\tbreakpoint = index;\n\t\t\t\tWordWrapFlag = FALSE; // word will start at beginning of next line\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tException: When the current text buffer cannot be broken at a logical\n\t\t**\tplace AND the text is starting past the left margin, THEN there is\n\t\t**\tan implied break between the previous text output and this one.\n\t\t**\tOutput the current text on the next line left margin.\n\t\t*/\n\t\tif (!index) {\n\t\t\tif (WinCx && !WordWrapFlag) {\n\t\t\t\tbreakpoint = breaksize = 0;\t\t// Continue text on next line.\n\t\t\t\tWordWrapFlag = TRUE;\t\t// indicate a word continuation.\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbreakpoint = breakit;\t// Just print as much as possible.\n\t\t\t}\n\t\t}\n\t}\n\n\tbreakchar = Line[breakpoint];\n\tLine[breakpoint] = '\\0';\n\n\tLogicPage->Print(Line, x, y, WinC, WinB);\n\tWinCx += breaksize;\t\t\t\t\t// add size of text string printed.\n\n\tLine[breakpoint] = breakchar;\n\tif (breakchar == KA_SPACE) {\t\t// take out a space between words.\n\t\tbreakpoint++;\n\t}\n\n\t// take out another space for double spacing after end of sentence.\n\tif (Line[breakpoint] == KA_SPACE) {\n\t\tbreakpoint++;\n\t}\n\n\tstrcpy(Line, &Line[breakpoint]);\n\tPos = strlen(Line);\n\tPPos = String_Pixel_Width(Line);\n\n\t/*\n\t**\tIf at this point there is still text in the buffer, then flushing has\n\t**\tnot been completed.  Scroll to next line and repeat the text flushing\n\t**\tprocess.\n\t*/\n\tif (Pos || WinCx >= WindowWidth) {\n\t\tWinCx = WPos = 0;\n\t\t#if(FALSE)\n\t\t\tif (WinCy >= WindowLines-1) {\n\t\t\t\tScroll_Window();\n\t\t\t} else {\n\t\t\t\tWinCy++;\n\t\t\t}\n\t\t#else\n\t\t\tWinCy++;\n\t\t#endif\n\t\tFlush_Line();\n\t\tScrollCounter++;\t// must be done after flush line for correct counting\n\t}\n}\n\n\n/***************************************************************************\n * IN_CHAR -- Stores (un-dipped) character(s) from input to buffer.        *\n *                                                                         *\n *    Use this routine to fetch the next character from the input stream.  *\n *    If the character was dipthonged, then it will be broken into its     *\n *    component ASCII characters and stored in the specified location.     *\n *    This is the core character stream reading code.                      *\n *                                                                         *\n * INPUT:   str   -- char pointer to the position to store the character(s)*\n *                   fetched from the input stream.                        *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void In_Char(char *str)\n{\n\tchar\tc;\t\t// Character to return.\n\tchar\tnext;\t// Following character (if any).\n\n\tc = next = '\\0';\n\n\t/*\n\t**\tFetch a raw byte from the input stream.\n\t*/\n\tif (AltSource) {\n\t\tif (*AltSource == '\\0') {\n\t\t\tAltSource = NULL;\n\t\t\tc = Stack;\n\t\t} else {\n\t\t\tc = *AltSource++;\n\t\t}\n\t}\n\n\tif (!c && MainSource) {\n\t\tif (*MainSource == '\\0') {\n\t\t\tMainSource = NULL;\n\t\t} else {\n\t\t\tc = *MainSource++;\n\t\t}\n\t}\n\n\t/*\n\t**\tConvert a dipthong character into it's component\n\t**\tASCII characters.\n\t*/\n\tif (c & 0x80) {\n\t\tc &= 0x7F;\n\t\tnext = c & (char)0x07;\n\t\tc = (char)((c & (char)0x78) >> 3);\n\n\t\tnext = Dipthong[c][next];\t// Dipthong character.\n\t\tc = Common[c];\t\t\t\t// Common character.\n\t}\n\n\t*str++ = c;\n\t*str = next;\n}\n\n\n/***************************************************************************\n * FETCH_CHAR -- Gets one undipthonged char from input.                    *\n *                                                                         *\n *    This routine will fetch one character from the input stream.  The    *\n *    character has already been un-dipthonged.  It is a straight ASCII    *\n *    character.  This routine ensures that if the next character in the   *\n *    input stream needs to be examined, it is available in Char[0].       *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  Returns next character in the input stream (ASCII).  If NULL   *\n *          is returned, then this indicates the end of the input stream.  *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE char Fetch_Char(void)\n{\n\tchar\tc;\t\t// Character to return.\n\n\tif (!Char[0]) {\n\t\tIn_Char(&Char[0]);\n\t}\n\n\tc = Char[0];\n\tChar[0] = Char[1];\n\tChar[1] = '\\0';\n\n\tif (!Char[0]) {\n\t\tIn_Char(&Char[0]);\n\t}\n\n\treturn (c);\n}\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/WINHIDE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./winhide.c 1.10 1994/05/20 15:35:50 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Dune                                     *\n *                                                                         *\n *                    File Name : WINHIDE.C                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : May 30, 1991                             *\n *                                                                         *\n *                  Last Update : August 16, 1991   [JLB]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Window_Hide_Mouse -- Hides the mouse when it enters a window.         *\n *   Window_Show_Mouse -- Shows the mouse after Window_Hide_Mouse hides it.*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t<wwstd.h>\n#include\t<keyboard.h>\n#include \"ww_win.h\"\n\n\n#if(IBM)\n/***************************************************************************\n * WINDOW_HIDE_MOUSE -- Hides the mouse when it enters a window.           *\n *                                                                         *\n *    This is an intelligent form of Conditional_Hide_Mouse().  It will    *\n *    hide the mouse if it enters the specified window (see the            *\n *    WindowList global).                                                  *\n *                                                                         *\n * INPUT:   window   - Window number.                                      *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   Just like Conditional_Hide_Mouse(), this function is NOT    *\n *             nestable.                                                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/26/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Window_Hide_Mouse(int window)\n{\n\tint\tx,y,w,h;\n\n\tx = WindowList[window][WINDOWX]<<3;\n\ty = WindowList[window][WINDOWY];\n\tw = WindowList[window][WINDOWWIDTH]<<3;\n\th = WindowList[window][WINDOWHEIGHT];\n//\tConditional_Hide_Mouse(x,y,x+w-1,y+h-1);\n}\n\n\n/***************************************************************************\n * WINDOW_SHOW_MOUSE -- Shows the mouse after Window_Hide_Mouse hides it.  *\n *                                                                         *\n *    This routines will show the mouse after Window_Hide_Mouse has hidden *\n *    it.                                                                  *\n *                                                                         *\n * INPUT:      none                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/22/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Window_Show_Mouse(void)\n{\n//\tConditional_Show_Mouse();\n}\n#endif\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/WPROFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Library profiler                                             *\n *                                                                                             *\n *                    File Name : WPROFILE.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 11/17/95                                                     *\n *                                                                                             *\n *                  Last Update : November 20th 1995 [ST]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *                                                                                             *\n *  New System                                                                                 *\n * ~~~~~~~~~~~                                                                                 *\n *                                                                                             *\n *  The new profiler system creates a seperate thread and then starts a timer off there. The   *\n *  timer in the second thread uses GetThreadContext to sample the IP address of each user     *\n *  thread. This system has the advantage of being able to sample what is happening in all the *\n *  threads we own not just the main thread. Another advantage is that it doesnt require a     *\n *  major recompilation.                                                                       *\n *  The disadvantage is that we dont really know what is going on when the IP is outside the   *\n *  scope of our threads - We could be in direct draw, direct sound or even something like the *\n *  VMM and there is no way to tell.                                                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n *  Old System                                                                                 *\n * ~~~~~~~~~~~                                                                                 *\n *                                                                                             *\n *  The profiler works by using the function prologue and epilogue hooks available in Watcom   *\n *  to register the current functions address in a global variable and then sampling the       *\n *  contents of the variable using a windows timer which runs at up to 1000 samples per second.*\n *                                                                                             *\n *  Compile the code to be sampled with the -ep and -ee flags to enable the prologue (__PRO)   *\n *  and epilogue (__EPI) calls to be generated.                                                *\n *  At the beginning of the section to be profiled (just before main loop normally) call the   *\n *  Start_Profiler function to start sampling. At the end of the section, call Stop_Profiler   *\n *  which will stop the timer and write the profile data to disk in the PROFILE.BIN file.      *\n *                                                                                             *\n *  Use PROFILE.EXE to view the results of the session.                                        *\n *                                                                                             *\n *  The addition of prologue and epilogue code will slow down the product and the profiler     *\n *  allocates a huge buffer for data so it should not be linked in unless it is going to be    *\n *  used.                                                                                      *\n *                                                                                             *\n *  The advantage of the prologue/epilogue approach is that all samples represent valid        *\n *  addresses within our code so we get valid results we can use even when the IP is in system *\n *  code.                                                                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *  Start_Profiler -- initialises the profiler data and starts gathering data                  *\n *  Stop_Profiler -- stops the timer and writes the profile data to disk                       *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#define WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#include <windows.h>\n#include <windowsx.h>\n#include <wwstd.h>\n#include <rawfile.h>\n#include <file.h>\n#include \"profile.h\"\n#include <vdmdbg.h>\n#include <timer.h>\n\n#define PROFILE\n\nextern \"C\"{\n#ifdef PROFILE\nunsigned\tProfileList\t[PROFILE_RATE*MAX_PROFILE_TIME];\n#else\nunsigned\tProfileList\t[2];\n#endif\nunsigned\tProfilePtr;\n}\n\nextern \"C\" void Old_Profiler_Callback ( UINT, UINT , DWORD, DWORD, DWORD );\nextern \"C\" void New_Profiler_Callback (void);\nextern \"C\" {\n\textern unsigned ProfileFunctionAddress;\n}\n\nunsigned long\tProfilerEvent;\t\t//Handle for profiler callback\nunsigned long\tProfilerThread;\t//Handle for profiler thread\n\n\nHANDLE\t\tCCThreadHandle;\nCONTEXT\tThreadContext;\n\n\n#if (PROFILE_SYSTEM == NEW_PROFILE_SYSTEM)\n\n/***********************************************************************************************\n * Thread_Callback -- gets the IP address of our thread and registers it                       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Windows timer callback parms - not used                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/2/96 6:37AM ST : Created                                                               *\n *=============================================================================================*/\n\nvoid CALLBACK Thread_Callback (UINT,UINT,DWORD,DWORD,DWORD)\n{\n\tThreadContext.ContextFlags = VDMCONTEXT_CONTROL;\n\tif (!InTimerCallback){\n\t\tGetThreadContext ( CCThreadHandle , &ThreadContext );\n\t}else{\n\t\tGetThreadContext (TimerThreadHandle , &ThreadContext);\n\t}\n\n\tProfileFunctionAddress = ThreadContext.Eip;\n\tNew_Profiler_Callback();\n}\n\n\n/***********************************************************************************************\n * Profile_Thread -- this is the thread our profiler runs in. It just starts off a timer and   *\n *                   then buggers off into an infinite message loop. We shouldnt get messages  *\n *                   here as this isnt our primary thread                                      *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/2/96 6:39AM ST : Created                                                               *\n *=============================================================================================*/\nvoid Profile_Thread (void)\n{\n\tMSG msg;\n\tProfilerEvent = timeSetEvent (1000/PROFILE_RATE , 1 , Thread_Callback , 0 , TIME_PERIODIC);\n\t//ProfilerEvent = timeSetEvent (100 , 1 , Thread_Callback , 0 , TIME_ONESHOT);\n\tdo  {\n\t\tGetMessage(&msg,NULL,0,0);\n\t} while(1);\n}\n\n#endif //(PROFILE_SYSTEM == OLD_PROFILE_SYSTEM)\n\n\n/***********************************************************************************************\n * Start_Profiler -- initialises the profiler system and starts sampling                       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: There may be a pause when sampling starts as Win95 does some VMM stuff            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:12PM ST : Created                                                             *\n *=============================================================================================*/\n\nvoid __cdecl Start_Profiler (void)\n{\n#ifdef PROFILE\n\tif (!ProfilerEvent){\n\t\tmemset (&ProfileList[0],-1,PROFILE_RATE*MAX_PROFILE_TIME*4);\n\t}\n\n\tProfile_Init();\n\n\tif (!ProfilerEvent){\n\n#if (PROFILE_SYSTEM == OLD_PROFILE_SYSTEM)\n\t\t/*\n\t\t** Old profile system - just set up a timer to monitor the global variable based on\n\t\t** the last place __PRO was called from\n\t\t*/\n\t\tProfilerEvent = timeSetEvent (1000/PROFILE_RATE , 1 , (void CALLBACK (UINT,UINT,DWORD,DWORD,DWORD))Old_Profiler_Callback , 0 , TIME_PERIODIC);\n#else\n\t\t/*\n\t\t** New profile system - create a second thread that will do all the profiling\n\t\t** using GetThreadContext\n\t\t*/\n\t\tif ( DuplicateHandle( GetCurrentProcess(), GetCurrentThread() , GetCurrentProcess() ,&CCThreadHandle , 0 , TRUE , DUPLICATE_SAME_ACCESS) ){\n\t\t\tProfilerEvent= (unsigned)CreateThread(NULL,2048,(LPTHREAD_START_ROUTINE)&Profile_Thread,NULL,0,&ProfilerThread);\n\t\t}\n#endif\n\n\t}\n\n#else\n\tProfilerEvent = 0;\n#endif\n\n}\n\n\n\n/***********************************************************************************************\n * Stop_Profiler -- stops the sampling timer and writes the colledted data to disk             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: Writes to file PROFILE.BIN                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/20/95 5:13PM ST : Created                                                             *\n *=============================================================================================*/\n\nvoid __cdecl Stop_Profiler (void)\n{\n\tif (ProfilerEvent){\n\n#if (PROFILE_SYSTEM == OLD_PROFILE_SYSTEM)\n\t\t//\n\t\t// Old system - just remove the timer event\n\t\t//\n\t\ttimeKillEvent(ProfilerEvent);\n#else\n\t\t//\n\t\t// New system - kill the profiling thread\n\t\t//\n\t\tTerminateThread((HANDLE)ProfilerThread,0);\n#endif\n\n\t\tProfilerEvent=NULL;\n\n\t\tProfile_End();\n\n\t\tint handle = Open_File ( \"profile.bin\" , WRITE );\n\t\tif (handle != WW_ERROR){\n\t\t\tWrite_File (handle , &ProfileList[0] , ProfilePtr*4);\n\t\t\tClose_File (handle);\n\t\t}\n\t}\n}\n\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/WRITELBM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/wwlib32/file/rcs/writelbm.cpp 1.1 1994/04/20 14:38:57 scott_bowen Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Write LBM File                           *\n *                                                                         *\n *                    File Name : writelbm.c                               *\n *                                                                         *\n *                   Programmer : Scott Bowen                              *\n *                                                                         *\n *                   Start Date :  November 18, 1991                       *\n *                                                                         *\n *                  Last Update : November 19, 1991   [SB]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Get_Line -- convert one plane of one row to a packed plane            *\n *   Write_BMHD -- writes out the bit map header (LocalHeader)             *\n *   Write_Body -- writes out compressed data in an LBM file               *\n *   Write_CMAP -- Writes out CMAP (palette) information                   *\n *   Write_LBM_File -- Writes out a file in LBM format                     *\n *   Write_Row -- compresses and writes a row plane to .lbm file           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n// At the end of this file there is an IFF definition for a .LBM file.\n\n#include \"iff.h\"\n#include \"file.h\"\n#include <wwstd.h>\n#include <stdio.h>\n#include <string.h>\n\n\n\t// A BitMapHeader is stored in a BMHD chunk.  This structure MUST be an even size\ntypedef struct {\n    unsigned short w, h;\t\t\t\t\t\t\t// raster width & height in pixels \n    unsigned short x, y;\t\t\t\t\t\t\t// position for this image\n    unsigned char planes;\t\t\t\t\t\t\t// # source bitplanes \n    unsigned char masking;\t\t\t\t\t\t\t// masking technique \n    unsigned char compression;\t\t\t\t\t// compression algoithm\n    unsigned char pad1;\t\t\t\t\t\t\t\t// UNUSED.  For consistency, put 0 here.\n    unsigned short transcolor;\t\t\t\t\t// transparent \"color number\"\n    unsigned char xaspect, yaspect;\t\t\t\t// aspect ratio, a rational number x/y\n    unsigned short pagewidth, pageheight;\t\t// source \"page\" size in pixels\n} BitMapHeaderType;\n\n\n// All values in LocalHeader are always the same except planes.  This is set in Write_BMHD\n// the short values must be in low-high order for compatibility.\n\nPRIVATE BitMapHeaderType LocalHeader = {\n\t0x4001, 0xc800, 0, 0, 0, 0,\t\t// width, height, x, y, planes, mask\n\t1,   0, 0xFF00, 5, 6, \t\t\t\t// compress, pad1, transcolor, xasptect, yaspect\n\t0x4001,\t0xC800 };\t\t\t\t\t// pagewidth, pageheight\n\n\t\n\t// Used to verify that the write of the header was valid\n#define BM_HEADER_SIZE\t\t(((sizeof(BitMapHeaderType) + 1) & 0xFFFE) + 8L)\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE long Write_BMHD(int lbmhandle, int bitplanes);\nPRIVATE long Write_CMAP(int lbmhandle, unsigned char * palette, int bitplanes);\nPRIVATE long Write_BODY(int lbmhandle, BufferClass& buff, int bitplanes);\nPRIVATE long Write_Row(int lbmhandle, unsigned char *buffer);\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * WRITE_LBM_FILE -- Writes out a file in LBM format                       *\n *                                                                         *\n * INPUT:  int lbmhandle -- lbm file handle already opened by caller      *\n *         BufferClass buff -- buff where MCGA picture is                     *\n *         int bitplane -- number of bitplanes to convert to              *\n *         char *palette -- pointer to palette for buff                    *\n *                                                                         *\n * OUTPUT: Returns BOOL -- successfull or not                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/18/1991  SB : Created.                                             *\n *=========================================================================*/\n\nPUBLIC BOOL Write_LBM_File(int lbmhandle, BufferClass& buff, int bitplanes, unsigned char *palette)\n{\n\tlong filesize;\n\n\n\tSeek_File(lbmhandle, 0L, SEEK_SET);\t\t\t\t\t\t// goto beginning of file \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\tWrite_File(lbmhandle, \"FORM????ILBM\", 12L);\t\t\t// First 12 bytes of all .lbm files \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// size is unkown so write ????\n\tfilesize = 12L; \t\t\t\t\t\t\t\t\t\t\t\t// 4 bytes for \"ILBM\" \n\n\tfilesize += Write_BMHD(lbmhandle, bitplanes);\t\t// write out BMHD (fixed size)\n\tfilesize += Write_CMAP(lbmhandle, palette, bitplanes);\t// write out CMAP \n\n\t\t// Write out the body, or compressed picture image.  This size will depend\n\t\t// on the compression, but the value passed back is what the compressor\n\t\t// assumed was written to file\n\n\tfilesize += Write_BODY(lbmhandle, buff, bitplanes);\n\n\t\t// Verify that we were able to write out the file without running out of space\n\tif (Seek_File(lbmhandle, 0L, SEEK_END) != filesize) {\n\t\treturn(FALSE);\n\t}\n\n\tSeek_File(lbmhandle, 4L, SEEK_SET);\t\t\t\t\t\t// goto beginning of file \n\tfilesize = Reverse_Long(filesize - 8L);\t\t\t\t// - 8 because of \"FORM\" + WORD (size)\n\tWrite_File(lbmhandle, (char *) &filesize, 4L);\t\t// patch in filesize \n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * WRITE_BMHD -- writes out the bit map header (LocalHeader)               *\n *                                                                         *\n * INPUT:  int lbmhandle -- file handle for lbm file                      *\n *         int pitplanes -- number of bitplanes to write out              *\n *                                                                         *\n * OUTPUT: long number of bytes hopefully written out to .LBM file         *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/19/1991  SB : Created.                                             *\n *=========================================================================*/\nPRIVATE long Write_BMHD(int lbmhandle, int bitplanes)\n{\n\tlong size;\n\t\n\tWrite_File(lbmhandle, \"BMHD\", 4L);\t\t\t\t\t// write out chunk title \n\tsize = Reverse_Long(sizeof(LocalHeader));\t\t\t// write out size of LocalHeader chunk\n\tWrite_File(lbmhandle, (char *) &size, 4L);\n\n\tLocalHeader.planes\t= bitplanes;\t\t\t\t\t// only nonconstant value in LocalHeader\n\n\t\t// Make sure size is even. Return 8 = \"BMHD\" + size of the bitmap header structure\n\n\treturn(Write_File(lbmhandle, (char *) &LocalHeader,\n\t                 (sizeof(LocalHeader) + 1) & 0xFFFE) + 8L);\n}\n\n\n/***************************************************************************\n * WRITE_CMAP -- Writes out CMAP (palette) information                     *\n *                                                                         *\n *                                                                         *\n * INPUT:  int lbmhandle -- file handle of lbm file                       *\n *         char * palette -- pointer to paletter information       \t\t\t*\n *         int bitplanes -- used to figure out size of palette            *\n *                                                                         *\n * OUTPUT: long number of bytes that should have been written out to .LBM. *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/19/1991  SB : Created.                                             *\n *=========================================================================*/\n\nPRIVATE long Write_CMAP(int lbmhandle, unsigned char * palette, int bitplanes)\n{\n\tint color, r, g, b, colors;\n\tlong size;\n\tunsigned char *pal_ptr;\n\tchar rgb[3];\n\n\n\tWrite_File(lbmhandle, \"CMAP\", 4L);\t\t\t\t\t\t// write out palette info\n\tcolors = 1 << bitplanes;\t\t\t\t\t\t\t\t\t// colors = 2 to the bitplanes\n\tsize = Reverse_Long(colors * 3L);\t\t\t\t\t\t// size = colors * 3 guns\n\n \tWrite_File(lbmhandle, (char *) &size, 4L);\n\n\tfor (pal_ptr = palette, color = 0; color < colors; color++) { // for each color\n\n\t\tif ((r = *pal_ptr++) != 0) {\t\t\t// DPaint changes allows 0 - 100 for gun values\t\t\n\t\t\tr = (r << 2) | 0x03;\t\t\t\t\t// this must be converted to 0 - 256 for LBM\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t// so LBM_val = (DP_val * 4) | 3 if DP_val != 0\n\t\tif ((g = *pal_ptr++) != 0) {\t\t\t\n\t\t\tg = (g << 2) | 0x03;\n\t\t}\n\t\tif ((b = *pal_ptr++) != 0) {\n\t\t\tb = (b << 2) | 0x03;\n\t\t}\n\t\trgb[0] = r;\t\t\t\t\t\t\t\t\t// assign gun values to an array to write out\n\t\trgb[1] = g;\n\t\trgb[2] = b;\n\t\t\n\t\tWrite_File(lbmhandle, rgb, 3L);\n\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// size = colors * 3\n\treturn(((colors << 1) + colors) + 8L);\t// total size of CMAP 8 = \"CMAP\" + WORD (size)\n}\n\n\n/***************************************************************************\n * WRITE_BODY -- writes out compressed data in an LBM file                 *\n *                                                                         *\n * INPUT: int lbmhandle -- file handle of lbm file                        *\n *                                                                         *\n * OUTPUT: long - number of byte written                                   *\n *  \t                                                                     *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/19/1991  SB : Created.                                             *\n *=========================================================================*/\n\nPRIVATE long Write_BODY(int lbmhandle, BufferClass& buff, int bitplanes)\n{\n\tlong bodysize = 0;\n\tlong actualsize;\n\tlong size;\n\tint planebit;\n\tint line, plane;\n\tunsigned char buffer[40];\n\tunsigned char *buffptr;\n\n\tWrite_File(lbmhandle, \"BODY????\", 8L);\t\t// BODY chunk ID, ???? reserved for chuncksize \n\n\tbuffptr = (unsigned char *) buff.Get_Buffer();\t\t\t\t\t\t// point to beginning of buff\n\n\tfor (line = 0; line < 200; line++) {\n\t\tplanebit = 1;\t\t\t\t\t\t\t\t\t\t\t// start with bit 1 set \n\n\t\tfor (plane = 0; plane < bitplanes; plane++) {\n\t\t\tPack_2_Plane(buffer, buffptr, planebit);\t// convert to planar\n\t\t\tbodysize += Write_Row(lbmhandle, buffer); // write to to the BODY in the LBM\n\n\t\t\tplanebit <<= 1;\t\t\t\t\t\t\t\t\t// set next bit\n\t\t}\n\n\t\tbuffptr += 320;\t\t\t\t\t\t\t\t\t\t// row size is 320\n\t}\n\n\tactualsize = bodysize + (bodysize&0x01);\n\n\tif (actualsize != bodysize) {\n\t\tWrite_File(lbmhandle, buffer, 1);\t\t// Padd the block.\n\t}\n\n\tSeek_File(lbmhandle, -(actualsize + 4L), SEEK_CUR);\t\t// Patch in chunksize\n\tsize = Reverse_Long(bodysize);\n\tWrite_File(lbmhandle, (char *) &size ,4L);\t\t\t\n\n\treturn(actualsize + 8L);\t\t// total size of BODY,  \"BODY????\" = 8 bytes\n}\n\n/***************************************************************************\n * WRITE_ROW -- compresses and writes a row plane to .lbm file             *\n *                                                                         *\n * INPUT:  int lbmhandle -- lbm file handle                               *\n *         unsigned char *buffer -- pointer to buffer to be written out            *\n *                                                                         *\n * OUTPUT: long size of chunk that should have been written out            *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/19/1991  SB : Created.                                             *\n *=========================================================================*/\n// this algorithm was taken from WILBM.c written by EA that was in the\n// 1985 yearbook.  This is the compression method that DP.EXE uses.\n// Change only if DP.EXE changes.\n\nPRIVATE long Write_Row(int lbmhandle, unsigned char *buffer)\n{\n\tint i;\n\tint chunksize = 0;\n\tint dataLength = 40;\t  \t\t\t\t\t// 320 rows / 8 ( 1 plane per row)\n\tunsigned char repCode, current, curr_plus_2;\n\tunsigned char *buffptr;\n\n\twhile (dataLength) {\n\n  \t\t// If at least 2 more bytes and they are equal, then replicate \n\n\t\tif ((dataLength >= 2) && (buffer[0] == buffer[1])) {\n\t\t\tbuffptr = buffer;\n\t\t\tfor (i = 0; (i <= 128) &&  (i < (dataLength - 1)); i++) {\n\t\t\t\tif (*buffptr != buffptr[1]) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbuffptr++;\n\t\t\t}\n\t\t\ti++;\n\t\t\trepCode = -i + 1;\n\t\t\tWrite_File(lbmhandle, &repCode, 1L);\t\t\t// Write count as -count+1\n\t\t\tWrite_File(lbmhandle, buffer,   1L);\t\t\t// Write byte to replicate\n\t\t\tbuffer += i;\n\t\t\tdataLength -= i;\n\t\t\tchunksize  += 2;\n\n\t\t}\n\t\telse { // Copy literally till 3 byte run or two 2 byte runs found \n\n\t\t\tfor (i = 0; (i <= 128) && (i < dataLength); i++) {\n\t\t\t\tcurrent     = buffer[i];\n\t\t\t\tcurr_plus_2 = buffer[i + 2];\n\n\t\t\t\tif (i == dataLength - 1)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (current != buffer[i + 1])\n\t\t\t\t\tcontinue;\n\t\t\t\tif (i == dataLength - 2)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (current == curr_plus_2)\n\t\t\t\t\tbreak;\n\t\t\t\tif (i == dataLength - 3)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (curr_plus_2 == buffer[i + 3])\n\t\t\t\t\t break;\n\t\t\t}\n\t\t\trepCode = i - 1;\n\t\t\tWrite_File(lbmhandle, &repCode, 1L);\t\t\t// Write count as count-1 \n\t\t\tWrite_File(lbmhandle, buffer, (long) i);\t\t// Write 'count' bytes\n\t\t\tbuffer += i;\n\t\t\tdataLength -= i;\n\t\t\tchunksize += i + 1;\n\t\t}\n\t}  // end while\n\n\treturn(chunksize);\n}\n\n\n#if(FALSE)\n\nThis is a definition of a DPII .LBM file.\nBelow this definition are differences in DPIIe .LMB files.\n\nCreated by : Scott K. Bowen Nov 18, 1991\n\t\nStart with .LBM to read definition :\n\n.LBM\t\t-> \"FORM\" + FILESIZE + \"ILMB\" + CHUNKS\n\nBITPLANES\t-> (word) // number of bit planes used\nBLUE\t\t\t-> (byte) // blue color gun value\nBMHD \t\t\t-> \"BMHD\" + CHUNKSIZE + CONTEXT\nBODY\t\t\t->\n\nCHUNKS\t\t-> BMHD | BODY | CMAP | DPPV | CRNG | ????\nCHUNKSIZE\t-> (long) // size of chunk not including header or size.\nCMAP\t\t\t-> \"CMAP\" + CHUNKSIZE + PALETTE_INFO\nCOMPRESS_METHOD -> (byte) // compression method used\nCONTEXT\t\t-> WIDTH + HEIGHT + POSX + POSY + #_BITPLANES + MASKING +\n\t\t\t\t   COMPRESS_METHOD + PAD + TRANS_COL + XASPECT + YASPECT +\n\t\t\t\t\tPAGEWIDTH + PAGEHEIGHT\nCRNG\t\t\t-> // we do not use\n\nDPPV\t\t\t-> // we do not use\n\nFILESIZE\t\t-> (long)   //size of file minus (sizeof(FORM) + sizeof(FILESIZE)\n\nGREEN\t\t\t-> (byte) // green color gun value\n\nHEIGHT\t\t-> (word) // of picture\n\nMASKING\t\t-> (byte) // masking type ?\n\nNUM_COLORS\t-> //number of colors used depending on format\n\nPAGE_WIDTH\t-> (word) // width of page\nPAGE_HEIGHT\t-> (word) // height of page\nPALETTE_INFO-> (RED+GREEN+BLUE) @ NUM_COLORS\nPAD \t\t\t-> (byte) // not used.  used as a padding\nPOSX \t\t\t-> (word) // staring position\nPOSY\t\t\t-> (word) // staring position\n\nRED\t\t\t-> (byte) // red color gun value\n\nTRANS_COL\t-> (word) // transparrent color\n\nWIDTH\t\t\t-> (word) // of picture \n\nXASPECT\t\t-> (byte) // x aspect ratio\n\nYASPECT\t\t-> (byte) // y aspect ratio\n\n????\t\t\t-> // other possibilities\n\n\nDifferences in DPII enhance version\n\n.LBM \t\t-> \"FORM\" + FILESIZE + \"PBM \" + CHUNKS\nDPPV\t\t-> DPPS\t\t// uses dpps instead of dppv\nCHUNKS\t\t-> + TINY\t// add these to old definition\n \n\n\n\n#endif\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/WRITEPCX.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : iff                                      *\n *                                                                         *\n *                    File Name : WRITEPCX.CPP                             *\n *                                                                         *\n *                   Programmer : Julio R. Jerez                           *\n *                                                                         *\n *                   Start Date : May 2, 1995                              *\n *                                                                         *\n *                  Last Update : May 2, 1995   [JRJ]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * int Save_PCX_File (char* name, GraphicViewPortClass& pic, char* palette)*\n *= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n#include  <wwlib32.h>\n#include \"filepcx.h\"\n#include <wwmem.h>\nstatic void Write_Pcx_ScanLine ( int file_handle , int scansize , char * ptr );\n\n\n/***************************************************************************\n * WRITE_PCX_FILE -- Write the data in ViewPort to a pcx file              *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:  name is a NULL terminated string of the fromat [xxxx.pcx]\t\t\t*\n *\t\t\t  pic\t is a pointer to a GraphicViewPortClass or to a \t\t\t\t*\n *\t\t\t\t\t GraphicBufferClass holding the picture. \t\t\t\t\t\t\t*\n *        palette is a pointer the the memry block holding the color \t\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *              palette of the picture.                                    *\n *                                                                         *\n * OUTPUT: FALSE  if the function fails zero otherwise             \t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/04/1995 JRJ : Created.                                             *\n *   08/01/1995 SKB : Copy the palette so it is not modified.              *\n *=========================================================================*/\nint Write_PCX_File (char* name, GraphicViewPortClass& pic, unsigned char* palette )\n{\n \tunsigned char palcopy[256 * 3];\n\tunsigned     i ;\n\tunsigned\t   width ;\n\tint \t      file_handle ;\n\tint\t\t\t\tVP_Scan_Line ;\n\tchar\t     * ptr ;\n\tRGB  \t\t  * pal ;\n\tGraphicBufferClass\t* Graphic_Buffer ;\n\tPCX_HEADER   header = { 10 , 5 , 1 , 8 , 0 , 0 , 319 , 199 ,\n\t\t\t\t\t\t\t\t\t320 , 200 , { 0 } , 0 , 1 , 320 , 1 , {0} } ;\n\n\t// Open file name\n\tfile_handle = Open_File ( name , WRITE ) ;\n\tif ( file_handle == ERROR ) return FALSE ;\n\n\n\theader.width  = pic.Get_Width() - 1 ;\n\theader.height = pic.Get_Height() - 1 ;\n\theader.byte_per_line = pic.Get_Width() ;\n\tWrite_File ( file_handle, & header , sizeof (PCX_HEADER)) ;\n\n\tVP_Scan_Line = pic.Get_Width()\t+ pic.Get_XAdd();\n\tGraphic_Buffer = pic.Get_Graphic_Buffer() ;\n\tptr = ( char * ) Graphic_Buffer->Get_Buffer() ;\n\tptr += ( (pic.Get_YPos() * VP_Scan_Line) + pic.Get_XPos() );\n\n\tfor ( i = 0 ; i < header.height + 1 ; i ++ )\n   \tWrite_Pcx_ScanLine ( file_handle , header.byte_per_line, ptr + i * VP_Scan_Line ) ;\n\n\tMem_Copy(palette, palcopy, 256 * 3);\n\tpal = ( RGB * ) palcopy ;\n\tfor ( i = 0 ; i < 256 ; i ++ ) {\n\t\tpal -> red <<= 2 ;\n\t\tpal -> green <<= 2 ;\n\t\tpal -> blue <<= 2 ;\n\t\tpal ++ ;\n\t}\n\ti = 0x0c ;\n\tWrite_File ( file_handle, & i , 1 ) ;\n\tWrite_File ( file_handle, palcopy , 256 * sizeof (RGB) ) ;\n\tClose_File (file_handle) ;\n\treturn 0 ;\n}\n\n\n\n\n/***************************************************************************\n * WRITE_PCX_SCANLINE -- function to write a single pcx scanline to a file *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/04/1995 JRJ : Created.                                             *\n *=========================================================================*/\n\n#define\tPOOL_SIZE 2048\n#define WRITE_CHAR(x) {\t\\\n\t\t\t\t\t\t\t\t* file_ptr ++ = x ; \\\n\t\t\t\t\t\t\t   if ( file_ptr >= & pool [ POOL_SIZE ]\t) { \\\n\t\t\t\t\t\t\t\t  Write_File ( file_handle, pool , POOL_SIZE ) ; \\\n\t\t\t\t\t\t\t\t  file_ptr = pool ; \\\n\t\t\t\t\t\t\t }\t}\n\n\nvoid Write_Pcx_ScanLine ( int file_handle , int scansize , char * ptr )\n{\n\tunsigned     i ;\n\tunsigned     rle ;\n\tunsigned     color ;\n\tunsigned\t\tlast ;\n\tchar\t\t  * file_ptr ;\n\tchar\t\t \tpool [ POOL_SIZE ] ;\n\n\tfile_ptr = pool ;\n\tlast = * ptr ;\n\trle = 1 ;\n\n\tfor ( i = 1 ; i < scansize ; i ++ ) {\n   \tcolor = 0xff & * ++ ptr ;\n\t\tif ( color == last ) {\n\t\t\trle ++ ;\n\t\t\tif ( rle == 63 )\t {\n\t\t\t\tWRITE_CHAR ( 255 ) ;\n\t\t\t\tWRITE_CHAR ( color ) ;\n\t\t\t\trle = 0 ;\n\t\t\t}\n\t\t} else {\n\t  \t\tif ( rle ) {\n\t\t \t\tif ( rle == 1 && ( 192 != ( 192 & last ))) {\n\t\t\t   \tWRITE_CHAR ( last ) ;\n\t\t     \t} else {\n\t\t      \tWRITE_CHAR ( rle | 192 ) ;\n\t     \t   \tWRITE_CHAR ( last ) ;\n\t\t\t\t}\n\t\t\t}\n\t\t\tlast = color ;\n\t\t\trle = 1 ;\n\t\t}\n\t}\n\tif ( rle ) {\n\t\tif ( rle == 1 && ( 192 != ( 192 & last ))) {\n\t\t\tWRITE_CHAR ( last ) ;\n\t\t} else {\n\t\t\tWRITE_CHAR ( rle | 192 ) ;\n\t   \tWRITE_CHAR ( last) ;\n\t\t}\n\t}\n\n\tWrite_File ( file_handle, pool , ( int ) file_ptr - ( int ) pool ) ;\n}\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/WSA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./wsa.c 1.16 1994/05/20 15:35:27 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library Animation System                 *\n *                                                                         *\n *                    File Name : WSA.C                                    *\n *                                                                         *\n *                   Programmer : Michael Legg                             *\n *                                                                         *\n *                   Start Date : November 20, 1991                        *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *   There are many different ways that the user can use the WSA library   *\n * module.  The options are as follows :                                   *\n *                                                                         *\n *   System Allocation vs User Buffer - The user may request that the      *\n *       system allocate the needed buffer from the heap or the user may\t*\n *       pass his own buffer in for the animator to use.                   *\n *                                                                         *\n *   Resident vs File based - If there is enough RAM, the user may put the *\n *       entire animation into RAM for fastest animations.  If there is    *\n *       not enouph RAM, the system will automatically make it so each     *\n *       frame will be read off disk when needed.                          *\n *                                                                         *\n *   Direct to Page vs Use of a user buffer -- Noramally Direct to page\t\t*\n *       is the best method both in speed and in RAM need to hold anim.    *\n *       One may want to use the write to user buffer method if they       *\n *       are using the animation in a non sequencial order.                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Animate_Frame -- Displays a frame of a given animation                *\n *   Get_Animation_Frame_Count --  Return Number of frames in an animation.  *\n *   Get_Animation_X -- Gets the x from an animation                       *\n *   Get_Animation_Y -- Gets the y from an animation                       *\n *   Get_Animation_Width -- Gets the width from an animation               *\n *   Get_Animation_Height -- The height of the animation we are processing *\n *   Apply_Delta -- Copies frame into delta buffer, then applies to target *\n *   Close_Animation -- Close the animation, freeing the space if necessary*\n *   Get_File_Frame_Offset -- Get offset of a delta frame from animate file*\n *   Get_Resident_Frame_Offset -- Gets frame offset of animate file in RAM *\n *   Open_Animation -- Opens an animation file and reads into buffer       *\n *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include <wwstd.h>\n#include \"wsa.h\"\n#include <wwmem.h>\n#include <file.h>\n#include <misc.h>\n#include <iff.h>\n#include <mem.h>\n#include <string.h>\n\n//\n// WSA animation header allocation type.\n// If we need more then 8 flags for the flags variable, we can combine\n// USER_ALLOCATED with SYS_ALLOCATED  and combine FILE with RESIDENT.\n//\n#define\tWSA_USER_ALLOCATED \t0x01\n#define\tWSA_SYS_ALLOCATED  \t0x02\n#define\tWSA_FILE           \t0x04\n#define\tWSA_RESIDENT       \t0x08\n#define\tWSA_TARGET_IN_BUFFER\t0x10\n#define\tWSA_LINEAR_ONLY\t\t0x20\n#define\tWSA_FRAME_0_ON_PAGE  0x40\n#define\tWSA_AMIGA_ANIMATION  0x80\n#define\tWSA_PALETTE_PRESENT\t0x100\n#define\tWSA_FRAME_0_IS_DELTA\t0x200\n\n// These are used to call Apply_XOR_Delta_To_Page_Or_Viewport() to setup flags parameter.  If\n// These change, make sure and change their values in lp_asm.asm.\n#define\tDO_XOR\t\t\t\t\t0x0\n#define\tDO_COPY\t\t\t\t\t0x01\n#define\tTO_VIEWPORT\t\t\t\t0x0\n#define\tTO_PAGE\t\t\t\t\t0x02\n\n\n\n\ntypedef struct {\n\tunsigned short current_frame;\n\tunsigned short total_frames;\n\tunsigned short pixel_x;\n\tunsigned short pixel_y;\n\tunsigned short pixel_width;\n\tunsigned short pixel_height;\n\tunsigned short largest_frame_size;\n\tchar *delta_buffer;\n\tchar *file_buffer;\n\tchar file_name[ 13 ];\n\tshort flags;\n\t// New fields that animate does not know about below this point. SEE EXTRA_charS_ANIMATE_NOT_KNOW_ABOUT\n\tshort file_handle;\n\tunsigned long anim_mem_size;\n} SysAnimHeaderType;\n\n// NOTE:\"THIS IS A BAD THING. SINCE sizeof(SysAnimHeaderType) CHANGED, THE ANIMATE.EXE\n// UTILITY DID NOT KNOW I UPDATED IT, IT ADDS IT TO largest_frame_size BEFORE SAVING\n// IT TO THE FILE.  THIS MEANS I HAVE TO ADD THESE charS ON NOW FOR IT TO WORK.\n#define EXTRA_charS_ANIMATE_NOT_KNOW_ABOUT\t(sizeof(short) + sizeof(unsigned long))\n\n\n//\n// Header structure for the file.\n// NOTE:  The 'total_frames' field is used to differentiate between Amiga and IBM\n// animations.  Amiga animations have the HIGH bit set.\n//\ntypedef struct {\n\tunsigned short total_frames;\n\tunsigned short pixel_x;\n\tunsigned short pixel_y;\n\tunsigned short pixel_width;\n\tunsigned short pixel_height;\n\tunsigned short largest_frame_size;\n\tshort\tflags;\n\tunsigned long frame0_offset;\n\tunsigned long frame0_end;\n\t/* unsigned long data_seek_offset, unsigned short frame_size ... */\n} WSA_FileHeaderType;\n\n#define WSA_FILE_HEADER_SIZE\t( sizeof(WSA_FileHeaderType) - (2 * sizeof(unsigned long)) )\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE unsigned long Get_Resident_Frame_Offset( char *file_buffer, int frame );\nPRIVATE unsigned long Get_File_Frame_Offset( int file_handle, int frame, int palette_adjust);\nPRIVATE BOOL Apply_Delta(SysAnimHeaderType *sys_header, int curr_frame, char *dest_ptr, int dest_w);\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * OPEN_ANIMATION -- Opens an animation file and reads into buffer         *\n *                                                                         *\n * INPUT:   char *file_name of animation sequence file.                    *\n *          char *user_buffer pointer if one exists  (NULL ok)             *\n *          unsigned long user_buffer_size if known  (NULL ok)                     *\n *          WSAOpenType user_flags - flags on how to open.                 *\n *          unsigned char *palette - pointer to palette space for return (NULL ok) *\n *                                                                         *\n * OUTPUT:  void *pointer to animation data.  Must be used for all \t\t\t*\n *               other WSA calls.                                          *\n *                                                                         *\n * WARNINGS: May return NULL, please check.                                *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/26/1991  SB : Created.                                             *\n *=========================================================================*/\nvoid * __cdecl Open_Animation(char const *file_name, char *user_buffer, long user_buffer_size, WSAOpenType user_flags, unsigned char *palette)\n{\n\tint\t\t\t\t\t\tfh, anim_flags;\n\tint\t\t\t\t\t\tpalette_adjust;\n\tunsigned int\t\t\t\t\t\toffsets_size;\n\tunsigned int\t\t\t\t\t\tframe0_size;\n\tlong\t\t\t\t\t\ttarget_buffer_size, delta_buffer_size, file_buffer_size;\n\tlong\t\t\t\t\t\tmax_buffer_size,    min_buffer_size;\n\tchar\t\t\t\t\t\t*sys_anim_header_buffer;\n\tchar\t\t\t\t\t\t*target_buffer;\n\tchar\t\t\t\t\t\t*delta_buffer, *delta_back;\n\tSysAnimHeaderType\t\t*sys_header;\n\tWSA_FileHeaderType\tfile_header;\n\n\t/*======================================================================*/\n\t/* Open the file to get the header information\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\n\tanim_flags\t= 0;\n\tfh\t\t\t\t= Open_File(file_name, READ);\n\tRead_File(fh, (char *) &file_header, sizeof(WSA_FileHeaderType));\n\n\t/*======================================================================*/\n\t/* If the file has an attached palette then if we have a valid palette\t*/\n\t/*\t\tpointer we need to read it in.\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\n\tif (file_header.flags & 1) {\n\t\tanim_flags\t\t|= WSA_PALETTE_PRESENT;\n\t\tpalette_adjust\t = 768;\n\n\t\tif (palette != NULL) {\n\t\t\tSeek_File(fh, sizeof(unsigned long) * (file_header.total_frames), SEEK_CUR);\n\t\t\tRead_File(fh, palette, 768L);\n\t\t}\n\n\t} else {\n\t\tpalette_adjust = 0;\n\t}\n\n\t// Check for flag from ANIMATE indicating that this animation was\n\t// created from a .LBM and a .ANM.  These means that the first\n\t// frame is a XOR Delta from a picture, not black.\n\tif (file_header.flags & 2) {\n\t\tanim_flags\t\t|= WSA_FRAME_0_IS_DELTA;\n\t}\n\n\n\t// Get the total file size minus the size of the first frame and the size\n\t// of the file header.  These will not be read in to save even more space.\n\tfile_buffer_size = Seek_File(fh, 0L, SEEK_END);\n\n\tif (file_header.frame0_offset) {\n\t\tlong tlong;\n\n\t\ttlong = file_header.frame0_end - file_header.frame0_offset;\n\t\tframe0_size = (unsigned short) tlong;\n\t}\n\telse {\n\t\tanim_flags |= WSA_FRAME_0_ON_PAGE;\n\t\tframe0_size = 0;\n\t}\n\n\tfile_buffer_size -= palette_adjust + frame0_size + WSA_FILE_HEADER_SIZE;\n\n\t// We need to determine the buffer sizes required for the animation.  At a\n\t// minimum, we need a target buffer for the uncompressed frame and a delta\n\t// buffer for the delta data.  We may be able to make the file resident,\n\t// so we will determine the file size.\n\t//\n\t// If the target buffer is in the user buffer\n\t// Then figure its size\n\t// and set the allocation flag\n\t// Else size is zero.\n\t//\n\tif (user_flags & WSA_OPEN_DIRECT) {\n\t \ttarget_buffer_size = 0L;\n\t}\n\telse {\n\t\tanim_flags |= WSA_TARGET_IN_BUFFER;\n\t\ttarget_buffer_size = (unsigned long) file_header.pixel_width * file_header.pixel_height;\n\t}\n\n\t// NOTE:\"THIS IS A BAD THING. SINCE sizeof(SysAnimHeaderType) CHANGED, THE ANIMATE.EXE\n\t// UTILITY DID NOT KNOW I UPDATED IT, IT ADDS IT TO largest_frame_size BEFORE SAVING\n\t// IT TO THE FILE.  THIS MEANS I HAVE TO ADD THESE charS ON NOW FOR IT TO WORK.\n\tdelta_buffer_size  = (unsigned long) file_header.largest_frame_size + EXTRA_charS_ANIMATE_NOT_KNOW_ABOUT;\n\tmin_buffer_size = target_buffer_size + delta_buffer_size;\n\tmax_buffer_size = min_buffer_size + file_buffer_size;\n\n\t// check to see if buffer size is big enough for at least min required\n\tif (user_buffer && (user_buffer_size < min_buffer_size)) {\n\t\tClose_File(fh);\n\t\treturn(NULL);\n\t}\n\n\t// A buffer was not passed in, so do allocations\n\tif (user_buffer == NULL) {\n\n\t\t// If the user wants it from the disk, then let us give it to him,\n\t\t// otherwise, try to give a max allocation he can have.\n\t\tif (user_flags & WSA_OPEN_FROM_DISK) {\n\t\t\tuser_buffer_size = min_buffer_size;\n\t\t}\n\t\t// else no buffer size, then try max configuration.\n\t\telse if (!user_buffer_size) {\n\t\t\tuser_buffer_size = max_buffer_size;\n\t\t}\n\t\t// else if buffer specified is less then max needed, give min.\n\t\telse if (user_buffer_size < max_buffer_size) {\n\t\t\tuser_buffer_size = min_buffer_size;\n\t\t}\n\t\t// otherwise we only want to alloc what we need.\n\t\telse {\n\t\t\tuser_buffer_size = max_buffer_size;\n\t\t}\n\n\n\t\t// Check to see if enough RAM available for buffer_size.\n\t\tif (user_buffer_size > Ram_Free(MEM_NORMAL)) {\n\n \t\t\t// If not enough room for even the min, return no buffer.\n\n\t\t\tif (min_buffer_size > Ram_Free(MEM_NORMAL)) {\n\t\t\t\tClose_File(fh);\n\t\t\t\treturn(NULL);\n\t\t\t}\n\n\t\t\t// Else make buffer size the min and allocate it.\n\t\t\tuser_buffer_size = min_buffer_size;\n\t\t}\n\n\t\t// allocate buffer needed\n\t\tuser_buffer = (char *) Alloc(user_buffer_size, MEM_CLEAR);\n\n\t\tanim_flags |= WSA_SYS_ALLOCATED;\n\t}\n\telse {\n\t\t// Check to see if the user_buffer_size should be min or max.\n\t\tif ((user_flags & WSA_OPEN_FROM_DISK) || (user_buffer_size < max_buffer_size)) {\n\t\t \tuser_buffer_size = min_buffer_size;\n\t\t}\n\t\telse {\n\t\t \tuser_buffer_size = max_buffer_size;\n\t\t}\n\t\tanim_flags |= WSA_USER_ALLOCATED;\n\t}\n\n\n\t// Set the pointers to the RAM buffers\n\tsys_anim_header_buffer = user_buffer;\n\ttarget_buffer = (char *) Add_Long_To_Pointer(sys_anim_header_buffer, sizeof(SysAnimHeaderType));\n\tdelta_buffer  = (char *) Add_Long_To_Pointer(target_buffer, target_buffer_size);\n\n\t//\tClear target buffer if it is in the user buffer.\n\tif (target_buffer_size) {\n\t\tmemset( target_buffer, 0, (unsigned short) target_buffer_size );\n\t}\n\n\t// Poke data into the system animation header (start of user_buffer)\n\t// current_frame is set to total_frames so that Animate_Frame() knows that\n\t// it needs to clear the target buffer.\n\n\tsys_header = ( SysAnimHeaderType * ) sys_anim_header_buffer;\n\tsys_header -> current_frame =\n\tsys_header -> total_frames  = file_header.total_frames;\n\tsys_header -> pixel_x\t\t = file_header.pixel_x;\n\tsys_header -> pixel_y\t\t = file_header.pixel_y;\n\tsys_header -> pixel_width   = file_header.pixel_width;\n\tsys_header -> pixel_height  = file_header.pixel_height;\n\tsys_header -> anim_mem_size = user_buffer_size;\n\tsys_header -> delta_buffer  = delta_buffer;\n\tsys_header -> largest_frame_size =\n                 (unsigned short) (delta_buffer_size - sizeof(SysAnimHeaderType));\n\n\tstrcpy(sys_header->file_name, file_name);\n\n\t// Figure how much room the frame offsets take up in the file.\n\t// Add 2 - one for the wrap around and one for the final end offset.\n\toffsets_size = (file_header.total_frames + 2) << 2;\n\n\t// Can the user_buffer_size handle the maximum case buffer?\n\tif ( user_buffer_size == max_buffer_size) {\n\n\t\t//\n\t\t//\tset the file buffer pointer,\n\t\t// Skip over the header information.\n\t\t// Read in the offsets.\n\t\t// Skip over the first frame.\n\t\t// Read in remaining frames.\n\t\t//\n\n\t\tsys_header->file_buffer = (char *)Add_Long_To_Pointer(delta_buffer,sys_header->largest_frame_size);\n\t\tSeek_File( fh, WSA_FILE_HEADER_SIZE, SEEK_SET);\n\t\tRead_File( fh, sys_header->file_buffer, offsets_size);\n\t\tSeek_File( fh, frame0_size + palette_adjust, SEEK_CUR);\n\t\tRead_File( fh, sys_header->file_buffer + offsets_size,\n\t\t           file_buffer_size - offsets_size);\n\n\t\t//\n\t\t// Find out if there is an ending value for the last frame.\n\t\t// If there is not, then this animation will not be able to\n\t\t// loop back to the beginning.\n\t\t//\n\t\tif (Get_Resident_Frame_Offset( sys_header->file_buffer, sys_header->total_frames + 1))\n\t\t\tanim_flags |= WSA_RESIDENT;\n\t\telse\n\t\t\tanim_flags |= WSA_LINEAR_ONLY | WSA_RESIDENT;\n\t}\n\telse {\t// buffer cannot handle max_size of buffer\n\n\t\tif(Get_File_Frame_Offset( fh, sys_header->total_frames + 1, palette_adjust))\n\t\t\tanim_flags |= WSA_FILE;\n\t\telse\n\t\t\tanim_flags |= WSA_LINEAR_ONLY | WSA_FILE;\n////\n\t\tsys_header->file_buffer = NULL;\n\t}\n\n\t// Figure where to back load frame 0 into the delta buffer.\n\tdelta_back = (char *)Add_Long_To_Pointer(delta_buffer,\n\t\t\t\t\t sys_header->largest_frame_size - frame0_size);\n\n\t// Read the first frame into the delta buffer and uncompress it.\n\t// Then close it.\n\tSeek_File( fh, WSA_FILE_HEADER_SIZE + offsets_size + palette_adjust, SEEK_SET);\n\tRead_File( fh, delta_back, frame0_size);\n\n\t// We do not use the file handle when it is in RAM.\n\tif (anim_flags & WSA_RESIDENT) {\n\t\tsys_header -> file_handle = (short) -1;\n\t \tClose_File(fh);\n\t}\n\telse {\n\t\tsys_header -> file_handle = (short)fh;\n\t}\n\n\tLCW_Uncompress(delta_back, delta_buffer, sys_header->largest_frame_size);\n\n\t// Finally set the flags,\n\tsys_header->flags = (short)anim_flags;\n\n\t// return valid handle\n\treturn( user_buffer );\n}\n\n\n/***************************************************************************\n * CLOSE_ANIMATION -- Close the animation, freeing the space if necessary. *\n *                                                                         *\n * INPUT:      void *handle to the animation data buffer                   *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   handle MUST have been returned by Open_Animation            *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/23/1991  ML : Created.                                             *\n *=========================================================================*/\nvoid __cdecl Close_Animation( void *handle )\n{\n\tSysAnimHeaderType *sys_header;\n\n\t// Assign our local system header pointer to the beginning of the handle space\n\tsys_header = (SysAnimHeaderType *) handle;\n\n\t// Close the WSA file in it was disk based.\n\tif (sys_header->flags & WSA_FILE) {\n\t\tClose_File(sys_header->file_handle);\n\t}\n\n\t// Check to see if the buffer was allocated OR the programmer provided the buffer\n\tif (handle && sys_header->flags & WSA_SYS_ALLOCATED) {\n\t\tFree(handle);\n\t}\n}\n\n/***************************************************************************\n * ANIMATE_FRAME -- Displays a frame of a given animation                  *\n *                                                                         *\n * INPUT:   void *handle to the animation.                                 *\n *          int frame_number wanted to be displayed                       *\n *          int x_pixel position of left side of animation on page        *\n *          int y_pixel position of top of animation on page              *\n *                                                                         *\n * OUTPUT:  BOOL if successfull or not.                                   *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/27/1991  SB : Created.                                             *\n *=========================================================================*/\n#pragma off (unreferenced)\nBOOL __cdecl Animate_Frame(void *handle, GraphicViewPortClass& view,\n                         int frame_number, int x_pixel, int y_pixel,\n                         WSAType flags_and_prio, void *magic_cols, void *magic)\n{\n\tSysAnimHeaderType \t*sys_header;\t\t// fix up the void pointer past in.\n\tint \t\t\t\t\t\tcurr_frame;\t\t\t// current frame we are on.\n\tint\t\t\t\t\t\ttotal_frames;\t\t// number of frames in anim.\n\tint\t\t\t\t\t\tdistance;\t\t\t// distance to desired frame.\n\tint\t\t\t\t\t\tsearch_dir;\t\t\t// direcion to search for desired frame.\n\tint\t\t\t\t\t\tsearch_frames;\t\t// How many frames to search.\n\tint\t\t\t\t\t\tloop;\t\t\t\t\t// Just a loop varible.\n\tchar\t\t\t\t\t\t*frame_buffer;\t\t// our destination.\n\tBOOL\t\t\t\t\t\tdirect_to_dest;\t// are we going directly to the destination?\n\tint\t\t\t\t\t\tdest_width;\t\t\t// the width of the destination buffer or page.\n\n\n\t// Assign local pointer to the beginning of the buffer where the system information\n\t// resides\n\tsys_header = (SysAnimHeaderType \t*)handle;\n\n\t// Get the total number of frames\n\ttotal_frames = sys_header->total_frames;\n\n\t// Are the animation handle and the frame number valid?\n\tif (!handle || (total_frames <= frame_number)) {\n\t\treturn FALSE;\n\t}\n\n\tif (view.Lock()!=TRUE) return (FALSE);\n\n\t// Decide if we are going to a page or a viewport (part of a buffer).\n\tdest_width\t= view.Get_Width() + view.Get_XAdd() + view.Get_Pitch();\n\n\t//\n\t// adjust x_pixel and y_pixel by system pixel_x and pixel_y respectively.\n\t//\n\tx_pixel += (short)sys_header->pixel_x;\n\ty_pixel += (short)sys_header->pixel_y;\n\n\t//\n\t// Check to see if we are using a buffer inside of the animation buffer or if\n\t// it is being drawn directly to the destination page or buffer.\n\t//\n\tif (sys_header->flags & WSA_TARGET_IN_BUFFER) {\n\t\t// Get a pointer to the frame in animation buffer.\n\t\tframe_buffer = (char *)Add_Long_To_Pointer(sys_header, sizeof(SysAnimHeaderType));\n\t\tdirect_to_dest = FALSE;\n\t}\n\telse {\n\t\tframe_buffer\t= (char *)view.Get_Offset();\n\t\tframe_buffer  += (y_pixel * dest_width) + x_pixel;\n\t\tdirect_to_dest\t= TRUE;\n\t}\n\t//\n\t// If current_frame is equal to tatal_frames, then no animations have taken place\n\t// so must uncompress frame 0 in delta buffer to the frame_buffer/page if it\n\t// exists.\n\t//\n\tif (sys_header->current_frame == total_frames) {\n\n\t\t// Call apply delta telling it wether to copy or to xor depending on if the\n\t\t// target is a page or a buffer.\n\n\t\tif (!(sys_header->flags & WSA_FRAME_0_ON_PAGE)) {\n\t\t\tif (direct_to_dest) {\n\n\t\t\t\t// The last parameter says weather to copy or to XOR.  If  the\n\t\t\t\t// first frame is a DELTA, then it must be XOR'd.  A TRUE is\n\t\t\t\t// copy while FALSE is XOR.\n\n\t\t\t\tApply_XOR_Delta_To_Page_Or_Viewport(frame_buffer, sys_header->delta_buffer,\n\t\t\t\t                        \tsys_header->pixel_width, dest_width, //dest_width - sys_header->pixel_width,\n\t\t\t\t\t\t\t\t\t\t\t\t\t(sys_header->flags & WSA_FRAME_0_IS_DELTA)? DO_XOR : DO_COPY);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tApply_XOR_Delta(frame_buffer, sys_header->delta_buffer);\n\t\t\t}\n\t\t}\n\t\tsys_header->current_frame = 0;\n\t}\n\n\t//\n\t// Get the current frame\n\t// If no looping aloud, are the trying to do it anyways?\n\t//\n\tcurr_frame = sys_header->current_frame;\n#if (FALSE)\n\t// This is commented out since we will let them loop even though they should\n\t// not - it will be slower.\n\tif ( (sys_header->flags & WSA_LINEAR_ONLY) && (frame_number < cur_frame) ) {\n\t\tview.Unlock();\n\t \treturn FALSE;\n\t}\n#endif\n\n\t// Get absoulte distance from our current frame to the target frame\n\tdistance = ABS(curr_frame - frame_number);\n\n\t// Assume we are searching right\n\tsearch_dir = 1;\n\n\t// Calculate the number of frames to search if we go right and wrap\n\n\tif (frame_number > curr_frame) {\n\t\tsearch_frames = total_frames - frame_number + curr_frame;\n\n\t\t// Is going right faster than going backwards?\n\t\t// Or are they trying to loop when the should not?\n\t\tif ((search_frames < distance) && !(sys_header->flags & WSA_LINEAR_ONLY)) {\n\t\t\tsearch_dir = -1;\t\t\t\t\t\t\t\t// No, so go left\n\t\t}\n\t\telse {\n\t\t\tsearch_frames = distance;\n\t\t}\n\t}\n\telse {\n\t\tsearch_frames = total_frames - curr_frame + frame_number;\n\n\t\t// Is going right faster than going backwards?\n\t\t// Or are they trying to loop when the should not?\n\t\tif ((search_frames >= distance) || (sys_header->flags & WSA_LINEAR_ONLY)) {\n\t\t\tsearch_dir = -1;\t\t\t\t\t\t\t\t// No, so go left\n\t\t\tsearch_frames = distance;\n\t\t}\n\t}\n\n\t// Take care of the case when we are searching right (possibly right)\n\n\tif (search_dir > 0) {\n\t\tfor (loop = 0; loop < search_frames; loop++) {\n\n\t\t\t// Move the logical frame number ordinally right\n\t\t\tcurr_frame += search_dir;\n\n\t\t\tApply_Delta(sys_header, curr_frame, frame_buffer, dest_width);\n\n\t\t\t// Adjust the current frame number, taking into consideration that we could\n\t\t\t// have wrapped\n\n\t\t\tif (curr_frame == total_frames) {\n\t\t\t\tcurr_frame = 0;\n\t\t\t}\n\t\t}\n\t}\n\telse {\n\t\tfor (loop = 0; loop < search_frames; loop++) {\n\n\t\t\t// If we are going backwards and we are on frame 0, the delta to get\n\t\t\t// to the last frame is the n + 1 delta (wrap delta)\n\n\t\t\tif (curr_frame == 0) {\n\t\t\t\tcurr_frame = total_frames;\n\t\t\t}\n\n\t\t\tApply_Delta(sys_header, curr_frame, frame_buffer, dest_width);\n\n\t\t\tcurr_frame += search_dir;\n\t\t}\n\t}\n\n\tsys_header->current_frame = (short)frame_number;\n\n\t// If we did this all in a hidden buffer, then copy it to the desired page or viewport.\n\tif (sys_header->flags & WSA_TARGET_IN_BUFFER) {\n#if TRUE\n\n\t\tBuffer_To_Page(x_pixel, y_pixel, sys_header->pixel_width, sys_header->pixel_height, frame_buffer, view);\n\n#else\n\t\tint\tflags = ((unsigned short)flags_and_prio & 0xFF00u) >> 12u;\n\t\tint\tpri = flags_and_prio & 0x00FF;\n\n\t\tBuffer_Bitblit_To_LogicPage(x_pixel, y_pixel, sys_header->pixel_width,\n\t\t\t\t\t\t\t\t\t\t  sys_header->pixel_height, 0, flags, frame_buffer, pri,\n\t\t\t\t\t\t\t\t\t\t  magic_cols, magic);\n#endif\n\t}\n\n\tview.Unlock();\n\treturn TRUE;\n}\n/***************************************************************************\n * ANIMATE_FRAME -- Displays a frame of a given animation                  *\n *                                                                         *\n * INPUT:   void *handle to the animation.                                 *\n *          int frame_number wanted to be displayed                       *\n *          int x_pixel position of left side of animation on page        *\n *          int y_pixel position of top of animation on page              *\n *                                                                         *\n * OUTPUT:  BOOL if successfull or not.                                   *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/27/1991  SB : Created.                                             *\n *=========================================================================*/\n#pragma argsused\n#ifdef cuts\nBOOL __cdecl Animate_Frame(void *handle, GraphicViewPortClass& view,\n                         int frame_number, int x_pixel, int y_pixel,\n                         WSAType flags_and_prio, void *magic_cols, void *magic)\n{\n\tSysAnimHeaderType \t*sys_header;\t\t// fix up the void pointer past in.\n\tint \t\t\t\t\t\tcurr_frame;\t\t\t// current frame we are on.\n\tint\t\t\t\t\t\ttotal_frames;\t\t// number of frames in anim.\n\tint\t\t\t\t\t\tdistance;\t\t\t// distance to desired frame.\n\tint\t\t\t\t\t\tsearch_dir;\t\t\t// direcion to search for desired frame.\n\tint\t\t\t\t\t\tsearch_frames;\t\t// How many frames to search.\n\tint\t\t\t\t\t\tloop;\t\t\t\t\t// Just a loop varible.\n\tchar\t\t\t\t\t\t*frame_buffer;\t\t// our destination.\n\tBOOL\t\t\t\t\t\tdirect_to_dest;\t// are we going directly to the destination?\n\tint\t\t\t\t\t\tdest_width;\t\t\t// the width of the destination buffer or page.\n\n\t// Assign local pointer to the beginning of the buffer where the system information\n\t// resides\n\tsys_header = (SysAnimHeaderType \t*)handle;\n\n\t// Get the total number of frames\n\ttotal_frames = sys_header->total_frames;\n\n\t// Are the animation handle and the frame number valid?\n\tif (!handle || (total_frames <= frame_number)) {\n\t\treturn FALSE;\n\t}\n\n\n\t// Decide if we are going to a page or a viewport (part of a buffer).\n\tdest_width\t= view.Get_Width() + view.Get_XAdd();\n\n\t//\n\t// adjust x_pixel and y_pixel by system pixel_x and pixel_y respectively.\n\t//\n\tx_pixel += (short)sys_header->pixel_x;\n\ty_pixel += (short)sys_header->pixel_y;\n\n\t//\n\t// Check to see if we are using a buffer inside of the animation buffer or if\n\t// it is being drawn directly to the destination page or buffer.\n\t//\n\tif (sys_header->flags & WSA_TARGET_IN_BUFFER) {\n\t\t// Get a pointer to the frame in animation buffer.\n\t\tframe_buffer = (char *)Add_Long_To_Pointer(sys_header, sizeof(SysAnimHeaderType));\n\t\tdirect_to_dest = FALSE;\n\t}\n\telse {\n\t\tframe_buffer\t= (char *)view.Get_Offset();\n\t\tframe_buffer  += (y_pixel * dest_width) + x_pixel;\n\t\tdirect_to_dest\t= TRUE;\n\t}\n\t//\n\t// If current_frame is equal to tatal_frames, then no animations have taken place\n\t// so must uncompress frame 0 in delta buffer to the frame_buffer/page if it\n\t// exists.\n\t//\n\tif (sys_header->current_frame == total_frames) {\n\n\t\t// Call apply delta telling it wether to copy or to xor depending on if the\n\t\t// target is a page or a buffer.\n\n\t\tif (!(sys_header->flags & WSA_FRAME_0_ON_PAGE)) {\n\t\t\tif (direct_to_dest) {\n\n\t\t\t\t// The last parameter says weather to copy or to XOR.  If  the\n\t\t\t\t// first frame is a DELTA, then it must be XOR'd.  A TRUE is\n\t\t\t\t// copy while FALSE is XOR.\n\t\t\t\tApply_XOR_Delta_To_Page_Or_Viewport(frame_buffer, sys_header->delta_buffer,\n\t\t\t\t                        \tsys_header->pixel_width, dest_width, //dest_width - sys_header->pixel_width,\n\t\t\t\t\t\t\t\t\t\t\t\t\t(sys_header->flags & WSA_FRAME_0_IS_DELTA)? DO_XOR : DO_COPY);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tApply_XOR_Delta(frame_buffer, sys_header->delta_buffer);\n\t\t\t}\n\t\t}\n\t\tsys_header->current_frame = 0;\n\t}\n\n\t//\n\t// Get the current frame\n\t// If no looping aloud, are the trying to do it anyways?\n\t//\n\tcurr_frame = sys_header->current_frame;\n#if (FALSE)\n\t// This is commented out since we will let them loop even though they should\n\t// not - it will be slower.\n\tif ( (sys_header->flags & WSA_LINEAR_ONLY) && (frame_number < cur_frame) ) {\n\t \treturn FALSE;\n\t}\n#endif\n\n\t// Get absoulte distance from our current frame to the target frame\n\tdistance = ABS(curr_frame - frame_number);\n\n\t// Assume we are searching right\n\tsearch_dir = 1;\n\n\t// Calculate the number of frames to search if we go right and wrap\n\n\tif (frame_number > curr_frame) {\n\t\tsearch_frames = total_frames - frame_number + curr_frame;\n\n\t\t// Is going right faster than going backwards?\n\t\t// Or are they trying to loop when the should not?\n\t\tif ((search_frames < distance) && !(sys_header->flags & WSA_LINEAR_ONLY)) {\n\t\t\tsearch_dir = -1;\t\t\t\t\t\t\t\t// No, so go left\n\t\t}\n\t\telse {\n\t\t\tsearch_frames = distance;\n\t\t}\n\t}\n\telse {\n\t\tsearch_frames = total_frames - curr_frame + frame_number;\n\n\t\t// Is going right faster than going backwards?\n\t\t// Or are they trying to loop when the should not?\n\t\tif ((search_frames >= distance) || (sys_header->flags & WSA_LINEAR_ONLY)) {\n\t\t\tsearch_dir = -1;\t\t\t\t\t\t\t\t// No, so go left\n\t\t\tsearch_frames = distance;\n\t\t}\n\t}\n\n\t// Take care of the case when we are searching right (possibly right)\n\n\tif (search_dir > 0) {\n\t\tfor (loop = 0; loop < search_frames; loop++) {\n\n\t\t\t// Move the logical frame number ordinally right\n\t\t\tcurr_frame += search_dir;\n\n\t\t\tApply_Delta(sys_header, curr_frame, frame_buffer, dest_width);\n\n\t\t\t// Adjust the current frame number, taking into consideration that we could\n\t\t\t// have wrapped\n\n\t\t\tif (curr_frame == total_frames) {\n\t\t\t\tcurr_frame = 0;\n\t\t\t}\n\t\t}\n\t}\n\telse {\n\t\tfor (loop = 0; loop < search_frames; loop++) {\n\n\t\t\t// If we are going backwards and we are on frame 0, the delta to get\n\t\t\t// to the last frame is the n + 1 delta (wrap delta)\n\n\t\t\tif (curr_frame == 0) {\n\t\t\t\tcurr_frame = total_frames;\n\t\t\t}\n\n\t\t\tApply_Delta(sys_header, curr_frame, frame_buffer, dest_width);\n\n\t\t\tcurr_frame += search_dir;\n\t\t}\n\t}\n\n\tsys_header->current_frame = frame_number;\n\n\t// If we did this all in a hidden buffer, then copy it to the desired page or viewport.\n\tif (sys_header->flags & WSA_TARGET_IN_BUFFER) {\n#if TRUE\n\n\t\tBuffer_To_Page(x_pixel, y_pixel, sys_header->pixel_width, sys_header->pixel_height, frame_buffer, view);\n\n#else\n\t\tint\tflags = ((unsigned short)flags_and_prio & 0xFF00u) >> 12u;\n\t\tint\tpri = flags_and_prio & 0x00FF;\n\n\t\tBuffer_Bitblit_To_LogicPage(x_pixel, y_pixel, sys_header->pixel_width,\n\t\t\t\t\t\t\t\t\t\t  sys_header->pixel_height, 0, flags, frame_buffer, pri,\n\t\t\t\t\t\t\t\t\t\t  magic_cols, magic);\n#endif\n\t}\n\n\n\treturn TRUE;\n}\n#endif\n\n\n/***************************************************************************\n * ANIMATE_FRAME_COUNT -- Return Number of frames in an animation.         *\n *                                                                         *\n * INPUT:   void *handle to the animation.                                 *\n *                                                                         *\n * OUTPUT:  int number of frames in animation.                            *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/05/1991  SB : Created.                                             *\n *=========================================================================*/\nint __cdecl Get_Animation_Frame_Count(void *handle)\n{\n\tSysAnimHeaderType *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn((short)sys_header->total_frames);\n}\n\n\n/***************************************************************************\n * GET_ANIM_X -- Gets the x from an animation                              *\n *                                                                         *\n *                                                                         *\n * INPUT:\t\tvoid * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:     int the x of the animation we are processing\t\t\t\t   *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/03/1992 DRD : Created.                                             *\n *=========================================================================*/\nint __cdecl Get_Animation_X(void const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->pixel_x);\n}\n\n/***************************************************************************\n * GET_ANIM_Y -- Gets the y from an animation                              *\n *                                                                         *\n *                                                                         *\n * INPUT:\t\tvoid * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:     int the y of the animation we are processing\t\t\t\t   *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/14/1992 PWG : Created.                                             *\n *=========================================================================*/\nint __cdecl Get_Animation_Y(void const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->pixel_y);\n}\n\n/***************************************************************************\n * GET_ANIM_WIDTH -- Gets the width from an animation                      *\n *                                                                         *\n *                                                                         *\n * INPUT:\t\tvoid * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:     int the width of the animation we are processing\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/14/1992 PWG : Created.                                             *\n *=========================================================================*/\nint __cdecl Get_Animation_Width(void const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->pixel_width);\n}\n\n/***************************************************************************\n * GET_ANIM_HEIGHT -- The height of the animation we are processing        *\n *                                                                         *\n * INPUT:\t\tvoid * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:     int the height of the animation we are processing\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/14/1992 PWG : Created.                                             *\n *=========================================================================*/\nint __cdecl Get_Animation_Height(void const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->pixel_height);\n}\n\n\n/***************************************************************************\n * GET_ANIM_PALETTE -- Returns true if the anim had an attached palette    *\n *                                                                         *\n * INPUT:\t\tvoid * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:\t\tint True if the animation has a set palette.  False if the\t*\n *\t\t\t\t\tanimation does not.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/14/1992 PWG : Created.                                             *\n *=========================================================================*/\nint __cdecl Get_Animation_Palette(void const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->flags & WSA_PALETTE_PRESENT);\n}\n\n\n/***************************************************************************\n * GET_ANIMATION_SIZE -- Return the amount of memory the animation is using*\n *                                                                         *\n *                                                                         *\n * INPUT:\t\tvoid * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:\t\tunsigned long number of byte used by animation. \t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/23/1994 SKB : Created.                                             *\n *=========================================================================*/\nunsigned long __cdecl Get_Animation_Size(void const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->anim_mem_size);\n}\n\n/* ::::::::::::::::::::::::::::  PRIVATE FUNCTIONS  :::::::::::::::::::::::::::::: */\n\n\n/***************************************************************************\n * GET_RESIDENT_FRAME_OFFSET -- Gets frame offset of animate file in RAM   *\n *                                                                         *\n * INPUT:      char *file_buffer in RAM of animation file.                 *\n *             int frame number that we need the offset of.               *\n *                                                                         *\n * OUTPUT:     int offset of frame requested.                             *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/26/1991  SB : Created.                                             *\n *=========================================================================*/\nPRIVATE unsigned long Get_Resident_Frame_Offset( char *file_buffer, int frame )\n{\n\tunsigned long frame0_size;\n\tunsigned long *lptr;\n\n\t// If there is a frame 0, the calculate its size.\n\tlptr = (unsigned long *) file_buffer;\n\n\tif (*lptr) {\n\t\tframe0_size = lptr[1] - *lptr;\n\t} else {\n\t \tframe0_size = 0;\n\t}\n\n\t// Return the offset into RAM for the frame.\n\tlptr += frame;\n\tif (*lptr)\n\t\t\treturn (*lptr - (frame0_size + WSA_FILE_HEADER_SIZE));\n\telse\n\t\treturn (0L);\n}\n\n\n/***************************************************************************\n * GET_FILE_FRAME_OFFSET -- Get offset of a delta frame from animate file. *\n *                                                                         *\n * INPUT:      int file_handle of animation file.                         *\n *             int frame number that we need the offset of.               *\n *                                                                         *\n * OUTPUT:     int offset of frame requested.                             *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/26/1991  SB : Created.                                             *\n *=========================================================================*/\nPRIVATE unsigned long Get_File_Frame_Offset( int file_handle, int frame, int palette_adjust)\n{\n\tunsigned long offset;\n\n\tSeek_File(file_handle, (frame << 2) + WSA_FILE_HEADER_SIZE, SEEK_SET);\n\n\tif (Read_File(file_handle, (char *) &offset, sizeof(unsigned long)) != sizeof(unsigned long)) {\n\t\toffset = 0L;\n\t}\n\toffset += palette_adjust;\n\treturn( offset );\n}\n\n\n/***************************************************************************\n * APPLY_DELTA -- Copies frame into delta buffer, then applies to target   *\n *                                                                         *\n * INPUT:      SysAnimHeaderType *sys_header - pointer to animation buffer.*\n *             int curr_frame - frame to put into target buffer.          *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:     BOOL - Return wether or not it worked.                      *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/26/1991  SB : Created.                                             *\n *=========================================================================*/\nPRIVATE BOOL Apply_Delta(SysAnimHeaderType *sys_header, int curr_frame, char *dest_ptr, int dest_w)\n{\n\tchar *data_ptr, *delta_back;\n\tint file_handle, palette_adjust;\n\tunsigned long frame_data_size, frame_offset;\n\n\n\tpalette_adjust = ((sys_header->flags & WSA_PALETTE_PRESENT) ? 768 : 0);\n\tdelta_back\t\t= sys_header->delta_buffer;\n\n\tif (sys_header->flags & WSA_RESIDENT) {\n\t\t// Get offset of the given frame in the resident file\n\t\t// Get the size of the frame <- (frame+1 offset) - (offset)\n\t\t// Point at the delta data\n\t\t// figure offset to load data into end of delta buffer\n\t\t// copy it into buffer\n\n\t\tframe_offset = Get_Resident_Frame_Offset(sys_header->file_buffer, curr_frame);\n\t\tframe_data_size = Get_Resident_Frame_Offset(sys_header->file_buffer, curr_frame + 1) -\tframe_offset;\n\n\t  \tdata_ptr \t= (char *)Add_Long_To_Pointer(sys_header->file_buffer, frame_offset);\n\t  \tdelta_back \t= (char *)Add_Long_To_Pointer(delta_back,\n\t  \t\t\t\t\t\t sys_header->largest_frame_size - frame_data_size);\n\n\t\tMem_Copy( data_ptr, delta_back, frame_data_size );\n\n\t} else if (sys_header -> flags & WSA_FILE) {\n\n\t\t//\tOpen up file because not file not in RAM.\n\t\t// Get offset of the given frame in the file on disk\n\t\t// Get the size of the frame <- (frame+1 offset) - (offset)\n\t\t// Return if Get_.._offset() failed.  -- need error handling????\n\t\t//\tSeek to delta data.\n\t\t// figure offset to load data into end of delta buffer\n\t\t//\tRead it into buffer -- Return if correct amount not read.-- errors??\n\n\t\tfile_handle  = sys_header->file_handle;\n\t\tSeek_File(file_handle, 0L, SEEK_SET);\n\n\t\tframe_offset = Get_File_Frame_Offset(file_handle, curr_frame, palette_adjust);\n\t\tframe_data_size = Get_File_Frame_Offset(file_handle, curr_frame + 1, palette_adjust) - frame_offset;\n\n\t\tif (!frame_offset || !frame_data_size) {\n\t\t\treturn(FALSE);\n\t\t}\n\n\t\tSeek_File(file_handle, frame_offset, SEEK_SET);\n\t\tdelta_back \t= (char *)Add_Long_To_Pointer(delta_back, sys_header->largest_frame_size - frame_data_size);\n\n\t\tif (Read_File(file_handle, delta_back, frame_data_size) != frame_data_size) {\n\t\t\treturn(FALSE);\n\t\t}\n\t}\n\n\t// Uncompress data at end of delta buffer to the beginning of delta buffer.\n\t// Find start of target buffer.\n\t// Apply the XOR delta.\n\n\tLCW_Uncompress(delta_back, sys_header->delta_buffer, sys_header->largest_frame_size);\n\n\tif (sys_header->flags & WSA_TARGET_IN_BUFFER) {\n\t\tApply_XOR_Delta(dest_ptr, sys_header->delta_buffer);\n\t}\n\telse {\n\t\tApply_XOR_Delta_To_Page_Or_Viewport(dest_ptr, sys_header->delta_buffer,\n\t\t                        sys_header->pixel_width,  dest_w, DO_XOR);\n\t}\n\n\treturn(TRUE);\n}\n\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/WWMOUSE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : BITBLIT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Philip W. Gorrow\t\t\t   *\n;*                                                                         *\n;*                   Start Date : December 12, 1995                        *\n;*                                                                         *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \"drawbuff.inc\"\nINCLUDE \"gbuffer.inc\"\nINCLUDE \"shape.inc\"\nINCLUDE \".\\mouse.inc\"\n\nGLOBAL\tC LCW_Uncompress:NEAR\nGLOBAL\tC Get_Shape_Uncomp_Size     :NEAR\nGLOBAL\tC Get_Shape_Width      \t  :NEAR\nGLOBAL\tC Get_Shape_Original_Height :NEAR\nGLOBAL\t_ShapeBuffer\t\t  :DWORD\n\nCODESEG\n\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tMouseClass *\t\t- pointer to mouse class data\t   *\n;*\t\tGraphicBufferClass *\t- screen to draw the mouse on\t   *\n;*\t\tint x\t\t\t- x position to store the mouse at *\n;*\t\tint y\t\t\t- y position to store the mouse at *\n;*\t\tint store\t\t- whether to store buffer or save  *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* Note: The x and y that this routine expects to receive are based on\t   *\n;*       the mouse cursor position.  This routine automatically adjusts\t   *\n;*\t for hot spot, so that adjustment should not be made prior to\t   *\n;*\t this point.\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tvoid Mouse_Shadow_Buffer(GraphicBufferClass *src/dest,\t   *\n;*\t\t\t\t\tvoid *buffer\n;*\t\t\t\t\tint x_pixel,\t\t\t   *\n;*\t\t\t\t\tint y_pixel,\t\t\t   *\n;*\t\t\t\t\tint store);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Mouse_Shadow_Buffer:NEAR\n\tPROC\tMouse_Shadow_Buffer C NEAR\n\tUSES\teax,ebx,ecx,edx,edi,esi\n\n\tARG\tthis:\t\tDWORD\n\tARG\tsrc_dst_obj:\tDWORD\n\tARG\tbuffer:DWORD\n\tARG\tx:\t\tDWORD\n\tARG\ty:\t\tDWORD\n\tARG\thotx:\t\tDWORD\n\tARG\thoty:\t\tDWORD\n\tARG\tstore:\t\tDWORD\n\n\tlocal\tx0: \t\tdword\n\tlocal\ty0: \t\tdword\n\tlocal\tx1: \t\tdword\n\tlocal\ty1: \t\tdword\n\tlocal\tbuffx0: \tdword\n\tlocal\tbuffy0: \tdword\n\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tesi, [this]\t\t\t; get offset to mouse data\n\tmov\tedi, [src_dst_obj]\t\t; get offset to mouse data\n\n\tmov\teax, [x]\n\tmov\tebx, [y]\n\tsub\teax, [hotx]\n\tsub\tebx, [hoty]\n\n\tmov\t[x0], eax\n\tmov\t[y0], ebx\n\tadd\teax, [(MouseType esi).CursorWidth]\n\tadd\tebx, [(MouseType esi).CursorHeight]\n\tmov\t[x1], eax\n\tmov\t[y1], ebx\n\n\tmov\t[buffx0], 0\n\tmov\teax, [buffer]\n\tmov\t[buffy0], eax\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\n\txor \teax, eax\n\txor \tedx, edx\n\n\tmov\tecx, [x0]\n\tmov\tebx, [x1]\n\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [x0]\n\tmov\tebx, [x1]\n\tsub\tecx, [(GraphicViewPort edi).GVPWidth]\n\tsub\tebx, [(GraphicViewPort edi).GVPWidth]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [y0]\n\tmov\tebx, [y1]\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [y0]\n\tmov\tebx, [y1]\n\tsub\tecx, [(GraphicViewPort edi).GVPHeight]\n\tsub\tebx, [(GraphicViewPort edi).GVPHeight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\txor\tal, 5\n\txor\tdl, 5\n\tmov\tah, al\n\ttest\tdl, al\n\tjnz\t??out\n\tor\tal, dl\n\tjz\t??not_clip\n\n\ttest\tah, 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx, [x0]\n\tneg\tebx\n\tmov\t[buffx0], ebx\n\tmov\t[x0], 0\n\n??scr_left_ok:\n\ttest\tah, 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx, [y0]\n\tneg\tebx\n\timul\tebx, [(MouseType esi).CursorWidth]\n\tadd\t[buffy0], ebx\n\tmov\t[y0], 0\n\n??scr_bottom_ok:\n\ttest\tdl, 0100b\n\tjz\t??scr_right_ok\n\tmov\teax, [(GraphicViewPort edi).GVPWidth]  ; get width into register\n\tmov\t[x1], eax\n??scr_right_ok:\n\ttest\tdl, 0001b\n\tjz\t??not_clip\n\tmov\teax, [(GraphicViewPort edi).GVPHeight]  ; get width into register\n\tmov\t[y1], eax\n\n??not_clip:\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax, [y0]\n\tmov\tedx, [(GraphicViewPort edi).GVPWidth]\n\tadd\tedx, [(GraphicViewPort edi).GVPXAdd]\n\tadd\tedx, [(GraphicViewPort edi).GVPPitch]\n\timul\teax, edx\n\tadd\teax, [x0]\n\tmov\tedi, [(GraphicViewPort edi).GVPOffset]\n\tadd\tedi, eax\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx, [(MouseType esi).CursorWidth]\t; turn this into an offset\n\tmov\tesi, [buffy0]\t\t\t; edx points to source\n\tadd\tesi, [buffx0]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax, [x1]\n\tmov\tecx, [y1]\n\tsub\teax, [x0]\n\tjle\t??out\n\tsub\tecx, [y0]\n\tjle\t??out\n\n\tsub\tedx, eax\n\tsub\tebx, eax\n\tpush\tebp\n\tcmp\t[store], 1\t\t\t\t\t; are we storing page?\n\tje\t\t??store_entry\t\t\t\t; if so go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tebp, ecx\n??restore_loop:\n\tmov\tecx, eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi, ebx\t\t\t\t; move past right clipped pixels\n\tadd\tedi, edx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tesi, edi\t\t\t\t\t; xchg the source and the dest\n\tmov\tebp, ecx\n\n??store_loop:\n\tmov\tecx, eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi, edx\t\t\t\t; move past right clipped pixels\n\tadd\tedi, ebx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n??out:\n\tret\n\tENDP\tMouse_Shadow_Buffer\n\n;***************************************************************************\n;* DRAW_MOUSE -- Handles drawing the mouse cursor\t\t\t   *\n;*                                                                         *\n;* INPUT:\tMouseClass *\t\t- pointer to mouse class data\t   *\n;*\t\tGraphicBufferClass *\t- screen to draw the mouse on\t   *\n;*\t\tint x\t\t\t- x position to store the mouse at *\n;*\t\tint y\t\t\t- y position to store the mouse at *\n;*                                                                         *\n;* Note: The x and y that this routine expects to receive are based on\t   *\n;*       the mouse cursor position.  This routine automatically adjusts\t   *\n;*\t for hot spot, so that adjustment should not be made prior to\t   *\n;*\t this point.\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* PROTO:       void Draw_Mouse(\tMouseClass * mouse_data,\t   *\n;*\t\t\t\t\tGraphicBufferClass *destination,   *\n;*\t\t\t\t\tint x_pixel,\t\t\t   *\n;* \t\t\t\t\tint y_pixel);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Draw_Mouse:NEAR\n\tPROC\tDraw_Mouse C NEAR\n\tUSES\teax,ebx,ecx,edx,edi,esi\n\n\tARG\tthis:DWORD\n\tARG\tdest:DWORD\n\tARG\tmousex:DWORD\n\tARG\tmousey:DWORD\n\n\tlocal\tx0:dword\n\tlocal\ty0:dword\n\tlocal\tx1:dword\n\tlocal\ty1:dword\n\tlocal\tbuffx0:dword\n\tlocal\tbuffy0:dword\n\n\n\tmov\tesi, [this]    \t; get 32 bit offset to mouse data\n\tmov\tedi, [dest]\t; get 32 bit offset to dest buffer\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax, [mousex]\n\tmov\tebx, [mousey]\n\tsub\teax, [(MouseType esi).MouseXHot]\n\tsub\tebx, [(MouseType esi).MouseYHot]\n\n\tmov\t[x0], eax\n\tmov\t[y0], ebx\n\tadd\teax,[(MouseType esi).CursorWidth]\n\tadd\tebx,[(MouseType esi).CursorHeight]\n\tmov\t[x1], eax\n\tmov\t[y1], ebx\n\n\tmov\t[buffx0], 0\n\tmov\teax, [(MouseType esi).MouseCursor]\n\tmov\t[buffy0], eax\n\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\txor \teax, eax\n\txor \tedx, edx\n\n\tmov\tecx, [x0]\n\tmov\tebx, [x1]\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [x0]\n\tmov\tebx, [x1]\n\tsub\tecx, [(GraphicViewPort edi).GVPWidth]\n\tsub\tebx, [(GraphicViewPort edi).GVPWidth]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [y0]\n\tmov\tebx, [y1]\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\tmov\tecx, [y0]\n\tmov\tebx, [y1]\n\tsub\tecx, [(GraphicViewPort edi).GVPHeight]\n\tsub\tebx, [(GraphicViewPort edi).GVPHeight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax, ecx, 1\n\tshld\tedx, ebx, 1\n\n\txor\tal, 5\n\txor\tdl, 5\n\tmov\tah, al\n\ttest\tdl, al\n\tjnz\t??out\n\tor\tal, dl\n\tjz\t??not_clip\n\n\ttest\tah, 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx, [x0]\n\tneg\tebx\n\tmov\t[buffx0], ebx\n\tmov\t[x0], 0\n\n??scr_left_ok:\n\ttest\tah, 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx, [y0]\n\tneg\tebx\n\timul\tebx, [(MouseType esi).CursorWidth]\n\tadd\t[buffy0], ebx\n\tmov\t[y0], 0\n\n??scr_bottom_ok:\n\ttest\tdl, 0100b\n\tjz\t??scr_right_ok\n\tmov\teax, [(GraphicViewPort edi).GVPWidth]  ; get width into register\n\tmov\t[x1] , eax\n??scr_right_ok:\n\ttest\tdl, 0001b\n\tjz\t??not_clip\n\tmov\teax, [(GraphicViewPort edi).GVPHeight]  ; get width into register\n\tmov\t[y1] , eax\n\n??not_clip:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax, [y0]\n\tmov\tedx, [(GraphicViewPort edi).GVPWidth]\n\tadd\tedx, [(GraphicViewPort edi).GVPXAdd]\n\tadd\tedx, [(GraphicViewPort edi).GVPPitch]\n\timul\teax, edx\n\tadd\teax, [x0]\n\tmov\tedi, [(GraphicViewPort edi).GVPOffset]\n\tadd\tedi, eax\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx, [(MouseType esi).CursorWidth]\t; turn this into an offset\n\tmov\tesi, [buffy0]\t\t\t; edx points to source\n\tadd\tesi, [buffx0]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax, [x1]\n\tmov\tecx, [y1]\n\tsub\teax, [x0]\n\tjle\t??out\n\tsub\tecx, [y0]\n\tjle\t??out\n\n\tsub\tedx, eax\n\tsub\tebx, eax\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah, al\n??inner_loop:\n\tmov\tch, [esi]\n\tinc\tesi\n\ttest\tch, ch\n\tjz\t??inc_edi\n\tmov\t[edi], ch\n??inc_edi:\n\tinc\tedi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tesi, ebx      \t\t\t; move past right clipped pixels\n\tadd\tedi, edx      \t\t\t; adjust dest to next line\n\tdec\tcl\t      \t\t\t; decrement number of rows to do\n\tjnz\t??top_loop    \t\t\t; if more to do, do it\n??out:\n\tret\n\n\tENDP\tDraw_Mouse\n;***************************************************************************\n;* SET_MOUSE_CURSOR -- Sets the shape to be used as the mouse.             *\n;*                                                                         *\n;*    This will inform the system of the shape desired as the mouse        *\n;*    cursor.                                                              *\n;*                                                                         *\n;* INPUT:    xhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           yhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           cursor      -- Shape to use as the new mouse shape.           *\n;*                                                                         *\n;* OUTPUT:   Returns with a pointer to the original mouse shape.           *\n;*                                                                         *\n;* PROTO:\tVOID  *Set_Mouse_Cursor(\tint  xhotspot, \t\t   *\n;*\t\t\t\t\t\tint  yhotspot, \t\t   *\n;*\t\t\t\t\t\tvoid *cursor);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   02/13/1992 JLB : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC ASM_Set_Mouse_Cursor:NEAR\n\tPROC\tASM_Set_Mouse_Cursor C NEAR\n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\tthis:DWORD\t\t\t\t; pointer to mouse cursor struct\n\tARG\txhotspot:DWORD\t\t\t\t; the x hot spot of the mouse\n\tARG\tyhotspot:DWORD\t\t\t\t; the y hot spot of the mouse\n\tARG\tcursor:DWORD\t\t\t\t; ptr to the new mouse cursor\n\n\tLOCAL\tdatasize:DWORD\n\tLOCAL\tstype:WORD\n\tLOCAL\tswidth:DWORD\t\t; Shape width.\n\tLOCAL\tsheight:DWORD\t\t; Shape height.\n\tLOCAL\tssize:DWORD\t\t; Size of raw shape.\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\tmov\tesi,[this]\t\t\t; get offset of real mode data start\n\n\t;-------------------------------------------------------------------\n\t; Calculate the size of the buffer needed.\n\t;-------------------------------------------------------------------\n\tpush\t[cursor]\n\tcall\tGet_Shape_Uncomp_Size\n\tpop\tedx\n\tmov\t[datasize],eax\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Width\n\tpop\tedx\n\tmov\t[swidth],eax\n\tcmp\teax,[(MouseType esi).MaxWidth]\n\tjg\t??end\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Original_Height\n\tpop\tedx\n\tmov\t[sheight],eax\n\tcmp\teax,[(MouseType esi).MaxHeight]\n\tjg\t??end\n\n\n\tmov\tebx,[sheight]\n\tmov\teax,[swidth]\n\timul\tebx,eax\n\n??copy_mouse:\n\tmov\tedi,[(MouseType esi).MouseCursor]\t\t; set edi to point to mouse buffer\n\tmov\tesi,[cursor]\t\t\t; set esi to point to mouse shape\n\tmov\tax,[esi]\t\t\t; get the shape type byte\n\tmov\t[stype],ax\t\t\t; save off the shape type\n\ttest\tax,MAKESHAPE_NOCOMP\t\t; is it marked as no compression?\n\tje\t??comp_shape\t\t\t; if not go to the comped shape code\n\n??copy_type:\n\n\ttest\t[stype],MAKESHAPE_COMPACT\t; if the shape a 16 color shape?\n\tjne\t??16_color_copy\t\t\t; if it is then go handle it\n\n??normal_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed NORMAL shapes just get run-length uncompressed\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t\t; find size of shape in pixels\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes\n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??norm_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??norm_trans\t\t\t; if its a zero its transparent\n\tmov\t[edi],al\t\t\t; write out the pixel to dest\n\tinc\tedi\t\t\t\t; move to next dest position\n\tdec\tedx\t\t\t\t; we have now written another pix\n\tjnz\t??norm_unrle\t\t\t; if more to write then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are all done\n\n??norm_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\n\tjnz\t??norm_unrle\t\t\t; if more to do then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are done\n\n??16_color_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed 16 color shapes just get remaped and UN-RLE'd\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\tebx,esi\t\t\t\t; save of position of remap\n\tadd\tesi,16\t\t\t\t; move past remap table\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t; load up the height\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes\n\txor\teax,eax\t\t\t\t; clear high of lookup variable\n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??16_color_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??16_color_trans\t\t; if its a zero its transparent\n\tmov\tal,[ebx+eax]\t\t\t; remap the pixel from 16 color table\n\tmov\t[edi],al\t\t\t; store it out to the dest address\n\tinc\tedi\t\t\t\t; move to next dest address\n\tdec\tedx\t\t\t\t; we have now written a pixel\n\tjnz\t??16_color_unrle\n\tjmp\t??done_copy\n??16_color_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\t\t\t\t; subtract off count ahead of time\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\t\t\t\t; or edx to test for zero\n\tjnz\t??16_color_unrle\n\tjmp\t??done_copy\n\n\t;-------------------------------------------------------------------\n\t; Deal with the compressed shape by copying it into the shape\n\t;   staging buffer.\n\t;-------------------------------------------------------------------\n??comp_shape:\n\tmov\tedi,[ShapeBuffer]\t; get a pointer to ShapeBuffer\n\tmov\tax,[esi]\t\t; load in the shape type\n\tadd\tesi,2\t\t\t; increment the shape pointer\n\tor\tax,MAKESHAPE_NOCOMP\t; make the shape as uncompressed\n\tmov\t[stype],ax\t\t; save off the shape type\n\tmov\t[edi],ax\t\t; write out uncompressed shape\n\tadd\tedi,2\n\n\t;-------------------------------------------------------------------\n\t; Process the shape header information and copy it over to the new\n\t;   location.\n\t;-------------------------------------------------------------------\n\tmov\tecx,4 \t\t\t; transfer height, width, org and\n\ttest\teax,MAKESHAPE_COMPACT\t; is it a 16 color shape?\n\tje\t??copy_head\t\t; no - don't worry about it\n\tadd\tecx,8\t\t\t; otherwise adjust ecx for header\n??copy_head:\n\trep\tmovsw\t\t\t; copy the necessary bytes\n\n\tmov \teax,[datasize]\t\t; get uncompressed length\n\tpush\teax\t\t\t; push as third param\n\tpush\tedi\t\t\t; push the destination offset\n\tpush\tesi\t\t\t; push the source offset\n\tcall\tLCW_Uncompress\t\t; do the uncompress\n\tpop\teax\n\tpop\teax\n\tpop\teax\n\tmov\tesi,[this]\n\tmov\tedi,[(MouseType esi).MouseCursor]\t\t; set edi to point to mouse buffer\n\tmov\tesi,[ShapeBuffer]\n\tjmp\t??copy_type\n\n??done_copy:\n\tmov\tesi,[this]\t; get offset of real mode data start\n\n\tmov\teax,[xhotspot]\t\t; get the mouse cursors x hotspot\n\tmov\t[(MouseType esi).MouseXHot],eax\n\tmov\teax,[yhotspot]\t\t; get the mouse cursors y hotspot\n\tmov\t[(MouseType esi).MouseYHot],eax\n\n\tmov\tebx,[sheight]\t\t; get shape height\n\tmov\t[(MouseType esi).CursorHeight],ebx\n\tmov\tebx,[swidth]\n\tmov\t[(MouseType esi).CursorWidth],ebx\n\n\t;-------------------------------------------------------------------\n\t; Final cleanup and exit.\n\t;-------------------------------------------------------------------\n??end:\n\tpush\t[cursor]\n\tpush\t[(MouseType esi).PrevCursor]\n\tpop\teax\n\tpop\t[(MouseType esi).PrevCursor]\n\tret\t\t\t\t; and return back to the world\n\n\tENDP\tASM_Set_Mouse_Cursor\n\nEND\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/XORDELTA.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; **************************************************************************\n; **   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   *\n; **************************************************************************\n; *                                                                        *\n; *                 Project Name : WSA Support routines\t\t\t   *\n; *                                                                        *\n; *                    File Name : XORDELTA.ASM                            *\n; *                                                                        *\n; *                   Programmer : Scott K. Bowen\t\t\t   *\n; *                                                                        *\n; *                  Last Update :May 23, 1994   [SKB]                     *\n; *                                                                        *\n; *------------------------------------------------------------------------*\n; * Functions:                                                             *\n;*   Apply_XOR_Delta -- Apply XOR delta data to a buffer.                  *\n;*   Apply_XOR_Delta_To_Page_Or_Viewport -- Calls the copy or the XOR funti*\n;*   Copy_Delta_buffer -- Copies XOR Delta Data to a section of a page.    *\n;*   XOR_Delta_Buffer -- Xor's the data in a XOR Delta format to a page.   *\n; * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n\n\nLOCALS ??\n\n; These are used to call Apply_XOR_Delta_To_Page_Or_Viewport() to setup flags parameter.  If\n; These change, make sure and change their values in wsa.cpp.\nDO_XOR\t\tequ\t0\nDO_COPY\t\tequ\t1\nTO_VIEWPORT\tequ\t0\nTO_PAGE\t\tequ\t2\n\n;\n; Routines defined in this module\n;\n;\n; UWORD Apply_XOR_Delta(UWORD page_seg, BYTE *delta_ptr);\n; PUBLIC Apply_XOR_Delta_To_Page_Or_Viewport(UWORD page_seg, BYTE *delta_ptr, WORD width, WORD copy)\n;\n;\tPROC\tC XOR_Delta_Buffer\n;\tPROC\tC Copy_Delta_Buffer\n;\n\nGLOBAL \tC Apply_XOR_Delta:NEAR\nGLOBAL \tC Apply_XOR_Delta_To_Page_Or_Viewport:NEAR\n\n\n\n\tCODESEG\n\n\n\n;***************************************************************************\n;* APPLY_XOR_DELTA -- Apply XOR delta data to a linear buffer.             *\n;*   AN example of this in C is at the botton of the file commented out.   *\n;*                                                                         *\n;* INPUT:  BYTE *target - destination buffer.                              *\n;*         BYTE *delta - xor data to be delta uncompress.                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   05/23/1994 SKB : Created.                                             *\n;*=========================================================================*\nPROC\tApply_XOR_Delta C near\n\tUSES \tebx,ecx,edx,edi,esi\n\tARG\ttarget:DWORD \t\t; pointers.\n\tARG\tdelta:DWORD\t\t; pointers.\n\n\t; Optimized for 486/pentium by rearanging instructions.\n\tmov\tedi,[target]\t\t; get our pointers into offset registers.\n\tmov\tesi,[delta]\n\n\tcld\t\t\t\t; make sure we go forward\n\txor\tecx,ecx\t\t\t; use cx for loop\n\n??top_loop:\n\txor\teax,eax\t\t\t; clear out eax.\n\tmov\tal,[esi]\t\t; get delta source byte\n\tinc\tesi\n\n\ttest\tal,al\t\t\t; check for a SHORTDUMP ; check al incase of sign value.\n\tje\t??short_run\n\tjs\t??check_others\n\n;\n; SHORTDUMP\n;\n\tmov\tecx,eax\t\t\t; stick count in cx\n\n??dump_loop:\n\tmov\tal,[esi]\t\t;get delta XOR byte\n\txor\t[edi],al\t\t; xor that byte on the dest\n\tinc\tesi\n\tinc\tedi\n\tdec\tecx\n\tjnz\t??dump_loop\n\tjmp\t??top_loop\n\n;\n; SHORTRUN\n;\n\n??short_run:\n\tmov\tcl,[esi]\t\t; get count\n\tinc\tesi\t\t\t; inc delta source\n\n??do_run:\n\tmov\tal,[esi]\t\t; get XOR byte\n\tinc\tesi\n\n??run_loop:\n\txor\t[edi],al\t\t; xor that byte.\n\n\tinc\tedi\t\t\t; go to next dest pixel\n\tdec\tecx\t\t\t; one less to go.\n\tjnz\t??run_loop\n\tjmp\t??top_loop\n\n;\n; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP\n;\n\n??check_others:\n\tsub\teax,080h\t\t; opcode -= 0x80\n\tjnz\t??do_skip\t\t; if zero then get next word, otherwise use remainder.\n\n\tmov\tax,[esi]\n\tlea\tesi,[esi+2]\t\t; get word code in ax\n\ttest\tax,ax\t\t\t; set flags. (not 32bit register so neg flag works)\n\tjle\t??not_long_skip\n\n;\n; SHORTSKIP AND LONGSKIP\n;\n??do_skip:\n\tadd\tedi,eax\t\t\t; do the skip.\n\tjmp\t??top_loop\n\n\n??not_long_skip:\n\tjz\t??stop\t\t\t; long count of zero means stop\n\tsub\teax,08000h     \t\t; opcode -= 0x8000\n\ttest\teax,04000h\t\t; is it a LONGRUN (code & 0x4000)?\n\tje\t??long_dump\n\n;\n; LONGRUN\n;\n\tsub\teax,04000h\t\t; opcode -= 0x4000\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??do_run\t\t; jump to run code.\n\n\n;\n; LONGDUMP\n;\n\n??long_dump:\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??dump_loop\t\t; go to the dump loop.\n\n??stop:\n\n\tret\n\n\tENDP\tApply_XOR_Delta\n\n\n;----------------------------------------------------------------------------\n\n\n;***************************************************************************\n;* APPLY_XOR_DELTA_To_Page_Or_Viewport -- Calls the copy or the XOR funtion.           *\n;*                                                                         *\n;*\t\t\t\t\t\t\t\t\t   *\n;* \tThis funtion is call to either xor or copy XOR_Delta data onto a   *\n;*\tpage instead of a buffer.  The routine will set up the registers   *\n;*\tneed for the actual routines that will perform the copy or xor.\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tThe registers are setup as follows :\t\t\t\t   *\n;*\t\tes:edi - destination segment:offset onto page.\t\t   *\n;*\t\tds:esi - source buffer segment:offset of delta data.\t   *\n;*\t\tdx,cx,ax - are all zeroed out before entry.\t\t   *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/09/1992  SB : Created.                                             *\n;*=========================================================================*\n\n;PUBLIC Apply_XOR_Delta_To_Page_Or_Viewport(UWORD page_seg, BYTE *delta_ptr, WORD width, WORD flags, WORD descriptor)\nPROC\tApply_XOR_Delta_To_Page_Or_Viewport C near\n\tUSES \tebx,ecx,edx,edi,esi\n\tARG\ttarget:DWORD\t\t; pointer to the destination buffer.\n\tARG\tdelta:DWORD\t\t; pointer to the delta buffer.\n\tARG\twidth:DWORD\t\t; width of animation.\n\tARG\tnextrow:DWORD\t\t; Page/Buffer width - anim width.\n\tARG\tcopy:DWORD\t\t; should it be copied or xor'd?\n\n\n\tmov\tedi,[target]\t\t; Get the target pointer.\n\tmov\tesi,[delta]\t\t; Get the destination pointer.\n\n\txor\teax,eax\t\t\t; clear eax, later put them into ecx and edx.\n\n\tcld\t\t\t\t; make sure we go forward\n\n\tmov\tebx,[nextrow]\t\t; get the amount to add to get to next row from end.  push it later...\n\n\tmov\tecx,eax\t\t\t; use cx for loop\n\tmov\tedx,eax\t\t\t; use dx to count the relative column.\n\n\tpush\tebx\t\t\t; push nextrow onto the stack for Copy/XOR_Delta_Buffer.\n\tmov\tebx,[width]\t\t; bx will hold the max column for speed compares\n\n; At this point, all the registers have been set up.  Now call the correct function\n; to either copy or xor the data.\n\n\tcmp\t[copy],DO_XOR\t\t; Do we want to copy or XOR\n\tje\t??xorfunct\t\t; Jump to XOR if not copy\n\tcall\tCopy_Delta_Buffer\t; Call the function to copy the delta buffer.\n\tjmp\t??didcopy\t\t; jump past XOR\n??xorfunct:\n\tcall\tXOR_Delta_Buffer\t; Call funtion to XOR the deltat buffer.\n??didcopy:\n\tpop\tebx\t\t\t; remove the push done to pass a value.\n\n\tret\n\n\tENDP\tApply_XOR_Delta_To_Page_Or_Viewport\n;----------------------------------------------------------------------------\n\n\n;***************************************************************************\n;* XOR_DELTA_BUFFER -- Xor's the data in a XOR Delta format to a page.     *\n;*\tThis will only work right if the page has the previous data on it. *\n;*\tThis function should only be called by XOR_Delta_Buffer_To_Page_Or_Viewport.   *\n;*      The registers must be setup as follows :                           *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*\tes:edi - destination segment:offset onto page.\t\t \t   *\n;*\tds:esi - source buffer segment:offset of delta data.\t \t   *\n;*\tedx,ecx,eax - are all zeroed out before entry.\t\t \t   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/09/1992  SB : Created.                                             *\n;*=========================================================================*\n\nPROC\tXOR_Delta_Buffer C near\n\tARG\tnextrow:DWORD\n\n??top_loop:\n\txor\teax,eax\t\t\t; clear out eax.\n\tmov\tal,[esi]\t\t; get delta source byte\n\tinc\tesi\n\n\ttest\tal,al\t\t\t; check for a SHORTDUMP ; check al incase of sign value.\n\tje\t??short_run\n\tjs\t??check_others\n\n;\n; SHORTDUMP\n;\n\tmov\tecx,eax\t\t\t; stick count in cx\n\n??dump_loop:\n\tmov\tal,[esi]\t\t; get delta XOR byte\n\txor\t[edi],al\t\t; xor that byte on the dest\n\tinc\tesi\n\tinc\tedx\t\t\t; increment our count on current column\n\tinc\tedi\n\tcmp\tedx,ebx\t\t\t; are we at the final column\n\tjne\t??end_col1\t\t; if not the jmp over the code\n\n\tsub\tedi,edx\t\t\t; get our column back to the beginning.\n\txor\tedx,edx\t\t\t; zero out our column counter\n\tadd\tedi,[nextrow]\t\t; jump to start of next row\n??end_col1:\n\n\tdec\tecx\n\tjnz\t??dump_loop\n\tjmp\t??top_loop\n\n;\n; SHORTRUN\n;\n\n??short_run:\n\tmov\tcl,[esi]\t\t; get count\n\tinc\tesi\t\t\t; inc delta source\n\n??do_run:\n\tmov\tal,[esi]\t\t; get XOR byte\n\tinc\tesi\n\n??run_loop:\n\txor\t[edi],al\t\t; xor that byte.\n\n\tinc\tedx\t\t\t; increment our count on current column\n\tinc\tedi\t\t\t; go to next dest pixel\n\tcmp\tedx,ebx\t\t\t; are we at the final column\n\tjne\t??end_col2\t\t; if not the jmp over the code\n\n\tsub\tedi,ebx\t\t\t; get our column back to the beginning.\n\txor\tedx,edx\t\t\t; zero out our column counter\n\tadd\tedi,[nextrow]\t\t; jump to start of next row\n??end_col2:\n\n\n\tdec\tecx\n\tjnz\t??run_loop\n\tjmp\t??top_loop\n\n;\n; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP\n;\n\n??check_others:\n\tsub\teax,080h\t\t; opcode -= 0x80\n\tjnz\t??do_skip\t\t; if zero then get next word, otherwise use remainder.\n\n\tmov\tax,[esi]\t\t; get word code in ax\n\tlea\tesi,[esi+2]\n\ttest\tax,ax\t\t\t; set flags. (not 32bit register so neg flag works)\n\tjle\t??not_long_skip\n\n;\n; SHORTSKIP AND LONGSKIP\n;\n??do_skip:\n\tsub\tedi,edx\t\t\t; go back to beginning or row.\n\tadd\tedx,eax\t\t\t; incriment our count on current row\n??recheck3:\n\tcmp\tedx,ebx\t\t\t; are we past the end of the row\n\tjb\t??end_col3  \t\t; if not the jmp over the code\n\n\tsub\tedx,ebx\t\t\t; Subtract width from the col counter\n\tadd\tedi,[nextrow]  \t\t; jump to start of next row\n\tjmp\t??recheck3\t\t; jump up to see if we are at the right row\n??end_col3:\n\tadd\tedi,edx\t\t\t; get to correct position in row.\n\tjmp\t??top_loop\n\n\n??not_long_skip:\n\tjz\t??stop\t\t\t; long count of zero means stop\n\tsub\teax,08000h     \t\t; opcode -= 0x8000\n\ttest\teax,04000h\t\t; is it a LONGRUN (code & 0x4000)?\n\tje\t??long_dump\n\n;\n; LONGRUN\n;\n\tsub\teax,04000h\t\t; opcode -= 0x4000\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??do_run\t\t; jump to run code.\n\n\n;\n; LONGDUMP\n;\n\n??long_dump:\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??dump_loop\t\t; go to the dump loop.\n\n??stop:\n\n\tret\n\n\n\tENDP\tXOR_Delta_Buffer\n\n;----------------------------------------------------------------------------\n\n\n;***************************************************************************\n;* COPY_DELTA_BUFFER -- Copies XOR Delta Data to a section of a page.      *\n;*\tThis function should only be called by XOR_Delta_Buffer_To_Page_Or_Viewport.   *\n;*      The registers must be setup as follows :                           *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*\tes:edi - destination segment:offset onto page.\t\t \t   *\n;*\tds:esi - source buffer segment:offset of delta data.\t \t   *\n;*\tdx,cx,ax - are all zeroed out before entry.\t\t \t   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/09/1992  SB : Created.                                             *\n;*=========================================================================*\nPROC\tCopy_Delta_Buffer C near\n\tARG\tnextrow:DWORD\n\n??top_loop:\n\txor\teax,eax\t\t\t; clear out eax.\n\tmov\tal,[esi]\t\t; get delta source byte\n\tinc\tesi\n\n\ttest\tal,al\t\t\t; check for a SHORTDUMP ; check al incase of sign value.\n\tje\t??short_run\n\tjs\t??check_others\n\n;\n; SHORTDUMP\n;\n\tmov\tecx,eax\t\t\t; stick count in cx\n\n??dump_loop:\n\tmov\tal,[esi]\t\t; get delta XOR byte\n\n\tmov\t[edi],al\t\t; store that byte on the dest\n\n\tinc\tedx\t\t\t; increment our count on current column\n\tinc\tesi\n\tinc\tedi\n\tcmp\tedx,ebx\t\t\t; are we at the final column\n\tjne\t??end_col1\t\t; if not the jmp over the code\n\n\tsub\tedi,edx\t\t\t; get our column back to the beginning.\n\txor\tedx,edx\t\t\t; zero out our column counter\n\tadd\tedi,[nextrow]\t\t; jump to start of next row\n??end_col1:\n\n\tdec\tecx\n\tjnz\t??dump_loop\n\tjmp\t??top_loop\n\n;\n; SHORTRUN\n;\n\n??short_run:\n\tmov\tcl,[esi]\t\t; get count\n\tinc\tesi\t\t\t; inc delta source\n\n??do_run:\n\tmov\tal,[esi]\t\t; get XOR byte\n\tinc\tesi\n\n??run_loop:\n\tmov\t[edi],al\t\t; store the byte (instead of XOR against current color)\n\n\tinc\tedx\t\t\t; increment our count on current column\n\tinc\tedi\t\t\t; go to next dest pixel\n\tcmp\tedx,ebx\t\t\t; are we at the final column\n\tjne\t??end_col2\t\t; if not the jmp over the code\n\n\tsub\tedi,ebx\t\t\t; get our column back to the beginning.\n\txor\tedx,edx\t\t\t; zero out our column counter\n\tadd\tedi,[nextrow]\t\t; jump to start of next row\n??end_col2:\n\n\n\tdec\tecx\n\tjnz\t??run_loop\n\tjmp\t??top_loop\n\n;\n; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP\n;\n\n??check_others:\n\tsub\teax,080h\t\t; opcode -= 0x80\n\tjnz\t??do_skip\t\t; if zero then get next word, otherwise use remainder.\n\n\tmov\tax,[esi]\t\t; get word code in ax\n\tlea\tesi,[esi+2]\n\ttest\tax,ax\t\t\t; set flags. (not 32bit register so neg flag works)\n\tjle\t??not_long_skip\n\n;\n; SHORTSKIP AND LONGSKIP\n;\n??do_skip:\n\tsub\tedi,edx\t\t\t; go back to beginning or row.\n\tadd\tedx,eax\t\t\t; incriment our count on current row\n??recheck3:\n\tcmp\tedx,ebx\t\t\t; are we past the end of the row\n\tjb\t??end_col3  \t\t; if not the jmp over the code\n\n\tsub\tedx,ebx\t\t\t; Subtract width from the col counter\n\tadd\tedi,[nextrow]  \t\t; jump to start of next row\n\tjmp\t??recheck3\t\t; jump up to see if we are at the right row\n??end_col3:\n\tadd\tedi,edx\t\t\t; get to correct position in row.\n\tjmp\t??top_loop\n\n\n??not_long_skip:\n\tjz\t??stop\t\t\t; long count of zero means stop\n\tsub\teax,08000h     \t\t; opcode -= 0x8000\n\ttest\teax,04000h\t\t; is it a LONGRUN (code & 0x4000)?\n\tje\t??long_dump\n\n;\n; LONGRUN\n;\n\tsub\teax,04000h\t\t; opcode -= 0x4000\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??do_run\t\t; jump to run code.\n\n\n;\n; LONGDUMP\n;\n\n??long_dump:\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??dump_loop\t\t; go to the dump loop.\n\n??stop:\n\n\tret\n\n\tENDP\tCopy_Delta_Buffer\n\n;----------------------------------------------------------------------------\n\n\tEND\n\n\n;----------------------------------------------------------------------------\n;\n;PUBLIC UWORD Apply_XOR_Delta(UWORD page_seg, BYTE *delta_ptr)\n;{\n;\n;\tregister UWORD loop;\n;\tBYTE opcode, xor_byte;\n;\tUWORD bytes_to_uncompress = 64000U;\n;\n;\n;\t/* Make our buffer pointer */\n;\n;\tto    = MK_FP(page_seg, 0);\n;\tdelta = Normalize_Pointer(delta_ptr);\n;\n;\n;\twhile (bytes_to_uncompress) {\n;\n;\t\topcode = *delta++;\n;\n;\n;\t\t/* Check for SHORTDUMP */\n;\n;\t\tif (opcode > 0) {\n;\n;\n;\t\t\tbytes_to_uncompress -= opcode;\n;\n;\t\t\tfor (loop = 0; loop < opcode; loop++) {\n;\t\t\t\txor_byte = *delta++;\n;\t\t\t\t*to++ ^= xor_byte;\n;\t\t\t}\n;\t\t\tcontinue;\n;\t\t}\n;\n;\t\t/* Check for SHORTRUN */\n;\n;\t\tif (opcode == 0) {\n;\n;\t\t\tword_count = *delta++;\n;\t\t\txor_byte   = *delta++;\n;\n;\t\t\tbytes_to_uncompress -= word_count;\n;\n;\t\t\tfor (loop = 0; loop < word_count; loop++) {\n;\t\t\t\t*to++ ^= xor_byte;\n;\t\t\t}\n;\t\t\tcontinue;\n;\t\t}\n;\n;\t\t/* By now, we know it must be a LONGDUMP, SHORTSKIP, or LONGSKIP */\n;\n;\t\topcode -= 0x80;\n;\n;\n;\t\t/* Is it a SHORTSKIP? */\n;\n;\t\tif (opcode != 0) {\n;\n;\t\t\tto += opcode;\n;\t\t\tbytes_to_uncompress -= (WORD) opcode;\n;\t\t\tcontinue;\n;\t\t}\n;\n;\n;\t\tword_count = *((UWORD *) delta)++;\n;\n;\t\t/* Is it a LONGSKIP? */\n;\n;\t\tif ((WORD) word_count > 0) {\n;\n;\t\t\tto += word_count;\n;\t\t\tbytes_to_uncompress -= (WORD) word_count;\n;\t\t\tcontinue;\n;\t\t}\n;\n;\n;\t\tword_count -= 0x8000;\n;\n;\t\t/* Is it a LONGRUN? */\n;\n;\t\tif (word_count & 0x4000) {\n;\n;\t\t\tword_count -= 0x4000;\n;\n;\t\t\tbytes_to_uncompress -= word_count;\n;\n;\t\t\txor_byte = *delta++;\n;\n;\t\t\tfor (loop = 0; loop < word_count; loop++) {\n;\t\t\t\t*to++ ^= xor_byte;\n;\t\t\t}\n;\t\t\tcontinue;\n;\t\t}\n;\n;\n;\t\t/* It must be a LONGDUMP */\n;\n;\t\tbytes_to_uncompress -= word_count;\n;\n;\t\tfor (loop = 0; loop < word_count; loop++) {\n;\t\t\txor_byte = *delta++;\n;\t\t\t*to++ ^= xor_byte;\n;\t\t}\n;\t}\n;\n;\n;\treturn(64000U);\n;}\n;\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/SRCDEBUG/_DIPTABL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./_diptabl.c 1.11 1994/05/20 15:36:04 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : _DIPTABL.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : July 3, 1991                             *\n *                                                                         *\n *                  Last Update : July 3, 1991   [JLB]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nchar Common[16]={' ','e','t','a','i','n','o','s','r','l','h','c','d','u','p','m'};\n\nchar Dipthong[16][8]={\n\t{'t','a','s','i','o',' ','w','b'},\n\t{' ','r','n','s','d','a','l','m'},\n\t{'h',' ','i','e','o','r','a','s'},\n\t{'n','r','t','l','c',' ','s','y'},\n\t{'n','s','t','c','l','o','e','r'},\n\t{' ','d','t','g','e','s','i','o'},\n\t{'n','r',' ','u','f','m','s','w'},\n\t{' ','t','e','p','.','i','c','a'},\n\t{'e',' ','o','i','a','d','u','r'},\n\t{' ','l','a','e','i','y','o','d'},\n\t{'e','i','a',' ','o','t','r','u'},\n\t{'e','t','o','a','k','h','l','r'},\n\t{' ','e','i','u',',','.','o','a'},\n\t{'n','s','r','c','t','l','a','i'},\n\t{'l','e','o','i','r','a','t','p'},\n\t{'e','a','o','i','p',' ','b','m'},\n};\n\u001a"
  },
  {
    "path": "WIN32LIB/TILE/ICONSET.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library                                  *\n *                                                                         *\n *                    File Name : ICONSET.C                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : June 9, 1991                             *\n *                                                                         *\n *                  Last Update : September 15, 1993   [JLB]               *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Load_Icon_Set -- Loads an icons set and initializes it.               *\n *   Free_Icon_Set -- Frees allocations made by Load_Icon_Set().           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n//#include\t\"function.h\"\n\n#define\t\t_WIN32\n#define\t\tWIN32_LEAN_AND_MEAN\n\n#include\t<dos.h>\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<mem.h>\n#include\t<wwstd.h>\n#include\t<file.h>\n#include\t\"tile.h\"\n#include\t<iff.h>\n\n\n\nextern int Misc;\n\nvoid *  Load_Icon_Set(char const *filename, void *iconsetptr, long buffsize);\nvoid  Free_Icon_Set(void const *iconset);\nlong  Get_Icon_Set_Size(void const *iconset);\nint  Get_Icon_Set_Width(void const *iconset);\nint  Get_Icon_Set_Height(void const *iconset);\nvoid *  Get_Icon_Set_Icondata(void const *iconset);\nvoid *  Get_Icon_Set_Trans(void const *iconset);\nvoid *  Get_Icon_Set_Remapdata(void const *iconset);\nvoid *  Get_Icon_Set_Palettedata(void const *iconset);\nint  Get_Icon_Set_Count(void const *iconset);\nvoid *  Get_Icon_Set_Map(void const *iconset);\n\n\n//#define\tICON_PALETTE_BYTES\t16\n//#define\tICON_MAX\t\t\t\t\t256\n\n/***************************************************************************\n**\tThe terrain is rendered by using icons.  These are the buffers that hold\n**\tthe icon data, remap tables, and remap index arrays.\n*/\n//PRIVATE char *IconPalette = NULL;\t\t// MCGA only.\n//PRIVATE char *IconRemap = NULL;\t\t\t// MCGA only.\n\n#define\tFORM_RPAL\tMAKE_ID('R','P','A','L')\n#define\tFORM_RTBL\tMAKE_ID('R','T','B','L')\n#define\tFORM_SSET\tMAKE_ID('S','S','E','T')\n#define\tFORM_SINF\tMAKE_ID('S','I','N','F')\n#define\tFORM_ICON\tMAKE_ID('I','C','O','N')\n#define\tFORM_TRNS\tMAKE_ID('T','R','N','S')\n#define\tFORM_MAP\t\tMAKE_ID('M','A','P',' ')\n\n\n\n/***************************************************************************\n * LOAD_ICON_SET -- Loads an icons set and initializes it.                 *\n *                                                                         *\n *    This routine will load an IFF icon set from disk.  It handles all    *\n *    of the necessary allocations.                                        *\n *                                                                         *\n * INPUT:   filename -- Name of the icon file.                             *\n *                                                                         *\n *          buffer   -- Pointer to paragraph aligned buffer to hold data.  *\n *                                                                         *\n *          size     -- Size of the buffer (in bytes).                     *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   In EEGA mode the iconset buffer will be free because the    *\n *             icons will have been transferred to card ram.               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1991 JLB : Created.                                             *\n *   07/01/1991 JLB : Determines icon size from file.                      *\n *   07/15/1991 JLB : Load and uncompress onto the same buffer.            *\n *   09/15/1993 JLB : Added EMS support.                                   *\n *=========================================================================*/\nvoid *  Load_Icon_Set(char const *filename, void *iconsetptr, long buffsize)\n{\n\tint\tfh;\t\t\t\t// File handle of iconset.\n\tint\tbytespericon;\t// The number of bytes per icon.\n\tunsigned long\ticons=0;\t\t\t// Number of icons loaded.\n\tunsigned long\tsize;\t\t\t\t// Size of the icon chunk (raw).\n\n\tunsigned long\ttranssize;\n\tvoid\t*transptr=NULL;\n\n\tunsigned long\tmapsize;\t\t\t\t// Icon map chunk size.\n\tvoid\t*mapptr=NULL;\t\t// Icon map pointer.\n\tvoid\t*returnptr=NULL;\t// Iconset pointer returned by routine.\n\tBOOL\tallocated=FALSE;\t// Was the iconset block allocated?\n\tIControl_Type\t*idata=NULL;\t// Icon data loaded.\n\tlong\tid;\t\t\t\t// ID of file openned.\n\tstruct {\n\t\tchar\tWidth;\t\t// Width of icon in bytes.\n\t\tchar\tHeight;\t\t// Height of icon in bytes.\n\t\tchar\tFormat;\t\t// Graphic mode.\n\t\t\t\t\t\t\t\t//lint -esym(754,Format)\n\t\tchar\tBitplanes;\t// Number of bitplanes per icon.\n\t} sinf;\n\n\t/*\n\t**\tOpen the icon set for loading.  If it is not a legal icon set\n\t**\tdata file, then abort.\n\t*/\n\tfh = Open_Iff_File(filename);\n\tif (fh != WW_ERROR) {\n\t\tRead_File(fh, &id, sizeof(long));\n\t\tif (id == FORM_ICON) {\n\n\t\t\t/*\n\t\t\t**\tDetermine the size of the icons and set up the graphic\n\t\t\t**\tsystem accordingly.  Also get the sizes of the various\n\t\t\t**\tdata blocks that have to be loaded.\n\t\t\t*/\n\t\t\tRead_Iff_Chunk(fh, FORM_SINF, &sinf, sizeof(sinf));\n\t\t\tbytespericon = ((((int)sinf.Width)<<3)*(((int)sinf.Height)<<3)*(int)sinf.Bitplanes)>>3;\n\n\t\t\tsize = Get_Iff_Chunk_Size(fh,FORM_SSET);\n\t\t\t\ttranssize = Get_Iff_Chunk_Size(fh, FORM_TRNS);\n\t\t\tmapsize = Get_Iff_Chunk_Size(fh, FORM_MAP);\n\n\t\t\t/*\n\t\t\t**\tAllocate the icon buffer if one isn't provided.  First try EMS and\n\t\t\t**\tthen try conventional RAM.\n\t\t\t*/\n\t\t\tallocated = FALSE;\n\t\t\tif (!iconsetptr) {\n\t\t\t\t\tbuffsize = size + transsize + mapsize + sizeof(IControl_Type);\n\n\t\t\t\tMisc = buffsize;\n\t\t\t\ticonsetptr = Alloc(buffsize, MEM_NORMAL);\n\t\t\t\tallocated = (iconsetptr != NULL);\n\t\t\t}\n\n\t\t\tif (iconsetptr && (size+transsize+mapsize+sizeof(IControl_Type)) <= buffsize) {\n\n\t\t\t\tidata = (IControl_Type *)iconsetptr;\n\n\t\t\t\tmemset(idata, 0, sizeof(IControl_Type));\n\n\t\t\t\t/*\n\t\t\t\t**\tInitialize the iconset header structure.\n\t\t\t\t*/\n\t\t\t\tidata->Width = (short)(((short)sinf.Width)<<3);\n\t\t\t\tidata->Height = (short)(((short)sinf.Height)<<3);\n\t\t\t\tidata->Allocated = (short)allocated;\n\t\t\t\tidata->Icons = (long)iconsetptr + sizeof(IControl_Type);\n\t\t\t\tidata->Map = idata->Icons + size;\n\t\t\t\t\tidata->TransFlag = sizeof(IControl_Type) + size + mapsize;\n\t\t\t\tidata->Size = buffsize;\n\n\t\t\t\t\t{\n\t\t\t\t\t\tlong\tval;\n\n\t\t\t\t\t\tval = Read_Iff_Chunk(fh, FORM_SSET, Add_Long_To_Pointer(iconsetptr, sizeof(IControl_Type)), size);\n\t\t\t\t\t\ticons = (int)(val/(long)bytespericon);\n\t\t\t\t\t\tidata = (IControl_Type *)iconsetptr;\n\t\t\t\t\t}\n\n\t\t\t\tif (mapsize) {\n\t\t\t\t\ticons = mapsize;\n\t\t\t\t}\n\t\t\t\tidata->Count = (short)icons;\n\n\t\t\t\t/*\n\t\t\t\t**\tLimit buffer to only the size needed.  This is done AFTER loading of the\n\t\t\t\t**\traw icon data because it might have been compressed and thus need any\n\t\t\t\t**\textra space to perform an overlapped decompression.\n\t\t\t\t*/\n\t\t\t\t\tif (buffsize > size + transsize + mapsize + sizeof(IControl_Type)) {\n\t\t\t\t\t\tbuffsize = size + transsize + mapsize + sizeof(IControl_Type);\n\t\t\t\t\t}\n\n\t\t\t\t\ttransptr = Add_Long_To_Pointer(iconsetptr, idata->TransFlag);\n\t\t\t\t\tRead_Iff_Chunk(fh, FORM_TRNS, transptr, transsize);\n\t\t\t\t\tidata = (IControl_Type *)iconsetptr;\n\n\t\t\t\tmapptr = (void*)idata->Map;\n\t\t\t\tRead_Iff_Chunk(fh, FORM_MAP, mapptr, mapsize);\n\n\t\t\t\t/*\n\t\t\t\t**\tLet the graphic overlay know of the icon data.  This could involve\n\t\t\t\t**\ttranslation and other data manipulations.\n\t\t\t\t*/\n\t\t\t\t//Init_Stamps(iconsetptr);\n\n\t\t\t\treturnptr = iconsetptr;\n\t\t\t}\n\t\t}\n\t\tClose_Iff_File(fh);\n\t}\n\n\treturn (returnptr);\t\t// Return with icon pointer.\n}\n\n\n/***************************************************************************\n * FREE_ICON_SET -- Frees allocations made by Load_Icon_Set().             *\n *                                                                         *\n *    This routine is used to free up any allocations by Load_Icon_Set().  *\n *    Use this routine when a new icon set is to be loaded.                *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid  Free_Icon_Set(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tif (icontrol->Allocated) {\n\t\t\tFree((void *)iconset);\n\t\t}\n\t}\n}\n\n\nlong  Get_Icon_Set_Size(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tlong\t\t\t\tsize=0;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tsize = icontrol->Size;\n\t}\n\treturn(size);\n}\n\n\nint  Get_Icon_Set_Width(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tint\t\t\t\twidth=0;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\twidth = icontrol->Width;\n\t}\n\treturn(width);\n}\n\n\nint  Get_Icon_Set_Height(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tint\t\t\t\theight=0;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\theight = icontrol->Height;\n\t}\n\treturn(height);\n}\n\n\nvoid *  Get_Icon_Set_Icondata(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol)\n\t\treturn(Add_Long_To_Pointer(iconset, (LONG)icontrol->Icons));\n\treturn(NULL);\n}\n\nvoid *  Get_Icon_Set_Trans(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tvoid\t\t\t\t*ptr=NULL;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tptr = Add_Long_To_Pointer((void *)iconset, icontrol->TransFlag);\n\t}\n\treturn(ptr);\n}\n\n\nint  Get_Icon_Set_Count(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tint\t\t\t\tcount;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tcount = icontrol->Count;\n\t}\n\treturn(count);\n}\n\n\nvoid *  Get_Icon_Set_Map(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol)\n\t\treturn(Add_Long_To_Pointer(iconset, (LONG)icontrol->Map));\n\treturn(NULL);\n}\n"
  },
  {
    "path": "WIN32LIB/TILE/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = tile\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\t\ticonset.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\tmkdir run\n\tcd run\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\run\\vcs.cfg\n\tupdate\n\tcd..\n\tmkdir art\n\tcd art\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\art\\vcs.cfg\n\tupdate\n\tcd..\n\twmake\n\tcd ..\n\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/TILE/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = tile\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t\ticonset.obj\t\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) \n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n -+iconset.obj\n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/TILE/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = tile\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\t\ticonset.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include \n\t copy *.inc $(%WIN32LIB)\\include \n\t copy *.cpp $(%WIN32LIB)\\srcdebug \n\t copy *.asm $(%WIN32LIB)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\tmkdir run\n\tcd run\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\run\\vcs.cfg\n\tupdate\n\tcd..\n\tmkdir art\n\tcd art\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\art\\vcs.cfg\n\tupdate\n\tcd..\n\twmake \n\tcd ..\n\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/TILE/TILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the TILE Library                 *\n *                                                                         *\n *                    File Name : TILE.H                                   *\n *                                                                         *\n *                   Programmer : Barry W. Green                           *\n *                                                                         *\n *                   Start Date : February 2, 1995                         *\n *                                                                         *\n *                  Last Update : February 2, 1995 [BWG]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TILE_H\n#define TILE_H\n\n/*=========================================================================*/\n/* The following prototypes are for the file: ICONSET.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid * Load_Icon_Set(char const *filename, void *iconsetptr, long buffsize);\nvoid Free_Icon_Set(void const *iconset);\nlong Get_Icon_Set_Size(void const *iconset);\nint Get_Icon_Set_Width(void const *iconset);\nint Get_Icon_Set_Height(void const *iconset);\nvoid * Get_Icon_Set_Icondata(void const *iconset);\nvoid * Get_Icon_Set_Trans(void const *iconset);\nvoid * Get_Icon_Set_Remapdata(void const *iconset);\nvoid * Get_Icon_Set_Palettedata(void const *iconset);\nint Get_Icon_Set_Count(void const *iconset);\nvoid * Get_Icon_Set_Map(void const *iconset);\n#if (0)\n/*\n** This is the control structure at the start of a loaded icon set.  It must match\n** the structure in WWLIB.I!  This structure MUST be a multiple of 16 bytes long.\n*/\ntypedef struct {\n\tshort\tWidth;\t\t\t// Width of icons (pixels).\n\tshort\tHeight;\t\t\t// Height of icons (pixels).\n\tshort\tCount;\t\t\t// Number of (logical) icons in this set.\n//\tBOOL\tAllocated;\t\t// Was this iconset allocated?\n\tshort\tAllocated;\t\t// Was this iconset allocated?\n\tlong\tSize;\t\t\t\t// Size of entire iconset memory block.\n\tunsigned char *Icons;\t\t\t// Offset from buffer start to icon data.\n\tlong\tPalettes;\t\t// Offset from buffer start to palette data.\n\tlong\tRemaps;\t\t\t// Offset from buffer start to remap index data.\n\tlong\tTransFlag;\t\t// Offset for transparency flag table.\n\tunsigned char *Map;\t\t\t\t// Icon map offset (if present).\n} IControl_Type;\n#endif\t//(0)\n\ntypedef struct {\n\tshort\tWidth;\t\t\t// Width of icons (pixels).\n\tshort\tHeight;\t\t\t// Height of icons (pixels).\n\tshort\tCount;\t\t\t// Number of (logical) icons in this set.\n\tshort\tAllocated;\t\t// Was this iconset allocated?\n\tshort MapWidth;\t\t// Width of map (in icons).\n\tshort MapHeight;\t\t// Height of map (in icons).\n\tlong\tSize;\t\t\t\t// Size of entire iconset memory block.\n\tlong\tIcons;\t\t\t// Offset from buffer start to icon data.\n//\tunsigned char * Icons;\t// Offset from buffer start to icon data.\n\tlong\tPalettes;\t\t// Offset from buffer start to palette data.\n\tlong\tRemaps;\t\t\t// Offset from buffer start to remap index data.\n\tlong\tTransFlag;\t\t// Offset for transparency flag table.\n\tlong\tColorMap;\t\t// Offset for color control value table.\n\tlong\tMap;\t\t\t\t// Icon map offset (if present).\n//\tunsigned char * Map;\t\t\t\t// Icon map offset (if present).\n} IControl_Type;\n\n\n#endif //TILE_H\n\n"
  },
  {
    "path": "WIN32LIB/TIMER/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = timer\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\ttimer.obj\t&\n\ttimerdwn.obj\t&\n\ttimerini.obj\n\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n\n#---------------------------------------------------------------------------\n# The keyboard object files is also dependant on an IBN file which is\n#   generated from KEYIREAL.ASM\n#---------------------------------------------------------------------------\ntimereal.ibn: timereal.obj\n\t%create\t$^*.rsp\n\t%append $^*.rsp $^&.obj\n\t%append $^*.rsp $^&.exe\n\t%append $^*.rsp $^&.map\n\ttlink @$^*.rsp\n        tdstrip timereal.exe\n        ebn\ttimereal.exe\n\ntimereal.obj:\ttimereal.asm\n\ttasm /zn /la /ml /m2 timereal.asm\n\ntimera.obj: timereal.ibn timera.asm\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/TIMER/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = timer\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t\ttimer.obj\t\t\\\n\t\t\t\ttimerdwn.obj\t\\\n\t\t\t\ttimerini.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) \n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n +-timer.obj\t\t&\n+-timerdwn.obj\t&\n+-timerini.obj\n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/TIMER/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = timer\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\ttimer.obj\t&\n\ttimerdwn.obj\t&\n\ttimerini.obj\n\n \n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include \n\t copy *.inc $(%WIN32LIB)\\include \n\t copy *.cpp $(%WIN32LIB)\\srcdebug \n\t copy *.asm $(%WIN32LIB)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n\n#---------------------------------------------------------------------------\n# The keyboard object files is also dependant on an IBN file which is \n#   generated from KEYIREAL.ASM\n#---------------------------------------------------------------------------\ntimereal.ibn: timereal.obj\n\t%create\t$^*.rsp\n\t%append $^*.rsp $^&.obj\n\t%append $^*.rsp $^&.exe\n\t%append $^*.rsp $^&.map\n\ttlink @$^*.rsp\n        tdstrip timereal.exe\n        ebn\ttimereal.exe\n\ntimereal.obj:\ttimereal.asm\n\ttasm /zn /la /ml /m2 timereal.asm\n\ntimera.obj: timereal.ibn timera.asm\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/TIMER/TIMER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Temp timer for 32bit lib                 *\n *                                                                         *\n *                    File Name : TIMER.CPP                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : July 6, 1994                             *\n *                                                                         *\n *                  Last Update : May 3, 1995   [SKB]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   TC::Time -- Return the time on the timer.                             *\n *   TC::TimerClass -- Construct a timer class object.                     *\n *   TC::Stop -- Stop the timer.                                           *\n *   TC::Start -- Start a timer.                                           *\n *   TC::Set -- Set the time of a timer.                                   *\n *   TC::Reset -- Clear the timer.                                         *\n *   TimerClass::Time -- Get the current time of timer.                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"timer.H\"\n#include <stdio.h>\n#include <stdlib.h>\n\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////////// Code ////////////////////////////////////////\n\n/***************************************************************************\n * TC::TIMERCLASS -- Construct a timer class object.                       *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nTimerClass::TimerClass(BaseTimerEnum timer, BOOL on)\n{\n\tAccumulated = 0;\n\tStarted = 0;\n\n\tTickType=timer;\n\n\tif (on && TimerSystemOn) Start();\n}\n\n\n\n\n/***********************************************************************************************\n * TC:Get_Ticks -- return the number of ticks on the system or user timers                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   tick count                                                                        *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *              10/5/95 4:17PM ST : Created                                                    *\n *=============================================================================================*/\n\nlong TimerClass::Get_Ticks ( void )\n\n{\n\tif ( WindowsTimer ){\n\t\tswitch ( TickType ){\n\n\t\t \tcase BT_SYSTEM :\n\t\t\t\treturn ( WindowsTimer->Get_System_Tick_Count() );\n\n\t\t \tcase BT_USER :\n\t\t\t\treturn ( WindowsTimer->Get_User_Tick_Count() );\n\n\t\t}\n\t}\n\treturn 0;\n}\n\n\n\n/***************************************************************************\n * TIMERCLASS::TIME -- Get the current time of timer.                      *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1995 SKB : Created.                                             *\n *=========================================================================*/\nlong TimerClass::Time(void)\n{\n\tif (Started) {\n\t\tlong ticks = Get_Ticks();\n\t\tAccumulated += ticks - (Started-1);\n\t\tStarted = ticks+1;\n\t}\n\treturn(Accumulated);\n}\n\n\n/***************************************************************************\n * TC::STOP -- Stop the timer.                                             *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong TimerClass::Stop(void)\n{\n\tlong time = Time();\n\tStarted = 0;\n\treturn(time);\n}\n\n\n/***************************************************************************\n * TC::START -- Start a timer.                                             *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong TimerClass::Start(void)\n{\n\tif (!Started) {\n\t\tStarted = Get_Ticks()+1;\n\t}\n\treturn(Time());\n}\n\n\n/***************************************************************************\n * TC::SET -- Set the time of a timer.                                     *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:  long value to set timer at.                                     *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *   05/03/1995 SKB : If start return Start since it returns Time          *\n *=========================================================================*/\nlong TimerClass::Set(long value, BOOL start)\n{\n\tStarted = 0;\n\tAccumulated = value;\n\tif (start) return (Start());\n\treturn(Time());\n}"
  },
  {
    "path": "WIN32LIB/TIMER/TIMER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Timer Class Functions                    *\n *                                                                         *\n *                    File Name : TIMER.H                                  *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : July 6, 1994                             *\n *                                                                         *\n *                  Last Update : July 12, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TIMER_H\n#define TIMER_H\n\n\n#define WIN32 1\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#include <windows.h>\n#include <windowsx.h>\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TIMERA.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// Externs /////////////////////////////////////////////\nextern BOOL \t\tTimerSystemOn;\nextern\tHANDLE\tTimerThreadHandle;\t\t//Handle of timer thread\nextern\tint\t\tInTimerCallback;\t\t\t//true if we are currently in a callback\n\n\n/*=========================================================================*/\ntypedef enum BaseTimerEnum {\n\tBT_SYSTEM,\t\t\t// System timer (60 / second).\n\tBT_USER\t\t\t\t// User controllable timer (? / second).\n} BaseTimerEnum;\n\nclass TimerClass {\n \tpublic:\n\t\t// Constructor.  Timers set before low level init has been done will not\n\t\t// be able to be 'Started' or 'on' until timer system is in place.\n\t\tTimerClass(BaseTimerEnum timer=BT_SYSTEM, BOOL start=FALSE);\n\n\t\t// No destructor.\n\t\t~TimerClass(void){}\n\n\t\t//\n\t\tlong Set(long value, BOOL start=TRUE);\t// Set initial timer value.\n\t\tlong Stop(void);\t\t\t\t// Pause timer.\n\t\tlong Start(void);\t\t\t\t// Resume timer.\n\t\tlong Reset(BOOL start=TRUE);\t// Reset timer to zero.\n\t\tlong Time(void);\t\t\t\t// Fetch current timer value.\n\n\tprotected:\n\t\tlong Started;\t\t\t\t\t// Time last started (0 == not paused).\n\t\tlong Accumulated;\t\t\t\t//\tTotal accumulated ticks.\n\n\tprivate:\n//\t\tlong (*Get_Ticks)(void);\t// System timer fetch.\n\t\tBaseTimerEnum\tTickType;\n\t\tlong Get_Ticks (void);\n};\n\n\ninline long TimerClass::Reset(BOOL start)\n{\n\treturn(Set(0, start));\n}\n\n\nclass CountDownTimerClass : private TimerClass {\n\tpublic:\n\t\t// Constructor.  Timers set before low level init has been done will not\n\t\t// be able to be 'Started' or 'on' until timer system is in place.\n\t\tCountDownTimerClass(BaseTimerEnum timer, long set, int on=FALSE);\n\t\tCountDownTimerClass(BaseTimerEnum timer=BT_SYSTEM, int on=FALSE);\n\n\t\t// No destructor.\n\t\t~CountDownTimerClass(void){}\n\n\t\t// Public functions\n\t\tlong Set(long set, BOOL start=TRUE);\t// Set count down value.\n\t\tlong Reset(BOOL start=TRUE);\t// Reset timer to zero.\n\t\tlong Stop(void);\t\t\t// Pause timer.\n\t\tlong Start(void);\t\t\t// Resume timer.\n\t\tlong Time(void);\t\t\t// Fetch current count down value.\n\n\tprotected:\n\t\tlong DelayTime;\t\t\t// Ticks remaining before countdown timer expires.\n};\n\ninline long CountDownTimerClass::Stop(void)\n{\n\tTimerClass::Stop();\n\treturn(Time());\n}\n\ninline long CountDownTimerClass::Start(void)\n{\n\tTimerClass::Start();\n\treturn(Time());\n}\n\ninline long CountDownTimerClass::Reset(BOOL start)\n{\n\treturn (TimerClass::Reset(start));\n}\n\n\n\n\nclass WinTimerClass {\n\n\tpublic:\n\t\tWinTimerClass ( UINT freq=60 , BOOL partial=0 );\n\t\t~WinTimerClass();\n\n\t\tvoid \t\tUpdate_Tick_Count ( void );\n\t\tunsigned\tGet_System_Tick_Count ( void );\n\t\tunsigned\tGet_User_Tick_Count ( void );\n\n\tprivate:\n\n\t\tunsigned\t\tTimerHandle;\t//Handle for windows timer event\n\t\tunsigned\t\tFrequency;\t\t//Frequency of our windows timer in ticks per second\n\n\t\tunsigned\t\tTrueRate;\t\t//True rate of clock. (only use word)\n\t\tunsigned\t\tSysTicks;\t\t//Tick count of timer.\n\t\tunsigned\t\tUserTicks;\t\t//Tick count of timer.\n\t\tunsigned\t\tUserRate;\t\t//Desired rate of timer.\n\n\n};\n\n\nextern\tWinTimerClass\t*WindowsTimer;\n\n\n\n\n\n\n\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// externs  //////////////////////////////////////////\n#ifndef FUNCTION_H\nextern TimerClass\t\t\t\t\tTickCount;\n#endif\nextern CountDownTimerClass\t\tCountDown;\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// Prototypes //////////////////////////////////////////\n\nextern \"C\" {\n\tlong __cdecl Get_System_Tick_Count(void);\n\tlong __cdecl Get_User_Tick_Count(void);\n\tvoid far __cdecl Timer_Interrupt_Func(void);\n//\tlong Get_Num_Interrupts(unsigned int realmode);\n\tvoid __cdecl Disable_Timer_Interrupt(void);\n\tvoid __cdecl Enable_Timer_Interrupt(void);\n}\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TIMER.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nBOOL __cdecl Init_Timer_System(unsigned int freq, int partial = FALSE);\nBOOL __cdecl Remove_Timer_System(VOID);\n\n\n#endif // TIMER_H\n\n"
  },
  {
    "path": "WIN32LIB/TIMER/TIMERDWN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Temp timer for 32bit lib                 *\n *                                                                         *\n *                    File Name : TIMER.CPP                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : July 6, 1994                             *\n *                                                                         *\n *                  Last Update : July 12, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   CDTC::Time -- Return the time on the timer.                           *\n *   CDTC::Stop -- Stop the timer.                                         *\n *   CDTC::Start -- Start a timer.                                         *\n *   CDTC::DownTimerClass -- Construct a timer class object.               *\n *   CDTC::Set -- Set the time of a timer.                           \t\t*\n *   CDTC::Reset -- Clear the timer.                                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"timer.H\"\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////////// Defines /////////////////////////////////////\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////////// Code ////////////////////////////////////////\n\n\n/***************************************************************************\n * TC::CountDownTimerClass -- Construct a timer class object.              *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nCountDownTimerClass::CountDownTimerClass(BaseTimerEnum timer, long set, int on)\n\t\t\t\t\t\t\t:TimerClass(timer, on)\n{\n\tSet(set, on);\n}\n\nCountDownTimerClass::CountDownTimerClass(BaseTimerEnum timer, int on)\n\t\t\t\t\t\t\t:TimerClass(timer, FALSE)\n{\n\tDelayTime = 0;\n\tif (on) Start();\n}\n\n\n/***************************************************************************\n * CDTC::TIME -- Return the time on the timer.                             *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong CountDownTimerClass::Time()\n{\n\tlong ticks = DelayTime - TimerClass::Time();\n\n\tif (ticks < 0) {\n\t\tticks = 0;\n\t}\n\treturn(ticks);\n}\n\n\n/***************************************************************************\n * CDTC::SET -- Set the time of a timer.                             \t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:  ULONG value to set timer at.                                    *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong CountDownTimerClass::Set(long value, BOOL start)\n{\n\tDelayTime = value;\n\tTimerClass::Reset(start);\n\treturn(Time());\n}\n\n\n\n"
  },
  {
    "path": "WIN32LIB/TIMER/TIMERINI.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Temp timer for 32bit lib                 *\n *                                                                         *\n *                    File Name : TIMERINI.CPP                             *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : July 6, 1994                             *\n *                                                                         *\n *                  Last Update : July 6, 1994   [SKB]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Init_Timer_System -- Initialize the WW timer system.                  *\n *   Remove_Timer_System -- Removes the timer system.                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include <mmsystem.h>\n#include \"timer.H\"\n#include <profile.h>\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////////// Defines /////////////////////////////////////\n\n#define COPY_FROM_MEM\tTRUE\n\n/////////////////////////////////////////////////////////////////////////////////\n////////////////////////////// timera.asm functions//////////////////////////////\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern BOOL Install_Timer_Interrupt(VOID *bin_ptr, UINT rm_size, UINT freq, BOOL partial);\nextern BOOL Remove_Timer_Interrupt(VOID);\n\n#ifdef __cplusplus\n}\n#endif\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////// Global Data /////////////////////////////////////\n\nBOOL\tTimerSystemOn\t= FALSE;\n\n// Global timers that the library or user can count on existing.\nTimerClass\t\t\t\t\tTickCount(BT_SYSTEM);\nCountDownTimerClass\t\tCountDown(BT_SYSTEM, 0);\n\n\n// Prototype for timer callback\nvoid CALLBACK Timer_Callback ( UINT event_id, UINT res1 , DWORD user, DWORD  res2, DWORD  res3 );\n\nHANDLE\tTimerThreadHandle = 0;\t\t//Handle of timer thread\nint\t\tInTimerCallback\t= 0;\t\t//Flag to say if we are in a timer callback\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////////// Code ////////////////////////////////////////\n\n\n\n\n\n/***************************************************************************\n * WinTimerClass::WinTimerClass -- Initialize the WW timer system.         *\n *                                                                         *\n *                                                                         *\n * INPUT: UINT : user timer frequency.\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/5/95 3:47PM : ST Created.                                          *\n *=========================================================================*/\nWinTimerClass::WinTimerClass (UINT freq, BOOL partial)\n{\n\tBOOL\t\tsuccess;\n\n\t//\n\t// Inform windows that we want a higher than normal\n\t// timer resolution\n\t//\n#ifdef __SW_EP\n\ttimeBeginPeriod(1000/PROFILE_RATE);\n\tFrequency = PROFILE_RATE;\n#else\n\ttimeBeginPeriod ( 1000/freq );\n\tFrequency = freq;\n#endif\n\n\n\t//\n\t// Install the timer callback event handler\n\t//\n\tTimerHandle = timeSetEvent ( 1000/freq , 1 , Timer_Callback , 0 , TIME_PERIODIC);\n\tTimerSystemOn = success = ( TimerHandle !=0 );\n\n\tif (success)  {\n\t\tif (!partial) {\n\t\t\tWindowsTimer=this;\n\t\t\tTickCount.Start();\n\t\t}\n\t}else{\n\t\tchar error_str [128];\n\t\tsprintf (error_str, \"Error - timer system failed to start. Error code %d\\n\", GetLastError());\n\t\tOutputDebugString(error_str);\n\t}\n}\n\n\n\n/***************************************************************************\n * WinTimerClass::~WinTimerClass -- Removes the timer system.              *\n *                                                                         *\n *                                                                         *\n * INPUT:   NONE.                                                          *\n *                                                                         *\n * OUTPUT:  BOOL was it removed successfuly                                *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/5/95 3:47PM : ST Created.                                          *\n *=========================================================================*/\nWinTimerClass::~WinTimerClass( void )\n{\n\n\tif ( TimerHandle ){\n\t\ttimeKillEvent ( TimerHandle );\n\t}\n\n\tTimerSystemOn = FALSE;\n\ttimeEndPeriod ( 1000/Frequency );\n}\n\n\n\n\n\n/***********************************************************************************************\n * Timer_Callback -- Main timer callback. Equivalent to a timer interrupt handler              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    uint timer ID                                                                     *\n *           uint reserved                                                                     *\n *           long 0 (application defined)                                                      *\n *           long reserved                                                                     *\n *           long reserved                                                                     *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/5/95 3:19PM ST : Created                                                              *\n *=============================================================================================*/\n\n\nvoid CALLBACK Timer_Callback (UINT , UINT , DWORD , DWORD , DWORD)\n{\n\t//CONTEXT\tcontext;\n\n\tInTimerCallback++;\n\tif (!TimerThreadHandle){\n\t\tDuplicateHandle (GetCurrentProcess(), GetCurrentThread() , GetCurrentProcess() ,&TimerThreadHandle , 0 , TRUE , DUPLICATE_SAME_ACCESS);\n\t}\n\n\n\tif (WindowsTimer) {\n\t\tWindowsTimer->Update_Tick_Count();\n\t}\n\tInTimerCallback--;\n}\n\n\n\n\n\n\n/***********************************************************************************************\n * WinTimerClass::Update_Tick_Count -- update westwood timers                                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/5/95 3:58PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid WinTimerClass::Update_Tick_Count ( void )\n{\n/*\n *\n *  Increment westwood timers\n *\n */\n\tSysTicks++;\n\tUserTicks++;\n\n}\n\n\n\n\n\n\n\n\n/*\n;***************************************************************************\n;* GET_NUM_INTERRUPTS -- Returns the number of interrupts that have occured*\n;*                                                                         *\n;* INPUT: TRUE - returns num RM ints.                                      *\n;*        FALSE - return num PM ints.                                      *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/12/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Num_Interrupts C Near\n\tUSES\tesi\n\tARG\trealmode:DWORD\n\n\tmov\tesi,[RealModePtr]\n\tcmp\t[realmode],0\n\tje\t??prot_mode\n\tmov\teax,[(TimerType PTR esi).NumRMInts]\n\tret\n??prot_mode:\n\tmov\teax,[(TimerType PTR esi).NumPMInts]\n\tret\n\n\tENDP\n  */\n\n\n\n\n/***********************************************************************************************\n * WinTimerClass::Get_System_Tick_Count -- returns the system tick count                       *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   tick count                                                                        *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/5/95 4:02PM ST : Created                                                              *\n *=============================================================================================*/\n\nunsigned WinTimerClass::Get_System_Tick_Count ( void )\n{\n\treturn ( SysTicks );\n}\n\n\n\n/***********************************************************************************************\n * WinTimerClass::Get_User_Tick_Count -- returns the user tick count                           *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   tick count                                                                        *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/5/95 4:02PM ST : Created                                                              *\n *=============================================================================================*/\n\nunsigned WinTimerClass::Get_User_Tick_Count ( void )\n{\n\treturn ( UserTicks );\n}\n"
  },
  {
    "path": "WIN32LIB/WINCOMM/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = wincomm\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n        wincomm.obj     &\n        modemreg.obj    &\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WWLIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\n#**************************** End of makefile ******************************\n"
  },
  {
    "path": "WIN32LIB/WINCOMM/MODEMREG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer/ WW Library                                *\n *                                                                                             *\n *                    File Name : MODEMREG.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 10/18/96                                                     *\n *                                                                                             *\n *                  Last Update : October 18th 1996 [ST]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *                                                                                             *\n *   Functions for obtaining modem infommation from the Win95 registry                         *\n *                                                                                             *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *                                                                                             *\n * Search_Registry_Key -- Search a registry key and all its subkeys for a given value          *\n * MREC::ModemRegistryEntryClass -- Constructor for ModemRegistryEntryClass                    *\n * MREC::~ModemRegistryEntryClass -- Destructor.Free all the memory we allocated for modem info*\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\n\n\n#include \"modemreg.h\"\n#include <stdio.h>\n\n\nextern HKEY Get_Registry_Sub_Key (HKEY base_key, char *search_key, BOOL close);\n\n\n\n\n/***********************************************************************************************\n * Search_Registry_Key -- Search a registry key and all its subkeys for a given value          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    handle to key to search in                                                        *\n *           name of key to search for                                                         *\n *           value expected in key                                                             *\n *                                                                                             *\n * OUTPUT:   Handle to key containing value. Null if not found.                                *\n *                                                                                             *\n * WARNINGS: This function reenters itself.                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/18/96 4:01AM ST : Created                                                             *\n *=============================================================================================*/\nHKEY Search_Registry_Key (HKEY key_in, char *value_name, char *search_string)\n{\n\n\tint \ttop_key_index = 0;\t\t\t\t// Index of topmost key\n\tint \tretval;\t\t\t\t\t\t\t\t// Result of registry api calls\n\tHKEY\tnext_key;\t\t\t\t\t\t\t// handle of next key examine\n\tHKEY\tnext_search;\t\t\t\t\t\t// handle of next key to search\n\n\n\tchar\t\t\t\t*subkey_name = new char [256];\t\t\t// Area to contain result of key enumeration\n\tunsigned long\tsubkey_name_length = 256;\t\t\t\t\t// Length of enumeration result area\n\tFILETIME\t\t\tfiletime;\t\t\t\t\t\t\t\t\t\t// Time key was last touched. Not used.\n\tunsigned long\tvalue_type;\t\t\t\t\t\t\t\t\t\t// Type of data that is contained in a key.\n\tunsigned char\t*key_value = new unsigned char [256];\t// Area to return key values into\n\tunsigned long\tkey_value_length = 256;\t\t\t\t\t\t// Length of key value area\n\n\t/*\n\t** Scan through and enumerate all subkeys of this key. Exit the loop when there are\n\t** no more sub keys to enumerate.\n\t*/\n\tdo {\n\t\tsubkey_name_length = 256;\t\t\t// Has to be set each time through the loop\n\n\t\t/*\n\t\t** Get the next key\n\t\t*/\n\t\tretval = RegEnumKeyEx (key_in, top_key_index++, subkey_name, &subkey_name_length, NULL, NULL, NULL, &filetime);\n\n\t\tif ( retval == ERROR_SUCCESS ){\n\n\t\t\t/*\n\t\t\t** Get a handle to this key so we can search it.\n\t\t\t*/\n\t\t\tnext_key = Get_Registry_Sub_Key (key_in, subkey_name, FALSE);\n\n\t\t\tif (next_key){\n\n\t\t\t\tkey_value_length = 256;\t\t// Has to be set each time through the loop\n\n\t\t\t\tif ( RegQueryValueEx (next_key, value_name, NULL, &value_type, key_value, &key_value_length) == ERROR_SUCCESS){\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If this value is type string then do a compare with the value we are looking for\n\t\t\t\t\t*/\n\t\t\t\t\tif (value_type == REG_SZ && !strcmp ((char*)key_value, search_string)){\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** This is our man. Delete our workspace and return the key handle\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tdelete [] subkey_name;\n\t\t\t\t\t\tdelete [] key_value;\n\t\t\t\t\t\treturn (next_key);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** We didnt find our search value so search this key for more sub keys by reentering\n\t\t\t\t** this function with the handle of the subkey.\n\t\t\t\t*/\n\t\t\t\tnext_search = Search_Registry_Key (next_key, value_name, search_string);\n\t\t\t\tRegCloseKey (next_key);\n\n\t\t\t\t/*\n\t\t\t\t** If the value was found in a subkey then just return with the key handle.\n\t\t\t\t*/\n\t\t\t\tif (next_search){\n\t\t\t\t\tdelete [] subkey_name;\n\t\t\t\t\tdelete [] key_value;\n\t\t\t\t\treturn (next_search);\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t} while (retval == ERROR_SUCCESS);\n\n\t/*\n\t** Clean up and exit.\n\t*/\n\tdelete [] subkey_name;\n\tdelete [] key_value;\n\n\treturn (0);\n}\n\n\n\n/***********************************************************************************************\n * MREC::ModemRegistryEntryClass -- Constructor for ModemRegistryEntryClass                    *\n *                                                                                             *\n *  This function does all the work in the class. All the registry searching is done here      *\n *                                                                                             *\n * INPUT:    Modem number                                                                      *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/18/96 4:12AM ST : Created                                                             *\n *=============================================================================================*/\nModemRegistryEntryClass::ModemRegistryEntryClass (int modem_number)\n{\n\tHKEY\t\t\t\tkey;\n\tunsigned char\treturn_buf[256];\n\tDWORD\t\t\t\tretbuf_size = sizeof(return_buf);\n\n\tint\t\t\t\tpnp = 0;\t\t\t\t\t//Not a plug n pray modem\n\n\t/*\n\t** Initialise all the info we expect from the registry to NULL.\n\t** Any entries we cant find will just stay NULL.\n\t*/\n\tModemName = NULL;\n\tModemDeviceName = NULL;\n\tErrorCorrectionEnable = NULL;\n\tErrorCorrectionDisable = NULL;\n\tCompressionEnable = NULL;\n\tCompressionDisable = NULL;\n\tHardwareFlowControl = NULL;\n\tNoFlowControl = NULL;\n\n\n\t/*\n\t** Modem info is stored under\n\t** HKEY_LOCAL_MACHINE / System / CurrentControlSet / Services / Class / Modem / nnnn\n\t** where nnnn is a four digit modem number.\n\t*/\n\n\tkey = Get_Registry_Sub_Key (HKEY_LOCAL_MACHINE, \"System\", FALSE);\n\tif (!key) return;\n\n\tkey = Get_Registry_Sub_Key (key, \"CurrentControlSet\", TRUE);\n\tif (!key) return;\n\n\tkey = Get_Registry_Sub_Key (key, \"Services\", TRUE);\n\tif (!key) return;\n\n\tkey = Get_Registry_Sub_Key (key, \"Class\", TRUE);\n\tif (!key) return;\n\n\tkey = Get_Registry_Sub_Key (key, \"Modem\", TRUE);\n\tif (!key) return;\n\n\tchar which_modem[5];\n\tsprintf (which_modem, \"%04d\", modem_number);\n\n\t/*\n\t** Get a handle to the modem key if it exists. Then extract the info we need.\n\t*/\n\tkey = Get_Registry_Sub_Key (key, which_modem, TRUE);\n\tif (!key) return;\n\n\n\t/*\n\t** Get the name of the modem. This is what will be displayed in the modem list presented\n\t** to the user.\n\t*/\n\tif (RegQueryValueEx(key, \"Model\", NULL, NULL, return_buf, &retbuf_size) != ERROR_SUCCESS){\n\t\tRegCloseKey (key);\n\t\treturn;\n\t}\n\tModemName = new char [retbuf_size];\n\tmemcpy (ModemName, return_buf, retbuf_size);\n\n\t/*\n\t** Find out what COM port the modem is attached to. If this info isnt here, then its a\n\t** Plug n Pray modem. Set the flag so we know to do the pnp search later.\n\t*/\n\tretbuf_size = sizeof (return_buf);\n\tif (RegQueryValueEx(key, \"AttachedTo\", NULL, NULL, return_buf, &retbuf_size) != ERROR_SUCCESS){\n\t\t/*\n\t\t** Must be a plug n pray modem. Set the flag. We will look for the port later.\n\t\t*/\n\t\tpnp = 1;\n\t\tModemDeviceName = new char [strlen (ModemName)+1];\n\t\tstrcpy (ModemDeviceName, ModemName);\n\t}else{\n\t\tModemDeviceName = new char [retbuf_size];\n\t\tmemcpy (ModemDeviceName, return_buf, retbuf_size);\n\t}\n\n\n\t/*\n\t** The list of modem 'AT' commands is stored in the 'Settings'  key.\n\t*/\n\tkey = Get_Registry_Sub_Key (key, \"Settings\", TRUE);\n\tif (!key) return;\n\n\n\t/*\n\t** Extract the control strings for error control.\n\t*/\n\tretbuf_size = sizeof (return_buf);\n\tif (RegQueryValueEx(key, \"ErrorControl_On\", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){\n\t\tErrorCorrectionEnable = new char [retbuf_size];\n\t\tmemcpy (ErrorCorrectionEnable, return_buf, retbuf_size);\n\t}\n\n\tretbuf_size = sizeof (return_buf);\n\tif (RegQueryValueEx(key, \"ErrorControl_Off\", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){\n\t\tErrorCorrectionDisable = new char [retbuf_size];\n\t\tmemcpy (ErrorCorrectionDisable, return_buf, retbuf_size);\n\t}\n\n\t/*\n\t** Extract the control strings for data compression.\n\t*/\n\tretbuf_size = sizeof (return_buf);\n\tif (RegQueryValueEx(key, \"Compression_On\", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){\n\t\tCompressionEnable = new char [retbuf_size];\n\t\tmemcpy (CompressionEnable, return_buf, retbuf_size);\n\t}\n\n\tretbuf_size = sizeof (return_buf);\n\tif (RegQueryValueEx(key, \"Compression_Off\", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){\n\t\tCompressionDisable = new char [retbuf_size];\n\t\tmemcpy (CompressionDisable, return_buf, retbuf_size);\n\t}\n\n\t/*\n\t** Extract the control strings for hardware flow control.\n\t*/\n\tretbuf_size = sizeof (return_buf);\n\tif (RegQueryValueEx(key, \"FlowControl_Hard\", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){\n\t\tHardwareFlowControl = new char [retbuf_size];\n\t\tmemcpy (HardwareFlowControl, return_buf, retbuf_size);\n\t}\n\n\t/*\n\t** Extract the control strings for no flow control.\n\t*/\n\tretbuf_size = sizeof (return_buf);\n\tif (RegQueryValueEx(key, \"FlowControl_Off\", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){\n\t\tNoFlowControl = new char [retbuf_size];\n\t\tmemcpy (NoFlowControl, return_buf, retbuf_size);\n\t}\n\n\n\n\tRegCloseKey (key);\n\n\n\n\t/*\n\t** If this is a plug n pray modem then we need to search for the COM port it is\n\t** attached to.\n\t*/\n\tif (pnp){\n\n\t\t/*\n\t\t** The driver name in the HKEY_LOCAL_MACHINE / Enum section will be Modem\\nnnn where nnnn\n\t  \t** is a four digit modem number.\n\t\t*/\n\t\tchar search_string [256] = {\"Modem\\\\\"};\n\t\tstrcat (search_string, which_modem);\n\n\t\t/*\n\t\t** Search through all the registry entries under HKEY_LOCAL_MACHINE / Enum\n\t\t*/\n\t\tkey = Get_Registry_Sub_Key (HKEY_LOCAL_MACHINE, \"Enum\", FALSE);\n\t\tif (!key) return;\n\n\t\tHKEY newkey = Search_Registry_Key ( key, \"Driver\", search_string );\n\n\t\tif (newkey){\n\t\t\tretbuf_size = sizeof (return_buf);\n\n\t\t\t/*\n\t\t\t** Extract the PORTNAME value. This is the name of the port to use to communicate\n\t\t\t** with the modem.\n\t\t\t*/\n\t\t\tretbuf_size = sizeof (return_buf);\n\t\t\tif (RegQueryValueEx(newkey, \"PORTNAME\", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){\n\n\t\t\t\tif (ModemDeviceName) delete [] ModemDeviceName;\n\n\t\t\t\tModemDeviceName = new char [retbuf_size];\n\t\t\t\tmemcpy (ModemDeviceName, return_buf, retbuf_size);\n\t\t\t}\n\t\t}\n\t\tRegCloseKey (key);\n\t}\n\n}\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * MREC::~ModemRegistryEntryClass -- Destructor.Free all the memory we allocated for modem info*\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/18/96 11:39AM ST : Created                                                              *\n *=============================================================================================*/\nModemRegistryEntryClass::~ModemRegistryEntryClass (void)\n{\n\tif (ModemName) delete [] ModemName;\n\tif (ModemDeviceName) delete [] ModemDeviceName;\n\n\tif (ErrorCorrectionEnable) delete [] ErrorCorrectionEnable;\n\tif (ErrorCorrectionDisable) delete [] ErrorCorrectionDisable;\n\n\tif (CompressionEnable) delete [] CompressionEnable;\n\tif (CompressionDisable) delete [] CompressionDisable;\n\n\tif (HardwareFlowControl) delete [] HardwareFlowControl;\n\tif (NoFlowControl) delete [] NoFlowControl;\n}\n\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/WINCOMM/MODEMREG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#ifndef WIN32\n#define WIN32\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#endif\t//WIN32\n#include <windows.h>\n\n\n\nclass ModemRegistryEntryClass {\n\n\tpublic:\n\n\t\tModemRegistryEntryClass (int modem_number);\n\t\t~ModemRegistryEntryClass (void);\n\n\n\t\tchar *Get_Modem_Name (void) { return (ModemName); }\n\n\t\tchar *Get_Modem_Device_Name (void) { return (ModemDeviceName); }\n\n\t\tchar *Get_Modem_Error_Correction_Enable (void) { return (ErrorCorrectionEnable); }\n\n\t\tchar *Get_Modem_Error_Correction_Disable (void) { return (ErrorCorrectionDisable); }\n\n\t\tchar *Get_Modem_Compression_Enable (void) { return (CompressionEnable); }\n\n\t\tchar *Get_Modem_Compression_Disable (void) { return (CompressionDisable); }\n\n\t\tchar *Get_Modem_Hardware_Flow_Control (void) { return (HardwareFlowControl); }\n\n\t\tchar *Get_Modem_No_Flow_Control (void) { return (HardwareFlowControl); }\n\n\tprivate:\n\n\t\tchar *ModemName;\n\t\tchar *ModemDeviceName;\n\t\tchar *ErrorCorrectionEnable;\n\t\tchar *ErrorCorrectionDisable;\n\t\tchar *CompressionEnable;\n\t\tchar *CompressionDisable;\n\t\tchar *HardwareFlowControl;\n\t\tchar *NoFlowControl;\n\n};\n\n\n\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/WINCOMM/WINCOMM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer/ WW Library                                *\n *                                                                                             *\n *                    File Name : WINCOMM.H                                                    *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 1/10/96                                                      *\n *                                                                                             *\n *                  Last Update : January 10th 1996 [ST]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *                                                                                             *\n *   Functions for WinModemClass & WinNullModemClass                                           *\n *                                                                                             *\n *   These classes was created to replace the greenleaf comms functions used in C&C DOS with   *\n *  WIN32 API calls.                                                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\n//#include \"function.h\"\n#include \t\"wincomm.h\"\n#include\t\"timer.h\"\n#include\t\"keyboard.h\"\n#include\t\"misc.h\"\n#include <io.h>\n#include <sys\\types.h>\n#include <sys\\stat.h>\n#include <fcntl.h>\n\n\n/*\n** Define this to log modem activity to disk.\n*/\n//#define LOG_MODEM\n\n/*\n** Object represents a serial port\n*/\nWinModemClass\t*SerialPort = NULL;\n\n\n\n/***********************************************************************************************\n * WMC::WinModemClass -- WinModemClass constructor                                             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:14PM ST : Created                                                              *\n *=============================================================================================*/\n\nWinModemClass::WinModemClass(void)\n{\n\t/*\n\t** Allocate memory for our internal circular serial input buffer\n\t*/\n\tSerialBuffer = new unsigned char [SIZE_OF_WINDOWS_SERIAL_BUFFER];\n\n\t/*\n\t** Initialise the serial buffer pointers\n\t*/\n\tSerialBufferReadPtr\t= 0;\n\tSerialBufferWritePtr\t= 0;\n\n\t/*\n\t** Clear the waiting flags\n\t*/\n\tWaitingForSerialCharRead\t= FALSE;\n\tWaitingForSerialCharWrite\t= FALSE;\n\n\t/*\n\t** No default abort or echo function\n\t*/\n\tAbortFunction = NULL;\n\tEchoFunction  = NULL;\n\n\n\t/*\n\t** Clear the running error count\n\t*/\n\tFramingErrors=0;\n\tIOErrors=0;\n\tBufferOverruns=0;\n\tInBufferOverflows=0;\n\tParityErrors=0;\n\tOutBufferOverflows=0;\n\n\t/*\n\t** We havnt opened a port yet so...\n\t*/\n\tPortHandle = 0;\n}\n\n\n\n/***********************************************************************************************\n * WMC::~WinModemClass -- destructor for WinModemClass                                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:15PM ST : Created                                                              *\n *=============================================================================================*/\n\nWinModemClass::~WinModemClass(void)\n{\n\t/*\n\t** Close the port\n\t*/\n\tif (PortHandle){\n\t\tSerial_Port_Close();\n\t}\n\n\t/*\n\t** Free the serial buffer\n\t*/\n\tif (SerialBuffer){\n\t\tdelete [] SerialBuffer;\n\t}\n}\n\n\n\n/***********************************************************************************************\n * Get_Registry_Sub_Key -- search a registry key for a sub-key                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    handle of key to search                                                           *\n *           text to search for                                                                *\n *           true if old key should be closed when new key opened                              *\n *                                                                                             *\n * OUTPUT:   handle to the key we found or 0                                                   *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/12/96 2:11PM ST : Created                                                              *\n *=============================================================================================*/\n\nHKEY Get_Registry_Sub_Key (HKEY base_key, char *search_key, BOOL close)\n{\n\n\tchar\t\tclass_string[1024];\n\tDWORD\t\tstring_size = 1024;\n\tDWORD\t\tnum_sub_keys;\n\tDWORD\t\tlongest_sub_key_name;\n\tDWORD\t\tlongest_class_string;\n\tDWORD\t\tnum_value_entries;\n\tDWORD\t\tlongest_value_name_length;\n\tDWORD\t\tlongest_value_data_length;\n\tDWORD\t\tsecurity_descriptor_length;\n\tFILETIME\tlast_write_time;\n\tHKEY\t\tresult_key;\n\tDWORD\t\tsub_key_buffer_size;\n\n\tchar\t\t*sub_key_buffer;\n\tchar\t\t*sub_key_class;\n\n\n\tif (RegQueryInfoKey (base_key,\n\t\t\t\t\t\t\t&class_string[0],\n\t\t\t\t\t\t\t&string_size,\n\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t&num_sub_keys,\n\t\t\t\t\t\t\t&longest_sub_key_name,\n\t\t\t\t\t\t\t&longest_class_string,\n\t\t\t\t\t\t\t&num_value_entries,\n\t\t\t\t\t\t\t&longest_value_name_length,\n\t\t\t\t\t\t\t&longest_value_data_length,\n\t\t\t\t\t\t\t&security_descriptor_length,\n\t\t\t\t\t\t\t&last_write_time) != ERROR_SUCCESS) return (0);\n\n\tsub_key_buffer_size = longest_sub_key_name+16;\n\tsub_key_buffer = new char [sub_key_buffer_size];\n\tsub_key_class\t= new char [longest_class_string+1];\n\n\tfor (int key_num=0 ; key_num<num_sub_keys ; key_num++){\n\n\t\t*sub_key_buffer = 0;\n\t\tlongest_sub_key_name = sub_key_buffer_size;\n\t\tRegEnumKeyEx(base_key,\n\t\t\t\t\t\tkey_num,\n\t\t\t\t\t\tsub_key_buffer,\n\t\t\t\t\t\t&longest_sub_key_name,\n\t\t\t\t\t\tNULL,\n\t\t\t\t\t\tsub_key_class,\n\t\t\t\t\t\t&longest_class_string,\n\t\t\t\t\t\t&last_write_time);\n\n\t\tif (!stricmp(search_key, sub_key_buffer)){\n\n\t\t\tif (RegOpenKeyEx(\tbase_key,\n\t\t\t\t\t\t\t\t\tsub_key_buffer,\n\t\t\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t\t\tKEY_READ,\n\t\t\t\t\t\t\t\t\t&result_key) == ERROR_SUCCESS){\n\n\t\t\t\tif (close){\n\t\t\t\t\tRegCloseKey(base_key);\n\t\t\t\t}\n\t\t\t\tdelete [] sub_key_buffer;\n\t\t\t\tdelete [] sub_key_class;\n\t\t\t\treturn (result_key);\n\t\t\t}\n\t\t}\n\n\t}\n\n\tif (close){\n\t\tRegCloseKey(base_key);\n\t}\n\tdelete [] sub_key_buffer;\n\tdelete [] sub_key_class;\n\treturn (0);\n}\n\n\n\n/***********************************************************************************************\n * Get_Modem_Name_From_Registry -- retrieve the name of the installed modem from the registry  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    buffer to put the name in                                                         *\n *           length of buffer                                                                  *\n *                                                                                             *\n * OUTPUT:   TRUE if modem was found in the registry                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/12/96 2:13PM ST : Created                                                              *\n *=============================================================================================*/\nBOOL Get_Modem_Name_From_Registry(char *buffer, int buffer_len)\n{\n\tHKEY\tkey;\n\tchar\tmodem_name[256];\n\tDWORD\tmodem_name_size = 256;\n\n\tkey = Get_Registry_Sub_Key (HKEY_LOCAL_MACHINE, \"Enum\", FALSE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"Root\", TRUE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"Modem\", TRUE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"0000\", TRUE);\n\tif (!key) return (FALSE);\n\n\tif (RegQueryValueEx(key, \"FriendlyName\", NULL, NULL, (unsigned char*)&modem_name[0], &modem_name_size) != ERROR_SUCCESS){\n\t\tRegCloseKey(key);\n\t\treturn (FALSE);\n\t}\n\n\tRegCloseKey(key);\n\tmemcpy (buffer, modem_name, min(buffer_len, modem_name_size));\n\treturn (TRUE);\n}\n\n\n\n\n\n\n\n#ifdef cuts\n\n/***********************************************************************************************\n * WMC::Serial_Port_Open -- opens a com port for asyncronous read/write and gets a handle to it*\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Com port \t- 0=com1, 1=com2 etc.                                                 *\n *           baud rate \t- bits per second                                                     *\n *           parity \t\t- true or false                                                       *\n *           word length\t- 5 to 8 bits                                                         *\n *           stop bits\t- 0=1 stop bit, 1=1.5 & 2=2                                           *\n *                                                                                             *\n * OUTPUT:   Handle to port                                                                    *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:17PM ST : Created                                                              *\n *=============================================================================================*/\n\n//VOID FAR PASCAL lineCallbackFunc(DWORD hDevice, DWORD dwMsg,\n//    DWORD dwCallbackInstance, DWORD dwParam1, DWORD dwParam2,\n//   DWORD dwParam3)\n\nVOID FAR PASCAL lineCallbackFunc(DWORD ,DWORD ,DWORD ,DWORD ,DWORD ,DWORD);\n\nextern HINSTANCE ProgramInstance;\n\nHANDLE\tWinModemClass::Serial_Port_Open (int com, int baud, int parity, int wordlen, int stopbits)\n{\n\tHANDLE\t\t\tcom_handle;\t\t\t//temporary storage for the port handle\n\tDCB\t\t\t\tdevice_control;\t//device control block\n\tCOMMTIMEOUTS\ttimeouts;\t\t\t//timeout values\n\tchar\t\t\t\tmodem_name[256];\t//name of modem\n\tchar\t\t\t\tdevice_name[266]={\"\\\\\\\\.\\\\\"};\t//device name to open\n\tDWORD\t\t\t\tconfig_size = 2048;\n\tchar\t\t\t\tconfig[2048];\n\tCOMMCONFIG\t\t*modem_config = (COMMCONFIG*)&config[0];\n\tMODEMDEVCAPS\t*modem_caps;\n\tint\t\t\t\ttemp;\n\tBOOL\t\t\t\tfound_modem;\n\n\t/*\n\t** Map for com port values to device names\n\t*/\n\tstatic char com_ids[8][5]={\n\t\t\"COM1\",\n\t\t\"COM2\",\n\t\t\"COM3\",\n\t\t\"COM4\",\n\t\t\"COM5\",\n\t\t\"COM6\",\n\t\t\"COM7\",\n\t\t\"COM8\"\n\t};\n\n\n\tHLINEAPP \tapp_line_handle;\n\tDWORD\t\t\tnum_devices;\n\n\tlineInitialise (&app_line_handle, ProgramInstance, &lineCallbackFunc, NULL, &num_devices);\n\n\n\n\n\n\n\tfound_modem = TRUE;\n\n\tif (!Get_Modem_Name_From_Registry(modem_name, 256)){\n\t\tstrcpy(modem_name, com_ids[com]);\n\t\tfound_modem = FALSE;\n\t}\n\n\tstrcat(device_name, modem_name);\n\n\n\tPortHandle = 0;\n\n\t/*\n\t** Open the com port for asyncronous reads/writes\n\t*/\n\tcom_handle = CreateFile (device_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);\n\n\tif (com_handle == INVALID_HANDLE_VALUE) return (com_handle);\n\n\tPortHandle = com_handle;\n\n\t/*\n\t** Set the size of the windows communication buffers\n\t*/\n\tSetupComm(com_handle, 2048, 2048);\n\n\n\t/*\n\t** Create an event object for asyncronous reads\n\t*/\n\tReadOverlap.Internal \t\t= 0;\n\tReadOverlap.InternalHigh\t= 0;\n\tReadOverlap.Offset\t\t\t= 0;\n\tReadOverlap.OffsetHigh\t\t= 0;\n\tReadOverlap.hEvent\t\t\t= CreateEvent (NULL, TRUE, TRUE, NULL);\n\n\t/*\n\t** Create an event object for asyncronous writes\n\t*/\n\tWriteOverlap.Internal \t\t= 0;\n\tWriteOverlap.InternalHigh\t= 0;\n\tWriteOverlap.Offset\t\t\t= 0;\n\tWriteOverlap.OffsetHigh\t\t= 0;\n\tWriteOverlap.hEvent\t\t\t= CreateEvent (NULL, TRUE, TRUE, NULL);\n\n\tif (!found_modem){\n\t\t/*\n\t\t** Get the current state of the com port as a basis for our device control block\n\t\t*/\n\t\tGetCommState (com_handle , &device_control);\n\n\t\t/*\n\t\t** Communications settings\n\t\t*/\n\t\tdevice_control.BaudRate = baud;\n\t\tdevice_control.fParity \t= parity;\n\t\tdevice_control.ByteSize = wordlen;\n\t\tdevice_control.StopBits\t= stopbits-1;\n\n\t\t/*\n\t\t** Misc settings for flow control etc.\n\t\t*/\n\t\tdevice_control.fBinary\t\t\t= TRUE;\t\t\t\t\t\t\t// Binary mode data transfer\n\t\tdevice_control.fOutxCtsFlow \t= TRUE;  \t\t\t\t\t\t// CTS flow control\n\t\tdevice_control.fRtsControl\t\t= RTS_CONTROL_HANDSHAKE;\t// RTS flow control\n\t\tdevice_control.fErrorChar\t\t= FALSE;\t\t\t\t\t\t\t// Dont put an error char into our input stream\n\t\tdevice_control.fOutxDsrFlow\t= FALSE;\t\t\t\t\t\t\t// No DSR flow control\n\t\tdevice_control.fDtrControl\t\t= DTR_CONTROL_ENABLE;\t\t// Enable control of DTR line\n\t\tdevice_control.fOutX\t\t\t\t= FALSE;\t\t\t\t\t\t\t// No XON/XOF flow control\n\t\tdevice_control.fInX\t\t\t\t= FALSE;\t\t\t\t\t\t\t// No XON/XOF flow control\n\t\tdevice_control.fAbortOnError\t= FALSE;\t\t\t\t\t\t\t// Device continues to send after an error\n\n\t\t/*\n\t\t** Pass the device settings to windows\n\t\t*/\n\t\tif (SetCommState (com_handle , &device_control) != TRUE){\n\t\t\tSerial_Port_Close();\n\t\t\treturn (INVALID_HANDLE_VALUE);\n\t\t}\n\t}else{\n\n\t\t/*\n\t\t** If we are talking to a modem device then turn off compression and error correction\n\t\t*/\n\t\tGetCommConfig(PortHandle ,modem_config, &config_size);\n\n\t\tif (modem_config->dwProviderSubType == PST_MODEM){\n\t\t\ttemp = modem_config->dwProviderOffset;\n\t\t\ttemp += (int)modem_config;\n\t\t\tmodem_caps = (MODEMDEVCAPS*)temp;\n\t\t\tmodem_caps->dwModemOptions &= ~(\tMDM_COMPRESSION |\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tMDM_ERROR_CONTROL |\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tMDM_FLOWCONTROL_HARD);\n\t\t\tSetCommConfig(PortHandle, modem_config ,(unsigned)config_size);\n\t\t}\n\t}\n\n\n\t/*\n\t** Set the device timeouts\n\t*/\n\ttimeouts.ReadIntervalTimeout \t\t\t= 10000;\t//10 seconds between incoming packets\n\ttimeouts.ReadTotalTimeoutMultiplier = 0;\t\t//disable total timeouts\n\ttimeouts.ReadTotalTimeoutConstant\t= 0;\t\t//disable total timeouts\n    timeouts.WriteTotalTimeoutMultiplier= 0;\t\t//disable total timeouts\n    timeouts.WriteTotalTimeoutConstant\t= 0;\t\t//disable total timeouts\n\n\tif (SetCommTimeouts(com_handle, &timeouts) !=TRUE){\n\t\tSerial_Port_Close();\n\t\treturn (INVALID_HANDLE_VALUE);\n\t}\n\n\treturn (com_handle);\n}\n#endif\n\n\n\n\n\n/***********************************************************************************************\n * WMC::Serial_Port_Open -- opens a com port for asyncronous read/write and gets a handle to it*\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Com port \t- 0=com1, 1=com2 etc.                                                 *\n *           baud rate \t- bits per second                                                     *\n *           parity \t\t- true or false                                                       *\n *           word length\t- 5 to 8 bits                                                         *\n *           stop bits\t- 0=1 stop bit, 1=1.5 & 2=2                                           *\n *           flow control- 0 = none, 1 = hardware                                              *\n *                                                                                             *\n * OUTPUT:   Handle to port                                                                    *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:17PM ST : Created                                                              *\n *=============================================================================================*/\nHANDLE\tWinModemClass::Serial_Port_Open (char *device_name, int baud, int parity, int wordlen, int stopbits, int flowcontrol)\n{\n\tHANDLE\t\t\tcom_handle;\t\t\t//temporary storage for the port handle\n\tDCB\t\t\t\tdevice_control;\t//device control block\n\tCOMMTIMEOUTS\ttimeouts;\t\t\t//timeout values\n#if (0)\n\t/*\n\t** Map for com port values to device names\n\t*/\n\tstatic char com_ids[8][5]={\n\t\t\"COM1\",\n\t\t\"COM2\",\n\t\t\"COM3\",\n\t\t\"COM4\",\n\t\t\"COM5\",\n\t\t\"COM6\",\n\t\t\"COM7\",\n\t\t\"COM8\"\n\t};\n#endif\t//(0)\n\n\tint\terrorval;\n\tchar\terrortxt[128];\n\n\tchar devname[266]={\"\\\\\\\\.\\\\\"};\t//device name to open\n\tstrcat (devname, device_name);\n\n\tPortHandle = 0;\n\n\t/*\n\t** Open the com port for asyncronous reads/writes\n\t*/\n\t//com_handle = CreateFile (&com_ids[com][0], GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);\n\tcom_handle = CreateFile (devname, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);\n\n\tif (com_handle == INVALID_HANDLE_VALUE) return (com_handle);\n\n\tPortHandle = com_handle;\n\n\t/*\n\t** Set the size of the windows communication buffers\n\t*/\n\tSetupComm(com_handle, SIZE_OF_WINDOWS_SERIAL_BUFFER, SIZE_OF_WINDOWS_SERIAL_BUFFER);\n\n\t/*\n\t** Reset any read or write operation and purge the buffers\n\t*/\n\tPurgeComm (PortHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);\n\n\t/*\n\t** Create an event object for asyncronous reads\n\t*/\n\tReadOverlap.Internal \t\t= 0;\n\tReadOverlap.InternalHigh\t= 0;\n\tReadOverlap.Offset\t\t\t= 0;\n\tReadOverlap.OffsetHigh\t\t= 0;\n\tReadOverlap.hEvent\t\t\t= CreateEvent (NULL, TRUE, TRUE, NULL);\n\n\t/*\n\t** Create an event object for asyncronous writes\n\t*/\n\tWriteOverlap.Internal \t\t= 0;\n\tWriteOverlap.InternalHigh\t= 0;\n\tWriteOverlap.Offset\t\t\t= 0;\n\tWriteOverlap.OffsetHigh\t\t= 0;\n\tWriteOverlap.hEvent\t\t\t= CreateEvent (NULL, TRUE, TRUE, NULL);\n\n\n\t/*\n\t** Get the current state of the com port as a basis for our device control block\n\t*/\n\tif (GetCommState (com_handle , &device_control)){\n\n\t\t/*\n\t\t** Communications settings\n\t\t*/\n\t\tdevice_control.BaudRate = baud;\n\t\tdevice_control.fParity \t= parity;\n\t\tdevice_control.ByteSize = (char)wordlen;\n\t\tdevice_control.StopBits\t= (char)(stopbits-1);\n\n\t\t/*\n\t\t** Misc settings for flow control etc.\n\t\t*/\n\t\tdevice_control.fBinary\t\t\t= TRUE;\t\t\t\t\t\t\t// Binary mode data transfer\n\t\tdevice_control.fOutxCtsFlow \t= TRUE;  \t\t\t\t\t\t// CTS flow control\n\t\tdevice_control.fRtsControl\t\t= RTS_CONTROL_HANDSHAKE;\t// RTS flow control\n\t\tdevice_control.fErrorChar\t\t= FALSE;\t\t\t\t\t\t\t// Dont put an error char into our input stream\n\t\tdevice_control.fOutxDsrFlow\t= FALSE;\t\t\t\t\t\t\t// No DSR flow control\n\t\tdevice_control.fDtrControl\t\t= DTR_CONTROL_ENABLE;\t\t// Enable control of DTR line\n\t\tdevice_control.fOutX\t\t\t\t= FALSE;\t\t\t\t\t\t\t// No XON/XOF flow control\n\t\tdevice_control.fInX\t\t\t\t= FALSE;\t\t\t\t\t\t\t// No XON/XOF flow control\n\t\tdevice_control.fAbortOnError\t= FALSE;\t\t\t\t\t\t\t// Device continues to send after an error\n\n\t\t/*\n\t\t** Disable hardware flow control if required\n\t\t*/\n\t\tif (!flowcontrol){\n\t\t\tdevice_control.fOutxCtsFlow \t= FALSE;  \t\t\t\t\t// CTS flow control\n\t\t\tdevice_control.fRtsControl\t\t= RTS_CONTROL_DISABLE;\t// RTS flow control\n\t\t}\n\n\t\t/*\n\t\t** Pass the device settings to windows\n\t\t*/\n\t\tif ( !SetCommState (com_handle , &device_control)){\n\t\t\terrorval = GetLastError();\n\t\t\tsprintf (errortxt, \"RA95 -- SetCommState returned error code %d.\\n\", errorval);\n\t\t\tOutputDebugString (errortxt);\n\t\t\t//Serial_Port_Close();\n\t\t\t//return (INVALID_HANDLE_VALUE);\n\t\t}\n\t}else{\n\t\terrorval = GetLastError();\n\t\tsprintf (errortxt, \"RA95 -- GetCommState returned error code %d.\\n\", errorval);\n\t\tOutputDebugString (errortxt);\n\t}\n\n\n\n\t/*\n\t** Set the device timeouts\n\t*/\n\ttimeouts.ReadIntervalTimeout \t\t\t= 1000;\t//1 second between incoming bytes will time-out the read\n\ttimeouts.ReadTotalTimeoutMultiplier = 0;\t\t//disable per byte timeouts\n\ttimeouts.ReadTotalTimeoutConstant\t= 3000;\t//Read operations time out after 3 secs if no data received\n    timeouts.WriteTotalTimeoutMultiplier= 500;\t//Allow 1/2 ms between each char write\n    timeouts.WriteTotalTimeoutConstant\t= 1000;\t//Write operations time out after 1 sec + 1/2 sec per char if data wasnt sent\n\n\tif ( !SetCommTimeouts(com_handle, &timeouts) ){\n\t\terrorval = GetLastError();\n\t\tsprintf (errortxt, \"RA95 -- SetCommTimeouts returned error code %d.\\n\", errorval);\n\t\tOutputDebugString (errortxt);\n\t\t//Serial_Port_Close();\n\t\t//return (INVALID_HANDLE_VALUE);\n\t}\n\n\treturn (com_handle);\n}\n\n\n\n\n\n/***********************************************************************************************\n * WMC::Set_Modem_Dial_Type -- sets dial type to WC_TOUCH_TONE or WC_PULSE                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    WC_TOUCH_TONE or WC_PULSE                                                         *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:22PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid WinModemClass::Set_Modem_Dial_Type(WinCommDialMethodType method)\n{\n\tDialingMethod = method;\n}\n\n\n\n\n/***********************************************************************************************\n * WMC::Get_Modem_Status -- gets the status of the modem control lines                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Modem status. Any of the following bits CTS_SET, DSR_SET, RI_SET or CD_SET        *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:24PM ST : Created                                                              *\n *=============================================================================================*/\n\nunsigned WinModemClass::Get_Modem_Status(void)\n{\n\tDWORD\t\tmodem_stat = 0;\n\tunsigned\tlong return_stat = 0;\n\n\t/*\n\t** Get the modem status\n\t*/\n\tGetCommModemStatus(PortHandle, &modem_stat);\n\n\t/*\n\t** Translate the windows status flags to greenleaf flags\n\t*/\n\tif (MS_CTS_ON  & modem_stat) return_stat |= CTS_SET;\n\tif (MS_DSR_ON  & modem_stat) return_stat |= DSR_SET;\n\tif (MS_RING_ON & modem_stat) return_stat |= RI_SET;\n\tif (MS_RLSD_ON & modem_stat) return_stat |= CD_SET;\n\n\treturn (return_stat);\n\n}\n\n\n\n/***********************************************************************************************\n * WMC::Set_Serial_DTR -- set the state of the modems DTR control line                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    state - true or false                                                             *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:25PM ST : Created                                                              *\n *=============================================================================================*/\nvoid WinModemClass::Set_Serial_DTR(BOOL state)\n{\n\tif (state){\n\t\tEscapeCommFunction(PortHandle, SETDTR);\n\t}else{\n\t\tEscapeCommFunction(PortHandle, CLRDTR);\n\t}\n}\n\n\n\n\n\n/***********************************************************************************************\n * WMC::Serial_Port_Close -- close the port and free the port handle                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:26PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid WinModemClass::Serial_Port_Close (void)\n{\n\tif (PortHandle){\n\t\tCloseHandle(PortHandle);\n\t\tPortHandle = 0;\n\t}\n}\n\n\n\n/***********************************************************************************************\n * WMC::Read_Serial_Chars -- copys chars from the windows serial buffer to the class buffer    *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   TRUE if any chars read                                                            *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:26PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid Smart_Printf( char *format, ... );\nBOOL WinModemClass::Read_Serial_Chars (void)\n{\n\tDWORD\tbytes_read;\t\t\t\t//amount of data read this time\n\tBOOL\tread_result;\t\t\t//result of ReadFile\n\tBOOL\toverlap_result;\t\t//result of GetOverlappedResult\n\tDWORD\ttotal_bytes_read=0;\t//total amount of data read\n\tint\tbytes_to_read;\n\tint\ti;\n\n\t/*\n\t** Are we were still waiting for the last read operation to finish?\n\t*/\n\tif (WaitingForSerialCharRead){\n\n\t\t/*\n\t\t** Check the result of the last read operation\n\t\t*/\n\t\tbytes_read = 0;\n\t\toverlap_result = GetOverlappedResult(PortHandle, &ReadOverlap, &bytes_read, FALSE);\n\n\t\t/*\n\t\t** If we got a good result from GetOverlappedResult and data was read then move it\n\t\t**  to our circular buffer\n\t\t*/\n\t\tif (overlap_result){\n\t\t\tWaitingForSerialCharRead = FALSE;\t//Flag that we are no longer waiting for a read\n\n\t\t\tif (bytes_read){\n\t\t\t\tfor (i=0 ; i<bytes_read ; i++){\n\t\t\t\t\t*(SerialBuffer + SerialBufferWritePtr++) = TempSerialBuffer[i];\n\t\t\t\t\tSerialBufferWritePtr &= SIZE_OF_WINDOWS_SERIAL_BUFFER - 1;\n\t\t\t\t}\n\t\t\t\ttotal_bytes_read += bytes_read;\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t** No chars were read since last time so just return\n\t\t\t*/\n\t\t\tif (GetLastError() == ERROR_IO_INCOMPLETE){\n\t\t\t\treturn (FALSE);\n\t\t\t}\n\t\t}\n\n\t}\n\n\n\t/*\n\t**\n\t** There is no outstanding read to wait for so try a new read\n\t**\n\t*/\n\n\t/*\n\t** Clear the event object\n\t*/\n\tResetEvent(ReadOverlap.hEvent);\n\n\n\t/*\n\t**\n\t** Clear any communications errors and get the number of bytes in the in buffer\n\t**\n\t*/\n\tDWORD \terror;\n\tCOMSTAT\tstatus;\n\n\tbytes_to_read = 1;\n\n\tif (ClearCommError(PortHandle, &error,\t&status)){\n\n\t\tInQueue \t= status.cbInQue;\n\t\tOutQueue\t= status.cbOutQue;\n\n\t\tif (error){\n\t\t\tif (CE_FRAME & error)\tFramingErrors++;\n\t\t\tif (CE_IOE & error) \t\tIOErrors++;\n\t\t\tif (CE_OVERRUN & error) BufferOverruns++;\n\t\t\tif (CE_RXOVER & error)  InBufferOverflows++;\n\t\t\tif (CE_RXPARITY & error)ParityErrors++;\n\t\t\tif (CE_TXFULL & error)  OutBufferOverflows++;\n\t\t\tbytes_to_read = 0;\n\t\t}else{\n\t\t\tbytes_to_read = min(status.cbInQue, SIZE_OF_WINDOWS_SERIAL_BUFFER);\n\t\t}\n\t}\n\n\tif (!bytes_to_read) bytes_to_read++;\n\n\n\t/*\n\t**\n\t** Start reading bytes\n\t**\n\t*/\n\n\tdo{\n\t\t/*\n\t\t** Try a read operation\n\t\t*/\n\t\tbytes_read = 0;\n\t\tread_result = ReadFile(PortHandle ,TempSerialBuffer ,bytes_to_read ,&bytes_read, &ReadOverlap);\n\n\t\tif (!read_result){\n\n\t\t\t/*\n\t\t\t** Read failed\n\t\t\t*/\n\t\t\tif (GetLastError() == ERROR_IO_PENDING){\n\n\t\t\t\t/*\n\t\t\t\t** But it threaded in the background OK so flag that we must wait for it to finish\n\t\t\t\t*/\n\t\t\t\tWaitingForSerialCharRead = TRUE;\n\t\t\t}\n\n\t\t}else{\n\n\t\t\t/*\n\t\t\t** Read was successful - copy to our circular buffer and try reading again\n\t\t\t*/\n\t\t\tif (bytes_read){\n\t\t\t\tfor (i=0 ; i<bytes_read ; i++){\n\t\t\t\t\t*(SerialBuffer + SerialBufferWritePtr++) = TempSerialBuffer[i];\n\t\t\t\t\tSerialBufferWritePtr &= SIZE_OF_WINDOWS_SERIAL_BUFFER - 1;\n\t\t\t\t}\n\t\t\t\ttotal_bytes_read += bytes_read;\n\t\t\t}\n\t\tbytes_to_read = 1;\n\t\t}\n\n\t} while (read_result == TRUE);\n\n\treturn ((BOOL)total_bytes_read);\n}\n\n\n\n\n\n\n\n/***********************************************************************************************\n * WMC::Read_From_Serial_Port -- retrieves chars from the internal class circular buffer which *\n *                               is filled from the windows serial buffer                      *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    buffer to copy to                                                                 *\n *           size of buffer                                                                    *\n *                                                                                             *\n * OUTPUT:   number of chars copied                                                            *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:27PM ST : Created                                                              *\n *=============================================================================================*/\n\nint WinModemClass::Read_From_Serial_Port (unsigned char *dest_ptr, int buffer_len)\n{\n\tint\tbytes_read;\n\tint\tbytes_to_copy = 0;\n\tunsigned char *original_dest = dest_ptr;\n\n\t/*\n\t** Get any outstanding data from the windows serial buffer into our class' circular buffer\n\t*/\n\tbytes_read = Read_Serial_Chars();\n\n\tif (bytes_read){\n\n\t\t/*\n\t\t** Calculate how many bytes should be copied to the user buffer\n\t\t*/\n\t\tbytes_to_copy = SerialBufferWritePtr - SerialBufferReadPtr;\n\t\tif (bytes_to_copy <0 ) bytes_to_copy += SIZE_OF_WINDOWS_SERIAL_BUFFER;\n\t\tif (bytes_to_copy>buffer_len) bytes_to_copy = buffer_len;\n\n\t\t/*\n\t\t** Loop to copy the data from the internal class buffer to the users buffer\n\t\t*/\n\t\tfor (int i=0 ; i<bytes_to_copy ; i++){\n\n\t\t\t/*\n\t\t\t** Call the users echo function if required\n\t\t\t*/\n\t\t\tif (EchoFunction && *(SerialBuffer + SerialBufferReadPtr) !=13 ){\n\t\t\t\tEchoFunction(*(SerialBuffer + SerialBufferReadPtr));\n\t\t\t}\n\n\t\t\t*dest_ptr++ = *(SerialBuffer + SerialBufferReadPtr++);\n\t\t\tSerialBufferReadPtr &= SIZE_OF_WINDOWS_SERIAL_BUFFER-1;\n\t\t}\n\t}\n\n#ifdef LOG_MODEM\n\n\tif (bytes_read){\n\n\t\tchar *outstr = new char[bytes_read+1];\n\t\tmemcpy (outstr, original_dest, bytes_read);\n\t\toutstr[bytes_read] = 0;\n\t\tOutputDebugString (outstr);\n\n\t\tint\thandle;\n\n\t\thandle = open(\"COMMLOG.TXT\",O_WRONLY | O_CREAT | O_APPEND | O_TEXT);\n\n\t\tif (handle != -1){\n\t\t\twrite(handle, original_dest, bytes_read);\n\t\t\tclose(handle);\n\t\t}\n\t}\n#endif\t//LOG_MODEM\n\n\n\treturn(bytes_to_copy);\n}\n\n\n\n\n/***********************************************************************************************\n * WMC::Wait_For_Serial_Write -- waits for output buffer to empty                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:29PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid WinModemClass::Wait_For_Serial_Write()\n{\n\tDWORD\t\t\t\t\t\tbytes_written;\n\tBOOL\t\t\t\t\t\toverlap_result;\n\tBOOL \t\t\t\t\t\twait_send;\n\tCountDownTimerClass\ttimer;\n\n\tif (WaitingForSerialCharWrite){\n\n\t\ttimer.Set(60*5);\n\n\t\t/*\n\t\t** Wait until the overlapped port write is finished\n\t\t*/\n\t\tdo{\n\t\t\twait_send = FALSE;\n\t\t\toverlap_result = GetOverlappedResult(PortHandle, &WriteOverlap, &bytes_written, FALSE);\n\n\t\t\tif (!overlap_result){\n\t\t\t\tif (GetLastError() == ERROR_IO_INCOMPLETE){\n\t\t\t\t\twait_send = TRUE;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}while(wait_send && timer.Time());\n\n\t\tWaitingForSerialCharWrite = FALSE;\n\t}\n\n\tResetEvent(WriteOverlap.hEvent);\n}\n\n\n\n\n/***********************************************************************************************\n * WMC::Write_To_Serial_Port -- writes data to the serial port                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to data                                                                       *\n *           bytes to write                                                                    *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:29PM ST : Created                                                              *\n *=============================================================================================*/\n\nvoid WinModemClass::Write_To_Serial_Port (unsigned char *buffer, int length)\n{\n\tDWORD\tbytes_written;\n\tBOOL\twrite_result;\n\n\n#ifdef LOG_MODEM\n\n\tif (length){\n\n\t\tchar *outstr = new char[length+1];\n\t\tmemcpy (outstr, buffer, length);\n\t\toutstr[length] = 0;\n\t\tOutputDebugString (outstr);\n\n\t\tint\thandle;\n\n\t\thandle = open(\"COMMLOG.TXT\",O_WRONLY | O_CREAT | O_APPEND | O_TEXT);\n\n\t\tif (handle != -1){\n\t\t\twrite(handle, buffer, length);\n\t\t\tclose(handle);\n\t\t}\n\t}\n#endif\t//LOG_MODEM\n\n\n\n\t/*\n\t** Wait for the end of the last write operation\n\t*/\n\tWait_For_Serial_Write();\n\n\t/*\n\t** Write the data to the port\n\t*/\n\twrite_result = WriteFile (PortHandle, buffer, length, &bytes_written, &WriteOverlap);\n\n\tif (!write_result){\n\t\tif (GetLastError() == ERROR_IO_PENDING){\n\t\t\tWaitingForSerialCharWrite = TRUE;\n\t\t}\n\t}\n\n}\n\n\n\n\n/***********************************************************************************************\n * WMC::Get_Modem_Result -- gets the result code from the modem after issuing an 'AT' command  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    delay for result time-out                                                         *\n *           ptr to buffer to receive modem result                                             *\n *           length of buffer                                                                  *\n *                                                                                             *\n * OUTPUT:   un-elapsed delay                                                                  *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:30PM ST : Created                                                              *\n *=============================================================================================*/\n\nextern void CCDebugString (char*);\n\nint WinModemClass::Get_Modem_Result(int delay, char *buffer, int buffer_len)\n{\n\n\tCountDownTimerClass\ttimer;\n\tint\t\t\t\t\t\tdest_ptr;\n\tchar\t\t\t\t\t\t*cr_ptr;\n\tchar\t\t\t\t\t\t*lf_ptr;\n\tint\t\t\t\t\t\tcopy_bytes;\n\n\t//OutputDebugString (\"Wincomm - In Get_Modem_Result\\n\");\n\n\tchar abuffer [128];\n\tsprintf (abuffer, \"Wincomm - delay = %d, buffer = %p, buffer_len = %d.\\n\", delay, buffer, buffer_len);\n\t//OutputDebugString (abuffer);\n\n\t//OutputDebugString (\"Wincomm - About to clear input buffer.\\n\");\n\tmemset(buffer, 0 ,buffer_len);\n\tdest_ptr = 0;\n\n\t/*\n\t** Loop to parse data from the modem and discard any echoed 'AT' commands or spurious LF\n\t** and CR characters.\n\t**\n\t*/\n\n\t//OutputDebugString (\"Wincomm - Entering do loop.\\n\");\n\tdo{\n\t\tcr_ptr \t= NULL;\t\t\t//Set the result pointer to NULL\n\t\t//OutputDebugString (\"Wincomm - About to set timer.\\n\");\n\t\ttimer.Set(delay/16);\t\t//Set and start the timer\n\n\t\t/*\n\t\t** Keep reading from the serial port until...\n\t\t**    1. we time out\n\t\t**    2. the user abort by pressing ESC\n\t\t**    3. the supplied buffer fills up\n\t\t**    4. there is an app switch\n\t\t** or 5. we get a CR character from the modem\n\t\t*/\n\t\t//OutputDebugString (\"Wincomm - About to enter inner do loop.\\n\");\n\t\tdo{\n\t\t\tif (AbortFunction){// &&\n\t\t\t\t //_Kbd->Check()) {\n\n\t\t\t\t//OutputDebugString (\"Wincomm - About to call abort function.\\n\");\n\t\t\t\tint abort = AbortFunction();\n\t\t\t\tsprintf (abuffer ,\"Wincomm - About function returned %d.\\n\", abort);\n\t\t\t\t//OutputDebugString (abuffer);\n\t\t\t\tif (abort != COMMSUCCESS) return (abort);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If we had lost focus then abort\n\t\t\t*/\n\t\t\tif (AllSurfaces.SurfacesRestored){\n\t\t\t\t//OutputDebugString (\"Wincomm - Aborting due to loss of focus.\\n\");\n\t\t\t\treturn (0);\n\t\t\t}\n\n\t\t\t//OutputDebugString (\"Wincomm - About to call Read_From_Serial_Port.\\n\");\n\t\t\tdest_ptr += Read_From_Serial_Port((unsigned char*)(buffer + dest_ptr), (int)buffer_len-dest_ptr);\n\t\t\tsprintf (abuffer, \"Wincomm - End of inner do loop. Time is %d.\\n\", timer.Time());\n\t\t\t//OutputDebugString (abuffer);\n\t\t} while (timer.Time() &&\n\t\t\t\t\tdest_ptr < buffer_len &&\n\t\t\t\t\t!strchr (buffer, 13) );\n\n\t\t//OutputDebugString (\"Wincomm - Exited inner do loop.\\n\");\n\n\n\t\t/*\n\t\t** We need to discard this result if it is just an echo of the 'AT' command we sent\n\t\t*/\n\t\tcr_ptr = strstr(buffer,\"AT\");\n\t\tif (cr_ptr){\n\t\t\tif (*buffer == 'A' && *(buffer+1) == 'T' && strchr(buffer,13)){\n\t\t\t\t//OutputDebugString (\"Wincomm - Discarding command echo.\\n\");\n\t\t\t\tcr_ptr = strchr(buffer,13);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** If it wasnt an AT echo then strip off any leading CR/LF characters\n\t\t*/\n\t\tif (!cr_ptr && (*buffer==13 || *buffer==10)){\n\t\t\tcr_ptr = strchr(buffer,13);\n\t\t\tlf_ptr = strchr(buffer,10);\n\t\t\tif (!cr_ptr || (lf_ptr && lf_ptr < cr_ptr)){\n\t\t\t\t//OutputDebugString (\"Wincomm - Stripping CR/LF.\\n\");\n\t\t\t\tcr_ptr = strchr(buffer,10);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Copy the good stuff at the end of the buffer over the 'AT' or CR/LF chars\n\t\t*/\n\t\tif (cr_ptr){\n\t\t\t//OutputDebugString (\"Wincomm - Copying over start of buffer.\\n\");\n\t\t\twhile(*cr_ptr == 13 || *cr_ptr == 10){\n\t\t\t\tcr_ptr++;\n\t\t\t}\n\n\t\t\tif (cr_ptr != buffer){\n\t\t\t\tcopy_bytes = (int)cr_ptr - (int)buffer;\n\t\t\t\tmemcpy(buffer, cr_ptr, buffer_len - copy_bytes);\n\t\t\t\tdest_ptr -= copy_bytes;\n\t\t\t}\n\t\t}\n\n\t\t//OutputDebugString (\"Wincomm - End of outer do loop.\\n\");\n\t}while(cr_ptr);\n\n\n\t/*\n\t** Terminate the string at the first CR character as this is what Greenleaf does\n\t*/\n\tif (strchr(buffer, 13)){\n\t\t//OutputDebugString (\"Truncating result string.\\n\");\n\t\t*(strchr(buffer, 13)) = 0;\n\t}\n\n\t//sprintf (abuffer, \"Wincomm - returning remaining delay of %d.\\n\", timer.Time());\n\t//OutputDebugString (abuffer);\n\treturn (timer.Time());\n}\n\n\n\n\n/***********************************************************************************************\n * WMC::Dial_Modem -- issue an 'ATD' command to the modem                                      *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    string - number to dial                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: Use Set_Modem_Dial_Type to choose pulse or tone dialling                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:32PM ST : Created                                                              *\n *=============================================================================================*/\nvoid WinModemClass::Dial_Modem(char *dial_number)\n{\n\tchar\tdial_string[80];\n\n\t/*\n\t** Create the dial command to send to the modem\n\t*/\n\tstrcpy (dial_string, \"ATD\");\n\tif (DialingMethod == WC_TOUCH_TONE){\n\t\tstrcat(dial_string, \"T\");\n\t}else{\n\t\tstrcat(dial_string, \"P\");\n\t}\n\n\t/*\n\t** Stick a carriage return on the end\n\t*/\n\tstrcat (dial_string, dial_number);\n\tstrcat (dial_string, \"\\r\");\n\n\t/*\n\t** Write the dial command to the serial port and wait for the write to complete\n\t*/\n\tWrite_To_Serial_Port ((unsigned char*)dial_string, strlen(dial_string));\n\tWait_For_Serial_Write();\n}\n\n\n\n\n\n/***********************************************************************************************\n * WMC::Send_Command_To_Modem -- send an 'AT' command to the modem and await a response        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    command string                                                                    *\n *           terminator byte (usually \"\\r\")                                                    *\n *           ptr to buffer to receive modem result code                                        *\n *           length of buffer                                                                  *\n *           timeout delay for waiting for result                                              *\n *           number of times to retry the command                                              *\n *                                                                                             *\n * OUTPUT:   result code                                                                       *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:33PM ST : Created                                                              *\n *=============================================================================================*/\n\nint WinModemClass::Send_Command_To_Modem(char *command, char terminator, char *buffer, int buflen, int delay, int retries)\n{\n\n\tint\t\t\t\ttimes;\n\tunsigned\tchar\ttmp_string[80];\n\tchar\t\t\t\ttmp_buff[80];\n\tchar\t\t\t\tterm_string[2];\n\tint\t\t\t\ttime;\n\n\t/*\n\t** Build the terminator string\n\t*/\n\tterm_string[0]\t= terminator;\n\tterm_string[1]\t= 0;\n\n\t/*\n\t** Create the command from the supplied command and terminator\n\t*/\n\tstrcpy((char*)tmp_string, command);\n\tstrcat((char*)tmp_string, term_string);\n\n\n\t/*\n\t** Flush out any pending characters from the port\n\t*/\n\tunsigned char\tnothing_buff[80];\n\tRead_From_Serial_Port(nothing_buff,80);\n\tSleep (100);\n\tRead_From_Serial_Port(nothing_buff,80);\n\n\n\tfor (times = 0 ; times<retries; times++){\n\n\t\t/*\n\t\t** Write the command to the serial port\n\t\t*/\n//Smart_Printf(\"%s\",tmp_string);\n\t\tWrite_To_Serial_Port (tmp_string, strlen((char*)tmp_string));\n\t\tWait_For_Serial_Write();\n\n\t\t//Delay(120);\n\n\t\t/*\n\t\t** Wait for the result of the command from the modem\n\t\t*/\n\t\tmemset(tmp_buff, 0, 80);\n\t\ttime = Get_Modem_Result(delay, tmp_buff, 80);\n//Smart_Printf(\"%s%s\",tmp_buff,\"\\r\");\n\n\t\t/*\n\t\t** If it is a pretty standard result then just return\n\t\t*/\n\t\tif (!strcmp(tmp_buff,\"0\")) return (MODEM_CMD_0);\n\t\tif (strstr(tmp_buff,\"OK\")) return (MODEM_CMD_OK);\n\t\tif (strstr(tmp_buff,\"ERROR\")) return (MODEM_CMD_ERROR);\n\n\t\t/*\n\t\t** If the result was a 3 digit number then copy it to the users buffer and return OK\n\t\t*/\n\t\tif (strlen(tmp_buff)==3){\n\t\t\tif ( (tmp_buff[0] >= '0' && tmp_buff[0] <='9') &&\n\t\t\t\t  (tmp_buff[1] >= '0' && tmp_buff[1] <='9') &&\n\t\t\t\t  (tmp_buff[2] >= '0' && tmp_buff[2] <='9')) {\n\t\t\t\tstrncpy(buffer, tmp_buff, MIN(buflen, 80));\n\t\t\t\treturn (MODEM_CMD_OK);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** It was a non-standard(ish) result so copy it to the users buffer\n\t\t*/\n\t\tstrncpy(buffer, tmp_buff, MIN(buflen, 80));\n\n\t\t/*\n\t\t** Spurious write for no apparent reason. Well it was there in the DOS version so...\n\t\t*/\n\t\tSleep (100);\n\t\tWrite_To_Serial_Port((unsigned char*)\"\\r\",1);\n\t\tWait_For_Serial_Write();\n\t\tSleep (100);\n\t}\n\n\treturn (ASTIMEOUT);\n}\n\n\n\n/***********************************************************************************************\n * WMC::Set_Echo_Function -- set up the echo function pointer                                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to echo function                                                              *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:35PM ST : Created                                                              *\n *=============================================================================================*/\nvoid WinModemClass::Set_Echo_Function( void ( *func )( char c) )\n{\n\tEchoFunction = func;\n}\n\n\n\n/***********************************************************************************************\n * WMC::Set_Abort_Function -- set up the abort function pointer                                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to abort function                                                             *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/10/96 2:35PM ST : Created                                                              *\n *=============================================================================================*/\nvoid WinModemClass::Set_Abort_Function(int (*func)(void))\n{\n\tAbortFunction = func;\n}\n\n\n/***********************************************************************************************\n * WMC::Get_Port_Handle -- returns a handle to the communications port                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Com port handle                                                                   *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/23/96 1:25PM ST : Created                                                              *\n *=============================================================================================*/\nHANDLE\tWinModemClass::Get_Port_Handle(void)\n{\n\treturn (PortHandle);\n}\n\n"
  },
  {
    "path": "WIN32LIB/WINCOMM/WINCOMM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/***********************************************************************************************\n ***              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               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer/ WW Library                                *\n *                                                                                             *\n *                    File Name : WINCOMM.H                                                    *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 1/10/96                                                      *\n *                                                                                             *\n *                  Last Update : January 10th 1996 [ST]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *                                                                                             *\n *   These classes was created to replace the greenleaf comms functions used in C&C DOS with   *\n *  WIN32 API calls.                                                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef WIN32\n#define\tWIN32\n#define\t_WIN32\n#endif\t//WIN32\n#include <windows.h>\n\ntypedef enum WinCommDialMethodType {\n\tWC_TOUCH_TONE = 0,\n\tWC_PULSE\n} WinCommDialMethodType;\n\n\n\n#define\tCOMMSUCCESS\t\t0\n#define \tASTIMEOUT      -10\n#define\tCOMMUSERABORT\t-16\n\n\n/*\n** The size of our serial buffer within the class.\n**\n** !!!!!! THIS MUST BE  A POWER OF 2 !!!!!!\n**\n*/\n#define SIZE_OF_WINDOWS_SERIAL_BUFFER 2048\n\n\n\n/*\n** WinModemClass.\n**\n** This class provides access to modems under Win95. The functions are designed to be more or less\n** drop in replacements for the Grenleaf comms functions.\n*/\n\nclass WinModemClass\n{\n\n\tpublic:\n\n\t\t\t\t\tWinModemClass (void);\t\t//WinModemClass Contructor\n\t\tvirtual\t~WinModemClass (void);\t\t//WinModemClass Destructor\n\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Serial port open should be called to get a handle to the COM port\n\t\t\t\t\t** This needs to be called first as other class members rely on the handle\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: PortOpenGreenleafFast\n\t\t\t\t\t*/\n\t\t//virtual\tHANDLE\tSerial_Port_Open (int port, int baud, int parity, int wordlen, int stopbits);\n\t\tvirtual\tHANDLE\tSerial_Port_Open (char *device_name, int baud, int parity, int wordlen, int stopbits, int flowcontrol);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** This function releases the COM port handle and should be called after\n\t\t\t\t\t** communications have finished\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: PortClose\n\t\t\t\t\t*/\n\t\t\t\t\tvoid\t\tSerial_Port_Close (void);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** This member copies any bytes from the internal class serial buffer\n\t\t\t\t\t** into your user buffer.\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: ReadBuffer\n\t\t\t\t\t*/\n\t\t\t\t\tint\t\tRead_From_Serial_Port (unsigned char *dest_ptr, int buffer_len);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Write chars to the serial port\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: WriteBuffer\n\t\t\t\t\t*/\n\t\t\t\t\tvoid\t\tWrite_To_Serial_Port (unsigned char *buffer, int length);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Wait for the outgoing buffer to empty\n\t\t\t\t\t*/\n\t\t\t\t\tvoid\t\tWait_For_Serial_Write (void);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Set the dial type to DIAL_TOUCH_TONE or DIAL_PULSE\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: HMSetDiallingMethod\n\t\t\t\t\t*/\n\t\tvirtual\tvoid\t\tSet_Modem_Dial_Type (WinCommDialMethodType method);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Get the status of the modem control lines\n\t\t\t\t\t** Possible flags are: CTS_SET DSR_SET RI_SET & CD_SET\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: GetModemStatus\n\t\t\t\t\t*/\n\t\tvirtual\tunsigned\tGet_Modem_Status (void);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Set the DTR line to the given state\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: SetDtr\n\t\t\t\t\t*/\n\t\tvirtual\tvoid\t\tSet_Serial_DTR (BOOL state);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Get the result code from the modem after issuing an 'AT' command\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: HMInputLine\n\t\t\t\t\t*/\n\t\tvirtual\tint\t\tGet_Modem_Result (int delay, char *buffer, int buffer_len);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Issue a dial command to the modem.\n\t\t\t\t\t** Use Set_Modem_Dial_Type to select pulse or tone dial\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: HMDial\n\t\t\t\t\t*/\n\t\tvirtual\tvoid\t\tDial_Modem (char *dial_number);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Send a command to the modem. This is usually an 'AT' command.\n\t\t\t\t\t** Function will optionally retry until 'OK' is received.\n\t\t\t\t\t*/\n\t\tvirtual\tint\t\tSend_Command_To_Modem (char *command, char terminator, char *buffer, int buflen, int delay, int retries);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Sets a pointer to a function that will be called for each incoming serial char\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: HMSetUpEchoRoutine\n\t\t\t\t\t*/\n\t\tvirtual\tvoid\t\tSet_Echo_Function (void(*func)(char c));\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Sets a pointer to a function that will be called if ESC is pressed during a dial\n\t\t\t\t\t**\n\t\t\t\t\t** Replacement for Greenleaf function: HMSetUpAbortKey\n\t\t\t\t\t*/\n\t\tvirtual\tvoid\t\tSet_Abort_Function (int (*func)(void));\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Member to allow access to the serial port handle\n\t\t\t\t\t*/\n\t\t\t\t\tHANDLE\tGet_Port_Handle(void);\n\n\t\t/*\n\t\t** Status vars for debugging purposes\n\t\t*/\n\t\tint FramingErrors;\n\t\tint IOErrors;\n\t\tint BufferOverruns;\n\t\tint InBufferOverflows;\n\t\tint ParityErrors;\n\t\tint OutBufferOverflows;\n\t\tint InQueue;\n\t\tint OutQueue;\n\n\t\t/*\n\t\t** Modem send result codes\n\t\t*/\n\t\tenum SendModemEnum {\n\t\t\tMODEM_CMD_TIMEOUT = 0,\n\t\t\tMODEM_CMD_OK,\n\t\t\tMODEM_CMD_0,\n\t\t\tMODEM_CMD_ERROR\n\t\t};\n\n\n\t\t/*\n\t\t** Enums for modem status flags\n\t\t*/\n\t\tenum {\n\t\t\tCTS_SET  = 0x10,\n\t\t\tDSR_SET  = 0x20,\n          RI_SET   = 0x40,\n          CD_SET   = 0x80\n       };\n\n\n\tprotected:\n\n\n\t\t/*\n\t\t** Copy incoming data from the windows file buffer into the internal class buffer\n\t\t*/\n\t\tBOOL\t\t\t\t\t\t\tRead_Serial_Chars(void);\n\n\t\t/*\n\t\t** Pointer to the internal class circular buffer for incoming data\n\t\t*/\n\t\tunsigned char\t\t\t\t*SerialBuffer;\n\n\t\t/*\n\t\t** Overlap object for asyncronous reads from the serial port\n\t\t*/\n\t\tOVERLAPPED\t\t\t\t\tReadOverlap;\n\n\t\t/*\n\t\t** Overlap object for asyncronous writes to the serial port\n\t\t*/\n\t\tOVERLAPPED\t\t\t\t\tWriteOverlap;\n\n\t\t/*\n\t\t** Flag that there is no outstanding incoming data in the windows buffer\n\t\t*/\n\t\tBOOL\t\t\t\t\t\t\tWaitingForSerialCharRead;\n\n\t\t/*\n\t\t** Flag that we are waiting for the last write to port operation to complete\n\t\t*/\n\t\tBOOL\t\t\t\t\t\t\tWaitingForSerialCharWrite;\n\n\t\t/*\n\t\t** Head and Tail pointers for our internal serial buffer\n\t\t*/\n\t\tint\t\t\t\t\t\t\tSerialBufferReadPtr;\n\t\tint\t\t\t\t\t\t\tSerialBufferWritePtr;\n\n\t\t/*\n\t\t** Windows handle to the COM port device\n\t\t*/\n\t\tHANDLE\t\t\t\t\t\tPortHandle;\n\n\t\t/*\n\t\t** Dialing method - DIAL_TOUCH_TONE or DIAL_PULSE\n\t\t*/\n\t\tWinCommDialMethodType\tDialingMethod;\n\n\t\t/*\n\t\t** Pointer to function for echoing incoming data - can be NULL\n\t\t*/\n\t\tvoid \t\t\t\t\t\t\t(*EchoFunction)(char c);\n\n\t\t/*\n\t\t** Pointer to function for aborting when ESC pressed - can be NULL\n\t\t*/\n\t\tint\t\t\t\t\t\t\t(*AbortFunction)(void);\n\n\t\t/*\n\t\t** Serial buffer for asyncronous reads\n\t\t*/\n\t\tchar\t\t\t\t\t\t\tTempSerialBuffer[SIZE_OF_WINDOWS_SERIAL_BUFFER];\n};\n\n\n\n\n\n\n\n\n\n\n/*\n** WinNullModemClass.\n**\n** This class provides access to serial ports under Win95. The functions are designed to be more or less\n** drop in replacements for the Grenleaf comms functions.\n**\n** This class just overloads the WinModemClass members that arent required for direct serial communications\n** via a 'null modem' cable.\n*/\nclass WinNullModemClass : public WinModemClass\n{\n\n\tpublic:\n\n\t\tvirtual\tinline\tvoid\t\tSet_Modem_Dial_Type (int){};\n\t\tvirtual\tinline\tunsigned\tGet_Modem_Status (void){return (0);};\n\t\tvirtual\tinline\tvoid\t\tSet_Serial_DTR (BOOL){};\n\t\tvirtual\tinline\tint\t\tGet_Modem_Result (int, char*, int){return(0);};\n\t\tvirtual\tinline\tvoid\t\tDial_Modem (char*){};\n\t\tvirtual\tinline\tint\t\tSend_Command_To_Modem (char*, char, char*, int, int, int){return (0);};\n\t\tvirtual\tinline\tvoid\t\tSet_Echo_Function (void(*)(char)){};\n\t\tvirtual\tinline\tvoid\t\tSet_Abort_Function (int(*)(void)){};\n\n};\n\n\nextern WinModemClass *SerialPort;\n\n\n\n\n\n\n\n\n\n//\n//\n// This bit swiped from the SDK because its not in the Watcom headers yet\n//\n//\n\n/************************************************************************\n*                                                                       *\n*   mcx.h -- This module defines the 32-Bit Windows MCX APIs            *\n*                                                                       *\n*   Copyright (c) 1990-1995, Microsoft Corp. All rights reserved.       *\n*                                                                       *\n************************************************************************/\n\n#ifndef _MCX_H_\n#define _MCX_H_\n\ntypedef struct _MODEMDEVCAPS {\n    DWORD   dwActualSize;\n    DWORD   dwRequiredSize;\n    DWORD   dwDevSpecificOffset;\n    DWORD   dwDevSpecificSize;\n\n    // product and version identification\n    DWORD   dwModemProviderVersion;\n    DWORD   dwModemManufacturerOffset;\n    DWORD   dwModemManufacturerSize;\n    DWORD   dwModemModelOffset;\n    DWORD   dwModemModelSize;\n    DWORD   dwModemVersionOffset;\n    DWORD   dwModemVersionSize;\n\n    // local option capabilities\n    DWORD   dwDialOptions;          // bitmap of supported values\n    DWORD   dwCallSetupFailTimer;   // maximum in seconds\n    DWORD   dwInactivityTimeout;    // maximum in seconds\n    DWORD   dwSpeakerVolume;        // bitmap of supported values\n    DWORD   dwSpeakerMode;          // bitmap of supported values\n    DWORD   dwModemOptions;         // bitmap of supported values\n    DWORD   dwMaxDTERate;           // maximum value in bit/s\n    DWORD   dwMaxDCERate;           // maximum value in bit/s\n\n    // Variable portion for proprietary expansion\n    BYTE    abVariablePortion [1];\n} MODEMDEVCAPS, *PMODEMDEVCAPS, *LPMODEMDEVCAPS;\n\ntypedef struct _MODEMSETTINGS {\n    DWORD   dwActualSize;\n    DWORD   dwRequiredSize;\n    DWORD   dwDevSpecificOffset;\n    DWORD   dwDevSpecificSize;\n\n    // static local options (read/write)\n    DWORD   dwCallSetupFailTimer;       // seconds\n    DWORD   dwInactivityTimeout;        // seconds\n    DWORD   dwSpeakerVolume;            // level\n    DWORD   dwSpeakerMode;              // mode\n    DWORD   dwPreferredModemOptions;    // bitmap\n\n    // negotiated options (read only) for current or last call\n    DWORD   dwNegotiatedModemOptions;   // bitmap\n    DWORD   dwNegotiatedDCERate;        // bit/s\n\n    // Variable portion for proprietary expansion\n    BYTE    abVariablePortion [1];\n} MODEMSETTINGS, *PMODEMSETTINGS, *LPMODEMSETTINGS;\n\n// Dial Options\n#define DIALOPTION_BILLING  0x00000040  // Supports wait for bong \"$\"\n#define DIALOPTION_QUIET    0x00000080  // Supports wait for quiet \"@\"\n#define DIALOPTION_DIALTONE 0x00000100  // Supports wait for dial tone \"W\"\n\n// SpeakerVolume for MODEMDEVCAPS\n#define MDMVOLFLAG_LOW      0x00000001\n#define MDMVOLFLAG_MEDIUM   0x00000002\n#define MDMVOLFLAG_HIGH     0x00000004\n\n// SpeakerVolume for MODEMSETTINGS\n#define MDMVOL_LOW          0x00000000\n#define MDMVOL_MEDIUM       0x00000001\n#define MDMVOL_HIGH         0x00000002\n\n// SpeakerMode for MODEMDEVCAPS\n#define MDMSPKRFLAG_OFF         0x00000001\n#define MDMSPKRFLAG_DIAL        0x00000002\n#define MDMSPKRFLAG_ON          0x00000004\n#define MDMSPKRFLAG_CALLSETUP   0x00000008\n\n// SpeakerMode for MODEMSETTINGS\n#define MDMSPKR_OFF         0x00000000\n#define MDMSPKR_DIAL        0x00000001\n#define MDMSPKR_ON          0x00000002\n#define MDMSPKR_CALLSETUP   0x00000003\n\n// Modem Options\n#define MDM_COMPRESSION      0x00000001\n#define MDM_ERROR_CONTROL    0x00000002\n#define MDM_FORCED_EC        0x00000004\n#define MDM_CELLULAR         0x00000008\n#define MDM_FLOWCONTROL_HARD 0x00000010\n#define MDM_FLOWCONTROL_SOFT 0x00000020\n#define MDM_CCITT_OVERRIDE   0x00000040\n#define MDM_SPEED_ADJUST     0x00000080\n#define MDM_TONE_DIAL        0x00000100\n#define MDM_BLIND_DIAL       0x00000200\n#define MDM_V23_OVERRIDE     0x00000400\n\n#endif /* _MCX_H_ */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "WIN32LIB/WSA/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = wsa\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\twsa.obj\t\t&\n\txordelta.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB32)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/WSA/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = wsa\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t   wsa.obj\t\t\t\\\n   \t\t\txordelta.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) \n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n +-wsa.obj\t\t\t&\n+-xordelta.obj\n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/WSA/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = wsa\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\twsa.obj\t\t&\n\txordelta.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB32)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include \n\t copy *.inc $(%WIN32LIB)\\include \n\t copy *.cpp $(%WIN32LIB)\\srcdebug \n\t copy *.asm $(%WIN32LIB)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WIN32LIB/WSA/WSA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./wsa.c 1.16 1994/05/20 15:35:27 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library Animation System                 *\n *                                                                         *\n *                    File Name : WSA.C                                    *\n *                                                                         *\n *                   Programmer : Michael Legg                             *\n *                                                                         *\n *                   Start Date : November 20, 1991                        *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *   There are many different ways that the user can use the WSA library   *\n * module.  The options are as follows :                                   *\n *                                                                         *\n *   System Allocation vs User Buffer - The user may request that the      *\n *       system allocate the needed buffer from the heap or the user may\t*\n *       pass his own buffer in for the animator to use.                   *\n *                                                                         *\n *   Resident vs File based - If there is enough RAM, the user may put the *\n *       entire animation into RAM for fastest animations.  If there is    *\n *       not enouph RAM, the system will automatically make it so each     *\n *       frame will be read off disk when needed.                          *\n *                                                                         *\n *   Direct to Page vs Use of a user buffer -- Noramally Direct to page\t\t*\n *       is the best method both in speed and in RAM need to hold anim.    *\n *       One may want to use the write to user buffer method if they       *\n *       are using the animation in a non sequencial order.                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Animate_Frame -- Displays a frame of a given animation                *\n *   Get_Animation_Frame_Count --  Return Number of frames in an animation.  *\n *   Get_Animation_X -- Gets the x from an animation                       *\n *   Get_Animation_Y -- Gets the y from an animation                       *\n *   Get_Animation_Width -- Gets the width from an animation               *\n *   Get_Animation_Height -- The height of the animation we are processing *\n *   Apply_Delta -- Copies frame into delta buffer, then applies to target *\n *   Close_Animation -- Close the animation, freeing the space if necessary*\n *   Get_File_Frame_Offset -- Get offset of a delta frame from animate file*\n *   Get_Resident_Frame_Offset -- Gets frame offset of animate file in RAM *\n *   Open_Animation -- Opens an animation file and reads into buffer       *\n *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include <wwstd.h>\n#include \"wsa.h\"\n#include <wwmem.h>\n#include <file.h>\n#include <misc.h>\n#include <iff.h>\n#include <mem.h>\n#include <string.h>\n\n//\n// WSA animation header allocation type.\n// If we need more then 8 flags for the flags variable, we can combine\n// USER_ALLOCATED with SYS_ALLOCATED  and combine FILE with RESIDENT.\n//\n#define\tWSA_USER_ALLOCATED \t0x01\n#define\tWSA_SYS_ALLOCATED  \t0x02\n#define\tWSA_FILE           \t0x04\n#define\tWSA_RESIDENT       \t0x08\n#define\tWSA_TARGET_IN_BUFFER\t0x10\n#define\tWSA_LINEAR_ONLY\t\t0x20\n#define\tWSA_FRAME_0_ON_PAGE  0x40\n#define\tWSA_AMIGA_ANIMATION  0x80\n#define\tWSA_PALETTE_PRESENT\t0x100\n#define\tWSA_FRAME_0_IS_DELTA\t0x200\n\n// These are used to call Apply_XOR_Delta_To_Page_Or_Viewport() to setup flags parameter.  If\n// These change, make sure and change their values in lp_asm.asm.\n#define\tDO_XOR\t\t\t\t\t0x0\n#define\tDO_COPY\t\t\t\t\t0x01\n#define\tTO_VIEWPORT\t\t\t\t0x0\n#define\tTO_PAGE\t\t\t\t\t0x02\n\n\n\n\ntypedef struct {\n\tunsigned short current_frame;\n\tunsigned short total_frames;\n\tunsigned short pixel_x;\n\tunsigned short pixel_y;\n\tunsigned short pixel_width;\n\tunsigned short pixel_height;\n\tunsigned short largest_frame_size;\n\tchar *delta_buffer;\n\tchar *file_buffer;\n\tchar file_name[ 13 ];\n\tshort flags;\n\t// New fields that animate does not know about below this point. SEE EXTRA_charS_ANIMATE_NOT_KNOW_ABOUT\n\tshort file_handle;\n\tunsigned long anim_mem_size;\n} SysAnimHeaderType;\n\n// NOTE:\"THIS IS A BAD THING. SINCE sizeof(SysAnimHeaderType) CHANGED, THE ANIMATE.EXE\n// UTILITY DID NOT KNOW I UPDATED IT, IT ADDS IT TO largest_frame_size BEFORE SAVING\n// IT TO THE FILE.  THIS MEANS I HAVE TO ADD THESE charS ON NOW FOR IT TO WORK.\n#define EXTRA_charS_ANIMATE_NOT_KNOW_ABOUT\t(sizeof(short) + sizeof(unsigned long))\n\n\n//\n// Header structure for the file.\n// NOTE:  The 'total_frames' field is used to differentiate between Amiga and IBM\n// animations.  Amiga animations have the HIGH bit set.\n//\ntypedef struct {\n\tunsigned short total_frames;\n\tunsigned short pixel_x;\n\tunsigned short pixel_y;\n\tunsigned short pixel_width;\n\tunsigned short pixel_height;\n\tunsigned short largest_frame_size;\n\tshort\tflags;\n\tunsigned long frame0_offset;\n\tunsigned long frame0_end;\n\t/* unsigned long data_seek_offset, unsigned short frame_size ... */\n} WSA_FileHeaderType;\n\n#define WSA_FILE_HEADER_SIZE\t( sizeof(WSA_FileHeaderType) - (2 * sizeof(unsigned long)) )\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE unsigned long Get_Resident_Frame_Offset( char *file_buffer, int frame );\nPRIVATE unsigned long Get_File_Frame_Offset( int file_handle, int frame, int palette_adjust);\nPRIVATE BOOL Apply_Delta(SysAnimHeaderType *sys_header, int curr_frame, char *dest_ptr, int dest_w);\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * OPEN_ANIMATION -- Opens an animation file and reads into buffer         *\n *                                                                         *\n * INPUT:   char *file_name of animation sequence file.                    *\n *          char *user_buffer pointer if one exists  (NULL ok)             *\n *          unsigned long user_buffer_size if known  (NULL ok)                     *\n *          WSAOpenType user_flags - flags on how to open.                 *\n *          unsigned char *palette - pointer to palette space for return (NULL ok) *\n *                                                                         *\n * OUTPUT:  void *pointer to animation data.  Must be used for all \t\t\t*\n *               other WSA calls.                                          *\n *                                                                         *\n * WARNINGS: May return NULL, please check.                                *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/26/1991  SB : Created.                                             *\n *=========================================================================*/\nvoid * __cdecl Open_Animation(char const *file_name, char *user_buffer, long user_buffer_size, WSAOpenType user_flags, unsigned char *palette)\n{\n\tint\t\t\t\t\t\tfh, anim_flags;\n\tint\t\t\t\t\t\tpalette_adjust;\n\tunsigned int\t\t\t\t\t\toffsets_size;\n\tunsigned int\t\t\t\t\t\tframe0_size;\n\tlong\t\t\t\t\t\ttarget_buffer_size, delta_buffer_size, file_buffer_size;\n\tlong\t\t\t\t\t\tmax_buffer_size,    min_buffer_size;\n\tchar\t\t\t\t\t\t*sys_anim_header_buffer;\n\tchar\t\t\t\t\t\t*target_buffer;\n\tchar\t\t\t\t\t\t*delta_buffer, *delta_back;\n\tSysAnimHeaderType\t\t*sys_header;\n\tWSA_FileHeaderType\tfile_header;\n\n\t/*======================================================================*/\n\t/* Open the file to get the header information\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\n\tanim_flags\t= 0;\n\tfh\t\t\t\t= Open_File(file_name, READ);\n\tRead_File(fh, (char *) &file_header, sizeof(WSA_FileHeaderType));\n\n\t/*======================================================================*/\n\t/* If the file has an attached palette then if we have a valid palette\t*/\n\t/*\t\tpointer we need to read it in.\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\n\tif (file_header.flags & 1) {\n\t\tanim_flags\t\t|= WSA_PALETTE_PRESENT;\n\t\tpalette_adjust\t = 768;\n\n\t\tif (palette != NULL) {\n\t\t\tSeek_File(fh, sizeof(unsigned long) * (file_header.total_frames), SEEK_CUR);\n\t\t\tRead_File(fh, palette, 768L);\n\t\t}\n\n\t} else {\n\t\tpalette_adjust = 0;\n\t}\n\n\t// Check for flag from ANIMATE indicating that this animation was\n\t// created from a .LBM and a .ANM.  These means that the first\n\t// frame is a XOR Delta from a picture, not black.\n\tif (file_header.flags & 2) {\n\t\tanim_flags\t\t|= WSA_FRAME_0_IS_DELTA;\n\t}\n\n\n\t// Get the total file size minus the size of the first frame and the size\n\t// of the file header.  These will not be read in to save even more space.\n\tfile_buffer_size = Seek_File(fh, 0L, SEEK_END);\n\n\tif (file_header.frame0_offset) {\n\t\tlong tlong;\n\n\t\ttlong = file_header.frame0_end - file_header.frame0_offset;\n\t\tframe0_size = (unsigned short) tlong;\n\t}\n\telse {\n\t\tanim_flags |= WSA_FRAME_0_ON_PAGE;\n\t\tframe0_size = 0;\n\t}\n\n\tfile_buffer_size -= palette_adjust + frame0_size + WSA_FILE_HEADER_SIZE;\n\n\t// We need to determine the buffer sizes required for the animation.  At a\n\t// minimum, we need a target buffer for the uncompressed frame and a delta\n\t// buffer for the delta data.  We may be able to make the file resident,\n\t// so we will determine the file size.\n\t//\n\t// If the target buffer is in the user buffer\n\t// Then figure its size\n\t// and set the allocation flag\n\t// Else size is zero.\n\t//\n\tif (user_flags & WSA_OPEN_DIRECT) {\n\t \ttarget_buffer_size = 0L;\n\t}\n\telse {\n\t\tanim_flags |= WSA_TARGET_IN_BUFFER;\n\t\ttarget_buffer_size = (unsigned long) file_header.pixel_width * file_header.pixel_height;\n\t}\n\n\t// NOTE:\"THIS IS A BAD THING. SINCE sizeof(SysAnimHeaderType) CHANGED, THE ANIMATE.EXE\n\t// UTILITY DID NOT KNOW I UPDATED IT, IT ADDS IT TO largest_frame_size BEFORE SAVING\n\t// IT TO THE FILE.  THIS MEANS I HAVE TO ADD THESE charS ON NOW FOR IT TO WORK.\n\tdelta_buffer_size  = (unsigned long) file_header.largest_frame_size + EXTRA_charS_ANIMATE_NOT_KNOW_ABOUT;\n\tmin_buffer_size = target_buffer_size + delta_buffer_size;\n\tmax_buffer_size = min_buffer_size + file_buffer_size;\n\n\t// check to see if buffer size is big enough for at least min required\n\tif (user_buffer && (user_buffer_size < min_buffer_size)) {\n\t\tClose_File(fh);\n\t\treturn(NULL);\n\t}\n\n\t// A buffer was not passed in, so do allocations\n\tif (user_buffer == NULL) {\n\n\t\t// If the user wants it from the disk, then let us give it to him,\n\t\t// otherwise, try to give a max allocation he can have.\n\t\tif (user_flags & WSA_OPEN_FROM_DISK) {\n\t\t\tuser_buffer_size = min_buffer_size;\n\t\t}\n\t\t// else no buffer size, then try max configuration.\n\t\telse if (!user_buffer_size) {\n\t\t\tuser_buffer_size = max_buffer_size;\n\t\t}\n\t\t// else if buffer specified is less then max needed, give min.\n\t\telse if (user_buffer_size < max_buffer_size) {\n\t\t\tuser_buffer_size = min_buffer_size;\n\t\t}\n\t\t// otherwise we only want to alloc what we need.\n\t\telse {\n\t\t\tuser_buffer_size = max_buffer_size;\n\t\t}\n\n\n\t\t// Check to see if enough RAM available for buffer_size.\n\t\tif (user_buffer_size > Ram_Free(MEM_NORMAL)) {\n\n \t\t\t// If not enough room for even the min, return no buffer.\n\n\t\t\tif (min_buffer_size > Ram_Free(MEM_NORMAL)) {\n\t\t\t\tClose_File(fh);\n\t\t\t\treturn(NULL);\n\t\t\t}\n\n\t\t\t// Else make buffer size the min and allocate it.\n\t\t\tuser_buffer_size = min_buffer_size;\n\t\t}\n\n\t\t// allocate buffer needed\n\t\tuser_buffer = (char *) Alloc(user_buffer_size, MEM_CLEAR);\n\n\t\tanim_flags |= WSA_SYS_ALLOCATED;\n\t}\n\telse {\n\t\t// Check to see if the user_buffer_size should be min or max.\n\t\tif ((user_flags & WSA_OPEN_FROM_DISK) || (user_buffer_size < max_buffer_size)) {\n\t\t \tuser_buffer_size = min_buffer_size;\n\t\t}\n\t\telse {\n\t\t \tuser_buffer_size = max_buffer_size;\n\t\t}\n\t\tanim_flags |= WSA_USER_ALLOCATED;\n\t}\n\n\n\t// Set the pointers to the RAM buffers\n\tsys_anim_header_buffer = user_buffer;\n\ttarget_buffer = (char *) Add_Long_To_Pointer(sys_anim_header_buffer, sizeof(SysAnimHeaderType));\n\tdelta_buffer  = (char *) Add_Long_To_Pointer(target_buffer, target_buffer_size);\n\n\t//\tClear target buffer if it is in the user buffer.\n\tif (target_buffer_size) {\n\t\tmemset( target_buffer, 0, (unsigned short) target_buffer_size );\n\t}\n\n\t// Poke data into the system animation header (start of user_buffer)\n\t// current_frame is set to total_frames so that Animate_Frame() knows that\n\t// it needs to clear the target buffer.\n\n\tsys_header = ( SysAnimHeaderType * ) sys_anim_header_buffer;\n\tsys_header -> current_frame =\n\tsys_header -> total_frames  = file_header.total_frames;\n\tsys_header -> pixel_x\t\t = file_header.pixel_x;\n\tsys_header -> pixel_y\t\t = file_header.pixel_y;\n\tsys_header -> pixel_width   = file_header.pixel_width;\n\tsys_header -> pixel_height  = file_header.pixel_height;\n\tsys_header -> anim_mem_size = user_buffer_size;\n\tsys_header -> delta_buffer  = delta_buffer;\n\tsys_header -> largest_frame_size =\n                 (unsigned short) (delta_buffer_size - sizeof(SysAnimHeaderType));\n\n\tstrcpy(sys_header->file_name, file_name);\n\n\t// Figure how much room the frame offsets take up in the file.\n\t// Add 2 - one for the wrap around and one for the final end offset.\n\toffsets_size = (file_header.total_frames + 2) << 2;\n\n\t// Can the user_buffer_size handle the maximum case buffer?\n\tif ( user_buffer_size == max_buffer_size) {\n\n\t\t//\n\t\t//\tset the file buffer pointer,\n\t\t// Skip over the header information.\n\t\t// Read in the offsets.\n\t\t// Skip over the first frame.\n\t\t// Read in remaining frames.\n\t\t//\n\n\t\tsys_header->file_buffer = (char *)Add_Long_To_Pointer(delta_buffer,sys_header->largest_frame_size);\n\t\tSeek_File( fh, WSA_FILE_HEADER_SIZE, SEEK_SET);\n\t\tRead_File( fh, sys_header->file_buffer, offsets_size);\n\t\tSeek_File( fh, frame0_size + palette_adjust, SEEK_CUR);\n\t\tRead_File( fh, sys_header->file_buffer + offsets_size,\n\t\t           file_buffer_size - offsets_size);\n\n\t\t//\n\t\t// Find out if there is an ending value for the last frame.\n\t\t// If there is not, then this animation will not be able to\n\t\t// loop back to the beginning.\n\t\t//\n\t\tif (Get_Resident_Frame_Offset( sys_header->file_buffer, sys_header->total_frames + 1))\n\t\t\tanim_flags |= WSA_RESIDENT;\n\t\telse\n\t\t\tanim_flags |= WSA_LINEAR_ONLY | WSA_RESIDENT;\n\t}\n\telse {\t// buffer cannot handle max_size of buffer\n\n\t\tif(Get_File_Frame_Offset( fh, sys_header->total_frames + 1, palette_adjust))\n\t\t\tanim_flags |= WSA_FILE;\n\t\telse\n\t\t\tanim_flags |= WSA_LINEAR_ONLY | WSA_FILE;\n////\n\t\tsys_header->file_buffer = NULL;\n\t}\n\n\t// Figure where to back load frame 0 into the delta buffer.\n\tdelta_back = (char *)Add_Long_To_Pointer(delta_buffer,\n\t\t\t\t\t sys_header->largest_frame_size - frame0_size);\n\n\t// Read the first frame into the delta buffer and uncompress it.\n\t// Then close it.\n\tSeek_File( fh, WSA_FILE_HEADER_SIZE + offsets_size + palette_adjust, SEEK_SET);\n\tRead_File( fh, delta_back, frame0_size);\n\n\t// We do not use the file handle when it is in RAM.\n\tif (anim_flags & WSA_RESIDENT) {\n\t\tsys_header -> file_handle = (short) -1;\n\t \tClose_File(fh);\n\t}\n\telse {\n\t\tsys_header -> file_handle = (short)fh;\n\t}\n\n\tLCW_Uncompress(delta_back, delta_buffer, sys_header->largest_frame_size);\n\n\t// Finally set the flags,\n\tsys_header->flags = (short)anim_flags;\n\n\t// return valid handle\n\treturn( user_buffer );\n}\n\n\n/***************************************************************************\n * CLOSE_ANIMATION -- Close the animation, freeing the space if necessary. *\n *                                                                         *\n * INPUT:      void *handle to the animation data buffer                   *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   handle MUST have been returned by Open_Animation            *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/23/1991  ML : Created.                                             *\n *=========================================================================*/\nvoid __cdecl Close_Animation( void *handle )\n{\n\tSysAnimHeaderType *sys_header;\n\n\t// Assign our local system header pointer to the beginning of the handle space\n\tsys_header = (SysAnimHeaderType *) handle;\n\n\t// Close the WSA file in it was disk based.\n\tif (sys_header->flags & WSA_FILE) {\n\t\tClose_File(sys_header->file_handle);\n\t}\n\n\t// Check to see if the buffer was allocated OR the programmer provided the buffer\n\tif (handle && sys_header->flags & WSA_SYS_ALLOCATED) {\n\t\tFree(handle);\n\t}\n}\n\n/***************************************************************************\n * ANIMATE_FRAME -- Displays a frame of a given animation                  *\n *                                                                         *\n * INPUT:   void *handle to the animation.                                 *\n *          int frame_number wanted to be displayed                       *\n *          int x_pixel position of left side of animation on page        *\n *          int y_pixel position of top of animation on page              *\n *                                                                         *\n * OUTPUT:  BOOL if successfull or not.                                   *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/27/1991  SB : Created.                                             *\n *=========================================================================*/\n#pragma off (unreferenced)\nBOOL __cdecl Animate_Frame(void *handle, GraphicViewPortClass& view,\n                         int frame_number, int x_pixel, int y_pixel,\n                         WSAType flags_and_prio, void *magic_cols, void *magic)\n{\n\tSysAnimHeaderType \t*sys_header;\t\t// fix up the void pointer past in.\n\tint \t\t\t\t\t\tcurr_frame;\t\t\t// current frame we are on.\n\tint\t\t\t\t\t\ttotal_frames;\t\t// number of frames in anim.\n\tint\t\t\t\t\t\tdistance;\t\t\t// distance to desired frame.\n\tint\t\t\t\t\t\tsearch_dir;\t\t\t// direcion to search for desired frame.\n\tint\t\t\t\t\t\tsearch_frames;\t\t// How many frames to search.\n\tint\t\t\t\t\t\tloop;\t\t\t\t\t// Just a loop varible.\n\tchar\t\t\t\t\t\t*frame_buffer;\t\t// our destination.\n\tBOOL\t\t\t\t\t\tdirect_to_dest;\t// are we going directly to the destination?\n\tint\t\t\t\t\t\tdest_width;\t\t\t// the width of the destination buffer or page.\n\n\n\t// Assign local pointer to the beginning of the buffer where the system information\n\t// resides\n\tsys_header = (SysAnimHeaderType \t*)handle;\n\n\t// Get the total number of frames\n\ttotal_frames = sys_header->total_frames;\n\n\t// Are the animation handle and the frame number valid?\n\tif (!handle || (total_frames <= frame_number)) {\n\t\treturn FALSE;\n\t}\n\n\tif (view.Lock()!=TRUE) return (FALSE);\n\n\t// Decide if we are going to a page or a viewport (part of a buffer).\n\tdest_width\t= view.Get_Width() + view.Get_XAdd() + view.Get_Pitch();\n\n\t//\n\t// adjust x_pixel and y_pixel by system pixel_x and pixel_y respectively.\n\t//\n\tx_pixel += (short)sys_header->pixel_x;\n\ty_pixel += (short)sys_header->pixel_y;\n\n\t//\n\t// Check to see if we are using a buffer inside of the animation buffer or if\n\t// it is being drawn directly to the destination page or buffer.\n\t//\n\tif (sys_header->flags & WSA_TARGET_IN_BUFFER) {\n\t\t// Get a pointer to the frame in animation buffer.\n\t\tframe_buffer = (char *)Add_Long_To_Pointer(sys_header, sizeof(SysAnimHeaderType));\n\t\tdirect_to_dest = FALSE;\n\t}\n\telse {\n\t\tframe_buffer\t= (char *)view.Get_Offset();\n\t\tframe_buffer  += (y_pixel * dest_width) + x_pixel;\n\t\tdirect_to_dest\t= TRUE;\n\t}\n\t//\n\t// If current_frame is equal to tatal_frames, then no animations have taken place\n\t// so must uncompress frame 0 in delta buffer to the frame_buffer/page if it\n\t// exists.\n\t//\n\tif (sys_header->current_frame == total_frames) {\n\n\t\t// Call apply delta telling it wether to copy or to xor depending on if the\n\t\t// target is a page or a buffer.\n\n\t\tif (!(sys_header->flags & WSA_FRAME_0_ON_PAGE)) {\n\t\t\tif (direct_to_dest) {\n\n\t\t\t\t// The last parameter says weather to copy or to XOR.  If  the\n\t\t\t\t// first frame is a DELTA, then it must be XOR'd.  A TRUE is\n\t\t\t\t// copy while FALSE is XOR.\n\n\t\t\t\tApply_XOR_Delta_To_Page_Or_Viewport(frame_buffer, sys_header->delta_buffer,\n\t\t\t\t                        \tsys_header->pixel_width, dest_width, //dest_width - sys_header->pixel_width,\n\t\t\t\t\t\t\t\t\t\t\t\t\t(sys_header->flags & WSA_FRAME_0_IS_DELTA)? DO_XOR : DO_COPY);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tApply_XOR_Delta(frame_buffer, sys_header->delta_buffer);\n\t\t\t}\n\t\t}\n\t\tsys_header->current_frame = 0;\n\t}\n\n\t//\n\t// Get the current frame\n\t// If no looping aloud, are the trying to do it anyways?\n\t//\n\tcurr_frame = sys_header->current_frame;\n#if (FALSE)\n\t// This is commented out since we will let them loop even though they should\n\t// not - it will be slower.\n\tif ( (sys_header->flags & WSA_LINEAR_ONLY) && (frame_number < cur_frame) ) {\n\t\tview.Unlock();\n\t \treturn FALSE;\n\t}\n#endif\n\n\t// Get absoulte distance from our current frame to the target frame\n\tdistance = ABS(curr_frame - frame_number);\n\n\t// Assume we are searching right\n\tsearch_dir = 1;\n\n\t// Calculate the number of frames to search if we go right and wrap\n\n\tif (frame_number > curr_frame) {\n\t\tsearch_frames = total_frames - frame_number + curr_frame;\n\n\t\t// Is going right faster than going backwards?\n\t\t// Or are they trying to loop when the should not?\n\t\tif ((search_frames < distance) && !(sys_header->flags & WSA_LINEAR_ONLY)) {\n\t\t\tsearch_dir = -1;\t\t\t\t\t\t\t\t// No, so go left\n\t\t}\n\t\telse {\n\t\t\tsearch_frames = distance;\n\t\t}\n\t}\n\telse {\n\t\tsearch_frames = total_frames - curr_frame + frame_number;\n\n\t\t// Is going right faster than going backwards?\n\t\t// Or are they trying to loop when the should not?\n\t\tif ((search_frames >= distance) || (sys_header->flags & WSA_LINEAR_ONLY)) {\n\t\t\tsearch_dir = -1;\t\t\t\t\t\t\t\t// No, so go left\n\t\t\tsearch_frames = distance;\n\t\t}\n\t}\n\n\t// Take care of the case when we are searching right (possibly right)\n\n\tif (search_dir > 0) {\n\t\tfor (loop = 0; loop < search_frames; loop++) {\n\n\t\t\t// Move the logical frame number ordinally right\n\t\t\tcurr_frame += search_dir;\n\n\t\t\tApply_Delta(sys_header, curr_frame, frame_buffer, dest_width);\n\n\t\t\t// Adjust the current frame number, taking into consideration that we could\n\t\t\t// have wrapped\n\n\t\t\tif (curr_frame == total_frames) {\n\t\t\t\tcurr_frame = 0;\n\t\t\t}\n\t\t}\n\t}\n\telse {\n\t\tfor (loop = 0; loop < search_frames; loop++) {\n\n\t\t\t// If we are going backwards and we are on frame 0, the delta to get\n\t\t\t// to the last frame is the n + 1 delta (wrap delta)\n\n\t\t\tif (curr_frame == 0) {\n\t\t\t\tcurr_frame = total_frames;\n\t\t\t}\n\n\t\t\tApply_Delta(sys_header, curr_frame, frame_buffer, dest_width);\n\n\t\t\tcurr_frame += search_dir;\n\t\t}\n\t}\n\n\tsys_header->current_frame = (short)frame_number;\n\n\t// If we did this all in a hidden buffer, then copy it to the desired page or viewport.\n\tif (sys_header->flags & WSA_TARGET_IN_BUFFER) {\n#if TRUE\n\n\t\tBuffer_To_Page(x_pixel, y_pixel, sys_header->pixel_width, sys_header->pixel_height, frame_buffer, view);\n\n#else\n\t\tint\tflags = ((unsigned short)flags_and_prio & 0xFF00u) >> 12u;\n\t\tint\tpri = flags_and_prio & 0x00FF;\n\n\t\tBuffer_Bitblit_To_LogicPage(x_pixel, y_pixel, sys_header->pixel_width,\n\t\t\t\t\t\t\t\t\t\t  sys_header->pixel_height, 0, flags, frame_buffer, pri,\n\t\t\t\t\t\t\t\t\t\t  magic_cols, magic);\n#endif\n\t}\n\n\tview.Unlock();\n\treturn TRUE;\n}\n/***************************************************************************\n * ANIMATE_FRAME -- Displays a frame of a given animation                  *\n *                                                                         *\n * INPUT:   void *handle to the animation.                                 *\n *          int frame_number wanted to be displayed                       *\n *          int x_pixel position of left side of animation on page        *\n *          int y_pixel position of top of animation on page              *\n *                                                                         *\n * OUTPUT:  BOOL if successfull or not.                                   *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/27/1991  SB : Created.                                             *\n *=========================================================================*/\n#pragma argsused\n#ifdef cuts\nBOOL __cdecl Animate_Frame(void *handle, GraphicViewPortClass& view,\n                         int frame_number, int x_pixel, int y_pixel,\n                         WSAType flags_and_prio, void *magic_cols, void *magic)\n{\n\tSysAnimHeaderType \t*sys_header;\t\t// fix up the void pointer past in.\n\tint \t\t\t\t\t\tcurr_frame;\t\t\t// current frame we are on.\n\tint\t\t\t\t\t\ttotal_frames;\t\t// number of frames in anim.\n\tint\t\t\t\t\t\tdistance;\t\t\t// distance to desired frame.\n\tint\t\t\t\t\t\tsearch_dir;\t\t\t// direcion to search for desired frame.\n\tint\t\t\t\t\t\tsearch_frames;\t\t// How many frames to search.\n\tint\t\t\t\t\t\tloop;\t\t\t\t\t// Just a loop varible.\n\tchar\t\t\t\t\t\t*frame_buffer;\t\t// our destination.\n\tBOOL\t\t\t\t\t\tdirect_to_dest;\t// are we going directly to the destination?\n\tint\t\t\t\t\t\tdest_width;\t\t\t// the width of the destination buffer or page.\n\n\t// Assign local pointer to the beginning of the buffer where the system information\n\t// resides\n\tsys_header = (SysAnimHeaderType \t*)handle;\n\n\t// Get the total number of frames\n\ttotal_frames = sys_header->total_frames;\n\n\t// Are the animation handle and the frame number valid?\n\tif (!handle || (total_frames <= frame_number)) {\n\t\treturn FALSE;\n\t}\n\n\n\t// Decide if we are going to a page or a viewport (part of a buffer).\n\tdest_width\t= view.Get_Width() + view.Get_XAdd();\n\n\t//\n\t// adjust x_pixel and y_pixel by system pixel_x and pixel_y respectively.\n\t//\n\tx_pixel += (short)sys_header->pixel_x;\n\ty_pixel += (short)sys_header->pixel_y;\n\n\t//\n\t// Check to see if we are using a buffer inside of the animation buffer or if\n\t// it is being drawn directly to the destination page or buffer.\n\t//\n\tif (sys_header->flags & WSA_TARGET_IN_BUFFER) {\n\t\t// Get a pointer to the frame in animation buffer.\n\t\tframe_buffer = (char *)Add_Long_To_Pointer(sys_header, sizeof(SysAnimHeaderType));\n\t\tdirect_to_dest = FALSE;\n\t}\n\telse {\n\t\tframe_buffer\t= (char *)view.Get_Offset();\n\t\tframe_buffer  += (y_pixel * dest_width) + x_pixel;\n\t\tdirect_to_dest\t= TRUE;\n\t}\n\t//\n\t// If current_frame is equal to tatal_frames, then no animations have taken place\n\t// so must uncompress frame 0 in delta buffer to the frame_buffer/page if it\n\t// exists.\n\t//\n\tif (sys_header->current_frame == total_frames) {\n\n\t\t// Call apply delta telling it wether to copy or to xor depending on if the\n\t\t// target is a page or a buffer.\n\n\t\tif (!(sys_header->flags & WSA_FRAME_0_ON_PAGE)) {\n\t\t\tif (direct_to_dest) {\n\n\t\t\t\t// The last parameter says weather to copy or to XOR.  If  the\n\t\t\t\t// first frame is a DELTA, then it must be XOR'd.  A TRUE is\n\t\t\t\t// copy while FALSE is XOR.\n\t\t\t\tApply_XOR_Delta_To_Page_Or_Viewport(frame_buffer, sys_header->delta_buffer,\n\t\t\t\t                        \tsys_header->pixel_width, dest_width, //dest_width - sys_header->pixel_width,\n\t\t\t\t\t\t\t\t\t\t\t\t\t(sys_header->flags & WSA_FRAME_0_IS_DELTA)? DO_XOR : DO_COPY);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tApply_XOR_Delta(frame_buffer, sys_header->delta_buffer);\n\t\t\t}\n\t\t}\n\t\tsys_header->current_frame = 0;\n\t}\n\n\t//\n\t// Get the current frame\n\t// If no looping aloud, are the trying to do it anyways?\n\t//\n\tcurr_frame = sys_header->current_frame;\n#if (FALSE)\n\t// This is commented out since we will let them loop even though they should\n\t// not - it will be slower.\n\tif ( (sys_header->flags & WSA_LINEAR_ONLY) && (frame_number < cur_frame) ) {\n\t \treturn FALSE;\n\t}\n#endif\n\n\t// Get absoulte distance from our current frame to the target frame\n\tdistance = ABS(curr_frame - frame_number);\n\n\t// Assume we are searching right\n\tsearch_dir = 1;\n\n\t// Calculate the number of frames to search if we go right and wrap\n\n\tif (frame_number > curr_frame) {\n\t\tsearch_frames = total_frames - frame_number + curr_frame;\n\n\t\t// Is going right faster than going backwards?\n\t\t// Or are they trying to loop when the should not?\n\t\tif ((search_frames < distance) && !(sys_header->flags & WSA_LINEAR_ONLY)) {\n\t\t\tsearch_dir = -1;\t\t\t\t\t\t\t\t// No, so go left\n\t\t}\n\t\telse {\n\t\t\tsearch_frames = distance;\n\t\t}\n\t}\n\telse {\n\t\tsearch_frames = total_frames - curr_frame + frame_number;\n\n\t\t// Is going right faster than going backwards?\n\t\t// Or are they trying to loop when the should not?\n\t\tif ((search_frames >= distance) || (sys_header->flags & WSA_LINEAR_ONLY)) {\n\t\t\tsearch_dir = -1;\t\t\t\t\t\t\t\t// No, so go left\n\t\t\tsearch_frames = distance;\n\t\t}\n\t}\n\n\t// Take care of the case when we are searching right (possibly right)\n\n\tif (search_dir > 0) {\n\t\tfor (loop = 0; loop < search_frames; loop++) {\n\n\t\t\t// Move the logical frame number ordinally right\n\t\t\tcurr_frame += search_dir;\n\n\t\t\tApply_Delta(sys_header, curr_frame, frame_buffer, dest_width);\n\n\t\t\t// Adjust the current frame number, taking into consideration that we could\n\t\t\t// have wrapped\n\n\t\t\tif (curr_frame == total_frames) {\n\t\t\t\tcurr_frame = 0;\n\t\t\t}\n\t\t}\n\t}\n\telse {\n\t\tfor (loop = 0; loop < search_frames; loop++) {\n\n\t\t\t// If we are going backwards and we are on frame 0, the delta to get\n\t\t\t// to the last frame is the n + 1 delta (wrap delta)\n\n\t\t\tif (curr_frame == 0) {\n\t\t\t\tcurr_frame = total_frames;\n\t\t\t}\n\n\t\t\tApply_Delta(sys_header, curr_frame, frame_buffer, dest_width);\n\n\t\t\tcurr_frame += search_dir;\n\t\t}\n\t}\n\n\tsys_header->current_frame = frame_number;\n\n\t// If we did this all in a hidden buffer, then copy it to the desired page or viewport.\n\tif (sys_header->flags & WSA_TARGET_IN_BUFFER) {\n#if TRUE\n\n\t\tBuffer_To_Page(x_pixel, y_pixel, sys_header->pixel_width, sys_header->pixel_height, frame_buffer, view);\n\n#else\n\t\tint\tflags = ((unsigned short)flags_and_prio & 0xFF00u) >> 12u;\n\t\tint\tpri = flags_and_prio & 0x00FF;\n\n\t\tBuffer_Bitblit_To_LogicPage(x_pixel, y_pixel, sys_header->pixel_width,\n\t\t\t\t\t\t\t\t\t\t  sys_header->pixel_height, 0, flags, frame_buffer, pri,\n\t\t\t\t\t\t\t\t\t\t  magic_cols, magic);\n#endif\n\t}\n\n\n\treturn TRUE;\n}\n#endif\n\n\n/***************************************************************************\n * ANIMATE_FRAME_COUNT -- Return Number of frames in an animation.         *\n *                                                                         *\n * INPUT:   void *handle to the animation.                                 *\n *                                                                         *\n * OUTPUT:  int number of frames in animation.                            *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/05/1991  SB : Created.                                             *\n *=========================================================================*/\nint __cdecl Get_Animation_Frame_Count(void *handle)\n{\n\tSysAnimHeaderType *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn((short)sys_header->total_frames);\n}\n\n\n/***************************************************************************\n * GET_ANIM_X -- Gets the x from an animation                              *\n *                                                                         *\n *                                                                         *\n * INPUT:\t\tvoid * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:     int the x of the animation we are processing\t\t\t\t   *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/03/1992 DRD : Created.                                             *\n *=========================================================================*/\nint __cdecl Get_Animation_X(void const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->pixel_x);\n}\n\n/***************************************************************************\n * GET_ANIM_Y -- Gets the y from an animation                              *\n *                                                                         *\n *                                                                         *\n * INPUT:\t\tvoid * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:     int the y of the animation we are processing\t\t\t\t   *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/14/1992 PWG : Created.                                             *\n *=========================================================================*/\nint __cdecl Get_Animation_Y(void const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->pixel_y);\n}\n\n/***************************************************************************\n * GET_ANIM_WIDTH -- Gets the width from an animation                      *\n *                                                                         *\n *                                                                         *\n * INPUT:\t\tvoid * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:     int the width of the animation we are processing\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/14/1992 PWG : Created.                                             *\n *=========================================================================*/\nint __cdecl Get_Animation_Width(void const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->pixel_width);\n}\n\n/***************************************************************************\n * GET_ANIM_HEIGHT -- The height of the animation we are processing        *\n *                                                                         *\n * INPUT:\t\tvoid * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:     int the height of the animation we are processing\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/14/1992 PWG : Created.                                             *\n *=========================================================================*/\nint __cdecl Get_Animation_Height(void const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->pixel_height);\n}\n\n\n/***************************************************************************\n * GET_ANIM_PALETTE -- Returns true if the anim had an attached palette    *\n *                                                                         *\n * INPUT:\t\tvoid * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:\t\tint True if the animation has a set palette.  False if the\t*\n *\t\t\t\t\tanimation does not.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/14/1992 PWG : Created.                                             *\n *=========================================================================*/\nint __cdecl Get_Animation_Palette(void const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->flags & WSA_PALETTE_PRESENT);\n}\n\n\n/***************************************************************************\n * GET_ANIMATION_SIZE -- Return the amount of memory the animation is using*\n *                                                                         *\n *                                                                         *\n * INPUT:\t\tvoid * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:\t\tunsigned long number of byte used by animation. \t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/23/1994 SKB : Created.                                             *\n *=========================================================================*/\nunsigned long __cdecl Get_Animation_Size(void const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->anim_mem_size);\n}\n\n/* ::::::::::::::::::::::::::::  PRIVATE FUNCTIONS  :::::::::::::::::::::::::::::: */\n\n\n/***************************************************************************\n * GET_RESIDENT_FRAME_OFFSET -- Gets frame offset of animate file in RAM   *\n *                                                                         *\n * INPUT:      char *file_buffer in RAM of animation file.                 *\n *             int frame number that we need the offset of.               *\n *                                                                         *\n * OUTPUT:     int offset of frame requested.                             *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/26/1991  SB : Created.                                             *\n *=========================================================================*/\nPRIVATE unsigned long Get_Resident_Frame_Offset( char *file_buffer, int frame )\n{\n\tunsigned long frame0_size;\n\tunsigned long *lptr;\n\n\t// If there is a frame 0, the calculate its size.\n\tlptr = (unsigned long *) file_buffer;\n\n\tif (*lptr) {\n\t\tframe0_size = lptr[1] - *lptr;\n\t} else {\n\t \tframe0_size = 0;\n\t}\n\n\t// Return the offset into RAM for the frame.\n\tlptr += frame;\n\tif (*lptr)\n\t\t\treturn (*lptr - (frame0_size + WSA_FILE_HEADER_SIZE));\n\telse\n\t\treturn (0L);\n}\n\n\n/***************************************************************************\n * GET_FILE_FRAME_OFFSET -- Get offset of a delta frame from animate file. *\n *                                                                         *\n * INPUT:      int file_handle of animation file.                         *\n *             int frame number that we need the offset of.               *\n *                                                                         *\n * OUTPUT:     int offset of frame requested.                             *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/26/1991  SB : Created.                                             *\n *=========================================================================*/\nPRIVATE unsigned long Get_File_Frame_Offset( int file_handle, int frame, int palette_adjust)\n{\n\tunsigned long offset;\n\n\tSeek_File(file_handle, (frame << 2) + WSA_FILE_HEADER_SIZE, SEEK_SET);\n\n\tif (Read_File(file_handle, (char *) &offset, sizeof(unsigned long)) != sizeof(unsigned long)) {\n\t\toffset = 0L;\n\t}\n\toffset += palette_adjust;\n\treturn( offset );\n}\n\n\n/***************************************************************************\n * APPLY_DELTA -- Copies frame into delta buffer, then applies to target   *\n *                                                                         *\n * INPUT:      SysAnimHeaderType *sys_header - pointer to animation buffer.*\n *             int curr_frame - frame to put into target buffer.          *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:     BOOL - Return wether or not it worked.                      *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/26/1991  SB : Created.                                             *\n *=========================================================================*/\nPRIVATE BOOL Apply_Delta(SysAnimHeaderType *sys_header, int curr_frame, char *dest_ptr, int dest_w)\n{\n\tchar *data_ptr, *delta_back;\n\tint file_handle, palette_adjust;\n\tunsigned long frame_data_size, frame_offset;\n\n\n\tpalette_adjust = ((sys_header->flags & WSA_PALETTE_PRESENT) ? 768 : 0);\n\tdelta_back\t\t= sys_header->delta_buffer;\n\n\tif (sys_header->flags & WSA_RESIDENT) {\n\t\t// Get offset of the given frame in the resident file\n\t\t// Get the size of the frame <- (frame+1 offset) - (offset)\n\t\t// Point at the delta data\n\t\t// figure offset to load data into end of delta buffer\n\t\t// copy it into buffer\n\n\t\tframe_offset = Get_Resident_Frame_Offset(sys_header->file_buffer, curr_frame);\n\t\tframe_data_size = Get_Resident_Frame_Offset(sys_header->file_buffer, curr_frame + 1) -\tframe_offset;\n\n\t  \tdata_ptr \t= (char *)Add_Long_To_Pointer(sys_header->file_buffer, frame_offset);\n\t  \tdelta_back \t= (char *)Add_Long_To_Pointer(delta_back,\n\t  \t\t\t\t\t\t sys_header->largest_frame_size - frame_data_size);\n\n\t\tMem_Copy( data_ptr, delta_back, frame_data_size );\n\n\t} else if (sys_header -> flags & WSA_FILE) {\n\n\t\t//\tOpen up file because not file not in RAM.\n\t\t// Get offset of the given frame in the file on disk\n\t\t// Get the size of the frame <- (frame+1 offset) - (offset)\n\t\t// Return if Get_.._offset() failed.  -- need error handling????\n\t\t//\tSeek to delta data.\n\t\t// figure offset to load data into end of delta buffer\n\t\t//\tRead it into buffer -- Return if correct amount not read.-- errors??\n\n\t\tfile_handle  = sys_header->file_handle;\n\t\tSeek_File(file_handle, 0L, SEEK_SET);\n\n\t\tframe_offset = Get_File_Frame_Offset(file_handle, curr_frame, palette_adjust);\n\t\tframe_data_size = Get_File_Frame_Offset(file_handle, curr_frame + 1, palette_adjust) - frame_offset;\n\n\t\tif (!frame_offset || !frame_data_size) {\n\t\t\treturn(FALSE);\n\t\t}\n\n\t\tSeek_File(file_handle, frame_offset, SEEK_SET);\n\t\tdelta_back \t= (char *)Add_Long_To_Pointer(delta_back, sys_header->largest_frame_size - frame_data_size);\n\n\t\tif (Read_File(file_handle, delta_back, frame_data_size) != frame_data_size) {\n\t\t\treturn(FALSE);\n\t\t}\n\t}\n\n\t// Uncompress data at end of delta buffer to the beginning of delta buffer.\n\t// Find start of target buffer.\n\t// Apply the XOR delta.\n\n\tLCW_Uncompress(delta_back, sys_header->delta_buffer, sys_header->largest_frame_size);\n\n\tif (sys_header->flags & WSA_TARGET_IN_BUFFER) {\n\t\tApply_XOR_Delta(dest_ptr, sys_header->delta_buffer);\n\t}\n\telse {\n\t\tApply_XOR_Delta_To_Page_Or_Viewport(dest_ptr, sys_header->delta_buffer,\n\t\t                        sys_header->pixel_width,  dest_w, DO_XOR);\n\t}\n\n\treturn(TRUE);\n}\n\n"
  },
  {
    "path": "WIN32LIB/WSA/WSA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WSA 32bit LIbrary                        *\n *                                                                         *\n *                    File Name : WSA.H                                    *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : May 23, 1994                             *\n *                                                                         *\n *                  Last Update : May 25, 1994   [SKB]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Open_Animation -- file name and flags, system allocates buffer.       *\n *   Open_Animation -- file name, flags, palette, system allocates buffer. *\n *   Open_Animation -- file_name, graphic buffer, flags.                   *\n *   Open_Animation -- file name, bufferclass, flags, palette.             *\n *   Open_Animation -- filename, ptr, size, flags, no palette.             *\n *   Animate_Frame -- Animate a frame to a page with magic colors.         *\n *   Animate_Frame -- Animate a frame to a viewport with magic colors.     *\n *   Animate_Frame -- Animate a frame to a page.                           *\n *   Animate_Frame -- Animate a frame to a viewport.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WSA_H\n#define WSA_H\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n#ifndef GBUFFER_H\n#include \"gbuffer.h\"\n#endif\n\n//lint -strong(AJX,WSAType)\ntypedef enum {\n\tWSA_NORMAL,\t\t\t\t\t\t\t\t// Normal WSA animation\n\tWSA_GHOST\t \t= 0x1000,\t\t\t// Or'd with the above flags to get ghosting\n\tWSA_PRIORITY2 \t= 0x2000,\t\t\t// Copy using a priority (or in the priority)\n\tWSA_TRANS    \t= 0x4000,\t\t\t// Copy frame, ignoring transparent colors\n\tWSA_PRIORITY \t= 0x8000\t\t\t\t// Copy using a priority (or in the priority)\n} WSAType;\n\n\n//lint -strong(AJX,WSAOpenType)\ntypedef enum {\n\tWSA_OPEN_FROM_MEM\t\t= 0x0000,\t// Try to load entire anim into memory.\n\tWSA_OPEN_INDIRECT\t\t= 0x0000,\t// First animate to internal buffer, then copy to page/viewport.\n\tWSA_OPEN_FROM_DISK\t= 0x0001,\t// Force the animation to be disk based.\n\tWSA_OPEN_DIRECT\t\t= 0x0002,\t// Animate directly to page or viewport.\n\n\t// These next two have been added for the 32 bit library to give a better idea of what is\n\t// happening.  You may want to animate directly to the destination or indirectly to the\n\t// destination by using the animations buffer.  Indirecly is best if the dest is a seenpage\n\t// and the animation is not linear or if the destination is modified between frames.\n\tWSA_OPEN_TO_PAGE  = WSA_OPEN_DIRECT ,\n\tWSA_OPEN_TO_BUFFER= WSA_OPEN_INDIRECT ,\n\n} WSAOpenType;\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WSA.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid * __cdecl Open_Animation(char const *file_name, char *user_buffer, long user_buffer_size, WSAOpenType user_flags, unsigned char *palette=NULL);\nvoid __cdecl Close_Animation( void *handle );\nBOOL __cdecl Animate_Frame(void *handle, GraphicViewPortClass& view,\n                         int frame_number, int x_pixel=0, int y_pixel=0,\n                         WSAType flags_and_prio = WSA_NORMAL, void *magic_cols=NULL, void *magic=NULL);\nint __cdecl Get_Animation_Frame_Count(void *handle);\nBOOL __cdecl Animate_Frame(void *handle, VideoViewPortClass& view,\n                         int frame_number, int x_pixel=0, int y_pixel=0,\n                         WSAType flags_and_prio = WSA_NORMAL, void *magic_cols=NULL, void *magic=NULL);\nint __cdecl Get_Animation_Frame_Count(void *handle);\nint __cdecl Get_Animation_X(void const *handle);\nint __cdecl Get_Animation_Y(void const *handle);\nint __cdecl Get_Animation_Width(void const *handle);\nint __cdecl Get_Animation_Height(void const *handle);\nint __cdecl Get_Animation_Palette(void const *handle);\nunsigned long __cdecl Get_Animation_Size(void const *handle);\n\n\n/***************************************************************************\n * OPEN_ANIMATION -- file name, flags, palette, system allocates buffer.   *\n *                                                                         *\n *                                                                         *\n * INPUT:   char *file_name - name of file to open.                        *\n *          WSAOpenType user_flags - flags on how to open.                 *\n *          unsigned char *palette - pointer to a palette buffer to fill.          *\n *                                                                         *\n * OUTPUT:  void *pointer to animation data.  Must be used for all \t\t\t*\n *               other WSA calls.                                          *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/24/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline void  * __cdecl Open_Animation(char *file_name, WSAOpenType user_flags, unsigned char *palette=NULL)\n{\n\treturn (Open_Animation(file_name, NULL, 0L, user_flags,  palette));\n}\n\n\n/***************************************************************************\n * OPEN_ANIMATION -- file_name, bufferclass, flags. \t\t\t\t\t\t\t\t*\n *                                                                         *\n *                                                                         *\n * INPUT:   char *file_name - name of file to open.                        *\n *          GraphicBufferClass - pointer to a buffer.                      *\n *          WSAOpenType user_flags - flags on how to open.                 *\n *          unsigned char *palette - pointer to a palette buffer to fill.          *\n *                                                                         *\n * OUTPUT:  void *pointer to animation data.  Must be used for all \t\t\t*\n *               other WSA calls.                                          *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/24/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline void * __cdecl Open_Animation(char *file_name, BufferClass& buffer, WSAOpenType user_flags,  unsigned char *palette=NULL)\n{\n\treturn (Open_Animation(file_name, (char *)buffer.Get_Buffer(), buffer.Get_Size(), user_flags, palette));\n}\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LP_ASM.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n\nextern \"C\" {\nunsigned int __cdecl Apply_XOR_Delta(char *source_ptr, char *delta_ptr);\nvoid  __cdecl Apply_XOR_Delta_To_Page_Or_Viewport(void *target, void *delta, int width, int nextrow, int copy);\n}\n\n\n\n#endif // WSA_H\n\n"
  },
  {
    "path": "WIN32LIB/WSA/XORDELTA.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; **************************************************************************\n; **   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   *\n; **************************************************************************\n; *                                                                        *\n; *                 Project Name : WSA Support routines\t\t\t   *\n; *                                                                        *\n; *                    File Name : XORDELTA.ASM                            *\n; *                                                                        *\n; *                   Programmer : Scott K. Bowen\t\t\t   *\n; *                                                                        *\n; *                  Last Update :May 23, 1994   [SKB]                     *\n; *                                                                        *\n; *------------------------------------------------------------------------*\n; * Functions:                                                             *\n;*   Apply_XOR_Delta -- Apply XOR delta data to a buffer.                  *\n;*   Apply_XOR_Delta_To_Page_Or_Viewport -- Calls the copy or the XOR funti*\n;*   Copy_Delta_buffer -- Copies XOR Delta Data to a section of a page.    *\n;*   XOR_Delta_Buffer -- Xor's the data in a XOR Delta format to a page.   *\n; * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n\n\nLOCALS ??\n\n; These are used to call Apply_XOR_Delta_To_Page_Or_Viewport() to setup flags parameter.  If\n; These change, make sure and change their values in wsa.cpp.\nDO_XOR\t\tequ\t0\nDO_COPY\t\tequ\t1\nTO_VIEWPORT\tequ\t0\nTO_PAGE\t\tequ\t2\n\n;\n; Routines defined in this module\n;\n;\n; UWORD Apply_XOR_Delta(UWORD page_seg, BYTE *delta_ptr);\n; PUBLIC Apply_XOR_Delta_To_Page_Or_Viewport(UWORD page_seg, BYTE *delta_ptr, WORD width, WORD copy)\n;\n;\tPROC\tC XOR_Delta_Buffer\n;\tPROC\tC Copy_Delta_Buffer\n;\n\nGLOBAL \tC Apply_XOR_Delta:NEAR\nGLOBAL \tC Apply_XOR_Delta_To_Page_Or_Viewport:NEAR\n\n\n\n\tCODESEG\n\n\n\n;***************************************************************************\n;* APPLY_XOR_DELTA -- Apply XOR delta data to a linear buffer.             *\n;*   AN example of this in C is at the botton of the file commented out.   *\n;*                                                                         *\n;* INPUT:  BYTE *target - destination buffer.                              *\n;*         BYTE *delta - xor data to be delta uncompress.                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   05/23/1994 SKB : Created.                                             *\n;*=========================================================================*\nPROC\tApply_XOR_Delta C near\n\tUSES \tebx,ecx,edx,edi,esi\n\tARG\ttarget:DWORD \t\t; pointers.\n\tARG\tdelta:DWORD\t\t; pointers.\n\n\t; Optimized for 486/pentium by rearanging instructions.\n\tmov\tedi,[target]\t\t; get our pointers into offset registers.\n\tmov\tesi,[delta]\n\n\tcld\t\t\t\t; make sure we go forward\n\txor\tecx,ecx\t\t\t; use cx for loop\n\n??top_loop:\n\txor\teax,eax\t\t\t; clear out eax.\n\tmov\tal,[esi]\t\t; get delta source byte\n\tinc\tesi\n\n\ttest\tal,al\t\t\t; check for a SHORTDUMP ; check al incase of sign value.\n\tje\t??short_run\n\tjs\t??check_others\n\n;\n; SHORTDUMP\n;\n\tmov\tecx,eax\t\t\t; stick count in cx\n\n??dump_loop:\n\tmov\tal,[esi]\t\t;get delta XOR byte\n\txor\t[edi],al\t\t; xor that byte on the dest\n\tinc\tesi\n\tinc\tedi\n\tdec\tecx\n\tjnz\t??dump_loop\n\tjmp\t??top_loop\n\n;\n; SHORTRUN\n;\n\n??short_run:\n\tmov\tcl,[esi]\t\t; get count\n\tinc\tesi\t\t\t; inc delta source\n\n??do_run:\n\tmov\tal,[esi]\t\t; get XOR byte\n\tinc\tesi\n\n??run_loop:\n\txor\t[edi],al\t\t; xor that byte.\n\n\tinc\tedi\t\t\t; go to next dest pixel\n\tdec\tecx\t\t\t; one less to go.\n\tjnz\t??run_loop\n\tjmp\t??top_loop\n\n;\n; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP\n;\n\n??check_others:\n\tsub\teax,080h\t\t; opcode -= 0x80\n\tjnz\t??do_skip\t\t; if zero then get next word, otherwise use remainder.\n\n\tmov\tax,[esi]\n\tlea\tesi,[esi+2]\t\t; get word code in ax\n\ttest\tax,ax\t\t\t; set flags. (not 32bit register so neg flag works)\n\tjle\t??not_long_skip\n\n;\n; SHORTSKIP AND LONGSKIP\n;\n??do_skip:\n\tadd\tedi,eax\t\t\t; do the skip.\n\tjmp\t??top_loop\n\n\n??not_long_skip:\n\tjz\t??stop\t\t\t; long count of zero means stop\n\tsub\teax,08000h     \t\t; opcode -= 0x8000\n\ttest\teax,04000h\t\t; is it a LONGRUN (code & 0x4000)?\n\tje\t??long_dump\n\n;\n; LONGRUN\n;\n\tsub\teax,04000h\t\t; opcode -= 0x4000\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??do_run\t\t; jump to run code.\n\n\n;\n; LONGDUMP\n;\n\n??long_dump:\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??dump_loop\t\t; go to the dump loop.\n\n??stop:\n\n\tret\n\n\tENDP\tApply_XOR_Delta\n\n\n;----------------------------------------------------------------------------\n\n\n;***************************************************************************\n;* APPLY_XOR_DELTA_To_Page_Or_Viewport -- Calls the copy or the XOR funtion.           *\n;*                                                                         *\n;*\t\t\t\t\t\t\t\t\t   *\n;* \tThis funtion is call to either xor or copy XOR_Delta data onto a   *\n;*\tpage instead of a buffer.  The routine will set up the registers   *\n;*\tneed for the actual routines that will perform the copy or xor.\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tThe registers are setup as follows :\t\t\t\t   *\n;*\t\tes:edi - destination segment:offset onto page.\t\t   *\n;*\t\tds:esi - source buffer segment:offset of delta data.\t   *\n;*\t\tdx,cx,ax - are all zeroed out before entry.\t\t   *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/09/1992  SB : Created.                                             *\n;*=========================================================================*\n\n;PUBLIC Apply_XOR_Delta_To_Page_Or_Viewport(UWORD page_seg, BYTE *delta_ptr, WORD width, WORD flags, WORD descriptor)\nPROC\tApply_XOR_Delta_To_Page_Or_Viewport C near\n\tUSES \tebx,ecx,edx,edi,esi\n\tARG\ttarget:DWORD\t\t; pointer to the destination buffer.\n\tARG\tdelta:DWORD\t\t; pointer to the delta buffer.\n\tARG\twidth:DWORD\t\t; width of animation.\n\tARG\tnextrow:DWORD\t\t; Page/Buffer width - anim width.\n\tARG\tcopy:DWORD\t\t; should it be copied or xor'd?\n\n\n\tmov\tedi,[target]\t\t; Get the target pointer.\n\tmov\tesi,[delta]\t\t; Get the destination pointer.\n\n\txor\teax,eax\t\t\t; clear eax, later put them into ecx and edx.\n\n\tcld\t\t\t\t; make sure we go forward\n\n\tmov\tebx,[nextrow]\t\t; get the amount to add to get to next row from end.  push it later...\n\n\tmov\tecx,eax\t\t\t; use cx for loop\n\tmov\tedx,eax\t\t\t; use dx to count the relative column.\n\n\tpush\tebx\t\t\t; push nextrow onto the stack for Copy/XOR_Delta_Buffer.\n\tmov\tebx,[width]\t\t; bx will hold the max column for speed compares\n\n; At this point, all the registers have been set up.  Now call the correct function\n; to either copy or xor the data.\n\n\tcmp\t[copy],DO_XOR\t\t; Do we want to copy or XOR\n\tje\t??xorfunct\t\t; Jump to XOR if not copy\n\tcall\tCopy_Delta_Buffer\t; Call the function to copy the delta buffer.\n\tjmp\t??didcopy\t\t; jump past XOR\n??xorfunct:\n\tcall\tXOR_Delta_Buffer\t; Call funtion to XOR the deltat buffer.\n??didcopy:\n\tpop\tebx\t\t\t; remove the push done to pass a value.\n\n\tret\n\n\tENDP\tApply_XOR_Delta_To_Page_Or_Viewport\n;----------------------------------------------------------------------------\n\n\n;***************************************************************************\n;* XOR_DELTA_BUFFER -- Xor's the data in a XOR Delta format to a page.     *\n;*\tThis will only work right if the page has the previous data on it. *\n;*\tThis function should only be called by XOR_Delta_Buffer_To_Page_Or_Viewport.   *\n;*      The registers must be setup as follows :                           *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*\tes:edi - destination segment:offset onto page.\t\t \t   *\n;*\tds:esi - source buffer segment:offset of delta data.\t \t   *\n;*\tedx,ecx,eax - are all zeroed out before entry.\t\t \t   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/09/1992  SB : Created.                                             *\n;*=========================================================================*\n\nPROC\tXOR_Delta_Buffer C near\n\tARG\tnextrow:DWORD\n\n??top_loop:\n\txor\teax,eax\t\t\t; clear out eax.\n\tmov\tal,[esi]\t\t; get delta source byte\n\tinc\tesi\n\n\ttest\tal,al\t\t\t; check for a SHORTDUMP ; check al incase of sign value.\n\tje\t??short_run\n\tjs\t??check_others\n\n;\n; SHORTDUMP\n;\n\tmov\tecx,eax\t\t\t; stick count in cx\n\n??dump_loop:\n\tmov\tal,[esi]\t\t; get delta XOR byte\n\txor\t[edi],al\t\t; xor that byte on the dest\n\tinc\tesi\n\tinc\tedx\t\t\t; increment our count on current column\n\tinc\tedi\n\tcmp\tedx,ebx\t\t\t; are we at the final column\n\tjne\t??end_col1\t\t; if not the jmp over the code\n\n\tsub\tedi,edx\t\t\t; get our column back to the beginning.\n\txor\tedx,edx\t\t\t; zero out our column counter\n\tadd\tedi,[nextrow]\t\t; jump to start of next row\n??end_col1:\n\n\tdec\tecx\n\tjnz\t??dump_loop\n\tjmp\t??top_loop\n\n;\n; SHORTRUN\n;\n\n??short_run:\n\tmov\tcl,[esi]\t\t; get count\n\tinc\tesi\t\t\t; inc delta source\n\n??do_run:\n\tmov\tal,[esi]\t\t; get XOR byte\n\tinc\tesi\n\n??run_loop:\n\txor\t[edi],al\t\t; xor that byte.\n\n\tinc\tedx\t\t\t; increment our count on current column\n\tinc\tedi\t\t\t; go to next dest pixel\n\tcmp\tedx,ebx\t\t\t; are we at the final column\n\tjne\t??end_col2\t\t; if not the jmp over the code\n\n\tsub\tedi,ebx\t\t\t; get our column back to the beginning.\n\txor\tedx,edx\t\t\t; zero out our column counter\n\tadd\tedi,[nextrow]\t\t; jump to start of next row\n??end_col2:\n\n\n\tdec\tecx\n\tjnz\t??run_loop\n\tjmp\t??top_loop\n\n;\n; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP\n;\n\n??check_others:\n\tsub\teax,080h\t\t; opcode -= 0x80\n\tjnz\t??do_skip\t\t; if zero then get next word, otherwise use remainder.\n\n\tmov\tax,[esi]\t\t; get word code in ax\n\tlea\tesi,[esi+2]\n\ttest\tax,ax\t\t\t; set flags. (not 32bit register so neg flag works)\n\tjle\t??not_long_skip\n\n;\n; SHORTSKIP AND LONGSKIP\n;\n??do_skip:\n\tsub\tedi,edx\t\t\t; go back to beginning or row.\n\tadd\tedx,eax\t\t\t; incriment our count on current row\n??recheck3:\n\tcmp\tedx,ebx\t\t\t; are we past the end of the row\n\tjb\t??end_col3  \t\t; if not the jmp over the code\n\n\tsub\tedx,ebx\t\t\t; Subtract width from the col counter\n\tadd\tedi,[nextrow]  \t\t; jump to start of next row\n\tjmp\t??recheck3\t\t; jump up to see if we are at the right row\n??end_col3:\n\tadd\tedi,edx\t\t\t; get to correct position in row.\n\tjmp\t??top_loop\n\n\n??not_long_skip:\n\tjz\t??stop\t\t\t; long count of zero means stop\n\tsub\teax,08000h     \t\t; opcode -= 0x8000\n\ttest\teax,04000h\t\t; is it a LONGRUN (code & 0x4000)?\n\tje\t??long_dump\n\n;\n; LONGRUN\n;\n\tsub\teax,04000h\t\t; opcode -= 0x4000\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??do_run\t\t; jump to run code.\n\n\n;\n; LONGDUMP\n;\n\n??long_dump:\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??dump_loop\t\t; go to the dump loop.\n\n??stop:\n\n\tret\n\n\n\tENDP\tXOR_Delta_Buffer\n\n;----------------------------------------------------------------------------\n\n\n;***************************************************************************\n;* COPY_DELTA_BUFFER -- Copies XOR Delta Data to a section of a page.      *\n;*\tThis function should only be called by XOR_Delta_Buffer_To_Page_Or_Viewport.   *\n;*      The registers must be setup as follows :                           *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*\tes:edi - destination segment:offset onto page.\t\t \t   *\n;*\tds:esi - source buffer segment:offset of delta data.\t \t   *\n;*\tdx,cx,ax - are all zeroed out before entry.\t\t \t   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/09/1992  SB : Created.                                             *\n;*=========================================================================*\nPROC\tCopy_Delta_Buffer C near\n\tARG\tnextrow:DWORD\n\n??top_loop:\n\txor\teax,eax\t\t\t; clear out eax.\n\tmov\tal,[esi]\t\t; get delta source byte\n\tinc\tesi\n\n\ttest\tal,al\t\t\t; check for a SHORTDUMP ; check al incase of sign value.\n\tje\t??short_run\n\tjs\t??check_others\n\n;\n; SHORTDUMP\n;\n\tmov\tecx,eax\t\t\t; stick count in cx\n\n??dump_loop:\n\tmov\tal,[esi]\t\t; get delta XOR byte\n\n\tmov\t[edi],al\t\t; store that byte on the dest\n\n\tinc\tedx\t\t\t; increment our count on current column\n\tinc\tesi\n\tinc\tedi\n\tcmp\tedx,ebx\t\t\t; are we at the final column\n\tjne\t??end_col1\t\t; if not the jmp over the code\n\n\tsub\tedi,edx\t\t\t; get our column back to the beginning.\n\txor\tedx,edx\t\t\t; zero out our column counter\n\tadd\tedi,[nextrow]\t\t; jump to start of next row\n??end_col1:\n\n\tdec\tecx\n\tjnz\t??dump_loop\n\tjmp\t??top_loop\n\n;\n; SHORTRUN\n;\n\n??short_run:\n\tmov\tcl,[esi]\t\t; get count\n\tinc\tesi\t\t\t; inc delta source\n\n??do_run:\n\tmov\tal,[esi]\t\t; get XOR byte\n\tinc\tesi\n\n??run_loop:\n\tmov\t[edi],al\t\t; store the byte (instead of XOR against current color)\n\n\tinc\tedx\t\t\t; increment our count on current column\n\tinc\tedi\t\t\t; go to next dest pixel\n\tcmp\tedx,ebx\t\t\t; are we at the final column\n\tjne\t??end_col2\t\t; if not the jmp over the code\n\n\tsub\tedi,ebx\t\t\t; get our column back to the beginning.\n\txor\tedx,edx\t\t\t; zero out our column counter\n\tadd\tedi,[nextrow]\t\t; jump to start of next row\n??end_col2:\n\n\n\tdec\tecx\n\tjnz\t??run_loop\n\tjmp\t??top_loop\n\n;\n; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP\n;\n\n??check_others:\n\tsub\teax,080h\t\t; opcode -= 0x80\n\tjnz\t??do_skip\t\t; if zero then get next word, otherwise use remainder.\n\n\tmov\tax,[esi]\t\t; get word code in ax\n\tlea\tesi,[esi+2]\n\ttest\tax,ax\t\t\t; set flags. (not 32bit register so neg flag works)\n\tjle\t??not_long_skip\n\n;\n; SHORTSKIP AND LONGSKIP\n;\n??do_skip:\n\tsub\tedi,edx\t\t\t; go back to beginning or row.\n\tadd\tedx,eax\t\t\t; incriment our count on current row\n??recheck3:\n\tcmp\tedx,ebx\t\t\t; are we past the end of the row\n\tjb\t??end_col3  \t\t; if not the jmp over the code\n\n\tsub\tedx,ebx\t\t\t; Subtract width from the col counter\n\tadd\tedi,[nextrow]  \t\t; jump to start of next row\n\tjmp\t??recheck3\t\t; jump up to see if we are at the right row\n??end_col3:\n\tadd\tedi,edx\t\t\t; get to correct position in row.\n\tjmp\t??top_loop\n\n\n??not_long_skip:\n\tjz\t??stop\t\t\t; long count of zero means stop\n\tsub\teax,08000h     \t\t; opcode -= 0x8000\n\ttest\teax,04000h\t\t; is it a LONGRUN (code & 0x4000)?\n\tje\t??long_dump\n\n;\n; LONGRUN\n;\n\tsub\teax,04000h\t\t; opcode -= 0x4000\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??do_run\t\t; jump to run code.\n\n\n;\n; LONGDUMP\n;\n\n??long_dump:\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??dump_loop\t\t; go to the dump loop.\n\n??stop:\n\n\tret\n\n\tENDP\tCopy_Delta_Buffer\n\n;----------------------------------------------------------------------------\n\n\tEND\n\n\n;----------------------------------------------------------------------------\n;\n;PUBLIC UWORD Apply_XOR_Delta(UWORD page_seg, BYTE *delta_ptr)\n;{\n;\n;\tregister UWORD loop;\n;\tBYTE opcode, xor_byte;\n;\tUWORD bytes_to_uncompress = 64000U;\n;\n;\n;\t/* Make our buffer pointer */\n;\n;\tto    = MK_FP(page_seg, 0);\n;\tdelta = Normalize_Pointer(delta_ptr);\n;\n;\n;\twhile (bytes_to_uncompress) {\n;\n;\t\topcode = *delta++;\n;\n;\n;\t\t/* Check for SHORTDUMP */\n;\n;\t\tif (opcode > 0) {\n;\n;\n;\t\t\tbytes_to_uncompress -= opcode;\n;\n;\t\t\tfor (loop = 0; loop < opcode; loop++) {\n;\t\t\t\txor_byte = *delta++;\n;\t\t\t\t*to++ ^= xor_byte;\n;\t\t\t}\n;\t\t\tcontinue;\n;\t\t}\n;\n;\t\t/* Check for SHORTRUN */\n;\n;\t\tif (opcode == 0) {\n;\n;\t\t\tword_count = *delta++;\n;\t\t\txor_byte   = *delta++;\n;\n;\t\t\tbytes_to_uncompress -= word_count;\n;\n;\t\t\tfor (loop = 0; loop < word_count; loop++) {\n;\t\t\t\t*to++ ^= xor_byte;\n;\t\t\t}\n;\t\t\tcontinue;\n;\t\t}\n;\n;\t\t/* By now, we know it must be a LONGDUMP, SHORTSKIP, or LONGSKIP */\n;\n;\t\topcode -= 0x80;\n;\n;\n;\t\t/* Is it a SHORTSKIP? */\n;\n;\t\tif (opcode != 0) {\n;\n;\t\t\tto += opcode;\n;\t\t\tbytes_to_uncompress -= (WORD) opcode;\n;\t\t\tcontinue;\n;\t\t}\n;\n;\n;\t\tword_count = *((UWORD *) delta)++;\n;\n;\t\t/* Is it a LONGSKIP? */\n;\n;\t\tif ((WORD) word_count > 0) {\n;\n;\t\t\tto += word_count;\n;\t\t\tbytes_to_uncompress -= (WORD) word_count;\n;\t\t\tcontinue;\n;\t\t}\n;\n;\n;\t\tword_count -= 0x8000;\n;\n;\t\t/* Is it a LONGRUN? */\n;\n;\t\tif (word_count & 0x4000) {\n;\n;\t\t\tword_count -= 0x4000;\n;\n;\t\t\tbytes_to_uncompress -= word_count;\n;\n;\t\t\txor_byte = *delta++;\n;\n;\t\t\tfor (loop = 0; loop < word_count; loop++) {\n;\t\t\t\t*to++ ^= xor_byte;\n;\t\t\t}\n;\t\t\tcontinue;\n;\t\t}\n;\n;\n;\t\t/* It must be a LONGDUMP */\n;\n;\t\tbytes_to_uncompress -= word_count;\n;\n;\t\tfor (loop = 0; loop < word_count; loop++) {\n;\t\t\txor_byte = *delta++;\n;\t\t\t*to++ ^= xor_byte;\n;\t\t}\n;\t}\n;\n;\n;\treturn(64000U);\n;}\n;\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/WW_WIN/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = ww_win\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\twindows.obj\t&\n\twinhide.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\\$^*.cpp\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include\n\t copy *.inc $(%WIN32LIB)\\include\n\t copy *.cpp $(%WIN32LIB)\\srcdebug\n\t copy *.asm $(%WIN32LIB)\\srcdebug\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\tmkdir run\n\tcd run\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\run\\vcs.cfg\n\tupdate\n\tcd..\n\tmkdir art\n\tcd art\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\art\\vcs.cfg\n\tupdate\n\tcd..\n\twmake\n\tcd ..\n\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/WW_WIN/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WWFLAT path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n.AUTODEPEND\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef COMPILER\n!error COMPILER Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = ww_win\nPROJ_DIR    = $(WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(WIN32LIB)\\lib\n\n!include $(WIN32LIB)\\\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS =\t\\\n\t\t\t\twindows.obj\t\t\\\n\t\t\t\twinhide.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.path.asm\t=\t$(PROJ_DIR)\n.path.c\t\t=\t$(PROJ_DIR)\n.path.cpp\t=\t$(PROJ_DIR)\n.path.h\t\t=\t$(PROJ_DIR)\n.path.obj\t=\t$(PROJ_DIR)\n.path.lib\t=\t$(WIN32LIB)\\lib\n.path.exe\t=\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t\t= bcc32\nCPP_CMD\t  \t= bcc32\nLIB_CMD\t  \t= tlib\nLINK_CMD  \t= tlink32\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(WIN32LIB)\\LIB;$(COMPILER)\\LIB\nINCLUDEPATH\t= $(WIN32LIB)\\INCLUDE;$(COMPILER)\\INCLUDE\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib \n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\\\$(PROJ_NAME).lib: $(OBJECTS) \n\t copy *.h   $(WIN32LIB)\\\\include \n\t copy *.inc $(WIN32LIB)\\\\include \n\t copy *.cpp $(WIN32LIB)\\\\srcdebug \n\t copy *.asm $(WIN32LIB)\\\\srcdebug \n\t$(LIB_CMD) $< $(LIB_CFG)  @&&| \n +-windows.obj\t\t\\\n+-winhide.obj\n|\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(WWVCS)\\\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n"
  },
  {
    "path": "WIN32LIB/WW_WIN/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   \t\t*\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           \t*\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n#* WIN32LIB\t\t= your root WIN32LIB path\t\t\t\t\t   \t\t\t\t\t\t\t*\n#* WIN32VCS\t\t= root directory for wwlib version control archive\t   \t\t*\n#* COMPILER\t\t= your Watcom installation path\t\t\t\t   \t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_NAME\t= name of the library you're building\t\t\t   \t\t\t\t*\n#* OBJECTS\t\t= list of objects in your library\t\t\t   \t\t\t\t\t*\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t\t*\n#* PROJ_DIR\t\t= full pathname of your working directory\t\t   \t\t\t\t*\n#* .path.xxx\t= full pathname where various file types live\t\t   \t\t*\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS  \n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = ww_win\nPROJ_DIR    = $(%WIN32LIB)\\$(PROJ_NAME)\nLIB_DIR     = $(%WIN32LIB)\\lib\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\twindows.obj\t&\n\twinhide.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WIN32LIB\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WIN32LIB)\\include \n\t copy *.inc $(%WIN32LIB)\\include \n\t copy *.cpp $(%WIN32LIB)\\srcdebug \n\t copy *.asm $(%WIN32LIB)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\tmkdir run\n\tcd run\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\run\\vcs.cfg\n\tupdate\n\tcd..\n\tmkdir art\n\tcd art\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\art\\vcs.cfg\n\tupdate\n\tcd..\n\twmake \n\tcd ..\n\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/WW_WIN/OLD/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : jan 24, 1995                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = windows\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\twindows.obj\t&\n\twinhide.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\tmkdir run\n\tcd run\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\run\\vcs.cfg\n\tupdate\n\tcd..\n\tmkdir art\n\tcd art\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\art\\vcs.cfg\n\tupdate\n\tcd..\n\twmake \n\tcd ..\n\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/WW_WIN/OLD/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : jan 24, 1995                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = windows\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\twindows.obj\t&\n\twinhide.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\tmkdir run\n\tcd run\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\run\\vcs.cfg\n\tupdate\n\tcd..\n\tmkdir art\n\tcd art\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\art\\vcs.cfg\n\tupdate\n\tcd..\n\twmake \n\tcd ..\n\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/WW_WIN/OLD/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : jan 24, 1995                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = windows\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\twindows.obj\t&\n\twinhide.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\tmkdir run\n\tcd run\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\run\\vcs.cfg\n\tupdate\n\tcd..\n\tmkdir art\n\tcd art\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\art\\vcs.cfg\n\tupdate\n\tcd..\n\twmake \n\tcd ..\n\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/WW_WIN/OLD/WINDOWS.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./windows.c 1.12 1994/05/20 15:35:25 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : WINDOWS.C                                *\n *                                                                         *\n *                   Programmer : Everyone                                 *\n *                                                                         *\n *                  Last Update : February 3, 1992   [DRD]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Change_New_Window -- Combined Change_Window and New_Window.           *\n *   Change_Window -- Changes the 'current' window in the system.          *\n *   Fetch_Char -- Gets one undipthonged char from input.                  *\n *   Flush_Line -- Outputs the accumulate text line to screen.             *\n *   In_Char -- Stores (un-dipped) character(s) from input to buffer.      *\n *   New_Window -- Clears the current window to the background color.      *\n *   Set_More_Off -- Turns the 'more' prompting off.                       *\n *   Set_More_On -- Turns the 'more' prompting on.                         *\n *   Set_More_Prompt -- Adjusts the more prompt text for default routine   *\n *   Standard_More_Prompt -- Default more prompt code for Window_Print     *\n *   Window_Int_Print -- Prints an integer to the window.                  *\n *   Window_Print -- Displays and wraps text into a window.                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <ctype.h>\n#include <stdlib.h>\n#include <string.h>\n#include\t<stdio.h>\n#include\t<stdarg.h>\n#include <wwstd.h>\n#include \"windows.h\"\n#include <keyboard.h>\n#include\t<font.h>\n#include <dipthong.h>\n\nPRIVATE void Scroll_Window(void);\nPRIVATE void Flush_Line(void);\nPRIVATE void In_Char(char *str);\nPRIVATE char Fetch_Char(void);\n\n\nPRIVATE int ScrollCounter = 0;\t//\tCount of the lines displayed before a pause.\nPRIVATE char Line[84];\t// Staging line buffer.\nPRIVATE int Pos;\t\t\t// Char Position of next free character.\nPRIVATE int PPos;\t\t// Pixel position of next free character.\nPRIVATE int WPos;\t\t// Char position in window.\nPRIVATE char *MainSource;\nPRIVATE char *AltSource;\nPRIVATE char Char[2];\nPRIVATE char Stack;\nPRIVATE char WordWrapFlag = FALSE;\t// flag for a word wrap.\n\nPRIVATE int MoreSpace = 7;\nPRIVATE int MoreFColor = 0;\nPRIVATE int MoreBColor = 0;\n\n\nint WindowColumns=40;\nint WindowLines=25;\nint WindowWidth=40;\nunsigned int WinB=0;\nunsigned int WinC=1;\nunsigned int WinX=0;\nunsigned int WinY=0;\nunsigned int WinCx=0;\nunsigned int WinCy=0;\nunsigned int WinH=25;\nunsigned int WinW=40;\nunsigned int Window=0;\n\nint MoreOn = TRUE;\nchar *TXT_MoreText = \"--More--\";\nvoid (*Window_More_Ptr)(BYTE const *,int,int,int) = Standard_More_Prompt;\n\nextern GraphicBufferClass *LogicPage;\n/***************************************************************************\n * STANDARD_MORE_PROMPT -- Default more prompt code for Window_Print       *\n *                                                                         *\n *    This is the standard \"<more>\" prompting code that is used by         *\n *    Window_Print when a page is full of text and a pause is desired      *\n *    before the next page of text is printed.  This function is called    *\n *    through the Window_More_Ptr global.                                  *\n *                                                                         *\n * INPUT:   prompt   -- Pointer to ASCII text that will be window printed  *\n *                      at the right margin.                               *\n *                                                                         *\n *          space    -- The number of spaces to allow for the 'more' text. *\n *                                                                         *\n *          fcolor   -- The foreground color to use for the 'more' text.   *\n *                                                                         *\n *          bcolor   -- The background oclor to use for the 'more' text.   *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/29/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Standard_More_Prompt(char const *prompt, int space, int fcolor, int bcolor)\n{\n\tint\tx, y, moresize;\n\t\n\tmoresize = (space - 1) * (FontWidth+FontXSpacing);\n\tx = ((WinX+WinW) << 3) - moresize;\n\t//y = WinY + ((WinH/FontHeight)-1)*FontHeight;\n\ty = WinY + (WinCy-1) * (FontHeight+FontYSpacing);\n\n\t// Default \"more\" prompter.\n\tLogicPage->Print(prompt, x, y, fcolor ? fcolor : WindowList[Window][WINDOWBCOL], bcolor ? bcolor : WindowList[Window][WINDOWFCOL]);\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Show_Mouse();\n//BG\t}\n\n\tClear_KeyBuffer();\n\tGet_Key();\n\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Hide_Mouse(Window);\n//BG\t}\n\n\t// Erase the more prompt prompt.\n\t//\tText_Print(prompt, x, y, WinB, WinB);\n\tLogicPage->Fill_Rect(x, y, x + moresize - 1, y + (FontHeight+FontYSpacing) - 1, WinB);\n}\n\n\n/***************************************************************************\n * SET_MORE_PROMPT -- Adjusts the more prompt text for default routine     *\n *                                                                         *\n *    Use this routine to control the text of the \"<MORE>\" prompt that     *\n *    the default more prompt routine uses.  This can be useful for        *\n *    foreign language translations.                                       *\n *                                                                         *\n * INPUT:   prompt   -- Pointer to ASCII text that will be window printed  *\n *                      at the right margin.                               *\n *                                                                         *\n *          space    -- The number of spaces to allow for the 'more' text. *\n *                                                                         *\n *          fcolor   -- The foreground color to use for the 'more' text.   *\n *                                                                         *\n *          bcolor   -- The background color to use for the 'more' text.   *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/29/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Set_More_Prompt(char const *prompt, int space, int fcolor, int bcolor)\n{\n\tif (prompt) {\n\t\tTXT_MoreText = (char*)prompt;\n\t\tMoreSpace = space;\n\t\tMoreFColor = fcolor;\n\t\tMoreBColor = bcolor;\n\t}\n\telse {\n\t\tTXT_MoreText = \"<MORE>\";\n\t\tMoreSpace = 7;\n\t\tMoreFColor = MoreBColor = 0;\n\t}\n}\n\n\n/***************************************************************************\n * SET_MORE_ON -- Turns the 'more' prompting on.                           *\n *                                                                         *\n *    Use this routine to turn on the 'more' prompting that Window_Print   *\n *    does.  If you have a custom more function pointer, then that         *\n *    routine will be called, otherwise the library default 'more' prompt  *\n *    will be utilized.                                                    *\n *                                                                         *\n * INPUT:      none                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Set_More_On(void)\n{\n\tMoreOn = TRUE;\n\tScrollCounter = 0;\n}\n\n\n/***************************************************************************\n * SET_MORE_OFF -- Turns the 'more' prompting off.                         *\n *                                                                         *\n *    This routine will turn the 'more' prompting that Window_Print does   *\n *    off.                                                                 *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Set_More_Off(void)\n{\n\tMoreOn = FALSE;\n}\n\n\n/***************************************************************************\n * CHANGE_WINDOW -- Changes the 'current' window in the system.            *\n *                                                                         *\n *    Use this routine to change the 'current' window.  The current window *\n *    is used in Window_Print and some other graphic output routines.      *\n *                                                                         *\n * INPUT:   windnum  -- The window number to change to.                    *\n *                                                                         *\n * OUTPUT:  Returns with the previously current window.                    *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nint Change_Window(int windnum)\n{\n\tint\toldwindow;\n\tint\t*data;\n\n\toldwindow = Window;\n\tWindow = windnum;\n\tdata = &WindowList[windnum][0];\n\n\tWinX = *data++;\n\tWinY = *data++;\n\tWinW = *data++;\n\tWinH = *data++;\n\tWinC = *data++;\n\tWinB = *data++;\n\tWinCx = *data++;\n\tWinCy = *data++;\n\tScrollCounter = 0;\n\tWPos = WinCx / (FontWidth+FontXSpacing);\n\tWindowLines = (WinH-FontYSpacing) / (FontHeight+FontYSpacing);\n\tWindowWidth = WinW << 3;\n\tWindowColumns = WindowWidth / (FontWidth+FontXSpacing);\n\treturn (oldwindow);\n}\n\n\n/***************************************************************************\n * CHANGE_NEW_WINDOW -- Combined Change_Window and New_Window.             *\n *                                                                         *\n *    This is a combo-routine.  It merely combines the Change_Window       *\n *    with the New_Window routines.  It will save some (small) code if     *\n *    you use this routine instead of the two function calls.              *\n *                                                                         *\n * INPUT:   window   -- Window number to change to and clear.              *\n *                                                                         *\n * OUTPUT:  Returns with the previously current window.                    *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nint Change_New_Window(int windnum)\n{\n\tint\toldwindow;\n\n\toldwindow = Change_Window(windnum);\n\tNew_Window();\n\treturn(oldwindow);\n}\n\n\n/***************************************************************************\n * NEW_WINDOW -- Clears the current window to the background color.        *\n *                                                                         *\n *    This routine clears the current window to the background color.  It  *\n *    is used in preparation to Window_Print because it ensures a clean    *\n *    'slate' for the text.                                                *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid New_Window(void)\n{\n\tint\tx,y,w,h;\n\n\tx = WinX << 3;\n\ty = WinY;\n\tw = (WinX + WinW) << 3;\n\th = WinY + WinH;\n\n\tLogicPage->Fill_Rect(x, y, w - 1, h - 1, WinB);\n\n\tWinCx = WPos = 0;\n\tWinCy = 0;\n\tScrollCounter = 0;\n}\n\n\n/***************************************************************************\n * WINDOW_INT_PRINT -- Prints an integer to the window.                    *\n *                                                                         *\n *    Use this routine to print an integer to the window.  This routine    *\n *    as all other Window printing routines will handle word wrap.         *\n *                                                                         *\n * INPUT:   num   -- The integer to convert to ASCII and print.            *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Window_Int_Print(int num)\n{\n\tWindow_Print(\"%d\", num);\n}\n\t\t\t\n\n/***************************************************************************\n * WINDOW_PRINT -- Displays and wraps text into a window.                  *\n *                                                                         *\n *    This is the general purpos text output routine that will handle      *\n *    word wrap within a window.  It is useful for displaying arbitrary    *\n *    text.  This routine will handle dipthonged text and as such it       *\n *    can be quite useful in saving memory.                                *\n *                                                                         *\n * INPUT:   string   -- String to print.  This can be of ANY length and    *\n *                      can even contain some formatting codes.  The       *\n *                      codes supported are:                               *\n *                                                                         *\n *             KA_SETX        Forces the cursor X position to the value    *\n *                            specified.                                   *\n *                                                                         *\n *             KA_SETY        Forces the cursor Y position to the value    *\n *                            specified.                                   *\n *                                                                         *\n *             KA_MORE        Causes an immediate \"<MORE>\" prompt          *\n *                            regardless of the scroll situation.          *\n *                                                                         *\n *             KA_RETURN      Breaks line and continues output at the      *\n *                            left edge of following line.                 *\n *                                                                         *\n *                                                                         *\n *             KA_FORMFEED    Clears the window and continues printing at  *\n *                            the upper left corner.                       *\n *                                                                         *\n *             KA_SETBKGDCOL  Set the background color with the color      *\n *                            specified by the following byte.             *\n *                                                                         *\n *                                                                         *\n *             KA_SETFORECOL  Set the foreground color with the color      *\n *                            specified by the following byte.             *\n *                                                                         *\n *             KA_TAB         Move the cursor over to the next tabstop.    *\n *                            Tabstops are set every 8 columns.            *\n *                                                                         *\n *             KA_SPCTAB      Insert spaces until the cursor is positioned *\n *                            at the next tabstop.                         *\n *                                                                         *\n *             %s             Replace the \"%s\" with the text pointed to    *\n *                            by the pointer argument passed to the        *\n *                            routine (follows same method a printf).      *\n *                                                                         *\n *             %d             Replace the \"%d\" with an integer ASCII       *\n *                            number of the int passed to the routine.    *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *   07/29/1991 JLB : Added MORE, SETX, and SETY                           *\n *=========================================================================*/\nvoid Window_Print(char const string[], ...)\n{\n\tint\t\toldcx, x, y;\t// Scratch variables.\n\tchar\t\tc;\t\t\t\t\t// Current character.\n\tchar\t\tbuffer[10];\t\t// Working %d buffer.\n\tint\t\told_c, old_b;\t// Original window colors.\n\tva_list\targ;\t\t\t\t// Argument list var.\n\n\n\tva_start(arg, string);\n\n\tWordWrapFlag = FALSE;\t\t\t// initialize word wrap flag.\n\tPos = PPos = 0;\n\tLine[0] = '\\0';\n\tChar[0] = Char[1] = 0;\n\tMainSource = (char*)&string[0];\n\tAltSource = NULL;\n\told_c = WinC;\n\told_b = WinB;\n\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Hide_Mouse(Window);\n//BG\t}\n\n\twhile (TRUE) {\n\n\t\tc = Fetch_Char();\n\n\t\tif (!c) break;\t// Exit on NULL character.\n\n\t\t/*\n\t\t**\tSubstitution commands only work if not already expanding a\n\t\t**\tstring.\n\t\t*/\n\t\tif (!AltSource) {\n\t\t\tif (c == '%') {\n\t\t \t\tswitch(tolower(Char[0])) {\n\t\t\t\t\tcase 's':\n\t\t\t\t\t\tAltSource = va_arg(arg, char*);\n\t\t\t\t\t\tif (AltSource) {\n\t\t\t\t\t\t\tStack = Char[1];\n\t\t\t\t\t\t\tChar[0] = Char[1] = '\\0';\n\t\t\t\t\t\t\tc = Fetch_Char();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'd':\n\t\t\t\t\t\tAltSource = buffer;\n\t\t\t\t\t\tsprintf(buffer, \"%d\", va_arg(arg, int));\n\t\t\t\t\t\tStack = Char[1];\n\t\t\t\t\t\tChar[0] = Char[1] = '\\0';\n\t\t\t\t\t\tc = Fetch_Char();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tswitch(c) {\n\n#if(FALSE)\n\t// these are the positions of foreign language characters\n\t\t\t/*\n\t\t\t** These are characters that shouldn't be window printed because\n\t\t\t**\tthey are currently reserved.\n\t\t\t*/\n\t\t\tcase KA_CTRL_C:\n\t\t\tcase KA_CTRL_D:\n\t\t\tcase KA_CTRL_E:\n\t\t\tcase KA_CTRL_G:\n\t\t\tcase KA_CTRL_J:\n\t\t\tcase KA_CTRL_K:\n\t\t\tcase KA_CTRL_N:\n\t\t\tcase KA_CTRL_O:\n\t\t\tcase KA_CTRL_P:\n\t\t\tcase KA_CTRL_Q:\n\t\t\tcase KA_CTRL_R:\n\t\t\tcase KA_CTRL_T:\n\t\t\tcase KA_CTRL_U:\n\t\t\tcase KA_CTRL_V:\n\t\t\tcase KA_CTRL_W:\n\t\t\tcase KA_CTRL_Z:\n\t\t\tcase KA_CTRL_BACKSLASH:\n\t\t\tcase KA_CTRL_CARROT:\n\t\t\tcase KA_CTRL_UNDERLINE:\n\t\t\t\tbreak;\n#endif\n\t\t\t/*\n\t\t\t**\tForce cursor column to specified X value.\n\t\t\t*/\n\t\t\tcase KA_SETX:\n\t\t\t\tFlush_Line();\n\t\t\t\tWPos  = Fetch_Char();\n\t\t\t\tWPos  = MAX(0, WPos);\n\n\t\t\t\t// WPos is max width char position\n\n\t\t\t\tWPos  = MIN(WindowColumns-1, WPos);\n\t\t\t\tWinCx = WPos * (FontWidth+FontXSpacing);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tForce the cursor to specified Y value.\n\t\t\t*/\n\t\t\tcase KA_SETY:\n\t\t\t\tFlush_Line();\n\t\t\t\tWinCy = Fetch_Char();\n\t\t\t\t//WinCy = MAX(0, WinCy);\n\t\t\t\tWinCy = MIN((long)WindowLines-1, (long)WinCy);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tForce a \"<MORE>\" prompt.\n\t\t\t*/\n\t\t\tcase KA_MORE:\n\t\t\t\tFlush_Line();\n\t\t\t\tif (Window_More_Ptr) {\n//BG\t\t\t\t\tif (LogicPage == SEENPAGE) Window_Show_Mouse();\n\t\t\t\t\tWindow_More_Ptr(TXT_MoreText, MoreSpace, MoreFColor, MoreBColor);\n//BG\t\t\t\t\tif (LogicPage == SEENPAGE) Window_Hide_Mouse(Window);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tClear and home the window cursor.  This is the same\n\t\t\t**\tas New_Window().\n\t\t\t*/\n\t\t\tcase KA_FORMFEED:\n\t\t\t\tNew_Window();\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tMove cursor to start of next line.\n\t\t\t*/\n\t\t\tcase KA_RETURN:\n\t\t\t\tFlush_Line();\n\t\t\t\tScrollCounter++;\n\t\t\t\tWinCx = 0;\n\n#if(FALSE)\n\t\t\t\tif (WinCy >= WindowLines-1) {\n\t\t\t\t\tScroll_Window();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tWinCy++;\n\t\t\t\t}\n#else\n\t  \t\t\tWinCy++;\n#endif\n\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tSet the background color.\n\t\t\t*/\n\t\t\tcase KA_SETBKGDCOL:\n\t\t\t\tFlush_Line();\n\t\t\t\tWinB = Fetch_Char();\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tSet the foreground color.\n\t\t\t*/\n\t\t\tcase KA_SETFORECOL:\n\t\t\t\tFlush_Line();\n\t\t\t\tWinC = Fetch_Char();\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tMove cursor to next column.\n\t\t\t*/\n\t\t\tcase KA_TAB:\n\t\t\t\tFlush_Line();\n\t\t\t\tWPos = ((WPos + 8) & 0xFFF8) - 1;\n\t\t\t\tif (WPos >= WindowColumns) {\n\t\t\t\t\tWPos = 0;\n\t\t\t\t}\n\t\t\t\tWinCx = WPos * (FontWidth+FontXSpacing);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tTab to specified column but add spaces.\n\t\t\t*/\n\t\t\tcase KA_SPCTAB:\n\t\t\t\tFlush_Line();\n\t\t\t\toldcx = WinCx;\n\t\t\t\tx = WinX << 3;\n\t\t\t\ty = WinY + (WinCy * (FontHeight+FontYSpacing));\n\t\t\t\tWPos = ((WPos + 8) & 0xFFF8) - 1;\n\n\t\t\t\tif (WPos >= WindowColumns) {\n\t\t\t\t\tWinCx = WPos = 0;\n\n\t\t\t\t\t// Fill_Rect instead of printing spaces\n\n\t\t\t\t\tLogicPage->Fill_Rect(x + oldcx, y,\n\t\t\t\t\t\t\t\tx + WindowWidth - 1, y + (FontHeight+FontYSpacing) - 1, WinB);\n\n\t\t\t\t\tScrollCounter++;\n\t\t  \t\t\tWinCy++;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tWinCx = WPos * (FontWidth+FontXSpacing);\n\n\t\t\t\t\t// Fill_Rect instead of printing spaces\n\n\t\t\t\t\tLogicPage->Fill_Rect(x + oldcx, y,\n\t\t\t\t\t\t\t\tx + WinCx - 1, y + (FontHeight+FontYSpacing) - 1, WinB);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tnext character is a extended value 1-127, but 128 is added\n\t\t\t** for a value 129-255\n\t\t\t*/\n\t\t\tcase KA_EXTEND:\n\t\t\t\tc = 127;\n\n\t\t\t// NOTE: this falls thru to the default case DO NOT MOVE!!!!!\n\n\n\t\t\t/*\n\t\t\t**\tnext character is a literal value 1-127, except 13\n\t\t\t*/\n\t\t\tcase KA_LITERAL:\n\t\t\t\tif (c != (char) 127) {\t// check if fell thru from extend case\n\t\t\t\t\tc = 0;\t\t\t\t\t// set to zero for literal case\n\t\t\t\t}\n\t\t\t\tc += Fetch_Char();\n\n\t\t\t// NOTE: this falls thru to the default case DO NOT MOVE!!!!!\n\n\n\t\t\t/*\n\t\t\t**\tNormal character output.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\tPPos += Char_Pixel_Width(c);\t// get pixel location of next char\n\t\t\t\tLine[Pos++] = c;\n\t\t\t\tLine[Pos] = '\\0';\n\n\t\t\t\tif (WinCx + PPos > WindowWidth) {\n\t\t\t\t\tFlush_Line();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is text still pending, then display it before exiting.\n\t*/\n\tif (Pos) Flush_Line();\n\n\t/*\n\t**\tRecord changes in the cursor position.\n\t*/\n\tWindowList[Window][WINDOWCURSORX] = WinCx;\n\tWindowList[Window][WINDOWCURSORY] = WinCy;\n\n\t/*\n\t**\tRestore the window colors to their original values.\n\t*/\n\tWindowList[Window][WINDOWFCOL] = WinC = old_c;\n\tWindowList[Window][WINDOWBCOL] = WinB = old_b;\n\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Show_Mouse();\n//BG\t}\n\n\tva_end(arg);\n}\n\n\n/***************************************************************************\n * SCROLL_WINDOW -- Scrolls the text window up one line.                   *\n *                                                                         *\n *    This will scroll the text window up one line.  It will handle any    *\n *    pausing for \"more\" if the MoreOn flag is set.                        *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine assumes that the LogicPage is the SEENPAGE.    *\n *             If this is not the case, the program may appear to hang     *\n *             if a \"more\" prompt is generated.                            *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void Scroll_Window(void)\n{\n\tint\ty;\t\t// Top pixel row of bottom line of window.\n\n\t/*\n\t**\tPossibly prompt for more text.\n\t*/\n\tif (ScrollCounter >= WindowLines-1 && MoreOn) {\n\t\tScrollCounter = 0;\n\n\t\tif (Window_More_Ptr) {\n//BG\t\t\tif (LogicPage == SEENPAGE) Window_Show_Mouse();\n\t\t\tWindow_More_Ptr(TXT_MoreText, MoreSpace, MoreFColor, MoreBColor);\n//BG\t\t\tif (LogicPage == SEENPAGE) Window_Hide_Mouse(Window);\n\t\t}\n\t}\n\n\t/*\n\t**\tScroll the window up one line.\n\t*/\n\ty = ((WinH / (FontHeight+FontYSpacing)) - 1) * (FontHeight+FontYSpacing);\n\tLogicPage->Blit(*LogicPage,WinX<<3, WinY + (FontHeight+FontYSpacing), WinX<<3, WinY, WinW<<3, WinH - (FontHeight+FontYSpacing) );\n\tLogicPage->Fill_Rect(WinX<<3, \n\t\t\t\tWinY + y, \n\t\t\t\t((WinX+WinW)<<3) - 1,\n\t\t\t\tWinY + WinH - 1, \n\t\t\t\tWinB);\n}\n\n\n/***************************************************************************\n * FLUSH_LINE -- Outputs the accumulate text line to screen.               *\n *                                                                         *\n *    This will display the accumlated text line to the screen.  It will   *\n *    handle breaking the text line at an appropriate position.            *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void Flush_Line(void)\n{\n\tint\tbreakit, breaksize, breakwidth;\n\tint\tx, y;\t\t\t\t\t// Coordinates of text print.\n\tint\tbreakpoint;\t\t\t// Point to break the line (if possible).\n\tchar\tbreakchar;\t\t\t// Break replace character.\n\tint\tindex;\t\t\t\t// Backward moving index var.\n\n\t/*\n\t** There could be a held <CR> and this is implied by the cursor Y position\n\t** beyond the bottom of the window.  If this is the case, then scroll the\n\t**\twindow and proceed with the line flush.\n\t*/\n\twhile (WinCy >= WindowLines /*&& Pos > 0*/) {\n\t\tScroll_Window();\n\t\tif (WinCy >= WindowLines) WinCy--;\n\t}\n\t//if (WinCy >= WindowLines) WinCy = WindowLines-1;\n\n\tx = (WinX<<3) + WinCx;\n\ty = WinY + (WinCy*(FontHeight+FontYSpacing));\n\n\tbreakwidth = WindowWidth;\n//\tif (ScrollCounter >= WindowLines - 1 && MoreOn) {\n//\t\tbreakwidth -= (MoreSpace * (FontWidth+FontXSpacing));\t\t// use maximum font width\n//\t}\n\n\t/*\n\t**\tTry to break the line at the last space IF the line has reached the edge\n\t**\tof the window.\n\t*/\n\tbreakpoint = Pos;\n\tbreaksize = PPos;\n\tif (WinCx + breaksize > breakwidth) {\n\t\t\n\t\t/*\n\t\t**\tSince the text WILL spill past the edge of the window, determine the \n\t\t**\tpoint where the break should occur.  If this line is ready for the <MORE>\n\t\t**\tprompt, then breaking must account for the <MORE> text.\n\t\t*/\n\t\tif (ScrollCounter >= WindowLines - 1 && MoreOn) {\n\t\t\tbreakwidth -= (MoreSpace * (FontWidth+FontXSpacing));\t\t// use maximum font width\n\t\t}\n\t\tbreakwidth -= WinCx;\n\n\t\tbreakit = 0;\n\t\tfor (index = breakpoint - 1; index > 0; index--) {\n\t\t\tbreakchar = Line[index];\n\t\t\tbreaksize -= Char_Pixel_Width(breakchar);\n\n\t\t\t// only once, find largest text that can fit on the line\n\t\t\tif (!breakit) {\n\t\t\t\t// was this the char that went past the right edge\n\t\t\t\tif (breaksize <= breakwidth) {\n\t\t\t\t\tbreakit = index;\t// save this position if there is no spaces\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// after largest text is found then look for a space to break on\n\t\t\tif (breakit && breakchar == KA_SPACE) {\n\t\t\t\tbreakpoint = index;\n\t\t\t\tWordWrapFlag = FALSE; // word will start at beginning of next line\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tException: When the current text buffer cannot be broken at a logical\n\t\t**\tplace AND the text is starting past the left margin, THEN there is\n\t\t**\tan implied break between the previous text output and this one.\n\t\t**\tOutput the current text on the next line left margin.\n\t\t*/\n\t\tif (!index) {\n\t\t\tif (WinCx && !WordWrapFlag) {\n\t\t\t\tbreakpoint = breaksize = 0;\t\t// Continue text on next line.\n\t\t\t\tWordWrapFlag = TRUE;\t\t// indicate a word continuation.\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbreakpoint = breakit;\t// Just print as much as possible.\n\t\t\t}\n\t\t}\n\t}\n\n\tbreakchar = Line[breakpoint];\n\tLine[breakpoint] = '\\0';\n\n\tLogicPage->Print(Line, x, y, WinC, WinB);\n\tWinCx += breaksize;\t\t\t\t\t// add size of text string printed.\n\n\tLine[breakpoint] = breakchar;\n\tif (breakchar == KA_SPACE) {\t\t// take out a space between words.\n\t\tbreakpoint++;\n\t}\n\n\t// take out another space for double spacing after end of sentence.\n\tif (Line[breakpoint] == KA_SPACE) {\n\t\tbreakpoint++;\n\t}\n\n\tstrcpy(Line, &Line[breakpoint]);\n\tPos = strlen(Line);\n\tPPos = String_Pixel_Width(Line);\n\n\t/*\n\t**\tIf at this point there is still text in the buffer, then flushing has\n\t**\tnot been completed.  Scroll to next line and repeat the text flushing\n\t**\tprocess.\n\t*/\n\tif (Pos || WinCx >= WindowWidth) {\n\t\tWinCx = WPos = 0;\n\t\t#if(FALSE)\n\t\t\tif (WinCy >= WindowLines-1) {\n\t\t\t\tScroll_Window();\n\t\t\t} else {\n\t\t\t\tWinCy++;\n\t\t\t}\n\t\t#else\n\t\t\tWinCy++;\n\t\t#endif\n\t\tFlush_Line();\n\t\tScrollCounter++;\t// must be done after flush line for correct counting\n\t}\n}\n\n\n/***************************************************************************\n * IN_CHAR -- Stores (un-dipped) character(s) from input to buffer.        *\n *                                                                         *\n *    Use this routine to fetch the next character from the input stream.  *\n *    If the character was dipthonged, then it will be broken into its     *\n *    component ASCII characters and stored in the specified location.     *\n *    This is the core character stream reading code.                      *\n *                                                                         *\n * INPUT:   str   -- char pointer to the position to store the character(s)*\n *                   fetched from the input stream.                        *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void In_Char(char *str)\n{\n\tchar\tc;\t\t// Character to return.\n\tchar\tnext;\t// Following character (if any).\n\n\tc = next = '\\0';\n\n\t/*\n\t**\tFetch a raw byte from the input stream.\n\t*/\n\tif (AltSource) {\n\t\tif (*AltSource == '\\0') {\n\t\t\tAltSource = NULL;\n\t\t\tc = Stack;\n\t\t} else {\n\t\t\tc = *AltSource++;\n\t\t}\n\t}\n\n\tif (!c && MainSource) {\n\t\tif (*MainSource == '\\0') {\n\t\t\tMainSource = NULL;\n\t\t} else {\n\t\t\tc = *MainSource++;\n\t\t}\n\t}\n\n\t/*\n\t**\tConvert a dipthong character into it's component\n\t**\tASCII characters.\n\t*/\n\tif (c & 0x80) {\n\t\tc &= 0x7F;\n\t\tnext = c & 0x07;\n\t\tc = (c & 0x78) >> 3;\n\n\t\tnext = Dipthong[c][next];\t// Dipthong character.\n\t\tc = Common[c];\t\t\t\t// Common character.\n\t}\n\n\t*str++ = c;\n\t*str = next;\n}\n\n\n/***************************************************************************\n * FETCH_CHAR -- Gets one undipthonged char from input.                    *\n *                                                                         *\n *    This routine will fetch one character from the input stream.  The    *\n *    character has already been un-dipthonged.  It is a straight ASCII    *\n *    character.  This routine ensures that if the next character in the   *\n *    input stream needs to be examined, it is available in Char[0].       *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  Returns next character in the input stream (ASCII).  If NULL   *\n *          is returned, then this indicates the end of the input stream.  *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE char Fetch_Char(void)\n{\n\tchar\tc;\t\t// Character to return.\n\n\tif (!Char[0]) {\n\t\tIn_Char(&Char[0]);\n\t}\n\n\tc = Char[0];\n\tChar[0] = Char[1];\n\tChar[1] = '\\0';\n\n\tif (!Char[0]) {\n\t\tIn_Char(&Char[0]);\n\t}\n\n\treturn (c);\n}\n\u001a\n"
  },
  {
    "path": "WIN32LIB/WW_WIN/OLD/WINHIDE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./winhide.c 1.10 1994/05/20 15:35:50 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Dune                                     *\n *                                                                         *\n *                    File Name : WINHIDE.C                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : May 30, 1991                             *\n *                                                                         *\n *                  Last Update : August 16, 1991   [JLB]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Window_Hide_Mouse -- Hides the mouse when it enters a window.         *\n *   Window_Show_Mouse -- Shows the mouse after Window_Hide_Mouse hides it.*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t<wwstd.h>\n#include\t<keyboard.h>\n#include \"windows.h\"\n\n\n#if(IBM)\n/***************************************************************************\n * WINDOW_HIDE_MOUSE -- Hides the mouse when it enters a window.           *\n *                                                                         *\n *    This is an intelligent form of Conditional_Hide_Mouse().  It will    *\n *    hide the mouse if it enters the specified window (see the            *\n *    WindowList global).                                                  *\n *                                                                         *\n * INPUT:   window   - Window number.                                      *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   Just like Conditional_Hide_Mouse(), this function is NOT    *\n *             nestable.                                                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/26/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Window_Hide_Mouse(int window)\n{\n\tint\tx,y,w,h;\n\n\tx = WindowList[window][WINDOWX]<<3;\n\ty = WindowList[window][WINDOWY];\n\tw = WindowList[window][WINDOWWIDTH]<<3;\n\th = WindowList[window][WINDOWHEIGHT];\n\tConditional_Hide_Mouse(x,y,x+w-1,y+h-1);\n}\n\n\n/***************************************************************************\n * WINDOW_SHOW_MOUSE -- Shows the mouse after Window_Hide_Mouse hides it.  *\n *                                                                         *\n *    This routines will show the mouse after Window_Hide_Mouse has hidden *\n *    it.                                                                  *\n *                                                                         *\n * INPUT:      none                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/22/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Window_Show_Mouse(void)\n{\n\tConditional_Show_Mouse();\n}\n#endif\n\n\n\u001a"
  },
  {
    "path": "WIN32LIB/WW_WIN/OLD/WW_WIN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the WINDOWS Library              *\n *                                                                         *\n *                    File Name : WINDOWS.H                                *\n *                                                                         *\n *                   Programmer : Barry W. Green                           *\n *                                                                         *\n *                   Start Date : February 16, 1995                        *\n *                                                                         *\n *                  Last Update : February 16, 1995 [BWG]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WINDOWS_H\n#define WINDOWS_H\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WINHIDE.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Window_Hide_Mouse(int window);\nvoid Window_Show_Mouse(void);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WINDOWS.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Standard_More_Prompt(char const *prompt, int space, int fcolor, int bcolor);\nvoid Set_More_Prompt(char const *prompt, int space, int fcolor, int bcolor);\nvoid Set_More_On(void);\nvoid Set_More_Off(void);\nint Change_Window(int windnum);\nint Change_New_Window(int windnum);\nvoid New_Window(void);\nvoid Window_Int_Print(int num);\nvoid Window_Print(char const string[], ...);\n\n/*\n**\tThe WindowList[][8] array contains the following elements.  Use these\n**\tdefines when accessing the WindowList.\n*/\ntypedef enum {\n\tWINDOWX,\t\t\t// X byte position of left edge.\n\tWINDOWY,\t\t\t// Y pixel position of top edge.\n\tWINDOWWIDTH,\t// Width in bytes of the window.\n\tWINDOWHEIGHT,\t// Height in pixels of the window.\n\tWINDOWFCOL,\t\t// Default foreground color.\n\tWINDOWBCOL,\t\t// Default background color.\n\tWINDOWCURSORX,\t// Current cursor X position (in rows).\n\tWINDOWCURSORY,\t// Current cursor Y position (in lines).\n\tWINDOWPADDING=0x1000\n} WindowIndexType;\n\nextern int WindowList[][8];\nextern int WindowColumns;\nextern int WindowLines;\nextern int WindowWidth;\nextern unsigned int WinB;\nextern unsigned int WinC;\nextern unsigned int WinX;\nextern unsigned int WinY;\nextern unsigned int WinCx;\nextern unsigned int WinCy;\nextern unsigned int WinH;\nextern unsigned int WinW;\nextern unsigned int Window;\n\nextern int MoreOn;\nextern char *TXT_MoreText;\n\nextern void (*Window_More_Ptr)(char const *, int, int, int);\n\n#endif //WINDOWS_H\n\n\u001a"
  },
  {
    "path": "WIN32LIB/WW_WIN/WINDOWS.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./windows.c 1.12 1994/05/20 15:35:25 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : WINDOWS.C                                *\n *                                                                         *\n *                   Programmer : Everyone                                 *\n *                                                                         *\n *                  Last Update : February 3, 1992   [DRD]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Change_New_Window -- Combined Change_Window and New_Window.           *\n *   Change_Window -- Changes the 'current' window in the system.          *\n *   Fetch_Char -- Gets one undipthonged char from input.                  *\n *   Flush_Line -- Outputs the accumulate text line to screen.             *\n *   In_Char -- Stores (un-dipped) character(s) from input to buffer.      *\n *   New_Window -- Clears the current window to the background color.      *\n *   Set_More_Off -- Turns the 'more' prompting off.                       *\n *   Set_More_On -- Turns the 'more' prompting on.                         *\n *   Set_More_Prompt -- Adjusts the more prompt text for default routine   *\n *   Standard_More_Prompt -- Default more prompt code for Window_Print     *\n *   Window_Int_Print -- Prints an integer to the window.                  *\n *   Window_Print -- Displays and wraps text into a window.                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <ctype.h>\n#include <stdlib.h>\n#include <string.h>\n#include\t<stdio.h>\n#include\t<stdarg.h>\n#include <wwstd.h>\n#include \"ww_win.h\"\n#include <keyboard.h>\n#include\t<font.h>\n#include <dipthong.h>\n\nPRIVATE void Scroll_Window(void);\nPRIVATE void Flush_Line(void);\nPRIVATE void In_Char(char *str);\nPRIVATE char Fetch_Char(void);\n\n\nPRIVATE int ScrollCounter = 0;\t//\tCount of the lines displayed before a pause.\nPRIVATE char Line[84];\t// Staging line buffer.\nPRIVATE int Pos;\t\t\t// Char Position of next free character.\nPRIVATE int PPos;\t\t// Pixel position of next free character.\nPRIVATE int WPos;\t\t// Char position in window.\nPRIVATE char *MainSource;\nPRIVATE char *AltSource;\nPRIVATE char Char[2];\nPRIVATE char Stack;\nPRIVATE char WordWrapFlag = FALSE;\t// flag for a word wrap.\n\nPRIVATE int MoreSpace = 7;\nPRIVATE int MoreFColor = 0;\nPRIVATE int MoreBColor = 0;\n\n\nint WindowColumns=40;\nint WindowLines=25;\nint WindowWidth=40;\nunsigned int WinB=0;\nunsigned int WinC=1;\nunsigned int WinX=0;\nunsigned int WinY=0;\nunsigned int WinCx=0;\nunsigned int WinCy=0;\nunsigned int WinH=25;\nunsigned int WinW=40;\nunsigned int Window=0;\n\nint MoreOn = TRUE;\nchar *TXT_MoreText = \"--More--\";\nvoid (*Window_More_Ptr)(char const *,int,int,int) = Standard_More_Prompt;\n\nextern GraphicViewPortClass *LogicPage;\n/***************************************************************************\n * STANDARD_MORE_PROMPT -- Default more prompt code for Window_Print       *\n *                                                                         *\n *    This is the standard \"<more>\" prompting code that is used by         *\n *    Window_Print when a page is full of text and a pause is desired      *\n *    before the next page of text is printed.  This function is called    *\n *    through the Window_More_Ptr global.                                  *\n *                                                                         *\n * INPUT:   prompt   -- Pointer to ASCII text that will be window printed  *\n *                      at the right margin.                               *\n *                                                                         *\n *          space    -- The number of spaces to allow for the 'more' text. *\n *                                                                         *\n *          fcolor   -- The foreground color to use for the 'more' text.   *\n *                                                                         *\n *          bcolor   -- The background oclor to use for the 'more' text.   *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/29/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Standard_More_Prompt(char const *prompt, int space, int fcolor, int bcolor)\n{\n\tint\tx, y, moresize;\n\n\tmoresize = (space - 1) * (FontWidth+FontXSpacing);\n\tx = ((WinX+WinW) << 3) - moresize;\n\t//y = WinY + ((WinH/FontHeight)-1)*FontHeight;\n\ty = WinY + (WinCy-1) * (FontHeight+FontYSpacing);\n\n\t// Default \"more\" prompter.\n\tLogicPage->Print(prompt, x, y, fcolor ? fcolor : WindowList[Window][WINDOWBCOL], bcolor ? bcolor : WindowList[Window][WINDOWFCOL]);\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Show_Mouse();\n//BG\t}\n\n\t// PWG - have to figure out how to do this in windows library\n\n//\tClear_KeyBuffer();\n//\tGet_Key();\n\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Hide_Mouse(Window);\n//BG\t}\n\n\t// Erase the more prompt prompt.\n\t//\tText_Print(prompt, x, y, WinB, WinB);\n\tLogicPage->Fill_Rect(x, y, x + moresize - 1, y + (FontHeight+FontYSpacing) - 1, (unsigned char)WinB);\n}\n\n\n/***************************************************************************\n * SET_MORE_PROMPT -- Adjusts the more prompt text for default routine     *\n *                                                                         *\n *    Use this routine to control the text of the \"<MORE>\" prompt that     *\n *    the default more prompt routine uses.  This can be useful for        *\n *    foreign language translations.                                       *\n *                                                                         *\n * INPUT:   prompt   -- Pointer to ASCII text that will be window printed  *\n *                      at the right margin.                               *\n *                                                                         *\n *          space    -- The number of spaces to allow for the 'more' text. *\n *                                                                         *\n *          fcolor   -- The foreground color to use for the 'more' text.   *\n *                                                                         *\n *          bcolor   -- The background color to use for the 'more' text.   *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/29/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Set_More_Prompt(char const *prompt, int space, int fcolor, int bcolor)\n{\n\tif (prompt) {\n\t\tTXT_MoreText = (char*)prompt;\n\t\tMoreSpace = space;\n\t\tMoreFColor = fcolor;\n\t\tMoreBColor = bcolor;\n\t}\n\telse {\n\t\tTXT_MoreText = \"<MORE>\";\n\t\tMoreSpace = 7;\n\t\tMoreFColor = MoreBColor = 0;\n\t}\n}\n\n\n/***************************************************************************\n * SET_MORE_ON -- Turns the 'more' prompting on.                           *\n *                                                                         *\n *    Use this routine to turn on the 'more' prompting that Window_Print   *\n *    does.  If you have a custom more function pointer, then that         *\n *    routine will be called, otherwise the library default 'more' prompt  *\n *    will be utilized.                                                    *\n *                                                                         *\n * INPUT:      none                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Set_More_On(void)\n{\n\tMoreOn = TRUE;\n\tScrollCounter = 0;\n}\n\n\n/***************************************************************************\n * SET_MORE_OFF -- Turns the 'more' prompting off.                         *\n *                                                                         *\n *    This routine will turn the 'more' prompting that Window_Print does   *\n *    off.                                                                 *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Set_More_Off(void)\n{\n\tMoreOn = FALSE;\n}\n\n\n/***************************************************************************\n * CHANGE_WINDOW -- Changes the 'current' window in the system.            *\n *                                                                         *\n *    Use this routine to change the 'current' window.  The current window *\n *    is used in Window_Print and some other graphic output routines.      *\n *                                                                         *\n * INPUT:   windnum  -- The window number to change to.                    *\n *                                                                         *\n * OUTPUT:  Returns with the previously current window.                    *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nint Change_Window(int windnum)\n{\n\tint\toldwindow;\n\tint\t*data;\n\n\toldwindow = Window;\n\tWindow = windnum;\n\tdata = &WindowList[windnum][0];\n\n\tWinX = *data++;\n\tWinY = *data++;\n\tWinW = *data++;\n\tWinH = *data++;\n\tWinC = *data++;\n\tWinB = *data++;\n\tWinCx = *data++;\n\tWinCy = *data++;\n\tScrollCounter = 0;\n\tWPos = WinCx / (FontWidth+FontXSpacing);\n\tWindowLines = (WinH-FontYSpacing) / (FontHeight+FontYSpacing);\n\tWindowWidth = WinW << 3;\n\tWindowColumns = WindowWidth / (FontWidth+FontXSpacing);\n\treturn (oldwindow);\n}\n\n\n/***************************************************************************\n * CHANGE_NEW_WINDOW -- Combined Change_Window and New_Window.             *\n *                                                                         *\n *    This is a combo-routine.  It merely combines the Change_Window       *\n *    with the New_Window routines.  It will save some (small) code if     *\n *    you use this routine instead of the two function calls.              *\n *                                                                         *\n * INPUT:   window   -- Window number to change to and clear.              *\n *                                                                         *\n * OUTPUT:  Returns with the previously current window.                    *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nint Change_New_Window(int windnum)\n{\n\tint\toldwindow;\n\n\toldwindow = Change_Window(windnum);\n\tNew_Window();\n\treturn(oldwindow);\n}\n\n\n/***************************************************************************\n * NEW_WINDOW -- Clears the current window to the background color.        *\n *                                                                         *\n *    This routine clears the current window to the background color.  It  *\n *    is used in preparation to Window_Print because it ensures a clean    *\n *    'slate' for the text.                                                *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid New_Window(void)\n{\n\tint\tx,y,w,h;\n\n\tx = WinX << 3;\n\ty = WinY;\n\tw = (WinX + WinW) << 3;\n\th = WinY + WinH;\n\n\tLogicPage->Fill_Rect(x, y, w - 1, h - 1, (unsigned char)WinB);\n\n\tWinCx = WPos = 0;\n\tWinCy = 0;\n\tScrollCounter = 0;\n}\n\n\n/***************************************************************************\n * WINDOW_INT_PRINT -- Prints an integer to the window.                    *\n *                                                                         *\n *    Use this routine to print an integer to the window.  This routine    *\n *    as all other Window printing routines will handle word wrap.         *\n *                                                                         *\n * INPUT:   num   -- The integer to convert to ASCII and print.            *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Window_Int_Print(int num)\n{\n\tWindow_Print(\"%d\", num);\n}\n\n\n/***************************************************************************\n * WINDOW_PRINT -- Displays and wraps text into a window.                  *\n *                                                                         *\n *    This is the general purpos text output routine that will handle      *\n *    word wrap within a window.  It is useful for displaying arbitrary    *\n *    text.  This routine will handle dipthonged text and as such it       *\n *    can be quite useful in saving memory.                                *\n *                                                                         *\n * INPUT:   string   -- String to print.  This can be of ANY length and    *\n *                      can even contain some formatting codes.  The       *\n *                      codes supported are:                               *\n *                                                                         *\n *             KA_SETX        Forces the cursor X position to the value    *\n *                            specified.                                   *\n *                                                                         *\n *             KA_SETY        Forces the cursor Y position to the value    *\n *                            specified.                                   *\n *                                                                         *\n *             KA_MORE        Causes an immediate \"<MORE>\" prompt          *\n *                            regardless of the scroll situation.          *\n *                                                                         *\n *             KA_RETURN      Breaks line and continues output at the      *\n *                            left edge of following line.                 *\n *                                                                         *\n *                                                                         *\n *             KA_FORMFEED    Clears the window and continues printing at  *\n *                            the upper left corner.                       *\n *                                                                         *\n *             KA_SETBKGDCOL  Set the background color with the color      *\n *                            specified by the following byte.             *\n *                                                                         *\n *                                                                         *\n *             KA_SETFORECOL  Set the foreground color with the color      *\n *                            specified by the following byte.             *\n *                                                                         *\n *             KA_TAB         Move the cursor over to the next tabstop.    *\n *                            Tabstops are set every 8 columns.            *\n *                                                                         *\n *             KA_SPCTAB      Insert spaces until the cursor is positioned *\n *                            at the next tabstop.                         *\n *                                                                         *\n *             %s             Replace the \"%s\" with the text pointed to    *\n *                            by the pointer argument passed to the        *\n *                            routine (follows same method a printf).      *\n *                                                                         *\n *             %d             Replace the \"%d\" with an integer ASCII       *\n *                            number of the int passed to the routine.    *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *   07/29/1991 JLB : Added MORE, SETX, and SETY                           *\n *=========================================================================*/\nvoid Window_Print(char const string[], ...)\n{\n\tint\t\toldcx, x, y;\t// Scratch variables.\n\tchar\t\tc;\t\t\t\t\t// Current character.\n\tchar\t\tbuffer[10];\t\t// Working %d buffer.\n\tint\t\told_c, old_b;\t// Original window colors.\n\tva_list\targ;\t\t\t\t// Argument list var.\n\n\n\tva_start(arg, string);\n\n\tWordWrapFlag = FALSE;\t\t\t// initialize word wrap flag.\n\tPos = PPos = 0;\n\tLine[0] = '\\0';\n\tChar[0] = Char[1] = 0;\n\tMainSource = (char*)&string[0];\n\tAltSource = NULL;\n\told_c = WinC;\n\told_b = WinB;\n\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Hide_Mouse(Window);\n//BG\t}\n\n\twhile (TRUE) {\n\n\t\tc = Fetch_Char();\n\n\t\tif (!c) break;\t// Exit on NULL character.\n\n\t\t/*\n\t\t**\tSubstitution commands only work if not already expanding a\n\t\t**\tstring.\n\t\t*/\n\t\tif (!AltSource) {\n\t\t\tif (c == '%') {\n\t\t \t\tswitch(tolower(Char[0])) {\n\t\t\t\t\tcase 's':\n\t\t\t\t\t\tAltSource = va_arg(arg, char*);\n\t\t\t\t\t\tif (AltSource) {\n\t\t\t\t\t\t\tStack = Char[1];\n\t\t\t\t\t\t\tChar[0] = Char[1] = '\\0';\n\t\t\t\t\t\t\tc = Fetch_Char();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'd':\n\t\t\t\t\t\tAltSource = buffer;\n\t\t\t\t\t\tsprintf(buffer, \"%d\", va_arg(arg, int));\n\t\t\t\t\t\tStack = Char[1];\n\t\t\t\t\t\tChar[0] = Char[1] = '\\0';\n\t\t\t\t\t\tc = Fetch_Char();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tswitch(c) {\n\n#if(FALSE)\n\t// these are the positions of foreign language characters\n\t\t\t/*\n\t\t\t** These are characters that shouldn't be window printed because\n\t\t\t**\tthey are currently reserved.\n\t\t\t*/\n\t\t\tcase KA_CTRL_C:\n\t\t\tcase KA_CTRL_D:\n\t\t\tcase KA_CTRL_E:\n\t\t\tcase KA_CTRL_G:\n\t\t\tcase KA_CTRL_J:\n\t\t\tcase KA_CTRL_K:\n\t\t\tcase KA_CTRL_N:\n\t\t\tcase KA_CTRL_O:\n\t\t\tcase KA_CTRL_P:\n\t\t\tcase KA_CTRL_Q:\n\t\t\tcase KA_CTRL_R:\n\t\t\tcase KA_CTRL_T:\n\t\t\tcase KA_CTRL_U:\n\t\t\tcase KA_CTRL_V:\n\t\t\tcase KA_CTRL_W:\n\t\t\tcase KA_CTRL_Z:\n\t\t\tcase KA_CTRL_BACKSLASH:\n\t\t\tcase KA_CTRL_CARROT:\n\t\t\tcase KA_CTRL_UNDERLINE:\n\t\t\t\tbreak;\n#endif\n\t\t\t/*\n\t\t\t**\tForce cursor column to specified X value.\n\t\t\t*/\n\t\t\tcase KA_SETX:\n\t\t\t\tFlush_Line();\n\t\t\t\tWPos  = Fetch_Char();\n\t\t\t\tWPos  = MAX(0, WPos);\n\n\t\t\t\t// WPos is max width char position\n\n\t\t\t\tWPos  = MIN(WindowColumns-1, WPos);\n\t\t\t\tWinCx = WPos * (FontWidth+FontXSpacing);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tForce the cursor to specified Y value.\n\t\t\t*/\n\t\t\tcase KA_SETY:\n\t\t\t\tFlush_Line();\n\t\t\t\tWinCy = Fetch_Char();\n\t\t\t\t//WinCy = MAX(0, WinCy);\n\t\t\t\tWinCy = MIN((long)WindowLines-1, (long)WinCy);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tForce a \"<MORE>\" prompt.\n\t\t\t*/\n\t\t\tcase KA_MORE:\n\t\t\t\tFlush_Line();\n\t\t\t\tif (Window_More_Ptr) {\n//BG\t\t\t\t\tif (LogicPage == SEENPAGE) Window_Show_Mouse();\n\t\t\t\t\tWindow_More_Ptr(TXT_MoreText, MoreSpace, MoreFColor, MoreBColor);\n//BG\t\t\t\t\tif (LogicPage == SEENPAGE) Window_Hide_Mouse(Window);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tClear and home the window cursor.  This is the same\n\t\t\t**\tas New_Window().\n\t\t\t*/\n\t\t\tcase KA_FORMFEED:\n\t\t\t\tNew_Window();\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tMove cursor to start of next line.\n\t\t\t*/\n\t\t\tcase KA_RETURN:\n\t\t\t\tFlush_Line();\n\t\t\t\tScrollCounter++;\n\t\t\t\tWinCx = 0;\n\n#if(FALSE)\n\t\t\t\tif (WinCy >= WindowLines-1) {\n\t\t\t\t\tScroll_Window();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tWinCy++;\n\t\t\t\t}\n#else\n\t  \t\t\tWinCy++;\n#endif\n\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tSet the background color.\n\t\t\t*/\n\t\t\tcase KA_SETBKGDCOL:\n\t\t\t\tFlush_Line();\n\t\t\t\tWinB = Fetch_Char();\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tSet the foreground color.\n\t\t\t*/\n\t\t\tcase KA_SETFORECOL:\n\t\t\t\tFlush_Line();\n\t\t\t\tWinC = Fetch_Char();\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tMove cursor to next column.\n\t\t\t*/\n\t\t\tcase KA_TAB:\n\t\t\t\tFlush_Line();\n\t\t\t\tWPos = ((WPos + 8) & 0xFFF8) - 1;\n\t\t\t\tif (WPos >= WindowColumns) {\n\t\t\t\t\tWPos = 0;\n\t\t\t\t}\n\t\t\t\tWinCx = WPos * (FontWidth+FontXSpacing);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tTab to specified column but add spaces.\n\t\t\t*/\n\t\t\tcase KA_SPCTAB:\n\t\t\t\tFlush_Line();\n\t\t\t\toldcx = WinCx;\n\t\t\t\tx = WinX << 3;\n\t\t\t\ty = WinY + (WinCy * (FontHeight+FontYSpacing));\n\t\t\t\tWPos = ((WPos + 8) & 0xFFF8) - 1;\n\n\t\t\t\tif (WPos >= WindowColumns) {\n\t\t\t\t\tWinCx = WPos = 0;\n\n\t\t\t\t\t// Fill_Rect instead of printing spaces\n\n\t\t\t\t\tLogicPage->Fill_Rect(x + oldcx, y,\n\t\t\t\t\t\t\t\tx + WindowWidth - 1, y + (FontHeight+FontYSpacing) - 1, (unsigned char)WinB);\n\n\t\t\t\t\tScrollCounter++;\n\t\t  \t\t\tWinCy++;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tWinCx = WPos * (FontWidth+FontXSpacing);\n\n\t\t\t\t\t// Fill_Rect instead of printing spaces\n\n\t\t\t\t\tLogicPage->Fill_Rect(x + oldcx, y,\n\t\t\t\t\t\t\t\tx + WinCx - 1, y + (FontHeight+FontYSpacing) - 1, (unsigned char)WinB);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tnext character is a extended value 1-127, but 128 is added\n\t\t\t** for a value 129-255\n\t\t\t*/\n\t\t\tcase KA_EXTEND:\n\t\t\t\tc = 127;\n\n\t\t\t// NOTE: this falls thru to the default case DO NOT MOVE!!!!!\n\n\n\t\t\t/*\n\t\t\t**\tnext character is a literal value 1-127, except 13\n\t\t\t*/\n//\t\t\tcase KA_LITERAL:\n//\t\t\t\tif (c != (char) 127) {\t// check if fell thru from extend case\n//\t\t\t\t\tc = 0;\t\t\t\t\t// set to zero for literal case\n//\t\t\t\t}\n//\t\t\t\tc += Fetch_Char();\n\n\t\t\t// NOTE: this falls thru to the default case DO NOT MOVE!!!!!\n\n\n\t\t\t/*\n\t\t\t**\tNormal character output.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\tPPos += Char_Pixel_Width(c);\t// get pixel location of next char\n\t\t\t\tLine[Pos++] = c;\n\t\t\t\tLine[Pos] = '\\0';\n\n\t\t\t\tif (WinCx + PPos > WindowWidth) {\n\t\t\t\t\tFlush_Line();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is text still pending, then display it before exiting.\n\t*/\n\tif (Pos) Flush_Line();\n\n\t/*\n\t**\tRecord changes in the cursor position.\n\t*/\n\tWindowList[Window][WINDOWCURSORX] = WinCx;\n\tWindowList[Window][WINDOWCURSORY] = WinCy;\n\n\t/*\n\t**\tRestore the window colors to their original values.\n\t*/\n\tWindowList[Window][WINDOWFCOL] = WinC = old_c;\n\tWindowList[Window][WINDOWBCOL] = WinB = old_b;\n\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Show_Mouse();\n//BG\t}\n\n\tva_end(arg);\n}\n\n\n/***************************************************************************\n * SCROLL_WINDOW -- Scrolls the text window up one line.                   *\n *                                                                         *\n *    This will scroll the text window up one line.  It will handle any    *\n *    pausing for \"more\" if the MoreOn flag is set.                        *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine assumes that the LogicPage is the SEENPAGE.    *\n *             If this is not the case, the program may appear to hang     *\n *             if a \"more\" prompt is generated.                            *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void Scroll_Window(void)\n{\n\tint\ty;\t\t// Top pixel row of bottom line of window.\n\n\t/*\n\t**\tPossibly prompt for more text.\n\t*/\n\tif (ScrollCounter >= WindowLines-1 && MoreOn) {\n\t\tScrollCounter = 0;\n\n\t\tif (Window_More_Ptr) {\n//BG\t\t\tif (LogicPage == SEENPAGE) Window_Show_Mouse();\n\t\t\tWindow_More_Ptr(TXT_MoreText, MoreSpace, MoreFColor, MoreBColor);\n//BG\t\t\tif (LogicPage == SEENPAGE) Window_Hide_Mouse(Window);\n\t\t}\n\t}\n\n\t/*\n\t**\tScroll the window up one line.\n\t*/\n\ty = ((WinH / (FontHeight+FontYSpacing)) - 1) * (FontHeight+FontYSpacing);\n\tLogicPage->Blit(*LogicPage,WinX<<3, WinY + (FontHeight+FontYSpacing), WinX<<3, WinY, WinW<<3, WinH - (FontHeight+FontYSpacing) );\n\tLogicPage->Fill_Rect(WinX<<3,\n\t\t\t\tWinY + y,\n\t\t\t\t((WinX+WinW)<<3) - 1,\n\t\t\t\tWinY + WinH - 1,\n\t\t\t\t(unsigned char)WinB);\n}\n\n\n/***************************************************************************\n * FLUSH_LINE -- Outputs the accumulate text line to screen.               *\n *                                                                         *\n *    This will display the accumlated text line to the screen.  It will   *\n *    handle breaking the text line at an appropriate position.            *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void Flush_Line(void)\n{\n\tint\tbreakit, breaksize, breakwidth;\n\tint\tx, y;\t\t\t\t\t// Coordinates of text print.\n\tint\tbreakpoint;\t\t\t// Point to break the line (if possible).\n\tchar\tbreakchar;\t\t\t// Break replace character.\n\tint\tindex;\t\t\t\t// Backward moving index var.\n\n\t/*\n\t** There could be a held <CR> and this is implied by the cursor Y position\n\t** beyond the bottom of the window.  If this is the case, then scroll the\n\t**\twindow and proceed with the line flush.\n\t*/\n\twhile (WinCy >= WindowLines /*&& Pos > 0*/) {\n\t\tScroll_Window();\n\t\tif (WinCy >= WindowLines) WinCy--;\n\t}\n\t//if (WinCy >= WindowLines) WinCy = WindowLines-1;\n\n\tx = (WinX<<3) + WinCx;\n\ty = WinY + (WinCy*(FontHeight+FontYSpacing));\n\n\tbreakwidth = WindowWidth;\n//\tif (ScrollCounter >= WindowLines - 1 && MoreOn) {\n//\t\tbreakwidth -= (MoreSpace * (FontWidth+FontXSpacing));\t\t// use maximum font width\n//\t}\n\n\t/*\n\t**\tTry to break the line at the last space IF the line has reached the edge\n\t**\tof the window.\n\t*/\n\tbreakpoint = Pos;\n\tbreaksize = PPos;\n\tif (WinCx + breaksize > breakwidth) {\n\n\t\t/*\n\t\t**\tSince the text WILL spill past the edge of the window, determine the\n\t\t**\tpoint where the break should occur.  If this line is ready for the <MORE>\n\t\t**\tprompt, then breaking must account for the <MORE> text.\n\t\t*/\n\t\tif (ScrollCounter >= WindowLines - 1 && MoreOn) {\n\t\t\tbreakwidth -= (MoreSpace * (FontWidth+FontXSpacing));\t\t// use maximum font width\n\t\t}\n\t\tbreakwidth -= WinCx;\n\n\t\tbreakit = 0;\n\t\tfor (index = breakpoint - 1; index > 0; index--) {\n\t\t\tbreakchar = Line[index];\n\t\t\tbreaksize -= Char_Pixel_Width(breakchar);\n\n\t\t\t// only once, find largest text that can fit on the line\n\t\t\tif (!breakit) {\n\t\t\t\t// was this the char that went past the right edge\n\t\t\t\tif (breaksize <= breakwidth) {\n\t\t\t\t\tbreakit = index;\t// save this position if there is no spaces\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// after largest text is found then look for a space to break on\n\t\t\tif (breakit && breakchar == KA_SPACE) {\n\t\t\t\tbreakpoint = index;\n\t\t\t\tWordWrapFlag = FALSE; // word will start at beginning of next line\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tException: When the current text buffer cannot be broken at a logical\n\t\t**\tplace AND the text is starting past the left margin, THEN there is\n\t\t**\tan implied break between the previous text output and this one.\n\t\t**\tOutput the current text on the next line left margin.\n\t\t*/\n\t\tif (!index) {\n\t\t\tif (WinCx && !WordWrapFlag) {\n\t\t\t\tbreakpoint = breaksize = 0;\t\t// Continue text on next line.\n\t\t\t\tWordWrapFlag = TRUE;\t\t// indicate a word continuation.\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbreakpoint = breakit;\t// Just print as much as possible.\n\t\t\t}\n\t\t}\n\t}\n\n\tbreakchar = Line[breakpoint];\n\tLine[breakpoint] = '\\0';\n\n\tLogicPage->Print(Line, x, y, WinC, WinB);\n\tWinCx += breaksize;\t\t\t\t\t// add size of text string printed.\n\n\tLine[breakpoint] = breakchar;\n\tif (breakchar == KA_SPACE) {\t\t// take out a space between words.\n\t\tbreakpoint++;\n\t}\n\n\t// take out another space for double spacing after end of sentence.\n\tif (Line[breakpoint] == KA_SPACE) {\n\t\tbreakpoint++;\n\t}\n\n\tstrcpy(Line, &Line[breakpoint]);\n\tPos = strlen(Line);\n\tPPos = String_Pixel_Width(Line);\n\n\t/*\n\t**\tIf at this point there is still text in the buffer, then flushing has\n\t**\tnot been completed.  Scroll to next line and repeat the text flushing\n\t**\tprocess.\n\t*/\n\tif (Pos || WinCx >= WindowWidth) {\n\t\tWinCx = WPos = 0;\n\t\t#if(FALSE)\n\t\t\tif (WinCy >= WindowLines-1) {\n\t\t\t\tScroll_Window();\n\t\t\t} else {\n\t\t\t\tWinCy++;\n\t\t\t}\n\t\t#else\n\t\t\tWinCy++;\n\t\t#endif\n\t\tFlush_Line();\n\t\tScrollCounter++;\t// must be done after flush line for correct counting\n\t}\n}\n\n\n/***************************************************************************\n * IN_CHAR -- Stores (un-dipped) character(s) from input to buffer.        *\n *                                                                         *\n *    Use this routine to fetch the next character from the input stream.  *\n *    If the character was dipthonged, then it will be broken into its     *\n *    component ASCII characters and stored in the specified location.     *\n *    This is the core character stream reading code.                      *\n *                                                                         *\n * INPUT:   str   -- char pointer to the position to store the character(s)*\n *                   fetched from the input stream.                        *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void In_Char(char *str)\n{\n\tchar\tc;\t\t// Character to return.\n\tchar\tnext;\t// Following character (if any).\n\n\tc = next = '\\0';\n\n\t/*\n\t**\tFetch a raw byte from the input stream.\n\t*/\n\tif (AltSource) {\n\t\tif (*AltSource == '\\0') {\n\t\t\tAltSource = NULL;\n\t\t\tc = Stack;\n\t\t} else {\n\t\t\tc = *AltSource++;\n\t\t}\n\t}\n\n\tif (!c && MainSource) {\n\t\tif (*MainSource == '\\0') {\n\t\t\tMainSource = NULL;\n\t\t} else {\n\t\t\tc = *MainSource++;\n\t\t}\n\t}\n\n\t/*\n\t**\tConvert a dipthong character into it's component\n\t**\tASCII characters.\n\t*/\n\tif (c & 0x80) {\n\t\tc &= 0x7F;\n\t\tnext = c & (char)0x07;\n\t\tc = (char)((c & (char)0x78) >> 3);\n\n\t\tnext = Dipthong[c][next];\t// Dipthong character.\n\t\tc = Common[c];\t\t\t\t// Common character.\n\t}\n\n\t*str++ = c;\n\t*str = next;\n}\n\n\n/***************************************************************************\n * FETCH_CHAR -- Gets one undipthonged char from input.                    *\n *                                                                         *\n *    This routine will fetch one character from the input stream.  The    *\n *    character has already been un-dipthonged.  It is a straight ASCII    *\n *    character.  This routine ensures that if the next character in the   *\n *    input stream needs to be examined, it is available in Char[0].       *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  Returns next character in the input stream (ASCII).  If NULL   *\n *          is returned, then this indicates the end of the input stream.  *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE char Fetch_Char(void)\n{\n\tchar\tc;\t\t// Character to return.\n\n\tif (!Char[0]) {\n\t\tIn_Char(&Char[0]);\n\t}\n\n\tc = Char[0];\n\tChar[0] = Char[1];\n\tChar[1] = '\\0';\n\n\tif (!Char[0]) {\n\t\tIn_Char(&Char[0]);\n\t}\n\n\treturn (c);\n}\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/WW_WIN/WINHIDE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./winhide.c 1.10 1994/05/20 15:35:50 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Dune                                     *\n *                                                                         *\n *                    File Name : WINHIDE.C                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : May 30, 1991                             *\n *                                                                         *\n *                  Last Update : August 16, 1991   [JLB]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Window_Hide_Mouse -- Hides the mouse when it enters a window.         *\n *   Window_Show_Mouse -- Shows the mouse after Window_Hide_Mouse hides it.*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t<wwstd.h>\n#include\t<keyboard.h>\n#include \"ww_win.h\"\n\n\n#if(IBM)\n/***************************************************************************\n * WINDOW_HIDE_MOUSE -- Hides the mouse when it enters a window.           *\n *                                                                         *\n *    This is an intelligent form of Conditional_Hide_Mouse().  It will    *\n *    hide the mouse if it enters the specified window (see the            *\n *    WindowList global).                                                  *\n *                                                                         *\n * INPUT:   window   - Window number.                                      *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   Just like Conditional_Hide_Mouse(), this function is NOT    *\n *             nestable.                                                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/26/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Window_Hide_Mouse(int window)\n{\n\tint\tx,y,w,h;\n\n\tx = WindowList[window][WINDOWX]<<3;\n\ty = WindowList[window][WINDOWY];\n\tw = WindowList[window][WINDOWWIDTH]<<3;\n\th = WindowList[window][WINDOWHEIGHT];\n//\tConditional_Hide_Mouse(x,y,x+w-1,y+h-1);\n}\n\n\n/***************************************************************************\n * WINDOW_SHOW_MOUSE -- Shows the mouse after Window_Hide_Mouse hides it.  *\n *                                                                         *\n *    This routines will show the mouse after Window_Hide_Mouse has hidden *\n *    it.                                                                  *\n *                                                                         *\n * INPUT:      none                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/22/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Window_Show_Mouse(void)\n{\n//\tConditional_Show_Mouse();\n}\n#endif\n\n\n\u001a\n"
  },
  {
    "path": "WIN32LIB/WW_WIN/WW_WIN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the WINDOWS Library              *\n *                                                                         *\n *                    File Name : WINDOWS.H                                *\n *                                                                         *\n *                   Programmer : Barry W. Green                           *\n *                                                                         *\n *                   Start Date : February 16, 1995                        *\n *                                                                         *\n *                  Last Update : February 16, 1995 [BWG]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WINDOWS_H\n#define WINDOWS_H\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WINHIDE.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Window_Hide_Mouse(int window);\nvoid Window_Show_Mouse(void);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WINDOWS.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Standard_More_Prompt(char const *prompt, int space, int fcolor, int bcolor);\nvoid Set_More_Prompt(char const *prompt, int space, int fcolor, int bcolor);\nvoid Set_More_On(void);\nvoid Set_More_Off(void);\nint Change_Window(int windnum);\nint Change_New_Window(int windnum);\nvoid New_Window(void);\nvoid Window_Int_Print(int num);\nvoid Window_Print(char const string[], ...);\n\n/*\n**\tThe WindowList[][8] array contains the following elements.  Use these\n**\tdefines when accessing the WindowList.\n*/\ntypedef enum {\n\tWINDOWX,\t\t\t// X byte position of left edge.\n\tWINDOWY,\t\t\t// Y pixel position of top edge.\n\tWINDOWWIDTH,\t// Width in bytes of the window.\n\tWINDOWHEIGHT,\t// Height in pixels of the window.\n\tWINDOWFCOL,\t\t// Default foreground color.\n\tWINDOWBCOL,\t\t// Default background color.\n\tWINDOWCURSORX,\t// Current cursor X position (in rows).\n\tWINDOWCURSORY,\t// Current cursor Y position (in lines).\n\tWINDOWPADDING=0x1000\n} WindowIndexType;\n\nextern int WindowList[][8];\nextern int WindowColumns;\nextern int WindowLines;\nextern int WindowWidth;\nextern unsigned int WinB;\nextern unsigned int WinC;\nextern unsigned int WinX;\nextern unsigned int WinY;\nextern unsigned int WinCx;\nextern unsigned int WinCy;\nextern unsigned int WinH;\nextern unsigned int WinW;\nextern unsigned int Window;\n\nextern int MoreOn;\nextern char *TXT_MoreText;\n\nextern void (*Window_More_Ptr)(char const *, int, int, int);\n\n#endif //WINDOWS_H\n\n\u001a"
  },
  {
    "path": "WINVQ/INCLUDE/VOCFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VOCFILE_H\n#define VOCFILE_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     vocfile.h\n*\n* DESCRIPTION\n*     VOC audio file definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*      \n****************************************************************************/\n\n/* VOC file header.\n *\n * type   - File type description\n * offset - Offset of data block from the start of VOC file.\n * ver    - File format version number\n * id     - File identification code.\n */\ntypedef struct _VOCHeader {\n\tchar           type[0x14];\n\tunsigned short offset;\n\tunsigned short ver;\n\tunsigned short id;\n} VOCHeader;\n\n/* VOC sub-block block types */\n#define VBT_TERMINATE 0  /* Last block of file (no size field) */\n#define VBT_VOICEDATA 1  /* New set of voice data */\n#define VBT_VOICECONT 2  /* Continuation of voice data */\n#define VBT_SILENCE   3  /* Silence period */\n#define VBT_MARKER    4  /* Syncronization marker */\n#define VBT_ASCII     5  /* NULL terminated string */\n#define VBT_REPEAT    6  /* Mark beginning of repeat loop */\n#define VBT_ENDREPEAT 7  /* Mark end of repeat loop */\n#define VBT_EXTENDED  8\n\n#define IS_VOC(a,b) (((~a)+0x1234)==b)\n#define BLOCK_LEN(a) ((a&0x00FFFFFFL))\n\n#endif  /* VOCFILE_H */\n\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQ.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQ_H\n#define VQ_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* NAME\n*     vq.h\n*\n* DESCRIPTION\n*     VQ file definition\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     September 28, 1995\n*\n* NOTES\n*     VQ file organization:\n*\n*       Header: This structure contains all the data pertaining to the VQ.\n*               (See structure definition for details)\n*\n*               Size: 40 bytes\n*\n*       Palette: Color palette used by this VQ. Stored as 24 bit RGB entries.\n*\n*                Size: (PaletteRange * 3) bytes\n*\n*       Codebook: Sequence of vector blocks used to represent the VQ image.\n*                 Also called the dictionary. The sequence is sorted by\n*                 usage, so the first entry is the most commonly used block.\n*\n*                 Size: ((BlockWidth * BlockHeight) * CodebookSize) bytes\n*\n*       Pointers: Vector pointer map used to indicate the construction of\n*                 the vector blocks. Also called codewords.\n*\n*                 Size: (((ImageWidth / BlockWidth)\n*                       * (ImageHeight / BlockHeight)) * 2)\n*\n*     Pointer format:\n*\n*       Single color - Value less than or equal to 'Num1Color'\n*       Multi Color  - Value greater than 'Num1Color'\n*\n****************************************************************************/\n\n/* VQHeader - VQ header structure.\n *\n * ImageSize       - Compressed image size \n * ImageWidth      - Image x-dimension\n * ImageHeight     - Image y-dimension\n * BlockWidth      - Block x-dimension\n * BlockHeight     - Block y-dimension\n * BlockType       - Block type\n * PaletteRange    - Number of palette colors\n * Num1Color       - Number of 1-color blocks & 1-color colors\n * CodebookSize    - Number of actual codebook entries\n * CodingFlag      - Flag for 2-color blocks\n * FrameDiffMethod - Frame differencing method\n * ForcedPalette   - Force a palette on image\n * F555Palette     - Flag for output 15-bit palette\n * VQVersion       - VQ Version #\n * pad[5]          - Pad out to 40 bytes total\n */\ntypedef struct _VQHeader {\n\tunsigned long  ImageSize;\n\tunsigned short ImageWidth;\n\tunsigned short ImageHeight;\n\tunsigned short BlockWidth;\n\tunsigned short BlockHeight;\n\tunsigned short BlockType;\n\tunsigned short PaletteRange;\n\tunsigned short Num1Color;\n\tunsigned short CodebookSize;\n\tunsigned short CodingFlag;\n\tunsigned short FrameDiffMethod;\n\tunsigned short ForcedPalette;\n\tunsigned short F555Palette;\n\tunsigned short VQVersion;\n\tunsigned short pad[5];\n} VQHeader;\n\n#endif /* VQ_H */\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQA32/CAPTION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQACAPTION_H\n#define VQACAPTION_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library (32 bit protected mode)\n*\n* FILE\n*     caption.h\n*\n* DESCRIPTION\n*     Text caption definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 26, 1995\n*\n****************************************************************************/\n\n\n#define VQACAPTIONS_ON\t\t0\n\n/*---------------------------------------------------------------------------\n * STRUCTURES AND RELATED DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* CaptionNode: Node describing a caption to process.\n *\n * Succ    - Pointer to the next node in the list (successor).\n * Pred    - Pointer to the previous node in the list (predecessor).\n * Flags   - Status flags.\n * CapText - Pointer to the CaptionText being processed.\n * Char    - Pointer to current character in the string.\n * CurX    - Current X position.\n * CurY    - Current Y position.\n * BoundW  - Bounding width of text.\n * BoundH  - Bounding height of text.\n */\ntypedef struct _CaptionNode {\n\tstruct _CaptionNode *Succ;\n\tstruct _CaptionNode *Pred;\n\tunsigned short      Flags;\n\tCaptionText         *Captext;\n\tchar                *Char;\n\tunsigned short      CurX;\n\tunsigned short      CurY;\n\tunsigned short      BoundW;\n\tunsigned short      BoundH;\n} CaptionNode;\n\n/* CaptionNode flag definitions. */\n#define CNB_USED 0  /* This node is being used. */\n#define CNF_USED (1<<CNB_USED)\n\n\n/* CaptionList: Double linked list of outstanding captions to process.\n *\n * Head     - Pointer to the first node in the list.\n * Tail     - Always NULL\n * TailPred - Pointer to the last node in the list.\n */\ntypedef struct _CaptionList {\n\tCaptionNode *Head;\n\tCaptionNode *Tail;\n\tCaptionNode *TailPred;\n} CaptionList;\n\n\n/* CaptionInfo:\n *\n * Next   - Pointer to the next caption to be processed.\n * List   - List of pending captions to process.\n * Font   - Font to use for this caption.\n * BoundX - X position of bounding box.\n * BoundY - Y position of bounding box.\n * BoundW - Width of bounding box.\n * BoundH - Height of bounding box.\n * Buffer - Caption chunk buffer.\n */\ntypedef struct _CaptionInfo {\n\tCaptionText    *Next;\n\tCaptionList    List;\n\tvoid           *Font;\n\tchar           FontHeight;\n\tchar           FontWidth;\n\tvoid           *Buffer;\n} CaptionInfo;\n\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\nCaptionInfo *OpenCaptions(void *captions, void *font);\nvoid CloseCaptions(CaptionInfo *cap);\nvoid DoCaptions(CaptionInfo *cap, unsigned long frame);\n\n#endif /* VQACAPTION_H */\n\n\u001a"
  },
  {
    "path": "WINVQ/INCLUDE/VQA32/SOS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sos.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DEFINED   \n#define  _SOS_DEFINED   \n#include \"sosdefs.h\"\n\n#pragma pack(4)\n \n// error definition for sound operating system  \n#define  _SOS_ERR          -1\n\n// number of drivers allowed to be open at one time\n#define  _SOS_MAX_DRIVERS  5\n\n// structure definition for the capabilities\ntypedef struct _tagCAPABILITIES\n{\n   BYTE  szDeviceName[ 32 ];  // device name\n   WORD  wDeviceVersion;      // device version\n   WORD  wBitsPerSample;      // bits per sound sample\n   WORD  wChannels;           // stereo/mono sound card\n   WORD  wMinRate;            // minimum rate\n   WORD  wMaxRate;            // maximum rate\n   WORD  wMixerOnBoard;       // board contains mixer\n   WORD  wMixerFlags;         // mixer capabilities\n   WORD  wFlags;              // miscellaneous flags   \n   short far * lpPortList;         // list of usable ports\n   short far * lpDMAList;          // list of usable dma channels\n   short far * lpIRQList;          // list of usable irq channels\n   short far * lpRateList;         // list of usable rates, -1 if any in min to max\n   WORD  fBackground;         // foreground or background driver\n   WORD  wDeviceID;           // ID for the device\n   WORD  wTimerID;            // ID for the timer\n   \n} _SOS_CAPABILITIES; \n\n// far pointer to the device capabilities structure\ntypedef _SOS_CAPABILITIES far *  LPSOSDEVICECAPS;\n\n// flag types for driver\n#define  _FLAGS_SIGNED              0x8000\n  \n// devices that can be loaded\n#define  _SOUND_BLASTER_8_MONO      0xe000\n#define  _SOUND_BLASTER_8_ST        0xe001\n#define  _SBPRO_8_ST                _SOUND_BLASTER_8_ST\n#define  _SBPRO_8_MONO              0xe00f\n#define  _SOUND_MASTER_II_8_MONO    0xe002\n#define  _MV_PAS_8_MONO             0xe003\n#define  _MV_PAS_16_MONO            0xe004\n#define  _MV_PAS_8_ST               0xe005\n#define  _MV_PAS_16_ST              0xe006\n#define  _ADLIB_GOLD_8_ST           0xe007\n#define  _ADLIB_GOLD_16_ST          0xe008\n#define  _ADLIB_GOLD_8_MONO         0xe009\n#define  _ADLIB_GOLD_16_MONO        0xe00a\n#define  _MICROSOFT_8_MONO          0xe00b\n#define  _MICROSOFT_8_ST            0xe00c\n#define  _MICROSOFT_16_MONO         0xe00d\n#define  _MICROSOFT_16_ST           0xe00e\n#define  _SOUND_SOURCE_8_MONO_PC    0xe010\n#define  _SOUND_SOURCE_8_MONO_TANDY 0xe011\n#define  _GENERAL_PORT_8_MONO       0xe012\n#define  _GENERAL_PORT_8_MONO_R     0xe013\n#define  _SIERRA_8_MONO             0xe014\n#define  _SB16_8_MONO               0xe015\n#define  _SB16_8_ST                 0xe016\n#define  _SB16_16_MONO              0xe017\n#define  _SB16_16_ST                0xe018\n#define  _ESS_AUDIODRIVE_8_MONO     0xe019\n#define  _ESS_AUDIODRIVE_8_ST       0xe01a\n#define  _ESS_AUDIODRIVE_16_MONO    0xe01b\n#define  _ESS_AUDIODRIVE_16_ST      0xe01c\n#define  _SOUNDSCAPE_8_MONO         0xe01d\n#define  _SOUNDSCAPE_8_ST           0xe01e\n#define  _SOUNDSCAPE_16_MONO        0xe01f\n#define  _SOUNDSCAPE_16_ST          0xe020\n#define  _RAP10_8_MONO              0xe021\n#define  _RAP10_16_MONO             0xe022\n#define  _GUS_8_MONO                0xe023\n#define  _GUS_8_ST                  0xe024\n#define  _GUS_16_MONO               0xe025\n#define  _GUS_16_ST                 0xe026\n#define  _GUS_MAX_8_MONO            0xe027\n#define  _GUS_MAX_8_ST              0xe028\n#define  _GUS_MAX_16_MONO           0xe029\n#define  _GUS_MAX_16_ST             0xe02a\n#define  _WAVEJAMMER_8_MONO         0xe02b\n#define  _WAVEJAMMER_8_ST           0xe02c\n#define  _WAVEJAMMER_16_MONO        0xe02d\n#define  _WAVEJAMMER_16_ST          0xe02e\n#define  _TEMPOCS_8_MONO            0xe02f\n#define  _TEMPOCS_8_ST              0xe030\n#define  _TEMPOCS_16_MONO           0xe031\n#define  _TEMPOCS_16_ST             0xe032\n#define  _WAVEJAMMERCD_8_MONO       0xe033\n#define  _WAVEJAMMERCD_8_ST         0xe034\n#define  _WAVEJAMMERCD_16_MONO      0xe035\n#define  _WAVEJAMMERCD_16_ST        0xe036\n#define  _SOUND_BLASTER_8_MONO_R    0xe050\n#define  _MICROSOFT_8_MONO_R        0xe051\n#define  _SOUND_MASTER_II_8_MONO_R  0xe052\n#define  _ADLIB_GOLD_8_MONO_R       0xe053\n#define  _MV_PAS_8_MONO_R           0xe054\n#define  _RAP10_8_MONO_R            0xe058\n#define  _RAP10_16_MONO_R           0xe059\n#define  _SB16_8_MONO_R             0xe05a\n#define  _SB16_8_ST_R               0xe05b\n#define  _SB16_16_MONO_R            0xe05c\n#define  _SB16_16_ST_R              0xe05d\n#define  _MV_PAS_16_MONO_R          0xe060\n#define  _SOUNDSCAPE_8_MONO_R       0xe061\n#define  _SOUNDSCAPE_8_ST_R         0xe062\n#define  _SOUNDSCAPE_16_MONO_R      0xe063\n#define  _SOUNDSCAPE_16_ST_R        0xe064\n#define  _ESS_AUDIODRIVE_8_MONO_R   0xe065\n#define  _ESS_AUDIODRIVE_8_ST_R     0xe066\n#define  _ESS_AUDIODRIVE_16_MONO_R  0xe067\n#define  _ESS_AUDIODRIVE_16_ST_R    0xe068\n#define  _SPEECH_THING_8_MONO       0xe090\n#define  _YAMAHA_8_MONO             0xe106\n#define  _INT_SPEAKER_8_MONO        0xe107\n\n// call indexes for the loadable drivers\nenum\n{ \n   _DRV_INIT,\n   _DRV_UNINIT,\n   _DRV_SETRATE,\n   _DRV_SETACTION,\n   _DRV_START,\n   _DRV_STOP,\n   _DRV_PAUSE,\n   _DRV_RESUME,\n   _DRV_CAPABILITIES,\n   _DRV_PLAY_FOREGROUND,\n   _DRV_GET_FILL_INFO, \n   _DRV_GET_CALL_FUNCTIONS,\n   _DRV_SET_CALL_FUNCTIONS\n};\n\n// fill info\ntypedef  struct   _tagFillInfo\n         {\n\n            LPSTR lpFillHandler;                   // pointer to fill handler\n            LPWORD lpDMAFillCount;                 // pointer to dma count\n            LPSTR lpSampleList;                    // pointer to sample list\n            LPWORD lpDMAMasterVolume;              // pointer to dma count\n\n         } _SOS_FILL_INFO;\n\n// caps info structure\ntypedef  struct   _tagCapsInfo\n         {\n\n            LPSTR    lpPortList;                   // pointer to port list\n            LPSTR    lpDMAList;                    // pointer to DMA list\n            LPSTR    lpIRQList;                    // pointer to IRQ list\n            LPSTR    lpRateList;                   // pointer to rate list\n\n         } _SOS_CAPS_INFO;\n\n// maximum number of available voice\n#define  _MAX_VOICES    32\n\n// structure definition\ntypedef  struct   _tagSAMPLE\n{\n   LPSTR    samplePtr;                 // pointer to data buffer\n   LPSTR    sampleData;                // pointer to active data\n   LPSTR    sampleLoopPtr;             // pointer for loop back\n\n   WORD     sampleLength;              // length of sample\n   WORD     sampleIndex;               // index into sample\n   WORD     sampleLoopLength;          // length of loop\n   \n   WORD     sampleBytesLeft;           // bytes left to play in sample\n\n   WORD     sampleLoopPoint;           // byte count for loop point\n   WORD     sampleLoopEndLength;       // length of remaining chunk\n\n   short    sampleFlags;               // control sample\n   short    sampleVolume;              // volume control\n   short    sampleID;                  // sample ID\n\n   short    sampleChannel;             // channel to play sample on\n   short    sampleLoopCount;           // loop count\n   short    sampleLastFill;            // last fill position\n   VOID ( far cdecl * sampleCallback )( WORD, WORD, WORD ); // callback function for sample\n\n   WORD     samplePitchAdd;\n   short    samplePitchFraction;\n\n   short    samplePort;                // port to use for non-dma digitized\n\n   WORD     sampleTotalBytes;\n   WORD     sampleByteLength;\n\n   short    samplePanLocation;\n   short    samplePanSpeed;\n   short    samplePanDirection;\n   short    samplePanStart;\n   short    samplePanEnd;\n   \n   short    sampleDelayBytes;\n   short    sampleDelayRepeat;\n   \n   WORD     sampleADPCMPredicted;\n   short    sampleADPCMIndex;\n\n   short    sampleRootNoteMIDI;   \n\n   WORD  sampleTemp1;   \n   \n} _SOS_SAMPLE;\n\n// enumeration for left or right channel\nenum\n{\n   _LEFT_CHANNEL,\n   _RIGHT_CHANNEL,\n   _CENTER_CHANNEL,\n   _INTERLEAVED\n};\n\n// enumeration for foreground and background\nenum\n{ \n   _FOREGROUND,\n   _BACKGROUND \n};\n\n// defines for the sample flags\n#define  _ACTIVE           0x8000\n#define  _LOOPING          0x4000\n#define  _FIRST_TIME       0x2000\n#define  _PENDING_RELEASE  0x1000\n#define  _CONTINUE_BLOCK   0x0800\n#define  _PITCH_SHIFT      0x0400\n#define  _PANNING          0x0200\n#define  _VOLUME           0x0100\n#define  _TRANSLATE16TO8   0x0080\n#define  _STAGE_LOOP       0x0040\n#define  _TRANSLATE8TO16   0x0020\n#define  _STEREOTOMONO     0x0010\n\n// defines for the wParam flags \n#define  _SINGLE_SAMPLE 0x01\n\n#define  _SOS_DCAPS_AUTO_REINIT     0x01\n#define  _SOS_DCAPS_MPU_401         0x02\n#define  _SOS_DCAPS_OPL2            0x04\n#define  _SOS_DCAPS_OPL3            0x08\n#define  _SOS_DCAPS_OPL4            0x10\n#define  _SOS_DCAPS_WAVETABLE       0x20\n#define  _SOS_DCAPS_DL_SAMPLES      0x40\n#define  _SOS_DCAPS_FIFO_DEVICE     0x80\n#define  _SOS_DCAPS_ENV_NEEDED      0x100\n#define  _SOS_DCAPS_PSEUDO_DMA1     0x200\n#define  _SOS_DCAPS_SIGNED_DATA     0x8000\n\n// file header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // number of drivers in the file\n   WORD  wDrivers;\n\n   // offset of first driver\n   WORD  lOffset;\n\n   // size of the file\n   WORD  lFileSize;\n\n} _FILEHEADER;\n\n// driver header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // offset of next driver\n   WORD  lNextDriver;\n\n   // size of current driver\n   WORD  wSize;\n\n   // id for the current device\n   WORD  wDeviceID;\n\n   // id for the type of DOS extender\n   WORD  wExtenderType;\n\n} _DRIVERHEADER;\n\n// device hardware information\ntypedef struct\n{\n   // port to be used\n   WORD  wPort;\n\n   // irq to use\n   WORD  wIRQ;\n\n   // dma channel to se\n   WORD  wDMA; \n  \n   // extra parameter\n   WORD  wParam;\n\n} _SOS_HARDWARE;\n\n// structure definition for start sample\ntypedef struct\n{\n   // pointer to sample\n   LPSTR lpSamplePtr;\n\n   // size of the sample\n   WORD  dwSampleSize;\n\n   // number of times to loop the sample -1 is infinite\n   WORD  wLoopCount;\n\n   // channel to play sample on\n   WORD  wChannel;\n\n   // volume to play sample at\n   WORD wVolume;\n\n   // id for the sample\n   WORD  wSampleID;\n\n   // far pointer to the callback function\n   VOID ( far cdecl *lpCallback )( WORD, WORD, WORD );\n\n   // port to use if driver is a non-dma background driver\n   WORD  wSamplePort; \n\n   // flags field\n   WORD  wSampleFlags;\n\n   // total length of sample including loops, etc..\n   WORD     dwSampleByteLength;\n\n   // loop point for the sample\n   WORD  dwSampleLoopPoint;\n   WORD  dwSampleLoopLength;\n\n   // pitch shifting components \n   WORD     dwSamplePitchAdd;\n   WORD    wSamplePitchFraction;\n\n   // pan components\n   WORD    wSamplePanLocation;\n   WORD    wSamplePanSpeed;\n   WORD    wSamplePanDirection;\n   WORD    wSamplePanStart;\n   WORD    wSamplePanEnd;\n   \n   // delay parts\n   WORD    wSampleDelayBytes;\n   WORD    wSampleDelayRepeat;\n\n   // compression components   \n   WORD     dwSampleADPCMPredicted;\n   WORD    wSampleADPCMIndex;\n\n   // root note for pitch shifting \n   WORD    wSampleRootNoteMIDI;   \n\n   // filler for future upgrades\n   WORD  dwSampleTemp1;   \n   WORD  dwSampleTemp2;   \n   WORD  dwSampleTemp3;   \n\n} _SOS_START_SAMPLE;\n\n// structure for initializing a driver\ntypedef struct\n{  \n   WORD  wBufferSize;\n   LPSTR lpBuffer;\n   BOOL  wAllocateBuffer;\n   WORD  wSampleRate;\n   WORD  wParam;\n   LONG  dwParam;\n   VOID ( far *lpFillHandler )( VOID );\n   LPSTR lpDriverMemory;\n   LPSTR lpDriverMemoryCS;\n   LPSTR lpTimerMemory;\n   LPSTR lpTimerMemoryCS;\n   WORD  wTimerID;\n   WORD  wPhysical;\n\n} _SOS_INIT_DRIVER;\n\n// define for the timer types to use\n#define  _SOS_NORMAL_TIMER          0x00\n\n// enumeration for the timer types\nenum\n{\n   _TIMER_8_MONO   =     0x1000,\n   _TIMER_8_ST,          \n   _TIMER_16_MONO,       \n   _TIMER_16_ST,         \n   _TIMER_8_MONO_ULAW,  \n   _TIMER_8_ST_ULAW,    \n   _TIMER_16_MONO_ULAW, \n   _TIMER_16_ST_ULAW,   \n   _TIMER_8_MONO_REC,   \n   _TIMER_8_MONO_ULAW_REC,\n   _TIMER_UNDEFINED_1,      \n   _TIMER_UNDEFINED_2,\n   _TIMER_UNDEFINED_3,\n   _TIMER_UNDEFINED_4,\n   _TIMER_UNDEFINED_5,\n   _TIMER_UNDEFINED_6,\n   _TIMER_UNDEFINED_7,\n   _TIMER_UNDEFINED_8,\n   _TIMER_UNDEFINED_9,\n   _TIMER_UNDEFINED_A,\n   _TIMER_UNDEFINED_B,\n   _TIMER_UNDEFINED_C,\n   _TIMER_UNDEFINED_D,\n   _TIMER_UNDEFINED_E,\n   _TIMER_UNDEFINED_F,\n   _TIMER_UNDEFINED_10,\n   _TIMER_UNDEFINED_11,\n   _TIMER_UNDEFINED_12,\n   _TIMER_UNDEFINED_13,\n   _TIMER_UNDEFINED_14,\n   _TIMER_UNDEFINED_15,\n   _TIMER_UNDEFINED_16,\n   _TIMER_8_SOUND_SOURCE,\n   _TIMER_8_SOUND_SOURCE_TANDY,\n   _TIMER_8_GENERAL_PORT,\n   _TIMER_8_GENERAL_PORT_REC   \n};\n\n// define for no slots available\n#define  _ERR_NO_SLOTS ( WORD )-1\n\n// error codes for the system\nenum\n{\n   _ERR_NO_ERROR,\n   _ERR_DRIVER_NOT_LOADED,\n   _ERR_INVALID_POINTER,\n   _ERR_DETECT_INITIALIZED,\n   _ERR_FAIL_ON_FILE_OPEN,\n   _ERR_MEMORY_FAIL,\n   _ERR_INVALID_DRIVER_ID,\n   _ERR_NO_DRIVER_FOUND,\n   _ERR_DETECTION_FAILURE,\n   _ERR_DRIVER_LOADED,\n   _ERR_INVALID_HANDLE,\n   _ERR_NO_HANDLES,\n   _ERR_PAUSED,   \n   _ERR_NOT_PAUSED,\n   _ERR_INVALID_DATA,\n   _ERR_DRV_FILE_FAIL,\n   _ERR_INVALID_PORT,\n   _ERR_INVALID_IRQ,\n   _ERR_INVALID_DMA,\n   _ERR_INVALID_DMA_IRQ\n};   \n\n// maximum number of timer events that can be registered \n#define  _TIMER_MAX_EVENTS    0x10  \n\n// flags for the debugging system\n#define  _SOS_DEBUG_NORMAL       0x0000\n#define  _SOS_DEBUG_NO_TIMER     0x0001\n#define  _SOS_TIMER_DPMI         0x0002\n\n// define for types of DOS extenders\n#define  _SOS_RATIONAL           0x8000\n#define  _SOS_FLASHTECK          0x4000\n\n// defines for the types of timers for different\n// dos extenders\n#define  _SOS_TIMER_NEAR         0x8000\n#define  _SOS_TIMER_FAR          0x4000\n \n// values for callback information\nenum\n{\n   _SAMPLE_PROCESSED,\n   _SAMPLE_LOOPING,\n   _SAMPLE_DONE\n};\n\n// define for special 18.2 callback rate to dos\n#define  _TIMER_DOS_RATE   0xff00\n\n#pragma pack()\n\n#pragma aux int_3 = \"int 3\"\n \n#pragma pack( 1 ) \ntypedef struct\n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned       segment;\n\tunsigned short\tnumber_available;\n\tunsigned short number_used;\n\tunsigned       page0;\n\n} EVDS_STRUCT;\n\ntypedef struct \n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned short segment;\n\tunsigned short\tID;\n\tunsigned       physical;\n\n} VDS_STRUCT;\n\n#pragma pack() \n\n#include \"sosdata.h\"\n#include \"sosfnct.h\"\n\n#endif\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQA32/SOSDATA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdata.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DATA\n#define  _SOS_DATA\n\n#include <stddef.h>\n\n#pragma pack(4) \nextern   WORD     _sosDIGIData_Start;\nextern   WORD     _sosDIGIData_End;\nextern   WORD     _wSOSDriverLinear[];\nextern   WORD     _wSOSTimerLinear[];\nextern   LPSTR    _lpSOSDriver[];\nextern   LPSTR    _lpSOSTimer[];\nextern   LPSTR    _lpSOSDriverCS[];\nextern   LPSTR    _lpSOSTimerCS[];\nextern   BOOL     _wSOSDriverLoaded[];\nextern   BOOL     _wSOSTimerLoaded[];\nextern   BOOL     _wSOSDriverInitialized[];\nextern   WORD     _wSOSOutputRate[];\nextern   WORD     _wSOSDMABuffersize[];\nextern   LONG     _dwSOSDMABufferPhysical[];\nextern   LPSTR    _lpSOSDMABuffer[];\nextern   BOOL     _wTimerUsed;\nextern   VOID ( far *_lpSOSFillHandler[] )( VOID );\nextern   WORD     _wSOSTimerType[];\nextern   WORD     _wSOSDriverType[];\nextern   _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ];\nextern   LPWORD      _lpSOSDMAIrqCount[];\nextern   LPWORD      _lpSOSDMAFillCount[];\nextern   WORD        _wSOSTmrNextCount;\nextern   VOID ( interrupt far *_lpSOSOldTimer )( VOID );\nextern   WORD     _wSOSDriverID[];\nextern   _SOS_CAPABILITIES _sSOSDriverCaps[];\nextern   WORD        _wSOSDMAPortList[];\nextern   BYTE        _bSOSDMAChannel[];\nextern   _SOS_INIT_DRIVER     _sSOSDIGIInitDriver[];\nextern   BYTE  _pSOSDriverPath[];\nextern   BYTE  _pSOSTempDriverPath[];\nextern   BOOL  _wTIMERUsed;\nextern   WORD  _wTIMERValue;\nextern   VOID ( far * _lpTIMEREvents[] )( VOID );\nextern   WORD _wTIMEREventRate[];\nextern   WORD _dwTIMEREventFraction[];\nextern   WORD _dwTIMEREventFractionCurrent[];\nextern   BYTE  _bSOSMIDITimerSongHandler[];\nextern   BYTE  _bSOSMIDISongHandle;\nextern   WORD  _wSOSTimerMemHandle[];\nextern   WORD  _wSOSDriverMemHandle[];\nextern   WORD  _wSOSRealSeg[];\n\nextern   _FILEHEADER    _sDETFileHeader;\nextern   _DRIVERHEADER  _sDETDriverHeader;\nextern   _FILEHEADER    sLOADFileHeader;\nextern   _DRIVERHEADER  sLOADDriverHeader;\nextern   BOOL           _wDETInitialized;\nextern   WORD           _wDETLinear;\nextern   LPSTR          _lpDETDriverBuffer;    \nextern   LPSTR          _lpDETDriverBufferCS;\nextern   WORD           _hDETFile;\nextern   DWORD          _dwDETDriverIndex;\nextern   WORD           _wDETDriverIndexCur;\nextern   WORD           _wDETMemHandle;\nextern   LPSOSDEVICECAPS _lpDETDeviceCaps;\nextern   _SOS_CAPABILITIES _sDETCaps;  \nextern   PSTR _pSOSErrorStrings[];\nextern   BOOL _wSOSBufferAllocated[];\nextern   BOOL _wSOSSystemInitialized;\nextern   VDS_STRUCT _sSOSVDSInfo;\nextern   _SOS_FILL_INFO _sSOSFillInfo;\nextern   WORD    _wSOSTimerEventIndex;\nextern   WORD  _wSOSTimerEntered;\nextern   WORD  _wSOSDriverSize[];\nextern   WORD  _wSOSTimerSize[];\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nextern   WORD  _sosDIGIData1_Start;\nextern   WORD  _sosDIGIData1_End;\nextern   WORD  _sosDIGIData2_Start;\nextern   WORD  _sosDIGIData2_End;\nextern   BYTE  _bTIMERInstalled;\nextern   BYTE  _bTIMERDPMI;\nextern   WORD  wDetectPort;\nextern   WORD  wDetectIRQ;\nextern   WORD  wDetectDMA;\nextern   WORD  wDetectParam;\n#ifdef __cplusplus\n}\n#endif \n\n#pragma pack()\n\n#endif\n\u001a\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQA32/SOSDEFS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdefs.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n\n#ifndef  _SOSDEFS_DEFINED\n#define  _SOSDEFS_DEFINED\n\n#undef   _TRUE\n#undef   _FALSE\n#undef   _NULL\nenum  \n      { \n         _FALSE, \n         _TRUE \n      };\n\n#define  _NULL  0\n\n#ifndef  VOID\n#define  VOID           void\n#endif\ntypedef  int            BOOL;\ntypedef  unsigned int   UINT;\ntypedef  unsigned char  BYTE;\ntypedef  unsigned       WORD;\n#ifndef  LONG\ntypedef  signed long    LONG;\n#endif\ntypedef  unsigned long  DWORD;\n\ntypedef  BYTE  *        PBYTE;\ntypedef  char near *    PSTR;\ntypedef  WORD  *        PWORD;\ntypedef  LONG  *        PLONG;\ntypedef  VOID  *        PVOID;\n\ntypedef  BYTE  far   *  LPBYTE;\ntypedef  BYTE  far   *  LPSTR;\ntypedef  WORD  far   *  LPWORD;\ntypedef  LONG  far   *  LPLONG;\ntypedef  VOID  far   *  LPVOID;\n\ntypedef  BYTE  huge  *  HPBYTE;\ntypedef  BYTE  huge  *  HPSTR;\ntypedef  WORD  huge  *  HPWORD;\ntypedef  LONG  huge  *  HPLONG;\ntypedef  VOID  huge  *  HPVOID;\n\ntypedef  unsigned       HANDLE;\n\n#endif\n\u001a\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQA32/SOSFNCT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosfnct.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_FUNCTIONS\n#define  _SOS_FUNCTIONS\n\n#pragma pack(4)\n\nWORD sosDIGILockMemory          (  VOID  );\nWORD sosDIGIUnLockMemory        (  VOID  );\nWORD sosDIGIInitSystem           (  LPSTR, WORD  );\nWORD sosDIGIUnInitSystem         (  VOID  );\nWORD sosDIGIInitDriver           (  WORD, _SOS_HARDWARE far *,\n                                    _SOS_INIT_DRIVER far *, WORD far *   );\nWORD sosDIGIUnInitDriver         (  WORD, BOOL, BOOL  );\nWORD sosDIGILoadDriver          (  WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD sosDIGIUnLoadDriver         (  WORD  );\nWORD sosDIGIGetDeviceCaps        (  WORD, LPSOSDEVICECAPS  );\n\n#ifdef PHARLAP\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#else\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#endif\n\nWORD sosDIGIStopSample           (  WORD, WORD  );\nWORD sosDIGISamplesPlaying       (  WORD  );\nBOOL sosDIGISampleDone           (  WORD, WORD  );\nBOOL sosDIGISampleFilling        (  WORD, WORD  );\nWORD sosDIGIStartSample          (  WORD, _SOS_START_SAMPLE far *  );\nWORD sosDIGIContinueSample       (  WORD, WORD, _SOS_START_SAMPLE far * );\n\n\nWORD  sosDIGIDetectInit          (  LPSTR  );\nWORD  sosDIGIDetectUnInit        (  VOID  );\nWORD  sosDIGIDetectFindHardware  (  WORD, _SOS_CAPABILITIES far *, WORD far * );\nWORD  sosDIGIDetectFindFirst     (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectFindNext      (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectGetSettings   (  _SOS_HARDWARE far *  );\nWORD  sosDIGIDetectGetCaps       (  WORD, _SOS_CAPABILITIES far *  );\nWORD  sosDIGIDetectVerifySettings(  _SOS_HARDWARE far *  );\nPSTR  sosGetErrorString          (  WORD  );\n\nWORD  sosDIGILoadTimer           (  WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD  sosDIGIUnLoadTimer         (  WORD  );\n\nWORD  sosTIMERRegisterEvent      ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle );\nWORD  sosTIMERInitSystem               (  WORD, WORD  );\nWORD  sosTIMERUnInitSystem             (  WORD  );\nWORD  sosTIMERSetRate                  (  WORD  );  \nWORD  sosTIMERRemoveEvent              (  WORD );\nWORD  sosTIMERAlterEventRate           (  WORD, WORD  );\nWORD  sosTIMERGetEventRate             (  WORD  );\nVOID far sosTIMEROldHandler            (  VOID  );\nVOID far sosTIMERHandler               (  VOID  );\n\n// functions in soscntl.c\nWORD  sosDIGISetSampleVolume     ( WORD, WORD, WORD );\nWORD  sosDIGIGetSampleVolume     ( WORD, WORD );\nWORD  sosDIGISetChannel          ( WORD, WORD, WORD );\nWORD  sosDIGIGetChannel          ( WORD, WORD );\nWORD  sosDIGIGetBytesProcessed   ( WORD, WORD );\nWORD  sosDIGIGetLoopCount        ( WORD, WORD );\nWORD  sosDIGISetPanLocation      ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanLocation      ( WORD, WORD );\nDWORD sosDIGISetPitch            ( WORD, WORD, DWORD );\nDWORD sosDIGIGetPitch            ( WORD, WORD );\nWORD  sosDIGIGetDMAPosition      ( WORD );\nWORD  sosDIGISetPanSpeed         ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanSpeed         ( WORD, WORD );\nWORD  sosDIGIGetSampleID         ( WORD, WORD );\nWORD  sosDIGIGetSampleHandle     ( WORD, WORD );\nWORD  sosDIGISetMasterVolume     ( WORD, WORD );\n#ifdef PHARLAP\nVOID  sosFreeVDSPage          ( unsigned short, unsigned short, DWORD );\nWORD  sosAllocVDSPage         ( unsigned short *, unsigned short *, DWORD * );\n#else\nWORD  sosAllocVDSPage            ( LPSTR *, WORD *, WORD * );\nVOID  sosFreeVDSPage             ( WORD, WORD, LONG );\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef PHARLAP\nextern   int   cdecl sosRealFree          ( int );\nextern   BOOL  cdecl  _sos_read( WORD, LPSTR, WORD, WORD * );\nextern   int   cdecl sosRealAlloc( int, int *, int * );\nextern   void  cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD );\nextern   int   cdecl sosGetCS( VOID );\nextern   int   cdecl sosGetES( VOID );\n#else\nextern   int   cdecl sosRealAlloc         ( int, int *, int * );\nextern   int   cdecl sosRealFree          ( int );\n#endif\n\n// sos driver functions\nextern   WORD  cdecl sosDRVLockMemory     ( DWORD, DWORD );\nextern   WORD  cdecl sosDRVUnLockMemory   ( DWORD, DWORD );\nextern   void  cdecl sosDRVGetCapsInfo    ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVGetCapsPtr     ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVInit           ( LPSTR, LPSTR, int, int, int, int, int, int );  \nextern   void  cdecl sosDRVStart          ( LPSTR, LPSTR, int, int );\nextern   void  cdecl sosDRVSetRate        ( LPSTR, LPSTR, int );\nextern   void  cdecl sosDRVSetAction      ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVStop           ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVUnInit         ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVGetFillInfo    ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * );\nextern   void  cdecl sosFillSampleStructs ( PSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVExist       ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVGetSettings ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR );\nextern   WORD  cdecl sosDIGIInitForWindows( WORD );\nextern   WORD  cdecl sosDIGIUnInitForWindows( WORD );\nextern   LPSTR cdecl sosAllocateFarMem      ( WORD, PSTR, WORD * );\nextern   LPSTR cdecl sosCreateAliasCS       ( LPSTR );\nextern   VOID  cdecl sosFreeSelector        ( LPSTR, DWORD );\nextern   LPSTR cdecl sosMAKEDOSPtr          ( PSTR );\nextern   VOID  cdecl sosDetDRVSetEnvString  ( DWORD, PSTR );\nextern   PSTR  cdecl sosDetDRVGetEnvString  ( DWORD );\nextern   VOID  cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR );\nextern   VOID  cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR );\nextern   WORD  cdecl sosDRVGetFreeMemory     ( VOID );\nextern   WORD  cdecl sosDRVAllocVDSStruct    ( WORD, WORD *, WORD * );\nextern   WORD  cdecl sosDRVFreeVDSStruct     ( WORD, WORD );\nextern   WORD  cdecl sosDRVIsWindowsActive   ( VOID );\nextern   WORD  cdecl sosDRVVDSGetBuffer    ( WORD );\nextern   WORD  cdecl sosDRVVDSFreeBuffer   ( WORD );\nextern   WORD  cdecl getDS( VOID );\nextern   WORD  cdecl sosDRVMakeDMASelector   ( WORD );  \nextern   WORD  cdecl sosDRVFreeDMASelector   ( WORD );  \n\n\nextern   void  cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) );\nextern   void  cdecl sosTIMERDRVUnInit( void );\nextern   void  cdecl sosTIMERDRVHandler( void );\nextern   void  cdecl sosTIMERDRVFHandler( void );\nextern   void  cdecl sosTIMERDRVEnable( void );\nextern   void  cdecl sosTIMERDRVDisable( void );\nextern   void  cdecl sosTIMERDRVCallOld( void );\nextern   void  cdecl sosTIMERDRVSetRate( WORD );    \nextern   void  cdecl sosDIGITimer_Start( void );\nextern   void  cdecl sosDIGITimer_End( void );\nextern   void  cdecl sosDIGIDrv_Start( void );\nextern   void  cdecl sosDIGIDrv_End( void );\n#ifdef __cplusplus\n}\n#endif \n\n// external functions for handling system initialization and \n// uninitialization\nWORD  sosEXDIGInitDriver               (  WORD, WORD, WORD, LPSTR,\n                                          _SOS_HARDWARE far *, WORD *  );\nWORD  sosEXDIGIUnInitDriver            (  VOID  );\n\nWORD  sosEXDETFindDriver               (  WORD, LPSTR, _SOS_HARDWARE far *,\n                                          _SOS_CAPABILITIES far *  );\n\n// memory locking prototypes\nVOID  sosDIGICaps_Start( VOID );\nVOID  sosDIGICaps_End( VOID );\nVOID  sosDIGIErr_Start( VOID );\nVOID  sosDIGIErr_End( VOID );\nVOID  sosDIGITmr_Start( VOID );\nVOID  sosDIGITmr_End( VOID );\nVOID  sosDIGIStart_Start( VOID );\nVOID  sosDIGIStart_End( VOID );\nVOID  sosDIGIPlyng_Start( VOID );\nVOID  sosDIGIPlyng_End( VOID );\nVOID  sosDIGIRate_Start( VOID );\nVOID  sosDIGIRate_End( VOID );\nVOID  sosDIGIDone_Start( VOID );\nVOID  sosDIGIDone_End( VOID );\nVOID  sosDIGIDetec_Start( VOID );\nVOID  sosDIGIDetec_End( VOID );\nVOID  sosDIGIInit_Start( VOID );\nVOID  sosDIGIInit_End( VOID );\nVOID  sosDIGILoad_Start( VOID );\nVOID  sosDIGILoad_End( VOID );\nVOID  sosDIGICntl_Start( VOID );\nVOID  sosDIGICntl_End( VOID );\n\n#pragma pack()\n\n#endif\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQA32/SOSRES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosres.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#define  _SOS_RESOURCE\n#ifndef  _SOS_RESOURCE\n#define  _SOS_RESOURCE\n\n// structure for resource file header\ntypedef struct\n{\n   // file version\n   WORD     wVersion;\n\n   // file size\n   LONG     dwFileSize;\n\n   // number of resources in file\n   WORD     wResCount;\n\n   // offset of resource data from top of file\n   LONG     dwResOffset;\n\n   // offset of sync track from top of file\n   LONG     dwSyncTrackOffset;\n\n}  _RES_FILE_HEADER;\n\n// structure for resource block header\ntypedef struct\n{\n   // resource id\n   WORD     wID;\n\n   // resource type\n   WORD     wResType;\n\n   // offset of next block\n   LONG     dwNextBlock; \n\n   // size of the current resource information\n   LONG     dwResSize;\n\n   // rate to play block at\n   WORD     wBlockRate;\n\n   // id for the sync track to use\n   WORD     wSyncTrackID;\n\n}  _RES_BLOCK_HEADER;\n\n// structure for sync mark tag\ntypedef struct _tagSYNCMARK\n{\n   // ID of the type of mark being used\n   WORD  wID;\n\n   // location in data of sync mark\n   LONG  dwSyncOffset;\n\n   // length of sync block\n   LONG  dwSyncSize;\n\n   // start sample data\n   _SOS_START_SAMPLE sampleData;\n    \n} _RES_SYNCMARK;\n\ntypedef union\n{\n   // structure for sync mark tag\n   _RES_SYNCMARK  syncMark; \n\n} _RES_TAG;\n\n// union for filter information for prepareWave\ntypedef union\n{\n   // filter type\n   WORD     wFilterID;\n\n   // structure for volume\n   struct   volume \n   {\n      WORD  wVolume;\n   };\n\n   // structure for delay\n   struct   delay\n   {  \n      WORD  wDelaySamples;\n   };\n\n} _SOS_FILTER; \n\n \n#endif\n\n\u001a"
  },
  {
    "path": "WINVQ/INCLUDE/VQA32/UNVQ.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAUNVQ_H\n#define VQAUNVQ_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQAPlay32 library. (32-Bit protected mode)\n*\n* FILE\n*     unvq.h\n*\n* DESCRIPTION\n*     VQ frame decompress definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Feburary 8, 1995\n*\n****************************************************************************/\n\n#ifdef PHARLAP_TNT\n#include <pltypes.h>\n#endif\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* unvqbuff.asm */\n#ifndef PHARLAP_TNT\nvoid __cdecl UnVQ_2x2(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\nvoid __cdecl UnVQ_2x3(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\nvoid __cdecl UnVQ_4x2(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\nvoid __cdecl UnVQ_4x4(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\nvoid __cdecl UnVQ_4x2_Woofer(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\n/* unvqvesa.asm */\nvoid __cdecl UnVQ_4x2_VESA320_32K(unsigned char *codebook,\n\t\tunsigned char *pointers, unsigned char *palette,\n\t\tunsigned long grains_per_win,unsigned long dummy1,unsigned long dummy2);\n\n#else /* PHARLAP_TNT */\n\nvoid __cdecl UnVQ_2x2(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n\nvoid __cdecl UnVQ_2x3(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n\nvoid __cdecl UnVQ_4x2(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n\nvoid __cdecl UnVQ_4x4(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n\n/* unvqvesa.asm */\nvoid __cdecl UnVQ_4x2_VESA320_32K(unsigned char *codebook,\n\t\tunsigned char *pointers, FARPTR palette, unsigned long grains_per_win,\n\t\tunsigned long dummy1, unsigned long dummy2);\n\n#endif /* PHARLAP_TNT */\n\n/* unvqxmde.asm */\nvoid __cdecl UnVQ_4x2_Xmode(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long dummy);\n\nvoid __cdecl UnVQ_4x2_XmodeCB(unsigned char *cbdummy, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long dummy);\n\nvoid __cdecl Upload_4x2CB(unsigned char *codebook, unsigned long numentries);\nvoid __cdecl XlatePointers(unsigned char *pointers, unsigned long numpointers);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQAUNVQ_H */\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQA32/VQAFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAFILE_H\n#define VQAFILE_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqafile.h\n*\n* DESCRIPTION\n*     VQA file format definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 10, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\iff.h>\n\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n\n/*---------------------------------------------------------------------------\n * STRUCTURE DEFINITIONS AND RELATED DEFINES.\n *-------------------------------------------------------------------------*/\n\n/* VQAHeader: VQA movie description header. (VQHD)\n *\n * Version       - VQA version.\n * Flags         - Various flags. (See below)\n * ImageWidth    - Image width in pixels.\n * ImageHeight   - Image height in pixels.\n * BlockWidth    - Block width in pixels.\n * BlockHeight   - Block height in pixels.\n * Frames        - Total number of frames in the movie.\n * FPS           - Playback rate (Frame Per Second).\n * Groupsize     - Frame grouping size (frames per codebook).\n * Num1Colors    - Number of 1 color colors.\n * CBentries     - Number of codebook entries.\n * Xpos          - X position to draw frames. (-1 = Center)\n * Ypos          - Y position to draw frames. (-1 = Center)\n * MaxFramesize  - Size of largest frame.\n * SampleRate    - Sample rate of primary audio stream.\n * Channels      - Number of channels in primary audio stream.\n * BitsPerSample - Sample bit size in primary audio stream.\n * FutureUse     - Reserved for future expansion.\n */\ntypedef struct _VQAHeader {\n\tunsigned short Version;\n\tunsigned short Flags;\n\tunsigned short Frames;\n\tunsigned short ImageWidth;\n\tunsigned short ImageHeight;\n\tunsigned char  BlockWidth;\n\tunsigned char  BlockHeight;\n\tunsigned char  FPS;\n\tunsigned char  Groupsize;\n\tunsigned short Num1Colors;\n\tunsigned short CBentries;\n\tunsigned short Xpos;\n\tunsigned short Ypos;\n\tunsigned short MaxFramesize;\n\tunsigned short SampleRate;\n\tunsigned char  Channels;\n\tunsigned char  BitsPerSample;\n\tunsigned short AltSampleRate;\n\tunsigned char  AltChannels;\n\tunsigned char  AltBitsPerSample;\n\tunsigned short FutureUse[5];\n} VQAHeader;\n\n/* Version type. */\n#define VQAHD_VER1 1\n#define VQAHD_VER2 2\n\n/* VQA header flag definitions */\n#define VQAHDB_AUDIO    0 /* Audio track present. */\n#define VQAHDB_ALTAUDIO 1 /* Alternate audio track present. */\n#define VQAHDF_AUDIO    (1<<VQAHDB_AUDIO)\n#define VQAHDF_ALTAUDIO (1<<VQAHDB_ALTAUDIO)\n\n\n/* Frame information (FINF) chunk definitions\n *\n * The FINF chunk contains a longword (4 bytes) entry for each\n * frame in the movie. This entry is divided into two parts,\n * flags (4 bits) and offset (28 bits).\n *\n * BITS   NAME     DESCRIPTION\n * -----------------------------------------------------------\n * 31-28  Flags    4 bitwise boolean flags.\n * 27-0   Offset   Offset in WORDS from the start of the file.\n */\n#define VQAFINB_KEY  31\n#define VQAFINB_PAL  30\n#define VQAFINB_SYNC 29\n#define VQAFINF_KEY  (1L<<VQAFINB_KEY)\n#define VQAFINF_PAL  (1L<<VQAFINB_PAL)\n#define VQAFINF_SYNC (1L<<VQAFINB_SYNC)\n\n/* FINF related defines and macros. */\n#define VQAFINF_OFFSET 0x0FFFFFFFL\n#define VQAFINF_FLAGS  0xF0000000L\n#define VQAFRAME_OFFSET(a) (((a & VQAFINF_OFFSET)<<1))\n\n/* VQ vector pointer codes. */\n#define VPC_ONE_SINGLE    0xF000 /* One single color block */\n#define VPC_ONE_SEMITRANS 0xE000 /* One semitransparent block */\n#define VPC_SHORT_DUMP    0xD000 /* Short dump of single color blocks */\n#define VPC_LONG_DUMP     0xC000 /* Long dump of single color blocks */\n#define VPC_SHORT_RUN     0xB000 /* Short run of single color blocks */\n#define VPC_LONG_RUN      0xA000 /* Long run */\n\n/* Long run codes. */\n#define LRC_SEMITRANS 0xC000 /* Long run of semitransparent blocks. */\n#define LRC_SINGLE    0x8000 /* Long run of single color blocks. */\n\n/* Defines used for Run-Skip-Dump compression. */\n#define MIN_SHORT_RUN_LENGTH  2\n#define MAX_SHORT_RUN_LENGTH  15\n#define MIN_LONG_RUN_LENGTH   2\n#define MAX_LONG_RUN_LENGTH   4095\n#define MIN_SHORT_DUMP_LENGTH 3\n#define MAX_SHORT_DUMP_LENGTH 15\n#define MIN_LONG_DUMP_LENGTH  2\n#define MAX_LONG_DUMP_LENGTH  4095\n\n#define WORD_HI_BIT 0x8000\n\n/*---------------------------------------------------------------------------\n * VQA FILE CHUNK ID DEFINITIONS.\n *-------------------------------------------------------------------------*/\n\n#define ID_WVQA MAKE_ID('W','V','Q','A') /* Westwood VQ Animation form. */\n#define ID_VQHD MAKE_ID('V','Q','H','D') /* VQ header. */\n#define ID_NAME MAKE_ID('N','A','M','E') /* Name string. */\n#define ID_FINF MAKE_ID('F','I','N','F') /* Frame information. */\n#define ID_VQFR MAKE_ID('V','Q','F','R') /* VQ frame container. */\n#define ID_VQFK MAKE_ID('V','Q','F','K') /* VQ key frame container. */\n#define ID_CBF0 MAKE_ID('C','B','F','0') /* Full codebook. */\n#define ID_CBFZ MAKE_ID('C','B','F','Z') /* Full codebook (compressed). */\n#define ID_CBP0 MAKE_ID('C','B','P','0') /* Partial codebook. */\n#define ID_CBPZ MAKE_ID('C','B','P','Z') /* Partial codebook (compressed). */\n#define ID_VPT0 MAKE_ID('V','P','T','0') /* Vector pointers. */\n#define ID_VPTZ MAKE_ID('V','P','T','Z') /* Vector pointers (compressed). */\n#define ID_VPTK MAKE_ID('V','P','T','K') /* Vector pointers (Delta Key). */\n#define ID_VPTD MAKE_ID('V','P','T','D') /* Vector pointers (Delta). */\n#define ID_VPTR MAKE_ID('V','P','T','R') /* Pointers RSD compressed. */\n#define ID_VPRZ MAKE_ID('V','P','R','Z') /* Pointers RSD, lcw compressed. */\n#define ID_CPL0 MAKE_ID('C','P','L','0') /* Color palette. */\n#define ID_CPLZ MAKE_ID('C','P','L','Z') /* Color palette (compressed). */\n#define ID_SND0 MAKE_ID('S','N','D','0') /* Sound */\n#define ID_SND1 MAKE_ID('S','N','D','1') /* Sound (Zap compressed). */\n#define ID_SND2 MAKE_ID('S','N','D','2') /* Sound (ADPCM compressed). */\n#define ID_SNDZ MAKE_ID('S','N','D','Z') /* Sound (LCW compression). */\n\n#define ID_SNA0 MAKE_ID('S','N','A','0') /* Sound */\n#define ID_SNA1 MAKE_ID('S','N','A','1') /* Sound (Zap compressed). */\n#define ID_SNA2 MAKE_ID('S','N','A','2') /* Sound (ADPCM compressed). */\n#define ID_SNAZ MAKE_ID('S','N','A','Z') /* Sound (LCW compression). */\n\n#define ID_CAP0 MAKE_ID('C','A','P','0') /* Caption text */\n#define ID_EVA0 MAKE_ID('E','V','A','0') /* EVA text */\n\n#ifdef __WATCOMC__\n#pragma pack();\n#endif\n\n#endif /* VQAFILE_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQA32/VQAPLAY.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAPLAY_H\n#define VQAPLAY_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqaplay.h\n*\n* DESCRIPTION\n*      VQAPlay library definitions.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 10, 1995\n*\n****************************************************************************/\n\n/*---------------------------------------------------------------------------\n * CONDITIONAL COMPILATION FLAGS\n *-------------------------------------------------------------------------*/\n\n// MEG - 11.28.95 - added for debug\nextern void Debug_Printf( char *format_string, ... );\n\n#ifdef __WATCOMC__\n#define VQASTANDALONE 0  /* Stand alone player */\n#define VQAVOC_ON     0  /* Enable VOC file override */\n#define\tVQAMONO_ON    0  /* Mono display output enable/disable */\n#define VQADIRECT_SOUND 1\t/* Use windows direct sound system */\n#define VQAAUDIO_ON   1  /* Audio playback enable/disable */\n#define VQAVIDEO_ON   0  /* Video manager enable/disable */\n#define VQAMCGA_ON    1  /* MCGA enable/disable */\n#define VQAXMODE_ON   0  /* Xmode enable/disable */\n#define VQAVESA_ON    0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2  1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4  0  /* 4x4 block decode enable/disable */\n#define VQAWOOFER_ON  0\n#else\n#define VQASTANDALONE 0  /* Stand alone player */\n#define VQAVOC_ON     0  /* Enable VOC file override */\n#define\tVQAMONO_ON    1  /* Mono display output enable/disable */\n#define VQADIRECT_SOUND 1\t/* Use windows direct sound system */\n#define VQAAUDIO_ON   1  /* Audio playback enable/disable */\n#define VQAVIDEO_ON   0  /* Video manager enable/disable */\n#define VQAMCGA_ON    1  /* MCGA enable/disable */\n#define VQAXMODE_ON   0  /* Xmode enable/disable */\n#define VQAVESA_ON    0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2  1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4  0  /* 4x4 block decode enable/disable */\n#define VQAWOOFER_ON  0\n#endif\n\n\n\n#if (VQAAUDIO_ON && VQADIRECT_SOUND)\n#ifndef WIN32\n#define WIN32 1\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#endif\n#undef WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <windowsx.h>\n#include \"dsound.h\"\n#endif\n\n\n\n/*---------------------------------------------------------------------------\n * GENERAL CONSTANT DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* Playback modes. */\n#define VQAMODE_RUN   0  /* Run the movie through the end. */\n#define VQAMODE_WALK  1  /* Draw the next frame then return. */\n#define VQAMODE_PAUSE 2  /* Suspend movie playback. */\n#define VQAMODE_STOP  3  /* Stop the movie. */\n\n/* Playback timer methods */\n#define VQA_TMETHOD_DEFAULT -1 /* Use default timer method. */\n#define\tVQA_TMETHOD_DOS      1 /* DOS timer method */\n#define\tVQA_TMETHOD_INT      2 /* Interrupt timer method */\n#define\tVQA_TMETHOD_AUDIO    3 /* Audio timer method */\n\n#define\tVQA_TIMETICKS 60 /* Clock ticks per second */\n\n/* Error/Status conditions */\n#define VQAERR_NONE      0  /* No error */\n#define\tVQAERR_EOF      -1  /* Valid end of file */\n#define VQAERR_OPEN     -2  /* Unable to open */\n#define\tVQAERR_READ     -3  /* Read error */\n#define VQAERR_WRITE    -4  /* Write error */\n#define VQAERR_SEEK     -5  /* Seek error */\n#define VQAERR_NOTVQA   -6  /* Not a valid VQA file. */\n#define VQAERR_NOMEM    -7  /* Unable to allocate memory */\n#define\tVQAERR_NOBUFFER -8  /* No buffer avail for load/draw */\n#define\tVQAERR_NOT_TIME -9  /* Not time for frame yet */\n#define\tVQAERR_SLEEPING -10 /* Function is in a sleep state */\n#define VQAERR_VIDEO    -11 /* Video related error. */\n#define VQAERR_AUDIO    -12 /* Audio related error. */\n#define VQAERR_PAUSED   -13 /* In paused state. */\n\n/* Event flags. */\n#define VQAEVENT_PALETTE (1<<0)\n#define VQAEVENT_SYNC    (1<<1)\n\n\n/*---------------------------------------------------------------------------\n * STRUCTURES AND RELATED DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* VQAConfig: Player configuration structure\n *\n * DrawerCallback - User routine for Drawer to call each frame (NULL = none)\n * EventHandler   - User routine for notification to client of events.\n * NotifyFlags    - User specified events to be notified about.\n * Vmode          - Requested Video mode (May be promoted).\n * VBIBit         - Vertical blank bit polarity.\n * ImageBuf       - Pointer to caller's buffer for the Drawer to use as its\n *                  ImageBuf; NULL = player will allocate its own, if\n *                  VQACFGF_BUFFER is set in DrawFlags.\n * ImageWidth     - Width of Image buffer.\n * ImageHeight    - Height of Image buffer.\n * X1             - Draw window X coordinate (-1 = Center).\n * Y1             - Draw window Y coordinate (-1 = Center).\n * FrameRate      - Desired frames per second (-1 = use VQA header's value).\n * DrawRate       - Desired drawing frame rate; allows the Drawer to draw at\n *                  a separate rate from the Loader.\n * TimerMethod    - Timer method to use during playback.\n * DrawFlags      - Bits control various special drawing options. (See below)\n * OptionFlags    - Bits control various special misc options. (See below)\n * NumFrameBufs   - Desired number of frame buffers. (Default = 6)\n * NumCBBufs      - Desired number of codebook buffers. (Default = 3)\n * SoundObject\t\t- Ptr to callers Direct Sound Object (Default =NULL)\n * PrimaryBufferPtr- Ptr to callers Primary Sound Buffer. (Default = NULL)\n * VocFile        - Name of VOC file to play instead of VQA audio track.\n * AudioBuf       - Pointer to audio buffer.\n * AudioBufSize   - Size of audio buffer. (Default = 32768)\n * AudioRate      - Audio data playback rate (-1 = use samplerate scaled\n *                  to the frame rate)\n * Volume         - Audio playback volume. (0x7FFF = max)\n * HMIBufSize     - Desired HMI buffer size. (Default = 2000)\n * DigiHandle     - Handle to an initialized sound driver. (-1 = none)\n * DigiCard       - HMI ID of card to use. (0 = none, -1 = auto-detect)\n * DigiPort       - Audio port address. (-1 = auto-detect)\n * DigiIRQ        - Audio IRQ. (-1 = auto-detect)\n * DigiDMA        - Audio DMA channel. (-1 = auto-detect)\n * Language       - Language identifier. (Not used)\n * CapFont        - Pointer to font to use for subtitle text captions.\n * EVAFont        - Pointer to font to use for E.V.A text cations. (For C&C)\n */\ntypedef struct _VQAConfig {\n\tlong          \t\t\t(*DrawerCallback)(unsigned char *screen, long framenum);\n\tlong          \t\t\t(*EventHandler)(unsigned long event,void *buffer,long nbytes);\n\tunsigned long \t\t\tNotifyFlags;\n\tlong          \t\t\tVmode;\n\tlong          \t\t\tVBIBit;\n\tunsigned char \t\t\t*ImageBuf;\n\tlong          \t\t\tImageWidth;\n\tlong          \t\t\tImageHeight;\n\tlong          \t\t\tX1,Y1;\n\tlong          \t\t\tFrameRate;\n\tlong          \t\t\tDrawRate;\n\tlong          \t\t\tTimerMethod;\n\tlong          \t\t\tDrawFlags;\n\tlong          \t\t\tOptionFlags;\n\tlong          \t\t\tNumFrameBufs;\n\tlong          \t\t\tNumCBBufs;\n#if (VQADIRECT_SOUND)\n\tLPDIRECTSOUND\t\t\tSoundObject;\n\tLPDIRECTSOUNDBUFFER\tPrimaryBufferPtr;\n#endif\t//(VQADIRECT_SOUND)\n\tchar          \t\t\t*VocFile;\n\tunsigned char \t\t\t*AudioBuf;\n\tlong          \t\t\tAudioBufSize;\n\tlong          \t\t\tAudioRate;\n\tlong          \t\t\tVolume;\n\tlong          \t\t\tHMIBufSize;\n\tlong          \t\t\tDigiHandle;\n\tlong          \t\t\tDigiCard;\n\tlong          \t\t\tDigiPort;\n\tlong          \t\t\tDigiIRQ;\n\tlong          \t\t\tDigiDMA;\n\tlong          \t\t\tLanguage;\n\tchar          \t\t\t*CapFont;\n\tchar          \t\t\t*EVAFont; /* For C&C Only */\n} VQAConfig;\n\n/* Drawer Configuration flags (DrawFlags) */\n#define\tVQACFGB_BUFFER   0 /* Buffer UnVQ enable */\n#define\tVQACFGB_NODRAW   1 /* Drawing disable */\n#define VQACFGB_NOSKIP   2 /* Disable frame skipping. */\n#define\tVQACFGB_VRAMCB   3 /* XMode VRAM copy enable */\n#define VQACFGB_ORIGIN   4 /* 0,0 origin position */\n#define\tVQACFGB_SCALEX2  6 /* Scale X2 enable (VESA 320x200 to 640x400) */\n#define VQACFGB_WOOFER   7\n#define\tVQACFGF_BUFFER   (1<<VQACFGB_BUFFER)\n#define\tVQACFGF_NODRAW   (1<<VQACFGB_NODRAW)\n#define\tVQACFGF_NOSKIP   (1<<VQACFGB_NOSKIP)\n#define\tVQACFGF_VRAMCB   (1<<VQACFGB_VRAMCB)\n#define\tVQACFGF_ORIGIN   (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPLEFT  (0<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPRIGHT (1<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTRIGHT (2<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTLEFT  (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_SCALEX2  (1<<VQACFGB_SCALEX2)\n#define VQACFGF_WOOFER   (1<<VQACFGB_WOOFER)\n\n/* Options Configuration (OptionFlags) */\n#define\tVQAOPTB_AUDIO    0 /* Audio enable. */\n#define\tVQAOPTB_STEP     1 /* Single step enable. */\n#define\tVQAOPTB_MONO     2 /* Mono output enable. */\n#define VQAOPTB_PALOFF   3 /* Palette set disable. */\n#define\tVQAOPTB_SLOWPAL  4 /* Slow palette enable. */\n#define VQAOPTB_HMIINIT  5 /* HMI already initialized by client. */\n#define VQAOPTB_ALTAUDIO 6 /* Use alternate audio track. */\n#define VQAOPTB_CAPTIONS 7 /* Show captions. */\n#define VQAOPTB_EVA      8 /* Show EVA text (For C&C only) */\n#define\tVQAOPTF_AUDIO    (1<<VQAOPTB_AUDIO)\n#define\tVQAOPTF_STEP     (1<<VQAOPTB_STEP)\n#define\tVQAOPTF_MONO     (1<<VQAOPTB_MONO)\n#define VQAOPTF_PALOFF   (1<<VQAOPTB_PALOFF)\n#define\tVQAOPTF_SLOWPAL  (1<<VQAOPTB_SLOWPAL)\n#define VQAOPTF_HMIINIT  (1<<VQAOPTB_HMIINIT)\n#define\tVQAOPTF_ALTAUDIO (1<<VQAOPTB_ALTAUDIO)\n#define VQAOPTF_CAPTIONS (1<<VQAOPTB_CAPTIONS)\n#define VQAOPTF_EVA      (1<<VQAOPTB_EVA) /* For C&C only */\n\n\n/* VQAInfo: Information about the VQA movie.\n *\n * NumFrames   - The number of frames contained in the movie.\n * ImageHeight - Height of image in pixels.\n * ImageWidth  - Width of image in pixels.\n * ImageBuf    - Pointer to the image buffer VQA draw into.\n */\ntypedef struct _VQAInfo {\n\tlong NumFrames;\n\tlong ImageWidth;\n\tlong ImageHeight;\n\tunsigned char *ImageBuf;\n} VQAInfo;\n\n\n/* VQAStatistics: Statistics about the VQA movie played.\n *\n * StartTime     - Time movie started.\n * EndTime       - Time movie stoped.\n * FramesLoaded  - Total number of frames loaded.\n * FramesDrawn   - Total number of frames drawn.\n * FramesSkipped - Total number of frames skipped.\n * MaxFrameSize  - Size of largest frame.\n * SamplesPlayed - Number of sample bytes played.\n * MemUsed       - Total bytes used. (Low memory)\n */\ntypedef struct _VQAStatistics {\n\tlong          StartTime;\n\tlong          EndTime;\n\tlong          FramesLoaded;\n\tlong          FramesDrawn;\n\tlong          FramesSkipped;\n\tlong          MaxFrameSize;\n\tunsigned long SamplesPlayed;\n\tunsigned long MemUsed;\n} VQAStatistics;\n\n\n/* VQAHandle: VQA file handle. (Must be obtained by calling VQA_Alloc()\n *            and freed through VQA_Free(). This is the only legal way\n *            to obtain and dispose of a VQAHandle.\n *\n * VQAio - Something meaningful to the IO manager. (See DOCS)\n */\ntypedef struct _VQAHandle {\n\tunsigned long VQAio;\n} VQAHandle;\n\n/* Possible IO command values */\n#define VQACMD_INIT    1 /* Prepare the IO for a session */\n#define VQACMD_CLEANUP 2 /* Terminate IO session */\n#define VQACMD_OPEN    3 /* Open file */\n#define VQACMD_CLOSE   4 /* Close file */\n#define VQACMD_READ    5 /* Read bytes */\n#define VQACMD_WRITE   6 /* Write bytes */\n#define VQACMD_SEEK    7 /* Seek */\n\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n/* Configuration routines. */\nvoid VQA_INIConfig(VQAConfig *config);\nvoid VQA_DefaultConfig(VQAConfig *config);\n\n/* Handle manipulation routines. */\nVQAHandle *VQA_Alloc(void);\nvoid VQA_Free(VQAHandle *vqa);\nvoid VQA_Reset(VQAHandle *vqa);\nvoid VQA_InitAsDOS(VQAHandle *vqa);\nvoid VQA_Init(VQAHandle *vqa, long(*iohandler)(VQAHandle *vqa, long action,\n\t\tvoid *buffer, long nbytes));\nunsigned char *VQA_GetPalette(VQAHandle *vqa);\nlong VQA_GetPaletteSize(VQAHandle *vqa);\nvoid VQA_Set_DrawBuffer(VQAHandle *vqa, unsigned char *buffer,\n\t\tunsigned long width, unsigned long height,\n\t\tlong xpos, long ypos);\n\n/* File routines. */\nlong VQA_Open(VQAHandle *vqa, char const *filename, VQAConfig *config);\nvoid VQA_Close(VQAHandle *vqa);\nlong VQA_Play(VQAHandle *vqa, long mode);\nlong VQA_SeekFrame(VQAHandle *vqa, long frame, long fromwhere);\nlong VQA_SetStop(VQAHandle *vqa, long stop);\n\n/* Information/statistics access routines. */\nvoid VQA_GetInfo(VQAHandle *vqa, VQAInfo *info);\nvoid VQA_GetStats(VQAHandle *vqa, VQAStatistics *stats);\nchar *VQA_Version(void);\nchar *VQA_IDString(void);\n\n#endif /* VQAPLAY_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQA32/VQAPLAY.H.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAPLAY_H\n#define VQAPLAY_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqaplay.h\n*\n* DESCRIPTION\n*      VQAPlay library definitions.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 10, 1995\n*\n****************************************************************************/\n\n/*---------------------------------------------------------------------------\n * CONDITIONAL COMPILATION FLAGS\n *-------------------------------------------------------------------------*/\n\n// MEG - 11.28.95 - added for debug\nextern void Debug_Printf( char *format_string, ... );\n\n#ifdef __WATCOMC__\n#define VQASTANDALONE 0  /* Stand alone player */\n#define VQAVOC_ON     0  /* Enable VOC file override */\n#define\tVQAMONO_ON    0  /* Mono display output enable/disable */\n#define VQADIRECT_SOUND 1\t/* Use windows direct sound system */\n#define VQAAUDIO_ON   1  /* Audio playback enable/disable */\n#define VQAVIDEO_ON   0  /* Video manager enable/disable */\n#define VQAMCGA_ON    1  /* MCGA enable/disable */\n#define VQAXMODE_ON   0  /* Xmode enable/disable */\n#define VQAVESA_ON    0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2  1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4  0  /* 4x4 block decode enable/disable */\n#define VQAWOOFER_ON  0\n#else\n#define VQASTANDALONE 0  /* Stand alone player */\n#define VQAVOC_ON     0  /* Enable VOC file override */\n#define\tVQAMONO_ON    1  /* Mono display output enable/disable */\n#define VQADIRECT_SOUND 1\t/* Use windows direct sound system */\n#define VQAAUDIO_ON   1  /* Audio playback enable/disable */\n#define VQAVIDEO_ON   0  /* Video manager enable/disable */\n#define VQAMCGA_ON    1  /* MCGA enable/disable */\n#define VQAXMODE_ON   0  /* Xmode enable/disable */\n#define VQAVESA_ON    0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2  1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4  0  /* 4x4 block decode enable/disable */\n#define VQAWOOFER_ON  0\n#endif\n\n\n\n#if (VQAAUDIO_ON && VQADIRECT_SOUND)\n#ifndef WIN32 1\n#define WIN32\n#define _WIN32\n#endif\n#undef WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <windowsx.h>\n#include \"dsound.h\"\n#endif\n\n\n\n/*---------------------------------------------------------------------------\n * GENERAL CONSTANT DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* Playback modes. */\n#define VQAMODE_RUN   0  /* Run the movie through the end. */\n#define VQAMODE_WALK  1  /* Draw the next frame then return. */\n#define VQAMODE_PAUSE 2  /* Suspend movie playback. */\n#define VQAMODE_STOP  3  /* Stop the movie. */\n\n/* Playback timer methods */\n#define VQA_TMETHOD_DEFAULT -1 /* Use default timer method. */\n#define\tVQA_TMETHOD_DOS      1 /* DOS timer method */\n#define\tVQA_TMETHOD_INT      2 /* Interrupt timer method */\n#define\tVQA_TMETHOD_AUDIO    3 /* Audio timer method */\n\n#define\tVQA_TIMETICKS 60 /* Clock ticks per second */\n\n/* Error/Status conditions */\n#define VQAERR_NONE      0  /* No error */\n#define\tVQAERR_EOF      -1  /* Valid end of file */\n#define VQAERR_OPEN     -2  /* Unable to open */\n#define\tVQAERR_READ     -3  /* Read error */\n#define VQAERR_WRITE    -4  /* Write error */\n#define VQAERR_SEEK     -5  /* Seek error */\n#define VQAERR_NOTVQA   -6  /* Not a valid VQA file. */\n#define VQAERR_NOMEM    -7  /* Unable to allocate memory */\n#define\tVQAERR_NOBUFFER -8  /* No buffer avail for load/draw */\n#define\tVQAERR_NOT_TIME -9  /* Not time for frame yet */\n#define\tVQAERR_SLEEPING -10 /* Function is in a sleep state */\n#define VQAERR_VIDEO    -11 /* Video related error. */\n#define VQAERR_AUDIO    -12 /* Audio related error. */\n#define VQAERR_PAUSED   -13 /* In paused state. */\n\n/* Event flags. */\n#define VQAEVENT_PALETTE (1<<0)\n#define VQAEVENT_SYNC    (1<<1)\n\n\n/*---------------------------------------------------------------------------\n * STRUCTURES AND RELATED DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* VQAConfig: Player configuration structure\n *\n * DrawerCallback - User routine for Drawer to call each frame (NULL = none)\n * EventHandler   - User routine for notification to client of events.\n * NotifyFlags    - User specified events to be notified about.\n * Vmode          - Requested Video mode (May be promoted).\n * VBIBit         - Vertical blank bit polarity.\n * ImageBuf       - Pointer to caller's buffer for the Drawer to use as its\n *                  ImageBuf; NULL = player will allocate its own, if\n *                  VQACFGF_BUFFER is set in DrawFlags.\n * ImageWidth     - Width of Image buffer.\n * ImageHeight    - Height of Image buffer.\n * X1             - Draw window X coordinate (-1 = Center).\n * Y1             - Draw window Y coordinate (-1 = Center).\n * FrameRate      - Desired frames per second (-1 = use VQA header's value).\n * DrawRate       - Desired drawing frame rate; allows the Drawer to draw at\n *                  a separate rate from the Loader.\n * TimerMethod    - Timer method to use during playback.\n * DrawFlags      - Bits control various special drawing options. (See below)\n * OptionFlags    - Bits control various special misc options. (See below)\n * NumFrameBufs   - Desired number of frame buffers. (Default = 6)\n * NumCBBufs      - Desired number of codebook buffers. (Default = 3)\n * SoundObject\t\t- Ptr to callers Direct Sound Object (Default =NULL)\n * PrimaryBufferPtr- Ptr to callers Primary Sound Buffer. (Default = NULL)\n * VocFile        - Name of VOC file to play instead of VQA audio track.\n * AudioBuf       - Pointer to audio buffer.\n * AudioBufSize   - Size of audio buffer. (Default = 32768)\n * AudioRate      - Audio data playback rate (-1 = use samplerate scaled\n *                  to the frame rate)\n * Volume         - Audio playback volume. (0x7FFF = max)\n * HMIBufSize     - Desired HMI buffer size. (Default = 2000)\n * DigiHandle     - Handle to an initialized sound driver. (-1 = none)\n * DigiCard       - HMI ID of card to use. (0 = none, -1 = auto-detect)\n * DigiPort       - Audio port address. (-1 = auto-detect)\n * DigiIRQ        - Audio IRQ. (-1 = auto-detect)\n * DigiDMA        - Audio DMA channel. (-1 = auto-detect)\n * Language       - Language identifier. (Not used)\n * CapFont        - Pointer to font to use for subtitle text captions.\n * EVAFont        - Pointer to font to use for E.V.A text cations. (For C&C)\n */\ntypedef struct _VQAConfig {\n\tlong          \t\t\t(*DrawerCallback)(unsigned char *screen, long framenum);\n\tlong          \t\t\t(*EventHandler)(unsigned long event,void *buffer,long nbytes);\n\tunsigned long \t\t\tNotifyFlags;\n\tlong          \t\t\tVmode;\n\tlong          \t\t\tVBIBit;\n\tunsigned char \t\t\t*ImageBuf;\n\tlong          \t\t\tImageWidth;\n\tlong          \t\t\tImageHeight;\n\tlong          \t\t\tX1,Y1;\n\tlong          \t\t\tFrameRate;\n\tlong          \t\t\tDrawRate;\n\tlong          \t\t\tTimerMethod;\n\tlong          \t\t\tDrawFlags;\n\tlong          \t\t\tOptionFlags;\n\tlong          \t\t\tNumFrameBufs;\n\tlong          \t\t\tNumCBBufs;\n#if (VQADIRECT_SOUND)\n\tLPDIRECTSOUND\t\t\tSoundObject;\n\tLPDIRECTSOUNDBUFFER\tPrimaryBufferPtr;\n#endif\t//(VQADIRECT_SOUND)\n\tchar          \t\t\t*VocFile;\n\tunsigned char \t\t\t*AudioBuf;\n\tlong          \t\t\tAudioBufSize;\n\tlong          \t\t\tAudioRate;\n\tlong          \t\t\tVolume;\n\tlong          \t\t\tHMIBufSize;\n\tlong          \t\t\tDigiHandle;\n\tlong          \t\t\tDigiCard;\n\tlong          \t\t\tDigiPort;\n\tlong          \t\t\tDigiIRQ;\n\tlong          \t\t\tDigiDMA;\n\tlong          \t\t\tLanguage;\n\tchar          \t\t\t*CapFont;\n\tchar          \t\t\t*EVAFont; /* For C&C Only */\n} VQAConfig;\n\n/* Drawer Configuration flags (DrawFlags) */\n#define\tVQACFGB_BUFFER   0 /* Buffer UnVQ enable */\n#define\tVQACFGB_NODRAW   1 /* Drawing disable */\n#define VQACFGB_NOSKIP   2 /* Disable frame skipping. */\n#define\tVQACFGB_VRAMCB   3 /* XMode VRAM copy enable */\n#define VQACFGB_ORIGIN   4 /* 0,0 origin position */\n#define\tVQACFGB_SCALEX2  6 /* Scale X2 enable (VESA 320x200 to 640x400) */\n#define VQACFGB_WOOFER   7\n#define\tVQACFGF_BUFFER   (1<<VQACFGB_BUFFER)\n#define\tVQACFGF_NODRAW   (1<<VQACFGB_NODRAW)\n#define\tVQACFGF_NOSKIP   (1<<VQACFGB_NOSKIP)\n#define\tVQACFGF_VRAMCB   (1<<VQACFGB_VRAMCB)\n#define\tVQACFGF_ORIGIN   (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPLEFT  (0<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPRIGHT (1<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTRIGHT (2<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTLEFT  (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_SCALEX2  (1<<VQACFGB_SCALEX2)\n#define VQACFGF_WOOFER   (1<<VQACFGB_WOOFER)\n\n/* Options Configuration (OptionFlags) */\n#define\tVQAOPTB_AUDIO    0 /* Audio enable. */\n#define\tVQAOPTB_STEP     1 /* Single step enable. */\n#define\tVQAOPTB_MONO     2 /* Mono output enable. */\n#define VQAOPTB_PALOFF   3 /* Palette set disable. */\n#define\tVQAOPTB_SLOWPAL  4 /* Slow palette enable. */\n#define VQAOPTB_HMIINIT  5 /* HMI already initialized by client. */\n#define VQAOPTB_ALTAUDIO 6 /* Use alternate audio track. */\n#define VQAOPTB_CAPTIONS 7 /* Show captions. */\n#define VQAOPTB_EVA      8 /* Show EVA text (For C&C only) */\n#define\tVQAOPTF_AUDIO    (1<<VQAOPTB_AUDIO)\n#define\tVQAOPTF_STEP     (1<<VQAOPTB_STEP)\n#define\tVQAOPTF_MONO     (1<<VQAOPTB_MONO)\n#define VQAOPTF_PALOFF   (1<<VQAOPTB_PALOFF)\n#define\tVQAOPTF_SLOWPAL  (1<<VQAOPTB_SLOWPAL)\n#define VQAOPTF_HMIINIT  (1<<VQAOPTB_HMIINIT)\n#define\tVQAOPTF_ALTAUDIO (1<<VQAOPTB_ALTAUDIO)\n#define VQAOPTF_CAPTIONS (1<<VQAOPTB_CAPTIONS)\n#define VQAOPTF_EVA      (1<<VQAOPTB_EVA) /* For C&C only */\n\n\n/* VQAInfo: Information about the VQA movie.\n *\n * NumFrames   - The number of frames contained in the movie.\n * ImageHeight - Height of image in pixels.\n * ImageWidth  - Width of image in pixels.\n * ImageBuf    - Pointer to the image buffer VQA draw into.\n */\ntypedef struct _VQAInfo {\n\tlong NumFrames;\n\tlong ImageWidth;\n\tlong ImageHeight;\n\tunsigned char *ImageBuf;\n} VQAInfo;\n\n\n/* VQAStatistics: Statistics about the VQA movie played.\n *\n * StartTime     - Time movie started.\n * EndTime       - Time movie stoped.\n * FramesLoaded  - Total number of frames loaded.\n * FramesDrawn   - Total number of frames drawn.\n * FramesSkipped - Total number of frames skipped.\n * MaxFrameSize  - Size of largest frame.\n * SamplesPlayed - Number of sample bytes played.\n * MemUsed       - Total bytes used. (Low memory)\n */\ntypedef struct _VQAStatistics {\n\tlong          StartTime;\n\tlong          EndTime;\n\tlong          FramesLoaded;\n\tlong          FramesDrawn;\n\tlong          FramesSkipped;\n\tlong          MaxFrameSize;\n\tunsigned long SamplesPlayed;\n\tunsigned long MemUsed;\n} VQAStatistics;\n\n\n/* VQAHandle: VQA file handle. (Must be obtained by calling VQA_Alloc()\n *            and freed through VQA_Free(). This is the only legal way\n *            to obtain and dispose of a VQAHandle.\n *\n * VQAio - Something meaningful to the IO manager. (See DOCS)\n */\ntypedef struct _VQAHandle {\n\tunsigned long VQAio;\n} VQAHandle;\n\n/* Possible IO command values */\n#define VQACMD_INIT    1 /* Prepare the IO for a session */\n#define VQACMD_CLEANUP 2 /* Terminate IO session */\n#define VQACMD_OPEN    3 /* Open file */\n#define VQACMD_CLOSE   4 /* Close file */\n#define VQACMD_READ    5 /* Read bytes */\n#define VQACMD_WRITE   6 /* Write bytes */\n#define VQACMD_SEEK    7 /* Seek */\n\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n/* Configuration routines. */\nvoid VQA_INIConfig(VQAConfig *config);\nvoid VQA_DefaultConfig(VQAConfig *config);\n\n/* Handle manipulation routines. */\nVQAHandle *VQA_Alloc(void);\nvoid VQA_Free(VQAHandle *vqa);\nvoid VQA_Reset(VQAHandle *vqa);\nvoid VQA_InitAsDOS(VQAHandle *vqa);\nvoid VQA_Init(VQAHandle *vqa, long(*iohandler)(VQAHandle *vqa, long action,\n\t\tvoid *buffer, long nbytes));\nunsigned char *VQA_GetPalette(VQAHandle *vqa);\nlong VQA_GetPaletteSize(VQAHandle *vqa);\nvoid VQA_Set_DrawBuffer(VQAHandle *vqa, unsigned char *buffer,\n\t\tunsigned long width, unsigned long height,\n\t\tlong xpos, long ypos);\n\n/* File routines. */\nlong VQA_Open(VQAHandle *vqa, char const *filename, VQAConfig *config);\nvoid VQA_Close(VQAHandle *vqa);\nlong VQA_Play(VQAHandle *vqa, long mode);\nlong VQA_SeekFrame(VQAHandle *vqa, long frame, long fromwhere);\nlong VQA_SetStop(VQAHandle *vqa, long stop);\n\n/* Information/statistics access routines. */\nvoid VQA_GetInfo(VQAHandle *vqa, VQAInfo *info);\nvoid VQA_GetStats(VQAHandle *vqa, VQAStatistics *stats);\nchar *VQA_Version(void);\nchar *VQA_IDString(void);\n\n#endif /* VQAPLAY_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQA32/VQAPLAYP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAPLAYP_H\n#define VQAPLAYP_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqaplayp.h\n*\n* DESCRIPTION\n*     VQAPlay private library definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*     Bill Randolph\n*\n* DATE\n*     August 21, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\video.h>\n#include <vqm32\\soscomp.h>\n#include <vqm32\\captoken.h>\n#include \"vqafile.h\"\n#include \"vqaplay.h\"\n#include \"caption.h\"\n\n#if(VQAAUDIO_ON)\n#if(VQADIRECT_SOUND)\nextern HWND MainWindow;\n#else\n#include \"sos.h\"\n#endif\n#endif\n\n/*---------------------------------------------------------------------------\n * GENERAL CONSTANT DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* Internal library version. */\n#define VQA_VERSION \"2.42\"\n#define VQA_DATE    __DATE__\" \"__TIME__\n\n#define VQA_IDSTRING \"VQA32 \"VQA_VERSION\" (\"VQA_DATE\")\"\n#define VQA_REQUIRES \"VQM32 2.12 or better.\"\n\n/* Block dimensions macro and identifiers. */\n#define BLOCK_DIM(a,b) (((a&0xFF)<<8)|(b&0xFF))\n#define BLOCK_2X2 BLOCK_DIM(2,2)\n#define BLOCK_2X3 BLOCK_DIM(2,3)\n#define BLOCK_4X2 BLOCK_DIM(4,2)\n#define BLOCK_4X4 BLOCK_DIM(4,4)\n\n/* Memory limits */\n#define\tVQA_MAX_CBBUFS    10 /* Maximum number of codebook buffers */\n#define\tVQA_MAX_FRAMEBUFS 30 /* Maximum number of frame buffers */\n\n/* Special Constants */\n#define\tVQA_MASK_POINTER 0x8000 /* Pointer value to use for masking. */\n\n\n/*---------------------------------------------------------------------------\n * STRUCTURES AND RELATED DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* ChunkHeader: IFF chunk identifier header.\n *\n * id   - 4 Byte chunk id.\n * size - Size of chunk.\n */\ntypedef struct _ChunkHeader {\n\tunsigned long id;\n\tunsigned long size;\n} ChunkHeader;\n\n\n/* ZAPHeader: ZAP audio compression header. NOTE: If the uncompressed size\n *            and the compressed size are equal then the audio frame is RAW\n *            (NOT COMPRESSED).\n *\n * UnCompSize - Uncompressed size in bytes.\n * CompSize   - Compressed size in bytes.\n */\ntypedef struct _ZAPHeader {\n\tunsigned short UnCompSize;\n\tunsigned short CompSize;\n} ZAPHeader;\n\n\n/* VQACBNode: A circular list of codebook buffers, used by the load task.\n *            If the data is compressed, it is loaded into the end of the\n *            buffer and the compression flags is set. Otherwise the data\n *            is loaded into the start of the buffer.\n *            (Make sure this structure's size is always DWORD aligned.)\n *\n * Buffer   - Pointer to Codebook data.\n * Next     - Pointer to next VQACBNode in the codebook list.\n * Flags    - Used by the drawer to tell if certain operations have been\n *            performed on this codebook, such as downloading to VRAM,\n *            or pre-scaling it. This field is cleared by the Loader when a\n *            new codebook is loaded.\n * CBOffset - Offset into the buffer of the compressed data.\n */\ntypedef struct _VQACBNode {\n\tunsigned char     *Buffer;\n\tstruct _VQACBNode *Next;\n\tunsigned long     Flags;\n\tunsigned long     CBOffset;\n} VQACBNode;\n\n/* VQACBNode flags */\n#define\tVQACBB_DOWNLOADED 0 /* Download codebook to VRAM (XMODE VRAM) */\n#define VQACBB_CBCOMP     1 /* Codebook is compressed */\n#define\tVQACBF_DOWNLOADED (1<<VQACBB_DOWNLOADED)\n#define\tVQACBF_CBCOMP     (1<<VQACBB_CBCOMP)\n\n\n/* VQAFrameNode: A circular list of frame buffers, filled in by the load\n *               task. If the data is compressed, it is loaded into the end\n *               of the buffer and the compress flag is set. Otherwise, it's\n *               loaded into the start of the buffer.\n *               (Make sure this structure's size is always DWORD aligned.)\n *\n * Pointers    - Pointer to the vector pointer data.\n * Codebook    - Pointer to VQACBNode list entry for this frame.\n * Palette     - Pointer to an array of palette colors (R,G,B).\n * Next        - Pointer to the next entry in the Frame Buffer List.\n * Flags       - Inter-process communication flags for this frame (see below)\n *               set by Loader, cleared by Flipper.\n * FrameNum    - Number of this frame in the animation.\n * PtrOffset   - Offset into buffer of the compressed vector pointer data.\n * PalOffset   - Offset into buffer of the compressed palette data.\n * PaletteSize - Size of the palette for this frame (in bytes).\n */\ntypedef struct _VQAFrameNode {\n\tunsigned char        *Pointers;\n\tVQACBNode            *Codebook;\n\tunsigned char        *Palette;\n\tstruct _VQAFrameNode *Next;\n\tunsigned long        Flags;\n\tlong                 FrameNum;\n\tlong                 PtrOffset;\n\tlong                 PalOffset;\n\tlong                 PaletteSize;\n} VQAFrameNode;\n\n/* FrameNode flags */\n#define\tVQAFRMB_LOADED  0 /* Frame loaded */\n#define\tVQAFRMB_KEY     1 /* Key Frame (must be drawn) */\n#define\tVQAFRMB_PALETTE 2 /* Palette needs set */\n#define VQAFRMB_PALCOMP 3 /* Palette is compressed */\n#define VQAFRMB_PTRCOMP 4 /* Vector pointer data is compressed */\n#define\tVQAFRMF_LOADED  (1<<VQAFRMB_LOADED)\n#define\tVQAFRMF_KEY     (1<<VQAFRMB_KEY)\n#define\tVQAFRMF_PALETTE (1<<VQAFRMB_PALETTE)\n#define\tVQAFRMF_PALCOMP (1<<VQAFRMB_PALCOMP)\n#define\tVQAFRMF_PTRCOMP (1<<VQAFRMB_PTRCOMP)\n\n\n/* VQALoader: Data needed exclusively by the Loader.\n *            (Make sure this structure's size is always DWORD aligned.)\n *\n * CurCB         - Pointer to the current codebook node to load data into.\n * FullCB        - Pointer to the last fully-loaded codebook node.\n * CurFrame      - Pointer to the current frame node to load data into.\n * NumPartialCB  - Number of partial codebooks accumulated.\n * PartialCBSize - Size of partial codebook (LCW'd or not), in bytes\n * CurFrameNum   - The number of the frame being loaded by the Loader.\n * LastCBFrame   - Last frame in the animation that contains a partial CB\n * LastFrameNum  - Number of the last loaded frame\n * WaitsOnDrawer - Number of wait states Loader hits waiting on the Drawer\n * WaitsOnAudio  - Number of wait states Loader hits waiting on HMI\n * FrameSize     - Size of the last frame in bytes.\n * MaxFrameSize  - Size of the largest frame in the animation.\n * CurChunkHdr   - Chunk header of the chunk currently being processed.\n */\ntypedef struct _VQALoader {\n\tVQACBNode    *CurCB;\n\tVQACBNode    *FullCB;\n\tVQAFrameNode *CurFrame;\n\tlong         NumPartialCB;\n\tlong         PartialCBSize;\n\tlong         CurFrameNum;\n\tlong         LastCBFrame;\n\tlong         LastFrameNum;\n\tlong         WaitsOnDrawer;\n\tlong         WaitsOnAudio;\n\tlong         FrameSize;\n\tlong         MaxFrameSize;\n\tChunkHeader  CurChunkHdr;\n} VQALoader;\n\n\n/* VQADrawer: Data needed exclusively by the Drawer.\n *            (Make sure this structure's size is always DWORD aligned.)\n *\n * CurFrame       - Pointer to the current frame to draw.\n * Flags          - Flags for the draw routines (IE: VQADRWF_SETPAL)\n * Display        - Pointer to DisplayInfo structure for active video mode.\n * ImageBuf       - Buffer to un-vq into, must be DWORD aligned.\n * ImageWidth     - Width of Image buffer (in pixels).\n * ImageHeight    - Height of Image buffer (in pixels).\n * X1,Y1,X2,Y2    - Coordinates of image corners (in pixels).\n * ScreenOffset   - Offset into screen memory, for centering small images.\n * CurPalSize     - Size of the current palette in bytes.\n * Palette_24     - Copy of the last-loaded palette\n * Palette_15     - 15-bit version of Palette_24, for 32K-color modes\n * BlocksPerRow   - # of VQ blocks per row for this resolution/block width.\n * NumRows        - # of rows of VQ blocks for this resolution/block height.\n * NumBlocks      - Total number of blocks in the image.\n * MaskStart      - Pointer index of start of mask rectangle.\n * MaskWidth      - Width of mask rectangle, in blocks.\n * MaskHeight     - Height of mask rectangle, in blocks.\n * LastTime       - The time when that last frame was drawn.\n * LastFrame      - The number of the last frame selected.\n * LastFrameNum   - Number of the last frame drawn.\n * DesiredFrame   - The number of the frame that should be drawn.\n * NumSkipped     - Number of frames skipped.\n * WaitsOnFlipper - Number of wait states Drawer hits waiting on the Flipper.\n * WaitsOnLoader  - Number of wait states Drawer hits waiting on the Loader.\n */\ntypedef struct _VQADrawer {\n\tVQAFrameNode  *CurFrame;\n\tunsigned long Flags;\n\tDisplayInfo   *Display;\n\tunsigned char *ImageBuf;\n\tlong          ImageWidth;\n\tlong          ImageHeight;\n\tlong          X1,Y1,X2,Y2;\n\tlong          ScreenOffset;\n\tlong          CurPalSize;\n\tunsigned char Palette_24[768];\n\tunsigned char Palette_15[512];\n\tlong          BlocksPerRow;\n\tlong          NumRows;\n\tlong          NumBlocks;\n\tlong          MaskStart;\n\tlong          MaskWidth;\n\tlong          MaskHeight;\n\tlong          LastTime;\n\tlong          LastFrame;\n\tlong          LastFrameNum;\n\tlong          DesiredFrame;\n\tlong          NumSkipped;\n\tlong          WaitsOnFlipper;\n\tlong          WaitsOnLoader;\n} VQADrawer;\n\n/* Drawer flags */\n#define\tVQADRWB_SETPAL 0  /* Set palette */\n#define\tVQADRWF_SETPAL (1<<VQADRWB_SETPAL)\n\n\n/* VQAFlipper: Data needed exclusively by the page-flipper.\n *             (Make sure this structure's size is always DWORD aligned.)\n *\n * CurFrame     - Pointer to current flipper frame.\n * LastFrameNum - Number of last flipped frame\n * pad          - DWORD alignment padding.\n */\ntypedef struct _VQAFlipper {\n\tVQAFrameNode *CurFrame;\n\tlong         LastFrameNum;\n} VQAFlipper;\n\n\n#if(VQAAUDIO_ON)\n\n#ifdef __WATCOMC__\n#pragma pack(4);\n#endif\n\n/* VQAAudio: Data needed exclusively by audio playback.\n *           (Make sure this structure's size is always DWORD aligned.)\n *\n * Buffer         - Pointer to the audio buffer.\n * AudBufPos      - Current audio buffer position, for copying data in buffer.\n * IsLoaded       - Inter-process communication flag:\n *                  0 = is loadable, 1 = is not. Loader sets it when it\n *                  loads, audio callback clears it when it plays one.\n * NumAudBlocks   - Number of HMI blocks in the audio buffer.\n * CurBlock       - Current audio block\n * NextBlock      - Next audio block\n * TempBuf        - Pointer to temp buffer for loading/decompressing audio\n *                  data.\n * TempBufLen     - Number of bytes loaded into temp buffer.\n * TempBufSize    - Size of temp buffer in bytes.\n * Flags          - Various audio flags. (See below)\n * PlayPosition   - HMI's current buffer position.\n * SamplesPlayed  - Total samples played.\n * NumSkipped     - Count of buffers missed.\n * SampleRate     - Recorded sampling rate of the track.\n * Channels       - Number of channels in the track.\n * BitsPerSample  - Bit resolution size of sample (8,16)\n * BytesPerSec    - Recorded data transfer for one second.\n * ADPCM_Info     - ADPCM decompression information structure.\n * DigiHandle     - HMI digital device handle.\n * SampleHandle   - HMI sample handle.\n * DigiTimer      - HMI digital fill handler timer handle.\n * sSOSSampleData - HMI sample structure.\n * DigiCaps       - HMI sound card digital capabilities.\n * DigiHardware   - HMI sound card digital hardware settings.\n * sSOSInitDriver - HMI driver initialization structure.\n * TimerHandle\t\t- Handle to Windows multi-media timer\n * SoundTimerHandle- Handle to extra Windows mm timer req. for direct sound\n * SecondaryBufferPtr - Pointer to out direct sound secondary buffer\n * DSBuffFormat\t\t- WAVEFORMATEX structure for direct sound\n * BufferDesc\t\t- Description structure for setting up direct sound buffers\n * SecondaryBufferSize - length in bytes of our secondary sound buffer\n * EndLastAudioChunk - Offset into secondary buffer of the end of the last chunk of audio copied in\n * ChunksMovedToAudioBuffer - Total number of HMIBufSize chunks moved into the secondary buffer\n * LastChunkPosition - Offset position of last chunk copied to secondary buffer\n * CreatedSoundObject - True if we had to create our own direct sound object\n * CreatedSoundBuffer - True if we had to create out own direct sound primary buffer\n */\ntypedef struct _VQAAudio {\n\tunsigned char      *Buffer;\n\tunsigned long      AudBufPos;\n\tshort              *IsLoaded;\n\tunsigned long      NumAudBlocks;\n\tunsigned long      CurBlock;\n\tunsigned long      NextBlock;\n\tunsigned char      *TempBuf;\n\tunsigned long      TempBufLen;\n\tunsigned long      TempBufSize;\n\tunsigned long      Flags;\n\tunsigned long      PlayPosition;\n\tunsigned long      SamplesPlayed;\n\tunsigned long      NumSkipped;\n\tunsigned short     SampleRate;\n\tunsigned char      Channels;\n\tunsigned char      BitsPerSample;\n\tunsigned long      BytesPerSec;\n\t_SOS_COMPRESS_INFO ADPCM_Info;\n#if (!VQADIRECT_SOUND)\n\tWORD               DigiHandle;\n\tWORD               SampleHandle;\n\tWORD               DigiTimer;\n\t_SOS_START_SAMPLE  sSOSSampleData;\n\t_SOS_CAPABILITIES  DigiCaps;\n\t_SOS_HARDWARE      DigiHardware;\n\t_SOS_INIT_DRIVER   sSOSInitDriver;\n#else\n\tunsigned\t\t\t\t\tTimerHandle;\n\tunsigned\t\t\t\t\tSoundTimerHandle;\n\tLPDIRECTSOUNDBUFFER\tSecondaryBufferPtr;\n\tWAVEFORMATEX\t\t\tDsBuffFormat;\n\tDSBUFFERDESC\t\t\tBufferDesc;\n\tunsigned\t\t\t\t\tSecondaryBufferSize;\n\tunsigned\t\t\t\t\tEndLastAudioChunk;\n\tunsigned\t\t\t\t\tChunksMovedToAudioBuffer;\n\tunsigned\t\t\t\t\tLastChunkPosition;\n\tBOOL\t\t\t\t\t\tCreatedSoundObject;\n\tBOOL\t\t\t\t\t\tCreatedSoundBuffer;\n#endif\n} VQAAudio;\n\n/* Audio flags. */\n#define VQAAUDB_DIGIINIT  0  /* HMI digital driver initialized (2 bits) */\n#define VQAAUDB_TIMERINIT 2  /* HMI timer system initialized (2 bits) */\n#define VQAAUDB_HMITIMER  4  /* HMI timer callback initialized (2 bits) */\n#define VQAAUDB_ISPLAYING 6  /* Audio playing flag. */\n#define VQAAUDB_MEMLOCKED 30 /* Audio memory page locked. */\n#define VQAAUDB_MODLOCKED 31 /* Audio module page locked. */\n\n#define VQAAUDF_DIGIINIT  (3<<VQAAUDB_DIGIINIT)\n#define VQAAUDF_TIMERINIT (3<<VQAAUDB_TIMERINIT)\n#define VQAAUDF_HMITIMER  (3<<VQAAUDB_HMITIMER)\n#define VQAAUDF_ISPLAYING (1<<VQAAUDB_ISPLAYING)\n#define VQAAUDF_MEMLOCKED (1<<VQAAUDB_MEMLOCKED)\n#define VQAAUDF_MODLOCKED (1<<VQAAUDB_MODLOCKED)\n\n/* HMI device initialization conditions. (DIGIINIT, TIMERINIT, HMITIMER) */\n#define HMI_UNINIT  0  /* Unitialize state. */\n#define HMI_VQAINIT 1  /* VQA initialized */\n#define HMI_APPINIT 2  /* Application initialized */\n\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n\n#endif /* VQAAUDIO_ON */\n\n\n/* VQAData: This stucture contains all the data used for playing a VQA.\n *\n * Draw_Frame   - Pointer to the draw-frame routine for this video mode.\n * Page_Flip    - Pointer to the page flip function for this video mode.\n * UnVQ         - Pointer to the UnVQ routine for this vid mode & blk size.\n * FrameData    - Frame buffer circular list head.\n * CBData       - Codebook circular list head.\n * Audio        - Audio buffer\n * Loader       - Loader's data\n * Drawer       - Drawer's data\n * Flipper      - Flipper's data\n * Flags        - Flags used by the player.\n * Foff         - Pointer to frame offset table.\n * VBIBit       - Vertical blank bit polarity.\n * Max_CB_Size  - Maximum size of an uncompressed codebook\n * Max_Pal_Size - Maximum size of an uncompressed palette\n * Max_Ptr_Size - Maximum size of uncompressed pointer data\n * LoadedFrames - Number of frames loaded\n * DrawnFrames  - Number of frames drawn\n * StartTime    - Start time in VQA time ticks\n * EndTime      - Stop time in VQA time ticks\n * MemUsed      - Number of bytes allocated by VQA_AllocBuffers\n */\ntypedef struct _VQAData {\n\tlong (*Draw_Frame)(VQAHandle *vqa);\n\tlong (*Page_Flip)(VQAHandle *vqa);\n\n\t#ifndef PHARLAP_TNT\n\tvoid __cdecl (*UnVQ)(unsigned char *codebook, unsigned char *pointers,\n\t\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\t\tunsigned long numrows, unsigned long bufwidth);\n\t#else\n\tvoid __cdecl (*UnVQ)(unsigned char *codebook, unsigned char *pointers,\n\t\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\t\tunsigned long bufwidth);\n\t#endif\n\n\tVQAFrameNode  *FrameData;\n\tVQACBNode     *CBData;\n\n\t#if(VQAAUDIO_ON)\n\tVQAAudio      Audio;\n\t#endif\n\n\tVQALoader     Loader;\n\tVQADrawer     Drawer;\n\tVQAFlipper    Flipper;\n\tunsigned long Flags;\n\tlong          *Foff;\n\tlong          VBIBit;\n\tlong          Max_CB_Size;\n\tlong          Max_Pal_Size;\n\tlong          Max_Ptr_Size;\n\tlong          LoadedFrames;\n\tlong          DrawnFrames;\n\tlong          StartTime;\n\tlong          EndTime;\n\tlong          MemUsed;\n} VQAData;\n\n/* VQAData flags */\n#define VQADATB_UPDATE 0 /* Update the display. */\n#define VQADATB_DSLEEP 1 /* Drawer sleep state. */\n#define VQADATB_LSLEEP 2 /* Loader sleep state. */\n#define VQADATB_DDONE  3 /* Drawer done flag. (0 = done) */\n#define VQADATB_LDONE  4 /* Loader done flag. (0 = done) */\n#define VQADATB_PRIMED 5 /* Buffers are primed. */\n#define VQADATB_PAUSED 6 /* The player is paused. */\n#define VQADATF_UPDATE (1<<VQADATB_UPDATE)\n#define VQADATF_DSLEEP (1<<VQADATB_DSLEEP)\n#define VQADATF_LSLEEP (1<<VQADATB_LSLEEP)\n#define VQADATF_DDONE  (1<<VQADATB_DDONE)\n#define VQADATF_LDONE  (1<<VQADATB_LDONE)\n#define VQADATF_PRIMED (1<<VQADATB_PRIMED)\n#define VQADATF_PAUSED (1<<VQADATB_PAUSED)\n\n\n/* VQAHandleP: Private VQA file handle. Must be obtained by calling\n *             VQA_Alloc() and freed through VQA_Free(). This is the only\n *             legal way to obtain and dispose of a VQAHandle.\n *\n * VQAio     - Something meaningful to the IO manager. (See DOCS)\n * IOHandler - IO handler callback.\n * VQABuf    - Pointer to internal data buffers.\n * Config    - Configuration structure.\n * Header    - VQA header structure.\n * vocfh     - Override audiotrack file handle.\n */\ntypedef struct _VQAHandleP {\n\tunsigned long VQAio;\n\tlong          (*IOHandler)(VQAHandle *vqa, long action, void *buffer,\n\t                          long nbytes);\n\tVQAData       *VQABuf;\n\tVQAConfig     Config;\n\tVQAHeader     Header;\n\tlong          vocfh;\n\tCaptionInfo   *Caption;\n\tCaptionInfo   *EVA;\n} VQAHandleP;\n\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n/* Loader/Drawer system. */\nlong VQA_LoadFrame(VQAHandle *vqa);\nvoid VQA_Configure_Drawer(VQAHandleP *vqap);\nlong User_Update(VQAHandle *vqa);\n\n/* Timer system. */\nlong VQA_StartTimerInt(VQAHandleP *vqap, long init);\nvoid VQA_StopTimerInt(VQAHandleP *vqap);\nvoid VQA_SetTimer(VQAHandleP *vqap, long time, long method);\nunsigned long VQA_GetTime(VQAHandleP *vqap);\nlong VQA_TimerMethod(void);\n\n/* Audio system. */\n#if(VQAAUDIO_ON)\nlong VQA_OpenAudio(VQAHandleP *vqap , HWND window);\nvoid VQA_CloseAudio(VQAHandleP *vqap);\nlong VQA_StartAudio(VQAHandleP *vqap);\nvoid VQA_StopAudio(VQAHandleP *vqap);\nlong CopyAudio(VQAHandleP *vqap);\n#endif\n\n/* Debugging system. */\nvoid VQA_InitMono(VQAHandleP *vqap);\nvoid VQA_UpdateMono(VQAHandleP *vqap);\n\n#endif /* VQAPLAYP_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQFILE_H\n#define VQFILE_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     VQFile.h\n*\n* DESCRIPTION\n*     VQ file format definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*      \n* DATE\n*     September 27, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\iff.h>\n\n/* Disable Watcom structure alignment. */\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n\n/*---------------------------------------------------------------------------\n * STRUCTURE DEFINITIONS AND RELATED INFORMATION\n *-------------------------------------------------------------------------*/\n\n/* VQHeader: VQ header.\n *\n * Version     - VQ file version\n * Flags       - Various flags (see below)\n * ImageWidth  - Width of constructed image in pixels.\n * ImageHeight - Height of contructed image in pixels.\n * BlockType   - Type of codebook block. (EX: rectangle)\n * BlockWidth  - Width of a codebook block in pixels.\n * BlockHeight - Height of a codebook block in pixels.\n * BlockDepth  - Depth of a codebook block in bits.\n * CBEntries   - Number of entries in the codebook.\n * VPtrType    - Vector pointer type. (IE: Banked)\n * PalStart    - Starting entry position of palette.\n * PalLength   - Number of palette entries the palette.\n * PalDepth    - Depth of palette entries in bits.\n * ColorModel  - Color model of this VQ\n */\ntypedef struct _VQHeader {\n\tshort Version;\n\tshort Flags;\n\tshort ImageWidth;\n\tshort ImageHeight;\n\tshort BlockType;\n\tshort BlockWidth;\n\tshort BlockHeight;\n\tshort BlockDepth;\n\tshort CBEntries;\n\tshort VPtrType;\n\tshort PalStart;\n\tshort PalLengh;\n\tshort PalDepth;\n\tshort ColorModel;\n} VQHeader;\n\n\n/* VQ file flags */\n#define VQHB_CBCOMP 0 /* Codebook compressed */\n#define VQHB_CTCOMP 1 /* Color table compressed */\n#define VQHB_VPCOMP 2 /* Vector pointers compressed */\n#define VQHF_CBCOMP (1<<VQHB_CBCOMP)\n#define VQHF_CTCOMP (1<<VQHB_CTCOMP)\n#define VQHF_VPCOMP (1<<VQHB_VPCOMP)\n\n/* Block types */\n#define VQBT_RECT 0 /* Rectangle Width X Height */\n\n/* Color models */\n#define VQCM_PALETTED 0 /* Palette (8 bit indices) */\n#define VQCM_RGBTRUE  1 /* RBG truecolor (24 bit) */\n#define VQCM_YBRTRUE  2 /* YCbCr truecolor */\n\n\n/*---------------------------------------------------------------------------\n * VQ FILE CHUNK ID DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n#define ID_VQHR MAKE_ID('V','Q','H','R') /* VQ Header */\n#define ID_VQCB MAKE_ID('V','Q','C','B') /* VQ Codebook */\n#define ID_VQCT MAKE_ID('V','Q','C','T') /* VQ Color Table (palette) */\n#define ID_VQVP MAKE_ID('V','Q','V','P') /* VQ Vector pointers */\n\n#ifdef __WATCOMC__\n#pragma pack();\n#endif\n\n#endif /* VQFILE_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/ALL.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMALL_H\n#define VQMALL_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     all.h\n*\n* DESCRIPTION\n*     All VQMisc32 library definitions. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 5, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\iff.h>\n#include <vqm32\\mono.h>\n#include <vqm32\\portio.h>\n#include <vqm32\\profile.h>\n#include <vqm32\\targa.h>\n#include <vqm32\\compress.h>\n#include <vqm32\\video.h>\n#include <vqm32\\palette.h>\n#include <vqm32\\vesavid.h>\n#include <vqm32\\vesablit.h>\n#include <vqm32\\graphics.h>\n#include <vqm32\\mixfile.h>\n#include <vqm32\\crc.h>\n#include <vqm32\\huffman.h>\n#include <vqm32\\mem.h>\n\n#endif /* VQMALL_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/CAPTOKEN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMCAPTOKEN_H\n#define VQMCAPTOKEN_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     captoken.h\n*\n* DESCRIPTION\n*     Text caption script definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 26, 1995\n*\n****************************************************************************/\n\n/* CaptionText: This structure describes a line of text to be displayed\n *              with the video/audio.\n *\n * Size     - Size of caption in bytes.\n * OnFrame  - Frame number to display caption.\n * OffFrame - Frame number to clear caption.\n * Flags    - Display modifiers.\n * CPF      - Characters to draw per frame.\n * Xpos     - X pixel position to display caption.\n * Ypos     - Y pixel position to display caption.\n * BgPen    - Background pen to use.\n * FgPen    - Foreground pen to use.\n * Text     - Text string to display. (WORD aligned)\n */\ntypedef struct _CaptionText {\n\tunsigned short Size;\n\tunsigned short OnFrame;\n\tunsigned short OffFrame;\n\tunsigned char  Flags;\n\tchar           CPF;\n\tunsigned short Xpos;\n\tunsigned short Ypos;\n\tchar           BgPen;\n\tchar           FgPen;\n\tchar           Text[];\n} CaptionText;\n\n/* CaptionText flag definitions. */\n#define CTF_JUSTIFY\t(3<<0)  /* Justification field. */\n#define CTF_ABS     (0<<0)  /* Use absolute X,Y positions. */\n#define CTF_CENTER  (1<<0)  /* Justify on Center */\n#define CTF_LEFT    (2<<0)  /* Justify on left */\n#define CTF_RIGHT   (3<<0)  /* Justify on right */\n#define CTF_FLASH   (1<<4)  /* Flash text. */\n\n/* Function prototypes. */\nlong BuildCaptions(char *name, char *buffer);\n\n#endif /* VQMCAPTOKEN_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/COMPRESS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMCOMP_H\n#define VQMCOMP_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     compress.h\n*\n* DESCRIPTION\n*     Compression definitions. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nunsigned long __cdecl LCW_Compress(char const *source, char *dest,\n\t\tunsigned long length);\nunsigned long __cdecl LCW_Uncompress(char const *source, char *dest,\n\t\tunsigned long length);\nlong AudioZap(void *source, void *dest, long size);\nlong __cdecl AudioUnzap(void *source, void *dest, long);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMCOMP_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/CRC.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMCRC_H\n#define VQMCRC_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     CRC.h\n*\n* DESCRIPTION\n*     CRC calculation definitions.\n*\n* PROGRAMMER\n*     Joe L. Bostic\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nlong __cdecl Calculate_CRC(void const *buffer, long length);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMCRC_H */\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/FONT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMFONT_H\n#define VQMFONT_H\n/****************************************************************************\n*\n*        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\n*\n*---------------------------------------------------------------------------\n*\n* FILE\n*     font.h\n*\n* DESCRIPTION\n*     Font definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     March 9, 1995\n*\n****************************************************************************/\n\n/* Font: A Westwood style font.\n *\n * Size       - Size of font.\n * CompMethod - Compression method of font. (0 = none)\n * NumBlks    - Number of data blocks.\n * InfoBlk    - Offset to font information block.\n * OffsetBlk  - Offset to character offset block.\n * WidthBlk   - Offset to character width block.\n * DataBlk    - Offset to character data block.\n * HeightBlk  - Offset to character height block.\n */\ntypedef struct _Font {\n\tunsigned short Size;\n\tunsigned char  CompMethod;\n\tunsigned char  NumBlks;\n\tunsigned short InfoBlk;\n\tunsigned short OffsetBlk;\n\tunsigned short WidthBlk;\n\tunsigned short DataBlk;\n\tunsigned short HeightBlk;\n} Font;\n\ntypedef struct _FontInfo {\n\tlong huh;\n\tunsigned char MaxHeight;\n\tunsigned char MaxWidth;\n} FontInfo;\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern void const *FontPtr;\nextern int FontXSpacing;\nextern int FontYSpacing;\n\n#ifdef __cplusplus\n}\n#endif\n\nextern char FontWidth;\nextern char FontHeight;\nextern char *FontWidthBlockPtr;\n\n/* Function prototypes. */\nvoid *cdecl Load_Font(char const *name);\nvoid *cdecl Set_Font(void const *font);\nunsigned short __cdecl String_Pixel_Width(char const *string);\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef __WATCOMC__\nlong __cdecl __saveregs Char_Pixel_Width(char chr);\n#else\nlong __cdecl Char_Pixel_Width(char chr);\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMFONT_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/GRAPHICS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMGRAPHICS_H\n#define VQMGRAPHICS_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     graphics.h\n*\n* DESCRIPTION\n*     Graphic rendering and manipulation definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 27, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid __cdecl Eor_Region(long sx, long sy, long dx, long dy, long color);\nvoid __cdecl Fill_Rect(long x1, long y1, long x2, long y2, long color);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMGRAPHICS_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/HUFFMAN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef HUFFMAN_H\n#define HUFFMAN_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     huffman.h\n*\n* DESCRIPTION\n*     Huffman order 0 compress/decompress definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     May 19, 1995\n*\n****************************************************************************/\n\n\n/* TreeNode: Huffman decoding tree node.\n *\n * count  - Weight of the node in the tree.\n * child0 - Child node 0\n * child1 - Child node 1\n */\ntypedef struct _TreeNode {\n \tunsigned long  count;\n\tunsigned short child0;\n\tunsigned short child1;\n} TreeNode;\n\n\n/* HuffCode: This structure is used for storing the code for each symbol\n *            during encoding. A table of codes for each symbol is built\n *            from the Huffman tree.\n *\n * code - Code used to represent a symbol.\n * bits - Length of code in bits.\n */\ntypedef struct _HuffCode {\n\tunsigned short code;\n\tshort          bits;\n} HuffCode;\n\n\n#define HUFF_EOS 256 /* End of stream symbol */\n\n/* Prototypes */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nlong __cdecl HuffCompress(unsigned char *data, unsigned char *buffer,\n\t\tlong length, char *work);\n\nlong __cdecl HuffDecompress(unsigned char *data, unsigned char *buffer,\n\t\tlong length, char *work);\n\nvoid __cdecl HuffCount(unsigned char *data, TreeNode *nodes, long length,\n\t\tlong zero);\n\nvoid __cdecl HuffScaleCounts(TreeNode *nodes);\nlong __cdecl RLEHuffCounts(TreeNode *nodes, unsigned char *buffer);\nlong __cdecl BuildHuffTree(TreeNode *nodes);\n\nvoid __cdecl ConvertToCodes(TreeNode *nodes, HuffCode *codes,\n\t\tunsigned short code, short bits, short node);\n\nlong __cdecl HuffEncode(unsigned char *data, unsigned char *buffer,\n\t\tHuffCode *codes, long length);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* HUFFMAN_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/IFF.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMIFF_H\n#define VQMIFF_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     iff.h\n* \n* DESCRIPTION\n*     IFF (Interchange File Format) manager definitions.\n*     (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/* FormHeader - Structure associated with IFF forms.\n *\n * id   - IFF form id (IE: \"FORM\")\n * size - Length of IFF in bytes\n * type - Form type (IE: \"ILBM\")\n */\ntypedef struct _FormHeader {\n\tlong id;\n\tlong size;\n\tlong type;\n} FormHeader;\n\n/* Context - Structure associated with chunks.\n *\n * id   - Chunk identifier.\n * size - Size of chunk in bytes.\n * scan - Bytes read/written.\n */\ntypedef struct _Context {\n\tlong id;\n\tlong size;\n\tlong scan;\n} Context;\n\n/* IFFHandle - Structure associated with an active IFF read\\write session.\n *\n * fh    - DOS filehandle\n * flags - Internal flags used by IFF routines.\n * form  - IFF form information.\n * scan  - Bytes read/written\n * cn    - Context of current chunk.\n */\ntypedef struct _IFFHandle {\n\tlong       fh;\n\tlong       flags;\n\tFormHeader form;\n\tlong       scan;\n\tContext    cn;\n} IFFHandle;\n\n/*\tbit masks for \"flags\" field. */\n#define IFFB_READ  0\n#define IFFB_WRITE 1\n#define IFFF_READ  (1<<IFFB_READ)\n#define IFFF_WRITE (1<<IFFB_WRITE)\n\n/* IFF return codes. Most functions return either zero for success or\n * one of these codes. The exceptions are the read/write functions which,\n * return positive values for number of bytes read or written, or a negative\n * error code.\n *\n * IFFERR_EOF   - End of file.\n * IFFERR_READ  - Read error.\n * IFFERR_WRITE - Write error.\n * IFFERR_NOMEM - Unable to allocate memory.\n */\n#define IFFERR_EOF   -1\n#define IFFERR_READ  -2\n#define IFFERR_WRITE -3\n#define IFFERR_NOMEM -4\n\n/* Macros to make things easier. */\n#define REVERSE_LONG(id) (unsigned long)((((unsigned long)(id)>>24) \\\n\t\t&0x000000FFL)|(((unsigned long)(id)>>8) \\\n\t\t&0x0000FF00L)|(((unsigned long)(id)<<8) \\\n\t\t&0x00FF0000L)|(((unsigned long)(id)<<24)&0xFF000000L))\n\n#define REVERSE_WORD(id) ((unsigned short)((((unsigned short)(id)<<8) \\\n\t\t&0x00FF00)|(((unsigned short)(id)>>8)&0x0FF)))\n\n#define PADSIZE(size) (((size)+1)&(~1))\n\n#ifndef MAKE_ID\n#define MAKE_ID(a,b,c,d) ((long)((long)(d)<<24)|((long)(c)<<16)| \\\n\t\t((long)(b)<<8)|(long)(a))\n#endif\n\n/* Universal IFF identifiers */\n#define ID_FORM MAKE_ID('F','O','R','M')\n#define ID_LIST MAKE_ID('L','I','S','T')\n#define ID_PROP MAKE_ID('P','R','O','P')\n#define ID_NULL MAKE_ID(' ',' ',' ',' ')\n\n/* Prototypes */\nIFFHandle *OpenIFF(char *, long);\nvoid CloseIFF(IFFHandle *);\nlong ReadForm(IFFHandle *, FormHeader *);\nlong WriteForm(IFFHandle *, FormHeader *);\nlong ReadChunkHeader(IFFHandle *);\nlong WriteChunkHeader(IFFHandle *, long, long);\nlong WriteChunk(IFFHandle *, long, char *, long);\nlong WriteChunkBytes(IFFHandle *, char *, long);\nlong ReadChunkBytes(IFFHandle *, char *, long);\nlong SkipChunkBytes(IFFHandle *, long);\nlong FindChunk(IFFHandle *, long);\nchar *IDtoStr(long, char *);\nlong CurrentFilePos(IFFHandle *);\n\n#endif /* VQMIFF_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/MEM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAMEM_H\n#define VQAMEM_H\n/****************************************************************************\n*\n*        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\n*\n*---------------------------------------------------------------------------\n*\n* FILE\n*     mem.h\n*\n* DESCRIPTION\n*     Memory management definitions.\n*\n* PROGRAMMER\n*     Phil Gorrow\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 5, 1995\n*\n****************************************************************************/\n\n/* Definitions */\n#define DPMI_INT    0x0031\n#define DPMI_LOCK   0x0600\n#define DPMI_UNLOCK 0x0601\n\n/* Prototypes */\n#ifdef __WATCOMC__\nvoid DPMI_Lock(void const *ptr, long const size);\nvoid DPMI_Unlock(void const *ptr, long const size);\n#else\n#define DPMI_Lock(a,b)\n#define DPMI_Unlock(a,b)\n#endif\n\n#endif /* VQAMEM_H */\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/MIXFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMMIXFILE_H\n#define VQMMIXFILE_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     mixfile.h\n*\n* DESCRIPTION\n*     A mix file is basically a group of files concatinated together\n*     proceeded by a header describing where in the file each individual\n*     entry is located. These definitions are provided to simplify the access\n*     to these file entries.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/* Disable structure alignment.*/\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n\n/*---------------------------------------------------------------------------\n * STRUCTURE DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* MIXHeader: Mix file data header.\n *\n * Count - Number of entries contained in this mix file.\n * Size  - Size of Mix file.\n */\ntypedef struct _MIXHeader {\n\tshort Count;\n\tlong  Size;\n} MIXHeader;\n\n/* MIXSubBlock: Mix file entry descriptor.\n *\n * CRC    - Unique entry identifier.\n * Offset - Offset from beginning of data segment to entry.\n * Size   - Size of entry.\n */\ntypedef struct _MIXSubBlock {\n\tlong CRC;\n\tlong Offset;\n\tlong Size;\n} MIXSubBlock;\n\n/* MIXHandle: Mix file handle.\n *\n * Name    - Pointer to the name of the mix file this handle is for.\n * Size    - Size of entire mix file.\n * FH      - DOS file handle of opened entry.\n * Count   - Number of files contained in this mix.\n * Entries - Array of 'Count' MIXSubBlock structure entries.\n */\ntypedef struct _MIXHandle {\n\tchar        *Name;\n\tlong        Size;\n\tlong        FH;\n\tlong        Count;\n\tMIXSubBlock Entries[];\n} MIXHandle;\n\n/*---------------------------------------------------------------------------\n * PROTOTYPES\n *-------------------------------------------------------------------------*/\n\nMIXHandle *OpenMix(char *name);\nvoid CloseMix(MIXHandle *mix);\nlong OpenMixEntry(MIXHandle *mix, char *name);\n\n/* Restore original alignment */\n#ifdef __WATCOMC__\n#pragma pack();\n#endif\n\n#endif /* VQMMIXFILE_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/MONO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMMONO_H\n#define VQMMONO_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     mono.h\n*\n* DESCRIPTION\n*     Mono screen definitions. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Feburary 8, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid __cdecl Mono_Enable(void);\nvoid __cdecl Mono_Disable(void);\nvoid __cdecl Mono_Set_Cursor(long x, long y);\nvoid __cdecl Mono_Clear_Screen(void);\nvoid __cdecl Mono_Scroll(long lines);\nvoid __cdecl Mono_Put_Char(long character, long attrib);\nvoid __cdecl Mono_Draw_Rect(long x, long y, long w, long h, long attrib,\n\t\tlong thick);\n\nvoid __cdecl Mono_Text_Print(void const *text, long x, long y, long attrib);\nvoid __cdecl Mono_Print(void const *text);\nshort __cdecl Mono_View_Page(long page);\nshort __cdecl Mono_X(void);\nshort __cdecl Mono_Y(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMMONO_H */\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/PALETTE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMPALETTE_H\n#define VQMPALETTE_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Palette.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     Palette definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid __cdecl SetPalette(unsigned char *palette,long numbytes,unsigned long slowpal);\nvoid __cdecl ReadPalette(void *palette);\nvoid __cdecl SetDAC(long color, long red, long green, long blue);\nvoid __cdecl TranslatePalette(void *pal24, void *pal15, long numbytes);\n\n#ifdef __cplusplus\n}\n#endif\n\nvoid SortPalette(unsigned char *pal, long numcolors);\n\n#endif /* VQMPALETTE_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/PORTIO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMPORTIO_H\n#define VQMPORTIO_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Portio.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     Hardware port I/O\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n#ifdef __BORLANDC__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nshort __cdecl inp(unsigned short portid);\nvoid __cdecl outp(unsigned short portid, short value);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* __BORLANDC__ */\n\n#endif /* VQMPORTIO_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/PROFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMPROFILE_H\n#define VQMPROFILE_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Profile.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     INI file profiling definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\nlong GetINIInt(char const *section, char const *entry,\n\t\tlong deflt, char *fname);\n\nlong GetINIString(char const *section, char const *entry, \n\t\tchar const *def, char *retbuffer, long retlen, char *fname);\n\nlong Get_Frame_Pathname(char *inifile,long anim_frame,char *ext,\n\t\tchar *outbuf);\n\n#endif /* VQMPROFILE_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/REALMODE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMREALMODE_H\n#define VQMREALMODE_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     realmode.h\n*\n* DESCRIPTION\n*     Real-mode interfacing definitions and equates. Many of the definitions\n*     and descriptions in this file were taken from other sources and\n*     compiled here for use in MISC32 library.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 6, 1995\n*\n****************************************************************************/\n\n/* REALPTR: Real-mode pointer (segment:offset16).\n *\n * The REALPTR data type is used in protected mode to hold real-mode\n * pointers. The type is an unsigned long value, were the upper 16 bits\n * are the segment number and the lower 16 bit are an offset. This type\n * and the associated macros are identical to that of the PHARLAP \"pltypes.h\"\n * definitions for easy of conversion to WATCOM/4GW.\n */\ntypedef unsigned long REALPTR;\n\n#define RP_OFF(rp) ((unsigned short)(((unsigned long)(rp)) & 0xFFFF))\n#define RP_SEG(rp) ((unsigned short)(((unsigned long)(rp)) >> 16))\n#define RP_SET(rp, off, seg) (rp = ((unsigned long)(seg) << 16) + (off))\n#define RP_INCR(rp, incr) (rp += ((unsigned long)(incr)) & 0xFFFF)\n\n#define MK_PTR(off, seg) (void *)((((unsigned long)seg&0xFFFF)<<4)+off)\n\n/* RMInfo: Real-mode interrupt call structure.\n *\n * Information that needs to be passed down to the real-mode interrupt is\n * transfered using this structure. The address to this protected-mode\n * structure (allocated by user) is passed into DPMI function 0x300. DOS/4GW\n * will then use this information to set up the real-mode registers, switch\n * to real-mode and then execute the interrupt in real-mode.\n */\ntypedef struct _RMInfo {\n\tlong  edi;\n\tlong  esi;\n\tlong  ebp;\n\tlong  reservedbysystem;\n\tlong  ebx;\n\tlong  edx;\n\tlong  ecx;\n\tlong  eax;\n\tshort flags;\n\tshort es,ds,fs,gs,ip,cs,sp,ss;\n} RMInfo;\n\n#endif /* VQMREALMODE_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/SOSCOMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*  File              : soscomp.h\n*  Date Created      : 6/1/94\n*  Description       :\n*\n*  Programmer(s)     : Nick Skrepetos\n*  Last Modification : 10/1/94 - 11:37:9 AM\n*  Additional Notes  : Modified by Denzil E. Long, Jr.\n*\n*****************************************************************************\n*            Copyright (c) 1994,  HMI, Inc.  All Rights Reserved            *\n****************************************************************************/\n\n#ifndef  _SOS_COMPRESS\n#define  _SOS_COMPRESS\n\n/* compression types */\nenum {\n\t_ADPCM_TYPE_1,\n\t};\n\n/* define compression structure */\ntypedef struct _tagCOMPRESS_INFO {\n\tchar       *lpSource;\n\tchar       *lpDest;\n\tunsigned long dwCompSize;\n\tunsigned long dwUnCompSize;\n\tshort         wBitSize;\n\tshort\t\t\t    wChannels;\n\tunsigned long dwSampleIndex;\n\tlong          dwPredicted;\n\tlong          dwDifference;\n\tshort         wCodeBuf;\n\tshort         wCode;\n\tshort         wStep;\n\tshort         wIndex;\n\n\tunsigned long dwSampleIndex2; //added BP for channel 2\n\tlong          dwPredicted2;   //added BP for channel 2\n\tlong          dwDifference2; \t//added BP for channel 2\n\tshort         wCodeBuf2; \t\t//added BP for channel 2\n\tshort         wCode2; \t\t\t//added BP for channel 2\n\tshort         wStep2; \t\t\t//added BP for channel 2\n\tshort         wIndex2; \t\t\t//added BP for channel 2\n\t} _SOS_COMPRESS_INFO;\n\n/* compressed file type header */\ntypedef struct _tagCOMPRESS_HEADER {\n\tunsigned long dwType;              // type of compression\n\tunsigned long dwCompressedSize;    // compressed file size\n\tunsigned long dwUnCompressedSize;  // uncompressed file size\n\tunsigned long dwSourceBitSize;     // original bit size\n\tchar          szName[16];          // file type, for error checking\n\t} _SOS_COMPRESS_HEADER;\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid __cdecl VQA_sosCODECInitStream(_SOS_COMPRESS_INFO *);\nunsigned long __cdecl VQA_sosCODECCompressData(_SOS_COMPRESS_INFO *,unsigned long);\nunsigned long __cdecl VQA_sosCODECDecompressData(_SOS_COMPRESS_INFO *,unsigned long);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/TARGA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMTARGA_H\n#define VQMTARGA_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Targa.h (32-Bit protected mode)\n* \n* DESCRIPTION\n*     Targa Image File definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/*---------------------------------------------------------------------------\n * Targa Header definitions\n *-------------------------------------------------------------------------*/\n\n/* TGAHeader - Targa Image File header.\n *\n * IDLength        - Size of Image ID field\n * ColorMapType    - Color map type.\n * ImageType       - Image type code.\n * CMapStart       - Color map origin.\n * CMapLength      - Color map length.\n * CMapDepth       - Depth of color map entries.\n * XOffset         - X origin of image.\n * YOffset         - Y origin of image.\n * Width           - Width of image.\n * Height          - Height of image.\n * PixelDepth      - Image pixel size\n * ImageDescriptor - Image descriptor byte.\n */\ntypedef struct _TGAHeader {\n\tchar  IDLength;\n\tchar  ColorMapType;\n\tchar  ImageType;\n\tshort CMapStart;\n\tshort CMapLength;\n\tchar  CMapDepth;\n\tshort XOffset;\n\tshort YOffset;\n\tshort Width;\n\tshort Height;\n\tchar  PixelDepth;\n\tchar  ImageDescriptor;\n} TGAHeader;\n\n/* ImageType definiton */\n#define TGA_NOIMAGE           0  /* No image data included in file */\n#define TGA_CMAPPED           1  /* Color-mapped image data */\n#define TGA_TRUECOLOR         2  /* Truecolor image data */\n#define TGA_MONO              3  /* Monochrome image data */\n#define TGA_CMAPPED_ENCODED   9  /* Color-mapped image data (Encoded) */\n#define TGA_TRUECOLOR_ENCODED 10 /* Truecolor image data (Encoded) */\n#define TGA_MONO_ENCODED      11 /* Monochrome image data (Encoded) */\n\n/* ImageDescriptor definition */\n#define TGAF_ATTRIB_BITS (0x0F<<0) /* Number of attribute bits per pixel */\n#define TGAF_XORIGIN     (1<<4)\n#define TGAF_YORIGIN     (1<<5)\n\n/*---------------------------------------------------------------------------\n * Targa Handle definitions\n *-------------------------------------------------------------------------*/\n\n/* TGAHandle - Targa Image File handle.\n *\n * fh     - File handle returned by open().\n * mode   - Access mode.\n * header - TGAHeader structure.\n */\ntypedef struct _TGAHandle {\n\tshort          fh;\n\tunsigned short mode;\n\tTGAHeader      header;\n} TGAHandle;\n\n/* Access modes. */\n#define TGA_READMODE  0\n#define TGA_WRITEMODE 1\n#define TGA_RDWRMODE  2\n\n/* Error codes */\n#define TGAERR_OPEN         -1\n#define TGAERR_READ         -2\n#define TGAERR_WRITE        -3\n#define TGAERR_SYNTAX       -4\n#define TGAERR_NOMEM        -5\n#define TGAERR_NOTSUPPORTED -6\n \n/*---------------------------------------------------------------------------\n * Function prototypes\n *-------------------------------------------------------------------------*/\n\nTGAHandle *OpenTarga(char *, unsigned short);\nvoid CloseTarga(TGAHandle *);\nlong LoadTarga(char *, char *, char *);\nlong SaveTarga(char *, TGAHeader *, char *, char *);\nvoid XFlipTarga(TGAHeader *, char *);\nvoid YFlipTarga(TGAHeader *, char *);\n\n#endif /* VQMTARGA_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/TEXT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMTEXT_H\n#define VQMTEXT_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     text.h\n*\n* DESCRIPTION\n*     Text printing definitions. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     March 13, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nlong __cdecl Text_Print(char *string, long x, long y, long fcol, long bcol);\nvoid __cdecl Draw_Char(long character, long x, long y);\nvoid __cdecl Set_Font_Palette_Range(void *palette, long start, long end);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMTEXT_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/VESABLIT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMVESABLIT_H\n#define VQMVESABLIT_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     VESABlit.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     VESA bitblit routines.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\video.h>\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\nvoid VESA_Blit_640x480(DisplayInfo *disp,unsigned char *buf,long x1,\n\t\tlong y1,long width,long height);\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid __cdecl Blit_VESA640x480(DisplayInfo *disp,unsigned char *buf,long x1,\n\t\tlong y1,long width,long height);\n\nvoid __cdecl Buf_320x200_To_VESA_320x200(unsigned char *buffer, long grain);\nvoid __cdecl Buf_320x200_To_VESA_640x400(unsigned char *buffer, long grain);\nvoid __cdecl Buf_320x200_To_VESA_32K(unsigned char *buffer,\n\t\tunsigned char *palette, long grain);\n\nvoid __cdecl Copy_Row(char *, char *, long);\nvoid __cdecl Copy_Word_Row(char *source, char *dest, char *palette,\n\t\tlong numbytes);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMVESABLIT_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/VESAVID.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMVESAVID_H\n#define VQMVESAVID_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     VESAVid.h (32-Bit protected mode)\n* \n* DESCRIPTION\n*     VESA video manager definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n#ifndef __WATCOMC__\n#include <pharlap.h>\n#else\n#include \"realmode.h\"\n#endif\n\n/*---------------------------------------------------------------------------\n * VESA Video Modes\n *-------------------------------------------------------------------------*/\n\n#define\tVESA_640X400_256   0x100\n#define\tVESA_640X480_256   0x101\n#define\tVESA_800X600_16    0x102\n#define\tVESA_800X600_256   0x103\n#define\tVESA_1024X768_16   0x104\n#define\tVESA_1024X768_256  0x105\n#define\tVESA_1280X400_16   0x106\n#define\tVESA_1280X400_256  0x107\n#define\tVESA_TEXT_80X60    0x108\n#define\tVESA_TEXT_132X25   0x109\n#define\tVESA_TEXT_132X60   0x10C\n#define\tVESA_320X200_32K_1 0x10D\n#define\tVESA_320X200_32K_2 0x10E\n#define\tVESA_640X480_32K   0x110\n#define\tVESA_640X480_65K   0x111\n#define\tVESA_640X480_16M   0x112\n#define\tVESA_800X600_32K   0x113\n#define\tVESA_800X600_65K   0x114\n#define\tVESA_1024X768_32K  0x116\n#define\tVESA_1024X768_65K  0x117\n\n#define\tVESA_MIN VESA_640X400_256\n#define\tVESA_MAX VESA_1024X768_65K\n\n/*---------------------------------------------------------------------------\n * Structure definitions\n *-------------------------------------------------------------------------*/\n\n/* VESAInfo - General information about this VESA implementation.\n *            (Filled in by VESA BIOS Function 0)\n *\n * Signature    - Will always be 'VESA'\n * Version      - Version #\n * OEMString    - OEM ID string\n * Capabilities - Not defined by VESA yet\n * AvailModes   - List of available modes; terminated with -1 (0xffff)\n * TotalMemory  - ???\n * Reserved     - Pads structure to 256 bytes total\n */\ntypedef struct _VESAInfo {\n\tchar           Signature[4];\n\tunsigned short Version;\n\tREALPTR        OEMString;\n\tunsigned long  Capabilities;\n\tREALPTR        AvailModes;\n\tunsigned short TotalMemory;\n\tunsigned char  Reserved[236];\n} VESAInfo;\n\n/* VESAModeInfo - Information about this VESA mode.\n *                (Filled in by VESA BIOS Function 1)\n *\n * Attributes       - bit 0: 1 = mode is supported\n *                    bit 1: 1 = optional info available\n *                    bit 2: 1 = std BIOS output functions valid in this mode\n *                    bit 3: 0 = monochrome, 1 = color\n *                    bit 4: 0 = text mode, 1 = graphics\n * WinA_Attributes  - bit 0 = window exists, bit 1=readable, bit 2= writable\n * WinB_Attributes  - bit 0 = window exists, bit 1=readable, bit 2= writable\n * WinGranularity   - smallest address boundary window can be placed upon;\n *                    size is in KB (ie 64, 32, 4)\n * WinSize          - size of windows in KB (ie 64, 32)\n * WinA_Segment     - location of Window A in CPU space (usually 0xa000)\n * WinB_Segment     - location of Window B in CPU space (usually 0xb000)\n * WinFunc          - address of window-setting function (This is provided \n *                    as an alternative to Int 10 for speed.)\n * BytesPerScanline - # bytes per scan line\n * \n * Optional info (available if bit 1 of Attributes is set):\n *\n * XRes             - X-resolution\n * YRes             - Y-resolution\n * XCharSize        - Horizontal size of char cell\n * YCharSize        - Vertical size of char cell\n * NumPlanes        - # of memory planes (???)\n * BitsPerPixel     - # bites per pixel\n * NumBanks         - # of banks (ie planes)\n * MemoryModel      - 00h = Text mode\n *                    01h = CGA mode\n *                    02h = Hercules\n *                    03h = 4 plane planar mode\n *                    04h = packed pixel mode (1 byte/pixel)\n *                    05h = non-chain 4, 256-color mode\n *                    06-0Fh = \n *                    10-FFh = OEM-specific\n * BankSize         - Bank size in KB\n */\ntypedef struct _VESAModeInfo {\n\tunsigned short Attributes;\n\tunsigned char  WinA_Attributes;\n\tunsigned char  WinB_Attributes;\n\tunsigned short WinGranularity;\n\tunsigned short WinSize;\n\tunsigned short WinA_Segment;\n\tunsigned short WinB_Segment;\n\tREALPTR        WinFunc;\n\tunsigned short BytesPerScanline;\n\tunsigned short XRes;\n\tunsigned short YRes;\n\tunsigned char  XCharSize;\n\tunsigned char  YCharSize;\n\tunsigned char  NumPlanes;\n\tunsigned char  BitsPerPixel;\n\tunsigned char  NumBanks;\n\tunsigned char  MemoryModel;\n\tunsigned char  BankSize;\n\tunsigned char  NumInputPages;\n\tunsigned char  Reserved;\n\tunsigned char  RedMaskSize;\n\tunsigned char  RedFieldPosition;\n\tunsigned char  GreenMaskSize;\n\tunsigned char  GreenFieldPosition;\n\tunsigned char  BlueMaskSize; \n\tunsigned char  BlueFieldPosition;\n\tunsigned char  RsvdMaskSize;\n\tunsigned char  RsvdFieldPosition;\n\tunsigned char  DirectColorModeInfo;\n\tunsigned char  pad[216];\n} VESAModeInfo;\n\n/*---------------------------------------------------------------------------\n * Function prototypes\n *-------------------------------------------------------------------------*/\n\nlong InitVESA(void);\nvoid UninitVESA(void);\nVESAModeInfo *SetVESAMode(long mode);\nVESAModeInfo *ReadVESAModeInfo(long mode);\nvoid SetVESAWindow(long grain_num);\n\n#endif /* VQMVESAVID_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/VESAVID.I",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*       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\n;*\n;*----------------------------------------------------------------------------\n;*\n;* FILE\n;*     vesavid.i\n;*\n;* DESCRIPTION\n;*     VESA video manager definitions. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;****************************************************************************\n\n;----------------------------------------------------------------------------\n; VESA video modes\n;----------------------------------------------------------------------------\n\nVESA_640X400_256   EQU\t0x100\nVESA_640X480_256   EQU\t0x101\nVESA_800X600_16    EQU\t0x102\nVESA_800X600_256   EQU\t0x103\nVESA_1024X768_16   EQU\t0x104\nVESA_1024X768_256  EQU\t0x105\nVESA_1280X400_16   EQU\t0x106\nVESA_1280X400_256  EQU\t0x107\nVESA_TEXT_80X60    EQU\t0x108\nVESA_TEXT_132X25   EQU\t0x109\nVESA_TEXT_132X60   EQU\t0x10C\nVESA_320X200_32K_1 EQU\t0x10D\nVESA_320X200_32K_2 EQU\t0x10E\nVESA_640X480_32K   EQU\t0x110\nVESA_640X480_65K   EQU\t0x111\nVESA_640X480_16M   EQU\t0x112\nVESA_800X600_32K   EQU\t0x113\nVESA_800X600_65K   EQU\t0x114\nVESA_1024X768_32K  EQU\t0x116\nVESA_1024X768_65K  EQU\t0x117\n\nVESA_MIN EQU\tVESA_640X400_256\nVESA_MAX EQU\tVESA_1024X768_65K\n\n;----------------------------------------------------------------------------\n; Structure definitions\n;----------------------------------------------------------------------------\n\n; VESAInfo - General information about this VESA implementation.\n;            (Filled in by VESA BIOS Function 0)\n;\n; Signature    - Will always be 'VESA'\n; Ver          - Version #\n; OEMString    - OEM ID string\n; Capabilities - Not defined by VESA yet\n; AvailModes   - List of available modes; terminated with -1 (0xffff)\n; TotalMemory  - ???\n; Reserved     - Pads structure to 256 bytes total\n\n\tSTRUC\tVESAInfo\nSignature\tDD\t?\nVer\tDW\t?\nOEMString\tDD\t?\nCapabilities\tDD\t?\nAvailModes\tDD\t?\nTotalMemory\tDW\t?\nReserved\tDB\t236 DUP (?)\n\tENDS\tVESAInfo\n\n; VESAModeInfo - Information about this VESA mode.\n;                (Filled in by VESA BIOS Function 1)\n;\n; Attributes       - bit 0: 1 = mode is supported\n;                    bit 1: 1 = optional info available\n;                    bit 2: 1 = std BIOS output functions valid in this mode\n;                    bit 3: 0 = monochrome, 1 = color\n;                    bit 4: 0 = text mode, 1 = graphics\n; WinA_Attributes  - bit 0 = window exists, bit 1=readable, bit 2= writable\n; WinB_Attributes  - bit 0 = window exists, bit 1=readable, bit 2= writable\n; WinGranularity   - smallest address boundary window can be placed upon;\n;                    size is in KB (ie 64, 32, 4)\n; WinSize          - size of windows in KB (ie 64, 32)\n; WinA_Segment     - location of Window A in CPU space (usually 0xa000)\n; WinB_Segment     - location of Window B in CPU space (usually 0xb000)\n; WinFunc          - address of window-setting function (This is provided \n;                    as an alternative to Int 10 for speed.)\n; BytesPerScanline - # bytes per scan line\n; \n; Optional info (available if bit 1 of Attributes is set):\n;\n; XRes             - X-resolution\n; YRes             - Y-resolution\n; XCharSize        - Horizontal size of char cell\n; YCharSize        - Vertical size of char cell\n; NumPlanes        - # of memory planes (???)\n; BitsPerPixel     - # bites per pixel\n; NumBanks         - # of banks (ie planes)\n; MemoryModel      - 00h = Text mode\n;                    01h = CGA mode\n;                    02h = Hercules\n;                    03h = 4 plane planar mode\n;                    04h = packed pixel mode (1 byte/pixel)\n;                    05h = non-chain 4, 256-color mode\n;                    06-0Fh = \n;                    10-FFh = OEM-specific\n; BankSize         - Bank size in KB\n\n\t\tSTRUC\tVESAModeInfo \nAttributes\t\tDW\t?\nWinA_Attributes\tDB\t?\nWinB_Attributes\tDB\t?\nWinGranularity\tDW\t?\nWinSize\t\tDW\t?\nWinA_Segment\t\tDW\t?\nWinB_Segment\t\tDW\t?\nWinFunc\t\tDD\t?\nBytesPerScanline\tDW\t?\nXRes\t\tDW\t?\nYRes\t\tDW\t?\nXCharSize\t\tDB\t?\nYCharSize\t\tDB\t?\nNumPlanes\t\tDB\t?\nBitsPerPixel\t\tDB\t?\nNumBanks\t\tDB\t?\nMemoryModel\t\tDB\t?\nBankSize\t\tDB\t?\nNumInputPages\t\tDB\t?\nReserved\t\tDB\t?\nRedMaskSize\t\tDB\t?\nRedFieldPosition\tDB\t?\nGreenMaskSize\t\tDB\t?\nGreenFieldPosition\tDB\t?\nBlueMaskSize\t\tDB\t?\nBlueFieldPosition\tDB\t?\nRsvdMaskSize\t\tDB\t?\nRsvdFieldPosition\tDB\t?\nDirectColorModeInfo\tDB\t?\npad\t\tDB\t216 DUP (?)\n\t\tENDS\tVESAModeInfo\n\n;----------------------------------------------------------------------------\n; Function definitions\n;----------------------------------------------------------------------------\n\n\tGLOBAL C InitVESA:PROC\n\tGLOBAL C UninitVESA:PROC\n\tGLOBAL C SetVESAMode:PROC\n\tGLOBAL C ReadVESAModeInfo:PROC\n\tGLOBAL C SetVESAWindow:PROC\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     SET_WINDOW - Sets window A to the specified bank.\n;\n; SYNOPSIS\n;     SET_WINDOW GrainNum\n;\n; FUNCTION\n;     This routine uses the C Set_Window function rather than going through\n;     the BIOS, for two reasons: (1) Speed, and (2) On the Cirrus Logic 54xx\n;     VESA cards, BIOS calls make noise while playing digital audio.\n;\n; INPUTS\n;     GrainNum - Granularity number.\n;\n; RESULT\n;     NONE\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tSET_WINDOW grain_num\n\tpush\tesi\n\tpush\tedi\n\tpush\tes\n\tcall\tSetVESAWindow C,grain_num\n\tpop\tes\n\tpop\tedi\n\tpop\tesi\n\tENDM\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/VGA.I",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     vga.i\n;*\n;* DESCRIPTION\n;*     VGA hardware definitions. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;****************************************************************************\n\n;----------------------------------------------------------------------------\n; VGA Registers\n;----------------------------------------------------------------------------\n\nR_SEQUENCER\t\tEQU\t03C4h\t;Sequencer Controller Index reg\nSEQ_RESET\t\tEQU\t00h\t;Reset\nSEQ_MAP_MASK\t\tEQU\t02h\t;Index in Sequencer of Map Mask reg\nSEQ_MEMORY_MODE\tEQU\t04h\t;Memory Mode\n\nR_GRAPHICS_CONTROLLER\tEQU\t03CEh\t;Graphics Controller Index reg\nGC_READ_MAP\t\tEQU\t04h\t;Index in GController of Read Map reg\nGC_MODE\t\tEQU\t05h\t;Read/Write Modes\nGC_MISC\t\tEQU\t06h\t;Read/Write Modes\nGC_BITMASK\t\tEQU\t08h\t;Index in GController of BitMask reg\n\nR_CRT_CONTROLLER\tEQU\t03D4h\t;CRT Controller Index reg\nCRT_VERT_TOTAL\tEQU\t06h\t;Vertical total\nCRT_OVERFLOW\t\tEQU\t07h\t;Overflow\nCRT_MAX_SCANLINE\tEQU\t09h\t;Max scan line\nCRT_STARTADDR_HIGH\tEQU\t0Ch\t;Bitmap start address high byte\nCRT_STARTADDR_LOW\tEQU\t0Dh\t;Bitmap start address low byte\nCRT_VERTRET_START\tEQU\t010h\t;Vertical retrace pulse start\nCRT_VERTRET_END\tEQU\t011h\t;Vertical retrace pulse end\nCRT_VERTDISP_END\tEQU\t012h\t;Vertical display end\nCRT_UNDERLINE\t\tEQU\t014h\t;Underline location\nCRT_START_VB\t\tEQU\t015h\t;Start vertical blank\nCRT_END_VB\t\tEQU\t016h\t;End vertical blank\nCRT_MODE_CONTROL\tEQU\t017h\t;Mode control\nR_MISC_OUTPUT\t\tEQU\t03C2h\t;Miscellaneous Output reg\n\n;----------------------------------------------------------------------------\n; Palette Registers\n;----------------------------------------------------------------------------\n\nPEL_READ_ADDR\t\tEQU\t03C7h\nPEL_WRITE_ADDR\tEQU\t03C8h\nPEL_DATA\t\tEQU\t03C9h\n\n;----------------------------------------------------------------------------\n; XMode planes, for the Map Mask register\n;----------------------------------------------------------------------------\n\nXPLANE_1\tEQU\t1\nXPLANE_2\tEQU\t2\nXPLANE_3\tEQU\t4\nXPLANE_4\tEQU\t8\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     SET_PLANE - Set an XMode plane.\n;\n; SYNOPSIS\n;     SET_PLANE plane\n;\n; INPUTS\n;     plane - Number of Xmode plane to set.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tSET_PLANE plane\n\tmov\tedx,R_SEQUENCER\n\tmov\teax,SEQ_MAP_MASK\n\tout\tdx,al\n\tinc\tedx\n\tmov\teax,plane\n\tout\tdx,al\n\tENDM\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     SET_BITMASK - Set the BitMask register.\n;\n; SYNOPSIS\n;     SET_BITMASK mask\n;\n; INPUTS\n;     mask - Bitmask to use.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tSET_BITMASK mask\n\tmov\tedx,R_GRAPHICS_CONTROLLER\n\tmov\teax,GC_BITMASK\n\tout\tdx,al\n\tinc\tedx\n\tmov\teax,mask\n\tout\tdx,al\n\tENDM\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     SET_WRITEMODE - Set the VGA writemode.\n;\n; SYNOPSIS\n;     SET_WRITEMODE mode\n;\n; INPUTS\n;     mode - Write mode.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tSET_WRITEMODE mode\n\tmov\tedx,R_GRAPHICS_CONTROLLER\n\tmov\teax,GC_MODE\n\tout\tdx,al\n\tinc\tedx\n\tin\tal,dx\t;Read the register\n\tand\tal,0FCh\t;Turn off 2 lower bits\n\tor\tal,mode\t;Set write mode\n\tout\tdx,al\n\tENDM\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     OUTPORT - Output data to a VGA register.\n;\n; SYNOPSIS\n;     OUTPORT port,register,data\n;\n; INPUTS\n;     port     - Port address.\n;     register - Register to write to.\n;     data     - Data to write.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tOUTPORT port,register,data\n\tmov\tedx,port\n\tmov\tal,register\n\tout\tdx,al\n\tinc\tedx\n\tmov\tal,data\n\tout\tdx,al\n\tENDM\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     INPORT - Input data from a VGA register.\n;\n; SYNOPSIS\n;     data = INPORT port,register\n;\n; INPUTS\n;     port     - Port address.\n;     register - Register to read from.\n;\n; RESULT\n;     data - Value read from port in AL.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tINPORT port,register\n\tmov\tedx,port\n\tmov\tal,register\n\tout\tdx,al\n\tinc\tedx\n\tin\tal,dx\n\tENDM\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/VIDEO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMVIDEO_H\n#define VQMVIDEO_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Video.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     Video manager definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\vesavid.h>\n\n/*---------------------------------------------------------------------------\n * VGA video modes\n *-------------------------------------------------------------------------*/\n\n#define\tTEXT_VIDEO 0x02\n#define\tMCGA 0x13\n#define\tXMODE_320X200 0x50\n#define\tXMODE_320X240 0x51\n#define\tXMODE_320X400 0x52\n#define\tXMODE_320X480 0x53\n#define\tXMODE_360X400 0x54\n#define\tXMODE_360X480 0x55\n\n#define\tXMODE_MIN 0x50\n#define\tXMODE_MAX 0x55\n\n/*---------------------------------------------------------------------------\n * Structure definitions\n *-------------------------------------------------------------------------*/\n\n/* DisplayInfo - Information about the current display.\n *\n * Mode     - Mode identification.\n * XRes     - X resolution of mode.\n * YRes     - Y resolution of mode.\n * VBIbit   - Polarity of vertical blank bit.\n * Extended - Pointer to mode specific data structure.\n */\ntypedef struct _DisplayInfo {\n\tlong Mode;\n\tlong XRes;\n\tlong YRes;\n\tlong VBIbit;\n\tvoid *Extended;\n} DisplayInfo;\n\n/*---------------------------------------------------------------------------\n * Function prototypes\n *-------------------------------------------------------------------------*/\n\nDisplayInfo *SetVideoMode(long mode);\nDisplayInfo *GetDisplayInfo(void);\nlong TestVBIBit(void);\nlong GetVBIBit(void);\n\nvoid SetupXPaging(void);\nvoid FlipXPage(void);\nunsigned char *GetXHidPage(void);\nunsigned char *GetXSeenPage(void);\nvoid DisplayXPage(long page);\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid __cdecl WaitNoVB(short vbibit);\nvoid __cdecl WaitVB(short vbibit);\nvoid __cdecl ClearVRAM(void);\nlong __cdecl SetXMode(long mode);\nvoid __cdecl ClearXMode(void);\nvoid __cdecl ShowXPage(unsigned long StartOffset);\nvoid __cdecl Xmode_BufferCopy_320x200(void *buff, void *screen);\nvoid __cdecl Xmode_Blit(void *buffer, void *screen, long imgwidth, long imgheight);\nvoid __cdecl MCGA_BufferCopy(unsigned char *buffer, unsigned char *dummy);\nvoid __cdecl MCGA_Blit(unsigned char *buffer, unsigned char *screen,\n\t\tlong imgwidth, long imgheight);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMVIDEO_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/VQM32/VIDEO.I",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*       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\n;*\n;*----------------------------------------------------------------------------\n;*\n;* FILE\n;*     video.i\n;*\n;* DESCRIPTION\n;*     Video manager definitions. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;****************************************************************************\n\n\tINCLUDE\t\"vesavid.i\"\n\n;----------------------------------------------------------------------------\n; Video Modes\n;----------------------------------------------------------------------------\n\nTEXT\tEQU\t002h\nMCGA\tEQU\t013h\nXMODE_320X200\tEQU\t050h\nXMODE_320X240\tEQU\t051h\nXMODE_320X400\tEQU\t052h\nXMODE_320X480\tEQU\t053h\nXMODE_360X400\tEQU\t054h\nXMODE_360X480\tEQU\t055h\n\n;----------------------------------------------------------------------------\n; Structure definitions\n;----------------------------------------------------------------------------\n\n; DisplayInfo - Information about the current display.\n;\n; Mode     - Mode identification\n; XRes     - X resolution\n; YRes     - Y resolution\n; VBIbit   - Polarity of vertical blank bit.\n; Extended - Pointer to mode specified data structure.\n\n\tSTRUC\tDisplayInfo\nMode\tDD\t?\nXRes\tDD\t?\nYRes\tDD\t?\nVBIbit\tDD\t?\nExtended\tDD\t?\n\tENDS\tDisplayInfo\n\n;----------------------------------------------------------------------------\n; Function definitions\n;----------------------------------------------------------------------------\n\n\tGLOBAL C GetDisplayInfo:NEAR\n\tGLOBAL C GetVBIBit:NEAR\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/WAVEFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef WAVEFILE_H\n#define WAVEFILE_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     wavefile.c\n*\n* DESCRIPTION\n*     WAVE file format definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*      \n* DATE\n*     February 21, 1995\n*\n****************************************************************************/\n\n/* WAVHeader: WAVE file header.\n *\n * RIFF - 4 byte identifier (always \"RIFF\").\n * Size - Size in bytes of entire file.\n * WAVE - 4 byte identifier (always \"WAVE\").\n */\ntypedef struct _WAVHeader {\n\tlong RIFF;\n\tlong Size;\n\tlong WAVE;\n} WAVHeader;\n\n/* WAVFormat: This structure describes the format of the audio data contained\n *            in the WAV file.\n *\n * FormatTag      - \n * Channels       - Number of channels (1 = mono, 2 = stereo).\n * SamplesPerSec  - Sampling rate.\n * AvgBytesPerSec - Bytes in 1 second of audio (Rate * SampleSize * Channels)\n * BlockAlign     - padding.\n * BitsPerSample  - Number of bits per sample (8, 16).\n */\ntypedef struct _WAVFormat {\n\tshort FormatTag;\n\tshort Channels;\n\tlong  SamplesPerSec;\n \tlong  AvgBytesPerSec;\n\tshort BlockAlign;\n\tshort BitsPerSample;\n} WAVFormat;\n\n#endif /* WAVEFILE_H */\n\n"
  },
  {
    "path": "WINVQ/INCLUDE/WWTYPES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef WWTYPES_H\n#define WWTYPES_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILENAME\n*     wwtypes.h\n*\n* DESCRIPTION\n*     Westwood standard types definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*      \n****************************************************************************/\n\n#define\tTRUE  1\n#define\tFALSE 0\n\n#define\tVOID    void\n#define\tPRIVATE static\n#define\tPUBLIC\n\n#define\tBOOL  short\n#define\tBYTE  char\n#define\tUBYTE unsigned char\n#define\tWORD  signed short\n#define\tUWORD unsigned short\n#define\tLONG  signed long\n#define\tULONG unsigned long\n\n#endif /* WWTYPES_H */\n\n"
  },
  {
    "path": "WINVQ/LIB/README.TXT",
    "content": "Library naming convention.\n\n   nnnssctm.lib\n\n   Where:\n     nnn = ID (such as 'VQA') 3 characters\n     ss  = Size field (32bit / 16bit) 2 characters\n     c   = Compiler name (W = Watcom, B = Borland)\n     t   = Compiler type (P = \"C++\", C = Standard \"C\")\n     m   = Memory model (F = flat, T = TNT)\n"
  },
  {
    "path": "WINVQ/VPLAY32/BCC32.CFG",
    "content": "-c\n-3\n-d\n-H=c:\\projects\\vplay32\\obj\\headers.sym\n-wpro\n-weas\n-wpre\n-IC:\\PROJECTS\\INCLUDE;C:\\DEV\\BC4\\INCLUDE;C:\\DEV\\TNT\\INCLUDE\n-DPHARLAP_TNT=1\n"
  },
  {
    "path": "WINVQ/VPLAY32/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# FILE\n#     makefile (Watcom C/C++ 10.0a)\n#\n# DESCRIPTION\n#     Makefile for test program\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n# \n# DATE\n#     February 10, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     WATCOM - Watcom C installation path.\n#\n#****************************************************************************\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n!ifndef %PRJ || %PRJVCS || %WATCOM\n!error Environment not configured.\n!endif\n\n.OPTIMIZE\n.ERASE\n\n#----------------------------------------------------------------------------\n# PROJECT DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJNAME = VPLAY4GW\nPRJDIR  = $(%PRJ)\\VPLAY32\n\nOBJECTS = &\n\tplyvqa32.obj\n\n#LIBRARYS = vqm32w.lib vqa32w.lib sosdw1cs.lib\nLIBRARYS = vqm32wp.lib vqa32wp.lib sosdw1ps.lib\n\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!ifdef %LIB\nLIBPATH = $(%PRJ)\\LIB;$(%LIB)\n!else\nLIBPATH = $(%PRJ)\\LIB;$(%WATCOM)\\LIB386\n!endif\n\n!ifdef %INCLUDE\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%INCLUDE)\n!else\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%WATCOM)\\H\n!endif\n\npath_c   = .\\\npath_cpp = .\\\npath_h   = .\\\npath_asm = .\\\npath_i   = .\\\npath_obj = .\\O\npath_lib = $(%PRJ)\\LIB\npath_exe = .\\\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULE EXTENSIONS AND PATHS\n#----------------------------------------------------------------------------\n\n.EXTENSIONS :\n.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i\n\n.c : $(path_c)\n.cpp : $(path_cpp)\n.cpp : $(path_cpp)\n.h : $(path_h)\n.asm : $(path_asm)\n.i : $(path_i)\n.obj : $(path_obj)\n.lib : $(path_lib)\n.exe : $(path_exe)\n\n#----------------------------------------------------------------------------\n# TOOLS, COMMANDS AND CONFIGURATIONS\n#----------------------------------------------------------------------------\n\nCC_CMD   = wcc386\nCCP_CMD  = wpp386\nASM_CMD  = tasm32\nLINK_CMD = wlink\nLIB_CMD  = wlib\n\nCC_OPTS  = -i$(INCLUDEPATH) -j -zp1 -5s -mf -oaeilrt -s -zq -d2\nASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /dPHARLAP_TNT=0\nLIB_OPTS = /b /c /q /t\nLINK_CFG = $(PRJNAME).lnk\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall : $(LINK_CFG) $(PRJNAME).exe .SYMBOLIC\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj :\n  $(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\n.cpp.obj :\n  $(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\n.asm.obj :\n\t$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\\$^.\n\n#----------------------------------------------------------------------------\n# BUILD THE APPLICATION\n#----------------------------------------------------------------------------\n\n$(PRJNAME).exe : $(OBJECTS) $(LIBRARYS) $(LINK_CFG)\n\t$(LINK_CMD) @$(LINK_CFG)\n\n#----------------------------------------------------------------------------\n# LINKER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(LINK_CFG) : makefile\n\t@echo Updating $(LINK_CFG)!\n\t@%create $(LINK_CFG)\n\t@%write $(LINK_CFG) SYSTEM dos4g\n\t@%write $(LINK_CFG) OPTION map\n\t@%write $(LINK_CFG) NAME $(PRJNAME)\n\t@%write $(LINK_CFG) DEBUG ALL\n\t@%write $(LINK_CFG) LIBPATH $(LIBPATH)\n\t@for %i in ($(OBJECTS)) do @%write $(LINK_CFG) FILE $(path_obj)\\%i\n\t@for %i in ($(LIBRARYS)) do @%write $(LINK_CFG) LIBRARY %i\n\n"
  },
  {
    "path": "WINVQ/VPLAY32/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VPlay32 - VQA player (32-bit protected mode)\n#\n# FILE\n#     Makefile\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n#      \n# DATE\n#     February 9, 1995\n#\n# ENVIROMENT\n#     PRJ    = Root projects path\n#     PRJVCS = Root path for projects version control archive\n#     BCDIR  = Root Borland installation path\n#     TNTDIR = Root Pharlap TNT-DOS Extender path\n#\n#****************************************************************************\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n!if !$d(PRJ) || !$d(PRJVCS) || !$d(BCDIR) || !$d(TNTDIR)\n!error Environment not configured.\n!endif\n\n.AUTODEPEND\n\n#----------------------------------------------------------------------------\n# PROJECT DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJNAME\t= vplaytnt\nPRJDIR  = $(PRJ)\\VPLAY32\n\nOBJECTS = \\\n\tobj\\plyvqa32.obj \\\n\nPRJLIBS = \\\n\tvqa32bp.lib \\\n\tvqm32bp.lib \\\n\t\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!if $d(LIB)\nLIBPATH = $(PRJ)\\LIB;$(LIB)\n!else\nLIBPATH = $(PRJ)\\LIB;$(TNTDIR)\\LIB;$(BCDIR)\\LIB\n!endif\n\n!if $d(INCLUDE)\nINCLUDEPATH\t= $(PRJ)\\INCLUDE;$(INCLUDE)\n!else\nINCLUDEPATH\t= $(PRJ)\\INCLUDE;$(TNTDIR)\\INCLUDE;$(BCDIR)\\INCLUDE\n!endif\n\n.path.asm\t= $(PRJDIR)\n.path.c\t\t= $(PRJDIR)\n.path.cpp\t= $(PRJDIR)\n.path.h\t\t= $(PRJDIR)\n.path.def\t= $(PRJDIR)\n.path.exe\t= $(PRJDIR)\n.path.obj\t= $(PRJDIR)\\OBJ\n.path.sym\t= $(PRJDIR)\\OBJ\n.path.map = $(PRJDIR)\\OBJ\n.path.lib\t= $(PRJ)\\LIB\n\n#----------------------------------------------------------------------------\n# TOOLS, COMMANDS AND CONFIGURATIONS\n#----------------------------------------------------------------------------\n\nCC_CMD   = bcc32\nASM_CMD  = tasm32\nLINK_CMD = tlink32\nLIB_CMD  = tlib\nTNT_CMD  = cfig386\n\nCC_CFG    = bcc32.cfg\nASM_CFG   = tasm32.cfg\nLINK_CFG  = tlink32.cfg\nLIB_CFG   = tlib.cfg\nCFG_FILES = $(CC_CFG) $(ASM_CFG) $(LINK_CFG) $(LIB_CFG)\nTNT_FLAGS = -minreal 256\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall: $(PRJNAME).exe\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj:\n\t$(CC_CMD) -P- -n$(.path.obj) {$< }\n\n.cpp.obj:\n\t$(CC_CMD) -P -n$(.path.obj) {$< }\n\n.asm.obj:\n\t$(ASM_CMD) @$(ASM_CFG) $<,$(.path.obj)\\$&\n\n#----------------------------------------------------------------------------\n# BUILD THE APPLICATION\n#----------------------------------------------------------------------------\n\n$(PRJNAME).exe: $(OBJECTS) $(PRJLIBS) $(PRJNAME).def\n\t$(LINK_CMD) @&&| \nc0x32.obj+\n$(OBJECTS)\n$(.path.exe)\\$(PRJNAME).exe\t \n$(.path.map)\\$(PRJNAME).map\n$(PRJLIBS)+\ndos32.lib+\ndosx32.lib+\nerrno.lib+\nimport32.lib+\ncw32.lib\n$(.path.def)\\$(PRJNAME).def\n|\n\n\t$(TNT_CMD) $(PRJNAME) $(TNT_FLAGS)\n\n#----------------------------------------------------------------------------\n# ALL OBJECTS DEPEND ON THE CONFIGURATION FILES\n#----------------------------------------------------------------------------\n\n$(OBJECTS):\t$(CFG_FILES)\n\n#----------------------------------------------------------------------------\n# COMPILER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(CC_CFG): makefile\n\tcopy &&|\n-c\n-3\n-d\n-H=$(.path.sym)\\headers.sym\n-wpro\n-weas\n-wpre\n-I$(INCLUDEPATH)\n-DPHARLAP_TNT=1\n#-v\n| $(CC_CFG)\n \n#----------------------------------------------------------------------------\n# ASSEMBLER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(ASM_CFG): makefile\n\tcopy &&|\n/la\n/t\n/m\n/w+\n/jJUMPS\n/ml\n/p\n/z\n/i$(PRJ)\\INCLUDE\n/zi\n| $(ASM_CFG)\n\n#----------------------------------------------------------------------------\n# LINKER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(LINK_CFG): makefile\n\tcopy &&|\n/c\n/m\n/Gm\n-L$(LIBPATH)\n-v\n| $(LINK_CFG)\n\n#----------------------------------------------------------------------------\n# LIBRARIAN CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(LIB_CFG):\tmakefile\n\tcopy &&|\n/C /E\n| $(LIB_CFG)\n\n\n"
  },
  {
    "path": "WINVQ/VPLAY32/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# FILE\n#     makefile (Watcom C/C++ 10.0a)\n#\n# DESCRIPTION\n#     Makefile for test program\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n# \n# DATE\n#     February 10, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     WATCOM - Watcom C installation path.\n#\n#****************************************************************************\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n!ifndef %PRJ || %PRJVCS || %WATCOM\n!error Environment not configured.\n!endif\n\n.OPTIMIZE\n.ERASE\n\n#----------------------------------------------------------------------------\n# PROJECT DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJNAME = VPLAY4GW\nPRJDIR  = $(%PRJ)\\VPLAY32\n\nOBJECTS = &\n\tplyvqa32.obj\n\n#LIBRARYS = vqm32w.lib vqa32w.lib sosdw1cs.lib\nLIBRARYS = vqm32wp.lib vqa32wp.lib sosdw1ps.lib\n\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!ifdef %LIB\nLIBPATH = $(%PRJ)\\LIB;$(%LIB)\n!else\nLIBPATH = $(%PRJ)\\LIB;$(%WATCOM)\\LIB386\n!endif\n\n!ifdef %INCLUDE\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%INCLUDE)\n!else\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%WATCOM)\\H\n!endif\n\npath_c   = .\\\npath_cpp = .\\\npath_h   = .\\\npath_asm = .\\\npath_i   = .\\\npath_obj = .\\O\npath_lib = $(%PRJ)\\LIB\npath_exe = .\\\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULE EXTENSIONS AND PATHS\n#----------------------------------------------------------------------------\n\n.EXTENSIONS :\n.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i\n\n.c : $(path_c)\n.cpp : $(path_cpp)\n.cpp : $(path_cpp)\n.h : $(path_h)\n.asm : $(path_asm)\n.i : $(path_i)\n.obj : $(path_obj)\n.lib : $(path_lib)\n.exe : $(path_exe)\n\n#----------------------------------------------------------------------------\n# TOOLS, COMMANDS AND CONFIGURATIONS\n#----------------------------------------------------------------------------\n\nCC_CMD   = wcc386\nCCP_CMD  = wpp386\nASM_CMD  = tasm32\nLINK_CMD = wlink\nLIB_CMD  = wlib\n\nCC_OPTS  = -i$(INCLUDEPATH) -j -zp1 -5s -mf -oaeilrt -s -zq\nASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /dPHARLAP_TNT=0\nLIB_OPTS = /b /c /q /t\nLINK_CFG = $(PRJNAME).lnk\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall : $(LINK_CFG) $(PRJNAME).exe .SYMBOLIC\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj :\n  $(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\n.cpp.obj :\n  $(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\n.asm.obj :\n\t$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\\$^.\n\n#----------------------------------------------------------------------------\n# BUILD THE APPLICATION\n#----------------------------------------------------------------------------\n\n$(PRJNAME).exe : $(OBJECTS) $(LIBRARYS) $(LINK_CFG)\n\t$(LINK_CMD) @$(LINK_CFG)\n\n#----------------------------------------------------------------------------\n# LINKER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(LINK_CFG) : makefile\n\t@echo Updating $(LINK_CFG)!\n\t@%create $(LINK_CFG)\n\t@%write $(LINK_CFG) SYSTEM dos4g\n\t@%write $(LINK_CFG) OPTION map\n\t@%write $(LINK_CFG) NAME $(PRJNAME)\n\t@%write $(LINK_CFG) DEBUG ALL\n\t@%write $(LINK_CFG) LIBPATH $(LIBPATH)\n\t@for %i in ($(OBJECTS)) do @%write $(LINK_CFG) FILE $(path_obj)\\%i\n\t@for %i in ($(LIBRARYS)) do @%write $(LINK_CFG) LIBRARY %i\n\n"
  },
  {
    "path": "WINVQ/VPLAY32/PLYVQA32.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA stand-alone player. (32Bit protected mode)\n*\n* FILE\n*     Plyvqa32.c\n*\n* DESCRIPTION\n*     This program is a stand-alone VQA Player, as well as an example of how\n*     to incorporate VQAPlay into a program.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 7, 1995\n*\n*----------------------------------------------------------------------------\n*\n* FUNCTIONS\n*     main             - Standard 'C' entry point.\n*     Usage            - Display usage information.\n*     Options          - Parse user options.\n*     Find_File_Name   - Find a filename on the command line.\n*     Print_Play_Stats - Print player statistics.\n*     Check_Key        - Check keyboard for keypress.\n*     Get_Key          - Get a key from the keyboard buffer.\n*     HardErr_Handler  - Hardware error handle.\n*\n****************************************************************************/\n\n#define CAPTIONS 0\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <conio.h>\n#include <sys\\timeb.h>\n#include <mem.h>\n#include <io.h>\n#include <ctype.h>\n#include <process.h>\n#include <dos.h>\n\n#include <vqa32\\vqaplay.h>\n#include <vqa32\\vqafile.h>\n#include <vqm32\\all.h>\n\n#if(CAPTIONS)\n#include <vqm32\\font.h>\n#endif\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\nlong OutputStats = 0;\nlong OutputTime = 0;\nlong LastKey;\n\n/* Embedded version string */\nchar VerTag[] = {\"$VER$VQAPlay 2.6 (07/07/95) 32Bit\"};\nchar ReqTag[] = {\"$REQ$VQA32 Version 2.37 & VQM32 Version 2.11 or better.\"};\n\n/* Prototypes */\nvoid main(long argc, char **argv);\nstatic void Usage(long showall);\nstatic void Options(long argc, char *argv[], VQAConfig *config);\nstatic char *Find_File_Name(long argc, char *argv[], char *desired_ext);\nstatic char *GetFilePart(char *path);\nvoid Print_Play_Stats(VQAConfig *config, VQAStatistics *stats);\nlong VQCallback(unsigned char *screen, long framenum);\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nint __cdecl Check_Key(void);\nint __cdecl Get_Key(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n#ifndef __WATCOMC__\n#if(0)\nint HardErr_Handler(int errval, int ax, int bp, int si);\n#endif\n#else\nint __far HardErr_Handler(unsigned deverror, unsigned errcode,\n\t\tunsigned __far *devhdr);\n#endif\n\n\n/****************************************************************************\n*\n* NAME\n*     main - Standard 'C' entry point.\n*\n* SYNOPSIS\n*     main(ArgC, ArgV)\n*\n*     void main(short, char *[]);\n*\n* FUNCTION\n*     Initial 'C' user-routine called by startup code.\n*\n* INPUTS\n*     ArgC - Argument count, number of arguments passed in.\n*     ArgV - Argument array, pointers to arguments.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid main(long argc, char **argv)\n{\n\tVQAConfig     myconfig;\n\tVQAStatistics stats;\n\tVQAHandle     *vqa;\n\tchar          *name;\n\tlong          i;\n\n\t/* Parse command-line */\n\tif (argc < 2) {\n\t\tUsage(1);\n\t\texit(0);\n\t}\n\n\t/* Get filename */\n\tname = Find_File_Name(argc, argv, \".VQA\");\n\n\tif (name == NULL) {\n\t\tUsage(1);\n\t\texit(0);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE PLAYBACK CONFIGURATION\n\t *-----------------------------------------------------------------------*/\n\tVQA_DefaultConfig(&myconfig);\n\tmyconfig.HMIBufSize = 2048*2;\n\n\t#if(CAPTIONS)\n\tmyconfig.CapFont = (char *)Load_Font(\"caption.fnt\");\n\tmyconfig.OptionFlags |= VQAOPTF_CAPTIONS;\n\tSet_Font(myconfig.CapFont);\n\tSetDAC(251,255,255,255); // WHITE\n\tSetDAC(252,255,000,000); // RED\n\tSetDAC(253,000,255,000); // GREEN\n\tSetDAC(254,0,0,0);\n\tSetDAC(255,255,000,255); // CYCLE\n\t#endif\n\n\t/* Configure player with command-line */\n\tOptions(argc, argv, &myconfig);\n\n\t/*-------------------------------------------------------------------------\n\t * INSTALL THE CUSTOM CRITICAL ERROR HANDLER\n\t *-----------------------------------------------------------------------*/\n\t#ifndef __WATCOMC__\n\t#if(0)\n\tharderr(HardErr_Handler);\n\t#endif\n\t#else\n\t_harderr(HardErr_Handler);\n\t#endif\n\n\t/*-------------------------------------------------------------------------\n\t * SET THE VIDEO MODE AND VBI POLARITY BIT\n\t *-----------------------------------------------------------------------*/\n\tSetVideoMode(myconfig.Vmode);\n\tmyconfig.VBIBit = GetVBIBit();\n\n\t/*-------------------------------------------------------------------------\n\t * PLAY THE MOVIE\n\t *-----------------------------------------------------------------------*/\n\n\t/* Allocate a VQA handle. */\n\tif ((vqa = VQA_Alloc()) != NULL) {\n\n\t\t/* Initialize the handle as a standard DOS handle. */\n\t\tVQA_InitAsDOS(vqa);\n\n\t\t/* Open the movie for playback. */\n\t\tif (VQA_Open(vqa, name, &myconfig) == 0) {\n\n\t\t\t#if(1)\n\t\t\tVQA_Reset(vqa);\n\t\t\tVQA_SetStop(vqa, 100);\n\t\t\tVQA_SeekFrame(vqa, 50, 0);\n\n\t\t\tfor (i = 0; i < 3; i++) {\n\t\t\t\t/* Actually set the movie off. */\n\t\t\t\tVQA_Play(vqa, VQAMODE_RUN);\n\t\t\t\tVQA_Reset(vqa);\n\t\t\t\tVQA_SeekFrame(vqa, 50, 0);\n\t\t\t}\n\t\t\t#else\n\t\t\t{\n\t\t\tlong done = 0;\n\t\t\tlong mode = VQAMODE_WALK;\n\t\t\tlong key;\n\n\t\t\tdo {\n\t\t\t\tswitch (VQA_Play(vqa, mode)) {\n\t\t\t\t\tcase VQAERR_NONE:\n\t\t\t\t\tcase VQAERR_PAUSED:\n\t\t\t\t\tcase VQAERR_NOT_TIME:\n\t\t\t\t\tcase VQAERR_SLEEPING:\n\t\t\t\t\t\tkey = Check_Key();\n\n\t\t\t\t\t\tif (key != 0) {\n\t\t\t\t\t\t\tswitch (key) {\n\t\t\t\t\t\t\t\tcase ' ':\n\t\t\t\t\t\t\t\t\tmode = VQAMODE_PAUSE;\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 0x1B:\n\t\t\t\t\t\t\t\t\tdone = 1;\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\tmode = VQAMODE_WALK;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tdone = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} while (done == 0);\n\t\t\t}\n\t\t\t#endif\n\n\t\t\t/* Retrieve playback statistics (FPS, time, etc...) */\n\t\t\tVQA_GetStats(vqa, &stats);\n\n\t\t\t/* Close the movie. */\n\t\t\tVQA_Close(vqa);\n\n\t\t}\n\n\t\t/* Free the VQA handle. */\n\t\tVQA_Free(vqa);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * RESTORE DISPLAY TO TEXT AND PRINT STATISTICS\n\t *-----------------------------------------------------------------------*/\n\tSetVideoMode(TEXT);\n\n\t#if(CAPTIONS)\n\tif (myconfig.CapFont != NULL) free(myconfig.CapFont);\n\t#endif\n\n\tUsage(0);\n\n\t/* Print play statistics */\n\tif (OutputStats) {\n\t\tprintf(\"Movie Name: %s\\n\",strupr(name));\n\t\tPrint_Play_Stats(&myconfig, &stats);\n\t}\n\n\texit(0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Usage - Display usage information.\n*\n* SYNOPSIS\n*     Usage()\n*\n*     void Usage(void);\n*\n* FUNCTION\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Usage(long showall)\n{\n\tprintf(\"\\n%s Copyright (c) 1995 Westwood Studios.\\n\", &VerTag[5]);\n\tprintf(\"Playback library: %s\\n\", VQA_IDString());\n\tputs(\"Written by Denzil E. Long, Jr.\\n\");\n\n\tif (showall) {\n\t\tputs(\"Usage: VPLAY <filename> [options]\");\n\n\t\tputs(\"  -z:     Single-step\");\n\t\tputs(\"  -d:     No drawing\");\n\t\tputs(\"  -fn:    Draw at 'n' frames per second\");\n\t\tputs(\"  -ln:    Load at 'n' frames per second\");\n\t\tputs(\"  -b:     Use buffered video\");\n\t\tputs(\"  -o:     Output play statistics\");\n\n\t\tputs(\"  -p:     Enable slow palette setting\");\n\t\tputs(\"  -w:     Enable woofer drawing.\");\n\n\t\t#if(VQAMONO_ON)\n\t\tputs(\"  -m:     Enable mono screen output\");\n\t\t#endif\n\n\t\t#if(VQAAUDIO_ON)\n\t\tputs(\"  -a:     Audio playback rate\");\n\t\tputs(\"  -ac:    Compatibility mode (Force SoundBlaster).\");\n\t\tputs(\"  -alt:   Play alternate audio track.\");\n\t\tputs(\"  -s:     Disable sound\");\n\n\t\t#if(VQAVOC_ON)\n\t\tputs(\"  -cname: Name of VOC file to play instead of interleaved audio\");\n\t\t#endif\n\t\t#endif\n\n\t\tputs(\"  -t_:    Timer method:\");\n\t\tputs(\"    a = Audio DMA position\");\n\t\tputs(\"    i = Interrupt\");\n\t\tputs(\"    d = DOS\");\n\n\t\tputs(\"  -v_:    Video mode:\");\n\n\t\t#if(VQAMCGA_ON)\n\t\tputs(\"    m = MCGA\");\n\t\t#endif\n\n\t\t#if(VQAXMODE_ON)\n\t\tputs(\"    w = XMODE 320x200\");\n\t\tputs(\"    x = XMODE 320x240\");\n\t\tputs(\"    y = XMODE 320x200, VRAM mode\");\n\t\tputs(\"    z = XMODE 320x240, VRAM mode\");\n\t\t#endif\n\n\t\t#if(VQAVESA_ON)\n\t\tputs(\"    u = VESA 320x200\");\n\t\tputs(\"    v = VESA 640x480 in a window (buffered only)\");\n\t\tputs(\"    s = VESA 640x480 scaled to 640x400 (buffered only)\");\n\t\t#endif\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Options - Parse user options.\n*\n* SYNOPSIS\n*     Options(ArgC, ArgV, Anim)\n*\n*     void Options(long, char *[], VQAnim *);\n*\n* FUNCTION\n*\n* INPUTS\n*     ArgC - Argument count, same as passed to main().\n*     ArgV - Argument array, same as passed to main().\n*     Anim - Pointer to VQAnim structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Options(long argc, char *argv[], VQAConfig *config)\n{\n\tlong l;\n\tlong i;\n\n\t/* Scan arguments for any options ( / or - followed by a letter) */\n\tfor (l = 0; l < argc; l++) {\n\t\tif (argv[l][0] == '/' || argv[l][0] == '-') {\n\n\t\t\t/* Convert the argument to uppercase. */\n\t\t\tfor (i = 1; argv[l][i] != 0; i++) {\n\t\t\t\targv[l][i] = toupper(argv[l][i]);\n\t\t\t}\n\n\t\t\tswitch (argv[l][1]) {\n\n\t\t\t\t/* Set Audio Playback rate */\n\t\t\t\t#if(VQAAUDIO_ON)\n\t\t\t\tcase 'A':\n\t\t\t\t\tif (isdigit(argv[l][2])) {\n\t\t\t\t\t\tconfig->AudioRate = atoi(&argv[l][2]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (argv[l][2] == 'C') {\n\t\t\t\t\t\t\tconfig->DigiCard = 0xE000;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (strcmpi(&argv[l][2], \"LT\") == 0) {\n\t\t\t\t\t\t\t\tconfig->OptionFlags |= VQAOPTF_ALTAUDIO;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t#endif\n\n\t\t\t\t/* Turn off UnVQ to screen */\n\t\t\t\tcase 'B':\n\t\t\t\t\tconfig->DrawFlags |= VQACFGF_BUFFER;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/* VOC File Name */\n\t\t\t\t#if(VQAAUDIO_ON && VQAVOC_ON)\n\t\t\t\tcase 'C':\n\t\t\t\t\tconfig->VocFile = (argv[l] + 2);\n\t\t\t\t\tbreak;\n\t\t\t\t#endif\n\n\t\t\t\t/* Turn off vertical blank wait */\n\t\t\t\tcase 'D':\n\t\t\t\t\tconfig->DrawFlags |= VQACFGF_NODRAW;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/* Set Drawer's frame rate */\n\t\t\t\tcase 'F':\n\t\t\t\t\tconfig->DrawRate = atoi(&argv[l][2]);\n\t\t\t\t\tbreak;\n\n\t\t\t\t/* Set Loader's frame rate */\n\t\t\t\tcase 'L':\n\t\t\t\t\tconfig->FrameRate = atoi(&argv[l][2]);\n\t\t\t\t\tbreak;\n\n\t\t\t\t/* Mono mode */\n\t\t\t\t#if(VQAMONO_ON)\n\t\t\t\tcase 'M':\n\t\t\t\t\tconfig->OptionFlags |= VQAOPTF_MONO;\n\t\t\t\t\tbreak;\n\t\t\t\t#endif\n\n\t\t\t\t/* Output statistics */\n\t\t\t\tcase 'O':\n\t\t\t\t\tOutputStats = 1;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/* Slow palette mode */\n\t\t\t\tcase 'P':\n\t\t\t\t\tconfig->OptionFlags |= VQAOPTF_SLOWPAL;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/* Run with no sound */\n\t\t\t\t#if(VQAAUDIO_ON)\n\t\t\t\tcase 'S':\n\t\t\t\t\tconfig->OptionFlags &= (~VQAOPTF_AUDIO);\n\t\t\t\t\tbreak;\n\t\t\t\t#endif\n\n\t\t\t\tcase 'T':\n\t\t\t\t\tswitch (argv[l][2]) {\n\t\t\t\t\t\tcase 'A':\n\t\t\t\t\t\t\tconfig->TimerMethod = VQA_TMETHOD_AUDIO;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 'I':\n\t\t\t\t\t\t\tconfig->TimerMethod = VQA_TMETHOD_INT;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 'D':\n\t\t\t\t\t\t\tconfig->TimerMethod = VQA_TMETHOD_DOS;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t/* Set video mode */\n\t\t\t\tcase 'V':\n\t\t\t\t\tif (argv[l][2] == 'M') {\n\t\t\t\t\t\tconfig->Vmode = MCGA;\n\t\t\t\t\t}\n\t\t\t\t\t#if(VQAXMODE_ON)\n\t\t\t\t\telse if (argv[l][2] == 'W') {\n\t\t\t\t\t\tconfig->Vmode = XMODE_320X200;\n\t\t\t\t\t}\n\t\t\t\t\telse if (argv[l][2] == 'X') {\n\t\t\t\t\t\tconfig->Vmode = XMODE_320X240;\n\t\t\t\t\t}\n\t\t\t\t\telse if (argv[l][2] == 'Y') {\n\t\t\t\t\t\tconfig->Vmode = XMODE_320X200;\n\t\t\t\t\t\tconfig->DrawFlags |= VQACFGF_VRAMCB;\n\t\t\t\t\t}\n\t\t\t\t\telse if (argv[l][2] == 'Z') {\n\t\t\t\t\t\tconfig->Vmode = XMODE_320X240;\n\t\t\t\t\t\tconfig->DrawFlags |= VQACFGF_VRAMCB;\n\t\t\t\t\t}\n\t\t\t\t\t#endif\n\n\t\t\t\t\t#if(VQAVESA_ON)\n\t\t\t\t\telse if (argv[l][2] == 'V') {\n\t\t\t\t\t\tconfig->Vmode = VESA_640X480_256;\n\t\t\t\t\t\tconfig->DrawFlags |= VQACFGF_BUFFER;\n\t\t\t\t\t}\n\t\t\t\t\telse if (argv[l][2] == 'S') {\n\t\t\t\t\t\tconfig->Vmode = VESA_640X480_256;\n\t\t\t\t\t\tconfig->DrawFlags |= (VQACFGF_BUFFER|VQACFGF_SCALEX2);\n\t\t\t\t\t}\n\t\t\t\t\telse if (argv[l][2] == 'U') {\n\t\t\t\t\t\tconfig->Vmode = VESA_320X200_32K_1;\n\t\t\t\t\t}\n\t\t\t\t\t#endif\n\t\t\t\t\telse {\n\t\t\t\t\t\tprintf(\"Unsupported video mode flag: %c\\n\", argv[l][2]);\n\t\t\t\t\t\texit(0);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t#if(VQAWOOFER_ON)\n\t\t\t\tcase 'W':\n\t\t\t\t\tconfig->DrawFlags |= VQACFGB_WOOFER;\n\t\t\t\t\tbreak;\n\t\t\t\t#endif\n\n\t\t\t\t/* Single-step */\n\t\t\t\tcase 'Z':\n\t\t\t\t\tconfig->OptionFlags |= VQAOPTF_STEP;\n\t\t\t\t\tconfig->DrawFlags |= VQACFGF_NOSKIP;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Find_File_Name - Find a filename on the command line.\n*\n* SYNOPSIS\n*     Name = Fine_File_Name(ArgC, ArgV, Ext, Anim)\n*\n*     char * Fine_File_Name(short, char *[], char *, VQAnim);\n*\n* FUNCTION\n*      Finds a file name on the command line, excluding anything with \"/\" or\n*      \"-\" on it. The given extension is added to the name if there is no\n*      extension in the filename.\n*\n* INPUTS\n*      ArgC - Argument count same as in main().\n*      ArgV - Argument array same as in main().\n*      Ext  - Pointer to filename extension.\n*      Anim - Pointer to VQAnim structure.\n*\n* RESULT\n*      Name = Pointer to filename.\n*\n****************************************************************************/\n\nstatic char *Find_File_Name(long argc, char *argv[], char *desired_ext)\n{\n\tlong        opt = 1;\n\tstatic char drive[_MAX_DRIVE] = {0};\n\tstatic char dir[_MAX_DIR] = {0};\n\tstatic char fname[_MAX_FNAME] = {0};\n\tstatic char ext[_MAX_EXT] = {0};\n\tstatic char pathname[_MAX_PATH] = {0};\n\n\t/* Search for a non '-' option */\n\twhile ((argv[opt][0] == '/') || (argv[opt][0] == '-')) {\n\t\topt++;\n\t}\n\n\tif (argc == opt) {\n\t \treturn (NULL);\n\t}\n\n\t/* Split the filename into its components */\n\t_splitpath(argv[opt],drive,dir,fname,ext);\n\n\tif (strlen(ext) == 0) {\n\t\tstrcpy(ext,desired_ext);\n\t}\n\n\t/* Rebuild the complete filename */\n\t_makepath(pathname, drive, dir, fname, ext);\n\n\treturn (pathname);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Print_Play_Stats - Print player statistics.\n*\n* SYNOPSIS\n*     Print_Play_Stats(Anim)\n*\n*     void Print_Play_Stats(VQAnim);\n*\n* FUNCTION\n*\n* INPUTS\n*     Anim - Pointer to VQAnim structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid Print_Play_Stats(VQAConfig *config, VQAStatistics *stats)\n{\n\tlong tim1,tim2;\n\tlong fps1,fps2;\n\n\t/* Video mode name */\n\tprintf(\"Video Mode: \");\n\n\tif (config->Vmode == MCGA) {\n\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\tputs(\"MCGA Buffered\");\n\t\t} else {\n\t\t\tputs(\"MCGA\");\n\t\t}\n\t}\n\t#if(VQAXMODE_ON)\n\telse if (config->Vmode == XMODE_320X200) {\n\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\tputs(\"XMODE 320x200 Buffered\");\n\t\t} else {\n\t\t\tif (config->DrawFlags & VQACFGF_VRAMCB) {\n\t\t\t\tputs(\"XMODE 320x200 VRAM\");\n\t\t\t} else {\n\t\t\t\tputs(\"XMODE 320x200\");\n\t\t\t}\n\t\t}\n\t}\n\telse if (config->Vmode == XMODE_320X240) {\n\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\tputs(\"XMODE 320x240 Buffered\");\n\t\t} else {\n\t\t\tif (config->DrawFlags & VQACFGF_VRAMCB) {\n\t\t\t\tputs(\"XMODE 320x240 VRAM\");\n\t\t\t} else {\n\t\t\t\tputs(\"XMODE 320x240\");\n\t\t\t}\n\t\t}\n\t}\n\t#endif\n\n\t#if(VQAVESA_ON)\n\telse if (config->Vmode == VESA_640X480_256) {\n\t\tif (config->DrawFlags & VQACFGF_SCALEX2) {\n\t\t\tputs(\"VESA 640x480 Scaled\");\n\t\t} else {\n\t\t\tputs(\"VESA 640x480 Windowed\");\n\t\t}\n\t} else if (config->Vmode==VESA_320X200_32K_1) {\n\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\tputs(\"VESA 320x200 Buffered\");\n\t\t} else {\n\t\t\tputs(\"VESA 320x200\");\n\t\t}\n\t}\n\t#endif\n\telse {\n\t\tputs(\"UNKNOWN\");\n\t}\n\n\tprintf(\"%lu bytes used.\\n\", stats->MemUsed);\n\n\ttim1 = ((stats->EndTime - stats->StartTime) / VQA_TIMETICKS);\n\ttim2 = (((stats->EndTime - stats->StartTime) * 10) / VQA_TIMETICKS);\n\tprintf(\"Elapsed time %d.%d seconds.\\n\", tim1, tim2 - (tim1 * 10));\n\n\tprintf(\"%u frames loaded.\\n\", stats->FramesLoaded);\n\tprintf(\"%u frames drawn.\\n\", stats->FramesDrawn);\n\tprintf(\"%u frames skipped.\\n\", stats->FramesSkipped);\n\n\t/* Frame rates */\n\tfps1 = ((stats->FramesLoaded * VQA_TIMETICKS)\n\t\t\t/ (stats->EndTime - stats->StartTime));\n\tfps2 = (stats->FramesLoaded * VQA_TIMETICKS * 10)\n\t\t\t/ (stats->EndTime - stats->StartTime);\n\tprintf(\"Load rate: %d.%d FPS\\n\", fps1, fps2 - (fps1 * 10));\n\n\tfps1 = (stats->FramesDrawn * VQA_TIMETICKS)\n\t\t\t/ (stats->EndTime -stats->StartTime);\n\tfps2 = (stats->FramesDrawn * VQA_TIMETICKS * 10)\n\t\t\t/ (stats->EndTime - stats->StartTime);\n\tprintf(\"Draw rate: %d.%d FPS\\n\", fps1, fps2 - (fps1 * 10));\n\n\t/* Audio */\n\tprintf(\"Audio samples played: %lu\\n\", stats->SamplesPlayed);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Check_Key - Check keyboard for keypress.\n*\n* SYNOPSIS\n*     Key = Check_Key()\n*\n*     short Check_Key(void);\n*\n* FUNCTION\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Key - Value of key pressed.\n*\n****************************************************************************/\n\nint Check_Key(void)\n{\n\tif (kbhit()) {\n\t\tLastKey = getch();\n\t\treturn (LastKey);\n\t} else {\n\t\treturn (0);\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Get_Key - Get a key from the keyboard buffer.\n*\n* SYNOPSIS\n*     Key = Get_Key()\n*\n*     short Get_Key(void);\n*\n* FUNCTION\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Key - Value of key.\n*\n****************************************************************************/\n\nint Get_Key(void)\n{\n\treturn (LastKey);\n}\n\n\n#ifndef __WATCOMC__\n#if(0)\n/****************************************************************************\n*\n* NAME\n*     HardErr_Handler - Hardware error handle.\n*\n* SYNOPSIS\n*     HardErr_Handler(Error, AX, BP, SI)\n*\n*     int HardErr_Handler(int, int, int, int);\n*\n* FUNCTION\n*     DOS calls 1 through 0xc are OK; any other will corrupt DOS.\n*     Important safety tip: The arguments for this function are NOT the\n*     same as those for the Microsoft '_harderr()' function.\n*\n* INPUTS\n*     Error - Error type value. Low order byte can be:\n*\n*             0  = Attempt to write to write-protected disk.\n*             1  = Unknown unit.\n*             2  = Drive not ready.\n*             3  = Unknown command.\n*             4  = CRC error.\n*             5  = Bad drive-request structure length.\n*             6  = Seek error.\n*             7  = Unknown media type.\n*             8  = Sector not found.\n*             9  = Printer out of paper.\n*             10 = Write fault.\n*             11 = Read fault.\n*             12 = General failure.\n*\n*     AX    - Will be non-negative if this is a disk error, negative\n*             otherwise. low-order byte of ax gives failing drive number\n*             high bits:\n*\n*             15 0 = disk error\n*             14     not used\n*             13 0 = \"Ignore\" not allowed\n*             12 0 = \"Retry\" not allowed\n*             11 0 = \"Fail\" not allowed (fail is same as abort)\n*             10,9:\n*             00     DOS\n*             01     File allocation table\n*             10     Directory\n*             11     Data area\n*             8 0  = Read error, 1 = Write error\n*\n*     BP,SI - Not used\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nint HardErr_Handler(int errval, int ax, int bp, int si)\n{\n\t/* Suppress compiler warnings */\n\terrval = errval;\n\tbp = bp;\n\tsi = si;\n\n\t/* If AX < 0, this was not a disk error, so return the ABORT code */\n\tif (ax < 0) {\n\t\thardretn(_HARDERR_ABORT);\n\t}\n\n\t/* Otherwise, if this is a drive-not-ready error, retry 5 times */\n\tif (kbhit() != 0) {\n\t\tif (ax & (1 << 13)) {\n\t\t\thardresume(_HARDERR_IGNORE);\n\t\t} else if (ax & (1 << 11)) {\n\t\t\thardresume(_HARDERR_FAIL);\n\t\t} else {\n\t\t\thardresume(_HARDERR_RETRY);\n\t\t}\n\t} else {\n\t\tif (ax & (1 << 12)) {\n\t\t\thardresume(_HARDERR_RETRY);\n\t\t} else {\n\t\t\thardresume(_HARDERR_IGNORE);\n\t\t}\n\t}\n\n\treturn (0);\n}\n#endif\n\n#else\n/****************************************************************************\n*\n* NAME\n*     HardErr_Handler - Critical error handler for INT 0x24.\n*\n* SYNOPSIS\n*     Action = HardErr_Handler(DeviceError, ErrorCode, DeviceHeader)\n*\n*     int HardErr_Handler(unsigned, unsigned, unsigned __far *);\n*\n* FUNCTION\n*\n* INPUTS\n*     DeviceError  - Device error description.\n*\n*                    bit 15    0 indicates disk error.\n*                    bit 14    not used\n*                    bit 13    0 indicates \"Ignore\" response not allowed.\n*                    bit 12    0 indicates \"Retry\" response not allowed.\n*                    bit 11    0 indicates \"Fail\" response not allowed.\n*                    bit 9,10  location of error.\n*\n*                              Value   Meaning\n*\n*                              00      MS-DOS\n*                              01      File Allocation Table (FAT)\n*                              10      Directory\n*                              11      Data area\n*\n*                    bit 8     0 indicates read error,1 indicates write error\n*\n*                    The low-order byte indicates the drive where the error\n*                    occurred; (0 = drive A, 1 = drive B, etc.).\n*\n*   \tErrorCode    - Type of error.\n*\n*                    The low-order byte can be one of the following values:\n*\n*                    0x00  Attempt to write to a write-protected disk.\n*                    0x01  Unknown unit.\n*                    0x02  Drive not ready.\n*                    0x03  Unknown command.\n*                    0x04  CRC error in data.\n*                    0x05  Bad drive-request structure length.\n*                    0x06  Seek error.\n*                    0x07  Unknown media type.\n*                    0x08  Sector not found.\n*                    0x09  Printer out of paper.\n*                    0x0A  Write fault.\n*                    0x0B  Read fault.\n*                    0x0C  General fault.\n*\n*     DeviceHeader - Pointer to a device header control-block that contains\n*                    information about the device on which the error\n*                    occurred.\n*\n* RESULT\n*     Action - Indication of what action to take using one of the following\n*              values:\n*\n*              Value             Meaning\n*\n*              _HARDERR_IGNORE   Ignore the error.\n*              _HARDERR_RETRY    Retry the operation.\n*              _HARDERR_ABORT    Abort the program issuing INT 0x23\n*              _HARDERR_FAIL     Fail the system call that is in progress\n*                                (DOS 3.0 or higher)\n*\n****************************************************************************/\n\nint __far HardErr_Handler(unsigned deverror, unsigned errcode,\n\t\tunsigned __far *devhdr)\n{\n\t/* Prevent compiler warnings. */\n\terrcode = errcode;\n\tdevhdr = devhdr;\n\n\t/* If this is not a disk error, then return the ABORT code. */\n\tif (deverror & (1 << 15)) {\n\t\treturn (_HARDERR_ABORT);\n\t}\n\n\t/* If this is a drive-not-ready error then continue to retry. */\n\tif (kbhit() != 0) {\n\t\tif (deverror & (1 << 13)) {\n\t\t\t_hardresume(_HARDERR_IGNORE);\n\t\t}\n\t\telse if (deverror & (1 << 11)) {\n\t\t\t_hardresume(_HARDERR_FAIL);\n\t\t}\n\t\telse {\n\t\t\t_hardresume(_HARDERR_RETRY);\n\t\t}\n\t} else {\n\t\tif (deverror & (1 << 12)) {\n\t\t\t_hardresume(_HARDERR_RETRY);\n\t\t} else {\n\t\t\t_hardresume(_HARDERR_IGNORE);\n\t\t}\n\t}\n\n\treturn (0);\n}\n#endif\n\n\n/****************************************************************************\n*\n* NAME\n*     GetFilePart - Get the filename part of path/filename.\n*\n* SYNOPSIS\n*     Filename = GetFilePart(Path)\n*\n*     char *GetFilePart(char *);\n*\n* FUNCTION\n*\n* INPUTS\n*     Path - Full path to retrieve filename from.\n*\n* RESULT\n*     Filename - Pointer to filename or NULL if no filename.\n*\n****************************************************************************/\n\nstatic char *GetFilePart(char *path)\n{\n\tchar *ptr;\n\n\tptr = strrchr(path, '\\\\');\n\n\tif (ptr == NULL) {\n\t\tptr = strrchr(path, ':');\n\t}\n\n\tif (strlen(ptr) > 1) {\n\t\tptr++;\n\t}\n\n\treturn (ptr);\n}\n\n"
  },
  {
    "path": "WINVQ/VPLAY32/TASM32.CFG",
    "content": "/la\n/t\n/m\n/w+\n/jJUMPS\n/ml\n/p\n/z\n/iC:\\PROJECTS\\INCLUDE\n/zi\n"
  },
  {
    "path": "WINVQ/VPLAY32/TLIB.CFG",
    "content": "/C /E\n"
  },
  {
    "path": "WINVQ/VPLAY32/TLINK32.CFG",
    "content": "/c\n/m\n/Gm\n-LC:\\PROJECTS\\LIB;C:\\DEV\\BC4\\LIB\n-v\n"
  },
  {
    "path": "WINVQ/VPLAY32/VPLAYTNT.DEF",
    "content": "stub 'gotnt.exe'"
  },
  {
    "path": "WINVQ/VQA32/AUDIO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     audio.c\n*\n* DESCRIPTION\n*     Audio playback and timing.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     August 4, 1995\n*\n*\n* HISTORY:\n*     Modified for Win95 Direct Sound - Steve T 1/2/96 6:35AM\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_StartTimerInt - Initialize system timer interrupt.\n*     VQA_StopTimerInt  - Remove system timer interrupt.\n*     VQA_SetTimer      - Resets current time to given tick value.\n*     VQA_GetTime       - Return current time.\n*     VQA_TimerMethod   - Get timer method being used.\n*     VQA_OpenAudio     - Open sound system.\n*     VQA_CloseAudio    - Close sound system\n*     VQA_StartAudio    - Starts audio playback\n*     VQA_StopAudio     - Stop audio playback.\n*     CopyAudio         - Copy data from Audio Temp buf into Audio play buf.\n*\n* PRIVATE\n*     TimerCallback - VQA timer event. (Called by HMI)\n*     AutoDetect    - Auto detect the sound card.\n*     AudioCallback - Sound system callback.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <malloc.h>\n#include <mem.h>\n#include <sys\\timeb.h>\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n\n#ifdef __WATCOMC__\n#pragma pack(4);\n#endif\n\n\n/*---------------------------------------------------------------------------\n * AUDIO DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n#define USE_WINDOWS_TIME\t1\n\n#define HMI_SAMPLE 0x1000\n#define MAKE_LONG(a,b) (((long)(a)<<16)|(long)((b)&0x0000FFFFL))\n\n/*---------------------------------------------------------------------------\n * PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n#if( USE_WINDOWS_TIME )\n\textern unsigned long Get_Game_Time( void );\n#endif\n\n#if(VQAAUDIO_ON)\n#if(VQADIRECT_SOUND)\nvoid CALLBACK TimerCallback ( UINT event_id, UINT res1 , DWORD user, DWORD  res2, DWORD  res3 );\nBOOL Move_HMI_Audio_Block_To_Direct_Sound_Buffer (void);\nvoid CALLBACK AudioCallback ( UINT , UINT , DWORD , DWORD , DWORD );\n\n#else\n\nlong AutoDetect(_SOS_CAPABILITIES *digicaps, long bitsize, long channels);\nvoid far TimerCallback(void);\nvoid far __cdecl AudioCallback(WORD wDriverHandle, WORD wAction,\n\t\tWORD wSampleID);\n\n/* Dummy functions used to mark the start/end address of the file. */\nstatic void StartAddr(void);\nstatic void EndAddr(void);\n\n#endif\n/*---------------------------------------------------------------------------\n * GLOBAL DATA\n *-------------------------------------------------------------------------*/\n\nstatic VQAHandleP *VQAP = NULL;\nstatic long AudioFlags = 0;\nstatic long TimerSysCount = 0;\nstatic long TimerIntCount = 0;\nstatic WORD VQATimer = 0;\nstatic long TimerMethod;\nstatic long VQATickCount = 0;\n#endif /* VQAAUDIO_ON */\n\nstatic long TickOffset = 0;\nchar *HMIDevName = \"<none>\";\n\n#if(VQAAUDIO_ON)\n\n#if(!VQADIRECT_SOUND)\n\n/* This is a dummy function that is used to mark the start of the module.\n * It is necessary for locking the memory the module occupies. This prevents\n * the virtual memory manager from swapping out this memory.\n */\nstatic void StartAddr(void)\n{\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StartTimerInt - Initialize system timer interrupt.\n*\n* SYNOPSIS\n*     Error = VQA_StartTimerInt(VQA, Init)\n*\n*     long VQA_StartTimerInt(VQAHandeP *, long);\n*\n* FUNCTION\n*     Initialize the HMI timer system and add our own timer event. If the\n*     system has already been initialized then we are given access to the\n*     the timer system.\n*\n* INPUTS\n*     VQA  - Pointer to private VQAHandle structure.\n*     Init - Initialize HMI timer system flag. (TRUE = Initialize)\n*\n* RESULT\n*     Error - 0 if successful, -1 if error.\n*\n****************************************************************************/\n\nlong VQA_StartTimerInt(VQAHandleP *vqap, long init)\n{\n\tVQAAudio *audio;\n\n\t/* Dereference for quick access. */\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Does the caller want me to initialize the timer system? */\n\tif (init == 0) {\n\n\t\t/* If the timer system is uninitialized then it is the players\n\t\t * responsibility to do it.\n\t\t */\n\t\tif ((AudioFlags & VQAAUDF_TIMERINIT)==(HMI_UNINIT<<VQAAUDB_TIMERINIT)) {\n\t\t\tsosTIMERInitSystem(_TIMER_DOS_RATE, _SOS_DEBUG_NORMAL);\n\n\t\t\t/* Flag the timer system as open. */\n\t\t\tAudioFlags |= (HMI_VQAINIT << VQAAUDB_TIMERINIT);\n\t\t}\n\n\t\t/* Flag availability of the timer system. */\n\t\taudio->Flags |= (HMI_VQAINIT << VQAAUDB_TIMERINIT);\n\t} else {\n\t\taudio->Flags |= (HMI_APPINIT << VQAAUDB_TIMERINIT);\n\t}\n\n\t/* Increment the timer system usage count. */\n\tTimerSysCount++;\n\n\t/* Register the VQA_TickCount timer event. */\n\tif ((AudioFlags & VQAAUDF_HMITIMER) == (HMI_UNINIT<<VQAAUDB_HMITIMER)) {\n\t\tif (sosTIMERRegisterEvent(VQA_TIMETICKS,TimerCallback,&VQATimer) == 0) {\n\n\t\t\t/* Flag the timer interrupt as being registered. */\n\t\t\tAudioFlags |= (HMI_VQAINIT << VQAAUDB_HMITIMER);\n\t\t} else {\n\t\t\treturn (-1);\n\t\t}\n\t}\n\n\t/* Flag availability of the timer interrupt. */\n\taudio->Flags |= (HMI_VQAINIT << VQAAUDB_HMITIMER);\n\n\t/* Increment the timer interrupt usage count. */\n\tTimerIntCount++;\n\n\t/* Lock the memory occupied by this module. */\n\tif ((audio->Flags & VQAAUDF_MODLOCKED) == 0) {\n\t\tDPMI_Lock((void *)&StartAddr, (long)&EndAddr - (long)&StartAddr);\n\t\taudio->Flags |= VQAAUDF_MODLOCKED;\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StopTimerInt - Remove system timer interrupt.\n*\n* SYNOPSIS\n*     VQA_StopTimerInt()\n*\n*     void VQA_StopTimerInt(void);\n*\n* FUNCTION\n*     Remove our timer event from the HMI timer system. Uninitialize the\n*     HMI timer system if we initialized it.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_StopTimerInt(VQAHandleP *vqap)\n{\n\tVQAAudio *audio;\n\n\t/* Dereference for quick access. */\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Decrement the timer interrupt usage count. */\n\tif (TimerIntCount) {\n\t\tTimerIntCount--;\n\t}\n\n\t/* Remove the timer interrrupt if it is initialized and the use count is\n\t * zero. Otherwise, clear the callers timer interrupt availability flag.\n\t */\n\tif (((AudioFlags & VQAAUDF_HMITIMER) == (HMI_VQAINIT<<VQAAUDB_HMITIMER))\n\t\t\t&& (TimerIntCount == 0)) {\n\n\t\tsosTIMERRemoveEvent(VQATimer);\n\t\tAudioFlags &= ~VQAAUDF_HMITIMER;\n\t} else {\n\t\taudio->Flags &= ~VQAAUDF_HMITIMER;\n\t}\n\n\t/* Derement the timer system usage count. */\n\tif (TimerSysCount) {\n\t\tTimerSysCount--;\n\t}\n\n\t/* Close the timer system if it has been opened and the use count is zero.\n\t * Otherwise, clear the callers timer system availability flag.\n\t */\n\tif (((AudioFlags & VQAAUDF_TIMERINIT) == (HMI_VQAINIT<<VQAAUDB_TIMERINIT))\n\t\t\t&& (TimerSysCount == 0)) {\n\n\t\tsosTIMERUnInitSystem(0);\n\t\tAudioFlags &= ~VQAAUDF_TIMERINIT;\n\t} else {\n\t\taudio->Flags &= ~VQAAUDF_TIMERINIT;\n\t}\n\n\t/* Unlock the memory accupied by this module. */\n\tif ((audio->Flags & VQAAUDF_MODLOCKED) == 1) {\n\t\tDPMI_Unlock(&StartAddr, (long)&EndAddr - (long)&StartAddr);\n\t\taudio->Flags &= ~VQAAUDF_MODLOCKED;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     TimerCallback - VQA timer event. (Called by HMI)\n*\n* SYNOPSIS\n*     TimerCallback()\n*\n*     void TimerCallback(void);\n*\n* FUNCTION\n*     Our custom timer event. This is the timer event that we register with\n*     HMI for system timing.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid far TimerCallback(void)\n{\n\tVQATickCount++;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_OpenAudio - Open sound system.\n*\n* SYNOPSIS\n*     Error = VQA_OpenAudio(VQAHandleP)\n*\n*     long VQA_OpenAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Initialize the sound system by setting the DigiHandle to and HMI\n*     driver handle. The timer must first be initialized before calling\n*     this function.\n*\n* INPUTS\n*     VQAHandleP - Pointer to private VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, -1 if error.\n*\n****************************************************************************/\n\nlong VQA_OpenAudio(VQAHandleP *vqap)\n{\n\tVQAData       *vqabuf;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tVQAHeader     *header;\n\tunsigned char *driver_path;\n\tWORD          port;\n\tlong          rc;\n\n\t/* Dereference data memebers for quicker access. */\n\tconfig = &vqap->Config;\n\theader = &vqap->Header;\n\tvqabuf = vqap->VQABuf;\n\taudio = &vqabuf->Audio;\n\n\t/* Fail if no audio buffer or DigiCard is 0 (no sound) */\n\tif ((audio->Buffer == NULL) || (config->DigiCard == 0)) {\n\t\treturn (-1);\n\t}\n\n\t/* Reset the buffer position to the beginning. */\n\taudio->CurBlock = 0;\n\n\t/* Initialize the HMI driver structure. */\n\taudio->sSOSInitDriver.wAllocateBuffer = _TRUE;\n\taudio->sSOSInitDriver.wParam = 19;\n\taudio->sSOSInitDriver.wTimerID = _SOS_NORMAL_TIMER;\n\n\t/*-------------------------------------------------------------------------\n\t * Compute the playback rate:\n\t *\n\t * - If Config->AudioRate is -1, use HMI_DATA_RATE scaled to the specified\n\t *   frame rate (so the audio plays faster if we're playing faster)\n\t * - otherwise, use the specified rate\n\t *-----------------------------------------------------------------------*/\n\tif (config->AudioRate != -1) {\n\t\taudio->sSOSInitDriver.wSampleRate = config->AudioRate;\n\t}\n\telse if (config->FrameRate != header->FPS) {\n\t\taudio->sSOSInitDriver.wSampleRate = ((audio->SampleRate*config->FrameRate)\n\t\t\t\t/ (unsigned long)header->FPS);\n\n\t\tconfig->AudioRate = audio->sSOSInitDriver.wSampleRate;\n\t} else {\n\t\taudio->sSOSInitDriver.wSampleRate = audio->SampleRate;\n\t\tconfig->AudioRate = audio->SampleRate;\n\t}\n\n\t/* If the application has already initialized HMI then set the\n\t * necessary variables. Otherwise we must setup HMI ourself.\n\t */\n\tif ((config->OptionFlags & VQAOPTF_HMIINIT)\n\t\t\t|| ((AudioFlags & VQAAUDF_DIGIINIT) != 0)) {\n\n\t\t/* The application MUST provide the card type! */\n\t\tif (config->DigiCard == -1) {\n\t\t\treturn (-1);\n\t\t}\n\n\t\t/* Init the detection system */\n\t\tdriver_path = (unsigned char *)\".\\\\\";\n\n\t\tif ((rc = sosDIGIDetectInit(driver_path)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Get the capabilities of the card being used. */\n\t\trc = sosDIGIDetectGetCaps(config->DigiCard, &audio->DigiCaps);\n\t\tsosDIGIDetectUnInit();\n\n\t\tif (rc != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\taudio->DigiHandle = config->DigiHandle;\n\t\taudio->Flags |= (HMI_APPINIT << VQAAUDB_TIMERINIT);\n\t\taudio->Flags |= (HMI_APPINIT << VQAAUDB_DIGIINIT);\n\n\t\tif ((AudioFlags & (VQAAUDF_TIMERINIT|VQAAUDF_DIGIINIT)) == 0) {\n\t\t\tHMIDevName = \"App-Specific\";\n\t\t\tAudioFlags |= (HMI_APPINIT << VQAAUDB_TIMERINIT);\n\t\t\tAudioFlags |= (HMI_APPINIT << VQAAUDB_DIGIINIT);\n\t\t}\n\t} else {\n\n\t\t/* Init the detection system */\n\t\tdriver_path = (unsigned char *)\".\\\\\";\n\n\t\tif ((rc = sosDIGIDetectInit(driver_path)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/*-----------------------------------------------------------------------\n\t\t * Initialize DigiHardware with port, IRQ, and DMA, and make sure\n\t\t * Config.DigiCard contains the HMI ID we want to use:\n\t\t *\n\t\t * - If Config.DigiCard is -1, auto-detect the hardware; then, do a\n\t\t *   FindHardware so the GetSettings will work\n\t\t * - If Config.DigiCard is filled in, but port, IRQ or DMA is -1, use\n\t\t *   FindHardware & GetSettings to get the settings\n\t\t * - If all are filled in, just use them as they are\n\t\t *---------------------------------------------------------------------*/\n\n\t\t/* Auto-Detect */\n\t\tif (config->DigiCard == -1) {\n\n\t\t\t/* Version 1 VQA's have only 8 bit mono audio streams. */\n\t\t\tif (header->Version == VQAHD_VER1) {\n\t\t\t\tconfig->DigiCard = AutoDetect(&audio->DigiCaps, 8, 1);\n\t\t\t} else {\n\t\t\t\tconfig->DigiCard = AutoDetect(&audio->DigiCaps, audio->BitsPerSample,\n\t\t\t\t\t\taudio->Channels);\n\n\t\t\t\t/* Resort to 8bit mono */\n\t\t\t\tif (config->DigiCard == -1) {\n\t\t\t\t\tconfig->DigiCard = AutoDetect(&audio->DigiCaps, 8, 1);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (config->DigiCard == -1) {\n\t\t\t\tsosDIGIDetectUnInit();\n\t\t\t\treturn (-1);\n\t\t\t}\n\t\t}\n\n\t\t/* Do a FindHardware & GetSettings */\n\t\tif (config->DigiPort == -1) {\n\t\t  if (sosDIGIDetectFindHardware(config->DigiCard, &audio->DigiCaps,\n\t\t\t\t\t&port)) {\n\n\t\t\t\tsosDIGIDetectUnInit();\n\t\t\t\treturn (-1);\n\t\t\t}\n\n\t\t\tif (sosDIGIDetectGetSettings(&audio->DigiHardware)) {\n\t\t\t\tsosDIGIDetectUnInit();\n\t\t\t\treturn (-1);\n\t\t\t}\n\n\t\t\tconfig->DigiPort = audio->DigiHardware.wPort;\n\t\t\tconfig->DigiIRQ = audio->DigiHardware.wIRQ;\n\t\t\tconfig->DigiDMA = audio->DigiHardware.wDMA;\n\t\t\tHMIDevName = (char *)audio->DigiCaps.szDeviceName;\n\t\t} else {\n\t\t\taudio->DigiHardware.wPort = config->DigiPort;\n\t\t\taudio->DigiHardware.wIRQ = config->DigiIRQ;\n\t\t\taudio->DigiHardware.wDMA = config->DigiDMA;\n\t\t\tHMIDevName = \"App-Specific\";\n\t\t}\n\n\t\tsosDIGIDetectUnInit();\n\n\t\t/* Initialize the DIGI system & driver */\n\t\tsosDIGIInitSystem(driver_path, _SOS_DEBUG_NORMAL);\n\t\taudio->sSOSInitDriver.wBufferSize = config->HMIBufSize;\n\t\taudio->sSOSInitDriver.lpBuffer = NULL;\n\t\taudio->sSOSInitDriver.lpFillHandler = NULL;\n\t\taudio->sSOSInitDriver.lpDriverMemory = NULL;\n\t\taudio->sSOSInitDriver.lpTimerMemory = NULL;\n\t\taudio->DigiHandle = -1;\n\n\t\tif ((rc = sosDIGIInitDriver(config->DigiCard, &audio->DigiHardware,\n\t\t\t\t&audio->sSOSInitDriver, &audio->DigiHandle)) != 0) {\n\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/*-----------------------------------------------------------------------\n\t\t * Register the timer event\n\t\t *---------------------------------------------------------------------*/\n\n\t\t/* If the timer hasn't been init'd, do it now */\n\t\tif ((AudioFlags & VQAAUDF_TIMERINIT) == (HMI_UNINIT<<VQAAUDB_TIMERINIT)) {\n\t\t\tsosTIMERInitSystem(_TIMER_DOS_RATE ,_SOS_DEBUG_NORMAL);\n\t\t\taudio->Flags |= (HMI_VQAINIT << VQAAUDB_TIMERINIT);\n \t\t\tAudioFlags |= (HMI_VQAINIT << VQAAUDB_TIMERINIT);\n\t\t}\n\n\t\t/* Register the event */\n\t\trc = sosTIMERRegisterEvent(VQA_TIMETICKS,\n\t\t\t\taudio->sSOSInitDriver.lpFillHandler, &audio->DigiTimer);\n\n\t\tif (rc) {\n\t\t\tsosDIGIUnInitDriver(audio->DigiHandle, _TRUE, _TRUE);\n\t\t\tsosDIGIUnInitSystem();\n\t\t\treturn (rc);\n\t\t}\n\n\t\tconfig->DigiHandle = audio->DigiHandle;\n\t\taudio->Flags |= (HMI_VQAINIT << VQAAUDB_DIGIINIT);\n\t\tAudioFlags |= (HMI_VQAINIT << VQAAUDB_DIGIINIT);\n\t}\n\n\tif ((audio->Flags & VQAAUDF_MODLOCKED) == 0) {\n\t\tDPMI_Lock(&StartAddr, (long)&EndAddr - (long)&StartAddr);\n\t\taudio->Flags |= VQAAUDF_MODLOCKED;\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_CloseAudio - Close sound system\n*\n* SYNOPSIS\n*     VQA_CloseAudio()\n*\n*     void VQA_CloseAudio(void);\n*\n* FUNCTION\n*     Removes VQA's involvement in the audio system.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_CloseAudio(VQAHandleP *vqap)\n{\n\tVQAAudio *audio;\n\n\t/* Dereference for quick access. */\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Remove the Digi event */\n\tif ((AudioFlags & VQAAUDF_DIGIINIT) == (HMI_VQAINIT<<VQAAUDB_DIGIINIT)) {\n\t\tsosTIMERRemoveEvent(audio->DigiTimer);\n\t}\n\n\t/* Un-init timer if necessary */\n\tif ((AudioFlags & VQAAUDF_TIMERINIT) == (HMI_VQAINIT<<VQAAUDB_TIMERINIT)) {\n\t\tsosTIMERUnInitSystem(0);\n\t}\n\n\taudio->Flags &= ~VQAAUDF_TIMERINIT;\n\tAudioFlags &= ~VQAAUDF_TIMERINIT;\n\n\t/* Remove the driver */\n\tif ((audio->Flags & VQAAUDF_DIGIINIT) == (HMI_VQAINIT<<VQAAUDB_DIGIINIT)) {\n\t\tsosDIGIUnInitDriver(audio->DigiHandle, _TRUE, _TRUE);\n\t\tsosDIGIUnInitSystem();\n\t}\n\n\taudio->Flags &= ~VQAAUDF_DIGIINIT;\n\tAudioFlags &= ~VQAAUDF_DIGIINIT;\n\tAudioFlags &= ~VQAAUDF_ISPLAYING;\n\n\t/* Unlock the memory accupied by this module. */\n\tif ((audio->Flags & VQAAUDF_MODLOCKED) == 1) {\n\t\tDPMI_Unlock(&StartAddr, (long)&EndAddr - (long)&StartAddr);\n\t\taudio->Flags &= ~VQAAUDF_MODLOCKED;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     AutoDetect - Auto detect the sound card.\n*\n* SYNOPSIS\n*     CardID = AutoDetect(DigiCaps, BitSize, Channels)\n*\n*     long AutoDetect(_SOS_CAPABILITIES *, long, long);\n*\n* FUNCTION\n*     Autodetects the type of sound card present in the system.\n*\n* INPUTS\n*     DigiCaps - Pointer to HMI digital card capabilities structure.\n*     BitSize  - Bits per sample size.\n*     Channels - Number of desired channels.\n*\n* RESULT\n*     CardID - HMI ID of the sound card found, -1 if none.\n*\n****************************************************************************/\n\nlong AutoDetect(_SOS_CAPABILITIES *digicaps, long bitsize, long channels)\n{\n\tlong device_id = -1;\n\tWORD port;\n\tlong i;\n\tlong rc;\n\n\t/* Search for an 8-bit mono device */\n\tif (sosDIGIDetectFindFirst(digicaps, &port)) {\n\t\treturn (-1);\n\t}\n\n\tchannels--;\n\n\ti = 0;\n\twhile (i < 6) {\n\t\ti++;\n\n\t\tif ((digicaps->wBitsPerSample == bitsize)\n\t\t\t\t&& (digicaps->wChannels == channels)) {\n\n\t\t\tbreak;\n\t\t}\n\n\t\tif (sosDIGIDetectFindNext(digicaps, &port)) {\n\t\t\treturn (-1);\n\t\t}\n\t}\n\n\t/* Exit if failed to find the required device */\n\tif ((digicaps->wBitsPerSample != bitsize)\n\t\t\t|| (digicaps->wChannels != channels)) {\n\n\t\treturn (-1);\n\t}\n\n\t/* Stash the ID */\n\tdevice_id = digicaps->wDeviceID;\n\n\t/* Now that we have handled the initial pass, verify that if we found an\n\t * _ADLIB_GOLD_8_MONO that it is not a Logitech Sound Wave man in disguise.\n\t */\n\tif ((WORD)digicaps->wDeviceID == _ADLIB_GOLD_8_MONO) {\n\t\trc = sosDIGIDetectFindNext(digicaps, &port);\n\n\t\twhile ((i < 6) && (rc == 0)) {\n\t\t\ti++;\n\n\t\t\tif ((digicaps->wBitsPerSample == 8) && (digicaps->wChannels == 0)) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif ((rc = sosDIGIDetectFindNext(digicaps, &port)) != 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/* If we don't have an error use the secondary device ID, after all,\n\t\t * anything's better than an Adlib Gold.  If we do have an error or there\n\t\t * is nothing we can use then the device ID is already set to the adlib\n\t\t * gold so just let it rip.\n\t\t */\n\t\tif ((rc == 0) && ((WORD)digicaps->wDeviceID == _SBPRO_8_MONO)) {\n\t\t\treturn (digicaps->wDeviceID);\n\t\t}\n\t}\n\n\treturn (device_id);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StartAudio - Starts audio playback\n*\n* SYNOPSIS\n*     Error = VQA_StartAudio(VQA)\n*\n*     long VQA_StartAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Start the audio playback for the movie.\n*\n* INPUTS\n*     VQA - Pointer to private VQA handle.\n*\n* RESULT\n*     Error - 0 if successful, or -1 error code.\n*\n****************************************************************************/\n\nlong VQA_StartAudio(VQAHandleP *vqap)\n{\n\tVQAConfig *config;\n\tVQAAudio  *audio;\n\n\t/* Save buffers for the callback routine */\n\tVQAP = vqap;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tconfig = &vqap->Config;\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Return if already playing */\n\tif (AudioFlags & VQAAUDF_ISPLAYING) {\n\t\treturn (-1);\n\t}\n\n \t/* Set my driver handle */\n\tif (config->DigiHandle != -1) {\n\t\taudio->DigiHandle = config->DigiHandle;\n\t}\n\n\tif (audio->DigiHandle == (WORD)-1) {\n\t\treturn (-1);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * Initialize the sample structure.\n\t *-----------------------------------------------------------------------*/\n\tmemset(&audio->sSOSSampleData, 0, sizeof(_SOS_START_SAMPLE));\n  audio->sSOSSampleData.lpSamplePtr = (unsigned char *)audio->Buffer;\n \taudio->sSOSSampleData.dwSampleSize = config->HMIBufSize;\n\taudio->sSOSSampleData.wVolume = (config->Volume << 7);\n\taudio->sSOSSampleData.wSampleID = HMI_SAMPLE;\n\taudio->sSOSSampleData.lpCallback = AudioCallback;\n\n\t/* Set the channel flags for the type of data we have. */\n\tif (audio->Channels == 2) {\n\t\taudio->sSOSSampleData.wChannel = _INTERLEAVED;\n\t} else {\n\t\taudio->sSOSSampleData.wChannel = _CENTER_CHANNEL;\n\t}\n\n\t/* If the card is unable to handle stereo data the we must notify the\n\t * sound system to convert the stereo data to mono data during playback.\n\t */\n\tif ((audio->Channels - 1) > audio->DigiCaps.wChannels) {\n\t\taudio->sSOSSampleData.wSampleFlags |= _STEREOTOMONO;\n\t}\n\n\t/* If the card is unable to handle the sample size of the audio data\n\t * then we must notify the sound system to convert the audio data to\n\t * the proper format.\n\t */\n\tif (audio->BitsPerSample != audio->DigiCaps.wBitsPerSample) {\n\t\tif (audio->BitsPerSample > audio->DigiCaps.wBitsPerSample) {\n\t\t\taudio->sSOSSampleData.wSampleFlags |= _TRANSLATE16TO8;\n\t\t} else {\n\t\t\taudio->sSOSSampleData.wSampleFlags |= _TRANSLATE8TO16;\n\t\t}\n\t}\n\n\t/* Adjust the pitch if the driver is setup to playback at a different\n\t * rate than what the sample was recorded at.\n\t */\n\tif (audio->sSOSInitDriver.wSampleRate != audio->SampleRate) {\n\t\tldiv_t result;\n\n\t\tresult = ldiv(audio->SampleRate, audio->sSOSInitDriver.wSampleRate);\n\t\taudio->sSOSSampleData.dwSamplePitchAdd = (long)MAKE_LONG((short)result.quot,\n\t\t\t\t(short)(((long)result.rem * 0x10000L) / audio->sSOSInitDriver.wSampleRate));\n\t\taudio->sSOSSampleData.wSampleFlags |= _PITCH_SHIFT;\n\t}\n\n\t/* Start playback */\n \taudio->SampleHandle = sosDIGIStartSample(audio->DigiHandle,\n\t\t\t&audio->sSOSSampleData);\n\n\taudio->Flags |= VQAAUDF_ISPLAYING;\n\tAudioFlags |= VQAAUDF_ISPLAYING;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StopAudio - Stop audio playback.\n*\n* SYNOPSIS\n*     VQA_StopAudio(VQA)\n*\n*     void VQA_StopAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Halts the currently playing audio stream.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_StopAudio(VQAHandleP *vqap)\n{\n\tVQAAudio *audio;\n\n\t/* Dereference for quick access. */\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Just return if not playing */\n\tif (AudioFlags & VQAAUDF_ISPLAYING) {\n\t\tsosDIGIStopSample(audio->DigiHandle, audio->SampleHandle);\n\t\taudio->Flags &= ~VQAAUDF_ISPLAYING;\n\t\tAudioFlags &= ~VQAAUDF_ISPLAYING;\n\t}\n\n\tVQAP = NULL;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     CopyAudio - Copy data from Audio Temp buffer into Audio play buffer.\n*\n* SYNOPSIS\n*     Error = CopyAudio(VQA)\n*\n*     long CopyAudio(VQAHandleP *);\n*\n* FUNCTION\n*     This routine just copies the data in the TempBuf into the correct\n*     spots in the audio play buffer.  If there is no room available in the\n*     audio play buffer, the routine returns VQAERR_SLEEPING, which will put\n*     the whole Loader to \"sleep\" while it waits for a free buffer.\n*\n*     If there's no data in the TempBuf to copy, the routine just returns 0.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle structure.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nlong CopyAudio(VQAHandleP *vqap)\n{\n\tVQAAudio  *audio;\n\tVQAConfig *config;\n\tlong      startblock;\n\tlong      endblock;\n\tlong      len1,len2;\n\tlong      i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\taudio = &vqap->VQABuf->Audio;\n\tconfig = &vqap->Config;\n\n\t/* If audio is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, or if there's no data to copy, just return 0\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (vqap->vocfh != -1)\n\t\t\t|| (audio->Buffer == NULL) || (audio->TempBufLen == 0)) {\n\t#else  /* VQAVOC_ON */\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (audio->Buffer == NULL)\n\t\t\t|| (audio->TempBufLen == 0)) {\n\t#endif /* VQAVOC_ON */\n\n\t\treturn (0);\n\t}\n\n\t/* Compute start & end blocks to copy into */\n\tstartblock = (audio->AudBufPos / config->HMIBufSize);\n\tendblock = (audio->AudBufPos + audio->TempBufLen) / config->HMIBufSize;\n\n\tif (endblock >= audio->NumAudBlocks) {\n\t\tendblock -= audio->NumAudBlocks;\n\t}\n\n\t/* If 'endblock' hasn't played yet, return VQAERR_SLEEPING */\n\tif (audio->IsLoaded[endblock] == 1) {\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\t/* Copy the data:\n\t *\n\t *  - If 'startblock' < 'endblock', copy the entire buffer\n\t *  - Otherwise, fill to the end of the buffer with part of the data, then\n\t *    copy the rest to the beginning of the buffer\n\t */\n\tif (startblock <= endblock) {\n\n\t\t/* Copy data */\n\t\tmemcpy((audio->Buffer + audio->AudBufPos), audio->TempBuf,\n\t\t\t\taudio->TempBufLen);\n\n\t\t/* Adjust current load position */\n\t\taudio->AudBufPos += audio->TempBufLen;\n\n\t\t/* Mark buffer as empty */\n\t\taudio->TempBufLen = 0;\n\n\t\t/* Set all blocks to loaded */\n\t\tfor (i = startblock; i < endblock; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t} else {\n\n\t\t/* Compute length of each piece */\n\t\tlen1 = config->AudioBufSize - audio->AudBufPos;\n\t\tlen2 = audio->TempBufLen - len1;\n\n\t\t/* Copy 1st piece into end of Audio Buffer */\n\t\tmemcpy((audio->Buffer + audio->AudBufPos), audio->TempBuf, len1);\n\n\t\t/* Copy 2nd piece into start of Audio Buffer */\n\t\tmemcpy(audio->Buffer, audio->TempBuf + len1, len2);\n\n\t\t/* Adjust load position */\n\t\taudio->AudBufPos = len2;\n\n\t\t/* Mark buffer as empty */\n\t\taudio->TempBufLen = 0;\n\n\t\t/* Set blocks to loaded */\n\t\tfor (i = startblock; i < audio->NumAudBlocks; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\tfor (i = 0; i < endblock; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     AudioCallback - Sound system callback.\n*\n* SYNOPSIS\n*     AudioCallback(DriverHandle, Action, SampleID)\n*\n*     void AudioCallback(WORD, WORD, WORD);\n*\n* FUNCTION\n*     Our custom audio callback routine that services HMI.\n*\n* INPUTS\n*     DriverHandle - HMI driver handle.\n*     Action       - Action taken.\n*     SampleID     - ID of sample.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid far __cdecl AudioCallback(WORD wDriverHandle,WORD wAction,WORD wSampleID)\n{\n\tVQAAudio  *audio;\n\tVQAConfig *config;\n\n\t/* Dereference commonly used data members for quicker access. */\n\taudio = &VQAP->VQABuf->Audio;\n\tconfig = &VQAP->Config;\n\n\t/* Suppress compiler warnings */\n\twDriverHandle = wDriverHandle;\n\twSampleID = wSampleID;\n\n  /* See if we're called because the buffer is empty */\n\tif (wAction == _SAMPLE_PROCESSED) {\n\n\t\t/* Compute the 'NextBlock' index */\n\t\taudio->NextBlock = audio->CurBlock + 1;\n\n\t\tif (audio->NextBlock >= audio->NumAudBlocks) {\n\t\t\taudio->NextBlock = 0;\n\t\t}\n\n\t\t/* See if the next block has data in it; if so, update the audio\n\t\t * buffer play position & the 'CurBlock' value.\n\t\t * If not, don't change anything and replay this block.\n\t\t */\n\t\tif (audio->IsLoaded[audio->NextBlock] == 1) {\n\n\t\t\t/* Update this block's status to loadable (0) */\n\t\t\taudio->IsLoaded[audio->CurBlock] = 0;\n\n\t\t\t/* Update position within audio buffer */\n\t\t\taudio->PlayPosition += config->HMIBufSize;\n\t\t\taudio->CurBlock++;\n\n\t\t\tif (audio->PlayPosition >= config->AudioBufSize) {\n\t\t\t\taudio->PlayPosition = 0;\n\t\t\t\taudio->CurBlock = 0;\n\t\t\t}\n\t\t} else {\n\t\t\taudio->NumSkipped++;\n\t\t}\n\n\t\t/* Start the new buffer playing */\n\t  audio->sSOSSampleData.lpSamplePtr = (unsigned char *)(audio->Buffer)\n\t\t\t\t+ audio->PlayPosition;\n\n   \tsosDIGIContinueSample(audio->DigiHandle, audio->SampleHandle,\n\t\t\t\t&audio->sSOSSampleData);\n\n\t\taudio->SamplesPlayed += config->HMIBufSize;\n\t}\n}\n\n/* Dummy function used to mark the beginning address of the file. */\nstatic void EndAddr(void)\n{\n}\n\n\n\n#else\t//!VQADIRECT_SOUND\n\n/**************************************************************************\n*\n* Start of Direct Sound code\n*\n*\n* The direct sound implementation works by taking what would have been the\n* HMI sound buffer and feeding the contents to a direct sound secondary\n* buffer.\n*\n* Steve T. -  12/15/95\n*\n*\n*\n*\n***************************************************************************/\n\nBOOL\tSuspendAudioCallback = FALSE;\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StartTimerInt - Initialize system timer interrupt.\n*\n* SYNOPSIS\n*     Error = VQA_StartTimerInt(VQA, Init)\n*\n*     long VQA_StartTimerInt(VQAHandeP *, long);\n*\n* FUNCTION\n*     Initialize the HMI timer system and add our own timer event. If the\n*     system has already been initialized then we are given access to the\n*     the timer system.\n*\n* INPUTS\n*     VQA  - Pointer to private VQAHandle structure.\n*     Init - Initialize HMI timer system flag. (TRUE = Initialize)\n*\n* RESULT\n*     Error - 0 if successful, -1 if error.\n*\n****************************************************************************/\n\nlong VQA_StartTimerInt(VQAHandleP *vqap, long init)\n{\n\tVQAAudio *audio;\n\n\t/* Dereference for quick access. */\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Register the VQA_TickCount timer event. */\n\tif ((AudioFlags & VQAAUDF_HMITIMER) == (HMI_UNINIT<<VQAAUDB_HMITIMER)) {\n\t\tVQATimer = timeSetEvent ( 1000/VQA_TIMETICKS , 1 , TimerCallback , 0 , TIME_PERIODIC);\n\n\t\tif (VQATimer){\n\n\t\t\t/* Flag the timer interrupt as being registered. */\n\t\t\tAudioFlags |= (HMI_VQAINIT << VQAAUDB_HMITIMER);\n\t\t} else {\n\t\t\treturn (-1);\n\t\t}\n\t}\n\n\t/* Flag availability of the timer interrupt. */\n\taudio->Flags |= (HMI_VQAINIT << VQAAUDB_HMITIMER);\n\n\t/* Increment the timer interrupt usage count. */\n\tTimerIntCount++;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StopTimerInt - Remove system timer interrupt.\n*\n* SYNOPSIS\n*     VQA_StopTimerInt()\n*\n*     void VQA_StopTimerInt(void);\n*\n* FUNCTION\n*     Remove our timer event from the HMI timer system. Uninitialize the\n*     HMI timer system if we initialized it.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_StopTimerInt(VQAHandleP *vqap)\n{\n\tVQAAudio *audio;\n\n\t/* Dereference for quick access. */\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Decrement the timer interrupt usage count. */\n\tif (TimerIntCount) {\n\t\tTimerIntCount--;\n\t}\n\n\t/* Remove the timer interrrupt if it is initialized and the use count is\n\t * zero. Otherwise, clear the callers timer interrupt availability flag.\n\t */\n\tif (((AudioFlags & VQAAUDF_HMITIMER) == (HMI_VQAINIT<<VQAAUDB_HMITIMER))\n\t\t\t&& (TimerIntCount == 0)) {\n\n\t\ttimeKillEvent(VQATimer);\n\t\tAudioFlags &= ~VQAAUDF_HMITIMER;\n\t} else {\n\t\tAudioFlags &= ~VQAAUDF_HMITIMER;\n\t}\n\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     TimerCallback - VQA timer event. (Called by Windoze)\n*\n* SYNOPSIS\n*     TimerCallback()\n*\n*     void TimerCallback(void);\n*\n* FUNCTION\n*     Our custom timer event. This is the timer event that we register with\n*     Windows for system timing.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid CALLBACK TimerCallback (UINT , UINT , DWORD , DWORD , DWORD)\n{\n\tVQATickCount++;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_OpenAudio - Open sound system.\n*\n* SYNOPSIS\n*     Error = VQA_OpenAudio(VQAHandleP)\n*\n*     long VQA_OpenAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Initialise the sound system. Create a direct sound object and the\n*     direct sound primary sound buffer if they dont already exist.\n*\n* INPUTS\n*     VQAHandleP - Pointer to private VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, -1 if error.\n*\n****************************************************************************/\n\nlong VQA_OpenAudio(VQAHandleP *vqap, HWND window)\n{\n\tVQAData       *vqabuf;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tVQAHeader     *header;\n\tunsigned char *driver_path;\n\tWORD          port;\n\tlong          rc;\n\n\t/* Dereference data memebers for quicker access. */\n\tconfig = &vqap->Config;\n\theader = &vqap->Header;\n\tvqabuf = vqap->VQABuf;\n\taudio = &vqabuf->Audio;\n\n\t/* Reset the buffer position to the beginning. */\n\taudio->CurBlock = 0;\n\n\n\t/*\n\t**\tcreate the direct sound object if it doesnt already exist\n\t*/\n\tif (!config->SoundObject){\n\n\t\tif ( DirectSoundCreate (NULL,&config->SoundObject,NULL) !=DS_OK ) {\n\t\t\treturn (-1);\n\t\t}else{\n\t\t\taudio->CreatedSoundObject = TRUE;\n\t\t\t/*\n\t\t\t**\tGive ourselves exclusive access to the sound card\n\t\t\t*/\n\t\t\tif ( config->SoundObject->SetCooperativeLevel( window, DSSCL_EXCLUSIVE ) != DS_OK){\n\t\t\t\tconfig->SoundObject->Release();\n\t\t\t\treturn (-1);\n\t\t\t}\n\t\t}\n\n\n\t\tif (!config->PrimaryBufferPtr){\n\t\t\t/*\n\t\t\t** Define the format of the primary sound buffer\n\t\t\t*/\n\t\t\tmemset (&audio->BufferDesc , 0 , sizeof(DSBUFFERDESC));\n\t\t\taudio->BufferDesc.dwSize=sizeof(DSBUFFERDESC);\n\t\t\taudio->BufferDesc.dwFlags=DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;\n\n\t\t\tmemset (&audio->DsBuffFormat , 0 , sizeof(WAVEFORMATEX));\n\t\t\taudio->DsBuffFormat.wFormatTag\t= WAVE_FORMAT_PCM;\n\t\t\taudio->DsBuffFormat.nChannels\t\t= (unsigned short) 2;\n\n\n\t\t\t/*-------------------------------------------------------------------------\n\t \t\t* Compute the playback rate:\n\t \t\t*\n\t \t\t* - If Config->AudioRate is -1, use HMI_DATA_RATE scaled to the specified\n\t \t\t*   frame rate (so the audio plays faster if we're playing faster)\n\t \t\t* - otherwise, use the specified rate\n\t \t\t*-----------------------------------------------------------------------*/\n\t\t\tif (config->AudioRate != -1) {\n\t\t\t\taudio->DsBuffFormat.nSamplesPerSec = config->AudioRate;\n\t\t\t}\n\t\t\telse if (config->FrameRate != header->FPS) {\n\t\t\t\taudio->DsBuffFormat.nSamplesPerSec = ((audio->SampleRate*config->FrameRate)\n\t\t\t\t\t\t/ (unsigned long)header->FPS);\n\n\t\t\t\tconfig->AudioRate = audio->DsBuffFormat.nSamplesPerSec;\n\t\t\t} else {\n\t\t\t\taudio->DsBuffFormat.nSamplesPerSec = audio->SampleRate;\n\t\t\t\tconfig->AudioRate = audio->SampleRate;\n\t\t\t}\n\n\t\t\taudio->DsBuffFormat.wBitsPerSample\t= (short) 16;\n\t\t\taudio->DsBuffFormat.nBlockAlign\t= (unsigned short)( (audio->DsBuffFormat.wBitsPerSample/8) * audio->DsBuffFormat.nChannels);\n\t\t\taudio->DsBuffFormat.nAvgBytesPerSec= audio->DsBuffFormat.nSamplesPerSec * audio->DsBuffFormat.nBlockAlign;\n\t\t\taudio->DsBuffFormat.cbSize = 0;\n\n\t\t\t/*\n\t\t\t**  Create the direct sound primary sound buffer object\n\t\t\t*/\n\t\t\tif ( config->SoundObject->CreateSoundBuffer (&audio->BufferDesc ,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&config->PrimaryBufferPtr ,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNULL ) !=DS_OK ){\n\t\t\t\tif (audio->CreatedSoundObject){\n\t\t\t\t\tconfig->SoundObject->Release();\n\t\t\t\t\taudio->CreatedSoundObject = FALSE;\n\t\t\t\t}\n\t\t\t\treturn (-1);\n\t\t\t}\n\n\t\t\taudio->CreatedSoundBuffer = TRUE;\n\t\t}\n\t}\n\n\taudio->Flags |= (HMI_VQAINIT << VQAAUDB_DIGIINIT);\n\tAudioFlags |= (HMI_VQAINIT << VQAAUDB_DIGIINIT);\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_CloseAudio - Close sound system\n*\n* SYNOPSIS\n*     VQA_CloseAudio()\n*\n*     void VQA_CloseAudio(void);\n*\n* FUNCTION\n*     Removes VQA's involvement in the audio system.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_CloseAudio(VQAHandleP *vqap)\n{\n\tVQAAudio\t\t*audio;\n\tVQAConfig\t*config;\n\n\t/* Dereference for quick access. */\n\taudio\t = &vqap->VQABuf->Audio;\n\tconfig = &vqap->Config;\n\n\t/*\n\t** If the audio is still playing then stop it\n\t*/\n\tVQA_StopAudio(vqap);\n\n\t/* Remove the windows callback event */\n\t//if ((AudioFlags & VQAAUDF_DIGIINIT) == (HMI_VQAINIT<<VQAAUDB_DIGIINIT)) {\n\t//\ttimeKillEvent(audio->TimerHandle);\n\t//}\n\n\taudio->Flags &= ~VQAAUDF_TIMERINIT;\n\tAudioFlags &= ~VQAAUDF_TIMERINIT;\n\n\t/*\n\t**  Remove the direct sound primary buffer if we created it\n\t*/\n\tif (audio->CreatedSoundBuffer){\n\t\tconfig->PrimaryBufferPtr->Stop();\n\t\tconfig->PrimaryBufferPtr->Release();\n\t\tconfig->PrimaryBufferPtr = NULL;\n\t\taudio->CreatedSoundBuffer = FALSE;\n\t}\n\n\t/*\n\t** If we created the sound object then remove that as well\n\t*/\n\tif (audio->CreatedSoundObject){\n\t\tconfig->SoundObject->Release();\n\t\tconfig->SoundObject = NULL;\n\t}\n\n\taudio->Flags &= ~VQAAUDF_DIGIINIT;\n\tAudioFlags &= ~VQAAUDF_DIGIINIT;\n\tAudioFlags &= ~VQAAUDF_ISPLAYING;\n\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StartAudio - Starts audio playback\n*\n* SYNOPSIS\n*     Error = VQA_StartAudio(VQA)\n*\n*     long VQA_StartAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Start the audio playback for the movie.\n*\n* INPUTS\n*     VQA - Pointer to private VQA handle.\n*\n* RESULT\n*     Error - 0 if successful, or -1 error code.\n*\n****************************************************************************/\n\nlong VQA_StartAudio(VQAHandleP *vqap)\n{\n\tVQAConfig *config;\n\tVQAAudio  *audio;\n\n\t/* Save buffers for the callback routine */\n\tVQAP = vqap;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tconfig = &vqap->Config;\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Return if already playing */\n\tif (AudioFlags & VQAAUDF_ISPLAYING) {\n\t\treturn (-1);\n\t}\n\n\t/*\n\t** If we already have a direct sound secondary buffer then get rid of it\n\t*/\n\tif (audio->SecondaryBufferPtr != NULL){\n\t\taudio->SecondaryBufferPtr->Stop();\n\t\taudio->SecondaryBufferPtr->Release();\n\t\taudio->SecondaryBufferPtr = NULL;\n\t}\n\t/*\n\t** Make it big enough for 4 blocks of HMI data\n\t*/\n\taudio->SecondaryBufferSize = config->HMIBufSize*4;\n\n\t/*\n\t** Define the format for the secondary sound buffer\n\t*/\n\tmemset (&audio->BufferDesc , 0 , sizeof(DSBUFFERDESC));\n\taudio->BufferDesc.dwSize\t\t\t\t= sizeof(DSBUFFERDESC);\n\taudio->BufferDesc.dwFlags\t\t\t\t= DSBCAPS_CTRLVOLUME;\n\taudio->BufferDesc.dwBufferBytes\t\t= audio->SecondaryBufferSize;\n\taudio->BufferDesc.lpwfxFormat \t\t= (LPWAVEFORMATEX) &audio->DsBuffFormat;\n\tmemset (&audio->DsBuffFormat , 0 , sizeof(WAVEFORMATEX));\n\taudio->DsBuffFormat.wFormatTag\t\t= WAVE_FORMAT_PCM;\n\taudio->DsBuffFormat.nSamplesPerSec\t= audio->SampleRate;\n\taudio->DsBuffFormat.nChannels\t\t\t= audio->Channels;\n\taudio->DsBuffFormat.wBitsPerSample\t= audio->BitsPerSample;\n\taudio->DsBuffFormat.nBlockAlign\t\t= (short) ((audio->DsBuffFormat.wBitsPerSample/8) * audio->DsBuffFormat.nChannels);\n\taudio->DsBuffFormat.nAvgBytesPerSec\t= audio->DsBuffFormat.nSamplesPerSec * audio->DsBuffFormat.nBlockAlign;\n\n\t/*\n\t** Create the secondary sound buffer object\n\t*/\n\tconfig->SoundObject->CreateSoundBuffer (&audio->BufferDesc , &audio->SecondaryBufferPtr , NULL);\n\n\t/*\n\t** Set the format of the primary buffer to the same as the secondary buffer\n\t*/\n\tconfig->PrimaryBufferPtr->Stop();\n\tconfig->PrimaryBufferPtr->SetFormat (&audio->DsBuffFormat);\n\n\tif (config->PrimaryBufferPtr->Play(0, 0, DSBPLAY_LOOPING) != DS_OK){\n\t\treturn (-1);\n\t}\n\n\t/* Start playback */\n\taudio->EndLastAudioChunk = 0;\n\taudio->ChunksMovedToAudioBuffer = 0;\n\tMove_HMI_Audio_Block_To_Direct_Sound_Buffer();\n\tMove_HMI_Audio_Block_To_Direct_Sound_Buffer();\n\taudio->SecondaryBufferPtr->SetCurrentPosition (0);\n\tif (audio->SecondaryBufferPtr->Play(0, 0, DSBPLAY_LOOPING) != DS_OK){\n\t\treturn (-1);\n\t}\n\n\t/*\n\t** Set the volume\n\t*/\n\tlong volume = config->Volume << 7;\n\taudio->SecondaryBufferPtr->SetVolume(- ( ( (32768 - volume)*1000) >>15 ) );\n\n\t// Set orf 60hz timer\n\taudio->TimerHandle = timeSetEvent ( 1000/60 , 1 , AudioCallback , 0 , TIME_PERIODIC);\n\n\taudio->Flags |= VQAAUDF_ISPLAYING;\n\tAudioFlags |= VQAAUDF_ISPLAYING;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StopAudio - Stop audio playback.\n*\n* SYNOPSIS\n*     VQA_StopAudio(VQA)\n*\n*     void VQA_StopAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Halts the currently playing audio stream.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_StopAudio(VQAHandleP *vqap)\n{\n\tVQAAudio *audio;\n\tVQAConfig *config;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tconfig = &vqap->Config;\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Just return if not playing */\n\tif (AudioFlags & VQAAUDF_ISPLAYING) {\n\n\t\t/*\n\t\t** Stop the primary buffer so the audio doesnt glitch\n\t\t*/\n\t\tconfig->PrimaryBufferPtr->Stop();\n\n\t\t/*\n\t\t** Remove the windows timer event\n\t\t*/\n\t\ttimeKillEvent(audio->TimerHandle);\n\t\taudio->TimerHandle = NULL;\n\n\t\t/*\n\t\t** Kill the secondary sound buffer\n\t\t*/\n\t\tif (audio->SecondaryBufferPtr){\n\t\t\taudio->SecondaryBufferPtr->Stop();\n\t\t\taudio->SecondaryBufferPtr->Release();\n\t\t\taudio->SecondaryBufferPtr = NULL;\n\t\t}\n\t\taudio->Flags &= ~VQAAUDF_ISPLAYING;\n\t\tAudioFlags &= ~VQAAUDF_ISPLAYING;\n\t}\n\n\tVQAP = NULL;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     CopyAudio - Copy data from Audio Temp buffer into Audio play buffer.\n*\n* SYNOPSIS\n*     Error = CopyAudio(VQA)\n*\n*     long CopyAudio(VQAHandleP *);\n*\n* FUNCTION\n*     This routine just copies the data in the TempBuf into the correct\n*     spots in the audio play buffer.  If there is no room available in the\n*     audio play buffer, the routine returns VQAERR_SLEEPING, which will put\n*     the whole Loader to \"sleep\" while it waits for a free buffer.\n*\n*     If there's no data in the TempBuf to copy, the routine just returns 0.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle structure.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nlong CopyAudio(VQAHandleP *vqap)\n{\n\tVQAAudio  *audio;\n\tVQAConfig *config;\n\tlong      startblock;\n\tlong      endblock;\n\tlong      len1,len2;\n\tlong      i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\taudio = &vqap->VQABuf->Audio;\n\tconfig = &vqap->Config;\n\n\t/* If audio is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, or if there's no data to copy, just return 0\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (vqap->vocfh != -1)\n\t\t\t|| (audio->Buffer == NULL) || (audio->TempBufLen == 0)) {\n\t#else  /* VQAVOC_ON */\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (audio->Buffer == NULL)\n\t\t\t|| (audio->TempBufLen == 0)) {\n\t#endif /* VQAVOC_ON */\n\n\t\treturn (0);\n\t}\n\n\t/* Compute start & end blocks to copy into */\n\tstartblock = (audio->AudBufPos / config->HMIBufSize);\n\tendblock = (audio->AudBufPos + audio->TempBufLen) / config->HMIBufSize;\n\n\tif (endblock >= audio->NumAudBlocks) {\n\t\tendblock -= audio->NumAudBlocks;\n\t}\n\n\t/* If 'endblock' hasn't played yet, return VQAERR_SLEEPING */\n\tif (audio->IsLoaded[endblock] == 1) {\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\t/* Copy the data:\n\t *\n\t *  - If 'startblock' < 'endblock', copy the entire buffer\n\t *  - Otherwise, fill to the end of the buffer with part of the data, then\n\t *    copy the rest to the beginning of the buffer\n\t */\n\tif (startblock <= endblock) {\n\n\t\t/* Copy data */\n\t\tmemcpy((audio->Buffer + audio->AudBufPos), audio->TempBuf,\n\t\t\t\taudio->TempBufLen);\n\n\t\t/* Adjust current load position */\n\t\taudio->AudBufPos += audio->TempBufLen;\n\n\t\t/* Mark buffer as empty */\n\t\taudio->TempBufLen = 0;\n\n\t\t/* Set all blocks to loaded */\n\t\tfor (i = startblock; i < endblock; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t} else {\n\n\t\t/* Compute length of each piece */\n\t\tlen1 = config->AudioBufSize - audio->AudBufPos;\n\t\tlen2 = audio->TempBufLen - len1;\n\n\t\t/* Copy 1st piece into end of Audio Buffer */\n\t\tmemcpy((audio->Buffer + audio->AudBufPos), audio->TempBuf, len1);\n\n\t\t/* Copy 2nd piece into start of Audio Buffer */\n\t\tmemcpy(audio->Buffer, audio->TempBuf + len1, len2);\n\n\t\t/* Adjust load position */\n\t\taudio->AudBufPos = len2;\n\n\t\t/* Mark buffer as empty */\n\t\taudio->TempBufLen = 0;\n\n\t\t/* Set blocks to loaded */\n\t\tfor (i = startblock; i < audio->NumAudBlocks; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\tfor (i = 0; i < endblock; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t}\n}\n\n\nBOOL\tVQAAudioPaused = FALSE;\n\nvoid VQA_PauseAudio(void)\n{\n\tVQAAudio  \t*audio;\n\tif (VQAP && VQAP->VQABuf){\n\n\t\taudio = &VQAP->VQABuf->Audio;\n\n\t\tif (audio->SecondaryBufferPtr){\n\n\t\t\tif (AudioFlags & VQAAUDF_ISPLAYING && !VQAAudioPaused) {\n\n\t\t\t\taudio->SecondaryBufferPtr->Stop();\n\t\t\t\tVQAAudioPaused = TRUE;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nvoid VQA_ResumeAudio(void)\n{\n\tVQAAudio  \t*audio;\n\tif (VQAP && VQAP->VQABuf){\n\n\t\taudio = &VQAP->VQABuf->Audio;\n\n\t\tif (audio->SecondaryBufferPtr){\n\n\t\t\tif (AudioFlags & VQAAUDF_ISPLAYING && VQAAudioPaused) {\n\n\t\t\t\taudio->SecondaryBufferPtr->SetCurrentPosition (0);\n\t\t\t\taudio->LastChunkPosition = 0;\n\t\t\t\taudio->EndLastAudioChunk = 0;\n\t\t\t\tMove_HMI_Audio_Block_To_Direct_Sound_Buffer();\n\t\t\t\taudio->SecondaryBufferPtr->Play(0,0,DSBPLAY_LOOPING);\n\t\t\t\tVQAAudioPaused = FALSE;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n\n\n\n/****************************************************************************\n*\n* NAME\n*     AudioCallback - Sound system callback.\n*\n* SYNOPSIS\n*     AudioCallback(DriverHandle, Action, SampleID)\n*\n*     void AudioCallback(WORD, WORD, WORD);\n*\n* FUNCTION\n*     Our custom audio callback routine that services HMI.\n*\n* INPUTS\n*     DriverHandle - HMI driver handle.\n*     Action       - Action taken.\n*     SampleID     - ID of sample.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid CALLBACK AudioCallback ( UINT, UINT, DWORD, DWORD, DWORD )\n\n{\n\tVQAAudio  \t*audio;\n\tVQAConfig \t*config;\n\tDWORD\t\t\tplay_cursor;\t\t//Position that direct sound is reading from\n\tDWORD\t\t\twrite_cursor;\t\t//Position in buffer that we can write to\n\tHRESULT\t\treturn_code;\n\tBOOL\t\t\tbuffer_stopped = FALSE;\n\tDWORD\t\t\tstatus;\n\n\n\tif (SuspendAudioCallback || VQAAudioPaused) return;\n\n\t/* Dereference commonly used data members for quicker access. */\n\taudio = &VQAP->VQABuf->Audio;\n\tconfig = &VQAP->Config;\n\n\tif (!audio->SecondaryBufferPtr) return;\n\n\t/*\n\t** See if we are nearing the end of the meaningful data in the direct sound buffer\n\t*/\n\treturn_code = audio->SecondaryBufferPtr->GetCurrentPosition (&play_cursor , &write_cursor);\n\n\tBOOL write_more = FALSE;\n\n\tif (return_code == DSERR_BUFFERLOST || config->PrimaryBufferPtr->GetStatus(&status) == DSERR_BUFFERLOST){\n\t\tconfig->PrimaryBufferPtr->Restore();\n\t\taudio->SecondaryBufferPtr->Restore();\n\t\taudio->SecondaryBufferPtr->Stop();\n\t\tbuffer_stopped = TRUE;\n\t\taudio->SecondaryBufferPtr->SetCurrentPosition (0);\n\t\taudio->LastChunkPosition = 0;\n\t\taudio->EndLastAudioChunk = 0;\n\t\twrite_more = TRUE;\n\t}\n\n\n\tif (play_cursor < audio->EndLastAudioChunk){\n\t\tif (audio->EndLastAudioChunk - play_cursor <= audio->SecondaryBufferSize/4){\n\t\t\twrite_more = TRUE;\n\t\t}\n\t}else{\n\t\tif (( play_cursor > audio->SecondaryBufferSize*3/4) && audio->EndLastAudioChunk==0 ){\n\t\t\twrite_more = TRUE;\n\t\t}\n\t}\n\n\t/*\n\t** See if we need to fill the buffer\n\t*/\n\tif (write_more){\n\t\tif (Move_HMI_Audio_Block_To_Direct_Sound_Buffer()){\n\n\t\t\t/*\n\t\t\t** Start the buffer playing again if we had to stop it\n\t\t\t*/\n\t\t\tif (buffer_stopped){\n\t\t\t\taudio->SecondaryBufferPtr->Play(0,0,DSBPLAY_LOOPING);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Move_HMI_Audio_Block_To_Direct_Sound_Buffer -- moves an audio block which would have been   *\n *                                                played by HMI into a direct sound            *\n *                                                secondary buffer                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   BOOL was block moved                                                              *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    12/21/95 9:51AM ST : Created                                                              *\n *=============================================================================================*/\nextern int VQAMovieDone;\nBOOL Move_HMI_Audio_Block_To_Direct_Sound_Buffer (void)\n{\n\tVQAAudio  \t*audio;\n\tVQAConfig \t*config;\n\n\tLPVOID\t\tplay_buffer_ptr;\t//Beginning of locked area of buffer\n\tLPVOID\t\tdummy_buffer_ptr;\t//Length of locked area in buffer\n\tDWORD\t\t\tlock_length1;\t\t//Beginning of second locked area in buffer\n\tDWORD\t\t\tlock_length2;\t\t//Length of second locked area in buffer\n\tunsigned\t\tnext_fill_pos;\n\tHRESULT\t\treturn_code;\n\tDWORD\t\t\tstatus;\n\n\n\t/* Dereference commonly used data members for quicker access. */\n\taudio = &VQAP->VQABuf->Audio;\n\tconfig = &VQAP->Config;\n\n\n\t/*************************************************************************\n\t**\n\t** Copy the data from the HMI play position into the direct sound buffer\n\t**\n\t*/\n\tnext_fill_pos = audio->EndLastAudioChunk;\n\n\t/*\n\t** Lock the buffer to get a pointer to it\n\t*/\n\treturn_code= audio->SecondaryBufferPtr->Lock ((DWORD)next_fill_pos,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(DWORD)config->HMIBufSize,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&play_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&lock_length1,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&dummy_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&lock_length2,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t0 );\n\n\tif (return_code!=DS_OK) return(FALSE);\n\tif (config->PrimaryBufferPtr->GetStatus(&status) == DSERR_BUFFERLOST) return(FALSE);\n\n\t/*\n\t** Copy the HMI audio buffer to the direct sound buffer\n\t*/\n\tmemcpy ((char*)play_buffer_ptr , (char*)((unsigned)audio->Buffer + (unsigned)audio->PlayPosition) , config->HMIBufSize);\n\n\t/*\n\t** Unlock the direct sound buffer\n\t*/\n\taudio->SecondaryBufferPtr->Unlock(play_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\tlock_length1,\n\t\t\t\t\t\t\t\t\t\t\t\tdummy_buffer_ptr,\n\t\t\t\t\t\t\t\t\t\t\t\tlock_length2);\n\t/*\n\t** Update our audio data pointers\n\t*/\n\taudio->LastChunkPosition = next_fill_pos;\n\taudio->EndLastAudioChunk = next_fill_pos + config->HMIBufSize;\n\tif (audio->EndLastAudioChunk >= audio->SecondaryBufferSize){\n\t\taudio->EndLastAudioChunk = 0;\n\t}\n\n\t/* Compute the 'NextBlock' index */\n\taudio->NextBlock = audio->CurBlock + 1;\n\n\tif (audio->NextBlock >= audio->NumAudBlocks) {\n\t\taudio->NextBlock = 0;\n\t}\n\n\t/* See if the next block has data in it; if so, update the audio\n\t\t* buffer play position & the 'CurBlock' value.\n\t\t* If not, don't change anything and replay this block.\n\t\t*/\n\tif (audio->IsLoaded[audio->NextBlock] == 1) {\n\n\t\t/* Update this block's status to loadable (0) */\n\t\taudio->IsLoaded[audio->CurBlock] = 0;\n\n\t\t/* Update position within audio buffer */\n\t\taudio->PlayPosition += config->HMIBufSize;\n\t\taudio->CurBlock++;\n\n\t\tif (audio->PlayPosition >= config->AudioBufSize) {\n\t\t\taudio->PlayPosition = 0;\n\t\t\taudio->CurBlock = 0;\n\t\t}\n\t\taudio->ChunksMovedToAudioBuffer++;\n\t\treturn (TRUE);\n\t} else {\n\t\tif (VQAMovieDone){\n\t\t\taudio->ChunksMovedToAudioBuffer++;\n\t\t}\n\t\taudio->NumSkipped++;\n\t\t/*\n\t\t** Enable frame skipping to prevent this happening again\n\t\t*/\n\t\tconfig->DrawFlags &= ~VQACFGF_NOSKIP;\n\t\treturn (FALSE);\n\t}\n}\n\n\n\n\n\n#endif\t//!VQADIRECT_SOUND\n\n\n#endif /* VQAAUDIO_ON */\n\n\n\n\n\n\n\n\n\n\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_SetTimer - Resets current time to given tick value.\n*\n* SYNOPSIS\n*     VQA_SetTimer(Time, Method)\n*\n*     void VQA_SetTimer(long, long);\n*\n* FUNCTION\n*     Sets 'TickOffset' to a value that will make the current time look like\n*     the time passed in. This function allows the player to be \"paused\",\n*     by recording the time of the pause, and then setting the timer to\n*     that time. The timer method used by the player is also set. The method\n*     selected is not neccesarily the method that will be used because some\n*     timer methods work with only certain playback conditions. (EX: The\n*     audio DMA timer method cannot be used if there is not any audio\n*     playing.)\n*\n* INPUTS\n*     Time   - Value to set current time to.\n*     Method - Timer method to use.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_SetTimer(VQAHandleP *vqap, long time, long method)\n{\n\tunsigned long curtime;\n\n\t#if(VQAAUDIO_ON)\n\tVQAAudio      *audio;\n\n\t/* Dereference for quick access. */\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* If the client does not have a preferencee then pick a method\n\t * based on the state of the player.\n\t */\n\tif (method == VQA_TMETHOD_DEFAULT) {\n\n\t\t/* If we are playing audio, use the audio DMA position. */\n\t\tif (AudioFlags & VQAAUDF_ISPLAYING) {\n\t\t\tmethod = VQA_TMETHOD_AUDIO;\n\t\t}\n\n\t\t/* Otherwise use the HMI timer if it is initialized. */\n\t\telse if (AudioFlags & VQAAUDF_HMITIMER) {\n\t\t\tmethod = VQA_TMETHOD_INT;\n\t\t}\n\n\t\t/* If all else fails resort the the \"jerky\" DOS time. */\n\t\telse {\n\t\t\tmethod = VQA_TMETHOD_DOS;\n\t\t}\n\t} else {\n\n\t\t/* We cannot use the DMA position if there isn't any audio playing. */\n\t\tif (!(AudioFlags & VQAAUDF_ISPLAYING) && (method == VQA_TMETHOD_AUDIO)) {\n\t\t\tmethod = VQA_TMETHOD_INT;\n\t\t}\n\n\t\t/* We cannot use the timer if it has not been initialized. */\n\t\tif (!(AudioFlags & VQAAUDF_HMITIMER) && (method == VQA_TMETHOD_INT)) {\n\t\t\tmethod = VQA_TMETHOD_DOS;\n\t\t}\n\t}\n\n\tTimerMethod = method;\n\t#else\n\tmethod = method;\n\t#endif\n\n\tTickOffset = 0L;\n\tcurtime = VQA_GetTime(vqap);\n\tTickOffset = (time - curtime);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_GetTime - Return current time.\n*\n* SYNOPSIS\n*     Time = VQA_GetTime()\n*\n*     unsigned long VQA_GetTime(void);\n*\n* FUNCTION\n*     This routine returns timer ticks computed one of 3 ways:\n*\n*     1) If audio is playing, the timer is based on the DMA buffer position:\n*        Compute the number of audio samples that have actually been played.\n*        The following internal HMI variables are used:\n*\n*          _lpSOSDMAFillCount[drv_handle]: current DMA buffer position\n*          _lpSOSSampleList[drv_handle][samp_handle]:\n*          sampleTotalBytes: total bytes sent by HMI to the DMA buffer\n*          sampleLastFill: HMI's last fill position in DMA buffer\n*\n*        So, the number of samples actually played is:\n*\n*          sampleTotalBytes - <DMA_diff>\n*          where <DMA_diff> is how far ahead sampleLastFill is in front of\n*          _lpSOSDMAFillCount: (sampleLastFill - _lpSOSDMAFillCount)\n*\n*        These values are indices into a circular DMA buffer, so:\n*\n*          if (sampleLastFill >= _lpSOSDMAFillCount)\n*            <DMA_diff> = sampleLastFill - _lpSOSDMAFillCount\n*          else\n*            <DMA_diff> = (DMA_BUF_SIZE - lpSOSDMAFillCount) + sampleLastFill\n*\n*        Note that, if using the stereo driver with mono data, you must\n*        divide LastFill & FillCount by 2, but not TotalBytes. If using the\n*        stereo driver with stereo data, you must divide all 3 variables\n*        by 2.\n*\n*     2) If no audio is playing, but the timer interrupt is running,\n*        VQATickCount is used as the timer\n*\n*     3) If no audio is playing & no timer interrupt is going, the DOS 18.2\n*        system timer is used.\n*\n*     Regardless of the method, TickOffset is used as an offset from the\n*     computed time.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Time - Time in VQA_TIMETICKS\n*\n****************************************************************************/\nunsigned long VQA_GetTime(VQAHandleP *vqap)\n{\n\t#if(VQAAUDIO_ON)\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tunsigned long fillcount;\n\tunsigned long lastfill;\n\tunsigned long dma_diff;\n\tunsigned long totalbytes;\n\tunsigned long samples;\n\tDWORD\t\t\t\tplay_cursor;\t\t//Position that direct sound is reading from\n\tDWORD\t\t\t\twrite_cursor;\t\t//Position in buffer that we can write to\n\tunsigned\t\t\ttemp;\n\t#endif\n\n\t// MEG 09.25.95 - changed from long to unsigned long\n\tunsigned long ticks;\n\n\t#if(VQAAUDIO_ON)\n\tswitch (TimerMethod) {\n\n\t\t/* If Audio is playing then timing is based on the audio DMA buffer\n\t\t * position.\n\t\t */\n\t\tcase VQA_TMETHOD_AUDIO:\n\n\t\t\t/* Dereference commonly used data members for quicker access. */\n\t\t\taudio = &vqap->VQABuf->Audio;\n\t\t\tconfig = &vqap->Config;\n\t\t\t//vqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\n\t\t\t#if (VQADIRECT_SOUND)\n\n\t\t\t\ttotalbytes = (audio->ChunksMovedToAudioBuffer) * config->HMIBufSize;\n\n\t\t\tif (audio->SecondaryBufferPtr &&\n\t\t\t\taudio->SecondaryBufferPtr->GetCurrentPosition (&play_cursor , &write_cursor) == DS_OK){\n\t\t\t\ttotalbytes = (audio->ChunksMovedToAudioBuffer) * config->HMIBufSize;\n\n\t\t\t\tif (audio->LastChunkPosition){\n\t\t\t\t\ttotalbytes += play_cursor - audio->LastChunkPosition;\n\t\t\t\t}else {\n\t\t\t\t\tif (play_cursor > audio->SecondaryBufferSize*3/4){\n\t\t\t\t\t\ttotalbytes -= audio->SecondaryBufferSize - play_cursor;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttotalbytes += play_cursor - audio->LastChunkPosition;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\n\t\t\t}else{\n\t\t\t\ttotalbytes = (audio->ChunksMovedToAudioBuffer-1) * config->HMIBufSize;\n\t\t\t}\n\n\n\t\t\tsamples = totalbytes/audio->DsBuffFormat.nChannels;\n\t\t\tsamples = samples/(audio->DsBuffFormat.wBitsPerSample >> 3);\n\n\t\t\t#else\t\t//VQADIRECT_SOUND\n\n\t\t\t/* Compute our current position in the audio track by getting the\n\t\t\t * bytes processed by HMI. Then adjust the bytes processed by the\n\t\t\t * position of the DMA fill handler, this should tell us exactly\n\t\t\t * where we are in the audio track.\n\t\t\t */\n\t\t\tfillcount = (unsigned long)(*_lpSOSDMAFillCount[audio->DigiHandle]);\n\t\t\tlastfill = _lpSOSSampleList[audio->DigiHandle][audio->SampleHandle]->sampleLastFill;\n\t\t\ttotalbytes = _lpSOSSampleList[audio->DigiHandle][audio->SampleHandle]->sampleTotalBytes;\n\n\t\t\tif (totalbytes == 0) {\n\t\t\t\tdma_diff = 0;\n\t\t\t} else {\n\t\t\t\tif (lastfill > fillcount) {\n\t\t\t\t\tdma_diff = lastfill - fillcount;\n\t\t\t\t} else {\n\t\t\t\t\tdma_diff = (config->HMIBufSize - fillcount) + lastfill;\n\t\t\t\t}\n\n\t\t\t\tif (dma_diff > totalbytes) {\n\t\t\t\t\tdma_diff = totalbytes;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Calculate the number of samples by taking the total number of\n\t\t\t * bytes processed and divide it by the number of channels and\n\t\t\t * bits per sample.\n\t\t\t */\n\t\t\tsamples = totalbytes - dma_diff;\n\t\t\tsamples -= (audio->NumSkipped * config->HMIBufSize);\n\t\t\tsamples /= (audio->Channels * (audio->BitsPerSample >> 3));\n\n\t\t\t#endif\t//VQADIRECT_SOUND\n\n\t\t\t/* The elapsed ticks is calculated by the number of samples\n\t\t\t * processed times the tick resolution per second divided by the\n\t\t\t * sample rate.\n\t\t\t */\n\t\t\tticks = (long)((samples * VQA_TIMETICKS) / audio->SampleRate);\n\t\t\tticks += TickOffset;\n\t\t\tbreak;\n\n\t\t/* No audio playing, but timer interrupt is going; use VQATickCount */\n\t\tcase VQA_TMETHOD_INT:\n\t\t\tticks = (VQATickCount + TickOffset);\n\t\t\tbreak;\n\n\t\t/* No interrupts are going at all; use DOS's time */\n\t\tdefault:\n\t\tcase VQA_TMETHOD_DOS:\n\t\t\t{\n\t\t\tstruct timeb mytime;\n\n\t\t\tftime(&mytime);\n \t\t\tticks = (unsigned long)mytime.time*1000L+(unsigned long)mytime.millitm;\n\t\t\tticks = ((ticks * VQA_TIMETICKS) / 1000L);\n\t\t\tticks += TickOffset;\n\t\t\t}\n\t\t\tbreak;\n\t}\n\t#else\n\t{\n\t// MEG 09.23.95 - Use Windows timer.\n#if( ! USE_WINDOWS_TIME )\n\n\tstruct timeb mytime;\n\n\tftime(&mytime);\n\tticks = (unsigned long)mytime.time*1000L+(unsigned long)mytime.millitm;\n\n#else\n\n\tticks = Get_Game_Time();\n\n#endif\n\n//\tticks = ((ticks * VQA_TIMETICKS) / 1000L);\n\n\t// MEG 09.25.95 - multiply by 3, divide by 50 instead of multiplying by\n\t// 60 and dividing by 1000.  The reason for this is that multiplying by\n\t// 60 causes an overflow pretty quickly if the value from Get_Game_Time\n\t// is high.\n\tticks = ((ticks * 3L) / 50L);\n\n\tticks += TickOffset;\n\t}\n\t#endif\n\n\treturn (ticks);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_TimerMethod - Get timer method being used.\n*\n* SYNOPSIS\n*     Method = VQA_TimerMethod()\n*\n*     long VQA_TimerMethod(void);\n*\n* FUNCTION\n*     Returns the ID of the current timer method being used.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Method - Method used for the timer.\n*\n****************************************************************************/\n\nlong VQA_TimerMethod(void)\n{\n\t#if(VQAAUDIO_ON)\n\treturn (TimerMethod);\n\t#else\n\treturn (VQA_TMETHOD_DOS);\n\t#endif\n}\n\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n"
  },
  {
    "path": "WINVQ/VQA32/BCC32.CFG",
    "content": "-c\n-3\n-d\n-H=c:\\projects\\vqa32\\obj\\headers.sym\n-wpro\n-weas\n-wpre\n-IC:\\PROJECTS\\INCLUDE;C:\\DEV\\BC4\\INCLUDE;C:\\DEV\\TNT\\INCLUDE\n-DPHARLAP_TNT=1\n"
  },
  {
    "path": "WINVQ/VQA32/CAPTION.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library (32 bit protected mode)\n*\n* FILE\n*     caption.c\n*\n* DESCRIPTION\n*     Text caption process/display manager.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 26, 1995\n*\n****************************************************************************/\n\n#include <mem.h>\n#include <malloc.h>\n#include <vqm32\\font.h>\n#include <vqm32\\text.h>\n#include <vqm32\\graphics.h>\n#include <vqm32\\captoken.h>\n#include \"caption.h\"\n\n#if( VQACAPTIONS_ON )\n\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n#define NUM_NODES 3\n\n/* Function prototypes. */\nstatic CaptionNode *AddCaptionNode(CaptionList *list, CaptionText *captext);\nstatic void RemCaptionNode(CaptionList *list, CaptionNode *node);\n\n\n/****************************************************************************\n*\n* NAME\n*     OpenCaptions - Initialize the caption system.\n*\n* SYNOPSIS\n*     OpenCaptions(Captions, Font)\n*\n*     CaptionInfo *OpenCaptions(void *, void *);\n*\n* FUNCTION\n*     Allocate and initialize resources used by the caption system.\n*\n* INPUTS\n*     Captions - Captions to process.\n*     Font     - Font to use to display captions.\n*\n* RESULT\n*     CaptionInfo - Caption information structure.\n*\n* SEE ALSO\n*     CloseCaption\n*\n****************************************************************************/\n\nCaptionInfo *OpenCaptions(void *captions, void *font)\n{\n\tCaptionInfo *cap = NULL;\n\tCaptionNode *node;\n\tFontInfo    *fi;\n\tlong        i;\n\n\t/* Allocate memory for the captioning system. */\n\tcap = (CaptionInfo *)malloc(sizeof(CaptionInfo) + (sizeof(CaptionNode)\n\t\t\t* NUM_NODES));\n\n\tif (cap != NULL) {\n\t\tmemset(cap,0,(sizeof(CaptionInfo) + (sizeof(CaptionNode) * NUM_NODES)));\n\t\tcap->Buffer = captions;\n\t\tcap->Next = (CaptionText *)captions;\n\n\t\t/* Initialize font */\n\t\tfi = (FontInfo *)((char *)font + ((Font *)font)->InfoBlk);\n\t\tcap->Font = font;\n\t\tcap->FontHeight = fi->MaxHeight;\n\t\tcap->FontWidth = fi->MaxWidth;\n\n\t\t/* Initialize list header. */\n\t\tcap->List.Head = (CaptionNode *)&cap->List.Tail;\n\t\tcap->List.Tail = NULL;\n\t\tcap->List.TailPred = (CaptionNode *)&cap->List.Head;\n\n\t\t/* Link nodes. */\n\t\tnode = (CaptionNode *)((char *)cap + sizeof(CaptionInfo));\n\n\t\tfor (i = 0; i < NUM_NODES; i++) {\n\t\t\tnode->Succ = cap->List.Head;\n\t\t\tcap->List.Head = node;\n\t\t\tnode->Pred = (CaptionNode *)&cap->List.Head;\n\t\t\tnode->Succ->Pred = node;\n\n\t\t\t/* Next node. */\n\t\t\tnode = (CaptionNode *)((char *)node + sizeof(CaptionNode));\n\t\t}\n\t}\n\n\treturn (cap);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     CloseCaptions - Shutdown the caption system.\n*\n* SYNOPSIS\n*     CloseCaptions(CaptionInfo)\n*\n*     void CloseCaptions(CaptionInfo *);\n*\n* FUNCTION\n*     Free the resources allocated by the caption system.\n*\n* INPUTS\n*     CaptionInfo - Caption information structure.\n*\n* RESULT\n*     NONE\n*\n* SEE ALSO\n*     OpenCaptions\n*\n****************************************************************************/\n\nvoid CloseCaptions(CaptionInfo *cap)\n{\n\tfree(cap);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DoCaption - Process and display caption text.\n*\n* SYNOPSIS\n*     DoCaption(Captions, Frame)\n*\n*     void DoCaption(CaptionInfo *, unsigned long);\n*\n* FUNCTION\n*     Process the caption events.\n*\n* INPUTS\n*     Captions - Pointer to CaptionInfo structure.\n*     Frame    - Current frame number being processed.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid DoCaptions(CaptionInfo *cap, unsigned long frame)\n{\n\tCaptionText *captext;\n\tCaptionNode *node;\n\tvoid const  *oldfont;\n\tlong        width;\n\tlong        i;\n\n\t/* Initialize variables. */\n\toldfont = Set_Font((char *)cap->Font);\n\n\t/*-------------------------------------------------------------------------\n\t * Process the captions that are on the active queue.\n\t *-----------------------------------------------------------------------*/\n\tnode = cap->List.Head;\n\n\twhile ((node->Succ != NULL) && (node->Flags & CNF_USED)) {\n\t\tcaptext = node->Captext;\n\n\t\t/* Clear the any previous captions that have expired. */\n\t\tif (captext->OffFrame <= frame) {\n\t\t\tFill_Rect(captext->Xpos, captext->Ypos,\n\t\t\t\t\t(captext->Xpos + node->BoundW - 1),\n\t\t\t\t\t(captext->Ypos + node->BoundH - 1), 0);\n\n\t\t\t/* Remove the caption from the active list. */\n\t\t\tnode = node->Pred;\n\t\t\tRemCaptionNode(&cap->List, node->Succ);\n\t\t} else {\n\t\t\tif (captext->CPF != 0) {\n\n\t\t\t\t/* If a NULL terminator is not found then display the next set of\n\t\t\t\t * characters, otherwise remove the node.\n\t\t\t\t */\n\t\t\t\tif (*node->Char != 0) {\n\t\t\t\t\tSet_Font_Palette_Range(&captext->BgPen, 0, 1);\n\n\t\t\t\t\tfor (i = 0; i < captext->CPF; i++) {\n\n\t\t\t\t\t\t/* Check for terminator. */\n\t\t\t\t\t\tif (*node->Char == 0) {\n\t\t\t\t\t\t\tcaptext->CPF = 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t/* Check for newline. */\n\t\t\t\t\t\telse if (*node->Char == 0x0D) {\n\t\t\t\t\t\t\tnode->Char++;\n\t\t\t\t\t\t\tnode->CurX = captext->Xpos;\n\t\t\t\t\t\t\tnode->CurY += cap->FontHeight;\n\t\t\t\t\t\t\tnode->BoundH += cap->FontHeight;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tDraw_Char(*node->Char, node->CurX, node->CurY);\n\t\t\t\t\t\tnode->CurX += Char_Pixel_Width(*node->Char);\n\t\t\t\t\t\tnode->Char++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (captext->Flags & CTF_FLASH) {\n\t\t\t\tif (frame & 4) {\n\t\t\t\t\tFill_Rect(captext->Xpos, captext->Ypos,\n\t\t\t\t\t\t\t(captext->Xpos + node->BoundW - 1),\n\t\t\t\t\t\t\t(captext->Ypos + node->BoundH - 1), 0);\n\t\t\t\t} else {\n\t\t\t \t\tText_Print(captext->Text, captext->Xpos, captext->Ypos,\n\t\t\t\t\t\t\tcaptext->FgPen, captext->BgPen);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Next node. */\n\t\tnode = node->Succ;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * Process any captions that are waiting to be activated.\n\t *-----------------------------------------------------------------------*/\n\tcaptext = cap->Next;\n\n\twhile (captext->OnFrame <= frame) {\n\n\t\twidth = String_Pixel_Width(captext->Text);\n\n\t\tswitch (captext->Flags & CTF_JUSTIFY) {\n\t\t\tcase CTF_RIGHT:\n\t\t\t\tcaptext->Xpos = (319 - width);\n\t\t\t\tbreak;\n\n\t\t\tcase CTF_LEFT:\n\t\t\t\tcaptext->Xpos = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase CTF_CENTER:\n\t\t\t\tcaptext->Xpos = (160 - (width / 2));\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/* Display the text and record its bounding box. */\n\t\tif (captext->CPF == 0) {\n\t \t\ti = Text_Print(captext->Text, captext->Xpos, captext->Ypos,\n\t\t\t\t\tcaptext->FgPen, captext->BgPen);\n\n\t\t\tnode = AddCaptionNode(&cap->List, captext);\n\t\t\tnode->BoundW = width;\n\t\t\tnode->BoundH = (cap->FontHeight * i);\n\t\t} else {\n\t\t\tnode = AddCaptionNode(&cap->List, captext);\n\t\t\tnode->BoundW = width;\n\t\t\tnode->BoundH = cap->FontHeight;\n\t\t}\n\n\t\t/* Next */\n\t\tcap->Next = (CaptionText *)(((char *)captext) + captext->Size);\n\t\tcaptext = cap->Next;\n\t}\n\n\tSet_Font(oldfont);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     AddCaptionNode - Add a caption to the processing list.\n*\n* SYNOPSIS\n*     Node = AddCaptionNode(List, Caption)\n*\n*     CaptionNode *AddCaptionNode(CaptionList *, CaptionText *);\n*\n* FUNCTION\n*     Add a caption the caption processing list.\n*\n* INPUTS\n*     List    - Caption processing list.\n*     Caption - Caption to add to the list.\n*\n* RESULT\n*     Node - Pointer to node, otherwise NULL if error.\n*\n****************************************************************************/\n\nstatic CaptionNode *AddCaptionNode(CaptionList *list, CaptionText *captext)\n{\n\tCaptionNode *node = NULL;\n\n\t/* If this list is not full. */\n\tnode = list->TailPred;\n\n\tif (!(node->Flags & CNF_USED)) {\n\n\t\t/* Remove the node from the tail. */\n\t\tnode->Pred->Succ = node->Succ;\n\t\tlist->TailPred = node->Pred;\n\n\t\tnode->Flags |= CNF_USED;\n\t\tnode->Captext = captext;\n\t\tnode->Char = captext->Text;\n\t\tnode->CurX = captext->Xpos;\n\t\tnode->CurY = captext->Ypos;\n\t\t\n\t\t/* Add the node to the head. */\n\t\tnode->Succ = list->Head;\n\t\tlist->Head = node;\n\t\tnode->Pred = (CaptionNode *)&list->Head;\n\t\tnode->Succ->Pred = node;\n\t}\n\n\treturn (node);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     RemCaptionNode - Remove a caption from the processing list.\n*\n* SYNOPSIS\n*     RemCaptionNode(List, Node)\n*\n*     void RemCaptionNode(CaptionList *, CaptionNode *);\n*\n* FUNCTION\n*     Remove the caption from the processing list. Mark the node as unused\n*     and put it at the tail of the list.\n*\n* INPUTS\n*     List - Caption processing list.\n*     Node - Caption node to remove.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void RemCaptionNode(CaptionList *list, CaptionNode *node)\n{\n\t/* If the nodes successor is null then we are at the tail. */\n\tif (node->Succ != NULL) {\n\n\t\t/* Mark the node as unused. */\n\t\tnode->Flags = 0;\n\n\t\t/* Relink the node to the tail. */\n\t\tnode->Succ->Pred = node->Pred;\n\t\tnode->Pred->Succ = node->Succ;\n\t\tnode->Succ = (CaptionNode *)&list->Tail;\n\t\tnode->Pred = list->TailPred;\n\t\tlist->TailPred->Succ = node;\n\t\tlist->TailPred = node;\n\t}\n}\n\n\n#endif // VQACAPTIONS_ON\n\u001a"
  },
  {
    "path": "WINVQ/VQA32/CAPTION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQACAPTION_H\n#define VQACAPTION_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library (32 bit protected mode)\n*\n* FILE\n*     caption.h\n*\n* DESCRIPTION\n*     Text caption definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 26, 1995\n*\n****************************************************************************/\n\n\n#define VQACAPTIONS_ON\t\t0\n\n/*---------------------------------------------------------------------------\n * STRUCTURES AND RELATED DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* CaptionNode: Node describing a caption to process.\n *\n * Succ    - Pointer to the next node in the list (successor).\n * Pred    - Pointer to the previous node in the list (predecessor).\n * Flags   - Status flags.\n * CapText - Pointer to the CaptionText being processed.\n * Char    - Pointer to current character in the string.\n * CurX    - Current X position.\n * CurY    - Current Y position.\n * BoundW  - Bounding width of text.\n * BoundH  - Bounding height of text.\n */\ntypedef struct _CaptionNode {\n\tstruct _CaptionNode *Succ;\n\tstruct _CaptionNode *Pred;\n\tunsigned short      Flags;\n\tCaptionText         *Captext;\n\tchar                *Char;\n\tunsigned short      CurX;\n\tunsigned short      CurY;\n\tunsigned short      BoundW;\n\tunsigned short      BoundH;\n} CaptionNode;\n\n/* CaptionNode flag definitions. */\n#define CNB_USED 0  /* This node is being used. */\n#define CNF_USED (1<<CNB_USED)\n\n\n/* CaptionList: Double linked list of outstanding captions to process.\n *\n * Head     - Pointer to the first node in the list.\n * Tail     - Always NULL\n * TailPred - Pointer to the last node in the list.\n */\ntypedef struct _CaptionList {\n\tCaptionNode *Head;\n\tCaptionNode *Tail;\n\tCaptionNode *TailPred;\n} CaptionList;\n\n\n/* CaptionInfo:\n *\n * Next   - Pointer to the next caption to be processed.\n * List   - List of pending captions to process.\n * Font   - Font to use for this caption.\n * BoundX - X position of bounding box.\n * BoundY - Y position of bounding box.\n * BoundW - Width of bounding box.\n * BoundH - Height of bounding box.\n * Buffer - Caption chunk buffer.\n */\ntypedef struct _CaptionInfo {\n\tCaptionText    *Next;\n\tCaptionList    List;\n\tvoid           *Font;\n\tchar           FontHeight;\n\tchar           FontWidth;\n\tvoid           *Buffer;\n} CaptionInfo;\n\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\nCaptionInfo *OpenCaptions(void *captions, void *font);\nvoid CloseCaptions(CaptionInfo *cap);\nvoid DoCaptions(CaptionInfo *cap, unsigned long frame);\n\n#endif /* VQACAPTION_H */\n\n\u001a"
  },
  {
    "path": "WINVQ/VQA32/CONFIG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     config.c\n*\n* DESCRIPTION\n*     Player configuration routines.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 10, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_INIConfig     - Initialize VQAConfig structure with INI settings.\n*     VQA_DefaultConfig - Initialize VQAConfig structure with defaults.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n/* Default configuration structure. */\nstatic VQAConfig _defaultconfig = {\n\n\t/* DrawerCallback: This is a function that is called for every frame\n\t * in the movie.\n\t */\n\tNULL,\n\n\t/* EventHandler: This is a function that is called for every event that\n\t * the client requested to be notified about.\n\t */\n\tNULL,\n\n\t/* NotifyFlags: Flags representing the events the client wishes to be\n\t * notified about during playback.\n\t */\n\tNULL,\n\n\t/* Vmode: Video mode to use. */\n\tMCGA,\n\n\t/* VBIBit: Vertical blank bit polarity. */\n\t-1,\n\n\t/* ImageBuf: Pointer to image buffer to draw into. */\n\tNULL,\n\n\t/* ImageWidth, ImageHeight: Width and height dimensions of image buffer.\n\t * A width and height value of -1 tells the player to consider the image\n\t * buffer as having the same dimensions as the frames in the movie.\n\t */\n\t320, 200, /* Image width and height */\n\n\t/* X1, Y1: These are the coordinates to put the movies frame in the image\n\t * buffer. Values of -1 tell the drawer to center the frames in the buffer.\n\t */\n\t-1, -1,\n\n\t/* FrameRate: The rate to load the frames at. A value of -1 tells the\n\t * player to use the framerate of the movie.\n\t */\n\t-1,\n\n\t/* DrawRate: The rate to draw the frames at. A value of -1 tells the\n\t * player to use the framerate of the movie. A value of 0 tells the player\n\t * to use a fixed rate based on the frame size.\n\t */\n\t-1,\n\n\t/* TimerMethod: Timer method to use for playback. */\n\t-1,\n\n\t/* DrawFlags: Various drawing related flags. */\n\t0,\n\n\t/* OptionFlags: Various player options. */\n\tVQAOPTF_AUDIO,\n\n\t/* NumFrameBufs: The number of frame buffers to allocate/use. */\n\t6,\n\n\t/* NumCBBufs: The number of codebook buffers to allocate/use. */\n\t3,\n\n#if (VQADIRECT_SOUND)\n\t/* -----------------12/15/95 10:40AM-----------------\n\t * SoundObject - ptr to games direct sound object. Null if VQ should create\n\t * --------------------------------------------------*/\n\tNULL,\n\n\t/* -----------------12/15/95 10:41AM-----------------\n\t * PrimaryBufferPtr - ptr to games primary sound buffer. Null if VQ should create\n\t * --------------------------------------------------*/\n\tNULL,\n#endif\t//(VQADIRECT_SOUND)\n\n\t/* VocFile: Filename of audio track override. A value of 0 tells the\n\t * player not to override the movies audio track.\n\t */\n\tNULL,\n\n\t/* AudioBuf: Audio buffer to use. A value of 0 tells the player that\n\t * it has to allocate a buffer itself.\n\t */\n\tNULL,\n\n\t/* AudioBufSize: Size of audio buffer to use/allocate. A value of -1\n\t * tells the player to compute the buffer size from the audio\n\t * information in the movie.\n\t */\n\t-1,\n\n\t/* AudioRate: Audio playback rate in samples per second. A value of -1\n\t * tells the player to use the audio rate of the movie.\n\t */\n\t-1,\n\n\t/* Volume: Volume level to playback audio track. */\n\t0x00FF,\n\n\t/* HMIBufSize: Size of HMIs internal buffer. */\n#if (VQADIRECT_SOUND)\n\t8192L,\n#else\n\t2048L,\n#endif\n\t/* DigiHandle: Handle to an initialized HMI sound driver. A value of -1\n\t * tells the player it must initialize the HMI sound driver itself.\n\t */\n\t-1,\n\n\t/* DigiCard: HMI ID of audio card to use. A value of 0 tells the player\n\t * not to use any card. A value of -1 tells the player to autodetect the\n\t * card in the system.\n\t */\n\t-1,\n\n\t/* DigiPort: Port address of the sound card. A value of -1 tells the player\n\t * to autodetect this address.\n\t */\n\t-1,\n\n\t/* DigiIRQ: Interrupt number of sound card. A value of -1 tells the player\n\t * to autodetect the interrupt used by the card.\n\t */\n\t-1,\n\n\t/* DigiDMA: DMA channel of the sound card. A value of -1 tells the player\n\t * to autodetect the channel used by the card.\n \t */\n\t-1,\n\n\t/* Language: Prefered language. */\n\t0,\n\n\t/* CaptionFont: Caption text font. */\n\tNULL,\n\n\t/* EVAFont: EVA text font. */\n\tNULL,\n\n};\n\n/* Supported video modes. */\n#if(VQAVIDEO_ON)\nenum VMTAGS {\n\tVMTAG_NONE = 0,\n\n\t#if(VQAMCGA_ON)\n\tVMTAG_MCGA,\n\tVMTAG_MCGA_BUF,\n\t#endif\n\n\t#if(VQAXMODE_ON)\n\tVMTAG_XMODE320X200,\n\tVMTAG_XMODE320X200_BUF,\n\tVMTAG_XMODE320X200_VRAM,\n\tVMTAG_XMODE320X240,\n\tVMTAG_XMODE320X240_BUF,\n\tVMTAG_XMODE320X240_VRAM,\n\t#endif\n\n\t#if(VQAVESA_ON)\n\tVMTAG_VESA640X480_BUF,\n\tVMTAG_VESA640X480_X2,\n\tVMTAG_VESA320X200,\n\tVMTAG_VESA320X200_BUF,\n\t#endif\n};\n\ntypedef struct _VideoModeTag {\n\tchar const *token;\n\tlong       id;\n} VideoModeTag;\n\nVideoModeTag VideoModeTags[] = {\n\t{\"NONE\",VMTAG_NONE},\n\n\t#if(VQAMCGA_ON)\n\t{\"MCGA\",    VMTAG_MCGA},\n\t{\"MCGA_BUF\",VMTAG_MCGA_BUF},\n\t#endif /* VQAMCGA_ON */\n\n\t#if(VQAXMODE_ON)\n\t{\"XMODE_320X200\",     VMTAG_XMODE320X200},\n\t{\"XMODE_320X200_BUF\", VMTAG_XMODE320X200_BUF},\n\t{\"XMODE_320X200_VRAM\",VMTAG_XMODE320X200_VRAM},\n\t{\"XMODE_320X240\",     VMTAG_XMODE320X240},\n\t{\"XMODE_320X240_BUF\", VMTAG_XMODE320X240_BUF},\n\t{\"XMODE_320X240_VRAM\",VMTAG_XMODE320X240_VRAM},\n\t#endif /* VQAXMODE_ON */\n\n\t#if(VQAVESA_ON)\n\t{\"VESA_640X480_BUF\",VMTAG_VESA640X480_BUF},\n\t{\"VESA_640X480_X2\", VMTAG_VESA640X480_X2},\n\t{\"VESA_320X200\",    VMTAG_VESA320X200},\n\t{\"VESA_320X200_BUF\",VMTAG_VESA320X200_BUF},\n\t#endif /* VQAVESA_ON */\n\n\t{NULL, NULL}\n};\n#endif /* VQAVIDEO_ON */\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_INIConfig - Initialize VQAConfig structure with INI settings.\n*\n* SYNOPSIS\n*     VQA_INIConfig(Config)\n*\n*     void VQA_INIConfig(VQAConfig *);\n*\n* FUNCTION\n*     Initializes the configuration structure from the player INI file.\n*\n* INPUTS\n*     Config - Pointer to VQAConfig structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_INIConfig(VQAConfig *config)\n{\n\tchar *ininame;\n\tchar buf[80];\n\tlong i;\n\n\t/* Set all Config entries to 0. */\n\tmemset(config, 0, sizeof(VQAConfig));\n\n\t/* Retrieve player INI filename from an enviroment variable if\n\t * it is provided.\n\t */\n\tif ((ininame = getenv(\"VQACFG\")) == NULL) {\n\t\tininame = \"PLAYER.INI\";\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * VIDEO MODE AND DRAW FLAGS\n\t *-----------------------------------------------------------------------*/\n\t#if(VQAVIDEO_ON)\n\t/* Get video mode from INI */\n\tGetINIString(\"Player\", \"PlayerMode\", \"MCGA\", buf, 80, ininame);\n\n\t/* Search supported modes for a match. */\n\ti = 0;\n\n\twhile (VideoModeTags[i].token != NULL) {\n\t\tif (stricmp(buf, VideoModeTags[i].token) == 0) {\n\t\t\tbreak;\n\t\t}\n\t\ti++;\n\t}\n\n\t/* Setup for requested mode */\n\tswitch (VideoModeTags[i].id) {\n\n\t\t/* MCGA direct */\n\t\t#if(VQAMONO_ON)\n\t\tcase VMTAG_MCGA:\n\t\t\tconfig->Vmode = MCGA;\n\t\t\tbreak;\n\n\t\t/* MCGA buffered */\n\t\tcase VMTAG_MCGA_BUF:\n\t\t\tconfig->Vmode = MCGA;\n\t\t\tconfig->DrawFlags |= VQACFGF_BUFFER;\n\t\t\tbreak;\n\t\t#endif /* VQAMCGA_ON */\n\n\t\t/* XMODE direct (320x200) */\n\t\t#if(VQAXMODE_ON)\n\t\tcase VMTAG_XMODE320X200:\n\t\t\tconfig->Vmode = XMODE_320X200;\n\t\t\tbreak;\n\n\t\t/* XMODE buffered (320x200) */\n\t\tcase VMTAG_XMODE320X200_BUF:\n\t\t\tconfig->Vmode = XMODE_320X200;\n\t\t\tconfig->DrawFlags |= VQACFGF_BUFFER;\n\t\t\tbreak;\n\n\t\t/* XMODE VRAM codebook (320x200) */\n\t\tcase VMTAG_XMODE320X200_VRAM:\n\t\t\tconfig->Vmode = XMODE_320X200;\n\t\t\tconfig->DrawFlags |= VQACFGF_VRAMCB;\n\t\t\tbreak;\n\n\t\t/* XMODE direct (320x240) */\n\t\tcase VMTAG_XMODE320X240:\n\t\t\tconfig->Vmode = XMODE_320X240;\n\t\t\tbreak;\n\n\t\t/* XMODE buffered (320x240) */\n\t\tcase VMTAG_XMODE320X240_BUF:\n\t\t\tconfig->Vmode = XMODE_320X240;\n\t\t\tconfig->DrawFlags |= VQACFGF_BUFFER;\n\t\t\tbreak;\n\n\t\t/* XMODE VRAM codebook (320x240) */\n\t\tcase VMTAG_XMODE320X240_VRAM:\n\t\t\tconfig->Vmode = XMODE_320X240;\n\t\t\tconfig->DrawFlags |= VQACFGF_VRAMCB;\n\t\t\tbreak;\n\t\t#endif /* VQAXMODE_ON */\n\n\t\t/* VESA buffered (640x480_256) */\n\t\t#if(VQAVESA_ON)\n\t\tcase VMTAG_VESA640X480_BUF:\n\t\t\tconfig->Vmode = VESA_640X480_256;\n\t\t\tconfig->DrawFlags |= VQACFGF_BUFFER;\n\t\t\tbreak;\n\n\t\t/* VESA buffered scaled (640x480_256) */\n\t\tcase VMTAG_VESA640X480_X2:\n\t\t\tconfig->Vmode = VESA_640X480_256;\n\t\t\tconfig->DrawFlags |= (VQACFGF_BUFFER|VQACFGF_SCALEX2);\n\t\t\tbreak;\n\n\t\t/* VESA direct (320x200_32k) */\n\t\tcase VMTAG_VESA320X200:\n\t\t\tconfig->Vmode = VESA_320X200_32K_1;\n\t\t\tbreak;\n\n\t\t/* VESA buffered (320x200_32k) */\n\t\tcase VMTAG_VESA320X200_BUF:\n\t\t\tconfig->Vmode = VESA_320X200_32K_1;\n\t\t\tconfig->DrawFlags |= VQACFGF_BUFFER;\n\t\t\tbreak;\n\t\t#endif /* VQAVESA_ON */\n\n\t\t/* Default to MCGA direct */\n\t\tVMTAG_NONE:\n\t\tdefault:\n\t\t\tconfig->Vmode = MCGA;\n\t\t\tbreak;\n\t}\n\t#endif /* VQAVIDEO_ON */\n\n\t/* Get framerate and drawrate. */\n\tGetINIString(\"Player\", \"FrameRate\", \"-1\", buf, 80, ininame);\n\tconfig->FrameRate = atoi(buf);\n\n\tGetINIString(\"Player\", \"DrawRate\", \"Variable\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"Variable\")) {\n\t\tconfig->DrawRate = -1;\n\t} else {\n\t\tconfig->DrawRate = 0;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * AUDIO SETTINGS\n\t *-----------------------------------------------------------------------*/\n\tGetINIString(\"Player\", \"AudioRate\", \"-1\", buf, 80, ininame);\n\tconfig->AudioRate = atoi(buf);\n\n\t/* OptionFlags */\n\tGetINIString(\"Player\", \"SoundEnabled\", \"True\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"True\") || !stricmp(buf, \"1\")) {\n\t\tconfig->OptionFlags |= VQAOPTF_AUDIO;\n\t} else {\n\t\tconfig->OptionFlags &= (~VQAOPTF_AUDIO);\n\t}\n\n\t/* Default audio settings. */\n\tconfig->AudioBufSize = 32768U;\n\tconfig->HMIBufSize = 2048;\n\tconfig->DigiHandle = -1;\n\tconfig->Volume = 0x00FF;\n\tconfig->DigiCard = 0xFFFF;\n\tconfig->DigiPort = -1;\n\tconfig->DigiIRQ = -1;\n\tconfig->DigiDMA = -1;\n\n\t/* Configure sound hardware */\n\tGetINIString(\"Player\", \"Port\", \"-1\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"-1\")) {\n\t\tconfig->DigiPort = -1;\n\t} else {\n\t\tsscanf(buf, \"%x\", &config->DigiPort);\n\t}\n\n\tGetINIString(\"Player\", \"IRQ\", \"-1\", buf, 80, ininame);\n\tconfig->DigiIRQ = atoi(buf);\n\tGetINIString(\"Player\", \"DMA\", \"-1\", buf, 80, ininame);\n\tconfig->DigiDMA = atoi(buf);\n\n\t/*-------------------------------------------------------------------------\n\t * GENERAL OPTIONS\n\t *-----------------------------------------------------------------------*/\n\n\t/* Enable/Disable single stepping */\n\tGetINIString(\"Player\", \"SingleStep\", \"False\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"True\") || !stricmp(buf, \"1\")) {\n\t\tconfig->OptionFlags |= VQAOPTF_STEP;\n\t\tconfig->DrawFlags |= VQACFGF_NOSKIP;\n\t} else {\n\t\tconfig->OptionFlags &= (~VQAOPTF_STEP);\n\t}\n\n\t/* Enable/Disable Slowpalette */\n\tGetINIString(\"Player\", \"SlowPalette\", \"False\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"True\") || !stricmp(buf, \"1\")) {\n\t\tconfig->OptionFlags |= VQAOPTF_SLOWPAL;\n\t} else {\n\t\tconfig->OptionFlags &= (~VQAOPTF_SLOWPAL);\n\t}\n\n\t/* Enable/Disable monochrome display */\n\tGetINIString(\"Player\", \"MonoOutput\", \"False\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"True\") || !stricmp(buf, \"1\")) {\n\t\tconfig->OptionFlags |= VQAOPTF_MONO;\n\t} else {\n\t\tconfig->OptionFlags &= (~VQAOPTF_MONO);\n\t}\n\n\t/* Frame and codebook buffers */\n\tconfig->NumFrameBufs = 6;\n\tconfig->NumCBBufs = 3;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_DefaultConfig - Initialize VQAConfig structure with defaults.\n*\n* SYNOPSIS\n*     VQA_DefaultConfig(Config);\n*\n*     void VQA_DefaultConfig(VQAConfig *);\n*\n* FUNCTION\n*     Initialize configuration with default settings.\n*\n* INPUTS\n*     Config - Pointer to VQA configuration structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_DefaultConfig(VQAConfig *config)\n{\n\tmemcpy(config, &_defaultconfig, sizeof(VQAConfig));\n}\n\n\n\n\n"
  },
  {
    "path": "WINVQ/VQA32/DRAWER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQAPlay32 library. (32-Bit protected mode)\n*\n* FILE\n*     drawer.c\n*\n* DESCRIPTION\n*     Frame drawing and page flip control.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     June 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_Configure_Drawer - Configure the drawer routines.\n*\n* PRIVATE\n*     Select_Frame             - Selects frame to draw and preforms frame\n*                                skip.\n*     Prepare_Frame            - Process/Decompress frame information.\n*     DrawFrame_Xmode          - Draws a frame directly to Xmode screen.\n*     DrawFrame_XmodeBuf       - Draws a frame in Xmode format to a buffer.\n*     DrawFrame_XmodeVRAM      - Draws a frame in Xmode with resident\n*                                Codebook.\n*     PageFlip_Xmode           - Page flip Xmode display.\n*     DrawFrame_MCGA           - Draws a frame directly to MCGA screen.\n*     PageFlip_MCGA            - Page flip MCGA display.\n*     DrawFrame_MCGABuf        - Draws a frame in MCGA format to a buffer.\n*     PageFlip_MCGABuf         - Page flip a buffered MCGA display.\n*     DrawFrame_VESA640        - Draws a frame in VESA640 format.\n*     DrawFrame_VESA320_32K    - Draws a frame to VESA320_32K screen.\n*     DrawFrame_VESA320_32KBuf - Draws a frame in VESA320_32K format to a\n*                                buffer.\n*     PageFlip_VESA            - Page flip VESA display.\n*     DrawFrame_Buffer         - Draw a frame to a buffer.\n*     PageFlip_Nop             - Do nothing page flip.\n*     UnVQ_Nop                 - Do nothing UnVQ.\n*     Mask_Rect                - Sets non-drawable rectangle in image.\n*     Mask_Pointers            - Mask vector pointer that are in the mask\n*                                rectangle.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <malloc.h>\n#include <conio.h>\n#include <dos.h>\n#include <mem.h>\n#include \"vq.h\"\n#include \"unvq.h\"\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n#include \"caption.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\nstatic long Select_Frame(VQAHandleP *vqap);\nstatic void Prepare_Frame(VQAData *vqabuf);\n\n#if(VQAMCGA_ON)\nstatic long DrawFrame_MCGABuf(VQAHandle *vqa);\nstatic long PageFlip_MCGABuf(VQAHandle *vqa);\nstatic long DrawFrame_MCGA(VQAHandle *vqa);\nstatic long PageFlip_MCGA(VQAHandle *vqa);\n#endif /* VQAMCGA_ON */\n\n#if(VQAXMODE_ON)\nstatic long DrawFrame_XmodeBuf(VQAHandle *vqa);\nstatic long DrawFrame_Xmode(VQAHandle *vqa);\nstatic long DrawFrame_XmodeVRAM(VQAHandle *vqa);\nstatic void PageFlip_Xmode(VQAHandle *vqabuf);\n#endif /* VQAXMODE_ON */\n\n#if(VQAVESA_ON)\nstatic long DrawFrame_VESA640(VQAHandle *vqa);\nstatic long DrawFrame_VESA320_32K(VQAHandle *vqa);\nstatic long DrawFrame_VESA320_32KBuf(VQAHandle *vqa);\nstatic void PageFlip_VESA(VQAHandle *vqabuf);\n#endif /* VQAVESA_ON */\n\nstatic long DrawFrame_Buffer(VQAHandle *vqa);\nstatic long PageFlip_Nop(VQAHandle *vqa);\n\n#ifndef PHARLAP_TNT\nstatic void __cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n#else\nstatic void __cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n#endif\n\n#if(0)\nstatic void Mask_Rect(VQAHandle *vqa, unsigned long x1, unsigned long y1,\n\t\tunsigned long x2, unsigned long y2);\nstatic void Mask_Pointers(VQAData *vqabuf);\n#endif\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_GetPalette - Get the palette used in the movie.\n*\n* SYNOPSIS\n*     Palette = VQA_GetPalette(VQA)\n*\n*     char *VQA_GetPalette(VQAHandle *);\n*\n* FUNCTION\n*     Retrieve the address of the current palette used in the movie. If there\n*     isn't a palette available then a NULL value will be returned.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle to get palette for.\n*\n* RESULT\n*     Palette - Pointer to palette or NULL if no palette available.\n*\n****************************************************************************/\n\nunsigned char *VQA_GetPalette(VQAHandle *vqa)\n{\n\tVQADrawer *drawer;\n\tunsigned char *palette = NULL;\n\n\t/* Dereference commonly used data members for quick access. */\n\tdrawer = &((VQAHandleP *)vqa)->VQABuf->Drawer;\n\n\tif (drawer->CurPalSize > 0) {\n\t\tpalette = drawer->Palette_24;\n\t}\n\n\treturn (palette);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_GetPaletteSize - Get the size of the palette used in the movie.\n*\n* SYNOPSIS\n*     PalSize = VQA_GetPaletteSize(VQA)\n*\n*     long VQA_GetPaletteSize(VQAHandle *);\n*\n* FUNCTION\n*     Retrieve the size of the current palette used in the movie. If there\n*     isn't a palette available then a zero size will be returned.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle to get palette for.\n*\n* RESULT\n*     PalSize - Size in bytes of the current palette.\n*\n****************************************************************************/\n\nlong VQA_GetPaletteSize(VQAHandle *vqa)\n{\n\tVQADrawer *drawer;\n\n\t/* Dereference commonly used data members for quick access. */\n\tdrawer = &((VQAHandleP *)vqa)->VQABuf->Drawer;\n\n\treturn (drawer->CurPalSize);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Set_DrawBuffer - Set the buffer to draw the images to.\n*\n* SYNOPSIS\n*     VQA_Set_DrawBuffer(VQA, Buffer, Width, Height, XPos, YPos)\n*\n*     void VQA_Set_DrawBuffer(VQAHandle *, unsigned char *,\n*                             unsigned long, unsigned long, unsigned long,\n*                             unsigned long);\n*\n* FUNCTION\n*     Set the draw buffer to the buffer provided by the client.\n*\n* INPUTS\n*     VQA    - Pointer to VQAHandle to set buffer for.\n*     Buffer - Pointer to new image buffer.\n*     Width  - Width of the buffer in pixels.\n*     Height - Height of the buffer in pixels.\n*     XPos   - X pixel position in buffer to draw image.\n*     YPos   - Y pixel position in buffer to draw image.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Set_DrawBuffer(VQAHandle *vqa, unsigned char *buffer,\n\t\tunsigned long width, unsigned long height,\n\t\tlong xpos, long ypos)\n{\n\tVQAHeader *header;\n\tVQADrawer *drawer;\n\tVQAConfig *config;\n\tlong      origin;\n\n\t/* Dereference commonly used data members for quick access. */\n\theader = &((VQAHandleP *)vqa)->Header;\n\tdrawer = &((VQAHandleP *)vqa)->VQABuf->Drawer;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\torigin = (config->DrawFlags & VQACFGF_ORIGIN);\n\n\t/* Set the drawer buffer information. */\n\tdrawer->ImageBuf = buffer;\n\tdrawer->ImageWidth = width;\n\tdrawer->ImageHeight = height;\n\n\t/*-------------------------------------------------------------------------\n\t * SET THE DRAW POSITION OF THE MOVIE.\n\t *\n\t * X1 = -1 -- Center image of the X axis, otherwise use X1 value.\n\t * Y1 = -1 -- Center image of the Y axis, otherwise use Y1 value.\n\t *-----------------------------------------------------------------------*/\n\tif ((xpos == -1) && (ypos == -1)) {\n\n\t\t#if(VQAVIDEO_ON)\n\t\tdrawer->X1 = ((drawer->Display->XRes - header->image_width) / 2);\n\t\tdrawer->Y1 = ((drawer->Display->YRes - header->image_height) / 2);\n\t\t#else  /* VQAVIDEO_ON */\n\t\tdrawer->X1 = ((width - header->ImageWidth) / 2);\n\t\tdrawer->Y1 = ((height - header->ImageHeight) / 2);\n\t\t#endif /* VQAVIDEO_ON */\n\n\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\tdrawer->Y2 = ((drawer->Y1 + header->ImageHeight) - 1);\n\t} else {\n\t\tswitch (origin) {\n\t\t\tdefault:\n\t\t\tcase VQACFGF_TOPLEFT:\n\t\t\t\tdrawer->X1 = xpos;\n\t\t\t\tdrawer->Y1 = ypos;\n\t\t\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\t\t\tdrawer->Y2 = ((drawer->Y1 + header->ImageHeight) - 1);\n\t\t\t\tbreak;\n\n\t\t\tcase VQACFGF_BOTLEFT:\n\t\t\t\tdrawer->X1 = xpos;\n\t\t\t\tdrawer->Y1 = (height - ypos);\n\t\t\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\t\t\tdrawer->Y2 = ((drawer->Y2 - header->ImageHeight) - 1);\n\t\t\t\tbreak;\n\n\t\t\tcase VQACFGF_BOTRIGHT:\n\t\t\t\tdrawer->X1 = (width - xpos);\n\t\t\t\tdrawer->Y1 = (height - ypos);\n\t\t\t\tdrawer->X2 = (drawer->X1 - header->ImageWidth);\n\t\t\t\tdrawer->Y2 = (drawer->Y1 - header->ImageHeight);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/* Pre-compute the draw offset for speed. */\n\tdrawer->ScreenOffset = ((width * drawer->Y1) + drawer->X1);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Configure_Drawer - Configure the drawer routines.\n*\n* SYNOPSIS\n*     VQA_Configure_Drawer(VQA)\n*\n*     void VQA_Configure_Drawer(VQAHandleP *);\n*\n* FUNCTION\n*     Configure the drawing system for the current movie and configuration\n*     options.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Configure_Drawer(VQAHandleP *vqap)\n{\n\tVQAData   *vqabuf;\n\tVQAConfig *config;\n\tVQAHeader *header;\n\tVQADrawer *drawer;\n\tlong      origin;\n\tlong      blkdim;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\theader = &vqap->Header;\n\tconfig = &vqap->Config;\n\torigin = (config->DrawFlags & VQACFGF_ORIGIN);\n\n\t/*-------------------------------------------------------------------------\n\t * SET THE DRAW POSITION OF THE MOVIE.\n\t *\n\t * X1 = -1 -- Center image of the X axis, otherwise use X1 value.\n\t * Y1 = -1 -- Center image of the Y axis, otherwise use Y1 value.\n\t *-----------------------------------------------------------------------*/\n\tif ((config->X1 == -1) && (config->Y1 == -1)) {\n\n\t\t#if(VQAVIDEO_ON)\n\t\tdrawer->X1 = ((drawer->Display->XRes - header->image_width) / 2);\n\t\tdrawer->Y1 = ((drawer->Display->YRes - header->image_height) / 2);\n\t\t#else  /* VQAVIDEO_ON */\n\t\tdrawer->X1 = ((drawer->ImageWidth - header->ImageWidth) / 2);\n\t\tdrawer->Y1 = ((drawer->ImageHeight - header->ImageHeight) / 2);\n\t\t#endif /* VQAVIDEO_ON */\n\n\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\tdrawer->Y2 = ((drawer->Y1 + header->ImageHeight) - 1);\n\t} else {\n\t\tswitch (origin) {\n\t\t\tdefault:\n\t\t\tcase VQACFGF_TOPLEFT:\n\t\t\t\tdrawer->X1 = config->X1;\n\t\t\t\tdrawer->Y1 = config->Y1;\n\t\t\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\t\t\tdrawer->Y2 = ((drawer->Y1 + header->ImageHeight) - 1);\n\t\t\t\tbreak;\n\n\t\t\tcase VQACFGF_BOTLEFT:\n\t\t\t\tdrawer->X1 = config->X1;\n\t\t\t\tdrawer->Y1 = (drawer->ImageHeight - config->Y1);\n\t\t\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\t\t\tdrawer->Y2 = ((drawer->Y2 - header->ImageHeight) - 1);\n\t\t\t\tbreak;\n\n\t\t\tcase VQACFGF_BOTRIGHT:\n\t\t\t\tdrawer->X1 = (drawer->ImageWidth - config->X1);\n\t\t\t\tdrawer->Y1 = (drawer->ImageHeight - config->Y1);\n\t\t\t\tdrawer->X2 = (drawer->X1 - header->ImageWidth);\n\t\t\t\tdrawer->Y2 = (drawer->Y1 - header->ImageHeight);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE UNVQ ROUTINE FOR THE SPECIFIED VIDEO MODE AND BLOCK SIZE.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Pre-compute commonly used values for speed. */\n\tdrawer->BlocksPerRow = header->ImageWidth / header->BlockWidth;\n\tdrawer->NumRows = header->ImageHeight / header->BlockHeight;\n\tdrawer->NumBlocks = drawer->BlocksPerRow * drawer->NumRows;\n\tblkdim = BLOCK_DIM(header->BlockWidth, header->BlockHeight);\n\n\t/* Initialize draw routine vectors to a NOP routine in order to prevent\n\t * a crash.\n\t */\n\tvqabuf->UnVQ = UnVQ_Nop;\n\tvqabuf->Page_Flip = PageFlip_Nop;\n\n\t/* If the client specifies buffering then go ahead an set the unvq\n\t * vector. All of the buffered modes use the same unvq routines.\n\t */\n\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\tswitch (blkdim) {\n\t\t\t#if(VQABLOCK_2X2)\n\t\t\tcase BLOCK_2X2:\n\t\t\t\tvqabuf->UnVQ = UnVQ_2x2;\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\t#if(VQABLOCK_2X3)\n\t\t\tcase BLOCK_2X3:\n\t\t\t\tvqabuf->UnVQ = UnVQ_2x3;\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\t#if(VQABLOCK_4X2)\n\t\t\tcase BLOCK_4X2:\n\t\t\t\tvqabuf->UnVQ = UnVQ_4x2;\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\t#if(VQABLOCK_4X4)\n\t\t\tcase BLOCK_4X4:\n\t\t\t\tvqabuf->UnVQ = UnVQ_4x4;\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n \t\t}\n \t}\n\n\t/* Initialize the draw vectors for the specified video mode. */\n\tswitch (config->Vmode) {\n\n\t\t/* MCGA */\n\t\t#if(VQAMCGA_ON)\n\t\tcase MCGA:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_MCGABuf;\n\t\t\t\tvqabuf->Page_Flip = PageFlip_MCGABuf;\n\t\t\t} else {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_MCGA;\n\t\t\t\tvqabuf->Page_Flip = PageFlip_MCGA;\n\n\t\t\t\t/* MCGA uses the same unvq routines that are used for unvqing\n\t\t\t\t * to a buffer because MCGA mode is just another buffer. However,\n\t\t\t\t * instead of drawing to an allocated RAM buffer we are drawing\n\t\t\t\t * directly to the VRAM video buffer.\n\t\t\t\t */\n\t\t\t\tswitch (blkdim) {\n\t\t\t\t\t#if(VQABLOCK_2X2)\n\t\t\t\t\tcase BLOCK_2X2:\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_2x2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\n\t\t\t\t\t#if(VQABLOCK_2X3)\n\t\t\t\t\tcase BLOCK_2X3:\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_2x3;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\n\t\t\t\t\t#if(VQABLOCK_4X2)\n\t\t\t\t\tcase BLOCK_4X2:\n\t\t\t\t\t\t#if(!VQAWOOFER_ON)\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2;\n\t\t\t\t\t\t#else\n\t\t\t\t\t\tif (config->DrawFlags & VQACFGF_WOOFER) {\n\t\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2_Woofer;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t#endif\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\n\t\t\t\t\t#if(VQABLOCK_4X4)\n\t\t\t\t\tcase BLOCK_4X4:\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x4;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Pre-compute the draw offset for speed. */\n\t\t\tdrawer->ScreenOffset = ((320 * drawer->Y1) + drawer->X1);\n\t\t\tbreak;\n\t\t#endif /* VQAMCGA_ON */\n\n\t\t/* XMODE */\n\t\t#if(VQAXMODE_ON)\n\t\tcase XMODE_320X200:\n\t\tcase XMODE_320X240:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_XmodeBuf;\n\t\t\t\tvqabuf->Page_Flip = PageFlip_Xmode;\n\t\t\t} else {\n\t\t\t\tvqabuf->Page_Flip = PageFlip_Xmode;\n\n\t\t\t\tif (config->DrawFlags & VQACFGF_VRAMCB) {\n\t\t\t\t\tvqabuf->Draw_Frame = DrawFrame_XmodeVRAM;\n\n\t\t\t\t\tswitch (blkdim) {\n\t\t\t\t\t\t#if(VQABLOCK_4X2)\n\t\t\t\t\t\tcase BLOCK_4X2:\n\t\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2_XmodeCB;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t#endif /* VQABLOCK_4X2 */\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tvqabuf->Draw_Frame = DrawFrame_Xmode;\n\n\t\t\t\t\tswitch (blkdim) {\n\t\t\t\t\t\t#if(VQABLOCK_4X2)\n\t\t\t\t\t\tcase BLOCK_4X2:\n\t\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2_Xmode;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t#endif /* VQABLOCK_4X2 */\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Pre-compute the draw offset for speed. */\n\t\t\tdrawer->ScreenOffset = (((320 / 4) * drawer->Y1) + (drawer->X1 / 4));\n\t\t\tbreak;\n\t\t#endif /* VQAXMODE_ON */\n\n\t\t/* VESA */\n\t\t#if(VQAVESA_ON)\n\n\t\t/* Currently this is a buffered mode, but should be optimized for\n\t\t * for screen direct.\n\t\t */\n\t\tcase VESA_640X480_256:\n\t\t\tvqabuf->Draw_Frame = DrawFrame_VESA640;\n\t\t\tvqabuf->Page_Flip = PageFlip_VESA;\n\t\t\tbreak;\n\n\t\tcase VESA_320X200_32K_1:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_VESA320_32KBuf;\n\t\t\t} else {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_VESA320_32K;\n\n\t\t\t\tswitch (blkdim) {\n\t\t\t\t\t#if(VQABLOCK_4X2)\n\t\t\t\t\tcase BLOCK_4X2:\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2_VESA320_32K;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t#endif /* VQAVESA_ON */\n\n\t\t/* Purely buffered (Video refresh is up to the client. */\n\t\tdefault:\n\t\t\tvqabuf->Draw_Frame = DrawFrame_Buffer;\n\n\t\t\t/* Pre-compute the draw offset for speed. */\n\t\t\tdrawer->ScreenOffset = ((drawer->ImageWidth * drawer->Y1)+drawer->X1);\n\t\t\tbreak;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Select_Frame - Selects frame to draw and preforms frame skip.\n*\n* SYNOPSIS\n*     Error = Select_Frame(VQA)\n*\n*     long Select_Frame(VQAHandleP *);\n*\n* FUNCTION\n*     Select a frame to draw. This is were the frame skipping/delay is\n*     performed.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Select_Frame(VQAHandleP *vqap)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAConfig    *config;\n\tVQAFrameNode *curframe;\n\tlong         desiredframe;\n\t// MEG 11.29.95 - changed from long to unsigned long\n\tunsigned long curtime;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tconfig = &vqap->Config;\n\tvqabuf = vqap->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = drawer->CurFrame;\n\n\t/* Make sure the current frame is drawable. If the frame is not ready\n\t * then we must wait for the loader to catch up.\n\t */\n\tif ((curframe->Flags & VQAFRMF_LOADED) == 0) {\n\t\tdrawer->WaitsOnLoader++;\n\t\treturn (VQAERR_NOBUFFER);\n\t}\n\n\t/* If single stepping then return with the next frame.*/\n\tif (config->OptionFlags & VQAOPTF_STEP) {\n\t\tdrawer->LastFrame = curframe->FrameNum;\n\t\treturn (0);\n\t}\n\n\t/* Find the frame # we should play (rounded to nearest frame): */\n\tcurtime = VQA_GetTime(vqap);\n//\tdesiredframe = ((curtime * config->FrameRate) / VQA_TIMETICKS);\n\t// MEG MOD 06.22.95 - Should look for the desired frame to draw, not load,\n\t// right?\n\tdesiredframe = ((curtime * config->DrawRate) / VQA_TIMETICKS);\n\n\t#if(VQAMONO_ON)\n\tdrawer->DesiredFrame = desiredframe;\n\t#endif\n\n\t/* Handle the cases where the player is going so fast that it's not time\n\t * to draw this frame yet.\n\t *\n\t * - If the Drawer is using a slower frame rate than the Loader, use a\n\t *   delta-time-based wait; otherwise, use the frame number as the wait.\n\t */\n\tif (config->DrawRate != config->FrameRate) {\n\t\tif (curtime - drawer->LastTime < (VQA_TIMETICKS / config->DrawRate)) {\n\t\t\treturn (VQAERR_NOT_TIME);\n\t\t}\n\t} else {\n\t\tif (curframe->FrameNum > desiredframe) {\n\t\t\treturn (VQAERR_NOT_TIME);\n\t\t}\n\t}\n\n\t/* Make sure we draw at least 5 frames per second */\n\tif ((curframe->FrameNum - drawer->LastFrame) >= (config->FrameRate / 5)) {\n\t\tdrawer->LastFrame = curframe->FrameNum;\n\t\treturn (0);\n\t}\n\n\t/* If frame skipping is disabled then draw every frame. */\n\tif (config->DrawFlags & VQACFGF_NOSKIP) {\n\t\tdrawer->LastFrame = curframe->FrameNum;\n\t\treturn (0);\n\t}\n\n\t/* Handle the case where the player is going too slow, so we have to skip\n\t * some frames:\n\t *\n\t * - If this is a Key Frame, draw it\n\t * - If this frame's # is less than what we're supposed to draw, skip it\n\t *   (Because the 1st 'desiredframe' will be 0, FrameNum MUST be typecast\n\t *   to signed WORD for the comparison; otherwise, the comparison uses\n\t *   UWORDs, and the first frame is always skipped.)\n\t * - If this is a palette-set frame, set the palette before skipping it\n\t * - Loop until we get the frame we need, or there's no frames available\n\t */\n\twhile (1) {\n\n\t\t/* No frame available; return */\n\t\tif ((curframe->Flags & VQAFRMF_LOADED) == 0) {\n\t\t\treturn (VQAERR_NOBUFFER);\n\t\t}\n\n\t\t/* Force drawing of a Key Frame */\n\t\tif (curframe->Flags & VQAFRMF_KEY) {\n\t\t\tbreak;\n\t\t}\n\n\t\t/* Skip the frame */\n\t\tif (curframe->FrameNum < desiredframe) {\n\n\t\t\t/* Handle a palette in a skipped frame:\n\t\t\t *\n\t\t\t * - Stash the palette in Drawer.Palette_24\n\t\t\t * - Set the Drawer.Flags VQADRWF_SETPAL bit, to tell the page-flip\n\t\t\t *   routines that this palette must be set\n\t\t\t */\n\t\t\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\n\t\t\t\t/* Un-LCW if needed */\n\t\t\t\tif (curframe->Flags & VQAFRMF_PALCOMP) {\n\t\t\t\t\tcurframe->PaletteSize = LCW_Uncompress((char *)curframe->Palette\n\t\t\t\t\t\t\t+ curframe->PalOffset, (char *)curframe->Palette,\n\t\t\t\t\t\t\tvqabuf->Max_Pal_Size);\n\n\t\t\t\t\tcurframe->Flags &= ~VQAFRMF_PALCOMP;\n\t\t\t\t}\n\n\t\t\t\t/* Stash the palette */\n\t\t\t\tmemcpy(drawer->Palette_24, curframe->Palette, curframe->PaletteSize);\n\t\t\t\tdrawer->CurPalSize = curframe->PaletteSize;\n\t\t\t\tdrawer->Flags |= VQADRWF_SETPAL;\n\t\t\t}\n\n\t\t\t/* Invoke callback with NULL screen ptr */\n\t\t\tif (config->DrawerCallback != NULL) {\n\t\t\t\tif ((config->DrawerCallback(NULL, curframe->FrameNum)) != 0) {\n\t\t\t\t\treturn (VQAERR_EOF);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Skip the frame */\n\t\t\tcurframe->Flags = 0L;\n\t\t\tcurframe = curframe->Next;\n\t\t\tdrawer->CurFrame = curframe;\n\t\t\tdrawer->NumSkipped++;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tdrawer->LastFrame = curframe->FrameNum;\n\tdrawer->LastTime = curtime;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Prepare_Frame - Process/Decompress frame information.\n*\n* SYNOPSIS\n*     Prepare_Frame(VQAData)\n*\n*     void Prepare_Frame(VQAData *);\n*\n* FUNCTION\n*     Decompress and preprocess the various frame elements (codebook,\n*     pointers, palette, etc...)\n*\n* INPUTS\n*     VQAData - Pointer to VQAData structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Prepare_Frame(VQAData *vqabuf)\n{\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tVQACBNode    *codebook;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = drawer->CurFrame;\n\tcodebook = curframe->Codebook;\n\n\t/* Decompress the codebook, if needed */\n\tif (codebook->Flags & VQACBF_CBCOMP) {\n\n\t\t/* Decompress the codebook. */\n\t\tLCW_Uncompress((char *)codebook->Buffer + codebook->CBOffset,\n\t\t\t\t(char *)codebook->Buffer, vqabuf->Max_CB_Size);\n\n\t\t/* Mark as uncompressed for the next time we use it */\n\t\tcodebook->Flags &= (~VQACBF_CBCOMP);\n\t}\n\n\t/* Decompress the palette, if needed */\n\tif (curframe->Flags & VQAFRMF_PALCOMP) {\n\t\tcurframe->PaletteSize = LCW_Uncompress((char *)curframe->Palette +\n\t\t\t\tcurframe->PalOffset,(char *)curframe->Palette,vqabuf->Max_Pal_Size);\n\n\t\t/* Mark as uncompressed */\n\t\tcurframe->Flags &= ~VQAFRMF_PALCOMP;\n\t}\n\n\t/* Decompress the pointer data, if needed */\n\tif (curframe->Flags & VQAFRMF_PTRCOMP) {\n\t\tLCW_Uncompress((char *)curframe->Pointers + curframe->PtrOffset,\n\t\t\t\t(char *)curframe->Pointers, vqabuf->Max_Ptr_Size);\n\n\t\t/* Mark as uncompressed */\n\t\tcurframe->Flags &= ~VQAFRMF_PTRCOMP;\n\t}\n\n\t/* Mask the pointers */\n\t#if(0)\n\tMask_Pointers(vqabuf);\n\t#endif\n}\n\n\n#if(VQAXMODE_ON)\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_Xmode - Draws a frame in Xmode format (Screen direct).\n*\n* SYNOPSIS\n*     Error = DrawFrame_Xmode(VQA)\n*\n*     long DrawFrame_Xmode(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Skip frames\n*       - UnLCW frame\n*       - Un-VQ into video RAM\n*       - Wait on Update_Enabled\n*       - Set the Flipper's CurFrame\n*       - Set Update_Enabled\n*       - Go to next frame\n*       - User_Update:\n*         Flip X-Page\n*         Set Palette from Flipper.CurFrame\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the correct spot on\n*     the Xmode screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_Xmode(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *scrn;\n\tlong          rc;\n\n\t/* Dereference data members for quick access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n \t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* Dereference current frame for quicker access */\n\t\tcurframe = drawer->CurFrame;\n\n\t\t/* Un-VQ the image */\n\t\tscrn = GetXHidPage();\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tscrn + drawer->ScreenOffset, drawer->BlocksPerRow,\n\t\t\t\tdrawer->NumRows, 320);\n\n\t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tif ((config->DrawerCallback(scrn, curframe->FrameNum)) != 0) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access */\n\tcurframe = drawer->CurFrame;\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_XmodeBuf - Draws a frame in Xmode format to a buffer.\n*\n* SYNOPSIS\n*     Error = DrawFrame_XmodeBuf(VQA)\n*\n*     long DrawFrame_XmodeBuf(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Skip frames\n*       - UnLCW frame\n*       - Un-VQ into ImageBuf\n*       - Copy ImageBuf to video RAM\n*       - Wait on Update_Enabled\n*       - Set the Flipper's CurFrame\n*       - Set Update_Enabled\n*       - Go to next frame\n*\t      - User_Update:\n*         Flip X-Page\n*         Set Palette from Flipper.CurFrame\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the upper-left\n*     corner of ImageBuf, then copying ImageBuf into the correct part of the\n*     Xmode screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_XmodeBuf(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAHeader     *header;\n\tVQAConfig     *config;\n\tunsigned char *scrn;\n\tlong          rc;\n\n\t/* Dereference data members for quicker access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\theader = &((VQAHandleP *)vqa)->Header;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* Dereference current frame for quicker access. */\n\t\tcurframe = drawer->CurFrame;\n\n\t\t/* Un-VQ the image */\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tdrawer->ImageBuf, drawer->BlocksPerRow, drawer->NumRows,\n\t\t\t\theader->ImageWidth);\n\n\t\t/* Copy the buffer */\n\t\tscrn = GetXHidPage();\n\n\t\tif ((header->ImageWidth < 320) || (header->ImageHeight < 200)) {\n\t\t\tXmode_Blit(drawer->ImageBuf, scrn + drawer->ScreenOffset,\n\t\t\t\t\theader->ImageWidth, header->ImageHeight);\n\t\t} else {\n\t\t\tXmode_BufferCopy_320x200(drawer->ImageBuf,scrn + drawer->ScreenOffset);\n\t\t}\n\n\t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tif ((config->DrawerCallback(scrn, curframe->FrameNum)) != 0) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_XmodeVRAM - Draws a frame in Xmode with resident Codebook.\n*\n* SYNOPSIS\n*     Error = DrawFrame_XmodeVRAM(VQA)\n*\n*     long DrawFrame_XmodeVRAM(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Download Codebook if it isn't already (do this before skipping\n*         frames, so Select_Frame will smooth out the delay)\n*       - Skip frames\n*       - UnLCW frame\n*       - Convert Pointers to VRAM format\n*       - Un-VQ by copying codebook blocks within VRAM\n*       - Wait on Update_Enabled\n*       - Set the Flipper's CurFrame\n*       - Set Update_Enabled\n*       - Go to next frame\n*       - User_Update:\n*         Flip X-Page\n*         Set Palette from Flipper.CurFrame\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the correct spot on\n*     the Xmode screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_XmodeVRAM(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *scrn;\n\tlong          rc;\n\n\t/* Dereference data members for quicker access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* Dereference current frame for quicker access. */\n\t\tcurframe = drawer->CurFrame;\n\n\t\t/* Download codebook to VRAM */\n\t\tif ((curframe->Codebook->Flags & VQACBF_DOWNLOADED) == 0) {\n\t\t\tUpload_4x2CB(curframe->Codebook->Buffer,\n\t\t\t\t\t((VQAHandleP *)vqa)->Header.CBentries\n\t\t\t\t\t+ ((VQAHandleP *)vqa)->Header.Num1Colors);\n\n\t\t\tcurframe->Codebook->Flags |= VQACBF_DOWNLOADED;\n\t\t}\n\n\t\t/* Convert pointers to VRAM format */\n\t\tXlatePointers(curframe->Pointers, drawer->NumBlocks);\n\n\t\t/* Un-VQ the image */\n\t\tscrn = GetXHidPage();\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tscrn + drawer->ScreenOffset, drawer->BlocksPerRow,\n\t\t\t\tdrawer->NumRows, 320);\n\n\t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tif ((config->DrawerCallback(scrn, curframe->FrameNum)) != 0) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_Xmode - Page flip Xmode display.\n*\n* SYNOPSIS\n*     PageFlip_Xmode(VQA)\n*\n*     void PageFlip_Xmode(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void PageFlip_Xmode(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tunsigned char *pal;\n\tVQAConfig     *config;\n\tlong          palsize;\n\tlong          slowpal;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = vqabuf->Flipper.CurFrame;\n\n\t/* Pre-decode 'vqa' for speed */\n\tpal = curframe->Palette;\n\tpalsize = curframe->PaletteSize;\n\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\n\t/* - If this is a palette-set frame:\n\t * - Wait for NoVB (active scan)\n\t * - Flip the page (doesn't take effect until next active scan\n\t * - Wait for VB\n\t * - Set the palette\n\t * - Otherwise, just flip the page\n\t */\n\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tFlipXPage();\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(pal, palsize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)pal, (long)palsize);\n\t\t}\n\t}\n\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\tdrawer->Flags &= (~VQADRWF_SETPAL);\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tFlipXPage();\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(drawer->Palette_24, drawer->CurPalSize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)drawer->Palette_24,\n\t\t\t\t\t(long)drawer->CurPalSize);\n\t\t}\n\t} else {\n\t\tFlipXPage();\n\t}\n}\n#endif /* VQAXMODE_ON */\n\n\n#if(VQAMCGA_ON)\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_MCGA - Draws a frame directly to MCGA screen.\n*\n* SYNOPSIS\n*     Error = DrawFrame_MCGA(VQA)\n*\n*     long DrawFrame_MCGA(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Skip frames\n*       - UnLCW frame\n*       - Wait on Update_Enabled\n*       - Set Update_Enabled\n*       - Go to next frame\n*       - User_Update:\n*         set palette\n*         UnVQ to screen\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the correct spot on\n*     the screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_MCGA(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tlong         rc;\n\n\t/* Dereference commonly used data members for quicker access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Select the frame to draw. */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_MCGA - Page flip MCGA display.\n*\n* SYNOPSIS\n*     PageFlip_MCGA(VQA)\n*\n*     long PageFlip_MCGA(VQAHandle *);\n*\n* FUNCTION\n*     Since the MCGA mode only has one buffer, the drawing is actually done\n*     at this point.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle structure.\n*\n* RESULT\n*     Error - 0 if successfull, otherwise VQAERR_???\n*\n****************************************************************************/\n\nstatic long PageFlip_MCGA(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *pal;\n\tunsigned char *ptrs;\n\tunsigned char *cb;\n\tlong          palsize;\n\tlong          slowpal;\n\tlong          blocksperrow;\n\tlong          numrows;\n\n\t#ifndef PHARLAP_TNT\n\tunsigned char *scrn;\n\t#else\n\tFARPTR        scrn;\n\t#endif\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = vqabuf->Flipper.CurFrame;\n\n\t/*-------------------------------------------------------------------------\n\t * WAIT FOR THE VERTICAL BLANK TO SET THE PALETTE.\n\t *-----------------------------------------------------------------------*/\n\tif ((curframe->Flags & VQAFRMF_PALETTE)\n\t\t\t|| (drawer->Flags & VQADRWF_SETPAL)) {\n\n\t\tpal = curframe->Palette;\n\t\tpalsize = curframe->PaletteSize;\n\t\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\n\t\t/* Wait for the VBlank. */\n\t \tWaitNoVB(vqabuf->VBIBit);\n\t \tWaitVB(vqabuf->VBIBit);\n\n\t\t/* Set the palette. */\n\t\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\t\tSetPalette(pal, palsize, slowpal);\n\t\t\t}\n\n\t\t\t/* Notify the client of the palette change. */\n\t\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)pal, (long)palsize);\n\t\t\t}\n\t\t}\n\t\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\t\tdrawer->Flags &= (~VQADRWF_SETPAL);\n\n\t\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\t\tSetPalette(drawer->Palette_24, drawer->CurPalSize, slowpal);\n\t\t\t}\n\n\t\t\t/* Notify the client of the palette change. */\n\t\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)drawer->Palette_24,\n\t\t\t\t\t\t(long)drawer->CurPalSize);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * UNVQ THE FRAME DIRECTLY TO THE MCGA SCREEN.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Get screen address, blocks per row and number of rows. */\n\t#ifndef PHARLAP_TNT\n\tscrn = (unsigned char *)(0xA0000 + (unsigned long)drawer->ScreenOffset);\n\t#else\n\tFP_SET(scrn, drawer->ScreenOffset, 0x1C);\n\t#endif\n\n\tblocksperrow = drawer->BlocksPerRow;\n\tnumrows = drawer->NumRows;\n\tptrs = curframe->Pointers;\n\tcb = curframe->Codebook->Buffer;\n\tvqabuf->UnVQ(cb, ptrs, scrn, blocksperrow, numrows, 320);\n\n\t#if(VQACAPTIONS_ON)\n\t/* Process captions. */\n\tif ((((VQAHandleP *)vqa)->Caption != NULL)\n\t\t\t&& (config->OptionFlags & VQAOPTF_CAPTIONS)) {\n\t\tDoCaptions(((VQAHandleP *)vqa)->Caption, curframe->FrameNum);\n\t}\n\n\tif ((((VQAHandleP *)vqa)->EVA != NULL)\n\t\t\t&& (config->OptionFlags & VQAOPTF_EVA)) {\n\t\tDoCaptions(((VQAHandleP *)vqa)->EVA, curframe->FrameNum);\n\t}\n\n\t#endif\n\n\t/* Invoke user's callback routine */\n\tif (config->DrawerCallback != NULL) {\n\t\tif ((config->DrawerCallback(NULL, curframe->FrameNum)) != 0) {\n\t\t\treturn (VQAERR_EOF);\n\t\t}\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_MCGABuf - Draws a frame in MCGA format to a buffer.\n*\n* SYNOPSIS\n*     Error = DrawFrame_MCGABuf(VQA)\n*\n*     long DrawFrame_MCGABuf(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Skip frames\n*       - UnLCW frame\n*       - Wait on Update_Enabled (can't use imgbuf til User_Update's done)\n*       - Un-VQ into ImageBuf\n*       - Set the Flipper's CurFrame\n*       - Set Update_Enabled\n*       - Go to next frame\n*       - User_Update:\n*         set Palette from Flipper.CurFrame\n*         copy ImageBuf to screen\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the upper-left\n*     corner of ImageBuf, then copying ImageBuf onto the screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_MCGABuf(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tlong         rc;\n\n\t#ifndef PHARLAP_TNT\n\tunsigned char *scrn;\n\t#else\n\tFARPTR        scrn;\n\t#endif\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t#ifndef PHARLAP_TNT\n\tscrn = drawer->ImageBuf;\n\t#else\n\tFP_SET(scrn, drawer->ImageBuf, 0x14);\n\t#endif\n\n\t/* Un-VQ the image */\n\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, scrn,\n\t\t\tdrawer->BlocksPerRow, drawer->NumRows,\n\t\t\t((VQAHandleP *)vqa)->Header.ImageWidth);\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_MCGABuf - Page flip a buffered MCGA display.\n*\n* SYNOPSIS\n*     PageFlip_MCGABuf(VQA)\n*\n*     void PageFlip_MCGABuf(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successfull, otherwise VQAERR_???\n*\n****************************************************************************/\n\nstatic long PageFlip_MCGABuf(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *pal;\n\tunsigned char *buf;\n\tunsigned char *scrn;\n\tlong          palsize;\n\tlong          slowpal;\n\tlong          imgwidth;\n\tlong          imgheight;\n\n\t/* Derefernce commonly used data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = vqabuf->Flipper.CurFrame;\n\n\t/* Pre-decode 'vqa' for speed */\n\tpal = curframe->Palette;\n\tpalsize = curframe->PaletteSize;\n\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\n\t/* - If this is a palette-set frame:\n\t * - Wait for the vertical blank\n\t * - Set the palette\n\t * - Copy ImageBuf to SEENPAGE:\n\t * - use blit routine if image is smaller than full-screen, since the\n\t *   buffer copy assumes a full-screen image\n\t */\n\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(pal, palsize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)pal, (long)palsize);\n\t\t}\n\t}\n\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\tdrawer->Flags &= (~VQADRWF_SETPAL);\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(drawer->Palette_24, drawer->CurPalSize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)drawer->Palette_24,\n\t\t\t\t\t(long)drawer->CurPalSize);\n\t\t}\n\t}\n\n\t/* Draw image to the screen. */\n\timgwidth = ((VQAHandleP *)vqa)->Header.ImageWidth;\n\timgheight = ((VQAHandleP *)vqa)->Header.ImageHeight;\n\tbuf = drawer->ImageBuf;\n\n\t#ifndef PHARLAP_TNT\n\tscrn = (unsigned char *)0xA0000;\n\t#endif\n\n\tif ((imgwidth < 320) || (imgheight < 200)) {\n\t\t#ifndef PHARLAP_TNT\n\t\tscrn += drawer->ScreenOffset;\n\t\t#else\n\t\tscrn = (unsigned char *)drawer->ScreenOffset;\n\t\t#endif\n\n\t\tMCGA_Blit(buf, scrn, imgwidth, imgheight);\n\t} else {\n\t\tMCGA_BufferCopy(buf, NULL);\n\t}\n\n\t/* Invoke user's callback routine */\n\tif (config->DrawerCallback != NULL) {\n\t\tif ((config->DrawerCallback(NULL, curframe->FrameNum)) != 0) {\n\t\t\treturn (VQAERR_EOF);\n\t\t}\n\t}\n\n\treturn (0);\n}\n#endif /* VQAMCGA_ON */\n\n\n#if(VQAVESA_ON)\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_VESA640 - Draws a frame in VESA 640 format.\n*\n* SYNOPSIS\n*     Error = DrawFrame_VESA640(VQA)\n*\n*     long DrawFrame_VESA640(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_VESA640(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tlong         rc;\n\n\t#ifndef PHARLAP_TNT\n\tunsigned char *scrn;\n\t#else\n\tFARPTR        scrn;\n\t#endif\n\n\t/* Dereference data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\t}\n\n\t/* Dereference current frame. */\n\tcurframe = drawer->CurFrame;\n\n\t/* Wait for Update_Enabled to be set low */\n \tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tvqabuf->Drawer.WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t#ifndef PHARLAP_TNT\n\tscrn = drawer->ImageBuf + drawer->ScreenOffset;\n\t#else\n\tFP_SET(scrn, drawer->ImageBuf + drawer->ScreenOffset, 0x14);\n\t#endif\n\n\t/* Un-VQ the image */\n\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, scrn,\n\t\t\tdrawer->BlocksPerRow, drawer->NumRows, drawer->ImageWidth);\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_VESA320_32K - Draws a frame in VESA 320 format.\n*\n* SYNOPSIS\n*     Error = DrawFrame_VESA320_32K(VQA)\n*\n*     long DrawFrame_VESA320_32K(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_VESA320_32K(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tVQAConfig    *config;\n\tlong         rc;\n\tlong         grain;\n\n\t/* Dereference data members for quicker access. */\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* Dereference current frame. */\n\t\tcurframe = drawer->CurFrame;\n\n\t\t/* Translate palette to 15-bit */\n\t\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\t\tTranslatePalette(curframe->Palette, drawer->Palette_15,\n\t\t\t\t\tcurframe->PaletteSize);\n\t\t}\n\t\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\t\tTranslatePalette(drawer->Palette_24, drawer->Palette_15,\n\t\t\t\t\tdrawer->CurPalSize);\n\t\t}\n\n\t\t/* UnVQ directly to screen */\n\t\tgrain = ((VESAModeInfo *)(drawer->Display->Extended))->WinSize\n\t\t\t\t/ ((VESAModeInfo *)(drawer->Display->Extended))->WinGranularity;\n\n\t\t#ifndef PHARLAP_TNT\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tdrawer->Palette_15, grain, 0, 0);\n\t\t#else\n\t\t{\n\t\tFARPTR temp;\n\n\t\tFP_SET(temp, drawer->Palette_15, 0x14);\n\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, temp,\n\t\t\t\tgrain, 0, 0);\n\t\t}\n\t\t#endif\n\n\t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tif ((config->DrawerCallback(0, curframe->FrameNum)) != 0) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Wait for VQ_Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_VESA320_32KBuf - Draws a frame in VESA320_32K format to a\n*                                buffer.\n*\n* SYNOPSIS\n*     Error = DrawFrame_VESA320_32KBuf(VQA)\n*\n*     long DrawFrame_VESA320_32KBuf(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_VESA320_32KBuf(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tVQAConfig    *config;\n\tlong         rc;\n\tlong         grain;\n\n\t/* Dereference data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = drawer->CurFrame;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* UnVQ buffered mode */\n\t\t#ifndef PHARLAP_TNT\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tdrawer->ImageBuf, drawer->BlocksPerRow, drawer->NumRows,\n\t\t\t\t((VQAHandleP *)vqa)->Header.image_width);\n\t\t#else\n\t\t{\n\t\tFARPTR scrn;\n\n\t\tFP_SET(scrn, drawer->ImageBuf, 0x14);\n\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, scrn,\n\t\t\t\tdrawer->BlocksPerRow, drawer->NumRows,\n\t\t\t\t((VQAHandleP *)vqa)->Header.image_width);\n\t\t}\n\t\t#endif\n\n\t\t/* Translate the palette to 15-bit */\n\t\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\t\tTranslatePalette(curframe->Palette, drawer->Palette_15,\n\t\t\t\t\tcurframe->PaletteSize);\n\t\t}\n\t\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\t\tTranslatePalette(drawer->Palette_24, drawer->Palette_15,\n\t\t\t\t\tdrawer->CurPalSize);\n\t\t}\n\n\t\t/* Copy the buffer */\n\t\tgrain = ((VESAModeInfo *)(drawer->Display->Extended))->WinSize\n\t\t\t\t/ ((VESAModeInfo *)(drawer->Display->Extended))->WinGranularity;\n\n\t\tBuf_320x200_To_VESA_32K(drawer->ImageBuf, drawer->Palette_15, grain);\n\n \t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tif ((config->DrawerCallback(0, curframe->FrameNum)) != 0) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t\tdrawer->WaitsOnFlipper++;\n\t}\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_VESA - Page flip VESA display.\n*\n* SYNOPSIS\n*     PageFlip_VESA(VQA)\n*\n*     void PageFlip_VESA(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void PageFlip_VESA(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *pal;\n\tlong          palsize;\n\tlong          slowpal;\n\tlong          grain;\n\n\t/* Dereference date members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = vqabuf->Flipper.CurFrame;\n\n\t/* Pre-decode 'vqa' for speed */\n\tpal = curframe->Palette;\n\tpalsize = curframe->PaletteSize;\n\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\n\t/* Set the palette */\n\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(pal, palsize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)pal, (long)palsize);\n\t\t}\n\t}\n\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\tdrawer->Flags &= (~VQADRWF_SETPAL);\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(drawer->Palette_24, drawer->CurPalSize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)drawer->Palette_24,\n\t\t\t\t\t(long)drawer->CurPalSize);\n\t\t}\n\t}\n\n\t/* Copy the buffer */\n\tgrain = ((VESAModeInfo *)(drawer->Display->Extended))->WinSize\n\t\t\t/ ((VESAModeInfo *)(drawer->Display->Extended))->WinGranularity;\n\n\tswitch (((VQAHandleP *)vqa)->Header.image_width) {\n\t\tcase 320:\n\t\t\tif (config->DrawFlags & VQACFGF_SCALEX2) {\n\t\t\t\tBuf_320x200_To_VESA_640x400(drawer->ImageBuf, grain);\n\t\t\t} else {\n\t\t\t\tBuf_320x200_To_VESA_320x200(drawer->ImageBuf, grain);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tVESA_Blit_640x480(drawer->Display, drawer->ImageBuf, drawer->X1,\n\t\t\t\t\tdrawer->Y1, ((VQAHandleP *)vqa)->Header.image_width,\n\t\t\t\t\t((VQAHandleP *)vqa)->Header.image_height);\n\t\t\tbreak;\n\t}\n\n\t/* Invoke user's callback routine */\n\tif (config->DrawerCallback != NULL) {\n\t\tif ((config->DrawerCallback(drawer->ImageBuf, curframe->FrameNum)) != 0) {\n\t\t\treturn (VQAERR_EOF);\n\t\t}\n\t}\n}\n#endif /* VQAVESA_ON */\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_Buffer - Draw a frame to a buffer.\n*\n* SYNOPSIS\n*     Error = DrawFrame_Buffer(VQA)\n*\n*     long DrawFrame_Buffere(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQA handle.\n*\n* RESULT\n*     Error - 0 if successful, otherwise VQAERR_??? error code.\n*\n****************************************************************************/\n\nextern void __cdecl Set_Palette(void *palette);\nextern void Flag_To_Set_Palette(unsigned char *palette,long numbytes,unsigned long slowpal);\nstatic long DrawFrame_Buffer(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tVQAConfig    *config;\n\tlong         rc;\n\tunsigned char *pal;\n\tlong          palsize;\n\tlong          slowpal;\n\n\t#ifndef PHARLAP_TNT\n\tunsigned char *buff;\n\t#else\n\tFARPTR        buff;\n\t#endif\n\n\t/* Dereference data members for quicker access. */\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t#ifndef PHARLAP_TNT\n\tbuff = (unsigned char *)(drawer->ImageBuf + drawer->ScreenOffset);\n\t#else\n\tFP_SET(buff, drawer->ImageBuf + drawer->ScreenOffset, 0x14);\n\t#endif\n\n\n\tpal = curframe->Palette;\n\tpalsize = curframe->PaletteSize;\n\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\n\t/* Set the palette if neccessary */\n\tif ((curframe->Flags & VQAFRMF_PALETTE)\n\t\t\t|| (drawer->Flags & VQADRWF_SETPAL)) {\n\t\tFlag_To_Set_Palette(pal, palsize, slowpal);\n\t\tcurframe->Flags &= ~VQAFRMF_PALETTE;\n\t\tdrawer->Flags &= ~VQADRWF_SETPAL;\n \t}\n\n\n\t/* Un-VQ the image */\n\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, buff,\n\t\t\tdrawer->BlocksPerRow, drawer->NumRows, drawer->ImageWidth);\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Invoke user's callback routine */\n\tif (config->DrawerCallback != NULL) {\n\t\tif ((config->DrawerCallback(drawer->ImageBuf, curframe->FrameNum)) != 0) {\n\t\t\treturn (VQAERR_EOF);\n\t\t}\n\t}\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     UnVQ_Nop - Do nothing UnVQ.\n*\n* SYNOPSIS\n*     UnVQ_Nop(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n*\n*     void UnVQ_Nop(unsigned char *, unsigned char *, unsigned char *,\n*                   unsigned long, unsigned long, unsigned long);\n* FUNCTION\n*\n* INPUTS\n*     Codebook - Not used. (Prototype placeholder)\n*     Pointers - Not used. (Prototype placeholder)\n*     Buffer   - Not used. (Prototype placeholder)\n*     BPR      - Not used. (Prototype placeholder)\n*     Rows     - Not used. (Prototype placeholder)\n*     BufWidth - Not used. (Prototype placeholder)\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\n#ifndef PHARLAP_TNT\nstatic void __cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth)\n#else\nstatic void __cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth)\n#endif\n{\n\t/* Suppress compiler warnings */\n\tcodebook = codebook;\n\tpointers = pointers;\n\tbuffer = buffer;\n\tblocksperrow = blocksperrow;\n\tnumrows = numrows;\n\tbufwidth = bufwidth;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_Nop - Do nothing page flip.\n*\n* SYNOPSIS\n*     PageFlip_Nop(VQA)\n*\n*     void PageFlip_Nop(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQA handle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic long PageFlip_Nop(VQAHandle *vqa)\n{\n\tvqa = vqa;\n\n\treturn (0);\n}\n\n\n#if(0)\n/****************************************************************************\n*\n* NAME\n*     Mask_Rect - Sets non-drawable rectangle in image.\n*\n* SYNOPSIS\n*     Mask_Rect(VQA, X1, Y1, X2, Y2)\n*\n*     void Mask_Rect(VQAHandle *, unsigned long, unsigned long,\n*                    unsigned long, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQA handle.\n*     X1  - X coordinate of upper-left corner\n*     Y1  - Y coordinate of upper-left corner\n*     X2  - X coordinate of lower-right corner\n*     Y2  - Y coordinate of lower-right corner\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Mask_Rect(VQAHandle *vqa, unsigned long x1, unsigned long y1,\n\t\tunsigned long x2, unsigned long y2)\n{\n\tVQAData   *vqabuf;\n\tVQADrawer *drawer;\n\tVQAHeader *header;\n\tlong      blocks_per_row;\n\n\t/* Dereference data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\theader = &((VQAHandleP *)vqa)->Header;\n\tdrawer =  &vqabuf->Drawer;\n\n\t/* Clip coords to image size */\n\tif (x1 < vqabuf->Drawer.X1) {\n\t\tx1 = vqabuf->Drawer.X1;\n\t}\n\n\tif (y1 < vqabuf->Drawer.Y1) {\n\t\ty1 = vqabuf->Drawer.Y1;\n\t}\n\n\tif (x2 > vqabuf->Drawer.X2) {\n\t\tx2 = vqabuf->Drawer.X2;\n\t}\n\n\tif (y2 > vqabuf->Drawer.Y2) {\n\t\ty2 = vqabuf->Drawer.Y2;\n\t}\n\n\t/* Convert pixel coords to block coords */\n\tx1 /= header->block_width;\n\tx2 /= header->block_width;\n\ty1 /= header->block_height;\n\ty2 /= header->block_height;\n\n\t/* Compute the mask values */\n\tblocks_per_row = (header->image_width / header->block_width);\n\tvqabuf->Drawer.MaskStart = blocks_per_row * y1 + x1;\n\n\tif (x1 == x2) {\n\t\tdrawer->MaskWidth = 0;\n\t} else {\n\t\tdrawer->MaskWidth = x2 - x1 + 1;\n\t}\n\n\tif (y1 == y2) {\n\t\tdrawer->MaskHeight = 0;\n\t} else {\n\t\tdrawer->MaskHeight = y2 - y1 + 1;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Mask_Pointers - Mask vector pointer that are in the mask rectangle.\n*\n* SYNOPSIS\n*     Mask_Pointers(VQAData)\n*\n*     void Mask_Pointers(VQAData *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQAData - Pointer to VQAData structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Mask_Pointers(VQAData *vqabuf)\n{\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tunsigned long *ptr;\n\tunsigned long i,j;\n\tunsigned long start;\n\n\t/* Dereference data members for quicker access. */\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = drawer->CurFrame;\n\tstart = vqabuf->Drawer.MaskStart;\n\n\tfor (i = 0; i < drawer->MaskHeight; i++) {\n\t\tptr = (unsigned long *)(curframe->Pointers) + start;\n\n\t\tfor (j = 0; j < drawer->MaskWidth; j++) {\n\t\t\tptr[j] = VQA_MASK_POINTER;\n\t\t}\n\n\t\tstart += drawer->BlocksPerRow;\n\t}\n}\n#endif\n\n"
  },
  {
    "path": "WINVQ/VQA32/DSTREAM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQAPlay32 library.\n*\n* FILE\n*     dstream.c\n*\n* DESCRIPTION\n*     DOS IO handler.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 10, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_InitAsDOS - Initialize IO with the standard DOS handler.\n*\n* PRIVATE\n*     VQADOSHandler - Standard DOS IO handler.\n*\n****************************************************************************/\n\n#include <fcntl.h>\n#include <io.h>\n#include \"vqaplayp.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\nstatic long VQADOSHandler(VQAHandle *vqa, long action, void *buffer,\n\t\tlong nbytes);\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_InitAsDOS - Initialize IO with the standard DOS handler.\n*\n* SYNOPSIS\n*     VQA_InitAsDOS(VQA)\n*\n*     VQA_InitAsDOS(VQAHandle *);\n*\n* FUNCTION\n*     Initialize the IO of the specified handle as a standard DOS access.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle to initialize as DOS.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_InitAsDOS(VQAHandle *vqa)\n{\n\t((VQAHandleP *)vqa)->IOHandler = VQADOSHandler;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQADOSHandler - Standard DOS IO handler.\n*\n* SYNOPSIS\n*     Error = VQADOSHandler(VQA, Action, Buffer, NBytes)\n*\n*     unsigned long VQADOSHandler(VQAHandle *, long, long, long);\n*\n* FUNCTION\n*      Perform the requested action on the standard DOS file system.\n*\n* INPUTS\n*      VQA    - VQAHandle to operate on.\n*      Action - Action to perform.\n*      Buffer - Buffer to Read/Write to/from.\n*      NBytes - Number of bytes to operate on.\n*\n* RESULT\n*      Error - 0 if successful, otherwise error.\n*\n****************************************************************************/\n\nstatic long VQADOSHandler(VQAHandle *vqa, long action, void *buffer,\n\t\tlong nbytes)\n{\n\tlong fh;\n\tlong error;\n\n\tfh = vqa->VQAio;\n\n\t/* Perform the action specified by the IO command */\n\tswitch (action) {\n\n\t\t/* VQACMD_READ means read NBytes and place it in the memory\n\t\t * pointed to by Buffer.\n\t\t *\n\t\t * Any error code returned will be remapped by VQA library into\n\t\t * VQAERR_READ.\n\t\t */\n\t\tcase VQACMD_READ:\n\t\t\terror = (read(fh, buffer, nbytes) != nbytes);\n\t\t\tbreak;\n\n\t\t/* VQACMD_WRITE is analogous to VQACMD_READ.\n\t\t *\n\t\t * Writing is not allowed to the VQA file, VQA library will remap the\n\t\t * error into VQAERR_WRITE.\n\t\t */\n\t\tcase VQACMD_WRITE:\n\t\t\terror = 1;\n\t\t\tbreak;\n\n\t\t/* VQACMD_SEEK asks that you perform a seek relative to the current\n\t\t * position. NBytes is a signed number, indicating seek direction\n\t\t * (positive for forward, negative for backward). Buffer has no meaning\n\t\t * here.\n\t\t *\n\t\t * Any error code returned will be remapped by VQA library into\n\t\t * VQAERR_SEEK.\n\t\t */\n\t\tcase VQACMD_SEEK:\n\t\t\terror = (lseek(fh, nbytes, (long)buffer) == -1);\n\t\t\tbreak;\n\n\t\t/* VQACMD_OPEN asks that you open the file for access. */\n\t\tcase VQACMD_OPEN:\n\t\t\terror = open((char *)buffer, (O_RDONLY|O_BINARY));\n\n\t\t\tif (error != -1) {\n\t\t\t\tvqa->VQAio = error;\n\t\t\t\terror = 0;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase VQACMD_CLOSE:\n\t\t\tclose(fh);\n\t\t\terror = 0;\n\t\t\tbreak;\n\n\t\t/* VQACMD_INIT means to prepare your IO for reading. This is used for\n\t\t * certain IOs that can't be read immediately upon opening, and need\n\t\t * further preparation. This operation is allowed to fail; the error code\n\t\t * will be returned directly to the client.\n\t\t */\n\t\tcase VQACMD_INIT:\n\n\t\t/* IFFCMD_CLEANUP means to terminate the transaction with the associated\n\t\t * IO. This is used for IOs that can't simply be closed. This operation\n\t\t * is not allowed to fail; any error returned will be ignored.\n\t\t */\n\t\tcase VQACMD_CLEANUP:\n\t\t\terror = 0;\n\t\t\tbreak;\n\t}\n\n\treturn (error);\n}\n\n"
  },
  {
    "path": "WINVQ/VQA32/LOADER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     loader.c\n*\n* DESCRIPTION\n*     Stream loading and pre-processing.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     August 21, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_Open      - Open a VQA file to play.\n*     VQA_Close     - Close an opened VQA file.\n*     VQA_LoadFrame - Load the next video frame from the VQA data stream.\n*     VQA_SeekFrame - Position the movie stream to the specified frame.\n*\n* PRIVATE\n*     AllocBuffers  - Allocates the numerous VQA play buffers\n*     FreeBuffers   - Frees the VQA play buffers\n*     PrimeBuffers  - Pre-Load the internal buffers.\n*     Load_FINF     - Loads the Frame Info Table.\n*     Load_VQHD     - Loads a VQA Header.\n*     Load_CBF0     - Loads a full, uncompressed codebook\n*     Load_CBFZ     - Loads a full, compressed codebook\n*     Load_CBP0     - Loads a partial uncompressed codebook\n*     Load_CBPZ     - Loads a partial compressed codebook\n*     Load_CPL0     - Loads an uncompressed palette\n*     Load_CPLZ     - Loads a compressed palette\n*     Load_VPT0     - Loads uncompressed pointers\n*     Load_VPTZ     - Loads compressed pointers\n*     Load_VQF      - Loads a VQ Frame chunk\n*     Load_SND0     - Loads an uncompressed sound chunk\n*     Load_SND1     - Loads a compressed sound chunk\n*     Load_AudFrame - Loads blocks from separate audio file, if needed.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <fcntl.h>\n#include <io.h>\n#include <malloc.h>\n#include <mem.h>\n#include <dos.h>\n#include \"vq.h\"\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n#include \"caption.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\nstatic VQAData *AllocBuffers(VQAHeader *header, VQAConfig *config);\nstatic void FreeBuffers(VQAData *vqa, VQAConfig *config, VQAHeader *header);\nstatic long PrimeBuffers(VQAHandle *vqa);\nstatic long Load_VQF(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_FINF(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_VQHD(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CBF0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CBFZ(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CBP0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CBPZ(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CPL0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CPLZ(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_VPT0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_VPTZ(VQAHandleP *vqap, unsigned long iffsize);\n\n#if(VQAAUDIO_ON)\nstatic long Load_SND0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_SND1(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_SND2(VQAHandleP *vqap, unsigned long iffsize);\n\n#if(VQAVOC_ON)\nstatic void Load_AudFrame(VQAHandleP *vqap);\n#endif /* VQAVOC_ON */\n\n#endif /* VQAAUDIO_ON */\n\n\nextern \"C\"{\n\tvoid __cdecl Force_VM_Page_In (void *buffer, int length);\n}\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Open - Open a VQA file to play.\n*\n* SYNOPSIS\n*     Error = VQA_Open(VQA, Name, Config)\n*\n*     long VQA_Open(VQAHandle *, char *, VQAConfig *);\n*\n* FUNCTION\n*     - Open a VQA file for reading.\n*     - Validate that it is an IFF file, of the VQA type.\n*     - Read the VQA header.\n*     - Open a VOC file for playback, if requested.\n*     - Set the Loader's frame rate, if the caller's Config structure's\n*       FrameRate is set to -1\n*     - Set the Drawer's frame rate, if the caller's Config structure's\n*       DrawRate is set to -1\n*\n* INPUTS\n*     VQA    - Pointer to initialized handle. Obtained by VQA_Alloc().\n*     Name   - Pointer to name of VQA file to open.\n*     Config - Pointer to initialized VQA configuration structure.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_ error code.\n*\n****************************************************************************/\n\n#define OPEN_VQHD     (1<<0)\n#define OPEN_FINF     (1<<1)\n#define OPEN_CAPTIONS (1<<2)\n#define OPEN_EVA      (1<<3)\nextern int VQAMovieDone;\nlong VQA_Open(VQAHandle *vqa, char const *filename, VQAConfig *config)\n{\n\tVQAHandleP  *vqap;\n\tVQAHeader   *header;\n\tChunkHeader chunk;\n\tlong        max_frm_size;\n\tlong        i;\n\tlong        done;\n\tlong        found;\n\tchar        *ptr;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqap = (VQAHandleP *)vqa;\n\theader = &vqap->Header;\n\n\tVQAMovieDone = 0;\n\t/*-------------------------------------------------------------------------\n\t * VERIFY VALIDITY OF VQA FILE.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Open the file. */\n\tif (vqap->IOHandler(vqa, VQACMD_OPEN, (void *)filename, 0)) {\n\t\treturn (VQAERR_OPEN);\n\t}\n\n\t/* Read the file ID & Size */\n\tif (vqap->IOHandler(vqa, VQACMD_READ, &chunk, 8)) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Verify an IFF FORM */\n\tif ((chunk.id != ID_FORM) || (chunk.size == 0)) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_NOTVQA);\n\t}\n\n\t/* Read in WVQA ID */\n\tif (vqap->IOHandler(vqa, VQACMD_READ, &chunk, 4)) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Verify VQA */\n\tif (chunk.id != ID_WVQA) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_NOTVQA);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE PLAYERS CONFIGURATION\n\t *-----------------------------------------------------------------------*/\n\n\t/* Use the clients configuration if they provided one. */\n\tif (config != NULL) {\n\t\tmemcpy(&vqap->Config, config, sizeof(VQAConfig));\n\t} else {\n\t\tVQA_DefaultConfig(&vqap->Config);\n\t}\n\n\t/* Use the internal configuration structure from now on. */\n\tconfig = &vqap->Config;\n\n\t/*-------------------------------------------------------------------------\n\t * PROCESS THE PRE-FRAME CHUNKS (VQHD, CAP, FINF, ETC...)\n\t *-----------------------------------------------------------------------*/\n\tfound = 0;\n\tdone = 0;\n\n\twhile (!done) {\n\t\tif (vqap->IOHandler(vqa, VQACMD_READ, &chunk, 8)) {\n\t\t\tVQA_Close(vqa);\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\n\t\tchunk.size = REVERSE_LONG(chunk.size);\n\n\t\tswitch (chunk.id) {\n\n\t\t\t/*---------------------------------------------------------------------\n\t\t\t * READ IN THE VQA HEADER.\n\t\t\t *-------------------------------------------------------------------*/\n\t\t\tcase ID_VQHD:\n\t\t\t\tif (chunk.size != sizeof(VQAHeader)) {\n\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\treturn (VQAERR_NOTVQA);\n\t\t\t\t}\n\n\t\t\t\t/* Read the header data. */\n\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_READ, header, PADSIZE(chunk.size))) {\n\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/*-------------------------------------------------------------------\n\t\t\t\t * SETUP THE CONFIGURATION FROM THE HEADER.\n\t\t\t\t *-----------------------------------------------------------------*/\n\t\t\t\tif (config->ImageWidth == -1) {\n\t\t\t\t\tconfig->ImageWidth = header->ImageWidth;\n\t\t\t\t}\n\n\t\t\t\tif (config->ImageHeight == -1) {\n\t\t\t\t\tconfig->ImageHeight = header->ImageHeight;\n\t\t\t\t}\n\n\t\t\t\t/* If Loaders frame rate is -1 then use the value from the header. */\n\t\t\t\tif (config->FrameRate == -1) {\n\t\t\t\t\tconfig->FrameRate = header->FPS;\n\t\t\t\t}\n\n\t\t\t\t/* If Drawers frame rate is -1 then use the value from the header,\n\t\t\t\t * which will result in a \"variable\" frame rate.\n\t\t\t\t */\n\t\t\t\tif (config->DrawRate == -1) {\n\t\t\t\t\tconfig->DrawRate = header->FPS;\n\t\t\t\t}\n\n\t\t\t\t/* Finally, if the DrawRate was set to -1 or 0 (ie MaxRate contained\n\t\t\t\t * bogus values), set it to the header value.\n\t\t\t\t */\n\t\t\t\tif ((config->DrawRate == -1) || (config->DrawRate == 0)) {\n\t\t\t\t\tconfig->DrawRate = header->FPS;\n\t\t\t\t}\n\n\t\t\t\t#if(VQAAUDIO_ON)\n\t\t\t\t/* If an alternate audio track is not available then turn it off.\n\t\t\t\t * This enables the primary audio track to be played.\n\t\t\t\t */\n\t\t\t\tif ((header->Version > VQAHD_VER1)\n\t\t\t\t\t\t&& !(header->Flags & VQAHDF_ALTAUDIO)) {\n\t\t\t\t\tconfig->OptionFlags &= ~VQAOPTF_ALTAUDIO;\n\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\t/*-------------------------------------------------------------------\n\t\t\t\t * ALLOCATE THE BUFFERS THAT WE NEED TO PLAY THE VQA.\n\t\t\t\t *-----------------------------------------------------------------*/\n\t\t\t\tif ((vqap->VQABuf = AllocBuffers(header, config)) == NULL) {\n\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\treturn (VQAERR_NOMEM);\n\t\t\t\t}\n\n\t\t\t\tfound |= OPEN_VQHD;\n\t\t\t\tbreak;\n\n\t\t\t#if( VQACAPTIONS_ON )\n\n\t\t\t/*---------------------------------------------------------------------\n\t\t\t * READ IN AND OPEN THE CAPTIONS STREAM.\n\t\t\t *-------------------------------------------------------------------*/\n\t\t\tcase ID_CAP0:\n\t\t\t\tif ((config->CapFont != NULL)\n\t\t\t\t\t\t&& (config->OptionFlags & VQAOPTF_CAPTIONS)) {\n\n\t\t\t\t\tshort size = 0;\n\n\t\t\t\t\t/* Get uncompressed size of captions. */\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_READ, &size, sizeof(short))) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Allocate buffer for captions. */\n\t\t\t\t\ti = size + 50;\n\n\t\t\t\t\tif ((ptr = (char *)malloc(i)) == NULL) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_NOMEM);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Read in the captions chunk. */\n\t\t\t\t\ti -= PADSIZE(chunk.size);\n\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_READ, (ptr + i),\n\t\t\t\t\t\t\tPADSIZE(chunk.size - sizeof(short)))) {\n\n\t\t\t\t\t\tfree(ptr);\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Decompress the captions. */\n\t\t\t\t\tLCW_Uncompress((ptr + i), ptr, size);\n\t\t\t\t\tvqap->Caption = OpenCaptions(ptr, config->CapFont);\n\n\t\t\t\t\tif (vqap->Caption == NULL) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_NOMEM);\n\t\t\t\t\t}\n\n\t\t\t\t\tfound |= OPEN_CAPTIONS;\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(chunk.size))) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\n\t\t\tcase ID_EVA0:\n\t\t\t\tif ((config->EVAFont != NULL)\n\t\t\t\t\t\t&& (config->OptionFlags & VQAOPTF_EVA)) {\n\n\t\t\t\t\tshort size = 0;\n\n\t\t\t\t\t/* Get uncompressed size of captions. */\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_READ, &size, sizeof(short))) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Allocate buffer for captions. */\n\t\t\t\t\ti = size + 50;\n\n\t\t\t\t\tif ((ptr = (char *)malloc(i)) == NULL) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_NOMEM);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Read in the captions chunk. */\n\t\t\t\t\ti -= PADSIZE(chunk.size);\n\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_READ, (ptr + i),\n\t\t\t\t\t\t\tPADSIZE(chunk.size - sizeof(short)))) {\n\t\t\t\t\t\tfree (ptr);\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Decompress the captions. */\n\t\t\t\t\tLCW_Uncompress((ptr + i), ptr, size);\n\t\t\t\t\tvqap->EVA = OpenCaptions(ptr, config->EVAFont);\n\n\t\t\t\t\tif (vqap->EVA == NULL) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_NOMEM);\n\t\t\t\t\t}\n\n\t\t\t\t\tfound |= OPEN_EVA;\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(chunk.size))) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\n\n\t\t\t#endif\n\n\t\t\t/*---------------------------------------------------------------------\n\t\t\t * READ FRAME INFORMATION\n\t\t\t *-------------------------------------------------------------------*/\n\t\t\tcase ID_FINF:\n\t\t\t\tif (Load_FINF(vqap, chunk.size)) {\n\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\tdone = 1;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\tPADSIZE(chunk.size))) {\n\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE VIDEO SYSTEM IF WE ARE REQUIRED TO HANDLE THAT.\n\t *-----------------------------------------------------------------------*/\n\t#if(VQAVIDEO_ON)\n\tif ((vqap->VQABuf->Drawer.Display = SetVideoMode(config->Vmode)) == 0) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_VIDEO);\n\t}\n\n\t/* Set the VBIBit polarity. */\n\tvqap->VQABuf->VBIBit = GetVBIBit();\n\t#else\n\tif (config->VBIBit == -1) {\n\t\tconfig->VBIBit = TestVBIBit();\n\t}\n\n\tvqap->VQABuf->VBIBit = config->VBIBit;\n\n\t#if( VQACAPTIONS_ON )\n\n\tif (found & OPEN_CAPTIONS|OPEN_EVA) {\n\t\tSetDAC(251,255,255,255); /* White */\n\t\tSetDAC(252,255,000,000); /* Red */\n\t\tSetDAC(253,000,255,000); /* Green */\n\t\tSetDAC(254,255,255,255);\n\t\tSetDAC(255,255,000,255); /* Cycle */\n\t}\n\n\t#endif\n\n\t#endif /* VQAVIDEO_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * AUDIO TRACK OVERRIDE FROM EXTERNAL FILE (.VOC)\n\t *-----------------------------------------------------------------------*/\n\n\t/* Open VOC file if one is requested. */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (config->VocFile != NULL) {\n\t\tvqap->vocfh = open(config->VocFile, (O_RDONLY|O_BINARY));\n\t} else {\n\t\tvqap->vocfh = -1;\n\t}\n\n\t/* Make sure we won't try to play audio. */\n\tif ((vqap->vocfh == -1) && ((header->Flags & VQAHDF_AUDIO) == 0)) {\n\t\tconfig->OptionFlags &= (~VQAOPTF_AUDIO);\n\t}\n\t#else  /* VQAVOC_ON */\n\n\t/* If the movie does not contain an audio track make sure we won't try\n\t * to play one.\n\t */\n\tif (((header->Flags & VQAHDF_AUDIO) == 0)) {\n\t\tconfig->OptionFlags &= (~VQAOPTF_AUDIO);\n\t}\n\t#endif /* VQAVOC_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE AUDIO PLAYBACK/TIMING SYSTEM.\n\t *-----------------------------------------------------------------------*/\n\t#if(VQAAUDIO_ON)\n\tif (config->OptionFlags & VQAOPTF_AUDIO) {\n\t\tVQAAudio *audio;\n\n\t\t/* Dereference for quick access. */\n\t\taudio = &vqap->VQABuf->Audio;\n\n\t\t/* Open HMI audio resource for playback. */\n\t\tif (VQA_OpenAudio(vqap , MainWindow)) {\n\t\t\tVQA_Close(vqa);\n\t\t\treturn (VQAERR_AUDIO);\n\t\t}\n\n\t\t/* Initialize ADPCM information structure for audio stream. */\n\t\tVQA_sosCODECInitStream(&audio->ADPCM_Info);\n\n\t\tif (header->Version == VQAHD_VER1) {\n\t\t\taudio->ADPCM_Info.wBitSize = 8;\n\t\t\taudio->ADPCM_Info.dwUnCompSize = (22050L/header->FPS) * header->Frames;\n\t\t\taudio->ADPCM_Info.wChannels = 1;\n\t\t} else {\n\t\t\taudio->ADPCM_Info.wBitSize = audio->BitsPerSample;\n\t\t\taudio->ADPCM_Info.dwUnCompSize = (((audio->SampleRate / header->FPS)\n\t\t\t\t\t* (audio->BitsPerSample >> 3)) * audio->Channels) * header->Frames;\n\n\t\t\taudio->ADPCM_Info.wChannels = audio->Channels;\n\t\t}\n\n\t\taudio->ADPCM_Info.dwCompSize = audio->ADPCM_Info.dwUnCompSize\n\t\t\t\t/ (audio->ADPCM_Info.wBitSize / 4);\n\t}\n\n\t/* Turn off audio if the HMI DigiHandle is invalid. */\n#if (!VQADIRECT_SOUND)\n\tif (config->DigiHandle == -1) {\n\t\tconfig->OptionFlags &= ~VQAOPTF_AUDIO;\n\t}\n\n\t/* Setup the timer interrupt if the client requests it for the timing\n\t * source.\n\t */\n\tif (!(config->OptionFlags & VQAOPTF_AUDIO)\n\t\t\t|| (config->TimerMethod == VQA_TMETHOD_INT)) {\n\n\t\t/* Start HMI timer system for timing. */\n\t\tif (VQA_StartTimerInt(vqap, (config->OptionFlags & VQAOPTF_HMIINIT))) {\n\t\t\tVQA_Close(vqa);\n\t\t\treturn (VQAERR_AUDIO);\n\t\t}\n\t}\n#endif\t//VQADIRECT_SOUND\n\t#endif /* VQAAUDIO_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * PRIME THE BUFFERS BY PRE-LOADING THEM WITH FRAME DATA.\n\t *-----------------------------------------------------------------------*/\n\tif (PrimeBuffers(vqa) != 0) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_READ);\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Close - Close an opened VQA file.\n*\n* SYNOPSIS\n*     VQA_Close(VQA)\n*\n*     void VQA_Close(VQAHandle *);\n*\n* FUNCTION\n*     Close the file that was opened with VQA_Open().\n*\n* INPUTS\n*     VQA - Pointer VQAHandle to close.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Close(VQAHandle *vqa)\n{\n\tlong (*iohandler)(VQAHandle *, long, void *, long);\n\n\t/* Restore video mode to text. */\n\t#if(VQAVIDEO_ON)\n\tSetVideoMode(TEXT_VIDEO);\n\t#endif /* VQAVIDEO_ON */\n\n\t/* Shutdown audio/timing system. */\n\t#if(VQAAUDIO_ON)\n\tif (((VQAHandleP *)vqa)->Config.OptionFlags & VQAOPTF_AUDIO) {\n\t\tVQA_CloseAudio((VQAHandleP *)vqa);\n\t} else {\n\t\tVQA_StopTimerInt((VQAHandleP *)vqa);\n\t}\n\t#endif /* VQAAUDIO_ON */\n\n\t#if( VQACAPTIONS_ON )\n\n\t/* Free captions. */\n\tif (((VQAHandleP *)vqa)->Caption != NULL) {\n\t\tif (((VQAHandleP *)vqa)->Caption->Buffer != NULL) {\n\t\t\tfree(((VQAHandleP *)vqa)->Caption->Buffer);\n\t\t}\n\n\t\tCloseCaptions(((VQAHandleP *)vqa)->Caption);\n\t}\n\n\t/* Free EVA. */\n\tif (((VQAHandleP *)vqa)->EVA != NULL) {\n\t\tif (((VQAHandleP *)vqa)->EVA->Buffer != NULL) {\n\t\t\tfree(((VQAHandleP *)vqa)->EVA->Buffer);\n\t\t}\n\n\t\tCloseCaptions(((VQAHandleP *)vqa)->EVA);\n\t}\n\n\n\t#endif\n\n\t/* Free memory */\n\tif (((VQAHandleP *)vqa)->VQABuf != NULL) {\n\t\tFreeBuffers(((VQAHandleP *)vqa)->VQABuf, &((VQAHandleP *)vqa)->Config,\n\t\t\t\t&((VQAHandleP *)vqa)->Header);\n\t}\n\n\t/* Close the VOC override file if one was opened */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((VQAHandleP *)vqa)->vocfh != -1) {\n\t\tclose(((VQAHandleP *)vqa)->vocfh);\n\t}\n\t#endif /* VQAVOC_ON */\n\n\t/* Close the VQA file */\n\t((VQAHandleP *)vqa)->IOHandler(vqa, VQACMD_CLOSE, NULL, 0);\n\n\t/* Reset the VQAHandle */\n\tiohandler = ((VQAHandleP *)vqa)->IOHandler;\n\tmemset(vqa, 0, sizeof(VQAHandleP));\n\t((VQAHandleP *)vqa)->IOHandler = iohandler;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_LoadFrame - Load the next video frame from the VQA data stream.\n*\n* SYNOPSIS\n*     Error = VQA_LoadFrame(VQA)\n*\n*     long VQA_LoadFrame(VQAHandle *);\n*\n* FUNCTION\n*     The codebook is split up such that the last frame of every group gets\n*     a new, complete codebook, ready for the next group.  The first codebook\n*     in the VQA is a full codebook, and goes with the first frame's data.\n*     Partial codebooks are stored per frame after that, and they add up to\n*     a full codebook just before the first frame for the next group is read.\n*\n*     (Currently, this routine can read either the older non-frame-grouped\n*     VQA file format, or the new frame-chunk format.  For the older format,\n*     it's assumed that the last chunk in a frame is the pointer data.)\n*\n*     This routine also does a sort of \"cooperative multitasking\".  If the\n*     Loader hits a \"wait state\" where it has to wait on the audio to finish\n*     playing before it can continue to load, it sets a \"sleep\" flag and\n*     just returns.  The sleep flag is checked on entry to see if it needs\n*     to jump to the proper execution point. This may improve performance on\n*     some platforms, but it also allows the Loader to be called regardless\n*     of the size of the buffers; if the buffers fill up or the audio fails\n*     to play, the Loader won't just get stuck.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle structure.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nlong VQA_LoadFrame(VQAHandle *vqa)\n{\n\tVQAHandleP    *vqap;\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tChunkHeader   *chunk;\n\tunsigned long iffsize;\n\tlong          frame_loaded = 0;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqap = (VQAHandleP *)vqa;\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\tdrawer = &((VQAHandleP *)vqa)->VQABuf->Drawer;\n\tcurframe = loader->CurFrame;\n\tchunk = &loader->CurChunkHdr;\n\n\t/* We have reached the end of the file if we loaded all the frames. */\n\tif (loader->CurFrameNum >= vqap->Header.Frames) {\n\t\treturn (VQAERR_EOF);\n\t}\n\n\t/* If we're reading audio from a VOC file then service that requirement. */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (vqap->vocfh != -1) {\n\t\tLoad_AudFrame(vqap);\n\t}\n\t#endif /* VQAAUDIO_ON & VQAVOC_ON */\n\n\t/* If no buffer is available for loading then return. This allows the\n\t * drawer to service one of the buffers more readily. (We'll wait for one\n\t * to free up).\n\t */\n\tif (curframe->Flags & VQAFRMF_LOADED) {\n\t\tloader->WaitsOnDrawer++;\n\t\treturn (VQAERR_NOBUFFER);\n\t}\n\n\t/* If we're not sleeping, initialize */\n\tif (!(vqabuf->Flags & VQADATF_LSLEEP)) {\n\t\tframe_loaded = 0;\n\t\tloader->FrameSize = 0;\n\n\t\t/* Initialize the codebook ptr for the frame we're about to load:\n\t\t * (This frame's codebook is the last full codebook; we have to init it\n\t\t * now, because if we're on the last frame in a group, we'll get a new\n\t\t * FullCB pointer.)\n\t\t */\n\t\tcurframe->Codebook = loader->FullCB;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * THE MAIN LOADER LOOP\n\t *-----------------------------------------------------------------------*/\n\twhile (frame_loaded == 0) {\n\n\t\t/* Read new chunk, only if we're not sleeping */\n\t\tif (!(vqabuf->Flags & VQADATF_LSLEEP)) {\n\n\t\t\t/* Read chunk ID */\n\t\t\tif (vqap->IOHandler(vqa, VQACMD_READ, chunk, 8)) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\n\t\t\tiffsize = REVERSE_LONG(chunk->size);\n\t\t\tloader->FrameSize += iffsize;\n\t\t}\n\n\t\t/* Handle each chunk type */\n\t\tswitch (chunk->id) {\n\n\t\t\t/* VQ Normal Frame */\n\t\t\tcase ID_VQFR:\n\t\t\t\tif (Load_VQF(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* VQ Key Frame */\n\t\t\tcase ID_VQFK:\n\t\t\t\tif (Load_VQF(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as being key. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_KEY;\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* Full uncompressed codebook */\n\t\t\tcase ID_CBF0:\n\t\t\t\tif (Load_CBF0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Full compressed codebook */\n\t\t\tcase ID_CBFZ:\n\t\t\t\tif (Load_CBFZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Partial uncompressed codebook */\n\t\t\tcase ID_CBP0:\n\t\t\t\tif (Load_CBP0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Partial compressed codebook */\n\t\t\tcase ID_CBPZ:\n\t\t\t\tif (Load_CBPZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed palette */\n\t\t\tcase ID_CPL0:\n\t\t\t\tif (Load_CPL0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* If this is the first occurance of a palette then store it now.\n\t\t\t\t * This functionality is needed for Monopoly!\n\t\t\t\t */\n\t\t\t\tif (drawer->CurPalSize == 0) {\n\t\t\t\t\tmemcpy(drawer->Palette_24,curframe->Palette,curframe->PaletteSize);\n\t\t\t\t\tdrawer->CurPalSize = curframe->PaletteSize;\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as having a palette. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_PALETTE;\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed palette */\n\t\t\tcase ID_CPLZ:\n\t\t\t\tif (Load_CPLZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* If this is the first occurance of a palette then store it now.\n\t\t\t\t * This functionality is needed for Monopoly!\n\t\t\t\t */\n\t\t\t\tif (drawer->CurPalSize == 0) {\n\t\t\t\t\tdrawer->CurPalSize = LCW_Uncompress((char *)curframe->Palette\n\t\t\t\t\t\t\t+ curframe->PalOffset, (char *)drawer->Palette_24,\n\t\t\t\t\t\t\tvqabuf->Max_Pal_Size);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as having a palette. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_PALETTE;\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed pointer data */\n\t\t\tcase ID_VPT0:\n\t\t\t\tif (Load_VPT0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed pointer data */\n\t\t\tcase ID_VPTZ:\n\t\t\tcase ID_VPTD:\n\t\t\t\tif (Load_VPTZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* Pointer data Key (Must draw) */\n\t\t\tcase ID_VPTK:\n\t\t\t\tif (Load_VPTZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as being key. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_KEY;\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed audio frame.\n\t\t\t *\n\t\t\t *  - Make sure the sound load buffer (Audio.TempBuf) is empty; if not\n\t\t\t *    go into a sleep state.\n\t\t\t *  - Load the data into TempBuf.\n\t\t\t */\n\t\t\t#if(VQAAUDIO_ON)\n\t\t\tcase ID_SND0:\n\t\t\t\tif (!(vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO)) {\n\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load an uncompressed audio frame. */\n\t\t\t\t\tif (Load_SND0(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ID_SNA0:\n\t\t\t\tif (vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO) {\n\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load an uncompressed audio frame. */\n\t\t\t\t\tif (Load_SND0(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed audio frame.\n\t\t\t *\n\t\t\t *  - Make sure the sound load buffer (Audio.TempBuf) is empty; if not\n\t\t\t *    go into a sleep state.\n\t\t\t *  - Load the data into TempBuf.\n\t\t\t */\n\t\t\tcase ID_SND1:\n\t\t\t\tif (!(vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO)) {\n\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load a compressed audio frame. */\n\t\t\t\t\tif (Load_SND1(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ID_SNA1:\n\t\t\t\tif (vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO) {\n\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load a compressed audio frame. */\n\t\t\t\t\tif (Load_SND1(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* HMI ADPCM compressed audio frame.\n\t\t\t *\n\t\t\t *  - Make sure the sound load buffer (Audio.TempBuf) is empty; if not\n\t\t\t *    go into a sleep state.\n\t\t\t *  - Load the data into TempBuf.\n\t\t\t */\n\t\t\tcase ID_SND2:\n\t\t\t\tif (!(vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO)) {\n\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load a compressed audio frame. */\n\t\t\t\t\tif (Load_SND2(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ID_SNA2:\n\t\t\t\tif (vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO) {\n\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load a compressed audio frame. */\n\t\t\t\t\tif (Load_SND2(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\t/* Skip any unknown chunks. */\n\t\t\tdefault:\n\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/* Update maximum frame size stat. */\n\tif ((loader->CurFrameNum>0) && (loader->FrameSize>loader->MaxFrameSize)) {\n\t\tloader->MaxFrameSize = loader->FrameSize;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * SET UP THE FRAME FOR DRAWING.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Set the frame # */\n\tcurframe->FrameNum = loader->CurFrameNum;\n\tloader->CurFrameNum++;\n\n\t/* Update data for mono output */\n\tloader->LastFrameNum = loader->CurFrameNum;\n\n\t/* Loader is finished with this frame; tell Drawer to draw it */\n\tcurframe->Flags |= VQAFRMF_LOADED;\n\tloader->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_SeekFrame - Position the movie stream to the specified frame.\n*\n* SYNOPSIS\n*     Frame = VQA_SeekFrame(VQA, Frame, FromWhere)\n*\n*     long VQA_SeekFrame(VQAHandle *, long, long);\n*\n* FUNCTION\n*     This function sets the movie stream to the new frame specified by\n*     the 'offset' parameter. 'FromWhere' is a symbolic constant that is used\n*     to specify from where in the stream offset should be applied.\n*\n* INPUTS\n*     VQA       - Pointer to VQAHandle of movie to seek into.\n*     Frame     - Frame to seek to.\n*     FromWhere - Relative position indicator.\n*\n* RESULT\n*     Frame - New frame position or -1 if error.\n*\n****************************************************************************/\n\nlong VQA_SeekFrame(VQAHandle *vqa, long framenum, long fromwhere)\n{\n\tVQAHandleP   *vqap;\n\tVQAData      *vqabuf;\n\tVQALoader    *loader;\n\tVQAHeader    *header;\n\tVQAFrameNode *frame;\n\tVQAConfig    *config;\n\tlong         group;\n\tlong         i;\n\tlong         rc = VQAERR_NONE;\n\n\t#if(VQAAUDIO_ON)\n\tVQAAudio     *audio;\n\tlong         audio_on;\n \t#endif\n\n\t/* Dereference commonly used data members for quick access. */\n\tvqap = (VQAHandleP *)vqa;\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\theader = &vqap->Header;\n\tconfig = &vqap->Config;\n\n\tfromwhere = fromwhere;\n\n\t#if(VQAAUDIO_ON)\n\taudio = &vqabuf->Audio;\n\n\t/* Stop audio playback. */\n\taudio_on = (audio->Flags & VQAAUDF_ISPLAYING);\n\tVQA_StopAudio(vqap);\n\t#endif\n\n\t/* Make sure the requested frame is valid and the frame information\n\t * array is allocated before continuing.\n\t */\n\tif ((framenum < header->Frames) && (vqabuf->Foff != NULL)) {\n\n\t\t/* Find and load the most recent palette. */\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\n\t\t\t/* Get the current frame. */\n\t\t\tframe = loader->CurFrame;\n\n\t\t\tfor (i = framenum; i >= 0; i--) {\n\t\t\t\tif (vqabuf->Foff[i] & VQAFINF_PAL) {\n\n\t\t\t\t\t/* Seek to the palette frame. */\n\t\t\t\t\trc = vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_SET,\n\t\t\t\t\t\t\tVQAFRAME_OFFSET(vqabuf->Foff[i]));\n\n\t\t\t\t\t/* Fool the loader into thinking this frame is empty. */\n\t\t\t\t\tif (!rc) {\n\t\t\t\t\t\tloader->NumPartialCB = 0;\n\t\t\t\t\t\tloader->PartialCBSize = 0;\n\t\t\t\t\t\tloader->FullCB = vqabuf->CBData;\n\t\t\t\t\t\tloader->CurCB = vqabuf->CBData;\n\t\t\t\t\t\tloader->CurFrameNum = 0;\n\t\t\t\t\t\tframe->Flags = 0;\n\n\t\t\t\t\t\t/* Load the frame with the palette. */\n\t\t\t\t\t\tif (VQA_LoadFrame(vqa) == 0) {\n\n\t\t\t\t\t\t\t/* Decompress the palette if neccessary.*/\n\t\t\t\t\t\t\tif (frame->Flags & VQAFRMF_PALCOMP) {\n\t\t\t\t\t\t\t\tframe->PaletteSize = LCW_Uncompress((char *)frame->Palette\n\t\t\t\t\t\t\t\t\t\t+ frame->PalOffset, (char *)frame->Palette,\n \t\t\t\t\t\t\t\t\t\tvqabuf->Max_Pal_Size);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tSetPalette(frame->Palette, frame->PaletteSize, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\trc = VQAERR_SEEK;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Build the codebook for the frame we are seeking to. */\n\t\tif (!rc) {\n\n\t\t\t/* Compute the starting group frame of the requested frame. */\n\t\t\tgroup = (framenum / header->Groupsize);\n\t\t\tgroup = (group * header->Groupsize);\n\n\t\t\t/* The codebook for the group we want to goto is found in the previous\n\t\t\t * group, with the exception of the very first group.\n\t\t\t */\n\t\t\tif (group >= header->Groupsize) {\n\t\t\t\tgroup -= header->Groupsize;\n\t\t\t}\n\n\t\t\t/* Seek to the start of the group containing the partial codebooks for\n\t\t\t * the target frame.\n\t\t\t */\n\t\t\tif (!vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_SET,\n\t\t\t\t\tVQAFRAME_OFFSET(vqabuf->Foff[group]))) {\n\n\t\t\t\t/* Throw away any audio frames that were loaded. */\n\t\t\t\t#if(VQAAUDIO_ON)\n\t\t\t\tif ((config->OptionFlags & VQAOPTF_AUDIO)\n\t\t\t\t\t\t&& (audio->Buffer != NULL)) {\n\t\t\t\t\tmemset(audio->IsLoaded, 0, audio->NumAudBlocks * sizeof(short));\n\t\t\t\t\tmemset(audio->Buffer, 0, config->AudioBufSize);\n\n\t\t\t\t\t/* Position the audio buffer to 1/2 second. */\n\t\t\t\t\taudio->AudBufPos = (long)(((audio->SampleRate * audio->Channels)\n\t\t\t\t\t\t\t* (audio->BitsPerSample >> 3)) / 2);\n\n\t\t\t\t\t/* Mark 1/2 second of the audio buffer as loaded. */\n\t\t\t\t\tfor (i = 0; i < (audio->AudBufPos / config->HMIBufSize); i++) {\n\t\t\t\t\t\taudio->IsLoaded[i] = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\t/* Force the loader to the desired frame. */\n\t\t\t\tloader->NumPartialCB = 0;\n\t\t\t\tloader->PartialCBSize = 0;\n\t\t\t\tloader->FullCB = vqabuf->CBData;\n\t\t\t\tloader->CurCB = vqabuf->CBData;\n\t\t\t\tloader->CurFrameNum = group;\n\n\t\t\t\t/* Load frames up to the target frame collecting partial codebooks\n\t\t\t\t * along the way.\n\t\t\t\t */\n\t\t\t\tfor (i = 0; i < (framenum - group); i++) {\n\n\t\t\t\t\t/* Fool the loader into thinking the frame has been drawn. */\n\t\t\t\t\tloader->CurFrame->Flags = 0;\n\n\t\t\t\t\t#if(VQAAUDIO_ON)\n\t\t\t\t\taudio->TempBufLen = 0;\n\t\t\t\t\t#endif\n\n\t\t\t\t\t/* Load the frame. */\n\t\t\t\t\tif ((rc = VQA_LoadFrame(vqa)) != 0) {\n\t\t\t\t\t\tif ((rc != VQAERR_NOBUFFER) && (rc != VQAERR_SLEEPING)) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\trc = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* If everything is okay, then re-prime the buffers. */\n\t\t\t\tif (!rc) {\n\n\t\t\t\t\t/* Mark all the frames except the current one as empty. */\n\t\t\t\t\tloader->CurFrame->Flags = 0;\n\t\t\t\t\tframe = loader->CurFrame->Next;\n\n\t\t\t\t\twhile (frame != loader->CurFrame) {\n\t\t\t\t\t\tframe->Flags = 0;\n\t\t\t\t\t\tframe = frame->Next;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Set the drawer to the current frame and the loader\n\t\t\t\t\t * to the next.\n\t\t\t\t\t */\n\t\t\t\t\tvqabuf->Drawer.CurFrame = loader->CurFrame;\n\n\t\t\t\t\t/* Prime the buffers for the new position. */\n\t\t\t\t\trc = PrimeBuffers(vqa);\n\n\t\t\t\t\t/* An end of file is not considered and error. */\n\t\t\t\t\tif ((rc == 0) || (rc == VQAERR_EOF)) {\n\t\t\t\t\t\trc = framenum;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trc = VQAERR_SEEK;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Restart audio playback. */\n\t#if(VQAAUDIO_ON)\n\tif (audio_on) {\n\t\tVQA_StartAudio(vqap);\n\t}\n\t#endif\n\n\treturn (rc);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     AllocBuffers - Allocate VQA play buffers.\n*\n* SYNOPSIS\n*     VQAData = AllocBuffers(Header, Config)\n*\n*     VQAData *AllocBuffers(VQAHeader *, VQAConfig *);\n*\n* FUNCTION\n*     For those structures that contain buffer pointers (codebook nodes,\n*     frame buffer nodes), enough memory is allocated for both the structure\n*     and its associated buffers, then the buffer pointers are pointed to\n*     the appropriate offset from the structure pointer.  This allows us\n*     to perform only one malloc & free for each node.\n*\n*     Buffers allocated:\n*       - vqa\n*       - vqa->CBData (list)\n*       - vqa->FrameData (list)\n*       - vqa->Drawer.ImageBuf\n*       - vqa->Audio.Buffer\n*       - vqa->Audio.IsLoaded\n*       - vqa->Foff\n*\n* INPUTS\n*     Header - Pointer to VQAHeader structure.\n*     Config - Pointer to VQA configuration structure.\n*\n* RESULT\n*     VQAData - Pointer to initialized VQAData structure.\n*\n****************************************************************************/\n\nstatic VQAData *AllocBuffers(VQAHeader *header, VQAConfig *config)\n{\n\tVQAData      *vqa;\n\tVQACBNode    *cbnode;\n\tVQACBNode    *this_cb;\n\tVQAFrameNode *framenode;\n\tVQAFrameNode *this_frame;\n\tlong         i;\n\n\t/* Check the configuration for valid values. */\n\tif ((config->NumCBBufs == 0) || (config->NumFrameBufs == 0)) {\n\t\treturn (NULL);\n\t}\n\n\t/* Allocate the master structure */\n\tif ((vqa = (VQAData *)malloc(sizeof(VQAData))) == NULL) {\n\t\treturn (NULL);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE VQA DATA STRUCTURES.\n\t *\n\t * Pointers are set to NULL initially, and filled in as the buffers are\n\t * allocated.  The Max buffer sizes are computed with 1K of padding,\n\t * and'd with 0xFFFC to make the size divisible by 4, to ensure DWORD\n\t * alignment.\n\t *-----------------------------------------------------------------------*/\n#if (!VQADIRECT_SOUND)\n\tDPMI_Lock(vqa, sizeof(VQAData));\n#endif\t//VQADIRECT_SOUND\n\n\tmemset(vqa, 0, sizeof(VQAData));\n\tvqa->MemUsed = sizeof(VQAData);\n\tvqa->Drawer.LastTime = (-VQA_TIMETICKS);\n\n\t/* Set maximum codebook size. */\n\tvqa->Max_CB_Size = ((header->CBentries) * header->BlockWidth\n\t\t\t* header->BlockHeight + 250) & 0xFFFC;\n\n\t/* Set maximum palette size. */\n\tvqa->Max_Pal_Size = (768 + 1024) & 0xFFFC;\n\n\t/* Set maximum vector pointers size. */\n\tvqa->Max_Ptr_Size = ((header->ImageWidth / header->BlockWidth)\n\t\t\t* (header->ImageHeight / header->BlockHeight)\n\t\t\t* sizeof(short) + 1024) & 0xFFFC;\n\n\t/* Set the frame number of the frame containing the last codebook. */\n\tvqa->Loader.LastCBFrame = (((header->Frames - 1) / header->Groupsize)\n\t\t\t* header->Groupsize);\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE THE CODEBOOK BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\tfor (i = 0; i < config->NumCBBufs; i++) {\n\n\t\t/* Allocate a codebook node. */\n\t\tcbnode = (VQACBNode *)malloc((sizeof(VQACBNode) + vqa->Max_CB_Size));\n\n\t\t/* If failure then clean up and exit. */\n\t\tif (cbnode == NULL) {\n\t\t\tFreeBuffers(vqa, config, header);\n\t\t\treturn (NULL);\n\t\t}\n\n\t\t/* Lock the buffer to prevent page swapping. */\n#if (!VQADIRECT_SOUND)\n\t\tDPMI_Lock(cbnode, (sizeof(VQACBNode) + vqa->Max_CB_Size));\n#else\t//!VQADIRECT_SOUND\n\t\t/* Make sure the allocated memory is paged in */\n\t\tForce_VM_Page_In(cbnode, (sizeof(VQACBNode) + vqa->Max_CB_Size));\n#endif\t//(!VQADIRECT_SOUND)\n\n\n\n\t\t/* Keep count of the memory usage. */\n\t\tvqa->MemUsed += (long)(sizeof(VQACBNode) + vqa->Max_CB_Size);\n\n\t\t/* Initialize the node */\n\t\tmemset(cbnode, 0, sizeof(VQACBNode));\n\t\tcbnode->Buffer = (unsigned char *)cbnode + sizeof(VQACBNode);\n\n\t\t/* Install the node */\n\t\tif (i == 0) {\n\t\t\tvqa->CBData = cbnode;\n\t\t\tthis_cb = cbnode;\n\t\t} else {\n\t\t\tthis_cb->Next = cbnode;\n\t\t\tthis_cb = cbnode;\n\t\t}\n\t}\n\n\t/* Make the list circular */\n\tcbnode->Next = vqa->CBData;\n\n\t/* Install the Codebook list */\n\tvqa->Loader.CurCB = vqa->CBData;\n\tvqa->Loader.FullCB = vqa->CBData;\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE THE FRAME BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\tfor (i = 0; i < config->NumFrameBufs; i++) {\n\n\t\t/* Allocate a pointer node */\n\t\tframenode = (VQAFrameNode *)malloc((sizeof(VQAFrameNode)\n\t\t\t\t+ vqa->Max_Ptr_Size + vqa->Max_Pal_Size));\n\n\t\t/* If failure then clean up and exit. */\n\t\tif (framenode == NULL) {\n\t\t\tFreeBuffers(vqa, config, header);\n\t\t\treturn (NULL);\n\t\t}\n\n\t\t/* Lock the buffer to prevent page swapping. */\n#if (!VQADIRECT_SOUND)\n\t\tDPMI_Lock(framenode, sizeof(VQAFrameNode) + vqa->Max_Ptr_Size\n\t\t\t\t+ vqa->Max_Pal_Size);\n#else\t//!VQADIRECT_SOUND\n\t\t/* Make sure the allocated memory is paged in */\n\t\tForce_VM_Page_In(framenode, sizeof(VQAFrameNode) + vqa->Max_Ptr_Size\n\t\t\t\t\t\t\t\t+ vqa->Max_Pal_Size);\n#endif\t//(!VQADIRECT_SOUND)\n\n\t\t/* Keep count of the memory usage. */\n\t\tvqa->MemUsed += (long)(sizeof(VQAFrameNode) + vqa->Max_Ptr_Size\n\t\t\t\t+ vqa->Max_Pal_Size);\n\n\t\t/* Initialize the node */\n\t\tmemset(framenode, 0, sizeof(VQAFrameNode));\n\t\tframenode->Pointers = (unsigned char *)framenode + sizeof(VQAFrameNode);\n\t\tframenode->Palette = (unsigned char *)framenode + sizeof(VQAFrameNode)\n\t\t\t\t+ vqa->Max_Ptr_Size;\n\n\t\tframenode->Codebook = vqa->CBData;\n\n\t\t/* Install the node */\n\t\tif (i == 0) {\n\t\t\tvqa->FrameData = framenode;\n\t\t\tthis_frame = framenode;\n\t\t} else {\n\t\t\tthis_frame->Next = framenode;\n\t\t\tthis_frame = framenode;\n\t\t}\n\t}\n\n\t/* Make the list circular */\n\tframenode->Next = vqa->FrameData;\n\n\t/* Install the Frame Buffer list */\n\tvqa->Loader.CurFrame = vqa->FrameData;\n\tvqa->Drawer.CurFrame = vqa->FrameData;\n\tvqa->Flipper.CurFrame = vqa->FrameData;\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE THE IMAGE BUFFERS IF ONE IS NOT ALREADY PROVIDED.\n\t *-----------------------------------------------------------------------*/\n\tif (config->ImageBuf == NULL) {\n\n\t\t/* Allocate our own buffer. */\n\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\tvqa->Drawer.ImageBuf = (unsigned char *)malloc((header->ImageWidth\n\t\t\t\t\t* header->ImageHeight));\n\n\t\t\t/* If the allocation failed we must free up and exit. */\n\t\t\tif (vqa->Drawer.ImageBuf == NULL) {\n\t\t\t\tFreeBuffers(vqa, config, header);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\n\t\t\t/* Lock to prevent page swapping. */\n#if (!VQADIRECT_SOUND)\n\t\t\tDPMI_Lock(vqa->Drawer.ImageBuf,header->ImageWidth*header->ImageHeight);\n#else\t//!VQADIRECT_SOUND\n\t\t\t/* Make sure the allocated memory is paged in */\n\t\t\tForce_VM_Page_In(vqa->Drawer.ImageBuf,header->ImageWidth*header->ImageHeight);\n#endif\t//(!VQADIRECT_SOUND)\n\n\t\t\t/* Plugin image buffer information. */\n\t\t\tvqa->Drawer.ImageWidth = header->ImageWidth;\n\t\t\tvqa->Drawer.ImageHeight = header->ImageHeight;\n\t\t\tvqa->MemUsed += (long)(header->ImageWidth * header->ImageHeight);\n\t\t} else {\n\t\t\tvqa->Drawer.ImageWidth = config->ImageWidth;\n\t\t\tvqa->Drawer.ImageHeight = config->ImageHeight;\n\t\t}\n\t} else {\n\n\t\t/* Use caller provided buffer */\n\t\tvqa->Drawer.ImageBuf = config->ImageBuf;\n\t\tvqa->Drawer.ImageWidth = config->ImageWidth;\n\t\tvqa->Drawer.ImageHeight = config->ImageHeight;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE AND INITIALIZE AUDIO BUFFERS AND STRUCTURES.\n\t *-----------------------------------------------------------------------*/\n\t#if(VQAAUDIO_ON)\n\tif ((header->Flags & VQAHDF_AUDIO)\n\t\t\t&& (config->OptionFlags & VQAOPTF_AUDIO)) {\n\n\t\t/* Dereference audio structure for quick access. */\n\t\tVQAAudio *audio = &vqa->Audio;\n\n\t\t/* Version 1 VQA's only supported 22050 8 bit mono audio. */\n\t\tif (header->Version < VQAHD_VER2) {\n\t\t\taudio->SampleRate = 22050U;\n\t\t\taudio->Channels = 1;\n\t\t\taudio->BitsPerSample = 8;\n\t\t\taudio->BytesPerSec = 22050;\n\t\t} else {\n\t\t\tif ((config->OptionFlags & VQAOPTF_ALTAUDIO)\n\t\t\t\t\t&& (header->Flags & VQAHDF_ALTAUDIO)) {\n\t\t\t\taudio->SampleRate = header->AltSampleRate;\n\t\t\t\taudio->Channels = header->AltChannels;\n\t\t\t\taudio->BitsPerSample = header->AltBitsPerSample;\n\t\t\t} else {\n\t\t\t\taudio->SampleRate = header->SampleRate;\n\t\t\t\taudio->Channels = header->Channels;\n\t\t\t\taudio->BitsPerSample = header->BitsPerSample;\n\t\t\t}\n\n\t\t\taudio->BytesPerSec = ((audio->SampleRate * audio->Channels)\n\t\t\t\t\t* (audio->BitsPerSample >> 3));\n\t\t}\n\n\t\t/* Adjust the HMI buffer to accomodate the amount of data. */\n\t\t#if(0)\n\t\tconfig->HMIBufSize *= (audio->SampleRate / 22050);\n\t\tconfig->HMIBufSize *= audio->Channels * (audio->BitsPerSample >> 3);\n\t\t#endif\n\n\t\t/* The default audio buffer size should be large enough to hold\n\t\t * 1.5 seconds of data.\n\t\t */\n\t\tif (config->AudioBufSize == -1) {\n\n\t\t\t/* Compute the number of HMI buffers that will completly fit into\n\t\t\t * 1.5 seconds of audio data.\n\t\t\t */\n\t\t\ti = ((audio->BytesPerSec+(audio->BytesPerSec/2))/config->HMIBufSize);\n\t\t\tconfig->AudioBufSize = (config->HMIBufSize * i);\n\t\t}\n\n\t\t/* Do not allocate anything if the audio buffer is zero length. */\n\t\tif (config->AudioBufSize > 0) {\n\n\t\t\t/* Allocate an audio buffer if the user did not provide one.\n\t\t\t * Otherwise, use the user supplied buffer.\n\t\t\t */\n\t\t\tif (config->AudioBuf == NULL) {\n\t\t\t\taudio->Buffer = (unsigned char *)malloc(config->AudioBufSize);\n\n\t\t\t\t/* If failure then clean up and exit. */\n\t\t\t\tif (audio->Buffer == NULL) {\n\t\t\t\t\tFreeBuffers(vqa, config, header);\n\t\t\t\t\treturn (NULL);\n\t\t\t\t}\n\n#if (!VQADIRECT_SOUND)\n\t\t\t\tDPMI_Lock(audio->Buffer, config->AudioBufSize);\n#else\t//!VQADIRECT_SOUND\n\t\t\t\t/* Make sure the allocated memory is paged in */\n\t\t\t\tForce_VM_Page_In(audio->Buffer, config->AudioBufSize);\n#endif\t//(!VQADIRECT_SOUND)\n\n\t\t\t\t/* Add audio buffer size to memory usage. */\n\t\t\t\tvqa->MemUsed += config->AudioBufSize;\n\t\t\t} else {\n\t\t\t\taudio->Buffer = config->AudioBuf;\n\t\t\t}\n\n\t\t\t/* Allocate IsLoaded flags */\n\t\t\taudio->NumAudBlocks = (config->AudioBufSize / config->HMIBufSize);\n\t\t\taudio->IsLoaded = (short *)malloc(audio->NumAudBlocks * sizeof(short));\n\n\t\t\t/* If failure then clean up and exit. */\n\t\t\tif (audio->IsLoaded == NULL) {\n\t\t\t\tFreeBuffers(vqa, config, header);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\n\t\t\t/* Lock to prevent page swapping. */\n#if (!VQADIRECT_SOUND)\n\t\t\tDPMI_Lock(audio->IsLoaded, audio->NumAudBlocks * sizeof(short));\n#else\t//!VQADIRECT_SOUND\n\t\t\t/* Make sure the allocated memory is paged in */\n\t\t\tForce_VM_Page_In(audio->IsLoaded, audio->NumAudBlocks * sizeof(short));\n#endif\t//(!VQADIRECT_SOUND)\n\n\t\t\t/* Add IsLoaded flags array to memory usage. */\n\t\t\tvqa->MemUsed += (audio->NumAudBlocks * sizeof(short));\n\n\t\t\t/* Initialize audio IsLoaded flags to false. */\n\t\t\tmemset(audio->IsLoaded, 0, audio->NumAudBlocks * sizeof(short));\n\n\t\t\t/* Allocate temporary staging buffer for the audio frames. */\n\t\t\taudio->TempBufSize = ((audio->BytesPerSec / header->FPS) * 2) + 100;\n\t\t\taudio->TempBuf = (unsigned char *)malloc(audio->TempBufSize);\n\n\t\t\tif (audio->TempBuf == NULL) {\n\t\t\t\tFreeBuffers(vqa, config, header);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\n\t\t\t/* Lock to prevent page swapping. */\n#if (!VQADIRECT_SOUND)\n\t\t\tDPMI_Lock(audio->TempBuf, audio->TempBufSize);\n#else\t//!VQADIRECT_SOUND\n\t\t\t/* Make sure the allocated memory is paged in */\n\t\t\tForce_VM_Page_In(audio->TempBuf, audio->TempBufSize);\n#endif\t//(!VQADIRECT_SOUND)\n\n\t\t\t/* Add temporary buffer size to memory usage. */\n\t\t\tvqa->MemUsed += audio->TempBufSize;\n\t\t}\n\t}\n\t#endif /* VQAAUDIO_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE THE FRAME INFORMATION TABLE IF REQUESTED.\n\t *-----------------------------------------------------------------------*/\n\tvqa->Foff = (long *)malloc(header->Frames * sizeof(long));\n\n\tif (vqa->Foff == NULL) {\n\t\tFreeBuffers(vqa, config, header);\n\t\treturn (NULL);\n\t}\n\n\t/* Lock to prevent page swapping. */\n#if (!VQADIRECT_SOUND)\n\tDPMI_Lock(vqa->Foff, header->Frames * sizeof(long));\n#else\t//!VQADIRECT_SOUND\n\t/* Make sure the allocated memory is paged in */\n\tForce_VM_Page_In(vqa->Foff, header->Frames * sizeof(long));\n#endif\t//(!VQADIRECT_SOUND)\n\n\t/* Keep a running total of memory usage. */\n\tvqa->MemUsed += (header->Frames * sizeof(long));\n\n\treturn (vqa);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     FreeBuffers - Free VQA play buffers.\n*\n* SYNOPSIS\n*     FreeBuffers(VQAData, Config, Header)\n*\n*     void FreeBuffers(VQAData *, VQAConfig *, VQAHeader *);\n*\n* FUNCTION\n*      Free the buffers allocated by AllocBuffers().\n*\n* INPUTS\n*      VQAData - Pointer to VQAData structure.\n*      Config  - Pointer to configuration structure.\n*      Header  - Pointer to movie header structure.\n*\n* RESULT\n*      NONE\n*\n****************************************************************************/\n\nstatic void FreeBuffers(VQAData *vqa, VQAConfig *config, VQAHeader *header)\n{\n\tVQACBNode    *cb_this,\n\t             *cb_next;\n\tVQAFrameNode *frame_this,\n\t             *frame_next;\n\tlong         i;\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE FRAME INFORMATION TABLE.\n\t *-----------------------------------------------------------------------*/\n\tif (vqa->Foff) {\n#if (!VQADIRECT_SOUND)\n\t\tDPMI_Unlock(vqa->Foff, header->Frames * sizeof(long));\n#endif\t//(!VQADIRECT_SOUND)\n\t\tfree(vqa->Foff);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE AUDIO BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\n\t#if(VQAAUDIO_ON)\n\tif ((config->AudioBuf == NULL) && (vqa->Audio.Buffer)) {\n#if (!VQADIRECT_SOUND)\n\t\tDPMI_Unlock(vqa->Audio.Buffer, config->AudioBufSize);\n#endif\t//(!VQADIRECT_SOUND)\n\t\tfree(vqa->Audio.Buffer);\n\t}\n\n\t/* Free the audio segments loaded flag array. */\n\tif (vqa->Audio.IsLoaded) {\n#if (!VQADIRECT_SOUND)\n\t\tDPMI_Unlock(vqa->Audio.IsLoaded,vqa->Audio.NumAudBlocks * sizeof(short));\n#endif\t//(!VQADIRECT_SOUND)\n\t\tfree(vqa->Audio.IsLoaded);\n\t}\n\n\t/* Free the temporary audio buffer. */\n\tif (vqa->Audio.TempBuf) {\n#if (!VQADIRECT_SOUND)\n\t\tDPMI_Unlock(vqa->Audio.TempBuf, vqa->Audio.TempBufSize);\n#endif\t//(!VQADIRECT_SOUND)\n\t\tfree(vqa->Audio.TempBuf);\n\t}\n\t#endif /* VQAAUDIO_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE IMAGE BUFFER ONLY IF WE ALLOCATED IT.\n\t *-----------------------------------------------------------------------*/\n\tif ((config->ImageBuf == NULL) && vqa->Drawer.ImageBuf) {\n#if (!VQADIRECT_SOUND)\n\t\tDPMI_Unlock(vqa->Drawer.ImageBuf,header->ImageWidth*header->ImageHeight);\n#endif\t//(!VQADIRECT_SOUND)\n\t\tfree(vqa->Drawer.ImageBuf);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE FRAME BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\tframe_this = vqa->FrameData;\n\n\tfor (i = 0; i < config->NumFrameBufs; i++) {\n\t\tif (frame_this) {\n\t\t\tframe_next = frame_this->Next;\n#if (!VQADIRECT_SOUND)\n\t\t\tDPMI_Unlock(frame_this, sizeof(VQAFrameNode) + vqa->Max_Ptr_Size\n\t\t\t\t\t+ vqa->Max_Pal_Size);\n#endif\t//(!VQADIRECT_SOUND)\n\t\t\tfree(frame_this);\n\t\t\tframe_this = frame_next;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE CODEBOOK BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\tcb_this = vqa->CBData;\n\n\tfor (i = 0; i < config->NumCBBufs; i++) {\n\t\tif (cb_this) {\n\t\t\tcb_next = cb_this->Next;\n#if (!VQADIRECT_SOUND)\n\t\t\tDPMI_Unlock(cb_this, sizeof(VQACBNode) + vqa->Max_CB_Size);\n#endif\t//(!VQADIRECT_SOUND)\n\t\t\tfree(cb_this);\n\t\t\tcb_this = cb_next;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE VQA DATA STRUCTURES.\n\t *-----------------------------------------------------------------------*/\n#if (!VQADIRECT_SOUND)\n\tDPMI_Unlock(vqa, sizeof(VQAData));\n#endif\t//(!VQADIRECT_SOUND)\n\tfree(vqa);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PrimeBuffers - Pre-Load the internal buffers.\n*\n* SYNOPSIS\n*     Error = PrimeBuffers(VQA)\n*\n*     long = PrimeBuffers(VQAHandle *);\n*\n* FUNCTION\n*     Pre-load the internal buffers in order to give the player some slack\n*     in the playback of large frames.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle structure.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nlong PrimeBuffers(VQAHandle *vqa)\n{\n\tVQAData   *vqabuf;\n\tVQAConfig *config;\n\tlong      rc;\n\tlong      i;\n\n\t/* Dereference commonly used data members for quick access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* Pre-load the buffers */\n\tfor (i = 0; i < config->NumFrameBufs; i++) {\n\t\tif ((rc = VQA_LoadFrame(vqa)) == 0) {\n\t\t\tvqabuf->LoadedFrames++;\n\t\t}\n\t\telse if ((rc != VQAERR_NOBUFFER) && (rc != VQAERR_SLEEPING)) {\n\t\t\treturn (rc);\n\t\t}\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_VQF - Loads a VQ Frame chunk.\n*\n* SYNOPSIS\n*     Error = Load_VQF(VQA, Iffsize)\n*\n*     long Load_VQF(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*     The VQ Frame Chunk contains a set of other chunks (codebooks,\n*     palettes, pointers).  This routine reads the frame's chunk size,\n*     then loops until it's read that many bytes.\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_VQF(VQAHandleP *vqap, unsigned long frame_iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQAFrameNode  *curframe;\n\tChunkHeader   *chunk;\n\tunsigned long iffsize;\n\tunsigned long framesize;\n\tunsigned long bytes_loaded = 0;\n\tVQADrawer     *drawer;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tcurframe = vqabuf->Loader.CurFrame;\n\tframesize = PADSIZE(frame_iffsize);\n\tdrawer = &(vqap->VQABuf->Drawer);\n\tchunk = &vqabuf->Loader.CurChunkHdr;\n\n\t/*-------------------------------------------------------------------------\n\t * FRAME LOADING LOOP.\n\t *-----------------------------------------------------------------------*/\n\twhile (bytes_loaded < framesize) {\n\n\t\t/* Read chunk ID */\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, chunk, 8)) {\n\t\t\treturn (VQAERR_EOF);\n\t\t}\n\n\t\tiffsize = REVERSE_LONG(chunk->size);\n\t\tbytes_loaded += 8;\n\t\tbytes_loaded += PADSIZE(iffsize);\n\n\t\t/* Handle each chunk type */\n\t\tswitch (chunk->id) {\n\n\t\t\t/* Full uncompressed codebook */\n\t\t\tcase ID_CBF0:\n\t\t\t\tif (Load_CBF0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Full compressed codebook */\n\t\t\tcase ID_CBFZ:\n\t\t\t\tif (Load_CBFZ(vqap, iffsize)) {\n\t\t\t\t \treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Partial uncompressed codebook */\n\t\t\tcase ID_CBP0:\n\t\t\t\tif (Load_CBP0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Partial compressed codebook */\n\t\t\tcase ID_CBPZ:\n\t\t\t\tif (Load_CBPZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed palette */\n\t\t\tcase ID_CPL0:\n\t\t\t\tif (Load_CPL0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* If this is the first occurance of a palette then store it now.\n\t\t\t\t * This functionality is needed for Monopoly!\n\t\t\t\t */\n\t\t\t\tif (drawer->CurPalSize == 0) {\n\t\t\t\t\tmemcpy(drawer->Palette_24,curframe->Palette,curframe->PaletteSize);\n\t\t\t\t\tdrawer->CurPalSize = curframe->PaletteSize;\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as having a palette. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_PALETTE;\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed palette */\n\t\t\tcase ID_CPLZ:\n\t\t\t\tif (Load_CPLZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* If this is the first occurance of a palette then store it now.\n\t\t\t\t * This functionality is needed for Monopoly!\n\t\t\t\t */\n\t\t\t\tif (drawer->CurPalSize == 0) {\n\t\t\t\t\tdrawer->CurPalSize = LCW_Uncompress((char *)curframe->Palette\n\t\t\t\t\t\t\t+ curframe->PalOffset, (char *)drawer->Palette_24,\n\t\t\t\t\t\t\tvqabuf->Max_Pal_Size);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as having a palette. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_PALETTE;\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed pointer data */\n\t\t\tcase ID_VPT0:\n\t\t\t\tif (Load_VPT0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed pointer data */\n\t\t\tcase ID_VPTZ:\n\t\t\tcase ID_VPTD:\n\t\t\t\tif (Load_VPTZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed pointer data */\n\t\t\tcase ID_VPTK:\n\t\t\t\tif (Load_VPTZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as being key. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_KEY;\n\t\t\t\tbreak;\n\n\t\t\t/* An unknown chunk in the video frame is an error. */\n\t\t\tdefault:\n\t\t\t\treturn (VQAERR_READ);\n\t\t}\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_FINF - Load Frame Info chunk.\n*\n* SYNOPSIS\n*     Error = Load_FINF(VQA, Iffsize)\n*\n*     long Load_FINF(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*     Load FINF chunk if buffer available, otherwise skip it.\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_FINF(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData *vqabuf;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\n\t/* Load the frame information table if we need to, otherwise we will\n\t * skip it.\n\t */\n\tif (vqabuf->Foff != NULL) {\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, vqabuf->Foff,\n\t\t\t\tPADSIZE(iffsize))) {\n\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\t} else {\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\tPADSIZE(iffsize))) {\n\t\t\treturn (VQAERR_SEEK);\n\t\t}\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_VQHD - Load VQA header chunk.\n*\n* SYNOPSIS\n*     Error = Load_VQHD(VQA, Iffsize)\n*\n*     long Load_VQHD(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_VQHD(VQAHandleP *vqap, unsigned long iffsize)\n{\n\t/* Read the header */\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, &vqap->Header,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Reconfigure the Drawer for the new settings */\n\tVQA_Configure_Drawer(vqap);\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CBF0 - Load full uncompressed codebook.\n*\n* SYNOPSIS\n*     Error = Load_CBF0(VQA, Iffsize)\n*\n*     long Load_CBF0(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CBF0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQALoader *loader;\n\tVQACBNode *curcb;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tloader = &vqap->VQABuf->Loader;\n\tcurcb = loader->CurCB;\n\n\t/* Read into the start of the buffer */\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, curcb->Buffer,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Reset the partial codebook counter. */\n\tloader->NumPartialCB = 0;\n\n\t/* Flag this codebook as uncompressed. */\n\tcurcb->Flags &= (~VQACBF_CBCOMP);\n\tcurcb->CBOffset = 0;\n\n\t/* Clock pointers to next CB Buffer. */\n\tloader->FullCB = curcb;\n\tloader->FullCB->Flags &= (~VQACBF_DOWNLOADED);\n\tloader->CurCB = curcb->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CBFZ - Load full compressed codebook.\n*\n* SYNOPSIS\n*     Error = Load_CBFZ(VQA, Iffsize)\n*\n*     long Load_CBFZ(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CBFZ(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQALoader     *loader;\n\tVQACBNode     *curcb;\n\tvoid          *buffer;\n\tunsigned long padsize;\n\tunsigned long lcwoffset;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tloader = &vqap->VQABuf->Loader;\n\tcurcb = loader->CurCB;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* Load the codebook into the end of the buffer. */\n\tlcwoffset = vqap->VQABuf->Max_CB_Size - padsize;\n\tbuffer = curcb->Buffer + lcwoffset;\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Reset the partial codebook counter. */\n\tloader->NumPartialCB = 0;\n\n\t/* Flag this codebook as compressed */\n\tcurcb->Flags |= VQACBF_CBCOMP;\n\tcurcb->CBOffset = lcwoffset;\n\n\t/* Clock pointers to next CB Buffer */\n\tloader->FullCB = curcb;\n\tloader->FullCB->Flags &= (~VQACBF_DOWNLOADED);\n\tloader->CurCB = curcb->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CBP0 - Load partial uncompressed codebook.\n*\n* SYNOPSIS\n*     Error = Load_CBP0(VQA, Iffsize)\n*\n*     long Load_CBP0(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CBP0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData   *vqabuf;\n\tVQALoader *loader;\n\tVQACBNode *curcb;\n\tvoid      *buffer;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\tcurcb = loader->CurCB;\n\n\t/*-------------------------------------------------------------------------\n\t * ASSEMBLY PARTIAL CODEBOOKS.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Read the partial codebook into the next position in the buffer. */\n\tbuffer = curcb->Buffer + loader->PartialCBSize;\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Accumulate the partial codebook values. */\n\tloader->PartialCBSize += iffsize;\n\tloader->NumPartialCB++;\n\n\t/*-------------------------------------------------------------------------\n\t * PROCESS FULL CODEBOOK.\n\t *-----------------------------------------------------------------------*/\n\tif (loader->NumPartialCB == vqap->Header.Groupsize) {\n\n\t\t/* Reset the codebook accumulator values */\n\t\tloader->NumPartialCB = 0;\n\t\tloader->PartialCBSize = 0;\n\n\t\t/* Flag this codebook as uncompressed */\n\t\tcurcb->Flags &= (~VQACBF_CBCOMP);\n\t\tcurcb->CBOffset = 0;\n\n\t\t/* Go to the next codebook buffer */\n\t\tloader->FullCB = curcb;\n\t\tloader->FullCB->Flags &= (~VQACBF_DOWNLOADED);\n\t\tloader->CurCB = curcb->Next;\n\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CBPZ - Load partial compressed codebook.\n*\n* SYNOPSIS\n*     Error = Load_CBPZ(VQA, Iffsize)\n*\n*     long Load_CBPZ(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CBPZ(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQACBNode     *curcb;\n\tvoid          *buffer;\n\tunsigned long padsize;\n\n\t/* Dereference commonly used data members for quicker access */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\tcurcb = loader->CurCB;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* Attempt to compute the LCW offset into the codebook buffer by\n\t * multiplying the size of this chunk by the # frames/group, and adding\n\t * a small fudge factor on, then subtracting that from the CB buffer size.\n\t */\n\tif (loader->PartialCBSize == 0) {\n\t\tcurcb->CBOffset = (vqabuf->Max_CB_Size\n\t\t\t\t- (padsize * vqap->Header.Groupsize + 100));\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * ASSEMBLE PARTIAL CODEBOOKS.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Read the partial codebook into the next position in the buffer. */\n\tbuffer = ((curcb->Buffer + curcb->CBOffset) + loader->PartialCBSize);\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Accumulate partial codebook values */\n\tloader->PartialCBSize += iffsize;\n\tloader->NumPartialCB++;\n\n\t/*-------------------------------------------------------------------------\n\t * PROCESS FULL CODEBOOK.\n\t *-----------------------------------------------------------------------*/\n\tif (loader->NumPartialCB == vqap->Header.Groupsize) {\n\n\t\t/* Reset the codebook accumulator values. */\n\t\tloader->NumPartialCB = 0;\n\t\tloader->PartialCBSize = 0;\n\n\t\t/* Flag this codebook as compressed. */\n\t\tcurcb->Flags |= VQACBF_CBCOMP;\n\n\t\t/* Go to the next codebook buffer */\n\t\tloader->FullCB = curcb;\n\t\tloader->FullCB->Flags &= (~VQACBF_DOWNLOADED);\n\t\tloader->CurCB = curcb->Next;\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CPL0 - Load an uncompressed palette.\n*\n* SYNOPSIS\n*     Error = Load_CPL0(VQA, Iffsize)\n*\n*     long Load_CPL0(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CPL0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAFrameNode *curframe;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tcurframe = vqap->VQABuf->Loader.CurFrame;\n\n\t/* Read the palette into the palette buffer */\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, curframe->Palette,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Flag the palette as uncompressed. */\n\tcurframe->Flags &= ~VQAFRMF_PALCOMP;\n\tcurframe->PalOffset = 0;\n\tcurframe->PaletteSize = iffsize;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CPLZ - Load compressed palette.\n*\n* SYNOPSIS\n*     Error = Load_CPLZ(VQA, Iffsize)\n*\n*     long Load_CPLZ(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CPLZ(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAFrameNode  *curframe;\n\tvoid          *buffer;\n\tunsigned long padsize;\n\tunsigned long lcwoffset;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tcurframe = vqap->VQABuf->Loader.CurFrame;\n\tpadsize = PADSIZE(iffsize);\n\n \t/* Read the palette into the end of the palette buffer. */\n\tlcwoffset = vqap->VQABuf->Max_Pal_Size - padsize;\n\tbuffer = curframe->Palette + lcwoffset;\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Flag this palette as compressed. */\n\tcurframe->Flags |= VQAFRMF_PALCOMP;\n\tcurframe->PalOffset = lcwoffset;\n\tcurframe->PaletteSize = iffsize;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_VPT0 - Load uncompressed pointers.\n*\n* SYNOPSIS\n*     Error = Load_VPT0(VQA, Iffsize)\n*\n*     long Load_VPT0(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_VPT0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAFrameNode *curframe;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tcurframe = vqap->VQABuf->Loader.CurFrame;\n\n\t/* Read the pointers into start of the pointer buffer. */\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, curframe->Pointers,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Flag this frame as uncompressed */\n\tcurframe->Flags &= ~VQAFRMF_PTRCOMP;\n\tcurframe->PtrOffset = 0;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_VPTZ - Load compressed pointers.\n*\n* SYNOPSIS\n*     Error = Load_VPTZ(VQA, Iffsize)\n*\n*     long Load_VPTZ(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_VPTZ(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAFrameNode  *curframe;\n\tvoid          *buffer;\n\tunsigned long padsize;\n\tunsigned long lcwoffset;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tcurframe = vqap->VQABuf->Loader.CurFrame;\n\tpadsize = PADSIZE(iffsize);\n\tlcwoffset = vqap->VQABuf->Max_Ptr_Size - padsize;\n\n\t/* Read the pointers into end of the pointer buffer. */\n\tbuffer = curframe->Pointers + lcwoffset;\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Flag this frame as compressed. */\n\tcurframe->Flags |= VQAFRMF_PTRCOMP;\n\tcurframe->PtrOffset = lcwoffset;\n\n\treturn (0);\n}\n\n\n#if(VQAAUDIO_ON)\n/****************************************************************************\n*\n* NAME\n*     Load_SND0 - Load uncompressed sound chunk.\n*\n* SYNOPSIS\n*     Error = Load_SND0(VQA, Iffsize)\n*\n*     long Load_SND0(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*     This routine normally loads the chunk into the TempBuf, unless the\n*     chunk is larger than the temp buffer size, in which case it puts it\n*     directly into the audio buffer itself.  This assumes that the only\n*     such chunk will be the first audio chunk!\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_SND0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tunsigned long padsize;\n\tlong          i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\taudio = &vqabuf->Audio;\n\tconfig = &vqap->Config;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* If sound is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, just skip the chunk.\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0)\n\t\t\t|| (vqap->vocfh != -1) || (audio->Buffer == NULL)) {\n\t#else  /* VQAVOC_ON */\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0)\n\t\t\t|| (audio->Buffer == NULL)) {\n\t#endif /* VQAVOC_ON */\n\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\tpadsize)) {\n\t\t\treturn (VQAERR_SEEK);\n\t\t} else {\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\t/* Read large startup chunk directly into AudioBuf */\n\tif ((padsize > audio->TempBufSize) && (audio->AudBufPos == 0)) {\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, audio->Buffer,\n\t\t\t\tpadsize)) {\n\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\n\t\taudio->AudBufPos += iffsize;\n\n\t\t/* Flag the audio frame flags as loaded for the initial audio frame. */\n\t\tfor (i = 0; i < (iffsize / config->HMIBufSize); i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t} else {\n\n\t\t/*  Read data into TempBuf */\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, audio->TempBuf,\n\t\t\t\tpadsize)) {\n\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\t}\n\n\t/* Set the TempBufLen */\n\taudio->TempBufLen = iffsize;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_SND1 - Load compressed sound chunk.\n*\n* SYNOPSIS\n*     Error = Load_SND1(VQA, Iffsize)\n*\n*     long Load_SND1(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*     This routine normally loads the chunk into the TempBuf, unless the\n*     chunk is larger than the temp buffer size, in which case it puts it\n*     directly into the audio buffer itself.  This assumes that the only\n*     such chunk will be the first audio chunk!\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_SND1(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tunsigned char *loadbuf;\n\tunsigned long padsize;\n\tZAPHeader     zap;\n\tlong          i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\taudio = &vqabuf->Audio;\n\tconfig = &vqap->Config;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* If sound is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, just skip the chunk\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (vqap->vocfh != -1)\n\t\t\t|| (audio->Buffer == NULL)) {\n\t#else\n\tif (((config->OptionFlags & VQAOPTF_AUDIO)==0) || (audio->Buffer==NULL)) {\n\t#endif /* VQAVOC_ON */\n\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\tpadsize)) {\n\t\t\treturn (VQAERR_SEEK);\n\t\t} else {\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\t/* Read the ZAP audio frame header. */\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, &zap,\n\t\t\tsizeof(ZAPHeader))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Adjust chunk size */\n\tpadsize -= sizeof(ZAPHeader);\n\n\t/* Read large startup chunk directly into AudioBuf */\n\tif ((zap.UnCompSize > audio->TempBufSize) && (audio->AudBufPos == 0)) {\n\n\t\t/* Load RAW uncompressed data. */\n\t\tif (zap.UnCompSize == zap.CompSize) {\n\t\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, audio->Buffer,\n\t\t\t\t\tpadsize)) {\n\n\t\t\t\treturn (VQAERR_READ);\n\t\t\t}\n\t\t} else {\n\n\t\t\t/* Load compressed data into the end of the buffer. */\n\t\t\tloadbuf = (audio->Buffer + config->AudioBufSize) - padsize;\n\n\t\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, loadbuf,\n\t\t\t\t\tpadsize)) {\n\n\t\t\t\treturn (VQAERR_READ);\n\t\t\t}\n\n\t\t\t/* Uncompress the audio frame. */\n\t\t\tAudioUnzap(loadbuf, audio->Buffer, zap.UnCompSize);\n\t\t}\n\n\t\t/* Set buffer positions & flags */\n\t\taudio->AudBufPos += zap.UnCompSize;\n\n\t\tfor (i = 0; i < (zap.UnCompSize / config->HMIBufSize); i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t}\n\n\t/* Load an audio frame. */\n\tif (zap.UnCompSize == zap.CompSize) {\n\n\t\t/* If the frame is uncompressed the load it in directly. */\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, audio->TempBuf,\n\t\t\t\tpadsize)) {\n\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\t} else {\n\n\t\t/* Load the audio frame into the end of the buffer. */\n\t\tloadbuf = ((audio->TempBuf + audio->TempBufSize) - padsize);\n\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, loadbuf, padsize)) {\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\n\t\t/* Uncompress the audio frame. */\n\t\tAudioUnzap(loadbuf, audio->TempBuf, zap.UnCompSize);\n\t}\n\n\t/* Set the TempBufLen */\n\taudio->TempBufLen = zap.UnCompSize;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_SND2 - Load ADPCM compressed sound chunk.\n*\n* SYNOPSIS\n*     Error = Load_SND2(VQA, Iffsize)\n*\n*     long Load_SND2(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*     This routine normally loads the chunk into the TempBuf, unless the\n*     chunk is larger than the temp buffer size, in which case it puts it\n*     directly into the audio buffer itself.  This assumes that the only\n*     such chunk will be the first audio chunk!\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_SND2(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tunsigned char *loadbuf;\n\tunsigned long padsize;\n\tunsigned long uncomp_size;\n\tlong          i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\taudio = &vqabuf->Audio;\n\tconfig = &vqap->Config;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* If sound is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, just skip the chunk\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (vqap->vocfh != -1)\n\t\t\t|| (audio->Buffer == NULL)) {\n\t#else  /* VQAVOC_ON */\n\tif (((config->OptionFlags & VQAOPTF_AUDIO)==0) || (audio->Buffer==NULL)) {\n\t#endif /* VQAVOC_ON */\n\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\tpadsize)) {\n\t\t\treturn (VQAERR_SEEK);\n\t\t} else {\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\tuncomp_size = iffsize * (audio->BitsPerSample / 4);\n\n\t/* Read large startup chunk directly into AudioBuf */\n\tif ((uncomp_size > audio->TempBufSize) && (audio->AudBufPos == 0)) {\n\n\t\t/* Load compressed data into the end of the buffer. */\n\t\tloadbuf = (audio->Buffer + config->AudioBufSize) - padsize;\n\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, loadbuf, padsize)) {\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\n\t\t/* Uncompress the audio frame. */\n\t\taudio->ADPCM_Info.lpSource = (char *)loadbuf;\n\t\taudio->ADPCM_Info.lpDest = (char *)audio->Buffer;\n\t\tVQA_sosCODECDecompressData(&audio->ADPCM_Info, uncomp_size);\n\n\t\t/* Set buffer positions & flags */\n\t\taudio->AudBufPos += uncomp_size;\n\n\t\tfor (i = 0; i < (uncomp_size / config->HMIBufSize); i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t}\n\n\t/* Load an audio frame. */\n\tloadbuf = ((audio->TempBuf + audio->TempBufSize) - padsize);\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, loadbuf, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Uncompress the audio frame. */\n\taudio->ADPCM_Info.lpSource = (char *)loadbuf;\n\taudio->ADPCM_Info.lpDest = (char *)audio->TempBuf;\n\tVQA_sosCODECDecompressData(&audio->ADPCM_Info, uncomp_size);\n\n\t/* Set the TempBufLen */\n\taudio->TempBufLen = uncomp_size;\n\n\treturn (0);\n}\n\n\n#if(VQAVOC_ON)\n/****************************************************************************\n*\n* NAME\n*     Load_AudFrame - Loads blocks from seperate VOC file.\n*\n* SYNOPSIS\n*     Load_AudFrame(VQA)\n*\n*     void Load_AudFrame(VQAHandleP *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to private VQA handle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Load_AudFrame(VQAHandleP *vqap)\n{\n\tVQAData     *vqabuf;\n\tVQALoader   *loader;\n\tVQAAudio    *audio;\n\tVQAConfig   *config;\n\tstatic long lastplayblock = -1;\n\tstatic long myblock = 0;\n\tstatic long firsttime = 1;\n\tlong        numblocks;\n\tlong        i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\taudio = &vqabuf->Audio;\n\tconfig = &vqap->Config;\n\n\t/* Do nothing if no buffer */\n\tif (audio->Buffer == NULL) {\n\t\treturn;\n\t}\n\n\t/* If this is the first time we're called, pre-load the 1st 'n' audio\n\t * blocks, where 'n' is half the total audio buffer size; this way, we'll\n\t * always stay ahead of HMI.\n\t */\n\tif (firsttime) {\n\t\tnumblocks = (audio->NumAudBlocks / 2);\n\t\tread(vqap->vocfh, audio->Buffer, config->HMIBufSize * numblocks);\n\t\taudio->AudBufPos += config->HMIBufSize * numblocks;\n\n\t\tif (audio->AudBufPos >= config->AudioBufSize) {\n\t\t\taudio->AudBufPos = 0;\n\t\t}\n\n\t\tfor (i = 0; i < numblocks; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\tmyblock += numblocks;\n\n\t\tif (myblock >= audio->NumAudBlocks) {\n\t\t\tmyblock = 0;\n\t\t}\n\n\t\tfirsttime = 0;\n\t}\n\n\t/* If HMI's block has changed, load the next block & mark it as loaded */\n\tif (audio->PlayPosition / config->HMIBufSize != lastplayblock) {\n\n\t\t/* update HMI's last known block position */\n\t\tlastplayblock = audio->PlayPosition / config->HMIBufSize;\n\n\t\t/* read the VOC data */\n\t\tread(vqap->vocfh, (audio->Buffer + myblock * config->HMIBufSize),\n\t\t\t\tconfig->HMIBufSize);\n\n\t\taudio->AudBufPos += config->HMIBufSize;\n\n\t\tif (audio->AudBufPos >= config->AudioBufSize) {\n\t\t\taudio->AudBufPos = 0;\n\t\t}\n\n\t\t/* set the IsLoaded flags */\n\t\taudio->IsLoaded[myblock] = 1;\n\n\t\t/* increment my block counter */\n\t\tmyblock++;\n\n\t\tif (myblock >= audio->NumAudBlocks) {\n\t\t\tmyblock = 0;\n\t\t}\n\t}\n}\n#endif /* VQAVOC_ON */\n#endif /* VQAAUDIO_ON */\n\n"
  },
  {
    "path": "WINVQ/VQA32/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQAPlay 32-bit library.\n#\n# FILE\n#     makefile (Watcom C/C++ 10.0a)\n#\n# DESCRIPTION\n#     Makefile for generating the 32-bit VQAPlay library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n# \n# DATE\n#     February 10, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     WATCOM - Watcom C installation path.\n#\n#****************************************************************************\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n.OPTIMIZE\n.ERASE\n\n#----------------------------------------------------------------------------\n# PROJECTS DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJ    = ..\nWATCOM = C:\\WATCOM\nPRJNAME = vqa32wp\nPRJDIR  = $(PRJ)\\VQA32\n\nOBJECTS = &\n\tconfig.obj &\n\ttask.obj &\n\tloader.obj &\n\tdrawer.obj &\n\taudio.obj &\n\tmonodisp.obj &\n\tdstream.obj &\n\tunvqbuff.obj &\n\tunvqvesa.obj &\n\tvertag.obj &\n\tcaption.obj &\n#\tunvqxmde.obj\n\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!ifdef %LIB\nLIBPATH = $(PRJ)\\LIB;$(%LIB)\n!else\nLIBPATH = $(PRJ)\\LIB;$(WATCOM)\\LIB386\n!endif\n\n!ifdef %INCLUDE\nINCLUDEPATH = $(PRJ)\\INCLUDE;$(%INCLUDE)\n!else\nINCLUDEPATH = $(PRJ)\\INCLUDE;$(WATCOM)\\H\n!endif\n\npath_c   = .\\\npath_cpp = .\\\npath_h   = .\\\npath_asm = .\\\npath_i   = .\\\npath_obj = .\\O\npath_lib = $(PRJ)\\LIB\npath_exe = .\\\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULE EXTENSIONS AND PATHS\n#----------------------------------------------------------------------------\n\n.EXTENSIONS :\n.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i\n\n.c : $(path_c)\n.cpp : $(path_cpp)\n.h : $(path_h)\n.asm : $(path_asm)\n.i : $(path_i)\n.obj : $(path_obj)\n.lib : $(path_lib)\n.exe : $(path_exe)\n\n#----------------------------------------------------------------------------\n# Tools/commands & configurations\n#----------------------------------------------------------------------------\n\nCC_CMD   = wcc386\nCCP_CMD  = wpp386\nASM_CMD  = tasm32\nLINK_CMD = wlink\nLIB_CMD  = wlib\n\nCC_OPTS  = -i$(INCLUDEPATH) -j -zp1 -5r -mf -oaeilrt -s -zq -d1\nASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /i$(PRJ)\\INCLUDE\\VQM32 /dPHARLAP_TNT=0\nLIB_OPTS = /b /c /q\nLINK_CFG = $(PRJNAME).lnk\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall : $(PRJNAME).lib .SYMBOLIC\n\n$(PRJNAME).lib : $(OBJECTS) .SYMBOLIC\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj :\n  $(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.cpp.obj :\n  $(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\\$^.\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\nupdate: .SYMBOLIC\n\t@echo Updating VQAPlay32 header files!\n\t@copy vqaplay.h ..\\include\\vqa32 >NUL\n\t@copy vqafile.h ..\\include\\vqa32 >NUL\n\n"
  },
  {
    "path": "WINVQ/VQA32/MAKEFILE.BAK",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQAPlay 32-bit library.\n#\n# FILE\n#     makefile (Watcom C/C++ 10.0a)\n#\n# DESCRIPTION\n#     Makefile for generating the 32-bit VQAPlay library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n# \n# DATE\n#     February 10, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     WATCOM - Watcom C installation path.\n#\n#****************************************************************************\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n.OPTIMIZE\n.ERASE\n\n#----------------------------------------------------------------------------\n# PROJECTS DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJ    = ..\nWATCOM = C:\\WATCOM\nPRJNAME = vqa32wp\nPRJDIR  = $(PRJ)\\VQA32\n\nOBJECTS = &\n\tconfig.obj &\n\ttask.obj &\n\tloader.obj &\n\tdrawer.obj &\n\taudio.obj &\n\tmonodisp.obj &\n\tdstream.obj &\n\tunvqbuff.obj &\n\tunvqvesa.obj &\n\tvertag.obj &\n\tcaption.obj &\n#\tunvqxmde.obj\n\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!ifdef %LIB\nLIBPATH = $(PRJ)\\LIB;$(%LIB)\n!else\nLIBPATH = $(PRJ)\\LIB;$(WATCOM)\\LIB386\n!endif\n\n!ifdef %INCLUDE\nINCLUDEPATH = $(PRJ)\\INCLUDE;$(%INCLUDE)\n!else\nINCLUDEPATH = $(PRJ)\\INCLUDE;$(WATCOM)\\H\n!endif\n\npath_c   = .\\\npath_cpp = .\\\npath_h   = .\\\npath_asm = .\\\npath_i   = .\\\npath_obj = .\\O\npath_lib = $(PRJ)\\LIB\npath_exe = .\\\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULE EXTENSIONS AND PATHS\n#----------------------------------------------------------------------------\n\n.EXTENSIONS :\n.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i\n\n.c : $(path_c)\n.cpp : $(path_cpp)\n.h : $(path_h)\n.asm : $(path_asm)\n.i : $(path_i)\n.obj : $(path_obj)\n.lib : $(path_lib)\n.exe : $(path_exe)\n\n#----------------------------------------------------------------------------\n# Tools/commands & configurations\n#----------------------------------------------------------------------------\n\nCC_CMD   = wcc386\nCCP_CMD  = wpp386\nASM_CMD  = tasm32\nLINK_CMD = wlink\nLIB_CMD  = wlib\n\nCC_OPTS  = -i$(INCLUDEPATH) -j -zp1 -5r -mf -oaeilrt -s -zq -d2\nASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /i$(PRJ)\\INCLUDE\\VQM32 /dPHARLAP_TNT=0\nLIB_OPTS = /b /c /q\nLINK_CFG = $(PRJNAME).lnk\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall : $(PRJNAME).lib .SYMBOLIC\n\n$(PRJNAME).lib : $(OBJECTS) .SYMBOLIC\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj :\n  $(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.cpp.obj :\n  $(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\\$^.\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\nupdate: .SYMBOLIC\n\t@echo Updating VQAPlay32 header files!\n\t@copy vqaplay.h ..\\include\\vqa32 >NUL\n\t@copy vqafile.h ..\\include\\vqa32 >NUL\n\n\u001a"
  },
  {
    "path": "WINVQ/VQA32/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQAPlay32 library.\n#\n# FILE\n#     makefile (Borland/TNT)\n#\n# DESCRIPTION\n#     Makefile for generating the 32-bit VQAPlay library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n#\n# DATE\n#     Feburary 7, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     BCDIR  - Borland C installation path.\n#     TNTDIR - Pharlap/TNT installation path.\n#\n#****************************************************************************\n\n.AUTODEPEND\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n!if !$d(PRJ) || !$d(PRJVCS) || !$d(BCDIR) || !$d(TNTDIR) \n!error Environment not configured.\n!endif\n\n#----------------------------------------------------------------------------\n# PROJECTS DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJNAME\t= vqa32bp\nPRJDIR = $(PRJ)\\VQA32\n\nOBJECTS = \\\n\tconfig.obj \\\n\ttask.obj \\\n\tloader.obj \\\n\tdrawer.obj \\\n\taudio.obj \\\n\tmonodisp.obj \\\n\tdstream.obj \\\n\tunvqbuff.obj \\\n\tunvqvesa.obj \\\n\tvertag.obj \\\n\tcaption.obj \\\n#\tunvqxmde.obj \\\n\nPRJLIBS = \\\n\tvqm32bp.lib \\\n\t\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!if $d(LIB)\nLIBPATH = $(PRJ)\\LIB;$(LIB)\n!else\nLIBPATH = $(PRJ)\\LIB;$(TNTDIR)\\LIB;$(BCDIR)\\LIB\n!endif\n\n!if $d(INCLUDE)\nINCLUDEPATH\t= $(PRJ)\\INCLUDE;$(INCLUDE)\n!else\nINCLUDEPATH\t= $(PRJ)\\INCLUDE;$(TNTDIR)\\INCLUDE;$(BCDIR)\\INCLUDE\n!endif\n\n.path.asm = $(PRJDIR)\n.path.c   = $(PRJDIR)\n.path.cpp = $(PRJDIR)\n.path.h   = $(PRJDIR)\n.path.exe = $(PRJDIR)\n.path.obj = $(PRJDIR)\\OBJ\n.path.sym = $(PRJDIR)\\OBJ\n.path.lib = $(PRJ)\\LIB\n\n#----------------------------------------------------------------------------\n# TOOLS, COMMAND AND CONFIGURATIONS\n#----------------------------------------------------------------------------\n\nCC_CMD   = bcc32\nASM_CMD  = tasm32\nLINK_CMD = tlink32\nLIB_CMD  = tlib\n\nCC_CFG    = bcc32.cfg\nASM_CFG   = tasm32.cfg\nLINK_CFG  = tlink32.cfg\nLIB_CFG   = tlib.cfg\nCFG_FILES = $(CC_CFG) $(ASM_CFG) $(LINK_CFG) $(LIB_CFG)\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall: $(PRJNAME).lib\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj:\n\t$(CC_CMD) -P- -n$(.path.obj) {$< }\n\n.cpp.obj:\n\t$(CC_CMD) -P -n$(.path.obj) {$< }\n\n.asm.obj:\n\t$(ASM_CMD) @$(ASM_CFG) $<,$(.path.obj)\\$&\n\n#----------------------------------------------------------------------------\n# BUILD LIBRARY\n#----------------------------------------------------------------------------\n\n$(PRJNAME).lib: $(OBJECTS)\n\t- @del $(.path.lib)\\$(PRJNAME).lib >&NUL\n\t$(LIB_CMD) $(.path.lib)\\$(PRJNAME).lib @$(LIB_CFG) @&&|\n-+$(**: = -+)\n|\n\t- @copy vqaplay.h $(PRJ)\\INCLUDE\\VQA32 >&NUL\n\t- @copy vqafile.h $(PRJ)\\INCLUDE\\VQA32 >&NUL\n\n#----------------------------------------------------------------------------\n# ALL OBJECTS DEPEND ON THE CONFIGURATION FILES\n#----------------------------------------------------------------------------\n\n$(OBJECTS):\t$(CFG_FILES)\n\n#----------------------------------------------------------------------------\n# COMPILER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(CC_CFG): makefile\n\tcopy &&|\n-c\n-3\n-d\n-H=$(.path.sym)\\headers.sym\n-wpro\n-weas\n-wpre\n-I$(INCLUDEPATH)\n-DPHARLAP_TNT=1\n#-v\n| $(CC_CFG)\n \n#----------------------------------------------------------------------------\n# ASSEMBLER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(ASM_CFG): makefile\n\tcopy &&|\n/t\n/m\n/w+\n/jJUMPS\n/ml\n/p\n/z\n/i$(PRJ)\\INCLUDE\\VQM32\n/zi\n/dPHARLAP_TNT=1\n| $(ASM_CFG)\n\n#----------------------------------------------------------------------------\n# LINKER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(LINK_CFG): makefile\n\tcopy &&|\n/c\n/m\n/Gm\n-L$(LIBPATH)\n-v\n| $(LINK_CFG)\n\n#----------------------------------------------------------------------------\n# LIBRARIAN CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(LIB_CFG):\tmakefile\n\tcopy &&|\n/C /E\n| $(LIB_CFG)\n\n"
  },
  {
    "path": "WINVQ/VQA32/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQAPlay 32-bit library.\n#\n# FILE\n#     makefile (Watcom C/C++ 10.0a)\n#\n# DESCRIPTION\n#     Makefile for generating the 32-bit VQAPlay library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n# \n# DATE\n#     February 10, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     WATCOM - Watcom C installation path.\n#\n#****************************************************************************\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n!ifndef %PRJ || %PRJVCS || %WATCOM\n!error Environment not configured.\n!endif\n\n.OPTIMIZE\n.ERASE\n\n#----------------------------------------------------------------------------\n# PROJECTS DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJNAME = vqa32wp\nPRJDIR  = $(%PRJ)\\VQA32\n\nOBJECTS = &\n\tconfig.obj &\n\ttask.obj &\n\tloader.obj &\n\tdrawer.obj &\n\taudio.obj &\n\tmonodisp.obj &\n\tdstream.obj &\n\tunvqbuff.obj &\n\tunvqvesa.obj &\n\tvertag.obj &\n\tcaption.obj &\n#\tunvqxmde.obj\n\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!ifdef %LIB\nLIBPATH = $(%PRJ)\\LIB;$(%LIB)\n!else\nLIBPATH = $(%PRJ)\\LIB;$(%WATCOM)\\LIB386\n!endif\n\n!ifdef %INCLUDE\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%INCLUDE)\n!else\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%WATCOM)\\H\n!endif\n\npath_c   = .\\\npath_cpp = .\\\npath_h   = .\\\npath_asm = .\\\npath_i   = .\\\npath_obj = .\\O\npath_lib = $(%PRJ)\\LIB\npath_exe = .\\\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULE EXTENSIONS AND PATHS\n#----------------------------------------------------------------------------\n\n.EXTENSIONS :\n.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i\n\n.c : $(path_c)\n.cpp : $(path_cpp)\n.h : $(path_h)\n.asm : $(path_asm)\n.i : $(path_i)\n.obj : $(path_obj)\n.lib : $(path_lib)\n.exe : $(path_exe)\n\n#----------------------------------------------------------------------------\n# Tools/commands & configurations\n#----------------------------------------------------------------------------\n\nCC_CMD   = wcc386\nCCP_CMD  = wpp386\nASM_CMD  = tasm32\nLINK_CMD = wlink\nLIB_CMD  = wlib\n\nCC_OPTS  = -i$(INCLUDEPATH) -j -zp1 -5s -mf -oaeilrt -s -zq\nASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /i$(%PRJ)\\INCLUDE\\VQM32 /dPHARLAP_TNT=0\nLIB_OPTS = /b /c /q\nLINK_CFG = $(PRJNAME).lnk\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall : $(PRJNAME).lib .SYMBOLIC\n\n$(PRJNAME).lib : $(OBJECTS) .SYMBOLIC\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj :\n  $(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.cpp.obj :\n  $(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\\$^.\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\nupdate: .SYMBOLIC\n\t@echo Updating VQAPlay32 header files!\n\t@copy vqaplay.h ..\\include\\vqa32 >NUL\n\t@copy vqafile.h ..\\include\\vqa32 >NUL\n\n"
  },
  {
    "path": "WINVQ/VQA32/MONODISP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     monodisp.c\n*\n* DESCRIPTION\n*     Monochrome display (debug)\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 6, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_InitMono   - Initialize the player's mono screen.\n*     VQA_UpdateMono - Update the player's mono output.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <string.h>\n#include \"vq.h\"\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n\n#if(VQAMONO_ON)\n\n/* Main window */\n#define\tMAIN_WX1   0\n#define\tMAIN_WX2   79\n#define\tMAIN_WY1   0\n#define\tMAIN_WY2   9\n#define\tMAIN_TITLE \"VQA Player\"\n\n/* Loader data window */\n#define\tLOADER_WX1   0\n#define\tLOADER_WX2   39\n#define\tLOADER_WY1   10\n#define\tLOADER_WY2   20\n#define\tLOADER_TITLE \" Frame Loader \"\n\n/* Drawer data window */\n#define\tDRAWER_WX1   40\n#define\tDRAWER_WX2   79\n#define\tDRAWER_WY1   10\n#define\tDRAWER_WY2   20\n#define\tDRAWER_TITLE \" Frame Drawer \"\n\n/* Audio data window */\n#define\tAUDIO_WX1   0\n#define\tAUDIO_WX2   39\n#define\tAUDIO_WY1   21\n#define\tAUDIO_WY2   24\n#define\tAUDIO_TITLE \" Audio Callback \"\n\n/* Flipper data window */\n#define\tFLIPPER_WX1   40\n#define\tFLIPPER_WX2   79\n#define\tFLIPPER_WY1   21\n#define\tFLIPPER_WY2   24\n#define\tFLIPPER_TITLE \" Frame Flipper \"\n\nextern char *HMIDevName;\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_InitMono - Initialize the player's mono screen.\n*\n* SYNOPSIS\n*     VQA_InitMono(VQA)\n*\n*     void VQA_InitMono(VQAHandleP *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to private VQA handle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\n#pragma argsused\nvoid VQA_InitMono(VQAHandleP *vqap)\n{\n\tVQAData   *vqabuf;\n\tVQAConfig *config;\n\tchar      txt[80];\n\n\t/* Dereference commonly used data members of quick access. */\n\tvqabuf = vqap->VQABuf;\n\tconfig = &vqap->Config;\n\n\t/* Enable and clear the mono screen */\n\tMono_Enable();\n\tMono_Clear_Screen();\n\n\t/* Init main window */\n\tMono_Draw_Rect(MAIN_WX1, MAIN_WY1, (MAIN_WX2 - MAIN_WX1 + 1),\n\t\t\t(MAIN_WY2 - MAIN_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((MAIN_WX2 + MAIN_WX1 - strlen(MAIN_TITLE)) / 2, MAIN_WY1);\n\tMono_Print(MAIN_TITLE);\n\n\t/* Video mode */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 1);\n\tMono_Print(\"Video Mode: \");\n\n\tswitch (config->Vmode) {\n\n\t\t#if(VQAMONO_ON)\n\t\tcase MCGA:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tMono_Print(\"MCGA Buffered\");\n\t\t\t} else {\n\t\t\t\tMono_Print(\"MCGA Direct to screen\");\n\t\t\t}\n\t\t\tbreak;\n\t\t#endif\n\n\t\t#if(VQAXMODE_ON)\n\t\tcase XMODE_320X200:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tMono_Print(\"XMODE 320x200 Buffered\");\n\t\t\t} else {\n\t\t\t\tif (config->DrawFlags & VQACFGF_VRAMCB) {\n\t\t\t\t\tMono_Print(\"XMODE 320x200 VRAM Copy\");\n\t\t\t\t} else {\n\t\t\t\t\tMono_Print(\"XMODE 320x200 Linear->Banked\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase XMODE_320X240:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tMono_Print(\"XMODE 320x240 Buffered\");\n\t\t\t} else {\n\t\t\t\tif (config->DrawFlags & VQACFGF_VRAMCB) {\n\t\t\t\t\tMono_Print(\"XMODE 320x240 VRAM Copy\");\n\t\t\t\t} else {\n\t\t\t\t\tMono_Print(\"XMODE 320x240 Linear->Banked\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t#endif\n\n\t\t#if(VQAVESA_ON)\n\t\tcase VESA_640X480_256:\n\t\t\tMono_Print(\"VESA 640x480\");\n\t\t\tbreak;\n\n\t\tcase VESA_320X200_32K_1:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tMono_Print(\"VESA 320x200 Buffered\");\n\t\t\t} else {\n\t\t\t\tMono_Print(\"VESA 320x200 Direct to screen\");\n\t\t\t}\n\t\t\tbreak;\n\t\t#endif\n\n\t\tdefault:\n\t\t\tMono_Print(\"UNKNOWN\");\n\t\t\tbreak;\n\t}\n\n\t/* Sound status */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 2);\n\tMono_Print(\"               Sound: \");\n\n\tif (config->OptionFlags & VQAOPTF_AUDIO) {\n\t\tsprintf(txt,\"%u Hz\", config->AudioRate);\n\t\tMono_Print(txt);\n\t}\telse {\n\t\tMono_Print(\"OFF\");\n\t}\n\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 3);\n\tMono_Print(\"         Driver Name: \");\n\tMono_Print(HMIDevName);\n\n\t/* Frame rates */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 4);\n\tsprintf(txt,\"     Load Frame Rate: %d\", config->FrameRate);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 5);\n\tsprintf(txt,\"     Draw Frame Rate: %d\", config->DrawRate);\n\tMono_Print(txt);\n\n\t/* Slow palette */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 6);\n\tMono_Print(\"        Slow palette: \");\n\n\tif (config->OptionFlags & VQAOPTF_SLOWPAL) {\n\t\tMono_Print(\"ON\");\n\t} else {\n\t\tMono_Print(\"OFF\");\n\t}\n\n\t/* Memory Usage */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 7);\n\tsprintf(txt,\"         Memory Used: %ld\", vqabuf->MemUsed);\n\tMono_Print(txt);\n\n\t/* Timer Method */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 8);\n\n\tif (VQA_TimerMethod() == VQA_TMETHOD_DOS) {\n\t\tMono_Print(\"           DOS Timer:\");\n\t} else if (VQA_TimerMethod() == VQA_TMETHOD_INT) {\n\t\tMono_Print(\"     Interrupt Timer:\");\n\t} else if (VQA_TimerMethod() == VQA_TMETHOD_AUDIO) {\n\t\tMono_Print(\"     Audio DMA Timer:\");\n\t} else {\n\t\tMono_Print(\"             Defualt:\");\n\t}\n\n\t/* Init loader data window */\n\tMono_Draw_Rect(LOADER_WX1, LOADER_WY1, (LOADER_WX2 - LOADER_WX1 + 1),\n\t\t\t(LOADER_WY2 - LOADER_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((LOADER_WX2 + LOADER_WX1 - strlen(LOADER_TITLE)) / 2,\n\t\t\tLOADER_WY1);\n\n\tMono_Print(LOADER_TITLE);\n\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 1);\n\tMono_Print(\"  Current Frame #:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 2);\n\tMono_Print(\"# Waits on Drawer:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 3);\n\tMono_Print(\" # Waits on Audio:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 4);\n\tMono_Print(\"       Frame Size:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 5);\n\tMono_Print(\"   Max Frame Size:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY2 - 2);\n\tMono_Print(\"Audio:\");\n\n\t/* Init drawer data window */\n\tMono_Draw_Rect(DRAWER_WX1, DRAWER_WY1, (DRAWER_WX2 - DRAWER_WX1 + 1),\n\t\t\t(DRAWER_WY2 - DRAWER_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((DRAWER_WX2 + DRAWER_WX1 - strlen(DRAWER_TITLE)) / 2,\n\t\t\tDRAWER_WY1);\n\n\tMono_Print(DRAWER_TITLE);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 1);\n\tMono_Print(\"   Current Frame #:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 2);\n\tMono_Print(\"   Desired Frame #:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 3);\n\tMono_Print(\"# Waits on Flipper:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 4);\n\tMono_Print(\" # Waits on Loader:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 5);\n\tMono_Print(\"  # Frames Skipped:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 6);\n\tMono_Print(\"     VQ Block Size:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY2 - 2);\n\tMono_Print(\"Frames:                 Cbooks:\");\n\n\t/* Init audio data window */\n\tMono_Draw_Rect(AUDIO_WX1, AUDIO_WY1, (AUDIO_WX2 - AUDIO_WX1 + 1),\n\t\t\t(AUDIO_WY2 - AUDIO_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((AUDIO_WX2 + AUDIO_WX1 - strlen(AUDIO_TITLE)) / 2,\n\t\t\tAUDIO_WY1);\n\n\tMono_Print(AUDIO_TITLE);\n\n\tMono_Set_Cursor(AUDIO_WX1 + 2, AUDIO_WY1 + 1);\n\tMono_Print(\"# Repeated Buffers:\");\n\n\t/* Init flipper data window */\n\tMono_Draw_Rect(FLIPPER_WX1, FLIPPER_WY1, (FLIPPER_WX2 - FLIPPER_WX1 + 1),\n\t\t\t(FLIPPER_WY2 - FLIPPER_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((FLIPPER_WX2 + FLIPPER_WX1 - strlen(FLIPPER_TITLE)) / 2,\n\t\t\tFLIPPER_WY1);\n\n\tMono_Print(FLIPPER_TITLE);\n\n\tMono_Set_Cursor(FLIPPER_WX1 + 2, FLIPPER_WY1 + 1);\n\tMono_Print(\"Current Frame #:\");\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_UpdateMono - Update the player's mono output.\n*\n* SYNOPSIS\n*     VQA_UpdateMono(VQA)\n*\n*     void VQA_UpdateMono(VQAHandleP *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to private VQA handle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\n#pragma argsused\nvoid VQA_UpdateMono(VQAHandleP *vqap)\n{\n\tVQAData       *vqabuf;\n\tVQAConfig     *config;\n\tVQAFrameNode  *frame;\n\tVQACBNode     *cbook;\n\tlong          frameindex = -1;\n\tlong          loadcb = -1;\n\tlong          drawcb = -1;\n\tlong          i;\n\tunsigned long curtime;\n\tchar          txt[80];\n\n\t/* Dereference commonly used data members for quick access. */\n\tvqabuf = vqap->VQABuf;\n\tconfig = &vqap->Config;\n\n\t/* Timer value */\n\tcurtime = VQA_GetTime(vqap);\n\tMono_Set_Cursor(MAIN_WX1 + 40, MAIN_WY1 + 8);\n\tsprintf(txt,\"%02ld:%02ld.%02ld\",curtime / (VQA_TIMETICKS * VQA_TIMETICKS),\n\t\t\tcurtime / VQA_TIMETICKS,((curtime * 100L) / VQA_TIMETICKS)\n\t\t\t-((curtime / VQA_TIMETICKS) * 100L));\n\n\tMono_Print(txt);\n\n\t/* Loader data */\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 1);\n\tsprintf(txt,\"%4d\",vqabuf->Loader.LastFrameNum);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 2);\n\tsprintf(txt,\"%4ld\",vqabuf->Loader.WaitsOnDrawer);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 3);\n\tsprintf(txt,\"%4ld\",vqabuf->Loader.WaitsOnAudio);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 4);\n\tsprintf(txt,\"%5u\",vqabuf->Loader.FrameSize);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 5);\n\tsprintf(txt,\"%5u\",vqabuf->Loader.MaxFrameSize);\n\tMono_Print(txt);\n\n\t#if(VQAAUDIO_ON)\n\t/* Draw a picture of the audio buffers */\n\tfor (i = 0; i < vqabuf->Audio.NumAudBlocks; i++) {\n\t\tif (vqabuf->Audio.IsLoaded[i] == 0) {\n\t\t\ttxt[i] = '_';\n\t\t} else {\n\t\t\ttxt[i] = 'X';\n\t\t}\n\t}\n\n\ttxt[i] = 0;\n\tMono_Set_Cursor(LOADER_WX1 + 9,LOADER_WY2 - 2);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 9,LOADER_WY2-1); \n\tMono_Print(\"                        \");\n\n\tMono_Set_Cursor(LOADER_WX1 + 9 + vqabuf->Audio.PlayPosition\n\t\t\t/ config->HMIBufSize,LOADER_WY2 - 1);\n\n\tMono_Print(\"P\");\n\n\tMono_Set_Cursor(LOADER_WX1 + 9 + vqabuf->Audio.AudBufPos\n\t\t\t/ config->HMIBufSize,LOADER_WY2 - 1);\n\n\tMono_Print(\"L\");\n\t#endif /* VQAAUDIO_ON */\n\n\t/* Drawer data */\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 1);\n\tsprintf(txt,\"%4d\", vqabuf->Drawer.LastFrameNum);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 2);\n\tsprintf(txt,\"%4d\", vqabuf->Drawer.DesiredFrame);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 3);\n\tsprintf(txt,\"%4ld\", vqabuf->Drawer.WaitsOnFlipper);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 4);\n\tsprintf(txt,\"%4ld\", vqabuf->Drawer.WaitsOnLoader);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 5);\n\tsprintf(txt,\"%4d\", vqabuf->Drawer.NumSkipped);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 6);\n\tsprintf(txt,\" %dx%d\", vqap->Header.BlockWidth, vqap->Header.BlockHeight);\n\tMono_Print(txt);\n\n\t/* Draw a picture of the frame buffers */\n\tframe = vqabuf->FrameData;\n\n\tfor (i = 0; i < config->NumFrameBufs; i++) {\n\t\tif (frame->Flags & VQAFRMF_LOADED) {\n\t\t\ttxt[i] = 'X';\n\t\t} else {\n\t\t\ttxt[i] = '_';\n\t\t}\n\n\t\tif (vqabuf->Flipper.CurFrame == frame) {\n\t\t\tframeindex = i;\n\t\t}\n\n\t\tframe = frame->Next;\n\t}\n\n\ttxt[i] = 0;\n\tMono_Set_Cursor(DRAWER_WX1 + 10,DRAWER_WY2 - 2);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 10,DRAWER_WY2 - 1);\n\tMono_Print(\"              \");\n\n\tMono_Set_Cursor(DRAWER_WX1 + 10 + frameindex,DRAWER_WY2 - 1);\n\tMono_Print(\"^\");\n\n\t/* Draw a picture of the codebook buffers */\n\tcbook = vqabuf->CBData;\n\n\tfor (i = 0; i < config->NumCBBufs; i++) {\n\t\tif (vqabuf->Loader.CurCB == cbook) {\n\t\t\tloadcb = i;\n\t\t}\n\n\t\tif (vqabuf->Flipper.CurFrame->Codebook == cbook) {\n\t\t\tdrawcb = i;\n\t\t}\n\n\t\tcbook = cbook->Next;\n\t}\n\n\tMono_Set_Cursor(DRAWER_WX1 + 34,DRAWER_WY2 - 2);\n\tMono_Print(\"___\");\n\n\tMono_Set_Cursor(DRAWER_WX1 + 34,DRAWER_WY2 - 1);\n\tMono_Print(\"   \");\n\n\tMono_Set_Cursor(DRAWER_WX1 + 34 + loadcb,DRAWER_WY2 - 1);\n\tMono_Print(\"L\");\n\n\tMono_Set_Cursor(DRAWER_WX1 + 34 + drawcb,DRAWER_WY2 - 1);\n\tMono_Print(\"D\");\n\n\t/* Audio data */\n\t#if(VQAAUDIO_ON)\n\tMono_Set_Cursor(AUDIO_WX1 + 22, AUDIO_WY1 + 1);\n\tsprintf(txt,\"%4ld\", vqabuf->Audio.NumSkipped);\n\tMono_Print(txt);\n\t#endif\n\n\t/* Flipper data */\n\tMono_Set_Cursor(FLIPPER_WX1 + 22,FLIPPER_WY1 + 1);\n\tsprintf(txt,\"%4d\", vqabuf->Flipper.LastFrameNum);\n\tMono_Print(txt);\n\tMono_Set_Cursor(0,0);\n}\n\n#endif /* VQAMONO_ON */\n\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/AUDIO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     audio.c\n*\n* DESCRIPTION\n*     Audio playback and timing.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     August 4, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_StartTimerInt - Initialize system timer interrupt.\n*     VQA_StopTimerInt  - Remove system timer interrupt.\n*     VQA_SetTimer      - Resets current time to given tick value.\n*     VQA_GetTime       - Return current time.\n*     VQA_TimerMethod   - Get timer method being used.\n*     VQA_OpenAudio     - Open sound system.\n*     VQA_CloseAudio    - Close sound system\n*     VQA_StartAudio    - Starts audio playback\n*     VQA_StopAudio     - Stop audio playback.\n*     CopyAudio         - Copy data from Audio Temp buf into Audio play buf.\n*\n* PRIVATE\n*     TimerCallback - VQA timer event. (Called by HMI)\n*     AutoDetect    - Auto detect the sound card.\n*     AudioCallback - Sound system callback.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <malloc.h>\n#include <mem.h>\n#include <sys\\timeb.h>\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n\n#ifdef __WATCOMC__\n#pragma pack(4);\n#endif\n\n#if(VQAAUDIO_ON)\n#include \"sos.h\"\n#endif\n\n\n/*---------------------------------------------------------------------------\n * AUDIO DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n#define USE_WINDOWS_TIME\t1\n\n#define HMI_SAMPLE 0x1000\n#define MAKE_LONG(a,b) (((long)(a)<<16)|(long)((b)&0x0000FFFFL))\n\n/*---------------------------------------------------------------------------\n * PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n#if( USE_WINDOWS_TIME )\n\textern unsigned long Get_Game_Time( void );\n#endif\n\n#if(VQAAUDIO_ON)\nlong AutoDetect(_SOS_CAPABILITIES *digicaps, long bitsize, long channels);\nvoid far TimerCallback(void);\nvoid far cdecl AudioCallback(WORD wDriverHandle, WORD wAction,\n\t\tWORD wSampleID);\n\n/* Dummy functions used to mark the start/end address of the file. */\nstatic void StartAddr(void);\nstatic void EndAddr(void);\n\n\n/*---------------------------------------------------------------------------\n * GLOBAL DATA\n *-------------------------------------------------------------------------*/\n\nstatic VQAHandleP *VQAP = NULL;\nstatic long AudioFlags = 0;\nstatic long TimerSysCount = 0;\nstatic long TimerIntCount = 0;\nstatic WORD VQATimer = 0;\nstatic long TimerMethod;\nstatic long VQATickCount = 0;\n#endif /* VQAAUDIO_ON */\n\nstatic long TickOffset = 0;\nchar *HMIDevName = \"<none>\";\n\n#if(VQAAUDIO_ON)\n/* This is a dummy function that is used to mark the start of the module.\n * It is necessary for locking the memory the module occupies. This prevents\n * the virtual memory manager from swapping out this memory.\n */\nstatic void StartAddr(void)\n{\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StartTimerInt - Initialize system timer interrupt.\n*\n* SYNOPSIS\n*     Error = VQA_StartTimerInt(VQA, Init)\n*\n*     long VQA_StartTimerInt(VQAHandeP *, long);\n*\n* FUNCTION\n*     Initialize the HMI timer system and add our own timer event. If the\n*     system has already been initialized then we are given access to the\n*     the timer system.\n*\n* INPUTS\n*     VQA  - Pointer to private VQAHandle structure.\n*     Init - Initialize HMI timer system flag. (TRUE = Initialize)\n*\n* RESULT\n*     Error - 0 if successful, -1 if error.\n*\n****************************************************************************/\n\nlong VQA_StartTimerInt(VQAHandleP *vqap, long init)\n{\n\tVQAAudio *audio;\n\n\t/* Dereference for quick access. */\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Does the caller want me to initialize the timer system? */\n\tif (init == 0) {\n\n\t\t/* If the timer system is uninitialized then it is the players\n\t\t * responsibility to do it.\n\t\t */\n\t\tif ((AudioFlags & VQAAUDF_TIMERINIT)==(HMI_UNINIT<<VQAAUDB_TIMERINIT)) {\n\t\t\tsosTIMERInitSystem(_TIMER_DOS_RATE, _SOS_DEBUG_NORMAL);\n\n\t\t\t/* Flag the timer system as open. */\n\t\t\tAudioFlags |= (HMI_VQAINIT << VQAAUDB_TIMERINIT);\n\t\t}\n\n\t\t/* Flag availability of the timer system. */\n\t\taudio->Flags |= (HMI_VQAINIT << VQAAUDB_TIMERINIT);\n\t} else {\n\t\taudio->Flags |= (HMI_APPINIT << VQAAUDB_TIMERINIT);\n\t}\n\n\t/* Increment the timer system usage count. */\n\tTimerSysCount++;\n\n\t/* Register the VQA_TickCount timer event. */\n\tif ((AudioFlags & VQAAUDF_HMITIMER) == (HMI_UNINIT<<VQAAUDB_HMITIMER)) {\n\t\tif (sosTIMERRegisterEvent(VQA_TIMETICKS,TimerCallback,&VQATimer) == 0) {\n\n\t\t\t/* Flag the timer interrupt as being registered. */\n\t\t\tAudioFlags |= (HMI_VQAINIT << VQAAUDB_HMITIMER);\n\t\t} else {\n\t\t\treturn (-1);\n\t\t}\n\t}\n\n\t/* Flag availability of the timer interrupt. */\n\taudio->Flags |= (HMI_VQAINIT << VQAAUDB_HMITIMER);\n\t\n\t/* Increment the timer interrupt usage count. */\n\tTimerIntCount++;\n\n\t/* Lock the memory occupied by this module. */\n\tif ((audio->Flags & VQAAUDF_MODLOCKED) == 0) {\n\t\tDPMI_Lock((void *)&StartAddr, (long)&EndAddr - (long)&StartAddr);\n\t\taudio->Flags |= VQAAUDF_MODLOCKED;\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StopTimerInt - Remove system timer interrupt.\n*\n* SYNOPSIS\n*     VQA_StopTimerInt()\n*\n*     void VQA_StopTimerInt(void);\n*\n* FUNCTION\n*     Remove our timer event from the HMI timer system. Uninitialize the\n*     HMI timer system if we initialized it.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_StopTimerInt(VQAHandleP *vqap)\n{\n\tVQAAudio *audio;\n\n\t/* Dereference for quick access. */\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Decrement the timer interrupt usage count. */\n\tif (TimerIntCount) {\n\t\tTimerIntCount--;\n\t}\n\n\t/* Remove the timer interrrupt if it is initialized and the use count is\n\t * zero. Otherwise, clear the callers timer interrupt availability flag.\n\t */\n\tif (((AudioFlags & VQAAUDF_HMITIMER) == (HMI_VQAINIT<<VQAAUDB_HMITIMER))\n\t\t\t&& (TimerIntCount == 0)) {\n\n\t\tsosTIMERRemoveEvent(VQATimer);\n\t\tAudioFlags &= ~VQAAUDF_HMITIMER;\n\t} else {\n\t\taudio->Flags &= ~VQAAUDF_HMITIMER;\n\t}\n\n\t/* Derement the timer system usage count. */\n\tif (TimerSysCount) {\n\t\tTimerSysCount--;\n\t}\n\n\t/* Close the timer system if it has been opened and the use count is zero.\n\t * Otherwise, clear the callers timer system availability flag.\n\t */\n\tif (((AudioFlags & VQAAUDF_TIMERINIT) == (HMI_VQAINIT<<VQAAUDB_TIMERINIT))\n\t\t\t&& (TimerSysCount == 0)) {\n\n\t\tsosTIMERUnInitSystem(0);\n\t\tAudioFlags &= ~VQAAUDF_TIMERINIT;\n\t} else {\n\t\taudio->Flags &= ~VQAAUDF_TIMERINIT;\n\t}\n\n\t/* Unlock the memory accupied by this module. */\n\tif ((audio->Flags & VQAAUDF_MODLOCKED) == 1) {\n\t\tDPMI_Unlock(&StartAddr, (long)&EndAddr - (long)&StartAddr);\n\t\taudio->Flags &= ~VQAAUDF_MODLOCKED;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     TimerCallback - VQA timer event. (Called by HMI)\n*\n* SYNOPSIS\n*     TimerCallback()\n*\n*     void TimerCallback(void);\n*\n* FUNCTION\n*     Our custom timer event. This is the timer event that we register with\n*     HMI for system timing.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid far TimerCallback(void)\n{\n\tVQATickCount++;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_OpenAudio - Open sound system.\n*\n* SYNOPSIS\n*     Error = VQA_OpenAudio(VQAHandleP)\n*\n*     long VQA_OpenAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Initialize the sound system by setting the DigiHandle to and HMI\n*     driver handle. The timer must first be initialized before calling\n*     this function.\n*\n* INPUTS\n*     VQAHandleP - Pointer to private VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, -1 if error.\n*\n****************************************************************************/\n\nlong VQA_OpenAudio(VQAHandleP *vqap)\n{\n\tVQAData       *vqabuf;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tVQAHeader     *header;\n\tunsigned char *driver_path;\n\tWORD          port;\n\tlong          rc;\n\n\t/* Dereference data memebers for quicker access. */\n\tconfig = &vqap->Config;\n\theader = &vqap->Header;\n\tvqabuf = vqap->VQABuf;\n\taudio = &vqabuf->Audio;\n\n\t/* Fail if no audio buffer or DigiCard is 0 (no sound) */\n\tif ((audio->Buffer == NULL) || (config->DigiCard == 0)) {\n\t\treturn (-1);\n\t}\n\n\t/* Reset the buffer position to the beginning. */\n\taudio->CurBlock = 0;\n\n\t/* Initialize the HMI driver structure. */\n\taudio->sSOSInitDriver.wAllocateBuffer = _TRUE;\n\taudio->sSOSInitDriver.wParam = 19;\n\taudio->sSOSInitDriver.wTimerID = _SOS_NORMAL_TIMER;\n\n\t/*-------------------------------------------------------------------------\n\t * Compute the playback rate:\n\t *\n\t * - If Config->AudioRate is -1, use HMI_DATA_RATE scaled to the specified\n\t *   frame rate (so the audio plays faster if we're playing faster)\n\t * - otherwise, use the specified rate\n\t *-----------------------------------------------------------------------*/\n\tif (config->AudioRate != -1) {\n\t\taudio->sSOSInitDriver.wSampleRate = config->AudioRate;\n\t}\n\telse if (config->FrameRate != header->FPS) {\n\t\taudio->sSOSInitDriver.wSampleRate = ((audio->SampleRate*config->FrameRate)\n\t\t\t\t/ (unsigned long)header->FPS);\n\n\t\tconfig->AudioRate = audio->sSOSInitDriver.wSampleRate;\n\t} else {\n\t\taudio->sSOSInitDriver.wSampleRate = audio->SampleRate;\n\t\tconfig->AudioRate = audio->SampleRate;\n\t}\n\n\t/* If the application has already initialized HMI then set the\n\t * necessary variables. Otherwise we must setup HMI ourself.\n\t */\n\tif ((config->OptionFlags & VQAOPTF_HMIINIT)\n\t\t\t|| ((AudioFlags & VQAAUDF_DIGIINIT) != 0)) {\n\n\t\t/* The application MUST provide the card type! */\n\t\tif (config->DigiCard == -1) {\n\t\t\treturn (-1);\n\t\t}\n\n\t\t/* Init the detection system */\n\t\tdriver_path = (unsigned char *)\".\\\\\";\n\n\t\tif ((rc = sosDIGIDetectInit(driver_path)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Get the capabilities of the card being used. */\n\t\trc = sosDIGIDetectGetCaps(config->DigiCard, &audio->DigiCaps);\n\t\tsosDIGIDetectUnInit();\n\n\t\tif (rc != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\taudio->DigiHandle = config->DigiHandle;\n\t\taudio->Flags |= (HMI_APPINIT << VQAAUDB_TIMERINIT);\n\t\taudio->Flags |= (HMI_APPINIT << VQAAUDB_DIGIINIT);\n\n\t\tif ((AudioFlags & (VQAAUDF_TIMERINIT|VQAAUDF_DIGIINIT)) == 0) {\n\t\t\tHMIDevName = \"App-Specific\";\n\t\t\tAudioFlags |= (HMI_APPINIT << VQAAUDB_TIMERINIT);\n\t\t\tAudioFlags |= (HMI_APPINIT << VQAAUDB_DIGIINIT);\n\t\t}\n\t} else {\n\n\t\t/* Init the detection system */\n\t\tdriver_path = (unsigned char *)\".\\\\\";\n\n\t\tif ((rc = sosDIGIDetectInit(driver_path)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/*-----------------------------------------------------------------------\n\t\t * Initialize DigiHardware with port, IRQ, and DMA, and make sure\n\t\t * Config.DigiCard contains the HMI ID we want to use:\n\t\t *\n\t\t * - If Config.DigiCard is -1, auto-detect the hardware; then, do a \n\t\t *   FindHardware so the GetSettings will work\n\t\t * - If Config.DigiCard is filled in, but port, IRQ or DMA is -1, use\n\t\t *   FindHardware & GetSettings to get the settings\n\t\t * - If all are filled in, just use them as they are\n\t\t *---------------------------------------------------------------------*/\n\n\t\t/* Auto-Detect */\n\t\tif (config->DigiCard == -1) {\n\n\t\t\t/* Version 1 VQA's have only 8 bit mono audio streams. */\n\t\t\tif (header->Version == VQAHD_VER1) {\n\t\t\t\tconfig->DigiCard = AutoDetect(&audio->DigiCaps, 8, 1);\n\t\t\t} else {\n\t\t\t\tconfig->DigiCard = AutoDetect(&audio->DigiCaps, audio->BitsPerSample,\n\t\t\t\t\t\taudio->Channels);\n\n\t\t\t\t/* Resort to 8bit mono */\n\t\t\t\tif (config->DigiCard == -1) {\n\t\t\t\t\tconfig->DigiCard = AutoDetect(&audio->DigiCaps, 8, 1);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (config->DigiCard == -1) {\n\t\t\t\tsosDIGIDetectUnInit();\n\t\t\t\treturn (-1);\n\t\t\t}\n\t\t}\n\n\t\t/* Do a FindHardware & GetSettings */\n\t\tif (config->DigiPort == -1) {\n\t\t  if (sosDIGIDetectFindHardware(config->DigiCard, &audio->DigiCaps,\n\t\t\t\t\t&port)) {\n\n\t\t\t\tsosDIGIDetectUnInit();\n\t\t\t\treturn (-1);\n\t\t\t}\n\n\t\t\tif (sosDIGIDetectGetSettings(&audio->DigiHardware)) {\n\t\t\t\tsosDIGIDetectUnInit();\n\t\t\t\treturn (-1);\n\t\t\t}\n\n\t\t\tconfig->DigiPort = audio->DigiHardware.wPort;\n\t\t\tconfig->DigiIRQ = audio->DigiHardware.wIRQ;\n\t\t\tconfig->DigiDMA = audio->DigiHardware.wDMA;\n\t\t\tHMIDevName = (char *)audio->DigiCaps.szDeviceName;\n\t\t} else {\n\t\t\taudio->DigiHardware.wPort = config->DigiPort;\n\t\t\taudio->DigiHardware.wIRQ = config->DigiIRQ;\n\t\t\taudio->DigiHardware.wDMA = config->DigiDMA;\n\t\t\tHMIDevName = \"App-Specific\";\n\t\t}\n\n\t\tsosDIGIDetectUnInit();\n\n\t\t/* Initialize the DIGI system & driver */\n\t\tsosDIGIInitSystem(driver_path, _SOS_DEBUG_NORMAL);\n\t\taudio->sSOSInitDriver.wBufferSize = config->HMIBufSize;\n\t\taudio->sSOSInitDriver.lpBuffer = NULL;\n\t\taudio->sSOSInitDriver.lpFillHandler = NULL;\n\t\taudio->sSOSInitDriver.lpDriverMemory = NULL;\n\t\taudio->sSOSInitDriver.lpTimerMemory = NULL;\n\t\taudio->DigiHandle = -1;\n\n\t\tif ((rc = sosDIGIInitDriver(config->DigiCard, &audio->DigiHardware, \n\t\t\t\t&audio->sSOSInitDriver, &audio->DigiHandle)) != 0) {\n\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/*-----------------------------------------------------------------------\n\t\t * Register the timer event\n\t\t *---------------------------------------------------------------------*/\n\n\t\t/* If the timer hasn't been init'd, do it now */\n\t\tif ((AudioFlags & VQAAUDF_TIMERINIT) == (HMI_UNINIT<<VQAAUDB_TIMERINIT)) {\n\t\t\tsosTIMERInitSystem(_TIMER_DOS_RATE ,_SOS_DEBUG_NORMAL);\n\t\t\taudio->Flags |= (HMI_VQAINIT << VQAAUDB_TIMERINIT);\n \t\t\tAudioFlags |= (HMI_VQAINIT << VQAAUDB_TIMERINIT);\n\t\t}\n\n\t\t/* Register the event */\n\t\trc = sosTIMERRegisterEvent(VQA_TIMETICKS,\n\t\t\t\taudio->sSOSInitDriver.lpFillHandler, &audio->DigiTimer);\n\n\t\tif (rc) {\n\t\t\tsosDIGIUnInitDriver(audio->DigiHandle, _TRUE, _TRUE);\n\t\t\tsosDIGIUnInitSystem();\n\t\t\treturn (rc);\n\t\t}\n\n\t\tconfig->DigiHandle = audio->DigiHandle;\n\t\taudio->Flags |= (HMI_VQAINIT << VQAAUDB_DIGIINIT);\n\t\tAudioFlags |= (HMI_VQAINIT << VQAAUDB_DIGIINIT);\n\t}\n\n\tif ((audio->Flags & VQAAUDF_MODLOCKED) == 0) {\n\t\tDPMI_Lock(&StartAddr, (long)&EndAddr - (long)&StartAddr);\n\t\taudio->Flags |= VQAAUDF_MODLOCKED;\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_CloseAudio - Close sound system\n*\n* SYNOPSIS\n*     VQA_CloseAudio()\n*\n*     void VQA_CloseAudio(void);\n*\n* FUNCTION\n*     Removes VQA's involvement in the audio system.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_CloseAudio(VQAHandleP *vqap)\n{\n\tVQAAudio *audio;\n\n\t/* Dereference for quick access. */\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Remove the Digi event */\n\tif ((AudioFlags & VQAAUDF_DIGIINIT) == (HMI_VQAINIT<<VQAAUDB_DIGIINIT)) {\n\t\tsosTIMERRemoveEvent(audio->DigiTimer);\n\t}\n\n\t/* Un-init timer if necessary */\n\tif ((AudioFlags & VQAAUDF_TIMERINIT) == (HMI_VQAINIT<<VQAAUDB_TIMERINIT)) {\n\t\tsosTIMERUnInitSystem(0);\n\t}\n\n\taudio->Flags &= ~VQAAUDF_TIMERINIT;\n\tAudioFlags &= ~VQAAUDF_TIMERINIT;\n\n\t/* Remove the driver */\n\tif ((audio->Flags & VQAAUDF_DIGIINIT) == (HMI_VQAINIT<<VQAAUDB_DIGIINIT)) {\n\t\tsosDIGIUnInitDriver(audio->DigiHandle, _TRUE, _TRUE);\n\t\tsosDIGIUnInitSystem();\n\t}\n\n\taudio->Flags &= ~VQAAUDF_DIGIINIT;\n\tAudioFlags &= ~VQAAUDF_DIGIINIT;\n\tAudioFlags &= ~VQAAUDF_ISPLAYING;\n\n\t/* Unlock the memory accupied by this module. */\n\tif ((audio->Flags & VQAAUDF_MODLOCKED) == 1) {\n\t\tDPMI_Unlock(&StartAddr, (long)&EndAddr - (long)&StartAddr);\n\t\taudio->Flags &= ~VQAAUDF_MODLOCKED;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     AutoDetect - Auto detect the sound card.\n*\n* SYNOPSIS\n*     CardID = AutoDetect(DigiCaps, BitSize, Channels)\n*\n*     long AutoDetect(_SOS_CAPABILITIES *, long, long);\n*\n* FUNCTION\n*     Autodetects the type of sound card present in the system.\n*\n* INPUTS\n*     DigiCaps - Pointer to HMI digital card capabilities structure.\n*     BitSize  - Bits per sample size.\n*     Channels - Number of desired channels.\n*\n* RESULT\n*     CardID - HMI ID of the sound card found, -1 if none.\n*\n****************************************************************************/\n\nlong AutoDetect(_SOS_CAPABILITIES *digicaps, long bitsize, long channels)\n{\n\tlong device_id = -1;\n\tWORD port;\n\tlong i;\n\tlong rc;\n\n\t/* Search for an 8-bit mono device */\n\tif (sosDIGIDetectFindFirst(digicaps, &port)) {\n\t\treturn (-1);\n\t}\n\n\tchannels--;\n\n\ti = 0;\n\twhile (i < 6) {\n\t\ti++;\n\n\t\tif ((digicaps->wBitsPerSample == bitsize)\n\t\t\t\t&& (digicaps->wChannels == channels)) {\n\n\t\t\tbreak;\n\t\t}\n\n\t\tif (sosDIGIDetectFindNext(digicaps, &port)) {\n\t\t\treturn (-1);\n\t\t}\n\t}\n\n\t/* Exit if failed to find the required device */\n\tif ((digicaps->wBitsPerSample != bitsize)\n\t\t\t|| (digicaps->wChannels != channels)) {\n\n\t\treturn (-1);\n\t}\n\n\t/* Stash the ID */\n\tdevice_id = digicaps->wDeviceID;\n\n\t/* Now that we have handled the initial pass, verify that if we found an\n\t * _ADLIB_GOLD_8_MONO that it is not a Logitech Sound Wave man in disguise.\n\t */\n\tif ((WORD)digicaps->wDeviceID == _ADLIB_GOLD_8_MONO) {\n\t\trc = sosDIGIDetectFindNext(digicaps, &port);\n\n\t\twhile ((i < 6) && (rc == 0)) {\n\t\t\ti++;\n\n\t\t\tif ((digicaps->wBitsPerSample == 8) && (digicaps->wChannels == 0)) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif ((rc = sosDIGIDetectFindNext(digicaps, &port)) != 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/* If we don't have an error use the secondary device ID, after all, \n\t\t * anything's better than an Adlib Gold.  If we do have an error or there\n\t\t * is nothing we can use then the device ID is already set to the adlib \n\t\t * gold so just let it rip.\n\t\t */\n\t\tif ((rc == 0) && ((WORD)digicaps->wDeviceID == _SBPRO_8_MONO)) {\n\t\t\treturn (digicaps->wDeviceID);\n\t\t}\n\t}\n\n\treturn (device_id);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StartAudio - Starts audio playback\n*\n* SYNOPSIS\n*     Error = VQA_StartAudio(VQA)\n*\n*     long VQA_StartAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Start the audio playback for the movie.\n*\n* INPUTS\n*     VQA - Pointer to private VQA handle.\n*\n* RESULT\n*     Error - 0 if successful, or -1 error code.\n*\n****************************************************************************/\n\nlong VQA_StartAudio(VQAHandleP *vqap)\n{\n\tVQAConfig *config;\n\tVQAAudio  *audio;\n\n\t/* Save buffers for the callback routine */\n\tVQAP = vqap;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tconfig = &vqap->Config;\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Return if already playing */\n\tif (AudioFlags & VQAAUDF_ISPLAYING) {\n\t\treturn (-1);\n\t}\n\n \t/* Set my driver handle */\n\tif (config->DigiHandle != -1) {\n\t\taudio->DigiHandle = config->DigiHandle;\n\t}\n\n\tif (audio->DigiHandle == (WORD)-1) {\n\t\treturn (-1);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * Initialize the sample structure.\n\t *-----------------------------------------------------------------------*/\n\tmemset(&audio->sSOSSampleData, 0, sizeof(_SOS_START_SAMPLE));\n  audio->sSOSSampleData.lpSamplePtr = (unsigned char *)audio->Buffer;\n \taudio->sSOSSampleData.dwSampleSize = config->HMIBufSize;\n\taudio->sSOSSampleData.wVolume = (config->Volume << 7);\n\taudio->sSOSSampleData.wSampleID = HMI_SAMPLE;\n\taudio->sSOSSampleData.lpCallback = AudioCallback;\n\n\t/* Set the channel flags for the type of data we have. */\n\tif (audio->Channels == 2) {\n\t\taudio->sSOSSampleData.wChannel = _INTERLEAVED;\n\t} else {\n\t\taudio->sSOSSampleData.wChannel = _CENTER_CHANNEL;\n\t}\n\n\t/* If the card is unable to handle stereo data the we must notify the\n\t * sound system to convert the stereo data to mono data during playback.\n\t */\n\tif ((audio->Channels - 1) > audio->DigiCaps.wChannels) {\n\t\taudio->sSOSSampleData.wSampleFlags |= _STEREOTOMONO;\n\t}\n\n\t/* If the card is unable to handle the sample size of the audio data\n\t * then we must notify the sound system to convert the audio data to\n\t * the proper format.\n\t */\n\tif (audio->BitsPerSample != audio->DigiCaps.wBitsPerSample) {\n\t\tif (audio->BitsPerSample > audio->DigiCaps.wBitsPerSample) {\n\t\t\taudio->sSOSSampleData.wSampleFlags |= _TRANSLATE16TO8;\n\t\t} else {\n\t\t\taudio->sSOSSampleData.wSampleFlags |= _TRANSLATE8TO16;\n\t\t}\n\t}\n\n\t/* Adjust the pitch if the driver is setup to playback at a different\n\t * rate than what the sample was recorded at.\n\t */\n\tif (audio->sSOSInitDriver.wSampleRate != audio->SampleRate) {\n\t\tldiv_t result;\n\n\t\tresult = ldiv(audio->SampleRate, audio->sSOSInitDriver.wSampleRate);\n\t\taudio->sSOSSampleData.dwSamplePitchAdd = (long)MAKE_LONG((short)result.quot,\n\t\t\t\t(short)(((long)result.rem * 0x10000L) / audio->sSOSInitDriver.wSampleRate));\n\t\taudio->sSOSSampleData.wSampleFlags |= _PITCH_SHIFT;\n\t}\n\n\t/* Start playback */\n \taudio->SampleHandle = sosDIGIStartSample(audio->DigiHandle, \n\t\t\t&audio->sSOSSampleData);\n\n\taudio->Flags |= VQAAUDF_ISPLAYING;\n\tAudioFlags |= VQAAUDF_ISPLAYING;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_StopAudio - Stop audio playback.\n*\n* SYNOPSIS\n*     VQA_StopAudio(VQA)\n*\n*     void VQA_StopAudio(VQAHandleP *);\n*\n* FUNCTION\n*     Halts the currently playing audio stream.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_StopAudio(VQAHandleP *vqap)\n{\n\tVQAAudio *audio;\n\n\t/* Dereference for quick access. */\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* Just return if not playing */\n\tif (AudioFlags & VQAAUDF_ISPLAYING) {\n\t\tsosDIGIStopSample(audio->DigiHandle, audio->SampleHandle);\n\t\taudio->Flags &= ~VQAAUDF_ISPLAYING;\n\t\tAudioFlags &= ~VQAAUDF_ISPLAYING;\n\t}\n\n\tVQAP = NULL;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     CopyAudio - Copy data from Audio Temp buffer into Audio play buffer.\n*\n* SYNOPSIS\n*     Error = CopyAudio(VQA)\n*\n*     long CopyAudio(VQAHandleP *);\n*\n* FUNCTION\n*     This routine just copies the data in the TempBuf into the correct\n*     spots in the audio play buffer.  If there is no room available in the\n*     audio play buffer, the routine returns VQAERR_SLEEPING, which will put\n*     the whole Loader to \"sleep\" while it waits for a free buffer.\n*\n*     If there's no data in the TempBuf to copy, the routine just returns 0.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle structure.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nlong CopyAudio(VQAHandleP *vqap)\n{\n\tVQAAudio  *audio;\n\tVQAConfig *config;\n\tlong      startblock;\n\tlong      endblock;\n\tlong      len1,len2;\n\tlong      i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\taudio = &vqap->VQABuf->Audio;\n\tconfig = &vqap->Config;\n\n\t/* If audio is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, or if there's no data to copy, just return 0\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (vqap->vocfh != -1)\n\t\t\t|| (audio->Buffer == NULL) || (audio->TempBufLen == 0)) {\n\t#else  /* VQAVOC_ON */\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (audio->Buffer == NULL)\n\t\t\t|| (audio->TempBufLen == 0)) {\n\t#endif /* VQAVOC_ON */\n\n\t\treturn (0);\n\t}\n\n\t/* Compute start & end blocks to copy into */\n\tstartblock = (audio->AudBufPos / config->HMIBufSize);\n\tendblock = (audio->AudBufPos + audio->TempBufLen) / config->HMIBufSize;\n\n\tif (endblock >= audio->NumAudBlocks) {\n\t\tendblock -= audio->NumAudBlocks;\n\t}\n\n\t/* If 'endblock' hasn't played yet, return VQAERR_SLEEPING */\n\tif (audio->IsLoaded[endblock] == 1) {\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\t/* Copy the data:\n\t *\n\t *  - If 'startblock' < 'endblock', copy the entire buffer\n\t *  - Otherwise, fill to the end of the buffer with part of the data, then\n\t *    copy the rest to the beginning of the buffer\n\t */\n\tif (startblock <= endblock) {\n\n\t\t/* Copy data */\n\t\tmemcpy((audio->Buffer + audio->AudBufPos), audio->TempBuf,\n\t\t\t\taudio->TempBufLen);\n\n\t\t/* Adjust current load position */\n\t\taudio->AudBufPos += audio->TempBufLen;\n\n\t\t/* Mark buffer as empty */\n\t\taudio->TempBufLen = 0;\n\n\t\t/* Set all blocks to loaded */\n\t\tfor (i = startblock; i < endblock; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t} else {\n\n\t\t/* Compute length of each piece */\n\t\tlen1 = config->AudioBufSize - audio->AudBufPos;\n\t\tlen2 = audio->TempBufLen - len1;\n \n\t\t/* Copy 1st piece into end of Audio Buffer */\n\t\tmemcpy((audio->Buffer + audio->AudBufPos), audio->TempBuf, len1);\n\n\t\t/* Copy 2nd piece into start of Audio Buffer */\n\t\tmemcpy(audio->Buffer, audio->TempBuf + len1, len2);\n\t\t\n\t\t/* Adjust load position */\n\t\taudio->AudBufPos = len2;\n\n\t\t/* Mark buffer as empty */\n\t\taudio->TempBufLen = 0;\n\n\t\t/* Set blocks to loaded */\n\t\tfor (i = startblock; i < audio->NumAudBlocks; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\tfor (i = 0; i < endblock; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     AudioCallback - Sound system callback.\n*\n* SYNOPSIS\n*     AudioCallback(DriverHandle, Action, SampleID)\n*\n*     void AudioCallback(WORD, WORD, WORD);\n*\n* FUNCTION\n*     Our custom audio callback routine that services HMI.\n*\n* INPUTS\n*     DriverHandle - HMI driver handle.\n*     Action       - Action taken.\n*     SampleID     - ID of sample.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid far cdecl AudioCallback(WORD wDriverHandle,WORD wAction,WORD wSampleID)\n{\n\tVQAAudio  *audio;\n\tVQAConfig *config;\n\n\t/* Dereference commonly used data members for quicker access. */\n\taudio = &VQAP->VQABuf->Audio;\n\tconfig = &VQAP->Config;\n\n\t/* Suppress compiler warnings */\n\twDriverHandle = wDriverHandle;\n\twSampleID = wSampleID;\n\n  /* See if we're called because the buffer is empty */\n\tif (wAction == _SAMPLE_PROCESSED) {\n\n\t\t/* Compute the 'NextBlock' index */\n\t\taudio->NextBlock = audio->CurBlock + 1;\n\n\t\tif (audio->NextBlock >= audio->NumAudBlocks) {\n\t\t\taudio->NextBlock = 0;\n\t\t}\n\n\t\t/* See if the next block has data in it; if so, update the audio\n\t\t * buffer play position & the 'CurBlock' value.\n\t\t * If not, don't change anything and replay this block.\n\t\t */\n\t\tif (audio->IsLoaded[audio->NextBlock] == 1) {\n\n\t\t\t/* Update this block's status to loadable (0) */\n\t\t\taudio->IsLoaded[audio->CurBlock] = 0;\n\n\t\t\t/* Update position within audio buffer */\n\t\t\taudio->PlayPosition += config->HMIBufSize;\n\t\t\taudio->CurBlock++;\n\n\t\t\tif (audio->PlayPosition >= config->AudioBufSize) {\n\t\t\t\taudio->PlayPosition = 0;\n\t\t\t\taudio->CurBlock = 0;\n\t\t\t}\n\t\t} else {\n\t\t\taudio->NumSkipped++;\n\t\t}\n\n\t\t/* Start the new buffer playing */\n\t  audio->sSOSSampleData.lpSamplePtr = (unsigned char *)(audio->Buffer)\n\t\t\t\t+ audio->PlayPosition;\n\n   \tsosDIGIContinueSample(audio->DigiHandle, audio->SampleHandle,\n\t\t\t\t&audio->sSOSSampleData);\n\n\t\taudio->SamplesPlayed += config->HMIBufSize;\n\t}\n}\n\n/* Dummy function used to mark the beginning address of the file. */\nstatic void EndAddr(void)\n{\n}\n#endif /* VQAAUDIO_ON */\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_SetTimer - Resets current time to given tick value.\n*\n* SYNOPSIS\n*     VQA_SetTimer(Time, Method)\n*\n*     void VQA_SetTimer(long, long);\n*\n* FUNCTION\n*     Sets 'TickOffset' to a value that will make the current time look like\n*     the time passed in. This function allows the player to be \"paused\",\n*     by recording the time of the pause, and then setting the timer to\n*     that time. The timer method used by the player is also set. The method\n*     selected is not neccesarily the method that will be used because some\n*     timer methods work with only certain playback conditions. (EX: The\n*     audio DMA timer method cannot be used if there is not any audio\n*     playing.)\n*\n* INPUTS\n*     Time   - Value to set current time to.\n*     Method - Timer method to use.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_SetTimer(VQAHandleP *vqap, long time, long method)\n{\n\tunsigned long curtime;\n\n\t#if(VQAAUDIO_ON)\n\tVQAAudio      *audio;\n\n\t/* Dereference for quick access. */\n\taudio = &vqap->VQABuf->Audio;\n\n\t/* If the client does not have a preferencee then pick a method\n\t * based on the state of the player.\n\t */\n\tif (method == VQA_TMETHOD_DEFAULT) {\n\n\t\t/* If we are playing audio, use the audio DMA position. */\n\t\tif (AudioFlags & VQAAUDF_ISPLAYING) {\n\t\t\tmethod = VQA_TMETHOD_AUDIO;\n\t\t}\n\n\t\t/* Otherwise use the HMI timer if it is initialized. */\n\t\telse if (AudioFlags & VQAAUDF_HMITIMER) {\n\t\t\tmethod = VQA_TMETHOD_INT;\n\t\t}\n\n\t\t/* If all else fails resort the the \"jerky\" DOS time. */\n\t\telse {\n\t\t\tmethod = VQA_TMETHOD_DOS;\n\t\t}\n\t} else {\n\n\t\t/* We cannot use the DMA position if there isn't any audio playing. */\n\t\tif (!(AudioFlags & VQAAUDF_ISPLAYING) && (method == VQA_TMETHOD_AUDIO)) {\n\t\t\tmethod = VQA_TMETHOD_INT;\n\t\t}\n\n\t\t/* We cannot use the timer if it has not been initialized. */\n\t\tif (!(AudioFlags & VQAAUDF_HMITIMER) && (method == VQA_TMETHOD_INT)) {\n\t\t\tmethod = VQA_TMETHOD_DOS;\n\t\t}\n\t}\n\n\tTimerMethod = method;\n\t#else\n\tmethod = method;\n\t#endif\n\n\tTickOffset = 0L;\n\tcurtime = VQA_GetTime(vqap);\n\tTickOffset = (time - curtime);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_GetTime - Return current time.\n*\n* SYNOPSIS\n*     Time = VQA_GetTime()\n*\n*     unsigned long VQA_GetTime(void);\n*\n* FUNCTION\n*     This routine returns timer ticks computed one of 3 ways:\n*\n*     1) If audio is playing, the timer is based on the DMA buffer position:\n*        Compute the number of audio samples that have actually been played.\n*        The following internal HMI variables are used:\n*\n*          _lpSOSDMAFillCount[drv_handle]: current DMA buffer position\n*          _lpSOSSampleList[drv_handle][samp_handle]:\n*          sampleTotalBytes: total bytes sent by HMI to the DMA buffer\n*          sampleLastFill: HMI's last fill position in DMA buffer\n*\n*        So, the number of samples actually played is:\n*\n*          sampleTotalBytes - <DMA_diff>\n*          where <DMA_diff> is how far ahead sampleLastFill is in front of\n*          _lpSOSDMAFillCount: (sampleLastFill - _lpSOSDMAFillCount)\n*\n*        These values are indices into a circular DMA buffer, so:\n*\n*          if (sampleLastFill >= _lpSOSDMAFillCount)\n*            <DMA_diff> = sampleLastFill - _lpSOSDMAFillCount\n*          else\n*            <DMA_diff> = (DMA_BUF_SIZE - lpSOSDMAFillCount) + sampleLastFill\n*\n*        Note that, if using the stereo driver with mono data, you must\n*        divide LastFill & FillCount by 2, but not TotalBytes. If using the\n*        stereo driver with stereo data, you must divide all 3 variables\n*        by 2.\n*\n*     2) If no audio is playing, but the timer interrupt is running,\n*        VQATickCount is used as the timer\n*\n*     3) If no audio is playing & no timer interrupt is going, the DOS 18.2\n*        system timer is used.\n*\n*     Regardless of the method, TickOffset is used as an offset from the\n*     computed time.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Time - Time in VQA_TIMETICKS\n*\n****************************************************************************/\n\nunsigned long VQA_GetTime(VQAHandleP *vqap)\n{\n\t#if(VQAAUDIO_ON)\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tunsigned long fillcount;\n\tunsigned long lastfill;\n\tunsigned long dma_diff;\n\tunsigned long totalbytes;\n\tunsigned long samples;\n\t#endif\n\n\t// MEG 09.25.95 - changed from long to unsigned long\n\tunsigned long ticks;\n\n\t#if(VQAAUDIO_ON)\n\tswitch (TimerMethod) {\n\n\t\t/* If Audio is playing then timing is based on the audio DMA buffer\n\t\t * position.\n\t\t */\n\t\tcase VQA_TMETHOD_AUDIO:\n\n\t\t\t/* Dereference commonly used data members for quicker access. */\n\t\t\taudio = &vqap->VQABuf->Audio;\n\t\t\tconfig = &vqap->Config;\n\n\t\t\t/* Compute our current position in the audio track by getting the\n\t\t\t * bytes processed by HMI. Then adjust the bytes processed by the\n\t\t\t * position of the DMA fill handler, this should tell us exactly\n\t\t\t * where we are in the audio track.\n\t\t\t */\n\t\t\tfillcount = (unsigned long)(*_lpSOSDMAFillCount[audio->DigiHandle]);\n\t\t\tlastfill = _lpSOSSampleList[audio->DigiHandle][audio->SampleHandle]->sampleLastFill;\n\t\t\ttotalbytes = _lpSOSSampleList[audio->DigiHandle][audio->SampleHandle]->sampleTotalBytes;\n\n\t\t\tif (totalbytes == 0) {\n\t\t\t\tdma_diff = 0;\n\t\t\t} else {\n\t\t\t\tif (lastfill > fillcount) {\n\t\t\t\t\tdma_diff = lastfill - fillcount;\n\t\t\t\t} else {\n\t\t\t\t\tdma_diff = (config->HMIBufSize - fillcount) + lastfill;\n\t\t\t\t}\n\n\t\t\t\tif (dma_diff > totalbytes) {\n\t\t\t\t\tdma_diff = totalbytes;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Calculate the number of samples by taking the total number of\n\t\t\t * bytes processed and divide it by the number of channels and \n\t\t\t * bits per sample.\n\t\t\t */\n\t\t\tsamples = totalbytes - dma_diff;\n\t\t\tsamples -= (audio->NumSkipped * config->HMIBufSize);\n\t\t\tsamples /= (audio->Channels * (audio->BitsPerSample >> 3));\n\n\t\t\t/* The elapsed ticks is calculated by the number of samples\n\t\t\t * processed times the tick resolution per second divided by the\n\t\t\t * sample rate.\n\t\t\t */\n\t\t\tticks = (long)((samples * VQA_TIMETICKS) / audio->SampleRate);\n\t\t\tticks += TickOffset;\n\t\t\tbreak;\n\n\t\t/* No audio playing, but timer interrupt is going; use VQATickCount */\n\t\tcase VQA_TMETHOD_INT:\n\t\t\tticks = (VQATickCount + TickOffset);\n\t\t\tbreak;\n\n\t\t/* No interrupts are going at all; use DOS's time */\n\t\tdefault:\n\t\tcase VQA_TMETHOD_DOS:\n\t\t\t{\n\t\t\tstruct timeb mytime;\n\n\t\t\tftime(&mytime);\n \t\t\tticks = (unsigned long)mytime.time*1000L+(unsigned long)mytime.millitm;\n\t\t\tticks = ((ticks * VQA_TIMETICKS) / 1000L);\n\t\t\tticks += TickOffset;\n\t\t\t}\n\t\t\tbreak;\n\t}\n\t#else\n\t{\n\t// MEG 09.23.95 - Use Windows timer.\n#if( ! USE_WINDOWS_TIME )\n\n\tstruct timeb mytime;\n\n\tftime(&mytime);\n\tticks = (unsigned long)mytime.time*1000L+(unsigned long)mytime.millitm;\n\n#else\n\n\tticks = Get_Game_Time();\n\n#endif\n\n//\tticks = ((ticks * VQA_TIMETICKS) / 1000L);\n\n\t// MEG 09.25.95 - multiply by 3, divide by 50 instead of multiplying by\n\t// 60 and dividing by 1000.  The reason for this is that multiplying by\n\t// 60 causes an overflow pretty quickly if the value from Get_Game_Time\n\t// is high.\n\tticks = ((ticks * 3L) / 50L);\n\n\tticks += TickOffset;\n\t}\n\t#endif\n\n\treturn (ticks);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_TimerMethod - Get timer method being used.\n*\n* SYNOPSIS\n*     Method = VQA_TimerMethod()\n*\n*     long VQA_TimerMethod(void);\n*\n* FUNCTION\n*     Returns the ID of the current timer method being used.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Method - Method used for the timer.\n*\n****************************************************************************/\n\nlong VQA_TimerMethod(void)\n{\n\t#if(VQAAUDIO_ON)\n\treturn (TimerMethod);\n\t#else\n\treturn (VQA_TMETHOD_DOS);\n\t#endif\n}\n\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n\n\u001a"
  },
  {
    "path": "WINVQ/VQA32/OLD/BCC32.CFG",
    "content": "-c\n-3\n-d\n-H=c:\\projects\\vqa32\\obj\\headers.sym\n-wpro\n-weas\n-wpre\n-IC:\\PROJECTS\\INCLUDE;C:\\DEV\\BC4\\INCLUDE;C:\\DEV\\TNT\\INCLUDE\n-DPHARLAP_TNT=1\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/CAPTION.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library (32 bit protected mode)\n*\n* FILE\n*     caption.c\n*\n* DESCRIPTION\n*     Text caption process/display manager.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 26, 1995\n*\n****************************************************************************/\n\n#include <mem.h>\n#include <malloc.h>\n#include <vqm32\\font.h>\n#include <vqm32\\text.h>\n#include <vqm32\\graphics.h>\n#include <vqm32\\captoken.h>\n#include \"caption.h\"\n\n#if( VQACAPTIONS_ON )\n\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n#define NUM_NODES 3\n\n/* Function prototypes. */\nstatic CaptionNode *AddCaptionNode(CaptionList *list, CaptionText *captext);\nstatic void RemCaptionNode(CaptionList *list, CaptionNode *node);\n\n\n/****************************************************************************\n*\n* NAME\n*     OpenCaptions - Initialize the caption system.\n*\n* SYNOPSIS\n*     OpenCaptions(Captions, Font)\n*\n*     CaptionInfo *OpenCaptions(void *, void *);\n*\n* FUNCTION\n*     Allocate and initialize resources used by the caption system.\n*\n* INPUTS\n*     Captions - Captions to process.\n*     Font     - Font to use to display captions.\n*\n* RESULT\n*     CaptionInfo - Caption information structure.\n*\n* SEE ALSO\n*     CloseCaption\n*\n****************************************************************************/\n\nCaptionInfo *OpenCaptions(void *captions, void *font)\n{\n\tCaptionInfo *cap = NULL;\n\tCaptionNode *node;\n\tFontInfo    *fi;\n\tlong        i;\n\n\t/* Allocate memory for the captioning system. */\n\tcap = (CaptionInfo *)malloc(sizeof(CaptionInfo) + (sizeof(CaptionNode)\n\t\t\t* NUM_NODES));\n\n\tif (cap != NULL) {\n\t\tmemset(cap,0,(sizeof(CaptionInfo) + (sizeof(CaptionNode) * NUM_NODES)));\n\t\tcap->Buffer = captions;\n\t\tcap->Next = (CaptionText *)captions;\n\n\t\t/* Initialize font */\n\t\tfi = (FontInfo *)((char *)font + ((Font *)font)->InfoBlk);\n\t\tcap->Font = font;\n\t\tcap->FontHeight = fi->MaxHeight;\n\t\tcap->FontWidth = fi->MaxWidth;\n\n\t\t/* Initialize list header. */\n\t\tcap->List.Head = (CaptionNode *)&cap->List.Tail;\n\t\tcap->List.Tail = NULL;\n\t\tcap->List.TailPred = (CaptionNode *)&cap->List.Head;\n\n\t\t/* Link nodes. */\n\t\tnode = (CaptionNode *)((char *)cap + sizeof(CaptionInfo));\n\n\t\tfor (i = 0; i < NUM_NODES; i++) {\n\t\t\tnode->Succ = cap->List.Head;\n\t\t\tcap->List.Head = node;\n\t\t\tnode->Pred = (CaptionNode *)&cap->List.Head;\n\t\t\tnode->Succ->Pred = node;\n\n\t\t\t/* Next node. */\n\t\t\tnode = (CaptionNode *)((char *)node + sizeof(CaptionNode));\n\t\t}\n\t}\n\n\treturn (cap);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     CloseCaptions - Shutdown the caption system.\n*\n* SYNOPSIS\n*     CloseCaptions(CaptionInfo)\n*\n*     void CloseCaptions(CaptionInfo *);\n*\n* FUNCTION\n*     Free the resources allocated by the caption system.\n*\n* INPUTS\n*     CaptionInfo - Caption information structure.\n*\n* RESULT\n*     NONE\n*\n* SEE ALSO\n*     OpenCaptions\n*\n****************************************************************************/\n\nvoid CloseCaptions(CaptionInfo *cap)\n{\n\tfree(cap);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DoCaption - Process and display caption text.\n*\n* SYNOPSIS\n*     DoCaption(Captions, Frame)\n*\n*     void DoCaption(CaptionInfo *, unsigned long);\n*\n* FUNCTION\n*     Process the caption events.\n*\n* INPUTS\n*     Captions - Pointer to CaptionInfo structure.\n*     Frame    - Current frame number being processed.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid DoCaptions(CaptionInfo *cap, unsigned long frame)\n{\n\tCaptionText *captext;\n\tCaptionNode *node;\n\tvoid const  *oldfont;\n\tlong        width;\n\tlong        i;\n\n\t/* Initialize variables. */\n\toldfont = Set_Font((char *)cap->Font);\n\n\t/*-------------------------------------------------------------------------\n\t * Process the captions that are on the active queue.\n\t *-----------------------------------------------------------------------*/\n\tnode = cap->List.Head;\n\n\twhile ((node->Succ != NULL) && (node->Flags & CNF_USED)) {\n\t\tcaptext = node->Captext;\n\n\t\t/* Clear the any previous captions that have expired. */\n\t\tif (captext->OffFrame <= frame) {\n\t\t\tFill_Rect(captext->Xpos, captext->Ypos,\n\t\t\t\t\t(captext->Xpos + node->BoundW - 1),\n\t\t\t\t\t(captext->Ypos + node->BoundH - 1), 0);\n\n\t\t\t/* Remove the caption from the active list. */\n\t\t\tnode = node->Pred;\n\t\t\tRemCaptionNode(&cap->List, node->Succ);\n\t\t} else {\n\t\t\tif (captext->CPF != 0) {\n\n\t\t\t\t/* If a NULL terminator is not found then display the next set of\n\t\t\t\t * characters, otherwise remove the node.\n\t\t\t\t */\n\t\t\t\tif (*node->Char != 0) {\n\t\t\t\t\tSet_Font_Palette_Range(&captext->BgPen, 0, 1);\n\n\t\t\t\t\tfor (i = 0; i < captext->CPF; i++) {\n\n\t\t\t\t\t\t/* Check for terminator. */\n\t\t\t\t\t\tif (*node->Char == 0) {\n\t\t\t\t\t\t\tcaptext->CPF = 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t/* Check for newline. */\n\t\t\t\t\t\telse if (*node->Char == 0x0D) {\n\t\t\t\t\t\t\tnode->Char++;\n\t\t\t\t\t\t\tnode->CurX = captext->Xpos;\n\t\t\t\t\t\t\tnode->CurY += cap->FontHeight;\n\t\t\t\t\t\t\tnode->BoundH += cap->FontHeight;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tDraw_Char(*node->Char, node->CurX, node->CurY);\n\t\t\t\t\t\tnode->CurX += Char_Pixel_Width(*node->Char);\n\t\t\t\t\t\tnode->Char++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (captext->Flags & CTF_FLASH) {\n\t\t\t\tif (frame & 4) {\n\t\t\t\t\tFill_Rect(captext->Xpos, captext->Ypos,\n\t\t\t\t\t\t\t(captext->Xpos + node->BoundW - 1),\n\t\t\t\t\t\t\t(captext->Ypos + node->BoundH - 1), 0);\n\t\t\t\t} else {\n\t\t\t \t\tText_Print(captext->Text, captext->Xpos, captext->Ypos,\n\t\t\t\t\t\t\tcaptext->FgPen, captext->BgPen);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Next node. */\n\t\tnode = node->Succ;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * Process any captions that are waiting to be activated.\n\t *-----------------------------------------------------------------------*/\n\tcaptext = cap->Next;\n\n\twhile (captext->OnFrame <= frame) {\n\n\t\twidth = String_Pixel_Width(captext->Text);\n\n\t\tswitch (captext->Flags & CTF_JUSTIFY) {\n\t\t\tcase CTF_RIGHT:\n\t\t\t\tcaptext->Xpos = (319 - width);\n\t\t\t\tbreak;\n\n\t\t\tcase CTF_LEFT:\n\t\t\t\tcaptext->Xpos = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase CTF_CENTER:\n\t\t\t\tcaptext->Xpos = (160 - (width / 2));\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/* Display the text and record its bounding box. */\n\t\tif (captext->CPF == 0) {\n\t \t\ti = Text_Print(captext->Text, captext->Xpos, captext->Ypos,\n\t\t\t\t\tcaptext->FgPen, captext->BgPen);\n\n\t\t\tnode = AddCaptionNode(&cap->List, captext);\n\t\t\tnode->BoundW = width;\n\t\t\tnode->BoundH = (cap->FontHeight * i);\n\t\t} else {\n\t\t\tnode = AddCaptionNode(&cap->List, captext);\n\t\t\tnode->BoundW = width;\n\t\t\tnode->BoundH = cap->FontHeight;\n\t\t}\n\n\t\t/* Next */\n\t\tcap->Next = (CaptionText *)(((char *)captext) + captext->Size);\n\t\tcaptext = cap->Next;\n\t}\n\n\tSet_Font(oldfont);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     AddCaptionNode - Add a caption to the processing list.\n*\n* SYNOPSIS\n*     Node = AddCaptionNode(List, Caption)\n*\n*     CaptionNode *AddCaptionNode(CaptionList *, CaptionText *);\n*\n* FUNCTION\n*     Add a caption the caption processing list.\n*\n* INPUTS\n*     List    - Caption processing list.\n*     Caption - Caption to add to the list.\n*\n* RESULT\n*     Node - Pointer to node, otherwise NULL if error.\n*\n****************************************************************************/\n\nstatic CaptionNode *AddCaptionNode(CaptionList *list, CaptionText *captext)\n{\n\tCaptionNode *node = NULL;\n\n\t/* If this list is not full. */\n\tnode = list->TailPred;\n\n\tif (!(node->Flags & CNF_USED)) {\n\n\t\t/* Remove the node from the tail. */\n\t\tnode->Pred->Succ = node->Succ;\n\t\tlist->TailPred = node->Pred;\n\n\t\tnode->Flags |= CNF_USED;\n\t\tnode->Captext = captext;\n\t\tnode->Char = captext->Text;\n\t\tnode->CurX = captext->Xpos;\n\t\tnode->CurY = captext->Ypos;\n\t\t\n\t\t/* Add the node to the head. */\n\t\tnode->Succ = list->Head;\n\t\tlist->Head = node;\n\t\tnode->Pred = (CaptionNode *)&list->Head;\n\t\tnode->Succ->Pred = node;\n\t}\n\n\treturn (node);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     RemCaptionNode - Remove a caption from the processing list.\n*\n* SYNOPSIS\n*     RemCaptionNode(List, Node)\n*\n*     void RemCaptionNode(CaptionList *, CaptionNode *);\n*\n* FUNCTION\n*     Remove the caption from the processing list. Mark the node as unused\n*     and put it at the tail of the list.\n*\n* INPUTS\n*     List - Caption processing list.\n*     Node - Caption node to remove.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void RemCaptionNode(CaptionList *list, CaptionNode *node)\n{\n\t/* If the nodes successor is null then we are at the tail. */\n\tif (node->Succ != NULL) {\n\n\t\t/* Mark the node as unused. */\n\t\tnode->Flags = 0;\n\n\t\t/* Relink the node to the tail. */\n\t\tnode->Succ->Pred = node->Pred;\n\t\tnode->Pred->Succ = node->Succ;\n\t\tnode->Succ = (CaptionNode *)&list->Tail;\n\t\tnode->Pred = list->TailPred;\n\t\tlist->TailPred->Succ = node;\n\t\tlist->TailPred = node;\n\t}\n}\n\n\n#endif // VQACAPTIONS_ON\n\u001a"
  },
  {
    "path": "WINVQ/VQA32/OLD/CAPTION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQACAPTION_H\n#define VQACAPTION_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library (32 bit protected mode)\n*\n* FILE\n*     caption.h\n*\n* DESCRIPTION\n*     Text caption definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 26, 1995\n*\n****************************************************************************/\n\n\n#define VQACAPTIONS_ON\t\t0\n\n/*---------------------------------------------------------------------------\n * STRUCTURES AND RELATED DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* CaptionNode: Node describing a caption to process.\n *\n * Succ    - Pointer to the next node in the list (successor).\n * Pred    - Pointer to the previous node in the list (predecessor).\n * Flags   - Status flags.\n * CapText - Pointer to the CaptionText being processed.\n * Char    - Pointer to current character in the string.\n * CurX    - Current X position.\n * CurY    - Current Y position.\n * BoundW  - Bounding width of text.\n * BoundH  - Bounding height of text.\n */\ntypedef struct _CaptionNode {\n\tstruct _CaptionNode *Succ;\n\tstruct _CaptionNode *Pred;\n\tunsigned short      Flags;\n\tCaptionText         *Captext;\n\tchar                *Char;\n\tunsigned short      CurX;\n\tunsigned short      CurY;\n\tunsigned short      BoundW;\n\tunsigned short      BoundH;\n} CaptionNode;\n\n/* CaptionNode flag definitions. */\n#define CNB_USED 0  /* This node is being used. */\n#define CNF_USED (1<<CNB_USED)\n\n\n/* CaptionList: Double linked list of outstanding captions to process.\n *\n * Head     - Pointer to the first node in the list.\n * Tail     - Always NULL\n * TailPred - Pointer to the last node in the list.\n */\ntypedef struct _CaptionList {\n\tCaptionNode *Head;\n\tCaptionNode *Tail;\n\tCaptionNode *TailPred;\n} CaptionList;\n\n\n/* CaptionInfo:\n *\n * Next   - Pointer to the next caption to be processed.\n * List   - List of pending captions to process.\n * Font   - Font to use for this caption.\n * BoundX - X position of bounding box.\n * BoundY - Y position of bounding box.\n * BoundW - Width of bounding box.\n * BoundH - Height of bounding box.\n * Buffer - Caption chunk buffer.\n */\ntypedef struct _CaptionInfo {\n\tCaptionText    *Next;\n\tCaptionList    List;\n\tvoid           *Font;\n\tchar           FontHeight;\n\tchar           FontWidth;\n\tvoid           *Buffer;\n} CaptionInfo;\n\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\nCaptionInfo *OpenCaptions(void *captions, void *font);\nvoid CloseCaptions(CaptionInfo *cap);\nvoid DoCaptions(CaptionInfo *cap, unsigned long frame);\n\n#endif /* VQACAPTION_H */\n\n\u001a"
  },
  {
    "path": "WINVQ/VQA32/OLD/CONFIG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     config.c\n*\n* DESCRIPTION\n*     Player configuration routines.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 10, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_INIConfig     - Initialize VQAConfig structure with INI settings.\n*     VQA_DefaultConfig - Initialize VQAConfig structure with defaults.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n/* Default configuration structure. */\nstatic VQAConfig _defaultconfig = {\n\n\t/* DrawerCallback: This is a function that is called for every frame\n\t * in the movie.\n\t */\n\tNULL,\n\n\t/* EventHandler: This is a function that is called for every event that\n\t * the client requested to be notified about.\n\t */\n\tNULL,\n\n\t/* NotifyFlags: Flags representing the events the client wishes to be\n\t * notified about during playback.\n\t */\n\tNULL,\n\n\t/* Vmode: Video mode to use. */\n\tMCGA,\n\n\t/* VBIBit: Vertical blank bit polarity. */\n\t-1,\n\n\t/* ImageBuf: Pointer to image buffer to draw into. */\n\tNULL,\n\n\t/* ImageWidth, ImageHeight: Width and height dimensions of image buffer.\n\t * A width and height value of -1 tells the player to consider the image\n\t * buffer as having the same dimensions as the frames in the movie.\n\t */\n\t320, 200, /* Image width and height */\n\n\t/* X1, Y1: These are the coordinates to put the movies frame in the image\n\t * buffer. Values of -1 tell the drawer to center the frames in the buffer.\n\t */\n\t-1, -1,\n\n\t/* FrameRate: The rate to load the frames at. A value of -1 tells the\n\t * player to use the framerate of the movie.\n\t */\n\t-1,\n\n\t/* DrawRate: The rate to draw the frames at. A value of -1 tells the\n\t * player to use the framerate of the movie. A value of 0 tells the player\n\t * to use a fixed rate based on the frame size.\n\t */\n\t-1,\n\n\t/* TimerMethod: Timer method to use for playback. */\n\t-1,\n\n\t/* DrawFlags: Various drawing related flags. */\n\t0,\n\n\t/* OptionFlags: Various player options. */\n\tVQAOPTF_AUDIO,\n\n\t/* NumFrameBufs: The number of frame buffers to allocate/use. */\n\t6,\n\n\t/* NumCBBufs: The number of codebook buffers to allocate/use. */\n\t3,\n\n\t/* VocFile: Filename of audio track override. A value of 0 tells the\n\t * player not to override the movies audio track.\n\t */\n\tNULL,\n\n\t/* AudioBuf: Audio buffer to use. A value of 0 tells the player that\n\t * it has to allocate a buffer itself.\n\t */\n\tNULL,\n\n\t/* AudioBufSize: Size of audio buffer to use/allocate. A value of -1\n\t * tells the player to compute the buffer size from the audio\n\t * information in the movie.\n\t */\n\t-1,\n\n\t/* AudioRate: Audio playback rate in samples per second. A value of -1\n\t * tells the player to use the audio rate of the movie.\n\t */\n\t-1,\n\n\t/* Volume: Volume level to playback audio track. */\n\t0x00FF,\n\n\t/* HMIBufSize: Size of HMIs internal buffer. */\n\t2048L,\n\n\t/* DigiHandle: Handle to an initialized HMI sound driver. A value of -1\n\t * tells the player it must initialize the HMI sound driver itself.\n\t */\n\t-1,\n\n\t/* DigiCard: HMI ID of audio card to use. A value of 0 tells the player\n\t * not to use any card. A value of -1 tells the player to autodetect the\n\t * card in the system.\n\t */\n\t-1,\n\n\t/* DigiPort: Port address of the sound card. A value of -1 tells the player\n\t * to autodetect this address.\n\t */\n\t-1,\n\n\t/* DigiIRQ: Interrupt number of sound card. A value of -1 tells the player\n\t * to autodetect the interrupt used by the card.\n\t */\n\t-1,\n\n\t/* DigiDMA: DMA channel of the sound card. A value of -1 tells the player\n\t * to autodetect the channel used by the card.\n \t */\n\t-1,\n\n\t/* Language: Prefered language. */\n\t0,\n\n\t/* CaptionFont: Caption text font. */\n\tNULL,\n};\n\n/* Supported video modes. */\n#if(VQAVIDEO_ON)\nenum VMTAGS {\n\tVMTAG_NONE = 0,\n\n\t#if(VQAMCGA_ON)\n\tVMTAG_MCGA,\n\tVMTAG_MCGA_BUF,\n\t#endif\n\n\t#if(VQAXMODE_ON)\n\tVMTAG_XMODE320X200,\n\tVMTAG_XMODE320X200_BUF,\n\tVMTAG_XMODE320X200_VRAM,\n\tVMTAG_XMODE320X240,\n\tVMTAG_XMODE320X240_BUF,\n\tVMTAG_XMODE320X240_VRAM,\n\t#endif\n\n\t#if(VQAVESA_ON)\n\tVMTAG_VESA640X480_BUF,\n\tVMTAG_VESA640X480_X2,\n\tVMTAG_VESA320X200,\n\tVMTAG_VESA320X200_BUF,\n\t#endif\n};\n\ntypedef struct _VideoModeTag {\n\tchar const *token;\n\tlong       id;\n} VideoModeTag;\n\nVideoModeTag VideoModeTags[] = {\n\t{\"NONE\",VMTAG_NONE},\n\n\t#if(VQAMCGA_ON)\n\t{\"MCGA\",    VMTAG_MCGA},\n\t{\"MCGA_BUF\",VMTAG_MCGA_BUF},\n\t#endif /* VQAMCGA_ON */\n\n\t#if(VQAXMODE_ON)\n\t{\"XMODE_320X200\",     VMTAG_XMODE320X200},\n\t{\"XMODE_320X200_BUF\", VMTAG_XMODE320X200_BUF},\n\t{\"XMODE_320X200_VRAM\",VMTAG_XMODE320X200_VRAM},\n\t{\"XMODE_320X240\",     VMTAG_XMODE320X240},\n\t{\"XMODE_320X240_BUF\", VMTAG_XMODE320X240_BUF},\n\t{\"XMODE_320X240_VRAM\",VMTAG_XMODE320X240_VRAM},\n\t#endif /* VQAXMODE_ON */\n\n\t#if(VQAVESA_ON)\n\t{\"VESA_640X480_BUF\",VMTAG_VESA640X480_BUF},\n\t{\"VESA_640X480_X2\", VMTAG_VESA640X480_X2},\n\t{\"VESA_320X200\",    VMTAG_VESA320X200},\n\t{\"VESA_320X200_BUF\",VMTAG_VESA320X200_BUF},\n\t#endif /* VQAVESA_ON */\n\n\t{NULL, NULL}\n};\n#endif /* VQAVIDEO_ON */\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_INIConfig - Initialize VQAConfig structure with INI settings.\n*\n* SYNOPSIS\n*     VQA_INIConfig(Config)\n*\n*     void VQA_INIConfig(VQAConfig *);\n*\n* FUNCTION\n*     Initializes the configuration structure from the player INI file.\n*\n* INPUTS\n*     Config - Pointer to VQAConfig structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_INIConfig(VQAConfig *config)\n{\n\tchar *ininame;\n\tchar buf[80];\n\tlong i;\n\n\t/* Set all Config entries to 0. */\n\tmemset(config, 0, sizeof(VQAConfig));\n\n\t/* Retrieve player INI filename from an enviroment variable if\n\t * it is provided.\n\t */\n\tif ((ininame = getenv(\"VQACFG\")) == NULL) {\n\t\tininame = \"PLAYER.INI\";\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * VIDEO MODE AND DRAW FLAGS\n\t *-----------------------------------------------------------------------*/\n\t#if(VQAVIDEO_ON)\n\t/* Get video mode from INI */\n\tGetINIString(\"Player\", \"PlayerMode\", \"MCGA\", buf, 80, ininame);\n\n\t/* Search supported modes for a match. */\n\ti = 0;\n\n\twhile (VideoModeTags[i].token != NULL) {\n\t\tif (stricmp(buf, VideoModeTags[i].token) == 0) {\n\t\t\tbreak;\n\t\t}\n\t\ti++;\n\t}\n\n\t/* Setup for requested mode */\n\tswitch (VideoModeTags[i].id) {\n\n\t\t/* MCGA direct */\n\t\t#if(VQAMONO_ON)\n\t\tcase VMTAG_MCGA:\n\t\t\tconfig->Vmode = MCGA;\n\t\t\tbreak;\n\n\t\t/* MCGA buffered */\n\t\tcase VMTAG_MCGA_BUF:\n\t\t\tconfig->Vmode = MCGA;\n\t\t\tconfig->DrawFlags |= VQACFGF_BUFFER;\n\t\t\tbreak;\n\t\t#endif /* VQAMCGA_ON */\n\n\t\t/* XMODE direct (320x200) */\n\t\t#if(VQAXMODE_ON)\n\t\tcase VMTAG_XMODE320X200:\n\t\t\tconfig->Vmode = XMODE_320X200;\n\t\t\tbreak;\n\n\t\t/* XMODE buffered (320x200) */\n\t\tcase VMTAG_XMODE320X200_BUF:\n\t\t\tconfig->Vmode = XMODE_320X200;\n\t\t\tconfig->DrawFlags |= VQACFGF_BUFFER;\n\t\t\tbreak;\n\n\t\t/* XMODE VRAM codebook (320x200) */\n\t\tcase VMTAG_XMODE320X200_VRAM:\n\t\t\tconfig->Vmode = XMODE_320X200;\n\t\t\tconfig->DrawFlags |= VQACFGF_VRAMCB;\n\t\t\tbreak;\n\n\t\t/* XMODE direct (320x240) */\n\t\tcase VMTAG_XMODE320X240:\n\t\t\tconfig->Vmode = XMODE_320X240;\n\t\t\tbreak;\n\n\t\t/* XMODE buffered (320x240) */\n\t\tcase VMTAG_XMODE320X240_BUF:\n\t\t\tconfig->Vmode = XMODE_320X240;\n\t\t\tconfig->DrawFlags |= VQACFGF_BUFFER;\n\t\t\tbreak;\n\n\t\t/* XMODE VRAM codebook (320x240) */\n\t\tcase VMTAG_XMODE320X240_VRAM:\n\t\t\tconfig->Vmode = XMODE_320X240;\n\t\t\tconfig->DrawFlags |= VQACFGF_VRAMCB;\n\t\t\tbreak;\n\t\t#endif /* VQAXMODE_ON */\n\n\t\t/* VESA buffered (640x480_256) */\n\t\t#if(VQAVESA_ON)\n\t\tcase VMTAG_VESA640X480_BUF:\n\t\t\tconfig->Vmode = VESA_640X480_256;\n\t\t\tconfig->DrawFlags |= VQACFGF_BUFFER;\n\t\t\tbreak;\n\n\t\t/* VESA buffered scaled (640x480_256) */\n\t\tcase VMTAG_VESA640X480_X2:\n\t\t\tconfig->Vmode = VESA_640X480_256;\n\t\t\tconfig->DrawFlags |= (VQACFGF_BUFFER|VQACFGF_SCALEX2);\n\t\t\tbreak;\n\n\t\t/* VESA direct (320x200_32k) */\n\t\tcase VMTAG_VESA320X200:\n\t\t\tconfig->Vmode = VESA_320X200_32K_1;\n\t\t\tbreak;\n\n\t\t/* VESA buffered (320x200_32k) */\n\t\tcase VMTAG_VESA320X200_BUF:\n\t\t\tconfig->Vmode = VESA_320X200_32K_1;\n\t\t\tconfig->DrawFlags |= VQACFGF_BUFFER;\n\t\t\tbreak;\n\t\t#endif /* VQAVESA_ON */\n\n\t\t/* Default to MCGA direct */\n\t\tVMTAG_NONE:\n\t\tdefault:\n\t\t\tconfig->Vmode = MCGA;\n\t\t\tbreak;\n\t}\n\t#endif /* VQAVIDEO_ON */\n\n\t/* Get framerate and drawrate. */\n\tGetINIString(\"Player\", \"FrameRate\", \"-1\", buf, 80, ininame);\n\tconfig->FrameRate = atoi(buf);\n\n\tGetINIString(\"Player\", \"DrawRate\", \"Variable\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"Variable\")) {\n\t\tconfig->DrawRate = -1;\n\t} else {\n\t\tconfig->DrawRate = 0;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * AUDIO SETTINGS\t \n\t *-----------------------------------------------------------------------*/\n\tGetINIString(\"Player\", \"AudioRate\", \"-1\", buf, 80, ininame);\n\tconfig->AudioRate = atoi(buf);\n\n\t/* OptionFlags */\n\tGetINIString(\"Player\", \"SoundEnabled\", \"True\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"True\") || !stricmp(buf, \"1\")) {\n\t\tconfig->OptionFlags |= VQAOPTF_AUDIO;\n\t} else {\n\t\tconfig->OptionFlags &= (~VQAOPTF_AUDIO);\n\t}\n\n\t/* Default audio settings. */\n\tconfig->AudioBufSize = 32768U;\n\tconfig->HMIBufSize = 2048;\n\tconfig->DigiHandle = -1;\n\tconfig->Volume = 0x00FF;\n\tconfig->DigiCard = 0xFFFF;\n\tconfig->DigiPort = -1;\n\tconfig->DigiIRQ = -1;\n\tconfig->DigiDMA = -1;\n\n\t/* Configure sound hardware */\n\tGetINIString(\"Player\", \"Port\", \"-1\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"-1\")) {\n\t\tconfig->DigiPort = -1;\n\t} else {\n\t\tsscanf(buf, \"%x\", &config->DigiPort);\n\t}\n\n\tGetINIString(\"Player\", \"IRQ\", \"-1\", buf, 80, ininame);\n\tconfig->DigiIRQ = atoi(buf);\n\tGetINIString(\"Player\", \"DMA\", \"-1\", buf, 80, ininame);\n\tconfig->DigiDMA = atoi(buf);\n\n\t/*-------------------------------------------------------------------------\n\t * GENERAL OPTIONS\n\t *-----------------------------------------------------------------------*/\n\n\t/* Enable/Disable single stepping */ \n\tGetINIString(\"Player\", \"SingleStep\", \"False\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"True\") || !stricmp(buf, \"1\")) {\n\t\tconfig->OptionFlags |= VQAOPTF_STEP;\n\t\tconfig->DrawFlags |= VQACFGF_NOSKIP;\n\t} else {\n\t\tconfig->OptionFlags &= (~VQAOPTF_STEP);\n\t}\n\n\t/* Enable/Disable Slowpalette */\n\tGetINIString(\"Player\", \"SlowPalette\", \"False\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"True\") || !stricmp(buf, \"1\")) {\n\t\tconfig->OptionFlags |= VQAOPTF_SLOWPAL;\n\t} else {\n\t\tconfig->OptionFlags &= (~VQAOPTF_SLOWPAL);\n\t}\n\n\t/* Enable/Disable monochrome display */\n\tGetINIString(\"Player\", \"MonoOutput\", \"False\", buf, 80, ininame);\n\n\tif (!stricmp(buf, \"True\") || !stricmp(buf, \"1\")) {\n\t\tconfig->OptionFlags |= VQAOPTF_MONO;\n\t} else {\n\t\tconfig->OptionFlags &= (~VQAOPTF_MONO);\n\t}\n\n\t/* Frame and codebook buffers */\n\tconfig->NumFrameBufs = 6;\n\tconfig->NumCBBufs = 3;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_DefaultConfig - Initialize VQAConfig structure with defaults.\n*\n* SYNOPSIS\n*     VQA_DefaultConfig(Config);\n*\n*     void VQA_DefaultConfig(VQAConfig *);\n*\n* FUNCTION\n*     Initialize configuration with default settings.\n*\n* INPUTS\n*     Config - Pointer to VQA configuration structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_DefaultConfig(VQAConfig *config)\n{\n\tmemcpy(config, &_defaultconfig, sizeof(VQAConfig));\n}\n\n\n\n\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/DRAWER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQAPlay32 library. (32-Bit protected mode)\n*\n* FILE\n*     drawer.c\n*\n* DESCRIPTION\n*     Frame drawing and page flip control.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     June 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_Configure_Drawer - Configure the drawer routines.\n*\n* PRIVATE\n*     Select_Frame             - Selects frame to draw and preforms frame\n*                                skip.\n*     Prepare_Frame            - Process/Decompress frame information.\n*     DrawFrame_Xmode          - Draws a frame directly to Xmode screen.\n*     DrawFrame_XmodeBuf       - Draws a frame in Xmode format to a buffer.\n*     DrawFrame_XmodeVRAM      - Draws a frame in Xmode with resident\n*                                Codebook.\n*     PageFlip_Xmode           - Page flip Xmode display.\n*     DrawFrame_MCGA           - Draws a frame directly to MCGA screen.\n*     PageFlip_MCGA            - Page flip MCGA display.\n*     DrawFrame_MCGABuf        - Draws a frame in MCGA format to a buffer.\n*     PageFlip_MCGABuf         - Page flip a buffered MCGA display.\n*     DrawFrame_VESA640        - Draws a frame in VESA640 format.\n*     DrawFrame_VESA320_32K    - Draws a frame to VESA320_32K screen.\n*     DrawFrame_VESA320_32KBuf - Draws a frame in VESA320_32K format to a\n*                                buffer.\n*     PageFlip_VESA            - Page flip VESA display.\n*     DrawFrame_Buffer         - Draw a frame to a buffer.\n*     PageFlip_Nop             - Do nothing page flip.\n*     UnVQ_Nop                 - Do nothing UnVQ.\n*     Mask_Rect                - Sets non-drawable rectangle in image.\n*     Mask_Pointers            - Mask vector pointer that are in the mask\n*                                rectangle.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <malloc.h>\n#include <conio.h>\n#include <dos.h>\n#include <mem.h>\n#include \"vq.h\"\n#include \"unvq.h\"\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n#include \"caption.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\nstatic long Select_Frame(VQAHandleP *vqap);\nstatic void Prepare_Frame(VQAData *vqabuf);\n\n#if(VQAMCGA_ON)\nstatic long DrawFrame_MCGABuf(VQAHandle *vqa);\nstatic long PageFlip_MCGABuf(VQAHandle *vqa);\nstatic long DrawFrame_MCGA(VQAHandle *vqa);\nstatic long PageFlip_MCGA(VQAHandle *vqa);\n#endif /* VQAMCGA_ON */\n\n#if(VQAXMODE_ON)\nstatic long DrawFrame_XmodeBuf(VQAHandle *vqa);\nstatic long DrawFrame_Xmode(VQAHandle *vqa);\nstatic long DrawFrame_XmodeVRAM(VQAHandle *vqa);\nstatic void PageFlip_Xmode(VQAHandle *vqabuf);\n#endif /* VQAXMODE_ON */\n\n#if(VQAVESA_ON)\nstatic long DrawFrame_VESA640(VQAHandle *vqa);\nstatic long DrawFrame_VESA320_32K(VQAHandle *vqa);\nstatic long DrawFrame_VESA320_32KBuf(VQAHandle *vqa);\nstatic void PageFlip_VESA(VQAHandle *vqabuf);\n#endif /* VQAVESA_ON */\n\nstatic long DrawFrame_Buffer(VQAHandle *vqa);\nstatic long PageFlip_Nop(VQAHandle *vqa);\n\n#ifndef PHARLAP_TNT\nstatic void cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n#else\nstatic void cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n#endif\n\n#if(0)\nstatic void Mask_Rect(VQAHandle *vqa, unsigned long x1, unsigned long y1,\n\t\tunsigned long x2, unsigned long y2);\nstatic void Mask_Pointers(VQAData *vqabuf);\n#endif\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_GetPalette - Get the palette used in the movie.\n*\n* SYNOPSIS\n*     Palette = VQA_GetPalette(VQA)\n*\n*     char *VQA_GetPalette(VQAHandle *);\n*\n* FUNCTION\n*     Retrieve the address of the current palette used in the movie. If there\n*     isn't a palette available then a NULL value will be returned.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle to get palette for.\n*\n* RESULT\n*     Palette - Pointer to palette or NULL if no palette available.\n*\n****************************************************************************/\n\nunsigned char *VQA_GetPalette(VQAHandle *vqa)\n{\n\tVQADrawer *drawer;\n\tunsigned char *palette = NULL;\n\n\t/* Dereference commonly used data members for quick access. */\n\tdrawer = &((VQAHandleP *)vqa)->VQABuf->Drawer;\n\n\tif (drawer->CurPalSize > 0) {\n\t\tpalette = drawer->Palette_24;\n\t}\n\n\treturn (palette);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_GetPaletteSize - Get the size of the palette used in the movie.\n*\n* SYNOPSIS\n*     PalSize = VQA_GetPaletteSize(VQA)\n*\n*     long VQA_GetPaletteSize(VQAHandle *);\n*\n* FUNCTION\n*     Retrieve the size of the current palette used in the movie. If there\n*     isn't a palette available then a zero size will be returned.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle to get palette for.\n*\n* RESULT\n*     PalSize - Size in bytes of the current palette.\n*\n****************************************************************************/\n\nlong VQA_GetPaletteSize(VQAHandle *vqa)\n{\n\tVQADrawer *drawer;\n\n\t/* Dereference commonly used data members for quick access. */\n\tdrawer = &((VQAHandleP *)vqa)->VQABuf->Drawer;\n\n\treturn (drawer->CurPalSize);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Set_DrawBuffer - Set the buffer to draw the images to.\n*\n* SYNOPSIS\n*     VQA_Set_DrawBuffer(VQA, Buffer, Width, Height, XPos, YPos)\n*\n*     void VQA_Set_DrawBuffer(VQAHandle *, unsigned char *,\n*                             unsigned long, unsigned long, unsigned long,\n*                             unsigned long);\n*\n* FUNCTION\n*     Set the draw buffer to the buffer provided by the client.\n*\n* INPUTS\n*     VQA    - Pointer to VQAHandle to set buffer for.\n*     Buffer - Pointer to new image buffer.\n*     Width  - Width of the buffer in pixels.\n*     Height - Height of the buffer in pixels.\n*     XPos   - X pixel position in buffer to draw image.\n*     YPos   - Y pixel position in buffer to draw image.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Set_DrawBuffer(VQAHandle *vqa, unsigned char *buffer,\n\t\tunsigned long width, unsigned long height,\n\t\tlong xpos, long ypos)\n{\n\tVQAHeader *header;\n\tVQADrawer *drawer;\n\tVQAConfig *config;\n\tlong      origin;\n\n\t/* Dereference commonly used data members for quick access. */\n\theader = &((VQAHandleP *)vqa)->Header;\n\tdrawer = &((VQAHandleP *)vqa)->VQABuf->Drawer;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\torigin = (config->DrawFlags & VQACFGF_ORIGIN);\n\n\t/* Set the drawer buffer information. */\n\tdrawer->ImageBuf = buffer;\n\tdrawer->ImageWidth = width;\n\tdrawer->ImageHeight = height;\n\n\t/*-------------------------------------------------------------------------\n\t * SET THE DRAW POSITION OF THE MOVIE.\n\t *\n\t * X1 = -1 -- Center image of the X axis, otherwise use X1 value.\n\t * Y1 = -1 -- Center image of the Y axis, otherwise use Y1 value.\n\t *-----------------------------------------------------------------------*/\n\tif ((xpos == -1) && (ypos == -1)) {\n\n\t\t#if(VQAVIDEO_ON)\n\t\tdrawer->X1 = ((drawer->Display->XRes - header->image_width) / 2);\n\t\tdrawer->Y1 = ((drawer->Display->YRes - header->image_height) / 2);\n\t\t#else  /* VQAVIDEO_ON */\n\t\tdrawer->X1 = ((width - header->ImageWidth) / 2);\n\t\tdrawer->Y1 = ((height - header->ImageHeight) / 2);\n\t\t#endif /* VQAVIDEO_ON */\n\n\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\tdrawer->Y2 = ((drawer->Y1 + header->ImageHeight) - 1);\n\t} else {\n\t\tswitch (origin) {\n\t\t\tdefault:\n\t\t\tcase VQACFGF_TOPLEFT:\n\t\t\t\tdrawer->X1 = xpos;\n\t\t\t\tdrawer->Y1 = ypos;\n\t\t\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\t\t\tdrawer->Y2 = ((drawer->Y1 + header->ImageHeight) - 1);\n\t\t\t\tbreak;\n\n\t\t\tcase VQACFGF_BOTLEFT:\n\t\t\t\tdrawer->X1 = xpos;\n\t\t\t\tdrawer->Y1 = (height - ypos);\n\t\t\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\t\t\tdrawer->Y2 = ((drawer->Y2 - header->ImageHeight) - 1);\n\t\t\t\tbreak;\n\n\t\t\tcase VQACFGF_BOTRIGHT:\n\t\t\t\tdrawer->X1 = (width - xpos);\n\t\t\t\tdrawer->Y1 = (height - ypos);\n\t\t\t\tdrawer->X2 = (drawer->X1 - header->ImageWidth);\n\t\t\t\tdrawer->Y2 = (drawer->Y1 - header->ImageHeight);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/* Pre-compute the draw offset for speed. */\n\tdrawer->ScreenOffset = ((width * drawer->Y1) + drawer->X1);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Configure_Drawer - Configure the drawer routines.\n*\n* SYNOPSIS\n*     VQA_Configure_Drawer(VQA)\n*\n*     void VQA_Configure_Drawer(VQAHandleP *);\n*\n* FUNCTION\n*     Configure the drawing system for the current movie and configuration\n*     options.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Configure_Drawer(VQAHandleP *vqap)\n{\n\tVQAData   *vqabuf;\n\tVQAConfig *config;\n\tVQAHeader *header;\n\tVQADrawer *drawer;\n\tlong      origin;\n\tlong      blkdim;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\theader = &vqap->Header;\n\tconfig = &vqap->Config;\n\torigin = (config->DrawFlags & VQACFGF_ORIGIN);\n\n\t/*-------------------------------------------------------------------------\n\t * SET THE DRAW POSITION OF THE MOVIE.\n\t *\n\t * X1 = -1 -- Center image of the X axis, otherwise use X1 value.\n\t * Y1 = -1 -- Center image of the Y axis, otherwise use Y1 value.\n\t *-----------------------------------------------------------------------*/\n\tif ((config->X1 == -1) && (config->Y1 == -1)) {\n\n\t\t#if(VQAVIDEO_ON)\n\t\tdrawer->X1 = ((drawer->Display->XRes - header->image_width) / 2);\n\t\tdrawer->Y1 = ((drawer->Display->YRes - header->image_height) / 2);\n\t\t#else  /* VQAVIDEO_ON */\n\t\tdrawer->X1 = ((drawer->ImageWidth - header->ImageWidth) / 2);\n\t\tdrawer->Y1 = ((drawer->ImageHeight - header->ImageHeight) / 2);\n\t\t#endif /* VQAVIDEO_ON */\n\n\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\tdrawer->Y2 = ((drawer->Y1 + header->ImageHeight) - 1);\n\t} else {\n\t\tswitch (origin) {\n\t\t\tdefault:\n\t\t\tcase VQACFGF_TOPLEFT:\n\t\t\t\tdrawer->X1 = config->X1;\n\t\t\t\tdrawer->Y1 = config->Y1;\n\t\t\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\t\t\tdrawer->Y2 = ((drawer->Y1 + header->ImageHeight) - 1);\n\t\t\t\tbreak;\n\n\t\t\tcase VQACFGF_BOTLEFT:\n\t\t\t\tdrawer->X1 = config->X1;\n\t\t\t\tdrawer->Y1 = (drawer->ImageHeight - config->Y1);\n\t\t\t\tdrawer->X2 = ((drawer->X1 + header->ImageWidth) - 1);\n\t\t\t\tdrawer->Y2 = ((drawer->Y2 - header->ImageHeight) - 1);\n\t\t\t\tbreak;\n\n\t\t\tcase VQACFGF_BOTRIGHT:\n\t\t\t\tdrawer->X1 = (drawer->ImageWidth - config->X1);\n\t\t\t\tdrawer->Y1 = (drawer->ImageHeight - config->Y1);\n\t\t\t\tdrawer->X2 = (drawer->X1 - header->ImageWidth);\n\t\t\t\tdrawer->Y2 = (drawer->Y1 - header->ImageHeight);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE UNVQ ROUTINE FOR THE SPECIFIED VIDEO MODE AND BLOCK SIZE.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Pre-compute commonly used values for speed. */\n\tdrawer->BlocksPerRow = header->ImageWidth / header->BlockWidth;\n\tdrawer->NumRows = header->ImageHeight / header->BlockHeight;\n\tdrawer->NumBlocks = drawer->BlocksPerRow * drawer->NumRows;\n\tblkdim = BLOCK_DIM(header->BlockWidth, header->BlockHeight);\n\n\t/* Initialize draw routine vectors to a NOP routine in order to prevent\n\t * a crash.\n\t */\n\tvqabuf->UnVQ = UnVQ_Nop;\n\tvqabuf->Page_Flip = PageFlip_Nop;\n\n\t/* If the client specifies buffering then go ahead an set the unvq\n\t * vector. All of the buffered modes use the same unvq routines.\n\t */\n\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\tswitch (blkdim) {\n\t\t\t#if(VQABLOCK_2X2)\n\t\t\tcase BLOCK_2X2:\n\t\t\t\tvqabuf->UnVQ = UnVQ_2x2;\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\t#if(VQABLOCK_2X3)\n\t\t\tcase BLOCK_2X3:\n\t\t\t\tvqabuf->UnVQ = UnVQ_2x3;\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\t#if(VQABLOCK_4X2)\n\t\t\tcase BLOCK_4X2:\n\t\t\t\tvqabuf->UnVQ = UnVQ_4x2;\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\t#if(VQABLOCK_4X4)\n\t\t\tcase BLOCK_4X4:\n\t\t\t\tvqabuf->UnVQ = UnVQ_4x4;\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n \t\t}\n \t}\n\n\t/* Initialize the draw vectors for the specified video mode. */\n\tswitch (config->Vmode) {\n\n\t\t/* MCGA */\n\t\t#if(VQAMCGA_ON)\n\t\tcase MCGA:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_MCGABuf;\n\t\t\t\tvqabuf->Page_Flip = PageFlip_MCGABuf;\n\t\t\t} else {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_MCGA;\n\t\t\t\tvqabuf->Page_Flip = PageFlip_MCGA;\n\n\t\t\t\t/* MCGA uses the same unvq routines that are used for unvqing\n\t\t\t\t * to a buffer because MCGA mode is just another buffer. However,\n\t\t\t\t * instead of drawing to an allocated RAM buffer we are drawing\n\t\t\t\t * directly to the VRAM video buffer.\n\t\t\t\t */\n\t\t\t\tswitch (blkdim) {\n\t\t\t\t\t#if(VQABLOCK_2X2)\n\t\t\t\t\tcase BLOCK_2X2:\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_2x2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\n\t\t\t\t\t#if(VQABLOCK_2X3)\n\t\t\t\t\tcase BLOCK_2X3:\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_2x3;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\n\t\t\t\t\t#if(VQABLOCK_4X2)\n\t\t\t\t\tcase BLOCK_4X2:\n\t\t\t\t\t\t#if(!VQAWOOFER_ON)\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2;\n\t\t\t\t\t\t#else\n\t\t\t\t\t\tif (config->DrawFlags & VQACFGF_WOOFER) {\n\t\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2_Woofer;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t#endif\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\n\t\t\t\t\t#if(VQABLOCK_4X4)\n\t\t\t\t\tcase BLOCK_4X4:\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x4;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Pre-compute the draw offset for speed. */\n\t\t\tdrawer->ScreenOffset = ((320 * drawer->Y1) + drawer->X1);\n\t\t\tbreak;\n\t\t#endif /* VQAMCGA_ON */\n\n\t\t/* XMODE */\n\t\t#if(VQAXMODE_ON)\n\t\tcase XMODE_320X200:\n\t\tcase XMODE_320X240:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_XmodeBuf;\n\t\t\t\tvqabuf->Page_Flip = PageFlip_Xmode;\n\t\t\t} else {\n\t\t\t\tvqabuf->Page_Flip = PageFlip_Xmode;\n\n\t\t\t\tif (config->DrawFlags & VQACFGF_VRAMCB) {\n\t\t\t\t\tvqabuf->Draw_Frame = DrawFrame_XmodeVRAM;\n\n\t\t\t\t\tswitch (blkdim) {\n\t\t\t\t\t\t#if(VQABLOCK_4X2)\n\t\t\t\t\t\tcase BLOCK_4X2:\n\t\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2_XmodeCB;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t#endif /* VQABLOCK_4X2 */\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tvqabuf->Draw_Frame = DrawFrame_Xmode;\n\n\t\t\t\t\tswitch (blkdim) {\n\t\t\t\t\t\t#if(VQABLOCK_4X2)\n\t\t\t\t\t\tcase BLOCK_4X2:\n\t\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2_Xmode;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t#endif /* VQABLOCK_4X2 */\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Pre-compute the draw offset for speed. */\n\t\t\tdrawer->ScreenOffset = (((320 / 4) * drawer->Y1) + (drawer->X1 / 4));\n\t\t\tbreak;\n\t\t#endif /* VQAXMODE_ON */\n\n\t\t/* VESA */\n\t\t#if(VQAVESA_ON)\n\n\t\t/* Currently this is a buffered mode, but should be optimized for\n\t\t * for screen direct.\n\t\t */\n\t\tcase VESA_640X480_256:\n\t\t\tvqabuf->Draw_Frame = DrawFrame_VESA640;\n\t\t\tvqabuf->Page_Flip = PageFlip_VESA;\n\t\t\tbreak;\n\n\t\tcase VESA_320X200_32K_1:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_VESA320_32KBuf;\n\t\t\t} else {\n\t\t\t\tvqabuf->Draw_Frame = DrawFrame_VESA320_32K;\n\n\t\t\t\tswitch (blkdim) {\n\t\t\t\t\t#if(VQABLOCK_4X2)\n\t\t\t\t\tcase BLOCK_4X2:\n\t\t\t\t\t\tvqabuf->UnVQ = UnVQ_4x2_VESA320_32K;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t#endif\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t#endif /* VQAVESA_ON */\n\n\t\t/* Purely buffered (Video refresh is up to the client. */\n\t\tdefault:\n\t\t\tvqabuf->Draw_Frame = DrawFrame_Buffer;\n\n\t\t\t/* Pre-compute the draw offset for speed. */\n\t\t\tdrawer->ScreenOffset = ((drawer->ImageWidth * drawer->Y1)+drawer->X1);\n\t\t\tbreak;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Select_Frame - Selects frame to draw and preforms frame skip.\n*\n* SYNOPSIS\n*     Error = Select_Frame(VQA)\n*\n*     long Select_Frame(VQAHandleP *);\n*\n* FUNCTION\n*     Select a frame to draw. This is were the frame skipping/delay is\n*     performed.\n*\n* INPUTS\n*     VQA - Pointer to private VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Select_Frame(VQAHandleP *vqap)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAConfig    *config;\n\tVQAFrameNode *curframe;\n\tlong         desiredframe;\n\t// MEG 11.29.95 - changed from long to unsigned long\n\tunsigned long curtime;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tconfig = &vqap->Config;\n\tvqabuf = vqap->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = drawer->CurFrame;\n\n\t/* Make sure the current frame is drawable. If the frame is not ready\n\t * then we must wait for the loader to catch up.\n\t */\n\tif ((curframe->Flags & VQAFRMF_LOADED) == 0) {\n\t\tdrawer->WaitsOnLoader++;\n\t\treturn (VQAERR_NOBUFFER);\n\t}\n\n\t/* If single stepping then return with the next frame.*/\n\tif (config->OptionFlags & VQAOPTF_STEP) {\n\t\tdrawer->LastFrame = curframe->FrameNum;\n\t\treturn (0);\n\t}\n\n\t/* Find the frame # we should play (rounded to nearest frame): */\n\tcurtime = VQA_GetTime(vqap);\n//\tdesiredframe = ((curtime * config->FrameRate) / VQA_TIMETICKS);\n\t// MEG MOD 06.22.95 - Should look for the desired frame to draw, not load,\n\t// right?\n\tdesiredframe = ((curtime * config->DrawRate) / VQA_TIMETICKS);\n\n\t#if(VQAMONO_ON)\n\tdrawer->DesiredFrame = desiredframe;\n\t#endif\n\n\t/* Handle the cases where the player is going so fast that it's not time \n\t * to draw this frame yet.\n\t *\n\t * - If the Drawer is using a slower frame rate than the Loader, use a\n\t *   delta-time-based wait; otherwise, use the frame number as the wait.\n\t */\n\tif (config->DrawRate != config->FrameRate) {\n\t\tif (curtime - drawer->LastTime < (VQA_TIMETICKS / config->DrawRate)) {\n\t\t\treturn (VQAERR_NOT_TIME);\n\t\t}\n\t} else {\n\t\tif (curframe->FrameNum > desiredframe) {\n\t\t\treturn (VQAERR_NOT_TIME);\n\t\t}\n\t}\n\n\t/* Make sure we draw at least 5 frames per second */\n\tif ((curframe->FrameNum - drawer->LastFrame) >= (config->FrameRate / 5)) {\n\t\tdrawer->LastFrame = curframe->FrameNum;\n\t\treturn (0);\n\t}\n\n\t/* If frame skipping is disabled then draw every frame. */\n\tif (config->DrawFlags & VQACFGF_NOSKIP) {\n\t\tdrawer->LastFrame = curframe->FrameNum;\n\t\treturn (0);\n\t}\n\n\t/* Handle the case where the player is going too slow, so we have to skip \n\t * some frames:\n\t *\n\t * - If this is a Key Frame, draw it\n\t * - If this frame's # is less than what we're supposed to draw, skip it\n\t *   (Because the 1st 'desiredframe' will be 0, FrameNum MUST be typecast \n\t *   to signed WORD for the comparison; otherwise, the comparison uses \n\t *   UWORDs, and the first frame is always skipped.)\n\t * - If this is a palette-set frame, set the palette before skipping it\n\t * - Loop until we get the frame we need, or there's no frames available\n\t */\n\twhile (1) {\n\n\t\t/* No frame available; return */\n\t\tif ((curframe->Flags & VQAFRMF_LOADED) == 0) {\n\t\t\treturn (VQAERR_NOBUFFER);\n\t\t}\n\n\t\t/* Force drawing of a Key Frame */\n\t\tif (curframe->Flags & VQAFRMF_KEY) {\n\t\t\tbreak;\n\t\t}\n\n\t\t/* Skip the frame */\n\t\tif (curframe->FrameNum < desiredframe) {\n\n\t\t\t/* Handle a palette in a skipped frame:\n\t\t\t *\n\t\t\t * - Stash the palette in Drawer.Palette_24\n\t\t\t * - Set the Drawer.Flags VQADRWF_SETPAL bit, to tell the page-flip\n\t\t\t *   routines that this palette must be set\n\t\t\t */\n\t\t\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\n\t\t\t\t/* Un-LCW if needed */\n\t\t\t\tif (curframe->Flags & VQAFRMF_PALCOMP) {\n\t\t\t\t\tcurframe->PaletteSize = LCW_Uncompress((char *)curframe->Palette\n\t\t\t\t\t\t\t+ curframe->PalOffset, (char *)curframe->Palette,\n\t\t\t\t\t\t\tvqabuf->Max_Pal_Size);\n\n\t\t\t\t\tcurframe->Flags &= ~VQAFRMF_PALCOMP;\n\t\t\t\t}\n\n\t\t\t\t/* Stash the palette */\n\t\t\t\tmemcpy(drawer->Palette_24, curframe->Palette, curframe->PaletteSize);\n\t\t\t\tdrawer->CurPalSize = curframe->PaletteSize;\n\t\t\t\tdrawer->Flags |= VQADRWF_SETPAL;\n\t\t\t}\n\n\t\t\t/* Invoke callback with NULL screen ptr */\n\t\t\tif (config->DrawerCallback != NULL) {\n\t\t\t\tif ((config->DrawerCallback(NULL, curframe->FrameNum)) != 0) {\n\t\t\t\t\treturn (VQAERR_EOF);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Skip the frame */\n\t\t\tcurframe->Flags = 0L;\n\t\t\tcurframe = curframe->Next;\n\t\t\tdrawer->CurFrame = curframe;\n\t\t\tdrawer->NumSkipped++;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tdrawer->LastFrame = curframe->FrameNum;\n\tdrawer->LastTime = curtime;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Prepare_Frame - Process/Decompress frame information.\n*\n* SYNOPSIS\n*     Prepare_Frame(VQAData)\n*\n*     void Prepare_Frame(VQAData *);\n*\n* FUNCTION\n*     Decompress and preprocess the various frame elements (codebook,\n*     pointers, palette, etc...)\n*\n* INPUTS\n*     VQAData - Pointer to VQAData structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Prepare_Frame(VQAData *vqabuf)\n{\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tVQACBNode    *codebook;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = drawer->CurFrame;\n\tcodebook = curframe->Codebook;\n\n\t/* Decompress the codebook, if needed */\n\tif (codebook->Flags & VQACBF_CBCOMP) {\n\n\t\t/* Decompress the codebook. */\n\t\tLCW_Uncompress((char *)codebook->Buffer + codebook->CBOffset,\n\t\t\t\t(char *)codebook->Buffer, vqabuf->Max_CB_Size);\n\n\t\t/* Mark as uncompressed for the next time we use it */\n\t\tcodebook->Flags &= (~VQACBF_CBCOMP);\n\t}\n\n\t/* Decompress the palette, if needed */\n\tif (curframe->Flags & VQAFRMF_PALCOMP) {\n\t\tcurframe->PaletteSize = LCW_Uncompress((char *)curframe->Palette +\n\t\t\t\tcurframe->PalOffset,(char *)curframe->Palette,vqabuf->Max_Pal_Size);\n\n\t\t/* Mark as uncompressed */\n\t\tcurframe->Flags &= ~VQAFRMF_PALCOMP;\n\t}\n\n\t/* Decompress the pointer data, if needed */\n\tif (curframe->Flags & VQAFRMF_PTRCOMP) {\n\t\tLCW_Uncompress((char *)curframe->Pointers + curframe->PtrOffset,\n\t\t\t\t(char *)curframe->Pointers, vqabuf->Max_Ptr_Size);\n\n\t\t/* Mark as uncompressed */\n\t\tcurframe->Flags &= ~VQAFRMF_PTRCOMP;\n\t}\n\n\t/* Mask the pointers */\n\t#if(0)\n\tMask_Pointers(vqabuf);\n\t#endif\n}\n\n\n#if(VQAXMODE_ON)\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_Xmode - Draws a frame in Xmode format (Screen direct).\n*\n* SYNOPSIS\n*     Error = DrawFrame_Xmode(VQA)\n*\n*     long DrawFrame_Xmode(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Skip frames\n*       - UnLCW frame\n*       - Un-VQ into video RAM\n*       - Wait on Update_Enabled\n*       - Set the Flipper's CurFrame\n*       - Set Update_Enabled\n*       - Go to next frame\n*       - User_Update:\n*         Flip X-Page\n*         Set Palette from Flipper.CurFrame\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the correct spot on\n*     the Xmode screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_Xmode(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *scrn;\n\tlong          rc;\n\n\t/* Dereference data members for quick access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n \t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* Dereference current frame for quicker access */\n\t\tcurframe = drawer->CurFrame;\n\n\t\t/* Un-VQ the image */\n\t\tscrn = GetXHidPage();\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tscrn + drawer->ScreenOffset, drawer->BlocksPerRow,\n\t\t\t\tdrawer->NumRows, 320);\n\n\t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tif ((config->DrawerCallback(scrn, curframe->FrameNum)) != 0) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access */\n\tcurframe = drawer->CurFrame;\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_XmodeBuf - Draws a frame in Xmode format to a buffer.\n*\n* SYNOPSIS\n*     Error = DrawFrame_XmodeBuf(VQA)\n*\n*     long DrawFrame_XmodeBuf(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Skip frames\n*       - UnLCW frame\n*       - Un-VQ into ImageBuf\n*       - Copy ImageBuf to video RAM\n*       - Wait on Update_Enabled\n*       - Set the Flipper's CurFrame\n*       - Set Update_Enabled\n*       - Go to next frame\n*\t      - User_Update:\n*         Flip X-Page\n*         Set Palette from Flipper.CurFrame\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the upper-left\n*     corner of ImageBuf, then copying ImageBuf into the correct part of the\n*     Xmode screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_XmodeBuf(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAHeader     *header;\n\tVQAConfig     *config;\n\tunsigned char *scrn;\n\tlong          rc;\n\n\t/* Dereference data members for quicker access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\theader = &((VQAHandleP *)vqa)->Header;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* Dereference current frame for quicker access. */\n\t\tcurframe = drawer->CurFrame;\n\n\t\t/* Un-VQ the image */\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tdrawer->ImageBuf, drawer->BlocksPerRow, drawer->NumRows,\n\t\t\t\theader->ImageWidth);\n\n\t\t/* Copy the buffer */\n\t\tscrn = GetXHidPage();\n\n\t\tif ((header->ImageWidth < 320) || (header->ImageHeight < 200)) {\n\t\t\tXmode_Blit(drawer->ImageBuf, scrn + drawer->ScreenOffset,\n\t\t\t\t\theader->ImageWidth, header->ImageHeight);\n\t\t} else {\n\t\t\tXmode_BufferCopy_320x200(drawer->ImageBuf,scrn + drawer->ScreenOffset);\n\t\t}\n\n\t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tif ((config->DrawerCallback(scrn, curframe->FrameNum)) != 0) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_XmodeVRAM - Draws a frame in Xmode with resident Codebook.\n*\n* SYNOPSIS\n*     Error = DrawFrame_XmodeVRAM(VQA)\n*\n*     long DrawFrame_XmodeVRAM(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Download Codebook if it isn't already (do this before skipping\n*         frames, so Select_Frame will smooth out the delay)\n*       - Skip frames\n*       - UnLCW frame\n*       - Convert Pointers to VRAM format\n*       - Un-VQ by copying codebook blocks within VRAM\n*       - Wait on Update_Enabled\n*       - Set the Flipper's CurFrame\n*       - Set Update_Enabled\n*       - Go to next frame\n*       - User_Update:\n*         Flip X-Page\n*         Set Palette from Flipper.CurFrame\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the correct spot on\n*     the Xmode screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_XmodeVRAM(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *scrn;\n\tlong          rc;\n\n\t/* Dereference data members for quicker access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* Dereference current frame for quicker access. */\n\t\tcurframe = drawer->CurFrame;\n\n\t\t/* Download codebook to VRAM */\n\t\tif ((curframe->Codebook->Flags & VQACBF_DOWNLOADED) == 0) {\n\t\t\tUpload_4x2CB(curframe->Codebook->Buffer,\n\t\t\t\t\t((VQAHandleP *)vqa)->Header.CBentries\n\t\t\t\t\t+ ((VQAHandleP *)vqa)->Header.Num1Colors);\n\n\t\t\tcurframe->Codebook->Flags |= VQACBF_DOWNLOADED;\n\t\t}\n\n\t\t/* Convert pointers to VRAM format */\n\t\tXlatePointers(curframe->Pointers, drawer->NumBlocks);\n\n\t\t/* Un-VQ the image */\n\t\tscrn = GetXHidPage();\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tscrn + drawer->ScreenOffset, drawer->BlocksPerRow,\n\t\t\t\tdrawer->NumRows, 320);\n\n\t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tif ((config->DrawerCallback(scrn, curframe->FrameNum)) != 0) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_Xmode - Page flip Xmode display.\n*\n* SYNOPSIS\n*     PageFlip_Xmode(VQA)\n*\n*     void PageFlip_Xmode(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void PageFlip_Xmode(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tunsigned char *pal;\n\tVQAConfig     *config;\n\tlong          palsize;\n\tlong          slowpal;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = vqabuf->Flipper.CurFrame;\n\n\t/* Pre-decode 'vqa' for speed */\n\tpal = curframe->Palette;\n\tpalsize = curframe->PaletteSize;\n\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\n\t/* - If this is a palette-set frame:\n\t * - Wait for NoVB (active scan)\n\t * - Flip the page (doesn't take effect until next active scan\n\t * - Wait for VB\n\t * - Set the palette\n\t * - Otherwise, just flip the page\n\t */\n\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tFlipXPage();\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(pal, palsize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)pal, (long)palsize);\n\t\t}\n\t}\n\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\tdrawer->Flags &= (~VQADRWF_SETPAL);\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tFlipXPage();\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(drawer->Palette_24, drawer->CurPalSize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)drawer->Palette_24,\n\t\t\t\t\t(long)drawer->CurPalSize);\n\t\t}\n\t} else {\n\t\tFlipXPage();\n\t}\n}\n#endif /* VQAXMODE_ON */\n\n\n#if(VQAMCGA_ON)\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_MCGA - Draws a frame directly to MCGA screen.\n*\n* SYNOPSIS\n*     Error = DrawFrame_MCGA(VQA)\n*\n*     long DrawFrame_MCGA(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Skip frames\n*       - UnLCW frame\n*       - Wait on Update_Enabled\n*       - Set Update_Enabled\n*       - Go to next frame\n*       - User_Update:\n*         set palette\n*         UnVQ to screen\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the correct spot on\n*     the screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_MCGA(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tlong         rc;\n\n\t/* Dereference commonly used data members for quicker access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Select the frame to draw. */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_MCGA - Page flip MCGA display.\n*\n* SYNOPSIS\n*     PageFlip_MCGA(VQA)\n*\n*     long PageFlip_MCGA(VQAHandle *);\n*\n* FUNCTION\n*     Since the MCGA mode only has one buffer, the drawing is actually done\n*     at this point.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle structure.\n*\n* RESULT\n*     Error - 0 if successfull, otherwise VQAERR_???\n*\n****************************************************************************/\n\nstatic long PageFlip_MCGA(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *pal;\n\tunsigned char *ptrs;\n\tunsigned char *cb;\n\tlong          palsize;\n\tlong          slowpal;\n\tlong          blocksperrow;\n\tlong          numrows;\n\n\t#ifndef PHARLAP_TNT\n\tunsigned char *scrn;\n\t#else\n\tFARPTR        scrn;\n\t#endif\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = vqabuf->Flipper.CurFrame;\n\n\t/*-------------------------------------------------------------------------\n\t * WAIT FOR THE VERTICAL BLANK TO SET THE PALETTE.\n\t *-----------------------------------------------------------------------*/\n\tif ((curframe->Flags & VQAFRMF_PALETTE)\n\t\t\t|| (drawer->Flags & VQADRWF_SETPAL)) {\n\n\t\tpal = curframe->Palette;\n\t\tpalsize = curframe->PaletteSize;\n\t\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\n\t\t/* Wait for the VBlank. */\n\t \tWaitNoVB(vqabuf->VBIBit);\n\t \tWaitVB(vqabuf->VBIBit);\n\n\t\t/* Set the palette. */\n\t\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\t\tSetPalette(pal, palsize, slowpal);\n\t\t\t}\n\n\t\t\t/* Notify the client of the palette change. */\n\t\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)pal, (long)palsize);\n\t\t\t}\n\t\t}\n\t\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\t\tdrawer->Flags &= (~VQADRWF_SETPAL);\n\n\t\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\t\tSetPalette(drawer->Palette_24, drawer->CurPalSize, slowpal);\n\t\t\t}\n\n\t\t\t/* Notify the client of the palette change. */\n\t\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)drawer->Palette_24,\n\t\t\t\t\t\t(long)drawer->CurPalSize);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * UNVQ THE FRAME DIRECTLY TO THE MCGA SCREEN.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Get screen address, blocks per row and number of rows. */\n\t#ifndef PHARLAP_TNT\n\tscrn = (unsigned char *)(0xA0000 + (unsigned long)drawer->ScreenOffset);\n\t#else\n\tFP_SET(scrn, drawer->ScreenOffset, 0x1C);\n\t#endif\n\n\tblocksperrow = drawer->BlocksPerRow;\n\tnumrows = drawer->NumRows;\n\tptrs = curframe->Pointers;\n\tcb = curframe->Codebook->Buffer;\n\tvqabuf->UnVQ(cb, ptrs, scrn, blocksperrow, numrows, 320);\n\n\t#if(VQACAPTIONS_ON)\n\t/* Process captions. */\n\tif ((((VQAHandleP *)vqa)->Caption != NULL)\n\t\t\t&& (config->OptionFlags & VQAOPTF_CAPTIONS)) {\n\t\tDoCaptions(((VQAHandleP *)vqa)->Caption, curframe->FrameNum);\n\t}\n\t#endif\n\n\t/* Invoke user's callback routine */\n\tif (config->DrawerCallback != NULL) {\n\t\tif ((config->DrawerCallback(NULL, curframe->FrameNum)) != 0) {\n\t\t\treturn (VQAERR_EOF);\n\t\t}\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_MCGABuf - Draws a frame in MCGA format to a buffer.\n*\n* SYNOPSIS\n*     Error = DrawFrame_MCGABuf(VQA)\n*\n*     long DrawFrame_MCGABuf(VQAHandle *);\n*\n* FUNCTION\n*     Algorithm:\n*       - Skip frames\n*       - UnLCW frame\n*       - Wait on Update_Enabled (can't use imgbuf til User_Update's done)\n*       - Un-VQ into ImageBuf\n*       - Set the Flipper's CurFrame\n*       - Set Update_Enabled\n*       - Go to next frame\n*       - User_Update:\n*         set Palette from Flipper.CurFrame\n*         copy ImageBuf to screen\n*\n*     This function implements a sort of cooperative multitasking.  If the\n*     Drawer hits a \"wait state\", where it has to wait for Update_Enabled\n*     to toggle, it sets a flag and returns.  This flag is checked on entry\n*     to see if we need to jump to the proper execution point. This should\n*     improve performance on some platforms.\n*\n*     This routine handles small images by UnVQ'ing into the upper-left\n*     corner of ImageBuf, then copying ImageBuf onto the screen.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_MCGABuf(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tlong         rc;\n\n\t#ifndef PHARLAP_TNT\n\tunsigned char *scrn;\n\t#else\n\tFARPTR        scrn;\n\t#endif\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t#ifndef PHARLAP_TNT\n\tscrn = drawer->ImageBuf;\n\t#else\n\tFP_SET(scrn, drawer->ImageBuf, 0x14);\n\t#endif\n\n\t/* Un-VQ the image */\n\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, scrn,\n\t\t\tdrawer->BlocksPerRow, drawer->NumRows,\n\t\t\t((VQAHandleP *)vqa)->Header.ImageWidth);\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_MCGABuf - Page flip a buffered MCGA display.\n*\n* SYNOPSIS\n*     PageFlip_MCGABuf(VQA)\n*\n*     void PageFlip_MCGABuf(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successfull, otherwise VQAERR_???\n*\n****************************************************************************/\n\nstatic long PageFlip_MCGABuf(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *pal;\n\tunsigned char *buf;\n\tunsigned char *scrn;\n\tlong          palsize;\n\tlong          slowpal;\n\tlong          imgwidth;\n\tlong          imgheight;\n\n\t/* Derefernce commonly used data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = vqabuf->Flipper.CurFrame;\n\n\t/* Pre-decode 'vqa' for speed */\n\tpal = curframe->Palette;\n\tpalsize = curframe->PaletteSize;\n\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\n\t/* - If this is a palette-set frame:\n\t * - Wait for the vertical blank\n\t * - Set the palette\n\t * - Copy ImageBuf to SEENPAGE:\n\t * - use blit routine if image is smaller than full-screen, since the\n\t *   buffer copy assumes a full-screen image\n\t */\n\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(pal, palsize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)pal, (long)palsize);\n\t\t}\n\t}\n\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\tdrawer->Flags &= (~VQADRWF_SETPAL);\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(drawer->Palette_24, drawer->CurPalSize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)drawer->Palette_24,\n\t\t\t\t\t(long)drawer->CurPalSize);\n\t\t}\n\t}\n\n\t/* Draw image to the screen. */\n\timgwidth = ((VQAHandleP *)vqa)->Header.ImageWidth;\n\timgheight = ((VQAHandleP *)vqa)->Header.ImageHeight;\n\tbuf = drawer->ImageBuf;\n\n\t#ifndef PHARLAP_TNT\n\tscrn = (unsigned char *)0xA0000;\n\t#endif\n\n\tif ((imgwidth < 320) || (imgheight < 200)) {\n\t\t#ifndef PHARLAP_TNT\n\t\tscrn += drawer->ScreenOffset;\n\t\t#else\n\t\tscrn = (unsigned char *)drawer->ScreenOffset;\n\t\t#endif\n\n\t\tMCGA_Blit(buf, scrn, imgwidth, imgheight);\n\t} else {\n\t\tMCGA_BufferCopy(buf, NULL);\n\t}\n\n\t/* Invoke user's callback routine */\n\tif (config->DrawerCallback != NULL) {\n\t\tif ((config->DrawerCallback(NULL, curframe->FrameNum)) != 0) {\n\t\t\treturn (VQAERR_EOF);\n\t\t}\n\t}\n\n\treturn (0);\n}\n#endif /* VQAMCGA_ON */\n\n\n#if(VQAVESA_ON)\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_VESA640 - Draws a frame in VESA 640 format.\n*\n* SYNOPSIS\n*     Error = DrawFrame_VESA640(VQA)\n*\n*     long DrawFrame_VESA640(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_VESA640(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tlong         rc;\n\n\t#ifndef PHARLAP_TNT\n\tunsigned char *scrn;\n\t#else\n\tFARPTR        scrn;\n\t#endif\n\n\t/* Dereference data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\t}\n\n\t/* Dereference current frame. */\n\tcurframe = drawer->CurFrame;\n\n\t/* Wait for Update_Enabled to be set low */\n \tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tvqabuf->Drawer.WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t#ifndef PHARLAP_TNT\n\tscrn = drawer->ImageBuf + drawer->ScreenOffset;\n\t#else\n\tFP_SET(scrn, drawer->ImageBuf + drawer->ScreenOffset, 0x14);\n\t#endif\n\n\t/* Un-VQ the image */\n\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, scrn,\n\t\t\tdrawer->BlocksPerRow, drawer->NumRows, drawer->ImageWidth);\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_VESA320_32K - Draws a frame in VESA 320 format.\n*\n* SYNOPSIS\n*     Error = DrawFrame_VESA320_32K(VQA)\n*\n*     long DrawFrame_VESA320_32K(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_VESA320_32K(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tVQAConfig    *config;\n\tlong         rc;\n\tlong         grain;\n\n\t/* Dereference data members for quicker access. */\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* Dereference current frame. */\n\t\tcurframe = drawer->CurFrame;\n\n\t\t/* Translate palette to 15-bit */\n\t\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\t\tTranslatePalette(curframe->Palette, drawer->Palette_15,\n\t\t\t\t\tcurframe->PaletteSize);\n\t\t}\n\t\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\t\tTranslatePalette(drawer->Palette_24, drawer->Palette_15,\n\t\t\t\t\tdrawer->CurPalSize);\n\t\t}\n\n\t\t/* UnVQ directly to screen */\n\t\tgrain = ((VESAModeInfo *)(drawer->Display->Extended))->WinSize\n\t\t\t\t/ ((VESAModeInfo *)(drawer->Display->Extended))->WinGranularity;\n\n\t\t#ifndef PHARLAP_TNT\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tdrawer->Palette_15, grain, 0, 0);\n\t\t#else\n\t\t{\n\t\tFARPTR temp;\n\n\t\tFP_SET(temp, drawer->Palette_15, 0x14);\n\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, temp,\n\t\t\t\tgrain, 0, 0);\n\t\t}\n\t\t#endif\n\n\t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tif ((config->DrawerCallback(0, curframe->FrameNum)) != 0) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Wait for VQ_Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_VESA320_32KBuf - Draws a frame in VESA320_32K format to a\n*                                buffer.\n*\n* SYNOPSIS\n*     Error = DrawFrame_VESA320_32KBuf(VQA)\n*\n*     long DrawFrame_VESA320_32KBuf(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_VESA320_32KBuf(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tVQAConfig    *config;\n\tlong         rc;\n\tlong         grain;\n\n\t/* Dereference data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = drawer->CurFrame;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\n\t\t/* UnVQ buffered mode */\n\t\t#ifndef PHARLAP_TNT\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers,\n\t\t\t\tdrawer->ImageBuf, drawer->BlocksPerRow, drawer->NumRows,\n\t\t\t\t((VQAHandleP *)vqa)->Header.image_width);\n\t\t#else\n\t\t{\n\t\tFARPTR scrn;\n\n\t\tFP_SET(scrn, drawer->ImageBuf, 0x14);\n\n\t\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, scrn,\n\t\t\t\tdrawer->BlocksPerRow, drawer->NumRows,\n\t\t\t\t((VQAHandleP *)vqa)->Header.image_width);\n\t\t}\n\t\t#endif\n\n\t\t/* Translate the palette to 15-bit */\n\t\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\t\tTranslatePalette(curframe->Palette, drawer->Palette_15,\n\t\t\t\t\tcurframe->PaletteSize);\n\t\t}\n\t\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\t\tTranslatePalette(drawer->Palette_24, drawer->Palette_15,\n\t\t\t\t\tdrawer->CurPalSize);\n\t\t}\n\n\t\t/* Copy the buffer */\n\t\tgrain = ((VESAModeInfo *)(drawer->Display->Extended))->WinSize\n\t\t\t\t/ ((VESAModeInfo *)(drawer->Display->Extended))->WinGranularity;\n\n\t\tBuf_320x200_To_VESA_32K(drawer->ImageBuf, drawer->Palette_15, grain);\n\n \t\t/* Invoke user's callback routine */\n\t\tif (config->DrawerCallback != NULL) {\n\t\t\tif ((config->DrawerCallback(0, curframe->FrameNum)) != 0) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t\tdrawer->WaitsOnFlipper++;\n\t}\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_VESA - Page flip VESA display.\n*\n* SYNOPSIS\n*     PageFlip_VESA(VQA)\n*\n*     void PageFlip_VESA(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void PageFlip_VESA(VQAHandle *vqa)\n{\n\tVQAData       *vqabuf;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tVQAConfig     *config;\n\tunsigned char *pal;\n\tlong          palsize;\n\tlong          slowpal;\n\tlong          grain;\n\n\t/* Dereference date members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = vqabuf->Flipper.CurFrame;\n\n\t/* Pre-decode 'vqa' for speed */\n\tpal = curframe->Palette;\n\tpalsize = curframe->PaletteSize;\n\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\n\t/* Set the palette */\n\tif (curframe->Flags & VQAFRMF_PALETTE) {\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(pal, palsize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)pal, (long)palsize);\n\t\t}\n\t}\n\telse if (drawer->Flags & VQADRWF_SETPAL) {\n\t\tdrawer->Flags &= (~VQADRWF_SETPAL);\n\t\tWaitNoVB(vqabuf->VBIBit);\n\t\tWaitVB(vqabuf->VBIBit);\n\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\t\t\tSetPalette(drawer->Palette_24, drawer->CurPalSize, slowpal);\n\t\t}\n\n\t\t/* Notify the client of the palette change. */\n\t\tif ((config->NotifyFlags & VQAEVENT_PALETTE)\n\t\t\t\t&& (config->EventHandler != NULL)) {\n\n\t\t\tconfig->EventHandler(VQAEVENT_PALETTE, (void *)drawer->Palette_24,\n\t\t\t\t\t(long)drawer->CurPalSize);\n\t\t}\n\t}\n\n\t/* Copy the buffer */\n\tgrain = ((VESAModeInfo *)(drawer->Display->Extended))->WinSize\n\t\t\t/ ((VESAModeInfo *)(drawer->Display->Extended))->WinGranularity;\n\n\tswitch (((VQAHandleP *)vqa)->Header.image_width) {\n\t\tcase 320:\n\t\t\tif (config->DrawFlags & VQACFGF_SCALEX2) {\n\t\t\t\tBuf_320x200_To_VESA_640x400(drawer->ImageBuf, grain);\n\t\t\t} else {\n\t\t\t\tBuf_320x200_To_VESA_320x200(drawer->ImageBuf, grain);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tVESA_Blit_640x480(drawer->Display, drawer->ImageBuf, drawer->X1,\n\t\t\t\t\tdrawer->Y1, ((VQAHandleP *)vqa)->Header.image_width,\n\t\t\t\t\t((VQAHandleP *)vqa)->Header.image_height);\n\t\t\tbreak;\n\t}\n\n\t/* Invoke user's callback routine */\n\tif (config->DrawerCallback != NULL) {\n\t\tif ((config->DrawerCallback(drawer->ImageBuf, curframe->FrameNum)) != 0) {\n\t\t\treturn (VQAERR_EOF);\n\t\t}\n\t}\n}\n#endif /* VQAVESA_ON */\n\n\n/****************************************************************************\n*\n* NAME\n*     DrawFrame_Buffer - Draw a frame to a buffer.\n*\n* SYNOPSIS\n*     Error = DrawFrame_Buffer(VQA)\n*\n*     long DrawFrame_Buffere(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQA handle.\n*\n* RESULT\n*     Error - 0 if successful, otherwise VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DrawFrame_Buffer(VQAHandle *vqa)\n{\n\tVQAData      *vqabuf;\n\tVQADrawer    *drawer;\n\tVQAFrameNode *curframe;\n\tVQAConfig    *config;\n\tlong         rc;\n\n\t#ifndef PHARLAP_TNT\n\tunsigned char *buff;\n\t#else\n\tFARPTR        buff;\n\t#endif\n\n\t/* Dereference data members for quicker access. */\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\n\t/* Check our \"sleep\" state */\n\tif (!(vqabuf->Flags & VQADATF_DSLEEP)) {\n\n\t\t/* Find the frame to draw */\n\t\tif ((rc = Select_Frame((VQAHandleP *)vqa)) != 0) {\n\t\t\treturn (rc);\n\t\t}\n\n\t\t/* Uncompress the frame data */\n\t\tPrepare_Frame(vqabuf);\n\t}\n \n\t/* Wait for Update_Enabled to be set low */\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\t\tvqabuf->Flags |= VQADATF_DSLEEP;\n\t\treturn (VQAERR_SLEEPING);\n\t}\n\n\tif (vqabuf->Flags & VQADATF_DSLEEP) {\n\t\tdrawer->WaitsOnFlipper++;\n\t\tvqabuf->Flags &= (~VQADATF_DSLEEP);\n\t}\n\n\t/* Dereference current frame for quicker access. */\n\tcurframe = drawer->CurFrame;\n\n\t#ifndef PHARLAP_TNT\n\tbuff = (unsigned char *)(drawer->ImageBuf + drawer->ScreenOffset);\n\t#else\n\tFP_SET(buff, drawer->ImageBuf + drawer->ScreenOffset, 0x14);\n\t#endif\n\n\t/* Un-VQ the image */\n\tvqabuf->UnVQ(curframe->Codebook->Buffer, curframe->Pointers, buff,\n\t\t\tdrawer->BlocksPerRow, drawer->NumRows, drawer->ImageWidth);\n\n\t/* Update data for mono output */\n\tdrawer->LastFrameNum = curframe->FrameNum;\n\n\t/* Tell the flipper which frame to use */\n\tvqabuf->Flipper.CurFrame = curframe;\n\n\t/* Set the page-avail flag for the flipper */\n\tvqabuf->Flags |= VQADATF_UPDATE;\n\n\t/* Invoke user's callback routine */\n\tif (config->DrawerCallback != NULL) {\n\t\tif ((config->DrawerCallback(drawer->ImageBuf, curframe->FrameNum)) != 0) {\n\t\t\treturn (VQAERR_EOF);\n\t\t}\n\t}\n\n\t/* Move to the next frame */\n\tdrawer->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     UnVQ_Nop - Do nothing UnVQ.\n*\n* SYNOPSIS\n*     UnVQ_Nop(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n*\n*     void UnVQ_Nop(unsigned char *, unsigned char *, unsigned char *,\n*                   unsigned long, unsigned long, unsigned long);\n* FUNCTION\n*\n* INPUTS\n*     Codebook - Not used. (Prototype placeholder)\n*     Pointers - Not used. (Prototype placeholder)\n*     Buffer   - Not used. (Prototype placeholder)\n*     BPR      - Not used. (Prototype placeholder)\n*     Rows     - Not used. (Prototype placeholder)\n*     BufWidth - Not used. (Prototype placeholder)\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\n#ifndef PHARLAP_TNT\nstatic void cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth)\n#else\nstatic void cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth)\n#endif\n{\n\t/* Suppress compiler warnings */\n\tcodebook = codebook;\n\tpointers = pointers;\n\tbuffer = buffer;\n\tblocksperrow = blocksperrow;\n\tnumrows = numrows;\n\tbufwidth = bufwidth;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PageFlip_Nop - Do nothing page flip.\n*\n* SYNOPSIS\n*     PageFlip_Nop(VQA)\n*\n*     void PageFlip_Nop(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQA handle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic long PageFlip_Nop(VQAHandle *vqa)\n{\n\tvqa = vqa;\n\n\treturn (0);\n}\n\n\n#if(0)\n/****************************************************************************\n*\n* NAME\n*     Mask_Rect - Sets non-drawable rectangle in image.\n*\n* SYNOPSIS\n*     Mask_Rect(VQA, X1, Y1, X2, Y2)\n*\n*     void Mask_Rect(VQAHandle *, unsigned long, unsigned long,\n*                    unsigned long, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to VQA handle.\n*     X1  - X coordinate of upper-left corner\n*     Y1  - Y coordinate of upper-left corner\n*     X2  - X coordinate of lower-right corner\n*     Y2  - Y coordinate of lower-right corner\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Mask_Rect(VQAHandle *vqa, unsigned long x1, unsigned long y1,\n\t\tunsigned long x2, unsigned long y2)\n{\n\tVQAData   *vqabuf;\n\tVQADrawer *drawer;\n\tVQAHeader *header;\n\tlong      blocks_per_row;\n\n\t/* Dereference data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\theader = &((VQAHandleP *)vqa)->Header;\n\tdrawer =  &vqabuf->Drawer;\n\n\t/* Clip coords to image size */\n\tif (x1 < vqabuf->Drawer.X1) {\n\t\tx1 = vqabuf->Drawer.X1;\n\t}\n\n\tif (y1 < vqabuf->Drawer.Y1) {\n\t\ty1 = vqabuf->Drawer.Y1;\n\t}\n\n\tif (x2 > vqabuf->Drawer.X2) {\n\t\tx2 = vqabuf->Drawer.X2;\n\t}\n\n\tif (y2 > vqabuf->Drawer.Y2) {\n\t\ty2 = vqabuf->Drawer.Y2;\n\t}\n\n\t/* Convert pixel coords to block coords */\n\tx1 /= header->block_width;\n\tx2 /= header->block_width;\n\ty1 /= header->block_height;\n\ty2 /= header->block_height;\n\n\t/* Compute the mask values */\n\tblocks_per_row = (header->image_width / header->block_width);\n\tvqabuf->Drawer.MaskStart = blocks_per_row * y1 + x1;\n\n\tif (x1 == x2) {\n\t\tdrawer->MaskWidth = 0;\n\t} else {\n\t\tdrawer->MaskWidth = x2 - x1 + 1;\n\t}\n\n\tif (y1 == y2) {\n\t\tdrawer->MaskHeight = 0;\n\t} else {\n\t\tdrawer->MaskHeight = y2 - y1 + 1;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Mask_Pointers - Mask vector pointer that are in the mask rectangle.\n*\n* SYNOPSIS\n*     Mask_Pointers(VQAData)\n*\n*     void Mask_Pointers(VQAData *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQAData - Pointer to VQAData structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Mask_Pointers(VQAData *vqabuf)\n{\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tunsigned long *ptr;\n\tunsigned long i,j;\n\tunsigned long start;\n\n\t/* Dereference data members for quicker access. */\n\tdrawer = &vqabuf->Drawer;\n\tcurframe = drawer->CurFrame;\n\tstart = vqabuf->Drawer.MaskStart;\n\n\tfor (i = 0; i < drawer->MaskHeight; i++) {\n\t\tptr = (unsigned long *)(curframe->Pointers) + start;\n\n\t\tfor (j = 0; j < drawer->MaskWidth; j++) {\n\t\t\tptr[j] = VQA_MASK_POINTER;\n\t\t}\n\n\t\tstart += drawer->BlocksPerRow;\n\t}\n}\n#endif\n\n\u001a"
  },
  {
    "path": "WINVQ/VQA32/OLD/DSTREAM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQAPlay32 library.\n*\n* FILE\n*     dstream.c\n*\n* DESCRIPTION\n*     DOS IO handler.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 10, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_InitAsDOS - Initialize IO with the standard DOS handler.\n*\n* PRIVATE\n*     VQADOSHandler - Standard DOS IO handler.\n*\n****************************************************************************/\n\n#include <fcntl.h>\n#include <io.h>\n#include \"vqaplayp.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\nstatic long VQADOSHandler(VQAHandle *vqa, long action, void *buffer,\n\t\tlong nbytes);\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_InitAsDOS - Initialize IO with the standard DOS handler.\n*\n* SYNOPSIS\n*     VQA_InitAsDOS(VQA)\n*\n*     VQA_InitAsDOS(VQAHandle *);\n*\n* FUNCTION\n*     Initialize the IO of the specified handle as a standard DOS access.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle to initialize as DOS.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_InitAsDOS(VQAHandle *vqa)\n{\n\t((VQAHandleP *)vqa)->IOHandler = VQADOSHandler;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQADOSHandler - Standard DOS IO handler.\n*\n* SYNOPSIS\n*     Error = VQADOSHandler(VQA, Action, Buffer, NBytes)\n*\n*     unsigned long VQADOSHandler(VQAHandle *, long, long, long);\n*\n* FUNCTION\n*      Perform the requested action on the standard DOS file system.\n*\n* INPUTS\n*      VQA    - VQAHandle to operate on.\n*      Action - Action to perform.\n*      Buffer - Buffer to Read/Write to/from.\n*      NBytes - Number of bytes to operate on.\n*\n* RESULT\n*      Error - 0 if successful, otherwise error.\n*\n****************************************************************************/\n\nstatic long VQADOSHandler(VQAHandle *vqa, long action, void *buffer,\n\t\tlong nbytes)\n{\n\tlong fh;\n\tlong error;\n\n\tfh = vqa->VQAio;\n\n\t/* Perform the action specified by the IO command */\n\tswitch (action) {\n\n\t\t/* VQACMD_READ means read NBytes and place it in the memory\n\t\t * pointed to by Buffer.\n\t\t *\n\t\t * Any error code returned will be remapped by VQA library into\n\t\t * VQAERR_READ.\n\t\t */\n\t\tcase VQACMD_READ:\n\t\t\terror = (read(fh, buffer, nbytes) != nbytes);\n\t\t\tbreak;\n\n\t\t/* VQACMD_WRITE is analogous to VQACMD_READ.\n\t\t *\n\t\t * Writing is not allowed to the VQA file, VQA library will remap the\n\t\t * error into VQAERR_WRITE.\n\t\t */\n\t\tcase VQACMD_WRITE:\n\t\t\terror = 1;\n\t\t\tbreak;\n\n\t\t/* VQACMD_SEEK asks that you perform a seek relative to the current\n\t\t * position. NBytes is a signed number, indicating seek direction\n\t\t * (positive for forward, negative for backward). Buffer has no meaning\n\t\t * here.\n\t\t *\n\t\t * Any error code returned will be remapped by VQA library into\n\t\t * VQAERR_SEEK.\n\t\t */\n\t\tcase VQACMD_SEEK:\n\t\t\terror = (lseek(fh, nbytes, (long)buffer) == -1);\n\t\t\tbreak;\n\n\t\t/* VQACMD_OPEN asks that you open the file for access. */\n\t\tcase VQACMD_OPEN:\n\t\t\terror = open((char *)buffer, (O_RDONLY|O_BINARY));\n\n\t\t\tif (error != -1) {\n\t\t\t\tvqa->VQAio = error;\n\t\t\t\terror = 0;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase VQACMD_CLOSE:\n\t\t\tclose(fh);\n\t\t\terror = 0;\n\t\t\tbreak;\n\n\t\t/* VQACMD_INIT means to prepare your IO for reading. This is used for\n\t\t * certain IOs that can't be read immediately upon opening, and need\n\t\t * further preparation. This operation is allowed to fail; the error code\n\t\t * will be returned directly to the client.\n\t\t */\n\t\tcase VQACMD_INIT:\n\n\t\t/* IFFCMD_CLEANUP means to terminate the transaction with the associated\n\t\t * IO. This is used for IOs that can't simply be closed. This operation\n\t\t * is not allowed to fail; any error returned will be ignored.\n\t\t */\n\t\tcase VQACMD_CLEANUP:\n\t\t\terror = 0;\n\t\t\tbreak;\n\t}\n\n\treturn (error);\n}\n\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/LOADER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     loader.c\n*\n* DESCRIPTION\n*     Stream loading and pre-processing.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     August 21, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_Open      - Open a VQA file to play.\n*     VQA_Close     - Close an opened VQA file.\n*     VQA_LoadFrame - Load the next video frame from the VQA data stream.\n*     VQA_SeekFrame - Position the movie stream to the specified frame.\n*\n* PRIVATE\n*     AllocBuffers  - Allocates the numerous VQA play buffers\n*     FreeBuffers   - Frees the VQA play buffers\n*     PrimeBuffers  - Pre-Load the internal buffers.\n*     Load_FINF     - Loads the Frame Info Table.\n*     Load_VQHD     - Loads a VQA Header.\n*     Load_CBF0     - Loads a full, uncompressed codebook\n*     Load_CBFZ     - Loads a full, compressed codebook\n*     Load_CBP0     - Loads a partial uncompressed codebook\n*     Load_CBPZ     - Loads a partial compressed codebook\n*     Load_CPL0     - Loads an uncompressed palette\n*     Load_CPLZ     - Loads a compressed palette\n*     Load_VPT0     - Loads uncompressed pointers\n*     Load_VPTZ     - Loads compressed pointers\n*     Load_VQF      - Loads a VQ Frame chunk\n*     Load_SND0     - Loads an uncompressed sound chunk\n*     Load_SND1     - Loads a compressed sound chunk\n*     Load_AudFrame - Loads blocks from separate audio file, if needed.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <fcntl.h>\n#include <io.h>\n#include <malloc.h>\n#include <mem.h>\n#include <dos.h>\n#include \"vq.h\"\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n#include \"caption.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\nstatic VQAData *AllocBuffers(VQAHeader *header, VQAConfig *config);\nstatic void FreeBuffers(VQAData *vqa, VQAConfig *config, VQAHeader *header);\nstatic long PrimeBuffers(VQAHandle *vqa);\nstatic long Load_VQF(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_FINF(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_VQHD(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CBF0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CBFZ(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CBP0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CBPZ(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CPL0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_CPLZ(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_VPT0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_VPTZ(VQAHandleP *vqap, unsigned long iffsize);\n\n#if(VQAAUDIO_ON)\nstatic long Load_SND0(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_SND1(VQAHandleP *vqap, unsigned long iffsize);\nstatic long Load_SND2(VQAHandleP *vqap, unsigned long iffsize);\n\n#if(VQAVOC_ON)\nstatic void Load_AudFrame(VQAHandleP *vqap);\n#endif /* VQAVOC_ON */\n\n#endif /* VQAAUDIO_ON */\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Open - Open a VQA file to play.\n*\n* SYNOPSIS\n*     Error = VQA_Open(VQA, Name, Config)\n*\n*     long VQA_Open(VQAHandle *, char *, VQAConfig *);\n*\n* FUNCTION\n*     - Open a VQA file for reading.\n*     - Validate that it is an IFF file, of the VQA type.\n*     - Read the VQA header.\n*     - Open a VOC file for playback, if requested.\n*     - Set the Loader's frame rate, if the caller's Config structure's\n*       FrameRate is set to -1\n*     - Set the Drawer's frame rate, if the caller's Config structure's\n*       DrawRate is set to -1\n*\n* INPUTS\n*     VQA    - Pointer to initialized handle. Obtained by VQA_Alloc().\n*     Name   - Pointer to name of VQA file to open.\n*     Config - Pointer to initialized VQA configuration structure.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_ error code.\n*\n****************************************************************************/\n\n#define OPEN_VQHD     (1<<0)\n#define OPEN_FINF     (1<<1)\n#define OPEN_CAPTIONS (1<<2)\n\nlong VQA_Open(VQAHandle *vqa, char const *filename, VQAConfig *config)\n{\n\tVQAHandleP  *vqap;\n\tVQAHeader   *header;\n\tChunkHeader chunk;\n\tlong        max_frm_size;\n\tlong        i;\n\tlong        done;\n\tlong        found;\n\tchar        *ptr;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqap = (VQAHandleP *)vqa;\n\theader = &vqap->Header;\n\n\t/*-------------------------------------------------------------------------\n\t * VERIFY VALIDITY OF VQA FILE.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Open the file. */\n\tif (vqap->IOHandler(vqa, VQACMD_OPEN, (void *)filename, 0)) {\n\t\treturn (VQAERR_OPEN);\n\t}\n\n\t/* Read the file ID & Size */\n\tif (vqap->IOHandler(vqa, VQACMD_READ, &chunk, 8)) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Verify an IFF FORM */\n\tif ((chunk.id != ID_FORM) || (chunk.size == 0)) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_NOTVQA);\n\t}\n\n\t/* Read in WVQA ID */\n\tif (vqap->IOHandler(vqa, VQACMD_READ, &chunk, 4)) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Verify VQA */\n\tif (chunk.id != ID_WVQA) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_NOTVQA);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE PLAYERS CONFIGURATION\n\t *-----------------------------------------------------------------------*/\n\n\t/* Use the clients configuration if they provided one. */\n\tif (config != NULL) {\n\t\tmemcpy(&vqap->Config, config, sizeof(VQAConfig));\n\t} else {\n\t\tVQA_DefaultConfig(&vqap->Config);\n\t}\n\n\t/* Use the internal configuration structure from now on. */\n\tconfig = &vqap->Config;\n\n\t/*-------------------------------------------------------------------------\n\t * PROCESS THE PRE-FRAME CHUNKS (VQHD, CAP, FINF, ETC...)\n\t *-----------------------------------------------------------------------*/\n\tfound = 0;\n\tdone = 0;\n\n\twhile (!done) {\n\t\tif (vqap->IOHandler(vqa, VQACMD_READ, &chunk, 8)) {\n\t\t\tVQA_Close(vqa);\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\n\t\tchunk.size = REVERSE_LONG(chunk.size);\n\n\t\tswitch (chunk.id) {\n\n\t\t\t/*---------------------------------------------------------------------\n\t\t\t * READ IN THE VQA HEADER.\n\t\t\t *-------------------------------------------------------------------*/\n\t\t\tcase ID_VQHD:\n\t\t\t\tif (chunk.size != sizeof(VQAHeader)) {\n\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\treturn (VQAERR_NOTVQA);\n\t\t\t\t}\n\n\t\t\t\t/* Read the header data. */\n\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_READ, header, PADSIZE(chunk.size))) {\n\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/*-------------------------------------------------------------------\n\t\t\t\t * SETUP THE CONFIGURATION FROM THE HEADER.\n\t\t\t\t *-----------------------------------------------------------------*/\n\t\t\t\tif (config->ImageWidth == -1) {\n\t\t\t\t\tconfig->ImageWidth = header->ImageWidth;\n\t\t\t\t}\n\n\t\t\t\tif (config->ImageHeight == -1) {\n\t\t\t\t\tconfig->ImageHeight = header->ImageHeight;\n\t\t\t\t}\n\n\t\t\t\t/* If Loaders frame rate is -1 then use the value from the header. */\n\t\t\t\tif (config->FrameRate == -1) {\n\t\t\t\t\tconfig->FrameRate = header->FPS;\n\t\t\t\t}\n\n\t\t\t\t/* If Drawers frame rate is -1 then use the value from the header,\n\t\t\t\t * which will result in a \"variable\" frame rate.\n\t\t\t\t */\n\t\t\t\tif (config->DrawRate == -1) {\n\t\t\t\t\tconfig->DrawRate = header->FPS;\n\t\t\t\t}\n\n\t\t\t\t/* Finally, if the DrawRate was set to -1 or 0 (ie MaxRate contained\n\t\t\t\t * bogus values), set it to the header value.\n\t\t\t\t */\n\t\t\t\tif ((config->DrawRate == -1) || (config->DrawRate == 0)) {\n\t\t\t\t\tconfig->DrawRate = header->FPS;\n\t\t\t\t}\n\n\t\t\t\t#if(VQAAUDIO_ON)\n\t\t\t\t/* If an alternate audio track is not available then turn it off.\n\t\t\t\t * This enables the primary audio track to be played.\n\t\t\t\t */\n\t\t\t\tif ((header->Version > VQAHD_VER1)\n\t\t\t\t\t\t&& !(header->Flags & VQAHDF_ALTAUDIO)) {\n\t\t\t\t\tconfig->OptionFlags &= ~VQAOPTF_ALTAUDIO;\n\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\t/*-------------------------------------------------------------------\n\t\t\t\t * ALLOCATE THE BUFFERS THAT WE NEED TO PLAY THE VQA.\n\t\t\t\t *-----------------------------------------------------------------*/\n\t\t\t\tif ((vqap->VQABuf = AllocBuffers(header, config)) == NULL) {\n\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\treturn (VQAERR_NOMEM);\n\t\t\t\t}\n\n\t\t\t\tfound |= OPEN_VQHD;\n\t\t\t\tbreak;\n\n\t\t\t#if( VQACAPTIONS_ON )\n\n\t\t\t/*---------------------------------------------------------------------\n\t\t\t * READ IN AND OPEN THE CAPTIONS STREAM.\n\t\t\t *-------------------------------------------------------------------*/\n\t\t\tcase ID_CAP0:\n\t\t\t\tif ((config->CapFont != NULL)\n\t\t\t\t\t\t&& (config->OptionFlags & VQAOPTF_CAPTIONS)) {\n\n\t\t\t\t\tshort size = 0;\n\n\t\t\t\t\t/* Get uncompressed size of captions. */\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_READ, &size, sizeof(short))) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Allocate buffer for captions. */\n\t\t\t\t\ti = size + 50;\n\n\t\t\t\t\tif ((ptr = (char *)malloc(i)) == NULL) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_NOMEM);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Read in the captions chunk. */\n\t\t\t\t\ti -= PADSIZE(chunk.size);\n\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_READ, (ptr + i),\n\t\t\t\t\t\t\tPADSIZE(chunk.size - sizeof(short)))) {\n\n\t\t\t\t\t\tfree(ptr);\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Decompress the captions. */\n\t\t\t\t\tLCW_Uncompress((ptr + i), ptr, size);\n\t\t\t\t\tvqap->Caption = OpenCaptions(ptr, config->CapFont);\n\n\t\t\t\t\tif (vqap->Caption == NULL) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_NOMEM);\n\t\t\t\t\t}\n\n\t\t\t\t\tfound |= OPEN_CAPTIONS;\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(chunk.size))) {\n\t\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t#endif\n\n\t\t\t/*---------------------------------------------------------------------\n\t\t\t * READ FRAME INFORMATION\n\t\t\t *-------------------------------------------------------------------*/\n\t\t\tcase ID_FINF:\n\t\t\t\tif (Load_FINF(vqap, chunk.size)) {\n\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\tdone = 1;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\tPADSIZE(chunk.size))) {\n\t\t\t\t\tVQA_Close(vqa);\n\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE VIDEO SYSTEM IF WE ARE REQUIRED TO HANDLE THAT.\n\t *-----------------------------------------------------------------------*/\n\t#if(VQAVIDEO_ON)\n\tif ((vqap->VQABuf->Drawer.Display = SetVideoMode(config->Vmode)) == 0) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_VIDEO);\n\t}\n\n\t/* Set the VBIBit polarity. */\n\tvqap->VQABuf->VBIBit = GetVBIBit();\n\t#else\n\tif (config->VBIBit == -1) {\n\t\tconfig->VBIBit = TestVBIBit();\n\t}\n\n\tvqap->VQABuf->VBIBit = config->VBIBit;\n\n\t#if( VQACAPTIONS_ON )\n\n\tif (found & OPEN_CAPTIONS) {\n\t\tSetDAC(251,255,255,255); /* White */\n\t\tSetDAC(252,255,000,000); /* Red */\n\t\tSetDAC(253,000,255,000); /* Green */\n\t\tSetDAC(254,255,255,255);\n\t\tSetDAC(255,255,000,255); /* Cycle */\n\t}\n\n\t#endif\n\n\t#endif /* VQAVIDEO_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * AUDIO TRACK OVERRIDE FROM EXTERNAL FILE (.VOC)\n\t *-----------------------------------------------------------------------*/\n\n\t/* Open VOC file if one is requested. */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (config->VocFile != NULL) {\n\t\tvqap->vocfh = open(config->VocFile, (O_RDONLY|O_BINARY));\n\t} else {\n\t\tvqap->vocfh = -1;\n\t}\n\n\t/* Make sure we won't try to play audio. */\n\tif ((vqap->vocfh == -1) && ((header->Flags & VQAHDF_AUDIO) == 0)) {\n\t\tconfig->OptionFlags &= (~VQAOPTF_AUDIO);\n\t}\n\t#else  /* VQAVOC_ON */\n\n\t/* If the movie does not contain an audio track make sure we won't try\n\t * to play one.\n\t */\n\tif (((header->Flags & VQAHDF_AUDIO) == 0)) {\n\t\tconfig->OptionFlags &= (~VQAOPTF_AUDIO);\n\t}\n\t#endif /* VQAVOC_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE AUDIO PLAYBACK/TIMING SYSTEM.\n\t *-----------------------------------------------------------------------*/\n\t#if(VQAAUDIO_ON)\n\tif (config->OptionFlags & VQAOPTF_AUDIO) {\n\t\tVQAAudio *audio;\n\n\t\t/* Dereference for quick access. */\n\t\taudio = &vqap->VQABuf->Audio;\n\n\t\t/* Open HMI audio resource for playback. */\n\t\tif (VQA_OpenAudio(vqap)) {\n\t\t\tVQA_Close(vqa);\n\t\t\treturn (VQAERR_AUDIO);\n\t\t}\n\n\t\t/* Initialize ADPCM information structure for audio stream. */\n\t\tsosCODECInitStream(&audio->ADPCM_Info);\n\n\t\tif (header->Version == VQAHD_VER1) {\n\t\t\taudio->ADPCM_Info.wBitSize = 8;\n\t\t\taudio->ADPCM_Info.dwUnCompSize = (22050L/header->FPS) * header->Frames;\n\t\t\taudio->ADPCM_Info.wChannels = 1;\n\t\t} else {\n\t\t\taudio->ADPCM_Info.wBitSize = audio->BitsPerSample;\n\t\t\taudio->ADPCM_Info.dwUnCompSize = (((audio->SampleRate / header->FPS)\n\t\t\t\t\t* (audio->BitsPerSample >> 3)) * audio->Channels) * header->Frames;\n\n\t\t\taudio->ADPCM_Info.wChannels = audio->Channels;\n\t\t}\n\n\t\taudio->ADPCM_Info.dwCompSize = audio->ADPCM_Info.dwUnCompSize\n\t\t\t\t/ (audio->ADPCM_Info.wBitSize / 4);\n\t}\n\n\t/* Turn off audio if the HMI DigiHandle is invalid. */\n\tif (config->DigiHandle == -1) {\n\t\tconfig->OptionFlags &= ~VQAOPTF_AUDIO;\n\t}\n\n\t/* Setup the timer interrupt if the client requests it for the timing\n\t * source.\n\t */\n\tif (!(config->OptionFlags & VQAOPTF_AUDIO)\n\t\t\t|| (config->TimerMethod == VQA_TMETHOD_INT)) {\n\n\t\t/* Start HMI timer system for timing. */\n\t\tif (VQA_StartTimerInt(vqap, (config->OptionFlags & VQAOPTF_HMIINIT))) {\n\t\t\tVQA_Close(vqa);\n\t\t\treturn (VQAERR_AUDIO);\n\t\t}\n\t}\n\t#endif /* VQAAUDIO_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * PRIME THE BUFFERS BY PRE-LOADING THEM WITH FRAME DATA.\n\t *-----------------------------------------------------------------------*/\n\tif (PrimeBuffers(vqa) != 0) {\n\t\tVQA_Close(vqa);\n\t\treturn (VQAERR_READ);\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Close - Close an opened VQA file.\n*\n* SYNOPSIS\n*     VQA_Close(VQA)\n*\n*     void VQA_Close(VQAHandle *);\n*\n* FUNCTION\n*     Close the file that was opened with VQA_Open().\n*\n* INPUTS\n*     VQA - Pointer VQAHandle to close.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Close(VQAHandle *vqa)\n{\n\tlong (*iohandler)(VQAHandle *, long, void *, long);\n\n\t/* Restore video mode to text. */\n\t#if(VQAVIDEO_ON)\n\tSetVideoMode(TEXT);\n\t#endif /* VQAVIDEO_ON */\n\n\t/* Shutdown audio/timing system. */\n\t#if(VQAAUDIO_ON)\n\tif (((VQAHandleP *)vqa)->Config.OptionFlags & VQAOPTF_AUDIO) {\n\t\tVQA_CloseAudio((VQAHandleP *)vqa);\n\t} else {\n\t\tVQA_StopTimerInt((VQAHandleP *)vqa);\n\t}\n\t#endif /* VQAAUDIO_ON */\n\n\t#if( VQACAPTIONS_ON )\n\n\t/* Free captions. */\n\tif (((VQAHandleP *)vqa)->Caption != NULL) {\n\t\tif (((VQAHandleP *)vqa)->Caption->Buffer != NULL) {\n\t\t\tfree(((VQAHandleP *)vqa)->Caption->Buffer);\n\t\t}\n\n\t\tCloseCaptions(((VQAHandleP *)vqa)->Caption);\n\t}\n\n\t#endif\n\n\t/* Free memory */\n\tif (((VQAHandleP *)vqa)->VQABuf != NULL) {\n\t\tFreeBuffers(((VQAHandleP *)vqa)->VQABuf, &((VQAHandleP *)vqa)->Config,\n\t\t\t\t&((VQAHandleP *)vqa)->Header);\n\t}\n\n\t/* Close the VOC override file if one was opened */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((VQAHandleP *)vqa)->vocfh != -1) {\n\t\tclose(((VQAHandleP *)vqa)->vocfh);\n\t}\n\t#endif /* VQAVOC_ON */\n\n\t/* Close the VQA file */\n\t((VQAHandleP *)vqa)->IOHandler(vqa, VQACMD_CLOSE, NULL, 0);\n\n\t/* Reset the VQAHandle */\n\tiohandler = ((VQAHandleP *)vqa)->IOHandler;\n\tmemset(vqa, 0, sizeof(VQAHandleP));\n\t((VQAHandleP *)vqa)->IOHandler = iohandler;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_LoadFrame - Load the next video frame from the VQA data stream.\n*\n* SYNOPSIS\n*     Error = VQA_LoadFrame(VQA)\n*\n*     long VQA_LoadFrame(VQAHandle *);\n*\n* FUNCTION\n*     The codebook is split up such that the last frame of every group gets\n*     a new, complete codebook, ready for the next group.  The first codebook\n*     in the VQA is a full codebook, and goes with the first frame's data.\n*     Partial codebooks are stored per frame after that, and they add up to\n*     a full codebook just before the first frame for the next group is read.\n*\n*     (Currently, this routine can read either the older non-frame-grouped\n*     VQA file format, or the new frame-chunk format.  For the older format,\n*     it's assumed that the last chunk in a frame is the pointer data.)\n*\n*     This routine also does a sort of \"cooperative multitasking\".  If the\n*     Loader hits a \"wait state\" where it has to wait on the audio to finish\n*     playing before it can continue to load, it sets a \"sleep\" flag and\n*     just returns.  The sleep flag is checked on entry to see if it needs\n*     to jump to the proper execution point. This may improve performance on\n*     some platforms, but it also allows the Loader to be called regardless\n*     of the size of the buffers; if the buffers fill up or the audio fails\n*     to play, the Loader won't just get stuck.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle structure.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nlong VQA_LoadFrame(VQAHandle *vqa)\n{\n\tVQAHandleP    *vqap;\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQADrawer     *drawer;\n\tVQAFrameNode  *curframe;\n\tChunkHeader   *chunk;\n\tunsigned long iffsize;\n\tlong          frame_loaded = 0;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqap = (VQAHandleP *)vqa;\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\tdrawer = &((VQAHandleP *)vqa)->VQABuf->Drawer;\n\tcurframe = loader->CurFrame;\n\tchunk = &loader->CurChunkHdr;\n\n\t/* We have reached the end of the file if we loaded all the frames. */\n\tif (loader->CurFrameNum >= vqap->Header.Frames) {\n\t\treturn (VQAERR_EOF);\n\t}\n\n\t/* If we're reading audio from a VOC file then service that requirement. */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (vqap->vocfh != -1) {\n\t\tLoad_AudFrame(vqap);\n\t}\n\t#endif /* VQAAUDIO_ON & VQAVOC_ON */\n\n\t/* If no buffer is available for loading then return. This allows the\n\t * drawer to service one of the buffers more readily. (We'll wait for one\n\t * to free up).\n\t */\n\tif (curframe->Flags & VQAFRMF_LOADED) {\n\t\tloader->WaitsOnDrawer++;\n\t\treturn (VQAERR_NOBUFFER);\n\t}\n\n\t/* If we're not sleeping, initialize */\n\tif (!(vqabuf->Flags & VQADATF_LSLEEP)) {\n\t\tframe_loaded = 0;\n\t\tloader->FrameSize = 0;\n\n\t\t/* Initialize the codebook ptr for the frame we're about to load:\n\t\t * (This frame's codebook is the last full codebook; we have to init it\n\t\t * now, because if we're on the last frame in a group, we'll get a new\n\t\t * FullCB pointer.)\n\t\t */\n\t\tcurframe->Codebook = loader->FullCB;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * THE MAIN LOADER LOOP\n\t *-----------------------------------------------------------------------*/\n\twhile (frame_loaded == 0) {\n\n\t\t/* Read new chunk, only if we're not sleeping */\n\t\tif (!(vqabuf->Flags & VQADATF_LSLEEP)) {\n\n\t\t\t/* Read chunk ID */\n\t\t\tif (vqap->IOHandler(vqa, VQACMD_READ, chunk, 8)) {\n\t\t\t\treturn (VQAERR_EOF);\n\t\t\t}\n\n\t\t\tiffsize = REVERSE_LONG(chunk->size);\n\t\t\tloader->FrameSize += iffsize;\n\t\t}\n\n\t\t/* Handle each chunk type */\n\t\tswitch (chunk->id) {\n\n\t\t\t/* VQ Normal Frame */\n\t\t\tcase ID_VQFR:\n\t\t\t\tif (Load_VQF(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* VQ Key Frame */\n\t\t\tcase ID_VQFK:\n\t\t\t\tif (Load_VQF(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as being key. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_KEY;\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* Full uncompressed codebook */\n\t\t\tcase ID_CBF0:\n\t\t\t\tif (Load_CBF0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Full compressed codebook */\n\t\t\tcase ID_CBFZ:\n\t\t\t\tif (Load_CBFZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Partial uncompressed codebook */\n\t\t\tcase ID_CBP0:\n\t\t\t\tif (Load_CBP0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Partial compressed codebook */\n\t\t\tcase ID_CBPZ:\n\t\t\t\tif (Load_CBPZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed palette */\n\t\t\tcase ID_CPL0:\n\t\t\t\tif (Load_CPL0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* If this is the first occurance of a palette then store it now.\n\t\t\t\t * This functionality is needed for Monopoly!\n\t\t\t\t */\n\t\t\t\tif (drawer->CurPalSize == 0) {\n\t\t\t\t\tmemcpy(drawer->Palette_24,curframe->Palette,curframe->PaletteSize);\n\t\t\t\t\tdrawer->CurPalSize = curframe->PaletteSize;\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as having a palette. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_PALETTE;\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed palette */\n\t\t\tcase ID_CPLZ:\n\t\t\t\tif (Load_CPLZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* If this is the first occurance of a palette then store it now.\n\t\t\t\t * This functionality is needed for Monopoly!\n\t\t\t\t */\n\t\t\t\tif (drawer->CurPalSize == 0) {\n\t\t\t\t\tdrawer->CurPalSize = LCW_Uncompress((char *)curframe->Palette\n\t\t\t\t\t\t\t+ curframe->PalOffset, (char *)drawer->Palette_24,\n\t\t\t\t\t\t\tvqabuf->Max_Pal_Size);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as having a palette. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_PALETTE;\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed pointer data */\n\t\t\tcase ID_VPT0:\n\t\t\t\tif (Load_VPT0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed pointer data */\n\t\t\tcase ID_VPTZ:\n\t\t\tcase ID_VPTD:\n\t\t\t\tif (Load_VPTZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* Pointer data Key (Must draw) */\n\t\t\tcase ID_VPTK:\n\t\t\t\tif (Load_VPTZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as being key. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_KEY;\n\t\t\t\tframe_loaded = 1;\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed audio frame.\n\t\t\t *\n\t\t\t *  - Make sure the sound load buffer (Audio.TempBuf) is empty; if not\n\t\t\t *    go into a sleep state.\n\t\t\t *  - Load the data into TempBuf.\n\t\t\t */\n\t\t\t#if(VQAAUDIO_ON)\n\t\t\tcase ID_SND0:\n\t\t\t\tif (!(vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO)) {\n\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load an uncompressed audio frame. */\n\t\t\t\t\tif (Load_SND0(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ID_SNA0:\n\t\t\t\tif (vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO) {\n\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load an uncompressed audio frame. */\n\t\t\t\t\tif (Load_SND0(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed audio frame.\n\t\t\t *\n\t\t\t *  - Make sure the sound load buffer (Audio.TempBuf) is empty; if not\n\t\t\t *    go into a sleep state.\n\t\t\t *  - Load the data into TempBuf.\n\t\t\t */\n\t\t\tcase ID_SND1:\n\t\t\t\tif (!(vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO)) {\n\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load a compressed audio frame. */\n\t\t\t\t\tif (Load_SND1(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ID_SNA1:\n\t\t\t\tif (vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO) {\n\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load a compressed audio frame. */\n\t\t\t\t\tif (Load_SND1(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* HMI ADPCM compressed audio frame.\n\t\t\t *\n\t\t\t *  - Make sure the sound load buffer (Audio.TempBuf) is empty; if not\n\t\t\t *    go into a sleep state.\n\t\t\t *  - Load the data into TempBuf.\n\t\t\t */\n\t\t\tcase ID_SND2:\n\t\t\t\tif (!(vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO)) {\n\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load a compressed audio frame. */\n\t\t\t\t\tif (Load_SND2(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ID_SNA2:\n\t\t\t\tif (vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO) {\n\n\t\t\t\t\t/* Move the last audio frame to the play buffer. */\n\t\t\t\t\tif (CopyAudio(vqap) == VQAERR_SLEEPING) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LSLEEP;\n\t\t\t\t\t\treturn (VQAERR_SLEEPING);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvqabuf->Flags &= (~VQADATF_LSLEEP);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Load a compressed audio frame. */\n\t\t\t\t\tif (Load_SND2(vqap, iffsize) != 0) {\n\t\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t#endif\n\n\t\t\t/* Skip any unknown chunks. */\n\t\t\tdefault:\n\t\t\t\tif (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\t\t\tPADSIZE(iffsize))) {\n\t\t\t\t\treturn (VQAERR_SEEK);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/* Update maximum frame size stat. */\n\tif ((loader->CurFrameNum>0) && (loader->FrameSize>loader->MaxFrameSize)) {\n\t\tloader->MaxFrameSize = loader->FrameSize;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * SET UP THE FRAME FOR DRAWING.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Set the frame # */\n\tcurframe->FrameNum = loader->CurFrameNum;\n\tloader->CurFrameNum++;\n\n\t/* Update data for mono output */\n\tloader->LastFrameNum = loader->CurFrameNum;\n\n\t/* Loader is finished with this frame; tell Drawer to draw it */\n\tcurframe->Flags |= VQAFRMF_LOADED;\n\tloader->CurFrame = curframe->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_SeekFrame - Position the movie stream to the specified frame.\n*\n* SYNOPSIS\n*     Frame = VQA_SeekFrame(VQA, Frame, FromWhere)\n*\n*     long VQA_SeekFrame(VQAHandle *, long, long);\n*\n* FUNCTION\n*     This function sets the movie stream to the new frame specified by\n*     the 'offset' parameter. 'FromWhere' is a symbolic constant that is used\n*     to specify from where in the stream offset should be applied.\n*\n* INPUTS\n*     VQA       - Pointer to VQAHandle of movie to seek into.\n*     Frame     - Frame to seek to.\n*     FromWhere - Relative position indicator.\n*\n* RESULT\n*     Frame - New frame position or -1 if error.\n*\n****************************************************************************/\n\nlong VQA_SeekFrame(VQAHandle *vqa, long framenum, long fromwhere)\n{\n\tVQAHandleP   *vqap;\n\tVQAData      *vqabuf;\n\tVQALoader    *loader;\n\tVQAHeader    *header;\n\tVQAFrameNode *frame;\n\tVQAConfig    *config;\n\tlong         group;\n\tlong         i;\n\tlong         rc = VQAERR_NONE;\n\n\t#if(VQAAUDIO_ON)\n\tVQAAudio     *audio;\n\tlong         audio_on;\n \t#endif\n\n\t/* Dereference commonly used data members for quick access. */\n\tvqap = (VQAHandleP *)vqa;\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\theader = &vqap->Header;\n\tconfig = &vqap->Config;\n\n\tfromwhere = fromwhere;\n\n\t#if(VQAAUDIO_ON)\n\taudio = &vqabuf->Audio;\n\n\t/* Stop audio playback. */\n\taudio_on = (audio->Flags & VQAAUDF_ISPLAYING);\n\tVQA_StopAudio(vqap);\n\t#endif\n\n\t/* Make sure the requested frame is valid and the frame information\n\t * array is allocated before continuing.\n\t */\n\tif ((framenum < header->Frames) && (vqabuf->Foff != NULL)) {\n\n\t\t/* Find and load the most recent palette. */\n\t\tif (!(config->OptionFlags & VQAOPTF_PALOFF)) {\n\n\t\t\t/* Get the current frame. */\n\t\t\tframe = loader->CurFrame;\n\n\t\t\tfor (i = framenum; i >= 0; i--) {\n\t\t\t\tif (vqabuf->Foff[i] & VQAFINF_PAL) {\n\n\t\t\t\t\t/* Seek to the palette frame. */\n\t\t\t\t\trc = vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_SET,\n\t\t\t\t\t\t\tVQAFRAME_OFFSET(vqabuf->Foff[i]));\n\n\t\t\t\t\t/* Fool the loader into thinking this frame is empty. */\n\t\t\t\t\tif (!rc) {\n\t\t\t\t\t\tloader->NumPartialCB = 0;\n\t\t\t\t\t\tloader->PartialCBSize = 0;\n\t\t\t\t\t\tloader->FullCB = vqabuf->CBData;\n\t\t\t\t\t\tloader->CurCB = vqabuf->CBData;\n\t\t\t\t\t\tloader->CurFrameNum = 0;\n\t\t\t\t\t\tframe->Flags = 0;\n\n\t\t\t\t\t\t/* Load the frame with the palette. */\n\t\t\t\t\t\tif (VQA_LoadFrame(vqa) == 0) {\n\n\t\t\t\t\t\t\t/* Decompress the palette if neccessary.*/\n\t\t\t\t\t\t\tif (frame->Flags & VQAFRMF_PALCOMP) {\n\t\t\t\t\t\t\t\tframe->PaletteSize = LCW_Uncompress((char *)frame->Palette\n\t\t\t\t\t\t\t\t\t\t+ frame->PalOffset, (char *)frame->Palette,\n \t\t\t\t\t\t\t\t\t\tvqabuf->Max_Pal_Size);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tSetPalette(frame->Palette, frame->PaletteSize, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\trc = VQAERR_SEEK;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Build the codebook for the frame we are seeking to. */\n\t\tif (!rc) {\n\n\t\t\t/* Compute the starting group frame of the requested frame. */\n\t\t\tgroup = (framenum / header->Groupsize);\n\t\t\tgroup = (group * header->Groupsize);\n\n\t\t\t/* The codebook for the group we want to goto is found in the previous\n\t\t\t * group, with the exception of the very first group.\n\t\t\t */\n\t\t\tif (group >= header->Groupsize) {\n\t\t\t\tgroup -= header->Groupsize;\n\t\t\t}\n\n\t\t\t/* Seek to the start of the group containing the partial codebooks for\n\t\t\t * the target frame.\n\t\t\t */\n\t\t\tif (!vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_SET,\n\t\t\t\t\tVQAFRAME_OFFSET(vqabuf->Foff[group]))) {\n\n\t\t\t\t/* Throw away any audio frames that were loaded. */\n\t\t\t\t#if(VQAAUDIO_ON)\n\t\t\t\tif ((config->OptionFlags & VQAOPTF_AUDIO)\n\t\t\t\t\t\t&& (audio->Buffer != NULL)) {\n\t\t\t\t\tmemset(audio->IsLoaded, 0, audio->NumAudBlocks * sizeof(short));\n\t\t\t\t\tmemset(audio->Buffer, 0, config->AudioBufSize);\n\n\t\t\t\t\t/* Position the audio buffer to 1/2 second. */\n\t\t\t\t\taudio->AudBufPos = (long)(((audio->SampleRate * audio->Channels)\n\t\t\t\t\t\t\t* (audio->BitsPerSample >> 3)) / 2);\n\n\t\t\t\t\t/* Mark 1/2 second of the audio buffer as loaded. */\n\t\t\t\t\tfor (i = 0; i < (audio->AudBufPos / config->HMIBufSize); i++) {\n\t\t\t\t\t\taudio->IsLoaded[i] = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\t/* Force the loader to the desired frame. */\n\t\t\t\tloader->NumPartialCB = 0;\n\t\t\t\tloader->PartialCBSize = 0;\n\t\t\t\tloader->FullCB = vqabuf->CBData;\n\t\t\t\tloader->CurCB = vqabuf->CBData;\n\t\t\t\tloader->CurFrameNum = group;\n\n\t\t\t\t/* Load frames up to the target frame collecting partial codebooks\n\t\t\t\t * along the way.\n\t\t\t\t */\n\t\t\t\tfor (i = 0; i < (framenum - group); i++) {\n\n\t\t\t\t\t/* Fool the loader into thinking the frame has been drawn. */\n\t\t\t\t\tloader->CurFrame->Flags = 0;\n\n\t\t\t\t\t#if(VQAAUDIO_ON)\n\t\t\t\t\taudio->TempBufLen = 0;\n\t\t\t\t\t#endif\n\n\t\t\t\t\t/* Load the frame. */\n\t\t\t\t\tif ((rc = VQA_LoadFrame(vqa)) != 0) {\n\t\t\t\t\t\tif ((rc != VQAERR_NOBUFFER) && (rc != VQAERR_SLEEPING)) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\trc = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* If everything is okay, then re-prime the buffers. */\n\t\t\t\tif (!rc) {\n\n\t\t\t\t\t/* Mark all the frames except the current one as empty. */\n\t\t\t\t\tloader->CurFrame->Flags = 0;\n\t\t\t\t\tframe = loader->CurFrame->Next;\n\n\t\t\t\t\twhile (frame != loader->CurFrame) {\n\t\t\t\t\t\tframe->Flags = 0;\n\t\t\t\t\t\tframe = frame->Next;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Set the drawer to the current frame and the loader\n\t\t\t\t\t * to the next.\n\t\t\t\t\t */\n\t\t\t\t\tvqabuf->Drawer.CurFrame = loader->CurFrame;\n\n\t\t\t\t\t/* Prime the buffers for the new position. */\n\t\t\t\t\trc = PrimeBuffers(vqa);\n\n\t\t\t\t\t/* An end of file is not considered and error. */\n\t\t\t\t\tif ((rc == 0) || (rc == VQAERR_EOF)) {\n\t\t\t\t\t\trc = framenum;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trc = VQAERR_SEEK;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Restart audio playback. */\n\t#if(VQAAUDIO_ON)\n\tif (audio_on) {\n\t\tVQA_StartAudio(vqap);\n\t}\n\t#endif\n\n\treturn (rc);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     AllocBuffers - Allocate VQA play buffers.\n*\n* SYNOPSIS\n*     VQAData = AllocBuffers(Header, Config)\n*\n*     VQAData *AllocBuffers(VQAHeader *, VQAConfig *);\n*\n* FUNCTION\n*     For those structures that contain buffer pointers (codebook nodes,\n*     frame buffer nodes), enough memory is allocated for both the structure\n*     and its associated buffers, then the buffer pointers are pointed to\n*     the appropriate offset from the structure pointer.  This allows us\n*     to perform only one malloc & free for each node.\n*\n*     Buffers allocated:\n*       - vqa\n*       - vqa->CBData (list)\n*       - vqa->FrameData (list)\n*       - vqa->Drawer.ImageBuf\n*       - vqa->Audio.Buffer\n*       - vqa->Audio.IsLoaded\n*       - vqa->Foff\n*\n* INPUTS\n*     Header - Pointer to VQAHeader structure.\n*     Config - Pointer to VQA configuration structure.\n*\n* RESULT\n*     VQAData - Pointer to initialized VQAData structure.\n*\n****************************************************************************/\n\nstatic VQAData *AllocBuffers(VQAHeader *header, VQAConfig *config)\n{\n\tVQAData      *vqa;\n\tVQACBNode    *cbnode;\n\tVQACBNode    *this_cb;\n\tVQAFrameNode *framenode;\n\tVQAFrameNode *this_frame;\n\tlong         i;\n\n\t/* Check the configuration for valid values. */\n\tif ((config->NumCBBufs == 0) || (config->NumFrameBufs == 0)) {\n\t\treturn (NULL);\n\t}\n\n\t/* Allocate the master structure */\n\tif ((vqa = (VQAData *)malloc(sizeof(VQAData))) == NULL) {\n\t\treturn (NULL);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * INITIALIZE THE VQA DATA STRUCTURES.\n\t *\n\t * Pointers are set to NULL initially, and filled in as the buffers are\n\t * allocated.  The Max buffer sizes are computed with 1K of padding,\n\t * and'd with 0xFFFC to make the size divisible by 4, to ensure DWORD\n\t * alignment.\n\t *-----------------------------------------------------------------------*/\n\tDPMI_Lock(vqa, sizeof(VQAData));\n\tmemset(vqa, 0, sizeof(VQAData));\n\tvqa->MemUsed = sizeof(VQAData);\n\tvqa->Drawer.LastTime = (-VQA_TIMETICKS);\n\n\t/* Set maximum codebook size. */\n\tvqa->Max_CB_Size = ((header->CBentries) * header->BlockWidth\n\t\t\t* header->BlockHeight + 250) & 0xFFFC;\n\n\t/* Set maximum palette size. */\n\tvqa->Max_Pal_Size = (768 + 1024) & 0xFFFC;\n\n\t/* Set maximum vector pointers size. */\n\tvqa->Max_Ptr_Size = ((header->ImageWidth / header->BlockWidth)\n\t\t\t* (header->ImageHeight / header->BlockHeight)\n\t\t\t* sizeof(short) + 1024) & 0xFFFC;\n\n\t/* Set the frame number of the frame containing the last codebook. */\n\tvqa->Loader.LastCBFrame = (((header->Frames - 1) / header->Groupsize)\n\t\t\t* header->Groupsize);\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE THE CODEBOOK BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\tfor (i = 0; i < config->NumCBBufs; i++) {\n\n\t\t/* Allocate a codebook node. */\n\t\tcbnode = (VQACBNode *)malloc((sizeof(VQACBNode) + vqa->Max_CB_Size));\n\n\t\t/* If failure then clean up and exit. */\n\t\tif (cbnode == NULL) {\n\t\t\tFreeBuffers(vqa, config, header);\n\t\t\treturn (NULL);\n\t\t}\n\n\t\t/* Lock the buffer to prevent page swapping. */\n\t\tDPMI_Lock(cbnode, (sizeof(VQACBNode) + vqa->Max_CB_Size));\n\n\t\t/* Keep count of the memory usage. */\n\t\tvqa->MemUsed += (long)(sizeof(VQACBNode) + vqa->Max_CB_Size);\n\n\t\t/* Initialize the node */\n\t\tmemset(cbnode, 0, sizeof(VQACBNode));\n\t\tcbnode->Buffer = (unsigned char *)cbnode + sizeof(VQACBNode);\n\n\t\t/* Install the node */\n\t\tif (i == 0) {\n\t\t\tvqa->CBData = cbnode;\n\t\t\tthis_cb = cbnode;\n\t\t} else {\n\t\t\tthis_cb->Next = cbnode;\n\t\t\tthis_cb = cbnode;\n\t\t}\n\t}\n\n\t/* Make the list circular */\n\tcbnode->Next = vqa->CBData;\n\n\t/* Install the Codebook list */\n\tvqa->Loader.CurCB = vqa->CBData;\n\tvqa->Loader.FullCB = vqa->CBData;\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE THE FRAME BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\tfor (i = 0; i < config->NumFrameBufs; i++) {\n\n\t\t/* Allocate a pointer node */\n\t\tframenode = (VQAFrameNode *)malloc((sizeof(VQAFrameNode)\n\t\t\t\t+ vqa->Max_Ptr_Size + vqa->Max_Pal_Size));\n\n\t\t/* If failure then clean up and exit. */\n\t\tif (framenode == NULL) {\n\t\t\tFreeBuffers(vqa, config, header);\n\t\t\treturn (NULL);\n\t\t}\n\n\t\t/* Lock the buffer to prevent page swapping. */\n\t\tDPMI_Lock(framenode, sizeof(VQAFrameNode) + vqa->Max_Ptr_Size\n\t\t\t\t+ vqa->Max_Pal_Size);\n\n\t\t/* Keep count of the memory usage. */\n\t\tvqa->MemUsed += (long)(sizeof(VQAFrameNode) + vqa->Max_Ptr_Size\n\t\t\t\t+ vqa->Max_Pal_Size);\n\n\t\t/* Initialize the node */\n\t\tmemset(framenode, 0, sizeof(VQAFrameNode));\n\t\tframenode->Pointers = (unsigned char *)framenode + sizeof(VQAFrameNode);\n\t\tframenode->Palette = (unsigned char *)framenode + sizeof(VQAFrameNode)\n\t\t\t\t+ vqa->Max_Ptr_Size;\n\n\t\tframenode->Codebook = vqa->CBData;\n\n\t\t/* Install the node */\n\t\tif (i == 0) {\n\t\t\tvqa->FrameData = framenode;\n\t\t\tthis_frame = framenode;\n\t\t} else {\n\t\t\tthis_frame->Next = framenode;\n\t\t\tthis_frame = framenode;\n\t\t}\n\t}\n\n\t/* Make the list circular */\n\tframenode->Next = vqa->FrameData;\n\n\t/* Install the Frame Buffer list */\n\tvqa->Loader.CurFrame = vqa->FrameData;\n\tvqa->Drawer.CurFrame = vqa->FrameData;\n\tvqa->Flipper.CurFrame = vqa->FrameData;\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE THE IMAGE BUFFERS IF ONE IS NOT ALREADY PROVIDED.\n\t *-----------------------------------------------------------------------*/\n\tif (config->ImageBuf == NULL) {\n\n\t\t/* Allocate our own buffer. */\n\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\tvqa->Drawer.ImageBuf = (unsigned char *)malloc((header->ImageWidth\n\t\t\t\t\t* header->ImageHeight));\n\n\t\t\t/* If the allocation failed we must free up and exit. */\n\t\t\tif (vqa->Drawer.ImageBuf == NULL) {\n\t\t\t\tFreeBuffers(vqa, config, header);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\n\t\t\t/* Lock to prevent page swapping. */\n\t\t\tDPMI_Lock(vqa->Drawer.ImageBuf,header->ImageWidth*header->ImageHeight);\n\n\t\t\t/* Plugin image buffer information. */\n\t\t\tvqa->Drawer.ImageWidth = header->ImageWidth;\n\t\t\tvqa->Drawer.ImageHeight = header->ImageHeight;\n\t\t\tvqa->MemUsed += (long)(header->ImageWidth * header->ImageHeight);\n\t\t} else {\n\t\t\tvqa->Drawer.ImageWidth = config->ImageWidth;\n\t\t\tvqa->Drawer.ImageHeight = config->ImageHeight;\n\t\t}\n\t} else {\n\n\t\t/* Use caller provided buffer */\n\t\tvqa->Drawer.ImageBuf = config->ImageBuf;\n\t\tvqa->Drawer.ImageWidth = config->ImageWidth;\n\t\tvqa->Drawer.ImageHeight = config->ImageHeight;\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE AND INITIALIZE AUDIO BUFFERS AND STRUCTURES.\n\t *-----------------------------------------------------------------------*/\n\t#if(VQAAUDIO_ON)\n\tif ((header->Flags & VQAHDF_AUDIO)\n\t\t\t&& (config->OptionFlags & VQAOPTF_AUDIO)) {\n\n\t\t/* Dereference audio structure for quick access. */\n\t\tVQAAudio *audio = &vqa->Audio;\n\n\t\t/* Version 1 VQA's only supported 22050 8 bit mono audio. */\n\t\tif (header->Version < VQAHD_VER2) {\n\t\t\taudio->SampleRate = 22050U;\n\t\t\taudio->Channels = 1;\n\t\t\taudio->BitsPerSample = 8;\n\t\t\taudio->BytesPerSec = 22050;\n\t\t} else {\n\t\t\tif ((config->OptionFlags & VQAOPTF_ALTAUDIO)\n\t\t\t\t\t&& (header->Flags & VQAHDF_ALTAUDIO)) {\n\t\t\t\taudio->SampleRate = header->AltSampleRate;\n\t\t\t\taudio->Channels = header->AltChannels;\n\t\t\t\taudio->BitsPerSample = header->AltBitsPerSample;\n\t\t\t} else {\n\t\t\t\taudio->SampleRate = header->SampleRate;\n\t\t\t\taudio->Channels = header->Channels;\n\t\t\t\taudio->BitsPerSample = header->BitsPerSample;\n\t\t\t}\n\n\t\t\taudio->BytesPerSec = ((audio->SampleRate * audio->Channels)\n\t\t\t\t\t* (audio->BitsPerSample >> 3));\n\t\t}\n\n\t\t/* Adjust the HMI buffer to accomodate the amount of data. */\n\t\t#if(0)\n\t\tconfig->HMIBufSize *= (audio->SampleRate / 22050);\n\t\tconfig->HMIBufSize *= audio->Channels * (audio->BitsPerSample >> 3);\n\t\t#endif\n\n\t\t/* The default audio buffer size should be large enough to hold\n\t\t * 1.5 seconds of data.\n\t\t */\n\t\tif (config->AudioBufSize == -1) {\n\n\t\t\t/* Compute the number of HMI buffers that will completly fit into\n\t\t\t * 1.5 seconds of audio data.\n\t\t\t */\n\t\t\ti = ((audio->BytesPerSec+(audio->BytesPerSec/2))/config->HMIBufSize);\n\t\t\tconfig->AudioBufSize = (config->HMIBufSize * i);\n\t\t}\n\n\t\t/* Do not allocate anything if the audio buffer is zero length. */\n\t\tif (config->AudioBufSize > 0) {\n\n\t\t\t/* Allocate an audio buffer if the user did not provide one.\n\t\t\t * Otherwise, use the user supplied buffer.\n\t\t\t */\n\t\t\tif (config->AudioBuf == NULL) {\n\t\t\t\taudio->Buffer = (unsigned char *)malloc(config->AudioBufSize);\n\n\t\t\t\t/* If failure then clean up and exit. */\n\t\t\t\tif (audio->Buffer == NULL) {\n\t\t\t\t\tFreeBuffers(vqa, config, header);\n\t\t\t\t\treturn (NULL);\n\t\t\t\t}\n\n\t\t\t\tDPMI_Lock(audio->Buffer, config->AudioBufSize);\n\n\t\t\t\t/* Add audio buffer size to memory usage. */\n\t\t\t\tvqa->MemUsed += config->AudioBufSize;\n\t\t\t} else {\n\t\t\t\taudio->Buffer = config->AudioBuf;\n\t\t\t}\n\n\t\t\t/* Allocate IsLoaded flags */\n\t\t\taudio->NumAudBlocks = (config->AudioBufSize / config->HMIBufSize);\n\t\t\taudio->IsLoaded = (short *)malloc(audio->NumAudBlocks * sizeof(short));\n\n\t\t\t/* If failure then clean up and exit. */\n\t\t\tif (audio->IsLoaded == NULL) {\n\t\t\t\tFreeBuffers(vqa, config, header);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\n\t\t\t/* Lock to prevent page swapping. */\n\t\t\tDPMI_Lock(audio->IsLoaded, audio->NumAudBlocks * sizeof(short));\n\n\t\t\t/* Add IsLoaded flags array to memory usage. */\n\t\t\tvqa->MemUsed += (audio->NumAudBlocks * sizeof(short));\n\n\t\t\t/* Initialize audio IsLoaded flags to false. */\n\t\t\tmemset(audio->IsLoaded, 0, audio->NumAudBlocks * sizeof(short));\n\n\t\t\t/* Allocate temporary staging buffer for the audio frames. */\n\t\t\taudio->TempBufSize = ((audio->BytesPerSec / header->FPS) * 2) + 100;\n\t\t\taudio->TempBuf = (unsigned char *)malloc(audio->TempBufSize);\n\n\t\t\tif (audio->TempBuf == NULL) {\n\t\t\t\tFreeBuffers(vqa, config, header);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\n\t\t\t/* Lock to prevent page swapping. */\n\t\t\tDPMI_Lock(audio->TempBuf, audio->TempBufSize);\n\n\t\t\t/* Add temporary buffer size to memory usage. */\n\t\t\tvqa->MemUsed += audio->TempBufSize;\n\t\t}\n\t}\n\t#endif /* VQAAUDIO_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * ALLOCATE THE FRAME INFORMATION TABLE IF REQUESTED.\n\t *-----------------------------------------------------------------------*/\n\tvqa->Foff = (long *)malloc(header->Frames * sizeof(long));\n\n\tif (vqa->Foff == NULL) {\n\t\tFreeBuffers(vqa, config, header);\n\t\treturn (NULL);\n\t}\n\n\t/* Lock to prevent page swapping. */\n\tDPMI_Lock(vqa->Foff, header->Frames * sizeof(long));\n\n\t/* Keep a running total of memory usage. */\n\tvqa->MemUsed += (header->Frames * sizeof(long));\n\n\treturn (vqa);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     FreeBuffers - Free VQA play buffers.\n*\n* SYNOPSIS\n*     FreeBuffers(VQAData, Config, Header)\n*\n*     void FreeBuffers(VQAData *, VQAConfig *, VQAHeader *);\n*\n* FUNCTION\n*      Free the buffers allocated by AllocBuffers().\n*\n* INPUTS\n*      VQAData - Pointer to VQAData structure.\n*      Config  - Pointer to configuration structure.\n*      Header  - Pointer to movie header structure.\n*\n* RESULT\n*      NONE\n*\n****************************************************************************/\n\nstatic void FreeBuffers(VQAData *vqa, VQAConfig *config, VQAHeader *header)\n{\n\tVQACBNode    *cb_this,\n\t             *cb_next;\n\tVQAFrameNode *frame_this,\n\t             *frame_next;\n\tlong         i;\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE FRAME INFORMATION TABLE.\n\t *-----------------------------------------------------------------------*/\n\tif (vqa->Foff) {\n\t\tDPMI_Unlock(vqa->Foff, header->Frames * sizeof(long));\n\t\tfree(vqa->Foff);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE AUDIO BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\n\t#if(VQAAUDIO_ON)\n\tif ((config->AudioBuf == NULL) && (vqa->Audio.Buffer)) {\n\t\tDPMI_Unlock(vqa->Audio.Buffer, config->AudioBufSize);\n\t\tfree(vqa->Audio.Buffer);\n\t}\n\n\t/* Free the audio segments loaded flag array. */\n\tif (vqa->Audio.IsLoaded) {\n\t\tDPMI_Unlock(vqa->Audio.IsLoaded,vqa->Audio.NumAudBlocks * sizeof(short));\n\t\tfree(vqa->Audio.IsLoaded);\n\t}\n\n\t/* Free the temporary audio buffer. */\n\tif (vqa->Audio.TempBuf) {\n\t\tDPMI_Unlock(vqa->Audio.TempBuf, vqa->Audio.TempBufSize);\n\t\tfree(vqa->Audio.TempBuf);\n\t}\n\t#endif /* VQAAUDIO_ON */\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE IMAGE BUFFER ONLY IF WE ALLOCATED IT.\n\t *-----------------------------------------------------------------------*/\n\tif ((config->ImageBuf == NULL) && vqa->Drawer.ImageBuf) {\n\t\tDPMI_Unlock(vqa->Drawer.ImageBuf,header->ImageWidth*header->ImageHeight);\n\t\tfree(vqa->Drawer.ImageBuf);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE FRAME BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\tframe_this = vqa->FrameData;\n\n\tfor (i = 0; i < config->NumFrameBufs; i++) {\n\t\tif (frame_this) {\n\t\t\tframe_next = frame_this->Next;\n\t\t\tDPMI_Unlock(frame_this, sizeof(VQAFrameNode) + vqa->Max_Ptr_Size\n\t\t\t\t\t+ vqa->Max_Pal_Size);\n\t\t\tfree(frame_this);\n\t\t\tframe_this = frame_next;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE CODEBOOK BUFFERS.\n\t *-----------------------------------------------------------------------*/\n\tcb_this = vqa->CBData;\n\n\tfor (i = 0; i < config->NumCBBufs; i++) {\n\t\tif (cb_this) {\n\t\t\tcb_next = cb_this->Next;\n\t\t\tDPMI_Unlock(cb_this, sizeof(VQACBNode) + vqa->Max_CB_Size);\n\t\t\tfree(cb_this);\n\t\t\tcb_this = cb_next;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * FREE THE VQA DATA STRUCTURES.\n\t *-----------------------------------------------------------------------*/\n\tDPMI_Unlock(vqa, sizeof(VQAData));\n\tfree(vqa);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     PrimeBuffers - Pre-Load the internal buffers.\n*\n* SYNOPSIS\n*     Error = PrimeBuffers(VQA)\n*\n*     long = PrimeBuffers(VQAHandle *);\n*\n* FUNCTION\n*     Pre-load the internal buffers in order to give the player some slack\n*     in the playback of large frames.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle structure.\n*\n* RESULT\n*     Error - 0 if successful, or VQAERR_??? error code.\n*\n****************************************************************************/\n\nlong PrimeBuffers(VQAHandle *vqa)\n{\n\tVQAData   *vqabuf;\n\tVQAConfig *config;\n\tlong      rc;\n\tlong      i;\n\n\t/* Dereference commonly used data members for quick access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* Pre-load the buffers */\n\tfor (i = 0; i < config->NumFrameBufs; i++) {\n\t\tif ((rc = VQA_LoadFrame(vqa)) == 0) {\n\t\t\tvqabuf->LoadedFrames++;\n\t\t}\n\t\telse if ((rc != VQAERR_NOBUFFER) && (rc != VQAERR_SLEEPING)) {\n\t\t\treturn (rc);\n\t\t}\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_VQF - Loads a VQ Frame chunk.\n*\n* SYNOPSIS\n*     Error = Load_VQF(VQA, Iffsize)\n*\n*     long Load_VQF(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*     The VQ Frame Chunk contains a set of other chunks (codebooks,\n*     palettes, pointers).  This routine reads the frame's chunk size,\n*     then loops until it's read that many bytes.\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_VQF(VQAHandleP *vqap, unsigned long frame_iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQAFrameNode  *curframe;\n\tChunkHeader   *chunk;\n\tunsigned long iffsize;\n\tunsigned long framesize;\n\tunsigned long bytes_loaded = 0;\n\tVQADrawer     *drawer;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tcurframe = vqabuf->Loader.CurFrame;\n\tframesize = PADSIZE(frame_iffsize);\n\tdrawer = &(vqap->VQABuf->Drawer);\n\tchunk = &vqabuf->Loader.CurChunkHdr;\n\n\t/*-------------------------------------------------------------------------\n\t * FRAME LOADING LOOP.\n\t *-----------------------------------------------------------------------*/\n\twhile (bytes_loaded < framesize) {\n\n\t\t/* Read chunk ID */\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, chunk, 8)) {\n\t\t\treturn (VQAERR_EOF);\n\t\t}\n\n\t\tiffsize = REVERSE_LONG(chunk->size);\n\t\tbytes_loaded += 8;\n\t\tbytes_loaded += PADSIZE(iffsize);\n\n\t\t/* Handle each chunk type */\n\t\tswitch (chunk->id) {\n\n\t\t\t/* Full uncompressed codebook */\n\t\t\tcase ID_CBF0:\n\t\t\t\tif (Load_CBF0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Full compressed codebook */\n\t\t\tcase ID_CBFZ:\n\t\t\t\tif (Load_CBFZ(vqap, iffsize)) {\n\t\t\t\t \treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Partial uncompressed codebook */\n\t\t\tcase ID_CBP0:\n\t\t\t\tif (Load_CBP0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Partial compressed codebook */\n\t\t\tcase ID_CBPZ:\n\t\t\t\tif (Load_CBPZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed palette */\n\t\t\tcase ID_CPL0:\n\t\t\t\tif (Load_CPL0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* If this is the first occurance of a palette then store it now.\n\t\t\t\t * This functionality is needed for Monopoly!\n\t\t\t\t */\n\t\t\t\tif (drawer->CurPalSize == 0) {\n\t\t\t\t\tmemcpy(drawer->Palette_24,curframe->Palette,curframe->PaletteSize);\n\t\t\t\t\tdrawer->CurPalSize = curframe->PaletteSize;\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as having a palette. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_PALETTE;\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed palette */\n\t\t\tcase ID_CPLZ:\n\t\t\t\tif (Load_CPLZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* If this is the first occurance of a palette then store it now.\n\t\t\t\t * This functionality is needed for Monopoly!\n\t\t\t\t */\n\t\t\t\tif (drawer->CurPalSize == 0) {\n\t\t\t\t\tdrawer->CurPalSize = LCW_Uncompress((char *)curframe->Palette\n\t\t\t\t\t\t\t+ curframe->PalOffset, (char *)drawer->Palette_24,\n\t\t\t\t\t\t\tvqabuf->Max_Pal_Size);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as having a palette. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_PALETTE;\n\t\t\t\tbreak;\n\n\t\t\t/* Uncompressed pointer data */\n\t\t\tcase ID_VPT0:\n\t\t\t\tif (Load_VPT0(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed pointer data */\n\t\t\tcase ID_VPTZ:\n\t\t\tcase ID_VPTD:\n\t\t\t\tif (Load_VPTZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Compressed pointer data */\n\t\t\tcase ID_VPTK:\n\t\t\t\tif (Load_VPTZ(vqap, iffsize)) {\n\t\t\t\t\treturn (VQAERR_READ);\n\t\t\t\t}\n\n\t\t\t\t/* Flag this frame as being key. */\n\t\t\t\tcurframe->Flags |= VQAFRMF_KEY;\n\t\t\t\tbreak;\n\n\t\t\t/* An unknown chunk in the video frame is an error. */\n\t\t\tdefault:\n\t\t\t\treturn (VQAERR_READ);\n\t\t}\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_FINF - Load Frame Info chunk.\n*\n* SYNOPSIS\n*     Error = Load_FINF(VQA, Iffsize)\n*\n*     long Load_FINF(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*     Load FINF chunk if buffer available, otherwise skip it.\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_FINF(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData *vqabuf;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\n\t/* Load the frame information table if we need to, otherwise we will\n\t * skip it.\n\t */\n\tif (vqabuf->Foff != NULL) {\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, vqabuf->Foff,\n\t\t\t\tPADSIZE(iffsize))) {\n\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\t} else {\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\tPADSIZE(iffsize))) {\n\t\t\treturn (VQAERR_SEEK);\n\t\t}\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_VQHD - Load VQA header chunk.\n*\n* SYNOPSIS\n*     Error = Load_VQHD(VQA, Iffsize)\n*\n*     long Load_VQHD(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_VQHD(VQAHandleP *vqap, unsigned long iffsize)\n{\n\t/* Read the header */\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, &vqap->Header,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Reconfigure the Drawer for the new settings */\n\tVQA_Configure_Drawer(vqap);\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CBF0 - Load full uncompressed codebook.\n*\n* SYNOPSIS\n*     Error = Load_CBF0(VQA, Iffsize)\n*\n*     long Load_CBF0(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CBF0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQALoader *loader;\n\tVQACBNode *curcb;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tloader = &vqap->VQABuf->Loader;\n\tcurcb = loader->CurCB;\n\n\t/* Read into the start of the buffer */\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, curcb->Buffer,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Reset the partial codebook counter. */\n\tloader->NumPartialCB = 0;\n\n\t/* Flag this codebook as uncompressed. */\n\tcurcb->Flags &= (~VQACBF_CBCOMP);\n\tcurcb->CBOffset = 0;\n\n\t/* Clock pointers to next CB Buffer. */\n\tloader->FullCB = curcb;\n\tloader->FullCB->Flags &= (~VQACBF_DOWNLOADED);\n\tloader->CurCB = curcb->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CBFZ - Load full compressed codebook.\n*\n* SYNOPSIS\n*     Error = Load_CBFZ(VQA, Iffsize)\n*\n*     long Load_CBFZ(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CBFZ(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQALoader     *loader;\n\tVQACBNode     *curcb;\n\tvoid          *buffer;\n\tunsigned long padsize;\n\tunsigned long lcwoffset;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tloader = &vqap->VQABuf->Loader;\n\tcurcb = loader->CurCB;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* Load the codebook into the end of the buffer. */\n\tlcwoffset = vqap->VQABuf->Max_CB_Size - padsize;\n\tbuffer = curcb->Buffer + lcwoffset;\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Reset the partial codebook counter. */\n\tloader->NumPartialCB = 0;\n\n\t/* Flag this codebook as compressed */\n\tcurcb->Flags |= VQACBF_CBCOMP;\n\tcurcb->CBOffset = lcwoffset;\n\n\t/* Clock pointers to next CB Buffer */\n\tloader->FullCB = curcb;\n\tloader->FullCB->Flags &= (~VQACBF_DOWNLOADED);\n\tloader->CurCB = curcb->Next;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CBP0 - Load partial uncompressed codebook.\n*\n* SYNOPSIS\n*     Error = Load_CBP0(VQA, Iffsize)\n*\n*     long Load_CBP0(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQA_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CBP0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData   *vqabuf;\n\tVQALoader *loader;\n\tVQACBNode *curcb;\n\tvoid      *buffer;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\tcurcb = loader->CurCB;\n\n\t/*-------------------------------------------------------------------------\n\t * ASSEMBLY PARTIAL CODEBOOKS.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Read the partial codebook into the next position in the buffer. */\n\tbuffer = curcb->Buffer + loader->PartialCBSize;\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Accumulate the partial codebook values. */\n\tloader->PartialCBSize += iffsize;\n\tloader->NumPartialCB++;\n\n\t/*-------------------------------------------------------------------------\n\t * PROCESS FULL CODEBOOK.\n\t *-----------------------------------------------------------------------*/\n\tif (loader->NumPartialCB == vqap->Header.Groupsize) {\n\n\t\t/* Reset the codebook accumulator values */\n\t\tloader->NumPartialCB = 0;\n\t\tloader->PartialCBSize = 0;\n\n\t\t/* Flag this codebook as uncompressed */\n\t\tcurcb->Flags &= (~VQACBF_CBCOMP);\n\t\tcurcb->CBOffset = 0;\n\n\t\t/* Go to the next codebook buffer */\n\t\tloader->FullCB = curcb;\n\t\tloader->FullCB->Flags &= (~VQACBF_DOWNLOADED);\n\t\tloader->CurCB = curcb->Next;\n\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CBPZ - Load partial compressed codebook.\n*\n* SYNOPSIS\n*     Error = Load_CBPZ(VQA, Iffsize)\n*\n*     long Load_CBPZ(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CBPZ(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQACBNode     *curcb;\n\tvoid          *buffer;\n\tunsigned long padsize;\n\n\t/* Dereference commonly used data members for quicker access */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\tcurcb = loader->CurCB;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* Attempt to compute the LCW offset into the codebook buffer by\n\t * multiplying the size of this chunk by the # frames/group, and adding\n\t * a small fudge factor on, then subtracting that from the CB buffer size.\n\t */\n\tif (loader->PartialCBSize == 0) {\n\t\tcurcb->CBOffset = (vqabuf->Max_CB_Size\n\t\t\t\t- (padsize * vqap->Header.Groupsize + 100));\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * ASSEMBLE PARTIAL CODEBOOKS.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Read the partial codebook into the next position in the buffer. */\n\tbuffer = ((curcb->Buffer + curcb->CBOffset) + loader->PartialCBSize);\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Accumulate partial codebook values */\n\tloader->PartialCBSize += iffsize;\n\tloader->NumPartialCB++;\n\n\t/*-------------------------------------------------------------------------\n\t * PROCESS FULL CODEBOOK.\n\t *-----------------------------------------------------------------------*/\n\tif (loader->NumPartialCB == vqap->Header.Groupsize) {\n\n\t\t/* Reset the codebook accumulator values. */\n\t\tloader->NumPartialCB = 0;\n\t\tloader->PartialCBSize = 0;\n\n\t\t/* Flag this codebook as compressed. */\n\t\tcurcb->Flags |= VQACBF_CBCOMP;\n\n\t\t/* Go to the next codebook buffer */\n\t\tloader->FullCB = curcb;\n\t\tloader->FullCB->Flags &= (~VQACBF_DOWNLOADED);\n\t\tloader->CurCB = curcb->Next;\n\t}\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CPL0 - Load an uncompressed palette.\n*\n* SYNOPSIS\n*     Error = Load_CPL0(VQA, Iffsize)\n*\n*     long Load_CPL0(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CPL0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAFrameNode *curframe;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tcurframe = vqap->VQABuf->Loader.CurFrame;\n\n\t/* Read the palette into the palette buffer */\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, curframe->Palette,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Flag the palette as uncompressed. */\n\tcurframe->Flags &= ~VQAFRMF_PALCOMP;\n\tcurframe->PalOffset = 0;\n\tcurframe->PaletteSize = iffsize;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_CPLZ - Load compressed palette.\n*\n* SYNOPSIS\n*     Error = Load_CPLZ(VQA, Iffsize)\n*\n*     long Load_CPLZ(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_CPLZ(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAFrameNode  *curframe;\n\tvoid          *buffer;\n\tunsigned long padsize;\n\tunsigned long lcwoffset;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tcurframe = vqap->VQABuf->Loader.CurFrame;\n\tpadsize = PADSIZE(iffsize);\n\n \t/* Read the palette into the end of the palette buffer. */\n\tlcwoffset = vqap->VQABuf->Max_Pal_Size - padsize;\n\tbuffer = curframe->Palette + lcwoffset;\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Flag this palette as compressed. */\n\tcurframe->Flags |= VQAFRMF_PALCOMP;\n\tcurframe->PalOffset = lcwoffset;\n\tcurframe->PaletteSize = iffsize;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_VPT0 - Load uncompressed pointers.\n*\n* SYNOPSIS\n*     Error = Load_VPT0(VQA, Iffsize)\n*\n*     long Load_VPT0(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_VPT0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAFrameNode *curframe;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tcurframe = vqap->VQABuf->Loader.CurFrame;\n\n\t/* Read the pointers into start of the pointer buffer. */\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, curframe->Pointers,\n\t\t\tPADSIZE(iffsize))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Flag this frame as uncompressed */\n\tcurframe->Flags &= ~VQAFRMF_PTRCOMP;\n\tcurframe->PtrOffset = 0;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_VPTZ - Load compressed pointers.\n*\n* SYNOPSIS\n*     Error = Load_VPTZ(VQA, Iffsize)\n*\n*     long Load_VPTZ(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_VPTZ(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAFrameNode  *curframe;\n\tvoid          *buffer;\n\tunsigned long padsize;\n\tunsigned long lcwoffset;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tcurframe = vqap->VQABuf->Loader.CurFrame;\n\tpadsize = PADSIZE(iffsize);\n\tlcwoffset = vqap->VQABuf->Max_Ptr_Size - padsize;\n\n\t/* Read the pointers into end of the pointer buffer. */\n\tbuffer = curframe->Pointers + lcwoffset;\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Flag this frame as compressed. */\n\tcurframe->Flags |= VQAFRMF_PTRCOMP;\n\tcurframe->PtrOffset = lcwoffset;\n\n\treturn (0);\n}\n\n\n#if(VQAAUDIO_ON)\n/****************************************************************************\n*\n* NAME\n*     Load_SND0 - Load uncompressed sound chunk.\n*\n* SYNOPSIS\n*     Error = Load_SND0(VQA, Iffsize)\n*\n*     long Load_SND0(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*     This routine normally loads the chunk into the TempBuf, unless the\n*     chunk is larger than the temp buffer size, in which case it puts it\n*     directly into the audio buffer itself.  This assumes that the only\n*     such chunk will be the first audio chunk!\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_SND0(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tunsigned long padsize;\n\tlong          i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\taudio = &vqabuf->Audio;\n\tconfig = &vqap->Config;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* If sound is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, just skip the chunk.\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0)\n\t\t\t|| (vqap->vocfh != -1) || (audio->Buffer == NULL)) {\n\t#else  /* VQAVOC_ON */\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0)\n\t\t\t|| (audio->Buffer == NULL)) {\n\t#endif /* VQAVOC_ON */\n\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\tpadsize)) {\n\t\t\treturn (VQAERR_SEEK);\n\t\t} else {\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\t/* Read large startup chunk directly into AudioBuf */\n\tif ((padsize > audio->TempBufSize) && (audio->AudBufPos == 0)) {\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, audio->Buffer,\n\t\t\t\tpadsize)) {\n\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\n\t\taudio->AudBufPos += iffsize;\n\n\t\t/* Flag the audio frame flags as loaded for the initial audio frame. */\n\t\tfor (i = 0; i < (iffsize / config->HMIBufSize); i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t} else {\n\n\t\t/*  Read data into TempBuf */\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, audio->TempBuf,\n\t\t\t\tpadsize)) {\n\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\t}\n\n\t/* Set the TempBufLen */\n\taudio->TempBufLen = iffsize;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_SND1 - Load compressed sound chunk.\n*\n* SYNOPSIS\n*     Error = Load_SND1(VQA, Iffsize)\n*\n*     long Load_SND1(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*     This routine normally loads the chunk into the TempBuf, unless the\n*     chunk is larger than the temp buffer size, in which case it puts it\n*     directly into the audio buffer itself.  This assumes that the only\n*     such chunk will be the first audio chunk!\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_SND1(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tunsigned char *loadbuf;\n\tunsigned long padsize;\n\tZAPHeader     zap;\n\tlong          i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\taudio = &vqabuf->Audio;\n\tconfig = &vqap->Config;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* If sound is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, just skip the chunk\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (vqap->vocfh != -1)\n\t\t\t|| (audio->Buffer == NULL)) {\n\t#else\n\tif (((config->OptionFlags & VQAOPTF_AUDIO)==0) || (audio->Buffer==NULL)) {\n\t#endif /* VQAVOC_ON */\n\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\tpadsize)) {\n\t\t\treturn (VQAERR_SEEK);\n\t\t} else {\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\t/* Read the ZAP audio frame header. */\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, &zap,\n\t\t\tsizeof(ZAPHeader))) {\n\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Adjust chunk size */\n\tpadsize -= sizeof(ZAPHeader);\n\n\t/* Read large startup chunk directly into AudioBuf */\n\tif ((zap.UnCompSize > audio->TempBufSize) && (audio->AudBufPos == 0)) {\n\n\t\t/* Load RAW uncompressed data. */\n\t\tif (zap.UnCompSize == zap.CompSize) {\n\t\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, audio->Buffer,\n\t\t\t\t\tpadsize)) {\n\n\t\t\t\treturn (VQAERR_READ);\n\t\t\t}\n\t\t} else {\n\n\t\t\t/* Load compressed data into the end of the buffer. */\n\t\t\tloadbuf = (audio->Buffer + config->AudioBufSize) - padsize;\n\n\t\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, loadbuf,\n\t\t\t\t\tpadsize)) {\n\n\t\t\t\treturn (VQAERR_READ);\n\t\t\t}\n\n\t\t\t/* Uncompress the audio frame. */\n\t\t\tAudioUnzap(loadbuf, audio->Buffer, zap.UnCompSize);\n\t\t}\n\n\t\t/* Set buffer positions & flags */\n\t\taudio->AudBufPos += zap.UnCompSize;\n\n\t\tfor (i = 0; i < (zap.UnCompSize / config->HMIBufSize); i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t}\n\n\t/* Load an audio frame. */\n\tif (zap.UnCompSize == zap.CompSize) {\n\n\t\t/* If the frame is uncompressed the load it in directly. */\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, audio->TempBuf,\n\t\t\t\tpadsize)) {\n\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\t} else {\n\n\t\t/* Load the audio frame into the end of the buffer. */\n\t\tloadbuf = ((audio->TempBuf + audio->TempBufSize) - padsize);\n\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, loadbuf, padsize)) {\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\n\t\t/* Uncompress the audio frame. */\n\t\tAudioUnzap(loadbuf, audio->TempBuf, zap.UnCompSize);\n\t}\n\n\t/* Set the TempBufLen */\n\taudio->TempBufLen = zap.UnCompSize;\n\n\treturn (0);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_SND2 - Load ADPCM compressed sound chunk.\n*\n* SYNOPSIS\n*     Error = Load_SND2(VQA, Iffsize)\n*\n*     long Load_SND2(VQAHandleP *, unsigned long);\n*\n* FUNCTION\n*     This routine normally loads the chunk into the TempBuf, unless the\n*     chunk is larger than the temp buffer size, in which case it puts it\n*     directly into the audio buffer itself.  This assumes that the only\n*     such chunk will be the first audio chunk!\n*\n* INPUTS\n*     VQA     - Pointer to private VQA handle.\n*     Iffsize - Size of IFF chunk.\n*\n* RESULT\n*     Error - 0 if successful or VQAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long Load_SND2(VQAHandleP *vqap, unsigned long iffsize)\n{\n\tVQAData       *vqabuf;\n\tVQALoader     *loader;\n\tVQAAudio      *audio;\n\tVQAConfig     *config;\n\tunsigned char *loadbuf;\n\tunsigned long padsize;\n\tunsigned long uncomp_size;\n\tlong          i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\taudio = &vqabuf->Audio;\n\tconfig = &vqap->Config;\n\tpadsize = PADSIZE(iffsize);\n\n\t/* If sound is disabled, or if we're playing from a VOC file, or if\n\t * there's no Audio Buffer, just skip the chunk\n\t */\n\t#if(VQAVOC_ON && VQAAUDIO_ON)\n\tif (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (vqap->vocfh != -1)\n\t\t\t|| (audio->Buffer == NULL)) {\n\t#else  /* VQAVOC_ON */\n\tif (((config->OptionFlags & VQAOPTF_AUDIO)==0) || (audio->Buffer==NULL)) {\n\t#endif /* VQAVOC_ON */\n\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_SEEK, (void *)SEEK_CUR,\n\t\t\t\tpadsize)) {\n\t\t\treturn (VQAERR_SEEK);\n\t\t} else {\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\tuncomp_size = iffsize * (audio->BitsPerSample / 4);\n\n\t/* Read large startup chunk directly into AudioBuf */\n\tif ((uncomp_size > audio->TempBufSize) && (audio->AudBufPos == 0)) {\n\n\t\t/* Load compressed data into the end of the buffer. */\n\t\tloadbuf = (audio->Buffer + config->AudioBufSize) - padsize;\n\n\t\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, loadbuf, padsize)) {\n\t\t\treturn (VQAERR_READ);\n\t\t}\n\n\t\t/* Uncompress the audio frame. */\n\t\taudio->ADPCM_Info.lpSource = (char *)loadbuf;\n\t\taudio->ADPCM_Info.lpDest = (char *)audio->Buffer;\n\t\tsosCODECDecompressData(&audio->ADPCM_Info, uncomp_size);\n\n\t\t/* Set buffer positions & flags */\n\t\taudio->AudBufPos += uncomp_size;\n\n\t\tfor (i = 0; i < (uncomp_size / config->HMIBufSize); i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\treturn (0);\n\t}\n\n\t/* Load an audio frame. */\n\tloadbuf = ((audio->TempBuf + audio->TempBufSize) - padsize);\n\n\tif (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, loadbuf, padsize)) {\n\t\treturn (VQAERR_READ);\n\t}\n\n\t/* Uncompress the audio frame. */\n\taudio->ADPCM_Info.lpSource = (char *)loadbuf;\n\taudio->ADPCM_Info.lpDest = (char *)audio->TempBuf;\n\tsosCODECDecompressData(&audio->ADPCM_Info, uncomp_size);\n\n\t/* Set the TempBufLen */\n\taudio->TempBufLen = uncomp_size;\n\n\treturn (0);\n}\n\n\n#if(VQAVOC_ON)\n/****************************************************************************\n*\n* NAME\n*     Load_AudFrame - Loads blocks from seperate VOC file.\n*\n* SYNOPSIS\n*     Load_AudFrame(VQA)\n*\n*     void Load_AudFrame(VQAHandleP *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to private VQA handle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void Load_AudFrame(VQAHandleP *vqap)\n{\n\tVQAData     *vqabuf;\n\tVQALoader   *loader;\n\tVQAAudio    *audio;\n\tVQAConfig   *config;\n\tstatic long lastplayblock = -1;\n\tstatic long myblock = 0;\n\tstatic long firsttime = 1;\n\tlong        numblocks;\n\tlong        i;\n\n\t/* Dereference commonly used data members for quicker access. */\n\tvqabuf = vqap->VQABuf;\n\tloader = &vqabuf->Loader;\n\taudio = &vqabuf->Audio;\n\tconfig = &vqap->Config;\n\n\t/* Do nothing if no buffer */\n\tif (audio->Buffer == NULL) {\n\t\treturn;\n\t}\n\n\t/* If this is the first time we're called, pre-load the 1st 'n' audio\n\t * blocks, where 'n' is half the total audio buffer size; this way, we'll\n\t * always stay ahead of HMI.\n\t */\n\tif (firsttime) {\n\t\tnumblocks = (audio->NumAudBlocks / 2);\n\t\tread(vqap->vocfh, audio->Buffer, config->HMIBufSize * numblocks);\n\t\taudio->AudBufPos += config->HMIBufSize * numblocks;\n\n\t\tif (audio->AudBufPos >= config->AudioBufSize) {\n\t\t\taudio->AudBufPos = 0;\n\t\t}\n\n\t\tfor (i = 0; i < numblocks; i++) {\n\t\t\taudio->IsLoaded[i] = 1;\n\t\t}\n\n\t\tmyblock += numblocks;\n\n\t\tif (myblock >= audio->NumAudBlocks) {\n\t\t\tmyblock = 0;\n\t\t}\n\n\t\tfirsttime = 0;\n\t}\n\n\t/* If HMI's block has changed, load the next block & mark it as loaded */\n\tif (audio->PlayPosition / config->HMIBufSize != lastplayblock) {\n\n\t\t/* update HMI's last known block position */\n\t\tlastplayblock = audio->PlayPosition / config->HMIBufSize;\n\n\t\t/* read the VOC data */\n\t\tread(vqap->vocfh, (audio->Buffer + myblock * config->HMIBufSize),\n\t\t\t\tconfig->HMIBufSize);\n\n\t\taudio->AudBufPos += config->HMIBufSize;\n\n\t\tif (audio->AudBufPos >= config->AudioBufSize) {\n\t\t\taudio->AudBufPos = 0;\n\t\t}\n\n\t\t/* set the IsLoaded flags */\n\t\taudio->IsLoaded[myblock] = 1;\n\n\t\t/* increment my block counter */\n\t\tmyblock++;\n\n\t\tif (myblock >= audio->NumAudBlocks) {\n\t\t\tmyblock = 0;\n\t\t}\n\t}\n}\n#endif /* VQAVOC_ON */\n#endif /* VQAAUDIO_ON */\n\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQAPlay 32-bit library.\n#\n# FILE\n#     makefile (Watcom C/C++ 10.0a)\n#\n# DESCRIPTION\n#     Makefile for generating the 32-bit VQAPlay library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n# \n# DATE\n#     February 10, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     WATCOM - Watcom C installation path.\n#\n#****************************************************************************\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n.OPTIMIZE\n.ERASE\n\n#----------------------------------------------------------------------------\n# PROJECTS DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJ    = ..\nWATCOM = C:\\WATCOM\nPRJNAME = vqa32wp\nPRJDIR  = $(PRJ)\\VQA32\n\nOBJECTS = &\n\tconfig.obj &\n\ttask.obj &\n\tloader.obj &\n\tdrawer.obj &\n\taudio.obj &\n\tmonodisp.obj &\n\tdstream.obj &\n\tunvqbuff.obj &\n\tunvqvesa.obj &\n\tvertag.obj &\n\tcaption.obj &\n#\tunvqxmde.obj\n\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!ifdef %LIB\nLIBPATH = $(PRJ)\\LIB;$(%LIB)\n!else\nLIBPATH = $(PRJ)\\LIB;$(WATCOM)\\LIB386\n!endif\n\n!ifdef %INCLUDE\nINCLUDEPATH = $(PRJ)\\INCLUDE;$(%INCLUDE)\n!else\nINCLUDEPATH = $(PRJ)\\INCLUDE;$(WATCOM)\\H\n!endif\n\npath_c   = .\\\npath_cpp = .\\\npath_h   = .\\\npath_asm = .\\\npath_i   = .\\\npath_obj = .\\O\npath_lib = $(PRJ)\\LIB\npath_exe = .\\\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULE EXTENSIONS AND PATHS\n#----------------------------------------------------------------------------\n\n.EXTENSIONS :\n.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i\n\n.c : $(path_c)\n.cpp : $(path_cpp)\n.h : $(path_h)\n.asm : $(path_asm)\n.i : $(path_i)\n.obj : $(path_obj)\n.lib : $(path_lib)\n.exe : $(path_exe)\n\n#----------------------------------------------------------------------------\n# Tools/commands & configurations\n#----------------------------------------------------------------------------\n\nCC_CMD   = wcc386\nCCP_CMD  = wpp386\nASM_CMD  = tasm32\nLINK_CMD = wlink\nLIB_CMD  = wlib\n\nCC_OPTS  = -i$(INCLUDEPATH) -j -zp1 -5r -mf -oaeilrt -s -zq -d2\nASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /i$(PRJ)\\INCLUDE\\VQM32 /dPHARLAP_TNT=0\nLIB_OPTS = /b /c /q\nLINK_CFG = $(PRJNAME).lnk\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall : $(PRJNAME).lib .SYMBOLIC\n\n$(PRJNAME).lib : $(OBJECTS) .SYMBOLIC\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj :\n  $(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.cpp.obj :\n  $(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\\$^.\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\nupdate: .SYMBOLIC\n\t@echo Updating VQAPlay32 header files!\n\t@copy vqaplay.h ..\\include\\vqa32 >NUL\n\t@copy vqafile.h ..\\include\\vqa32 >NUL\n\n\u001a"
  },
  {
    "path": "WINVQ/VQA32/OLD/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQAPlay32 library.\n#\n# FILE\n#     makefile (Borland/TNT)\n#\n# DESCRIPTION\n#     Makefile for generating the 32-bit VQAPlay library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n#\n# DATE\n#     Feburary 7, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     BCDIR  - Borland C installation path.\n#     TNTDIR - Pharlap/TNT installation path.\n#\n#****************************************************************************\n\n.AUTODEPEND\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n!if !$d(PRJ) || !$d(PRJVCS) || !$d(BCDIR) || !$d(TNTDIR) \n!error Environment not configured.\n!endif\n\n#----------------------------------------------------------------------------\n# PROJECTS DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJNAME\t= vqa32bp\nPRJDIR = $(PRJ)\\VQA32\n\nOBJECTS = \\\n\tconfig.obj \\\n\ttask.obj \\\n\tloader.obj \\\n\tdrawer.obj \\\n\taudio.obj \\\n\tmonodisp.obj \\\n\tdstream.obj \\\n\tunvqbuff.obj \\\n\tunvqvesa.obj \\\n\tvertag.obj \\\n\tcaption.obj \\\n#\tunvqxmde.obj \\\n\nPRJLIBS = \\\n\tvqm32bp.lib \\\n\t\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!if $d(LIB)\nLIBPATH = $(PRJ)\\LIB;$(LIB)\n!else\nLIBPATH = $(PRJ)\\LIB;$(TNTDIR)\\LIB;$(BCDIR)\\LIB\n!endif\n\n!if $d(INCLUDE)\nINCLUDEPATH\t= $(PRJ)\\INCLUDE;$(INCLUDE)\n!else\nINCLUDEPATH\t= $(PRJ)\\INCLUDE;$(TNTDIR)\\INCLUDE;$(BCDIR)\\INCLUDE\n!endif\n\n.path.asm = $(PRJDIR)\n.path.c   = $(PRJDIR)\n.path.cpp = $(PRJDIR)\n.path.h   = $(PRJDIR)\n.path.exe = $(PRJDIR)\n.path.obj = $(PRJDIR)\\OBJ\n.path.sym = $(PRJDIR)\\OBJ\n.path.lib = $(PRJ)\\LIB\n\n#----------------------------------------------------------------------------\n# TOOLS, COMMAND AND CONFIGURATIONS\n#----------------------------------------------------------------------------\n\nCC_CMD   = bcc32\nASM_CMD  = tasm32\nLINK_CMD = tlink32\nLIB_CMD  = tlib\n\nCC_CFG    = bcc32.cfg\nASM_CFG   = tasm32.cfg\nLINK_CFG  = tlink32.cfg\nLIB_CFG   = tlib.cfg\nCFG_FILES = $(CC_CFG) $(ASM_CFG) $(LINK_CFG) $(LIB_CFG)\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall: $(PRJNAME).lib\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj:\n\t$(CC_CMD) -P- -n$(.path.obj) {$< }\n\n.cpp.obj:\n\t$(CC_CMD) -P -n$(.path.obj) {$< }\n\n.asm.obj:\n\t$(ASM_CMD) @$(ASM_CFG) $<,$(.path.obj)\\$&\n\n#----------------------------------------------------------------------------\n# BUILD LIBRARY\n#----------------------------------------------------------------------------\n\n$(PRJNAME).lib: $(OBJECTS)\n\t- @del $(.path.lib)\\$(PRJNAME).lib >&NUL\n\t$(LIB_CMD) $(.path.lib)\\$(PRJNAME).lib @$(LIB_CFG) @&&|\n-+$(**: = -+)\n|\n\t- @copy vqaplay.h $(PRJ)\\INCLUDE\\VQA32 >&NUL\n\t- @copy vqafile.h $(PRJ)\\INCLUDE\\VQA32 >&NUL\n\n#----------------------------------------------------------------------------\n# ALL OBJECTS DEPEND ON THE CONFIGURATION FILES\n#----------------------------------------------------------------------------\n\n$(OBJECTS):\t$(CFG_FILES)\n\n#----------------------------------------------------------------------------\n# COMPILER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(CC_CFG): makefile\n\tcopy &&|\n-c\n-3\n-d\n-H=$(.path.sym)\\headers.sym\n-wpro\n-weas\n-wpre\n-I$(INCLUDEPATH)\n-DPHARLAP_TNT=1\n#-v\n| $(CC_CFG)\n \n#----------------------------------------------------------------------------\n# ASSEMBLER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(ASM_CFG): makefile\n\tcopy &&|\n/t\n/m\n/w+\n/jJUMPS\n/ml\n/p\n/z\n/i$(PRJ)\\INCLUDE\\VQM32\n/zi\n/dPHARLAP_TNT=1\n| $(ASM_CFG)\n\n#----------------------------------------------------------------------------\n# LINKER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(LINK_CFG): makefile\n\tcopy &&|\n/c\n/m\n/Gm\n-L$(LIBPATH)\n-v\n| $(LINK_CFG)\n\n#----------------------------------------------------------------------------\n# LIBRARIAN CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(LIB_CFG):\tmakefile\n\tcopy &&|\n/C /E\n| $(LIB_CFG)\n\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQAPlay 32-bit library.\n#\n# FILE\n#     makefile (Watcom C/C++ 10.0a)\n#\n# DESCRIPTION\n#     Makefile for generating the 32-bit VQAPlay library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n# \n# DATE\n#     February 10, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     WATCOM - Watcom C installation path.\n#\n#****************************************************************************\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n!ifndef %PRJ || %PRJVCS || %WATCOM\n!error Environment not configured.\n!endif\n\n.OPTIMIZE\n.ERASE\n\n#----------------------------------------------------------------------------\n# PROJECTS DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJNAME = vqa32wp\nPRJDIR  = $(%PRJ)\\VQA32\n\nOBJECTS = &\n\tconfig.obj &\n\ttask.obj &\n\tloader.obj &\n\tdrawer.obj &\n\taudio.obj &\n\tmonodisp.obj &\n\tdstream.obj &\n\tunvqbuff.obj &\n\tunvqvesa.obj &\n\tvertag.obj &\n\tcaption.obj &\n#\tunvqxmde.obj\n\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!ifdef %LIB\nLIBPATH = $(%PRJ)\\LIB;$(%LIB)\n!else\nLIBPATH = $(%PRJ)\\LIB;$(%WATCOM)\\LIB386\n!endif\n\n!ifdef %INCLUDE\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%INCLUDE)\n!else\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%WATCOM)\\H\n!endif\n\npath_c   = .\\\npath_cpp = .\\\npath_h   = .\\\npath_asm = .\\\npath_i   = .\\\npath_obj = .\\O\npath_lib = $(%PRJ)\\LIB\npath_exe = .\\\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULE EXTENSIONS AND PATHS\n#----------------------------------------------------------------------------\n\n.EXTENSIONS :\n.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i\n\n.c : $(path_c)\n.cpp : $(path_cpp)\n.h : $(path_h)\n.asm : $(path_asm)\n.i : $(path_i)\n.obj : $(path_obj)\n.lib : $(path_lib)\n.exe : $(path_exe)\n\n#----------------------------------------------------------------------------\n# Tools/commands & configurations\n#----------------------------------------------------------------------------\n\nCC_CMD   = wcc386\nCCP_CMD  = wpp386\nASM_CMD  = tasm32\nLINK_CMD = wlink\nLIB_CMD  = wlib\n\nCC_OPTS  = -i$(INCLUDEPATH) -j -zp1 -5s -mf -oaeilrt -s -zq\nASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /i$(%PRJ)\\INCLUDE\\VQM32 /dPHARLAP_TNT=0\nLIB_OPTS = /b /c /q\nLINK_CFG = $(PRJNAME).lnk\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall : $(PRJNAME).lib .SYMBOLIC\n\n$(PRJNAME).lib : $(OBJECTS) .SYMBOLIC\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj :\n  $(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.cpp.obj :\n  $(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\\$^.\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\nupdate: .SYMBOLIC\n\t@echo Updating VQAPlay32 header files!\n\t@copy vqaplay.h ..\\include\\vqa32 >NUL\n\t@copy vqafile.h ..\\include\\vqa32 >NUL\n\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/MONODISP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     monodisp.c\n*\n* DESCRIPTION\n*     Monochrome display (debug)\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 6, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_InitMono   - Initialize the player's mono screen.\n*     VQA_UpdateMono - Update the player's mono output.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <string.h>\n#include \"vq.h\"\n#include \"vqaplayp.h\"\n#include <vqm32\\all.h>\n\n#if(VQAMONO_ON)\n\n/* Main window */\n#define\tMAIN_WX1   0\n#define\tMAIN_WX2   79\n#define\tMAIN_WY1   0\n#define\tMAIN_WY2   9\n#define\tMAIN_TITLE \"VQA Player\"\n\n/* Loader data window */\n#define\tLOADER_WX1   0\n#define\tLOADER_WX2   39\n#define\tLOADER_WY1   10\n#define\tLOADER_WY2   20\n#define\tLOADER_TITLE \" Frame Loader \"\n\n/* Drawer data window */\n#define\tDRAWER_WX1   40\n#define\tDRAWER_WX2   79\n#define\tDRAWER_WY1   10\n#define\tDRAWER_WY2   20\n#define\tDRAWER_TITLE \" Frame Drawer \"\n\n/* Audio data window */\n#define\tAUDIO_WX1   0\n#define\tAUDIO_WX2   39\n#define\tAUDIO_WY1   21\n#define\tAUDIO_WY2   24\n#define\tAUDIO_TITLE \" Audio Callback \"\n\n/* Flipper data window */\n#define\tFLIPPER_WX1   40\n#define\tFLIPPER_WX2   79\n#define\tFLIPPER_WY1   21\n#define\tFLIPPER_WY2   24\n#define\tFLIPPER_TITLE \" Frame Flipper \"\n\nextern char *HMIDevName;\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_InitMono - Initialize the player's mono screen.\n*\n* SYNOPSIS\n*     VQA_InitMono(VQA)\n*\n*     void VQA_InitMono(VQAHandleP *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to private VQA handle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\n#pragma argsused\nvoid VQA_InitMono(VQAHandleP *vqap)\n{\n\tVQAData   *vqabuf;\n\tVQAConfig *config;\n\tchar      txt[80];\n\n\t/* Dereference commonly used data members of quick access. */\n\tvqabuf = vqap->VQABuf;\n\tconfig = &vqap->Config;\n\n\t/* Enable and clear the mono screen */\n\tMono_Enable();\n\tMono_Clear_Screen();\n\n\t/* Init main window */\n\tMono_Draw_Rect(MAIN_WX1, MAIN_WY1, (MAIN_WX2 - MAIN_WX1 + 1),\n\t\t\t(MAIN_WY2 - MAIN_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((MAIN_WX2 + MAIN_WX1 - strlen(MAIN_TITLE)) / 2, MAIN_WY1);\n\tMono_Print(MAIN_TITLE);\n\n\t/* Video mode */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 1);\n\tMono_Print(\"Video Mode: \");\n\n\tswitch (config->Vmode) {\n\n\t\t#if(VQAMONO_ON)\n\t\tcase MCGA:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tMono_Print(\"MCGA Buffered\");\n\t\t\t} else {\n\t\t\t\tMono_Print(\"MCGA Direct to screen\");\n\t\t\t}\n\t\t\tbreak;\n\t\t#endif\n\n\t\t#if(VQAXMODE_ON)\n\t\tcase XMODE_320X200:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tMono_Print(\"XMODE 320x200 Buffered\");\n\t\t\t} else {\n\t\t\t\tif (config->DrawFlags & VQACFGF_VRAMCB) {\n\t\t\t\t\tMono_Print(\"XMODE 320x200 VRAM Copy\");\n\t\t\t\t} else {\n\t\t\t\t\tMono_Print(\"XMODE 320x200 Linear->Banked\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase XMODE_320X240:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tMono_Print(\"XMODE 320x240 Buffered\");\n\t\t\t} else {\n\t\t\t\tif (config->DrawFlags & VQACFGF_VRAMCB) {\n\t\t\t\t\tMono_Print(\"XMODE 320x240 VRAM Copy\");\n\t\t\t\t} else {\n\t\t\t\t\tMono_Print(\"XMODE 320x240 Linear->Banked\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t#endif\n\n\t\t#if(VQAVESA_ON)\n\t\tcase VESA_640X480_256:\n\t\t\tMono_Print(\"VESA 640x480\");\n\t\t\tbreak;\n\n\t\tcase VESA_320X200_32K_1:\n\t\t\tif (config->DrawFlags & VQACFGF_BUFFER) {\n\t\t\t\tMono_Print(\"VESA 320x200 Buffered\");\n\t\t\t} else {\n\t\t\t\tMono_Print(\"VESA 320x200 Direct to screen\");\n\t\t\t}\n\t\t\tbreak;\n\t\t#endif\n\n\t\tdefault:\n\t\t\tMono_Print(\"UNKNOWN\");\n\t\t\tbreak;\n\t}\n\n\t/* Sound status */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 2);\n\tMono_Print(\"               Sound: \");\n\n\tif (config->OptionFlags & VQAOPTF_AUDIO) {\n\t\tsprintf(txt,\"%u Hz\", config->AudioRate);\n\t\tMono_Print(txt);\n\t}\telse {\n\t\tMono_Print(\"OFF\");\n\t}\n\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 3);\n\tMono_Print(\"         Driver Name: \");\n\tMono_Print(HMIDevName);\n\n\t/* Frame rates */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 4);\n\tsprintf(txt,\"     Load Frame Rate: %d\", config->FrameRate);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 5);\n\tsprintf(txt,\"     Draw Frame Rate: %d\", config->DrawRate);\n\tMono_Print(txt);\n\n\t/* Slow palette */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 6);\n\tMono_Print(\"        Slow palette: \");\n\n\tif (config->OptionFlags & VQAOPTF_SLOWPAL) {\n\t\tMono_Print(\"ON\");\n\t} else {\n\t\tMono_Print(\"OFF\");\n\t}\n\n\t/* Memory Usage */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 7);\n\tsprintf(txt,\"         Memory Used: %ld\", vqabuf->MemUsed);\n\tMono_Print(txt);\n\n\t/* Timer Method */\n\tMono_Set_Cursor(MAIN_WX1 + 18, MAIN_WY1 + 8);\n\n\tif (VQA_TimerMethod() == VQA_TMETHOD_DOS) {\n\t\tMono_Print(\"           DOS Timer:\");\n\t} else if (VQA_TimerMethod() == VQA_TMETHOD_INT) {\n\t\tMono_Print(\"     Interrupt Timer:\");\n\t} else if (VQA_TimerMethod() == VQA_TMETHOD_AUDIO) {\n\t\tMono_Print(\"     Audio DMA Timer:\");\n\t} else {\n\t\tMono_Print(\"             Defualt:\");\n\t}\n\n\t/* Init loader data window */\n\tMono_Draw_Rect(LOADER_WX1, LOADER_WY1, (LOADER_WX2 - LOADER_WX1 + 1),\n\t\t\t(LOADER_WY2 - LOADER_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((LOADER_WX2 + LOADER_WX1 - strlen(LOADER_TITLE)) / 2,\n\t\t\tLOADER_WY1);\n\n\tMono_Print(LOADER_TITLE);\n\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 1);\n\tMono_Print(\"  Current Frame #:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 2);\n\tMono_Print(\"# Waits on Drawer:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 3);\n\tMono_Print(\" # Waits on Audio:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 4);\n\tMono_Print(\"       Frame Size:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY1 + 5);\n\tMono_Print(\"   Max Frame Size:\");\n\tMono_Set_Cursor(LOADER_WX1 + 2, LOADER_WY2 - 2);\n\tMono_Print(\"Audio:\");\n\n\t/* Init drawer data window */\n\tMono_Draw_Rect(DRAWER_WX1, DRAWER_WY1, (DRAWER_WX2 - DRAWER_WX1 + 1),\n\t\t\t(DRAWER_WY2 - DRAWER_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((DRAWER_WX2 + DRAWER_WX1 - strlen(DRAWER_TITLE)) / 2,\n\t\t\tDRAWER_WY1);\n\n\tMono_Print(DRAWER_TITLE);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 1);\n\tMono_Print(\"   Current Frame #:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 2);\n\tMono_Print(\"   Desired Frame #:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 3);\n\tMono_Print(\"# Waits on Flipper:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 4);\n\tMono_Print(\" # Waits on Loader:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 5);\n\tMono_Print(\"  # Frames Skipped:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY1 + 6);\n\tMono_Print(\"     VQ Block Size:\");\n\tMono_Set_Cursor(DRAWER_WX1 + 2, DRAWER_WY2 - 2);\n\tMono_Print(\"Frames:                 Cbooks:\");\n\n\t/* Init audio data window */\n\tMono_Draw_Rect(AUDIO_WX1, AUDIO_WY1, (AUDIO_WX2 - AUDIO_WX1 + 1),\n\t\t\t(AUDIO_WY2 - AUDIO_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((AUDIO_WX2 + AUDIO_WX1 - strlen(AUDIO_TITLE)) / 2,\n\t\t\tAUDIO_WY1);\n\n\tMono_Print(AUDIO_TITLE);\n\n\tMono_Set_Cursor(AUDIO_WX1 + 2, AUDIO_WY1 + 1);\n\tMono_Print(\"# Repeated Buffers:\");\n\n\t/* Init flipper data window */\n\tMono_Draw_Rect(FLIPPER_WX1, FLIPPER_WY1, (FLIPPER_WX2 - FLIPPER_WX1 + 1),\n\t\t\t(FLIPPER_WY2 - FLIPPER_WY1 + 1), 2, 1);\n\n\tMono_Set_Cursor((FLIPPER_WX2 + FLIPPER_WX1 - strlen(FLIPPER_TITLE)) / 2,\n\t\t\tFLIPPER_WY1);\n\n\tMono_Print(FLIPPER_TITLE);\n\n\tMono_Set_Cursor(FLIPPER_WX1 + 2, FLIPPER_WY1 + 1);\n\tMono_Print(\"Current Frame #:\");\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_UpdateMono - Update the player's mono output.\n*\n* SYNOPSIS\n*     VQA_UpdateMono(VQA)\n*\n*     void VQA_UpdateMono(VQAHandleP *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Pointer to private VQA handle.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\n#pragma argsused\nvoid VQA_UpdateMono(VQAHandleP *vqap)\n{\n\tVQAData       *vqabuf;\n\tVQAConfig     *config;\n\tVQAFrameNode  *frame;\n\tVQACBNode     *cbook;\n\tlong          frameindex = -1;\n\tlong          loadcb = -1;\n\tlong          drawcb = -1;\n\tlong          i;\n\tunsigned long curtime;\n\tchar          txt[80];\n\n\t/* Dereference commonly used data members for quick access. */\n\tvqabuf = vqap->VQABuf;\n\tconfig = &vqap->Config;\n\n\t/* Timer value */\n\tcurtime = VQA_GetTime(vqap);\n\tMono_Set_Cursor(MAIN_WX1 + 40, MAIN_WY1 + 8);\n\tsprintf(txt,\"%02ld:%02ld.%02ld\",curtime / (VQA_TIMETICKS * VQA_TIMETICKS),\n\t\t\tcurtime / VQA_TIMETICKS,((curtime * 100L) / VQA_TIMETICKS)\n\t\t\t-((curtime / VQA_TIMETICKS) * 100L));\n\n\tMono_Print(txt);\n\n\t/* Loader data */\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 1);\n\tsprintf(txt,\"%4d\",vqabuf->Loader.LastFrameNum);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 2);\n\tsprintf(txt,\"%4ld\",vqabuf->Loader.WaitsOnDrawer);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 3);\n\tsprintf(txt,\"%4ld\",vqabuf->Loader.WaitsOnAudio);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 4);\n\tsprintf(txt,\"%5u\",vqabuf->Loader.FrameSize);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 22, LOADER_WY1 + 5);\n\tsprintf(txt,\"%5u\",vqabuf->Loader.MaxFrameSize);\n\tMono_Print(txt);\n\n\t#if(VQAAUDIO_ON)\n\t/* Draw a picture of the audio buffers */\n\tfor (i = 0; i < vqabuf->Audio.NumAudBlocks; i++) {\n\t\tif (vqabuf->Audio.IsLoaded[i] == 0) {\n\t\t\ttxt[i] = '_';\n\t\t} else {\n\t\t\ttxt[i] = 'X';\n\t\t}\n\t}\n\n\ttxt[i] = 0;\n\tMono_Set_Cursor(LOADER_WX1 + 9,LOADER_WY2 - 2);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(LOADER_WX1 + 9,LOADER_WY2-1); \n\tMono_Print(\"                        \");\n\n\tMono_Set_Cursor(LOADER_WX1 + 9 + vqabuf->Audio.PlayPosition\n\t\t\t/ config->HMIBufSize,LOADER_WY2 - 1);\n\n\tMono_Print(\"P\");\n\n\tMono_Set_Cursor(LOADER_WX1 + 9 + vqabuf->Audio.AudBufPos\n\t\t\t/ config->HMIBufSize,LOADER_WY2 - 1);\n\n\tMono_Print(\"L\");\n\t#endif /* VQAAUDIO_ON */\n\n\t/* Drawer data */\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 1);\n\tsprintf(txt,\"%4d\", vqabuf->Drawer.LastFrameNum);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 2);\n\tsprintf(txt,\"%4d\", vqabuf->Drawer.DesiredFrame);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 3);\n\tsprintf(txt,\"%4ld\", vqabuf->Drawer.WaitsOnFlipper);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 4);\n\tsprintf(txt,\"%4ld\", vqabuf->Drawer.WaitsOnLoader);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 5);\n\tsprintf(txt,\"%4d\", vqabuf->Drawer.NumSkipped);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 22,DRAWER_WY1 + 6);\n\tsprintf(txt,\" %dx%d\", vqap->Header.BlockWidth, vqap->Header.BlockHeight);\n\tMono_Print(txt);\n\n\t/* Draw a picture of the frame buffers */\n\tframe = vqabuf->FrameData;\n\n\tfor (i = 0; i < config->NumFrameBufs; i++) {\n\t\tif (frame->Flags & VQAFRMF_LOADED) {\n\t\t\ttxt[i] = 'X';\n\t\t} else {\n\t\t\ttxt[i] = '_';\n\t\t}\n\n\t\tif (vqabuf->Flipper.CurFrame == frame) {\n\t\t\tframeindex = i;\n\t\t}\n\n\t\tframe = frame->Next;\n\t}\n\n\ttxt[i] = 0;\n\tMono_Set_Cursor(DRAWER_WX1 + 10,DRAWER_WY2 - 2);\n\tMono_Print(txt);\n\n\tMono_Set_Cursor(DRAWER_WX1 + 10,DRAWER_WY2 - 1);\n\tMono_Print(\"              \");\n\n\tMono_Set_Cursor(DRAWER_WX1 + 10 + frameindex,DRAWER_WY2 - 1);\n\tMono_Print(\"^\");\n\n\t/* Draw a picture of the codebook buffers */\n\tcbook = vqabuf->CBData;\n\n\tfor (i = 0; i < config->NumCBBufs; i++) {\n\t\tif (vqabuf->Loader.CurCB == cbook) {\n\t\t\tloadcb = i;\n\t\t}\n\n\t\tif (vqabuf->Flipper.CurFrame->Codebook == cbook) {\n\t\t\tdrawcb = i;\n\t\t}\n\n\t\tcbook = cbook->Next;\n\t}\n\n\tMono_Set_Cursor(DRAWER_WX1 + 34,DRAWER_WY2 - 2);\n\tMono_Print(\"___\");\n\n\tMono_Set_Cursor(DRAWER_WX1 + 34,DRAWER_WY2 - 1);\n\tMono_Print(\"   \");\n\n\tMono_Set_Cursor(DRAWER_WX1 + 34 + loadcb,DRAWER_WY2 - 1);\n\tMono_Print(\"L\");\n\n\tMono_Set_Cursor(DRAWER_WX1 + 34 + drawcb,DRAWER_WY2 - 1);\n\tMono_Print(\"D\");\n\n\t/* Audio data */\n\t#if(VQAAUDIO_ON)\n\tMono_Set_Cursor(AUDIO_WX1 + 22, AUDIO_WY1 + 1);\n\tsprintf(txt,\"%4ld\", vqabuf->Audio.NumSkipped);\n\tMono_Print(txt);\n\t#endif\n\n\t/* Flipper data */\n\tMono_Set_Cursor(FLIPPER_WX1 + 22,FLIPPER_WY1 + 1);\n\tsprintf(txt,\"%4d\", vqabuf->Flipper.LastFrameNum);\n\tMono_Print(txt);\n\tMono_Set_Cursor(0,0);\n}\n\n#endif /* VQAMONO_ON */\n\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/SOS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sos.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DEFINED   \n#define  _SOS_DEFINED   \n#include \"sosdefs.h\"\n\n#pragma pack(4)\n \n// error definition for sound operating system  \n#define  _SOS_ERR          -1\n\n// number of drivers allowed to be open at one time\n#define  _SOS_MAX_DRIVERS  5\n\n// structure definition for the capabilities\ntypedef struct _tagCAPABILITIES\n{\n   BYTE  szDeviceName[ 32 ];  // device name\n   WORD  wDeviceVersion;      // device version\n   WORD  wBitsPerSample;      // bits per sound sample\n   WORD  wChannels;           // stereo/mono sound card\n   WORD  wMinRate;            // minimum rate\n   WORD  wMaxRate;            // maximum rate\n   WORD  wMixerOnBoard;       // board contains mixer\n   WORD  wMixerFlags;         // mixer capabilities\n   WORD  wFlags;              // miscellaneous flags   \n   short far * lpPortList;         // list of usable ports\n   short far * lpDMAList;          // list of usable dma channels\n   short far * lpIRQList;          // list of usable irq channels\n   short far * lpRateList;         // list of usable rates, -1 if any in min to max\n   WORD  fBackground;         // foreground or background driver\n   WORD  wDeviceID;           // ID for the device\n   WORD  wTimerID;            // ID for the timer\n   \n} _SOS_CAPABILITIES; \n\n// far pointer to the device capabilities structure\ntypedef _SOS_CAPABILITIES far *  LPSOSDEVICECAPS;\n\n// flag types for driver\n#define  _FLAGS_SIGNED              0x8000\n  \n// devices that can be loaded\n#define  _SOUND_BLASTER_8_MONO      0xe000\n#define  _SOUND_BLASTER_8_ST        0xe001\n#define  _SBPRO_8_ST                _SOUND_BLASTER_8_ST\n#define  _SBPRO_8_MONO              0xe00f\n#define  _SOUND_MASTER_II_8_MONO    0xe002\n#define  _MV_PAS_8_MONO             0xe003\n#define  _MV_PAS_16_MONO            0xe004\n#define  _MV_PAS_8_ST               0xe005\n#define  _MV_PAS_16_ST              0xe006\n#define  _ADLIB_GOLD_8_ST           0xe007\n#define  _ADLIB_GOLD_16_ST          0xe008\n#define  _ADLIB_GOLD_8_MONO         0xe009\n#define  _ADLIB_GOLD_16_MONO        0xe00a\n#define  _MICROSOFT_8_MONO          0xe00b\n#define  _MICROSOFT_8_ST            0xe00c\n#define  _MICROSOFT_16_MONO         0xe00d\n#define  _MICROSOFT_16_ST           0xe00e\n#define  _SOUND_SOURCE_8_MONO_PC    0xe010\n#define  _SOUND_SOURCE_8_MONO_TANDY 0xe011\n#define  _GENERAL_PORT_8_MONO       0xe012\n#define  _GENERAL_PORT_8_MONO_R     0xe013\n#define  _SIERRA_8_MONO             0xe014\n#define  _SB16_8_MONO               0xe015\n#define  _SB16_8_ST                 0xe016\n#define  _SB16_16_MONO              0xe017\n#define  _SB16_16_ST                0xe018\n#define  _ESS_AUDIODRIVE_8_MONO     0xe019\n#define  _ESS_AUDIODRIVE_8_ST       0xe01a\n#define  _ESS_AUDIODRIVE_16_MONO    0xe01b\n#define  _ESS_AUDIODRIVE_16_ST      0xe01c\n#define  _SOUNDSCAPE_8_MONO         0xe01d\n#define  _SOUNDSCAPE_8_ST           0xe01e\n#define  _SOUNDSCAPE_16_MONO        0xe01f\n#define  _SOUNDSCAPE_16_ST          0xe020\n#define  _RAP10_8_MONO              0xe021\n#define  _RAP10_16_MONO             0xe022\n#define  _GUS_8_MONO                0xe023\n#define  _GUS_8_ST                  0xe024\n#define  _GUS_16_MONO               0xe025\n#define  _GUS_16_ST                 0xe026\n#define  _GUS_MAX_8_MONO            0xe027\n#define  _GUS_MAX_8_ST              0xe028\n#define  _GUS_MAX_16_MONO           0xe029\n#define  _GUS_MAX_16_ST             0xe02a\n#define  _WAVEJAMMER_8_MONO         0xe02b\n#define  _WAVEJAMMER_8_ST           0xe02c\n#define  _WAVEJAMMER_16_MONO        0xe02d\n#define  _WAVEJAMMER_16_ST          0xe02e\n#define  _TEMPOCS_8_MONO            0xe02f\n#define  _TEMPOCS_8_ST              0xe030\n#define  _TEMPOCS_16_MONO           0xe031\n#define  _TEMPOCS_16_ST             0xe032\n#define  _WAVEJAMMERCD_8_MONO       0xe033\n#define  _WAVEJAMMERCD_8_ST         0xe034\n#define  _WAVEJAMMERCD_16_MONO      0xe035\n#define  _WAVEJAMMERCD_16_ST        0xe036\n#define  _SOUND_BLASTER_8_MONO_R    0xe050\n#define  _MICROSOFT_8_MONO_R        0xe051\n#define  _SOUND_MASTER_II_8_MONO_R  0xe052\n#define  _ADLIB_GOLD_8_MONO_R       0xe053\n#define  _MV_PAS_8_MONO_R           0xe054\n#define  _RAP10_8_MONO_R            0xe058\n#define  _RAP10_16_MONO_R           0xe059\n#define  _SB16_8_MONO_R             0xe05a\n#define  _SB16_8_ST_R               0xe05b\n#define  _SB16_16_MONO_R            0xe05c\n#define  _SB16_16_ST_R              0xe05d\n#define  _MV_PAS_16_MONO_R          0xe060\n#define  _SOUNDSCAPE_8_MONO_R       0xe061\n#define  _SOUNDSCAPE_8_ST_R         0xe062\n#define  _SOUNDSCAPE_16_MONO_R      0xe063\n#define  _SOUNDSCAPE_16_ST_R        0xe064\n#define  _ESS_AUDIODRIVE_8_MONO_R   0xe065\n#define  _ESS_AUDIODRIVE_8_ST_R     0xe066\n#define  _ESS_AUDIODRIVE_16_MONO_R  0xe067\n#define  _ESS_AUDIODRIVE_16_ST_R    0xe068\n#define  _SPEECH_THING_8_MONO       0xe090\n#define  _YAMAHA_8_MONO             0xe106\n#define  _INT_SPEAKER_8_MONO        0xe107\n\n// call indexes for the loadable drivers\nenum\n{ \n   _DRV_INIT,\n   _DRV_UNINIT,\n   _DRV_SETRATE,\n   _DRV_SETACTION,\n   _DRV_START,\n   _DRV_STOP,\n   _DRV_PAUSE,\n   _DRV_RESUME,\n   _DRV_CAPABILITIES,\n   _DRV_PLAY_FOREGROUND,\n   _DRV_GET_FILL_INFO, \n   _DRV_GET_CALL_FUNCTIONS,\n   _DRV_SET_CALL_FUNCTIONS\n};\n\n// fill info\ntypedef  struct   _tagFillInfo\n         {\n\n            LPSTR lpFillHandler;                   // pointer to fill handler\n            LPWORD lpDMAFillCount;                 // pointer to dma count\n            LPSTR lpSampleList;                    // pointer to sample list\n            LPWORD lpDMAMasterVolume;              // pointer to dma count\n\n         } _SOS_FILL_INFO;\n\n// caps info structure\ntypedef  struct   _tagCapsInfo\n         {\n\n            LPSTR    lpPortList;                   // pointer to port list\n            LPSTR    lpDMAList;                    // pointer to DMA list\n            LPSTR    lpIRQList;                    // pointer to IRQ list\n            LPSTR    lpRateList;                   // pointer to rate list\n\n         } _SOS_CAPS_INFO;\n\n// maximum number of available voice\n#define  _MAX_VOICES    32\n\n// structure definition\ntypedef  struct   _tagSAMPLE\n{\n   LPSTR    samplePtr;                 // pointer to data buffer\n   LPSTR    sampleData;                // pointer to active data\n   LPSTR    sampleLoopPtr;             // pointer for loop back\n\n   WORD     sampleLength;              // length of sample\n   WORD     sampleIndex;               // index into sample\n   WORD     sampleLoopLength;          // length of loop\n   \n   WORD     sampleBytesLeft;           // bytes left to play in sample\n\n   WORD     sampleLoopPoint;           // byte count for loop point\n   WORD     sampleLoopEndLength;       // length of remaining chunk\n\n   short    sampleFlags;               // control sample\n   short    sampleVolume;              // volume control\n   short    sampleID;                  // sample ID\n\n   short    sampleChannel;             // channel to play sample on\n   short    sampleLoopCount;           // loop count\n   short    sampleLastFill;            // last fill position\n   VOID ( far cdecl * sampleCallback )( WORD, WORD, WORD ); // callback function for sample\n\n   WORD     samplePitchAdd;\n   short    samplePitchFraction;\n\n   short    samplePort;                // port to use for non-dma digitized\n\n   WORD     sampleTotalBytes;\n   WORD     sampleByteLength;\n\n   short    samplePanLocation;\n   short    samplePanSpeed;\n   short    samplePanDirection;\n   short    samplePanStart;\n   short    samplePanEnd;\n   \n   short    sampleDelayBytes;\n   short    sampleDelayRepeat;\n   \n   WORD     sampleADPCMPredicted;\n   short    sampleADPCMIndex;\n\n   short    sampleRootNoteMIDI;   \n\n   WORD  sampleTemp1;   \n   \n} _SOS_SAMPLE;\n\n// enumeration for left or right channel\nenum\n{\n   _LEFT_CHANNEL,\n   _RIGHT_CHANNEL,\n   _CENTER_CHANNEL,\n   _INTERLEAVED\n};\n\n// enumeration for foreground and background\nenum\n{ \n   _FOREGROUND,\n   _BACKGROUND \n};\n\n// defines for the sample flags\n#define  _ACTIVE           0x8000\n#define  _LOOPING          0x4000\n#define  _FIRST_TIME       0x2000\n#define  _PENDING_RELEASE  0x1000\n#define  _CONTINUE_BLOCK   0x0800\n#define  _PITCH_SHIFT      0x0400\n#define  _PANNING          0x0200\n#define  _VOLUME           0x0100\n#define  _TRANSLATE16TO8   0x0080\n#define  _STAGE_LOOP       0x0040\n#define  _TRANSLATE8TO16   0x0020\n#define  _STEREOTOMONO     0x0010\n\n// defines for the wParam flags \n#define  _SINGLE_SAMPLE 0x01\n\n#define  _SOS_DCAPS_AUTO_REINIT     0x01\n#define  _SOS_DCAPS_MPU_401         0x02\n#define  _SOS_DCAPS_OPL2            0x04\n#define  _SOS_DCAPS_OPL3            0x08\n#define  _SOS_DCAPS_OPL4            0x10\n#define  _SOS_DCAPS_WAVETABLE       0x20\n#define  _SOS_DCAPS_DL_SAMPLES      0x40\n#define  _SOS_DCAPS_FIFO_DEVICE     0x80\n#define  _SOS_DCAPS_ENV_NEEDED      0x100\n#define  _SOS_DCAPS_PSEUDO_DMA1     0x200\n#define  _SOS_DCAPS_SIGNED_DATA     0x8000\n\n// file header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // number of drivers in the file\n   WORD  wDrivers;\n\n   // offset of first driver\n   WORD  lOffset;\n\n   // size of the file\n   WORD  lFileSize;\n\n} _FILEHEADER;\n\n// driver header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // offset of next driver\n   WORD  lNextDriver;\n\n   // size of current driver\n   WORD  wSize;\n\n   // id for the current device\n   WORD  wDeviceID;\n\n   // id for the type of DOS extender\n   WORD  wExtenderType;\n\n} _DRIVERHEADER;\n\n// device hardware information\ntypedef struct\n{\n   // port to be used\n   WORD  wPort;\n\n   // irq to use\n   WORD  wIRQ;\n\n   // dma channel to se\n   WORD  wDMA; \n  \n   // extra parameter\n   WORD  wParam;\n\n} _SOS_HARDWARE;\n\n// structure definition for start sample\ntypedef struct\n{\n   // pointer to sample\n   LPSTR lpSamplePtr;\n\n   // size of the sample\n   WORD  dwSampleSize;\n\n   // number of times to loop the sample -1 is infinite\n   WORD  wLoopCount;\n\n   // channel to play sample on\n   WORD  wChannel;\n\n   // volume to play sample at\n   WORD wVolume;\n\n   // id for the sample\n   WORD  wSampleID;\n\n   // far pointer to the callback function\n   VOID ( far cdecl *lpCallback )( WORD, WORD, WORD );\n\n   // port to use if driver is a non-dma background driver\n   WORD  wSamplePort; \n\n   // flags field\n   WORD  wSampleFlags;\n\n   // total length of sample including loops, etc..\n   WORD     dwSampleByteLength;\n\n   // loop point for the sample\n   WORD  dwSampleLoopPoint;\n   WORD  dwSampleLoopLength;\n\n   // pitch shifting components \n   WORD     dwSamplePitchAdd;\n   WORD    wSamplePitchFraction;\n\n   // pan components\n   WORD    wSamplePanLocation;\n   WORD    wSamplePanSpeed;\n   WORD    wSamplePanDirection;\n   WORD    wSamplePanStart;\n   WORD    wSamplePanEnd;\n   \n   // delay parts\n   WORD    wSampleDelayBytes;\n   WORD    wSampleDelayRepeat;\n\n   // compression components   \n   WORD     dwSampleADPCMPredicted;\n   WORD    wSampleADPCMIndex;\n\n   // root note for pitch shifting \n   WORD    wSampleRootNoteMIDI;   \n\n   // filler for future upgrades\n   WORD  dwSampleTemp1;   \n   WORD  dwSampleTemp2;   \n   WORD  dwSampleTemp3;   \n\n} _SOS_START_SAMPLE;\n\n// structure for initializing a driver\ntypedef struct\n{  \n   WORD  wBufferSize;\n   LPSTR lpBuffer;\n   BOOL  wAllocateBuffer;\n   WORD  wSampleRate;\n   WORD  wParam;\n   LONG  dwParam;\n   VOID ( far *lpFillHandler )( VOID );\n   LPSTR lpDriverMemory;\n   LPSTR lpDriverMemoryCS;\n   LPSTR lpTimerMemory;\n   LPSTR lpTimerMemoryCS;\n   WORD  wTimerID;\n   WORD  wPhysical;\n\n} _SOS_INIT_DRIVER;\n\n// define for the timer types to use\n#define  _SOS_NORMAL_TIMER          0x00\n\n// enumeration for the timer types\nenum\n{\n   _TIMER_8_MONO   =     0x1000,\n   _TIMER_8_ST,          \n   _TIMER_16_MONO,       \n   _TIMER_16_ST,         \n   _TIMER_8_MONO_ULAW,  \n   _TIMER_8_ST_ULAW,    \n   _TIMER_16_MONO_ULAW, \n   _TIMER_16_ST_ULAW,   \n   _TIMER_8_MONO_REC,   \n   _TIMER_8_MONO_ULAW_REC,\n   _TIMER_UNDEFINED_1,      \n   _TIMER_UNDEFINED_2,\n   _TIMER_UNDEFINED_3,\n   _TIMER_UNDEFINED_4,\n   _TIMER_UNDEFINED_5,\n   _TIMER_UNDEFINED_6,\n   _TIMER_UNDEFINED_7,\n   _TIMER_UNDEFINED_8,\n   _TIMER_UNDEFINED_9,\n   _TIMER_UNDEFINED_A,\n   _TIMER_UNDEFINED_B,\n   _TIMER_UNDEFINED_C,\n   _TIMER_UNDEFINED_D,\n   _TIMER_UNDEFINED_E,\n   _TIMER_UNDEFINED_F,\n   _TIMER_UNDEFINED_10,\n   _TIMER_UNDEFINED_11,\n   _TIMER_UNDEFINED_12,\n   _TIMER_UNDEFINED_13,\n   _TIMER_UNDEFINED_14,\n   _TIMER_UNDEFINED_15,\n   _TIMER_UNDEFINED_16,\n   _TIMER_8_SOUND_SOURCE,\n   _TIMER_8_SOUND_SOURCE_TANDY,\n   _TIMER_8_GENERAL_PORT,\n   _TIMER_8_GENERAL_PORT_REC   \n};\n\n// define for no slots available\n#define  _ERR_NO_SLOTS ( WORD )-1\n\n// error codes for the system\nenum\n{\n   _ERR_NO_ERROR,\n   _ERR_DRIVER_NOT_LOADED,\n   _ERR_INVALID_POINTER,\n   _ERR_DETECT_INITIALIZED,\n   _ERR_FAIL_ON_FILE_OPEN,\n   _ERR_MEMORY_FAIL,\n   _ERR_INVALID_DRIVER_ID,\n   _ERR_NO_DRIVER_FOUND,\n   _ERR_DETECTION_FAILURE,\n   _ERR_DRIVER_LOADED,\n   _ERR_INVALID_HANDLE,\n   _ERR_NO_HANDLES,\n   _ERR_PAUSED,   \n   _ERR_NOT_PAUSED,\n   _ERR_INVALID_DATA,\n   _ERR_DRV_FILE_FAIL,\n   _ERR_INVALID_PORT,\n   _ERR_INVALID_IRQ,\n   _ERR_INVALID_DMA,\n   _ERR_INVALID_DMA_IRQ\n};   \n\n// maximum number of timer events that can be registered \n#define  _TIMER_MAX_EVENTS    0x10  \n\n// flags for the debugging system\n#define  _SOS_DEBUG_NORMAL       0x0000\n#define  _SOS_DEBUG_NO_TIMER     0x0001\n#define  _SOS_TIMER_DPMI         0x0002\n\n// define for types of DOS extenders\n#define  _SOS_RATIONAL           0x8000\n#define  _SOS_FLASHTECK          0x4000\n\n// defines for the types of timers for different\n// dos extenders\n#define  _SOS_TIMER_NEAR         0x8000\n#define  _SOS_TIMER_FAR          0x4000\n \n// values for callback information\nenum\n{\n   _SAMPLE_PROCESSED,\n   _SAMPLE_LOOPING,\n   _SAMPLE_DONE\n};\n\n// define for special 18.2 callback rate to dos\n#define  _TIMER_DOS_RATE   0xff00\n\n#pragma pack()\n\n#pragma aux int_3 = \"int 3\"\n \n#pragma pack( 1 ) \ntypedef struct\n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned       segment;\n\tunsigned short\tnumber_available;\n\tunsigned short number_used;\n\tunsigned       page0;\n\n} EVDS_STRUCT;\n\ntypedef struct \n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned short segment;\n\tunsigned short\tID;\n\tunsigned       physical;\n\n} VDS_STRUCT;\n\n#pragma pack() \n\n#include \"sosdata.h\"\n#include \"sosfnct.h\"\n\n#endif\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/SOSDATA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdata.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DATA\n#define  _SOS_DATA\n\n#include <stddef.h>\n\n#pragma pack(4) \nextern   WORD     _sosDIGIData_Start;\nextern   WORD     _sosDIGIData_End;\nextern   WORD     _wSOSDriverLinear[];\nextern   WORD     _wSOSTimerLinear[];\nextern   LPSTR    _lpSOSDriver[];\nextern   LPSTR    _lpSOSTimer[];\nextern   LPSTR    _lpSOSDriverCS[];\nextern   LPSTR    _lpSOSTimerCS[];\nextern   BOOL     _wSOSDriverLoaded[];\nextern   BOOL     _wSOSTimerLoaded[];\nextern   BOOL     _wSOSDriverInitialized[];\nextern   WORD     _wSOSOutputRate[];\nextern   WORD     _wSOSDMABuffersize[];\nextern   LONG     _dwSOSDMABufferPhysical[];\nextern   LPSTR    _lpSOSDMABuffer[];\nextern   BOOL     _wTimerUsed;\nextern   VOID ( far *_lpSOSFillHandler[] )( VOID );\nextern   WORD     _wSOSTimerType[];\nextern   WORD     _wSOSDriverType[];\nextern   _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ];\nextern   LPWORD      _lpSOSDMAIrqCount[];\nextern   LPWORD      _lpSOSDMAFillCount[];\nextern   WORD        _wSOSTmrNextCount;\nextern   VOID ( interrupt far *_lpSOSOldTimer )( VOID );\nextern   WORD     _wSOSDriverID[];\nextern   _SOS_CAPABILITIES _sSOSDriverCaps[];\nextern   WORD        _wSOSDMAPortList[];\nextern   BYTE        _bSOSDMAChannel[];\nextern   _SOS_INIT_DRIVER     _sSOSDIGIInitDriver[];\nextern   BYTE  _pSOSDriverPath[];\nextern   BYTE  _pSOSTempDriverPath[];\nextern   BOOL  _wTIMERUsed;\nextern   WORD  _wTIMERValue;\nextern   VOID ( far * _lpTIMEREvents[] )( VOID );\nextern   WORD _wTIMEREventRate[];\nextern   WORD _dwTIMEREventFraction[];\nextern   WORD _dwTIMEREventFractionCurrent[];\nextern   BYTE  _bSOSMIDITimerSongHandler[];\nextern   BYTE  _bSOSMIDISongHandle;\nextern   WORD  _wSOSTimerMemHandle[];\nextern   WORD  _wSOSDriverMemHandle[];\nextern   WORD  _wSOSRealSeg[];\n\nextern   _FILEHEADER    _sDETFileHeader;\nextern   _DRIVERHEADER  _sDETDriverHeader;\nextern   _FILEHEADER    sLOADFileHeader;\nextern   _DRIVERHEADER  sLOADDriverHeader;\nextern   BOOL           _wDETInitialized;\nextern   WORD           _wDETLinear;\nextern   LPSTR          _lpDETDriverBuffer;    \nextern   LPSTR          _lpDETDriverBufferCS;\nextern   WORD           _hDETFile;\nextern   DWORD          _dwDETDriverIndex;\nextern   WORD           _wDETDriverIndexCur;\nextern   WORD           _wDETMemHandle;\nextern   LPSOSDEVICECAPS _lpDETDeviceCaps;\nextern   _SOS_CAPABILITIES _sDETCaps;  \nextern   PSTR _pSOSErrorStrings[];\nextern   BOOL _wSOSBufferAllocated[];\nextern   BOOL _wSOSSystemInitialized;\nextern   VDS_STRUCT _sSOSVDSInfo;\nextern   _SOS_FILL_INFO _sSOSFillInfo;\nextern   WORD    _wSOSTimerEventIndex;\nextern   WORD  _wSOSTimerEntered;\nextern   WORD  _wSOSDriverSize[];\nextern   WORD  _wSOSTimerSize[];\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nextern   WORD  _sosDIGIData1_Start;\nextern   WORD  _sosDIGIData1_End;\nextern   WORD  _sosDIGIData2_Start;\nextern   WORD  _sosDIGIData2_End;\nextern   BYTE  _bTIMERInstalled;\nextern   BYTE  _bTIMERDPMI;\nextern   WORD  wDetectPort;\nextern   WORD  wDetectIRQ;\nextern   WORD  wDetectDMA;\nextern   WORD  wDetectParam;\n#ifdef __cplusplus\n}\n#endif \n\n#pragma pack()\n\n#endif\n\u001a\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/SOSDEFS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdefs.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n\n#ifndef  _SOSDEFS_DEFINED\n#define  _SOSDEFS_DEFINED\n\n#undef   _TRUE\n#undef   _FALSE\n#undef   _NULL\nenum  \n      { \n         _FALSE, \n         _TRUE \n      };\n\n#define  _NULL  0\n\n#ifndef  VOID\n#define  VOID           void\n#endif\ntypedef  int            BOOL;\ntypedef  unsigned int   UINT;\ntypedef  unsigned char  BYTE;\ntypedef  unsigned       WORD;\n#ifndef  LONG\ntypedef  signed long    LONG;\n#endif\ntypedef  unsigned long  DWORD;\n\ntypedef  BYTE  *        PBYTE;\ntypedef  char near *    PSTR;\ntypedef  WORD  *        PWORD;\ntypedef  LONG  *        PLONG;\ntypedef  VOID  *        PVOID;\n\ntypedef  BYTE  far   *  LPBYTE;\ntypedef  BYTE  far   *  LPSTR;\ntypedef  WORD  far   *  LPWORD;\ntypedef  LONG  far   *  LPLONG;\ntypedef  VOID  far   *  LPVOID;\n\ntypedef  BYTE  huge  *  HPBYTE;\ntypedef  BYTE  huge  *  HPSTR;\ntypedef  WORD  huge  *  HPWORD;\ntypedef  LONG  huge  *  HPLONG;\ntypedef  VOID  huge  *  HPVOID;\n\ntypedef  unsigned       HANDLE;\n\n#endif\n\u001a\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/SOSFNCT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosfnct.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_FUNCTIONS\n#define  _SOS_FUNCTIONS\n\n#pragma pack(4)\n\nWORD sosDIGILockMemory          (  VOID  );\nWORD sosDIGIUnLockMemory        (  VOID  );\nWORD sosDIGIInitSystem           (  LPSTR, WORD  );\nWORD sosDIGIUnInitSystem         (  VOID  );\nWORD sosDIGIInitDriver           (  WORD, _SOS_HARDWARE far *,\n                                    _SOS_INIT_DRIVER far *, WORD far *   );\nWORD sosDIGIUnInitDriver         (  WORD, BOOL, BOOL  );\nWORD sosDIGILoadDriver          (  WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD sosDIGIUnLoadDriver         (  WORD  );\nWORD sosDIGIGetDeviceCaps        (  WORD, LPSOSDEVICECAPS  );\n\n#ifdef PHARLAP\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#else\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#endif\n\nWORD sosDIGIStopSample           (  WORD, WORD  );\nWORD sosDIGISamplesPlaying       (  WORD  );\nBOOL sosDIGISampleDone           (  WORD, WORD  );\nBOOL sosDIGISampleFilling        (  WORD, WORD  );\nWORD sosDIGIStartSample          (  WORD, _SOS_START_SAMPLE far *  );\nWORD sosDIGIContinueSample       (  WORD, WORD, _SOS_START_SAMPLE far * );\n\n\nWORD  sosDIGIDetectInit          (  LPSTR  );\nWORD  sosDIGIDetectUnInit        (  VOID  );\nWORD  sosDIGIDetectFindHardware  (  WORD, _SOS_CAPABILITIES far *, WORD far * );\nWORD  sosDIGIDetectFindFirst     (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectFindNext      (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectGetSettings   (  _SOS_HARDWARE far *  );\nWORD  sosDIGIDetectGetCaps       (  WORD, _SOS_CAPABILITIES far *  );\nWORD  sosDIGIDetectVerifySettings(  _SOS_HARDWARE far *  );\nPSTR  sosGetErrorString          (  WORD  );\n\nWORD  sosDIGILoadTimer           (  WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD  sosDIGIUnLoadTimer         (  WORD  );\n\nWORD  sosTIMERRegisterEvent      ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle );\nWORD  sosTIMERInitSystem               (  WORD, WORD  );\nWORD  sosTIMERUnInitSystem             (  WORD  );\nWORD  sosTIMERSetRate                  (  WORD  );  \nWORD  sosTIMERRemoveEvent              (  WORD );\nWORD  sosTIMERAlterEventRate           (  WORD, WORD  );\nWORD  sosTIMERGetEventRate             (  WORD  );\nVOID far sosTIMEROldHandler            (  VOID  );\nVOID far sosTIMERHandler               (  VOID  );\n\n// functions in soscntl.c\nWORD  sosDIGISetSampleVolume     ( WORD, WORD, WORD );\nWORD  sosDIGIGetSampleVolume     ( WORD, WORD );\nWORD  sosDIGISetChannel          ( WORD, WORD, WORD );\nWORD  sosDIGIGetChannel          ( WORD, WORD );\nWORD  sosDIGIGetBytesProcessed   ( WORD, WORD );\nWORD  sosDIGIGetLoopCount        ( WORD, WORD );\nWORD  sosDIGISetPanLocation      ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanLocation      ( WORD, WORD );\nDWORD sosDIGISetPitch            ( WORD, WORD, DWORD );\nDWORD sosDIGIGetPitch            ( WORD, WORD );\nWORD  sosDIGIGetDMAPosition      ( WORD );\nWORD  sosDIGISetPanSpeed         ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanSpeed         ( WORD, WORD );\nWORD  sosDIGIGetSampleID         ( WORD, WORD );\nWORD  sosDIGIGetSampleHandle     ( WORD, WORD );\nWORD  sosDIGISetMasterVolume     ( WORD, WORD );\n#ifdef PHARLAP\nVOID  sosFreeVDSPage          ( unsigned short, unsigned short, DWORD );\nWORD  sosAllocVDSPage         ( unsigned short *, unsigned short *, DWORD * );\n#else\nWORD  sosAllocVDSPage            ( LPSTR *, WORD *, WORD * );\nVOID  sosFreeVDSPage             ( WORD, WORD, LONG );\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef PHARLAP\nextern   int   cdecl sosRealFree          ( int );\nextern   BOOL  cdecl  _sos_read( WORD, LPSTR, WORD, WORD * );\nextern   int   cdecl sosRealAlloc( int, int *, int * );\nextern   void  cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD );\nextern   int   cdecl sosGetCS( VOID );\nextern   int   cdecl sosGetES( VOID );\n#else\nextern   int   cdecl sosRealAlloc         ( int, int *, int * );\nextern   int   cdecl sosRealFree          ( int );\n#endif\n\n// sos driver functions\nextern   WORD  cdecl sosDRVLockMemory     ( DWORD, DWORD );\nextern   WORD  cdecl sosDRVUnLockMemory   ( DWORD, DWORD );\nextern   void  cdecl sosDRVGetCapsInfo    ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVGetCapsPtr     ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVInit           ( LPSTR, LPSTR, int, int, int, int, int, int );  \nextern   void  cdecl sosDRVStart          ( LPSTR, LPSTR, int, int );\nextern   void  cdecl sosDRVSetRate        ( LPSTR, LPSTR, int );\nextern   void  cdecl sosDRVSetAction      ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVStop           ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVUnInit         ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVGetFillInfo    ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * );\nextern   void  cdecl sosFillSampleStructs ( PSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVExist       ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVGetSettings ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR );\nextern   WORD  cdecl sosDIGIInitForWindows( WORD );\nextern   WORD  cdecl sosDIGIUnInitForWindows( WORD );\nextern   LPSTR cdecl sosAllocateFarMem      ( WORD, PSTR, WORD * );\nextern   LPSTR cdecl sosCreateAliasCS       ( LPSTR );\nextern   VOID  cdecl sosFreeSelector        ( LPSTR, DWORD );\nextern   LPSTR cdecl sosMAKEDOSPtr          ( PSTR );\nextern   VOID  cdecl sosDetDRVSetEnvString  ( DWORD, PSTR );\nextern   PSTR  cdecl sosDetDRVGetEnvString  ( DWORD );\nextern   VOID  cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR );\nextern   VOID  cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR );\nextern   WORD  cdecl sosDRVGetFreeMemory     ( VOID );\nextern   WORD  cdecl sosDRVAllocVDSStruct    ( WORD, WORD *, WORD * );\nextern   WORD  cdecl sosDRVFreeVDSStruct     ( WORD, WORD );\nextern   WORD  cdecl sosDRVIsWindowsActive   ( VOID );\nextern   WORD  cdecl sosDRVVDSGetBuffer    ( WORD );\nextern   WORD  cdecl sosDRVVDSFreeBuffer   ( WORD );\nextern   WORD  cdecl getDS( VOID );\nextern   WORD  cdecl sosDRVMakeDMASelector   ( WORD );  \nextern   WORD  cdecl sosDRVFreeDMASelector   ( WORD );  \n\n\nextern   void  cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) );\nextern   void  cdecl sosTIMERDRVUnInit( void );\nextern   void  cdecl sosTIMERDRVHandler( void );\nextern   void  cdecl sosTIMERDRVFHandler( void );\nextern   void  cdecl sosTIMERDRVEnable( void );\nextern   void  cdecl sosTIMERDRVDisable( void );\nextern   void  cdecl sosTIMERDRVCallOld( void );\nextern   void  cdecl sosTIMERDRVSetRate( WORD );    \nextern   void  cdecl sosDIGITimer_Start( void );\nextern   void  cdecl sosDIGITimer_End( void );\nextern   void  cdecl sosDIGIDrv_Start( void );\nextern   void  cdecl sosDIGIDrv_End( void );\n#ifdef __cplusplus\n}\n#endif \n\n// external functions for handling system initialization and \n// uninitialization\nWORD  sosEXDIGInitDriver               (  WORD, WORD, WORD, LPSTR,\n                                          _SOS_HARDWARE far *, WORD *  );\nWORD  sosEXDIGIUnInitDriver            (  VOID  );\n\nWORD  sosEXDETFindDriver               (  WORD, LPSTR, _SOS_HARDWARE far *,\n                                          _SOS_CAPABILITIES far *  );\n\n// memory locking prototypes\nVOID  sosDIGICaps_Start( VOID );\nVOID  sosDIGICaps_End( VOID );\nVOID  sosDIGIErr_Start( VOID );\nVOID  sosDIGIErr_End( VOID );\nVOID  sosDIGITmr_Start( VOID );\nVOID  sosDIGITmr_End( VOID );\nVOID  sosDIGIStart_Start( VOID );\nVOID  sosDIGIStart_End( VOID );\nVOID  sosDIGIPlyng_Start( VOID );\nVOID  sosDIGIPlyng_End( VOID );\nVOID  sosDIGIRate_Start( VOID );\nVOID  sosDIGIRate_End( VOID );\nVOID  sosDIGIDone_Start( VOID );\nVOID  sosDIGIDone_End( VOID );\nVOID  sosDIGIDetec_Start( VOID );\nVOID  sosDIGIDetec_End( VOID );\nVOID  sosDIGIInit_Start( VOID );\nVOID  sosDIGIInit_End( VOID );\nVOID  sosDIGILoad_Start( VOID );\nVOID  sosDIGILoad_End( VOID );\nVOID  sosDIGICntl_Start( VOID );\nVOID  sosDIGICntl_End( VOID );\n\n#pragma pack()\n\n#endif\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/SOSRES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosres.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#define  _SOS_RESOURCE\n#ifndef  _SOS_RESOURCE\n#define  _SOS_RESOURCE\n\n// structure for resource file header\ntypedef struct\n{\n   // file version\n   WORD     wVersion;\n\n   // file size\n   LONG     dwFileSize;\n\n   // number of resources in file\n   WORD     wResCount;\n\n   // offset of resource data from top of file\n   LONG     dwResOffset;\n\n   // offset of sync track from top of file\n   LONG     dwSyncTrackOffset;\n\n}  _RES_FILE_HEADER;\n\n// structure for resource block header\ntypedef struct\n{\n   // resource id\n   WORD     wID;\n\n   // resource type\n   WORD     wResType;\n\n   // offset of next block\n   LONG     dwNextBlock; \n\n   // size of the current resource information\n   LONG     dwResSize;\n\n   // rate to play block at\n   WORD     wBlockRate;\n\n   // id for the sync track to use\n   WORD     wSyncTrackID;\n\n}  _RES_BLOCK_HEADER;\n\n// structure for sync mark tag\ntypedef struct _tagSYNCMARK\n{\n   // ID of the type of mark being used\n   WORD  wID;\n\n   // location in data of sync mark\n   LONG  dwSyncOffset;\n\n   // length of sync block\n   LONG  dwSyncSize;\n\n   // start sample data\n   _SOS_START_SAMPLE sampleData;\n    \n} _RES_SYNCMARK;\n\ntypedef union\n{\n   // structure for sync mark tag\n   _RES_SYNCMARK  syncMark; \n\n} _RES_TAG;\n\n// union for filter information for prepareWave\ntypedef union\n{\n   // filter type\n   WORD     wFilterID;\n\n   // structure for volume\n   struct   volume \n   {\n      WORD  wVolume;\n   };\n\n   // structure for delay\n   struct   delay\n   {  \n      WORD  wDelaySamples;\n   };\n\n} _SOS_FILTER; \n\n \n#endif\n\n\u001a"
  },
  {
    "path": "WINVQ/VQA32/OLD/TASK.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     task.c\n*\n* DESCRIPTION\n*     Loading and drawing delegation\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 25, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_Alloc    - Allocate a VQAHandle to use.\n*     VQA_Free     - Free a VQAHandle.\n*     VQA_Init     - Initialize the VQAHandle IO.\n*     VQA_Play     - Play the VQA movie.\n*     VQA_SetStop  - Set the frame the player should stop on.\n*     VQA_GetInfo  - Get VQA movie information.\n*     VQA_GetStats - Get VQA movie statistics.\n*     VQA_Version  - Get VQA library version number.\n*     VQA_IDString - Get the VQA player library's ID string.\n*\n* PRIVATE\n*     VQA_IO_Task        - Loader task for multitasking.\n*     VQA_Rendering_Task - Drawer task for multitasking.\n*     User_Update        - Page flip routine called by the task interrupt.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <malloc.h>\n#include <dos.h>\n#include <mem.h>\n#include <conio.h>\n#include <sys\\timeb.h>\n#include <vqm32\\all.h>\n#include \"vqaplayp.h\"\n#include <vqm32\\font.h>\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n/* Externals */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern int __cdecl Check_Key(void);\nextern int __cdecl Get_Key(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Alloc - Allocate a VQAHandle to use.\n*\n* SYNOPSIS\n*     VQAHandle = VQA_Alloc()\n*\n*     VQAHandle *VQA_Alloc(void);\n*\n* FUNCTION\n*     Obtain a VQAHandle. This handle is used by most VQA library functions,\n*     and contains the current position in the file. This is the only legal\n*     way to obtain a VQAHandle.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     VQA - Handle of a VQA.\n*\n****************************************************************************/\n\nVQAHandle *VQA_Alloc(void)\n{\n\tVQAHandleP *vqa;\n\n\tif ((vqa = (VQAHandleP *)malloc(sizeof(VQAHandleP))) != NULL) {\n\t\tmemset(vqa, 0, sizeof(VQAHandleP));\n\t}\n\n\treturn ((VQAHandle *)vqa);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Free - Free a VQAHandle.\n*\n* SYNOPSIS\n*     VQA_Free(VQA)\n*\n*     void VQA_Free(VQAHandle *);\n*\n* FUNCTION\n*     Dispose of a VQAHandle. This is the only legal way to dispose of a\n*     VQAHandle.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle to dispose of.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Free(VQAHandle *vqa)\n{\n\tif (vqa) free(vqa);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Init - Initialize the VQAHandle IO handler.\n*\n* SYNOPSIS\n*     VQA_Init(VQA, IOHandler)\n*\n*     void VQA_Init(VQAHandle *, IOHandler *);\n*\n* FUNCTION\n*     Initialize the specified VQAHandle IO with the client provided custom\n*     IO handler.\n*\n* INPUTS\n*     VQA       - Pointer to VQAHandle to initialize.\n*     IOHandler - Pointer to custom file I/O handler function.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Init(VQAHandle *vqa, long(*iohandler)(VQAHandle *vqa, long action,\n\t\tvoid *buffer, long nbytes))\n{\n\t((VQAHandleP *)vqa)->IOHandler = iohandler;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Reset - Reset the VQAHandle.\n*\n* SYNOPSIS\n*     VQA_Reset(VQA)\n*\n*     void VQA_Reset(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - VQAHandle to reset.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Reset(VQAHandle *vqa)\n{\n\tVQAData *vqabuf;\n\n\t/* Dereference data members for quick access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\n\tvqabuf->Flags = 0;\n\tvqabuf->LoadedFrames = 0;\n\tvqabuf->DrawnFrames = 0;\n\tvqabuf->StartTime = 0;\n\tvqabuf->EndTime = 0;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Play - Play the VQA movie.\n*\n* SYNOPSIS\n*     Error = VQA_Play(VQA, Mode)\n*\n*     long VQA_Play(VQAHandle *, long);\n*\n* FUNCTION\n*     Playback the movie associated with the specified VQAHandle.\n*\n* INPUTS\n*     VQA  - Pointer to handle of movie to play.\n*     Mode - Playback mode.\n*              VQAMODE_RUN   - Run the movie until completion.\n*              VQAMODE_WALK  - Walk the movie frame by frame.\n*              VQAMODE_PAUSE - Pause the movie.\n*              VQAMODE_STOP  - Stop the movie (Shutdown).\n*\n* RESULT\n*     Error - 0 if successful, or error code.\n*\n****************************************************************************/\n\nlong VQA_Play(VQAHandle *vqa, long mode)\n{\n\tVQAData   *vqabuf;\n\tVQAConfig *config;\n\tVQADrawer *drawer;\n\tlong      rc;\n\tlong      i;\n\tlong      key;\n\n\t/* Dereference commonly used data members for quick access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* One time player priming. */\n\tif (!(vqabuf->Flags & VQADATF_PRIMED)) {\n\n\t\t/* Init the Drawer's configuration */\n\t\tVQA_Configure_Drawer((VQAHandleP *)vqa);\n\n\t\t/* If audio enabled & loaded, start playing */\n\t\t#if(VQAAUDIO_ON)\n\t\tif ((config->OptionFlags & VQAOPTF_AUDIO) && vqabuf->Audio.IsLoaded[0]) {\n\t\t\tVQA_StartAudio((VQAHandleP *)vqa);\n\t\t}\n\t\t#endif\n\n\t\t/* Initialize the timer */\n\t\ti = ((vqabuf->Drawer.CurFrame->FrameNum * VQA_TIMETICKS)\n\t\t\t\t/ config->DrawRate);\n\n\t\tVQA_SetTimer((VQAHandleP *)vqa, i, config->TimerMethod);\n\t\tvqabuf->StartTime = VQA_GetTime((VQAHandleP *)vqa);\n\n\t\t/* Set up the Mono screen */\n\t\t#if(VQAMONO_ON)\n\t\tif (config->OptionFlags & VQAOPTF_MONO) {\n\t\t\tVQA_InitMono((VQAHandleP *)vqa);\n\t\t}\n\t\t#endif\n\n\t\t/* Priming is complete. */\n\t\tvqabuf->Flags |= VQADATF_PRIMED;\n\t}\n\n\t/* Main Player Loop */\n\tswitch (mode) {\n\t\tcase VQAMODE_PAUSE:\n\t\t\tif ((vqabuf->Flags & VQADATF_PAUSED) == 0) {\n\t\t\t\tvqabuf->Flags |= VQADATF_PAUSED;\n\t\t\t\tvqabuf->EndTime = VQA_GetTime((VQAHandleP *)vqa);\n\n\t\t\t\t/* Stop the audio while the movie is paused. */\n\t\t\t\t#if(VQAAUDIO_ON)\n\t\t\t\tif (vqabuf->Audio.Flags & VQAAUDF_ISPLAYING) {\n\t\t\t\t\tVQA_StopAudio((VQAHandleP *)vqa);\n\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\trc = VQAERR_PAUSED;\n\t\t\tbreak;\n\n\t\tcase VQAMODE_RUN:\n\t\tcase VQAMODE_WALK:\n\t\tdefault:\n\n\t\t\t/* Start up the movie if is it currently paused. */\n\t\t\tif (vqabuf->Flags & VQADATF_PAUSED) {\n\t\t\t\tvqabuf->Flags &= ~VQADATF_PAUSED;\n\n\t\t\t\t/* Start the audio if it was previously on. */\n\t\t\t\t#if(VQAAUDIO_ON)\n\t\t\t\tif (config->OptionFlags & VQAOPTF_AUDIO) {\n\t\t\t\t\tVQA_StartAudio((VQAHandleP *)vqa);\n\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\tVQA_SetTimer((VQAHandleP *)vqa, vqabuf->EndTime, config->TimerMethod);\n\t\t\t}\n\n\t\t\t/* Load, Draw, Load, Draw, Load, Draw ... */\n\t\t\twhile ((vqabuf->Flags & (VQADATF_DDONE|VQADATF_LDONE))\n\t\t\t\t\t!= (VQADATF_DDONE|VQADATF_LDONE)) {\n\n\t\t\t\t/* Load a frame */\n\t\t\t\tif (!(vqabuf->Flags & VQADATF_LDONE)) {\n\t\t\t\t\tif ((rc = VQA_LoadFrame(vqa)) == 0) {\n\t\t\t\t\t\tvqabuf->LoadedFrames++;\n\t\t\t\t\t}\n\t\t\t\t\telse if ((rc != VQAERR_NOBUFFER) && (rc != VQAERR_SLEEPING)) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LDONE;\n\t\t\t\t\t\trc = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* Draw a frame */\n\t\t\t\tif ((config->DrawFlags & VQACFGF_NODRAW) == 0) {\n\t\t\t\t\tif ((rc = (*(vqabuf->Draw_Frame))(vqa)) == 0) {\n\t\t\t\t\t\tvqabuf->DrawnFrames++;\n\t\t\t\t\t\trc = vqabuf->Drawer.LastFrameNum;\n\n\t\t\t\t\t\tif (User_Update(vqa)) {\n\t\t\t\t\t\t\tvqabuf->Flags |= (VQADATF_DDONE|VQADATF_LDONE);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if ((vqabuf->Flags & VQADATF_LDONE)\n\t\t\t\t\t\t\t&& (rc == VQAERR_NOBUFFER)) {\n\t\t\t\t\t\tvqabuf->Flags |= VQADATF_DDONE;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tvqabuf->Flags |= VQADATF_DDONE;\n\t\t\t\t\tdrawer->CurFrame->Flags = 0L;\n\t\t\t\t\tdrawer->CurFrame = drawer->CurFrame->Next;\n\t\t\t\t}\n\n\t\t\t\t/* Update Mono output */\n\t\t\t\t#if(VQAMONO_ON)\n\t\t\t\tif (config->OptionFlags & VQAOPTF_MONO) {\n\t\t\t\t\tVQA_UpdateMono((VQAHandleP *)vqa);\n\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\tif (mode == VQAMODE_WALK) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t#if(VQASTANDALONE)\n\t\t\t\telse {\n\n\t\t\t\t\t/* Do single-stepping check. */\n\t\t\t\t\tif (config->OptionFlags & VQAOPTF_STEP) {\n\t\t\t\t\t\twhile ((key = Check_Key()) == 0);\n\t\t\t\t\t\tGet_Key();\n\n\t\t\t\t\t\t/* Escape key still quits. */\n\t\t\t\t\t\tif (key == 27) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Check for ESC */\n\t\t\t\t\tif ((key = Check_Key()) != 0) {\n\t\t\t\t\t\tmode = VQAMODE_STOP;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n\t/* If the movie is finished or we are requested to stop then shutdown. */\n\tif (((vqabuf->Flags & (VQADATF_DDONE|VQADATF_LDONE))\n\t\t\t== (VQADATF_DDONE|VQADATF_LDONE)) || (mode == VQAMODE_STOP)) {\n\n\t\t/* Record the end time; must be done before stopping audio, since we're\n\t\t * getting the elapsed time from the audio DMA position.\n\t\t */\n\t\tvqabuf->EndTime = VQA_GetTime((VQAHandleP *)vqa);\n\n\t\t/* Stop audio, if it's playing. */\n\t\t#if(VQAAUDIO_ON)\n\t\tif (vqabuf->Audio.Flags & VQAAUDF_ISPLAYING) {\n\t\t\tVQA_StopAudio((VQAHandleP *)vqa);\n\t\t}\n\t\t#endif\n\n\t\t/* Movie is finished. */\n\t\trc = VQAERR_EOF;\n\t}\n\n\treturn (rc);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_SetStop - Set the frame the player should stop on.\n*\n* SYNOPSIS\n*     OldStop = VQA_SetStop(VQA, Frame)\n*\n*     long = VQA_SetStop(VQAHandle *, long);\n*\n* FUNCTION\n*     Set the frame that the player should stop on. This function will only\n*     work on movies that are already open.\n*\n* INPUTS\n*     VQA   - VQAHandle of movie to set the stop frame for.\n*     Frame - Frame number to stop on.\n*\n* RESULT\n*     OldStop - Previous stop frame. (-1 = invalid stop frame)\n*\n****************************************************************************/\n\nlong VQA_SetStop(VQAHandle *vqa, long stop)\n{\n\tlong      oldstop = -1;\n\tVQAHeader *header;\n\n\t/* Get a local pointer to the header. */\n\theader = &((VQAHandleP *)vqa)->Header;\n\n\tif ((stop > 0) && (header->Frames >= stop)) {\n\t\toldstop = header->Frames;\n\t\theader->Frames = stop;\n\t}\n\n\treturn (oldstop);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_GetInfo - Get VQA movie information.\n*\n* SYNOPSIS\n*     VQA_GetInfo(VQA, Info)\n*\n*     void VQA_GetInfo(VQAHandle *, VQAInfo *);\n*\n* FUNCTION\n*     Retrieve information about the opened movie.\n*\n* INPUTS\n*     VQA  - Pointer to VQAHandle of opened movie.\n*     Info - Pointer to VQAInfo structure to fill.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_GetInfo(VQAHandle *vqa, VQAInfo *info)\n{\n\tVQAHeader *header;\n\n\t/* Dereference header structure. */\n\theader = &((VQAHandleP *)vqa)->Header;\n\n\tinfo->NumFrames = header->Frames;\n\tinfo->ImageHeight = header->ImageHeight;\n\tinfo->ImageWidth = header->ImageWidth;\n\tinfo->ImageBuf = ((VQAHandleP *)vqa)->VQABuf->Drawer.ImageBuf;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_GetStats - Get VQA movie statistics.\n*\n* SYNOPSIS\n*     VQA_GetStats(VQA, Stats)\n*\n*     void VQA_GetStats(VQAHandle *, VQAStatistics *);\n*\n* FUNCTION\n*     Retrieve the statistics for the VQA movie.\n*\n* INPUTS\n*     VQA   - Handle of VQA movie to get statistics for.\n*     Stats - Pointer to VQAStatistics to fill.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_GetStats(VQAHandle *vqa, VQAStatistics *stats)\n{\n\tVQAData *vqabuf;\n\n\t/* Dereference VQAData structure from VQAHandle */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\n\tstats->MemUsed = vqabuf->MemUsed;\n\tstats->StartTime = vqabuf->StartTime;\n\tstats->EndTime = vqabuf->EndTime;\n\tstats->FramesLoaded = vqabuf->LoadedFrames;\n\tstats->FramesDrawn = vqabuf->DrawnFrames;\n\tstats->FramesSkipped = vqabuf->Drawer.NumSkipped;\n\tstats->MaxFrameSize = vqabuf->Loader.MaxFrameSize;\n\n\t#if(VQAAUDIO_ON)\n\tstats->SamplesPlayed = vqabuf->Audio.SamplesPlayed;\n\t#else\n\tstats->SamplesPlayed = 0;\n\t#endif\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Version - Get VQA library version number.\n*\n* SYNOPSIS\n*     Version = VQA_Version()\n*\n*     char *VQA_Version(void);\n*\n* FUNCTION\n*     Return the version of the VQA player library.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Version - Pointer to version number string.\n*\n****************************************************************************/\n\nchar *VQA_Version(void)\n{\n\treturn(VQA_VERSION);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_IDString - Get the VQA player library's ID string.\n*\n* SYNOPSIS\n*     IDString = VQA_IDString()\n*\n*     char *VQA_IDString(void);\n*\n* FUNCTION\n*     Return the ID string of this VQA player library.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     IDString - Pointer to ID string.\n*\n****************************************************************************/\n\nchar *VQA_IDString(void)\n{\n\treturn (VQA_IDSTRING);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     User_Update - Page flip routine called by the task interrupt.\n*\n* SYNOPSIS\n*     User_Update(VQA)\n*\n*     long User_Update(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Handle of VQA movie.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nlong User_Update(VQAHandle *vqa)\n{\n\tVQAData *vqabuf;\n\tlong    rc = 0;\n\n\t/* Dereference data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\n\t\t/* Invoke the page flip routine */\n\t\trc = (*(vqabuf->Page_Flip))(vqa);\n\n\t\t/* Update data for mono output */\n\t\tvqabuf->Flipper.LastFrameNum = vqabuf->Flipper.CurFrame->FrameNum;\n\n\t\t/* Mark the frame as loadable */\n\t\tvqabuf->Flipper.CurFrame->Flags = 0L;\n\t\tvqabuf->Flags &= (~VQADATF_UPDATE);\n\t}\n\n\treturn (rc);\n}\n\nvoid VQA_Dummy(void)\n{\n\tSet_Font(NULL);\n}\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/TASM32.CFG",
    "content": "/t\n/m\n/w+\n/jJUMPS\n/ml\n/p\n/z\n/iC:\\PROJECTS\\INCLUDE\\VQM32\n/zi\n/dPHARLAP_TNT=1\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/TLIB.CFG",
    "content": "/C /E\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/TLINK32.CFG",
    "content": "/c\n/m\n/Gm\n-LC:\\PROJECTS\\LIB;C:\\DEV\\BC4\\LIB\n-v\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/UNVQ.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAUNVQ_H\n#define VQAUNVQ_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQAPlay32 library. (32-Bit protected mode)\n*\n* FILE\n*     unvq.h\n*\n* DESCRIPTION\n*     VQ frame decompress definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Feburary 8, 1995\n*\n****************************************************************************/\n\n#ifdef PHARLAP_TNT\n#include <pltypes.h>\n#endif\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* unvqbuff.asm */\n#ifndef PHARLAP_TNT\nvoid cdecl UnVQ_2x2(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\nvoid cdecl UnVQ_2x3(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\nvoid cdecl UnVQ_4x2(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\nvoid cdecl UnVQ_4x4(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\nvoid cdecl UnVQ_4x2_Woofer(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\n/* unvqvesa.asm */\nvoid cdecl UnVQ_4x2_VESA320_32K(unsigned char *codebook,\n\t\tunsigned char *pointers, unsigned char *palette,\n\t\tunsigned long grains_per_win,unsigned long dummy1,unsigned long dummy2);\n\n#else /* PHARLAP_TNT */\n\nvoid cdecl UnVQ_2x2(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n\nvoid cdecl UnVQ_2x3(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n\nvoid cdecl UnVQ_4x2(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n\nvoid cdecl UnVQ_4x4(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n\n/* unvqvesa.asm */\nvoid cdecl UnVQ_4x2_VESA320_32K(unsigned char *codebook,\n\t\tunsigned char *pointers, FARPTR palette, unsigned long grains_per_win,\n\t\tunsigned long dummy1, unsigned long dummy2);\n\n#endif /* PHARLAP_TNT */\n\n/* unvqxmde.asm */\nvoid cdecl UnVQ_4x2_Xmode(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long dummy);\n\nvoid cdecl UnVQ_4x2_XmodeCB(unsigned char *cbdummy, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long dummy);\n\nvoid cdecl Upload_4x2CB(unsigned char *codebook, unsigned long numentries);\nvoid cdecl XlatePointers(unsigned char *pointers, unsigned long numpointers);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQAUNVQ_H */\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/UNVQBUFF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PROJECT\n;*     VQAPlay library.\n;*\n;* FILE\n;*     UnVQBuff.asm\n;*\n;* DESCRIPTION\n;*     Buffered VQ decompress/draw routines.\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     Feburary 8, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     UnVQ_2x2 - Draw 2x2 block VQ frame to a buffer.\n;*     UnVQ_2x3 - Draw 2x3 block VQ frame to a buffer.\n;*     UnVQ_4x2 - Draw 4x2 block VQ frame to a buffer.\n;*     UnVQ_4x4 - Draw 4x4 block VQ frame to a buffer.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"vga.i\"\n\tINCLUDE\t\"vesavid.i\"\n\tINCLUDE\t\"vqaplay.i\"\n\tCODESEG\n\nSKIP_PTR\tEQU\t8000h\n\n\n\tIF\tVQABLOCK_2X2\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_2x2 - Draw 2x2 block VQ frame to a buffer.\n;*\n;* SYNOPSIS\n;*     UnVQ_2x2(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n;*\n;*     void UnVQ_2x2(unsigned char *, unsigned char *, unsigned char *,\n;*                        unsigned short, unsigned short, unsigned short);\n;*\n;* FUNCTION\n;*     This function draws an image into the specified buffer from the\n;*     pointers and codebook provided. This routine has been optimized for\n;*     a 320x200 image.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook used to draw image.\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to buffer to draw image into.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*     BufWidth - Width of destination buffer in pixels.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC UnVQ_2x2:NEAR\n\tPROC\tUnVQ_2x2 C NEAR USES ebx ecx edx esi edi\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tARG\tbuffer:NEAR PTR\n\tENDIF\n\n\tARG\tblocksperrow:DWORD\n\tARG\tnumrows:DWORD\n\tARG\tbufwidth:DWORD\n\n\tLOCAL\tdata_end:DWORD\n\tLOCAL\tcb_offset:DWORD\n\tLOCAL\tedi_startval:DWORD\n\tLOCAL\trowoffset:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tmov\teax,[codebook]\t\t;Adjust the codebook address so\n\tsub\teax,4\t\t; that the pointer offsets will\n\tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n\tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n\tshl\teax,1\t\t; row of blocks.\n\tmov\t[rowoffset],eax\n\n\tmov\tesi,[pointers]\n\tmov\teax,[numrows]\t\t;Compute the end address of the\n\tmul\t[blocksperrow]\t\t; pointer data.\n\tshl\teax,1\n\tadd\teax,esi\n\tmov\t[data_end],eax\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tmov\tedi,[buffer]\n\tENDIF\n\n\tmov\t[edi_startval],edi\n\n;----------------------------------------------------------------------------\n;\tDrawing loop\n;----------------------------------------------------------------------------\n\n??Start_row:\n\tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n??Not_finished_a_line:\n\tsub\tebx,ebx\n\tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n\tadd\tesi,2\t\t; then advance to the next one.\n\n\tor\tbx,bx\t\t;Is it a one color block?\n\tjs\tshort ??One_color\n\n;\tDraw multi-color block\n\n\tadd\tebx,[cb_offset]\t;Codeword address\n\tmov\teax,[ebx]\t\t;Read codeword\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],ax\t\t;Write 1st row to dest\n\tELSE\n\tmov\t[edi],ax\t\t;Write 1st row to dest\n\tENDIF\n\n\tshr\teax,16\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],ax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi+ebx],ax\t\t;Write 2nd row to dest\n\tENDIF\n\n\n\tadd\tedi,2\t\t;Next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n;\tDraw 1-color block\n\n??One_color:\n\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n\tjne\t??Draw_One_Color\n\n\tadd\tedi,2\t\t;Move to next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Next_row\n\n??Draw_One_Color:\n\tnot\tbx\t\t;NOT pointer value to get color\n\tmov\tbh,bl\t\t;Duplicate color through the\n\tmov\tax,bx\t\t; entire dword register.\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],ax\t\t;Write 1st row to dest\n\tmov\t[es:edi+ebx],ax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi],ax\t\t;Write 1st row to dest\n\tmov\t[edi+ebx],ax\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tedi,2\t\t;Next dest block positionw\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n??Next_row:\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n??End_of_data:\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\n\tENDP\tUnVQ_2x2\n\tENDIF\t;VQABLOCK_2X2\n\n\n\tIF\tVQABLOCK_2X3\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_2x3 - Draw 2x3 block VQ frame to a buffer.\n;*\n;* SYNOPSIS\n;*     UnVQ_2x3(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n;*\n;*     void UnVQ_2x3(unsigned char *, unsigned char *, unsigned char *,\n;*                        unsigned short, unsigned short, unsigned short);\n;*\n;* FUNCTION\n;*     This function draws an image into the specified buffer from the\n;*     pointers and codebook provided. This routine has been optimized for\n;*     a 320x200 image.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook used to draw image.\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to buffer to draw image into.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*     BufWidth - Width of destination buffer in pixels.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC UnVQ_2x3:NEAR\n\tPROC\tUnVQ_2x3 C NEAR USES ebx ecx edx esi edi\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tARG\tbuffer:NEAR PTR\n\tENDIF\n\n\tARG\tblocksperrow:DWORD\n\tARG\tnumrows:DWORD\n\tARG\tbufwidth:DWORD\n\n\tLOCAL\tdata_end:DWORD\n\tLOCAL\tcb_offset:DWORD\n\tLOCAL\tedi_startval:DWORD\n\tLOCAL\trowoffset:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tmov\teax,[codebook]\t\t;Adjust the codebook address so\n\tsub\teax,4\t\t; that the pointer offsets will\n\tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n\tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n\tshl\teax,1\t\t; row of blocks.\n\tadd\teax,[bufwidth]\n\tmov\t[rowoffset],eax\n\n\tmov\tesi,[pointers]\n\tmov\teax,[numrows]\t\t;Compute the end address of the\n\tmul\t[blocksperrow]\t\t; pointer data.\n\tshl\teax,1\n\tadd\teax,esi\n\tmov\t[data_end],eax\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tmov\tedi,[buffer]\n\tENDIF\n\n\tmov\t[edi_startval],edi\n\n;----------------------------------------------------------------------------\n;\tDrawing loop\n;----------------------------------------------------------------------------\n\n??Start_row:\n\tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n??Not_finished_a_line:\n\tsub\tebx,ebx\n\tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n\tadd\tesi,2\t\t; then advance to the next one.\n\n\tor\tbx,bx\t\t;Is it a one color block?\n\tjs\tshort ??One_color\n\n;\tDraw multi-color block\n\n\tadd\tebx,[cb_offset]\t;Codeword address\n\tmov\teax,[ebx]\t\t;Read 1st row of codeword\n\tmov\tdx,[ebx+4]\t\t;Read 2nd row of codeword\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],ax\t\t;Write 1st row to dest\n\tELSE\n\tmov\t[edi],ax\t\t;Write 1st row to dest\n\tENDIF\n\n\tshr\teax,16\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],ax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi+ebx],ax\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],dx\n\tELSE\n\tmov\t[edi+ebx],dx\n\tENDIF\n\n\tadd\tedi,2\t\t;Next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n;\tDraw 1-color block\n\n??One_color:\n\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n\tjne\t??Draw_One_Color\n\n\tadd\tedi,2\t\t;Move to next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Next_row\n\n??Draw_One_Color:\n\tnot\tbx\t\t;NOT pointer value to get color\n\tmov\tbh,bl\t\t;Duplicate color through the\n\tmov\tax,bx\t\t; entire dword register.\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],ax\t\t;Write 1st row to dest\n\tmov\t[es:edi+ebx],ax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi],ax\t\t;Write 1st row to dest\n\tmov\t[edi+ebx],ax\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],ax\t;Write 2rd row to dest\n\tELSE\n\tmov\t[edi+ebx],ax\t\t;Write 2rd row to dest\n\tENDIF\n\n\tadd\tedi,2\t\t;Next dest block positionw\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n??Next_row:\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n??End_of_data:\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\n\tENDP\tUnVQ_2x3\n\tENDIF\t;VQABLOCK_2X3\n\n\n\tIF\tVQABLOCK_4X2\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x2 - Draw 4x2 block VQ frame to a buffer.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x2(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n;*\n;*     void UnVQ_4x2(unsigned char *, unsigned char *, unsigned char *,\n;*                        long, long, long);\n;*\n;* FUNCTION\n;*     This function draws an image into the specified buffer from the\n;*     pointers and codebook provided. This routine has been optimized for\n;*     a 320x200 image.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook used to draw image.\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to buffer to draw image into.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*     BufWidth - Width of destination buffer in pixels.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n;;;\tGLOBAL\tC UnVQ_4x2:NEAR\n;;;\tPROC\tUnVQ_4x2 C NEAR USES ebx ecx edx esi edi\n;;;\n;;;\tARG\tcodebook:NEAR PTR\n;;;\tARG\tpointers:NEAR PTR\n;;;\n;;;\tIF\tPHARLAP_TNT\n;;;\tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n;;;\tELSE\n;;;\tARG\tbuffer:NEAR PTR\n;;;\tENDIF\n;;;\n;;;\tARG\tblocksperrow:DWORD\n;;;\tARG\tnumrows:DWORD\n;;;\tARG\tbufwidth:DWORD\n;;;\n;;;\tLOCAL\tdata_end:DWORD\n;;;\tLOCAL\tcb_offset:DWORD\n;;;\tLOCAL\tedi_startval:DWORD\n;;;\tLOCAL\trowoffset:DWORD\n;;;\n;;;;----------------------------------------------------------------------------\n;;;;\tInitialize\n;;;;----------------------------------------------------------------------------\n;;;\n;;;\tmov\teax,[codebook]\t\t;Adjust the codebook address so\n;;;\tsub\teax,4\t\t; that the pointer offsets will\n;;;\tmov\t[cb_offset],eax\t; point directly at the codeword.\n;;;\n;;;\tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n;;;\tshl\teax,1\t\t; row of blocks.\n;;;\tmov\t[rowoffset],eax\n;;;\n;;;\tmov\tesi,[pointers]\n;;;\tmov\teax,[numrows]\t\t;Compute the end address of the\n;;;\tmul\t[blocksperrow]\t\t; pointer data.\n;;;\tshl\teax,1\n;;;\tadd\teax,esi\n;;;\tmov\t[data_end],eax\n;;;\n;;;\tIF\tPHARLAP_TNT\n;;;\tpush\tes\n;;;\tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n;;;\tELSE\n;;;\tmov\tedi,[buffer]\n;;;\tENDIF\n;;;\n;;;\tmov\t[edi_startval],edi\n;;;\n;;;;----------------------------------------------------------------------------\n;;;;\tDrawing loop\n;;;;----------------------------------------------------------------------------\n;;;\n;;;??Start_row:\n;;;\tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n;;;\n;;;??Not_finished_a_line:\n;;;\tsub\tebx,ebx\n;;;\tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n;;;\tadd\tesi,2\t\t; then advance to the next one.\n;;;\n;;;\tor\tbx,bx\t\t;Is it a one color block?\n;;;\tjs\tshort ??One_color\n;;;\n;;;;\tDraw multi-color block\n;;;\n;;;\tadd\tebx,[cb_offset]\t;Codeword address\n;;;\tmov\teax,[ebx]\t\t;Read 1st row of codeword\n;;;\tmov\tedx,[ebx+4]\t\t;Read 2nd row of codeword\n;;;\tmov\tebx,[bufwidth]\n;;;\n;;;\tIF\tPHARLAP_TNT\n;;;\tmov\t[es:edi],eax\t\t;Write 1st row to dest\n;;;\tmov\t[es:edi+ebx],edx\t;Write 2nd row to dest\n;;;\tELSE\n;;;\tmov\t[edi],eax\t\t;Write 1st row to dest\n;;;\tmov\t[edi+ebx],edx\t\t;Write 2nd row to dest\n;;;\tENDIF\n;;;\n;;;\tadd\tedi,4\t\t;Next dest block position\n;;;\tdec\tecx\t\t;More blocks for this row?\n;;;\tjnz\tshort ??Not_finished_a_line\n;;;\n;;;;\tAdvance to the next destination row of blocks.\n;;;\n;;;\tmov\tedi,[edi_startval]\n;;;\tadd\tedi,[rowoffset]\n;;;\tmov\t[edi_startval],edi\n;;;\n;;;\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n;;;\tjnb\tshort ??End_of_data\t; pointers buffer?\n;;;\tjmp\t??Start_row\n;;;\n;;;;\tDraw 1-color block\n;;;\n;;;??One_color:\n;;;\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n;;;\tjne\t??Draw_One_Color\n;;;\n;;;\tadd\tedi,4\t\t;Move to next dest block position\n;;;\tdec\tecx\t\t;More blocks for this row?\n;;;\tjnz\tshort ??Not_finished_a_line\n;;;\tjmp\t??Next_row\n;;;\n;;;??Draw_One_Color:\n;;;\tnot\tbx\t\t;NOT pointer value to get color\n;;;\tmov\tbh,bl\t\t;Duplicate color through the\n;;;\tmov\tax,bx\t\t; entire dword register.\n;;;\trol\teax,16\n;;;\tmov\tax,bx\n;;;\tmov\tebx,[bufwidth]\n;;;\n;;;\tIF\tPHARLAP_TNT\n;;;\tmov\t[es:edi],eax\t\t;Write 1st row to dest\n;;;\tmov\t[es:edi+ebx],eax\t;Write 2nd row to dest\n;;;\tELSE\n;;;\tmov\t[edi],eax\t\t;Write 1st row to dest\n;;;\tmov\t[edi+ebx],eax\t\t;Write 2nd row to dest\n;;;\tENDIF\n;;;\n;;;\tadd\tedi,4\t\t;Next dest block positionw\n;;;\tdec\tecx\t\t;More blocks for this row?\n;;;\tjnz\tshort ??Not_finished_a_line\n;;;\n;;;;\tAdvance to the next destination row of blocks.\n;;;\n;;;??Next_row:\n;;;\tmov\tedi,[edi_startval]\n;;;\tadd\tedi,[rowoffset]\n;;;\tmov\t[edi_startval],edi\n;;;\n;;;\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n;;;\tjnb\tshort ??End_of_data\t; pointers buffer?\n;;;\tjmp\t??Start_row\n;;;\n;;;??End_of_data:\n;;;\tIF\tPHARLAP_TNT\n;;;\tpop\tes\n;;;\tENDIF\n;;;\n;;;\tret\n;;;\n;;;\tENDP\tUnVQ_4x2\n;;;\tENDIF\t;VQABLOCK_4X2\n\n\tGLOBAL\tC UnVQ_4x2:NEAR\n\tPROC\tUnVQ_4x2 C NEAR USES ebx ecx edx esi edi\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\tARG\tbuffer:NEAR PTR\n\tARG\tblocksperrow:DWORD\n\tARG\tnumrows:DWORD\n\tARG\tbufwidth:DWORD\n\n\tLOCAL\tdata_end:DWORD\n\tLOCAL\tcb_offset:DWORD\n\tLOCAL\tedi_startval:DWORD\n\tLOCAL\trowoffset:DWORD\n\tLOCAL\tentries:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tmov\teax,[codebook]\t\t;Adjust the codebook address so\n;\tsub\teax,4\t\t; that the pointer offsets will\n\tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n\tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n\tshl\teax,1\t\t; row of blocks.\n\tmov\t[rowoffset],eax\n\n\tmov\tesi,[pointers]\n\tmov\teax,[numrows]\t\t;Compute the end address of the\n\tmul\t[blocksperrow]\t\t; pointer data.\n\tmov\t[entries],eax\n\tadd\teax,esi\n\tmov\t[data_end],eax\n\n\tmov\tedi,[buffer]\n\tmov\t[edi_startval],edi\n\n;----------------------------------------------------------------------------\n;\tDrawing loop\n;----------------------------------------------------------------------------\n\n??Start_row:\n\tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n??Not_finished_a_line:\n\tmov\teax,[entries]\n\txor\tebx,ebx\n\tmov\tbl,[esi]\n\tmov\tbh,[esi + eax]\t;Get the codebook pointer value\n\tinc\tesi\t\t; then advance to the next one.\n\n\tcmp\tbh,00Fh\t\t;Is it a one color block?\n\tje\tshort ??One_color\n\n;\tDraw multi-color block\n\n\tshl\tebx,3\n\tadd\tebx,[cb_offset]\t;Codeword address\n\tmov\teax,[ebx]\t\t;Read 1st row of codeword\n\tmov\tedx,[ebx+4]\t\t;Read 2nd row of codeword\n\tmov\tebx,[bufwidth]\n\tmov\t[edi],eax\t\t;Write 1st row to dest\n\tmov\t[edi+ebx],edx\t\t;Write 2nd row to dest\n\n\tadd\tedi,4\t\t;Next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n;\tDraw 1-color block\n\n??One_color:\n;\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n;\tjne\t??Draw_One_Color\n;\n;\tadd\tedi,4\t\t;Move to next dest block position\n;\tdec\tecx\t\t;More blocks for this row?\n;\tjnz\tshort ??Not_finished_a_line\n;\tjmp\t??Next_row\n\n??Draw_One_Color:\n;\tnot\tbx\t\t;NOT pointer value to get color\n\tmov\tbh,bl\t\t;Duplicate color through the\n\tmov\tax,bx\t\t; entire dword register.\n\trol\teax,16\n\tmov\tax,bx\n\tmov\tebx,[bufwidth]\n\tmov\t[edi],eax\t\t;Write 1st row to dest\n\tmov\t[edi+ebx],eax\t\t;Write 2nd row to dest\n\n\tadd\tedi,4\t\t;Next dest block positionw\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n??Next_row:\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n??End_of_data:\n\tret\n\n\tENDP\tUnVQ_4x2\n\tENDIF\t;VQABLOCK_4X2\n\n\n\tIF\tVQABLOCK_4X4\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x4 - Draw 4x4 block VQ frame to a buffer.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x4(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n;*\n;*     void UnVQ_4x4(unsigned char *, unsigned char *, unsigned char *,\n;*                        unsigned short, unsigned short, unsigned short);\n;*\n;* FUNCTION\n;*     This function draws an image into the specified buffer from the\n;*     pointers and codebook provided. This routine has been optimized for\n;*     a 320x200 image.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook used to draw image.\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to buffer to draw image into.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*     BufWidth - Width of destination buffer in pixels.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC UnVQ_4x4:NEAR\n\tPROC\tUnVQ_4x4 C NEAR USES ebx ecx edx esi edi\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tARG\tbuffer:NEAR PTR\n\tENDIF\n\n   \tARG\tblocksperrow:DWORD\n   \tARG\tnumrows:DWORD\n   \tARG\tbufwidth:DWORD\n\n   \tLOCAL\tdata_end:DWORD\n   \tLOCAL\tcb_offset:DWORD\n      \tLOCAL\tedi_startval:DWORD\n      \tLOCAL\trowoffset:DWORD\n\n      ;----------------------------------------------------------------------------\n      ;\tInitialize\n      ;----------------------------------------------------------------------------\n\n      \tmov\teax,[codebook]\t\t;Adjust the codebook address so\n      \tsub\teax,4\t\t; that the pointer offsets will\n      \tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n      \tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n      \tshl\teax,2\t\t; row of blocks\n      \tmov\t[rowoffset],eax\n\n      \tmov\tesi,[pointers]\n      \tmov\teax,[numrows]\t\t;Compute the end address of the\n      \tmul\t[blocksperrow]\t\t; pointer data.\n      \tshl\teax,1\n      \tadd\teax,esi\n      \tmov\t[data_end],eax\n\n      \tIF\tPHARLAP_TNT\n      \tpush\tes\n      \tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n      \tELSE\n      \tmov\tedi,[buffer]\n      \tENDIF\n\n      \tmov\t[edi_startval],edi\n\n      ;----------------------------------------------------------------------------\n      ;\tDrawing loop\n      ;----------------------------------------------------------------------------\n\n      ??Start_row:\n      \tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n      ??Not_finished_a_line:\n      \tsub\tebx,ebx\n      \tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n      \tadd\tesi,2\t\t; then advance to the next one.\n\n      \tor\tbx,bx\t\t;Is it a one color block?\n      \tjs\tshort ??One_color\n\n      ;\tDraw multi-color block\n\n      \tadd\tebx,[cb_offset]\t;Codeword address\n      \tmov\teax,[ebx]\t\t;Read 1st row of codeword\n      \tmov\tedx,[ebx+4]\t\t;Read 2nd row of codeword\n\n      \tIF\tPHARLAP_TNT\n      \tmov\t[es:edi],eax\t\t;Write 1st row to dest\n      \tELSE\n      \tmov\t[edi],eax\t\t;Write 1st row to dest\n      \tENDIF\n\n      \tmov\teax,ebx\n   \tmov\tebx,[bufwidth]\n\n   \tIF\tPHARLAP_TNT\n   \tmov\t[es:edi+ebx],edx\t;Write 2nd row to dest\n   \tELSE\n   \tmov\t[edi+ebx],edx\t\t;Write 2nd row to dest\n\tENDIF\n\n\tmov\tebx,eax\n\tmov\teax,[ebx+8]\n\tmov\tedx,[ebx+12]\n\tmov\tebx,[bufwidth]\n\tshl\tebx,1\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],eax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi+ebx],eax\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],edx\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi+ebx],edx\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tedi,4\t\t;Next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n;\tDraw 1-color block\n\n??One_color:\n\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n\tjne\t??Draw_One_Color\n\n\tadd\tedi,4\t\t;Move to next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Next_row\n\n??Draw_One_Color:\n\tnot\tbx\t\t;NOT pointer value to get color\n\tmov\tbh,bl\t\t;Duplicate color through the\n\tmov\tax,bx\t\t; entire dword register.\n\trol\teax,16\n\tmov\tax,bx\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],eax\t\t;Write 1st row to dest\n\tmov\t[es:edi+ebx],eax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi],eax\t\t;Write 1st row to dest\n\tmov\t[edi+ebx],eax\t\t;Write 2nd row to dest\n   \tENDIF\n\n   \tadd\tebx,[bufwidth]\n\n   \tIF\tPHARLAP_TNT\n   \tmov\t[es:edi+ebx],eax\t;Write 3rd row to dest\n   \tELSE\n   \tmov\t[edi+ebx],eax\t\t;Write 3rd row to dest\n   \tENDIF\n\n   \tadd\tebx,[bufwidth]\n\n   \tIF\tPHARLAP_TNT\n   \tmov\t[es:edi+ebx],eax\t;Write 4th row to dest\n   \tELSE\n   \tmov\t[edi+ebx],eax\t\t;Write 4th row to dest\n   \tENDIF\n\n   \tadd\tedi,4\t\t;Next dest block positionw\n      \tdec\tecx\t\t;More blocks for this row?\n      \tjnz\t??Not_finished_a_line\n\n      ;\tAdvance to the next destination row of blocks.\n\n      ??Next_row:\n      \tmov\tedi,[edi_startval]\n      \tadd\tedi,[rowoffset]\n      \tmov\t[edi_startval],edi\n\n      \tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n      \tjnb\tshort ??End_of_data\t; pointers buffer?\n      \tjmp\t??Start_row\n\n      ??End_of_data:\n      \tIF\tPHARLAP_TNT\n      \tpop\tes\n      \tENDIF\n\n         \tret\n\n         \tENDP\tUnVQ_4x4\n         \tENDIF\t;VQABLOCK_4X4\n\n\n\n         \tIF\tVQABLOCK_WOOFER\n         \tIF\tVQABLOCK_4X2\n         ;****************************************************************************\n         ;*\n         ;* NAME\n         ;*     UnVQ_4x2_Woofer - Draw 4x2 block VQ frame to a buffer.\n         ;*\n         ;* SYNOPSIS\n         ;*     UnVQ_4x2_Woofer(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n         ;*\n         ;*     void UnVQ_4x2_Woofer(unsigned char *, unsigned char *,\n         ;*                          unsigned char *, long, long, long);\n         ;*\n         ;* FUNCTION\n         ;*     This function draws an image into the specified buffer from the\n         ;*     pointers and codebook provided. This routine has been optimized for\n         ;*     a 320x200 image.\n         ;*\n         ;* INPUTS\n         ;*     Codebook - Pointer to codebook used to draw image.\n         ;*     Pointers - Pointer to vector pointer data.\n         ;*     Buffer   - Pointer to buffer to draw image into.\n         ;*     BPR      - Number of blocks per row.\n         ;*     Rows     - Number of rows.\n         ;*     BufWidth - Width of destination buffer in pixels.\n         ;*\n         ;* RESULT\n         ;*     NONE\n         ;*\n         ;****************************************************************************\n\n         \tGLOBAL\tC UnVQ_4x2_Woofer:NEAR\n         \tPROC\tUnVQ_4x2_Woofer C NEAR USES ebx ecx edx esi edi\n\n         \tARG\tcodebook:NEAR PTR\n         \tARG\tpointers:NEAR PTR\n\n         \tIF\tPHARLAP_TNT\n         \tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n         \tELSE\n         \tARG\tbuffer:NEAR PTR\n         \tENDIF\n\n         \tARG\tblocksperrow:DWORD\n         \tARG\tnumrows:DWORD\n      \tARG\tbufwidth:DWORD\n\n      \tLOCAL\tdata_end:DWORD\n      \tLOCAL\tcb_offset:DWORD\n      \tLOCAL\tedi_startval:DWORD\n      \tLOCAL\trowoffset:DWORD\n      \tLOCAL\tentries:DWORD\n\n      ;----------------------------------------------------------------------------\n      ;\tInitialize\n      ;----------------------------------------------------------------------------\n\n      \tmov\teax,[codebook]\t\t;Adjust the codebook address so\n      ;\tsub\teax,4\t\t; that the pointer offsets will\n      \tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n      \tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n      \tshl\teax,1\t\t; row of blocks.\n      \tmov\t[rowoffset],eax\n\n      \tmov\tesi,[pointers]\n      \tmov\teax,[numrows]\t\t;Compute the end address of the\n      \tmul\t[blocksperrow]\t\t; pointer data.\n      \tmov\t[entries],eax\n      ;\tshl\teax,1\n      \tadd\teax,esi\n      \tmov\t[data_end],eax\n\n      \tIF\tPHARLAP_TNT\n      \tpush\tes\n      \tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n      \tELSE\n      \tmov\tedi,[buffer]\n      \tENDIF\n\n      \tmov\t[edi_startval],edi\n\n      ;----------------------------------------------------------------------------\n      ;\tDrawing loop\n      ;----------------------------------------------------------------------------\n\n      ??Start_row:\n      \tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n      ??Not_finished_a_line:\n      \tmov\teax,[entries]\n      \txor\tebx,ebx\n      ;\tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n      ;\tadd\tesi,2\t\t; then advance to the next one.\n      \tmov\tbl,[esi]\n      \tmov\tbh,[esi + eax]\n      \tinc\tesi\n\n      ;\tor\tbx,bx\t\t;Is it a one color block?\n      ;\tjs\tshort ??One_color\n\n      \tcmp\tbh,00Fh\n      \tje\tshort ??One_color\n\n      ;\tDraw multi-color block\n\n      \tshl\tebx,3\n\n      \tadd\tebx,[cb_offset]\t;Codeword address\n      \tmov\teax,[ebx]\t\t;Read 1st row of codeword\n      \tmov\tedx,[ebx+4]\t\t;Read 2nd row of codeword\n      \tmov\tebx,[bufwidth]\n\n      \tIF\tPHARLAP_TNT\n      \tmov\t[es:edi],al\t\t;Write 1st row to dest\n      \tshr\teax,16\n      \tmov\t[es:edi+2],al\n      \tmov\t[es:edi+ebx+1],dh\t\t;Write 1st row to dest\n      \tshr\tedx,16\n      \tmov\t[es:edi+ebx+3],dh\n      \tELSE\n      \tmov\t[edi],al\t\t;Write 1st row to dest\n      \tshr\teax,16\n      \tmov\t[edi+2],al\n      \tmov\t[edi+ebx+1],dh\t\t;Write 1st row to dest\n      \tshr\tedx,16\n      \tmov\t[edi+ebx+3],dh\n      \tENDIF\n\n      \tadd\tedi,4\t\t;Next dest block position\n      \tdec\tecx\t\t;More blocks for this row?\n      \tjnz\tshort ??Not_finished_a_line\n\n      ;\tAdvance to the next destination row of blocks.\n\n      \tmov\tedi,[edi_startval]\n      \tadd\tedi,[rowoffset]\n      \tmov\t[edi_startval],edi\n\n      \tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n      \tjnb\tshort ??End_of_data\t; pointers buffer?\n      \tjmp\t??Start_row\n\n      ;\tDraw 1-color block\n\n      ??One_color:\n      ;\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n      ;\tjne\t??Draw_One_Color\n\n      ;\tadd\tedi,4\t\t;Move to next dest block position\n      ;\tdec\tecx\t\t;More blocks for this row?\n      ;\tjnz\tshort ??Not_finished_a_line\n      ;\tjmp\t??Next_row\n\n      ??Draw_One_Color:\n      ;\tnot\tbx\t\t;NOT pointer value to get color\n      \tmov\tal,bl\n      \tmov\tebx,[bufwidth]\n\n      \tIF\tPHARLAP_TNT\n      \tmov\t[es:edi],al\n      \tmov\t[es:edi+2],al\n      \tmov\t[es:edi+ebx+1],al\t;Write 2nd row to dest\n      \tmov\t[es:edi+ebx+3],al\t;Write 2nd row to dest\n      \tELSE\n      \tmov\t[edi],al\n      \tmov\t[edi+2],al\n      \tmov\t[edi+ebx+1],al\t\t;Write 2nd row to dest\n      \tmov\t[edi+ebx+3],al\t\t;Write 2nd row to dest\n      \tENDIF\n\n      \tadd\tedi,4\t\t;Next dest block positionw\n      \tdec\tecx\t\t;More blocks for this row?\n      \tjnz\t??Not_finished_a_line\n\n      ;\tAdvance to the next destination row of blocks.\n\n      ??Next_row:\n      \tmov\tedi,[edi_startval]\n      \tadd\tedi,[rowoffset]\n      \tmov\t[edi_startval],edi\n\n      \tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n      \tjnb\tshort ??End_of_data\t; pointers buffer?\n      \tjmp\t??Start_row\n\n      ??End_of_data:\n      \tIF\tPHARLAP_TNT\n      \tpop\tes\n      \tENDIF\n\n      \tret\n\n      \tENDP\tUnVQ_4x2_Woofer\n      \tENDIF\t;VQABLOCK_4X2\n      \tENDIF\t;VQABLOCK_WOOFER\n\n      \tEND\n\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/UNVQVESA.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PROJECT\n;*     VQAPlay32 library.\n;*\n;* FILE\n;*     unvqvesa.asm\n;*\n;* DESCRIPTION\n;*     VESA VQ decompress/draw routines. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     UnVQ_4x2_VESA320_32K - Draw 4x2 VQ frame to VESA320 32k color.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"vga.i\"\n\tINCLUDE\t\"vesavid.i\"\n\tINCLUDE\t\"vqaplay.i\"\n\tCODESEG\n\nSKIP_PTR\tEQU\t8000h\n\n\tIF\tVQAVESA_ON\n\tIF\tVQABLOCK_4X2\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x2_VESA320_32K - Draw 4x2 VQ frame to VESA320 32k color.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x2_VESA320_32K(Codebook, Pointers, Palette, GrainPerWin)\n;*\n;*     void UnVQ_4x2_VESA320_32K(char *, char *, char *, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Codebook    - Pointer to codebook.\n;*     Pointers    - Pointer to vector pointer data to unvq.\n;*     Palette     - Pointer to 15-bit palette.\n;*     GrainPerWin - Granularity units for 64k window.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n \n;---------------------------------------------------------------------------\n; SET_2_PIXELS:\n; - Loads 2 bytes from codebook, expands them into words in eax\n; - Sets them on the screen\n;   cb_index: offset into codebook of start of 2 bytes to load\n;   di_index: offset from current di to draw 2 pixels\n;   BX: offset into codebook of this block\n; Uses: EAX, DX, SI!\n;---------------------------------------------------------------------------\n\n\tMACRO\tSET_2_PIXELS cb_index,edi_index\n\txor\tedx,edx\n\tmov\tdl,[BYTE PTR ebx+1+cb_index]\n\tshl\tedx,1\n\tadd\tedx,[palette]\n\tmov\tesi,edx\n\tmov\tax,[WORD PTR esi]\n\tshl\teax,16\n\txor\tedx,edx\n\tmov\tdl,[BYTE PTR ebx+cb_index]\n\tshl\tedx,1\n\tadd\tedx,[palette]\n\tmov\tesi,edx\n\tmov\tax,[WORD PTR esi]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[DWORD PTR es:edi+edi_index],eax\n\tELSE\n\tmov\t[DWORD PTR edi+edi_index],eax\n\tENDIF\n\tENDM\n\n;---------------------------------------------------------------------------\n; DRAW_BLOCK_ROWS macro:\n; Draws 'numrows' rows of 'blocksperrow' blocks each\n;---------------------------------------------------------------------------\n\n\tMACRO\tDRAW_BLOCK_ROWS numrows,blocksperrow\n\tLOCAL\t??Start_row\n\tLOCAL\t??Not_finished_a_line\n\tLOCAL\t??One_color\n\tLOCAL\t??Draw_One_Color\n\tLOCAL\t??Next_row\n\tLOCAL\t??Done\n\n\tmov\t[rowcount],numrows\t\t; initialize row counter\n\n\t;---------------------------------------- Start a new row:\n??Start_row:\n\tmov\tecx,blocksperrow\t\t\t; # blocks to fill a line\n\n\t;---------------------------------------- Start a new block:\n??Not_finished_a_line:\n\t;........................................ Get next pointer word:\n\txor\tebx,ebx\n\tmov\tbx,[WORD PTR esi]\t\t; BX = pointer word\n\tadd\tesi,2\n\n\t;........................................ Check for a 1-color block:\n\tor\tbx,bx\t\t\t\t; see if high bit is set\n\tjs\t??One_color\n\n\t;---------------------------------------- Multi-color block:\n\tmov\t[esi_save],esi\t\t\t; save current SI\n\tadd\tebx,[cb_offset]\t\t\t; get codebook offset\n\tSET_2_PIXELS 0,0\n\tSET_2_PIXELS 2,4\n\tSET_2_PIXELS 4,640\n\tSET_2_PIXELS 6,644\n\tadd\tedi,8\t\t\t\t; next block position\n\tmov\tesi,[esi_save]\t\t\t; get current SI\n\n\t;........................................ Check block count\n\tdec\tecx\t\t\t\t; decrement block count\n\tjnz\t??Not_finished_a_line\n\n\t;---------------------------------------- Next block row:\n\tadd\tedi,640\n\t;\n\t;............ see if we're past the end of the ptr data ............\n\t;\n\tdec\t[rowcount]\n\tjnz\t??Start_row\n\tjmp\t??Done\n\n\t;---------------------------------------- 1-color block:\n??One_color:\n\t;................... skip ptr value SKIP_PTR .......................\n\tcmp\tbx,SKIP_PTR\n\tjne\t??Draw_One_Color\n\tadd\tedi,8\n\tdec\tecx\n\tjnz\t??Not_finished_a_line\n\tjmp\t??Next_row\n??Draw_One_Color:\n\tnot\tbx\t\t\t\t; get palette index\n\tshl\tbx,1\t\t\t\t; convert to WORD offset\n\tadd\tebx,[palette]\n\tmov\tax,[WORD PTR ebx]\t\t; get 15-bit palette value\n\tmov\tdx,ax\t\t\t\t; copy it into dx\n\tshl\teax,16\n\tmov\tax,dx\t\t\t\t; eax = 2 pixels, same color\n\tmov\tedx,eax\t\t\t\t; edx = 2 pixels, same color\n\n\tIF\tPHARLAP_TNT\n\tmov\t[DWORD PTR es:edi],eax\t\t; set 2 pixels\n\tmov\t[DWORD PTR es:edi+4],edx\t\t; set 2 pixels\n\tmov\t[DWORD PTR es:edi+640],eax\t; set 2 pixels\n\tmov\t[DWORD PTR es:edi+644],edx\t; set 2 pixels\n\tELSE\n\tmov\t[DWORD PTR edi],eax\t\t; set 2 pixels\n\tmov\t[DWORD PTR edi+4],edx\t\t; set 2 pixels\n\tmov\t[DWORD PTR edi+640],eax\t; set 2 pixels\n\tmov\t[DWORD PTR edi+644],edx\t; set 2 pixels\n\tENDIF\n\n\tadd\tedi,8\t\t\t\t; next block position\n\n\t;........................................ Check block count\n\tdec\tecx\t\t\t\t; decrement block count\n\tjnz\t??Not_finished_a_line\n\n\t;---------------------------------------- Next block row:\n??Next_row:\n\tadd\tedi,640\n\t;\n\t;............ see if we're past the end of the ptr data ............\n\t;\n\tdec\t[rowcount]\n\tjnz\t??Start_row\n??Done:\n\tENDM\n\n;---------------------------------------------------------------------------\n; DRAW_BLOCK_PART_ROW macro:\n; Draws top or bottom half of blocks on a row\n; 'numblocks' = # blocks to draw\n; 'cb_add' = amt to add to codebook (0=top half, 4=bottom half)\n;---------------------------------------------------------------------------\n\n\tMACRO\tDRAW_BLOCK_PART_ROW numblocks,cb_add\n\tLOCAL\t??Not_finished_a_line\n\tLOCAL\t??One_color\n\tLOCAL\t??Draw_One_Color\n\tLOCAL\t??Done\n\n\tmov\tecx,numblocks\n\n\t;---------------------------------------- Start a new block:\n??Not_finished_a_line:\n\t;........................................ Get next pointer word:\n\txor\tebx,ebx\n\tmov\tbx,[WORD PTR esi]\t\t; BX = pointer word\n\tadd\tesi,2\n\n\t;........................................ Check for a 1-color block:\n\tor\tbx,bx\t\t\t\t; see if high bit is set\n\tjs\tshort ??One_color\n\n\t;---------------------------------------- Multi-color block:\n\tmov\t[esi_save],esi\t\t\t; save current SI\n\tadd\tebx,[cb_offset]\t\t\t; get codebook offset\n\tSET_2_PIXELS cb_add,0\n\tSET_2_PIXELS cb_add+2,4\n\tadd\tedi,8\t\t\t\t; next block position\n\tmov\tesi,[esi_save]\t\t\t; get current SI\n\n\t;........................................ Check block count\n\tdec\tecx\t\t\t\t; decrement block count\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Done\n\n\t;---------------------------------------- 1-color block:\n??One_color:\n\t;................... skip ptr value SKIP_PTR .......................\n\tcmp\tbx,SKIP_PTR\n\tjne\t??Draw_One_Color\n\tadd\tedi,8\n\tdec\tecx\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Done\n??Draw_One_Color:\n\tnot\tbx\t\t\t\t; get palette index\n\tshl\tbx,1\t\t\t\t; convert to WORD offset\n\tadd\tebx,[palette]\n\tmov\tax,[WORD PTR ebx]\t\t; get 15-bit palette value\n\tmov\tdx,ax\t\t\t\t; copy it into dx\n\tshl\teax,16\n\tmov\tax,dx\t\t\t\t; eax = 2 pixels, same color\n\tmov\tedx,eax\t\t\t\t; edx = 2 pixels, same color\n\n\tIF\tPHARLAP_TNT\n\tmov\t[DWORD PTR es:edi],eax\t\t; set 2 pixels\n\tmov\t[DWORD PTR es:edi+4],edx\t\t; set 2 pixels\n\tELSE\n\tmov\t[DWORD PTR edi],eax\t\t; set 2 pixels\n\tmov\t[DWORD PTR edi+4],edx\t\t; set 2 pixels\n\tENDIF\n\n\tadd\tedi,8\t\t\t\t; next block position\n\n\t;........................................ Check block count\n\tdec\tecx\t\t\t\t; decrement block count\n\tjnz\t??Not_finished_a_line\n??Done:\n\tENDM\n\n;===========================================================================\n; The actual procedure:\n;===========================================================================\n\n\tGLOBAL\tC UnVQ_4x2_VESA320_32K:NEAR\n\tPROC\tUnVQ_4x2_VESA320_32K C NEAR\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tARG\tpal:QWORD\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tARG\tpalette:NEAR PTR\n\tENDIF\n\n\tARG\tgrains_per_win:DWORD\n\tARG\tdummy1:DWORD\n\tARG\tdummy2:DWORD\n\n\tLOCAL\trowcount:DWORD\t\t; # rows drawn\n\tLOCAL\tesi_save:DWORD\n\tLOCAL\tcb_offset:DWORD\n\n\tIF\tPHARLAP_TNT\n\tLOCAL\tpalette:NEAR PTR\n\tENDIF\n\n\t;-------------------------------------------------------------------\n\t; Save registers\n\t;-------------------------------------------------------------------\n\tpushad\n\n\t;-------------------------------------------------------------------\n\t; Set GS:[cb_offset] to codebook\n\t;-------------------------------------------------------------------\n\tmov\teax,[codebook]\n\tsub\teax,4\n\tmov\t[cb_offset],eax\n\tmov\tesi,[pointers]\n\n\t;-------------------------------------------------------------------\n\t; Set ES:DI to screen\n\t;-------------------------------------------------------------------\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tles\tedi,[FWORD pal]\n\tmov\t[palette],edi\n\tmov\teax,01Ch\n\tmov\tes,ax\n\tmov\tedi,0\n\tELSE\n\tmov\tedi,0A0000h\n\tENDIF\n\n\t;-------------------------------------------------------------------\n\t; Do Bank 0:\n\t; - 102 full scanlines (51 rows of blocks)\n\t; - 128 pixels of the top half of blocks (32 top-half blocks)\n\t;-------------------------------------------------------------------\n\tSET_WINDOW 0\n\tDRAW_BLOCK_ROWS 51,80\n\tDRAW_BLOCK_PART_ROW 32,0\t; do top half\n\n\t;-------------------------------------------------------------------\n\t; Do Bank 1:\n\t; - 128 pixels of the bottom half of the previous 32 blocks\n\t; - 192 pixels of full blocks (1 row of 48 blocks)\n\t; - 96 full scanlines (48 rows of blocks)\n\t;-------------------------------------------------------------------\n\tSET_WINDOW [grains_per_win]\n\tsub\tesi,64\t\t\t; subtract word size of last 32 blks\n\tmov\tedi,384\n\tDRAW_BLOCK_PART_ROW 32,4\t; do bottom half\n\tmov\tedi,0\n\tDRAW_BLOCK_ROWS 1,48\t\t; draw one row of 48 full blocks\n\tDRAW_BLOCK_ROWS 48,80\t\t; draw 48 full block rows\n\n??End_of_data:\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tpopad\n\tret\n\n\tENDP\tUnVQ_4x2_VESA320_32K\n\n\tENDIF\t;VQABLOCK_4X2\n\tENDIF\t;VQAVESA_ON\n\n\tEND\n\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/UNVQXMDE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PROJECT\n;*     VQAPlay library.\n;*\n;* FILE\n;*     UnVQxmde.asm\n;*\n;* DESCRIPTION\n;*     XMode VQ decompress/draw routines.\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     May 18, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     UnVQ_4x2_Xmode       - Draw 4x2 VQ frame directly to Xmode.\n;*     UnVQ_4x2_XmodeCB     - Draw 4x2 VQ frame to Xmode from VRAM codebook.\n;*     Upload_4x2CB         - Upload 4x2 codebook into XMode VRAM.\n;*     UnVQ_4x2_VESA320_32K - Draw 4x2 VQ frame to VESA320 32k color.\n;*     XlatePointers        - Translate pointer to optimal XMode format.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"vga.i\"\n\tINCLUDE\t\"vesavid.i\"\n\tINCLUDE\t\"vqaplay.i\"\n\tCODESEG\n\n\tIF\tVQAXMODE_ON\n\nSKIP_PTR\tEQU\t8000h\nCBOOK_SEG\tEQU\t(0B0000h - 270h)\n\n\n\tIF\tVQABLOCK_4X2\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x2_Xmode - Draw 4x2 VQ frame directly to Xmode.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x2_Xmode(Codebook, Pointers, Buffer, BPR, Rows, Dummy)\n;*\n;*     void UnVQ_4x2_Xmode(unsigned char *, unsigned char *, unsigned char *,\n;*                         unsigned short, unsigned short, unsigned short);\n;*\n;* FUNCTION\n;*     This function draws an image to the Xmode display from the pointers\n;*     and codebook provided. This routine has been optimized for a 320x200\n;*     image.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook used to draw image.\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to buffer to draw image into.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*     Dummy    - Not used (prototype placeholder)\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC UnVQ_4x2_Xmode:NEAR\n\tPROC\tUnVQ_4x2_Xmode C NEAR USES\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tARG\tbuffer:NEAR PTR\n\tENDIF\n\n\tARG\tblocksperrow:DWORD\n\tARG\tnumrows:DWORD\n\tARG\tbufwidth:DWORD\n\n\tLOCAL\tdata_end:DWORD\n\tLOCAL\tcb_offset:DWORD\n\tLOCAL\tedi_startval:DWORD\n\tLOCAL\trowoffset:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tmov\teax,[codebook]\t\t;Adjust the codebook address so\n\tsub\teax,4\t\t; that the pointer offsets will\n\tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n\tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n\tshl\teax,1\t\t; row of blocks.\n\tmov\t[rowoffset],eax\n\n\tmov\tesi,[pointers]\n\tmov\teax,[numrows]\t\t;Compute the end address of the\n\tmul\t[blocksperrow]\t\t; pointer data.\n\tshl\teax,1\n\tadd\teax,esi\n\tmov\t[data_end],eax\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tmov\tedi,[buffer]\n\tENDIF\n\n\tmov\t[edi_startval],edi\n\n;----------------------------------------------------------------------------\n;\tDrawing loop\n;----------------------------------------------------------------------------\n\n\tSET_PLANE\tXPLANE_1\n\n??Start_row:\n\tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n??Not_finished_a_line1:\n\tsub\tebx,ebx\n\tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n\tadd\tesi,2\t\t; then advance to the next one.\n\n\tor\tbx,bx\t\t;Is it a one color block?\n\tjs\tshort ??One_color1\n\n;\tDraw multi-color block\n\n\tadd\tebx,[cb_offset]\t;Codeword address\n\tmov\teax,[ebx]\t\t;Read 1st row of codeword\n\tmov\tedx,[ebx+4]\t\t;Read 2nd row of codeword\n;\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],eax\t\t;Write 1st row to dest\n\tmov\t[es:edi+ebx],edx\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi],al\t\t;Write 1st row to dest\n\tmov\t[edi+80],dl\t\t;Write 2nd row to dest\n\tENDIF\n\n;\tadd\tedi,4\t\t;Next dest block position\n\tinc\tedi\t\t;Next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n;\tDraw 1-color block\n\n??One_color1:\n\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n\tjne\t??Draw_One_Color\n\n\tadd\tedi,4\t\t;Move to next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Next_row\n\n??Draw_One_Color:\n\tnot\tbx\t\t;NOT pointer value to get color\n\tmov\tbh,bl\t\t;Duplicate color through the\n\tmov\tax,bx\t\t; entire dword register.\n\trol\teax,16\n\tmov\tax,bx\n;\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],eax\t\t;Write 1st row to dest\n\tmov\t[es:edi+ebx],eax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi],al\t\t;Write 1st row to dest\n\tmov\t[edi+80],al\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tedi,4\t\t;Next dest block positionw\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n??Next_row:\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n??End_of_data:\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\tENDP\tUnVQ_4x2_Xmode\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x2_XmodeCB - Draw 4x2 VQ frame to Xmode from VRAM codebook.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x2_XmodeCB(Dummy, Pointers, Buffer, BPR, Rows)\n;* \n;*     void UnVQ_4x2_XmodeCB(unsigned char *, unsigned char *,\n;*                           unsigned char *, unsigned short,\n;*                           unsigned short);\n;*\n;* FUNCTION\n;*     This routine copies codebook entries from video RAM to video RAM.\n;*     The procedure for Write Mode 1 is:\n;*\n;*       - Perform a CPU read at the address of the 4-byte codebook entry;\n;*         this will load each byte at that address from all 4 bitplanes\n;*         into the VGA's internal latches.\n;*\n;*       - Perform a CPU write at the destination address, with the BitMask\n;*         register set to 0 (this tells the VGA hardware to only use the\n;*         data stored in the latches to write with), and the Map Mask\n;*         register set to 0Fh (all bitplanes enabled).\n;*\n;*     Optimized for 320x200.\n;*     The codebook must have been downloaded to video RAM before this\n;*     routine is called. This routine assumes the multicolor block pointers\n;*     have been pre-divided by 4, and have a total of 512 added to them, so\n;*     the pointer is an exact offset into the codebook.\n;*\n;* INPUTS\n;*     Dummy    - Not used (prototype placeholder)\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to Xmode buffer.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC UnVQ_4x2_XmodeCB:NEAR\n\tPROC\tUnVQ_4x2_XmodeCB C NEAR USES\n\n\tARG\tcbdummy:FAR PTR\n\tARG\tpointers:FAR PTR\n\tARG\tbuffer:FAR PTR\n\tARG\tblocksperrow:WORD\n\tARG\tnumrows:WORD\n\n;\t;-------------------------------------------------------------------\n;\t; Local variables:\n;\t;-------------------------------------------------------------------\n;\tLOCAL\tdi_startval:WORD\t; init value for DI, for new row\n;\n;\t;===================================================================\n;\t; Initialization\n;\t;===================================================================\n;\t;-------------------------------------------------------------------\n;\t; Save our registers\n;\t;-------------------------------------------------------------------\n;\tpush\tds\n;\tpush\tes\n;\tpush\tfs\n;\tpushad\n;\n;\t;-------------------------------------------------------------------\n;\t; Save codebook's segment in DS\n;\t;-------------------------------------------------------------------\n;\tmov\tax,CBOOK_SEG\n;\tmov\tds,ax\n;\n;\t;-------------------------------------------------------------------\n;\t; Load pointers into FS:BX\n;\t;-------------------------------------------------------------------\n;\tles\tdi,[pointers]\n;\tmov\tax,es\n;\tmov\tfs,ax\n;\tmov\tbx,di\n;\n;\t;-------------------------------------------------------------------\n;\t; Load screen address into ES:DI\n;\t;-------------------------------------------------------------------\n;\tles\tdi, [buffer]   \t\t\t; point ES:DI to dest\n;\tmov\t[di_startval],di\t\t; store it\n;\n;\t;-------------------------------------------------------------------\n;\t; Initialize VGA registers:\n;\t; - Enable all bitplanes for writing\n;\t; - Set the BitMask register to 0, so only the data from the\n;\t;   VGA latches is written into the bitplanes\n;\t;-------------------------------------------------------------------\n;\tSET_PLANE 0fh\t\t\t\t; enable all planes for write\n;\tSET_WRITEMODE 1\n;\n;\t;===================================================================\n;\t; The drawing loop:\n;\t; DS:SI = codebook\n;\t; ES:DI = drawing buffer\n;\t; FS:BX = pointers\n;\t;===================================================================\n;\t;-------------------------------------------------------------------\n;\t; Start a new row of drawing\n;\t;-------------------------------------------------------------------\n;??Start_row:\n;\tmov\tcx,[blocksperrow]\t\t; # blocks to fill a line\n;\n;\t;-------------------------------------------------------------------\n;\t; Start a new block\n;\t;-------------------------------------------------------------------\n;??Not_finished_a_line:\n;\t;\n;\t;..................... get next pointer word .......................\n;\t;\n;\tmov\tsi,[WORD PTR fs:bx]\t\t; SI = ptr word (cbook offset)\n;\tadd\tbx,2\t\t\t\t; next ptr word\n;\t;\n;\t;................... skip ptr value SKIP_PTR .......................\n;\t;\n;\tcmp\tsi,SKIP_PTR\n;\tjne\t??Draw_Block\n;\tinc\tdi\n;\tdec\tcx\n;\tjnz\tshort ??Not_finished_a_line\n;\tjmp\t??Next_row\n;\n;\t;-------------------------------------------------------------------\n;\t; Draw a block via the VGA internal latches:\n;\t; DS:SI = codebook address\n;\t; ES:DI = buffer position to draw at\n;\t; - Load the VGA latches from the 1st 4 codebook bytes\n;\t; - write 4 pixels with one CPU write\n;\t; - If this is a one-color block, skip the next codebook read\n;\t;   (Video RAM reads are very slow); otherwise, latch the next 4\n;\t;   codebook bytes\n;\t; - write the next 4 pixels\n;\t;-------------------------------------------------------------------\n;\t;\n;\t;..................... draw 1st 4 pixels ...........................\n;\t;\n;??Draw_Block:\n;\tmov\tal,[ds:si]\t\t\t; latch 1st 4 cbook bytes\n;\tmov\t[es:di],al\t\t\t; write 4 pixels\n;\t;\n;\t;.................. check for 1-color block ........................\n;\t;\n;\tcmp\tsi,512\t\t\t\t; if 1color blk, don't read\n;\tjb\t??One_Color\n;\t;\n;\t;..................... draw next 4 pixels ..........................\n;\t;\n;\tmov\tal,[ds:si+1]\t\t\t; latch next 4 cbook bytes\n;??One_Color:\n;\tmov\t[es:di+80],al\t\t\t; write next 4 pixels\n;\tinc\tdi\t\t\t\t; next block position\n;\t;\n;\t;...................... check block count ..........................\n;\t;\n;\tdec\tcx\t\t\t\t; decrement block count\n;\tjnz\tshort ??Not_finished_a_line\n;\n;\t;-------------------------------------------------------------------\n;\t; Go to the next block row:\n;\t; - Add (80*2/16) to ES, and set DI to its start-row value\n;\t;   (Incrementing the segment allows us to unpack up to 1MB of data)\n;\t;-------------------------------------------------------------------\n;\t;\n;\t;...................... add (320*2/16) to ES .......................\n;\t;\n;??Next_row:\n;\tmov\tax,es\n;\tadd\tax,10\t\t\t\t; add 80*2/16\n;\tmov\tes,ax\n;\t;\n;\t;.................. set DI to its start-row value ..................\n;\t;\n;\tmov\tdi,[di_startval]\n;\t;\n;\t;............ see if we're past the end of the ptr data ............\n;\t;\n;\tdec\t[numrows]\n;\tjg\t??Start_row\n;\n;??End_of_data:\n;\t;-------------------------------------------------------------------\n;\t; Restore VGA Write Mode to 0\n;\t;-------------------------------------------------------------------\n;\tSET_WRITEMODE 0\n;\n;\tpopad\n;\tpop\tfs\n;\tpop\tes\n;\tpop\tds\n\tret\n\n\tENDP\tUnVQ_4x2_XmodeCB\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Upload_4x2CB - Upload 4x2 codebook into XMode VRAM.\n;*\n;* SYNOPSIS\n;*     Upload_4x2CB(Codebook, Entries)\n;*\n;*     void Upload_4x2CB(unsigned char *, unsigned short);\n;*\n;* FUNCTION\n;*     This routine copies the given codebook into Xmode VRAM, so that it\n;*     can be used later for direct video-to-video copies. The address used\n;*     is the end of video memory minus 02700h (10K). This should be plenty\n;*     for a 3000-entry codebook; each 4x2 codebook entry will take up 8\n;*     8 bytes, or 2 addresses in XMode (6000 addresses).\n;*\n;*     The routine also creates a 1-color-block table in VRAM, so the 1-color\n;*     blocks can be generated the same way as the multicolor blocks.\n;*\n;*     XMode 320x200 uses 320x200/4 addresses per page, for a total of 32000\n;*     addresses.  XMode 320x240 uses 320x240/4 addresses per page, for a\n;*     total of 38400 addresses.  This leaves 27136 addresses unused.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook to copy.\n;*     Entries  - Number of codebook entries to copy.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Upload_4x2CB:NEAR\n\tPROC\tUpload_4x2CB C NEAR USES\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tnumentries:DWORD\n\n;\t;===================================================================\n;\t; Generate the 1-color block table by writing each color value from\n;\t; 0-255 into all 4 bitplanes, at 256 consecutive addresses:\n;\t;===================================================================\n;\tSET_PLANE 0fh\t\t\t; enable all bitplanes for writing\n;\t;...................................................................\n;\t; Set ES:DI to destination address, set up CX for the loop\n;\t;...................................................................\n;\tmov\tax,CBOOK_SEG\n;\tmov\tes,ax\n;\tmov\tdi,0\n;\tmov\tcx,256\n;\tmov\tax,0\n;??1_Color_Loop:\n;\tmov\t[es:di],al\t\t\t; write 4 bytes\n;\tinc\tdi\t\t\t\t; next 4-byte position\n;\tmov\t[es:di],al\t\t\t; write 4 bytes\n;\tinc\tdi\t\t\t\t; next 4-byte position\n;\tinc\tax\t\t\t\t; next color #\n;\tdec\tcx\t\t\t\t; decrement loop counter\n;\tjnz\t??1_Color_Loop\n;\n;\t;===================================================================\n;\t; Copy the codebook into video RAM, one plane at a time:\n;\t;===================================================================\n;\t;-------------------------------------------------------------------\n;\t; Copy codebook byte 0 into Plane 1\n;\t;-------------------------------------------------------------------\n;\t;...................................................................\n;\t; Set DS:SI to codebook address, ES:DI to screen address\n;\t; (Codebook is stored at offset 1, so the pointers will point at\n;\t; exactly the right offset.)\n;\t;...................................................................\n;\tlds\tsi, [codebook]\t\t\t; DS:SI = codebook\n;\tmov\tax,CBOOK_SEG\n;\tmov\tes,ax\n;\tmov\tdi,512\n;\n;\t;...................................................................\n;\t; Set up the loop\n;\t;...................................................................\n;\tSET_PLANE XPLANE_1\n;\tmov\tcx,[numentries]\t\t\t; set loop counter\n;\tshl\tcx,1\t\t\t\t; do 2 DWORDS per cbook entry\n;\n;\t;...................................................................\n;\t; Loop through codebook entries\n;\t;...................................................................\n;??CB_Loop_1:\n;\tmov\tal,[ds:si]\n;\tmov\t[es:di],al\n;\tadd\tsi,4\n;\tinc\tdi\n;\tdec\tcx\n;\tjnz\t??CB_Loop_1\n;\n;\t;-------------------------------------------------------------------\n;\t; Copy codebook byte 1 Plane 2\n;\t;-------------------------------------------------------------------\n;\t;...................................................................\n;\t; Set DS:SI to codebook address, ES:DI to screen address\n;\t; (Codebook is stored at offset 1, so the pointers will point at\n;\t; exactly the right offset.)\n;\t;...................................................................\n;\tlds\tsi, [codebook]\t\t\t; DS:SI = codebook\n;\tmov\tax,CBOOK_SEG\n;\tmov\tes,ax\n;\tmov\tdi,512\n;\tadd\tsi,1\t\t\t\t; use 2nd byte value\n;\n;\t;...................................................................\n;\t; Set up the loop\n;\t;...................................................................\n;\tSET_PLANE XPLANE_2\n;\tmov\tcx,[numentries]\t\t\t; set loop counter\n;\tshl\tcx,1\t\t\t\t; do 2 DWORDS per cbook entry\n;\n;\t;...................................................................\n;\t; Loop through codebook entries\n;\t;...................................................................\n;??CB_Loop_2:\n;\tmov\tal,[ds:si]\n;\tmov\t[es:di],al\n;\tadd\tsi,4\n;\tinc\tdi\n;\tdec\tcx\n;\tjnz\t??CB_Loop_2\n;\n;\t;-------------------------------------------------------------------\n;\t; Copy codebook byte 2 Plane 3\n;\t;-------------------------------------------------------------------\n;\t;...................................................................\n;\t; Set DS:SI to codebook address, ES:DI to screen address\n;\t; (Codebook is stored at offset 1, so the pointers will point at\n;\t; exactly the right offset.)\n;\t;...................................................................\n;\tlds\tsi, [codebook]\t\t\t; DS:SI = codebook\n;\tmov\tax,CBOOK_SEG\n;\tmov\tes,ax\n;\tmov\tdi,512\n;\tadd\tsi,2\t\t\t\t; use 3rd byte value\n;\n;\t;...................................................................\n;\t; Set up the loop\n;\t;...................................................................\n;\tSET_PLANE XPLANE_3\n;\tmov\tcx,[numentries]\t\t\t; set loop counter\n;\tshl\tcx,1\t\t\t\t; do 2 DWORDS per cbook entry\n;\n;\t;...................................................................\n;\t; Loop through codebook entries\n;\t;...................................................................\n;??CB_Loop_3:\n;\tmov\tal,[ds:si]\n;\tmov\t[es:di],al\n;\tadd\tsi,4\n;\tinc\tdi\n;\tdec\tcx\n;\tjnz\t??CB_Loop_3\n;\n;\t;-------------------------------------------------------------------\n;\t; Copy codebook byte 3 Plane 4\n;\t;-------------------------------------------------------------------\n;\t;...................................................................\n;\t; Set DS:SI to codebook address, ES:DI to screen address\n;\t; (Codebook is stored at offset 1, so the pointers will point at\n;\t; exactly the right offset.)\n;\t;...................................................................\n;\tlds\tsi, [codebook]\t\t\t; DS:SI = codebook\n;\tmov\tax,CBOOK_SEG\n;\tmov\tes,ax\n;\tmov\tdi,512\n;\tadd\tsi,3\t\t\t\t; use 4th byte value\n;\n;\t;...................................................................\n;\t; Set up the loop\n;\t;...................................................................\n;\tSET_PLANE XPLANE_4\n;\tmov\tcx,[numentries]\t\t\t; set loop counter\n;\tshl\tcx,1\t\t\t\t; do 2 DWORDS per cbook entry\n;\n;\t;...................................................................\n;\t; Loop through codebook entries\n;\t;...................................................................\n;??CB_Loop_4:\n;\tmov\tal,[ds:si]\n;\tmov\t[es:di],al\n;\tadd\tsi,4\n;\tinc\tdi\n;\tdec\tcx\n;\tjnz\t??CB_Loop_4\n;\n\tret\n\n\tENDP\tUpload_4x2CB\n\n\tENDIF\t;VQABLOCK_4X2\n\n;****************************************************************************\n;*\n;* NAME\n;*     XlatePointers - Translate pointer to optimal XMode format.\n;*\n;* SYNOPSIS\n;*     XlatePointers(Pointers, Entries)\n;*\n;*     void XlatePointers(unsigned char *, unsigned short);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Pointers - Pointer to vector pointers to translate.\n;*     Entries  - Number of pointer entries.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC XlatePointers:NEAR\n\tPROC\tXlatePointers C NEAR USES\n\n\tARG\tpointers:NEAR PTR\n\tARG\tnumpointers:DWORD\n\n;\t;-------------------------------------------------------------------\n;\t; Load pointers into DS:SI\n;\t;-------------------------------------------------------------------\n;\tlds\tsi,[pointers]\n;\n;\tmov\tcx,[numpointers]\t\t; init to # pointers on scrn\n;\n;??Process_pointer:\n;\t;\n;\t;..................... get next pointer word .......................\n;\t;\n;\tmov\tax,[WORD PTR ds:si]\t\t; SI = ptr word (cbook offset)\n;\t;\n;\t;.................... check for a 1-color block ....................\n;\t;\n;\tor\tax,ax\t\t\t\t; check to see if high bit set\n;\tjs\tshort ??One_color\n;\t;\n;\t;....................... multi-color pointer .......................\n;\t;\n;\tsub\tax,4\t\t\t\t; subtract 4\n;\tshr\tax,2\t\t\t\t; divide by 4\n;\tadd\tax,512\t\t\t\t; add 512\n;\tmov\t[WORD PTR ds:si],ax\t\t; save new value\n;\tadd\tsi,2\t\t\t\t; next ptr word\n;\t;\n;\t;....................... see if we're done .........................\n;\t;\n;\tdec\tcx\n;\tjnz\t??Process_pointer\n;\tjmp\t??Done\n;\n;??One_color:\n;\t;\n;\t;......................... 1-color pointer .........................\n;\t;\n;\tnot\tax\t\t\t\t; get actual color value\n;\tshl\tax,1\t\t\t\t; multiply by 2\n;\tmov\t[WORD PTR ds:si],ax\t\t; save new value\n;\tadd\tsi,2\t\t\t\t; next ptr word\n;\t;\n;\t;....................... see if we're done .........................\n;\t;\n;\tdec\tcx\n;\tjnz\t??Process_pointer\n;\n;??Done:\n\tret\n\n\tENDP\tXlatePointers\n\n\tENDIF\t;VQAXMODE_ON\n\tEND\n\n\n\n\n\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/VERTAG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vertag.c\n*\n* DESCRIPTION\n*     Version Tag\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     February 23, 1995\n*\n****************************************************************************/\n\n#include \"vqaplayp.h\"\n\n#ifdef __WATCOMC__\n#define DEVNAME \"Watcom/4GW\"\n#else\n#define DEVNAME \"Borland/TNT\"\n#endif\n\nchar VerTag[] = {\"$VER$\" VQA_IDSTRING\" \"DEVNAME\" (\"VQA_DATE\")\"};\nchar ReqTag[] = {\"$REQ$\" VQA_REQUIRES};\n\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/VQAFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAFILE_H\n#define VQAFILE_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqafile.h\n*\n* DESCRIPTION\n*     VQA file format definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*      \n* DATE\n*     April 10, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\iff.h>\n\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n\n/*---------------------------------------------------------------------------\n * STRUCTURE DEFINITIONS AND RELATED DEFINES.\n *-------------------------------------------------------------------------*/\n\n/* VQAHeader: VQA movie description header. (VQHD)\n *\n * Version       - VQA version.\n * Flags         - Various flags. (See below)\n * ImageWidth    - Image width in pixels.\n * ImageHeight   - Image height in pixels.\n * BlockWidth    - Block width in pixels.\n * BlockHeight   - Block height in pixels.\n * Frames        - Total number of frames in the movie.\n * FPS           - Playback rate (Frame Per Second).\n * Groupsize     - Frame grouping size (frames per codebook).\n * Num1Colors    - Number of 1 color colors.\n * CBentries     - Number of codebook entries.\n * Xpos          - X position to draw frames. (-1 = Center)\n * Ypos          - Y position to draw frames. (-1 = Center)\n * MaxFramesize  - Size of largest frame.\n * SampleRate    - Sample rate of primary audio stream.\n * Channels      - Number of channels in primary audio stream.\n * BitsPerSample - Sample bit size in primary audio stream.\n * FutureUse     - Reserved for future expansion.\n */\ntypedef struct _VQAHeader {\n\tunsigned short Version;\n\tunsigned short Flags;\n\tunsigned short Frames;\n\tunsigned short ImageWidth;\n\tunsigned short ImageHeight;\n\tunsigned char  BlockWidth;\n\tunsigned char  BlockHeight;\n\tunsigned char  FPS;\n\tunsigned char  Groupsize;\n\tunsigned short Num1Colors;\n\tunsigned short CBentries;\n\tunsigned short Xpos;\n\tunsigned short Ypos;\n\tunsigned short MaxFramesize;\n\tunsigned short SampleRate;\n\tunsigned char  Channels;\n\tunsigned char  BitsPerSample;\n\tunsigned short AltSampleRate;\n\tunsigned char  AltChannels;\n\tunsigned char  AltBitsPerSample;\n\tunsigned short FutureUse[5];\n} VQAHeader;\n\n/* Version type. */\n#define VQAHD_VER1 1\n#define VQAHD_VER2 2\n\n/* VQA header flag definitions */\n#define VQAHDB_AUDIO    0 /* Audio track present. */\n#define VQAHDB_ALTAUDIO 1 /* Alternate audio track present. */\n#define VQAHDF_AUDIO    (1<<VQAHDB_AUDIO)\n#define VQAHDF_ALTAUDIO (1<<VQAHDB_ALTAUDIO)\n\n\n/* Frame information (FINF) chunk definitions\n *\n * The FINF chunk contains a longword (4 bytes) entry for each\n * frame in the movie. This entry is divided into two parts,\n * flags (4 bits) and offset (28 bits).\n *\n * BITS   NAME     DESCRIPTION\n * -----------------------------------------------------------\n * 31-28  Flags    4 bitwise boolean flags.\n * 27-0   Offset   Offset in WORDS from the start of the file.\n */\n#define VQAFINB_KEY  31\n#define VQAFINB_PAL  30\n#define VQAFINB_SYNC 29\n#define VQAFINF_KEY  (1L<<VQAFINB_KEY)\n#define VQAFINF_PAL  (1L<<VQAFINB_PAL)\n#define VQAFINF_SYNC (1L<<VQAFINB_SYNC)\n\n/* FINF related defines and macros. */\n#define VQAFINF_OFFSET 0x0FFFFFFFL\n#define VQAFINF_FLAGS  0xF0000000L\n#define VQAFRAME_OFFSET(a) (((a & VQAFINF_OFFSET)<<1))\n\n/* VQ vector pointer codes. */\n#define VPC_ONE_SINGLE    0xF000 /* One single color block */\n#define VPC_ONE_SEMITRANS 0xE000 /* One semitransparent block */\n#define VPC_SHORT_DUMP    0xD000 /* Short dump of single color blocks */\n#define VPC_LONG_DUMP     0xC000 /* Long dump of single color blocks */\n#define VPC_SHORT_RUN     0xB000 /* Short run of single color blocks */\n#define VPC_LONG_RUN      0xA000 /* Long run */\n\n/* Long run codes. */\n#define LRC_SEMITRANS 0xC000 /* Long run of semitransparent blocks. */\n#define LRC_SINGLE    0x8000 /* Long run of single color blocks. */\n\n/* Defines used for Run-Skip-Dump compression. */\n#define MIN_SHORT_RUN_LENGTH  2\n#define MAX_SHORT_RUN_LENGTH  15\n#define MIN_LONG_RUN_LENGTH   2\n#define MAX_LONG_RUN_LENGTH   4095\n#define MIN_SHORT_DUMP_LENGTH 3\n#define MAX_SHORT_DUMP_LENGTH 15\n#define MIN_LONG_DUMP_LENGTH  2\n#define MAX_LONG_DUMP_LENGTH  4095\n\n#define WORD_HI_BIT 0x8000\n\n/*---------------------------------------------------------------------------\n * VQA FILE CHUNK ID DEFINITIONS.\n *-------------------------------------------------------------------------*/\n\n#define ID_WVQA MAKE_ID('W','V','Q','A') /* Westwood VQ Animation form. */\n#define ID_VQHD MAKE_ID('V','Q','H','D') /* VQ header. */\n#define ID_NAME MAKE_ID('N','A','M','E') /* Name string. */\n#define ID_FINF MAKE_ID('F','I','N','F') /* Frame information. */\n#define ID_VQFR MAKE_ID('V','Q','F','R') /* VQ frame container. */\n#define ID_VQFK MAKE_ID('V','Q','F','K') /* VQ key frame container. */\n#define ID_CBF0 MAKE_ID('C','B','F','0') /* Full codebook. */\n#define ID_CBFZ MAKE_ID('C','B','F','Z') /* Full codebook (compressed). */\n#define ID_CBP0 MAKE_ID('C','B','P','0') /* Partial codebook. */\n#define ID_CBPZ MAKE_ID('C','B','P','Z') /* Partial codebook (compressed). */\n#define ID_VPT0 MAKE_ID('V','P','T','0') /* Vector pointers. */\n#define ID_VPTZ MAKE_ID('V','P','T','Z') /* Vector pointers (compressed). */\n#define ID_VPTK MAKE_ID('V','P','T','K') /* Vector pointers (Delta Key). */\n#define ID_VPTD MAKE_ID('V','P','T','D') /* Vector pointers (Delta). */\n#define ID_VPTR MAKE_ID('V','P','T','R') /* Pointers RSD compressed. */\n#define ID_VPRZ MAKE_ID('V','P','R','Z') /* Pointers RSD, lcw compressed. */\n#define ID_CPL0 MAKE_ID('C','P','L','0') /* Color palette. */\n#define ID_CPLZ MAKE_ID('C','P','L','Z') /* Color palette (compressed). */\n#define ID_SND0 MAKE_ID('S','N','D','0') /* Sound */\n#define ID_SND1 MAKE_ID('S','N','D','1') /* Sound (Zap compressed). */\n#define ID_SND2 MAKE_ID('S','N','D','2') /* Sound (ADPCM compressed). */\n#define ID_SNDZ MAKE_ID('S','N','D','Z') /* Sound (LCW compression). */\n\n#define ID_SNA0 MAKE_ID('S','N','A','0') /* Sound */\n#define ID_SNA1 MAKE_ID('S','N','A','1') /* Sound (Zap compressed). */\n#define ID_SNA2 MAKE_ID('S','N','A','2') /* Sound (ADPCM compressed). */\n#define ID_SNAZ MAKE_ID('S','N','A','Z') /* Sound (LCW compression). */\n\n#define ID_CAP0 MAKE_ID('C','A','P','0') /* Caption text */\n\n#ifdef __WATCOMC__\n#pragma pack();\n#endif\n\n#endif /* VQAFILE_H */\n\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/VQAPLAY.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAPLAY_H\n#define VQAPLAY_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqaplay.h\n*\n* DESCRIPTION\n*      VQAPlay library definitions.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 10, 1995\n*\n****************************************************************************/\n\n/*---------------------------------------------------------------------------\n * CONDITIONAL COMPILATION FLAGS\n *-------------------------------------------------------------------------*/\n\n// MEG - 11.28.95 - added for debug\nextern void Debug_Printf( char *format_string, ... );\n\n#ifdef __WATCOMC__\n#define VQASTANDALONE 0  /* Stand alone player */\n#define VQAVOC_ON     0  /* Enable VOC file override */\n#define\tVQAMONO_ON    0  /* Mono display output enable/disable */\n#define VQAAUDIO_ON   0  /* Audio playback enable/disable */\n#define VQAVIDEO_ON   0  /* Video manager enable/disable */\n#define VQAMCGA_ON    1  /* MCGA enable/disable */\n#define VQAXMODE_ON   0  /* Xmode enable/disable */\n#define VQAVESA_ON    0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2  1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4  0  /* 4x4 block decode enable/disable */\n#define VQAWOOFER_ON  0\n#else\n#define VQASTANDALONE 0  /* Stand alone player */\n#define VQAVOC_ON     0  /* Enable VOC file override */\n#define\tVQAMONO_ON    1  /* Mono display output enable/disable */\n#define VQAAUDIO_ON   0  /* Audio playback enable/disable */\n#define VQAVIDEO_ON   0  /* Video manager enable/disable */\n#define VQAMCGA_ON    1  /* MCGA enable/disable */\n#define VQAXMODE_ON   0  /* Xmode enable/disable */\n#define VQAVESA_ON    0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2  1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4  0  /* 4x4 block decode enable/disable */\n#define VQAWOOFER_ON  0\n#endif\n\n\n/*---------------------------------------------------------------------------\n * GENERAL CONSTANT DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* Playback modes. */\n#define VQAMODE_RUN   0  /* Run the movie through the end. */\n#define VQAMODE_WALK  1  /* Draw the next frame then return. */\n#define VQAMODE_PAUSE 2  /* Suspend movie playback. */\n#define VQAMODE_STOP  3  /* Stop the movie. */\n\n/* Playback timer methods */\n#define VQA_TMETHOD_DEFAULT -1 /* Use default timer method. */\n#define\tVQA_TMETHOD_DOS      1 /* DOS timer method */\n#define\tVQA_TMETHOD_INT      2 /* Interrupt timer method */\n#define\tVQA_TMETHOD_AUDIO    3 /* Audio timer method */\n\n#define\tVQA_TIMETICKS 60 /* Clock ticks per second */\n\n/* Error/Status conditions */\n#define VQAERR_NONE      0  /* No error */\n#define\tVQAERR_EOF      -1  /* Valid end of file */\n#define VQAERR_OPEN     -2  /* Unable to open */\n#define\tVQAERR_READ     -3  /* Read error */\n#define VQAERR_WRITE    -4  /* Write error */\n#define VQAERR_SEEK     -5  /* Seek error */\n#define VQAERR_NOTVQA   -6  /* Not a valid VQA file. */\n#define VQAERR_NOMEM    -7  /* Unable to allocate memory */\n#define\tVQAERR_NOBUFFER -8  /* No buffer avail for load/draw */\n#define\tVQAERR_NOT_TIME -9  /* Not time for frame yet */\n#define\tVQAERR_SLEEPING -10 /* Function is in a sleep state */\n#define VQAERR_VIDEO    -11 /* Video related error. */\n#define VQAERR_AUDIO    -12 /* Audio related error. */\n#define VQAERR_PAUSED   -13 /* In paused state. */\n\n/* Event flags. */\n#define VQAEVENT_PALETTE (1<<0)\n#define VQAEVENT_SYNC    (1<<1)\n\n\n/*---------------------------------------------------------------------------\n * STRUCTURES AND RELATED DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* VQAConfig: Player configuration structure\n *\n * DrawerCallback - User routine for Drawer to call each frame (NULL = none)\n * EventHandler   - User routine for notification to client of events.\n * NotifyFlags    - User specified events to be notified about.\n * Vmode          - Requested Video mode (May be promoted).\n * VBIBit         - Vertical blank bit polarity.\n * ImageBuf       - Pointer to caller's buffer for the Drawer to use as its\n *                  ImageBuf; NULL = player will allocate its own, if\n *                  VQACFGF_BUFFER is set in DrawFlags.\n * ImageWidth     - Width of Image buffer.\n * ImageHeight    - Height of Image buffer.\n * X1             - Draw window X coordinate (-1 = Center).\n * Y1             - Draw window Y coordinate (-1 = Center).\n * FrameRate      - Desired frames per second (-1 = use VQA header's value).\n * DrawRate       - Desired drawing frame rate; allows the Drawer to draw at\n *                  a separate rate from the Loader.\n * TimerMethod    - Timer method to use during playback.\n * DrawFlags      - Bits control various special drawing options. (See below)\n * OptionFlags    - Bits control various special misc options. (See below)\n * NumFrameBufs   - Desired number of frame buffers. (Default = 6)\n * NumCBBufs      - Desired number of codebook buffers. (Default = 3)\n * VocFile        - Name of VOC file to play instead of VQA audio track.\n * AudioBuf       - Pointer to audio buffer.\n * AudioBufSize   - Size of audio buffer. (Default = 32768)\n * AudioRate      - Audio data playback rate (-1 = use samplerate scaled\n *                  to the frame rate)\n * Volume         - Audio playback volume. (0x7FFF = max)\n * HMIBufSize     - Desired HMI buffer size. (Default = 2000)\n * DigiHandle     - Handle to an initialized sound driver. (-1 = none)\n * DigiCard       - HMI ID of card to use. (0 = none, -1 = auto-detect)\n * DigiPort       - Audio port address. (-1 = auto-detect)\n * DigiIRQ        - Audio IRQ. (-1 = auto-detect)\n * DigiDMA        - Audio DMA channel. (-1 = auto-detect)\n * Language       - Language identifier. (Not used)\n * CapFont        - Pointer to font to use for subtitle text captions.\n */\ntypedef struct _VQAConfig {\n\tlong          (*DrawerCallback)(unsigned char *screen, long framenum);\n\tlong          (*EventHandler)(unsigned long event,void *buffer,long nbytes);\n\tunsigned long NotifyFlags;\n\tlong          Vmode;\n\tlong          VBIBit;\n\tunsigned char *ImageBuf;\n\tlong          ImageWidth;\n\tlong          ImageHeight;\n\tlong          X1,Y1;\n\tlong          FrameRate;\n\tlong          DrawRate;\n\tlong          TimerMethod;\n\tlong          DrawFlags;\n\tlong          OptionFlags;\n\tlong          NumFrameBufs;\n\tlong          NumCBBufs;\n\tchar          *VocFile;\n\tunsigned char *AudioBuf;\n\tlong          AudioBufSize;\n\tlong          AudioRate;\n\tlong          Volume;\n\tlong          HMIBufSize;\n\tlong          DigiHandle;\n\tlong          DigiCard;\n\tlong          DigiPort;\n\tlong          DigiIRQ;\n\tlong          DigiDMA;\n\tlong          Language;\n\tchar          *CapFont;\n} VQAConfig;\n\n/* Drawer Configuration flags (DrawFlags) */\n#define\tVQACFGB_BUFFER   0 /* Buffer UnVQ enable */\n#define\tVQACFGB_NODRAW   1 /* Drawing disable */\n#define VQACFGB_NOSKIP   2 /* Disable frame skipping. */\n#define\tVQACFGB_VRAMCB   3 /* XMode VRAM copy enable */\n#define VQACFGB_ORIGIN   4 /* 0,0 origin position */\n#define\tVQACFGB_SCALEX2  6 /* Scale X2 enable (VESA 320x200 to 640x400) */\n#define VQACFGB_WOOFER   7\n#define\tVQACFGF_BUFFER   (1<<VQACFGB_BUFFER)\n#define\tVQACFGF_NODRAW   (1<<VQACFGB_NODRAW)\n#define\tVQACFGF_NOSKIP   (1<<VQACFGB_NOSKIP)\n#define\tVQACFGF_VRAMCB   (1<<VQACFGB_VRAMCB)\n#define\tVQACFGF_ORIGIN   (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPLEFT  (0<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPRIGHT (1<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTRIGHT (2<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTLEFT  (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_SCALEX2  (1<<VQACFGB_SCALEX2)\n#define VQACFGF_WOOFER   (1<<VQACFGB_WOOFER)\n\n/* Options Configuration (OptionFlags) */\n#define\tVQAOPTB_AUDIO    0 /* Audio enable. */\n#define\tVQAOPTB_STEP     1 /* Single step enable. */\n#define\tVQAOPTB_MONO     2 /* Mono output enable. */\n#define VQAOPTB_PALOFF   3 /* Palette set disable. */\n#define\tVQAOPTB_SLOWPAL  4 /* Slow palette enable. */\n#define VQAOPTB_HMIINIT  5 /* HMI already initialized by client. */\n#define VQAOPTB_ALTAUDIO 6 /* Use alternate audio track. */\n#define VQAOPTB_CAPTIONS 7 /* Show captions. */\n#define\tVQAOPTF_AUDIO    (1<<VQAOPTB_AUDIO)\n#define\tVQAOPTF_STEP     (1<<VQAOPTB_STEP)\n#define\tVQAOPTF_MONO     (1<<VQAOPTB_MONO)\n#define VQAOPTF_PALOFF   (1<<VQAOPTB_PALOFF)\n#define\tVQAOPTF_SLOWPAL  (1<<VQAOPTB_SLOWPAL)\n#define VQAOPTF_HMIINIT  (1<<VQAOPTB_HMIINIT)\n#define\tVQAOPTF_ALTAUDIO (1<<VQAOPTB_ALTAUDIO)\n#define VQAOPTF_CAPTIONS (1<<VQAOPTB_CAPTIONS)\n\n\n/* VQAInfo: Information about the VQA movie.\n *\n * NumFrames   - The number of frames contained in the movie.\n * ImageHeight - Height of image in pixels.\n * ImageWidth  - Width of image in pixels.\n * ImageBuf    - Pointer to the image buffer VQA draw into.\n */\ntypedef struct _VQAInfo {\n\tlong NumFrames;\n\tlong ImageWidth;\n\tlong ImageHeight;\n\tunsigned char *ImageBuf;\n} VQAInfo;\n\n\n/* VQAStatistics: Statistics about the VQA movie played.\n *\n * StartTime     - Time movie started.\n * EndTime       - Time movie stoped.\n * FramesLoaded  - Total number of frames loaded.\n * FramesDrawn   - Total number of frames drawn.\n * FramesSkipped - Total number of frames skipped.\n * MaxFrameSize  - Size of largest frame.\n * SamplesPlayed - Number of sample bytes played.\n * MemUsed       - Total bytes used. (Low memory)\n */\ntypedef struct _VQAStatistics {\n\tlong          StartTime;\n\tlong          EndTime;\n\tlong          FramesLoaded;\n\tlong          FramesDrawn;\n\tlong          FramesSkipped;\n\tlong          MaxFrameSize;\n\tunsigned long SamplesPlayed;\n\tunsigned long MemUsed;\n} VQAStatistics;\n\n\n/* VQAHandle: VQA file handle. (Must be obtained by calling VQA_Alloc()\n *            and freed through VQA_Free(). This is the only legal way\n *            to obtain and dispose of a VQAHandle.\n *\n * VQAio - Something meaningful to the IO manager. (See DOCS)\n */\ntypedef struct _VQAHandle {\n\tunsigned long VQAio;\n} VQAHandle;\n\n/* Possible IO command values */\n#define VQACMD_INIT    1 /* Prepare the IO for a session */\n#define VQACMD_CLEANUP 2 /* Terminate IO session */\n#define VQACMD_OPEN    3 /* Open file */\n#define VQACMD_CLOSE   4 /* Close file */\n#define VQACMD_READ    5 /* Read bytes */\n#define VQACMD_WRITE   6 /* Write bytes */\n#define VQACMD_SEEK    7 /* Seek */\n\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n/* Configuration routines. */\nvoid VQA_INIConfig(VQAConfig *config);\nvoid VQA_DefaultConfig(VQAConfig *config);\n\n/* Handle manipulation routines. */\nVQAHandle *VQA_Alloc(void);\nvoid VQA_Free(VQAHandle *vqa);\nvoid VQA_Reset(VQAHandle *vqa);\nvoid VQA_InitAsDOS(VQAHandle *vqa);\nvoid VQA_Init(VQAHandle *vqa, long(*iohandler)(VQAHandle *vqa, long action,\n\t\tvoid *buffer, long nbytes));\nunsigned char *VQA_GetPalette(VQAHandle *vqa);\nlong VQA_GetPaletteSize(VQAHandle *vqa);\nvoid VQA_Set_DrawBuffer(VQAHandle *vqa, unsigned char *buffer,\n\t\tunsigned long width, unsigned long height,\n\t\tlong xpos, long ypos);\n\n/* File routines. */\nlong VQA_Open(VQAHandle *vqa, char const *filename, VQAConfig *config);\nvoid VQA_Close(VQAHandle *vqa);\nlong VQA_Play(VQAHandle *vqa, long mode);\nlong VQA_SeekFrame(VQAHandle *vqa, long frame, long fromwhere);\nlong VQA_SetStop(VQAHandle *vqa, long stop);\n\n/* Information/statistics access routines. */\nvoid VQA_GetInfo(VQAHandle *vqa, VQAInfo *info);\nvoid VQA_GetStats(VQAHandle *vqa, VQAStatistics *stats);\nchar *VQA_Version(void);\nchar *VQA_IDString(void);\n\n#endif /* VQAPLAY_H */\n\n\u001a"
  },
  {
    "path": "WINVQ/VQA32/OLD/VQAPLAY.I",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PROJECT\n;*     VQAPlay 32 library.\n;*\n;* FILE\n;*     vqaplay.i\n;*\n;* DESCRIPTION\n;*      VQA player definitions.\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 30, 1995\n;*\n;****************************************************************************\n\n;*---------------------------------------------------------------------------\n;* CONDITIONAL COMPILATION FLAGS\n;*---------------------------------------------------------------------------\n\n\tIF\tPHARLAP_TNT\n\nVQASTANDALONE\tEQU\t0\t;Stand alone player\nVQAMONO_ON\tEQU\t1\t;Mono display output enable/disable\nVQAAUDIO_ON\tEQU\t0\t;Audio playback enable/disable\nVQAVIDEO_ON\tEQU\t0\t;Video manager enable/disable\nVQAMCGA_ON\tEQU\t1\t;MCGA enable/disable\nVQAXMODE_ON\tEQU\t0\t;Xmode enable/disable\nVQAVESA_ON\tEQU\t0\t;VESA enable/disable\nVQABLOCK_2X2\tEQU\t0\t;2x2 block decode enable/disable\nVQABLOCK_2X3\tEQU\t0\t;2x3 block decode enable/disable\nVQABLOCK_4X2\tEQU\t1\t;4x2 block decode enable/disable\nVQABLOCK_4X4\tEQU\t0\t;4x4 block decode enable/disable\nVQABLOCK_WOOFER\tEQU\t0\n\n\tELSE\n\nVQASTANDALONE\tEQU\t0\t;Stand alone player\nVQAMONO_ON\tEQU\t0\t;Mono display output enable/disable\nVQAAUDIO_ON\tEQU\t1\t;Audio playback enable/disable\nVQAVIDEO_ON\tEQU\t0\t;Video manager enable/disable\nVQAMCGA_ON\tEQU\t1\t;MCGA enable/disable\nVQAXMODE_ON\tEQU\t0\t;Xmode enable/disable\nVQAVESA_ON\tEQU\t0\t;VESA enable/disable\nVQABLOCK_2X2\tEQU\t0\t;2x2 block decode enable/disable\nVQABLOCK_2X3\tEQU\t0\t;2x3 block decode enable/disable\nVQABLOCK_4X2\tEQU\t1\t;4x2 block decode enable/disable\nVQABLOCK_4X4\tEQU\t0\t;4x4 block decode enable/disable\nVQABLOCK_WOOFER\tEQU\t0\n\n\tENDIF\n"
  },
  {
    "path": "WINVQ/VQA32/OLD/VQAPLAYP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAPLAYP_H\n#define VQAPLAYP_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqaplayp.h\n*\n* DESCRIPTION\n*     VQAPlay private library definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*     Bill Randolph\n*\n* DATE\n*     August 21, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\video.h>\n#include <vqm32\\soscomp.h>\n#include <vqm32\\captoken.h>\n#include \"vqafile.h\"\n#include \"vqaplay.h\"\n#include \"caption.h\"\n\n#if(VQAAUDIO_ON)\n#include \"sos.h\"\n#endif\n\n/*---------------------------------------------------------------------------\n * GENERAL CONSTANT DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* Internal library version. */\n#define VQA_VERSION \"2.42\"\n#define VQA_DATE    __DATE__\" \"__TIME__\n\n#define VQA_IDSTRING \"VQA32 \"VQA_VERSION\" (\"VQA_DATE\")\"\n#define VQA_REQUIRES \"VQM32 2.12 or better.\"\n\n/* Block dimensions macro and identifiers. */\n#define BLOCK_DIM(a,b) (((a&0xFF)<<8)|(b&0xFF))\n#define BLOCK_2X2 BLOCK_DIM(2,2)\n#define BLOCK_2X3 BLOCK_DIM(2,3)\n#define BLOCK_4X2 BLOCK_DIM(4,2)\n#define BLOCK_4X4 BLOCK_DIM(4,4)\n\n/* Memory limits */\n#define\tVQA_MAX_CBBUFS    10 /* Maximum number of codebook buffers */\n#define\tVQA_MAX_FRAMEBUFS 30 /* Maximum number of frame buffers */\n\n/* Special Constants */\n#define\tVQA_MASK_POINTER 0x8000 /* Pointer value to use for masking. */\n\n\n/*---------------------------------------------------------------------------\n * STRUCTURES AND RELATED DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* ChunkHeader: IFF chunk identifier header.\n *\n * id   - 4 Byte chunk id.\n * size - Size of chunk.\n */\ntypedef struct _ChunkHeader {\n\tunsigned long id;\n\tunsigned long size;\n} ChunkHeader;\n\n\n/* ZAPHeader: ZAP audio compression header. NOTE: If the uncompressed size\n *            and the compressed size are equal then the audio frame is RAW\n *            (NOT COMPRESSED).\n *\n * UnCompSize - Uncompressed size in bytes.\n * CompSize   - Compressed size in bytes.\n */\ntypedef struct _ZAPHeader {\n\tunsigned short UnCompSize;\n\tunsigned short CompSize;\n} ZAPHeader;\n\n\n/* VQACBNode: A circular list of codebook buffers, used by the load task.\n *            If the data is compressed, it is loaded into the end of the\n *            buffer and the compression flags is set. Otherwise the data\n *            is loaded into the start of the buffer.\n *            (Make sure this structure's size is always DWORD aligned.)\n *\n * Buffer   - Pointer to Codebook data.\n * Next     - Pointer to next VQACBNode in the codebook list.\n * Flags    - Used by the drawer to tell if certain operations have been\n *            performed on this codebook, such as downloading to VRAM,\n *            or pre-scaling it. This field is cleared by the Loader when a\n *            new codebook is loaded.\n * CBOffset - Offset into the buffer of the compressed data.\n */\ntypedef struct _VQACBNode {\n\tunsigned char     *Buffer;\n\tstruct _VQACBNode *Next;\n\tunsigned long     Flags;\n\tunsigned long     CBOffset;\n} VQACBNode;\n\n/* VQACBNode flags */\n#define\tVQACBB_DOWNLOADED 0 /* Download codebook to VRAM (XMODE VRAM) */\n#define VQACBB_CBCOMP     1 /* Codebook is compressed */\n#define\tVQACBF_DOWNLOADED (1<<VQACBB_DOWNLOADED)\n#define\tVQACBF_CBCOMP     (1<<VQACBB_CBCOMP)\n\n\n/* VQAFrameNode: A circular list of frame buffers, filled in by the load\n *               task. If the data is compressed, it is loaded into the end\n *               of the buffer and the compress flag is set. Otherwise, it's\n *               loaded into the start of the buffer.\n *               (Make sure this structure's size is always DWORD aligned.)\n *\n * Pointers    - Pointer to the vector pointer data.\n * Codebook    - Pointer to VQACBNode list entry for this frame.\n * Palette     - Pointer to an array of palette colors (R,G,B).\n * Next        - Pointer to the next entry in the Frame Buffer List.\n * Flags       - Inter-process communication flags for this frame (see below)\n *               set by Loader, cleared by Flipper.\n * FrameNum    - Number of this frame in the animation.\n * PtrOffset   - Offset into buffer of the compressed vector pointer data.\n * PalOffset   - Offset into buffer of the compressed palette data.\n * PaletteSize - Size of the palette for this frame (in bytes).\n */\ntypedef struct _VQAFrameNode {\n\tunsigned char        *Pointers;\n\tVQACBNode            *Codebook;\n\tunsigned char        *Palette;\n\tstruct _VQAFrameNode *Next;\n\tunsigned long        Flags; \n\tlong                 FrameNum;\n\tlong                 PtrOffset;\n\tlong                 PalOffset;\n\tlong                 PaletteSize;\n} VQAFrameNode;\n\n/* FrameNode flags */\n#define\tVQAFRMB_LOADED  0 /* Frame loaded */\n#define\tVQAFRMB_KEY     1 /* Key Frame (must be drawn) */\n#define\tVQAFRMB_PALETTE 2 /* Palette needs set */\n#define VQAFRMB_PALCOMP 3 /* Palette is compressed */\n#define VQAFRMB_PTRCOMP 4 /* Vector pointer data is compressed */\n#define\tVQAFRMF_LOADED  (1<<VQAFRMB_LOADED)\n#define\tVQAFRMF_KEY     (1<<VQAFRMB_KEY)\n#define\tVQAFRMF_PALETTE (1<<VQAFRMB_PALETTE)\n#define\tVQAFRMF_PALCOMP (1<<VQAFRMB_PALCOMP)\n#define\tVQAFRMF_PTRCOMP (1<<VQAFRMB_PTRCOMP)\n\n\n/* VQALoader: Data needed exclusively by the Loader.\n *            (Make sure this structure's size is always DWORD aligned.)\n *\n * CurCB         - Pointer to the current codebook node to load data into.\n * FullCB        - Pointer to the last fully-loaded codebook node.\n * CurFrame      - Pointer to the current frame node to load data into.\n * NumPartialCB  - Number of partial codebooks accumulated.\n * PartialCBSize - Size of partial codebook (LCW'd or not), in bytes\n * CurFrameNum   - The number of the frame being loaded by the Loader.\n * LastCBFrame   - Last frame in the animation that contains a partial CB\n * LastFrameNum  - Number of the last loaded frame\n * WaitsOnDrawer - Number of wait states Loader hits waiting on the Drawer\n * WaitsOnAudio  - Number of wait states Loader hits waiting on HMI\n * FrameSize     - Size of the last frame in bytes.\n * MaxFrameSize  - Size of the largest frame in the animation.\n * CurChunkHdr   - Chunk header of the chunk currently being processed.\n */\ntypedef struct _VQALoader {\n\tVQACBNode    *CurCB;\n\tVQACBNode    *FullCB;\n\tVQAFrameNode *CurFrame;\n\tlong         NumPartialCB;\n\tlong         PartialCBSize;\n\tlong         CurFrameNum;\n\tlong         LastCBFrame;\n\tlong         LastFrameNum;\n\tlong         WaitsOnDrawer;\n\tlong         WaitsOnAudio;\n\tlong         FrameSize;\n\tlong         MaxFrameSize;\n\tChunkHeader  CurChunkHdr;\n} VQALoader;\n\n\n/* VQADrawer: Data needed exclusively by the Drawer.\n *            (Make sure this structure's size is always DWORD aligned.)\n *\n * CurFrame       - Pointer to the current frame to draw.\n * Flags          - Flags for the draw routines (IE: VQADRWF_SETPAL)\n * Display        - Pointer to DisplayInfo structure for active video mode.\n * ImageBuf       - Buffer to un-vq into, must be DWORD aligned.\n * ImageWidth     - Width of Image buffer (in pixels).\n * ImageHeight    - Height of Image buffer (in pixels).\n * X1,Y1,X2,Y2    - Coordinates of image corners (in pixels).\n * ScreenOffset   - Offset into screen memory, for centering small images.\n * CurPalSize     - Size of the current palette in bytes.\n * Palette_24     - Copy of the last-loaded palette\n * Palette_15     - 15-bit version of Palette_24, for 32K-color modes\n * BlocksPerRow   - # of VQ blocks per row for this resolution/block width.\n * NumRows        - # of rows of VQ blocks for this resolution/block height.\n * NumBlocks      - Total number of blocks in the image.\n * MaskStart      - Pointer index of start of mask rectangle.\n * MaskWidth      - Width of mask rectangle, in blocks.\n * MaskHeight     - Height of mask rectangle, in blocks.\n * LastTime       - The time when that last frame was drawn.\n * LastFrame      - The number of the last frame selected.\n * LastFrameNum   - Number of the last frame drawn.\n * DesiredFrame   - The number of the frame that should be drawn.\n * NumSkipped     - Number of frames skipped.\n * WaitsOnFlipper - Number of wait states Drawer hits waiting on the Flipper.\n * WaitsOnLoader  - Number of wait states Drawer hits waiting on the Loader.\n */\ntypedef struct _VQADrawer {\n\tVQAFrameNode  *CurFrame;\n\tunsigned long Flags;\n\tDisplayInfo   *Display;\n\tunsigned char *ImageBuf;\n\tlong          ImageWidth;\n\tlong          ImageHeight;\n\tlong          X1,Y1,X2,Y2;\n\tlong          ScreenOffset;\n\tlong          CurPalSize;\n\tunsigned char Palette_24[768];\n\tunsigned char Palette_15[512];\n\tlong          BlocksPerRow;\n\tlong          NumRows;\n\tlong          NumBlocks;\n\tlong          MaskStart;\n\tlong          MaskWidth;\n\tlong          MaskHeight;\n\tlong          LastTime;\n\tlong          LastFrame;\n\tlong          LastFrameNum;\n\tlong          DesiredFrame;\n\tlong          NumSkipped;\n\tlong          WaitsOnFlipper;\n\tlong          WaitsOnLoader;\n} VQADrawer;\n\n/* Drawer flags */\n#define\tVQADRWB_SETPAL 0  /* Set palette */\n#define\tVQADRWF_SETPAL (1<<VQADRWB_SETPAL)\n\n\n/* VQAFlipper: Data needed exclusively by the page-flipper.\n *             (Make sure this structure's size is always DWORD aligned.)\n *\n * CurFrame     - Pointer to current flipper frame.\n * LastFrameNum - Number of last flipped frame\n * pad          - DWORD alignment padding.\n */\ntypedef struct _VQAFlipper {\n\tVQAFrameNode *CurFrame;\n\tlong         LastFrameNum;\n} VQAFlipper;\n\n\n#if(VQAAUDIO_ON)\n\n#ifdef __WATCOMC__\n#pragma pack(4);\n#endif\n\n/* VQAAudio: Data needed exclusively by audio playback.\n *           (Make sure this structure's size is always DWORD aligned.)\n *\n * Buffer         - Pointer to the audio buffer.\n * AudBufPos      - Current audio buffer position, for copying data in buffer.\n * IsLoaded       - Inter-process communication flag:\n *                  0 = is loadable, 1 = is not. Loader sets it when it\n *                  loads, audio callback clears it when it plays one.\n * NumAudBlocks   - Number of HMI blocks in the audio buffer.\n * CurBlock       - Current audio block\n * NextBlock      - Next audio block\n * TempBuf        - Pointer to temp buffer for loading/decompressing audio\n *                  data.\n * TempBufLen     - Number of bytes loaded into temp buffer.\n * TempBufSize    - Size of temp buffer in bytes.\n * Flags          - Various audio flags. (See below)\n * PlayPosition   - HMI's current buffer position.\n * SamplesPlayed  - Total samples played.\n * NumSkipped     - Count of buffers missed.\n * SampleRate     - Recorded sampling rate of the track.\n * Channels       - Number of channels in the track.\n * BitsPerSample  - Bit resolution size of sample (8,16)\n * BytesPerSec    - Recorded data transfer for one second.\n * DigiHandle     - HMI digital device handle.\n * SampleHandle   - HMI sample handle.\n * DigiTimer      - HMI digital fill handler timer handle.\n * sSOSSampleData - HMI sample structure.\n * ADPCM_Info     - ADPCM decompression information structure.\n * DigiCaps       - HMI sound card digital capabilities.\n * DigiHardware   - HMI sound card digital hardware settings.\n * sSOSInitDriver - HMI driver initialization structure.\n */\ntypedef struct _VQAAudio {\n\tunsigned char      *Buffer;\n\tunsigned long      AudBufPos;\n\tshort              *IsLoaded;\n\tunsigned long      NumAudBlocks;\n\tunsigned long      CurBlock;\n\tunsigned long      NextBlock;\n\tunsigned char      *TempBuf;\n\tunsigned long      TempBufLen;\n\tunsigned long      TempBufSize;\n\tunsigned long      Flags;\n\tunsigned long      PlayPosition;\n\tunsigned long      SamplesPlayed;\n\tunsigned long      NumSkipped;\n\tunsigned short     SampleRate;\n\tunsigned char      Channels;\n\tunsigned char      BitsPerSample;\n\tunsigned long      BytesPerSec;\n\tWORD               DigiHandle;\n\tWORD               SampleHandle;\n\tWORD               DigiTimer;\n\t_SOS_START_SAMPLE  sSOSSampleData;\n\t_SOS_COMPRESS_INFO ADPCM_Info;\n\t_SOS_CAPABILITIES  DigiCaps;\n\t_SOS_HARDWARE      DigiHardware;\n\t_SOS_INIT_DRIVER   sSOSInitDriver;\n} VQAAudio;\n\n/* Audio flags. */\n#define VQAAUDB_DIGIINIT  0  /* HMI digital driver initialized (2 bits) */\n#define VQAAUDB_TIMERINIT 2  /* HMI timer system initialized (2 bits) */\n#define VQAAUDB_HMITIMER  4  /* HMI timer callback initialized (2 bits) */\n#define VQAAUDB_ISPLAYING 6  /* Audio playing flag. */\n#define VQAAUDB_MEMLOCKED 30 /* Audio memory page locked. */\n#define VQAAUDB_MODLOCKED 31 /* Audio module page locked. */\n\n#define VQAAUDF_DIGIINIT  (3<<VQAAUDB_DIGIINIT)\n#define VQAAUDF_TIMERINIT (3<<VQAAUDB_TIMERINIT)\n#define VQAAUDF_HMITIMER  (3<<VQAAUDB_HMITIMER)\n#define VQAAUDF_ISPLAYING (1<<VQAAUDB_ISPLAYING)\n#define VQAAUDF_MEMLOCKED (1<<VQAAUDB_MEMLOCKED)\n#define VQAAUDF_MODLOCKED (1<<VQAAUDB_MODLOCKED)\n\n/* HMI device initialization conditions. (DIGIINIT, TIMERINIT, HMITIMER) */\n#define HMI_UNINIT  0  /* Unitialize state. */\n#define HMI_VQAINIT 1  /* VQA initialized */\n#define HMI_APPINIT 2  /* Application initialized */\n\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n\n#endif /* VQAAUDIO_ON */\n\n\n/* VQAData: This stucture contains all the data used for playing a VQA.\n *\n * Draw_Frame   - Pointer to the draw-frame routine for this video mode.\n * Page_Flip    - Pointer to the page flip function for this video mode.\n * UnVQ         - Pointer to the UnVQ routine for this vid mode & blk size.\n * FrameData    - Frame buffer circular list head.\n * CBData       - Codebook circular list head.\n * Audio        - Audio buffer\n * Loader       - Loader's data\n * Drawer       - Drawer's data\n * Flipper      - Flipper's data\n * Flags        - Flags used by the player.\n * Foff         - Pointer to frame offset table.\n * VBIBit       - Vertical blank bit polarity.\n * Max_CB_Size  - Maximum size of an uncompressed codebook\n * Max_Pal_Size - Maximum size of an uncompressed palette\n * Max_Ptr_Size - Maximum size of uncompressed pointer data\n * LoadedFrames - Number of frames loaded\n * DrawnFrames  - Number of frames drawn\n * StartTime    - Start time in VQA time ticks\n * EndTime      - Stop time in VQA time ticks\n * MemUsed      - Number of bytes allocated by VQA_AllocBuffers\n */\ntypedef struct _VQAData {\n\tlong (*Draw_Frame)(VQAHandle *vqa);\n\tlong (*Page_Flip)(VQAHandle *vqa);\n\n\t#ifndef PHARLAP_TNT\n\tvoid cdecl (*UnVQ)(unsigned char *codebook, unsigned char *pointers,\n\t\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\t\tunsigned long numrows, unsigned long bufwidth);\n\t#else\n\tvoid cdecl (*UnVQ)(unsigned char *codebook, unsigned char *pointers,\n\t\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\t\tunsigned long bufwidth);\n\t#endif\n\n\tVQAFrameNode  *FrameData;\n\tVQACBNode     *CBData;\n\n\t#if(VQAAUDIO_ON)\n\tVQAAudio      Audio;\n\t#endif\n\n\tVQALoader     Loader;\n\tVQADrawer     Drawer;\n\tVQAFlipper    Flipper;\n\tunsigned long Flags;\n\tlong          *Foff;\n\tlong          VBIBit;\n\tlong          Max_CB_Size;\n\tlong          Max_Pal_Size;\n\tlong          Max_Ptr_Size;\n\tlong          LoadedFrames;\n\tlong          DrawnFrames;\n\tlong          StartTime;\n\tlong          EndTime;\n\tlong          MemUsed;\n} VQAData;\n\n/* VQAData flags */\n#define VQADATB_UPDATE 0 /* Update the display. */\n#define VQADATB_DSLEEP 1 /* Drawer sleep state. */\n#define VQADATB_LSLEEP 2 /* Loader sleep state. */\n#define VQADATB_DDONE  3 /* Drawer done flag. (0 = done) */\n#define VQADATB_LDONE  4 /* Loader done flag. (0 = done) */\n#define VQADATB_PRIMED 5 /* Buffers are primed. */\n#define VQADATB_PAUSED 6 /* The player is paused. */\n#define VQADATF_UPDATE (1<<VQADATB_UPDATE)\n#define VQADATF_DSLEEP (1<<VQADATB_DSLEEP)\n#define VQADATF_LSLEEP (1<<VQADATB_LSLEEP)\n#define VQADATF_DDONE  (1<<VQADATB_DDONE)\n#define VQADATF_LDONE  (1<<VQADATB_LDONE)\n#define VQADATF_PRIMED (1<<VQADATB_PRIMED)\n#define VQADATF_PAUSED (1<<VQADATB_PAUSED)\n\n\n/* VQAHandleP: Private VQA file handle. Must be obtained by calling\n *             VQA_Alloc() and freed through VQA_Free(). This is the only\n *             legal way to obtain and dispose of a VQAHandle.\n *\n * VQAio     - Something meaningful to the IO manager. (See DOCS)\n * IOHandler - IO handler callback.\n * VQABuf    - Pointer to internal data buffers.\n * Config    - Configuration structure.\n * Header    - VQA header structure.\n * vocfh     - Override audiotrack file handle.\n */\ntypedef struct _VQAHandleP {\n\tunsigned long VQAio;\n\tlong          (*IOHandler)(VQAHandle *vqa, long action, void *buffer,\n\t                          long nbytes);\n\tVQAData       *VQABuf;\n\tVQAConfig     Config;\n\tVQAHeader     Header;\n\tlong          vocfh;\n\tCaptionInfo   *Caption;\n} VQAHandleP;\n\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n/* Loader/Drawer system. */\nlong VQA_LoadFrame(VQAHandle *vqa);\nvoid VQA_Configure_Drawer(VQAHandleP *vqap);\nlong User_Update(VQAHandle *vqa);\n\n/* Timer system. */\nlong VQA_StartTimerInt(VQAHandleP *vqap, long init);\nvoid VQA_StopTimerInt(VQAHandleP *vqap);\nvoid VQA_SetTimer(VQAHandleP *vqap, long time, long method);\nunsigned long VQA_GetTime(VQAHandleP *vqap);\nlong VQA_TimerMethod(void);\n\n/* Audio system. */\n#if(VQAAUDIO_ON)\nlong VQA_OpenAudio(VQAHandleP *vqap);\nvoid VQA_CloseAudio(VQAHandleP *vqap);\nlong VQA_StartAudio(VQAHandleP *vqap);\nvoid VQA_StopAudio(VQAHandleP *vqap);\nlong CopyAudio(VQAHandleP *vqap);\n#endif\n\n/* Debugging system. */\nvoid VQA_InitMono(VQAHandleP *vqap);\nvoid VQA_UpdateMono(VQAHandleP *vqap);\n\n#endif /* VQAPLAYP_H */\n\n"
  },
  {
    "path": "WINVQ/VQA32/SOS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sos.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DEFINED   \n#define  _SOS_DEFINED   \n#include \"sosdefs.h\"\n\n#pragma pack(4)\n \n// error definition for sound operating system  \n#define  _SOS_ERR          -1\n\n// number of drivers allowed to be open at one time\n#define  _SOS_MAX_DRIVERS  5\n\n// structure definition for the capabilities\ntypedef struct _tagCAPABILITIES\n{\n   BYTE  szDeviceName[ 32 ];  // device name\n   WORD  wDeviceVersion;      // device version\n   WORD  wBitsPerSample;      // bits per sound sample\n   WORD  wChannels;           // stereo/mono sound card\n   WORD  wMinRate;            // minimum rate\n   WORD  wMaxRate;            // maximum rate\n   WORD  wMixerOnBoard;       // board contains mixer\n   WORD  wMixerFlags;         // mixer capabilities\n   WORD  wFlags;              // miscellaneous flags   \n   short far * lpPortList;         // list of usable ports\n   short far * lpDMAList;          // list of usable dma channels\n   short far * lpIRQList;          // list of usable irq channels\n   short far * lpRateList;         // list of usable rates, -1 if any in min to max\n   WORD  fBackground;         // foreground or background driver\n   WORD  wDeviceID;           // ID for the device\n   WORD  wTimerID;            // ID for the timer\n   \n} _SOS_CAPABILITIES; \n\n// far pointer to the device capabilities structure\ntypedef _SOS_CAPABILITIES far *  LPSOSDEVICECAPS;\n\n// flag types for driver\n#define  _FLAGS_SIGNED              0x8000\n  \n// devices that can be loaded\n#define  _SOUND_BLASTER_8_MONO      0xe000\n#define  _SOUND_BLASTER_8_ST        0xe001\n#define  _SBPRO_8_ST                _SOUND_BLASTER_8_ST\n#define  _SBPRO_8_MONO              0xe00f\n#define  _SOUND_MASTER_II_8_MONO    0xe002\n#define  _MV_PAS_8_MONO             0xe003\n#define  _MV_PAS_16_MONO            0xe004\n#define  _MV_PAS_8_ST               0xe005\n#define  _MV_PAS_16_ST              0xe006\n#define  _ADLIB_GOLD_8_ST           0xe007\n#define  _ADLIB_GOLD_16_ST          0xe008\n#define  _ADLIB_GOLD_8_MONO         0xe009\n#define  _ADLIB_GOLD_16_MONO        0xe00a\n#define  _MICROSOFT_8_MONO          0xe00b\n#define  _MICROSOFT_8_ST            0xe00c\n#define  _MICROSOFT_16_MONO         0xe00d\n#define  _MICROSOFT_16_ST           0xe00e\n#define  _SOUND_SOURCE_8_MONO_PC    0xe010\n#define  _SOUND_SOURCE_8_MONO_TANDY 0xe011\n#define  _GENERAL_PORT_8_MONO       0xe012\n#define  _GENERAL_PORT_8_MONO_R     0xe013\n#define  _SIERRA_8_MONO             0xe014\n#define  _SB16_8_MONO               0xe015\n#define  _SB16_8_ST                 0xe016\n#define  _SB16_16_MONO              0xe017\n#define  _SB16_16_ST                0xe018\n#define  _ESS_AUDIODRIVE_8_MONO     0xe019\n#define  _ESS_AUDIODRIVE_8_ST       0xe01a\n#define  _ESS_AUDIODRIVE_16_MONO    0xe01b\n#define  _ESS_AUDIODRIVE_16_ST      0xe01c\n#define  _SOUNDSCAPE_8_MONO         0xe01d\n#define  _SOUNDSCAPE_8_ST           0xe01e\n#define  _SOUNDSCAPE_16_MONO        0xe01f\n#define  _SOUNDSCAPE_16_ST          0xe020\n#define  _RAP10_8_MONO              0xe021\n#define  _RAP10_16_MONO             0xe022\n#define  _GUS_8_MONO                0xe023\n#define  _GUS_8_ST                  0xe024\n#define  _GUS_16_MONO               0xe025\n#define  _GUS_16_ST                 0xe026\n#define  _GUS_MAX_8_MONO            0xe027\n#define  _GUS_MAX_8_ST              0xe028\n#define  _GUS_MAX_16_MONO           0xe029\n#define  _GUS_MAX_16_ST             0xe02a\n#define  _WAVEJAMMER_8_MONO         0xe02b\n#define  _WAVEJAMMER_8_ST           0xe02c\n#define  _WAVEJAMMER_16_MONO        0xe02d\n#define  _WAVEJAMMER_16_ST          0xe02e\n#define  _TEMPOCS_8_MONO            0xe02f\n#define  _TEMPOCS_8_ST              0xe030\n#define  _TEMPOCS_16_MONO           0xe031\n#define  _TEMPOCS_16_ST             0xe032\n#define  _WAVEJAMMERCD_8_MONO       0xe033\n#define  _WAVEJAMMERCD_8_ST         0xe034\n#define  _WAVEJAMMERCD_16_MONO      0xe035\n#define  _WAVEJAMMERCD_16_ST        0xe036\n#define  _SOUND_BLASTER_8_MONO_R    0xe050\n#define  _MICROSOFT_8_MONO_R        0xe051\n#define  _SOUND_MASTER_II_8_MONO_R  0xe052\n#define  _ADLIB_GOLD_8_MONO_R       0xe053\n#define  _MV_PAS_8_MONO_R           0xe054\n#define  _RAP10_8_MONO_R            0xe058\n#define  _RAP10_16_MONO_R           0xe059\n#define  _SB16_8_MONO_R             0xe05a\n#define  _SB16_8_ST_R               0xe05b\n#define  _SB16_16_MONO_R            0xe05c\n#define  _SB16_16_ST_R              0xe05d\n#define  _MV_PAS_16_MONO_R          0xe060\n#define  _SOUNDSCAPE_8_MONO_R       0xe061\n#define  _SOUNDSCAPE_8_ST_R         0xe062\n#define  _SOUNDSCAPE_16_MONO_R      0xe063\n#define  _SOUNDSCAPE_16_ST_R        0xe064\n#define  _ESS_AUDIODRIVE_8_MONO_R   0xe065\n#define  _ESS_AUDIODRIVE_8_ST_R     0xe066\n#define  _ESS_AUDIODRIVE_16_MONO_R  0xe067\n#define  _ESS_AUDIODRIVE_16_ST_R    0xe068\n#define  _SPEECH_THING_8_MONO       0xe090\n#define  _YAMAHA_8_MONO             0xe106\n#define  _INT_SPEAKER_8_MONO        0xe107\n\n// call indexes for the loadable drivers\nenum\n{ \n   _DRV_INIT,\n   _DRV_UNINIT,\n   _DRV_SETRATE,\n   _DRV_SETACTION,\n   _DRV_START,\n   _DRV_STOP,\n   _DRV_PAUSE,\n   _DRV_RESUME,\n   _DRV_CAPABILITIES,\n   _DRV_PLAY_FOREGROUND,\n   _DRV_GET_FILL_INFO, \n   _DRV_GET_CALL_FUNCTIONS,\n   _DRV_SET_CALL_FUNCTIONS\n};\n\n// fill info\ntypedef  struct   _tagFillInfo\n         {\n\n            LPSTR lpFillHandler;                   // pointer to fill handler\n            LPWORD lpDMAFillCount;                 // pointer to dma count\n            LPSTR lpSampleList;                    // pointer to sample list\n            LPWORD lpDMAMasterVolume;              // pointer to dma count\n\n         } _SOS_FILL_INFO;\n\n// caps info structure\ntypedef  struct   _tagCapsInfo\n         {\n\n            LPSTR    lpPortList;                   // pointer to port list\n            LPSTR    lpDMAList;                    // pointer to DMA list\n            LPSTR    lpIRQList;                    // pointer to IRQ list\n            LPSTR    lpRateList;                   // pointer to rate list\n\n         } _SOS_CAPS_INFO;\n\n// maximum number of available voice\n#define  _MAX_VOICES    32\n\n// structure definition\ntypedef  struct   _tagSAMPLE\n{\n   LPSTR    samplePtr;                 // pointer to data buffer\n   LPSTR    sampleData;                // pointer to active data\n   LPSTR    sampleLoopPtr;             // pointer for loop back\n\n   WORD     sampleLength;              // length of sample\n   WORD     sampleIndex;               // index into sample\n   WORD     sampleLoopLength;          // length of loop\n   \n   WORD     sampleBytesLeft;           // bytes left to play in sample\n\n   WORD     sampleLoopPoint;           // byte count for loop point\n   WORD     sampleLoopEndLength;       // length of remaining chunk\n\n   short    sampleFlags;               // control sample\n   short    sampleVolume;              // volume control\n   short    sampleID;                  // sample ID\n\n   short    sampleChannel;             // channel to play sample on\n   short    sampleLoopCount;           // loop count\n   short    sampleLastFill;            // last fill position\n   VOID ( far cdecl * sampleCallback )( WORD, WORD, WORD ); // callback function for sample\n\n   WORD     samplePitchAdd;\n   short    samplePitchFraction;\n\n   short    samplePort;                // port to use for non-dma digitized\n\n   WORD     sampleTotalBytes;\n   WORD     sampleByteLength;\n\n   short    samplePanLocation;\n   short    samplePanSpeed;\n   short    samplePanDirection;\n   short    samplePanStart;\n   short    samplePanEnd;\n   \n   short    sampleDelayBytes;\n   short    sampleDelayRepeat;\n   \n   WORD     sampleADPCMPredicted;\n   short    sampleADPCMIndex;\n\n   short    sampleRootNoteMIDI;   \n\n   WORD  sampleTemp1;   \n   \n} _SOS_SAMPLE;\n\n// enumeration for left or right channel\nenum\n{\n   _LEFT_CHANNEL,\n   _RIGHT_CHANNEL,\n   _CENTER_CHANNEL,\n   _INTERLEAVED\n};\n\n// enumeration for foreground and background\nenum\n{ \n   _FOREGROUND,\n   _BACKGROUND \n};\n\n// defines for the sample flags\n#define  _ACTIVE           0x8000\n#define  _LOOPING          0x4000\n#define  _FIRST_TIME       0x2000\n#define  _PENDING_RELEASE  0x1000\n#define  _CONTINUE_BLOCK   0x0800\n#define  _PITCH_SHIFT      0x0400\n#define  _PANNING          0x0200\n#define  _VOLUME           0x0100\n#define  _TRANSLATE16TO8   0x0080\n#define  _STAGE_LOOP       0x0040\n#define  _TRANSLATE8TO16   0x0020\n#define  _STEREOTOMONO     0x0010\n\n// defines for the wParam flags \n#define  _SINGLE_SAMPLE 0x01\n\n#define  _SOS_DCAPS_AUTO_REINIT     0x01\n#define  _SOS_DCAPS_MPU_401         0x02\n#define  _SOS_DCAPS_OPL2            0x04\n#define  _SOS_DCAPS_OPL3            0x08\n#define  _SOS_DCAPS_OPL4            0x10\n#define  _SOS_DCAPS_WAVETABLE       0x20\n#define  _SOS_DCAPS_DL_SAMPLES      0x40\n#define  _SOS_DCAPS_FIFO_DEVICE     0x80\n#define  _SOS_DCAPS_ENV_NEEDED      0x100\n#define  _SOS_DCAPS_PSEUDO_DMA1     0x200\n#define  _SOS_DCAPS_SIGNED_DATA     0x8000\n\n// file header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // number of drivers in the file\n   WORD  wDrivers;\n\n   // offset of first driver\n   WORD  lOffset;\n\n   // size of the file\n   WORD  lFileSize;\n\n} _FILEHEADER;\n\n// driver header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // offset of next driver\n   WORD  lNextDriver;\n\n   // size of current driver\n   WORD  wSize;\n\n   // id for the current device\n   WORD  wDeviceID;\n\n   // id for the type of DOS extender\n   WORD  wExtenderType;\n\n} _DRIVERHEADER;\n\n// device hardware information\ntypedef struct\n{\n   // port to be used\n   WORD  wPort;\n\n   // irq to use\n   WORD  wIRQ;\n\n   // dma channel to se\n   WORD  wDMA; \n  \n   // extra parameter\n   WORD  wParam;\n\n} _SOS_HARDWARE;\n\n// structure definition for start sample\ntypedef struct\n{\n   // pointer to sample\n   LPSTR lpSamplePtr;\n\n   // size of the sample\n   WORD  dwSampleSize;\n\n   // number of times to loop the sample -1 is infinite\n   WORD  wLoopCount;\n\n   // channel to play sample on\n   WORD  wChannel;\n\n   // volume to play sample at\n   WORD wVolume;\n\n   // id for the sample\n   WORD  wSampleID;\n\n   // far pointer to the callback function\n   VOID ( far cdecl *lpCallback )( WORD, WORD, WORD );\n\n   // port to use if driver is a non-dma background driver\n   WORD  wSamplePort; \n\n   // flags field\n   WORD  wSampleFlags;\n\n   // total length of sample including loops, etc..\n   WORD     dwSampleByteLength;\n\n   // loop point for the sample\n   WORD  dwSampleLoopPoint;\n   WORD  dwSampleLoopLength;\n\n   // pitch shifting components \n   WORD     dwSamplePitchAdd;\n   WORD    wSamplePitchFraction;\n\n   // pan components\n   WORD    wSamplePanLocation;\n   WORD    wSamplePanSpeed;\n   WORD    wSamplePanDirection;\n   WORD    wSamplePanStart;\n   WORD    wSamplePanEnd;\n   \n   // delay parts\n   WORD    wSampleDelayBytes;\n   WORD    wSampleDelayRepeat;\n\n   // compression components   \n   WORD     dwSampleADPCMPredicted;\n   WORD    wSampleADPCMIndex;\n\n   // root note for pitch shifting \n   WORD    wSampleRootNoteMIDI;   \n\n   // filler for future upgrades\n   WORD  dwSampleTemp1;   \n   WORD  dwSampleTemp2;   \n   WORD  dwSampleTemp3;   \n\n} _SOS_START_SAMPLE;\n\n// structure for initializing a driver\ntypedef struct\n{  \n   WORD  wBufferSize;\n   LPSTR lpBuffer;\n   BOOL  wAllocateBuffer;\n   WORD  wSampleRate;\n   WORD  wParam;\n   LONG  dwParam;\n   VOID ( far *lpFillHandler )( VOID );\n   LPSTR lpDriverMemory;\n   LPSTR lpDriverMemoryCS;\n   LPSTR lpTimerMemory;\n   LPSTR lpTimerMemoryCS;\n   WORD  wTimerID;\n   WORD  wPhysical;\n\n} _SOS_INIT_DRIVER;\n\n// define for the timer types to use\n#define  _SOS_NORMAL_TIMER          0x00\n\n// enumeration for the timer types\nenum\n{\n   _TIMER_8_MONO   =     0x1000,\n   _TIMER_8_ST,          \n   _TIMER_16_MONO,       \n   _TIMER_16_ST,         \n   _TIMER_8_MONO_ULAW,  \n   _TIMER_8_ST_ULAW,    \n   _TIMER_16_MONO_ULAW, \n   _TIMER_16_ST_ULAW,   \n   _TIMER_8_MONO_REC,   \n   _TIMER_8_MONO_ULAW_REC,\n   _TIMER_UNDEFINED_1,      \n   _TIMER_UNDEFINED_2,\n   _TIMER_UNDEFINED_3,\n   _TIMER_UNDEFINED_4,\n   _TIMER_UNDEFINED_5,\n   _TIMER_UNDEFINED_6,\n   _TIMER_UNDEFINED_7,\n   _TIMER_UNDEFINED_8,\n   _TIMER_UNDEFINED_9,\n   _TIMER_UNDEFINED_A,\n   _TIMER_UNDEFINED_B,\n   _TIMER_UNDEFINED_C,\n   _TIMER_UNDEFINED_D,\n   _TIMER_UNDEFINED_E,\n   _TIMER_UNDEFINED_F,\n   _TIMER_UNDEFINED_10,\n   _TIMER_UNDEFINED_11,\n   _TIMER_UNDEFINED_12,\n   _TIMER_UNDEFINED_13,\n   _TIMER_UNDEFINED_14,\n   _TIMER_UNDEFINED_15,\n   _TIMER_UNDEFINED_16,\n   _TIMER_8_SOUND_SOURCE,\n   _TIMER_8_SOUND_SOURCE_TANDY,\n   _TIMER_8_GENERAL_PORT,\n   _TIMER_8_GENERAL_PORT_REC   \n};\n\n// define for no slots available\n#define  _ERR_NO_SLOTS ( WORD )-1\n\n// error codes for the system\nenum\n{\n   _ERR_NO_ERROR,\n   _ERR_DRIVER_NOT_LOADED,\n   _ERR_INVALID_POINTER,\n   _ERR_DETECT_INITIALIZED,\n   _ERR_FAIL_ON_FILE_OPEN,\n   _ERR_MEMORY_FAIL,\n   _ERR_INVALID_DRIVER_ID,\n   _ERR_NO_DRIVER_FOUND,\n   _ERR_DETECTION_FAILURE,\n   _ERR_DRIVER_LOADED,\n   _ERR_INVALID_HANDLE,\n   _ERR_NO_HANDLES,\n   _ERR_PAUSED,   \n   _ERR_NOT_PAUSED,\n   _ERR_INVALID_DATA,\n   _ERR_DRV_FILE_FAIL,\n   _ERR_INVALID_PORT,\n   _ERR_INVALID_IRQ,\n   _ERR_INVALID_DMA,\n   _ERR_INVALID_DMA_IRQ\n};   \n\n// maximum number of timer events that can be registered \n#define  _TIMER_MAX_EVENTS    0x10  \n\n// flags for the debugging system\n#define  _SOS_DEBUG_NORMAL       0x0000\n#define  _SOS_DEBUG_NO_TIMER     0x0001\n#define  _SOS_TIMER_DPMI         0x0002\n\n// define for types of DOS extenders\n#define  _SOS_RATIONAL           0x8000\n#define  _SOS_FLASHTECK          0x4000\n\n// defines for the types of timers for different\n// dos extenders\n#define  _SOS_TIMER_NEAR         0x8000\n#define  _SOS_TIMER_FAR          0x4000\n \n// values for callback information\nenum\n{\n   _SAMPLE_PROCESSED,\n   _SAMPLE_LOOPING,\n   _SAMPLE_DONE\n};\n\n// define for special 18.2 callback rate to dos\n#define  _TIMER_DOS_RATE   0xff00\n\n#pragma pack()\n\n#pragma aux int_3 = \"int 3\"\n \n#pragma pack( 1 ) \ntypedef struct\n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned       segment;\n\tunsigned short\tnumber_available;\n\tunsigned short number_used;\n\tunsigned       page0;\n\n} EVDS_STRUCT;\n\ntypedef struct \n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned short segment;\n\tunsigned short\tID;\n\tunsigned       physical;\n\n} VDS_STRUCT;\n\n#pragma pack() \n\n#include \"sosdata.h\"\n#include \"sosfnct.h\"\n\n#endif\n"
  },
  {
    "path": "WINVQ/VQA32/SOSDATA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdata.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DATA\n#define  _SOS_DATA\n\n#include <stddef.h>\n\n#pragma pack(4) \nextern   WORD     _sosDIGIData_Start;\nextern   WORD     _sosDIGIData_End;\nextern   WORD     _wSOSDriverLinear[];\nextern   WORD     _wSOSTimerLinear[];\nextern   LPSTR    _lpSOSDriver[];\nextern   LPSTR    _lpSOSTimer[];\nextern   LPSTR    _lpSOSDriverCS[];\nextern   LPSTR    _lpSOSTimerCS[];\nextern   BOOL     _wSOSDriverLoaded[];\nextern   BOOL     _wSOSTimerLoaded[];\nextern   BOOL     _wSOSDriverInitialized[];\nextern   WORD     _wSOSOutputRate[];\nextern   WORD     _wSOSDMABuffersize[];\nextern   LONG     _dwSOSDMABufferPhysical[];\nextern   LPSTR    _lpSOSDMABuffer[];\nextern   BOOL     _wTimerUsed;\nextern   VOID ( far *_lpSOSFillHandler[] )( VOID );\nextern   WORD     _wSOSTimerType[];\nextern   WORD     _wSOSDriverType[];\nextern   _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ];\nextern   LPWORD      _lpSOSDMAIrqCount[];\nextern   LPWORD      _lpSOSDMAFillCount[];\nextern   WORD        _wSOSTmrNextCount;\nextern   VOID ( interrupt far *_lpSOSOldTimer )( VOID );\nextern   WORD     _wSOSDriverID[];\nextern   _SOS_CAPABILITIES _sSOSDriverCaps[];\nextern   WORD        _wSOSDMAPortList[];\nextern   BYTE        _bSOSDMAChannel[];\nextern   _SOS_INIT_DRIVER     _sSOSDIGIInitDriver[];\nextern   BYTE  _pSOSDriverPath[];\nextern   BYTE  _pSOSTempDriverPath[];\nextern   BOOL  _wTIMERUsed;\nextern   WORD  _wTIMERValue;\nextern   VOID ( far * _lpTIMEREvents[] )( VOID );\nextern   WORD _wTIMEREventRate[];\nextern   WORD _dwTIMEREventFraction[];\nextern   WORD _dwTIMEREventFractionCurrent[];\nextern   BYTE  _bSOSMIDITimerSongHandler[];\nextern   BYTE  _bSOSMIDISongHandle;\nextern   WORD  _wSOSTimerMemHandle[];\nextern   WORD  _wSOSDriverMemHandle[];\nextern   WORD  _wSOSRealSeg[];\n\nextern   _FILEHEADER    _sDETFileHeader;\nextern   _DRIVERHEADER  _sDETDriverHeader;\nextern   _FILEHEADER    sLOADFileHeader;\nextern   _DRIVERHEADER  sLOADDriverHeader;\nextern   BOOL           _wDETInitialized;\nextern   WORD           _wDETLinear;\nextern   LPSTR          _lpDETDriverBuffer;    \nextern   LPSTR          _lpDETDriverBufferCS;\nextern   WORD           _hDETFile;\nextern   DWORD          _dwDETDriverIndex;\nextern   WORD           _wDETDriverIndexCur;\nextern   WORD           _wDETMemHandle;\nextern   LPSOSDEVICECAPS _lpDETDeviceCaps;\nextern   _SOS_CAPABILITIES _sDETCaps;  \nextern   PSTR _pSOSErrorStrings[];\nextern   BOOL _wSOSBufferAllocated[];\nextern   BOOL _wSOSSystemInitialized;\nextern   VDS_STRUCT _sSOSVDSInfo;\nextern   _SOS_FILL_INFO _sSOSFillInfo;\nextern   WORD    _wSOSTimerEventIndex;\nextern   WORD  _wSOSTimerEntered;\nextern   WORD  _wSOSDriverSize[];\nextern   WORD  _wSOSTimerSize[];\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nextern   WORD  _sosDIGIData1_Start;\nextern   WORD  _sosDIGIData1_End;\nextern   WORD  _sosDIGIData2_Start;\nextern   WORD  _sosDIGIData2_End;\nextern   BYTE  _bTIMERInstalled;\nextern   BYTE  _bTIMERDPMI;\nextern   WORD  wDetectPort;\nextern   WORD  wDetectIRQ;\nextern   WORD  wDetectDMA;\nextern   WORD  wDetectParam;\n#ifdef __cplusplus\n}\n#endif \n\n#pragma pack()\n\n#endif\n\u001a\n"
  },
  {
    "path": "WINVQ/VQA32/SOSDEFS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdefs.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n\n#ifndef  _SOSDEFS_DEFINED\n#define  _SOSDEFS_DEFINED\n\n#undef   _TRUE\n#undef   _FALSE\n#undef   _NULL\nenum  \n      { \n         _FALSE, \n         _TRUE \n      };\n\n#define  _NULL  0\n\n#ifndef  VOID\n#define  VOID           void\n#endif\ntypedef  int            BOOL;\ntypedef  unsigned int   UINT;\ntypedef  unsigned char  BYTE;\ntypedef  unsigned       WORD;\n#ifndef  LONG\ntypedef  signed long    LONG;\n#endif\ntypedef  unsigned long  DWORD;\n\ntypedef  BYTE  *        PBYTE;\ntypedef  char near *    PSTR;\ntypedef  WORD  *        PWORD;\ntypedef  LONG  *        PLONG;\ntypedef  VOID  *        PVOID;\n\ntypedef  BYTE  far   *  LPBYTE;\ntypedef  BYTE  far   *  LPSTR;\ntypedef  WORD  far   *  LPWORD;\ntypedef  LONG  far   *  LPLONG;\ntypedef  VOID  far   *  LPVOID;\n\ntypedef  BYTE  huge  *  HPBYTE;\ntypedef  BYTE  huge  *  HPSTR;\ntypedef  WORD  huge  *  HPWORD;\ntypedef  LONG  huge  *  HPLONG;\ntypedef  VOID  huge  *  HPVOID;\n\ntypedef  unsigned       HANDLE;\n\n#endif\n\u001a\n"
  },
  {
    "path": "WINVQ/VQA32/SOSFNCT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosfnct.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_FUNCTIONS\n#define  _SOS_FUNCTIONS\n\n#pragma pack(4)\n\nWORD sosDIGILockMemory          (  VOID  );\nWORD sosDIGIUnLockMemory        (  VOID  );\nWORD sosDIGIInitSystem           (  LPSTR, WORD  );\nWORD sosDIGIUnInitSystem         (  VOID  );\nWORD sosDIGIInitDriver           (  WORD, _SOS_HARDWARE far *,\n                                    _SOS_INIT_DRIVER far *, WORD far *   );\nWORD sosDIGIUnInitDriver         (  WORD, BOOL, BOOL  );\nWORD sosDIGILoadDriver          (  WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD sosDIGIUnLoadDriver         (  WORD  );\nWORD sosDIGIGetDeviceCaps        (  WORD, LPSOSDEVICECAPS  );\n\n#ifdef PHARLAP\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#else\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#endif\n\nWORD sosDIGIStopSample           (  WORD, WORD  );\nWORD sosDIGISamplesPlaying       (  WORD  );\nBOOL sosDIGISampleDone           (  WORD, WORD  );\nBOOL sosDIGISampleFilling        (  WORD, WORD  );\nWORD sosDIGIStartSample          (  WORD, _SOS_START_SAMPLE far *  );\nWORD sosDIGIContinueSample       (  WORD, WORD, _SOS_START_SAMPLE far * );\n\n\nWORD  sosDIGIDetectInit          (  LPSTR  );\nWORD  sosDIGIDetectUnInit        (  VOID  );\nWORD  sosDIGIDetectFindHardware  (  WORD, _SOS_CAPABILITIES far *, WORD far * );\nWORD  sosDIGIDetectFindFirst     (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectFindNext      (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectGetSettings   (  _SOS_HARDWARE far *  );\nWORD  sosDIGIDetectGetCaps       (  WORD, _SOS_CAPABILITIES far *  );\nWORD  sosDIGIDetectVerifySettings(  _SOS_HARDWARE far *  );\nPSTR  sosGetErrorString          (  WORD  );\n\nWORD  sosDIGILoadTimer           (  WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD  sosDIGIUnLoadTimer         (  WORD  );\n\nWORD  sosTIMERRegisterEvent      ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle );\nWORD  sosTIMERInitSystem               (  WORD, WORD  );\nWORD  sosTIMERUnInitSystem             (  WORD  );\nWORD  sosTIMERSetRate                  (  WORD  );  \nWORD  sosTIMERRemoveEvent              (  WORD );\nWORD  sosTIMERAlterEventRate           (  WORD, WORD  );\nWORD  sosTIMERGetEventRate             (  WORD  );\nVOID far sosTIMEROldHandler            (  VOID  );\nVOID far sosTIMERHandler               (  VOID  );\n\n// functions in soscntl.c\nWORD  sosDIGISetSampleVolume     ( WORD, WORD, WORD );\nWORD  sosDIGIGetSampleVolume     ( WORD, WORD );\nWORD  sosDIGISetChannel          ( WORD, WORD, WORD );\nWORD  sosDIGIGetChannel          ( WORD, WORD );\nWORD  sosDIGIGetBytesProcessed   ( WORD, WORD );\nWORD  sosDIGIGetLoopCount        ( WORD, WORD );\nWORD  sosDIGISetPanLocation      ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanLocation      ( WORD, WORD );\nDWORD sosDIGISetPitch            ( WORD, WORD, DWORD );\nDWORD sosDIGIGetPitch            ( WORD, WORD );\nWORD  sosDIGIGetDMAPosition      ( WORD );\nWORD  sosDIGISetPanSpeed         ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanSpeed         ( WORD, WORD );\nWORD  sosDIGIGetSampleID         ( WORD, WORD );\nWORD  sosDIGIGetSampleHandle     ( WORD, WORD );\nWORD  sosDIGISetMasterVolume     ( WORD, WORD );\n#ifdef PHARLAP\nVOID  sosFreeVDSPage          ( unsigned short, unsigned short, DWORD );\nWORD  sosAllocVDSPage         ( unsigned short *, unsigned short *, DWORD * );\n#else\nWORD  sosAllocVDSPage            ( LPSTR *, WORD *, WORD * );\nVOID  sosFreeVDSPage             ( WORD, WORD, LONG );\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef PHARLAP\nextern   int   cdecl sosRealFree          ( int );\nextern   BOOL  cdecl  _sos_read( WORD, LPSTR, WORD, WORD * );\nextern   int   cdecl sosRealAlloc( int, int *, int * );\nextern   void  cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD );\nextern   int   cdecl sosGetCS( VOID );\nextern   int   cdecl sosGetES( VOID );\n#else\nextern   int   cdecl sosRealAlloc         ( int, int *, int * );\nextern   int   cdecl sosRealFree          ( int );\n#endif\n\n// sos driver functions\nextern   WORD  cdecl sosDRVLockMemory     ( DWORD, DWORD );\nextern   WORD  cdecl sosDRVUnLockMemory   ( DWORD, DWORD );\nextern   void  cdecl sosDRVGetCapsInfo    ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVGetCapsPtr     ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVInit           ( LPSTR, LPSTR, int, int, int, int, int, int );  \nextern   void  cdecl sosDRVStart          ( LPSTR, LPSTR, int, int );\nextern   void  cdecl sosDRVSetRate        ( LPSTR, LPSTR, int );\nextern   void  cdecl sosDRVSetAction      ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVStop           ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVUnInit         ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVGetFillInfo    ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * );\nextern   void  cdecl sosFillSampleStructs ( PSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVExist       ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVGetSettings ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR );\nextern   WORD  cdecl sosDIGIInitForWindows( WORD );\nextern   WORD  cdecl sosDIGIUnInitForWindows( WORD );\nextern   LPSTR cdecl sosAllocateFarMem      ( WORD, PSTR, WORD * );\nextern   LPSTR cdecl sosCreateAliasCS       ( LPSTR );\nextern   VOID  cdecl sosFreeSelector        ( LPSTR, DWORD );\nextern   LPSTR cdecl sosMAKEDOSPtr          ( PSTR );\nextern   VOID  cdecl sosDetDRVSetEnvString  ( DWORD, PSTR );\nextern   PSTR  cdecl sosDetDRVGetEnvString  ( DWORD );\nextern   VOID  cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR );\nextern   VOID  cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR );\nextern   WORD  cdecl sosDRVGetFreeMemory     ( VOID );\nextern   WORD  cdecl sosDRVAllocVDSStruct    ( WORD, WORD *, WORD * );\nextern   WORD  cdecl sosDRVFreeVDSStruct     ( WORD, WORD );\nextern   WORD  cdecl sosDRVIsWindowsActive   ( VOID );\nextern   WORD  cdecl sosDRVVDSGetBuffer    ( WORD );\nextern   WORD  cdecl sosDRVVDSFreeBuffer   ( WORD );\nextern   WORD  cdecl getDS( VOID );\nextern   WORD  cdecl sosDRVMakeDMASelector   ( WORD );  \nextern   WORD  cdecl sosDRVFreeDMASelector   ( WORD );  \n\n\nextern   void  cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) );\nextern   void  cdecl sosTIMERDRVUnInit( void );\nextern   void  cdecl sosTIMERDRVHandler( void );\nextern   void  cdecl sosTIMERDRVFHandler( void );\nextern   void  cdecl sosTIMERDRVEnable( void );\nextern   void  cdecl sosTIMERDRVDisable( void );\nextern   void  cdecl sosTIMERDRVCallOld( void );\nextern   void  cdecl sosTIMERDRVSetRate( WORD );    \nextern   void  cdecl sosDIGITimer_Start( void );\nextern   void  cdecl sosDIGITimer_End( void );\nextern   void  cdecl sosDIGIDrv_Start( void );\nextern   void  cdecl sosDIGIDrv_End( void );\n#ifdef __cplusplus\n}\n#endif \n\n// external functions for handling system initialization and \n// uninitialization\nWORD  sosEXDIGInitDriver               (  WORD, WORD, WORD, LPSTR,\n                                          _SOS_HARDWARE far *, WORD *  );\nWORD  sosEXDIGIUnInitDriver            (  VOID  );\n\nWORD  sosEXDETFindDriver               (  WORD, LPSTR, _SOS_HARDWARE far *,\n                                          _SOS_CAPABILITIES far *  );\n\n// memory locking prototypes\nVOID  sosDIGICaps_Start( VOID );\nVOID  sosDIGICaps_End( VOID );\nVOID  sosDIGIErr_Start( VOID );\nVOID  sosDIGIErr_End( VOID );\nVOID  sosDIGITmr_Start( VOID );\nVOID  sosDIGITmr_End( VOID );\nVOID  sosDIGIStart_Start( VOID );\nVOID  sosDIGIStart_End( VOID );\nVOID  sosDIGIPlyng_Start( VOID );\nVOID  sosDIGIPlyng_End( VOID );\nVOID  sosDIGIRate_Start( VOID );\nVOID  sosDIGIRate_End( VOID );\nVOID  sosDIGIDone_Start( VOID );\nVOID  sosDIGIDone_End( VOID );\nVOID  sosDIGIDetec_Start( VOID );\nVOID  sosDIGIDetec_End( VOID );\nVOID  sosDIGIInit_Start( VOID );\nVOID  sosDIGIInit_End( VOID );\nVOID  sosDIGILoad_Start( VOID );\nVOID  sosDIGILoad_End( VOID );\nVOID  sosDIGICntl_Start( VOID );\nVOID  sosDIGICntl_End( VOID );\n\n#pragma pack()\n\n#endif\n"
  },
  {
    "path": "WINVQ/VQA32/SOSRES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosres.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#define  _SOS_RESOURCE\n#ifndef  _SOS_RESOURCE\n#define  _SOS_RESOURCE\n\n// structure for resource file header\ntypedef struct\n{\n   // file version\n   WORD     wVersion;\n\n   // file size\n   LONG     dwFileSize;\n\n   // number of resources in file\n   WORD     wResCount;\n\n   // offset of resource data from top of file\n   LONG     dwResOffset;\n\n   // offset of sync track from top of file\n   LONG     dwSyncTrackOffset;\n\n}  _RES_FILE_HEADER;\n\n// structure for resource block header\ntypedef struct\n{\n   // resource id\n   WORD     wID;\n\n   // resource type\n   WORD     wResType;\n\n   // offset of next block\n   LONG     dwNextBlock; \n\n   // size of the current resource information\n   LONG     dwResSize;\n\n   // rate to play block at\n   WORD     wBlockRate;\n\n   // id for the sync track to use\n   WORD     wSyncTrackID;\n\n}  _RES_BLOCK_HEADER;\n\n// structure for sync mark tag\ntypedef struct _tagSYNCMARK\n{\n   // ID of the type of mark being used\n   WORD  wID;\n\n   // location in data of sync mark\n   LONG  dwSyncOffset;\n\n   // length of sync block\n   LONG  dwSyncSize;\n\n   // start sample data\n   _SOS_START_SAMPLE sampleData;\n    \n} _RES_SYNCMARK;\n\ntypedef union\n{\n   // structure for sync mark tag\n   _RES_SYNCMARK  syncMark; \n\n} _RES_TAG;\n\n// union for filter information for prepareWave\ntypedef union\n{\n   // filter type\n   WORD     wFilterID;\n\n   // structure for volume\n   struct   volume \n   {\n      WORD  wVolume;\n   };\n\n   // structure for delay\n   struct   delay\n   {  \n      WORD  wDelaySamples;\n   };\n\n} _SOS_FILTER; \n\n \n#endif\n\n\u001a"
  },
  {
    "path": "WINVQ/VQA32/TASK.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     task.c\n*\n* DESCRIPTION\n*     Loading and drawing delegation\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 25, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VQA_Alloc    - Allocate a VQAHandle to use.\n*     VQA_Free     - Free a VQAHandle.\n*     VQA_Init     - Initialize the VQAHandle IO.\n*     VQA_Play     - Play the VQA movie.\n*     VQA_SetStop  - Set the frame the player should stop on.\n*     VQA_GetInfo  - Get VQA movie information.\n*     VQA_GetStats - Get VQA movie statistics.\n*     VQA_Version  - Get VQA library version number.\n*     VQA_IDString - Get the VQA player library's ID string.\n*\n* PRIVATE\n*     VQA_IO_Task        - Loader task for multitasking.\n*     VQA_Rendering_Task - Drawer task for multitasking.\n*     User_Update        - Page flip routine called by the task interrupt.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <malloc.h>\n#include <dos.h>\n#include <mem.h>\n#include <conio.h>\n#include <sys\\timeb.h>\n#include <vqm32\\all.h>\n#include \"vqaplayp.h\"\n#include <vqm32\\font.h>\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n/* Externals */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern int __cdecl Check_Key(void);\nextern int __cdecl Get_Key(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Alloc - Allocate a VQAHandle to use.\n*\n* SYNOPSIS\n*     VQAHandle = VQA_Alloc()\n*\n*     VQAHandle *VQA_Alloc(void);\n*\n* FUNCTION\n*     Obtain a VQAHandle. This handle is used by most VQA library functions,\n*     and contains the current position in the file. This is the only legal\n*     way to obtain a VQAHandle.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     VQA - Handle of a VQA.\n*\n****************************************************************************/\n\nVQAHandle *VQA_Alloc(void)\n{\n\tVQAHandleP *vqa;\n\n\tif ((vqa = (VQAHandleP *)malloc(sizeof(VQAHandleP))) != NULL) {\n\t\tmemset(vqa, 0, sizeof(VQAHandleP));\n\t}\n\n\treturn ((VQAHandle *)vqa);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Free - Free a VQAHandle.\n*\n* SYNOPSIS\n*     VQA_Free(VQA)\n*\n*     void VQA_Free(VQAHandle *);\n*\n* FUNCTION\n*     Dispose of a VQAHandle. This is the only legal way to dispose of a\n*     VQAHandle.\n*\n* INPUTS\n*     VQA - Pointer to VQAHandle to dispose of.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Free(VQAHandle *vqa)\n{\n\tif (vqa) free(vqa);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Init - Initialize the VQAHandle IO handler.\n*\n* SYNOPSIS\n*     VQA_Init(VQA, IOHandler)\n*\n*     void VQA_Init(VQAHandle *, IOHandler *);\n*\n* FUNCTION\n*     Initialize the specified VQAHandle IO with the client provided custom\n*     IO handler.\n*\n* INPUTS\n*     VQA       - Pointer to VQAHandle to initialize.\n*     IOHandler - Pointer to custom file I/O handler function.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Init(VQAHandle *vqa, long(*iohandler)(VQAHandle *vqa, long action,\n\t\tvoid *buffer, long nbytes))\n{\n\t((VQAHandleP *)vqa)->IOHandler = iohandler;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Reset - Reset the VQAHandle.\n*\n* SYNOPSIS\n*     VQA_Reset(VQA)\n*\n*     void VQA_Reset(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - VQAHandle to reset.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_Reset(VQAHandle *vqa)\n{\n\tVQAData *vqabuf;\n\n\t/* Dereference data members for quick access */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\n\tvqabuf->Flags = 0;\n\tvqabuf->LoadedFrames = 0;\n\tvqabuf->DrawnFrames = 0;\n\tvqabuf->StartTime = 0;\n\tvqabuf->EndTime = 0;\n}\n\nint\tVQAMovieDone;\n/****************************************************************************\n*\n* NAME\n*     VQA_Play - Play the VQA movie.\n*\n* SYNOPSIS\n*     Error = VQA_Play(VQA, Mode)\n*\n*     long VQA_Play(VQAHandle *, long);\n*\n* FUNCTION\n*     Playback the movie associated with the specified VQAHandle.\n*\n* INPUTS\n*     VQA  - Pointer to handle of movie to play.\n*     Mode - Playback mode.\n*              VQAMODE_RUN   - Run the movie until completion.\n*              VQAMODE_WALK  - Walk the movie frame by frame.\n*              VQAMODE_PAUSE - Pause the movie.\n*              VQAMODE_STOP  - Stop the movie (Shutdown).\n*\n* RESULT\n*     Error - 0 if successful, or error code.\n*\n****************************************************************************/\n\nlong VQA_Play(VQAHandle *vqa, long mode)\n{\n\tVQAData   *vqabuf;\n\tVQAConfig *config;\n\tVQADrawer *drawer;\n\tlong      rc;\n\tlong      i;\n\tlong      key;\n\n#ifdef WIN32\n\tunsigned char *pal;\n\tlong          palsize;\n\tlong          slowpal;\n\tVQAFrameNode *curframe;\n\tint\t\t\tsetpalette;\n#endif\t//WIN32\n\n\n\n#ifdef WIN32\n\t/*\n\t** Save the process priority level then bump it up\n\t*/\n\tDWORD process_priority = GetPriorityClass(GetCurrentProcess());\n\tSetPriorityClass (GetCurrentProcess() , HIGH_PRIORITY_CLASS);\n#endif //WIN32\n\n\t/* Dereference commonly used data members for quick access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\tdrawer = &vqabuf->Drawer;\n\tconfig = &((VQAHandleP *)vqa)->Config;\n\n\t/* One time player priming. */\n\tif (!(vqabuf->Flags & VQADATF_PRIMED)) {\n\n\t\t/* Init the Drawer's configuration */\n\t\tVQA_Configure_Drawer((VQAHandleP *)vqa);\n\n\t\t/* If audio enabled & loaded, start playing */\n\t\t#if(VQAAUDIO_ON)\n\t\tif ((config->OptionFlags & VQAOPTF_AUDIO) && vqabuf->Audio.IsLoaded[0]) {\n\t\t\tVQA_StartAudio((VQAHandleP *)vqa);\n\t\t}\n\t\t#endif\n\n\t\t/* Initialize the timer */\n\t\ti = ((vqabuf->Drawer.CurFrame->FrameNum * VQA_TIMETICKS)\n\t\t\t\t/ config->DrawRate);\n\n\t\tVQA_SetTimer((VQAHandleP *)vqa, i, config->TimerMethod);\n\t\tvqabuf->StartTime = VQA_GetTime((VQAHandleP *)vqa);\n\n\t\t/* Set up the Mono screen */\n\t\t#if(VQAMONO_ON)\n\t\tif (config->OptionFlags & VQAOPTF_MONO) {\n\t\t\tVQA_InitMono((VQAHandleP *)vqa);\n\t\t}\n\t\t#endif\n\n\t\t/* Priming is complete. */\n\t\tvqabuf->Flags |= VQADATF_PRIMED;\n\t}\n\n\t/* Main Player Loop */\n\tswitch (mode) {\n\t\tcase VQAMODE_PAUSE:\n\t\t\tif ((vqabuf->Flags & VQADATF_PAUSED) == 0) {\n\t\t\t\tvqabuf->Flags |= VQADATF_PAUSED;\n\t\t\t\tvqabuf->EndTime = VQA_GetTime((VQAHandleP *)vqa);\n\n\t\t\t\t/* Stop the audio while the movie is paused. */\n\t\t\t\t#if(VQAAUDIO_ON)\n\t\t\t\tif (vqabuf->Audio.Flags & VQAAUDF_ISPLAYING) {\n\t\t\t\t\tVQA_StopAudio((VQAHandleP *)vqa);\n\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\trc = VQAERR_PAUSED;\n\t\t\tbreak;\n\n\t\tcase VQAMODE_RUN:\n\t\tcase VQAMODE_WALK:\n\t\tdefault:\n\n\t\t\t/* Start up the movie if is it currently paused. */\n\t\t\tif (vqabuf->Flags & VQADATF_PAUSED) {\n\t\t\t\tvqabuf->Flags &= ~VQADATF_PAUSED;\n\n\t\t\t\t/* Start the audio if it was previously on. */\n\t\t\t\t#if(VQAAUDIO_ON)\n\t\t\t\tif (config->OptionFlags & VQAOPTF_AUDIO) {\n\t\t\t\t\tif (VQA_StartAudio((VQAHandleP *)vqa) != 0){\n\n\t\t\t\t\t\t/* Stop audio, if it's playing. */\n\t\t\t\t\t\tVQA_StopAudio((VQAHandleP *)vqa);\n\t\t\t\t\t#ifdef WIN32\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Restore the process priority level\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tSetPriorityClass (GetCurrentProcess() , process_priority);\n\t\t\t\t\t#endif //WIN32\n\t\t\t\t\t\treturn (VQAERR_EOF);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\tVQA_SetTimer((VQAHandleP *)vqa, vqabuf->EndTime, config->TimerMethod);\n\t\t\t}\n\n\t\t\t/* Load, Draw, Load, Draw, Load, Draw ... */\n\t\t\twhile ((vqabuf->Flags & (VQADATF_DDONE|VQADATF_LDONE))\n\t\t\t\t\t!= (VQADATF_DDONE|VQADATF_LDONE)) {\n\n\t\t\t\t/* Load a frame */\n\t\t\t\tif (!(vqabuf->Flags & VQADATF_LDONE)) {\n\t\t\t\t\tif ((rc = VQA_LoadFrame(vqa)) == 0) {\n\t\t\t\t\t\tvqabuf->LoadedFrames++;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tif ((rc != VQAERR_NOBUFFER) && (rc != VQAERR_SLEEPING)) {\n\t\t\t\t\t\t\tvqabuf->Flags |= VQADATF_LDONE;\n\t\t\t\t\t\t\trc = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tVQAMovieDone++;\n\t\t\t\t}\n\n\n\t\t\t\t/* Draw a frame */\n\t\t\t\tif ((config->DrawFlags & VQACFGF_NODRAW) == 0) {\n\t\t\t\t\tif ((rc = (*(vqabuf->Draw_Frame))(vqa)) == 0) {\n\t\t\t\t\t\tvqabuf->DrawnFrames++;\n\t\t\t\t\t\trc = vqabuf->Drawer.LastFrameNum;\n\n\t\t\t\t\t\t#ifdef WIN32never\n\t\t\t\t\t\tcurframe = drawer->CurFrame;\n\t\t\t\t\t\tpal = curframe->Palette;\n\t\t\t\t\t\tpalsize = curframe->PaletteSize;\n\t\t\t\t\t\tslowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;\n\t\t\t\t\t\tif ((curframe->Flags & VQAFRMF_PALETTE)\n\t\t\t\t\t\t\t\t|| (drawer->Flags & VQADRWF_SETPAL)) {\n\t\t\t\t\t\t\tsetpalette = TRUE;\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tsetpalette = FALSE;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t#endif\n\n\t\t\t\t\t\tif (User_Update(vqa)) {\n\t\t\t\t\t\t\tvqabuf->Flags |= (VQADATF_DDONE|VQADATF_LDONE);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t#ifdef WIN32never\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Set the palette if neccessary\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (setpalette) {\n\t\t\t\t\t\t\tSetPalette(pal, palsize, slowpal);\n\t\t\t\t\t\t\tcurframe->Flags &= ~VQAFRMF_PALETTE;\n\t\t\t\t\t\t\tdrawer->Flags &= ~VQADRWF_SETPAL;\n \t\t\t\t\t\t}\n\t\t\t\t\t\t#endif\t//WIN32\n\n\t\t\t\t\t}else {\n\t\t\t\t\t\tif (rc==VQAERR_EOF) break;\n\t\t\t\t\t\tif ((vqabuf->Flags & VQADATF_LDONE)\t&& (rc == VQAERR_NOBUFFER)) {\n\t\t\t\t\t\t\tvqabuf->Flags |= VQADATF_DDONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tvqabuf->Flags |= VQADATF_DDONE;\n\t\t\t\t\tdrawer->CurFrame->Flags = 0L;\n\t\t\t\t\tdrawer->CurFrame = drawer->CurFrame->Next;\n\t\t\t\t}\n\n\t\t\t\t/* Update Mono output */\n\t\t\t\t#if(VQAMONO_ON)\n\t\t\t\tif (config->OptionFlags & VQAOPTF_MONO) {\n\t\t\t\t\tVQA_UpdateMono((VQAHandleP *)vqa);\n\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\tif (mode == VQAMODE_WALK) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t#if(VQASTANDALONE)\n\t\t\t\telse {\n\n\t\t\t\t\t/* Do single-stepping check. */\n\t\t\t\t\tif (config->OptionFlags & VQAOPTF_STEP) {\n\t\t\t\t\t\twhile ((key = Check_Key()) == 0);\n\t\t\t\t\t\tGet_Key();\n\n\t\t\t\t\t\t/* Escape key still quits. */\n\t\t\t\t\t\tif (key == 27) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Check for ESC */\n\t\t\t\t\tif ((key = Check_Key()) != 0) {\n\t\t\t\t\t\tmode = VQAMODE_STOP;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n\t/* If the movie is finished or we are requested to stop then shutdown. */\n\tif (((vqabuf->Flags & (VQADATF_DDONE|VQADATF_LDONE))\n\t\t\t== (VQADATF_DDONE|VQADATF_LDONE)) || (mode == VQAMODE_STOP)) {\n\n\t\t/* Record the end time; must be done before stopping audio, since we're\n\t\t * getting the elapsed time from the audio DMA position.\n\t\t */\n\t\tvqabuf->EndTime = VQA_GetTime((VQAHandleP *)vqa);\n\n\t\t/* Movie is finished. */\n\t\trc = VQAERR_EOF;\n\t}\n\n\t/* Stop audio, if it's playing. */\n\t#if(VQAAUDIO_ON)\n\tif (vqabuf->Audio.Flags & VQAAUDF_ISPLAYING) {\n\t\tVQA_StopAudio((VQAHandleP *)vqa);\n\t}\n\t#endif\n\n\n#ifdef WIN32\n\t/*\n\t** Restore the process priority level\n\t*/\n\tSetPriorityClass (GetCurrentProcess() , process_priority);\n#endif //WIN32\n\n\treturn (rc);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_SetStop - Set the frame the player should stop on.\n*\n* SYNOPSIS\n*     OldStop = VQA_SetStop(VQA, Frame)\n*\n*     long = VQA_SetStop(VQAHandle *, long);\n*\n* FUNCTION\n*     Set the frame that the player should stop on. This function will only\n*     work on movies that are already open.\n*\n* INPUTS\n*     VQA   - VQAHandle of movie to set the stop frame for.\n*     Frame - Frame number to stop on.\n*\n* RESULT\n*     OldStop - Previous stop frame. (-1 = invalid stop frame)\n*\n****************************************************************************/\n\nlong VQA_SetStop(VQAHandle *vqa, long stop)\n{\n\tlong      oldstop = -1;\n\tVQAHeader *header;\n\n\t/* Get a local pointer to the header. */\n\theader = &((VQAHandleP *)vqa)->Header;\n\n\tif ((stop > 0) && (header->Frames >= stop)) {\n\t\toldstop = header->Frames;\n\t\theader->Frames = stop;\n\t}\n\n\treturn (oldstop);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_GetInfo - Get VQA movie information.\n*\n* SYNOPSIS\n*     VQA_GetInfo(VQA, Info)\n*\n*     void VQA_GetInfo(VQAHandle *, VQAInfo *);\n*\n* FUNCTION\n*     Retrieve information about the opened movie.\n*\n* INPUTS\n*     VQA  - Pointer to VQAHandle of opened movie.\n*     Info - Pointer to VQAInfo structure to fill.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_GetInfo(VQAHandle *vqa, VQAInfo *info)\n{\n\tVQAHeader *header;\n\n\t/* Dereference header structure. */\n\theader = &((VQAHandleP *)vqa)->Header;\n\n\tinfo->NumFrames = header->Frames;\n\tinfo->ImageHeight = header->ImageHeight;\n\tinfo->ImageWidth = header->ImageWidth;\n\tinfo->ImageBuf = ((VQAHandleP *)vqa)->VQABuf->Drawer.ImageBuf;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_GetStats - Get VQA movie statistics.\n*\n* SYNOPSIS\n*     VQA_GetStats(VQA, Stats)\n*\n*     void VQA_GetStats(VQAHandle *, VQAStatistics *);\n*\n* FUNCTION\n*     Retrieve the statistics for the VQA movie.\n*\n* INPUTS\n*     VQA   - Handle of VQA movie to get statistics for.\n*     Stats - Pointer to VQAStatistics to fill.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VQA_GetStats(VQAHandle *vqa, VQAStatistics *stats)\n{\n\tVQAData *vqabuf;\n\n\t/* Dereference VQAData structure from VQAHandle */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\n\tstats->MemUsed = vqabuf->MemUsed;\n\tstats->StartTime = vqabuf->StartTime;\n\tstats->EndTime = vqabuf->EndTime;\n\tstats->FramesLoaded = vqabuf->LoadedFrames;\n\tstats->FramesDrawn = vqabuf->DrawnFrames;\n\tstats->FramesSkipped = vqabuf->Drawer.NumSkipped;\n\tstats->MaxFrameSize = vqabuf->Loader.MaxFrameSize;\n\n\t#if(VQAAUDIO_ON)\n\tstats->SamplesPlayed = vqabuf->Audio.SamplesPlayed;\n\t#else\n\tstats->SamplesPlayed = 0;\n\t#endif\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_Version - Get VQA library version number.\n*\n* SYNOPSIS\n*     Version = VQA_Version()\n*\n*     char *VQA_Version(void);\n*\n* FUNCTION\n*     Return the version of the VQA player library.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Version - Pointer to version number string.\n*\n****************************************************************************/\n\nchar *VQA_Version(void)\n{\n\treturn(VQA_VERSION);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     VQA_IDString - Get the VQA player library's ID string.\n*\n* SYNOPSIS\n*     IDString = VQA_IDString()\n*\n*     char *VQA_IDString(void);\n*\n* FUNCTION\n*     Return the ID string of this VQA player library.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     IDString - Pointer to ID string.\n*\n****************************************************************************/\n\nchar *VQA_IDString(void)\n{\n\treturn (VQA_IDSTRING);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     User_Update - Page flip routine called by the task interrupt.\n*\n* SYNOPSIS\n*     User_Update(VQA)\n*\n*     long User_Update(VQAHandle *);\n*\n* FUNCTION\n*\n* INPUTS\n*     VQA - Handle of VQA movie.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nlong User_Update(VQAHandle *vqa)\n{\n\tVQAData *vqabuf;\n\tlong    rc = 0;\n\n\t/* Dereference data members for quicker access. */\n\tvqabuf = ((VQAHandleP *)vqa)->VQABuf;\n\n\tif (vqabuf->Flags & VQADATF_UPDATE) {\n\n\t\t/* Invoke the page flip routine */\n\t\trc = (*(vqabuf->Page_Flip))(vqa);\n\n\t\t/* Update data for mono output */\n\t\tvqabuf->Flipper.LastFrameNum = vqabuf->Flipper.CurFrame->FrameNum;\n\n\t\t/* Mark the frame as loadable */\n\t\tvqabuf->Flipper.CurFrame->Flags = 0L;\n\t\tvqabuf->Flags &= (~VQADATF_UPDATE);\n\t}\n\n\treturn (rc);\n}\n\nvoid VQA_Dummy(void)\n{\n\tSet_Font(NULL);\n}\n"
  },
  {
    "path": "WINVQ/VQA32/TASM32.CFG",
    "content": "/t\n/m\n/w+\n/jJUMPS\n/ml\n/p\n/z\n/iC:\\PROJECTS\\INCLUDE\\VQM32\n/zi\n/dPHARLAP_TNT=1\n"
  },
  {
    "path": "WINVQ/VQA32/TLIB.CFG",
    "content": "/C /E\n"
  },
  {
    "path": "WINVQ/VQA32/TLINK32.CFG",
    "content": "/c\n/m\n/Gm\n-LC:\\PROJECTS\\LIB;C:\\DEV\\BC4\\LIB\n-v\n"
  },
  {
    "path": "WINVQ/VQA32/UNVQ.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAUNVQ_H\n#define VQAUNVQ_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQAPlay32 library. (32-Bit protected mode)\n*\n* FILE\n*     unvq.h\n*\n* DESCRIPTION\n*     VQ frame decompress definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Feburary 8, 1995\n*\n****************************************************************************/\n\n#ifdef PHARLAP_TNT\n#include <pltypes.h>\n#endif\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* unvqbuff.asm */\n#ifndef PHARLAP_TNT\nvoid __cdecl UnVQ_2x2(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\nvoid __cdecl UnVQ_2x3(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\nvoid __cdecl UnVQ_4x2(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\nvoid __cdecl UnVQ_4x4(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\nvoid __cdecl UnVQ_4x2_Woofer(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long bufwidth);\n\n/* unvqvesa.asm */\nvoid __cdecl UnVQ_4x2_VESA320_32K(unsigned char *codebook,\n\t\tunsigned char *pointers, unsigned char *palette,\n\t\tunsigned long grains_per_win,unsigned long dummy1,unsigned long dummy2);\n\n#else /* PHARLAP_TNT */\n\nvoid __cdecl UnVQ_2x2(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n\nvoid __cdecl UnVQ_2x3(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n\nvoid __cdecl UnVQ_4x2(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n\nvoid __cdecl UnVQ_4x4(unsigned char *codebook, unsigned char *pointers,\n\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\tunsigned long bufwidth);\n\n/* unvqvesa.asm */\nvoid __cdecl UnVQ_4x2_VESA320_32K(unsigned char *codebook,\n\t\tunsigned char *pointers, FARPTR palette, unsigned long grains_per_win,\n\t\tunsigned long dummy1, unsigned long dummy2);\n\n#endif /* PHARLAP_TNT */\n\n/* unvqxmde.asm */\nvoid __cdecl UnVQ_4x2_Xmode(unsigned char *codebook, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long dummy);\n\nvoid __cdecl UnVQ_4x2_XmodeCB(unsigned char *cbdummy, unsigned char *pointers,\n\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\tunsigned long numrows, unsigned long dummy);\n\nvoid __cdecl Upload_4x2CB(unsigned char *codebook, unsigned long numentries);\nvoid __cdecl XlatePointers(unsigned char *pointers, unsigned long numpointers);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQAUNVQ_H */\n"
  },
  {
    "path": "WINVQ/VQA32/UNVQBUFF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PROJECT\n;*     VQAPlay library.\n;*\n;* FILE\n;*     UnVQBuff.asm\n;*\n;* DESCRIPTION\n;*     Buffered VQ decompress/draw routines.\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     Feburary 8, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     UnVQ_2x2 - Draw 2x2 block VQ frame to a buffer.\n;*     UnVQ_2x3 - Draw 2x3 block VQ frame to a buffer.\n;*     UnVQ_4x2 - Draw 4x2 block VQ frame to a buffer.\n;*     UnVQ_4x4 - Draw 4x4 block VQ frame to a buffer.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"vga.i\"\n\tINCLUDE\t\"vesavid.i\"\n\tINCLUDE\t\"vqaplay.i\"\n\tCODESEG\n\nSKIP_PTR\tEQU\t8000h\n\n\n\tIF\tVQABLOCK_2X2\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_2x2 - Draw 2x2 block VQ frame to a buffer.\n;*\n;* SYNOPSIS\n;*     UnVQ_2x2(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n;*\n;*     void UnVQ_2x2(unsigned char *, unsigned char *, unsigned char *,\n;*                        unsigned short, unsigned short, unsigned short);\n;*\n;* FUNCTION\n;*     This function draws an image into the specified buffer from the\n;*     pointers and codebook provided. This routine has been optimized for\n;*     a 320x200 image.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook used to draw image.\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to buffer to draw image into.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*     BufWidth - Width of destination buffer in pixels.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC UnVQ_2x2:NEAR\n\tPROC\tUnVQ_2x2 C NEAR USES ebx ecx edx esi edi\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tARG\tbuffer:NEAR PTR\n\tENDIF\n\n\tARG\tblocksperrow:DWORD\n\tARG\tnumrows:DWORD\n\tARG\tbufwidth:DWORD\n\n\tLOCAL\tdata_end:DWORD\n\tLOCAL\tcb_offset:DWORD\n\tLOCAL\tedi_startval:DWORD\n\tLOCAL\trowoffset:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tmov\teax,[codebook]\t\t;Adjust the codebook address so\n\tsub\teax,4\t\t; that the pointer offsets will\n\tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n\tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n\tshl\teax,1\t\t; row of blocks.\n\tmov\t[rowoffset],eax\n\n\tmov\tesi,[pointers]\n\tmov\teax,[numrows]\t\t;Compute the end address of the\n\tmul\t[blocksperrow]\t\t; pointer data.\n\tshl\teax,1\n\tadd\teax,esi\n\tmov\t[data_end],eax\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tmov\tedi,[buffer]\n\tENDIF\n\n\tmov\t[edi_startval],edi\n\n;----------------------------------------------------------------------------\n;\tDrawing loop\n;----------------------------------------------------------------------------\n\n??Start_row:\n\tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n??Not_finished_a_line:\n\tsub\tebx,ebx\n\tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n\tadd\tesi,2\t\t; then advance to the next one.\n\n\tor\tbx,bx\t\t;Is it a one color block?\n\tjs\tshort ??One_color\n\n;\tDraw multi-color block\n\n\tadd\tebx,[cb_offset]\t;Codeword address\n\tmov\teax,[ebx]\t\t;Read codeword\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],ax\t\t;Write 1st row to dest\n\tELSE\n\tmov\t[edi],ax\t\t;Write 1st row to dest\n\tENDIF\n\n\tshr\teax,16\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],ax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi+ebx],ax\t\t;Write 2nd row to dest\n\tENDIF\n\n\n\tadd\tedi,2\t\t;Next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n;\tDraw 1-color block\n\n??One_color:\n\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n\tjne\t??Draw_One_Color\n\n\tadd\tedi,2\t\t;Move to next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Next_row\n\n??Draw_One_Color:\n\tnot\tbx\t\t;NOT pointer value to get color\n\tmov\tbh,bl\t\t;Duplicate color through the\n\tmov\tax,bx\t\t; entire dword register.\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],ax\t\t;Write 1st row to dest\n\tmov\t[es:edi+ebx],ax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi],ax\t\t;Write 1st row to dest\n\tmov\t[edi+ebx],ax\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tedi,2\t\t;Next dest block positionw\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n??Next_row:\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n??End_of_data:\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\n\tENDP\tUnVQ_2x2\n\tENDIF\t;VQABLOCK_2X2\n\n\n\tIF\tVQABLOCK_2X3\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_2x3 - Draw 2x3 block VQ frame to a buffer.\n;*\n;* SYNOPSIS\n;*     UnVQ_2x3(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n;*\n;*     void UnVQ_2x3(unsigned char *, unsigned char *, unsigned char *,\n;*                        unsigned short, unsigned short, unsigned short);\n;*\n;* FUNCTION\n;*     This function draws an image into the specified buffer from the\n;*     pointers and codebook provided. This routine has been optimized for\n;*     a 320x200 image.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook used to draw image.\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to buffer to draw image into.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*     BufWidth - Width of destination buffer in pixels.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC UnVQ_2x3:NEAR\n\tPROC\tUnVQ_2x3 C NEAR USES ebx ecx edx esi edi\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tARG\tbuffer:NEAR PTR\n\tENDIF\n\n\tARG\tblocksperrow:DWORD\n\tARG\tnumrows:DWORD\n\tARG\tbufwidth:DWORD\n\n\tLOCAL\tdata_end:DWORD\n\tLOCAL\tcb_offset:DWORD\n\tLOCAL\tedi_startval:DWORD\n\tLOCAL\trowoffset:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tmov\teax,[codebook]\t\t;Adjust the codebook address so\n\tsub\teax,4\t\t; that the pointer offsets will\n\tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n\tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n\tshl\teax,1\t\t; row of blocks.\n\tadd\teax,[bufwidth]\n\tmov\t[rowoffset],eax\n\n\tmov\tesi,[pointers]\n\tmov\teax,[numrows]\t\t;Compute the end address of the\n\tmul\t[blocksperrow]\t\t; pointer data.\n\tshl\teax,1\n\tadd\teax,esi\n\tmov\t[data_end],eax\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tmov\tedi,[buffer]\n\tENDIF\n\n\tmov\t[edi_startval],edi\n\n;----------------------------------------------------------------------------\n;\tDrawing loop\n;----------------------------------------------------------------------------\n\n??Start_row:\n\tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n??Not_finished_a_line:\n\tsub\tebx,ebx\n\tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n\tadd\tesi,2\t\t; then advance to the next one.\n\n\tor\tbx,bx\t\t;Is it a one color block?\n\tjs\tshort ??One_color\n\n;\tDraw multi-color block\n\n\tadd\tebx,[cb_offset]\t;Codeword address\n\tmov\teax,[ebx]\t\t;Read 1st row of codeword\n\tmov\tdx,[ebx+4]\t\t;Read 2nd row of codeword\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],ax\t\t;Write 1st row to dest\n\tELSE\n\tmov\t[edi],ax\t\t;Write 1st row to dest\n\tENDIF\n\n\tshr\teax,16\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],ax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi+ebx],ax\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],dx\n\tELSE\n\tmov\t[edi+ebx],dx\n\tENDIF\n\n\tadd\tedi,2\t\t;Next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n;\tDraw 1-color block\n\n??One_color:\n\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n\tjne\t??Draw_One_Color\n\n\tadd\tedi,2\t\t;Move to next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Next_row\n\n??Draw_One_Color:\n\tnot\tbx\t\t;NOT pointer value to get color\n\tmov\tbh,bl\t\t;Duplicate color through the\n\tmov\tax,bx\t\t; entire dword register.\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],ax\t\t;Write 1st row to dest\n\tmov\t[es:edi+ebx],ax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi],ax\t\t;Write 1st row to dest\n\tmov\t[edi+ebx],ax\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],ax\t;Write 2rd row to dest\n\tELSE\n\tmov\t[edi+ebx],ax\t\t;Write 2rd row to dest\n\tENDIF\n\n\tadd\tedi,2\t\t;Next dest block positionw\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n??Next_row:\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n??End_of_data:\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\n\tENDP\tUnVQ_2x3\n\tENDIF\t;VQABLOCK_2X3\n\n\n\tIF\tVQABLOCK_4X2\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x2 - Draw 4x2 block VQ frame to a buffer.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x2(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n;*\n;*     void UnVQ_4x2(unsigned char *, unsigned char *, unsigned char *,\n;*                        long, long, long);\n;*\n;* FUNCTION\n;*     This function draws an image into the specified buffer from the\n;*     pointers and codebook provided. This routine has been optimized for\n;*     a 320x200 image.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook used to draw image.\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to buffer to draw image into.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*     BufWidth - Width of destination buffer in pixels.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n;;;\tGLOBAL\tC UnVQ_4x2:NEAR\n;;;\tPROC\tUnVQ_4x2 C NEAR USES ebx ecx edx esi edi\n;;;\n;;;\tARG\tcodebook:NEAR PTR\n;;;\tARG\tpointers:NEAR PTR\n;;;\n;;;\tIF\tPHARLAP_TNT\n;;;\tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n;;;\tELSE\n;;;\tARG\tbuffer:NEAR PTR\n;;;\tENDIF\n;;;\n;;;\tARG\tblocksperrow:DWORD\n;;;\tARG\tnumrows:DWORD\n;;;\tARG\tbufwidth:DWORD\n;;;\n;;;\tLOCAL\tdata_end:DWORD\n;;;\tLOCAL\tcb_offset:DWORD\n;;;\tLOCAL\tedi_startval:DWORD\n;;;\tLOCAL\trowoffset:DWORD\n;;;\n;;;;----------------------------------------------------------------------------\n;;;;\tInitialize\n;;;;----------------------------------------------------------------------------\n;;;\n;;;\tmov\teax,[codebook]\t\t;Adjust the codebook address so\n;;;\tsub\teax,4\t\t; that the pointer offsets will\n;;;\tmov\t[cb_offset],eax\t; point directly at the codeword.\n;;;\n;;;\tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n;;;\tshl\teax,1\t\t; row of blocks.\n;;;\tmov\t[rowoffset],eax\n;;;\n;;;\tmov\tesi,[pointers]\n;;;\tmov\teax,[numrows]\t\t;Compute the end address of the\n;;;\tmul\t[blocksperrow]\t\t; pointer data.\n;;;\tshl\teax,1\n;;;\tadd\teax,esi\n;;;\tmov\t[data_end],eax\n;;;\n;;;\tIF\tPHARLAP_TNT\n;;;\tpush\tes\n;;;\tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n;;;\tELSE\n;;;\tmov\tedi,[buffer]\n;;;\tENDIF\n;;;\n;;;\tmov\t[edi_startval],edi\n;;;\n;;;;----------------------------------------------------------------------------\n;;;;\tDrawing loop\n;;;;----------------------------------------------------------------------------\n;;;\n;;;??Start_row:\n;;;\tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n;;;\n;;;??Not_finished_a_line:\n;;;\tsub\tebx,ebx\n;;;\tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n;;;\tadd\tesi,2\t\t; then advance to the next one.\n;;;\n;;;\tor\tbx,bx\t\t;Is it a one color block?\n;;;\tjs\tshort ??One_color\n;;;\n;;;;\tDraw multi-color block\n;;;\n;;;\tadd\tebx,[cb_offset]\t;Codeword address\n;;;\tmov\teax,[ebx]\t\t;Read 1st row of codeword\n;;;\tmov\tedx,[ebx+4]\t\t;Read 2nd row of codeword\n;;;\tmov\tebx,[bufwidth]\n;;;\n;;;\tIF\tPHARLAP_TNT\n;;;\tmov\t[es:edi],eax\t\t;Write 1st row to dest\n;;;\tmov\t[es:edi+ebx],edx\t;Write 2nd row to dest\n;;;\tELSE\n;;;\tmov\t[edi],eax\t\t;Write 1st row to dest\n;;;\tmov\t[edi+ebx],edx\t\t;Write 2nd row to dest\n;;;\tENDIF\n;;;\n;;;\tadd\tedi,4\t\t;Next dest block position\n;;;\tdec\tecx\t\t;More blocks for this row?\n;;;\tjnz\tshort ??Not_finished_a_line\n;;;\n;;;;\tAdvance to the next destination row of blocks.\n;;;\n;;;\tmov\tedi,[edi_startval]\n;;;\tadd\tedi,[rowoffset]\n;;;\tmov\t[edi_startval],edi\n;;;\n;;;\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n;;;\tjnb\tshort ??End_of_data\t; pointers buffer?\n;;;\tjmp\t??Start_row\n;;;\n;;;;\tDraw 1-color block\n;;;\n;;;??One_color:\n;;;\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n;;;\tjne\t??Draw_One_Color\n;;;\n;;;\tadd\tedi,4\t\t;Move to next dest block position\n;;;\tdec\tecx\t\t;More blocks for this row?\n;;;\tjnz\tshort ??Not_finished_a_line\n;;;\tjmp\t??Next_row\n;;;\n;;;??Draw_One_Color:\n;;;\tnot\tbx\t\t;NOT pointer value to get color\n;;;\tmov\tbh,bl\t\t;Duplicate color through the\n;;;\tmov\tax,bx\t\t; entire dword register.\n;;;\trol\teax,16\n;;;\tmov\tax,bx\n;;;\tmov\tebx,[bufwidth]\n;;;\n;;;\tIF\tPHARLAP_TNT\n;;;\tmov\t[es:edi],eax\t\t;Write 1st row to dest\n;;;\tmov\t[es:edi+ebx],eax\t;Write 2nd row to dest\n;;;\tELSE\n;;;\tmov\t[edi],eax\t\t;Write 1st row to dest\n;;;\tmov\t[edi+ebx],eax\t\t;Write 2nd row to dest\n;;;\tENDIF\n;;;\n;;;\tadd\tedi,4\t\t;Next dest block positionw\n;;;\tdec\tecx\t\t;More blocks for this row?\n;;;\tjnz\tshort ??Not_finished_a_line\n;;;\n;;;;\tAdvance to the next destination row of blocks.\n;;;\n;;;??Next_row:\n;;;\tmov\tedi,[edi_startval]\n;;;\tadd\tedi,[rowoffset]\n;;;\tmov\t[edi_startval],edi\n;;;\n;;;\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n;;;\tjnb\tshort ??End_of_data\t; pointers buffer?\n;;;\tjmp\t??Start_row\n;;;\n;;;??End_of_data:\n;;;\tIF\tPHARLAP_TNT\n;;;\tpop\tes\n;;;\tENDIF\n;;;\n;;;\tret\n;;;\n;;;\tENDP\tUnVQ_4x2\n;;;\tENDIF\t;VQABLOCK_4X2\n\n\tGLOBAL\tC UnVQ_4x2:NEAR\n\tPROC\tUnVQ_4x2 C NEAR USES ebx ecx edx esi edi\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\tARG\tbuffer:NEAR PTR\n\tARG\tblocksperrow:DWORD\n\tARG\tnumrows:DWORD\n\tARG\tbufwidth:DWORD\n\n\tLOCAL\tdata_end:DWORD\n\tLOCAL\tcb_offset:DWORD\n\tLOCAL\tedi_startval:DWORD\n\tLOCAL\trowoffset:DWORD\n\tLOCAL\tentries:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tmov\teax,[codebook]\t\t;Adjust the codebook address so\n;\tsub\teax,4\t\t; that the pointer offsets will\n\tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n\tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n\tshl\teax,1\t\t; row of blocks.\n\tmov\t[rowoffset],eax\n\n\tmov\tesi,[pointers]\n\tmov\teax,[numrows]\t\t;Compute the end address of the\n\tmul\t[blocksperrow]\t\t; pointer data.\n\tmov\t[entries],eax\n\tadd\teax,esi\n\tmov\t[data_end],eax\n\n\tmov\tedi,[buffer]\n\tmov\t[edi_startval],edi\n\n;----------------------------------------------------------------------------\n;\tDrawing loop\n;----------------------------------------------------------------------------\n\n??Start_row:\n\tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n??Not_finished_a_line:\n\tmov\teax,[entries]\n\txor\tebx,ebx\n\tmov\tbl,[esi]\n\tmov\tbh,[esi + eax]\t;Get the codebook pointer value\n\tinc\tesi\t\t; then advance to the next one.\n\n\tcmp\tbh,00Fh\t\t;Is it a one color block?\n\tje\tshort ??One_color\n\n;\tDraw multi-color block\n\n\tshl\tebx,3\n\tadd\tebx,[cb_offset]\t;Codeword address\n\tmov\teax,[ebx]\t\t;Read 1st row of codeword\n\tmov\tedx,[ebx+4]\t\t;Read 2nd row of codeword\n\tmov\tebx,[bufwidth]\n\tmov\t[edi],eax\t\t;Write 1st row to dest\n\tmov\t[edi+ebx],edx\t\t;Write 2nd row to dest\n\n\tadd\tedi,4\t\t;Next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n;\tDraw 1-color block\n\n??One_color:\n;\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n;\tjne\t??Draw_One_Color\n;\n;\tadd\tedi,4\t\t;Move to next dest block position\n;\tdec\tecx\t\t;More blocks for this row?\n;\tjnz\tshort ??Not_finished_a_line\n;\tjmp\t??Next_row\n\n??Draw_One_Color:\n;\tnot\tbx\t\t;NOT pointer value to get color\n\tmov\tbh,bl\t\t;Duplicate color through the\n\tmov\tax,bx\t\t; entire dword register.\n\trol\teax,16\n\tmov\tax,bx\n\tmov\tebx,[bufwidth]\n\tmov\t[edi],eax\t\t;Write 1st row to dest\n\tmov\t[edi+ebx],eax\t\t;Write 2nd row to dest\n\n\tadd\tedi,4\t\t;Next dest block positionw\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n??Next_row:\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n??End_of_data:\n\tret\n\n\tENDP\tUnVQ_4x2\n\tENDIF\t;VQABLOCK_4X2\n\n\n\tIF\tVQABLOCK_4X4\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x4 - Draw 4x4 block VQ frame to a buffer.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x4(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n;*\n;*     void UnVQ_4x4(unsigned char *, unsigned char *, unsigned char *,\n;*                        unsigned short, unsigned short, unsigned short);\n;*\n;* FUNCTION\n;*     This function draws an image into the specified buffer from the\n;*     pointers and codebook provided. This routine has been optimized for\n;*     a 320x200 image.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook used to draw image.\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to buffer to draw image into.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*     BufWidth - Width of destination buffer in pixels.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC UnVQ_4x4:NEAR\n\tPROC\tUnVQ_4x4 C NEAR USES ebx ecx edx esi edi\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tARG\tbuffer:NEAR PTR\n\tENDIF\n\n   \tARG\tblocksperrow:DWORD\n   \tARG\tnumrows:DWORD\n   \tARG\tbufwidth:DWORD\n\n   \tLOCAL\tdata_end:DWORD\n   \tLOCAL\tcb_offset:DWORD\n      \tLOCAL\tedi_startval:DWORD\n      \tLOCAL\trowoffset:DWORD\n\n      ;----------------------------------------------------------------------------\n      ;\tInitialize\n      ;----------------------------------------------------------------------------\n\n      \tmov\teax,[codebook]\t\t;Adjust the codebook address so\n      \tsub\teax,4\t\t; that the pointer offsets will\n      \tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n      \tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n      \tshl\teax,2\t\t; row of blocks\n      \tmov\t[rowoffset],eax\n\n      \tmov\tesi,[pointers]\n      \tmov\teax,[numrows]\t\t;Compute the end address of the\n      \tmul\t[blocksperrow]\t\t; pointer data.\n      \tshl\teax,1\n      \tadd\teax,esi\n      \tmov\t[data_end],eax\n\n      \tIF\tPHARLAP_TNT\n      \tpush\tes\n      \tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n      \tELSE\n      \tmov\tedi,[buffer]\n      \tENDIF\n\n      \tmov\t[edi_startval],edi\n\n      ;----------------------------------------------------------------------------\n      ;\tDrawing loop\n      ;----------------------------------------------------------------------------\n\n      ??Start_row:\n      \tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n      ??Not_finished_a_line:\n      \tsub\tebx,ebx\n      \tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n      \tadd\tesi,2\t\t; then advance to the next one.\n\n      \tor\tbx,bx\t\t;Is it a one color block?\n      \tjs\tshort ??One_color\n\n      ;\tDraw multi-color block\n\n      \tadd\tebx,[cb_offset]\t;Codeword address\n      \tmov\teax,[ebx]\t\t;Read 1st row of codeword\n      \tmov\tedx,[ebx+4]\t\t;Read 2nd row of codeword\n\n      \tIF\tPHARLAP_TNT\n      \tmov\t[es:edi],eax\t\t;Write 1st row to dest\n      \tELSE\n      \tmov\t[edi],eax\t\t;Write 1st row to dest\n      \tENDIF\n\n      \tmov\teax,ebx\n   \tmov\tebx,[bufwidth]\n\n   \tIF\tPHARLAP_TNT\n   \tmov\t[es:edi+ebx],edx\t;Write 2nd row to dest\n   \tELSE\n   \tmov\t[edi+ebx],edx\t\t;Write 2nd row to dest\n\tENDIF\n\n\tmov\tebx,eax\n\tmov\teax,[ebx+8]\n\tmov\tedx,[ebx+12]\n\tmov\tebx,[bufwidth]\n\tshl\tebx,1\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],eax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi+ebx],eax\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi+ebx],edx\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi+ebx],edx\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tedi,4\t\t;Next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n;\tDraw 1-color block\n\n??One_color:\n\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n\tjne\t??Draw_One_Color\n\n\tadd\tedi,4\t\t;Move to next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Next_row\n\n??Draw_One_Color:\n\tnot\tbx\t\t;NOT pointer value to get color\n\tmov\tbh,bl\t\t;Duplicate color through the\n\tmov\tax,bx\t\t; entire dword register.\n\trol\teax,16\n\tmov\tax,bx\n\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],eax\t\t;Write 1st row to dest\n\tmov\t[es:edi+ebx],eax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi],eax\t\t;Write 1st row to dest\n\tmov\t[edi+ebx],eax\t\t;Write 2nd row to dest\n   \tENDIF\n\n   \tadd\tebx,[bufwidth]\n\n   \tIF\tPHARLAP_TNT\n   \tmov\t[es:edi+ebx],eax\t;Write 3rd row to dest\n   \tELSE\n   \tmov\t[edi+ebx],eax\t\t;Write 3rd row to dest\n   \tENDIF\n\n   \tadd\tebx,[bufwidth]\n\n   \tIF\tPHARLAP_TNT\n   \tmov\t[es:edi+ebx],eax\t;Write 4th row to dest\n   \tELSE\n   \tmov\t[edi+ebx],eax\t\t;Write 4th row to dest\n   \tENDIF\n\n   \tadd\tedi,4\t\t;Next dest block positionw\n      \tdec\tecx\t\t;More blocks for this row?\n      \tjnz\t??Not_finished_a_line\n\n      ;\tAdvance to the next destination row of blocks.\n\n      ??Next_row:\n      \tmov\tedi,[edi_startval]\n      \tadd\tedi,[rowoffset]\n      \tmov\t[edi_startval],edi\n\n      \tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n      \tjnb\tshort ??End_of_data\t; pointers buffer?\n      \tjmp\t??Start_row\n\n      ??End_of_data:\n      \tIF\tPHARLAP_TNT\n      \tpop\tes\n      \tENDIF\n\n         \tret\n\n         \tENDP\tUnVQ_4x4\n         \tENDIF\t;VQABLOCK_4X4\n\n\n\n         \tIF\tVQABLOCK_WOOFER\n         \tIF\tVQABLOCK_4X2\n         ;****************************************************************************\n         ;*\n         ;* NAME\n         ;*     UnVQ_4x2_Woofer - Draw 4x2 block VQ frame to a buffer.\n         ;*\n         ;* SYNOPSIS\n         ;*     UnVQ_4x2_Woofer(Codebook, Pointers, Buffer, BPR, Rows, BufWidth)\n         ;*\n         ;*     void UnVQ_4x2_Woofer(unsigned char *, unsigned char *,\n         ;*                          unsigned char *, long, long, long);\n         ;*\n         ;* FUNCTION\n         ;*     This function draws an image into the specified buffer from the\n         ;*     pointers and codebook provided. This routine has been optimized for\n         ;*     a 320x200 image.\n         ;*\n         ;* INPUTS\n         ;*     Codebook - Pointer to codebook used to draw image.\n         ;*     Pointers - Pointer to vector pointer data.\n         ;*     Buffer   - Pointer to buffer to draw image into.\n         ;*     BPR      - Number of blocks per row.\n         ;*     Rows     - Number of rows.\n         ;*     BufWidth - Width of destination buffer in pixels.\n         ;*\n         ;* RESULT\n         ;*     NONE\n         ;*\n         ;****************************************************************************\n\n         \tGLOBAL\tC UnVQ_4x2_Woofer:NEAR\n         \tPROC\tUnVQ_4x2_Woofer C NEAR USES ebx ecx edx esi edi\n\n         \tARG\tcodebook:NEAR PTR\n         \tARG\tpointers:NEAR PTR\n\n         \tIF\tPHARLAP_TNT\n         \tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n         \tELSE\n         \tARG\tbuffer:NEAR PTR\n         \tENDIF\n\n         \tARG\tblocksperrow:DWORD\n         \tARG\tnumrows:DWORD\n      \tARG\tbufwidth:DWORD\n\n      \tLOCAL\tdata_end:DWORD\n      \tLOCAL\tcb_offset:DWORD\n      \tLOCAL\tedi_startval:DWORD\n      \tLOCAL\trowoffset:DWORD\n      \tLOCAL\tentries:DWORD\n\n      ;----------------------------------------------------------------------------\n      ;\tInitialize\n      ;----------------------------------------------------------------------------\n\n      \tmov\teax,[codebook]\t\t;Adjust the codebook address so\n      ;\tsub\teax,4\t\t; that the pointer offsets will\n      \tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n      \tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n      \tshl\teax,1\t\t; row of blocks.\n      \tmov\t[rowoffset],eax\n\n      \tmov\tesi,[pointers]\n      \tmov\teax,[numrows]\t\t;Compute the end address of the\n      \tmul\t[blocksperrow]\t\t; pointer data.\n      \tmov\t[entries],eax\n      ;\tshl\teax,1\n      \tadd\teax,esi\n      \tmov\t[data_end],eax\n\n      \tIF\tPHARLAP_TNT\n      \tpush\tes\n      \tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n      \tELSE\n      \tmov\tedi,[buffer]\n      \tENDIF\n\n      \tmov\t[edi_startval],edi\n\n      ;----------------------------------------------------------------------------\n      ;\tDrawing loop\n      ;----------------------------------------------------------------------------\n\n      ??Start_row:\n      \tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n      ??Not_finished_a_line:\n      \tmov\teax,[entries]\n      \txor\tebx,ebx\n      ;\tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n      ;\tadd\tesi,2\t\t; then advance to the next one.\n      \tmov\tbl,[esi]\n      \tmov\tbh,[esi + eax]\n      \tinc\tesi\n\n      ;\tor\tbx,bx\t\t;Is it a one color block?\n      ;\tjs\tshort ??One_color\n\n      \tcmp\tbh,00Fh\n      \tje\tshort ??One_color\n\n      ;\tDraw multi-color block\n\n      \tshl\tebx,3\n\n      \tadd\tebx,[cb_offset]\t;Codeword address\n      \tmov\teax,[ebx]\t\t;Read 1st row of codeword\n      \tmov\tedx,[ebx+4]\t\t;Read 2nd row of codeword\n      \tmov\tebx,[bufwidth]\n\n      \tIF\tPHARLAP_TNT\n      \tmov\t[es:edi],al\t\t;Write 1st row to dest\n      \tshr\teax,16\n      \tmov\t[es:edi+2],al\n      \tmov\t[es:edi+ebx+1],dh\t\t;Write 1st row to dest\n      \tshr\tedx,16\n      \tmov\t[es:edi+ebx+3],dh\n      \tELSE\n      \tmov\t[edi],al\t\t;Write 1st row to dest\n      \tshr\teax,16\n      \tmov\t[edi+2],al\n      \tmov\t[edi+ebx+1],dh\t\t;Write 1st row to dest\n      \tshr\tedx,16\n      \tmov\t[edi+ebx+3],dh\n      \tENDIF\n\n      \tadd\tedi,4\t\t;Next dest block position\n      \tdec\tecx\t\t;More blocks for this row?\n      \tjnz\tshort ??Not_finished_a_line\n\n      ;\tAdvance to the next destination row of blocks.\n\n      \tmov\tedi,[edi_startval]\n      \tadd\tedi,[rowoffset]\n      \tmov\t[edi_startval],edi\n\n      \tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n      \tjnb\tshort ??End_of_data\t; pointers buffer?\n      \tjmp\t??Start_row\n\n      ;\tDraw 1-color block\n\n      ??One_color:\n      ;\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n      ;\tjne\t??Draw_One_Color\n\n      ;\tadd\tedi,4\t\t;Move to next dest block position\n      ;\tdec\tecx\t\t;More blocks for this row?\n      ;\tjnz\tshort ??Not_finished_a_line\n      ;\tjmp\t??Next_row\n\n      ??Draw_One_Color:\n      ;\tnot\tbx\t\t;NOT pointer value to get color\n      \tmov\tal,bl\n      \tmov\tebx,[bufwidth]\n\n      \tIF\tPHARLAP_TNT\n      \tmov\t[es:edi],al\n      \tmov\t[es:edi+2],al\n      \tmov\t[es:edi+ebx+1],al\t;Write 2nd row to dest\n      \tmov\t[es:edi+ebx+3],al\t;Write 2nd row to dest\n      \tELSE\n      \tmov\t[edi],al\n      \tmov\t[edi+2],al\n      \tmov\t[edi+ebx+1],al\t\t;Write 2nd row to dest\n      \tmov\t[edi+ebx+3],al\t\t;Write 2nd row to dest\n      \tENDIF\n\n      \tadd\tedi,4\t\t;Next dest block positionw\n      \tdec\tecx\t\t;More blocks for this row?\n      \tjnz\t??Not_finished_a_line\n\n      ;\tAdvance to the next destination row of blocks.\n\n      ??Next_row:\n      \tmov\tedi,[edi_startval]\n      \tadd\tedi,[rowoffset]\n      \tmov\t[edi_startval],edi\n\n      \tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n      \tjnb\tshort ??End_of_data\t; pointers buffer?\n      \tjmp\t??Start_row\n\n      ??End_of_data:\n      \tIF\tPHARLAP_TNT\n      \tpop\tes\n      \tENDIF\n\n      \tret\n\n      \tENDP\tUnVQ_4x2_Woofer\n      \tENDIF\t;VQABLOCK_4X2\n      \tENDIF\t;VQABLOCK_WOOFER\n\n      \tEND\n\n"
  },
  {
    "path": "WINVQ/VQA32/UNVQVESA.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PROJECT\n;*     VQAPlay32 library.\n;*\n;* FILE\n;*     unvqvesa.asm\n;*\n;* DESCRIPTION\n;*     VESA VQ decompress/draw routines. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     UnVQ_4x2_VESA320_32K - Draw 4x2 VQ frame to VESA320 32k color.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"vga.i\"\n\tINCLUDE\t\"vesavid.i\"\n\tINCLUDE\t\"vqaplay.i\"\n\tCODESEG\n\nSKIP_PTR\tEQU\t8000h\n\n\tIF\tVQAVESA_ON\n\tIF\tVQABLOCK_4X2\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x2_VESA320_32K - Draw 4x2 VQ frame to VESA320 32k color.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x2_VESA320_32K(Codebook, Pointers, Palette, GrainPerWin)\n;*\n;*     void UnVQ_4x2_VESA320_32K(char *, char *, char *, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Codebook    - Pointer to codebook.\n;*     Pointers    - Pointer to vector pointer data to unvq.\n;*     Palette     - Pointer to 15-bit palette.\n;*     GrainPerWin - Granularity units for 64k window.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n \n;---------------------------------------------------------------------------\n; SET_2_PIXELS:\n; - Loads 2 bytes from codebook, expands them into words in eax\n; - Sets them on the screen\n;   cb_index: offset into codebook of start of 2 bytes to load\n;   di_index: offset from current di to draw 2 pixels\n;   BX: offset into codebook of this block\n; Uses: EAX, DX, SI!\n;---------------------------------------------------------------------------\n\n\tMACRO\tSET_2_PIXELS cb_index,edi_index\n\txor\tedx,edx\n\tmov\tdl,[BYTE PTR ebx+1+cb_index]\n\tshl\tedx,1\n\tadd\tedx,[palette]\n\tmov\tesi,edx\n\tmov\tax,[WORD PTR esi]\n\tshl\teax,16\n\txor\tedx,edx\n\tmov\tdl,[BYTE PTR ebx+cb_index]\n\tshl\tedx,1\n\tadd\tedx,[palette]\n\tmov\tesi,edx\n\tmov\tax,[WORD PTR esi]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[DWORD PTR es:edi+edi_index],eax\n\tELSE\n\tmov\t[DWORD PTR edi+edi_index],eax\n\tENDIF\n\tENDM\n\n;---------------------------------------------------------------------------\n; DRAW_BLOCK_ROWS macro:\n; Draws 'numrows' rows of 'blocksperrow' blocks each\n;---------------------------------------------------------------------------\n\n\tMACRO\tDRAW_BLOCK_ROWS numrows,blocksperrow\n\tLOCAL\t??Start_row\n\tLOCAL\t??Not_finished_a_line\n\tLOCAL\t??One_color\n\tLOCAL\t??Draw_One_Color\n\tLOCAL\t??Next_row\n\tLOCAL\t??Done\n\n\tmov\t[rowcount],numrows\t\t; initialize row counter\n\n\t;---------------------------------------- Start a new row:\n??Start_row:\n\tmov\tecx,blocksperrow\t\t\t; # blocks to fill a line\n\n\t;---------------------------------------- Start a new block:\n??Not_finished_a_line:\n\t;........................................ Get next pointer word:\n\txor\tebx,ebx\n\tmov\tbx,[WORD PTR esi]\t\t; BX = pointer word\n\tadd\tesi,2\n\n\t;........................................ Check for a 1-color block:\n\tor\tbx,bx\t\t\t\t; see if high bit is set\n\tjs\t??One_color\n\n\t;---------------------------------------- Multi-color block:\n\tmov\t[esi_save],esi\t\t\t; save current SI\n\tadd\tebx,[cb_offset]\t\t\t; get codebook offset\n\tSET_2_PIXELS 0,0\n\tSET_2_PIXELS 2,4\n\tSET_2_PIXELS 4,640\n\tSET_2_PIXELS 6,644\n\tadd\tedi,8\t\t\t\t; next block position\n\tmov\tesi,[esi_save]\t\t\t; get current SI\n\n\t;........................................ Check block count\n\tdec\tecx\t\t\t\t; decrement block count\n\tjnz\t??Not_finished_a_line\n\n\t;---------------------------------------- Next block row:\n\tadd\tedi,640\n\t;\n\t;............ see if we're past the end of the ptr data ............\n\t;\n\tdec\t[rowcount]\n\tjnz\t??Start_row\n\tjmp\t??Done\n\n\t;---------------------------------------- 1-color block:\n??One_color:\n\t;................... skip ptr value SKIP_PTR .......................\n\tcmp\tbx,SKIP_PTR\n\tjne\t??Draw_One_Color\n\tadd\tedi,8\n\tdec\tecx\n\tjnz\t??Not_finished_a_line\n\tjmp\t??Next_row\n??Draw_One_Color:\n\tnot\tbx\t\t\t\t; get palette index\n\tshl\tbx,1\t\t\t\t; convert to WORD offset\n\tadd\tebx,[palette]\n\tmov\tax,[WORD PTR ebx]\t\t; get 15-bit palette value\n\tmov\tdx,ax\t\t\t\t; copy it into dx\n\tshl\teax,16\n\tmov\tax,dx\t\t\t\t; eax = 2 pixels, same color\n\tmov\tedx,eax\t\t\t\t; edx = 2 pixels, same color\n\n\tIF\tPHARLAP_TNT\n\tmov\t[DWORD PTR es:edi],eax\t\t; set 2 pixels\n\tmov\t[DWORD PTR es:edi+4],edx\t\t; set 2 pixels\n\tmov\t[DWORD PTR es:edi+640],eax\t; set 2 pixels\n\tmov\t[DWORD PTR es:edi+644],edx\t; set 2 pixels\n\tELSE\n\tmov\t[DWORD PTR edi],eax\t\t; set 2 pixels\n\tmov\t[DWORD PTR edi+4],edx\t\t; set 2 pixels\n\tmov\t[DWORD PTR edi+640],eax\t; set 2 pixels\n\tmov\t[DWORD PTR edi+644],edx\t; set 2 pixels\n\tENDIF\n\n\tadd\tedi,8\t\t\t\t; next block position\n\n\t;........................................ Check block count\n\tdec\tecx\t\t\t\t; decrement block count\n\tjnz\t??Not_finished_a_line\n\n\t;---------------------------------------- Next block row:\n??Next_row:\n\tadd\tedi,640\n\t;\n\t;............ see if we're past the end of the ptr data ............\n\t;\n\tdec\t[rowcount]\n\tjnz\t??Start_row\n??Done:\n\tENDM\n\n;---------------------------------------------------------------------------\n; DRAW_BLOCK_PART_ROW macro:\n; Draws top or bottom half of blocks on a row\n; 'numblocks' = # blocks to draw\n; 'cb_add' = amt to add to codebook (0=top half, 4=bottom half)\n;---------------------------------------------------------------------------\n\n\tMACRO\tDRAW_BLOCK_PART_ROW numblocks,cb_add\n\tLOCAL\t??Not_finished_a_line\n\tLOCAL\t??One_color\n\tLOCAL\t??Draw_One_Color\n\tLOCAL\t??Done\n\n\tmov\tecx,numblocks\n\n\t;---------------------------------------- Start a new block:\n??Not_finished_a_line:\n\t;........................................ Get next pointer word:\n\txor\tebx,ebx\n\tmov\tbx,[WORD PTR esi]\t\t; BX = pointer word\n\tadd\tesi,2\n\n\t;........................................ Check for a 1-color block:\n\tor\tbx,bx\t\t\t\t; see if high bit is set\n\tjs\tshort ??One_color\n\n\t;---------------------------------------- Multi-color block:\n\tmov\t[esi_save],esi\t\t\t; save current SI\n\tadd\tebx,[cb_offset]\t\t\t; get codebook offset\n\tSET_2_PIXELS cb_add,0\n\tSET_2_PIXELS cb_add+2,4\n\tadd\tedi,8\t\t\t\t; next block position\n\tmov\tesi,[esi_save]\t\t\t; get current SI\n\n\t;........................................ Check block count\n\tdec\tecx\t\t\t\t; decrement block count\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Done\n\n\t;---------------------------------------- 1-color block:\n??One_color:\n\t;................... skip ptr value SKIP_PTR .......................\n\tcmp\tbx,SKIP_PTR\n\tjne\t??Draw_One_Color\n\tadd\tedi,8\n\tdec\tecx\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Done\n??Draw_One_Color:\n\tnot\tbx\t\t\t\t; get palette index\n\tshl\tbx,1\t\t\t\t; convert to WORD offset\n\tadd\tebx,[palette]\n\tmov\tax,[WORD PTR ebx]\t\t; get 15-bit palette value\n\tmov\tdx,ax\t\t\t\t; copy it into dx\n\tshl\teax,16\n\tmov\tax,dx\t\t\t\t; eax = 2 pixels, same color\n\tmov\tedx,eax\t\t\t\t; edx = 2 pixels, same color\n\n\tIF\tPHARLAP_TNT\n\tmov\t[DWORD PTR es:edi],eax\t\t; set 2 pixels\n\tmov\t[DWORD PTR es:edi+4],edx\t\t; set 2 pixels\n\tELSE\n\tmov\t[DWORD PTR edi],eax\t\t; set 2 pixels\n\tmov\t[DWORD PTR edi+4],edx\t\t; set 2 pixels\n\tENDIF\n\n\tadd\tedi,8\t\t\t\t; next block position\n\n\t;........................................ Check block count\n\tdec\tecx\t\t\t\t; decrement block count\n\tjnz\t??Not_finished_a_line\n??Done:\n\tENDM\n\n;===========================================================================\n; The actual procedure:\n;===========================================================================\n\n\tGLOBAL\tC UnVQ_4x2_VESA320_32K:NEAR\n\tPROC\tUnVQ_4x2_VESA320_32K C NEAR\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tARG\tpal:QWORD\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tARG\tpalette:NEAR PTR\n\tENDIF\n\n\tARG\tgrains_per_win:DWORD\n\tARG\tdummy1:DWORD\n\tARG\tdummy2:DWORD\n\n\tLOCAL\trowcount:DWORD\t\t; # rows drawn\n\tLOCAL\tesi_save:DWORD\n\tLOCAL\tcb_offset:DWORD\n\n\tIF\tPHARLAP_TNT\n\tLOCAL\tpalette:NEAR PTR\n\tENDIF\n\n\t;-------------------------------------------------------------------\n\t; Save registers\n\t;-------------------------------------------------------------------\n\tpushad\n\n\t;-------------------------------------------------------------------\n\t; Set GS:[cb_offset] to codebook\n\t;-------------------------------------------------------------------\n\tmov\teax,[codebook]\n\tsub\teax,4\n\tmov\t[cb_offset],eax\n\tmov\tesi,[pointers]\n\n\t;-------------------------------------------------------------------\n\t; Set ES:DI to screen\n\t;-------------------------------------------------------------------\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tles\tedi,[FWORD pal]\n\tmov\t[palette],edi\n\tmov\teax,01Ch\n\tmov\tes,ax\n\tmov\tedi,0\n\tELSE\n\tmov\tedi,0A0000h\n\tENDIF\n\n\t;-------------------------------------------------------------------\n\t; Do Bank 0:\n\t; - 102 full scanlines (51 rows of blocks)\n\t; - 128 pixels of the top half of blocks (32 top-half blocks)\n\t;-------------------------------------------------------------------\n\tSET_WINDOW 0\n\tDRAW_BLOCK_ROWS 51,80\n\tDRAW_BLOCK_PART_ROW 32,0\t; do top half\n\n\t;-------------------------------------------------------------------\n\t; Do Bank 1:\n\t; - 128 pixels of the bottom half of the previous 32 blocks\n\t; - 192 pixels of full blocks (1 row of 48 blocks)\n\t; - 96 full scanlines (48 rows of blocks)\n\t;-------------------------------------------------------------------\n\tSET_WINDOW [grains_per_win]\n\tsub\tesi,64\t\t\t; subtract word size of last 32 blks\n\tmov\tedi,384\n\tDRAW_BLOCK_PART_ROW 32,4\t; do bottom half\n\tmov\tedi,0\n\tDRAW_BLOCK_ROWS 1,48\t\t; draw one row of 48 full blocks\n\tDRAW_BLOCK_ROWS 48,80\t\t; draw 48 full block rows\n\n??End_of_data:\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tpopad\n\tret\n\n\tENDP\tUnVQ_4x2_VESA320_32K\n\n\tENDIF\t;VQABLOCK_4X2\n\tENDIF\t;VQAVESA_ON\n\n\tEND\n\n"
  },
  {
    "path": "WINVQ/VQA32/UNVQXMDE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PROJECT\n;*     VQAPlay library.\n;*\n;* FILE\n;*     UnVQxmde.asm\n;*\n;* DESCRIPTION\n;*     XMode VQ decompress/draw routines.\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     May 18, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     UnVQ_4x2_Xmode       - Draw 4x2 VQ frame directly to Xmode.\n;*     UnVQ_4x2_XmodeCB     - Draw 4x2 VQ frame to Xmode from VRAM codebook.\n;*     Upload_4x2CB         - Upload 4x2 codebook into XMode VRAM.\n;*     UnVQ_4x2_VESA320_32K - Draw 4x2 VQ frame to VESA320 32k color.\n;*     XlatePointers        - Translate pointer to optimal XMode format.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"vga.i\"\n\tINCLUDE\t\"vesavid.i\"\n\tINCLUDE\t\"vqaplay.i\"\n\tCODESEG\n\n\tIF\tVQAXMODE_ON\n\nSKIP_PTR\tEQU\t8000h\nCBOOK_SEG\tEQU\t(0B0000h - 270h)\n\n\n\tIF\tVQABLOCK_4X2\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x2_Xmode - Draw 4x2 VQ frame directly to Xmode.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x2_Xmode(Codebook, Pointers, Buffer, BPR, Rows, Dummy)\n;*\n;*     void UnVQ_4x2_Xmode(unsigned char *, unsigned char *, unsigned char *,\n;*                         unsigned short, unsigned short, unsigned short);\n;*\n;* FUNCTION\n;*     This function draws an image to the Xmode display from the pointers\n;*     and codebook provided. This routine has been optimized for a 320x200\n;*     image.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook used to draw image.\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to buffer to draw image into.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*     Dummy    - Not used (prototype placeholder)\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC UnVQ_4x2_Xmode:NEAR\n\tPROC\tUnVQ_4x2_Xmode C NEAR USES\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tpointers:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tARG\tbuffer:QWORD\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tARG\tbuffer:NEAR PTR\n\tENDIF\n\n\tARG\tblocksperrow:DWORD\n\tARG\tnumrows:DWORD\n\tARG\tbufwidth:DWORD\n\n\tLOCAL\tdata_end:DWORD\n\tLOCAL\tcb_offset:DWORD\n\tLOCAL\tedi_startval:DWORD\n\tLOCAL\trowoffset:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tmov\teax,[codebook]\t\t;Adjust the codebook address so\n\tsub\teax,4\t\t; that the pointer offsets will\n\tmov\t[cb_offset],eax\t; point directly at the codeword.\n\n\tmov\teax,[bufwidth]\t\t;Compute the offset to the next\n\tshl\teax,1\t\t; row of blocks.\n\tmov\t[rowoffset],eax\n\n\tmov\tesi,[pointers]\n\tmov\teax,[numrows]\t\t;Compute the end address of the\n\tmul\t[blocksperrow]\t\t; pointer data.\n\tshl\teax,1\n\tadd\teax,esi\n\tmov\t[data_end],eax\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tles\tedi,[FWORD buffer]\t;KLUDGE - bcc32 pads FARPTR\n\tELSE\n\tmov\tedi,[buffer]\n\tENDIF\n\n\tmov\t[edi_startval],edi\n\n;----------------------------------------------------------------------------\n;\tDrawing loop\n;----------------------------------------------------------------------------\n\n\tSET_PLANE\tXPLANE_1\n\n??Start_row:\n\tmov\tecx,[blocksperrow]\t;Number of blocks in a line\n\n??Not_finished_a_line1:\n\tsub\tebx,ebx\n\tmov\tbx,[WORD PTR esi]\t;Get the codebook pointer value\n\tadd\tesi,2\t\t; then advance to the next one.\n\n\tor\tbx,bx\t\t;Is it a one color block?\n\tjs\tshort ??One_color1\n\n;\tDraw multi-color block\n\n\tadd\tebx,[cb_offset]\t;Codeword address\n\tmov\teax,[ebx]\t\t;Read 1st row of codeword\n\tmov\tedx,[ebx+4]\t\t;Read 2nd row of codeword\n;\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],eax\t\t;Write 1st row to dest\n\tmov\t[es:edi+ebx],edx\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi],al\t\t;Write 1st row to dest\n\tmov\t[edi+80],dl\t\t;Write 2nd row to dest\n\tENDIF\n\n;\tadd\tedi,4\t\t;Next dest block position\n\tinc\tedi\t\t;Next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n;\tDraw 1-color block\n\n??One_color1:\n\tcmp\tbx,SKIP_PTR\t\t;Is this a skip block?\n\tjne\t??Draw_One_Color\n\n\tadd\tedi,4\t\t;Move to next dest block position\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\tjmp\t??Next_row\n\n??Draw_One_Color:\n\tnot\tbx\t\t;NOT pointer value to get color\n\tmov\tbh,bl\t\t;Duplicate color through the\n\tmov\tax,bx\t\t; entire dword register.\n\trol\teax,16\n\tmov\tax,bx\n;\tmov\tebx,[bufwidth]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],eax\t\t;Write 1st row to dest\n\tmov\t[es:edi+ebx],eax\t;Write 2nd row to dest\n\tELSE\n\tmov\t[edi],al\t\t;Write 1st row to dest\n\tmov\t[edi+80],al\t\t;Write 2nd row to dest\n\tENDIF\n\n\tadd\tedi,4\t\t;Next dest block positionw\n\tdec\tecx\t\t;More blocks for this row?\n\tjnz\tshort ??Not_finished_a_line\n\n;\tAdvance to the next destination row of blocks.\n\n??Next_row:\n\tmov\tedi,[edi_startval]\n\tadd\tedi,[rowoffset]\n\tmov\t[edi_startval],edi\n\n\tcmp\tesi,[data_end]\t\t;Have we reached the end of the\n\tjnb\tshort ??End_of_data\t; pointers buffer?\n\tjmp\t??Start_row\n\n??End_of_data:\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\tENDP\tUnVQ_4x2_Xmode\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     UnVQ_4x2_XmodeCB - Draw 4x2 VQ frame to Xmode from VRAM codebook.\n;*\n;* SYNOPSIS\n;*     UnVQ_4x2_XmodeCB(Dummy, Pointers, Buffer, BPR, Rows)\n;* \n;*     void UnVQ_4x2_XmodeCB(unsigned char *, unsigned char *,\n;*                           unsigned char *, unsigned short,\n;*                           unsigned short);\n;*\n;* FUNCTION\n;*     This routine copies codebook entries from video RAM to video RAM.\n;*     The procedure for Write Mode 1 is:\n;*\n;*       - Perform a CPU read at the address of the 4-byte codebook entry;\n;*         this will load each byte at that address from all 4 bitplanes\n;*         into the VGA's internal latches.\n;*\n;*       - Perform a CPU write at the destination address, with the BitMask\n;*         register set to 0 (this tells the VGA hardware to only use the\n;*         data stored in the latches to write with), and the Map Mask\n;*         register set to 0Fh (all bitplanes enabled).\n;*\n;*     Optimized for 320x200.\n;*     The codebook must have been downloaded to video RAM before this\n;*     routine is called. This routine assumes the multicolor block pointers\n;*     have been pre-divided by 4, and have a total of 512 added to them, so\n;*     the pointer is an exact offset into the codebook.\n;*\n;* INPUTS\n;*     Dummy    - Not used (prototype placeholder)\n;*     Pointers - Pointer to vector pointer data.\n;*     Buffer   - Pointer to Xmode buffer.\n;*     BPR      - Number of blocks per row.\n;*     Rows     - Number of rows.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC UnVQ_4x2_XmodeCB:NEAR\n\tPROC\tUnVQ_4x2_XmodeCB C NEAR USES\n\n\tARG\tcbdummy:FAR PTR\n\tARG\tpointers:FAR PTR\n\tARG\tbuffer:FAR PTR\n\tARG\tblocksperrow:WORD\n\tARG\tnumrows:WORD\n\n;\t;-------------------------------------------------------------------\n;\t; Local variables:\n;\t;-------------------------------------------------------------------\n;\tLOCAL\tdi_startval:WORD\t; init value for DI, for new row\n;\n;\t;===================================================================\n;\t; Initialization\n;\t;===================================================================\n;\t;-------------------------------------------------------------------\n;\t; Save our registers\n;\t;-------------------------------------------------------------------\n;\tpush\tds\n;\tpush\tes\n;\tpush\tfs\n;\tpushad\n;\n;\t;-------------------------------------------------------------------\n;\t; Save codebook's segment in DS\n;\t;-------------------------------------------------------------------\n;\tmov\tax,CBOOK_SEG\n;\tmov\tds,ax\n;\n;\t;-------------------------------------------------------------------\n;\t; Load pointers into FS:BX\n;\t;-------------------------------------------------------------------\n;\tles\tdi,[pointers]\n;\tmov\tax,es\n;\tmov\tfs,ax\n;\tmov\tbx,di\n;\n;\t;-------------------------------------------------------------------\n;\t; Load screen address into ES:DI\n;\t;-------------------------------------------------------------------\n;\tles\tdi, [buffer]   \t\t\t; point ES:DI to dest\n;\tmov\t[di_startval],di\t\t; store it\n;\n;\t;-------------------------------------------------------------------\n;\t; Initialize VGA registers:\n;\t; - Enable all bitplanes for writing\n;\t; - Set the BitMask register to 0, so only the data from the\n;\t;   VGA latches is written into the bitplanes\n;\t;-------------------------------------------------------------------\n;\tSET_PLANE 0fh\t\t\t\t; enable all planes for write\n;\tSET_WRITEMODE 1\n;\n;\t;===================================================================\n;\t; The drawing loop:\n;\t; DS:SI = codebook\n;\t; ES:DI = drawing buffer\n;\t; FS:BX = pointers\n;\t;===================================================================\n;\t;-------------------------------------------------------------------\n;\t; Start a new row of drawing\n;\t;-------------------------------------------------------------------\n;??Start_row:\n;\tmov\tcx,[blocksperrow]\t\t; # blocks to fill a line\n;\n;\t;-------------------------------------------------------------------\n;\t; Start a new block\n;\t;-------------------------------------------------------------------\n;??Not_finished_a_line:\n;\t;\n;\t;..................... get next pointer word .......................\n;\t;\n;\tmov\tsi,[WORD PTR fs:bx]\t\t; SI = ptr word (cbook offset)\n;\tadd\tbx,2\t\t\t\t; next ptr word\n;\t;\n;\t;................... skip ptr value SKIP_PTR .......................\n;\t;\n;\tcmp\tsi,SKIP_PTR\n;\tjne\t??Draw_Block\n;\tinc\tdi\n;\tdec\tcx\n;\tjnz\tshort ??Not_finished_a_line\n;\tjmp\t??Next_row\n;\n;\t;-------------------------------------------------------------------\n;\t; Draw a block via the VGA internal latches:\n;\t; DS:SI = codebook address\n;\t; ES:DI = buffer position to draw at\n;\t; - Load the VGA latches from the 1st 4 codebook bytes\n;\t; - write 4 pixels with one CPU write\n;\t; - If this is a one-color block, skip the next codebook read\n;\t;   (Video RAM reads are very slow); otherwise, latch the next 4\n;\t;   codebook bytes\n;\t; - write the next 4 pixels\n;\t;-------------------------------------------------------------------\n;\t;\n;\t;..................... draw 1st 4 pixels ...........................\n;\t;\n;??Draw_Block:\n;\tmov\tal,[ds:si]\t\t\t; latch 1st 4 cbook bytes\n;\tmov\t[es:di],al\t\t\t; write 4 pixels\n;\t;\n;\t;.................. check for 1-color block ........................\n;\t;\n;\tcmp\tsi,512\t\t\t\t; if 1color blk, don't read\n;\tjb\t??One_Color\n;\t;\n;\t;..................... draw next 4 pixels ..........................\n;\t;\n;\tmov\tal,[ds:si+1]\t\t\t; latch next 4 cbook bytes\n;??One_Color:\n;\tmov\t[es:di+80],al\t\t\t; write next 4 pixels\n;\tinc\tdi\t\t\t\t; next block position\n;\t;\n;\t;...................... check block count ..........................\n;\t;\n;\tdec\tcx\t\t\t\t; decrement block count\n;\tjnz\tshort ??Not_finished_a_line\n;\n;\t;-------------------------------------------------------------------\n;\t; Go to the next block row:\n;\t; - Add (80*2/16) to ES, and set DI to its start-row value\n;\t;   (Incrementing the segment allows us to unpack up to 1MB of data)\n;\t;-------------------------------------------------------------------\n;\t;\n;\t;...................... add (320*2/16) to ES .......................\n;\t;\n;??Next_row:\n;\tmov\tax,es\n;\tadd\tax,10\t\t\t\t; add 80*2/16\n;\tmov\tes,ax\n;\t;\n;\t;.................. set DI to its start-row value ..................\n;\t;\n;\tmov\tdi,[di_startval]\n;\t;\n;\t;............ see if we're past the end of the ptr data ............\n;\t;\n;\tdec\t[numrows]\n;\tjg\t??Start_row\n;\n;??End_of_data:\n;\t;-------------------------------------------------------------------\n;\t; Restore VGA Write Mode to 0\n;\t;-------------------------------------------------------------------\n;\tSET_WRITEMODE 0\n;\n;\tpopad\n;\tpop\tfs\n;\tpop\tes\n;\tpop\tds\n\tret\n\n\tENDP\tUnVQ_4x2_XmodeCB\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Upload_4x2CB - Upload 4x2 codebook into XMode VRAM.\n;*\n;* SYNOPSIS\n;*     Upload_4x2CB(Codebook, Entries)\n;*\n;*     void Upload_4x2CB(unsigned char *, unsigned short);\n;*\n;* FUNCTION\n;*     This routine copies the given codebook into Xmode VRAM, so that it\n;*     can be used later for direct video-to-video copies. The address used\n;*     is the end of video memory minus 02700h (10K). This should be plenty\n;*     for a 3000-entry codebook; each 4x2 codebook entry will take up 8\n;*     8 bytes, or 2 addresses in XMode (6000 addresses).\n;*\n;*     The routine also creates a 1-color-block table in VRAM, so the 1-color\n;*     blocks can be generated the same way as the multicolor blocks.\n;*\n;*     XMode 320x200 uses 320x200/4 addresses per page, for a total of 32000\n;*     addresses.  XMode 320x240 uses 320x240/4 addresses per page, for a\n;*     total of 38400 addresses.  This leaves 27136 addresses unused.\n;*\n;* INPUTS\n;*     Codebook - Pointer to codebook to copy.\n;*     Entries  - Number of codebook entries to copy.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Upload_4x2CB:NEAR\n\tPROC\tUpload_4x2CB C NEAR USES\n\n\tARG\tcodebook:NEAR PTR\n\tARG\tnumentries:DWORD\n\n;\t;===================================================================\n;\t; Generate the 1-color block table by writing each color value from\n;\t; 0-255 into all 4 bitplanes, at 256 consecutive addresses:\n;\t;===================================================================\n;\tSET_PLANE 0fh\t\t\t; enable all bitplanes for writing\n;\t;...................................................................\n;\t; Set ES:DI to destination address, set up CX for the loop\n;\t;...................................................................\n;\tmov\tax,CBOOK_SEG\n;\tmov\tes,ax\n;\tmov\tdi,0\n;\tmov\tcx,256\n;\tmov\tax,0\n;??1_Color_Loop:\n;\tmov\t[es:di],al\t\t\t; write 4 bytes\n;\tinc\tdi\t\t\t\t; next 4-byte position\n;\tmov\t[es:di],al\t\t\t; write 4 bytes\n;\tinc\tdi\t\t\t\t; next 4-byte position\n;\tinc\tax\t\t\t\t; next color #\n;\tdec\tcx\t\t\t\t; decrement loop counter\n;\tjnz\t??1_Color_Loop\n;\n;\t;===================================================================\n;\t; Copy the codebook into video RAM, one plane at a time:\n;\t;===================================================================\n;\t;-------------------------------------------------------------------\n;\t; Copy codebook byte 0 into Plane 1\n;\t;-------------------------------------------------------------------\n;\t;...................................................................\n;\t; Set DS:SI to codebook address, ES:DI to screen address\n;\t; (Codebook is stored at offset 1, so the pointers will point at\n;\t; exactly the right offset.)\n;\t;...................................................................\n;\tlds\tsi, [codebook]\t\t\t; DS:SI = codebook\n;\tmov\tax,CBOOK_SEG\n;\tmov\tes,ax\n;\tmov\tdi,512\n;\n;\t;...................................................................\n;\t; Set up the loop\n;\t;...................................................................\n;\tSET_PLANE XPLANE_1\n;\tmov\tcx,[numentries]\t\t\t; set loop counter\n;\tshl\tcx,1\t\t\t\t; do 2 DWORDS per cbook entry\n;\n;\t;...................................................................\n;\t; Loop through codebook entries\n;\t;...................................................................\n;??CB_Loop_1:\n;\tmov\tal,[ds:si]\n;\tmov\t[es:di],al\n;\tadd\tsi,4\n;\tinc\tdi\n;\tdec\tcx\n;\tjnz\t??CB_Loop_1\n;\n;\t;-------------------------------------------------------------------\n;\t; Copy codebook byte 1 Plane 2\n;\t;-------------------------------------------------------------------\n;\t;...................................................................\n;\t; Set DS:SI to codebook address, ES:DI to screen address\n;\t; (Codebook is stored at offset 1, so the pointers will point at\n;\t; exactly the right offset.)\n;\t;...................................................................\n;\tlds\tsi, [codebook]\t\t\t; DS:SI = codebook\n;\tmov\tax,CBOOK_SEG\n;\tmov\tes,ax\n;\tmov\tdi,512\n;\tadd\tsi,1\t\t\t\t; use 2nd byte value\n;\n;\t;...................................................................\n;\t; Set up the loop\n;\t;...................................................................\n;\tSET_PLANE XPLANE_2\n;\tmov\tcx,[numentries]\t\t\t; set loop counter\n;\tshl\tcx,1\t\t\t\t; do 2 DWORDS per cbook entry\n;\n;\t;...................................................................\n;\t; Loop through codebook entries\n;\t;...................................................................\n;??CB_Loop_2:\n;\tmov\tal,[ds:si]\n;\tmov\t[es:di],al\n;\tadd\tsi,4\n;\tinc\tdi\n;\tdec\tcx\n;\tjnz\t??CB_Loop_2\n;\n;\t;-------------------------------------------------------------------\n;\t; Copy codebook byte 2 Plane 3\n;\t;-------------------------------------------------------------------\n;\t;...................................................................\n;\t; Set DS:SI to codebook address, ES:DI to screen address\n;\t; (Codebook is stored at offset 1, so the pointers will point at\n;\t; exactly the right offset.)\n;\t;...................................................................\n;\tlds\tsi, [codebook]\t\t\t; DS:SI = codebook\n;\tmov\tax,CBOOK_SEG\n;\tmov\tes,ax\n;\tmov\tdi,512\n;\tadd\tsi,2\t\t\t\t; use 3rd byte value\n;\n;\t;...................................................................\n;\t; Set up the loop\n;\t;...................................................................\n;\tSET_PLANE XPLANE_3\n;\tmov\tcx,[numentries]\t\t\t; set loop counter\n;\tshl\tcx,1\t\t\t\t; do 2 DWORDS per cbook entry\n;\n;\t;...................................................................\n;\t; Loop through codebook entries\n;\t;...................................................................\n;??CB_Loop_3:\n;\tmov\tal,[ds:si]\n;\tmov\t[es:di],al\n;\tadd\tsi,4\n;\tinc\tdi\n;\tdec\tcx\n;\tjnz\t??CB_Loop_3\n;\n;\t;-------------------------------------------------------------------\n;\t; Copy codebook byte 3 Plane 4\n;\t;-------------------------------------------------------------------\n;\t;...................................................................\n;\t; Set DS:SI to codebook address, ES:DI to screen address\n;\t; (Codebook is stored at offset 1, so the pointers will point at\n;\t; exactly the right offset.)\n;\t;...................................................................\n;\tlds\tsi, [codebook]\t\t\t; DS:SI = codebook\n;\tmov\tax,CBOOK_SEG\n;\tmov\tes,ax\n;\tmov\tdi,512\n;\tadd\tsi,3\t\t\t\t; use 4th byte value\n;\n;\t;...................................................................\n;\t; Set up the loop\n;\t;...................................................................\n;\tSET_PLANE XPLANE_4\n;\tmov\tcx,[numentries]\t\t\t; set loop counter\n;\tshl\tcx,1\t\t\t\t; do 2 DWORDS per cbook entry\n;\n;\t;...................................................................\n;\t; Loop through codebook entries\n;\t;...................................................................\n;??CB_Loop_4:\n;\tmov\tal,[ds:si]\n;\tmov\t[es:di],al\n;\tadd\tsi,4\n;\tinc\tdi\n;\tdec\tcx\n;\tjnz\t??CB_Loop_4\n;\n\tret\n\n\tENDP\tUpload_4x2CB\n\n\tENDIF\t;VQABLOCK_4X2\n\n;****************************************************************************\n;*\n;* NAME\n;*     XlatePointers - Translate pointer to optimal XMode format.\n;*\n;* SYNOPSIS\n;*     XlatePointers(Pointers, Entries)\n;*\n;*     void XlatePointers(unsigned char *, unsigned short);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Pointers - Pointer to vector pointers to translate.\n;*     Entries  - Number of pointer entries.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC XlatePointers:NEAR\n\tPROC\tXlatePointers C NEAR USES\n\n\tARG\tpointers:NEAR PTR\n\tARG\tnumpointers:DWORD\n\n;\t;-------------------------------------------------------------------\n;\t; Load pointers into DS:SI\n;\t;-------------------------------------------------------------------\n;\tlds\tsi,[pointers]\n;\n;\tmov\tcx,[numpointers]\t\t; init to # pointers on scrn\n;\n;??Process_pointer:\n;\t;\n;\t;..................... get next pointer word .......................\n;\t;\n;\tmov\tax,[WORD PTR ds:si]\t\t; SI = ptr word (cbook offset)\n;\t;\n;\t;.................... check for a 1-color block ....................\n;\t;\n;\tor\tax,ax\t\t\t\t; check to see if high bit set\n;\tjs\tshort ??One_color\n;\t;\n;\t;....................... multi-color pointer .......................\n;\t;\n;\tsub\tax,4\t\t\t\t; subtract 4\n;\tshr\tax,2\t\t\t\t; divide by 4\n;\tadd\tax,512\t\t\t\t; add 512\n;\tmov\t[WORD PTR ds:si],ax\t\t; save new value\n;\tadd\tsi,2\t\t\t\t; next ptr word\n;\t;\n;\t;....................... see if we're done .........................\n;\t;\n;\tdec\tcx\n;\tjnz\t??Process_pointer\n;\tjmp\t??Done\n;\n;??One_color:\n;\t;\n;\t;......................... 1-color pointer .........................\n;\t;\n;\tnot\tax\t\t\t\t; get actual color value\n;\tshl\tax,1\t\t\t\t; multiply by 2\n;\tmov\t[WORD PTR ds:si],ax\t\t; save new value\n;\tadd\tsi,2\t\t\t\t; next ptr word\n;\t;\n;\t;....................... see if we're done .........................\n;\t;\n;\tdec\tcx\n;\tjnz\t??Process_pointer\n;\n;??Done:\n\tret\n\n\tENDP\tXlatePointers\n\n\tENDIF\t;VQAXMODE_ON\n\tEND\n\n\n\n\n\n"
  },
  {
    "path": "WINVQ/VQA32/VERTAG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vertag.c\n*\n* DESCRIPTION\n*     Version Tag\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     February 23, 1995\n*\n****************************************************************************/\n\n#include \"vqaplayp.h\"\n\n#ifdef __WATCOMC__\n#define DEVNAME \"Watcom/4GW\"\n#else\n#define DEVNAME \"Borland/TNT\"\n#endif\n\nchar VerTag[] = {\"$VER$\" VQA_IDSTRING\" \"DEVNAME\" (\"VQA_DATE\")\"};\nchar ReqTag[] = {\"$REQ$\" VQA_REQUIRES};\n\n"
  },
  {
    "path": "WINVQ/VQA32/VQAFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAFILE_H\n#define VQAFILE_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqafile.h\n*\n* DESCRIPTION\n*     VQA file format definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 10, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\iff.h>\n\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n\n/*---------------------------------------------------------------------------\n * STRUCTURE DEFINITIONS AND RELATED DEFINES.\n *-------------------------------------------------------------------------*/\n\n/* VQAHeader: VQA movie description header. (VQHD)\n *\n * Version       - VQA version.\n * Flags         - Various flags. (See below)\n * ImageWidth    - Image width in pixels.\n * ImageHeight   - Image height in pixels.\n * BlockWidth    - Block width in pixels.\n * BlockHeight   - Block height in pixels.\n * Frames        - Total number of frames in the movie.\n * FPS           - Playback rate (Frame Per Second).\n * Groupsize     - Frame grouping size (frames per codebook).\n * Num1Colors    - Number of 1 color colors.\n * CBentries     - Number of codebook entries.\n * Xpos          - X position to draw frames. (-1 = Center)\n * Ypos          - Y position to draw frames. (-1 = Center)\n * MaxFramesize  - Size of largest frame.\n * SampleRate    - Sample rate of primary audio stream.\n * Channels      - Number of channels in primary audio stream.\n * BitsPerSample - Sample bit size in primary audio stream.\n * FutureUse     - Reserved for future expansion.\n */\ntypedef struct _VQAHeader {\n\tunsigned short Version;\n\tunsigned short Flags;\n\tunsigned short Frames;\n\tunsigned short ImageWidth;\n\tunsigned short ImageHeight;\n\tunsigned char  BlockWidth;\n\tunsigned char  BlockHeight;\n\tunsigned char  FPS;\n\tunsigned char  Groupsize;\n\tunsigned short Num1Colors;\n\tunsigned short CBentries;\n\tunsigned short Xpos;\n\tunsigned short Ypos;\n\tunsigned short MaxFramesize;\n\tunsigned short SampleRate;\n\tunsigned char  Channels;\n\tunsigned char  BitsPerSample;\n\tunsigned short AltSampleRate;\n\tunsigned char  AltChannels;\n\tunsigned char  AltBitsPerSample;\n\tunsigned short FutureUse[5];\n} VQAHeader;\n\n/* Version type. */\n#define VQAHD_VER1 1\n#define VQAHD_VER2 2\n\n/* VQA header flag definitions */\n#define VQAHDB_AUDIO    0 /* Audio track present. */\n#define VQAHDB_ALTAUDIO 1 /* Alternate audio track present. */\n#define VQAHDF_AUDIO    (1<<VQAHDB_AUDIO)\n#define VQAHDF_ALTAUDIO (1<<VQAHDB_ALTAUDIO)\n\n\n/* Frame information (FINF) chunk definitions\n *\n * The FINF chunk contains a longword (4 bytes) entry for each\n * frame in the movie. This entry is divided into two parts,\n * flags (4 bits) and offset (28 bits).\n *\n * BITS   NAME     DESCRIPTION\n * -----------------------------------------------------------\n * 31-28  Flags    4 bitwise boolean flags.\n * 27-0   Offset   Offset in WORDS from the start of the file.\n */\n#define VQAFINB_KEY  31\n#define VQAFINB_PAL  30\n#define VQAFINB_SYNC 29\n#define VQAFINF_KEY  (1L<<VQAFINB_KEY)\n#define VQAFINF_PAL  (1L<<VQAFINB_PAL)\n#define VQAFINF_SYNC (1L<<VQAFINB_SYNC)\n\n/* FINF related defines and macros. */\n#define VQAFINF_OFFSET 0x0FFFFFFFL\n#define VQAFINF_FLAGS  0xF0000000L\n#define VQAFRAME_OFFSET(a) (((a & VQAFINF_OFFSET)<<1))\n\n/* VQ vector pointer codes. */\n#define VPC_ONE_SINGLE    0xF000 /* One single color block */\n#define VPC_ONE_SEMITRANS 0xE000 /* One semitransparent block */\n#define VPC_SHORT_DUMP    0xD000 /* Short dump of single color blocks */\n#define VPC_LONG_DUMP     0xC000 /* Long dump of single color blocks */\n#define VPC_SHORT_RUN     0xB000 /* Short run of single color blocks */\n#define VPC_LONG_RUN      0xA000 /* Long run */\n\n/* Long run codes. */\n#define LRC_SEMITRANS 0xC000 /* Long run of semitransparent blocks. */\n#define LRC_SINGLE    0x8000 /* Long run of single color blocks. */\n\n/* Defines used for Run-Skip-Dump compression. */\n#define MIN_SHORT_RUN_LENGTH  2\n#define MAX_SHORT_RUN_LENGTH  15\n#define MIN_LONG_RUN_LENGTH   2\n#define MAX_LONG_RUN_LENGTH   4095\n#define MIN_SHORT_DUMP_LENGTH 3\n#define MAX_SHORT_DUMP_LENGTH 15\n#define MIN_LONG_DUMP_LENGTH  2\n#define MAX_LONG_DUMP_LENGTH  4095\n\n#define WORD_HI_BIT 0x8000\n\n/*---------------------------------------------------------------------------\n * VQA FILE CHUNK ID DEFINITIONS.\n *-------------------------------------------------------------------------*/\n\n#define ID_WVQA MAKE_ID('W','V','Q','A') /* Westwood VQ Animation form. */\n#define ID_VQHD MAKE_ID('V','Q','H','D') /* VQ header. */\n#define ID_NAME MAKE_ID('N','A','M','E') /* Name string. */\n#define ID_FINF MAKE_ID('F','I','N','F') /* Frame information. */\n#define ID_VQFR MAKE_ID('V','Q','F','R') /* VQ frame container. */\n#define ID_VQFK MAKE_ID('V','Q','F','K') /* VQ key frame container. */\n#define ID_CBF0 MAKE_ID('C','B','F','0') /* Full codebook. */\n#define ID_CBFZ MAKE_ID('C','B','F','Z') /* Full codebook (compressed). */\n#define ID_CBP0 MAKE_ID('C','B','P','0') /* Partial codebook. */\n#define ID_CBPZ MAKE_ID('C','B','P','Z') /* Partial codebook (compressed). */\n#define ID_VPT0 MAKE_ID('V','P','T','0') /* Vector pointers. */\n#define ID_VPTZ MAKE_ID('V','P','T','Z') /* Vector pointers (compressed). */\n#define ID_VPTK MAKE_ID('V','P','T','K') /* Vector pointers (Delta Key). */\n#define ID_VPTD MAKE_ID('V','P','T','D') /* Vector pointers (Delta). */\n#define ID_VPTR MAKE_ID('V','P','T','R') /* Pointers RSD compressed. */\n#define ID_VPRZ MAKE_ID('V','P','R','Z') /* Pointers RSD, lcw compressed. */\n#define ID_CPL0 MAKE_ID('C','P','L','0') /* Color palette. */\n#define ID_CPLZ MAKE_ID('C','P','L','Z') /* Color palette (compressed). */\n#define ID_SND0 MAKE_ID('S','N','D','0') /* Sound */\n#define ID_SND1 MAKE_ID('S','N','D','1') /* Sound (Zap compressed). */\n#define ID_SND2 MAKE_ID('S','N','D','2') /* Sound (ADPCM compressed). */\n#define ID_SNDZ MAKE_ID('S','N','D','Z') /* Sound (LCW compression). */\n\n#define ID_SNA0 MAKE_ID('S','N','A','0') /* Sound */\n#define ID_SNA1 MAKE_ID('S','N','A','1') /* Sound (Zap compressed). */\n#define ID_SNA2 MAKE_ID('S','N','A','2') /* Sound (ADPCM compressed). */\n#define ID_SNAZ MAKE_ID('S','N','A','Z') /* Sound (LCW compression). */\n\n#define ID_CAP0 MAKE_ID('C','A','P','0') /* Caption text */\n#define ID_EVA0 MAKE_ID('E','V','A','0') /* EVA text */\n\n#ifdef __WATCOMC__\n#pragma pack();\n#endif\n\n#endif /* VQAFILE_H */\n\n"
  },
  {
    "path": "WINVQ/VQA32/VQAPLAY.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAPLAY_H\n#define VQAPLAY_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqaplay.h\n*\n* DESCRIPTION\n*      VQAPlay library definitions.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 10, 1995\n*\n****************************************************************************/\n\n/*---------------------------------------------------------------------------\n * CONDITIONAL COMPILATION FLAGS\n *-------------------------------------------------------------------------*/\n\n// MEG - 11.28.95 - added for debug\nextern void Debug_Printf( char *format_string, ... );\n\n#ifdef __WATCOMC__\n#define VQASTANDALONE 0  /* Stand alone player */\n#define VQAVOC_ON     0  /* Enable VOC file override */\n#define\tVQAMONO_ON    0  /* Mono display output enable/disable */\n#define VQADIRECT_SOUND 1       /* Use windows direct sound system */\n#define VQAAUDIO_ON   1  /* Audio playback enable/disable */\n#define VQAVIDEO_ON   0  /* Video manager enable/disable */\n#define VQAMCGA_ON    1  /* MCGA enable/disable */\n#define VQAXMODE_ON   0  /* Xmode enable/disable */\n#define VQAVESA_ON    0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2  1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4  0  /* 4x4 block decode enable/disable */\n#define VQAWOOFER_ON  0\n#else\n#define VQASTANDALONE 0  /* Stand alone player */\n#define VQAVOC_ON     0  /* Enable VOC file override */\n#define\tVQAMONO_ON    1  /* Mono display output enable/disable */\n#define VQADIRECT_SOUND 1\t/* Use windows direct sound system */\n#define VQAAUDIO_ON   1  /* Audio playback enable/disable */\n#define VQAVIDEO_ON   0  /* Video manager enable/disable */\n#define VQAMCGA_ON    1  /* MCGA enable/disable */\n#define VQAXMODE_ON   0  /* Xmode enable/disable */\n#define VQAVESA_ON    0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2  1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4  0  /* 4x4 block decode enable/disable */\n#define VQAWOOFER_ON  0\n#endif\n\n\n\n#if (VQAAUDIO_ON && VQADIRECT_SOUND)\n#define WIN32\n#define _WIN32\n#undef WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <windowsx.h>\n#include \"dsound.h\"\n#endif\n\n\n\n/*---------------------------------------------------------------------------\n * GENERAL CONSTANT DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* Playback modes. */\n#define VQAMODE_RUN   0  /* Run the movie through the end. */\n#define VQAMODE_WALK  1  /* Draw the next frame then return. */\n#define VQAMODE_PAUSE 2  /* Suspend movie playback. */\n#define VQAMODE_STOP  3  /* Stop the movie. */\n\n/* Playback timer methods */\n#define VQA_TMETHOD_DEFAULT -1 /* Use default timer method. */\n#define\tVQA_TMETHOD_DOS      1 /* DOS timer method */\n#define\tVQA_TMETHOD_INT      2 /* Interrupt timer method */\n#define\tVQA_TMETHOD_AUDIO    3 /* Audio timer method */\n\n#define\tVQA_TIMETICKS 60 /* Clock ticks per second */\n\n/* Error/Status conditions */\n#define VQAERR_NONE      0  /* No error */\n#define\tVQAERR_EOF      -1  /* Valid end of file */\n#define VQAERR_OPEN     -2  /* Unable to open */\n#define\tVQAERR_READ     -3  /* Read error */\n#define VQAERR_WRITE    -4  /* Write error */\n#define VQAERR_SEEK     -5  /* Seek error */\n#define VQAERR_NOTVQA   -6  /* Not a valid VQA file. */\n#define VQAERR_NOMEM    -7  /* Unable to allocate memory */\n#define\tVQAERR_NOBUFFER -8  /* No buffer avail for load/draw */\n#define\tVQAERR_NOT_TIME -9  /* Not time for frame yet */\n#define\tVQAERR_SLEEPING -10 /* Function is in a sleep state */\n#define VQAERR_VIDEO    -11 /* Video related error. */\n#define VQAERR_AUDIO    -12 /* Audio related error. */\n#define VQAERR_PAUSED   -13 /* In paused state. */\n\n/* Event flags. */\n#define VQAEVENT_PALETTE (1<<0)\n#define VQAEVENT_SYNC    (1<<1)\n\n\n/*---------------------------------------------------------------------------\n * STRUCTURES AND RELATED DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* VQAConfig: Player configuration structure\n *\n * DrawerCallback - User routine for Drawer to call each frame (NULL = none)\n * EventHandler   - User routine for notification to client of events.\n * NotifyFlags    - User specified events to be notified about.\n * Vmode          - Requested Video mode (May be promoted).\n * VBIBit         - Vertical blank bit polarity.\n * ImageBuf       - Pointer to caller's buffer for the Drawer to use as its\n *                  ImageBuf; NULL = player will allocate its own, if\n *                  VQACFGF_BUFFER is set in DrawFlags.\n * ImageWidth     - Width of Image buffer.\n * ImageHeight    - Height of Image buffer.\n * X1             - Draw window X coordinate (-1 = Center).\n * Y1             - Draw window Y coordinate (-1 = Center).\n * FrameRate      - Desired frames per second (-1 = use VQA header's value).\n * DrawRate       - Desired drawing frame rate; allows the Drawer to draw at\n *                  a separate rate from the Loader.\n * TimerMethod    - Timer method to use during playback.\n * DrawFlags      - Bits control various special drawing options. (See below)\n * OptionFlags    - Bits control various special misc options. (See below)\n * NumFrameBufs   - Desired number of frame buffers. (Default = 6)\n * NumCBBufs      - Desired number of codebook buffers. (Default = 3)\n * SoundObject\t\t- Ptr to callers Direct Sound Object (Default =NULL)\n * PrimaryBufferPtr- Ptr to callers Primary Sound Buffer. (Default = NULL)\n * VocFile        - Name of VOC file to play instead of VQA audio track.\n * AudioBuf       - Pointer to audio buffer.\n * AudioBufSize   - Size of audio buffer. (Default = 32768)\n * AudioRate      - Audio data playback rate (-1 = use samplerate scaled\n *                  to the frame rate)\n * Volume         - Audio playback volume. (0x7FFF = max)\n * HMIBufSize     - Desired HMI buffer size. (Default = 2000)\n * DigiHandle     - Handle to an initialized sound driver. (-1 = none)\n * DigiCard       - HMI ID of card to use. (0 = none, -1 = auto-detect)\n * DigiPort       - Audio port address. (-1 = auto-detect)\n * DigiIRQ        - Audio IRQ. (-1 = auto-detect)\n * DigiDMA        - Audio DMA channel. (-1 = auto-detect)\n * Language       - Language identifier. (Not used)\n * CapFont        - Pointer to font to use for subtitle text captions.\n * EVAFont        - Pointer to font to use for E.V.A text cations. (For C&C)\n */\ntypedef struct _VQAConfig {\n\tlong          \t\t\t(*DrawerCallback)(unsigned char *screen, long framenum);\n\tlong          \t\t\t(*EventHandler)(unsigned long event,void *buffer,long nbytes);\n\tunsigned long \t\t\tNotifyFlags;\n\tlong          \t\t\tVmode;\n\tlong          \t\t\tVBIBit;\n\tunsigned char \t\t\t*ImageBuf;\n\tlong          \t\t\tImageWidth;\n\tlong          \t\t\tImageHeight;\n\tlong          \t\t\tX1,Y1;\n\tlong          \t\t\tFrameRate;\n\tlong          \t\t\tDrawRate;\n\tlong          \t\t\tTimerMethod;\n\tlong          \t\t\tDrawFlags;\n\tlong          \t\t\tOptionFlags;\n\tlong          \t\t\tNumFrameBufs;\n\tlong          \t\t\tNumCBBufs;\n#if (VQADIRECT_SOUND)\n\tLPDIRECTSOUND\t\t\tSoundObject;\n\tLPDIRECTSOUNDBUFFER\tPrimaryBufferPtr;\n#endif\t//(VQADIRECT_SOUND)\n\tchar          \t\t\t*VocFile;\n\tunsigned char \t\t\t*AudioBuf;\n\tlong          \t\t\tAudioBufSize;\n\tlong          \t\t\tAudioRate;\n\tlong          \t\t\tVolume;\n\tlong          \t\t\tHMIBufSize;\n\tlong          \t\t\tDigiHandle;\n\tlong          \t\t\tDigiCard;\n\tlong          \t\t\tDigiPort;\n\tlong          \t\t\tDigiIRQ;\n\tlong          \t\t\tDigiDMA;\n\tlong          \t\t\tLanguage;\n\tchar          \t\t\t*CapFont;\n\tchar          \t\t\t*EVAFont; /* For C&C Only */\n} VQAConfig;\n\n/* Drawer Configuration flags (DrawFlags) */\n#define\tVQACFGB_BUFFER   0 /* Buffer UnVQ enable */\n#define\tVQACFGB_NODRAW   1 /* Drawing disable */\n#define VQACFGB_NOSKIP   2 /* Disable frame skipping. */\n#define\tVQACFGB_VRAMCB   3 /* XMode VRAM copy enable */\n#define VQACFGB_ORIGIN   4 /* 0,0 origin position */\n#define\tVQACFGB_SCALEX2  6 /* Scale X2 enable (VESA 320x200 to 640x400) */\n#define VQACFGB_WOOFER   7\n#define\tVQACFGF_BUFFER   (1<<VQACFGB_BUFFER)\n#define\tVQACFGF_NODRAW   (1<<VQACFGB_NODRAW)\n#define\tVQACFGF_NOSKIP   (1<<VQACFGB_NOSKIP)\n#define\tVQACFGF_VRAMCB   (1<<VQACFGB_VRAMCB)\n#define\tVQACFGF_ORIGIN   (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPLEFT  (0<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPRIGHT (1<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTRIGHT (2<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTLEFT  (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_SCALEX2  (1<<VQACFGB_SCALEX2)\n#define VQACFGF_WOOFER   (1<<VQACFGB_WOOFER)\n\n/* Options Configuration (OptionFlags) */\n#define\tVQAOPTB_AUDIO    0 /* Audio enable. */\n#define\tVQAOPTB_STEP     1 /* Single step enable. */\n#define\tVQAOPTB_MONO     2 /* Mono output enable. */\n#define VQAOPTB_PALOFF   3 /* Palette set disable. */\n#define\tVQAOPTB_SLOWPAL  4 /* Slow palette enable. */\n#define VQAOPTB_HMIINIT  5 /* HMI already initialized by client. */\n#define VQAOPTB_ALTAUDIO 6 /* Use alternate audio track. */\n#define VQAOPTB_CAPTIONS 7 /* Show captions. */\n#define VQAOPTB_EVA      8 /* Show EVA text (For C&C only) */\n#define\tVQAOPTF_AUDIO    (1<<VQAOPTB_AUDIO)\n#define\tVQAOPTF_STEP     (1<<VQAOPTB_STEP)\n#define\tVQAOPTF_MONO     (1<<VQAOPTB_MONO)\n#define VQAOPTF_PALOFF   (1<<VQAOPTB_PALOFF)\n#define\tVQAOPTF_SLOWPAL  (1<<VQAOPTB_SLOWPAL)\n#define VQAOPTF_HMIINIT  (1<<VQAOPTB_HMIINIT)\n#define\tVQAOPTF_ALTAUDIO (1<<VQAOPTB_ALTAUDIO)\n#define VQAOPTF_CAPTIONS (1<<VQAOPTB_CAPTIONS)\n#define VQAOPTF_EVA      (1<<VQAOPTB_EVA) /* For C&C only */\n\n\n/* VQAInfo: Information about the VQA movie.\n *\n * NumFrames   - The number of frames contained in the movie.\n * ImageHeight - Height of image in pixels.\n * ImageWidth  - Width of image in pixels.\n * ImageBuf    - Pointer to the image buffer VQA draw into.\n */\ntypedef struct _VQAInfo {\n\tlong NumFrames;\n\tlong ImageWidth;\n\tlong ImageHeight;\n\tunsigned char *ImageBuf;\n} VQAInfo;\n\n\n/* VQAStatistics: Statistics about the VQA movie played.\n *\n * StartTime     - Time movie started.\n * EndTime       - Time movie stoped.\n * FramesLoaded  - Total number of frames loaded.\n * FramesDrawn   - Total number of frames drawn.\n * FramesSkipped - Total number of frames skipped.\n * MaxFrameSize  - Size of largest frame.\n * SamplesPlayed - Number of sample bytes played.\n * MemUsed       - Total bytes used. (Low memory)\n */\ntypedef struct _VQAStatistics {\n\tlong          StartTime;\n\tlong          EndTime;\n\tlong          FramesLoaded;\n\tlong          FramesDrawn;\n\tlong          FramesSkipped;\n\tlong          MaxFrameSize;\n\tunsigned long SamplesPlayed;\n\tunsigned long MemUsed;\n} VQAStatistics;\n\n\n/* VQAHandle: VQA file handle. (Must be obtained by calling VQA_Alloc()\n *            and freed through VQA_Free(). This is the only legal way\n *            to obtain and dispose of a VQAHandle.\n *\n * VQAio - Something meaningful to the IO manager. (See DOCS)\n */\ntypedef struct _VQAHandle {\n\tunsigned long VQAio;\n} VQAHandle;\n\n/* Possible IO command values */\n#define VQACMD_INIT    1 /* Prepare the IO for a session */\n#define VQACMD_CLEANUP 2 /* Terminate IO session */\n#define VQACMD_OPEN    3 /* Open file */\n#define VQACMD_CLOSE   4 /* Close file */\n#define VQACMD_READ    5 /* Read bytes */\n#define VQACMD_WRITE   6 /* Write bytes */\n#define VQACMD_SEEK    7 /* Seek */\n\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n/* Configuration routines. */\nvoid VQA_INIConfig(VQAConfig *config);\nvoid VQA_DefaultConfig(VQAConfig *config);\n\n/* Handle manipulation routines. */\nVQAHandle *VQA_Alloc(void);\nvoid VQA_Free(VQAHandle *vqa);\nvoid VQA_Reset(VQAHandle *vqa);\nvoid VQA_InitAsDOS(VQAHandle *vqa);\nvoid VQA_Init(VQAHandle *vqa, long(*iohandler)(VQAHandle *vqa, long action,\n\t\tvoid *buffer, long nbytes));\nunsigned char *VQA_GetPalette(VQAHandle *vqa);\nlong VQA_GetPaletteSize(VQAHandle *vqa);\nvoid VQA_Set_DrawBuffer(VQAHandle *vqa, unsigned char *buffer,\n\t\tunsigned long width, unsigned long height,\n\t\tlong xpos, long ypos);\n\n/* File routines. */\nlong VQA_Open(VQAHandle *vqa, char const *filename, VQAConfig *config);\nvoid VQA_Close(VQAHandle *vqa);\nlong VQA_Play(VQAHandle *vqa, long mode);\nlong VQA_SeekFrame(VQAHandle *vqa, long frame, long fromwhere);\nlong VQA_SetStop(VQAHandle *vqa, long stop);\nvoid VQA_PauseAudio(void);\nvoid VQA_ResumeAudio(void);\n\n/* Information/statistics access routines. */\nvoid VQA_GetInfo(VQAHandle *vqa, VQAInfo *info);\nvoid VQA_GetStats(VQAHandle *vqa, VQAStatistics *stats);\nchar *VQA_Version(void);\nchar *VQA_IDString(void);\n\n#endif /* VQAPLAY_H */\n\n"
  },
  {
    "path": "WINVQ/VQA32/VQAPLAY.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAPLAY_H\n#define VQAPLAY_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqaplay.h\n*\n* DESCRIPTION\n*      VQAPlay library definitions.\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 10, 1995\n*\n****************************************************************************/\n\n/*---------------------------------------------------------------------------\n * CONDITIONAL COMPILATION FLAGS\n *-------------------------------------------------------------------------*/\n\n// MEG - 11.28.95 - added for debug\nextern void Debug_Printf( char *format_string, ... );\n\n#ifdef __WATCOMC__\n#define VQASTANDALONE 0  /* Stand alone player */\n#define VQAVOC_ON     0  /* Enable VOC file override */\n#define\tVQAMONO_ON    0  /* Mono display output enable/disable */\n#define VQADIRECT_SOUND 1       /* Use windows direct sound system */\n#define VQAAUDIO_ON   1  /* Audio playback enable/disable */\n#define VQAVIDEO_ON   0  /* Video manager enable/disable */\n#define VQAMCGA_ON    1  /* MCGA enable/disable */\n#define VQAXMODE_ON   0  /* Xmode enable/disable */\n#define VQAVESA_ON    0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2  1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4  0  /* 4x4 block decode enable/disable */\n#define VQAWOOFER_ON  0\n#else\n#define VQASTANDALONE 0  /* Stand alone player */\n#define VQAVOC_ON     0  /* Enable VOC file override */\n#define\tVQAMONO_ON    1  /* Mono display output enable/disable */\n#define VQADIRECT_SOUND 1\t/* Use windows direct sound system */\n#define VQAAUDIO_ON   1  /* Audio playback enable/disable */\n#define VQAVIDEO_ON   0  /* Video manager enable/disable */\n#define VQAMCGA_ON    1  /* MCGA enable/disable */\n#define VQAXMODE_ON   0  /* Xmode enable/disable */\n#define VQAVESA_ON    0  /* VESA enable/disable */\n#define\tVQABLOCK_2X2  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_2X3  0  /* 2x2 block decode enable/disable */\n#define\tVQABLOCK_4X2  1  /* 4x2 block decode enable/disable */\n#define\tVQABLOCK_4X4  0  /* 4x4 block decode enable/disable */\n#define VQAWOOFER_ON  0\n#endif\n\n\n\n#if (VQAAUDIO_ON && VQADIRECT_SOUND)\n#define WIN32 1\n#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check\n#define _WIN32\n#endif // _WIN32\n#undef WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <windowsx.h>\n#include \"dsound.h\"\n#endif\n\n\n\n/*---------------------------------------------------------------------------\n * GENERAL CONSTANT DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* Playback modes. */\n#define VQAMODE_RUN   0  /* Run the movie through the end. */\n#define VQAMODE_WALK  1  /* Draw the next frame then return. */\n#define VQAMODE_PAUSE 2  /* Suspend movie playback. */\n#define VQAMODE_STOP  3  /* Stop the movie. */\n\n/* Playback timer methods */\n#define VQA_TMETHOD_DEFAULT -1 /* Use default timer method. */\n#define\tVQA_TMETHOD_DOS      1 /* DOS timer method */\n#define\tVQA_TMETHOD_INT      2 /* Interrupt timer method */\n#define\tVQA_TMETHOD_AUDIO    3 /* Audio timer method */\n\n#define\tVQA_TIMETICKS 60 /* Clock ticks per second */\n\n/* Error/Status conditions */\n#define VQAERR_NONE      0  /* No error */\n#define\tVQAERR_EOF      -1  /* Valid end of file */\n#define VQAERR_OPEN     -2  /* Unable to open */\n#define\tVQAERR_READ     -3  /* Read error */\n#define VQAERR_WRITE    -4  /* Write error */\n#define VQAERR_SEEK     -5  /* Seek error */\n#define VQAERR_NOTVQA   -6  /* Not a valid VQA file. */\n#define VQAERR_NOMEM    -7  /* Unable to allocate memory */\n#define\tVQAERR_NOBUFFER -8  /* No buffer avail for load/draw */\n#define\tVQAERR_NOT_TIME -9  /* Not time for frame yet */\n#define\tVQAERR_SLEEPING -10 /* Function is in a sleep state */\n#define VQAERR_VIDEO    -11 /* Video related error. */\n#define VQAERR_AUDIO    -12 /* Audio related error. */\n#define VQAERR_PAUSED   -13 /* In paused state. */\n\n/* Event flags. */\n#define VQAEVENT_PALETTE (1<<0)\n#define VQAEVENT_SYNC    (1<<1)\n\n\n/*---------------------------------------------------------------------------\n * STRUCTURES AND RELATED DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* VQAConfig: Player configuration structure\n *\n * DrawerCallback - User routine for Drawer to call each frame (NULL = none)\n * EventHandler   - User routine for notification to client of events.\n * NotifyFlags    - User specified events to be notified about.\n * Vmode          - Requested Video mode (May be promoted).\n * VBIBit         - Vertical blank bit polarity.\n * ImageBuf       - Pointer to caller's buffer for the Drawer to use as its\n *                  ImageBuf; NULL = player will allocate its own, if\n *                  VQACFGF_BUFFER is set in DrawFlags.\n * ImageWidth     - Width of Image buffer.\n * ImageHeight    - Height of Image buffer.\n * X1             - Draw window X coordinate (-1 = Center).\n * Y1             - Draw window Y coordinate (-1 = Center).\n * FrameRate      - Desired frames per second (-1 = use VQA header's value).\n * DrawRate       - Desired drawing frame rate; allows the Drawer to draw at\n *                  a separate rate from the Loader.\n * TimerMethod    - Timer method to use during playback.\n * DrawFlags      - Bits control various special drawing options. (See below)\n * OptionFlags    - Bits control various special misc options. (See below)\n * NumFrameBufs   - Desired number of frame buffers. (Default = 6)\n * NumCBBufs      - Desired number of codebook buffers. (Default = 3)\n * SoundObject\t\t- Ptr to callers Direct Sound Object (Default =NULL)\n * PrimaryBufferPtr- Ptr to callers Primary Sound Buffer. (Default = NULL)\n * VocFile        - Name of VOC file to play instead of VQA audio track.\n * AudioBuf       - Pointer to audio buffer.\n * AudioBufSize   - Size of audio buffer. (Default = 32768)\n * AudioRate      - Audio data playback rate (-1 = use samplerate scaled\n *                  to the frame rate)\n * Volume         - Audio playback volume. (0x7FFF = max)\n * HMIBufSize     - Desired HMI buffer size. (Default = 2000)\n * DigiHandle     - Handle to an initialized sound driver. (-1 = none)\n * DigiCard       - HMI ID of card to use. (0 = none, -1 = auto-detect)\n * DigiPort       - Audio port address. (-1 = auto-detect)\n * DigiIRQ        - Audio IRQ. (-1 = auto-detect)\n * DigiDMA        - Audio DMA channel. (-1 = auto-detect)\n * Language       - Language identifier. (Not used)\n * CapFont        - Pointer to font to use for subtitle text captions.\n * EVAFont        - Pointer to font to use for E.V.A text cations. (For C&C)\n */\ntypedef struct _VQAConfig {\n\tlong          \t\t\t(*DrawerCallback)(unsigned char *screen, long framenum);\n\tlong          \t\t\t(*EventHandler)(unsigned long event,void *buffer,long nbytes);\n\tunsigned long \t\t\tNotifyFlags;\n\tlong          \t\t\tVmode;\n\tlong          \t\t\tVBIBit;\n\tunsigned char \t\t\t*ImageBuf;\n\tlong          \t\t\tImageWidth;\n\tlong          \t\t\tImageHeight;\n\tlong          \t\t\tX1,Y1;\n\tlong          \t\t\tFrameRate;\n\tlong          \t\t\tDrawRate;\n\tlong          \t\t\tTimerMethod;\n\tlong          \t\t\tDrawFlags;\n\tlong          \t\t\tOptionFlags;\n\tlong          \t\t\tNumFrameBufs;\n\tlong          \t\t\tNumCBBufs;\n#if (VQADIRECT_SOUND)\n\tLPDIRECTSOUND\t\t\tSoundObject;\n\tLPDIRECTSOUNDBUFFER\tPrimaryBufferPtr;\n#endif\t//(VQADIRECT_SOUND)\n\tchar          \t\t\t*VocFile;\n\tunsigned char \t\t\t*AudioBuf;\n\tlong          \t\t\tAudioBufSize;\n\tlong          \t\t\tAudioRate;\n\tlong          \t\t\tVolume;\n\tlong          \t\t\tHMIBufSize;\n\tlong          \t\t\tDigiHandle;\n\tlong          \t\t\tDigiCard;\n\tlong          \t\t\tDigiPort;\n\tlong          \t\t\tDigiIRQ;\n\tlong          \t\t\tDigiDMA;\n\tlong          \t\t\tLanguage;\n\tchar          \t\t\t*CapFont;\n\tchar          \t\t\t*EVAFont; /* For C&C Only */\n} VQAConfig;\n\n/* Drawer Configuration flags (DrawFlags) */\n#define\tVQACFGB_BUFFER   0 /* Buffer UnVQ enable */\n#define\tVQACFGB_NODRAW   1 /* Drawing disable */\n#define VQACFGB_NOSKIP   2 /* Disable frame skipping. */\n#define\tVQACFGB_VRAMCB   3 /* XMode VRAM copy enable */\n#define VQACFGB_ORIGIN   4 /* 0,0 origin position */\n#define\tVQACFGB_SCALEX2  6 /* Scale X2 enable (VESA 320x200 to 640x400) */\n#define VQACFGB_WOOFER   7\n#define\tVQACFGF_BUFFER   (1<<VQACFGB_BUFFER)\n#define\tVQACFGF_NODRAW   (1<<VQACFGB_NODRAW)\n#define\tVQACFGF_NOSKIP   (1<<VQACFGB_NOSKIP)\n#define\tVQACFGF_VRAMCB   (1<<VQACFGB_VRAMCB)\n#define\tVQACFGF_ORIGIN   (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPLEFT  (0<<VQACFGB_ORIGIN)\n#define\tVQACFGF_TOPRIGHT (1<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTRIGHT (2<<VQACFGB_ORIGIN)\n#define\tVQACFGF_BOTLEFT  (3<<VQACFGB_ORIGIN)\n#define\tVQACFGF_SCALEX2  (1<<VQACFGB_SCALEX2)\n#define VQACFGF_WOOFER   (1<<VQACFGB_WOOFER)\n\n/* Options Configuration (OptionFlags) */\n#define\tVQAOPTB_AUDIO    0 /* Audio enable. */\n#define\tVQAOPTB_STEP     1 /* Single step enable. */\n#define\tVQAOPTB_MONO     2 /* Mono output enable. */\n#define VQAOPTB_PALOFF   3 /* Palette set disable. */\n#define\tVQAOPTB_SLOWPAL  4 /* Slow palette enable. */\n#define VQAOPTB_HMIINIT  5 /* HMI already initialized by client. */\n#define VQAOPTB_ALTAUDIO 6 /* Use alternate audio track. */\n#define VQAOPTB_CAPTIONS 7 /* Show captions. */\n#define VQAOPTB_EVA      8 /* Show EVA text (For C&C only) */\n#define\tVQAOPTF_AUDIO    (1<<VQAOPTB_AUDIO)\n#define\tVQAOPTF_STEP     (1<<VQAOPTB_STEP)\n#define\tVQAOPTF_MONO     (1<<VQAOPTB_MONO)\n#define VQAOPTF_PALOFF   (1<<VQAOPTB_PALOFF)\n#define\tVQAOPTF_SLOWPAL  (1<<VQAOPTB_SLOWPAL)\n#define VQAOPTF_HMIINIT  (1<<VQAOPTB_HMIINIT)\n#define\tVQAOPTF_ALTAUDIO (1<<VQAOPTB_ALTAUDIO)\n#define VQAOPTF_CAPTIONS (1<<VQAOPTB_CAPTIONS)\n#define VQAOPTF_EVA      (1<<VQAOPTB_EVA) /* For C&C only */\n\n\n/* VQAInfo: Information about the VQA movie.\n *\n * NumFrames   - The number of frames contained in the movie.\n * ImageHeight - Height of image in pixels.\n * ImageWidth  - Width of image in pixels.\n * ImageBuf    - Pointer to the image buffer VQA draw into.\n */\ntypedef struct _VQAInfo {\n\tlong NumFrames;\n\tlong ImageWidth;\n\tlong ImageHeight;\n\tunsigned char *ImageBuf;\n} VQAInfo;\n\n\n/* VQAStatistics: Statistics about the VQA movie played.\n *\n * StartTime     - Time movie started.\n * EndTime       - Time movie stoped.\n * FramesLoaded  - Total number of frames loaded.\n * FramesDrawn   - Total number of frames drawn.\n * FramesSkipped - Total number of frames skipped.\n * MaxFrameSize  - Size of largest frame.\n * SamplesPlayed - Number of sample bytes played.\n * MemUsed       - Total bytes used. (Low memory)\n */\ntypedef struct _VQAStatistics {\n\tlong          StartTime;\n\tlong          EndTime;\n\tlong          FramesLoaded;\n\tlong          FramesDrawn;\n\tlong          FramesSkipped;\n\tlong          MaxFrameSize;\n\tunsigned long SamplesPlayed;\n\tunsigned long MemUsed;\n} VQAStatistics;\n\n\n/* VQAHandle: VQA file handle. (Must be obtained by calling VQA_Alloc()\n *            and freed through VQA_Free(). This is the only legal way\n *            to obtain and dispose of a VQAHandle.\n *\n * VQAio - Something meaningful to the IO manager. (See DOCS)\n */\ntypedef struct _VQAHandle {\n\tunsigned long VQAio;\n} VQAHandle;\n\n/* Possible IO command values */\n#define VQACMD_INIT    1 /* Prepare the IO for a session */\n#define VQACMD_CLEANUP 2 /* Terminate IO session */\n#define VQACMD_OPEN    3 /* Open file */\n#define VQACMD_CLOSE   4 /* Close file */\n#define VQACMD_READ    5 /* Read bytes */\n#define VQACMD_WRITE   6 /* Write bytes */\n#define VQACMD_SEEK    7 /* Seek */\n\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n/* Configuration routines. */\nvoid VQA_INIConfig(VQAConfig *config);\nvoid VQA_DefaultConfig(VQAConfig *config);\n\n/* Handle manipulation routines. */\nVQAHandle *VQA_Alloc(void);\nvoid VQA_Free(VQAHandle *vqa);\nvoid VQA_Reset(VQAHandle *vqa);\nvoid VQA_InitAsDOS(VQAHandle *vqa);\nvoid VQA_Init(VQAHandle *vqa, long(*iohandler)(VQAHandle *vqa, long action,\n\t\tvoid *buffer, long nbytes));\nunsigned char *VQA_GetPalette(VQAHandle *vqa);\nlong VQA_GetPaletteSize(VQAHandle *vqa);\nvoid VQA_Set_DrawBuffer(VQAHandle *vqa, unsigned char *buffer,\n\t\tunsigned long width, unsigned long height,\n\t\tlong xpos, long ypos);\n\n/* File routines. */\nlong VQA_Open(VQAHandle *vqa, char const *filename, VQAConfig *config);\nvoid VQA_Close(VQAHandle *vqa);\nlong VQA_Play(VQAHandle *vqa, long mode);\nlong VQA_SeekFrame(VQAHandle *vqa, long frame, long fromwhere);\nlong VQA_SetStop(VQAHandle *vqa, long stop);\nvoid VQA_PauseAudio(void);\nvoid VQA_ResumeAudio(void);\n\n/* Information/statistics access routines. */\nvoid VQA_GetInfo(VQAHandle *vqa, VQAInfo *info);\nvoid VQA_GetStats(VQAHandle *vqa, VQAStatistics *stats);\nchar *VQA_Version(void);\nchar *VQA_IDString(void);\n\n#endif /* VQAPLAY_H */\n\n"
  },
  {
    "path": "WINVQ/VQA32/VQAPLAY.I",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PROJECT\n;*     VQAPlay 32 library.\n;*\n;* FILE\n;*     vqaplay.i\n;*\n;* DESCRIPTION\n;*      VQA player definitions.\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 30, 1995\n;*\n;****************************************************************************\n\n;*---------------------------------------------------------------------------\n;* CONDITIONAL COMPILATION FLAGS\n;*---------------------------------------------------------------------------\n\n\tIF\tPHARLAP_TNT\n\nVQASTANDALONE\tEQU\t0\t;Stand alone player\nVQAMONO_ON\tEQU\t1\t;Mono display output enable/disable\nVQAAUDIO_ON\tEQU\t0\t;Audio playback enable/disable\nVQAVIDEO_ON\tEQU\t0\t;Video manager enable/disable\nVQAMCGA_ON\tEQU\t1\t;MCGA enable/disable\nVQAXMODE_ON\tEQU\t0\t;Xmode enable/disable\nVQAVESA_ON\tEQU\t0\t;VESA enable/disable\nVQABLOCK_2X2\tEQU\t0\t;2x2 block decode enable/disable\nVQABLOCK_2X3\tEQU\t0\t;2x3 block decode enable/disable\nVQABLOCK_4X2\tEQU\t1\t;4x2 block decode enable/disable\nVQABLOCK_4X4\tEQU\t1\t;4x4 block decode enable/disable\nVQABLOCK_WOOFER\tEQU\t0\n\n\tELSE\n\nVQASTANDALONE\tEQU\t0\t;Stand alone player\nVQAMONO_ON\tEQU\t0\t;Mono display output enable/disable\nVQAAUDIO_ON\tEQU\t1\t;Audio playback enable/disable\nVQAVIDEO_ON\tEQU\t0\t;Video manager enable/disable\nVQAMCGA_ON\tEQU\t1\t;MCGA enable/disable\nVQAXMODE_ON\tEQU\t0\t;Xmode enable/disable\nVQAVESA_ON\tEQU\t0\t;VESA enable/disable\nVQABLOCK_2X2\tEQU\t0\t;2x2 block decode enable/disable\nVQABLOCK_2X3\tEQU\t0\t;2x3 block decode enable/disable\nVQABLOCK_4X2\tEQU\t1\t;4x2 block decode enable/disable\nVQABLOCK_4X4\tEQU\t1\t;4x4 block decode enable/disable\nVQABLOCK_WOOFER\tEQU\t0\n\n\tENDIF\n"
  },
  {
    "path": "WINVQ/VQA32/VQAPLAYP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAPLAYP_H\n#define VQAPLAYP_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQA player library. (32-Bit protected mode)\n*\n* FILE\n*     vqaplayp.h\n*\n* DESCRIPTION\n*     VQAPlay private library definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*     Bill Randolph\n*\n* DATE\n*     August 21, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\video.h>\n#include <vqm32\\soscomp.h>\n#include <vqm32\\captoken.h>\n#include \"vqafile.h\"\n#include \"vqaplay.h\"\n#include \"caption.h\"\n\n#if(VQAAUDIO_ON)\n#if(VQADIRECT_SOUND)\nextern HWND MainWindow;\n#else\n#include \"sos.h\"\n#endif\n#endif\n\n/*---------------------------------------------------------------------------\n * GENERAL CONSTANT DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* Internal library version. */\n#define VQA_VERSION \"2.42\"\n#define VQA_DATE    __DATE__\" \"__TIME__\n\n#define VQA_IDSTRING \"VQA32 \"VQA_VERSION\" (\"VQA_DATE\")\"\n#define VQA_REQUIRES \"VQM32 2.12 or better.\"\n\n/* Block dimensions macro and identifiers. */\n#define BLOCK_DIM(a,b) (((a&0xFF)<<8)|(b&0xFF))\n#define BLOCK_2X2 BLOCK_DIM(2,2)\n#define BLOCK_2X3 BLOCK_DIM(2,3)\n#define BLOCK_4X2 BLOCK_DIM(4,2)\n#define BLOCK_4X4 BLOCK_DIM(4,4)\n\n/* Memory limits */\n#define\tVQA_MAX_CBBUFS    10 /* Maximum number of codebook buffers */\n#define\tVQA_MAX_FRAMEBUFS 30 /* Maximum number of frame buffers */\n\n/* Special Constants */\n#define\tVQA_MASK_POINTER 0x8000 /* Pointer value to use for masking. */\n\n\n/*---------------------------------------------------------------------------\n * STRUCTURES AND RELATED DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* ChunkHeader: IFF chunk identifier header.\n *\n * id   - 4 Byte chunk id.\n * size - Size of chunk.\n */\ntypedef struct _ChunkHeader {\n\tunsigned long id;\n\tunsigned long size;\n} ChunkHeader;\n\n\n/* ZAPHeader: ZAP audio compression header. NOTE: If the uncompressed size\n *            and the compressed size are equal then the audio frame is RAW\n *            (NOT COMPRESSED).\n *\n * UnCompSize - Uncompressed size in bytes.\n * CompSize   - Compressed size in bytes.\n */\ntypedef struct _ZAPHeader {\n\tunsigned short UnCompSize;\n\tunsigned short CompSize;\n} ZAPHeader;\n\n\n/* VQACBNode: A circular list of codebook buffers, used by the load task.\n *            If the data is compressed, it is loaded into the end of the\n *            buffer and the compression flags is set. Otherwise the data\n *            is loaded into the start of the buffer.\n *            (Make sure this structure's size is always DWORD aligned.)\n *\n * Buffer   - Pointer to Codebook data.\n * Next     - Pointer to next VQACBNode in the codebook list.\n * Flags    - Used by the drawer to tell if certain operations have been\n *            performed on this codebook, such as downloading to VRAM,\n *            or pre-scaling it. This field is cleared by the Loader when a\n *            new codebook is loaded.\n * CBOffset - Offset into the buffer of the compressed data.\n */\ntypedef struct _VQACBNode {\n\tunsigned char     *Buffer;\n\tstruct _VQACBNode *Next;\n\tunsigned long     Flags;\n\tunsigned long     CBOffset;\n} VQACBNode;\n\n/* VQACBNode flags */\n#define\tVQACBB_DOWNLOADED 0 /* Download codebook to VRAM (XMODE VRAM) */\n#define VQACBB_CBCOMP     1 /* Codebook is compressed */\n#define\tVQACBF_DOWNLOADED (1<<VQACBB_DOWNLOADED)\n#define\tVQACBF_CBCOMP     (1<<VQACBB_CBCOMP)\n\n\n/* VQAFrameNode: A circular list of frame buffers, filled in by the load\n *               task. If the data is compressed, it is loaded into the end\n *               of the buffer and the compress flag is set. Otherwise, it's\n *               loaded into the start of the buffer.\n *               (Make sure this structure's size is always DWORD aligned.)\n *\n * Pointers    - Pointer to the vector pointer data.\n * Codebook    - Pointer to VQACBNode list entry for this frame.\n * Palette     - Pointer to an array of palette colors (R,G,B).\n * Next        - Pointer to the next entry in the Frame Buffer List.\n * Flags       - Inter-process communication flags for this frame (see below)\n *               set by Loader, cleared by Flipper.\n * FrameNum    - Number of this frame in the animation.\n * PtrOffset   - Offset into buffer of the compressed vector pointer data.\n * PalOffset   - Offset into buffer of the compressed palette data.\n * PaletteSize - Size of the palette for this frame (in bytes).\n */\ntypedef struct _VQAFrameNode {\n\tunsigned char        *Pointers;\n\tVQACBNode            *Codebook;\n\tunsigned char        *Palette;\n\tstruct _VQAFrameNode *Next;\n\tunsigned long        Flags;\n\tlong                 FrameNum;\n\tlong                 PtrOffset;\n\tlong                 PalOffset;\n\tlong                 PaletteSize;\n} VQAFrameNode;\n\n/* FrameNode flags */\n#define\tVQAFRMB_LOADED  0 /* Frame loaded */\n#define\tVQAFRMB_KEY     1 /* Key Frame (must be drawn) */\n#define\tVQAFRMB_PALETTE 2 /* Palette needs set */\n#define VQAFRMB_PALCOMP 3 /* Palette is compressed */\n#define VQAFRMB_PTRCOMP 4 /* Vector pointer data is compressed */\n#define\tVQAFRMF_LOADED  (1<<VQAFRMB_LOADED)\n#define\tVQAFRMF_KEY     (1<<VQAFRMB_KEY)\n#define\tVQAFRMF_PALETTE (1<<VQAFRMB_PALETTE)\n#define\tVQAFRMF_PALCOMP (1<<VQAFRMB_PALCOMP)\n#define\tVQAFRMF_PTRCOMP (1<<VQAFRMB_PTRCOMP)\n\n\n/* VQALoader: Data needed exclusively by the Loader.\n *            (Make sure this structure's size is always DWORD aligned.)\n *\n * CurCB         - Pointer to the current codebook node to load data into.\n * FullCB        - Pointer to the last fully-loaded codebook node.\n * CurFrame      - Pointer to the current frame node to load data into.\n * NumPartialCB  - Number of partial codebooks accumulated.\n * PartialCBSize - Size of partial codebook (LCW'd or not), in bytes\n * CurFrameNum   - The number of the frame being loaded by the Loader.\n * LastCBFrame   - Last frame in the animation that contains a partial CB\n * LastFrameNum  - Number of the last loaded frame\n * WaitsOnDrawer - Number of wait states Loader hits waiting on the Drawer\n * WaitsOnAudio  - Number of wait states Loader hits waiting on HMI\n * FrameSize     - Size of the last frame in bytes.\n * MaxFrameSize  - Size of the largest frame in the animation.\n * CurChunkHdr   - Chunk header of the chunk currently being processed.\n */\ntypedef struct _VQALoader {\n\tVQACBNode    *CurCB;\n\tVQACBNode    *FullCB;\n\tVQAFrameNode *CurFrame;\n\tlong         NumPartialCB;\n\tlong         PartialCBSize;\n\tlong         CurFrameNum;\n\tlong         LastCBFrame;\n\tlong         LastFrameNum;\n\tlong         WaitsOnDrawer;\n\tlong         WaitsOnAudio;\n\tlong         FrameSize;\n\tlong         MaxFrameSize;\n\tChunkHeader  CurChunkHdr;\n} VQALoader;\n\n\n/* VQADrawer: Data needed exclusively by the Drawer.\n *            (Make sure this structure's size is always DWORD aligned.)\n *\n * CurFrame       - Pointer to the current frame to draw.\n * Flags          - Flags for the draw routines (IE: VQADRWF_SETPAL)\n * Display        - Pointer to DisplayInfo structure for active video mode.\n * ImageBuf       - Buffer to un-vq into, must be DWORD aligned.\n * ImageWidth     - Width of Image buffer (in pixels).\n * ImageHeight    - Height of Image buffer (in pixels).\n * X1,Y1,X2,Y2    - Coordinates of image corners (in pixels).\n * ScreenOffset   - Offset into screen memory, for centering small images.\n * CurPalSize     - Size of the current palette in bytes.\n * Palette_24     - Copy of the last-loaded palette\n * Palette_15     - 15-bit version of Palette_24, for 32K-color modes\n * BlocksPerRow   - # of VQ blocks per row for this resolution/block width.\n * NumRows        - # of rows of VQ blocks for this resolution/block height.\n * NumBlocks      - Total number of blocks in the image.\n * MaskStart      - Pointer index of start of mask rectangle.\n * MaskWidth      - Width of mask rectangle, in blocks.\n * MaskHeight     - Height of mask rectangle, in blocks.\n * LastTime       - The time when that last frame was drawn.\n * LastFrame      - The number of the last frame selected.\n * LastFrameNum   - Number of the last frame drawn.\n * DesiredFrame   - The number of the frame that should be drawn.\n * NumSkipped     - Number of frames skipped.\n * WaitsOnFlipper - Number of wait states Drawer hits waiting on the Flipper.\n * WaitsOnLoader  - Number of wait states Drawer hits waiting on the Loader.\n */\ntypedef struct _VQADrawer {\n\tVQAFrameNode  *CurFrame;\n\tunsigned long Flags;\n\tDisplayInfo   *Display;\n\tunsigned char *ImageBuf;\n\tlong          ImageWidth;\n\tlong          ImageHeight;\n\tlong          X1,Y1,X2,Y2;\n\tlong          ScreenOffset;\n\tlong          CurPalSize;\n\tunsigned char Palette_24[768];\n\tunsigned char Palette_15[512];\n\tlong          BlocksPerRow;\n\tlong          NumRows;\n\tlong          NumBlocks;\n\tlong          MaskStart;\n\tlong          MaskWidth;\n\tlong          MaskHeight;\n\tlong          LastTime;\n\tlong          LastFrame;\n\tlong          LastFrameNum;\n\tlong          DesiredFrame;\n\tlong          NumSkipped;\n\tlong          WaitsOnFlipper;\n\tlong          WaitsOnLoader;\n} VQADrawer;\n\n/* Drawer flags */\n#define\tVQADRWB_SETPAL 0  /* Set palette */\n#define\tVQADRWF_SETPAL (1<<VQADRWB_SETPAL)\n\n\n/* VQAFlipper: Data needed exclusively by the page-flipper.\n *             (Make sure this structure's size is always DWORD aligned.)\n *\n * CurFrame     - Pointer to current flipper frame.\n * LastFrameNum - Number of last flipped frame\n * pad          - DWORD alignment padding.\n */\ntypedef struct _VQAFlipper {\n\tVQAFrameNode *CurFrame;\n\tlong         LastFrameNum;\n} VQAFlipper;\n\n\n#if(VQAAUDIO_ON)\n\n#ifdef __WATCOMC__\n#pragma pack(4);\n#endif\n\n/* VQAAudio: Data needed exclusively by audio playback.\n *           (Make sure this structure's size is always DWORD aligned.)\n *\n * Buffer         - Pointer to the audio buffer.\n * AudBufPos      - Current audio buffer position, for copying data in buffer.\n * IsLoaded       - Inter-process communication flag:\n *                  0 = is loadable, 1 = is not. Loader sets it when it\n *                  loads, audio callback clears it when it plays one.\n * NumAudBlocks   - Number of HMI blocks in the audio buffer.\n * CurBlock       - Current audio block\n * NextBlock      - Next audio block\n * TempBuf        - Pointer to temp buffer for loading/decompressing audio\n *                  data.\n * TempBufLen     - Number of bytes loaded into temp buffer.\n * TempBufSize    - Size of temp buffer in bytes.\n * Flags          - Various audio flags. (See below)\n * PlayPosition   - HMI's current buffer position.\n * SamplesPlayed  - Total samples played.\n * NumSkipped     - Count of buffers missed.\n * SampleRate     - Recorded sampling rate of the track.\n * Channels       - Number of channels in the track.\n * BitsPerSample  - Bit resolution size of sample (8,16)\n * BytesPerSec    - Recorded data transfer for one second.\n * ADPCM_Info     - ADPCM decompression information structure.\n * DigiHandle     - HMI digital device handle.\n * SampleHandle   - HMI sample handle.\n * DigiTimer      - HMI digital fill handler timer handle.\n * sSOSSampleData - HMI sample structure.\n * DigiCaps       - HMI sound card digital capabilities.\n * DigiHardware   - HMI sound card digital hardware settings.\n * sSOSInitDriver - HMI driver initialization structure.\n * TimerHandle\t\t- Handle to Windows multi-media timer\n * SoundTimerHandle- Handle to extra Windows mm timer req. for direct sound\n * SecondaryBufferPtr - Pointer to out direct sound secondary buffer\n * DSBuffFormat\t\t- WAVEFORMATEX structure for direct sound\n * BufferDesc\t\t- Description structure for setting up direct sound buffers\n * SecondaryBufferSize - length in bytes of our secondary sound buffer\n * EndLastAudioChunk - Offset into secondary buffer of the end of the last chunk of audio copied in\n * ChunksMovedToAudioBuffer - Total number of HMIBufSize chunks moved into the secondary buffer\n * LastChunkPosition - Offset position of last chunk copied to secondary buffer\n * CreatedSoundObject - True if we had to create our own direct sound object\n * CreatedSoundBuffer - True if we had to create out own direct sound primary buffer\n */\ntypedef struct _VQAAudio {\n\tunsigned char      *Buffer;\n\tunsigned long      AudBufPos;\n\tshort              *IsLoaded;\n\tunsigned long      NumAudBlocks;\n\tunsigned long      CurBlock;\n\tunsigned long      NextBlock;\n\tunsigned char      *TempBuf;\n\tunsigned long      TempBufLen;\n\tunsigned long      TempBufSize;\n\tunsigned long      Flags;\n\tunsigned long      PlayPosition;\n\tunsigned long      SamplesPlayed;\n\tunsigned long      NumSkipped;\n\tunsigned short     SampleRate;\n\tunsigned char      Channels;\n\tunsigned char      BitsPerSample;\n\tunsigned long      BytesPerSec;\n\t_SOS_COMPRESS_INFO ADPCM_Info;\n#if (!VQADIRECT_SOUND)\n\tWORD               DigiHandle;\n\tWORD               SampleHandle;\n\tWORD               DigiTimer;\n\t_SOS_START_SAMPLE  sSOSSampleData;\n\t_SOS_CAPABILITIES  DigiCaps;\n\t_SOS_HARDWARE      DigiHardware;\n\t_SOS_INIT_DRIVER   sSOSInitDriver;\n#else\n\tunsigned\t\t\t\t\tTimerHandle;\n\tunsigned\t\t\t\t\tSoundTimerHandle;\n\tLPDIRECTSOUNDBUFFER\tSecondaryBufferPtr;\n\tWAVEFORMATEX\t\t\tDsBuffFormat;\n\tDSBUFFERDESC\t\t\tBufferDesc;\n\tunsigned\t\t\t\t\tSecondaryBufferSize;\n\tunsigned\t\t\t\t\tEndLastAudioChunk;\n\tunsigned\t\t\t\t\tChunksMovedToAudioBuffer;\n\tunsigned\t\t\t\t\tLastChunkPosition;\n\tBOOL\t\t\t\t\t\tCreatedSoundObject;\n\tBOOL\t\t\t\t\t\tCreatedSoundBuffer;\n#endif\n} VQAAudio;\n\n/* Audio flags. */\n#define VQAAUDB_DIGIINIT  0  /* HMI digital driver initialized (2 bits) */\n#define VQAAUDB_TIMERINIT 2  /* HMI timer system initialized (2 bits) */\n#define VQAAUDB_HMITIMER  4  /* HMI timer callback initialized (2 bits) */\n#define VQAAUDB_ISPLAYING 6  /* Audio playing flag. */\n#define VQAAUDB_MEMLOCKED 30 /* Audio memory page locked. */\n#define VQAAUDB_MODLOCKED 31 /* Audio module page locked. */\n\n#define VQAAUDF_DIGIINIT  (3<<VQAAUDB_DIGIINIT)\n#define VQAAUDF_TIMERINIT (3<<VQAAUDB_TIMERINIT)\n#define VQAAUDF_HMITIMER  (3<<VQAAUDB_HMITIMER)\n#define VQAAUDF_ISPLAYING (1<<VQAAUDB_ISPLAYING)\n#define VQAAUDF_MEMLOCKED (1<<VQAAUDB_MEMLOCKED)\n#define VQAAUDF_MODLOCKED (1<<VQAAUDB_MODLOCKED)\n\n/* HMI device initialization conditions. (DIGIINIT, TIMERINIT, HMITIMER) */\n#define HMI_UNINIT  0  /* Unitialize state. */\n#define HMI_VQAINIT 1  /* VQA initialized */\n#define HMI_APPINIT 2  /* Application initialized */\n\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n\n#endif /* VQAAUDIO_ON */\n\n\n/* VQAData: This stucture contains all the data used for playing a VQA.\n *\n * Draw_Frame   - Pointer to the draw-frame routine for this video mode.\n * Page_Flip    - Pointer to the page flip function for this video mode.\n * UnVQ         - Pointer to the UnVQ routine for this vid mode & blk size.\n * FrameData    - Frame buffer circular list head.\n * CBData       - Codebook circular list head.\n * Audio        - Audio buffer\n * Loader       - Loader's data\n * Drawer       - Drawer's data\n * Flipper      - Flipper's data\n * Flags        - Flags used by the player.\n * Foff         - Pointer to frame offset table.\n * VBIBit       - Vertical blank bit polarity.\n * Max_CB_Size  - Maximum size of an uncompressed codebook\n * Max_Pal_Size - Maximum size of an uncompressed palette\n * Max_Ptr_Size - Maximum size of uncompressed pointer data\n * LoadedFrames - Number of frames loaded\n * DrawnFrames  - Number of frames drawn\n * StartTime    - Start time in VQA time ticks\n * EndTime      - Stop time in VQA time ticks\n * MemUsed      - Number of bytes allocated by VQA_AllocBuffers\n */\ntypedef struct _VQAData {\n\tlong (*Draw_Frame)(VQAHandle *vqa);\n\tlong (*Page_Flip)(VQAHandle *vqa);\n\n\t#ifndef PHARLAP_TNT\n\tvoid __cdecl (*UnVQ)(unsigned char *codebook, unsigned char *pointers,\n\t\t\tunsigned char *buffer, unsigned long blocksperrow,\n\t\t\tunsigned long numrows, unsigned long bufwidth);\n\t#else\n\tvoid __cdecl (*UnVQ)(unsigned char *codebook, unsigned char *pointers,\n\t\t\tFARPTR buffer, unsigned long blocksperrow, unsigned long numrows,\n\t\t\tunsigned long bufwidth);\n\t#endif\n\n\tVQAFrameNode  *FrameData;\n\tVQACBNode     *CBData;\n\n\t#if(VQAAUDIO_ON)\n\tVQAAudio      Audio;\n\t#endif\n\n\tVQALoader     Loader;\n\tVQADrawer     Drawer;\n\tVQAFlipper    Flipper;\n\tunsigned long Flags;\n\tlong          *Foff;\n\tlong          VBIBit;\n\tlong          Max_CB_Size;\n\tlong          Max_Pal_Size;\n\tlong          Max_Ptr_Size;\n\tlong          LoadedFrames;\n\tlong          DrawnFrames;\n\tlong          StartTime;\n\tlong          EndTime;\n\tlong          MemUsed;\n} VQAData;\n\n/* VQAData flags */\n#define VQADATB_UPDATE 0 /* Update the display. */\n#define VQADATB_DSLEEP 1 /* Drawer sleep state. */\n#define VQADATB_LSLEEP 2 /* Loader sleep state. */\n#define VQADATB_DDONE  3 /* Drawer done flag. (0 = done) */\n#define VQADATB_LDONE  4 /* Loader done flag. (0 = done) */\n#define VQADATB_PRIMED 5 /* Buffers are primed. */\n#define VQADATB_PAUSED 6 /* The player is paused. */\n#define VQADATF_UPDATE (1<<VQADATB_UPDATE)\n#define VQADATF_DSLEEP (1<<VQADATB_DSLEEP)\n#define VQADATF_LSLEEP (1<<VQADATB_LSLEEP)\n#define VQADATF_DDONE  (1<<VQADATB_DDONE)\n#define VQADATF_LDONE  (1<<VQADATB_LDONE)\n#define VQADATF_PRIMED (1<<VQADATB_PRIMED)\n#define VQADATF_PAUSED (1<<VQADATB_PAUSED)\n\n\n/* VQAHandleP: Private VQA file handle. Must be obtained by calling\n *             VQA_Alloc() and freed through VQA_Free(). This is the only\n *             legal way to obtain and dispose of a VQAHandle.\n *\n * VQAio     - Something meaningful to the IO manager. (See DOCS)\n * IOHandler - IO handler callback.\n * VQABuf    - Pointer to internal data buffers.\n * Config    - Configuration structure.\n * Header    - VQA header structure.\n * vocfh     - Override audiotrack file handle.\n */\ntypedef struct _VQAHandleP {\n\tunsigned long VQAio;\n\tlong          (*IOHandler)(VQAHandle *vqa, long action, void *buffer,\n\t                          long nbytes);\n\tVQAData       *VQABuf;\n\tVQAConfig     Config;\n\tVQAHeader     Header;\n\tlong          vocfh;\n\tCaptionInfo   *Caption;\n\tCaptionInfo   *EVA;\n} VQAHandleP;\n\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\n/* Loader/Drawer system. */\nlong VQA_LoadFrame(VQAHandle *vqa);\nvoid VQA_Configure_Drawer(VQAHandleP *vqap);\nlong User_Update(VQAHandle *vqa);\n\n/* Timer system. */\nlong VQA_StartTimerInt(VQAHandleP *vqap, long init);\nvoid VQA_StopTimerInt(VQAHandleP *vqap);\nvoid VQA_SetTimer(VQAHandleP *vqap, long time, long method);\nunsigned long VQA_GetTime(VQAHandleP *vqap);\nlong VQA_TimerMethod(void);\n\n/* Audio system. */\n#if(VQAAUDIO_ON)\nlong VQA_OpenAudio(VQAHandleP *vqap , HWND window);\nvoid VQA_CloseAudio(VQAHandleP *vqap);\nlong VQA_StartAudio(VQAHandleP *vqap);\nvoid VQA_StopAudio(VQAHandleP *vqap);\nlong CopyAudio(VQAHandleP *vqap);\n#endif\n\n/* Debugging system. */\nvoid VQA_InitMono(VQAHandleP *vqap);\nvoid VQA_UpdateMono(VQAHandleP *vqap);\n\n#endif /* VQAPLAYP_H */\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/DEBUG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Virtual Monopoly                         *\n *                                                                         *\n *                    File Name : DEBUG.CPP                                *\n *                                                                         *\n *                   Programmer : Michael Legg                             *\n *                                                                         *\n *                   Start Date : November 22, 1994                        *\n *                                                                         *\n *                  Last Update : May 30, 1995   [ML]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Get_And_Display_Windows_Debug -- GetWinDebugInfo() called for checking*\n *   Debug_Mono_Message -- Post a line to the monochrome monitor           *\n *   Debug_Window_Message -- One of many ways to pop up a debug msg window *\n *   Debug_Show_Palette -- Display the current 256 color palette           *\n *   Debug_Draw_Line_Test -- Tests Westwood library Draw_Line()            *\n *   Debug_Put_Pixel_Test -- Tests the Westwood library Put_Pixel()        *\n *   Debug_Shape_Test -- Tests the Westwood Library Draw_Shape()           *\n *   Debug_Print_Game_Stats -- Code to display player stats w/ text        *\n *   Debug_Rig_Roll -- Pops up dialog to fix the next dice roll            *\n *   Debug_Adjust_Players_Cash -- Changes the current players money        *\n *   Debug_Rig_Roll_Dialog_Procedure -- Handles commands to dialog         *\n *   Debug_Adjust_Cash_Dialog_Proc -- Handles dialog messages for this     *\n *   Debug_Mono_Print_Whose_Turn -- Displays current turn on MONO display  *\n *   Build_Debug_Log_File_Name -- Based on the date and time of system     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include \"function.h\"\n#include \"debug.rh\"\n#include \"strings.rh\"\n\n#if( RIG_ROLL_FOR_PLAYTEST )\nVOID Debug_Rig_Roll( WindowHandle window_handle );\nPRIVATE BOOL Debug_Rig_Roll_Dialog_Procedure( WindowHandle window_handle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t UINT message,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t WPARAM w_param,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t LPARAM l_param );\n#endif\n\n#if( DEBUG_CODE )\n/*\n\tpublic functions\n*/\nVOID Get_And_Display_Windows_Debug_Info( BYTE *command_line_string );\nVOID Debug_Mono_Message( BYTE *message );\n//VOID Debug_Window_Message( BYTE *message );\nVOID Debug_Show_Palette( VOID );\nVOID Debug_Draw_Line_Test( VOID );\nVOID Debug_Put_Pixel_Test( VOID );\nVOID Debug_Shape_Test( VOID );\nVOID Debug_Print_Game_Stats( VOID );\nVOID Debug_Adjust_Players_Cash( WindowHandle window_handle );\nVOID Debug_Mono_Print_Whose_Turn( PlayerType player );\nVOID Build_Debug_Log_File_Name( BYTE *name_string );\n\n/*\n\tprivate functions\n*/\nPRIVATE BOOL Debug_Adjust_Cash_Dialog_Procedure( WindowHandle window_handle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t UINT message,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t WPARAM w_param,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t LPARAM l_param );\n#endif\n\n\n\n#if( DEBUG_CHECKSUM_ALL_SITES_DATA )\nPRIVATE VOID Give_To_The_Mikes( VOID );\n#endif\n\n#if( DEBUG_CODE )\n/*\n\tcode begins...\n*/\n\n/***************************************************************************\n * DEBUG_MONO_MESSAGE -- Post a line to the monochrome monitor             *\n *                                                                         *\n * INPUT: the message to print                                             *\n *                                                                         *\n * OUTPUT: a message on the monochrome monitor display                     *\n *                                                                         *\n * WARNINGS: try to end messages with \\r\\n!                                *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\n#pragma argsused\nVOID Debug_Mono_Message( BYTE *message )\n{\n\t#if( DEBUG_LOG_TO_MONO_DISPLAY )\n\t\tBYTE *temp_string;\n\t\tBYTE *temp_null_position;\n\t\tBYTE temp_char;\t\n\t\tINT length_left;\n\t#endif\n\t#if( DEBUG_LOG_TO_FILE )\n\t\tINT fh;\n\t\tstatic BOOL _errored_once = FALSE;\n\t\tBYTE name_path_string[ _MAX_PATH ];\n      BOOL danger;\n\t#endif\n\n\t#if( DEBUG_LOG_TO_FILE )\n\n\t\tdanger = Danger_Test_Hard_Drive_Space();\n\n\t\tif ( ! _errored_once && ! danger ) {\n\n\t\t\tif ( *(Executable_Path+0) != '\\0' ) {\n\t\t\t\tsprintf( name_path_string,\n\t\t\t\t\t\t\t\"%s%s\",\n\t\t\t\t\t\t\tExecutable_Path,\n\t\t\t\t\t\t\tDebug_Log_File_Name );\n\t\t\t\tfh = Open_File( name_path_string, READ|WRITE );\n\t\t\t\tif ( fh == FILEOPENERROR || fh == -1 ) {\n\t\t\t\t\tsprintf( Text_String,\n\t\t\t\t\t\t\t\t\"Unable to open %s for WRITE.\\r\\n\",\n\t\t\t\t\t\t\t\tDebug_Log_File_Name );\n\t\t\t\t\t#if( DEBUG_CODE )\n\t\t\t\t\t\tDebug_Error_Window_Message( Text_String );\n               #endif\n\t\t\t\t\t_errored_once = TRUE;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tSeek_File( fh, 0, SEEK_END );\n\t\t\t\t\tWrite_File( (INT)fh, (BYTE *)message, (ULONG)(strlen(message)) );\n\t\t\t\t\tClose_File( fh );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t#endif\n\n\n\t#if( DEBUG_LOG_TO_MONO_DISPLAY )\n\n\t\tif ( ! Debug_Mono_Messages ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( ! Windows_95_Detected_Flag ) {\n\t\t\tOutputDebugString( \".\" );\n\t\t}\n//\t\telse {\n//\t\t\tMonochrome_Output( \"> \" );\n//\t\t}\n\n\t\tlength_left = strlen( message );\n\t\ttemp_null_position = message;\n\t\twhile ( length_left > 80 ) {\n\t\t\ttemp_string = temp_null_position;\n\t\t\ttemp_null_position += 80;\n\t\t\ttemp_char = *temp_null_position;\n\t\t\ttemp_null_position[ 0 ] = '\\0';\n\n\t\t\tif ( Windows_95_Detected_Flag ) {\n\t\t\t\tMonochrome_Output( temp_string );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tOutputDebugString( temp_string );\n\t\t\t}\n\n\t\t\t*temp_null_position = temp_char;\n\t\t\tlength_left -= 80;\n\t\t}\n\t\ttemp_string = temp_null_position;\n\n\t\tif ( Windows_95_Detected_Flag ) {\n\t\t\tMonochrome_Output( temp_string );\n\t\t}\n\t\telse {\n\t\t\tOutputDebugString( temp_string );\n\t\t}\n\n\t#endif\n\n}\n\n/***************************************************************************\n * DEBUG_SHOW_PALETTE -- Display the current 256 color palette             *\n *                                                                         *\n * INPUT: none                                                             *\n *                                                                         *\n * OUTPUT: none                                                            *\n *                                                                         *\n * WARNINGS: none                                                          *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\nVOID Debug_Show_Palette( VOID )\n{\n\t#define PIXEL_SIZE 19\n\tINT i, j, x, y;\n\tUBYTE color;\n\tDeviceContextHandle screen_dc;\n\n\tif ( Game_Is_Now_Currently_Interrupted ) {\n\t\tStandard_Window_Message( \"Game_Is_Now_Currently_Interrupted = TRUE\", \"X\" );\n\t\tif ( Current_Interrupting_Player > NO_PLAYER ) {\n\t\t\tsprintf( Text_String,\n\t\t\t\t\t\t\"Current_Interrupting_Player = %s\\r\\n\",\n\t\t\t\t\t\tPlayers[ Current_Interrupting_Player ].Get_Name() );\n\t\t}\n\t\telse {\n\t\t\tsprintf( Text_String,\n\t\t\t\t\t\t\"Current_Interrupting_Player = unknown\\r\\n\" );\n\t\t}\n\t\tStandard_Window_Message( Text_String, \"X\" );\n\t}\n\telse {\n\t\tStandard_Window_Message( \"Game_Is_Now_Currently_Interrupted = FALSE\", \"X\" );\n\t}\n\n\tcolor = 0;\n\tfor ( i = 0; i < 16; i ++ ) { \n\t\tfor ( j = 0; j < 16; j ++ ) { \n\t\t\tx = VQ_MOVIE_X + (j * PIXEL_SIZE);\n\t\t\ty = VQ_MOVIE_Y + (i * PIXEL_SIZE);\n\t\t\tMonopoly_Fill_Rect( x, y, x+PIXEL_SIZE-1, y+PIXEL_SIZE-1, COLOR_BLACK );\n\t\t\tMonopoly_Fill_Rect( x+1, y+1, x+PIXEL_SIZE-2, y+PIXEL_SIZE-2, color++ );\n\t\t}\n\t}\n\n\tscreen_dc = GetDC( Main_Window_Handle );\n//\tWinGBitBlt( Screen_DC, \n\tWinGBitBlt( screen_dc, \n\t\t\t\t\tVQ_MOVIE_X, VQ_MOVIE_Y,\n\t\t\t\t\tVQ_MOVIE_WIDTH, \n\t\t\t\t\tVQ_MOVIE_HEIGHT,\n\t\t\t\t\tWinG_DC, \n\t\t\t\t\tVQ_MOVIE_X, VQ_MOVIE_Y );\n\tReleaseDC( Main_Window_Handle, screen_dc );\n}\n\n\n/***************************************************************************\n * DEBUG_DRAW_LINE_TEST -- Tests Westwood library Draw_Line()              *\n *                                                                         *\n * INPUT: none                                                             *\n *                                                                         *\n * OUTPUT: none                                                            *\n *                                                                         *\n * WARNINGS: make sure WinG buffer is active!                              *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\nVOID Debug_Draw_Line_Test( VOID )\n{\n#if( 0 )\n//\tINT x1=0, y1=0, x2=638, y2=438;\n\tINT x1, y1=0, x2=638, y2=438;\n\t\n\tfor ( x1=0; x1<=638; x1+=10 ) {\n\t\tHidBuff_Class_Ptr->Draw_Line( x1,y1,x2,y2,255 );\n\t\tWinGBitBlt( Screen_DC, \n\t\t\t\t\t\tmin(x1,x2), min(y1,y2),\n\t\t\t\t\t\tabs(x2-x1)+1, \n\t\t\t\t\t\tabs(y2-y1)+1,\n\t\t\t\t\t\tWinG_DC, \n\t\t\t\t\t\tmin(x1,x2), min(y1,y2) );\n\t\tx2-=10;\n\t}\n\tx1=0;\n//\ty1=0;\n\tx2=638;\n\ty2=438;\n\tfor ( y1=0; y1<=438; y1+=10 ) {\n\tHidBuff_Class_Ptr->Draw_Line( x1,y1,x2,y2,255 );\n\t\tWinGBitBlt( Screen_DC, \n\t\t\t\t\t\tmin(x1,x2), min(y1,y2),\n\t\t\t\t\t\tabs(x2-x1)+1, \n\t\t\t\t\t\tabs(y2-y1)+1,\n\t\t\t\t\t\tWinG_DC, \n\t\t\t\t\t\tmin(x1,x2), min(y1,y2) );\n\t\ty2-=10;\n\t}\n#endif\n}\n\n\n/***************************************************************************\n * DEBUG_PUT_PIXEL_TEST -- Tests the Westwood library Put_Pixel()          *\n *                                                                         *\n * INPUT: none                                                             *\n *                                                                         *\n * OUTPUT: none                                                            *\n *                                                                         *\n * WARNINGS: Make sure WinG buffer is active                               *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\nVOID Debug_Put_Pixel_Test( VOID )\n{\n#if( 0 )\n\tINT x = random( 640 );\n\tINT y = random( 440 );\n\tINT xweight=1; int yweight=1; \n\tLONG i;\n\tstatic UBYTE color = 0;\n\n\tcolor++;\n\tfor ( i=0; i<100000; i ++ ) {\n\t\n\t\tHidBuff_Class_Ptr->Put_Pixel( x, y, color );\n\t\tWinGBitBlt( Screen_DC, \n\t\t\t\t\t\tx, y,\n\t\t\t\t\t\t1, \n\t\t\t\t\t\t1,\n\t\t\t\t\t\tWinG_DC, \n\t\t\t\t\t\tx, y );\n\t\t\n\t\tif ( x <= 0 ) {\n\t\t\tx = 0;\n\t\t\txweight = 1;\n\t\t}\n\t\tif ( y <= 0 ) {\n\t\t\ty = 0;\n\t\t\tyweight = 1;\n\t\t}\n\t\tif ( x >= WING_BITMAP_WIDTH-1 ) {\n\t\t\tx = WING_BITMAP_WIDTH-1;\n\t\t\txweight = -1;\n\t\t}\n\t\tif ( y >= WING_BITMAP_HEIGHT-1 ) {\n\t\t\ty = WING_BITMAP_HEIGHT-1;\n\t\t\tyweight = -1;\n\t\t}\n\t\tif ( xweight > 0 ) {\n\t\t\t/* 0-9 */\n\t\t\t/* 0-9 */\n\t\t\tif ( random( 10 ) <= 4 ) { \n\t\t\t\tx ++;\n\t\t\t}\n\t\t\telse { /* 0 */\n\t\t\t\tx --;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t/* 0-9 */\n\t\t\tif ( random( 10 ) <= 4 ) { \n\t\t\t\tx --;\n\t\t\t}\n\t\t\telse { /* 0 */\n\t\t\t\tx ++;\n\t\t\t}\n\t\t}\n\t\tif ( yweight > 0 ) {\n\t\t\t/* 0-9 */\n\t\t\tif ( random( 10 ) <= 4 ) { \n\t\t\t\ty ++;\n\t\t\t}\n\t\t\telse { /* 0 */\n\t\t\t\ty --;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t/* 0-9 */\n\t\t\tif ( random( 10 ) <= 4 ) { \n\t\t\t\ty --;\n\t\t\t}\n\t\t\telse { /* 0 */\n\t\t\t\ty ++;\n\t\t\t}\n\t\t}\n\t}\n#endif\n}\n\n\n/***************************************************************************\n * DEBUG_SHAPE_TEST -- Tests the Westwood Library Draw_Shape()             *\n *                                                                         *\n * INPUT: none                                                             *\n *                                                                         *\n * OUTPUT: none                                                            *\n *                                                                         *\n * WARNINGS: Make sure the WinG buffer is active!                          *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\nVOID Debug_Shape_Test( VOID )\n{\n#if( 0 )\n\tBYTE *shapebuf, *shapes;\n\tLONG fsize;\n\tCHAR *shape_ptr[ 37 ];\n\tINT i, j, x;\n\n\tINT wwfh;\n\t\n\tDebug_Mono_Message( \"------------------------------------------\\r\\n\" );\n\tsprintf( Text_String, \"Mem before shape buff alloc(5000): %ld\\r\\n\", Ram_Free( MEM_NORMAL ) );\n\tDebug_Mono_Message( Text_String );\n\t\n\tshapebuf = (char *) Alloc( 5000, MEM_NORMAL );\n\t\n\tsprintf( Text_String, \"Mem after shape buff alloc(5000): %ld\\r\\n\", Ram_Free( MEM_NORMAL ) );\n\tDebug_Mono_Message( Text_String );\n\t\n\tif ( shapebuf == NULL ) {\n\t\tDebug_Mono_Message(\"shapebuf alloc failed.\\n\");\n\t}\n\tSet_Shape_Buffer (shapebuf,5000);\n\n\twwfh = Open_File( \"MSW00.SHP\", READ );\n\tsprintf( Text_String, \"File opened with wwfh %d\\r\\n\", wwfh );\n\tDebug_Mono_Message( Text_String );\n\tif( wwfh == -1 ) {\n\t\tDebug_Mono_Message(\"File not found\\n\");\n\t}\n\tfsize = File_Size( wwfh );\n\tsprintf( Text_String, \"File_Size( %d ) = %d\\r\\n\", wwfh, fsize );\n\tDebug_Mono_Message( Text_String );\n\tif ( fsize > 0 ) {\n\t\tshapes = (char *) Alloc( fsize, MEM_NORMAL );\n\t\tif( shapes == NULL) {\n\t\t\tDebug_Mono_Message(\"shapes alloc failed\\n\");\n\t\t}\n\t\tRead_File( wwfh, shapes, fsize ); \n\t\tClose_File( wwfh );\n\t}\n\t\n\tsprintf( Text_String, \"Mem after shapedata alloc: %ld\\r\\n\", Ram_Free( MEM_NORMAL ) );\n\tDebug_Mono_Message( Text_String );\n\n\tfor( i = 0; i <= 36; i++ ) {\n\t\tshape_ptr[ i ] = Get_Shape( shapes, i );\n\t}\n\n\tsprintf( Text_String, \"Mem after all shapes alloc: %ld\\r\\n\", Ram_Free( MEM_NORMAL ) );\n\tDebug_Mono_Message( Text_String );\n\t\n\tFree( shapes );\n\t\n\tx = -64;\n\tfor ( j = 0; j < 20; j ++ ) {\n\t\tfor ( i = 21; i <= 28; i ++ ) {\n\t\t\tRefresh_Board_BMP_On_Hid();\n\t\t\tif ( shape_ptr[ i ] ) {\n//\t\t\t\tDraw_Shape( HidBuff_Class_Ptr, shape_ptr[ i ], x, 71, SHAPE_NORMAL );\n\t\t\t\tDraw_Shape( HidBuff_Class_Ptr, shape_ptr[ i ], x, 0, SHAPE_SCALING, 340, 340 );\n\t\t\t\tHidBuff_Class_Ptr->Put_Pixel( x, 100, 3 );\n\n\t\t\t\tWinGBitBlt( Screen_DC, \n\t\t\t\t\t\t\t\tx, 0,\n\t\t\t\t\t\t\t\t200, 200,\n\t\t\t\t\t\t\t\tWinG_DC, \n\t\t\t\t\t\t\t\tx, 0 );\n\t\t\t}\n\t\t\tx += 4;\n\t\t}\n\t}\n\tif ( shape_ptr[ 0 ] ) {\n\t\tRefresh_Board_BMP_On_Hid();\n//\t\tDraw_Shape( HidBuff_Class_Ptr, shape_ptr[ 0 ], x, 71, SHAPE_NORMAL );\n\t\tDraw_Shape( HidBuff_Class_Ptr, shape_ptr[ 0 ], x, 0, SHAPE_SCALING, 340, 340 );\n\t\tHidBuff_Class_Ptr->Put_Pixel( x, 100, 3 );\n\t\tWinGBitBlt( Screen_DC, \n\t\t\t\t\t\tx, 0,\n\t\t\t\t\t\t200, 200,\n\t\t\t\t\t\tWinG_DC, \n\t\t\t\t\t\tx, 0 );\n\t}\n\n\tfor( i = 0; i <= 36; i++ ) {\n\t\tFree( shape_ptr[ i ] );\n\t}\n\t\n\tFree( shapebuf );\n\n\tsprintf( Text_String, \"Mem when all done: %ld\\r\\n\", Ram_Free( MEM_NORMAL ) );\n\tDebug_Mono_Message( Text_String );\n\tDebug_Mono_Message( \"------------------------------------------\\r\\n\" );\n#endif\n}\n\n#if( 0 )\n#define DEBUG_TEXT_X\t\t\t4\n#define DEBUG_TEXT_Y\t\t\t12\n#define DEBUG_TEXT_SPACING 13\n/***************************************************************************\n * DEBUG_PRINT_GAME_STATS -- Code to display player stats w/ text          *\n *                                                                         *\n * INPUT: none                                                             *\n *                                                                         *\n * OUTPUT: none                                                            *\n *                                                                         *\n * WARNINGS: none                                                          *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\nVOID Debug_Print_Game_Stats( VOID )\n{\n\tINT i;\n\tINT x;\n\tINT y;\n\tPlayerType whos_turn;\n\tBYTE temp_token_string[ 50 ];\n\tBYTE temp_ai_string[ 50 ];\n\tBYTE temp_string[ 50 ];\n\n\t/*\n\t\tno game, no stats\n\t*/\n\tif ( ! Game_Status.Is_Game_In_Progress() ) {\n\t\treturn;\n\t}\n\n\tx = DEBUG_TEXT_X;\n\ty = DEBUG_TEXT_Y;\n\n\twhos_turn = Game_Status.Get_Whos_Turn_Is_It_Now();\n\n\tSetTextAlign( Screen_DC, TA_LEFT ); \n\tSelectObject( Screen_DC, GetStockObject( ANSI_VAR_FONT ) );\n\tSetTextCharacterExtra( Screen_DC, 0 );\n\n\tfor ( i = PLAYER_1; i < TOTAL_PLAYERS; i ++ ) {\n\t\tif ( Players[ i ].Is_Active() ) {\n\t\t\tif ( whos_turn == i ) {\n\t\t\t\tstrcpy( Text_String_2, \"*\" );\n\t\t\t\trgb_vals = PALETTERGB( 0, 0, 255 );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tstrcpy( Text_String_2, \" \" );\n\t\t\t\trgb_vals = WHITE_RGB_COLOR_REF;\n\t\t\t}\n\n\t\t\tsprintf( temp_string, \"%d: \", i+1 );\n\t\t\tstrcat( Text_String_2, temp_string );\n\n\t\t\t// grab token name\n\t\t\tif ( Players[ i ].Get_Token() >= TOKEN_FIRST ) {\n\t\t\t\tLoadString( Global_Instance_Handle, \n\t\t\t\t\t\t\t\tSTRING_TOKEN_FIRST + Players[ i ].Get_Token(),\n\t\t\t\t\t\t\t\ttemp_token_string, \n\t\t\t\t\t\t\t\t50 );\n\t\t\t}\n\t\t\telse {\n\t\t\t\t*temp_token_string = '\\0';\n\t\t\t}\n\n\t\t\t// grab ai name\n\t\t\tif ( Players[ i ].Get_AI_Type() >= AI_FIRST ) {\n\t\t\t\tLoadString( Global_Instance_Handle, \n\t\t\t\t\t\t\t\tSTRING_AI_FIRST + Players[ i ].Get_AI_Type(),\n\t\t\t\t\t\t\t\ttemp_ai_string, \n\t\t\t\t\t\t\t\t50 );\n\t\t\t}\n\t\t\telse {\n\t\t\t\t*temp_ai_string = '\\0';\n\t\t\t}\n\n\t\t\tsprintf( Text_String, \n\t\t\t\t\t\t\"%s%s, $%d, %s \",\n\t\t\t\t\t\tText_String_2,\n\t\t\t\t\t\tPlayers[ i ].Get_Name(),\n\t\t\t\t\t\tPlayers[ i ].Get_Cash(),\n\t\t\t\t\t\ttemp_token_string );\n\n\t\t\tSetTextColor( Screen_DC, rgb_vals );\n\t\t\tTextOut( Screen_DC, \n\t\t\t\t\t\tx, \n\t\t\t\t\t\ty,\n\t\t\t\t\t\tText_String, \n\t\t\t\t\t\tstrlen( Text_String ) );\n\n\t\t\t/*\n\t\t\t\tnow print liquid assets, available assets, tradable assets,\n\t\t\t\t\ttotal assets and monopolies...\n\t\t\t*/\n\t\t\ty += DEBUG_TEXT_SPACING;\n\t\t\tsprintf( Text_String, \"     AI: $%s       \", temp_ai_string );\n\t\t\tTextOut( Screen_DC, \n\t\t\t\t\t\tx, \n\t\t\t\t\t\ty,\n\t\t\t\t\t\tText_String, \n\t\t\t\t\t\tstrlen( Text_String ) );\n\t\t\ty += DEBUG_TEXT_SPACING;\n\t\t\tsprintf( Text_String, \"     Liquid Assets: $%u       \", Players[ i ].Get_Liquid_Assets() );\n\t\t\tTextOut( Screen_DC, \n\t\t\t\t\t\tx, \n\t\t\t\t\t\ty,\n\t\t\t\t\t\tText_String, \n\t\t\t\t\t\tstrlen( Text_String ) );\n\t\t\ty += DEBUG_TEXT_SPACING;\n\t\t\tsprintf( Text_String, \"     Available Assets: $%u       \", Players[ i ].Get_Available_Assets() );\n\t\t\tTextOut( Screen_DC, \n\t\t\t\t\t\tx, \n\t\t\t\t\t\ty,\n\t\t\t\t\t\tText_String, \n\t\t\t\t\t\tstrlen( Text_String ) );\n//\t\t\ty += DEBUG_TEXT_SPACING;\n//\t\t\tsprintf( Text_String, \"   Tradable Assets: $%u       \", Players[ i ].Get_Tradable_Assets() );\n//\t\t\tTextOut( Screen_DC, \n//\t\t\t\t\t\tx, \n//\t\t\t\t\t\ty,\n//\t\t\t\t\t\tText_String, \n//\t\t\t\t\t\tstrlen( Text_String ) );\n\t\t\ty += DEBUG_TEXT_SPACING;\n\t\t\tsprintf( Text_String, \"     Total Assets: $%u       \", Players[ i ].Get_Total_Assets( FALSE ) );\n\t\t\tTextOut( Screen_DC, \n\t\t\t\t\t\tx, \n\t\t\t\t\t\ty,\n\t\t\t\t\t\tText_String, \n\t\t\t\t\t\tstrlen( Text_String ) );\n\t\t\ty += DEBUG_TEXT_SPACING;\n//\t\t\tsprintf( Text_String, \"     Monopolies: %u       \", Players[ i ].Get_Monopolies() );\n//\t\t\tTextOut( Screen_DC, \n//\t\t\t\t\t\tx, \n//\t\t\t\t\t\ty,\n//\t\t\t\t\t\tText_String, \n//\t\t\t\t\t\tstrlen( Text_String ) );\n//\t\t\ty += DEBUG_TEXT_SPACING;\n\t\t}\n\t}\n\n\t/*\n\t\tFree parking!\n\t*/\n\ty += DEBUG_TEXT_SPACING;\n\tif ( Game_Status.Does_Free_Parking_Collect_Cash() ) {\n\t\tstrcpy( Text_String_2, \"Active\" );\n\t}\n\telse {\n\t\tstrcpy( Text_String_2, \"Inactive\" );\n\t}\n\tsprintf( Text_String,\n\t\t\t\t\"Free Parking: $%d, %s      \",\n\t\t\t\tGame_Status.Get_Free_Parking_Money(),\n\t\t\t\tText_String_2 );\n\n\trgb_vals = BLACK_RGB_COLOR_REF;\n\tSetTextColor( Screen_DC, rgb_vals );\n\tTextOut( Screen_DC, \n\t\t\t\tx, \n\t\t\t\ty,\n\t\t\t\tText_String, \n\t\t\t\tstrlen( Text_String ) );\n\n\t/*\n\t\tBank\n\t*/\n\ty += DEBUG_TEXT_SPACING;\n\tsprintf( Text_String,\n\t\t\t\t\"Bank: %d houses, %d hotels, $infinite      \",\n\t\t\t\tBank.Get_Houses(),\n\t\t\t\tBank.Get_Hotels() );\n\tTextOut( Screen_DC, \n\t\t\t\tx, \n\t\t\t\ty,\n\t\t\t\tText_String, \n\t\t\t\tstrlen( Text_String ) );\n}\n#endif\n\n\n/***************************************************************************\n * DEBUG_ADJUST_PLAYERS_CASH -- Changes the current players money          *\n *                                                                         *\n * INPUT: parent window handle                                             *\n *                                                                         *\n * OUTPUT: none                                                            *\n *                                                                         *\n * WARNINGS: none                                                          *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\nVOID Debug_Adjust_Players_Cash( WindowHandle window_handle )\n{\n\tif ( ! Game_Status.Is_Game_In_Progress() ) {\n\t\tDebug_Error_Window_Message( \"Game not in progress!\" );\n\t\treturn;\n\t}\n\n\tDialogBox( Global_Instance_Handle, \n\t\t\t\t  \"DebugSetCashDlgBox\", \n\t\t\t\t  window_handle, \n\t\t\t\t  (DLGPROC) Debug_Adjust_Cash_Dialog_Procedure );\n\t\n}\n\n#pragma argsused\n\n/***************************************************************************\n * DEBUG_ADJUST_CASH_DIALOG_PROC -- Handles dialog messages for this       *\n *                                                                         *\n * INPUT: standard windows dialog command parameters                       *\n *                                                                         *\n * OUTPUT: TRUE if cash modified, FALSE if not                             *\n *                                                                         *\n * WARNINGS: none                                                          *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\nPRIVATE BOOL Debug_Adjust_Cash_Dialog_Procedure( WindowHandle window_handle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t UINT message,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t WPARAM w_param,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t LPARAM l_param )\n{\n\tINT cash;\n\tPlayerType player;\n\n\tswitch( message ) {\n\t\n\t\tcase WM_COMMAND:\n\n\t\t\tif ( LOWORD( w_param ) == IDOK ) {\n\n\t\t\t\tGetDlgItemText( window_handle, \n\t\t\t\t\t\t\t\t\t CASH_EDIT1, \n\t\t\t\t\t\t\t\t\t Text_String, \n\t\t\t\t\t\t\t\t\t SIZE_OF_TEXT_STRING );\n\t\t\t\tcash = atoi( Text_String );\n\t\t\t\tif ( cash < 0 ) {\n\t\t\t\t\tcash = 0;\n\t\t\t\t}\n\t\t\t\tif ( cash > 100000 ) {\n\t\t\t\t\tcash = 100000;\n\t\t\t\t}\n\n\t\t\t\tplayer = Game_Status.Get_Whos_Turn_Is_It_Now();\n//\t\t\t\tPlayers[ player ].Set_Money( cash );\n\t\t\t\t// FALSE = not incoming, so outgoing to other systems\n\t\t\t\tSend_Game_Command( FALSE, CMD_SET_CASH, player, cash );\n\n\t\t\t\tsprintf( Text_String,\n\t\t\t\t\t\t\t\"%s now has $%d.\\r\\n\",\n\t\t\t\t\t\t\tPlayers[ player ].Get_Name(), cash );\n\t\t\t\tDebug_Mono_Message( Text_String );\n\t\t\t\tRefresh_Player_Interface( player, TRUE );\n\n\t\t\t\tEndDialog( window_handle, IDOK );\n\t\t\t\treturn( TRUE );\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WM_INITDIALOG:\n\t\t\t\t/*\n\t\t\t\t\tDefault cash for player\n\t\t\t\t*/\n\t\t\t\tplayer = Game_Status.Get_Whos_Turn_Is_It_Now();\n\t\t\t\titoa( Players[ player ].Get_Cash(), Text_String, 10 );\n\t\t\t\tSetDlgItemText( window_handle, \n\t\t\t\t\t\t\t\t\t CASH_EDIT1, \n\t\t\t\t\t\t\t\t\t Text_String );\n\t\t\t\tSendDlgItemMessage( window_handle, \n\t\t\t\t\t\t\t\t\t\t  CASH_EDIT1,\n\t\t\t\t\t\t\t\t\t\t  EM_SETSEL,  \n\t\t\t\t\t\t\t\t\t\t  (WPARAM) 0,\n\t\t\t\t\t\t\t\t\t\t  (LPARAM) -1 );\n\t\t\t\treturn( TRUE );\n\n\t\tdefault: break;\n\n\t}\n\treturn( FALSE );\n}\n\n// TC \nextern BYTE *Debug_Chance_Card_Text[];\n\nVOID Debug_Show_Chance_Deck( VOID )\n{\n\tChanceCardType card;\n\tINT i;\n\n\tfor ( i = 0; i < TOTAL_CHANCE_CARDS_IN_MAX_DECK; i ++ ) {\n\t\tcard = Game_Cards.Query_Chance_Card( i );\n\t\tif ( card > CHANCE_NO_CARD ) {\n\t\t\tsprintf( Text_String,\n\t\t\t\t\t\t\"Chance card[ %d ] = %s\\r\\n\",\n\t\t\t\t\t\ti,\n\t\t\t\t\t\tDebug_Chance_Card_Text[ card ] );\n\t\t}\n\t\telse {\n\t\t\tsprintf( Text_String,\n\t\t\t\t\t\t\"Chance card[ %d ] = -1\\r\\n\",\n\t\t\t\t\t\ti );\n\t\t}\n\t\tDebug_Mono_Message( Text_String );\n\t}\n}\n\n// TC \nextern BYTE *Debug_CC_Card_Text[];\n\nVOID Debug_Show_CC_Deck( VOID )\n{\n\tCommunityChestCardType card;\n\tINT i;\n\n\tfor ( i = 0; i < TOTAL_COMMUNITY_CHEST_CARDS_IN_MAX_DECK; i ++ ) {\n\t\tcard = Game_Cards.Query_CC_Card( i );\n\t\tif ( card > CC_NO_CARD ) {\n\t\t\tsprintf( Text_String,\n\t\t\t\t\t\t\"C. Chest card[ %d ] = %s\\r\\n\",\n\t\t\t\t\t\ti,\n\t\t\t\t\t\tDebug_CC_Card_Text[ card ] );\n\t\t}\n\t\telse {\n\t\t\tsprintf( Text_String,\n\t\t\t\t\t\t\"C. Chest card[ %d ] = -1\\r\\n\",\n\t\t\t\t\t\ti );\n\t\t}\n\t\tDebug_Mono_Message( Text_String );\n\t}\n}\n\n/***************************************************************************\n * DEBUG_MONO_PRINT_WHOSE_TURN -- Displays current turn on MONO display    *\n *                                                                         *\n * INPUT: player whos turn it is                                           *\n *                                                                         *\n * OUTPUT: a message to the MONO display                                   *\n *                                                                         *\n * WARNINGS: none                                                          *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\nVOID Debug_Mono_Print_Whose_Turn( PlayerType player )\n{\n\tDebug_Mono_Message( \"--------------------------------------------------------------------------\\r\\n\" );\n\tsprintf( Text_String, \"--- %s's turn...\\r\\n\", Players[ player ].Get_Name() );\n\tDebug_Mono_Message( Text_String );\n\tDebug_Mono_Message( \"--------------------------------------------------------------------------\\r\\n\" );\n}\n\nVOID Debug_Display_Bank_Status( VOID )\n{\n\tsprintf( Text_String,\n\t\t\t\t\"Hotels in bank = %d, Houses in bank = %d\",\n\t\t\t\tBank.Get_Hotels(),\n\t\t\t\tBank.Get_Houses() );\n\tStandard_Window_Message( Text_String, \"DEBUG\" );\n}\n\nVOID Debug_Show_Player_Info( VOID )\n{\n\tBYTE *tokens[ TOTAL_TOKENS ] = {\n\t\t\"CANNON \",\n\t\t\"CAR    \",\n\t\t\"DOG    \",\n\t\t\"HAT    \",\n\t\t\"IRON   \",\n\t\t\"HORSE  \",\n\t\t\"SHIP   \",\n\t\t\"SHOE   \",\n\t\t\"THIMBLE\",\n\t\t\"WBARROW\",\n\t};\n\tBYTE *ais[ TOTAL_AI_TYPES ] = {\n\t\t\"LOCAL HUMAN \",\n\t\t\"LOCAL AI    \",\n\t\t\"REMOTE HUMAN\",\n\t\t\"REMOTE AI   \",\n\t};\n\tBYTE *status[ TOTAL_ACTIVE_STATUSES ] = {\n\t\t\"INACTIVE\",\n\t\t\"ACTIVE  \",\n\t\t\"BANKRUPT\",\n\t};\n\tINT i;\n\n\tDebug_Mono_Message( \"****************************************************\\r\\n\" );\n\tsprintf( Text_String,\n\t\t\t\t\"Game_Is_Now_Currently_Interrupted = %d\\r\\n\",\n\t\t\t\tGame_Is_Now_Currently_Interrupted );\n\tDebug_Mono_Message( Text_String );\n\tfor ( i = FIRST_PLAYER; i <= LAST_PLAYER; i ++ ) {\n\t\tif ( Players[ i ].Get_Active_Status() != PLAYER_INACTIVE ) {\n\t\t\tsprintf( Text_String,\n\t\t\t\t\t\t\"Player[ %d ] - %s | %s | %s | %s | %s\\r\\n\",\n\t\t\t\t\t\ti,\n\t\t\t\t\t\ttokens[ Players[ i ].Get_Token() ],\n\t\t\t\t\t\tais[ Players[ i ].Get_AI_Type() ],\n\t\t\t\t\t\tPlayers[ i ].Get_IP_Address(),\n\t\t\t\t\t\tstatus[ Players[ i ].Get_Active_Status() ],\n\t\t\t\t\t\tPlayers[ i ].Get_Name() );\n\t\t}\n\t\telse {\n\t\t\tsprintf( Text_String,\n\t\t\t\t\t\t\"Player[ %d ] INACTIVE\\r\\n\",\n\t\t\t\t\t\ti );\n\n\t\t}\n\t\tDebug_Mono_Message( Text_String );\n\t}\n\tDebug_Mono_Message( \"****************************************************\\r\\n\" );\n\n}\n\nVOID Debug_Give_All_Properties( PlayerType player )\n{\n\tINT i;\n\n\tif ( player >= FIRST_PLAYER ) {\n\t\tfor ( i = PROP_FIRST; i <= PROP_LAST; i ++ ) {\n//\t\t\tProperty_Data[ i ].Set_Owner( player );\n\t\t\tSend_Game_Command( FALSE, CMD_SET_OWNER, player, i );\n\t\t}\n//\t\tRefresh_Player_Interface( player, TRUE );\n\t\tSend_Game_Command( FALSE, CMD_FULLY_REFRESH_SCREEN );\n\t}\n}\n\n#endif /* DEBUG_CODE */\n\n#if( DEBUG_CHECKSUM_ALL_SITES_DATA )\n#if( COMPILE_WINSOCK )\nVOID Debug_Broadcast_Save_Game_Checksum_Other_Sites( VOID )\n{\n\tULONG file_size;\n\tINT fh;\n\tINT i;\n\tULONG check_sum;\n\tBYTE *buffer;\n//\tSOCKET temp_socket;\n//\tINT status;\n\tINT low_int;\n\tINT high_int;\n\tUBYTE add_byte;\n\tBYTE *file_name;\n\n\t/*\n\t\tdon't do this unless we are multi-site\n\t*/\n\tif ( ! Multiple_Site_Game_In_Progress ) {\n\t\treturn;\n\t}\n\n\tfile_name = Text_String_3;\n\tsprintf( file_name,\n\t\t\t\t\"%s%s\",\n\t\t\t\tExecutable_Path,\n\t\t\t\t\"TEMPSEND.TMP\" );\n\n\t/*\n\t\tfirst save out the current game data\n\t*/\n\tDOS_Save_A_Game( file_name, TRUE ); // TRUE = site-to-site verification\n\t/*\n\t\tnow allocate a buffer and load the save data back up\n\t*/\n\tfh = Open_File( file_name, READ );\n\tif ( fh != -1 ) {\n\t\tfile_size = File_Size( fh );\n\t\tbuffer = (BYTE *) Alloc( (ULONG) file_size + 10, MEM_NORMAL );\n\t\tif ( buffer == NULL ) {\n\t\t\tClose_File( fh );\n\t\t\t#if ( DEBUG_CODE )\n\t\t\t\tDebug_Error_Window_Message( \"Unable to alloc buffer in Debug_Broadcast_Save_Game_Data_To_Other_Sites()\" );\n\t\t\t#endif\n\t\t\treturn;\n\t\t}\n\t\tRead_File( fh, buffer, file_size );\n\t\tClose_File( fh );\n\t}\n\n\t/*\n\t\tnow checksum the buffer\n\t*/\n\tcheck_sum = 0L;\n\tfor ( i = 0; i < file_size; i ++ ) {\n\t\tadd_byte = (UBYTE) *(buffer + i);\n\t\tcheck_sum += (add_byte * (i+1));\n\t}\n\tlow_int = LOWORD( check_sum );\n\thigh_int = HIWORD( check_sum );\n\n\t#if( DEBUG_CODE )\n\t\tsprintf( Text_String,\n\t\t\t\t\t\"Local checksum of %s is %ld, sending %d (low) & %d (high)...\\r\\n\",\n\t\t\t\t\tfile_name,\n\t\t\t\t\tcheck_sum,\n\t\t\t\t\tlow_int,\n\t\t\t\t\thigh_int );\n\t\tDebug_Mono_Message( Text_String );\n\t#endif\n\n\t/*\n\t\tsend a system command with the checksum game data\n\t*/\n\tWinSock_Broadcast_Command( CMD_SENDING_CHECKSUM_DATA, 3, (INT) file_size, low_int, high_int );\n\n\tif ( buffer ) {\n\t\tFree( buffer );\n//\t\tbuffer = NULL;\n\t}\n//\tDelete_File( file_name );\n}\n#endif\n#endif\n\n#if( DEBUG_CHECKSUM_ALL_SITES_DATA )\n#if( COMPILE_WINSOCK )\nVOID Debug_Compare_Local_Checksum_With_Received_Checksum( INT received_file_size, INT low_int, INT high_int )\n{\n\tINT fh;\n\tULONG received_check_sum;\n\tULONG local_check_sum;\n\tBYTE *buffer = NULL;\n\tINT local_file_size;\n\tINT i;\n\tUBYTE add_byte;\n\tBYTE *file_name;\n\tstatic BOOL _errored_already = FALSE;\n\n\tif ( _errored_already ) {\n\t\treturn;\n\t}\n\n\t/*\n\t\tdon't do this unless we are multi-site\n\t*/\n\tif ( ! Multiple_Site_Game_In_Progress ) {\n\t\treturn;\n\t}\n\n\treceived_check_sum = high_int;\n\treceived_check_sum <<= 16;\n\treceived_check_sum += low_int;\n\n\t#if( DEBUG_CODE )\n\t\tsprintf( Text_String,\n\t\t\t\t\t\"Getting ready to compare other sites file, size = %d, checksum = %ld\\r\\n\",\n\t\t\t\t\treceived_file_size,\n\t\t\t\t\treceived_check_sum );\n\t\tDebug_Mono_Message( Text_String );\n\t#endif\n\n\tfile_name = Text_String_3;\n\n\tsprintf( file_name,\n\t\t\t\t\"%s%s\",\n\t\t\t\tExecutable_Path,\n\t\t\t\t\"TEMPSAVE.TMP\" );\n\n\t/*\n\t\tsave out out current game right now!\n\t*/\n\tDOS_Save_A_Game( file_name, TRUE ); // TRUE = site-to-site verification\n\t/*\n\t\tnow load it, and check sum it\n\t*/\n\t/*\n\t\tnow allocate a buffer and load the save data back up\n\t*/\n\tfh = Open_File( file_name, READ );\n\tif ( fh != -1 ) {\n\t\tlocal_file_size = File_Size( fh );\n\t\tbuffer = (BYTE *) Alloc( (ULONG) local_file_size + 10, MEM_NORMAL );\n\t\tif ( buffer == NULL ) {\n\t\t\tClose_File( fh );\n\t\t\t#if ( DEBUG_CODE )\n\t\t\t\tDebug_Error_Window_Message( \"Unable to alloc buffer in Debug_Broadcast_Save_Game_Data_To_Other_Sites()\" );\n\t\t\t#endif\n\t\t\treturn;\n\t\t}\n\t\tRead_File( fh, buffer, local_file_size );\n\t\tClose_File( fh );\n\t}\n\t/*\n\t\tnow checksum the buffer\n\t*/\n\tlocal_check_sum = 0L;\n\tfor ( i = 0; i < local_file_size; i ++ ) {\n\t\tadd_byte = (UBYTE) *(buffer + i);\n\t\tlocal_check_sum += (add_byte * (i+1));\n\t}\n\t/*\n\t\tfree the buffer\n\t*/\t\t\n\tif( buffer ) {\n\t\tFree( buffer );\n\t}\n\n\t/*\n\t\tnow compare files sizes and check sum!\n\t*/\n\tif ( local_file_size != received_file_size ) {\n\t\tsprintf( Text_String,\n\t\t\t\t\t\"ERROR! TEMPSAVE.TMP (local, %d) & TEMPSEND.TMP (remote, %d) file sizes don't match!\\r\\n\",\n\t\t\t\t\tlocal_file_size, received_file_size );\n\t\t#if( DEBUG_CODE )\n\t\t\tDebug_Mono_Message( Text_String );\n// \t\tdon't post anything!\n\t\t\tDebug_Error_Window_Message( Text_String );\n\t\t#endif\n\n\t\treturn;\n\t}\n\tif ( local_check_sum != received_check_sum ) {\n\n\t\tLOCAL_RESET_SITE_OPTION( SITE_OPTION_COMPUTER_ROLLS_FOR_ITSELF );\n\t\tSend_Game_Command( FALSE, CMD_SET_GAME_OVER_FLAG, TRUE );\n\t\t_errored_already = TRUE;\n\n\t\t#if( DEBUG_CODE )\n\t\t\tsprintf( Text_String,\n\t\t\t\t\t\t\"ERROR! TEMPSAVE.TMP (local, %ld) & TEMPSEND.TMP (remote, %ld) checksums don't match!\\r\\n\",\n\t\t\t\t\t\tlocal_check_sum, received_check_sum );\n// \t\tGive_To_The_Mikes();\n\t\t\tDebug_Mono_Message( Text_String );\n\t\t\tDebug_Error_Window_Message( Text_String );\n\t\t#endif\n\n\t\treturn;\n\t}\n\t/*\n\t\tokay! everything matches!\n\t*/\n\t#if( DEBUG_CODE )\n\t\tsprintf( Text_String,\n\t\t\t\t\t\"TEMPSAVE.TMP (local, %ld) & TEMPSEND.TMP (remote, %ld) checksums match!\\r\\n\",\n\t\t\t\t\tlocal_check_sum, received_check_sum );\n\t\tDebug_Mono_Message( Text_String );\n\t#endif\n}\n#endif\n#endif\n\n#if( DEBUG_CHECKSUM_ALL_SITES_DATA )\nPRIVATE VOID Give_To_The_Mikes( VOID )\n{\n\tReal_Error_Window_Message( \"Put TEMPSAVE.TMP from your system on a floppy...\" );\n\tReal_Error_Window_Message( \"and put TEMPSEND.TMP from your oppenent systems on the floppy...\" );\n\tReal_Error_Window_Message( \"...and then give it to the Mike's for error checking!\" );\n}\n#endif\n\n#if( DEBUG_WRITE_IDS_IN_SAVES )\nLONG Debug_Write_ID_Save_Game_File( INT file_handle, BYTE *three_byte_id )\n{\n\tLONG bytes_read_or_written = 0L;\n\n\tif ( file_handle > -1 ) {\n\t\tbytes_read_or_written += Write_File( file_handle, three_byte_id, 3 );\n\t}\n\n\treturn( bytes_read_or_written );\n}\n#endif\n\n#if( DEBUG_WRITE_IDS_IN_SAVES )\nLONG Debug_Read_ID_Save_Game_File( INT file_handle )\n{\n\tLONG bytes_read_or_written = 0L;\n\tBYTE junk[ 4 ];\n\n\tif ( file_handle > -1 ) {\n\t\tbytes_read_or_written += Read_File( file_handle, &junk, 3 );\n\t}\n\n\treturn( bytes_read_or_written );\n}\n#endif\n\n#if( DEBUG_WRITE_IDS_IN_SAVES )\nLONG Debug_Write_ID_Save_Game_Memory( MemorySaveBufferType buffer_num, BYTE *three_byte_id )\n{\n\tLONG bytes_read_or_written = 0L;\n\n\tbytes_read_or_written += Memory_Save_Games[ buffer_num ].Write_Data( (UBYTE *) three_byte_id, 3 );\n\n\treturn( bytes_read_or_written );\n}\n#endif\n\n#if( DEBUG_WRITE_IDS_IN_SAVES )\nLONG Debug_Read_ID_Save_Game_Memory( MemorySaveBufferType buffer_num )\n{\n\tLONG bytes_read_or_written = 0L;\n\tBYTE junk[ 4 ];\n\n\tbytes_read_or_written += Memory_Save_Games[ buffer_num ].Read_Data( (UBYTE *) &junk, 3 );\n\n\treturn( bytes_read_or_written );\n}\n#endif\n\n/***************************************************************************\n * BUILD_DEBUG_LOG_FILE_NAME -- Based on the date and time of system       *\n *                                                                         *\n * INPUT: buffer to put file name in                                       *\n *                                                                         *\n * OUTPUT: none                                                            *\n *                                                                         *\n * WARNINGS: the buffer had better be at least 13 characters for filename  *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\n#if( DEBUG_LOG_TO_FILE )\nVOID Build_Debug_Log_File_Name( BYTE *name_string_buffer, BYTE *system_id_string_buffer )\n{\n\tSYSTEMTIME data;\n\tBYTE *ptr;\n\tINT fh;\n\tBYTE *file_name;\n\t\t\n\t/*\n\t\tbuild file in following format:\n\n\t\tAA BB CC DD . 0EE -> AABBCCDD.0EE\n\n\t\tAA = month 01-12\n\t\tBB = day 01-31\n\t\tCC = hour 00-23\n\t\tDD = minute 00-59\n\t\tEE = second 00-59\n\t*/\n\n\t/*\n\t\tget system time and data information and build a file name\n\t*/\n\tGetSystemTime( &data );\n//\tsprintf( name_string,\n//\t\t\t\t\"%2d%2d%2d%2d.%2d\",\n//\t\t\t\tdata.wMonth,\n//\t\t\t\tdata.wDay,\n//\t\t\t\tdata.wHour,\n//\t\t\t\tdata.wMinute,\n//\t\t\t\tdata.wSecond );\n\tsprintf( name_string_buffer,\n\t\t\t\t\"%2d%2d%2d%2d.%3d\",\n\t\t\t\tdata.wMonth,\n\t\t\t\tdata.wDay,\n\t\t\t\tdata.wHour,\n\t\t\t\tdata.wMinute,\n\t\t\t\t0 );\n\n\t/*\n\t\treplace spaces w/ 0's in file name\n\t*/\t\t\t\n\tptr = name_string_buffer;\n\twhile ( *ptr != '\\0' ) {\n\t\tif ( *ptr == ' ' ) {\n\t\t\t*ptr = '0';\n\t\t}\n\t\tptr ++;\n\t}\n\n//\t#if( DEBUG_CODE )\n//\t\tsprintf( Text_String,\n//\t\t\t\t\t\"Log file name for this session: %s\\r\\n\",\n//\t\t\t\t\tname_string );\n//\t\tDebug_Mono_Message( Text_String );\n//\t#endif\n\n\t/*\n\t\tbuild .INI file name (with directory path) in Text_String_2\n\t*/\n\tsprintf( Text_String_2,\n\t\t\t\t\"%sMONOPOLY.INI\",\n\t\t\t\tExecutable_Path );\n\n\t/*\n\t\tnow get the system id from \"monopoly.ini\" in Text_String_3, error if not in there\n\t*/\n\tif ( ! Find_File( Text_String_2 ) ) {\n\t\tsprintf( Text_String,\n\t\t\t\t\t\"%s not found!\",\n\t\t\t\t\tText_String_2 );\n\t\tDebug_Error_Window_Message( Text_String );\n\t\treturn;\n\t}\n\n\t/*\n\t\tget the DebugSystemName in Text_String_3 \n\t*/\n\tGetPrivateProfileString( \"Monopoly\",\n\t\t\t\t\t\t\t\t\t \"DebugSystemName\",\n\t\t\t\t\t\t\t\t\t \"No DebugSystemName found!\",\n\t\t\t\t\t\t\t\t\t Text_String_3,\n\t\t\t\t\t\t\t\t\t SIZE_OF_TEXT_STRING,\n\t\t\t\t\t\t\t\t\t Text_String_2 );\n\n\t/*\n\t\tNow store the system name\n   */\n\tif( strlen( Text_String_3 ) >= SIZE_OF_DEBUG_SYSTEM_ID_NAME ) {\n\t\t*( Text_String_3 + SIZE_OF_DEBUG_SYSTEM_ID_NAME - 1 ) = '\\0';\n\t}\n\tstrcpy( system_id_string_buffer, Text_String_3 );\n\n//\t#if( DEBUG_CODE )\n//\t\tsprintf( Text_String,\n//\t\t\t\t\t\"Legal DebugSystemName for this session: %s\\r\\n\",\n//\t\t\t\t\tText_String_3 );\n//\t\tDebug_Mono_Message( Text_String );\n//\t#endif\n\n\t/*\n\t\topen and write header to the log file\n\t*/\n\tstrcpy( Text_String_2,\n\t\t\t  \"----------------------------------------------------------------\\r\\n\" );\n\tsprintf( Text_String,\n\t\t\t\t\"---File: %s \\r\\n---Running on %02d/%02d/%02d at %02d:%02d \\r\\n---System: %s \\r\\n\",\n\t\t\t\tname_string_buffer,\n\t\t\t\tdata.wMonth, data.wDay, data.wYear,\n\t\t\t\tdata.wHour, data.wMinute,\n\t\t\t\tText_String_3 );\n\n//\t#if( DEBUG_CODE )\n//\tDebug_Mono_Message( Text_String );\n// #endif\n\n\t/*\n\t\topen the file and write out the header info!\n\t*/\n\n\tfile_name = Text_String_3;\n\tsprintf( file_name,\n\t\t\t\t\"%s%s\",\n\t\t\t\tExecutable_Path,\n\t\t\t\tname_string_buffer );\n\n\tfh = Open_File( file_name, WRITE );\n\tWrite_File( (INT)fh, (BYTE *)Text_String_2, (ULONG)(strlen(Text_String_2)) );\n\tWrite_File( (INT)fh, (BYTE *)Text_String,   (ULONG)(strlen(Text_String)) );\n\tWrite_File( (INT)fh, (BYTE *)Text_String_2, (ULONG)(strlen(Text_String_2)) );\n\tClose_File( fh );\n}\n\n#endif\n\n#if( DEBUG_LOG_TO_FILE )\nVOID Debug_Print_Log_File_Name_On_Board_Hid( VOID )\n{\n#if( 0 )\n\tSetTextAlign( WinG_DC, TA_LEFT ); \n\tSelectObject( WinG_DC, GetStockObject( ANSI_VAR_FONT ) );\n\tSetTextColor( WinG_DC, BLACK_RGB_COLOR_REF );\n\tSetTextCharacterExtra( WinG_DC, 0 );\n\tSetBkMode( WinG_DC, TRANSPARENT );\n\n\tsprintf( Text_String,\n\t\t\t\t\"Debug file: %s\",\n\t\t\t\tDebug_Log_File_Name );\n\n\tTextOut( WinG_DC, \n\t\t\t\tVQ_MOVIE_X+2, \n\t\t\t\tVQ_MOVIE_Y-2,\n\t\t\t\tText_String, \n\t\t\t\tstrlen( Text_String ) );\n\n\tsprintf( Text_String,\n\t\t\t\t\"System name: %s\",\n\t\t\t\tDebug_System_ID_Name );\n\n\tTextOut( WinG_DC, \n\t\t\t\tVQ_MOVIE_X+2, \n\t\t\t\tVQ_MOVIE_Y-2+10,\n\t\t\t\tText_String, \n\t\t\t\tstrlen( Text_String ) );\n\n\tsprintf( Text_String,\n\t\t\t\t\"Vers: %s\",\n\t\t\t\tVERSION_NUMBER_STRING );\n\n\tTextOut( WinG_DC, \n\t\t\t\tVQ_MOVIE_X+2, \n\t\t\t\tVQ_MOVIE_Y-2+20,\n\t\t\t\tText_String, \n\t\t\t\tstrlen( Text_String ) );\n#endif\n}\n#endif // DEBUG_CODE\n\n/*\n\tThis needs to be outside DEBUG_CODE\n*/\n/***************************************************************************\n * GET_AND_DISPLAY_WINDOWS_DEBUG -- GetWinDebugInfo() is called for checkin*\n *                                                                         *\n * INPUT: none                                                             *\n *                                                                         *\n * OUTPUT: none                                                            *\n *                                                                         *\n * WARNINGS: avoid the raptor pit on Jurassic Park                         *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\nBOOL Get_Windows_System_Info( VOID )\n{\n\tOSVERSIONINFO version_info;\t\n\tDWORD major;\n\tDWORD minor;\n\tFLOAT float_version;\n\n//#if( 0 )\n//\tWINDEBUGINFO current_windows_debug_info;\n//\tGetWinDebugInfo( &current_windows_debug_info,\n//\t\t\t\t\t\t  WDI_OPTIONS | WDI_FILTER | WDI_ALLOC_BREAK );\n//\tsprintf( Text_String,\n//\t\t\t\t\"Debug info:\\r\\nflags = %d, options = %d, filter = %d, alloc module = %s, \\r\\nalloc break = %ld, alloc count = %ld.\\r\\n\",\n//\t\t\t\tcurrent_windows_debug_info.flags,\n//\t\t\t\tcurrent_windows_debug_info.dwOptions,\n//\t\t\t\tcurrent_windows_debug_info.dwFilter,\n//\t\t\t\tcurrent_windows_debug_info.achAllocModule,\n//\t\t\t\tcurrent_windows_debug_info.dwAllocBreak,\n//\t\t\t\tcurrent_windows_debug_info.dwAllocCount );\n//\tDebug_Mono_Message( Text_String );\n//#endif\n\n\t/*------------------------------------------------------------------------*/\n\n\tWindows_95_Detected_Flag = FALSE;\n\n\tversion_info.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );\n\tif ( GetVersionEx( &version_info ) ) {\n\t\tsprintf( Text_String,\n\t\t\t\t\t\"Windows OS version: %ld.%ld, build #%ld, %s\\r\\n\",\n\t\t\t\t\tversion_info.dwMajorVersion,\t\n\t\t\t\t\tversion_info.dwMinorVersion,\t\n\t\t\t\t\tversion_info.dwBuildNumber,\n\t\t\t\t\tversion_info.szCSDVersion );\n\t\tDebug_Mono_Message( Text_String );\n\n\t\tif ( version_info.dwPlatformId == VER_PLATFORM_WIN32s ) {  // 0\n\t\t\t#if( DEBUG_CODE )\n\t\t\t\tDebug_Mono_Message( \"Windows OS Platform: Win32s on Windows 3.1\\r\\n\" );\n         #endif\n\n\t\t\tWindows_95_Detected_Flag = FALSE;\n\t\t\t/*\n\t\t\t\tif Win32s, make sure that we have version 1.25 or greater\n\t\t\t*/\n\t\t\tmajor = version_info.dwMajorVersion;\n\t\t\tminor = version_info.dwMinorVersion;\n\t\t\tsprintf( Text_String,\n\t\t\t\t\t\t\"%ld.%ld\",\n\t\t\t\t\t\tmajor, minor );\n\t\t\tsscanf( Text_String, \"%f\", &float_version );\n//\t\t\tif ( major < REQUIRED_WIN32S_MAJOR_VERSION || \n//\t\t\t\t( major == REQUIRED_WIN32S_MAJOR_VERSION && minor < REQUIRED_WIN32S_MINOR_VERSION ) ) {\n//\t\t\t\t\t\t\tReal_Error_Window_Message( \"Win32s version 1.25 or greater is required. Run SETUP.EXE from the Monopoly CD-ROM CD.\" );\t\n//\t\t\t\t\t\t\treturn( FALSE );\n//\t\t\t}\n\t\t\tif ( float_version < REQUIRED_WIN32S_FLOAT_VERSION ) {\n\t\t\t\t/*\n\t\t\t\t\tdo both in case TRR not set up\n\t\t\t\t*/\n\t\t\t\tReal_Error_Window_Message_String( \"Win32s version 1.25 or greater is required. Run SETUP.EXE from the Monopoly CD-ROM CD.\" );\t\n\t\t\t\tReal_Error_Window_Message( STR_TRR_SYSTEM_ERROR_76 );\t\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t}\n//\t\telse if ( version_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) { // 1\n\t\telse if ( version_info.dwPlatformId == 1 ) { // 1\n\t\t\t#if( DEBUG_CODE )\n\t\t\t\tDebug_Mono_Message( \"Windows OS Platform: Win32 on Chicago\\r\\n\" );\n\t\t\t#endif\n\t\t\tWindows_95_Detected_Flag = TRUE;\n\t\t}\n\t\telse if ( version_info.dwPlatformId == VER_PLATFORM_WIN32_NT ) {  // 2\n\t\t\t#if( DEBUG_CODE )\n\t\t\t\tDebug_Mono_Message( \"Windows OS Platform: Win32 NT\\r\\n\" );\n\t\t\t#endif\n\t\t\tWindows_95_Detected_Flag = FALSE;\n\t\t}\n\t\telse {\n\t\t\t#if( DEBUG_CODE )\n\t\t\t\tDebug_Mono_Message( \"Windows OS Platform: Unknown!\\r\\n\" );\n\t\t\t#endif\n\t\t\tWindows_95_Detected_Flag = TRUE; // just to be safe! future versions!\n\t\t}\n\t}\n\telse {\n\t\tDebug_Mono_Message( \"Unable to GetVersionEx()!\\r\\n\" );\n\t}\n\n\t/*------------------------------------------------------------------------*/\n\n//\t/*\n//\t\tdisplay command line string, if any\n//\t*/\n//\tsprintf( Text_String,\n//\t\t\t\t\"WinMain() command line string = %s\\r\\n\",\n//\t\t\t\tcommand_line_string );\n//\tDebug_Mono_Message( Text_String );\n\n\t/*\n\t\tShow the current directory\n\t*/\n//\tGetCurrentDirectory( SIZE_OF_TEXT_STRING, Text_String_3 );\n//\tsprintf( Text_String,\n//\t\t\t\t\"GetCurrentDirectory() = %s\\r\\n\",\n//\t\t\t\tText_String_3 );\n//\tDebug_Mono_Message( Text_String );\n\n\tsprintf( Text_String,\n\t\t\t\t\"Executable_Path[] = %s\\r\\n\",\n\t\t\t\tExecutable_Path );\n\tDebug_Mono_Message( Text_String );\n\n\tsprintf( Text_String,\n\t\t\t\t\"CD_Root_Path[] = %s\\r\\n\",\n\t\t\t\tCD_Root_Path );\n\tDebug_Mono_Message( Text_String );\n\n\t/*\n\t\tdisplay argv arguments\n\t*/\n//\tfor ( i = 0; i < _argc; i ++ ) {\n//\t\tsprintf( Text_String,\n//\t\t\t\t\t\"WinMain() argv[ %d ] = %s\\r\\n\",\n//\t\t\t\t\ti,\n//\t\t\t\t\t_argv[ i ] );\n//\t\tDebug_Mono_Message( Text_String );\n//\t}\n\n\treturn( TRUE );\n}\n\n//#if( DEBUG_VERIFY_ALL_SITES_DATA )\n//VOID Debug_Broadcast_Save_Game_Data_To_Other_Sites( VOID )\n//{\n//\tBYTE *file_name = \"TEMPSEND.TMP\";\n//\tULONG file_size;\n//\tINT fh;\n//\tINT i;\n//\tBYTE *buffer;\n//\tSOCKET temp_socket;\n//\tINT status;\n//\n//\t/*\n//\t\tfirst save out the current game data\n//\t*/\n//\tDOS_Save_Game( file_name, TRUE ); // TRUE = site-to-site verification\n//\t/*\n//\t\tnow allocate a buffer and load the save data back up\n//\t*/\n//\tfh = Open_File( file_name, READ );\n//\tif ( fh != -1 ) {\n//\t\tfile_size = File_Size( fh );\n//\t\tbuffer = (BYTE *) Alloc( (ULONG) file_size + 10, MEM_NORMAL );\n//\t\tif ( buffer == NULL ) {\n//\t\t\tClose_File( fh );\n//\t\t\tGeneric_Window_Message( \"Unable to alloc buffer in Debug_Broadcast_Save_Game_Data_To_Other_Sites()\", \" \" );\n//\t\t\treturn;\n//\t\t}\n//\t\tRead_File( fh, buffer, file_size );\n//\t\tClose_File( fh );\n//\t}\n//\n//\t#if( COMPILE_WINSOCK )\n//\t\t/*\n//\t\t\tsend a system command that the save game data is coming over\n//\t\t*/\n//\t\tWinSock_Broadcast_Command( CMD_HERE_COMES_MY_GAME_STATUS_BUFFER, 1, (INT) file_size );\n//\t\t/*\n//\t\t\tnow blast the data over!\n//\t\t*/\n//\t\t/* if this system was the original host */\n//\t\tif ( Waiting_Socket_Index > -1 ) {\n//\t\t\t/* send the command to all the \"waiter links\" */\n//\t\t\tfor ( i = 0; i <= Waiting_Socket_Index; i ++ ) {\n//\t\t\t\ttemp_socket = Hosts_Waiting_Sockets[ i ].accepted_connection_waiting_socket;\n//\t\t\t\tif ( temp_socket != INVALID_SOCKET ) {\n//\t\t\t\t\tstatus = WINSOCK_SEND( temp_socket, buffer, file_size, 0 );\n//\t\t\t\t\tif ( status == SOCKET_ERROR ) {\n//\t\t\t\t\t\tGeneric_Window_Message( \"Bad send() of save game data\", \" \" );\n//\t\t\t\t\t}\n//\t\t\t\t\telse {\n//\t\t\t\t\t\tsprintf( Text_String, \"%d size save game data buffer sent\\r\\n\", status );\n//\t\t\t\t\t\tDebug_Mono_Message( Text_String );\n//\t\t\t\t\t}\n//\t\t\t\t}\n//\t\t\t}\n//\t\t}\n//\t\t/* else this system is a webbee */\n//\t\telse {\n//\t\t\t/* send the command to the original host */\n//\t\t\tif ( WC_Temp_Waiter_Socket != INVALID_SOCKET ) {\n//\t\t\t\tstatus = WINSOCK_SEND( WC_Temp_Waiter_Socket, buffer, file_size, 0 );\n//\t\t\t\tif ( status == SOCKET_ERROR ) {\n//\t\t\t\t\tGeneric_Window_Message( \"Bad send() of save game data\", \" \" );\n//\t\t\t\t}\n//\t\t\t\telse {\n//\t\t\t\t\tsprintf( Text_String, \"%d size save game data buffer sent\\r\\n\", status );\n//\t\t\t\t\tDebug_Mono_Message( Text_String );\n//\t\t\t\t}\n//\t\t\t}\n//\t\t\t/* then send the command to all other connected webbees */\n//\t\t\tfor ( i = 0; i <= Web_Accepted_Socket_Index; i ++ ) {\n//\t\t\t\ttemp_socket = Web_Accepted_Sockets[ i ];\n//\t\t\t\tif ( temp_socket != INVALID_SOCKET ) {\n//\t\t\t\t\tstatus = WINSOCK_SEND( temp_socket, buffer, file_size, 0 );\n//\t\t\t\t\tif ( status == SOCKET_ERROR ) {\n//\t\t\t\t\t\tGeneric_Window_Message( \"Bad send() of save game data\", \" \" );\n//\t\t\t\t\t}\n//\t\t\t\t\telse {\n//\t\t\t\t\t\tsprintf( Text_String, \"%d size save game data buffer sent\\r\\n\", status );\n//\t\t\t\t\t\tDebug_Mono_Message( Text_String );\n//\t\t\t\t\t}\n//\t\t\t\t}\n//\t\t\t}\n//\t\t}\n//\t#endif\n//\n//\tif ( buffer ) {\n//\t\tFree( buffer );\n////\t\tbuffer = NULL;\n//\t}\n////\tDelete_File( file_name );\n//}\n//#endif /* DEBUG_VERIFY_ALL_SITE_DATA */\n\n//#if( DEBUG_VERIFY_ALL_SITES_DATA )\n//VOID Debug_Prepare_To_Receive_Other_Site_Save_Game_Data( INT buffer_size )\n//{\n//\tif ( Incoming_Save_Game_Data ) {\n//\t\tGeneric_Window_Message( \"Incoming_Save_Game_Data already allocated!\", \" \" );\n//\t\tFree( Incoming_Save_Game_Data );\n//\t\tIncoming_Save_Game_Data = NULL;\n//\t}\n//\n//\tIncoming_Save_Game_Data = (BYTE *) Alloc( (buffer_size) + 10, MEM_NORMAL );\n//\tIncoming_Save_Game_Data_Size = buffer_size;\n//\tif ( ! Incoming_Save_Game_Data ) {\n//\t\tGeneric_Window_Message( \"Unable to allocate Incoming_Save_Game_Data\\r\\n\", \" \" );\n//\t\tIncoming_Save_Game_Data_Size = 0;\n//\t}\t\n//\telse {\n//\t\tDebug_Mono_Message( \"Incoming_Save_Game_Data allocated and ready for receive...\\r\\n\" );\n//\t}\n//}\n//#endif /* DEBUG_VERIFY_ALL_SITE_DATA */\n//\n//#if( DEBUG_VERIFY_ALL_SITES_DATA )\n//VOID Debug_Verify_Incoming_Save_Data( INT bytes_actually_received )\n//{\n//\tINT fh;\n//\tBYTE *buffer = NULL;\n//\tBYTE *file_name = \"TEMPSAVE.TMP\";\n//\tLONG file_compare;\n//\n//\tif ( ! Incoming_Save_Game_Data || ! Incoming_Save_Game_Data_Size ) {\n//\t\treturn;\n//\t}\n//\n//\tsprintf( Text_String,\n//\t\t\t\t\"Save game data rec'd for verify, expected %d, actual %d\\r\\n\",\n//\t\t\t\tIncoming_Save_Game_Data_Size,\n//\t\t\t\tbytes_actually_received );\n//\tDebug_Mono_Message( Text_String );\t\t\t\t\t\t\t\t\n//\n//\t/*\n//\t\ttemp save the \"just received save game\" buffer out\n//\t*/\n//\tfh = Open_File( \"TEMPRECV.MNO\", WRITE );\n//\tif ( fh != -1 ) {\n//\t\tWrite_File( fh, (BYTE *) Incoming_Save_Game_Data, Incoming_Save_Game_Data_Size );\n//\t\tClose_File( fh );\n//\t}\n//\telse {\n//\t\tGeneric_Window_Message( \"Unable to save out temporary rec'd save game\", \" \" );\n//\t}\n//\n//\t/*\n//\t\tnow compare the data just rec'd with our current save game\n//\t*/\n//\t/*\n//\t\tfirst save out the local current game data on this system\n//\t*/\n//\tDOS_Save_Game( file_name, TRUE ); // TRUE = site-to-site verification\n//\n//\t/*\n//\t\tdo file compare here between file_name (local) and\n//\t\ttemprecv.mno (rec'd from remote)\n//\t*/\n//\tfile_compare = Debug_Compare_Two_Files( file_name, \"TEMPRECV.MNO\" );\n//\tswitch( file_compare ) {\n//\t\tcase -4L: Debug_Mono_Message( \"Received game status data fine!\\r\\n\" ); break;\n//\t\tcase -3L: Debug_Mono_Message( \"Memory error occured w/ file compare!\\r\\n\" ); break;\n//\t\tcase -2L: Debug_Mono_Message( \"File error occured w/ file compare!\\r\\n\" ); break;\n//\t\tcase -1L: Generic_Window_Message( \"Error! Data verification file sizes different!\", \" \" );\n//\t\tdefault:\t\n//\t\t\tsprintf( Text_String,\n//\t\t\t\t\t\t\"Error! Data verification files differ at byte %ld\",\n//\t\t\t\t\t\tfile_compare );\n//\t\t\tGeneric_Window_Message( Text_String, \" \" );\t\t\t\n//\t\t\tsprintf( Text_String,\n//\t\t\t\t\t\t\"Compare %s (our system) and TEMPRECV.MNO (rec'd)!\",\n//\t\t\t\t\t\tfile_name );\n//\t\t\tGeneric_Window_Message( Text_String, \" \" );\t\t\t\n//\t}\n//\n//\t/*\n//\t\tfree the temporary buffer\n//\t*/\n//\tif( buffer ) {\n//\t\tFree( buffer );\n////\t\tbuffer = NULL;\n//\t}\n//\t/*\n//\t\tfree it all up for next time\n//\t*/\n//\tif( Incoming_Save_Game_Data ) {\n//\t\tFree( Incoming_Save_Game_Data );\n//\t\tIncoming_Save_Game_Data = NULL;\t\n//\t}\n//\tIncoming_Save_Game_Data_Size = 0;\n//}\n//#endif /* DEBUG_VERIFY_ALL_SITE_DATA */\n\n///*\n//\t0+ = different at byte 0+\n//\t-1\t= size different\n//\t-2 = file / DOS error\n//\t-3\t= allocation / memory error\n//\t-4 = files are the same!\n//*/\n//#if( DEBUG_VERIFY_ALL_SITES_DATA )\n//LONG Debug_Compare_Two_Files( BYTE *file_name_1, BYTE *file_name_2 )\n//{\n//\tINT fh_1;\n//\tINT fh_2;\n//\tLONG file_size_1;\n//\tLONG file_size_2;\n//\tUBYTE *buffer_1;\n//\tUBYTE *buffer_2;\n//\tUBYTE *ptr_1;\n//\tUBYTE *ptr_2;\n//\tLONG bytes_read_1;\n//\tLONG bytes_read_2;\n//\tLONG i;\n//\tLONG error_byte_index;\n//\n//\tfh_1 = Open_File( file_name_1, READ );\n//\tif ( fh_1 == -1 ) {\n//\t\tsprintf( Text_String,\n//\t\t\t\t\t\"File %s could not be opened\\r\\n\",\n//\t\t\t\t\tfile_name_1 );\n//\t\tDebug_Mono_Message( Text_String );\n//\t\treturn( -2L ); // ERROR!\n//\n//\t}\n//\tfh_2 = Open_File( file_name_2, READ );\n//\tif ( fh_2 == -1 ) {\n//\t\tsprintf( Text_String,\n//\t\t\t\t\t\"File %s could not be opened\\r\\n\",\n//\t\t\t\t\tfile_name_2 );\n//\t\tDebug_Mono_Message( Text_String );\n//\t\tClose_File( fh_1 );\n//\t\treturn( -2L );  // ERROR!\n//\n//\t}\n//\n//\tfile_size_1 = File_Size( fh_1 );\n//\tfile_size_2 = File_Size( fh_2 );\n////\tfile_size_1 = 662;\n////\tfile_size_2 = 662;\n//\n//\tsprintf( Text_String,\n//\t\t\t\t\"File_Size() of %s = %d bytes, File_Size() of %s = %d bytes\\r\\n\",\n//\t\t\t\tfile_name_1,\n//\t\t\t\tfile_size_1,\n//\t\t\t\tfile_name_2,\n//\t\t\t\tfile_size_2 );\n//\tDebug_Mono_Message( Text_String );\n//\n//\tif ( file_size_1 != file_size_2 ) {\n////\t\tDebug_Mono_Message( \"About to call Close_File()\\r\\n\" );\n//\t\tClose_File( fh_1 );\n////\t\tDebug_Mono_Message( \"About to call Close_File()\\r\\n\" );\n//\t\tClose_File( fh_2 );\n//\t\treturn( -1L );  // ERROR!\n//\t}\n//\n////\tDebug_Mono_Message( \"About to call Alloc()\\r\\n\" );\n//\tbuffer_1 = (UBYTE *) Alloc( (ULONG) (file_size_1 + 10L), MEM_NORMAL );\n////\tDebug_Mono_Message( \"About to call Alloc()\\r\\n\" );\n//\tbuffer_2 = (UBYTE *) Alloc( (ULONG) (file_size_2 + 10L), MEM_NORMAL );\n//\tif ( ! buffer_1 || ! buffer_2 ) {\n//\t\tif ( buffer_1 ) {\n////\t\t\tDebug_Mono_Message( \"error, About to call Free()\\r\\n\" );\n//\t\t\tFree( buffer_1 );\n//\t\t}\n//\t\tif ( buffer_2 ) {\n////\t\t\tDebug_Mono_Message( \"error, About to call Free()\\r\\n\" );\n//\t\t\tFree( buffer_2 );\n//\t\t}\n////\t\tDebug_Mono_Message( \"error, About to call Close_File()\\r\\n\" );\n//\t\tClose_File( fh_1 );\n////\t\tDebug_Mono_Message( \"error, About to call Close_File()\\r\\n\" );\n//\t\tClose_File( fh_2 );\n//\t\treturn( -3L );  // ERROR!\n//\t}\n//\n////\tDebug_Mono_Message( \"About to call Read_File()\\r\\n\" );\n//\tbytes_read_1 = Read_File( fh_1, buffer_1, file_size_1 );\n////\tDebug_Mono_Message( \"About to call Read_File()\\r\\n\" );\n//\tbytes_read_2 = Read_File( fh_2, buffer_2, file_size_2 );\n////\tDebug_Mono_Message( \"About to call Close_File()\\r\\n\" );\n//\tClose_File( fh_1 );\n////\tDebug_Mono_Message( \"About to call Close_File()\\r\\n\" );\n//\tClose_File( fh_2 );\n//\n//\tsprintf( Text_String,\n//\t\t\t\t\"Bytes read of %s = %d bytes, bytes read of %s = %d bytes\\r\\n\",\n//\t\t\t\tfile_name_1,\n//\t\t\t\tbytes_read_1,\n//\t\t\t\tfile_name_2,\n//\t\t\t\tbytes_read_2 );\n//\tDebug_Mono_Message( Text_String );\n//\n//\tif ( bytes_read_1 != bytes_read_2 ) {\n////\t\tDebug_Mono_Message( \"Error, About to call Free()\\r\\n\" );\n//\t\tFree( buffer_1 );\n////\t\tDebug_Mono_Message( \"Error, About to call Free()\\r\\n\" );\n//\t\tFree( buffer_2 );\n//\t\treturn( -2L ); // ERROR!\n//\t}\n//\n////\tDebug_Mono_Message( \"About to call memcmp()\\r\\n\" );\n//\tif ( memcmp( buffer_1, buffer_2, file_size_1 ) ) {\n//\n//\t\tDebug_Mono_Message( \"Error: Files are different\\r\\n\" );\n//\n//\t\tptr_1 = (UBYTE *) buffer_1;\n//\t\tptr_2 = (UBYTE *) buffer_2;\n//\t\t/*\n//\t\t\tscan the data and find which byte # the error occured on\n//\t\t*/\n//\t\terror_byte_index = 0L;\n//\t\tfor ( i = 0; i < file_size_1; i ++ ) {\n//\t\t\tif ( *ptr_1 != *ptr_2 ) {\n//\t\t\t\terror_byte_index = i;\n//\t\t\t\ti = file_size_1;\n//\t\t\t}\n//\t\t\tptr_1 += 1;\n//\t\t\tptr_2 += 1;\n//\t\t}\n//\n////\t\tDebug_Mono_Message( \"Error, About to call Free()\\r\\n\" );\n//\t\tFree( buffer_1 );\n////\t\tDebug_Mono_Message( \"Error, About to call Free()\\r\\n\" );\n//\t\tFree( buffer_2 );\n//\n//\t\tsprintf( Text_String,\n//\t\t\t\t\t\"Error, files are different at byte #%d\\r\\n\",\n//\t\t\t\t\terror_byte_index );\n//\t\tDebug_Mono_Message( Text_String );\n//\n//\t\treturn( (LONG) error_byte_index ); // ERROR!\n//\t}\n//\n////\tDebug_Mono_Message( \"About to call Free()\\r\\n\" );\n//\tFree( buffer_1 );\n////\tDebug_Mono_Message( \"About to call Free()\\r\\n\" );\n//\tFree( buffer_2 );\n//\n//\tDebug_Mono_Message( \"Both files match!\\r\\n\" );\n//\treturn( -4L ); // SUCCESS!\n//}\n//#endif\n\nBYTE *Debug_Get_Time_String( VOID )\n{\n\tSYSTEMTIME data;\n\tstatic BYTE _time_string[ 20 ];\n\t\t\n\t/*\n\t\tbuild file in following format:\n\n\t\tAA BB CC DD . 0EE -> AABBCCDD.0EE\n\n\t\tAA = month 01-12\n\t\tBB = day 01-31\n\t\tCC = hour 00-23\n\t\tDD = minute 00-59\n\t\tEE = second 00-59\n\t*/\n\n\t/*\n\t\tget system time and data information and build a file name\n\t*/\n\tGetSystemTime( &data );\n//\tsprintf( _time_string,\n//\t\t\t\t\"%2d%2d%2d%2d.%2d\",\n//\t\t\t\tdata.wMonth,\n//\t\t\t\tdata.wDay,\n//\t\t\t\tdata.wHour,\n//\t\t\t\tdata.wMinute,\n//\t\t\t\tdata.wSecond );\n\tsprintf( _time_string,\n\t\t\t\t\"%2d:%2d\",\n\t\t\t\tdata.wHour,\n\t\t\t\tdata.wMinute );\n\n\treturn( _time_string );\n}\n\n\nVOID Check_For_Duplicate_Tokens_Bug( VOID )\n{\n#if( DEBUG_CODE )\n\tINT i, j;\n\tGameTokenType token;\n\n\tfor ( i = FIRST_PLAYER; i < Game_Status.Get_Total_Players(); i ++ ) {\n\t\ttoken = Players[ i ].Get_Token();\n\t\tfor ( j = FIRST_PLAYER; j < Game_Status.Get_Total_Players(); j ++ ) {\n\t\t\tif ( j != i ) {\n\t\t\t\tif ( Players[ j ].Get_Token() == token ) {\n\t\t\t\t\t/*\n\t\t\t\t\t\tSound the alarm!\n\t\t\t\t\t*/\n\t\t\t\t\tPlay_Sound( SND_GOTOJAIL, PLAY_KILL_PREVIOUS_SOUND, BROADCAST_SOUND );\n\t\t\t\t\tDebug_Error_Window_Message( \"Emergency! The annoying Double-token bug has been encountered!\\r\\n\" );\n\t\t\t\t\tDebug_Error_Window_Message( \"Give the .000 log file from this system/game to the Mikes!\" );\n\t\t\t\t\tDebug_Error_Window_Message( \"Get the .000 log files from the other systems in this game, too.\" );\n\t\t\t\t\tDebug_Error_Window_Message( \"Other data may be hosed, so this game is probably now invalid.\" );\n\t\t\t\t\tDebug_Error_Window_Message( \"With the log file, we should be able to find the stinkin' bug.\" );\n\t\t\t\t\tDebug_Error_Window_Message( \"Excellent work, Mr. Bond!\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#endif\n}\n\n#if( RIG_ROLL_FOR_PLAYTEST )\n/***************************************************************************\n * DEBUG_RIG_ROLL -- Pops up dialog to fix the next dice roll              *\n *                                                                         *\n * INPUT: parent window handle                                             *\n *                                                                         *\n * OUTPUT: none                                                            *\n *                                                                         *\n * WARNINGS: none                                                          *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\nVOID Debug_Rig_Roll( WindowHandle window_handle )\n{\n\tif ( ! Game_Status.Is_Game_In_Progress() ) {\n\t\t#if( DEBUG_CODE )\n\t\t\tDebug_Error_Window_Message( \"Game not in progress!\" );\n\t\t#endif\n\t\treturn;\n\t}\n\n\tDialogBox( Global_Instance_Handle, \n\t\t\t\t  \"DebugDiceDlgBox\", \n\t\t\t\t  window_handle, \n\t\t\t\t  (DLGPROC) Debug_Rig_Roll_Dialog_Procedure );\n\n\t#if( DEBUG_CODE )\n\t\tDebug_Mono_Message( \"***** The next roll has been rigged! *****\\r\\n\" );\n\t#endif\n\n\t#if( COMPILE_WINSOCK )\n//\tif ( Multiple_Site_Game_In_Progress ) {\t\n//\t\tWinSock_Broadcast_Cmd_String( CMD_SEND_YELL_MESSAGE_STRING, \n//\t\t\t\t\t\t\t\t\t\t\t\tGame_Status.Get_Whos_Turn_Is_It_Now(), \n//\t\t\t\t\t\t\t\t\t\t\t\t\"The next dice roll has been rigged!\\r\\n\" );\n// }\n   #endif\n}\n\n#pragma argsused\n/***************************************************************************\n * DEBUG_RIG_ROLL_DIALOG_PROCEDURE -- Handles commands to dialog           *\n *                                                                         *\n * INPUT: standard windows dialog command parameters                       *\n *                                                                         *\n * OUTPUT: TRUE if dice rigged, FALSE if not                               *\n *                                                                         *\n * WARNINGS: none                                                          *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\nPRIVATE BOOL Debug_Rig_Roll_Dialog_Procedure( WindowHandle window_handle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t UINT message,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t WPARAM w_param,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t LPARAM l_param )\n{\n\tINT die1, die2;\n\n\tswitch( message ) {\n\t\n\t\tcase WM_COMMAND:\n\n\t\t\tif ( LOWORD( w_param ) == IDOK ) {\n\n\t\t\t\tGetDlgItemText( window_handle, \n\t\t\t\t\t\t\t\t\t DIE_EDIT1, \n\t\t\t\t\t\t\t\t\t Text_String, \n\t\t\t\t\t\t\t\t\t SIZE_OF_TEXT_STRING );\n\t\t\t\tdie1 = atoi( Text_String );\n\n\t\t\t\tGetDlgItemText( window_handle, \n\t\t\t\t\t\t\t\t\t DIE_EDIT2, \n\t\t\t\t\t\t\t\t\t Text_String, \n\t\t\t\t\t\t\t\t\t SIZE_OF_TEXT_STRING );\n\t\t\t\tdie2 = atoi( Text_String );\n\n\t\t\t\tif ( die1 < 1 || die1 > 6 || die2 < 1 || die2 > 6 ) {\n\t\t\t\t\t#if( DEBUG_CODE )\n\t\t\t\t\t\tDebug_Error_Window_Message( \"Illegal values, defaulting to 1 & 1.\\r\\n\" );\n               #endif\n\t\t\t\t\tdie1 = 1;\n\t\t\t\t\tdie2 = 1;\n\t\t\t\t}\n\n\t\t\t\tDice.Set_Debug_Die( 1, die1 );\n\t\t\t\tDice.Set_Debug_Die( 2, die2 );\n\n\t\t\t\tsprintf( Text_String,\n\t\t\t\t\t\t\t\"The next dice roll is rigged for a %d and a %d.\\r\\n\",\n\t\t\t\t\t\t\tdie1, die2 );\n\t\t\t\tDebug_Mono_Message( Text_String );\n\n\t\t\t\tEndDialog( window_handle, TRUE );\n\t\t\t\treturn( TRUE );\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault: break;\n\n\t}\n\treturn( FALSE );\n}\n#endif\n\n\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/DEBUG.RC",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Virtual Monopoly                         *\n *                                                                         *\n *                    File Name : DEBUG.RC                                 *\n *                                                                         *\n *                   Programmer : Michael Legg                             *\n *                                                                         *\n *                   Start Date : February 9, 1995                         *\n *                                                                         *\n *                  Last Update : May 30, 1995   [ML]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include \"defines.h\"\n#include \"debug.rh\"\n\n#if( RIG_ROLL_FOR_PLAYTEST )\n\nDebugDiceDlgBox DIALOG 152, 52, 109, 85\nSTYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU\nCAPTION \"Deciding Next Roll...\"\nFONT 8, \"MS Sans Serif\"\n{\n PUSHBUTTON \"Ready to roll...\", IDOK, 18, 59, 72, 16\n EDITTEXT DIE_EDIT1, 57, 15, 25, 12\n EDITTEXT DIE_EDIT2, 57, 35, 25, 12\n LTEXT \"Bone #2\", -1, 26, 36, 29, 8\n LTEXT \"Bone #1\", -1, 26, 18, 29, 9\n}\n\n#endif\n\n#if( DEBUG_CODE )\n\nDebugSetCashDlgBox DIALOG 152, 52, 106, 64\nSTYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU\nCAPTION \"Set Player's Cash\"\nFONT 8, \"MS Sans Serif\"\n{\n DEFPUSHBUTTON \"OK\", IDOK, 31, 39, 43, 13\n EDITTEXT CASH_EDIT1, 32, 15, 41, 12\n}\n\n#endif\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/DIALOGS.RC",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQA VIEWER                               *\n *                                                                         *\n *                    File Name : DIALOGS.RC                               *\n *                                                                         *\n *                   Programmer : Mike Grayford                            *\n *                                                                         *\n *                   Start Date : Dec 5, 1995                              *\n *                                                                         *\n *                  Last Update : Dec 5, 1995 [MG]                         *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include \"windows.h\"\n#include \"dialogs.rh\"\n\nGEEB DIALOG 152, 52, 106, 64\n//STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU\nSTYLE WS_POPUP\nCAPTION \"Hi\"\n{\n   DEFPUSHBUTTON \"OK\", IDOK, 31, 39, 43, 13\n   EDITTEXT FRAME_RATE, 32, 15, 41, 12\n}\n\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/DIALOGS.RH",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQA VIEWER                               *\n *                                                                         *\n *                    File Name : DIALOGS.RH                               *\n *                                                                         *\n *                   Programmer : Mike Grayford                            *\n *                                                                         *\n *                   Start Date : Dec 5, 1995                              *\n *                                                                         *\n *                  Last Update : Dec 5, 1995 [MG]                         *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#define FRAME_RATE\t100\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/GAMETIME.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQAVIEW                                  *\n *                                                                         *\n *                    File Name : GAMETIME.CPP                             *\n *                                                                         *\n *                   Programmer : Michael Grayford                         *\n *                                                                         *\n *                   Start Date :                                          *\n *                                                                         *\n *                  Last Update : Nov 22, 1995   [MG]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n//==========================================================================\n// INCLUDES\n//==========================================================================\n\n#include <windows.h>\n#include <gametime.h>\n\n//==========================================================================\n// PUBLIC DATA\n//==========================================================================\n\nGameTimeClass Game_Time;\n\n/***************************************************************************\n * GameTimeClass - Constructor function for GameTimeClass                  *\n *                                                                         *\n * INPUT:\t                                                                 *\n *                                                                         *\n * OUTPUT:\t                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1995  MG : Created.                                             *\n *=========================================================================*/\nGameTimeClass::GameTimeClass( void )\n{\n\tgame_start_time = timeGetTime();\n}\n\n\n/***************************************************************************\n * Get_Time - returns the time in ms elapsed since game was started        *\n *                                                                         *\n * INPUT:\t                                                                 *\n *                                                                         *\n * OUTPUT:\t                                                              *\n *\t\tunsigned long - time in milliseconds since game was started         *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1995  MG : Created.                                             *\n *=========================================================================*/\nunsigned long GameTimeClass::Get_Time( void )\n{\n\tunsigned long curr_windows_time;\n\tunsigned long game_time;\n\n\tcurr_windows_time = timeGetTime();\n\tif ( curr_windows_time <= game_start_time ) {\n\t\t// Handles the case if the windows time wraps while playing the game.\n\t\tgame_time = MAX_ULONG - game_start_time + curr_windows_time;\n\t}\n\telse {\n   \t\tgame_time = curr_windows_time - game_start_time;\n\t}\n\treturn( game_time );\n}\n\n\n/***************************************************************************\n * Get_Game_Time - returns the time in ms elapsed since game was started   *\n *                                                                         *\n * INPUT:\t                                                                 *\n *                                                                         *\n * OUTPUT:\t                                                              *\n *\t\tunsigned long - time in milliseconds since game was started         *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1995  MG : Created.                                             *\n *=========================================================================*/\nunsigned long Get_Game_Time( void )\n{\n\treturn( Game_Time.Get_Time() );\n}\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/GAMETIME.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQAVIEW                                  *\n *                                                                         *\n *                    File Name : GAMETIME.H                               *\n *                                                                         *\n *                   Programmer : Michael Grayford                         *\n *                                                                         *\n *                   Start Date :                                          *\n *                                                                         *\n *                  Last Update : Nov 22, 1995   [MG]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n//==========================================================================\n// PUBLIC FUNCTIONS\n//==========================================================================\n\nextern unsigned long Get_Game_Time();\n\n//==========================================================================\n// PUBLIC DEFINES\n//==========================================================================\n\n#define MAX_ULONG\t\t\t\t0xFFFFFFFF\n\n//==========================================================================\n// CLASSES\n//==========================================================================\n\nclass GameTimeClass {\n\tprivate:\n\t\tunsigned long game_start_time;\n\n\tpublic:\n\t\tGameTimeClass( void );\n\t\tunsigned long Get_Time( void );\n\n}; /* VQAClass */\n\n\n//==========================================================================\n// PUBLIC DATA\n//==========================================================================\n\nextern GameTimeClass Game_Time;\n\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/INTERPAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\n;**********************************************************************************************\n;**   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  I N C                     **\n;**********************************************************************************************\n;*                                                                                            *\n;*                 Project Name : VQA Viewer                                                  *\n;*                                                                                            *\n;*                    File Name : INTERPAL.ASM                                                *\n;*                                                                                            *\n;*                   Programmer : Steve Tall                                                  *\n;*                                                                                            *\n;*                   Start Date : December 15th, 1995                                         *\n;*                                                                                            *\n;*                  Last Update : December 22nd, 1995  [ST]                                   *\n;*                                                                                            *\n;*--------------------------------------------------------------------------------------------*\n;* Functions:                                                                                 *\n;*                                                                                            *\n;*  Asm_Interpolate -- interpolate a 320x200 buffer to a 640x400 screen                       *\n;*                                                                                            *\n;*                                                                                            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  *\n\n\n\n\n\t\tIDEAL\n\t\tP386\n\t\tMODEL USE32 FLAT\n\n\n\t\tsegment mycode page public use32 'code'\t; Need stricter segment alignment\n\nglobal\t\tC\tAsm_Interpolate:near\nglobal\t\tC\tPalette_Interpolation_Table:byte\n\n\n\n\n\n;*********************************************************************************************\n;* Asm_Interpolate -- interpolate a 320x200 buffer to a 640x400 screen                       *\n;*                                                                                           *\n;* INPUT:\tptr to source buffer (320x200 image)                                         *\n;*              ptr to dest buffer (640x400)                                                 *\n;*              height of source buffer                                                      *\n;*              width f source buffer                                                        *\n;*              width of dest buffer                                                         *\n;*                                                                                           *\n;*                                                                                           *\n;* OUTPUT:      none                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   12/15/95 ST : Created.                                                                  *\n;*===========================================================================================*\n\nPROC\t\tAsm_Interpolate C near\n\n\t\tARG\tsrc_ptr:dword\n\t\tARG\tdest_ptr:dword\n\t\tARG\tsource_height:dword\n\t\tARG\tsource_width:dword\n\t\tARG\tdest_width:dword\n\n\t\tLOCAL\told_dest:dword\n\t\tLOCAL\twidth_counter:dword\n\n\t\tpushad\n\n\t\tmov\teax,[dest_ptr]\n\t\tmov\t[old_dest],eax\n\n\t\tmov\tesi,[src_ptr]\n\n??each_line_loop:\n\t\tmov\t[width_counter],0\n\t\tmov\tecx,[source_width]\n\t\tsub\tecx,2\n\t\tshr\tecx,1\n\t\tmov\tedi,[old_dest]\n\t\tjmp\t??interpolate_loop\n\n\t\talign\t32\n;\n; convert 2 pixels of source into 4 pixels of destination\n; so we can write to video memory with dwords\n;\n??interpolate_loop:\n\t\tmov\teax,[esi]\n\t\tlea\tesi,[esi+2]\n\t\tmov\tedx,eax\n\t\tmov\tebx,eax\n\t\tand\tedx,65535\n\t\tror\tebx,8\n\t\tmov\tbl,[edx+Palette_Interpolation_Table]\n\t\tmov\tbh,ah\n\t\tand\teax,000ffff00h\n\t\tror\tebx,8\n\n;1st 3 pixels now in ebx\n\n\t\tshr\teax,8\n\t\tmov\tbh,[eax+Palette_Interpolation_Table]\n\t\tror\tebx,16\n\t\tmov\t[edi],ebx\n\t\tadd\tedi,4\n\n\t\tdec\tecx\n\t\tjnz\t??interpolate_loop\n\n; do the last three pixels and a blank on the end of a row\n\t\txor\teax,eax\n\t\tmov\tax,[esi]\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\t\tlea\tesi,[esi+2]\n\t\tmov\tal,[eax+Palette_Interpolation_Table]\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\t\tmov\t[edi],ah\n\t\tinc\tedi\n\t\tmov\t[byte edi],0\n\n\t\tmov\tedi,[dest_width]\n\t\tadd\t[old_dest],edi\n\n\t\tdec\t[source_height]\n\t\tjnz\t??each_line_loop\n\n\t\tpopad\n\t\tret\n\nendp\t\tAsm_Interpolate\n\n\n\n\nends\t\tmycode\n\nend\n\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/MAIN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/**********************************************************************************************\n ***             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              ***\n **********************************************************************************************\n *                                                                                            *\n *                 Project Name : VQAVIEW\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                                            *\n *                    File Name : MAIN.CPP                                                \t   *\n *                                                                                            *\n *                   Programmer : Mike Grayford                                               *\n *                                                                                            *\n *                   Start Date : November 14, 1995                                          \t*\n *                                                                                            *\n *                  Last Update : November 20, 1995 [MG]                                     \t*\n *                                                                                            *\n *--------------------------------------------------------------------------------------------*\n * Functions:                                                                                 *\n *  WinMain \t\t-- Program entry point                                                      \t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/\n\n\n//---------------------------------------------------------------------------------------------\n//\tINCLUDES\n//---------------------------------------------------------------------------------------------\n\n#include <windows.h>\n#include <windowsx.h>\n#include <gbuffer.h>\n#include <ddraw.h>\n#include <file.h>\n#include <wwmem.h>\n\n#include <westwood.h>\n#include <main.h>\n#include <vidmode.h>\n#include <mainwind.h>\n#include <monochrm.h>\n#include <movies.h>\n\n\nextern void VQA_Test( char *filename );\n\n//==========================================================================\n// Public data\n//==========================================================================\n\nGraphicBufferClass *Screen_Buffer = NULL;\nint\t\t\t\t\t\tScreenWidth = VIDEO_MODE_WIDTH;\n\nBOOL\tGameInFocus = TRUE;\nvoid Block_Mouse(GraphicBufferClass*){}\nvoid Unblock_Mouse(GraphicBufferClass*){}\n\n\n/***********************************************************************************************\n * WinMain -- Program entry point                                                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Standard Windows startup parameters                                               *\n *                                                                                             *\n * OUTPUT:   wParam of the message queue                                                       *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/15/95 1:28PM ST : Created                                                             *\n *=============================================================================================*/\n\nint WINAPI WinMain (\n\tHandle instance_handle,\n\tHandle prev_instance_handle,\n\tString command_line_string,\n\tint show_window_command )\n{\n\tif (!prev_instance_handle){\n\t\t//\n\t\t// If the program is already running, bail.\n\t\t//\n\t\tif ( prev_instance_handle ) {\n\t\t\treturn( 0 );\n\t\t}\n\n\t\t//\n\t\t// Create the main window.\n\t\t//\n\t\tMain_Window.Create_Main_Window( instance_handle );\n\n\t\t//\n\t\t// Show the window.\n\t\t//\n\t\tMain_Window.Display_Window();\n\n\t\t//\n\t\t// Create the GraphicBufferClass that will be the screen buffer\n\t\t//\n\t\tScreen_Buffer = new GraphicBufferClass ( VIDEO_MODE_WIDTH, VIDEO_MODE_HEIGHT, (GBC_Enum)(GBC_VIDEOMEM | GBC_VISIBLE) );\n\n\t\t//\n\t\t// Initialize Movie system.\n\t\t//\n\t\tInitialize_Movie_System();\n\n\t\tif (*command_line_string){\n\t\t\tVQA_Test(command_line_string);\n\t\t}else{\n\t\t\t//\n\t\t\t// Windows message loop\n\t\t\t//\n\t\t\twhile ( Main_Window.Update_Windows_Messages() ) ;\n\t\t}\n\n\t\t//\n\t\t// Free the Movie system.\n\t\t//\n\t\tFree_Movie_System();\n\n\t\treturn( Main_Window.Get_Message_Queue_wParam() );\n\t}else{\n\t\treturn (-1);\n\t}\n\n}\n\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/MAIN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/**********************************************************************************************\n ***             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              ***\n **********************************************************************************************\n *                                                                                            *\n *                 Project Name : VQAVIEW\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                                            *\n *                    File Name : MAIN.H                                                \t   *\n *                                                                                            *\n *                   Programmer : Mike Grayford                                               *\n *                                                                                            *\n *                   Start Date : November 20, 1995                                          \t*\n *                                                                                            *\n *                  Last Update : November 20, 1995 [MG]                                     \t*\n *                                                                                            *\n *--------------------------------------------------------------------------------------------*\n *                                                                                            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/\n\n//==========================================================================\n// INCLUDES\n//==========================================================================\n\n#include <gbuffer.h>\n\n//==========================================================================\n// PUBLIC DATA\n//==========================================================================\n\nextern GraphicBufferClass *Screen_Buffer;\n\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/MAINWIND.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQAVIEW\t\t\t\t                       *\n *                                                                         *\n *                    File Name : MAINWIND.CPP                             *\n *                                                                         *\n *                   Programmer : Mike Grayford                         \t  *\n *                                                                         *\n *                   Start Date : Nov 15, 1995                             *\n *                                                                         *\n *                  Last Update : Nov 15, 1995   [MG]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <windows.h>\n\n#include <westwood.h>\n#include <mainwind.h>\n#include <vidmode.h>\n#include <wm.h>\n#include <misc.h>\n#include <wwlib.h>\n\n//==========================================================================\n// Private defines\n//==========================================================================\n\n#define APPLICATION_NAME\t\t\"VQAVIEW\"\n#define APPLICATION_TITLE\t\"VQA Movie Viewer\"\n\n\n//==========================================================================\n// Public data\n//==========================================================================\n\nMainWindowClass Main_Window;\n\n//==========================================================================\n// Private functions\n//==========================================================================\n\nlong WINAPI Main_Window_Message_Handler(\n\tWindowHandle window_handle,\n\tunsigned int message,\n\tunsigned int w_param,\n\tlong l_param );\n\n\n/***************************************************************************\n * MainWindowClass::MainWindowClass -- Constructor for MainWindowClass\t  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY: See PVCS log                                                   *\n *=========================================================================*/\nMainWindowClass::MainWindowClass( void )\n{\n\t// Much ado about nothing.\n}\n\n\nvoid MainWindowClass::Create_Main_Window( InstanceHandle instance_handle )\n{\n\tWindowClass window_class;\n\n\t//\n\t// Register the window class.\n\t//\n\twindow_class.style         = CS_OWNDC;\n\twindow_class.lpfnWndProc   = Main_Window_Message_Handler;\n\twindow_class.cbClsExtra    = 0;\n\twindow_class.cbWndExtra    = 0;\n\twindow_class.hInstance     = instance_handle;\n\twindow_class.hIcon         = LoadIcon ( NULL, IDI_APPLICATION );\n\twindow_class.hCursor       = LoadCursor ( NULL, IDC_ARROW );\n\twindow_class.hbrBackground = GetStockObject( BLACK_BRUSH );\n\twindow_class.lpszMenuName  = APPLICATION_NAME;\n\twindow_class.lpszClassName = APPLICATION_NAME;\n\n\tRegisterClass ( &window_class );\n\n\t//\n\t// Create our main window\n\t//\n\tmain_window_handle = CreateWindowEx (\n\t\tWS_EX_TOPMOST,\t\t\t\t\t// extended window info\n\t\tAPPLICATION_NAME,\t\t\t\t// window class name\n\t\tAPPLICATION_TITLE,         // window caption\n//\t\tWS_POPUP | WS_MAXIMIZE,    // window style\n\t\tWS_OVERLAPPED,\t\t\t\t\t// window style\n\t\t0,                         // initial x position\n\t\t0,                         // initial y position\n\t\tVIDEO_MODE_WIDTH,          // initial width\n\t\tVIDEO_MODE_HEIGHT,         // initial height\n\t\tNULL,                      // parent window handle\n\t\tNULL,                      // window menu handle\n\t\tinstance_handle,           // program instance handle\n\t\tNULL );                    // creation parameters\n\n\tMainWindow = main_window_handle;\n\n\tglobal_instance_handle = instance_handle;\n}\n\n\nvoid MainWindowClass::Display_Window( void )\n{\n\t//\n\t// Bring up the window, force a paint, and make sure we are the foreground window.\n\t//\n\tShowWindow( main_window_handle, SW_SHOWMAXIMIZED );\n\tUpdateWindow( main_window_handle );\n\tSetForegroundWindow( main_window_handle );\n\n\t//\n\t// Via direct draw, set the video mode.\n\t//\n\tSet_Video_Mode( main_window_handle, VIDEO_MODE_WIDTH, VIDEO_MODE_HEIGHT, VIDEO_MODE_BITS_PER_PIXEL );\n\n}\n\n\nBOOL MainWindowClass::Update_Windows_Messages( void )\n{\n\tif ( PeekMessage( &message_queue, NULL, 0, 0, PM_NOREMOVE ) ) {\n\t\tif ( GetMessage( &message_queue, NULL, 0, 0 ) ) {\n\t\t\tTranslateMessage( &message_queue );\n\t\t\tDispatchMessage( &message_queue );\n\t\t}\n\t\telse {\n\t\t\treturn( FALSE );\n\t\t}\n\t}\n\n\treturn( TRUE );\n}\n\n\nint MainWindowClass::Get_Message_Queue_wParam( void )\n{\n\treturn( message_queue.wParam );\n}\n\n\nWindowHandle MainWindowClass::Get_Window_Handle( void )\n{\n\treturn( main_window_handle );\n}\n\n\nlong WINAPI Main_Window_Message_Handler(\n\tWindowHandle window_handle,\n\tunsigned int message,\n\tunsigned int w_param,\n\tlong l_param )\n{\n\tswitch ( message ) {\n\n\t\tcase WM_COMMAND:\n\t\t\treturn( WM_Command_Func( window_handle, message, w_param, l_param ) );\n\n\t\tcase WM_TIMER:\n\t\t\tbreak;\n\n\t\tcase WM_ACTIVATEAPP:\n\t\t\tWM_ActivateApp_Func( window_handle, message, w_param, l_param );\n\t\t\tbreak;\n\n\t\tcase WM_DESTROY:\n\t\t\tWM_Destroy_Func( window_handle, message, w_param, l_param );\n\t\t\treturn( 0 );\n\t}\n\n\treturn( DefWindowProc( window_handle, message, w_param, l_param ) );\n}\n\n\nInstanceHandle MainWindowClass::Get_Instance_Handle( void )\n{\n\treturn( global_instance_handle );\n}\n\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/MAINWIND.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQAVIEW\t\t\t\t                       *\n *                                                                         *\n *                    File Name : MAINWIND.H                               *\n *                                                                         *\n *                   Programmer : Michael Grayford                         *\n *                                                                         *\n *                   Start Date : Nov 15, 1995                             *\n *                                                                         *\n *                  Last Update : Nov 15, 1995   [MG]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n//==========================================================================\n// Public classes\n//==========================================================================\n\nclass MainWindowClass {\n\tpublic:\n\n\t\t//==========================================================================\n\t\t// Public functions\n\t\t//==========================================================================\n\n\t\tMainWindowClass( void );\n\t\tvoid Create_Main_Window( InstanceHandle instance_handle );\n\t\tWindowHandle Get_Window_Handle( void );\n\t\tvoid Display_Window( void );\n\t\tBOOL Update_Windows_Messages( void );\n\t\tint Get_Message_Queue_wParam( void );\n\t\tInstanceHandle Get_Instance_Handle( void );\n\n\tprivate:\n\n\t\t//==========================================================================\n\t\t// Private data\n\t\t//==========================================================================\n\n\t\tWindowHandle\tmain_window_handle;\n\t\tInstanceHandle\tglobal_instance_handle;\n\t\tMessageQueue\tmessage_queue;\n\n\t\t//==========================================================================\n\t\t// Private functions\n\t\t//==========================================================================\n\n}; /* VQAClass */\n\n\n//==========================================================================\n// Public data\n//==========================================================================\n\nextern MainWindowClass Main_Window;\n\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Blade Runner\t\t\t\t\t\t\t   \t\t *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Mike Grayford\t\t\t   \t\t\t\t\t *\n#*                                                                         *\n#*                   Start Date : Nov 14, 1995  \t                   \t\t *\n#*                                                                         *\n#*                  Last Update : \t\t\t                   \t\t\t\t\t *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   \t\t\t\t\t\t\t\t *\n#* WIN32LIB\t= the root of the WW library\t\t\t   \t\t\t\t\t\t \t *\n#* WIN32VCS\t= root directory for WW library version control archive\t \t *\n#* COMPILER\t= your Watcom installation path\t\t\t\t   \t\t\t\t \t *\n#*                                                                         *\n#*\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t *\n#* Required changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t *\n#* PROJ_NAME\t= name of the executable program you're building \t   \t\t *\n#* PROJ_LIBS\t= Westwood libraries to link your EXE to \t           \t\t\t *\n#* OBJECTS\t= list of objects in your current working directory\t   \t\t *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   \t\t\t\t\t\t\t\t *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   \t\t\t\t *\n#* .xxx:\t= full pathname where various file types live\t\t   \t\t\t *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WIN32LIB\n!error WIN32LIB Environment var not configured.\n!endif\n\n!ifndef %WIN32VCS\n!error WIN32VCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM\n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n#---------------------------------------------------------------------------\n# PROJ_NAME = library name\n# PROJ_DIR = directory containing source & objects\n#---------------------------------------------------------------------------\nPROJ_NAME\t= VQAVIEW\nPROJ_DIR\t= $(%BLADE)\\VQA\\VQAVIEW\nLIB_DIR\t\t= $(%WIN32LIB)\\LIB\nVQA_LIB_DIR = $(%BLADE)\\VQA\\LIB\n\n!include $(%WIN32LIB)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS =\t&\n\tgametime.obj\t&\n\tmain.obj\t\t\t&\n\tmainwind.obj\t&\n\tmonochrm.obj\t&\n\tmovies.obj\t\t&\n\tpal.obj\t\t\t&\n\tvq.obj\t\t\t&\n\twm.obj\t\t&\n\tinterpal.obj\n\nRESOURCES = &\n\tdialogs.res\t\t&\n\tmenus.res\n\nPROJ_LIBS = &\n\tdrawbuff.lib\t&\n\tmem.lib\t\t\t&\n\tmisc.lib\t\t\t&\n\trawfile.lib\n\nVQA_LIBS = &\n\tvqa32wp.lib\t\t&\n\tvqm32wp.lib\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n\n.EXTENSIONS: .res .rc\n\n.asm:\t$(PROJ_DIR)\n.c:   \t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:   \t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WIN32LIB)\\lib;$(VQA_LIB_DIR)\n.exe:\t$(PROJ_DIR)\n.rc:\t\t$(PROJ_DIR)\n.res:\t$(PROJ_DIR)\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm\nRC_CMD\t\t= wrc\n\n#---------------------------------------------------------------------------\n# Include & library paths\n# If LIB & INCLUDE are already defined, they are used in addition to the\n# WWLIB32 lib & include; otherwise, they're constructed from\n# BCDIR\n#---------------------------------------------------------------------------\n\nLIBPATH\t  \t= $(%WIN32LIB)\\LIB;$(%WATCOM)\\LIB386\\NT;$(BLADE)\\VQA\\LIB\nINCLUDEPATH\t= $(PROJ_DIR);$(%WIN32LIB)\\INCLUDE;$(%WATCOM)\\H;$(PROJ_DIR)\\..;$(PROJ_DIR)\\..\\VQA32\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler:\n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WIN32LIB)\\project.cfg .AUTODEPEND\n\t$(CPP_CMD) -db $(CC_CFG) /i=$(INCLUDEPATH) $<\n\n.asm.obj: $(%WIN32LIB)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n.rc.res:\n\t$(RC_CMD) /r $<\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(PROJ_NAME).exe\n\n#---------------------------------------------------------------------------\n# Build the EXE\n#---------------------------------------------------------------------------\n$(PROJ_NAME).exe: $(OBJECTS) $(PROJ_NAME).lnk $(PROJ_LIBS) $(VQA_LIBS) $(RESOURCES)\n\t $(LINK_CMD) $(LINK_CFG) name $^@ @$(PROJ_NAME).lnk\n\t for %index in ($(RESOURCES)) do $(RC_CMD) -t %index $(PROJ_NAME).exe\n\n\n#$(PROJ_LIBS):\n#\techo updating base library $^@\n#\tcd ..\n#\twmake\n#\tcd $(PROJ_DIR)\n\n\n$(PROJ_NAME).lnk : $(OBJECTS) makefile\n       %create $^@\n       for %index in ($(OBJECTS))  do %append $^@ file %index\n       for %index in ($(PROJ_LIBS)) do %append $^@ library $(LIB_DIR)\\%index\n\t\t\t%append $^@ library $(LIB_DIR)\\ddraw.lib\n\t\t\t%append $^@ library $(LIB_DIR)\\dsound.lib\n       for %index in ($(VQA_LIBS)) do %append $^@ library $(VQA_LIB_DIR)\\%index\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/MENUS.RC",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQAVIEW                                  *\n *                                                                         *\n *                    File Name : MENUS.RC                                 *\n *                                                                         *\n *                   Programmer : Mike Grayford                            *\n *                                                                         *\n *                   Start Date : November 22, 1995                        *\n *                                                                         *\n *                  Last Update : Nov 22, 1995   [MG]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include \"menus.rh\"\n\nVQAVIEW MENU\nBEGIN\n\tPOPUP \"File\"\n\tBEGIN\n \t\tMENUITEM \"&Open movie...\",   \t\tMENU_OPEN\n\t\tMENUITEM SEPARATOR\n\t\tMENUITEM \"E&xit\",\t\t\tMENU_EXIT\n\tEND\n\n\tPOPUP \"Options\"\n\tBEGIN\n\t\tMENUITEM \"Set Movie Frame &Rate\",\tMENU_SET_MOVIE_FRAME_RATE\n\tEND\nEND\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/MENUS.RH",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Virtual Monopoly                         *\n *                                                                         *\n *                    File Name : MENUS.RH                                 *\n *                                                                         *\n *                   Programmer : Mike Grayford                            *\n *                                                                         *\n *                   Start Date : November 22, 1995                        *\n *                                                                         *\n *                  Last Update : Nov 22, 1995   [MG]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n/* MENU BAR */\n#define MENU_BAR_FILE\t\t   \t0\n\n/* FILE */\n#define MENU_OPEN      \t\t\t100\n#define MENU_EXIT      \t\t\t110\n\n/* OPTIONS */\n#define MENU_SET_MOVIE_FRAME_RATE\t200\n\n\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/MONOCHRM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQAVIEW                                  *\n *                                                                         *\n *                    File Name : MONOCHRM.CPP                             *\n *                                                                         *\n *                   Programmer : Michael Legg                             *\n *                                                                         *\n *                   Start Date : May 10, 1995                             *\n *                                                                         *\n *                  Last Update : May 30, 1995   [ML]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *                                                                         *\n *  These are not our functions, but Microsoft's from DBWIN.EXE            *\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <mem.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <string.h>\n#include <monochrm.h>\n#include <westwood.h>\n\ntypedef struct\n{\n\t char ch;\n\t char attr;\n} CA;\n\n#define CCOLMAX         80\n#define CROWMAX       \t25\n\n#define ESC             27\n#define BELL            7\n#define DEFATTR       \t0x07\n#define CA_SPACE        ((DEFATTR << 8) | ' ')\n\n// row+1 = DBWIN\n#define PCA(row, col)   (0xB0000 + ( (((row+0)*CCOLMAX)+col) * sizeof(CA)))\n\nstatic void Monochrome_Output( char *string );\nstatic void CACopy( CA *pcaDst, CA *pcaSrc, int cca );\nstatic void CAFill( CA *pcaDst, int cca, int ca );\n\nint rowCur = 0;\nint colCur = 0;\n\n/***************************************************************************\n * DEBUG_PRINTF - works like printf, with limit of 10 variable args        *\n *                                                                         *\n * INPUT: same as printf                                                   *\n *                                                                         *\n * OUTPUT: a message on the monochrome monitor display                     *\n *                                                                         *\n * WARNINGS: try to end messages with \\r\\n!                                *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\nvoid Debug_Printf( char *format_string, ... )\n{\n\tva_list ap;\n\tint arg[ 10 ];\n\tchar output_string[ 255 ];\n\n\tva_start( ap, format_string );\n\targ[ 0 ] = va_arg( ap, int );\n\targ[ 1 ] = va_arg( ap, int );\n\targ[ 2 ] = va_arg( ap, int );\n\targ[ 3 ] = va_arg( ap, int );\n\targ[ 4 ] = va_arg( ap, int );\n\targ[ 5 ] = va_arg( ap, int );\n\targ[ 6 ] = va_arg( ap, int );\n\targ[ 7 ] = va_arg( ap, int );\n\targ[ 8 ] = va_arg( ap, int );\n\targ[ 9 ] = va_arg( ap, int );\n\tva_end( ap );\n\n\tsprintf( (char *) output_string,\n\t\t\t\t(char *) format_string,\n\t\t\t\targ[ 0 ],\n\t\t\t\targ[ 1 ],\n\t\t\t\targ[ 2 ],\n\t\t\t\targ[ 3 ],\n\t\t\t\targ[ 4 ],\n\t\t\t\targ[ 5 ],\n\t\t\t\targ[ 6 ],\n\t\t\t\targ[ 7 ],\n\t\t\t\targ[ 8 ],\n\t\t\t\targ[ 9 ] );\n\n\tDebug_Mono_Message( (char *) output_string );\n}\n\n/***************************************************************************\n * DEBUG_MONO_MESSAGE -- Post a line to the monochrome monitor             *\n *                                                                         *\n * INPUT: the message to print                                             *\n *                                                                         *\n * OUTPUT: a message on the monochrome monitor display                     *\n *                                                                         *\n * WARNINGS: try to end messages with \\r\\n!                                *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\nvoid Debug_Mono_Message( char *message )\n{\n\tchar *temp_string;\n\tchar *temp_null_position;\n\tchar temp_char;\n\tint length_left;\n\n\tlength_left = strlen( message );\n\ttemp_null_position = message;\n\twhile ( length_left > CCOLMAX ) {\n\t\ttemp_string = temp_null_position;\n\t\ttemp_null_position += CCOLMAX;\n\t\ttemp_char = *temp_null_position;\n\t\ttemp_null_position[ 0 ] = '\\0';\n\n\t\tMonochrome_Output( temp_string );\n\n\t\t*temp_null_position = temp_char;\n\t\tlength_left -= CCOLMAX;\n\t}\n\ttemp_string = temp_null_position;\n\n\tMonochrome_Output( temp_string );\n}\n\nstatic void Monochrome_Output( char *string )\n{\n\t CA *pca;\n\t char ch;\n\t static int _initialized = FALSE;\n\n\t pca = (CA *) PCA(rowCur, colCur);\n\n\t if ( ! _initialized ) {\n\t\t  CAFill( (CA *) PCA(0, 0),\n\t\t\t\t\t (CCOLMAX * CROWMAX),\n\t\t\t\t\t CA_SPACE );\n\t\t  colCur = 0;\n\t\t  rowCur = 0;\n\t\t  _initialized = TRUE;\n\t }\n\n\t while ( TRUE ) {\n\n\t\tch = *string++;\n\t\tif ( ! ch ) {\n\t\t\tbreak;\n\t\t}\n\n\t\tswitch (ch) {\n\n\t\t  case '\\b':\n\t\t\t\tif (colCur > 0)\n\t\t\t\t{\n\t\t\t\t\t colCur--;\n\t\t\t\t\t pca--;\n\t\t\t\t\t pca->ch = ' ';\n\t\t\t\t\t pca->attr = DEFATTR;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t  case BELL:\n//\t\t\t\tMessageBeep(0);\n\t\t\t\tbreak;\n\n\t\t  case '\\t':\n\t\t\t\tpca    += 8 - colCur % 8;\n\t\t\t\tcolCur += 8 - colCur % 8;\n\t\t\t\tbreak;\n\n\t\t  case '\\r':\n\t\t\t\tcolCur = 0;\n\t\t\t\tpca = (CA *) PCA(rowCur, colCur);\n\t\t\t\tbreak;\n\n\t\t  default:\n\t\t\t\tpca->ch = ch;\n\t\t\t\tpca->attr = DEFATTR;\n\t\t\t\tpca++;\n\t\t\t\tcolCur++;\n\n\t\t\t\tif (colCur < CCOLMAX)\n\t\t\t\t\t break;\n\n\t\t\t\t// fall through to handle LF\n\n\t\t  case '\\n':\n\t\t\t\tcolCur = 0;\n\t\t\t\trowCur++;\n\n\t\t\t\tif (rowCur >= CROWMAX)\n\t\t\t\t{\n\t\t\t\t\t CACopy( (CA *) PCA(0, 0), (CA *) PCA(1, 0), CCOLMAX * (CROWMAX - 1));\n\t\t\t\t\t CAFill( (CA *) PCA(CROWMAX - 1, 0), CCOLMAX, CA_SPACE);\n\t\t\t\t\t rowCur = CROWMAX - 1;\n\t\t\t\t}\n\n\t\t\t\tpca = (CA *) PCA(rowCur, colCur);\n\t\t\t\tbreak;\n\n\t\t  case ESC:\n\t\t\t\t//\n\t\t\t\t// ANSI clear screen escape\n\t\t\t\t//\n\t\t\t\tif (string[1] == '[' && string[2] == '2' && string[3] == 'J')\n\t\t\t\t{\n\t\t\t\t\t CAFill( (CA *)PCA(0,0), CCOLMAX * CROWMAX, CA_SPACE);\n\t\t\t\t\t rowCur = colCur = 0;\n\t\t\t\t\t string += 3;\n\t\t\t\t}\n\t\t  }\n\t }\n}\n\nstatic void CACopy( CA *pcaDst, CA *pcaSrc, int cca )\n{\n\tint i;\n\n\tfor ( i = 0; i < cca; i ++ ) {\n\t\t*pcaDst = *pcaSrc;\n\t\tpcaDst ++;\n\t\tpcaSrc ++;\n\t}\n}\n\nstatic void CAFill( CA *pcaDst, int cca, int ca )\n{\n\tint i;\n\n\tfor ( i = 0; i < cca; i ++ ) {\n\t\tmemcpy( pcaDst, &ca, sizeof( int ) );\n\t\tpcaDst ++;\n\t}\n}\n"
  },
  {
    "path": "WINVQ/VQAVIEW/MONOCHRM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQAVIEW                                  *\n *                                                                         *\n *                    File Name : MONOCHRM.H                               *\n *                                                                         *\n *                   Programmer : Michael Grayford                         *\n *                                                                         *\n *                   Start Date :                                          *\n *                                                                         *\n *                  Last Update : Nov 24, 1995   [ML]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MONOCHRM_H\n#define MONOCHRM_H\n\n//==========================================================================\n// PUBLIC FUNCTIONS\n//==========================================================================\n\nvoid Debug_Printf( char *format_string, ... );\nvoid Debug_Mono_Message( char *message );\n\n#endif\n"
  },
  {
    "path": "WINVQ/VQAVIEW/MOVIES.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQAVIEW                                  *\n *                                                                         *\n *                    File Name : MOVIES.CPP                               *\n *                                                                         *\n *                   Programmer : Michael Grayford                         *\n *                                                                         *\n *                   Start Date :                                          *\n *                                                                         *\n *                  Last Update : Nov 29, 1995   [MG]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n//==========================================================================\n// INCLUDES\n//==========================================================================\n\n#include <windows.h>\n#include <westwood.h>\n#include <vq.h>\n#include <movies.h>\n#include <mainwind.h>\n#include <main.h>\n#include <pal.h>\n\n//==========================================================================\n// PRIVATE FUNCTIONS\n//==========================================================================\n\nvoid VQA_Test( char *filename );\nvoid Create_Palette_Interpolation_Table( void );\nvoid Interpolate_2X_Scale( GraphicBufferClass *source, GraphicBufferClass *dest );\n\n\n//==========================================================================\n// PRIVATE GLOBALS\n//==========================================================================\n\nextern \"C\"{\n\textern unsigned char *InterpolationPalette;\n\textern unsigned char Palette_Interpolation_Table[SIZE_OF_PALETTE][SIZE_OF_PALETTE];\n\textern void __cdecl Asm_Create_Palette_Interpolation_Table(void);\n\textern void __cdecl Asm_Interpolate (unsigned char* src_ptr ,\n\t\t\t\t\t\t \t\t\t\t\t\t\tunsigned char* dest_ptr ,\n\t\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tlines ,\n\t\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tsrc_width ,\n\t\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tdest_width);\n\n}\nunsigned char Palette_Interpolation_Table[ SIZE_OF_PALETTE ][ SIZE_OF_PALETTE ];\nunsigned char *InterpolationPalette;\n\nVQAClass\t\t\t*TestVqa;\n\n#if( ! DRAW_TO_VIDEO )\n\tGraphicBufferClass *Draw_Page = NULL;\n\tGraphicBufferClass *Back_Page = NULL;\n\tGraphicBufferClass *Hid_Page = NULL;\n#endif\n\n\n\n/***************************************************************************\n * Initialize_Movie_System - Allocate memory needed for caching and any\t  *\n *\t\tpermanent Movie data.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * INPUT: NONE\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT: int - an error value                                            *\n *                                                                         *\n * WARNINGS: Yellow alert!                                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/29/1995  MG : Created.                                             *\n *=========================================================================*/\nint Initialize_Movie_System( void )\n{\n\t#if( ! DRAW_TO_VIDEO )\n\t\t//\n\t\t// Set up the graphic pages:\n\t\t// Draw_Page - the page that the VQA library draws to. (Normal RAM)\n\t\t// Back_Page - the page that the drawn image is scaled to. (Normal RAM)\n\t\t// Hid_Page - the page in video RAM that the scaled image is copied to before copy to screen.\n\t\t//\n\t\tDraw_Page = new GraphicBufferClass ( MOVIE_WIDTH, MOVIE_HEIGHT );\n\t\tBack_Page = new GraphicBufferClass ( VIDEO_MODE_WIDTH, VIDEO_MODE_HEIGHT );\n\t\tHid_Page = new GraphicBufferClass ( VIDEO_MODE_WIDTH, VIDEO_MODE_HEIGHT, (GBC_Enum)(GBC_VIDEOMEM) );\n\t#endif\n\n\t//\n\t// Okay, we're cool.\n\t//\n\treturn( VQA_INIT_NO_ERROR );\n}\n\n/***************************************************************************\n * Free_Movie_System - Free up memory used by Movie cache system and any   *\n *\t\tpermanent Movie data.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * INPUT: NONE\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT: NONE                                                            *\n *                                                                         *\n * WARNINGS: Red alert!                                                    *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/29/1995  MG : Created.                                             *\n *=========================================================================*/\nvoid Free_Movie_System( void )\n{\n\t#if( ! DRAW_TO_VIDEO )\n\t\tif ( Draw_Page ) {\n\t\t\tdelete( Draw_Page );\n\t\t}\n\t\tif ( Back_Page ) {\n\t\t\tdelete( Back_Page );\n\t\t}\n\t\tif ( Hid_Page ) {\n\t\t\tdelete( Hid_Page );\n\t\t}\n\t\tDraw_Page = NULL;\n\t\tBack_Page = NULL;\n\t\tHid_Page = NULL;\n\t#endif\n\n\treturn;\n}\n\n\n/***************************************************************************\n * Choose_Movie - Brings up choice of VQA files.\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * INPUT: NONE                                                             *\n *                                                                         *\n * OUTPUT: NONE                                                            *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/15/1995  MG : Created.                                             *\n *=========================================================================*/\nvoid Choose_Movie( WindowHandle window_handle )\n{\n\tint\ti;\n\tchar\ttemp_file[_MAX_FNAME + _MAX_EXT];\n\tstatic OPENFILENAME open_file_dlg;\n\tstatic char path_filename[ _MAX_PATH*500 ];\n\tstatic char filename[ _MAX_FNAME + _MAX_EXT ];\n\tstatic char *filters[] = {\n\t\t\"VQA files (*.VQA)\",  \"*.vqa\",\n\t\t\"All Files\", \"*.*\",\n\t\t\"\" } ;\n\n\tfilename[0]=0;\n\tmemset (&path_filename[0],0,_MAX_PATH*500);\n\n\topen_file_dlg.lStructSize \t\t\t= sizeof( OPENFILENAME );\n\topen_file_dlg.hwndOwner \t\t\t= window_handle;\n\topen_file_dlg.hInstance \t\t\t= NULL;\n\topen_file_dlg.lpstrFilter \t\t\t= filters[ 0 ];\n\topen_file_dlg.lpstrCustomFilter \t= NULL;\n\topen_file_dlg.nMaxCustFilter \t\t= 0;\n\topen_file_dlg.nFilterIndex \t\t= 1;\n\topen_file_dlg.lpstrFile \t\t\t= path_filename;\n\topen_file_dlg.nMaxFile \t\t\t\t= _MAX_PATH*500;\n\topen_file_dlg.lpstrFileTitle \t\t= filename;\n\topen_file_dlg.nMaxFileTitle \t\t= _MAX_FNAME + _MAX_EXT;\n\topen_file_dlg.lpstrInitialDir \t= NULL;\n\topen_file_dlg.lpstrTitle \t\t\t= \"Choose a VQA to run\";\n\topen_file_dlg.Flags \t\t\t\t\t= OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT;\n\topen_file_dlg.nFileOffset \t\t\t= 0;\n\topen_file_dlg.nFileExtension \t\t= 0;\n\topen_file_dlg.lpstrDefExt\t\t\t= \"vqa\";\n\topen_file_dlg.lCustData\t\t\t\t= 0l;\n\topen_file_dlg.lpfnHook\t\t\t\t= NULL;\n\topen_file_dlg.lpTemplateName\t\t= NULL;\n\n\tif ( GetOpenFileName( &open_file_dlg ) ) {\n\n\t\tif ( filename[ 0 ] != '\\0' ) {\n\t\t\tVQA_Test( filename );\n\t\t} else {\n\n\t\t\tint\tlast_file=0;\n\t\t\tfor (i=0 ; i<open_file_dlg.nMaxFile ; i++){\n\t\t\t\tif (path_filename[i]==0 || path_filename[i]==' '){\n\n\t\t\t\t\tif (!(i-last_file)) break;\n\t\t\t\t\tmemcpy( &temp_file[0] , &path_filename[last_file] , i-last_file);\n\t\t\t\t\ttemp_file[i-last_file]=0;\n\t\t\t\t\tif (last_file){\n\t\t\t\t\t\tVQA_Test(temp_file);\n\t\t\t\t\t}else{\n\t\t\t\t\t\tSetCurrentDirectory(temp_file);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (path_filename[i]==0){\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}else{\n\t\t\t\t\t\tlast_file = i+1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n   }\n}\n\n\n/***************************************************************************\n * VQA_Test - plays a generic VQA                                          *\n *                                                                         *\n * INPUT: char *filename                                                   *\n *                                                                         *\n * OUTPUT: NONE                                                            *\n *                                                                         *\n * WARNINGS: Red alert!                                                    *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1995  MG : Created.                                             *\n *=========================================================================*/\nvoid VQA_Test( char *filename )\n{\n\tchar\t\t\t\t*temp_ptr;\n\tint\t\t\t\ti;\n\tchar\t\t\t\t*draw_surface_ptr;\n\tGraphicBufferClass\t*draw_buffer_ptr;\n\tlong\t\t\t\t(*callback_function_ptr) (unsigned char *, long);\n\n\t//\n\t// Handle windows messages so that any repaint occurs before we start\n\t// playing the movie.\n\t//\n\tMain_Window.Update_Windows_Messages();\n\n\t// Strip the extension off the filename.\n\tfilename = strtok( filename, \".\" );\n\n\t#if( DRAW_TO_VIDEO )\n\t\tdraw_buffer_ptr = Screen_Buffer;\n\t\tcallback_function_ptr = Draw_To_Video_Callback;\n\t#else\n\t\tdraw_buffer_ptr = Draw_Page;\n\t\tcallback_function_ptr = Draw_To_Buffer_Callback;\n\t#endif\n\n\t//\n\t// Get the draw buffer.\n\t//\n\tdraw_buffer_ptr->Lock();\n\tdraw_surface_ptr = (char *) draw_buffer_ptr->Get_Offset();\n\tdraw_buffer_ptr->Unlock();\n\n\t//\n\t// Clear the drawing surface with color 0.\n\t//\n\tdraw_buffer_ptr->Lock();\n\ttemp_ptr = draw_surface_ptr;\n\tfor ( i = 0; i < (MOVIE_WIDTH * MOVIE_HEIGHT); i ++ ) {\n\t\t*temp_ptr = COLOR_BLACK;\n\t\ttemp_ptr ++;\n\t}\n\tdraw_buffer_ptr->Unlock();\n\n\t//\n\t// Create a new VQA object.\n\t//\n\tTestVqa = new VQAClass(\n\t\tfilename,\n\t\tdraw_surface_ptr,\n\t\tFROM_DISK,\n\t\tcallback_function_ptr );\n\n\t//\n\t// Allocate the buffers for the VQA.\n\t//\n\tif ( TestVqa->Open_And_Load_Buffers() ) {\n\n\t\tTestVqa->Read_Palettes();\n\n\t\t//\n\t\t// Play the VQA.\n\t\t//\n\t\tTestVqa->Play_VQA( PLAY_ALL_FRAMES );\n\n\t\t//\n\t\t// Close the VQA.\n\t\t//\n\t\tTestVqa->Close_And_Free_VQA();\n\n\t\tTestVqa->Write_Palettes();\n\n\t\tdelete TestVqa;\n\t}\n}\n\n\n/***************************************************************************\n * DRAW_TO_VIDEO_CALLBACK -- Callback after a VQA frame is drawn to video  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1995  MG : Created.                                             *\n *=========================================================================*/\nlong Draw_To_Video_Callback( unsigned char *buffer, long frame_number )\n{\n\treturn( 0 );\n}\n\n\n\n/***************************************************************************\n * DRAW_TO_BUFFER_CALLBACK -- Copies the drawn frame to the screen         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1995  MG : Created.                                             *\n *=========================================================================*/\nlong Draw_To_Buffer_Callback( unsigned char *buffer, long frame_number )\n{\n\t//\n\t// Frame was skipped, bail.\n\t//\n\tif ( buffer == NULL ) {\n\t\treturn( 0 );\n\t}\n\n\t#if( ! DRAW_TO_VIDEO )\n\n\t\t//\n\t\t// Do the cool interpolated, interlaced scale.\n\t\t//\n\t\t#if( 1 )\n\t\t\tInterpolate_2X_Scale( Draw_Page, Back_Page );\n\t\t\tBack_Page->Blit( *Screen_Buffer, 0, 0, 0, 100, 640, 314 );\n\t\t#endif\n\n\t\t//\n\t\t// Draw 320x200 to Normal RAM, scale to Screen.\n\t\t//\n\t\t#if( 0 )\n\t\t\tDraw_Page->Scale( *Screen_Buffer );\n\t\t#endif\n\n\t\t//\n\t\t// Draw 320x200 to Normal RAM, scale to Normal RAM, Blit to Hid, Blit to Screen.\n\t\t//\n\t\t#if( 0 )\n\t\t\tDraw_Page->Scale( *Back_Page );\n\t\t\tBack_Page->Blit( *Hid_Page );\n\t\t\tHid_Page->Blit( *Screen_Buffer );\n\t\t#endif\n\n\t\t//\n\t\t// Draw 320x200 to Normal RAM, scale to Normal RAM, Blit to Screen.\n\t\t//\n\t\t#if( 0 )\n\t\t\tDraw_Page->Scale( *Back_Page );\n\t\t\tBack_Page->Blit( *Screen_Buffer );\n\t\t#endif\n\n\t\t//\n\t\t// Draw 320x200 to Normal RAM, Blit to Screen.\n\t\t//\n\t\t#if( 0 )\n\t\t\tDraw_Page->Blit( *Screen_Buffer );\n\t\t#endif\n\n\t#endif\n\n\n\treturn( 0 );\n}\n\n\n\n/***************************************************************************\n * CREATE_PALETTE_INTERPOLATION_TABLE                                      *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/06/1995  MG : Created.                                             *\n *=========================================================================*/\nvoid Create_Palette_Interpolation_Table( void )\n{\n\n//\tInterpolationPalette = (unsigned char*)CurrentPalette;\n//\tAsm_Create_Palette_Interpolation_Table();\n//#if 0\n\tint \t\t\t\ti;\n\tint \t\t\t\tj;\n\tint \t\t\t\tp;\n\tunsigned char\t*first_palette_ptr;\n\tunsigned char\t*second_palette_ptr;\n\tunsigned char\t*match_pal_ptr;\n\tint\t\t\t\tfirst_r;\n\tint\t\t\t\tfirst_g;\n\tint\t\t\t\tfirst_b;\n\tint\t\t\t\tsecond_r;\n\tint\t\t\t\tsecond_g;\n\tint\t\t\t\tsecond_b;\n\tint\t\t\t\tdiff_r;\n\tint\t\t\t\tdiff_g;\n\tint\t\t\t\tdiff_b;\n\tint\t\t\t\tdest_r;\n\tint\t\t\t\tdest_g;\n\tint\t\t\t\tdest_b;\n\tint \t\t\t\tdistance;\n\tint \t\t\t\tclosest_distance;\n\tint \t\t\t\tindex_of_closest_color;\n\n\t//\n\t// Create an interpolation table for the current palette.\n\t//\n\tfirst_palette_ptr = (unsigned char *) CurrentPalette;\n\tfor ( i = 0; i < SIZE_OF_PALETTE; i ++ ) {\n\n\t\t//\n\t\t// Get the first palette entry's RGB.\n\t\t//\n\t\tfirst_r = *first_palette_ptr;\n\t\tfirst_palette_ptr ++;\n\t\tfirst_g = *first_palette_ptr;\n\t\tfirst_palette_ptr ++;\n\t\tfirst_b = *first_palette_ptr;\n\t\tfirst_palette_ptr ++;\n\n\t\tsecond_palette_ptr = (unsigned char *) CurrentPalette;\n\t\tfor  ( j = 0; j < SIZE_OF_PALETTE; j ++ ) {\n\t\t\t//\n\t\t\t// Get the second palette entry's RGB.\n\t\t\t//\n\t\t\tsecond_r = *second_palette_ptr;\n\t\t\tsecond_palette_ptr ++;\n\t\t\tsecond_g = *second_palette_ptr;\n\t\t\tsecond_palette_ptr ++;\n\t\t\tsecond_b = *second_palette_ptr;\n\t\t\tsecond_palette_ptr ++;\n\n\t\t\t//\n\t\t\t// Now calculate the RGB halfway between the first and second colors.\n\t\t\t//\n\t\t\tdest_r = ( first_r + second_r ) >> 1;\n\t\t\tdest_g = ( first_g + second_g ) >> 1;\n\t\t\tdest_b = ( first_b + second_b ) >> 1;\n\n\t\t\t//\n\t\t\t// Now find the color in the palette that most closely matches the interpolated color.\n\t\t\t//\n\t\t\tindex_of_closest_color = 0;\n//\t\t\tclosest_distance = (256 * 256) * 3;\n\t\t\tclosest_distance = 500000;\n\t\t\tmatch_pal_ptr = (unsigned char *) CurrentPalette;\n\t\t\tfor ( p = 0; p < SIZE_OF_PALETTE; p ++ ) {\n\t\t\t\tdiff_r = ( ((int) (*match_pal_ptr)) - dest_r );\n\t\t\t\tmatch_pal_ptr ++;\n\t\t\t\tdiff_g = ( ((int) (*match_pal_ptr)) - dest_g );\n\t\t\t\tmatch_pal_ptr ++;\n\t\t\t\tdiff_b = ( ((int) (*match_pal_ptr)) - dest_b );\n\t\t\t\tmatch_pal_ptr ++;\n\n\t\t\t\tdistance = ( diff_r * diff_r ) + ( diff_g * diff_g ) + ( diff_b * diff_b );\n\t\t\t\tif ( distance < closest_distance ) {\n\t\t\t\t\tclosest_distance = distance;\n\t\t\t\t\tindex_of_closest_color = p;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tPalette_Interpolation_Table[ i ][ j ] = (unsigned char) index_of_closest_color;\n\t\t}\n\t}\n\n\treturn;\n//#endif\n}\n\n\n\n\n#if( 1 )\n/***************************************************************************\n * INTERPOLATE_2X_SCALE                                                    *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/06/1995  MG : Created.                                             *\n *=========================================================================*/\nvoid Interpolate_2X_Scale( GraphicBufferClass *source, GraphicBufferClass *dest)\n{\n\tunsigned char\t*src_ptr;\n\tunsigned char\t*dest_ptr;\n\tunsigned char\t*last_dest_ptr;\n\tunsigned char\t*end_of_source;\n\tint\tsrc_width;\n\tint\tdest_width;\n//\tint\twidth_counter;\n\tBOOL\tsource_locked = FALSE;\n\tBOOL\tdest_locked = FALSE;\n\n\t/*\n\t** Lock video surfaces if requred\n\t*/\n\tif (source->Get_IsDirectDraw()){\n\t\tif (!source->Lock()) return;\n\t\tsource_locked = TRUE;\n\t}\n\tif (dest->Get_IsDirectDraw()){\n\t\tif (!dest->Lock()) {\n\t\t\tif (source_locked){\n\t\t\t\tsource->Unlock();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tdest_locked = TRUE;\n\t}\n\n\t//\n\t// Get pointers to the source and destination buffers.\n\t//\n\tsrc_ptr = (unsigned char *) source->Get_Offset();\n\tdest_ptr = (unsigned char *) dest->Get_Offset();\n\tend_of_source = src_ptr + ( source->Get_Width() * source->Get_Height() );\n\n\t//\n\t// Get width of source and dest buffers.\n\t//\n\tsrc_width = source->Get_Width();\n\tdest_width = 2*(dest->Get_Width() + dest->Get_XAdd() + dest->Get_Pitch());\n\tlast_dest_ptr = dest_ptr;\n\n\tAsm_Interpolate ( src_ptr , dest_ptr , source->Get_Height() , src_width , dest_width);\n\n\tif (source_locked) source->Unlock();\n\tif (dest_locked) dest->Unlock();\n\n\treturn;\n}\n#endif\n\n\n\n\n#if( 0 )\n/***************************************************************************\n * INTERPOLATE_2X_SCALE                                                    *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/06/1995  MG : Created.                                             *\n *=========================================================================*/\nvoid Interpolate_2X_Scale( GraphicBufferClass *source, GraphicBufferClass *dest )\n{\n\tunsigned char\t*src_ptr;\n\tunsigned char\t*dest_ptr;\n\tunsigned char\t*end_of_source;\n\tint\tsrc_width;\n\tint\tdest_width;\n\tint\twidth_counter;\n\n\t//\n\t// Get pointers to the source and destination buffers.\n\t//\n\tsrc_ptr = (unsigned char *) source->Get_Offset();\n\tdest_ptr = (unsigned char *) dest->Get_Offset();\n\tend_of_source = src_ptr + ( source->Get_Width() * source->Get_Height() );\n\n\t//\n\t// Get width of source and dest buffers.\n\t//\n\tsrc_width = source->Get_Width();\n\tdest_width = dest->Get_Width();\n\n\t//\n\t// Copy over the first pixel (upper left).\n\t//\n\t*dest_ptr = *src_ptr;\n\tsrc_ptr ++;\n\tdest_ptr ++;\n\n\t//\n\t// Scale copy.\n\t//\n\twidth_counter = 0;\n\twhile ( src_ptr < end_of_source ) {\n\n\t\t//\n\t\t// Blend this pixel with the one to the left and place this new color in the dest buffer.\n\t\t//\n\t\t*dest_ptr = Palette_Interpolation_Table[ (*src_ptr) ][ (*( src_ptr - 1 )) ];\n\t\tdest_ptr ++;\n\n\t\t//\n\t\t// Now place the source pixel into the dest buffer.\n\t\t//\n\t\t*dest_ptr = *src_ptr;\n\n\t\tsrc_ptr ++;\n\t\tdest_ptr ++;\n\n\t\twidth_counter ++;\n\t\tif ( width_counter == src_width ) {\n\t\t\twidth_counter = 0;\n\t\t\tdest_ptr += dest_width;\n\t\t}\n\t}\n\n\n\treturn;\n}\n#endif\n\n\n#if( 0 )\n/***************************************************************************\n * INTERPOLATE_2X_SCALE                                                    *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/06/1995  MG : Created.                                             *\n *=========================================================================*/\nvoid Interpolate_2X_Scale( GraphicBufferClass *source, GraphicBufferClass *dest )\n{\n\tunsigned char\t*src_ptr;\n\tunsigned char\t*dest_ptr;\n\tunsigned char\t*dest2_ptr;\n\tunsigned char\t*end_of_source;\n\tint\tsrc_width;\n\tint\tdest_width;\n\tint\twidth_counter;\n\n\t//\n\t// Get pointers to the source and destination buffers.\n\t//\n\tsrc_ptr = (unsigned char *) source->Get_Offset();\n\tdest_ptr = (unsigned char *) dest->Get_Offset();\n\tend_of_source = src_ptr + ( source->Get_Width() * source->Get_Height() );\n\n\t//\n\t// Get width of source and dest buffers.\n\t//\n\tsrc_width = source->Get_Width();\n\tdest_width = dest->Get_Width();\n\n\t//\n\t// Copy over the first pixel (upper left).\n\t//\n\t*dest_ptr = *src_ptr;\n\tsrc_ptr ++;\n\tdest_ptr += 2;\n\tdest2_ptr = dest_ptr + dest_width + 1;\n\n\t//\n\t// Scale copy.\n\t//\n\twidth_counter = 0;\n\twhile ( src_ptr < end_of_source ) {\n\n\t\t//\n\t\t// Blend this pixel with the one to the left and place this new color in the dest buffer.\n\t\t//\n\t\t*dest2_ptr = Palette_Interpolation_Table[ (*src_ptr) ][ (*( src_ptr - 1 )) ];\n\t\tdest2_ptr += 2;\n\n\t\t//\n\t\t// Now place the source pixel into the dest buffer.\n\t\t//\n\t\t*dest_ptr = *src_ptr;\n\n\t\tsrc_ptr ++;\n\t\tdest_ptr += 2;\n\n\t\twidth_counter ++;\n\t\tif ( width_counter == src_width ) {\n\t\t\twidth_counter = 0;\n\t\t\tdest_ptr += dest_width;\n\t\t\tdest2_ptr += dest_width;\n\t\t}\n\t}\n\n\n\treturn;\n}\n\n#endif\n\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/MOVIES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQAVIEW                                  *\n *                                                                         *\n *                    File Name : VQ.CPP                                   *\n *                                                                         *\n *                   Programmer : Michael Grayford                         *\n *                                                                         *\n *                   Start Date :                                          *\n *                                                                         *\n *                  Last Update : May 31, 1995   [MG]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Choose_VQA - Brings up choice of VQA files.\t\t\t\t\t\t\t\t\t  *\n *   Draw_To_Video_Callback -- callback after draw VQA frame to video      *\n *   Draw_To_Buffer_Callback -- callback after draw VQA frame to buffer    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n//==========================================================================\n// PUBLIC FUNCTIONS\n//==========================================================================\n\nextern int Initialize_Movie_System( void );\nextern void Free_Movie_System( void );\nextern void Choose_Movie( WindowHandle window_handle );\nextern long Draw_To_Video_Callback( unsigned char *buffer, long frame_number );\nextern long Draw_To_Buffer_Callback( unsigned char *buffer, long frame_number );\nextern void Create_Palette_Interpolation_Table( void );\n\n//==========================================================================\n// PRIVATE DEFINES\n//==========================================================================\n\n#define DRAW_TO_VIDEO\t\tFALSE\n\n\n//==========================================================================\n// PUBLIC FUNCTIONS\n//==========================================================================\n\n#if( DRAW_TO_VIDEO )\n\n#define MOVIE_WIDTH\t640\n#define MOVIE_HEIGHT\t480\n\n#else\n\n#define MOVIE_WIDTH\t320\n#define MOVIE_HEIGHT\t200\n\n#endif\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/PAL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQAVIEW                                  *\n *                                                                         *\n *                    File Name : PAL.CPP                                  *\n *                                                                         *\n *                   Programmer : Mike Grayford                            *\n *                                                                         *\n *                   Start Date : November 20, 1995                        *\n *                                                                         *\n *                  Last Update : Nov 20, 1995   [MG]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *                                                                         *\n * Update_Full_Palette -- Modifies the Windows palette                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <windows.h>\n\n#include <westwood.h>\n#include <vidmode.h>\n#include <pal.h>\n#include <gbuffer.h>\n#include <main.h>\n#include <monochrm.h>\n#include <wwlib.h>\n#include <memflag.h>\n#include <vq.h>\n\n\n//---------------------------------------------------------------------------------------------\n//\tPUBLIC DATA\n//---------------------------------------------------------------------------------------------\n\n//---------------------------------------------------------------------------------------------\n//\tPRIVATE GLOBALS\n//---------------------------------------------------------------------------------------------\n\n\n/***************************************************************************\n * Update_Full_Palette -- Modifies the Windows palette                     *\n *                                                                         *\n * INPUT: unsigned char *palette - pointer to the entire raw palette\t\t  *\n *                                                                         *\n * OUTPUT: NONE\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS: Watch out for falling bricks.\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/27/1995  MG : Created.                                             *\n *=========================================================================*/\nvoid Update_Full_Palette( unsigned char *palette )\n{\n\tPALETTEENTRY\tpe[ SIZE_OF_PALETTE ];\n\tunsigned char\t*pal_pos;\n\tint\t\t\t\ti;\n\n\tpal_pos = palette;\n\tfor ( i = 0; i < SIZE_OF_PALETTE; i ++ ) {\n\t\tpe[ i ].peRed = *pal_pos;\n\t\tpal_pos ++;\n\t\tpe[ i ].peGreen = *pal_pos;\n\t\tpal_pos ++;\n\t\tpe[ i ].peBlue = *pal_pos;\n\t\tpal_pos ++;\n\t}\n\n  \tMem_Copy( palette, CurrentPalette, SIZE_OF_PALETTE * 3 );\n\n\tDirectDrawObject->CreatePalette( DDPCAPS_8BIT, &pe[ 0 ], &PalettePtr, NULL );\n\tScreen_Buffer->Get_Graphic_Buffer()->Get_DD_Surface()->SetPalette( PalettePtr );\n\tPalettePtr->SetEntries( DDPSETPAL_VSYNC , 0 , SIZE_OF_PALETTE , &pe[ 0 ] );\n}\n\n\n\n\n\n\nextern\tVQAClass\t*TestVqa;\n\nextern \"C\"{\n\tvoid __cdecl SetPalette(unsigned char *palette,long ,unsigned long );\n}\n\nvoid __cdecl SetPalette(unsigned char *palette,long ,unsigned long )\n{\n\tTestVqa->Update_Palette(palette);\n}\n\n\n\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/PAL.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQAVIEW                                  *\n *                                                                         *\n *                    File Name : PAL.H                                    *\n *                                                                         *\n *                   Programmer : Michael Grayford                         *\n *                                                                         *\n *                   Start Date : Nov 27, 1995                             *\n *                                                                         *\n *                  Last Update : Nov 22, 1995   [MG]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n//==========================================================================\n// PUBLIC FUNCTIONS\n//==========================================================================\n\nvoid Update_Full_Palette( unsigned char *palette );\n\n//==========================================================================\n// PUBLIC FUNCTIONS\n//==========================================================================\n\nextern \"C\" {\n\tchar CurrentPalette[ SIZE_OF_PALETTE * 3 ];\n}\n\n//==========================================================================\n// PUBLIC DEFINES\n//==========================================================================\n\n#define COLOR_BLACK\t\t0\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/TEST.MAK",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n.rc.res:\n\thello\n\u001a"
  },
  {
    "path": "WINVQ/VQAVIEW/VIDMODE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#define VIDEO_MODE_WIDTH\t\t\t\t640\n#define VIDEO_MODE_HEIGHT\t\t\t480\n#define VIDEO_MODE_BITS_PER_PIXEL\t8\n#define SIZE_OF_PALETTE\t\t\t\t256\n\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/VQ.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQAVIEW                                  *\n *                                                                         *\n *                    File Name : VQ.CPP                                   *\n *                                                                         *\n *                   Programmer : Michael Grayford                         *\n *                                                                         *\n *                   Start Date :                                          *\n *                                                                         *\n *                  Last Update : May 31, 1995   [MG]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * Initialize_VQA_System - Allocate memory needed for caching and any\t\t  *\n *\t\tpermanent VQA data.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * Free_VQA_System - Free up memory used by VQA cache system and any \t\t  *\n *\t\tpermanent VQA data.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *   Disk_VQA_Stream_Handler -- Handles file io for VQAs run from disk.    *\n *   VQ_Drawer_Callback -- Blits the frame to the screen.                  *\n *   VQAClass::VQAClass -- Constructor for VQAClass object.                *\n *   VQAClass::Update_Palette -- Updates the system palette.               *\n *   VQAClass::Open_And_Load_Buffers -- Opens VQA file, fills frame buffers*\n *   VQAClass::Seek_To_Frame -- Performs file seek to specified frame.     *\n *   VQAClass::Play_VQA - Plays from the current frame of the VQA up to    *\n *\t\tand including the last frame specified.\t\t\t\t\t\t\t\t\t  *\n *   VQAClass::Play_Generic_VQA -- Private func to play any Monopoly VQA.  *\n *   VQAClass::Play_VQA_Frame - Plays the specified frame,seek if necessary*\n *   VQAClass::Pause_VQA - Pauses a VQA in order to freeze the VQA timers. *\n *   VQAClass::Close_And_Free_VQA -- Closes vqa, frees instanc, frees cache*\n *   Check_Key -- NULL function for VQA play library.                      *\n *   Get_Key -- NULL function for VQA play library.                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n//==========================================================================\n// INCLUDES\n//==========================================================================\n\n#include <windows.h>\n#include <windowsx.h>\n#include <westwood.h>\n#include <file.h>\n#include <stdio.h>\n#include <memflag.h>\n#include <vq.h>\n#include <mainwind.h>\n#include <pal.h>\n#include <wwstd.h>\n#include <gbuffer.h>\n#include <main.h>\n#include <monochrm.h>\n#include <vidmode.h>\n#include <movies.h>\n#include <gametime.h>\n#include <dialogs.rh>\n#include <vqm32\\compress.h>\n\n//==========================================================================\n// PRIVATE DEFINES\n//==========================================================================\n\n#define DEBUG_CODE\t\t\t\t\t\tTRUE\n#define DEBUG_MOVIE_FRAME_RATE    -1\n\n\n//==========================================================================\n// PRIVATE FUNCTIONS\n//==========================================================================\n\nlong Disk_VQA_Stream_Handler(\n\t\tVQAHandle *vqa_handle, long action, void *buffer, long nbytes );\n\n#if( DEBUG_CODE )\nBOOL Set_Frame_Rate_Dialog_Procedure(\n\tWindowHandle window_handle,\n\tUINT message,\n\tWPARAM w_param,\n\tLPARAM l_param );\n#endif\n\n//==========================================================================\n// PRIVATE GLOBALS\n//==========================================================================\n\n#if( DEBUG_CODE )\n\tint Debug_Movie_Frame_Rate = -1;\n#endif\n\n\n/***************************************************************************\n * VQAClass::VQAClass -- Constructor for VQAClass object.                  *\n *                                                                         *\n * INPUT:                                                                  *\n *   base_filename - vqa filename without the extension.\t\t\t\t\t\t  *\n *   buffer - buffer to draw to.\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *   callback - pointer to function that will blit the drawn frames.       *\n *   media_source - either FROM_MEMORY or FROM_DISK.\t\t\t\t\t\t\t  *\n *   id - more specific info about the vqa, like exact property location.  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY: See PVCS log                                                   *\n *=========================================================================*/\nVQAClass::VQAClass( char *filename, char *buffer, short media_src, long (*callback) (unsigned char *, long) )\n{\n\t// Initialize config options.\n\tVQA_DefaultConfig( &vqa_config );\n\n\t//-------------------------------------------------------------------------\n\t// Set up video config options.\n\t//-------------------------------------------------------------------------\n\tvqa_config.Vmode = 0;\n\tvqa_config.ImageBuf = (unsigned char *)buffer;\n\n\t//\n\t// Set up draw options.\n\t//\n\tvqa_config.DrawFlags = VQACFGF_TOPLEFT;\n\tvqa_config.DrawFlags |= VQACFGF_BUFFER;\n\t//vqa_config.DrawFlags |= VQACFGF_NOSKIP;\n\n\t//\n\t// Set the dimensions of the draw buffer.\n\t//\n\tvqa_config.ImageWidth = MOVIE_WIDTH;\n\tvqa_config.ImageHeight = MOVIE_HEIGHT;\n\tvqa_config.X1 = 0;\n\tvqa_config.Y1 = 0;\n\n\t//\n\t// Set up the drawer callback for the VQA.\n\t//\n\tvqa_config.DrawerCallback = callback;\n\n\t//\n\t// Set the load rate (it is misnamed FrameRate)\n\t//\n\tvqa_config.FrameRate = -1;\n\n\t//\n\t// Set the frame rate (DrawRate)\n\t//\n\tvqa_config.DrawRate = -1;\n\n\t#if( DEBUG_CODE )\n\t\tvqa_config.FrameRate = Debug_Movie_Frame_Rate;\n\t\tvqa_config.DrawRate = Debug_Movie_Frame_Rate;\n\t\tvqa_config.FrameRate = DEBUG_MOVIE_FRAME_RATE;\n\t\tvqa_config.DrawRate = DEBUG_MOVIE_FRAME_RATE;\n\t#endif\n\n\tvqa_config.SoundObject = NULL;\t//Get_Sound_Object();\n\tvqa_config.PrimaryBufferPtr = NULL;\t//Get_Primart_Buffer();\n\n\t//-------------------------------------------------------------------------\n\t// Create a VQ instance for playing from memory - does not actually allocate buffers.\n\t//-------------------------------------------------------------------------\n\tvqa_handle = VQA_Alloc();\n\n\t//\n\t// Set the IO handler for this VQ instance.\n\t//\n\tmedia_source = media_src;\n\tswitch( media_source ) {\n\t\tcase FROM_DISK:\n\t\tdefault:\n\t\t\tvqa_config.NumFrameBufs = 6;\n\t\t\tvqa_config.NumCBBufs = 3;\n\t\t\tVQA_Init( vqa_handle, Disk_VQA_Stream_Handler );\n\t\t\tbreak;\n\t}\n\n\t//-------------------------------------------------------------------------\n\t// Initialize private class variables.\n\t//-------------------------------------------------------------------------\n\n\tfor (int i=0 ; i<50 ; i++){\n\t\tInterpolatedPalettes[i] = NULL;\n\t}\n\n\t// Init file_handle\n\tfile_handle = NULL;\n\n\t// Initialize starting frame number to first frame of movie.\n\tcurrent_frame = 0;\n\n\t// Set total frames.\n\ttotal_frames = 0;\n\n\t// Save the base filename for this VQA instance.\n\tstrcpy( base_filename, filename );\n\n\t// Save the vqa filename for this VQA instance.\n\tsprintf( vqa_filename, \"%s.vqa\", filename );\n\n\t// Initially, vqa is not open.\n\tvqa_is_open = FALSE;\n\n}\n\n\nVQAClass::~VQAClass(void)\n{\n\tfor (int i=0 ; i<50 ;i++){\n\t\tif (InterpolatedPalettes[i]){\n\t\t\tfree (InterpolatedPalettes[i]);\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * DISK_VQA_STREAM_HANDLER -- Handles file io for VQAs run from disk.      *\n *                                                                         *\n * INPUT:                                                                  *\n *    vqa_handle - pointer to the vqa instance.                            *\n *    action - specifies the io operation to be performed.\t\t\t\t\t  *\n *    buffer - buffer to write out or read into.\t\t\t\t\t\t\t\t\t  *\n *    nbytes - number of bytes to read, write, seek...\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY: See PVCS log                                                   *\n *=========================================================================*/\nlong Disk_VQA_Stream_Handler(\n\tVQAHandle *vqa_handle, long action, void *buffer, long nbytes)\n{\n\tunsigned char\ttemp_char;\n\tint\t\t\t\tfh;\n\tlong\t\t\t\terror;\n\n\tfh = vqa_handle->VQAio;\n\n\t//\n\t// Perform the action specified by the stream command.\n\t//\n\tswitch ( action ) {\n\n\t\t//\n\t\t// VQACMD_READ means read NBytes from the stream and place it in the\n\t\t// memory pointed to by Buffer.\n\t\t//\n\t\t// Any error code returned will be remapped by VQA library into\n\t\t// VQAERR_READ.\n\t\t//\n\t\tcase VQACMD_READ:\n\t\t\terror = ( Read_File( fh, buffer, nbytes ) != nbytes );\n\t\t\tbreak;\n\n\t\t//\n\t\t// VQACMD_WRITE is analogous to VQACMD_READ.\n\t\t//\n\t\t// Writing is not allowed to the VQA file, VQA library will remap the\n\t\t// error into VQAERR_WRITE.\n\t\t//\n\t\tcase VQACMD_WRITE:\n\t\t\terror = 1;\n\t\t\tbreak;\n\n\t\t//\n\t\t// VQACMD_SEEK asks that you perform a seek relative to the current\n\t\t// position. NBytes is a signed number, indicating seek direction\n\t\t// (positive for forward, negative for backward). Buffer has no meaning\n\t\t// here.\n\t\t//\n\t\t// Any error code returned will be remapped by VQA library into\n\t\t// VQAERR_SEEK.\n\t\t//\n\t\tcase VQACMD_SEEK:\n\t\t\t//\n\t\t\t// In order to force a physical seek, we must seek to a position that\n\t\t\t// is one byte before our real destination, and then read one byte.\n\t\t\t//\n\t\t\tif ( nbytes > 0 ) {\n\t\t\t\tnbytes -= 1;\n\t\t\t\terror = ( Seek_File( fh, nbytes, (long) buffer ) == 0 );\n\t\t\t\tRead_File( fh, &temp_char, 1 );\n\t\t\t}\n\t\t\telse {\n\t\t\t\terror = ( Seek_File( fh, nbytes, (long) buffer ) == 0 );\n\t\t\t}\n\t\t\tbreak;\n\n\t\t//\n\t\t// VQACMD_OPEN asks that you open your stream for access.\n\t\t//\n\t\tcase VQACMD_OPEN:\n\t\t\terror = Open_File( (char const *) buffer, READ );\n\t\t\tif ( error != WW_ERROR ) {\n\t\t\t\tvqa_handle->VQAio = error;\n\t\t\t\terror = 0;\n\t\t\t}\n\t\t\telse {\n\t\t\t\terror = TRUE;\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tcase VQACMD_CLOSE:\n\t\t\tClose_File( fh );\n\t\t\terror = 0;\n\t\t\tbreak;\n\n\t\t//\n\t\t// VQACMD_INIT means to prepare your stream for reading. This is used for\n\t\t// certain streams that can't be read immediately upon opening, and need\n\t\t// further preparation. This operation is allowed to fail; the error code\n\t\t// will be returned directly to the client.\n\t\t//\n\t\tcase VQACMD_INIT:\n\t\t\terror = 0;\n\t\t\tbreak;\n\n\t\t//\n\t\t// VQACMD_CLEANUP means to terminate the transaction with the associated\n\t\t// stream. This is used for streams that can't simply be closed. This\n\t\t// operation is not allowed to fail; any error returned will be ignored.\n\t\t//\n\t\tcase VQACMD_CLEANUP:\n\t\t\terror = 0;\n\t\t\tbreak;\n\t}\n\n\treturn ( error );\n}\n\n\n\n/***********************************************************************************************\n * Increase_Palette_Luminance -- increase contrast of colours in a palette                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to palette                                                                    *\n *           percentage increase of red                                                        *\n *           percentage increase of green                                                      *\n *           percentage increase of blue                                                       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    12/12/95 12:16PM ST : Created                                                            *\n *=============================================================================================*/\n\nvoid Increase_Palette_Luminance (unsigned char *palette , int red_percentage , int green_percentage , int blue_percentage)\n{\n\n\tunsigned\tint\tred;\n\tunsigned\tint\tgreen;\n\tunsigned\tint\tblue;\n\tfor (int i=0 ; i<SIZE_OF_PALETTE*3 ; i+=3){\n\n\t\tred \t= (unsigned)*(palette+i);\n\t\tgreen = (unsigned)*(palette+i+1);\n\t\tblue\t= (unsigned)*(palette+i+2);\n\n\t\tred \t+= red*red_percentage/100;\n\t\tgreen\t+= green*green_percentage/100;\n\t\tblue\t+= blue*blue_percentage/100;\n\n\t\tred \t= MIN (255,red);\n\t\tgreen\t= MIN (255,green);\n\t\tblue\t= MIN (255,blue);\n\n\t\t*(palette+i)\t=(unsigned char)red;\n\t\t*(palette+i+1)\t=(unsigned char)green;\n\t\t*(palette+i+2)\t=(unsigned char)blue;\n\n\t}\n\n}\n\n/***************************************************************************\n * VQACLASS::UPDATE_PALETTE -- Updates the system and WinG palettes.       *\n *                                                                         *\n * INPUT:                                                                  *\n *    none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *    TRUE\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *    See PVCS log\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *=========================================================================*/\nextern BOOL SuspendAudioCallback;\nextern \"C\" unsigned char Palette_Interpolation_Table[ SIZE_OF_PALETTE ][ SIZE_OF_PALETTE ];\nBOOL VQAClass::Update_Palette( unsigned char *newpalette )\n{\n\tunsigned char *pal_src = newpalette;\n\tunsigned char *pal_dst = palette;\n\n\tfor (int j=0 ; j<SIZE_OF_PALETTE*3 ; j++){\n\t\t*pal_dst++ = (*pal_src++)<<2;\n\t}\n\n\t//Increase_Palette_Luminance(palette , 30 , 30 , 30);\n\tUpdate_Full_Palette( palette );\n\n\n\t/*\n\t**  If there was no palette table on disk then create one\n\t*/\n\tif (PalettesRead){\n\t\tmemcpy (&Palette_Interpolation_Table[0][0] , InterpolatedPalettes[NumPalettes] , 65536);\n\t\tNumPalettes++;\n\t} else {\n\n\t\tSuspendAudioCallback = TRUE;\n\t\tCreate_Palette_Interpolation_Table();\n\n\t\tfor (int i=0 ; i<50 ;i++){\n\t\t\tif (!InterpolatedPalettes[i]){\n\t\t\t\tInterpolatedPalettes[i] = (unsigned char*)malloc (SIZE_OF_PALETTE*SIZE_OF_PALETTE);\n\t\t\t\tmemcpy (InterpolatedPalettes[i] , &Palette_Interpolation_Table[0][0] , SIZE_OF_PALETTE*SIZE_OF_PALETTE);\n\t\t\t\tNumPalettes++;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tSuspendAudioCallback = FALSE;\n\t}\n\n\treturn( TRUE );\n}\n\n\n\n\n/***********************************************************************************************\n * Strip_Interpolated_Palette -- strip the redundancy out of an interpolated palette table     *\n *                                                                                             *\n * This just replaces the redundant entries with zeros so the palette will compress better     *\n *                                                                                             *\n * INPUT:    ptr to palette                                                                    *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    12/21/95 10:34AM ST : Created                                                            *\n *=============================================================================================*/\nvoid Strip_Interpolated_Palette(unsigned char *interpal)\n{\n\tfor (int y=0 ; y<255 ;y++){\n\t\tmemset (interpal + (y*256+y+1), 0 , 256-y-1);\n\t}\n}\n\n\n/***********************************************************************************************\n * Rebuild_Interpolated_Palette -- rebuilds the entries stripped by Strip_Interpolated_Palette *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to palette                                                                    *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    12/21/95 10:35AM ST : Created                                                            *\n *=============================================================================================*/\nvoid Rebuild_Interpolated_Palette(unsigned char *interpal)\n{\n\tfor (int y=0 ; y<255 ; y++){\n\t\tfor (int x=y+1 ; x<256 ; x++){\n\t\t\t*(interpal + (y*256+x)) = *(interpal + (x*256+y));\n\t\t}\n\t}\n}\n\n\n\n/***********************************************************************************************\n * VQAC::Read_Palettes -- read the associated palette interpolation tables from disk           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    12/21/95 10:36AM ST : Created                                                            *\n *=============================================================================================*/\n\nvoid VQAClass::Read_Palettes(void)\n{\n\tunsigned char \t*comp_buff = (unsigned char*)malloc(65536);\n\tunsigned\t\t\tcomp_size;\n\n\tNumPalettes=0;\n\tPalettesRead = FALSE;\n\n\t/*\n\t** Create the palette file name from the VQ file name. Palette files have .VQP ext\n\t*/\n\tmemcpy (&PaletteFilename[0] , &vqa_filename[0] , _MAX_PATH);\n\tfor (int i=0 ; i<_MAX_PATH ; i++){\n\t\tif (PaletteFilename[i] == '.'){\n\t\t\tPaletteFilename[i+1] = 'V';\n\t\t\tPaletteFilename[i+2] = 'Q';\n\t\t\tPaletteFilename[i+3] = 'P';\n\t\t\tPaletteFilename[i+4] = 0;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t** If the palette file is available the open it\n\t*/\n\tPaletteFile = new RawFileClass (PaletteFilename);\n\tif (PaletteFile->Is_Available()){\n\n\t\tPaletteFile->Open(READ);\n\n\t\t/*\n\t\t** Find out how many palettes are in the file\n\t\t*/\n\t\tPaletteFile->Read(&NumPalettes , 4);\n\n\t\t/*\n\t\t** Read each palette. Palettes are all the same size.\n\t\t*/\n\t\tfor (i=0 ; i<NumPalettes ; i++){\n\t\t\tInterpolatedPalettes[i] = (unsigned char *)malloc (65536);\n\t\t\tmemset (InterpolatedPalettes[i],0,65536);\n\n\t\t\tfor (int y=0 ; y<256 ;y++){\n\t\t\t\tPaletteFile->Read (InterpolatedPalettes[i] + y*256 , y+1);\n\t\t\t}\n\n\t\t\t//PaletteFile->Read(&comp_size,4);\n\t\t\t//PaletteFile->Read(comp_buff , comp_size);\n\t\t\t//LCW_Uncompress((char const*)comp_buff,(char*)InterpolatedPalettes[i],65536);\n\n\t\t\t/*\n\t\t\t** Rebuild the entries that were lost when the palette was written to disk\n\t\t\t*/\n\t\t\tRebuild_Interpolated_Palette(InterpolatedPalettes[i]);\n\t\t}\n\n\t\tPalettesRead = TRUE;\n\t\tPaletteFile->Close();\n\t\tNumPalettes = 0;\n\n\t}\n\tdelete PaletteFile;\n}\n\n\n\n\n\n/***********************************************************************************************\n * VQAC::Write_Palettes -- write the palette interpolation tables to disk                      *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    12/21/95 10:37AM ST : Created                                                            *\n *=============================================================================================*/\n\nvoid VQAClass::Write_Palettes(void)\n{\n\tunsigned char \t*comp_buff = (unsigned char*)malloc(65536);\n\tunsigned\t\t\tcomp_size;\n\n\t/*\n\t** If the palette file wasnt there when we started playing the VQ then create one\n\t*/\n\tif (NumPalettes && !PalettesRead){\n\n\t\tPaletteFile = new RawFileClass (PaletteFilename);\n\t\tPaletteFile->Open(WRITE);\n\n\t\t/*\n\t\t** Write the number of palettes we created\n\t\t*/\n\t\tPaletteFile->Write(&NumPalettes , 4);\n\n\t\t/*\n\t\t** Write the non-redundant palette table entries for each palette table\n\t\t*/\n\t\tfor (int i=0 ; i<NumPalettes ; i++){\n\t\t\t//Strip_Interpolated_Palette(InterpolatedPalettes[i]);\n\t\t\t//comp_size = LCW_Compress ((char const*)InterpolatedPalettes[i] , (char*)comp_buff , 65536);\n\n\n\t\t\tfor (int y=0 ; y<256 ;y++){\n\t\t\t\tPaletteFile->Write (InterpolatedPalettes[i] + y*256 , y+1);\n\t\t\t}\n\t\t}\n\t\tPaletteFile->Close();\n\t\tdelete PaletteFile;\n\t}\n}\n\n\n\n/***************************************************************************\n * VQACLASS::OPEN_AND_LOAD_BUFFERS -- Opens VQA file and fills frame buffrs*\n *                                                                         *\n * INPUT:                                                                  *\n *    none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *    TRUE if successful        \t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   See PVCS log\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *=========================================================================*/\nBOOL VQAClass::Open_And_Load_Buffers( void )\n{\n\tVQAInfo\tvqa_info;\n\tunsigned char\t\t*pal_ptr;\n\tINT\t\ti;\n\n\n\t//\n\t// Open the VQA file, allocate the buffers for this VQ instance, and pre-\n\t// load the buffers.\n\t//\n\tif ( VQA_Open( vqa_handle, vqa_filename, &vqa_config ) != 0 ) {\n\t\tvqa_is_open = FALSE;\n\t\treturn( FALSE );\n\t}\n#if (0)\n\t//\n\t// Get the VQA's palette.\n\t//\n\tpal_ptr = (unsigned char *) VQA_GetPalette( vqa_handle );\n\tif ( pal_ptr ) {\n\n\t\t//\n\t\t// Get a copy of the VQA's palette.\n\t\t//\n\t\tMem_Copy( pal_ptr, palette, ( SIZE_OF_PALETTE * 3 ) );\n\n\t\t//\n\t\t// The palette in the VQA files is 6-bit per pixel, so shift all the\n\t\t// values to make them 8-bits per pixel.\n\t\t//\n\t\tfor ( i = 0; i < ( SIZE_OF_PALETTE * 3 ); i ++ ) {\n\t\t\tpalette[ i ] <<= 2;\n\t\t}\n\t}\n#endif\n\t//\n\t// Get frame information about the VQA.\n\t//\n\tVQA_GetInfo( vqa_handle, &vqa_info );\n\ttotal_frames = vqa_info.NumFrames;\n\n\tvqa_is_open = TRUE;\n\n\treturn( TRUE );\n}\n\n\n\n/***************************************************************************\n * VQACLASS::SEEK_TO_FRAME -- Performs file seek to specified frame.       *\n *                                                                         *\n * INPUT:                                                                  *\n *    frame - frame number to seek to.\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *    none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   See PVCS log\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *=========================================================================*/\nvoid VQAClass::Seek_To_Frame( unsigned long frame )\n{\n\t//\n\t// Don't bother seeking if already there.\n\t//\n\tif ( frame == current_frame ) {\n\t\treturn;\n\t}\n\n\tif ( VQA_SeekFrame( vqa_handle, frame, SEEK_SET ) != -1 ) {\n\t\tcurrent_frame = frame;\n\t}\n}\n\n/***************************************************************************\n * Play_VQA - Plays from the current frame of the VQA up to and including  *\n *\t\tthe last frame specified.\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * INPUT: INT last_frame - last frame to be displayed                      *\n *                                                                         *\n * OUTPUT: NONE                                                            *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/20/1995  MG : Created.                                             *\n *=========================================================================*/\nint VQAClass::Play_VQA( int last_frame_to_play )\n{\n\tINT return_code;\n\n\t#if( DEBUG_CODE )\n\t\tVQAStatistics\tvqa_stats;\n\t\tfloat\t\t\t\tframes_per_sec;\n\t\tunsigned long\tstart_time;\n\t\tunsigned long\tend_time;\n\t#endif\n\n\t//\n\t// Before starting to play, make sure we have the correct palette.\n\t//\n\t//Update_Palette();\n\n//\n// Create table for scaling low-res VQA's.\n//\n\n\t//Create_Palette_Interpolation_Table();\n\n\t//\n\t// Get current time for timing purposes.\n\t//\n\t#if( DEBUG_CODE )\n\t\tstart_time = Get_Game_Time();\n\t#endif\n\n\t//\n\t// Call the appropriate play routine.\n\t//\n\treturn_code = Play_Generic_VQA( last_frame_to_play );\n\n\t//\n\t// Get VQA statistics.\n\t//\n\t#if( DEBUG_CODE )\n\t\tend_time = Get_Game_Time();\n\t\tVQA_GetStats( vqa_handle, &vqa_stats );\n\t\tif ( ( end_time - start_time ) <= 0.0 ) {\n\t\t\tframes_per_sec = 0.0;\n\t\t}\n\t\telse {\n\t\t\tframes_per_sec = vqa_stats.FramesDrawn / ( ( end_time - start_time ) / 1000.0 );\n\t\t}\n\t\tDebug_Printf( \"Frames drawn=%d. Frames/sec=%03.02f. Frames skipped = %d\\r\\n\", vqa_stats.FramesDrawn, frames_per_sec, vqa_stats.FramesSkipped );\n\t#endif\n\n\t//\n\t// If PLAY_ALL_FRAMES was specified, reset curr frame to beginning of movie.\n\t//\n\tif ( last_frame_to_play == PLAY_ALL_FRAMES ) {\n\t\tcurrent_frame = 0;\n\t}\n\n\treturn( return_code );\n}\n\n\n/***************************************************************************\n * VQACLASS::PLAY_GENERIC_VQA -- Private func to play any Monopoly VQA.    *\n *                                                                         *\n * INPUT:                                                                  *\n *   last_frame_to_play - last frame to be drawn.\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *   INT error code.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   See PVCS log\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *=========================================================================*/\nint VQAClass::Play_Generic_VQA( int last_frame_to_play )\n{\n\tlong\t\t\t\terrval;\n\n\tswitch( last_frame_to_play ) {\n\t\tcase PLAY_ALL_FRAMES:\n\t\t\tSeek_To_Frame( 0 );\n\t\t\t// FALL THROUGH...\n\t\tcase PLAY_TO_END_OF_MOVIE:\n\t\t\tlast_frame_to_play = total_frames - 1;\n\t\t\tbreak;\n\t}\n\n\t//\n\t// Play frames until the last desired frame is drawn.\n\t//\n\terrval = 0;\n\n\twhile (\n\t\t( errval == VQAERR_NOT_TIME || errval >= 0 || errval == VQAERR_NOBUFFER || errval == VQAERR_SLEEPING ) &&\n\t\t( current_frame <= last_frame_to_play ) ) {\n\n\t\t//\n\t\t// Check for Windows Messages.\n\t\t//\n\t\tMain_Window.Update_Windows_Messages();\n\n\t\t#if( DRAW_TO_VIDEO )\n\t\t\tScreen_Buffer->Lock();\n\t\t#endif\n\n\t\t//\n\t\t// Maybe draw another frame.\n\t\t//\n\t\terrval = VQA_Play( vqa_handle, VQAMODE_WALK );\n\n\t\t#if( DRAW_TO_VIDEO )\n\t\t\tScreen_Buffer->Unlock();\n\t\t#endif\n\n\t\t// If we actually played a frame update the current frame number.\n\t\tif ( errval >= 0 ) {\n\t\t\tcurrent_frame = errval;\n         current_frame ++;\n\t\t}\n\t}\n\n\treturn( VQA_PLAY_NO_ERROR );\n}\n\n\n/***************************************************************************\n * Play_VQA_Frame - Plays the specified frame, seeking to it if necessary. *\n *                                                                         *\n * INPUT: INT frame_number                                                 *\n *                                                                         *\n * OUTPUT: NONE                                                            *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/20/1995  MG : Created.                                             *\n *=========================================================================*/\nvoid VQAClass::Play_VQA_Frame( INT frame_number )\n{\n\tif ( frame_number == PLAY_LAST_FRAME ) {\n\t\tframe_number = total_frames - 1;\n\t}\n\n\t//\n\t// If not currently at the desired frame, seek to it.\n\t//\n\tif ( current_frame != frame_number ) {\n\t\tSeek_To_Frame( frame_number );\n\t\tcurrent_frame = frame_number;\n\t}\n\n\t//\n\t// Display the frame.\n\t//\n\tPlay_VQA( frame_number );\n\n\t//\n\t// If at end of movie, reset to start of movie.\n\t//\n\tif ( current_frame >= total_frames ) {\n\t\tcurrent_frame = 0;\n\t}\n}\n\n/***************************************************************************\n * Pause_VQA - Pauses a VQA in order to freeze the VQA timers.\t\t\t\t  *\n *                                                                         *\n * INPUT: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                             \t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/29/1995  MG : Created.                                             *\n *=========================================================================*/\nvoid VQAClass::Pause_VQA( void )\n{\n\tVQA_Play( vqa_handle, VQAMODE_PAUSE );\n}\n\n\n\n/***************************************************************************\n * VQACLASS::CLOSE_AND_FREE_VQA -- Closes vqa, frees instance, frees cache *\n *                                                                         *\n * INPUT:                                                                  *\n *   none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *   none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   See PVCS log.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *=========================================================================*/\nvoid VQAClass::Close_And_Free_VQA( void )\n{\n\tif ( vqa_is_open ) {\n\t\tVQA_Close( vqa_handle );\n\t}\n\tVQA_Free( vqa_handle );\n}\n\n\n\n/***************************************************************************\n * CHECK_KEY -- NULL function for VQA play library.                        *\n *                                                                         *\n * INPUT: NONE                                                             *\n *                                                                         *\n * OUTPUT: 0                                                               *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   See PVCS log\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *=========================================================================*/\nunsigned short Check_Key( void )\n{\n\treturn( 0 );\n}\n\n\n\n/***************************************************************************\n * GET_KEY -- NULL function for VQA play library.                          *\n *                                                                         *\n * INPUT: NONE                                                             *\n *                                                                         *\n * OUTPUT: 0                                                               *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   See PVCS log\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *=========================================================================*/\nunsigned short Get_Key( void )\n{\n\treturn( 0 );\n}\n\n\n/***************************************************************************\n * Set_Movie_Frame_Rate - Debug function for setting movie playback rate   *\n *                                                                         *\n * INPUT: NONE                                                             *\n *                                                                         *\n * OUTPUT: NONE                                                            *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\nvoid Set_Movie_Frame_Rate( void )\n{\n\tint retval;\n\n\t#if( 0 )\n\n\tretval = DialogBox(\n\t\tMain_Window.Get_Instance_Handle(),\n\t\t\"GEEB\",\n\t\tMain_Window.Get_Window_Handle(),\n\t\t(DLGPROC) Set_Frame_Rate_Dialog_Procedure );\n\n\tDebug_Printf( \"retval = %d\\r\\n\", retval );\n\n\t#endif\n}\n\n\n/***************************************************************************\n * SET_FRAME_RATE_DIALOG_PROCEDURE                                         *\n *                                                                         *\n * INPUT: standard windows dialog command parameters                       *\n *                                                                         *\n * OUTPUT: NONE                                                            *\n *                                                                         *\n * WARNINGS: none                                                          *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\nBOOL Set_Frame_Rate_Dialog_Procedure(\n\tWindowHandle window_handle,\n\tUINT message,\n\tWPARAM w_param,\n\tLPARAM l_param )\n{\n\tchar frame_rate_string[ 5 ];\n\n\tswitch( message ) {\n\n\t\tcase WM_COMMAND:\n\n\t\t\tif ( LOWORD( w_param ) == IDOK ) {\n\n\t\t\t\tGetDlgItemText( window_handle, FRAME_RATE, frame_rate_string, sizeof( frame_rate_string ) );\n\t\t\t\tDebug_Movie_Frame_Rate = atoi( frame_rate_string );\n\n\t\t\t\tif ( Debug_Movie_Frame_Rate < -1 ) {\n\t\t\t\t\tDebug_Movie_Frame_Rate = -1;\n\t\t\t\t}\n\n\t\t\t\tDebug_Printf( \"Setting movie frame rate to %d\\r\\n\", Debug_Movie_Frame_Rate );\n\n\t\t\t\tEndDialog( window_handle, TRUE );\n\t\t\t\treturn( TRUE );\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\n\t}\n\treturn( FALSE );\n}\n\n\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/VQ.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQAVIEW                                  *\n *                                                                         *\n *                    File Name : VQ.H                                     *\n *                                                                         *\n *                   Programmer : Michael Grayford                         *\n *                                                                         *\n *                   Start Date :                                          *\n *                                                                         *\n *                  Last Update : Nov 22, 1995   [MG]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n//==========================================================================\n// INCLUDES\n//==========================================================================\n\n#include <vqa32\\vqaplay.h>\n#include <vidmode.h>\n#define bool BOOL\n#define true 1\n#define false 0\n#include <rawfile.h>\n\n//==========================================================================\n// PUBLIC FUNCTIONS\n//==========================================================================\n\nvoid Set_Movie_Frame_Rate( void );\n\n//==========================================================================\n// PRIVATE DEFINES\n//==========================================================================\n\n//--------------------------------------------------------------------------\n// GENERAL DEFINES\n//--------------------------------------------------------------------------\n\n#define VQ_BLOCK_WIDTH\t\t4\n#define VQ_BLOCK_HEIGHT\t\t4\n#define VQ_COLUMNS\t\t\t( VQ_MOVIE_WIDTH / VQ_BLOCK_WIDTH )\n#define VQ_ROWS\t\t\t\t( VQ_MOVIE_HEIGHT / VQ_BLOCK_HEIGHT )\n\n// Codes for media_src parameter of VQAClass constructor:\n#define FROM_DISK\t\t\t\t0\n#define FROM_MEMORY\t\t\t1\n\n// CODES for Play_VQA:\n#define PLAY_ALL_FRAMES\t\t \t-1\n#define PLAY_TO_END_OF_MOVIE\t-2\n\n// CODES for Play_VQA_Frame:\n#define PLAY_LAST_FRAME\t\t\t-1\n\n// Error codes returned by VQA_INIT:\n#define VQA_INIT_NO_ERROR\t\t\t\t\t-1\n#define VQA_INIT_FAILED_MEM_POOL_ALLOC\t-2\n#define VQA_INIT_FAILED_SCRATCH_ALLOC\t-3\n\n// Codes for Cache_VQA:\n#define CACHE_REST_OF_FILE\t\t0\n\n// Error codes returned by CACHE_VQA\n#define CACHE_NO_ERROR\t\t\t-1\n#define CACHE_EOF\t\t\t\t\t-2\n#define CACHE_FAILED_MEM_ALLOC\t-3\n#define CACHE_OPEN_FILE_ERROR\t-4\n#define CACHE_READ_ERROR\t\t\t-5\n\n// Error codes returned by Play_VQA:\n#define VQA_PLAY_NO_ERROR\t\t0\n#define VQA_PLAY_USER_BREAK\t\t1\n\n#define VECTOR_FORMAT_OFFSETS\t1\n#define VECTOR_FORMAT_INDEXES\t2\n#define MAX_CODEBOOK_OFFSET\t\t32766\n\n//==========================================================================\n// PUBLIC DATA\n//==========================================================================\n\nextern unsigned char \t\t*Movie_Scratch_Buffer;\n\n//==========================================================================\n// CLASSES\n//==========================================================================\n\nclass VQAClass {\n\tprivate:\n\t\tchar \t\t\t\tbase_filename[ _MAX_PATH ];\n\t\tchar \t\t\t\tvqa_filename[ _MAX_PATH ];\n\t\tchar\t\t\t\tPaletteFilename [_MAX_PATH];\n\t\tVQAConfig\t\tvqa_config;\n\t\tVQAHandle\t\t*vqa_handle;\n\t\tshort\t\t\t\tmedia_source;\n\t\tint\t\t\t\tfile_handle;\n\t\tunsigned char\tpalette[ SIZE_OF_PALETTE * 3 ];\n\t\tint\t\t\t\tcurrent_frame;\n\t\tint\t\t\t\ttotal_frames;\n\t\tBOOL\t\t\t\tvqa_is_open;\n\t\tunsigned char\t*InterpolatedPalettes[50];\t\t//Max 50 palette changes in a vq\n\t\tBOOL\t\t\t\tPalettesRead;\n\t\tRawFileClass\t*PaletteFile;\n\t\tunsigned\t\t\tNumPalettes;\n\n\n\n\t\t/*=========================================================================*/\n\t\t/* Private functions.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*=========================================================================*/\n\t\tint VQAClass::Play_Generic_VQA( int last_frame_to_play );\n\n\tpublic:\n\t\tVQAClass( char *filename, char *buffer, short media_src, long (*callback) (unsigned char *, long) );\n\t\t~VQAClass (void);\n\t\tBOOL VQAClass::Update_Palette( unsigned char *newpalette );\n\t\tBOOL Open_And_Load_Buffers( void );\n\t\tvoid Seek_To_Frame( unsigned long frame );\n\t\tint Play_VQA( int last_frame_to_play );\n\t\tvoid Play_VQA_Frame( int frame_number );\n\t\tvoid Pause_VQA( void );\n\t\tvoid Close_And_Free_VQA( void );\n\t\tvoid VQAClass::Read_Palettes(void);\n\t\tvoid VQAClass::Write_Palettes(void);\n}; /* VQAClass */\n\n\n//==========================================================================\n// TYPES\n//==========================================================================\n\ntypedef struct {\n\tunsigned long\tfile_offset;\n\tunsigned long\tfile_size;\n} VQACacheHeader;\n\n\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/WESTWOOD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Virtual_Monopoly                         *\n *                                                                         *\n *                    File Name : WESTWOOD.H                               *\n *                                                                         *\n *                   Programmer : Michael Legg / Mike Grayford             *\n *                                                                         *\n *                   Start Date : January 2, 1995                          *\n *                                                                         *\n *                  Last Update : Nov 15, 1995   [MG]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#define BitmapHandle\t\t\t\tHBITMAP\n#define DCHandle\t\t\t\t   HDC\n#define DIBPointer\t\t\t\t\tLPBITMAPINFOHEADER\n#define Handle\t\t\t\t\t\tHANDLE\n#define MenuHandle\t\t\t\t\tHMENU\n#define MessageQueue\t\t\t\tMSG\n#define PaintStruct\t\t\t\tPAINTSTRUCT\n#define PaletteHandle\t\t\t\tHPALETTE\n#define Rectangle\t\t\t\t\tRECT\n#define String\t\t\t   \t\tLPSTR\n#define WindowClass\t\t\t\tWNDCLASS\n#define WindowHandle\t\t\t\tHWND\n#define FileHandle\t\t\t\t\tHFILE\n#define CursorHandle\t\t\t\tHCURSOR\n#define AcceleratorHandle\t\tHACCEL\n#define IconHandle\t\t\t\t\tHICON\n#define InstanceHandle\t\t\tHINSTANCE\n#define DirectDrawPalettePtr\tLPDIRECTDRAWPALETTE\n#define DirectDrawObjectPtr\t\tLPDIRECTDRAW\n#define BOOL\t\t\t\t\t\t\tint\n#define TRUE\t\t\t\t\t\t1\n#define FALSE\t\t\t\t\t\t0\n\u001a"
  },
  {
    "path": "WINVQ/VQAVIEW/WM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQAVIEW                                  *\n *                                                                         *\n *                    File Name : WM.CPP                                   *\n *                                                                         *\n *                   Programmer : Mike Grayford                            *\n *                                                                         *\n *                   Start Date : November 20, 1995                        *\n *                                                                         *\n *                  Last Update : Nov 20, 1995   [MG]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n//==========================================================================\n// INCLUDES\n//==========================================================================\n\n#include <windows.h>\n\n#include <westwood.h>\n#include <wm.h>\n#include <gbuffer.h>\n#include <main.h>\n#include <mainwind.h>\n#include <menus.rh>\n\n#include <movies.h>\n#include <vq.h>\n\n\n//==========================================================================\n// PUBLIC FUNCTIONS\n//==========================================================================\n\nvoid Menu_Exit_Game( void );\n\n\n/***************************************************************************\n * WM_COMMAND_FUNC -- Handles all main window commands                     *\n *                                                                         *\n * INPUT: standard windows dialog command parameters                       *\n *                                                                         *\n * OUTPUT: IDOK or IDCANCEL                                                *\n *                                                                         *\n * WARNINGS: none                                                          *\n *                                                                         *\n * HISTORY:                                                                *\n *    11/20/95 MG : Created                                                *\n *=========================================================================*/\nlong WM_Command_Func(\n\tWindowHandle window_handle,\n\tunsigned int message,\n\tWPARAM w_param,\n\tLPARAM l_param )\n{\n\tswitch( w_param ) {\n\t\tcase MENU_EXIT:\n\t\t\tMenu_Exit_Game();\n\t\t\tbreak;\n\n\t\tcase MENU_OPEN:\n\t\t\tChoose_Movie( Main_Window.Get_Window_Handle() );\n\t\t\tbreak;\n\n\t\tcase MENU_SET_MOVIE_FRAME_RATE:\n\t\t\tSet_Movie_Frame_Rate();\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\treturn( 0 );\n}\n\n\n/***************************************************************************\n * WM_SYS_COMMAND_FUNC -- Handles all system menu commands                 *\n *                                                                         *\n * INPUT: standard windows dialog command parameters                       *\n *                                                                         *\n * OUTPUT: IDOK or IDCANCEL                                                *\n *                                                                         *\n * WARNINGS: none                                                          *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\n#pragma argsused\nlong WM_Sys_Command_Func(\n\tWindowHandle window_handle,\n\tunsigned int message,\n\tWPARAM w_param,\n\tLPARAM l_param )\n{\n\tswitch( w_param & 0xfff0 ) {\n\t\tcase SC_CLOSE:\n\t\t\tbreak;\n\n\t\tcase SC_MINIMIZE:\n\t\t\tbreak;\n\n\t\tcase SC_MAXIMIZE:\n\t\tcase SC_RESTORE:\n\t\t\tbreak;\n\n\t\tcase SC_KEYMENU:\n\t\tcase SC_MOUSEMENU:\n         break;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\treturn( DefWindowProc( window_handle, message, w_param, l_param ) );\n}\n\n\n/***************************************************************************\n * WM_PAINT_FUNC -- Code that is executed when WM_PAINT is sent            *\n *                                                                         *\n * INPUT: standard windows dialog command parameter passing                *\n *                                                                         *\n * OUTPUT: unused                                                          *\n *                                                                         *\n * WARNINGS: none                                                          *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\n#pragma argsused\nlong WM_Paint_Func(\n\tWindowHandle window_handle,\n\tunsigned int message,\n\tunsigned int w_param,\n\tlong l_param )\n{\n\treturn( 0 );\n}\n\n\n/***************************************************************************\n * WM_DESTROY_FUNC -- Handles when a WM_DESTROY hits the main window       *\n *                                                                         *\n * INPUT: standard windows dialog command parameters                       *\n *                                                                         *\n * OUTPUT: unused                                                          *\n *                                                                         *\n * WARNINGS: none                                                          *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\nlong WM_Destroy_Func(\n\tWindowHandle window_handle,\n\tunsigned int message,\n\tunsigned int w_param,\n\tlong l_param )\n{\n\tif ( Screen_Buffer ) {\n\t\tdelete( Screen_Buffer );\n\t}\n\n\tPostQuitMessage( w_param );\n\n\treturn( 0L );\n}\n\n\n/***************************************************************************\n * WM_MOUSE_BUTTON_FUNC -- Handles when a MOUSE button command comes in    *\n *                                                                         *\n * INPUT: standard windows dialog command parameters                       *\n *                                                                         *\n * OUTPUT: unused                                                          *\n *                                                                         *\n * WARNINGS: none                                                          *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\nlong WM_Mouse_Button_Func(\n\tWindowHandle window_handle,\n\tunsigned int message,\n\tunsigned int w_param,\n\tlong l_param )\n{\n\tint x_pix;\n\tint y_pix;\n\n\tx_pix = LOWORD( l_param );\n\ty_pix = HIWORD( l_param );\n\n\tswitch ( message ) {\n\t\tcase WM_LBUTTONDOWN:\n\t\tcase WM_MBUTTONDOWN:\n\t\tcase WM_RBUTTONDOWN:\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn( 0 );\n}\n\n\n\n/***************************************************************************\n * WM_ACTIVATEAPP_FUNC -- Handles WM_ACTIVATEAPP                           *\n *                                                                         *\n * INPUT: standard windows dialog command parameters                       *\n *                                                                         *\n * OUTPUT: unused                                                          *\n *                                                                         *\n * WARNINGS: none                                                          *\n *                                                                         *\n * HISTORY: see PVCS log                                                   *\n *=========================================================================*/\nlong WM_ActivateApp_Func(\n\tWindowHandle window_handle,\n\tunsigned int message,\n\tunsigned int w_param,\n\tlong l_param )\n{\n\treturn( 0 );\n}\n\n\n\nvoid Menu_Exit_Game( void )\n{\n\tPostMessage( Main_Window.Get_Window_Handle(), WM_CLOSE, 0, 0L );\n}\n\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/WM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQAVIEW                                  *\n *                                                                         *\n *                    File Name : WM.H                                     *\n *                                                                         *\n *                   Programmer : Mike Grayford                            *\n *                                                                         *\n *                   Start Date : November 20, 1995                        *\n *                                                                         *\n *                  Last Update : Nov 20, 1995   [MG]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n//==========================================================================\n// Public functions\n//==========================================================================\n\nlong WM_Command_Func(\n\tWindowHandle window_handle,\n\tunsigned int message,\n\tWPARAM w_param,\n\tLPARAM l_param );\n\nlong WM_Sys_Command_Func(\n\tWindowHandle window_handle,\n\tunsigned int message,\n\tWPARAM w_param,\n\tLPARAM l_param );\n\nlong WM_Paint_Func(\n\tWindowHandle window_handle,\n\tunsigned int message,\n\tunsigned int w_param,\n\tlong l_param );\n\nlong WM_Mouse_Button_Func(\n\tWindowHandle window_handle,\n\tunsigned int message,\n\tunsigned int w_param,\n\tlong l_param );\n\nlong WM_ActivateApp_Func(\n\tWindowHandle window_handle,\n\tunsigned int message,\n\tunsigned int w_param,\n\tlong l_param );\n\nlong WM_Destroy_Func(\n\tWindowHandle window_handle,\n\tunsigned int message,\n\tunsigned int w_param,\n\tlong l_param );\n\n\n"
  },
  {
    "path": "WINVQ/VQAVIEW/WWLIB.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : VQAVIEW                                  *\n *                                                                         *\n *                    File Name : WWLIB.H                               *\n *                                                                         *\n *                   Programmer : Michael Grayford                         *\n *                                                                         *\n *                   Start Date :                                          *\n *                                                                         *\n *                  Last Update : Nov 22, 1995   [MG]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nextern DirectDrawObjectPtr DirectDrawObject;\nextern DirectDrawPalettePtr PalettePtr;\nextern WindowHandle MainWindow;\n\n"
  },
  {
    "path": "WINVQ/VQM32/ALL.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMALL_H\n#define VQMALL_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     all.h\n*\n* DESCRIPTION\n*     All VQMisc32 library definitions. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 5, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\iff.h>\n#include <vqm32\\mono.h>\n#include <vqm32\\portio.h>\n#include <vqm32\\profile.h>\n#include <vqm32\\targa.h>\n#include <vqm32\\compress.h>\n#include <vqm32\\video.h>\n#include <vqm32\\palette.h>\n#include <vqm32\\vesavid.h>\n#include <vqm32\\vesablit.h>\n#include <vqm32\\graphics.h>\n#include <vqm32\\mixfile.h>\n#include <vqm32\\crc.h>\n#include <vqm32\\huffman.h>\n#include <vqm32\\mem.h>\n\n#endif /* VQMALL_H */\n\n"
  },
  {
    "path": "WINVQ/VQM32/AUDUNZAP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     audunzap.asm \n;*\n;* DESCRIPTION\n;*     Audio uncompress (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Joe L. Bostic\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     February 9, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     AudioUnzap - Uncompress zapped audio sample.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\nCODE_2BIT\tEQU\t0\nCODE_4BIT\tEQU\t1\nCODE_RAW\tEQU\t2\nCODE_SILENCE\tEQU\t3\nMAGICNUMBER\tEQU\t00000DEAFh\nMAGICNUMBER2\tEQU\t0BABEBABEh\n\n_2bitdecode\tDB\t-2,-1,0,1\n_4bitdecode\tDB\t-9,-8,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,8\n\n;****************************************************************************\n;*\n;* NAME\n;*     AudioUnzap - Uncompress zapped audio sample.\n;*\n;* SYNOPSIS\n;*     Size = AudioUnzap(Source, Dest, Size)\n;*\n;*     long AudioUnzap(void *, void *, long);\n;*\n;* FUNCTION\n;*     Decompress the zapped audio sample data into a buffer.\n;*\n;* INPUTS\n;*     Source - Pointer to encoded audio data.\n;*     Dest   - Pointer to buffer to decompress into.\n;*     Size   - Maximum size of dest buffer.\n;*\n;* RESULT\n;*     Size - Number of uncompressed bytes.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC AudioUnzap:NEAR\n\tPROC\tAudioUnzap C NEAR USES ebx ecx edx esi edi\n\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tcount:DWORD\n\n\tLOCAL\tprevious:BYTE\n\tLOCAL\tincount:DWORD\n\n\tmov\t[incount],0\t;Bytes read from source\n\n;\tSource, Dest and count must be valid.\n\n;\tcmp\t[source],0\n;\tje\t??fini\n\n;\tcmp\t[dest],0\n;\tje\t??fini\n\n;\tcmp\t[count],0\n;\tje\t??fini\n\n\tmov\tesi,[source]\t;Pointer to source data.\n\tmov\tedi,[dest]\t;Pointer to destination data.\n\tmov\tecx,[count]\t;Number of bytes to fill dest buffer.\n\tmov\tdl,080h\t;Previous sample (starting value).\n\tcld\n\n??mainloop:\n\tcmp\tecx,0\t;If dest full then exit\n\tjle\t??fini\n\n\txor\teax,eax\n\tmov\tal,[esi]\t;Get code byte\n\tinc\t[incount]\n\tinc\tesi\n\tshl\teax,2\t;AH contains code.\n\tshr\tal,2\t;AL contains sub-code data.\n\n\tcmp\tah,CODE_RAW\t;Raw sequence?\n\tjne\tshort ??try4bit\n\n;\tThe code contains either a 5 bit delta or a count of\n;\traw samples to dump out.\n\n\ttest\tal,00100000b\n\tje\tshort ??justraw\n\n;\tThe lower 5 bits are actually a signed delta.\n;\tSign extend the delta and add it to the stream.\n\n\tshl\tal,3\n\tsar\tal,3\n\tadd\tdl,al\n\tmov\t[edi],dl\n\tdec\tecx\n\tinc\tedi\n\tjmp\t??mainloop\n\n;\tThe lower 5 bits hold a count of the number of raw\n;\tsamples that follow this code. Dump these samples to\n;\tthe output buffer.\n\n??justraw:\n\tmov\tebx,ecx\n\txor\tah,ah\n\tinc\tal\n\tmov\tecx,eax\n\tshr\tecx,1\n\trep\tmovsw\n\tadc\tecx,ecx\n\trep\tmovsb\n\tmov\tecx,ebx\n\tadd\t[incount],eax\n\tsub\tecx,eax\n\tdec\tedi\n\tmov\tdl,[edi]\t;Set \"previous\" value.\n\tinc\tedi\n\tjmp\t??mainloop\n\n;\tCheck to see if this is a 4 bit delta code sequence.\n\n??try4bit:\n\tinc\tal\t;Following codes use AL+1\n\tcmp\tah,CODE_4BIT\n\tjne\tshort ??try2bit\n\n;\tA sequence of 4bit deltas follow. AL equals the\n;\tnumber of nibble packed delta bytes to process.\n\n??bit4loop:\n\tmov\tah,[esi]\t;Fetch nibble packed delta codes\n\tmov\tbl,ah\n\tinc\t[incount]\n\tinc\tesi\n\n;\tAdd first delta to 'previous' sample already in DL.\n\n\tand\tebx,00001111b\n\tadd\tdl,[_4bitdecode+ebx]\n\tpushf\n\tcmp\t[_4bitdecode+ebx],0\n\tjl\tshort ??neg1\n\n\tpopf\n\tjnc\tshort ??ok1\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok1\n\n??neg1:\n\tpopf\n\tjc\tshort ??ok1\n\n\txor\tdl,dl\n\n??ok1:\n\tmov\tdh,dl\t;DH now holds new 'previous' sample.\n\tmov\tbl,ah\n\tshr\tbl,4\n\tadd\tdh,[_4bitdecode+ebx]\n\tpushf\n\tcmp\t[_4bitdecode+ebx],0\n\tjl\tshort ??neg2\n\n\tpopf\n\tjnc\tshort ??ok2\n\n\tmov\tdh,0FFh\n\tjmp\tshort ??ok2\n\n??neg2:\n\tpopf\n\tjc\tshort ??ok2\n\n\txor\tdh,dh\n\n??ok2:\n\tmov\t[edi],dx\t;Output the two sample bytes\n\tsub\tecx,2\n\tadd\tedi,2\n\n;\tPut the correct 'previous' sample in DL where it belongs.\n\n\tmov\tdl,dh\n\n;\tIf there are more deltas to process then loop back.\n\n\tdec\tal\n\tjnz\tshort ??bit4loop\n\tjmp\t??mainloop\n\n;\tCheck to see if 2 bit deltas need to be processed.\n\n??try2bit:\n\tcmp\tah,CODE_2BIT\n\tjne\t??zerodelta\n\n;\tA sequence of 2bit deltas follow.  AL equals the number of \n;\tpacked delta bytes to process.\n\n??bit2loop:\n\tmov\tah,[esi]\t;Fetch packed delat codes\n\tinc\t[incount]\n\tinc\tesi\n\n;\tAdd first delta to 'previous' sample already in DL.\n\n\tmov\tbl,ah\n\tand\tebx,000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushf\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg3\n\n\tpopf\n\tjnc\tshort ??ok3\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok3\n\n??neg3:\n\tpopf\n\tjc\tshort ??ok3\n\txor\tdl,dl\n\n??ok3:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,2\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushf\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg4\n\n\tpopf\n\tjnc\tshort ??ok4\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok4\n\n??neg4:\n\tpopf\n\tjc\tshort ??ok4\n\n\txor\tdl,dl\n\n??ok4:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,4\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushf\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg5\n\n\tpopf\n\tjnc\tshort ??ok5\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok5\n\n??neg5:\n\tpopf\n\tjc\tshort ??ok5\n\n\txor\tdl,dl\n\n??ok5:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,6\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushf\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg6\n\n\tpopf\n\tjnc\tshort ??ok6\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok6\n\n??neg6:\n\tpopf\n\tjc\tshort ??ok6\n\n\txor\tdl,dl\n\n??ok6:\n\tror\tedx,8\n\tmov\t[edi],edx\t;Output two sample bytes\n\tsub\tecx,4\n\tadd\tedi,4\n\n;\tPut the correct 'previous' sample in DL where it belongs.\n\n\trol\tedx,8\n\n;\tIf there are more deltas to process then loop back.\n\n\tdec\tal\n\tjnz\t??bit2loop\n\tjmp\t??mainloop\n\n;\tThere is a run of zero deltas.  Zero deltas merely duplicate\n;\tthe 'previous' sample the requested number of times.\n\n??zerodelta:\n\txor\tebx,ebx\n\tmov\tbl,al\n\tmov\tal,dl\n\tsub\tecx,ebx\n\txchg\tecx,ebx\n\trep\tstosb\n\tmov\tecx,ebx\n\tjmp\t??mainloop\n\n??fini:\n\tmov\teax,[incount]\n\tret\n\n\tENDP\tAudioUnzap\n\n\tEND\n\n"
  },
  {
    "path": "WINVQ/VQM32/AUDZAP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Audzap.c\n*\n* DESCRIPTION\n*     Lossy audio compression. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Joe L. Bostic\n*      \n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     AudioZap - Compress audio sample data.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <mem.h>\n#include \"compress.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n#define\tMIN(a,b) (((a)<(b)) ? (a) : (b))\n#define\tMAX(a,b) (((a)>(b)) ? (a) : (b))\n\ntypedef enum {\n\tCODE_2BIT,    /* Bit packed 2 bit delta. */\n\tCODE_4BIT,    /* Nibble packed 4 bit delta. */\n\tCODE_RAW,     /* Raw sample. */\n\tCODE_SILENCE  /* Run of silence. */\n} SCodeType;\n\nchar _2bitencode[5] = {\n\t0,1,2,3\n};\n\nlong _2bitdecode[4] = {\n\t-2,-1,0,1\n};\n\nchar _4bitencode[19] = {\n\t0,1,2,2,3,4,5,6,7,(8),\n\t8,9,10,11,12,13,13,14,15\n};\n\nlong _4bitdecode[16] = {\n\t-9,-8,-6,-5,-4,-3,-2,\n\t-1,0,1,2,3,4,5,6,8\n};\n\n\n/****************************************************************************\n*\n* NAME\n*     AudioZap - Compress audio sample data.\n*\n* SYNOPSIS\n*     Size = AudioZap(Source, Dest, Size)\n*\n*     long AudioZap(void *, void *, long);\n*\n* FUNCTION\n*     NOTE - If the compressed size is equal to or greater than the original\n*     size then the data could not be compressed and the uncompressed data\n*     should be written.\n*\n* INPUTS\n*     Source - Pointer to buffer containing audio sample data.\n*     Dest   - Pointer to buffer to put encoded data.\n*     Size   - Number of bytes to compress.\n*\n* RESULT\n*     Size - Size in bytes of encoded data.\n*\n****************************************************************************/\n\nlong AudioZap(void *source, void *dest, long size)\n{\n\tunsigned char *s = (unsigned char *)source;\n\tunsigned char *d = (unsigned char *)dest;\n\tlong          delta;\n\tunsigned long previous = 0x80;\n\tlong          outcount = 0;\n\tunsigned char *s4;\n\tunsigned long p4;\n\tlong          max4;\n\tunsigned char *lastraw = 0;\n\tlong          osize = size;\n\tunsigned long i;\n\tunsigned long dd;\n\n\t/* Reduce very small amplitudes to silence.  Usually a rather large\n\t * portion of a sample is hovering around the silence value.  This is\n\t * due, in part, to the artifacting of the sample process.  These low\n\t * amplitudes are not audible.\n\t */\n\tmax4 = size;\n\ts = (unsigned char *)source;\n\n\twhile (size > 0 && outcount < osize) {\n\n\t\t/* First check for runs of zero deltas.  If a run of at least\n\t\t * any can be found, then output it.\n\t\t */\n\t\ts4 = s;\n\t\tmax4 = MIN(63 + 1, size);\n\n\t\tfor (i = 0; i < max4; i++) {\n\t\t\tif (previous != *s4++)\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/* When there is a code transition, terminate any run of raw\n\t\t * samples.\n\t\t */\n\t\tif (i > 2) {\n\t\t\tlastraw = 0;\n\t\t\t*d++ = ((i - 1)|(CODE_SILENCE << 6));\n\t\t\toutcount++;\n\t\t\ts += i;\n\t\t\tsize -= i;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/* If there are fewer than 4 samples remaining, then using delta\n\t\t * compression is inefficient.  Just drop into the raw routine\n\t\t */\n\t\tif (size > 4) {\n\t\t\ts4 = s;\n\t\t\tp4 = previous;\n\n\t\t\t/* Find out the number of lossless 2 bit deltas available.  These\n\t\t\t * deltas are always present in quads.  The compressed code is\n\t\t\t * the delta quad count followed by the deltas in bit packed bytes.\n\t\t\t */\n\t\t\tmax4 = MIN(64L * 4L + 4L + 4L, size);\n\n\t\t\tfor (i = 0; i < max4; i++) {\n\t\t\t\tdelta = (((int)*s4++) - p4);\n\n\t\t\t\tif ((delta < -2) || (delta > 1)) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tp4 += _2bitdecode[_2bitencode[delta + 2]];\n\n\t\t\t\tif (((signed)p4) < 0) {\n\t\t\t\t\tp4 = 0;\n\t\t\t\t}\n\n\t\t\t\tif (((signed)p4) > 255) {\n\t\t\t\t\tp4 = 255;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ti >>= 2;  // Delta 2 always occur in quads -- force this.\n\n\t\t\t/* If there is the minimum benificial number of delta 2s available,\n\t\t\t * then compress them.\n\t\t\t */\n\t\t\tif (i) {\n\n\t\t\t\t/* When there is a code transition, terminate any run of raw\n\t\t\t\t * samples.\n\t\t\t\t */\n\t\t\t\tlastraw = 0;\n\n\t\t\t\t/* Output the delta 4 pair count.  This is the number of pairs\n\t\t\t\t * minus the 'free' two pairs already assumed to be there.\n\t\t\t\t */\n\t\t\t\ti = MIN(i, (63 + 1));\n\t\t\t\t*d++ = ((i - 1)|(CODE_2BIT << 6));\n\t\t\t\toutcount++;\n\n\t\t\t\tfor (dd = 0; dd < i; dd++) {\n\t\t\t\t\tint delta1, delta2, delta3, delta4;\n\n\t\t\t\t\tdelta1 = _2bitencode[((((int)*s++) - previous) + 2)];\n\t\t\t\t\tprevious += _2bitdecode[delta1];\n\n\t\t\t\t\tif (((signed)previous) < 0) {\n\t\t\t\t\t\tprevious = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (((signed)previous) > 255) {\n\t\t\t\t\t\tprevious = 255;\n\t\t\t\t\t}\n\n\t\t\t\t\tsize--;\n\t\t\t\t\tdelta2 = _2bitencode[((((int)*s++) - previous) + 2)];\n\t\t\t\t\tprevious += _2bitdecode[delta2];\n\n\t\t\t\t\tif (((signed)previous) < 0) {\n\t\t\t\t\t\tprevious = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (((signed)previous) > 255) {\n\t\t\t\t\t\tprevious = 255;\n\t\t\t\t\t}\n\n\t\t\t\t\tsize--;\n\t\t\t\t\tdelta3 = _2bitencode[((((int)*s++) - previous) + 2)];\n\t\t\t\t\tprevious += _2bitdecode[delta3];\n\n\t\t\t\t\tif (((signed)previous) < 0) {\n\t\t\t\t\t\tprevious = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (((signed)previous) > 255) {\n\t\t\t\t\t\tprevious = 255;\n\t\t\t\t\t}\n\n\t\t\t\t\tsize--;\n\t\t\t\t\tdelta4 = _2bitencode[((((int)*s++) - previous) + 2)];\n\t\t\t\t\tprevious += _2bitdecode[delta4];\n\n\t\t\t\t\tif (((signed)previous) < 0) {\n\t\t\t\t\t\tprevious = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (((signed)previous) > 255) {\n\t\t\t\t\t\tprevious = 255;\n\t\t\t\t\t}\n\n\t\t\t\t\tsize--;\n\t\t\t\t\t*d++ = ((delta4 << 6)|(delta3 << 4)|(delta2 << 2)|delta1);\n\t\t\t\t\toutcount++;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t} else {\n\t\t\t\ts4 = s;\n\t\t\t\tp4 = previous;\n\n\t\t\t\t/* Find out the number of lossless 4 bit deltas follow.  These\n\t\t\t\t * deltas are always present in pairs.  The compressed code is\n\t\t\t\t * the delta pair count followed by the deltas in nibble packed\n\t\t\t\t * bytes.\n\t\t\t\t */\n\t\t\t\tmax4 = MIN(64L * 2L + 4L + 4L, size);\n\n\t\t\t\tfor (i = 0; i < max4; i++) {\n\t\t\t\t\tdelta = (((int)*s4++) - p4);\n\n\t\t\t\t\tif (delta < -9 || delta >= 9) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tp4 += _4bitdecode[_4bitencode[(delta + 9)]];\n\n\t\t\t\t\tif (((signed)p4) < 0) {\n\t\t\t\t\t\tp4 = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (((signed)p4) > 255) {\n\t\t\t\t\t\tp4 = 255;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\ti >>= 1; // Delta 4 always occur in pairs -- force this.\n\n\t\t\t\t/* If there is the minimum benificial number of delta 4s available,\n\t\t\t\t * then compress them.\n\t\t\t\t */\n\t\t\t\tif (i) {\n\n\t\t\t\t\t/* When there is a code transition, terminate any run of raw\n\t\t\t\t\t * samples.\n\t\t\t\t\t */\n\t\t\t\t\tlastraw = 0;\n\n\t\t\t\t\t/* Output the delta 4 pair count.  This is the number of pairs\n\t\t\t\t\t * minus the 'free' two pairs already assumed to be there.\n\t\t\t\t\t */\n\t\t\t\t\ti = MIN(i, (63 + 1));\n\t\t\t\t\t*d++ = ((i - 1)|(CODE_4BIT << 6));\n\t\t\t\t\toutcount++;\n\n\t\t\t\t\tfor (dd = 0; dd < i; dd++) {\n\t\t\t\t\t\tint delta1, delta2;\n\n\t\t\t\t\t\tdelta1 = _4bitencode[((((int)*s++) - previous) + 9)];\n\t\t\t\t\t\tprevious += _4bitdecode[delta1];\n\n\t\t\t\t\t\tif (((signed)previous) < 0) {\n\t\t\t\t\t\t\tprevious = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (((signed)previous) > 255) {\n\t\t\t\t\t\t\tprevious = 255;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tsize--;\n\t\t\t\t\t\tdelta2 = _4bitencode[((((int)*s++) - previous) + 9)];\n\t\t\t\t\t\tprevious += _4bitdecode[delta2];\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (((signed)previous) < 0) {\n\t\t\t\t\t\t\tprevious = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (((signed)previous) > 255) {\n\t\t\t\t\t\t\tprevious = 255;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tsize--;\n\t\t\t\t\t\t*d++ = ((delta2 << 4)|(delta1 & 0x0F));\n\t\t\t\t\t\toutcount++;\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Raw output since deltas were unsuccessful.  If this is a run\n\t\t * of raw output, then merely tack it onto the run rather than\n\t\t * create a new code sequence.\n\t\t */\n\t\tif (lastraw) {\n\t\t\t*lastraw = ((*lastraw) + 1);\n\n\t\t\t/* There is only so much a run code can accomodate.  If the limit\n\t\t\t * has been reached, then terminate this code.  A new one will be\n\t\t\t * created if necessary.\n\t\t\t */\n\t\t\tif ((*lastraw & 0x1F) == 0x1F) {\n\t\t\t\tlastraw = 0;\n\t\t\t}\n\t\t} else {\n\t\t\t\n\t\t\t/* If there is no current raw dump of samples, then check to see if\n\t\t\t * this sample can fit into a 5 bit delta.  If it can, then store\n\t\t\t * it as such as a parasite to the \"raw\" code.  This will save a byte\n\t\t\t * for any stray 5 bit deltas that happen along.  It is expected that\n\t\t\t * this is more frequent than 6 or more bit deltas that would necessitate\n\t\t\t * the use of the RAW code.\n\t\t\t */\n\t\t\tdelta = (((int)*s) - previous);\n\n\t\t\tif ((delta >= -16) && (delta <= 15)) {\n\t\t\t\tlastraw = 0;\n\t\t\t\t*d++ = ((CODE_RAW << 6)|0x20|(delta & 0x1F));\n\t\t\t\toutcount++;\n\t\t\t\tprevious = *s++;\n\t\t\t\tsize--;\n\t\t\t\tcontinue;\n\t\t\t} else {\n\t\t\t\tlastraw = d;\n\t\t\t\t*d++ = (CODE_RAW << 6);\n\t\t\t\toutcount++;\n\t\t\t}\n\t\t}\n\n\t\t*d++ = previous = *s++;\n\t\tsize--;\n\t\toutcount++;\n\t}\n\n\t/* Check to see if the compression process actually resulted in smaller\n\t * data size.  In some cases, the 'compressed' data is actually larger.  In\n\t * this case, just output the raw frame.  If the compressed and actual frame\n\t * size match, then it is presumed that no compression occurs.\n\t */\n\tif (outcount >= osize) {\n\t\tmemcpy(dest, source, (size_t)osize);\n\t\toutcount = osize;\n\t}\n\n\treturn(outcount);\n}\n\n"
  },
  {
    "path": "WINVQ/VQM32/BCC32.CFG",
    "content": "-c\n-3\n-d\n-H=c:\\projects\\vqm32\\obj\\headers.sym\n-wpro\n-weas\n-wpre\n-IC:\\PROJECTS\\INCLUDE;C:\\DEV\\BC4\\INCLUDE;C:\\DEV\\TNT\\INCLUDE\n-DPHARLAP_TNT=1\n"
  },
  {
    "path": "WINVQ/VQM32/CAPTOKEN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     captoken.c\n*\n* DESCRIPTION\n*     Tokenize a caption script for playback processing.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 26, 1995\n*\n****************************************************************************/\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <errno.h>\n#include <string.h>\n#include <ctype.h>\n#include \"captoken.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n#define STRING_LENGTH 256\n#define PADSIZE(size) (((size)+1)&(~1))\n\ntypedef enum {\n\tTOKEN_NULL = 0,\n\tTOKEN_BGCOL,\n\tTOKEN_FGCOL,\n\tTOKEN_XPOS,\n\tTOKEN_YPOS,\n\tTOKEN_ABS,\n\tTOKEN_LEFT,\n\tTOKEN_RIGHT,\n\tTOKEN_CENTER,\n\tTOKEN_FLASH,\n\tTOKEN_CPF,\n\tTOKEN_END\n} TokenTag;\n\ntypedef struct _Token {\n\tchar *name;\n\tlong tag;\n} Token;\n\n/* Script tokens:\n * BG/BGCOL     - Background pen color (EX: BG=<color name>)\n * FG/FGCOL     - Foreground pen color (EX: FG=<color name>)\n * X/XPOS       - X pixel position of text (EX: X=<pixel cord>)\n * Y/YPOS       - Y pixel position of text (EX: Y=<pixel cord>)\n * ABS/ABSOLUTE - Absolute justification\n * LEFT         - Left side justification\n * RIGHT        - Right side justification\n * CENTER       - Center justification\n * FLASH        - Enable flashing of text\n * CPF          - Print rate in characters per frame (EX: CPF=<rate>)\n * END          - Terminate compilation of caption script\n */\nToken tokens[] = {\n\t\"BG\", TOKEN_BGCOL,\n\t\"BGCOL\", TOKEN_BGCOL,\n\t\"FG\", TOKEN_FGCOL,\n\t\"FGCOL\", TOKEN_FGCOL,\n\t\"X\", TOKEN_XPOS,\n\t\"XPOS\", TOKEN_XPOS,\n\t\"Y\", TOKEN_YPOS,\n\t\"YPOS\", TOKEN_YPOS,\n\t\"ABS\", TOKEN_ABS,\n\t\"ABSOLUTE\", TOKEN_ABS,\n\t\"LEFT\", TOKEN_LEFT,\n\t\"RIGHT\", TOKEN_RIGHT,\n\t\"CENTER\", TOKEN_CENTER,\n\t\"FLASH\", TOKEN_FLASH,\n\t\"CPF\", TOKEN_CPF,\n\t\"END\", TOKEN_END,\n\tNULL, TOKEN_NULL,\n};\n\nToken colors[] = {\n\t\"BLACK\", 0,\n\t\"WHITE\", 251,\n\t\"RED\", 252,\n\t\"GREEN\", 253,\n\t\"SHADOW\", 254,\n\t\"CYCLE\", 255,\n\tNULL, -1,\n};\n\n/* Prototypes. */\nstatic long GetColorNum(char *name);\nstatic long IsNumeric(char *string);\nstatic void FormatString(char *string);\n\n\n/****************************************************************************\n*\n* NAME\n*     BuildCaptions - Compile a caption script.\n*\n* SYNOPSIS\n*     Size = BuildCaptions(Name, Buffer)\n*\n*     long BuildCaptions(char *, char *);\n*\n* FUNCTION\n*     Generate a compiled caption script for use in VQA playback.\n*\n* INPUTS\n*     Name   - Name of caption script file to compile.\n*     Buffer - Buffer to put compiled captions into.\n*\n* RESULT\n*     Size - Size of compiled captions (in bytes).\n*\n****************************************************************************/\n\nlong BuildCaptions(char *name, char *buffer)\n{\n\tFILE        *fp;\n\tchar        *ptr;\n\tchar        *ptr1;\n\tlong        size = 0;\n\tlong        error;\n\tlong        i;\n\tlong        tag;\n\tCaptionText caption;\n\tchar        string[STRING_LENGTH];\n\n\t/* Initialize the caption parameters. */\n\tmemset(&caption, 0, sizeof(CaptionText));\n\n\t/* Open the captions script file. */\n\tfp = fopen(name, \"r\");\n\n\tif (fp != NULL) {\n\t\terror = 0;\n\n\t\twhile (!error) {\n\t\t\tif (fgets(string, STRING_LENGTH, fp) == NULL) {\n\t\t\t\tif (errno == 0) {\n\t\t\t\t\terror = 1;\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\n\t\t\t/* Replace the newline with a NULL terminator. */\n\t\t\tstring[strlen(string) - 1] = 0;\n\n\t\t\t/* Ignore comment lines. */\n\t\t\tif (string[0] == ';') continue;\n\n\t\t\tptr = strtok(string, \"=\");\n\n\t\t\tif (ptr != NULL) {\n\n\t\t\t\t/* Check for a comma */\n\t\t\t\tptr1 = strchr(ptr, ',');\n\n\t\t\t\tif (ptr1 != NULL) {\n\t\t\t\t\t*ptr1++ = 0;\n\t\t\t\t}\n\n\t\t\t\t/* Is this a frame number. */\n\t\t\t\tif (IsNumeric(ptr) && IsNumeric(ptr1)) {\n\t\t\t\t\ti = atoi(ptr);\n\n\t\t\t\t\t/* Frames must be defined in ascending order. */\n\t\t\t\t\tif ((unsigned short)i >= caption.OnFrame) {\n\t\t\t\t\t\tcaption.OnFrame = i;\n\t\t\t\t\t\tcaption.OffFrame = atoi(ptr1);\n\t\t\t\t\t\tcaption.Size = sizeof(CaptionText);\n\n\t\t\t\t\t\t/* Get caption text. */\n\t\t\t\t\t\tptr = strtok(NULL, \"\");\n\n\t\t\t\t\t\tif (ptr != NULL) {\n\t\t\t\t\t\t\tFormatString(ptr);\n\t\t\t\t\t\t\ti = strlen(ptr) + 1;\n\t\t\t\t\t\t\tcaption.Size += PADSIZE(i);\n\t\t\t\t\t\t\tsize += caption.Size;\n\n\t\t\t\t\t\t\t/* Copy the caption structure. */\n\t\t\t\t\t\t\tmemcpy(buffer, &caption, sizeof(CaptionText));\n\t\t\t\t\t\t\tbuffer += sizeof(CaptionText);\n\n\t\t\t\t\t\t\t/* Copy the caption text. */\n\t\t\t\t\t\t\tmemcpy(buffer, ptr, i);\n\t\t\t\t\t\t\tbuffer += i;\n\n\t\t\t\t\t\t\t/* WORD align */\n\t\t\t\t\t\t\tif (PADSIZE(i) > i) {\n\t\t\t\t\t\t\t\t*buffer++ = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\terror = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/* Search for matching token. */\n\t\t\t\t\ttag = TOKEN_NULL;\n\t\t\t\t\ti = 0;\n\n\t\t\t\t\twhile (tokens[i].name != NULL) {\n\t\t\t\t\t\tif (strcmpi(tokens[i].name, ptr) == 0) {\n\t\t\t\t\t\t\ttag = tokens[i].tag;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ti++;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Get the data element. */\n\t\t\t\t\tptr = strtok(NULL, \"\");\n\n\t\t\t\t\tswitch (tag) {\n\t\t\t\t\t\tcase TOKEN_BGCOL:\n\t\t\t\t\t\t\tcaption.BgPen = (char)GetColorNum(ptr);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_FGCOL:\n\t\t\t\t\t\t\tcaption.FgPen = (char)GetColorNum(ptr);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_XPOS:\n\t\t\t\t\t\t\tcaption.Xpos = (unsigned short)atoi(ptr);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_YPOS:\n\t\t\t\t\t\t\tcaption.Ypos = (unsigned short)atoi(ptr);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_ABS:\n\t\t\t\t\t\t\tcaption.Flags &= ~CTF_JUSTIFY;\n\t\t\t\t\t\t\tcaption.Flags |= CTF_ABS;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_LEFT:\n\t\t\t\t\t\t\tcaption.Flags &= ~CTF_JUSTIFY;\n\t\t\t\t\t\t\tcaption.Flags |= CTF_LEFT;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_RIGHT:\n\t\t\t\t\t\t\tcaption.Flags &= ~CTF_JUSTIFY;\n\t\t\t\t\t\t\tcaption.Flags |= CTF_RIGHT;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_CENTER:\n\t\t\t\t\t\t\tcaption.Flags &= ~CTF_JUSTIFY;\n\t\t\t\t\t\t\tcaption.Flags |= CTF_CENTER;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_FLASH:\n\t\t\t\t\t\t\tif (strcmpi(ptr, \"OFF\") == 0) {\n\t\t\t\t\t\t\t\tcaption.Flags &= ~CTF_FLASH;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcaption.Flags |= CTF_FLASH;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOKEN_CPF:\n\t\t\t\t\t\t\tcaption.CPF = (char)atoi(ptr);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t/* Termination captions */\n\t\t\t\t\t\tcase TOKEN_END:\n\t\t\t\t\t\t\tcaption.Size = sizeof(CaptionText);\n\t\t\t\t\t\t\tcaption.OnFrame = (unsigned short)-1;\n\t\t\t\t\t\t\tmemcpy(buffer, &caption, sizeof(CaptionText));\n\t\t\t\t\t\t\tbuffer += sizeof(CaptionText);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Close the script file. */\n\t\tfclose(fp);\n\t}\n\n\treturn (size);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetColorNum - Get the color number from the color name.\n*\n* SYNOPSIS\n*     Color = GetColorNum(Name)\n*\n*     long GetColorNum(char *);\n*\n* FUNCTION\n*     Look the color number that corresponds to the color name.\n*\n* INPUTS\n*     Name - Name of color.\n*\n* RESULT\n*     Color - Color number.\n*\n****************************************************************************/\n\nstatic long GetColorNum(char *name)\n{\n\tlong color = -1;\n\tlong i;\n\n\ti = 0;\n\n\t/* Scan for a matching name and return the corresponding color number. */\n\twhile (colors[i].name != NULL) {\n\t\tif (strcmpi(colors[i].name, name) == 0) {\n\t\t\tcolor = colors[i].tag;\n\t\t}\n\n\t\ti++;\n\t}\n\n\treturn (color);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     IsNumeric - Check if a string is numeric.\n*\n* SYNOPSIS\n*     Condition = IsNumeric(String)\n*\n*     long IsNumeric(char *);\n*\n* FUNCTION\n*     Interogate the string to see if it represents a numeric value. Each\n*     byte of the string must be between 0x30 and 0x39 inclusively.\n*\n* INPUTS\n*     String - String to check.\n*\n* RESULT\n*     Condition - 1 if numeric, 0 if not.\n*\n****************************************************************************/\n\nstatic long IsNumeric(char *string)\n{\n\tlong flag = 1;\n\n\t/* Ignore any proceeding sign designation. */\n\tif ((*string == '-') || (*string == '+')) {\n\t\tstring++;\n\t}\n\n\t/* Check to see if every byte in the string is a digit. */\n\twhile (flag && (*string != 0)) {\n\t\tif (!isdigit(*string++)) {\n\t\t\tflag = 0;\n\t\t}\n\t}\n\n\treturn (flag);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     FormatString - Parse any format codes in the string.\n*\n* SYNOPSIS\n*     FormatString(String)\n*\n*     void FormatString(char *);\n*\n* FUNCTION\n*     Format a string with any embedded format commands contained in the\n*     input string.\n*\n*     Supported format commands:\n*       /n - Insert carriage return. (0x0D)\n*       /r - Insert carriage return. (0x0D)\n*       // - Literal backslash.\n*\n* INPUTS\n*     String - Pointer to string to format.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void FormatString(char *string)\n{\n\tchar *ptr;\n\n\t/* NULL strings are invalid. */\n\tif (string != NULL) {\n\t\tptr = string;\n\n\t\t/* Scan the string for embedded format commands. */\n\t\twhile ((ptr = strchr(ptr, '/')) != NULL) {\n\t\t\tswitch (*(ptr + 1)) {\n\n\t\t\t\t/* Carriage return. */\n\t\t\t\tcase 'n':\n\t\t\t\tcase 'r':\n\t\t\t\t\t*ptr = 0x0D;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/* Literal backslash. */\n\t\t\t\tcase '/':\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/* Remove the unwanted character. */\n\t\t\tstrcpy((ptr + 1), (ptr + 2));\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "WINVQ/VQM32/CAPTOKEN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMCAPTOKEN_H\n#define VQMCAPTOKEN_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     captoken.h\n*\n* DESCRIPTION\n*     Text caption script definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 26, 1995\n*\n****************************************************************************/\n\n/* CaptionText: This structure describes a line of text to be displayed\n *              with the video/audio.\n *\n * Size     - Size of caption in bytes.\n * OnFrame  - Frame number to display caption.\n * OffFrame - Frame number to clear caption.\n * Flags    - Display modifiers.\n * CPF      - Characters to draw per frame.\n * Xpos     - X pixel position to display caption.\n * Ypos     - Y pixel position to display caption.\n * BgPen    - Background pen to use.\n * FgPen    - Foreground pen to use.\n * Text     - Text string to display. (WORD aligned)\n */\ntypedef struct _CaptionText {\n\tunsigned short Size;\n\tunsigned short OnFrame;\n\tunsigned short OffFrame;\n\tunsigned char  Flags;\n\tchar           CPF;\n\tunsigned short Xpos;\n\tunsigned short Ypos;\n\tchar           BgPen;\n\tchar           FgPen;\n\tchar           Text[];\n} CaptionText;\n\n/* CaptionText flag definitions. */\n#define CTF_JUSTIFY\t(3<<0)  /* Justification field. */\n#define CTF_ABS     (0<<0)  /* Use absolute X,Y positions. */\n#define CTF_CENTER  (1<<0)  /* Justify on Center */\n#define CTF_LEFT    (2<<0)  /* Justify on left */\n#define CTF_RIGHT   (3<<0)  /* Justify on right */\n#define CTF_FLASH   (1<<4)  /* Flash text. */\n\n/* Function prototypes. */\nlong BuildCaptions(char *name, char *buffer);\n\n#endif /* VQMCAPTOKEN_H */\n\n"
  },
  {
    "path": "WINVQ/VQM32/CHRWIDTH.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*---------------------------------------------------------------------------\n*\n* FILE\n*     chrwidth.c\n*\n* DESCRIPTION\n*     Character pixel width.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     June 9, 1995\n*\n*---------------------------------------------------------------------------\n*\n* PUBLIC\n*     Char_Pixel_Width - Get the pixel width of a character.\n*\n****************************************************************************/\n\n#include \"font.h\"\n\n\n/****************************************************************************\n*\n* NAME\n*     Char_Pixel_Width - Get the pixel width of a character.\n*\n* SYNOPSIS\n*     Width = Char_Pixel_Width(Character)\n*\n*     long Char_Pixel_Width(char);\n*\n* FUNCTION\n*     Gets the pixel width of the specified character.\n*\n* INPUTS\n*     Character - Character to get the width for.\n*\n* RESULT\n*     Width - Width in pixels.\n*\n****************************************************************************/\n\n#ifdef __WATCOMC__\nlong __cdecl __saveregs Char_Pixel_Width(char chr)\n#else\n#pragma saveregs\nlong __cdecl Char_Pixel_Width(char chr)\n#endif\n{\n\treturn (*(FontWidthBlockPtr + chr) + FontXSpacing);\n}\n"
  },
  {
    "path": "WINVQ/VQM32/COMPRESS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMCOMP_H\n#define VQMCOMP_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     compress.h\n*\n* DESCRIPTION\n*     Compression definitions. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nunsigned long __cdecl LCW_Compress(char const *source, char *dest,\n\t\tunsigned long length);\nunsigned long __cdecl LCW_Uncompress(char const *source, char *dest,\n\t\tunsigned long length);\nlong AudioZap(void *source, void *dest, long size);\nlong __cdecl AudioUnzap(void *source, void *dest, long);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMCOMP_H */\n\n"
  },
  {
    "path": "WINVQ/VQM32/CRC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     crc.asm\n;*\n;* DESCRIPTION\n;*     CRC checksum calculation.\n;*\n;* PROGRAMMER\n;*     Joe L. Bostic\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     Calculate_CRC - Calculate CRC checksum.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     Calculate_CRC - Calculate CRC checksum.\n;*\n;* SYNOPSIS\n;*     CRC = Calculate_CRC(Buffer, Length)\n;*\n;*     long Calculate_CRC(void *, long);\n;*\n;* FUNCTION\n;*     Compute a CRC checksum for a block of memory.\n;*\n;* INPUTS\n;*     Buffer - Pointer to buffer to calculate CRC for.\n;*     Length - Length of buffer.\n;*\n;* RESULT\n;*     CRC - CRC value.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Calculate_CRC:NEAR\n\tPROC\tCalculate_CRC C NEAR USES esi ebx ecx edx\n\tARG\tbuffer:NEAR PTR\n\tARG\tlength:DWORD\n\n\tmov\tesi,[buffer]\n\tcld\n\n\t; Clear CRC to default (NULL) value.\n\txor\tebx,ebx\n\n\tmov\tecx,[length]\t;Get length of data block\n\tor\tecx,ecx\n\tjz\tshort ??fini\n\n\t; Prepare the length counters.\n\tmov\tedx,ecx\n\tand\tdl,011b\n\tshr\tecx,2\n\n\t; Perform the bulk of the CRC scanning.\n\tor\tecx,ecx\n\tjz\tshort ??remainder\n\n??accumloop:\n\tlodsd\n\trol\tebx,1\n\tadd\tebx,eax\n\tloop\t??accumloop\n\n\t; Handle the remainder bytes.\n??remainder:\n\tor\tdl,dl\n\tjz\tshort ??fini\n\tmov\tecx,edx\n\txor\teax,eax\n\n\tpush\tecx\n??nextbyte:\n\tlodsb\n\tror\teax,8\n\tloop\t??nextbyte\n\tpop\tecx\n\tneg\tecx\n\tadd\tecx,4\n\tshl\tecx,3\n\tror\teax,cl\n\n;??nextbyte:\n;\tshl\teax,8\n;\tlodsb\n;\tloop\t??nextbyte\n\trol\tebx,1\n\tadd\tebx,eax\n\n??fini:\n\tmov\teax,ebx\n\tret\n\n\tENDP\tCalculate_CRC\n\n\tEND\n"
  },
  {
    "path": "WINVQ/VQM32/CRC.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMCRC_H\n#define VQMCRC_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     CRC.h\n*\n* DESCRIPTION\n*     CRC calculation definitions.\n*\n* PROGRAMMER\n*     Joe L. Bostic\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nlong __cdecl Calculate_CRC(void const *buffer, long length);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMCRC_H */\n"
  },
  {
    "path": "WINVQ/VQM32/DRAWCHAR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header:   U:\\vq\\projects\\vqm32\\drawchar.asv   1.1   08 May 1995 10:48:32   DENZIL_LONG  $\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : DRAWCHAR.ASM                             *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : August 20, 1993                          *\n;*                                                                         *\n;*                  Last Update : August 20, 1993   [JLB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\nXPIXEL_MAX\t\tEQU\t320\nYPIXEL_MAX\t\tEQU\t200\n\nFONTINFOBLOCK\t\tEQU\t4\nFONTOFFSETBLOCK\tEQU\t6\nFONTWIDTHBLOCK\tEQU\t8\nFONTDATABLOCK\t\tEQU\t10\nFONTHEIGHTBLOCK\tEQU\t12\n\nFONTINFOMAXHEIGHT\tEQU\t4\nFONTINFOMAXWIDTH\tEQU\t5\n\n\tEXTRN\tC FontPtr:NEAR PTR\n\n;***********************************************************\n; DRAW_CHAR\n;\n; VOID Draw_Char(BYTE fontchar, WORD x_pixel, WORD y_pixel);\n;\n; Draws a character to the screen only if given coordinates that will allow\n; the entire character to be drawn on the screen else will exit.\n; \n; NOTE: This is a routine called by Text_Print.\n;\n;*\n\tGLOBAL\tC Draw_Char:NEAR\n\tPROC\tDraw_Char C NEAR USES eax ebx ecx edx esi edi \n\tARG\tfontchar:DWORD\n\tARG\tx_pixel:DWORD\n\tARG\ty_pixel:DWORD\n\n\tLOCAL\tinfoblock:DWORD\n\tLOCAL\toffsetblock:DWORD\n\tLOCAL\twidthblock:DWORD\n\tLOCAL\theightblock:DWORD\n\tLOCAL\tfwidth:DWORD\n\tLOCAL\tnextline:DWORD\n\tLOCAL\tstartv:BYTE\n\tLOCAL\tdheight:BYTE\n\tLOCAL\twheight:BYTE\n\n\tmov\tesi,[FontPtr]\n\n\t; Set up some working local variables.\n\n\txor\teax,eax\n\tmov\tax,[esi+FONTINFOBLOCK]\t; get offset to info block\n\tmov\t[infoblock],eax\t\t; save offset to info block\n\tmov\tax,[esi+FONTOFFSETBLOCK]\t; get offset to offset block\n\tmov\t[offsetblock],eax\t\t; save offset to offset block\n\tmov\tax,[esi+FONTWIDTHBLOCK]\t; get offset to width block\n\tmov\t[widthblock],eax\t\t; save offset to width block\n\tmov\tax,[esi+FONTHEIGHTBLOCK]\t; get offset to height block\n\tmov\t[heightblock],eax\t\t; save offset to height block\n\n\t; Fetch character data offset -- if NULL then undefined character.\n\n\tmov\tebx,[fontchar]\n\tand\tebx,0FFh\n\tshl\tebx,1\t\t; make word index\n\tadd\tebx,[offsetblock]\t; add offset to offset block\n\txor\tecx,ecx\n\tmov\tcx,[esi+ebx]\t\t; load offset to font data\n\tor\tecx,ecx\n\tjz\t??exit\t\t; is this character a null? if so exit\n\n\t; If the character is off the left/right edge of the screen then abort.\n\n\tmov\tedx,[x_pixel]\n\tcmp\tedx,XPIXEL_MAX\n\tjae\t??exit\n\n\t; If the character is off the top/bottom edge of the screen then abort.\n\n\tmov\tebx,[fontchar]\t\t; get char\n\tand\tebx,0FFh\n\tadd\tebx,[widthblock]\t; add offset to width block\n\txor\teax,eax\n\tmov\tal,[esi+ebx]\t\t; get width for character\n\tmov\t[fwidth],eax\t\t; save char width\n\tadd\teax,edx\t\t; ax = char len + x\n\tcmp\teax,XPIXEL_MAX\n\tja\t??exit\n\n\tmov\tedi,edx\t\t; save xpos in di\n\n\tmov\tedx,[y_pixel]\n\tcmp\tedx,YPIXEL_MAX\n\tjae\t??exit\n\n\tmov\tebx,[infoblock]\t; get offset to offset block\n\txor\teax,eax\n\t\t\t\t; get font max height from info block\n\tmov\tal,[esi+ebx+FONTINFOMAXHEIGHT]\n\tmov\t[wheight],al\t\t; save max height of character\n\tadd\teax,edx\t\t; add height to y pos\n\tcmp\teax,YPIXEL_MAX\t\t; will it go off the bottom\n\tja\t??exit\n\n??vdraw:\n\tmov\tebx,[fontchar]\t\t; get char\n\tand\tebx,0FFh\n\tshl\tebx,1\t\t; make 2 byte index\n\tadd\tebx,[heightblock]\t; add offset to height block\n\tmov\tah,[esi+ebx]\t\t; get start vertical for character\n\tmov\t[startv],ah\t\t; save start vertical for later\n\tmov\tal,[esi+ebx+1]\t\t; get data height for character\n\tmov\t[dheight],al\t\t; save data height for later\n\tadd\tah,al\t\t; add background and data\n\tsub\t[wheight],ah\t\t; remaining background height\n\n\tadd\tesi,ecx\t\t; add font offset to font data\n\n\tpush\tedx\n\tmov\teax,XPIXEL_MAX\n\tmul\tedx\n\tadd\tedi,eax\n\tpop\tedx\n\n\tmov\teax,XPIXEL_MAX\n\tsub\teax,[fwidth]\n\tmov\t[nextline],eax\t\t; ?? to add to index for the nextline\n\n\tadd\tedi,0A0000h\n\tmov\tebx,OFFSET ColorXlat\t; setup up bx for xlat commands\n\txor\tecx,ecx\n\tmov\tcl,[startv]\t\t; number of scan lines that are\n\t\t\t\t; background color\n\tor\tecx,ecx\t\t; if starting vertical is zero\n\tje\tshort ??skiplead\t; skip drawing top background lines\n\n\tmov\tal,0\n\txlat\t[ebx]\t\t; get background color\n\n\tor\tal,al\t\t; check for none zero color\n\tjne\tshort ??lheight\t; update background color\n\n\tpush\tedx\n\tmov\teax,XPIXEL_MAX\n\tmul\tecx\n\tadd\tedi,eax\n\tpop\tedx\n\n\tmov\tebx,OFFSET ColorXlat\t; restore bx for xlat commands\n\tjmp\tSHORT ??skiplead\n\n??lheight:\n\tmov\tedx,[fwidth]\t\t; width of char\n\n??lwidth:\n\tstosb\t\t\t; write out line of pixels for width\n\tdec\tedx\n\tjne\t??lwidth\n\n??lnext:\n\tadd\tedi,[nextline]\t\t; goto next line at the start of char\n\tloop\t??lheight\t\t; any more lines\n\n??skiplead:\n\tmov\tcl,[dheight]\t\t; number of scan lines that are data\n\tor\tecx,ecx\t\t; is there any data to be drawn\n\tje\tshort ??exit\n\n??vheight:\n\tmov\tedx,[fwidth]\t\t; width of char\n\n??vwidth:\n\tlodsb\t\t\t\t; get byte value from font data\n\tmov\tah,al\t\t\t; save hinibble\n\tand\tal,00FH\t\t\t; get lonibble\n\txlat\t[ebx]\t\t\t; get new color\n\tor\tal,al\n\tje\tshort ??chklowidth\t\t; skip color zero\n\n\tmov\t[edi],al\t\t; write out pixel of lonibble\n\n??chklowidth:\n\tinc\tedi\n\tdec\tedx\n\tje\tshort ??vnext\t\t\t; check if done with width of char\n\n\tmov\tal,ah\t\t\t; get byte value\n\tand\tal,0F0H\t\t\t; get hinibble\n\txlat\t[ebx]\t\t\t; get new color\n\tor\tal,al\n\tje\tshort ??chkhiwidth\t\t; skip color zero\n\n\tmov\t[edi],al\t\t; write out pixel of hinibble\n\n??chkhiwidth:\n\tinc\tedi\n\tdec\tedx\n\tjne\t??vwidth\t\t; check if done with width of char\n\n??vnext:\n\tadd\tedi,[nextline]\t\t; next line at start of char\n\tloop\t??vheight\t\t; any more lines\n\n\n??trail:\n\tmov\tcl,[wheight]\t\t; remaining height of background color\n\tor\tecx,ecx\t\t\t; if trailing height is zero\n\tjle\tshort ??exit\t\t\t; skip drawing bottom background lines\n\n\tmov\tal,0\n\txlat\t[ebx]\t\t\t; get background color\n\tor\tal,al\t\t\t; check for color zero\n\tje\tshort ??exit\t\t\t; skip drawing\n\n??theight:\n\tmov\tedx,[fwidth]\t\t; width of char\n\n??twidth:\n\tstosb\t\t\t\t; write out line of pixels for width\n\tdec\tedx\n\tjne\t??twidth\n\n??tnext:\n\tadd\tedi,[nextline]\t\t; next line at start of char\n\tloop\t??theight\t\t; any more lines\n\n\n??exit:\n\tret\n\n\tENDP\tDraw_Char\n\n;***********************************************************\n\n\n;***********************************************************\n; SET_FONT_PALETTE_RANGE\n;\n; VOID Set_Font_Palette_Range(VOID *palette, WORD start, WORD end);\n;\n; This routine changes the local Draw_Char color translation table\n; with the color numbers in palette.\n;\n; Bounds Checking: forces start and end to a range of 0-15\n;*\n\tGLOBAL\tC Set_Font_Palette_Range:NEAR\n\tPROC\tSet_Font_Palette_Range C NEAR USES eax ebx ecx edi esi\n\tARG\tpalette:NEAR PTR\n\tARG\tstart:DWORD\n\tARG\tendval:DWORD\n\n\tcld\n\tmov\tesi,[palette]\n\tmov\tebx,[start]\n\tand\tebx,0FH\t\t\t; value 0-15\n\n\tmov\tecx,[endval]\n\tand\tecx,0FH\t\t\t; value 0-15\n\n\tcmp\tecx,ebx\t\t\t; if end < start then exit\n\tjl\tshort ??exit\n\n\tsub\tecx,ebx\t\t\t; number of colors = end - start + 1\n\tinc\tecx\n\n\tmov\tedi,OFFSET ColorXlat\t; get start of xlat table\n\tadd\tedi,ebx\t\t\t; add starting offset\n\tshl\tebx,4\t\t\t; multiply start offset by 16\n\tadd\tebx,OFFSET ColorXlat\t; add start of xlat table\n\n; updates 0-15 for lonibble xlat\n; updates 0,16,32,...,240 for hinibble xlat\n\n??setpal:\n\tlodsb\t\t\t\t; get color number\n\tstosb\t\t\t\t; save color number for lonibble xlat\n\tmov\t[ebx],al\t\t; save color number for hinibble xlat\n\tadd\tebx,010H\t\t\t; add 16 to index for hinibble offset\n\tloop\t??setpal\n\n??exit:\n\tret\n\n\tENDP\tSet_Font_Palette_Range\n\n;***********************************************************\n\n\n;***********************************************************\n; DRAW_CHAR_SETUP\n;\n; VOID Draw_Char_Setup(VOID);\n;\n; This routine sets up code segment variables for Draw_Char.\n; \n; NOTE: This is a routine called by Set_Font.\n;\n;*\n\tGLOBAL\tC Draw_Char_Setup:NEAR\n\tPROC\tDraw_Char_Setup C NEAR\n\n\tret\n\n\tENDP\tDraw_Char_Setup\n\n\tDATASEG\n\nColorXlat\tDB\t000H,001H,002H,003H,004H,005H,006H,007H\n\tDB\t008H,009H,00AH,00BH,00CH,00DH,00EH,00FH\n\n\tDB\t001H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t002H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t003H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t004H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t005H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t006H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t007H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t008H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t009H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00AH,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00BH,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00CH,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00DH,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00EH,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00FH\n\n;***********************************************************\n\tEND\n\n"
  },
  {
    "path": "WINVQ/VQM32/DRAWCHAR.BAK",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header:   U:\\vq\\projects\\vqm32\\drawchar.asv   1.1   08 May 1995 10:48:32   DENZIL_LONG  $\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : DRAWCHAR.ASM                             *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : August 20, 1993                          *\n;*                                                                         *\n;*                  Last Update : August 20, 1993   [JLB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\nXPIXEL_MAX\t\tEQU\t320\nYPIXEL_MAX\t\tEQU\t200\n\nFONTINFOBLOCK\t\tEQU\t4\nFONTOFFSETBLOCK\tEQU\t6\nFONTWIDTHBLOCK\tEQU\t8\nFONTDATABLOCK\t\tEQU\t10\nFONTHEIGHTBLOCK\tEQU\t12\n\nFONTINFOMAXHEIGHT\tEQU\t4\nFONTINFOMAXWIDTH\tEQU\t5\n\n\tEXTRN\tFontPtr:NEAR PTR\n\n;***********************************************************\n; DRAW_CHAR\n;\n; VOID Draw_Char(BYTE fontchar, WORD x_pixel, WORD y_pixel);\n;\n; Draws a character to the screen only if given coordinates that will allow\n; the entire character to be drawn on the screen else will exit.\n; \n; NOTE: This is a routine called by Text_Print.\n;\n;*\n\tGLOBAL\tC Draw_Char:NEAR\n\tPROC\tDraw_Char C NEAR USES eax ebx ecx edx esi edi \n\tARG\tfontchar:DWORD\n\tARG\tx_pixel:DWORD\n\tARG\ty_pixel:DWORD\n\n\tLOCAL\tinfoblock:DWORD\n\tLOCAL\toffsetblock:DWORD\n\tLOCAL\twidthblock:DWORD\n\tLOCAL\theightblock:DWORD\n\tLOCAL\tfwidth:DWORD\n\tLOCAL\tnextline:DWORD\n\tLOCAL\tstartv:BYTE\n\tLOCAL\tdheight:BYTE\n\tLOCAL\twheight:BYTE\n\n\tmov\tesi,[FontPtr]\n\n\t; Set up some working local variables.\n\n\txor\teax,eax\n\tmov\tax,[esi+FONTINFOBLOCK]\t; get offset to info block\n\tmov\t[infoblock],eax\t\t; save offset to info block\n\tmov\tax,[esi+FONTOFFSETBLOCK]\t; get offset to offset block\n\tmov\t[offsetblock],eax\t\t; save offset to offset block\n\tmov\tax,[esi+FONTWIDTHBLOCK]\t; get offset to width block\n\tmov\t[widthblock],eax\t\t; save offset to width block\n\tmov\tax,[esi+FONTHEIGHTBLOCK]\t; get offset to height block\n\tmov\t[heightblock],eax\t\t; save offset to height block\n\n\t; Fetch character data offset -- if NULL then undefined character.\n\n\tmov\tebx,[fontchar]\n\tand\tebx,0FFh\n\tshl\tebx,1\t\t; make word index\n\tadd\tebx,[offsetblock]\t; add offset to offset block\n\txor\tecx,ecx\n\tmov\tcx,[esi+ebx]\t\t; load offset to font data\n\tor\tecx,ecx\n\tjz\t??exit\t\t; is this character a null? if so exit\n\n\t; If the character is off the left/right edge of the screen then abort.\n\n\tmov\tedx,[x_pixel]\n\tcmp\tedx,XPIXEL_MAX\n\tjae\t??exit\n\n\t; If the character is off the top/bottom edge of the screen then abort.\n\n\tmov\tebx,[fontchar]\t\t; get char\n\tand\tebx,0FFh\n\tadd\tebx,[widthblock]\t; add offset to width block\n\txor\teax,eax\n\tmov\tal,[esi+ebx]\t\t; get width for character\n\tmov\t[fwidth],eax\t\t; save char width\n\tadd\teax,edx\t\t; ax = char len + x\n\tcmp\teax,XPIXEL_MAX\n\tja\t??exit\n\n\tmov\tedi,edx\t\t; save xpos in di\n\n\tmov\tedx,[y_pixel]\n\tcmp\tedx,YPIXEL_MAX\n\tjae\t??exit\n\n\tmov\tebx,[infoblock]\t; get offset to offset block\n\txor\teax,eax\n\t\t\t\t; get font max height from info block\n\tmov\tal,[esi+ebx+FONTINFOMAXHEIGHT]\n\tmov\t[wheight],al\t\t; save max height of character\n\tadd\teax,edx\t\t; add height to y pos\n\tcmp\teax,YPIXEL_MAX\t\t; will it go off the bottom\n\tja\t??exit\n\n??vdraw:\n\tmov\tebx,[fontchar]\t\t; get char\n\tand\tebx,0FFh\n\tshl\tebx,1\t\t; make 2 byte index\n\tadd\tebx,[heightblock]\t; add offset to height block\n\tmov\tah,[esi+ebx]\t\t; get start vertical for character\n\tmov\t[startv],ah\t\t; save start vertical for later\n\tmov\tal,[esi+ebx+1]\t\t; get data height for character\n\tmov\t[dheight],al\t\t; save data height for later\n\tadd\tah,al\t\t; add background and data\n\tsub\t[wheight],ah\t\t; remaining background height\n\n\tadd\tesi,ecx\t\t; add font offset to font data\n\n\tpush\tedx\n\tmov\teax,XPIXEL_MAX\n\tmul\tedx\n\tadd\tedi,eax\n\tpop\tedx\n\n\tmov\teax,XPIXEL_MAX\n\tsub\teax,[fwidth]\n\tmov\t[nextline],eax\t\t; ?? to add to index for the nextline\n\n\tadd\tedi,0A0000h\n\tmov\tebx,OFFSET ColorXlat\t; setup up bx for xlat commands\n\txor\tecx,ecx\n\tmov\tcl,[startv]\t\t; number of scan lines that are\n\t\t\t\t; background color\n\tor\tecx,ecx\t\t; if starting vertical is zero\n\tje\tshort ??skiplead\t; skip drawing top background lines\n\n\tmov\tal,0\n\txlat\t[ebx]\t\t; get background color\n\n\tor\tal,al\t\t; check for none zero color\n\tjne\tshort ??lheight\t; update background color\n\n\tpush\tedx\n\tmov\teax,XPIXEL_MAX\n\tmul\tecx\n\tadd\tedi,eax\n\tpop\tedx\n\n\tmov\tebx,OFFSET ColorXlat\t; restore bx for xlat commands\n\tjmp\tSHORT ??skiplead\n\n??lheight:\n\tmov\tedx,[fwidth]\t\t; width of char\n\n??lwidth:\n\tstosb\t\t\t; write out line of pixels for width\n\tdec\tedx\n\tjne\t??lwidth\n\n??lnext:\n\tadd\tedi,[nextline]\t\t; goto next line at the start of char\n\tloop\t??lheight\t\t; any more lines\n\n??skiplead:\n\tmov\tcl,[dheight]\t\t; number of scan lines that are data\n\tor\tecx,ecx\t\t; is there any data to be drawn\n\tje\tshort ??exit\n\n??vheight:\n\tmov\tedx,[fwidth]\t\t; width of char\n\n??vwidth:\n\tlodsb\t\t\t\t; get byte value from font data\n\tmov\tah,al\t\t\t; save hinibble\n\tand\tal,00FH\t\t\t; get lonibble\n\txlat\t[ebx]\t\t\t; get new color\n\tor\tal,al\n\tje\tshort ??chklowidth\t\t; skip color zero\n\n\tmov\t[edi],al\t\t; write out pixel of lonibble\n\n??chklowidth:\n\tinc\tedi\n\tdec\tedx\n\tje\tshort ??vnext\t\t\t; check if done with width of char\n\n\tmov\tal,ah\t\t\t; get byte value\n\tand\tal,0F0H\t\t\t; get hinibble\n\txlat\t[ebx]\t\t\t; get new color\n\tor\tal,al\n\tje\tshort ??chkhiwidth\t\t; skip color zero\n\n\tmov\t[edi],al\t\t; write out pixel of hinibble\n\n??chkhiwidth:\n\tinc\tedi\n\tdec\tedx\n\tjne\t??vwidth\t\t; check if done with width of char\n\n??vnext:\n\tadd\tedi,[nextline]\t\t; next line at start of char\n\tloop\t??vheight\t\t; any more lines\n\n\n??trail:\n\tmov\tcl,[wheight]\t\t; remaining height of background color\n\tor\tecx,ecx\t\t\t; if trailing height is zero\n\tjle\tshort ??exit\t\t\t; skip drawing bottom background lines\n\n\tmov\tal,0\n\txlat\t[ebx]\t\t\t; get background color\n\tor\tal,al\t\t\t; check for color zero\n\tje\tshort ??exit\t\t\t; skip drawing\n\n??theight:\n\tmov\tedx,[fwidth]\t\t; width of char\n\n??twidth:\n\tstosb\t\t\t\t; write out line of pixels for width\n\tdec\tedx\n\tjne\t??twidth\n\n??tnext:\n\tadd\tedi,[nextline]\t\t; next line at start of char\n\tloop\t??theight\t\t; any more lines\n\n\n??exit:\n\tret\n\n\tENDP\tDraw_Char\n\n;***********************************************************\n\n\n;***********************************************************\n; SET_FONT_PALETTE_RANGE\n;\n; VOID Set_Font_Palette_Range(VOID *palette, WORD start, WORD end);\n;\n; This routine changes the local Draw_Char color translation table\n; with the color numbers in palette.\n;\n; Bounds Checking: forces start and end to a range of 0-15\n;*\n\tGLOBAL\tC Set_Font_Palette_Range:NEAR\n\tPROC\tSet_Font_Palette_Range C NEAR USES eax ebx ecx edi esi\n\tARG\tpalette:NEAR PTR\n\tARG\tstart:DWORD\n\tARG\tendval:DWORD\n\n\tcld\n\tmov\tesi,[palette]\n\tmov\tebx,[start]\n\tand\tebx,0FH\t\t\t; value 0-15\n\n\tmov\tecx,[endval]\n\tand\tecx,0FH\t\t\t; value 0-15\n\n\tcmp\tecx,ebx\t\t\t; if end < start then exit\n\tjl\tshort ??exit\n\n\tsub\tecx,ebx\t\t\t; number of colors = end - start + 1\n\tinc\tecx\n\n\tmov\tedi,OFFSET ColorXlat\t; get start of xlat table\n\tadd\tedi,ebx\t\t\t; add starting offset\n\tshl\tebx,4\t\t\t; multiply start offset by 16\n\tadd\tebx,OFFSET ColorXlat\t; add start of xlat table\n\n; updates 0-15 for lonibble xlat\n; updates 0,16,32,...,240 for hinibble xlat\n\n??setpal:\n\tlodsb\t\t\t\t; get color number\n\tstosb\t\t\t\t; save color number for lonibble xlat\n\tmov\t[ebx],al\t\t; save color number for hinibble xlat\n\tadd\tebx,010H\t\t\t; add 16 to index for hinibble offset\n\tloop\t??setpal\n\n??exit:\n\tret\n\n\tENDP\tSet_Font_Palette_Range\n\n;***********************************************************\n\n\n;***********************************************************\n; DRAW_CHAR_SETUP\n;\n; VOID Draw_Char_Setup(VOID);\n;\n; This routine sets up code segment variables for Draw_Char.\n; \n; NOTE: This is a routine called by Set_Font.\n;\n;*\n\tGLOBAL\tC Draw_Char_Setup:NEAR\n\tPROC\tDraw_Char_Setup C NEAR\n\n\tret\n\n\tENDP\tDraw_Char_Setup\n\n\tDATASEG\n\nColorXlat\tDB\t000H,001H,002H,003H,004H,005H,006H,007H\n\tDB\t008H,009H,00AH,00BH,00CH,00DH,00EH,00FH\n\n\tDB\t001H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t002H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t003H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t004H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t005H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t006H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t007H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t008H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t009H,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00AH,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00BH,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00CH,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00DH,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00EH,000H,000H,000H,000H,000H,000H,000H\n\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\tDB\t00FH\n\n;***********************************************************\n\tEND\n\n"
  },
  {
    "path": "WINVQ/VQM32/FILLRECT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     fillrect.asm\n;*\n;* DESCRIPTION\n;*     Rectangle rendering.\n;*\n;* PROGRAMMER\n;*     Joe L. Bostic\n;*\n;* DATE\n;*     Febuary 8, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     Fill_Rect - Draw a filled rectangle.\n;*     Eor_Region - Hilights or unhilights a region by EOR it.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     Eor_Region - Hilights or unhilights a region by EOR it.\n;*\n;* SYNOPSIS\n;*     Eor_Region(X1, Y1, X2, Y2, Color)\n;*\n;*     void Eor_Region(long, long, long, long, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     X1    - Starting X position.\n;*     Y1    - Starting Y position.\n;*     X2    - Ending X position.\n;*     Y2    - Ending Y position.\n;*     Color - Color to EOR.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Eor_Region:NEAR\n\tPROC\tEor_Region C NEAR USES eax ebx ecx edx edi\n\tARG\tx1_pixel:DWORD\n\tARG\ty1_pixel:DWORD\n\tARG\tx2_pixel:DWORD\n\tARG\ty2_pixel:DWORD\n\tARG\tcolor:DWORD\n\tLOCAL\teorit:DWORD\n\n\tmov\t[eorit],1\n\tjmp\tshort Fill_Rect_Entry\n\n\tENDP\tEor_Region\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Fill_Rect - Draw a filled rectangle.\n;*\n;* SYNOPSIS\n;*     Fill_Rect(X1, Y1, X2, Y2, Color)\n;*\n;*     void Fill_Rect(long, long, long, long, long);\n;*\n;* FUNCTION\n;*     Fill a rectangle area with a specified color.\n;*\n;* INPUTS\n;*     X1    - Starting X position.\n;*     Y1    - Starting Y position.\n;*     X2    - Ending X position.\n;*     Y2    - Ending Y position.\n;*     Color - Color to draw rectangle\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Fill_Rect:NEAR\n\tPROC\tFill_Rect C NEAR USES eax ebx ecx edx edi\n\tARG\tx1_pixel:DWORD\n\tARG\ty1_pixel:DWORD\n\tARG\tx2_pixel:DWORD\n\tARG\ty2_pixel:DWORD\n\tARG\tcolor:DWORD\n\tLOCAL\teorit:DWORD\n\n\tmov\t[eorit],0\n\nFill_Rect_Entry:\n\tcld\t\t\t; always go forward\n\tmov\tedi,0A0000h\n\n\t; Verify bounds of x1_pixel.\n\tmov\teax,[x1_pixel]\n\tcmp\teax,320\t;XPIXEL_MAX\n\tjae\tshort ??exit\n\n\t; Verify bounds of x2_pixel.\n\tmov\tebx,[x2_pixel]\n\tcmp\tebx,320\t;XPIXEL_MAX\n\tjae\tshort ??exit\n\n\t; Backward rectangles are legal -- adjust for it.\n\tcmp\teax,ebx\n\tjbe\tshort ??okx\n\txchg\teax,ebx\n??okx:\n\n\t; Verify bounds of y1_pixel.\n\tmov\tecx,[y1_pixel]\n\tcmp\tecx,200\t;YPIXEL_MAX\n\tjae\tshort ??exit\n\n\t; Verify bounds of y2_pixel.\n\tmov\tedx,[y2_pixel]\n\tcmp\tedx,200\t;YPIXEL_MAX\n\tjae\tshort ??exit\n\n\t; Backward rectangles are legal -- adjust for it.\n\tcmp\tecx,edx\n\tjbe\tshort ??oky\n\txchg\tecx,edx\n??oky:\n\n\t; Set DX for height and BX for width.\n\tsub\tedx,ecx\n\tinc\tedx\n\tsub\tebx,eax\n\tinc\tebx\n\n\t; Adjust DI to match offset into page of upper left corner.\n\tpush\tedx\n\tpush\teax\n\tmov\teax,320\t;XPIXEL_MAX\n\tmul\tecx\n\tadd\tedi,eax\t\t\t; Add in Y offset.\n\tpop\tedx\n\tadd\tedi,edx\t\t\t; Add in X offset.\n\tpop\tedx\n\n\t; Fill the region with the specified color.\n\tmov\teax,320\t;XPIXEL_MAX\n\tsub\teax,ebx\n\txchg\teax,[color]\n\tmov\tah,al\n\tcmp\t[eorit],0\n\tje\tshort ??loop\n\n;------\tEOR rectangle filling.\n??loop2:\n\tmov\tecx,ebx\t\t\t; Length of row\n??loop2in:\n\tlodsb\n\txor\tal,ah\n\tstosb\n\tloop\t??loop2in\n\tadd\tedi,[color]\t\t; Modulo add for next line prep.\n\tdec\tedx\n\tjg\tshort ??loop2\n\tjmp\tshort ??exit\n\n;------\tConventional rectangle filling.\n??loop:\n\tmov\tecx,ebx\t\t\t; Length of row\n\tshr\tecx,1\n\trep\tstosw\n\tadc\tecx,0\n\trep\tstosb\n\tadd\tedi,[color]\t\t; Modulo add for next line prep.\n\tdec\tedx\n\tjg\tshort ??loop\n\n??exit:\n\tret\n\n\tENDP\tFill_Rect\n\n\tEND\n\n"
  },
  {
    "path": "WINVQ/VQM32/FONT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*---------------------------------------------------------------------------\n*\n* FILE\n*     font.c\n*\n* DESCRIPTION\n*     Font manipulation.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     March 9, 1995\n*\n*---------------------------------------------------------------------------\n*\n* PUBLIC\n*     Load_Font          - Open a font for use.\n*     Set_Font           - Set the default system font.\n*     String_Pixel_Width - Get the pixel width of a string.\n*\n****************************************************************************/\n\n#include <stdlib.h>\n#include <fcntl.h>\n#include <io.h>\n#include <string.h>\n#include <malloc.h>\n#include \"font.h\"\n\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n/* min and max macros */\n#ifdef __cplusplus\n#ifndef max\n#define max(a,b)  (((a) > (b)) ? (a) : (b))\n#endif\n#ifndef min\n#define min(a,b)  (((a) < (b)) ? (a) : (b))\n#endif\n#endif\n\nvoid const *FontPtr = NULL;\nchar FontHeight = 8;\nchar FontWidth = 8;\nint FontXSpacing = 0;\nint FontYSpacing = 0;\nchar *FontWidthBlockPtr = NULL;\n\n\n/****************************************************************************\n*\n* NAME\n*     Load_Font - Open a font for use.\n*\n* SYNOPSIS\n*     Font = Load_Font(Name)\n*\n*     char *Load_Font(char *);\n*\n* FUNCTION\n*     Open a graphics font for use by Text_Print(). Use free() to dispose\n*     of the font.\n*\n* INPUTS\n*     Name - Name of font file to open.\n*\n* RESULT\n*     Font - Pointer to font, NULL if error.\n*\n****************************************************************************/\n\nvoid *cdecl Load_Font(char const *name)\n{\n\tFont  *font = NULL;\n\tlong  fh;\n\tshort size;\n\tshort valid;\n\n\t/* Open the font. */\n\tif ((fh = open(name, (O_RDONLY|O_BINARY))) != -1) {\n\n\t\t/* Get the size of the font. */\n\t\tif (read(fh, &size, 2) == 2) {\n\n\t\t\t/* Allocate memory to contain the font. */\n\t\t\tif ((font = (Font *)malloc((unsigned long)size)) != NULL) {\n\t\t\t\tvalid = 0;\t\n\n\t\t\t\t/* Read in the body of the font. */\n\t\t\t\tif (read(fh, &font->CompMethod, (unsigned long)(size - 2))\n\t\t\t\t\t\t== (unsigned long)(size - 2)) {\n\t\t\t\t\t\n\t\t\t\t\t/* Verify the validity of the font. */\n\t\t\t\t\tif ((font->CompMethod == 0) && (font->NumBlks == 5)) {\n\t\t\t\t\t\tfont->Size = size;\n\t\t\t\t\t\tvalid = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* Free the font if it is not valid. */\n\t\t\t\tif (valid == 0) {\n\t\t\t\t\tfree(font);\n\t\t\t\t\tfont = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Close the font. */\n\t\tclose(fh);\n\t}\n\n\treturn ((char *)font);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Set_Font - Set the default system font.\n*\n* SYNOPSIS\n*     OldFont = Set_Font(Font)\n*\n*     char *Set_Font(char *);\n*\n* FUNCTION\n*     Sets up the specified font as the default font used by the system.\n*\n* INPUTS\n*     Font - Pointer to Font to set as default. (NULL returns current font)\n*\n* RESULT\n*     OldFont - Previous font.\n*\n****************************************************************************/\n\nvoid *cdecl Set_Font(void const *font)\n{\n\tvoid const *oldfont;\n\tFontInfo   *fi;\n\n\toldfont = FontPtr;\n\t\n\tif (font != NULL) {\n\t\tFontWidthBlockPtr = ((char *)font + ((Font *)font)->WidthBlk);\n\t\tfi = (FontInfo *)((char *)font + ((Font *)font)->InfoBlk);\n\t\tFontHeight = fi->MaxHeight;\n\t\tFontWidth = fi->MaxWidth;\n\t\tFontPtr = font;\n\t}\n\n\treturn ((void *)oldfont);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     String_Pixel_Width - Get the pixel width of a string.\n*\n* SYNOPSIS\n*     Width = String_Pixel_Width(String)\n*\n*     long String_Pixel_Width(char *);\n*\n* FUNCTION\n*     Calculates the pixel width of a string of characters.\n*\n* INPUTS\n*     String - Pointer to string to calculate width for.\n*\n* RESULT\n*     Width - Width of string in pixels.\n*\n****************************************************************************/\n\nunsigned short String_Pixel_Width(char const *string)\n{\n\tlong width = 0;\n\tlong largest = 0;\n\n\twhile (*string != NULL) {\n\t\tif (*string == '\\r') {\n\t\t\tstring++;\n\t\t\tlargest = max(largest, width);\n\t\t\twidth = 0;\n\t\t} else {\n\t\t\twidth += Char_Pixel_Width(*string++);\n\t\t}\n\t}\n\n\tlargest = max(largest, width);\n\n\treturn (largest);\n}\n\n"
  },
  {
    "path": "WINVQ/VQM32/FONT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMFONT_H\n#define VQMFONT_H\n/****************************************************************************\n*\n*        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\n*\n*---------------------------------------------------------------------------\n*\n* FILE\n*     font.h\n*\n* DESCRIPTION\n*     Font definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     March 9, 1995\n*\n****************************************************************************/\n\n/* Font: A Westwood style font.\n *\n * Size       - Size of font.\n * CompMethod - Compression method of font. (0 = none)\n * NumBlks    - Number of data blocks.\n * InfoBlk    - Offset to font information block.\n * OffsetBlk  - Offset to character offset block.\n * WidthBlk   - Offset to character width block.\n * DataBlk    - Offset to character data block.\n * HeightBlk  - Offset to character height block.\n */\ntypedef struct _Font {\n\tunsigned short Size;\n\tunsigned char  CompMethod;\n\tunsigned char  NumBlks;\n\tunsigned short InfoBlk;\n\tunsigned short OffsetBlk;\n\tunsigned short WidthBlk;\n\tunsigned short DataBlk;\n\tunsigned short HeightBlk;\n} Font;\n\ntypedef struct _FontInfo {\n\tlong huh;\n\tunsigned char MaxHeight;\n\tunsigned char MaxWidth;\n} FontInfo;\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern void const *FontPtr;\nextern int FontXSpacing;\nextern int FontYSpacing;\n\n#ifdef __cplusplus\n}\n#endif\n\nextern char FontWidth;\nextern char FontHeight;\nextern char *FontWidthBlockPtr;\n\n/* Function prototypes. */\nvoid *cdecl Load_Font(char const *name);\nvoid *cdecl Set_Font(void const *font);\nunsigned short __cdecl String_Pixel_Width(char const *string);\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef __WATCOMC__\nlong __cdecl __saveregs Char_Pixel_Width(char chr);\n#else\nlong __cdecl Char_Pixel_Width(char chr);\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMFONT_H */\n\n"
  },
  {
    "path": "WINVQ/VQM32/GRAPHICS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMGRAPHICS_H\n#define VQMGRAPHICS_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     graphics.h\n*\n* DESCRIPTION\n*     Graphic rendering and manipulation definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     April 27, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid __cdecl Eor_Region(long sx, long sy, long dx, long dy, long color);\nvoid __cdecl Fill_Rect(long x1, long y1, long x2, long y2, long color);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMGRAPHICS_H */\n\n"
  },
  {
    "path": "WINVQ/VQM32/HUFFCMP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     huffcmp.h\n*\n* DESCRIPTION\n*     Huffman order 0 compressor.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     May 19, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     HuffCompress    - Compress data using huffman order 0 compression.\n*     HuffCount       - Count the frequency of occurence of every byte.\n*     HuffScaleCounts - Scale down the frequency counts.\n*     RLEHuffCounts   - Run Length Encode the Huffman counts.\n*     ConvertToCodes  - Convert the Huffman tree into a table of codes.\n*     HuffEncode      - Huffman encode the data.\n*\n****************************************************************************/\n\n#include <mem.h>\n#include \"huffman.h\"\n\n\n/****************************************************************************\n*\n* NAME\n*     HuffCompress - Compress data using huffman order 0 compression.\n*\n* SYNOPSIS\n*     Size = HuffCompress(Data, Buffer, Size, Temp)\n*\n*     long HuffCompress(unsigned char *, unsigned char *, long, char *);\n*\n* FUNCTION\n*     This function performs an order 0 Huffman encoding of the input data.\n*     The algorithm used is fairly straightforward. First a count is made of\n*     all the bytes in the input data, then the counts are scaled down to\n*     a single byte representation in the node array. After the counts are\n*     scaled, a Huffman decoding tree is built from the node array. Then\n*     a code array is built by traversing the tree for each symbol. Finally,\n*     the input data is compressed.\n*\n* INPUTS\n*     Data   - Pointer to data to compress.\n*     Buffer - Pointer to compressed data.\n*     Size   - Length of data to compress.\n*     Temp   - Pointer to temporary working buffer. (Must be >= 5120 bytes!)\n*\n* RESULT\n*     Size - Compressed size.\n*\n****************************************************************************/\n\nlong __cdecl HuffCompress(unsigned char *data, unsigned char *buffer,\n\t\tlong length, char *temp)\n{\n\t#if(1)\n\tTreeNode *nodes;\n\tHuffCode *codes;\n\tlong     size;\n\tlong     root;\n\n\t/* Initialize variables */\n\tnodes = (TreeNode *)temp;\n\ttemp += (514 * sizeof(TreeNode));\n\tcodes = (HuffCode *)temp;\n\n\t/* Analyze the frequency of the data. */\n\tHuffCount(data, nodes, length, 1);\n\tHuffScaleCounts(nodes);\n\n\t/* Save the counts for the decompression. */\n\tsize = RLEHuffCounts(nodes, buffer);\n\tbuffer += size;\n\n\t/* Build the Huffman decode tree and generate codes for encoding. */\n\troot = BuildHuffTree(nodes);\n\tConvertToCodes(nodes, codes, 0, 0, root);\n\n\t/* Encode the data. */\n\tsize += HuffEncode(data, buffer, codes, length);\n\n\treturn (size);\n\t#else\n\tTreeNode      *nodes;\n\tHuffCode      *codes;\n\tunsigned long *counts;\n\tunsigned long max_count;\n\tlong          i;\n\tlong          size;\n\tlong          first;\n\tlong          last;\n\tlong          next;\n\tunsigned long symbol;\n\tunsigned long mask;\n\n\t/* Initialize variables. */\n\tnodes = (TreeNode *)temp;\n\ttemp += (514 * sizeof(TreeNode));\n\tcounts = (unsigned long *)temp;\n\tcodes = (HuffCode *)temp;\n\n\t/* Zero the initial counts. */\n\tmemset(temp, 0, 256 * sizeof(unsigned long));\n\tsize = 0;\n\n\t/*-------------------------------------------------------------------------\n\t * Calculate the distribution of the data then scale down the counts so\n\t * they fit in an 8 bit value. This is done in order to limit the size of\n\t * the codes to 16 bits.\n\t *-----------------------------------------------------------------------*/\n\ti = 0;\n\n\twhile (i < length) {\n\t\tcounts[((unsigned char *)data)[i]]++;\n\t\ti++;\n\t}\n\n\t/* Scale down the counts. */\n\tmax_count = 0;\n\n\t/* Find the maximum count. */\n\tfor (i = 0; i < 256; i++) {\n\t\tif (counts[i] > max_count) {\n\t\t\tmax_count = counts[i];\n\t\t}\n\t}\n\n\tif (max_count == 0) {\n\t\tcounts[0] = 1;\n\t\tmax_count = 1;\n\t}\n\n\tmax_count /= 255;\n\tmax_count++;\n\n\t/* Scale down the counts. */\n\tfor (i = 0; i < 256; i++) {\n\t\tnodes[i].count = (unsigned long)(counts[i] / max_count);\n\n\t\t/* Make sure that a node with a non-zero count does not get scaled\n\t\t * down to zero.\n\t\t */\n\t\tif ((nodes[i].count == 0) && (counts[i] != 0)) {\n\t\t\tnodes[i].count = 1;\n\t\t}\n\t}\n\n\tnodes[HUFF_EOS].count = 1;\n\n\t/*-------------------------------------------------------------------------\n\t * OUTPUT THE COUNTS\n\t *\n\t * In order to save space, we store runs of counts in the following format:\n\t *\n\t *   Start, Stop, Counts..., Start, Stop, Counts..., ..., 0\n\t *\n\t * The list is terminated by storing a start value of zero (0).\n\t *\n\t * In order to efficiently use this format, we do not want to stop a run\n\t * because of just one or two zero counts. So we include zero counts of\n\t * less than three (3) in the run.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Find the first occurance of a non-zero count. */\n\tfirst = 0;\n\n\twhile ((first < 255) && (nodes[first].count == 0)) {\n\t\tfirst++;\n\t}\n\n\t/* Each time I hit the start of the loop, I assume that first is the\n\t * number for a run of non-zero values.  The rest of the loop is\n\t * concerned with finding the value for last, which is the end of the\n\t * run, and the value of next, which is the start of the next run.\n\t * At the end of the loop, I assign next to first, so it starts in on\n\t * the next run.\n\t */\n\tfor (; first < 256; first = next) {\n\t\tlast = first + 1;\n\n\t\tfor (;;) {\n\n\t\t\t/* Find the end of the run of non-zeros. */\n\t\t\tfor (; last < 256; last++) {\n\t\t\t\tif (nodes[last].count == 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t    last--;\n\n\t\t\t/* Check the beginning of the next run of non-zero counts. */\n\t\t\tfor (next = last + 1; next < 256; next++) {\n\t\t\t\tif (nodes[next].count != 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Quit the run if we have reached the end. */\n\t\t\tif (next > 255) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/* Quit the run if there is more than three non-zero counts. */\n\t\t\tif ((next - last) > 3) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t  last = next;\n\t\t};\n\n\t\t/* Output Start and Stop. */\n\t\t*buffer++ = first;\n\t\t*buffer++ = last;\n\n\t\t/* Output the run of counts. */\n\t\tfor (i = first; i <= last; i++) {\n\t\t\t*buffer++ = (char)nodes[i].count;\n\t\t}\n\n\t\tsize += (((last - first) + 1) + 2);\n\t}\n\n\t/* Output terminator. */\n\t*buffer++ = 0;\n\tsize++;\n\n\t/*-------------------------------------------------------------------------\n\t * Build the Huffman tree. All active nodes are scanned in order to locate\n\t * the two nodes with the minimum weights. These two weights are added\n\t * together and assigned to a new node. The new node makes the two minimum\n\t * nodes into its 0 child and 1 child. The two minimum nodes are then\n\t * marked as inactive. This process repeats until their is only one node\n\t * left, which is the root node.\n\t *-----------------------------------------------------------------------*/\n\n\t/* Node 513 is used to arbitratilly provide a node with a guaranteed\n\t * maximum value.\n\t */\n\tnodes[513].count = 0xFFFF;\n\n\tfor (next = (HUFF_EOS + 1); ; next++) {\n\t\tfirst = 513;\n\t\tlast = 513;\n\n\t\tfor (i = 0; i < next; i++) {\n\n\t\t\t/* We are only concerned with non-zero count nodes. */\n\t\t\tif (nodes[i].count != 0) {\n\t\t\t\tif (nodes[i].count < nodes[first].count) {\n\t\t\t\t\tlast = first;\n\t\t\t\t\tfirst = i;\n\t\t\t\t} else if (nodes[i].count < nodes[last].count) {\n\t\t\t\t\tlast = i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (last == 513) {\n\t\t\tbreak;\n\t\t}\n\n\t\tnodes[next].count = (nodes[first].count + nodes[last].count);\n\t\tnodes[first].count = 0;\n\t\tnodes[last].count = 0;\n\t\tnodes[next].child0 = (first << 3);\n\t\tnodes[next].child1 = (last << 3);\n\t}\n\n\tnext--;\n\n\t/*-------------------------------------------------------------------------\n\t * Convert the Huffman tree into an encoding table then encode the data.\n\t *-----------------------------------------------------------------------*/\n\tConvertToCodes(nodes, codes, 0, 0, (next << 3));\n\n\t/* Encode the data. */\n\t*buffer = 0;\n\tnext = 0x80;\n\ti = 0;\n\n\tdo {\n\t\tif (i < length) {\n\t\t\tsymbol = ((unsigned char *)data)[i];\n\t\t} else {\n\t\t\tsymbol = HUFF_EOS;\n\t\t}\n\n\t\tmask = 1L << (codes[symbol].bits - 1);\n\n\t\twhile (mask != 0) {\n\n\t\t\t/* Set a bit in the output stream for each bit in the code. */\n\t\t\tif (mask & codes[symbol].code) {\n\t\t\t\t*buffer |= next;\n\t\t\t}\n\n\t\t\t/* Next bit position. */\n\t\t\tnext >>= 1;\n\n\t\t\t/* Advance to the next byte in the output stream when the current\n\t\t\t * byte is full.\n\t\t\t */\n\t\t\tif (next == 0) {\n\t\t\t\tbuffer++;\n\t\t\t\t*buffer = 0;\n\t\t\t\tnext = 0x80;\n\t\t\t\tsize++;\n\t\t\t}\n\n\t\t\t/* Next bit in the code. */\n\t\t\tmask >>= 1;\n\t\t}\n\n\t\ti++;\n\t} while (symbol != HUFF_EOS);\n\n\tif (next != 0x80) {\n\t\tsize++;\n\t}\n\n\treturn (size);\n\t#endif\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     HuffCount - Count the frequency of occurence of every byte.\n*\n* SYNOPSIS\n*     HuffCount(Data, Nodes, Length, Zero)\n*\n*     void HuffCounts(unsigned char *, TreeNode *, long, long);\n*\n* FUNCTION\n*     This function counts the frequency of occurence of every byte in the\n*     input data. The nodes must be initialized to zero prior to calling this\n*     function for the first time, otherwise the counts will be flawed.\n*\n* INPUTS\n*     Data     - Pointer to data to analyze.\n*     TreeNode - Pointer to array of nodes.\n*     Length   - Length of data to analyze.\n*     Zero     - Zero any previous counts flag. (TRUE = zero counts)\n*\n* RESULT\n*     Size - Amount of buffer used to hold counts.\n*\n****************************************************************************/\n\nvoid __cdecl HuffCount(unsigned char *data, TreeNode *nodes, long length,\n\t\tlong zero)\n{\n\tlong i;\n\n\t/* Zero any previous counts. */\n\tif (zero) {\n\t\tfor (i = 0; i < 256; i++) {\n\t\t\tnodes[i].count = 0;\n\t\t}\n\t}\n\n\t/* Calculate the distribution of the data. */\n\ti = 0;\n\n\twhile (i < length) {\n\t\tnodes[((unsigned char *)data)[i]].count++;\n\t\ti++;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     HuffScaleCounts - Scale down the frequency counts.\n*\n* SYNOPSIS\n*     HuffScaleCounts(Nodes)\n*\n*     void HuffScaleCounts(TreeNode *);\n*\n* FUNCTION\n*     In order to limit the size of the Huffman codes to 16 bits, we must\n*     scale down the counts so they can be represented by a BYTE size value.\n*\n* INPUTS\n*     Nodes  - Pointer to nodes to scale counts for.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid __cdecl HuffScaleCounts(TreeNode *nodes)\n{\n\tunsigned long max_count;\n\tunsigned long unscaled;\n\tlong          i;\n\tlong          first;\n\tlong          last;\n\tlong          next;\n\n\t/* Scale down the counts so they fit in an 8 bit value. This is done in\n\t * order to limit the size of the codes to 16 bits.\n\t */\n\tmax_count = 0;\n\n\t/* Find the maximum count. */\n\tfor (i = 0; i < 256; i++) {\n\t\tif (nodes[i].count > max_count) {\n\t\t\tmax_count = nodes[i].count;\n\t\t}\n\t}\n\n\tif (max_count == 0) {\n\t\tnodes[0].count = 1;\n\t\tmax_count = 1;\n\t}\n\n\tmax_count /= 255;\n\tmax_count++;\n\n\t/* Scale down the counts. */\n\tfor (i = 0; i < 256; i++) {\n\t\tunscaled = nodes[i].count;\n\t\tnodes[i].count /= max_count;\n\n\t\t/* Make sure that a node with a non-zero count does not get scaled\n\t\t * down to zero.\n\t\t */\n\t\tif ((nodes[i].count == 0) && (unscaled != 0)) {\n\t\t\tnodes[i].count = 1;\n\t\t}\n\t}\n\n\tnodes[HUFF_EOS].count = 1;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     RLEHuffCounts - Run Length Encode the Huffman counts.\n*\n* SYNOPSIS\n*     Size = RLEHuffCounts(Nodes, Buffer)\n*\n*     long RLEHuffCounts(TreeNode *, unsigned char *);\n*\n* FUNCTION\n*     In order for the decoder to build the same model, we have to transmit\n*     the symbol counts to it. To save space we do not save all 256 symbols\n*     unconditionally, instead we run length encode the counts. The format\n*     used to store the counts is as follows:\n*\n*       Start, Stop, Counts[n], Start, Stop, Counts[n], .... 0\n*\n*     Note: The sequence is terminated by a start value of 0. Also at least\n*     1 run of counts has to be stored, even if the first start value is 0.\n*\n* INPUTS\n*     Nodes  - Pointer to initialized nodes.\n*     Buffer - Pointer to buffer to store RLE'd counts.\n*\n* RESULT\n*     Size - Size of the RLE'd counts.\n*\n****************************************************************************/\n\nlong __cdecl RLEHuffCounts(TreeNode *nodes, unsigned char *buffer)\n{\n\tlong i;\n\tlong first;\n\tlong last;\n\tlong next;\n\tlong size = 0;\n\n\t/* Find the first occurance of a non-zero count. */\n\tfirst = 0;\n\n\twhile ((first < 255) && (nodes[first].count == 0)) {\n\t\tfirst++;\n\t}\n\n\t/* Each time I hit the start of the loop, I assume that first is the\n\t * number for a run of non-zero values.  The rest of the loop is\n\t * concerned with finding the value for last, which is the end of the\n\t * run, and the value of next, which is the start of the next run.\n\t * At the end of the loop, I assign next to first, so it starts in on\n\t * the next run.\n\t */\n\tfor (; first < 256; first = next) {\n\t\tlast = first + 1;\n\n\t\tfor (;;) {\n\n\t\t\t/* Find the end of the run of non-zeros. */\n\t\t\tfor (; last < 256; last++) {\n\t\t\t\tif (nodes[last].count == 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t    last--;\n\n\t\t\t/* Check the beginning of the next run of non-zero counts. */\n\t\t\tfor (next = last + 1; next < 256; next++) {\n\t\t\t\tif (nodes[next].count != 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Quit the run if we have reached the end. */\n\t\t\tif (next > 255) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/* Quit the run if there is more than three non-zero counts. */\n\t\t\tif ((next - last) > 3) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t  last = next;\n\t\t};\n\n\t\t/* Output Start and Stop. */\n\t\t*buffer++ = first;\n\t\t*buffer++ = last;\n\n\t\t/* Output the run of counts. */\n\t\tfor (i = first; i <= last; i++) {\n\t\t\t*buffer++ = (unsigned char)nodes[i].count;\n\t\t}\n\n\t\tsize += (((last - first) + 1) + 2);\n\t}\n\n\t/* Output terminator. */\n\t*buffer = 0;\n\tsize++;\n\n\treturn (size);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     ConvertToCodes - Convert the Huffman tree into a table of codes.\n*\n* SYNOPSIS\n*     ConvertToCodes(Nodes, Codes, Code, Bits, Node)\n*\n*     void ConvertToCodes(TreeNode *, HuffCode *, unsigned short, short,\n*                         short);\n*\n* FUNCTION\n*     Since the Huffman tree is built as a decoding tree, there is no simple\n*     way to get the encoding values for each symbol. This routine\n*     recursively walks through the tree, adding the child bits to each code\n*     until it gets to a leaf. When it gets to a leaf, it stores the code\n*     value.\n*\n* INPUTS\n*     Nodes - Pointer to the Huffman tree.\n*     Codes - Pointer to the table of codes to generate.\n*     Code  - Code being built (initialize with 0).\n*     Bits  - Number of bits the code is comprised of (initialize with 0).\n*     Node  - Number of the current node.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid __cdecl ConvertToCodes(TreeNode *nodes, HuffCode *codes,\n\t\tunsigned short code, short bits, short node)\n{\n\tnode >>= 3;\n\n\tif (node <= HUFF_EOS) {\n\t\tcodes[node].code = code;\n\t\tcodes[node].bits = bits;\n\t\treturn;\n\t}\n\n\tcode <<= 1;\n\tbits++;\n\tConvertToCodes(nodes, codes, code, bits, nodes[node].child0);\n\tConvertToCodes(nodes, codes, code|1, bits, nodes[node].child1);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     HuffEncode - Huffman encode the data.\n*\n* SYNOPSIS\n*     Size = HuffEncode(Data, Buffer, Codes, Length);\n*\n*     long HuffEncode(unsigned char *, unsigned char *, HuffCodes *, long);\n*\n* FUNCTION\n*     Encoding of the data is simple. Each byte of data is taken as the index\n*     of the codes array, the corresponding code is then put in the output.\n*\n* INPUTS\n*     Data   - Pointer to data to encode.\n*     Buffer - Pointer to buffer to hold encoded data.\n*     Codes  - Pointer to array of Huffman codes.\n*     Length - Length of data buffer to encode.\n*\n* RESULT\n*     Size - Size of encoded data.\n*\n****************************************************************************/\n\nlong __cdecl HuffEncode(unsigned char *data, unsigned char *buffer,\n\t\tHuffCode *codes, long length)\n{\n\tlong          i;\n\tlong          size;\n\tlong          next;\n\tunsigned long mask;\n\tunsigned long symbol;\n\n\t/* Initialize */\n\t*buffer = 0;\n\tnext = 0x80;\n\ti = 0;\n\n\tdo {\n\t\tif (i < length) {\n\t\t\tsymbol = ((unsigned char *)data)[i];\n\t\t} else {\n\t\t\tsymbol = HUFF_EOS;\n\t\t}\n\n\t\tmask = 1L << (codes[symbol].bits - 1);\n\n\t\twhile (mask != 0) {\n\n\t\t\t/* Set a bit in the output stream for each bit in the code. */\n\t\t\tif (mask & codes[symbol].code) {\n\t\t\t\t*buffer |= next;\n\t\t\t}\n\n\t\t\t/* Next bit position. */\n\t\t\tnext >>= 1;\n\n\t\t\t/* Advance to the next byte in the output stream when the current\n\t\t\t * byte is full.\n\t\t\t */\n\t\t\tif (next == 0) {\n\t\t\t\tbuffer++;\n\t\t\t\t*buffer = 0;\n\t\t\t\tnext = 0x80;\n\t\t\t\tsize++;\n\t\t\t}\n\n\t\t\t/* Next bit in the code. */\n\t\t\tmask >>= 1;\n\t\t}\n\n\t\ti++;\n\t} while (symbol != HUFF_EOS);\n\n\tif (next != 0x80) {\n\t\tsize++;\n\t}\n\n\treturn (size);\n}\n\n"
  },
  {
    "path": "WINVQ/VQM32/HUFFDCMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     huffdcmp.asm\n;*\n;* DESCRIPTION\n;*     Huffman order 0 decompressor.\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     May 22, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     HuffDecompress - Decompress Huffman order 0 encoded data.\n;*     BuildHuffTree  - Build the Huffman decode tree.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\n\tSTRUC\tTreeNode\ncount\tDD\t?\t;Weight of the node\nchild0\tDW\t?\t;Child node 0\nchild1\tDW\t?\t;Child node 1\n\tENDS\tTreeNode\n\nHUFF_EOS\tEQU\t256\n\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     HuffDecompress - Decompress Huffman order 0 encoded data.\n;*\n;* SYNOPSIS\n;*     Size = HuffDecompress(Data, Buffer, Length, Temp)\n;*\n;*     long = HuffDecompress(unsigned char *, unsigned char *, long, char *);\n;*\n;* FUNCTION\n;*     Expand data that has been compressed with order 0 Huffman coding.\n;*     The model (counts) are extracted from the data and a decode tree is\n;*     built. The data is expanded by reading a bit and traversing the tree\n;*     until a leaf node is encountered.\n;*\n;* INPUTS\n;*     Data   - Pointer to Huffman encoded data.\n;*     Buffer - Pointer to decompress buffer.\n;*     Length - Maximum decompress length.\n;*     Temp   - Pointer to temporary working buffer. (Must be >= 5120 bytes!)\n;*\n;* RESULT\n;*     Size - Size of decompressed data.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC HuffDecompress:NEAR\n\tPROC\tHuffDecompress C NEAR USES esi edi ebx ecx edx\n\n\tARG\tdata:NEAR PTR\n\tARG\tbuffer:NEAR PTR\n\tARG\tlength:DWORD\n\tARG\ttemp:NEAR PTR\n\n\tLOCAL\tnext:DWORD\n\n;*---------------------------------------------------------------------------\n;*\tRead in the set of counts\n;*---------------------------------------------------------------------------\n\n\tmov\tesi,[data]\t\t;Compressed data\n\tmov\tebx,[temp]\t\t;Nodes array\n\n\tmov\tax,[esi]\t\t;Get first and last count\n\txor\tedx,edx\t\t;i = 0\n\txor\tecx,ecx\n\tadd\tesi,2\n\n??getcounts:\n\tcmp\tal,dl\t\t;Reached start of run?\n\tjne\t??zerocount\n\n;*\tCopy the run of counts to the nodes\n\n\tsub\tah,al\t\t;Run length = Stop - Start\n\txor\tecx,ecx\n\tmov\tcl,ah\n\txor\teax,eax\n\tinc\tecx\t\t;Run length + 1\n\n??copycounts:\n\tmov\tal,[esi]\t\t;Get count\n\tinc\tedx\t\t;i++\n\tmov\t[ebx],eax\t\t;Write count to node\n\tinc\tesi\n\tadd\tebx,8\t\t;Next node\n\tdec\tecx\n\tjnz\t??copycounts\n\n\tmov\tax,[esi]\t\t;Get next start\n\tinc\tesi\n\tcmp\tal,0\t\t;Terminator?\n\tje\tshort ??nextcount\n\n\tinc\tesi\n\tjmp\tshort ??nextcount\n\n;*\tFill empty nodes with 0\n\n??zerocount:\n\tmov\t[DWORD PTR ebx],ecx\n\tinc\tedx\t\t;i++\n\tadd\tebx,8\t\t;Next node\n\n??nextcount:\n\tcmp\tedx,256\n\tjl\tshort ??getcounts\n\n\tmov\t[WORD PTR ebx],1\n\tmov\t[data],esi\n\n;*---------------------------------------------------------------------------\n;*\tBuild the Huffman tree. All active nodes are scanned in order\n;*\tto locate the two nodes with the minimum weights. These two\n;*\tweights are added together and assigned a new node. The new\n;*\tnode makes the two minimum nodes into its 0 child and 1 child.\n;*\tThe two minimum nodes are then marked as inactive. This process\n;*\trepeats until their is only one node left, which is the root.\n;*---------------------------------------------------------------------------\n\t\n\tmov\teax,[temp]\t\t;Nodes array\n\tmov\tesi,eax\n\tadd\teax,(513 * 8)\t\t;Node[513] = guaranteed maximum\n\tmov\t[DWORD PTR eax],-1\n\n\tmov\t[next],((HUFF_EOS + 1) * 8)\n\n??sortnext:\n\tmov\tedx,(513 * 8)\t\t;first = 513\n\tmov\tedi,edx\t\t;last = 513\n\txor\tecx,ecx\t\t;i = 0\n\tmov\tebx,esi\t\t;nodes[i]\n\n??sortnodes:\n\tcmp\t[WORD PTR ebx],0\t;Only check non-zero nodes\n\tjz\t??nextnode\n\n;*\tnodes[i].count < nodes[first].count\n\n\tmov\teax,[DWORD PTR esi + edx]\n\tcmp\teax,[DWORD PTR ebx]\n\tjbe\t??checklast\n\n\tmov\tedi,edx\t\t;last = first\n\tmov\tedx,ecx\t\t;first = i\n\tjmp\tshort ??nextnode\n\n;*\tnodes[i].count < nodes[last].count\n\n??checklast:\n\tmov\teax,[DWORD PTR esi + edi]\n\tcmp\teax,[DWORD PTR ebx]\n\tjbe\t??nextnode\n\n\tmov\tedi,ecx\t\t;last = i\n\n??nextnode:\n\tadd\tecx,8\t\t;i++\n\tadd\tebx,8\t\t;nodes[i]\n\tcmp\tecx,[next]\n\tjne\tshort ??sortnodes\n\n;*\tTree done when last = 513\n\n\tcmp\tedi,(513 * 8)\n\tje\tshort ??decode\n\n\tmov\tebx,[next]\n\tadd\tebx,esi\n\tmov\t[WORD PTR ebx+4],dx\t;nodes[next].child0 = first\n\tmov\t[WORD PTR ebx+6],di\t;nodes[next].child1 = last\n\n\tadd\tedx,esi\n\tmov\teax,[DWORD PTR edx]\t;nodes[first].count\n\tadd\tedi,esi\n\tmov\t[DWORD PTR ebx],eax\n\t\n\tmov\tecx,[DWORD PTR edi]\t;nodes[last].count\n\txor\teax,eax\n\tadd\t[DWORD PTR ebx],ecx\n\n\tmov\t[DWORD PTR edx],eax\t;nodes[first].count = 0\n\tmov\t[DWORD PTR edi],eax\t;nodes[lats].count = 0\n\tadd\t[next],8\n\tjmp\t??sortnext\n\n;*---------------------------------------------------------------------------\n;*\tExpand the compressed data. As each new symbol is decoded, the\n;*\ttree is traversed, starting at the root node, reading a bit in,\n;*\tand taking either the child0 or child1 path. Eventually, the\n;*\ttree winds down to a leaf node, and the corresponding symbol is\n;*\toutput. If the symbol is the HUFF_EOS symbol the process\n;*\tterminates.\n;*---------------------------------------------------------------------------\n\n??decode:\n\tsub\t[next],8\t\t;rootnode - 1\n\txor\tecx,ecx\n\tmov\tesi,[data]\t\t;Input data buffer\n\tmov\tal,080h\t\t;mask = 0x80\n\tmov\tedi,[buffer]\t\t;Output buffer\n\tmov\tah,[esi]\t\t;Data byte\n\tmov\tebx,[temp]\n\tinc\tesi\n\n??decodeloop:\n\tmov\tedx,[next]\t\t;node = root\n\t\n??walktree:\n\tmov\tecx,4\n\tadd\tecx,edx\n\ttest\tal,ah\n\tjz\tshort ??getnode\n\n\tadd\tecx,2\n\n??getnode:\n\tmov\tdx,[WORD PTR ebx + ecx]\t\t;nodes[node].child\n\tshr\tal,1\n\tjnz\tshort ??checkleaf\n\n\tmov\tah,[esi]\t\t;Get next data byte\n\tmov\tal,080h\t\t;Reset mask\n\tinc\tesi\n\n??checkleaf:\n\tcmp\tedx,(HUFF_EOS * 8)\n\tjg\tshort ??walktree\n\tje\tshort ??done\n\n\tshr\tedx,3\n\tmov\t[edi],dl\n\tinc\tedi\n\tjmp\tshort ??decodeloop\n\n??done:\n\tmov\teax,edi\n\tsub\teax,[buffer]\n\tret\n\n\tENDP\tHuffDecompress\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     BuildHuffTree - Build the Huffman decode tree.\n;*\n;* SYNOPSIS\n;*     Root = BuildHuffTree(Nodes)\n;*\n;*     long BuildHuffTree(TreeNode *);\n;*\n;* FUNCTION\n;*     Build the Huffman tree. All active nodes are scanned in order to\n;*     locate the two nodes with the minimum weights. These two weights are\n;*     added together and assigned a new node. The new node makes the two\n;*     minimum nodes into its 0 child and 1 child. The two minimum nodes are\n;*     then marked as inactive. This process repeats until their is only one\n;*     node left, which is the root.\n;*\n;* INPUTS\n;*     Nodes - Pointer to array of nodes.\n;*\n;* RESULT\n;*     Root - Number of root node.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC BuildHuffTree:NEAR\n\tPROC\tBuildHuffTree C NEAR USES esi edi ebx ecx edx\n\n\tARG\ttemp:NEAR PTR\n\t\n\tLOCAL\tnext:DWORD\n\n\tmov\teax,[temp]\t\t;Nodes array\n\tmov\tesi,eax\n\tadd\teax,(513 * 8)\t\t;Node[513] = guaranteed maximum\n\tmov\t[DWORD PTR eax],-1\n\n\tmov\t[next],((HUFF_EOS + 1) * 8)\n\n??sortnext:\n\tmov\tedx,(513 * 8)\t\t;first = 513\n\tmov\tedi,edx\t\t;last = 513\n\txor\tecx,ecx\t\t;i = 0\n\tmov\tebx,esi\t\t;nodes[i]\n\n??sortnodes:\n\tcmp\t[WORD PTR ebx],0\t;Only check non-zero nodes\n\tjz\t??nextnode\n\n;*\tnodes[i].count < nodes[first].count\n\n\tmov\teax,[DWORD PTR esi + edx]\n\tcmp\teax,[DWORD PTR ebx]\n\tjbe\t??checklast\n\n\tmov\tedi,edx\t\t;last = first\n\tmov\tedx,ecx\t\t;first = i\n\tjmp\tshort ??nextnode\n\n;*\tnodes[i].count < nodes[last].count\n\n??checklast:\n\tmov\teax,[DWORD PTR esi + edi]\n\tcmp\teax,[DWORD PTR ebx]\n\tjbe\t??nextnode\n\n\tmov\tedi,ecx\t\t;last = i\n\n??nextnode:\n\tadd\tecx,8\t\t;i++\n\tadd\tebx,8\n\tcmp\tecx,[next]\n\tjne\tshort ??sortnodes\n\n;*\tTree done when last = 513\n\n\tcmp\tedi,(513 * 8)\n\tje\tshort ??done\n\n\tmov\tebx,[next]\n\tadd\tebx,esi\t\t;nodes[next]\n\tmov\t[WORD PTR ebx+4],dx\t;nodes[next].child0 = first\n\tmov\t[WORD PTR ebx+6],di\t;nodes[next].child1 = last\n\n\tadd\tedx,esi\n\tmov\teax,[DWORD PTR edx]\t;nodes[first].count\n\tadd\tedi,esi\n\tmov\t[DWORD PTR ebx],eax\n\n\tmov\tecx,[DWORD PTR edi]\t;nodes[last].count\n\txor\teax,eax \n\tadd\t[DWORD PTR ebx],ecx\n\n\tmov\t[DWORD PTR edx],eax\t;nodes[first].count = 0\n\tmov\t[DWORD PTR edi],eax\t;nodes[lats].count = 0\n\tadd\t[next],8\n\tjmp\t??sortnext\n\n??done:\n\tmov\teax,[next]\n\tsub\teax,8\n\tret\n\n\tENDP\tBuildHuffTree\n\n\tEND\n\n"
  },
  {
    "path": "WINVQ/VQM32/HUFFMAN.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef HUFFMAN_H\n#define HUFFMAN_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     huffman.h\n*\n* DESCRIPTION\n*     Huffman order 0 compress/decompress definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     May 19, 1995\n*\n****************************************************************************/\n\n\n/* TreeNode: Huffman decoding tree node.\n *\n * count  - Weight of the node in the tree.\n * child0 - Child node 0\n * child1 - Child node 1\n */\ntypedef struct _TreeNode {\n \tunsigned long  count;\n\tunsigned short child0;\n\tunsigned short child1;\n} TreeNode;\n\n\n/* HuffCode: This structure is used for storing the code for each symbol\n *            during encoding. A table of codes for each symbol is built\n *            from the Huffman tree.\n *\n * code - Code used to represent a symbol.\n * bits - Length of code in bits.\n */\ntypedef struct _HuffCode {\n\tunsigned short code;\n\tshort          bits;\n} HuffCode;\n\n\n#define HUFF_EOS 256 /* End of stream symbol */\n\n/* Prototypes */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nlong __cdecl HuffCompress(unsigned char *data, unsigned char *buffer,\n\t\tlong length, char *work);\n\nlong __cdecl HuffDecompress(unsigned char *data, unsigned char *buffer,\n\t\tlong length, char *work);\n\nvoid __cdecl HuffCount(unsigned char *data, TreeNode *nodes, long length,\n\t\tlong zero);\n\nvoid __cdecl HuffScaleCounts(TreeNode *nodes);\nlong __cdecl RLEHuffCounts(TreeNode *nodes, unsigned char *buffer);\nlong __cdecl BuildHuffTree(TreeNode *nodes);\n\nvoid __cdecl ConvertToCodes(TreeNode *nodes, HuffCode *codes,\n\t\tunsigned short code, short bits, short node);\n\nlong __cdecl HuffEncode(unsigned char *data, unsigned char *buffer,\n\t\tHuffCode *codes, long length);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* HUFFMAN_H */\n\n"
  },
  {
    "path": "WINVQ/VQM32/IFF.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     iff.c\n*\n* DESCRIPTION\n*     IFF manager. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*      \n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     OpenIFF          - Open an IFF for reading or writting.\n*     CloseIFF         - Close an IFF.\n*     ReadForm         - Read the IFF FORM, size and type of the file.\n*     WriteForm        - Write IFF form ID, size and type fields.\n*     ReadChunkHeader  - Read the IFF chunk identification header.\n*     WriteChunkHeader - Write an IFF chunk identification header.\n*     WriteChunk       - Write an IFF chunk with data from a buffer.\n*     WriteChunkBytes  - Write data from a buffer to the IFF stream.\n*     SkipChunkBytes   - Skip bytes in a chunk.\n*     FindChunk        - Scan for a specific chunk name.\n*     IDtoStr          - Convert a longword identifier to a NULL-terminated\n*                        string.\n*     CurrentFilePos   - Get the current file position.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <malloc.h>\n#include <io.h>\n#include <fcntl.h>\n#include <sys\\stat.h>\n#include <mem.h>\n#include \"iff.h\"\n\n\n/****************************************************************************\n*\n* NAME\n*     OpenIFF - Open an IFF for reading or writting.\n*\n* SYNOPSIS\n*     IFFHandle = OpenIFF(Name, Mode)\n*\n*     IFFHandle *OpenIFF(char *, long);\n*\n* FUNCTION\n*     Opens an IFF for a new read or write.  The direction of the I/O is\n*     given by the value of Mode, which can be either IFF_READ or IFF_WRITE.\n*\n* INPUTS\n*     Name - Pointer to name of file to open.\n*     Mode - IFF_READ or IFF_WRITE.\n*\n* RESULT\n*     IFFHandle - Pointer to IFFHandle structure or NULL if error.\n*\n****************************************************************************/\n\nIFFHandle *OpenIFF(char *name, long mode)\n{\n\tIFFHandle *iff;\n\n\t/* Allocate IFFHandle structure. */\n\tif ((iff = (IFFHandle *)malloc(sizeof(IFFHandle))) != NULL) {\n\n\t\t/* Initialize handle.*/\n\t\tmemset(iff, 0, sizeof(IFFHandle));\n\t\tiff->flags = mode;\n\n\t\tswitch (mode) {\n\t\t\tcase IFFF_READ:\n\t\t\t\tiff->fh = open(name, O_RDONLY|O_BINARY);\n\t\t\t\tbreak;\n\n\t\t\tcase IFFF_WRITE:\n\t\t\t\tiff->fh = open(name, (O_CREAT|O_TRUNC|O_WRONLY|O_BINARY),\n\t\t\t\t\t\t(S_IREAD|S_IWRITE));\n\n\t\t\t\tprintf(\"\\r\");\n\t\t\t\tbreak;\n\n\t\t\tcase (IFFF_READ|IFFF_WRITE):\n\t\t\t\tiff->fh = open(name, (O_RDWR|O_BINARY), (S_IREAD|S_IWRITE));\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tiff->fh = -1;\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/* If something went wrong we must free up any resources\n\t\t * that we have opened.\n\t\t */\n\t\tif (iff->fh == -1) {\n\t\t\tfree(iff);\n\t\t\tiff = NULL;\n\t\t}\n\t}\n\n\treturn (iff);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     CloseIFF - Close an IFF.\n*\n* SYNOPSIS\n*     CloseIFF(IFFHandle)\n*\n*     void CloseIFF(IFFHandle *);\n*\n* FUNCTION\n*     Completes an IFF read or write operation.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid CloseIFF(IFFHandle *iff)\n{\n\tlong length;\n\n\t/* Write the length of the FORM */\n\tif ((iff->flags & IFFF_WRITE) && ((iff->form.size == 0)\n\t\t\t|| (iff->scan > iff->form.size))) {\n\n\t\tlseek(iff->fh, 4, SEEK_SET);\n\t\tlength = REVERSE_LONG(iff->scan);\n\t\twrite(iff->fh, &length, 4);\n\t}\n\n\tclose(iff->fh);\n\tfree(iff);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     ReadForm - Read the IFF FORM, size and type of the file.\n*\n* SYNOPSIS\n*     Error = ReadForm(IFFHandle, FormHeader)\n*\n*     long ReadForm(IFFHandle *, FormHeader *);\n*\n* FUNCTION\n*     Read in the IFF form, size, type information. If the FormHeader\n*     structure pointer is NULL then the FORM will be read into the\n*     IFFHandles form structure.\n*\n* INPUTS\n*     IFFHandle  - Pointer to IFFHandle structure.\n*     FormHeader - Pointer to FormHeader structure.\n*\n* RESULT\n*     Error - 0 if successful or IFFERR_??? error code.\n*\n****************************************************************************/\n\nlong ReadForm(IFFHandle *iff, FormHeader *form)\n{\n\tFormHeader *ptr;\n \tlong       error;\n\n\t/* Read the FORM into the IFFHandle or the provided FormHeader. */\n\tif (form == NULL) {\n\t\tptr = &iff->form;\n\t} else {\n\t\tptr = form;\n\t}\n\n\t/* Read in IFF FORM from the file stream.. */\n\tif ((error = read(iff->fh, ptr, 12)) == 12) {\n\t\tptr->size = REVERSE_LONG(ptr->size);\n\t\tiff->scan = 4;\n\t\terror = 0;\n\t} else {\n\t\tif (error == -1)\n\t\t\terror = IFFERR_READ;\n\t\telse if (error == 0)\n\t\t\terror = IFFERR_EOF;\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     WriteForm - Write IFF form ID, size and type fields.\n*\n* SYNOPSIS\n*     Error = WriteForm(IFFHandle)\n*\n*     long WriteForm(IFFHandle, FormHeader *);\n*\n* FUNCTION\n*     Write out the IFF form, size, type information. If the size field\n*     is zero then the IFF form size will be calculated and written by\n*     the CloseIFF() function. If the FormHeader structure pointer is NULL\n*     the the form from the IFFHandle will be written.\n*\n* INPUTS\n*     IFFHandle  - Pointer to IFFHandle structure.\n*     FormHeader - Pointer to FormHeader structure.\n*\n* RESULT\n*     Error - 0 if successful or IFFERR_??? error code.\n*\n****************************************************************************/\n\nlong WriteForm(IFFHandle *iff, FormHeader *form)\n{\n\tFormHeader *ptr;\n\tlong       error = 0;\n\n\t/* Use the FORM from the IFFHandle or the provided FormHeader. */\n\tif (form == NULL) {\n\t\tptr = &iff->form;\n\t} else {\n\t\tptr = form;\n\t}\n\n\t/* Write the IFF form to the file stream. */\n\tif (iff->flags & IFFF_WRITE) {\n\t\tptr->size = REVERSE_LONG(ptr->size);\n\n\t\tif (write(iff->fh, ptr, 12) == 12) {\n\t\t\tiff->scan = 4;\n\t\t} else {\n\t\t\terror = IFFERR_WRITE;\n\t\t}\n\t} else {\n\t\terror = IFFERR_WRITE;\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     ReadChunkHeader - Read the IFF chunk identification header.\n*\n* SYNOPSIS\n*     Error = ReadChunkHeader(IFFHandle)\n*\n*     long ReadChunkHeader(IFFHandle *);\n*\n* FUNCTION\n*     Read the IFF identification header from the files data stream.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*\n* RESULT\n*     Error - 0 if successful or IFFERR_??? error code.\n*\n****************************************************************************/\n\nlong ReadChunkHeader(IFFHandle *iff)\n{\n\tlong error = 0;\n\n\t/* Skip any part of the previous chunk that hasn't been processed. */\n\tif ((iff->cn.size != 0) && (iff->cn.scan < PADSIZE(iff->cn.size))) {\n\t\terror = lseek(iff->fh, (PADSIZE(iff->cn.size) - iff->cn.scan), SEEK_CUR);\n\n\t\tif (error == -1) {\n\t\t\terror = IFFERR_READ;\n\t\t} else {\n\t\t\terror = 0;\n\t\t}\n\t}\n\n\t/* Read in the next chunk header context. */\n\tif (!error) {\n\t\tif ((error = read(iff->fh, &iff->cn, 8)) == 8) {\n\t\t\terror = 0;\n\t\t\tiff->scan += 8;\n\t\t\tiff->cn.size = REVERSE_LONG(iff->cn.size);\n\t\t\tiff->cn.scan = 0;\n\t\t} else {\n\t\t\tif (error == -1) {\n\t\t\t\terror = IFFERR_READ;\n\t\t\t}\telse if (error == 0) {\n\t\t\t\terror = IFFERR_EOF;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     WriteChunkHeader - Write an IFF chunk identification header.\n*\n* SYNOPSIS\n*     Error = WriteChunkHeader(IFFHandle, ID, Size)\n*\n*     long WriteChunkHeader(IFFHandle *, long, long);\n*\n* FUNCTION\n*     Write an IFF identification header to the files data stream.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*     ID        - ID code of chunk.\n*     Size      - Size of chunk in bytes (WORD aligned).\n*\n* RESULT\n*     Error - 0 if successful or IFFERR_??? error code.\n*\n****************************************************************************/\n\nlong WriteChunkHeader(IFFHandle *iff, long id, long size)\n{\n\tlong error = 0;\n\n\t/* Make sure it is okay to write. */\n\tif (iff->flags & IFFF_WRITE) {\n\t\tiff->cn.id = id;\n\t\tiff->cn.size = REVERSE_LONG(size);\n\t\tiff->cn.scan = 0;\n\n\t\tif (write(iff->fh, &iff->cn, 8) == 8) {\n\t\t\tiff->scan += 8;\n\t\t} else {\n\t\t\terror = IFFERR_WRITE;\n\t\t}\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     WriteChunk - Write an IFF chunk with data from a buffer.\n*\n* SYNOPSIS\n*     Actual = WriteChunk(IFFHandle, ID, Buffer, Size)\n*\n*     long WriteChunk(IFFHandle *, long, char *, long);\n*\n* FUNCTION\n*     Write a IFF chunk at the current file position.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*     ID        - ID code of chunk.\n*     Buffer    - Pointer to buffer area with bytes to be written.\n*     Size      - Number of bytes to write.\n*\n* RESULT\n*     Actual - (positive) Bytes written or (negative) IFFERR_??? error code.\n*\n****************************************************************************/\n\nlong WriteChunk(IFFHandle *iff, long id, char *buffer, long size)\n{\n\tContext cn;\n \tlong    actual;\n\n\t/* Make sure we can write to this file. */\n\tif (iff->flags & IFFF_WRITE) {\n\t\tcn.id = id;\n\t  cn.size = REVERSE_LONG(size);\n\n\t\t/* Write chunk header. */\n\t\tif (write(iff->fh, &cn, 8) == 8) {\n\t\t\tiff->scan += 8;\n\t\t\tiff->cn.scan += 8;\n\n\t\t\t/* Write chunk data. */\n\t\t\tactual = write(iff->fh, buffer, size);\n\n\t\t\tif (actual == size) {\n\t\t\t\tiff->scan += actual;\n\t\t\t\tiff->cn.scan += actual;\n\n\t\t\t\t/* Write chunk padding if necessary. */\n\t\t\t\tif (PADSIZE(size) > size) {\n\t\t\t\t\tid = 0;\n\n\t\t\t\t\tif (write(iff->fh, &id, 1) == 1) {\n\t\t\t\t\t\tiff->scan++;\n\t\t\t\t\t\tiff->cn.scan++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tactual = IFFERR_WRITE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tactual = IFFERR_WRITE;\n\t\t\t}\n\t\t} else {\n\t\t\tactual = IFFERR_WRITE;\n\t\t}\n\t} else {\n\t\tactual = IFFERR_WRITE;\n\t}\n\n\treturn (actual);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     WriteChunkBytes - Write data from a buffer to the IFF stream.\n*\n* SYNOPSIS\n*     Actual = WriteChunkBytes(IFFHandle, Buffer, Size)\n*\n*     long WriteChunk(IFFHandle *, char *, long);\n*\n* FUNCTION\n*     Write a IFF chunk at the current file position.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*     Buffer    - Pointer to buffer area with bytes to be written.\n*     Size      - Number of bytes to write.\n*\n* RESULT\n*     Actual - (positive) Bytes written or (negative) IFFERR_??? error code.\n*\n****************************************************************************/\n\nlong WriteChunkBytes(IFFHandle *iff, char *buffer, long size)\n{\n\tlong actual;\n\n\t/* Make sure we can write to this file. */\n\tif (iff->flags & IFFF_WRITE) {\n\n\t\t/* Write data. */\n\t\tif ((actual = (unsigned short)write(iff->fh, buffer, size)) == size) {\n\t\t\tiff->scan += actual;\n\t\t\tiff->cn.scan += actual;\n\t\t} else {\n\t\t\tactual = IFFERR_WRITE;\n\t\t}\n\t} else {\n\t\tactual = IFFERR_WRITE;\n\t}\n\n\treturn (actual);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     ReadChunkBytes - Read data from a chunk into a buffer.\n*\n* SYNOPSIS\n*     Actual = ReadChunkBytes(IFFHandle, Buffer, Length)\n*\n*     long ReadChunkBytes(IFFHandle *, char *, long);\n*\n* FUNCTION\n*     Read in 'Length' number of bytes from the current chunk context.\n*     If the specified length exceeds the number of bytes remaining in the\n*     chunk ReadChunkBytes() will read in only the number of remaining\n*     bytes. ReadChunkBytes() will never read beyond the scope of the\n*     current chunk.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*     Buffer    - Pointer to buffer to read data into.\n*     Length    - Number of bytes to read.\n*\n* RESULT\n*     Actual - (positive) Bytes written or (negative) IFFERR_??? error code.\n*\n****************************************************************************/\n\nlong ReadChunkBytes(IFFHandle *iff, char *buffer, long size)\n{\n\tlong actual;\n\n\t/* If the actual bytes remaining in the current chunk is less than\n\t * the requested bytes to read then adjust the read request size\n\t * to only read in the bytes that remain in the chunk.\n\t */\n\tactual = (iff->cn.size - iff->cn.scan);\n\n\tif (size > actual) {\n\t\tsize = actual;\n\t}\n\n\t/* Read in the requested number of bytes. */\n\tif ((actual = read(iff->fh, buffer, size)) != size) {\n\t\tactual = IFFERR_READ;\n\t} else {\n\t\tiff->scan += actual;\n\t\tiff->cn.scan += actual;\n\t}\n\n\treturn (actual);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     SkipChunkBytes - Skip bytes in a chunk.\n*\n* SYNOPSIS\n*     Error = SkipChunkBytes(IFFHandle, Skip)\n*\n*     long SkipChunkBytes(IFFHandle *, long);\n*\n* FUNCTION\n*     Skip the specified number of bytes of the chunk.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*     Skip      - Number of bytes to skip.\n*\n* RESULT\n*     Error - 0 if successful or FAIL_??? error code.\n*\n****************************************************************************/\n\nlong SkipChunkBytes(IFFHandle *iff, long skip)\n{\n\tlong error = 0;\n\n\tif (lseek(iff->fh, skip, SEEK_CUR) == -1) {\n\t\terror = IFFERR_READ;\n\t} else {\n\t\tiff->scan += skip;\n\t\tiff->cn.scan += skip;\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     FindChunk - Scan for a specific chunk name.\n*\n* SYNOPSIS\n*     Error = FindChunk(IFFHandle, ID)\n*\n*     long FindChunk(IFFHandle *, long);\n*\n* FUNCTION\n*     Scan from the current file position for the next occurance of the\n*     specified chunk ID. When a match is found the function will return\n*     with the matching chunk as the current context.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*     ID        - ID code of chunk.\n*\n* RESULT\n*     Error - 0 if successful or FAIL_??? error code.\n*\n****************************************************************************/\n\nlong FindChunk(IFFHandle *iff, long id)\n{\n\tlong found = 0;\n\tlong error = 0;\n\n\t/* Invalid handle check. */\n\tif (iff != NULL) {\n\n\t\t/* Scan until we have a match or an error. */\n\t\twhile ((found == 0) && !(error = ReadChunkHeader(iff))) {\n\n\t\t\t/* If we found a match the terminate scan, otherwise skip this\n\t\t\t * chunk and process the next.\n\t\t\t */\n\t\t\tif (iff->cn.id == id) {\n\t\t\t\tfound = 1;\n\t\t\t} else {\n\t\t\t\terror = SkipChunkBytes(iff, PADSIZE(iff->cn.size));\n\t\t\t}\n\t\t}\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     IDtoStr - Convert a longword identifier to a NULL-terminated string.\n*\n* SYNOPSIS\n*     String = IDtoStr(ID, Buffer)\n*\n*     char *IDtoStr(long, char *);\n*\n* FUNCTION\n*     Writes the ASCII equivalent of the given longword ID into buffer as a\n*     NULL-terminated string.\n*\n* INPUTS\n*     ID     - Longword ID.\n*     Buffer - Character buffer to accept string (at least 5 characters).\n*\n* RESULT\n*     String - The value of \"Buffer\".\n*\n****************************************************************************/\n\nchar *IDtoStr(long id, char *buf)\n{\n\tmemcpy(buf, &id, 4);\n\t*(buf + 4) = 0;\n\n\treturn (buf);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     CurrentFilePos - Get the current file position.\n*\n* SYNOPSIS\n*     Position = CurrentFilePos(IFFHandle)\n*\n*     long CurrentFilePos(IFFHandle *);\n*\n* FUNCTION\n*     This function returns the offset in bytes of the current file position\n*     from the beginning of the IFF.\n*\n* INPUTS\n*     IFFHandle - Pointer to IFFHandle structure.\n*\n* RESULT\n*     Position - Offset in bytes from the beginning of the file to the\n*                current position.\n*\n****************************************************************************/\n\nlong CurrentFilePos(IFFHandle *iff)\n{\n\tlong offset;\n\n\tif ((offset = lseek(iff->fh, 0, SEEK_CUR)) == -1) {\n\t\toffset = IFFERR_READ;\n\t}\n\n\treturn (offset);\n}\n\n"
  },
  {
    "path": "WINVQ/VQM32/IFF.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMIFF_H\n#define VQMIFF_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     iff.h\n* \n* DESCRIPTION\n*     IFF (Interchange File Format) manager definitions.\n*     (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/* FormHeader - Structure associated with IFF forms.\n *\n * id   - IFF form id (IE: \"FORM\")\n * size - Length of IFF in bytes\n * type - Form type (IE: \"ILBM\")\n */\ntypedef struct _FormHeader {\n\tlong id;\n\tlong size;\n\tlong type;\n} FormHeader;\n\n/* Context - Structure associated with chunks.\n *\n * id   - Chunk identifier.\n * size - Size of chunk in bytes.\n * scan - Bytes read/written.\n */\ntypedef struct _Context {\n\tlong id;\n\tlong size;\n\tlong scan;\n} Context;\n\n/* IFFHandle - Structure associated with an active IFF read\\write session.\n *\n * fh    - DOS filehandle\n * flags - Internal flags used by IFF routines.\n * form  - IFF form information.\n * scan  - Bytes read/written\n * cn    - Context of current chunk.\n */\ntypedef struct _IFFHandle {\n\tlong       fh;\n\tlong       flags;\n\tFormHeader form;\n\tlong       scan;\n\tContext    cn;\n} IFFHandle;\n\n/*\tbit masks for \"flags\" field. */\n#define IFFB_READ  0\n#define IFFB_WRITE 1\n#define IFFF_READ  (1<<IFFB_READ)\n#define IFFF_WRITE (1<<IFFB_WRITE)\n\n/* IFF return codes. Most functions return either zero for success or\n * one of these codes. The exceptions are the read/write functions which,\n * return positive values for number of bytes read or written, or a negative\n * error code.\n *\n * IFFERR_EOF   - End of file.\n * IFFERR_READ  - Read error.\n * IFFERR_WRITE - Write error.\n * IFFERR_NOMEM - Unable to allocate memory.\n */\n#define IFFERR_EOF   -1\n#define IFFERR_READ  -2\n#define IFFERR_WRITE -3\n#define IFFERR_NOMEM -4\n\n/* Macros to make things easier. */\n#define REVERSE_LONG(id) (unsigned long)((((unsigned long)(id)>>24) \\\n\t\t&0x000000FFL)|(((unsigned long)(id)>>8) \\\n\t\t&0x0000FF00L)|(((unsigned long)(id)<<8) \\\n\t\t&0x00FF0000L)|(((unsigned long)(id)<<24)&0xFF000000L))\n\n#define REVERSE_WORD(id) ((unsigned short)((((unsigned short)(id)<<8) \\\n\t\t&0x00FF00)|(((unsigned short)(id)>>8)&0x0FF)))\n\n#define PADSIZE(size) (((size)+1)&(~1))\n\n#ifndef MAKE_ID\n#define MAKE_ID(a,b,c,d) ((long)((long)(d)<<24)|((long)(c)<<16)| \\\n\t\t((long)(b)<<8)|(long)(a))\n#endif\n\n/* Universal IFF identifiers */\n#define ID_FORM MAKE_ID('F','O','R','M')\n#define ID_LIST MAKE_ID('L','I','S','T')\n#define ID_PROP MAKE_ID('P','R','O','P')\n#define ID_NULL MAKE_ID(' ',' ',' ',' ')\n\n/* Prototypes */\nIFFHandle *OpenIFF(char *, long);\nvoid CloseIFF(IFFHandle *);\nlong ReadForm(IFFHandle *, FormHeader *);\nlong WriteForm(IFFHandle *, FormHeader *);\nlong ReadChunkHeader(IFFHandle *);\nlong WriteChunkHeader(IFFHandle *, long, long);\nlong WriteChunk(IFFHandle *, long, char *, long);\nlong WriteChunkBytes(IFFHandle *, char *, long);\nlong ReadChunkBytes(IFFHandle *, char *, long);\nlong SkipChunkBytes(IFFHandle *, long);\nlong FindChunk(IFFHandle *, long);\nchar *IDtoStr(long, char *);\nlong CurrentFilePos(IFFHandle *);\n\n#endif /* VQMIFF_H */\n\n"
  },
  {
    "path": "WINVQ/VQM32/LCWCOMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     lcwcomp.asm\n;*\n;* DESCRIPTION\n;*     LCW compression code. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Louis Castle\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     LCW_Compress - LCW compress a buffer of memory.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     LCW_Compress - LCW compress a buffer of memory.\n;*\n;* SYNOPSIS\n;*     Size = LCW_Compress(Source, Dest, Length)\n;*\n;*     long LCW_Compress(void *, void *, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Source - Pointer to data to compress.\n;*     Dest   - Pointer to buffer to put compressed data.\n;*     Length - Length in bytes of data to compress.\n;*\n;* RESULT\n;*     Size - Size in bytes of compresed data.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC LCW_Compress:NEAR\n\tPROC\tLCW_Compress C NEAR USES ebx ecx edx esi edi\n\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tdatasize:DWORD\n\n\tLOCAL\tinlen:DWORD\n\tLOCAL\ta1stdest:DWORD\n\tLOCAL\ta1stsrc:DWORD\n\tLOCAL\tlenoff:DWORD\n\tLOCAL\tndest:DWORD\n\tLOCAL\tcount:DWORD\n\tLOCAL\tmatchoff:DWORD\n\tLOCAL\tend_of_data:DWORD\n\n\tmov\tesi,[source]\n\tmov\tedi,[dest]\n\tmov\tedx,[datasize]\n\n\tcld\t\t\t;Forward direction\n\tmov\tebx,esi\n\tadd\tebx,edx\n\tmov\t[end_of_data],ebx\t;Save end of source address\n\tmov\t[inlen],1\t\t;Set the in-length flag\n\tmov\t[a1stdest],edi\t \t;Save original dest\n\tmov\t[a1stsrc],esi\t \t;Save original source\n\tmov\t[lenoff],edi\t \t;Save offset length\n\n\tmov\tal,081h\t\t;First byte is always a len\n\tstosb\t\t\t;Write out a len of 1\n\tlodsb\t\t\t;Get the byte\n\tstosb\t\t\t;Save it\n\n??loop:\n\tmov\t[ndest],edi\t\t;Save offset of compressed data\n\tmov\tedi,[a1stsrc]\t\t;Get address of first byte\n\tmov\t[count],1\t\t;Set the count of run to 0\n\n??searchloop:\n \tsub\teax,eax\n\tmov\tal,[esi]\t\t;Get the current byte of data\n\tcmp\tal,[esi + 64]\n\tjne\tshort ??notrunlength\n\n\tmov\tebx,edi\n\tmov\tedi,esi\n\tmov\tecx,[end_of_data]\n\tsub\tecx,edi\n   \trepe\tscasb\n\tdec\tedi\n\tmov\tecx,edi\n\tsub\tecx,esi\n\tcmp\tecx,65\n\tjb\tshort ??notlongenough\n\n\tmov\t[inlen],0\t\t;Clear the in-length flag\n\tmov\tesi,edi\n\tmov\tedi,[ndest]\n\tmov\tah,al\n\tmov\tal,0FEh\n\tstosb\n\txchg\tecx,eax\n\tstosw\n\tmov\tal,ch\n\tstosb\n\n\tmov\t[ndest],edi\t\t;Save offset of compressed data\n\tmov\tedi,ebx\n\tjmp\t??searchloop\n\n??notlongenough:\n\tmov\tedi,ebx\n\n??notrunlength:\n??oploop:\n\tmov\tecx,esi\t\t;Address of the last byte +1\n\tsub\tecx,edi\t\t;Total number of bytes left\n\tjz\tshort ??searchdone\n\n\trepne\tscasb\t\t;Look for a match\n\tjne\tshort ??searchdone\t;If we don't find one we're done\n\n\tmov\tebx,[count]\n\tmov\tah,[esi+ebx-1]\n\tcmp\tah,[edi+ebx-2]\n\tjne\t??oploop\n\n\tmov\tedx,esi\t\t;Save address for the next search\n\tmov\tebx,edi\t\t;Save address for the length calc\n\tdec\tedi\t\t;Back up one for compare\n\tmov\tecx,[end_of_data]\t;Get the end of data\n\tsub\tecx,esi\t\t;Sub current source for max len\n\trepe\tcmpsb  \t\t;See how many bytes match\n\tjne\tshort ??notend\n\n\tinc\tedi\n\n??notend:\n\tmov\tesi,edx\n\tmov\teax,edi\t\t;Get the dest\n\tsub\teax,ebx\t\t;Sub the start for total bytes that match\n\tmov\tedi,ebx\t\t;Restore dest\n\tcmp\teax,[count]\t\t;See if its better than before\n\tjb\t??searchloop\t\t;If not keep looking\n\n\tmov\t[count],eax\t\t;If so keep the count\n\tdec\tebx\t\t;Back it up for the actual match offset\n\tmov\t[matchoff],ebx \t;Save the offset for later\n\tjmp\t??searchloop\t\t;Loop until we searched it all\n\n??searchdone:\n\tmov\tecx,[count]\t\t;Get the count of the longest run\n\tmov\tedi,[ndest]\t\t;Get the paragraph of our compressed data\n\tcmp\tecx,2\t\t;See if its not enough run to matter\n\tjbe\tshort ??lenin\t\t;If its 0,1, or 2 its too small\n\n\tcmp\tecx,10\t\t;If not, see if it would fit in a short\n\tja\tshort ??medrun\t\t;If not, see if its a medium run\n\n\tmov\teax,esi\t\t;If its short get the current address\n\tsub\teax,[matchoff] \t;Sub the offset of the match\n\tcmp\teax,0FFFh\t\t;If its less than 12 bits its a short\n\tja\tshort ??medrun\t\t;If its not, its a medium\n\n??shortrun:\n\tmov\tbl,cl\t\t;Get the length (3-10)\n\tsub\tbl,3\t\t;Sub 3 for a 3 bit number 0-7\n\tshl\tbl,4\n\tadd\tah,bl\n\txchg\tah,al\n\tjmp\tshort ??srunnxt\t;Do the run fixup code\n\n??medrun:\n\tcmp\tecx,64\t\t;See if its a short run\n\tja\tshort ??longrun\t;If not, oh well at least its long\n\n\tsub\tcl,3\t\t;Back down 3 to keep it in 6 bits\n\tor\tcl,0C0h\t\t;The highest bits are always on\n\tmov\tal,cl\t\t;Put it in al for the stosb\n\tstosb\t\t\t;Store it\n\tjmp\tshort ??medrunnxt \t;Do the run fixup code\n\n??lenin:\n\tcmp\t[inlen],0\t\t;Is it doing a length?\n\tjnz\tshort ??len\t\t;If so, skip code\n\n??lenin1:\n\tmov\t[lenoff],edi\t\t;Save the length code offset\n\tmov\tal,80h\t\t;Set the length to 0\n\tstosb\t\t\t;Save it\n\n??len:\n\tmov\tebx,[lenoff]\t\t;Get the offset of the length code\n\tcmp\t[BYTE PTR ebx],0BFh\t;See if its maxed out\n\tje\t??lenin1\t\t;If so put out a new len code\n\n??stolen:\n\tinc\t[BYTE PTR ebx] \t;Inc the count code\n\tlodsb\t\t\t;Get the byte\n\tstosb\t\t\t;Store it\n\tmov\t[inlen],1\t\t;We are now in a length so save it\n\tjmp\tshort ??nxt\t\t;Do the next code\n\n??longrun:\n\tmov\tal,0FFh\t\t;Its a long so set a code of FF\n\tstosb\t\t\t;Store it\n\tmov\teax,[count]\t\t;Send out the count\n\tstosw\t\t\t;Store it\n\n??medrunnxt:\n\tmov\teax,[matchoff] \t;Get the offset\n\tsub\teax,[a1stsrc]\t\t;Make it relative tot he start of data\n\n??srunnxt:\n\tstosw\t\t\t;Store it\n\tadd\tesi,[count]\t\t;Add in the length of the run to the source\n\tmov\t[inlen],0\t\t;Set the in leght flag to false\n\n??nxt:\n\tcmp\tesi,[end_of_data]\t;See if we did the whole pic\n\tjae\tshort ??out\t\t;If so, cool! were done\n\tjmp\t??loop\n\n??out:\n\tmov\teax,080h\t\t;Remember to send an end of data code\n\tstosb\t\t\t;Store it\n\tmov\teax,edi\t\t;Get the last compressed address\n\tsub\teax,[a1stdest]\t\t;Sub the first for the compressed size\n\tret\n\n\tENDP\tLCW_Compress\n\n\tEND\n"
  },
  {
    "path": "WINVQ/VQM32/LCWUNCMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     lcwuncmp.asm\n;*\n;* DESCRIPTION\n;*     LCW uncompress routine. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Chris Yates\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     LCW_Uncompress - Uncompress LCW encoded data.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     LCW_Uncompress - Uncompress LCW encoded data.\n;*\n;* SYNOPSIS\n;*     Size = LCW_Uncompress(Source, Dest, Length)\n;*\n;*     LONG LCW_Uncompress(void *, void *, long);\n;*\n;* FUNCTION\n;*     Uncompress data to the following codes in the format b = byte,\n;*     w = word, n = byte code pulled from compressed data.\n;*\n;*     Bit field of n            Command     Description\n;*     ------------------------------------------------------------------\n;*     n=0xxxyyyy,yyyyyyyy       short run   back y bytes and run x+3\n;*     n=10xxxxxx,n1,n2,..,nx+1  med length  copy the next x+1 bytes\n;*     n=11xxxxxx,w1             med run     run x+3 bytes from offset w1\n;*     n=11111111,w1,w2          long copy   copy w1 bytes from offset w2\n;*     n=11111110,w1,b1          long run    run byte b1 for w1 bytes\n;*     n=10000000                end         end of data reached\n;*\n;* INPUTS\n;*     Source - Pointer to LCW encoded data.\n;*     Dest   - Pointer to buffer to uncompress into.\n;*     Length -\n;*\n;* RESULT\n;*     Size - Size of uncompressed data in bytes.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC LCW_Uncompress:NEAR\n\tPROC\tLCW_Uncompress C NEAR USES ebx ecx edx esi edi\n\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tlength:DWORD\n\n\tLOCAL\ta1stdest:DWORD\n\tLOCAL\tmaxlen:DWORD\n\tLOCAL\tlastbyte:DWORD\n\tLOCAL\tlastcom:DWORD\n\tLOCAL\tlastcom1:DWORD\n\n\tmov\tesi,[source]\t\t;ESI - Source address\n\tmov\tedi,[dest]\t\t;EDI - Destination address\n\tmov\tedx,[length]\t\t;EDX - Maximum length\n\n\tmov\t[a1stdest],edi\t\t;Save dest address\n\tadd\tedx,edi\t\t;Last address (Dest + length)\n\tmov\t[lastbyte],edx\n\n\tcld\t\t\t;Forward direction\n\tmov\tebx,esi\t\t;Save source address\n\n??loop:\n;\tExit if no bytes are remaining.\n\n\tmov\teax,[lastbyte]\n\tsub\teax,edi\n\tjz\tshort ??out\n\n\tmov\t[maxlen],eax\t\t;Save for string commands\n\tmov\tesi,ebx\t\t;Restore source address\n\tlodsb\n\tor\tal,al\t\t;See if its a short run\n\tjs\tshort ??notshort\n\n\tmov\tah,al\t\t;Put rel offset high nibble in ah\n\tand\tah,0Fh\t\t; Only 4 bits count\n \tsub\tecx,ecx\n\tmov\tch,al\t\t;Put count nibble in ch\n\tshr\tch,4\n\tmov\tcl,ch\n\txor\tch,ch\n\tadd\tecx,3\t\t;Get actual run length\n\tcmp\tecx,[maxlen]\t\t;Is it too big to fit?\n\tjbe\tshort ??rsok\t\t;If not, its ok\n\n\tmov\tecx,[maxlen]\t\t;If so, max it out so it dosen't overrun\n\n??rsok:\n\tlodsb\t\t\t;Get rel offset low byte\n\tmov\tebx,esi\t\t;Save the source address\n\tmov\tesi,edi\t\t;Get the current dest\n\tsub\tesi,eax\t\t;Get relative offset\n\trep\tmovsb\n\tjmp\t??loop\n\n??notshort:\n\ttest\tal,40h\t\t;Is it a length?\n\tjne\tshort ??notlength\t;If not it could be med or long run\n\n;\tIf end code then exit.\n\n\tcmp\tal,80h\n\tje\tshort ??out\n\n\tmov\tcl,al\t\t;Put the byte in count register\n\tand\tecx,3Fh\t\t;Mask off the extra bits\n\tcmp\tecx,[maxlen]\t\t;Is it too big to fit?\n\tjbe\tshort ??lenok\t\t;If not, its ok\n\n\tmov\tecx,[maxlen]\t\t;If so, max it out so it dosen't overrun\n\n??lenok:\n\trep\tmovsb\n\tmov\tebx,esi\t\t;Save the source offset\n\tjmp\t??loop\n\n??out:\n      \tmov\teax,edi\n\tsub\teax,[a1stdest]\n\tjmp\tshort ??exit\n\n??notlength:\n\tmov\tcl,al\t\t;Get the entire code\n\tand\tecx,3Fh\t\t;Mask off all but the size -3\n\tadd\tecx,3\t\t;Add 3 for byte count\n\tcmp\tal,0FEh\n\tjne\tshort ??notrunlength\n\n\tsub\teax,eax\n\tlodsw\n\tmov\tecx,eax\n\tsub\teax,eax\n\tlodsb\n\tmov\tebx,esi\t\t;Save the source offset\n\tcmp\tecx,[maxlen]\t\t;Is it too big to fit?\n\tjbe\tshort ??runlenok\t;If not, its ok\n\n\tmov\tecx,[maxlen]\t\t;If so, max it out so it dosen't overrun\n\n??runlenok:\n\trep\tstosb\n\tjmp\t??loop\n\n??notrunlength:\n\tcmp\tal,0FFh\t\t;Is it a long run?\n\tjne\tshort ??notlong\t;If not use the code as the size\n\n\tsub\teax,eax\n\tlodsw\t\t\t;If so, get the size\n\tmov\tecx,eax\t\t;Put int the count byte\n\n??notlong:\n\tlodsw\t\t\t;Get the rel index\n\tmov\tebx,esi\t\t;Save the source offset\n\tadd\teax,[a1stdest]\t\t;Add in the first index\n\tmov\tesi,eax\t\t;Use this as a source\n\tcmp\tecx,[maxlen]\t\t;Is it too big to fit?\n\tjbe\tshort ??runok\t\t;If not, its ok\n\n\tmov\tecx,[maxlen]\t\t;If so, max it out so it dosen't overrun\n\n??runok:\n\trep\tmovsb\n\tjmp\t??loop\n\n??exit:\n\tmov\teax,edi\n\tmov\tebx,[dest]\n\tsub\teax,ebx\t\t;Calculate bytes uncompressed.\n\tret\n\n\tENDP\tLCW_Uncompress\n\n\tEND\n        \n"
  },
  {
    "path": "WINVQ/VQM32/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQMisc 32-bit library. (Watcom/4GW)\n#\n# FILE\n#     makefile\n#\n# DESCRIPTION\n#     Makefile for generating VQMisc32 library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n# \n# DATE\n#     Feburary 10, 1995\n#\n#****************************************************************************\n\n.OPTIMIZE\n.ERASE\n\n#----------------------------------------------------------------------------\n# PROJECTS DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJ\t\t= ..\nPRJNAME = vqm32wp\nPRJDIR  = $(PRJ)\\VQM32\nWATCOM\t= c:\\watcom\n\nOBJECTS = &\n\tiff.obj &\n\tprofile.obj &\n\taudzap.obj &\n\taudunzap.obj &\n\ttarga.obj &\n\tvertag.obj &\n\tsortpal.obj &\n\tpalette.obj &\n\tmono.obj &\n\tlcwuncmp.obj &\n\tlcwcomp.obj &\n\ttestvb.obj &\n\tvb.obj &\n\tmcgabuf.obj &\n\tvideo.obj &\n\txmode.obj &\n\txmodepg.obj &\n\tvesabuf.obj &\n\tvesablit.obj &\n\tvesavid.obj &\n\tsoscodec.obj &\n\tchrwidth.obj &\n\tmixfile.obj &\n\tcrc.obj &\n\tfillrect.obj &\n\tcaptoken.obj &\n\thuffcmp.obj &\n\thuffdcmp.obj &\n\tmem.obj &\n\tdrawchar.obj &\n\ttextprnt.obj &\n\tfont.obj &\n\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!ifdef %LIB\nLIBPATH = $(PRJ)\\LIB;$(%LIB)\n!else\nLIBPATH = $(PRJ)\\LIB;$(WATCOM)\\LIB386\n!endif\n\n!ifdef %INCLUDE\nINCLUDEPATH = $(PRJ)\\INCLUDE;$(%INCLUDE)\n!else\nINCLUDEPATH = $(PRJ)\\INCLUDE;$(WATCOM)\\H\n!endif\n\npath_c   = .\\\npath_cpp = .\\\npath_h   = .\\\npath_asm = .\\\npath_i   = .\\\npath_obj = .\\O\npath_lib = $(PRJ)\\LIB\npath_exe = .\\\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULE EXTENSIONS AND PATHS\n#----------------------------------------------------------------------------\n\n.EXTENSIONS :\n.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i\n\n.c : $(path_c)\n.cpp : $(path_cpp)\n.h : $(path_h)\n.asm : $(path_asm)\n.i : $(path_i)\n.obj : $(path_obj)\n.lib : $(path_lib)\n.exe : $(path_exe)\n\n#----------------------------------------------------------------------------\n# TOOLS, COMMANDS AND CONFIGURATIONS\n#----------------------------------------------------------------------------\n\nCC_CMD   = wcc386\nCCP_CMD  = wpp386\nASM_CMD  = tasm32\nLINK_CMD = wlink\nLIB_CMD  = wlib\n\nCC_OPTS  = -i$(INCLUDEPATH) -j -zp1 -5r -mf -oaeilrt -s -zq\nASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /dPHARLAP_TNT=0\nLIB_OPTS = /b /c /q\nLINK_CFG = $(PRJNAME).lnk\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall : $(PRJNAME).lib .SYMBOLIC\n\n$(PRJNAME).lib : $(OBJECTS) .SYMBOLIC\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj :\n  $(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.cpp.obj :\n  $(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\\$^.\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\nupdate: .SYMBOLIC\n\t@echo Updating VQMisc32 header files!\n\t@copy *.h $(PRJ)\\INCLUDE\\VQM32 >NUL\n\t@copy *.i $(PRJ)\\INCLUDE\\VQM32 >NUL\n\n\u001a"
  },
  {
    "path": "WINVQ/VQM32/MAKEFILE.BOR",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#       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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQMisc32 library. (Borland/TNT)\n#\n# FILE\n#     makefile\n#\n# DESCRIPTION\n#     Makefile for generating VQMisc32 library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n# \n# DATE\n#     Febuary 7, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     BCDIR  - Borland C installation path.\n#     TNTDIR - Pharlap/TNT installation path.\n#\n#****************************************************************************\n\n.AUTODEPEND\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n!if !$d(PRJ) || !$d(PRJVCS) || !$d(BCDIR) || !$d(TNTDIR)\n!error Environment not configured.\n!endif\n\n#----------------------------------------------------------------------------\n# PROJECT DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJNAME = VQM32BP\nPRJDIR  = $(PRJ)\\VQM32\n\nOBJECTS = \\\n\tiff.obj \\\n\tprofile.obj \\\n\taudzap.obj \\\n\taudunzap.obj \\\n\ttarga.obj \\\n\tvertag.obj \\\n\tsortpal.obj \\\n \tpalette.obj \\\n\tmono.obj \\\n\tlcwuncmp.obj \\\n\tlcwcomp.obj \\\n\ttestvb.obj \\\n\tvb.obj \\\n\tmcgabuf.obj \\\n\tvideo.obj \\\n\txmode.obj \\\n\txmodepg.obj \\\n\tvesabuf.obj \\\n\tvesablit.obj \\\n\tvesavid.obj \\\n\tsoscodec.obj \\\n\tdrawchar.obj \\\n\ttextprnt.obj \\\n\tfont.obj \\\n\tchrwidth.obj \\\n\tmixfile.obj \\\n\tcrc.obj \\\n\tfillrect.obj \\\n\tcaptoken.obj \\\n\thuffcmp.obj \\\n\thuffdcmp.obj \\\n\tmem.obj \\\n\tportio.obj \\\n\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!if $d(LIB)\nLIBPATH = $(PRJ)\\LIB;$(LIB)\n!else\nLIBPATH = $(PRJ)\\LIB;$(TNTDIR)\\LIB;$(BCDIR)\\LIB\n!endif\n\n!if $d(INCLUDE)\nINCLUDEPATH = $(PRJ)\\INCLUDE;$(INCLUDE)\n!else\nINCLUDEPATH = $(PRJ)\\INCLUDE;$(TNTDIR)\\INCLUDE;$(BCDIR)\\INCLUDE\n!endif\n\n.path.asm = $(PRJDIR)\n.path.c   = $(PRJDIR)\n.path.cpp = $(PRJDIR)\n.path.h   = $(PRJDIR)\n.path.exe = $(PRJDIR)\n.path.obj = $(PRJDIR)\\OBJ\n.path.sym = $(PRJDIR)\\OBJ\n.path.lib = $(PRJ)\\LIB\n\n#----------------------------------------------------------------------------\n# TOOLS, COMMANDS AND CONFIGURATIONS\n#----------------------------------------------------------------------------\n\nCC_CMD   = bcc32\nASM_CMD  = tasm32\nLINK_CMD = tlink32\nLIB_CMD  = tlib\n\nCC_CFG    = bcc32.cfg\nASM_CFG   = tasm32.cfg\nLINK_CFG  = tlink32.cfg\nLIB_CFG   = tlib.cfg\nCFG_FILES = $(CC_CFG) $(ASM_CFG) $(LINK_CFG) $(LIB_CFG)\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall: $(PRJNAME).lib\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj:\n  $(CC_CMD) -P- -n$(.path.obj) {$< }\n\n.cpp.obj:\n  $(CC_CMD) -P -n$(.path.obj) {$< }\n\n.asm.obj:\n  $(ASM_CMD) @$(ASM_CFG) $<,$(.path.obj)\\$&\n\n#----------------------------------------------------------------------------\n# BUILD THE LIBRARY\n#----------------------------------------------------------------------------\n\n$(PRJNAME).lib: $(OBJECTS)\n\t- @del $(.path.lib)\\$(PRJNAME).lib >&NUL\n\t$(LIB_CMD) $(.path.lib)\\$(PRJNAME).lib @$(LIB_CFG) @&&|\n-+$(**: = -+)\n|\n\t- @copy *.h $(PRJ)\\INCLUDE\\VQM32 >&NUL\n\t- @copy *.i $(PRJ)\\INCLUDE\\VQM32 >&NUL\n\n#----------------------------------------------------------------------------\n# ALL OBJECTS DEPEND ON THE CONFIGURATION FILES\n#----------------------------------------------------------------------------\n\n$(OBJECTS): $(CFG_FILES)\n\n#----------------------------------------------------------------------------\n# COMPILER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(CC_CFG): makefile\n\tcopy &&|\n-c\n-3\n-d\n-H=$(.path.sym)\\headers.sym\n-wpro\n-weas\n-wpre\n-I$(INCLUDEPATH)\n-DPHARLAP_TNT=1\n#-v\n| $(CC_CFG)\n \n#----------------------------------------------------------------------------\n# ASSEMBLER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(ASM_CFG): makefile\n\tcopy &&|\n/t\n/m\n/w+\n/jJUMPS\n/ml\n/p\n/z\n/i$(PRJ)\\INCLUDE\n/zi\n/dPHARLAP_TNT=1\n| $(ASM_CFG)\n\n#----------------------------------------------------------------------------\n# LINKER CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(LINK_CFG): makefile\n\tcopy &&|\n/c\n/m\n/Gm\n-L$(LIBPATH)\n-v\n| $(LINK_CFG)\n\n#----------------------------------------------------------------------------\n# LIBRARIAN CONFIGURATION\n#----------------------------------------------------------------------------\n\n$(LIB_CFG):\tmakefile\n\tcopy &&|\n/C /E\n| $(LIB_CFG)\n\n"
  },
  {
    "path": "WINVQ/VQM32/MAKEFILE.WAT",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#****************************************************************************\n#\n#        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\n#\n#----------------------------------------------------------------------------\n#\n# PROJECT\n#     VQMisc 32-bit library. (Watcom/4GW)\n#\n# FILE\n#     makefile\n#\n# DESCRIPTION\n#     Makefile for generating VQMisc32 library.\n#\n# PROGRAMMER\n#     Denzil E. Long, Jr.\n# \n# DATE\n#     Feburary 10, 1995\n#\n# ENVIROMENT\n#     PRJ    - Projects path.\n#     PRJVCS - Version control archive path.\n#     WATCOM - Watcom C installation path.\n#\n#****************************************************************************\n\n.OPTIMIZE\n.ERASE\n\n#----------------------------------------------------------------------------\n# VERIFY ENVIROMENT\n#----------------------------------------------------------------------------\n\n!ifndef %PRJ || %PRJVCS || %WATCOM\n!error Environment not configured.\n!endif\n\n#----------------------------------------------------------------------------\n# PROJECTS DEPENDENT MACROS\n#----------------------------------------------------------------------------\n\nPRJNAME = vqm32wp\nPRJDIR  = $(%PRJ)\\VQM32\n\nOBJECTS = &\n\tiff.obj &\n\tprofile.obj &\n\taudzap.obj &\n\taudunzap.obj &\n\ttarga.obj &\n\tvertag.obj &\n\tsortpal.obj &\n\tpalette.obj &\n\tmono.obj &\n\tlcwuncmp.obj &\n\tlcwcomp.obj &\n\ttestvb.obj &\n\tvb.obj &\n\tmcgabuf.obj &\n\tvideo.obj &\n\txmode.obj &\n\txmodepg.obj &\n\tvesabuf.obj &\n\tvesablit.obj &\n\tvesavid.obj &\n\tsoscodec.obj &\n\tdrawchar.obj &\n\ttextprnt.obj &\n\tfont.obj &\n\tchrwidth.obj &\n\tmixfile.obj &\n\tcrc.obj &\n\tfillrect.obj &\n\tcaptoken.obj &\n\thuffcmp.obj &\n\thuffdcmp.obj &\n\tmem.obj &\n\n#----------------------------------------------------------------------------\n# PATH MACROS\n#----------------------------------------------------------------------------\n\n!ifdef %LIB\nLIBPATH = $(%PRJ)\\LIB;$(%LIB)\n!else\nLIBPATH = $(%PRJ)\\LIB;$(%WATCOM)\\LIB386\n!endif\n\n!ifdef %INCLUDE\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%INCLUDE)\n!else\nINCLUDEPATH = $(%PRJ)\\INCLUDE;$(%WATCOM)\\H\n!endif\n\npath_c   = .\\\npath_cpp = .\\\npath_h   = .\\\npath_asm = .\\\npath_i   = .\\\npath_obj = .\\O\npath_lib = $(%PRJ)\\LIB\npath_exe = .\\\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULE EXTENSIONS AND PATHS\n#----------------------------------------------------------------------------\n\n.EXTENSIONS :\n.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i\n\n.c : $(path_c)\n.cpp : $(path_cpp)\n.h : $(path_h)\n.asm : $(path_asm)\n.i : $(path_i)\n.obj : $(path_obj)\n.lib : $(path_lib)\n.exe : $(path_exe)\n\n#----------------------------------------------------------------------------\n# TOOLS, COMMANDS AND CONFIGURATIONS\n#----------------------------------------------------------------------------\n\nCC_CMD   = wcc386\nCCP_CMD  = wpp386\nASM_CMD  = tasm32\nLINK_CMD = wlink\nLIB_CMD  = wlib\n\nCC_OPTS  = -i$(INCLUDEPATH) -j -zp1 -5s -mf -oaeilrt -s -zq\nASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /dPHARLAP_TNT=0\nLIB_OPTS = /b /c /q\nLINK_CFG = $(PRJNAME).lnk\n\n#----------------------------------------------------------------------------\n# DEFAULT TARGET\n#----------------------------------------------------------------------------\n\nall : $(PRJNAME).lib .SYMBOLIC\n\n$(PRJNAME).lib : $(OBJECTS) .SYMBOLIC\n\n#----------------------------------------------------------------------------\n# IMPLICIT RULES\n#----------------------------------------------------------------------------\n\n.c.obj :\n  $(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.cpp.obj :\n  $(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\\$^. $<\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\n.asm.obj:\n\t$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\\$^.\n\t$(LIB_CMD) $(LIB_OPTS) $(path_lib)\\$(PRJNAME).lib -+$(path_obj)\\$]&\n\nupdate: .SYMBOLIC\n\t@echo Updating VQMisc32 header files!\n\t@copy *.h $(%PRJ)\\INCLUDE\\VQM32 >NUL\n\t@copy *.i $(%PRJ)\\INCLUDE\\VQM32 >NUL\n\n"
  },
  {
    "path": "WINVQ/VQM32/MCGABUF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     mcgabuf.asm\n;*\n;* DESCRIPTION\n;*     MCGA display routines. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Bill Randolph\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     Febuary 3, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     ClearVRAM       - Clear all VRAM.\n;*     MCGA_BufferCopy - Copy 320x200 buffer to MCGA VRAM\n;*     MCGA_Blit       - Bit blit a block to the MCGA screen.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"vga.i\"\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     ClearVRAM - Clear all VRAM.\n;*\n;* SYNOPSIS\n;*     ClearVRAM()\n;*\n;*     void ClearVRAM(void);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC ClearVRAM:NEAR\n \tPROC\tClearVRAM C NEAR USES eax ecx edi es\n\n\tIF\tPHARLAP_TNT\n\tmov\teax,01Ch\t;Set ES selector to video memory\n\tmov\tes,ax\n\tmov\tedi,0\n\tELSE\n\tmov\tedi,0A0000h\n\tENDIF\n\n\tSET_PLANE 0Fh\t;Enable all planes for writing\n\tcld\n\tmov\tecx,16000\t;Clear 320x200\n\txor\teax,eax\n\trep\tstosd\n\tret\n\n\tENDP\tClearVRAM\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     MCGA_BufferCopy - Copy 320x200 buffer to MCGA VRAM\n;*\n;* SYNOPSIS\n;*     MCGA_BufferCopy(Buffer, Dummy)\n;*\n;*     void MCGA_BufferCopy(char *, char *);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Buffer - Pointer to buffer to transfer.\n;*     Dummy  - Prototype placeholder.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC MCGA_BufferCopy:NEAR\n\tPROC\tMCGA_BufferCopy C NEAR USES ecx esi edi es\n\n\tARG\tbuffer:NEAR PTR\n\tARG\tdummy:NEAR PTR\n\n\tIF\tPHARLAP_TNT\n\tmov\teax,01Ch\n\tmov\tes,ax\n\tmov\tedi,0\n\tELSE\n\tmov\tedi,0A0000h\n\tENDIF\n\n\tmov\tesi, [buffer]\n\tmov\tecx,16000\n\trep \tmovsd\t;Transfer the data\n\tret\n\n\tENDP\tMCGA_BufferCopy\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     MCGA_Blit - Bit blit a block to the MCGA screen.\n;*\n;* SYNOPSIS\n;*     MCGA_Blit(Buffer, Screen, Width, Height)\n;*\n;*     void MCGA_Blit(char *, char *, long, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Buffer - Pointer to buffer to copy.\n;*     Screen - Screen address to copy buffer to.\n;*     Width  - Width of block.\n;*     Height - Height of block.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC MCGA_Blit:NEAR\n\tPROC\tMCGA_Blit C NEAR USES ecx edx esi edi\n\n\tARG\tbuffer:NEAR PTR\n\tARG\tscreen:NEAR PTR\n\tARG\timgwidth:DWORD\n\tARG\timgheight:DWORD\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tmov\teax,1Ch\t;Set ES selector to VRAM\n\tmov\tes,ax\n\tENDIF\n\n\tmov\tesi,[buffer]\n\tmov\tedi,[screen]\n\tmov\tedx,320\n\tsub\tedx,[imgwidth]\t;Compute modulo\n\n??Do_row:\n\tmov\tecx,[imgwidth]\n\trep \tmovsb\n\tadd\tedi,edx\n\tdec\t[imgheight]\n\tjnz\t??Do_row\n\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\n\tENDP\tMCGA_Blit\n\n\tEND\n\n"
  },
  {
    "path": "WINVQ/VQM32/MEM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*---------------------------------------------------------------------------\n*\n* FILE\n*     mem.c\n*\n* DESCRIPTION\n*     Memory management.\n*\n* PROGRAMMER\n*     Phil Gorrow\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 5, 1995\n*\n*---------------------------------------------------------------------------\n*\n* PUBLIC\n*     DPMI_Lock   - Lock a memory page.\n*     DPMI_Unlock - Unlock a locked memory page.\n*\n****************************************************************************/\n\n#ifdef __WATCOMC__\n#include <dos.h>\n#include <mem.h>\n#include <vqm32\\mem.h>\n\n\n/****************************************************************************\n*\n* NAME\n*     DPMI_Lock - Lock a memory page.\n*\n* SYNOPSIS\n*     DPMI_Lock(Address, Size)\n*\n*     void DPMI_Lock(void *, long);\n*\n* FUNCTION\n*\n* INPUTS\n*     Address - Starting linear address of memory to lock.\n*     Size    - Size of region to lock in bytes.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid DPMI_Lock(void const *ptr, long const size)\n{\n\tunion REGS   regs;\n\tstruct SREGS sregs;\n\n\tmemset(&regs, 0, sizeof(REGS));\n\tsegread(&sregs);\n\n\t/* Lock the memory page.\n\t *\n\t * AX    = 0x600\n\t * BX:CX = Starting linear address of memory to lock.\n\t * SI:DI = Size of region to lock in bytes.\n\t */\n\tregs.x.eax = DPMI_LOCK;\n\tregs.x.ebx = ((long)ptr & 0xFFFF0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000FFFF);\n\tregs.x.esi = ((long)size & 0xFFFF0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000FFFF);\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DPMI_Unlock - Unlock a locked memory page.\n*\n* SYNOPSIS\n*     DPMI_Unlock(Address, Size)\n*\n*     void DPMI_Unlock(void *, long);\n*\n* FUNCTION\n*\n* INPUTS\n*     Address - Starting linear address of memory to unlock.\n*     Size    - Size of region to unlock in bytes.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid DPMI_Unlock(void const *ptr, long const size)\n{\n\tunion REGS   regs;\n\tstruct SREGS sregs;\n\n\t/* Unlock memory page. */\n\tmemset(&regs, 0 ,sizeof(REGS));\n\tsegread(&sregs);\n\n\tregs.x.eax = DPMI_UNLOCK;\n\tregs.x.ebx = ((long)ptr & 0xFFFF0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000FFFF);\n\tregs.x.esi = ((long)size & 0xFFFF0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000FFFF);\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n}\n\n#endif /* __WATCOMC__ */\n"
  },
  {
    "path": "WINVQ/VQM32/MEM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQAMEM_H\n#define VQAMEM_H\n/****************************************************************************\n*\n*        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\n*\n*---------------------------------------------------------------------------\n*\n* FILE\n*     mem.h\n*\n* DESCRIPTION\n*     Memory management definitions.\n*\n* PROGRAMMER\n*     Phil Gorrow\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     July 5, 1995\n*\n****************************************************************************/\n\n/* Definitions */\n#define DPMI_INT    0x0031\n#define DPMI_LOCK   0x0600\n#define DPMI_UNLOCK 0x0601\n\n/* Prototypes */\n#ifdef __WATCOMC__\nvoid DPMI_Lock(void const *ptr, long const size);\nvoid DPMI_Unlock(void const *ptr, long const size);\n#else\n#define DPMI_Lock(a,b)\n#define DPMI_Unlock(a,b)\n#endif\n\n#endif /* VQAMEM_H */\n"
  },
  {
    "path": "WINVQ/VQM32/MIXFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     mixfile.c\n*\n* DESCRIPTION\n*     A mix file is basically a group of files concatinated together\n*     proceeded by a header describing where in the file each individual\n*     entry is located. These routines are provided to simplify the access\n*     to these file entries.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* MixFile format:\n*\n*     HEADER\n*       (2 bytes) Count - The number of entries in this file.\n*       (4 bytes) Size  - Size of the mix file in bytes.\n*\n*     SUBBLOCKS (There are \"Count\" number of these.)\n*       (4 bytes) CRC    - Entry descriptor (CRC of filename).\n*       (4 bytes) Offset - Offset in bytes from beginning of the DATA chunk.\n*       (4 bytes) Size   - Size of entry.\n*\n*     DATA\n*       Entry data.\n* \n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     OpenMix - Open mix file for access.\n*     CloseMix - Close a mix file.\n*     OpenMixEntry - Open a mix file entry.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <fcntl.h>\n#include <io.h>\n#include <mem.h>\n#include <string.h>\n#include \"mixfile.h\"\n#include \"crc.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\nint compfunc(void const *ptr1, void const *ptr2);\n\n\n/****************************************************************************\n*\n* NAME\n*     OpenMix - Open mix file for access.\n*\n* SYNOPSIS\n*     MixHandle = OpenMix(Name)\n*\n*     MixHandle *OpenMix(char *);\n*\n* FUNCTION\n*     Open a mix file for access.\n*\n* INPUTS\n*     Name - Pointer to name of mix file to open.\n*\n* RESULT\n*     MixHandle - Pointer to handle for mix file.\n*\n****************************************************************************/\n\nMIXHandle *OpenMix(char *name)\n{\n  MIXHeader mfhdr;\n\tMIXHandle *mix = NULL;\n\tlong      fh;\n\tlong      sbsize;\n\tlong      size;\n\n\t/* Open mix file and read in header. */\n\tif ((fh = open(name, (O_RDONLY|O_BINARY))) != -1) {\n\t\tif (read(fh, &mfhdr, sizeof(MIXHeader)) == sizeof(MIXHeader)) {\n\n\t\t\t/* Allocate handle based on the number of SubBlocks. */\n\t\t\tsbsize = (mfhdr.Count * sizeof(MIXSubBlock));\n\t\t\tsize = sbsize + sizeof(MIXHandle);\n\n\t\t\tif ((mix = (MIXHandle *)malloc(size)) != NULL) {\n\t\t\t\tmemset(mix, 0, size);\n\t\t\t\tmix->Name = name;\n\t\t\t\tmix->Size = mfhdr.Size;\n\t\t\t\tmix->Count = mfhdr.Count;\n\n\t\t\t\t/* Read in the SubBlock entries. */\n\t\t\t\tif (read(fh, &mix->Entries[0], sbsize) != sbsize) {\n\t\t\t\t\tfree(mix);\n\t\t\t\t\tmix = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tclose(fh);\n\t}\n\n\treturn (mix);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     CloseMix - Close a mix file.\n*\n* SYNOPSIS\n*     CloseMix(MixHandle)\n*\n*     void CloseMix(MixHandle *);\n*\n* FUNCTION\n*     Close a mix file by freeing its handle.\n*\n* INPUTS\n*     MixHandle - Pointer to MixHandle returned by OpenMix().\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid CloseMix(MIXHandle *mix)\n{\n\tfree(mix);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     OpenMixEntry - Open a mix file entry.\n*\n* SYNOPSIS\n*     FH = OpenMixEntry(MixHandle, EntryName)\n*\n*     short OpenMixEntry(MIXHandle *, char *);\n*\n* FUNCTION\n*     Opens an entry from the specified mix file handle. Use close() to close\n*     the file when done.\n*\n* INPUTS\n*     MixHandle - Pointer to MIXHandle containing entry to open.\n*     EntryName - Pointer to name of mix file entry to open.\n*\n* RESULT\n*     FH - DOS filehandle, -1 if unable to open.\n*\n****************************************************************************/\n\nlong OpenMixEntry(MIXHandle *mix, char *name)\n{\n\tMIXSubBlock key;\n\tMIXSubBlock *block;\n\tlong        fh;\n\n\t/* Search for the specified file in the mix file. */\n\tkey.CRC = Calculate_CRC(name, strlen(name));\n\tblock = (MIXSubBlock *)bsearch(&key, &mix->Entries[0], mix->Count,\n\t\t\tsizeof(MIXSubBlock), compfunc);\n\n\t/* If the block exists for the requested filename. */\n\tif (block != NULL) {\n\n\t\t/* Initialize the key for file access. */\n\t\tkey.Offset = block->Offset;\n\t\tkey.Offset += (mix->Count * sizeof(MIXSubBlock)) + sizeof(MIXHeader);\n\n\t\t/* Open the mix file. */\n\t\tif ((fh = open(mix->Name, (O_RDONLY|O_BINARY))) != -1) {\n\n\t\t\t/* Seek to the start of the file. */\n\t\t\tif (lseek(fh, key.Offset, SEEK_SET) == -1) {\n\t\t\t\tclose(fh);\n\t\t\t\tfh = -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn (fh);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     compfunc - Compare function for bsearch().\n*\n* SYNOPSIS\n*     Result = compfunc(Entry1, Entry2);\n*\n*     int compfunc(void const *, void const *);\n*\n* FUNCTION\n*\n* INPUTS\n*     Entry1 - Pointer to first entry to compare.\n*     Entry2 - Pointer to second entry to compare.\n*\n* RESULT\n*     Result -\n*\n****************************************************************************/\n\nint compfunc(void const *ptr1, void const *ptr2) \n{\n\tif (((MIXSubBlock *)ptr1)->CRC < ((MIXSubBlock *)ptr2)->CRC) return -1;\n\tif (((MIXSubBlock *)ptr1)->CRC > ((MIXSubBlock *)ptr2)->CRC) return 1;\n\treturn(0);\n}\n\n\n"
  },
  {
    "path": "WINVQ/VQM32/MIXFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMMIXFILE_H\n#define VQMMIXFILE_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     mixfile.h\n*\n* DESCRIPTION\n*     A mix file is basically a group of files concatinated together\n*     proceeded by a header describing where in the file each individual\n*     entry is located. These definitions are provided to simplify the access\n*     to these file entries.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/* Disable structure alignment.*/\n#ifdef __WATCOMC__\n#pragma pack(1);\n#endif\n\n/*---------------------------------------------------------------------------\n * STRUCTURE DEFINITIONS\n *-------------------------------------------------------------------------*/\n\n/* MIXHeader: Mix file data header.\n *\n * Count - Number of entries contained in this mix file.\n * Size  - Size of Mix file.\n */\ntypedef struct _MIXHeader {\n\tshort Count;\n\tlong  Size;\n} MIXHeader;\n\n/* MIXSubBlock: Mix file entry descriptor.\n *\n * CRC    - Unique entry identifier.\n * Offset - Offset from beginning of data segment to entry.\n * Size   - Size of entry.\n */\ntypedef struct _MIXSubBlock {\n\tlong CRC;\n\tlong Offset;\n\tlong Size;\n} MIXSubBlock;\n\n/* MIXHandle: Mix file handle.\n *\n * Name    - Pointer to the name of the mix file this handle is for.\n * Size    - Size of entire mix file.\n * FH      - DOS file handle of opened entry.\n * Count   - Number of files contained in this mix.\n * Entries - Array of 'Count' MIXSubBlock structure entries.\n */\ntypedef struct _MIXHandle {\n\tchar        *Name;\n\tlong        Size;\n\tlong        FH;\n\tlong        Count;\n\tMIXSubBlock Entries[];\n} MIXHandle;\n\n/*---------------------------------------------------------------------------\n * PROTOTYPES\n *-------------------------------------------------------------------------*/\n\nMIXHandle *OpenMix(char *name);\nvoid CloseMix(MIXHandle *mix);\nlong OpenMixEntry(MIXHandle *mix, char *name);\n\n/* Restore original alignment */\n#ifdef __WATCOMC__\n#pragma pack();\n#endif\n\n#endif /* VQMMIXFILE_H */\n\n"
  },
  {
    "path": "WINVQ/VQM32/MONO.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     mono.asm\n;*\n;* DESCRIPTION\n;*     Mono screen print and output routines. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     Febuary 8, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     Mono_Enable       - Enable mono output.\n;*     Mono_Disable      - Disable mono output.\n;*     Mono_X            - Get mono cursors X position.\n;*     Mono_Y            - Get mono cursors Y position.\n;*     Mono_Set_Cursor   - Set the mono cursor to specified coordinates.\n;*     Mono_Clear_Screen - Clear the mono screen.\n;*     Mono_Scroll       - Scroll the mono screen up.\n;*     Mono_Put_Char     - Ouput a character to the mono screen.\n;*     Mono_Draw_Rect    - Draw a box on the mono screen.\n;*     Mono_Text_Print   - Print a string to the mono screen at a specified\n;*                         position.\n;*     Mono_Print        - Print a string to the mono screen.\n;*     Mono_View_Page    - View a mono page.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\n\tDATASEG\n\nMonoEnabled\tDD\t1\nMonoX\tDD\t0\nMonoY\tDD\t0\nMonoOff\tDD\t0\n\nCharData\tDB\t0DAh,0C4h,0BFh,0B3h,0D9h,0C4h,0C0h,0B3h\t; Single line\n\tDB\t0D5h,0CDh,0B8h,0B3h,0BEh,0CDh,0D4h,0B3h\t; Double horz.\n\tDB\t0D6h,0C4h,0B7h,0BAh,0BDh,0C4h,0D3h,0BAh\t; Double vert.\n\tDB\t0C9h,0CDh,0BBh,0BAh,0BCh,0CDh,0C8h,0BAh\t; Double line.\n\n\n;\t\tx,y,dist\nBoxData\tDB\t1,0,0\t\t; Upper left corner.\n\tDB\t1,0,1\t\t; Top edge.\n\tDB\t0,1,0\t\t; Upper right corner.\n\tDB\t0,1,2\t\t; Right edge.\n\tDB\t-1,0,0\t\t; Bottom right corner.\n\tDB\t-1,0,1\t\t; Bottom edge.\n\tDB\t0,-1,0\t\t; Bottom left corner.\n\tDB\t0,-1,2\t\t; Left edge.\n\tDB\t0,0,-1\t\t; End of list.\n\nPageMap\tDD\t0,1,2,3,4,5,6,7\n\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Enable - Enable mono output.\n;*\n;* SYNOPSIS\n;*     Mono_Enable()\n;*\n;*     void Mono_Enable(void);\n;*\n;* FUNCTION\n;*     Turn on the MonoEnabled flag.\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Enable:NEAR\n\tPROC\tMono_Enable C NEAR\n\n\tmov\t[MonoEnabled],1\n\tret\n\n\tENDP\tMono_Enable\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Disable - Disable mono output.\n;*\n;* SYNOPSIS\n;*     Mono_Disable()\n;*\n;*     void Mono_Disable(void);\n;*\n;* FUNCTION\n;*     Turn off the MonoEnabled flag.\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Disable:NEAR\n\tPROC\tMono_Disable C NEAR\n\n\tmov\t[MonoEnabled],0\n\tret\n\n\tENDP\tMono_Disable\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_X - Get mono cursors X position.\n;*\n;* SYNOPSIS\n;*     X = Mono_X()\n;*\n;*     long Mono_X(void);\n;*\n;* FUNCTION\n;*     Return the X position of the mono screen cursor.\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     X - X coordinate position.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_X:NEAR\n\tPROC\tMono_X C NEAR\n\n\tmov\teax,[MonoX]\n\tret\n\n\tENDP\tMono_X\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Y - Get mono cursors Y position.\n;*\n;* SYNOPSIS\n;*     Y = Mono_Y()\n;*\n;*     long Mono_Y(void);\n;*\n;* FUNCTION\n;*     Return the Y position of the mono screen cursor.\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     Y - Y coordinate position.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Y:NEAR\n\tPROC\tMono_Y C NEAR\n\n\tmov\teax,[MonoY]\n\tret\n\n\tENDP\tMono_Y\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Set_Cursor - Set the mono cursor to specified coordinates.\n;*\n;* SYNOPSIS\n;*     Mono_Set_Cursor(X, Y)\n;*\n;*     void Mono_Set_Cursor(long, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     X - X coordinate position.\n;*     Y - Y coordinate position.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Set_Cursor:NEAR\n\tPROC\tMono_Set_Cursor C NEAR USES eax ebx edx\n\n\tARG\txpos:DWORD\n\tARG\typos:DWORD\n\n\tcmp\t[MonoEnabled],0\n\tje\tshort ??fini\n\n\tmov\teax,[ypos]\n\tmov\tah,80\n\timul\tah\n\tadd\teax,[xpos]\n\tmov\tebx,eax\n\n;\tUpdate cursor position.\n\n\tmov\tdx,03B4h\n\tmov\tal,0Eh\t\t;High byte register set.\n\tout\tdx,al\n\tinc\tdx\n\tmov\tal,bh\n\tout\tdx,al\t\t;Set high byte.\n\n\tdec\tdx\n\tmov\tal,0Fh\t\t;Low byte register set.\n\tout\tdx,al\n\tinc\tdx\n\tmov\tal,bl\n\tout\tdx,al\t\t;Set low byte.\n\n;\tUpdate the globals.\n\n\tadd\tebx,ebx\n\tmov\t[MonoOff],ebx\n\tmov\teax,[xpos]\n\tmov\t[MonoX],eax\n\tmov\teax,[ypos]\n\tmov\t[MonoY],eax\n\n??fini:\n\tret\n\n\tENDP\tMono_Set_Cursor\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Clear_Screen - Clear the mono screen.\n;*\n;* SYNOPSIS\n;*     Mono_Clear_Screen()\n;*\n;*     void Mono_Clear_Screen(void);\n;*\n;* FUNCTION\n;*     Clear the mono screen and set the mono cursor to the upperleft corner\n;*     of the screen.\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Clear_Screen:NEAR\n\tPROC\tMono_Clear_Screen C NEAR USES es eax ecx edi\n\n;\tExit if mono disabled\n\n\tcmp\t[MonoEnabled],0\n\tje\tshort ??fini\n\n;\tClear the mono screen\n\n\tIF\tPHARLAP_TNT\n\tmov\tax,034h\n\tmov\tes,ax\t\t;Set ES selector to first MB\n\tENDIF\n\n\tmov\tedi,0B0000h\t\t;EDI = Mono screen address\n\txor\teax,eax\t\t;Set char & attributes to 0\n\tmov\tecx,8000h/4\t\t;Number of longwords to clear\n\trep\tstosd\t\t;Clear the mono screen.\n\tcall\tMono_Set_Cursor C,eax,eax\n\n??fini:\n\tret\n\n\tENDP\tMono_Clear_Screen\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Scroll - Scroll the mono screen up.\n;*\n;* SYNOPSIS\n;*     Mono_Scroll(Lines)\n;*\n;*     void Mono_Scroll(long);\n;*\n;* FUNCTION\n;*     Move the contents of the mono screen up the specified number of lines\n;*     while clearing out the bottom lines.\n;*\n;* INPUTS\n;*     Lines - Number of lines to scroll the screen up.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Scroll:NEAR\n\tPROC\tMono_Scroll C NEAR USES es eax ebx ecx esi edi\n\tARG\tlines:DWORD\n\n;\tExit if mono disabled\n\n\tcmp\t[MonoEnabled],0\n\tje\tshort ??fini\n\n;\tExit if lines to scroll is 0.\n\n\tmov\teax,[lines]\n\tor\teax,eax\n\tje\tshort ??fini\n\n;\tMove the screen data up the specified lines\n\n\tmov\tebx,eax\n\n??looper:\n\tIF\tPHARLAP_TNT\n\tmov\tax,034h\n\tmov\tes,ax\t\t;Set ES selector to first MB\n\tENDIF\n\n   \tpush\tds\t\t;Save DS selector\n\tmov\tds,ax\t\t;Set DS selector to first MB\n\n\tmov\tecx,((80*24)/2)\t;Number of DWORDs to move\n\tmov\tesi,0B00A0h\n\tmov\tedi,0B0000h\n\trep\tmovsd\n\n\tpop\tds\t\t;Restore DS selector\n\tdec\t[MonoY]\n\tsub\t[MonoOff],(80*2)\n\n\txor\teax,eax\n\tmov\tecx,(80/2)\n\trep\tstosd\n\n\tdec\tebx\n\tjne\t??looper\n\n??fini:\n\tret\n\n\tENDP\tMono_Scroll\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Put_Char - Ouput a character to the mono screen.\n;*\n;* SYNOPSIS\n;*     Mono_Put_Char(Character, Attributes)\n;*\n;*     void Mono_Put_Char(long, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Character  - ASCII character to output.\n;*     Attributes - Display attributes\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Put_Char:NEAR\n\tPROC\tMono_Put_Char C NEAR USES es eax edi\n\tARG\tcharacter:DWORD\n\tARG\tattrib:DWORD\n\n;\tExit if mono disabled\n\n\tcmp\t[MonoEnabled],0\n\tje\tshort ??fini\n\n;\tOutput character to the mono screen\n\n\tcld\n\n\tIF\tPHARLAP_TNT\n\tmov\tax,034h\n\tmov\tes,ax\t\t;Set ES selector to first MB\n\tENDIF\n\n\tmov\tedi,0B0000h\t\t;EDI = mono screen\n\tadd\tedi,[MonoOff]\t\t;Add cursor offset\n\tmov\teax,[character]\n\tmov\tah,[BYTE PTR attrib]\n\tstosw\n\n;\tUpdate cursor position.\n\n\tinc\t[MonoX]\t\t; X position moves.\n\tcall\tMono_Set_Cursor C,[MonoX],[MonoY]\n\n??fini:\n\tret\n\n\tENDP\tMono_Put_Char\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Draw_Rect - Draw a box on the mono screen.\n;*\n;* SYNOPSIS\n;*     Mono_Draw_Rect(X, Y, Width, Height, Attributes, Thickness)\n;*\n;*     void Mono_Draw_Rect();\n;*\n;* FUNCTION\n;*     Draw a rectangle text box on the mono screen.\n;*\n;* INPUTS\n;*     X          - X coordinate position of upperleft corner.\n;*     Y          - Y coordinate position of upperleft corner.\n;*     Width      - Desired width.\n;*     Height     - Desired height.\n;*     Attributes - Display attributes.\n;*     Thickness  - Line thickness.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Draw_Rect:NEAR\n\tPROC\tMono_Draw_Rect C NEAR\n\tARG\txpos:DWORD\n\tARG\typos:DWORD\n\tARG\twidth:DWORD\n\tARG\theight:DWORD\n\tARG\tattrib:DWORD\n\tARG\tthick:DWORD\n\n;\tExit if mono disabled\n\n\tpushad\n\tcmp\t[MonoEnabled],0\n\tje\t??fini\n\n;\tSelect the character table for the desired line thickness\n\n\tmov\tedi,OFFSET CharData\n\tmov\tcl,3\n\tmov\teax,[thick]\n\tand\teax,011b\n\tshl\teax,cl\n\tadd\tedi,eax\n\n;\tPrep width and height.\n\n\tcmp\t[width],2\n\tjb\t??fini\n\n\tcmp\t[height],2\n\tjb\t??fini\n\n\tsub\t[width],2\n\tsub\t[height],2\n\n;\tSet cursor position to upperleft corner of box\n\n\tpush\t[MonoY]\n\tpush\t[MonoX]\t\t;Save current cursor position\n\tcall\tMono_Set_Cursor C,[xpos],[ypos]\n\n;\tDraw the rectangle\n\n\tmov\tesi,OFFSET BoxData\n\n;\tDetermine the number of characters to output\n\n??drawloop:\n\tmov\tecx,[width]\n\tcmp\t[BYTE PTR esi+2],1\n\tje\tshort ??gotlen\n\n\tmov\tecx,[height]\n\tcmp\t[BYTE PTR esi+2],2\n\tje\tshort ??gotlen\n\n\tmov\tecx,1\n\n??gotlen:\n\tjecxz\t??donerun\n\n??runloop:\n\txor\teax,eax\n\tmov\tal,[BYTE PTR edi]\n\tcall\tMono_Put_Char C,eax,[attrib]\t;Output the character.\n\n\tmov\tal,[BYTE PTR esi+1]\n\tcbw\n\tcwde\n\tadd\teax,[MonoY]\n\tpush\teax\n\tmov\tal,[BYTE PTR esi]\n\tcbw\n\tcwde\n\tadd\teax,[MonoX]\n\tdec\teax\t\t; Undo cursor advance.\n\tpush\teax\n\tcall\tMono_Set_Cursor\t; Properly advance cursor.\n\tadd\tsp,8\n\tloop\t??runloop\n\n;\tAdvance to next control entry.\n\n??donerun:\n\tadd\tesi,3\n\tinc\tedi\n\tcmp\t[BYTE PTR esi+2],-1\n\tjne\t??drawloop\n\n;\tRestore cursor to original position.\n\n\tcall\tMono_Set_Cursor\n\tadd\tsp,8\n\n??fini:\n\tpopad\n\tret\n\n\tENDP\tMono_Draw_Rect\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Text_Print - Print a string to the mono screen at a specified\n;*                       position.\n;*\n;* SYNOPSIS\n;*     Mono_Text_Print(String, X, Y, Attributes, Update)\n;*\n;*     void Mono_Text_Print(char *, long, long, long, long);\n;*\n;* FUNCTION\n;*     Print a NULL terminated string to the mono screen at the specified\n;*     cooridinates and attributes.\n;*\n;* INPUTS\n;*     String     - Pointer to NULL terminated string.\n;*     X          - X coordinate position.\n;*     Y          - Y coordinate position.\n;*     Attributes - Display attributes\n;*     Update     - Update cursor position flag.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC _Mono_Text_Print:NEAR\n\tPROC\t_Mono_Text_Print C NEAR USES eax esi\n\tARG\ttext:NEAR PTR\n\tARG\txpos:DWORD\n\tARG\typos:DWORD\n\tARG\tattrib:DWORD\n\tARG\tupdate:DWORD\n\n;\tSave the current cursor position.\n\n\tpush\t[MonoY]\n\tpush\t[MonoX]\n\tcmp\t[text],0\t\t;Exit if the string is NULL\n\tje\tshort ??fini\n\n\tcall\tMono_Set_Cursor C,[xpos],[ypos]\n\n;\tPrint string to the mono screen\n\n\tmov\tesi,[text]\t\t;Text pointer\n\n??charloop:\n\tmov\teax,[esi]\n\tinc\tesi\n\tor\tal,al\t\t;Stop on a NULL\n\tje\tshort ??fini\n\n\tcmp\tal,13\t\t;Special processing for '\\r'\n\tje\tshort ??cr\n\n;\tOutput character to mono screen\n\n??normal:\n\txor\tah,ah\n\tcall\tMono_Put_Char C,eax,[attrib]\n\n;\tPerform adjustments if wrapping past right margin.\n\n\tcmp\t[MonoX],80\n\tjb\tshort ??nowrap\n\n\tinc\t[ypos]\n\tcall\tMono_Set_Cursor C,0,[ypos]\n\tjmp\tshort ??nowrap\n\n\t; Move to start of next line.\n\n??cr:\n\tinc\t[ypos]\n\tcall\tMono_Set_Cursor C,[xpos],[ypos]\n\n;\tScroll the monochrome screen if necessary.\n\n??nowrap:\n\tcmp\t[MonoY],25\n\tjb\tshort ??noscroll\n\n\tcall\tMono_Scroll C,1\n\tdec\t[ypos]\n\n??noscroll:\n\tjmp\tshort ??charloop\n\n??fini:\n\tcmp\t[update],0\n\tjne\tshort ??noupdate\n\n\tcall\tMono_Set_Cursor\n\n??noupdate:\n\tpop\teax\n\tpop\teax\n\tret\n\n\tENDP\t_Mono_Text_Print\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Text_Print - Print a string to the mono screen. (ASM call)\n;*\n;* SYNOPSIS\n;*     Mono_Text_Print(String, X, Y, Attributes)\n;*\n;*     void Mono_Text_Print(char *, long, long, long);\n;*\n;* FUNCTION\n;*     Print a NULL terminated string to the mono screen at the specified\n;*     cooridinates and attributes.\n;*\n;* INPUTS\n;*     String     - Pointer to NULL terminated string.\n;*     X          - X coordinate position.\n;*     Y          - Y coordinate position.\n;*     Attributes - Display attributes\n;*\n;* RESULT\n;*     NONE\n;*\n;* SEE ALSO\n;*     _Mono_Text_Print\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Text_Print:NEAR\n\tPROC\tMono_Text_Print C NEAR USES\n\tARG\ttext:NEAR PTR\n\tARG\txpos:DWORD\n\tARG\typos:DWORD\n\tARG\tattrib:DWORD\n\n;\tExit if mono disabled\n\n\tcmp\t[MonoEnabled],0\n\tje\tshort ??fini\n\n\tcall\t_Mono_Text_Print C,[text],[xpos],[ypos],[attrib],0\n\n??fini:\n\tret\n\n\tENDP\tMono_Text_Print\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_Print - Print a string to the mono screen.\n;*\n;* SYNOPSIS\n;*     Mono_Print(String)\n;*\n;*     void Mono_Print(char *);\n;*\n;* FUNCTION\n;*     Print a string to the mono screen at the current cursor position and\n;*     update the cursor position.\n;*\n;* INPUTS\n;*     String - Pointer to NULL terminated string.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_Print:NEAR\n\tPROC\tMono_Print C NEAR\n\tARG\ttext:NEAR PTR\n\n;\tExit if mono disabled\n\n\tcmp\t[MonoEnabled],0\n\tje\tshort ??fini\n\n\tcall\t_Mono_Text_Print C,[text],[MonoX],[MonoY],2,1\n\n??fini:\n\tret\n\n\tENDP\tMono_Print\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Mono_View_Page - View a mono page.\n;*\n;* SYNOPSIS\n;*     Oldpage = Mono_View_Page(Page)\n;*\n;*     long Mono_View_Page(long);\n;*\n;* FUNCTION\n;*     Displays the specified page in displayable mono memory.\n;*\n;* INPUTS\n;*     Page - Page to view.\n;*\n;* RESULT\n;*     Oldpage - Previous page.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Mono_View_Page:NEAR\n\tPROC\tMono_View_Page C NEAR USES ds es eax ebx ecx edi esi\n\tARG\tpage:DWORD\n\tLOCAL\toldpage:DWORD\n\n;\tPrepare the original page number for return to caller.\n\n\tcld\n\tmov\tebx,[PageMap]\n\tmov\t[oldpage],ebx\n\n;\tExit of mono disabled\n\n\tcmp\t[MonoEnabled],0\n\tje\tshort ??fini\n\n;\tIf the desired page is already displayed, then don't do anything.\n\n\tmov\teax,[page]\n\tcmp\teax,ebx\n\tje\tshort ??fini\n\n;\tVerify that page specified is legal.\n\n\tcmp\teax,7\n\tja\tshort ??fini\n\n;\tFind where the logical page to display is actually located.\n\n\tmov\tecx,8\n\tpush\tds\n\tpop\tes\n\tlea\tedi,[PageMap]\n\trepne\tscasw\n\tneg\tecx\n\tadd\tecx,7\t\t; CX = where desired page is located.\n\n;\tSwap the page ID bytes in the PageMap array.\n\n\tsub\tedi,4\n\tmov\tebx,[PageMap]\n\tmov\teax,[edi]\n\tmov\t[edi],ebx\n\tmov\t[PageMap],eax\n\n\tshl\tecx,8\n\tadd\tecx,eax\n\tmov\tesi,ecx\n\n\tIF\tPHARLAP_TNT\n\tmov\tax,034h\n\tmov\tds,ax\n\tENDIF\n\n\tmov\tedi,0B0000h\n\n;\tExchange the two pages.\n\n\tmov\tecx,1000H/4\n\n??looper:\n\tmov\tedx,[edi]\n\tmov\tebx,[esi]\n\tmov\t[edi],ebx\n\tmov\t[esi],edx\n\tadd\tesi,4\n\tadd\tedi,4\n\tloop\t??looper\n\n;\tReturn with the original page number.\n\n??fini:\n\tmov      \teax,[oldpage]\n\tret\n\t\n\tENDP\tMono_View_Page\n\n\tEND\n\n"
  },
  {
    "path": "WINVQ/VQM32/MONO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMMONO_H\n#define VQMMONO_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     mono.h\n*\n* DESCRIPTION\n*     Mono screen definitions. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Feburary 8, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid __cdecl Mono_Enable(void);\nvoid __cdecl Mono_Disable(void);\nvoid __cdecl Mono_Set_Cursor(long x, long y);\nvoid __cdecl Mono_Clear_Screen(void);\nvoid __cdecl Mono_Scroll(long lines);\nvoid __cdecl Mono_Put_Char(long character, long attrib);\nvoid __cdecl Mono_Draw_Rect(long x, long y, long w, long h, long attrib,\n\t\tlong thick);\n\nvoid __cdecl Mono_Text_Print(void const *text, long x, long y, long attrib);\nvoid __cdecl Mono_Print(void const *text);\nshort __cdecl Mono_View_Page(long page);\nshort __cdecl Mono_X(void);\nshort __cdecl Mono_Y(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMMONO_H */\n"
  },
  {
    "path": "WINVQ/VQM32/PALETTE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     palette.asm\n;*\n;* DESCRIPTION\n;*     Hardware level palette routines. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Bill Randolph\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* To write palette colors:\n;* - Out color # to 3c8h\n;* - Out RGB values to 3c9h (data must be written in three's; PEL address\n;*   register auto-increments after 3 reads or writes)\n;*\n;* A time interval of about 240 ns is required between successive reads/\n;* writes; on very fast machines, this means that the system may not be\n;* able to handle a rapid-fire of RGB values.  So, a \"safe\" routine is\n;* provided that has wait states between each out.\n;* \n;* Reference: Progammers Guide to the EGA & VGA Cards, Ferraro, 2nd ed.\n;* (Chapter 8.)\n;*\n;* Note that, if you set the palette in active scan, the screen will\n;* flash; to prevent this, wait for vertical retrace (Vertical Blank\n;* Interval), or turn the display off by using the Screen Off field in\n;* the Clocking Mode register (Hmmmm....).\n;*\n;* To read palette colors:\n;* - Out color # to 3c7h\n;* - In RGB values from 3c9h (data must be read in three's; PEL address\n;*   register auto-increments after 3 reads or writes)\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     SetPalette       - Set the palette without waiting to Vblank.\n;*     ReadPalette      - Read the palette from the display adapter.\n;*     SetDAC           - Set a single palette color in the DAC.\n;*     TranslatePalette - Translate 24-bit color to 15-bit color.\n;*      \n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"vga.i\"\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     SetPalette - Set the palette without waiting to Vblank.\n;*\n;* SYNOPSIS\n;*     SetPalette(Palette, Numbytes, SlowFlag)\n;*\n;*     void SetPalette(char *, long, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Palette  - Pointer to the palette to set.\n;*     NumBytes - Number of bytes of palette to transfer (multiple of 3).\n;*     SlowFlag - Slow palette set flag.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC SetPalette:NEAR\n\tPROC\tSetPalette C NEAR USES eax ecx edx esi ds\n\n\tARG\tpalette:NEAR PTR\n\tARG\tnumbytes:DWORD\n\tARG\tslowpal:DWORD\n\n\tpushf\n\tcld\n\n\tcmp\t[slowpal],0\t;Do slow palette?\n\tjne\t??safe_palette_routine\n\n;----------------------------------------------------------------------------\n;\tFast palette set\n;----------------------------------------------------------------------------\n\n\tmov\tesi,[palette]\n\tmov\tedx,PEL_WRITE_ADDR\n\txor\tal,al\t\t\t\n\tout\tdx,al\t;Select color to write too.\n\tinc\tal\t;Step to the next color for next loop\n\tinc\tedx\t;DX = PEL_DATA\n\tmov\tecx,[numbytes]\t;Max # colors to set\n\trep \toutsb\t;Write 256 * RGB out to the palette\n\tpopf\n\tret\n\t\n;----------------------------------------------------------------------------\n;\tSafe palette set\n;----------------------------------------------------------------------------\n\n??safe_palette_routine:\n\tmov\tesi,[palette]\n\tmov\tecx,[numbytes]\n\tmov\tedx,PEL_WRITE_ADDR\n\tsub\teax,eax\n\tout\tdx,al\n\tmov\tedx,PEL_DATA\n\n??Write_loop:\n\tlodsb\n\tout\tdx,al\t;Red\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tlodsb\n\tout\tdx,al\t;Green\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tlodsb\n\tout\tdx,al\t;Blue\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tsub\tcx,3\n\tja\t??Write_loop\n\n\tpopf\n\tret\n\n\tENDP\tSetPalette\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     ReadPalette - Read the palette from the display adapter.\n;*\n;* SYNOPSIS\n;*     ReadPalette(Palette)\n;*\n;*     void SetPalette(char *);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Palette - Pointer buffer to copy palette into.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC ReadPalette:NEAR\n\tPROC\tReadPalette C NEAR USES ecx edx edi es\n\n\tARG\tpalette:NEAR PTR\n\n\tmov\tedi,[palette]\n\tmov\tecx,256\n\tmov\tedx,PEL_READ_ADDR\n\tsub\teax,eax\n\tout\tdx,al\n\tmov\tedx,PEL_DATA\n\n??Read_loop:\n\tin\tal,dx\t;Red\n\tstosb\t\t;Save the byte\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tin\tal,dx\t;Green\n\tstosb\t\t;Save the byte\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tin\tal,dx\t;Blue\n\tstosb\t\t;Save the byte\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tdec\tecx\n\tjnz\t??Read_loop\n\tret\n\n\tENDP\tReadPalette\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     SetDAC - Set a single palette color in the DAC.\n;*\n;* SYNOPSIS\n;*     SetDAC(ColorNum, Red, Green, Blue)\n;*\n;*     void SetPalette(long, char, char);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     ColorNum - Position number in palette of color to set.\n;*     Red      - Red gun value.\n;*     Green    - Green gun value.\n;*     Blue     - Blue gun value.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC SetDAC:NEAR\n\tPROC\tSetDAC C NEAR USES edx\n\n\tARG\tcolor_num:DWORD\n\tARG\tred:BYTE\n\tARG\tgreen:BYTE\n\tARG\tblue:BYTE\n\n\tmov\tedx,PEL_WRITE_ADDR\n\tmov\teax,[color_num]\n\tout\tdx,al\t;Set color position\n\tinc\tedx\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tmov\tal,[red]\n\tout\tdx,al\t;Set red gun\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tmov\tal,[green]\n\tout\tdx,al\t;Set green gun\n\tjmp\t$+02\t;Delay (flush instruction cache)\n\n\tmov\tal,[blue]\n\tout\tdx,al\t;Set blue gun\n\tret\n\n\tENDP\tSetDAC\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     TranslatePalette - Translate 24-bit color to 15-bit color.\n;*\n;* SYNOPSIS\n;*     TranslatePalette(Pal24, Pal15, NumBytes)\n;*\n;*     void TranslatePalette(char *, char *, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Pal24 - Pointer to 24-bit palette. (Input)\n;*     Pal15 - Pointer to 15-bit palette. (Output)\n;*     NumBytes - Number of bytes to translate. (divisible by 3)\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC TranslatePalette:NEAR\n\tPROC\tTranslatePalette C NEAR USES ecx edx edi esi\n\n\tARG\tpal24:NEAR PTR\n\tARG\tpal15:NEAR PTR\n\tARG\tnumbytes:DWORD\n\n\tmov\tesi,[pal24]\n\tmov\tedi,[pal15]\n\tmov\tecx,[numbytes]\n\n??TranslatePalette:\n\tmov\tah,[BYTE PTR esi]\t;AH = red\n\tmov\tal,[BYTE PTR esi+1]\t;AL = green\n\tmov\tdl,[BYTE PTR esi+2]\t;DL = blue\n\tshr\tah,1\t\t;Red = lower 5 bits of AH\n\tshl\tal,2\t\t;Green = upper 6 bits of AL\n\tshr\tdl,1\t\t;Blue = lower 5 bits of DL\n\tshl\teax,2\t\t;Make room for blue\n\tand\tal,0E0h\t\t;Trim off bottom bit of green\n\tor\tal,dl\t\t;Load in blue bits\n\tmov\t[WORD PTR edi],ax\t;Store the value\n\tadd\tesi,3\t\t;Increment to next RGB values\n\tadd\tedi,2\t\t;Increment to next palette word\n\tsub\tecx,3\n\tja\t??TranslatePalette\n\tret\n\n\tENDP\tTranslatePalette\n\n\tEND\n"
  },
  {
    "path": "WINVQ/VQM32/PALETTE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMPALETTE_H\n#define VQMPALETTE_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Palette.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     Palette definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid __cdecl SetPalette(unsigned char *palette,long numbytes,unsigned long slowpal);\nvoid __cdecl ReadPalette(void *palette);\nvoid __cdecl SetDAC(long color, long red, long green, long blue);\nvoid __cdecl TranslatePalette(void *pal24, void *pal15, long numbytes);\n\n#ifdef __cplusplus\n}\n#endif\n\nvoid SortPalette(unsigned char *pal, long numcolors);\n\n#endif /* VQMPALETTE_H */\n\n"
  },
  {
    "path": "WINVQ/VQM32/PORTIO.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     portio.asm\n;*\n;* DESCRIPTION\n;*     I/O Port access. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     inp  - Read a byte from a hardware port.\n;*     outp - Write a byte to a hardware port.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     inp - Read a byte from a hardware port.\n;*\n;* SYNOPSIS\n;*     Data = inp(PortID)\n;*\n;*     short inp(unsinged short);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     PortID - Address if hardware port.\n;*\n;* RESULT\n;*     Data - Data read from port.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC inp:NEAR\n\tPROC\tinp C NEAR USES edx\n\tARG\tport:WORD\n\n\tmov\tdx,[port]\n\txor\teax,eax\n\tin\tal,dx\n\tret\n\n\tENDP\tinp\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     outp - Write a byte to a hardware port.\n;*\n;* SYNOPSIS\n;*     outp(PortID, Value)\n;*\n;*     void outp(unsinged short, short);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     PortID - Address if hardware port.\n;*     Value  - Value to write.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC outp:NEAR\n\tPROC\toutp C NEAR USES edx\n\tARG\tport:WORD\n\tARG\tvalue:WORD\n\n\tmov\tdx,[port]\n\tmov\tax,[value]\n\tout\tdx,al\n\tret\n\n\tENDP\toutp\n\n\tEND\n"
  },
  {
    "path": "WINVQ/VQM32/PORTIO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMPORTIO_H\n#define VQMPORTIO_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Portio.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     Hardware port I/O\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n#ifdef __BORLANDC__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nshort __cdecl inp(unsigned short portid);\nvoid __cdecl outp(unsigned short portid, short value);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* __BORLANDC__ */\n\n#endif /* VQMPORTIO_H */\n\n"
  },
  {
    "path": "WINVQ/VQM32/PROFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     profile.c\n*\n* DESCRIPTION\n*     INI file processing. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*      \n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     Get_Frame_Pathname - Get pathname for a given frame and file type.\n*     GetINIInt          - Get an integer value from an INI file.\n*     GetINIString       - Get a string from the INI file.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"profile.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n#ifndef max\n#define max(a,b) (((a)>(b))?(a):(b))\n#endif\n#ifndef min\n#define min(a,b) (((a)<(b))?(a):(b))\n#endif\n\n#define isspace(c) ((c==' ')||(c=='\\t')||(c=='\\n')||(c=='\\r')?1:0)\n\nstatic char *strtrim(char *string);\nstatic long FileGets(FILE *fp, char *buf, long buflen);\n\n\n/****************************************************************************\n*\n* NAME\n*     Get_Frame_Pathname - Get pathname for a given frame and file type.\n*\n* SYNOPSIS\n*     Error = Get_Frame_Pathname(IniFile, Frame, Extension, Buffer)\n*\n*     long Get_Frame_Pathname(char *, long, char *, char *);\n*\n* FUNCTION\n*\n* INPUTS\n*     IniFile   - Pointer to INI filename.\n*     Frame     - Number of frame to get filename for.\n*     Extension - File extension type.\n*     Buffer    - Pointer to buffer to put pathname into.\n*\n* RESULT\n*     Error - 0 if successful, or -1 if error.\n*\n***************************************************************************/\n\nlong Get_Frame_Pathname(char *inifile, long anim_frame, char *ext,\n\t\tchar *outbuf)\n{\n\tchar rootdir[_MAX_PATH];\t// Root directory from INI file\n\tchar extdir[_MAX_PATH];\t\t// this extension's directory\n\tchar entry_name[40];\t\t\t// INI entry name\n\tchar inibuf[80];\t\t\t\t\t// string returned from INI file\n\tchar *prefix;\t\t\t\t\t\t\t// 4-char prefix for this scene\n\tchar *startstr;\t\t\t\t\t\t// starting frame #, string\n\tchar *endstr;\t\t\t\t\t\t\t// ending frame #, string\n\tchar *palstr;\t\t\t\t\t\t\t// palette filename string\n\tlong startnum;\t\t\t\t\t\t// scene's starting frame #\n\tlong endnum;\t\t\t\t\t\t\t// scene's ending frame #\n\tlong total_frames;\t\t\t\t// accumulated frame total\n\tlong scene_frames;\t\t\t\t// # frames in a given scene\n\tlong scene_num;\t\t\t\t\t\t// scene #\n\tlong file_frame;\t\t\t\t\t// file's frame #\n\tlong rc;\n\t\n\t/* Get directory for this file type */\n\tGetINIString(\"Path\", \"Root\", \"\", rootdir, 80, inifile);\n\n\tif (rootdir[strlen (rootdir) - 1] != '\\\\') {\n\t\tstrcat(rootdir,\"\\\\\");\n\t}\n\n\tGetINIString(\"Path\", ext, \"\", extdir, 80, inifile);\n\n\tif (extdir[strlen (extdir) - 1] != '\\\\') {\n\t\tstrcat(extdir,\"\\\\\");\n\t}\n\n\t/* VQG is a special case:\n\t *\n\t * The VQG files are named based upon the 1st 4 characters of the 'Name'\n\t * entry in the INI file, and their numbers match the actual animation\n\t * frame numbers, not the scene frame numbers.\n\t */\n\tif (!stricmp(ext, \"VQG\")) {\n\t\tGetINIString(\"Common\", \"Name\", \"\", inibuf, 80, inifile);\n\n\t\tif (strlen(inibuf) > 4) {\n\t\t\tinibuf[4] = 0;\n\t\t}\n\n\t\tsprintf(outbuf,\"%s%s%s%04d.%s\",rootdir,extdir,inibuf,anim_frame,ext);\n\t\treturn (0);\n\t}\n\n\t/*-------------------------------------------------------------------------\n\t * Loop through scenes until the desired frame # is found\n\t *-----------------------------------------------------------------------*/\n\ttotal_frames = 0;\n\tscene_num = 1;\n\n\twhile (1) {\n\n\t\t/* Get this scene's entry */\n\t\tsprintf(entry_name, \"Scene%d\", scene_num);\n\t\trc = GetINIString(\"Scenes\",entry_name,\"\",inibuf,80,inifile);\n\n\t\tif (rc == 0) {\n\t\t\treturn (-1);\n\t\t}\n\n\t\t/* Parse the INI entry */\n\t\tprefix = strtok(inibuf, \",\");\n\t\tstartstr = strtok(NULL, \",\");\n\t\tendstr = strtok(NULL, \",\");\n\t\tpalstr = strtok(NULL, \",\");\n\n\t\tif ((prefix == NULL) || (startstr == NULL) || (endstr == NULL)) {\n\t\t\treturn (-1);\n\t\t}\n\n\t\tstartnum = atoi(startstr);\n\t\tendnum = atoi(endstr);\n\t\tscene_frames = ((endnum - startnum) + 1);\n\n\t\t/* requested frame is found */\n\t\tif (anim_frame < (total_frames + scene_frames)) {\n\n\t\t\t/* Palette is a special case */\n\t\t\tif (!stricmp(ext, \"PAL\")) {\n\t\t\t\tif (palstr == NULL) {\n\t\t\t\t\treturn (-1);\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(outbuf, \"%s%s%s.PAL\", rootdir, extdir, palstr);\n\t\t\t\t\treturn (0);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfile_frame = ((anim_frame - total_frames) + startnum);\n\t\t\t\tsprintf(outbuf,\"%s%s%s%04d.%s\",rootdir,extdir,prefix,file_frame,ext);\n\t\t\t\treturn (0);\n\t\t\t}\n\t\t}\n\n\t\t/* Frame not found; go to next scene */\n\t\ttotal_frames += scene_frames;\n\t\tscene_num++;\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetINIInt - Get an integer value from an INI file.\n*\n* SYNOPSIS\n*     Value = GetINIInt(Section, Entry, Default, ININame)\n*\n*     long GetINIInt(char *, char *, long, char *);\n*\n* FUNCTION\n*     Retrieve an integer value from the INI file at the specified 'Section'\n*     and 'Entry' fields. If no value is defined then return the passed in\n*     'Default' value.\n*\n* INPUTS\n*     Section - Pointer to section name.\n*     Entry   - Pointer to entry name.\n*     Default - Default value.\n*     ININame - Pointer to INI filename.\n*\n* RESULT\n*     Value - Integer value from INI file or 'Default'.\n*\n****************************************************************************/\n\nlong GetINIInt(char const *section, char const *entry, long deflt, \n\t\tchar *fname)\n{\n\tchar buffer[20];\n\n\tsprintf(buffer, \"%d\", deflt);\n\tGetINIString(section, entry, buffer, buffer, sizeof(buffer),\n\t\t\tfname);\n\n\treturn (atoi(buffer));\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetINIString - Get a string from the INI file.\n*\n* SYNOPSIS\n*     Length = GetINIString(Section, Entry, Default, Buffer,\n*                                      Length, ININame)\n*\n*     long GetINIString(char *, char *, char *, char *, long,\n*                                  char *);\n*\n* FUNCTION\n*\n* INPUTS\n*     Section - Pointer to section name.\n*     Entry   - Pointer to entry name.\n*     Default - Pointer to default string.\n*     Buffer  - Pointer to buffer to copy string into.\n*     Length  - Maximum length of string.\n*     ININame - Pointer to INI filename.\n*\n* RESULT\n*     Length - Length of string copied into the buffer.\n*\n****************************************************************************/\n\nlong GetINIString(char const *section, char const *entry, \n\t\tchar const *def, char *retbuffer, long retlen, char *fname)\n{\n\tFILE *fp;\n\tlong retval;\n\tchar txt[80];\n\tchar secname[40];\n\tlong len;\n\tchar *workptr;\n\n\t/* Copy default value in case entry isn't found */\n\tstrncpy(retbuffer, def, (retlen - 1));\n\tretbuffer[retlen - 1] = 0;\n\tretval = min(strlen(def), (unsigned)retlen);\n\n\t/* Open the file */\n\tif ((fp = fopen(fname, \"rt\")) == NULL) {\n\t\treturn (retval);\n\t}\n\n\t/* Generate section name for search */\n\tsprintf(secname, \"[%s]\", section);\n\tlen = strlen(secname);\n\n\t/* Scan file for section name */\n\twhile (1) {\n\n\t\t/* Read line; return if end-of-file */\n\t\tif (FileGets(fp,txt,80)!=0) {\n\t\t\tfclose(fp);\n\t\t\treturn (retval);\n\t\t}\n\n\t\t/* Skip comments */\n\t\tif (txt[0] == ';') continue;\n\n\t\t/* Parse a section name */\n\t\tif (txt[0] == '[') {\n\t\t\tif (!memicmp(secname, txt, len)) break;\n\t\t}\n\t}\n\n\t/* Scan file for desired entry */\n\tlen = strlen(entry);\n\n\twhile (1) {\n\n\t\t/* Read line; return if end-of-file */\n\t\tif (FileGets(fp, txt, 80) != 0) {\n\t\t\tfclose(fp);\n\t\t\treturn (retval);\n\t\t}\n\n\t\t/* Skip comments */\n\t\tif (txt[0] == ';') continue;\n\n\t\t/* Return if start of next section reached */\n\t\tif (txt[0] == '[') {\n\t\t\tfclose(fp);\n\t\t\treturn (retval);\n\t\t}\n\n\t\t/* Entry found; parse it */\n\t\tif (!memicmp(entry, txt, len) && (isspace(txt[len])\n\t\t\t\t|| txt[len] == '=')) {\n\n\t\t\tfclose(fp);\n\n\t\t\t/* Find '=' character */\n\t\t\tworkptr = strchr(txt, '=');\n\n\t\t\t/* Return if not found */\n\t\t\tif (workptr == NULL) return (retval);\n\n\t\t\t/* Skip past '=' */\n\t\t\tworkptr++;\n\n\t\t\t/* Skip white space */\n\t\t\twhile (isspace(*workptr) && strlen(workptr) > 0) {\n\t\t\t\tworkptr++;\n\t\t\t}\n\n\t\t\t/* Return if no string left */\n\t\t\tif ((*workptr) == 0) return (retval);\n\n\t\t\tstrtrim(workptr);\n\t\t\tstrcpy(retbuffer,workptr);\n\n\t\t\treturn (strlen(workptr));\n\t\t}\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     strtrim - Trim off trailing spaces from a string.\n*\n* SYNOPSIS\n*     String = strtrim(String)\n*\n*     char *strtrim(char *);\n*\n* FUNCTION\n*\n* INPUTS\n*     String - Pointer to string to trim.\n*\n* RESULT\n*     String - Pointer to trimmed string.\n*\n****************************************************************************/\n\nstatic char *strtrim(char *string)\n{\n\tlong i;\n\n\t/* Return if NULL ptr or zero-length string */\n\tif ((string == NULL) || (strlen(string) == 0)) {\n\t\treturn (string);\n\t}\n\n\t/* Find 1st non-white-space character from the right */\n\ti = (strlen(string) - 1);\n\n\twhile ((i > 0) && isspace(string[i])) {\n\t\ti--;\n\t}\n\n\t/* Set end of string */\n\ti++;\n\tstring[i] = 0;\n\n\treturn (string);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     FileGets - A better fgets.\n*\n* SYNOPSIS\n*     Error = FileGets(FilePtr, Buffer, Length)\n*\n*     long FileGets(FILE *, char *, long);\n*\n* FUNCTION\n*\n* INPUTS\n*     FilePtr - File pointer.\n*     Buffer  - Pointer to buffer to fill.\n*     Length  - Maximum length of buffer.\n*\n* RESULT\n*     Error = 0 if successfull, or -1 if error.\n*\n****************************************************************************/\n\nstatic long FileGets(FILE *fp, char *buf, long buflen)\n{\n\tif (fgets(buf, buflen, fp)) {\n\t\tbuf[(strlen(buf) - 1)] = 0;\n\t\treturn (0);\n\t} else {\n\t\treturn (-1);\n\t}\n}\n\n"
  },
  {
    "path": "WINVQ/VQM32/PROFILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMPROFILE_H\n#define VQMPROFILE_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Profile.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     INI file profiling definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\nlong GetINIInt(char const *section, char const *entry,\n\t\tlong deflt, char *fname);\n\nlong GetINIString(char const *section, char const *entry, \n\t\tchar const *def, char *retbuffer, long retlen, char *fname);\n\nlong Get_Frame_Pathname(char *inifile,long anim_frame,char *ext,\n\t\tchar *outbuf);\n\n#endif /* VQMPROFILE_H */\n\n"
  },
  {
    "path": "WINVQ/VQM32/REALMODE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMREALMODE_H\n#define VQMREALMODE_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     realmode.h\n*\n* DESCRIPTION\n*     Real-mode interfacing definitions and equates. Many of the definitions\n*     and descriptions in this file were taken from other sources and\n*     compiled here for use in MISC32 library.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 6, 1995\n*\n****************************************************************************/\n\n/* REALPTR: Real-mode pointer (segment:offset16).\n *\n * The REALPTR data type is used in protected mode to hold real-mode\n * pointers. The type is an unsigned long value, were the upper 16 bits\n * are the segment number and the lower 16 bit are an offset. This type\n * and the associated macros are identical to that of the PHARLAP \"pltypes.h\"\n * definitions for easy of conversion to WATCOM/4GW.\n */\ntypedef unsigned long REALPTR;\n\n#define RP_OFF(rp) ((unsigned short)(((unsigned long)(rp)) & 0xFFFF))\n#define RP_SEG(rp) ((unsigned short)(((unsigned long)(rp)) >> 16))\n#define RP_SET(rp, off, seg) (rp = ((unsigned long)(seg) << 16) + (off))\n#define RP_INCR(rp, incr) (rp += ((unsigned long)(incr)) & 0xFFFF)\n\n#define MK_PTR(off, seg) (void *)((((unsigned long)seg&0xFFFF)<<4)+off)\n\n/* RMInfo: Real-mode interrupt call structure.\n *\n * Information that needs to be passed down to the real-mode interrupt is\n * transfered using this structure. The address to this protected-mode\n * structure (allocated by user) is passed into DPMI function 0x300. DOS/4GW\n * will then use this information to set up the real-mode registers, switch\n * to real-mode and then execute the interrupt in real-mode.\n */\ntypedef struct _RMInfo {\n\tlong  edi;\n\tlong  esi;\n\tlong  ebp;\n\tlong  reservedbysystem;\n\tlong  ebx;\n\tlong  edx;\n\tlong  ecx;\n\tlong  eax;\n\tshort flags;\n\tshort es,ds,fs,gs,ip,cs,sp,ss;\n} RMInfo;\n\n#endif /* VQMREALMODE_H */\n\n"
  },
  {
    "path": "WINVQ/VQM32/SORTPAL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     sortpal.c\n*\n* DESCRIPTION\n*     Palette sorting routines. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*     Bill Randolph\n*\n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     SortPalette    - Sort a palette.\n*     Comp_Luminance - Compare the luminace of two 24-bit palette entries.\n*     Comp_HSV       - Compare the HSV of two 24-bit palette entries.\n*     RGB_To_HSV     - Convert RGB color to HSV color.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include \"palette.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n/* HSV color model */\n#define DIVIDE_WITH_ROUND(n,d) (unsigned short)(((n)/(d))+ \\\n\t\t(unsigned short)(((n)%(d)) >= (((d)+1)>>1)))\n\n#define HSV_BASE          255\n#define HUE_WEIGHT        10L\n#define SATURATION_WEIGHT 100L\n#define VALUE_WEIGHT      1000L\n\n/* Prototypes */\nstatic int Comp_Luminance(const void *elem1, const void *elem2);\nstatic int Comp_HSV(const void *elem1, const void *elem2);\nstatic void RGB_To_HSV(unsigned short r, unsigned short g, unsigned short b, \n\t\tunsigned short *h, unsigned short *s, unsigned short *v);\n\n\n/****************************************************************************\n*\n* NAME\n*     SortPalette - Sort a palette.\n*\n* SYNOPSIS\n*     SortPalette(Palette, NumColors)\n*\n*     void SortPalette(unsigned char *, long);\n*\n* FUNCTION\n*     Sort the palette colors.\n*\n* INPUTS\n*     Palette   - Pointer to palette to sort.\n*     NumColors - Number of colors in the palette.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid SortPalette(unsigned char *pal, long numcolors)\n{\n\tqsort(pal, numcolors, 3, Comp_Luminance);\n\n\tpal[0] = 0;\n\tpal[1] = 0;\n\tpal[2] = 0;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Comp_Luminance - Compare the luminace of two 24-bit palette entries.\n*\n* SYNOPSIS\n*     Result = Comp_Luminance(Color1, Color2)\n*\n*     long Comp_Luminance(void *, void *);\n*\n* FUNCTION\n*     Compare the luminace of the two colors and determine which color is\n*     brighter than the other.\n*\n*     The computation used is:\n*       Luminance = (red * .299) + (green * .587) + (blue * .114)\n*\n* INPUTS\n*     Color1 - Pointer to palette entry.\n*     Color2 - Pointer to palette entry.\n*\n* RESULT\n*     Result - 0 = same, 1 = Color1 > Color2, -1 = Color1 < Color2\n*\n****************************************************************************/\n\nstatic int Comp_Luminance(const void *elem1, const void *elem2)\n{\n\tunsigned char *pal;\n\tlong          r,g,b;\n\tlong          total1,total2;\n\n\t/* Compute luminance for color1 */\n\tpal = (unsigned char *)elem1;\n\tr = ((long)pal[0]);\n\tg = ((long)pal[1]);\n\tb = ((long)pal[2]);\n\ttotal1 = ((r * 19595L) + (g * 38470L) + (b * 7471L));\n\n\t/* Compute luminance for color2 */\n\tpal = (unsigned char *)elem2;\n\tr = ((long)pal[0]);\n\tg = ((long)pal[1]);\n\tb = ((long)pal[2]);\n\ttotal2 = ((r * 19595L) + (g * 38470L) + (b * 7471L));\n\n\tif (total1 < total2) {\n\t\treturn (-1);\n\t} else if (total1 > total2) {\n\t\treturn (1);\n\t} else {\n\t\treturn (0);\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     Comp_HSV - Compare the HSV of two 24-bit palette entries.\n*\n* SYNOPSIS\n*     Result = Comp_HSV(Color1, Color2)\n*\n*     long Comp_HSV(void *, void *);\n*\n* FUNCTION\n*     Compare the HSV color values of two colors and determine the\n*     relationship between the colors in the color space.\n*\n* INPUTS\n*     Color1 - Pointer to 1st palette entry.\n*     Color2 - Pointer to 2nd palette entry.\n*\n* RESULT\n*     Result - 0 = same, 1 = Color1 > Color2, -1 = Color1 < Color2\n*\n****************************************************************************/\n\nstatic int Comp_HSV(const void *elem1, const void *elem2)\n{\n\tunsigned char  *pal;\n\tunsigned char  r,g,b;\n\tunsigned short h,s,v;\n\tunsigned long  key1,key2;\n\tlong           retval;\n\n\t/* Convert 1st element to HSV */\n\tpal = (unsigned char *)elem1;\n\tr = pal[0];\n\tg = pal[1];\n\tb = pal[2];\n\n\tRGB_To_HSV((unsigned short)r,(unsigned short)g,(unsigned short)b,&h,&s,&v);\n\tkey1 = ((h * HUE_WEIGHT) + (s * SATURATION_WEIGHT) + (v * VALUE_WEIGHT));\n\n\t/* Convert 2nd element to HSV */\n\tpal = (unsigned char *)elem2;\n\tr = pal[0];\n\tg = pal[1];\n\tb = pal[2];\n\n\tRGB_To_HSV((unsigned short)r,(unsigned short)g,(unsigned short)b,&h,&s,&v);\n\tkey2 = ((h * HUE_WEIGHT) + (s * SATURATION_WEIGHT) + (v * VALUE_WEIGHT));\n\n\tif (key1 != key2) {\n\t\tretval = ((key1 < key2) ? -1 : 1);\n\t} else {\n\t\tretval = 0;\n\t}\n\n\treturn (retval);\n}\n\n\n/***************************************************************************\n*\n* NAME\n*     RGB_To_HSV - Convert RGB color to HSV color.\n*\n* SYNOPSIS\n*     RGB_To_HSV(R, G, B, H, S, V)\n*\n*     void RGB_To_HSV(unsigned short, unsigned short, unsigned short,\n*                     unsigned short *, unsigned short *, unsigned short *);\n*\n* FUNCTION\n*     Convert the RBG color to a HSV color. Assumes 8 bits per gun of R, G\n*     and B data. Also the HSV is based on a 255 degree scale rather than\n*     the more accurate 360 degree scale.\n*\n* INPUTS\n*     R - Red gun value.\n*     G - Green gun value.\n*     B - Blue gun value.\n*     H - Pointer to H value. (H will be set upon return of this function)\n*     S - Pointer to S value. (S will be set upon return of this function)\n*     V - Pointer to V value. (V will be set upon return of this function)\n*\n* RESULT\n*     NONE\n*\n***************************************************************************/\n\nstatic void RGB_To_HSV(unsigned short r, unsigned short g, unsigned short b, \n\t\tunsigned short *h, unsigned short *s, unsigned short *v)\n{\n \tunsigned short m;\n\tunsigned short r1;\n\tunsigned short g1;\n\tunsigned short b1;\n\tunsigned short tmp;\n\n\t/* Set hue to default. */\n\t*h = 0;\n\n\t/* Set v = Max(r,g,b) to find dominant primary color. */\n\t*v = ((r > g) ? r : g);\n\n\tif (b > *v) {\n\t\t*v = b;\n\t}\n\n\t/* Set m = min(r,g,b) to find amount of white. */\n\tm = ((r < g) ? r : g);\n\n\tif (b < m) {\n\t\tm = b;\n\t}\n\n\t/* Determine the normalized saturation. */\n\tif (*v != 0) {\n\t\t*s = DIVIDE_WITH_ROUND((*v - m) * HSV_BASE, *v);\n\t} else {\n\t\t*s = 0;\n\t}\n\n\tif (*s != 0) {\n\t\ttmp = *v - m;\n\t \tr1 = DIVIDE_WITH_ROUND((*v - r) * HSV_BASE, tmp);\n\t \tg1 = DIVIDE_WITH_ROUND((*v - g) * HSV_BASE, tmp);\n\t \tb1 = DIVIDE_WITH_ROUND((*v - b) * HSV_BASE, tmp);\n\n\t\t/* Find effect of second most predominant color.\n\t\t * In which section of the hexagon of colors does the color lie?\n\t\t */\n\t\tif ((*v) == r) {\n\t\t \tif (m == g) {\n\t\t\t\t*h = 5 * HSV_BASE + b1;\n\t\t\t} else {\n\t\t\t\t*h = 1 * HSV_BASE - g1;\n\t\t\t}\n\t\t} else {\n\t\t\tif ((*v) == g) {\n\t\t\t \tif (m == b) {\n\t\t\t\t\t*h = 1 * HSV_BASE + r1;\n\t\t\t\t} else {\n\t\t\t\t\t*h = 3 * HSV_BASE - b1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t \tif (m == r) {\n\t\t\t\t\t*h = 3 * HSV_BASE + g1;\n\t\t\t\t} else {\n\t\t\t\t\t*h = 5 * HSV_BASE - r1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Divide by six and round. */\n\t\t*h = DIVIDE_WITH_ROUND(*h, 6);\n\t}\n}\n"
  },
  {
    "path": "WINVQ/VQM32/SOSCODEC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*          Copyright (c) 1994, HMI, INC. All Rights Reserved\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     soscodec.asm\n;*\n;* DESCRIPTION\n;*     HMI SOS ADPCM compression/decompression.\n;*\n;* PROGRAMMER\n;*     Nick Skrepetos\n;*     Denzil E. Long, Jr. (Fixed bugs, rewrote for watcom)\n;*\t   Bill Petro\t\t   (Added stereo support)\n;* DATE\n;*     Febuary 15, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\n\tSTRUC\tsCompInfo\nlpSource\tDD\t?\t;Compressed data pointer\nlpDest\tDD\t?\t;Uncompressed data pointer\ndwCompSize\tDD\t?\t;Compressed size\ndwUnCompSize\tDD\t?\t;Uncompressed size\nwBitSize\tDW\t?\t;Bit size for decompression\nwChannels\tDW\t?\t;number of channels\n\ndwSampleIndex\tDD\t?\t;Index into sample\ndwPredicted\tDD\t?\t;Next predicted value\ndwDifference\tDD\t?\t;Difference from last sample\nwCodeBuf\tDW\t?\t;Holds 2 nibbles for decompression\nwCode\tDW\t?\t;Current 4 bit code\nwStep\tDW\t?\t;Step value in table\nwIndex\tDW\t?\t;Index into step table\n\ndwSampleIndex2\tDD\t?\t;Index into sample\ndwPredicted2\tDD\t?\t;Next predicted value\ndwDifference2\tDD\t?\t;Difference from last sample\nwCodeBuf2 \tDW\t?\t;Holds 2 nibbles for decompression\nwCode2\tDW\t?\t;Current 4 bit code\nwStep2\tDW\t?\t;Step value in table\nwIndex2\tDW\t?\t;Index into step table\n\tENDS\tsCompInfo\n\n\tDATASEG\n\n;* Index table for stepping into step table\n\nwCODECIndexTab\tDW\t-1,-1,-1,-1,2,4,6,8\n\t\tDW\t-1,-1,-1,-1,2,4,6,8\n\n\n;Lookup table of replacement values\n;The actual sound value is replaced with an index to lookup in this table\n;The index only takes up a nibble(4bits) and represents an int(16bits)\n;Essentially:\n;Get a value\n;compare it with the value before it\n;find closest value in table and store the index into the table\n;if i'm going down then negitize it\n;go to next byte.\n\n;Theory for stereo:\n;1)handle stereo and mono in two seperate loops. cleaner...\n;start at byte 0 and skip every other byte(or word) both write and read\n;when we get done set start byte to 1 and do it again\n\n\n;This table essentialy round off to closes values in 3 distinct bands\n; precalculated and optimized(i guess) for human hearing.\n\nwCODECStepTab\tDW\t7,8,9,10,11,12,13,14\n\tDW\t16,17,19,21,23,25,28,31\n\tDW\t34,37,41,45,50,55,60,66\n\tDW\t73,80,88,97,107,118,130,143\n\tDW\t157,173,190,209,230,253,279,307\n\tDW\t337,371,408,449,494,544,598,658\n\tDW\t724,796,876,963,1060,1166,1282,1411\n\tDW\t1552,1707,1878,2066,2272,2499,2749,3024\n\tDW\t3327,3660,4026,4428,4871,5358,5894,6484\n\tDW\t7132,7845,8630,9493,10442,11487,12635,13899\n\tDW\t15289,16818,18500,20350,22385,24623,27086,29794\n\tDW\t32767\n\ndwCODECByteIndex\t\tDD\t0 ; this is when to stop compressing\ndwCODECBytesProcessed\t\tDD\t0 ; this is how many so far compressed\ndwCODECTempStep\t\tDD\t0 ; tempory storage for step value\nwCODECMask\t\t\tDW\t0 ; Current mask\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECInitStream - Initialize compression stream.\n;*\n;* SYNOPSIS\n;*     sosCODECInitStream(CompInfo)\n;*\n;*     void sosCODECInitStream(_SOS_COMPRESS_INFO *);\n;*\n;* FUNCTION\n;*     Initialize compression stream for compression and decompression.\n;*\n;* INPUTS\n;*     CompInfo - Compression information structure.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC VQA_sosCODECInitStream:NEAR\n\tPROC\tVQA_sosCODECInitStream C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\n\tmov\teax,[sSOSInfo]\n\tmov\t[(sCompInfo eax).wIndex],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).wStep],7  \t\t; start with a step of 7\n\tmov\t[(sCompInfo eax).dwPredicted],0 \t; no predicted value\n\tmov\t[(sCompInfo eax).dwSampleIndex],0\t;start at head of index\n\tmov\t[(sCompInfo eax).wIndex2],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).wStep2],7  \t\t; start with a step of 7\n\tmov\t[(sCompInfo eax).dwPredicted2],0 \t; no predicted value\n\tmov\t[(sCompInfo eax).dwSampleIndex2],0 \t;start at head of index\n\tret\n\n\tENDP\tVQA_sosCODECInitStream\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECCompressData - Compress audio data.\n;*\n;* SYNOPSIS\n;*     Size = sosCODECCompressData(CompInfo, NumBytes)\n;*\n;*     long sosCODECCompressData(_SOS_COMPRESS_INFO *, long);\n;*\n;* FUNCTION\n;*     Compress an audio data stream into 4:1 ADPCM. 16 bit data is\n;*     compressed 4:1, 8 bit data is compressed 2:1.\n;*\n;* INPUTS\n;*     CompInfo - Pointer to initialized compress information structure.\n;*     NumBytes - Number of bytes to compress.\n;*\n;* RESULT\n;*     Size - Size of compressed data.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC VQA_sosCODECCompressData:NEAR\n\tPROC\tVQA_sosCODECCompressData C NEAR\n\tARG\tsSOSInfo:NEAR PTR\n\tARG\twBytes:DWORD\n\n\tpush\tesi\n\tpush\tedi\n\tpush\tebx\n\tpush\tecx\n\tpush\tedx\n\n;*---------------------------------------------------------------------------\n;*\tInitialize\n;*---------------------------------------------------------------------------\n\n\tmov\tebx,[sSOSInfo]\n\tmov\teax,[wBytes]\n\tmov\t[dwCODECBytesProcessed],eax\n\tmov\t[(sCompInfo ebx).dwSampleIndex],0 \t;start at head of index\n\tmov\t[(sCompInfo ebx).dwSampleIndex2],0\t;start at head of index\n\n;\tCheck for 16 bit decompression\n\n\tcmp\t[(sCompInfo ebx).wBitSize],16\t\t;16 bit requested?\n\tjne\tshort ??skipByteDivide\t\t\t;no so skip divide\n\tshr\teax,1\t\t\t\t\t;divide size by 2\n\n??skipByteDivide:\n\tmov\t[dwCODECByteIndex],eax\n\tmov\tesi,[(sCompInfo ebx).lpSource]\t;ESI = source\n\tmov\tedi,[(sCompInfo ebx).lpDest]\t\t;EDI = dest\n\n\tcmp\t[(sCompInfo ebx).wChannels],2\t\t;stereo check\n\tje\t??mainloopl\n\n;------------------------------------------------------------------------\n; Mono start\n;------------------------------------------------------------------------\n\n??mainloop:\n\tcmp\t[(sCompInfo ebx).wBitSize],16  \t;are we doing 16 bit\n\tjne\tshort ??input8Bit\t       \t\t;no. goto 8 bit input\n\n\tmovsx\teax,[word ptr esi]\t       \t\t;Get 16bit sample\n\tadd\tesi,2\n\tjmp\tshort ??computeDiff\t\t\t\t;skip 8 bit load\n\n??input8Bit:\n\tmov\tah,[esi]\t\t\t\t\t;Get 8bit sample\n\tinc\tesi\n\txor\tal,al\t\t\t\t\t;zero out low byte\n\txor\tah,80h\t\t\t\t\t;flip sign bit\n\tmovsx\teax,ax\n\n??computeDiff:\n\tmovsx\tecx,[word ptr (sCompInfo ebx).dwPredicted]\n\tsub\teax,ecx\t\t\t\t\t;sample-predicted\n\txor\tecx,ecx\t\t\t\t\t;clear ecx\n\tcmp\teax,0\t\t\t\t\t;Diff > = 0\n\tjge\t??positive\n\n\tneg\teax\t\t\t\t\t;else difference= -difference\n\tor\tecx,8\t\t\t\t\t;set nibble sign bit in ecx\n\n??positive:\n\tmov\t[(sCompInfo ebx).wCode],cx\t\t;Store code\n\tmovsx\tecx,[(sCompInfo ebx).wStep]   \t;Get step value\n\tmov\t[dwCODECTempStep],ecx\n\tmov\tedx,4\t\t\t\t\t;mask value (i think)\n\tmov\tecx,3\t\t\t\t\t;loop count\n\n??quantizeLoop:\n\tcmp\teax,[dwCODECTempStep]\t  \t\t;Diff < step ?\n\tjl\tshort ??nextQLoop\t\t\t\t;goto nextQloop\n\n\t; OR in mask value into code and adjust difference.\n\n\tor\t[(sCompInfo ebx).wCode],dx\t\t;else or mask into code\n\tsub\teax,[dwCODECTempStep]\t\t\t;difference-=tempstep\n\n??nextQLoop:\n\tshr\t[dwCODECTempStep],1\t\t\t\t; TempStep>>=1\n\tshr\tedx,1\t\t\t\t\t; mask>>=1\n\tloop\t??quantizeLoop\t\t\t\t\t; back to quatize loop\n\n;-----------------------------------------------------------------------------------------\n; now i'v got the new diff and code is masked right\n;-----------------------------------------------------------------------------------------\n\n\t; store off new difference value\n\n\tmov\t[(sCompInfo ebx).dwDifference],eax\n\n\t; determine if sample index is even or odd.\n\t; this will determine if we need to get a new token or not.\n\n\ttest\t[(sCompInfo ebx).dwSampleIndex],1 \t; is it even? (starts at 0)\n\tjne\tshort ??storeToken\t\t\t; if so goto store token\n\n\t; else its odd so get token\n\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCode]\t\t;ax=wCode\n\tand\teax,0Fh\t\t\t\t\t;and off high nibble\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\t\t;wCodeBuf=ax\n\tjmp\tshort ??calcDifference\t\t\t;goto calcDifference\n\n??storeToken:\n\t; fetch new token\n\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCode]\t\t;ax=code\n\tshl\teax,4\t\t\t\t\t;shift low nibble to high\n\tor\tax,[(sCompInfo ebx).wCodeBuf]\t\t;or in the stored nibble\n\tmov\t[edi],al\t\t\t\t;*dest=al\n\tinc\tedi\t\t\t\t\t;dest++\n\n??calcDifference:\n\tmov\t[(sCompInfo ebx).dwDifference],0\t;dwDifference=0\n\txor\tecx,ecx\t\t\t\t\t;ecx=0\n\tmov\tcx,[(sCompInfo ebx).wStep]\t\t;cx=Step\n\txor\teax,eax\t\t\t\t\t;eax=0\n\tmov\tax,[(sCompInfo ebx).wCode]\t\t;ax=wCode\n\ttest\teax,4\t\t\t\t\t;Check 0100\n\tje\tshort ??no4\n\tadd\t[(sCompInfo ebx).dwDifference],ecx  \t;difference+=step\n\n??no4:\n\ttest\teax,2\t\t\t\t\t;Check 0010\n\tje\tshort ??no2\n\tmov\tedx,ecx\t\t\t\t\t;edx=wStep\n\tshr\tedx,1\t\t\t\t\t;edx>>1\n\tadd\t[(sCompInfo ebx).dwDifference],edx \t;Difference=wstep>>1\n\n??no2:\n\ttest\teax,1\t\t\t\t\t;Check 0001\n\tje\tshort ??no1\n\tmov\tedx,ecx\t\t\t\t\t;edx=wStep\n\tshr\tedx,2\t\t\t\t\t;edx>>2\n\tadd\t[(sCompInfo ebx).dwDifference],edx \t;Difference=wstep>>2\n\n??no1:\n\tmov\tedx,ecx\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference],edx\t;Difference=wstep>>3\n\ttest\teax,8\t\t\t\t\t;Check 1000\n\tje\tshort ??no8\n\tneg\t[(sCompInfo ebx).dwDifference]\t\t;Negate diff because sign bit was set\n\n??no8:\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\n\tadd\teax,[(sCompInfo ebx).dwDifference]\t;eax=Preditcted+Difference\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflow\n\tmov\teax,7FFFh\t\t\t\t;if overflow store 7fff in diff\n\n??noOverflow:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflow\n\tmov\teax,0FFFF8000h\t\t\t\t;if overflow  0FFFF8000 in diff\n\n??noUnderflow:\n\tmov\t[(sCompInfo ebx).dwPredicted],eax \t;store into predicted\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode]\t\t;cx=Code\n\txor\teax,eax\n\tshl\tecx,1\t\t\t\t\t;cx<<1\n\tmov\tax,[wCODECIndexTab + ecx]\t\t;ax=Indextab[ecx]\n\tadd\t[(sCompInfo ebx).wIndex],ax   \t\t;wIndex+=ax\n\tcmp\t[(sCompInfo ebx).wIndex],8000h\t\t; check if wIndex < 0\n\tjb\tshort ??checkOverflow\n\tmov\t[(sCompInfo ebx).wIndex],0\t\t; reset index to zero\n\tjmp\tshort ??adjustStep\n\n??checkOverflow:\n\tcmp\t[(sCompInfo ebx).wIndex],88\t\t; check if wIndex > 88\n\tjbe\tshort ??adjustStep\n\tmov\t[(sCompInfo ebx).wIndex],88\t\t; reset index to 88\n\n\n??adjustStep:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex],1\n\tmov\t[(sCompInfo ebx).wStep],ax\n\n\t; decrement bytes processed and loop back.\n\n\tdec\t[dwCODECByteIndex]\n\tjne\t??mainloop\t\t    \t\t; }while !0\n\n\tjmp\t??exitout\n;-----------------------------------------------------------------------\n;Stereo\tLeft Side\n;-----------------------------------------------------------------------\n\n??mainloopl:\n; determine bit size for input\t\t\t\t;do{\n\n\tcmp\t[(sCompInfo ebx).wBitSize],16  \t\t;are we doing 16 bit\n\tjne\tshort ??input8Bitl\t       \t\t;no. goto 8 bit input\t\t**\n\n\tmovsx\teax,[word ptr esi]\t       \t\t;load next word from source\n\tadd\tesi,4\t\t\t\t\t;inc source by 2 words  \t\t**\n\tjmp\tshort ??computeDiffl\t\t\t;skip 8 bit load\t\t\t**\n\n??input8Bitl:\n\tmov\tah,[esi]\t\t\t\t;Get 8 bit sample\n\tadd\tesi,2   \t\t\t\t;inc source by 2 bytes\t\t**\n\txor\tal,al\t\t\t\t\t;zero out low byte\n\txor\tah,80h\t\t\t\t\t;flip sign bit\n\tmovsx\teax,ax\t\t\t\t\t;sign extend into eax\n\n??computeDiffl:\n\t; compute difference\n\n\tmovsx\tecx,[word ptr (sCompInfo ebx).dwPredicted]\n\t\t\t\t\t\t\t;load predicted (starts at 0)\n\tsub\teax,ecx\t\t\t\t\t;difference=sample-preditcted\n\n\t; check if dwDifference > 0.  ECX is the\n\t; sign bit, it is initialized to positive.\n\n\txor\tecx,ecx\t\t\t\t       \t;clear ecx\n\tcmp\teax,0\t\t\t\t\t;if(difference>=0)\n\tjge\tshort ??positivel\t\t\t;goto positive\n\n\tneg\teax\t\t\t\t\t;else difference= -difference\n\tor\tecx,8\t\t\t\t\t;set nibble sign bit in ecx\n\n??positivel:\n\tmov\t[(sCompInfo ebx).wCode],cx\t\t;Store code from cx into struct\n\n\t; set up to quantize difference. initialize\n\t; wCODECTempStep = step value.\n\n\tmovsx\tecx,[(sCompInfo ebx).wStep]   \t\t;ecx=step value(starts at 7)\n\tmov\t[dwCODECTempStep],ecx\t\t\t;tempstep=step\n\tmov\tedx,4\t\t\t\t\t;edx=4   mask value (i think)\n\tmov\tecx,3\t\t\t\t\t;ecx is loop number so loop 3 times\n\n??quantizeLoopl:\n\t; check to see if difference > tempstep value.\n\n\tcmp\teax,[dwCODECTempStep]\t  \t\t;if(difference < tempstep)\n\tjl\tshort ??nextQLoopl\t\t\t;goto nextQloop\n\n\t; OR in mask value into code and adjust difference.\n\n\tor\t[(sCompInfo ebx).wCode],dx\t\t;else or mask into code\n\tsub\teax,[dwCODECTempStep]\t\t\t;difference-=tempstep\n\n??nextQLoopl:\n\n\t; shift down tempstep and mask\n\n\tshr\t[dwCODECTempStep],1\t\t\t; TempStep>>=1\n\tshr\tedx,1\t\t\t\t\t; mask>>=1\n\tloop\t??quantizeLoopl\t\t\t\t; back to quatize loop\n;------------------------------------------------------------------------------------------\n; now i'v got the new diff and code is masked right\n\n\t; store off new difference value\n\n\tmov\t[(sCompInfo ebx).dwDifference],eax\n\n\t; determine if sample index is even or odd.\n\t; this will determine if we need to get a new token or not.\n\n\ttest\t[(sCompInfo ebx).dwSampleIndex],1 \t; is it even? (starts at 0)\n\tjne\tshort ??storeTokenl\t\t\t; if so goto store token\t\t**\n\n\t; else its odd so get token\n\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCode]\t\t;ax=wCode\n\tand\teax,0Fh\t\t\t\t\t;and off high nibble\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\t\t;wCodeBuf=ax\n\tjmp\tshort ??calcDifferencel\t\t\t;goto calcDifference\t\t**\n\n??storeTokenl:\n\t; fetch new token\n\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCode]\t\t;ax=code\n\tshl\teax,4\t\t\t\t\t;shift low nibble to hign nibble\n\tor\tax,[(sCompInfo ebx).wCodeBuf]\t\t;or in the stored nibble\n\tmov\t[edi],al\t\t\t\t;*dest=al\n\tadd\tedi,2\t\t\t\t\t;dest+=2\t\t\t\t\t**\n\n??calcDifferencel:\n\tmov\t[(sCompInfo ebx).dwDifference],0;dwDifference=0\n\txor\tecx,ecx\t\t\t\t\t;ecx=0\n\tmov\tcx,[(sCompInfo ebx).wStep]\t\t;cx=Step\n\txor\teax,eax\t\t\t\t\t;eax=0\n\tmov\tax,[(sCompInfo ebx).wCode]\t\t;ax=wCode\n\ttest\teax,4\t\t\t\t\t;Check 0100\n\tje\tshort ??no4l\t\t\t\t;\t\t\t\t\t\t**\n\tadd\t[(sCompInfo ebx).dwDifference],ecx  \t;difference+=step\n\n??no4l:\n\ttest\teax,2\t\t\t\t\t;Check 0010\n\tje\tshort ??no2l\t\t\t\t;\t\t\t\t\t\t**\n\tmov\tedx,ecx\t\t\t\t\t;edx=wStep\n\tshr\tedx,1\t\t\t\t\t;edx>>1\n\tadd\t[(sCompInfo ebx).dwDifference],edx \t;Difference=wstep>>1\n\n??no2l:\n\ttest\teax,1\t\t\t\t\t;Check 0001\n\tje\tshort ??no1l\t\t\t\t;\t\t\t\t\t\t**\n\tmov\tedx,ecx\t\t\t\t\t;edx=wStep\n\tshr\tedx,2\t\t\t\t\t;edx>>2\n\tadd\t[(sCompInfo ebx).dwDifference],edx \t;Difference=wstep>>2\n\n??no1l:\n\tmov\tedx,ecx\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference],edx\t;Difference=wstep>>3\n\ttest\teax,8\t\t\t\t\t;Check 1000\n\tje\tshort ??no8l\n\n\t;Negate diff because sign bit was set\n\n\tneg\t[(sCompInfo ebx).dwDifference]\n\n??no8l:\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\n\tadd\teax,[(sCompInfo ebx).dwDifference]\t;eax=Preditcted+Difference\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowl\n\tmov\teax,7FFFh\t\t\t\t;if overflow store 7fff in diff\n\n??noOverflowl:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowl\n\tmov\teax,0FFFF8000h\t\t\t\t;if overflow  0FFFF8000 in diff\n\n??noUnderflowl:\n\tmov\t[(sCompInfo ebx).dwPredicted],eax \t;store into predicted\n\txor\tecx,ecx\t\t\t\t\t;adjust index\n\tmov\tcx,[(sCompInfo ebx).wCode]\t\t;cx=Code\n\txor\teax,eax\n\tshl\tecx,1\t\t\t\t\t;cx<<1\n\tmov\tax,[wCODECIndexTab + ecx]\t\t;ax=Indextab[ecx]\n\tadd\t[(sCompInfo ebx).wIndex],ax   \t\t;wIndex+=ax\n\n\n\tcmp\t[(sCompInfo ebx).wIndex],8000h\t\t;check if wIndex < 0\n\tjb\tshort ??checkOverflowl\t\t\t;\t\t\t\t\t\t\t\t**\n\tmov\t[(sCompInfo ebx).wIndex],0\t\t; reset index to zero\n\tjmp\tshort ??adjustStepl\t\t\t;\t\t\t\t\t\t\t**\n\n??checkOverflowl:\n\t; check if wIndex > 88\n\n\tcmp\t[(sCompInfo ebx).wIndex],88\n\tjbe\tshort ??adjustStepl\t\t\t;\t\t\t\t\t\t\t**\n\n\t; reset index to 88\n\n\tmov\t[(sCompInfo ebx).wIndex],88\n\n??adjustStepl:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex],1\n\tmov\t[(sCompInfo ebx).wStep],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2    ; sub 2 for stereo\t\t\t\t\t**\n\tjne\t??mainloopl\t\t    ; }while !0\t\t\t\t\t\t**\n\n;-------------------------------------------------------------------------\n;Right channel re-set up varibles\n;-------------------------------------------------------------------------\n\n\tmov\teax,[wBytes]\n\tmov\tesi,[(sCompInfo ebx).lpSource] \t\t; point to source buffer\n\tmov\tedi,[(sCompInfo ebx).lpDest]   \t\t; point to destination buffer\n\tinc esi\t\t\t\t\t\t; skip first byte\n\tinc edi\t\t\t\t\t\t; ship first byte\n\n;\tCheck for 16 bit compression\n\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tje\tshort ??do16bit\n\tmov\t[dwCODECByteIndex],eax\n\tjmp\tshort ??mainloopr\n\n??do16bit:\n\tshr\teax,1\t\t\t\t\t;16 bit so half as many bytes\n\tinc\tesi\t\t\t\t\t;16 bit so 1 more byte to skip\n\tmov\t[dwCODECByteIndex],eax\n\n\n;-----------------------------------------------------------------------\n;Start of Stereo Right Side\n;-----------------------------------------------------------------------\n\n??mainloopr:\n; determine bit size for input\t\t\t\t;do{\n\n\tcmp\t[(sCompInfo ebx).wBitSize],16  \t\t;are we doing 16 bit\n\tjne\tshort ??input8Bitr\t       \t\t;no. goto 8 bit input\t\t**\n\n\tmovsx\teax,[word ptr esi]\t       \t\t;load next word from source\n\tadd\tesi,4\t\t\t\t\t;inc source by 2 words  \t\t**\n\tjmp\tshort ??computeDiffr\t\t\t;skip 8 bit load\t\t\t**\n\n??input8Bitr:\n\tmov\tah,[esi]\t\t\t\t;Get 8 bit sample\n\tadd\tesi,2   \t\t\t\t;inc source by 2 bytes\t\t**\n\txor\tal,al\t\t\t\t\t;zero out low byte\n\txor\tah,80h\t\t\t\t\t;flip sign bit\n\tmovsx eax,ax\t\t\t\t\t;sign extend into eax\n\n??computeDiffr:\n\t; compute difference\n\n\tmovsx ecx,[word ptr (sCompInfo ebx).dwPredicted2]\n\t\t\t\t\t\t\t;load predicted (starts at 0)\n\tsub\teax,ecx\t\t\t\t\t;difference=sample-preditcted\n\n\t; check if dwDifference > 0.  ECX is the\n\t; sign bit, it is initialized to positive.\n\n\txor\tecx,ecx\t\t\t\t\t;clear ecx\n\tcmp\teax,0\t\t\t\t\t;if(difference>=0)\n\tjge\tshort ??positiver \t\t\t;goto positive\n\n\tneg\teax\t\t\t\t\t;else difference= -difference\n\tor\tecx,8\t\t\t\t\t;set nibble sign bit in ecx\n\n??positiver:\n\tmov\t[(sCompInfo ebx).wCode2],cx\t\t;Store code from cx into struct\n\n\t; set up to quantize difference. initialize\n\t; wCODECTempStep = step value.\n\n\tmovsx\tecx,[(sCompInfo ebx).wStep2]   \t\t;ecx=step value(starts at 7)\n\tmov\t[dwCODECTempStep],ecx\t\t\t;tempstep=step\n\tmov\tedx,4\t\t\t\t\t;edx=4   mask value (i think)\n\tmov\tecx,3\t\t\t\t\t;ecx is loop number so loop 3 times\n\n??quantizeLoopr:\n\t; check to see if difference > tempstep value.\n\n\tcmp\teax,[dwCODECTempStep]\t  \t\t;if(difference < tempstep)\n\tjl\tshort ??nextQLoopr\t\t\t;goto nextQloop\n\n\t; OR in mask value into code and adjust difference.\n\n\tor\t[(sCompInfo ebx).wCode2],dx\t\t;else or mask into code\n\tsub\teax,[dwCODECTempStep]\t\t\t;difference-=tempstep\n\n??nextQLoopr:\n\n\t; shift down tempstep and mask\n\n\tshr\t[dwCODECTempStep],1\t\t\t; TempStep>>=1\n\tshr\tedx,1\t\t\t\t\t; mask>>=1\n\tloop\t??quantizeLoopr\t\t\t\t; back to quatize loop\n;------------------------------------------------------------------------------------------\n; now i'v got the new diff and code is masked right\n\n\t; store off new difference value\n\n\tmov\t[(sCompInfo ebx).dwDifference2],eax\n\n\t; determine if sample index is even or odd.\n\t; this will determine if we need to get a new token or not.\n\n\ttest\t[(sCompInfo ebx).dwSampleIndex2],1\t; is it even? (starts at 0)\n\tjne\tshort ??storeTokenr\t\t\t; if so goto store token\t\t**\n\n\t; else its odd so get token\n\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCode2]\t\t;ax=wCode\n\tand\teax,0Fh\t\t\t\t\t;and off high nibble\n\tmov\t[(sCompInfo ebx).wCodeBuf2],ax\t\t;wCodeBuf=ax\n\tjmp\tshort ??calcDifferencer\t\t\t;goto calcDifference\t\t**\n\n??storeTokenr:\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCode2]\t\t;ax=code\n\tshl\teax,4\t\t\t\t\t;shift low nibble to hign nibble\n\tor\tax,[(sCompInfo ebx).wCodeBuf2]\t\t;or in the stored nibble\n\tmov\t[edi],al\t\t\t\t;*dest=al\n\tadd\tedi,2\t\t\t\t\t;dest+=2\t\t\t\t\t**\n\n??calcDifferencer:\n\tmov\t[(sCompInfo ebx).dwDifference2],0\t;dwDifference=0\n\txor\tecx,ecx\t\t\t\t\t;ecx=0\n\tmov\tcx,[(sCompInfo ebx).wStep2]\t\t;cx=Step\n\txor\teax,eax\t\t\t\t\t;eax=0\n\tmov\tax,[(sCompInfo ebx).wCode2]\t\t;ax=wCode\n\ttest\teax,4\t\t\t\t\t;Check 0100\n\tje\tshort ??no4r\n\tadd\t[(sCompInfo ebx).dwDifference2],ecx  \t;difference+=step\n\n??no4r:\n\ttest\teax,2\t\t\t\t\t;Check 0010\n\tje\tshort ??no2r\n\tmov\tedx,ecx\t\t\t\t\t;edx=wStep\n\tshr\tedx,1\t\t\t\t\t;edx>>1\n\tadd\t[(sCompInfo ebx).dwDifference2],edx ;Difference=wstep>>1\n\n??no2r:\n\ttest\teax,1\t\t\t\t\t;Check 0001\n\tje\tshort ??no1r\n\tmov\tedx,ecx\t\t\t\t\t;edx=wStep\n\tshr\tedx,2\t\t\t\t\t;edx>>2\n\tadd\t[(sCompInfo ebx).dwDifference2],edx \t;Difference=wstep>>2\n\n??no1r:\n\tmov\tedx,ecx\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\t;Difference=wstep>>3\n\ttest\teax,8\t\t\t\t\t;Check 1000\n\tje\tshort ??no8r\n\tneg\t[(sCompInfo ebx).dwDifference2]\n\n??no8r:\n\t; add difference to predicted value.\n\tmov\teax,[(sCompInfo ebx).dwPredicted2]\n\tadd\teax,[(sCompInfo ebx).dwDifference2]\t;eax=Preditcted+Difference\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowr\n\tmov\teax,7FFFh\t\t\t\t;if overflow store 7fff in diff\n\n??noOverflowr:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowr\n\tmov\teax,0FFFF8000h\t\t\t\t;if overflow  0FFFF8000 in diff\n\n??noUnderflowr:\n\tmov\t[(sCompInfo ebx).dwPredicted2],eax \t;store into predicted\n\txor\tecx,ecx\t\t\t\t\t;adjust index\n\tmov\tcx,[(sCompInfo ebx).wCode2]\t\t;cx=Code\n\txor\teax,eax\n\tshl\tecx,1\t\t\t\t\t;cx<<1\n\tmov\tax,[wCODECIndexTab + ecx]\t\t;ax=Indextab[ecx]\n\tadd\t[(sCompInfo ebx).wIndex2],ax   \t\t;wIndex+=ax\n\tcmp\t[(sCompInfo ebx).wIndex2],8000h\t\t;check if wIndex < 0\n\tjb\tshort ??checkOverflowr\n\tmov\t[(sCompInfo ebx).wIndex2],0\t\t;reset index to zero\n\tjmp\tshort ??adjustStepr\n\n??checkOverflowr:\n\n\tcmp\t[(sCompInfo ebx).wIndex2],88\t\t;check if wIndex > 88\n\tjbe\tshort ??adjustStepr\n\tmov\t[(sCompInfo ebx).wIndex2],88\t\t;reset index to 88\n\n\n??adjustStepr:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex2]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex2],1\n\tmov\t[(sCompInfo ebx).wStep2],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2    \t\t; sub 2 for stereo\n\tjne\t??mainloopr\t\t    \t\t; }while !0\n\n\n;-------------------------------------------------------------------------\n;Final clean up\n;-------------------------------------------------------------------------\n\n??exitout:\n\t; save off ESI and EDI back into compress info structure.\n\n;\tmov\t[(sCompInfo ebx).lpSource],esi\n;\tmov\t[(sCompInfo ebx).lpDest],edi\n\n\t; set up return value for number of bytes processed.\n\n\tmov\teax,[dwCODECBytesProcessed]\n\tshr\teax,1\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\t??leave\n\tshr\teax,1\t\t\t\t\t;if not 16 bit then div/2\n\n??leave:\n\tpop\tedx\n\tpop\tecx\n\tpop\tebx\n\tpop\tedi\n\tpop\tesi\n\tret\n\n\tENDP\tVQA_sosCODECCompressData\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECDecompressData - Decompress audio data.\n;*\n;* SYNOPSIS\n;*     Size = sosCODECDecompressData(CompInfo, NumBytes)\n;*\n;*     long sosCODECDecompressData(_SOS_COMPRESS_INFO *, long);\n;*\n;* FUNCTION\n;*     Decompress data from a 4:1 ADPCM compressed stream. The number of\n;*     bytes decompressed is returned.\n;*\n;* INPUTS\n;*     CompInfo - Compress information structure.\n;*     NumBytes - Number of bytes to compress.\n;*\n;* RESULT\n;*     Size - Size of decompressed data.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC VQA_sosCODECDecompressData:NEAR\n\tPROC\tVQA_sosCODECDecompressData C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\tARG\twBytes:DWORD\n\n\tpush\tesi\n\tpush\tedi\n\tpush\tebx\n\tpush\tecx\n\tpush\tedx\n\n;*---------------------------------------------------------------------------\n;*\tInitialize\n;*---------------------------------------------------------------------------\n\n\tmov\tebx,[sSOSInfo]\n\tmov\teax,[wBytes]\n\tmov\t[dwCODECBytesProcessed],eax\n\tmov\t[(sCompInfo ebx).dwSampleIndex],0 \t;start at head of index\n\tmov\t[(sCompInfo ebx).dwSampleIndex2],0 \t;start at head of index\n\n;*\tCheck for 16 bit decompression\n\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??skipByteDivide\n\tshr\teax,1\n\n??skipByteDivide:\n\tmov\t[dwCODECByteIndex],eax\n\tmov\tesi,[(sCompInfo ebx).lpSource]\n\tmov\tedi,[(sCompInfo ebx).lpDest]\n\tcmp\t[(sCompInfo ebx).wChannels],2\t\t;stereo check\n\tje\t??mainloopl\t\t\t\t;do left side first\n\n;\tDetermine if sample index is even or odd. This will determine\n;\tif we need to get a new token or not.\n\n;*---------------------------------------------------------------------------\n;*\tMain Mono Loop\n;*---------------------------------------------------------------------------\n\n??mainloop:\n\ttest\t[(sCompInfo ebx).dwSampleIndex],1\t;odd ??\n\tje\tshort ??fetchToken\t\t\t\t;if so get new token\n\txor\teax,eax\t\t\t\t\t;else shift int codebuf\n\tmov\tax,[(sCompInfo ebx).wCodeBuf]\t\t;ored with Code\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\tjmp\tshort ??calcDifference\n\n??fetchToken:\n\txor\teax,eax\t\t\t\t\t;get a new token\n\tmov\tal,[esi]\t\t\t\t\t;put in codebuf\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\n\tinc\tesi\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\t\t;and then code\n\n??calcDifference:\n\tmov\t[(sCompInfo ebx).dwDifference],0\t;reset diff\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep]\t\t;cx is step value\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4\n\tadd\t[(sCompInfo ebx).dwDifference],ecx\t;Add wStep\n\n??no4:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no2:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no1:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8\n\tneg\t[(sCompInfo ebx).dwDifference]\t;Negate diff\n\n??no8:\n\t; add difference to predicted value.\n\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\n\tadd\teax,[(sCompInfo ebx).dwDifference]\n\n\t; make sure there is no under or  overflow.\n\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflow\n\tmov\teax,7FFFh\n\n??noOverflow:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflow\n\tmov\teax,0FFFF8000h\n\n??noUnderflow:\n\tmov\t[(sCompInfo ebx).dwPredicted],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bit\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,2\n\tjmp\tshort ??adjustIndex\n\n??output8Bit:\n\t; output 8 bit sample\n\n\txor\tah,80h\n\tmov\t[edi],ah\n\tinc\tedi\n\n??adjustIndex:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex],ax \t\t;check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex],8000h\n\tjb\tshort ??checkOverflow\n\tmov\t[(sCompInfo ebx).wIndex],0\t\t;reset index to zero\n\tjmp\tshort ??adjustStep\n\n??checkOverflow:\n\tcmp\t[(sCompInfo ebx).wIndex],88\t\t;check if wIndex > 88\n\tjbe\tshort ??adjustStep\n\tmov\t[(sCompInfo ebx).wIndex],88\t\t;reset index to 88\n\n??adjustStep:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex],1\n\tmov\t[(sCompInfo ebx).wStep],ax\n\n\t; decrement bytes processed and loop back.\n\n\tdec\t[dwCODECByteIndex]\n\tjne\t??mainloop\n\tjmp\t??exitout\n\n;--------------------------------------------------------------------------\n;Left Channel Start\n;--------------------------------------------------------------------------\n\n\n??mainloopl:\n\ttest\t[(sCompInfo ebx).dwSampleIndex],1\n\tje\tshort ??fetchTokenl\n\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCodeBuf]\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\tjmp\tshort ??calcDifferencel\n\n??fetchTokenl:\n\txor\teax,eax\n\tmov\tal,[esi]\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\n\tadd\tesi,2\t\t\t\t\t;2 for stereo\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\n??calcDifferencel:\n\t\t\t\t\t\t\t; reset difference\n\n\tmov\t[(sCompInfo ebx).dwDifference],0\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep]\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4l\n\tadd\t[(sCompInfo ebx).dwDifference],ecx\t;Add wStep\n\n??no4l:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2l\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no2l:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1l\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no1l:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8l\n\tneg\t[(sCompInfo ebx).dwDifference]\t\t;Negate diff\n\n??no8l:\n\t\t; add difference to predicted value.\n\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\n\tadd\teax,[(sCompInfo ebx).dwDifference]\n\n\t\t; make sure there is no under or  overflow.\n\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowl\n\tmov\teax,7FFFh\n\n??noOverflowl:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowl\n\tmov\teax,0FFFF8000h\n\n??noUnderflowl:\n\tmov\t[(sCompInfo ebx).dwPredicted],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bitl\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,4\t\t\t\t\t;4 for stereo\n\tjmp\tshort ??adjustIndexl\n\n??output8Bitl:\n\t; output 8 bit sample\n\n\txor\tah,80h\n\tmov\t[edi],ah\n\tadd\tedi,2\t\t\t\t\t;2 for stereo\n\n??adjustIndexl:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex],ax\n\t\t\t\t\t\t\t; check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex],8000h\n\tjb\tshort ??checkOverflowl\n\tmov\t[(sCompInfo ebx).wIndex],0\n\tjmp\tshort ??adjustStepl\t\t\t;reset index to zero\n\n\n??checkOverflowl:\n\n\tcmp\t[(sCompInfo ebx).wIndex],88\t\t; check if wIndex > 88\n\tjbe\tshort ??adjustStepl\n\tmov\t[(sCompInfo ebx).wIndex],88\t\t; reset index to 88\n\n??adjustStepl:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex],1\n\tmov\t[(sCompInfo ebx).wStep],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2\n\tjne\t??mainloopl\n;----------------------------------------------------------------------------\n; Right Side Setup\n;----------------------------------------------------------------------------\n\tmov\teax,[wBytes]\n\tmov\t[dwCODECBytesProcessed],eax\n\tmov\tesi,[(sCompInfo ebx).lpSource]\n\tmov\tedi,[(sCompInfo ebx).lpDest]\n\tinc\tesi\t\t\t\t\t; skip left channel\n\tinc\tedi\t\t\t\t     \t; skip left channel\n\tcmp\t[(sCompInfo ebx).wBitSize],16\t\t;16 bit ??\n\tje\tshort ??doByteDivide\n\tmov\t[dwCODECByteIndex],eax\n\tjmp  short ??mainloopr\n\n??doByteDivide:\n\tshr\teax,1 \t\t\t\t\t;Divide size by two\n\tinc\tedi   \t\t\t\t\t; 16 bit so skip 1 more\n\tmov\t[dwCODECByteIndex],eax\n\n\n;--------------------------------------------------------------------------\n;Right Channel Start\n;--------------------------------------------------------------------------\n\n\n??mainloopr:\n\ttest\t[(sCompInfo ebx).dwSampleIndex2],1\n\tje\tshort ??fetchTokenr\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCodeBuf2]\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode2],ax\n\tjmp\tshort ??calcDifferencer\n\n??fetchTokenr:\n\txor\teax,eax\n\tmov\tal,[esi]\n\tmov\t[(sCompInfo ebx).wCodeBuf2],ax\n\tadd\tesi,2\t\t\t\t     \t;2 for stereo\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode2],ax\n\n??calcDifferencer:\n\t\t\t\t\t\t\t; reset difference\n\n\tmov\t[(sCompInfo ebx).dwDifference2],0\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep2]\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4r\n\tadd\t[(sCompInfo ebx).dwDifference2],ecx\t;Add wStep\n\n??no4r:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2r\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\n??no2r:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1r\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\n??no1r:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8r\n\tneg\t[(sCompInfo ebx).dwDifference2]\t\t;Negate diff\n\n??no8r:\n\t; add difference to predicted value.\n\tmov\teax,[(sCompInfo ebx).dwPredicted2]\n\tadd\teax,[(sCompInfo ebx).dwDifference2]\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowr\n\tmov\teax,7FFFh\n\n??noOverflowr:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowr\n\tmov\teax,0FFFF8000h\n\n??noUnderflowr:\n\tmov\t[(sCompInfo ebx).dwPredicted2],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bitr\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,4\t\t\t\t\t;4 for stereo\t\t***\n\tjmp\tshort ??adjustIndexr\n\n??output8Bitr:\n\t\t\t\t\t\t\t; output 8 bit sample\n\txor\tah,80h\n\tmov\t[edi],ah\n\tadd\tedi,2\t\t\t\t\t;2 for stereo\n\n??adjustIndexr:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode2]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex2],ax\n\t\t\t\t\t\t\t; check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex2],8000h\n\tjb\tshort ??checkOverflowr\n\t\t\t\t\t\t\t; reset index to zero\n\tmov\t[(sCompInfo ebx).wIndex2],0\n\tjmp\tshort ??adjustStepr\n\n??checkOverflowr:\n\t\t\t\t\t\t\t; check if wIndex > 88\n\tcmp\t[(sCompInfo ebx).wIndex2],88\n\tjbe\tshort ??adjustStepr\n\tmov\t[(sCompInfo ebx).wIndex2],88\t\t; reset index to 88\n\n??adjustStepr:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex2]\n\txor\teax,eax\n\tshl\tecx,1\n\tmov\tax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex2],1\n\tmov\t[(sCompInfo ebx).wStep2],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2\n\tjne\t??mainloopr\n\n\n??exitout:\n;\t\tdon't think we need this but just in case i'll leave it here!!\n\n;\tmov\t[(sCompInfo ebx).lpSource],esi\n;\tmov\t[(sCompInfo ebx).lpDest],edi\n\t; set up return value for number of bytes processed.\n\tmov\teax,[dwCODECBytesProcessed]\n\tpop\tedx\n\tpop\tecx\n\tpop\tebx\n\tpop\tedi\n\tpop\tesi\n\tret\n\n\tENDP\tVQA_sosCODECDecompressData\n\tEND\n\n\u001a\n"
  },
  {
    "path": "WINVQ/VQM32/SOSCOMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*  File              : soscomp.h\n*  Date Created      : 6/1/94\n*  Description       :\n*\n*  Programmer(s)     : Nick Skrepetos\n*  Last Modification : 10/1/94 - 11:37:9 AM\n*  Additional Notes  : Modified by Denzil E. Long, Jr.\n*\n*****************************************************************************\n*            Copyright (c) 1994,  HMI, Inc.  All Rights Reserved            *\n****************************************************************************/\n\n#ifndef  _SOS_COMPRESS\n#define  _SOS_COMPRESS\n\n/* compression types */\nenum {\n\t_ADPCM_TYPE_1,\n\t};\n\n/* define compression structure */\ntypedef struct _tagCOMPRESS_INFO {\n\tchar       *lpSource;\n\tchar       *lpDest;\n\tunsigned long dwCompSize;\n\tunsigned long dwUnCompSize;\n\tshort         wBitSize;\n\tshort\t\t\t    wChannels;\n\tunsigned long dwSampleIndex;\n\tlong          dwPredicted;\n\tlong          dwDifference;\n\tshort         wCodeBuf;\n\tshort         wCode;\n\tshort         wStep;\n\tshort         wIndex;\n\n\tunsigned long dwSampleIndex2; //added BP for channel 2\n\tlong          dwPredicted2;   //added BP for channel 2\n\tlong          dwDifference2; \t//added BP for channel 2\n\tshort         wCodeBuf2; \t\t//added BP for channel 2\n\tshort         wCode2; \t\t\t//added BP for channel 2\n\tshort         wStep2; \t\t\t//added BP for channel 2\n\tshort         wIndex2; \t\t\t//added BP for channel 2\n\t} _SOS_COMPRESS_INFO;\n\n/* compressed file type header */\ntypedef struct _tagCOMPRESS_HEADER {\n\tunsigned long dwType;              // type of compression\n\tunsigned long dwCompressedSize;    // compressed file size\n\tunsigned long dwUnCompressedSize;  // uncompressed file size\n\tunsigned long dwSourceBitSize;     // original bit size\n\tchar          szName[16];          // file type, for error checking\n\t} _SOS_COMPRESS_HEADER;\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid __cdecl VQA_sosCODECInitStream(_SOS_COMPRESS_INFO *);\nunsigned long __cdecl VQA_sosCODECCompressData(_SOS_COMPRESS_INFO *,unsigned long);\nunsigned long __cdecl VQA_sosCODECDecompressData(_SOS_COMPRESS_INFO *,unsigned long);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n\n"
  },
  {
    "path": "WINVQ/VQM32/TARGA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     targa.c\n* \n* DESCRIPTION\n*     Targa Image File reader. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     OpenTarga  - Open Targa image file.\n*     CloseTarga - Close Targa image file.\n*     LoadTarga  - Load Targa image file.\n*     XFlipTarga - X flip the image.\n*     YFlipTarga - Y flip the image.\n*\n* PRIVATE\n*     DecodeImageData - Decompress Targa image data.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <malloc.h>\n#include <mem.h>\n#include <io.h>\n#include <fcntl.h>\n#include <sys\\stat.h>\n#include \"targa.h\"\n\n/* Private data declerations. */\nstatic long DecodeImageData(TGAHandle *, char *);\nstatic void InvertImageData(TGAHeader *, char *);\n\n/****************************************************************************\n*\n* NAME\n*     OpenTarga - Open Targa image file.\n*\n* SYNOPSIS\n*     TGAHandle = OpenTarga(Name, Mode)\n*\n*     TGAHandle *OpenTarga(char *, unsigned short);\n*\n* FUNCTION\n*     Open a Targa image file and read in its header. The file stream will\n*     positioned after the ID field (if there is one).\n*\n* INPUTS\n*     Name - Pointer to name of Targa file.\n*     Mode - Access mode.\n*\n* RESULT\n*     TGAHandle - Pointer to initialized TGAHandle or NULL if error.\n*\n****************************************************************************/\n\nTGAHandle *OpenTarga(char *name, unsigned short mode)\n{\n\tTGAHandle *tga;\n\tlong       size;\n\tlong       error = 0;\n\n\t/* Allocate TGAHandle */\n\tif ((tga = (TGAHandle *)malloc(sizeof(TGAHandle))) != NULL) {\n\n\t\t/* Initialize TGAHandle structure. */\n\t\tmemset((void *)tga, 0, sizeof(TGAHandle));\n\t\ttga->mode = mode;\n\n\t\tswitch (mode) {\n\n\t\t\t/* Open targa file for read. */\n\t\t\tcase TGA_READMODE:\n\t\t\t\tif ((tga->fh = open(name, (O_RDONLY|O_BINARY))) != -1) {\n\n\t\t\t\t\t/* Read in header. */\n\t\t\t\t\tsize = read(tga->fh, &tga->header, sizeof(TGAHeader));\n\n\t\t\t\t\tif (size != sizeof(TGAHeader)) {\n\t\t\t\t\t\terror = 1;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Skip the ID field */\n\t\t\t\t\tif (!error && (tga->header.IDLength != 0)) {\n\t\t\t\t\t\tif (lseek(tga->fh, tga->header.IDLength, SEEK_CUR) == -1) {\n\t\t\t\t\t\t\terror = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\terror = 1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Open targa file for write. */\n\t\t\tcase TGA_WRITEMODE:\n\t\t\t\tif ((tga->fh = open(name, (O_CREAT|O_TRUNC|O_WRONLY|O_BINARY),\n\t\t\t\t\t\t(S_IREAD|S_IWRITE))) == -1) {\n\n\t\t\t\t\terror = 1;\n\t\t\t\t} else {\n\t\t\t\t\tprintf(\"\\r\");\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Open targa file for read/write.*/\n\t\t\tcase TGA_RDWRMODE:\n\t\t\t\tif ((tga->fh = open(name, (O_RDWR|O_BINARY),\n\t\t\t\t\t\t(S_IREAD|S_IWRITE))) != -1) {\n\n\t\t\t\t\t/* Read in header. */\n\t\t\t\t\tsize = read(tga->fh, &tga->header, sizeof(TGAHeader));\n\n\t\t\t\t\tif (size != sizeof(TGAHeader)) {\n\t\t\t\t\t\terror = 1;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Skip the ID field */\n\t\t\t\t\tif (!error && (tga->header.IDLength != 0)) {\n\t\t\t\t\t\tif (lseek(tga->fh, tga->header.IDLength, SEEK_CUR) == -1) {\n\t\t\t\t\t\t\terror = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\terror = 1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n \n\t\t/* Close on any error! */\n\t\tif (error) {\n\t\t\tCloseTarga(tga);\n\t\t\ttga = NULL;\n\t\t}\n\t}\n\n\treturn (tga);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     CloseTarga - Close Targa image file.\n*\n* SYNOPSIS\n*     CloseTarga(TGAHandle)\n*\n*     void CloseTarga(TGAHandle *);\n*\n* FUNCTION\n*     Close the Targa image file and free its handle.\n*\n* INPUTS\n*     TGAHandle - Pointer to TGAHandle returned by OpenTarga().\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid CloseTarga(TGAHandle *tga)\n{\n\t/* Ensure valid handle. */\n\tif (tga) {\n\n\t\t/* Close the file if it is open. */\n\t\tif (tga->fh != -1) close(tga->fh);\n\n\t\t/* Free TGAHandle */\n\t\tfree(tga);\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     LoadTarga - Load Targa Image File.\n*\n* SYNOPSIS\n*     Error = LoadTarga(Name, Palette, ImageBuffer)\n*\n*     long LoadTarga(char *, char *, char *);\n*\n* FUNCTION\n*     Open and load the Targa into the specified buffers. If either buffer\n*     pointer is NULL then that field will not be processed.\n*\n* INPUTS\n*     Name        - Name of Targa image file to load.\n*     Palette     - Pointer to buffer to load the palette into.\n*     ImageBuffer - Pointer to buffer to load the image data into.\n*\n* RESULT\n*     Error - 0 if successful, or TGAERR_??? error code.\n*\n****************************************************************************/\n\nlong LoadTarga(char *name, char *palette, char *image)\n{\n\tTGAHandle *tga;\n\tlong       size;\n\tlong       depth;\n\tlong       i,n;\n\tchar       c;\n\tlong       error = 0;\n\n\t/* Open the Targa */\n\tif ((tga = OpenTarga(name, TGA_READMODE)) != NULL) {\n\n\t\t/* Process ColorMap (palette) */\n\t\tif (tga->header.ColorMapType == 1) {\n\t\t\tdepth = (tga->header.CMapDepth >> 3);\n\t\t\tsize = (tga->header.CMapLength * depth);\n\n\t\t\t/* Load the palette from the TGA if a palette buffer is provided\n\t\t\t * otherwise we will skip it.\n\t\t\t */\n\t\t\tif ((palette != NULL) && (tga->header.CMapLength > 0)) {\n\n\t\t\t\t/* Adjust palette to the starting color entry. */\n\t\t\t\tpalette += (tga->header.CMapStart * depth);\n\n\t\t\t\t/* Read in the palette. */\n\t\t\t\tif (read(tga->fh, palette, size) == size) {\n\n\t\t\t\t\t/* Swap the byte ordering of the palette entries. */\n\t\t\t\t\tfor (i = 0; i < tga->header.CMapLength; i++) {\n\t\t\t\t\t\t#if(0)\n\t\t\t\t\t\tfor (n = 0; n < depth; n++) {\n\t\t\t\t\t\t\tc = *(palette + n);\n\t\t\t\t\t\t\t*(palette + n) = *(palette + ((depth - 1) - n));\n\t\t\t\t\t\t\t*(palette + ((depth - 1) - n)) = c;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t#else\n\t\t\t\t\t\tc = *palette;\n\t\t\t\t\t\t*palette = *(palette + (depth - 1));\n\t\t\t\t\t\t*(palette + (depth - 1)) = c;\n\t\t\t\t\t\t#endif\n\n\t\t\t\t\t\t/* Next entry */\n\t\t\t\t\t\tpalette += depth;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\terror = TGAERR_READ;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (lseek(tga->fh, size, SEEK_CUR) == -1) {\n\t\t\t\t\terror = TGAERR_READ;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Load the image data from the TGA if an image buffer is provided\n\t\t * otherwise we are done.\n\t\t */\n\t\tif (!error && (image != NULL)) {\n\t\t\tdepth = (tga->header.PixelDepth >> 3);\n\t\t\tsize = ((tga->header.Width * tga->header.Height) * depth);\n\n\t\t\tswitch (tga->header.ImageType) {\n\t\t\t\tcase TGA_CMAPPED:\n\t\t\t\t\tif (read(tga->fh, image, size) != size) {\n\t\t\t\t\t\terror = TGAERR_READ;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TGA_TRUECOLOR:\n\t\t\t\t\tif (read(tga->fh, image, size) == size) {\n\t\t\t\t\t\tInvertImageData(&tga->header, image);\n\t\t\t\t\t} else {\n\t\t\t\t\t\terror = TGAERR_READ;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TGA_CMAPPED_ENCODED:\n\t\t\t\t\terror = DecodeImageData(tga, image);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TGA_TRUECOLOR_ENCODED:\n\t\t\t\t\tif ((error = DecodeImageData(tga, image)) == NULL) {\n\t\t\t\t\t\tInvertImageData(&tga->header, image);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\terror = TGAERR_NOTSUPPORTED;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/* Arrange the image so that the origin position (coordinate 0,0)\n\t\t\t * is the upperleft hand corner of the image.\n\t\t\t */\n\t\t\tif (!error) {\n\t\t\t\tif (tga->header.ImageDescriptor & TGAF_XORIGIN) {\n\t\t\t\t\tXFlipTarga(&tga->header, image);\n\t\t\t\t}\n\n\t\t\t\tif ((tga->header.ImageDescriptor & TGAF_YORIGIN) == 0) {\n\t\t\t\t\tYFlipTarga(&tga->header, image);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Close the Targa */\n\t\tCloseTarga(tga);\n\t} else {\n\t\terror = TGAERR_OPEN;\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     SaveTarga - Save a Targa Image File.\n*\n* SYNOPSIS\n*     Error = SaveTarga(Name, TGAHeader, Palette, ImageBuffer)\n*\n*     long SaveTarga(char *, TGAHeader *, char *, char *);\n*\n* FUNCTION\n*\n* INPUTS\n*     Name        - Pointer to name of file to save.\n*     TGAHeader   - Pointer to initialized targa header structure.\n*     Palette     - Pointer to palette.\n*     ImageBuffer - Pointer to raw image data.\n*\n* RESULT\n*     Error - 0 if successful, or TGAERR_??? error code.\n*\n****************************************************************************/\n\nlong SaveTarga(char *name, TGAHeader *tgahd, char *palette, char *image)\n{\n\tTGAHandle *tga;\n\tlong       size;\n\tlong       depth;\n\tchar      *temppal;\n\tchar      *ptr;\n\tlong       i,n;\n\tchar       c;\n\tlong       error = 0;\n\n\t/* Open the Targa for write. */\n\tif ((tga = OpenTarga(name, TGA_WRITEMODE)) != NULL) {\n\n\t\t/* Write the header. */\n\t\tif (write(tga->fh, tgahd, sizeof(TGAHeader)) != sizeof(TGAHeader)) {\n\t\t\terror = TGAERR_WRITE;\n\t\t}\n\n\t\t/* Write the palette. */\n\t\tif (!error && (palette != NULL) && (tgahd->CMapLength > 0)) {\n\n\t\t\t/* Adjust palette to the starting color entry. */\n\t\t\tdepth = (tgahd->CMapDepth >> 3);\n\t\t\tpalette += (tgahd->CMapStart * depth);\n\t\t\tsize = (tgahd->CMapLength * depth);\n\n\t\t\t/* Allocate temporary buffer for palette manipulation. */\n\t\t\tif ((temppal = (char *)malloc(size)) != NULL) {\n\t\t\t\tmemcpy(temppal, palette, size);\n\t\t\t\tptr = temppal;\n\n\t\t\t\t/* Swap the byte ordering of the palette entries. */\n\t\t\t\tfor (i = 0; i < tga->header.CMapLength; i++) {\n\t\t\t\t\tfor (n = 0; n < (depth >> 1); n++) {\n\t\t\t\t\t\tc = *(ptr + n);\n\t\t\t\t\t\t*(ptr + n) = *(ptr + (depth - n));\n\t\t\t\t\t\t*(ptr + (depth - n)) = c;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Next entry */\n\t\t\t\t\tpalette += depth;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Write the palette. */\n\t\t\t\tif (write(tga->fh, temppal, size) != size) {\n\t\t\t\t\terror = TGAERR_WRITE;\n\t\t\t\t}\n\n\t\t\t\t/* Free temporary palette buffer. */\n\t\t\t\tfree(temppal);\n\t\t\t} else {\n\t\t\t\terror = TGAERR_NOMEM;\n\t\t\t}\n\t\t}\n\n\t\t/* Invert truecolor data. */\n\t\tif (tgahd->ImageType == TGA_TRUECOLOR) {\n\t\t\tInvertImageData(tgahd, image);\n\t\t}\n\n\t\t/* Write the image. */\n\t\tif (!error && (image != NULL)) {\n\t\t\tdepth = (tgahd->PixelDepth >> 3);\n\t\t\tsize = (((tgahd->Width * tgahd->Height)) * depth);\n\n\t\t\tif (write(tga->fh, image, size) != size) {\n\t\t\t\terror = TGAERR_WRITE;\n\t\t\t}\n\t\t}\n\n\t\t/* Close targa file. */\n\t\tCloseTarga(tga);\n\t} else {\n\t\terror = TGAERR_OPEN;\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     XFlipTarga - X flip the image.\n*\n* SYNOPSIS\n*     XFlipTarga(TGAHeader, Image)\n*\n*     void XFlipTarga(TGAHeader *, char *);\n*\n* FUNCTION\n*     Flip the image in memory on its X axis. (left to right)\n*\n* INPUTS\n*     TGAHeader - Pointer to initialized TGAHeader structure.\n*     Image     - Pointer to image buffer.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid XFlipTarga(TGAHeader *tga, char *image)\n{\n\tchar *ptr,*ptr1;\n\tlong  x,y,d;\n\tchar  v,v1;\n\tchar  depth;\n\n\t/* Pixel depth in bytes. */\n\tdepth = (tga->PixelDepth >> 3);\n\n\tfor (y = 0; y < tga->Height; y++) {\n\t\tptr = (image + ((tga->Width * depth) * y));\n\t\tptr1 = (ptr + ((tga->Width * depth) - depth));\n\n\t\tfor (x = 0; x < (tga->Width / 2); x++) {\n\t\t\tfor (d = 0; d < depth; d++) {\n\t\t\t\tv = *(ptr + d);\n\t\t\t\tv1 = *(ptr1 + d);\n\t\t\t\t*(ptr + d) = v1;\n\t\t\t\t*(ptr1 + d) = v;\n\t\t\t}\n\n\t\t\tptr += depth;\n\t\t\tptr1 -= depth;\n\t\t}\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     YFlipTarga - Y flip the image.\n*\n* SYNOPSIS\n*     YFlipTarga(TGAHeader, Image)\n*\n*     void YFlipTarga(TGAHeader *, char *);\n*\n* FUNCTION\n*     Flip the image in memory on its Y axis. (top to bottom)\n*\n* INPUTS\n*     TGAHeader - Pointer to initialized TGAHeader structure.\n*     Image     - Pointer to image buffer.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid YFlipTarga(TGAHeader *tga, char *image)\n{\n\tchar *ptr,*ptr1;\n\tlong  x,y;\n\tchar  v,v1;\n\tchar  depth;\n\n\t/* Pixel depth in bytes. */\n\tdepth = (tga->PixelDepth >> 3);\n\n\tfor (y = 0; y < (tga->Height >> 1); y++) {\n\n\t\t/* Compute address of lines to exchange. */\n\t\tptr = (image + ((tga->Width * y) * depth));\n\t\tptr1 = (image + ((tga->Width * (tga->Height - 1)) * depth));\n\t\tptr1 -= ((tga->Width * y) * depth);\n\n\t\t/* Exchange all the pixels on this scan line. */\n\t\tfor (x = 0; x < (tga->Width * depth); x++) {\n\t\t\tv = *ptr;\n\t\t\tv1 = *ptr1;\n\t\t\t*ptr = v1;\n\t\t\t*ptr1 = v;\n\t\t\tptr++;\n\t\t\tptr1++;\n\t\t}\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     DecodeImageData - Decompress Targa image data.\n*\n* SYNOPSIS\n*     Error = DecodeImageData(TGAHandle, ImageBuffer)\n*\n*     long DecodeImageData(TGAHandle *, char *);\n*\n* FUNCTION\n*     Decode the RLE compressed image data into the specified buffer from\n*     the file I/O stream.\n*\n* INPUTS\n*     TGAHandle   - Pointer to TGAHandle returned by OpenTarga().\n*     ImageBuffer - Pointer to buffer to decompress image into.\n*\n* RESULT\n*     Error - 0 if successful, or TGAERR_??? error code.\n*\n****************************************************************************/\n\nstatic long DecodeImageData(TGAHandle *tga, char *image)\n{\n\tchar          *packet;\n\tunsigned char  count;\n\tunsigned char  depth;\n\tunsigned long  pixel_count;\n\tunsigned long  size;\n\tunsigned long  c,i;\n\tlong           error = 0;\n\n\t/* Compute pixel depth in bytes. */\n\tdepth = (tga->header.PixelDepth >> 3);\n\n\t/* Total number of pixels compressed in this image. */\n\tpixel_count = (tga->header.Width * tga->header.Height);\n\n\t/* Allocate packet buffer to hold maximum encoded data run. */\n\tif ((packet = (char *)malloc(128 * depth)) != NULL) {\n\t\twhile ((pixel_count > 0) && !error) {\n\n\t\t\t/* Read count. */\n\t\t\tif (read(tga->fh, &count, 1) == 1) {\n\n\t\t\t\t/* If bit 8 of the count is set then we have a run of pixels,\n\t\t\t\t * otherwise the data is raw pixels.\n\t\t\t\t */\n\t\t\t\tif (count & 0x80) {\n\t\t\t\t\tcount &= 0x7F;\n\t\t\t\t\tcount++;\n\n\t\t\t\t\t/* Read in run pixel. */\n\t\t\t\t\tif (read(tga->fh, packet, depth) == depth) {\n\n\t\t\t\t\t\t/* Repeat the pixel for the run count in the image buffer. */\n\t\t\t\t\t\tfor (c = 0; c < count; c++) {\n\t\t\t\t\t\t\tfor (i = 0; i < depth; i++) {\n\t\t\t\t\t\t\t\t*image++ = *(packet + i);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\terror = TGAERR_READ;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tcount++;\n\t\t\t\t\tsize = (count * depth);\n\n\t\t\t\t\t/* Read in raw pixels. */\n\t\t\t\t\tif (read(tga->fh, packet, size) == size) {\n\n\t\t\t\t\t\t/* Copy the raw pixel data into the image buffer. */\n\t\t\t\t\t\tmemcpy(image, packet, size);\n\t\t\t\t\t\timage += size;\n\t\t\t\t\t} else {\n\t\t\t\t\t\terror = TGAERR_READ;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* Adjust the pixel count. */\n\t\t\t\tpixel_count -= count;\n\t\t\t} else {\n\t\t\t\terror = TGAERR_READ;\n\t\t\t}\n\t\t}\n\n\t\t/* Free packet buffer. */\n\t\tfree(packet);\n\t} else {\n\t\terror = TGAERR_NOMEM;\n\t}\n\n\treturn (error);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     InvertImageData - Invert TrueColor image data.\n*\n* SYNOPSIS\n*     InvertImageData(TGAHeader, ImageData)\n*\n*     void InvertImageData(TGAHeader *, char *);\n*\n* FUNCTION\n*\n* INPUTS\n*     TGAHeader - Pointer to initialized TGAHeader structure.\n*     ImageData - Pointer to TrueColor image data.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nstatic void InvertImageData(TGAHeader *tga, char *image)\n{\n\tlong depth;\n\tlong pixel_count;\n\tlong i;\n\tchar c;\n\n\t/* Compute the pixel depth in bytes. */\n\tdepth = (tga->PixelDepth >> 3);\n\n\t/* Total number of pixels in this image. */\n\tpixel_count = (tga->Width * tga->Height);\n\n\t/* 16-bit pixel layout is different that 24-bit and 32-bit. */\n\tif (depth > 2) {\n\t\twhile (pixel_count > 0) {\n\t\t\tfor (i = 0; i < (depth / 2); i++) {\n\t\t\t\tc = *(image + i);\n\t\t\t\t*(image + i) = *(image + ((depth - 1) - i));\n\t\t\t\t*(image + ((depth - 1) - i)) = c;\n\t\t\t}\n\n\t\t\t/* Next pixel */\n\t\t\tpixel_count--;\n\t\t\timage += depth;\n\t\t}\n\t} else {\n\t}\n}\n\n\n"
  },
  {
    "path": "WINVQ/VQM32/TARGA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMTARGA_H\n#define VQMTARGA_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Targa.h (32-Bit protected mode)\n* \n* DESCRIPTION\n*     Targa Image File definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n****************************************************************************/\n\n/*---------------------------------------------------------------------------\n * Targa Header definitions\n *-------------------------------------------------------------------------*/\n\n/* TGAHeader - Targa Image File header.\n *\n * IDLength        - Size of Image ID field\n * ColorMapType    - Color map type.\n * ImageType       - Image type code.\n * CMapStart       - Color map origin.\n * CMapLength      - Color map length.\n * CMapDepth       - Depth of color map entries.\n * XOffset         - X origin of image.\n * YOffset         - Y origin of image.\n * Width           - Width of image.\n * Height          - Height of image.\n * PixelDepth      - Image pixel size\n * ImageDescriptor - Image descriptor byte.\n */\ntypedef struct _TGAHeader {\n\tchar  IDLength;\n\tchar  ColorMapType;\n\tchar  ImageType;\n\tshort CMapStart;\n\tshort CMapLength;\n\tchar  CMapDepth;\n\tshort XOffset;\n\tshort YOffset;\n\tshort Width;\n\tshort Height;\n\tchar  PixelDepth;\n\tchar  ImageDescriptor;\n} TGAHeader;\n\n/* ImageType definiton */\n#define TGA_NOIMAGE           0  /* No image data included in file */\n#define TGA_CMAPPED           1  /* Color-mapped image data */\n#define TGA_TRUECOLOR         2  /* Truecolor image data */\n#define TGA_MONO              3  /* Monochrome image data */\n#define TGA_CMAPPED_ENCODED   9  /* Color-mapped image data (Encoded) */\n#define TGA_TRUECOLOR_ENCODED 10 /* Truecolor image data (Encoded) */\n#define TGA_MONO_ENCODED      11 /* Monochrome image data (Encoded) */\n\n/* ImageDescriptor definition */\n#define TGAF_ATTRIB_BITS (0x0F<<0) /* Number of attribute bits per pixel */\n#define TGAF_XORIGIN     (1<<4)\n#define TGAF_YORIGIN     (1<<5)\n\n/*---------------------------------------------------------------------------\n * Targa Handle definitions\n *-------------------------------------------------------------------------*/\n\n/* TGAHandle - Targa Image File handle.\n *\n * fh     - File handle returned by open().\n * mode   - Access mode.\n * header - TGAHeader structure.\n */\ntypedef struct _TGAHandle {\n\tshort          fh;\n\tunsigned short mode;\n\tTGAHeader      header;\n} TGAHandle;\n\n/* Access modes. */\n#define TGA_READMODE  0\n#define TGA_WRITEMODE 1\n#define TGA_RDWRMODE  2\n\n/* Error codes */\n#define TGAERR_OPEN         -1\n#define TGAERR_READ         -2\n#define TGAERR_WRITE        -3\n#define TGAERR_SYNTAX       -4\n#define TGAERR_NOMEM        -5\n#define TGAERR_NOTSUPPORTED -6\n \n/*---------------------------------------------------------------------------\n * Function prototypes\n *-------------------------------------------------------------------------*/\n\nTGAHandle *OpenTarga(char *, unsigned short);\nvoid CloseTarga(TGAHandle *);\nlong LoadTarga(char *, char *, char *);\nlong SaveTarga(char *, TGAHeader *, char *, char *);\nvoid XFlipTarga(TGAHeader *, char *);\nvoid YFlipTarga(TGAHeader *, char *);\n\n#endif /* VQMTARGA_H */\n\n"
  },
  {
    "path": "WINVQ/VQM32/TASM32.CFG",
    "content": "/t\n/m\n/w+\n/jJUMPS\n/ml\n/p\n/z\n/iC:\\PROJECTS\\INCLUDE\n/zi\n/dPHARLAP_TNT=1\n"
  },
  {
    "path": "WINVQ/VQM32/TESTVB.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     testvb.c\n*\n* DESCRIPTION\n*     Video mode setting. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     TestVBIBit     - Test the polarity of the vertical blank bit.\n*\n****************************************************************************/\n\n#include <sys\\timeb.h>\n\n#ifdef __BORLANDC__\n#include \"portio.h\"\n#else\n#include <conio.h>\n#endif\n\n/****************************************************************************\n*\n* NAME\n*     TestVBIBit - Test the polarity of the vertical blank bit.\n*\n* SYNOPSIS\n*     Polarity = TestVBIBit()\n*\n*     long TestVBIBit(void);\n*\n* FUNCTION\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Polarity - Polarity of the vertical blank bit.\n*\n****************************************************************************/\n\nlong TestVBIBit(void)\n{\n\tstatic struct timeb mytime;\n\tlong          curtime;\n\tlong          endtime;\n\tunsigned long high = 0;\n\tunsigned long low = 0;\n\n\t/* Set the check time for .25 (1/4) of a second. */\n\tftime(&mytime);\n\tcurtime = ((mytime.time * 1000) + mytime.millitm);\n\tendtime = (curtime + (1000 / 4));\n\n\t/* Sample the vertical blank bit for the specified period of time.\n\t * The state in which it is in the least is the vertical blank state,\n\t * the state in which it is in the most is the active scan state.\n\t */\n\twhile (endtime >= curtime) {\n\t\tftime(&mytime);\n\t\tcurtime = ((mytime.time * 1000) + mytime.millitm);\n\n\t\tif (inp(0x3DA) & 0x08) {\n\t\t\thigh++;\n\t\t} else {\n\t\t\tlow++;\n\t\t}\n\t}\n\n\treturn (high > low);\n}\n\n\n\n"
  },
  {
    "path": "WINVQ/VQM32/TEXT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMTEXT_H\n#define VQMTEXT_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     text.h\n*\n* DESCRIPTION\n*     Text printing definitions. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     March 13, 1995\n*\n****************************************************************************/\n\n/* Prototypes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nlong __cdecl Text_Print(char *string, long x, long y, long fcol, long bcol);\nvoid __cdecl Draw_Char(long character, long x, long y);\nvoid __cdecl Set_Font_Palette_Range(void *palette, long start, long end);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMTEXT_H */\n\n"
  },
  {
    "path": "WINVQ/VQM32/TEXTPRNT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header:   J:\\vq\\projects\\vqm32\\textprnt.asv   1.5   27 Jul 1995 13:57:04   DENZIL_LONG  $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : TEXTPRNT.ASM                             *\n;*                                                                         *\n;*                   Programmer : David R. Dettmer                         *\n;*                                                                         *\n;*                   Start Date : January 28, 1992                         *\n;*                                                                         *\n;*                  Last Update : February 3, 1992   [DRD]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n;  VOID Text_Print(BYTE *string, WORD x_pixel, WORD y_pixel,               *\n;                  WORD fcolor,  WORD bcolor);                             *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\nXPIXEL_MAX    EQU\t320\nYPIXEL_MAX\tEQU\t200\n\nFONTINFOBLOCK\t\tEQU\t4\nFONTOFFSETBLOCK\tEQU\t6\nFONTWIDTHBLOCK\tEQU\t8\nFONTDATABLOCK\t\tEQU\t10\nFONTHEIGHTBLOCK\tEQU\t12\n\nFONTINFOMAXHEIGHT\tEQU\t4\nFONTINFOMAXWIDTH\tEQU\t5\n\n\tEXTRN\tC Char_Pixel_Width:NEAR\n\tEXTRN\tC Draw_Char:NEAR\n\tEXTRN\tC Set_Font_Palette_Range:NEAR\n\tEXTRN\tFontPtr:NEAR PTR\n\tEXTRN\tFontYSpacing:DWORD\n\t\n;----------------------------------------------------------------------------\n; TEXT_PRINT\n;\n; VOID Text_Print(BYTE *string, WORD x_pixel, WORD y_pixel,\n;\t\t  WORD fcolor,  WORD bcolor);\n;\n; Print the given string to the LogicPage.\n;\n; Bounds Checking:\n;\n; if x_pixel < 0, then x_pixel = 0\n; if x_pixel >= XPIXEL_MAX, then exit\n; if y_pixel < 0, then y_pixel = 0\n; if y_pixel >= YPIXEL_MAX, then exit\n;*\n\n\tGLOBAL\tC Text_Print:NEAR\n\tPROC\tText_Print C NEAR USES ebx ecx edx edi esi\n\tARG\tstring:NEAR PTR\n\tARG\tx_pixel:DWORD\n\tARG\ty_pixel:DWORD\n\tARG\tfcol:DWORD\n\tARG\tbcol:DWORD\n\n\tLOCAL\tfwidth:DWORD\t;Pixel width of font.\n\tLOCAL\tfgbg:DWORD\t;Two bytes of background & foreground colors.\n\tLOCAL\tlines:DWORD\t;Number of lines\n\tLOCAL\tfontheight:DWORD\n\n\t; Make sure there is a font available. If not, then bail.\n\n\txor\teax,eax\n\tmov\t[lines],eax\n\n\tmov\teax,[FontPtr]\n\tor\teax,eax\n\tje\t??exit\n\n\tmovzx\tebx,[WORD PTR eax+FONTINFOBLOCK]\n\tadd\tebx,eax\n\tmovzx\teax,[BYTE PTR ebx+FONTINFOMAXHEIGHT]\n\tmov\t[fontheight],eax\n\tmov\tesi,[string]\n\n\tmov\tebx,[x_pixel]\t\t; x pixel\n\tcmp\tebx,XPIXEL_MAX\t\t; check max x pos\n\tjae\tshort ??exit\n\n\tmov\tecx,[y_pixel]\t\t; y pixel\n\tcmp\tecx,YPIXEL_MAX\t\t; check max y pos\n\tjge\tshort ??exit\n\n\tmov\tal,[BYTE PTR bcol]\n\tmov\tah,[BYTE PTR fcol]\n\tmov\t[fgbg],eax\n\tlea\teax,[fgbg]\n\tcall\tSet_Font_Palette_Range C,eax,0,1\n\n; start of loop to print string\n\n\txor\tedx,edx\n\tinc\t[lines]\n??loop:\n\tmov\tdl,[esi]\n\tinc\tesi\n\n\tcmp\tedx,0\t\t\t; end of string\n\tje\tshort ??exit\n\n\tcmp\tedx,13\t\t\t; cmp to a '\\r'\n\tjne\tshort ??chkxy\n\n\t; Advance the screen to the left edge and down one line. Check\n\t; to see if the coordinate would still be visible. If not, then\n\t; bail.\n\n??onelinedown:\n \tmov\tebx,[x_pixel]\t\t; get original x position\n\tadd\tecx,[fontheight]\n\tadd\tecx,[FontYSpacing]\n\tcmp\tecx,YPIXEL_MAX\t  \t; check y pos\n\tjae\tshort ??exit\n\tinc\t[lines]\n\tjmp\t??loop\n\n??chkxy:\n\tcall\tChar_Pixel_Width C,edx\n\n\t; Check to see if this character would spill past the right edge\n\t; of the screen. If it would then drop down a line.\n\n\tmov\t[fwidth],eax\t\t; save width of char for later\n\tadd\teax,ebx\n\n\tcmp\teax,XPIXEL_MAX\t\t; check x pos\n\tja\tshort ??onelinedown\n\n\tcall\tDraw_Char C,edx,ebx,ecx\n\n\tadd\tebx,[fwidth]\t\t; add font width\n\tjmp\t??loop\n\n\t; Exit routine and unlock string if it was in EMS.\n\n??exit:\n\tmov\teax,[lines]\n\tret\n\n\tENDP\tText_Print\n\n;----------------------------------------------------------------------------\n\tEND\n\n"
  },
  {
    "path": "WINVQ/VQM32/TLIB.CFG",
    "content": "/C /E\n"
  },
  {
    "path": "WINVQ/VQM32/TLINK32.CFG",
    "content": "/c\n/m\n/Gm\n-LC:\\PROJECTS\\LIB;C:\\DEV\\BC4\\LIB\n-v\n"
  },
  {
    "path": "WINVQ/VQM32/VB.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     vb.asm\n;*\n;* DESCRIPTION\n;*     Vertical blank routines. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     WaitNoVB - Wait for active scan.\n;*     WaitVB   - Wait for vertical blank.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"video.i\"\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     WaitNoVB - Wait for active scan.\n;*\n;* SYNOPSIS\n;*     WaitNoVB()\n;*\n;*     void WaitNoVB(void);\n;*\n;* FUNCTION\n;*     Sit and wait for the active scan of the display.\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC WaitNoVB:NEAR\n\tPROC\tWaitNoVB C NEAR USES edx\n\tARG\tvbibit:DWORD\n\n\tmov\teax,[vbibit]\n\tand\tal,1\n\tshl\tal,3\n\tmov\tah,al\n\n;\tloop while VBL bit != VQ_VertBlank\n\n??no_scan_yet:\n\tmov\tedx,03DAH\n\tin\tal,dx\n\tand\tal,8\n\txor\tal,ah\n\tjnz\tshort ??no_scan_yet\n\tret\n\n\tENDP\tWaitNoVB\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     WaitVB - Wait for vertical blank.\n;*\n;* SYNOPSIS\n;*     WaitVB()\n;*\n;*     void WaitVB(void);\n;*\n;* FUNCTION\n;*     Sit and wait for the vertical blank of the display.\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC WaitVB:NEAR\n\tPROC\tWaitVB C NEAR USES\n\tARG\tvbibit:DWORD\n\n\tmov\teax,[vbibit]\n\tand\tal,1\n\tshl\tal,3\n\tmov\tah,al\n\n;\tLoop while VBL bit = VQ_VertBlank\n\n??no_vbl_yet:\n\tmov\tedx,03DAH\n\tin\tal,dx\n\tand\tal,8\n\txor\tal,ah\n\tjz\tshort ??no_vbl_yet\n\tret\n\n\tENDP\tWaitVB\n\n\tEND\n"
  },
  {
    "path": "WINVQ/VQM32/VERTAG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*       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\n*\n*----------------------------------------------------------------------------\n*\n* PROJECT\n*     VQMisc32 library.\n*\n* FILE\n*     vertag.c (32-Bit protected mode)\n*\n* DESCRIPTION\n*     Embedded version string. This string is prefixed with a tag (\"$VER$\")\n*     which can be search for to find this string.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*      \n* DATE\n*     Febuary 8, 1995\n*\n****************************************************************************/\n\n#ifdef __WATCOMC__\n#define DEVNAME \"Watcom/4GW\"\n#else\n#define DEVNAME \"Borland/TNT\"\n#endif\n\nchar VerTag[] = {\"$VER$VQM32 2.12 \"DEVNAME\" (\"__DATE__\" \"__TIME__\")\"};\n"
  },
  {
    "path": "WINVQ/VQM32/VESABLIT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     vesablit.c\n*\n* DESCRIPTION\n*     VESA bitblit routines. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     VESA_Blit_640x480 - Blit to 640x480 256 color VESA mode.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <mem.h>\n#include <dos.h>\n#include \"video.h\"\n#include \"vesavid.h\"\n#include \"vesablit.h\"\n\n\n/****************************************************************************\n*\n* NAME\n*     VESA_Blit_640x480 - Blit to 640x480 256 color VESA mode.\n*\n* SYNOPSIS\n*     VESA_Blit_640x480(DisplayInfo, Buffer, X, Y, Width, Height)\n*\n*     void VESA_Blit_640x480(DisplayInfo *, char *, long, long, long, long);\n*\n* FUNCTION\n*\n* INPUTS\n*     DisplayInfo - Pointer to display information structure.\n*     Buffer      - Pointer to buffer to blit to VRAM.\n*     X           - Destination X coordinate of blit (upper left).\n*     Y           - Destination Y coordinate of blit (upper left).\n*     Width       - Width of blit.\n*     Height      - Height of blit.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid VESA_Blit_640x480(DisplayInfo *disp,unsigned char *buf,long x1,long y1,\n\t\tlong width,long height)\n{\n\tVESAModeInfo *vminfo;\n\tlong         bank;\n\tlong         last_bank;\n\tlong         bank_offset;\n\tlong         scrn_offset;\n\tlong         grains_per_win;\n\tlong         part1;\n\tlong         part2;\n\tlong         i;\n\n\t/* Initialize values */\n\tvminfo = (VESAModeInfo *)disp->Extended;\n\tscrn_offset = ((disp->XRes * y1) + x1);\n\tgrains_per_win = ((long)vminfo->WinSize / (long)vminfo->WinGranularity);\n\tbank_offset = scrn_offset % 65536L;\n\tlast_bank = -1;\n\n\tfor (i = 0; i < height; i++) {\n\n\t\t/* Compute which bank this scanline is in */\n\t\tbank = (scrn_offset / 65536L);\n\n\t\t/* Set a new bank */\n\t\tif (bank != last_bank) {\n\t\t\tSetVESAWindow(bank);\n\t\t\tlast_bank = bank;\n\t\t\tbank_offset = (scrn_offset % 65536L);\n\t\t}\n\n\t\t/* Copy a full scanline */\n\t\tif ((bank_offset + width) < 65536L) {\n\t\t\tCopy_Row((char *)buf, (char *)bank_offset, width);\n\t\t\tbuf += width;\n\t\t\tscrn_offset += disp->XRes;\n\t\t\tbank_offset += disp->XRes;\n\t\t}\n\n\t\t/* Copy two partial scanlines */\n\t\telse {\n\t\t\tpart1 = (65536L - bank_offset);\n\t\t\tpart2 = (width - part1);\n\t\t\tCopy_Row((char *)buf, (char *)bank_offset, part1);\n\n\t\t\tbuf += part1;\n\t\t\tbank += grains_per_win;\n\t\t\tlast_bank += grains_per_win;\n\t\t\tSetVESAWindow(bank);\n\t\t\tCopy_Row((char *)buf, (char *)0, part2);\n\n\t\t\tbuf += part2;\n\t\t\tscrn_offset += disp->XRes;\n\t\t\tbank_offset = (scrn_offset % 65536L);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "WINVQ/VQM32/VESABLIT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMVESABLIT_H\n#define VQMVESABLIT_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     VESABlit.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     VESA bitblit routines.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\video.h>\n\n/*---------------------------------------------------------------------------\n * FUNCTION PROTOTYPES\n *-------------------------------------------------------------------------*/\n\nvoid VESA_Blit_640x480(DisplayInfo *disp,unsigned char *buf,long x1,\n\t\tlong y1,long width,long height);\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid __cdecl Blit_VESA640x480(DisplayInfo *disp,unsigned char *buf,long x1,\n\t\tlong y1,long width,long height);\n\nvoid __cdecl Buf_320x200_To_VESA_320x200(unsigned char *buffer, long grain);\nvoid __cdecl Buf_320x200_To_VESA_640x400(unsigned char *buffer, long grain);\nvoid __cdecl Buf_320x200_To_VESA_32K(unsigned char *buffer,\n\t\tunsigned char *palette, long grain);\n\nvoid __cdecl Copy_Row(char *, char *, long);\nvoid __cdecl Copy_Word_Row(char *source, char *dest, char *palette,\n\t\tlong numbytes);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMVESABLIT_H */\n\n"
  },
  {
    "path": "WINVQ/VQM32/VESABUF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     vesabuf.asm\n;*\n;* DESCRIPTION\n;*     VESA buffered blit routines.  (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Bill Randolph\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     Febuary 3, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     Buf_320x200_To_VESA_320x200 - Buffer copy, unscaled\n;*     Buf_320x200_To_VESA_640x400 - Scales and copies 320x200 to 640x400\n;*     Buf_320x200_To_VESA_32K     - Copies 320x200 buffer to VESA 32K\n;*                                   colors\n;*     Copy_Row                    - Copy a row of pixels to VRAM.\n;*     Copy_Word_Row               - Copy a row of 15-bit pixels to VRAM\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"video.i\"\n\tCODESEG\n\n;---------------------------------------------------------------------------\n; DRAW_BLOCK_ROWS: draws 'numrows' rows of 2x2 blocks\n; Set ES:DI to current screen location\n; Set DS:SI to current source location\n; Uses: ax, cx, dx\n;---------------------------------------------------------------------------\n\tMACRO\tDRAW_BLOCK_ROWS numrows\n\tLOCAL\t??Start_row\n\tLOCAL\t??Not_finished_a_line\n\tLOCAL\t??Done\n\n\tmov\tedx,numrows\n??Start_row:\n\tmov\tecx,320\n\n??Not_finished_a_line:\n\tmov\tal,[BYTE PTR esi]\n\tmov\tah,al\n\tinc\tesi\n\n\tIF\tPHARLAP_TNT\n\tmov\t[WORD PTR es:edi],ax\n\tmov\t[WORD PTR es:edi+640],ax\n\tELSE\n\tmov\t[WORD PTR edi],ax\n\tmov\t[WORD PTR edi+640],ax\n\tENDIF\n\n\tadd\tedi,2\n\tdec\tecx\n\tjnz\t??Not_finished_a_line\n\n\tadd\tedi,640\n\tdec\tedx\n\tjz\t??Done\n\tjmp\t??Start_row\n\n??Done:\n\tENDM\n\n;---------------------------------------------------------------------------\n; DRAW_BLOCK_ROW: draws one row of 'numblks' 2x2 blocks\n; Set ES:DI to current screen location\n; Set DS:SI to current source location\n; Uses: ax, cx\n;---------------------------------------------------------------------------\n\tMACRO\tDRAW_BLOCK_ROW numblks\n\tLOCAL\t??Not_done\n\n\tmov\tecx,numblks\n\n??Not_done:\n\tmov\tal,[BYTE PTR esi]\n\tmov\tah,al\n\tinc\tesi\n\n\tIF\tPHARLAP_TNT\n\tmov\t[WORD PTR es:edi],ax\n\tmov\t[WORD PTR es:edi+640],ax\n\tELSE\n\tmov\t[WORD PTR edi],ax\n\tmov\t[WORD PTR edi+640],ax\n\tENDIF\n\n\tadd\tedi,2\n\tdec\tecx\n\tjnz\t??Not_done\n\n\tENDM\n\n;---------------------------------------------------------------------------\n; DRAW_PIXEL_ROW: draws 'numblks' 2x1 blocks\n; Set ES:DI to current screen location\n; Set DS:SI to current source location\n; Uses: ax, cx\n;---------------------------------------------------------------------------\n\tMACRO\tDRAW_PIXEL_ROW numblks\n\tLOCAL\t??Not_done\n\n\tmov\tecx,numblks\n\n??Not_done:\n\tmov\tal,[BYTE PTR esi]\n\tmov\tah,al\n\tinc\tesi\n\n\tIF\tPHARLAP_TNT\n\tmov\t[WORD PTR es:edi],ax\n\tELSE\n\tmov\t[WORD PTR edi],ax\n\tENDIF\n\n\tadd\tedi,2\n\tdec\tecx\n\tjnz\t??Not_done\n\n\tENDM\n\n;****************************************************************************\n;*\n;* NAME\n;*     Blit_VESA640x480 - Blit to 640x480 256 color VESA mode.\n;*\n;* SYNOPSIS\n;*     Blit_VESA640x480(DisplayInfo, Buffer, X, Y, Width, Height)\n;*\n;*     void Blit_VESA640x480(DisplayInfo *, char *, long, long, long, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     DisplayInfo - Pointer to display information structure.\n;*     Buffer      - Pointer to buffer to blit to VRAM.\n;*     X           - Destination X coordinate of blit (upper left).\n;*     Y           - Destination Y coordinate of blit (upper left).\n;*     Width       - Width of blit.\n;*     Height      - Height of blit.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n;\tGLOBAL\tC Blit_VESA640x480:NEAR\n;\tPROC\tBlit_VESA640x480 C NEAR USES\n;\n;\tARG\tdisp:NEAR PTR DisplayInfo\n;\tARG\tbuffer:NEAR PTR\n;\tARG\tx:DWORD\n;\tARG\ty:DWORD\n;\tARG\twidth:DWORD\n;\tARG\theight:DWORD\n;\n;\tLOCAL\tgrain:DWORD\n;\tLOCAL\tscrn_offset:DWORD\n;\tLOCAL\tbank_offset:DWORD\n;\tLOCAL\tbank:DWORD\n;\tLOCAL\txres:DWORD\n;\n;;----------------------------------------------------------------------------\n;;\tINITIALIZE\n;;----------------------------------------------------------------------------\n;\n;\tpushad\n;\n;;\tCalculate granularity units per window\n;\n;\tmov\tesi,[disp]\n;\txor\teax,eax\n;\tmov\tedi,[(DisplayInfo esi).Extended]\n;\txor\tebx,ebx\n;\tmov\tax,[(VESAModeInfo edi).WinSize]\n;\txor\tedx,edx\n;\tmov\tbx,[(VESAModeInfo edi).WinGranularity]\n;\tidiv\tebx\n;\tmov\t[grain],eax\n;\n;;\tCalculate screen offset\n;\n;\tmov\teax,[(DisplayInfo esi).XRes]\n;\tmov\t[xres],eax\n;\timul\t[y]\n;\tadd\teax,[x]\n;\tmov\t[scrn_offset],eax\n;\n;;\tCalculate bank offset\n;\n;\tmov\tebx,65536\n;\tidiv\tebx\n;\tmov\t[bank_offset],edx\n;\tmov\t[bank],eax\n;\n;\tpopad\n;\tret\n;\n;\tENDP\tBlit_VESA640x480\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Buf_320x200_To_VESA_320x200 - Buffer copy, unscaled\n;*\n;* SYNOPSIS\n;*     Buf_320x200_To_VESA_320x200(Buffer, GrainPerWin)\n;*\n;*     void Buf_320x200_To_VESA_320x200(char *, long);\n;*\n;* FUNCTION\n;*     To center the buffer on the screen, it's upper-left corner goes at\n;*     (160,140).  This means the buffer spans VESA banks 1,2 & 3, so it must\n;*     be copied in 3 parts:\n;*\n;*     Bank 1: starting offset 24224, 65 lines\n;*     Bank 2: starting offset 288, 102 lines\n;*     Bank 3: starting offset 32, 33 lines\n;*\n;* INPUTS\n;*     Buffer      - Pointer to buffer to transfer to VRAM\n;*     GrainPerWin - Granularity units per 64k window.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Buf_320x200_To_VESA_320x200:NEAR\n\tPROC\tBuf_320x200_To_VESA_320x200 C NEAR USES ebx ecx edx esi edi\n\n\tARG\tbuffer:NEAR PTR\n\tARG\tgrains_per_win:DWORD\n\n\tLOCAL\tgrain_num:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tmov\teax,01Ch\t;Set ES selector to VRAM\n\tmov\tes,ax\n\tENDIF\n\n\tmov\teax,[grains_per_win]\n\tmov\tesi,[buffer]\n\tmov\t[grain_num],eax\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 1\n;----------------------------------------------------------------------------\n\n\tSET_WINDOW [grain_num]\n\tmov\tedi,24224\t;Starting screen address\n\tmov\tedx,65\t;Lines to copy\n\n??SetBank1:\n\tmov\tecx,80\t;DWORDS to copy\n\trep\tmovsd\t;Move the pixels\n\tadd\tedi,320\t;Wrap to start of next line\n\tdec\tedx\t;Decrement our line counter\n\tjnz\t??SetBank1\t;Draw more lines\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 2\n;----------------------------------------------------------------------------\n\n\tmov\teax,[grains_per_win]\n\tadd\t[grain_num],eax\n\n\tSET_WINDOW [grain_num]\n\tmov\tedi,288\t;Starting screen address\n\tmov\tedx,102\t;Lines to copy\n\n??SetBank2:\n\tmov\tecx,80\t;DWORDS to copy\n\trep\tmovsd\t;Move the pixels\n\tadd\tedi,320\t;Wrap to start of next line\n\tdec\tedx\t;Decrement our line counter\n\tjnz\t??SetBank2\t;Draw more lines\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 3\n;----------------------------------------------------------------------------\n\n\tmov\teax,[grains_per_win]\n\tadd\t[grain_num],eax\n\n\tSET_WINDOW [grain_num]\n\tmov\tedi,32\t;Starting screen address\n\tmov\tedx,33\t;Lines to copy\n\n??SetBank3:\n\tmov\tecx,80\t;DWORDS to copy\n\trep\tmovsd\t;Move the pixels\n\tadd\tedi,320\t;Wrap to start of next line\n\tdec\tedx\t;Decrement our line counter\n\tjnz\t??SetBank3\t;Draw more lines\n\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\tret\n\n\tENDP\tBuf_320x200_To_VESA_320x200\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Buf_320x200_To_VESA_640x400 - Scales and copies 320x200 to 640x400\n;*\n;* SYNOPSIS\n;*     Buf_320x200_To_VESA_640x400(Buffer, GrainPerWin)\n;*     \n;*     void Buf_320x200_To_VESA_640x400(char *, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Buffer      - Pointer to buffer to transfer to VRAM\n;*     GrainPerWin - Granularity units per 64k window.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Buf_320x200_To_VESA_640x400:NEAR\n\tPROC\tBuf_320x200_To_VESA_640x400 C NEAR USES ebx ecx edx esi edi\n\n\tARG\tbuffer:NEAR PTR\n\tARG\tgrains_per_win:DWORD\n\n\tLOCAL\tgrain_num:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tmov\teax,01Ch\t;Set ES selector to VRAM\n\tmov\tes,ax\n\tENDIF\n\n\tmov\tesi,[buffer]\n\tmov\t[grain_num],0\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 0\n;\t- Skip down 40 scanlines (to center the image)\n;\t- Draw 62 scanlines (31 rows of blocks)\n;\t- Draw top half of 128 blocks\n;----------------------------------------------------------------------------\n\n\tSET_WINDOW [grain_num]\n\tmov\tedi,25600\t;Starting screen address\n\n\tDRAW_BLOCK_ROWS 62/2\t;Draw 31 rows of blocks\n\tDRAW_PIXEL_ROW 256/2\t;Draw top half of next 128 blocks\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 1\n;\t- Draw bottom half of previous 128 blocks\n;\t- Finish the scan line with full blocks\n;\t- Draw 100 scanlines of blocks\n;\t- last line: top half of 256 blocks\n;----------------------------------------------------------------------------\n\n\tmov\teax,[grains_per_win]\n\tadd\t[grain_num],eax\n\tSET_WINDOW [grain_num]\n\n\tsub\tesi,256/2\t;Draw bottom half of prev 128 blks\n\tmov\tedi,384\n\tDRAW_PIXEL_ROW 256/2\n\n\tmov\tedi,0\n\tDRAW_BLOCK_ROW 384/2\t;Fill rest of this block row\n\n\tadd\tedi,640\n\tDRAW_BLOCK_ROWS 100/2\t;Draw the block rows\n\tDRAW_PIXEL_ROW 512/2\t;Draw top half of next 512 blocks\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 2\n;\t- Draw bottom half of previous 256 blocks\n;\t- Finish the scan line with full blocks\n;\t- Draw 101 scanlines of blocks\n;\t- last line: 64 full blocks plus top half of 256 blocks\n;----------------------------------------------------------------------------\n\n\tmov\teax,[grains_per_win]\n\tadd\t[grain_num],eax\n\tSET_WINDOW [grain_num]\n\n\tsub\tesi,512/2\t;Draw bottom half of prev 256 blks\n\tmov\tedi,128\n\tDRAW_PIXEL_ROW 512/2\n\n\tmov\tedi,0\n\tDRAW_BLOCK_ROW 128/2\t;Fill rest of this block row\n\n\tadd\tedi,640\n\tDRAW_BLOCK_ROWS 101/2\t;Draw the block rows\n\tDRAW_BLOCK_ROW 128/2\t;Draw next 64 blocks\n\tDRAW_PIXEL_ROW 512/2\t;Top half of 256 blocks\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 3\n;\t- Draw bottom half of previous 256 blocks\n;\t- Finish the scan line with full blocks\n;\t- Draw 101 scanlines of blocks\n;\t- last line: 192 full blocks, top half of 128 blocks\n;----------------------------------------------------------------------------\n\n\tmov\teax,[grains_per_win]\n\tadd\t[grain_num],eax\n\tSET_WINDOW [grain_num]\n\n\tsub\tesi,512/2\t;Draw bottom half of prev 256 blks\n\tmov\tedi,0\n\tDRAW_PIXEL_ROW 512/2\n\tDRAW_BLOCK_ROWS 101/2\t;Draw the block rows\n\tDRAW_BLOCK_ROW 384/2\t;Last row of full blocks\n\tDRAW_PIXEL_ROW 256/2\t;Top half of 128 blocks\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 4\n;\t- Draw bottom half of previous 128 blocks\n;\t- Draw 30 scanlines of blocks\n;----------------------------------------------------------------------------\n\n\tmov\teax,[grains_per_win]\n\tadd\t[grain_num],eax\n\tSET_WINDOW [grain_num]\n\n\tsub\tesi,256/2\t;Draw bottom half of prev 256 blks\n\tmov\tedi,0\n\tDRAW_PIXEL_ROW 256/2\n\tDRAW_BLOCK_ROWS 30/2\t;Draw the block rows\n\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\n\tENDP\tBuf_320x200_To_VESA_640x400\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Buf_320x200_To_VESA_32K - Copies 320x200 buffer to VESA 32K colors\n;*\n;* SYNOPSIS\n;*     Buf_320x200_To_VESA_32K(Buffer, Palette, GrainPerWin)\n;*     \n;*     void Buf_320x200_To_VESA_32K(char *, char *, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Buffer      - Pointer to buffer to transfer to VRAM\n;*     Palette     - Pointer to 15-bit palette to use.\n;*     GrainPerWin - Granularity units per 64k window.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Buf_320x200_To_VESA_32K:NEAR\n\tPROC\tBuf_320x200_To_VESA_32K C NEAR USES ebx ecx edx esi edi\n\n\tARG\tbuffer:NEAR PTR\n\tARG\tpalette:NEAR PTR\n\tARG\tgrains_per_win:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tmov\teax,01Ch\t;Set ES selector to VRAM\n\tmov\tes,ax\n\tENDIF\n\n\tmov\tesi,[buffer]\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 0\n;----------------------------------------------------------------------------\n\n\tSET_WINDOW 0\n\tmov\tedi,0\t;Start at Bank 0, offset 0\n\tmov\tecx,32768\t;# words we'll be setting\n\n;\tGet the pixel's offset into the palette\n\n??Buf0Loop:\n\txor\teax,eax\n\tmov\tebx,[palette]\n\tmov\tal,[BYTE PTR esi]\n\tadd\tebx,eax\n\tinc\tesi\n\tadd\tebx,eax\n\n;\tstore the 15-bit palette value\n\n\tmov\tax,[WORD PTR ebx]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[WORD PTR es:edi],ax\n\tELSE\n\tmov\t[WORD PTR edi],ax\n\tENDIF\n\n\tadd\tedi,2\n\tdec\tecx\n\tjnz\t??Buf0Loop\n\n;----------------------------------------------------------------------------\n;\tCopy Bank 1\n;----------------------------------------------------------------------------\n\n\tSET_WINDOW [grains_per_win]\n\tmov\tedi,0\t;Start at Bank 1, offset 0\n\tmov\tecx,31232\t;# words we'll be setting\n\n;\tGet the pixel's offset into the palette\n\n??Buf1Loop:\n\txor\teax,eax\n\tmov\tebx,[palette]\n\tmov\tal,[BYTE PTR esi]\n\tadd\tebx,eax\n\tinc\tesi\n\tadd\tebx,eax\n\n;\tStore the 15-bit palette value\n\n\tmov\tax,[WORD PTR ebx]\n\n\tIF\tPHARLAP_TNT\n\tmov\t[WORD PTR es:edi],ax\n\tELSE\n\tmov\t[WORD PTR edi],ax\n\tENDIF\n\n\tadd\tedi,2\n\tdec\tecx\n\tjnz\t??Buf1Loop\n\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\n\tENDP\tBuf_320x200_To_VESA_32K\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Copy_Row - Copy a row of pixels to VRAM.\n;*\n;* SYNOPSIS\n;*     Copy_Row(Source, Dest, Length)\n;*\n;*     void Copy_Row(char *, char *, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Source - Pointer to data to copy to VRAM\n;*     Dest   - Destination VRAM address.\n;*     Length - Number of bytes to copy.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Copy_Row:NEAR\n\tPROC\tCopy_Row C NEAR USES ecx esi edi\n\t\n\tARG\tsource:NEAR PTR\n\tARG\tdest:NEAR PTR\n\tARG\tnumbytes:DWORD\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tmov\teax,01Ch\n\tmov\tes,ax\n\tENDIF\n\n\tcld\n\tmov\tesi,[source]\n\tmov\tedi,[dest]\n\tmov\tecx,[numbytes]\n\trep\tmovsb\n\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret\n\n\tENDP\tCopy_Row\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Copy_Word_Row - Copy a row of 15-bit pixels to VRAM\n;*\n;* SYNOPSIS\n;*     Copy_Word_Row(Source, Dest, Palette, Length)\n;*\n;*     void Copy_Word_Row(char *, char *, char *, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Source  - Pointer to data to transfer.\n;*     Dest    - Destination screen address.\n;*     Palette - 15bit palette to use.\n;*     Length  - Bytes to transfer.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Copy_Word_Row:NEAR\n\tPROC\tCopy_Word_Row C NEAR USES ebx ecx esi edi\n\n\tARG\tsource:NEAR PTR\n\tARG\tdest:NEAR PTR\n\tARG\tpalette:NEAR PTR\n\tARG\tnumbytes:DWORD\n\n\tIF\tPHARLAP_TNT\n\tpush\tes\n\tmov\teax,01Ch\n\tmov\tes,ax\n\tENDIF\n\n\tmov\tesi,[source]\n\tmov\tedi,[dest]\n\tmov\tecx,[numbytes]\n\n??loop:\n\tmov\tebx,[palette]\n\txor\teax,eax\n\tmov\tal,[esi]\t;Get pixel value\n\tshl\teax,1\t;Adjust for word entry\n\tadd\tebx,eax\t;Compute color address\n\tmov\tax,[ebx]\t;Get color\n\n\tIF\tPHARLAP_TNT\n\tmov\t[es:edi],ax\t;Set 16bit pixel\n\tELSE\n\tmov\t[edi],ax\t;Set 16bit pixel\n\tENDIF\n\n\tinc\tesi\t;Next source pixel\n\tadd\tedi,2\t;Next dest pixel\n\tdec\tecx\t;Decrement pixel count\n\tjnz\t??loop\n\n\tIF\tPHARLAP_TNT\n\tpop\tes\n\tENDIF\n\n\tret  \n\n\tENDP\tCopy_Word_Row\n\n\tEND\n\n"
  },
  {
    "path": "WINVQ/VQM32/VESAVID.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     vesavid.c\n*\n* DESCRIPTION\n*     VESA video manager. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     InitVESA         - Initialize the VESA video manager.\n*     UninitVESA       - Uninitialize the VESA video manager.\n*     SetVESAMode      - Set the display to the specified VESA video mode.\n*     ReadVESAModeInfo - Read the VESA mode information from the video card.\n*     SetVESAWindow    - Set VESA window A's start address.\n*\n****************************************************************************/\n\n#include <stdio.h>\n#include <mem.h>\n#include <dos.h>\n\n#ifndef __WATCOMC__\n#include <pldos32.h>\n#include <pharlap.h>\n#else\n#include \"realmode.h\"\n#endif\n\n#include \"vesavid.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n#ifdef __WATCOMC__\nstatic short _VInfoSel = NULL;\nstatic short _VInfoSeg = NULL;\nstatic short _ModeInfoSel = NULL;\nstatic short _ModeInfoSeg = NULL;\n\n#else  /* __WATCOMC__ */\n/* _regs       - Registers used for calling software interrupts.\n * _rpVInfo    - Real pointer to VInfo structure in conventional memory.\n * _rpModeInfo - Real pointer to ModeInfo structure in conventional memory.\n * _VInfo      - Protected mode copy of VInfo structure.\n * _ModeInfo   - Protected mode copy of ModeInfo structure.\n */\nstatic SWI_REGS _regs;\nstatic REALPTR _rpVInfo = NULL;\nstatic REALPTR _rpModeInfo = NULL;\nstatic VESAInfo _VInfo;\nstatic VESAModeInfo _ModeInfo;\n\n#endif /* __WATCOMC__ */\n\n\n/****************************************************************************\n*\n* NAME\n*     InitVESA - Initialize the VESA video manager.\n*\n* SYNOPSIS\n*     Error = InitVESA()\n*\n*     long InitVESA(void);\n*\n* FUNCTION\n*     Initialize the VESA video system. Get the VESA information from the\n*     VESA video bios.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Error - 0 if successful, or -1 error/VESA not supported.\n*\n****************************************************************************/\n\nlong InitVESA(void)\n{\n\t#ifdef __WATCOMC__\n\tunion REGS   r;\n\tstruct SREGS sr;\n\tRMInfo       rmi;\n\tlong         error = -1;\n\n\t/* Allocate real-mode memory for VESA structure. */\n\tr.x.eax = 0x0100;\n\tr.x.ebx = (sizeof(VESAInfo) + 15) >> 4;\n\tint386(0x31, &r, &r);\n\n\tif (r.x.cflag == 0) {\n\t\t_VInfoSel = r.w.dx;\n\t\t_VInfoSeg = r.w.ax;\n\n\t\t/* Allocate real-mode memory for VESAModeInfo structure. */\n\t\tr.x.eax = 0x0100;\n\t\tr.x.ebx = (sizeof(VESAModeInfo) + 15) >> 4;\n\t\tint386(0x31, &r, &r);\n\n\t\tif (r.x.cflag == 0) {\n\t\t\t_ModeInfoSel = r.w.dx;\n\t\t\t_ModeInfoSeg = r.w.ax;\n\n\t\t\t/* Clear VESAInfo structure. */\n\t\t\tmemset(MK_PTR(0, _VInfoSeg), 0, sizeof(VESAInfo));\n\n\t\t\t/* Get VESA information. */\n\t\t\tmemset(&rmi, 0, sizeof(RMInfo));\n\t\t\trmi.eax = 0x4F00;\n\t\t\trmi.edi = 0;\n\t\t\trmi.es = _VInfoSeg;\n\n\t\t\tsegread(&sr);\n\t\t\tr.w.ax = 0x0300;\n\t\t\tr.h.bl = 0x10;\n\t\t\tr.h.bh = 0;\n\t\t\tr.w.cx = 0;\n\t\t\tsr.es = FP_SEG(&rmi);\n\t\t\tr.x.edi = FP_OFF(&rmi);\n\t\t\tint386x(0x31, &r, &r, &sr);\n\n\t\t\tif ((r.x.cflag == 0) && (rmi.eax == 0x004F)) {\n\t\t\t\terror = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\n\tif (error != 0) {\n\t\tUninitVESA();\n\t}\n\n\treturn (error);\n\n\t#else  /* __WATCOMC__ */\n\n\tunsigned short rseg;\n\tlong           paras;\n\tlong           error = -1;\n\n\t/* Calculate size of VESAInfo structure in paragraphs */\n\tparas = (sizeof(VESAInfo) + 15) >> 4;\n\t\n\t/* Allocate real-mode memory for VESA structure. */\n\tif (_dx_real_alloc(paras, (unsigned short *)&rseg,\n\t\t\t(unsigned short *)&paras) == 0) {\n\n\t\tRP_SET(_rpVInfo, 0, rseg);\n\n\t\t/* Calculate size of VESAModeInfo structure in paragraphs */\n\t\tparas = (sizeof(VESAModeInfo) + 15) >> 4;\n\n\t\t/* Allocate real-mode memory for VESAModeInfo structure. */\n\t\tif (_dx_real_alloc(paras, (unsigned short *)&rseg,\n\t\t\t\t(unsigned short *)&paras) == 0) {\n\n\t\t\tRP_SET(_rpModeInfo, 0, rseg);\n\n\t\t\t/* Clear the input buffer */\n\t\t\tFillRealMem(_rpVInfo, 0, sizeof(VESAInfo));\n\n\t\t\t/* Set up function call */\n\t\t\t_regs.eax = 0x4F00;\n\t\t\t_regs.edi = RP_OFF(_rpVInfo);\n\t\t\t_regs.es = RP_SEG(_rpVInfo);\n\t\t\t_dx_real_int(0x10, &_regs);\n\n\t\t\tif (_regs.eax == 0x004F) {\n\t\t\t\tReadRealMem(&_VInfo, _rpVInfo, sizeof(VESAInfo));\n\t\t\t\terror = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (error != 0) {\n\t\tUninitVESA();\t\t\n\t}\n\n\treturn (error);\n\n\t#endif /* __WATCOMC__ */\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     UninitVESA - Uninitialize the VESA video manager.\n*\n* SYNOPSIS\n*     UninitVESA()\n*\n*     void UninitVESA(void);\n*\n* FUNCTION\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid UninitVESA(void)\n{\n\t#ifdef __WATCOMC__\n\tunion REGS r;\n\n\t/* Free VESAInfo structure */\n\tif (_VInfoSeg != NULL) {\n\t\tr.x.eax = 0x0101;\n\t\tr.x.edx = _VInfoSel;\n\t\tint386(0x31, &r, &r);\n\n\t\t_VInfoSeg = NULL;\n\t\t_VInfoSel = NULL;\n\t}\n\n\t/* Free VESAModeInfo structure */\n\tif (_ModeInfoSeg != NULL) {\n\t\tr.x.eax = 0x0101;\n\t\tr.x.edx = _VInfoSel;\n\t\tint386(0x31, &r, &r);\n\n\t\t_ModeInfoSeg = NULL;\n\t\t_ModeInfoSel = NULL;\n\t}\n\n\t#else  /* __WATCOMC__ */\n\n\t/* Free VESAInfo structure */\n\tif (_rpVInfo != NULL) {\n\t\t_dx_real_free(RP_SEG(_rpVInfo));\n\t\t_rpVInfo = NULL;\n\t}\n\n\t/* Free VESAModeInfo structure */\n\tif (_rpModeInfo != NULL) {\n\t\t_dx_real_free(RP_SEG(_rpModeInfo));\n\t\t_rpModeInfo = NULL;\n\t}\n\t#endif /* __WATCOMC__ */\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     SetVESAMode - Set the display adapter to the given VESA video mode.\n*\n* SYNOPSIS\n*     VESAModeInfo = SetVESAMode(Mode)\n*\n*     VESAModeInfo *SetVESAMode(long);\n*\n* FUNCTION\n*     Set the display adapter to the specified VESA video mode.\n*\n* INPUTS\n*     Mode - VESA video mode to set the display to.\n*\n* RESULT\n*     VESAModeInfo - Pointer to VESA mode information structure or NULL if\n*                    error.\n*\n****************************************************************************/\n\nVESAModeInfo *SetVESAMode(long mode)\n{\n\tVESAModeInfo *vminfo;\n\n\t/* Get mode info */\n\tif ((vminfo = ReadVESAModeInfo(mode)) != NULL) {\n\n\t\t/* If the mode is supported, set it. */\n\t\tif ((vminfo->Attributes & 0x01) != 0) {\n\n\t\t\t#ifdef __WATCOMC__\n\t\t\t{\n\t\t\tunion REGS r;\n\t\t\t\n\t\t\tr.x.eax = 0x4F02;\n\t\t\tr.x.ebx = mode;\n\t\t\tint386(0x10, &r, &r);\n\n\t\t\tif (r.x.eax != 0x004F)\n\t\t\t\tvminfo = NULL;\n\t\t\t}\n\n\t\t\t#else  /* __WATCOMC__ */\n\n\t\t\t/* Set up function call */\n\t\t\t_regs.eax = 0x4F02;\n\t\t\t_regs.ebx = mode;\n\t\t\t_dx_real_int(0x10, &_regs);\n\n\t\t\tif (_regs.eax != 0x004F) {\n\t\t\t\tvminfo = NULL;\n\t\t\t}\n\t\t\t#endif /* __WATCOMC__ */\n\t\t}\n\t}\n\n\treturn (vminfo);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     ReadVESAModeInfo - Read the VESA mode information from the video card.\n*\n* SYNOPSIS\n*     VESAModeInfo = ReadVESAModeInfo(Mode)\n*\n*     VESAModeInfo *ReadVESAModeInfo(long);\n*\n* FUNCTION\n*     Read information about the specified mode from the VESA video BIOS.\n*\n* INPUTS\n*     Mode - Mode ID to get information about.\n*\n* RESULT\n*     VESAModeInfo - Pointer to VESA mode information structure or NULL if\n*                    error.\n*\n****************************************************************************/\n\nVESAModeInfo *ReadVESAModeInfo(long mode)\n{\n\tVESAModeInfo *vminfo = NULL;\n\n\t#ifdef __WATCOMC__\n\tunion REGS   r;\n\tstruct SREGS sr;\n\tRMInfo       rmi;\n\n\t/* Make sure we have real-mode memory. */\n\tif (_ModeInfoSeg != NULL) {\n\t\tmemset(MK_PTR(0, _ModeInfoSeg), 0, sizeof(VESAModeInfo));\n\n\t\t/* Get mode information. */\n\t\tmemset(&rmi, 0, sizeof(RMInfo));\n\t\trmi.eax = 0x4F01;\n\t\trmi.ecx = mode;\n\t\trmi.edi = 0;\n\t\trmi.es = _ModeInfoSeg;\n\n\t\tsegread(&sr);\n\t\tr.w.ax = 0x0300;\n\t\tr.w.bx = 0x0010;\n\t\tr.w.cx = 0;\n\t\tsr.es = FP_SEG(&rmi);\n\t\tr.x.edi = FP_OFF(&rmi);\n\t\tint386x(0x31, &r, &r, &sr);\n\n\t\tif ((r.x.cflag == 0) && (rmi.eax == 0x004F)) {\n\t\t\tvminfo = (VESAModeInfo *)MK_PTR(0, _ModeInfoSeg);\n\t\t}\n\t}\n\n\t#else  /* __WATCOMC__ */\n\n\t/* Make sure we have real-mode memory. */\n\tif (_rpModeInfo != NULL) {\n\n\t\t/* Clear the input buffer */\n\t\tFillRealMem(_rpModeInfo, 0, sizeof(VESAModeInfo));\n\n\t\t/* Set up function call */\n\t\t_regs.eax = 0x4F01;\n\t\t_regs.ecx = mode;\n\t\t_regs.edi = RP_OFF(_rpModeInfo);\n\t\t_regs.es = RP_SEG(_rpModeInfo);\n\t\t_dx_real_int(0x10, &_regs);\n\n\t\tif (_regs.eax == 0x004F) {\n\t\t\tReadRealMem(&_ModeInfo, _rpModeInfo, sizeof(VESAModeInfo));\n\t\t\tvminfo = &_ModeInfo;\n\t\t}\n\t}\n\t#endif /* __WATCOMC__ */\n\n\treturn (vminfo);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     SetVESAWindow - Set VESA window A's start address.\n*\n* SYNOPSIS\n*     Error = SetVESAWindow(GrainNum)\n*\n*     long SetVESAWindow(long);\n*\n* FUNCTION\n*     This function invokes the Window Function, whose address is provided\n*     in the VESAModeInfo structure. The 'GrainNum' must be in granularity\n*     units as specified in the ModeInfo structure.\n*\n* INPUTS\n*     GrainNum - Granularity number to set window to.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid SetVESAWindow(long grain)\n{\n\t#ifdef __WATCOMC__\n\t#else  /* __WATCOMC__ */\n\n  RMC_BLK regp;\n\t\n\tregp.eax = 0x4F05;\n\tregp.ebx = 0x00;\n\tregp.edx = grain;\n\t_dx_call_real(_ModeInfo.WinFunc, &regp, 0);\n\t#endif /* __WATCOMC__ */\n}\n\n"
  },
  {
    "path": "WINVQ/VQM32/VESAVID.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMVESAVID_H\n#define VQMVESAVID_H\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     VESAVid.h (32-Bit protected mode)\n* \n* DESCRIPTION\n*     VESA video manager definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n#ifndef __WATCOMC__\n#include <pharlap.h>\n#else\n#include \"realmode.h\"\n#endif\n\n/*---------------------------------------------------------------------------\n * VESA Video Modes\n *-------------------------------------------------------------------------*/\n\n#define\tVESA_640X400_256   0x100\n#define\tVESA_640X480_256   0x101\n#define\tVESA_800X600_16    0x102\n#define\tVESA_800X600_256   0x103\n#define\tVESA_1024X768_16   0x104\n#define\tVESA_1024X768_256  0x105\n#define\tVESA_1280X400_16   0x106\n#define\tVESA_1280X400_256  0x107\n#define\tVESA_TEXT_80X60    0x108\n#define\tVESA_TEXT_132X25   0x109\n#define\tVESA_TEXT_132X60   0x10C\n#define\tVESA_320X200_32K_1 0x10D\n#define\tVESA_320X200_32K_2 0x10E\n#define\tVESA_640X480_32K   0x110\n#define\tVESA_640X480_65K   0x111\n#define\tVESA_640X480_16M   0x112\n#define\tVESA_800X600_32K   0x113\n#define\tVESA_800X600_65K   0x114\n#define\tVESA_1024X768_32K  0x116\n#define\tVESA_1024X768_65K  0x117\n\n#define\tVESA_MIN VESA_640X400_256\n#define\tVESA_MAX VESA_1024X768_65K\n\n/*---------------------------------------------------------------------------\n * Structure definitions\n *-------------------------------------------------------------------------*/\n\n/* VESAInfo - General information about this VESA implementation.\n *            (Filled in by VESA BIOS Function 0)\n *\n * Signature    - Will always be 'VESA'\n * Version      - Version #\n * OEMString    - OEM ID string\n * Capabilities - Not defined by VESA yet\n * AvailModes   - List of available modes; terminated with -1 (0xffff)\n * TotalMemory  - ???\n * Reserved     - Pads structure to 256 bytes total\n */\ntypedef struct _VESAInfo {\n\tchar           Signature[4];\n\tunsigned short Version;\n\tREALPTR        OEMString;\n\tunsigned long  Capabilities;\n\tREALPTR        AvailModes;\n\tunsigned short TotalMemory;\n\tunsigned char  Reserved[236];\n} VESAInfo;\n\n/* VESAModeInfo - Information about this VESA mode.\n *                (Filled in by VESA BIOS Function 1)\n *\n * Attributes       - bit 0: 1 = mode is supported\n *                    bit 1: 1 = optional info available\n *                    bit 2: 1 = std BIOS output functions valid in this mode\n *                    bit 3: 0 = monochrome, 1 = color\n *                    bit 4: 0 = text mode, 1 = graphics\n * WinA_Attributes  - bit 0 = window exists, bit 1=readable, bit 2= writable\n * WinB_Attributes  - bit 0 = window exists, bit 1=readable, bit 2= writable\n * WinGranularity   - smallest address boundary window can be placed upon;\n *                    size is in KB (ie 64, 32, 4)\n * WinSize          - size of windows in KB (ie 64, 32)\n * WinA_Segment     - location of Window A in CPU space (usually 0xa000)\n * WinB_Segment     - location of Window B in CPU space (usually 0xb000)\n * WinFunc          - address of window-setting function (This is provided \n *                    as an alternative to Int 10 for speed.)\n * BytesPerScanline - # bytes per scan line\n * \n * Optional info (available if bit 1 of Attributes is set):\n *\n * XRes             - X-resolution\n * YRes             - Y-resolution\n * XCharSize        - Horizontal size of char cell\n * YCharSize        - Vertical size of char cell\n * NumPlanes        - # of memory planes (???)\n * BitsPerPixel     - # bites per pixel\n * NumBanks         - # of banks (ie planes)\n * MemoryModel      - 00h = Text mode\n *                    01h = CGA mode\n *                    02h = Hercules\n *                    03h = 4 plane planar mode\n *                    04h = packed pixel mode (1 byte/pixel)\n *                    05h = non-chain 4, 256-color mode\n *                    06-0Fh = \n *                    10-FFh = OEM-specific\n * BankSize         - Bank size in KB\n */\ntypedef struct _VESAModeInfo {\n\tunsigned short Attributes;\n\tunsigned char  WinA_Attributes;\n\tunsigned char  WinB_Attributes;\n\tunsigned short WinGranularity;\n\tunsigned short WinSize;\n\tunsigned short WinA_Segment;\n\tunsigned short WinB_Segment;\n\tREALPTR        WinFunc;\n\tunsigned short BytesPerScanline;\n\tunsigned short XRes;\n\tunsigned short YRes;\n\tunsigned char  XCharSize;\n\tunsigned char  YCharSize;\n\tunsigned char  NumPlanes;\n\tunsigned char  BitsPerPixel;\n\tunsigned char  NumBanks;\n\tunsigned char  MemoryModel;\n\tunsigned char  BankSize;\n\tunsigned char  NumInputPages;\n\tunsigned char  Reserved;\n\tunsigned char  RedMaskSize;\n\tunsigned char  RedFieldPosition;\n\tunsigned char  GreenMaskSize;\n\tunsigned char  GreenFieldPosition;\n\tunsigned char  BlueMaskSize; \n\tunsigned char  BlueFieldPosition;\n\tunsigned char  RsvdMaskSize;\n\tunsigned char  RsvdFieldPosition;\n\tunsigned char  DirectColorModeInfo;\n\tunsigned char  pad[216];\n} VESAModeInfo;\n\n/*---------------------------------------------------------------------------\n * Function prototypes\n *-------------------------------------------------------------------------*/\n\nlong InitVESA(void);\nvoid UninitVESA(void);\nVESAModeInfo *SetVESAMode(long mode);\nVESAModeInfo *ReadVESAModeInfo(long mode);\nvoid SetVESAWindow(long grain_num);\n\n#endif /* VQMVESAVID_H */\n\n"
  },
  {
    "path": "WINVQ/VQM32/VESAVID.I",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*       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\n;*\n;*----------------------------------------------------------------------------\n;*\n;* FILE\n;*     vesavid.i\n;*\n;* DESCRIPTION\n;*     VESA video manager definitions. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;****************************************************************************\n\n;----------------------------------------------------------------------------\n; VESA video modes\n;----------------------------------------------------------------------------\n\nVESA_640X400_256   EQU\t0x100\nVESA_640X480_256   EQU\t0x101\nVESA_800X600_16    EQU\t0x102\nVESA_800X600_256   EQU\t0x103\nVESA_1024X768_16   EQU\t0x104\nVESA_1024X768_256  EQU\t0x105\nVESA_1280X400_16   EQU\t0x106\nVESA_1280X400_256  EQU\t0x107\nVESA_TEXT_80X60    EQU\t0x108\nVESA_TEXT_132X25   EQU\t0x109\nVESA_TEXT_132X60   EQU\t0x10C\nVESA_320X200_32K_1 EQU\t0x10D\nVESA_320X200_32K_2 EQU\t0x10E\nVESA_640X480_32K   EQU\t0x110\nVESA_640X480_65K   EQU\t0x111\nVESA_640X480_16M   EQU\t0x112\nVESA_800X600_32K   EQU\t0x113\nVESA_800X600_65K   EQU\t0x114\nVESA_1024X768_32K  EQU\t0x116\nVESA_1024X768_65K  EQU\t0x117\n\nVESA_MIN EQU\tVESA_640X400_256\nVESA_MAX EQU\tVESA_1024X768_65K\n\n;----------------------------------------------------------------------------\n; Structure definitions\n;----------------------------------------------------------------------------\n\n; VESAInfo - General information about this VESA implementation.\n;            (Filled in by VESA BIOS Function 0)\n;\n; Signature    - Will always be 'VESA'\n; Ver          - Version #\n; OEMString    - OEM ID string\n; Capabilities - Not defined by VESA yet\n; AvailModes   - List of available modes; terminated with -1 (0xffff)\n; TotalMemory  - ???\n; Reserved     - Pads structure to 256 bytes total\n\n\tSTRUC\tVESAInfo\nSignature\tDD\t?\nVer\tDW\t?\nOEMString\tDD\t?\nCapabilities\tDD\t?\nAvailModes\tDD\t?\nTotalMemory\tDW\t?\nReserved\tDB\t236 DUP (?)\n\tENDS\tVESAInfo\n\n; VESAModeInfo - Information about this VESA mode.\n;                (Filled in by VESA BIOS Function 1)\n;\n; Attributes       - bit 0: 1 = mode is supported\n;                    bit 1: 1 = optional info available\n;                    bit 2: 1 = std BIOS output functions valid in this mode\n;                    bit 3: 0 = monochrome, 1 = color\n;                    bit 4: 0 = text mode, 1 = graphics\n; WinA_Attributes  - bit 0 = window exists, bit 1=readable, bit 2= writable\n; WinB_Attributes  - bit 0 = window exists, bit 1=readable, bit 2= writable\n; WinGranularity   - smallest address boundary window can be placed upon;\n;                    size is in KB (ie 64, 32, 4)\n; WinSize          - size of windows in KB (ie 64, 32)\n; WinA_Segment     - location of Window A in CPU space (usually 0xa000)\n; WinB_Segment     - location of Window B in CPU space (usually 0xb000)\n; WinFunc          - address of window-setting function (This is provided \n;                    as an alternative to Int 10 for speed.)\n; BytesPerScanline - # bytes per scan line\n; \n; Optional info (available if bit 1 of Attributes is set):\n;\n; XRes             - X-resolution\n; YRes             - Y-resolution\n; XCharSize        - Horizontal size of char cell\n; YCharSize        - Vertical size of char cell\n; NumPlanes        - # of memory planes (???)\n; BitsPerPixel     - # bites per pixel\n; NumBanks         - # of banks (ie planes)\n; MemoryModel      - 00h = Text mode\n;                    01h = CGA mode\n;                    02h = Hercules\n;                    03h = 4 plane planar mode\n;                    04h = packed pixel mode (1 byte/pixel)\n;                    05h = non-chain 4, 256-color mode\n;                    06-0Fh = \n;                    10-FFh = OEM-specific\n; BankSize         - Bank size in KB\n\n\t\tSTRUC\tVESAModeInfo \nAttributes\t\tDW\t?\nWinA_Attributes\tDB\t?\nWinB_Attributes\tDB\t?\nWinGranularity\tDW\t?\nWinSize\t\tDW\t?\nWinA_Segment\t\tDW\t?\nWinB_Segment\t\tDW\t?\nWinFunc\t\tDD\t?\nBytesPerScanline\tDW\t?\nXRes\t\tDW\t?\nYRes\t\tDW\t?\nXCharSize\t\tDB\t?\nYCharSize\t\tDB\t?\nNumPlanes\t\tDB\t?\nBitsPerPixel\t\tDB\t?\nNumBanks\t\tDB\t?\nMemoryModel\t\tDB\t?\nBankSize\t\tDB\t?\nNumInputPages\t\tDB\t?\nReserved\t\tDB\t?\nRedMaskSize\t\tDB\t?\nRedFieldPosition\tDB\t?\nGreenMaskSize\t\tDB\t?\nGreenFieldPosition\tDB\t?\nBlueMaskSize\t\tDB\t?\nBlueFieldPosition\tDB\t?\nRsvdMaskSize\t\tDB\t?\nRsvdFieldPosition\tDB\t?\nDirectColorModeInfo\tDB\t?\npad\t\tDB\t216 DUP (?)\n\t\tENDS\tVESAModeInfo\n\n;----------------------------------------------------------------------------\n; Function definitions\n;----------------------------------------------------------------------------\n\n\tGLOBAL C InitVESA:PROC\n\tGLOBAL C UninitVESA:PROC\n\tGLOBAL C SetVESAMode:PROC\n\tGLOBAL C ReadVESAModeInfo:PROC\n\tGLOBAL C SetVESAWindow:PROC\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     SET_WINDOW - Sets window A to the specified bank.\n;\n; SYNOPSIS\n;     SET_WINDOW GrainNum\n;\n; FUNCTION\n;     This routine uses the C Set_Window function rather than going through\n;     the BIOS, for two reasons: (1) Speed, and (2) On the Cirrus Logic 54xx\n;     VESA cards, BIOS calls make noise while playing digital audio.\n;\n; INPUTS\n;     GrainNum - Granularity number.\n;\n; RESULT\n;     NONE\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tSET_WINDOW grain_num\n\tpush\tesi\n\tpush\tedi\n\tpush\tes\n\tcall\tSetVESAWindow C,grain_num\n\tpop\tes\n\tpop\tedi\n\tpop\tesi\n\tENDM\n\n"
  },
  {
    "path": "WINVQ/VQM32/VGA.I",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     vga.i\n;*\n;* DESCRIPTION\n;*     VGA hardware definitions. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;****************************************************************************\n\n;----------------------------------------------------------------------------\n; VGA Registers\n;----------------------------------------------------------------------------\n\nR_SEQUENCER\t\tEQU\t03C4h\t;Sequencer Controller Index reg\nSEQ_RESET\t\tEQU\t00h\t;Reset\nSEQ_MAP_MASK\t\tEQU\t02h\t;Index in Sequencer of Map Mask reg\nSEQ_MEMORY_MODE\tEQU\t04h\t;Memory Mode\n\nR_GRAPHICS_CONTROLLER\tEQU\t03CEh\t;Graphics Controller Index reg\nGC_READ_MAP\t\tEQU\t04h\t;Index in GController of Read Map reg\nGC_MODE\t\tEQU\t05h\t;Read/Write Modes\nGC_MISC\t\tEQU\t06h\t;Read/Write Modes\nGC_BITMASK\t\tEQU\t08h\t;Index in GController of BitMask reg\n\nR_CRT_CONTROLLER\tEQU\t03D4h\t;CRT Controller Index reg\nCRT_VERT_TOTAL\tEQU\t06h\t;Vertical total\nCRT_OVERFLOW\t\tEQU\t07h\t;Overflow\nCRT_MAX_SCANLINE\tEQU\t09h\t;Max scan line\nCRT_STARTADDR_HIGH\tEQU\t0Ch\t;Bitmap start address high byte\nCRT_STARTADDR_LOW\tEQU\t0Dh\t;Bitmap start address low byte\nCRT_VERTRET_START\tEQU\t010h\t;Vertical retrace pulse start\nCRT_VERTRET_END\tEQU\t011h\t;Vertical retrace pulse end\nCRT_VERTDISP_END\tEQU\t012h\t;Vertical display end\nCRT_UNDERLINE\t\tEQU\t014h\t;Underline location\nCRT_START_VB\t\tEQU\t015h\t;Start vertical blank\nCRT_END_VB\t\tEQU\t016h\t;End vertical blank\nCRT_MODE_CONTROL\tEQU\t017h\t;Mode control\nR_MISC_OUTPUT\t\tEQU\t03C2h\t;Miscellaneous Output reg\n\n;----------------------------------------------------------------------------\n; Palette Registers\n;----------------------------------------------------------------------------\n\nPEL_READ_ADDR\t\tEQU\t03C7h\nPEL_WRITE_ADDR\tEQU\t03C8h\nPEL_DATA\t\tEQU\t03C9h\n\n;----------------------------------------------------------------------------\n; XMode planes, for the Map Mask register\n;----------------------------------------------------------------------------\n\nXPLANE_1\tEQU\t1\nXPLANE_2\tEQU\t2\nXPLANE_3\tEQU\t4\nXPLANE_4\tEQU\t8\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     SET_PLANE - Set an XMode plane.\n;\n; SYNOPSIS\n;     SET_PLANE plane\n;\n; INPUTS\n;     plane - Number of Xmode plane to set.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tSET_PLANE plane\n\tmov\tedx,R_SEQUENCER\n\tmov\teax,SEQ_MAP_MASK\n\tout\tdx,al\n\tinc\tedx\n\tmov\teax,plane\n\tout\tdx,al\n\tENDM\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     SET_BITMASK - Set the BitMask register.\n;\n; SYNOPSIS\n;     SET_BITMASK mask\n;\n; INPUTS\n;     mask - Bitmask to use.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tSET_BITMASK mask\n\tmov\tedx,R_GRAPHICS_CONTROLLER\n\tmov\teax,GC_BITMASK\n\tout\tdx,al\n\tinc\tedx\n\tmov\teax,mask\n\tout\tdx,al\n\tENDM\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     SET_WRITEMODE - Set the VGA writemode.\n;\n; SYNOPSIS\n;     SET_WRITEMODE mode\n;\n; INPUTS\n;     mode - Write mode.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tSET_WRITEMODE mode\n\tmov\tedx,R_GRAPHICS_CONTROLLER\n\tmov\teax,GC_MODE\n\tout\tdx,al\n\tinc\tedx\n\tin\tal,dx\t;Read the register\n\tand\tal,0FCh\t;Turn off 2 lower bits\n\tor\tal,mode\t;Set write mode\n\tout\tdx,al\n\tENDM\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     OUTPORT - Output data to a VGA register.\n;\n; SYNOPSIS\n;     OUTPORT port,register,data\n;\n; INPUTS\n;     port     - Port address.\n;     register - Register to write to.\n;     data     - Data to write.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tOUTPORT port,register,data\n\tmov\tedx,port\n\tmov\tal,register\n\tout\tdx,al\n\tinc\tedx\n\tmov\tal,data\n\tout\tdx,al\n\tENDM\n\n;----------------------------------------------------------------------------\n;\n; NAME\n;     INPORT - Input data from a VGA register.\n;\n; SYNOPSIS\n;     data = INPORT port,register\n;\n; INPUTS\n;     port     - Port address.\n;     register - Register to read from.\n;\n; RESULT\n;     data - Value read from port in AL.\n;\n; USES\n;     eax, edx\n;\n;----------------------------------------------------------------------------\n\n\tMACRO\tINPORT port,register\n\tmov\tedx,port\n\tmov\tal,register\n\tout\tdx,al\n\tinc\tedx\n\tin\tal,dx\n\tENDM\n\n"
  },
  {
    "path": "WINVQ/VQM32/VIDEO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     video.c\n*\n* DESCRIPTION\n*     Video mode setting. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     SetVideoMode   - Set the video mode.\n*     GetDisplayInfo - Get the display info for the current video mode.\n*     GetVBIBit      - Get the vertical blank bit polarity.\n*\n****************************************************************************/\n\n#include <stdlib.h>\n#include <dos.h>\n#include <conio.h>\n\n#ifndef __WATCOMC__\n#include <pharlap.h>\n#include <pldos32.h>\n#else\n#include \"realmode.h\"\n#endif\n\n#include \"video.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\nstatic DisplayInfo _Display = {-1,0,0,0,NULL};\n\n\n/****************************************************************************\n*\n* NAME\n*     SetVideoMode - Set the display to the specified video mode.\n*\n* SYNOPSIS\n*     DisplayInfo = SetVideoMode(Mode)\n*\n*     DisplayInfo *SetVideoMode(long);\n*\n* FUNCTION\n*     Set the video display adapter to the desired video mode.\n*\n* INPUTS\n*     Mode - Desired video mode.\n*\n* RESULT\n*     DisplayInfo - Pointer to DisplayInfo structure, otherwise 0 for error.\n*\n****************************************************************************/\n\nDisplayInfo *SetVideoMode(long mode)\n{\n\t#ifdef __WATCOMC__\n\tunion REGS   regs;\n\tstruct SREGS sregs;\n\t#else\n\tunion _REGS  regs;\n\t#endif\n\n\tDisplayInfo  *di = NULL;\n\tVESAModeInfo *vminfo;\n\tlong         error;\n\n\t/* Initialize the video manager on the first invocation of\n\t * SetVideoMode()\n\t */\n\tif (_Display.Mode == -1) {\n\t\t_Display.VBIbit = TestVBIBit();\n\t}\n\n\t/* Clear the VRAM before enabling the mode so that there is\n\t * not any garbage on the screen.\n\t */\n\tClearVRAM();\n\n\t/* If the requested mode is the same as the current mode then\n\t * we do not need to do anything.\n\t */\n\tif (mode != _Display.Mode) {\n\n\t\t/* Uninitialize VESA if the previous mode was a VESA mode and the new\n\t\t * mode is not.\n\t\t */\n\t\tif (((_Display.Mode >= VESA_MIN) && (_Display.Mode <= VESA_MAX))\n\t\t\t\t&& ((mode < VESA_MIN) && (mode > VESA_MAX))) {\n\n\t\t\tUninitVESA();\n\t\t}\n\n\t\t/* Set display to an XMode. */\n\t\tif ((mode >= XMODE_MIN) && (mode <= XMODE_MAX)) {\n\t\t\tSetXMode(mode);\n\t\t\tClearXMode();\n\t\t\tSetupXPaging();\n\t\t\tShowXPage(0);\n\t\t\t_Display.Mode = mode;\n\t\t\t_Display.Extended = NULL;\n\t\t\tdi = &_Display;\n\n\t\t\t/* Set display resolution information */\n\t\t\tswitch (mode) {\n\t\t\t\tcase XMODE_320X200:\n\t\t\t\t\t_Display.XRes = 320;\n\t\t\t\t\t_Display.YRes = 200;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase XMODE_320X240:\n\t\t\t\t\t_Display.XRes = 320;\n\t\t\t\t\t_Display.YRes = 240;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase XMODE_320X400:\n\t\t\t\t\t_Display.XRes = 320;\n\t\t\t\t\t_Display.YRes = 400;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase XMODE_320X480:\n\t\t\t\t\t_Display.XRes = 320;\n\t\t\t\t\t_Display.YRes = 480;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase XMODE_360X400:\n\t\t\t\t\t_Display.XRes = 360;\n\t\t\t\t\t_Display.YRes = 400;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase XMODE_360X480:\n\t\t\t\t\t_Display.XRes = 360;\n\t\t\t\t\t_Display.YRes = 480;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\telse if ((mode >= VESA_MIN) && (mode <= VESA_MAX)) {\n\n\t\t\t/* Initialize the VESA manager if the current mode is not a VESA\n\t\t\t * mode.\n\t\t\t */\n\t\t\tif ((_Display.Mode < VESA_MIN) || (_Display.Mode > VESA_MAX)) {\n\t\t\t\t error = InitVESA();\n\t\t\t}\n\n\t\t\tif (!error) {\n\n\t\t\t\t/* Set the display to MCGA before going into VESA. This needs to be\n\t\t\t\t * done to ensure that the video ram selector is initialized. This\n\t\t\t\t * fixes a bug in some VESA BIOS'.\n\t\t\t\t */\n\t\t\t\t#ifndef __WATCOMC__\n\t\t\t\tregs.x.ax = mode;\n\t\t\t\t_int86(0x10, &regs, &regs);\n\t\t\t\t#else\n\t\t\t\tsegread(&sregs);\n\t\t\t\tregs.x.eax = mode;\n\t\t\t\tint386x(0x10, &regs, &regs, &sregs);\n\t\t\t\t#endif\n\n\t\t\t\tif ((vminfo = SetVESAMode(mode)) != NULL) {\n\t\t\t\t\t_Display.Mode = mode;\n\t\t\t\t\t_Display.XRes = (long)vminfo->XRes;\n\t\t\t\t\t_Display.YRes = (long)vminfo->YRes;\n\t\t\t\t\t_Display.Extended = vminfo;\n\t\t\t\t\tdi = &_Display;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t#ifndef __WATCOMC__\n\t\t\tregs.x.ax = mode;\n\t\t\t_int86(0x10, &regs, &regs);\n\t\t\t#else\n\t\t\tsegread(&sregs);\n\t\t\tregs.x.eax = mode;\n\t\t\tint386x(0x10, &regs, &regs, &sregs);\n\t\t\t#endif\n\n\t\t\t_Display.Mode = mode;\n\t\t\t_Display.XRes = 320;\n\t\t\t_Display.YRes = 200;\n\t\t\t_Display.Extended = NULL;\n\t\t\tdi = &_Display;\n\t\t}\n\t} else {\n\t\tdi = &_Display;\n\t}\n\n\treturn (di);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetDisplayInfo - Get the display info for the current video mode.\n*\n* SYNOPSIS\n*     DisplayInfo = GetDisplayInfo()\n*\n*     DisplayInfo *GetDisplayInfo(void);\n*\n* FUNCTION\n*     Return a pointer to the current display information structure.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     DisplayInfo - Pointer to initialized display info or NULL if not valid.\n*\n****************************************************************************/\n\nDisplayInfo *GetDisplayInfo(void)\n{\n\tif (_Display.Mode != 0) {\n\t\treturn (&_Display);\n\t} else {\n\t\treturn (NULL);\n\t}\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetVBIBit - Get the vertical blank bit polarity.\n*\n* SYNOPSIS\n*     VBIBit = GetVBIBit()\n*\n*     long GetVBIBit(void);\n*\n* FUNCTION\n*     Return the polarity of the vertical blank bit.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     VBIBit - Vertical blank bit polarity.\n*\n****************************************************************************/\n\nlong GetVBIBit(void)\n{\n\treturn (_Display.VBIbit);\n}\n\n"
  },
  {
    "path": "WINVQ/VQM32/VIDEO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef VQMVIDEO_H\n#define VQMVIDEO_H\n/****************************************************************************\n*\n*        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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     Video.h (32-Bit protected mode)\n*\n* DESCRIPTION\n*     Video manager definitions.\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     Febuary 3, 1995\n*\n****************************************************************************/\n\n#include <vqm32\\vesavid.h>\n\n/*---------------------------------------------------------------------------\n * VGA video modes\n *-------------------------------------------------------------------------*/\n\n#define\tTEXT_VIDEO 0x02\n#define\tMCGA 0x13\n#define\tXMODE_320X200 0x50\n#define\tXMODE_320X240 0x51\n#define\tXMODE_320X400 0x52\n#define\tXMODE_320X480 0x53\n#define\tXMODE_360X400 0x54\n#define\tXMODE_360X480 0x55\n\n#define\tXMODE_MIN 0x50\n#define\tXMODE_MAX 0x55\n\n/*---------------------------------------------------------------------------\n * Structure definitions\n *-------------------------------------------------------------------------*/\n\n/* DisplayInfo - Information about the current display.\n *\n * Mode     - Mode identification.\n * XRes     - X resolution of mode.\n * YRes     - Y resolution of mode.\n * VBIbit   - Polarity of vertical blank bit.\n * Extended - Pointer to mode specific data structure.\n */\ntypedef struct _DisplayInfo {\n\tlong Mode;\n\tlong XRes;\n\tlong YRes;\n\tlong VBIbit;\n\tvoid *Extended;\n} DisplayInfo;\n\n/*---------------------------------------------------------------------------\n * Function prototypes\n *-------------------------------------------------------------------------*/\n\nDisplayInfo *SetVideoMode(long mode);\nDisplayInfo *GetDisplayInfo(void);\nlong TestVBIBit(void);\nlong GetVBIBit(void);\n\nvoid SetupXPaging(void);\nvoid FlipXPage(void);\nunsigned char *GetXHidPage(void);\nunsigned char *GetXSeenPage(void);\nvoid DisplayXPage(long page);\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid __cdecl WaitNoVB(short vbibit);\nvoid __cdecl WaitVB(short vbibit);\nvoid __cdecl ClearVRAM(void);\nlong __cdecl SetXMode(long mode);\nvoid __cdecl ClearXMode(void);\nvoid __cdecl ShowXPage(unsigned long StartOffset);\nvoid __cdecl Xmode_BufferCopy_320x200(void *buff, void *screen);\nvoid __cdecl Xmode_Blit(void *buffer, void *screen, long imgwidth, long imgheight);\nvoid __cdecl MCGA_BufferCopy(unsigned char *buffer, unsigned char *dummy);\nvoid __cdecl MCGA_Blit(unsigned char *buffer, unsigned char *screen,\n\t\tlong imgwidth, long imgheight);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* VQMVIDEO_H */\n\n"
  },
  {
    "path": "WINVQ/VQM32/VIDEO.I",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*       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\n;*\n;*----------------------------------------------------------------------------\n;*\n;* FILE\n;*     video.i\n;*\n;* DESCRIPTION\n;*     Video manager definitions. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     January 26, 1995\n;*\n;****************************************************************************\n\n\tINCLUDE\t\"vesavid.i\"\n\n;----------------------------------------------------------------------------\n; Video Modes\n;----------------------------------------------------------------------------\n\nTEXT\tEQU\t002h\nMCGA\tEQU\t013h\nXMODE_320X200\tEQU\t050h\nXMODE_320X240\tEQU\t051h\nXMODE_320X400\tEQU\t052h\nXMODE_320X480\tEQU\t053h\nXMODE_360X400\tEQU\t054h\nXMODE_360X480\tEQU\t055h\n\n;----------------------------------------------------------------------------\n; Structure definitions\n;----------------------------------------------------------------------------\n\n; DisplayInfo - Information about the current display.\n;\n; Mode     - Mode identification\n; XRes     - X resolution\n; YRes     - Y resolution\n; VBIbit   - Polarity of vertical blank bit.\n; Extended - Pointer to mode specified data structure.\n\n\tSTRUC\tDisplayInfo\nMode\tDD\t?\nXRes\tDD\t?\nYRes\tDD\t?\nVBIbit\tDD\t?\nExtended\tDD\t?\n\tENDS\tDisplayInfo\n\n;----------------------------------------------------------------------------\n; Function definitions\n;----------------------------------------------------------------------------\n\n\tGLOBAL C GetDisplayInfo:NEAR\n\tGLOBAL C GetVBIBit:NEAR\n\n"
  },
  {
    "path": "WINVQ/VQM32/XMODE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*        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\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     xmode.asm\n;*\n;* DESCRIPTION\n;*     Xmode graphics display routines. (32-Bit protected mode)\n;*\n;* PROGRAMMER\n;*     Bill Randolph\n;*     Denzil E. Long, Jr.\n;*\n;* DATE\n;*     Febuary 3, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*     SetXMode                 - Set the specified Xmode video mode.\n;*     ClearXMode               - Clear the XMode VRAM.\n;*     ShowXPage                - Set a specific page for XMode display.\n;*     Xmode_BufferCopy_320x200 - Copy 320x200 buffer to Xmode VRAM.\n;*     Xmode_Blit               - Bit blit a block to the XMode display.\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tINCLUDE\t\"vga.i\"\n\tINCLUDE\t\"video.i\"\n\tCODESEG\n\n;****************************************************************************\n;*\n;* NAME\n;*     SetXMode - Set the specified Xmode video mode.\n;*\n;* SYNOPSIS\n;*     Error = SetXMode(Mode)\n;*\n;*     long SetXMode(long);\n;*\n;* FUNCTION\n;*     This routines set the current display adapter to the specified Xmode.\n;*     Portions of this routine were take from Dr. Dobb's, written in C, and\n;*     portions were taken from Dominic's 320x200 code.\n;*\n;* INPUTS\n;*     Mode - Xmode mode to set display to.\n;*\n;* RESULT\n;*     Error - 0 if successful, or -1 if error.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC SetXMode:NEAR\n\tPROC\tSetXMode C NEAR USES edx\n\n\tARG\tmode:DWORD\n\n??Set320x200:\n\tcmp\t[mode],XMODE_320X200\t;320x200?\n\tjne\t??Set320x240\n\n\tIF\t0\n\tmov\teax,MCGA\n\tint\t10h\n\n;\tMemory Mode:\n;\tbit3 (chain) = 0 (planes are accessed via Map Mask)\n;\tbit2 (odd/even) = 1 (use sequential addressing mode)\n\n\tINPORT R_SEQUENCER,SEQ_MEMORY_MODE\n\tand\tal,not 08h\t\t\t;Turn off chain 4\n\tor\tal,04h\t\t\t;Turn off odd/even\n\tout\tdx,al\n\n\tINPORT R_GRAPHICS_CONTROLLER,GC_MODE\n\tand\tal,not 10h\t\t\t;Turn off odd/even\n\tout\tdx,al\n\n\tINPORT R_GRAPHICS_CONTROLLER,GC_MISC\n\tand\tal,not 02h\t\t\t;Turn off chain\n\tout\tdx,al\n\n\tOUTPORT R_SEQUENCER,SEQ_MAP_MASK,0Fh\n\tINPORT R_CRT_CONTROLLER, CRT_MAX_SCANLINE\n\tand\tal,not 1fh\t\t\t;Clear low 5 bits\n\tor\tal,1     \t\t\t;Mode = 0 => 400 lines\n\tout\tdx,al\t\t\t;Mode =1  => 200\n\n\tINPORT R_CRT_CONTROLLER,CRT_UNDERLINE\n\tand\tal,not 40h\t\t\t;Turn off doubleword\n\tout\tdx,al\n\n\tINPORT R_CRT_CONTROLLER,CRT_MODE_CONTROL\n\tor\tal,40h\t\t\t;Turn on byte mode bit,\n\tout\tdx,al\t    \t\t; so mem scanned linearly\n\tENDIF\n\n;\tThe following section of code is from Roger Stevens' XMode\n;\texample code; it's the same as 320x400, except the value sent\n;\tto CRT_MAX_SCANLINE is 41, not 40.\n\n\tmov\teax,MCGA\n\tint\t10h\n\n\tOUTPORT R_SEQUENCER,SEQ_MEMORY_MODE,06h\n\tINPORT R_CRT_CONTROLLER,CRT_VERTRET_END\n\tand\tal,07Fh\n\tout\tdx,al\n\n\tOUTPORT R_CRT_CONTROLLER,CRT_MAX_SCANLINE,41h\n\tOUTPORT R_CRT_CONTROLLER,CRT_UNDERLINE,00h\n\tOUTPORT R_CRT_CONTROLLER,CRT_MODE_CONTROL,0E3h\n\n\tmov\teax,0\n\tjmp\t??Done\n\n??Set320x240:\n\tcmp\t[mode],XMODE_320X240\t;320x240?\n\tjne\t??Set320x400\n\n;\tStart by setting MCGA to let the BIOS program the registers;\n;\tthen, reprogram the registers that need it.\n\n\tmov\teax,MCGA\n\tint\t10h\n\n;\tMemory Mode:\n;\tbit3 (chain) = 0 (planes are accessed via Map Mask)\n;\tbit2 (odd/even) = 1 (use sequential addressing mode)\n;\tbit1 (extended mem) = 1 (>64K video RAM)\n;\tbit0 (alpha/graph) = 0 (graphics mode)\n\n\tOUTPORT R_SEQUENCER,SEQ_MEMORY_MODE,06h\n\n;\tIssue a Sequencer Reset\n\tOUTPORT R_SEQUENCER,SEQ_RESET,01h\n\n;\tMisc Output: (set to 1100 0011)\n;\tBit 7: VSync polarity (1=negative)\n;\tBit 6: HSync polarity (1=negative)\n;\tBit 5: page bit for odd/even (0=low 64K)\n;\tBit 4: Video drivers (0=enable)\n;\tBit 3,2: clock select (0=25-MHz clock)\n;\tBit 1: VRAM access (1 = enable CPU to access)\n;\tBit 0: I/O Address (1=color emulation)\n\n\tmov\tedx,R_MISC_OUTPUT\n\tmov\tal,0C3h\n\tout\tdx,al\n\n;\tClear Sequencer Reset\n\n\tOUTPORT R_SEQUENCER,SEQ_RESET,03h\n\n;\tRead Vertical Retrace End, and with 07f to clear high bit\n;\t(clearing bit 7 enables writing to registers 0-7)\n\n\tINPORT R_CRT_CONTROLLER,CRT_VERTRET_END\n\tand\tal,07Fh\n\tout\tdx,al\n\n;\tProgram the CRT Controller to display 480 scanlines, but to\n;\tdouble each scanline so only 240 are displayed:\n\n\tOUTPORT R_CRT_CONTROLLER,CRT_UNDERLINE,00h\n\tOUTPORT R_CRT_CONTROLLER,CRT_MODE_CONTROL,0E3h\n\tOUTPORT R_CRT_CONTROLLER,CRT_VERT_TOTAL,0Dh\n\tOUTPORT R_CRT_CONTROLLER,CRT_OVERFLOW,03Eh\n\tOUTPORT R_CRT_CONTROLLER,CRT_VERTRET_START,0EAh\n\tOUTPORT R_CRT_CONTROLLER,CRT_VERTRET_END,0ACh\n\tOUTPORT R_CRT_CONTROLLER,CRT_VERTDISP_END,0DFh\n\tOUTPORT R_CRT_CONTROLLER,CRT_START_VB,0E7h\n\tOUTPORT R_CRT_CONTROLLER,CRT_END_VB,06h\n\tOUTPORT R_CRT_CONTROLLER,CRT_MAX_SCANLINE,041h\n\n\txor\teax,eax\n\tjmp\t??Done\n\n??Set320x400:\n\tcmp\t[mode],XMODE_320X400\t;320x400\n\tjne\t??Set320x480\n\n\tmov\teax,MCGA\n\tint\t10h\n\n\tOUTPORT R_SEQUENCER,04h,06h\n\tINPORT R_CRT_CONTROLLER,011h\n\tand\tal,07Fh\n\tout\tdx,al\n\n\tOUTPORT R_CRT_CONTROLLER,09h,40h\n\tOUTPORT R_CRT_CONTROLLER,014h,00h\n\tOUTPORT R_CRT_CONTROLLER,017h,0E3h\n\n\txor\teax,eax\n\tjmp\t??Done\n\n??Set320x480:\n\tcmp\t[mode],XMODE_320X480\t;320x480?\n\tjne\t??Set360x400\n\n\tmov\teax,MCGA\n\tint\t10h\n\n\tmov\tedx,R_SEQUENCER\n\tmov\teax,0604h\n\tout\tdx,ax\n\n\tmov\teax,0100h\n\tout\tdx,ax\n\n\tmov\tedx,R_MISC_OUTPUT\n\tmov\tal,0C3h\n\tout\tdx,al\n\n\tmov\tedx,R_SEQUENCER\n\tmov\teax,0300h\n\tout\tdx,ax\n\n\tmov\tedx,R_CRT_CONTROLLER\n\tmov\tal,011h\n\tout\tdx,al\n\n\tmov\tedx,03D5h\n\tin\tal,dx\n\tand\tal,07Fh\n\tout\tdx,al\n\n\tmov\tedx,R_CRT_CONTROLLER\n\tmov\teax,04009h\n\tout\tdx,ax\n\tmov\teax,00014h\n\tout\tdx,ax\n\tmov\teax,0E317h\n\tout\tdx,ax\n\tmov\teax,00D06h\n\tout\tdx,ax\n\tmov\teax,03E07h\n\tout\tdx,ax\n\tmov\teax,0EA10h\n\tout\tdx,ax\n\tmov\teax,0AC11h\n\tout\tdx,ax\n\tmov\teax,0DF12h\n\tout\tdx,ax\n\tmov\teax,0E715h\n\tout\tdx,ax\n\tmov\teax,00616h\n\tout\tdx,ax\n\tmov\teax,04009h\n\tout\tdx,ax\n\n\txor\teax,eax\n\tjmp\t??Done\n\n??Set360x400:\n\tcmp\t[mode],XMODE_360X400\t;360x400\n\tjne\t??Set360x480\n\n\tmov\teax,MCGA\n\tint\t10h\n\n\tmov\tedx,R_SEQUENCER\n\tmov\teax,0604h\n\tout\tdx,ax\n\n\tmov\teax,0100h\n\tout\tdx,ax\n\n\tmov\tedx,R_MISC_OUTPUT\n\tmov\tal,067h\n\tout\tdx,al\n\n\tmov\tedx,R_SEQUENCER\n\tmov\teax,0300h\n\tout\tdx,ax\n\n\tmov\tedx,R_CRT_CONTROLLER\n\tmov\tal,011h\n\tout\tdx,al\n\n\tmov\tedx,03D5h\n\tin\tal,dx\n\tand\tal,07Fh\n\tout\tdx,al\n\n\tmov\tedx,R_CRT_CONTROLLER\n\tmov\teax,06B00h\n\tout\tdx,ax\n\tmov\teax,05901h\n\tout\tdx,ax\n\tmov\teax,05A02h\n\tout\tdx,ax\n\tmov\teax,08E03h\n\tout\tdx,ax\n\tmov\teax,05E04h\n\tout\tdx,ax\n\tmov\teax,08A05h\n\tout\tdx,ax\n\tmov\teax,04009\n\tout\tdx,ax\n\tmov\teax,00014h\n\tout\tdx,ax\n\tmov\teax,0E317h\n\tout\tdx,ax\n\tmov\teax,02D13h\n\tout\tdx,ax\n\n\txor\teax,eax\n\tjmp\t??Done\n\n??Set360x480:\n\tcmp\t[mode],XMODE_360X480\t;360x480?\n\tjne\t??Unknown_mode\n\n\tmov\teax,MCGA\n\tint\t10h\n\n\tmov\tedx,R_SEQUENCER\n\tmov\teax,0604h\n\tout\tdx,ax\n\n\tmov\teax,0100h\n\tout\tdx,ax\n\n\tmov\tedx,R_MISC_OUTPUT\n\tmov\tal,0E7h\n\tout\tdx,al\n\n\tmov\tedx,R_SEQUENCER\n\tmov\teax,0300h\n\tout\tdx,ax\n\n\tmov\tedx,R_CRT_CONTROLLER\n\tmov\tal,011h\n\tout\tdx,al\n\n\tmov\tedx,03D5h\n\tin\tal,dx\n\tand\tal,07Fh\n\tout\tdx,al\n\n\tmov\tedx,R_CRT_CONTROLLER\n\tmov\teax,06B00h\n\tout\tdx,ax\n\tmov\teax,05901h\n\tout\tdx,ax\n\tmov\teax,05A02h\n\tout\tdx,ax\n\tmov\teax,08E03h\n\tout\tdx,ax\n\tmov\teax,05E04h\n\tout\tdx,ax\n\tmov\teax,08A05h\n\tout\tdx,ax\n\tmov\teax,04009h\n\tout\tdx,ax\n\tmov\teax,00014h\n\tout\tdx,ax\n\tmov\teax,0E317h\n\tout\tdx,ax\n\tmov\teax,00D06h\n\tout\tdx,ax\n\tmov\teax,03E07h\n\tout\tdx,ax\n\tmov\teax,0EA10h\n\tout\tdx,ax\n\tmov\teax,0AC11h\n\tout\tdx,ax\n\tmov\teax,0DF12h\n\tout\tdx,ax\n\tmov\teax,0E715h\n\tout\tdx,ax\n\tmov\teax,00616h\n\tout\tdx,ax\n\tmov\teax,02D13h\n\tout\tdx,ax\n\n\txor\teax,eax\n\tjmp\t??Done\n\n??Unknown_mode:\n\tmov\teax,0FFFFFFFFh\t;Unknown mode\n\n??Done:\n\tret\n\n\tENDP\tSetXMode\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     ClearXMode - Clear the XMode VRAM.\n;*\n;* SYNOPSIS\n;*     ClearXMode()\n;*\n;*     void ClearXMode(void);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     NONE\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC ClearXMode:NEAR\n\tPROC\tClearXMode C NEAR USES eax ecx edi es\n\n\tIF\tPHARLAP_TNT\n\tmov\teax,01Ch\n\tmov\tes,ax\t\t;Set ES selector to VRAM\n\tmov\tedi,0\n\tELSE\n\tmov\tedi,0A0000h\n\tENDIF\n\tSET_PLANE 0Fh\n\tmov\tecx,((320*240*2)/4/4)\n\txor\teax,eax\n\trep\tstosd\n\tret\n\n\tENDP\tClearXMode\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     ShowXPage - Set a specific page for XMode display.\n;*\n;* SYNOPSIS\n;*     ShowXPage(Offset)\n;*\n;*     void ShowXPage();\n;*\n;* FUNCTION\n;*     Show the page at the specified offset in the bitmap. Page-flip takes\n;*     effect on the next active scan cycle.\n;*\n;* INPUTS\n;*     Offset - Offset to set page to.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC ShowXPage:NEAR\n\tPROC\tShowXPage C NEAR USES eax ebx ecx edx\n\n\tARG\tStartOffset:DWORD\n\n\tmov\tedx,R_CRT_CONTROLLER\n\tmov\tbl,CRT_STARTADDR_LOW\n\tmov\tbh,[byte ptr StartOffset]\n\tmov\tcl,CRT_STARTADDR_HIGH\n\tmov\tch,[byte ptr StartOffset+1]\n\tmov\teax,ebx\n\tout\tdx,ax\n\tmov\teax,ecx\n\tout\tdx,ax\n\tret\n\n\tENDP\tShowXPage\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Xmode_BufferCopy_320x200 - Copy 320x200 buffer to Xmode VRAM.\n;*\n;* SYNOPSIS\n;*     Xmode_BufferCopy_320x200(Buffer, Screen)\n;*\n;*     void Xmode_BufferCopy_320x200(char *, char *);\n;*\n;* FUNCTION\n;*     BitBlt copy to VRAM.\n;*\n;* INPUTS\n;*     Buffer - Pointer to buffer to copy to XMode VRAM.\n;*     Screen - XMode VRAM screen address to copy buffer to.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Xmode_BufferCopy_320x200:NEAR\n\tPROC\tXmode_BufferCopy_320x200 C NEAR USES eax ecx edx edi esi es\n\n\tARG\tbuffer:NEAR PTR\n\tARG\tscreen:NEAR PTR\n\n\tLOCAL\tsave_esi:DWORD\n\tLOCAL\tsave_edi:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\t\n\tIF\tPHARLAP_TNT\n\tmov\teax,01Ch\t;Set ES selector to VRAM.\n\tmov\tes,ax\n\tENDIF\n\n\tmov\tesi,[buffer]\t;Set pointers\n\tmov\tedi,[screen]\n\tmov\t[save_esi],esi\n\tmov\t[save_edi],edi\n\n;----------------------------------------------------------------------------\n;\tCopy plane 1\n;----------------------------------------------------------------------------\n\n\tSET_PLANE XPLANE_1\n\tmov\tecx,4000\n\nx_loop_1:\n\tmov\tal,[esi + 8]\t;Get pixel\n\tmov\tah,[esi + 12]\t;Get pixel\n\tror\teax,16\n\tmov\tal,[esi]\t;Get pixel\n\tmov\tah,[esi + 4]\t;Get pixel\n\tmov\t[es:edi],eax \t;Write plane 1 pixels to VRAM\n\n\tadd\tesi,16\t;Next source pixel position\n\tadd\tedi,4\t;Next VRAM position\n\tdec\tecx\n\tjnz\tshort x_loop_1\n\n;----------------------------------------------------------------------------\n;\tCopy plane 2\n;----------------------------------------------------------------------------\n\n\tmov\tesi,[save_esi]\t;Restore pointers\n\tmov\tedi,[save_edi]\n\tinc\tesi\t;Adjust source pointer to plane 2\n\n\tSET_PLANE XPLANE_2\n\tmov\tecx,4000\n\nx_loop_2:\n\tmov\tal,[esi + 8]\t;Get pixel\n\tmov\tah,[esi + 12]\t;Get pixel\n\tror\teax,16\n\tmov\tal,[esi]\t;Get pixel\n\tmov\tah,[esi + 4]\t;Get pixel\n\tmov\t[es:edi],eax\t;Write plane 2 pixels to VRAM\n\n\tadd\tesi,16\t;Next source pixel position\n\tadd\tedi,4\t;Next VRAM position\n\tdec\tecx\n\tjnz\tshort x_loop_2\n\n;----------------------------------------------------------------------------\n;\tCopy plane 3\n;----------------------------------------------------------------------------\n\n\tmov\tesi,[save_esi]\t;Restore pointers\n\tmov\tedi,[save_edi]\n\tadd\tesi,2\t;Adjust source pointer to plane 3\n\n\tSET_PLANE XPLANE_3\n\tmov\tecx,4000\n\nx_loop_3:\n\tmov\tal,[esi + 8]\t;Get pixel\n\tmov\tah,[esi + 12]\t;Get pixel\n\tror\teax,16\n\tmov\tal,[esi]\t;Get pixel\n\tmov\tah,[esi + 4]\t;Get pixel\n\tmov\t[es:edi],eax\t;Write plane 3 pixels to VRAM\n\n\tadd\tesi,16\t;Next source pixel position\n\tadd\tedi,4\t;Next VRAM position\n\tdec\tecx\n\tjnz\tshort x_loop_3\n\n;----------------------------------------------------------------------------\n;\tCopy plane 4\n;----------------------------------------------------------------------------\n\n\tmov\tesi,[save_esi]\t;Restore pointers\n\tmov\tedi,[save_edi]\n\tadd\tesi,3\t;Adjust source pointer to plane 4\n\n\tSET_PLANE XPLANE_4\n\tmov\tecx,4000\nx_loop_4:\n\tmov\tal,[esi + 8]\t;Get pixel\n\tmov\tah,[esi + 12]\t;Get pixel\n\tror\teax,16\n\tmov\tal,[esi]\t;Get pixel\n\tmov\tah,[esi + 4]\t;Get pixel\n\tmov\t[es:edi],eax\t;Write plane 4 pixels to VRAM\n\n\tadd\tesi,16\t;Next source pixel position\n\tadd\tedi,4\t;Next screen position\n\tdec\tecx\n\tjnz\tshort x_loop_4\n\tret\n\n\tENDP\tXmode_BufferCopy_320x200\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     Xmode_Blit - Bit blit a block to the XMode display.\n;*\n;* SYNOPSIS\n;*     XMode_Blit(Buffer, Screen, Width, Height)\n;*\n;*     void XMode_Blit(char *, char *, long, long);\n;*\n;* FUNCTION\n;*\n;* INPUTS\n;*     Buffer - Pointer buffer to blit to screen.\n;*     Screen - Screen address to blit buffer to.\n;*     Width  - Width of buffer.\n;*     Height - Height of buffer.\n;*\n;* RESULT\n;*     NONE\n;*\n;* WARNINGS\n;*     Assumes the screen to be 320 pixels wide and the source buffer width\n;*     to be divisible by 16.\n;*\n;****************************************************************************\n\n\tGLOBAL\tC Xmode_Blit:NEAR\n\tPROC\tXmode_Blit C NEAR USES ecx edx esi edi es\n\n\tARG\tbuffer:NEAR PTR\n\tARG\tscreen:NEAR PTR\n\tARG\timgwidth:DWORD\n\tARG\timgheight:DWORD\n\n\tLOCAL\trowcount:DWORD\n\tLOCAL\txplane:DWORD\n\tLOCAL\tedi_startval:DWORD\n\tLOCAL\tesi_startval:DWORD\n\tLOCAL\txadd:DWORD\n\n;----------------------------------------------------------------------------\n;\tInitialize\n;----------------------------------------------------------------------------\n\n\tIF\tPHARLAP_TNT\n\tmov\teax,01Ch\t;Set ES selector to VRAM\n\tmov\tes,ax\n\tENDIF\n\n\tmov\tesi,[buffer]\n\tmov\tedi,[screen]\n\tmov\t[esi_startval],esi\n\tmov\t[edi_startval],edi\n\n\tmov\tedx,320\t;Compute modulo\n\tsub\tedx,[imgwidth]\n\tshr\tedx,2\n\tmov\t[xadd],edx\n\n;----------------------------------------------------------------------------\n;\tTransfer the data on plane at a time.\n;----------------------------------------------------------------------------\n\n\tmov\t[xplane],1\n\n??Do_plane:\n\tSET_PLANE [xplane]\t;Set plane to transfer to\n\tmov\teax,[imgheight]\n\tmov\t[rowcount],eax\n\tmov\tedx,[xadd]\n\n??Do_row:\n\tmov\tecx,[imgwidth]\t;Length of row to copy in DWORDS\n\tshr\tecx,4\n\n;\tTransfer a row of pixels\n\n??Not_done:\n\tmov\tal,[esi + 8]\t;Get pixel\n\tmov\tah,[esi + 12]\t;Get pixel\n\tror\teax,16\n\tmov\tal,[esi]\t;Get pixel\n\tmov\tah,[esi + 4]\t;Get pixel\n\tmov\t[es:edi],eax\t;Write pixels to VRAM plane\n\n\tadd\tesi,16\t;Next source position\n\tadd\tedi,4\t;Next VRAM position\n\tdec\tecx\n\tjnz\t??Not_done\n\n\tadd\tedi,edx\t;Next VRAM row\n\tdec\t[rowcount]\t;Decrement the row count\n\tjnz\t??Do_row\n\n;\tGo to next X-Plane\n\n\tinc\t[esi_startval]\n\tmov\teax,[esi_startval]\n\tmov\tesi,eax\n\tmov\teax,[edi_startval]\n\tmov\tedi,eax\n\tshl\t[xplane],1\n\tcmp\t[xplane],16\n\tjnz\t??Do_plane\n\tret\n\n\tENDP\tXmode_Blit\n\n\tEND\n\n"
  },
  {
    "path": "WINVQ/VQM32/XMODEPG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*         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\n*\n*----------------------------------------------------------------------------\n*\n* FILE\n*     xmodepg.c\n*\n* DESCRIPTION\n*     Xmode page access. (32-Bit protected mode)\n*\n* PROGRAMMER\n*     Bill Randolph\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     January 26, 1995\n*\n*----------------------------------------------------------------------------\n*\n* PUBLIC\n*     SetupXPaging - Setup Xmode paging variables.\n*     FlipXPage    - Page flip to next Xmode page.\n*     ShowXPage    - Show the specified Xmode page.\n*     GetXHidPage  - Get the address of the current Xmode HidPage.\n*     GetXSeenPage - Get the address of the current Xmode SeenPage.\n*\n****************************************************************************/\n\n#include <dos.h>\n#include \"video.h\"\n\n/*---------------------------------------------------------------------------\n * PRIVATE DECLARATIONS\n *-------------------------------------------------------------------------*/\n\n#define PAGE0_START_OFFSET 0\n#define PAGE1_START_OFFSET ((320 * 240) / 4)\n\n/* PageFlip page values. */\nstatic unsigned long PageStartOffsets[2] = {\n\tPAGE0_START_OFFSET,\n\tPAGE1_START_OFFSET\n};\n\nstatic long DisplayedPage;\nstatic long NonDisplayedPage;\n\n/****************************************************************************\n*\n* NAME\n*     SetupXPaging - Setup Xmode paging variables.\n*\n* SYNOPSIS\n*     SetupXPaging()\n*\n*     void SetupXPaging(void);\n*\n* FUNCTION\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid SetupXPaging(void)\n{\n\tDisplayedPage = 1;\n\tNonDisplayedPage = DisplayedPage ^ 1;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     FlipXPage - Page flip to next Xmode page.\n*\n* SYNOPSIS\n*     FlipXPage()\n*\n*     void FlipXPage(void);\n*\n* FUNCTION\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid FlipXPage(void)\n{\n\tShowXPage(PageStartOffsets[NonDisplayedPage]);\n\tDisplayedPage = NonDisplayedPage;\n\tNonDisplayedPage = DisplayedPage ^ 1;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     ShowXPage - Show the specified Xmode page.\n*\n* SYNOPSIS\n*     ShowXPage(page)\n*\n*     void ShowXPage(long);\n*\n* FUNCTION\n*\n* INPUTS\n*     Page - Xmode page number to show.\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid DisplayXPage(long page)\n{\n\tShowXPage(PageStartOffsets[page & 1]);\n\tDisplayedPage = page;\n\tNonDisplayedPage = DisplayedPage ^ 1;\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetXHidPage - Get the address of the current Xmode HidPage.\n*\n* SYNOPSIS\n*     HidPage = GetXHidPage()\n*\n*     unsigned char *GetXHidPage(void);\n*\n* FUNCTION\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     HidPage - Address of Xmode HidPage.\n*\n****************************************************************************/\n\nunsigned char *GetXHidPage(void)\n{\n\treturn((unsigned char *)PageStartOffsets[NonDisplayedPage]);\n}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetXSeenPage - Get the address of the current Xmode SeenPage.\n*\n* SYNOPSIS\n*     SeenPage = GetXSeenPage()\n*\n*     unsigned char *GetXSeenPage(void);\n*\n* FUNCTION\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     SeePage - Address of the Xmode SeenPage.\n*\n****************************************************************************/\n\nunsigned char *GetXSeenPage(void)\n{\n\treturn ((unsigned char *)PageStartOffsets[DisplayedPage]);\n}\n\n"
  },
  {
    "path": "WWFLAT32/AUDIO/AUDIO.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : AUDIO.H                                  *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : March 10, 1995                           *\n *                                                                         *\n *                  Last Update : March 10, 1995   [PWG]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwstd.h\"\n\n/*=========================================================================*/\n/* AUD file header type\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tAUD_FLAG_STEREO\t1\n#define\tAUD_FLAG_16BIT\t\t2\n\n// PWG 3-14-95: This structure used to have bit fields defined for Stereo\n//   and Bits.  These were removed because watcom packs them into a 32 bit\n//   flag entry even though they could have fit in a 8 bit entry.\n#pragma pack(1);\ntypedef struct {\n\tshort int\tRate;\t\t\t\t// Playback rate (hertz).\n\tlong\tSize;\t\t\t\t// Size of data (bytes).\n\tlong\tUncompSize;\t\t\t\t// Size of data (bytes).\n\tunsigned char Flags;\t// Holds flags for info\n\t\t\t\t\t\t\t\t//  1: Is the sample stereo?\n\t\t\t\t\t\t\t\t//  2: Is the sample 16 bits?\n\tunsigned char Compression;\t// What kind of compression for this sample?\n} AUDHeaderType;\n\n\n/*=========================================================================*/\n/*\tThere can be a different sound driver for sound effects, digitized\t\t*/\n/*\tsamples, and musical scores.  Each one must be of these specified\t\t\t*/\n/*\ttypes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\ntypedef enum {\n\tSAMPLE_NONE,\t\t// No digitized sounds will be played.\n\tSAMPLE_SB,\t\t\t// Sound Blaster digitized driver.\n\tSAMPLE_SBPRO,\t\t// Sound Blaster Pro digitized driver.\n\tSAMPLE_PAS,\t\t\t// Pro-Audio Spectrum digitized driver.\n\tSAMPLE_ADLIBG,\t\t// Adlib-Gold digitized driver.\n\tSAMPLE_TANDY,\t\t// Tandy 'compatible' driver.\n\tSAMPLE_PCSPKR,\t\t// PC speaker digitized driver (The Audio Solution driver).\n\tSAMPLE_ADLIB,\t\t// Adlib digitized driver (The Audio Solution driver).\n\tSAMPLE_TEMP=0x1000,\n\tSAMPLE_LAST\n} Sample_Type;\n\ntypedef enum {\n\tSCORE_NONE,\t\t\t// No scores will be played.\n\tSCORE_ALFX,\t\t\t// Westwood's ALFX adlib compatable driver.\n\tSCORE_WWPCSPKR,\t// Westwood's PC-speaker driver (obsolete).\n\tSCORE_WWTANDY,\t\t// Westwood's PC-speaker driver with Tandy mod (obsolete).\n\tSCORE_PCSPKR,\t\t// PC speaker XMIDI driver.\n\tSCORE_TANDY,\t\t// Tandy XMIDI driver.\n\tSCORE_MT32,\t\t\t// MT-32 / LAPC-1 Roland XMIDI driver.\n\tSCORE_CANVAS,\t\t// Sound Canvas SC-55.\n\tSCORE_ADLIB,\t\t// Adlib XMIDI driver.\n\tSCORE_ADLIBG,\t\t// Adlib Gold XMIDI driver.\n\tSCORE_PASFM,\t\t// Pro Audio Spectrum XMIDI driver.\n\tSCORE_SBFM,\t\t\t// Sound Blaster XMIDI driver.\n\tSCORE_SBP1FM,\t\t// Sound Blaster Pro (YM3812) XMIDI driver.\n\tSCORE_SBP2FM,\t\t// Sound Blaster Pro (OPL3) XMIDI driver (Can't use with SFX_ALFX).\n\tSCORE_TEMP=0x1000,\n\tSCORE_LAST\n} Score_Type;\n\ntypedef enum {\n\tSFX_NONE,\t\t\t// No sound effects will be played.\n\tSFX_ALFX,\t\t\t// Westwood's ALFX adlib compatable driver.\n\tSFX_WWPCSPKR,\t\t// Westwood's PC-speaker driver.\n\tSFX_WWTANDY,\t\t// Westwood's PC-speaker driver with Tandy mod.\n\tSFX_PCSPKR,\t\t\t// PC speaker XMIDI driver.\n\tSFX_TANDY,\t\t\t// Tandy XMIDI driver.\n\tSFX_MT32,\t\t\t// MT-32 / LAPC-1 Roland XMIDI driver.\n\tSFX_CANVAS,\t\t\t// Sound Canvas SC-55.\n\tSFX_ADLIB,\t\t\t// Adlib XMIDI driver.\n\tSFX_ADLIBG,\t\t\t// Adlib Gold XMIDI driver.\n\tSFX_PASFM,\t\t\t// Pro Audio Spectrum XMIDI driver.\n\tSFX_SBFM,\t\t\t// Sound Blaster XMIDI driver.\n\tSFX_SBP1FM,\t\t\t// Sound Blaster Pro (YM3812) XMIDI driver.\n\tSFX_SBP2FM,\t\t\t// Sound Blaster Pro (OPL3) XMIDI driver.\n\tSFX_TEMP=0x1000,\n\tSFX_LAST\n} SFX_Type;\n\ntypedef enum RateEnum {\n\tPLAYBACK_RATE_SLOW =11025,\n\tPLAYBACK_RATE_NORMAL =(11025 * 2),\n\tPLAYBACK_RATE_FAST =(11025 * 4),\n} RateType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SOUNDIO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nint File_Stream_Sample(char const *filename, BOOL real_time_start = FALSE);\nint File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start = FALSE);\nvoid cdecl _saveregs Sound_Callback(void);\nvoid cdecl far __saveregs __loadds maintenance_callback(void);\nvoid *Load_Sample(char const *filename);\nlong Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);\nlong Sample_Read(int fh, void *buffer, long size);\nvoid Free_Sample(void const *sample);\nBOOL Sound_Init(int sfx, int score, int sample, RateType rate, int bits_per_sample, int max_samples, int reverse_channels);\nBOOL Audio_Init(int sample, int address, int inter, int dma, RateType rate, int bits_per_sample, int max_samples, int reverse_channels = FALSE);\nvoid Sound_End(void);\nvoid Stop_Sample(int handle);\nBOOL Sample_Status(int handle);\nBOOL Is_Sample_Playing(void const * sample);\nvoid Stop_Sample_Playing(void const * sample);\nint Play_Sample(void const *sample, int priority=0xFF, int volume=0xFF, signed short panloc = 0x0);\nint Play_Sample_Handle(void const *sample, int priority, int volume, signed short panloc, int id);\nint Set_Sound_Vol(int volume);\nint Set_Score_Vol(int volume);\nvoid Fade_Sample(int handle, int ticks);\nint Get_Free_Sample_Handle(int priority);\nint Get_Digi_Handle(void);\nlong Sample_Length(void const *sample);\n\nextern int Misc;\nextern SFX_Type SoundType;\nextern Sample_Type SampleType;\n"
  },
  {
    "path": "WWFLAT32/AUDIO/AUDIO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : AUDIO.H                                  *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : March 10, 1995                           *\n *                                                                         *\n *                  Last Update : March 10, 1995   [PWG]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwstd.h\"\n\n/*=========================================================================*/\n/* AUD file header type\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tAUD_FLAG_STEREO\t1\n#define\tAUD_FLAG_16BIT\t\t2\n\n// PWG 3-14-95: This structure used to have bit fields defined for Stereo\n//   and Bits.  These were removed because watcom packs them into a 32 bit\n//   flag entry even though they could have fit in a 8 bit entry.\n#pragma pack(1);\ntypedef struct {\n\tshort int\tRate;\t\t\t\t// Playback rate (hertz).\n\tlong\tSize;\t\t\t\t// Size of data (bytes).\n\tlong\tUncompSize;\t\t\t\t// Size of data (bytes).\n\tunsigned char Flags;\t// Holds flags for info\n\t\t\t\t\t\t\t\t//  1: Is the sample stereo?\n\t\t\t\t\t\t\t\t//  2: Is the sample 16 bits?\n\tunsigned char Compression;\t// What kind of compression for this sample?\n} AUDHeaderType;\n\n\n/*=========================================================================*/\n/*\tThere can be a different sound driver for sound effects, digitized\t\t*/\n/*\tsamples, and musical scores.  Each one must be of these specified\t\t\t*/\n/*\ttypes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\ntypedef enum {\n\tSAMPLE_NONE,\t\t// No digitized sounds will be played.\n\tSAMPLE_SB,\t\t\t// Sound Blaster digitized driver.\n\tSAMPLE_SBPRO,\t\t// Sound Blaster Pro digitized driver.\n\tSAMPLE_PAS,\t\t\t// Pro-Audio Spectrum digitized driver.\n\tSAMPLE_ADLIBG,\t\t// Adlib-Gold digitized driver.\n\tSAMPLE_TANDY,\t\t// Tandy 'compatible' driver.\n\tSAMPLE_PCSPKR,\t\t// PC speaker digitized driver (The Audio Solution driver).\n\tSAMPLE_ADLIB,\t\t// Adlib digitized driver (The Audio Solution driver).\n\tSAMPLE_TEMP=0x1000,\n\tSAMPLE_LAST\n} Sample_Type;\n\ntypedef enum {\n\tSCORE_NONE,\t\t\t// No scores will be played.\n\tSCORE_ALFX,\t\t\t// Westwood's ALFX adlib compatable driver.\n\tSCORE_WWPCSPKR,\t// Westwood's PC-speaker driver (obsolete).\n\tSCORE_WWTANDY,\t\t// Westwood's PC-speaker driver with Tandy mod (obsolete).\n\tSCORE_PCSPKR,\t\t// PC speaker XMIDI driver.\n\tSCORE_TANDY,\t\t// Tandy XMIDI driver.\n\tSCORE_MT32,\t\t\t// MT-32 / LAPC-1 Roland XMIDI driver.\n\tSCORE_CANVAS,\t\t// Sound Canvas SC-55.\n\tSCORE_ADLIB,\t\t// Adlib XMIDI driver.\n\tSCORE_ADLIBG,\t\t// Adlib Gold XMIDI driver.\n\tSCORE_PASFM,\t\t// Pro Audio Spectrum XMIDI driver.\n\tSCORE_SBFM,\t\t\t// Sound Blaster XMIDI driver.\n\tSCORE_SBP1FM,\t\t// Sound Blaster Pro (YM3812) XMIDI driver.\n\tSCORE_SBP2FM,\t\t// Sound Blaster Pro (OPL3) XMIDI driver (Can't use with SFX_ALFX).\n\tSCORE_TEMP=0x1000,\n\tSCORE_LAST\n} Score_Type;\n\ntypedef enum {\n\tSFX_NONE,\t\t\t// No sound effects will be played.\n\tSFX_ALFX,\t\t\t// Westwood's ALFX adlib compatable driver.\n\tSFX_WWPCSPKR,\t\t// Westwood's PC-speaker driver.\n\tSFX_WWTANDY,\t\t// Westwood's PC-speaker driver with Tandy mod.\n\tSFX_PCSPKR,\t\t\t// PC speaker XMIDI driver.\n\tSFX_TANDY,\t\t\t// Tandy XMIDI driver.\n\tSFX_MT32,\t\t\t// MT-32 / LAPC-1 Roland XMIDI driver.\n\tSFX_CANVAS,\t\t\t// Sound Canvas SC-55.\n\tSFX_ADLIB,\t\t\t// Adlib XMIDI driver.\n\tSFX_ADLIBG,\t\t\t// Adlib Gold XMIDI driver.\n\tSFX_PASFM,\t\t\t// Pro Audio Spectrum XMIDI driver.\n\tSFX_SBFM,\t\t\t// Sound Blaster XMIDI driver.\n\tSFX_SBP1FM,\t\t\t// Sound Blaster Pro (YM3812) XMIDI driver.\n\tSFX_SBP2FM,\t\t\t// Sound Blaster Pro (OPL3) XMIDI driver.\n\tSFX_TEMP=0x1000,\n\tSFX_LAST\n} SFX_Type;\n\ntypedef enum RateEnum {\n\tPLAYBACK_RATE_SLOW =11025,\n\tPLAYBACK_RATE_NORMAL =(11025 * 2),\n\tPLAYBACK_RATE_FAST =(11025 * 4),\n} RateType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SOUNDIO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nint File_Stream_Sample(char const *filename, BOOL real_time_start = FALSE);\nint File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start = FALSE);\nvoid cdecl _saveregs Sound_Callback(void);\nvoid cdecl far __saveregs __loadds maintenance_callback(void);\nvoid *Load_Sample(char const *filename);\nlong Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);\nlong Sample_Read(int fh, void *buffer, long size);\nvoid Free_Sample(void const *sample);\nBOOL Sound_Init(int sfx, int score, int sample, RateType rate, int bits_per_sample, int max_samples, int reverse_channels);\nBOOL Audio_Init(int sample, int address, int inter, int dma, RateType rate, int bits_per_sample, int max_samples, int reverse_channels = FALSE);\nvoid Sound_End(void);\nvoid Stop_Sample(int handle);\nBOOL Sample_Status(int handle);\nBOOL Is_Sample_Playing(void const * sample);\nvoid Stop_Sample_Playing(void const * sample);\nint Play_Sample(void const *sample, int priority=0xFF, int volume=0xFF, signed short panloc = 0x0);\nint Play_Sample_Handle(void const *sample, int priority, int volume, signed short panloc, int id);\nint Set_Sound_Vol(int volume);\nint Set_Score_Vol(int volume);\nvoid Fade_Sample(int handle, int ticks);\nint Get_Free_Sample_Handle(int priority);\nint Get_Digi_Handle(void);\nlong Sample_Length(void const *sample);\n\nextern int Misc;\nextern SFX_Type SoundType;\nextern Sample_Type SampleType;\nextern short StreamLowImpact;\n"
  },
  {
    "path": "WWFLAT32/AUDIO/AUDUNCMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Audio Library            *\n;*                                                                         *\n;*                    File Name : AUDUNCMP.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : March 14, 1995                           *\n;*                                                                         *\n;*                  Last Update : June 26, 1995   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Decompress_Frame_Lock -- locks the JLB audio decompression code       *\n;*   Decompress_Frame_Unlock -- Unlocks the JLB audio compression code     *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\nDPMI_INTR\t\tequ\t31h\t\n\nLABEL \tLockedCodeStart\tBYTE\n\nCODE_2BIT\tEQU\t0\nCODE_4BIT\tEQU\t1\nCODE_RAW\tEQU\t2\nCODE_SILENCE\tEQU\t3\nMAGICNUMBER\tEQU\t00000DEAFh\nMAGICNUMBER2\tEQU\t0BABEBABEh\n\n_2bitdecode\tDB\t-2,-1,0,1\n_4bitdecode\tDB\t-9,-8,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,8\n\n\n;***************************************************************************\n;* DECOMPRESS_FRAME -- Uncompresses a WW compressed audio frame            *\n;*                                                                         *\n;* INPUT:\tvoid * source - pointer to encoded audio data              *\n;*\t\tvoid * dest   - pointer to decompression area\t\t   *\n;*\t\tlong size     - the maximum size of destination buffer\t   *\n;*                                                                         *\n;* OUTPUT:      long - the number of bytes we uncompressed                 *\n;*                                                                         *\n;* PROTO:\tlong Decompress_Frame(void *, void *, long);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/14/1995 PWG : Created.                                             *\n;*=========================================================================*\n\n\tGLOBAL\tDecompress_Frame:NEAR\n\tPROC\tDecompress_Frame C NEAR USES ebx ecx edx esi edi\n\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tcount:DWORD\n\n\tLOCAL\tprevious:BYTE\n\tLOCAL\tincount:DWORD\n\n\tpushf\n\tcld\n\tmov\t[incount],0\t;Bytes read from source\n\n\n;\tSource, Dest and count must be valid.\n\n\tcmp\t[source],0\n\tje\t??fini\n\n\tcmp\t[dest],0\n\tje\t??fini\n\n\tcmp\t[count],0\n\tje\t??fini\n\n\tmov\tesi,[source]\t;Pointer to source data.\n\tmov\tedi,[dest]\t;Pointer to destination data.\n\tmov\tecx,[count]\t;Number of bytes to fill dest buffer.\n\tmov\tdl,080h\t;Previous sample (starting value).\n\n??mainloop:\n\tcmp\tecx,0\t;If dest full then exit\n\tjle\t??fini\n\n\txor\teax,eax\n\tmov\tal,[esi]\t;Get code byte\n\tinc\t[incount]\n\tinc\tesi\n\tshl\teax,2\t;AH contains code.\n\tshr\tal,2\t;AL contains sub-code data.\n\n\tcmp\tah,CODE_RAW\t;Raw sequence?\n\tjne\tshort ??try4bit\n\n;\tThe code contains either a 5 bit delta or a count of\n;\traw samples to dump out.\n\n\ttest\tal,00100000b\n\tje\tshort ??justraw\n\n;\tThe lower 5 bits are actually a signed delta.\n;\tSign extend the delta and add it to the stream.\n\n\tshl\tal,3\n\tsar\tal,3\n\tadd\tdl,al\n\tmov\t[edi],dl\n\tdec\tecx\n\tinc\tedi\n\tjmp\t??mainloop\n\n;\tThe lower 5 bits hold a count of the number of raw\n;\tsamples that follow this code. Dump these samples to\n;\tthe output buffer.\n\n??justraw:\n\tmov\tebx,ecx\n\txor\tah,ah\n\tinc\tal\n\tmov\tecx,eax\n\tshr\tecx,1\n\trep\tmovsw\n\tadc\tecx,ecx\n\trep\tmovsb\n\tmov\tecx,ebx\n\tadd\t[incount],eax\n\tsub\tecx,eax\n\tdec\tedi\n\tmov\tdl,[edi]\t;Set \"previous\" value.\n\tinc\tedi\n\tjmp\t??mainloop\n\n;\tCheck to see if this is a 4 bit delta code sequence.\n\n??try4bit:\n\tinc\tal\t;Following codes use AL+1\n\tcmp\tah,CODE_4BIT\n\tjne\tshort ??try2bit\n\n;\tA sequence of 4bit deltas follow. AL equals the\n;\tnumber of nibble packed delta bytes to process.\n\n??bit4loop:\n\tmov\tah,[esi]\t;Fetch nibble packed delta codes\n\tmov\tbl,ah\n\tinc\t[incount]\n\tinc\tesi\n\n;\tAdd first delta to 'previous' sample already in DL.\n\n\tand\tebx,00001111b\n\tadd\tdl,[_4bitdecode+ebx]\n\tpushf\n\tcmp\t[_4bitdecode+ebx],0\n\tjl\tshort ??neg1\n\n\tpopf\n\tjnc\tshort ??ok1\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok1\n\n??neg1:\n\tpopf\n\tjc\tshort ??ok1\n\n\txor\tdl,dl\n\n??ok1:\n\tmov\tdh,dl\t;DH now holds new 'previous' sample.\n\tmov\tbl,ah\n\tshr\tbl,4\n\tadd\tdh,[_4bitdecode+ebx]\n\tpushf\n\tcmp\t[_4bitdecode+ebx],0\n\tjl\tshort ??neg2\n\n\tpopf\n\tjnc\tshort ??ok2\n\n\tmov\tdh,0FFh\n\tjmp\tshort ??ok2\n\n??neg2:\n\tpopf\n\tjc\tshort ??ok2\n\n\txor\tdh,dh\n\n??ok2:\n\tmov\t[edi],dx\t;Output the two sample bytes\n\tsub\tecx,2\n\tadd\tedi,2\n\n;\tPut the correct 'previous' sample in DL where it belongs.\n\n\tmov\tdl,dh\n\n;\tIf there are more deltas to process then loop back.\n\n\tdec\tal\n\tjnz\tshort ??bit4loop\n\tjmp\t??mainloop\n\n;\tCheck to see if 2 bit deltas need to be processed.\n\n??try2bit:\n\tcmp\tah,CODE_2BIT\n\tjne\t??zerodelta\n\n;\tA sequence of 2bit deltas follow.  AL equals the number of \n;\tpacked delta bytes to process.\n\n??bit2loop:\n\tmov\tah,[esi]\t;Fetch packed delat codes\n\tinc\t[incount]\n\tinc\tesi\n\n;\tAdd first delta to 'previous' sample already in DL.\n\n\tmov\tbl,ah\n\tand\tebx,000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushf\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg3\n\n\tpopf\n\tjnc\tshort ??ok3\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok3\n\n??neg3:\n\tpopf\n\tjc\tshort ??ok3\n\txor\tdl,dl\n\n??ok3:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,2\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushf\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg4\n\n\tpopf\n\tjnc\tshort ??ok4\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok4\n\n??neg4:\n\tpopf\n\tjc\tshort ??ok4\n\n\txor\tdl,dl\n\n??ok4:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,4\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushf\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg5\n\n\tpopf\n\tjnc\tshort ??ok5\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok5\n\n??neg5:\n\tpopf\n\tjc\tshort ??ok5\n\n\txor\tdl,dl\n\n??ok5:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,6\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushf\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg6\n\n\tpopf\n\tjnc\tshort ??ok6\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok6\n\n??neg6:\n\tpopf\n\tjc\tshort ??ok6\n\n\txor\tdl,dl\n\n??ok6:\n\tror\tedx,8\n\tmov\t[edi],edx\t;Output two sample bytes\n\tsub\tecx,4\n\tadd\tedi,4\n\n;\tPut the correct 'previous' sample in DL where it belongs.\n\n\trol\tedx,8\n\n;\tIf there are more deltas to process then loop back.\n\n\tdec\tal\n\tjnz\t??bit2loop\n\tjmp\t??mainloop\n\n;\tThere is a run of zero deltas.  Zero deltas merely duplicate\n;\tthe 'previous' sample the requested number of times.\n\n??zerodelta:\n\txor\tebx,ebx\n\tmov\tbl,al\n\tmov\tal,dl\n\tsub\tecx,ebx\n\txchg\tecx,ebx\n\trep\tstosb\n\tmov\tecx,ebx\n\tjmp\t??mainloop\n\n??fini:\n\tpopf\n\tmov\teax,[incount]\n\tret\n\n\tENDP\tDecompress_Frame\n\nLABEL \tLockedCodeEnd\tBYTE\n\n\n;***************************************************************************\n;* DECOMPRESS_FRAME_LOCK -- locks the JLB audio decompression code         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is lock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:       BOOL Decompress_Frame_Lock(void);                          *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tDecompress_Frame_Lock:NEAR\n\tPROC\tDecompress_Frame_Lock C NEAR USES ebx ecx edx esi edi\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n  \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\n\tENDP\tDecompress_Frame_Lock\n\n;***************************************************************************\n;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code       *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is unlock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:\tBOOL Decompress_Frame_Unlock(void);                        *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tDecompress_Frame_Unlock:NEAR\n\tPROC\tDecompress_Frame_Unlock C NEAR USES ebx ecx edx esi edi\n\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\n\tENDP\tDecompress_Frame_Unlock\n\n\n\n\tEND\n"
  },
  {
    "path": "WWFLAT32/AUDIO/DIFFTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* dwDiffTable - ADPCM Lookup table for sample differences\n;****************************************************************************\n\n\t\talign\t4\n\ndwDiffTable\tDD\t0\t; Index = 0 Token = 0\n\t\tDD\t1\t; Index = 0 Token = 1\n\t\tDD\t3\t; Index = 0 Token = 2\n\t\tDD\t4\t; Index = 0 Token = 3\n\t\tDD\t7\t; Index = 0 Token = 4\n\t\tDD\t8\t; Index = 0 Token = 5\n\t\tDD\t10\t; Index = 0 Token = 6\n\t\tDD\t11\t; Index = 0 Token = 7\n\t\tDD\t0\t; Index = 0 Token = 8\n\t\tDD\t-1\t; Index = 0 Token = 9\n\t\tDD\t-3\t; Index = 0 Token = 10\n\t\tDD\t-4\t; Index = 0 Token = 11\n\t\tDD\t-7\t; Index = 0 Token = 12\n\t\tDD\t-8\t; Index = 0 Token = 13\n\t\tDD\t-10\t; Index = 0 Token = 14\n\t\tDD\t-11\t; Index = 0 Token = 15\n\t\tDD\t1\t; Index = 1 Token = 0\n\t\tDD\t3\t; Index = 1 Token = 1\n\t\tDD\t5\t; Index = 1 Token = 2\n\t\tDD\t7\t; Index = 1 Token = 3\n\t\tDD\t9\t; Index = 1 Token = 4\n\t\tDD\t11\t; Index = 1 Token = 5\n\t\tDD\t13\t; Index = 1 Token = 6\n\t\tDD\t15\t; Index = 1 Token = 7\n\t\tDD\t-1\t; Index = 1 Token = 8\n\t\tDD\t-3\t; Index = 1 Token = 9\n\t\tDD\t-5\t; Index = 1 Token = 10\n\t\tDD\t-7\t; Index = 1 Token = 11\n\t\tDD\t-9\t; Index = 1 Token = 12\n\t\tDD\t-11\t; Index = 1 Token = 13\n\t\tDD\t-13\t; Index = 1 Token = 14\n\t\tDD\t-15\t; Index = 1 Token = 15\n\t\tDD\t1\t; Index = 2 Token = 0\n\t\tDD\t3\t; Index = 2 Token = 1\n\t\tDD\t5\t; Index = 2 Token = 2\n\t\tDD\t7\t; Index = 2 Token = 3\n\t\tDD\t10\t; Index = 2 Token = 4\n\t\tDD\t12\t; Index = 2 Token = 5\n\t\tDD\t14\t; Index = 2 Token = 6\n\t\tDD\t16\t; Index = 2 Token = 7\n\t\tDD\t-1\t; Index = 2 Token = 8\n\t\tDD\t-3\t; Index = 2 Token = 9\n\t\tDD\t-5\t; Index = 2 Token = 10\n\t\tDD\t-7\t; Index = 2 Token = 11\n\t\tDD\t-10\t; Index = 2 Token = 12\n\t\tDD\t-12\t; Index = 2 Token = 13\n\t\tDD\t-14\t; Index = 2 Token = 14\n\t\tDD\t-16\t; Index = 2 Token = 15\n\t\tDD\t1\t; Index = 3 Token = 0\n\t\tDD\t3\t; Index = 3 Token = 1\n\t\tDD\t6\t; Index = 3 Token = 2\n\t\tDD\t8\t; Index = 3 Token = 3\n\t\tDD\t11\t; Index = 3 Token = 4\n\t\tDD\t13\t; Index = 3 Token = 5\n\t\tDD\t16\t; Index = 3 Token = 6\n\t\tDD\t18\t; Index = 3 Token = 7\n\t\tDD\t-1\t; Index = 3 Token = 8\n\t\tDD\t-3\t; Index = 3 Token = 9\n\t\tDD\t-6\t; Index = 3 Token = 10\n\t\tDD\t-8\t; Index = 3 Token = 11\n\t\tDD\t-11\t; Index = 3 Token = 12\n\t\tDD\t-13\t; Index = 3 Token = 13\n\t\tDD\t-16\t; Index = 3 Token = 14\n\t\tDD\t-18\t; Index = 3 Token = 15\n\t\tDD\t1\t; Index = 4 Token = 0\n\t\tDD\t3\t; Index = 4 Token = 1\n\t\tDD\t6\t; Index = 4 Token = 2\n\t\tDD\t8\t; Index = 4 Token = 3\n\t\tDD\t12\t; Index = 4 Token = 4\n\t\tDD\t14\t; Index = 4 Token = 5\n\t\tDD\t17\t; Index = 4 Token = 6\n\t\tDD\t19\t; Index = 4 Token = 7\n\t\tDD\t-1\t; Index = 4 Token = 8\n\t\tDD\t-3\t; Index = 4 Token = 9\n\t\tDD\t-6\t; Index = 4 Token = 10\n\t\tDD\t-8\t; Index = 4 Token = 11\n\t\tDD\t-12\t; Index = 4 Token = 12\n\t\tDD\t-14\t; Index = 4 Token = 13\n\t\tDD\t-17\t; Index = 4 Token = 14\n\t\tDD\t-19\t; Index = 4 Token = 15\n\t\tDD\t1\t; Index = 5 Token = 0\n\t\tDD\t4\t; Index = 5 Token = 1\n\t\tDD\t7\t; Index = 5 Token = 2\n\t\tDD\t10\t; Index = 5 Token = 3\n\t\tDD\t13\t; Index = 5 Token = 4\n\t\tDD\t16\t; Index = 5 Token = 5\n\t\tDD\t19\t; Index = 5 Token = 6\n\t\tDD\t22\t; Index = 5 Token = 7\n\t\tDD\t-1\t; Index = 5 Token = 8\n\t\tDD\t-4\t; Index = 5 Token = 9\n\t\tDD\t-7\t; Index = 5 Token = 10\n\t\tDD\t-10\t; Index = 5 Token = 11\n\t\tDD\t-13\t; Index = 5 Token = 12\n\t\tDD\t-16\t; Index = 5 Token = 13\n\t\tDD\t-19\t; Index = 5 Token = 14\n\t\tDD\t-22\t; Index = 5 Token = 15\n\t\tDD\t1\t; Index = 6 Token = 0\n\t\tDD\t4\t; Index = 6 Token = 1\n\t\tDD\t7\t; Index = 6 Token = 2\n\t\tDD\t10\t; Index = 6 Token = 3\n\t\tDD\t14\t; Index = 6 Token = 4\n\t\tDD\t17\t; Index = 6 Token = 5\n\t\tDD\t20\t; Index = 6 Token = 6\n\t\tDD\t23\t; Index = 6 Token = 7\n\t\tDD\t-1\t; Index = 6 Token = 8\n\t\tDD\t-4\t; Index = 6 Token = 9\n\t\tDD\t-7\t; Index = 6 Token = 10\n\t\tDD\t-10\t; Index = 6 Token = 11\n\t\tDD\t-14\t; Index = 6 Token = 12\n\t\tDD\t-17\t; Index = 6 Token = 13\n\t\tDD\t-20\t; Index = 6 Token = 14\n\t\tDD\t-23\t; Index = 6 Token = 15\n\t\tDD\t1\t; Index = 7 Token = 0\n\t\tDD\t4\t; Index = 7 Token = 1\n\t\tDD\t8\t; Index = 7 Token = 2\n\t\tDD\t11\t; Index = 7 Token = 3\n\t\tDD\t15\t; Index = 7 Token = 4\n\t\tDD\t18\t; Index = 7 Token = 5\n\t\tDD\t22\t; Index = 7 Token = 6\n\t\tDD\t25\t; Index = 7 Token = 7\n\t\tDD\t-1\t; Index = 7 Token = 8\n\t\tDD\t-4\t; Index = 7 Token = 9\n\t\tDD\t-8\t; Index = 7 Token = 10\n\t\tDD\t-11\t; Index = 7 Token = 11\n\t\tDD\t-15\t; Index = 7 Token = 12\n\t\tDD\t-18\t; Index = 7 Token = 13\n\t\tDD\t-22\t; Index = 7 Token = 14\n\t\tDD\t-25\t; Index = 7 Token = 15\n\t\tDD\t2\t; Index = 8 Token = 0\n\t\tDD\t6\t; Index = 8 Token = 1\n\t\tDD\t10\t; Index = 8 Token = 2\n\t\tDD\t14\t; Index = 8 Token = 3\n\t\tDD\t18\t; Index = 8 Token = 4\n\t\tDD\t22\t; Index = 8 Token = 5\n\t\tDD\t26\t; Index = 8 Token = 6\n\t\tDD\t30\t; Index = 8 Token = 7\n\t\tDD\t-2\t; Index = 8 Token = 8\n\t\tDD\t-6\t; Index = 8 Token = 9\n\t\tDD\t-10\t; Index = 8 Token = 10\n\t\tDD\t-14\t; Index = 8 Token = 11\n\t\tDD\t-18\t; Index = 8 Token = 12\n\t\tDD\t-22\t; Index = 8 Token = 13\n\t\tDD\t-26\t; Index = 8 Token = 14\n\t\tDD\t-30\t; Index = 8 Token = 15\n\t\tDD\t2\t; Index = 9 Token = 0\n\t\tDD\t6\t; Index = 9 Token = 1\n\t\tDD\t10\t; Index = 9 Token = 2\n\t\tDD\t14\t; Index = 9 Token = 3\n\t\tDD\t19\t; Index = 9 Token = 4\n\t\tDD\t23\t; Index = 9 Token = 5\n\t\tDD\t27\t; Index = 9 Token = 6\n\t\tDD\t31\t; Index = 9 Token = 7\n\t\tDD\t-2\t; Index = 9 Token = 8\n\t\tDD\t-6\t; Index = 9 Token = 9\n\t\tDD\t-10\t; Index = 9 Token = 10\n\t\tDD\t-14\t; Index = 9 Token = 11\n\t\tDD\t-19\t; Index = 9 Token = 12\n\t\tDD\t-23\t; Index = 9 Token = 13\n\t\tDD\t-27\t; Index = 9 Token = 14\n\t\tDD\t-31\t; Index = 9 Token = 15\n\t\tDD\t2\t; Index = 10 Token = 0\n\t\tDD\t6\t; Index = 10 Token = 1\n\t\tDD\t11\t; Index = 10 Token = 2\n\t\tDD\t15\t; Index = 10 Token = 3\n\t\tDD\t21\t; Index = 10 Token = 4\n\t\tDD\t25\t; Index = 10 Token = 5\n\t\tDD\t30\t; Index = 10 Token = 6\n\t\tDD\t34\t; Index = 10 Token = 7\n\t\tDD\t-2\t; Index = 10 Token = 8\n\t\tDD\t-6\t; Index = 10 Token = 9\n\t\tDD\t-11\t; Index = 10 Token = 10\n\t\tDD\t-15\t; Index = 10 Token = 11\n\t\tDD\t-21\t; Index = 10 Token = 12\n\t\tDD\t-25\t; Index = 10 Token = 13\n\t\tDD\t-30\t; Index = 10 Token = 14\n\t\tDD\t-34\t; Index = 10 Token = 15\n\t\tDD\t2\t; Index = 11 Token = 0\n\t\tDD\t7\t; Index = 11 Token = 1\n\t\tDD\t12\t; Index = 11 Token = 2\n\t\tDD\t17\t; Index = 11 Token = 3\n\t\tDD\t23\t; Index = 11 Token = 4\n\t\tDD\t28\t; Index = 11 Token = 5\n\t\tDD\t33\t; Index = 11 Token = 6\n\t\tDD\t38\t; Index = 11 Token = 7\n\t\tDD\t-2\t; Index = 11 Token = 8\n\t\tDD\t-7\t; Index = 11 Token = 9\n\t\tDD\t-12\t; Index = 11 Token = 10\n\t\tDD\t-17\t; Index = 11 Token = 11\n\t\tDD\t-23\t; Index = 11 Token = 12\n\t\tDD\t-28\t; Index = 11 Token = 13\n\t\tDD\t-33\t; Index = 11 Token = 14\n\t\tDD\t-38\t; Index = 11 Token = 15\n\t\tDD\t2\t; Index = 12 Token = 0\n\t\tDD\t7\t; Index = 12 Token = 1\n\t\tDD\t13\t; Index = 12 Token = 2\n\t\tDD\t18\t; Index = 12 Token = 3\n\t\tDD\t25\t; Index = 12 Token = 4\n\t\tDD\t30\t; Index = 12 Token = 5\n\t\tDD\t36\t; Index = 12 Token = 6\n\t\tDD\t41\t; Index = 12 Token = 7\n\t\tDD\t-2\t; Index = 12 Token = 8\n\t\tDD\t-7\t; Index = 12 Token = 9\n\t\tDD\t-13\t; Index = 12 Token = 10\n\t\tDD\t-18\t; Index = 12 Token = 11\n\t\tDD\t-25\t; Index = 12 Token = 12\n\t\tDD\t-30\t; Index = 12 Token = 13\n\t\tDD\t-36\t; Index = 12 Token = 14\n\t\tDD\t-41\t; Index = 12 Token = 15\n\t\tDD\t3\t; Index = 13 Token = 0\n\t\tDD\t9\t; Index = 13 Token = 1\n\t\tDD\t15\t; Index = 13 Token = 2\n\t\tDD\t21\t; Index = 13 Token = 3\n\t\tDD\t28\t; Index = 13 Token = 4\n\t\tDD\t34\t; Index = 13 Token = 5\n\t\tDD\t40\t; Index = 13 Token = 6\n\t\tDD\t46\t; Index = 13 Token = 7\n\t\tDD\t-3\t; Index = 13 Token = 8\n\t\tDD\t-9\t; Index = 13 Token = 9\n\t\tDD\t-15\t; Index = 13 Token = 10\n\t\tDD\t-21\t; Index = 13 Token = 11\n\t\tDD\t-28\t; Index = 13 Token = 12\n\t\tDD\t-34\t; Index = 13 Token = 13\n\t\tDD\t-40\t; Index = 13 Token = 14\n\t\tDD\t-46\t; Index = 13 Token = 15\n\t\tDD\t3\t; Index = 14 Token = 0\n\t\tDD\t10\t; Index = 14 Token = 1\n\t\tDD\t17\t; Index = 14 Token = 2\n\t\tDD\t24\t; Index = 14 Token = 3\n\t\tDD\t31\t; Index = 14 Token = 4\n\t\tDD\t38\t; Index = 14 Token = 5\n\t\tDD\t45\t; Index = 14 Token = 6\n\t\tDD\t52\t; Index = 14 Token = 7\n\t\tDD\t-3\t; Index = 14 Token = 8\n\t\tDD\t-10\t; Index = 14 Token = 9\n\t\tDD\t-17\t; Index = 14 Token = 10\n\t\tDD\t-24\t; Index = 14 Token = 11\n\t\tDD\t-31\t; Index = 14 Token = 12\n\t\tDD\t-38\t; Index = 14 Token = 13\n\t\tDD\t-45\t; Index = 14 Token = 14\n\t\tDD\t-52\t; Index = 14 Token = 15\n\t\tDD\t3\t; Index = 15 Token = 0\n\t\tDD\t10\t; Index = 15 Token = 1\n\t\tDD\t18\t; Index = 15 Token = 2\n\t\tDD\t25\t; Index = 15 Token = 3\n\t\tDD\t34\t; Index = 15 Token = 4\n\t\tDD\t41\t; Index = 15 Token = 5\n\t\tDD\t49\t; Index = 15 Token = 6\n\t\tDD\t56\t; Index = 15 Token = 7\n\t\tDD\t-3\t; Index = 15 Token = 8\n\t\tDD\t-10\t; Index = 15 Token = 9\n\t\tDD\t-18\t; Index = 15 Token = 10\n\t\tDD\t-25\t; Index = 15 Token = 11\n\t\tDD\t-34\t; Index = 15 Token = 12\n\t\tDD\t-41\t; Index = 15 Token = 13\n\t\tDD\t-49\t; Index = 15 Token = 14\n\t\tDD\t-56\t; Index = 15 Token = 15\n\t\tDD\t4\t; Index = 16 Token = 0\n\t\tDD\t12\t; Index = 16 Token = 1\n\t\tDD\t21\t; Index = 16 Token = 2\n\t\tDD\t29\t; Index = 16 Token = 3\n\t\tDD\t38\t; Index = 16 Token = 4\n\t\tDD\t46\t; Index = 16 Token = 5\n\t\tDD\t55\t; Index = 16 Token = 6\n\t\tDD\t63\t; Index = 16 Token = 7\n\t\tDD\t-4\t; Index = 16 Token = 8\n\t\tDD\t-12\t; Index = 16 Token = 9\n\t\tDD\t-21\t; Index = 16 Token = 10\n\t\tDD\t-29\t; Index = 16 Token = 11\n\t\tDD\t-38\t; Index = 16 Token = 12\n\t\tDD\t-46\t; Index = 16 Token = 13\n\t\tDD\t-55\t; Index = 16 Token = 14\n\t\tDD\t-63\t; Index = 16 Token = 15\n\t\tDD\t4\t; Index = 17 Token = 0\n\t\tDD\t13\t; Index = 17 Token = 1\n\t\tDD\t22\t; Index = 17 Token = 2\n\t\tDD\t31\t; Index = 17 Token = 3\n\t\tDD\t41\t; Index = 17 Token = 4\n\t\tDD\t50\t; Index = 17 Token = 5\n\t\tDD\t59\t; Index = 17 Token = 6\n\t\tDD\t68\t; Index = 17 Token = 7\n\t\tDD\t-4\t; Index = 17 Token = 8\n\t\tDD\t-13\t; Index = 17 Token = 9\n\t\tDD\t-22\t; Index = 17 Token = 10\n\t\tDD\t-31\t; Index = 17 Token = 11\n\t\tDD\t-41\t; Index = 17 Token = 12\n\t\tDD\t-50\t; Index = 17 Token = 13\n\t\tDD\t-59\t; Index = 17 Token = 14\n\t\tDD\t-68\t; Index = 17 Token = 15\n\t\tDD\t5\t; Index = 18 Token = 0\n\t\tDD\t15\t; Index = 18 Token = 1\n\t\tDD\t25\t; Index = 18 Token = 2\n\t\tDD\t35\t; Index = 18 Token = 3\n\t\tDD\t46\t; Index = 18 Token = 4\n\t\tDD\t56\t; Index = 18 Token = 5\n\t\tDD\t66\t; Index = 18 Token = 6\n\t\tDD\t76\t; Index = 18 Token = 7\n\t\tDD\t-5\t; Index = 18 Token = 8\n\t\tDD\t-15\t; Index = 18 Token = 9\n\t\tDD\t-25\t; Index = 18 Token = 10\n\t\tDD\t-35\t; Index = 18 Token = 11\n\t\tDD\t-46\t; Index = 18 Token = 12\n\t\tDD\t-56\t; Index = 18 Token = 13\n\t\tDD\t-66\t; Index = 18 Token = 14\n\t\tDD\t-76\t; Index = 18 Token = 15\n\t\tDD\t5\t; Index = 19 Token = 0\n\t\tDD\t16\t; Index = 19 Token = 1\n\t\tDD\t27\t; Index = 19 Token = 2\n\t\tDD\t38\t; Index = 19 Token = 3\n\t\tDD\t50\t; Index = 19 Token = 4\n\t\tDD\t61\t; Index = 19 Token = 5\n\t\tDD\t72\t; Index = 19 Token = 6\n\t\tDD\t83\t; Index = 19 Token = 7\n\t\tDD\t-5\t; Index = 19 Token = 8\n\t\tDD\t-16\t; Index = 19 Token = 9\n\t\tDD\t-27\t; Index = 19 Token = 10\n\t\tDD\t-38\t; Index = 19 Token = 11\n\t\tDD\t-50\t; Index = 19 Token = 12\n\t\tDD\t-61\t; Index = 19 Token = 13\n\t\tDD\t-72\t; Index = 19 Token = 14\n\t\tDD\t-83\t; Index = 19 Token = 15\n\t\tDD\t6\t; Index = 20 Token = 0\n\t\tDD\t18\t; Index = 20 Token = 1\n\t\tDD\t31\t; Index = 20 Token = 2\n\t\tDD\t43\t; Index = 20 Token = 3\n\t\tDD\t56\t; Index = 20 Token = 4\n\t\tDD\t68\t; Index = 20 Token = 5\n\t\tDD\t81\t; Index = 20 Token = 6\n\t\tDD\t93\t; Index = 20 Token = 7\n\t\tDD\t-6\t; Index = 20 Token = 8\n\t\tDD\t-18\t; Index = 20 Token = 9\n\t\tDD\t-31\t; Index = 20 Token = 10\n\t\tDD\t-43\t; Index = 20 Token = 11\n\t\tDD\t-56\t; Index = 20 Token = 12\n\t\tDD\t-68\t; Index = 20 Token = 13\n\t\tDD\t-81\t; Index = 20 Token = 14\n\t\tDD\t-93\t; Index = 20 Token = 15\n\t\tDD\t6\t; Index = 21 Token = 0\n\t\tDD\t19\t; Index = 21 Token = 1\n\t\tDD\t33\t; Index = 21 Token = 2\n\t\tDD\t46\t; Index = 21 Token = 3\n\t\tDD\t61\t; Index = 21 Token = 4\n\t\tDD\t74\t; Index = 21 Token = 5\n\t\tDD\t88\t; Index = 21 Token = 6\n\t\tDD\t101\t; Index = 21 Token = 7\n\t\tDD\t-6\t; Index = 21 Token = 8\n\t\tDD\t-19\t; Index = 21 Token = 9\n\t\tDD\t-33\t; Index = 21 Token = 10\n\t\tDD\t-46\t; Index = 21 Token = 11\n\t\tDD\t-61\t; Index = 21 Token = 12\n\t\tDD\t-74\t; Index = 21 Token = 13\n\t\tDD\t-88\t; Index = 21 Token = 14\n\t\tDD\t-101\t; Index = 21 Token = 15\n\t\tDD\t7\t; Index = 22 Token = 0\n\t\tDD\t22\t; Index = 22 Token = 1\n\t\tDD\t37\t; Index = 22 Token = 2\n\t\tDD\t52\t; Index = 22 Token = 3\n\t\tDD\t67\t; Index = 22 Token = 4\n\t\tDD\t82\t; Index = 22 Token = 5\n\t\tDD\t97\t; Index = 22 Token = 6\n\t\tDD\t112\t; Index = 22 Token = 7\n\t\tDD\t-7\t; Index = 22 Token = 8\n\t\tDD\t-22\t; Index = 22 Token = 9\n\t\tDD\t-37\t; Index = 22 Token = 10\n\t\tDD\t-52\t; Index = 22 Token = 11\n\t\tDD\t-67\t; Index = 22 Token = 12\n\t\tDD\t-82\t; Index = 22 Token = 13\n\t\tDD\t-97\t; Index = 22 Token = 14\n\t\tDD\t-112\t; Index = 22 Token = 15\n\t\tDD\t8\t; Index = 23 Token = 0\n\t\tDD\t24\t; Index = 23 Token = 1\n\t\tDD\t41\t; Index = 23 Token = 2\n\t\tDD\t57\t; Index = 23 Token = 3\n\t\tDD\t74\t; Index = 23 Token = 4\n\t\tDD\t90\t; Index = 23 Token = 5\n\t\tDD\t107\t; Index = 23 Token = 6\n\t\tDD\t123\t; Index = 23 Token = 7\n\t\tDD\t-8\t; Index = 23 Token = 8\n\t\tDD\t-24\t; Index = 23 Token = 9\n\t\tDD\t-41\t; Index = 23 Token = 10\n\t\tDD\t-57\t; Index = 23 Token = 11\n\t\tDD\t-74\t; Index = 23 Token = 12\n\t\tDD\t-90\t; Index = 23 Token = 13\n\t\tDD\t-107\t; Index = 23 Token = 14\n\t\tDD\t-123\t; Index = 23 Token = 15\n\t\tDD\t9\t; Index = 24 Token = 0\n\t\tDD\t27\t; Index = 24 Token = 1\n\t\tDD\t45\t; Index = 24 Token = 2\n\t\tDD\t63\t; Index = 24 Token = 3\n\t\tDD\t82\t; Index = 24 Token = 4\n\t\tDD\t100\t; Index = 24 Token = 5\n\t\tDD\t118\t; Index = 24 Token = 6\n\t\tDD\t136\t; Index = 24 Token = 7\n\t\tDD\t-9\t; Index = 24 Token = 8\n\t\tDD\t-27\t; Index = 24 Token = 9\n\t\tDD\t-45\t; Index = 24 Token = 10\n\t\tDD\t-63\t; Index = 24 Token = 11\n\t\tDD\t-82\t; Index = 24 Token = 12\n\t\tDD\t-100\t; Index = 24 Token = 13\n\t\tDD\t-118\t; Index = 24 Token = 14\n\t\tDD\t-136\t; Index = 24 Token = 15\n\t\tDD\t10\t; Index = 25 Token = 0\n\t\tDD\t30\t; Index = 25 Token = 1\n\t\tDD\t50\t; Index = 25 Token = 2\n\t\tDD\t70\t; Index = 25 Token = 3\n\t\tDD\t90\t; Index = 25 Token = 4\n\t\tDD\t110\t; Index = 25 Token = 5\n\t\tDD\t130\t; Index = 25 Token = 6\n\t\tDD\t150\t; Index = 25 Token = 7\n\t\tDD\t-10\t; Index = 25 Token = 8\n\t\tDD\t-30\t; Index = 25 Token = 9\n\t\tDD\t-50\t; Index = 25 Token = 10\n\t\tDD\t-70\t; Index = 25 Token = 11\n\t\tDD\t-90\t; Index = 25 Token = 12\n\t\tDD\t-110\t; Index = 25 Token = 13\n\t\tDD\t-130\t; Index = 25 Token = 14\n\t\tDD\t-150\t; Index = 25 Token = 15\n\t\tDD\t11\t; Index = 26 Token = 0\n\t\tDD\t33\t; Index = 26 Token = 1\n\t\tDD\t55\t; Index = 26 Token = 2\n\t\tDD\t77\t; Index = 26 Token = 3\n\t\tDD\t99\t; Index = 26 Token = 4\n\t\tDD\t121\t; Index = 26 Token = 5\n\t\tDD\t143\t; Index = 26 Token = 6\n\t\tDD\t165\t; Index = 26 Token = 7\n\t\tDD\t-11\t; Index = 26 Token = 8\n\t\tDD\t-33\t; Index = 26 Token = 9\n\t\tDD\t-55\t; Index = 26 Token = 10\n\t\tDD\t-77\t; Index = 26 Token = 11\n\t\tDD\t-99\t; Index = 26 Token = 12\n\t\tDD\t-121\t; Index = 26 Token = 13\n\t\tDD\t-143\t; Index = 26 Token = 14\n\t\tDD\t-165\t; Index = 26 Token = 15\n\t\tDD\t12\t; Index = 27 Token = 0\n\t\tDD\t36\t; Index = 27 Token = 1\n\t\tDD\t60\t; Index = 27 Token = 2\n\t\tDD\t84\t; Index = 27 Token = 3\n\t\tDD\t109\t; Index = 27 Token = 4\n\t\tDD\t133\t; Index = 27 Token = 5\n\t\tDD\t157\t; Index = 27 Token = 6\n\t\tDD\t181\t; Index = 27 Token = 7\n\t\tDD\t-12\t; Index = 27 Token = 8\n\t\tDD\t-36\t; Index = 27 Token = 9\n\t\tDD\t-60\t; Index = 27 Token = 10\n\t\tDD\t-84\t; Index = 27 Token = 11\n\t\tDD\t-109\t; Index = 27 Token = 12\n\t\tDD\t-133\t; Index = 27 Token = 13\n\t\tDD\t-157\t; Index = 27 Token = 14\n\t\tDD\t-181\t; Index = 27 Token = 15\n\t\tDD\t13\t; Index = 28 Token = 0\n\t\tDD\t39\t; Index = 28 Token = 1\n\t\tDD\t66\t; Index = 28 Token = 2\n\t\tDD\t92\t; Index = 28 Token = 3\n\t\tDD\t120\t; Index = 28 Token = 4\n\t\tDD\t146\t; Index = 28 Token = 5\n\t\tDD\t173\t; Index = 28 Token = 6\n\t\tDD\t199\t; Index = 28 Token = 7\n\t\tDD\t-13\t; Index = 28 Token = 8\n\t\tDD\t-39\t; Index = 28 Token = 9\n\t\tDD\t-66\t; Index = 28 Token = 10\n\t\tDD\t-92\t; Index = 28 Token = 11\n\t\tDD\t-120\t; Index = 28 Token = 12\n\t\tDD\t-146\t; Index = 28 Token = 13\n\t\tDD\t-173\t; Index = 28 Token = 14\n\t\tDD\t-199\t; Index = 28 Token = 15\n\t\tDD\t14\t; Index = 29 Token = 0\n\t\tDD\t43\t; Index = 29 Token = 1\n\t\tDD\t73\t; Index = 29 Token = 2\n\t\tDD\t102\t; Index = 29 Token = 3\n\t\tDD\t132\t; Index = 29 Token = 4\n\t\tDD\t161\t; Index = 29 Token = 5\n\t\tDD\t191\t; Index = 29 Token = 6\n\t\tDD\t220\t; Index = 29 Token = 7\n\t\tDD\t-14\t; Index = 29 Token = 8\n\t\tDD\t-43\t; Index = 29 Token = 9\n\t\tDD\t-73\t; Index = 29 Token = 10\n\t\tDD\t-102\t; Index = 29 Token = 11\n\t\tDD\t-132\t; Index = 29 Token = 12\n\t\tDD\t-161\t; Index = 29 Token = 13\n\t\tDD\t-191\t; Index = 29 Token = 14\n\t\tDD\t-220\t; Index = 29 Token = 15\n\t\tDD\t16\t; Index = 30 Token = 0\n\t\tDD\t48\t; Index = 30 Token = 1\n\t\tDD\t81\t; Index = 30 Token = 2\n\t\tDD\t113\t; Index = 30 Token = 3\n\t\tDD\t146\t; Index = 30 Token = 4\n\t\tDD\t178\t; Index = 30 Token = 5\n\t\tDD\t211\t; Index = 30 Token = 6\n\t\tDD\t243\t; Index = 30 Token = 7\n\t\tDD\t-16\t; Index = 30 Token = 8\n\t\tDD\t-48\t; Index = 30 Token = 9\n\t\tDD\t-81\t; Index = 30 Token = 10\n\t\tDD\t-113\t; Index = 30 Token = 11\n\t\tDD\t-146\t; Index = 30 Token = 12\n\t\tDD\t-178\t; Index = 30 Token = 13\n\t\tDD\t-211\t; Index = 30 Token = 14\n\t\tDD\t-243\t; Index = 30 Token = 15\n\t\tDD\t17\t; Index = 31 Token = 0\n\t\tDD\t52\t; Index = 31 Token = 1\n\t\tDD\t88\t; Index = 31 Token = 2\n\t\tDD\t123\t; Index = 31 Token = 3\n\t\tDD\t160\t; Index = 31 Token = 4\n\t\tDD\t195\t; Index = 31 Token = 5\n\t\tDD\t231\t; Index = 31 Token = 6\n\t\tDD\t266\t; Index = 31 Token = 7\n\t\tDD\t-17\t; Index = 31 Token = 8\n\t\tDD\t-52\t; Index = 31 Token = 9\n\t\tDD\t-88\t; Index = 31 Token = 10\n\t\tDD\t-123\t; Index = 31 Token = 11\n\t\tDD\t-160\t; Index = 31 Token = 12\n\t\tDD\t-195\t; Index = 31 Token = 13\n\t\tDD\t-231\t; Index = 31 Token = 14\n\t\tDD\t-266\t; Index = 31 Token = 15\n\t\tDD\t19\t; Index = 32 Token = 0\n\t\tDD\t58\t; Index = 32 Token = 1\n\t\tDD\t97\t; Index = 32 Token = 2\n\t\tDD\t136\t; Index = 32 Token = 3\n\t\tDD\t176\t; Index = 32 Token = 4\n\t\tDD\t215\t; Index = 32 Token = 5\n\t\tDD\t254\t; Index = 32 Token = 6\n\t\tDD\t293\t; Index = 32 Token = 7\n\t\tDD\t-19\t; Index = 32 Token = 8\n\t\tDD\t-58\t; Index = 32 Token = 9\n\t\tDD\t-97\t; Index = 32 Token = 10\n\t\tDD\t-136\t; Index = 32 Token = 11\n\t\tDD\t-176\t; Index = 32 Token = 12\n\t\tDD\t-215\t; Index = 32 Token = 13\n\t\tDD\t-254\t; Index = 32 Token = 14\n\t\tDD\t-293\t; Index = 32 Token = 15\n\t\tDD\t21\t; Index = 33 Token = 0\n\t\tDD\t64\t; Index = 33 Token = 1\n\t\tDD\t107\t; Index = 33 Token = 2\n\t\tDD\t150\t; Index = 33 Token = 3\n\t\tDD\t194\t; Index = 33 Token = 4\n\t\tDD\t237\t; Index = 33 Token = 5\n\t\tDD\t280\t; Index = 33 Token = 6\n\t\tDD\t323\t; Index = 33 Token = 7\n\t\tDD\t-21\t; Index = 33 Token = 8\n\t\tDD\t-64\t; Index = 33 Token = 9\n\t\tDD\t-107\t; Index = 33 Token = 10\n\t\tDD\t-150\t; Index = 33 Token = 11\n\t\tDD\t-194\t; Index = 33 Token = 12\n\t\tDD\t-237\t; Index = 33 Token = 13\n\t\tDD\t-280\t; Index = 33 Token = 14\n\t\tDD\t-323\t; Index = 33 Token = 15\n\t\tDD\t23\t; Index = 34 Token = 0\n\t\tDD\t70\t; Index = 34 Token = 1\n\t\tDD\t118\t; Index = 34 Token = 2\n\t\tDD\t165\t; Index = 34 Token = 3\n\t\tDD\t213\t; Index = 34 Token = 4\n\t\tDD\t260\t; Index = 34 Token = 5\n\t\tDD\t308\t; Index = 34 Token = 6\n\t\tDD\t355\t; Index = 34 Token = 7\n\t\tDD\t-23\t; Index = 34 Token = 8\n\t\tDD\t-70\t; Index = 34 Token = 9\n\t\tDD\t-118\t; Index = 34 Token = 10\n\t\tDD\t-165\t; Index = 34 Token = 11\n\t\tDD\t-213\t; Index = 34 Token = 12\n\t\tDD\t-260\t; Index = 34 Token = 13\n\t\tDD\t-308\t; Index = 34 Token = 14\n\t\tDD\t-355\t; Index = 34 Token = 15\n\t\tDD\t26\t; Index = 35 Token = 0\n\t\tDD\t78\t; Index = 35 Token = 1\n\t\tDD\t130\t; Index = 35 Token = 2\n\t\tDD\t182\t; Index = 35 Token = 3\n\t\tDD\t235\t; Index = 35 Token = 4\n\t\tDD\t287\t; Index = 35 Token = 5\n\t\tDD\t339\t; Index = 35 Token = 6\n\t\tDD\t391\t; Index = 35 Token = 7\n\t\tDD\t-26\t; Index = 35 Token = 8\n\t\tDD\t-78\t; Index = 35 Token = 9\n\t\tDD\t-130\t; Index = 35 Token = 10\n\t\tDD\t-182\t; Index = 35 Token = 11\n\t\tDD\t-235\t; Index = 35 Token = 12\n\t\tDD\t-287\t; Index = 35 Token = 13\n\t\tDD\t-339\t; Index = 35 Token = 14\n\t\tDD\t-391\t; Index = 35 Token = 15\n\t\tDD\t28\t; Index = 36 Token = 0\n\t\tDD\t85\t; Index = 36 Token = 1\n\t\tDD\t143\t; Index = 36 Token = 2\n\t\tDD\t200\t; Index = 36 Token = 3\n\t\tDD\t258\t; Index = 36 Token = 4\n\t\tDD\t315\t; Index = 36 Token = 5\n\t\tDD\t373\t; Index = 36 Token = 6\n\t\tDD\t430\t; Index = 36 Token = 7\n\t\tDD\t-28\t; Index = 36 Token = 8\n\t\tDD\t-85\t; Index = 36 Token = 9\n\t\tDD\t-143\t; Index = 36 Token = 10\n\t\tDD\t-200\t; Index = 36 Token = 11\n\t\tDD\t-258\t; Index = 36 Token = 12\n\t\tDD\t-315\t; Index = 36 Token = 13\n\t\tDD\t-373\t; Index = 36 Token = 14\n\t\tDD\t-430\t; Index = 36 Token = 15\n\t\tDD\t31\t; Index = 37 Token = 0\n\t\tDD\t94\t; Index = 37 Token = 1\n\t\tDD\t157\t; Index = 37 Token = 2\n\t\tDD\t220\t; Index = 37 Token = 3\n\t\tDD\t284\t; Index = 37 Token = 4\n\t\tDD\t347\t; Index = 37 Token = 5\n\t\tDD\t410\t; Index = 37 Token = 6\n\t\tDD\t473\t; Index = 37 Token = 7\n\t\tDD\t-31\t; Index = 37 Token = 8\n\t\tDD\t-94\t; Index = 37 Token = 9\n\t\tDD\t-157\t; Index = 37 Token = 10\n\t\tDD\t-220\t; Index = 37 Token = 11\n\t\tDD\t-284\t; Index = 37 Token = 12\n\t\tDD\t-347\t; Index = 37 Token = 13\n\t\tDD\t-410\t; Index = 37 Token = 14\n\t\tDD\t-473\t; Index = 37 Token = 15\n\t\tDD\t34\t; Index = 38 Token = 0\n\t\tDD\t103\t; Index = 38 Token = 1\n\t\tDD\t173\t; Index = 38 Token = 2\n\t\tDD\t242\t; Index = 38 Token = 3\n\t\tDD\t313\t; Index = 38 Token = 4\n\t\tDD\t382\t; Index = 38 Token = 5\n\t\tDD\t452\t; Index = 38 Token = 6\n\t\tDD\t521\t; Index = 38 Token = 7\n\t\tDD\t-34\t; Index = 38 Token = 8\n\t\tDD\t-103\t; Index = 38 Token = 9\n\t\tDD\t-173\t; Index = 38 Token = 10\n\t\tDD\t-242\t; Index = 38 Token = 11\n\t\tDD\t-313\t; Index = 38 Token = 12\n\t\tDD\t-382\t; Index = 38 Token = 13\n\t\tDD\t-452\t; Index = 38 Token = 14\n\t\tDD\t-521\t; Index = 38 Token = 15\n\t\tDD\t38\t; Index = 39 Token = 0\n\t\tDD\t114\t; Index = 39 Token = 1\n\t\tDD\t191\t; Index = 39 Token = 2\n\t\tDD\t267\t; Index = 39 Token = 3\n\t\tDD\t345\t; Index = 39 Token = 4\n\t\tDD\t421\t; Index = 39 Token = 5\n\t\tDD\t498\t; Index = 39 Token = 6\n\t\tDD\t574\t; Index = 39 Token = 7\n\t\tDD\t-38\t; Index = 39 Token = 8\n\t\tDD\t-114\t; Index = 39 Token = 9\n\t\tDD\t-191\t; Index = 39 Token = 10\n\t\tDD\t-267\t; Index = 39 Token = 11\n\t\tDD\t-345\t; Index = 39 Token = 12\n\t\tDD\t-421\t; Index = 39 Token = 13\n\t\tDD\t-498\t; Index = 39 Token = 14\n\t\tDD\t-574\t; Index = 39 Token = 15\n\t\tDD\t42\t; Index = 40 Token = 0\n\t\tDD\t126\t; Index = 40 Token = 1\n\t\tDD\t210\t; Index = 40 Token = 2\n\t\tDD\t294\t; Index = 40 Token = 3\n\t\tDD\t379\t; Index = 40 Token = 4\n\t\tDD\t463\t; Index = 40 Token = 5\n\t\tDD\t547\t; Index = 40 Token = 6\n\t\tDD\t631\t; Index = 40 Token = 7\n\t\tDD\t-42\t; Index = 40 Token = 8\n\t\tDD\t-126\t; Index = 40 Token = 9\n\t\tDD\t-210\t; Index = 40 Token = 10\n\t\tDD\t-294\t; Index = 40 Token = 11\n\t\tDD\t-379\t; Index = 40 Token = 12\n\t\tDD\t-463\t; Index = 40 Token = 13\n\t\tDD\t-547\t; Index = 40 Token = 14\n\t\tDD\t-631\t; Index = 40 Token = 15\n\t\tDD\t46\t; Index = 41 Token = 0\n\t\tDD\t138\t; Index = 41 Token = 1\n\t\tDD\t231\t; Index = 41 Token = 2\n\t\tDD\t323\t; Index = 41 Token = 3\n\t\tDD\t417\t; Index = 41 Token = 4\n\t\tDD\t509\t; Index = 41 Token = 5\n\t\tDD\t602\t; Index = 41 Token = 6\n\t\tDD\t694\t; Index = 41 Token = 7\n\t\tDD\t-46\t; Index = 41 Token = 8\n\t\tDD\t-138\t; Index = 41 Token = 9\n\t\tDD\t-231\t; Index = 41 Token = 10\n\t\tDD\t-323\t; Index = 41 Token = 11\n\t\tDD\t-417\t; Index = 41 Token = 12\n\t\tDD\t-509\t; Index = 41 Token = 13\n\t\tDD\t-602\t; Index = 41 Token = 14\n\t\tDD\t-694\t; Index = 41 Token = 15\n\t\tDD\t51\t; Index = 42 Token = 0\n\t\tDD\t153\t; Index = 42 Token = 1\n\t\tDD\t255\t; Index = 42 Token = 2\n\t\tDD\t357\t; Index = 42 Token = 3\n\t\tDD\t459\t; Index = 42 Token = 4\n\t\tDD\t561\t; Index = 42 Token = 5\n\t\tDD\t663\t; Index = 42 Token = 6\n\t\tDD\t765\t; Index = 42 Token = 7\n\t\tDD\t-51\t; Index = 42 Token = 8\n\t\tDD\t-153\t; Index = 42 Token = 9\n\t\tDD\t-255\t; Index = 42 Token = 10\n\t\tDD\t-357\t; Index = 42 Token = 11\n\t\tDD\t-459\t; Index = 42 Token = 12\n\t\tDD\t-561\t; Index = 42 Token = 13\n\t\tDD\t-663\t; Index = 42 Token = 14\n\t\tDD\t-765\t; Index = 42 Token = 15\n\t\tDD\t56\t; Index = 43 Token = 0\n\t\tDD\t168\t; Index = 43 Token = 1\n\t\tDD\t280\t; Index = 43 Token = 2\n\t\tDD\t392\t; Index = 43 Token = 3\n\t\tDD\t505\t; Index = 43 Token = 4\n\t\tDD\t617\t; Index = 43 Token = 5\n\t\tDD\t729\t; Index = 43 Token = 6\n\t\tDD\t841\t; Index = 43 Token = 7\n\t\tDD\t-56\t; Index = 43 Token = 8\n\t\tDD\t-168\t; Index = 43 Token = 9\n\t\tDD\t-280\t; Index = 43 Token = 10\n\t\tDD\t-392\t; Index = 43 Token = 11\n\t\tDD\t-505\t; Index = 43 Token = 12\n\t\tDD\t-617\t; Index = 43 Token = 13\n\t\tDD\t-729\t; Index = 43 Token = 14\n\t\tDD\t-841\t; Index = 43 Token = 15\n\t\tDD\t61\t; Index = 44 Token = 0\n\t\tDD\t184\t; Index = 44 Token = 1\n\t\tDD\t308\t; Index = 44 Token = 2\n\t\tDD\t431\t; Index = 44 Token = 3\n\t\tDD\t555\t; Index = 44 Token = 4\n\t\tDD\t678\t; Index = 44 Token = 5\n\t\tDD\t802\t; Index = 44 Token = 6\n\t\tDD\t925\t; Index = 44 Token = 7\n\t\tDD\t-61\t; Index = 44 Token = 8\n\t\tDD\t-184\t; Index = 44 Token = 9\n\t\tDD\t-308\t; Index = 44 Token = 10\n\t\tDD\t-431\t; Index = 44 Token = 11\n\t\tDD\t-555\t; Index = 44 Token = 12\n\t\tDD\t-678\t; Index = 44 Token = 13\n\t\tDD\t-802\t; Index = 44 Token = 14\n\t\tDD\t-925\t; Index = 44 Token = 15\n\t\tDD\t68\t; Index = 45 Token = 0\n\t\tDD\t204\t; Index = 45 Token = 1\n\t\tDD\t340\t; Index = 45 Token = 2\n\t\tDD\t476\t; Index = 45 Token = 3\n\t\tDD\t612\t; Index = 45 Token = 4\n\t\tDD\t748\t; Index = 45 Token = 5\n\t\tDD\t884\t; Index = 45 Token = 6\n\t\tDD\t1020\t; Index = 45 Token = 7\n\t\tDD\t-68\t; Index = 45 Token = 8\n\t\tDD\t-204\t; Index = 45 Token = 9\n\t\tDD\t-340\t; Index = 45 Token = 10\n\t\tDD\t-476\t; Index = 45 Token = 11\n\t\tDD\t-612\t; Index = 45 Token = 12\n\t\tDD\t-748\t; Index = 45 Token = 13\n\t\tDD\t-884\t; Index = 45 Token = 14\n\t\tDD\t-1020\t; Index = 45 Token = 15\n\t\tDD\t74\t; Index = 46 Token = 0\n\t\tDD\t223\t; Index = 46 Token = 1\n\t\tDD\t373\t; Index = 46 Token = 2\n\t\tDD\t522\t; Index = 46 Token = 3\n\t\tDD\t672\t; Index = 46 Token = 4\n\t\tDD\t821\t; Index = 46 Token = 5\n\t\tDD\t971\t; Index = 46 Token = 6\n\t\tDD\t1120\t; Index = 46 Token = 7\n\t\tDD\t-74\t; Index = 46 Token = 8\n\t\tDD\t-223\t; Index = 46 Token = 9\n\t\tDD\t-373\t; Index = 46 Token = 10\n\t\tDD\t-522\t; Index = 46 Token = 11\n\t\tDD\t-672\t; Index = 46 Token = 12\n\t\tDD\t-821\t; Index = 46 Token = 13\n\t\tDD\t-971\t; Index = 46 Token = 14\n\t\tDD\t-1120\t; Index = 46 Token = 15\n\t\tDD\t82\t; Index = 47 Token = 0\n\t\tDD\t246\t; Index = 47 Token = 1\n\t\tDD\t411\t; Index = 47 Token = 2\n\t\tDD\t575\t; Index = 47 Token = 3\n\t\tDD\t740\t; Index = 47 Token = 4\n\t\tDD\t904\t; Index = 47 Token = 5\n\t\tDD\t1069\t; Index = 47 Token = 6\n\t\tDD\t1233\t; Index = 47 Token = 7\n\t\tDD\t-82\t; Index = 47 Token = 8\n\t\tDD\t-246\t; Index = 47 Token = 9\n\t\tDD\t-411\t; Index = 47 Token = 10\n\t\tDD\t-575\t; Index = 47 Token = 11\n\t\tDD\t-740\t; Index = 47 Token = 12\n\t\tDD\t-904\t; Index = 47 Token = 13\n\t\tDD\t-1069\t; Index = 47 Token = 14\n\t\tDD\t-1233\t; Index = 47 Token = 15\n\t\tDD\t90\t; Index = 48 Token = 0\n\t\tDD\t271\t; Index = 48 Token = 1\n\t\tDD\t452\t; Index = 48 Token = 2\n\t\tDD\t633\t; Index = 48 Token = 3\n\t\tDD\t814\t; Index = 48 Token = 4\n\t\tDD\t995\t; Index = 48 Token = 5\n\t\tDD\t1176\t; Index = 48 Token = 6\n\t\tDD\t1357\t; Index = 48 Token = 7\n\t\tDD\t-90\t; Index = 48 Token = 8\n\t\tDD\t-271\t; Index = 48 Token = 9\n\t\tDD\t-452\t; Index = 48 Token = 10\n\t\tDD\t-633\t; Index = 48 Token = 11\n\t\tDD\t-814\t; Index = 48 Token = 12\n\t\tDD\t-995\t; Index = 48 Token = 13\n\t\tDD\t-1176\t; Index = 48 Token = 14\n\t\tDD\t-1357\t; Index = 48 Token = 15\n\t\tDD\t99\t; Index = 49 Token = 0\n\t\tDD\t298\t; Index = 49 Token = 1\n\t\tDD\t497\t; Index = 49 Token = 2\n\t\tDD\t696\t; Index = 49 Token = 3\n\t\tDD\t895\t; Index = 49 Token = 4\n\t\tDD\t1094\t; Index = 49 Token = 5\n\t\tDD\t1293\t; Index = 49 Token = 6\n\t\tDD\t1492\t; Index = 49 Token = 7\n\t\tDD\t-99\t; Index = 49 Token = 8\n\t\tDD\t-298\t; Index = 49 Token = 9\n\t\tDD\t-497\t; Index = 49 Token = 10\n\t\tDD\t-696\t; Index = 49 Token = 11\n\t\tDD\t-895\t; Index = 49 Token = 12\n\t\tDD\t-1094\t; Index = 49 Token = 13\n\t\tDD\t-1293\t; Index = 49 Token = 14\n\t\tDD\t-1492\t; Index = 49 Token = 15\n\t\tDD\t109\t; Index = 50 Token = 0\n\t\tDD\t328\t; Index = 50 Token = 1\n\t\tDD\t547\t; Index = 50 Token = 2\n\t\tDD\t766\t; Index = 50 Token = 3\n\t\tDD\t985\t; Index = 50 Token = 4\n\t\tDD\t1204\t; Index = 50 Token = 5\n\t\tDD\t1423\t; Index = 50 Token = 6\n\t\tDD\t1642\t; Index = 50 Token = 7\n\t\tDD\t-109\t; Index = 50 Token = 8\n\t\tDD\t-328\t; Index = 50 Token = 9\n\t\tDD\t-547\t; Index = 50 Token = 10\n\t\tDD\t-766\t; Index = 50 Token = 11\n\t\tDD\t-985\t; Index = 50 Token = 12\n\t\tDD\t-1204\t; Index = 50 Token = 13\n\t\tDD\t-1423\t; Index = 50 Token = 14\n\t\tDD\t-1642\t; Index = 50 Token = 15\n\t\tDD\t120\t; Index = 51 Token = 0\n\t\tDD\t360\t; Index = 51 Token = 1\n\t\tDD\t601\t; Index = 51 Token = 2\n\t\tDD\t841\t; Index = 51 Token = 3\n\t\tDD\t1083\t; Index = 51 Token = 4\n\t\tDD\t1323\t; Index = 51 Token = 5\n\t\tDD\t1564\t; Index = 51 Token = 6\n\t\tDD\t1804\t; Index = 51 Token = 7\n\t\tDD\t-120\t; Index = 51 Token = 8\n\t\tDD\t-360\t; Index = 51 Token = 9\n\t\tDD\t-601\t; Index = 51 Token = 10\n\t\tDD\t-841\t; Index = 51 Token = 11\n\t\tDD\t-1083\t; Index = 51 Token = 12\n\t\tDD\t-1323\t; Index = 51 Token = 13\n\t\tDD\t-1564\t; Index = 51 Token = 14\n\t\tDD\t-1804\t; Index = 51 Token = 15\n\t\tDD\t132\t; Index = 52 Token = 0\n\t\tDD\t397\t; Index = 52 Token = 1\n\t\tDD\t662\t; Index = 52 Token = 2\n\t\tDD\t927\t; Index = 52 Token = 3\n\t\tDD\t1192\t; Index = 52 Token = 4\n\t\tDD\t1457\t; Index = 52 Token = 5\n\t\tDD\t1722\t; Index = 52 Token = 6\n\t\tDD\t1987\t; Index = 52 Token = 7\n\t\tDD\t-132\t; Index = 52 Token = 8\n\t\tDD\t-397\t; Index = 52 Token = 9\n\t\tDD\t-662\t; Index = 52 Token = 10\n\t\tDD\t-927\t; Index = 52 Token = 11\n\t\tDD\t-1192\t; Index = 52 Token = 12\n\t\tDD\t-1457\t; Index = 52 Token = 13\n\t\tDD\t-1722\t; Index = 52 Token = 14\n\t\tDD\t-1987\t; Index = 52 Token = 15\n\t\tDD\t145\t; Index = 53 Token = 0\n\t\tDD\t436\t; Index = 53 Token = 1\n\t\tDD\t728\t; Index = 53 Token = 2\n\t\tDD\t1019\t; Index = 53 Token = 3\n\t\tDD\t1311\t; Index = 53 Token = 4\n\t\tDD\t1602\t; Index = 53 Token = 5\n\t\tDD\t1894\t; Index = 53 Token = 6\n\t\tDD\t2185\t; Index = 53 Token = 7\n\t\tDD\t-145\t; Index = 53 Token = 8\n\t\tDD\t-436\t; Index = 53 Token = 9\n\t\tDD\t-728\t; Index = 53 Token = 10\n\t\tDD\t-1019\t; Index = 53 Token = 11\n\t\tDD\t-1311\t; Index = 53 Token = 12\n\t\tDD\t-1602\t; Index = 53 Token = 13\n\t\tDD\t-1894\t; Index = 53 Token = 14\n\t\tDD\t-2185\t; Index = 53 Token = 15\n\t\tDD\t160\t; Index = 54 Token = 0\n\t\tDD\t480\t; Index = 54 Token = 1\n\t\tDD\t801\t; Index = 54 Token = 2\n\t\tDD\t1121\t; Index = 54 Token = 3\n\t\tDD\t1442\t; Index = 54 Token = 4\n\t\tDD\t1762\t; Index = 54 Token = 5\n\t\tDD\t2083\t; Index = 54 Token = 6\n\t\tDD\t2403\t; Index = 54 Token = 7\n\t\tDD\t-160\t; Index = 54 Token = 8\n\t\tDD\t-480\t; Index = 54 Token = 9\n\t\tDD\t-801\t; Index = 54 Token = 10\n\t\tDD\t-1121\t; Index = 54 Token = 11\n\t\tDD\t-1442\t; Index = 54 Token = 12\n\t\tDD\t-1762\t; Index = 54 Token = 13\n\t\tDD\t-2083\t; Index = 54 Token = 14\n\t\tDD\t-2403\t; Index = 54 Token = 15\n\t\tDD\t176\t; Index = 55 Token = 0\n\t\tDD\t528\t; Index = 55 Token = 1\n\t\tDD\t881\t; Index = 55 Token = 2\n\t\tDD\t1233\t; Index = 55 Token = 3\n\t\tDD\t1587\t; Index = 55 Token = 4\n\t\tDD\t1939\t; Index = 55 Token = 5\n\t\tDD\t2292\t; Index = 55 Token = 6\n\t\tDD\t2644\t; Index = 55 Token = 7\n\t\tDD\t-176\t; Index = 55 Token = 8\n\t\tDD\t-528\t; Index = 55 Token = 9\n\t\tDD\t-881\t; Index = 55 Token = 10\n\t\tDD\t-1233\t; Index = 55 Token = 11\n\t\tDD\t-1587\t; Index = 55 Token = 12\n\t\tDD\t-1939\t; Index = 55 Token = 13\n\t\tDD\t-2292\t; Index = 55 Token = 14\n\t\tDD\t-2644\t; Index = 55 Token = 15\n\t\tDD\t194\t; Index = 56 Token = 0\n\t\tDD\t582\t; Index = 56 Token = 1\n\t\tDD\t970\t; Index = 56 Token = 2\n\t\tDD\t1358\t; Index = 56 Token = 3\n\t\tDD\t1746\t; Index = 56 Token = 4\n\t\tDD\t2134\t; Index = 56 Token = 5\n\t\tDD\t2522\t; Index = 56 Token = 6\n\t\tDD\t2910\t; Index = 56 Token = 7\n\t\tDD\t-194\t; Index = 56 Token = 8\n\t\tDD\t-582\t; Index = 56 Token = 9\n\t\tDD\t-970\t; Index = 56 Token = 10\n\t\tDD\t-1358\t; Index = 56 Token = 11\n\t\tDD\t-1746\t; Index = 56 Token = 12\n\t\tDD\t-2134\t; Index = 56 Token = 13\n\t\tDD\t-2522\t; Index = 56 Token = 14\n\t\tDD\t-2910\t; Index = 56 Token = 15\n\t\tDD\t213\t; Index = 57 Token = 0\n\t\tDD\t639\t; Index = 57 Token = 1\n\t\tDD\t1066\t; Index = 57 Token = 2\n\t\tDD\t1492\t; Index = 57 Token = 3\n\t\tDD\t1920\t; Index = 57 Token = 4\n\t\tDD\t2346\t; Index = 57 Token = 5\n\t\tDD\t2773\t; Index = 57 Token = 6\n\t\tDD\t3199\t; Index = 57 Token = 7\n\t\tDD\t-213\t; Index = 57 Token = 8\n\t\tDD\t-639\t; Index = 57 Token = 9\n\t\tDD\t-1066\t; Index = 57 Token = 10\n\t\tDD\t-1492\t; Index = 57 Token = 11\n\t\tDD\t-1920\t; Index = 57 Token = 12\n\t\tDD\t-2346\t; Index = 57 Token = 13\n\t\tDD\t-2773\t; Index = 57 Token = 14\n\t\tDD\t-3199\t; Index = 57 Token = 15\n\t\tDD\t234\t; Index = 58 Token = 0\n\t\tDD\t703\t; Index = 58 Token = 1\n\t\tDD\t1173\t; Index = 58 Token = 2\n\t\tDD\t1642\t; Index = 58 Token = 3\n\t\tDD\t2112\t; Index = 58 Token = 4\n\t\tDD\t2581\t; Index = 58 Token = 5\n\t\tDD\t3051\t; Index = 58 Token = 6\n\t\tDD\t3520\t; Index = 58 Token = 7\n\t\tDD\t-234\t; Index = 58 Token = 8\n\t\tDD\t-703\t; Index = 58 Token = 9\n\t\tDD\t-1173\t; Index = 58 Token = 10\n\t\tDD\t-1642\t; Index = 58 Token = 11\n\t\tDD\t-2112\t; Index = 58 Token = 12\n\t\tDD\t-2581\t; Index = 58 Token = 13\n\t\tDD\t-3051\t; Index = 58 Token = 14\n\t\tDD\t-3520\t; Index = 58 Token = 15\n\t\tDD\t258\t; Index = 59 Token = 0\n\t\tDD\t774\t; Index = 59 Token = 1\n\t\tDD\t1291\t; Index = 59 Token = 2\n\t\tDD\t1807\t; Index = 59 Token = 3\n\t\tDD\t2324\t; Index = 59 Token = 4\n\t\tDD\t2840\t; Index = 59 Token = 5\n\t\tDD\t3357\t; Index = 59 Token = 6\n\t\tDD\t3873\t; Index = 59 Token = 7\n\t\tDD\t-258\t; Index = 59 Token = 8\n\t\tDD\t-774\t; Index = 59 Token = 9\n\t\tDD\t-1291\t; Index = 59 Token = 10\n\t\tDD\t-1807\t; Index = 59 Token = 11\n\t\tDD\t-2324\t; Index = 59 Token = 12\n\t\tDD\t-2840\t; Index = 59 Token = 13\n\t\tDD\t-3357\t; Index = 59 Token = 14\n\t\tDD\t-3873\t; Index = 59 Token = 15\n\t\tDD\t284\t; Index = 60 Token = 0\n\t\tDD\t852\t; Index = 60 Token = 1\n\t\tDD\t1420\t; Index = 60 Token = 2\n\t\tDD\t1988\t; Index = 60 Token = 3\n\t\tDD\t2556\t; Index = 60 Token = 4\n\t\tDD\t3124\t; Index = 60 Token = 5\n\t\tDD\t3692\t; Index = 60 Token = 6\n\t\tDD\t4260\t; Index = 60 Token = 7\n\t\tDD\t-284\t; Index = 60 Token = 8\n\t\tDD\t-852\t; Index = 60 Token = 9\n\t\tDD\t-1420\t; Index = 60 Token = 10\n\t\tDD\t-1988\t; Index = 60 Token = 11\n\t\tDD\t-2556\t; Index = 60 Token = 12\n\t\tDD\t-3124\t; Index = 60 Token = 13\n\t\tDD\t-3692\t; Index = 60 Token = 14\n\t\tDD\t-4260\t; Index = 60 Token = 15\n\t\tDD\t312\t; Index = 61 Token = 0\n\t\tDD\t936\t; Index = 61 Token = 1\n\t\tDD\t1561\t; Index = 61 Token = 2\n\t\tDD\t2185\t; Index = 61 Token = 3\n\t\tDD\t2811\t; Index = 61 Token = 4\n\t\tDD\t3435\t; Index = 61 Token = 5\n\t\tDD\t4060\t; Index = 61 Token = 6\n\t\tDD\t4684\t; Index = 61 Token = 7\n\t\tDD\t-312\t; Index = 61 Token = 8\n\t\tDD\t-936\t; Index = 61 Token = 9\n\t\tDD\t-1561\t; Index = 61 Token = 10\n\t\tDD\t-2185\t; Index = 61 Token = 11\n\t\tDD\t-2811\t; Index = 61 Token = 12\n\t\tDD\t-3435\t; Index = 61 Token = 13\n\t\tDD\t-4060\t; Index = 61 Token = 14\n\t\tDD\t-4684\t; Index = 61 Token = 15\n\t\tDD\t343\t; Index = 62 Token = 0\n\t\tDD\t1030\t; Index = 62 Token = 1\n\t\tDD\t1717\t; Index = 62 Token = 2\n\t\tDD\t2404\t; Index = 62 Token = 3\n\t\tDD\t3092\t; Index = 62 Token = 4\n\t\tDD\t3779\t; Index = 62 Token = 5\n\t\tDD\t4466\t; Index = 62 Token = 6\n\t\tDD\t5153\t; Index = 62 Token = 7\n\t\tDD\t-343\t; Index = 62 Token = 8\n\t\tDD\t-1030\t; Index = 62 Token = 9\n\t\tDD\t-1717\t; Index = 62 Token = 10\n\t\tDD\t-2404\t; Index = 62 Token = 11\n\t\tDD\t-3092\t; Index = 62 Token = 12\n\t\tDD\t-3779\t; Index = 62 Token = 13\n\t\tDD\t-4466\t; Index = 62 Token = 14\n\t\tDD\t-5153\t; Index = 62 Token = 15\n\t\tDD\t378\t; Index = 63 Token = 0\n\t\tDD\t1134\t; Index = 63 Token = 1\n\t\tDD\t1890\t; Index = 63 Token = 2\n\t\tDD\t2646\t; Index = 63 Token = 3\n\t\tDD\t3402\t; Index = 63 Token = 4\n\t\tDD\t4158\t; Index = 63 Token = 5\n\t\tDD\t4914\t; Index = 63 Token = 6\n\t\tDD\t5670\t; Index = 63 Token = 7\n\t\tDD\t-378\t; Index = 63 Token = 8\n\t\tDD\t-1134\t; Index = 63 Token = 9\n\t\tDD\t-1890\t; Index = 63 Token = 10\n\t\tDD\t-2646\t; Index = 63 Token = 11\n\t\tDD\t-3402\t; Index = 63 Token = 12\n\t\tDD\t-4158\t; Index = 63 Token = 13\n\t\tDD\t-4914\t; Index = 63 Token = 14\n\t\tDD\t-5670\t; Index = 63 Token = 15\n\t\tDD\t415\t; Index = 64 Token = 0\n\t\tDD\t1246\t; Index = 64 Token = 1\n\t\tDD\t2078\t; Index = 64 Token = 2\n\t\tDD\t2909\t; Index = 64 Token = 3\n\t\tDD\t3742\t; Index = 64 Token = 4\n\t\tDD\t4573\t; Index = 64 Token = 5\n\t\tDD\t5405\t; Index = 64 Token = 6\n\t\tDD\t6236\t; Index = 64 Token = 7\n\t\tDD\t-415\t; Index = 64 Token = 8\n\t\tDD\t-1246\t; Index = 64 Token = 9\n\t\tDD\t-2078\t; Index = 64 Token = 10\n\t\tDD\t-2909\t; Index = 64 Token = 11\n\t\tDD\t-3742\t; Index = 64 Token = 12\n\t\tDD\t-4573\t; Index = 64 Token = 13\n\t\tDD\t-5405\t; Index = 64 Token = 14\n\t\tDD\t-6236\t; Index = 64 Token = 15\n\t\tDD\t457\t; Index = 65 Token = 0\n\t\tDD\t1372\t; Index = 65 Token = 1\n\t\tDD\t2287\t; Index = 65 Token = 2\n\t\tDD\t3202\t; Index = 65 Token = 3\n\t\tDD\t4117\t; Index = 65 Token = 4\n\t\tDD\t5032\t; Index = 65 Token = 5\n\t\tDD\t5947\t; Index = 65 Token = 6\n\t\tDD\t6862\t; Index = 65 Token = 7\n\t\tDD\t-457\t; Index = 65 Token = 8\n\t\tDD\t-1372\t; Index = 65 Token = 9\n\t\tDD\t-2287\t; Index = 65 Token = 10\n\t\tDD\t-3202\t; Index = 65 Token = 11\n\t\tDD\t-4117\t; Index = 65 Token = 12\n\t\tDD\t-5032\t; Index = 65 Token = 13\n\t\tDD\t-5947\t; Index = 65 Token = 14\n\t\tDD\t-6862\t; Index = 65 Token = 15\n\t\tDD\t503\t; Index = 66 Token = 0\n\t\tDD\t1509\t; Index = 66 Token = 1\n\t\tDD\t2516\t; Index = 66 Token = 2\n\t\tDD\t3522\t; Index = 66 Token = 3\n\t\tDD\t4529\t; Index = 66 Token = 4\n\t\tDD\t5535\t; Index = 66 Token = 5\n\t\tDD\t6542\t; Index = 66 Token = 6\n\t\tDD\t7548\t; Index = 66 Token = 7\n\t\tDD\t-503\t; Index = 66 Token = 8\n\t\tDD\t-1509\t; Index = 66 Token = 9\n\t\tDD\t-2516\t; Index = 66 Token = 10\n\t\tDD\t-3522\t; Index = 66 Token = 11\n\t\tDD\t-4529\t; Index = 66 Token = 12\n\t\tDD\t-5535\t; Index = 66 Token = 13\n\t\tDD\t-6542\t; Index = 66 Token = 14\n\t\tDD\t-7548\t; Index = 66 Token = 15\n\t\tDD\t553\t; Index = 67 Token = 0\n\t\tDD\t1660\t; Index = 67 Token = 1\n\t\tDD\t2767\t; Index = 67 Token = 2\n\t\tDD\t3874\t; Index = 67 Token = 3\n\t\tDD\t4981\t; Index = 67 Token = 4\n\t\tDD\t6088\t; Index = 67 Token = 5\n\t\tDD\t7195\t; Index = 67 Token = 6\n\t\tDD\t8302\t; Index = 67 Token = 7\n\t\tDD\t-553\t; Index = 67 Token = 8\n\t\tDD\t-1660\t; Index = 67 Token = 9\n\t\tDD\t-2767\t; Index = 67 Token = 10\n\t\tDD\t-3874\t; Index = 67 Token = 11\n\t\tDD\t-4981\t; Index = 67 Token = 12\n\t\tDD\t-6088\t; Index = 67 Token = 13\n\t\tDD\t-7195\t; Index = 67 Token = 14\n\t\tDD\t-8302\t; Index = 67 Token = 15\n\t\tDD\t608\t; Index = 68 Token = 0\n\t\tDD\t1825\t; Index = 68 Token = 1\n\t\tDD\t3043\t; Index = 68 Token = 2\n\t\tDD\t4260\t; Index = 68 Token = 3\n\t\tDD\t5479\t; Index = 68 Token = 4\n\t\tDD\t6696\t; Index = 68 Token = 5\n\t\tDD\t7914\t; Index = 68 Token = 6\n\t\tDD\t9131\t; Index = 68 Token = 7\n\t\tDD\t-608\t; Index = 68 Token = 8\n\t\tDD\t-1825\t; Index = 68 Token = 9\n\t\tDD\t-3043\t; Index = 68 Token = 10\n\t\tDD\t-4260\t; Index = 68 Token = 11\n\t\tDD\t-5479\t; Index = 68 Token = 12\n\t\tDD\t-6696\t; Index = 68 Token = 13\n\t\tDD\t-7914\t; Index = 68 Token = 14\n\t\tDD\t-9131\t; Index = 68 Token = 15\n\t\tDD\t669\t; Index = 69 Token = 0\n\t\tDD\t2008\t; Index = 69 Token = 1\n\t\tDD\t3348\t; Index = 69 Token = 2\n\t\tDD\t4687\t; Index = 69 Token = 3\n\t\tDD\t6027\t; Index = 69 Token = 4\n\t\tDD\t7366\t; Index = 69 Token = 5\n\t\tDD\t8706\t; Index = 69 Token = 6\n\t\tDD\t10045\t; Index = 69 Token = 7\n\t\tDD\t-669\t; Index = 69 Token = 8\n\t\tDD\t-2008\t; Index = 69 Token = 9\n\t\tDD\t-3348\t; Index = 69 Token = 10\n\t\tDD\t-4687\t; Index = 69 Token = 11\n\t\tDD\t-6027\t; Index = 69 Token = 12\n\t\tDD\t-7366\t; Index = 69 Token = 13\n\t\tDD\t-8706\t; Index = 69 Token = 14\n\t\tDD\t-10045\t; Index = 69 Token = 15\n\t\tDD\t736\t; Index = 70 Token = 0\n\t\tDD\t2209\t; Index = 70 Token = 1\n\t\tDD\t3683\t; Index = 70 Token = 2\n\t\tDD\t5156\t; Index = 70 Token = 3\n\t\tDD\t6630\t; Index = 70 Token = 4\n\t\tDD\t8103\t; Index = 70 Token = 5\n\t\tDD\t9577\t; Index = 70 Token = 6\n\t\tDD\t11050\t; Index = 70 Token = 7\n\t\tDD\t-736\t; Index = 70 Token = 8\n\t\tDD\t-2209\t; Index = 70 Token = 9\n\t\tDD\t-3683\t; Index = 70 Token = 10\n\t\tDD\t-5156\t; Index = 70 Token = 11\n\t\tDD\t-6630\t; Index = 70 Token = 12\n\t\tDD\t-8103\t; Index = 70 Token = 13\n\t\tDD\t-9577\t; Index = 70 Token = 14\n\t\tDD\t-11050\t; Index = 70 Token = 15\n\t\tDD\t810\t; Index = 71 Token = 0\n\t\tDD\t2431\t; Index = 71 Token = 1\n\t\tDD\t4052\t; Index = 71 Token = 2\n\t\tDD\t5673\t; Index = 71 Token = 3\n\t\tDD\t7294\t; Index = 71 Token = 4\n\t\tDD\t8915\t; Index = 71 Token = 5\n\t\tDD\t10536\t; Index = 71 Token = 6\n\t\tDD\t12157\t; Index = 71 Token = 7\n\t\tDD\t-810\t; Index = 71 Token = 8\n\t\tDD\t-2431\t; Index = 71 Token = 9\n\t\tDD\t-4052\t; Index = 71 Token = 10\n\t\tDD\t-5673\t; Index = 71 Token = 11\n\t\tDD\t-7294\t; Index = 71 Token = 12\n\t\tDD\t-8915\t; Index = 71 Token = 13\n\t\tDD\t-10536\t; Index = 71 Token = 14\n\t\tDD\t-12157\t; Index = 71 Token = 15\n\t\tDD\t891\t; Index = 72 Token = 0\n\t\tDD\t2674\t; Index = 72 Token = 1\n\t\tDD\t4457\t; Index = 72 Token = 2\n\t\tDD\t6240\t; Index = 72 Token = 3\n\t\tDD\t8023\t; Index = 72 Token = 4\n\t\tDD\t9806\t; Index = 72 Token = 5\n\t\tDD\t11589\t; Index = 72 Token = 6\n\t\tDD\t13372\t; Index = 72 Token = 7\n\t\tDD\t-891\t; Index = 72 Token = 8\n\t\tDD\t-2674\t; Index = 72 Token = 9\n\t\tDD\t-4457\t; Index = 72 Token = 10\n\t\tDD\t-6240\t; Index = 72 Token = 11\n\t\tDD\t-8023\t; Index = 72 Token = 12\n\t\tDD\t-9806\t; Index = 72 Token = 13\n\t\tDD\t-11589\t; Index = 72 Token = 14\n\t\tDD\t-13372\t; Index = 72 Token = 15\n\t\tDD\t980\t; Index = 73 Token = 0\n\t\tDD\t2941\t; Index = 73 Token = 1\n\t\tDD\t4902\t; Index = 73 Token = 2\n\t\tDD\t6863\t; Index = 73 Token = 3\n\t\tDD\t8825\t; Index = 73 Token = 4\n\t\tDD\t10786\t; Index = 73 Token = 5\n\t\tDD\t12747\t; Index = 73 Token = 6\n\t\tDD\t14708\t; Index = 73 Token = 7\n\t\tDD\t-980\t; Index = 73 Token = 8\n\t\tDD\t-2941\t; Index = 73 Token = 9\n\t\tDD\t-4902\t; Index = 73 Token = 10\n\t\tDD\t-6863\t; Index = 73 Token = 11\n\t\tDD\t-8825\t; Index = 73 Token = 12\n\t\tDD\t-10786\t; Index = 73 Token = 13\n\t\tDD\t-12747\t; Index = 73 Token = 14\n\t\tDD\t-14708\t; Index = 73 Token = 15\n\t\tDD\t1078\t; Index = 74 Token = 0\n\t\tDD\t3235\t; Index = 74 Token = 1\n\t\tDD\t5393\t; Index = 74 Token = 2\n\t\tDD\t7550\t; Index = 74 Token = 3\n\t\tDD\t9708\t; Index = 74 Token = 4\n\t\tDD\t11865\t; Index = 74 Token = 5\n\t\tDD\t14023\t; Index = 74 Token = 6\n\t\tDD\t16180\t; Index = 74 Token = 7\n\t\tDD\t-1078\t; Index = 74 Token = 8\n\t\tDD\t-3235\t; Index = 74 Token = 9\n\t\tDD\t-5393\t; Index = 74 Token = 10\n\t\tDD\t-7550\t; Index = 74 Token = 11\n\t\tDD\t-9708\t; Index = 74 Token = 12\n\t\tDD\t-11865\t; Index = 74 Token = 13\n\t\tDD\t-14023\t; Index = 74 Token = 14\n\t\tDD\t-16180\t; Index = 74 Token = 15\n\t\tDD\t1186\t; Index = 75 Token = 0\n\t\tDD\t3559\t; Index = 75 Token = 1\n\t\tDD\t5932\t; Index = 75 Token = 2\n\t\tDD\t8305\t; Index = 75 Token = 3\n\t\tDD\t10679\t; Index = 75 Token = 4\n\t\tDD\t13052\t; Index = 75 Token = 5\n\t\tDD\t15425\t; Index = 75 Token = 6\n\t\tDD\t17798\t; Index = 75 Token = 7\n\t\tDD\t-1186\t; Index = 75 Token = 8\n\t\tDD\t-3559\t; Index = 75 Token = 9\n\t\tDD\t-5932\t; Index = 75 Token = 10\n\t\tDD\t-8305\t; Index = 75 Token = 11\n\t\tDD\t-10679\t; Index = 75 Token = 12\n\t\tDD\t-13052\t; Index = 75 Token = 13\n\t\tDD\t-15425\t; Index = 75 Token = 14\n\t\tDD\t-17798\t; Index = 75 Token = 15\n\t\tDD\t1305\t; Index = 76 Token = 0\n\t\tDD\t3915\t; Index = 76 Token = 1\n\t\tDD\t6526\t; Index = 76 Token = 2\n\t\tDD\t9136\t; Index = 76 Token = 3\n\t\tDD\t11747\t; Index = 76 Token = 4\n\t\tDD\t14357\t; Index = 76 Token = 5\n\t\tDD\t16968\t; Index = 76 Token = 6\n\t\tDD\t19578\t; Index = 76 Token = 7\n\t\tDD\t-1305\t; Index = 76 Token = 8\n\t\tDD\t-3915\t; Index = 76 Token = 9\n\t\tDD\t-6526\t; Index = 76 Token = 10\n\t\tDD\t-9136\t; Index = 76 Token = 11\n\t\tDD\t-11747\t; Index = 76 Token = 12\n\t\tDD\t-14357\t; Index = 76 Token = 13\n\t\tDD\t-16968\t; Index = 76 Token = 14\n\t\tDD\t-19578\t; Index = 76 Token = 15\n\t\tDD\t1435\t; Index = 77 Token = 0\n\t\tDD\t4306\t; Index = 77 Token = 1\n\t\tDD\t7178\t; Index = 77 Token = 2\n\t\tDD\t10049\t; Index = 77 Token = 3\n\t\tDD\t12922\t; Index = 77 Token = 4\n\t\tDD\t15793\t; Index = 77 Token = 5\n\t\tDD\t18665\t; Index = 77 Token = 6\n\t\tDD\t21536\t; Index = 77 Token = 7\n\t\tDD\t-1435\t; Index = 77 Token = 8\n\t\tDD\t-4306\t; Index = 77 Token = 9\n\t\tDD\t-7178\t; Index = 77 Token = 10\n\t\tDD\t-10049\t; Index = 77 Token = 11\n\t\tDD\t-12922\t; Index = 77 Token = 12\n\t\tDD\t-15793\t; Index = 77 Token = 13\n\t\tDD\t-18665\t; Index = 77 Token = 14\n\t\tDD\t-21536\t; Index = 77 Token = 15\n\t\tDD\t1579\t; Index = 78 Token = 0\n\t\tDD\t4737\t; Index = 78 Token = 1\n\t\tDD\t7896\t; Index = 78 Token = 2\n\t\tDD\t11054\t; Index = 78 Token = 3\n\t\tDD\t14214\t; Index = 78 Token = 4\n\t\tDD\t17372\t; Index = 78 Token = 5\n\t\tDD\t20531\t; Index = 78 Token = 6\n\t\tDD\t23689\t; Index = 78 Token = 7\n\t\tDD\t-1579\t; Index = 78 Token = 8\n\t\tDD\t-4737\t; Index = 78 Token = 9\n\t\tDD\t-7896\t; Index = 78 Token = 10\n\t\tDD\t-11054\t; Index = 78 Token = 11\n\t\tDD\t-14214\t; Index = 78 Token = 12\n\t\tDD\t-17372\t; Index = 78 Token = 13\n\t\tDD\t-20531\t; Index = 78 Token = 14\n\t\tDD\t-23689\t; Index = 78 Token = 15\n\t\tDD\t1737\t; Index = 79 Token = 0\n\t\tDD\t5211\t; Index = 79 Token = 1\n\t\tDD\t8686\t; Index = 79 Token = 2\n\t\tDD\t12160\t; Index = 79 Token = 3\n\t\tDD\t15636\t; Index = 79 Token = 4\n\t\tDD\t19110\t; Index = 79 Token = 5\n\t\tDD\t22585\t; Index = 79 Token = 6\n\t\tDD\t26059\t; Index = 79 Token = 7\n\t\tDD\t-1737\t; Index = 79 Token = 8\n\t\tDD\t-5211\t; Index = 79 Token = 9\n\t\tDD\t-8686\t; Index = 79 Token = 10\n\t\tDD\t-12160\t; Index = 79 Token = 11\n\t\tDD\t-15636\t; Index = 79 Token = 12\n\t\tDD\t-19110\t; Index = 79 Token = 13\n\t\tDD\t-22585\t; Index = 79 Token = 14\n\t\tDD\t-26059\t; Index = 79 Token = 15\n\t\tDD\t1911\t; Index = 80 Token = 0\n\t\tDD\t5733\t; Index = 80 Token = 1\n\t\tDD\t9555\t; Index = 80 Token = 2\n\t\tDD\t13377\t; Index = 80 Token = 3\n\t\tDD\t17200\t; Index = 80 Token = 4\n\t\tDD\t21022\t; Index = 80 Token = 5\n\t\tDD\t24844\t; Index = 80 Token = 6\n\t\tDD\t28666\t; Index = 80 Token = 7\n\t\tDD\t-1911\t; Index = 80 Token = 8\n\t\tDD\t-5733\t; Index = 80 Token = 9\n\t\tDD\t-9555\t; Index = 80 Token = 10\n\t\tDD\t-13377\t; Index = 80 Token = 11\n\t\tDD\t-17200\t; Index = 80 Token = 12\n\t\tDD\t-21022\t; Index = 80 Token = 13\n\t\tDD\t-24844\t; Index = 80 Token = 14\n\t\tDD\t-28666\t; Index = 80 Token = 15\n\t\tDD\t2102\t; Index = 81 Token = 0\n\t\tDD\t6306\t; Index = 81 Token = 1\n\t\tDD\t10511\t; Index = 81 Token = 2\n\t\tDD\t14715\t; Index = 81 Token = 3\n\t\tDD\t18920\t; Index = 81 Token = 4\n\t\tDD\t23124\t; Index = 81 Token = 5\n\t\tDD\t27329\t; Index = 81 Token = 6\n\t\tDD\t31533\t; Index = 81 Token = 7\n\t\tDD\t-2102\t; Index = 81 Token = 8\n\t\tDD\t-6306\t; Index = 81 Token = 9\n\t\tDD\t-10511\t; Index = 81 Token = 10\n\t\tDD\t-14715\t; Index = 81 Token = 11\n\t\tDD\t-18920\t; Index = 81 Token = 12\n\t\tDD\t-23124\t; Index = 81 Token = 13\n\t\tDD\t-27329\t; Index = 81 Token = 14\n\t\tDD\t-31533\t; Index = 81 Token = 15\n\t\tDD\t2312\t; Index = 82 Token = 0\n\t\tDD\t6937\t; Index = 82 Token = 1\n\t\tDD\t11562\t; Index = 82 Token = 2\n\t\tDD\t16187\t; Index = 82 Token = 3\n\t\tDD\t20812\t; Index = 82 Token = 4\n\t\tDD\t25437\t; Index = 82 Token = 5\n\t\tDD\t30062\t; Index = 82 Token = 6\n\t\tDD\t34687\t; Index = 82 Token = 7\n\t\tDD\t-2312\t; Index = 82 Token = 8\n\t\tDD\t-6937\t; Index = 82 Token = 9\n\t\tDD\t-11562\t; Index = 82 Token = 10\n\t\tDD\t-16187\t; Index = 82 Token = 11\n\t\tDD\t-20812\t; Index = 82 Token = 12\n\t\tDD\t-25437\t; Index = 82 Token = 13\n\t\tDD\t-30062\t; Index = 82 Token = 14\n\t\tDD\t-34687\t; Index = 82 Token = 15\n\t\tDD\t2543\t; Index = 83 Token = 0\n\t\tDD\t7630\t; Index = 83 Token = 1\n\t\tDD\t12718\t; Index = 83 Token = 2\n\t\tDD\t17805\t; Index = 83 Token = 3\n\t\tDD\t22893\t; Index = 83 Token = 4\n\t\tDD\t27980\t; Index = 83 Token = 5\n\t\tDD\t33068\t; Index = 83 Token = 6\n\t\tDD\t38155\t; Index = 83 Token = 7\n\t\tDD\t-2543\t; Index = 83 Token = 8\n\t\tDD\t-7630\t; Index = 83 Token = 9\n\t\tDD\t-12718\t; Index = 83 Token = 10\n\t\tDD\t-17805\t; Index = 83 Token = 11\n\t\tDD\t-22893\t; Index = 83 Token = 12\n\t\tDD\t-27980\t; Index = 83 Token = 13\n\t\tDD\t-33068\t; Index = 83 Token = 14\n\t\tDD\t-38155\t; Index = 83 Token = 15\n\t\tDD\t2798\t; Index = 84 Token = 0\n\t\tDD\t8394\t; Index = 84 Token = 1\n\t\tDD\t13990\t; Index = 84 Token = 2\n\t\tDD\t19586\t; Index = 84 Token = 3\n\t\tDD\t25183\t; Index = 84 Token = 4\n\t\tDD\t30779\t; Index = 84 Token = 5\n\t\tDD\t36375\t; Index = 84 Token = 6\n\t\tDD\t41971\t; Index = 84 Token = 7\n\t\tDD\t-2798\t; Index = 84 Token = 8\n\t\tDD\t-8394\t; Index = 84 Token = 9\n\t\tDD\t-13990\t; Index = 84 Token = 10\n\t\tDD\t-19586\t; Index = 84 Token = 11\n\t\tDD\t-25183\t; Index = 84 Token = 12\n\t\tDD\t-30779\t; Index = 84 Token = 13\n\t\tDD\t-36375\t; Index = 84 Token = 14\n\t\tDD\t-41971\t; Index = 84 Token = 15\n\t\tDD\t3077\t; Index = 85 Token = 0\n\t\tDD\t9232\t; Index = 85 Token = 1\n\t\tDD\t15388\t; Index = 85 Token = 2\n\t\tDD\t21543\t; Index = 85 Token = 3\n\t\tDD\t27700\t; Index = 85 Token = 4\n\t\tDD\t33855\t; Index = 85 Token = 5\n\t\tDD\t40011\t; Index = 85 Token = 6\n\t\tDD\t46166\t; Index = 85 Token = 7\n\t\tDD\t-3077\t; Index = 85 Token = 8\n\t\tDD\t-9232\t; Index = 85 Token = 9\n\t\tDD\t-15388\t; Index = 85 Token = 10\n\t\tDD\t-21543\t; Index = 85 Token = 11\n\t\tDD\t-27700\t; Index = 85 Token = 12\n\t\tDD\t-33855\t; Index = 85 Token = 13\n\t\tDD\t-40011\t; Index = 85 Token = 14\n\t\tDD\t-46166\t; Index = 85 Token = 15\n\t\tDD\t3385\t; Index = 86 Token = 0\n\t\tDD\t10156\t; Index = 86 Token = 1\n\t\tDD\t16928\t; Index = 86 Token = 2\n\t\tDD\t23699\t; Index = 86 Token = 3\n\t\tDD\t30471\t; Index = 86 Token = 4\n\t\tDD\t37242\t; Index = 86 Token = 5\n\t\tDD\t44014\t; Index = 86 Token = 6\n\t\tDD\t50785\t; Index = 86 Token = 7\n\t\tDD\t-3385\t; Index = 86 Token = 8\n\t\tDD\t-10156\t; Index = 86 Token = 9\n\t\tDD\t-16928\t; Index = 86 Token = 10\n\t\tDD\t-23699\t; Index = 86 Token = 11\n\t\tDD\t-30471\t; Index = 86 Token = 12\n\t\tDD\t-37242\t; Index = 86 Token = 13\n\t\tDD\t-44014\t; Index = 86 Token = 14\n\t\tDD\t-50785\t; Index = 86 Token = 15\n\t\tDD\t3724\t; Index = 87 Token = 0\n\t\tDD\t11172\t; Index = 87 Token = 1\n\t\tDD\t18621\t; Index = 87 Token = 2\n\t\tDD\t26069\t; Index = 87 Token = 3\n\t\tDD\t33518\t; Index = 87 Token = 4\n\t\tDD\t40966\t; Index = 87 Token = 5\n\t\tDD\t48415\t; Index = 87 Token = 6\n\t\tDD\t55863\t; Index = 87 Token = 7\n\t\tDD\t-3724\t; Index = 87 Token = 8\n\t\tDD\t-11172\t; Index = 87 Token = 9\n\t\tDD\t-18621\t; Index = 87 Token = 10\n\t\tDD\t-26069\t; Index = 87 Token = 11\n\t\tDD\t-33518\t; Index = 87 Token = 12\n\t\tDD\t-40966\t; Index = 87 Token = 13\n\t\tDD\t-48415\t; Index = 87 Token = 14\n\t\tDD\t-55863\t; Index = 87 Token = 15\n\t\tDD\t4095\t; Index = 88 Token = 0\n\t\tDD\t12286\t; Index = 88 Token = 1\n\t\tDD\t20478\t; Index = 88 Token = 2\n\t\tDD\t28669\t; Index = 88 Token = 3\n\t\tDD\t36862\t; Index = 88 Token = 4\n\t\tDD\t45053\t; Index = 88 Token = 5\n\t\tDD\t53245\t; Index = 88 Token = 6\n\t\tDD\t61436\t; Index = 88 Token = 7\n\t\tDD\t-4095\t; Index = 88 Token = 8\n\t\tDD\t-12286\t; Index = 88 Token = 9\n\t\tDD\t-20478\t; Index = 88 Token = 10\n\t\tDD\t-28669\t; Index = 88 Token = 11\n\t\tDD\t-36862\t; Index = 88 Token = 12\n\t\tDD\t-45053\t; Index = 88 Token = 13\n\t\tDD\t-53245\t; Index = 88 Token = 14\n\t\tDD\t-61436\t; Index = 88 Token = 15\n"
  },
  {
    "path": "WWFLAT32/AUDIO/FUNCTION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SOUNDIO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort Decompress_Frame(void * source, void * dest, short size);\nint cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback);\nint cdecl Stream_Sample(void *buffer, long size, BOOL (*callback);\nint cdecl File_Stream_Sample(char const *filename);\nint cdecl File_Stream_Sample_Vol(char const *filename, int volume);\nvoid cdecl _saveregs _loadds Sound_Callback(void);\nvoid cdecl far _saveregs _loadds maintenance_callback(void);\nvoid *cdecl Load_Sample(char const *filename);\nlong cdecl Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);\nlong cdecl Sample_Read(int fh, void *buffer, long size);\nvoid cdecl Free_Sample(void const *sample);\nBOOL cdecl Sound_Init(int sfx, int score, int sample);\nvoid far VQA_TimerCallback(void);\nBOOL Audio_Init(int sample, int address, int inter, int dma);\nvoid cdecl Sound_End(void);\nvoid cdecl Stop_Sample(int handle);\nBOOL cdecl Sample_Status(int handle);\nBOOL cdecl Is_Sample_Playing(void const * sample);\nvoid cdecl Stop_Sample_Playing(void const * sample);\nint cdecl Play_Sample(void const *sample);\nint cdecl Play_Sample_Vol(void const *sample, int priority, int volume);\nint cdecl Set_Sound_Vol(int volume);\nint cdecl Set_Score_Vol(int volume);\nvoid cdecl Fade_Sample(int handle, int ticks);\n"
  },
  {
    "path": "WWFLAT32/AUDIO/INDEXTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* wIndexTable - ADPCM Lookup table for indexes\n;****************************************************************************\n\n\t\talign\t4\n\nwIndexTable\tDW\t0\t* 2\t; Index = 0 Token = 0\n\t\tDW\t0\t* 2\t; Index = 0 Token = 1\n\t\tDW\t0\t* 2\t; Index = 0 Token = 2\n\t\tDW\t0\t* 2\t; Index = 0 Token = 3\n\t\tDW\t32\t* 2\t; Index = 0 Token = 4\n\t\tDW\t64\t* 2\t; Index = 0 Token = 5\n\t\tDW\t96\t* 2\t; Index = 0 Token = 6\n\t\tDW\t128\t* 2\t; Index = 0 Token = 7\n\t\tDW\t0\t* 2\t; Index = 0 Token = 8\n\t\tDW\t0\t* 2\t; Index = 0 Token = 9\n\t\tDW\t0\t* 2\t; Index = 0 Token = 10\n\t\tDW\t0\t* 2\t; Index = 0 Token = 11\n\t\tDW\t32\t* 2\t; Index = 0 Token = 12\n\t\tDW\t64\t* 2\t; Index = 0 Token = 13\n\t\tDW\t96\t* 2\t; Index = 0 Token = 14\n\t\tDW\t128\t* 2\t; Index = 0 Token = 15\n\t\tDW\t0\t* 2\t; Index = 1 Token = 0\n\t\tDW\t0\t* 2\t; Index = 1 Token = 1\n\t\tDW\t0\t* 2\t; Index = 1 Token = 2\n\t\tDW\t0\t* 2\t; Index = 1 Token = 3\n\t\tDW\t48\t* 2\t; Index = 1 Token = 4\n\t\tDW\t80\t* 2\t; Index = 1 Token = 5\n\t\tDW\t112\t* 2\t; Index = 1 Token = 6\n\t\tDW\t144\t* 2\t; Index = 1 Token = 7\n\t\tDW\t0\t* 2\t; Index = 1 Token = 8\n\t\tDW\t0\t* 2\t; Index = 1 Token = 9\n\t\tDW\t0\t* 2\t; Index = 1 Token = 10\n\t\tDW\t0\t* 2\t; Index = 1 Token = 11\n\t\tDW\t48\t* 2\t; Index = 1 Token = 12\n\t\tDW\t80\t* 2\t; Index = 1 Token = 13\n\t\tDW\t112\t* 2\t; Index = 1 Token = 14\n\t\tDW\t144\t* 2\t; Index = 1 Token = 15\n\t\tDW\t16\t* 2\t; Index = 2 Token = 0\n\t\tDW\t16\t* 2\t; Index = 2 Token = 1\n\t\tDW\t16\t* 2\t; Index = 2 Token = 2\n\t\tDW\t16\t* 2\t; Index = 2 Token = 3\n\t\tDW\t64\t* 2\t; Index = 2 Token = 4\n\t\tDW\t96\t* 2\t; Index = 2 Token = 5\n\t\tDW\t128\t* 2\t; Index = 2 Token = 6\n\t\tDW\t160\t* 2\t; Index = 2 Token = 7\n\t\tDW\t16\t* 2\t; Index = 2 Token = 8\n\t\tDW\t16\t* 2\t; Index = 2 Token = 9\n\t\tDW\t16\t* 2\t; Index = 2 Token = 10\n\t\tDW\t16\t* 2\t; Index = 2 Token = 11\n\t\tDW\t64\t* 2\t; Index = 2 Token = 12\n\t\tDW\t96\t* 2\t; Index = 2 Token = 13\n\t\tDW\t128\t* 2\t; Index = 2 Token = 14\n\t\tDW\t160\t* 2\t; Index = 2 Token = 15\n\t\tDW\t32\t* 2\t; Index = 3 Token = 0\n\t\tDW\t32\t* 2\t; Index = 3 Token = 1\n\t\tDW\t32\t* 2\t; Index = 3 Token = 2\n\t\tDW\t32\t* 2\t; Index = 3 Token = 3\n\t\tDW\t80\t* 2\t; Index = 3 Token = 4\n\t\tDW\t112\t* 2\t; Index = 3 Token = 5\n\t\tDW\t144\t* 2\t; Index = 3 Token = 6\n\t\tDW\t176\t* 2\t; Index = 3 Token = 7\n\t\tDW\t32\t* 2\t; Index = 3 Token = 8\n\t\tDW\t32\t* 2\t; Index = 3 Token = 9\n\t\tDW\t32\t* 2\t; Index = 3 Token = 10\n\t\tDW\t32\t* 2\t; Index = 3 Token = 11\n\t\tDW\t80\t* 2\t; Index = 3 Token = 12\n\t\tDW\t112\t* 2\t; Index = 3 Token = 13\n\t\tDW\t144\t* 2\t; Index = 3 Token = 14\n\t\tDW\t176\t* 2\t; Index = 3 Token = 15\n\t\tDW\t48\t* 2\t; Index = 4 Token = 0\n\t\tDW\t48\t* 2\t; Index = 4 Token = 1\n\t\tDW\t48\t* 2\t; Index = 4 Token = 2\n\t\tDW\t48\t* 2\t; Index = 4 Token = 3\n\t\tDW\t96\t* 2\t; Index = 4 Token = 4\n\t\tDW\t128\t* 2\t; Index = 4 Token = 5\n\t\tDW\t160\t* 2\t; Index = 4 Token = 6\n\t\tDW\t192\t* 2\t; Index = 4 Token = 7\n\t\tDW\t48\t* 2\t; Index = 4 Token = 8\n\t\tDW\t48\t* 2\t; Index = 4 Token = 9\n\t\tDW\t48\t* 2\t; Index = 4 Token = 10\n\t\tDW\t48\t* 2\t; Index = 4 Token = 11\n\t\tDW\t96\t* 2\t; Index = 4 Token = 12\n\t\tDW\t128\t* 2\t; Index = 4 Token = 13\n\t\tDW\t160\t* 2\t; Index = 4 Token = 14\n\t\tDW\t192\t* 2\t; Index = 4 Token = 15\n\t\tDW\t64\t* 2\t; Index = 5 Token = 0\n\t\tDW\t64\t* 2\t; Index = 5 Token = 1\n\t\tDW\t64\t* 2\t; Index = 5 Token = 2\n\t\tDW\t64\t* 2\t; Index = 5 Token = 3\n\t\tDW\t112\t* 2\t; Index = 5 Token = 4\n\t\tDW\t144\t* 2\t; Index = 5 Token = 5\n\t\tDW\t176\t* 2\t; Index = 5 Token = 6\n\t\tDW\t208\t* 2\t; Index = 5 Token = 7\n\t\tDW\t64\t* 2\t; Index = 5 Token = 8\n\t\tDW\t64\t* 2\t; Index = 5 Token = 9\n\t\tDW\t64\t* 2\t; Index = 5 Token = 10\n\t\tDW\t64\t* 2\t; Index = 5 Token = 11\n\t\tDW\t112\t* 2\t; Index = 5 Token = 12\n\t\tDW\t144\t* 2\t; Index = 5 Token = 13\n\t\tDW\t176\t* 2\t; Index = 5 Token = 14\n\t\tDW\t208\t* 2\t; Index = 5 Token = 15\n\t\tDW\t80\t* 2\t; Index = 6 Token = 0\n\t\tDW\t80\t* 2\t; Index = 6 Token = 1\n\t\tDW\t80\t* 2\t; Index = 6 Token = 2\n\t\tDW\t80\t* 2\t; Index = 6 Token = 3\n\t\tDW\t128\t* 2\t; Index = 6 Token = 4\n\t\tDW\t160\t* 2\t; Index = 6 Token = 5\n\t\tDW\t192\t* 2\t; Index = 6 Token = 6\n\t\tDW\t224\t* 2\t; Index = 6 Token = 7\n\t\tDW\t80\t* 2\t; Index = 6 Token = 8\n\t\tDW\t80\t* 2\t; Index = 6 Token = 9\n\t\tDW\t80\t* 2\t; Index = 6 Token = 10\n\t\tDW\t80\t* 2\t; Index = 6 Token = 11\n\t\tDW\t128\t* 2\t; Index = 6 Token = 12\n\t\tDW\t160\t* 2\t; Index = 6 Token = 13\n\t\tDW\t192\t* 2\t; Index = 6 Token = 14\n\t\tDW\t224\t* 2\t; Index = 6 Token = 15\n\t\tDW\t96\t* 2\t; Index = 7 Token = 0\n\t\tDW\t96\t* 2\t; Index = 7 Token = 1\n\t\tDW\t96\t* 2\t; Index = 7 Token = 2\n\t\tDW\t96\t* 2\t; Index = 7 Token = 3\n\t\tDW\t144\t* 2\t; Index = 7 Token = 4\n\t\tDW\t176\t* 2\t; Index = 7 Token = 5\n\t\tDW\t208\t* 2\t; Index = 7 Token = 6\n\t\tDW\t240\t* 2\t; Index = 7 Token = 7\n\t\tDW\t96\t* 2\t; Index = 7 Token = 8\n\t\tDW\t96\t* 2\t; Index = 7 Token = 9\n\t\tDW\t96\t* 2\t; Index = 7 Token = 10\n\t\tDW\t96\t* 2\t; Index = 7 Token = 11\n\t\tDW\t144\t* 2\t; Index = 7 Token = 12\n\t\tDW\t176\t* 2\t; Index = 7 Token = 13\n\t\tDW\t208\t* 2\t; Index = 7 Token = 14\n\t\tDW\t240\t* 2\t; Index = 7 Token = 15\n\t\tDW\t112\t* 2\t; Index = 8 Token = 0\n\t\tDW\t112\t* 2\t; Index = 8 Token = 1\n\t\tDW\t112\t* 2\t; Index = 8 Token = 2\n\t\tDW\t112\t* 2\t; Index = 8 Token = 3\n\t\tDW\t160\t* 2\t; Index = 8 Token = 4\n\t\tDW\t192\t* 2\t; Index = 8 Token = 5\n\t\tDW\t224\t* 2\t; Index = 8 Token = 6\n\t\tDW\t256\t* 2\t; Index = 8 Token = 7\n\t\tDW\t112\t* 2\t; Index = 8 Token = 8\n\t\tDW\t112\t* 2\t; Index = 8 Token = 9\n\t\tDW\t112\t* 2\t; Index = 8 Token = 10\n\t\tDW\t112\t* 2\t; Index = 8 Token = 11\n\t\tDW\t160\t* 2\t; Index = 8 Token = 12\n\t\tDW\t192\t* 2\t; Index = 8 Token = 13\n\t\tDW\t224\t* 2\t; Index = 8 Token = 14\n\t\tDW\t256\t* 2\t; Index = 8 Token = 15\n\t\tDW\t128\t* 2\t; Index = 9 Token = 0\n\t\tDW\t128\t* 2\t; Index = 9 Token = 1\n\t\tDW\t128\t* 2\t; Index = 9 Token = 2\n\t\tDW\t128\t* 2\t; Index = 9 Token = 3\n\t\tDW\t176\t* 2\t; Index = 9 Token = 4\n\t\tDW\t208\t* 2\t; Index = 9 Token = 5\n\t\tDW\t240\t* 2\t; Index = 9 Token = 6\n\t\tDW\t272\t* 2\t; Index = 9 Token = 7\n\t\tDW\t128\t* 2\t; Index = 9 Token = 8\n\t\tDW\t128\t* 2\t; Index = 9 Token = 9\n\t\tDW\t128\t* 2\t; Index = 9 Token = 10\n\t\tDW\t128\t* 2\t; Index = 9 Token = 11\n\t\tDW\t176\t* 2\t; Index = 9 Token = 12\n\t\tDW\t208\t* 2\t; Index = 9 Token = 13\n\t\tDW\t240\t* 2\t; Index = 9 Token = 14\n\t\tDW\t272\t* 2\t; Index = 9 Token = 15\n\t\tDW\t144\t* 2\t; Index = 10 Token = 0\n\t\tDW\t144\t* 2\t; Index = 10 Token = 1\n\t\tDW\t144\t* 2\t; Index = 10 Token = 2\n\t\tDW\t144\t* 2\t; Index = 10 Token = 3\n\t\tDW\t192\t* 2\t; Index = 10 Token = 4\n\t\tDW\t224\t* 2\t; Index = 10 Token = 5\n\t\tDW\t256\t* 2\t; Index = 10 Token = 6\n\t\tDW\t288\t* 2\t; Index = 10 Token = 7\n\t\tDW\t144\t* 2\t; Index = 10 Token = 8\n\t\tDW\t144\t* 2\t; Index = 10 Token = 9\n\t\tDW\t144\t* 2\t; Index = 10 Token = 10\n\t\tDW\t144\t* 2\t; Index = 10 Token = 11\n\t\tDW\t192\t* 2\t; Index = 10 Token = 12\n\t\tDW\t224\t* 2\t; Index = 10 Token = 13\n\t\tDW\t256\t* 2\t; Index = 10 Token = 14\n\t\tDW\t288\t* 2\t; Index = 10 Token = 15\n\t\tDW\t160\t* 2\t; Index = 11 Token = 0\n\t\tDW\t160\t* 2\t; Index = 11 Token = 1\n\t\tDW\t160\t* 2\t; Index = 11 Token = 2\n\t\tDW\t160\t* 2\t; Index = 11 Token = 3\n\t\tDW\t208\t* 2\t; Index = 11 Token = 4\n\t\tDW\t240\t* 2\t; Index = 11 Token = 5\n\t\tDW\t272\t* 2\t; Index = 11 Token = 6\n\t\tDW\t304\t* 2\t; Index = 11 Token = 7\n\t\tDW\t160\t* 2\t; Index = 11 Token = 8\n\t\tDW\t160\t* 2\t; Index = 11 Token = 9\n\t\tDW\t160\t* 2\t; Index = 11 Token = 10\n\t\tDW\t160\t* 2\t; Index = 11 Token = 11\n\t\tDW\t208\t* 2\t; Index = 11 Token = 12\n\t\tDW\t240\t* 2\t; Index = 11 Token = 13\n\t\tDW\t272\t* 2\t; Index = 11 Token = 14\n\t\tDW\t304\t* 2\t; Index = 11 Token = 15\n\t\tDW\t176\t* 2\t; Index = 12 Token = 0\n\t\tDW\t176\t* 2\t; Index = 12 Token = 1\n\t\tDW\t176\t* 2\t; Index = 12 Token = 2\n\t\tDW\t176\t* 2\t; Index = 12 Token = 3\n\t\tDW\t224\t* 2\t; Index = 12 Token = 4\n\t\tDW\t256\t* 2\t; Index = 12 Token = 5\n\t\tDW\t288\t* 2\t; Index = 12 Token = 6\n\t\tDW\t320\t* 2\t; Index = 12 Token = 7\n\t\tDW\t176\t* 2\t; Index = 12 Token = 8\n\t\tDW\t176\t* 2\t; Index = 12 Token = 9\n\t\tDW\t176\t* 2\t; Index = 12 Token = 10\n\t\tDW\t176\t* 2\t; Index = 12 Token = 11\n\t\tDW\t224\t* 2\t; Index = 12 Token = 12\n\t\tDW\t256\t* 2\t; Index = 12 Token = 13\n\t\tDW\t288\t* 2\t; Index = 12 Token = 14\n\t\tDW\t320\t* 2\t; Index = 12 Token = 15\n\t\tDW\t192\t* 2\t; Index = 13 Token = 0\n\t\tDW\t192\t* 2\t; Index = 13 Token = 1\n\t\tDW\t192\t* 2\t; Index = 13 Token = 2\n\t\tDW\t192\t* 2\t; Index = 13 Token = 3\n\t\tDW\t240\t* 2\t; Index = 13 Token = 4\n\t\tDW\t272\t* 2\t; Index = 13 Token = 5\n\t\tDW\t304\t* 2\t; Index = 13 Token = 6\n\t\tDW\t336\t* 2\t; Index = 13 Token = 7\n\t\tDW\t192\t* 2\t; Index = 13 Token = 8\n\t\tDW\t192\t* 2\t; Index = 13 Token = 9\n\t\tDW\t192\t* 2\t; Index = 13 Token = 10\n\t\tDW\t192\t* 2\t; Index = 13 Token = 11\n\t\tDW\t240\t* 2\t; Index = 13 Token = 12\n\t\tDW\t272\t* 2\t; Index = 13 Token = 13\n\t\tDW\t304\t* 2\t; Index = 13 Token = 14\n\t\tDW\t336\t* 2\t; Index = 13 Token = 15\n\t\tDW\t208\t* 2\t; Index = 14 Token = 0\n\t\tDW\t208\t* 2\t; Index = 14 Token = 1\n\t\tDW\t208\t* 2\t; Index = 14 Token = 2\n\t\tDW\t208\t* 2\t; Index = 14 Token = 3\n\t\tDW\t256\t* 2\t; Index = 14 Token = 4\n\t\tDW\t288\t* 2\t; Index = 14 Token = 5\n\t\tDW\t320\t* 2\t; Index = 14 Token = 6\n\t\tDW\t352\t* 2\t; Index = 14 Token = 7\n\t\tDW\t208\t* 2\t; Index = 14 Token = 8\n\t\tDW\t208\t* 2\t; Index = 14 Token = 9\n\t\tDW\t208\t* 2\t; Index = 14 Token = 10\n\t\tDW\t208\t* 2\t; Index = 14 Token = 11\n\t\tDW\t256\t* 2\t; Index = 14 Token = 12\n\t\tDW\t288\t* 2\t; Index = 14 Token = 13\n\t\tDW\t320\t* 2\t; Index = 14 Token = 14\n\t\tDW\t352\t* 2\t; Index = 14 Token = 15\n\t\tDW\t224\t* 2\t; Index = 15 Token = 0\n\t\tDW\t224\t* 2\t; Index = 15 Token = 1\n\t\tDW\t224\t* 2\t; Index = 15 Token = 2\n\t\tDW\t224\t* 2\t; Index = 15 Token = 3\n\t\tDW\t272\t* 2\t; Index = 15 Token = 4\n\t\tDW\t304\t* 2\t; Index = 15 Token = 5\n\t\tDW\t336\t* 2\t; Index = 15 Token = 6\n\t\tDW\t368\t* 2\t; Index = 15 Token = 7\n\t\tDW\t224\t* 2\t; Index = 15 Token = 8\n\t\tDW\t224\t* 2\t; Index = 15 Token = 9\n\t\tDW\t224\t* 2\t; Index = 15 Token = 10\n\t\tDW\t224\t* 2\t; Index = 15 Token = 11\n\t\tDW\t272\t* 2\t; Index = 15 Token = 12\n\t\tDW\t304\t* 2\t; Index = 15 Token = 13\n\t\tDW\t336\t* 2\t; Index = 15 Token = 14\n\t\tDW\t368\t* 2\t; Index = 15 Token = 15\n\t\tDW\t240\t* 2\t; Index = 16 Token = 0\n\t\tDW\t240\t* 2\t; Index = 16 Token = 1\n\t\tDW\t240\t* 2\t; Index = 16 Token = 2\n\t\tDW\t240\t* 2\t; Index = 16 Token = 3\n\t\tDW\t288\t* 2\t; Index = 16 Token = 4\n\t\tDW\t320\t* 2\t; Index = 16 Token = 5\n\t\tDW\t352\t* 2\t; Index = 16 Token = 6\n\t\tDW\t384\t* 2\t; Index = 16 Token = 7\n\t\tDW\t240\t* 2\t; Index = 16 Token = 8\n\t\tDW\t240\t* 2\t; Index = 16 Token = 9\n\t\tDW\t240\t* 2\t; Index = 16 Token = 10\n\t\tDW\t240\t* 2\t; Index = 16 Token = 11\n\t\tDW\t288\t* 2\t; Index = 16 Token = 12\n\t\tDW\t320\t* 2\t; Index = 16 Token = 13\n\t\tDW\t352\t* 2\t; Index = 16 Token = 14\n\t\tDW\t384\t* 2\t; Index = 16 Token = 15\n\t\tDW\t256\t* 2\t; Index = 17 Token = 0\n\t\tDW\t256\t* 2\t; Index = 17 Token = 1\n\t\tDW\t256\t* 2\t; Index = 17 Token = 2\n\t\tDW\t256\t* 2\t; Index = 17 Token = 3\n\t\tDW\t304\t* 2\t; Index = 17 Token = 4\n\t\tDW\t336\t* 2\t; Index = 17 Token = 5\n\t\tDW\t368\t* 2\t; Index = 17 Token = 6\n\t\tDW\t400\t* 2\t; Index = 17 Token = 7\n\t\tDW\t256\t* 2\t; Index = 17 Token = 8\n\t\tDW\t256\t* 2\t; Index = 17 Token = 9\n\t\tDW\t256\t* 2\t; Index = 17 Token = 10\n\t\tDW\t256\t* 2\t; Index = 17 Token = 11\n\t\tDW\t304\t* 2\t; Index = 17 Token = 12\n\t\tDW\t336\t* 2\t; Index = 17 Token = 13\n\t\tDW\t368\t* 2\t; Index = 17 Token = 14\n\t\tDW\t400\t* 2\t; Index = 17 Token = 15\n\t\tDW\t272\t* 2\t; Index = 18 Token = 0\n\t\tDW\t272\t* 2\t; Index = 18 Token = 1\n\t\tDW\t272\t* 2\t; Index = 18 Token = 2\n\t\tDW\t272\t* 2\t; Index = 18 Token = 3\n\t\tDW\t320\t* 2\t; Index = 18 Token = 4\n\t\tDW\t352\t* 2\t; Index = 18 Token = 5\n\t\tDW\t384\t* 2\t; Index = 18 Token = 6\n\t\tDW\t416\t* 2\t; Index = 18 Token = 7\n\t\tDW\t272\t* 2\t; Index = 18 Token = 8\n\t\tDW\t272\t* 2\t; Index = 18 Token = 9\n\t\tDW\t272\t* 2\t; Index = 18 Token = 10\n\t\tDW\t272\t* 2\t; Index = 18 Token = 11\n\t\tDW\t320\t* 2\t; Index = 18 Token = 12\n\t\tDW\t352\t* 2\t; Index = 18 Token = 13\n\t\tDW\t384\t* 2\t; Index = 18 Token = 14\n\t\tDW\t416\t* 2\t; Index = 18 Token = 15\n\t\tDW\t288\t* 2\t; Index = 19 Token = 0\n\t\tDW\t288\t* 2\t; Index = 19 Token = 1\n\t\tDW\t288\t* 2\t; Index = 19 Token = 2\n\t\tDW\t288\t* 2\t; Index = 19 Token = 3\n\t\tDW\t336\t* 2\t; Index = 19 Token = 4\n\t\tDW\t368\t* 2\t; Index = 19 Token = 5\n\t\tDW\t400\t* 2\t; Index = 19 Token = 6\n\t\tDW\t432\t* 2\t; Index = 19 Token = 7\n\t\tDW\t288\t* 2\t; Index = 19 Token = 8\n\t\tDW\t288\t* 2\t; Index = 19 Token = 9\n\t\tDW\t288\t* 2\t; Index = 19 Token = 10\n\t\tDW\t288\t* 2\t; Index = 19 Token = 11\n\t\tDW\t336\t* 2\t; Index = 19 Token = 12\n\t\tDW\t368\t* 2\t; Index = 19 Token = 13\n\t\tDW\t400\t* 2\t; Index = 19 Token = 14\n\t\tDW\t432\t* 2\t; Index = 19 Token = 15\n\t\tDW\t304\t* 2\t; Index = 20 Token = 0\n\t\tDW\t304\t* 2\t; Index = 20 Token = 1\n\t\tDW\t304\t* 2\t; Index = 20 Token = 2\n\t\tDW\t304\t* 2\t; Index = 20 Token = 3\n\t\tDW\t352\t* 2\t; Index = 20 Token = 4\n\t\tDW\t384\t* 2\t; Index = 20 Token = 5\n\t\tDW\t416\t* 2\t; Index = 20 Token = 6\n\t\tDW\t448\t* 2\t; Index = 20 Token = 7\n\t\tDW\t304\t* 2\t; Index = 20 Token = 8\n\t\tDW\t304\t* 2\t; Index = 20 Token = 9\n\t\tDW\t304\t* 2\t; Index = 20 Token = 10\n\t\tDW\t304\t* 2\t; Index = 20 Token = 11\n\t\tDW\t352\t* 2\t; Index = 20 Token = 12\n\t\tDW\t384\t* 2\t; Index = 20 Token = 13\n\t\tDW\t416\t* 2\t; Index = 20 Token = 14\n\t\tDW\t448\t* 2\t; Index = 20 Token = 15\n\t\tDW\t320\t* 2\t; Index = 21 Token = 0\n\t\tDW\t320\t* 2\t; Index = 21 Token = 1\n\t\tDW\t320\t* 2\t; Index = 21 Token = 2\n\t\tDW\t320\t* 2\t; Index = 21 Token = 3\n\t\tDW\t368\t* 2\t; Index = 21 Token = 4\n\t\tDW\t400\t* 2\t; Index = 21 Token = 5\n\t\tDW\t432\t* 2\t; Index = 21 Token = 6\n\t\tDW\t464\t* 2\t; Index = 21 Token = 7\n\t\tDW\t320\t* 2\t; Index = 21 Token = 8\n\t\tDW\t320\t* 2\t; Index = 21 Token = 9\n\t\tDW\t320\t* 2\t; Index = 21 Token = 10\n\t\tDW\t320\t* 2\t; Index = 21 Token = 11\n\t\tDW\t368\t* 2\t; Index = 21 Token = 12\n\t\tDW\t400\t* 2\t; Index = 21 Token = 13\n\t\tDW\t432\t* 2\t; Index = 21 Token = 14\n\t\tDW\t464\t* 2\t; Index = 21 Token = 15\n\t\tDW\t336\t* 2\t; Index = 22 Token = 0\n\t\tDW\t336\t* 2\t; Index = 22 Token = 1\n\t\tDW\t336\t* 2\t; Index = 22 Token = 2\n\t\tDW\t336\t* 2\t; Index = 22 Token = 3\n\t\tDW\t384\t* 2\t; Index = 22 Token = 4\n\t\tDW\t416\t* 2\t; Index = 22 Token = 5\n\t\tDW\t448\t* 2\t; Index = 22 Token = 6\n\t\tDW\t480\t* 2\t; Index = 22 Token = 7\n\t\tDW\t336\t* 2\t; Index = 22 Token = 8\n\t\tDW\t336\t* 2\t; Index = 22 Token = 9\n\t\tDW\t336\t* 2\t; Index = 22 Token = 10\n\t\tDW\t336\t* 2\t; Index = 22 Token = 11\n\t\tDW\t384\t* 2\t; Index = 22 Token = 12\n\t\tDW\t416\t* 2\t; Index = 22 Token = 13\n\t\tDW\t448\t* 2\t; Index = 22 Token = 14\n\t\tDW\t480\t* 2\t; Index = 22 Token = 15\n\t\tDW\t352\t* 2\t; Index = 23 Token = 0\n\t\tDW\t352\t* 2\t; Index = 23 Token = 1\n\t\tDW\t352\t* 2\t; Index = 23 Token = 2\n\t\tDW\t352\t* 2\t; Index = 23 Token = 3\n\t\tDW\t400\t* 2\t; Index = 23 Token = 4\n\t\tDW\t432\t* 2\t; Index = 23 Token = 5\n\t\tDW\t464\t* 2\t; Index = 23 Token = 6\n\t\tDW\t496\t* 2\t; Index = 23 Token = 7\n\t\tDW\t352\t* 2\t; Index = 23 Token = 8\n\t\tDW\t352\t* 2\t; Index = 23 Token = 9\n\t\tDW\t352\t* 2\t; Index = 23 Token = 10\n\t\tDW\t352\t* 2\t; Index = 23 Token = 11\n\t\tDW\t400\t* 2\t; Index = 23 Token = 12\n\t\tDW\t432\t* 2\t; Index = 23 Token = 13\n\t\tDW\t464\t* 2\t; Index = 23 Token = 14\n\t\tDW\t496\t* 2\t; Index = 23 Token = 15\n\t\tDW\t368\t* 2\t; Index = 24 Token = 0\n\t\tDW\t368\t* 2\t; Index = 24 Token = 1\n\t\tDW\t368\t* 2\t; Index = 24 Token = 2\n\t\tDW\t368\t* 2\t; Index = 24 Token = 3\n\t\tDW\t416\t* 2\t; Index = 24 Token = 4\n\t\tDW\t448\t* 2\t; Index = 24 Token = 5\n\t\tDW\t480\t* 2\t; Index = 24 Token = 6\n\t\tDW\t512\t* 2\t; Index = 24 Token = 7\n\t\tDW\t368\t* 2\t; Index = 24 Token = 8\n\t\tDW\t368\t* 2\t; Index = 24 Token = 9\n\t\tDW\t368\t* 2\t; Index = 24 Token = 10\n\t\tDW\t368\t* 2\t; Index = 24 Token = 11\n\t\tDW\t416\t* 2\t; Index = 24 Token = 12\n\t\tDW\t448\t* 2\t; Index = 24 Token = 13\n\t\tDW\t480\t* 2\t; Index = 24 Token = 14\n\t\tDW\t512\t* 2\t; Index = 24 Token = 15\n\t\tDW\t384\t* 2\t; Index = 25 Token = 0\n\t\tDW\t384\t* 2\t; Index = 25 Token = 1\n\t\tDW\t384\t* 2\t; Index = 25 Token = 2\n\t\tDW\t384\t* 2\t; Index = 25 Token = 3\n\t\tDW\t432\t* 2\t; Index = 25 Token = 4\n\t\tDW\t464\t* 2\t; Index = 25 Token = 5\n\t\tDW\t496\t* 2\t; Index = 25 Token = 6\n\t\tDW\t528\t* 2\t; Index = 25 Token = 7\n\t\tDW\t384\t* 2\t; Index = 25 Token = 8\n\t\tDW\t384\t* 2\t; Index = 25 Token = 9\n\t\tDW\t384\t* 2\t; Index = 25 Token = 10\n\t\tDW\t384\t* 2\t; Index = 25 Token = 11\n\t\tDW\t432\t* 2\t; Index = 25 Token = 12\n\t\tDW\t464\t* 2\t; Index = 25 Token = 13\n\t\tDW\t496\t* 2\t; Index = 25 Token = 14\n\t\tDW\t528\t* 2\t; Index = 25 Token = 15\n\t\tDW\t400\t* 2\t; Index = 26 Token = 0\n\t\tDW\t400\t* 2\t; Index = 26 Token = 1\n\t\tDW\t400\t* 2\t; Index = 26 Token = 2\n\t\tDW\t400\t* 2\t; Index = 26 Token = 3\n\t\tDW\t448\t* 2\t; Index = 26 Token = 4\n\t\tDW\t480\t* 2\t; Index = 26 Token = 5\n\t\tDW\t512\t* 2\t; Index = 26 Token = 6\n\t\tDW\t544\t* 2\t; Index = 26 Token = 7\n\t\tDW\t400\t* 2\t; Index = 26 Token = 8\n\t\tDW\t400\t* 2\t; Index = 26 Token = 9\n\t\tDW\t400\t* 2\t; Index = 26 Token = 10\n\t\tDW\t400\t* 2\t; Index = 26 Token = 11\n\t\tDW\t448\t* 2\t; Index = 26 Token = 12\n\t\tDW\t480\t* 2\t; Index = 26 Token = 13\n\t\tDW\t512\t* 2\t; Index = 26 Token = 14\n\t\tDW\t544\t* 2\t; Index = 26 Token = 15\n\t\tDW\t416\t* 2\t; Index = 27 Token = 0\n\t\tDW\t416\t* 2\t; Index = 27 Token = 1\n\t\tDW\t416\t* 2\t; Index = 27 Token = 2\n\t\tDW\t416\t* 2\t; Index = 27 Token = 3\n\t\tDW\t464\t* 2\t; Index = 27 Token = 4\n\t\tDW\t496\t* 2\t; Index = 27 Token = 5\n\t\tDW\t528\t* 2\t; Index = 27 Token = 6\n\t\tDW\t560\t* 2\t; Index = 27 Token = 7\n\t\tDW\t416\t* 2\t; Index = 27 Token = 8\n\t\tDW\t416\t* 2\t; Index = 27 Token = 9\n\t\tDW\t416\t* 2\t; Index = 27 Token = 10\n\t\tDW\t416\t* 2\t; Index = 27 Token = 11\n\t\tDW\t464\t* 2\t; Index = 27 Token = 12\n\t\tDW\t496\t* 2\t; Index = 27 Token = 13\n\t\tDW\t528\t* 2\t; Index = 27 Token = 14\n\t\tDW\t560\t* 2\t; Index = 27 Token = 15\n\t\tDW\t432\t* 2\t; Index = 28 Token = 0\n\t\tDW\t432\t* 2\t; Index = 28 Token = 1\n\t\tDW\t432\t* 2\t; Index = 28 Token = 2\n\t\tDW\t432\t* 2\t; Index = 28 Token = 3\n\t\tDW\t480\t* 2\t; Index = 28 Token = 4\n\t\tDW\t512\t* 2\t; Index = 28 Token = 5\n\t\tDW\t544\t* 2\t; Index = 28 Token = 6\n\t\tDW\t576\t* 2\t; Index = 28 Token = 7\n\t\tDW\t432\t* 2\t; Index = 28 Token = 8\n\t\tDW\t432\t* 2\t; Index = 28 Token = 9\n\t\tDW\t432\t* 2\t; Index = 28 Token = 10\n\t\tDW\t432\t* 2\t; Index = 28 Token = 11\n\t\tDW\t480\t* 2\t; Index = 28 Token = 12\n\t\tDW\t512\t* 2\t; Index = 28 Token = 13\n\t\tDW\t544\t* 2\t; Index = 28 Token = 14\n\t\tDW\t576\t* 2\t; Index = 28 Token = 15\n\t\tDW\t448\t* 2\t; Index = 29 Token = 0\n\t\tDW\t448\t* 2\t; Index = 29 Token = 1\n\t\tDW\t448\t* 2\t; Index = 29 Token = 2\n\t\tDW\t448\t* 2\t; Index = 29 Token = 3\n\t\tDW\t496\t* 2\t; Index = 29 Token = 4\n\t\tDW\t528\t* 2\t; Index = 29 Token = 5\n\t\tDW\t560\t* 2\t; Index = 29 Token = 6\n\t\tDW\t592\t* 2\t; Index = 29 Token = 7\n\t\tDW\t448\t* 2\t; Index = 29 Token = 8\n\t\tDW\t448\t* 2\t; Index = 29 Token = 9\n\t\tDW\t448\t* 2\t; Index = 29 Token = 10\n\t\tDW\t448\t* 2\t; Index = 29 Token = 11\n\t\tDW\t496\t* 2\t; Index = 29 Token = 12\n\t\tDW\t528\t* 2\t; Index = 29 Token = 13\n\t\tDW\t560\t* 2\t; Index = 29 Token = 14\n\t\tDW\t592\t* 2\t; Index = 29 Token = 15\n\t\tDW\t464\t* 2\t; Index = 30 Token = 0\n\t\tDW\t464\t* 2\t; Index = 30 Token = 1\n\t\tDW\t464\t* 2\t; Index = 30 Token = 2\n\t\tDW\t464\t* 2\t; Index = 30 Token = 3\n\t\tDW\t512\t* 2\t; Index = 30 Token = 4\n\t\tDW\t544\t* 2\t; Index = 30 Token = 5\n\t\tDW\t576\t* 2\t; Index = 30 Token = 6\n\t\tDW\t608\t* 2\t; Index = 30 Token = 7\n\t\tDW\t464\t* 2\t; Index = 30 Token = 8\n\t\tDW\t464\t* 2\t; Index = 30 Token = 9\n\t\tDW\t464\t* 2\t; Index = 30 Token = 10\n\t\tDW\t464\t* 2\t; Index = 30 Token = 11\n\t\tDW\t512\t* 2\t; Index = 30 Token = 12\n\t\tDW\t544\t* 2\t; Index = 30 Token = 13\n\t\tDW\t576\t* 2\t; Index = 30 Token = 14\n\t\tDW\t608\t* 2\t; Index = 30 Token = 15\n\t\tDW\t480\t* 2\t; Index = 31 Token = 0\n\t\tDW\t480\t* 2\t; Index = 31 Token = 1\n\t\tDW\t480\t* 2\t; Index = 31 Token = 2\n\t\tDW\t480\t* 2\t; Index = 31 Token = 3\n\t\tDW\t528\t* 2\t; Index = 31 Token = 4\n\t\tDW\t560\t* 2\t; Index = 31 Token = 5\n\t\tDW\t592\t* 2\t; Index = 31 Token = 6\n\t\tDW\t624\t* 2\t; Index = 31 Token = 7\n\t\tDW\t480\t* 2\t; Index = 31 Token = 8\n\t\tDW\t480\t* 2\t; Index = 31 Token = 9\n\t\tDW\t480\t* 2\t; Index = 31 Token = 10\n\t\tDW\t480\t* 2\t; Index = 31 Token = 11\n\t\tDW\t528\t* 2\t; Index = 31 Token = 12\n\t\tDW\t560\t* 2\t; Index = 31 Token = 13\n\t\tDW\t592\t* 2\t; Index = 31 Token = 14\n\t\tDW\t624\t* 2\t; Index = 31 Token = 15\n\t\tDW\t496\t* 2\t; Index = 32 Token = 0\n\t\tDW\t496\t* 2\t; Index = 32 Token = 1\n\t\tDW\t496\t* 2\t; Index = 32 Token = 2\n\t\tDW\t496\t* 2\t; Index = 32 Token = 3\n\t\tDW\t544\t* 2\t; Index = 32 Token = 4\n\t\tDW\t576\t* 2\t; Index = 32 Token = 5\n\t\tDW\t608\t* 2\t; Index = 32 Token = 6\n\t\tDW\t640\t* 2\t; Index = 32 Token = 7\n\t\tDW\t496\t* 2\t; Index = 32 Token = 8\n\t\tDW\t496\t* 2\t; Index = 32 Token = 9\n\t\tDW\t496\t* 2\t; Index = 32 Token = 10\n\t\tDW\t496\t* 2\t; Index = 32 Token = 11\n\t\tDW\t544\t* 2\t; Index = 32 Token = 12\n\t\tDW\t576\t* 2\t; Index = 32 Token = 13\n\t\tDW\t608\t* 2\t; Index = 32 Token = 14\n\t\tDW\t640\t* 2\t; Index = 32 Token = 15\n\t\tDW\t512\t* 2\t; Index = 33 Token = 0\n\t\tDW\t512\t* 2\t; Index = 33 Token = 1\n\t\tDW\t512\t* 2\t; Index = 33 Token = 2\n\t\tDW\t512\t* 2\t; Index = 33 Token = 3\n\t\tDW\t560\t* 2\t; Index = 33 Token = 4\n\t\tDW\t592\t* 2\t; Index = 33 Token = 5\n\t\tDW\t624\t* 2\t; Index = 33 Token = 6\n\t\tDW\t656\t* 2\t; Index = 33 Token = 7\n\t\tDW\t512\t* 2\t; Index = 33 Token = 8\n\t\tDW\t512\t* 2\t; Index = 33 Token = 9\n\t\tDW\t512\t* 2\t; Index = 33 Token = 10\n\t\tDW\t512\t* 2\t; Index = 33 Token = 11\n\t\tDW\t560\t* 2\t; Index = 33 Token = 12\n\t\tDW\t592\t* 2\t; Index = 33 Token = 13\n\t\tDW\t624\t* 2\t; Index = 33 Token = 14\n\t\tDW\t656\t* 2\t; Index = 33 Token = 15\n\t\tDW\t528\t* 2\t; Index = 34 Token = 0\n\t\tDW\t528\t* 2\t; Index = 34 Token = 1\n\t\tDW\t528\t* 2\t; Index = 34 Token = 2\n\t\tDW\t528\t* 2\t; Index = 34 Token = 3\n\t\tDW\t576\t* 2\t; Index = 34 Token = 4\n\t\tDW\t608\t* 2\t; Index = 34 Token = 5\n\t\tDW\t640\t* 2\t; Index = 34 Token = 6\n\t\tDW\t672\t* 2\t; Index = 34 Token = 7\n\t\tDW\t528\t* 2\t; Index = 34 Token = 8\n\t\tDW\t528\t* 2\t; Index = 34 Token = 9\n\t\tDW\t528\t* 2\t; Index = 34 Token = 10\n\t\tDW\t528\t* 2\t; Index = 34 Token = 11\n\t\tDW\t576\t* 2\t; Index = 34 Token = 12\n\t\tDW\t608\t* 2\t; Index = 34 Token = 13\n\t\tDW\t640\t* 2\t; Index = 34 Token = 14\n\t\tDW\t672\t* 2\t; Index = 34 Token = 15\n\t\tDW\t544\t* 2\t; Index = 35 Token = 0\n\t\tDW\t544\t* 2\t; Index = 35 Token = 1\n\t\tDW\t544\t* 2\t; Index = 35 Token = 2\n\t\tDW\t544\t* 2\t; Index = 35 Token = 3\n\t\tDW\t592\t* 2\t; Index = 35 Token = 4\n\t\tDW\t624\t* 2\t; Index = 35 Token = 5\n\t\tDW\t656\t* 2\t; Index = 35 Token = 6\n\t\tDW\t688\t* 2\t; Index = 35 Token = 7\n\t\tDW\t544\t* 2\t; Index = 35 Token = 8\n\t\tDW\t544\t* 2\t; Index = 35 Token = 9\n\t\tDW\t544\t* 2\t; Index = 35 Token = 10\n\t\tDW\t544\t* 2\t; Index = 35 Token = 11\n\t\tDW\t592\t* 2\t; Index = 35 Token = 12\n\t\tDW\t624\t* 2\t; Index = 35 Token = 13\n\t\tDW\t656\t* 2\t; Index = 35 Token = 14\n\t\tDW\t688\t* 2\t; Index = 35 Token = 15\n\t\tDW\t560\t* 2\t; Index = 36 Token = 0\n\t\tDW\t560\t* 2\t; Index = 36 Token = 1\n\t\tDW\t560\t* 2\t; Index = 36 Token = 2\n\t\tDW\t560\t* 2\t; Index = 36 Token = 3\n\t\tDW\t608\t* 2\t; Index = 36 Token = 4\n\t\tDW\t640\t* 2\t; Index = 36 Token = 5\n\t\tDW\t672\t* 2\t; Index = 36 Token = 6\n\t\tDW\t704\t* 2\t; Index = 36 Token = 7\n\t\tDW\t560\t* 2\t; Index = 36 Token = 8\n\t\tDW\t560\t* 2\t; Index = 36 Token = 9\n\t\tDW\t560\t* 2\t; Index = 36 Token = 10\n\t\tDW\t560\t* 2\t; Index = 36 Token = 11\n\t\tDW\t608\t* 2\t; Index = 36 Token = 12\n\t\tDW\t640\t* 2\t; Index = 36 Token = 13\n\t\tDW\t672\t* 2\t; Index = 36 Token = 14\n\t\tDW\t704\t* 2\t; Index = 36 Token = 15\n\t\tDW\t576\t* 2\t; Index = 37 Token = 0\n\t\tDW\t576\t* 2\t; Index = 37 Token = 1\n\t\tDW\t576\t* 2\t; Index = 37 Token = 2\n\t\tDW\t576\t* 2\t; Index = 37 Token = 3\n\t\tDW\t624\t* 2\t; Index = 37 Token = 4\n\t\tDW\t656\t* 2\t; Index = 37 Token = 5\n\t\tDW\t688\t* 2\t; Index = 37 Token = 6\n\t\tDW\t720\t* 2\t; Index = 37 Token = 7\n\t\tDW\t576\t* 2\t; Index = 37 Token = 8\n\t\tDW\t576\t* 2\t; Index = 37 Token = 9\n\t\tDW\t576\t* 2\t; Index = 37 Token = 10\n\t\tDW\t576\t* 2\t; Index = 37 Token = 11\n\t\tDW\t624\t* 2\t; Index = 37 Token = 12\n\t\tDW\t656\t* 2\t; Index = 37 Token = 13\n\t\tDW\t688\t* 2\t; Index = 37 Token = 14\n\t\tDW\t720\t* 2\t; Index = 37 Token = 15\n\t\tDW\t592\t* 2\t; Index = 38 Token = 0\n\t\tDW\t592\t* 2\t; Index = 38 Token = 1\n\t\tDW\t592\t* 2\t; Index = 38 Token = 2\n\t\tDW\t592\t* 2\t; Index = 38 Token = 3\n\t\tDW\t640\t* 2\t; Index = 38 Token = 4\n\t\tDW\t672\t* 2\t; Index = 38 Token = 5\n\t\tDW\t704\t* 2\t; Index = 38 Token = 6\n\t\tDW\t736\t* 2\t; Index = 38 Token = 7\n\t\tDW\t592\t* 2\t; Index = 38 Token = 8\n\t\tDW\t592\t* 2\t; Index = 38 Token = 9\n\t\tDW\t592\t* 2\t; Index = 38 Token = 10\n\t\tDW\t592\t* 2\t; Index = 38 Token = 11\n\t\tDW\t640\t* 2\t; Index = 38 Token = 12\n\t\tDW\t672\t* 2\t; Index = 38 Token = 13\n\t\tDW\t704\t* 2\t; Index = 38 Token = 14\n\t\tDW\t736\t* 2\t; Index = 38 Token = 15\n\t\tDW\t608\t* 2\t; Index = 39 Token = 0\n\t\tDW\t608\t* 2\t; Index = 39 Token = 1\n\t\tDW\t608\t* 2\t; Index = 39 Token = 2\n\t\tDW\t608\t* 2\t; Index = 39 Token = 3\n\t\tDW\t656\t* 2\t; Index = 39 Token = 4\n\t\tDW\t688\t* 2\t; Index = 39 Token = 5\n\t\tDW\t720\t* 2\t; Index = 39 Token = 6\n\t\tDW\t752\t* 2\t; Index = 39 Token = 7\n\t\tDW\t608\t* 2\t; Index = 39 Token = 8\n\t\tDW\t608\t* 2\t; Index = 39 Token = 9\n\t\tDW\t608\t* 2\t; Index = 39 Token = 10\n\t\tDW\t608\t* 2\t; Index = 39 Token = 11\n\t\tDW\t656\t* 2\t; Index = 39 Token = 12\n\t\tDW\t688\t* 2\t; Index = 39 Token = 13\n\t\tDW\t720\t* 2\t; Index = 39 Token = 14\n\t\tDW\t752\t* 2\t; Index = 39 Token = 15\n\t\tDW\t624\t* 2\t; Index = 40 Token = 0\n\t\tDW\t624\t* 2\t; Index = 40 Token = 1\n\t\tDW\t624\t* 2\t; Index = 40 Token = 2\n\t\tDW\t624\t* 2\t; Index = 40 Token = 3\n\t\tDW\t672\t* 2\t; Index = 40 Token = 4\n\t\tDW\t704\t* 2\t; Index = 40 Token = 5\n\t\tDW\t736\t* 2\t; Index = 40 Token = 6\n\t\tDW\t768\t* 2\t; Index = 40 Token = 7\n\t\tDW\t624\t* 2\t; Index = 40 Token = 8\n\t\tDW\t624\t* 2\t; Index = 40 Token = 9\n\t\tDW\t624\t* 2\t; Index = 40 Token = 10\n\t\tDW\t624\t* 2\t; Index = 40 Token = 11\n\t\tDW\t672\t* 2\t; Index = 40 Token = 12\n\t\tDW\t704\t* 2\t; Index = 40 Token = 13\n\t\tDW\t736\t* 2\t; Index = 40 Token = 14\n\t\tDW\t768\t* 2\t; Index = 40 Token = 15\n\t\tDW\t640\t* 2\t; Index = 41 Token = 0\n\t\tDW\t640\t* 2\t; Index = 41 Token = 1\n\t\tDW\t640\t* 2\t; Index = 41 Token = 2\n\t\tDW\t640\t* 2\t; Index = 41 Token = 3\n\t\tDW\t688\t* 2\t; Index = 41 Token = 4\n\t\tDW\t720\t* 2\t; Index = 41 Token = 5\n\t\tDW\t752\t* 2\t; Index = 41 Token = 6\n\t\tDW\t784\t* 2\t; Index = 41 Token = 7\n\t\tDW\t640\t* 2\t; Index = 41 Token = 8\n\t\tDW\t640\t* 2\t; Index = 41 Token = 9\n\t\tDW\t640\t* 2\t; Index = 41 Token = 10\n\t\tDW\t640\t* 2\t; Index = 41 Token = 11\n\t\tDW\t688\t* 2\t; Index = 41 Token = 12\n\t\tDW\t720\t* 2\t; Index = 41 Token = 13\n\t\tDW\t752\t* 2\t; Index = 41 Token = 14\n\t\tDW\t784\t* 2\t; Index = 41 Token = 15\n\t\tDW\t656\t* 2\t; Index = 42 Token = 0\n\t\tDW\t656\t* 2\t; Index = 42 Token = 1\n\t\tDW\t656\t* 2\t; Index = 42 Token = 2\n\t\tDW\t656\t* 2\t; Index = 42 Token = 3\n\t\tDW\t704\t* 2\t; Index = 42 Token = 4\n\t\tDW\t736\t* 2\t; Index = 42 Token = 5\n\t\tDW\t768\t* 2\t; Index = 42 Token = 6\n\t\tDW\t800\t* 2\t; Index = 42 Token = 7\n\t\tDW\t656\t* 2\t; Index = 42 Token = 8\n\t\tDW\t656\t* 2\t; Index = 42 Token = 9\n\t\tDW\t656\t* 2\t; Index = 42 Token = 10\n\t\tDW\t656\t* 2\t; Index = 42 Token = 11\n\t\tDW\t704\t* 2\t; Index = 42 Token = 12\n\t\tDW\t736\t* 2\t; Index = 42 Token = 13\n\t\tDW\t768\t* 2\t; Index = 42 Token = 14\n\t\tDW\t800\t* 2\t; Index = 42 Token = 15\n\t\tDW\t672\t* 2\t; Index = 43 Token = 0\n\t\tDW\t672\t* 2\t; Index = 43 Token = 1\n\t\tDW\t672\t* 2\t; Index = 43 Token = 2\n\t\tDW\t672\t* 2\t; Index = 43 Token = 3\n\t\tDW\t720\t* 2\t; Index = 43 Token = 4\n\t\tDW\t752\t* 2\t; Index = 43 Token = 5\n\t\tDW\t784\t* 2\t; Index = 43 Token = 6\n\t\tDW\t816\t* 2\t; Index = 43 Token = 7\n\t\tDW\t672\t* 2\t; Index = 43 Token = 8\n\t\tDW\t672\t* 2\t; Index = 43 Token = 9\n\t\tDW\t672\t* 2\t; Index = 43 Token = 10\n\t\tDW\t672\t* 2\t; Index = 43 Token = 11\n\t\tDW\t720\t* 2\t; Index = 43 Token = 12\n\t\tDW\t752\t* 2\t; Index = 43 Token = 13\n\t\tDW\t784\t* 2\t; Index = 43 Token = 14\n\t\tDW\t816\t* 2\t; Index = 43 Token = 15\n\t\tDW\t688\t* 2\t; Index = 44 Token = 0\n\t\tDW\t688\t* 2\t; Index = 44 Token = 1\n\t\tDW\t688\t* 2\t; Index = 44 Token = 2\n\t\tDW\t688\t* 2\t; Index = 44 Token = 3\n\t\tDW\t736\t* 2\t; Index = 44 Token = 4\n\t\tDW\t768\t* 2\t; Index = 44 Token = 5\n\t\tDW\t800\t* 2\t; Index = 44 Token = 6\n\t\tDW\t832\t* 2\t; Index = 44 Token = 7\n\t\tDW\t688\t* 2\t; Index = 44 Token = 8\n\t\tDW\t688\t* 2\t; Index = 44 Token = 9\n\t\tDW\t688\t* 2\t; Index = 44 Token = 10\n\t\tDW\t688\t* 2\t; Index = 44 Token = 11\n\t\tDW\t736\t* 2\t; Index = 44 Token = 12\n\t\tDW\t768\t* 2\t; Index = 44 Token = 13\n\t\tDW\t800\t* 2\t; Index = 44 Token = 14\n\t\tDW\t832\t* 2\t; Index = 44 Token = 15\n\t\tDW\t704\t* 2\t; Index = 45 Token = 0\n\t\tDW\t704\t* 2\t; Index = 45 Token = 1\n\t\tDW\t704\t* 2\t; Index = 45 Token = 2\n\t\tDW\t704\t* 2\t; Index = 45 Token = 3\n\t\tDW\t752\t* 2\t; Index = 45 Token = 4\n\t\tDW\t784\t* 2\t; Index = 45 Token = 5\n\t\tDW\t816\t* 2\t; Index = 45 Token = 6\n\t\tDW\t848\t* 2\t; Index = 45 Token = 7\n\t\tDW\t704\t* 2\t; Index = 45 Token = 8\n\t\tDW\t704\t* 2\t; Index = 45 Token = 9\n\t\tDW\t704\t* 2\t; Index = 45 Token = 10\n\t\tDW\t704\t* 2\t; Index = 45 Token = 11\n\t\tDW\t752\t* 2\t; Index = 45 Token = 12\n\t\tDW\t784\t* 2\t; Index = 45 Token = 13\n\t\tDW\t816\t* 2\t; Index = 45 Token = 14\n\t\tDW\t848\t* 2\t; Index = 45 Token = 15\n\t\tDW\t720\t* 2\t; Index = 46 Token = 0\n\t\tDW\t720\t* 2\t; Index = 46 Token = 1\n\t\tDW\t720\t* 2\t; Index = 46 Token = 2\n\t\tDW\t720\t* 2\t; Index = 46 Token = 3\n\t\tDW\t768\t* 2\t; Index = 46 Token = 4\n\t\tDW\t800\t* 2\t; Index = 46 Token = 5\n\t\tDW\t832\t* 2\t; Index = 46 Token = 6\n\t\tDW\t864\t* 2\t; Index = 46 Token = 7\n\t\tDW\t720\t* 2\t; Index = 46 Token = 8\n\t\tDW\t720\t* 2\t; Index = 46 Token = 9\n\t\tDW\t720\t* 2\t; Index = 46 Token = 10\n\t\tDW\t720\t* 2\t; Index = 46 Token = 11\n\t\tDW\t768\t* 2\t; Index = 46 Token = 12\n\t\tDW\t800\t* 2\t; Index = 46 Token = 13\n\t\tDW\t832\t* 2\t; Index = 46 Token = 14\n\t\tDW\t864\t* 2\t; Index = 46 Token = 15\n\t\tDW\t736\t* 2\t; Index = 47 Token = 0\n\t\tDW\t736\t* 2\t; Index = 47 Token = 1\n\t\tDW\t736\t* 2\t; Index = 47 Token = 2\n\t\tDW\t736\t* 2\t; Index = 47 Token = 3\n\t\tDW\t784\t* 2\t; Index = 47 Token = 4\n\t\tDW\t816\t* 2\t; Index = 47 Token = 5\n\t\tDW\t848\t* 2\t; Index = 47 Token = 6\n\t\tDW\t880\t* 2\t; Index = 47 Token = 7\n\t\tDW\t736\t* 2\t; Index = 47 Token = 8\n\t\tDW\t736\t* 2\t; Index = 47 Token = 9\n\t\tDW\t736\t* 2\t; Index = 47 Token = 10\n\t\tDW\t736\t* 2\t; Index = 47 Token = 11\n\t\tDW\t784\t* 2\t; Index = 47 Token = 12\n\t\tDW\t816\t* 2\t; Index = 47 Token = 13\n\t\tDW\t848\t* 2\t; Index = 47 Token = 14\n\t\tDW\t880\t* 2\t; Index = 47 Token = 15\n\t\tDW\t752\t* 2\t; Index = 48 Token = 0\n\t\tDW\t752\t* 2\t; Index = 48 Token = 1\n\t\tDW\t752\t* 2\t; Index = 48 Token = 2\n\t\tDW\t752\t* 2\t; Index = 48 Token = 3\n\t\tDW\t800\t* 2\t; Index = 48 Token = 4\n\t\tDW\t832\t* 2\t; Index = 48 Token = 5\n\t\tDW\t864\t* 2\t; Index = 48 Token = 6\n\t\tDW\t896\t* 2\t; Index = 48 Token = 7\n\t\tDW\t752\t* 2\t; Index = 48 Token = 8\n\t\tDW\t752\t* 2\t; Index = 48 Token = 9\n\t\tDW\t752\t* 2\t; Index = 48 Token = 10\n\t\tDW\t752\t* 2\t; Index = 48 Token = 11\n\t\tDW\t800\t* 2\t; Index = 48 Token = 12\n\t\tDW\t832\t* 2\t; Index = 48 Token = 13\n\t\tDW\t864\t* 2\t; Index = 48 Token = 14\n\t\tDW\t896\t* 2\t; Index = 48 Token = 15\n\t\tDW\t768\t* 2\t; Index = 49 Token = 0\n\t\tDW\t768\t* 2\t; Index = 49 Token = 1\n\t\tDW\t768\t* 2\t; Index = 49 Token = 2\n\t\tDW\t768\t* 2\t; Index = 49 Token = 3\n\t\tDW\t816\t* 2\t; Index = 49 Token = 4\n\t\tDW\t848\t* 2\t; Index = 49 Token = 5\n\t\tDW\t880\t* 2\t; Index = 49 Token = 6\n\t\tDW\t912\t* 2\t; Index = 49 Token = 7\n\t\tDW\t768\t* 2\t; Index = 49 Token = 8\n\t\tDW\t768\t* 2\t; Index = 49 Token = 9\n\t\tDW\t768\t* 2\t; Index = 49 Token = 10\n\t\tDW\t768\t* 2\t; Index = 49 Token = 11\n\t\tDW\t816\t* 2\t; Index = 49 Token = 12\n\t\tDW\t848\t* 2\t; Index = 49 Token = 13\n\t\tDW\t880\t* 2\t; Index = 49 Token = 14\n\t\tDW\t912\t* 2\t; Index = 49 Token = 15\n\t\tDW\t784\t* 2\t; Index = 50 Token = 0\n\t\tDW\t784\t* 2\t; Index = 50 Token = 1\n\t\tDW\t784\t* 2\t; Index = 50 Token = 2\n\t\tDW\t784\t* 2\t; Index = 50 Token = 3\n\t\tDW\t832\t* 2\t; Index = 50 Token = 4\n\t\tDW\t864\t* 2\t; Index = 50 Token = 5\n\t\tDW\t896\t* 2\t; Index = 50 Token = 6\n\t\tDW\t928\t* 2\t; Index = 50 Token = 7\n\t\tDW\t784\t* 2\t; Index = 50 Token = 8\n\t\tDW\t784\t* 2\t; Index = 50 Token = 9\n\t\tDW\t784\t* 2\t; Index = 50 Token = 10\n\t\tDW\t784\t* 2\t; Index = 50 Token = 11\n\t\tDW\t832\t* 2\t; Index = 50 Token = 12\n\t\tDW\t864\t* 2\t; Index = 50 Token = 13\n\t\tDW\t896\t* 2\t; Index = 50 Token = 14\n\t\tDW\t928\t* 2\t; Index = 50 Token = 15\n\t\tDW\t800\t* 2\t; Index = 51 Token = 0\n\t\tDW\t800\t* 2\t; Index = 51 Token = 1\n\t\tDW\t800\t* 2\t; Index = 51 Token = 2\n\t\tDW\t800\t* 2\t; Index = 51 Token = 3\n\t\tDW\t848\t* 2\t; Index = 51 Token = 4\n\t\tDW\t880\t* 2\t; Index = 51 Token = 5\n\t\tDW\t912\t* 2\t; Index = 51 Token = 6\n\t\tDW\t944\t* 2\t; Index = 51 Token = 7\n\t\tDW\t800\t* 2\t; Index = 51 Token = 8\n\t\tDW\t800\t* 2\t; Index = 51 Token = 9\n\t\tDW\t800\t* 2\t; Index = 51 Token = 10\n\t\tDW\t800\t* 2\t; Index = 51 Token = 11\n\t\tDW\t848\t* 2\t; Index = 51 Token = 12\n\t\tDW\t880\t* 2\t; Index = 51 Token = 13\n\t\tDW\t912\t* 2\t; Index = 51 Token = 14\n\t\tDW\t944\t* 2\t; Index = 51 Token = 15\n\t\tDW\t816\t* 2\t; Index = 52 Token = 0\n\t\tDW\t816\t* 2\t; Index = 52 Token = 1\n\t\tDW\t816\t* 2\t; Index = 52 Token = 2\n\t\tDW\t816\t* 2\t; Index = 52 Token = 3\n\t\tDW\t864\t* 2\t; Index = 52 Token = 4\n\t\tDW\t896\t* 2\t; Index = 52 Token = 5\n\t\tDW\t928\t* 2\t; Index = 52 Token = 6\n\t\tDW\t960\t* 2\t; Index = 52 Token = 7\n\t\tDW\t816\t* 2\t; Index = 52 Token = 8\n\t\tDW\t816\t* 2\t; Index = 52 Token = 9\n\t\tDW\t816\t* 2\t; Index = 52 Token = 10\n\t\tDW\t816\t* 2\t; Index = 52 Token = 11\n\t\tDW\t864\t* 2\t; Index = 52 Token = 12\n\t\tDW\t896\t* 2\t; Index = 52 Token = 13\n\t\tDW\t928\t* 2\t; Index = 52 Token = 14\n\t\tDW\t960\t* 2\t; Index = 52 Token = 15\n\t\tDW\t832\t* 2\t; Index = 53 Token = 0\n\t\tDW\t832\t* 2\t; Index = 53 Token = 1\n\t\tDW\t832\t* 2\t; Index = 53 Token = 2\n\t\tDW\t832\t* 2\t; Index = 53 Token = 3\n\t\tDW\t880\t* 2\t; Index = 53 Token = 4\n\t\tDW\t912\t* 2\t; Index = 53 Token = 5\n\t\tDW\t944\t* 2\t; Index = 53 Token = 6\n\t\tDW\t976\t* 2\t; Index = 53 Token = 7\n\t\tDW\t832\t* 2\t; Index = 53 Token = 8\n\t\tDW\t832\t* 2\t; Index = 53 Token = 9\n\t\tDW\t832\t* 2\t; Index = 53 Token = 10\n\t\tDW\t832\t* 2\t; Index = 53 Token = 11\n\t\tDW\t880\t* 2\t; Index = 53 Token = 12\n\t\tDW\t912\t* 2\t; Index = 53 Token = 13\n\t\tDW\t944\t* 2\t; Index = 53 Token = 14\n\t\tDW\t976\t* 2\t; Index = 53 Token = 15\n\t\tDW\t848\t* 2\t; Index = 54 Token = 0\n\t\tDW\t848\t* 2\t; Index = 54 Token = 1\n\t\tDW\t848\t* 2\t; Index = 54 Token = 2\n\t\tDW\t848\t* 2\t; Index = 54 Token = 3\n\t\tDW\t896\t* 2\t; Index = 54 Token = 4\n\t\tDW\t928\t* 2\t; Index = 54 Token = 5\n\t\tDW\t960\t* 2\t; Index = 54 Token = 6\n\t\tDW\t992\t* 2\t; Index = 54 Token = 7\n\t\tDW\t848\t* 2\t; Index = 54 Token = 8\n\t\tDW\t848\t* 2\t; Index = 54 Token = 9\n\t\tDW\t848\t* 2\t; Index = 54 Token = 10\n\t\tDW\t848\t* 2\t; Index = 54 Token = 11\n\t\tDW\t896\t* 2\t; Index = 54 Token = 12\n\t\tDW\t928\t* 2\t; Index = 54 Token = 13\n\t\tDW\t960\t* 2\t; Index = 54 Token = 14\n\t\tDW\t992\t* 2\t; Index = 54 Token = 15\n\t\tDW\t864\t* 2\t; Index = 55 Token = 0\n\t\tDW\t864\t* 2\t; Index = 55 Token = 1\n\t\tDW\t864\t* 2\t; Index = 55 Token = 2\n\t\tDW\t864\t* 2\t; Index = 55 Token = 3\n\t\tDW\t912\t* 2\t; Index = 55 Token = 4\n\t\tDW\t944\t* 2\t; Index = 55 Token = 5\n\t\tDW\t976\t* 2\t; Index = 55 Token = 6\n\t\tDW\t1008\t* 2\t; Index = 55 Token = 7\n\t\tDW\t864\t* 2\t; Index = 55 Token = 8\n\t\tDW\t864\t* 2\t; Index = 55 Token = 9\n\t\tDW\t864\t* 2\t; Index = 55 Token = 10\n\t\tDW\t864\t* 2\t; Index = 55 Token = 11\n\t\tDW\t912\t* 2\t; Index = 55 Token = 12\n\t\tDW\t944\t* 2\t; Index = 55 Token = 13\n\t\tDW\t976\t* 2\t; Index = 55 Token = 14\n\t\tDW\t1008\t* 2\t; Index = 55 Token = 15\n\t\tDW\t880\t* 2\t; Index = 56 Token = 0\n\t\tDW\t880\t* 2\t; Index = 56 Token = 1\n\t\tDW\t880\t* 2\t; Index = 56 Token = 2\n\t\tDW\t880\t* 2\t; Index = 56 Token = 3\n\t\tDW\t928\t* 2\t; Index = 56 Token = 4\n\t\tDW\t960\t* 2\t; Index = 56 Token = 5\n\t\tDW\t992\t* 2\t; Index = 56 Token = 6\n\t\tDW\t1024\t* 2\t; Index = 56 Token = 7\n\t\tDW\t880\t* 2\t; Index = 56 Token = 8\n\t\tDW\t880\t* 2\t; Index = 56 Token = 9\n\t\tDW\t880\t* 2\t; Index = 56 Token = 10\n\t\tDW\t880\t* 2\t; Index = 56 Token = 11\n\t\tDW\t928\t* 2\t; Index = 56 Token = 12\n\t\tDW\t960\t* 2\t; Index = 56 Token = 13\n\t\tDW\t992\t* 2\t; Index = 56 Token = 14\n\t\tDW\t1024\t* 2\t; Index = 56 Token = 15\n\t\tDW\t896\t* 2\t; Index = 57 Token = 0\n\t\tDW\t896\t* 2\t; Index = 57 Token = 1\n\t\tDW\t896\t* 2\t; Index = 57 Token = 2\n\t\tDW\t896\t* 2\t; Index = 57 Token = 3\n\t\tDW\t944\t* 2\t; Index = 57 Token = 4\n\t\tDW\t976\t* 2\t; Index = 57 Token = 5\n\t\tDW\t1008\t* 2\t; Index = 57 Token = 6\n\t\tDW\t1040\t* 2\t; Index = 57 Token = 7\n\t\tDW\t896\t* 2\t; Index = 57 Token = 8\n\t\tDW\t896\t* 2\t; Index = 57 Token = 9\n\t\tDW\t896\t* 2\t; Index = 57 Token = 10\n\t\tDW\t896\t* 2\t; Index = 57 Token = 11\n\t\tDW\t944\t* 2\t; Index = 57 Token = 12\n\t\tDW\t976\t* 2\t; Index = 57 Token = 13\n\t\tDW\t1008\t* 2\t; Index = 57 Token = 14\n\t\tDW\t1040\t* 2\t; Index = 57 Token = 15\n\t\tDW\t912\t* 2\t; Index = 58 Token = 0\n\t\tDW\t912\t* 2\t; Index = 58 Token = 1\n\t\tDW\t912\t* 2\t; Index = 58 Token = 2\n\t\tDW\t912\t* 2\t; Index = 58 Token = 3\n\t\tDW\t960\t* 2\t; Index = 58 Token = 4\n\t\tDW\t992\t* 2\t; Index = 58 Token = 5\n\t\tDW\t1024\t* 2\t; Index = 58 Token = 6\n\t\tDW\t1056\t* 2\t; Index = 58 Token = 7\n\t\tDW\t912\t* 2\t; Index = 58 Token = 8\n\t\tDW\t912\t* 2\t; Index = 58 Token = 9\n\t\tDW\t912\t* 2\t; Index = 58 Token = 10\n\t\tDW\t912\t* 2\t; Index = 58 Token = 11\n\t\tDW\t960\t* 2\t; Index = 58 Token = 12\n\t\tDW\t992\t* 2\t; Index = 58 Token = 13\n\t\tDW\t1024\t* 2\t; Index = 58 Token = 14\n\t\tDW\t1056\t* 2\t; Index = 58 Token = 15\n\t\tDW\t928\t* 2\t; Index = 59 Token = 0\n\t\tDW\t928\t* 2\t; Index = 59 Token = 1\n\t\tDW\t928\t* 2\t; Index = 59 Token = 2\n\t\tDW\t928\t* 2\t; Index = 59 Token = 3\n\t\tDW\t976\t* 2\t; Index = 59 Token = 4\n\t\tDW\t1008\t* 2\t; Index = 59 Token = 5\n\t\tDW\t1040\t* 2\t; Index = 59 Token = 6\n\t\tDW\t1072\t* 2\t; Index = 59 Token = 7\n\t\tDW\t928\t* 2\t; Index = 59 Token = 8\n\t\tDW\t928\t* 2\t; Index = 59 Token = 9\n\t\tDW\t928\t* 2\t; Index = 59 Token = 10\n\t\tDW\t928\t* 2\t; Index = 59 Token = 11\n\t\tDW\t976\t* 2\t; Index = 59 Token = 12\n\t\tDW\t1008\t* 2\t; Index = 59 Token = 13\n\t\tDW\t1040\t* 2\t; Index = 59 Token = 14\n\t\tDW\t1072\t* 2\t; Index = 59 Token = 15\n\t\tDW\t944\t* 2\t; Index = 60 Token = 0\n\t\tDW\t944\t* 2\t; Index = 60 Token = 1\n\t\tDW\t944\t* 2\t; Index = 60 Token = 2\n\t\tDW\t944\t* 2\t; Index = 60 Token = 3\n\t\tDW\t992\t* 2\t; Index = 60 Token = 4\n\t\tDW\t1024\t* 2\t; Index = 60 Token = 5\n\t\tDW\t1056\t* 2\t; Index = 60 Token = 6\n\t\tDW\t1088\t* 2\t; Index = 60 Token = 7\n\t\tDW\t944\t* 2\t; Index = 60 Token = 8\n\t\tDW\t944\t* 2\t; Index = 60 Token = 9\n\t\tDW\t944\t* 2\t; Index = 60 Token = 10\n\t\tDW\t944\t* 2\t; Index = 60 Token = 11\n\t\tDW\t992\t* 2\t; Index = 60 Token = 12\n\t\tDW\t1024\t* 2\t; Index = 60 Token = 13\n\t\tDW\t1056\t* 2\t; Index = 60 Token = 14\n\t\tDW\t1088\t* 2\t; Index = 60 Token = 15\n\t\tDW\t960\t* 2\t; Index = 61 Token = 0\n\t\tDW\t960\t* 2\t; Index = 61 Token = 1\n\t\tDW\t960\t* 2\t; Index = 61 Token = 2\n\t\tDW\t960\t* 2\t; Index = 61 Token = 3\n\t\tDW\t1008\t* 2\t; Index = 61 Token = 4\n\t\tDW\t1040\t* 2\t; Index = 61 Token = 5\n\t\tDW\t1072\t* 2\t; Index = 61 Token = 6\n\t\tDW\t1104\t* 2\t; Index = 61 Token = 7\n\t\tDW\t960\t* 2\t; Index = 61 Token = 8\n\t\tDW\t960\t* 2\t; Index = 61 Token = 9\n\t\tDW\t960\t* 2\t; Index = 61 Token = 10\n\t\tDW\t960\t* 2\t; Index = 61 Token = 11\n\t\tDW\t1008\t* 2\t; Index = 61 Token = 12\n\t\tDW\t1040\t* 2\t; Index = 61 Token = 13\n\t\tDW\t1072\t* 2\t; Index = 61 Token = 14\n\t\tDW\t1104\t* 2\t; Index = 61 Token = 15\n\t\tDW\t976\t* 2\t; Index = 62 Token = 0\n\t\tDW\t976\t* 2\t; Index = 62 Token = 1\n\t\tDW\t976\t* 2\t; Index = 62 Token = 2\n\t\tDW\t976\t* 2\t; Index = 62 Token = 3\n\t\tDW\t1024\t* 2\t; Index = 62 Token = 4\n\t\tDW\t1056\t* 2\t; Index = 62 Token = 5\n\t\tDW\t1088\t* 2\t; Index = 62 Token = 6\n\t\tDW\t1120\t* 2\t; Index = 62 Token = 7\n\t\tDW\t976\t* 2\t; Index = 62 Token = 8\n\t\tDW\t976\t* 2\t; Index = 62 Token = 9\n\t\tDW\t976\t* 2\t; Index = 62 Token = 10\n\t\tDW\t976\t* 2\t; Index = 62 Token = 11\n\t\tDW\t1024\t* 2\t; Index = 62 Token = 12\n\t\tDW\t1056\t* 2\t; Index = 62 Token = 13\n\t\tDW\t1088\t* 2\t; Index = 62 Token = 14\n\t\tDW\t1120\t* 2\t; Index = 62 Token = 15\n\t\tDW\t992\t* 2\t; Index = 63 Token = 0\n\t\tDW\t992\t* 2\t; Index = 63 Token = 1\n\t\tDW\t992\t* 2\t; Index = 63 Token = 2\n\t\tDW\t992\t* 2\t; Index = 63 Token = 3\n\t\tDW\t1040\t* 2\t; Index = 63 Token = 4\n\t\tDW\t1072\t* 2\t; Index = 63 Token = 5\n\t\tDW\t1104\t* 2\t; Index = 63 Token = 6\n\t\tDW\t1136\t* 2\t; Index = 63 Token = 7\n\t\tDW\t992\t* 2\t; Index = 63 Token = 8\n\t\tDW\t992\t* 2\t; Index = 63 Token = 9\n\t\tDW\t992\t* 2\t; Index = 63 Token = 10\n\t\tDW\t992\t* 2\t; Index = 63 Token = 11\n\t\tDW\t1040\t* 2\t; Index = 63 Token = 12\n\t\tDW\t1072\t* 2\t; Index = 63 Token = 13\n\t\tDW\t1104\t* 2\t; Index = 63 Token = 14\n\t\tDW\t1136\t* 2\t; Index = 63 Token = 15\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 0\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 1\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 2\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 3\n\t\tDW\t1056\t* 2\t; Index = 64 Token = 4\n\t\tDW\t1088\t* 2\t; Index = 64 Token = 5\n\t\tDW\t1120\t* 2\t; Index = 64 Token = 6\n\t\tDW\t1152\t* 2\t; Index = 64 Token = 7\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 8\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 9\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 10\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 11\n\t\tDW\t1056\t* 2\t; Index = 64 Token = 12\n\t\tDW\t1088\t* 2\t; Index = 64 Token = 13\n\t\tDW\t1120\t* 2\t; Index = 64 Token = 14\n\t\tDW\t1152\t* 2\t; Index = 64 Token = 15\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 0\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 1\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 2\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 3\n\t\tDW\t1072\t* 2\t; Index = 65 Token = 4\n\t\tDW\t1104\t* 2\t; Index = 65 Token = 5\n\t\tDW\t1136\t* 2\t; Index = 65 Token = 6\n\t\tDW\t1168\t* 2\t; Index = 65 Token = 7\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 8\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 9\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 10\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 11\n\t\tDW\t1072\t* 2\t; Index = 65 Token = 12\n\t\tDW\t1104\t* 2\t; Index = 65 Token = 13\n\t\tDW\t1136\t* 2\t; Index = 65 Token = 14\n\t\tDW\t1168\t* 2\t; Index = 65 Token = 15\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 0\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 1\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 2\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 3\n\t\tDW\t1088\t* 2\t; Index = 66 Token = 4\n\t\tDW\t1120\t* 2\t; Index = 66 Token = 5\n\t\tDW\t1152\t* 2\t; Index = 66 Token = 6\n\t\tDW\t1184\t* 2\t; Index = 66 Token = 7\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 8\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 9\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 10\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 11\n\t\tDW\t1088\t* 2\t; Index = 66 Token = 12\n\t\tDW\t1120\t* 2\t; Index = 66 Token = 13\n\t\tDW\t1152\t* 2\t; Index = 66 Token = 14\n\t\tDW\t1184\t* 2\t; Index = 66 Token = 15\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 0\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 1\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 2\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 3\n\t\tDW\t1104\t* 2\t; Index = 67 Token = 4\n\t\tDW\t1136\t* 2\t; Index = 67 Token = 5\n\t\tDW\t1168\t* 2\t; Index = 67 Token = 6\n\t\tDW\t1200\t* 2\t; Index = 67 Token = 7\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 8\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 9\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 10\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 11\n\t\tDW\t1104\t* 2\t; Index = 67 Token = 12\n\t\tDW\t1136\t* 2\t; Index = 67 Token = 13\n\t\tDW\t1168\t* 2\t; Index = 67 Token = 14\n\t\tDW\t1200\t* 2\t; Index = 67 Token = 15\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 0\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 1\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 2\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 3\n\t\tDW\t1120\t* 2\t; Index = 68 Token = 4\n\t\tDW\t1152\t* 2\t; Index = 68 Token = 5\n\t\tDW\t1184\t* 2\t; Index = 68 Token = 6\n\t\tDW\t1216\t* 2\t; Index = 68 Token = 7\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 8\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 9\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 10\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 11\n\t\tDW\t1120\t* 2\t; Index = 68 Token = 12\n\t\tDW\t1152\t* 2\t; Index = 68 Token = 13\n\t\tDW\t1184\t* 2\t; Index = 68 Token = 14\n\t\tDW\t1216\t* 2\t; Index = 68 Token = 15\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 0\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 1\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 2\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 3\n\t\tDW\t1136\t* 2\t; Index = 69 Token = 4\n\t\tDW\t1168\t* 2\t; Index = 69 Token = 5\n\t\tDW\t1200\t* 2\t; Index = 69 Token = 6\n\t\tDW\t1232\t* 2\t; Index = 69 Token = 7\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 8\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 9\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 10\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 11\n\t\tDW\t1136\t* 2\t; Index = 69 Token = 12\n\t\tDW\t1168\t* 2\t; Index = 69 Token = 13\n\t\tDW\t1200\t* 2\t; Index = 69 Token = 14\n\t\tDW\t1232\t* 2\t; Index = 69 Token = 15\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 0\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 1\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 2\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 3\n\t\tDW\t1152\t* 2\t; Index = 70 Token = 4\n\t\tDW\t1184\t* 2\t; Index = 70 Token = 5\n\t\tDW\t1216\t* 2\t; Index = 70 Token = 6\n\t\tDW\t1248\t* 2\t; Index = 70 Token = 7\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 8\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 9\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 10\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 11\n\t\tDW\t1152\t* 2\t; Index = 70 Token = 12\n\t\tDW\t1184\t* 2\t; Index = 70 Token = 13\n\t\tDW\t1216\t* 2\t; Index = 70 Token = 14\n\t\tDW\t1248\t* 2\t; Index = 70 Token = 15\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 0\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 1\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 2\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 3\n\t\tDW\t1168\t* 2\t; Index = 71 Token = 4\n\t\tDW\t1200\t* 2\t; Index = 71 Token = 5\n\t\tDW\t1232\t* 2\t; Index = 71 Token = 6\n\t\tDW\t1264\t* 2\t; Index = 71 Token = 7\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 8\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 9\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 10\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 11\n\t\tDW\t1168\t* 2\t; Index = 71 Token = 12\n\t\tDW\t1200\t* 2\t; Index = 71 Token = 13\n\t\tDW\t1232\t* 2\t; Index = 71 Token = 14\n\t\tDW\t1264\t* 2\t; Index = 71 Token = 15\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 0\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 1\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 2\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 3\n\t\tDW\t1184\t* 2\t; Index = 72 Token = 4\n\t\tDW\t1216\t* 2\t; Index = 72 Token = 5\n\t\tDW\t1248\t* 2\t; Index = 72 Token = 6\n\t\tDW\t1280\t* 2\t; Index = 72 Token = 7\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 8\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 9\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 10\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 11\n\t\tDW\t1184\t* 2\t; Index = 72 Token = 12\n\t\tDW\t1216\t* 2\t; Index = 72 Token = 13\n\t\tDW\t1248\t* 2\t; Index = 72 Token = 14\n\t\tDW\t1280\t* 2\t; Index = 72 Token = 15\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 0\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 1\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 2\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 3\n\t\tDW\t1200\t* 2\t; Index = 73 Token = 4\n\t\tDW\t1232\t* 2\t; Index = 73 Token = 5\n\t\tDW\t1264\t* 2\t; Index = 73 Token = 6\n\t\tDW\t1296\t* 2\t; Index = 73 Token = 7\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 8\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 9\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 10\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 11\n\t\tDW\t1200\t* 2\t; Index = 73 Token = 12\n\t\tDW\t1232\t* 2\t; Index = 73 Token = 13\n\t\tDW\t1264\t* 2\t; Index = 73 Token = 14\n\t\tDW\t1296\t* 2\t; Index = 73 Token = 15\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 0\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 1\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 2\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 3\n\t\tDW\t1216\t* 2\t; Index = 74 Token = 4\n\t\tDW\t1248\t* 2\t; Index = 74 Token = 5\n\t\tDW\t1280\t* 2\t; Index = 74 Token = 6\n\t\tDW\t1312\t* 2\t; Index = 74 Token = 7\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 8\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 9\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 10\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 11\n\t\tDW\t1216\t* 2\t; Index = 74 Token = 12\n\t\tDW\t1248\t* 2\t; Index = 74 Token = 13\n\t\tDW\t1280\t* 2\t; Index = 74 Token = 14\n\t\tDW\t1312\t* 2\t; Index = 74 Token = 15\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 0\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 1\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 2\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 3\n\t\tDW\t1232\t* 2\t; Index = 75 Token = 4\n\t\tDW\t1264\t* 2\t; Index = 75 Token = 5\n\t\tDW\t1296\t* 2\t; Index = 75 Token = 6\n\t\tDW\t1328\t* 2\t; Index = 75 Token = 7\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 8\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 9\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 10\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 11\n\t\tDW\t1232\t* 2\t; Index = 75 Token = 12\n\t\tDW\t1264\t* 2\t; Index = 75 Token = 13\n\t\tDW\t1296\t* 2\t; Index = 75 Token = 14\n\t\tDW\t1328\t* 2\t; Index = 75 Token = 15\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 0\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 1\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 2\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 3\n\t\tDW\t1248\t* 2\t; Index = 76 Token = 4\n\t\tDW\t1280\t* 2\t; Index = 76 Token = 5\n\t\tDW\t1312\t* 2\t; Index = 76 Token = 6\n\t\tDW\t1344\t* 2\t; Index = 76 Token = 7\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 8\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 9\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 10\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 11\n\t\tDW\t1248\t* 2\t; Index = 76 Token = 12\n\t\tDW\t1280\t* 2\t; Index = 76 Token = 13\n\t\tDW\t1312\t* 2\t; Index = 76 Token = 14\n\t\tDW\t1344\t* 2\t; Index = 76 Token = 15\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 0\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 1\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 2\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 3\n\t\tDW\t1264\t* 2\t; Index = 77 Token = 4\n\t\tDW\t1296\t* 2\t; Index = 77 Token = 5\n\t\tDW\t1328\t* 2\t; Index = 77 Token = 6\n\t\tDW\t1360\t* 2\t; Index = 77 Token = 7\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 8\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 9\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 10\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 11\n\t\tDW\t1264\t* 2\t; Index = 77 Token = 12\n\t\tDW\t1296\t* 2\t; Index = 77 Token = 13\n\t\tDW\t1328\t* 2\t; Index = 77 Token = 14\n\t\tDW\t1360\t* 2\t; Index = 77 Token = 15\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 0\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 1\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 2\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 3\n\t\tDW\t1280\t* 2\t; Index = 78 Token = 4\n\t\tDW\t1312\t* 2\t; Index = 78 Token = 5\n\t\tDW\t1344\t* 2\t; Index = 78 Token = 6\n\t\tDW\t1376\t* 2\t; Index = 78 Token = 7\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 8\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 9\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 10\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 11\n\t\tDW\t1280\t* 2\t; Index = 78 Token = 12\n\t\tDW\t1312\t* 2\t; Index = 78 Token = 13\n\t\tDW\t1344\t* 2\t; Index = 78 Token = 14\n\t\tDW\t1376\t* 2\t; Index = 78 Token = 15\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 0\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 1\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 2\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 3\n\t\tDW\t1296\t* 2\t; Index = 79 Token = 4\n\t\tDW\t1328\t* 2\t; Index = 79 Token = 5\n\t\tDW\t1360\t* 2\t; Index = 79 Token = 6\n\t\tDW\t1392\t* 2\t; Index = 79 Token = 7\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 8\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 9\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 10\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 11\n\t\tDW\t1296\t* 2\t; Index = 79 Token = 12\n\t\tDW\t1328\t* 2\t; Index = 79 Token = 13\n\t\tDW\t1360\t* 2\t; Index = 79 Token = 14\n\t\tDW\t1392\t* 2\t; Index = 79 Token = 15\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 0\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 1\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 2\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 3\n\t\tDW\t1312\t* 2\t; Index = 80 Token = 4\n\t\tDW\t1344\t* 2\t; Index = 80 Token = 5\n\t\tDW\t1376\t* 2\t; Index = 80 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 80 Token = 7\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 8\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 9\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 10\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 11\n\t\tDW\t1312\t* 2\t; Index = 80 Token = 12\n\t\tDW\t1344\t* 2\t; Index = 80 Token = 13\n\t\tDW\t1376\t* 2\t; Index = 80 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 80 Token = 15\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 0\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 1\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 2\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 3\n\t\tDW\t1328\t* 2\t; Index = 81 Token = 4\n\t\tDW\t1360\t* 2\t; Index = 81 Token = 5\n\t\tDW\t1392\t* 2\t; Index = 81 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 81 Token = 7\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 8\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 9\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 10\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 11\n\t\tDW\t1328\t* 2\t; Index = 81 Token = 12\n\t\tDW\t1360\t* 2\t; Index = 81 Token = 13\n\t\tDW\t1392\t* 2\t; Index = 81 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 81 Token = 15\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 0\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 1\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 2\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 3\n\t\tDW\t1344\t* 2\t; Index = 82 Token = 4\n\t\tDW\t1376\t* 2\t; Index = 82 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 7\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 8\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 9\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 10\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 11\n\t\tDW\t1344\t* 2\t; Index = 82 Token = 12\n\t\tDW\t1376\t* 2\t; Index = 82 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 15\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 0\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 1\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 2\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 3\n\t\tDW\t1360\t* 2\t; Index = 83 Token = 4\n\t\tDW\t1392\t* 2\t; Index = 83 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 7\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 8\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 9\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 10\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 11\n\t\tDW\t1360\t* 2\t; Index = 83 Token = 12\n\t\tDW\t1392\t* 2\t; Index = 83 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 15\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 0\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 1\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 2\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 3\n\t\tDW\t1376\t* 2\t; Index = 84 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 7\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 8\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 9\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 10\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 11\n\t\tDW\t1376\t* 2\t; Index = 84 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 15\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 0\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 1\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 2\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 3\n\t\tDW\t1392\t* 2\t; Index = 85 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 7\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 8\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 9\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 10\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 11\n\t\tDW\t1392\t* 2\t; Index = 85 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 15\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 0\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 1\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 2\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 7\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 8\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 9\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 10\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 15\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 0\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 1\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 2\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 7\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 8\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 9\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 10\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 15\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 0\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 1\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 2\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 7\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 8\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 9\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 10\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 15\n"
  },
  {
    "path": "WWFLAT32/AUDIO/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = AUDIO\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS = \t\t\t&\n\t\tsoundio.obj\t&\n\t\tsoundint.obj\t&\n\t\tsoundlck.obj\t&\n\t\tsoscodec.obj\t&\n\t\tauduncmp.obj\t\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.lib  $(%WWFLAT)\\lib\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t copy *.lib $(%WWFLAT)\\lib\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\nsoundio.obj: .AUTODEPEND\n\t$(CPP_CMD) -zp4 -5s -mf -s -d2 /i=$(%WWFLAT)\\include soundio.cpp\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\tcopy *.386 test\n\n#**************************** End of makefile ******************************\n\u001a\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/AUDIO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : AUDIO.H                                  *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : March 10, 1995                           *\n *                                                                         *\n *                  Last Update : March 10, 1995   [PWG]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwstd.h\"\n\n/*=========================================================================*/\n/* AUD file header type\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tAUD_FLAG_STEREO\t1\n#define\tAUD_FLAG_16BIT\t\t2\n\n// PWG 3-14-95: This structure used to have bit fields defined for Stereo\n//   and Bits.  These were removed because watcom packs them into a 32 bit\n//   flag entry even though they could have fit in a 8 bit entry.\n#pragma pack(1);\ntypedef struct {\n\tshort int\tRate;\t\t\t\t// Playback rate (hertz).\n\tlong\tSize;\t\t\t\t// Size of data (bytes).\n\tlong\tUncompSize;\t\t\t\t// Size of data (bytes).\n\tunsigned char Flags;\t// Holds flags for info\n\t\t\t\t\t\t\t\t//  1: Is the sample stereo?\n\t\t\t\t\t\t\t\t//  2: Is the sample 16 bits?\n\tunsigned char Compression;\t// What kind of compression for this sample?\n} AUDHeaderType;\n\n\n/*=========================================================================*/\n/*\tThere can be a different sound driver for sound effects, digitized\t\t*/\n/*\tsamples, and musical scores.  Each one must be of these specified\t\t\t*/\n/*\ttypes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\ntypedef enum {\n\tSAMPLE_NONE,\t\t// No digitized sounds will be played.\n\tSAMPLE_SB,\t\t\t// Sound Blaster digitized driver.\n\tSAMPLE_SBPRO,\t\t// Sound Blaster Pro digitized driver.\n\tSAMPLE_PAS,\t\t\t// Pro-Audio Spectrum digitized driver.\n\tSAMPLE_ADLIBG,\t\t// Adlib-Gold digitized driver.\n\tSAMPLE_TANDY,\t\t// Tandy 'compatible' driver.\n\tSAMPLE_PCSPKR,\t\t// PC speaker digitized driver (The Audio Solution driver).\n\tSAMPLE_ADLIB,\t\t// Adlib digitized driver (The Audio Solution driver).\n\tSAMPLE_TEMP=0x1000,\n\tSAMPLE_LAST\n} Sample_Type;\n\ntypedef enum {\n\tSCORE_NONE,\t\t\t// No scores will be played.\n\tSCORE_ALFX,\t\t\t// Westwood's ALFX adlib compatable driver.\n\tSCORE_WWPCSPKR,\t// Westwood's PC-speaker driver (obsolete).\n\tSCORE_WWTANDY,\t\t// Westwood's PC-speaker driver with Tandy mod (obsolete).\n\tSCORE_PCSPKR,\t\t// PC speaker XMIDI driver.\n\tSCORE_TANDY,\t\t// Tandy XMIDI driver.\n\tSCORE_MT32,\t\t\t// MT-32 / LAPC-1 Roland XMIDI driver.\n\tSCORE_CANVAS,\t\t// Sound Canvas SC-55.\n\tSCORE_ADLIB,\t\t// Adlib XMIDI driver.\n\tSCORE_ADLIBG,\t\t// Adlib Gold XMIDI driver.\n\tSCORE_PASFM,\t\t// Pro Audio Spectrum XMIDI driver.\n\tSCORE_SBFM,\t\t\t// Sound Blaster XMIDI driver.\n\tSCORE_SBP1FM,\t\t// Sound Blaster Pro (YM3812) XMIDI driver.\n\tSCORE_SBP2FM,\t\t// Sound Blaster Pro (OPL3) XMIDI driver (Can't use with SFX_ALFX).\n\tSCORE_TEMP=0x1000,\n\tSCORE_LAST\n} Score_Type;\n\ntypedef enum {\n\tSFX_NONE,\t\t\t// No sound effects will be played.\n\tSFX_ALFX,\t\t\t// Westwood's ALFX adlib compatable driver.\n\tSFX_WWPCSPKR,\t\t// Westwood's PC-speaker driver.\n\tSFX_WWTANDY,\t\t// Westwood's PC-speaker driver with Tandy mod.\n\tSFX_PCSPKR,\t\t\t// PC speaker XMIDI driver.\n\tSFX_TANDY,\t\t\t// Tandy XMIDI driver.\n\tSFX_MT32,\t\t\t// MT-32 / LAPC-1 Roland XMIDI driver.\n\tSFX_CANVAS,\t\t\t// Sound Canvas SC-55.\n\tSFX_ADLIB,\t\t\t// Adlib XMIDI driver.\n\tSFX_ADLIBG,\t\t\t// Adlib Gold XMIDI driver.\n\tSFX_PASFM,\t\t\t// Pro Audio Spectrum XMIDI driver.\n\tSFX_SBFM,\t\t\t// Sound Blaster XMIDI driver.\n\tSFX_SBP1FM,\t\t\t// Sound Blaster Pro (YM3812) XMIDI driver.\n\tSFX_SBP2FM,\t\t\t// Sound Blaster Pro (OPL3) XMIDI driver.\n\tSFX_TEMP=0x1000,\n\tSFX_LAST\n} SFX_Type;\n\ntypedef enum RateEnum {\n\tPLAYBACK_RATE_SLOW =11025,\n\tPLAYBACK_RATE_NORMAL =(11025 * 2),\n\tPLAYBACK_RATE_FAST =(11025 * 4),\n} RateType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SOUNDIO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nint File_Stream_Sample(char const *filename, BOOL real_time_start = FALSE);\nint File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start = FALSE);\nvoid cdecl _saveregs Sound_Callback(void);\nvoid cdecl far __saveregs __loadds maintenance_callback(void);\nvoid *Load_Sample(char const *filename);\nlong Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);\nlong Sample_Read(int fh, void *buffer, long size);\nvoid Free_Sample(void const *sample);\nBOOL Sound_Init(int sfx, int score, int sample, RateType rate, int bits_per_sample, int max_samples, int reverse_channels);\nBOOL Audio_Init(int sample, int address, int inter, int dma, RateType rate, int bits_per_sample, int max_samples, int reverse_channels = FALSE);\nvoid Sound_End(void);\nvoid Stop_Sample(int handle);\nBOOL Sample_Status(int handle);\nBOOL Is_Sample_Playing(void const * sample);\nvoid Stop_Sample_Playing(void const * sample);\nint Play_Sample(void const *sample, int priority=0xFF, int volume=0xFF, signed short panloc = 0x0);\nint Play_Sample_Handle(void const *sample, int priority, int volume, signed short panloc, int id);\nint Set_Sound_Vol(int volume);\nint Set_Score_Vol(int volume);\nvoid Fade_Sample(int handle, int ticks);\nint Get_Free_Sample_Handle(int priority);\nint Get_Digi_Handle(void);\nlong Sample_Length(void const *sample);\n\nextern int Misc;\nextern SFX_Type SoundType;\nextern Sample_Type SampleType;\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/AUDUNCMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Audio Library            *\n;*                                                                         *\n;*                    File Name : AUDUNCMP.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : March 14, 1995                           *\n;*                                                                         *\n;*                  Last Update : June 26, 1995   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Decompress_Frame_Lock -- locks the JLB audio decompression code       *\n;*   Decompress_Frame_Unlock -- Unlocks the JLB audio compression code     *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\tCODESEG\n\nDPMI_INTR\t\tequ\t31h\t\n\nLABEL \tLockedCodeStart\tBYTE\n\nCODE_2BIT\tEQU\t0\nCODE_4BIT\tEQU\t1\nCODE_RAW\tEQU\t2\nCODE_SILENCE\tEQU\t3\nMAGICNUMBER\tEQU\t00000DEAFh\nMAGICNUMBER2\tEQU\t0BABEBABEh\n\n_2bitdecode\tDB\t-2,-1,0,1\n_4bitdecode\tDB\t-9,-8,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,8\n\n\n;***************************************************************************\n;* DECOMPRESS_FRAME -- Uncompresses a WW compressed audio frame            *\n;*                                                                         *\n;* INPUT:\tvoid * source - pointer to encoded audio data              *\n;*\t\tvoid * dest   - pointer to decompression area\t\t   *\n;*\t\tlong size     - the maximum size of destination buffer\t   *\n;*                                                                         *\n;* OUTPUT:      long - the number of bytes we uncompressed                 *\n;*                                                                         *\n;* PROTO:\tlong Decompress_Frame(void *, void *, long);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/14/1995 PWG : Created.                                             *\n;*=========================================================================*\n\n\tGLOBAL\tDecompress_Frame:NEAR\n\tPROC\tDecompress_Frame C NEAR USES ebx ecx edx esi edi\n\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tcount:DWORD\n\n\tLOCAL\tprevious:BYTE\n\tLOCAL\tincount:DWORD\n\n\tpushf\n\tcld\n\tmov\t[incount],0\t;Bytes read from source\n\n\n;\tSource, Dest and count must be valid.\n\n\tcmp\t[source],0\n\tje\t??fini\n\n\tcmp\t[dest],0\n\tje\t??fini\n\n\tcmp\t[count],0\n\tje\t??fini\n\n\tmov\tesi,[source]\t;Pointer to source data.\n\tmov\tedi,[dest]\t;Pointer to destination data.\n\tmov\tecx,[count]\t;Number of bytes to fill dest buffer.\n\tmov\tdl,080h\t;Previous sample (starting value).\n\n??mainloop:\n\tcmp\tecx,0\t;If dest full then exit\n\tjle\t??fini\n\n\txor\teax,eax\n\tmov\tal,[esi]\t;Get code byte\n\tinc\t[incount]\n\tinc\tesi\n\tshl\teax,2\t;AH contains code.\n\tshr\tal,2\t;AL contains sub-code data.\n\n\tcmp\tah,CODE_RAW\t;Raw sequence?\n\tjne\tshort ??try4bit\n\n;\tThe code contains either a 5 bit delta or a count of\n;\traw samples to dump out.\n\n\ttest\tal,00100000b\n\tje\tshort ??justraw\n\n;\tThe lower 5 bits are actually a signed delta.\n;\tSign extend the delta and add it to the stream.\n\n\tshl\tal,3\n\tsar\tal,3\n\tadd\tdl,al\n\tmov\t[edi],dl\n\tdec\tecx\n\tinc\tedi\n\tjmp\t??mainloop\n\n;\tThe lower 5 bits hold a count of the number of raw\n;\tsamples that follow this code. Dump these samples to\n;\tthe output buffer.\n\n??justraw:\n\tmov\tebx,ecx\n\txor\tah,ah\n\tinc\tal\n\tmov\tecx,eax\n\tshr\tecx,1\n\trep\tmovsw\n\tadc\tecx,ecx\n\trep\tmovsb\n\tmov\tecx,ebx\n\tadd\t[incount],eax\n\tsub\tecx,eax\n\tdec\tedi\n\tmov\tdl,[edi]\t;Set \"previous\" value.\n\tinc\tedi\n\tjmp\t??mainloop\n\n;\tCheck to see if this is a 4 bit delta code sequence.\n\n??try4bit:\n\tinc\tal\t;Following codes use AL+1\n\tcmp\tah,CODE_4BIT\n\tjne\tshort ??try2bit\n\n;\tA sequence of 4bit deltas follow. AL equals the\n;\tnumber of nibble packed delta bytes to process.\n\n??bit4loop:\n\tmov\tah,[esi]\t;Fetch nibble packed delta codes\n\tmov\tbl,ah\n\tinc\t[incount]\n\tinc\tesi\n\n;\tAdd first delta to 'previous' sample already in DL.\n\n\tand\tebx,00001111b\n\tadd\tdl,[_4bitdecode+ebx]\n\tpushf\n\tcmp\t[_4bitdecode+ebx],0\n\tjl\tshort ??neg1\n\n\tpopf\n\tjnc\tshort ??ok1\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok1\n\n??neg1:\n\tpopf\n\tjc\tshort ??ok1\n\n\txor\tdl,dl\n\n??ok1:\n\tmov\tdh,dl\t;DH now holds new 'previous' sample.\n\tmov\tbl,ah\n\tshr\tbl,4\n\tadd\tdh,[_4bitdecode+ebx]\n\tpushf\n\tcmp\t[_4bitdecode+ebx],0\n\tjl\tshort ??neg2\n\n\tpopf\n\tjnc\tshort ??ok2\n\n\tmov\tdh,0FFh\n\tjmp\tshort ??ok2\n\n??neg2:\n\tpopf\n\tjc\tshort ??ok2\n\n\txor\tdh,dh\n\n??ok2:\n\tmov\t[edi],dx\t;Output the two sample bytes\n\tsub\tecx,2\n\tadd\tedi,2\n\n;\tPut the correct 'previous' sample in DL where it belongs.\n\n\tmov\tdl,dh\n\n;\tIf there are more deltas to process then loop back.\n\n\tdec\tal\n\tjnz\tshort ??bit4loop\n\tjmp\t??mainloop\n\n;\tCheck to see if 2 bit deltas need to be processed.\n\n??try2bit:\n\tcmp\tah,CODE_2BIT\n\tjne\t??zerodelta\n\n;\tA sequence of 2bit deltas follow.  AL equals the number of \n;\tpacked delta bytes to process.\n\n??bit2loop:\n\tmov\tah,[esi]\t;Fetch packed delat codes\n\tinc\t[incount]\n\tinc\tesi\n\n;\tAdd first delta to 'previous' sample already in DL.\n\n\tmov\tbl,ah\n\tand\tebx,000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushf\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg3\n\n\tpopf\n\tjnc\tshort ??ok3\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok3\n\n??neg3:\n\tpopf\n\tjc\tshort ??ok3\n\txor\tdl,dl\n\n??ok3:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,2\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushf\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg4\n\n\tpopf\n\tjnc\tshort ??ok4\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok4\n\n??neg4:\n\tpopf\n\tjc\tshort ??ok4\n\n\txor\tdl,dl\n\n??ok4:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,4\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushf\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg5\n\n\tpopf\n\tjnc\tshort ??ok5\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok5\n\n??neg5:\n\tpopf\n\tjc\tshort ??ok5\n\n\txor\tdl,dl\n\n??ok5:\n\tmov\tdh,dl\n\tror\tedx,8\n\tmov\tbl,ah\n\tshr\tebx,6\n\tand\tbl,00000011b\n\tadd\tdl,[_2bitdecode+ebx]\n\tpushf\n\tcmp\t[_2bitdecode+ebx],0\n\tjl\tshort ??neg6\n\n\tpopf\n\tjnc\tshort ??ok6\n\n\tmov\tdl,0FFh\n\tjmp\tshort ??ok6\n\n??neg6:\n\tpopf\n\tjc\tshort ??ok6\n\n\txor\tdl,dl\n\n??ok6:\n\tror\tedx,8\n\tmov\t[edi],edx\t;Output two sample bytes\n\tsub\tecx,4\n\tadd\tedi,4\n\n;\tPut the correct 'previous' sample in DL where it belongs.\n\n\trol\tedx,8\n\n;\tIf there are more deltas to process then loop back.\n\n\tdec\tal\n\tjnz\t??bit2loop\n\tjmp\t??mainloop\n\n;\tThere is a run of zero deltas.  Zero deltas merely duplicate\n;\tthe 'previous' sample the requested number of times.\n\n??zerodelta:\n\txor\tebx,ebx\n\tmov\tbl,al\n\tmov\tal,dl\n\tsub\tecx,ebx\n\txchg\tecx,ebx\n\trep\tstosb\n\tmov\tecx,ebx\n\tjmp\t??mainloop\n\n??fini:\n\tpopf\n\tmov\teax,[incount]\n\tret\n\n\tENDP\tDecompress_Frame\n\nLABEL \tLockedCodeEnd\tBYTE\n\n\n;***************************************************************************\n;* DECOMPRESS_FRAME_LOCK -- locks the JLB audio decompression code         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is lock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:       BOOL Decompress_Frame_Lock(void);                          *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tDecompress_Frame_Lock:NEAR\n\tPROC\tDecompress_Frame_Lock C NEAR USES ebx ecx edx esi edi\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n  \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\n\tENDP\tDecompress_Frame_Lock\n\n;***************************************************************************\n;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code       *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is unlock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:\tBOOL Decompress_Frame_Unlock(void);                        *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tDecompress_Frame_Unlock:NEAR\n\tPROC\tDecompress_Frame_Unlock C NEAR USES ebx ecx edx esi edi\n\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\n\tENDP\tDecompress_Frame_Unlock\n\n\n\n\tEND\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/DIFFTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* dwDiffTable - ADPCM Lookup table for sample differences\n;****************************************************************************\n\n\t\talign\t4\n\ndwDiffTable\tDD\t0\t; Index = 0 Token = 0\n\t\tDD\t1\t; Index = 0 Token = 1\n\t\tDD\t3\t; Index = 0 Token = 2\n\t\tDD\t4\t; Index = 0 Token = 3\n\t\tDD\t7\t; Index = 0 Token = 4\n\t\tDD\t8\t; Index = 0 Token = 5\n\t\tDD\t10\t; Index = 0 Token = 6\n\t\tDD\t11\t; Index = 0 Token = 7\n\t\tDD\t0\t; Index = 0 Token = 8\n\t\tDD\t-1\t; Index = 0 Token = 9\n\t\tDD\t-3\t; Index = 0 Token = 10\n\t\tDD\t-4\t; Index = 0 Token = 11\n\t\tDD\t-7\t; Index = 0 Token = 12\n\t\tDD\t-8\t; Index = 0 Token = 13\n\t\tDD\t-10\t; Index = 0 Token = 14\n\t\tDD\t-11\t; Index = 0 Token = 15\n\t\tDD\t1\t; Index = 1 Token = 0\n\t\tDD\t3\t; Index = 1 Token = 1\n\t\tDD\t5\t; Index = 1 Token = 2\n\t\tDD\t7\t; Index = 1 Token = 3\n\t\tDD\t9\t; Index = 1 Token = 4\n\t\tDD\t11\t; Index = 1 Token = 5\n\t\tDD\t13\t; Index = 1 Token = 6\n\t\tDD\t15\t; Index = 1 Token = 7\n\t\tDD\t-1\t; Index = 1 Token = 8\n\t\tDD\t-3\t; Index = 1 Token = 9\n\t\tDD\t-5\t; Index = 1 Token = 10\n\t\tDD\t-7\t; Index = 1 Token = 11\n\t\tDD\t-9\t; Index = 1 Token = 12\n\t\tDD\t-11\t; Index = 1 Token = 13\n\t\tDD\t-13\t; Index = 1 Token = 14\n\t\tDD\t-15\t; Index = 1 Token = 15\n\t\tDD\t1\t; Index = 2 Token = 0\n\t\tDD\t3\t; Index = 2 Token = 1\n\t\tDD\t5\t; Index = 2 Token = 2\n\t\tDD\t7\t; Index = 2 Token = 3\n\t\tDD\t10\t; Index = 2 Token = 4\n\t\tDD\t12\t; Index = 2 Token = 5\n\t\tDD\t14\t; Index = 2 Token = 6\n\t\tDD\t16\t; Index = 2 Token = 7\n\t\tDD\t-1\t; Index = 2 Token = 8\n\t\tDD\t-3\t; Index = 2 Token = 9\n\t\tDD\t-5\t; Index = 2 Token = 10\n\t\tDD\t-7\t; Index = 2 Token = 11\n\t\tDD\t-10\t; Index = 2 Token = 12\n\t\tDD\t-12\t; Index = 2 Token = 13\n\t\tDD\t-14\t; Index = 2 Token = 14\n\t\tDD\t-16\t; Index = 2 Token = 15\n\t\tDD\t1\t; Index = 3 Token = 0\n\t\tDD\t3\t; Index = 3 Token = 1\n\t\tDD\t6\t; Index = 3 Token = 2\n\t\tDD\t8\t; Index = 3 Token = 3\n\t\tDD\t11\t; Index = 3 Token = 4\n\t\tDD\t13\t; Index = 3 Token = 5\n\t\tDD\t16\t; Index = 3 Token = 6\n\t\tDD\t18\t; Index = 3 Token = 7\n\t\tDD\t-1\t; Index = 3 Token = 8\n\t\tDD\t-3\t; Index = 3 Token = 9\n\t\tDD\t-6\t; Index = 3 Token = 10\n\t\tDD\t-8\t; Index = 3 Token = 11\n\t\tDD\t-11\t; Index = 3 Token = 12\n\t\tDD\t-13\t; Index = 3 Token = 13\n\t\tDD\t-16\t; Index = 3 Token = 14\n\t\tDD\t-18\t; Index = 3 Token = 15\n\t\tDD\t1\t; Index = 4 Token = 0\n\t\tDD\t3\t; Index = 4 Token = 1\n\t\tDD\t6\t; Index = 4 Token = 2\n\t\tDD\t8\t; Index = 4 Token = 3\n\t\tDD\t12\t; Index = 4 Token = 4\n\t\tDD\t14\t; Index = 4 Token = 5\n\t\tDD\t17\t; Index = 4 Token = 6\n\t\tDD\t19\t; Index = 4 Token = 7\n\t\tDD\t-1\t; Index = 4 Token = 8\n\t\tDD\t-3\t; Index = 4 Token = 9\n\t\tDD\t-6\t; Index = 4 Token = 10\n\t\tDD\t-8\t; Index = 4 Token = 11\n\t\tDD\t-12\t; Index = 4 Token = 12\n\t\tDD\t-14\t; Index = 4 Token = 13\n\t\tDD\t-17\t; Index = 4 Token = 14\n\t\tDD\t-19\t; Index = 4 Token = 15\n\t\tDD\t1\t; Index = 5 Token = 0\n\t\tDD\t4\t; Index = 5 Token = 1\n\t\tDD\t7\t; Index = 5 Token = 2\n\t\tDD\t10\t; Index = 5 Token = 3\n\t\tDD\t13\t; Index = 5 Token = 4\n\t\tDD\t16\t; Index = 5 Token = 5\n\t\tDD\t19\t; Index = 5 Token = 6\n\t\tDD\t22\t; Index = 5 Token = 7\n\t\tDD\t-1\t; Index = 5 Token = 8\n\t\tDD\t-4\t; Index = 5 Token = 9\n\t\tDD\t-7\t; Index = 5 Token = 10\n\t\tDD\t-10\t; Index = 5 Token = 11\n\t\tDD\t-13\t; Index = 5 Token = 12\n\t\tDD\t-16\t; Index = 5 Token = 13\n\t\tDD\t-19\t; Index = 5 Token = 14\n\t\tDD\t-22\t; Index = 5 Token = 15\n\t\tDD\t1\t; Index = 6 Token = 0\n\t\tDD\t4\t; Index = 6 Token = 1\n\t\tDD\t7\t; Index = 6 Token = 2\n\t\tDD\t10\t; Index = 6 Token = 3\n\t\tDD\t14\t; Index = 6 Token = 4\n\t\tDD\t17\t; Index = 6 Token = 5\n\t\tDD\t20\t; Index = 6 Token = 6\n\t\tDD\t23\t; Index = 6 Token = 7\n\t\tDD\t-1\t; Index = 6 Token = 8\n\t\tDD\t-4\t; Index = 6 Token = 9\n\t\tDD\t-7\t; Index = 6 Token = 10\n\t\tDD\t-10\t; Index = 6 Token = 11\n\t\tDD\t-14\t; Index = 6 Token = 12\n\t\tDD\t-17\t; Index = 6 Token = 13\n\t\tDD\t-20\t; Index = 6 Token = 14\n\t\tDD\t-23\t; Index = 6 Token = 15\n\t\tDD\t1\t; Index = 7 Token = 0\n\t\tDD\t4\t; Index = 7 Token = 1\n\t\tDD\t8\t; Index = 7 Token = 2\n\t\tDD\t11\t; Index = 7 Token = 3\n\t\tDD\t15\t; Index = 7 Token = 4\n\t\tDD\t18\t; Index = 7 Token = 5\n\t\tDD\t22\t; Index = 7 Token = 6\n\t\tDD\t25\t; Index = 7 Token = 7\n\t\tDD\t-1\t; Index = 7 Token = 8\n\t\tDD\t-4\t; Index = 7 Token = 9\n\t\tDD\t-8\t; Index = 7 Token = 10\n\t\tDD\t-11\t; Index = 7 Token = 11\n\t\tDD\t-15\t; Index = 7 Token = 12\n\t\tDD\t-18\t; Index = 7 Token = 13\n\t\tDD\t-22\t; Index = 7 Token = 14\n\t\tDD\t-25\t; Index = 7 Token = 15\n\t\tDD\t2\t; Index = 8 Token = 0\n\t\tDD\t6\t; Index = 8 Token = 1\n\t\tDD\t10\t; Index = 8 Token = 2\n\t\tDD\t14\t; Index = 8 Token = 3\n\t\tDD\t18\t; Index = 8 Token = 4\n\t\tDD\t22\t; Index = 8 Token = 5\n\t\tDD\t26\t; Index = 8 Token = 6\n\t\tDD\t30\t; Index = 8 Token = 7\n\t\tDD\t-2\t; Index = 8 Token = 8\n\t\tDD\t-6\t; Index = 8 Token = 9\n\t\tDD\t-10\t; Index = 8 Token = 10\n\t\tDD\t-14\t; Index = 8 Token = 11\n\t\tDD\t-18\t; Index = 8 Token = 12\n\t\tDD\t-22\t; Index = 8 Token = 13\n\t\tDD\t-26\t; Index = 8 Token = 14\n\t\tDD\t-30\t; Index = 8 Token = 15\n\t\tDD\t2\t; Index = 9 Token = 0\n\t\tDD\t6\t; Index = 9 Token = 1\n\t\tDD\t10\t; Index = 9 Token = 2\n\t\tDD\t14\t; Index = 9 Token = 3\n\t\tDD\t19\t; Index = 9 Token = 4\n\t\tDD\t23\t; Index = 9 Token = 5\n\t\tDD\t27\t; Index = 9 Token = 6\n\t\tDD\t31\t; Index = 9 Token = 7\n\t\tDD\t-2\t; Index = 9 Token = 8\n\t\tDD\t-6\t; Index = 9 Token = 9\n\t\tDD\t-10\t; Index = 9 Token = 10\n\t\tDD\t-14\t; Index = 9 Token = 11\n\t\tDD\t-19\t; Index = 9 Token = 12\n\t\tDD\t-23\t; Index = 9 Token = 13\n\t\tDD\t-27\t; Index = 9 Token = 14\n\t\tDD\t-31\t; Index = 9 Token = 15\n\t\tDD\t2\t; Index = 10 Token = 0\n\t\tDD\t6\t; Index = 10 Token = 1\n\t\tDD\t11\t; Index = 10 Token = 2\n\t\tDD\t15\t; Index = 10 Token = 3\n\t\tDD\t21\t; Index = 10 Token = 4\n\t\tDD\t25\t; Index = 10 Token = 5\n\t\tDD\t30\t; Index = 10 Token = 6\n\t\tDD\t34\t; Index = 10 Token = 7\n\t\tDD\t-2\t; Index = 10 Token = 8\n\t\tDD\t-6\t; Index = 10 Token = 9\n\t\tDD\t-11\t; Index = 10 Token = 10\n\t\tDD\t-15\t; Index = 10 Token = 11\n\t\tDD\t-21\t; Index = 10 Token = 12\n\t\tDD\t-25\t; Index = 10 Token = 13\n\t\tDD\t-30\t; Index = 10 Token = 14\n\t\tDD\t-34\t; Index = 10 Token = 15\n\t\tDD\t2\t; Index = 11 Token = 0\n\t\tDD\t7\t; Index = 11 Token = 1\n\t\tDD\t12\t; Index = 11 Token = 2\n\t\tDD\t17\t; Index = 11 Token = 3\n\t\tDD\t23\t; Index = 11 Token = 4\n\t\tDD\t28\t; Index = 11 Token = 5\n\t\tDD\t33\t; Index = 11 Token = 6\n\t\tDD\t38\t; Index = 11 Token = 7\n\t\tDD\t-2\t; Index = 11 Token = 8\n\t\tDD\t-7\t; Index = 11 Token = 9\n\t\tDD\t-12\t; Index = 11 Token = 10\n\t\tDD\t-17\t; Index = 11 Token = 11\n\t\tDD\t-23\t; Index = 11 Token = 12\n\t\tDD\t-28\t; Index = 11 Token = 13\n\t\tDD\t-33\t; Index = 11 Token = 14\n\t\tDD\t-38\t; Index = 11 Token = 15\n\t\tDD\t2\t; Index = 12 Token = 0\n\t\tDD\t7\t; Index = 12 Token = 1\n\t\tDD\t13\t; Index = 12 Token = 2\n\t\tDD\t18\t; Index = 12 Token = 3\n\t\tDD\t25\t; Index = 12 Token = 4\n\t\tDD\t30\t; Index = 12 Token = 5\n\t\tDD\t36\t; Index = 12 Token = 6\n\t\tDD\t41\t; Index = 12 Token = 7\n\t\tDD\t-2\t; Index = 12 Token = 8\n\t\tDD\t-7\t; Index = 12 Token = 9\n\t\tDD\t-13\t; Index = 12 Token = 10\n\t\tDD\t-18\t; Index = 12 Token = 11\n\t\tDD\t-25\t; Index = 12 Token = 12\n\t\tDD\t-30\t; Index = 12 Token = 13\n\t\tDD\t-36\t; Index = 12 Token = 14\n\t\tDD\t-41\t; Index = 12 Token = 15\n\t\tDD\t3\t; Index = 13 Token = 0\n\t\tDD\t9\t; Index = 13 Token = 1\n\t\tDD\t15\t; Index = 13 Token = 2\n\t\tDD\t21\t; Index = 13 Token = 3\n\t\tDD\t28\t; Index = 13 Token = 4\n\t\tDD\t34\t; Index = 13 Token = 5\n\t\tDD\t40\t; Index = 13 Token = 6\n\t\tDD\t46\t; Index = 13 Token = 7\n\t\tDD\t-3\t; Index = 13 Token = 8\n\t\tDD\t-9\t; Index = 13 Token = 9\n\t\tDD\t-15\t; Index = 13 Token = 10\n\t\tDD\t-21\t; Index = 13 Token = 11\n\t\tDD\t-28\t; Index = 13 Token = 12\n\t\tDD\t-34\t; Index = 13 Token = 13\n\t\tDD\t-40\t; Index = 13 Token = 14\n\t\tDD\t-46\t; Index = 13 Token = 15\n\t\tDD\t3\t; Index = 14 Token = 0\n\t\tDD\t10\t; Index = 14 Token = 1\n\t\tDD\t17\t; Index = 14 Token = 2\n\t\tDD\t24\t; Index = 14 Token = 3\n\t\tDD\t31\t; Index = 14 Token = 4\n\t\tDD\t38\t; Index = 14 Token = 5\n\t\tDD\t45\t; Index = 14 Token = 6\n\t\tDD\t52\t; Index = 14 Token = 7\n\t\tDD\t-3\t; Index = 14 Token = 8\n\t\tDD\t-10\t; Index = 14 Token = 9\n\t\tDD\t-17\t; Index = 14 Token = 10\n\t\tDD\t-24\t; Index = 14 Token = 11\n\t\tDD\t-31\t; Index = 14 Token = 12\n\t\tDD\t-38\t; Index = 14 Token = 13\n\t\tDD\t-45\t; Index = 14 Token = 14\n\t\tDD\t-52\t; Index = 14 Token = 15\n\t\tDD\t3\t; Index = 15 Token = 0\n\t\tDD\t10\t; Index = 15 Token = 1\n\t\tDD\t18\t; Index = 15 Token = 2\n\t\tDD\t25\t; Index = 15 Token = 3\n\t\tDD\t34\t; Index = 15 Token = 4\n\t\tDD\t41\t; Index = 15 Token = 5\n\t\tDD\t49\t; Index = 15 Token = 6\n\t\tDD\t56\t; Index = 15 Token = 7\n\t\tDD\t-3\t; Index = 15 Token = 8\n\t\tDD\t-10\t; Index = 15 Token = 9\n\t\tDD\t-18\t; Index = 15 Token = 10\n\t\tDD\t-25\t; Index = 15 Token = 11\n\t\tDD\t-34\t; Index = 15 Token = 12\n\t\tDD\t-41\t; Index = 15 Token = 13\n\t\tDD\t-49\t; Index = 15 Token = 14\n\t\tDD\t-56\t; Index = 15 Token = 15\n\t\tDD\t4\t; Index = 16 Token = 0\n\t\tDD\t12\t; Index = 16 Token = 1\n\t\tDD\t21\t; Index = 16 Token = 2\n\t\tDD\t29\t; Index = 16 Token = 3\n\t\tDD\t38\t; Index = 16 Token = 4\n\t\tDD\t46\t; Index = 16 Token = 5\n\t\tDD\t55\t; Index = 16 Token = 6\n\t\tDD\t63\t; Index = 16 Token = 7\n\t\tDD\t-4\t; Index = 16 Token = 8\n\t\tDD\t-12\t; Index = 16 Token = 9\n\t\tDD\t-21\t; Index = 16 Token = 10\n\t\tDD\t-29\t; Index = 16 Token = 11\n\t\tDD\t-38\t; Index = 16 Token = 12\n\t\tDD\t-46\t; Index = 16 Token = 13\n\t\tDD\t-55\t; Index = 16 Token = 14\n\t\tDD\t-63\t; Index = 16 Token = 15\n\t\tDD\t4\t; Index = 17 Token = 0\n\t\tDD\t13\t; Index = 17 Token = 1\n\t\tDD\t22\t; Index = 17 Token = 2\n\t\tDD\t31\t; Index = 17 Token = 3\n\t\tDD\t41\t; Index = 17 Token = 4\n\t\tDD\t50\t; Index = 17 Token = 5\n\t\tDD\t59\t; Index = 17 Token = 6\n\t\tDD\t68\t; Index = 17 Token = 7\n\t\tDD\t-4\t; Index = 17 Token = 8\n\t\tDD\t-13\t; Index = 17 Token = 9\n\t\tDD\t-22\t; Index = 17 Token = 10\n\t\tDD\t-31\t; Index = 17 Token = 11\n\t\tDD\t-41\t; Index = 17 Token = 12\n\t\tDD\t-50\t; Index = 17 Token = 13\n\t\tDD\t-59\t; Index = 17 Token = 14\n\t\tDD\t-68\t; Index = 17 Token = 15\n\t\tDD\t5\t; Index = 18 Token = 0\n\t\tDD\t15\t; Index = 18 Token = 1\n\t\tDD\t25\t; Index = 18 Token = 2\n\t\tDD\t35\t; Index = 18 Token = 3\n\t\tDD\t46\t; Index = 18 Token = 4\n\t\tDD\t56\t; Index = 18 Token = 5\n\t\tDD\t66\t; Index = 18 Token = 6\n\t\tDD\t76\t; Index = 18 Token = 7\n\t\tDD\t-5\t; Index = 18 Token = 8\n\t\tDD\t-15\t; Index = 18 Token = 9\n\t\tDD\t-25\t; Index = 18 Token = 10\n\t\tDD\t-35\t; Index = 18 Token = 11\n\t\tDD\t-46\t; Index = 18 Token = 12\n\t\tDD\t-56\t; Index = 18 Token = 13\n\t\tDD\t-66\t; Index = 18 Token = 14\n\t\tDD\t-76\t; Index = 18 Token = 15\n\t\tDD\t5\t; Index = 19 Token = 0\n\t\tDD\t16\t; Index = 19 Token = 1\n\t\tDD\t27\t; Index = 19 Token = 2\n\t\tDD\t38\t; Index = 19 Token = 3\n\t\tDD\t50\t; Index = 19 Token = 4\n\t\tDD\t61\t; Index = 19 Token = 5\n\t\tDD\t72\t; Index = 19 Token = 6\n\t\tDD\t83\t; Index = 19 Token = 7\n\t\tDD\t-5\t; Index = 19 Token = 8\n\t\tDD\t-16\t; Index = 19 Token = 9\n\t\tDD\t-27\t; Index = 19 Token = 10\n\t\tDD\t-38\t; Index = 19 Token = 11\n\t\tDD\t-50\t; Index = 19 Token = 12\n\t\tDD\t-61\t; Index = 19 Token = 13\n\t\tDD\t-72\t; Index = 19 Token = 14\n\t\tDD\t-83\t; Index = 19 Token = 15\n\t\tDD\t6\t; Index = 20 Token = 0\n\t\tDD\t18\t; Index = 20 Token = 1\n\t\tDD\t31\t; Index = 20 Token = 2\n\t\tDD\t43\t; Index = 20 Token = 3\n\t\tDD\t56\t; Index = 20 Token = 4\n\t\tDD\t68\t; Index = 20 Token = 5\n\t\tDD\t81\t; Index = 20 Token = 6\n\t\tDD\t93\t; Index = 20 Token = 7\n\t\tDD\t-6\t; Index = 20 Token = 8\n\t\tDD\t-18\t; Index = 20 Token = 9\n\t\tDD\t-31\t; Index = 20 Token = 10\n\t\tDD\t-43\t; Index = 20 Token = 11\n\t\tDD\t-56\t; Index = 20 Token = 12\n\t\tDD\t-68\t; Index = 20 Token = 13\n\t\tDD\t-81\t; Index = 20 Token = 14\n\t\tDD\t-93\t; Index = 20 Token = 15\n\t\tDD\t6\t; Index = 21 Token = 0\n\t\tDD\t19\t; Index = 21 Token = 1\n\t\tDD\t33\t; Index = 21 Token = 2\n\t\tDD\t46\t; Index = 21 Token = 3\n\t\tDD\t61\t; Index = 21 Token = 4\n\t\tDD\t74\t; Index = 21 Token = 5\n\t\tDD\t88\t; Index = 21 Token = 6\n\t\tDD\t101\t; Index = 21 Token = 7\n\t\tDD\t-6\t; Index = 21 Token = 8\n\t\tDD\t-19\t; Index = 21 Token = 9\n\t\tDD\t-33\t; Index = 21 Token = 10\n\t\tDD\t-46\t; Index = 21 Token = 11\n\t\tDD\t-61\t; Index = 21 Token = 12\n\t\tDD\t-74\t; Index = 21 Token = 13\n\t\tDD\t-88\t; Index = 21 Token = 14\n\t\tDD\t-101\t; Index = 21 Token = 15\n\t\tDD\t7\t; Index = 22 Token = 0\n\t\tDD\t22\t; Index = 22 Token = 1\n\t\tDD\t37\t; Index = 22 Token = 2\n\t\tDD\t52\t; Index = 22 Token = 3\n\t\tDD\t67\t; Index = 22 Token = 4\n\t\tDD\t82\t; Index = 22 Token = 5\n\t\tDD\t97\t; Index = 22 Token = 6\n\t\tDD\t112\t; Index = 22 Token = 7\n\t\tDD\t-7\t; Index = 22 Token = 8\n\t\tDD\t-22\t; Index = 22 Token = 9\n\t\tDD\t-37\t; Index = 22 Token = 10\n\t\tDD\t-52\t; Index = 22 Token = 11\n\t\tDD\t-67\t; Index = 22 Token = 12\n\t\tDD\t-82\t; Index = 22 Token = 13\n\t\tDD\t-97\t; Index = 22 Token = 14\n\t\tDD\t-112\t; Index = 22 Token = 15\n\t\tDD\t8\t; Index = 23 Token = 0\n\t\tDD\t24\t; Index = 23 Token = 1\n\t\tDD\t41\t; Index = 23 Token = 2\n\t\tDD\t57\t; Index = 23 Token = 3\n\t\tDD\t74\t; Index = 23 Token = 4\n\t\tDD\t90\t; Index = 23 Token = 5\n\t\tDD\t107\t; Index = 23 Token = 6\n\t\tDD\t123\t; Index = 23 Token = 7\n\t\tDD\t-8\t; Index = 23 Token = 8\n\t\tDD\t-24\t; Index = 23 Token = 9\n\t\tDD\t-41\t; Index = 23 Token = 10\n\t\tDD\t-57\t; Index = 23 Token = 11\n\t\tDD\t-74\t; Index = 23 Token = 12\n\t\tDD\t-90\t; Index = 23 Token = 13\n\t\tDD\t-107\t; Index = 23 Token = 14\n\t\tDD\t-123\t; Index = 23 Token = 15\n\t\tDD\t9\t; Index = 24 Token = 0\n\t\tDD\t27\t; Index = 24 Token = 1\n\t\tDD\t45\t; Index = 24 Token = 2\n\t\tDD\t63\t; Index = 24 Token = 3\n\t\tDD\t82\t; Index = 24 Token = 4\n\t\tDD\t100\t; Index = 24 Token = 5\n\t\tDD\t118\t; Index = 24 Token = 6\n\t\tDD\t136\t; Index = 24 Token = 7\n\t\tDD\t-9\t; Index = 24 Token = 8\n\t\tDD\t-27\t; Index = 24 Token = 9\n\t\tDD\t-45\t; Index = 24 Token = 10\n\t\tDD\t-63\t; Index = 24 Token = 11\n\t\tDD\t-82\t; Index = 24 Token = 12\n\t\tDD\t-100\t; Index = 24 Token = 13\n\t\tDD\t-118\t; Index = 24 Token = 14\n\t\tDD\t-136\t; Index = 24 Token = 15\n\t\tDD\t10\t; Index = 25 Token = 0\n\t\tDD\t30\t; Index = 25 Token = 1\n\t\tDD\t50\t; Index = 25 Token = 2\n\t\tDD\t70\t; Index = 25 Token = 3\n\t\tDD\t90\t; Index = 25 Token = 4\n\t\tDD\t110\t; Index = 25 Token = 5\n\t\tDD\t130\t; Index = 25 Token = 6\n\t\tDD\t150\t; Index = 25 Token = 7\n\t\tDD\t-10\t; Index = 25 Token = 8\n\t\tDD\t-30\t; Index = 25 Token = 9\n\t\tDD\t-50\t; Index = 25 Token = 10\n\t\tDD\t-70\t; Index = 25 Token = 11\n\t\tDD\t-90\t; Index = 25 Token = 12\n\t\tDD\t-110\t; Index = 25 Token = 13\n\t\tDD\t-130\t; Index = 25 Token = 14\n\t\tDD\t-150\t; Index = 25 Token = 15\n\t\tDD\t11\t; Index = 26 Token = 0\n\t\tDD\t33\t; Index = 26 Token = 1\n\t\tDD\t55\t; Index = 26 Token = 2\n\t\tDD\t77\t; Index = 26 Token = 3\n\t\tDD\t99\t; Index = 26 Token = 4\n\t\tDD\t121\t; Index = 26 Token = 5\n\t\tDD\t143\t; Index = 26 Token = 6\n\t\tDD\t165\t; Index = 26 Token = 7\n\t\tDD\t-11\t; Index = 26 Token = 8\n\t\tDD\t-33\t; Index = 26 Token = 9\n\t\tDD\t-55\t; Index = 26 Token = 10\n\t\tDD\t-77\t; Index = 26 Token = 11\n\t\tDD\t-99\t; Index = 26 Token = 12\n\t\tDD\t-121\t; Index = 26 Token = 13\n\t\tDD\t-143\t; Index = 26 Token = 14\n\t\tDD\t-165\t; Index = 26 Token = 15\n\t\tDD\t12\t; Index = 27 Token = 0\n\t\tDD\t36\t; Index = 27 Token = 1\n\t\tDD\t60\t; Index = 27 Token = 2\n\t\tDD\t84\t; Index = 27 Token = 3\n\t\tDD\t109\t; Index = 27 Token = 4\n\t\tDD\t133\t; Index = 27 Token = 5\n\t\tDD\t157\t; Index = 27 Token = 6\n\t\tDD\t181\t; Index = 27 Token = 7\n\t\tDD\t-12\t; Index = 27 Token = 8\n\t\tDD\t-36\t; Index = 27 Token = 9\n\t\tDD\t-60\t; Index = 27 Token = 10\n\t\tDD\t-84\t; Index = 27 Token = 11\n\t\tDD\t-109\t; Index = 27 Token = 12\n\t\tDD\t-133\t; Index = 27 Token = 13\n\t\tDD\t-157\t; Index = 27 Token = 14\n\t\tDD\t-181\t; Index = 27 Token = 15\n\t\tDD\t13\t; Index = 28 Token = 0\n\t\tDD\t39\t; Index = 28 Token = 1\n\t\tDD\t66\t; Index = 28 Token = 2\n\t\tDD\t92\t; Index = 28 Token = 3\n\t\tDD\t120\t; Index = 28 Token = 4\n\t\tDD\t146\t; Index = 28 Token = 5\n\t\tDD\t173\t; Index = 28 Token = 6\n\t\tDD\t199\t; Index = 28 Token = 7\n\t\tDD\t-13\t; Index = 28 Token = 8\n\t\tDD\t-39\t; Index = 28 Token = 9\n\t\tDD\t-66\t; Index = 28 Token = 10\n\t\tDD\t-92\t; Index = 28 Token = 11\n\t\tDD\t-120\t; Index = 28 Token = 12\n\t\tDD\t-146\t; Index = 28 Token = 13\n\t\tDD\t-173\t; Index = 28 Token = 14\n\t\tDD\t-199\t; Index = 28 Token = 15\n\t\tDD\t14\t; Index = 29 Token = 0\n\t\tDD\t43\t; Index = 29 Token = 1\n\t\tDD\t73\t; Index = 29 Token = 2\n\t\tDD\t102\t; Index = 29 Token = 3\n\t\tDD\t132\t; Index = 29 Token = 4\n\t\tDD\t161\t; Index = 29 Token = 5\n\t\tDD\t191\t; Index = 29 Token = 6\n\t\tDD\t220\t; Index = 29 Token = 7\n\t\tDD\t-14\t; Index = 29 Token = 8\n\t\tDD\t-43\t; Index = 29 Token = 9\n\t\tDD\t-73\t; Index = 29 Token = 10\n\t\tDD\t-102\t; Index = 29 Token = 11\n\t\tDD\t-132\t; Index = 29 Token = 12\n\t\tDD\t-161\t; Index = 29 Token = 13\n\t\tDD\t-191\t; Index = 29 Token = 14\n\t\tDD\t-220\t; Index = 29 Token = 15\n\t\tDD\t16\t; Index = 30 Token = 0\n\t\tDD\t48\t; Index = 30 Token = 1\n\t\tDD\t81\t; Index = 30 Token = 2\n\t\tDD\t113\t; Index = 30 Token = 3\n\t\tDD\t146\t; Index = 30 Token = 4\n\t\tDD\t178\t; Index = 30 Token = 5\n\t\tDD\t211\t; Index = 30 Token = 6\n\t\tDD\t243\t; Index = 30 Token = 7\n\t\tDD\t-16\t; Index = 30 Token = 8\n\t\tDD\t-48\t; Index = 30 Token = 9\n\t\tDD\t-81\t; Index = 30 Token = 10\n\t\tDD\t-113\t; Index = 30 Token = 11\n\t\tDD\t-146\t; Index = 30 Token = 12\n\t\tDD\t-178\t; Index = 30 Token = 13\n\t\tDD\t-211\t; Index = 30 Token = 14\n\t\tDD\t-243\t; Index = 30 Token = 15\n\t\tDD\t17\t; Index = 31 Token = 0\n\t\tDD\t52\t; Index = 31 Token = 1\n\t\tDD\t88\t; Index = 31 Token = 2\n\t\tDD\t123\t; Index = 31 Token = 3\n\t\tDD\t160\t; Index = 31 Token = 4\n\t\tDD\t195\t; Index = 31 Token = 5\n\t\tDD\t231\t; Index = 31 Token = 6\n\t\tDD\t266\t; Index = 31 Token = 7\n\t\tDD\t-17\t; Index = 31 Token = 8\n\t\tDD\t-52\t; Index = 31 Token = 9\n\t\tDD\t-88\t; Index = 31 Token = 10\n\t\tDD\t-123\t; Index = 31 Token = 11\n\t\tDD\t-160\t; Index = 31 Token = 12\n\t\tDD\t-195\t; Index = 31 Token = 13\n\t\tDD\t-231\t; Index = 31 Token = 14\n\t\tDD\t-266\t; Index = 31 Token = 15\n\t\tDD\t19\t; Index = 32 Token = 0\n\t\tDD\t58\t; Index = 32 Token = 1\n\t\tDD\t97\t; Index = 32 Token = 2\n\t\tDD\t136\t; Index = 32 Token = 3\n\t\tDD\t176\t; Index = 32 Token = 4\n\t\tDD\t215\t; Index = 32 Token = 5\n\t\tDD\t254\t; Index = 32 Token = 6\n\t\tDD\t293\t; Index = 32 Token = 7\n\t\tDD\t-19\t; Index = 32 Token = 8\n\t\tDD\t-58\t; Index = 32 Token = 9\n\t\tDD\t-97\t; Index = 32 Token = 10\n\t\tDD\t-136\t; Index = 32 Token = 11\n\t\tDD\t-176\t; Index = 32 Token = 12\n\t\tDD\t-215\t; Index = 32 Token = 13\n\t\tDD\t-254\t; Index = 32 Token = 14\n\t\tDD\t-293\t; Index = 32 Token = 15\n\t\tDD\t21\t; Index = 33 Token = 0\n\t\tDD\t64\t; Index = 33 Token = 1\n\t\tDD\t107\t; Index = 33 Token = 2\n\t\tDD\t150\t; Index = 33 Token = 3\n\t\tDD\t194\t; Index = 33 Token = 4\n\t\tDD\t237\t; Index = 33 Token = 5\n\t\tDD\t280\t; Index = 33 Token = 6\n\t\tDD\t323\t; Index = 33 Token = 7\n\t\tDD\t-21\t; Index = 33 Token = 8\n\t\tDD\t-64\t; Index = 33 Token = 9\n\t\tDD\t-107\t; Index = 33 Token = 10\n\t\tDD\t-150\t; Index = 33 Token = 11\n\t\tDD\t-194\t; Index = 33 Token = 12\n\t\tDD\t-237\t; Index = 33 Token = 13\n\t\tDD\t-280\t; Index = 33 Token = 14\n\t\tDD\t-323\t; Index = 33 Token = 15\n\t\tDD\t23\t; Index = 34 Token = 0\n\t\tDD\t70\t; Index = 34 Token = 1\n\t\tDD\t118\t; Index = 34 Token = 2\n\t\tDD\t165\t; Index = 34 Token = 3\n\t\tDD\t213\t; Index = 34 Token = 4\n\t\tDD\t260\t; Index = 34 Token = 5\n\t\tDD\t308\t; Index = 34 Token = 6\n\t\tDD\t355\t; Index = 34 Token = 7\n\t\tDD\t-23\t; Index = 34 Token = 8\n\t\tDD\t-70\t; Index = 34 Token = 9\n\t\tDD\t-118\t; Index = 34 Token = 10\n\t\tDD\t-165\t; Index = 34 Token = 11\n\t\tDD\t-213\t; Index = 34 Token = 12\n\t\tDD\t-260\t; Index = 34 Token = 13\n\t\tDD\t-308\t; Index = 34 Token = 14\n\t\tDD\t-355\t; Index = 34 Token = 15\n\t\tDD\t26\t; Index = 35 Token = 0\n\t\tDD\t78\t; Index = 35 Token = 1\n\t\tDD\t130\t; Index = 35 Token = 2\n\t\tDD\t182\t; Index = 35 Token = 3\n\t\tDD\t235\t; Index = 35 Token = 4\n\t\tDD\t287\t; Index = 35 Token = 5\n\t\tDD\t339\t; Index = 35 Token = 6\n\t\tDD\t391\t; Index = 35 Token = 7\n\t\tDD\t-26\t; Index = 35 Token = 8\n\t\tDD\t-78\t; Index = 35 Token = 9\n\t\tDD\t-130\t; Index = 35 Token = 10\n\t\tDD\t-182\t; Index = 35 Token = 11\n\t\tDD\t-235\t; Index = 35 Token = 12\n\t\tDD\t-287\t; Index = 35 Token = 13\n\t\tDD\t-339\t; Index = 35 Token = 14\n\t\tDD\t-391\t; Index = 35 Token = 15\n\t\tDD\t28\t; Index = 36 Token = 0\n\t\tDD\t85\t; Index = 36 Token = 1\n\t\tDD\t143\t; Index = 36 Token = 2\n\t\tDD\t200\t; Index = 36 Token = 3\n\t\tDD\t258\t; Index = 36 Token = 4\n\t\tDD\t315\t; Index = 36 Token = 5\n\t\tDD\t373\t; Index = 36 Token = 6\n\t\tDD\t430\t; Index = 36 Token = 7\n\t\tDD\t-28\t; Index = 36 Token = 8\n\t\tDD\t-85\t; Index = 36 Token = 9\n\t\tDD\t-143\t; Index = 36 Token = 10\n\t\tDD\t-200\t; Index = 36 Token = 11\n\t\tDD\t-258\t; Index = 36 Token = 12\n\t\tDD\t-315\t; Index = 36 Token = 13\n\t\tDD\t-373\t; Index = 36 Token = 14\n\t\tDD\t-430\t; Index = 36 Token = 15\n\t\tDD\t31\t; Index = 37 Token = 0\n\t\tDD\t94\t; Index = 37 Token = 1\n\t\tDD\t157\t; Index = 37 Token = 2\n\t\tDD\t220\t; Index = 37 Token = 3\n\t\tDD\t284\t; Index = 37 Token = 4\n\t\tDD\t347\t; Index = 37 Token = 5\n\t\tDD\t410\t; Index = 37 Token = 6\n\t\tDD\t473\t; Index = 37 Token = 7\n\t\tDD\t-31\t; Index = 37 Token = 8\n\t\tDD\t-94\t; Index = 37 Token = 9\n\t\tDD\t-157\t; Index = 37 Token = 10\n\t\tDD\t-220\t; Index = 37 Token = 11\n\t\tDD\t-284\t; Index = 37 Token = 12\n\t\tDD\t-347\t; Index = 37 Token = 13\n\t\tDD\t-410\t; Index = 37 Token = 14\n\t\tDD\t-473\t; Index = 37 Token = 15\n\t\tDD\t34\t; Index = 38 Token = 0\n\t\tDD\t103\t; Index = 38 Token = 1\n\t\tDD\t173\t; Index = 38 Token = 2\n\t\tDD\t242\t; Index = 38 Token = 3\n\t\tDD\t313\t; Index = 38 Token = 4\n\t\tDD\t382\t; Index = 38 Token = 5\n\t\tDD\t452\t; Index = 38 Token = 6\n\t\tDD\t521\t; Index = 38 Token = 7\n\t\tDD\t-34\t; Index = 38 Token = 8\n\t\tDD\t-103\t; Index = 38 Token = 9\n\t\tDD\t-173\t; Index = 38 Token = 10\n\t\tDD\t-242\t; Index = 38 Token = 11\n\t\tDD\t-313\t; Index = 38 Token = 12\n\t\tDD\t-382\t; Index = 38 Token = 13\n\t\tDD\t-452\t; Index = 38 Token = 14\n\t\tDD\t-521\t; Index = 38 Token = 15\n\t\tDD\t38\t; Index = 39 Token = 0\n\t\tDD\t114\t; Index = 39 Token = 1\n\t\tDD\t191\t; Index = 39 Token = 2\n\t\tDD\t267\t; Index = 39 Token = 3\n\t\tDD\t345\t; Index = 39 Token = 4\n\t\tDD\t421\t; Index = 39 Token = 5\n\t\tDD\t498\t; Index = 39 Token = 6\n\t\tDD\t574\t; Index = 39 Token = 7\n\t\tDD\t-38\t; Index = 39 Token = 8\n\t\tDD\t-114\t; Index = 39 Token = 9\n\t\tDD\t-191\t; Index = 39 Token = 10\n\t\tDD\t-267\t; Index = 39 Token = 11\n\t\tDD\t-345\t; Index = 39 Token = 12\n\t\tDD\t-421\t; Index = 39 Token = 13\n\t\tDD\t-498\t; Index = 39 Token = 14\n\t\tDD\t-574\t; Index = 39 Token = 15\n\t\tDD\t42\t; Index = 40 Token = 0\n\t\tDD\t126\t; Index = 40 Token = 1\n\t\tDD\t210\t; Index = 40 Token = 2\n\t\tDD\t294\t; Index = 40 Token = 3\n\t\tDD\t379\t; Index = 40 Token = 4\n\t\tDD\t463\t; Index = 40 Token = 5\n\t\tDD\t547\t; Index = 40 Token = 6\n\t\tDD\t631\t; Index = 40 Token = 7\n\t\tDD\t-42\t; Index = 40 Token = 8\n\t\tDD\t-126\t; Index = 40 Token = 9\n\t\tDD\t-210\t; Index = 40 Token = 10\n\t\tDD\t-294\t; Index = 40 Token = 11\n\t\tDD\t-379\t; Index = 40 Token = 12\n\t\tDD\t-463\t; Index = 40 Token = 13\n\t\tDD\t-547\t; Index = 40 Token = 14\n\t\tDD\t-631\t; Index = 40 Token = 15\n\t\tDD\t46\t; Index = 41 Token = 0\n\t\tDD\t138\t; Index = 41 Token = 1\n\t\tDD\t231\t; Index = 41 Token = 2\n\t\tDD\t323\t; Index = 41 Token = 3\n\t\tDD\t417\t; Index = 41 Token = 4\n\t\tDD\t509\t; Index = 41 Token = 5\n\t\tDD\t602\t; Index = 41 Token = 6\n\t\tDD\t694\t; Index = 41 Token = 7\n\t\tDD\t-46\t; Index = 41 Token = 8\n\t\tDD\t-138\t; Index = 41 Token = 9\n\t\tDD\t-231\t; Index = 41 Token = 10\n\t\tDD\t-323\t; Index = 41 Token = 11\n\t\tDD\t-417\t; Index = 41 Token = 12\n\t\tDD\t-509\t; Index = 41 Token = 13\n\t\tDD\t-602\t; Index = 41 Token = 14\n\t\tDD\t-694\t; Index = 41 Token = 15\n\t\tDD\t51\t; Index = 42 Token = 0\n\t\tDD\t153\t; Index = 42 Token = 1\n\t\tDD\t255\t; Index = 42 Token = 2\n\t\tDD\t357\t; Index = 42 Token = 3\n\t\tDD\t459\t; Index = 42 Token = 4\n\t\tDD\t561\t; Index = 42 Token = 5\n\t\tDD\t663\t; Index = 42 Token = 6\n\t\tDD\t765\t; Index = 42 Token = 7\n\t\tDD\t-51\t; Index = 42 Token = 8\n\t\tDD\t-153\t; Index = 42 Token = 9\n\t\tDD\t-255\t; Index = 42 Token = 10\n\t\tDD\t-357\t; Index = 42 Token = 11\n\t\tDD\t-459\t; Index = 42 Token = 12\n\t\tDD\t-561\t; Index = 42 Token = 13\n\t\tDD\t-663\t; Index = 42 Token = 14\n\t\tDD\t-765\t; Index = 42 Token = 15\n\t\tDD\t56\t; Index = 43 Token = 0\n\t\tDD\t168\t; Index = 43 Token = 1\n\t\tDD\t280\t; Index = 43 Token = 2\n\t\tDD\t392\t; Index = 43 Token = 3\n\t\tDD\t505\t; Index = 43 Token = 4\n\t\tDD\t617\t; Index = 43 Token = 5\n\t\tDD\t729\t; Index = 43 Token = 6\n\t\tDD\t841\t; Index = 43 Token = 7\n\t\tDD\t-56\t; Index = 43 Token = 8\n\t\tDD\t-168\t; Index = 43 Token = 9\n\t\tDD\t-280\t; Index = 43 Token = 10\n\t\tDD\t-392\t; Index = 43 Token = 11\n\t\tDD\t-505\t; Index = 43 Token = 12\n\t\tDD\t-617\t; Index = 43 Token = 13\n\t\tDD\t-729\t; Index = 43 Token = 14\n\t\tDD\t-841\t; Index = 43 Token = 15\n\t\tDD\t61\t; Index = 44 Token = 0\n\t\tDD\t184\t; Index = 44 Token = 1\n\t\tDD\t308\t; Index = 44 Token = 2\n\t\tDD\t431\t; Index = 44 Token = 3\n\t\tDD\t555\t; Index = 44 Token = 4\n\t\tDD\t678\t; Index = 44 Token = 5\n\t\tDD\t802\t; Index = 44 Token = 6\n\t\tDD\t925\t; Index = 44 Token = 7\n\t\tDD\t-61\t; Index = 44 Token = 8\n\t\tDD\t-184\t; Index = 44 Token = 9\n\t\tDD\t-308\t; Index = 44 Token = 10\n\t\tDD\t-431\t; Index = 44 Token = 11\n\t\tDD\t-555\t; Index = 44 Token = 12\n\t\tDD\t-678\t; Index = 44 Token = 13\n\t\tDD\t-802\t; Index = 44 Token = 14\n\t\tDD\t-925\t; Index = 44 Token = 15\n\t\tDD\t68\t; Index = 45 Token = 0\n\t\tDD\t204\t; Index = 45 Token = 1\n\t\tDD\t340\t; Index = 45 Token = 2\n\t\tDD\t476\t; Index = 45 Token = 3\n\t\tDD\t612\t; Index = 45 Token = 4\n\t\tDD\t748\t; Index = 45 Token = 5\n\t\tDD\t884\t; Index = 45 Token = 6\n\t\tDD\t1020\t; Index = 45 Token = 7\n\t\tDD\t-68\t; Index = 45 Token = 8\n\t\tDD\t-204\t; Index = 45 Token = 9\n\t\tDD\t-340\t; Index = 45 Token = 10\n\t\tDD\t-476\t; Index = 45 Token = 11\n\t\tDD\t-612\t; Index = 45 Token = 12\n\t\tDD\t-748\t; Index = 45 Token = 13\n\t\tDD\t-884\t; Index = 45 Token = 14\n\t\tDD\t-1020\t; Index = 45 Token = 15\n\t\tDD\t74\t; Index = 46 Token = 0\n\t\tDD\t223\t; Index = 46 Token = 1\n\t\tDD\t373\t; Index = 46 Token = 2\n\t\tDD\t522\t; Index = 46 Token = 3\n\t\tDD\t672\t; Index = 46 Token = 4\n\t\tDD\t821\t; Index = 46 Token = 5\n\t\tDD\t971\t; Index = 46 Token = 6\n\t\tDD\t1120\t; Index = 46 Token = 7\n\t\tDD\t-74\t; Index = 46 Token = 8\n\t\tDD\t-223\t; Index = 46 Token = 9\n\t\tDD\t-373\t; Index = 46 Token = 10\n\t\tDD\t-522\t; Index = 46 Token = 11\n\t\tDD\t-672\t; Index = 46 Token = 12\n\t\tDD\t-821\t; Index = 46 Token = 13\n\t\tDD\t-971\t; Index = 46 Token = 14\n\t\tDD\t-1120\t; Index = 46 Token = 15\n\t\tDD\t82\t; Index = 47 Token = 0\n\t\tDD\t246\t; Index = 47 Token = 1\n\t\tDD\t411\t; Index = 47 Token = 2\n\t\tDD\t575\t; Index = 47 Token = 3\n\t\tDD\t740\t; Index = 47 Token = 4\n\t\tDD\t904\t; Index = 47 Token = 5\n\t\tDD\t1069\t; Index = 47 Token = 6\n\t\tDD\t1233\t; Index = 47 Token = 7\n\t\tDD\t-82\t; Index = 47 Token = 8\n\t\tDD\t-246\t; Index = 47 Token = 9\n\t\tDD\t-411\t; Index = 47 Token = 10\n\t\tDD\t-575\t; Index = 47 Token = 11\n\t\tDD\t-740\t; Index = 47 Token = 12\n\t\tDD\t-904\t; Index = 47 Token = 13\n\t\tDD\t-1069\t; Index = 47 Token = 14\n\t\tDD\t-1233\t; Index = 47 Token = 15\n\t\tDD\t90\t; Index = 48 Token = 0\n\t\tDD\t271\t; Index = 48 Token = 1\n\t\tDD\t452\t; Index = 48 Token = 2\n\t\tDD\t633\t; Index = 48 Token = 3\n\t\tDD\t814\t; Index = 48 Token = 4\n\t\tDD\t995\t; Index = 48 Token = 5\n\t\tDD\t1176\t; Index = 48 Token = 6\n\t\tDD\t1357\t; Index = 48 Token = 7\n\t\tDD\t-90\t; Index = 48 Token = 8\n\t\tDD\t-271\t; Index = 48 Token = 9\n\t\tDD\t-452\t; Index = 48 Token = 10\n\t\tDD\t-633\t; Index = 48 Token = 11\n\t\tDD\t-814\t; Index = 48 Token = 12\n\t\tDD\t-995\t; Index = 48 Token = 13\n\t\tDD\t-1176\t; Index = 48 Token = 14\n\t\tDD\t-1357\t; Index = 48 Token = 15\n\t\tDD\t99\t; Index = 49 Token = 0\n\t\tDD\t298\t; Index = 49 Token = 1\n\t\tDD\t497\t; Index = 49 Token = 2\n\t\tDD\t696\t; Index = 49 Token = 3\n\t\tDD\t895\t; Index = 49 Token = 4\n\t\tDD\t1094\t; Index = 49 Token = 5\n\t\tDD\t1293\t; Index = 49 Token = 6\n\t\tDD\t1492\t; Index = 49 Token = 7\n\t\tDD\t-99\t; Index = 49 Token = 8\n\t\tDD\t-298\t; Index = 49 Token = 9\n\t\tDD\t-497\t; Index = 49 Token = 10\n\t\tDD\t-696\t; Index = 49 Token = 11\n\t\tDD\t-895\t; Index = 49 Token = 12\n\t\tDD\t-1094\t; Index = 49 Token = 13\n\t\tDD\t-1293\t; Index = 49 Token = 14\n\t\tDD\t-1492\t; Index = 49 Token = 15\n\t\tDD\t109\t; Index = 50 Token = 0\n\t\tDD\t328\t; Index = 50 Token = 1\n\t\tDD\t547\t; Index = 50 Token = 2\n\t\tDD\t766\t; Index = 50 Token = 3\n\t\tDD\t985\t; Index = 50 Token = 4\n\t\tDD\t1204\t; Index = 50 Token = 5\n\t\tDD\t1423\t; Index = 50 Token = 6\n\t\tDD\t1642\t; Index = 50 Token = 7\n\t\tDD\t-109\t; Index = 50 Token = 8\n\t\tDD\t-328\t; Index = 50 Token = 9\n\t\tDD\t-547\t; Index = 50 Token = 10\n\t\tDD\t-766\t; Index = 50 Token = 11\n\t\tDD\t-985\t; Index = 50 Token = 12\n\t\tDD\t-1204\t; Index = 50 Token = 13\n\t\tDD\t-1423\t; Index = 50 Token = 14\n\t\tDD\t-1642\t; Index = 50 Token = 15\n\t\tDD\t120\t; Index = 51 Token = 0\n\t\tDD\t360\t; Index = 51 Token = 1\n\t\tDD\t601\t; Index = 51 Token = 2\n\t\tDD\t841\t; Index = 51 Token = 3\n\t\tDD\t1083\t; Index = 51 Token = 4\n\t\tDD\t1323\t; Index = 51 Token = 5\n\t\tDD\t1564\t; Index = 51 Token = 6\n\t\tDD\t1804\t; Index = 51 Token = 7\n\t\tDD\t-120\t; Index = 51 Token = 8\n\t\tDD\t-360\t; Index = 51 Token = 9\n\t\tDD\t-601\t; Index = 51 Token = 10\n\t\tDD\t-841\t; Index = 51 Token = 11\n\t\tDD\t-1083\t; Index = 51 Token = 12\n\t\tDD\t-1323\t; Index = 51 Token = 13\n\t\tDD\t-1564\t; Index = 51 Token = 14\n\t\tDD\t-1804\t; Index = 51 Token = 15\n\t\tDD\t132\t; Index = 52 Token = 0\n\t\tDD\t397\t; Index = 52 Token = 1\n\t\tDD\t662\t; Index = 52 Token = 2\n\t\tDD\t927\t; Index = 52 Token = 3\n\t\tDD\t1192\t; Index = 52 Token = 4\n\t\tDD\t1457\t; Index = 52 Token = 5\n\t\tDD\t1722\t; Index = 52 Token = 6\n\t\tDD\t1987\t; Index = 52 Token = 7\n\t\tDD\t-132\t; Index = 52 Token = 8\n\t\tDD\t-397\t; Index = 52 Token = 9\n\t\tDD\t-662\t; Index = 52 Token = 10\n\t\tDD\t-927\t; Index = 52 Token = 11\n\t\tDD\t-1192\t; Index = 52 Token = 12\n\t\tDD\t-1457\t; Index = 52 Token = 13\n\t\tDD\t-1722\t; Index = 52 Token = 14\n\t\tDD\t-1987\t; Index = 52 Token = 15\n\t\tDD\t145\t; Index = 53 Token = 0\n\t\tDD\t436\t; Index = 53 Token = 1\n\t\tDD\t728\t; Index = 53 Token = 2\n\t\tDD\t1019\t; Index = 53 Token = 3\n\t\tDD\t1311\t; Index = 53 Token = 4\n\t\tDD\t1602\t; Index = 53 Token = 5\n\t\tDD\t1894\t; Index = 53 Token = 6\n\t\tDD\t2185\t; Index = 53 Token = 7\n\t\tDD\t-145\t; Index = 53 Token = 8\n\t\tDD\t-436\t; Index = 53 Token = 9\n\t\tDD\t-728\t; Index = 53 Token = 10\n\t\tDD\t-1019\t; Index = 53 Token = 11\n\t\tDD\t-1311\t; Index = 53 Token = 12\n\t\tDD\t-1602\t; Index = 53 Token = 13\n\t\tDD\t-1894\t; Index = 53 Token = 14\n\t\tDD\t-2185\t; Index = 53 Token = 15\n\t\tDD\t160\t; Index = 54 Token = 0\n\t\tDD\t480\t; Index = 54 Token = 1\n\t\tDD\t801\t; Index = 54 Token = 2\n\t\tDD\t1121\t; Index = 54 Token = 3\n\t\tDD\t1442\t; Index = 54 Token = 4\n\t\tDD\t1762\t; Index = 54 Token = 5\n\t\tDD\t2083\t; Index = 54 Token = 6\n\t\tDD\t2403\t; Index = 54 Token = 7\n\t\tDD\t-160\t; Index = 54 Token = 8\n\t\tDD\t-480\t; Index = 54 Token = 9\n\t\tDD\t-801\t; Index = 54 Token = 10\n\t\tDD\t-1121\t; Index = 54 Token = 11\n\t\tDD\t-1442\t; Index = 54 Token = 12\n\t\tDD\t-1762\t; Index = 54 Token = 13\n\t\tDD\t-2083\t; Index = 54 Token = 14\n\t\tDD\t-2403\t; Index = 54 Token = 15\n\t\tDD\t176\t; Index = 55 Token = 0\n\t\tDD\t528\t; Index = 55 Token = 1\n\t\tDD\t881\t; Index = 55 Token = 2\n\t\tDD\t1233\t; Index = 55 Token = 3\n\t\tDD\t1587\t; Index = 55 Token = 4\n\t\tDD\t1939\t; Index = 55 Token = 5\n\t\tDD\t2292\t; Index = 55 Token = 6\n\t\tDD\t2644\t; Index = 55 Token = 7\n\t\tDD\t-176\t; Index = 55 Token = 8\n\t\tDD\t-528\t; Index = 55 Token = 9\n\t\tDD\t-881\t; Index = 55 Token = 10\n\t\tDD\t-1233\t; Index = 55 Token = 11\n\t\tDD\t-1587\t; Index = 55 Token = 12\n\t\tDD\t-1939\t; Index = 55 Token = 13\n\t\tDD\t-2292\t; Index = 55 Token = 14\n\t\tDD\t-2644\t; Index = 55 Token = 15\n\t\tDD\t194\t; Index = 56 Token = 0\n\t\tDD\t582\t; Index = 56 Token = 1\n\t\tDD\t970\t; Index = 56 Token = 2\n\t\tDD\t1358\t; Index = 56 Token = 3\n\t\tDD\t1746\t; Index = 56 Token = 4\n\t\tDD\t2134\t; Index = 56 Token = 5\n\t\tDD\t2522\t; Index = 56 Token = 6\n\t\tDD\t2910\t; Index = 56 Token = 7\n\t\tDD\t-194\t; Index = 56 Token = 8\n\t\tDD\t-582\t; Index = 56 Token = 9\n\t\tDD\t-970\t; Index = 56 Token = 10\n\t\tDD\t-1358\t; Index = 56 Token = 11\n\t\tDD\t-1746\t; Index = 56 Token = 12\n\t\tDD\t-2134\t; Index = 56 Token = 13\n\t\tDD\t-2522\t; Index = 56 Token = 14\n\t\tDD\t-2910\t; Index = 56 Token = 15\n\t\tDD\t213\t; Index = 57 Token = 0\n\t\tDD\t639\t; Index = 57 Token = 1\n\t\tDD\t1066\t; Index = 57 Token = 2\n\t\tDD\t1492\t; Index = 57 Token = 3\n\t\tDD\t1920\t; Index = 57 Token = 4\n\t\tDD\t2346\t; Index = 57 Token = 5\n\t\tDD\t2773\t; Index = 57 Token = 6\n\t\tDD\t3199\t; Index = 57 Token = 7\n\t\tDD\t-213\t; Index = 57 Token = 8\n\t\tDD\t-639\t; Index = 57 Token = 9\n\t\tDD\t-1066\t; Index = 57 Token = 10\n\t\tDD\t-1492\t; Index = 57 Token = 11\n\t\tDD\t-1920\t; Index = 57 Token = 12\n\t\tDD\t-2346\t; Index = 57 Token = 13\n\t\tDD\t-2773\t; Index = 57 Token = 14\n\t\tDD\t-3199\t; Index = 57 Token = 15\n\t\tDD\t234\t; Index = 58 Token = 0\n\t\tDD\t703\t; Index = 58 Token = 1\n\t\tDD\t1173\t; Index = 58 Token = 2\n\t\tDD\t1642\t; Index = 58 Token = 3\n\t\tDD\t2112\t; Index = 58 Token = 4\n\t\tDD\t2581\t; Index = 58 Token = 5\n\t\tDD\t3051\t; Index = 58 Token = 6\n\t\tDD\t3520\t; Index = 58 Token = 7\n\t\tDD\t-234\t; Index = 58 Token = 8\n\t\tDD\t-703\t; Index = 58 Token = 9\n\t\tDD\t-1173\t; Index = 58 Token = 10\n\t\tDD\t-1642\t; Index = 58 Token = 11\n\t\tDD\t-2112\t; Index = 58 Token = 12\n\t\tDD\t-2581\t; Index = 58 Token = 13\n\t\tDD\t-3051\t; Index = 58 Token = 14\n\t\tDD\t-3520\t; Index = 58 Token = 15\n\t\tDD\t258\t; Index = 59 Token = 0\n\t\tDD\t774\t; Index = 59 Token = 1\n\t\tDD\t1291\t; Index = 59 Token = 2\n\t\tDD\t1807\t; Index = 59 Token = 3\n\t\tDD\t2324\t; Index = 59 Token = 4\n\t\tDD\t2840\t; Index = 59 Token = 5\n\t\tDD\t3357\t; Index = 59 Token = 6\n\t\tDD\t3873\t; Index = 59 Token = 7\n\t\tDD\t-258\t; Index = 59 Token = 8\n\t\tDD\t-774\t; Index = 59 Token = 9\n\t\tDD\t-1291\t; Index = 59 Token = 10\n\t\tDD\t-1807\t; Index = 59 Token = 11\n\t\tDD\t-2324\t; Index = 59 Token = 12\n\t\tDD\t-2840\t; Index = 59 Token = 13\n\t\tDD\t-3357\t; Index = 59 Token = 14\n\t\tDD\t-3873\t; Index = 59 Token = 15\n\t\tDD\t284\t; Index = 60 Token = 0\n\t\tDD\t852\t; Index = 60 Token = 1\n\t\tDD\t1420\t; Index = 60 Token = 2\n\t\tDD\t1988\t; Index = 60 Token = 3\n\t\tDD\t2556\t; Index = 60 Token = 4\n\t\tDD\t3124\t; Index = 60 Token = 5\n\t\tDD\t3692\t; Index = 60 Token = 6\n\t\tDD\t4260\t; Index = 60 Token = 7\n\t\tDD\t-284\t; Index = 60 Token = 8\n\t\tDD\t-852\t; Index = 60 Token = 9\n\t\tDD\t-1420\t; Index = 60 Token = 10\n\t\tDD\t-1988\t; Index = 60 Token = 11\n\t\tDD\t-2556\t; Index = 60 Token = 12\n\t\tDD\t-3124\t; Index = 60 Token = 13\n\t\tDD\t-3692\t; Index = 60 Token = 14\n\t\tDD\t-4260\t; Index = 60 Token = 15\n\t\tDD\t312\t; Index = 61 Token = 0\n\t\tDD\t936\t; Index = 61 Token = 1\n\t\tDD\t1561\t; Index = 61 Token = 2\n\t\tDD\t2185\t; Index = 61 Token = 3\n\t\tDD\t2811\t; Index = 61 Token = 4\n\t\tDD\t3435\t; Index = 61 Token = 5\n\t\tDD\t4060\t; Index = 61 Token = 6\n\t\tDD\t4684\t; Index = 61 Token = 7\n\t\tDD\t-312\t; Index = 61 Token = 8\n\t\tDD\t-936\t; Index = 61 Token = 9\n\t\tDD\t-1561\t; Index = 61 Token = 10\n\t\tDD\t-2185\t; Index = 61 Token = 11\n\t\tDD\t-2811\t; Index = 61 Token = 12\n\t\tDD\t-3435\t; Index = 61 Token = 13\n\t\tDD\t-4060\t; Index = 61 Token = 14\n\t\tDD\t-4684\t; Index = 61 Token = 15\n\t\tDD\t343\t; Index = 62 Token = 0\n\t\tDD\t1030\t; Index = 62 Token = 1\n\t\tDD\t1717\t; Index = 62 Token = 2\n\t\tDD\t2404\t; Index = 62 Token = 3\n\t\tDD\t3092\t; Index = 62 Token = 4\n\t\tDD\t3779\t; Index = 62 Token = 5\n\t\tDD\t4466\t; Index = 62 Token = 6\n\t\tDD\t5153\t; Index = 62 Token = 7\n\t\tDD\t-343\t; Index = 62 Token = 8\n\t\tDD\t-1030\t; Index = 62 Token = 9\n\t\tDD\t-1717\t; Index = 62 Token = 10\n\t\tDD\t-2404\t; Index = 62 Token = 11\n\t\tDD\t-3092\t; Index = 62 Token = 12\n\t\tDD\t-3779\t; Index = 62 Token = 13\n\t\tDD\t-4466\t; Index = 62 Token = 14\n\t\tDD\t-5153\t; Index = 62 Token = 15\n\t\tDD\t378\t; Index = 63 Token = 0\n\t\tDD\t1134\t; Index = 63 Token = 1\n\t\tDD\t1890\t; Index = 63 Token = 2\n\t\tDD\t2646\t; Index = 63 Token = 3\n\t\tDD\t3402\t; Index = 63 Token = 4\n\t\tDD\t4158\t; Index = 63 Token = 5\n\t\tDD\t4914\t; Index = 63 Token = 6\n\t\tDD\t5670\t; Index = 63 Token = 7\n\t\tDD\t-378\t; Index = 63 Token = 8\n\t\tDD\t-1134\t; Index = 63 Token = 9\n\t\tDD\t-1890\t; Index = 63 Token = 10\n\t\tDD\t-2646\t; Index = 63 Token = 11\n\t\tDD\t-3402\t; Index = 63 Token = 12\n\t\tDD\t-4158\t; Index = 63 Token = 13\n\t\tDD\t-4914\t; Index = 63 Token = 14\n\t\tDD\t-5670\t; Index = 63 Token = 15\n\t\tDD\t415\t; Index = 64 Token = 0\n\t\tDD\t1246\t; Index = 64 Token = 1\n\t\tDD\t2078\t; Index = 64 Token = 2\n\t\tDD\t2909\t; Index = 64 Token = 3\n\t\tDD\t3742\t; Index = 64 Token = 4\n\t\tDD\t4573\t; Index = 64 Token = 5\n\t\tDD\t5405\t; Index = 64 Token = 6\n\t\tDD\t6236\t; Index = 64 Token = 7\n\t\tDD\t-415\t; Index = 64 Token = 8\n\t\tDD\t-1246\t; Index = 64 Token = 9\n\t\tDD\t-2078\t; Index = 64 Token = 10\n\t\tDD\t-2909\t; Index = 64 Token = 11\n\t\tDD\t-3742\t; Index = 64 Token = 12\n\t\tDD\t-4573\t; Index = 64 Token = 13\n\t\tDD\t-5405\t; Index = 64 Token = 14\n\t\tDD\t-6236\t; Index = 64 Token = 15\n\t\tDD\t457\t; Index = 65 Token = 0\n\t\tDD\t1372\t; Index = 65 Token = 1\n\t\tDD\t2287\t; Index = 65 Token = 2\n\t\tDD\t3202\t; Index = 65 Token = 3\n\t\tDD\t4117\t; Index = 65 Token = 4\n\t\tDD\t5032\t; Index = 65 Token = 5\n\t\tDD\t5947\t; Index = 65 Token = 6\n\t\tDD\t6862\t; Index = 65 Token = 7\n\t\tDD\t-457\t; Index = 65 Token = 8\n\t\tDD\t-1372\t; Index = 65 Token = 9\n\t\tDD\t-2287\t; Index = 65 Token = 10\n\t\tDD\t-3202\t; Index = 65 Token = 11\n\t\tDD\t-4117\t; Index = 65 Token = 12\n\t\tDD\t-5032\t; Index = 65 Token = 13\n\t\tDD\t-5947\t; Index = 65 Token = 14\n\t\tDD\t-6862\t; Index = 65 Token = 15\n\t\tDD\t503\t; Index = 66 Token = 0\n\t\tDD\t1509\t; Index = 66 Token = 1\n\t\tDD\t2516\t; Index = 66 Token = 2\n\t\tDD\t3522\t; Index = 66 Token = 3\n\t\tDD\t4529\t; Index = 66 Token = 4\n\t\tDD\t5535\t; Index = 66 Token = 5\n\t\tDD\t6542\t; Index = 66 Token = 6\n\t\tDD\t7548\t; Index = 66 Token = 7\n\t\tDD\t-503\t; Index = 66 Token = 8\n\t\tDD\t-1509\t; Index = 66 Token = 9\n\t\tDD\t-2516\t; Index = 66 Token = 10\n\t\tDD\t-3522\t; Index = 66 Token = 11\n\t\tDD\t-4529\t; Index = 66 Token = 12\n\t\tDD\t-5535\t; Index = 66 Token = 13\n\t\tDD\t-6542\t; Index = 66 Token = 14\n\t\tDD\t-7548\t; Index = 66 Token = 15\n\t\tDD\t553\t; Index = 67 Token = 0\n\t\tDD\t1660\t; Index = 67 Token = 1\n\t\tDD\t2767\t; Index = 67 Token = 2\n\t\tDD\t3874\t; Index = 67 Token = 3\n\t\tDD\t4981\t; Index = 67 Token = 4\n\t\tDD\t6088\t; Index = 67 Token = 5\n\t\tDD\t7195\t; Index = 67 Token = 6\n\t\tDD\t8302\t; Index = 67 Token = 7\n\t\tDD\t-553\t; Index = 67 Token = 8\n\t\tDD\t-1660\t; Index = 67 Token = 9\n\t\tDD\t-2767\t; Index = 67 Token = 10\n\t\tDD\t-3874\t; Index = 67 Token = 11\n\t\tDD\t-4981\t; Index = 67 Token = 12\n\t\tDD\t-6088\t; Index = 67 Token = 13\n\t\tDD\t-7195\t; Index = 67 Token = 14\n\t\tDD\t-8302\t; Index = 67 Token = 15\n\t\tDD\t608\t; Index = 68 Token = 0\n\t\tDD\t1825\t; Index = 68 Token = 1\n\t\tDD\t3043\t; Index = 68 Token = 2\n\t\tDD\t4260\t; Index = 68 Token = 3\n\t\tDD\t5479\t; Index = 68 Token = 4\n\t\tDD\t6696\t; Index = 68 Token = 5\n\t\tDD\t7914\t; Index = 68 Token = 6\n\t\tDD\t9131\t; Index = 68 Token = 7\n\t\tDD\t-608\t; Index = 68 Token = 8\n\t\tDD\t-1825\t; Index = 68 Token = 9\n\t\tDD\t-3043\t; Index = 68 Token = 10\n\t\tDD\t-4260\t; Index = 68 Token = 11\n\t\tDD\t-5479\t; Index = 68 Token = 12\n\t\tDD\t-6696\t; Index = 68 Token = 13\n\t\tDD\t-7914\t; Index = 68 Token = 14\n\t\tDD\t-9131\t; Index = 68 Token = 15\n\t\tDD\t669\t; Index = 69 Token = 0\n\t\tDD\t2008\t; Index = 69 Token = 1\n\t\tDD\t3348\t; Index = 69 Token = 2\n\t\tDD\t4687\t; Index = 69 Token = 3\n\t\tDD\t6027\t; Index = 69 Token = 4\n\t\tDD\t7366\t; Index = 69 Token = 5\n\t\tDD\t8706\t; Index = 69 Token = 6\n\t\tDD\t10045\t; Index = 69 Token = 7\n\t\tDD\t-669\t; Index = 69 Token = 8\n\t\tDD\t-2008\t; Index = 69 Token = 9\n\t\tDD\t-3348\t; Index = 69 Token = 10\n\t\tDD\t-4687\t; Index = 69 Token = 11\n\t\tDD\t-6027\t; Index = 69 Token = 12\n\t\tDD\t-7366\t; Index = 69 Token = 13\n\t\tDD\t-8706\t; Index = 69 Token = 14\n\t\tDD\t-10045\t; Index = 69 Token = 15\n\t\tDD\t736\t; Index = 70 Token = 0\n\t\tDD\t2209\t; Index = 70 Token = 1\n\t\tDD\t3683\t; Index = 70 Token = 2\n\t\tDD\t5156\t; Index = 70 Token = 3\n\t\tDD\t6630\t; Index = 70 Token = 4\n\t\tDD\t8103\t; Index = 70 Token = 5\n\t\tDD\t9577\t; Index = 70 Token = 6\n\t\tDD\t11050\t; Index = 70 Token = 7\n\t\tDD\t-736\t; Index = 70 Token = 8\n\t\tDD\t-2209\t; Index = 70 Token = 9\n\t\tDD\t-3683\t; Index = 70 Token = 10\n\t\tDD\t-5156\t; Index = 70 Token = 11\n\t\tDD\t-6630\t; Index = 70 Token = 12\n\t\tDD\t-8103\t; Index = 70 Token = 13\n\t\tDD\t-9577\t; Index = 70 Token = 14\n\t\tDD\t-11050\t; Index = 70 Token = 15\n\t\tDD\t810\t; Index = 71 Token = 0\n\t\tDD\t2431\t; Index = 71 Token = 1\n\t\tDD\t4052\t; Index = 71 Token = 2\n\t\tDD\t5673\t; Index = 71 Token = 3\n\t\tDD\t7294\t; Index = 71 Token = 4\n\t\tDD\t8915\t; Index = 71 Token = 5\n\t\tDD\t10536\t; Index = 71 Token = 6\n\t\tDD\t12157\t; Index = 71 Token = 7\n\t\tDD\t-810\t; Index = 71 Token = 8\n\t\tDD\t-2431\t; Index = 71 Token = 9\n\t\tDD\t-4052\t; Index = 71 Token = 10\n\t\tDD\t-5673\t; Index = 71 Token = 11\n\t\tDD\t-7294\t; Index = 71 Token = 12\n\t\tDD\t-8915\t; Index = 71 Token = 13\n\t\tDD\t-10536\t; Index = 71 Token = 14\n\t\tDD\t-12157\t; Index = 71 Token = 15\n\t\tDD\t891\t; Index = 72 Token = 0\n\t\tDD\t2674\t; Index = 72 Token = 1\n\t\tDD\t4457\t; Index = 72 Token = 2\n\t\tDD\t6240\t; Index = 72 Token = 3\n\t\tDD\t8023\t; Index = 72 Token = 4\n\t\tDD\t9806\t; Index = 72 Token = 5\n\t\tDD\t11589\t; Index = 72 Token = 6\n\t\tDD\t13372\t; Index = 72 Token = 7\n\t\tDD\t-891\t; Index = 72 Token = 8\n\t\tDD\t-2674\t; Index = 72 Token = 9\n\t\tDD\t-4457\t; Index = 72 Token = 10\n\t\tDD\t-6240\t; Index = 72 Token = 11\n\t\tDD\t-8023\t; Index = 72 Token = 12\n\t\tDD\t-9806\t; Index = 72 Token = 13\n\t\tDD\t-11589\t; Index = 72 Token = 14\n\t\tDD\t-13372\t; Index = 72 Token = 15\n\t\tDD\t980\t; Index = 73 Token = 0\n\t\tDD\t2941\t; Index = 73 Token = 1\n\t\tDD\t4902\t; Index = 73 Token = 2\n\t\tDD\t6863\t; Index = 73 Token = 3\n\t\tDD\t8825\t; Index = 73 Token = 4\n\t\tDD\t10786\t; Index = 73 Token = 5\n\t\tDD\t12747\t; Index = 73 Token = 6\n\t\tDD\t14708\t; Index = 73 Token = 7\n\t\tDD\t-980\t; Index = 73 Token = 8\n\t\tDD\t-2941\t; Index = 73 Token = 9\n\t\tDD\t-4902\t; Index = 73 Token = 10\n\t\tDD\t-6863\t; Index = 73 Token = 11\n\t\tDD\t-8825\t; Index = 73 Token = 12\n\t\tDD\t-10786\t; Index = 73 Token = 13\n\t\tDD\t-12747\t; Index = 73 Token = 14\n\t\tDD\t-14708\t; Index = 73 Token = 15\n\t\tDD\t1078\t; Index = 74 Token = 0\n\t\tDD\t3235\t; Index = 74 Token = 1\n\t\tDD\t5393\t; Index = 74 Token = 2\n\t\tDD\t7550\t; Index = 74 Token = 3\n\t\tDD\t9708\t; Index = 74 Token = 4\n\t\tDD\t11865\t; Index = 74 Token = 5\n\t\tDD\t14023\t; Index = 74 Token = 6\n\t\tDD\t16180\t; Index = 74 Token = 7\n\t\tDD\t-1078\t; Index = 74 Token = 8\n\t\tDD\t-3235\t; Index = 74 Token = 9\n\t\tDD\t-5393\t; Index = 74 Token = 10\n\t\tDD\t-7550\t; Index = 74 Token = 11\n\t\tDD\t-9708\t; Index = 74 Token = 12\n\t\tDD\t-11865\t; Index = 74 Token = 13\n\t\tDD\t-14023\t; Index = 74 Token = 14\n\t\tDD\t-16180\t; Index = 74 Token = 15\n\t\tDD\t1186\t; Index = 75 Token = 0\n\t\tDD\t3559\t; Index = 75 Token = 1\n\t\tDD\t5932\t; Index = 75 Token = 2\n\t\tDD\t8305\t; Index = 75 Token = 3\n\t\tDD\t10679\t; Index = 75 Token = 4\n\t\tDD\t13052\t; Index = 75 Token = 5\n\t\tDD\t15425\t; Index = 75 Token = 6\n\t\tDD\t17798\t; Index = 75 Token = 7\n\t\tDD\t-1186\t; Index = 75 Token = 8\n\t\tDD\t-3559\t; Index = 75 Token = 9\n\t\tDD\t-5932\t; Index = 75 Token = 10\n\t\tDD\t-8305\t; Index = 75 Token = 11\n\t\tDD\t-10679\t; Index = 75 Token = 12\n\t\tDD\t-13052\t; Index = 75 Token = 13\n\t\tDD\t-15425\t; Index = 75 Token = 14\n\t\tDD\t-17798\t; Index = 75 Token = 15\n\t\tDD\t1305\t; Index = 76 Token = 0\n\t\tDD\t3915\t; Index = 76 Token = 1\n\t\tDD\t6526\t; Index = 76 Token = 2\n\t\tDD\t9136\t; Index = 76 Token = 3\n\t\tDD\t11747\t; Index = 76 Token = 4\n\t\tDD\t14357\t; Index = 76 Token = 5\n\t\tDD\t16968\t; Index = 76 Token = 6\n\t\tDD\t19578\t; Index = 76 Token = 7\n\t\tDD\t-1305\t; Index = 76 Token = 8\n\t\tDD\t-3915\t; Index = 76 Token = 9\n\t\tDD\t-6526\t; Index = 76 Token = 10\n\t\tDD\t-9136\t; Index = 76 Token = 11\n\t\tDD\t-11747\t; Index = 76 Token = 12\n\t\tDD\t-14357\t; Index = 76 Token = 13\n\t\tDD\t-16968\t; Index = 76 Token = 14\n\t\tDD\t-19578\t; Index = 76 Token = 15\n\t\tDD\t1435\t; Index = 77 Token = 0\n\t\tDD\t4306\t; Index = 77 Token = 1\n\t\tDD\t7178\t; Index = 77 Token = 2\n\t\tDD\t10049\t; Index = 77 Token = 3\n\t\tDD\t12922\t; Index = 77 Token = 4\n\t\tDD\t15793\t; Index = 77 Token = 5\n\t\tDD\t18665\t; Index = 77 Token = 6\n\t\tDD\t21536\t; Index = 77 Token = 7\n\t\tDD\t-1435\t; Index = 77 Token = 8\n\t\tDD\t-4306\t; Index = 77 Token = 9\n\t\tDD\t-7178\t; Index = 77 Token = 10\n\t\tDD\t-10049\t; Index = 77 Token = 11\n\t\tDD\t-12922\t; Index = 77 Token = 12\n\t\tDD\t-15793\t; Index = 77 Token = 13\n\t\tDD\t-18665\t; Index = 77 Token = 14\n\t\tDD\t-21536\t; Index = 77 Token = 15\n\t\tDD\t1579\t; Index = 78 Token = 0\n\t\tDD\t4737\t; Index = 78 Token = 1\n\t\tDD\t7896\t; Index = 78 Token = 2\n\t\tDD\t11054\t; Index = 78 Token = 3\n\t\tDD\t14214\t; Index = 78 Token = 4\n\t\tDD\t17372\t; Index = 78 Token = 5\n\t\tDD\t20531\t; Index = 78 Token = 6\n\t\tDD\t23689\t; Index = 78 Token = 7\n\t\tDD\t-1579\t; Index = 78 Token = 8\n\t\tDD\t-4737\t; Index = 78 Token = 9\n\t\tDD\t-7896\t; Index = 78 Token = 10\n\t\tDD\t-11054\t; Index = 78 Token = 11\n\t\tDD\t-14214\t; Index = 78 Token = 12\n\t\tDD\t-17372\t; Index = 78 Token = 13\n\t\tDD\t-20531\t; Index = 78 Token = 14\n\t\tDD\t-23689\t; Index = 78 Token = 15\n\t\tDD\t1737\t; Index = 79 Token = 0\n\t\tDD\t5211\t; Index = 79 Token = 1\n\t\tDD\t8686\t; Index = 79 Token = 2\n\t\tDD\t12160\t; Index = 79 Token = 3\n\t\tDD\t15636\t; Index = 79 Token = 4\n\t\tDD\t19110\t; Index = 79 Token = 5\n\t\tDD\t22585\t; Index = 79 Token = 6\n\t\tDD\t26059\t; Index = 79 Token = 7\n\t\tDD\t-1737\t; Index = 79 Token = 8\n\t\tDD\t-5211\t; Index = 79 Token = 9\n\t\tDD\t-8686\t; Index = 79 Token = 10\n\t\tDD\t-12160\t; Index = 79 Token = 11\n\t\tDD\t-15636\t; Index = 79 Token = 12\n\t\tDD\t-19110\t; Index = 79 Token = 13\n\t\tDD\t-22585\t; Index = 79 Token = 14\n\t\tDD\t-26059\t; Index = 79 Token = 15\n\t\tDD\t1911\t; Index = 80 Token = 0\n\t\tDD\t5733\t; Index = 80 Token = 1\n\t\tDD\t9555\t; Index = 80 Token = 2\n\t\tDD\t13377\t; Index = 80 Token = 3\n\t\tDD\t17200\t; Index = 80 Token = 4\n\t\tDD\t21022\t; Index = 80 Token = 5\n\t\tDD\t24844\t; Index = 80 Token = 6\n\t\tDD\t28666\t; Index = 80 Token = 7\n\t\tDD\t-1911\t; Index = 80 Token = 8\n\t\tDD\t-5733\t; Index = 80 Token = 9\n\t\tDD\t-9555\t; Index = 80 Token = 10\n\t\tDD\t-13377\t; Index = 80 Token = 11\n\t\tDD\t-17200\t; Index = 80 Token = 12\n\t\tDD\t-21022\t; Index = 80 Token = 13\n\t\tDD\t-24844\t; Index = 80 Token = 14\n\t\tDD\t-28666\t; Index = 80 Token = 15\n\t\tDD\t2102\t; Index = 81 Token = 0\n\t\tDD\t6306\t; Index = 81 Token = 1\n\t\tDD\t10511\t; Index = 81 Token = 2\n\t\tDD\t14715\t; Index = 81 Token = 3\n\t\tDD\t18920\t; Index = 81 Token = 4\n\t\tDD\t23124\t; Index = 81 Token = 5\n\t\tDD\t27329\t; Index = 81 Token = 6\n\t\tDD\t31533\t; Index = 81 Token = 7\n\t\tDD\t-2102\t; Index = 81 Token = 8\n\t\tDD\t-6306\t; Index = 81 Token = 9\n\t\tDD\t-10511\t; Index = 81 Token = 10\n\t\tDD\t-14715\t; Index = 81 Token = 11\n\t\tDD\t-18920\t; Index = 81 Token = 12\n\t\tDD\t-23124\t; Index = 81 Token = 13\n\t\tDD\t-27329\t; Index = 81 Token = 14\n\t\tDD\t-31533\t; Index = 81 Token = 15\n\t\tDD\t2312\t; Index = 82 Token = 0\n\t\tDD\t6937\t; Index = 82 Token = 1\n\t\tDD\t11562\t; Index = 82 Token = 2\n\t\tDD\t16187\t; Index = 82 Token = 3\n\t\tDD\t20812\t; Index = 82 Token = 4\n\t\tDD\t25437\t; Index = 82 Token = 5\n\t\tDD\t30062\t; Index = 82 Token = 6\n\t\tDD\t34687\t; Index = 82 Token = 7\n\t\tDD\t-2312\t; Index = 82 Token = 8\n\t\tDD\t-6937\t; Index = 82 Token = 9\n\t\tDD\t-11562\t; Index = 82 Token = 10\n\t\tDD\t-16187\t; Index = 82 Token = 11\n\t\tDD\t-20812\t; Index = 82 Token = 12\n\t\tDD\t-25437\t; Index = 82 Token = 13\n\t\tDD\t-30062\t; Index = 82 Token = 14\n\t\tDD\t-34687\t; Index = 82 Token = 15\n\t\tDD\t2543\t; Index = 83 Token = 0\n\t\tDD\t7630\t; Index = 83 Token = 1\n\t\tDD\t12718\t; Index = 83 Token = 2\n\t\tDD\t17805\t; Index = 83 Token = 3\n\t\tDD\t22893\t; Index = 83 Token = 4\n\t\tDD\t27980\t; Index = 83 Token = 5\n\t\tDD\t33068\t; Index = 83 Token = 6\n\t\tDD\t38155\t; Index = 83 Token = 7\n\t\tDD\t-2543\t; Index = 83 Token = 8\n\t\tDD\t-7630\t; Index = 83 Token = 9\n\t\tDD\t-12718\t; Index = 83 Token = 10\n\t\tDD\t-17805\t; Index = 83 Token = 11\n\t\tDD\t-22893\t; Index = 83 Token = 12\n\t\tDD\t-27980\t; Index = 83 Token = 13\n\t\tDD\t-33068\t; Index = 83 Token = 14\n\t\tDD\t-38155\t; Index = 83 Token = 15\n\t\tDD\t2798\t; Index = 84 Token = 0\n\t\tDD\t8394\t; Index = 84 Token = 1\n\t\tDD\t13990\t; Index = 84 Token = 2\n\t\tDD\t19586\t; Index = 84 Token = 3\n\t\tDD\t25183\t; Index = 84 Token = 4\n\t\tDD\t30779\t; Index = 84 Token = 5\n\t\tDD\t36375\t; Index = 84 Token = 6\n\t\tDD\t41971\t; Index = 84 Token = 7\n\t\tDD\t-2798\t; Index = 84 Token = 8\n\t\tDD\t-8394\t; Index = 84 Token = 9\n\t\tDD\t-13990\t; Index = 84 Token = 10\n\t\tDD\t-19586\t; Index = 84 Token = 11\n\t\tDD\t-25183\t; Index = 84 Token = 12\n\t\tDD\t-30779\t; Index = 84 Token = 13\n\t\tDD\t-36375\t; Index = 84 Token = 14\n\t\tDD\t-41971\t; Index = 84 Token = 15\n\t\tDD\t3077\t; Index = 85 Token = 0\n\t\tDD\t9232\t; Index = 85 Token = 1\n\t\tDD\t15388\t; Index = 85 Token = 2\n\t\tDD\t21543\t; Index = 85 Token = 3\n\t\tDD\t27700\t; Index = 85 Token = 4\n\t\tDD\t33855\t; Index = 85 Token = 5\n\t\tDD\t40011\t; Index = 85 Token = 6\n\t\tDD\t46166\t; Index = 85 Token = 7\n\t\tDD\t-3077\t; Index = 85 Token = 8\n\t\tDD\t-9232\t; Index = 85 Token = 9\n\t\tDD\t-15388\t; Index = 85 Token = 10\n\t\tDD\t-21543\t; Index = 85 Token = 11\n\t\tDD\t-27700\t; Index = 85 Token = 12\n\t\tDD\t-33855\t; Index = 85 Token = 13\n\t\tDD\t-40011\t; Index = 85 Token = 14\n\t\tDD\t-46166\t; Index = 85 Token = 15\n\t\tDD\t3385\t; Index = 86 Token = 0\n\t\tDD\t10156\t; Index = 86 Token = 1\n\t\tDD\t16928\t; Index = 86 Token = 2\n\t\tDD\t23699\t; Index = 86 Token = 3\n\t\tDD\t30471\t; Index = 86 Token = 4\n\t\tDD\t37242\t; Index = 86 Token = 5\n\t\tDD\t44014\t; Index = 86 Token = 6\n\t\tDD\t50785\t; Index = 86 Token = 7\n\t\tDD\t-3385\t; Index = 86 Token = 8\n\t\tDD\t-10156\t; Index = 86 Token = 9\n\t\tDD\t-16928\t; Index = 86 Token = 10\n\t\tDD\t-23699\t; Index = 86 Token = 11\n\t\tDD\t-30471\t; Index = 86 Token = 12\n\t\tDD\t-37242\t; Index = 86 Token = 13\n\t\tDD\t-44014\t; Index = 86 Token = 14\n\t\tDD\t-50785\t; Index = 86 Token = 15\n\t\tDD\t3724\t; Index = 87 Token = 0\n\t\tDD\t11172\t; Index = 87 Token = 1\n\t\tDD\t18621\t; Index = 87 Token = 2\n\t\tDD\t26069\t; Index = 87 Token = 3\n\t\tDD\t33518\t; Index = 87 Token = 4\n\t\tDD\t40966\t; Index = 87 Token = 5\n\t\tDD\t48415\t; Index = 87 Token = 6\n\t\tDD\t55863\t; Index = 87 Token = 7\n\t\tDD\t-3724\t; Index = 87 Token = 8\n\t\tDD\t-11172\t; Index = 87 Token = 9\n\t\tDD\t-18621\t; Index = 87 Token = 10\n\t\tDD\t-26069\t; Index = 87 Token = 11\n\t\tDD\t-33518\t; Index = 87 Token = 12\n\t\tDD\t-40966\t; Index = 87 Token = 13\n\t\tDD\t-48415\t; Index = 87 Token = 14\n\t\tDD\t-55863\t; Index = 87 Token = 15\n\t\tDD\t4095\t; Index = 88 Token = 0\n\t\tDD\t12286\t; Index = 88 Token = 1\n\t\tDD\t20478\t; Index = 88 Token = 2\n\t\tDD\t28669\t; Index = 88 Token = 3\n\t\tDD\t36862\t; Index = 88 Token = 4\n\t\tDD\t45053\t; Index = 88 Token = 5\n\t\tDD\t53245\t; Index = 88 Token = 6\n\t\tDD\t61436\t; Index = 88 Token = 7\n\t\tDD\t-4095\t; Index = 88 Token = 8\n\t\tDD\t-12286\t; Index = 88 Token = 9\n\t\tDD\t-20478\t; Index = 88 Token = 10\n\t\tDD\t-28669\t; Index = 88 Token = 11\n\t\tDD\t-36862\t; Index = 88 Token = 12\n\t\tDD\t-45053\t; Index = 88 Token = 13\n\t\tDD\t-53245\t; Index = 88 Token = 14\n\t\tDD\t-61436\t; Index = 88 Token = 15\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/FUNCTION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SOUNDIO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort Decompress_Frame(void * source, void * dest, short size);\nint cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback);\nint cdecl Stream_Sample(void *buffer, long size, BOOL (*callback);\nint cdecl File_Stream_Sample(char const *filename);\nint cdecl File_Stream_Sample_Vol(char const *filename, int volume);\nvoid cdecl _saveregs _loadds Sound_Callback(void);\nvoid cdecl far _saveregs _loadds maintenance_callback(void);\nvoid *cdecl Load_Sample(char const *filename);\nlong cdecl Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);\nlong cdecl Sample_Read(int fh, void *buffer, long size);\nvoid cdecl Free_Sample(void const *sample);\nBOOL cdecl Sound_Init(int sfx, int score, int sample);\nvoid far VQA_TimerCallback(void);\nBOOL Audio_Init(int sample, int address, int inter, int dma);\nvoid cdecl Sound_End(void);\nvoid cdecl Stop_Sample(int handle);\nBOOL cdecl Sample_Status(int handle);\nBOOL cdecl Is_Sample_Playing(void const * sample);\nvoid cdecl Stop_Sample_Playing(void const * sample);\nint cdecl Play_Sample(void const *sample);\nint cdecl Play_Sample_Vol(void const *sample, int priority, int volume);\nint cdecl Set_Sound_Vol(int volume);\nint cdecl Set_Score_Vol(int volume);\nvoid cdecl Fade_Sample(int handle, int ticks);\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/INDEXTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* wIndexTable - ADPCM Lookup table for indexes\n;****************************************************************************\n\n\t\talign\t4\n\nwIndexTable\tDW\t0\t* 2\t; Index = 0 Token = 0\n\t\tDW\t0\t* 2\t; Index = 0 Token = 1\n\t\tDW\t0\t* 2\t; Index = 0 Token = 2\n\t\tDW\t0\t* 2\t; Index = 0 Token = 3\n\t\tDW\t32\t* 2\t; Index = 0 Token = 4\n\t\tDW\t64\t* 2\t; Index = 0 Token = 5\n\t\tDW\t96\t* 2\t; Index = 0 Token = 6\n\t\tDW\t128\t* 2\t; Index = 0 Token = 7\n\t\tDW\t0\t* 2\t; Index = 0 Token = 8\n\t\tDW\t0\t* 2\t; Index = 0 Token = 9\n\t\tDW\t0\t* 2\t; Index = 0 Token = 10\n\t\tDW\t0\t* 2\t; Index = 0 Token = 11\n\t\tDW\t32\t* 2\t; Index = 0 Token = 12\n\t\tDW\t64\t* 2\t; Index = 0 Token = 13\n\t\tDW\t96\t* 2\t; Index = 0 Token = 14\n\t\tDW\t128\t* 2\t; Index = 0 Token = 15\n\t\tDW\t0\t* 2\t; Index = 1 Token = 0\n\t\tDW\t0\t* 2\t; Index = 1 Token = 1\n\t\tDW\t0\t* 2\t; Index = 1 Token = 2\n\t\tDW\t0\t* 2\t; Index = 1 Token = 3\n\t\tDW\t48\t* 2\t; Index = 1 Token = 4\n\t\tDW\t80\t* 2\t; Index = 1 Token = 5\n\t\tDW\t112\t* 2\t; Index = 1 Token = 6\n\t\tDW\t144\t* 2\t; Index = 1 Token = 7\n\t\tDW\t0\t* 2\t; Index = 1 Token = 8\n\t\tDW\t0\t* 2\t; Index = 1 Token = 9\n\t\tDW\t0\t* 2\t; Index = 1 Token = 10\n\t\tDW\t0\t* 2\t; Index = 1 Token = 11\n\t\tDW\t48\t* 2\t; Index = 1 Token = 12\n\t\tDW\t80\t* 2\t; Index = 1 Token = 13\n\t\tDW\t112\t* 2\t; Index = 1 Token = 14\n\t\tDW\t144\t* 2\t; Index = 1 Token = 15\n\t\tDW\t16\t* 2\t; Index = 2 Token = 0\n\t\tDW\t16\t* 2\t; Index = 2 Token = 1\n\t\tDW\t16\t* 2\t; Index = 2 Token = 2\n\t\tDW\t16\t* 2\t; Index = 2 Token = 3\n\t\tDW\t64\t* 2\t; Index = 2 Token = 4\n\t\tDW\t96\t* 2\t; Index = 2 Token = 5\n\t\tDW\t128\t* 2\t; Index = 2 Token = 6\n\t\tDW\t160\t* 2\t; Index = 2 Token = 7\n\t\tDW\t16\t* 2\t; Index = 2 Token = 8\n\t\tDW\t16\t* 2\t; Index = 2 Token = 9\n\t\tDW\t16\t* 2\t; Index = 2 Token = 10\n\t\tDW\t16\t* 2\t; Index = 2 Token = 11\n\t\tDW\t64\t* 2\t; Index = 2 Token = 12\n\t\tDW\t96\t* 2\t; Index = 2 Token = 13\n\t\tDW\t128\t* 2\t; Index = 2 Token = 14\n\t\tDW\t160\t* 2\t; Index = 2 Token = 15\n\t\tDW\t32\t* 2\t; Index = 3 Token = 0\n\t\tDW\t32\t* 2\t; Index = 3 Token = 1\n\t\tDW\t32\t* 2\t; Index = 3 Token = 2\n\t\tDW\t32\t* 2\t; Index = 3 Token = 3\n\t\tDW\t80\t* 2\t; Index = 3 Token = 4\n\t\tDW\t112\t* 2\t; Index = 3 Token = 5\n\t\tDW\t144\t* 2\t; Index = 3 Token = 6\n\t\tDW\t176\t* 2\t; Index = 3 Token = 7\n\t\tDW\t32\t* 2\t; Index = 3 Token = 8\n\t\tDW\t32\t* 2\t; Index = 3 Token = 9\n\t\tDW\t32\t* 2\t; Index = 3 Token = 10\n\t\tDW\t32\t* 2\t; Index = 3 Token = 11\n\t\tDW\t80\t* 2\t; Index = 3 Token = 12\n\t\tDW\t112\t* 2\t; Index = 3 Token = 13\n\t\tDW\t144\t* 2\t; Index = 3 Token = 14\n\t\tDW\t176\t* 2\t; Index = 3 Token = 15\n\t\tDW\t48\t* 2\t; Index = 4 Token = 0\n\t\tDW\t48\t* 2\t; Index = 4 Token = 1\n\t\tDW\t48\t* 2\t; Index = 4 Token = 2\n\t\tDW\t48\t* 2\t; Index = 4 Token = 3\n\t\tDW\t96\t* 2\t; Index = 4 Token = 4\n\t\tDW\t128\t* 2\t; Index = 4 Token = 5\n\t\tDW\t160\t* 2\t; Index = 4 Token = 6\n\t\tDW\t192\t* 2\t; Index = 4 Token = 7\n\t\tDW\t48\t* 2\t; Index = 4 Token = 8\n\t\tDW\t48\t* 2\t; Index = 4 Token = 9\n\t\tDW\t48\t* 2\t; Index = 4 Token = 10\n\t\tDW\t48\t* 2\t; Index = 4 Token = 11\n\t\tDW\t96\t* 2\t; Index = 4 Token = 12\n\t\tDW\t128\t* 2\t; Index = 4 Token = 13\n\t\tDW\t160\t* 2\t; Index = 4 Token = 14\n\t\tDW\t192\t* 2\t; Index = 4 Token = 15\n\t\tDW\t64\t* 2\t; Index = 5 Token = 0\n\t\tDW\t64\t* 2\t; Index = 5 Token = 1\n\t\tDW\t64\t* 2\t; Index = 5 Token = 2\n\t\tDW\t64\t* 2\t; Index = 5 Token = 3\n\t\tDW\t112\t* 2\t; Index = 5 Token = 4\n\t\tDW\t144\t* 2\t; Index = 5 Token = 5\n\t\tDW\t176\t* 2\t; Index = 5 Token = 6\n\t\tDW\t208\t* 2\t; Index = 5 Token = 7\n\t\tDW\t64\t* 2\t; Index = 5 Token = 8\n\t\tDW\t64\t* 2\t; Index = 5 Token = 9\n\t\tDW\t64\t* 2\t; Index = 5 Token = 10\n\t\tDW\t64\t* 2\t; Index = 5 Token = 11\n\t\tDW\t112\t* 2\t; Index = 5 Token = 12\n\t\tDW\t144\t* 2\t; Index = 5 Token = 13\n\t\tDW\t176\t* 2\t; Index = 5 Token = 14\n\t\tDW\t208\t* 2\t; Index = 5 Token = 15\n\t\tDW\t80\t* 2\t; Index = 6 Token = 0\n\t\tDW\t80\t* 2\t; Index = 6 Token = 1\n\t\tDW\t80\t* 2\t; Index = 6 Token = 2\n\t\tDW\t80\t* 2\t; Index = 6 Token = 3\n\t\tDW\t128\t* 2\t; Index = 6 Token = 4\n\t\tDW\t160\t* 2\t; Index = 6 Token = 5\n\t\tDW\t192\t* 2\t; Index = 6 Token = 6\n\t\tDW\t224\t* 2\t; Index = 6 Token = 7\n\t\tDW\t80\t* 2\t; Index = 6 Token = 8\n\t\tDW\t80\t* 2\t; Index = 6 Token = 9\n\t\tDW\t80\t* 2\t; Index = 6 Token = 10\n\t\tDW\t80\t* 2\t; Index = 6 Token = 11\n\t\tDW\t128\t* 2\t; Index = 6 Token = 12\n\t\tDW\t160\t* 2\t; Index = 6 Token = 13\n\t\tDW\t192\t* 2\t; Index = 6 Token = 14\n\t\tDW\t224\t* 2\t; Index = 6 Token = 15\n\t\tDW\t96\t* 2\t; Index = 7 Token = 0\n\t\tDW\t96\t* 2\t; Index = 7 Token = 1\n\t\tDW\t96\t* 2\t; Index = 7 Token = 2\n\t\tDW\t96\t* 2\t; Index = 7 Token = 3\n\t\tDW\t144\t* 2\t; Index = 7 Token = 4\n\t\tDW\t176\t* 2\t; Index = 7 Token = 5\n\t\tDW\t208\t* 2\t; Index = 7 Token = 6\n\t\tDW\t240\t* 2\t; Index = 7 Token = 7\n\t\tDW\t96\t* 2\t; Index = 7 Token = 8\n\t\tDW\t96\t* 2\t; Index = 7 Token = 9\n\t\tDW\t96\t* 2\t; Index = 7 Token = 10\n\t\tDW\t96\t* 2\t; Index = 7 Token = 11\n\t\tDW\t144\t* 2\t; Index = 7 Token = 12\n\t\tDW\t176\t* 2\t; Index = 7 Token = 13\n\t\tDW\t208\t* 2\t; Index = 7 Token = 14\n\t\tDW\t240\t* 2\t; Index = 7 Token = 15\n\t\tDW\t112\t* 2\t; Index = 8 Token = 0\n\t\tDW\t112\t* 2\t; Index = 8 Token = 1\n\t\tDW\t112\t* 2\t; Index = 8 Token = 2\n\t\tDW\t112\t* 2\t; Index = 8 Token = 3\n\t\tDW\t160\t* 2\t; Index = 8 Token = 4\n\t\tDW\t192\t* 2\t; Index = 8 Token = 5\n\t\tDW\t224\t* 2\t; Index = 8 Token = 6\n\t\tDW\t256\t* 2\t; Index = 8 Token = 7\n\t\tDW\t112\t* 2\t; Index = 8 Token = 8\n\t\tDW\t112\t* 2\t; Index = 8 Token = 9\n\t\tDW\t112\t* 2\t; Index = 8 Token = 10\n\t\tDW\t112\t* 2\t; Index = 8 Token = 11\n\t\tDW\t160\t* 2\t; Index = 8 Token = 12\n\t\tDW\t192\t* 2\t; Index = 8 Token = 13\n\t\tDW\t224\t* 2\t; Index = 8 Token = 14\n\t\tDW\t256\t* 2\t; Index = 8 Token = 15\n\t\tDW\t128\t* 2\t; Index = 9 Token = 0\n\t\tDW\t128\t* 2\t; Index = 9 Token = 1\n\t\tDW\t128\t* 2\t; Index = 9 Token = 2\n\t\tDW\t128\t* 2\t; Index = 9 Token = 3\n\t\tDW\t176\t* 2\t; Index = 9 Token = 4\n\t\tDW\t208\t* 2\t; Index = 9 Token = 5\n\t\tDW\t240\t* 2\t; Index = 9 Token = 6\n\t\tDW\t272\t* 2\t; Index = 9 Token = 7\n\t\tDW\t128\t* 2\t; Index = 9 Token = 8\n\t\tDW\t128\t* 2\t; Index = 9 Token = 9\n\t\tDW\t128\t* 2\t; Index = 9 Token = 10\n\t\tDW\t128\t* 2\t; Index = 9 Token = 11\n\t\tDW\t176\t* 2\t; Index = 9 Token = 12\n\t\tDW\t208\t* 2\t; Index = 9 Token = 13\n\t\tDW\t240\t* 2\t; Index = 9 Token = 14\n\t\tDW\t272\t* 2\t; Index = 9 Token = 15\n\t\tDW\t144\t* 2\t; Index = 10 Token = 0\n\t\tDW\t144\t* 2\t; Index = 10 Token = 1\n\t\tDW\t144\t* 2\t; Index = 10 Token = 2\n\t\tDW\t144\t* 2\t; Index = 10 Token = 3\n\t\tDW\t192\t* 2\t; Index = 10 Token = 4\n\t\tDW\t224\t* 2\t; Index = 10 Token = 5\n\t\tDW\t256\t* 2\t; Index = 10 Token = 6\n\t\tDW\t288\t* 2\t; Index = 10 Token = 7\n\t\tDW\t144\t* 2\t; Index = 10 Token = 8\n\t\tDW\t144\t* 2\t; Index = 10 Token = 9\n\t\tDW\t144\t* 2\t; Index = 10 Token = 10\n\t\tDW\t144\t* 2\t; Index = 10 Token = 11\n\t\tDW\t192\t* 2\t; Index = 10 Token = 12\n\t\tDW\t224\t* 2\t; Index = 10 Token = 13\n\t\tDW\t256\t* 2\t; Index = 10 Token = 14\n\t\tDW\t288\t* 2\t; Index = 10 Token = 15\n\t\tDW\t160\t* 2\t; Index = 11 Token = 0\n\t\tDW\t160\t* 2\t; Index = 11 Token = 1\n\t\tDW\t160\t* 2\t; Index = 11 Token = 2\n\t\tDW\t160\t* 2\t; Index = 11 Token = 3\n\t\tDW\t208\t* 2\t; Index = 11 Token = 4\n\t\tDW\t240\t* 2\t; Index = 11 Token = 5\n\t\tDW\t272\t* 2\t; Index = 11 Token = 6\n\t\tDW\t304\t* 2\t; Index = 11 Token = 7\n\t\tDW\t160\t* 2\t; Index = 11 Token = 8\n\t\tDW\t160\t* 2\t; Index = 11 Token = 9\n\t\tDW\t160\t* 2\t; Index = 11 Token = 10\n\t\tDW\t160\t* 2\t; Index = 11 Token = 11\n\t\tDW\t208\t* 2\t; Index = 11 Token = 12\n\t\tDW\t240\t* 2\t; Index = 11 Token = 13\n\t\tDW\t272\t* 2\t; Index = 11 Token = 14\n\t\tDW\t304\t* 2\t; Index = 11 Token = 15\n\t\tDW\t176\t* 2\t; Index = 12 Token = 0\n\t\tDW\t176\t* 2\t; Index = 12 Token = 1\n\t\tDW\t176\t* 2\t; Index = 12 Token = 2\n\t\tDW\t176\t* 2\t; Index = 12 Token = 3\n\t\tDW\t224\t* 2\t; Index = 12 Token = 4\n\t\tDW\t256\t* 2\t; Index = 12 Token = 5\n\t\tDW\t288\t* 2\t; Index = 12 Token = 6\n\t\tDW\t320\t* 2\t; Index = 12 Token = 7\n\t\tDW\t176\t* 2\t; Index = 12 Token = 8\n\t\tDW\t176\t* 2\t; Index = 12 Token = 9\n\t\tDW\t176\t* 2\t; Index = 12 Token = 10\n\t\tDW\t176\t* 2\t; Index = 12 Token = 11\n\t\tDW\t224\t* 2\t; Index = 12 Token = 12\n\t\tDW\t256\t* 2\t; Index = 12 Token = 13\n\t\tDW\t288\t* 2\t; Index = 12 Token = 14\n\t\tDW\t320\t* 2\t; Index = 12 Token = 15\n\t\tDW\t192\t* 2\t; Index = 13 Token = 0\n\t\tDW\t192\t* 2\t; Index = 13 Token = 1\n\t\tDW\t192\t* 2\t; Index = 13 Token = 2\n\t\tDW\t192\t* 2\t; Index = 13 Token = 3\n\t\tDW\t240\t* 2\t; Index = 13 Token = 4\n\t\tDW\t272\t* 2\t; Index = 13 Token = 5\n\t\tDW\t304\t* 2\t; Index = 13 Token = 6\n\t\tDW\t336\t* 2\t; Index = 13 Token = 7\n\t\tDW\t192\t* 2\t; Index = 13 Token = 8\n\t\tDW\t192\t* 2\t; Index = 13 Token = 9\n\t\tDW\t192\t* 2\t; Index = 13 Token = 10\n\t\tDW\t192\t* 2\t; Index = 13 Token = 11\n\t\tDW\t240\t* 2\t; Index = 13 Token = 12\n\t\tDW\t272\t* 2\t; Index = 13 Token = 13\n\t\tDW\t304\t* 2\t; Index = 13 Token = 14\n\t\tDW\t336\t* 2\t; Index = 13 Token = 15\n\t\tDW\t208\t* 2\t; Index = 14 Token = 0\n\t\tDW\t208\t* 2\t; Index = 14 Token = 1\n\t\tDW\t208\t* 2\t; Index = 14 Token = 2\n\t\tDW\t208\t* 2\t; Index = 14 Token = 3\n\t\tDW\t256\t* 2\t; Index = 14 Token = 4\n\t\tDW\t288\t* 2\t; Index = 14 Token = 5\n\t\tDW\t320\t* 2\t; Index = 14 Token = 6\n\t\tDW\t352\t* 2\t; Index = 14 Token = 7\n\t\tDW\t208\t* 2\t; Index = 14 Token = 8\n\t\tDW\t208\t* 2\t; Index = 14 Token = 9\n\t\tDW\t208\t* 2\t; Index = 14 Token = 10\n\t\tDW\t208\t* 2\t; Index = 14 Token = 11\n\t\tDW\t256\t* 2\t; Index = 14 Token = 12\n\t\tDW\t288\t* 2\t; Index = 14 Token = 13\n\t\tDW\t320\t* 2\t; Index = 14 Token = 14\n\t\tDW\t352\t* 2\t; Index = 14 Token = 15\n\t\tDW\t224\t* 2\t; Index = 15 Token = 0\n\t\tDW\t224\t* 2\t; Index = 15 Token = 1\n\t\tDW\t224\t* 2\t; Index = 15 Token = 2\n\t\tDW\t224\t* 2\t; Index = 15 Token = 3\n\t\tDW\t272\t* 2\t; Index = 15 Token = 4\n\t\tDW\t304\t* 2\t; Index = 15 Token = 5\n\t\tDW\t336\t* 2\t; Index = 15 Token = 6\n\t\tDW\t368\t* 2\t; Index = 15 Token = 7\n\t\tDW\t224\t* 2\t; Index = 15 Token = 8\n\t\tDW\t224\t* 2\t; Index = 15 Token = 9\n\t\tDW\t224\t* 2\t; Index = 15 Token = 10\n\t\tDW\t224\t* 2\t; Index = 15 Token = 11\n\t\tDW\t272\t* 2\t; Index = 15 Token = 12\n\t\tDW\t304\t* 2\t; Index = 15 Token = 13\n\t\tDW\t336\t* 2\t; Index = 15 Token = 14\n\t\tDW\t368\t* 2\t; Index = 15 Token = 15\n\t\tDW\t240\t* 2\t; Index = 16 Token = 0\n\t\tDW\t240\t* 2\t; Index = 16 Token = 1\n\t\tDW\t240\t* 2\t; Index = 16 Token = 2\n\t\tDW\t240\t* 2\t; Index = 16 Token = 3\n\t\tDW\t288\t* 2\t; Index = 16 Token = 4\n\t\tDW\t320\t* 2\t; Index = 16 Token = 5\n\t\tDW\t352\t* 2\t; Index = 16 Token = 6\n\t\tDW\t384\t* 2\t; Index = 16 Token = 7\n\t\tDW\t240\t* 2\t; Index = 16 Token = 8\n\t\tDW\t240\t* 2\t; Index = 16 Token = 9\n\t\tDW\t240\t* 2\t; Index = 16 Token = 10\n\t\tDW\t240\t* 2\t; Index = 16 Token = 11\n\t\tDW\t288\t* 2\t; Index = 16 Token = 12\n\t\tDW\t320\t* 2\t; Index = 16 Token = 13\n\t\tDW\t352\t* 2\t; Index = 16 Token = 14\n\t\tDW\t384\t* 2\t; Index = 16 Token = 15\n\t\tDW\t256\t* 2\t; Index = 17 Token = 0\n\t\tDW\t256\t* 2\t; Index = 17 Token = 1\n\t\tDW\t256\t* 2\t; Index = 17 Token = 2\n\t\tDW\t256\t* 2\t; Index = 17 Token = 3\n\t\tDW\t304\t* 2\t; Index = 17 Token = 4\n\t\tDW\t336\t* 2\t; Index = 17 Token = 5\n\t\tDW\t368\t* 2\t; Index = 17 Token = 6\n\t\tDW\t400\t* 2\t; Index = 17 Token = 7\n\t\tDW\t256\t* 2\t; Index = 17 Token = 8\n\t\tDW\t256\t* 2\t; Index = 17 Token = 9\n\t\tDW\t256\t* 2\t; Index = 17 Token = 10\n\t\tDW\t256\t* 2\t; Index = 17 Token = 11\n\t\tDW\t304\t* 2\t; Index = 17 Token = 12\n\t\tDW\t336\t* 2\t; Index = 17 Token = 13\n\t\tDW\t368\t* 2\t; Index = 17 Token = 14\n\t\tDW\t400\t* 2\t; Index = 17 Token = 15\n\t\tDW\t272\t* 2\t; Index = 18 Token = 0\n\t\tDW\t272\t* 2\t; Index = 18 Token = 1\n\t\tDW\t272\t* 2\t; Index = 18 Token = 2\n\t\tDW\t272\t* 2\t; Index = 18 Token = 3\n\t\tDW\t320\t* 2\t; Index = 18 Token = 4\n\t\tDW\t352\t* 2\t; Index = 18 Token = 5\n\t\tDW\t384\t* 2\t; Index = 18 Token = 6\n\t\tDW\t416\t* 2\t; Index = 18 Token = 7\n\t\tDW\t272\t* 2\t; Index = 18 Token = 8\n\t\tDW\t272\t* 2\t; Index = 18 Token = 9\n\t\tDW\t272\t* 2\t; Index = 18 Token = 10\n\t\tDW\t272\t* 2\t; Index = 18 Token = 11\n\t\tDW\t320\t* 2\t; Index = 18 Token = 12\n\t\tDW\t352\t* 2\t; Index = 18 Token = 13\n\t\tDW\t384\t* 2\t; Index = 18 Token = 14\n\t\tDW\t416\t* 2\t; Index = 18 Token = 15\n\t\tDW\t288\t* 2\t; Index = 19 Token = 0\n\t\tDW\t288\t* 2\t; Index = 19 Token = 1\n\t\tDW\t288\t* 2\t; Index = 19 Token = 2\n\t\tDW\t288\t* 2\t; Index = 19 Token = 3\n\t\tDW\t336\t* 2\t; Index = 19 Token = 4\n\t\tDW\t368\t* 2\t; Index = 19 Token = 5\n\t\tDW\t400\t* 2\t; Index = 19 Token = 6\n\t\tDW\t432\t* 2\t; Index = 19 Token = 7\n\t\tDW\t288\t* 2\t; Index = 19 Token = 8\n\t\tDW\t288\t* 2\t; Index = 19 Token = 9\n\t\tDW\t288\t* 2\t; Index = 19 Token = 10\n\t\tDW\t288\t* 2\t; Index = 19 Token = 11\n\t\tDW\t336\t* 2\t; Index = 19 Token = 12\n\t\tDW\t368\t* 2\t; Index = 19 Token = 13\n\t\tDW\t400\t* 2\t; Index = 19 Token = 14\n\t\tDW\t432\t* 2\t; Index = 19 Token = 15\n\t\tDW\t304\t* 2\t; Index = 20 Token = 0\n\t\tDW\t304\t* 2\t; Index = 20 Token = 1\n\t\tDW\t304\t* 2\t; Index = 20 Token = 2\n\t\tDW\t304\t* 2\t; Index = 20 Token = 3\n\t\tDW\t352\t* 2\t; Index = 20 Token = 4\n\t\tDW\t384\t* 2\t; Index = 20 Token = 5\n\t\tDW\t416\t* 2\t; Index = 20 Token = 6\n\t\tDW\t448\t* 2\t; Index = 20 Token = 7\n\t\tDW\t304\t* 2\t; Index = 20 Token = 8\n\t\tDW\t304\t* 2\t; Index = 20 Token = 9\n\t\tDW\t304\t* 2\t; Index = 20 Token = 10\n\t\tDW\t304\t* 2\t; Index = 20 Token = 11\n\t\tDW\t352\t* 2\t; Index = 20 Token = 12\n\t\tDW\t384\t* 2\t; Index = 20 Token = 13\n\t\tDW\t416\t* 2\t; Index = 20 Token = 14\n\t\tDW\t448\t* 2\t; Index = 20 Token = 15\n\t\tDW\t320\t* 2\t; Index = 21 Token = 0\n\t\tDW\t320\t* 2\t; Index = 21 Token = 1\n\t\tDW\t320\t* 2\t; Index = 21 Token = 2\n\t\tDW\t320\t* 2\t; Index = 21 Token = 3\n\t\tDW\t368\t* 2\t; Index = 21 Token = 4\n\t\tDW\t400\t* 2\t; Index = 21 Token = 5\n\t\tDW\t432\t* 2\t; Index = 21 Token = 6\n\t\tDW\t464\t* 2\t; Index = 21 Token = 7\n\t\tDW\t320\t* 2\t; Index = 21 Token = 8\n\t\tDW\t320\t* 2\t; Index = 21 Token = 9\n\t\tDW\t320\t* 2\t; Index = 21 Token = 10\n\t\tDW\t320\t* 2\t; Index = 21 Token = 11\n\t\tDW\t368\t* 2\t; Index = 21 Token = 12\n\t\tDW\t400\t* 2\t; Index = 21 Token = 13\n\t\tDW\t432\t* 2\t; Index = 21 Token = 14\n\t\tDW\t464\t* 2\t; Index = 21 Token = 15\n\t\tDW\t336\t* 2\t; Index = 22 Token = 0\n\t\tDW\t336\t* 2\t; Index = 22 Token = 1\n\t\tDW\t336\t* 2\t; Index = 22 Token = 2\n\t\tDW\t336\t* 2\t; Index = 22 Token = 3\n\t\tDW\t384\t* 2\t; Index = 22 Token = 4\n\t\tDW\t416\t* 2\t; Index = 22 Token = 5\n\t\tDW\t448\t* 2\t; Index = 22 Token = 6\n\t\tDW\t480\t* 2\t; Index = 22 Token = 7\n\t\tDW\t336\t* 2\t; Index = 22 Token = 8\n\t\tDW\t336\t* 2\t; Index = 22 Token = 9\n\t\tDW\t336\t* 2\t; Index = 22 Token = 10\n\t\tDW\t336\t* 2\t; Index = 22 Token = 11\n\t\tDW\t384\t* 2\t; Index = 22 Token = 12\n\t\tDW\t416\t* 2\t; Index = 22 Token = 13\n\t\tDW\t448\t* 2\t; Index = 22 Token = 14\n\t\tDW\t480\t* 2\t; Index = 22 Token = 15\n\t\tDW\t352\t* 2\t; Index = 23 Token = 0\n\t\tDW\t352\t* 2\t; Index = 23 Token = 1\n\t\tDW\t352\t* 2\t; Index = 23 Token = 2\n\t\tDW\t352\t* 2\t; Index = 23 Token = 3\n\t\tDW\t400\t* 2\t; Index = 23 Token = 4\n\t\tDW\t432\t* 2\t; Index = 23 Token = 5\n\t\tDW\t464\t* 2\t; Index = 23 Token = 6\n\t\tDW\t496\t* 2\t; Index = 23 Token = 7\n\t\tDW\t352\t* 2\t; Index = 23 Token = 8\n\t\tDW\t352\t* 2\t; Index = 23 Token = 9\n\t\tDW\t352\t* 2\t; Index = 23 Token = 10\n\t\tDW\t352\t* 2\t; Index = 23 Token = 11\n\t\tDW\t400\t* 2\t; Index = 23 Token = 12\n\t\tDW\t432\t* 2\t; Index = 23 Token = 13\n\t\tDW\t464\t* 2\t; Index = 23 Token = 14\n\t\tDW\t496\t* 2\t; Index = 23 Token = 15\n\t\tDW\t368\t* 2\t; Index = 24 Token = 0\n\t\tDW\t368\t* 2\t; Index = 24 Token = 1\n\t\tDW\t368\t* 2\t; Index = 24 Token = 2\n\t\tDW\t368\t* 2\t; Index = 24 Token = 3\n\t\tDW\t416\t* 2\t; Index = 24 Token = 4\n\t\tDW\t448\t* 2\t; Index = 24 Token = 5\n\t\tDW\t480\t* 2\t; Index = 24 Token = 6\n\t\tDW\t512\t* 2\t; Index = 24 Token = 7\n\t\tDW\t368\t* 2\t; Index = 24 Token = 8\n\t\tDW\t368\t* 2\t; Index = 24 Token = 9\n\t\tDW\t368\t* 2\t; Index = 24 Token = 10\n\t\tDW\t368\t* 2\t; Index = 24 Token = 11\n\t\tDW\t416\t* 2\t; Index = 24 Token = 12\n\t\tDW\t448\t* 2\t; Index = 24 Token = 13\n\t\tDW\t480\t* 2\t; Index = 24 Token = 14\n\t\tDW\t512\t* 2\t; Index = 24 Token = 15\n\t\tDW\t384\t* 2\t; Index = 25 Token = 0\n\t\tDW\t384\t* 2\t; Index = 25 Token = 1\n\t\tDW\t384\t* 2\t; Index = 25 Token = 2\n\t\tDW\t384\t* 2\t; Index = 25 Token = 3\n\t\tDW\t432\t* 2\t; Index = 25 Token = 4\n\t\tDW\t464\t* 2\t; Index = 25 Token = 5\n\t\tDW\t496\t* 2\t; Index = 25 Token = 6\n\t\tDW\t528\t* 2\t; Index = 25 Token = 7\n\t\tDW\t384\t* 2\t; Index = 25 Token = 8\n\t\tDW\t384\t* 2\t; Index = 25 Token = 9\n\t\tDW\t384\t* 2\t; Index = 25 Token = 10\n\t\tDW\t384\t* 2\t; Index = 25 Token = 11\n\t\tDW\t432\t* 2\t; Index = 25 Token = 12\n\t\tDW\t464\t* 2\t; Index = 25 Token = 13\n\t\tDW\t496\t* 2\t; Index = 25 Token = 14\n\t\tDW\t528\t* 2\t; Index = 25 Token = 15\n\t\tDW\t400\t* 2\t; Index = 26 Token = 0\n\t\tDW\t400\t* 2\t; Index = 26 Token = 1\n\t\tDW\t400\t* 2\t; Index = 26 Token = 2\n\t\tDW\t400\t* 2\t; Index = 26 Token = 3\n\t\tDW\t448\t* 2\t; Index = 26 Token = 4\n\t\tDW\t480\t* 2\t; Index = 26 Token = 5\n\t\tDW\t512\t* 2\t; Index = 26 Token = 6\n\t\tDW\t544\t* 2\t; Index = 26 Token = 7\n\t\tDW\t400\t* 2\t; Index = 26 Token = 8\n\t\tDW\t400\t* 2\t; Index = 26 Token = 9\n\t\tDW\t400\t* 2\t; Index = 26 Token = 10\n\t\tDW\t400\t* 2\t; Index = 26 Token = 11\n\t\tDW\t448\t* 2\t; Index = 26 Token = 12\n\t\tDW\t480\t* 2\t; Index = 26 Token = 13\n\t\tDW\t512\t* 2\t; Index = 26 Token = 14\n\t\tDW\t544\t* 2\t; Index = 26 Token = 15\n\t\tDW\t416\t* 2\t; Index = 27 Token = 0\n\t\tDW\t416\t* 2\t; Index = 27 Token = 1\n\t\tDW\t416\t* 2\t; Index = 27 Token = 2\n\t\tDW\t416\t* 2\t; Index = 27 Token = 3\n\t\tDW\t464\t* 2\t; Index = 27 Token = 4\n\t\tDW\t496\t* 2\t; Index = 27 Token = 5\n\t\tDW\t528\t* 2\t; Index = 27 Token = 6\n\t\tDW\t560\t* 2\t; Index = 27 Token = 7\n\t\tDW\t416\t* 2\t; Index = 27 Token = 8\n\t\tDW\t416\t* 2\t; Index = 27 Token = 9\n\t\tDW\t416\t* 2\t; Index = 27 Token = 10\n\t\tDW\t416\t* 2\t; Index = 27 Token = 11\n\t\tDW\t464\t* 2\t; Index = 27 Token = 12\n\t\tDW\t496\t* 2\t; Index = 27 Token = 13\n\t\tDW\t528\t* 2\t; Index = 27 Token = 14\n\t\tDW\t560\t* 2\t; Index = 27 Token = 15\n\t\tDW\t432\t* 2\t; Index = 28 Token = 0\n\t\tDW\t432\t* 2\t; Index = 28 Token = 1\n\t\tDW\t432\t* 2\t; Index = 28 Token = 2\n\t\tDW\t432\t* 2\t; Index = 28 Token = 3\n\t\tDW\t480\t* 2\t; Index = 28 Token = 4\n\t\tDW\t512\t* 2\t; Index = 28 Token = 5\n\t\tDW\t544\t* 2\t; Index = 28 Token = 6\n\t\tDW\t576\t* 2\t; Index = 28 Token = 7\n\t\tDW\t432\t* 2\t; Index = 28 Token = 8\n\t\tDW\t432\t* 2\t; Index = 28 Token = 9\n\t\tDW\t432\t* 2\t; Index = 28 Token = 10\n\t\tDW\t432\t* 2\t; Index = 28 Token = 11\n\t\tDW\t480\t* 2\t; Index = 28 Token = 12\n\t\tDW\t512\t* 2\t; Index = 28 Token = 13\n\t\tDW\t544\t* 2\t; Index = 28 Token = 14\n\t\tDW\t576\t* 2\t; Index = 28 Token = 15\n\t\tDW\t448\t* 2\t; Index = 29 Token = 0\n\t\tDW\t448\t* 2\t; Index = 29 Token = 1\n\t\tDW\t448\t* 2\t; Index = 29 Token = 2\n\t\tDW\t448\t* 2\t; Index = 29 Token = 3\n\t\tDW\t496\t* 2\t; Index = 29 Token = 4\n\t\tDW\t528\t* 2\t; Index = 29 Token = 5\n\t\tDW\t560\t* 2\t; Index = 29 Token = 6\n\t\tDW\t592\t* 2\t; Index = 29 Token = 7\n\t\tDW\t448\t* 2\t; Index = 29 Token = 8\n\t\tDW\t448\t* 2\t; Index = 29 Token = 9\n\t\tDW\t448\t* 2\t; Index = 29 Token = 10\n\t\tDW\t448\t* 2\t; Index = 29 Token = 11\n\t\tDW\t496\t* 2\t; Index = 29 Token = 12\n\t\tDW\t528\t* 2\t; Index = 29 Token = 13\n\t\tDW\t560\t* 2\t; Index = 29 Token = 14\n\t\tDW\t592\t* 2\t; Index = 29 Token = 15\n\t\tDW\t464\t* 2\t; Index = 30 Token = 0\n\t\tDW\t464\t* 2\t; Index = 30 Token = 1\n\t\tDW\t464\t* 2\t; Index = 30 Token = 2\n\t\tDW\t464\t* 2\t; Index = 30 Token = 3\n\t\tDW\t512\t* 2\t; Index = 30 Token = 4\n\t\tDW\t544\t* 2\t; Index = 30 Token = 5\n\t\tDW\t576\t* 2\t; Index = 30 Token = 6\n\t\tDW\t608\t* 2\t; Index = 30 Token = 7\n\t\tDW\t464\t* 2\t; Index = 30 Token = 8\n\t\tDW\t464\t* 2\t; Index = 30 Token = 9\n\t\tDW\t464\t* 2\t; Index = 30 Token = 10\n\t\tDW\t464\t* 2\t; Index = 30 Token = 11\n\t\tDW\t512\t* 2\t; Index = 30 Token = 12\n\t\tDW\t544\t* 2\t; Index = 30 Token = 13\n\t\tDW\t576\t* 2\t; Index = 30 Token = 14\n\t\tDW\t608\t* 2\t; Index = 30 Token = 15\n\t\tDW\t480\t* 2\t; Index = 31 Token = 0\n\t\tDW\t480\t* 2\t; Index = 31 Token = 1\n\t\tDW\t480\t* 2\t; Index = 31 Token = 2\n\t\tDW\t480\t* 2\t; Index = 31 Token = 3\n\t\tDW\t528\t* 2\t; Index = 31 Token = 4\n\t\tDW\t560\t* 2\t; Index = 31 Token = 5\n\t\tDW\t592\t* 2\t; Index = 31 Token = 6\n\t\tDW\t624\t* 2\t; Index = 31 Token = 7\n\t\tDW\t480\t* 2\t; Index = 31 Token = 8\n\t\tDW\t480\t* 2\t; Index = 31 Token = 9\n\t\tDW\t480\t* 2\t; Index = 31 Token = 10\n\t\tDW\t480\t* 2\t; Index = 31 Token = 11\n\t\tDW\t528\t* 2\t; Index = 31 Token = 12\n\t\tDW\t560\t* 2\t; Index = 31 Token = 13\n\t\tDW\t592\t* 2\t; Index = 31 Token = 14\n\t\tDW\t624\t* 2\t; Index = 31 Token = 15\n\t\tDW\t496\t* 2\t; Index = 32 Token = 0\n\t\tDW\t496\t* 2\t; Index = 32 Token = 1\n\t\tDW\t496\t* 2\t; Index = 32 Token = 2\n\t\tDW\t496\t* 2\t; Index = 32 Token = 3\n\t\tDW\t544\t* 2\t; Index = 32 Token = 4\n\t\tDW\t576\t* 2\t; Index = 32 Token = 5\n\t\tDW\t608\t* 2\t; Index = 32 Token = 6\n\t\tDW\t640\t* 2\t; Index = 32 Token = 7\n\t\tDW\t496\t* 2\t; Index = 32 Token = 8\n\t\tDW\t496\t* 2\t; Index = 32 Token = 9\n\t\tDW\t496\t* 2\t; Index = 32 Token = 10\n\t\tDW\t496\t* 2\t; Index = 32 Token = 11\n\t\tDW\t544\t* 2\t; Index = 32 Token = 12\n\t\tDW\t576\t* 2\t; Index = 32 Token = 13\n\t\tDW\t608\t* 2\t; Index = 32 Token = 14\n\t\tDW\t640\t* 2\t; Index = 32 Token = 15\n\t\tDW\t512\t* 2\t; Index = 33 Token = 0\n\t\tDW\t512\t* 2\t; Index = 33 Token = 1\n\t\tDW\t512\t* 2\t; Index = 33 Token = 2\n\t\tDW\t512\t* 2\t; Index = 33 Token = 3\n\t\tDW\t560\t* 2\t; Index = 33 Token = 4\n\t\tDW\t592\t* 2\t; Index = 33 Token = 5\n\t\tDW\t624\t* 2\t; Index = 33 Token = 6\n\t\tDW\t656\t* 2\t; Index = 33 Token = 7\n\t\tDW\t512\t* 2\t; Index = 33 Token = 8\n\t\tDW\t512\t* 2\t; Index = 33 Token = 9\n\t\tDW\t512\t* 2\t; Index = 33 Token = 10\n\t\tDW\t512\t* 2\t; Index = 33 Token = 11\n\t\tDW\t560\t* 2\t; Index = 33 Token = 12\n\t\tDW\t592\t* 2\t; Index = 33 Token = 13\n\t\tDW\t624\t* 2\t; Index = 33 Token = 14\n\t\tDW\t656\t* 2\t; Index = 33 Token = 15\n\t\tDW\t528\t* 2\t; Index = 34 Token = 0\n\t\tDW\t528\t* 2\t; Index = 34 Token = 1\n\t\tDW\t528\t* 2\t; Index = 34 Token = 2\n\t\tDW\t528\t* 2\t; Index = 34 Token = 3\n\t\tDW\t576\t* 2\t; Index = 34 Token = 4\n\t\tDW\t608\t* 2\t; Index = 34 Token = 5\n\t\tDW\t640\t* 2\t; Index = 34 Token = 6\n\t\tDW\t672\t* 2\t; Index = 34 Token = 7\n\t\tDW\t528\t* 2\t; Index = 34 Token = 8\n\t\tDW\t528\t* 2\t; Index = 34 Token = 9\n\t\tDW\t528\t* 2\t; Index = 34 Token = 10\n\t\tDW\t528\t* 2\t; Index = 34 Token = 11\n\t\tDW\t576\t* 2\t; Index = 34 Token = 12\n\t\tDW\t608\t* 2\t; Index = 34 Token = 13\n\t\tDW\t640\t* 2\t; Index = 34 Token = 14\n\t\tDW\t672\t* 2\t; Index = 34 Token = 15\n\t\tDW\t544\t* 2\t; Index = 35 Token = 0\n\t\tDW\t544\t* 2\t; Index = 35 Token = 1\n\t\tDW\t544\t* 2\t; Index = 35 Token = 2\n\t\tDW\t544\t* 2\t; Index = 35 Token = 3\n\t\tDW\t592\t* 2\t; Index = 35 Token = 4\n\t\tDW\t624\t* 2\t; Index = 35 Token = 5\n\t\tDW\t656\t* 2\t; Index = 35 Token = 6\n\t\tDW\t688\t* 2\t; Index = 35 Token = 7\n\t\tDW\t544\t* 2\t; Index = 35 Token = 8\n\t\tDW\t544\t* 2\t; Index = 35 Token = 9\n\t\tDW\t544\t* 2\t; Index = 35 Token = 10\n\t\tDW\t544\t* 2\t; Index = 35 Token = 11\n\t\tDW\t592\t* 2\t; Index = 35 Token = 12\n\t\tDW\t624\t* 2\t; Index = 35 Token = 13\n\t\tDW\t656\t* 2\t; Index = 35 Token = 14\n\t\tDW\t688\t* 2\t; Index = 35 Token = 15\n\t\tDW\t560\t* 2\t; Index = 36 Token = 0\n\t\tDW\t560\t* 2\t; Index = 36 Token = 1\n\t\tDW\t560\t* 2\t; Index = 36 Token = 2\n\t\tDW\t560\t* 2\t; Index = 36 Token = 3\n\t\tDW\t608\t* 2\t; Index = 36 Token = 4\n\t\tDW\t640\t* 2\t; Index = 36 Token = 5\n\t\tDW\t672\t* 2\t; Index = 36 Token = 6\n\t\tDW\t704\t* 2\t; Index = 36 Token = 7\n\t\tDW\t560\t* 2\t; Index = 36 Token = 8\n\t\tDW\t560\t* 2\t; Index = 36 Token = 9\n\t\tDW\t560\t* 2\t; Index = 36 Token = 10\n\t\tDW\t560\t* 2\t; Index = 36 Token = 11\n\t\tDW\t608\t* 2\t; Index = 36 Token = 12\n\t\tDW\t640\t* 2\t; Index = 36 Token = 13\n\t\tDW\t672\t* 2\t; Index = 36 Token = 14\n\t\tDW\t704\t* 2\t; Index = 36 Token = 15\n\t\tDW\t576\t* 2\t; Index = 37 Token = 0\n\t\tDW\t576\t* 2\t; Index = 37 Token = 1\n\t\tDW\t576\t* 2\t; Index = 37 Token = 2\n\t\tDW\t576\t* 2\t; Index = 37 Token = 3\n\t\tDW\t624\t* 2\t; Index = 37 Token = 4\n\t\tDW\t656\t* 2\t; Index = 37 Token = 5\n\t\tDW\t688\t* 2\t; Index = 37 Token = 6\n\t\tDW\t720\t* 2\t; Index = 37 Token = 7\n\t\tDW\t576\t* 2\t; Index = 37 Token = 8\n\t\tDW\t576\t* 2\t; Index = 37 Token = 9\n\t\tDW\t576\t* 2\t; Index = 37 Token = 10\n\t\tDW\t576\t* 2\t; Index = 37 Token = 11\n\t\tDW\t624\t* 2\t; Index = 37 Token = 12\n\t\tDW\t656\t* 2\t; Index = 37 Token = 13\n\t\tDW\t688\t* 2\t; Index = 37 Token = 14\n\t\tDW\t720\t* 2\t; Index = 37 Token = 15\n\t\tDW\t592\t* 2\t; Index = 38 Token = 0\n\t\tDW\t592\t* 2\t; Index = 38 Token = 1\n\t\tDW\t592\t* 2\t; Index = 38 Token = 2\n\t\tDW\t592\t* 2\t; Index = 38 Token = 3\n\t\tDW\t640\t* 2\t; Index = 38 Token = 4\n\t\tDW\t672\t* 2\t; Index = 38 Token = 5\n\t\tDW\t704\t* 2\t; Index = 38 Token = 6\n\t\tDW\t736\t* 2\t; Index = 38 Token = 7\n\t\tDW\t592\t* 2\t; Index = 38 Token = 8\n\t\tDW\t592\t* 2\t; Index = 38 Token = 9\n\t\tDW\t592\t* 2\t; Index = 38 Token = 10\n\t\tDW\t592\t* 2\t; Index = 38 Token = 11\n\t\tDW\t640\t* 2\t; Index = 38 Token = 12\n\t\tDW\t672\t* 2\t; Index = 38 Token = 13\n\t\tDW\t704\t* 2\t; Index = 38 Token = 14\n\t\tDW\t736\t* 2\t; Index = 38 Token = 15\n\t\tDW\t608\t* 2\t; Index = 39 Token = 0\n\t\tDW\t608\t* 2\t; Index = 39 Token = 1\n\t\tDW\t608\t* 2\t; Index = 39 Token = 2\n\t\tDW\t608\t* 2\t; Index = 39 Token = 3\n\t\tDW\t656\t* 2\t; Index = 39 Token = 4\n\t\tDW\t688\t* 2\t; Index = 39 Token = 5\n\t\tDW\t720\t* 2\t; Index = 39 Token = 6\n\t\tDW\t752\t* 2\t; Index = 39 Token = 7\n\t\tDW\t608\t* 2\t; Index = 39 Token = 8\n\t\tDW\t608\t* 2\t; Index = 39 Token = 9\n\t\tDW\t608\t* 2\t; Index = 39 Token = 10\n\t\tDW\t608\t* 2\t; Index = 39 Token = 11\n\t\tDW\t656\t* 2\t; Index = 39 Token = 12\n\t\tDW\t688\t* 2\t; Index = 39 Token = 13\n\t\tDW\t720\t* 2\t; Index = 39 Token = 14\n\t\tDW\t752\t* 2\t; Index = 39 Token = 15\n\t\tDW\t624\t* 2\t; Index = 40 Token = 0\n\t\tDW\t624\t* 2\t; Index = 40 Token = 1\n\t\tDW\t624\t* 2\t; Index = 40 Token = 2\n\t\tDW\t624\t* 2\t; Index = 40 Token = 3\n\t\tDW\t672\t* 2\t; Index = 40 Token = 4\n\t\tDW\t704\t* 2\t; Index = 40 Token = 5\n\t\tDW\t736\t* 2\t; Index = 40 Token = 6\n\t\tDW\t768\t* 2\t; Index = 40 Token = 7\n\t\tDW\t624\t* 2\t; Index = 40 Token = 8\n\t\tDW\t624\t* 2\t; Index = 40 Token = 9\n\t\tDW\t624\t* 2\t; Index = 40 Token = 10\n\t\tDW\t624\t* 2\t; Index = 40 Token = 11\n\t\tDW\t672\t* 2\t; Index = 40 Token = 12\n\t\tDW\t704\t* 2\t; Index = 40 Token = 13\n\t\tDW\t736\t* 2\t; Index = 40 Token = 14\n\t\tDW\t768\t* 2\t; Index = 40 Token = 15\n\t\tDW\t640\t* 2\t; Index = 41 Token = 0\n\t\tDW\t640\t* 2\t; Index = 41 Token = 1\n\t\tDW\t640\t* 2\t; Index = 41 Token = 2\n\t\tDW\t640\t* 2\t; Index = 41 Token = 3\n\t\tDW\t688\t* 2\t; Index = 41 Token = 4\n\t\tDW\t720\t* 2\t; Index = 41 Token = 5\n\t\tDW\t752\t* 2\t; Index = 41 Token = 6\n\t\tDW\t784\t* 2\t; Index = 41 Token = 7\n\t\tDW\t640\t* 2\t; Index = 41 Token = 8\n\t\tDW\t640\t* 2\t; Index = 41 Token = 9\n\t\tDW\t640\t* 2\t; Index = 41 Token = 10\n\t\tDW\t640\t* 2\t; Index = 41 Token = 11\n\t\tDW\t688\t* 2\t; Index = 41 Token = 12\n\t\tDW\t720\t* 2\t; Index = 41 Token = 13\n\t\tDW\t752\t* 2\t; Index = 41 Token = 14\n\t\tDW\t784\t* 2\t; Index = 41 Token = 15\n\t\tDW\t656\t* 2\t; Index = 42 Token = 0\n\t\tDW\t656\t* 2\t; Index = 42 Token = 1\n\t\tDW\t656\t* 2\t; Index = 42 Token = 2\n\t\tDW\t656\t* 2\t; Index = 42 Token = 3\n\t\tDW\t704\t* 2\t; Index = 42 Token = 4\n\t\tDW\t736\t* 2\t; Index = 42 Token = 5\n\t\tDW\t768\t* 2\t; Index = 42 Token = 6\n\t\tDW\t800\t* 2\t; Index = 42 Token = 7\n\t\tDW\t656\t* 2\t; Index = 42 Token = 8\n\t\tDW\t656\t* 2\t; Index = 42 Token = 9\n\t\tDW\t656\t* 2\t; Index = 42 Token = 10\n\t\tDW\t656\t* 2\t; Index = 42 Token = 11\n\t\tDW\t704\t* 2\t; Index = 42 Token = 12\n\t\tDW\t736\t* 2\t; Index = 42 Token = 13\n\t\tDW\t768\t* 2\t; Index = 42 Token = 14\n\t\tDW\t800\t* 2\t; Index = 42 Token = 15\n\t\tDW\t672\t* 2\t; Index = 43 Token = 0\n\t\tDW\t672\t* 2\t; Index = 43 Token = 1\n\t\tDW\t672\t* 2\t; Index = 43 Token = 2\n\t\tDW\t672\t* 2\t; Index = 43 Token = 3\n\t\tDW\t720\t* 2\t; Index = 43 Token = 4\n\t\tDW\t752\t* 2\t; Index = 43 Token = 5\n\t\tDW\t784\t* 2\t; Index = 43 Token = 6\n\t\tDW\t816\t* 2\t; Index = 43 Token = 7\n\t\tDW\t672\t* 2\t; Index = 43 Token = 8\n\t\tDW\t672\t* 2\t; Index = 43 Token = 9\n\t\tDW\t672\t* 2\t; Index = 43 Token = 10\n\t\tDW\t672\t* 2\t; Index = 43 Token = 11\n\t\tDW\t720\t* 2\t; Index = 43 Token = 12\n\t\tDW\t752\t* 2\t; Index = 43 Token = 13\n\t\tDW\t784\t* 2\t; Index = 43 Token = 14\n\t\tDW\t816\t* 2\t; Index = 43 Token = 15\n\t\tDW\t688\t* 2\t; Index = 44 Token = 0\n\t\tDW\t688\t* 2\t; Index = 44 Token = 1\n\t\tDW\t688\t* 2\t; Index = 44 Token = 2\n\t\tDW\t688\t* 2\t; Index = 44 Token = 3\n\t\tDW\t736\t* 2\t; Index = 44 Token = 4\n\t\tDW\t768\t* 2\t; Index = 44 Token = 5\n\t\tDW\t800\t* 2\t; Index = 44 Token = 6\n\t\tDW\t832\t* 2\t; Index = 44 Token = 7\n\t\tDW\t688\t* 2\t; Index = 44 Token = 8\n\t\tDW\t688\t* 2\t; Index = 44 Token = 9\n\t\tDW\t688\t* 2\t; Index = 44 Token = 10\n\t\tDW\t688\t* 2\t; Index = 44 Token = 11\n\t\tDW\t736\t* 2\t; Index = 44 Token = 12\n\t\tDW\t768\t* 2\t; Index = 44 Token = 13\n\t\tDW\t800\t* 2\t; Index = 44 Token = 14\n\t\tDW\t832\t* 2\t; Index = 44 Token = 15\n\t\tDW\t704\t* 2\t; Index = 45 Token = 0\n\t\tDW\t704\t* 2\t; Index = 45 Token = 1\n\t\tDW\t704\t* 2\t; Index = 45 Token = 2\n\t\tDW\t704\t* 2\t; Index = 45 Token = 3\n\t\tDW\t752\t* 2\t; Index = 45 Token = 4\n\t\tDW\t784\t* 2\t; Index = 45 Token = 5\n\t\tDW\t816\t* 2\t; Index = 45 Token = 6\n\t\tDW\t848\t* 2\t; Index = 45 Token = 7\n\t\tDW\t704\t* 2\t; Index = 45 Token = 8\n\t\tDW\t704\t* 2\t; Index = 45 Token = 9\n\t\tDW\t704\t* 2\t; Index = 45 Token = 10\n\t\tDW\t704\t* 2\t; Index = 45 Token = 11\n\t\tDW\t752\t* 2\t; Index = 45 Token = 12\n\t\tDW\t784\t* 2\t; Index = 45 Token = 13\n\t\tDW\t816\t* 2\t; Index = 45 Token = 14\n\t\tDW\t848\t* 2\t; Index = 45 Token = 15\n\t\tDW\t720\t* 2\t; Index = 46 Token = 0\n\t\tDW\t720\t* 2\t; Index = 46 Token = 1\n\t\tDW\t720\t* 2\t; Index = 46 Token = 2\n\t\tDW\t720\t* 2\t; Index = 46 Token = 3\n\t\tDW\t768\t* 2\t; Index = 46 Token = 4\n\t\tDW\t800\t* 2\t; Index = 46 Token = 5\n\t\tDW\t832\t* 2\t; Index = 46 Token = 6\n\t\tDW\t864\t* 2\t; Index = 46 Token = 7\n\t\tDW\t720\t* 2\t; Index = 46 Token = 8\n\t\tDW\t720\t* 2\t; Index = 46 Token = 9\n\t\tDW\t720\t* 2\t; Index = 46 Token = 10\n\t\tDW\t720\t* 2\t; Index = 46 Token = 11\n\t\tDW\t768\t* 2\t; Index = 46 Token = 12\n\t\tDW\t800\t* 2\t; Index = 46 Token = 13\n\t\tDW\t832\t* 2\t; Index = 46 Token = 14\n\t\tDW\t864\t* 2\t; Index = 46 Token = 15\n\t\tDW\t736\t* 2\t; Index = 47 Token = 0\n\t\tDW\t736\t* 2\t; Index = 47 Token = 1\n\t\tDW\t736\t* 2\t; Index = 47 Token = 2\n\t\tDW\t736\t* 2\t; Index = 47 Token = 3\n\t\tDW\t784\t* 2\t; Index = 47 Token = 4\n\t\tDW\t816\t* 2\t; Index = 47 Token = 5\n\t\tDW\t848\t* 2\t; Index = 47 Token = 6\n\t\tDW\t880\t* 2\t; Index = 47 Token = 7\n\t\tDW\t736\t* 2\t; Index = 47 Token = 8\n\t\tDW\t736\t* 2\t; Index = 47 Token = 9\n\t\tDW\t736\t* 2\t; Index = 47 Token = 10\n\t\tDW\t736\t* 2\t; Index = 47 Token = 11\n\t\tDW\t784\t* 2\t; Index = 47 Token = 12\n\t\tDW\t816\t* 2\t; Index = 47 Token = 13\n\t\tDW\t848\t* 2\t; Index = 47 Token = 14\n\t\tDW\t880\t* 2\t; Index = 47 Token = 15\n\t\tDW\t752\t* 2\t; Index = 48 Token = 0\n\t\tDW\t752\t* 2\t; Index = 48 Token = 1\n\t\tDW\t752\t* 2\t; Index = 48 Token = 2\n\t\tDW\t752\t* 2\t; Index = 48 Token = 3\n\t\tDW\t800\t* 2\t; Index = 48 Token = 4\n\t\tDW\t832\t* 2\t; Index = 48 Token = 5\n\t\tDW\t864\t* 2\t; Index = 48 Token = 6\n\t\tDW\t896\t* 2\t; Index = 48 Token = 7\n\t\tDW\t752\t* 2\t; Index = 48 Token = 8\n\t\tDW\t752\t* 2\t; Index = 48 Token = 9\n\t\tDW\t752\t* 2\t; Index = 48 Token = 10\n\t\tDW\t752\t* 2\t; Index = 48 Token = 11\n\t\tDW\t800\t* 2\t; Index = 48 Token = 12\n\t\tDW\t832\t* 2\t; Index = 48 Token = 13\n\t\tDW\t864\t* 2\t; Index = 48 Token = 14\n\t\tDW\t896\t* 2\t; Index = 48 Token = 15\n\t\tDW\t768\t* 2\t; Index = 49 Token = 0\n\t\tDW\t768\t* 2\t; Index = 49 Token = 1\n\t\tDW\t768\t* 2\t; Index = 49 Token = 2\n\t\tDW\t768\t* 2\t; Index = 49 Token = 3\n\t\tDW\t816\t* 2\t; Index = 49 Token = 4\n\t\tDW\t848\t* 2\t; Index = 49 Token = 5\n\t\tDW\t880\t* 2\t; Index = 49 Token = 6\n\t\tDW\t912\t* 2\t; Index = 49 Token = 7\n\t\tDW\t768\t* 2\t; Index = 49 Token = 8\n\t\tDW\t768\t* 2\t; Index = 49 Token = 9\n\t\tDW\t768\t* 2\t; Index = 49 Token = 10\n\t\tDW\t768\t* 2\t; Index = 49 Token = 11\n\t\tDW\t816\t* 2\t; Index = 49 Token = 12\n\t\tDW\t848\t* 2\t; Index = 49 Token = 13\n\t\tDW\t880\t* 2\t; Index = 49 Token = 14\n\t\tDW\t912\t* 2\t; Index = 49 Token = 15\n\t\tDW\t784\t* 2\t; Index = 50 Token = 0\n\t\tDW\t784\t* 2\t; Index = 50 Token = 1\n\t\tDW\t784\t* 2\t; Index = 50 Token = 2\n\t\tDW\t784\t* 2\t; Index = 50 Token = 3\n\t\tDW\t832\t* 2\t; Index = 50 Token = 4\n\t\tDW\t864\t* 2\t; Index = 50 Token = 5\n\t\tDW\t896\t* 2\t; Index = 50 Token = 6\n\t\tDW\t928\t* 2\t; Index = 50 Token = 7\n\t\tDW\t784\t* 2\t; Index = 50 Token = 8\n\t\tDW\t784\t* 2\t; Index = 50 Token = 9\n\t\tDW\t784\t* 2\t; Index = 50 Token = 10\n\t\tDW\t784\t* 2\t; Index = 50 Token = 11\n\t\tDW\t832\t* 2\t; Index = 50 Token = 12\n\t\tDW\t864\t* 2\t; Index = 50 Token = 13\n\t\tDW\t896\t* 2\t; Index = 50 Token = 14\n\t\tDW\t928\t* 2\t; Index = 50 Token = 15\n\t\tDW\t800\t* 2\t; Index = 51 Token = 0\n\t\tDW\t800\t* 2\t; Index = 51 Token = 1\n\t\tDW\t800\t* 2\t; Index = 51 Token = 2\n\t\tDW\t800\t* 2\t; Index = 51 Token = 3\n\t\tDW\t848\t* 2\t; Index = 51 Token = 4\n\t\tDW\t880\t* 2\t; Index = 51 Token = 5\n\t\tDW\t912\t* 2\t; Index = 51 Token = 6\n\t\tDW\t944\t* 2\t; Index = 51 Token = 7\n\t\tDW\t800\t* 2\t; Index = 51 Token = 8\n\t\tDW\t800\t* 2\t; Index = 51 Token = 9\n\t\tDW\t800\t* 2\t; Index = 51 Token = 10\n\t\tDW\t800\t* 2\t; Index = 51 Token = 11\n\t\tDW\t848\t* 2\t; Index = 51 Token = 12\n\t\tDW\t880\t* 2\t; Index = 51 Token = 13\n\t\tDW\t912\t* 2\t; Index = 51 Token = 14\n\t\tDW\t944\t* 2\t; Index = 51 Token = 15\n\t\tDW\t816\t* 2\t; Index = 52 Token = 0\n\t\tDW\t816\t* 2\t; Index = 52 Token = 1\n\t\tDW\t816\t* 2\t; Index = 52 Token = 2\n\t\tDW\t816\t* 2\t; Index = 52 Token = 3\n\t\tDW\t864\t* 2\t; Index = 52 Token = 4\n\t\tDW\t896\t* 2\t; Index = 52 Token = 5\n\t\tDW\t928\t* 2\t; Index = 52 Token = 6\n\t\tDW\t960\t* 2\t; Index = 52 Token = 7\n\t\tDW\t816\t* 2\t; Index = 52 Token = 8\n\t\tDW\t816\t* 2\t; Index = 52 Token = 9\n\t\tDW\t816\t* 2\t; Index = 52 Token = 10\n\t\tDW\t816\t* 2\t; Index = 52 Token = 11\n\t\tDW\t864\t* 2\t; Index = 52 Token = 12\n\t\tDW\t896\t* 2\t; Index = 52 Token = 13\n\t\tDW\t928\t* 2\t; Index = 52 Token = 14\n\t\tDW\t960\t* 2\t; Index = 52 Token = 15\n\t\tDW\t832\t* 2\t; Index = 53 Token = 0\n\t\tDW\t832\t* 2\t; Index = 53 Token = 1\n\t\tDW\t832\t* 2\t; Index = 53 Token = 2\n\t\tDW\t832\t* 2\t; Index = 53 Token = 3\n\t\tDW\t880\t* 2\t; Index = 53 Token = 4\n\t\tDW\t912\t* 2\t; Index = 53 Token = 5\n\t\tDW\t944\t* 2\t; Index = 53 Token = 6\n\t\tDW\t976\t* 2\t; Index = 53 Token = 7\n\t\tDW\t832\t* 2\t; Index = 53 Token = 8\n\t\tDW\t832\t* 2\t; Index = 53 Token = 9\n\t\tDW\t832\t* 2\t; Index = 53 Token = 10\n\t\tDW\t832\t* 2\t; Index = 53 Token = 11\n\t\tDW\t880\t* 2\t; Index = 53 Token = 12\n\t\tDW\t912\t* 2\t; Index = 53 Token = 13\n\t\tDW\t944\t* 2\t; Index = 53 Token = 14\n\t\tDW\t976\t* 2\t; Index = 53 Token = 15\n\t\tDW\t848\t* 2\t; Index = 54 Token = 0\n\t\tDW\t848\t* 2\t; Index = 54 Token = 1\n\t\tDW\t848\t* 2\t; Index = 54 Token = 2\n\t\tDW\t848\t* 2\t; Index = 54 Token = 3\n\t\tDW\t896\t* 2\t; Index = 54 Token = 4\n\t\tDW\t928\t* 2\t; Index = 54 Token = 5\n\t\tDW\t960\t* 2\t; Index = 54 Token = 6\n\t\tDW\t992\t* 2\t; Index = 54 Token = 7\n\t\tDW\t848\t* 2\t; Index = 54 Token = 8\n\t\tDW\t848\t* 2\t; Index = 54 Token = 9\n\t\tDW\t848\t* 2\t; Index = 54 Token = 10\n\t\tDW\t848\t* 2\t; Index = 54 Token = 11\n\t\tDW\t896\t* 2\t; Index = 54 Token = 12\n\t\tDW\t928\t* 2\t; Index = 54 Token = 13\n\t\tDW\t960\t* 2\t; Index = 54 Token = 14\n\t\tDW\t992\t* 2\t; Index = 54 Token = 15\n\t\tDW\t864\t* 2\t; Index = 55 Token = 0\n\t\tDW\t864\t* 2\t; Index = 55 Token = 1\n\t\tDW\t864\t* 2\t; Index = 55 Token = 2\n\t\tDW\t864\t* 2\t; Index = 55 Token = 3\n\t\tDW\t912\t* 2\t; Index = 55 Token = 4\n\t\tDW\t944\t* 2\t; Index = 55 Token = 5\n\t\tDW\t976\t* 2\t; Index = 55 Token = 6\n\t\tDW\t1008\t* 2\t; Index = 55 Token = 7\n\t\tDW\t864\t* 2\t; Index = 55 Token = 8\n\t\tDW\t864\t* 2\t; Index = 55 Token = 9\n\t\tDW\t864\t* 2\t; Index = 55 Token = 10\n\t\tDW\t864\t* 2\t; Index = 55 Token = 11\n\t\tDW\t912\t* 2\t; Index = 55 Token = 12\n\t\tDW\t944\t* 2\t; Index = 55 Token = 13\n\t\tDW\t976\t* 2\t; Index = 55 Token = 14\n\t\tDW\t1008\t* 2\t; Index = 55 Token = 15\n\t\tDW\t880\t* 2\t; Index = 56 Token = 0\n\t\tDW\t880\t* 2\t; Index = 56 Token = 1\n\t\tDW\t880\t* 2\t; Index = 56 Token = 2\n\t\tDW\t880\t* 2\t; Index = 56 Token = 3\n\t\tDW\t928\t* 2\t; Index = 56 Token = 4\n\t\tDW\t960\t* 2\t; Index = 56 Token = 5\n\t\tDW\t992\t* 2\t; Index = 56 Token = 6\n\t\tDW\t1024\t* 2\t; Index = 56 Token = 7\n\t\tDW\t880\t* 2\t; Index = 56 Token = 8\n\t\tDW\t880\t* 2\t; Index = 56 Token = 9\n\t\tDW\t880\t* 2\t; Index = 56 Token = 10\n\t\tDW\t880\t* 2\t; Index = 56 Token = 11\n\t\tDW\t928\t* 2\t; Index = 56 Token = 12\n\t\tDW\t960\t* 2\t; Index = 56 Token = 13\n\t\tDW\t992\t* 2\t; Index = 56 Token = 14\n\t\tDW\t1024\t* 2\t; Index = 56 Token = 15\n\t\tDW\t896\t* 2\t; Index = 57 Token = 0\n\t\tDW\t896\t* 2\t; Index = 57 Token = 1\n\t\tDW\t896\t* 2\t; Index = 57 Token = 2\n\t\tDW\t896\t* 2\t; Index = 57 Token = 3\n\t\tDW\t944\t* 2\t; Index = 57 Token = 4\n\t\tDW\t976\t* 2\t; Index = 57 Token = 5\n\t\tDW\t1008\t* 2\t; Index = 57 Token = 6\n\t\tDW\t1040\t* 2\t; Index = 57 Token = 7\n\t\tDW\t896\t* 2\t; Index = 57 Token = 8\n\t\tDW\t896\t* 2\t; Index = 57 Token = 9\n\t\tDW\t896\t* 2\t; Index = 57 Token = 10\n\t\tDW\t896\t* 2\t; Index = 57 Token = 11\n\t\tDW\t944\t* 2\t; Index = 57 Token = 12\n\t\tDW\t976\t* 2\t; Index = 57 Token = 13\n\t\tDW\t1008\t* 2\t; Index = 57 Token = 14\n\t\tDW\t1040\t* 2\t; Index = 57 Token = 15\n\t\tDW\t912\t* 2\t; Index = 58 Token = 0\n\t\tDW\t912\t* 2\t; Index = 58 Token = 1\n\t\tDW\t912\t* 2\t; Index = 58 Token = 2\n\t\tDW\t912\t* 2\t; Index = 58 Token = 3\n\t\tDW\t960\t* 2\t; Index = 58 Token = 4\n\t\tDW\t992\t* 2\t; Index = 58 Token = 5\n\t\tDW\t1024\t* 2\t; Index = 58 Token = 6\n\t\tDW\t1056\t* 2\t; Index = 58 Token = 7\n\t\tDW\t912\t* 2\t; Index = 58 Token = 8\n\t\tDW\t912\t* 2\t; Index = 58 Token = 9\n\t\tDW\t912\t* 2\t; Index = 58 Token = 10\n\t\tDW\t912\t* 2\t; Index = 58 Token = 11\n\t\tDW\t960\t* 2\t; Index = 58 Token = 12\n\t\tDW\t992\t* 2\t; Index = 58 Token = 13\n\t\tDW\t1024\t* 2\t; Index = 58 Token = 14\n\t\tDW\t1056\t* 2\t; Index = 58 Token = 15\n\t\tDW\t928\t* 2\t; Index = 59 Token = 0\n\t\tDW\t928\t* 2\t; Index = 59 Token = 1\n\t\tDW\t928\t* 2\t; Index = 59 Token = 2\n\t\tDW\t928\t* 2\t; Index = 59 Token = 3\n\t\tDW\t976\t* 2\t; Index = 59 Token = 4\n\t\tDW\t1008\t* 2\t; Index = 59 Token = 5\n\t\tDW\t1040\t* 2\t; Index = 59 Token = 6\n\t\tDW\t1072\t* 2\t; Index = 59 Token = 7\n\t\tDW\t928\t* 2\t; Index = 59 Token = 8\n\t\tDW\t928\t* 2\t; Index = 59 Token = 9\n\t\tDW\t928\t* 2\t; Index = 59 Token = 10\n\t\tDW\t928\t* 2\t; Index = 59 Token = 11\n\t\tDW\t976\t* 2\t; Index = 59 Token = 12\n\t\tDW\t1008\t* 2\t; Index = 59 Token = 13\n\t\tDW\t1040\t* 2\t; Index = 59 Token = 14\n\t\tDW\t1072\t* 2\t; Index = 59 Token = 15\n\t\tDW\t944\t* 2\t; Index = 60 Token = 0\n\t\tDW\t944\t* 2\t; Index = 60 Token = 1\n\t\tDW\t944\t* 2\t; Index = 60 Token = 2\n\t\tDW\t944\t* 2\t; Index = 60 Token = 3\n\t\tDW\t992\t* 2\t; Index = 60 Token = 4\n\t\tDW\t1024\t* 2\t; Index = 60 Token = 5\n\t\tDW\t1056\t* 2\t; Index = 60 Token = 6\n\t\tDW\t1088\t* 2\t; Index = 60 Token = 7\n\t\tDW\t944\t* 2\t; Index = 60 Token = 8\n\t\tDW\t944\t* 2\t; Index = 60 Token = 9\n\t\tDW\t944\t* 2\t; Index = 60 Token = 10\n\t\tDW\t944\t* 2\t; Index = 60 Token = 11\n\t\tDW\t992\t* 2\t; Index = 60 Token = 12\n\t\tDW\t1024\t* 2\t; Index = 60 Token = 13\n\t\tDW\t1056\t* 2\t; Index = 60 Token = 14\n\t\tDW\t1088\t* 2\t; Index = 60 Token = 15\n\t\tDW\t960\t* 2\t; Index = 61 Token = 0\n\t\tDW\t960\t* 2\t; Index = 61 Token = 1\n\t\tDW\t960\t* 2\t; Index = 61 Token = 2\n\t\tDW\t960\t* 2\t; Index = 61 Token = 3\n\t\tDW\t1008\t* 2\t; Index = 61 Token = 4\n\t\tDW\t1040\t* 2\t; Index = 61 Token = 5\n\t\tDW\t1072\t* 2\t; Index = 61 Token = 6\n\t\tDW\t1104\t* 2\t; Index = 61 Token = 7\n\t\tDW\t960\t* 2\t; Index = 61 Token = 8\n\t\tDW\t960\t* 2\t; Index = 61 Token = 9\n\t\tDW\t960\t* 2\t; Index = 61 Token = 10\n\t\tDW\t960\t* 2\t; Index = 61 Token = 11\n\t\tDW\t1008\t* 2\t; Index = 61 Token = 12\n\t\tDW\t1040\t* 2\t; Index = 61 Token = 13\n\t\tDW\t1072\t* 2\t; Index = 61 Token = 14\n\t\tDW\t1104\t* 2\t; Index = 61 Token = 15\n\t\tDW\t976\t* 2\t; Index = 62 Token = 0\n\t\tDW\t976\t* 2\t; Index = 62 Token = 1\n\t\tDW\t976\t* 2\t; Index = 62 Token = 2\n\t\tDW\t976\t* 2\t; Index = 62 Token = 3\n\t\tDW\t1024\t* 2\t; Index = 62 Token = 4\n\t\tDW\t1056\t* 2\t; Index = 62 Token = 5\n\t\tDW\t1088\t* 2\t; Index = 62 Token = 6\n\t\tDW\t1120\t* 2\t; Index = 62 Token = 7\n\t\tDW\t976\t* 2\t; Index = 62 Token = 8\n\t\tDW\t976\t* 2\t; Index = 62 Token = 9\n\t\tDW\t976\t* 2\t; Index = 62 Token = 10\n\t\tDW\t976\t* 2\t; Index = 62 Token = 11\n\t\tDW\t1024\t* 2\t; Index = 62 Token = 12\n\t\tDW\t1056\t* 2\t; Index = 62 Token = 13\n\t\tDW\t1088\t* 2\t; Index = 62 Token = 14\n\t\tDW\t1120\t* 2\t; Index = 62 Token = 15\n\t\tDW\t992\t* 2\t; Index = 63 Token = 0\n\t\tDW\t992\t* 2\t; Index = 63 Token = 1\n\t\tDW\t992\t* 2\t; Index = 63 Token = 2\n\t\tDW\t992\t* 2\t; Index = 63 Token = 3\n\t\tDW\t1040\t* 2\t; Index = 63 Token = 4\n\t\tDW\t1072\t* 2\t; Index = 63 Token = 5\n\t\tDW\t1104\t* 2\t; Index = 63 Token = 6\n\t\tDW\t1136\t* 2\t; Index = 63 Token = 7\n\t\tDW\t992\t* 2\t; Index = 63 Token = 8\n\t\tDW\t992\t* 2\t; Index = 63 Token = 9\n\t\tDW\t992\t* 2\t; Index = 63 Token = 10\n\t\tDW\t992\t* 2\t; Index = 63 Token = 11\n\t\tDW\t1040\t* 2\t; Index = 63 Token = 12\n\t\tDW\t1072\t* 2\t; Index = 63 Token = 13\n\t\tDW\t1104\t* 2\t; Index = 63 Token = 14\n\t\tDW\t1136\t* 2\t; Index = 63 Token = 15\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 0\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 1\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 2\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 3\n\t\tDW\t1056\t* 2\t; Index = 64 Token = 4\n\t\tDW\t1088\t* 2\t; Index = 64 Token = 5\n\t\tDW\t1120\t* 2\t; Index = 64 Token = 6\n\t\tDW\t1152\t* 2\t; Index = 64 Token = 7\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 8\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 9\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 10\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 11\n\t\tDW\t1056\t* 2\t; Index = 64 Token = 12\n\t\tDW\t1088\t* 2\t; Index = 64 Token = 13\n\t\tDW\t1120\t* 2\t; Index = 64 Token = 14\n\t\tDW\t1152\t* 2\t; Index = 64 Token = 15\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 0\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 1\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 2\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 3\n\t\tDW\t1072\t* 2\t; Index = 65 Token = 4\n\t\tDW\t1104\t* 2\t; Index = 65 Token = 5\n\t\tDW\t1136\t* 2\t; Index = 65 Token = 6\n\t\tDW\t1168\t* 2\t; Index = 65 Token = 7\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 8\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 9\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 10\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 11\n\t\tDW\t1072\t* 2\t; Index = 65 Token = 12\n\t\tDW\t1104\t* 2\t; Index = 65 Token = 13\n\t\tDW\t1136\t* 2\t; Index = 65 Token = 14\n\t\tDW\t1168\t* 2\t; Index = 65 Token = 15\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 0\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 1\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 2\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 3\n\t\tDW\t1088\t* 2\t; Index = 66 Token = 4\n\t\tDW\t1120\t* 2\t; Index = 66 Token = 5\n\t\tDW\t1152\t* 2\t; Index = 66 Token = 6\n\t\tDW\t1184\t* 2\t; Index = 66 Token = 7\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 8\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 9\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 10\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 11\n\t\tDW\t1088\t* 2\t; Index = 66 Token = 12\n\t\tDW\t1120\t* 2\t; Index = 66 Token = 13\n\t\tDW\t1152\t* 2\t; Index = 66 Token = 14\n\t\tDW\t1184\t* 2\t; Index = 66 Token = 15\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 0\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 1\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 2\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 3\n\t\tDW\t1104\t* 2\t; Index = 67 Token = 4\n\t\tDW\t1136\t* 2\t; Index = 67 Token = 5\n\t\tDW\t1168\t* 2\t; Index = 67 Token = 6\n\t\tDW\t1200\t* 2\t; Index = 67 Token = 7\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 8\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 9\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 10\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 11\n\t\tDW\t1104\t* 2\t; Index = 67 Token = 12\n\t\tDW\t1136\t* 2\t; Index = 67 Token = 13\n\t\tDW\t1168\t* 2\t; Index = 67 Token = 14\n\t\tDW\t1200\t* 2\t; Index = 67 Token = 15\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 0\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 1\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 2\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 3\n\t\tDW\t1120\t* 2\t; Index = 68 Token = 4\n\t\tDW\t1152\t* 2\t; Index = 68 Token = 5\n\t\tDW\t1184\t* 2\t; Index = 68 Token = 6\n\t\tDW\t1216\t* 2\t; Index = 68 Token = 7\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 8\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 9\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 10\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 11\n\t\tDW\t1120\t* 2\t; Index = 68 Token = 12\n\t\tDW\t1152\t* 2\t; Index = 68 Token = 13\n\t\tDW\t1184\t* 2\t; Index = 68 Token = 14\n\t\tDW\t1216\t* 2\t; Index = 68 Token = 15\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 0\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 1\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 2\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 3\n\t\tDW\t1136\t* 2\t; Index = 69 Token = 4\n\t\tDW\t1168\t* 2\t; Index = 69 Token = 5\n\t\tDW\t1200\t* 2\t; Index = 69 Token = 6\n\t\tDW\t1232\t* 2\t; Index = 69 Token = 7\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 8\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 9\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 10\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 11\n\t\tDW\t1136\t* 2\t; Index = 69 Token = 12\n\t\tDW\t1168\t* 2\t; Index = 69 Token = 13\n\t\tDW\t1200\t* 2\t; Index = 69 Token = 14\n\t\tDW\t1232\t* 2\t; Index = 69 Token = 15\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 0\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 1\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 2\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 3\n\t\tDW\t1152\t* 2\t; Index = 70 Token = 4\n\t\tDW\t1184\t* 2\t; Index = 70 Token = 5\n\t\tDW\t1216\t* 2\t; Index = 70 Token = 6\n\t\tDW\t1248\t* 2\t; Index = 70 Token = 7\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 8\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 9\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 10\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 11\n\t\tDW\t1152\t* 2\t; Index = 70 Token = 12\n\t\tDW\t1184\t* 2\t; Index = 70 Token = 13\n\t\tDW\t1216\t* 2\t; Index = 70 Token = 14\n\t\tDW\t1248\t* 2\t; Index = 70 Token = 15\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 0\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 1\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 2\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 3\n\t\tDW\t1168\t* 2\t; Index = 71 Token = 4\n\t\tDW\t1200\t* 2\t; Index = 71 Token = 5\n\t\tDW\t1232\t* 2\t; Index = 71 Token = 6\n\t\tDW\t1264\t* 2\t; Index = 71 Token = 7\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 8\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 9\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 10\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 11\n\t\tDW\t1168\t* 2\t; Index = 71 Token = 12\n\t\tDW\t1200\t* 2\t; Index = 71 Token = 13\n\t\tDW\t1232\t* 2\t; Index = 71 Token = 14\n\t\tDW\t1264\t* 2\t; Index = 71 Token = 15\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 0\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 1\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 2\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 3\n\t\tDW\t1184\t* 2\t; Index = 72 Token = 4\n\t\tDW\t1216\t* 2\t; Index = 72 Token = 5\n\t\tDW\t1248\t* 2\t; Index = 72 Token = 6\n\t\tDW\t1280\t* 2\t; Index = 72 Token = 7\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 8\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 9\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 10\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 11\n\t\tDW\t1184\t* 2\t; Index = 72 Token = 12\n\t\tDW\t1216\t* 2\t; Index = 72 Token = 13\n\t\tDW\t1248\t* 2\t; Index = 72 Token = 14\n\t\tDW\t1280\t* 2\t; Index = 72 Token = 15\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 0\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 1\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 2\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 3\n\t\tDW\t1200\t* 2\t; Index = 73 Token = 4\n\t\tDW\t1232\t* 2\t; Index = 73 Token = 5\n\t\tDW\t1264\t* 2\t; Index = 73 Token = 6\n\t\tDW\t1296\t* 2\t; Index = 73 Token = 7\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 8\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 9\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 10\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 11\n\t\tDW\t1200\t* 2\t; Index = 73 Token = 12\n\t\tDW\t1232\t* 2\t; Index = 73 Token = 13\n\t\tDW\t1264\t* 2\t; Index = 73 Token = 14\n\t\tDW\t1296\t* 2\t; Index = 73 Token = 15\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 0\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 1\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 2\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 3\n\t\tDW\t1216\t* 2\t; Index = 74 Token = 4\n\t\tDW\t1248\t* 2\t; Index = 74 Token = 5\n\t\tDW\t1280\t* 2\t; Index = 74 Token = 6\n\t\tDW\t1312\t* 2\t; Index = 74 Token = 7\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 8\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 9\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 10\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 11\n\t\tDW\t1216\t* 2\t; Index = 74 Token = 12\n\t\tDW\t1248\t* 2\t; Index = 74 Token = 13\n\t\tDW\t1280\t* 2\t; Index = 74 Token = 14\n\t\tDW\t1312\t* 2\t; Index = 74 Token = 15\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 0\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 1\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 2\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 3\n\t\tDW\t1232\t* 2\t; Index = 75 Token = 4\n\t\tDW\t1264\t* 2\t; Index = 75 Token = 5\n\t\tDW\t1296\t* 2\t; Index = 75 Token = 6\n\t\tDW\t1328\t* 2\t; Index = 75 Token = 7\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 8\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 9\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 10\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 11\n\t\tDW\t1232\t* 2\t; Index = 75 Token = 12\n\t\tDW\t1264\t* 2\t; Index = 75 Token = 13\n\t\tDW\t1296\t* 2\t; Index = 75 Token = 14\n\t\tDW\t1328\t* 2\t; Index = 75 Token = 15\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 0\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 1\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 2\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 3\n\t\tDW\t1248\t* 2\t; Index = 76 Token = 4\n\t\tDW\t1280\t* 2\t; Index = 76 Token = 5\n\t\tDW\t1312\t* 2\t; Index = 76 Token = 6\n\t\tDW\t1344\t* 2\t; Index = 76 Token = 7\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 8\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 9\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 10\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 11\n\t\tDW\t1248\t* 2\t; Index = 76 Token = 12\n\t\tDW\t1280\t* 2\t; Index = 76 Token = 13\n\t\tDW\t1312\t* 2\t; Index = 76 Token = 14\n\t\tDW\t1344\t* 2\t; Index = 76 Token = 15\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 0\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 1\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 2\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 3\n\t\tDW\t1264\t* 2\t; Index = 77 Token = 4\n\t\tDW\t1296\t* 2\t; Index = 77 Token = 5\n\t\tDW\t1328\t* 2\t; Index = 77 Token = 6\n\t\tDW\t1360\t* 2\t; Index = 77 Token = 7\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 8\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 9\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 10\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 11\n\t\tDW\t1264\t* 2\t; Index = 77 Token = 12\n\t\tDW\t1296\t* 2\t; Index = 77 Token = 13\n\t\tDW\t1328\t* 2\t; Index = 77 Token = 14\n\t\tDW\t1360\t* 2\t; Index = 77 Token = 15\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 0\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 1\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 2\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 3\n\t\tDW\t1280\t* 2\t; Index = 78 Token = 4\n\t\tDW\t1312\t* 2\t; Index = 78 Token = 5\n\t\tDW\t1344\t* 2\t; Index = 78 Token = 6\n\t\tDW\t1376\t* 2\t; Index = 78 Token = 7\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 8\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 9\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 10\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 11\n\t\tDW\t1280\t* 2\t; Index = 78 Token = 12\n\t\tDW\t1312\t* 2\t; Index = 78 Token = 13\n\t\tDW\t1344\t* 2\t; Index = 78 Token = 14\n\t\tDW\t1376\t* 2\t; Index = 78 Token = 15\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 0\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 1\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 2\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 3\n\t\tDW\t1296\t* 2\t; Index = 79 Token = 4\n\t\tDW\t1328\t* 2\t; Index = 79 Token = 5\n\t\tDW\t1360\t* 2\t; Index = 79 Token = 6\n\t\tDW\t1392\t* 2\t; Index = 79 Token = 7\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 8\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 9\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 10\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 11\n\t\tDW\t1296\t* 2\t; Index = 79 Token = 12\n\t\tDW\t1328\t* 2\t; Index = 79 Token = 13\n\t\tDW\t1360\t* 2\t; Index = 79 Token = 14\n\t\tDW\t1392\t* 2\t; Index = 79 Token = 15\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 0\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 1\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 2\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 3\n\t\tDW\t1312\t* 2\t; Index = 80 Token = 4\n\t\tDW\t1344\t* 2\t; Index = 80 Token = 5\n\t\tDW\t1376\t* 2\t; Index = 80 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 80 Token = 7\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 8\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 9\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 10\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 11\n\t\tDW\t1312\t* 2\t; Index = 80 Token = 12\n\t\tDW\t1344\t* 2\t; Index = 80 Token = 13\n\t\tDW\t1376\t* 2\t; Index = 80 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 80 Token = 15\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 0\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 1\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 2\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 3\n\t\tDW\t1328\t* 2\t; Index = 81 Token = 4\n\t\tDW\t1360\t* 2\t; Index = 81 Token = 5\n\t\tDW\t1392\t* 2\t; Index = 81 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 81 Token = 7\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 8\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 9\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 10\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 11\n\t\tDW\t1328\t* 2\t; Index = 81 Token = 12\n\t\tDW\t1360\t* 2\t; Index = 81 Token = 13\n\t\tDW\t1392\t* 2\t; Index = 81 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 81 Token = 15\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 0\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 1\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 2\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 3\n\t\tDW\t1344\t* 2\t; Index = 82 Token = 4\n\t\tDW\t1376\t* 2\t; Index = 82 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 7\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 8\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 9\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 10\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 11\n\t\tDW\t1344\t* 2\t; Index = 82 Token = 12\n\t\tDW\t1376\t* 2\t; Index = 82 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 15\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 0\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 1\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 2\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 3\n\t\tDW\t1360\t* 2\t; Index = 83 Token = 4\n\t\tDW\t1392\t* 2\t; Index = 83 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 7\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 8\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 9\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 10\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 11\n\t\tDW\t1360\t* 2\t; Index = 83 Token = 12\n\t\tDW\t1392\t* 2\t; Index = 83 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 15\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 0\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 1\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 2\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 3\n\t\tDW\t1376\t* 2\t; Index = 84 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 7\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 8\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 9\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 10\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 11\n\t\tDW\t1376\t* 2\t; Index = 84 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 15\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 0\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 1\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 2\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 3\n\t\tDW\t1392\t* 2\t; Index = 85 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 7\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 8\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 9\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 10\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 11\n\t\tDW\t1392\t* 2\t; Index = 85 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 15\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 0\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 1\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 2\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 7\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 8\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 9\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 10\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 15\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 0\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 1\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 2\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 7\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 8\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 9\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 10\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 15\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 0\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 1\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 2\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 7\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 8\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 9\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 10\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 15\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = AUDIO\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS = \t\t\t&\n\t\tsoundio.obj\t&\n\t\tsoundint.obj\t&\n\t\tsoundlck.obj\t&\n\t\tsoscodec.obj\t&\n\t\tauduncmp.obj\t\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.lib  $(%WWFLAT)\\lib\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t copy *.lib $(%WWFLAT)\\lib\n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\nsoundio.obj: .AUTODEPEND\n\t$(CPP_CMD) -zp4 -5s -mf -s -d2 /i=$(%WWFLAT)\\include soundio.cpp\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake\n\tcd ..\n\tcopy *.386 test\n\n#**************************** End of makefile ******************************\n\u001a\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/NYBBTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* bNybbleTablexxxx - ADPCM Lookup table for nybbles\n;****************************************************************************\n\n\t\talign\t4\n\nbNybbleTableLow\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\n\t\talign 4\n\nbNybbleTableHigh\tDB\t00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2\n\t\tDB\t01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2\n\t\tDB\t02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2\n\t\tDB\t03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2\n\t\tDB\t04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2\n\t\tDB\t05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2\n\t\tDB\t06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2\n\t\tDB\t07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2\n\t\tDB\t08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2\n\t\tDB\t09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2\n\t\tDB\t0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2\n\t\tDB\t0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2\n\t\tDB\t0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2\n\t\tDB\t0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2\n\t\tDB\t0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2\n\t\tDB\t0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/SOS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sos.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DEFINED   \n#define  _SOS_DEFINED   \n#include \"sosdefs.h\"\n\n#pragma pack(4)\n \n// error definition for sound operating system  \n#define  _SOS_ERR          -1\n\n// number of drivers allowed to be open at one time\n#define  _SOS_MAX_DRIVERS  5\n\n// structure definition for the capabilities\ntypedef struct _tagCAPABILITIES\n{\n   BYTE  szDeviceName[ 32 ];  // device name\n   WORD  wDeviceVersion;      // device version\n   WORD  wBitsPerSample;      // bits per sound sample\n   WORD  wChannels;           // stereo/mono sound card\n   WORD  wMinRate;            // minimum rate\n   WORD  wMaxRate;            // maximum rate\n   WORD  wMixerOnBoard;       // board contains mixer\n   WORD  wMixerFlags;         // mixer capabilities\n   WORD  wFlags;              // miscellaneous flags   \n   short far * lpPortList;         // list of usable ports\n   short far * lpDMAList;          // list of usable dma channels\n   short far * lpIRQList;          // list of usable irq channels\n   short far * lpRateList;         // list of usable rates, -1 if any in min to max\n   WORD  fBackground;         // foreground or background driver\n   WORD  wDeviceID;           // ID for the device\n   WORD  wTimerID;            // ID for the timer\n   \n} _SOS_CAPABILITIES; \n\n// far pointer to the device capabilities structure\ntypedef _SOS_CAPABILITIES far *  LPSOSDEVICECAPS;\n\n// flag types for driver\n#define  _FLAGS_SIGNED              0x8000\n  \n// devices that can be loaded\n#define  _SOUND_BLASTER_8_MONO      0xe000\n#define  _SOUND_BLASTER_8_ST        0xe001\n#define  _SBPRO_8_ST                _SOUND_BLASTER_8_ST\n#define  _SBPRO_8_MONO              0xe00f\n#define  _SOUND_MASTER_II_8_MONO    0xe002\n#define  _MV_PAS_8_MONO             0xe003\n#define  _MV_PAS_16_MONO            0xe004\n#define  _MV_PAS_8_ST               0xe005\n#define  _MV_PAS_16_ST              0xe006\n#define  _ADLIB_GOLD_8_ST           0xe007\n#define  _ADLIB_GOLD_16_ST          0xe008\n#define  _ADLIB_GOLD_8_MONO         0xe009\n#define  _ADLIB_GOLD_16_MONO        0xe00a\n#define  _MICROSOFT_8_MONO          0xe00b\n#define  _MICROSOFT_8_ST            0xe00c\n#define  _MICROSOFT_16_MONO         0xe00d\n#define  _MICROSOFT_16_ST           0xe00e\n#define  _SOUND_SOURCE_8_MONO_PC    0xe010\n#define  _SOUND_SOURCE_8_MONO_TANDY 0xe011\n#define  _GENERAL_PORT_8_MONO       0xe012\n#define  _GENERAL_PORT_8_MONO_R     0xe013\n#define  _SIERRA_8_MONO             0xe014\n#define  _SB16_8_MONO               0xe015\n#define  _SB16_8_ST                 0xe016\n#define  _SB16_16_MONO              0xe017\n#define  _SB16_16_ST                0xe018\n#define  _ESS_AUDIODRIVE_8_MONO     0xe019\n#define  _ESS_AUDIODRIVE_8_ST       0xe01a\n#define  _ESS_AUDIODRIVE_16_MONO    0xe01b\n#define  _ESS_AUDIODRIVE_16_ST      0xe01c\n#define  _SOUNDSCAPE_8_MONO         0xe01d\n#define  _SOUNDSCAPE_8_ST           0xe01e\n#define  _SOUNDSCAPE_16_MONO        0xe01f\n#define  _SOUNDSCAPE_16_ST          0xe020\n#define  _RAP10_8_MONO              0xe021\n#define  _RAP10_16_MONO             0xe022\n#define  _GUS_8_MONO                0xe023\n#define  _GUS_8_ST                  0xe024\n#define  _GUS_16_MONO               0xe025\n#define  _GUS_16_ST                 0xe026\n#define  _GUS_MAX_8_MONO            0xe027\n#define  _GUS_MAX_8_ST              0xe028\n#define  _GUS_MAX_16_MONO           0xe029\n#define  _GUS_MAX_16_ST             0xe02a\n#define  _WAVEJAMMER_8_MONO         0xe02b\n#define  _WAVEJAMMER_8_ST           0xe02c\n#define  _WAVEJAMMER_16_MONO        0xe02d\n#define  _WAVEJAMMER_16_ST          0xe02e\n#define  _TEMPOCS_8_MONO            0xe02f\n#define  _TEMPOCS_8_ST              0xe030\n#define  _TEMPOCS_16_MONO           0xe031\n#define  _TEMPOCS_16_ST             0xe032\n#define  _WAVEJAMMERCD_8_MONO       0xe033\n#define  _WAVEJAMMERCD_8_ST         0xe034\n#define  _WAVEJAMMERCD_16_MONO      0xe035\n#define  _WAVEJAMMERCD_16_ST        0xe036\n#define  _SOUND_BLASTER_8_MONO_R    0xe050\n#define  _MICROSOFT_8_MONO_R        0xe051\n#define  _SOUND_MASTER_II_8_MONO_R  0xe052\n#define  _ADLIB_GOLD_8_MONO_R       0xe053\n#define  _MV_PAS_8_MONO_R           0xe054\n#define  _RAP10_8_MONO_R            0xe058\n#define  _RAP10_16_MONO_R           0xe059\n#define  _SB16_8_MONO_R             0xe05a\n#define  _SB16_8_ST_R               0xe05b\n#define  _SB16_16_MONO_R            0xe05c\n#define  _SB16_16_ST_R              0xe05d\n#define  _MV_PAS_16_MONO_R          0xe060\n#define  _SOUNDSCAPE_8_MONO_R       0xe061\n#define  _SOUNDSCAPE_8_ST_R         0xe062\n#define  _SOUNDSCAPE_16_MONO_R      0xe063\n#define  _SOUNDSCAPE_16_ST_R        0xe064\n#define  _ESS_AUDIODRIVE_8_MONO_R   0xe065\n#define  _ESS_AUDIODRIVE_8_ST_R     0xe066\n#define  _ESS_AUDIODRIVE_16_MONO_R  0xe067\n#define  _ESS_AUDIODRIVE_16_ST_R    0xe068\n#define  _SPEECH_THING_8_MONO       0xe090\n#define  _YAMAHA_8_MONO             0xe106\n#define  _INT_SPEAKER_8_MONO        0xe107\n\n// call indexes for the loadable drivers\nenum\n{ \n   _DRV_INIT,\n   _DRV_UNINIT,\n   _DRV_SETRATE,\n   _DRV_SETACTION,\n   _DRV_START,\n   _DRV_STOP,\n   _DRV_PAUSE,\n   _DRV_RESUME,\n   _DRV_CAPABILITIES,\n   _DRV_PLAY_FOREGROUND,\n   _DRV_GET_FILL_INFO, \n   _DRV_GET_CALL_FUNCTIONS,\n   _DRV_SET_CALL_FUNCTIONS\n};\n\n// fill info\ntypedef  struct   _tagFillInfo\n         {\n\n            LPSTR lpFillHandler;                   // pointer to fill handler\n            LPWORD lpDMAFillCount;                 // pointer to dma count\n            LPSTR lpSampleList;                    // pointer to sample list\n            LPWORD lpDMAMasterVolume;              // pointer to dma count\n\n         } _SOS_FILL_INFO;\n\n// caps info structure\ntypedef  struct   _tagCapsInfo\n         {\n\n            LPSTR    lpPortList;                   // pointer to port list\n            LPSTR    lpDMAList;                    // pointer to DMA list\n            LPSTR    lpIRQList;                    // pointer to IRQ list\n            LPSTR    lpRateList;                   // pointer to rate list\n\n         } _SOS_CAPS_INFO;\n\n// maximum number of available voice\n#define  _MAX_VOICES    32\n\n// structure definition\ntypedef  struct   _tagSAMPLE\n{\n   LPSTR    samplePtr;                 // pointer to data buffer\n   LPSTR    sampleData;                // pointer to active data\n   LPSTR    sampleLoopPtr;             // pointer for loop back\n\n   WORD     sampleLength;              // length of sample\n   WORD     sampleIndex;               // index into sample\n   WORD     sampleLoopLength;          // length of loop\n   \n   WORD     sampleBytesLeft;           // bytes left to play in sample\n\n   WORD     sampleLoopPoint;           // byte count for loop point\n   WORD     sampleLoopEndLength;       // length of remaining chunk\n\n   short    sampleFlags;               // control sample\n   short    sampleVolume;              // volume control\n   short    sampleID;                  // sample ID\n\n   short    sampleChannel;             // channel to play sample on\n   short    sampleLoopCount;           // loop count\n   short    sampleLastFill;            // last fill position\n   VOID ( far cdecl * sampleCallback )( WORD, WORD, WORD ); // callback function for sample\n\n   WORD     samplePitchAdd;\n   short    samplePitchFraction;\n\n   short    samplePort;                // port to use for non-dma digitized\n\n   WORD     sampleTotalBytes;\n   WORD     sampleByteLength;\n\n   short    samplePanLocation;\n   short    samplePanSpeed;\n   short    samplePanDirection;\n   short    samplePanStart;\n   short    samplePanEnd;\n   \n   short    sampleDelayBytes;\n   short    sampleDelayRepeat;\n   \n   WORD     sampleADPCMPredicted;\n   short    sampleADPCMIndex;\n\n   short    sampleRootNoteMIDI;   \n\n   WORD  sampleTemp1;   \n   \n} _SOS_SAMPLE;\n\n// enumeration for left or right channel\nenum\n{\n   _LEFT_CHANNEL,\n   _RIGHT_CHANNEL,\n   _CENTER_CHANNEL,\n   _INTERLEAVED\n};\n\n// enumeration for foreground and background\nenum\n{ \n   _FOREGROUND,\n   _BACKGROUND \n};\n\n// defines for the sample flags\n#define  _ACTIVE           0x8000\n#define  _LOOPING          0x4000\n#define  _FIRST_TIME       0x2000\n#define  _PENDING_RELEASE  0x1000\n#define  _CONTINUE_BLOCK   0x0800\n#define  _PITCH_SHIFT      0x0400\n#define  _PANNING          0x0200\n#define  _VOLUME           0x0100\n#define  _TRANSLATE16TO8   0x0080\n#define  _STAGE_LOOP       0x0040\n#define  _TRANSLATE8TO16   0x0020\n#define  _STEREOTOMONO     0x0010\n\n// defines for the wParam flags \n#define  _SINGLE_SAMPLE 0x01\n\n#define  _SOS_DCAPS_AUTO_REINIT     0x01\n#define  _SOS_DCAPS_MPU_401         0x02\n#define  _SOS_DCAPS_OPL2            0x04\n#define  _SOS_DCAPS_OPL3            0x08\n#define  _SOS_DCAPS_OPL4            0x10\n#define  _SOS_DCAPS_WAVETABLE       0x20\n#define  _SOS_DCAPS_DL_SAMPLES      0x40\n#define  _SOS_DCAPS_FIFO_DEVICE     0x80\n#define  _SOS_DCAPS_ENV_NEEDED      0x100\n#define  _SOS_DCAPS_PSEUDO_DMA1     0x200\n#define  _SOS_DCAPS_SIGNED_DATA     0x8000\n\n// file header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // number of drivers in the file\n   WORD  wDrivers;\n\n   // offset of first driver\n   WORD  lOffset;\n\n   // size of the file\n   WORD  lFileSize;\n\n} _FILEHEADER;\n\n// driver header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // offset of next driver\n   WORD  lNextDriver;\n\n   // size of current driver\n   WORD  wSize;\n\n   // id for the current device\n   WORD  wDeviceID;\n\n   // id for the type of DOS extender\n   WORD  wExtenderType;\n\n} _DRIVERHEADER;\n\n// device hardware information\ntypedef struct\n{\n   // port to be used\n   WORD  wPort;\n\n   // irq to use\n   WORD  wIRQ;\n\n   // dma channel to se\n   WORD  wDMA; \n  \n   // extra parameter\n   WORD  wParam;\n\n} _SOS_HARDWARE;\n\n// structure definition for start sample\ntypedef struct\n{\n   // pointer to sample\n   LPSTR lpSamplePtr;\n\n   // size of the sample\n   WORD  dwSampleSize;\n\n   // number of times to loop the sample -1 is infinite\n   WORD  wLoopCount;\n\n   // channel to play sample on\n   WORD  wChannel;\n\n   // volume to play sample at\n   WORD wVolume;\n\n   // id for the sample\n   WORD  wSampleID;\n\n   // far pointer to the callback function\n   VOID ( far cdecl *lpCallback )( WORD, WORD, WORD );\n\n   // port to use if driver is a non-dma background driver\n   WORD  wSamplePort; \n\n   // flags field\n   WORD  wSampleFlags;\n\n   // total length of sample including loops, etc..\n   WORD     dwSampleByteLength;\n\n   // loop point for the sample\n   WORD  dwSampleLoopPoint;\n   WORD  dwSampleLoopLength;\n\n   // pitch shifting components \n   WORD     dwSamplePitchAdd;\n   WORD    wSamplePitchFraction;\n\n   // pan components\n   WORD    wSamplePanLocation;\n   WORD    wSamplePanSpeed;\n   WORD    wSamplePanDirection;\n   WORD    wSamplePanStart;\n   WORD    wSamplePanEnd;\n   \n   // delay parts\n   WORD    wSampleDelayBytes;\n   WORD    wSampleDelayRepeat;\n\n   // compression components   \n   WORD     dwSampleADPCMPredicted;\n   WORD    wSampleADPCMIndex;\n\n   // root note for pitch shifting \n   WORD    wSampleRootNoteMIDI;   \n\n   // filler for future upgrades\n   WORD  dwSampleTemp1;   \n   WORD  dwSampleTemp2;   \n   WORD  dwSampleTemp3;   \n\n} _SOS_START_SAMPLE;\n\n// structure for initializing a driver\ntypedef struct\n{  \n   WORD  wBufferSize;\n   LPSTR lpBuffer;\n   BOOL  wAllocateBuffer;\n   WORD  wSampleRate;\n   WORD  wParam;\n   LONG  dwParam;\n   VOID ( far *lpFillHandler )( VOID );\n   LPSTR lpDriverMemory;\n   LPSTR lpDriverMemoryCS;\n   LPSTR lpTimerMemory;\n   LPSTR lpTimerMemoryCS;\n   WORD  wTimerID;\n   WORD  wPhysical;\n\n} _SOS_INIT_DRIVER;\n\n// define for the timer types to use\n#define  _SOS_NORMAL_TIMER          0x00\n\n// enumeration for the timer types\nenum\n{\n   _TIMER_8_MONO   =     0x1000,\n   _TIMER_8_ST,          \n   _TIMER_16_MONO,       \n   _TIMER_16_ST,         \n   _TIMER_8_MONO_ULAW,  \n   _TIMER_8_ST_ULAW,    \n   _TIMER_16_MONO_ULAW, \n   _TIMER_16_ST_ULAW,   \n   _TIMER_8_MONO_REC,   \n   _TIMER_8_MONO_ULAW_REC,\n   _TIMER_UNDEFINED_1,      \n   _TIMER_UNDEFINED_2,\n   _TIMER_UNDEFINED_3,\n   _TIMER_UNDEFINED_4,\n   _TIMER_UNDEFINED_5,\n   _TIMER_UNDEFINED_6,\n   _TIMER_UNDEFINED_7,\n   _TIMER_UNDEFINED_8,\n   _TIMER_UNDEFINED_9,\n   _TIMER_UNDEFINED_A,\n   _TIMER_UNDEFINED_B,\n   _TIMER_UNDEFINED_C,\n   _TIMER_UNDEFINED_D,\n   _TIMER_UNDEFINED_E,\n   _TIMER_UNDEFINED_F,\n   _TIMER_UNDEFINED_10,\n   _TIMER_UNDEFINED_11,\n   _TIMER_UNDEFINED_12,\n   _TIMER_UNDEFINED_13,\n   _TIMER_UNDEFINED_14,\n   _TIMER_UNDEFINED_15,\n   _TIMER_UNDEFINED_16,\n   _TIMER_8_SOUND_SOURCE,\n   _TIMER_8_SOUND_SOURCE_TANDY,\n   _TIMER_8_GENERAL_PORT,\n   _TIMER_8_GENERAL_PORT_REC   \n};\n\n// define for no slots available\n#define  _ERR_NO_SLOTS ( WORD )-1\n\n// error codes for the system\nenum\n{\n   _ERR_NO_ERROR,\n   _ERR_DRIVER_NOT_LOADED,\n   _ERR_INVALID_POINTER,\n   _ERR_DETECT_INITIALIZED,\n   _ERR_FAIL_ON_FILE_OPEN,\n   _ERR_MEMORY_FAIL,\n   _ERR_INVALID_DRIVER_ID,\n   _ERR_NO_DRIVER_FOUND,\n   _ERR_DETECTION_FAILURE,\n   _ERR_DRIVER_LOADED,\n   _ERR_INVALID_HANDLE,\n   _ERR_NO_HANDLES,\n   _ERR_PAUSED,   \n   _ERR_NOT_PAUSED,\n   _ERR_INVALID_DATA,\n   _ERR_DRV_FILE_FAIL,\n   _ERR_INVALID_PORT,\n   _ERR_INVALID_IRQ,\n   _ERR_INVALID_DMA,\n   _ERR_INVALID_DMA_IRQ\n};   \n\n// maximum number of timer events that can be registered \n#define  _TIMER_MAX_EVENTS    0x10  \n\n// flags for the debugging system\n#define  _SOS_DEBUG_NORMAL       0x0000\n#define  _SOS_DEBUG_NO_TIMER     0x0001\n#define  _SOS_TIMER_DPMI         0x0002\n\n// define for types of DOS extenders\n#define  _SOS_RATIONAL           0x8000\n#define  _SOS_FLASHTECK          0x4000\n\n// defines for the types of timers for different\n// dos extenders\n#define  _SOS_TIMER_NEAR         0x8000\n#define  _SOS_TIMER_FAR          0x4000\n \n// values for callback information\nenum\n{\n   _SAMPLE_PROCESSED,\n   _SAMPLE_LOOPING,\n   _SAMPLE_DONE\n};\n\n// define for special 18.2 callback rate to dos\n#define  _TIMER_DOS_RATE   0xff00\n\n#pragma pack()\n\n#pragma aux int_3 = \"int 3\"\n \n#pragma pack( 1 ) \ntypedef struct\n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned       segment;\n\tunsigned short\tnumber_available;\n\tunsigned short number_used;\n\tunsigned       page0;\n\n} EVDS_STRUCT;\n\ntypedef struct \n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned short segment;\n\tunsigned short\tID;\n\tunsigned       physical;\n\n} VDS_STRUCT;\n\n#pragma pack() \n\n#include \"sosdata.h\"\n#include \"sosfnct.h\"\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/SOSCODEC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*          Copyright (c) 1994, HMI, INC. All Rights Reserved\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     soscodec.asm\n;*\n;* DESCRIPTION\n;*     HMI SOS ADPCM compression/decompression.\n;*\n;* PROGRAMMER\n;*     Nick Skrepetos\n;*     Denzil E. Long, Jr. (Fixed bugs, rewrote for watcom)\n;*\t   Bill Petro\t\t   (Added stereo support)\n;* DATE\n;*     Febuary 15, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\n\nDPMI_INTR\t\tequ\t31h\t\nIF_LOCKED_PM_CODE\tequ\t1h\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t2h\t\t; Locked PM code for DPMI.\n\nSTRUC\tsCompInfo\nlpSource\t\tDD\t?\t;Compressed data pointer\nlpDest\t\t\tDD\t?\t;Uncompressed data pointer\ndwCompSize\t\tDD\t?\t;Compressed size\ndwUnCompSize\t\tDD\t?\t;Uncompressed size\n\ndwSampleIndex\t\tDD\t?\t;Index into sample\ndwPredicted\t\tDD\t?\t;Next predicted value\ndwDifference\t\tDD\t?\t;Difference from last sample\nwCodeBuf\t\tDW\t?\t;Holds 2 nibbles for decompression\nwCode\t\t\tDW\t?\t;Current 4 bit code\nwStep\t\t\tDW\t?\t;Step value in table\nwIndex\t\t\tDW\t?\t;Index into step table\n\ndwSampleIndex2\t\tDD\t?\t;Index into sample\ndwPredicted2\t\tDD\t?\t;Next predicted value\ndwDifference2\t\tDD\t?\t;Difference from last sample\nwCodeBuf2 \t\tDW\t?\t;Holds 2 nibbles for decompression\nwCode2\t\t\tDW\t?\t;Current 4 bit code\nwStep2\t\t\tDW\t?\t;Step value in table\nwIndex2\t\t\tDW\t?\t;Index into step table\n\nwBitSize\t\tDW\t?\t;Bit size for decompression\nwChannels\t\tDW\t?    \t;number of channels\nENDS\tsCompInfo\n\n\n\tDATASEG\n\n\nInitFlags\tDD\t0\t\t; Flags to indicate what has been initialized.\n\n\nLABEL\tLockedDataStart\tBYTE\t\n\n;* Index table for stepping into step table\n\nwCODECIndexTab\tDD\t-1,-1,-1,-1,2,4,6,8\n\t\tDD\t-1,-1,-1,-1,2,4,6,8\n\n\n;Lookup table of replacement values\n;The actual sound value is replaced with an index to lookup in this table\n;The index only takes up a nibble(4bits) and represents an int(16bits)\n;Essentially: \n;Get a value\n;compare it with the value before it\n;find closest value in table and store the index into the table\n;if i'm going down then negitize it\n;go to next byte.\n\n;Theory for stereo:\n;1)handle stereo and mono in two seperate loops. cleaner...\n;start at byte 0 and skip every other byte(or word) both write and read\n;when we get done\n;\tset start byte to 1 and do it again \n\n\n\n\n;This table essentialy round off to closes values in 3 distinct bands\n; precalculated and optimized(i guess) for human hearing.\n\nwCODECStepTab\tDD\t7,  \t8,  \t9,   \t10,   \t11,  \t12,   \t13,14   \t\t\n\t\tDD\t16, \t17, \t19, \t21,  \t23,   \t25,  \t28,   \t31\t\t\t\n\t\tDD\t34, \t37, \t41, \t45,  \t50,   \t55,  \t60,   \t66\t\t\t\n\t\tDD\t73, \t80, \t88, \t97,  \t107,  \t118, \t130,  \t143\t\t\t\n\t\tDD\t157,\t173,\t190,\t209, \t230,  \t253, \t279,  \t307\t\t\t\n\t\tDD\t337,\t371,\t408,\t449, \t494,  \t544, \t598,  \t658\t\t\t\n\t\tDD\t724,\t796,\t876,\t963, \t1060,\t1166,\t1282,\t1411\t\t\t\n\t\tDD\t1552,\t1707,\t1878,\t2066,\t2272,\t2499,\t2749,\t3024\t\t\t\n\t\tDD\t3327,\t3660,\t4026,\t4428,\t4871,\t5358,\t5894,\t6484\n\t\tDD\t7132,\t7845,\t8630,\t9493,\t10442,\t11487,\t12635,\t13899\t\t\n\t\tDD\t15289,\t16818,\t18500,\t20350,\t22385,\t24623,\t27086,\t29794 \n\t\tDD\t32767\t\t\t\n\nwCode\t\t\t\tDD\t0 ; this is to hold index into wCodeStep\ndwCODECByteIndex\t\tDD\t0 ; this is when to stop compressing\ndwCODECBytesProcessed\t\tDD\t0 ; this is how many so far compressed\ndwCODECTempStep\t\t\tDD\t0 ; tempory storage for step value\nwCODECMask\t\t\tDW\t0 ; Current mask\n\nLABEL\tLockedDataEnd\tBYTE\n\n\n\tCODESEG\n\nLABEL\tLockedCodeStart\tBYTE\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECInitStream - Initialize compression stream.\n;*\n;* SYNOPSIS\n;*     sosCODECInitStream(CompInfo)\n;*\n;*     void sosCODECInitStream(_SOS_COMPRESS_INFO *);\n;*\n;* FUNCTION\n;*     Initialize compression stream for compression and decompression.\n;*\n;* INPUTS\n;*     CompInfo - Compression information structure.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tsosCODECInitStream:NEAR\n\tPROC\tsosCODECInitStream C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\n\tmov\teax,[sSOSInfo]\n\tmov\t[(sCompInfo eax).wIndex],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).wStep],7  \t\t; start with a step of 7\n\tmov\t[(sCompInfo eax).dwPredicted],0 \t; no predicted value\n\tmov\t[(sCompInfo eax).dwSampleIndex],0\t;start at head of index\n\tmov\t[(sCompInfo eax).wIndex2],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).wStep2],7  \t\t; start with a step of 7\n\tmov\t[(sCompInfo eax).dwPredicted2],0 \t; no predicted value\n\tmov\t[(sCompInfo eax).dwSampleIndex2],0 \t;start at head of index\n\tret\n\n\tENDP\tsosCODECInitStream\n\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECDecompressData - Decompress audio data.\n;*\n;* SYNOPSIS\n;*     Size = sosCODECDecompressData(CompInfo, NumBytes)\n;*\n;*     long sosCODECDecompressData(_SOS_COMPRESS_INFO *, long);\n;*\n;* FUNCTION\n;*     Decompress data from a 4:1 ADPCM compressed stream. The number of\n;*     bytes decompressed is returned.\n;*\n;* INPUTS\n;*     CompInfo - Compress information structure.\n;*     NumBytes - Number of bytes to compress.\n;*\n;* RESULT\n;*     Size - Size of decompressed data.\n;*\n;****************************************************************************\n\n\tGLOBAL\tsosCODECDecompressData:NEAR\n\tPROC\tsosCODECDecompressData C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\tARG\twBytes:DWORD\n\n\tpush\tesi\n\tpush\tedi\t\t\t   \n\tpush\tebx\n\tpush\tecx\n\tpush\tedx\n\n;*---------------------------------------------------------------------------\n;*\tInitialize\n;*---------------------------------------------------------------------------\n\n\tmov\tebx,[sSOSInfo]\n\tmov\teax,[wBytes]\n\tmov\t[dwCODECBytesProcessed],eax\n\tmov\t[(sCompInfo ebx).dwSampleIndex],0 \t;start at head of index\n\tmov\t[(sCompInfo ebx).dwSampleIndex2],0 \t;start at head of index\n\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??skipByteDivide\n\n\tshr\teax,1\t;Divide size by two\n\n??skipByteDivide:\n\tmov\t[dwCODECByteIndex],eax\n\tmov\tesi,[(sCompInfo ebx).lpSource]\n\tmov\tedi,[(sCompInfo ebx).lpDest]\n\n\tcmp\t[(sCompInfo ebx).wChannels],2\t\t;stereo check\n\tje\t??mainloopl\t\t\t\t;do left side first\t\n\t\n;\tDetermine if sample index is even or odd. This will determine\n;\tif we need to get a new token or not.\n\n;---------------------------------------------------------------------------\n;Main Mono Loop\n;---------------------------------------------------------------------------\n\tpush\tebp\n\tmovzx\tedx,[(sCompInfo ebx).wIndex] \t\t;preload index\n\tmov\tebp, [dwCODECByteIndex]\n\tmov\tecx,[(sCompInfo ebx).dwSampleIndex]\t;preload SampleIndex\n\t\n??mainloop:\t \n\txor\teax,eax\t\t\t\t\t;get a new token\n\ttest\tecx,1\t\t\t\t\t;odd Sample??\n\tje\tshort ??fetchToken\t\t\t; if so get new token\n\tmov\tax,[(sCompInfo ebx).wCodeBuf]\t\t;ored with Code\n\tshr\teax,4\n\tjmp\tshort ??calcDifference\n\talign\t4\n\n??fetchToken:\n\tmov\tal,[esi]\t\t\t\t;put in codebuf\n\tinc\tesi\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\n\n\n??calcDifference:\n\txor\tecx,ecx\n\tand\teax,000Fh\n\tmov\tcx,[(sCompInfo ebx).wStep]\t\t;cx is step value\n\tmov\t[wCode],eax\n\tjmp\t[DWORD PTR JumpTable + eax*4]\n\talign\t4\n\n; note: it is important for speed reasons to keep the order the \n; following jumps entries as well as the \"align 4\" after some of\n; the jmp statements\n\n??7:\n\t; eax = x + x/2 + x/4 + x/8 = (8*x + 4*x +2*x + x)>>3 =\n\t;     = ( x * ( 8 + 4 + 2 + 1 )) >> 3 = ( x * 15 ) >> 3 \n\tlea\tecx,[ecx+ecx*2]\n\tlea\teax,[ecx+ecx*4]\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tjmp\t??save_dif\n\talign\t4\n\n??6:\n\t; eax = x + x / 2 + x / 8 = (8*x + 4*x + x) >> 3 =\n\t;     =\t( x * 8 + x * 5\t) >> 8\n\tlea\teax,[ecx+ecx*4]\n\tlea\teax,[eax+ecx*8]\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tjmp\t??save_dif\n\talign\t4\n\n??5:\n\t; eax = x + x / 4 + x / 8 = (8*x + 2*x + x) >> 3 = \n\t;     =\t( 8 * x + 3 * x) >> 3\n\tlea\teax,[ecx+ecx*2]\n\tlea\teax,[eax+ecx*8]\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tjmp\t??save_dif\n\talign\t4\n\n??4:\n\t; eax = x + x / 8 = (8*x + x) >> 3 = (x * 9)>> 3\n\tlea\teax,[ecx+ecx*8]\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tjmp\t??save_dif\n\talign\t4\n\n??3:\n\t; eax = x/2 + x/4 + x/8 = (4*x + 2*x + x) >> 3\n\t;     =\t( 4x + 3x ) >> 3\n\tlea\teax,[ecx+ecx*2]\n\tlea\teax,[eax+ecx*4]\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tjmp\t??save_dif\n\talign\t4\n\n??2:\n\t; eax = x/2 + x/8 = (4*x + x) >> 3\n\tlea\teax,[ecx+ecx*4]\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tjmp\t??save_dif\n\talign\t4\n\n??1:\n\t; eax = x/4 + x/8 = (2x + x )>>8\n\tlea\teax,[ecx+ecx*2]\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tjmp\t??save_dif\n\talign\t4\n\n??0:\n\t; eax = x/8 = x >> 3\n\tmov\teax,ecx\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tjmp\t ??save_dif\n\talign\t4\n\n??15:\n\t; eax = x + x/2 + x/4 + x/8 = (8*x + 4*x +2*x + x)>>3 =\n\t;     = ( x * ( 8 + 4 + 2 + 1 )) >> 3 = ( x * 15 ) >> 3 \n\tlea\tecx,[ecx+ecx*2]\n\tlea\teax,[ecx+ecx*4]\n\tjmp\t??neg_save_dif\n\talign\t4\n\n??14:\n\t; eax = x + x / 2 + x / 8 = (8*x + 4*x + x) >> 3 =\n\t;     =\t( x * 8 + x * 5\t) >> 8\n\tlea\teax,[ecx+ecx*4]\n\tlea\teax,[eax+ecx*8]\n\tjmp\t??neg_save_dif\n\talign\t4\n\n??13:\n\t; eax = x + x / 4 + x / 8 = (8*x + 2*x + x) >> 3 = \n\t;     =\t( 8 * x + 3 * x) >> 3\n\tlea\teax,[ecx+ecx*2]\n\tlea\teax,[eax+ecx*8]\n\tjmp\t??neg_save_dif\n\talign\t4\n\n??12:\n\t; eax = x + x / 8 = (8*x + x) >> 3 = (x * 9)>> 3\n\tlea\teax,[ecx+ecx*8]\n\tjmp\t??neg_save_dif\n\talign\t4\n\n??11:\n\t; eax = x/2 + x/4 + x/8 = (4*x + 2*x + x) >> 3\n\t;     =\t( 4*x - 3*x ) >> 3\n\tlea\teax,[ecx+ecx*2]\n\tlea\teax,[eax+ecx*4]\n\tjmp\t??neg_save_dif\n\talign\t4\n\n??10:\n\t; eax = x/2 + x/8 = (4*x + x) >> 3\n\tlea\teax,[ecx+ecx*4]\n\tjmp\t??neg_save_dif\n\talign\t4\n\n??9:\n\t; eax = x/4 + x/8 = (2x + x )>>8\n\tlea\teax,[ecx+ecx*2]\n\tjmp\t??neg_save_dif\n\talign\t4\n\n??8:\n\t; eax = x/8 = x >> 3\n\tmov\teax,ecx\t\t       ; !!important!! no need for align here\t\n\n??neg_save_dif:\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tneg \teax\n\n??save_dif:\n \tmov\tecx,[wCode]\t\t\t    ; load offset into CODETab table\t\n\tmov\t[(sCompInfo ebx).dwDifference],eax  ;Store wStep\n\n\t; add difference to predicted value.\n\tadd\teax,[(sCompInfo ebx).dwPredicted]\n\n\t; make sure there is no under or  overflow.\n\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflow\n\tmov\teax,7FFFh\n\n??noOverflow:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflow\n\tmov\teax,0FFFF8000h\n\n??noUnderflow:\n\tadd\tedx,[wCODECIndexTab + ecx*4]\t  ; won't hurt 486 \t\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tmov\t[(sCompInfo ebx).dwPredicted],eax\n\tmov\tecx,[(sCompInfo ebx).dwSampleIndex] ;load dwSampleindex\n\tje\tshort ??output16Bit\n\t; output 8 bit sample\n\txor\tah,80h\n\tmov\t[edi],ah\n\tinc\tedi\n\tjmp\tshort ??adjustIndex\n\talign\t4\n\n??output16Bit:\n\tmov\t[edi],ax\t\t\t  ;Output 16bit sample\n\tadd\tedi,2\n\n??adjustIndex:\n\tcmp\tedx,8000h\n\tjb\tshort ??checkOverflow\n\tmov\tedx,0\t\t\t\t;reset index to zero\n\n??checkOverflow:\n\tinc\tecx\t\t\t\t; advance index and store step value\n\tcmp\tedx,88\t\t\t\t;check if wIndex > 88\n\tjbe\tshort ??adjustStep\n\tmov\tedx,88\t\t\t\t;reset index to 88\n\n??adjustStep:\n\t; advance index and store step value\n\tmov\t[(sCompInfo ebx).dwSampleIndex],ecx\n\n\t; fetch wIndex so we can fetch new step value\n\tmov\teax,[wCODECStepTab + edx*4]\n\n\t; decrement bytes processed and loop back.\n\tdec\tebp\n\tmov\t[(sCompInfo ebx).wStep],ax\n\tjne\t??mainloop\n\tpop\tebp\n\n\tmov\teax,[wCode]\t\t\t; these three lines do not\n\tmov\t[(sCompInfo ebx).wCode],ax\t; seem to have any relevance\n\n\tmov\t[(sCompInfo ebx).wIndex],dx  \t; save index\n\tjmp\t??exitout\n\n;--------------------------------------------------------------------------\n;Left Channel Start\n;--------------------------------------------------------------------------\n\n\n??mainloopl:\n\ttest\t[(sCompInfo ebx).dwSampleIndex],1\n\tje\tshort ??fetchTokenl\n\t\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCodeBuf]\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\tjmp\tshort ??calcDifferencel\n\n??fetchTokenl:\n\txor\teax,eax\n\tmov\tal,[esi]\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\n\tadd\tesi,2\t\t\t\t\t;2 for stereo\t\t\t\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\n??calcDifferencel:\n\t\t\t\t\t\t\t; reset difference\n\n\tmov\t[(sCompInfo ebx).dwDifference],0\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep]\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4l\n\tadd\t[(sCompInfo ebx).dwDifference],ecx\t;Add wStep\n\n??no4l:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2l\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no2l:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1l\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no1l:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8l\n\tneg\t[(sCompInfo ebx).dwDifference]\t\t;Negate diff\n\n??no8l:\n\t\t; add difference to predicted value.\n\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\n\tadd\teax,[(sCompInfo ebx).dwDifference]\n\n\t\t; make sure there is no under or  overflow.\n\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowl\n\tmov\teax,7FFFh\n\n??noOverflowl:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowl\n\tmov\teax,0FFFF8000h\n\n??noUnderflowl:\n\tmov\t[(sCompInfo ebx).dwPredicted],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bitl\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,4\t\t\t\t\t;4 for stereo\t\t\n\tjmp\tshort ??adjustIndexl\n\n??output8Bitl:\n\t; output 8 bit sample\n\n\txor\tah,80h\n\tmov\t[edi],ah\n\tadd\tedi,2\t\t\t\t\t;2 for stereo       \n\n??adjustIndexl:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode]\n\txor\teax,eax\n\tshl\tecx,2\n\tmov\teax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex],ax\n\t\t\t\t\t\t\t; check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex],8000h\n\tjb\tshort ??checkOverflowl\n\tmov\t[(sCompInfo ebx).wIndex],0\n\tjmp\tshort ??adjustStepl\t\t\t;reset index to zero\n\n\n??checkOverflowl:\n\t\t\t\t\t\t\t\n\tcmp\t[(sCompInfo ebx).wIndex],88\t\t; check if wIndex > 88\n\tjbe\tshort ??adjustStepl\n\tmov\t[(sCompInfo ebx).wIndex],88\t\t; reset index to 88\n\n??adjustStepl:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex]\n\txor\teax,eax\n\tshl\tecx,2\n\tmov\teax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex],1\n\tmov\t[(sCompInfo ebx).wStep],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2\n\tjne\t??mainloopl\n;----------------------------------------------------------------------------\n; Right Side Setup\n;----------------------------------------------------------------------------\n\tmov\teax,[wBytes]\n\tmov\t[dwCODECBytesProcessed],eax\n\tmov\tesi,[(sCompInfo ebx).lpSource]\n\tmov\tedi,[(sCompInfo ebx).lpDest]\n\tinc\tesi\t\t\t\t\t; skip left channel\n\tinc\tedi\t\t\t\t     \t; skip left channel\n\tcmp\t[(sCompInfo ebx).wBitSize],16\t\t;16 bit ??\n\tje\tshort ??doByteDivide\t\t\t\n\tmov\t[dwCODECByteIndex],eax\n\tjmp  short ??mainloopr\n\t\n??doByteDivide:\n\tshr\teax,1 \t\t\t\t\t;Divide size by two\n\tinc\tedi   \t\t\t\t\t; 16 bit so skip 1 more\n\tmov\t[dwCODECByteIndex],eax\n\t\n\n;--------------------------------------------------------------------------\n;Right Channel Start\n;--------------------------------------------------------------------------\n\n\n??mainloopr:\t \n\ttest\t[(sCompInfo ebx).dwSampleIndex2],1\n\tje\tshort ??fetchTokenr\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCodeBuf2]\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode2],ax\n\tjmp\tshort ??calcDifferencer\n\n??fetchTokenr:\n\txor\teax,eax\n\tmov\tal,[esi]\n\tmov\t[(sCompInfo ebx).wCodeBuf2],ax\n\tadd\tesi,2\t\t\t\t     \t;2 for stereo\t\t\t\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode2],ax\n\n??calcDifferencer:\n\t\t\t\t\t\t\t; reset difference\n\n\tmov\t[(sCompInfo ebx).dwDifference2],0\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep2]\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4r\n\tadd\t[(sCompInfo ebx).dwDifference2],ecx\t;Add wStep\n\n??no4r:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2r\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\n??no2r:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1r\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\n??no1r:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8r\n\tneg\t[(sCompInfo ebx).dwDifference2]\t\t;Negate diff\n\n??no8r:\n\t; add difference to predicted value.\n\tmov\teax,[(sCompInfo ebx).dwPredicted2]\n\tadd\teax,[(sCompInfo ebx).dwDifference2]\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowr\n\tmov\teax,7FFFh\n\n??noOverflowr:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowr\n\tmov\teax,0FFFF8000h\n\n??noUnderflowr:\n\tmov\t[(sCompInfo ebx).dwPredicted2],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bitr\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,4\t\t\t\t\t;4 for stereo\t\t***\n\tjmp\tshort ??adjustIndexr\n\n??output8Bitr:\n\t\t\t\t\t\t\t; output 8 bit sample\n\txor\tah,80h\n\tmov\t[edi],ah\n\tadd\tedi,2\t\t\t\t\t;2 for stereo       \n\n??adjustIndexr:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode2]\n\txor\teax,eax\n\tshl\tecx,2\n\tmov\teax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex2],ax\n\t\t\t\t\t\t\t; check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex2],8000h\n\tjb\tshort ??checkOverflowr\n\t\t\t\t\t\t\t; reset index to zero\n\tmov\t[(sCompInfo ebx).wIndex2],0\n\tjmp\tshort ??adjustStepr\n\n??checkOverflowr:\n\t\t\t\t\t\t\t; check if wIndex > 88\n\tcmp\t[(sCompInfo ebx).wIndex2],88\t        \n\tjbe\tshort ??adjustStepr\n\tmov\t[(sCompInfo ebx).wIndex2],88\t\t; reset index to 88\n\n??adjustStepr:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex2]\n\txor\teax,eax\n\tshl\tecx,2\n\tmov\teax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex2],1\n\tmov\t[(sCompInfo ebx).wStep2],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2\n\tjne\t??mainloopr\n\t\n\n??exitout:\n;     \tdon't think we need this but just in case i'll leave it here!!\n\n;\tmov\t[(sCompInfo ebx).lpSource],esi\n;\tmov\t[(sCompInfo ebx).lpDest],edi\n\t; set up return value for number of bytes processed.\n\tmov\teax,[dwCODECBytesProcessed]\n\tpop\tedx\n\tpop\tecx\n\tpop\tebx\n\tpop\tedi\n\tpop\tesi\n\tret\n\nJumpTable\tDD\t??0\n\t\tDD\t??1\n\t\tDD\t??2\n\t\tDD\t??3\n\t\tDD\t??4\n\t\tDD\t??5\n\t\tDD\t??6\n\t\tDD\t??7\n\t\tDD\t??8\n\t\tDD\t??9\n\t\tDD\t??10\n\t\tDD\t??11\n\t\tDD\t??12\n\t\tDD\t??13\n\t\tDD\t??14\n\t\tDD\t??15\n\t\t\t \n\n\tENDP\tsosCODECDecompressData\n\nLABEL\tLockedCodeEnd\tBYTE\n\n;***************************************************************************\n;* sosCODEC_LOCK -- locks the JLB audio decompression code\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is lock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:       BOOL sosCODEC_Lock(void);                         \t   *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tsosCODEC_Lock:NEAR\n\tPROC\tsosCODEC_Lock C NEAR USES ebx ecx edx esi edi\n\n\t;\n\t; Lock the code that is used by the sos decompression method.\n\t;\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n  \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags], IF_LOCKED_PM_CODE\n\n\t;\n\t; Lock the data used by the sos decompression method.\n\t;\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags], IF_LOCKED_PM_DATA\n\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\tENDP\tsosCODEC_Lock\n\n;***************************************************************************\n;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code       *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is unlock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:\tBOOL sosCODEC_Unlock(void);                        \t   *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tsosCODEC_Unlock:NEAR\n\tPROC\tsosCODEC_Unlock C NEAR USES ebx ecx edx esi edi\n\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\n??code_not_locked:\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??data_not_locked:\n\tmov\t[InitFlags],0\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\tENDP\tsosCODEC_Unlock\n\n\tEND\n\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/SOSCOMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*  File              : soscomp.h\n*  Date Created      : 6/1/94\n*  Description       : \n*\n*  Programmer(s)     : Nick Skrepetos\n*  Last Modification : 10/1/94 - 11:37:9 AM\n*  Additional Notes  : Modified by Denzil E. Long, Jr.\n*\n*****************************************************************************\n*            Copyright (c) 1994,  HMI, Inc.  All Rights Reserved            *\n****************************************************************************/\n\n#ifndef  _SOS_COMPRESS\n#define  _SOS_COMPRESS\n\n/* compression types */\nenum {\n\t_ADPCM_TYPE_1,\n\t};\n\n/* define compression structure */\ntypedef struct _tagCOMPRESS_INFO {\n\tchar       *lpSource;\n\tchar       *lpDest;\n\tunsigned long dwCompSize;\n\tunsigned long dwUnCompSize;\n\tunsigned long dwSampleIndex;\n\tlong          dwPredicted;\n\tlong          dwDifference;\n\tshort         wCodeBuf;\n\tshort         wCode;\n\tshort         wStep;\n\tshort         wIndex;\n\n\tunsigned long dwSampleIndex2; //added BP for channel 2\n\tlong          dwPredicted2;   //added BP for channel 2\n\tlong          dwDifference2; \t//added BP for channel 2\n\tshort         wCodeBuf2; \t\t//added BP for channel 2\n\tshort         wCode2; \t\t\t//added BP for channel 2\n\tshort         wStep2; \t\t\t//added BP for channel 2\n\tshort         wIndex2; \t\t\t//added BP for channel 2\n\tshort         wBitSize;\n\tshort\t\t\t  wChannels;\t\t//added BP for # of channels\n\t} _SOS_COMPRESS_INFO;\n\n/* compressed file type header */\ntypedef struct _tagCOMPRESS_HEADER {\n\tunsigned long dwType;              // type of compression\n\tunsigned long dwCompressedSize;    // compressed file size\n\tunsigned long dwUnCompressedSize;  // uncompressed file size\n\tunsigned long dwSourceBitSize;     // original bit size\n\tchar          szName[16];          // file type, for error checking\n\t} _SOS_COMPRESS_HEADER;\n\n/* Prototypes */\nextern \"C\" {\n\tvoid sosCODECInitStream(_SOS_COMPRESS_INFO *);\n\tunsigned long sosCODECCompressData(_SOS_COMPRESS_INFO *,\tunsigned long);\n\tunsigned long sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);\n}\n\n#endif\n\u001a\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/SOSDATA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdata.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DATA\n#define  _SOS_DATA\n\n#include <stddef.h>\n\n#pragma pack(4) \nextern   WORD     _sosDIGIData_Start;\nextern   WORD     _sosDIGIData_End;\nextern   WORD     _wSOSDriverLinear[];\nextern   WORD     _wSOSTimerLinear[];\nextern   LPSTR    _lpSOSDriver[];\nextern   LPSTR    _lpSOSTimer[];\nextern   LPSTR    _lpSOSDriverCS[];\nextern   LPSTR    _lpSOSTimerCS[];\nextern   BOOL     _wSOSDriverLoaded[];\nextern   BOOL     _wSOSTimerLoaded[];\nextern   BOOL     _wSOSDriverInitialized[];\nextern   WORD     _wSOSOutputRate[];\nextern   WORD     _wSOSDMABuffersize[];\nextern   LONG     _dwSOSDMABufferPhysical[];\nextern   LPSTR    _lpSOSDMABuffer[];\nextern   BOOL     _wTimerUsed;\nextern   VOID ( far *_lpSOSFillHandler[] )( VOID );\nextern   WORD     _wSOSTimerType[];\nextern   WORD     _wSOSDriverType[];\nextern   _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ];\nextern   LPWORD      _lpSOSDMAIrqCount[];\nextern   LPWORD      _lpSOSDMAFillCount[];\nextern   WORD        _wSOSTmrNextCount;\nextern   VOID ( interrupt far *_lpSOSOldTimer )( VOID );\nextern   WORD     _wSOSDriverID[];\nextern   _SOS_CAPABILITIES _sSOSDriverCaps[];\nextern   WORD        _wSOSDMAPortList[];\nextern   BYTE        _bSOSDMAChannel[];\nextern   _SOS_INIT_DRIVER     _sSOSDIGIInitDriver[];\nextern   BYTE  _pSOSDriverPath[];\nextern   BYTE  _pSOSTempDriverPath[];\nextern   BOOL  _wTIMERUsed;\nextern   WORD  _wTIMERValue;\nextern   VOID ( far * _lpTIMEREvents[] )( VOID );\nextern   WORD _wTIMEREventRate[];\nextern   WORD _dwTIMEREventFraction[];\nextern   WORD _dwTIMEREventFractionCurrent[];\nextern   BYTE  _bSOSMIDITimerSongHandler[];\nextern   BYTE  _bSOSMIDISongHandle;\nextern   WORD  _wSOSTimerMemHandle[];\nextern   WORD  _wSOSDriverMemHandle[];\nextern   WORD  _wSOSRealSeg[];\n\nextern   _FILEHEADER    _sDETFileHeader;\nextern   _DRIVERHEADER  _sDETDriverHeader;\nextern   _FILEHEADER    sLOADFileHeader;\nextern   _DRIVERHEADER  sLOADDriverHeader;\nextern   BOOL           _wDETInitialized;\nextern   WORD           _wDETLinear;\nextern   LPSTR          _lpDETDriverBuffer;    \nextern   LPSTR          _lpDETDriverBufferCS;\nextern   WORD           _hDETFile;\nextern   DWORD          _dwDETDriverIndex;\nextern   WORD           _wDETDriverIndexCur;\nextern   WORD           _wDETMemHandle;\nextern   LPSOSDEVICECAPS _lpDETDeviceCaps;\nextern   _SOS_CAPABILITIES _sDETCaps;  \nextern   PSTR _pSOSErrorStrings[];\nextern   BOOL _wSOSBufferAllocated[];\nextern   BOOL _wSOSSystemInitialized;\nextern   VDS_STRUCT _sSOSVDSInfo;\nextern   _SOS_FILL_INFO _sSOSFillInfo;\nextern   WORD    _wSOSTimerEventIndex;\nextern   WORD  _wSOSTimerEntered;\nextern   WORD  _wSOSDriverSize[];\nextern   WORD  _wSOSTimerSize[];\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nextern   WORD  _sosDIGIData1_Start;\nextern   WORD  _sosDIGIData1_End;\nextern   WORD  _sosDIGIData2_Start;\nextern   WORD  _sosDIGIData2_End;\nextern   BYTE  _bTIMERInstalled;\nextern   BYTE  _bTIMERDPMI;\nextern   WORD  wDetectPort;\nextern   WORD  wDetectIRQ;\nextern   WORD  wDetectDMA;\nextern   WORD  wDetectParam;\n#ifdef __cplusplus\n}\n#endif \n\n#pragma pack()\n\n#endif\n\u001a\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/SOSDEFS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdefs.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n\n#ifndef  _SOSDEFS_DEFINED\n#define  _SOSDEFS_DEFINED\n\n#undef   _TRUE\n#undef   _FALSE\n#undef   _NULL\nenum  \n      { \n         _FALSE, \n         _TRUE \n      };\n\n#define  _NULL  0\n\n#ifndef  VOID\n#define  VOID           void\n#endif\ntypedef  int            BOOL;\ntypedef  unsigned int   UINT;\ntypedef  unsigned char  BYTE;\ntypedef  unsigned       WORD;\n#ifndef  LONG\ntypedef  signed long    LONG;\n#endif\ntypedef  unsigned long  DWORD;\n\ntypedef  BYTE  *        PBYTE;\ntypedef  char near *    PSTR;\ntypedef  WORD  *        PWORD;\ntypedef  LONG  *        PLONG;\ntypedef  VOID  *        PVOID;\n\ntypedef  BYTE  far   *  LPBYTE;\ntypedef  BYTE  far   *  LPSTR;\ntypedef  WORD  far   *  LPWORD;\ntypedef  LONG  far   *  LPLONG;\ntypedef  VOID  far   *  LPVOID;\n\ntypedef  BYTE  huge  *  HPBYTE;\ntypedef  BYTE  huge  *  HPSTR;\ntypedef  WORD  huge  *  HPWORD;\ntypedef  LONG  huge  *  HPLONG;\ntypedef  VOID  huge  *  HPVOID;\n\ntypedef  unsigned       HANDLE;\n\n#endif\n\u001a\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/SOSFNCT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosfnct.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_FUNCTIONS\n#define  _SOS_FUNCTIONS\n\n#pragma pack(4)\n\nWORD sosDIGILockMemory          (  VOID  );\nWORD sosDIGIUnLockMemory        (  VOID  );\nWORD sosDIGIInitSystem           (  LPSTR, WORD  );\nWORD sosDIGIUnInitSystem         (  VOID  );\nWORD sosDIGIInitDriver           (  WORD, _SOS_HARDWARE far *,\n                                    _SOS_INIT_DRIVER far *, WORD far *   );\nWORD sosDIGIUnInitDriver         (  WORD, BOOL, BOOL  );\nWORD sosDIGILoadDriver          (  WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD sosDIGIUnLoadDriver         (  WORD  );\nWORD sosDIGIGetDeviceCaps        (  WORD, LPSOSDEVICECAPS  );\n\n#ifdef PHARLAP\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#else\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#endif\n\nWORD sosDIGIStopSample           (  WORD, WORD  );\nWORD sosDIGISamplesPlaying       (  WORD  );\nBOOL sosDIGISampleDone           (  WORD, WORD  );\nBOOL sosDIGISampleFilling        (  WORD, WORD  );\nWORD sosDIGIStartSample          (  WORD, _SOS_START_SAMPLE far *  );\nWORD sosDIGIContinueSample       (  WORD, WORD, _SOS_START_SAMPLE far * );\n\n\nWORD  sosDIGIDetectInit          (  LPSTR  );\nWORD  sosDIGIDetectUnInit        (  VOID  );\nWORD  sosDIGIDetectFindHardware  (  WORD, _SOS_CAPABILITIES far *, WORD far * );\nWORD  sosDIGIDetectFindFirst     (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectFindNext      (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectGetSettings   (  _SOS_HARDWARE far *  );\nWORD  sosDIGIDetectGetCaps       (  WORD, _SOS_CAPABILITIES far *  );\nWORD  sosDIGIDetectVerifySettings(  _SOS_HARDWARE far *  );\nPSTR  sosGetErrorString          (  WORD  );\n\nWORD  sosDIGILoadTimer           (  WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD  sosDIGIUnLoadTimer         (  WORD  );\n\nWORD  sosTIMERRegisterEvent      ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle );\nWORD  sosTIMERInitSystem               (  WORD, WORD  );\nWORD  sosTIMERUnInitSystem             (  WORD  );\nWORD  sosTIMERSetRate                  (  WORD  );  \nWORD  sosTIMERRemoveEvent              (  WORD );\nWORD  sosTIMERAlterEventRate           (  WORD, WORD  );\nWORD  sosTIMERGetEventRate             (  WORD  );\nVOID far sosTIMEROldHandler            (  VOID  );\nVOID far sosTIMERHandler               (  VOID  );\n\n// functions in soscntl.c\nWORD  sosDIGISetSampleVolume     ( WORD, WORD, WORD );\nWORD  sosDIGIGetSampleVolume     ( WORD, WORD );\nWORD  sosDIGISetChannel          ( WORD, WORD, WORD );\nWORD  sosDIGIGetChannel          ( WORD, WORD );\nWORD  sosDIGIGetBytesProcessed   ( WORD, WORD );\nWORD  sosDIGIGetLoopCount        ( WORD, WORD );\nWORD  sosDIGISetPanLocation      ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanLocation      ( WORD, WORD );\nDWORD sosDIGISetPitch            ( WORD, WORD, DWORD );\nDWORD sosDIGIGetPitch            ( WORD, WORD );\nWORD  sosDIGIGetDMAPosition      ( WORD );\nWORD  sosDIGISetPanSpeed         ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanSpeed         ( WORD, WORD );\nWORD  sosDIGIGetSampleID         ( WORD, WORD );\nWORD  sosDIGIGetSampleHandle     ( WORD, WORD );\nWORD  sosDIGISetMasterVolume     ( WORD, WORD );\n#ifdef PHARLAP\nVOID  sosFreeVDSPage          ( unsigned short, unsigned short, DWORD );\nWORD  sosAllocVDSPage         ( unsigned short *, unsigned short *, DWORD * );\n#else\nWORD  sosAllocVDSPage            ( LPSTR *, WORD *, WORD * );\nVOID  sosFreeVDSPage             ( WORD, WORD, LONG );\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef PHARLAP\nextern   int   cdecl sosRealFree          ( int );\nextern   BOOL  cdecl  _sos_read( WORD, LPSTR, WORD, WORD * );\nextern   int   cdecl sosRealAlloc( int, int *, int * );\nextern   void  cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD );\nextern   int   cdecl sosGetCS( VOID );\nextern   int   cdecl sosGetES( VOID );\n#else\nextern   int   cdecl sosRealAlloc         ( int, int *, int * );\nextern   int   cdecl sosRealFree          ( int );\n#endif\n\n// sos driver functions\nextern   WORD  cdecl sosDRVLockMemory     ( DWORD, DWORD );\nextern   WORD  cdecl sosDRVUnLockMemory   ( DWORD, DWORD );\nextern   void  cdecl sosDRVGetCapsInfo    ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVGetCapsPtr     ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVInit           ( LPSTR, LPSTR, int, int, int, int, int, int );  \nextern   void  cdecl sosDRVStart          ( LPSTR, LPSTR, int, int );\nextern   void  cdecl sosDRVSetRate        ( LPSTR, LPSTR, int );\nextern   void  cdecl sosDRVSetAction      ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVStop           ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVUnInit         ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVGetFillInfo    ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * );\nextern   void  cdecl sosFillSampleStructs ( PSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVExist       ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVGetSettings ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR );\nextern   WORD  cdecl sosDIGIInitForWindows( WORD );\nextern   WORD  cdecl sosDIGIUnInitForWindows( WORD );\nextern   LPSTR cdecl sosAllocateFarMem      ( WORD, PSTR, WORD * );\nextern   LPSTR cdecl sosCreateAliasCS       ( LPSTR );\nextern   VOID  cdecl sosFreeSelector        ( LPSTR, DWORD );\nextern   LPSTR cdecl sosMAKEDOSPtr          ( PSTR );\nextern   VOID  cdecl sosDetDRVSetEnvString  ( DWORD, PSTR );\nextern   PSTR  cdecl sosDetDRVGetEnvString  ( DWORD );\nextern   VOID  cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR );\nextern   VOID  cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR );\nextern   WORD  cdecl sosDRVGetFreeMemory     ( VOID );\nextern   WORD  cdecl sosDRVAllocVDSStruct    ( WORD, WORD *, WORD * );\nextern   WORD  cdecl sosDRVFreeVDSStruct     ( WORD, WORD );\nextern   WORD  cdecl sosDRVIsWindowsActive   ( VOID );\nextern   WORD  cdecl sosDRVVDSGetBuffer    ( WORD );\nextern   WORD  cdecl sosDRVVDSFreeBuffer   ( WORD );\nextern   WORD  cdecl getDS( VOID );\nextern   WORD  cdecl sosDRVMakeDMASelector   ( WORD );  \nextern   WORD  cdecl sosDRVFreeDMASelector   ( WORD );  \n\n\nextern   void  cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) );\nextern   void  cdecl sosTIMERDRVUnInit( void );\nextern   void  cdecl sosTIMERDRVHandler( void );\nextern   void  cdecl sosTIMERDRVFHandler( void );\nextern   void  cdecl sosTIMERDRVEnable( void );\nextern   void  cdecl sosTIMERDRVDisable( void );\nextern   void  cdecl sosTIMERDRVCallOld( void );\nextern   void  cdecl sosTIMERDRVSetRate( WORD );    \nextern   void  cdecl sosDIGITimer_Start( void );\nextern   void  cdecl sosDIGITimer_End( void );\nextern   void  cdecl sosDIGIDrv_Start( void );\nextern   void  cdecl sosDIGIDrv_End( void );\n#ifdef __cplusplus\n}\n#endif \n\n// external functions for handling system initialization and \n// uninitialization\nWORD  sosEXDIGInitDriver               (  WORD, WORD, WORD, LPSTR,\n                                          _SOS_HARDWARE far *, WORD *  );\nWORD  sosEXDIGIUnInitDriver            (  VOID  );\n\nWORD  sosEXDETFindDriver               (  WORD, LPSTR, _SOS_HARDWARE far *,\n                                          _SOS_CAPABILITIES far *  );\n\n// memory locking prototypes\nVOID  sosDIGICaps_Start( VOID );\nVOID  sosDIGICaps_End( VOID );\nVOID  sosDIGIErr_Start( VOID );\nVOID  sosDIGIErr_End( VOID );\nVOID  sosDIGITmr_Start( VOID );\nVOID  sosDIGITmr_End( VOID );\nVOID  sosDIGIStart_Start( VOID );\nVOID  sosDIGIStart_End( VOID );\nVOID  sosDIGIPlyng_Start( VOID );\nVOID  sosDIGIPlyng_End( VOID );\nVOID  sosDIGIRate_Start( VOID );\nVOID  sosDIGIRate_End( VOID );\nVOID  sosDIGIDone_Start( VOID );\nVOID  sosDIGIDone_End( VOID );\nVOID  sosDIGIDetec_Start( VOID );\nVOID  sosDIGIDetec_End( VOID );\nVOID  sosDIGIInit_Start( VOID );\nVOID  sosDIGIInit_End( VOID );\nVOID  sosDIGILoad_Start( VOID );\nVOID  sosDIGILoad_End( VOID );\nVOID  sosDIGICntl_Start( VOID );\nVOID  sosDIGICntl_End( VOID );\n\n#pragma pack()\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/SOSRES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosres.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#define  _SOS_RESOURCE\n#ifndef  _SOS_RESOURCE\n#define  _SOS_RESOURCE\n\n// structure for resource file header\ntypedef struct\n{\n   // file version\n   WORD     wVersion;\n\n   // file size\n   LONG     dwFileSize;\n\n   // number of resources in file\n   WORD     wResCount;\n\n   // offset of resource data from top of file\n   LONG     dwResOffset;\n\n   // offset of sync track from top of file\n   LONG     dwSyncTrackOffset;\n\n}  _RES_FILE_HEADER;\n\n// structure for resource block header\ntypedef struct\n{\n   // resource id\n   WORD     wID;\n\n   // resource type\n   WORD     wResType;\n\n   // offset of next block\n   LONG     dwNextBlock; \n\n   // size of the current resource information\n   LONG     dwResSize;\n\n   // rate to play block at\n   WORD     wBlockRate;\n\n   // id for the sync track to use\n   WORD     wSyncTrackID;\n\n}  _RES_BLOCK_HEADER;\n\n// structure for sync mark tag\ntypedef struct _tagSYNCMARK\n{\n   // ID of the type of mark being used\n   WORD  wID;\n\n   // location in data of sync mark\n   LONG  dwSyncOffset;\n\n   // length of sync block\n   LONG  dwSyncSize;\n\n   // start sample data\n   _SOS_START_SAMPLE sampleData;\n    \n} _RES_SYNCMARK;\n\ntypedef union\n{\n   // structure for sync mark tag\n   _RES_SYNCMARK  syncMark; \n\n} _RES_TAG;\n\n// union for filter information for prepareWave\ntypedef union\n{\n   // filter type\n   WORD     wFilterID;\n\n   // structure for volume\n   struct   volume \n   {\n      WORD  wVolume;\n   };\n\n   // structure for delay\n   struct   delay\n   {  \n      WORD  wDelaySamples;\n   };\n\n} _SOS_FILTER; \n\n \n#endif\n\n\u001a"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/SOUND.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : SOUND.H                                  *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : September 1, 1993                        *\n *                                                                         *\n *                  Last Update : September 1, 1993   [JLB]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SOUND_H\n#define SOUND_H\n\n#define\tHMI_DRIVER\tTRUE\n#include\t\"sos.h\"\n#include\t\"soscomp.h\"\n\n/*\n**\tMaximum number of sound effects that may run at once.\n*/\n#define\tMAX_SFX\t\t4\n\n/*\n** Size of temp HMI low memory staging buffer.\n*/\n#define\tSFX_MINI_STAGE_BUFFER_SIZE\t\t(1024*4)\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/SOUND.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : SOUND.H                                  *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : September 1, 1993                        *\n *                                                                         *\n *                  Last Update : September 1, 1993   [JLB]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SOUND_H\n#define SOUND_H\n\n#define\tHMI_DRIVER\tTRUE\n#include\t\"sos.h\"\n#include\t\"soscomp.h\"\n\n/*\n**\tMaximum number of sound effects that may run at once.\n*/\n#define\tMAX_SFX\t\t5\n\n/*\n** Size of temp HMI low memory staging buffer.\n*/\n#define\tSFX_MINI_STAGE_BUFFER_SIZE\t\t(1024*4)\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/SOUNDINT.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDINT.H                               *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 23, 1995   [PWG]                    *\n *                                                                         *\n * This file is the include file for the Westwood Sound Sytem defines and  *\n * routines that are handled in an interrupt.\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"sound.h\"\n\n/*\n** Defines for true and false.  These are included because we do not allow\n** the sound int to include any of the westwood standard headers.  If we\n** did, there might be too much temptation to call another library function.\n** this would be bad, because then that function would not be locked.\n*/\n#define\tFALSE\t\t0\n#define\tTRUE\t\t1\n\n/*\n** Define the different type of sound compression avaliable to the westwood\n** library.\n*/\ntypedef enum {\n\tSCOMP_NONE=0,\t\t\t// No compression -- raw data.\n\tSCOMP_WESTWOOD=1,\t\t// Special sliding window delta compression.\n\tSCOMP_SONARC=33,\t\t// Sonarc frame compression.\n\tSCOMP_SOS=99\t\t\t// SOS frame compression.\n} SCompressType;\n\n/*\n**\tThis is the safety overrun margin for the sonarc compressed\n** data frames.  This value should be equal the maximum 'order' times\n**\tthe maximum number of bytes per sample.  It should be evenly divisible\n**\tby 16 to aid paragraph alignment.\n*/\n#define\tSONARC_MARGIN\t\t\t\t32\n\n\n/*\n** Define the sample control structure which helps us to handle feeding\n** data to the sound interrupt.\n*/\n#pragma pack(1);\ntypedef struct {\n\t/*\n\t**\tThis flags whether this sample structure is active or not.\n\t*/\n\tunsigned Active:1;\n\n\t/*\n\t**\tThis flags whether the sample is loading or has been started.\n\t*/\n\tunsigned Loading:1;\n\n\t/*\n\t**\tThis semaphore ensures that simultaneous update of this structure won't\n\t**\toccur.  This is necessary since both interrupt and regular code can modify\n\t**\tthis structure.\n\t*/\n\tunsigned DontTouch:1;\n\n\t/*\n\t**\tIf this sample is really to be considered a score rather than\n\t**\ta sound effect, then special rules apply.  These largely fall into\n\t**\tthe area of volume control.\n\t*/\n\tunsigned IsScore:1;\n\n\t/*\n\t**\tThis is the original sample pointer. It is used to control the sample based on\n\t**\tpointer rather than handle. The handle method is necessary when more than one\n\t**\tsample could be playing simultaneously. The pointer method is necessary when\n\t**\tthe dealing with a sample that may have stopped behind the programmer's back and\n\t**\tthis occurance is not otherwise determinable.  It is also used in\n\t** conjunction with original size to unlock a sample which has been DPMI\n\t** locked.\n\t*/\n\tvoid const *Original;\n\tlong OriginalSize;\n\n\t/*\n\t**\tThese are pointers to the double buffers in low ram.\n\t*/\n\tVOID *Buffer[2];\n\n\t/*\n\t**\tThe number of bytes in the buffer that has been filled but is not\n\t**\tyet playing.  This value is normally the size of the buffer,\n\t**\texcept for the case of the last bit of the sample.\n\t*/\n\tLONG DataLength;\n\n\t/*\n\t**\tThis is the buffer index for the low buffer that\n\t**\thas been filled with data but not yet being\n\t**\tplayed.\n\t*/\n\tWORD Index;\n\n\t/*\n\t**\tPointer to the sound data that has not yet been copied\n\t**\tto the playback buffers.\n\t*/\n\tVOID *Source;\n\n\t/*\n\t**\tThis is the number of bytes remaining in the source data as\n\t**\tpointed to by the \"Source\" element.\n\t*/\n\tLONG Remainder;\n\n\t/*\n\t**\tSamples maintain a priority which is used to determine\n\t**\twhich sounds live or die when the maximum number of\n\t**\tsounds are being played.\n\t*/\n\tWORD Priority;\n\n\t/*\n\t**\tThis is the handle as returned by sosDIGIStartSample function.\n\t*/\n\tWORD Handle;\n\n\t/*\n\t**\tThis is the current volume of the sample as it is being played.\n\t*/\n\tWORD Volume;\n\tWORD Reducer;\t\t// Amount to reduce volume per tick.\n\n\t/*\n\t**\tThis flags whether the sample is in stereo.\n\t*/\n\tWORD Stereo;\n\n\t/*\n\t**\tThis is the compression that the sound data is using.\n\t*/\n\tSCompressType Compression;\n\tWORD TrailerLen;\t\t\t\t\t\t// Number of trailer bytes in buffer.\n\tBYTE Trailer[SONARC_MARGIN];\t\t// Maximum number of 'order' samples needed.\n\n\n\tDWORD Pitch;\n\tWORD Flags;\n\n\t/*\n\t**\tThis flag indicates whether this sample needs servicing.  \n\t**\tServicing entails filling one of the empty low buffers.\n\t*/\n\tWORD Service;\n\n\t/*\n\t**\tThis flag is TRUE when the sample has stopped playing,\n\t**\tBUT there is more data available.  The sample must be\n\t**\trestarted upon filling the low buffer.\n\t*/\n\tBOOL Restart;\n\n\t/*\n\t**\tStreaming control handlers.\n\t*/\n\tBOOL (*Callback)(WORD id, WORD *odd, VOID **buffer, LONG *size);\n\tVOID\t*QueueBuffer;\t// Pointer to continued sample data.\n\tLONG\tQueueSize;\t\t// Size of queue buffer attached.\n\tWORD\tOdd;\t\t\t\t// Block number tracker (0..StreamBufferCount-1).\n\tint\tFilePending;\t// Number of buffers already filled ahead.\n\tlong\tFilePendingSize;\t// Number of bytes in last filled buffer.\n\n\t/*\n\t**\tThe file variables are used when streaming directly off of the \n\t**\thard drive.\n\t*/\n\tWORD\tFileHandle;\t\t// Streaming file handle (ERROR = not in use).\n\tVOID\t*FileBuffer;\t// Temporary streaming buffer (allowed to be freed).\n\t/*\n\t** The following structure is used if the sample if compressed using\n\t** the sos 16 bit compression Codec.\n\t*/\n\t_SOS_COMPRESS_INFO sosinfo;\n\n} SampleTrackerType;\n\n\ntypedef struct LockedData {\n\tunsigned int \t\tDigiHandle; \t\t\t// = -1;\n\tBOOL \t\t\t\t\tServiceSomething;\t\t// = FALSE;\n\tlong \t\t\t\t\tMagicNumber; \t\t\t// = 0xDEAF;\n\tVOID \t\t\t\t\t*UncompBuffer;\t\t\t// = NULL;\n\tlong \t\t\t\t\tStreamBufferSize; \t// = (2*SFX_MINI_STAGE_BUFFER_SIZE)+128;\n\tshort \t\t\t\tStreamBufferCount; \t// = 32;\n\tSampleTrackerType SampleTracker[MAX_SFX];\n\tunsigned int\t\tSoundVolume;\n\tunsigned int\t\tScoreVolume;\n\tBOOL\t\t\t\t\t_int;\n\tint\t\t\t\t\tMaxSamples;\t\t\t\t\n\tint\t\t\t\t\tRate;\t\t\t\t\n} LockedDataType;\n\nextern LockedDataType LockedData;\n#pragma pack(4);\n\nvoid Init_Locked_Data(void);\nvoid Unlock_Locked_Data(void);\nlong Simple_Copy(void ** source, long * ssize, void ** alternate, long * altsize, void **dest, long size);\nlong Sample_Copy(SampleTrackerType *st, void ** source, long * ssize, void ** alternate, long * altsize, void * dest, long size, SCompressType scomp, void * trailer, WORD *trailersize);\nVOID far cdecl maintenance_callback(VOID);\nVOID cdecl far DigiCallback(unsigned int driverhandle, unsigned int callsource, unsigned int sampleid);\nvoid far HMI_TimerCallback(void);\nvoid *Audio_Add_Long_To_Pointer(void const *ptr, long size);\nvoid\tDPMI_Unlock(VOID const *ptr, long const size);\nextern \"C\" {\n\tvoid\tAudio_Mem_Set(void const *ptr, unsigned char value, long size);\n\tvoid\tMem_Copy(void *source, void *dest, unsigned long bytes_to_copy);\n\tlong  Decompress_Frame(void * source, void * dest, long size);\n\tint\tDecompress_Frame_Lock(void);\n\tint\tDecompress_Frame_Unlock(void);\n\tint\tsosCODEC_Lock(void);\n\tint\tsosCODEC_Unlock(void);\n\tvoid\t__GETDS(void);\n}\t\t\n\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/SOUNDINT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDINT.CPP                             *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 28, 1995   [PWG]                    *\n *                                                                         *\n * This module contains all of the functions that are used within our      *\n * sound interrupt.  They are stored in a seperate module because memory\t*\n * around these functions must be locked or they will cause a read to\t\t*\n * be generated while in an interrupt.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Simple_Copy -- Copyies 1 or 2 source chuncks to a dest                *\n *   Sample_Copy -- Copies sound data from source format to raw format.    *\n *   DigiCallback -- Low level double buffering handler.                   *\n *   save_my_regs -- Inline function which will save assembly regs         *\n *   restore_my_regs -- Inline function which will restore saved registes  *\n *   Audio_Add_Long_To_Pointer -- Adds an offset to a ptr casted void      *\n *   Init_Locked_Data -- Initializes sound driver locked data              *\n *   Audio_Mem_Set -- Quick see routine to set memory to a value           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n#pragma pack(4)\n#include \"soundint.h\"\n//#include \"mem.h\"\n\n/***************************************************************************\n** All routines past this point must be locked for the sound driver to\t  **\n** function under a VCPI memory manager.  These locks are unnecessary if  **\n** the driver does not have to run under windows or does not use virtual  **\n** memory.                                                                **\n***************************************************************************/\n\t\n/***************************************************************************\n * SAVE_MY_REGS -- Inline function which will save assembly regs           *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n\n#pragma aux save_my_regs =\t\t\\\n\t\t\"pushfd\"\t\t\t\\\n\t\t\"pushad\"\t\t\t\\\n\t\t\"push ds\"\t\t\\\n\t\t\"push es\"\t\t\\\n\t\t\"push fs\"\t\t\\\n\t\t\"push gs\"\t\t\\\n\t\t\"push ds\"\t\t\\\n\t\t\"pop  es\";\n\n#pragma aux enable = \\\n\t\t\"sti\";\n\n#pragma aux disable = \\\n\t\t\"cli\";\n\n/***************************************************************************\n * RESTORE_MY_REGS -- Inline function which will restore saved registers   *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n\n#pragma aux restore_my_regs =\t\\\n\t\t\"pop\tgs\"\t\t\\\n\t\t\"pop\tfs\"\t\t\\\n\t\t\"pop\tes\"\t\t\\\n\t\t\"pop\tds\"\t\t\\\n\t\t\"popad\"\t\t\t\\\n\t\t\"popfd\";\n\n/***************************************************************************\n * SIMPLE_COPY -- Copyies 1 or 2 source chuncks to a dest                  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nlong Simple_Copy(void ** source, long * ssize, void ** alternate, long * altsize, void **dest, long size)\n{\n\n\n\tlong\tout = 0;\t\t// Number of bytes copied to the destination.\n\n\t/*\n\t**\tIt could happen that entering this routine, the source buffer\n\t**\thas been exhausted, but the alternate buffer is still valid.\n\t**\tMove the alternate into the primary position before proceeding.\n\t*/\n\tif (!(*ssize)) {\n\t\t*source = *alternate;\n\t\t*ssize = *altsize;\n\t\t*alternate = NULL;\n\t\t*altsize = 0;\n\t}\n\n\tif (*source && *ssize) {\n\t\tlong\ts;\t\t\t\t// Scratch length var.\n\n\t\t/*\n\t\t**\tCopy as much as possible from the primary source, but no\n\t\t**\tmore than the primary source has to offer.\n\t\t*/\n\t\ts = size;\n\t\tif (*ssize < s) s = *ssize;\n\t\tMem_Copy(*source, *dest, s);\n\t\t*source = Audio_Add_Long_To_Pointer(*source, s);\n\t\t*ssize -= s;\n\t\t*dest = Audio_Add_Long_To_Pointer(*dest, s);\n\t\tsize -= s;\n\t\tout += s;\n\n\t\t/*\n\t\t**\tIf the primary source was insufficient to fill the request, then\n\t\t**\tmove the alternate into the primary position and try again.\n\t\t*/\n\t\tif (size) {\n\t\t\t*source = *alternate;\n\t\t\t*ssize = *altsize;\n\t\t\t*alternate = 0;\n\t\t\t*altsize = 0;\n\t\t\tout += Simple_Copy(source, ssize, alternate, altsize, dest, size);\n\t\t}\n\t}\n\n\treturn(out);\n}\n\n/***********************************************************************************************\n * Sample_Copy -- Copies sound data from source format to raw format.                          *\n *                                                                                             *\n *    This routine is used to copy the sound data (possibly compressed) to the destination     *\n *    buffer in raw format.                                                                    *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the source data (possibly compressed).                      *\n *                                                                                             *\n *          dest     -- Pointer to the destination buffer.                                     *\n *                                                                                             *\n *          size     -- The size of the destination buffer.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes placed into the output buffer.  This is usually   *\n *          the number of bytes requested except in the case when the source is exhausted.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/03/1994 JLB : Created.                                                                 *\n *   09/04/1994 JLB : Revamped entirely.                                                       *\n *=============================================================================================*/\n#pragma argsused\nlong Sample_Copy(SampleTrackerType *st, void ** source, long * ssize, void ** alternate, long * altsize, void * dest, long size, SCompressType scomp, void * trailer, WORD *trailersize)\n{\n\n\tlong\ts;\n\tlong\tdatasize = 0;\t\t// Output bytes.\n\n\tswitch (scomp) {\n\t\tdefault:\n\n\t\tcase SCOMP_NONE:\n\t\t\tdatasize = Simple_Copy(source, ssize, alternate, altsize, &dest, size);\n\t\t\tbreak;\n\n\t\tcase SCOMP_WESTWOOD:\n\t\tcase SCOMP_SOS:\n\t\t\twhile (size > 0) {\n\n\t\t\t\t/*\n\t\t\t\t**\tThe block spans two buffers.  It must be copied down to \n\t\t\t\t**\ta staging area before it can be decompressed.\n\t\t\t\t*/\n\t\t\t\t{\n\t\t\t\t\tlong magic;\n\t\t\t\t\tunsigned short fsize;\n\t\t\t\t\tunsigned short dsize;\n\t\t\t\t\tvoid *fptr;\n\t\t\t\t\tvoid *dptr;\n\t\t\t\t\tvoid *mptr;\n\n\t\t\t\t\tfptr = &fsize;\n\t\t\t\t\tdptr = &dsize;\n\t\t\t\t\tmptr = &magic;\n\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &fptr, sizeof(fsize));\n\t\t\t\t\tif (s < sizeof(fsize)) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &dptr, sizeof(dsize));\n\t\t\t\t\tif (s < sizeof(dsize) || size < dsize) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &mptr, sizeof(magic));\n\t\t\t\t\tif (s < sizeof(magic) || magic != LockedData.MagicNumber) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the frame and uncompressed data size are identical, then this\n\t\t\t\t\t**\tindicates that the frame is not compressed.  Just copy it directly\n\t\t\t\t\t**\tto the destination buffer in this case.\n\t\t\t\t\t*/\n\t\t\t\t\tif (fsize == dsize) {\n\t\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &dest, fsize);\n\t\t\t\t\t\tif (s < dsize) {\n\t\t\t\t\t\t\treturn (datasize);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tThe frame was compressed, so copy it to the staging buffer, and then\n\t\t\t\t\t\t**\tuncompress it into the final destination buffer.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tfptr = LockedData.UncompBuffer;\n\t\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &fptr, fsize);\n\t\t\t\t\t\tif (s < fsize) {\n\t\t\t\t\t\t\treturn (datasize);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (scomp == SCOMP_WESTWOOD) {\n\t\t\t\t\t\t\tDecompress_Frame(LockedData.UncompBuffer, dest, dsize);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tst->sosinfo.lpSource = (char *)LockedData.UncompBuffer;\n\t\t\t\t\t\t\tst->sosinfo.lpDest\t = (char *)dest;\n\t\t\t\t\t\t\tsosCODECDecompressData(&st->sosinfo, dsize);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdest = Audio_Add_Long_To_Pointer(dest, dsize);\n\t\t\t\t\t}\n\t\t\t\t\tdatasize += dsize;\n\t\t\t\t\tsize -= dsize;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak;\n\t}\n\treturn(datasize);\n}\n\nVOID far cdecl maintenance_callback(VOID)\n{\n\tsave_my_regs();\n\tint\t\t\t\t\tindex;\n\tSampleTrackerType\t*st;\n\n\tif (!LockedData._int && LockedData.DigiHandle != -1 && LockedData.ServiceSomething) {\n\n\t\tLockedData._int++;\n\t\tenable();\n\t\tLockedData.ServiceSomething = FALSE;\n\t\tst = &LockedData.SampleTracker[0];\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\n\t\t\tif (st->Active) {\n\n\t\t\t\t/*\n\t\t\t\t**\tGeneral service routine to handle moving small blocks from the\n\t\t\t\t**\tsource into the low RAM staging buffers.  If the source is\n\t\t\t\t**\tcompressed, then this will also uncompress it as the copy\n\t\t\t\t**\tis performed.\n\t\t\t\t*/\n\t\t\t\tif (st->Service) {\n\t\t\t\t\tif (st->DontTouch) {\n\t\t\t\t\t\tLockedData.ServiceSomething = TRUE;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tst->Service = FALSE;\n\n#if(FALSE)\n\t\t\t\t\t\tst->DataLength = SFX_MINI_STAGE_BUFFER_SIZE;\n#else\n\t\t\t\t\t\tst->DataLength = Sample_Copy(\tst,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Source, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Remainder, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->QueueBuffer, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->QueueSize, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tst->Buffer[st->Index], \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSFX_MINI_STAGE_BUFFER_SIZE, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tst->Compression, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Trailer[0], \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->TrailerLen);\n\n#endif\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tFor file streamed samples, fill the queue pointer if needed.\n\t\t\t\t**\tThis allows for delays in calling the Sound_Callback function.\n\t\t\t\t*/\n\t\t\t\tif (!st->DontTouch && !st->QueueBuffer && st->FilePending) {\n\t\t\t\t\tst->QueueBuffer = Audio_Add_Long_To_Pointer(st->FileBuffer, (long)(st->Odd%LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t\t\t\t\tst->FilePending--;\n\t\t\t\t\tst->Odd++;\n\t\t\t\t\tif (!st->FilePending) {\n\t\t\t\t\t\tst->QueueSize = st->FilePendingSize;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tst->QueueSize = LockedData.StreamBufferSize;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAdvance to the next sample control structure.\n\t\t\t*/\n\t\t\tst++;\n\t\t}\n\t\tLockedData._int--;\n\t}\n\n\t\n\tif (!LockedData._int) {\n\n\t\tLockedData._int++;\n\t\tst = &LockedData.SampleTracker[0];\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\n\t\t\t/*\n\t\t\t**\tIf there are any samples that require fading, then do so at this\n\t\t\t**\ttime.\n\t\t\t*/\n\t\t\tif (st->Active && st->Reducer && st->Volume) {\n\t\t\t\tif (st->Reducer >= st->Volume) {\n\t\t\t\t\tst->Volume = 0;\n\t\t\t\t} else {\n\t\t\t\t\tst->Volume -= st->Reducer;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (st->IsScore) {\n\t\t\t\t\tsosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, (st->Volume>>8) * LockedData.ScoreVolume);\n\t\t\t\t} else {\n\t\t\t\t\tsosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, (st->Volume>>8) * LockedData.SoundVolume);\n\t\t\t\t}\n\t\t\t}\n\t\t\tst++;\n\t\t}\n\t\tLockedData._int--;\n\t}\n\trestore_my_regs();\n}\n/***********************************************************************************************\n * DigiCallback -- Low level double buffering handler.                                         *\n *                                                                                             *\n *    This routine is called in an interrupt to handle the double                              *\n *    buffering of digital audio.  This routine is the interface between                       *\n *    the buffers maintained by Sound_Callback() and the HMI driver                            *\n *    itself.                                                                                  *\n *                                                                                             *\n * INPUT:   driverhandle   -- The handle to the HMI driver.                                    *\n *                                                                                             *\n *          callsource     -- Code indicating the reason for the callback.                     *\n *                                                                                             *\n *          sampleid       -- The ID number of the sample itself.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This is called in an interrupt so it return as quickly as                       *\n *             possible.                                                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID cdecl far DigiCallback(unsigned int driverhandle, unsigned int callsource, unsigned int sampleid)\n{\n\tSampleTrackerType\t*st;\n\tint\tindex;\n\n\n\t/*\n\t**\tFind the correct control structure for the handle specified.\n\t*/\n\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\tst = &LockedData.SampleTracker[index];\n\t\tif (st->Active && st->Handle == sampleid) {\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (index == LockedData.MaxSamples) {\n\t\treturn;\n\t}\n\n\tif (driverhandle == LockedData.DigiHandle) {\n\n\t\tswitch (callsource) {\n\n\t\t\t/*\n\t\t\t**\tThe sample is now no longer audible.  Don't stop the sample\n\t\t\t**\ttracking if a servicing is needed.  If it is needed then\n\t\t\t**\tobviously the sample isn't quite done.\n\t\t\t*/\n\t\t\tcase _SAMPLE_DONE:\n\t\t\t\tst->Active = FALSE;\n\t\t\t\tif (!st->IsScore) {\n//\t\t\t\t\tDPMI_Unlock(st->Original, st->OriginalSize);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tThe sample is finished processing, but not necessarily finished playing.\n\t\t\t*/\n\t\t\tcase _SAMPLE_PROCESSED:\n\t\t\t\tif (st->DataLength && st->Active) {\n\t\t\t\t\t_SOS_START_SAMPLE start;\n\t\t\t\t\tlong dlength;\n\n\t\t\t\t\tdlength = st->DataLength;\n\t\t\t\t\tst->DataLength = 0;\n\n\t\t\t\t\tAudio_Mem_Set(&start, 0, sizeof(start));\n\t\t\t\t\tstart.lpSamplePtr = (LPSTR)st->Buffer[st->Index];\n\n\t\t\t\t\tstart.dwSampleSize = dlength-1;\n\n\t\t\t\t\tstart.wSampleFlags = st->Flags;\n\t\t\t\t\tstart.lpCallback = (void cdecl (far *)(unsigned int, unsigned int, unsigned int))&DigiCallback;\n\t\t\t\t\tstart.wLoopCount = 0;\n\t\t\t\t\tif (st->IsScore) {\n\t\t\t\t\t\tstart.wVolume = (st->Volume>>8) * LockedData.ScoreVolume;\n\t\t\t\t\t\tsosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, start.wVolume);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstart.wVolume = (st->Volume>>8) * LockedData.SoundVolume;\n\t\t\t\t\t\tsosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, start.wVolume);\n\t\t\t\t\t}\n\n\t\t\t\t\tstart.wChannel = st->Stereo;\n\t\t\t\t\tstart.wSampleID = index+1;\n\t\t\t\t\tstart.dwSamplePitchAdd = st->Pitch;\n\t\t\t\t\tst->Index ^= 1;\n\n\t\t\t\t\tif (st->Remainder || st->QueueBuffer || st->Callback || st->FilePending) {\n\t\t\t\t\t\tst->Service = TRUE;\n\t\t\t\t\t\tLockedData.ServiceSomething = TRUE;\n\t\t\t\t\t}\n\n\t\t\t\t\tsosDIGIContinueSample(LockedData.DigiHandle, st->Handle, &start);\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThis is necessary because Stop_Sample may screw things\n\t\t\t\t\t**\tup, otherwise.  Can't rely on the _SAMPLE_DONE call.\n\t\t\t\t\t*/\n\t\t\t\t\tst->Active = FALSE;\n\t\t\t\t\tif (!st->IsScore) {\n//\t\t\t\t\t\tDPMI_Unlock(st->Original, st->OriginalSize);\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tSample is now looping (not used).\n\t\t\t*/\n\t\t\tcase _SAMPLE_LOOPING:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n}\n\nvoid far HMI_TimerCallback(void)\n{\n}\n\n\n/***************************************************************************\n * ADD_LONG_TO_POINTER -- Adds an offset to a ptr casted void              *\n *                                                                         *\n * INPUT:\t\tvoid * ptr - the pointer to add to                          *\n *\t\t\t\t\tlong size  - the size to add to it\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     void * ptr - the new location it will point to              *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n\nvoid *Audio_Add_Long_To_Pointer(void const *ptr, long size) \n{\n \treturn ((void *) ( (char const *) ptr + size));\n}\n\n/***************************************************************************\n * AUDIO_MEM_SET -- Quick see routine to set memory to a value             *\n *                                                                         *\n * INPUT:\t\tvoid const *  - the memory that needs to be set             *\n *\t\t\t\t\tunsigned char - the value to set the memory to\t\t\t\t\t*\n *\t\t\t\t\tlong size     - how big an area to set\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/28/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid Audio_Mem_Set(void const *ptr, unsigned char value, long size)\n{\n\tunsigned char *temp = (unsigned char *)ptr;\n\tfor (int lp = 0; lp < size; lp ++) {\n\t\t*temp++ = value;\n\t}\n}\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/SOUNDINT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDINT.H                               *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 23, 1995   [PWG]                    *\n *                                                                         *\n * This file is the include file for the Westwood Sound Sytem defines and  *\n * routines that are handled in an interrupt.\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"sound.h\"\n\n/*\n** Defines for true and false.  These are included because we do not allow\n** the sound int to include any of the westwood standard headers.  If we\n** did, there might be too much temptation to call another library function.\n** this would be bad, because then that function would not be locked.\n*/\n#define\tFALSE\t\t0\n#define\tTRUE\t\t1\n\n/*\n** Define the different type of sound compression avaliable to the westwood\n** library.\n*/\ntypedef enum {\n\tSCOMP_NONE=0,\t\t\t// No compression -- raw data.\n\tSCOMP_WESTWOOD=1,\t\t// Special sliding window delta compression.\n\tSCOMP_SONARC=33,\t\t// Sonarc frame compression.\n\tSCOMP_SOS=99\t\t\t// SOS frame compression.\n} SCompressType;\n\n/*\n**\tThis is the safety overrun margin for the sonarc compressed\n** data frames.  This value should be equal the maximum 'order' times\n**\tthe maximum number of bytes per sample.  It should be evenly divisible\n**\tby 16 to aid paragraph alignment.\n*/\n#define\tSONARC_MARGIN\t\t\t\t32\n\n\n/*\n** Define the sample control structure which helps us to handle feeding\n** data to the sound interrupt.\n*/\n#pragma pack(1);\ntypedef struct {\n\t/*\n\t**\tThis flags whether this sample structure is active or not.\n\t*/\n\tunsigned Active:1;\n\n\t/*\n\t**\tThis flags whether the sample is loading or has been started.\n\t*/\n\tunsigned Loading:1;\n\n\t/*\n\t**\tThis semaphore ensures that simultaneous update of this structure won't\n\t**\toccur.  This is necessary since both interrupt and regular code can modify\n\t**\tthis structure.\n\t*/\n\tunsigned DontTouch:1;\n\n\t/*\n\t**\tIf this sample is really to be considered a score rather than\n\t**\ta sound effect, then special rules apply.  These largely fall into\n\t**\tthe area of volume control.\n\t*/\n\tunsigned IsScore:1;\n\n\t/*\n\t**\tThis is the original sample pointer. It is used to control the sample based on\n\t**\tpointer rather than handle. The handle method is necessary when more than one\n\t**\tsample could be playing simultaneously. The pointer method is necessary when\n\t**\tthe dealing with a sample that may have stopped behind the programmer's back and\n\t**\tthis occurance is not otherwise determinable.  It is also used in\n\t** conjunction with original size to unlock a sample which has been DPMI\n\t** locked.\n\t*/\n\tvoid const *Original;\n\tlong OriginalSize;\n\n\t/*\n\t**\tThese are pointers to the double buffers in low ram.\n\t*/\n\tVOID *Buffer[2];\n\n\t/*\n\t**\tThe number of bytes in the buffer that has been filled but is not\n\t**\tyet playing.  This value is normally the size of the buffer,\n\t**\texcept for the case of the last bit of the sample.\n\t*/\n\tLONG DataLength;\n\n\t/*\n\t**\tThis is the buffer index for the low buffer that\n\t**\thas been filled with data but not yet being\n\t**\tplayed.\n\t*/\n\tWORD Index;\n\n\t/*\n\t**\tPointer to the sound data that has not yet been copied\n\t**\tto the playback buffers.\n\t*/\n\tVOID *Source;\n\n\t/*\n\t**\tThis is the number of bytes remaining in the source data as\n\t**\tpointed to by the \"Source\" element.\n\t*/\n\tLONG Remainder;\n\n\t/*\n\t**\tSamples maintain a priority which is used to determine\n\t**\twhich sounds live or die when the maximum number of\n\t**\tsounds are being played.\n\t*/\n\tWORD Priority;\n\n\t/*\n\t**\tThis is the handle as returned by sosDIGIStartSample function.\n\t*/\n\tWORD Handle;\n\n\t/*\n\t**\tThis is the current volume of the sample as it is being played.\n\t*/\n\tWORD Volume;\n\tWORD Reducer;\t\t// Amount to reduce volume per tick.\n\n\t/*\n\t**\tThis flags whether the sample is in stereo.\n\t*/\n\tWORD Stereo;\n\n\t/*\n\t**\tThis is the compression that the sound data is using.\n\t*/\n\tSCompressType Compression;\n\tWORD TrailerLen;\t\t\t\t\t\t// Number of trailer bytes in buffer.\n\tBYTE Trailer[SONARC_MARGIN];\t\t// Maximum number of 'order' samples needed.\n\n\n\tDWORD Pitch;\n\tWORD Flags;\n\n\t/*\n\t**\tThis flag indicates whether this sample needs servicing.  \n\t**\tServicing entails filling one of the empty low buffers.\n\t*/\n\tWORD Service;\n\n\t/*\n\t**\tThis flag is TRUE when the sample has stopped playing,\n\t**\tBUT there is more data available.  The sample must be\n\t**\trestarted upon filling the low buffer.\n\t*/\n\tBOOL Restart;\n\n\t/*\n\t**\tStreaming control handlers.\n\t*/\n\tBOOL (*Callback)(WORD id, WORD *odd, VOID **buffer, LONG *size);\n\tVOID\t*QueueBuffer;\t// Pointer to continued sample data.\n\tLONG\tQueueSize;\t\t// Size of queue buffer attached.\n\tWORD\tOdd;\t\t\t\t// Block number tracker (0..StreamBufferCount-1).\n\tint\tFilePending;\t// Number of buffers already filled ahead.\n\tlong\tFilePendingSize;\t// Number of bytes in last filled buffer.\n\n\t/*\n\t**\tThe file variables are used when streaming directly off of the \n\t**\thard drive.\n\t*/\n\tWORD\tFileHandle;\t\t// Streaming file handle (ERROR = not in use).\n\tVOID\t*FileBuffer;\t// Temporary streaming buffer (allowed to be freed).\n\t/*\n\t** The following structure is used if the sample if compressed using\n\t** the sos 16 bit compression Codec.\n\t*/\n\t_SOS_COMPRESS_INFO sosinfo;\n\n} SampleTrackerType;\n\n\ntypedef struct LockedData {\n\tunsigned int \t\tDigiHandle; \t\t\t// = -1;\n\tBOOL \t\t\t\t\tServiceSomething;\t\t// = FALSE;\n\tlong \t\t\t\t\tMagicNumber; \t\t\t// = 0xDEAF;\n\tVOID \t\t\t\t\t*UncompBuffer;\t\t\t// = NULL;\n\tlong \t\t\t\t\tStreamBufferSize; \t// = (2*SFX_MINI_STAGE_BUFFER_SIZE)+128;\n\tshort \t\t\t\tStreamBufferCount; \t// = 32;\n\tSampleTrackerType SampleTracker[MAX_SFX];\n\tunsigned int\t\tSoundVolume;\n\tunsigned int\t\tScoreVolume;\n\tBOOL\t\t\t\t\t_int;\n\tint\t\t\t\t\tMaxSamples;\t\t\t\t\n\tint\t\t\t\t\tRate;\t\t\t\t\n} LockedDataType;\n\nextern LockedDataType LockedData;\n#pragma pack(4);\n\nvoid Init_Locked_Data(void);\nvoid Unlock_Locked_Data(void);\nlong Simple_Copy(void ** source, long * ssize, void ** alternate, long * altsize, void **dest, long size);\nlong Sample_Copy(SampleTrackerType *st, void ** source, long * ssize, void ** alternate, long * altsize, void * dest, long size, SCompressType scomp, void * trailer, WORD *trailersize);\nVOID far cdecl maintenance_callback(VOID);\nVOID cdecl far DigiCallback(unsigned int driverhandle, unsigned int callsource, unsigned int sampleid);\nvoid far HMI_TimerCallback(void);\nvoid *Audio_Add_Long_To_Pointer(void const *ptr, long size);\nvoid\tDPMI_Unlock(VOID const *ptr, long const size);\nextern \"C\" {\n\tvoid\tAudio_Mem_Set(void const *ptr, unsigned char value, long size);\n\tvoid\tMem_Copy(void const *source, void *dest, unsigned long bytes_to_copy);\n\tlong  Decompress_Frame(void * source, void * dest, long size);\n\tint\tDecompress_Frame_Lock(void);\n\tint\tDecompress_Frame_Unlock(void);\n\tint\tsosCODEC_Lock(void);\n\tint\tsosCODEC_Unlock(void);\n\tvoid\t__GETDS(void);\n}\t\t\n\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/SOUNDIO.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Id: soundio.cpp 1.41 1994/06/20 15:01:39 joe_bostic Exp $ */\n/***********************************************************************************************\n **             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             **\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Sound Library                                                *\n *                                                                                             *\n *                    File Name : SOUND.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 22, 1991                                                *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   File_Callback -- called to fill queue buffer for streaming sample     \t\t\t\t\t\t  *\n *   Stream_Sample_Volume -- generic streaming sample playback init                            *\n *   Stream_Sample -- generic streaming sample playback init                                   *\n *   File_Stream_Sample -- Streams a sample directly from a file.                              *\n *   File_Stream_Preload -- Handles initial proload of a streaming samples                     *\n *   File_Stream_Sample_Volume -- Streams a sample directly from a file w/volume.              *\n *   Sound_Callback -- Audio driver callback function.                                         *\n *   Load_Sample -- Loads a digitized sample into RAM.                                         *\n *   Load_Sample_Into_Buffer -- Loads a digitized sample into a buffer.                        *\n *   Free_Sample -- Frees a previously loaded digitized sample.                                *\n *   Sound_End -- Uninitializes the sound driver.                                              *\n *   Stop_Sample -- Stops any currently playing sampled sound.                                 *\n *   Sample_Status -- Queries the current playing sample status (if any).                      *\n *   Sample_Length -- returns length of a sample in ticks                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#pragma pack(4)\n#include\t\"soundint.h\"\n#include <dos.h>\n#include <mem.h>\n#include <stdio.h>\n#include <string.h>\n#include\t<direct.h>\n#include\t<stdlib.h>\n#include\t<wwmem.h>\n#include\t<keyboard.h>\n#include\t<file.h>\n#include\t<i86.h>\n#include <timer.h>\n#pragma pack(1)\n#include \"audio.h\"\n#pragma pack(4)\n\n/*\n**\tIf this is defined, then the streaming audio buffer will be filled\n**\tto maximum whenever filling is to occur. If undefined, it will fill\n**\tthe streaming buffer in smaller chunks.\n*/\n#define\tSIMPLE_FILLING\n\n/*\n**\tThis define (if present) enables the simple HMI hardware initialization process.\n**\tThe process does not do auto detection, but rather takes the value directly from\n**\tthe setup program and uses that as the sound card number.  The only \"detection\" it\n**\tdoes is to recognized the presence of the card and fetch its settings.\n*/\n#define\tSIMPLE_HMI_INIT\n\n\n/*\n**\tThis is the rate that the maintenance callback gets called.\n*/\n#define\tMAINTENANCE_RATE\t\t\t60\n\n/*\n**\tSize of the temporary buffer in XMS/EMS that direct file\n**\tstreaming of sounds will allocate.\n*/\n#define\tSTREAM_BUFFER_SIZE\t\t(128L*1024L)\n\n/*\n** Define the number of \"StreamBufferSize\" blocks that are read in\n** at a minimum when the streaming sample load callback routine\n** is called.  We will IGNORE loads that are less that this in order\n** to avoid constant seeking on the CD.\n*/\n#define\tSTREAM_CUSHION_BLOCKS\t4\n\n\n/*\n**\tThis is the maximum size that a sonarc block can be.  All sonarc blocks\n**\tmust be either a multiple of this value or a binary root of this value.\n*/\n#define\tLARGEST_SONARC_BLOCK\t\t2048\n\n\n//////////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////// structs ///////////////////////////////////////\n\nstatic _SOS_CAPABILITIES\tDigiCaps;\nstatic _SOS_HARDWARE \t\tDigiHardware;\nstatic WORD \t\t\t\t\tMidiHandle = -1;\nstatic unsigned int far\t\tDigiTimer = 0;\nstatic unsigned int far\t\tMaintainTimer = 0;\nstatic unsigned int far\t\tSystemTimer = 0;\nstatic int\t\t\t\t\t\tBits_Per_Sample;\nVOID \t\t\t\t\t\t\t\t*DigiBuffer = NULL;\nstatic BOOL \t\t\t\t\tStartingFileStream = FALSE;\nshort \t\t\t\t\t\t\tStreamLowImpact = FALSE;\nMemoryFlagType \t\t\t\tStreamBufferFlag = MEM_NORMAL;\nint \t\t\t\t\t\t\t\tMisc;\nSFX_Type \t\t\t\t\t\tSoundType;\nSample_Type \t\t\t\t\tSampleType;\nint\t\t\t\t\t\t\t\tReverseChannels = FALSE;\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nstatic BOOL File_Callback(WORD id, WORD *odd, VOID **buffer, LONG *size);\nstatic int cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback)(WORD id, WORD *odd, VOID **buffer, LONG *size), int volume, int handle);\nstatic int cdecl Stream_Sample(void *buffer, long size, BOOL (*callback)(WORD id, WORD *odd, VOID **buffer, LONG *size));\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n\n/***************************************************************************\n * FILE_CALLBACK -- called to fill queue buffer for streaming sample       *\n *                                                                         *\n * This callback is called whenever the queue buffer playback has begun\t\t*\n * and another buffer is needed for queuing up.  Returns TRUE if there\t\t*\n * is more data to read from the file.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:\tWORD id\t\t\t- the sample id number                          *\n *\t\t\t\tWORD *odd\t\t- which sample buffer to put info in\t\t\t\t*\n *\t\t\t\tVOID **buffer\t- the buffer pointer to load data into\t\t\t\t*\n *\t\t\t\tLONG *size\t\t- the amount to load\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:  BOOL true if more data to load, FALSE if done loading          *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nstatic BOOL File_Callback(WORD id, WORD *odd, VOID **buffer, LONG *size)\n{\n\tSampleTrackerType\t*st;\t\t// Pointer to sample playback control struct.\n\tVOID\t\t\t\t\t*ptr;\t\t// Pointer to working portion of file buffer.\n\n\tif (id != -1) {\n\t\tst = &LockedData.SampleTracker[id];\n\t\tptr = st->FileBuffer;\n\t\tif (ptr) {\n\n\t\t\t/*\n\t\t\t**\tMove the next pending block into the primary \n\t\t\t**\tposition.  Do this only if the queue pointer is\n\t\t\t**\tnull.\n\t\t\t*/\n\t\t\tst->DontTouch = TRUE;\n\t\t\tif (!*buffer && st->FilePending) {\n\t\t\t\t*buffer = Add_Long_To_Pointer(ptr, (long)(*odd % LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t\t\t\tst->FilePending--;\n\t\t\t\t*odd = *odd + 1;\n\t\t\t\tif (!st->FilePending) {\n\t\t\t\t\t*size = st->FilePendingSize;\n\t\t\t\t} else {\n\t\t\t\t\t*size = LockedData.StreamBufferSize;\n\t\t\t\t}\n\t\t\t}\n\t\t\tst->DontTouch = FALSE;\n\t\t\tmaintenance_callback();\n\n\t\t\t/*\n\t\t\t**\tIf the file handle is still valid, then read in the next\n\t\t\t**\tblock and add it to the next pending slot available.\n\t\t\t*/\n\t\t\tif (st->FilePending <\n\t\t\t\t(StreamLowImpact ? (LockedData.StreamBufferCount>>1) : ((LockedData.StreamBufferCount-3))) && st->FileHandle != ERROR) {\n\n\n\t\t\t\tint num_empty_buffers;\n\n#ifdef SIMPLE_FILLING\n\t\t\t\tnum_empty_buffers = (LockedData.StreamBufferCount-2) - st->FilePending;\n#else\n\n\t\t\t\t//\n\t\t\t\t// num_empty_buffers will be from 1 to StreamBufferCount\n\t\t\t\t//\n\t\t\t\tif (StreamLowImpact) {\n\t\t\t\t\tnum_empty_buffers = MIN((LockedData.StreamBufferCount >> 1)+STREAM_CUSHION_BLOCKS, (LockedData.StreamBufferCount - 2) - st->FilePending);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tnum_empty_buffers = (LockedData.StreamBufferCount - 2) - st->FilePending;\n\t\t\t\t}\n#endif\n\t\t\t\t\n\n\n\t\t\t\twhile (num_empty_buffers && st->FileHandle != ERROR) {\n\t\t\t\t\tint\ttofill;\n\t\t\t\t\tlong\tpsize;\n\n\t\t\t\t\ttofill = (*odd + st->FilePending) % LockedData.StreamBufferCount;\n\n\t\t\t\t\tptr = Add_Long_To_Pointer(st->FileBuffer, (long)tofill * (long)LockedData.StreamBufferSize);\n\t\t\t\t\tpsize = Read_File(st->FileHandle, ptr, LockedData.StreamBufferSize);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf less than the requested amount of data was read, this\n\t\t\t\t\t**\tindicates that the source file is exhausted.  Flag the source\n\t\t\t\t\t**\tfile as closed so that no further reading is attempted.\n\t\t\t\t\t*/\n\t\t\t\t\tif (psize != LockedData.StreamBufferSize) {\n\t\t\t\t\t\tClose_File(st->FileHandle);\n\t\t\t\t\t\tst->FileHandle = ERROR;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf any real data went into the pending buffer, then flag\n\t\t\t\t\t**\tthat this buffer is valid.\n\t\t\t\t\t*/\n\t\t\t\t\tif (psize) {\n\t\t\t\t\t\tst->DontTouch = TRUE;\n\t\t\t\t\t\tst->FilePendingSize = psize;\n\t\t\t\t\t\tst->FilePending++;\n\t\t\t\t\t\tst->DontTouch = FALSE;\n\t\t\t\t\t\tmaintenance_callback();\n\t\t\t\t\t}\n\t\t\t\t\tnum_empty_buffers--;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAfter filling all pending buffers, check to see if the queue buffer\n\t\t\t\t**\tis empty.  If so, then assign the first available pending buffer to the\n\t\t\t\t**\tqueue.\n\t\t\t\t*/\n\t\t\t\tst->DontTouch = TRUE;\n\t\t\t\tif (!st->QueueBuffer && st->FilePending) {\n\t\t\t\t\tst->QueueBuffer = Add_Long_To_Pointer(st->FileBuffer, (long)(st->Odd%LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t\t\t\t\tst->FilePending--;\n\t\t\t\t\tst->Odd++;\n\t\t\t\t\tif (!st->FilePending) {\n\t\t\t\t\t\tst->QueueSize = st->FilePendingSize;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tst->QueueSize = LockedData.StreamBufferSize;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tst->DontTouch = FALSE;\n\t\t\t\tmaintenance_callback();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf there are no more buffers that the callback routine\n\t\t\t**\tcan slot into the primary position, then signal that\n\t\t\t**\tno furthur callbacks are needed.\n\t\t\t*/\n\t\t\tif (st->FilePending) {\n\t\t\t\treturn(TRUE);\n\t\t\t}\n\t\t}\n\t}\n\treturn(FALSE);\n}\n\n/***************************************************************************\n * STREAM_SAMPLE_VOLUME -- generic streaming sample playback init          *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nstatic int cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback)(WORD id, WORD *odd, VOID **buffer, LONG *size), int volume, int handle)\n{\n\tint\t\t\t\t\t\tplayid=-1;\t// Sample play ID.\n\tSampleTrackerType\t\t*st;\t\t\t// Working pointer to sample control structure.\n\tlong\t\t\t\t\t\toldsize;\t\t// Copy of original sound size.\n\tAUDHeaderType\t\t\theader;\n\n\tif (buffer && size && LockedData.DigiHandle != -1) {\n\n\t\t/*\n\t\t**\tStart the first section of the sound playing.\n\t\t*/\n\t\tMem_Copy(buffer, &header, sizeof(header));\n\t\toldsize = header.Size;\n\t\theader.Size = size-sizeof(header);\n\t\tMem_Copy(&header, buffer, sizeof(header));\n\t\tplayid = Play_Sample_Handle(buffer, 0xFF, volume, 0x0, handle);\n\t\theader.Size = oldsize;\n\t\tMem_Copy(&header, buffer, sizeof(header));\n\n\t\t/*\n\t\t**\tIf the sample actually started playing, then flag this\n\t\t**\tsample as a streaming type and signal for a callback\n\t\t**\tto occur.\n\t\t*/\n\t\tif (playid != -1) {\n\t\t\tst = &LockedData.SampleTracker[playid];\n\n\t\t\tst->Callback = callback;\n\t\t\tst->Odd = 0;\n\t\t}\n\t}\n\treturn (playid);\n}\n\n/***************************************************************************\n * STREAM_SAMPLE -- generic streaming sample playback init          \t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nstatic int cdecl Stream_Sample(void *buffer, long size, BOOL (*callback)(WORD id, WORD *odd, VOID **buffer, LONG *size), int handle)\n{\n\treturn Stream_Sample_Vol(buffer, size, callback, 0xFF, handle);\n}\n\n\n\n/***********************************************************************************************\n * File_Stream_Sample -- Streams a sample directly from a file.                                *\n *                                                                                             *\n *    This will take the file specified and play it directly from disk.                        *\n *    It performs this by allocating a temporary buffer in XMS/EMS and                         *\n *    then keeping this buffer filled by the Sound_Callback() routine.                         *\n *                                                                                             *\n * INPUT:   filename -- The name of the file to play.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the handle to the sound -- just like Play_Sample().                        *\n *                                                                                             *\n * WARNINGS:   The temporary buffer is allocated when this routine is                          *\n *             called and then freed when the sound is finished.  Keep                         *\n *             this in mind.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint File_Stream_Sample(char const *filename, BOOL real_time_start)\n{\n\treturn File_Stream_Sample_Vol(filename, 0xFF, real_time_start);\n}\n\n/***************************************************************************\n * FILE_STREAM_PRELOAD -- Handles initial proload of streaming samples     *\n *                                                                         *\n * This function is called before a sample which streams from disk is      *\n * started.  It can be called to either fill the buffer in small chunks\t\t*\n * from the call back routine or to fill the entire buffer at once.  This\t*\n * is wholely dependant on whether the Loading bit is set within the \t\t*\n * sample tracker.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:\t\tLockedData.SampleTracker * to the header which tracks this samples     *\n *\t\t\t\t\t\t\t\t\t\t processing.\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/05/1995 PWG : Created.                                             *\n *=========================================================================*/\n\nvoid File_Stream_Preload(int handle)\n{\n\tSampleTrackerType\t*st\t= &LockedData.SampleTracker[handle];\n\tint\tfh\t\t\t\t\t\t= st->FileHandle;\n\tint \tmaxnum\t\t\t\t= (LockedData.StreamBufferCount >> 1) + STREAM_CUSHION_BLOCKS;\n\tvoid \t*buffer\t\t\t\t= st->FileBuffer;\n\tint\tnum;\n\n\t/*\n\t** Figure just how much we need to load.  If we are doing the load in progress\n\t** then we will only load two blocks.\n\t*/\n\tif (st->Loading) {\n\t\tnum = st->FilePending + 2;\n\t\tnum = MIN(num, maxnum);\n\t} else {\n\t\tnum = maxnum;\n\t}\n\n\t//printf(\"Before buffer load!\\n\");\n\t/*\n\t** Loop through the blocks and load up the number we need.\n\t*/\n\tfor (int index = st->FilePending; index < num; index++) {\n\t\tlong s = Read_File(fh, Add_Long_To_Pointer(buffer, (long)index * (long)LockedData.StreamBufferSize), LockedData.StreamBufferSize);\n\t\t//printf(\"Reading block of size %d Stream Buffer = %d\\n\");\n\t\tif (s) {\n\t\t\tst->FilePendingSize = s;\n\t\t\tst->FilePending++;\n\t\t}\n\t\tif (s < LockedData.StreamBufferSize) break;\n\t}\n\n\t/*\n\t** If the last block was incomplete (ie. it didn't completely fill the buffer) or\n\t** we have now filled up as much of the Streaming Buffer as we need to, then now is\n\t** the time to kick off the sample.\n\t*/\n\tif (st->FilePendingSize < LockedData.StreamBufferSize || index == maxnum) {\n\t\t//printf(\"Before Stream Sample Volume!\\n\");\n\t\t/*\n\t\t** Actually start the sample playing, and don't worry about the file callback\n\t\t** it won't be called for a while.\n\t\t*/\n\t\t{\n\t\t\tint old\t\t\t\t\t\t= LockedData.SoundVolume;\n\t\t\tint size\t\t\t\t\t\t= (st->FilePending == 1) ? st->FilePendingSize : LockedData.StreamBufferSize;\n\t\t\tLockedData.SoundVolume\t= LockedData.ScoreVolume;\n\n\t\t\tStartingFileStream \t\t= TRUE;\n\t\t\tStream_Sample_Vol(buffer, size, File_Callback, st->Volume, handle);\n\t\t\tStartingFileStream \t\t= FALSE;\n\t\t\tLockedData.SoundVolume \t= old;\n\t\t}\n\t\t//printf(\"After Stream Sample Volume!\\n\");\n\t\t/*\n\t\t** The Sample is finished loading (if it was loading in small pieces) so record that\n\t\t** so that it will now use the active logic in the file call back.\n\t\t*/\n\t\tst->Loading\t\t\t\t\t= FALSE;\n\n\t\t/*\n\t\t** Decrement the file pending because the first block is already playing thanks\n\t\t** to the play sample call above.\n\t\t*/\n\t\tst->FilePending--;\n\n\t\t/*\n\t\t** If File pending is now a zero, then we only preloaded one block and there\n\t\t** is nothing more to play.  So clear the sample tracing structure of the\n\t\t** information it no longer needs.\n\t\t*/\n\t\tif (!st->FilePending) {\n\t\t\tst->Odd\t\t\t\t\t= 0;\n\t\t\tst->QueueBuffer\t\t= 0;\n\t\t\tst->QueueSize\t\t\t= 0;\n\t\t\tst->FilePendingSize\t= 0;\n\t\t\tst->Callback \t\t\t= NULL;\n\t\t\tClose_File(fh);\n\t\t} else {\n\t\t\t/*\n\t\t\t**\tThe QueueBuffer counts as an already played block so remove it from the total.\n\t\t\t** Note: We didn't remove it before because there might not have been one.\n\t\t\t*/\n\t\t\tst->FilePending--;\n\n\t\t\t/*\n\t\t\t** When we start loading we need to start past the first two blocks.  Why this\n\t\t\t** is called Odd, I haven't got the slightest.\n\t\t\t*/\n\t\t\tst->Odd \t\t\t\t\t= 2;\n\n\t\t\t/*\n\t\t\t** If the file pending size is less than the stream buffer, then the last block\n\t\t\t** we loaded was the last block period.  So close the file and reset the handle.\n\t\t\t*/\n\t\t\tif (st->FilePendingSize != LockedData.StreamBufferSize) {\n\t\t\t\tClose_File(fh);\n\t\t\t\tst->FileHandle = ERROR;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** The Queue buffer needs to point at the next block to be processed.  The size\n\t\t\t** of the queue is dependant on how many more blocks there are.\n\t\t\t*/\n\t\t\tst->QueueBuffer = Add_Long_To_Pointer(buffer, LockedData.StreamBufferSize);\n\t\t\tif (!st->FilePending) {\n\t\t\t\tst->QueueSize = st->FilePendingSize;\n\t\t\t} else {\n\t\t\t\tst->QueueSize = LockedData.StreamBufferSize;\n\t\t\t}\n\t\t}\n\t}\n}\n/***********************************************************************************************\n * File_Stream_Sample_Vol -- Streams a sample directly from a file.                            *\n *                                                                                             *\n *    This will take the file specified and play it directly from disk.                        *\n *    It performs this by allocating a temporary buffer in XMS/EMS and                         *\n *    then keeping this buffer filled by the Sound_Callback() routine.                         *\n *                                                                                             *\n * INPUT:   filename -- The name of the file to play.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the handle to the sound -- just like Play_Sample().                        *\n *                                                                                             *\n * WARNINGS:   The temporary buffer is allocated when this routine is                          *\n *             called and then freed when the sound is finished.  Keep                         *\n *             this in mind.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start)\n{\n\tstatic VOID\t*buffer = NULL;\n\tSampleTrackerType\t*st;\n\tint\tfh;\n\tint\thandle = -1;\n\tlong\tsize;\n\tint\tindex;\n\n\tif (LockedData.DigiHandle != -1 && filename && Find_File(filename)) {\n\t\t//printf(\"Before initialize memory!\\n\");\n\t\t/*\n\t\t**\tMake sure all sample tracker structures point to the same\n\t\t**\tupper memory buffer.  This allocation only occurs if at\n\t\t**\tleast one sample gets \"streamed\".\n\t\t*/\n\t\tif (!buffer) {\n\t\t\tbuffer = Alloc(LockedData.StreamBufferSize * LockedData.StreamBufferCount, (MemoryFlagType)(StreamBufferFlag | MEM_TEMP | MEM_LOCK));\n\t\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\t\t\tLockedData.SampleTracker[index].FileBuffer = buffer;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** If after trying to allocate the buffer we still fail then\n\t\t** we can stream this sample.\n\t\t*/\n\t\tif (!buffer) return(-1);\n\t\t\n\t\t//printf(\"Before Open File!\\n\");\n\t\t/*\n\t\t** Lets see if we can sucessfully open up the file.  If we can't, \n\t\t** then there is no point in going any farther.\n\t\t*/\n\t\tif ((fh = Open_File(filename, READ)) == -1) {\n\t\t\treturn (-1);\n\t\t}\n\n\t\t//printf(\"Before Get Free Handle!\\n\");\n\t\t/*\n\t\t** Reserve a handle so that we can fill in the sample tracker\n\t\t** with the needed information.  If we dont get valid handle then\n\t\t** we might as well give up.\n\t\t*/\n\t\tif ((unsigned)(handle = Get_Free_Sample_Handle(0xFF)) >= LockedData.MaxSamples) {\n\t\t\treturn(-1);\n\t\t}\n\n\t\t/*\n\t\t** Now lets get a pointer to the proper sample handler and start\n\t\t** our manipulations.\n\t\t*/ \n\t\tst\t\t\t\t\t\t\t= &LockedData.SampleTracker[handle];\n\t\tst->IsScore\t\t\t\t= TRUE;\n\t\tst->FilePending\t\t= 0;\n\t\tst->FilePendingSize\t= 0;\n\t\tst->Loading\t\t\t\t= real_time_start;\n\t\tst->Volume\t\t\t\t= volume;\n\t\tst->FileHandle\t\t\t= fh;\n\t\t/*\n\t\t** Now that we have setup our initial data properly, let load up\n\t\t** the beginning of the sample we intend to stream.\n\t\t*/\n\t\t//printf(\"Before Preload!\\n\");\n\t\tFile_Stream_Preload(handle);\n\t}\n\treturn (handle);\n}\n\n/***********************************************************************************************\n * Sound_Callback -- Audio driver callback function.                                           *\n *                                                                                             *\n *    Maintains the audio buffers.  This routine must be called at least                       *\n *    11 times per second or else audio glitches will occur.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If this routine is not called often enough then audio                           *\n *             glitches will occur.                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID cdecl __saveregs __loadds Sound_Callback(VOID)\n{\n\tint\t\t\t\t\tindex;\n\tSampleTrackerType\t*st;\n\n\tif (LockedData.DigiHandle != -1) {\n\t\tst = &LockedData.SampleTracker[0];\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\t\tif (st->Loading) {\n\t\t\t\tFile_Stream_Preload(index);\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t**\tGeneral service routine to handle moving small blocks from the\n\t\t\t\t**\tsource into the low RAM staging buffers.\n\t\t\t\t*/\n\n\t\t\t\tif (st->Active) {\n\t\t\t\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSpecial check to see if the sample is a fading one AND\n\t\t\t\t\t**\tit has faded to silence, then stop it here.\n\t\t\t\t\t*/\n\t\t\t\t\tif (st->Reducer && !st->Volume) {\n\t\t\t\t\t\tStop_Sample(index);\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tFill the queuebuffer if it is currently empty\n\t\t\t\t\t\t**\tand there is a callback function defined to fill it.\n\t\t\t\t\t\t**\n\t\t\t\t\t\t** PWG/CDY & CO: We should be down by at least two blocks\n\t\t\t\t\t\t**\t\t\t\t\t  before we bother with this\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif ((!st->QueueBuffer || \n\t\t\t\t\t\t\t(st->FileHandle != ERROR && st->FilePending < LockedData.StreamBufferCount-3)) && \n\t\t\t\t\t\t\tst->Callback) {\n\n\t\t\t\t\t\t\tif (!st->Callback(index, &st->Odd, &st->QueueBuffer, &st->QueueSize)) {\n\t\t\t\t\t\t\t\tst->Callback = NULL;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThis catches the case where a streaming sample gets\n\t\t\t\t\t**\taborted prematurely because of failure to call the\n\t\t\t\t\t**\tcallback function frequently enough.  In this case, the\n\t\t\t\t\t**\tsample will be flagged as inactive, but the file handle\n\t\t\t\t\t**\twill not have been closed.\n\t\t\t\t\t*/\n\t\t\t\t\tif (st->FileHandle != ERROR) {\n\t\t\t\t\t\tClose_File(st->FileHandle);\n\t\t\t\t\t\tst->FileHandle = ERROR;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAdvance to the next sample control structure.\n\t\t\t*/\n\t\t\tst++;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Load_Sample -- Loads a digitized sample into RAM.                                           *\n *                                                                                             *\n *    This routine loads a digitized sample into RAM.                                          *\n *                                                                                             *\n * INPUT:   filename -- Name of the sound file to load.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the loaded sound file.  This pointer                     *\n *          is passed to Play_Sample when playback is desired.                                 *\n *                                                                                             *\n * WARNINGS:   If there is insufficient memory to load the sample, then                        *\n *             NULL will be returned.                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *   01/06/1994 JLB : HMI version.                                                             *\n *=============================================================================================*/\nVOID *Load_Sample(char const *filename)\n{\n\tvoid *buffer = NULL;\n\tlong\tsize;\n\tint\tfh;\n\n\tif (LockedData.DigiHandle == -1 || !filename || !Find_File(filename)) {\n\t\treturn (NULL);\n\t}\n\n\tfh = Open_File(filename, READ);\n\tif (fh != ERROR) {\n\t\tsize = File_Size(fh)+sizeof(AUDHeaderType);\n\t\tbuffer = Alloc(size, MEM_NORMAL);\n\n\t\tif (buffer) {\n\t\t\tSample_Read(fh, buffer, size);\n\t\t}\n\t\tClose_File(fh);\n\t\tMisc = size;\n\t}\n\treturn(buffer);\n}\n\n\n/***********************************************************************************************\n * Load_Sample_Into_Buffer -- Loads a digitized sample into a buffer.                          *\n *                                                                                             *\n *    This routine is used to load a digitized sample into a buffer                            *\n *    provided by the programmer.  This buffer can be in XMS or EMS.                           *\n *                                                                                             *\n * INPUT:   filename -- The filename to load.                                                  *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer to load into.                                    *\n *                                                                                             *\n *          size     -- The size of the buffer to load into.                                   *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually used in the buffer.                           *\n *                                                                                             *\n * WARNINGS:   This routine will not overflow the buffer provided.  This                       *\n *             means that the buffer must be big enough to hold the data                       *\n *             or else the sound will be cut short.                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Load_Sample_Into_Buffer(char const *filename, void *buffer, long size)\n{\n\tint\tfh;\n\n\t/*\n\t**\tVerify legality of parameters.\n\t*/\n\tif (!buffer || !size || LockedData.DigiHandle == -1 || !filename || !Find_File(filename)) {\n\t\treturn (NULL);\n\t}\n\n\tfh = Open_File(filename, READ);\n\tif (fh != ERROR) {\n\t\tsize = Sample_Read(fh, buffer, size);\n\t\tClose_File(fh);\n\t} else {\n\t\treturn(0);\n\t}\n\treturn(size);\n}\n\n\n/***********************************************************************************************\n * Sample_Read -- Reads sample data from an openned file.                                      *\n *                                                                                             *\n *    This routine reads a sample file.  It is presumed that the file is                       *\n *    already positioned at the start of the sample.  From this, it can                        *\n *    determine if it is a VOC or raw data and proceed accordingly.                            *\n *                                                                                             *\n * INPUT:   fh       -- File handle of already openned sample file.                            *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer to load data into.                               *\n *                                                                                             *\n *          size     -- The size of the buffer.                                                *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually used in the buffer.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Sample_Read(int fh, void *buffer, long size)\n{\n\n\tAUDHeaderType\tRawHeader;\n\tVOID\t*outbuffer;\t\t\t\t\t// Pointer to start of raw data.\n\tlong\tactual_bytes_read;\t\t// Actual bytes read in, including header\n\n/*\n\tConversion formula for TCrate and Hz rate.\n\n\tTC = 256 - 1m/rate\n\trate = 1m / (256-TC)\n*/\n\n\tif (!buffer || fh == ERROR || size <= sizeof(RawHeader)) return(NULL);\n\tsize -= sizeof(RawHeader);\n\toutbuffer = Add_Long_To_Pointer(buffer, sizeof(RawHeader));\n\n\t\t\t\tactual_bytes_read = \n\t\t\t\t\tRead_File(fh, &RawHeader, sizeof(RawHeader));\n\n\t\t\t\tactual_bytes_read +=\n\t\t\t\t\tRead_File(fh, outbuffer, MIN(size, RawHeader.Size));\n\n\n\tMem_Copy(&RawHeader, buffer, sizeof(RawHeader));\n\treturn(actual_bytes_read);\n}\n\n\n/***********************************************************************************************\n * Free_Sample -- Frees a previously loaded digitized sample.                                  *\n *                                                                                             *\n *    Use this routine to free the memory allocated by a previous call to                      *\n *    Load_Sample.                                                                             *\n *                                                                                             *\n * INPUT:   sample   -- Pointer to the sample to be freed.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID Free_Sample(VOID const *sample)\n{\n\tif (sample) Free((void *)sample);\n}\n\nBOOL Sound_Init(int sfx, int score, int sample, RateType rate, int bits_per_sample, int max_samples, int reverse_channels)\n{\n\treturn Audio_Init(sample, -1, -1, -1, rate, bits_per_sample, max_samples, reverse_channels);\n}\n\nBOOL Audio_Init(int sample, int address, int inter, int dma, RateType rate, int bits_per_sample, int max_samples, int reverse_channels)\n{\n\tint\t\t\t\t\terror;\t// Function error return code.\n\tunsigned int \t\tport;\n\tint\t\t\t\t\tindex;\n\t_SOS_INIT_DRIVER\tinit;\t\t// Driver init structure.\n\n\tInit_Locked_Data();\n\tmemset(&LockedData.SampleTracker[0], 0, sizeof(LockedData.SampleTracker));\n\tLockedData.Rate = rate;\n\n\tBits_Per_Sample = bits_per_sample;\n\n\tsosTIMERInitSystem(_TIMER_DOS_RATE, _SOS_DEBUG_NORMAL);\n\n\tif (TimerSystemOn) {\n\t\tsosTIMERRegisterEvent(60, &Timer_Interrupt_Func, &SystemTimer);\n\t\tTickCount.Start();\n\t} else\n\t\tsosTIMERRegisterEvent(60, &HMI_TimerCallback, &SystemTimer);\n\n\t/*\n\t**\tSpecial code to handle the HMI problem with running under Windows.\n\t*/\n\tif (/*Operating_System() != OS_DOS ||*/ sample == SAMPLE_NONE) {\n\t\treturn(FALSE);\n\t}\n\n\twhile (sample) {\n\n#ifdef SIMPLE_HMI_INIT\n\n\t\tif (address == -1 || inter == -1 || dma == -1) {\n\t\t\terror = sosDIGIDetectInit((LPSTR)NULL);\n\t\t\tif (error) {\n\t\t\t\tprintf(\"Cannot initialize detection system (%d).\\n\", error);\n\t\t\t\tGet_Key();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\terror = sosDIGIDetectFindHardware(sample, &DigiCaps, &port);\n\t\t\tif (error) {\n\t\t\t\tprintf(\"Cannot find sound card specified.\\n\");\n\t\t\t\tGet_Key();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Handle the override for Address, Interrupt, and DMA settings.\n\t\t\t*/\n\t\t\terror = sosDIGIDetectGetSettings(&DigiHardware);\n\t\t\tsosDIGIDetectUnInit();\n\t\t\tif (error) {\n\t\t\t\tprintf(\"Cannot get sound card settings.\\n\");\n\t\t\t\tGet_Key();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t \tDigiHardware.wPort = address;\n\t\t\tDigiHardware.wIRQ = inter;\n\t\t\tDigiHardware.wDMA = dma;\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tInitialize the digi-system and driver.\n\t\t*/\n\t\tsosDIGIInitSystem((LPSTR)NULL, _SOS_DEBUG_NORMAL);\n\t\tinit.wBufferSize\t\t= 1024*8;\t\t\t\t// Specify the DMA buf size\n\t\tinit.lpBuffer\t\t\t= (LPSTR)NULL;\n\t\tinit.wAllocateBuffer = TRUE;\n\t\tinit.wSampleRate\t\t= rate;\t\t\t\t\t// Sample playback rate.\n\t\tinit.wParam\t\t\t\t= 19;\n\t\tinit.dwParam\t\t\t= 0;\n\t\tinit.lpFillHandler\t= NULL;\n\t\tinit.lpDriverMemory\t= (LPSTR)NULL;\n\t\tinit.lpTimerMemory\t= (LPSTR)NULL;\n\t\tinit.wTimerID\t\t\t= _SOS_NORMAL_TIMER;\n \t\t\n\t\terror = 0;\n\t\terror = sosDIGIInitDriver( (int)sample, &DigiHardware, &init, &LockedData.DigiHandle);\n\t\tif (error) {\n\t\t\tprintf(\"Unable to initialize the sound driver.\\n\");\n\t\t\tGet_Key();\n\t\t\tbreak;\n\t\t}\n\n\t\terror = 0;\n\n\n\t\tif (sample >= _GUS_8_MONO || sample <= _GUS_16_ST) {\n\t\t\terror = sosTIMERRegisterEvent(150, init.lpFillHandler, &DigiTimer);\n\t\t} else {\n\t\t\terror = sosTIMERRegisterEvent(60, init.lpFillHandler, &DigiTimer);\n\t\t}\n\t\tif (error) {\n\t\t\tprintf(\"Unable to regiser the fill handler.\\n\");\n\t\t\tGet_Key();\n\t\t\tsosDIGIUnInitDriver(LockedData.DigiHandle, TRUE, TRUE);\n\t\t\tLockedData.DigiHandle = -1;\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tAllocate a decompression buffer equal to the size of a SONARC frame\n\t\t**\tblock.\n\t\t*/\n\t\tLockedData.UncompBuffer = Alloc(LARGEST_SONARC_BLOCK + 50, (MemoryFlagType)(MEM_NORMAL|MEM_CLEAR|MEM_LOCK));\n\t\tLockedData.MaxSamples\t= max_samples;\n\n\t\t/*\n\t\t**\tAllocate private staging buffers for double buffering sound into HMI\n\t\t**\tdriver.\n\t\t*/\n\t\tDigiBuffer = Alloc(2048+(((LONG)LockedData.MaxSamples*2) * (LONG)(SFX_MINI_STAGE_BUFFER_SIZE+SONARC_MARGIN)), (MemoryFlagType)(MEM_NORMAL|MEM_CLEAR|MEM_LOCK));\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\t\tLockedData.SampleTracker[index].Buffer[0] = Add_Long_To_Pointer(DigiBuffer, ((LONG)index*2) * (LONG)(SFX_MINI_STAGE_BUFFER_SIZE+SONARC_MARGIN));\n\t\t\tLockedData.SampleTracker[index].Buffer[1] = Add_Long_To_Pointer(DigiBuffer, ((LONG)index*2+1) * (LONG)(SFX_MINI_STAGE_BUFFER_SIZE+SONARC_MARGIN));\n\t\t\tLockedData.SampleTracker[index].FileHandle = ERROR;\n\t\t\tLockedData.SampleTracker[index].QueueBuffer = NULL;\n\t\t}\n\t\terror = sosTIMERRegisterEvent(MAINTENANCE_RATE, (void (__far *)(void))maintenance_callback, &MaintainTimer);\n\t\tif (error) {\n\t\t\tprintf(\"Unable to initialize the maintenance callback.\\n\");\n\t\t\tGet_Key();\n\t\t\tsosTIMERRemoveEvent(DigiTimer);\n\t\t\tsosDIGIUnInitDriver(LockedData.DigiHandle, TRUE, TRUE);\n\t\t\tLockedData.DigiHandle = -1;\n\t\t\tbreak;\n\t\t}\n\t\tSoundType = (SFX_Type)sample;\n\t\tSampleType = (Sample_Type)sample;\n\t\tReverseChannels = reverse_channels;\n\n\t\tbreak;\n\t}\n\n\treturn(TRUE);\n}\n\n\n/***********************************************************************************************\n * Sound_End -- Uninitializes the sound driver.                                                *\n *                                                                                             *\n *    This routine will uninitialize the sound driver (if any was                              *\n *    installed).  This routine must be called at program termination                          *\n *    time.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/23/1991 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID Sound_End(VOID)\n{\n\n\tif (LockedData.DigiHandle != -1) {\n\t\tsosTIMERRemoveEvent(DigiTimer);\n\t\tsosTIMERRemoveEvent(MaintainTimer);\n\t\tsosDIGIUnInitDriver(LockedData.DigiHandle, TRUE, TRUE);\n\t\tsosDIGIUnInitSystem();\n\t\tLockedData.DigiHandle = -1;\n\t}\n\tif (DigiBuffer) {\n\t\tFree(DigiBuffer);\n\t\tDigiBuffer = 0;\n\t}\n\tif (LockedData.UncompBuffer) {\n\t\tFree(LockedData.UncompBuffer);\n\t\tLockedData.UncompBuffer = 0;\n\t}\n\tsosTIMERRemoveEvent(SystemTimer);\n\tsosTIMERUnInitSystem(0);\n\tUnlock_Locked_Data();\n}\n\n\n\n\n/***********************************************************************************************\n * Stop_Sample -- Stops any currently playing sampled sound.                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID Stop_Sample(int handle)\n{\n\tif (LockedData.DigiHandle != -1 && (unsigned)handle < LockedData.MaxSamples) {\n\n\n\t\tif (LockedData.SampleTracker[handle].Active || LockedData.SampleTracker[handle].Loading) {\n\n\t\t\t\n\t\t\tLockedData.SampleTracker[handle].Active = FALSE;\n\t\t\tif (!LockedData.SampleTracker[handle].IsScore) {\n\t\t\t\tDPMI_Unlock(LockedData.SampleTracker[handle].Original, LockedData.SampleTracker[handle].OriginalSize);\n\t\t\t\tLockedData.SampleTracker[handle].Original = NULL;\n\t\t\t}\n\t\t\tLockedData.SampleTracker[handle].Priority = 0;\n\n\t\t\t/*\n\t\t\t**\tStop the sample if it is playing.\n\t\t\t*/\n\t\t\tif (!LockedData.SampleTracker[handle].Loading) {\n\t\t\t\tsosDIGIStopSample(LockedData.DigiHandle, LockedData.SampleTracker[handle].Handle);\n\t\t\t}\n\t\t\tLockedData.SampleTracker[handle].Loading = FALSE;\n\n\t\t\t/*\n\t\t\t**\tIf this is a streaming sample, then close the source file.\n\t\t\t*/\n\t\t\tif (LockedData.SampleTracker[handle].FileHandle != ERROR) {\n\t\t\t\tClose_File(LockedData.SampleTracker[handle].FileHandle);\n\t\t\t\tLockedData.SampleTracker[handle].FileHandle = ERROR;\n\t\t\t}\n\n\t\t\tLockedData.SampleTracker[handle].QueueBuffer = NULL;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Sample_Status -- Queries the current playing sample status (if any).                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nBOOL Sample_Status(int handle)\n{\n\t/*\n\t** If its an invalid handle or we do not have a sound driver then\n\t** the sample in question is not playing.\n\t*/\n\tif (LockedData.DigiHandle == -1 || (unsigned)handle >= LockedData.MaxSamples) return(FALSE);\n\t/*\n\t** If the sample is loading, then for all intents and purposes the\n\t** sample is playing.\n\t*/\n\tif (LockedData.SampleTracker[handle].Loading) return(TRUE);\n\t/* \n\t** If the sample is not active, then it is not playing\n\t*/\n\tif (!LockedData.SampleTracker[handle].Active) return(FALSE);\n\t/*\n\t** If we made it this far, then the Sample is still playing if sos says\n\t** that it is.\n\t*/\n\treturn (!sosDIGISampleDone(LockedData.DigiHandle, LockedData.SampleTracker[handle].Handle));\n}\n\n\nBOOL Is_Sample_Playing(void const * sample)\n{\n\tint index;\n\n\tif (!sample) return FALSE;\n\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\tif (LockedData.SampleTracker[index].Original == sample && Sample_Status(index)) {\n\t\t\treturn (TRUE);\n\t\t}\n\t}\n\treturn (FALSE);\n}\n\n\nVOID Stop_Sample_Playing(void const * sample)\n{\n\tint index;\n\n\tif (sample) {\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\t\tif (LockedData.SampleTracker[index].Original == sample) {\n\t\t\t\tStop_Sample(index);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\nint Get_Free_Sample_Handle(int priority)\n{\n\tint\tid;\n\n\t/*\n\t**\tFind a free SFX holding buffer slot.\n\t*/\n\tfor (id = LockedData.MaxSamples - 1; id >= 0; id--) {\n\t\tif (!LockedData.SampleTracker[id].Active && !LockedData.SampleTracker[id].Loading) {\n\t\t\tif (!StartingFileStream && LockedData.SampleTracker[id].IsScore) {\n\t\t\t\tStartingFileStream = TRUE;\t// Ensures only one channel is kept free for scores.\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (id < 0) {\n\t\tfor (id = 0; id < LockedData.MaxSamples; id++) {\n\t\t\tif (LockedData.SampleTracker[id].Priority <= priority) break;\n\t\t}\n\t\tif (id == LockedData.MaxSamples) {\n\t\t\treturn(-1);\t\t// Cannot play!\n\t\t}\n\t\tStop_Sample(id);\t\t\t\t\t\t\t// This sample gets clobbered.\n\t}\n\tif (id == -1) {\n\t\treturn -1;\n\t}\n\tif (LockedData.SampleTracker[id].FileHandle != ERROR) {\n\t\tClose_File(LockedData.SampleTracker[id].FileHandle);\n\t\tLockedData.SampleTracker[id].FileHandle = ERROR;\n\t}\n\tif (LockedData.SampleTracker[id].Original && !LockedData.SampleTracker[id].IsScore) {\n\t\tDPMI_Unlock(LockedData.SampleTracker[id].Original, LockedData.SampleTracker[id].OriginalSize);\n\t\tLockedData.SampleTracker[id].Original = NULL;\n\t}\n\tLockedData.SampleTracker[id].IsScore = FALSE;\n\treturn(id);\n}\n\nint Play_Sample(void const *sample, int priority, int volume, signed short panloc)\n{\n\treturn(Play_Sample_Handle(sample, priority, volume, panloc, Get_Free_Sample_Handle(priority)));\n}\n/***********************************************************************************************\n * Play_Sample_Vol -- Plays a digitized sample.                                                *\n *                                                                                             *\n *    Use this routine to play a previously loaded digitized sample.                           *\n *                                                                                             *\n * INPUT:   sample   -- Sample pointer as returned from Load_Sample.                           *\n *                                                                                             *\n *          volume   -- The volume to play (0..255 with 255=loudest).                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *   05/24/1992 JLB : Volume support -- Soundblaster Pro                                       *\n *   04/22/1994 JLB : Multiple sample playback rates.                                          *\n *=============================================================================================*/\nint Play_Sample_Handle(void const *sample, int priority, int volume, signed short panloc, int id)\n{\n\tAUDHeaderType\t\t\tRawHeader;\n\t_SOS_START_SAMPLE \tstart;\n\tSampleTrackerType\t\t*st=NULL;\t// Working pointer to sample tracker structure.\n\n\tif (!sample || LockedData.DigiHandle == -1) {\n\t\treturn(-1);\n\t}\n\n\tif (id == -1) {\n\t\treturn -1;\n\t}\n\n\t/*\n\t**\tFetch the control bytes from the start of the sample data.\n\t*/\n\tMem_Copy((void *)sample, (void *)&RawHeader, sizeof(RawHeader));\n\n\t/*\n\t**\tPrepare the sample tracker structure for processing of this\n\t**\tsample.  Fill the structure with data that can be determined\n\t**\tbefore the sample is started.\n\t*/\n\tst = &LockedData.SampleTracker[id];\n\tst->Compression\t= (SCompressType) ((unsigned char)RawHeader.Compression);\n\tst->Original\t\t= sample;\n\tst->OriginalSize\t= RawHeader.Size + sizeof(RawHeader);\n\tif (!st->IsScore) {\n\t\tDPMI_Lock(st->Original, st->OriginalSize);\n\t}\n\tst->Priority\t\t= priority;\n\tst->DontTouch\t\t= FALSE;\n\tst->Odd\t\t\t\t= 0;\n\tst->Reducer\t\t\t= 0;\n\tst->Restart\t\t\t= FALSE;\n\tst->QueueBuffer\t= NULL;\n\tst->QueueSize\t\t= NULL;\n\tst->TrailerLen \t= 0;\n\tst->Remainder\t\t= RawHeader.Size;\n\tst->Source\t\t\t= Add_Long_To_Pointer((void *)sample, sizeof(RawHeader));\n\tst->Service\t\t\t= FALSE;\n\n\t/*\n \t** If the code in question using HMI based compression then we need\n\t** to set up for uncompressing it.\n\t*/\n\tif (st->Compression == SCOMP_SOS) {\n\t\tst->sosinfo.wChannels\t = (RawHeader.Flags & AUD_FLAG_STEREO) ? 2  : 1;\n\t\tst->sosinfo.wBitSize\t\t = (RawHeader.Flags & AUD_FLAG_16BIT)  ? 16 : 8;\n\t\tst->sosinfo.dwCompSize\t = RawHeader.Size;\n   \tst->sosinfo.dwUnCompSize = RawHeader.Size * ( st->sosinfo.wBitSize / 4 );\n\t   sosCODECInitStream(&st->sosinfo);\n\t}\n\n\t/*\n\t**\tFill in one or both staging buffers if possible.\n\t*/\n\t_disable();\n//\tDisable_Timer_Interrupt();\n\tif (SFX_MINI_STAGE_BUFFER_SIZE == \n\t\t\t\t\tSample_Copy(st,\n\t\t\t\t\t\t\t\t\t&st->Source, \n\t\t\t\t\t\t\t\t\t&st->Remainder, \n\t\t\t\t\t\t\t\t\t&st->QueueBuffer, \n\t\t\t\t\t\t\t\t\t&st->QueueSize, \n\t\t\t\t\t\t\t\t\tst->Buffer[0], \n\t\t\t\t\t\t\t\t\tSFX_MINI_STAGE_BUFFER_SIZE, \n\t\t\t\t\t\t\t\t\tst->Compression, \n\t\t\t\t\t\t\t\t\t&st->Trailer[0], \n\t\t\t\t\t\t\t\t\t&st->TrailerLen)) {\n\n\t\tst->DataLength = Sample_Copy(st,\n\t\t\t\t\t\t\t\t\t\t&st->Source, \n\t\t\t\t\t\t\t\t\t\t&st->Remainder, \n\t\t\t\t\t\t\t\t\t\t&st->QueueBuffer, \n\t\t\t\t\t\t\t\t\t\t&st->QueueSize, \n\t\t\t\t\t\t\t\t\t\tst->Buffer[1], \n\t\t\t\t\t\t\t\t\t\tSFX_MINI_STAGE_BUFFER_SIZE, \n\t\t\t\t\t\t\t\t\t\tst->Compression, \n\t\t\t\t\t\t\t\t\t\t&st->Trailer[0], \n\t\t\t\t\t\t\t\t\t\t&st->TrailerLen);\n\t\tst->Index = 1;\n\t} else {\n\t\tst->Index = 0;\n\t\tst->DataLength = 0;\n\t}\n\t_enable();\n//\tEnable_Timer_Interrupt();\n\n\t/*\n\t**\tFill in the HMI start sample structure.\n\t*/\n\tmemset(&start, 0, sizeof(start));\n\n\tstart.lpSamplePtr = (LPSTR)st->Buffer[0];\n\tif (st->Index == 1) {\n\t\tstart.dwSampleSize = SFX_MINI_STAGE_BUFFER_SIZE-1;\n\t} else {\n\t\tstart.dwSampleSize = st->DataLength-1;\n\t}\n\tstart.lpCallback\t= (void cdecl (far *)(unsigned int, unsigned int, unsigned int))&DigiCallback;\n\tstart.wLoopCount\t= 0;\n\tstart.wSampleID\t= id;\n\n\t/*\n\t**\tAdjust pitch shifting as necessary so that lower playback\n\t**\tsamples can be supported.\n\t*/\n\tif (RawHeader.Rate != LockedData.Rate) {\n\t\tldiv_t\tresult;\n\n\t\tresult\t\t\t\t\t\t= ldiv((long)RawHeader.Rate, LockedData.Rate);\n\t\tstart.dwSamplePitchAdd\t= (long)MAKE_LONG((short)result.quot, (short)(((long)result.rem * 0x10000L) / LockedData.Rate));\n\t\tstart.wSampleFlags \t  |= _PITCH_SHIFT;\n\t}\n\n\t/*\n\t**\tSample translation flag.\n\t*/\n\n\tif (RawHeader.Flags & AUD_FLAG_16BIT) {\n\t\tif (Bits_Per_Sample == 8) {\n\t\t\tstart.wSampleFlags \t  |= _TRANSLATE16TO8;\n\t\t}\n\t} else {\n\t\tif (Bits_Per_Sample == 16) {\n\t\t\tstart.wSampleFlags \t  |= _TRANSLATE8TO16;\n\t\t}\n\t}\n\n\t/*\n\t**\tSample stereo flag.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_STEREO) {\n\t\tstart.wChannel \t\t\t= _INTERLEAVED;\n\t\tstart.wSampleFlags \t  |= _STEREOTOMONO;\n\t} else {\n\t\tstart.wChannel \t\t\t= _CENTER_CHANNEL;\n\t}\n\n\t/*\n\t**\tSample volume control flags.  Always give it volume control because\n\t**\tif not, then future volume control is either ignored or stops the\n\t**\tsample.\n\t*/\n\tst->Volume \t\t\t\t\t\t= volume << 7;\n\tstart.wVolume\t\t\t\t\t= (st->Volume >> 8) * LockedData.SoundVolume;\n\tstart.wSampleFlags  \t\t  |= _VOLUME;\n\t\n\t/*\n\t** If we have defined a panning location for the sound driver than\n\t** take care of it here.  Panning will only work with a stereo driver\n\t** and only if the sample is played _CENTER_CHANNEL.\n\t*/\n\tif ((panloc != 0x0) && (!(RawHeader.Flags & AUD_FLAG_STEREO))) {\n\t\tstart.wChannel \t\t\t= _CENTER_CHANNEL;\n\t\tpanloc \t\t\t\t\t\t= ((ReverseChannels) ? ((-panloc) + 0x8000) : ((panloc) + 0x8000));\n\t\tstart.wSampleFlags \t  |= _PANNING;\n\t\tstart.wSamplePanLocation= panloc;\n\t}\n\n\tst->Stereo \t= start.wChannel;\n\tst->Pitch \t= start.dwSamplePitchAdd;\n\tst->Flags \t= start.wSampleFlags;\n\n\t/*\n\t**\tStart the sample playing now.\n\t*/\n\t_disable();\t\t// NEW\n//\tDisable_Timer_Interrupt();\n\tst->Handle = sosDIGIStartSample(LockedData.DigiHandle, &start);\n\tif (st->Handle == -1) {\n\t\tid = -1;\n\t} else {\n\n\t\t/*\n\t\t**\tFill in the sample tracker structure with those values that are\n\t\t**\tdetermined AFTER the sample starts.\n\t\t*/\n\t\tst->Active = TRUE;\n\t}\n\t_enable();\t\t\t// NEW\n//\tEnable_Timer_Interrupt();\n\n\treturn(id);\n}\n\n\nint Set_Sound_Vol(int volume)\n{\n\tint old;\n\told = LockedData.SoundVolume;\n\tLockedData.SoundVolume = volume & 0xFF;\n\treturn(old);\n}\n\n\nint Set_Score_Vol(int volume)\n{\n\tint old;\n\told = LockedData.ScoreVolume;\n\tLockedData.ScoreVolume = volume & 0xFF;\n\treturn(old);\n}\n\n\nVOID Fade_Sample(int handle, int ticks)\n{\n\tif (Sample_Status(handle)) {\n\t\tif (!ticks || LockedData.SampleTracker[handle].Loading) {\n\t\t\tStop_Sample(handle);\n\t\t} else {\n\t\t\tSampleTrackerType * st;\n\n\t\t\tst = &LockedData.SampleTracker[handle];\n\t\t\tst->Reducer = (st->Volume / ticks)+1;\n\t\t}\n\t}\n}\nint Get_Digi_Handle(void)\n{\n\treturn(LockedData.DigiHandle);\n}\n\n/***************************************************************************\n * SAMPLE_LENGTH -- returns length of a sample in ticks                    *\n *                                                                         *\n * INPUT:\t\tvoid const *sample - pointer to the sample to get length    *\n *\t\t\t\t\t\t\t\t\t\t\t   of.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tlong   \t\t\t\t - length of the sample in ticks (60/sec) *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/05/1995 PWG : Created.                                             *\n *=========================================================================*/\nlong Sample_Length(void const *sample)\n{\n\tAUDHeaderType\t\t\tRawHeader;\n\n\tif (!sample) return(0);\n\n\tMem_Copy((void *)sample, (void *)&RawHeader, sizeof(RawHeader));\n\n\tlong time = RawHeader.UncompSize;\n\n\t/*\n\t** If the sample is a 16 bit sample, then it will take only half\n\t** as long to play.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_16BIT) {\n\t\ttime >>= 1;\n\t}\n\n\t/*\n\t** If the sample is a stereo sample, then it will take only half\n\t** as long to play.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_STEREO) {\n\t\ttime >>= 1;\n\t}\n\n\tif (RawHeader.Rate/60) {\n\t\ttime /= (RawHeader.Rate/60);\n\t}\n\treturn(time);\n}\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/SOUNDIO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Id: soundio.cpp 1.41 1994/06/20 15:01:39 joe_bostic Exp $ */\n/***********************************************************************************************\n **             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             **\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Sound Library                                                *\n *                                                                                             *\n *                    File Name : SOUND.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 22, 1991                                                *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   File_Callback -- called to fill queue buffer for streaming sample     \t\t\t\t\t\t  *\n *   Stream_Sample_Volume -- generic streaming sample playback init                            *\n *   Stream_Sample -- generic streaming sample playback init                                   *\n *   File_Stream_Sample -- Streams a sample directly from a file.                              *\n *   File_Stream_Preload -- Handles initial proload of a streaming samples                     *\n *   File_Stream_Sample_Volume -- Streams a sample directly from a file w/volume.              *\n *   Sound_Callback -- Audio driver callback function.                                         *\n *   Load_Sample -- Loads a digitized sample into RAM.                                         *\n *   Load_Sample_Into_Buffer -- Loads a digitized sample into a buffer.                        *\n *   Free_Sample -- Frees a previously loaded digitized sample.                                *\n *   Sound_End -- Uninitializes the sound driver.                                              *\n *   Stop_Sample -- Stops any currently playing sampled sound.                                 *\n *   Sample_Status -- Queries the current playing sample status (if any).                      *\n *   Sample_Length -- returns length of a sample in ticks                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#pragma pack(4)\n#include\t\"soundint.h\"\n#include <dos.h>\n#include <mem.h>\n#include <stdio.h>\n#include <string.h>\n#include\t<direct.h>\n#include\t<stdlib.h>\n#include\t<wwmem.h>\n#include\t<keyboard.h>\n#include\t<file.h>\n#include\t<i86.h>\n#include <timer.h>\n#pragma pack(1)\n#include \"audio.h\"\n#pragma pack(4)\n\n/*\n**\tIf this is defined, then the streaming audio buffer will be filled\n**\tto maximum whenever filling is to occur. If undefined, it will fill\n**\tthe streaming buffer in smaller chunks.\n*/\n#define\tSIMPLE_FILLING\n\n/*\n**\tThis define (if present) enables the simple HMI hardware initialization process.\n**\tThe process does not do auto detection, but rather takes the value directly from\n**\tthe setup program and uses that as the sound card number.  The only \"detection\" it\n**\tdoes is to recognized the presence of the card and fetch its settings.\n*/\n#define\tSIMPLE_HMI_INIT\n\n\n/*\n**\tThis is the rate that the maintenance callback gets called.\n*/\n#define\tMAINTENANCE_RATE\t\t\t60\n\n/*\n**\tSize of the temporary buffer in XMS/EMS that direct file\n**\tstreaming of sounds will allocate.\n*/\n#define\tSTREAM_BUFFER_SIZE\t\t(128L*1024L)\n\n/*\n** Define the number of \"StreamBufferSize\" blocks that are read in\n** at a minimum when the streaming sample load callback routine\n** is called.  We will IGNORE loads that are less that this in order\n** to avoid constant seeking on the CD.\n*/\n#define\tSTREAM_CUSHION_BLOCKS\t4\n\n\n/*\n**\tThis is the maximum size that a sonarc block can be.  All sonarc blocks\n**\tmust be either a multiple of this value or a binary root of this value.\n*/\n#define\tLARGEST_SONARC_BLOCK\t\t2048\n\n\n//////////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////// structs ///////////////////////////////////////\n\nstatic _SOS_CAPABILITIES\tDigiCaps;\nstatic _SOS_HARDWARE \t\tDigiHardware;\nstatic WORD \t\t\t\t\tMidiHandle = -1;\nstatic unsigned int far\t\tDigiTimer = 0;\nstatic unsigned int far\t\tMaintainTimer = 0;\nstatic unsigned int far\t\tSystemTimer = 0;\nstatic int\t\t\t\t\t\tBits_Per_Sample;\nVOID \t\t\t\t\t\t\t\t*DigiBuffer = NULL;\nstatic BOOL \t\t\t\t\tStartingFileStream = FALSE;\nshort \t\t\t\t\t\t\tStreamLowImpact = FALSE;\nMemoryFlagType \t\t\t\tStreamBufferFlag = MEM_NORMAL;\nint \t\t\t\t\t\t\t\tMisc;\nSFX_Type \t\t\t\t\t\tSoundType;\nSample_Type \t\t\t\t\tSampleType;\nint\t\t\t\t\t\t\t\tReverseChannels = FALSE;\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nstatic BOOL File_Callback(WORD id, WORD *odd, VOID **buffer, LONG *size);\nstatic int cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback)(WORD id, WORD *odd, VOID **buffer, LONG *size), int volume, int handle);\nstatic int cdecl Stream_Sample(void *buffer, long size, BOOL (*callback)(WORD id, WORD *odd, VOID **buffer, LONG *size));\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n\n/***************************************************************************\n * FILE_CALLBACK -- called to fill queue buffer for streaming sample       *\n *                                                                         *\n * This callback is called whenever the queue buffer playback has begun\t\t*\n * and another buffer is needed for queuing up.  Returns TRUE if there\t\t*\n * is more data to read from the file.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:\tWORD id\t\t\t- the sample id number                          *\n *\t\t\t\tWORD *odd\t\t- which sample buffer to put info in\t\t\t\t*\n *\t\t\t\tVOID **buffer\t- the buffer pointer to load data into\t\t\t\t*\n *\t\t\t\tLONG *size\t\t- the amount to load\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:  BOOL true if more data to load, FALSE if done loading          *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nstatic BOOL File_Callback(WORD id, WORD *odd, VOID **buffer, LONG *size)\n{\n\tSampleTrackerType\t*st;\t\t// Pointer to sample playback control struct.\n\tVOID\t\t\t\t\t*ptr;\t\t// Pointer to working portion of file buffer.\n\n\tif (id != -1) {\n\t\tst = &LockedData.SampleTracker[id];\n\t\tptr = st->FileBuffer;\n\t\tif (ptr) {\n\n\t\t\t/*\n\t\t\t**\tMove the next pending block into the primary \n\t\t\t**\tposition.  Do this only if the queue pointer is\n\t\t\t**\tnull.\n\t\t\t*/\n\t\t\tst->DontTouch = TRUE;\n\t\t\tif (!*buffer && st->FilePending) {\n\t\t\t\t*buffer = Add_Long_To_Pointer(ptr, (long)(*odd % LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t\t\t\tst->FilePending--;\n\t\t\t\t*odd = *odd + 1;\n\t\t\t\tif (!st->FilePending) {\n\t\t\t\t\t*size = st->FilePendingSize;\n\t\t\t\t} else {\n\t\t\t\t\t*size = LockedData.StreamBufferSize;\n\t\t\t\t}\n\t\t\t}\n\t\t\tst->DontTouch = FALSE;\n\t\t\tmaintenance_callback();\n\n\t\t\t/*\n\t\t\t**\tIf the file handle is still valid, then read in the next\n\t\t\t**\tblock and add it to the next pending slot available.\n\t\t\t*/\n\t\t\tif (st->FilePending <\n\t\t\t\t(StreamLowImpact ? (LockedData.StreamBufferCount>>1) : ((LockedData.StreamBufferCount-3))) && st->FileHandle != ERROR) {\n\n\n\t\t\t\tint num_empty_buffers;\n\n#ifdef SIMPLE_FILLING\n\t\t\t\tnum_empty_buffers = (LockedData.StreamBufferCount-2) - st->FilePending;\n#else\n\n\t\t\t\t//\n\t\t\t\t// num_empty_buffers will be from 1 to StreamBufferCount\n\t\t\t\t//\n\t\t\t\tif (StreamLowImpact) {\n\t\t\t\t\tnum_empty_buffers = MIN((LockedData.StreamBufferCount >> 1)+STREAM_CUSHION_BLOCKS, (LockedData.StreamBufferCount - 2) - st->FilePending);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tnum_empty_buffers = (LockedData.StreamBufferCount - 2) - st->FilePending;\n\t\t\t\t}\n#endif\n\t\t\t\t\n\n\n\t\t\t\twhile (num_empty_buffers && st->FileHandle != ERROR) {\n\t\t\t\t\tint\ttofill;\n\t\t\t\t\tlong\tpsize;\n\n\t\t\t\t\ttofill = (*odd + st->FilePending) % LockedData.StreamBufferCount;\n\n\t\t\t\t\tptr = Add_Long_To_Pointer(st->FileBuffer, (long)tofill * (long)LockedData.StreamBufferSize);\n\t\t\t\t\tpsize = Read_File(st->FileHandle, ptr, LockedData.StreamBufferSize);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf less than the requested amount of data was read, this\n\t\t\t\t\t**\tindicates that the source file is exhausted.  Flag the source\n\t\t\t\t\t**\tfile as closed so that no further reading is attempted.\n\t\t\t\t\t*/\n\t\t\t\t\tif (psize != LockedData.StreamBufferSize) {\n\t\t\t\t\t\tClose_File(st->FileHandle);\n\t\t\t\t\t\tst->FileHandle = ERROR;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf any real data went into the pending buffer, then flag\n\t\t\t\t\t**\tthat this buffer is valid.\n\t\t\t\t\t*/\n\t\t\t\t\tif (psize) {\n\t\t\t\t\t\tst->DontTouch = TRUE;\n\t\t\t\t\t\tst->FilePendingSize = psize;\n\t\t\t\t\t\tst->FilePending++;\n\t\t\t\t\t\tst->DontTouch = FALSE;\n\t\t\t\t\t\tmaintenance_callback();\n\t\t\t\t\t}\n\t\t\t\t\tnum_empty_buffers--;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAfter filling all pending buffers, check to see if the queue buffer\n\t\t\t\t**\tis empty.  If so, then assign the first available pending buffer to the\n\t\t\t\t**\tqueue.\n\t\t\t\t*/\n\t\t\t\tst->DontTouch = TRUE;\n\t\t\t\tif (!st->QueueBuffer && st->FilePending) {\n\t\t\t\t\tst->QueueBuffer = Add_Long_To_Pointer(st->FileBuffer, (long)(st->Odd%LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t\t\t\t\tst->FilePending--;\n\t\t\t\t\tst->Odd++;\n\t\t\t\t\tif (!st->FilePending) {\n\t\t\t\t\t\tst->QueueSize = st->FilePendingSize;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tst->QueueSize = LockedData.StreamBufferSize;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tst->DontTouch = FALSE;\n\t\t\t\tmaintenance_callback();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf there are no more buffers that the callback routine\n\t\t\t**\tcan slot into the primary position, then signal that\n\t\t\t**\tno furthur callbacks are needed.\n\t\t\t*/\n\t\t\tif (st->FilePending) {\n\t\t\t\treturn(TRUE);\n\t\t\t}\n\t\t}\n\t}\n\treturn(FALSE);\n}\n\n/***************************************************************************\n * STREAM_SAMPLE_VOLUME -- generic streaming sample playback init          *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nstatic int cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback)(WORD id, WORD *odd, VOID **buffer, LONG *size), int volume, int handle)\n{\n\tint\t\t\t\t\t\tplayid=-1;\t// Sample play ID.\n\tSampleTrackerType\t\t*st;\t\t\t// Working pointer to sample control structure.\n\tlong\t\t\t\t\t\toldsize;\t\t// Copy of original sound size.\n\tAUDHeaderType\t\t\theader;\n\n\tif (buffer && size && LockedData.DigiHandle != -1) {\n\n\t\t/*\n\t\t**\tStart the first section of the sound playing.\n\t\t*/\n\t\tMem_Copy(buffer, &header, sizeof(header));\n\t\toldsize = header.Size;\n\t\theader.Size = size-sizeof(header);\n\t\tMem_Copy(&header, buffer, sizeof(header));\n\t\tplayid = Play_Sample_Handle(buffer, 0xFF, volume, 0x0, handle);\n\t\theader.Size = oldsize;\n\t\tMem_Copy(&header, buffer, sizeof(header));\n\n\t\t/*\n\t\t**\tIf the sample actually started playing, then flag this\n\t\t**\tsample as a streaming type and signal for a callback\n\t\t**\tto occur.\n\t\t*/\n\t\tif (playid != -1) {\n\t\t\tst = &LockedData.SampleTracker[playid];\n\n\t\t\tst->Callback = callback;\n\t\t\tst->Odd = 0;\n\t\t}\n\t}\n\treturn (playid);\n}\n\n/***************************************************************************\n * STREAM_SAMPLE -- generic streaming sample playback init          \t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nstatic int cdecl Stream_Sample(void *buffer, long size, BOOL (*callback)(WORD id, WORD *odd, VOID **buffer, LONG *size), int handle)\n{\n\treturn Stream_Sample_Vol(buffer, size, callback, 0xFF, handle);\n}\n\n\n\n/***********************************************************************************************\n * File_Stream_Sample -- Streams a sample directly from a file.                                *\n *                                                                                             *\n *    This will take the file specified and play it directly from disk.                        *\n *    It performs this by allocating a temporary buffer in XMS/EMS and                         *\n *    then keeping this buffer filled by the Sound_Callback() routine.                         *\n *                                                                                             *\n * INPUT:   filename -- The name of the file to play.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the handle to the sound -- just like Play_Sample().                        *\n *                                                                                             *\n * WARNINGS:   The temporary buffer is allocated when this routine is                          *\n *             called and then freed when the sound is finished.  Keep                         *\n *             this in mind.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint File_Stream_Sample(char const *filename, BOOL real_time_start)\n{\n\treturn File_Stream_Sample_Vol(filename, 0xFF, real_time_start);\n}\n\n/***************************************************************************\n * FILE_STREAM_PRELOAD -- Handles initial proload of streaming samples     *\n *                                                                         *\n * This function is called before a sample which streams from disk is      *\n * started.  It can be called to either fill the buffer in small chunks\t\t*\n * from the call back routine or to fill the entire buffer at once.  This\t*\n * is wholely dependant on whether the Loading bit is set within the \t\t*\n * sample tracker.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:\t\tLockedData.SampleTracker * to the header which tracks this samples     *\n *\t\t\t\t\t\t\t\t\t\t processing.\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/05/1995 PWG : Created.                                             *\n *=========================================================================*/\n\nvoid File_Stream_Preload(int handle)\n{\n\tSampleTrackerType\t*st\t= &LockedData.SampleTracker[handle];\n\tint\tfh\t\t\t\t\t\t= st->FileHandle;\n\tint \tmaxnum\t\t\t\t= (LockedData.StreamBufferCount >> 1) + STREAM_CUSHION_BLOCKS;\n\tvoid \t*buffer\t\t\t\t= st->FileBuffer;\n\tint\tnum;\n\n\t/*\n\t** Figure just how much we need to load.  If we are doing the load in progress\n\t** then we will only load two blocks.\n\t*/\n\tif (st->Loading) {\n\t\tnum = st->FilePending + 2;\n\t\tnum = MIN(num, maxnum);\n\t} else {\n\t\tnum = maxnum;\n\t}\n\n\t//printf(\"Before buffer load!\\n\");\n\t/*\n\t** Loop through the blocks and load up the number we need.\n\t*/\n\tfor (int index = st->FilePending; index < num; index++) {\n\t\tlong s = Read_File(fh, Add_Long_To_Pointer(buffer, (long)index * (long)LockedData.StreamBufferSize), LockedData.StreamBufferSize);\n\t\t//printf(\"Reading block of size %d Stream Buffer = %d\\n\");\n\t\tif (s) {\n\t\t\tst->FilePendingSize = s;\n\t\t\tst->FilePending++;\n\t\t}\n\t\tif (s < LockedData.StreamBufferSize) break;\n\t}\n\n\t/*\n\t** If the last block was incomplete (ie. it didn't completely fill the buffer) or\n\t** we have now filled up as much of the Streaming Buffer as we need to, then now is\n\t** the time to kick off the sample.\n\t*/\n\tif (st->FilePendingSize < LockedData.StreamBufferSize || index == maxnum) {\n\t\t//printf(\"Before Stream Sample Volume!\\n\");\n\t\t/*\n\t\t** Actually start the sample playing, and don't worry about the file callback\n\t\t** it won't be called for a while.\n\t\t*/\n\t\t{\n\t\t\tint old\t\t\t\t\t\t= LockedData.SoundVolume;\n\t\t\tint size\t\t\t\t\t\t= (st->FilePending == 1) ? st->FilePendingSize : LockedData.StreamBufferSize;\n\t\t\tLockedData.SoundVolume\t= LockedData.ScoreVolume;\n\n\t\t\tStartingFileStream \t\t= TRUE;\n\t\t\tStream_Sample_Vol(buffer, size, File_Callback, st->Volume, handle);\n\t\t\tStartingFileStream \t\t= FALSE;\n\t\t\tLockedData.SoundVolume \t= old;\n\t\t}\n\t\t//printf(\"After Stream Sample Volume!\\n\");\n\t\t/*\n\t\t** The Sample is finished loading (if it was loading in small pieces) so record that\n\t\t** so that it will now use the active logic in the file call back.\n\t\t*/\n\t\tst->Loading\t\t\t\t\t= FALSE;\n\n\t\t/*\n\t\t** Decrement the file pending because the first block is already playing thanks\n\t\t** to the play sample call above.\n\t\t*/\n\t\tst->FilePending--;\n\n\t\t/*\n\t\t** If File pending is now a zero, then we only preloaded one block and there\n\t\t** is nothing more to play.  So clear the sample tracing structure of the\n\t\t** information it no longer needs.\n\t\t*/\n\t\tif (!st->FilePending) {\n\t\t\tst->Odd\t\t\t\t\t= 0;\n\t\t\tst->QueueBuffer\t\t= 0;\n\t\t\tst->QueueSize\t\t\t= 0;\n\t\t\tst->FilePendingSize\t= 0;\n\t\t\tst->Callback \t\t\t= NULL;\n\t\t\tClose_File(fh);\n\t\t} else {\n\t\t\t/*\n\t\t\t**\tThe QueueBuffer counts as an already played block so remove it from the total.\n\t\t\t** Note: We didn't remove it before because there might not have been one.\n\t\t\t*/\n\t\t\tst->FilePending--;\n\n\t\t\t/*\n\t\t\t** When we start loading we need to start past the first two blocks.  Why this\n\t\t\t** is called Odd, I haven't got the slightest.\n\t\t\t*/\n\t\t\tst->Odd \t\t\t\t\t= 2;\n\n\t\t\t/*\n\t\t\t** If the file pending size is less than the stream buffer, then the last block\n\t\t\t** we loaded was the last block period.  So close the file and reset the handle.\n\t\t\t*/\n\t\t\tif (st->FilePendingSize != LockedData.StreamBufferSize) {\n\t\t\t\tClose_File(fh);\n\t\t\t\tst->FileHandle = ERROR;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** The Queue buffer needs to point at the next block to be processed.  The size\n\t\t\t** of the queue is dependant on how many more blocks there are.\n\t\t\t*/\n\t\t\tst->QueueBuffer = Add_Long_To_Pointer(buffer, LockedData.StreamBufferSize);\n\t\t\tif (!st->FilePending) {\n\t\t\t\tst->QueueSize = st->FilePendingSize;\n\t\t\t} else {\n\t\t\t\tst->QueueSize = LockedData.StreamBufferSize;\n\t\t\t}\n\t\t}\n\t}\n}\n/***********************************************************************************************\n * File_Stream_Sample_Vol -- Streams a sample directly from a file.                            *\n *                                                                                             *\n *    This will take the file specified and play it directly from disk.                        *\n *    It performs this by allocating a temporary buffer in XMS/EMS and                         *\n *    then keeping this buffer filled by the Sound_Callback() routine.                         *\n *                                                                                             *\n * INPUT:   filename -- The name of the file to play.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the handle to the sound -- just like Play_Sample().                        *\n *                                                                                             *\n * WARNINGS:   The temporary buffer is allocated when this routine is                          *\n *             called and then freed when the sound is finished.  Keep                         *\n *             this in mind.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start)\n{\n\tstatic VOID\t*buffer = NULL;\n\tSampleTrackerType\t*st;\n\tint\tfh;\n\tint\thandle = -1;\n\tlong\tsize;\n\tint\tindex;\n\n\tif (LockedData.DigiHandle != -1 && filename && Find_File(filename)) {\n\t\t//printf(\"Before initialize memory!\\n\");\n\t\t/*\n\t\t**\tMake sure all sample tracker structures point to the same\n\t\t**\tupper memory buffer.  This allocation only occurs if at\n\t\t**\tleast one sample gets \"streamed\".\n\t\t*/\n\t\tif (!buffer) {\n\t\t\tbuffer = Alloc(LockedData.StreamBufferSize * LockedData.StreamBufferCount, (MemoryFlagType)(StreamBufferFlag | MEM_TEMP | MEM_LOCK));\n\t\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\t\t\tLockedData.SampleTracker[index].FileBuffer = buffer;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** If after trying to allocate the buffer we still fail then\n\t\t** we can stream this sample.\n\t\t*/\n\t\tif (!buffer) return(-1);\n\t\t\n\t\t//printf(\"Before Open File!\\n\");\n\t\t/*\n\t\t** Lets see if we can sucessfully open up the file.  If we can't, \n\t\t** then there is no point in going any farther.\n\t\t*/\n\t\tif ((fh = Open_File(filename, READ)) == -1) {\n\t\t\treturn (-1);\n\t\t}\n\n\t\t//printf(\"Before Get Free Handle!\\n\");\n\t\t/*\n\t\t** Reserve a handle so that we can fill in the sample tracker\n\t\t** with the needed information.  If we dont get valid handle then\n\t\t** we might as well give up.\n\t\t*/\n\t\tif ((unsigned)(handle = Get_Free_Sample_Handle(0xFF)) >= LockedData.MaxSamples) {\n\t\t\treturn(-1);\n\t\t}\n\n\t\t/*\n\t\t** Now lets get a pointer to the proper sample handler and start\n\t\t** our manipulations.\n\t\t*/ \n\t\tst\t\t\t\t\t\t\t= &LockedData.SampleTracker[handle];\n\t\tst->IsScore\t\t\t\t= TRUE;\n\t\tst->FilePending\t\t= 0;\n\t\tst->FilePendingSize\t= 0;\n\t\tst->Loading\t\t\t\t= real_time_start;\n\t\tst->Volume\t\t\t\t= volume;\n\t\tst->FileHandle\t\t\t= fh;\n\t\t/*\n\t\t** Now that we have setup our initial data properly, let load up\n\t\t** the beginning of the sample we intend to stream.\n\t\t*/\n\t\t//printf(\"Before Preload!\\n\");\n\t\tFile_Stream_Preload(handle);\n\t}\n\treturn (handle);\n}\n\n/***********************************************************************************************\n * Sound_Callback -- Audio driver callback function.                                           *\n *                                                                                             *\n *    Maintains the audio buffers.  This routine must be called at least                       *\n *    11 times per second or else audio glitches will occur.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If this routine is not called often enough then audio                           *\n *             glitches will occur.                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID cdecl __saveregs __loadds Sound_Callback(VOID)\n{\n\tint\t\t\t\t\tindex;\n\tSampleTrackerType\t*st;\n\n\tif (LockedData.DigiHandle != -1) {\n\t\tst = &LockedData.SampleTracker[0];\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\t\tif (st->Loading) {\n\t\t\t\tFile_Stream_Preload(index);\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t**\tGeneral service routine to handle moving small blocks from the\n\t\t\t\t**\tsource into the low RAM staging buffers.\n\t\t\t\t*/\n\n\t\t\t\tif (st->Active) {\n\t\t\t\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSpecial check to see if the sample is a fading one AND\n\t\t\t\t\t**\tit has faded to silence, then stop it here.\n\t\t\t\t\t*/\n\t\t\t\t\tif (st->Reducer && !st->Volume) {\n\t\t\t\t\t\tStop_Sample(index);\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tFill the queuebuffer if it is currently empty\n\t\t\t\t\t\t**\tand there is a callback function defined to fill it.\n\t\t\t\t\t\t**\n\t\t\t\t\t\t** PWG/CDY & CO: We should be down by at least two blocks\n\t\t\t\t\t\t**\t\t\t\t\t  before we bother with this\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif ((!st->QueueBuffer || \n\t\t\t\t\t\t\t(st->FileHandle != ERROR && st->FilePending < LockedData.StreamBufferCount-3)) && \n\t\t\t\t\t\t\tst->Callback) {\n\n\t\t\t\t\t\t\tif (!st->Callback(index, &st->Odd, &st->QueueBuffer, &st->QueueSize)) {\n\t\t\t\t\t\t\t\tst->Callback = NULL;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThis catches the case where a streaming sample gets\n\t\t\t\t\t**\taborted prematurely because of failure to call the\n\t\t\t\t\t**\tcallback function frequently enough.  In this case, the\n\t\t\t\t\t**\tsample will be flagged as inactive, but the file handle\n\t\t\t\t\t**\twill not have been closed.\n\t\t\t\t\t*/\n\t\t\t\t\tif (st->FileHandle != ERROR) {\n\t\t\t\t\t\tClose_File(st->FileHandle);\n\t\t\t\t\t\tst->FileHandle = ERROR;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAdvance to the next sample control structure.\n\t\t\t*/\n\t\t\tst++;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Load_Sample -- Loads a digitized sample into RAM.                                           *\n *                                                                                             *\n *    This routine loads a digitized sample into RAM.                                          *\n *                                                                                             *\n * INPUT:   filename -- Name of the sound file to load.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the loaded sound file.  This pointer                     *\n *          is passed to Play_Sample when playback is desired.                                 *\n *                                                                                             *\n * WARNINGS:   If there is insufficient memory to load the sample, then                        *\n *             NULL will be returned.                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *   01/06/1994 JLB : HMI version.                                                             *\n *=============================================================================================*/\nVOID *Load_Sample(char const *filename)\n{\n\tvoid *buffer = NULL;\n\tlong\tsize;\n\tint\tfh;\n\n\tif (LockedData.DigiHandle == -1 || !filename || !Find_File(filename)) {\n\t\treturn (NULL);\n\t}\n\n\tfh = Open_File(filename, READ);\n\tif (fh != ERROR) {\n\t\tsize = File_Size(fh)+sizeof(AUDHeaderType);\n\t\tbuffer = Alloc(size, MEM_NORMAL);\n\n\t\tif (buffer) {\n\t\t\tSample_Read(fh, buffer, size);\n\t\t}\n\t\tClose_File(fh);\n\t\tMisc = size;\n\t}\n\treturn(buffer);\n}\n\n\n/***********************************************************************************************\n * Load_Sample_Into_Buffer -- Loads a digitized sample into a buffer.                          *\n *                                                                                             *\n *    This routine is used to load a digitized sample into a buffer                            *\n *    provided by the programmer.  This buffer can be in XMS or EMS.                           *\n *                                                                                             *\n * INPUT:   filename -- The filename to load.                                                  *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer to load into.                                    *\n *                                                                                             *\n *          size     -- The size of the buffer to load into.                                   *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually used in the buffer.                           *\n *                                                                                             *\n * WARNINGS:   This routine will not overflow the buffer provided.  This                       *\n *             means that the buffer must be big enough to hold the data                       *\n *             or else the sound will be cut short.                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Load_Sample_Into_Buffer(char const *filename, void *buffer, long size)\n{\n\tint\tfh;\n\n\t/*\n\t**\tVerify legality of parameters.\n\t*/\n\tif (!buffer || !size || LockedData.DigiHandle == -1 || !filename || !Find_File(filename)) {\n\t\treturn (NULL);\n\t}\n\n\tfh = Open_File(filename, READ);\n\tif (fh != ERROR) {\n\t\tsize = Sample_Read(fh, buffer, size);\n\t\tClose_File(fh);\n\t} else {\n\t\treturn(0);\n\t}\n\treturn(size);\n}\n\n\n/***********************************************************************************************\n * Sample_Read -- Reads sample data from an openned file.                                      *\n *                                                                                             *\n *    This routine reads a sample file.  It is presumed that the file is                       *\n *    already positioned at the start of the sample.  From this, it can                        *\n *    determine if it is a VOC or raw data and proceed accordingly.                            *\n *                                                                                             *\n * INPUT:   fh       -- File handle of already openned sample file.                            *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer to load data into.                               *\n *                                                                                             *\n *          size     -- The size of the buffer.                                                *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually used in the buffer.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Sample_Read(int fh, void *buffer, long size)\n{\n\n\tAUDHeaderType\tRawHeader;\n\tVOID\t*outbuffer;\t\t\t\t\t// Pointer to start of raw data.\n\tlong\tactual_bytes_read;\t\t// Actual bytes read in, including header\n\n/*\n\tConversion formula for TCrate and Hz rate.\n\n\tTC = 256 - 1m/rate\n\trate = 1m / (256-TC)\n*/\n\n\tif (!buffer || fh == ERROR || size <= sizeof(RawHeader)) return(NULL);\n\tsize -= sizeof(RawHeader);\n\toutbuffer = Add_Long_To_Pointer(buffer, sizeof(RawHeader));\n\n\t\t\t\tactual_bytes_read = \n\t\t\t\t\tRead_File(fh, &RawHeader, sizeof(RawHeader));\n\n\t\t\t\tactual_bytes_read +=\n\t\t\t\t\tRead_File(fh, outbuffer, MIN(size, RawHeader.Size));\n\n\n\tMem_Copy(&RawHeader, buffer, sizeof(RawHeader));\n\treturn(actual_bytes_read);\n}\n\n\n/***********************************************************************************************\n * Free_Sample -- Frees a previously loaded digitized sample.                                  *\n *                                                                                             *\n *    Use this routine to free the memory allocated by a previous call to                      *\n *    Load_Sample.                                                                             *\n *                                                                                             *\n * INPUT:   sample   -- Pointer to the sample to be freed.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID Free_Sample(VOID const *sample)\n{\n\tif (sample) Free((void *)sample);\n}\n\nBOOL Sound_Init(int sfx, int score, int sample, RateType rate, int bits_per_sample, int max_samples, int reverse_channels)\n{\n\treturn Audio_Init(sample, -1, -1, -1, rate, bits_per_sample, max_samples, reverse_channels);\n}\n\nBOOL Audio_Init(int sample, int address, int inter, int dma, RateType rate, int bits_per_sample, int max_samples, int reverse_channels)\n{\n\tint\t\t\t\t\terror;\t// Function error return code.\n\tunsigned int \t\tport;\n\tint\t\t\t\t\tindex;\n\t_SOS_INIT_DRIVER\tinit;\t\t// Driver init structure.\n\n\tInit_Locked_Data();\n\tmemset(&LockedData.SampleTracker[0], 0, sizeof(LockedData.SampleTracker));\n\tLockedData.Rate = rate;\n\n\tBits_Per_Sample = bits_per_sample;\n\n\tsosTIMERInitSystem(_TIMER_DOS_RATE, _SOS_DEBUG_NORMAL);\n\n\tif (TimerSystemOn) {\n\t\tsosTIMERRegisterEvent(60, &Timer_Interrupt_Func, &SystemTimer);\n\t\tTickCount.Start();\n\t} else\n\t\tsosTIMERRegisterEvent(60, &HMI_TimerCallback, &SystemTimer);\n\n\t/*\n\t**\tSpecial code to handle the HMI problem with running under Windows.\n\t*/\n\tif (/*Operating_System() != OS_DOS ||*/ sample == SAMPLE_NONE) {\n\t\treturn(FALSE);\n\t}\n\n\twhile (sample) {\n\n#ifdef SIMPLE_HMI_INIT\n\n\t\tif (address == -1 || inter == -1 || dma == -1) {\n\t\t\terror = sosDIGIDetectInit((LPSTR)NULL);\n\t\t\tif (error) {\n\t\t\t\tprintf(\"Cannot initialize detection system (%d).\\n\", error);\n\t\t\t\tGet_Key();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\terror = sosDIGIDetectFindHardware(sample, &DigiCaps, &port);\n\t\t\tif (error) {\n\t\t\t\tprintf(\"Cannot find sound card specified.\\n\");\n\t\t\t\tGet_Key();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Handle the override for Address, Interrupt, and DMA settings.\n\t\t\t*/\n\t\t\terror = sosDIGIDetectGetSettings(&DigiHardware);\n\t\t\tsosDIGIDetectUnInit();\n\t\t\tif (error) {\n\t\t\t\tprintf(\"Cannot get sound card settings.\\n\");\n\t\t\t\tGet_Key();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t \tDigiHardware.wPort = address;\n\t\t\tDigiHardware.wIRQ = inter;\n\t\t\tDigiHardware.wDMA = dma;\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tInitialize the digi-system and driver.\n\t\t*/\n\t\tsosDIGIInitSystem((LPSTR)NULL, _SOS_DEBUG_NORMAL);\n\t\tinit.wBufferSize\t\t= 1024*8;\t\t\t\t// Specify the DMA buf size\n\t\tinit.lpBuffer\t\t\t= (LPSTR)NULL;\n\t\tinit.wAllocateBuffer = TRUE;\n\t\tinit.wSampleRate\t\t= rate;\t\t\t\t\t// Sample playback rate.\n\t\tinit.wParam\t\t\t\t= 19;\n\t\tinit.dwParam\t\t\t= 0;\n\t\tinit.lpFillHandler\t= NULL;\n\t\tinit.lpDriverMemory\t= (LPSTR)NULL;\n\t\tinit.lpTimerMemory\t= (LPSTR)NULL;\n\t\tinit.wTimerID\t\t\t= _SOS_NORMAL_TIMER;\n \t\t\n\t\terror = 0;\n\t\terror = sosDIGIInitDriver( (int)sample, &DigiHardware, &init, &LockedData.DigiHandle);\n\t\tif (error) {\n\t\t\tprintf(\"Unable to initialize the sound driver.\\n\");\n\t\t\tGet_Key();\n\t\t\tbreak;\n\t\t}\n\n\t\terror = 0;\n\n\n\t\tif (sample >= _GUS_8_MONO && sample <= _GUS_16_ST) {\n\t\t\terror = sosTIMERRegisterEvent(120, init.lpFillHandler, &DigiTimer);\n\t\t} else {\n\t\t\terror = sosTIMERRegisterEvent(60, init.lpFillHandler, &DigiTimer);\n\t\t}\n\t\tif (error) {\n\t\t\tprintf(\"Unable to regiser the fill handler.\\n\");\n\t\t\tGet_Key();\n\t\t\tsosDIGIUnInitDriver(LockedData.DigiHandle, TRUE, TRUE);\n\t\t\tLockedData.DigiHandle = -1;\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tAllocate a decompression buffer equal to the size of a SONARC frame\n\t\t**\tblock.\n\t\t*/\n\t\tLockedData.UncompBuffer = Alloc(LARGEST_SONARC_BLOCK + 50, (MemoryFlagType)(MEM_NORMAL|MEM_CLEAR|MEM_LOCK));\n\t\tLockedData.MaxSamples\t= max_samples;\n\n\t\t/*\n\t\t**\tAllocate private staging buffers for double buffering sound into HMI\n\t\t**\tdriver.\n\t\t*/\n\t\tDigiBuffer = Alloc(2048+(((LONG)LockedData.MaxSamples*2) * (LONG)(SFX_MINI_STAGE_BUFFER_SIZE+SONARC_MARGIN)), (MemoryFlagType)(MEM_NORMAL|MEM_CLEAR|MEM_LOCK));\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\t\tLockedData.SampleTracker[index].Buffer[0] = Add_Long_To_Pointer(DigiBuffer, ((LONG)index*2) * (LONG)(SFX_MINI_STAGE_BUFFER_SIZE+SONARC_MARGIN));\n\t\t\tLockedData.SampleTracker[index].Buffer[1] = Add_Long_To_Pointer(DigiBuffer, ((LONG)index*2+1) * (LONG)(SFX_MINI_STAGE_BUFFER_SIZE+SONARC_MARGIN));\n\t\t\tLockedData.SampleTracker[index].FileHandle = ERROR;\n\t\t\tLockedData.SampleTracker[index].QueueBuffer = NULL;\n\t\t}\n\t\terror = sosTIMERRegisterEvent(MAINTENANCE_RATE, (void (__far *)(void))maintenance_callback, &MaintainTimer);\n\t\tif (error) {\n\t\t\tprintf(\"Unable to initialize the maintenance callback.\\n\");\n\t\t\tGet_Key();\n\t\t\tsosTIMERRemoveEvent(DigiTimer);\n\t\t\tsosDIGIUnInitDriver(LockedData.DigiHandle, TRUE, TRUE);\n\t\t\tLockedData.DigiHandle = -1;\n\t\t\tbreak;\n\t\t}\n\t\tSoundType = (SFX_Type)sample;\n\t\tSampleType = (Sample_Type)sample;\n\t\tReverseChannels = reverse_channels;\n\n\t\tbreak;\n\t}\n\n\treturn(TRUE);\n}\n\n\n/***********************************************************************************************\n * Sound_End -- Uninitializes the sound driver.                                                *\n *                                                                                             *\n *    This routine will uninitialize the sound driver (if any was                              *\n *    installed).  This routine must be called at program termination                          *\n *    time.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/23/1991 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID Sound_End(VOID)\n{\n\n\tif (LockedData.DigiHandle != -1) {\n\t\tsosTIMERRemoveEvent(DigiTimer);\n\t\tsosTIMERRemoveEvent(MaintainTimer);\n\t\tsosDIGIUnInitDriver(LockedData.DigiHandle, TRUE, TRUE);\n\t\tsosDIGIUnInitSystem();\n\t\tLockedData.DigiHandle = -1;\n\t}\n\tif (DigiBuffer) {\n\t\tFree(DigiBuffer);\n\t\tDigiBuffer = 0;\n\t}\n\tif (LockedData.UncompBuffer) {\n\t\tFree(LockedData.UncompBuffer);\n\t\tLockedData.UncompBuffer = 0;\n\t}\n\tsosTIMERRemoveEvent(SystemTimer);\n\tsosTIMERUnInitSystem(0);\n\tUnlock_Locked_Data();\n}\n\n\n\n\n/***********************************************************************************************\n * Stop_Sample -- Stops any currently playing sampled sound.                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID Stop_Sample(int handle)\n{\n\tif (LockedData.DigiHandle != -1 && (unsigned)handle < LockedData.MaxSamples) {\n\n\n\t\tif (LockedData.SampleTracker[handle].Active || LockedData.SampleTracker[handle].Loading) {\n\n\t\t\t\n\t\t\tLockedData.SampleTracker[handle].Active = FALSE;\n\t\t\tif (!LockedData.SampleTracker[handle].IsScore) {\n\t\t\t\tDPMI_Unlock(LockedData.SampleTracker[handle].Original, LockedData.SampleTracker[handle].OriginalSize);\n\t\t\t\tLockedData.SampleTracker[handle].Original = NULL;\n\t\t\t}\n\t\t\tLockedData.SampleTracker[handle].Priority = 0;\n\n\t\t\t/*\n\t\t\t**\tStop the sample if it is playing.\n\t\t\t*/\n\t\t\tif (!LockedData.SampleTracker[handle].Loading) {\n\t\t\t\tsosDIGIStopSample(LockedData.DigiHandle, LockedData.SampleTracker[handle].Handle);\n\t\t\t}\n\t\t\tLockedData.SampleTracker[handle].Loading = FALSE;\n\n\t\t\t/*\n\t\t\t**\tIf this is a streaming sample, then close the source file.\n\t\t\t*/\n\t\t\tif (LockedData.SampleTracker[handle].FileHandle != ERROR) {\n\t\t\t\tClose_File(LockedData.SampleTracker[handle].FileHandle);\n\t\t\t\tLockedData.SampleTracker[handle].FileHandle = ERROR;\n\t\t\t}\n\n\t\t\tLockedData.SampleTracker[handle].QueueBuffer = NULL;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Sample_Status -- Queries the current playing sample status (if any).                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nBOOL Sample_Status(int handle)\n{\n\t/*\n\t** If its an invalid handle or we do not have a sound driver then\n\t** the sample in question is not playing.\n\t*/\n\tif (LockedData.DigiHandle == -1 || (unsigned)handle >= LockedData.MaxSamples) return(FALSE);\n\t/*\n\t** If the sample is loading, then for all intents and purposes the\n\t** sample is playing.\n\t*/\n\tif (LockedData.SampleTracker[handle].Loading) return(TRUE);\n\t/* \n\t** If the sample is not active, then it is not playing\n\t*/\n\tif (!LockedData.SampleTracker[handle].Active) return(FALSE);\n\t/*\n\t** If we made it this far, then the Sample is still playing if sos says\n\t** that it is.\n\t*/\n\treturn (!sosDIGISampleDone(LockedData.DigiHandle, LockedData.SampleTracker[handle].Handle));\n}\n\n\nBOOL Is_Sample_Playing(void const * sample)\n{\n\tint index;\n\n\tif (!sample) return FALSE;\n\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\tif (LockedData.SampleTracker[index].Original == sample && Sample_Status(index)) {\n\t\t\treturn (TRUE);\n\t\t}\n\t}\n\treturn (FALSE);\n}\n\n\nVOID Stop_Sample_Playing(void const * sample)\n{\n\tint index;\n\n\tif (sample) {\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\t\tif (LockedData.SampleTracker[index].Original == sample) {\n\t\t\t\tStop_Sample(index);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\nint Get_Free_Sample_Handle(int priority)\n{\n\tint\tid;\n\n\t/*\n\t**\tFind a free SFX holding buffer slot.\n\t*/\n\tfor (id = LockedData.MaxSamples - 1; id >= 0; id--) {\n\t\tif (!LockedData.SampleTracker[id].Active && !LockedData.SampleTracker[id].Loading) {\n\t\t\tif (!StartingFileStream && LockedData.SampleTracker[id].IsScore) {\n\t\t\t\tStartingFileStream = TRUE;\t// Ensures only one channel is kept free for scores.\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (id < 0) {\n\t\tfor (id = 0; id < LockedData.MaxSamples; id++) {\n\t\t\tif (LockedData.SampleTracker[id].Priority <= priority) break;\n\t\t}\n\t\tif (id == LockedData.MaxSamples) {\n\t\t\treturn(-1);\t\t// Cannot play!\n\t\t}\n\t\tStop_Sample(id);\t\t\t\t\t\t\t// This sample gets clobbered.\n\t}\n\tif (id == -1) {\n\t\treturn -1;\n\t}\n\tif (LockedData.SampleTracker[id].FileHandle != ERROR) {\n\t\tClose_File(LockedData.SampleTracker[id].FileHandle);\n\t\tLockedData.SampleTracker[id].FileHandle = ERROR;\n\t}\n\tif (LockedData.SampleTracker[id].Original && !LockedData.SampleTracker[id].IsScore) {\n\t\tDPMI_Unlock(LockedData.SampleTracker[id].Original, LockedData.SampleTracker[id].OriginalSize);\n\t\tLockedData.SampleTracker[id].Original = NULL;\n\t}\n\tLockedData.SampleTracker[id].IsScore = FALSE;\n\treturn(id);\n}\n\nint Play_Sample(void const *sample, int priority, int volume, signed short panloc)\n{\n\treturn(Play_Sample_Handle(sample, priority, volume, panloc, Get_Free_Sample_Handle(priority)));\n}\n/***********************************************************************************************\n * Play_Sample_Vol -- Plays a digitized sample.                                                *\n *                                                                                             *\n *    Use this routine to play a previously loaded digitized sample.                           *\n *                                                                                             *\n * INPUT:   sample   -- Sample pointer as returned from Load_Sample.                           *\n *                                                                                             *\n *          volume   -- The volume to play (0..255 with 255=loudest).                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *   05/24/1992 JLB : Volume support -- Soundblaster Pro                                       *\n *   04/22/1994 JLB : Multiple sample playback rates.                                          *\n *=============================================================================================*/\nint Play_Sample_Handle(void const *sample, int priority, int volume, signed short panloc, int id)\n{\n\tAUDHeaderType\t\t\tRawHeader;\n\t_SOS_START_SAMPLE \tstart;\n\tSampleTrackerType\t\t*st=NULL;\t// Working pointer to sample tracker structure.\n\n\tif (!sample || LockedData.DigiHandle == -1) {\n\t\treturn(-1);\n\t}\n\n\tif (id == -1) {\n\t\treturn -1;\n\t}\n\n\t/*\n\t**\tFetch the control bytes from the start of the sample data.\n\t*/\n\tMem_Copy((void *)sample, (void *)&RawHeader, sizeof(RawHeader));\n\n\t/*\n\t**\tPrepare the sample tracker structure for processing of this\n\t**\tsample.  Fill the structure with data that can be determined\n\t**\tbefore the sample is started.\n\t*/\n\tst = &LockedData.SampleTracker[id];\n\tst->Compression\t= (SCompressType) ((unsigned char)RawHeader.Compression);\n\tst->Original\t\t= sample;\n\tst->OriginalSize\t= RawHeader.Size + sizeof(RawHeader);\n\tif (!st->IsScore) {\n\t\tDPMI_Lock(st->Original, st->OriginalSize);\n\t}\n\tst->Priority\t\t= priority;\n\tst->DontTouch\t\t= FALSE;\n\tst->Odd\t\t\t\t= 0;\n\tst->Reducer\t\t\t= 0;\n\tst->Restart\t\t\t= FALSE;\n\tst->QueueBuffer\t= NULL;\n\tst->QueueSize\t\t= NULL;\n\tst->TrailerLen \t= 0;\n\tst->Remainder\t\t= RawHeader.Size;\n\tst->Source\t\t\t= Add_Long_To_Pointer((void *)sample, sizeof(RawHeader));\n\tst->Service\t\t\t= FALSE;\n\n\t/*\n \t** If the code in question using HMI based compression then we need\n\t** to set up for uncompressing it.\n\t*/\n\tif (st->Compression == SCOMP_SOS) {\n\t\tst->sosinfo.wChannels\t = (RawHeader.Flags & AUD_FLAG_STEREO) ? 2  : 1;\n\t\tst->sosinfo.wBitSize\t\t = (RawHeader.Flags & AUD_FLAG_16BIT)  ? 16 : 8;\n\t\tst->sosinfo.dwCompSize\t = RawHeader.Size;\n   \tst->sosinfo.dwUnCompSize = RawHeader.Size * ( st->sosinfo.wBitSize / 4 );\n\t   sosCODECInitStream(&st->sosinfo);\n\t}\n\n\t/*\n\t**\tFill in one or both staging buffers if possible.\n\t*/\n\t_disable();\n//\tDisable_Timer_Interrupt();\n\tif (SFX_MINI_STAGE_BUFFER_SIZE == \n\t\t\t\t\tSample_Copy(st,\n\t\t\t\t\t\t\t\t\t&st->Source, \n\t\t\t\t\t\t\t\t\t&st->Remainder, \n\t\t\t\t\t\t\t\t\t&st->QueueBuffer, \n\t\t\t\t\t\t\t\t\t&st->QueueSize, \n\t\t\t\t\t\t\t\t\tst->Buffer[0], \n\t\t\t\t\t\t\t\t\tSFX_MINI_STAGE_BUFFER_SIZE, \n\t\t\t\t\t\t\t\t\tst->Compression, \n\t\t\t\t\t\t\t\t\t&st->Trailer[0], \n\t\t\t\t\t\t\t\t\t&st->TrailerLen)) {\n\n\t\tst->DataLength = Sample_Copy(st,\n\t\t\t\t\t\t\t\t\t\t&st->Source, \n\t\t\t\t\t\t\t\t\t\t&st->Remainder, \n\t\t\t\t\t\t\t\t\t\t&st->QueueBuffer, \n\t\t\t\t\t\t\t\t\t\t&st->QueueSize, \n\t\t\t\t\t\t\t\t\t\tst->Buffer[1], \n\t\t\t\t\t\t\t\t\t\tSFX_MINI_STAGE_BUFFER_SIZE, \n\t\t\t\t\t\t\t\t\t\tst->Compression, \n\t\t\t\t\t\t\t\t\t\t&st->Trailer[0], \n\t\t\t\t\t\t\t\t\t\t&st->TrailerLen);\n\t\tst->Index = 1;\n\t} else {\n\t\tst->Index = 0;\n\t\tst->DataLength = 0;\n\t}\n\t_enable();\n//\tEnable_Timer_Interrupt();\n\n\t/*\n\t**\tFill in the HMI start sample structure.\n\t*/\n\tmemset(&start, 0, sizeof(start));\n\n\tstart.lpSamplePtr = (LPSTR)st->Buffer[0];\n\tif (st->Index == 1) {\n\t\tstart.dwSampleSize = SFX_MINI_STAGE_BUFFER_SIZE-1;\n\t} else {\n\t\tstart.dwSampleSize = st->DataLength-1;\n\t}\n\tstart.lpCallback\t= (void cdecl (far *)(unsigned int, unsigned int, unsigned int))&DigiCallback;\n\tstart.wLoopCount\t= 0;\n\tstart.wSampleID\t= id;\n\n\t/*\n\t**\tAdjust pitch shifting as necessary so that lower playback\n\t**\tsamples can be supported.\n\t*/\n\tif (RawHeader.Rate != LockedData.Rate) {\n\t\tldiv_t\tresult;\n\n\t\tresult\t\t\t\t\t\t= ldiv((long)RawHeader.Rate, LockedData.Rate);\n\t\tstart.dwSamplePitchAdd\t= (long)MAKE_LONG((short)result.quot, (short)(((long)result.rem * 0x10000L) / LockedData.Rate));\n\t\tstart.wSampleFlags \t  |= _PITCH_SHIFT;\n\t}\n\n\t/*\n\t**\tSample translation flag.\n\t*/\n\n\tif (RawHeader.Flags & AUD_FLAG_16BIT) {\n\t\tif (Bits_Per_Sample == 8) {\n\t\t\tstart.wSampleFlags \t  |= _TRANSLATE16TO8;\n\t\t}\n\t} else {\n\t\tif (Bits_Per_Sample == 16) {\n\t\t\tstart.wSampleFlags \t  |= _TRANSLATE8TO16;\n\t\t}\n\t}\n\n\t/*\n\t**\tSample stereo flag.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_STEREO) {\n\t\tstart.wChannel \t\t\t= _INTERLEAVED;\n\t\tstart.wSampleFlags \t  |= _STEREOTOMONO;\n\t} else {\n\t\tstart.wChannel \t\t\t= _CENTER_CHANNEL;\n\t}\n\n\t/*\n\t**\tSample volume control flags.  Always give it volume control because\n\t**\tif not, then future volume control is either ignored or stops the\n\t**\tsample.\n\t*/\n\tst->Volume \t\t\t\t\t\t= volume << 7;\n\tstart.wVolume\t\t\t\t\t= (st->Volume >> 8) * LockedData.SoundVolume;\n\tstart.wSampleFlags  \t\t  |= _VOLUME;\n\t\n\t/*\n\t** If we have defined a panning location for the sound driver than\n\t** take care of it here.  Panning will only work with a stereo driver\n\t** and only if the sample is played _CENTER_CHANNEL.\n\t*/\n\tif ((panloc != 0x0) && (!(RawHeader.Flags & AUD_FLAG_STEREO))) {\n\t\tstart.wChannel \t\t\t= _CENTER_CHANNEL;\n\t\tpanloc \t\t\t\t\t\t= ((ReverseChannels) ? ((-panloc) + 0x8000) : ((panloc) + 0x8000));\n\t\tstart.wSampleFlags \t  |= _PANNING;\n\t\tstart.wSamplePanLocation= panloc;\n\t}\n\n\tst->Stereo \t= start.wChannel;\n\tst->Pitch \t= start.dwSamplePitchAdd;\n\tst->Flags \t= start.wSampleFlags;\n\n\t/*\n\t**\tStart the sample playing now.\n\t*/\n\t_disable();\t\t// NEW\n//\tDisable_Timer_Interrupt();\n\tst->Handle = sosDIGIStartSample(LockedData.DigiHandle, &start);\n\tif (st->Handle == -1) {\n\t\tid = -1;\n\t} else {\n\n\t\t/*\n\t\t**\tFill in the sample tracker structure with those values that are\n\t\t**\tdetermined AFTER the sample starts.\n\t\t*/\n\t\tst->Active = TRUE;\n\t}\n\t_enable();\t\t\t// NEW\n//\tEnable_Timer_Interrupt();\n\n\treturn(id);\n}\n\n\nint Set_Sound_Vol(int volume)\n{\n\tint old;\n\told = LockedData.SoundVolume;\n\tLockedData.SoundVolume = volume & 0xFF;\n\treturn(old);\n}\n\n\nint Set_Score_Vol(int volume)\n{\n\tint old;\n\told = LockedData.ScoreVolume;\n\tLockedData.ScoreVolume = volume & 0xFF;\n\treturn(old);\n}\n\n\nVOID Fade_Sample(int handle, int ticks)\n{\n\tif (Sample_Status(handle)) {\n\t\tif (!ticks || LockedData.SampleTracker[handle].Loading) {\n\t\t\tStop_Sample(handle);\n\t\t} else {\n\t\t\tSampleTrackerType * st;\n\n\t\t\tst = &LockedData.SampleTracker[handle];\n\t\t\tst->Reducer = (st->Volume / ticks)+1;\n\t\t}\n\t}\n}\nint Get_Digi_Handle(void)\n{\n\treturn(LockedData.DigiHandle);\n}\n\n/***************************************************************************\n * SAMPLE_LENGTH -- returns length of a sample in ticks                    *\n *                                                                         *\n * INPUT:\t\tvoid const *sample - pointer to the sample to get length    *\n *\t\t\t\t\t\t\t\t\t\t\t   of.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tlong   \t\t\t\t - length of the sample in ticks (60/sec) *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/05/1995 PWG : Created.                                             *\n *=========================================================================*/\nlong Sample_Length(void const *sample)\n{\n\tAUDHeaderType\t\t\tRawHeader;\n\n\tif (!sample) return(0);\n\n\tMem_Copy((void *)sample, (void *)&RawHeader, sizeof(RawHeader));\n\n\tlong time = RawHeader.UncompSize;\n\n\t/*\n\t** If the sample is a 16 bit sample, then it will take only half\n\t** as long to play.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_16BIT) {\n\t\ttime >>= 1;\n\t}\n\n\t/*\n\t** If the sample is a stereo sample, then it will take only half\n\t** as long to play.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_STEREO) {\n\t\ttime >>= 1;\n\t}\n\n\tif (RawHeader.Rate/60) {\n\t\ttime /= (RawHeader.Rate/60);\n\t}\n\treturn(time);\n}\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NEW/SOUNDLCK.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDLCK.CPP                             *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 23, 1995   [PWG]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <dos.h>\n#include <mem.h>\n#include \"soundint.h\"\n#include \"wwmem.h\"\n\nLockedDataType LockedData;\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * INIT_LOCKED_DATA -- Initializes sound driver locked data                *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid Init_Locked_Data(void)\n{\n\t/*\n\t** Initialize all of the data elements that need to be locked.\n\t*/\n\tLockedData.DigiHandle\t\t\t= -1;\n\tLockedData.ServiceSomething\t= FALSE;\n\tLockedData.MagicNumber\t\t\t= 0xDEAF;\n\tLockedData.UncompBuffer\t\t\t= NULL;\n\tLockedData.StreamBufferSize\t= (2*SFX_MINI_STAGE_BUFFER_SIZE)+128;\n\tLockedData.StreamBufferCount\t= 32;\n\tLockedData.SoundVolume\t\t\t= 255;\n\tLockedData.ScoreVolume\t\t\t= 255;\n\tLockedData._int\t\t\t\t\t= FALSE;\n\tLockedData.MaxSamples\t\t\t= MAX_SFX;\n\n\t/*\n\t** Lock the sound specific c functions that will cause us problems if\n\t** they are swapped out during an interrupt.\n\t*/\n\tDPMI_Lock(&LockedData,\t\t\t\t\t\t\t4096L);\n\tDPMI_Lock(Simple_Copy, \t\t\t\t\t\t\t4096L);\n\tDPMI_Lock(Sample_Copy, \t\t\t\t\t\t\t4096L);\n\tDPMI_Lock((void *)maintenance_callback, \t4096L);\n\tDPMI_Lock((void *)DigiCallback, \t\t\t\t4096L);\n\tDPMI_Lock((void *)HMI_TimerCallback, \t\t4096L);\n\tDPMI_Lock(Audio_Add_Long_To_Pointer,\t\t4096L);\n\tDPMI_Lock(DPMI_Unlock,\t\t\t\t\t\t\t4096L);\n\n\t/*\n\t** Lock the library functions that will cause us problems if they are\n\t** swapped out during an interrupt.\n\t*/\n\tDPMI_Lock(Mem_Copy,\t\t\t\t\t\t\t\t4096L);\n\tDPMI_Lock(Audio_Mem_Set,\t\t\t\t\t\t4096L);\n\tDPMI_Lock(__GETDS,\t\t\t\t\t\t\t\t4096L);\n\n\t/*\n\t** Finally lock the two assembly modules that need locking.  This can\n\t** be handled by calling the lock function that is local to thier module\n\t** swapped out during an interrupt.\n\t*/\n\tDecompress_Frame_Lock();\n\tsosCODEC_Lock();\n}\n\nvoid Unlock_Locked_Data(void)\n{\n\t/*\n\t** Lock the sound specific c functions that will cause us problems if\n\t** they are swapped out during an interrupt.\n\t*/\n\tDPMI_Unlock(&LockedData,\t\t\t\t\t\t4096L);\n\tDPMI_Unlock(Simple_Copy, \t\t\t\t\t\t4096L);\n\tDPMI_Unlock(Sample_Copy, \t\t\t\t\t\t4096L);\n\tDPMI_Unlock((void *)maintenance_callback, 4096L);\n\tDPMI_Unlock((void *)DigiCallback, \t\t\t4096L);\n\tDPMI_Unlock((void *)HMI_TimerCallback,\t\t4096L);\n\tDPMI_Unlock(Audio_Add_Long_To_Pointer,\t\t4096L);\n\n\t/*\n\t** Lock the library functions that will cause us problems if they are\n\t** swapped out during an interrupt.\n\t*/\n\tDPMI_Unlock(Mem_Copy,\t\t\t\t\t\t\t4096L);\n\tDPMI_Unlock(Audio_Mem_Set,\t\t\t\t\t\t4096L);\n\tDPMI_Unlock(__GETDS,\t\t\t\t\t\t\t\t4096L);\n\t/*\n\t** Finally unlock the two assembly modules that need locking.  This can\n\t** be handled by calling the lock function that is local to thier module\n\t** swapped out during an interrupt.\n\t*/\n\tDecompress_Frame_Unlock();\n\tsosCODEC_Unlock();\n\n\t/*\n\t** As a last step go though all of the sample tracker structures and make\n\t** sure all the samples have been properly unlocked.\n\t*/\n\tfor (int id = 0; id < LockedData.MaxSamples; id++) {\n\t\tif (LockedData.SampleTracker[id].Original && !LockedData.SampleTracker[id].IsScore) {\n\t\t\tDPMI_Unlock(LockedData.SampleTracker[id].Original, LockedData.SampleTracker[id].OriginalSize);\n\t\t\tLockedData.SampleTracker[id].Original = NULL;\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "WWFLAT32/AUDIO/NYBBTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* bNybbleTablexxxx - ADPCM Lookup table for nybbles\n;****************************************************************************\n\n\t\talign\t4\n\nbNybbleTableLow\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\n\t\talign 4\n\nbNybbleTableHigh\tDB\t00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2\n\t\tDB\t01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2\n\t\tDB\t02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2\n\t\tDB\t03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2\n\t\tDB\t04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2\n\t\tDB\t05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2\n\t\tDB\t06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2\n\t\tDB\t07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2\n\t\tDB\t08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2\n\t\tDB\t09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2\n\t\tDB\t0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2\n\t\tDB\t0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2\n\t\tDB\t0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2\n\t\tDB\t0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2\n\t\tDB\t0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2\n\t\tDB\t0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2\n"
  },
  {
    "path": "WWFLAT32/AUDIO/SOS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sos.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DEFINED   \n#define  _SOS_DEFINED   \n#include \"sosdefs.h\"\n\n#pragma pack(4)\n \n// error definition for sound operating system  \n#define  _SOS_ERR          -1\n\n// number of drivers allowed to be open at one time\n#define  _SOS_MAX_DRIVERS  5\n\n// structure definition for the capabilities\ntypedef struct _tagCAPABILITIES\n{\n   BYTE  szDeviceName[ 32 ];  // device name\n   WORD  wDeviceVersion;      // device version\n   WORD  wBitsPerSample;      // bits per sound sample\n   WORD  wChannels;           // stereo/mono sound card\n   WORD  wMinRate;            // minimum rate\n   WORD  wMaxRate;            // maximum rate\n   WORD  wMixerOnBoard;       // board contains mixer\n   WORD  wMixerFlags;         // mixer capabilities\n   WORD  wFlags;              // miscellaneous flags   \n   short far * lpPortList;         // list of usable ports\n   short far * lpDMAList;          // list of usable dma channels\n   short far * lpIRQList;          // list of usable irq channels\n   short far * lpRateList;         // list of usable rates, -1 if any in min to max\n   WORD  fBackground;         // foreground or background driver\n   WORD  wDeviceID;           // ID for the device\n   WORD  wTimerID;            // ID for the timer\n   \n} _SOS_CAPABILITIES; \n\n// far pointer to the device capabilities structure\ntypedef _SOS_CAPABILITIES far *  LPSOSDEVICECAPS;\n\n// flag types for driver\n#define  _FLAGS_SIGNED              0x8000\n  \n// devices that can be loaded\n#define  _SOUND_BLASTER_8_MONO      0xe000\n#define  _SOUND_BLASTER_8_ST        0xe001\n#define  _SBPRO_8_ST                _SOUND_BLASTER_8_ST\n#define  _SBPRO_8_MONO              0xe00f\n#define  _SOUND_MASTER_II_8_MONO    0xe002\n#define  _MV_PAS_8_MONO             0xe003\n#define  _MV_PAS_16_MONO            0xe004\n#define  _MV_PAS_8_ST               0xe005\n#define  _MV_PAS_16_ST              0xe006\n#define  _ADLIB_GOLD_8_ST           0xe007\n#define  _ADLIB_GOLD_16_ST          0xe008\n#define  _ADLIB_GOLD_8_MONO         0xe009\n#define  _ADLIB_GOLD_16_MONO        0xe00a\n#define  _MICROSOFT_8_MONO          0xe00b\n#define  _MICROSOFT_8_ST            0xe00c\n#define  _MICROSOFT_16_MONO         0xe00d\n#define  _MICROSOFT_16_ST           0xe00e\n#define  _SOUND_SOURCE_8_MONO_PC    0xe010\n#define  _SOUND_SOURCE_8_MONO_TANDY 0xe011\n#define  _GENERAL_PORT_8_MONO       0xe012\n#define  _GENERAL_PORT_8_MONO_R     0xe013\n#define  _SIERRA_8_MONO             0xe014\n#define  _SB16_8_MONO               0xe015\n#define  _SB16_8_ST                 0xe016\n#define  _SB16_16_MONO              0xe017\n#define  _SB16_16_ST                0xe018\n#define  _ESS_AUDIODRIVE_8_MONO     0xe019\n#define  _ESS_AUDIODRIVE_8_ST       0xe01a\n#define  _ESS_AUDIODRIVE_16_MONO    0xe01b\n#define  _ESS_AUDIODRIVE_16_ST      0xe01c\n#define  _SOUNDSCAPE_8_MONO         0xe01d\n#define  _SOUNDSCAPE_8_ST           0xe01e\n#define  _SOUNDSCAPE_16_MONO        0xe01f\n#define  _SOUNDSCAPE_16_ST          0xe020\n#define  _RAP10_8_MONO              0xe021\n#define  _RAP10_16_MONO             0xe022\n#define  _GUS_8_MONO                0xe023\n#define  _GUS_8_ST                  0xe024\n#define  _GUS_16_MONO               0xe025\n#define  _GUS_16_ST                 0xe026\n#define  _GUS_MAX_8_MONO            0xe027\n#define  _GUS_MAX_8_ST              0xe028\n#define  _GUS_MAX_16_MONO           0xe029\n#define  _GUS_MAX_16_ST             0xe02a\n#define  _WAVEJAMMER_8_MONO         0xe02b\n#define  _WAVEJAMMER_8_ST           0xe02c\n#define  _WAVEJAMMER_16_MONO        0xe02d\n#define  _WAVEJAMMER_16_ST          0xe02e\n#define  _TEMPOCS_8_MONO            0xe02f\n#define  _TEMPOCS_8_ST              0xe030\n#define  _TEMPOCS_16_MONO           0xe031\n#define  _TEMPOCS_16_ST             0xe032\n#define  _WAVEJAMMERCD_8_MONO       0xe033\n#define  _WAVEJAMMERCD_8_ST         0xe034\n#define  _WAVEJAMMERCD_16_MONO      0xe035\n#define  _WAVEJAMMERCD_16_ST        0xe036\n#define  _SOUND_BLASTER_8_MONO_R    0xe050\n#define  _MICROSOFT_8_MONO_R        0xe051\n#define  _SOUND_MASTER_II_8_MONO_R  0xe052\n#define  _ADLIB_GOLD_8_MONO_R       0xe053\n#define  _MV_PAS_8_MONO_R           0xe054\n#define  _RAP10_8_MONO_R            0xe058\n#define  _RAP10_16_MONO_R           0xe059\n#define  _SB16_8_MONO_R             0xe05a\n#define  _SB16_8_ST_R               0xe05b\n#define  _SB16_16_MONO_R            0xe05c\n#define  _SB16_16_ST_R              0xe05d\n#define  _MV_PAS_16_MONO_R          0xe060\n#define  _SOUNDSCAPE_8_MONO_R       0xe061\n#define  _SOUNDSCAPE_8_ST_R         0xe062\n#define  _SOUNDSCAPE_16_MONO_R      0xe063\n#define  _SOUNDSCAPE_16_ST_R        0xe064\n#define  _ESS_AUDIODRIVE_8_MONO_R   0xe065\n#define  _ESS_AUDIODRIVE_8_ST_R     0xe066\n#define  _ESS_AUDIODRIVE_16_MONO_R  0xe067\n#define  _ESS_AUDIODRIVE_16_ST_R    0xe068\n#define  _SPEECH_THING_8_MONO       0xe090\n#define  _YAMAHA_8_MONO             0xe106\n#define  _INT_SPEAKER_8_MONO        0xe107\n\n// call indexes for the loadable drivers\nenum\n{ \n   _DRV_INIT,\n   _DRV_UNINIT,\n   _DRV_SETRATE,\n   _DRV_SETACTION,\n   _DRV_START,\n   _DRV_STOP,\n   _DRV_PAUSE,\n   _DRV_RESUME,\n   _DRV_CAPABILITIES,\n   _DRV_PLAY_FOREGROUND,\n   _DRV_GET_FILL_INFO, \n   _DRV_GET_CALL_FUNCTIONS,\n   _DRV_SET_CALL_FUNCTIONS\n};\n\n// fill info\ntypedef  struct   _tagFillInfo\n         {\n\n            LPSTR lpFillHandler;                   // pointer to fill handler\n            LPWORD lpDMAFillCount;                 // pointer to dma count\n            LPSTR lpSampleList;                    // pointer to sample list\n            LPWORD lpDMAMasterVolume;              // pointer to dma count\n\n         } _SOS_FILL_INFO;\n\n// caps info structure\ntypedef  struct   _tagCapsInfo\n         {\n\n            LPSTR    lpPortList;                   // pointer to port list\n            LPSTR    lpDMAList;                    // pointer to DMA list\n            LPSTR    lpIRQList;                    // pointer to IRQ list\n            LPSTR    lpRateList;                   // pointer to rate list\n\n         } _SOS_CAPS_INFO;\n\n// maximum number of available voice\n#define  _MAX_VOICES    32\n\n// structure definition\ntypedef  struct   _tagSAMPLE\n{\n   LPSTR    samplePtr;                 // pointer to data buffer\n   LPSTR    sampleData;                // pointer to active data\n   LPSTR    sampleLoopPtr;             // pointer for loop back\n\n   WORD     sampleLength;              // length of sample\n   WORD     sampleIndex;               // index into sample\n   WORD     sampleLoopLength;          // length of loop\n   \n   WORD     sampleBytesLeft;           // bytes left to play in sample\n\n   WORD     sampleLoopPoint;           // byte count for loop point\n   WORD     sampleLoopEndLength;       // length of remaining chunk\n\n   short    sampleFlags;               // control sample\n   short    sampleVolume;              // volume control\n   short    sampleID;                  // sample ID\n\n   short    sampleChannel;             // channel to play sample on\n   short    sampleLoopCount;           // loop count\n   short    sampleLastFill;            // last fill position\n   VOID ( far cdecl * sampleCallback )( WORD, WORD, WORD ); // callback function for sample\n\n   WORD     samplePitchAdd;\n   short    samplePitchFraction;\n\n   short    samplePort;                // port to use for non-dma digitized\n\n   WORD     sampleTotalBytes;\n   WORD     sampleByteLength;\n\n   short    samplePanLocation;\n   short    samplePanSpeed;\n   short    samplePanDirection;\n   short    samplePanStart;\n   short    samplePanEnd;\n   \n   short    sampleDelayBytes;\n   short    sampleDelayRepeat;\n   \n   WORD     sampleADPCMPredicted;\n   short    sampleADPCMIndex;\n\n   short    sampleRootNoteMIDI;   \n\n   WORD  sampleTemp1;   \n   \n} _SOS_SAMPLE;\n\n// enumeration for left or right channel\nenum\n{\n   _LEFT_CHANNEL,\n   _RIGHT_CHANNEL,\n   _CENTER_CHANNEL,\n   _INTERLEAVED\n};\n\n// enumeration for foreground and background\nenum\n{ \n   _FOREGROUND,\n   _BACKGROUND \n};\n\n// defines for the sample flags\n#define  _ACTIVE           0x8000\n#define  _LOOPING          0x4000\n#define  _FIRST_TIME       0x2000\n#define  _PENDING_RELEASE  0x1000\n#define  _CONTINUE_BLOCK   0x0800\n#define  _PITCH_SHIFT      0x0400\n#define  _PANNING          0x0200\n#define  _VOLUME           0x0100\n#define  _TRANSLATE16TO8   0x0080\n#define  _STAGE_LOOP       0x0040\n#define  _TRANSLATE8TO16   0x0020\n#define  _STEREOTOMONO     0x0010\n\n// defines for the wParam flags \n#define  _SINGLE_SAMPLE 0x01\n\n#define  _SOS_DCAPS_AUTO_REINIT     0x01\n#define  _SOS_DCAPS_MPU_401         0x02\n#define  _SOS_DCAPS_OPL2            0x04\n#define  _SOS_DCAPS_OPL3            0x08\n#define  _SOS_DCAPS_OPL4            0x10\n#define  _SOS_DCAPS_WAVETABLE       0x20\n#define  _SOS_DCAPS_DL_SAMPLES      0x40\n#define  _SOS_DCAPS_FIFO_DEVICE     0x80\n#define  _SOS_DCAPS_ENV_NEEDED      0x100\n#define  _SOS_DCAPS_PSEUDO_DMA1     0x200\n#define  _SOS_DCAPS_SIGNED_DATA     0x8000\n\n// file header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // number of drivers in the file\n   WORD  wDrivers;\n\n   // offset of first driver\n   WORD  lOffset;\n\n   // size of the file\n   WORD  lFileSize;\n\n} _FILEHEADER;\n\n// driver header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // offset of next driver\n   WORD  lNextDriver;\n\n   // size of current driver\n   WORD  wSize;\n\n   // id for the current device\n   WORD  wDeviceID;\n\n   // id for the type of DOS extender\n   WORD  wExtenderType;\n\n} _DRIVERHEADER;\n\n// device hardware information\ntypedef struct\n{\n   // port to be used\n   WORD  wPort;\n\n   // irq to use\n   WORD  wIRQ;\n\n   // dma channel to se\n   WORD  wDMA; \n  \n   // extra parameter\n   WORD  wParam;\n\n} _SOS_HARDWARE;\n\n// structure definition for start sample\ntypedef struct\n{\n   // pointer to sample\n   LPSTR lpSamplePtr;\n\n   // size of the sample\n   WORD  dwSampleSize;\n\n   // number of times to loop the sample -1 is infinite\n   WORD  wLoopCount;\n\n   // channel to play sample on\n   WORD  wChannel;\n\n   // volume to play sample at\n   WORD wVolume;\n\n   // id for the sample\n   WORD  wSampleID;\n\n   // far pointer to the callback function\n   VOID ( far cdecl *lpCallback )( WORD, WORD, WORD );\n\n   // port to use if driver is a non-dma background driver\n   WORD  wSamplePort; \n\n   // flags field\n   WORD  wSampleFlags;\n\n   // total length of sample including loops, etc..\n   WORD     dwSampleByteLength;\n\n   // loop point for the sample\n   WORD  dwSampleLoopPoint;\n   WORD  dwSampleLoopLength;\n\n   // pitch shifting components \n   WORD     dwSamplePitchAdd;\n   WORD    wSamplePitchFraction;\n\n   // pan components\n   WORD    wSamplePanLocation;\n   WORD    wSamplePanSpeed;\n   WORD    wSamplePanDirection;\n   WORD    wSamplePanStart;\n   WORD    wSamplePanEnd;\n   \n   // delay parts\n   WORD    wSampleDelayBytes;\n   WORD    wSampleDelayRepeat;\n\n   // compression components   \n   WORD     dwSampleADPCMPredicted;\n   WORD    wSampleADPCMIndex;\n\n   // root note for pitch shifting \n   WORD    wSampleRootNoteMIDI;   \n\n   // filler for future upgrades\n   WORD  dwSampleTemp1;   \n   WORD  dwSampleTemp2;   \n   WORD  dwSampleTemp3;   \n\n} _SOS_START_SAMPLE;\n\n// structure for initializing a driver\ntypedef struct\n{  \n   WORD  wBufferSize;\n   LPSTR lpBuffer;\n   BOOL  wAllocateBuffer;\n   WORD  wSampleRate;\n   WORD  wParam;\n   LONG  dwParam;\n   VOID ( far *lpFillHandler )( VOID );\n   LPSTR lpDriverMemory;\n   LPSTR lpDriverMemoryCS;\n   LPSTR lpTimerMemory;\n   LPSTR lpTimerMemoryCS;\n   WORD  wTimerID;\n   WORD  wPhysical;\n\n} _SOS_INIT_DRIVER;\n\n// define for the timer types to use\n#define  _SOS_NORMAL_TIMER          0x00\n\n// enumeration for the timer types\nenum\n{\n   _TIMER_8_MONO   =     0x1000,\n   _TIMER_8_ST,          \n   _TIMER_16_MONO,       \n   _TIMER_16_ST,         \n   _TIMER_8_MONO_ULAW,  \n   _TIMER_8_ST_ULAW,    \n   _TIMER_16_MONO_ULAW, \n   _TIMER_16_ST_ULAW,   \n   _TIMER_8_MONO_REC,   \n   _TIMER_8_MONO_ULAW_REC,\n   _TIMER_UNDEFINED_1,      \n   _TIMER_UNDEFINED_2,\n   _TIMER_UNDEFINED_3,\n   _TIMER_UNDEFINED_4,\n   _TIMER_UNDEFINED_5,\n   _TIMER_UNDEFINED_6,\n   _TIMER_UNDEFINED_7,\n   _TIMER_UNDEFINED_8,\n   _TIMER_UNDEFINED_9,\n   _TIMER_UNDEFINED_A,\n   _TIMER_UNDEFINED_B,\n   _TIMER_UNDEFINED_C,\n   _TIMER_UNDEFINED_D,\n   _TIMER_UNDEFINED_E,\n   _TIMER_UNDEFINED_F,\n   _TIMER_UNDEFINED_10,\n   _TIMER_UNDEFINED_11,\n   _TIMER_UNDEFINED_12,\n   _TIMER_UNDEFINED_13,\n   _TIMER_UNDEFINED_14,\n   _TIMER_UNDEFINED_15,\n   _TIMER_UNDEFINED_16,\n   _TIMER_8_SOUND_SOURCE,\n   _TIMER_8_SOUND_SOURCE_TANDY,\n   _TIMER_8_GENERAL_PORT,\n   _TIMER_8_GENERAL_PORT_REC   \n};\n\n// define for no slots available\n#define  _ERR_NO_SLOTS ( WORD )-1\n\n// error codes for the system\nenum\n{\n   _ERR_NO_ERROR,\n   _ERR_DRIVER_NOT_LOADED,\n   _ERR_INVALID_POINTER,\n   _ERR_DETECT_INITIALIZED,\n   _ERR_FAIL_ON_FILE_OPEN,\n   _ERR_MEMORY_FAIL,\n   _ERR_INVALID_DRIVER_ID,\n   _ERR_NO_DRIVER_FOUND,\n   _ERR_DETECTION_FAILURE,\n   _ERR_DRIVER_LOADED,\n   _ERR_INVALID_HANDLE,\n   _ERR_NO_HANDLES,\n   _ERR_PAUSED,   \n   _ERR_NOT_PAUSED,\n   _ERR_INVALID_DATA,\n   _ERR_DRV_FILE_FAIL,\n   _ERR_INVALID_PORT,\n   _ERR_INVALID_IRQ,\n   _ERR_INVALID_DMA,\n   _ERR_INVALID_DMA_IRQ\n};   \n\n// maximum number of timer events that can be registered \n#define  _TIMER_MAX_EVENTS    0x10  \n\n// flags for the debugging system\n#define  _SOS_DEBUG_NORMAL       0x0000\n#define  _SOS_DEBUG_NO_TIMER     0x0001\n#define  _SOS_TIMER_DPMI         0x0002\n\n// define for types of DOS extenders\n#define  _SOS_RATIONAL           0x8000\n#define  _SOS_FLASHTECK          0x4000\n\n// defines for the types of timers for different\n// dos extenders\n#define  _SOS_TIMER_NEAR         0x8000\n#define  _SOS_TIMER_FAR          0x4000\n \n// values for callback information\nenum\n{\n   _SAMPLE_PROCESSED,\n   _SAMPLE_LOOPING,\n   _SAMPLE_DONE\n};\n\n// define for special 18.2 callback rate to dos\n#define  _TIMER_DOS_RATE   0xff00\n\n#pragma pack()\n\n#pragma aux int_3 = \"int 3\"\n \n#pragma pack( 1 ) \ntypedef struct\n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned       segment;\n\tunsigned short\tnumber_available;\n\tunsigned short number_used;\n\tunsigned       page0;\n\n} EVDS_STRUCT;\n\ntypedef struct \n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned short segment;\n\tunsigned short\tID;\n\tunsigned       physical;\n\n} VDS_STRUCT;\n\n#pragma pack() \n\n#include \"sosdata.h\"\n#include \"sosfnct.h\"\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/AUDIO/SOSCODEC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;*\n;*          Copyright (c) 1994, HMI, INC. All Rights Reserved\n;*\n;*---------------------------------------------------------------------------\n;*\n;* FILE\n;*     soscodec.asm\n;*\n;* DESCRIPTION\n;*     HMI SOS ADPCM compression/decompression.\n;*\n;* PROGRAMMER\n;*     Nick Skrepetos\n;*     Denzil E. Long, Jr. (Fixed bugs, rewrote for watcom)\n;*\t   Bill Petro\t\t   (Added stereo support)\n;* DATE\n;*     Febuary 15, 1995\n;*\n;*---------------------------------------------------------------------------\n;*\n;* PUBLIC\n;*\n;****************************************************************************\n\n\tIDEAL\n\tP386\n\tMODEL\tUSE32 FLAT\n\tLOCALS\t??\n\n\nDPMI_INTR\t\tequ\t31h\t\nIF_LOCKED_PM_CODE\tequ\t1h\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t2h\t\t; Locked PM code for DPMI.\n\nSTRUC\tsCompInfo\nlpSource\t\tDD\t?\t;Compressed data pointer\nlpDest\t\t\tDD\t?\t;Uncompressed data pointer\ndwCompSize\t\tDD\t?\t;Compressed size\ndwUnCompSize\t\tDD\t?\t;Uncompressed size\n\ndwSampleIndex\t\tDD\t?\t;Index into sample\ndwPredicted\t\tDD\t?\t;Next predicted value\ndwDifference\t\tDD\t?\t;Difference from last sample\nwCodeBuf\t\tDW\t?\t;Holds 2 nibbles for decompression\nwCode\t\t\tDW\t?\t;Current 4 bit code\nwStep\t\t\tDW\t?\t;Step value in table\nwIndex\t\t\tDW\t?\t;Index into step table\n\ndwSampleIndex2\t\tDD\t?\t;Index into sample\ndwPredicted2\t\tDD\t?\t;Next predicted value\ndwDifference2\t\tDD\t?\t;Difference from last sample\nwCodeBuf2 \t\tDW\t?\t;Holds 2 nibbles for decompression\nwCode2\t\t\tDW\t?\t;Current 4 bit code\nwStep2\t\t\tDW\t?\t;Step value in table\nwIndex2\t\t\tDW\t?\t;Index into step table\n\nwBitSize\t\tDW\t?\t;Bit size for decompression\nwChannels\t\tDW\t?    \t;number of channels\nENDS\tsCompInfo\n\n\n\tDATASEG\n\n\nInitFlags\tDD\t0\t\t; Flags to indicate what has been initialized.\n\n\nLABEL\tLockedDataStart\tBYTE\t\n\n;* Index table for stepping into step table\n\nwCODECIndexTab\tDD\t-1,-1,-1,-1,2,4,6,8\n\t\tDD\t-1,-1,-1,-1,2,4,6,8\n\n\n;Lookup table of replacement values\n;The actual sound value is replaced with an index to lookup in this table\n;The index only takes up a nibble(4bits) and represents an int(16bits)\n;Essentially: \n;Get a value\n;compare it with the value before it\n;find closest value in table and store the index into the table\n;if i'm going down then negitize it\n;go to next byte.\n\n;Theory for stereo:\n;1)handle stereo and mono in two seperate loops. cleaner...\n;start at byte 0 and skip every other byte(or word) both write and read\n;when we get done\n;\tset start byte to 1 and do it again \n\n\n\n\n;This table essentialy round off to closes values in 3 distinct bands\n; precalculated and optimized(i guess) for human hearing.\n\nwCODECStepTab\tDD\t7,  \t8,  \t9,   \t10,   \t11,  \t12,   \t13,14   \t\t\n\t\tDD\t16, \t17, \t19, \t21,  \t23,   \t25,  \t28,   \t31\t\t\t\n\t\tDD\t34, \t37, \t41, \t45,  \t50,   \t55,  \t60,   \t66\t\t\t\n\t\tDD\t73, \t80, \t88, \t97,  \t107,  \t118, \t130,  \t143\t\t\t\n\t\tDD\t157,\t173,\t190,\t209, \t230,  \t253, \t279,  \t307\t\t\t\n\t\tDD\t337,\t371,\t408,\t449, \t494,  \t544, \t598,  \t658\t\t\t\n\t\tDD\t724,\t796,\t876,\t963, \t1060,\t1166,\t1282,\t1411\t\t\t\n\t\tDD\t1552,\t1707,\t1878,\t2066,\t2272,\t2499,\t2749,\t3024\t\t\t\n\t\tDD\t3327,\t3660,\t4026,\t4428,\t4871,\t5358,\t5894,\t6484\n\t\tDD\t7132,\t7845,\t8630,\t9493,\t10442,\t11487,\t12635,\t13899\t\t\n\t\tDD\t15289,\t16818,\t18500,\t20350,\t22385,\t24623,\t27086,\t29794 \n\t\tDD\t32767\t\t\t\n\nwCode\t\t\t\tDD\t0 ; this is to hold index into wCodeStep\ndwCODECByteIndex\t\tDD\t0 ; this is when to stop compressing\ndwCODECBytesProcessed\t\tDD\t0 ; this is how many so far compressed\ndwCODECTempStep\t\t\tDD\t0 ; tempory storage for step value\nwCODECMask\t\t\tDW\t0 ; Current mask\n\nLABEL\tLockedDataEnd\tBYTE\n\n\n\tCODESEG\n\nLABEL\tLockedCodeStart\tBYTE\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECInitStream - Initialize compression stream.\n;*\n;* SYNOPSIS\n;*     sosCODECInitStream(CompInfo)\n;*\n;*     void sosCODECInitStream(_SOS_COMPRESS_INFO *);\n;*\n;* FUNCTION\n;*     Initialize compression stream for compression and decompression.\n;*\n;* INPUTS\n;*     CompInfo - Compression information structure.\n;*\n;* RESULT\n;*     NONE\n;*\n;****************************************************************************\n\n\tGLOBAL\tsosCODECInitStream:NEAR\n\tPROC\tsosCODECInitStream C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\n\tmov\teax,[sSOSInfo]\n\tmov\t[(sCompInfo eax).wIndex],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).wStep],7  \t\t; start with a step of 7\n\tmov\t[(sCompInfo eax).dwPredicted],0 \t; no predicted value\n\tmov\t[(sCompInfo eax).dwSampleIndex],0\t;start at head of index\n\tmov\t[(sCompInfo eax).wIndex2],0 \t\t; starting index 0\n\tmov\t[(sCompInfo eax).wStep2],7  \t\t; start with a step of 7\n\tmov\t[(sCompInfo eax).dwPredicted2],0 \t; no predicted value\n\tmov\t[(sCompInfo eax).dwSampleIndex2],0 \t;start at head of index\n\tret\n\n\tENDP\tsosCODECInitStream\n\n\n\n;****************************************************************************\n;*\n;* NAME\n;*     sosCODECDecompressData - Decompress audio data.\n;*\n;* SYNOPSIS\n;*     Size = sosCODECDecompressData(CompInfo, NumBytes)\n;*\n;*     long sosCODECDecompressData(_SOS_COMPRESS_INFO *, long);\n;*\n;* FUNCTION\n;*     Decompress data from a 4:1 ADPCM compressed stream. The number of\n;*     bytes decompressed is returned.\n;*\n;* INPUTS\n;*     CompInfo - Compress information structure.\n;*     NumBytes - Number of bytes to compress.\n;*\n;* RESULT\n;*     Size - Size of decompressed data.\n;*\n;****************************************************************************\n\n\tGLOBAL\tsosCODECDecompressData:NEAR\n\tPROC\tsosCODECDecompressData C NEAR\n\n\tARG\tsSOSInfo:NEAR PTR\n\tARG\twBytes:DWORD\n\n\tpush\tesi\n\tpush\tedi\t\t\t   \n\tpush\tebx\n\tpush\tecx\n\tpush\tedx\n\n;*---------------------------------------------------------------------------\n;*\tInitialize\n;*---------------------------------------------------------------------------\n\n\tmov\tebx,[sSOSInfo]\n\tmov\teax,[wBytes]\n\tmov\t[dwCODECBytesProcessed],eax\n\tmov\t[(sCompInfo ebx).dwSampleIndex],0 \t;start at head of index\n\tmov\t[(sCompInfo ebx).dwSampleIndex2],0 \t;start at head of index\n\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??skipByteDivide\n\n\tshr\teax,1\t;Divide size by two\n\n??skipByteDivide:\n\tmov\t[dwCODECByteIndex],eax\n\tmov\tesi,[(sCompInfo ebx).lpSource]\n\tmov\tedi,[(sCompInfo ebx).lpDest]\n\n\tcmp\t[(sCompInfo ebx).wChannels],2\t\t;stereo check\n\tje\t??mainloopl\t\t\t\t;do left side first\t\n\t\n;\tDetermine if sample index is even or odd. This will determine\n;\tif we need to get a new token or not.\n\n;---------------------------------------------------------------------------\n;Main Mono Loop\n;---------------------------------------------------------------------------\n\tpush\tebp\n\tmovzx\tedx,[(sCompInfo ebx).wIndex] \t\t;preload index\n\tmov\tebp, [dwCODECByteIndex]\n\tmov\tecx,[(sCompInfo ebx).dwSampleIndex]\t;preload SampleIndex\n\t\n??mainloop:\t \n\txor\teax,eax\t\t\t\t\t;get a new token\n\ttest\tecx,1\t\t\t\t\t;odd Sample??\n\tje\tshort ??fetchToken\t\t\t; if so get new token\n\tmov\tax,[(sCompInfo ebx).wCodeBuf]\t\t;ored with Code\n\tshr\teax,4\n\tjmp\tshort ??calcDifference\n\talign\t4\n\n??fetchToken:\n\tmov\tal,[esi]\t\t\t\t;put in codebuf\n\tinc\tesi\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\n\n\n??calcDifference:\n\txor\tecx,ecx\n\tand\teax,000Fh\n\tmov\tcx,[(sCompInfo ebx).wStep]\t\t;cx is step value\n\tmov\t[wCode],eax\n\tjmp\t[DWORD PTR JumpTable + eax*4]\n\talign\t4\n\n; note: it is important for speed reasons to keep the order the \n; following jumps entries as well as the \"align 4\" after some of\n; the jmp statements\n\n??7:\n\t; eax = x + x/2 + x/4 + x/8 = (8*x + 4*x +2*x + x)>>3 =\n\t;     = ( x * ( 8 + 4 + 2 + 1 )) >> 3 = ( x * 15 ) >> 3 \n\tlea\tecx,[ecx+ecx*2]\n\tlea\teax,[ecx+ecx*4]\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tjmp\t??save_dif\n\talign\t4\n\n??6:\n\t; eax = x + x / 2 + x / 8 = (8*x + 4*x + x) >> 3 =\n\t;     =\t( x * 8 + x * 5\t) >> 8\n\tlea\teax,[ecx+ecx*4]\n\tlea\teax,[eax+ecx*8]\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tjmp\t??save_dif\n\talign\t4\n\n??5:\n\t; eax = x + x / 4 + x / 8 = (8*x + 2*x + x) >> 3 = \n\t;     =\t( 8 * x + 3 * x) >> 3\n\tlea\teax,[ecx+ecx*2]\n\tlea\teax,[eax+ecx*8]\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tjmp\t??save_dif\n\talign\t4\n\n??4:\n\t; eax = x + x / 8 = (8*x + x) >> 3 = (x * 9)>> 3\n\tlea\teax,[ecx+ecx*8]\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tjmp\t??save_dif\n\talign\t4\n\n??3:\n\t; eax = x/2 + x/4 + x/8 = (4*x + 2*x + x) >> 3\n\t;     =\t( 4x + 3x ) >> 3\n\tlea\teax,[ecx+ecx*2]\n\tlea\teax,[eax+ecx*4]\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tjmp\t??save_dif\n\talign\t4\n\n??2:\n\t; eax = x/2 + x/8 = (4*x + x) >> 3\n\tlea\teax,[ecx+ecx*4]\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tjmp\t??save_dif\n\talign\t4\n\n??1:\n\t; eax = x/4 + x/8 = (2x + x )>>8\n\tlea\teax,[ecx+ecx*2]\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tjmp\t??save_dif\n\talign\t4\n\n??0:\n\t; eax = x/8 = x >> 3\n\tmov\teax,ecx\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tjmp\t ??save_dif\n\talign\t4\n\n??15:\n\t; eax = x + x/2 + x/4 + x/8 = (8*x + 4*x +2*x + x)>>3 =\n\t;     = ( x * ( 8 + 4 + 2 + 1 )) >> 3 = ( x * 15 ) >> 3 \n\tlea\tecx,[ecx+ecx*2]\n\tlea\teax,[ecx+ecx*4]\n\tjmp\t??neg_save_dif\n\talign\t4\n\n??14:\n\t; eax = x + x / 2 + x / 8 = (8*x + 4*x + x) >> 3 =\n\t;     =\t( x * 8 + x * 5\t) >> 8\n\tlea\teax,[ecx+ecx*4]\n\tlea\teax,[eax+ecx*8]\n\tjmp\t??neg_save_dif\n\talign\t4\n\n??13:\n\t; eax = x + x / 4 + x / 8 = (8*x + 2*x + x) >> 3 = \n\t;     =\t( 8 * x + 3 * x) >> 3\n\tlea\teax,[ecx+ecx*2]\n\tlea\teax,[eax+ecx*8]\n\tjmp\t??neg_save_dif\n\talign\t4\n\n??12:\n\t; eax = x + x / 8 = (8*x + x) >> 3 = (x * 9)>> 3\n\tlea\teax,[ecx+ecx*8]\n\tjmp\t??neg_save_dif\n\talign\t4\n\n??11:\n\t; eax = x/2 + x/4 + x/8 = (4*x + 2*x + x) >> 3\n\t;     =\t( 4*x - 3*x ) >> 3\n\tlea\teax,[ecx+ecx*2]\n\tlea\teax,[eax+ecx*4]\n\tjmp\t??neg_save_dif\n\talign\t4\n\n??10:\n\t; eax = x/2 + x/8 = (4*x + x) >> 3\n\tlea\teax,[ecx+ecx*4]\n\tjmp\t??neg_save_dif\n\talign\t4\n\n??9:\n\t; eax = x/4 + x/8 = (2x + x )>>8\n\tlea\teax,[ecx+ecx*2]\n\tjmp\t??neg_save_dif\n\talign\t4\n\n??8:\n\t; eax = x/8 = x >> 3\n\tmov\teax,ecx\t\t       ; !!important!! no need for align here\t\n\n??neg_save_dif:\n\tsar\teax,3\t\t\t\t    ; now we divide x>>3\n\tneg \teax\n\n??save_dif:\n \tmov\tecx,[wCode]\t\t\t    ; load offset into CODETab table\t\n\tmov\t[(sCompInfo ebx).dwDifference],eax  ;Store wStep\n\n\t; add difference to predicted value.\n\tadd\teax,[(sCompInfo ebx).dwPredicted]\n\n\t; make sure there is no under or  overflow.\n\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflow\n\tmov\teax,7FFFh\n\n??noOverflow:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflow\n\tmov\teax,0FFFF8000h\n\n??noUnderflow:\n\tadd\tedx,[wCODECIndexTab + ecx*4]\t  ; won't hurt 486 \t\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tmov\t[(sCompInfo ebx).dwPredicted],eax\n\tmov\tecx,[(sCompInfo ebx).dwSampleIndex] ;load dwSampleindex\n\tje\tshort ??output16Bit\n\t; output 8 bit sample\n\txor\tah,80h\n\tmov\t[edi],ah\n\tinc\tedi\n\tjmp\tshort ??adjustIndex\n\talign\t4\n\n??output16Bit:\n\tmov\t[edi],ax\t\t\t  ;Output 16bit sample\n\tadd\tedi,2\n\n??adjustIndex:\n\tcmp\tedx,8000h\n\tjb\tshort ??checkOverflow\n\tmov\tedx,0\t\t\t\t;reset index to zero\n\n??checkOverflow:\n\tinc\tecx\t\t\t\t; advance index and store step value\n\tcmp\tedx,88\t\t\t\t;check if wIndex > 88\n\tjbe\tshort ??adjustStep\n\tmov\tedx,88\t\t\t\t;reset index to 88\n\n??adjustStep:\n\t; advance index and store step value\n\tmov\t[(sCompInfo ebx).dwSampleIndex],ecx\n\n\t; fetch wIndex so we can fetch new step value\n\tmov\teax,[wCODECStepTab + edx*4]\n\n\t; decrement bytes processed and loop back.\n\tdec\tebp\n\tmov\t[(sCompInfo ebx).wStep],ax\n\tjne\t??mainloop\n\tpop\tebp\n\n\tmov\teax,[wCode]\t\t\t; these three lines do not\n\tmov\t[(sCompInfo ebx).wCode],ax\t; seem to have any relevance\n\n\tmov\t[(sCompInfo ebx).wIndex],dx  \t; save index\n\tjmp\t??exitout\n\n;--------------------------------------------------------------------------\n;Left Channel Start\n;--------------------------------------------------------------------------\n\n\n??mainloopl:\n\ttest\t[(sCompInfo ebx).dwSampleIndex],1\n\tje\tshort ??fetchTokenl\n\t\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCodeBuf]\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\tjmp\tshort ??calcDifferencel\n\n??fetchTokenl:\n\txor\teax,eax\n\tmov\tal,[esi]\n\tmov\t[(sCompInfo ebx).wCodeBuf],ax\n\tadd\tesi,2\t\t\t\t\t;2 for stereo\t\t\t\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode],ax\n\n??calcDifferencel:\n\t\t\t\t\t\t\t; reset difference\n\n\tmov\t[(sCompInfo ebx).dwDifference],0\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep]\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4l\n\tadd\t[(sCompInfo ebx).dwDifference],ecx\t;Add wStep\n\n??no4l:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2l\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no2l:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1l\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\n??no1l:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8l\n\tneg\t[(sCompInfo ebx).dwDifference]\t\t;Negate diff\n\n??no8l:\n\t\t; add difference to predicted value.\n\n\tmov\teax,[(sCompInfo ebx).dwPredicted]\n\tadd\teax,[(sCompInfo ebx).dwDifference]\n\n\t\t; make sure there is no under or  overflow.\n\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowl\n\tmov\teax,7FFFh\n\n??noOverflowl:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowl\n\tmov\teax,0FFFF8000h\n\n??noUnderflowl:\n\tmov\t[(sCompInfo ebx).dwPredicted],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bitl\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,4\t\t\t\t\t;4 for stereo\t\t\n\tjmp\tshort ??adjustIndexl\n\n??output8Bitl:\n\t; output 8 bit sample\n\n\txor\tah,80h\n\tmov\t[edi],ah\n\tadd\tedi,2\t\t\t\t\t;2 for stereo       \n\n??adjustIndexl:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode]\n\txor\teax,eax\n\tshl\tecx,2\n\tmov\teax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex],ax\n\t\t\t\t\t\t\t; check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex],8000h\n\tjb\tshort ??checkOverflowl\n\tmov\t[(sCompInfo ebx).wIndex],0\n\tjmp\tshort ??adjustStepl\t\t\t;reset index to zero\n\n\n??checkOverflowl:\n\t\t\t\t\t\t\t\n\tcmp\t[(sCompInfo ebx).wIndex],88\t\t; check if wIndex > 88\n\tjbe\tshort ??adjustStepl\n\tmov\t[(sCompInfo ebx).wIndex],88\t\t; reset index to 88\n\n??adjustStepl:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex]\n\txor\teax,eax\n\tshl\tecx,2\n\tmov\teax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex],1\n\tmov\t[(sCompInfo ebx).wStep],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2\n\tjne\t??mainloopl\n;----------------------------------------------------------------------------\n; Right Side Setup\n;----------------------------------------------------------------------------\n\tmov\teax,[wBytes]\n\tmov\t[dwCODECBytesProcessed],eax\n\tmov\tesi,[(sCompInfo ebx).lpSource]\n\tmov\tedi,[(sCompInfo ebx).lpDest]\n\tinc\tesi\t\t\t\t\t; skip left channel\n\tinc\tedi\t\t\t\t     \t; skip left channel\n\tcmp\t[(sCompInfo ebx).wBitSize],16\t\t;16 bit ??\n\tje\tshort ??doByteDivide\t\t\t\n\tmov\t[dwCODECByteIndex],eax\n\tjmp  short ??mainloopr\n\t\n??doByteDivide:\n\tshr\teax,1 \t\t\t\t\t;Divide size by two\n\tinc\tedi   \t\t\t\t\t; 16 bit so skip 1 more\n\tmov\t[dwCODECByteIndex],eax\n\t\n\n;--------------------------------------------------------------------------\n;Right Channel Start\n;--------------------------------------------------------------------------\n\n\n??mainloopr:\t \n\ttest\t[(sCompInfo ebx).dwSampleIndex2],1\n\tje\tshort ??fetchTokenr\n\txor\teax,eax\n\tmov\tax,[(sCompInfo ebx).wCodeBuf2]\n\tshr\teax,4\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode2],ax\n\tjmp\tshort ??calcDifferencer\n\n??fetchTokenr:\n\txor\teax,eax\n\tmov\tal,[esi]\n\tmov\t[(sCompInfo ebx).wCodeBuf2],ax\n\tadd\tesi,2\t\t\t\t     \t;2 for stereo\t\t\t\n\tand\teax,000Fh\n\tmov\t[(sCompInfo ebx).wCode2],ax\n\n??calcDifferencer:\n\t\t\t\t\t\t\t; reset difference\n\n\tmov\t[(sCompInfo ebx).dwDifference2],0\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wStep2]\n\ttest\teax,4\t\t\t\t\t;Check for wCode & 4\n\tje\tshort ??no4r\n\tadd\t[(sCompInfo ebx).dwDifference2],ecx\t;Add wStep\n\n??no4r:\n\ttest\teax,2\t\t\t\t\t;Check for wCode & 2\n\tje\tshort ??no2r\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 1\n\tshr\tedx,1\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\n??no2r:\n\ttest\teax,1\t\t\t\t\t;Check for wCode & 1\n\tje\tshort ??no1r\n\tmov\tedx,ecx\t\t\t\t\t;Add wStep >> 2\n\tshr\tedx,2\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\n??no1r:\n\tmov\tedx,ecx\t\t\t\t\t;Add in wStep >> 3\n\tshr\tedx,3\n\tadd\t[(sCompInfo ebx).dwDifference2],edx\n\ttest\teax,8\t\t\t\t\t;Check for wCode & 8\n\tje\tshort ??no8r\n\tneg\t[(sCompInfo ebx).dwDifference2]\t\t;Negate diff\n\n??no8r:\n\t; add difference to predicted value.\n\tmov\teax,[(sCompInfo ebx).dwPredicted2]\n\tadd\teax,[(sCompInfo ebx).dwDifference2]\n\tcmp\teax,7FFFh\n\tjl\tshort ??noOverflowr\n\tmov\teax,7FFFh\n\n??noOverflowr:\n\tcmp\teax,0FFFF8000h\n\tjg\tshort ??noUnderflowr\n\tmov\teax,0FFFF8000h\n\n??noUnderflowr:\n\tmov\t[(sCompInfo ebx).dwPredicted2],eax\n\tcmp\t[(sCompInfo ebx).wBitSize],16\n\tjne\tshort ??output8Bitr\n\tmov\t[edi],ax\t\t\t\t;Output 16bit sample\n\tadd\tedi,4\t\t\t\t\t;4 for stereo\t\t***\n\tjmp\tshort ??adjustIndexr\n\n??output8Bitr:\n\t\t\t\t\t\t\t; output 8 bit sample\n\txor\tah,80h\n\tmov\t[edi],ah\n\tadd\tedi,2\t\t\t\t\t;2 for stereo       \n\n??adjustIndexr:\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wCode2]\n\txor\teax,eax\n\tshl\tecx,2\n\tmov\teax,[wCODECIndexTab + ecx]\n\tadd\t[(sCompInfo ebx).wIndex2],ax\n\t\t\t\t\t\t\t; check if wIndex < 0\n\tcmp\t[(sCompInfo ebx).wIndex2],8000h\n\tjb\tshort ??checkOverflowr\n\t\t\t\t\t\t\t; reset index to zero\n\tmov\t[(sCompInfo ebx).wIndex2],0\n\tjmp\tshort ??adjustStepr\n\n??checkOverflowr:\n\t\t\t\t\t\t\t; check if wIndex > 88\n\tcmp\t[(sCompInfo ebx).wIndex2],88\t        \n\tjbe\tshort ??adjustStepr\n\tmov\t[(sCompInfo ebx).wIndex2],88\t\t; reset index to 88\n\n??adjustStepr:\n\t; fetch wIndex so we can fetch new step value\n\n\txor\tecx,ecx\n\tmov\tcx,[(sCompInfo ebx).wIndex2]\n\txor\teax,eax\n\tshl\tecx,2\n\tmov\teax,[wCODECStepTab + ecx]\n\n\t; advance index and store step value\n\n\tadd\t[(sCompInfo ebx).dwSampleIndex2],1\n\tmov\t[(sCompInfo ebx).wStep2],ax\n\n\t; decrement bytes processed and loop back.\n\n\tsub\t[dwCODECByteIndex],2\n\tjne\t??mainloopr\n\t\n\n??exitout:\n;     \tdon't think we need this but just in case i'll leave it here!!\n\n;\tmov\t[(sCompInfo ebx).lpSource],esi\n;\tmov\t[(sCompInfo ebx).lpDest],edi\n\t; set up return value for number of bytes processed.\n\tmov\teax,[dwCODECBytesProcessed]\n\tpop\tedx\n\tpop\tecx\n\tpop\tebx\n\tpop\tedi\n\tpop\tesi\n\tret\n\nJumpTable\tDD\t??0\n\t\tDD\t??1\n\t\tDD\t??2\n\t\tDD\t??3\n\t\tDD\t??4\n\t\tDD\t??5\n\t\tDD\t??6\n\t\tDD\t??7\n\t\tDD\t??8\n\t\tDD\t??9\n\t\tDD\t??10\n\t\tDD\t??11\n\t\tDD\t??12\n\t\tDD\t??13\n\t\tDD\t??14\n\t\tDD\t??15\n\t\t\t \n\n\tENDP\tsosCODECDecompressData\n\nLABEL\tLockedCodeEnd\tBYTE\n\n;***************************************************************************\n;* sosCODEC_LOCK -- locks the JLB audio decompression code\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is lock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:       BOOL sosCODEC_Lock(void);                         \t   *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tsosCODEC_Lock:NEAR\n\tPROC\tsosCODEC_Lock C NEAR USES ebx ecx edx esi edi\n\n\t;\n\t; Lock the code that is used by the sos decompression method.\n\t;\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n  \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags], IF_LOCKED_PM_CODE\n\n\t;\n\t; Lock the data used by the sos decompression method.\n\t;\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags], IF_LOCKED_PM_DATA\n\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\tENDP\tsosCODEC_Lock\n\n;***************************************************************************\n;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code       *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      BOOL true is unlock sucessful, false otherwise\t\t   *\n;*                                                                         *\n;* PROTO:\tBOOL sosCODEC_Unlock(void);                        \t   *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   06/26/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tsosCODEC_Unlock:NEAR\n\tPROC\tsosCODEC_Unlock C NEAR USES ebx ecx edx esi edi\n\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\n??code_not_locked:\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??data_not_locked:\n\tmov\t[InitFlags],0\n\tmov\teax,1\n\tjmp\t??exit\n??error:\n\txor\teax,eax\n??exit:\n\tret\n\tENDP\tsosCODEC_Unlock\n\n\tEND\n\n"
  },
  {
    "path": "WWFLAT32/AUDIO/SOSCOMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*  File              : soscomp.h\n*  Date Created      : 6/1/94\n*  Description       : \n*\n*  Programmer(s)     : Nick Skrepetos\n*  Last Modification : 10/1/94 - 11:37:9 AM\n*  Additional Notes  : Modified by Denzil E. Long, Jr.\n*\n*****************************************************************************\n*            Copyright (c) 1994,  HMI, Inc.  All Rights Reserved            *\n****************************************************************************/\n\n#ifndef  _SOS_COMPRESS\n#define  _SOS_COMPRESS\n\n/* compression types */\nenum {\n\t_ADPCM_TYPE_1,\n\t};\n\n/* define compression structure */\ntypedef struct _tagCOMPRESS_INFO {\n\tchar       *lpSource;\n\tchar       *lpDest;\n\tunsigned long dwCompSize;\n\tunsigned long dwUnCompSize;\n\tunsigned long dwSampleIndex;\n\tlong          dwPredicted;\n\tlong          dwDifference;\n\tshort         wCodeBuf;\n\tshort         wCode;\n\tshort         wStep;\n\tshort         wIndex;\n\n\tunsigned long dwSampleIndex2; //added BP for channel 2\n\tlong          dwPredicted2;   //added BP for channel 2\n\tlong          dwDifference2; \t//added BP for channel 2\n\tshort         wCodeBuf2; \t\t//added BP for channel 2\n\tshort         wCode2; \t\t\t//added BP for channel 2\n\tshort         wStep2; \t\t\t//added BP for channel 2\n\tshort         wIndex2; \t\t\t//added BP for channel 2\n\tshort         wBitSize;\n\tshort\t\t\t  wChannels;\t\t//added BP for # of channels\n\t} _SOS_COMPRESS_INFO;\n\n/* compressed file type header */\ntypedef struct _tagCOMPRESS_HEADER {\n\tunsigned long dwType;              // type of compression\n\tunsigned long dwCompressedSize;    // compressed file size\n\tunsigned long dwUnCompressedSize;  // uncompressed file size\n\tunsigned long dwSourceBitSize;     // original bit size\n\tchar          szName[16];          // file type, for error checking\n\t} _SOS_COMPRESS_HEADER;\n\n/* Prototypes */\nextern \"C\" {\n\tvoid sosCODECInitStream(_SOS_COMPRESS_INFO *);\n\tunsigned long sosCODECCompressData(_SOS_COMPRESS_INFO *,\tunsigned long);\n\tunsigned long sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);\n}\n\n#endif\n\u001a\n"
  },
  {
    "path": "WWFLAT32/AUDIO/SOSDATA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdata.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DATA\n#define  _SOS_DATA\n\n#include <stddef.h>\n\n#pragma pack(4) \nextern   WORD     _sosDIGIData_Start;\nextern   WORD     _sosDIGIData_End;\nextern   WORD     _wSOSDriverLinear[];\nextern   WORD     _wSOSTimerLinear[];\nextern   LPSTR    _lpSOSDriver[];\nextern   LPSTR    _lpSOSTimer[];\nextern   LPSTR    _lpSOSDriverCS[];\nextern   LPSTR    _lpSOSTimerCS[];\nextern   BOOL     _wSOSDriverLoaded[];\nextern   BOOL     _wSOSTimerLoaded[];\nextern   BOOL     _wSOSDriverInitialized[];\nextern   WORD     _wSOSOutputRate[];\nextern   WORD     _wSOSDMABuffersize[];\nextern   LONG     _dwSOSDMABufferPhysical[];\nextern   LPSTR    _lpSOSDMABuffer[];\nextern   BOOL     _wTimerUsed;\nextern   VOID ( far *_lpSOSFillHandler[] )( VOID );\nextern   WORD     _wSOSTimerType[];\nextern   WORD     _wSOSDriverType[];\nextern   _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ];\nextern   LPWORD      _lpSOSDMAIrqCount[];\nextern   LPWORD      _lpSOSDMAFillCount[];\nextern   WORD        _wSOSTmrNextCount;\nextern   VOID ( interrupt far *_lpSOSOldTimer )( VOID );\nextern   WORD     _wSOSDriverID[];\nextern   _SOS_CAPABILITIES _sSOSDriverCaps[];\nextern   WORD        _wSOSDMAPortList[];\nextern   BYTE        _bSOSDMAChannel[];\nextern   _SOS_INIT_DRIVER     _sSOSDIGIInitDriver[];\nextern   BYTE  _pSOSDriverPath[];\nextern   BYTE  _pSOSTempDriverPath[];\nextern   BOOL  _wTIMERUsed;\nextern   WORD  _wTIMERValue;\nextern   VOID ( far * _lpTIMEREvents[] )( VOID );\nextern   WORD _wTIMEREventRate[];\nextern   WORD _dwTIMEREventFraction[];\nextern   WORD _dwTIMEREventFractionCurrent[];\nextern   BYTE  _bSOSMIDITimerSongHandler[];\nextern   BYTE  _bSOSMIDISongHandle;\nextern   WORD  _wSOSTimerMemHandle[];\nextern   WORD  _wSOSDriverMemHandle[];\nextern   WORD  _wSOSRealSeg[];\n\nextern   _FILEHEADER    _sDETFileHeader;\nextern   _DRIVERHEADER  _sDETDriverHeader;\nextern   _FILEHEADER    sLOADFileHeader;\nextern   _DRIVERHEADER  sLOADDriverHeader;\nextern   BOOL           _wDETInitialized;\nextern   WORD           _wDETLinear;\nextern   LPSTR          _lpDETDriverBuffer;    \nextern   LPSTR          _lpDETDriverBufferCS;\nextern   WORD           _hDETFile;\nextern   DWORD          _dwDETDriverIndex;\nextern   WORD           _wDETDriverIndexCur;\nextern   WORD           _wDETMemHandle;\nextern   LPSOSDEVICECAPS _lpDETDeviceCaps;\nextern   _SOS_CAPABILITIES _sDETCaps;  \nextern   PSTR _pSOSErrorStrings[];\nextern   BOOL _wSOSBufferAllocated[];\nextern   BOOL _wSOSSystemInitialized;\nextern   VDS_STRUCT _sSOSVDSInfo;\nextern   _SOS_FILL_INFO _sSOSFillInfo;\nextern   WORD    _wSOSTimerEventIndex;\nextern   WORD  _wSOSTimerEntered;\nextern   WORD  _wSOSDriverSize[];\nextern   WORD  _wSOSTimerSize[];\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nextern   WORD  _sosDIGIData1_Start;\nextern   WORD  _sosDIGIData1_End;\nextern   WORD  _sosDIGIData2_Start;\nextern   WORD  _sosDIGIData2_End;\nextern   BYTE  _bTIMERInstalled;\nextern   BYTE  _bTIMERDPMI;\nextern   WORD  wDetectPort;\nextern   WORD  wDetectIRQ;\nextern   WORD  wDetectDMA;\nextern   WORD  wDetectParam;\n#ifdef __cplusplus\n}\n#endif \n\n#pragma pack()\n\n#endif\n\u001a\n"
  },
  {
    "path": "WWFLAT32/AUDIO/SOSDEFS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdefs.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n\n#ifndef  _SOSDEFS_DEFINED\n#define  _SOSDEFS_DEFINED\n\n#undef   _TRUE\n#undef   _FALSE\n#undef   _NULL\nenum  \n      { \n         _FALSE, \n         _TRUE \n      };\n\n#define  _NULL  0\n\n#ifndef  VOID\n#define  VOID           void\n#endif\ntypedef  int            BOOL;\ntypedef  unsigned int   UINT;\ntypedef  unsigned char  BYTE;\ntypedef  unsigned       WORD;\n#ifndef  LONG\ntypedef  signed long    LONG;\n#endif\ntypedef  unsigned long  DWORD;\n\ntypedef  BYTE  *        PBYTE;\ntypedef  char near *    PSTR;\ntypedef  WORD  *        PWORD;\ntypedef  LONG  *        PLONG;\ntypedef  VOID  *        PVOID;\n\ntypedef  BYTE  far   *  LPBYTE;\ntypedef  BYTE  far   *  LPSTR;\ntypedef  WORD  far   *  LPWORD;\ntypedef  LONG  far   *  LPLONG;\ntypedef  VOID  far   *  LPVOID;\n\ntypedef  BYTE  huge  *  HPBYTE;\ntypedef  BYTE  huge  *  HPSTR;\ntypedef  WORD  huge  *  HPWORD;\ntypedef  LONG  huge  *  HPLONG;\ntypedef  VOID  huge  *  HPVOID;\n\ntypedef  unsigned       HANDLE;\n\n#endif\n\u001a\n"
  },
  {
    "path": "WWFLAT32/AUDIO/SOSFNCT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosfnct.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_FUNCTIONS\n#define  _SOS_FUNCTIONS\n\n#pragma pack(4)\n\nWORD sosDIGILockMemory          (  VOID  );\nWORD sosDIGIUnLockMemory        (  VOID  );\nWORD sosDIGIInitSystem           (  LPSTR, WORD  );\nWORD sosDIGIUnInitSystem         (  VOID  );\nWORD sosDIGIInitDriver           (  WORD, _SOS_HARDWARE far *,\n                                    _SOS_INIT_DRIVER far *, WORD far *   );\nWORD sosDIGIUnInitDriver         (  WORD, BOOL, BOOL  );\nWORD sosDIGILoadDriver          (  WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD sosDIGIUnLoadDriver         (  WORD  );\nWORD sosDIGIGetDeviceCaps        (  WORD, LPSOSDEVICECAPS  );\n\n#ifdef PHARLAP\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#else\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#endif\n\nWORD sosDIGIStopSample           (  WORD, WORD  );\nWORD sosDIGISamplesPlaying       (  WORD  );\nBOOL sosDIGISampleDone           (  WORD, WORD  );\nBOOL sosDIGISampleFilling        (  WORD, WORD  );\nWORD sosDIGIStartSample          (  WORD, _SOS_START_SAMPLE far *  );\nWORD sosDIGIContinueSample       (  WORD, WORD, _SOS_START_SAMPLE far * );\n\n\nWORD  sosDIGIDetectInit          (  LPSTR  );\nWORD  sosDIGIDetectUnInit        (  VOID  );\nWORD  sosDIGIDetectFindHardware  (  WORD, _SOS_CAPABILITIES far *, WORD far * );\nWORD  sosDIGIDetectFindFirst     (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectFindNext      (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectGetSettings   (  _SOS_HARDWARE far *  );\nWORD  sosDIGIDetectGetCaps       (  WORD, _SOS_CAPABILITIES far *  );\nWORD  sosDIGIDetectVerifySettings(  _SOS_HARDWARE far *  );\nPSTR  sosGetErrorString          (  WORD  );\n\nWORD  sosDIGILoadTimer           (  WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD  sosDIGIUnLoadTimer         (  WORD  );\n\nWORD  sosTIMERRegisterEvent      ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle );\nWORD  sosTIMERInitSystem               (  WORD, WORD  );\nWORD  sosTIMERUnInitSystem             (  WORD  );\nWORD  sosTIMERSetRate                  (  WORD  );  \nWORD  sosTIMERRemoveEvent              (  WORD );\nWORD  sosTIMERAlterEventRate           (  WORD, WORD  );\nWORD  sosTIMERGetEventRate             (  WORD  );\nVOID far sosTIMEROldHandler            (  VOID  );\nVOID far sosTIMERHandler               (  VOID  );\n\n// functions in soscntl.c\nWORD  sosDIGISetSampleVolume     ( WORD, WORD, WORD );\nWORD  sosDIGIGetSampleVolume     ( WORD, WORD );\nWORD  sosDIGISetChannel          ( WORD, WORD, WORD );\nWORD  sosDIGIGetChannel          ( WORD, WORD );\nWORD  sosDIGIGetBytesProcessed   ( WORD, WORD );\nWORD  sosDIGIGetLoopCount        ( WORD, WORD );\nWORD  sosDIGISetPanLocation      ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanLocation      ( WORD, WORD );\nDWORD sosDIGISetPitch            ( WORD, WORD, DWORD );\nDWORD sosDIGIGetPitch            ( WORD, WORD );\nWORD  sosDIGIGetDMAPosition      ( WORD );\nWORD  sosDIGISetPanSpeed         ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanSpeed         ( WORD, WORD );\nWORD  sosDIGIGetSampleID         ( WORD, WORD );\nWORD  sosDIGIGetSampleHandle     ( WORD, WORD );\nWORD  sosDIGISetMasterVolume     ( WORD, WORD );\n#ifdef PHARLAP\nVOID  sosFreeVDSPage          ( unsigned short, unsigned short, DWORD );\nWORD  sosAllocVDSPage         ( unsigned short *, unsigned short *, DWORD * );\n#else\nWORD  sosAllocVDSPage            ( LPSTR *, WORD *, WORD * );\nVOID  sosFreeVDSPage             ( WORD, WORD, LONG );\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef PHARLAP\nextern   int   cdecl sosRealFree          ( int );\nextern   BOOL  cdecl  _sos_read( WORD, LPSTR, WORD, WORD * );\nextern   int   cdecl sosRealAlloc( int, int *, int * );\nextern   void  cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD );\nextern   int   cdecl sosGetCS( VOID );\nextern   int   cdecl sosGetES( VOID );\n#else\nextern   int   cdecl sosRealAlloc         ( int, int *, int * );\nextern   int   cdecl sosRealFree          ( int );\n#endif\n\n// sos driver functions\nextern   WORD  cdecl sosDRVLockMemory     ( DWORD, DWORD );\nextern   WORD  cdecl sosDRVUnLockMemory   ( DWORD, DWORD );\nextern   void  cdecl sosDRVGetCapsInfo    ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVGetCapsPtr     ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVInit           ( LPSTR, LPSTR, int, int, int, int, int, int );  \nextern   void  cdecl sosDRVStart          ( LPSTR, LPSTR, int, int );\nextern   void  cdecl sosDRVSetRate        ( LPSTR, LPSTR, int );\nextern   void  cdecl sosDRVSetAction      ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVStop           ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVUnInit         ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVGetFillInfo    ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * );\nextern   void  cdecl sosFillSampleStructs ( PSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVExist       ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVGetSettings ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR );\nextern   WORD  cdecl sosDIGIInitForWindows( WORD );\nextern   WORD  cdecl sosDIGIUnInitForWindows( WORD );\nextern   LPSTR cdecl sosAllocateFarMem      ( WORD, PSTR, WORD * );\nextern   LPSTR cdecl sosCreateAliasCS       ( LPSTR );\nextern   VOID  cdecl sosFreeSelector        ( LPSTR, DWORD );\nextern   LPSTR cdecl sosMAKEDOSPtr          ( PSTR );\nextern   VOID  cdecl sosDetDRVSetEnvString  ( DWORD, PSTR );\nextern   PSTR  cdecl sosDetDRVGetEnvString  ( DWORD );\nextern   VOID  cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR );\nextern   VOID  cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR );\nextern   WORD  cdecl sosDRVGetFreeMemory     ( VOID );\nextern   WORD  cdecl sosDRVAllocVDSStruct    ( WORD, WORD *, WORD * );\nextern   WORD  cdecl sosDRVFreeVDSStruct     ( WORD, WORD );\nextern   WORD  cdecl sosDRVIsWindowsActive   ( VOID );\nextern   WORD  cdecl sosDRVVDSGetBuffer    ( WORD );\nextern   WORD  cdecl sosDRVVDSFreeBuffer   ( WORD );\nextern   WORD  cdecl getDS( VOID );\nextern   WORD  cdecl sosDRVMakeDMASelector   ( WORD );  \nextern   WORD  cdecl sosDRVFreeDMASelector   ( WORD );  \n\n\nextern   void  cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) );\nextern   void  cdecl sosTIMERDRVUnInit( void );\nextern   void  cdecl sosTIMERDRVHandler( void );\nextern   void  cdecl sosTIMERDRVFHandler( void );\nextern   void  cdecl sosTIMERDRVEnable( void );\nextern   void  cdecl sosTIMERDRVDisable( void );\nextern   void  cdecl sosTIMERDRVCallOld( void );\nextern   void  cdecl sosTIMERDRVSetRate( WORD );    \nextern   void  cdecl sosDIGITimer_Start( void );\nextern   void  cdecl sosDIGITimer_End( void );\nextern   void  cdecl sosDIGIDrv_Start( void );\nextern   void  cdecl sosDIGIDrv_End( void );\n#ifdef __cplusplus\n}\n#endif \n\n// external functions for handling system initialization and \n// uninitialization\nWORD  sosEXDIGInitDriver               (  WORD, WORD, WORD, LPSTR,\n                                          _SOS_HARDWARE far *, WORD *  );\nWORD  sosEXDIGIUnInitDriver            (  VOID  );\n\nWORD  sosEXDETFindDriver               (  WORD, LPSTR, _SOS_HARDWARE far *,\n                                          _SOS_CAPABILITIES far *  );\n\n// memory locking prototypes\nVOID  sosDIGICaps_Start( VOID );\nVOID  sosDIGICaps_End( VOID );\nVOID  sosDIGIErr_Start( VOID );\nVOID  sosDIGIErr_End( VOID );\nVOID  sosDIGITmr_Start( VOID );\nVOID  sosDIGITmr_End( VOID );\nVOID  sosDIGIStart_Start( VOID );\nVOID  sosDIGIStart_End( VOID );\nVOID  sosDIGIPlyng_Start( VOID );\nVOID  sosDIGIPlyng_End( VOID );\nVOID  sosDIGIRate_Start( VOID );\nVOID  sosDIGIRate_End( VOID );\nVOID  sosDIGIDone_Start( VOID );\nVOID  sosDIGIDone_End( VOID );\nVOID  sosDIGIDetec_Start( VOID );\nVOID  sosDIGIDetec_End( VOID );\nVOID  sosDIGIInit_Start( VOID );\nVOID  sosDIGIInit_End( VOID );\nVOID  sosDIGILoad_Start( VOID );\nVOID  sosDIGILoad_End( VOID );\nVOID  sosDIGICntl_Start( VOID );\nVOID  sosDIGICntl_End( VOID );\n\n#pragma pack()\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/AUDIO/SOSRES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosres.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#define  _SOS_RESOURCE\n#ifndef  _SOS_RESOURCE\n#define  _SOS_RESOURCE\n\n// structure for resource file header\ntypedef struct\n{\n   // file version\n   WORD     wVersion;\n\n   // file size\n   LONG     dwFileSize;\n\n   // number of resources in file\n   WORD     wResCount;\n\n   // offset of resource data from top of file\n   LONG     dwResOffset;\n\n   // offset of sync track from top of file\n   LONG     dwSyncTrackOffset;\n\n}  _RES_FILE_HEADER;\n\n// structure for resource block header\ntypedef struct\n{\n   // resource id\n   WORD     wID;\n\n   // resource type\n   WORD     wResType;\n\n   // offset of next block\n   LONG     dwNextBlock; \n\n   // size of the current resource information\n   LONG     dwResSize;\n\n   // rate to play block at\n   WORD     wBlockRate;\n\n   // id for the sync track to use\n   WORD     wSyncTrackID;\n\n}  _RES_BLOCK_HEADER;\n\n// structure for sync mark tag\ntypedef struct _tagSYNCMARK\n{\n   // ID of the type of mark being used\n   WORD  wID;\n\n   // location in data of sync mark\n   LONG  dwSyncOffset;\n\n   // length of sync block\n   LONG  dwSyncSize;\n\n   // start sample data\n   _SOS_START_SAMPLE sampleData;\n    \n} _RES_SYNCMARK;\n\ntypedef union\n{\n   // structure for sync mark tag\n   _RES_SYNCMARK  syncMark; \n\n} _RES_TAG;\n\n// union for filter information for prepareWave\ntypedef union\n{\n   // filter type\n   WORD     wFilterID;\n\n   // structure for volume\n   struct   volume \n   {\n      WORD  wVolume;\n   };\n\n   // structure for delay\n   struct   delay\n   {  \n      WORD  wDelaySamples;\n   };\n\n} _SOS_FILTER; \n\n \n#endif\n\n\u001a"
  },
  {
    "path": "WWFLAT32/AUDIO/SOUND.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : SOUND.H                                  *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : September 1, 1993                        *\n *                                                                         *\n *                  Last Update : September 1, 1993   [JLB]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SOUND_H\n#define SOUND_H\n\n#define\tHMI_DRIVER\tTRUE\n#include\t\"sos.h\"\n#include\t\"soscomp.h\"\n\n/*\n**\tMaximum number of sound effects that may run at once.\n*/\n#define\tMAX_SFX\t\t4\n\n/*\n** Size of temp HMI low memory staging buffer.\n*/\n#define\tSFX_MINI_STAGE_BUFFER_SIZE\t\t(1024*4)\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/AUDIO/SOUND.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : SOUND.H                                  *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : September 1, 1993                        *\n *                                                                         *\n *                  Last Update : September 1, 1993   [JLB]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SOUND_H\n#define SOUND_H\n\n#define\tHMI_DRIVER\tTRUE\n#include\t\"sos.h\"\n#include\t\"soscomp.h\"\n\n/*\n**\tMaximum number of sound effects that may run at once.\n*/\n#define\tMAX_SFX\t\t5\n\n/*\n** Size of temp HMI low memory staging buffer.\n*/\n#define\tSFX_MINI_STAGE_BUFFER_SIZE\t\t(1024*4)\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/AUDIO/SOUNDINT.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDINT.CPP                             *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 28, 1995   [PWG]                    *\n *                                                                         *\n * This module contains all of the functions that are used within our      *\n * sound interrupt.  They are stored in a seperate module because memory\t*\n * around these functions must be locked or they will cause a read to\t\t*\n * be generated while in an interrupt.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Simple_Copy -- Copyies 1 or 2 source chuncks to a dest                *\n *   Sample_Copy -- Copies sound data from source format to raw format.    *\n *   DigiCallback -- Low level double buffering handler.                   *\n *   save_my_regs -- Inline function which will save assembly regs         *\n *   restore_my_regs -- Inline function which will restore saved registes  *\n *   Audio_Add_Long_To_Pointer -- Adds an offset to a ptr casted void      *\n *   Init_Locked_Data -- Initializes sound driver locked data              *\n *   Audio_Mem_Set -- Quick see routine to set memory to a value           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n#pragma pack(4)\n#include \"soundint.h\"\n//#include \"mem.h\"\n\n/***************************************************************************\n** All routines past this point must be locked for the sound driver to\t  **\n** function under a VCPI memory manager.  These locks are unnecessary if  **\n** the driver does not have to run under windows or does not use virtual  **\n** memory.                                                                **\n***************************************************************************/\n\t\n/***************************************************************************\n * SAVE_MY_REGS -- Inline function which will save assembly regs           *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n\n#pragma aux save_my_regs =\t\t\\\n\t\t\"pushfd\"\t\t\t\\\n\t\t\"pushad\"\t\t\t\\\n\t\t\"push ds\"\t\t\\\n\t\t\"push es\"\t\t\\\n\t\t\"push fs\"\t\t\\\n\t\t\"push gs\"\t\t\\\n\t\t\"push ds\"\t\t\\\n\t\t\"pop  es\";\n\n#pragma aux enable = \\\n\t\t\"sti\";\n\n#pragma aux disable = \\\n\t\t\"cli\";\n\n/***************************************************************************\n * RESTORE_MY_REGS -- Inline function which will restore saved registers   *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n\n#pragma aux restore_my_regs =\t\\\n\t\t\"pop\tgs\"\t\t\\\n\t\t\"pop\tfs\"\t\t\\\n\t\t\"pop\tes\"\t\t\\\n\t\t\"pop\tds\"\t\t\\\n\t\t\"popad\"\t\t\t\\\n\t\t\"popfd\";\n\n/***************************************************************************\n * SIMPLE_COPY -- Copyies 1 or 2 source chuncks to a dest                  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nlong Simple_Copy(void ** source, long * ssize, void ** alternate, long * altsize, void **dest, long size)\n{\n\n\n\tlong\tout = 0;\t\t// Number of bytes copied to the destination.\n\n\t/*\n\t**\tIt could happen that entering this routine, the source buffer\n\t**\thas been exhausted, but the alternate buffer is still valid.\n\t**\tMove the alternate into the primary position before proceeding.\n\t*/\n\tif (!(*ssize)) {\n\t\t*source = *alternate;\n\t\t*ssize = *altsize;\n\t\t*alternate = NULL;\n\t\t*altsize = 0;\n\t}\n\n\tif (*source && *ssize) {\n\t\tlong\ts;\t\t\t\t// Scratch length var.\n\n\t\t/*\n\t\t**\tCopy as much as possible from the primary source, but no\n\t\t**\tmore than the primary source has to offer.\n\t\t*/\n\t\ts = size;\n\t\tif (*ssize < s) s = *ssize;\n\t\tMem_Copy(*source, *dest, s);\n\t\t*source = Audio_Add_Long_To_Pointer(*source, s);\n\t\t*ssize -= s;\n\t\t*dest = Audio_Add_Long_To_Pointer(*dest, s);\n\t\tsize -= s;\n\t\tout += s;\n\n\t\t/*\n\t\t**\tIf the primary source was insufficient to fill the request, then\n\t\t**\tmove the alternate into the primary position and try again.\n\t\t*/\n\t\tif (size) {\n\t\t\t*source = *alternate;\n\t\t\t*ssize = *altsize;\n\t\t\t*alternate = 0;\n\t\t\t*altsize = 0;\n\t\t\tout += Simple_Copy(source, ssize, alternate, altsize, dest, size);\n\t\t}\n\t}\n\n\treturn(out);\n}\n\n/***********************************************************************************************\n * Sample_Copy -- Copies sound data from source format to raw format.                          *\n *                                                                                             *\n *    This routine is used to copy the sound data (possibly compressed) to the destination     *\n *    buffer in raw format.                                                                    *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the source data (possibly compressed).                      *\n *                                                                                             *\n *          dest     -- Pointer to the destination buffer.                                     *\n *                                                                                             *\n *          size     -- The size of the destination buffer.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes placed into the output buffer.  This is usually   *\n *          the number of bytes requested except in the case when the source is exhausted.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/03/1994 JLB : Created.                                                                 *\n *   09/04/1994 JLB : Revamped entirely.                                                       *\n *=============================================================================================*/\n#pragma argsused\nlong Sample_Copy(SampleTrackerType *st, void ** source, long * ssize, void ** alternate, long * altsize, void * dest, long size, SCompressType scomp, void * trailer, WORD *trailersize)\n{\n\n\tlong\ts;\n\tlong\tdatasize = 0;\t\t// Output bytes.\n\n\tswitch (scomp) {\n\t\tdefault:\n\n\t\tcase SCOMP_NONE:\n\t\t\tdatasize = Simple_Copy(source, ssize, alternate, altsize, &dest, size);\n\t\t\tbreak;\n\n\t\tcase SCOMP_WESTWOOD:\n\t\tcase SCOMP_SOS:\n\t\t\twhile (size > 0) {\n\n\t\t\t\t/*\n\t\t\t\t**\tThe block spans two buffers.  It must be copied down to \n\t\t\t\t**\ta staging area before it can be decompressed.\n\t\t\t\t*/\n\t\t\t\t{\n\t\t\t\t\tlong magic;\n\t\t\t\t\tunsigned short fsize;\n\t\t\t\t\tunsigned short dsize;\n\t\t\t\t\tvoid *fptr;\n\t\t\t\t\tvoid *dptr;\n\t\t\t\t\tvoid *mptr;\n\n\t\t\t\t\tfptr = &fsize;\n\t\t\t\t\tdptr = &dsize;\n\t\t\t\t\tmptr = &magic;\n\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &fptr, sizeof(fsize));\n\t\t\t\t\tif (s < sizeof(fsize)) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &dptr, sizeof(dsize));\n\t\t\t\t\tif (s < sizeof(dsize) || size < dsize) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &mptr, sizeof(magic));\n\t\t\t\t\tif (s < sizeof(magic) || magic != LockedData.MagicNumber) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the frame and uncompressed data size are identical, then this\n\t\t\t\t\t**\tindicates that the frame is not compressed.  Just copy it directly\n\t\t\t\t\t**\tto the destination buffer in this case.\n\t\t\t\t\t*/\n\t\t\t\t\tif (fsize == dsize) {\n\t\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &dest, fsize);\n\t\t\t\t\t\tif (s < dsize) {\n\t\t\t\t\t\t\treturn (datasize);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tThe frame was compressed, so copy it to the staging buffer, and then\n\t\t\t\t\t\t**\tuncompress it into the final destination buffer.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tfptr = LockedData.UncompBuffer;\n\t\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &fptr, fsize);\n\t\t\t\t\t\tif (s < fsize) {\n\t\t\t\t\t\t\treturn (datasize);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (scomp == SCOMP_WESTWOOD) {\n\t\t\t\t\t\t\tDecompress_Frame(LockedData.UncompBuffer, dest, dsize);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tst->sosinfo.lpSource = (char *)LockedData.UncompBuffer;\n\t\t\t\t\t\t\tst->sosinfo.lpDest\t = (char *)dest;\n\t\t\t\t\t\t\tsosCODECDecompressData(&st->sosinfo, dsize);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdest = Audio_Add_Long_To_Pointer(dest, dsize);\n\t\t\t\t\t}\n\t\t\t\t\tdatasize += dsize;\n\t\t\t\t\tsize -= dsize;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak;\n\t}\n\treturn(datasize);\n}\n\nVOID far cdecl maintenance_callback(VOID)\n{\n\tsave_my_regs();\n\tint\t\t\t\t\tindex;\n\tSampleTrackerType\t*st;\n\n\tif (!LockedData._int && LockedData.DigiHandle != -1 && LockedData.ServiceSomething) {\n\n\t\tLockedData._int++;\n\t\tenable();\n\t\tLockedData.ServiceSomething = FALSE;\n\t\tst = &LockedData.SampleTracker[0];\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\n\t\t\tif (st->Active) {\n\n\t\t\t\t/*\n\t\t\t\t**\tGeneral service routine to handle moving small blocks from the\n\t\t\t\t**\tsource into the low RAM staging buffers.  If the source is\n\t\t\t\t**\tcompressed, then this will also uncompress it as the copy\n\t\t\t\t**\tis performed.\n\t\t\t\t*/\n\t\t\t\tif (st->Service) {\n\t\t\t\t\tif (st->DontTouch) {\n\t\t\t\t\t\tLockedData.ServiceSomething = TRUE;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tst->Service = FALSE;\n\n#if(FALSE)\n\t\t\t\t\t\tst->DataLength = SFX_MINI_STAGE_BUFFER_SIZE;\n#else\n\t\t\t\t\t\tst->DataLength = Sample_Copy(\tst,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Source, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Remainder, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->QueueBuffer, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->QueueSize, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tst->Buffer[st->Index], \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSFX_MINI_STAGE_BUFFER_SIZE, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tst->Compression, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Trailer[0], \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->TrailerLen);\n\n#endif\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tFor file streamed samples, fill the queue pointer if needed.\n\t\t\t\t**\tThis allows for delays in calling the Sound_Callback function.\n\t\t\t\t*/\n\t\t\t\tif (!st->DontTouch && !st->QueueBuffer && st->FilePending) {\n\t\t\t\t\tst->QueueBuffer = Audio_Add_Long_To_Pointer(st->FileBuffer, (long)(st->Odd%LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t\t\t\t\tst->FilePending--;\n\t\t\t\t\tst->Odd++;\n\t\t\t\t\tif (!st->FilePending) {\n\t\t\t\t\t\tst->QueueSize = st->FilePendingSize;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tst->QueueSize = LockedData.StreamBufferSize;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAdvance to the next sample control structure.\n\t\t\t*/\n\t\t\tst++;\n\t\t}\n\t\tLockedData._int--;\n\t}\n\n\t\n\tif (!LockedData._int) {\n\n\t\tLockedData._int++;\n\t\tst = &LockedData.SampleTracker[0];\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\n\t\t\t/*\n\t\t\t**\tIf there are any samples that require fading, then do so at this\n\t\t\t**\ttime.\n\t\t\t*/\n\t\t\tif (st->Active && st->Reducer && st->Volume) {\n\t\t\t\tif (st->Reducer >= st->Volume) {\n\t\t\t\t\tst->Volume = 0;\n\t\t\t\t} else {\n\t\t\t\t\tst->Volume -= st->Reducer;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (st->IsScore) {\n\t\t\t\t\tsosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, (st->Volume>>8) * LockedData.ScoreVolume);\n\t\t\t\t} else {\n\t\t\t\t\tsosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, (st->Volume>>8) * LockedData.SoundVolume);\n\t\t\t\t}\n\t\t\t}\n\t\t\tst++;\n\t\t}\n\t\tLockedData._int--;\n\t}\n\trestore_my_regs();\n}\n/***********************************************************************************************\n * DigiCallback -- Low level double buffering handler.                                         *\n *                                                                                             *\n *    This routine is called in an interrupt to handle the double                              *\n *    buffering of digital audio.  This routine is the interface between                       *\n *    the buffers maintained by Sound_Callback() and the HMI driver                            *\n *    itself.                                                                                  *\n *                                                                                             *\n * INPUT:   driverhandle   -- The handle to the HMI driver.                                    *\n *                                                                                             *\n *          callsource     -- Code indicating the reason for the callback.                     *\n *                                                                                             *\n *          sampleid       -- The ID number of the sample itself.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This is called in an interrupt so it return as quickly as                       *\n *             possible.                                                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID cdecl far DigiCallback(unsigned int driverhandle, unsigned int callsource, unsigned int sampleid)\n{\n\tSampleTrackerType\t*st;\n\tint\tindex;\n\n\n\t/*\n\t**\tFind the correct control structure for the handle specified.\n\t*/\n\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\tst = &LockedData.SampleTracker[index];\n\t\tif (st->Active && st->Handle == sampleid) {\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (index == LockedData.MaxSamples) {\n\t\treturn;\n\t}\n\n\tif (driverhandle == LockedData.DigiHandle) {\n\n\t\tswitch (callsource) {\n\n\t\t\t/*\n\t\t\t**\tThe sample is now no longer audible.  Don't stop the sample\n\t\t\t**\ttracking if a servicing is needed.  If it is needed then\n\t\t\t**\tobviously the sample isn't quite done.\n\t\t\t*/\n\t\t\tcase _SAMPLE_DONE:\n\t\t\t\tst->Active = FALSE;\n\t\t\t\tif (!st->IsScore) {\n//\t\t\t\t\tDPMI_Unlock(st->Original, st->OriginalSize);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tThe sample is finished processing, but not necessarily finished playing.\n\t\t\t*/\n\t\t\tcase _SAMPLE_PROCESSED:\n\t\t\t\tif (st->DataLength && st->Active) {\n\t\t\t\t\t_SOS_START_SAMPLE start;\n\t\t\t\t\tlong dlength;\n\n\t\t\t\t\tdlength = st->DataLength;\n\t\t\t\t\tst->DataLength = 0;\n\n\t\t\t\t\tAudio_Mem_Set(&start, 0, sizeof(start));\n\t\t\t\t\tstart.lpSamplePtr = (LPSTR)st->Buffer[st->Index];\n\n\t\t\t\t\tstart.dwSampleSize = dlength-1;\n\n\t\t\t\t\tstart.wSampleFlags = st->Flags;\n\t\t\t\t\tstart.lpCallback = (void cdecl (far *)(unsigned int, unsigned int, unsigned int))&DigiCallback;\n\t\t\t\t\tstart.wLoopCount = 0;\n\t\t\t\t\tif (st->IsScore) {\n\t\t\t\t\t\tstart.wVolume = (st->Volume>>8) * LockedData.ScoreVolume;\n\t\t\t\t\t\tsosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, start.wVolume);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstart.wVolume = (st->Volume>>8) * LockedData.SoundVolume;\n\t\t\t\t\t\tsosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, start.wVolume);\n\t\t\t\t\t}\n\n\t\t\t\t\tstart.wChannel = st->Stereo;\n\t\t\t\t\tstart.wSampleID = index+1;\n\t\t\t\t\tstart.dwSamplePitchAdd = st->Pitch;\n\t\t\t\t\tst->Index ^= 1;\n\n\t\t\t\t\tif (st->Remainder || st->QueueBuffer || st->Callback || st->FilePending) {\n\t\t\t\t\t\tst->Service = TRUE;\n\t\t\t\t\t\tLockedData.ServiceSomething = TRUE;\n\t\t\t\t\t}\n\n\t\t\t\t\tsosDIGIContinueSample(LockedData.DigiHandle, st->Handle, &start);\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThis is necessary because Stop_Sample may screw things\n\t\t\t\t\t**\tup, otherwise.  Can't rely on the _SAMPLE_DONE call.\n\t\t\t\t\t*/\n\t\t\t\t\tst->Active = FALSE;\n\t\t\t\t\tif (!st->IsScore) {\n//\t\t\t\t\t\tDPMI_Unlock(st->Original, st->OriginalSize);\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tSample is now looping (not used).\n\t\t\t*/\n\t\t\tcase _SAMPLE_LOOPING:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n}\n\nvoid far HMI_TimerCallback(void)\n{\n}\n\n\n/***************************************************************************\n * ADD_LONG_TO_POINTER -- Adds an offset to a ptr casted void              *\n *                                                                         *\n * INPUT:\t\tvoid * ptr - the pointer to add to                          *\n *\t\t\t\t\tlong size  - the size to add to it\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     void * ptr - the new location it will point to              *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n\nvoid *Audio_Add_Long_To_Pointer(void const *ptr, long size) \n{\n \treturn ((void *) ( (char const *) ptr + size));\n}\n\n/***************************************************************************\n * AUDIO_MEM_SET -- Quick see routine to set memory to a value             *\n *                                                                         *\n * INPUT:\t\tvoid const *  - the memory that needs to be set             *\n *\t\t\t\t\tunsigned char - the value to set the memory to\t\t\t\t\t*\n *\t\t\t\t\tlong size     - how big an area to set\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/28/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid Audio_Mem_Set(void const *ptr, unsigned char value, long size)\n{\n\tunsigned char *temp = (unsigned char *)ptr;\n\tfor (int lp = 0; lp < size; lp ++) {\n\t\t*temp++ = value;\n\t}\n}\n"
  },
  {
    "path": "WWFLAT32/AUDIO/SOUNDINT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDINT.CPP                             *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 28, 1995   [PWG]                    *\n *                                                                         *\n * This module contains all of the functions that are used within our      *\n * sound interrupt.  They are stored in a seperate module because memory\t*\n * around these functions must be locked or they will cause a read to\t\t*\n * be generated while in an interrupt.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Simple_Copy -- Copyies 1 or 2 source chuncks to a dest                *\n *   Sample_Copy -- Copies sound data from source format to raw format.    *\n *   DigiCallback -- Low level double buffering handler.                   *\n *   save_my_regs -- Inline function which will save assembly regs         *\n *   restore_my_regs -- Inline function which will restore saved registes  *\n *   Audio_Add_Long_To_Pointer -- Adds an offset to a ptr casted void      *\n *   Init_Locked_Data -- Initializes sound driver locked data              *\n *   Audio_Mem_Set -- Quick see routine to set memory to a value           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n#pragma pack(4)\n#include \"soundint.h\"\n//#include \"mem.h\"\n\n/***************************************************************************\n** All routines past this point must be locked for the sound driver to\t  **\n** function under a VCPI memory manager.  These locks are unnecessary if  **\n** the driver does not have to run under windows or does not use virtual  **\n** memory.                                                                **\n***************************************************************************/\n\t\n/***************************************************************************\n * SAVE_MY_REGS -- Inline function which will save assembly regs           *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n\n#pragma aux save_my_regs =\t\t\\\n\t\t\"pushfd\"\t\t\t\\\n\t\t\"pushad\"\t\t\t\\\n\t\t\"push ds\"\t\t\\\n\t\t\"push es\"\t\t\\\n\t\t\"push fs\"\t\t\\\n\t\t\"push gs\"\t\t\\\n\t\t\"push ds\"\t\t\\\n\t\t\"pop  es\";\n\n#pragma aux enable = \\\n\t\t\"sti\";\n\n#pragma aux disable = \\\n\t\t\"cli\";\n\n/***************************************************************************\n * RESTORE_MY_REGS -- Inline function which will restore saved registers   *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n\n#pragma aux restore_my_regs =\t\\\n\t\t\"pop\tgs\"\t\t\\\n\t\t\"pop\tfs\"\t\t\\\n\t\t\"pop\tes\"\t\t\\\n\t\t\"pop\tds\"\t\t\\\n\t\t\"popad\"\t\t\t\\\n\t\t\"popfd\";\n\n/***************************************************************************\n * SIMPLE_COPY -- Copyies 1 or 2 source chuncks to a dest                  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nlong Simple_Copy(void ** source, long * ssize, void ** alternate, long * altsize, void **dest, long size)\n{\n\n\n\tlong\tout = 0;\t\t// Number of bytes copied to the destination.\n\n\t/*\n\t**\tIt could happen that entering this routine, the source buffer\n\t**\thas been exhausted, but the alternate buffer is still valid.\n\t**\tMove the alternate into the primary position before proceeding.\n\t*/\n\tif (!(*ssize)) {\n\t\t*source = *alternate;\n\t\t*ssize = *altsize;\n\t\t*alternate = NULL;\n\t\t*altsize = 0;\n\t}\n\n\tif (*source && *ssize) {\n\t\tlong\ts;\t\t\t\t// Scratch length var.\n\n\t\t/*\n\t\t**\tCopy as much as possible from the primary source, but no\n\t\t**\tmore than the primary source has to offer.\n\t\t*/\n\t\ts = size;\n\t\tif (*ssize < s) s = *ssize;\n\t\tMem_Copy(*source, *dest, s);\n\t\t*source = Audio_Add_Long_To_Pointer(*source, s);\n\t\t*ssize -= s;\n\t\t*dest = Audio_Add_Long_To_Pointer(*dest, s);\n\t\tsize -= s;\n\t\tout += s;\n\n\t\t/*\n\t\t**\tIf the primary source was insufficient to fill the request, then\n\t\t**\tmove the alternate into the primary position and try again.\n\t\t*/\n\t\tif (size) {\n\t\t\t*source = *alternate;\n\t\t\t*ssize = *altsize;\n\t\t\t*alternate = 0;\n\t\t\t*altsize = 0;\n\t\t\tout += Simple_Copy(source, ssize, alternate, altsize, dest, size);\n\t\t}\n\t}\n\n\treturn(out);\n}\n\n/***********************************************************************************************\n * Sample_Copy -- Copies sound data from source format to raw format.                          *\n *                                                                                             *\n *    This routine is used to copy the sound data (possibly compressed) to the destination     *\n *    buffer in raw format.                                                                    *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the source data (possibly compressed).                      *\n *                                                                                             *\n *          dest     -- Pointer to the destination buffer.                                     *\n *                                                                                             *\n *          size     -- The size of the destination buffer.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes placed into the output buffer.  This is usually   *\n *          the number of bytes requested except in the case when the source is exhausted.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/03/1994 JLB : Created.                                                                 *\n *   09/04/1994 JLB : Revamped entirely.                                                       *\n *=============================================================================================*/\n#pragma argsused\nlong Sample_Copy(SampleTrackerType *st, void ** source, long * ssize, void ** alternate, long * altsize, void * dest, long size, SCompressType scomp, void * trailer, WORD *trailersize)\n{\n\n\tlong\ts;\n\tlong\tdatasize = 0;\t\t// Output bytes.\n\n\tswitch (scomp) {\n\t\tdefault:\n\n\t\tcase SCOMP_NONE:\n\t\t\tdatasize = Simple_Copy(source, ssize, alternate, altsize, &dest, size);\n\t\t\tbreak;\n\n\t\tcase SCOMP_WESTWOOD:\n\t\tcase SCOMP_SOS:\n\t\t\twhile (size > 0) {\n\n\t\t\t\t/*\n\t\t\t\t**\tThe block spans two buffers.  It must be copied down to \n\t\t\t\t**\ta staging area before it can be decompressed.\n\t\t\t\t*/\n\t\t\t\t{\n\t\t\t\t\tlong magic;\n\t\t\t\t\tunsigned short fsize;\n\t\t\t\t\tunsigned short dsize;\n\t\t\t\t\tvoid *fptr;\n\t\t\t\t\tvoid *dptr;\n\t\t\t\t\tvoid *mptr;\n\n\t\t\t\t\tfptr = &fsize;\n\t\t\t\t\tdptr = &dsize;\n\t\t\t\t\tmptr = &magic;\n\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &fptr, sizeof(fsize));\n\t\t\t\t\tif (s < sizeof(fsize)) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &dptr, sizeof(dsize));\n\t\t\t\t\tif (s < sizeof(dsize) || size < dsize) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\n\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &mptr, sizeof(magic));\n\t\t\t\t\tif (s < sizeof(magic) || magic != LockedData.MagicNumber) {\n\t\t\t\t\t\treturn datasize;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the frame and uncompressed data size are identical, then this\n\t\t\t\t\t**\tindicates that the frame is not compressed.  Just copy it directly\n\t\t\t\t\t**\tto the destination buffer in this case.\n\t\t\t\t\t*/\n\t\t\t\t\tif (fsize == dsize) {\n\t\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &dest, fsize);\n\t\t\t\t\t\tif (s < dsize) {\n\t\t\t\t\t\t\treturn (datasize);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tThe frame was compressed, so copy it to the staging buffer, and then\n\t\t\t\t\t\t**\tuncompress it into the final destination buffer.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tfptr = LockedData.UncompBuffer;\n\t\t\t\t\t\ts = Simple_Copy(source, ssize, alternate, altsize, &fptr, fsize);\n\t\t\t\t\t\tif (s < fsize) {\n\t\t\t\t\t\t\treturn (datasize);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (scomp == SCOMP_WESTWOOD) {\n\t\t\t\t\t\t\tDecompress_Frame(LockedData.UncompBuffer, dest, dsize);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tst->sosinfo.lpSource = (char *)LockedData.UncompBuffer;\n\t\t\t\t\t\t\tst->sosinfo.lpDest\t = (char *)dest;\n\t\t\t\t\t\t\tsosCODECDecompressData(&st->sosinfo, dsize);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdest = Audio_Add_Long_To_Pointer(dest, dsize);\n\t\t\t\t\t}\n\t\t\t\t\tdatasize += dsize;\n\t\t\t\t\tsize -= dsize;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak;\n\t}\n\treturn(datasize);\n}\n\nVOID far cdecl maintenance_callback(VOID)\n{\n\tsave_my_regs();\n\tint\t\t\t\t\tindex;\n\tSampleTrackerType\t*st;\n\n\tif (!LockedData._int && LockedData.DigiHandle != -1 && LockedData.ServiceSomething) {\n\n\t\tLockedData._int++;\n\t\tenable();\n\t\tLockedData.ServiceSomething = FALSE;\n\t\tst = &LockedData.SampleTracker[0];\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\n\t\t\tif (st->Active) {\n\n\t\t\t\t/*\n\t\t\t\t**\tGeneral service routine to handle moving small blocks from the\n\t\t\t\t**\tsource into the low RAM staging buffers.  If the source is\n\t\t\t\t**\tcompressed, then this will also uncompress it as the copy\n\t\t\t\t**\tis performed.\n\t\t\t\t*/\n\t\t\t\tif (st->Service) {\n\t\t\t\t\tif (st->DontTouch) {\n\t\t\t\t\t\tLockedData.ServiceSomething = TRUE;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tst->Service = FALSE;\n\n#if(FALSE)\n\t\t\t\t\t\tst->DataLength = SFX_MINI_STAGE_BUFFER_SIZE;\n#else\n\t\t\t\t\t\tst->DataLength = Sample_Copy(\tst,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Source, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Remainder, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->QueueBuffer, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->QueueSize, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tst->Buffer[st->Index], \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSFX_MINI_STAGE_BUFFER_SIZE, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tst->Compression, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->Trailer[0], \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&st->TrailerLen);\n\n#endif\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tFor file streamed samples, fill the queue pointer if needed.\n\t\t\t\t**\tThis allows for delays in calling the Sound_Callback function.\n\t\t\t\t*/\n\t\t\t\tif (!st->DontTouch && !st->QueueBuffer && st->FilePending) {\n\t\t\t\t\tst->QueueBuffer = Audio_Add_Long_To_Pointer(st->FileBuffer, (long)(st->Odd%LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t\t\t\t\tst->FilePending--;\n\t\t\t\t\tst->Odd++;\n\t\t\t\t\tif (!st->FilePending) {\n\t\t\t\t\t\tst->QueueSize = st->FilePendingSize;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tst->QueueSize = LockedData.StreamBufferSize;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAdvance to the next sample control structure.\n\t\t\t*/\n\t\t\tst++;\n\t\t}\n\t\tLockedData._int--;\n\t}\n\n\t\n\tif (!LockedData._int) {\n\n\t\tLockedData._int++;\n\t\tst = &LockedData.SampleTracker[0];\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\n\t\t\t/*\n\t\t\t**\tIf there are any samples that require fading, then do so at this\n\t\t\t**\ttime.\n\t\t\t*/\n\t\t\tif (st->Active && st->Reducer && st->Volume) {\n\t\t\t\tif (st->Reducer >= st->Volume) {\n\t\t\t\t\tst->Volume = 0;\n\t\t\t\t} else {\n\t\t\t\t\tst->Volume -= st->Reducer;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (st->IsScore) {\n\t\t\t\t\tsosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, (st->Volume>>8) * LockedData.ScoreVolume);\n\t\t\t\t} else {\n\t\t\t\t\tsosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, (st->Volume>>8) * LockedData.SoundVolume);\n\t\t\t\t}\n\t\t\t}\n\t\t\tst++;\n\t\t}\n\t\tLockedData._int--;\n\t}\n\trestore_my_regs();\n}\n/***********************************************************************************************\n * DigiCallback -- Low level double buffering handler.                                         *\n *                                                                                             *\n *    This routine is called in an interrupt to handle the double                              *\n *    buffering of digital audio.  This routine is the interface between                       *\n *    the buffers maintained by Sound_Callback() and the HMI driver                            *\n *    itself.                                                                                  *\n *                                                                                             *\n * INPUT:   driverhandle   -- The handle to the HMI driver.                                    *\n *                                                                                             *\n *          callsource     -- Code indicating the reason for the callback.                     *\n *                                                                                             *\n *          sampleid       -- The ID number of the sample itself.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This is called in an interrupt so it return as quickly as                       *\n *             possible.                                                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID cdecl far DigiCallback(unsigned int driverhandle, unsigned int callsource, unsigned int sampleid)\n{\n\tSampleTrackerType\t*st;\n\tint\tindex;\n\n\n\t/*\n\t**\tFind the correct control structure for the handle specified.\n\t*/\n\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\tst = &LockedData.SampleTracker[index];\n\t\tif (st->Active && st->Handle == sampleid) {\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (index == LockedData.MaxSamples) {\n\t\treturn;\n\t}\n\n\tif (driverhandle == LockedData.DigiHandle) {\n\n\t\tswitch (callsource) {\n\n\t\t\t/*\n\t\t\t**\tThe sample is now no longer audible.  Don't stop the sample\n\t\t\t**\ttracking if a servicing is needed.  If it is needed then\n\t\t\t**\tobviously the sample isn't quite done.\n\t\t\t*/\n\t\t\tcase _SAMPLE_DONE:\n\t\t\t\tst->Active = FALSE;\n\t\t\t\tif (!st->IsScore) {\n//\t\t\t\t\tDPMI_Unlock(st->Original, st->OriginalSize);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tThe sample is finished processing, but not necessarily finished playing.\n\t\t\t*/\n\t\t\tcase _SAMPLE_PROCESSED:\n\t\t\t\tif (st->DataLength && st->Active) {\n\t\t\t\t\t_SOS_START_SAMPLE start;\n\t\t\t\t\tlong dlength;\n\n\t\t\t\t\tdlength = st->DataLength;\n\t\t\t\t\tst->DataLength = 0;\n\n\t\t\t\t\tAudio_Mem_Set(&start, 0, sizeof(start));\n\t\t\t\t\tstart.lpSamplePtr = (LPSTR)st->Buffer[st->Index];\n\n\t\t\t\t\tstart.dwSampleSize = dlength-1;\n\n\t\t\t\t\tstart.wSampleFlags = st->Flags;\n\t\t\t\t\tstart.lpCallback = (void cdecl (far *)(unsigned int, unsigned int, unsigned int))&DigiCallback;\n\t\t\t\t\tstart.wLoopCount = 0;\n\t\t\t\t\tif (st->IsScore) {\n\t\t\t\t\t\tstart.wVolume = (st->Volume>>8) * LockedData.ScoreVolume;\n\t\t\t\t\t\tsosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, start.wVolume);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstart.wVolume = (st->Volume>>8) * LockedData.SoundVolume;\n\t\t\t\t\t\tsosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, start.wVolume);\n\t\t\t\t\t}\n\n\t\t\t\t\tstart.wChannel = st->Stereo;\n\t\t\t\t\tstart.wSampleID = index+1;\n\t\t\t\t\tstart.dwSamplePitchAdd = st->Pitch;\n\t\t\t\t\tst->Index ^= 1;\n\n\t\t\t\t\tif (st->Remainder || st->QueueBuffer || st->Callback || st->FilePending) {\n\t\t\t\t\t\tst->Service = TRUE;\n\t\t\t\t\t\tLockedData.ServiceSomething = TRUE;\n\t\t\t\t\t}\n\n\t\t\t\t\tsosDIGIContinueSample(LockedData.DigiHandle, st->Handle, &start);\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThis is necessary because Stop_Sample may screw things\n\t\t\t\t\t**\tup, otherwise.  Can't rely on the _SAMPLE_DONE call.\n\t\t\t\t\t*/\n\t\t\t\t\tst->Active = FALSE;\n\t\t\t\t\tif (!st->IsScore) {\n//\t\t\t\t\t\tDPMI_Unlock(st->Original, st->OriginalSize);\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tSample is now looping (not used).\n\t\t\t*/\n\t\t\tcase _SAMPLE_LOOPING:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n}\n\nvoid far HMI_TimerCallback(void)\n{\n}\n\n\n/***************************************************************************\n * ADD_LONG_TO_POINTER -- Adds an offset to a ptr casted void              *\n *                                                                         *\n * INPUT:\t\tvoid * ptr - the pointer to add to                          *\n *\t\t\t\t\tlong size  - the size to add to it\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     void * ptr - the new location it will point to              *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n\nvoid *Audio_Add_Long_To_Pointer(void const *ptr, long size) \n{\n \treturn ((void *) ( (char const *) ptr + size));\n}\n\n/***************************************************************************\n * AUDIO_MEM_SET -- Quick see routine to set memory to a value             *\n *                                                                         *\n * INPUT:\t\tvoid const *  - the memory that needs to be set             *\n *\t\t\t\t\tunsigned char - the value to set the memory to\t\t\t\t\t*\n *\t\t\t\t\tlong size     - how big an area to set\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/28/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid Audio_Mem_Set(void const *ptr, unsigned char value, long size)\n{\n\tunsigned char *temp = (unsigned char *)ptr;\n\tfor (int lp = 0; lp < size; lp ++) {\n\t\t*temp++ = value;\n\t}\n}\n"
  },
  {
    "path": "WWFLAT32/AUDIO/SOUNDINT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDINT.H                               *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 23, 1995   [PWG]                    *\n *                                                                         *\n * This file is the include file for the Westwood Sound Sytem defines and  *\n * routines that are handled in an interrupt.\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"sound.h\"\n\n/*\n** Defines for true and false.  These are included because we do not allow\n** the sound int to include any of the westwood standard headers.  If we\n** did, there might be too much temptation to call another library function.\n** this would be bad, because then that function would not be locked.\n*/\n#define\tFALSE\t\t0\n#define\tTRUE\t\t1\n\n/*\n** Define the different type of sound compression avaliable to the westwood\n** library.\n*/\ntypedef enum {\n\tSCOMP_NONE=0,\t\t\t// No compression -- raw data.\n\tSCOMP_WESTWOOD=1,\t\t// Special sliding window delta compression.\n\tSCOMP_SONARC=33,\t\t// Sonarc frame compression.\n\tSCOMP_SOS=99\t\t\t// SOS frame compression.\n} SCompressType;\n\n/*\n**\tThis is the safety overrun margin for the sonarc compressed\n** data frames.  This value should be equal the maximum 'order' times\n**\tthe maximum number of bytes per sample.  It should be evenly divisible\n**\tby 16 to aid paragraph alignment.\n*/\n#define\tSONARC_MARGIN\t\t\t\t32\n\n\n/*\n** Define the sample control structure which helps us to handle feeding\n** data to the sound interrupt.\n*/\n#pragma pack(1);\ntypedef struct {\n\t/*\n\t**\tThis flags whether this sample structure is active or not.\n\t*/\n\tunsigned Active:1;\n\n\t/*\n\t**\tThis flags whether the sample is loading or has been started.\n\t*/\n\tunsigned Loading:1;\n\n\t/*\n\t**\tThis semaphore ensures that simultaneous update of this structure won't\n\t**\toccur.  This is necessary since both interrupt and regular code can modify\n\t**\tthis structure.\n\t*/\n\tunsigned DontTouch:1;\n\n\t/*\n\t**\tIf this sample is really to be considered a score rather than\n\t**\ta sound effect, then special rules apply.  These largely fall into\n\t**\tthe area of volume control.\n\t*/\n\tunsigned IsScore:1;\n\n\t/*\n\t**\tThis is the original sample pointer. It is used to control the sample based on\n\t**\tpointer rather than handle. The handle method is necessary when more than one\n\t**\tsample could be playing simultaneously. The pointer method is necessary when\n\t**\tthe dealing with a sample that may have stopped behind the programmer's back and\n\t**\tthis occurance is not otherwise determinable.  It is also used in\n\t** conjunction with original size to unlock a sample which has been DPMI\n\t** locked.\n\t*/\n\tvoid const *Original;\n\tlong OriginalSize;\n\n\t/*\n\t**\tThese are pointers to the double buffers in low ram.\n\t*/\n\tVOID *Buffer[2];\n\n\t/*\n\t**\tThe number of bytes in the buffer that has been filled but is not\n\t**\tyet playing.  This value is normally the size of the buffer,\n\t**\texcept for the case of the last bit of the sample.\n\t*/\n\tLONG DataLength;\n\n\t/*\n\t**\tThis is the buffer index for the low buffer that\n\t**\thas been filled with data but not yet being\n\t**\tplayed.\n\t*/\n\tWORD Index;\n\n\t/*\n\t**\tPointer to the sound data that has not yet been copied\n\t**\tto the playback buffers.\n\t*/\n\tVOID *Source;\n\n\t/*\n\t**\tThis is the number of bytes remaining in the source data as\n\t**\tpointed to by the \"Source\" element.\n\t*/\n\tLONG Remainder;\n\n\t/*\n\t**\tSamples maintain a priority which is used to determine\n\t**\twhich sounds live or die when the maximum number of\n\t**\tsounds are being played.\n\t*/\n\tWORD Priority;\n\n\t/*\n\t**\tThis is the handle as returned by sosDIGIStartSample function.\n\t*/\n\tWORD Handle;\n\n\t/*\n\t**\tThis is the current volume of the sample as it is being played.\n\t*/\n\tWORD Volume;\n\tWORD Reducer;\t\t// Amount to reduce volume per tick.\n\n\t/*\n\t**\tThis flags whether the sample is in stereo.\n\t*/\n\tWORD Stereo;\n\n\t/*\n\t**\tThis is the compression that the sound data is using.\n\t*/\n\tSCompressType Compression;\n\tWORD TrailerLen;\t\t\t\t\t\t// Number of trailer bytes in buffer.\n\tBYTE Trailer[SONARC_MARGIN];\t\t// Maximum number of 'order' samples needed.\n\n\n\tDWORD Pitch;\n\tWORD Flags;\n\n\t/*\n\t**\tThis flag indicates whether this sample needs servicing.  \n\t**\tServicing entails filling one of the empty low buffers.\n\t*/\n\tWORD Service;\n\n\t/*\n\t**\tThis flag is TRUE when the sample has stopped playing,\n\t**\tBUT there is more data available.  The sample must be\n\t**\trestarted upon filling the low buffer.\n\t*/\n\tBOOL Restart;\n\n\t/*\n\t**\tStreaming control handlers.\n\t*/\n\tBOOL (*Callback)(WORD id, WORD *odd, VOID **buffer, LONG *size);\n\tVOID\t*QueueBuffer;\t// Pointer to continued sample data.\n\tLONG\tQueueSize;\t\t// Size of queue buffer attached.\n\tWORD\tOdd;\t\t\t\t// Block number tracker (0..StreamBufferCount-1).\n\tint\tFilePending;\t// Number of buffers already filled ahead.\n\tlong\tFilePendingSize;\t// Number of bytes in last filled buffer.\n\n\t/*\n\t**\tThe file variables are used when streaming directly off of the \n\t**\thard drive.\n\t*/\n\tWORD\tFileHandle;\t\t// Streaming file handle (ERROR = not in use).\n\tVOID\t*FileBuffer;\t// Temporary streaming buffer (allowed to be freed).\n\t/*\n\t** The following structure is used if the sample if compressed using\n\t** the sos 16 bit compression Codec.\n\t*/\n\t_SOS_COMPRESS_INFO sosinfo;\n\n} SampleTrackerType;\n\n\ntypedef struct LockedData {\n\tunsigned int \t\tDigiHandle; \t\t\t// = -1;\n\tBOOL \t\t\t\t\tServiceSomething;\t\t// = FALSE;\n\tlong \t\t\t\t\tMagicNumber; \t\t\t// = 0xDEAF;\n\tVOID \t\t\t\t\t*UncompBuffer;\t\t\t// = NULL;\n\tlong \t\t\t\t\tStreamBufferSize; \t// = (2*SFX_MINI_STAGE_BUFFER_SIZE)+128;\n\tshort \t\t\t\tStreamBufferCount; \t// = 32;\n\tSampleTrackerType SampleTracker[MAX_SFX];\n\tunsigned int\t\tSoundVolume;\n\tunsigned int\t\tScoreVolume;\n\tBOOL\t\t\t\t\t_int;\n\tint\t\t\t\t\tMaxSamples;\t\t\t\t\n\tint\t\t\t\t\tRate;\t\t\t\t\n} LockedDataType;\n\nextern LockedDataType LockedData;\n#pragma pack(4);\n\nvoid Init_Locked_Data(void);\nvoid Unlock_Locked_Data(void);\nlong Simple_Copy(void ** source, long * ssize, void ** alternate, long * altsize, void **dest, long size);\nlong Sample_Copy(SampleTrackerType *st, void ** source, long * ssize, void ** alternate, long * altsize, void * dest, long size, SCompressType scomp, void * trailer, WORD *trailersize);\nVOID far cdecl maintenance_callback(VOID);\nVOID cdecl far DigiCallback(unsigned int driverhandle, unsigned int callsource, unsigned int sampleid);\nvoid far HMI_TimerCallback(void);\nvoid *Audio_Add_Long_To_Pointer(void const *ptr, long size);\nvoid\tDPMI_Unlock(VOID const *ptr, long const size);\nextern \"C\" {\n\tvoid\tAudio_Mem_Set(void const *ptr, unsigned char value, long size);\n\tvoid\tMem_Copy(void const *source, void *dest, unsigned long bytes_to_copy);\n\tlong  Decompress_Frame(void * source, void * dest, long size);\n\tint\tDecompress_Frame_Lock(void);\n\tint\tDecompress_Frame_Unlock(void);\n\tint\tsosCODEC_Lock(void);\n\tint\tsosCODEC_Unlock(void);\n\tvoid\t__GETDS(void);\n}\t\t\n\n"
  },
  {
    "path": "WWFLAT32/AUDIO/SOUNDIO.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Id: soundio.cpp 1.41 1994/06/20 15:01:39 joe_bostic Exp $ */\n/***********************************************************************************************\n **             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             **\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Sound Library                                                *\n *                                                                                             *\n *                    File Name : SOUND.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 22, 1991                                                *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   File_Callback -- called to fill queue buffer for streaming sample     \t\t\t\t\t\t  *\n *   Stream_Sample_Volume -- generic streaming sample playback init                            *\n *   Stream_Sample -- generic streaming sample playback init                                   *\n *   File_Stream_Sample -- Streams a sample directly from a file.                              *\n *   File_Stream_Preload -- Handles initial proload of a streaming samples                     *\n *   File_Stream_Sample_Volume -- Streams a sample directly from a file w/volume.              *\n *   Sound_Callback -- Audio driver callback function.                                         *\n *   Load_Sample -- Loads a digitized sample into RAM.                                         *\n *   Load_Sample_Into_Buffer -- Loads a digitized sample into a buffer.                        *\n *   Free_Sample -- Frees a previously loaded digitized sample.                                *\n *   Sound_End -- Uninitializes the sound driver.                                              *\n *   Stop_Sample -- Stops any currently playing sampled sound.                                 *\n *   Sample_Status -- Queries the current playing sample status (if any).                      *\n *   Sample_Length -- returns length of a sample in ticks                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#pragma pack(4)\n#include\t\"soundint.h\"\n#include <dos.h>\n#include <mem.h>\n#include <stdio.h>\n#include <string.h>\n#include\t<direct.h>\n#include\t<stdlib.h>\n#include\t<wwmem.h>\n#include\t<keyboard.h>\n#include\t<file.h>\n#include\t<i86.h>\n#include <timer.h>\n#pragma pack(1)\n#include \"audio.h\"\n#pragma pack(4)\n\n\n//int Mono_Printf(char const *string, ...);\n#include\t<mono.h>\n\n/*\n**\tIf this is defined, then the streaming audio buffer will be filled\n**\tto maximum whenever filling is to occur. If undefined, it will fill\n**\tthe streaming buffer in smaller chunks.\n*/\n#define\tSIMPLE_FILLING\n\n/*\n**\tThis define (if present) enables the simple HMI hardware initialization process.\n**\tThe process does not do auto detection, but rather takes the value directly from\n**\tthe setup program and uses that as the sound card number.  The only \"detection\" it\n**\tdoes is to recognized the presence of the card and fetch its settings.\n*/\n#define\tSIMPLE_HMI_INIT\n\n\n/*\n**\tThis is the rate that the maintenance callback gets called.\n*/\n#define\tMAINTENANCE_RATE\t\t\t60\n\n/*\n**\tSize of the temporary buffer in XMS/EMS that direct file\n**\tstreaming of sounds will allocate.\n*/\n#define\tSTREAM_BUFFER_SIZE\t\t(128L*1024L)\n\n/*\n** Define the number of \"StreamBufferSize\" blocks that are read in\n** at a minimum when the streaming sample load callback routine\n** is called.  We will IGNORE loads that are less that this in order\n** to avoid constant seeking on the CD.\n*/\n#define\tSTREAM_CUSHION_BLOCKS\t4\n\n\n/*\n**\tThis is the maximum size that a sonarc block can be.  All sonarc blocks\n**\tmust be either a multiple of this value or a binary root of this value.\n*/\n#define\tLARGEST_SONARC_BLOCK\t\t2048\n\n\n//////////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////// structs ///////////////////////////////////////\n\nstatic _SOS_CAPABILITIES\tDigiCaps;\nstatic _SOS_HARDWARE \t\tDigiHardware;\nstatic WORD \t\t\t\t\tMidiHandle = -1;\nstatic unsigned int far\t\tDigiTimer = 0;\nstatic unsigned int far\t\tMaintainTimer = 0;\nstatic unsigned int far\t\tSystemTimer = 0;\nstatic int\t\t\t\t\t\tBits_Per_Sample;\nVOID \t\t\t\t\t\t\t\t*DigiBuffer = NULL;\nstatic BOOL \t\t\t\t\tStartingFileStream = FALSE;\nshort \t\t\t\t\t\t\tStreamLowImpact = FALSE;\nMemoryFlagType \t\t\t\tStreamBufferFlag = MEM_NORMAL;\nint \t\t\t\t\t\t\t\tMisc;\nSFX_Type \t\t\t\t\t\tSoundType;\nSample_Type \t\t\t\t\tSampleType;\nint\t\t\t\t\t\t\t\tReverseChannels = FALSE;\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nstatic BOOL File_Callback(WORD id, WORD *odd, VOID **buffer, LONG *size);\nstatic int cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback)(WORD id, WORD *odd, VOID **buffer, LONG *size), int volume, int handle);\nstatic int cdecl Stream_Sample(void *buffer, long size, BOOL (*callback)(WORD id, WORD *odd, VOID **buffer, LONG *size));\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n\n/***************************************************************************\n * FILE_CALLBACK -- called to fill queue buffer for streaming sample       *\n *                                                                         *\n * This callback is called whenever the queue buffer playback has begun\t\t*\n * and another buffer is needed for queuing up.  Returns TRUE if there\t\t*\n * is more data to read from the file.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:\tWORD id\t\t\t- the sample id number                          *\n *\t\t\t\tWORD *odd\t\t- which sample buffer to put info in\t\t\t\t*\n *\t\t\t\tVOID **buffer\t- the buffer pointer to load data into\t\t\t\t*\n *\t\t\t\tLONG *size\t\t- the amount to load\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:  BOOL true if more data to load, FALSE if done loading          *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nstatic BOOL File_Callback(WORD id, WORD *odd, VOID **buffer, LONG *size)\n{\n\tSampleTrackerType\t*st;\t\t// Pointer to sample playback control struct.\n\tVOID\t\t\t\t\t*ptr;\t\t// Pointer to working portion of file buffer.\n\n\tif (id != -1) {\n\t\tst = &LockedData.SampleTracker[id];\n\t\tptr = st->FileBuffer;\n\t\tif (ptr) {\n\n\t\t\t/*\n\t\t\t**\tMove the next pending block into the primary \n\t\t\t**\tposition.  Do this only if the queue pointer is\n\t\t\t**\tnull.\n\t\t\t*/\n\t\t\tst->DontTouch = TRUE;\n\t\t\tif (!*buffer && st->FilePending) {\n\t\t\t\t*buffer = Add_Long_To_Pointer(ptr, (long)(*odd % LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t\t\t\tst->FilePending--;\n\t\t\t\t*odd = *odd + 1;\n\t\t\t\tif (!st->FilePending) {\n\t\t\t\t\t*size = st->FilePendingSize;\n\t\t\t\t} else {\n\t\t\t\t\t*size = LockedData.StreamBufferSize;\n\t\t\t\t}\n\t\t\t}\n\t\t\tst->DontTouch = FALSE;\n\t\t\tmaintenance_callback();\n\n\t\t\t/*\n\t\t\t**\tIf the file handle is still valid, then read in the next\n\t\t\t**\tblock and add it to the next pending slot available.\n\t\t\t*/\n\t\t\tif (st->FilePending <\n\t\t\t\t(StreamLowImpact ? (LockedData.StreamBufferCount>>1) : ((LockedData.StreamBufferCount-3))) && st->FileHandle != ERROR) {\n\n\n\t\t\t\tint num_empty_buffers;\n\n#ifdef SIMPLE_FILLING\n\t\t\t\tnum_empty_buffers = (LockedData.StreamBufferCount-2) - st->FilePending;\n#else\n\n\t\t\t\t//\n\t\t\t\t// num_empty_buffers will be from 1 to StreamBufferCount\n\t\t\t\t//\n\t\t\t\tif (StreamLowImpact) {\n\t\t\t\t\tnum_empty_buffers = MIN((LockedData.StreamBufferCount >> 1)+STREAM_CUSHION_BLOCKS, (LockedData.StreamBufferCount - 2) - st->FilePending);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tnum_empty_buffers = (LockedData.StreamBufferCount - 2) - st->FilePending;\n\t\t\t\t}\n#endif\n\t\t\t\t\n\n\n\t\t\t\twhile (num_empty_buffers && st->FileHandle != ERROR) {\n\t\t\t\t\tint\ttofill;\n\t\t\t\t\tlong\tpsize;\n\n\t\t\t\t\ttofill = (*odd + st->FilePending) % LockedData.StreamBufferCount;\n\n\t\t\t\t\tptr = Add_Long_To_Pointer(st->FileBuffer, (long)tofill * (long)LockedData.StreamBufferSize);\n\t\t\t\t\tpsize = Read_File(st->FileHandle, ptr, LockedData.StreamBufferSize);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf less than the requested amount of data was read, this\n\t\t\t\t\t**\tindicates that the source file is exhausted.  Flag the source\n\t\t\t\t\t**\tfile as closed so that no further reading is attempted.\n\t\t\t\t\t*/\n\t\t\t\t\tif (psize != LockedData.StreamBufferSize) {\n\t\t\t\t\t\tClose_File(st->FileHandle);\n\t\t\t\t\t\tst->FileHandle = ERROR;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf any real data went into the pending buffer, then flag\n\t\t\t\t\t**\tthat this buffer is valid.\n\t\t\t\t\t*/\n\t\t\t\t\tif (psize) {\n\t\t\t\t\t\tst->DontTouch = TRUE;\n\t\t\t\t\t\tst->FilePendingSize = psize;\n\t\t\t\t\t\tst->FilePending++;\n\t\t\t\t\t\tst->DontTouch = FALSE;\n\t\t\t\t\t\tmaintenance_callback();\n\t\t\t\t\t}\n\t\t\t\t\tnum_empty_buffers--;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAfter filling all pending buffers, check to see if the queue buffer\n\t\t\t\t**\tis empty.  If so, then assign the first available pending buffer to the\n\t\t\t\t**\tqueue.\n\t\t\t\t*/\n\t\t\t\tst->DontTouch = TRUE;\n\t\t\t\tif (!st->QueueBuffer && st->FilePending) {\n\t\t\t\t\tst->QueueBuffer = Add_Long_To_Pointer(st->FileBuffer, (long)(st->Odd%LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t\t\t\t\tst->FilePending--;\n\t\t\t\t\tst->Odd++;\n\t\t\t\t\tif (!st->FilePending) {\n\t\t\t\t\t\tst->QueueSize = st->FilePendingSize;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tst->QueueSize = LockedData.StreamBufferSize;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tst->DontTouch = FALSE;\n\t\t\t\tmaintenance_callback();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf there are no more buffers that the callback routine\n\t\t\t**\tcan slot into the primary position, then signal that\n\t\t\t**\tno furthur callbacks are needed.\n\t\t\t*/\n\t\t\tif (st->FilePending) {\n\t\t\t\treturn(TRUE);\n\t\t\t}\n\t\t}\n\t}\n\treturn(FALSE);\n}\n\n/***************************************************************************\n * STREAM_SAMPLE_VOLUME -- generic streaming sample playback init          *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nstatic int cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback)(WORD id, WORD *odd, VOID **buffer, LONG *size), int volume, int handle)\n{\n\tint\t\t\t\t\t\tplayid=-1;\t// Sample play ID.\n\tSampleTrackerType\t\t*st;\t\t\t// Working pointer to sample control structure.\n\tlong\t\t\t\t\t\toldsize;\t\t// Copy of original sound size.\n\tAUDHeaderType\t\t\theader;\n\n\tif (buffer && size && LockedData.DigiHandle != -1) {\n\n\t\t/*\n\t\t**\tStart the first section of the sound playing.\n\t\t*/\n\t\tMem_Copy(buffer, &header, sizeof(header));\n\t\toldsize = header.Size;\n\t\theader.Size = size-sizeof(header);\n\t\tMem_Copy(&header, buffer, sizeof(header));\n\t\tplayid = Play_Sample_Handle(buffer, 0xFF, volume, 0x0, handle);\n\t\theader.Size = oldsize;\n\t\tMem_Copy(&header, buffer, sizeof(header));\n\n\t\t/*\n\t\t**\tIf the sample actually started playing, then flag this\n\t\t**\tsample as a streaming type and signal for a callback\n\t\t**\tto occur.\n\t\t*/\n\t\tif (playid != -1) {\n\t\t\tst = &LockedData.SampleTracker[playid];\n\n\t\t\tst->Callback = callback;\n\t\t\tst->Odd = 0;\n\t\t}\n\t}\n\treturn (playid);\n}\n\n/***************************************************************************\n * STREAM_SAMPLE -- generic streaming sample playback init          \t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nstatic int cdecl Stream_Sample(void *buffer, long size, BOOL (*callback)(WORD id, WORD *odd, VOID **buffer, LONG *size), int handle)\n{\n\treturn Stream_Sample_Vol(buffer, size, callback, 0xFF, handle);\n}\n\n\n\n/***********************************************************************************************\n * File_Stream_Sample -- Streams a sample directly from a file.                                *\n *                                                                                             *\n *    This will take the file specified and play it directly from disk.                        *\n *    It performs this by allocating a temporary buffer in XMS/EMS and                         *\n *    then keeping this buffer filled by the Sound_Callback() routine.                         *\n *                                                                                             *\n * INPUT:   filename -- The name of the file to play.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the handle to the sound -- just like Play_Sample().                        *\n *                                                                                             *\n * WARNINGS:   The temporary buffer is allocated when this routine is                          *\n *             called and then freed when the sound is finished.  Keep                         *\n *             this in mind.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint File_Stream_Sample(char const *filename, BOOL real_time_start)\n{\n\treturn File_Stream_Sample_Vol(filename, 0xFF, real_time_start);\n}\n\n/***************************************************************************\n * FILE_STREAM_PRELOAD -- Handles initial proload of streaming samples     *\n *                                                                         *\n * This function is called before a sample which streams from disk is      *\n * started.  It can be called to either fill the buffer in small chunks\t\t*\n * from the call back routine or to fill the entire buffer at once.  This\t*\n * is wholely dependant on whether the Loading bit is set within the \t\t*\n * sample tracker.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:\t\tLockedData.SampleTracker * to the header which tracks this samples     *\n *\t\t\t\t\t\t\t\t\t\t processing.\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/05/1995 PWG : Created.                                             *\n *=========================================================================*/\n\nvoid File_Stream_Preload(int handle)\n{\n\tSampleTrackerType\t*st\t= &LockedData.SampleTracker[handle];\n\tint\tfh\t\t\t\t\t\t= st->FileHandle;\n\tint \tmaxnum\t\t\t\t= (LockedData.StreamBufferCount >> 1) + STREAM_CUSHION_BLOCKS;\n\tvoid \t*buffer\t\t\t\t= st->FileBuffer;\n\tint\tnum;\n\n\t/*\n\t** Figure just how much we need to load.  If we are doing the load in progress\n\t** then we will only load two blocks.\n\t*/\n\tif (st->Loading) {\n\t\tnum = st->FilePending + 2;\n\t\tnum = MIN(num, maxnum);\n\t} else {\n\t\tnum = maxnum;\n\t}\n\n\t//printf(\"Before buffer load!\\n\");\n\t/*\n\t** Loop through the blocks and load up the number we need.\n\t*/\n\tfor (int index = st->FilePending; index < num; index++) {\n\t\tlong s = Read_File(fh, Add_Long_To_Pointer(buffer, (long)index * (long)LockedData.StreamBufferSize), LockedData.StreamBufferSize);\n\t\t//printf(\"Reading block of size %d Stream Buffer = %d\\n\");\n\t\tif (s) {\n\t\t\tst->FilePendingSize = s;\n\t\t\tst->FilePending++;\n\t\t}\n\t\tif (s < LockedData.StreamBufferSize) break;\n\t}\n\n\t/*\n\t** If the last block was incomplete (ie. it didn't completely fill the buffer) or\n\t** we have now filled up as much of the Streaming Buffer as we need to, then now is\n\t** the time to kick off the sample.\n\t*/\n\tif (st->FilePendingSize < LockedData.StreamBufferSize || index == maxnum) {\n\t\t//printf(\"Before Stream Sample Volume!\\n\");\n\t\t/*\n\t\t** Actually start the sample playing, and don't worry about the file callback\n\t\t** it won't be called for a while.\n\t\t*/\n\t\t{\n\t\t\tint old\t\t\t\t\t\t= LockedData.SoundVolume;\n\t\t\tint size\t\t\t\t\t\t= (st->FilePending == 1) ? st->FilePendingSize : LockedData.StreamBufferSize;\n\t\t\tLockedData.SoundVolume\t= LockedData.ScoreVolume;\n\n\t\t\tStartingFileStream \t\t= TRUE;\n\t\t\tStream_Sample_Vol(buffer, size, File_Callback, st->Volume, handle);\n\t\t\tStartingFileStream \t\t= FALSE;\n\t\t\tLockedData.SoundVolume \t= old;\n\t\t}\n\t\t//printf(\"After Stream Sample Volume!\\n\");\n\t\t/*\n\t\t** The Sample is finished loading (if it was loading in small pieces) so record that\n\t\t** so that it will now use the active logic in the file call back.\n\t\t*/\n\t\tst->Loading\t\t\t\t\t= FALSE;\n\n\t\t/*\n\t\t** Decrement the file pending because the first block is already playing thanks\n\t\t** to the play sample call above.\n\t\t*/\n\t\tst->FilePending--;\n\n\t\t/*\n\t\t** If File pending is now a zero, then we only preloaded one block and there\n\t\t** is nothing more to play.  So clear the sample tracing structure of the\n\t\t** information it no longer needs.\n\t\t*/\n\t\tif (!st->FilePending) {\n\t\t\tst->Odd\t\t\t\t\t= 0;\n\t\t\tst->QueueBuffer\t\t= 0;\n\t\t\tst->QueueSize\t\t\t= 0;\n\t\t\tst->FilePendingSize\t= 0;\n\t\t\tst->Callback \t\t\t= NULL;\n\t\t\tClose_File(fh);\n\t\t} else {\n\t\t\t/*\n\t\t\t**\tThe QueueBuffer counts as an already played block so remove it from the total.\n\t\t\t** Note: We didn't remove it before because there might not have been one.\n\t\t\t*/\n\t\t\tst->FilePending--;\n\n\t\t\t/*\n\t\t\t** When we start loading we need to start past the first two blocks.  Why this\n\t\t\t** is called Odd, I haven't got the slightest.\n\t\t\t*/\n\t\t\tst->Odd \t\t\t\t\t= 2;\n\n\t\t\t/*\n\t\t\t** If the file pending size is less than the stream buffer, then the last block\n\t\t\t** we loaded was the last block period.  So close the file and reset the handle.\n\t\t\t*/\n\t\t\tif (st->FilePendingSize != LockedData.StreamBufferSize) {\n\t\t\t\tClose_File(fh);\n\t\t\t\tst->FileHandle = ERROR;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** The Queue buffer needs to point at the next block to be processed.  The size\n\t\t\t** of the queue is dependant on how many more blocks there are.\n\t\t\t*/\n\t\t\tst->QueueBuffer = Add_Long_To_Pointer(buffer, LockedData.StreamBufferSize);\n\t\t\tif (!st->FilePending) {\n\t\t\t\tst->QueueSize = st->FilePendingSize;\n\t\t\t} else {\n\t\t\t\tst->QueueSize = LockedData.StreamBufferSize;\n\t\t\t}\n\t\t}\n\t}\n}\n/***********************************************************************************************\n * File_Stream_Sample_Vol -- Streams a sample directly from a file.                            *\n *                                                                                             *\n *    This will take the file specified and play it directly from disk.                        *\n *    It performs this by allocating a temporary buffer in XMS/EMS and                         *\n *    then keeping this buffer filled by the Sound_Callback() routine.                         *\n *                                                                                             *\n * INPUT:   filename -- The name of the file to play.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the handle to the sound -- just like Play_Sample().                        *\n *                                                                                             *\n * WARNINGS:   The temporary buffer is allocated when this routine is                          *\n *             called and then freed when the sound is finished.  Keep                         *\n *             this in mind.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start)\n{\n\tstatic VOID\t*buffer = NULL;\n\tSampleTrackerType\t*st;\n\tint\tfh;\n\tint\thandle = -1;\n\tlong\tsize;\n\tint\tindex;\n\n\tif (LockedData.DigiHandle != -1 && filename && Find_File(filename)) {\n\t\t//printf(\"Before initialize memory!\\n\");\n\t\t/*\n\t\t**\tMake sure all sample tracker structures point to the same\n\t\t**\tupper memory buffer.  This allocation only occurs if at\n\t\t**\tleast one sample gets \"streamed\".\n\t\t*/\n\t\tif (!buffer) {\n\t\t\tbuffer = Alloc(LockedData.StreamBufferSize * LockedData.StreamBufferCount, (MemoryFlagType)(StreamBufferFlag | MEM_TEMP | MEM_LOCK));\n\t\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\t\t\tLockedData.SampleTracker[index].FileBuffer = buffer;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** If after trying to allocate the buffer we still fail then\n\t\t** we can stream this sample.\n\t\t*/\n\t\tif (!buffer) return(-1);\n\t\t\n\t\t//printf(\"Before Open File!\\n\");\n\t\t/*\n\t\t** Lets see if we can sucessfully open up the file.  If we can't, \n\t\t** then there is no point in going any farther.\n\t\t*/\n\t\tif ((fh = Open_File(filename, READ)) == -1) {\n\t\t\treturn (-1);\n\t\t}\n\n\t\t//printf(\"Before Get Free Handle!\\n\");\n\t\t/*\n\t\t** Reserve a handle so that we can fill in the sample tracker\n\t\t** with the needed information.  If we dont get valid handle then\n\t\t** we might as well give up.\n\t\t*/\n\t\tif ((unsigned)(handle = Get_Free_Sample_Handle(0xFF)) >= LockedData.MaxSamples) {\n\t\t\treturn(-1);\n\t\t}\n\n\t\t/*\n\t\t** Now lets get a pointer to the proper sample handler and start\n\t\t** our manipulations.\n\t\t*/ \n\t\tst\t\t\t\t\t\t\t= &LockedData.SampleTracker[handle];\n\t\tst->IsScore\t\t\t\t= TRUE;\n\t\tst->FilePending\t\t= 0;\n\t\tst->FilePendingSize\t= 0;\n\t\tst->Loading\t\t\t\t= real_time_start;\n\t\tst->Volume\t\t\t\t= volume;\n\t\tst->FileHandle\t\t\t= fh;\n\t\t/*\n\t\t** Now that we have setup our initial data properly, let load up\n\t\t** the beginning of the sample we intend to stream.\n\t\t*/\n\t\t//printf(\"Before Preload!\\n\");\n\t\tFile_Stream_Preload(handle);\n\t}\n\treturn (handle);\n}\n\n/***********************************************************************************************\n * Sound_Callback -- Audio driver callback function.                                           *\n *                                                                                             *\n *    Maintains the audio buffers.  This routine must be called at least                       *\n *    11 times per second or else audio glitches will occur.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If this routine is not called often enough then audio                           *\n *             glitches will occur.                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID cdecl __saveregs __loadds Sound_Callback(VOID)\n{\n\tint\t\t\t\t\tindex;\n\tSampleTrackerType\t*st;\n\n\tif (LockedData.DigiHandle != -1) {\n\t\tst = &LockedData.SampleTracker[0];\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\t\tif (st->Loading) {\n\t\t\t\tFile_Stream_Preload(index);\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t**\tGeneral service routine to handle moving small blocks from the\n\t\t\t\t**\tsource into the low RAM staging buffers.\n\t\t\t\t*/\n\n\t\t\t\tif (st->Active) {\n\t\t\t\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSpecial check to see if the sample is a fading one AND\n\t\t\t\t\t**\tit has faded to silence, then stop it here.\n\t\t\t\t\t*/\n\t\t\t\t\tif (st->Reducer && !st->Volume) {\n\t\t\t\t\t\tStop_Sample(index);\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tFill the queuebuffer if it is currently empty\n\t\t\t\t\t\t**\tand there is a callback function defined to fill it.\n\t\t\t\t\t\t**\n\t\t\t\t\t\t** PWG/CDY & CO: We should be down by at least two blocks\n\t\t\t\t\t\t**\t\t\t\t\t  before we bother with this\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif ((!st->QueueBuffer || \n\t\t\t\t\t\t\t(st->FileHandle != ERROR && st->FilePending < LockedData.StreamBufferCount-3)) && \n\t\t\t\t\t\t\tst->Callback) {\n\n\t\t\t\t\t\t\tif (!st->Callback(index, &st->Odd, &st->QueueBuffer, &st->QueueSize)) {\n\t\t\t\t\t\t\t\tst->Callback = NULL;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThis catches the case where a streaming sample gets\n\t\t\t\t\t**\taborted prematurely because of failure to call the\n\t\t\t\t\t**\tcallback function frequently enough.  In this case, the\n\t\t\t\t\t**\tsample will be flagged as inactive, but the file handle\n\t\t\t\t\t**\twill not have been closed.\n\t\t\t\t\t*/\n\t\t\t\t\tif (st->FileHandle != ERROR) {\n\t\t\t\t\t\tClose_File(st->FileHandle);\n\t\t\t\t\t\tst->FileHandle = ERROR;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAdvance to the next sample control structure.\n\t\t\t*/\n\t\t\tst++;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Load_Sample -- Loads a digitized sample into RAM.                                           *\n *                                                                                             *\n *    This routine loads a digitized sample into RAM.                                          *\n *                                                                                             *\n * INPUT:   filename -- Name of the sound file to load.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the loaded sound file.  This pointer                     *\n *          is passed to Play_Sample when playback is desired.                                 *\n *                                                                                             *\n * WARNINGS:   If there is insufficient memory to load the sample, then                        *\n *             NULL will be returned.                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *   01/06/1994 JLB : HMI version.                                                             *\n *=============================================================================================*/\nVOID *Load_Sample(char const *filename)\n{\n\tvoid *buffer = NULL;\n\tlong\tsize;\n\tint\tfh;\n\n\tif (LockedData.DigiHandle == -1 || !filename || !Find_File(filename)) {\n\t\treturn (NULL);\n\t}\n\n\tfh = Open_File(filename, READ);\n\tif (fh != ERROR) {\n\t\tsize = File_Size(fh)+sizeof(AUDHeaderType);\n\t\tbuffer = Alloc(size, MEM_NORMAL);\n\n\t\tif (buffer) {\n\t\t\tSample_Read(fh, buffer, size);\n\t\t}\n\t\tClose_File(fh);\n\t\tMisc = size;\n\t}\n\treturn(buffer);\n}\n\n\n/***********************************************************************************************\n * Load_Sample_Into_Buffer -- Loads a digitized sample into a buffer.                          *\n *                                                                                             *\n *    This routine is used to load a digitized sample into a buffer                            *\n *    provided by the programmer.  This buffer can be in XMS or EMS.                           *\n *                                                                                             *\n * INPUT:   filename -- The filename to load.                                                  *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer to load into.                                    *\n *                                                                                             *\n *          size     -- The size of the buffer to load into.                                   *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually used in the buffer.                           *\n *                                                                                             *\n * WARNINGS:   This routine will not overflow the buffer provided.  This                       *\n *             means that the buffer must be big enough to hold the data                       *\n *             or else the sound will be cut short.                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Load_Sample_Into_Buffer(char const *filename, void *buffer, long size)\n{\n\tint\tfh;\n\n\t/*\n\t**\tVerify legality of parameters.\n\t*/\n\tif (!buffer || !size || LockedData.DigiHandle == -1 || !filename || !Find_File(filename)) {\n\t\treturn (NULL);\n\t}\n\n\tfh = Open_File(filename, READ);\n\tif (fh != ERROR) {\n\t\tsize = Sample_Read(fh, buffer, size);\n\t\tClose_File(fh);\n\t} else {\n\t\treturn(0);\n\t}\n\treturn(size);\n}\n\n\n/***********************************************************************************************\n * Sample_Read -- Reads sample data from an openned file.                                      *\n *                                                                                             *\n *    This routine reads a sample file.  It is presumed that the file is                       *\n *    already positioned at the start of the sample.  From this, it can                        *\n *    determine if it is a VOC or raw data and proceed accordingly.                            *\n *                                                                                             *\n * INPUT:   fh       -- File handle of already openned sample file.                            *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer to load data into.                               *\n *                                                                                             *\n *          size     -- The size of the buffer.                                                *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually used in the buffer.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Sample_Read(int fh, void *buffer, long size)\n{\n\n\tAUDHeaderType\tRawHeader;\n\tVOID\t*outbuffer;\t\t\t\t\t// Pointer to start of raw data.\n\tlong\tactual_bytes_read;\t\t// Actual bytes read in, including header\n\n/*\n\tConversion formula for TCrate and Hz rate.\n\n\tTC = 256 - 1m/rate\n\trate = 1m / (256-TC)\n*/\n\n\tif (!buffer || fh == ERROR || size <= sizeof(RawHeader)) return(NULL);\n\tsize -= sizeof(RawHeader);\n\toutbuffer = Add_Long_To_Pointer(buffer, sizeof(RawHeader));\n\n\t\t\t\tactual_bytes_read = \n\t\t\t\t\tRead_File(fh, &RawHeader, sizeof(RawHeader));\n\n\t\t\t\tactual_bytes_read +=\n\t\t\t\t\tRead_File(fh, outbuffer, MIN(size, RawHeader.Size));\n\n\n\tMem_Copy(&RawHeader, buffer, sizeof(RawHeader));\n\treturn(actual_bytes_read);\n}\n\n\n/***********************************************************************************************\n * Free_Sample -- Frees a previously loaded digitized sample.                                  *\n *                                                                                             *\n *    Use this routine to free the memory allocated by a previous call to                      *\n *    Load_Sample.                                                                             *\n *                                                                                             *\n * INPUT:   sample   -- Pointer to the sample to be freed.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID Free_Sample(VOID const *sample)\n{\n\tif (sample) Free((void *)sample);\n}\n\nBOOL Sound_Init(int sfx, int score, int sample, RateType rate, int bits_per_sample, int max_samples, int reverse_channels)\n{\n\treturn Audio_Init(sample, -1, -1, -1, rate, bits_per_sample, max_samples, reverse_channels);\n}\n\nBOOL Audio_Init(int sample, int address, int inter, int dma, RateType rate, int bits_per_sample, int max_samples, int reverse_channels)\n{\n\tint\t\t\t\t\terror;\t// Function error return code.\n\tunsigned int \t\tport;\n\tint\t\t\t\t\tindex;\n\t_SOS_INIT_DRIVER\tinit;\t\t// Driver init structure.\n\n\tInit_Locked_Data();\n\tmemset(&LockedData.SampleTracker[0], 0, sizeof(LockedData.SampleTracker));\n\tLockedData.Rate = rate;\n\n\tBits_Per_Sample = bits_per_sample;\n\n\tsosTIMERInitSystem(_TIMER_DOS_RATE, _SOS_DEBUG_NORMAL);\n\n\tif (TimerSystemOn) {\n\t\tsosTIMERRegisterEvent(60, &Timer_Interrupt_Func, &SystemTimer);\n\t\tTickCount.Start();\n\t} else\n\t\tsosTIMERRegisterEvent(60, &HMI_TimerCallback, &SystemTimer);\n\n\t/*\n\t**\tSpecial code to handle the HMI problem with running under Windows.\n\t*/\n\tif (/*Operating_System() != OS_DOS ||*/ sample == SAMPLE_NONE) {\n\t\treturn(FALSE);\n\t}\n\n\twhile (sample) {\n\n#ifdef SIMPLE_HMI_INIT\n\n\t\tif (address == -1 || inter == -1 || dma == -1) {\n\t\t\terror = sosDIGIDetectInit((LPSTR)NULL);\n\t\t\tif (error) {\n\t\t\t\tprintf(\"Cannot initialize detection system (%d).\\n\", error);\n\t\t\t\tGet_Key();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\terror = sosDIGIDetectFindHardware(sample, &DigiCaps, &port);\n\t\t\tif (error) {\n\t\t\t\tprintf(\"Cannot find sound card specified.\\n\");\n\t\t\t\tGet_Key();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Handle the override for Address, Interrupt, and DMA settings.\n\t\t\t*/\n\t\t\terror = sosDIGIDetectGetSettings(&DigiHardware);\n\t\t\tsosDIGIDetectUnInit();\n\t\t\tif (error) {\n\t\t\t\tprintf(\"Cannot get sound card settings.\\n\");\n\t\t\t\tGet_Key();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t \tDigiHardware.wPort = address;\n\t\t\tDigiHardware.wIRQ = inter;\n\t\t\tDigiHardware.wDMA = dma;\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tInitialize the digi-system and driver.\n\t\t*/\n\t\tsosDIGIInitSystem((LPSTR)NULL, _SOS_DEBUG_NORMAL);\n\t\tinit.wBufferSize\t\t= 1024*8;\t\t\t\t// Specify the DMA buf size\n\t\tinit.lpBuffer\t\t\t= (LPSTR)NULL;\n\t\tinit.wAllocateBuffer = TRUE;\n\t\tinit.wSampleRate\t\t= rate;\t\t\t\t\t// Sample playback rate.\n\t\tinit.wParam\t\t\t\t= 19;\n\t\tinit.dwParam\t\t\t= 0;\n\t\tinit.lpFillHandler\t= NULL;\n\t\tinit.lpDriverMemory\t= (LPSTR)NULL;\n\t\tinit.lpTimerMemory\t= (LPSTR)NULL;\n\t\tinit.wTimerID\t\t\t= _SOS_NORMAL_TIMER;\n \t\t\n\t\terror = 0;\n\t\terror = sosDIGIInitDriver( (int)sample, &DigiHardware, &init, &LockedData.DigiHandle);\n\t\tif (error) {\n\t\t\tprintf(\"Unable to initialize the sound driver.\\n\");\n\t\t\tGet_Key();\n\t\t\tbreak;\n\t\t}\n\n\t\terror = 0;\n\n\n\t\tif (sample >= _GUS_8_MONO && sample <= _GUS_16_ST) {\n\t\t\terror = sosTIMERRegisterEvent(120, init.lpFillHandler, &DigiTimer);\n\t\t} else {\n\t\t\terror = sosTIMERRegisterEvent(60, init.lpFillHandler, &DigiTimer);\n\t\t}\n\t\tif (error) {\n\t\t\tprintf(\"Unable to regiser the fill handler.\\n\");\n\t\t\tGet_Key();\n\t\t\tsosDIGIUnInitDriver(LockedData.DigiHandle, TRUE, TRUE);\n\t\t\tLockedData.DigiHandle = -1;\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tAllocate a decompression buffer equal to the size of a SONARC frame\n\t\t**\tblock.\n\t\t*/\n\t\tLockedData.UncompBuffer = Alloc(LARGEST_SONARC_BLOCK + 50, (MemoryFlagType)(MEM_NORMAL|MEM_CLEAR|MEM_LOCK));\n\t\tLockedData.MaxSamples\t= max_samples;\n\n\t\t/*\n\t\t**\tAllocate private staging buffers for double buffering sound into HMI\n\t\t**\tdriver.\n\t\t*/\n\t\tDigiBuffer = Alloc(2048+(((LONG)LockedData.MaxSamples*2) * (LONG)(SFX_MINI_STAGE_BUFFER_SIZE+SONARC_MARGIN)), (MemoryFlagType)(MEM_NORMAL|MEM_CLEAR|MEM_LOCK));\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\t\tLockedData.SampleTracker[index].Buffer[0] = Add_Long_To_Pointer(DigiBuffer, ((LONG)index*2) * (LONG)(SFX_MINI_STAGE_BUFFER_SIZE+SONARC_MARGIN));\n\t\t\tLockedData.SampleTracker[index].Buffer[1] = Add_Long_To_Pointer(DigiBuffer, ((LONG)index*2+1) * (LONG)(SFX_MINI_STAGE_BUFFER_SIZE+SONARC_MARGIN));\n\t\t\tLockedData.SampleTracker[index].FileHandle = ERROR;\n\t\t\tLockedData.SampleTracker[index].QueueBuffer = NULL;\n\t\t}\n\t\terror = sosTIMERRegisterEvent(MAINTENANCE_RATE, (void (__far *)(void))maintenance_callback, &MaintainTimer);\n\t\tif (error) {\n\t\t\tprintf(\"Unable to initialize the maintenance callback.\\n\");\n\t\t\tGet_Key();\n\t\t\tsosTIMERRemoveEvent(DigiTimer);\n\t\t\tsosDIGIUnInitDriver(LockedData.DigiHandle, TRUE, TRUE);\n\t\t\tLockedData.DigiHandle = -1;\n\t\t\tbreak;\n\t\t}\n\t\tSoundType = (SFX_Type)sample;\n\t\tSampleType = (Sample_Type)sample;\n\t\tReverseChannels = reverse_channels;\n\n\t\tbreak;\n\t}\n\n\treturn(TRUE);\n}\n\n\n/***********************************************************************************************\n * Sound_End -- Uninitializes the sound driver.                                                *\n *                                                                                             *\n *    This routine will uninitialize the sound driver (if any was                              *\n *    installed).  This routine must be called at program termination                          *\n *    time.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/23/1991 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID Sound_End(VOID)\n{\n\n\tif (LockedData.DigiHandle != -1) {\n\t\tsosTIMERRemoveEvent(DigiTimer);\n\t\tsosTIMERRemoveEvent(MaintainTimer);\n\t\tsosDIGIUnInitDriver(LockedData.DigiHandle, TRUE, TRUE);\n\t\tsosDIGIUnInitSystem();\n\t\tLockedData.DigiHandle = -1;\n\t}\n\tif (DigiBuffer) {\n\t\tFree(DigiBuffer);\n\t\tDigiBuffer = 0;\n\t}\n\tif (LockedData.UncompBuffer) {\n\t\tFree(LockedData.UncompBuffer);\n\t\tLockedData.UncompBuffer = 0;\n\t}\n\tsosTIMERRemoveEvent(SystemTimer);\n\tsosTIMERUnInitSystem(0);\n\tUnlock_Locked_Data();\n}\n\n\n\n\n/***********************************************************************************************\n * Stop_Sample -- Stops any currently playing sampled sound.                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID Stop_Sample(int handle)\n{\n\tif (LockedData.DigiHandle != -1 && (unsigned)handle < LockedData.MaxSamples) {\n\n\n\t\tif (LockedData.SampleTracker[handle].Active || LockedData.SampleTracker[handle].Loading) {\n\n\t\t\t\n\t\t\tLockedData.SampleTracker[handle].Active = FALSE;\n\t\t\tif (!LockedData.SampleTracker[handle].IsScore) {\n\t\t\t\tDPMI_Unlock(LockedData.SampleTracker[handle].Original, LockedData.SampleTracker[handle].OriginalSize);\n\t\t\t\tLockedData.SampleTracker[handle].Original = NULL;\n\t\t\t}\n\t\t\tLockedData.SampleTracker[handle].Priority = 0;\n\n\t\t\t/*\n\t\t\t**\tStop the sample if it is playing.\n\t\t\t*/\n\t\t\tif (!LockedData.SampleTracker[handle].Loading) {\n\t\t\t\tsosDIGIStopSample(LockedData.DigiHandle, LockedData.SampleTracker[handle].Handle);\n\t\t\t}\n\t\t\tLockedData.SampleTracker[handle].Loading = FALSE;\n\n\t\t\t/*\n\t\t\t**\tIf this is a streaming sample, then close the source file.\n\t\t\t*/\n\t\t\tif (LockedData.SampleTracker[handle].FileHandle != ERROR) {\n\t\t\t\tClose_File(LockedData.SampleTracker[handle].FileHandle);\n\t\t\t\tLockedData.SampleTracker[handle].FileHandle = ERROR;\n\t\t\t}\n\n\t\t\tLockedData.SampleTracker[handle].QueueBuffer = NULL;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Sample_Status -- Queries the current playing sample status (if any).                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nBOOL Sample_Status(int handle)\n{\n\t/*\n\t** If its an invalid handle or we do not have a sound driver then\n\t** the sample in question is not playing.\n\t*/\n\tif (LockedData.DigiHandle == -1 || (unsigned)handle >= LockedData.MaxSamples) return(FALSE);\n\t/*\n\t** If the sample is loading, then for all intents and purposes the\n\t** sample is playing.\n\t*/\n\tif (LockedData.SampleTracker[handle].Loading) return(TRUE);\n\t/* \n\t** If the sample is not active, then it is not playing\n\t*/\n\tif (!LockedData.SampleTracker[handle].Active) return(FALSE);\n\t/*\n\t** If we made it this far, then the Sample is still playing if sos says\n\t** that it is.\n\t*/\n\treturn (!sosDIGISampleDone(LockedData.DigiHandle, LockedData.SampleTracker[handle].Handle));\n}\n\n\nBOOL Is_Sample_Playing(void const * sample)\n{\n\tint index;\n\n\tif (!sample) return FALSE;\n\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\tif (LockedData.SampleTracker[index].Original == sample && Sample_Status(index)) {\n\t\t\treturn (TRUE);\n\t\t}\n\t}\n\treturn (FALSE);\n}\n\n\nVOID Stop_Sample_Playing(void const * sample)\n{\n\tint index;\n\n\tif (sample) {\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\t\tif (LockedData.SampleTracker[index].Original == sample) {\n\t\t\t\tStop_Sample(index);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\nint Get_Free_Sample_Handle(int priority)\n{\n\tint\tid;\n\n\t/*\n\t**\tFind a free SFX holding buffer slot.\n\t*/\n\tfor (id = LockedData.MaxSamples - 1; id >= 0; id--) {\n\t\tif (!LockedData.SampleTracker[id].Active && !LockedData.SampleTracker[id].Loading) {\n\t\t\tif (!StartingFileStream && LockedData.SampleTracker[id].IsScore) {\n\t\t\t\tStartingFileStream = TRUE;\t// Ensures only one channel is kept free for scores.\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (id < 0) {\n\t\tfor (id = 0; id < LockedData.MaxSamples; id++) {\n\t\t\tif (LockedData.SampleTracker[id].Priority <= priority) break;\n\t\t}\n\t\tif (id == LockedData.MaxSamples) {\n\t\t\treturn(-1);\t\t// Cannot play!\n\t\t}\n\t\tStop_Sample(id);\t\t\t\t\t\t\t// This sample gets clobbered.\n\t}\n\tif (id == -1) {\n\t\treturn -1;\n\t}\n\tif (LockedData.SampleTracker[id].FileHandle != ERROR) {\n\t\tClose_File(LockedData.SampleTracker[id].FileHandle);\n\t\tLockedData.SampleTracker[id].FileHandle = ERROR;\n\t}\n\tif (LockedData.SampleTracker[id].Original && !LockedData.SampleTracker[id].IsScore) {\n\t\tDPMI_Unlock(LockedData.SampleTracker[id].Original, LockedData.SampleTracker[id].OriginalSize);\n\t\tLockedData.SampleTracker[id].Original = NULL;\n\t}\n\tLockedData.SampleTracker[id].IsScore = FALSE;\n\treturn(id);\n}\n\nint Play_Sample(void const *sample, int priority, int volume, signed short panloc)\n{\n\treturn(Play_Sample_Handle(sample, priority, volume, panloc, Get_Free_Sample_Handle(priority)));\n}\n/***********************************************************************************************\n * Play_Sample_Vol -- Plays a digitized sample.                                                *\n *                                                                                             *\n *    Use this routine to play a previously loaded digitized sample.                           *\n *                                                                                             *\n * INPUT:   sample   -- Sample pointer as returned from Load_Sample.                           *\n *                                                                                             *\n *          volume   -- The volume to play (0..255 with 255=loudest).                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *   05/24/1992 JLB : Volume support -- Soundblaster Pro                                       *\n *   04/22/1994 JLB : Multiple sample playback rates.                                          *\n *=============================================================================================*/\nint Play_Sample_Handle(void const *sample, int priority, int volume, signed short panloc, int id)\n{\n\tAUDHeaderType\t\t\tRawHeader;\n\t_SOS_START_SAMPLE \tstart;\n\tSampleTrackerType\t\t*st=NULL;\t// Working pointer to sample tracker structure.\n\n\tif (!sample || LockedData.DigiHandle == -1) {\n\t\treturn(-1);\n\t}\n\n\tif (id == -1) {\n\t\treturn -1;\n\t}\n\n\t/*\n\t**\tFetch the control bytes from the start of the sample data.\n\t*/\n\tMem_Copy((void *)sample, (void *)&RawHeader, sizeof(RawHeader));\n\n\t/*\n\t**\tPrepare the sample tracker structure for processing of this\n\t**\tsample.  Fill the structure with data that can be determined\n\t**\tbefore the sample is started.\n\t*/\n\tst = &LockedData.SampleTracker[id];\n\tst->Compression\t= (SCompressType) ((unsigned char)RawHeader.Compression);\n\tst->Original\t\t= sample;\n\tst->OriginalSize\t= RawHeader.Size + sizeof(RawHeader);\n\tif (!st->IsScore) {\n\t\tDPMI_Lock(st->Original, st->OriginalSize);\n\t}\n\tst->Priority\t\t= priority;\n\tst->DontTouch\t\t= FALSE;\n\tst->Odd\t\t\t\t= 0;\n\tst->Reducer\t\t\t= 0;\n\tst->Restart\t\t\t= FALSE;\n\tst->QueueBuffer\t= NULL;\n\tst->QueueSize\t\t= NULL;\n\tst->TrailerLen \t= 0;\n\tst->Remainder\t\t= RawHeader.Size;\n\tst->Source\t\t\t= Add_Long_To_Pointer((void *)sample, sizeof(RawHeader));\n\tst->Service\t\t\t= FALSE;\n\n\t/*\n \t** If the code in question using HMI based compression then we need\n\t** to set up for uncompressing it.\n\t*/\n\tif (st->Compression == SCOMP_SOS) {\n\t\tst->sosinfo.wChannels\t = (RawHeader.Flags & AUD_FLAG_STEREO) ? 2  : 1;\n\t\tst->sosinfo.wBitSize\t\t = (RawHeader.Flags & AUD_FLAG_16BIT)  ? 16 : 8;\n\t\tst->sosinfo.dwCompSize\t = RawHeader.Size;\n   \tst->sosinfo.dwUnCompSize = RawHeader.Size * ( st->sosinfo.wBitSize / 4 );\n\t   sosCODECInitStream(&st->sosinfo);\n\t}\n\n\t/*\n\t**\tFill in one or both staging buffers if possible.\n\t*/\n\t_disable();\n//\tDisable_Timer_Interrupt();\n\tif (SFX_MINI_STAGE_BUFFER_SIZE == \n\t\t\t\t\tSample_Copy(st,\n\t\t\t\t\t\t\t\t\t&st->Source, \n\t\t\t\t\t\t\t\t\t&st->Remainder, \n\t\t\t\t\t\t\t\t\t&st->QueueBuffer, \n\t\t\t\t\t\t\t\t\t&st->QueueSize, \n\t\t\t\t\t\t\t\t\tst->Buffer[0], \n\t\t\t\t\t\t\t\t\tSFX_MINI_STAGE_BUFFER_SIZE, \n\t\t\t\t\t\t\t\t\tst->Compression, \n\t\t\t\t\t\t\t\t\t&st->Trailer[0], \n\t\t\t\t\t\t\t\t\t&st->TrailerLen)) {\n\n\t\tst->DataLength = Sample_Copy(st,\n\t\t\t\t\t\t\t\t\t\t&st->Source, \n\t\t\t\t\t\t\t\t\t\t&st->Remainder, \n\t\t\t\t\t\t\t\t\t\t&st->QueueBuffer, \n\t\t\t\t\t\t\t\t\t\t&st->QueueSize, \n\t\t\t\t\t\t\t\t\t\tst->Buffer[1], \n\t\t\t\t\t\t\t\t\t\tSFX_MINI_STAGE_BUFFER_SIZE, \n\t\t\t\t\t\t\t\t\t\tst->Compression, \n\t\t\t\t\t\t\t\t\t\t&st->Trailer[0], \n\t\t\t\t\t\t\t\t\t\t&st->TrailerLen);\n\t\tst->Index = 1;\n\t} else {\n\t\tst->Index = 0;\n\t\tst->DataLength = 0;\n\t}\n\t_enable();\n//\tEnable_Timer_Interrupt();\n\n\t/*\n\t**\tFill in the HMI start sample structure.\n\t*/\n\tmemset(&start, 0, sizeof(start));\n\n\tstart.lpSamplePtr = (LPSTR)st->Buffer[0];\n\tif (st->Index == 1) {\n\t\tstart.dwSampleSize = SFX_MINI_STAGE_BUFFER_SIZE-1;\n\t} else {\n\t\tstart.dwSampleSize = st->DataLength-1;\n\t}\n\tstart.lpCallback\t= (void cdecl (far *)(unsigned int, unsigned int, unsigned int))&DigiCallback;\n\tstart.wLoopCount\t= 0;\n\tstart.wSampleID\t= id;\n\n\t/*\n\t**\tAdjust pitch shifting as necessary so that lower playback\n\t**\tsamples can be supported.\n\t*/\n\tif (RawHeader.Rate != LockedData.Rate) {\n\t\tldiv_t\tresult;\n\n\t\tresult\t\t\t\t\t\t= ldiv((long)RawHeader.Rate, LockedData.Rate);\n\t\tstart.dwSamplePitchAdd\t= (long)MAKE_LONG((short)result.quot, (short)(((long)result.rem * 0x10000L) / LockedData.Rate));\n\t\tstart.wSampleFlags \t  |= _PITCH_SHIFT;\n\t}\n\n\t/*\n\t**\tSample translation flag.\n\t*/\n\n\tif (RawHeader.Flags & AUD_FLAG_16BIT) {\n\t\tif (Bits_Per_Sample == 8) {\n\t\t\tstart.wSampleFlags \t  |= _TRANSLATE16TO8;\n\t\t}\n\t} else {\n\t\tif (Bits_Per_Sample == 16) {\n\t\t\tstart.wSampleFlags \t  |= _TRANSLATE8TO16;\n\t\t}\n\t}\n\n\t/*\n\t**\tSample stereo flag.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_STEREO) {\n\t\tstart.wChannel \t\t\t= _INTERLEAVED;\n\t\tstart.wSampleFlags \t  |= _STEREOTOMONO;\n\t} else {\n\t\tstart.wChannel \t\t\t= _CENTER_CHANNEL;\n\t}\n\n\t/*\n\t**\tSample volume control flags.  Always give it volume control because\n\t**\tif not, then future volume control is either ignored or stops the\n\t**\tsample.\n\t*/\n\tst->Volume \t\t\t\t\t\t= volume << 7;\n\tstart.wVolume\t\t\t\t\t= (st->Volume >> 8) * LockedData.SoundVolume;\n\tstart.wSampleFlags  \t\t  |= _VOLUME;\n\t\n\t/*\n\t** If we have defined a panning location for the sound driver than\n\t** take care of it here.  Panning will only work with a stereo driver\n\t** and only if the sample is played _CENTER_CHANNEL.\n\t*/\n\tif ((panloc != 0x0) && (!(RawHeader.Flags & AUD_FLAG_STEREO))) {\n\t\tstart.wChannel \t\t\t= _CENTER_CHANNEL;\n\t\tpanloc \t\t\t\t\t\t= ((ReverseChannels) ? ((-panloc) + 0x8000) : ((panloc) + 0x8000));\n\t\tstart.wSampleFlags \t  |= _PANNING;\n\t\tstart.wSamplePanLocation= panloc;\n\t}\n\n\tst->Stereo \t= start.wChannel;\n\tst->Pitch \t= start.dwSamplePitchAdd;\n\tst->Flags \t= start.wSampleFlags;\n\n\t/*\n\t**\tStart the sample playing now.\n\t*/\n\t_disable();\t\t// NEW\n//\tDisable_Timer_Interrupt();\n\tst->Handle = sosDIGIStartSample(LockedData.DigiHandle, &start);\n\tif (st->Handle == -1) {\n\t\tid = -1;\n\t} else {\n\n\t\t/*\n\t\t**\tFill in the sample tracker structure with those values that are\n\t\t**\tdetermined AFTER the sample starts.\n\t\t*/\n\t\tst->Active = TRUE;\n\t}\n\t_enable();\t\t\t// NEW\n//\tEnable_Timer_Interrupt();\n\n\treturn(id);\n}\n\n\nint Set_Sound_Vol(int volume)\n{\n\tint old;\n\told = LockedData.SoundVolume;\n\tLockedData.SoundVolume = volume & 0xFF;\n\treturn(old);\n}\n\n\nint Set_Score_Vol(int volume)\n{\n\tint old;\n\told = LockedData.ScoreVolume;\n\tLockedData.ScoreVolume = volume & 0xFF;\n\treturn(old);\n}\n\n\nVOID Fade_Sample(int handle, int ticks)\n{\n\tif (Sample_Status(handle)) {\n\t\tif (!ticks || LockedData.SampleTracker[handle].Loading) {\n\t\t\tStop_Sample(handle);\n\t\t} else {\n\t\t\tSampleTrackerType * st;\n\n\t\t\tst = &LockedData.SampleTracker[handle];\n\t\t\tst->Reducer = (st->Volume / ticks)+1;\n\t\t}\n\t}\n}\nint Get_Digi_Handle(void)\n{\n\treturn(LockedData.DigiHandle);\n}\n\n/***************************************************************************\n * SAMPLE_LENGTH -- returns length of a sample in ticks                    *\n *                                                                         *\n * INPUT:\t\tvoid const *sample - pointer to the sample to get length    *\n *\t\t\t\t\t\t\t\t\t\t\t   of.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tlong   \t\t\t\t - length of the sample in ticks (60/sec) *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/05/1995 PWG : Created.                                             *\n *=========================================================================*/\nlong Sample_Length(void const *sample)\n{\n\tAUDHeaderType\t\t\tRawHeader;\n\n\tif (!sample) return(0);\n\n\tMem_Copy((void *)sample, (void *)&RawHeader, sizeof(RawHeader));\n\n\tlong time = RawHeader.UncompSize;\n\n\t/*\n\t** If the sample is a 16 bit sample, then it will take only half\n\t** as long to play.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_16BIT) {\n\t\ttime >>= 1;\n\t}\n\n\t/*\n\t** If the sample is a stereo sample, then it will take only half\n\t** as long to play.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_STEREO) {\n\t\ttime >>= 1;\n\t}\n\n\tif (RawHeader.Rate/60) {\n\t\ttime /= (RawHeader.Rate/60);\n\t}\n\treturn(time);\n}\n"
  },
  {
    "path": "WWFLAT32/AUDIO/SOUNDIO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Id: soundio.cpp 1.41 1994/06/20 15:01:39 joe_bostic Exp $ */\n/***********************************************************************************************\n **             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             **\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Sound Library                                                *\n *                                                                                             *\n *                    File Name : SOUND.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 22, 1991                                                *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   File_Callback -- called to fill queue buffer for streaming sample     \t\t\t\t\t\t  *\n *   Stream_Sample_Volume -- generic streaming sample playback init                            *\n *   Stream_Sample -- generic streaming sample playback init                                   *\n *   File_Stream_Sample -- Streams a sample directly from a file.                              *\n *   File_Stream_Preload -- Handles initial proload of a streaming samples                     *\n *   File_Stream_Sample_Volume -- Streams a sample directly from a file w/volume.              *\n *   Sound_Callback -- Audio driver callback function.                                         *\n *   Load_Sample -- Loads a digitized sample into RAM.                                         *\n *   Load_Sample_Into_Buffer -- Loads a digitized sample into a buffer.                        *\n *   Free_Sample -- Frees a previously loaded digitized sample.                                *\n *   Sound_End -- Uninitializes the sound driver.                                              *\n *   Stop_Sample -- Stops any currently playing sampled sound.                                 *\n *   Sample_Status -- Queries the current playing sample status (if any).                      *\n *   Sample_Length -- returns length of a sample in ticks                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#pragma pack(4)\n#include\t\"soundint.h\"\n#include <dos.h>\n#include <mem.h>\n#include <stdio.h>\n#include <string.h>\n#include\t<direct.h>\n#include\t<stdlib.h>\n#include\t<wwmem.h>\n#include\t<keyboard.h>\n#include\t<file.h>\n#include\t<i86.h>\n#include <timer.h>\n#pragma pack(1)\n#include \"audio.h\"\n#pragma pack(4)\n\n\n//int Mono_Printf(char const *string, ...);\n#include\t<mono.h>\n\n/*\n**\tIf this is defined, then the streaming audio buffer will be filled\n**\tto maximum whenever filling is to occur. If undefined, it will fill\n**\tthe streaming buffer in smaller chunks.\n*/\n#define\tSIMPLE_FILLING\n\n/*\n**\tThis define (if present) enables the simple HMI hardware initialization process.\n**\tThe process does not do auto detection, but rather takes the value directly from\n**\tthe setup program and uses that as the sound card number.  The only \"detection\" it\n**\tdoes is to recognized the presence of the card and fetch its settings.\n*/\n#define\tSIMPLE_HMI_INIT\n\n\n/*\n**\tThis is the rate that the maintenance callback gets called.\n*/\n#define\tMAINTENANCE_RATE\t\t\t60\n\n/*\n**\tSize of the temporary buffer in XMS/EMS that direct file\n**\tstreaming of sounds will allocate.\n*/\n#define\tSTREAM_BUFFER_SIZE\t\t(128L*1024L)\n\n/*\n** Define the number of \"StreamBufferSize\" blocks that are read in\n** at a minimum when the streaming sample load callback routine\n** is called.  We will IGNORE loads that are less that this in order\n** to avoid constant seeking on the CD.\n*/\n#define\tSTREAM_CUSHION_BLOCKS\t4\n\n\n/*\n**\tThis is the maximum size that a sonarc block can be.  All sonarc blocks\n**\tmust be either a multiple of this value or a binary root of this value.\n*/\n#define\tLARGEST_SONARC_BLOCK\t\t2048\n\n\n//////////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////// structs ///////////////////////////////////////\n\nstatic _SOS_CAPABILITIES\tDigiCaps;\nstatic _SOS_HARDWARE \t\tDigiHardware;\nstatic WORD \t\t\t\t\tMidiHandle = -1;\nstatic unsigned int far\t\tDigiTimer = 0;\nstatic unsigned int far\t\tMaintainTimer = 0;\nstatic unsigned int far\t\tSystemTimer = 0;\nstatic int\t\t\t\t\t\tBits_Per_Sample;\nVOID \t\t\t\t\t\t\t\t*DigiBuffer = NULL;\nstatic BOOL \t\t\t\t\tStartingFileStream = FALSE;\nshort \t\t\t\t\t\t\tStreamLowImpact = FALSE;\nMemoryFlagType \t\t\t\tStreamBufferFlag = MEM_NORMAL;\nint \t\t\t\t\t\t\t\tMisc;\nSFX_Type \t\t\t\t\t\tSoundType;\nSample_Type \t\t\t\t\tSampleType;\nint\t\t\t\t\t\t\t\tReverseChannels = FALSE;\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nstatic BOOL File_Callback(WORD id, WORD *odd, VOID **buffer, LONG *size);\nstatic int cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback)(WORD id, WORD *odd, VOID **buffer, LONG *size), int volume, int handle);\nstatic int cdecl Stream_Sample(void *buffer, long size, BOOL (*callback)(WORD id, WORD *odd, VOID **buffer, LONG *size));\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n\n/***************************************************************************\n * FILE_CALLBACK -- called to fill queue buffer for streaming sample       *\n *                                                                         *\n * This callback is called whenever the queue buffer playback has begun\t\t*\n * and another buffer is needed for queuing up.  Returns TRUE if there\t\t*\n * is more data to read from the file.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:\tWORD id\t\t\t- the sample id number                          *\n *\t\t\t\tWORD *odd\t\t- which sample buffer to put info in\t\t\t\t*\n *\t\t\t\tVOID **buffer\t- the buffer pointer to load data into\t\t\t\t*\n *\t\t\t\tLONG *size\t\t- the amount to load\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:  BOOL true if more data to load, FALSE if done loading          *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nstatic BOOL File_Callback(WORD id, WORD *odd, VOID **buffer, LONG *size)\n{\n\tSampleTrackerType\t*st;\t\t// Pointer to sample playback control struct.\n\tVOID\t\t\t\t\t*ptr;\t\t// Pointer to working portion of file buffer.\n\n\tif (id != -1) {\n\t\tst = &LockedData.SampleTracker[id];\n\t\tptr = st->FileBuffer;\n\t\tif (ptr) {\n\n\t\t\t/*\n\t\t\t**\tMove the next pending block into the primary \n\t\t\t**\tposition.  Do this only if the queue pointer is\n\t\t\t**\tnull.\n\t\t\t*/\n\t\t\tst->DontTouch = TRUE;\n\t\t\tif (!*buffer && st->FilePending) {\n\t\t\t\t*buffer = Add_Long_To_Pointer(ptr, (long)(*odd % LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t\t\t\tst->FilePending--;\n\t\t\t\t*odd = *odd + 1;\n\t\t\t\tif (!st->FilePending) {\n\t\t\t\t\t*size = st->FilePendingSize;\n\t\t\t\t} else {\n\t\t\t\t\t*size = LockedData.StreamBufferSize;\n\t\t\t\t}\n\t\t\t}\n\t\t\tst->DontTouch = FALSE;\n\t\t\tmaintenance_callback();\n\n\t\t\t/*\n\t\t\t**\tIf the file handle is still valid, then read in the next\n\t\t\t**\tblock and add it to the next pending slot available.\n\t\t\t*/\n\t\t\tif (st->FilePending <\n\t\t\t\t(StreamLowImpact ? (LockedData.StreamBufferCount>>1) : ((LockedData.StreamBufferCount-3))) && st->FileHandle != ERROR) {\n\n\n\t\t\t\tint num_empty_buffers;\n\n#ifdef SIMPLE_FILLING\n\t\t\t\tnum_empty_buffers = (LockedData.StreamBufferCount-2) - st->FilePending;\n#else\n\n\t\t\t\t//\n\t\t\t\t// num_empty_buffers will be from 1 to StreamBufferCount\n\t\t\t\t//\n\t\t\t\tif (StreamLowImpact) {\n\t\t\t\t\tnum_empty_buffers = MIN((LockedData.StreamBufferCount >> 1)+STREAM_CUSHION_BLOCKS, (LockedData.StreamBufferCount - 2) - st->FilePending);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tnum_empty_buffers = (LockedData.StreamBufferCount - 2) - st->FilePending;\n\t\t\t\t}\n#endif\n\t\t\t\t\n\n\n\t\t\t\twhile (num_empty_buffers && st->FileHandle != ERROR) {\n\t\t\t\t\tint\ttofill;\n\t\t\t\t\tlong\tpsize;\n\n\t\t\t\t\ttofill = (*odd + st->FilePending) % LockedData.StreamBufferCount;\n\n\t\t\t\t\tptr = Add_Long_To_Pointer(st->FileBuffer, (long)tofill * (long)LockedData.StreamBufferSize);\n\t\t\t\t\tpsize = Read_File(st->FileHandle, ptr, LockedData.StreamBufferSize);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf less than the requested amount of data was read, this\n\t\t\t\t\t**\tindicates that the source file is exhausted.  Flag the source\n\t\t\t\t\t**\tfile as closed so that no further reading is attempted.\n\t\t\t\t\t*/\n\t\t\t\t\tif (psize != LockedData.StreamBufferSize) {\n\t\t\t\t\t\tClose_File(st->FileHandle);\n\t\t\t\t\t\tst->FileHandle = ERROR;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf any real data went into the pending buffer, then flag\n\t\t\t\t\t**\tthat this buffer is valid.\n\t\t\t\t\t*/\n\t\t\t\t\tif (psize) {\n\t\t\t\t\t\tst->DontTouch = TRUE;\n\t\t\t\t\t\tst->FilePendingSize = psize;\n\t\t\t\t\t\tst->FilePending++;\n\t\t\t\t\t\tst->DontTouch = FALSE;\n\t\t\t\t\t\tmaintenance_callback();\n\t\t\t\t\t}\n\t\t\t\t\tnum_empty_buffers--;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAfter filling all pending buffers, check to see if the queue buffer\n\t\t\t\t**\tis empty.  If so, then assign the first available pending buffer to the\n\t\t\t\t**\tqueue.\n\t\t\t\t*/\n\t\t\t\tst->DontTouch = TRUE;\n\t\t\t\tif (!st->QueueBuffer && st->FilePending) {\n\t\t\t\t\tst->QueueBuffer = Add_Long_To_Pointer(st->FileBuffer, (long)(st->Odd%LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);\n\t\t\t\t\tst->FilePending--;\n\t\t\t\t\tst->Odd++;\n\t\t\t\t\tif (!st->FilePending) {\n\t\t\t\t\t\tst->QueueSize = st->FilePendingSize;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tst->QueueSize = LockedData.StreamBufferSize;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tst->DontTouch = FALSE;\n\t\t\t\tmaintenance_callback();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf there are no more buffers that the callback routine\n\t\t\t**\tcan slot into the primary position, then signal that\n\t\t\t**\tno furthur callbacks are needed.\n\t\t\t*/\n\t\t\tif (st->FilePending) {\n\t\t\t\treturn(TRUE);\n\t\t\t}\n\t\t}\n\t}\n\treturn(FALSE);\n}\n\n/***************************************************************************\n * STREAM_SAMPLE_VOLUME -- generic streaming sample playback init          *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nstatic int cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback)(WORD id, WORD *odd, VOID **buffer, LONG *size), int volume, int handle)\n{\n\tint\t\t\t\t\t\tplayid=-1;\t// Sample play ID.\n\tSampleTrackerType\t\t*st;\t\t\t// Working pointer to sample control structure.\n\tlong\t\t\t\t\t\toldsize;\t\t// Copy of original sound size.\n\tAUDHeaderType\t\t\theader;\n\n\tif (buffer && size && LockedData.DigiHandle != -1) {\n\n\t\t/*\n\t\t**\tStart the first section of the sound playing.\n\t\t*/\n\t\tMem_Copy(buffer, &header, sizeof(header));\n\t\toldsize = header.Size;\n\t\theader.Size = size-sizeof(header);\n\t\tMem_Copy(&header, buffer, sizeof(header));\n\t\tplayid = Play_Sample_Handle(buffer, 0xFF, volume, 0x0, handle);\n\t\theader.Size = oldsize;\n\t\tMem_Copy(&header, buffer, sizeof(header));\n\n\t\t/*\n\t\t**\tIf the sample actually started playing, then flag this\n\t\t**\tsample as a streaming type and signal for a callback\n\t\t**\tto occur.\n\t\t*/\n\t\tif (playid != -1) {\n\t\t\tst = &LockedData.SampleTracker[playid];\n\n\t\t\tst->Callback = callback;\n\t\t\tst->Odd = 0;\n\t\t}\n\t}\n\treturn (playid);\n}\n\n/***************************************************************************\n * STREAM_SAMPLE -- generic streaming sample playback init          \t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nstatic int cdecl Stream_Sample(void *buffer, long size, BOOL (*callback)(WORD id, WORD *odd, VOID **buffer, LONG *size), int handle)\n{\n\treturn Stream_Sample_Vol(buffer, size, callback, 0xFF, handle);\n}\n\n\n\n/***********************************************************************************************\n * File_Stream_Sample -- Streams a sample directly from a file.                                *\n *                                                                                             *\n *    This will take the file specified and play it directly from disk.                        *\n *    It performs this by allocating a temporary buffer in XMS/EMS and                         *\n *    then keeping this buffer filled by the Sound_Callback() routine.                         *\n *                                                                                             *\n * INPUT:   filename -- The name of the file to play.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the handle to the sound -- just like Play_Sample().                        *\n *                                                                                             *\n * WARNINGS:   The temporary buffer is allocated when this routine is                          *\n *             called and then freed when the sound is finished.  Keep                         *\n *             this in mind.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint File_Stream_Sample(char const *filename, BOOL real_time_start)\n{\n\treturn File_Stream_Sample_Vol(filename, 0xFF, real_time_start);\n}\n\n/***************************************************************************\n * FILE_STREAM_PRELOAD -- Handles initial proload of streaming samples     *\n *                                                                         *\n * This function is called before a sample which streams from disk is      *\n * started.  It can be called to either fill the buffer in small chunks\t\t*\n * from the call back routine or to fill the entire buffer at once.  This\t*\n * is wholely dependant on whether the Loading bit is set within the \t\t*\n * sample tracker.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:\t\tLockedData.SampleTracker * to the header which tracks this samples     *\n *\t\t\t\t\t\t\t\t\t\t processing.\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/05/1995 PWG : Created.                                             *\n *=========================================================================*/\n\nvoid File_Stream_Preload(int handle)\n{\n\tSampleTrackerType\t*st\t= &LockedData.SampleTracker[handle];\n\tint\tfh\t\t\t\t\t\t= st->FileHandle;\n\tint \tmaxnum\t\t\t\t= (LockedData.StreamBufferCount >> 1) + STREAM_CUSHION_BLOCKS;\n\tvoid \t*buffer\t\t\t\t= st->FileBuffer;\n\tint\tnum;\n\n\t/*\n\t** Figure just how much we need to load.  If we are doing the load in progress\n\t** then we will only load two blocks.\n\t*/\n\tif (st->Loading) {\n\t\tnum = st->FilePending + 2;\n\t\tnum = MIN(num, maxnum);\n\t} else {\n\t\tnum = maxnum;\n\t}\n\n\t//printf(\"Before buffer load!\\n\");\n\t/*\n\t** Loop through the blocks and load up the number we need.\n\t*/\n\tfor (int index = st->FilePending; index < num; index++) {\n\t\tlong s = Read_File(fh, Add_Long_To_Pointer(buffer, (long)index * (long)LockedData.StreamBufferSize), LockedData.StreamBufferSize);\n\t\t//printf(\"Reading block of size %d Stream Buffer = %d\\n\");\n\t\tif (s) {\n\t\t\tst->FilePendingSize = s;\n\t\t\tst->FilePending++;\n\t\t}\n\t\tif (s < LockedData.StreamBufferSize) break;\n\t}\n\n\t/*\n\t** If the last block was incomplete (ie. it didn't completely fill the buffer) or\n\t** we have now filled up as much of the Streaming Buffer as we need to, then now is\n\t** the time to kick off the sample.\n\t*/\n\tif (st->FilePendingSize < LockedData.StreamBufferSize || index == maxnum) {\n\t\t//printf(\"Before Stream Sample Volume!\\n\");\n\t\t/*\n\t\t** Actually start the sample playing, and don't worry about the file callback\n\t\t** it won't be called for a while.\n\t\t*/\n\t\t{\n\t\t\tint old\t\t\t\t\t\t= LockedData.SoundVolume;\n\t\t\tint size\t\t\t\t\t\t= (st->FilePending == 1) ? st->FilePendingSize : LockedData.StreamBufferSize;\n\t\t\tLockedData.SoundVolume\t= LockedData.ScoreVolume;\n\n\t\t\tStartingFileStream \t\t= TRUE;\n\t\t\tStream_Sample_Vol(buffer, size, File_Callback, st->Volume, handle);\n\t\t\tStartingFileStream \t\t= FALSE;\n\t\t\tLockedData.SoundVolume \t= old;\n\t\t}\n\t\t//printf(\"After Stream Sample Volume!\\n\");\n\t\t/*\n\t\t** The Sample is finished loading (if it was loading in small pieces) so record that\n\t\t** so that it will now use the active logic in the file call back.\n\t\t*/\n\t\tst->Loading\t\t\t\t\t= FALSE;\n\n\t\t/*\n\t\t** Decrement the file pending because the first block is already playing thanks\n\t\t** to the play sample call above.\n\t\t*/\n\t\tst->FilePending--;\n\n\t\t/*\n\t\t** If File pending is now a zero, then we only preloaded one block and there\n\t\t** is nothing more to play.  So clear the sample tracing structure of the\n\t\t** information it no longer needs.\n\t\t*/\n\t\tif (!st->FilePending) {\n\t\t\tst->Odd\t\t\t\t\t= 0;\n\t\t\tst->QueueBuffer\t\t= 0;\n\t\t\tst->QueueSize\t\t\t= 0;\n\t\t\tst->FilePendingSize\t= 0;\n\t\t\tst->Callback \t\t\t= NULL;\n\t\t\tClose_File(fh);\n\t\t} else {\n\t\t\t/*\n\t\t\t**\tThe QueueBuffer counts as an already played block so remove it from the total.\n\t\t\t** Note: We didn't remove it before because there might not have been one.\n\t\t\t*/\n\t\t\tst->FilePending--;\n\n\t\t\t/*\n\t\t\t** When we start loading we need to start past the first two blocks.  Why this\n\t\t\t** is called Odd, I haven't got the slightest.\n\t\t\t*/\n\t\t\tst->Odd \t\t\t\t\t= 2;\n\n\t\t\t/*\n\t\t\t** If the file pending size is less than the stream buffer, then the last block\n\t\t\t** we loaded was the last block period.  So close the file and reset the handle.\n\t\t\t*/\n\t\t\tif (st->FilePendingSize != LockedData.StreamBufferSize) {\n\t\t\t\tClose_File(fh);\n\t\t\t\tst->FileHandle = ERROR;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** The Queue buffer needs to point at the next block to be processed.  The size\n\t\t\t** of the queue is dependant on how many more blocks there are.\n\t\t\t*/\n\t\t\tst->QueueBuffer = Add_Long_To_Pointer(buffer, LockedData.StreamBufferSize);\n\t\t\tif (!st->FilePending) {\n\t\t\t\tst->QueueSize = st->FilePendingSize;\n\t\t\t} else {\n\t\t\t\tst->QueueSize = LockedData.StreamBufferSize;\n\t\t\t}\n\t\t}\n\t}\n}\n/***********************************************************************************************\n * File_Stream_Sample_Vol -- Streams a sample directly from a file.                            *\n *                                                                                             *\n *    This will take the file specified and play it directly from disk.                        *\n *    It performs this by allocating a temporary buffer in XMS/EMS and                         *\n *    then keeping this buffer filled by the Sound_Callback() routine.                         *\n *                                                                                             *\n * INPUT:   filename -- The name of the file to play.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the handle to the sound -- just like Play_Sample().                        *\n *                                                                                             *\n * WARNINGS:   The temporary buffer is allocated when this routine is                          *\n *             called and then freed when the sound is finished.  Keep                         *\n *             this in mind.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start)\n{\n\tstatic VOID\t*buffer = NULL;\n\tSampleTrackerType\t*st;\n\tint\tfh;\n\tint\thandle = -1;\n\tlong\tsize;\n\tint\tindex;\n\n\tif (LockedData.DigiHandle != -1 && filename && Find_File(filename)) {\n\t\t//printf(\"Before initialize memory!\\n\");\n\t\t/*\n\t\t**\tMake sure all sample tracker structures point to the same\n\t\t**\tupper memory buffer.  This allocation only occurs if at\n\t\t**\tleast one sample gets \"streamed\".\n\t\t*/\n\t\tif (!buffer) {\n\t\t\tbuffer = Alloc(LockedData.StreamBufferSize * LockedData.StreamBufferCount, (MemoryFlagType)(StreamBufferFlag | MEM_TEMP | MEM_LOCK));\n\t\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\t\t\tLockedData.SampleTracker[index].FileBuffer = buffer;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** If after trying to allocate the buffer we still fail then\n\t\t** we can stream this sample.\n\t\t*/\n\t\tif (!buffer) return(-1);\n\t\t\n\t\t//printf(\"Before Open File!\\n\");\n\t\t/*\n\t\t** Lets see if we can sucessfully open up the file.  If we can't, \n\t\t** then there is no point in going any farther.\n\t\t*/\n\t\tif ((fh = Open_File(filename, READ)) == -1) {\n\t\t\treturn (-1);\n\t\t}\n\n\t\t//printf(\"Before Get Free Handle!\\n\");\n\t\t/*\n\t\t** Reserve a handle so that we can fill in the sample tracker\n\t\t** with the needed information.  If we dont get valid handle then\n\t\t** we might as well give up.\n\t\t*/\n\t\tif ((unsigned)(handle = Get_Free_Sample_Handle(0xFF)) >= LockedData.MaxSamples) {\n\t\t\treturn(-1);\n\t\t}\n\n\t\t/*\n\t\t** Now lets get a pointer to the proper sample handler and start\n\t\t** our manipulations.\n\t\t*/ \n\t\tst\t\t\t\t\t\t\t= &LockedData.SampleTracker[handle];\n\t\tst->IsScore\t\t\t\t= TRUE;\n\t\tst->FilePending\t\t= 0;\n\t\tst->FilePendingSize\t= 0;\n\t\tst->Loading\t\t\t\t= real_time_start;\n\t\tst->Volume\t\t\t\t= volume;\n\t\tst->FileHandle\t\t\t= fh;\n\t\t/*\n\t\t** Now that we have setup our initial data properly, let load up\n\t\t** the beginning of the sample we intend to stream.\n\t\t*/\n\t\t//printf(\"Before Preload!\\n\");\n\t\tFile_Stream_Preload(handle);\n\t}\n\treturn (handle);\n}\n\n/***********************************************************************************************\n * Sound_Callback -- Audio driver callback function.                                           *\n *                                                                                             *\n *    Maintains the audio buffers.  This routine must be called at least                       *\n *    11 times per second or else audio glitches will occur.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If this routine is not called often enough then audio                           *\n *             glitches will occur.                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID cdecl __saveregs __loadds Sound_Callback(VOID)\n{\n\tint\t\t\t\t\tindex;\n\tSampleTrackerType\t*st;\n\n\tif (LockedData.DigiHandle != -1) {\n\t\tst = &LockedData.SampleTracker[0];\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\t\tif (st->Loading) {\n\t\t\t\tFile_Stream_Preload(index);\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t**\tGeneral service routine to handle moving small blocks from the\n\t\t\t\t**\tsource into the low RAM staging buffers.\n\t\t\t\t*/\n\n\t\t\t\tif (st->Active) {\n\t\t\t\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSpecial check to see if the sample is a fading one AND\n\t\t\t\t\t**\tit has faded to silence, then stop it here.\n\t\t\t\t\t*/\n\t\t\t\t\tif (st->Reducer && !st->Volume) {\n\t\t\t\t\t\tStop_Sample(index);\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tFill the queuebuffer if it is currently empty\n\t\t\t\t\t\t**\tand there is a callback function defined to fill it.\n\t\t\t\t\t\t**\n\t\t\t\t\t\t** PWG/CDY & CO: We should be down by at least two blocks\n\t\t\t\t\t\t**\t\t\t\t\t  before we bother with this\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif ((!st->QueueBuffer || \n\t\t\t\t\t\t\t(st->FileHandle != ERROR && st->FilePending < LockedData.StreamBufferCount-3)) && \n\t\t\t\t\t\t\tst->Callback) {\n\n\t\t\t\t\t\t\tif (!st->Callback(index, &st->Odd, &st->QueueBuffer, &st->QueueSize)) {\n\t\t\t\t\t\t\t\tst->Callback = NULL;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThis catches the case where a streaming sample gets\n\t\t\t\t\t**\taborted prematurely because of failure to call the\n\t\t\t\t\t**\tcallback function frequently enough.  In this case, the\n\t\t\t\t\t**\tsample will be flagged as inactive, but the file handle\n\t\t\t\t\t**\twill not have been closed.\n\t\t\t\t\t*/\n\t\t\t\t\tif (st->FileHandle != ERROR) {\n\t\t\t\t\t\tClose_File(st->FileHandle);\n\t\t\t\t\t\tst->FileHandle = ERROR;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAdvance to the next sample control structure.\n\t\t\t*/\n\t\t\tst++;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Load_Sample -- Loads a digitized sample into RAM.                                           *\n *                                                                                             *\n *    This routine loads a digitized sample into RAM.                                          *\n *                                                                                             *\n * INPUT:   filename -- Name of the sound file to load.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the loaded sound file.  This pointer                     *\n *          is passed to Play_Sample when playback is desired.                                 *\n *                                                                                             *\n * WARNINGS:   If there is insufficient memory to load the sample, then                        *\n *             NULL will be returned.                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *   01/06/1994 JLB : HMI version.                                                             *\n *=============================================================================================*/\nVOID *Load_Sample(char const *filename)\n{\n\tvoid *buffer = NULL;\n\tlong\tsize;\n\tint\tfh;\n\n\tif (LockedData.DigiHandle == -1 || !filename || !Find_File(filename)) {\n\t\treturn (NULL);\n\t}\n\n\tfh = Open_File(filename, READ);\n\tif (fh != ERROR) {\n\t\tsize = File_Size(fh)+sizeof(AUDHeaderType);\n\t\tbuffer = Alloc(size, MEM_NORMAL);\n\n\t\tif (buffer) {\n\t\t\tSample_Read(fh, buffer, size);\n\t\t}\n\t\tClose_File(fh);\n\t\tMisc = size;\n\t}\n\treturn(buffer);\n}\n\n\n/***********************************************************************************************\n * Load_Sample_Into_Buffer -- Loads a digitized sample into a buffer.                          *\n *                                                                                             *\n *    This routine is used to load a digitized sample into a buffer                            *\n *    provided by the programmer.  This buffer can be in XMS or EMS.                           *\n *                                                                                             *\n * INPUT:   filename -- The filename to load.                                                  *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer to load into.                                    *\n *                                                                                             *\n *          size     -- The size of the buffer to load into.                                   *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually used in the buffer.                           *\n *                                                                                             *\n * WARNINGS:   This routine will not overflow the buffer provided.  This                       *\n *             means that the buffer must be big enough to hold the data                       *\n *             or else the sound will be cut short.                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Load_Sample_Into_Buffer(char const *filename, void *buffer, long size)\n{\n\tint\tfh;\n\n\t/*\n\t**\tVerify legality of parameters.\n\t*/\n\tif (!buffer || !size || LockedData.DigiHandle == -1 || !filename || !Find_File(filename)) {\n\t\treturn (NULL);\n\t}\n\n\tfh = Open_File(filename, READ);\n\tif (fh != ERROR) {\n\t\tsize = Sample_Read(fh, buffer, size);\n\t\tClose_File(fh);\n\t} else {\n\t\treturn(0);\n\t}\n\treturn(size);\n}\n\n\n/***********************************************************************************************\n * Sample_Read -- Reads sample data from an openned file.                                      *\n *                                                                                             *\n *    This routine reads a sample file.  It is presumed that the file is                       *\n *    already positioned at the start of the sample.  From this, it can                        *\n *    determine if it is a VOC or raw data and proceed accordingly.                            *\n *                                                                                             *\n * INPUT:   fh       -- File handle of already openned sample file.                            *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer to load data into.                               *\n *                                                                                             *\n *          size     -- The size of the buffer.                                                *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually used in the buffer.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Sample_Read(int fh, void *buffer, long size)\n{\n\n\tAUDHeaderType\tRawHeader;\n\tVOID\t*outbuffer;\t\t\t\t\t// Pointer to start of raw data.\n\tlong\tactual_bytes_read;\t\t// Actual bytes read in, including header\n\n/*\n\tConversion formula for TCrate and Hz rate.\n\n\tTC = 256 - 1m/rate\n\trate = 1m / (256-TC)\n*/\n\n\tif (!buffer || fh == ERROR || size <= sizeof(RawHeader)) return(NULL);\n\tsize -= sizeof(RawHeader);\n\toutbuffer = Add_Long_To_Pointer(buffer, sizeof(RawHeader));\n\n\t\t\t\tactual_bytes_read = \n\t\t\t\t\tRead_File(fh, &RawHeader, sizeof(RawHeader));\n\n\t\t\t\tactual_bytes_read +=\n\t\t\t\t\tRead_File(fh, outbuffer, MIN(size, RawHeader.Size));\n\n\n\tMem_Copy(&RawHeader, buffer, sizeof(RawHeader));\n\treturn(actual_bytes_read);\n}\n\n\n/***********************************************************************************************\n * Free_Sample -- Frees a previously loaded digitized sample.                                  *\n *                                                                                             *\n *    Use this routine to free the memory allocated by a previous call to                      *\n *    Load_Sample.                                                                             *\n *                                                                                             *\n * INPUT:   sample   -- Pointer to the sample to be freed.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID Free_Sample(VOID const *sample)\n{\n\tif (sample) Free((void *)sample);\n}\n\nBOOL Sound_Init(int sfx, int score, int sample, RateType rate, int bits_per_sample, int max_samples, int reverse_channels)\n{\n\treturn Audio_Init(sample, -1, -1, -1, rate, bits_per_sample, max_samples, reverse_channels);\n}\n\nBOOL Audio_Init(int sample, int address, int inter, int dma, RateType rate, int bits_per_sample, int max_samples, int reverse_channels)\n{\n\tint\t\t\t\t\terror;\t// Function error return code.\n\tunsigned int \t\tport;\n\tint\t\t\t\t\tindex;\n\t_SOS_INIT_DRIVER\tinit;\t\t// Driver init structure.\n\n\tInit_Locked_Data();\n\tmemset(&LockedData.SampleTracker[0], 0, sizeof(LockedData.SampleTracker));\n\tLockedData.Rate = rate;\n\n\tBits_Per_Sample = bits_per_sample;\n\n\tsosTIMERInitSystem(_TIMER_DOS_RATE, _SOS_DEBUG_NORMAL);\n\n\tif (TimerSystemOn) {\n\t\tsosTIMERRegisterEvent(60, &Timer_Interrupt_Func, &SystemTimer);\n//\t\tTickCount.Start();\n\t} else\n\t\tsosTIMERRegisterEvent(60, &HMI_TimerCallback, &SystemTimer);\n\n\t/*\n\t**\tSpecial code to handle the HMI problem with running under Windows.\n\t*/\n\tif (/*Operating_System() != OS_DOS ||*/ sample == SAMPLE_NONE) {\n\t\treturn(FALSE);\n\t}\n\n\twhile (sample) {\n\n#ifdef SIMPLE_HMI_INIT\n\n\t\tif (address == -1 || inter == -1 || dma == -1) {\n\t\t\terror = sosDIGIDetectInit((LPSTR)NULL);\n\t\t\tif (error) {\n\t\t\t\tprintf(\"Cannot initialize detection system (%d).\\n\", error);\n\t\t\t\tGet_Key();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\terror = sosDIGIDetectFindHardware(sample, &DigiCaps, &port);\n\t\t\tif (error) {\n\t\t\t\tprintf(\"Cannot find sound card specified.\\n\");\n\t\t\t\tGet_Key();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Handle the override for Address, Interrupt, and DMA settings.\n\t\t\t*/\n\t\t\terror = sosDIGIDetectGetSettings(&DigiHardware);\n\t\t\tsosDIGIDetectUnInit();\n\t\t\tif (error) {\n\t\t\t\tprintf(\"Cannot get sound card settings.\\n\");\n\t\t\t\tGet_Key();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t \tDigiHardware.wPort = address;\n\t\t\tDigiHardware.wIRQ = inter;\n\t\t\tDigiHardware.wDMA = dma;\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tInitialize the digi-system and driver.\n\t\t*/\n\t\tsosDIGIInitSystem((LPSTR)NULL, _SOS_DEBUG_NORMAL);\n\t\tinit.wBufferSize\t\t= 1024*8;\t\t\t\t// Specify the DMA buf size\n\t\tinit.lpBuffer\t\t\t= (LPSTR)NULL;\n\t\tinit.wAllocateBuffer = TRUE;\n\t\tinit.wSampleRate\t\t= rate;\t\t\t\t\t// Sample playback rate.\n\t\tinit.wParam\t\t\t\t= 19;\n\t\tinit.dwParam\t\t\t= 0;\n\t\tinit.lpFillHandler\t= NULL;\n\t\tinit.lpDriverMemory\t= (LPSTR)NULL;\n\t\tinit.lpTimerMemory\t= (LPSTR)NULL;\n\t\tinit.wTimerID\t\t\t= _SOS_NORMAL_TIMER;\n \t\t\n\t\terror = 0;\n\t\terror = sosDIGIInitDriver( (int)sample, &DigiHardware, &init, &LockedData.DigiHandle);\n\t\tif (error) {\n\t\t\tprintf(\"Unable to initialize the sound driver.\\n\");\n\t\t\tGet_Key();\n\t\t\tbreak;\n\t\t}\n\n\t\terror = 0;\n\n\n\t\tif (sample >= _GUS_8_MONO && sample <= _GUS_16_ST) {\n\t\t\terror = sosTIMERRegisterEvent(120, init.lpFillHandler, &DigiTimer);\n\t\t} else {\n\t\t\terror = sosTIMERRegisterEvent(60, init.lpFillHandler, &DigiTimer);\n\t\t}\n\t\tif (error) {\n\t\t\tprintf(\"Unable to regiser the fill handler.\\n\");\n\t\t\tGet_Key();\n\t\t\tsosDIGIUnInitDriver(LockedData.DigiHandle, TRUE, TRUE);\n\t\t\tLockedData.DigiHandle = -1;\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tAllocate a decompression buffer equal to the size of a SONARC frame\n\t\t**\tblock.\n\t\t*/\n\t\tLockedData.UncompBuffer = Alloc(LARGEST_SONARC_BLOCK + 50, (MemoryFlagType)(MEM_NORMAL|MEM_CLEAR|MEM_LOCK));\n\t\tLockedData.MaxSamples\t= max_samples;\n\n\t\t/*\n\t\t**\tAllocate private staging buffers for double buffering sound into HMI\n\t\t**\tdriver.\n\t\t*/\n\t\tDigiBuffer = Alloc(2048+(((LONG)LockedData.MaxSamples*2) * (LONG)(SFX_MINI_STAGE_BUFFER_SIZE+SONARC_MARGIN)), (MemoryFlagType)(MEM_NORMAL|MEM_CLEAR|MEM_LOCK));\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\t\tLockedData.SampleTracker[index].Buffer[0] = Add_Long_To_Pointer(DigiBuffer, ((LONG)index*2) * (LONG)(SFX_MINI_STAGE_BUFFER_SIZE+SONARC_MARGIN));\n\t\t\tLockedData.SampleTracker[index].Buffer[1] = Add_Long_To_Pointer(DigiBuffer, ((LONG)index*2+1) * (LONG)(SFX_MINI_STAGE_BUFFER_SIZE+SONARC_MARGIN));\n\t\t\tLockedData.SampleTracker[index].FileHandle = ERROR;\n\t\t\tLockedData.SampleTracker[index].QueueBuffer = NULL;\n\t\t}\n\t\terror = sosTIMERRegisterEvent(MAINTENANCE_RATE, (void (__far *)(void))maintenance_callback, &MaintainTimer);\n\t\tif (error) {\n\t\t\tprintf(\"Unable to initialize the maintenance callback.\\n\");\n\t\t\tGet_Key();\n\t\t\tsosTIMERRemoveEvent(DigiTimer);\n\t\t\tsosDIGIUnInitDriver(LockedData.DigiHandle, TRUE, TRUE);\n\t\t\tLockedData.DigiHandle = -1;\n\t\t\tbreak;\n\t\t}\n\t\tSoundType = (SFX_Type)sample;\n\t\tSampleType = (Sample_Type)sample;\n\t\tReverseChannels = reverse_channels;\n\n\t\tbreak;\n\t}\n\n\treturn(TRUE);\n}\n\n\n/***********************************************************************************************\n * Sound_End -- Uninitializes the sound driver.                                                *\n *                                                                                             *\n *    This routine will uninitialize the sound driver (if any was                              *\n *    installed).  This routine must be called at program termination                          *\n *    time.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/23/1991 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID Sound_End(VOID)\n{\n\n\tif (LockedData.DigiHandle != -1) {\n\t\tsosTIMERRemoveEvent(DigiTimer);\n\t\tsosTIMERRemoveEvent(MaintainTimer);\n\t\tsosDIGIUnInitDriver(LockedData.DigiHandle, TRUE, TRUE);\n\t\tsosDIGIUnInitSystem();\n\t\tLockedData.DigiHandle = -1;\n\t}\n\tif (DigiBuffer) {\n\t\tFree(DigiBuffer);\n\t\tDigiBuffer = 0;\n\t}\n\tif (LockedData.UncompBuffer) {\n\t\tFree(LockedData.UncompBuffer);\n\t\tLockedData.UncompBuffer = 0;\n\t}\n\tsosTIMERRemoveEvent(SystemTimer);\n\tsosTIMERUnInitSystem(0);\n\tUnlock_Locked_Data();\n}\n\n\n\n\n/***********************************************************************************************\n * Stop_Sample -- Stops any currently playing sampled sound.                                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nVOID Stop_Sample(int handle)\n{\n\tif (LockedData.DigiHandle != -1 && (unsigned)handle < LockedData.MaxSamples) {\n\n\n\t\tif (LockedData.SampleTracker[handle].Active || LockedData.SampleTracker[handle].Loading) {\n\n\t\t\t\n\t\t\tLockedData.SampleTracker[handle].Active = FALSE;\n\t\t\tif (!LockedData.SampleTracker[handle].IsScore) {\n\t\t\t\tDPMI_Unlock(LockedData.SampleTracker[handle].Original, LockedData.SampleTracker[handle].OriginalSize);\n\t\t\t\tLockedData.SampleTracker[handle].Original = NULL;\n\t\t\t}\n\t\t\tLockedData.SampleTracker[handle].Priority = 0;\n\n\t\t\t/*\n\t\t\t**\tStop the sample if it is playing.\n\t\t\t*/\n\t\t\tif (!LockedData.SampleTracker[handle].Loading) {\n\t\t\t\tsosDIGIStopSample(LockedData.DigiHandle, LockedData.SampleTracker[handle].Handle);\n\t\t\t}\n\t\t\tLockedData.SampleTracker[handle].Loading = FALSE;\n\n\t\t\t/*\n\t\t\t**\tIf this is a streaming sample, then close the source file.\n\t\t\t*/\n\t\t\tif (LockedData.SampleTracker[handle].FileHandle != ERROR) {\n\t\t\t\tClose_File(LockedData.SampleTracker[handle].FileHandle);\n\t\t\t\tLockedData.SampleTracker[handle].FileHandle = ERROR;\n\t\t\t}\n\n\t\t\tLockedData.SampleTracker[handle].QueueBuffer = NULL;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Sample_Status -- Queries the current playing sample status (if any).                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nBOOL Sample_Status(int handle)\n{\n\t/*\n\t** If its an invalid handle or we do not have a sound driver then\n\t** the sample in question is not playing.\n\t*/\n\tif (LockedData.DigiHandle == -1 || (unsigned)handle >= LockedData.MaxSamples) return(FALSE);\n\t/*\n\t** If the sample is loading, then for all intents and purposes the\n\t** sample is playing.\n\t*/\n\tif (LockedData.SampleTracker[handle].Loading) return(TRUE);\n\t/* \n\t** If the sample is not active, then it is not playing\n\t*/\n\tif (!LockedData.SampleTracker[handle].Active) return(FALSE);\n\t/*\n\t** If we made it this far, then the Sample is still playing if sos says\n\t** that it is.\n\t*/\n\treturn (!sosDIGISampleDone(LockedData.DigiHandle, LockedData.SampleTracker[handle].Handle));\n}\n\n\nBOOL Is_Sample_Playing(void const * sample)\n{\n\tint index;\n\n\tif (!sample) return FALSE;\n\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\tif (LockedData.SampleTracker[index].Original == sample && Sample_Status(index)) {\n\t\t\treturn (TRUE);\n\t\t}\n\t}\n\treturn (FALSE);\n}\n\n\nVOID Stop_Sample_Playing(void const * sample)\n{\n\tint index;\n\n\tif (sample) {\n\t\tfor (index = 0; index < LockedData.MaxSamples; index++) {\n\t\t\tif (LockedData.SampleTracker[index].Original == sample) {\n\t\t\t\tStop_Sample(index);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\nint Get_Free_Sample_Handle(int priority)\n{\n\tint\tid;\n\n\t/*\n\t**\tFind a free SFX holding buffer slot.\n\t*/\n\tfor (id = LockedData.MaxSamples - 1; id >= 0; id--) {\n\t\tif (!LockedData.SampleTracker[id].Active && !LockedData.SampleTracker[id].Loading) {\n\t\t\tif (!StartingFileStream && LockedData.SampleTracker[id].IsScore) {\n\t\t\t\tStartingFileStream = TRUE;\t// Ensures only one channel is kept free for scores.\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (id < 0) {\n\t\tfor (id = 0; id < LockedData.MaxSamples; id++) {\n\t\t\tif (LockedData.SampleTracker[id].Priority <= priority) break;\n\t\t}\n\t\tif (id == LockedData.MaxSamples) {\n\t\t\treturn(-1);\t\t// Cannot play!\n\t\t}\n\t\tStop_Sample(id);\t\t\t\t\t\t\t// This sample gets clobbered.\n\t}\n\tif (id == -1) {\n\t\treturn -1;\n\t}\n\tif (LockedData.SampleTracker[id].FileHandle != ERROR) {\n\t\tClose_File(LockedData.SampleTracker[id].FileHandle);\n\t\tLockedData.SampleTracker[id].FileHandle = ERROR;\n\t}\n\tif (LockedData.SampleTracker[id].Original && !LockedData.SampleTracker[id].IsScore) {\n\t\tDPMI_Unlock(LockedData.SampleTracker[id].Original, LockedData.SampleTracker[id].OriginalSize);\n\t\tLockedData.SampleTracker[id].Original = NULL;\n\t}\n\tLockedData.SampleTracker[id].IsScore = FALSE;\n\treturn(id);\n}\n\nint Play_Sample(void const *sample, int priority, int volume, signed short panloc)\n{\n\treturn(Play_Sample_Handle(sample, priority, volume, panloc, Get_Free_Sample_Handle(priority)));\n}\n/***********************************************************************************************\n * Play_Sample_Vol -- Plays a digitized sample.                                                *\n *                                                                                             *\n *    Use this routine to play a previously loaded digitized sample.                           *\n *                                                                                             *\n * INPUT:   sample   -- Sample pointer as returned from Load_Sample.                           *\n *                                                                                             *\n *          volume   -- The volume to play (0..255 with 255=loudest).                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1992 JLB : Created.                                                                 *\n *   05/24/1992 JLB : Volume support -- Soundblaster Pro                                       *\n *   04/22/1994 JLB : Multiple sample playback rates.                                          *\n *=============================================================================================*/\nint Play_Sample_Handle(void const *sample, int priority, int volume, signed short panloc, int id)\n{\n\tAUDHeaderType\t\t\tRawHeader;\n\t_SOS_START_SAMPLE \tstart;\n\tSampleTrackerType\t\t*st=NULL;\t// Working pointer to sample tracker structure.\n\n\tif (!sample || LockedData.DigiHandle == -1) {\n\t\treturn(-1);\n\t}\n\n\tif (id == -1) {\n\t\treturn -1;\n\t}\n\n\t/*\n\t**\tFetch the control bytes from the start of the sample data.\n\t*/\n\tMem_Copy((void *)sample, (void *)&RawHeader, sizeof(RawHeader));\n\n\t/*\n\t**\tPrepare the sample tracker structure for processing of this\n\t**\tsample.  Fill the structure with data that can be determined\n\t**\tbefore the sample is started.\n\t*/\n\tst = &LockedData.SampleTracker[id];\n\tst->Compression\t= (SCompressType) ((unsigned char)RawHeader.Compression);\n\tst->Original\t\t= sample;\n\tst->OriginalSize\t= RawHeader.Size + sizeof(RawHeader);\n\tif (!st->IsScore) {\n\t\tDPMI_Lock(st->Original, st->OriginalSize);\n\t}\n\tst->Priority\t\t= priority;\n\tst->DontTouch\t\t= FALSE;\n\tst->Odd\t\t\t\t= 0;\n\tst->Reducer\t\t\t= 0;\n\tst->Restart\t\t\t= FALSE;\n\tst->QueueBuffer\t= NULL;\n\tst->QueueSize\t\t= NULL;\n\tst->TrailerLen \t= 0;\n\tst->Remainder\t\t= RawHeader.Size;\n\tst->Source\t\t\t= Add_Long_To_Pointer((void *)sample, sizeof(RawHeader));\n\tst->Service\t\t\t= FALSE;\n\n\t/*\n \t** If the code in question using HMI based compression then we need\n\t** to set up for uncompressing it.\n\t*/\n\tif (st->Compression == SCOMP_SOS) {\n\t\tst->sosinfo.wChannels\t = (RawHeader.Flags & AUD_FLAG_STEREO) ? 2  : 1;\n\t\tst->sosinfo.wBitSize\t\t = (RawHeader.Flags & AUD_FLAG_16BIT)  ? 16 : 8;\n\t\tst->sosinfo.dwCompSize\t = RawHeader.Size;\n   \tst->sosinfo.dwUnCompSize = RawHeader.Size * ( st->sosinfo.wBitSize / 4 );\n\t   sosCODECInitStream(&st->sosinfo);\n\t}\n\n\t/*\n\t**\tFill in one or both staging buffers if possible.\n\t*/\n\t_disable();\n//\tDisable_Timer_Interrupt();\n\tif (SFX_MINI_STAGE_BUFFER_SIZE == \n\t\t\t\t\tSample_Copy(st,\n\t\t\t\t\t\t\t\t\t&st->Source, \n\t\t\t\t\t\t\t\t\t&st->Remainder, \n\t\t\t\t\t\t\t\t\t&st->QueueBuffer, \n\t\t\t\t\t\t\t\t\t&st->QueueSize, \n\t\t\t\t\t\t\t\t\tst->Buffer[0], \n\t\t\t\t\t\t\t\t\tSFX_MINI_STAGE_BUFFER_SIZE, \n\t\t\t\t\t\t\t\t\tst->Compression, \n\t\t\t\t\t\t\t\t\t&st->Trailer[0], \n\t\t\t\t\t\t\t\t\t&st->TrailerLen)) {\n\n\t\tst->DataLength = Sample_Copy(st,\n\t\t\t\t\t\t\t\t\t\t&st->Source, \n\t\t\t\t\t\t\t\t\t\t&st->Remainder, \n\t\t\t\t\t\t\t\t\t\t&st->QueueBuffer, \n\t\t\t\t\t\t\t\t\t\t&st->QueueSize, \n\t\t\t\t\t\t\t\t\t\tst->Buffer[1], \n\t\t\t\t\t\t\t\t\t\tSFX_MINI_STAGE_BUFFER_SIZE, \n\t\t\t\t\t\t\t\t\t\tst->Compression, \n\t\t\t\t\t\t\t\t\t\t&st->Trailer[0], \n\t\t\t\t\t\t\t\t\t\t&st->TrailerLen);\n\t\tst->Index = 1;\n\t} else {\n\t\tst->Index = 0;\n\t\tst->DataLength = 0;\n\t}\n\t_enable();\n//\tEnable_Timer_Interrupt();\n\n\t/*\n\t**\tFill in the HMI start sample structure.\n\t*/\n\tmemset(&start, 0, sizeof(start));\n\n\tstart.lpSamplePtr = (LPSTR)st->Buffer[0];\n\tif (st->Index == 1) {\n\t\tstart.dwSampleSize = SFX_MINI_STAGE_BUFFER_SIZE-1;\n\t} else {\n\t\tstart.dwSampleSize = st->DataLength-1;\n\t}\n\tstart.lpCallback\t= (void cdecl (far *)(unsigned int, unsigned int, unsigned int))&DigiCallback;\n\tstart.wLoopCount\t= 0;\n\tstart.wSampleID\t= id;\n\n\t/*\n\t**\tAdjust pitch shifting as necessary so that lower playback\n\t**\tsamples can be supported.\n\t*/\n\tif (RawHeader.Rate != LockedData.Rate) {\n\t\tldiv_t\tresult;\n\n\t\tresult\t\t\t\t\t\t= ldiv((long)RawHeader.Rate, LockedData.Rate);\n\t\tstart.dwSamplePitchAdd\t= (long)MAKE_LONG((short)result.quot, (short)(((long)result.rem * 0x10000L) / LockedData.Rate));\n\t\tstart.wSampleFlags \t  |= _PITCH_SHIFT;\n\t}\n\n\t/*\n\t**\tSample translation flag.\n\t*/\n\n\tif (RawHeader.Flags & AUD_FLAG_16BIT) {\n\t\tif (Bits_Per_Sample == 8) {\n\t\t\tstart.wSampleFlags \t  |= _TRANSLATE16TO8;\n\t\t}\n\t} else {\n\t\tif (Bits_Per_Sample == 16) {\n\t\t\tstart.wSampleFlags \t  |= _TRANSLATE8TO16;\n\t\t}\n\t}\n\n\t/*\n\t**\tSample stereo flag.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_STEREO) {\n\t\tstart.wChannel \t\t\t= _INTERLEAVED;\n\t\tstart.wSampleFlags \t  |= _STEREOTOMONO;\n\t} else {\n\t\tstart.wChannel \t\t\t= _CENTER_CHANNEL;\n\t}\n\n\t/*\n\t**\tSample volume control flags.  Always give it volume control because\n\t**\tif not, then future volume control is either ignored or stops the\n\t**\tsample.\n\t*/\n\tst->Volume \t\t\t\t\t\t= volume << 7;\n\tstart.wVolume\t\t\t\t\t= (st->Volume >> 8) * LockedData.SoundVolume;\n\tstart.wSampleFlags  \t\t  |= _VOLUME;\n\t\n\t/*\n\t** If we have defined a panning location for the sound driver than\n\t** take care of it here.  Panning will only work with a stereo driver\n\t** and only if the sample is played _CENTER_CHANNEL.\n\t*/\n\tif ((panloc != 0x0) && (!(RawHeader.Flags & AUD_FLAG_STEREO))) {\n\t\tstart.wChannel \t\t\t= _CENTER_CHANNEL;\n\t\tpanloc \t\t\t\t\t\t= ((ReverseChannels) ? ((-panloc) + 0x8000) : ((panloc) + 0x8000));\n\t\tstart.wSampleFlags \t  |= _PANNING;\n\t\tstart.wSamplePanLocation= panloc;\n\t}\n\n\tst->Stereo \t= start.wChannel;\n\tst->Pitch \t= start.dwSamplePitchAdd;\n\tst->Flags \t= start.wSampleFlags;\n\n\t/*\n\t**\tStart the sample playing now.\n\t*/\n\t_disable();\t\t// NEW\n//\tDisable_Timer_Interrupt();\n\tst->Handle = sosDIGIStartSample(LockedData.DigiHandle, &start);\n\tif (st->Handle == -1) {\n\t\tid = -1;\n\t} else {\n\n\t\t/*\n\t\t**\tFill in the sample tracker structure with those values that are\n\t\t**\tdetermined AFTER the sample starts.\n\t\t*/\n\t\tst->Active = TRUE;\n\t}\n\t_enable();\t\t\t// NEW\n//\tEnable_Timer_Interrupt();\n\n\treturn(id);\n}\n\n\nint Set_Sound_Vol(int volume)\n{\n\tint old;\n\told = LockedData.SoundVolume;\n\tLockedData.SoundVolume = volume & 0xFF;\n\treturn(old);\n}\n\n\nint Set_Score_Vol(int volume)\n{\n\tint old;\n\told = LockedData.ScoreVolume;\n\tLockedData.ScoreVolume = volume & 0xFF;\n\treturn(old);\n}\n\n\nVOID Fade_Sample(int handle, int ticks)\n{\n\tif (Sample_Status(handle)) {\n\t\tif (!ticks || LockedData.SampleTracker[handle].Loading) {\n\t\t\tStop_Sample(handle);\n\t\t} else {\n\t\t\tSampleTrackerType * st;\n\n\t\t\tst = &LockedData.SampleTracker[handle];\n\t\t\tst->Reducer = (st->Volume / ticks)+1;\n\t\t}\n\t}\n}\nint Get_Digi_Handle(void)\n{\n\treturn(LockedData.DigiHandle);\n}\n\n/***************************************************************************\n * SAMPLE_LENGTH -- returns length of a sample in ticks                    *\n *                                                                         *\n * INPUT:\t\tvoid const *sample - pointer to the sample to get length    *\n *\t\t\t\t\t\t\t\t\t\t\t   of.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tlong   \t\t\t\t - length of the sample in ticks (60/sec) *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/05/1995 PWG : Created.                                             *\n *=========================================================================*/\nlong Sample_Length(void const *sample)\n{\n\tAUDHeaderType\t\t\tRawHeader;\n\n\tif (!sample) return(0);\n\n\tMem_Copy((void *)sample, (void *)&RawHeader, sizeof(RawHeader));\n\n\tlong time = RawHeader.UncompSize;\n\n\t/*\n\t** If the sample is a 16 bit sample, then it will take only half\n\t** as long to play.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_16BIT) {\n\t\ttime >>= 1;\n\t}\n\n\t/*\n\t** If the sample is a stereo sample, then it will take only half\n\t** as long to play.\n\t*/\n\tif (RawHeader.Flags & AUD_FLAG_STEREO) {\n\t\ttime >>= 1;\n\t}\n\n\tif (RawHeader.Rate/60) {\n\t\ttime /= (RawHeader.Rate/60);\n\t}\n\treturn(time);\n}\n"
  },
  {
    "path": "WWFLAT32/AUDIO/SOUNDLCK.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDLCK.CPP                             *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 23, 1995   [PWG]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <dos.h>\n#include <mem.h>\n#include \"soundint.h\"\n#include \"wwmem.h\"\n\nLockedDataType LockedData;\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * INIT_LOCKED_DATA -- Initializes sound driver locked data                *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid Init_Locked_Data(void)\n{\n\t/*\n\t** Initialize all of the data elements that need to be locked.\n\t*/\n\tLockedData.DigiHandle\t\t\t= -1;\n\tLockedData.ServiceSomething\t= FALSE;\n\tLockedData.MagicNumber\t\t\t= 0xDEAF;\n\tLockedData.UncompBuffer\t\t\t= NULL;\n\tLockedData.StreamBufferSize\t= (2*SFX_MINI_STAGE_BUFFER_SIZE)+128;\n\tLockedData.StreamBufferCount\t= 32;\n\tLockedData.SoundVolume\t\t\t= 255;\n\tLockedData.ScoreVolume\t\t\t= 255;\n\tLockedData._int\t\t\t\t\t= FALSE;\n\tLockedData.MaxSamples\t\t\t= MAX_SFX;\n\n\t/*\n\t** Lock the sound specific c functions that will cause us problems if\n\t** they are swapped out during an interrupt.\n\t*/\n\tDPMI_Lock(&LockedData,\t\t\t\t\t\t\t4096L);\n\tDPMI_Lock(Simple_Copy, \t\t\t\t\t\t\t4096L);\n\tDPMI_Lock(Sample_Copy, \t\t\t\t\t\t\t4096L);\n\tDPMI_Lock((void *)maintenance_callback, \t4096L);\n\tDPMI_Lock((void *)DigiCallback, \t\t\t\t4096L);\n\tDPMI_Lock((void *)HMI_TimerCallback, \t\t4096L);\n\tDPMI_Lock(Audio_Add_Long_To_Pointer,\t\t4096L);\n\tDPMI_Lock(DPMI_Unlock,\t\t\t\t\t\t\t4096L);\n\n\t/*\n\t** Lock the library functions that will cause us problems if they are\n\t** swapped out during an interrupt.\n\t*/\n\tDPMI_Lock(Mem_Copy,\t\t\t\t\t\t\t\t4096L);\n\tDPMI_Lock(Audio_Mem_Set,\t\t\t\t\t\t4096L);\n\tDPMI_Lock(__GETDS,\t\t\t\t\t\t\t\t4096L);\n\n\t/*\n\t** Finally lock the two assembly modules that need locking.  This can\n\t** be handled by calling the lock function that is local to thier module\n\t** swapped out during an interrupt.\n\t*/\n\tDecompress_Frame_Lock();\n\tsosCODEC_Lock();\n}\n\nvoid Unlock_Locked_Data(void)\n{\n\t/*\n\t** Lock the sound specific c functions that will cause us problems if\n\t** they are swapped out during an interrupt.\n\t*/\n\tDPMI_Unlock(&LockedData,\t\t\t\t\t\t4096L);\n\tDPMI_Unlock(Simple_Copy, \t\t\t\t\t\t4096L);\n\tDPMI_Unlock(Sample_Copy, \t\t\t\t\t\t4096L);\n\tDPMI_Unlock((void *)maintenance_callback, 4096L);\n\tDPMI_Unlock((void *)DigiCallback, \t\t\t4096L);\n\tDPMI_Unlock((void *)HMI_TimerCallback,\t\t4096L);\n\tDPMI_Unlock(Audio_Add_Long_To_Pointer,\t\t4096L);\n\n\t/*\n\t** Lock the library functions that will cause us problems if they are\n\t** swapped out during an interrupt.\n\t*/\n\tDPMI_Unlock(Mem_Copy,\t\t\t\t\t\t\t4096L);\n\tDPMI_Unlock(Audio_Mem_Set,\t\t\t\t\t\t4096L);\n\tDPMI_Unlock(__GETDS,\t\t\t\t\t\t\t\t4096L);\n\t/*\n\t** Finally unlock the two assembly modules that need locking.  This can\n\t** be handled by calling the lock function that is local to thier module\n\t** swapped out during an interrupt.\n\t*/\n\tDecompress_Frame_Unlock();\n\tsosCODEC_Unlock();\n\n\t/*\n\t** As a last step go though all of the sample tracker structures and make\n\t** sure all the samples have been properly unlocked.\n\t*/\n\tfor (int id = 0; id < LockedData.MaxSamples; id++) {\n\t\tif (LockedData.SampleTracker[id].Original && !LockedData.SampleTracker[id].IsScore) {\n\t\t\tDPMI_Unlock(LockedData.SampleTracker[id].Original, LockedData.SampleTracker[id].OriginalSize);\n\t\t\tLockedData.SampleTracker[id].Original = NULL;\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "WWFLAT32/DESCMGMT/DESCMGMT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Descriptor management                    *\n *                                                                         *\n *                    File Name : DESCMGMT.CPP                             *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : March 28, 1994                           *\n *                                                                         *\n *                  Last Update : March 28, 1994   []                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * MAP_SEGMENT_TO_ADDRESS -- Maps a physical address into a selector       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"descmgmt.h\"\n#include \"misc.h\"\n\n\n/***************************************************************************\n * MAP_SEGMENT_TO_ADDRESS -- Maps a physical address into a selector       *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT: selector UWORD The selector mapped to address. exit on error.   *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/25/1994  jaw: Created.                                             *\n *=========================================================================*/\n\nULONG Map_Segment_To_Address(ULONG address, ULONG length)\n{\t\t\t\t\t\t\t \t\t\t\t\n\n// this function is not longer needed by RATIONAL SYSTEM DOS4GW\n// linear addressing mode.\n// a> the first megabyte of memory is mapped to linear adress 0 - 0x10000h\n// b> all other addresses are linear offset from either ds: or es:\n\n/*\n\tUWORD segment;\n\tUWORD curDS;\n\tCD_DES desc;\n\tCD_DES cur_desc;\n\n\t// allocate a selector\n\tif(_dos_allocmem(0, &segment) != 0) {\n\t\tExit(1, \"Allocation of Descriptor.\\n\");\n\t}\n\n\t// get the data for this selector\n\tif(_dx_ldt_rd(segment, (UCHAR *)&desc) != 0) {\n\t\tExit(1, \"Reading Descriptor.\\n\");\n\t}\n\n\t// get the data for current data segment\n\tcurDS = GetDs();\n\tif(_dx_ldt_rd(curDS, (UCHAR *)&cur_desc) != 0) {\n\t\tExit(1, \"Reading Descriptor.\\n\");\n\t}\n\t\n\t// set limit\n\tdesc.limit0_15 \t\t= (USHORT)(length & 0xffff);\n\tdesc.limit16_19 \t= ((UCHAR)(length >> 16L)) | DOS_32;\n\n\t// set base address\n\tdesc.base0_15 \t\t= (USHORT)(address & 0xffff);\n\tdesc.base16_23\t\t= (UCHAR)((address >> 16) & 0xff);\n\tdesc.base24_31\t\t= (UCHAR)((address >> 24) & 0xff);\n\n\t// set rights mark as icurrent data segment\n\tdesc.arights \t\t= cur_desc.arights;\n\t\t\t\t\t\t\t \n\t// write to LDT selector\n\tif(_dx_ldt_wr(segment, (UCHAR *)&desc) != 0) {\n\t\tExit(1, \"Failed writing descriptor.\\n\");\n\t}\n\n\t// return selector number\n\treturn segment;\n */\n\n       if ( address & 0xfff0ffff ) \n\t    Exit ( 1 , \"Error mapping real address to lineal address.\\n\" ) ;\n\n       return address ;\n}\n\n"
  },
  {
    "path": "WWFLAT32/DESCMGMT/DESCMGMT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 library                          *\n *                                                                         *\n *                    File Name : DESCMGMT.H                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef DESCMGMT_H\n#define DESCMGMT_H\n\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n//=====================================================================\n// C type include files\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <dos.h>\n#include <bios.h>\n\n#ifdef __cplusplus\n}\n#endif\n\n// ====================================================================\n\n\n// types\n// These where taken from dos.h\n//==========================================\n\n// external functions\n// ===================================================\nextern ULONG Map_Segment_To_Address(ULONG address, ULONG length);\n\nextern \"C\" {\n\t// Assemble functions\n\textern UWORD FixSelector(UWORD sel);\n\textern UWORD GetDs(void);\n\textern UWORD GetCs(void);\n\textern VOID  GetDefaultSelectors(VOID);\n\textern UWORD Get_Standard_Selector(void);\n\n\t\n\t// Assembly data variables\n\textern UWORD CodeSelector;\n\textern UWORD DataSelector;\n\textern UWORD ScreenSelector;\n\textern UWORD GraphicsSelector;\n\textern UWORD PspSelector;\n\textern UWORD EnvSelector;\n\textern UWORD DosMemSelector;\n\textern UWORD Fp1167Selector;\n\textern UWORD FpWeitekSelector;\n\textern UWORD FpCyrixSelector;\n}\n\n#endif  // DESCMGMT_H\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/DESCMGMT/FFIXSEL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Fix a selector                           *\n;*                                                                         *\n;*                    File Name : FFIXSEL.ASM                              *\n;*                                                                         *\n;*                   Programmer : Jeff Wilson                              *\n;*                                                                         *\n;*                   Start Date : March 28, 1994                           *\n;*                                                                         *\n;*                  Last Update : March 28, 1994   []                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   FixSelector -- Fix the Priviledge level of a selector                 *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nEXTRN\t\t   exit\t\t\t: near\nGLOBAL             FixSelector          :NEAR\n\n;============================================================================\nCODESEG\n\n;***************************************************************************\n;* FIXSELECTOR -- Fix the Priviledge level of a selector                   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:  sel          the selector to fix-up                             *\n;*                                                                         *\n;* OUTPUT: UWORD        The fixed up selector                              *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/28/1994  jaw  Created.                                             *\n;*=========================================================================*\n\nPROC FixSelector \tC near \n\n\tUSES ecx,edx\n\t      \n\tARG\tsel:WORD\n\t\t\n;  Copy the Table Bit and IOPL from the Current CS\n\n; Something is wrong the program should not be here unthe any circunstance\t\n;\tmovzx\tecx,[sel]\n;\txor\teax,eax\n;\tmov\tax,cs\n;\tand\tax,7\n;\tor\tax,cx\npush 0\ncall exit\n\t\n\tret\n;====================\nENDP FixSelector\t\n\n\n\nEND\n\n\n\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/DESCMGMT/FGETCS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Get the code selector                    *\n;*                                                                         *\n;*                    File Name : FGETCS.ASM                               *\n;*                                                                         *\n;*                   Programmer : Jeff Wilson                              *\n;*                                                                         *\n;*                   Start Date : March 28, 1994                           *\n;*                                                                         *\n;*                  Last Update : March 28, 1994   []                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   GetCs -- Return the current Data selector.                            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nGLOBAL             GetCs          :NEAR\n\t\t       \n;============================================================================\nCODESEG\n\n;***************************************************************************\n;* GETCS -- Return the current Data selector.                              *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT: NONE                                                             *\n;*                                                                         *\n;* OUTPUT: UWORD        selector of the default code segment               *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/28/1994  jaw: Created.                                             *\n;*=========================================================================*\n\nPROC GetCs \tC near \n     \t\n\txor\teax,eax\n\tmov\tax,cs\n\tret\t   \n;====================\nENDP GetCs\t\n\t\n\nEND\n\n\n\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/DESCMGMT/FGETDS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Get the data selector                    *\n;*                                                                         *\n;*                    File Name : FGETDS.ASM                               *\n;*                                                                         *\n;*                   Programmer : Jeff Wilson                              *\n;*                                                                         *\n;*                   Start Date : March 28, 1994                           *\n;*                                                                         *\n;*                  Last Update : March 28, 1994   []                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   GetDs -- Return the current Data selector.                            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nGLOBAL             GetDs          :NEAR\n\t\t    \n;============================================================================\nCODESEG\n\n;***************************************************************************\n;* GETDS -- Return the current Data selector.                              *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT: NONE                                                             *\n;*                                                                         *\n;* OUTPUT: UWORD        selector of the default data segment               *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/28/1994  jaw: Created.                                             *\n;*=========================================================================*\n\nPROC GetDs \tC near \n     \n\txor\teax,eax\n\tmov\tax,ds\n\tret\n;====================\nENDP GetDs\t\n\n\nEND\n\n\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/DESCMGMT/FGETSEL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Get the Defines selectors\t\t   *\n;*                                                                         *\n;*                    File Name : FGETSEL.ASM                              *\n;*                                                                         *\n;*                   Programmer : Jeff Wilson                              *\n;*                                                                         *\n;*                   Start Date : March 28, 1994                           *\n;*                                                                         *\n;*                  Last Update : March 28, 1994   []                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   GetDefaultSelectors -- Return the current default selectors. \t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nGLOBAL      GetDefaultSelectors :NEAR\n\nGLOBAL \t    DataSelector\t:WORD\nGLOBAL \t    ScreenSelector\t:WORD\nGLOBAL \t    GraphicsSelector\t:WORD\nGLOBAL \t    PspSelector\t\t:WORD\nGLOBAL \t    EnvSelector\t\t:WORD\nGLOBAL \t    DosMemSelector\t:WORD\nGLOBAL \t    Fp1167Selector\t:WORD\nGLOBAL \t    FpWeitekSelector\t:WORD\nGLOBAL \t    FpCyrixSelector\t:WORD\nGLOBAL \t    CodeSelector\t:WORD\n\n\nDATASEG\n\n; It is very important that this section remain untouch\n; is not really needed by Rational System but is here to\n; keep compatibility with the TNT dos extender.\nDataSelector\t\tdw\t0\nScreenSelector\t\tdw\t0\nGraphicsSelector\tdw\t0\n\nPspSelector\t\tdw\t0\nEnvSelector\t\tdw\t0\nDosMemSelector\t\tdw\t0\n\nFp1167Selector\t\tdw\t0\nFpWeitekSelector\tdw\t0\nFpCyrixSelector\t\tdw\t0\n\nCodeSelector\t\tdw\t0\n\n\t\t    \n;============================================================================\nCODESEG\n\n;***************************************************************************\n;*  GetDefaultSelectors -- Setup the defaults selector values to have the  *\n;*    Correct Descriptor table and IOPL.\t\t\t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT: NONE                                                             *\n;*                                                                         *\n;* OUTPUT: \t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/28/1994  jaw: Created.                                             *\n;*=========================================================================*\n\nPROC GetDefaultSelectors \tC near \n\tUSES eax,esi,ecx\n\n\tlea\tedi,[DataSelector]\n\tlea\tecx,[CodeSelector]\n \tsub\tecx,edi\n\tshr\tecx,1\n\tmov\tax,ds\n\trep\tstosw\n\tmov\tax,cs\n\tmov\t[word ptr CodeSelector] , ax\n     \n\tret\t   \n;====================\nENDP GetDefaultSelectors\t\n     \n\nEND\n\n\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/DESCMGMT/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : jan 24, 1994                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* \t\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = descmgmt\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_PATH    = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = &\n\t  descmgmt.obj &\n\t  fgetsel.obj &\n\t  fgetcs.obj &\n\t  fgetds.obj &\n\t  ffixsel.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_PATH)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_PATH)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WWFLAT32/DIPTHONG/DIPTHONG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./dipthong.c 1.15 1994/05/20 15:35:17 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : DIPTHONG.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : February 23, 1992                        *\n *                                                                         *\n *                  Last Update : February 13, 1995 [BWG]                  *\n *                                                                         *\n * DIGRAM or DIATOMIC encoding is the correct term for this method.        *\n * This is a fixed dictionary digram encoding optimized for English text.  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Extract_String -- Extracts a string pointer from a string data block. *\n *   UnDip_Text -- Undipthongs a text string into specified buffer.        *\n *   Dip_Text -- Compresses text by using dipthonging.                     *\n *   Fixup_Text -- Converts dipthonged foreign text into normal text.      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n//#include\t\"function.h\"\n//#include\t\"ems.h\"\n#include <keyboard.h>\n#include \"dipthong.h\"\n\n/***************************************************************************\n * Fixup_Text -- Converts dipthonged foreign text into normal text.        *\n *                                                                         *\n *    Takes text that has been processed (or undipped) to hold foriegn     *\n *    language character pairs (needed for Window_Print) and converts it   *\n *    so that Text_Print will print it properly.  Typically this would be  *\n *    used after text has been undipped but before it will be Text_Printed.*\n *    Text that is to be Window_Printed doesn't and mustn't have its text  *\n *    processed by this routine.                                           *\n *                                                                         *\n * INPUT:   source   -- Pointer to the source string to process.           *\n *                                                                         *\n *          dest     -- Destination buffer to hold the processed string.   *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine will only reduce the size of the string if it  *\n *             modifies it at all.  Because of this it is quite legal to   *\n *             pass the same pointers to this routine so that it will      *\n *             modify the string \"in place\".                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/13/1993 JLB : Created.                                             *\n *   10/06/1994 JLB : Handles source string in EMS.                        *\n *=========================================================================*/\nvoid Fixup_Text(char const *source, char *dest)\n{\n\tif (source && dest) {\n\t\tchar const *src;\n\n\t\tsrc = source;\n\t\twhile (*src) {\n\t\t\tif (*src == KA_EXTEND) {\n\t\t\t\tsrc++;\n\t\t\t\t*dest++ = (*src++) + 127;\n\t\t\t} else {\n\t\t\t\t*dest++ = *src++;\n\t\t\t}\n\t\t}\n\t\t*dest = '\\0';\n\n\t}\n}\n\n\n/***************************************************************************\n * Dip_Text -- Compresses text by using dipthonging.                       *\n *                                                                         *\n *    This routine is used to compress text by using dipthonging.  Text    *\n *    that is compressed in this fashion usually is reduced in size by     *\n *    approximately 40%.                                                   *\n *                                                                         *\n * INPUT:   source   -- Pointer to the source string to compress.          *\n *                                                                         *\n *          dest     -- Pointer to the buffer that will hold the dipthong  *\n *                      text output.                                       *\n *                                                                         *\n * OUTPUT:  Returns the number of bytes output into the output buffer.     *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/13/1993 JLB : Created.                                             *\n *=========================================================================*/\nint Dip_Text(char const *source, char *dest)\n{\n\tunsigned char\tfirst,\t\t// First character in pair.\n\t\t\t\t\t\tnext;\t\t\t// Second character in pair.\n\tint\tlen;\t\t\t// Length of output string.\n\tint\tcommon,\t\t// Common character index.\n\t\t\tdipthong;\t// Dipthong character index.\n\n\tlen = 0;\t\t\t\t\t// No output characters YET.\n\n\tfirst = *source++;\n\tnext = *source;\n\twhile (first) {\n\n\t\tif (first > 127) {\n\n\t\t\t/*\n\t\t\t**\tCharacters greater than 127 cannot be dipthonged.  They must\n\t\t\t**\tbe preceeded with an extended character code.\n\t\t\t*/\n\t\t\t*dest++ = KA_EXTEND;\n\t\t\tlen++;\n\t\t\tfirst -= 127;\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tNormal characters can be dipthonged.  First see if there is a\n\t\t\t**\tmatch in the Common table.\n\t\t\t*/\n\t\t\tfor (common = 0; common < 16; common++) {\n\t\t\t\tif (Common[common] == first) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCommon character found.  See if there is a matching\n\t\t\t\t\t**\tDipthong character.\n\t\t\t\t\t*/\n\t\t\t\t\tfor (dipthong = 0; dipthong < 8; dipthong++) {\n\t\t\t\t\t\tif (Dipthong[common][dipthong] == next) {\n\t\t\t\t\t\t\tfirst = (unsigned char)(common << 3) | (unsigned char)dipthong | 0x80;\n\t\t\t\t\t\t\tsource++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tOutput the translated character to the destination buffer.\n\t\t*/\n\t\t*dest++ = first;\n\t\tlen++;\n\n\t\tfirst = *source++;\n\t\tnext = *source;\n\t}\n\n\t*dest = '\\0';\n\t\n\treturn(len);\n}\n\n\n/***************************************************************************\n * UnDip_Text -- Undipthongs a text string into specified buffer.          *\n *                                                                         *\n *    This routine is used to undipthong a text string and place the       *\n *    undipped text into the buffer specified.  Since dipthonged text is   *\n *    compressed, in order for the text to be used it must be undipped     *\n *    first.                                                               *\n *                                                                         *\n * INPUT:   source   -- Pointer to the dipped string.                      *\n *                                                                         *\n *          dest     -- Pointer to the destination buffer.                 *\n *                                                                         *\n * OUTPUT:  Returns the number of bytes placed into the destination        *\n *          buffer.                                                        *\n *                                                                         *\n * WARNINGS:   Be sure the destination buffer is big enough to hold the    *\n *             undipped text.                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/13/1993 JLB : Created.                                             *\n *   10/06/1994 JLB : Handles source string in EMS.                        *\n *=========================================================================*/\nint UnDip_Text(char const *source, char *dest)\n{\n\tint\tc;\t\t\t// Source input character.\n\tint\tcommon;\t// Common character index.\n\tint\tlen;\t\t// Length of output string.\n\tchar const *src;\n\n\tlen = 0;\t\t\t\t\t\t// Presume no translation.\n\n\t/*\n\t**\tSweep through the source text and dipthong it.\n\t*/\n\tsrc = source;\n\tc = *src++;\n\twhile (c) {\n\t\t\n\t\t/*\n\t\t**\tConvert a dipthong character into it's component\n\t\t**\tASCII characters.\n\t\t*/\n\t\tif (c & 0x80) {\n\t\t\tc &= 0x7F;\n\n\t\t\tcommon = (c & 0x78) >> 3;\n\n\t\t\t*dest++ = Common[common];\n\t\t\tlen++;\n\n\t\t\tc = Dipthong[common][c & 0x07];\n\t\t}\n\n\t\t*dest++ = (unsigned char)c;\n\t\tlen++;\n\n\t\tc = *src++;\n\t}\n\n\t/*\n\t**\tEnd the output text with a '\\0'.\n\t*/\n\t*dest++ = '\\0';\n\n\treturn(len);\n}\n\n\n/***************************************************************************\n * Extract_String -- Extracts a string pointer from a string data block.   *\n *                                                                         *\n *    This routine is used to find a pointer to the specified string       *\n *    inside a string block.  String data blocks are created with the      *\n *    TEXTMAKE utility.  The data block my reside in XMS or EMS memory,    *\n *    but of course the returned string pointer will also point to         *\n *    such memory.  In this case, the string must be placed in real        *\n *    memory before it can be used.                                        *\n *                                                                         *\n * INPUT:   data     -- Pointer to the string data block.                  *\n *                                                                         *\n *          string   -- The string number to extract (if < 0 then NULL     *\n *                      is returned).                                      *\n *                                                                         *\n * OUTPUT:  Returns with pointer to the string number specified.           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/13/1993 JLB : Created.                                             *\n *   08/13/1993 JLB : Handles EMS or XMS data pointer.                     *\n *=========================================================================*/\nchar *Extract_String(void const *data, int string)\n{\n\tunsigned short int\tconst *ptr;\n\tunsigned int\toffset;\n\n\tif (!data || string < 0) return(NULL);\n\t\t\n\tptr = (unsigned short int const *)data;\n\treturn (((char*)data) + ptr[string]);\n}\n"
  },
  {
    "path": "WWFLAT32/DIPTHONG/DIPTHONG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\nint Dip_Text(char const *source, char *dest);\nint UnDip_Text(char const *source, char *dest);\nchar *Extract_String(void const *data, int string);\nvoid Fixup_Text(char const *source, char *dest);\nextern char Common[];\nextern char Dipthong[16][8];\n"
  },
  {
    "path": "WWFLAT32/DIPTHONG/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : jan 24, 1995                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = dipthong\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tdipthong.obj\t&\n\t_diptabl.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\tmkdir run\n\tcd run\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\run\\vcs.cfg\n\tupdate\n\tcd..\n\tmkdir art\n\tcd art\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\art\\vcs.cfg\n\tupdate\n\tcd..\n\twmake \n\tcd ..\n\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/DIPTHONG/_DIPTABL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./_diptabl.c 1.11 1994/05/20 15:36:04 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : _DIPTABL.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : July 3, 1991                             *\n *                                                                         *\n *                  Last Update : July 3, 1991   [JLB]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nchar Common[16]={' ','e','t','a','i','n','o','s','r','l','h','c','d','u','p','m'};\n\nchar Dipthong[16][8]={\n\t{'t','a','s','i','o',' ','w','b'},\n\t{' ','r','n','s','d','a','l','m'},\n\t{'h',' ','i','e','o','r','a','s'},\n\t{'n','r','t','l','c',' ','s','y'},\n\t{'n','s','t','c','l','o','e','r'},\n\t{' ','d','t','g','e','s','i','o'},\n\t{'n','r',' ','u','f','m','s','w'},\n\t{' ','t','e','p','.','i','c','a'},\n\t{'e',' ','o','i','a','d','u','r'},\n\t{' ','l','a','e','i','y','o','d'},\n\t{'e','i','a',' ','o','t','r','u'},\n\t{'e','t','o','a','k','h','l','r'},\n\t{' ','e','i','u',',','.','o','a'},\n\t{'n','s','r','c','t','l','a','i'},\n\t{'l','e','o','i','r','a','t','p'},\n\t{'e','a','o','i','p',' ','b','m'},\n};\n\u001a"
  },
  {
    "path": "WWFLAT32/EXAMPLE/DEFINES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 Example                          *\n *                                                                         *\n *                    File Name : DEFINES.H                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\n#define USER_TIMER_FREQ\t\t60\n"
  },
  {
    "path": "WWFLAT32/EXAMPLE/EXTERNS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 Example                          *\n *                                                                         *\n *                    File Name : EXTERNS.H                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\nextern char\tNoTimer;\nextern char\tNoKeyBoard;\n"
  },
  {
    "path": "WWFLAT32/EXAMPLE/FUNCTION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 Example                          *\n *                                                                         *\n *                    File Name : FUNCTION.H                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwlib32.h\"\n#include \"defines.h\"\n#include \"structs.h\"\n#include\t\"externs.h\"\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MAIN.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern WORD Main_Program(WORD argc, BYTE *argv[]);\n\n\n/*=========================================================================*/\n"
  },
  {
    "path": "WWFLAT32/EXAMPLE/GLOBALS.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 Examples                         *\n *                                                                         *\n *                    File Name : GLOBALS.CPP                              *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\nchar\tNoTimer;\nchar\tNoKeyBoard;\n"
  },
  {
    "path": "WWFLAT32/EXAMPLE/MAIN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : libtest                                  *\n *                                                                         *\n *                    File Name : LIBTEST.CPP                              *\n *                                                                         *\n *                   Programmer : Jeff Wilson                            \t*\n *                                                                         *\n *                   Start Date : April 27, 1994                           *\n *                                                                         *\n *                  Last Update : May 3, 1994   [BR]                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Main_Program -- user-defined main routine, called from startup.c      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include \"function.h\"\n\n\n/***************************************************************************\n * Main_Program -- user-defined main routine, called from startup.c        *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tWORD argc\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tUBYTE *argv[]\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tReturns: TRUE\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1994 BR : Created.                                              *\n *=========================================================================*/\n#pragma argsused\nWORD Main_Program(WORD argc, BYTE *argv[])\n{\t  \t\t\t     \n\treturn (TRUE);\t\t\t  \n}\n\n\n//////////////////////////////////// End of File /////////////////////////////////////\n"
  },
  {
    "path": "WWFLAT32/EXAMPLE/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .EXE makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 20, 1995  \t                   *\n#*                                                                         *\n#*                  Last Update : \t\t\t                   *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*                                                                         *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the executable program you're building \t   *\n#* PROJ_LIBS\t= Westwood libraries to link your EXE to \t           *\n#* OBJECTS\t= list of objects in your current working directory\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .xxx:\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n#---------------------------------------------------------------------------\n# PROJ_NAME = library name\n# PROJ_DIR = directory containing source & objects\n#---------------------------------------------------------------------------\nPROJ_NAME\t= TEST\nPROJ_DIR\t= $(%WWFLAT)\\example\\TEST\nLIB_DIR\t        = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t   \t&\n\tmain.obj\t\t&\n\tstartup.obj\t\t&\n\tglobals.obj\n\nPROJ_LIBS = \t\t\t&\n\t    wwflat32.lib\n\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t $(PROJ_DIR)\n.c:   \t $(PROJ_DIR)\n.cpp:\t $(PROJ_DIR)\n.h:   \t $(PROJ_DIR)\n.obj:\t $(PROJ_DIR)\n.lib:\t $(%WWFLAT)\\lib\n.exe:\t $(PROJ_DIR)\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n# If LIB & INCLUDE are already defined, they are used in addition to the\n# WWLIB32 lib & include; otherwise, they're constructed from\n# BCDIR \n#---------------------------------------------------------------------------\n\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(PROJ_NAME).exe \n\n#---------------------------------------------------------------------------\n# Build the EXE\n#---------------------------------------------------------------------------\n$(PROJ_NAME).exe: $(OBJECTS)  $(PROJ_NAME).lnk $(PROJ_LIBS)\n\t $(LINK_CMD) $(LINK_CFG) system dos4g name $^@ @$(PROJ_NAME).lnk\n\n\n$(PROJ_LIBS):\t\t\n\techo updating base library $^@\n\tcd ..\n\twmake\n\tcd $(PROJ_DIR)\n\n\n$(PROJ_NAME).lnk : $(OBJECTS)\n       %create $^@\n       for %index in ($(OBJECTS))  do %append $^@ file %index\n       for %index in ($(PROJ_LIBS)) do %append $^@ library $(LIB_DIR)\\%index\n\n#**************************** End of makefile ******************************\n\n\n"
  },
  {
    "path": "WWFLAT32/EXAMPLE/STARTUP.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library startup routine.\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : STARTUP.CPP                              *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : July 14, 1994                            *\n *                                                                         *\n *                  Last Update : August 1, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Prog_End -- Called to shutdown Westood's library.                     *\n *   main -- Programs main entry point.                                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include <stdio.h>\n#include <stdlib.h>\n\n#define\tGRAPHICS\t\tTRUE\nvoid *ShapeBuffer = NULL;\n\n\n/***************************************************************************\n * MAIN -- Programs main entry point.                                      *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/01/1994 SKB : Created.                                             *\n *=========================================================================*/\n#pragma argsused\nWORD main(WORD argc, BYTE *argv[])\n{\n\tvoid *fontptr;\n\n\t/*======================================================================*/\n\t/* Install page fault handle in case of fatal crash.\t\t\t\t\t\t   */\n\t/*======================================================================*/\n\t  Install_Page_Fault_Handle ();\n\n\t/*======================================================================*/\n\t/* Setup the monochrome monitor for testing.\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\n\tMonoEnabled = (Find_Argv(\"-MONO\") ? TRUE : FALSE);\n\tMono_Clear_Screen();\n\n\t/*======================================================================*/\n\t/* Initialize the file data table.\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tWWDOS_Init(200, NULL, NULL);\n\n\t/*======================================================================*/\n\t/* Initialize the system font.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n#if GRAPHICS\n\tfontptr = Load_Font(\"STD6P.FNT\");\n\tif (!fontptr)  {\n\t\tprintf(\"Unable to load font.\");\n\t\texit(1);\n\t}\n\tSet_Font(fontptr);\n#endif\n\n\t/*======================================================================*/\n\t/* Setup the timer system.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (Find_Argv(\"-NOTIME\"))  {\n\t\tNoTimer = TRUE;\n\t} else {\n\t\tInit_Timer_System(USER_TIMER_FREQ);\n\t\tNoTimer = FALSE;\n\t}\n\n\t/*======================================================================*/\n\t/* Get the initial graphic mode.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n#if GRAPHICS\n\t if ( Set_Video_Mode(MCGA_MODE) == FALSE ) \n\t {\n\t\tprintf(\"Unable to Set Graphic Mode\\n\");\n\t\texit ( 0 ) ;\n\t }\n#endif\n\n\n\t/*======================================================================*/\n\t/* Now we get a keyboard handler.\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (Find_Argv(\"-NOKEY\")) {\n\t\tNoKeyBoard = TRUE;\n\t} else {\n\t\tNoKeyBoard = FALSE;\n\t\tInstall_Keyboard_Interrupt(\tGet_RM_Keyboard_Address(),\tGet_RM_Keyboard_Size());\n\n\t\tShapeBuffer = Alloc(5000, MEM_NORMAL);\n\t\tSet_Shape_Buffer(ShapeBuffer, 5000);\n\t\tInstall_Mouse(20, 20, 320, 200);\n\t}\n\n\t/*======================================================================*/\n\t/* Give the game some variance.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\trandomize();\n\n\t/*======================================================================*/\n\t/* Call the user main program.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tMain_Program(argc, argv);\n\n\t/*======================================================================*/\n\t/* Exit gracefully.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tProg_End();\n\n\treturn(0);\n}\n\n\n\n/***************************************************************************\n * PROG_END -- Called to shutdown Westood's library.                       *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:  exit() should not be called until this has been called       *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/01/1994 SKB : Created.                                             *\n *=========================================================================*/\nVOID Prog_End(VOID)\n{\n\t\n\t/*======================================================================*/\n\t/* Get rid of the keyboard handler.\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (!NoKeyBoard) {\n\t\tRemove_Mouse();\n\t\tFree(ShapeBuffer);\n\t\tRemove_Keyboard_Interrupt();\n\t}\n\n\t/*======================================================================*/\n\t/* Get rid of the timer system.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (!NoTimer)  {\n\t\tRemove_Timer_System();\n\t}\n\n\t/*======================================================================*/\n\t/* Restore the Video mode.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n#if GRAPHICS\n\tSet_Video_Mode(RESET_MODE);\n#endif\n\n\t/*======================================================================*/\n\t/* Close down the file system.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tWWDOS_Shutdown();\n}\n"
  },
  {
    "path": "WWFLAT32/EXAMPLE/STRUCTS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 Examples                         *\n *                                                                         *\n *                    File Name : STRUCTS.H                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n"
  },
  {
    "path": "WWFLAT32/EXAMPLE/WWLIB32.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 User include file                *\n *                                                                         *\n *                    File Name : WWLIB32.H                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWLIB32_H\n#define WWLIB32_H\n\n#include <wwstd.h>\n\n#include <buffer.h>\n#include <descmgmt.h>\n#include <file.h>\n#include <font.h>\n#include <gbuffer.h>\n#include <vbuffer.h>\n#include <iff.h>\n#include <filepcx.h>\n#include <keyboard.h>\n#include <mcgaprim.h>\n#include <misc.h>\n#include <mono.h>\n#include <palette.h>\n#include <playcd.h>\n#include <shape.h>\n#include <timer.h>\n#include <video.h>\n#include <wsa.h>\n#include <wwmem.h>\n\n\n\n#endif // WWLIB32_H\n"
  },
  {
    "path": "WWFLAT32/FILE/DEVICES.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/system/rcs/devices.asm 1.2 1994/04/28 12:41:41 jeff_wilson Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : DEVICES.ASM                              *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : 12 December, 1990   [CY]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n; VOID Get_Devices(VOID);                                                  *\n; WORD Is_Device_Real(WORD drive);                                         *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\n;----------------------------------------------------------------------------\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL  \t    Get_Devices          :NEAR\nGLOBAL              Is_Device_Real       :NEAR\n\nGLOBAL              MaxDevice          \t :BYTE\nGLOBAL              DefaultDrive         :BYTE\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; VOID Get_Devices(VOID);\n; WORD Is_Device_Real(WORD drive);\n;\n; ----------------------------------------------------------------\n\nCODESEG\n\n;***********************************************************\n;\n; GET_DEVICES\n;\n; VOID Get_Devices(VOID);\n;\n; This routine establishes the default disk drive and the maximum drive\n; available in the current system.\n;\n;*\nDOS\tequ\t21h\n\nPROC\tGet_Devices C near \n\tUSES eax,ebx,edx\n\t\t   \n   \tsub\teax,eax\n\tmov\tah,25\t\t\t; get current drive service\n\tint\tDOS\t\t\t; drive returned in al\n\tmov\t[DefaultDrive],al\t; save it\n\tmov\tdl,al\n\tmov\tah,14\t\t\t; set current as current drive\n\tint\tDOS\n\tdec\tal\t\t\t; al = max drives, make it n - 1\n\txor\tah,ah\t\t\t; clear high byte\n\tmov\tedx,eax\t\t\t; use dx to go backward to find out\n\tsub\tebx,ebx\n\n??back_loop:\n\tmov\tbl,dl\t\t\t; find out about the drive in dl\n\tinc\tbl\n\tmov\teax,0440Eh \t\t; get the physical drive associated\n\tint\tDOS\t\t\t; with this letter\n\tjnc\tshort ??later\t\t; if c clear, no error\n\tcmp\tal,0Fh\t\t\t; was it invalid? (0Fh = invalid)\n\tjne\tshort ??later\t\t; yes, so LATER\n\tdec\tedx\n\tjmp\t??back_loop\t\t; try, try again\n\n??later:\n\tmov\teax,edx\t\t\t; restore ax\n\tmov\t[MaxDevice],al\t\t; save the max drive #\n\n\tret\n\nENDP\tGet_Devices\n\n;***************************************************************\n\n\n;***************************************************************\n;\n; IS_DEVICE_REAL\n;\n; WORD Is_Device_Real(WORD drive);\n;\n; This routine will tell whether or not a device is a true\n; phisical one.  Send it the drive # to check.\n;\n;*\nPROC\tIs_Device_Real C near \n\tUSES ebx,edx\n\tARG\tdrive:WORD\n\n\tsub\tedx,edx\n\tmov\tdx,[drive]\n\n??next_drive:\n\tpush\tebx\n\tmov\tbl,dl\t\t\t; find out about the drive in dl\n\tinc\tbl\n\tmov\teax,0440Eh \t\t; get the physical drive associated\n\tint\tDOS\t\t\t; with this letter\n\tpop\tebx\n\n\tjnc\tshort ??it_is_real\t; jump if no error\n\tcmp\tal,01\t\t\t; 1 = invalid command, \n\t\t\t\t\t; 0F = invalid device\n\tje\tshort ??real\t\t\t; 1? it is ok (RAM device)\n\tjmp\tshort ??invalid\t\t; 0Fh, it was not a device\n\n??it_is_real:\n\tcmp\tal,0\t\t\t; was it a fixed device?\n\tje\tshort ??real\t\t\t; yes, it's ok\n\tdec\tal\t\t\t; make it a drive #\n\tcmp\tal,dl\t\t\t; is it a valid drive?\n\tje\tshort ??real\n\n??invalid:\t\t\t\t; The device is invalid.\n\tmov\teax,0\n\tjmp\tshort ??out\t\t\t\n\n??real:\t\t\t\t\t; Return true, for valid device.\n\tmov\teax,1\n\t\t    \n??out:\n\tret\nENDP\tIs_Device_Real\n\n;***************************************************************\n\nEND\n\u001a"
  },
  {
    "path": "WWFLAT32/FILE/DEVTABLE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/system/rcs/devtable.asm 1.2 1994/04/28 12:41:29 jeff_wilson Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : DEVTABLE.ASM                             *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : 12 December, 1990   [CY]                 *\n;*                                                                         *\n;* Updated to 32bit protected mode JAW\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n; VOID Init_Device_Table(BYTE *table);                                     *\n; WORD Max_Device(VOID);\t\t\t\t\t\t   *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nLOCALS ??\n\nDOS\tequ\t21h\n\nGLOBAL\t Max_Device\t\t\t:NEAR\nGLOBAL\t get_max_device \t\t:NEAR\nGLOBAL\t Init_Device_Table\t\t:NEAR\n\t\t\t\t\t \n\nCODESEG\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; VOID Init_Device_Table(BYTE *table);\n; WORD Max_Device(VOID);\n;\n; ----------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n;\n; WORD Max_Device(VOID);\n;\n\nPROC\tMax_Device C NEAR\n\t\n\tcall\tget_max_device\t\t; get max devices in ax\n\tret\n\nENDP\tMax_Device\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n;\n;\n; returns max devices in AX\n\nPROC\tget_max_device C NEAR \n\tUSES ebx,edx\n\t\n\tmov\tah,25\t\t\t; get current drive service\n\tint\tDOS\t\t\t; drive returned in al\n\tmov\tdl,al\n\tmov\tah,14\t\t\t; set current as current drive\n\tint\tDOS\n\tdec\tal\t\t\t; al = max drives, make it n - 1\n\txor\tah,ah\t\t\t; clear high byte\n\tsub\tedx,edx\n\tmov\tedx,eax\t\t\t; use dx to go backward to find out\n\t\t\t\t\t; if DOS is lying (down)\n\n??back_loop:\n\tpush\tds\n\tpush\tebx\n\tmov\tbl,dl\t\t\t; find out about the drive in dl\n\tinc\tbl\n\tmov\teax,0440Eh \t\t; get the physical drive associated\n\tint\tDOS\t\t\t; with this letter\n\tpop\tebx\n\tpop\tds\n\tjnc\tshort ??later\t\t; if c clear, no error\n\t\n\tcmp\tal,0Fh\t\t\t; was it invalid? (0Fh = invalid)\n\tjne\tshort ??later\t\t\t; yes, so LATER\n\t\n\tdec\tedx\n\tjmp\t??back_loop\t\t; try, try again\n\n??later:\n\tmov\teax,edx\t\t\t; restore ax\n\tret\n\nENDP\tget_max_device\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n;\n; VOID Init_Device_Table(BYTE *table);\n;\n\nPROC\tInit_Device_Table C NEAR \n\n\tUSES eax,ebx,edi,edx\n\tARG\ttable:DWORD\t   \t; Pointer to device table.\n\tLOCAL\tcurr_drive:BYTE\t   \t; Copy of current drive number.\n\n\tmov\tedi,[table]\n\n\tcall\tget_max_device\t\t; get max devices in ax\n\tadd\tedi,eax\n\tstd\n\tmov\t[curr_drive],al\t; save it\n\n??next_drive:\n\tmov\tdl,[curr_drive]\t; copy current drive #\n\tcmp\tdl,0FFh\t\t\t; are we done?\n\tje\tshort ??later\t\t\t; if so, later\n\n\tdec\t[curr_drive]\t\t; dec our local drive #\n\n\tpush\tds\n\tpush\tebx\n\tmov\tbl,dl\t\t\t; find out about the drive in dl\n\tinc\tbl\n\tmov\teax,0440Eh \t\t; get the physical drive associated\n\tint\tDOS\t\t\t; with this letter\n\tpop\tebx\n\tpop\tds\n\n\tjnc\tshort ??it_is_real\t\t; jump if no error\n\tcmp\tal,01\t\t\t; 1 = invalid command, \n\t\t\t\t\t; 0F = invalid device\n\tje\tshort ??set_as_current\t; 1? it is ok (RAM device)\n\tjmp\tshort ??invalid\t\t; 0Fh, it was not a device\n\n\n??it_is_real:\n\tcmp\tal,0\t\t\t; was it a fixed device?\n\tje\tshort ??set_as_current\t; yes, it's ok\n\t\n\tdec\tal\t\t\t; make it a drive #\n\tcmp\tal,dl\t\t\t; is it a valid drive?\n\tje\tshort ??set_as_current\n\n;\n; Device was logical and not active, so clear the entry\n;\n??invalid:\n\txor\tal,al\n\tstosb\n\tcmp\t[curr_drive],0\t\t; are we done checking?\n\tjge\t??next_drive\t   \t; no, go to next\n\t\n\tjmp\tshort ??later\n\n??set_as_current:\n\tmov\tal,1\n\tstosb\n\tcmp\tdl,0\t\t\t; are we before the A drive (invalid)\n\tjl\tshort ??later\t\t\t; yes, we are done checking\n\t\n\tjmp\t??next_drive\t\t; keep processing\n\n??later:\n\tcld\n\tret\n\nENDP\tInit_Device_Table\n\n;----------------------------------------------------------------------------\n\nEND\n\u001a"
  },
  {
    "path": "WWFLAT32/FILE/FFIRST.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : First First\t\t\t\t   *\n;*                                                                         *\n;*                    File Name : FFIRST.ASM                               *\n;*                                                                         *\n;*                   Programmer : Jeff Wilson                              *\n;*                                                                         *\n;*                   Start Date : March 28, 1994                           *\n;*                                                                         *\n;*                  Last Update : April 15, 1994   []                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Find_First -- Find a file spec                                        *\n;*   Find_Next -- Find next file in sreach params                          *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nLOCALS ??\n\nGLOBAL             Find_First         :NEAR\nGLOBAL             Find_Next          :NEAR\n\t\t    \n;============================================================================\nCODESEG\n\n\n;***************************************************************************\n;* FIND_FIRST -- Find a file spec                                          *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*\tfile_name\t\tFile spec to find. Maybe a wildcard name   *\n;*      mode                    File type                                  *\n;*      ffblk                   file data block ptr to write info into     *\n;*                                                                         *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/15/1994  jaw: Created.                                             *\n;*=========================================================================*\n\nPROC Find_First \tC near \n     \tUSES ebx,ecx,edx,esi,edi,es,ds\n     \tARG file_name:DWORD,mode:WORD,ffblk:DWORD\n     \t   \n     \tmov\tedx,[file_name]\n     \tmov\tcx,[mode]\n     \t\t\n     \tmov\teax,4e00h\t\t;first firstg function\n     \t\n     \tint\t21h\n     \t\t\t\t\t;Find it?\n     \tjnc\t??found_it\t\t;=>yes\n     \t\n\t; ax holds the error code\n\t;insure high word of eax is clear\n\tor\teax,0ffffffffh\n\tjmp\t??exit\n\t\n??found_it:\n     \t; found something\n     \t;copy the DTA into the user block\n     \tmov\teax,2f00h\t;get DTA address\n     \tint\t21h\n     \t\n     \tmov\tax,es\t\t;switch selectors\n     \tmov\tdx,ds\n     \tmov\tds,ax\n     \tmov\tes,dx\n     \n     \tmov\tesi,ebx\n     \tmov\tedi,[ffblk]\n     \t\n\tadd\tesi,21\t\t;SKIP RESERVED\n\tadd\tedi,4\t\t;SKIP RESERVED\n\t\t \n\tsub\teax,eax\n\tmov\tal,[esi]\t;get attrib byte\n\tmov\t[es:edi+4],eax\n\tinc\tesi\n\t\n\t;get time\n\tmov\tax,[esi]\n\tadd\tesi,2\n\tmov\t[es:edi+8],ax\n\t\n\t;get date\n\tmov\tax,[esi]\n\tadd\tesi,2\n\tmov\t[es:edi+10],ax\n\t\n\t;get file size\n\tmov\teax,[esi]\n\tadd\tesi,4\n\tmov\t[es:edi],eax\n\t\n\tadd\tedi,12\n\t\t    \n     \tmov\tecx,13\n     \t\t    \n     \trep\tmovsb\t\t;copy the DTA name\n     \t\n     \tmov\tax,es\n     \tmov\tds,ax\n     \t\n \txor\teax,eax\n??exit:\t\n\tret\n;====================\nENDP Find_First\t\n\n\n\n;***************************************************************************\n;* FIND_NEXT -- Find next file in sreach params                            *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*              NONE                                                       *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/15/1994  jaw: Created.                                             *\n;*=========================================================================*\n     \nPROC Find_Next C near\n\tUSES ebx,ecx,edx,esi,edi,ds,es\n\t\n     \tARG ffblk:DWORD\n     \t    \n\tmov\teax,04f00h\t\t;Find Next function\n\t\n\tint 21h\n\t       \t\t\t\t;Find anything?\n     \tjnc\t??found_it\t\t;=>no\n     \t\n\t; ax holds the error code\n\t;insure high word of eax is clear\n\tor\teax,0ffffffffh\n\tjmp\t??exit\n\t\n??found_it:\n     \t; found something\n     \t;copy the DTA into the user block\n     \tmov\teax,2f00h\t\t;get DTA address\n     \tint\t21h\n     \t\n     \tmov\tax,es\t\t\t;switch selectors\n     \tmov\tdx,ds\n     \tmov\tds,ax\n     \tmov\tes,dx\n     \n     \tmov\tesi,ebx\n     \tmov\tedi,[ffblk]\n     \t\n\tadd\tesi,21\t\t\t;SKIP RESERVED\n\tadd\tedi,4\t\t\t;SKIP RESERVED\n\t\t \n\tsub\teax,eax\n\tmov\tal,[esi]\t\t;get attrib byte\n\tmov\t[es:edi+4],eax\n\tinc\tesi\n\t\n\t;get time\n\tmov\tax,[esi]\n\tadd\tesi,2\n\tmov\t[es:edi+8],ax\n\t\n\t;get date\n\tmov\tax,[esi]\n\tadd\tesi,2\n\tmov\t[es:edi+10],ax\n\t\n\t;get file size\n\tmov\teax,[esi]\n\tadd\tesi,4\n\tmov\t[es:edi],eax\n\t\n\tadd\tedi,12\n\t\t    \n     \tmov\tecx,13\n     \t\t    \n     \trep\tmovsb\t\t;copy the DTA name\n     \t\n     \tmov\tax,es\n     \tmov\tds,ax\n     \t\n\txor\teax,eax\n??exit:\t\n\tret\n\t\nENDP Find_Next\n\n\nEND\n\n\n\n\n\u001a\n\n\u001a\n\u001a\n\u001a"
  },
  {
    "path": "WWFLAT32/FILE/FGLOB2.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : FILEIO Library                           *\n *                                                                         *\n *                    File Name : FILEGLOB.C                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 11, 1994                           *\n *                                                                         *\n *                  Last Update : April 11, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"_file.h\"\n\n/* Global varaiables */\nWORD Hard_Error_Occured=0;\n"
  },
  {
    "path": "WWFLAT32/FILE/FILE.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library - Filio header stuff.            *\n *                                                                         *\n *                    File Name : FILE.H                                 \t*\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : September 13, 1993                       *\n *                                                                         *\n *                  Last Update : April 11, 1994\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FILE_H\n#define FILE_H\n\n\n#ifndef ERROR\n#define\tERROR\t-1\n#endif\n\n#ifndef FILETEMP_H\n// This should be removed once the library is all intacked.\n#include \"filetemp.h\"\n#endif\n\n/*=========================================================================*/\n/* File IO system defines and enumerations\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#define\tXMAXPATH\t80\n\n/*\n**\tThese are the Open_File, Read_File, and Seek_File constants.\n*/\n#define READ\t\t\t\t\t\t1\t// Read access.\n#define WRITE\t\t\t\t\t\t2\t// Write access.\n#ifndef SEEK_SET\n#define SEEK_SET\t\t\t\t\t0\t// Seek from start of file.\n#define SEEK_CUR\t\t\t\t\t1\t// Seek relative from current location.\n#define SEEK_END\t\t\t\t\t2\t// Seek from end of file.\n#endif\n\n\ntypedef enum {\n\tFILEB_PROCESSED=8,// Was the packed file header of this file processed?\n\tFILEB_PRELOAD,\t\t// Scan for and make file resident at WWDOS_Init time?\n\tFILEB_RESIDENT,\t// Make resident at Open_File time?\n\tFILEB_FLUSH,\t\t// Un-resident at Close_File time?\n\tFILEB_PACKED,\t\t// Is this file packed?\n\tFILEB_KEEP,\t\t\t// Don't ever flush this resident file?\n\tFILEB_PRIORITY,\t// Flush this file last?\n\n\tFILEB_LAST\n} FileFlags_Type;\n\n#define\tFILEF_NONE\t\t\t0\n#define\tFILEF_PROCESSED\t(1<<FILEB_PROCESSED)\n#define\tFILEF_PRELOAD\t\t(1<<FILEB_PRELOAD)\n#define\tFILEF_RESIDENT\t\t(1<<FILEB_RESIDENT)\n#define\tFILEF_FLUSH\t\t\t(1<<FILEB_FLUSH)\n#define\tFILEF_PACKED\t\t(1<<FILEB_PACKED)\n#define\tFILEF_KEEP\t\t\t(1<<FILEB_KEEP)\n#define\tFILEF_PRIORITY\t\t(1<<FILEB_PRIORITY)\n\n/*\n** These errors are returned by WWDOS_Init().  All errors encountered are\n** or'd together so there may be more then one error returned.  Not all\n** errors are fatal, such as the cache errors.\n*/\ntypedef enum {\n\tFI_SUCCESS\t\t\t\t\t\t= 0x00,\n\tFI_CACHE_TOO_BIG\t\t\t\t= 0x01,\n\tFI_CACHE_ALREADY_INIT\t\t= 0x02,\n\tFI_FILEDATA_FILE_NOT_FOUND\t= 0x04,\n\tFI_FILEDATA_TOO_BIG\t\t\t= 0x08,\n \tFI_SEARCH_PATH_NOT_FOUND\t= 0x10,\n \tFI_STARTUP_PATH_NOT_FOUND\t= 0x20,\n\tFI_NO_CACHE_FOR_PRELOAD\t\t= 0x40,\n\tFI_FILETABLE_NOT_INIT\t\t= 0x80,\n} FileInitErrorType;\n\n\n/*\n**\tThese are the errors that are detected by the File I/O system and\n**\tpassed to the io error routine.\n*/\n//lint -strong(AJX,FileErrorType)\ntypedef enum {\n\tCANT_CREATE_FILE,\n\tBAD_OPEN_MODE,\n\tCOULD_NOT_OPEN,\n\tTOO_MANY_FILES,\n\tCLOSING_NON_HANDLE,\n\tREADING_NON_HANDLE,\n\tWRITING_NON_HANDLE,\n\tSEEKING_NON_HANDLE,\n\tSEEKING_BAD_OFFSET,\n\tWRITING_RESIDENT,\n\tUNKNOWN_INDEX,\n\tDID_NOT_CLOSE,\n\tFATAL_ERROR,\n\tFILE_NOT_LISTED,\n\tFILE_LENGTH_MISMATCH,\n\tINTERNAL_ERROR,\n\tMAKE_RESIDENT_ZERO_SIZE,\n\tRESIDENT_SORT_FAILURE,\n\n\tNUMBER_OF_ERRORS\t\t\t\t/* MAKE SURE THIS IS THE LAST ENTRY */\n} FileErrorType;\n\n// This is here tempararaly until library is put together.\n//extern WORD cdecl (*cdecl IO_Error)(FileErrorType error, BYTE const *filename);\nextern short (*Open_Error)(FileErrorType, BYTE const *);\n\n/*=========================================================================*/\n/* File IO system structures\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//lint -strong(AJX,FileDataType)\ntypedef struct {\n\tchar\t*Name;\t\t// File name (include sub-directory but not volume).\n\tlong\tSize;\t\t\t// File size (0=indeterminate).\n\tvoid\t*Ptr;\t\t\t// Resident file pointer.\n\tlong\tStart;\t\t// Starting offset in DOS handle file.\n\tunsigned char\tDisk;\t\t\t// Disk number location.\n\tunsigned char\tOpenCount;\t// Count of open locks on resident file.\n\tunsigned short\tFlag;\t\t\t// File control flags.\n} FileDataType;\n\n\n/*=========================================================================*/\n/* FIle IO system globals.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n// These are cpp errors in funtions declarations\tJULIO JEREZ\n\n// extern FileDataType cdecl FileData[];\n// extern BYTE cdecl ExecPath[XMAXPATH + 1];\n// extern BYTE cdecl DataPath[XMAXPATH + 1];\n// extern BYTE cdecl StartPath[XMAXPATH + 1];\n// extern BOOL cdecl UseCD;\n\n// The correct syntax is  NO TYPE MODIFIER APPLY TO DATA DECLARATIONS\nextern FileDataType FileData[];\nextern char ExecPath[XMAXPATH + 1];\nextern char DataPath[XMAXPATH + 1];\nextern char StartPath[XMAXPATH + 1];\nextern BOOL UseCD;\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILEINIT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid cdecl WWDOS_Shutdown(void);\nFileInitErrorType cdecl WWDOS_Init(unsigned long cachesize, char *filedata, char *cdpath);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILE.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint cdecl Open_File(char const *file_name, short mode);\nvoid cdecl Close_File(short handle);\nlong cdecl Read_File(short handle, void *buf, unsigned long bytes);\nlong cdecl Write_File(short handle, void const *buf, unsigned long bytes);\nunsigned long cdecl Seek_File(short handle, long offset, short starting);\nint cdecl File_Exists(char const *file_name);\nunsigned long cdecl File_Size(short handle);\nBOOL cdecl Is_Handle_Valid(short handle, FileErrorType error, char const *name);\nshort cdecl Open_File_With_Recovery( char const *file_name, unsigned short mode );\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILECACH.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid Unfragment_File_Cache(void);\nBOOL cdecl Make_File_Resident(char const *filename);\nshort cdecl Flush_Unused_File_Cache(short flush_keeps);\nBOOL cdecl Free_Resident_File(char const *file);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILECHNG.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort cdecl Create_File(char const *file_name);\nshort cdecl Delete_File(char const *file_name);\nBOOL cdecl Change_File_Size(short handle, unsigned long new_size);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILEINFO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort cdecl Get_DOS_Handle(short fh);\nshort cdecl Free_Handles(void);\nshort cdecl Find_Disk_Number(char const *file_name);\nshort cdecl Set_File_Flags(char const *filename, short flags);\nshort cdecl Clear_File_Flags(char const *filename, short flags);\nshort cdecl Get_File_Flags(char const *filename);\nBOOL cdecl Multi_Drive_Search(BOOL on);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FINDFILE.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort cdecl Find_File(char const *file_name);\nshort cdecl Find_File_Index(char const *filename);\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FFIRST.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#include <dos.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern short Find_First(unsigned char *fname, unsigned short mode, struct find_t *ffblk);\nextern short Find_Next(struct find_t *ffblk);\n\n#ifdef __cplusplus\n}\n#endif\n\n\n\n\n#endif // FILE_H\n\u001a\n"
  },
  {
    "path": "WWFLAT32/FILE/FILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library                                  *\n *                                                                         *\n *                    File Name : FILE.CPP                                 *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : September 13, 1993                       *\n *                                                                         *\n *                  Last Update : September 13, 1993   [SKB]               *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   File_Exists -- Searches for and FINDS the specified file.             *\n *   File_Size -- Determine the size of the specified file.                *\n *   Open_File -- Opens a file for access.                                 *\n *   Close_File -- Closes a file previously opened with Open_File.         *\n *   Seek_File -- Adjusts the position of the file pointer.                *\n *   Read_File -- Reads a block of data from a file.                       *\n *   Write_File -- Writes a block of data to a file.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#include <wwstd.h>\n#endif\t   \n\n#ifndef FILE_H\n#include \"_file.h\"\n#endif\n\n#ifndef WWMEM_H\n#include <wwmem.h>\n#endif\n\n\n#include <fcntl.h>\n#include <io.h>\n#include <sys\\stat.h>\n\n#define DEBUGPRINT FALSE\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * OPEN_FILE -- Opens a file for access.                                   *\n *                                                                         *\n *    This routine will open the specified file for access.  It functions  *\n *    in a similar manner to the regular DOS open command.                 *\n *                                                                         *\n * INPUT:   filename -- Pointer to the filename to open.                   *\n *                                                                         *\n *          mode     -- Access mode to use.                                *\n *             READ: A file opened for READ access, MUST be available.     *\n *                   This may cause a disk swap message to appear.         *\n *                                                                         *\n *             WRITE:A file opened for WRITE access (only), need not be    *\n *                   available.  If it can't be found, then it will be     *\n *                   created in the current directory.                     *\n *                                                                         *\n * OUTPUT:  Returns with the westwood file handle.  If ERROR is returned   *\n *          it means that the programmer took over the file error handler  *\n *          and signaled that an open access failure should not keep trying*\n *          for success.                                                   *\n *                                                                         *\n * WARNINGS:   If you take over the file error handling code, you must be  *\n *             sure to anticipate a possible ERROR value being returned.   *\n *             If you open a file for READ or READ|WRITE, then the file    *\n *             must previously exist.  To create a file for read and write *\n *             access, first open it for WRITE, then re-open it for        *\n *             read and write.                                             *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/11/1991 JLB : Created.                                             *\n *=========================================================================*/\nint cdecl Open_File(char const *file_name, int mode)\n{\n\tint\t\t\t\t\t\t\tfile_handle;\t\t\t\t// Westwood file handle.\n\tint\t\t\t\t\t \t\thandle;\t\t\t\t\t\t// DOS file handle.\n\tunsigned int\t\t\t\t \t\t\tlocal_mode;\t\t\t\t\t// DOS access mode number.\n\tint\t\t\t\t\t\t\tindex;\t\t\t\t\t\t// FileData index (if available).\n\tBOOL\t\t\t\t\t\t\timmediate;\t\t\t\t\t// Is the file immediately available?\n\tFileDataType\t\t\t\t*filedata;\t\t\t\t\t// Pointer to the current FileData.\n\tFileDataType\t\t\t\t*parent;\t\t\t\t\t\t// Pointer to the current FileData.\n\tFileHandleType\t\t\t\t*filehandletable;\t\t\t// Pointer to the current file handle.\n\n\tCallingDOSInt++;\n\n\n\t#if(DEBUGPRINT)\n\t\tMono_Printf(\"Open_File('%s')\\r\", file_name);\n\t#endif\n\n\t/*\n\t** Is there a slot in the FileHandleTable?  If not, then exit with\n\t**\ta file error.\n\t*/\n\tfilehandletable = FileHandleTable;\n\tfor (file_handle = 0; file_handle < TABLE_MAX; file_handle++, filehandletable++) {\n\t\tif (filehandletable->Empty) break;\n\t}\n\tif (file_handle == TABLE_MAX) {\n \t\tDo_IO_Error(TOO_MANY_FILES, file_name);\n\t}\n\n\t/*\n\t**\tFind the file in the FileTable (if it exists there).\n\t*/\n\tindex = Find_File_Index(file_name);\n\tfiledata = &FileDataPtr[index];\n\n\t// Start out looking at the start drive.\n\tibm_setdisk(*StartPath - 'A');\n\n\t/*\n\t**\tIf the file exists in the current directory, then by all\n\t**\tmeans, use that file instead of any corresponding pack\n\t**\tfile representation.  This is used as a means of\n\t**\toverriding packed files (quite handy).\n\t*/\n\timmediate = FALSE;\n\n\t/*\n\t**\tCheck the current directory by attempting to open with READ access.\n\t** Only check if the file is not already cached and it is a packed file.\n\t*/\n\tif ((index != ERROR) && (filedata->Flag & FILEF_PACKED) && (!filedata->Ptr)) \n\t{\n\t\tint\thandle2;\n\t\n\t\thandle2 = FILEOPEN(file_name, MODE_OLDFILE);\n\t\tif (handle2 != FILEOPENERROR) {\n\t\t\tFILECLOSE(handle2);\n\t\t\timmediate = TRUE;\n\t\t}\n\t}\n\n\n\t/*\n\t** Check to see if any WRITE permission is requested for the\n\t**\tfile.  If so, delete the file from RAM and mark it as non-resident.\n\t**\n\t**\tNOTE:\tIf the file is packed, we CAN NOT alter it in ANY way.\n\t**\t\t\tWe will return an ERROR to the user, and hope he/she is\n\t**\t\t\tsmart enough to handle it.\n\t*/\n\tif ((mode & WRITE) && index != ERROR && filedata->Ptr) {\n\t\tif(filedata->Flag & FILEF_PACKED) {\t\t// is file packed?\n\t\t\tMem_Free(FileCacheHeap, filedata->Ptr);\t\t\t\t\t\t\n\t\t\tfiledata->Ptr = NULL;\n\t\t} else {\t\t\t\t\t\t\t\t\t\t\t\t\t// file is packed\n\t\t\tDo_IO_Error(WRITING_RESIDENT, file_name);\n\t\t}\n\t}\n\n\t// If the file is cached already, then let us use it and leave.\n\tif (filedata->Ptr && index != ERROR) {\n\t\t/*\n\t\t**\tFile is resident.  Initialize the local table.\n\t\t*/\n\t\tfilehandletable->Index = index;\n\t\tfilehandletable->Empty = FALSE;\n\t\tfilehandletable->Pos = 0L;\n\t\tfilehandletable->Name = filedata->Name;\n\t\tfilehandletable->Handle = 0;\t// Resident flag.\n\t\tfilehandletable->Mode = mode;\n\n\t\t// If the cached file is packed and its parent is resident, then\n\t\t// add one to the parent open count.\n\t\tif (filedata->Flag & FILEF_PACKED) {\n\t\t\tparent = &FileDataPtr[filedata->Disk];\n\t\t}\n\t\telse {\n\t\t\tparent = NULL;\n\t\t}\n\n\t\tif (parent && (parent->Ptr == filedata->Ptr)) {\n\t\t\tfilehandletable->Start = filedata->Start;\n\t\t\tparent->OpenCount++;\n\t\t} else {\n\t\t\tfilehandletable->Start = 0;\n\t\t}\n\n\t\t// Mark the pointer in use so that it is never returned as the oldest\n\t\t// pointer location in memory.\n\t\tMem_In_Use(filedata->Ptr);\n\n\t} else {\n\t\t\n\t\t/*\n\t\t** At this time we determine if it is a packed file.  If so, the\n\t\t**\topening process takes a dramatically different turn.\n\t\t*/\n\t\tif (index != ERROR && (filedata->Flag & FILEF_PACKED) && !immediate && (mode & WRITE) == 0) {\n\n\t\t\t/*\n\t\t\t**\tThis is a packed file.  Perform recursive open process to reach\n\t\t\t**\tthe parent packed file.\n\t\t\t*/\n\t\t\tparent = &FileDataPtr[filedata->Disk];\n\t\t\tfile_handle = Open_File(parent->Name, mode);\n\n\t\t\t// Reread the parents information.\n\t\t\tparent = &FileDataPtr[filedata->Disk];\n\t\t\tfilehandletable = &FileHandleTable[file_handle];\n\n\t\t\t/*\n\t\t\t**\tProcess the packed file header.  Update the start offset for every\n\t\t\t**\tfile ellaborated in the packed file.  \n\t\t\t**\tException:  When a file is specified in the packed file and an\n\t\t\t**\t\t\t\t\tentry exists for it in the file table, BUT the entry\n\t\t\t**\t\t\t\t\tis not marked as packed, THEN ignore the packed version\n\t\t\t**\t\t\t\t\tof the file.\n\t\t\t*/\n\n\t\t\tif (FileData == FileDataPtr && \n\t\t\t    !(FileDataPtr[filehandletable->Index].Flag & FILEF_PROCESSED)) {\n\t\t\t\tlong\toffset;\t\t\t\t\t// Offset of sub-file start.\n\t\t\t\tint\ti;\t\t\t\t\t\t\t// Sub-file FileData index.\n\t\t\t\tchar\tname[FILENAMESIZE];\t// Name of sub-file.\n\t\t\t\tFileDataType\t*cur=NULL;\t// Current entry in FileData.\n\t\t\t\tFileDataType\t*last=NULL;\t// Last entry in FileData.\n\n\n\t\t\t\t#if(DEBUGPRINT)\n\t\t\t\t\tMono_Printf(\"Processing packed file '%s'\\r\", FileDataPtr[filedata->Disk].Name); \n\t\t\t\t#endif\n\n\t\t\t\tRead_File(file_handle, &offset, (unsigned long)sizeof(long));\n\t\t\t\twhile (offset) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDue to the fact that the embedded file name is of arbitrary\n\t\t\t\t\t**\tlength, we must read it in a byte at a time.  Reading stops\n\t\t\t\t\t**\twhen the terminating NULL is found.\n\t\t\t\t\t*/\n\t\t\t\t\ti=0;\n\t\t\t\t\tdo {\n\t\t\t\t\t\tRead_File(file_handle, &name[i], (unsigned long)sizeof(name[0]));\n\t\t\t\t\t} while (name[i++]);\n\n\t\t\t\t\ti = Find_File_Index(name);\n\t\t\t\t\tif (i != ERROR) {\n\t\t\t\t\t\tcur = &FileDataPtr[i];\n\t\t\t\t\t\tif ((cur->Flag & FILEF_PACKED) && cur->Disk == filehandletable->Index) {\n\n\t\t\t\t\t\t\tcur->Start = offset + FileDataPtr[ filehandletable->Index ].Start;\n\t\t\t\t\t\t\tif (last != NULL) {\n\t\t\t\t\t\t\t\tlast->Size = cur->Start - last->Start;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tlast = cur;\t\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// ERROR: File specified in packed file has no table entry.\n\t\t\t\t\t\t// When this occurs, the embedded file is ignored.\n\t\t\t\t\t}\n\n\t\t\t\t\tRead_File(file_handle, &offset, (unsigned long)sizeof(long));\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tFixup the size record of the last embedded file.\n\t\t\t\t*/\n\t\t\t\tif (last != NULL) {\n\t\t\t\t\tlast->Size = File_Size(file_handle) - last->Start;\n\t\t\t\t}\n\n\t\t\t\tFileDataPtr[filehandletable->Index].Flag |= FILEF_PROCESSED;\n\t\t\t}\n\n\t\t\t// if the parent is resident, the the child must have the same address.\n\t\t\tfiledata->Ptr = parent->Ptr;\n\n\t\t\t/*\n\t\t\t**\tSet starting position to start of embedded file.\n\t\t\t*/\n\t\t\tfilehandletable->Index = index;\n\t\t\tfilehandletable->Name = filedata->Name;\n\t\t\tfilehandletable->Start = filedata->Start;\n\n\t\t\tSeek_File(file_handle, NULL, SEEK_SET);\n\n\t\t\t// Attempt to cache the file if wanted, and room.\n\t\t\tCache_File(index, file_handle);\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tConvert the Westwood access mode into the system specific mode.\n\t\t\t*/\n\t\t\tlocal_mode = MODE_OLDFILE;\n\t\t\tswitch (mode) {\n\t\t\t\tcase READ:\n\t\t\t\t\tlocal_mode = MODE_OLDFILE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase READ | WRITE:\n\t\t\t\t\t#if(IBM)\n\t\t\t\t\t\tlocal_mode = MODE_READWRITE;\n\t\t\t\t\t#else\n\t\t\t\t\t\tlocal_mode = MODE_OLDFILE;\n\t\t\t\t\t#endif\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase WRITE:\n\t\t\t\t\tlocal_mode = MODE_NEWFILE;\n\t\t\t\t\tbreak;\n\n\n\t\t\t\tdefault:\n\t\t\t\t\tDo_IO_Error(BAD_OPEN_MODE, file_name);\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\t\t/*\n\t\t\t**\tThe file is disk based.  Perform the DOS open processing.\n\t\t\t*/\n\n\t\t\t/*\n\t\t\t**\tMake sure the file is available or the proper disk is inserted.\n\t\t\t** The file MUST exist if READ access is requested.  A mild attempt\n\t\t\t**\twill be made to find the file if open for WRITE only.\n\t\t\t*/\n\t\t\tif (mode & READ) {\n\t\t\t\tif (!File_Exists(file_name)) {\n\t\t\t\t\tCallingDOSInt--;\n\t\t\t\t\treturn(ERROR);\t\t\t/* Ignore the error */\n\t\t\t\t}\n\t\t\t} \n\n\n\t\t\t/*\n\t\t\t**\tRepetitively try to open the file until the error handler\n\t\t\t**\troutine indicates otherwise.\n\t\t\t*/\n\t\t\thandle = FILEOPENERROR;\n\t\t\tfor (;;) {\n\t\t\t\thandle = Open_File_With_Recovery( file_name, local_mode );\n\t\t\t\tif (handle != FILEOPENERROR) {\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tCHANGEDIR( DataPath );\n\t\t\t\t\tCHANGEDIR( StartPath );\n\t\t\t\t\tif (!Do_Open_Error(COULD_NOT_OPEN, file_name)) {\n\t\t\t\t\t\tCallingDOSInt--;\n\t\t\t\t\t\treturn(FILEOPENERROR);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tA file that is read off of disk cannot be part of\n\t\t\t**\ta pack file regardless of the bit settting.\n\t\t\t*/\n\t\t\tif (immediate && index != ERROR) {\n\t\t\t\tfiledata->Flag &= ~FILEF_PACKED;\n\t\t\t\tfiledata->Size = 0;\n\t\t\t}\n\n\t\t\tif (index != ERROR) {\n\n\t\t\t\t// The true file size is needed.\n\t\t\t\t// Go back to beginning of file.\n\t\t\t\tfiledata->Size = FILESEEK(handle, 0L, SEEK_END);\n\t\t\t\tFILESEEK(handle, 0L, SEEK_SET);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tInitialize the local file handle table.\n\t\t\t*/\n\t\t\tfilehandletable->Index = index;\n\t\t\tfilehandletable->Pos = 0L;\n\t\t\tfilehandletable->Start = 0L;\n\t\t\tfilehandletable->Empty = FALSE;\n\t\t\tfilehandletable->Handle = handle;\n\t\t\tfilehandletable->Mode = mode;\n\t\t\tif (index != ERROR) {\n\t\t\t\tfilehandletable->Name = filedata->Name;\n\t\t\t} else {\n\t\t\t\tfilehandletable->Name = NULL;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the file should be made resident, then do it at this time.\n\t\t\t**\tPerform all necessary adjustments to the file tables.\n\t\t\t*/\n\t\t\tif ((mode & WRITE) == 0) {\n\t\t\t\tCache_File(index, file_handle);\n\t\t\t}\n\t\t}\n\t}\n\n\t// If in the file table, increment the number of opens on this file.\n\tif (index != ERROR) {\n\t\tfiledata->OpenCount++;\n\t}\n\n\t/*\n\t**\tReturn with valid file handle.\n\t*/\n\tCallingDOSInt--;\n\treturn(file_handle);\n}\n\n\n/***************************************************************************\n * CLOSE_FILE -- Closes a file previously opened with Open_File.           *\n *                                                                         *\n *    Use this routine to close a file that was opened with Open_File.     *\n *    This is the only way to close a file that was opened with the        *\n *    Westwood file I/O system.                                            *\n *                                                                         *\n * INPUT:   handle   -- Westwood file handle.                              *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/11/1991 JLB : Created.                                             *\n *=========================================================================*/\nVOID cdecl Close_File(int handle)\n{\n\tint\t\t\t\tindex;\t\t\t\t\t// File data table index.\n\tBOOL\t\t\t\tflushed\t= FALSE;\t\t// If file flushed from cache, do change time stamp.\n\tBOOL\t\t\t\tstillopen;\n\tFileDataType\t*parent = NULL;\n\tFileDataType\t*filedata = NULL;\n\tVOID\t\t\t\t*memptr=NULL;\n\n\n\t#if(DEBUGPRINT)\n\t\tMono_Printf(\"Close_File(%d)\\r\", handle);\n\t#endif\n\n\n\t/*\n\t**\tCheck for file handle validity.\n\t*/\n\tif (!Is_Handle_Valid(handle, CLOSING_NON_HANDLE, NULL)) {\n\t\treturn;\n\t}\n\n\tCallingDOSInt++;\n\n\tindex = FileHandleTable[handle].Index;\n\tfiledata = &FileDataPtr[index];\n\n\t// Remove the OpenCount on the file.\n\tif (index != ERROR) {\n\n\t\tfiledata->OpenCount--;\n\t\tstillopen = filedata->OpenCount;\n\n\t\t// If this file packed in another, then decrement the parents open count.\n\t\tif (filedata->Flag & FILEF_PACKED) {\n\t\t\tparent = &FileDataPtr[filedata->Disk];\n\n\t\t\t// Do not dec OpenCount if the child was cached but not the parent.\n\t\t\tif (parent->Ptr == filedata->Ptr) {\n\t\t \t\tparent->OpenCount--;\n\t\t\t\tstillopen = parent->OpenCount;\n\t\t\t}\n\t\t}\n\t}\n\n\n\t// If the file was resident, then handle bookeeping.\n\tif (index != ERROR && filedata->Ptr) {\n\n\t\t// Get a pointer to the memory area for later use.\n\t\tmemptr = filedata->Ptr;\n\n\t\t// If file has a parent, and it is the cached file...\n\t\tif (parent && (parent->Ptr == filedata->Ptr)) {\n\n\t\t\t// The PAK'd file is closed just by setting the pointer.\n\t\t\tif (!filedata->OpenCount)\t{\n\t\t\t\tfiledata->Ptr = NULL;\n\t\t\t}\n\n\t\t\t// Uncache parent if no other sons are open and it should be flushed.\n\t\t\tif ((!parent->OpenCount) && (parent->Flag & FILEF_FLUSH)) {\n\t\t\t\tMem_Free(FileCacheHeap, parent->Ptr);\n\t\t\t\tparent->Ptr = NULL;\n\t\t\t\tflushed = TRUE;\n\t\t\t}\n\t\t}\n\t\t// Else should the file be flushed?  Only flush it if the flag says\n\t\t// so AND there are no other open counts on it.\n\t\telse if ((filedata->Flag & FILEF_FLUSH) && !filedata->OpenCount) {\n\t\t\tMem_Free(FileCacheHeap, filedata->Ptr);\n\t\t\tfiledata->Ptr = NULL;\n\t\t\tflushed = TRUE;\n\t\t}\n\n\t\t//\n\t\t// Set the time stamp on the close IF\n\t\t//     the file was not flush AND\n\t\t//     is not open AND \n\t\t//\t\t its time stamp should be changed by being a FILEF_KEEP|PROIORTY file.\n\t\t//\n\t\tif (!flushed && !stillopen && !(filedata->Flag & (FILEF_KEEP|FILEF_PRIORITY))) {\n\t\t\tMem_Reference(memptr);\n\t\t}\n\t} \n\t// Just a simple close will do.\n\telse \t{\n\t\tFILECLOSE(FileHandleTable[handle].Handle);\n\t}\n\n\t// The WWS handle is no longer being used.\n\tFileHandleTable[handle].Empty = TRUE;\n\n\tCallingDOSInt--;\n}\n\n\n\n/***************************************************************************\n * READ_FILE -- Reads a block of data from a file.                         *\n *                                                                         *\n *    This routine is used to read a block of data from a previously       *\n *    opened file.                                                         *\n *                                                                         *\n * INPUT:   handle   -- Westwood file handle returned from Open_File.      *\n *                                                                         *\n *          buf      -- Pointer to buffer to load the data into.           *\n *                                                                         *\n *          bytes    -- Number of bytes to load.                           *\n *                                                                         *\n * OUTPUT:  Returns with the number of bytes actually read from the file.  *\n *          If this number is less than the number requested, this         *\n *          indicates the end of the file.                                 *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/13/1991 JLB : Created.                                             *\n *=========================================================================*/\nlong cdecl Read_File(int handle, VOID *buf, unsigned long bytes)\n{\n\tint\t\t\t\t\tdoshandle;\t\t// DOS file handle.\n\tint\t\t\t\t\tfileindex;\t\t// File table index.\n\tlong\t\t\t\t\tbytesread;\t\t// Accumulation of number of bytes read.\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\n\t#if(DEBUGPRINT)\n\t\tMono_Printf(\"Read_File(%d, %08lx, %ld)\\r\", handle, buf, bytes);\n\t#endif\n\n\t/*\n\t**\tThe handle must be valid or else it is an error.\n\t*/\n\tif (!buf || !bytes || !Is_Handle_Valid(handle, READING_NON_HANDLE, NULL)) {\n\t\treturn(NULL);\n\t}\n\n\tCallingDOSInt++;\n\n\t/*\n\t**\tPrepare some working variables.\n\t*/\n\tdoshandle = FileHandleTable[handle].Handle;\n\tfileindex = FileHandleTable[handle].Index;\n\n\n\t/*\n\t**\tLimit the number of bytes to read according to the size of the\n\t**\tfile.  If no file size is specified, then don't perform the check.\n\t*/\n\tif (fileindex != ERROR) {\n\t\tfiledata = &FileDataPtr[fileindex];\n\n\t\tif (filedata->Size) {\n\t\t\tbytes = MIN((unsigned long)filedata->Size - FileHandleTable[handle].Pos, bytes);\n\t\t}\n\t}\n\n\t/*\n\t**\tStarts with no bytes being read in.\n\t*/\n\tbytesread = 0;\n\n\tif (bytes) {\n\n\t\tif (doshandle) {\n\t\t\t/*\n\t\t\t**\tPerform a DOS read of the file.  Read the file in chunks.\n\t\t\t*/\n\t\t\twhile (bytes) {\n\t\t\t\tlong\tnumber;\t// Number of bytes read.\n\n\t\t\t\t/*\n\t\t\t\t**\tRead in a chunk of file data.\n\t\t\t\t*/\n\t\t\t\tHard_Error_Occured = 0;\n\t\t\t\tnumber = (long)FILEREAD(doshandle, buf, MIN(bytes, IO_CHUNK_SIZE));\n\n\t\t\t\t/*\n\t\t\t\t** if a hard error occurs, read its copy on a different directory\n\t\t\t\t*/\n\t\t\t\tif ( Hard_Error_Occured\t) {\n\t\t\t\t\tnumber = Read_File_With_Recovery( handle, buf, (unsigned int)MIN(bytes, IO_CHUNK_SIZE));\n\t\t\t\t\tdoshandle = FileHandleTable[handle].Handle;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAdjust the remaining bytes to read counter and adjust the count\n\t\t\t\t**\tof the number of bytes actually read from the file.\n\t\t\t\t*/\n\t\t\t\tbytes -= number;\n\t\t\t\tbytesread += number;\n\n\t\t\t\t/*\n\t\t\t\t**\tAdjust the file position (manually).\n\t\t\t\t*/\n\t\t\t\tFileHandleTable[handle].Pos += number;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf less than requested bytes were read from the file, then \n\t\t\t\t** we KNOW that the reading loop must terminate.\n\t\t\t\t**\tWas there an error?\n\t\t\t\t*/\n\t\t\t\tif (number < IO_CHUNK_SIZE) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAdjust the destination pointer in anticipation of the next\n\t\t\t\t**\tfile read operation.\n\t\t\t\t*/\n\t\t\t\t// this is a BCC bug\n\t\t\t\t// (char *)buf += number;\n\t\t\t\t buf = (char* ) buf +  number;\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t#if (DEBUGPRINT)\n\t\t\t\tMono_Printf(\"Resident read '%s' %08lx[%ld].%ld\\r\", filedata->Name, (long)filedata->Start, FileHandleTable[handle].Pos, bytes);\n\t\t\t#endif\n\n\t\t\t/*\n\t\t\t**\tCopy the block of the file into the specified buffer.\n\t\t\t*/\n\t\t\tMem_Copy((VOID*)((long)filedata->Ptr + FileHandleTable[handle].Start + FileHandleTable[handle].Pos), buf, bytes);\n\t\t\tbytesread = bytes;\n\n\t\t\t/*\n\t\t\t**\tAdjust the file position (manually).\n\t\t\t*/\n\t\t\tFileHandleTable[handle].Pos += bytes;\n\t\t}\n\t}\n\n\t/*\n\t**\tReturn with the number of bytes read in from the file.\n\t*/\n\tCallingDOSInt--;\n\treturn(bytesread);\n}\n\n\n/***************************************************************************\n * WRITE_FILE -- Writes a block of data to a file.                         *\n *                                                                         *\n *    This routine will write a block of data to a file.  The file must    *\n *    have been previously opened with WRITE or READ|WRITE access.         *\n *    Writing cannot occur to a resident or packed file.                   *\n *                                                                         *\n * INPUT:   handle   -- File handle as returned by Open_File.              *\n *                                                                         *\n *          buf      -- Pointer to the buffer that holds the data to be    *\n *                      written out.                                       *\n *                                                                         *\n *          bytes    -- The number of bytes to write out.                  *\n *                                                                         *\n * OUTPUT:  Returns with the actual number of bytes written to the file.   *\n *                                                                         *\n * WARNINGS:   If the value returned from this function is less than the   *\n *             number of bytes requested to be written, then this          *\n *             indicates some kind of error NOT caught by the file I/O     *\n *             system.                                                     *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/13/1991 JLB : Created.                                             *\n *=========================================================================*/\nlong cdecl Write_File(int handle, VOID const *buf, unsigned long bytes)\n{\n\tint\t\t\t\t\tdoshandle;\t\t// DOS specific file handle.\n\tint\t\t\t\t\tfileindex;\t\t// FileData table index (if any).\n\tlong\t\t\t\t\tbyteswritten;\t// Accumulated number of bytes written.\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\n\t#if(DEBUGPRINT)\n\t\tMono_Printf(\"Write_File(%d, %08lx, %ld)\\r\", handle, buf, bytes);\n\t#endif\n\n\t/*\n\t**\tCheck to make sure the file handle is valid.\n\t*/\n\tif (!Is_Handle_Valid(handle, WRITING_NON_HANDLE, NULL)) {\n\t\treturn(NULL);\n\t}\n\tdoshandle = FileHandleTable[handle].Handle;\n\tfileindex = FileHandleTable[handle].Index;\n\tfiledata = &FileDataPtr[fileindex];\n\n\t/*\n\t**\tWriting to a resident file is an error condition.\n\t*/\n\tif (!doshandle) {\n\t\tDo_IO_Error(WRITING_RESIDENT, filedata->Name);\n\t\treturn(NULL);\n\t}\n\n\tCallingDOSInt++;\n\n\t/*\n\t**\tPerform a DOS write of the data.  This write is performed in blocks.\n\t*/\n\tbyteswritten = NULL;\n\n\twhile (bytes) {\n\t\tlong\toutbytes;\t\t// Number bytes written in one block.\n\n\t\t/*\n\t\t**\tWrite out one block of data.\n\t\t*/\n\t\toutbytes = FILEWRITE(doshandle, (void*)buf, MIN((long)bytes, IO_CHUNK_SIZE));\n\n\t\t/*\n\t\t**\tReduce the bytes remaining to output counter and adjust the\n\t\t**\tfile position.\n\t\t*/\n\t\tbytes -= outbytes;\n\t\tbyteswritten += outbytes;\n\t\tFileHandleTable[handle].Pos += outbytes;\n\n\t\t/*\n\t\t**\tIf NO bytes were written out, then this is some kind of unknown\n\t\t**\terror (possibly disk full?).\n\t\t*/\n\t\tif (!outbytes) {\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tPossible adjustment to the file's size.\n\t\t*/\n\t\tif (fileindex != ERROR) {\n\t\t\tfiledata->Size = MAX(filedata->Size, FileHandleTable[handle].Pos);\n\t\t}\n\n\t\t/*\n\t\t**\tAdjust the source pointer in anticipation of the next block write.\n\t\t*/\n\t\tbuf = (char*)(((long)buf) + outbytes);\n\t}\n\n\t/*\n\t**\tReturn with the actual number of bytes written.\n\t*/\n\tCallingDOSInt--;\n\treturn (byteswritten);\n}\n\n\n/***************************************************************************\n * SEEK_FILE -- Adjusts the position of the file pointer.                  *\n *                                                                         *\n *    This routine adjusts the position of the file pointer.  Use this     *\n *    to control where the next Read_File or Write_File will occur.        *\n *                                                                         *\n * INPUT:   handle   -- File handle as returned by Open_File.              *\n *                                                                         *\n *          offset   -- Signed offset from indicated starting position.    *\n *                                                                         *\n *          starting -- SEEK_CUR:   Seeks from the current position.       *\n *                      SEEK_SET:   Seeks from the start of the file.      *\n *                      SEEK_END:   Seeks backward from the end.\t\t\t\t*\n *                                                                         *\n * OUTPUT:  Returns with the new file position.                            *\n *                                                                         *\n * WARNINGS:   Seeking past the end or before the beginning of the file    *\n *             is not allowed.                                             *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/13/1991 JLB : Created.                                             *\n *=========================================================================*/\nunsigned long cdecl Seek_File(int handle, long offset, int starting)\n{\n\tint\t\t\t\t\tdoshandle;\t// DOS specific file handle.\n\tint\t\t\t\t\tfileindex;\t// FileData index (if any).\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\n\t#if(DEBUGPRINT)\n\t\tMono_Printf(\"Seek_File(%d, %ld, %d)\\r\", handle, offset, starting);\n\t#endif\n\n\t/*\n\t**\tCheck to make sure that the file handle is valid.\n\t*/\n\tif (!Is_Handle_Valid(handle, SEEKING_NON_HANDLE, NULL)) {\n\t\treturn(NULL);\n\t}\n\n\tCallingDOSInt++;\n\n\tfileindex = FileHandleTable[handle].Index;\n\tdoshandle = FileHandleTable[handle].Handle;\n\tfiledata = &FileDataPtr[fileindex];\n\n\tif (!doshandle) {\n\n\t\t/*\n\t\t**\tResident file seek is merely an adjustment to the position value.\n\t\t*/\n\t\tswitch (starting) {\n\n\t\t\t/*\n\t\t\t**\tManually position from start of file.\n\t\t\t*/\n\t\t\tcase SEEK_SET:\n\t\t\t\toffset = MAX((long)0, offset);\t\t// Only positive offsets allowed.\n\t\t\t\tFileHandleTable[handle].Pos = NULL;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tPosition is relative to end of file.\n\t\t\t*/\n\t\t\tcase SEEK_END:\n\t\t\t\toffset = MIN((long)0, offset);\t\t// Only negative offsets allowed.\n\t\t\t\tFileHandleTable[handle].Pos = filedata->Size;\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_CUR:\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tDo_IO_Error(SEEKING_BAD_OFFSET, FileHandleTable[handle].Name);\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tPerform the resident file position adjustment.\n\t\t*/\n\t\tFileHandleTable[handle].Pos += offset;\n\n\t\tFileHandleTable[handle].Pos = MIN(FileHandleTable[handle].Pos,  filedata->Size-1);\n\t\tFileHandleTable[handle].Pos = MAX(FileHandleTable[handle].Pos,  (long)0);\n\n\t} else {\n\n\t\t/*\n\t\t**\tSpecial handling for packed file seeks.\n\t\t*/\n\t\tif (fileindex != ERROR && (filedata->Flag & FILEF_PACKED)) {\n\t\t\tswitch (starting) {\n\t\t\t\tcase SEEK_SET:\n\t\t\t\t\tFileHandleTable[handle].Pos = offset;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase SEEK_END:\n\t\t\t\t\t// Only negative offsets allowed.\n\t\t\t\t\t// Do not allow seeking past the beginning.\n\t\t\t\t\toffset = MIN(0L, offset);\t\t\n\t\t\t\t\tif (-offset > filedata->Size) {\n\t\t\t\t\t \tDo_IO_Error(SEEKING_BAD_OFFSET, FileHandleTable[handle].Name);\n\t\t\t\t\t}\n\t\t\t\t\tFileHandleTable[handle].Pos = filedata->Size + offset;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase SEEK_CUR:\n\t\t\t\t\tFileHandleTable[handle].Pos += offset;\n\t\t\t\t\tif (FileHandleTable[handle].Pos < 0) {\n\t\t\t\t\t\tFileHandleTable[handle].Pos = 0;\n\t\t\t\t\t}\n\t\t\t\t\tif (FileHandleTable[handle].Pos >= filedata->Size) {\n\t\t\t\t\t\tFileHandleTable[handle].Pos = filedata->Size;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tDo_IO_Error(SEEKING_BAD_OFFSET, FileHandleTable[handle].Name);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tFILESEEK(doshandle, FileHandleTable[handle].Pos+FileHandleTable[handle].Start, SEEK_SET);\n\t\t\tCallingDOSInt--;\n\t\t\treturn (FileHandleTable[handle].Pos);\n\t\t}\n\t\t/*\n\t\t**\tPerform the straight DOS seek.\n\t\t*/\n\t\tFileHandleTable[handle].Pos = FILESEEK(doshandle, offset, starting);\n\n\t\t/*\n\t\t**\tFile position does not recognize packed offset.\n\t\t*/\n\t\tif (fileindex != ERROR) {\n\t\t\tFileHandleTable[handle].Pos -= FileHandleTable[handle].Start;\n\t\t\t//SKB FileHandleTable[handle].Pos -= filedata->Start;\n\t\t}\n\t}\n\n\t/*\n\t**\tReturn with the current file position.\n\t*/\n\tCallingDOSInt--;\n\treturn (FileHandleTable[handle].Pos);\n}\n\n\n/***************************************************************************\n * FILE_EXISTS -- Searches for and FINDS the specified file.               *\n *                                                                         *\n *    This routine will scan the available drives and return when the file *\n *    is accessable.  This routine is used when the programmer MUST be     *\n *    sure of a file's existance before proceeding.  This process is       *\n *    automatically performed on a Open_File with READ access.             *\n *                                                                         *\n * INPUT:   file_name   -- Name of the file to check for.                  *\n *                                                                         *\n * OUTPUT:  Returns the disk number that the file exits on (A=1, B=2, etc) *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/14/1991 JLB : Created.                                             *\n *=========================================================================*/\nBOOL cdecl File_Exists(char const *file_name)\n{\n\t/*\n\t**\tIf the filename is invalid then it errors out.\n\t*/\n\tif (!file_name) return(FALSE);\n\t/*\n\t**\tContinually search for the file (prompting as needed).  Only return\n\t**\tupon success or error function control reasons.\n\t*/\n\twhile (!Find_File(file_name)) {\n\n\t\t/*\n\t\t**\tIf the file could not be found then request for proper disk.\n\t\t*/\n\t\tdo {\n\t\t\t//struct\tfind_t ffblk;\n\t\t\t//char\t\tpath[MAXPATH];\n\t\t\t\n\t\t\tif (!Do_Open_Error(COULD_NOT_OPEN, file_name)) {\n\t\t\t\treturn(FALSE);\n\t\t\t}\n\t\t\tibm_setdisk(*DataPath - 'A');\n\n\t\t\t// Search for the volume ID so that the disk information get read in again.\n\t\t\t//_dos_findfirst(\"*.*\", _A_VOLID, &ffblk);\n\t\t} while (CHANGEDIR( DataPath ));\n\t}\n\treturn (TRUE);\n}\n\n\n/***************************************************************************\n * FILE_SIZE -- Determine the size of the specified file.                  *\n *                                                                         *\n *    This routine will return with the size of the file specified by the  *\n *    file handle passed in.                                               *\n *                                                                         *\n * INPUT:   handle   -- Westwood file handle.                              *\n *                                                                         *\n * OUTPUT:  Returns with the size of the file in bytes.                    *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1991 JLB : Created.                                             *\n *=========================================================================*/\nunsigned long cdecl File_Size(int handle)\n{\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\n\n\tif (FileHandleTable[handle].Index != ERROR) {\n\t\tfiledata = &FileDataPtr[FileHandleTable[handle].Index];\n\t\t\n\t\tif (filedata->Size) {\n\t\t\treturn(filedata->Size);\n\t\t}\n\t}\n\treturn (filelength(FileHandleTable[handle].Handle));\n}\n\n\n/***************************************************************************\n * IS_HANDLE_VALID -- Determines validity of the specified file handle.    *\n *                                                                         *\n *    Use this routine to determine if a file handle is valid or not.  It  *\n *    checks to see if it falls within legal limits and does in fact       *\n *    reference an open file.  This routine will call the error handler    *\n *    with the specified error number if the handle is not valid.          *\n *                                                                         *\n * INPUT:   handle   -- Handle to check for validity.                      *\n *                                                                         *\n *          error    -- Error number to use when calling the IO_Error      *\n *                      handler.                                           *\n *                                                                         *\n *          name     -- The file name (if known).                          *\n *                                                                         *\n * OUTPUT:  Returns with the file table index, if one exists for this      *\n *          file.                                                          *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/13/1991 JLB : Created.                                             *\n *=========================================================================*/\nBOOL cdecl Is_Handle_Valid(int handle, FileErrorType error, char const *name)\n{\n\t/*\n\t**\tThe handle must be valid or else it is an error.\n\t*/\n\tif (handle < 0 || handle >= TABLE_MAX) {\n\t\t/*\n\t\t**\tERROR: Invalid file handle.\n\t\t*/\n\t\tDo_IO_Error(error, name);\n\t}\n\n\t/*\n\t**\tAn unused file handle causes an error.\n\t*/\n\tif (FileHandleTable[handle].Empty) {\n\t\tDo_IO_Error(error, name);\n\t}\n\n\treturn (TRUE);\n}\n\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/FILE/FILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library - Filio header stuff.            *\n *                                                                         *\n *                    File Name : FILE.H                                 \t*\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : September 13, 1993                       *\n *                                                                         *\n *                  Last Update : April 11, 1994\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FILE_H\n#define FILE_H\n\n\n#ifndef ERROR\n#define\tERROR\t-1\n#endif\n\n#ifndef FILETEMP_H\n// This should be removed once the library is all intacked.\n#include \"filetemp.h\"\n#endif\n\n/*=========================================================================*/\n/* File IO system defines and enumerations\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#define\tXMAXPATH\t80\n\n/*\n**\tThese are the Open_File, Read_File, and Seek_File constants.\n*/\n#define READ\t\t\t\t\t\t1\t// Read access.\n#define WRITE\t\t\t\t\t\t2\t// Write access.\n#ifndef SEEK_SET\n#define SEEK_SET\t\t\t\t\t0\t// Seek from start of file.\n#define SEEK_CUR\t\t\t\t\t1\t// Seek relative from current location.\n#define SEEK_END\t\t\t\t\t2\t// Seek from end of file.\n#endif\n\n\ntypedef enum {\n\tFILEB_PROCESSED=8,// Was the packed file header of this file processed?\n\tFILEB_PRELOAD,\t\t// Scan for and make file resident at WWDOS_Init time?\n\tFILEB_RESIDENT,\t// Make resident at Open_File time?\n\tFILEB_FLUSH,\t\t// Un-resident at Close_File time?\n\tFILEB_PACKED,\t\t// Is this file packed?\n\tFILEB_KEEP,\t\t\t// Don't ever flush this resident file?\n\tFILEB_PRIORITY,\t// Flush this file last?\n\n\tFILEB_LAST\n} FileFlags_Type;\n\n#define\tFILEF_NONE\t\t\t0\n#define\tFILEF_PROCESSED\t(1<<FILEB_PROCESSED)\n#define\tFILEF_PRELOAD\t\t(1<<FILEB_PRELOAD)\n#define\tFILEF_RESIDENT\t\t(1<<FILEB_RESIDENT)\n#define\tFILEF_FLUSH\t\t\t(1<<FILEB_FLUSH)\n#define\tFILEF_PACKED\t\t(1<<FILEB_PACKED)\n#define\tFILEF_KEEP\t\t\t(1<<FILEB_KEEP)\n#define\tFILEF_PRIORITY\t\t(1<<FILEB_PRIORITY)\n\n/*\n** These errors are returned by WWDOS_Init().  All errors encountered are\n** or'd together so there may be more then one error returned.  Not all\n** errors are fatal, such as the cache errors.\n*/\ntypedef enum {\n\tFI_SUCCESS\t\t\t\t\t\t= 0x00,\n\tFI_CACHE_TOO_BIG\t\t\t\t= 0x01,\n\tFI_CACHE_ALREADY_INIT\t\t= 0x02,\n\tFI_FILEDATA_FILE_NOT_FOUND\t= 0x04,\n\tFI_FILEDATA_TOO_BIG\t\t\t= 0x08,\n \tFI_SEARCH_PATH_NOT_FOUND\t= 0x10,\n \tFI_STARTUP_PATH_NOT_FOUND\t= 0x20,\n\tFI_NO_CACHE_FOR_PRELOAD\t\t= 0x40,\n\tFI_FILETABLE_NOT_INIT\t\t= 0x80,\n} FileInitErrorType;\n\n\n/*\n**\tThese are the errors that are detected by the File I/O system and\n**\tpassed to the io error routine.\n*/\n//lint -strong(AJX,FileErrorType)\ntypedef enum {\n\tCANT_CREATE_FILE,\n\tBAD_OPEN_MODE,\n\tCOULD_NOT_OPEN,\n\tTOO_MANY_FILES,\n\tCLOSING_NON_HANDLE,\n\tREADING_NON_HANDLE,\n\tWRITING_NON_HANDLE,\n\tSEEKING_NON_HANDLE,\n\tSEEKING_BAD_OFFSET,\n\tWRITING_RESIDENT,\n\tUNKNOWN_INDEX,\n\tDID_NOT_CLOSE,\n\tFATAL_ERROR,\n\tFILE_NOT_LISTED,\n\tFILE_LENGTH_MISMATCH,\n\tINTERNAL_ERROR,\n\tMAKE_RESIDENT_ZERO_SIZE,\n\tRESIDENT_SORT_FAILURE,\n\n\tNUMBER_OF_ERRORS\t\t\t\t/* MAKE SURE THIS IS THE LAST ENTRY */\n} FileErrorType;\n\n// This is here tempararaly until library is put together.\n//extern WORD cdecl (*cdecl IO_Error)(FileErrorType error, BYTE const *filename);\nextern short (*Open_Error)(FileErrorType, BYTE const *);\n\n/*=========================================================================*/\n/* File IO system structures\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//lint -strong(AJX,FileDataType)\ntypedef struct {\n\tchar\t*Name;\t\t// File name (include sub-directory but not volume).\n\tlong\tSize;\t\t\t// File size (0=indeterminate).\n\tvoid\t*Ptr;\t\t\t// Resident file pointer.\n\tlong\tStart;\t\t// Starting offset in DOS handle file.\n\tunsigned char\tDisk;\t\t\t// Disk number location.\n\tunsigned char\tOpenCount;\t// Count of open locks on resident file.\n\tunsigned short\tFlag;\t\t\t// File control flags.\n} FileDataType;\n\n\n/*=========================================================================*/\n/* FIle IO system globals.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n// These are cpp errors in funtions declarations\tJULIO JEREZ\n\n// extern FileDataType cdecl FileData[];\n// extern BYTE cdecl ExecPath[XMAXPATH + 1];\n// extern BYTE cdecl DataPath[XMAXPATH + 1];\n// extern BYTE cdecl StartPath[XMAXPATH + 1];\n// extern BOOL cdecl UseCD;\n\n// The correct syntax is  NO TYPE MODIFIER APPLY TO DATA DECLARATIONS\nextern FileDataType FileData[];\nextern char ExecPath[XMAXPATH + 1];\nextern char DataPath[XMAXPATH + 1];\nextern char StartPath[XMAXPATH + 1];\nextern BOOL UseCD;\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILEINIT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid cdecl WWDOS_Shutdown(void);\nFileInitErrorType cdecl WWDOS_Init(unsigned long cachesize, char *filedata, char *cdpath);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILE.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint cdecl Open_File(char const *file_name, int mode);\nvoid cdecl Close_File(int handle);\nlong cdecl Read_File(int handle, void *buf, unsigned long bytes);\nlong cdecl Write_File(int handle, void const *buf, unsigned long bytes);\nunsigned long cdecl Seek_File(int handle, long offset, int starting);\nint cdecl File_Exists(char const *file_name);\nunsigned long cdecl File_Size(int handle);\nBOOL cdecl Is_Handle_Valid(int handle, FileErrorType error, char const *name);\nint cdecl Open_File_With_Recovery( char const *file_name, unsigned int mode );\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILECACH.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid Unfragment_File_Cache(void);\nBOOL cdecl Make_File_Resident(char const *filename);\nshort cdecl Flush_Unused_File_Cache(short flush_keeps);\nBOOL cdecl Free_Resident_File(char const *file);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILECHNG.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort cdecl Create_File(char const *file_name);\nshort cdecl Delete_File(char const *file_name);\nBOOL cdecl Change_File_Size(short handle, unsigned long new_size);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILEINFO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort cdecl Get_DOS_Handle(short fh);\nshort cdecl Free_Handles(void);\nshort cdecl Find_Disk_Number(char const *file_name);\nshort cdecl Set_File_Flags(char const *filename, short flags);\nshort cdecl Clear_File_Flags(char const *filename, short flags);\nshort cdecl Get_File_Flags(char const *filename);\nBOOL cdecl Multi_Drive_Search(BOOL on);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FINDFILE.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint cdecl Find_File(char const *file_name);\nint cdecl Find_File_Index(char const *filename);\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FFIRST.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#include <dos.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern short Find_First(unsigned char *fname, unsigned short mode, struct find_t *ffblk);\nextern short Find_Next(struct find_t *ffblk);\n\n#ifdef __cplusplus\n}\n#endif\n\n\n\n\n#endif // FILE_H\n\u001a\n"
  },
  {
    "path": "WWFLAT32/FILE/FILECACH.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library - File Caching routines          *\n *                                                                         *\n *                    File Name : FILECACH.CPP                             *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : September 13, 1993                       *\n *                                                                         *\n *                  Last Update : April 18, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Make_File_Resident -- Makes a file resident even if not flaged so.    *\n *   Flush_Unused_File_Cache -- Flushes the file cache of any non opened fi*\n *   Free_Resident_File -- Free the given file if it is resident.          *\n *   Unfragment_File_Cache -- Does a garbage collection on the file heap.  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWSTD_H\n#include <wwstd.h>\n#endif\t   \n\n#ifndef _FILE_H\n#include \"_file.h\"\n#endif\n\n#ifndef WWMEM_H\n#include <wwmem.h>\n#endif\n\n#include <string.h>\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n/***************************************************************************\n * UNFRAGMENT_FILE_CACHE -- Does a garbage collection on the file heap.    *\n *                                                                         *\n * INPUT:    NONE.                                                         *\n *                                                                         *\n * OUTPUT:   NONE.                                                         *\n *                                                                         *\n * WARNINGS: Can be a lengthy process.                                     *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nVOID Unfragment_File_Cache(VOID)\n{\n\tFileDataType\t*filedata;\n\tFileDataType\t*parent;\n\tUWORD\t\t\t\tidx;\n\n\n\t// Let the memory system clean up the file heap.\n\tMem_Cleanup(FileCacheHeap);\n\n\t// Now get our pointers back.\n\t// Start after the parent PAK files since we will need to check our pointers\n\t// with them.\n\tfiledata = &FileDataPtr[NumPAKFiles];\n\tfor (idx = NumPAKFiles; idx < NumPAKFiles; idx++, filedata++) {\n\twhile (filedata->Name) {\n\n\t\t// Only process files that are in the file cache.\n\t\tif (filedata->Ptr) {\n\n\t\t\t// Is a inner PAK file?\n\t\t\tif (filedata->Flag & FILEF_PACKED) {\n\n\t\t\t\tparent = &FileDataPtr[filedata->Disk];\n\n\t\t\t\t// Is it just a copied pointer of the parent?\n\t\t\t\tif (parent->Ptr == filedata->Ptr) {\t\n\t\t\t\t\tfiledata->Ptr = Mem_Find(FileCacheHeap, filedata->Disk);\n\t\t\t\t}\n\t\t\t\telse \n\t\t\t\t\tfiledata->Ptr = Mem_Find(FileCacheHeap, idx);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t \tfiledata->Ptr = Mem_Find(FileCacheHeap, idx);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Now that the children have been taken care of, let us do the parents.\n\tfor (filedata = FileDataPtr, idx = 0; idx < NumPAKFiles; idx++, filedata++) {\n\n\t\t// Only process files that are in the file cache.\n\t\tif (filedata->Ptr) {\n\t\t \tfiledata->Ptr = Mem_Find(FileCacheHeap, idx);\n\t\t}\n\t}\n}\n\n/***************************************************************************\n * MAKE_FILE_RESIDENT -- Makes a file resident even if not flaged so.      *\n *                                                                         *\n * INPUT:  BYTE *filename - name of file to be made resident.              *\n *                                                                         *\n * OUTPUT: BOOL if successful.  could fail in not enouph RAM or not found. *\n *                                                                         *\n * WARNINGS: File must be in FileData table.                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/13/1993 SKB : Created.                                             *\n *=========================================================================*/\nBOOL Make_File_Resident(BYTE const *filename)\n{\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\tFileDataType\t\thold;\t\t\t\t// Hold buffer for record (DO NOT ACCESS DIRECTLY)\n\tWORD\t\t\t\t\tfileindex;\n\tWORD\t\t\t\t\toldflag;\n\tWORD\t\t\t\t\thandle;\n\n\tfileindex = Find_File_Index(filename);\n\n\t//\tif the file is not in the table, we can't make it resident\n\tif (fileindex == ERROR) return(FALSE);\n\n\t// Get a pointer for quicker pointer action.\n\tfiledata = &FileDataPtr[fileindex];\n\n\t// Change the flags for a moment.\n\toldflag = filedata->Flag;\n\tfiledata->Flag |= FILEF_RESIDENT;\n\tfiledata->Flag &= ~FILEF_FLUSH;\n\n\t// Make the file resident.\n\thandle = Open_File(filename, READ);\n\tClose_File(handle);\n\n\t// Set flags back to normal.\n\tfiledata->Flag = oldflag;\n\n\treturn(TRUE);\n}\n\n/***************************************************************************\n * Flush_Unused_File_Cache -- Flushes the file cache of any non opened files.     *\n *                                                                         *\n * INPUT:     WORD flush_keep - TRUE to flush even files marked FILEF_KEEP.*\n *                                                                         *\n * OUTPUT:    WORD Number of file flushed.                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/23/1993  SB : Created.                                             *\n *=========================================================================*/\nWORD Flush_Unused_File_Cache(WORD flush_keeps) \n{\n\tWORD\t\t\t\tindex;\n\tWORD\t\t\t\tfreed = 0;\n\tFileDataType\t*filedata = NULL;\n\tFileDataType\thold;\t\t\t\t// Hold buffer for record (DO NOT ACCESS DIRECTLY)\n\n\t// Loop throuph the file table looking for files that could be freed.\n\tindex = 0;\n\tfiledata = &FileDataPtr[index];;\n\twhile (filedata->Name && strlen(filedata->Name)) {\n\n\t\tif (filedata->Ptr && !filedata->OpenCount && \n\t\t    (flush_keeps || !(filedata->Flag & FILEF_KEEP)) ) {\n\n\t\t\tMem_Free(FileCacheHeap, filedata->Ptr);\n\t\t\tfiledata->Ptr = NULL;\n\t\t\tfreed++;\n\t\t}\n\t\tindex++;\n\t\tfiledata = &FileDataPtr[index];;\n\t}\n\treturn (freed);\n}\n\n/***************************************************************************\n * FREE_RESIDENT_FILE -- Free the given file if it is resident.            *\n *                                                                         *\n * INPUT:      BYTE *file to free                                          *\n *                                                                         *\n * OUTPUT:     TRUE if file was free'd, FALSE otherwise                    *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/22/1992  CY : Created.                                             *\n *=========================================================================*/\nBOOL cdecl Free_Resident_File(BYTE const *file)\n{\n\tWORD\t\t\t\t\tfileindex;\n\tBOOL\t\t\t\t\toldflag;\t\t\t// Previous file flag.\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\tFileDataType\t\thold;\t\t\t\t// Hold buffer for record (DO NOT ACCESS DIRECTLY)\n\n\n\t//\tif the file is not in the table, we can't free it\n\tif ((fileindex = Find_File_Index(file)) == ERROR) {\n\t\treturn(FALSE);\n\t}\n\n\t// get a pointer for quicker calculations.\n\tfiledata = &FileDataPtr[fileindex];\n\n\t// If it isn't resident, don't try to Free it\n\tif (filedata->Ptr == NULL) {\n\t\treturn(TRUE);\n\t}\n\n\t// Change the flags for a moment.\n\toldflag = filedata->Flag;\n\tfiledata->Flag &= ~(FILEF_RESIDENT|FILEF_KEEP);\n\tfiledata->Flag |= FILEF_FLUSH;\n\n\t// Get the file out of Memory if it was there.\n\tClose_File(Open_File(file, READ));\n\n\t// Set flags back to original.\n\tfiledata->Flag = oldflag;\n\n\treturn(TRUE);\n}\n\n"
  },
  {
    "path": "WWFLAT32/FILE/FILECHNG.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library - File functions.                *\n *                                                                         *\n *                    File Name : FILECHNG.CPP                             *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : September 13, 1993                       *\n *                                                                         *\n *                  Last Update : September 13, 1993   [SKB]               *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Delete_File -- Deletes the file from the disk.                        *\n *   Create_File -- Creates an empty file on disk.                         *\n *   Change_File_Size -- Change the size of a writting file.               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n#ifndef _FILE_H\n#include \"_file.h\"\n#endif\n\n#ifndef WWMEM_H\n#include <wwmem.h>\n#endif\n\n#include <io.h>\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * CREATE_FILE -- Creates an empty file on disk.                           *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/24/1992 JLB : Created.                                             *\n *=========================================================================*/\nWORD cdecl Create_File(BYTE const *file_name)\n{\n\tWORD fd;\n\n\tif (!file_name) return(FALSE);\n\n\tfd = Open_File(file_name, WRITE);\n\tif (fd != ERROR) {\n\t\tClose_File(fd);\n\t\treturn(TRUE);\n\t}\n\treturn(FALSE);\n}\n\n\n/***************************************************************************\n * DELETE_FILE -- Deletes the file from the disk.                          *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/24/1992 JLB : Created.                                             *\n *=========================================================================*/\nWORD cdecl Delete_File(BYTE const *file_name)\n{\n\tWORD\t\t\t\t\tindex;\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\tFileDataType\t\thold;\t\t\t\t// Hold buffer for record (DO NOT ACCESS DIRECTLY)\n\n\tif (!file_name) return(FALSE);\n\n\tCallingDOSInt++;\n\n\tibm_setdisk(*StartPath - 'A');\n\n\tindex = Find_File_Index(file_name);\n\tfiledata = &FileDataPtr[index];\n\n\tif (index != ERROR && filedata->Ptr) {\n\t\tMem_Free(FileCacheHeap, filedata->Ptr);\n\t\tfiledata->Ptr = NULL;\n\t}\n\n\tindex = !FILEDELETE(file_name);\n\tCallingDOSInt--;\n\treturn(index);\n}\n\n\n\n/***************************************************************************\n * CHANGE_FILE_SIZE -- Change the size of a writting file.                 *\n *                                                                         *\n * INPUT:   WORD handle - handle of file.                                  *\n *          ULONG new_size - size of new handle.                           *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/13/1993 SKB : Created.                                             *\n *=========================================================================*/\nBOOL cdecl Change_File_Size(WORD handle, ULONG new_size)\n{\n\tWORD entry;\n\n\tif (Is_Handle_Valid(handle, WRITING_NON_HANDLE, NULL)) {\n\t\tentry = Get_DOS_Handle(handle);\n\t\tif (entry != ERROR) {\n\t\t\treturn(chsize(entry, new_size) != ERROR);\n\t\t}\n\t}\n\treturn(FALSE);\n}\n"
  },
  {
    "path": "WWFLAT32/FILE/FILEDATA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : File IO System LIbrary                   *\n *                                                                         *\n *                    File Name : FILEDATA.CPP                             *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 11, 1994                           *\n *                                                                         *\n *                  Last Update : April 11, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n#ifndef _FILE_H\n#include \"_file.h\"\n#endif\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/* \n\tstructure for FileDataType is:\n\n\tBYTE *filename:\tinitialize to actual file name on disk.\n\tLONG size:\t\t\tinitialize to actual file size on disk.\n\tBYTE *ptr:\t\t\tinitialize to a 0L below.\n\tWORD disk:\t\t\twhich floppy disk number (1+) file resides on.\n\tLONG pos:\t\t\tinitialize to a 0L below.\t\t\t\t\n\tUBYTE priority:\tfile priorities can be from 0 to 127. (127 = highest)\n \t\t\t\t\t\t\tif you want the file to be attempted to be made\n\t\t\t\t\t\t\tresident at runtime, add 128 to the file priority\n\t\t\t\t\t\t\tto set the high bit. even though the files\n\t\t\t\t\t\t\tpriority will appear to be 128 to 255, it will\n\t\t\t\t\t\t\tstill remain 0 to 127.\n*/\t\n\nFileDataType FileData[] = {\n\t{ \t\"\",               0L, \t\t0L, \t0, 0L,\t0\t\t\t}\n\t/* Must have an empty entry!!! */\n};\n"
  },
  {
    "path": "WWFLAT32/FILE/FILEGLOB.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : FILEIO Library                           *\n *                                                                         *\n *                    File Name : FILEGLOB.C                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 11, 1994                           *\n *                                                                         *\n *                  Last Update : April 11, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#include <wwstd.h>\n#endif\t   \n\n#ifndef FILE_H\n#include \"_file.h\"\n#endif\n\n#include <process.h>\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/* Global varaiables */\nBYTE ExecPath[XMAXPATH + 1];\nBYTE DataPath[XMAXPATH + 1];\nBYTE StartPath[XMAXPATH + 1];\nBOOL UseCD;\n\n/* File System only Global varaiables */\nBYTE CallingDOSInt;\t\t\t\t\t\t\t\t\t// Indicate we are performing a DOS function\nBYTE MaxDevice,DefaultDrive;\t\t\t\t\t\t\nBYTE MultiDriveSearch = TRUE;\t\t\t\t\t\t// Multiple drive search flag\nFileDataType *FileDataPtr = NULL;\nFileHandleType FileHandleTable[TABLE_MAX];\nUWORD NumFiles;\t\t\t\t\t\t\t\t\t\t// Number of files, except PAK, in file table.\nUWORD NumPAKFiles;\t\t\t\t\t\t\t\t\t// Number of PAK files in filetable.\nVOID *FileCacheHeap = NULL;\t\t\t\t\t\t// Pointer to the cache in memory.\nWORD DiskNumber;\t\t\t\t\t\t\t\t\t\t// Where file was found (-1 == current directory).\nWORD MaxDirNum = 0;\n\n\nWORD (*Open_Error)(FileErrorType, BYTE const *) = NULL;\n"
  },
  {
    "path": "WWFLAT32/FILE/FILEINFO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library - Fileio information functions.  *\n *                                                                         *\n *                    File Name : FILE.CPP                             \t\t*\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : September 13, 1993                       *\n *                                                                         *\n *                  Last Update : April 19, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Get_DOS_Handle -- Fetches system specific DOS file handle.            *\n *   Find_Disk_Number -- Determine disk a file resides upon.               *\n *   Set_File_Flags -- Sets flags for file if FileData table.              *\n *   Get_File_Flags -- Gets the flags on a file in the FileData table.     *\n *   Free_Handles -- Returns number of free file handles in WW system.     *\n *   Multi_Drive_Search -- Turns Multi search drive on and off.            *\n *   Clear_File_Flags -- Clears flags specified for file.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n#ifndef _FILE_H\n#include \"_file.h\"\n#endif\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * GET_DOS_HANDLE -- Fetches system specific DOS file handle.              *\n *                                                                         *\n *    This routine will return with the system specific DOS file handle.   *\n *    On the IBM, this is a WORD, on the Amiga, it is a LONG (BPTR).  Use  *\n *    this routine with caution, because the value returned is NOT         *\n *    portable.                                                            *\n *                                                                         *\n * INPUT:   fh -- Westwood file system handle.                             *\n *                                                                         *\n * OUTPUT:  Returns with the system DOS file handle (WORD or LONG).        *\n *                                                                         *\n * WARNINGS:   If you pass in an invalid file handle, or a file handle     *\n *             that references a resident file, then the ERROR code is     *\n *             returned.  Be SURE to check for this.                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/21/1991 JLB : Created.                                             *\n *   11/09/1991 JLB : Checks for illegal file handle passed in.            *\n *=========================================================================*/\nWORD cdecl Get_DOS_Handle(WORD fh)\n{\n\t/*\n\t**\tIf an illegal file handle is passed in then always abort.\n\t*/\n\tif (fh >= 0 && fh < TABLE_MAX) {\n\t\tif (!FileHandleTable[fh].Empty || FileHandleTable[fh].Handle) {\n\t\t\treturn(FileHandleTable[fh].Handle);\n\t\t}\n\n\t\t/*\n\t\t**\tIf it falls through here, then the file must be resident.  It is\n\t\t**\tillegal to get a DOS handle to a resident file.\n\t\t*/\n\t}\n\treturn(FILEOPENERROR);\n}\n\n/***************************************************************************\n * FREE_HANDLES -- Returns number of free file handles in WW system.       *\n *                                                                         *\n * INPUT:    NONE.                                                         *\n *                                                                         *\n * OUTPUT:   NONE.                                                         *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/13/1993 SKB : Created.                                             *\n *=========================================================================*/\nWORD cdecl Free_Handles(VOID)\n{\n\tWORD\tcount;\t\t// Count of the number of free file handles.\n\tWORD\tindex;\t\t// Working file handle index var.\n\t\n\tcount = 0;\n\tfor (index = 0; index < TABLE_MAX; index++) {\n\t\tif (FileHandleTable[index].Empty) count++;\n\t}\n\treturn(count);\n}\n\n\n\n/***************************************************************************\n * FIND_DISK_NUMBER -- Determine disk a file resides upon.                 *\n *                                                                         *\n *    This routine will determine the disk number that the specified       *\n *    file resides upon.  It determines this by scanning through the       *\n *    FileData table.  If the specified file is a packed file, then it     *\n *    will reference the parent packed file to determine the disk number.  *\n *                                                                         *\n * INPUT:   file_name   -- Pointer to the file name to check.              *\n *                                                                         *\n * OUTPUT:  Returns with the disk number that the file resides upon.  If   *\n *          ERROR is returned, then the file does not exist in the         *\n *          FileTable.  The number returned is 0=A, 1=B, etc.              *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1991 JLB : Created.                                             *\n *=========================================================================*/\nWORD cdecl Find_Disk_Number(BYTE const *file_name)\n{\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\tWORD\t\t\t\t\tindex;\t// FileTable index.\n\n\tindex = Find_File_Index(file_name);\n\n\tif (index != ERROR) {\n\t\t\n\t\tfiledata = &FileDataPtr[index];\n\n\t\tif (filedata->Flag & FILEF_PACKED) {\n\t\t\treturn (Find_Disk_Number(FileDataPtr[filedata->Disk].Name));\n\t\t}\n\t\treturn(filedata->Disk);\n\t}\n\treturn (index);\n}\n\n\n\n\n\n/***************************************************************************\n * SET_FILE_FLAGS -- Sets flags for file if FileData table.                *\n *                                                                         *\n * INPUT:  BYTE *filename - file to modify.                                *\n *         WORD flags - flags to set in file.                              *\n *                                                                         *\n * OUTPUT: WORD - if file found in FileData table.                         *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/04/1993 SKB : Created.                                             *\n *=========================================================================*/\nWORD cdecl Set_File_Flags(BYTE const *filename, WORD flags)\n{\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\tWORD\t\t\t\t\tindex;\t// FileTable index.\n\n\tindex = Find_File_Index(filename);\n\n\tif (index != ERROR) {\n\t\tfiledata = &FileDataPtr[index];\n\t\tfiledata->Flag |= flags;\n\t\treturn (TRUE);\n\t}\n\n\treturn (FALSE);\n}\n\n\n/***************************************************************************\n * CLEAR_FILE_FLAGS -- Clears flags specified for file.                    *\n *                                                                         *\n * INPUT:  BYTE *filename - file to modify.                                *\n *         WORD flags - flags to set in file.                              *\n *                                                                         *\n * OUTPUT: WORD - if file found in FileData table.                         *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1994 SKB : Created.                                             *\n *=========================================================================*/\nWORD cdecl Clear_File_Flags(BYTE const *filename, WORD flags)\n{\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\tWORD\t\t\t\t\tindex;\t// FileTable index.\n\n\tindex = Find_File_Index(filename);\n\n\tif (index != ERROR) {\n\t\tfiledata = &FileDataPtr[index];\n\t\tfiledata->Flag &= ~flags;\n\t\treturn (TRUE);\n\t}\n\n\treturn (FALSE);\n}\n\n\n\n/***************************************************************************\n * GET_FILE_FLAGS -- Gets the flags on a file in the FileData table.       *\n *                                                                         *\n *                                                                         *\n * INPUT:  BYTE *filename - file to modify.                                *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * OUTPUT: WORD - if file found in FileData table.                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/04/1993 SKB : Created.                                             *\n *=========================================================================*/\nWORD cdecl Get_File_Flags(BYTE const *filename)\n{\n\tFileDataType\t  \t*filedata;\t\t// Pointer to the current FileData.\n\tWORD\t\t\t\t\tindex;\t// FileTable index.\n\n\tindex = Find_File_Index(filename);\n\n\tif (index != ERROR) {\n\t\tfiledata = &FileDataPtr[index];\n\t\treturn (filedata->Flag);\n\t}\n\treturn (FALSE);\n}\n\n\n/***************************************************************************\n * MULTI_DRIVE_SEARCH -- Turns Multi search drive on and off.              *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/13/1993 SKB : Created.                                             *\n *=========================================================================*/\nBOOL cdecl Multi_Drive_Search(BOOL on)\n{\n\tBOOL\told;\n\n\tHard_Error_Occured = 0;\n\told = MultiDriveSearch;\n\tMultiDriveSearch = on;\n\treturn(old);\n}\n"
  },
  {
    "path": "WWFLAT32/FILE/FILEINIT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library - Fileio init routines.          *\n *                                                                         *\n *                    File Name : FILEINIT.C                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : September 13, 1993                       *\n *                                                                         *\n *                  Last Update : April 19, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   WWDOS_Init -- Initialize the fileio WWS fileio system.                *\n *   WWDOS_Shutdown -- Clean up any things that needs to be to exit game.  *\n *   Init_FileData_Table -- Initializes or reads in FileData Table.        *\n *   Sort_FileData_Table -- Sorts the FileData table that is in memory.    *\n *   Preload_Files -- Loads files marked with FILEF_PRELOAD into cache.    *\n *   Init_File_Cache -- Initializes and allocs the file cache heap.        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n#ifndef _FILE_H\n#include \"_file.h\"\n#endif\n\n#ifndef WWMEM_H\n#include <wwmem.h>\n#endif\n\n#ifndef MISC_H\n#include <misc.h>\n#endif\n\n#include <direct.h>\n#include <search.h>\n#include <string.h>\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE FileInitErrorType cdecl Init_File_Cache(ULONG cachesize);\nPRIVATE FileInitErrorType cdecl Init_FileData_Table(BYTE const *filename);\nPRIVATE FileInitErrorType cdecl Set_Search_Drives( BYTE *cdpath );\nPRIVATE FileInitErrorType cdecl Preload_Files(VOID);\nPRIVATE int QSort_Comp_Func(const void *p1, const void *p2);\nPRIVATE VOID Sort_FileData_Table(VOID);\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n/***************************************************************************\n * WWDOS_INIT -- Initialize the fileio WWS fileio system.                  *\n *                                                                         *\n *                                                                         *\n * INPUT:   ULONG cachesize - size wanted for the cache.                   *\n *          BYTE *filedat - NULL or name of filedata table file.           *\n *          BYTE *cdpath - NULL or secondary search path on a CD.          *\n *                                                                         *\n * OUTPUT:  Returns all errors encountered or'd together.\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:  User should call the WWDOS_Init function for all file \t\t\t*\n *            initialization.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1994 SKB : Created.                                             *\n *=========================================================================*/\nFileInitErrorType cdecl WWDOS_Init(ULONG cachesize, BYTE *filedata, BYTE *cdpath)\n{\n//\tFileInitErrorType errors;\n\tunsigned errors ;\n\t\n\t// This has not been completed yet, when it is, uncomment it and add errors.\n\tInstall_Hard_Error_Handler () ;\n\tGet_Devices();\n\n\tif (cachesize) {\t\n\t\terrors = Init_File_Cache(cachesize);\n\t} else {\n\t \terrors = FI_SUCCESS;\n\t}\n\n\n\terrors = errors | Init_FileData_Table(filedata);\n\n\terrors = errors | Set_Search_Drives(cdpath);\n\n\terrors = errors | Preload_Files();\n\n\n\treturn ( FileInitErrorType ) errors ;\n}\n\n/***************************************************************************\n * WWDOS_SHUTDOWN -- Clean up any things that needs to be in file syste to *\n *                   exit game.    \t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                   One could shut down the file system and open it back  *\n *                   up with a different size cache or filetable.          *\n *                                                                         *\n * INPUT:   NONE.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:  NONE.                                                          *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1994 SKB : Created.                                             *\n *=========================================================================*/\nVOID cdecl WWDOS_Shutdown(VOID)\n{\n\tFileDataType\t\t\t*filedata;\t\t\t\t\t// Pointer to the current FileData.\n\tWORD\t\t\t\t\t\tfile_handle;\n\tFileHandleType\t\t  \t*filehandletable;\t\t\t// Pointer to the current file handle.\n\n\t// Close all open files.\n\tfilehandletable = FileHandleTable;\n\tfor (file_handle = 0; file_handle < TABLE_MAX; file_handle++, filehandletable++) {\n\t\tif (!filehandletable->Empty) {\n\t\t  \tClose_File(file_handle);\n\t\t}\n\t}\n\n\t// Free the file cache heap.\n\tif (FileCacheHeap) {\n\n\t\t// Get a pointer to the current filedata.\n\t\tif (FileDataPtr) {\n\t \t\tfiledata = FileDataPtr;\n\t\t} else {\n\t \t\tfiledata = FileData;\n\t\t}\n\n\t\twhile(filedata->Name && filedata->Name[0]) {\n\t\t\tfiledata->Ptr = NULL;\n\t\t\tfiledata++;\n\t\t}\n\n\t\tFree(FileCacheHeap);\n\t\tFileCacheHeap = NULL;\n\t}\n\n\t// Free up the file data.\n\tif (FileDataPtr != FileData) {\n\t\tFree(FileDataPtr);\n\t}\n\tFileDataPtr = NULL;\n\n\tchdir(StartPath);\n\tibm_setdisk(*StartPath - 'A');\n\n\t// This has not been completed yet, when it is, uncomment it and add errors.\n\tRemove_Hard_Error_Handler();\n}\n\n\n/***************************************************************************\n * INIT_FILE_CACHE -- Initializes and allocs the file cache heap.          *\n *                                                                         *\n * INPUT:  ULONG cachesize - size of heap cache..                          *\n *                                                                         *\n * OUTPUT: FileInitErrorType  error code.                                  *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1994 SKB : Created.                                             *\n *=========================================================================*/\nPRIVATE FileInitErrorType cdecl Init_File_Cache(ULONG cachesize)\n{\n\t// Allocate and initialize the file cache heap.\n\tif (FileCacheHeap) {\n \t \treturn (FI_CACHE_ALREADY_INIT);\n\t}\n\n\tif ((Ram_Free(MEM_NORMAL) >= cachesize)) {\n\t\tFileCacheHeap = Alloc(cachesize, MEM_NORMAL);\n\t\tMem_Init(FileCacheHeap, cachesize);\n\t}\n\n\tif (!FileCacheHeap) {\n\t \treturn (FI_CACHE_TOO_BIG);\n\t}\n\n\treturn (FI_SUCCESS);\n}\n\n\n\n\n/***************************************************************************\n * INIT_FILEDATA_TABLE -- Initializes or reads in FileData Table.          *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT: FileInitErrorType  error code.                                  *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/13/1993 SKB : Created.                                             *\n *=========================================================================*/\nPRIVATE FileInitErrorType cdecl Init_FileData_Table(BYTE const *filename)\n{\n\tWORD\t\t\t\t\tfd;\n\tULONG\t\t\t\t\tfsize;\n\tFileDataType\t\t*ptr;\n\tWORD \t\t\t\t\tindex;\n\tBYTE\t\t\t\t\tfname[13];\t\t\n\n\t/*\n\t**\tInialize the file handle table to reflect no files open.\n\t*/\n\tfor (index = 0; index < TABLE_MAX; index++) {\n\t\tFileHandleTable[index].Empty = TRUE;\n\t}\n\n\t// Set up our FileData ptr to be the initial FileData table.\n\tFileDataPtr = FileData;\n\n\t// Sort the filedata table.\n\t// This needs to be done even if we load it off disk since the initial file data\n\t// table might contain a filename.\n\tSort_FileData_Table();\n\n\t// If there is a file name, then the filedata table will be loaded from disk.\n\tif (filename) {\n\t\tif (!Find_File(filename)) {\n\t\t \treturn (FI_FILEDATA_FILE_NOT_FOUND);\n\t\t}\n\t\tfd = Open_File(filename, READ);\n\n\t\tfsize = File_Size(fd);\n\n\t\tif ((Ram_Free(MEM_NORMAL) < fsize)) {\n\t\t\tClose_File(fd);\n\t\t \treturn (FI_FILEDATA_TOO_BIG);\n\t\t}\n\n\t\t// Allocate some system memory.\n\t\t// Setup the new FileDataPtr and this time.\n\t\tFileDataPtr = ptr = (FileDataType *) Alloc(fsize, MEM_NORMAL);\n\n\t\t// Load the file up into  memory.\n\t\tRead_File(fd, FileDataPtr, fsize);\n\t\tClose_File(fd);\n\n\t\t// Process the filetable.  The filenames need their pointers adjusted.\n\t\t// At this time we will also count the number of files and number of PAK files.\n\t\tNumPAKFiles = NumFiles = 0;\n\n\t\t// Make sure that the file name will have a NUL at the end.\n\t\tfname[12] = 0;\n\t\twhile(TRUE) {\n\t\t\t// Have we reached the end of the list?\t\n\t\t\tif (!ptr->Name) break;\n\t\t \t\n\t\t\t// Adjust the name pointer to point the the correct area.\n\t\t\tptr->Name = (BYTE *)FileDataPtr + (LONG) ptr->Name;\n\n\t\t\t// Count up weather it is a PAK file or a normal file.\n\t\t\tif (!NumFiles && strstr((char *) ptr->Name, (char *)  \".PAK\")) {\n\t\t\t \tNumPAKFiles++;\n\n\t\t\t\t// Mark that it has been processed so that Open_File() will not do it.\n\t\t\t\tptr->Flag |= FILEF_PROCESSED;\n\n\t\t\t} else {\n\t\t\t\tNumFiles++;\n\t\t\t}\n\n\t\t\t// Next record.\n\t\t\tptr++;\n\t\t}\n\t}\n\n\treturn (FI_SUCCESS);\n}\n\n\n\n\n/***************************************************************************\n * Set_Search_Drives -- Sets up the CDRom and HardDrive paths.             *\n *                                                                         *\n * INPUT:    BYTE *cdpath - path of data files on a CD.\t\t\t\t\t\t\t*\n *           \t\t\t\t\t Should pass in NULL for non CD products.\t\t\t*\n *           \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT: FileInitErrorType  error code.                                  *\n *           Varibable defined:                                            *\n *               ExecPath = Full path of EXE file.                         *\n *               StartPath = Directory user started in.                    *\n *               DataPath = secondary search path (typically CD-ROM).      *\n *           Note: format of paths is \"C:\\PATH\"                           \t*\n *                                                                         *\n * WARNINGS: The cdpath may be overiden by a \"-CD<path>\" command line      *\n *           arguement that specifies another drive (HARD or CD) and path  *\n *           where the data resides.  Whenever a file is opened, it checks *\n *           the startup drive first, then the CD search path if the first *\n *           search was unsuccessful.                                      *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/14/1993  SB : Created.                                             *\n *   04/19/1994 SKB : Mods for 32 bit library.                             *\n *=========================================================================*/\nPRIVATE FileInitErrorType cdecl Set_Search_Drives( BYTE *cdpath )\n{\n\tBYTE *ptr;\n\n\n#if LIB_EXTERNS_RESOLVED \n\t// NOTE: THIS IS WRONG, THIS IS NOT THE WAY TO GET THE EXE's PATH.\n\t// Locate the executable.\t\n\tstrcpy(ExecPath, _argv[0]);\n\n\t// Find the very last '\\' on the path.\n\tptr = strrchr((char *) ExecPath, (int) '\\\\');\n#else\n\tptr = NULL;\n#endif\n\n\t// Remove the exe name to just have the path.\n\tif (ptr == NULL) {\n\t\t*ExecPath = 0;\n\t}\n\telse {\n\t \t*ptr = 0; \n\t}\n\n\t// Did the user specify a second path?\n\tptr = Find_Argv(\"-CD\");\n\n\t// If so, set the data path to that.\n\tif (ptr) {\n\t\tstrcpy(DataPath, ptr + 3);\n\t}\n\t// Otherwise check to see if there is a CD-Rom drive.\n\telse {\n\t\tif (cdpath && *cdpath) {\n\n#if LIB_EXTERNS_RESOLVED\n\t\t\tUseCD = GetCDDrive();\n#else\n\t\t\tUseCD = FALSE;\n#endif\n\t\t}\n\t\telse {\n\t\t \tUseCD = FALSE;\n\t\t}\n\n\t\t// If so, set the Drive to it and find out if any directories.\n\t\tif ( UseCD ) {\n\t\t\tstrcpy( DataPath, \"A:\" );\n\t\t\tstrcat( DataPath, cdpath);\n\t\t\t*DataPath = 'A'+UseCD;\n\t\t}\n\t\t// If not, set the Data path to the execacutable path.\n\t\telse {\n\t \t\tstrcpy(DataPath, ExecPath);\n\t\t}\n\t}\n\n\t// Finnally, set the starting path.\n\tgetcwd(StartPath, XMAXPATH);\n\n\t// Make sure they are all uppercase.\n\tstrupr(StartPath);\n\tstrupr(DataPath);\n\tstrupr(ExecPath);\n\n\t// Change directories to the secondary search path (DataPath).\n\tif (*DataPath && chdir(DataPath)) {\n\t\treturn (FI_SEARCH_PATH_NOT_FOUND);\n\t}\n\n\t// Lastley, Make sure we are in the startup directory.  This will overide\n\t// the secondary data path if they are on the same drive.\n\tif (chdir(StartPath)) {\n\t\treturn (FI_STARTUP_PATH_NOT_FOUND);\n\t}\n\n\treturn (FI_SUCCESS);\n}\n\n\n/***************************************************************************\n * PRELOAD_FILES -- Loads files marked with FILEF_PRELOAD into cache.      *\n *                                                                         *\n *                                                                         *\n * INPUT:  none.                                                           *\n *                                                                         *\n * OUTPUT: FileInitErrorType  error code.                                  *\n *                                                                         *\n * WARNINGS: The FileData must be initialized and the file heap initialized*\n *           in order for this to work.                                    *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1994 SKB : Created.                                             *\n *=========================================================================*/\nPRIVATE FileInitErrorType cdecl Preload_Files(VOID)\n{\n\tFileDataType\t*filedata;\t\t// Working file data table pointer.\n\tBOOL\t\t\t\toldflag;\t\t\t// Previous file flag.\n\n\tif (!FileDataPtr) {\n\t\treturn (FI_FILETABLE_NOT_INIT);\n\t}\n\n\tif (!FileCacheHeap) {\n\t\treturn (FI_NO_CACHE_FOR_PRELOAD);\n\t}\n\n\t/*\n\t**\tMake all files flagged to be made resident at startup, resident.\n\t*/\n\tfiledata = FileDataPtr;\n\n\twhile (filedata->Name && strlen(filedata->Name)) {\n\t\tif (filedata->Flag & FILEF_PRELOAD) {\n\n\t\t\toldflag = filedata->Flag;\n\t\t\tfiledata->Flag |= FILEF_RESIDENT;\t// Make it resident.\n\t\t\tfiledata->Flag &= ~FILEF_FLUSH;\t\t// Don't purge on Close_File.\n\n\t\t\tClose_File(Open_File(filedata->Name, READ));\n\n\t\t\tfiledata->Flag &= ~(FILEF_RESIDENT|FILEF_FLUSH);\t// Clear bits.\n\t\t\tfiledata->Flag |= oldflag & (FILEF_RESIDENT|FILEF_FLUSH);\t// Restore bits.\n\n\t\t}\n\t\tfiledata++;\n\t}\n\treturn (FI_SUCCESS);\n}\n\n\n\n/***************************************************************************\n * SORT_FILEDATA_TABLE -- Sorts the FileData table that is in memory.      *\n *                                                                         *\n * INPUT:  NONE                                                            *\n *                                                                         *\n * OUTPUT: NONE.                                                           *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/13/1993 SKB : Created.                                             *\n *=========================================================================*/\n\nPRIVATE int QSort_Comp_Func(const void *p1, const void *p2)\n{\n\treturn(strcmp(((FileDataType*)p1)->Name, ((FileDataType*)p2)->Name));\n}\nPRIVATE VOID Sort_FileData_Table(VOID)\n{\n\t/*\n\t**\tSort the filetable it but keep the pack file indexes correct.\n\t*/\n\n\t/*\n\t**\tThe number of pak files in the file table.\n\t*/\n\tNumPAKFiles = 0;\n\tstrupr(FileData[NumPAKFiles].Name);\n\twhile (strstr((char *) FileData[NumPAKFiles].Name, (char *) \".PAK\")) {\n\t\tstrupr(FileData[NumPAKFiles].Name);\n\t\tNumPAKFiles++;\n\t}\n\n\t/*\n\t**\tCount the remaining files within the file table.\n\t*/\n\tNumFiles = 0;\n\twhile(FileData[NumFiles+NumPAKFiles].Name && FileData[NumFiles+NumPAKFiles].Name[0]) {\n\t\tstrupr(FileData[NumFiles+NumPAKFiles].Name);\n\t\tNumFiles++;\n\t}\n\n\t/*\n\t**\tSort the file entries (past the pak files).\n\t*/\n\tif (NumFiles) {\n\t\tqsort(&FileData[NumPAKFiles], NumFiles, sizeof(FileDataType), QSort_Comp_Func);\n\t}\n}\n\u001a\n"
  },
  {
    "path": "WWFLAT32/FILE/FILEIO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : FILEIO.C                                 *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : August 21, 1991                          *\n *                                                                         *\n *                  Last Update : September 13, 1993   [SKB]               *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n#ifndef _FILE_H\n#include \"_file.h\"\n#endif\n\n#include <dos.h>\n#include <direct.h>\n#include <io.h>\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\nWORD ibm_getdisk(VOID)\n{\n\tunsigned disk;\n\n\tCallingDOSInt++;\n  //\tdisk = getdisk();\n\t_dos_getdrive ( & disk ) ;\n\tCallingDOSInt--;\n\treturn(disk-1);\n}\n\nWORD ibm_setdisk(WORD drive)\n{\n//\tWORD disk;\n\tunsigned disk ;\n\n\tCallingDOSInt++;\n//\tdisk = setdisk(drive);\n\t_dos_setdrive ( drive+1 , & disk ) ;\n\tCallingDOSInt--;\n\treturn(disk);\n}\n\nWORD ibm_close(WORD handle)\n{\n\tWORD success;\n\n\tCallingDOSInt++;\n\tsuccess = close(handle);\n\tCallingDOSInt--;\n\treturn(success);\n}\n\nWORD ibm_unlink(BYTE const *name)\n{\n\tWORD success;\n\n\tCallingDOSInt++;\n\tsuccess = unlink(name);\n\tCallingDOSInt--;\n\treturn(success);\n}\n\nLONG ibm_lseek(WORD handle, LONG offset, WORD where)\n{\n\tLONG new_offset;\n\n\tCallingDOSInt++;\n\tnew_offset = lseek(handle, offset, where);\n\tCallingDOSInt--;\n\treturn(new_offset);\n}\n\nUWORD ibm_read(WORD handle, VOID *ptr, UWORD bytes)\n{\n\tUWORD bytes_read;\n\n\tCallingDOSInt++;\n\tbytes_read = read(handle, ptr, bytes);\n\tCallingDOSInt--;\n\treturn(bytes_read);\n}\n\nUWORD ibm_write(WORD handle, VOID *ptr, UWORD bytes)\n{\n\tUWORD bytes_written;\n\n\tCallingDOSInt++;\n\tbytes_written = write(handle, ptr, bytes);\n\tCallingDOSInt--;\n\treturn(bytes_written);\n}\n\nWORD ibm_open(BYTE const *name, UWORD mode, WORD attrib)\n{\n\tWORD handle;\n\n\tCallingDOSInt++;\n\thandle = open(name, mode, attrib);\n\tCallingDOSInt--;\n\treturn(handle);\n}\n\nWORD ibm_chdir(BYTE const *path)\n{\n\tWORD retval;\n\n\tCallingDOSInt++;\n\tretval = chdir(path);\n\tCallingDOSInt--;\n\treturn(retval);\n}\n\n\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/FILE/FILELIB.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : FILEIO Library support routines.         *\n *                                                                         *\n *                    File Name : FILELIB.C                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 11, 1994                           *\n *                                                                         *\n *                  Last Update : April 11, 1994   [SKB]                   *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *  Notes: This file contains private functions to the fileio system.      *\n *         While these functions may be used by any module in the fileio   *\n *         system, they cannot be used by a user program.  For this reason *\n *         they are put into this module.                                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Cache_File -- Attempts to cache file in XMS if flags set.             *\n *   Do_IO_Error -- Performs a non-recoverable error message display.      *\n *   Do_Open_Error -- Does an error message that could return.             *\n *   Is_Handle_Valid -- Determines validity of the specified file handle.  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n#ifndef _FILE_H\n#include \"_file.h\"\n#endif\n\n#ifndef WWMEM_H\n#include <wwmem.h>\n#endif\n\n\n#include <fcntl.h>\n#include <io.h>\n#include <process.h>\n#include <sys\\stat.h>\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * DO_ERROR -- Does an error message that could return.               *\n *                                                                         *\n *    This routine displays a file error message and unless the player     *\n *    presses <ESC>, it will return.  If the player presses <ESC>, then    *\n *    it will terminate the program.                                       *\n *                                                                         *\n * INPUT:   error    -- Error message number.                              *\n *                                                                         *\n *          filename -- File name that the error occured on.               *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Should the process be repeated?                    *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/09/1991 JLB : Created.                                             *\n *=========================================================================*/\n#pragma argsused\nWORD cdecl Do_Open_Error(FileErrorType errormsgnum, BYTE const *file_name)\n{\n\tBYTE\t*ptr=NULL;\t\t// Working file name pointer (just name and extension).\n\n\t/*\n\t** Since the file name may include a path, we must extract the true\n\t** file name from the given string.\n\t*/\n\tif (file_name) {\n#if  LIB_EXTERNS_RESOLVED \n\t\tptr = strrchr((char *) file_name, (int) '\\\\');\n#else\n\t\tptr = NULL;\n#endif\t\t\n\t\tif (ptr) {\n\t\t\tptr++;\n\t\t} else {\n\t\t\tptr = (BYTE *) file_name;\n\t\t}\n\t}\n\n#if  LIB_EXTERNS_RESOLVED \n\tstrupr(ptr);\n\treturn (IO_Error(errormsgnum, ptr));\n#else\n\treturn(0);\n\t\n#endif\t\n\n}\n\n\n/***************************************************************************\n * DO_IO_ERROR -- Performs a non-recoverable error message display.        *\n *                                                                         *\n *    This routine will perform a non-recoverable file error message       *\n *    display.  It is called when an error is detected that has no         *\n *    recovery or retry process defined.                                   *\n *                                                                         *\n * INPUT:   errornum -- Error number detected.                             *\n *                                                                         *\n *          filename -- Name of the file that caused the error.            *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/09/1991 JLB : Created.                                             *\n *=========================================================================*/\n#pragma argsused\nVOID cdecl Do_IO_Error(FileErrorType errormsgnum, BYTE const *filename)\n{\n#if  LIB_EXTERNS_RESOLVED \n\t(VOID)IO_Error(errormsgnum, filename);\n#endif\n\t#if(TRUE)\n\tProg_End();\n\texit((int)errormsgnum);\n\t#else\n\tProgram_End();\n\t#endif\n}\n\n\n/***************************************************************************\n * Read_File_With_Recovery -- read the same file on another directory if an error    *\n *                  occurs.                                                *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/16/1993  QY : Created.                                             *\n *=========================================================================*/\nLONG cdecl Read_File_With_Recovery( WORD handle, VOID *buf, UWORD bytes )\n{\n\tWORD newhandle;\n\tLONG bytes_read;\n\n\tdo {\n\t\tHard_Error_Occured = 0;\n\n\t\t// Make sure we are in the right path.\n\t\tCHANGEDIR( DataPath );\n\n\t\t// open the same file\n\t\tnewhandle = Open_File( FileHandleTable[ handle ].Name, FileHandleTable[ handle ].Mode );\n\t   Seek_File( newhandle, FileHandleTable[ handle ].Pos, SEEK_SET );\n\n\t\t// dos close the old file\n\t\tFILECLOSE( FileHandleTable[ handle ].Handle );\n\n\t\t// copy FileHandleTable[ newhandle ] to FileHandleTable[ handle ]\n\t\tMem_Copy( &FileHandleTable[ newhandle ], &FileHandleTable[ handle ],\n \t\t         ( ULONG ) sizeof( FileHandleTable[ newhandle ] ) );\n\n\t\t// delete FileHandleTable[newhandle]\n\n\t\tFileHandleTable[ newhandle ].Empty = TRUE;\n\n\t\t// continue reading file \n\t\tbytes_read = ( LONG ) FILEREAD( FileHandleTable[ handle ].Handle, buf, bytes );\n\n\t\t// if still error, do it again; else return the number of bytes read\n\t\tif ( !Hard_Error_Occured ) {\n\t\t\treturn( bytes_read );\n\t\t}\n\t\tif (!Do_Open_Error(COULD_NOT_OPEN, FileHandleTable[ handle ].Name)) {\n\t\t\treturn(FALSE);\n\t\t}\n\n\t} while (CHANGEDIR( DataPath ));\n\n\treturn (NULL);\n}\n\n/***************************************************************************\n * Open_File_With_Recovery -- open the same file on another directory      *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/16/1993  QY : Created.                                             *\n *=========================================================================*/\nWORD cdecl Open_File_With_Recovery( BYTE const *file_name, UWORD mode )\n{\n\tWORD handle;\n\n\tHard_Error_Occured = FALSE;\n\thandle = FILEOPEN(file_name, mode);\n\n\t// Do not return if there was a HardError and Using a CD and we are looking at\n\t// the CD.\n\tif (!Hard_Error_Occured || !UseCD || (ibm_getdisk() != (*DataPath - 'A'))) {\n\t\treturn (handle);\n\t}\n\n#if DEBUGPRINT\n\tMono_Print(file_name); Mono_Print(\":OPENERROR  \");\n#endif\n\n\tHard_Error_Occured = 0;\n\n\t// It is possible that the CD has been poped out and put back in, let us\n\t// change there and then try again.\n\tibm_setdisk(*DataPath - 'A');\n\tCHANGEDIR( DataPath );\n\n\t// open the same file\n\thandle = FILEOPEN( file_name, mode );\n\n\t// if still error, do it again; else return the dos handle\n\tif ( !Hard_Error_Occured ) {\n\t\treturn( handle );\n\t}\n\t\t\n\tHard_Error_Occured = 0;\n\treturn (FILEOPENERROR);\n}\n\n\n/***************************************************************************\n * CACHE_FILE -- Attempts to cache file in XMS if flags set.               *\n *                                                                         *\n *                                                                         *\n * INPUT:    WORD index - the index of the file in the FileData table.     *\n *           WORD file_handle - WWS file handle of file.                   *\n *                                                                         *\n * OUTPUT:   BOOL : was it cached?                                         *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1993 SKB : Created.                                             *\n *=========================================================================*/\nBOOL cdecl Cache_File(WORD index, WORD file_handle)\n{\n\tLONG\t\t\t\tfilesize;\t\t// Size of the memory block needed.\n\tLONG\t\t\t\tfreecache; \t\t// Amount of free XMS.\n\tFileDataType\t*filedata = NULL;\n\tFileDataType\thold;\n\tFileHandleType\t*filehandletable;\n\tWORD\t\t\t\tflag;\t\t\t\t// Type of system memory to cache file.\n\tWORD\t\t\t\tfile;\n\n\t// Only files in the file table can be cached.\n\tif (index == ERROR) {\n\t \treturn FALSE;\n\t}\n\n\t// Setup our pointer to the file we may want to cache.\n\tfiledata = &FileDataPtr[index];\n\n\t// Should this be cached, and is it not yet cached?\n\tif ((filedata->Flag & (FILEF_RESIDENT|FILEF_PRELOAD)) && !filedata->Ptr) {\n\n\t\tfilesize = filedata->Size;\n\n\t\t/*\n\t\t**\tIf there is o room to cache the file, then turn off its cache file.\n\t\t*/\n\t\tif (filesize > Mem_Pool_Size(FileCacheHeap)) { \n\n\t\t\t// Remove resident flags so that it will not keep trying to cache itself \n\t\t\t// since there will never be enough room for it.\n\t\t\tfiledata->Flag &= ~(FILEF_PRELOAD|FILEF_KEEP|FILEF_RESIDENT|FILEF_FLUSH);\n\t\t\t\n\t\t\treturn FALSE;\n\t\t}\n\n\n\t\t// Go through freeing files until there is enouph space in the\n\t\t// memory pool.\n\t\twhile (filesize > Mem_Avail(FileCacheHeap)) {\n\t\t\tVOID  *node;\n\n\t\t\t// Get the oldest non used file pointer.\n\t\t\tnode = Mem_Find_Oldest(FileCacheHeap);\n\n\t\t\t// If non was found, sorry no room for the new file.\n\t\t\tif (!node) {\n\t\t\t\treturn (FALSE);\n\t\t\t}\n\n\t\t\t// Get a pointer to the structure for convenience.\n\t\t\tfiledata = &FileDataPtr[Mem_Get_ID(node)];\n\n\t\t\t// Free it from the heap and update the file system so it knows that\n\t\t\t// the file is no longer in memory.\n\t\t\tMem_Free(FileCacheHeap, filedata->Ptr);\n\t\t\tfiledata->Ptr = NULL;\n\t\t}\n\n\n\t\t// If there is not a big enough space we will have to take garbage\n\t\t// collection hit.  (OUCH!!!!!!)\n\t\tif (filesize > Mem_Largest_Avail(FileCacheHeap)) {\n\t\t\tUnfragment_File_Cache();\n\t\t}\n\n\t\t// Make sure we have a big enough space and if so, put the file into memory.\n\t\tif (filesize < Mem_Largest_Avail(FileCacheHeap)) {\n\n\t\t\t// Get some pointers to save code space and time.\n\t\t\tfilehandletable = &FileHandleTable[file_handle];\n\t\t\tfiledata = &FileDataPtr[index];\n\n\t\t\t// Alloc the buffer in our file cache, then read the file in.\n\t\t\tfiledata->Ptr = Mem_Alloc(FileCacheHeap, filesize, index);\n\n\t\t\t// Extra check - it should not fail.\n\t\t\tif (!filedata->Ptr) return(FALSE);\n\n\t\t\t// Mark it so that it never comes back as Oldest used.\n\t\t\tMem_In_Use(filedata->Ptr);\n\n\t\t\t// Get the file into memory.\n\t\t\tRead_File(file_handle, filedata->Ptr, filesize);\n\n\t\t\t// reset the read index from the above read.\n\t\t\tfilehandletable->Pos = 0L;\n\n\t\t\t// This makes caching inner pak file possible.  No longer is the\n\t\t\t// PAK'd file based off the parent file.\n\t\t\tfilehandletable->Start = 0;\t  \n\n\t\t\t// Close the parent file.  Remove it's open count.\n\t\t\tif (filedata->Flag & FILEF_PACKED) {\n\t\t\t\tFileDataType\tp_hold;\n\t\t\t\tFileDataType\t*parent;\n\n\t\t\t\tparent = &FileDataPtr[filedata->Disk];\n\t\t\t\tparent->OpenCount--;\n\t\t\t}\n\t\t\tFILECLOSE(filehandletable->Handle);\n\t\t\tfilehandletable->Handle = 0;\n\n\t\t\treturn (TRUE);\n\t\t}\t\n\t}\n\n\t// The file was not cached, let the caller know.\n\treturn (FALSE);\n}\n"
  },
  {
    "path": "WWFLAT32/FILE/FILESTUB.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : wwlib32                                  *\n *                                                                         *\n *                    File Name : FILESTUB.CPP                             *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : May 3, 1994                              *\n *                                                                         *\n *                  Last Update : May 3, 1994   [BR]                       *\n *                                                                         *\n * This module is a temorary stub that contains IO_Error.\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include \"wwstd.h\"\n#include \"file.h\"\n\nWORD Text_IO_Error(FileErrorType, BYTE const *){return FALSE;}\nWORD (*IO_Error)(FileErrorType, BYTE const *)   = Text_IO_Error;\n\n/************************* End of filestub.cpp *****************************/\n"
  },
  {
    "path": "WWFLAT32/FILE/FILETEMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Temp header for file routines.           *\n *                                                                         *\n *                    File Name : FILETEMP.H                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 20, 1994                           *\n *                                                                         *\n *                  Last Update : April 20, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FILETEMP_H\n#define FILETEMP_H\n\n/////////////////////////////////////////////////////////////////////\n// THIS DOES NOT BELONG HERE.  IT WAS PUT HERE JUST TO GET THE THING\n// TO COMPILE.  ONCE THE BUFFER AND PAGE SYSTEMS ARE PUT IN, THESE\n// WILL NEED TO BE TAKEN OUT AND MODS MADE TO ANY FUNCTION USING BuffType.\n// SKB 4/20/94.\n\n\n\n/*=========================================================================*/\n/* Defines and such that must go into wwstd.h\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n// Look at FileErrorType below for the IO_Error function.\n//extern WORD cdecl (*cdecl IO_Error)(FileErrorType error, BYTE const *filename);\nVOID cdecl Prog_End(VOID);\nextern WORD Hard_Error_Occured;\n\n\n\n//////////////////////// END OF DON'T BELONG //////////////////////////////////\n\n#endif //FILETEMP_H\n"
  },
  {
    "path": "WWFLAT32/FILE/FINDFILE.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : FINDFILE.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : August 21, 1991                          *\n *                                                                         *\n *                  Last Update : September 29, 1993   [SKB]               *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Find_File_Index -- Finds the FileTable index number for a given file. *\n *   Find_File -- Checks if a file is immediatly available.                *\n *   Get_FileData -- Gets a pointer back to the correct file.              *\n *   Find_File -- Checks if a file is immediatly available.                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n#ifndef _FILE_H\n#include \"_file.h\"\n#endif\n\n#include <direct.h>\n#include <dos.h>\n#include <fcntl.h>\n#include <io.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <search.h>\n#include <sys\\stat.h>\n\n\n\n/***************************************************************************\n * FIND_FILE -- Checks if a file is immediatly available.                  *\n *                                                                         *\n *    Use this function to determine if a file is immediatly available.    *\n *    This routine will NOT request for the proper disk to be inserted     *\n *    if the file could not be found.  Use File_Exists for that feature.   *\n *    The Westwood file I/O system does NOT have to be initialized as      *\n *    a prerequisit to using this function.                                *\n *                                                                         *\n * INPUT:   file_name   -- Name of the file to check.                      *\n *                                                                         *\n * OUTPUT:  Returns the disk number that the file exits on (A=1, B=2, etc) *\n *                                                                         *\n * WARNINGS:   This sets the current drive to the drive that contains the  *\n *             specified file (if it is found).                            *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/14/1991 JLB : Created.                                             *\n *   03/14/1992 JLB : Modified for Amiga compatability.                    *\n *   01/11/1993 SKB : Modified for CD-ROM searches.                        *\n *=========================================================================*/\nint cdecl Find_File(char const *file_name)\n{\n\tFileDataType\t*filedata = NULL;\n\tWORD\t\t\t\tindex;\t\t\t\t\t// File index (if any).\n\tWORD\t\t\t\tdisk;\t\t\t\t\t\t// Disk number of file (if in filetable).\n\t\n\t/*\n\t**\tIf the filename is invalid then it errors out as if the file wasn't\n\t**\tfound (naturally).\n\t*/\n\tif (!file_name) return(FALSE);\n\n\t/*\n\t**\tDetermine if the file has a file table entry.  If it does, then\n\t**\tspecial checks and processing must occur.\n\t** Also, if it is in memory, return with it.\n\t*/\n\tindex = Find_File_Index(file_name);\n\tfiledata = &FileDataPtr[index];\n\n\tif (index != ERROR) {\n\n\t\t// If the file is currently cached, return TRUE that it was found.\n\t\tif (filedata->Ptr) {\n\t\t\treturn (TRUE);\n\t\t}\n\t}\n\n\n\t/*\n\t**\tAlways check the current directory for the file.  Only if it can't\n\t**\tbe found are furthur measures required.\n\t*/\n\tDiskNumber = ERROR;\t\t// This indicates file exists in current directory.\n\n\t\t\n \t#if (LIB_CDROM)\n\t\tibm_setdisk(*StartPath - 'A');\n \t#endif\n\n\t/*\n\t**\tCheck the current directory by attempting to open with READ access.\n\t*/\n\t{\n\t\tWORD\thandle;\n\t\t\n\t\tCallingDOSInt++;\n\t\thandle = open(file_name, O_RDONLY | O_BINARY, S_IREAD);\n\t\tCallingDOSInt--;\n\t\tif (handle != ERROR) \n\t\t{\n\t\t   //\tWORD\td;\n\t\t\tunsigned d ;\n\n\t\t\tCallingDOSInt++;\n\t\t\tclose(handle);\n\t\t\t// d = getdisk();\n\t\t\t_dos_getdrive ( & d) ;\n\t\t\tCallingDOSInt--;\n\t\t\treturn(d);\n\t\t}\n\t}\n\t\n\t\t\n\tif (index != ERROR) {\n\n\t\tdisk = filedata->Disk;\n\t\t/*\n\t\t**\tIf the file is in a packed file, then search for the packed file\n\t\t**\tinstead of the specified one.\n\t\t*/\n\t\tif (index != ERROR && (filedata->Flag & FILEF_PACKED)) {\n\t\t\tfiledata = &FileDataPtr[disk];\n\t\t\treturn (Find_File(filedata->Name));\n\t\t}\n\n\t}\n\n\t/*\n\t**\tIt could not be found on the current drive, so search the other\n\t**\tdrives if allowed to do so.\n\t*/\n\tif (!MultiDriveSearch) {\n\t\treturn(FALSE);\n\t}\n\n#if (LIB_CDROM)\n\t// If we were unable to find the file on the hard drive, change\n\t// drives to the CD rom drive and see if it is there.\n\tibm_setdisk(*DataPath - 'A');\n \n\t{\n\t\tWORD\thandle;\n\t\t\n\t\tHard_Error_Occured = 0;\n\n\t  \thandle = Open_File_With_Recovery( file_name, MODE_OLDFILE );\n\n\t\tif (handle != FILEOPENERROR) {\n\t\t\tFILECLOSE(handle);\n\t\t\treturn(ibm_getdisk() + 1);\n\t\t}\n\t}\n\n\tibm_setdisk(*StartPath - 'A');\n\treturn (FALSE);\n#else\n\n\t{\n\t\tWORD\tstart_drive;\t// Original current drive number.\n\n\t\t/*\n\t\t**\tRecord the current drive for restoring later in case of failure.\n\t\t*/\n\t\tCallingDOSInt++;\n\t\tstart_drive = getdisk();\n\t\tCallingDOSInt--;\n\n\t\t/*\n\t\t**\tSweep backward from the last real drive to the first, looking for the\n\t\t**\tfile on each in turn.\n\t\t*/\n\t\tfor (index = MaxDevice; index != -1; index--) {\n\t\t\tif (Is_Device_Real(index)) {\n\t\t\t\tCallingDOSInt++;\n\t\t\t \tsetdisk(index);\n\t\t\t\tCallingDOSInt--;\n\n\t\t\t\t{\n\t\t\t\t\tWORD\thandle;\n\n\t\t\t\t\tCallingDOSInt++;\n\t\t\t\t\thandle = open(file_name, O_RDONLY | O_BINARY, S_IREAD);\n\t\t\t\t\tCallingDOSInt--;\n\t\t\t\t\tif (handle != ERROR) {\n\t\t\t\t\t\tCallingDOSInt++;\n\t\t\t\t\t\tclose(handle);\n\t\t\t\t\t\tCallingDOSInt--;\n\t\t\t\t\t\tDiskNumber = index+1;\n\t\t\t\t\t\treturn (DiskNumber);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tCallingDOSInt++;\n\t\tsetdisk(start_drive);\n\t\tCallingDOSInt--;\n\t}\n\t\n\treturn(FALSE);\n#endif\n\n}\n\n\n/***************************************************************************\n * FIND_FILE_INDEX -- Finds the FileTable index number for a given file.   *\n *                                                                         *\n *    This function searches the FileTable and returns with the index of   *\n *    the matching file.  If the file doesn't exist in the table, then     *\n *    ERROR is returned.  It does not care about case.                     *\n *                                                                         *\n * INPUT:   filename -- Pointer to the filename to check.                  *\n *                                                                         *\n * OUTPUT:  Returns with the index into the FileTable.  If the file does   *\n *          not exist in the file table, then ERROR is returned.           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/09/1991 JLB : Created.                                             *\n *   06/11/1993 JLB : Sorts and binary searches the file table.            *\n *=========================================================================*/\nPRIVATE int Comp_Func(const void *p1, const void *p2)\n{\n\treturn(strcmp((char *) ((FileDataType*)p1)->Name, (char *) ((FileDataType*)p2)->Name));\n}\nWORD cdecl Find_File_Index(BYTE const *filename)\n{\n\tFileDataType\t*filedata;\t\t\t// File entry pointer.\n\tFileDataType\tkey;\t\t\t\t\t// Working file data type var.\n\n\t/*\n\t**\tPerform a binary search on the presorted filetable.\n\t*/\n\tif (filename) {\n\n\t\tfiledata = NULL;\n\t\tkey.Name = (BYTE *) strupr((char *)filename);\n\t\tif (strstr((char *)key.Name, (char *)\".PAK\")) {\n\t\t\t\n\t\t\t/*\n\t\t\t** If the FileData table was not loaded from the disk then the PAK files are\n\t\t\t** not sorted so Perform a linear search for the pak files.\n\t\t\t** Otherwise the files are sorted so speed things up by doing a bsearch.\n\t\t\t*/\n\t\t\tif (FileData == FileDataPtr) {\n\t\t\t\tfiledata = (FileDataType *) lfind(&key, FileDataPtr, (size_t *) &NumPAKFiles, sizeof(FileDataType), Comp_Func);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfiledata = (FileDataType *)bsearch(&key, FileDataPtr, NumPAKFiles, sizeof(FileDataType), Comp_Func);\n\t\t\t}\n\n\t\t} else {\n\t\t\t\t\n\t\t\t/*\n\t\t\t**\tPerform a binary search for the regular files.\n\t\t\t*/\n\t\t\tfiledata = (FileDataType *)bsearch(&key, &FileDataPtr[NumPAKFiles], NumFiles, sizeof(FileDataType), Comp_Func);\n\t\t}\n\n\t\t// Return the element in the array if file was found in table.\n\t\tif (filedata) {\n\t\t\treturn (filedata - FileDataPtr);\n\t\t\t//return ((WORD)((((LONG)filedata) - ((LONG)FileDataPtr)) / sizeof(FileDataType)));\n\t\t}\n\t}\n\treturn(ERROR);\n}\n\n\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/FILE/FINDFILE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : FINDFILE.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : August 21, 1991                          *\n *                                                                         *\n *                  Last Update : September 29, 1993   [SKB]               *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Find_File_Index -- Finds the FileTable index number for a given file. *\n *   Find_File -- Checks if a file is immediatly available.                *\n *   Get_FileData -- Gets a pointer back to the correct file.              *\n *   Find_File -- Checks if a file is immediatly available.                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n#ifndef _FILE_H\n#include \"_file.h\"\n#endif\n\n#include <direct.h>\n#include <dos.h>\n#include <fcntl.h>\n#include <io.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <search.h>\n#include <sys\\stat.h>\n\n\n\n/***************************************************************************\n * FIND_FILE -- Checks if a file is immediatly available.                  *\n *                                                                         *\n *    Use this function to determine if a file is immediatly available.    *\n *    This routine will NOT request for the proper disk to be inserted     *\n *    if the file could not be found.  Use File_Exists for that feature.   *\n *    The Westwood file I/O system does NOT have to be initialized as      *\n *    a prerequisit to using this function.                                *\n *                                                                         *\n * INPUT:   file_name   -- Name of the file to check.                      *\n *                                                                         *\n * OUTPUT:  Returns the disk number that the file exits on (A=1, B=2, etc) *\n *                                                                         *\n * WARNINGS:   This sets the current drive to the drive that contains the  *\n *             specified file (if it is found).                            *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/14/1991 JLB : Created.                                             *\n *   03/14/1992 JLB : Modified for Amiga compatability.                    *\n *   01/11/1993 SKB : Modified for CD-ROM searches.                        *\n *=========================================================================*/\nint cdecl Find_File(char const *file_name)\n{\n\tFileDataType\t*filedata = NULL;\n\tWORD\t\t\t\tindex;\t\t\t\t\t// File index (if any).\n\tWORD\t\t\t\tdisk;\t\t\t\t\t\t// Disk number of file (if in filetable).\n\t\n\t/*\n\t**\tIf the filename is invalid then it errors out as if the file wasn't\n\t**\tfound (naturally).\n\t*/\n\tif (!file_name) return(FALSE);\n\n\t/*\n\t**\tDetermine if the file has a file table entry.  If it does, then\n\t**\tspecial checks and processing must occur.\n\t** Also, if it is in memory, return with it.\n\t*/\n\tindex = Find_File_Index(file_name);\n\tfiledata = &FileDataPtr[index];\n\n\tif (index != ERROR) {\n\n\t\t// If the file is currently cached, return TRUE that it was found.\n\t\tif (filedata->Ptr) {\n\t\t\treturn (TRUE);\n\t\t}\n\t}\n\n\n\t/*\n\t**\tAlways check the current directory for the file.  Only if it can't\n\t**\tbe found are furthur measures required.\n\t*/\n\tDiskNumber = ERROR;\t\t// This indicates file exists in current directory.\n\n\t\t\n \t#if (LIB_CDROM)\n\t\tibm_setdisk(*StartPath - 'A');\n \t#endif\n\n\t/*\n\t**\tCheck the current directory by attempting to open with READ access.\n\t*/\n\t{\n\t\tWORD\thandle;\n\t\t\n\t\tCallingDOSInt++;\n\t\thandle = open(file_name, O_RDONLY | O_BINARY, S_IREAD);\n\t\tCallingDOSInt--;\n\t\tif (handle != ERROR) \n\t\t{\n\t\t   //\tWORD\td;\n\t\t\tunsigned d ;\n\n\t\t\tCallingDOSInt++;\n\t\t\tclose(handle);\n\t\t\t// d = getdisk();\n\t\t\t_dos_getdrive ( & d) ;\n\t\t\tCallingDOSInt--;\n\t\t\treturn(d);\n\t\t}\n\t}\n\t\n\t\t\n\tif (index != ERROR) {\n\n\t\tdisk = filedata->Disk;\n\t\t/*\n\t\t**\tIf the file is in a packed file, then search for the packed file\n\t\t**\tinstead of the specified one.\n\t\t*/\n\t\tif (index != ERROR && (filedata->Flag & FILEF_PACKED)) {\n\t\t\tfiledata = &FileDataPtr[disk];\n\t\t\treturn (Find_File(filedata->Name));\n\t\t}\n\n\t}\n\n\t/*\n\t**\tIt could not be found on the current drive, so search the other\n\t**\tdrives if allowed to do so.\n\t*/\n\tif (!MultiDriveSearch) {\n\t\treturn(FALSE);\n\t}\n\n#if (LIB_CDROM)\n\t// If we were unable to find the file on the hard drive, change\n\t// drives to the CD rom drive and see if it is there.\n\tibm_setdisk(*DataPath - 'A');\n \n\t{\n\t\tWORD\thandle;\n\t\t\n\t\tHard_Error_Occured = 0;\n\n\t  \thandle = Open_File_With_Recovery( file_name, MODE_OLDFILE );\n\n\t\tif (handle != FILEOPENERROR) {\n\t\t\tFILECLOSE(handle);\n\t\t\treturn(ibm_getdisk() + 1);\n\t\t}\n\t}\n\n\tibm_setdisk(*StartPath - 'A');\n\treturn (FALSE);\n#else\n\n\t{\n\t\tWORD\tstart_drive;\t// Original current drive number.\n\n\t\t/*\n\t\t**\tRecord the current drive for restoring later in case of failure.\n\t\t*/\n\t\tCallingDOSInt++;\n\t\tstart_drive = getdisk();\n\t\tCallingDOSInt--;\n\n\t\t/*\n\t\t**\tSweep backward from the last real drive to the first, looking for the\n\t\t**\tfile on each in turn.\n\t\t*/\n\t\tfor (index = MaxDevice; index != -1; index--) {\n\t\t\tif (Is_Device_Real(index)) {\n\t\t\t\tCallingDOSInt++;\n\t\t\t \tsetdisk(index);\n\t\t\t\tCallingDOSInt--;\n\n\t\t\t\t{\n\t\t\t\t\tWORD\thandle;\n\n\t\t\t\t\tCallingDOSInt++;\n\t\t\t\t\thandle = open(file_name, O_RDONLY | O_BINARY, S_IREAD);\n\t\t\t\t\tCallingDOSInt--;\n\t\t\t\t\tif (handle != ERROR) {\n\t\t\t\t\t\tCallingDOSInt++;\n\t\t\t\t\t\tclose(handle);\n\t\t\t\t\t\tCallingDOSInt--;\n\t\t\t\t\t\tDiskNumber = index+1;\n\t\t\t\t\t\treturn (DiskNumber);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tCallingDOSInt++;\n\t\tsetdisk(start_drive);\n\t\tCallingDOSInt--;\n\t}\n\t\n\treturn(FALSE);\n#endif\n\n}\n\n\n/***************************************************************************\n * FIND_FILE_INDEX -- Finds the FileTable index number for a given file.   *\n *                                                                         *\n *    This function searches the FileTable and returns with the index of   *\n *    the matching file.  If the file doesn't exist in the table, then     *\n *    ERROR is returned.  It does not care about case.                     *\n *                                                                         *\n * INPUT:   filename -- Pointer to the filename to check.                  *\n *                                                                         *\n * OUTPUT:  Returns with the index into the FileTable.  If the file does   *\n *          not exist in the file table, then ERROR is returned.           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/09/1991 JLB : Created.                                             *\n *   06/11/1993 JLB : Sorts and binary searches the file table.            *\n *=========================================================================*/\nPRIVATE int Comp_Func(const void *p1, const void *p2)\n{\n\treturn(strcmp((char *) ((FileDataType*)p1)->Name, (char *) ((FileDataType*)p2)->Name));\n}\nint cdecl Find_File_Index(char const *filename)\n{\n\tFileDataType\t*filedata;\t\t\t// File entry pointer.\n\tFileDataType\tkey;\t\t\t\t\t// Working file data type var.\n\n\t/*\n\t**\tPerform a binary search on the presorted filetable.\n\t*/\n\tif (filename) {\n\n\t\tfiledata = NULL;\n\t\tkey.Name = (BYTE *) strupr((char *)filename);\n\t\tif (strstr((char *)key.Name, (char *)\".PAK\")) {\n\t\t\t\n\t\t\t/*\n\t\t\t** If the FileData table was not loaded from the disk then the PAK files are\n\t\t\t** not sorted so Perform a linear search for the pak files.\n\t\t\t** Otherwise the files are sorted so speed things up by doing a bsearch.\n\t\t\t*/\n\t\t\tif (FileData == FileDataPtr) {\n\t\t\t\tfiledata = (FileDataType *) lfind(&key, FileDataPtr, (size_t *) &NumPAKFiles, sizeof(FileDataType), Comp_Func);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfiledata = (FileDataType *)bsearch(&key, FileDataPtr, NumPAKFiles, sizeof(FileDataType), Comp_Func);\n\t\t\t}\n\n\t\t} else {\n\t\t\t\t\n\t\t\t/*\n\t\t\t**\tPerform a binary search for the regular files.\n\t\t\t*/\n\t\t\tfiledata = (FileDataType *)bsearch(&key, &FileDataPtr[NumPAKFiles], NumFiles, sizeof(FileDataType), Comp_Func);\n\t\t}\n\n\t\t// Return the element in the array if file was found in table.\n\t\tif (filedata) {\n\t\t\treturn (filedata - FileDataPtr);\n\t\t\t//return ((WORD)((((LONG)filedata) - ((LONG)FileDataPtr)) / sizeof(FileDataType)));\n\t\t}\n\t}\n\treturn(ERROR);\n}\n\n\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/FILE/HARDERR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Hard/Critical Error Handler              *\n;*                                                                         *\n;*                    File Name : harderr.asm\t\t\t\t   *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen.\t\t\t   *\n;*                                                                         *\n;*                   Start Date : July  18, 1994                           *\n;*                                                                         *\n;*                  Last Update : July 26, 1994   [SKB]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Install_Hard_Error_Handler -- Setup for handling critical errors      *\n;*   Remove_Hard_Erroror_Handler -- Remove the critical error handler stuff*\n;*   Critical_Error_Handler -- Catch critical error interrupt.             *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nLOCALS ??\n\n;INCLUDE \"tntdos.inc\"\n\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////////// Equates ////////////////////////////////////////\nDOS_SYS_CALL\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nLOCK_PAGES\tEQU\t5\t\t; Lock pages subfunction using DX_MEM_MGT\nUNLOCK_PAGES\tEQU\t6\t\t; Unlock pages subfunction using DX_MEM_MGT\nCRITERR_INT_NUM EQU\t24h\n\nDISK_ERROR_BIT\tEQU\t01000000000000000b ; bit 7 of dh.\nDISK_ERROR\tEQU\t1\t\t; Value of Hard_Error_Occured if disk/floppy error.\nOTHER_ERROR\tEQU\t2\t\t; Value of Hard_Error_Occured if other type of error.\n\n;\n; Interrupt handler stack frame\n;\n_FLGS\tequ\t[DWORD PTR ebp+52]\t; 386|DOS-Extender flags\n_GS\tequ\t[WORD PTR ebp+48]\t; original GS\n_FS\tequ\t[WORD PTR ebp+44]\t; original FS\n_DS\tequ\t[WORD PTR ebp+40]\t; original DS\n_ES\tequ\t[WORD PTR ebp+36]\t; original ES\n_SS\tequ\t[WORD PTR ebp+32]\t; original SS\n_ESP\tequ\t[DWORD PTR ebp+28]\t; original ESP\n_EFLAGS\tequ\t[DWORD PTR ebp+24]\t; original EFLAGS\n_CS\tequ\t[DWORD PTR ebp+20]\t; original CS\n_EIP\tequ\t[DWORD PTR ebp+16]\t; original EIP\n_EBP\tequ\t[DWORD PTR ebp]\t\t; original EBP\n\n;\n; DOS critical error stack frame\n;\n_DOS_FLAGS equ\t[WORD PTR es:ebx+22]\t; interrupt stack frame from real\n_DOS_CS\tequ\t[WORD PTR es:ebx+20]\t; mode INT 21h\n_DOS_IP\tequ\t[WORD PTR es:ebx+18]\t;\n_DOS_ES\tequ\t[WORD PTR es:ebx+16]\t; regs at time INT 21h was issued\n_DOS_DS\tequ\t[WORD PTR es:ebx+14]\t\t; in real mode\n_DOS_BP\tequ\t[WORD PTR es:ebx+12]\t\t;\n_DOS_DI\tequ\t[WORD PTR es:ebx+10]\t\t;\n_DOS_SI\tequ\t[WORD PTR es:ebx+8]\t\t;\n_DOS_DX\tequ\t[WORD PTR es:ebx+6]\t\t;\n_DOS_CX\tequ\t[WORD PTR es:ebx+4]\t\t;\n_DOS_BX\tequ\t[WORD PTR es:ebx+2]\t\t;\n_DOS_AX\tequ\t[WORD PTR es:ebx]\t\t;\n\n\n; \n; Error codes put into Hard_Error_Code\n;\nDISK_WRITE_PROTECTED\tequ\t00h\nUNKOWN_DEVICE\t\tequ\t01h\nDRIVE_NOT_READY\t\tequ\t02h\nUNKOWN_COMMAND\t\tequ\t03h\nCRC_ERROR\t\tequ\t04h\nWRONG_DATA_LENGTH\tequ\t05h\nSEEK_ERROR\t\tequ\t06h\nUNKOWN_DEVICE_TYPE\tequ\t07h\nSECTOR_NOT_FOUND\tequ\t08h\nOUT_OF_PAPER\t\tequ\t09h\nWRITE_ERROR\t\tequ\t0Ah\nREAD_ERROR\t\tequ\t0Bh\nGENERAL_ERROR\t\tequ\t0Ch\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;/////////////////////////////////// Prototypes ///////////////////////////////////////\n\nGLOBAL\t Install_Hard_Error_Handler :NEAR\nGLOBAL\t Remove_Hard_Error_Handler  :NEAR\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////// Global/Local Data //////////////////////////////////\n\nDATASEG\n\nLABEL\tLockedDataStart\tBYTE\t\nHard_Error_Occured\tDB\t0\t; Hard disk error or other error.\nHard_Error_Code\t\tDB\t0\t; Error Code.\t\nLABEL\tLockedDataEnd\tBYTE\n\n\nOldRMI\t\tDD\t?\t; original real mode critical err vector\nOldPMIOffset\tDD\t?\t; original protected mode critical err vector\nOldPMISelector\tDD\t?     \t; original PM crit error selector.\n\nInitFlags\tDD\t0\t; Flags to indicate what has been initialized.\n\n; InitFlags that are set to have a fully functional interrupt.\nIF_SET_VECTORS\t\tequ\t1\t\t; Vectors have been set.\nIF_LOCKED_PM_CODE\tequ\t2\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t4\t\t; Locked PM data for DPMI.\nIF_FUNCTIONAL\t\tequ\t8\t\t; crit error is in and functional.\n\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////////// Code //////////////////////////////////////////\n\nCODESEG\n\n;***************************************************************************\n;* INSTALL_HARD_ERROR_HANDLER -- Setup for handling critical errors.         *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/26/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC Install_Hard_Error_Handler C near\n\tUSES eax,ebx,ecx,ds,es\n\tret\n\n\tENDP Install_Hard_Error_Handler\n\n\n;***************************************************************************\n;* REMOVE_HARD_ERROROR_HANDLER -- Remove the critical error handler stuff    *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/26/1994 SKB : Created.                                             *\n;*=========================================================================*\n\n\tPROC \tRemove_Hard_Error_Handler C near\n\tUSES \tebx,ecx,edx,ds,es\n;\n; Restore the original interrupt vectors and exit\n;\n\n\tret\n\n\tENDP Remove_Hard_Error_Handler\n\n\n;***************************************************************************\n;* Critical_Error_Handler -- Catch critical error interrupt.               *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/26/1994 SKB : Created.                                             *\n;*=========================================================================*\n\nLABEL \tLockedCodeStart\tBYTE\n\n\tPROC Critical_Error_Handler NEAR\n\n\tENDP Critical_Error_Handler\n\nLABEL \tLockedCodeEnd\t\tBYTE\n\nEND\n\u001a\n"
  },
  {
    "path": "WWFLAT32/FILE/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = file\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tfile.obj \t&\n\tfilecach.obj \t&\n\tfilechng.obj \t&\n\tfiledata.obj \t&\n\tfileglob.obj \t&\n\tfglob2.obj &\n\tfileinfo.obj \t&\n\tfileinit.obj \t&\n\tfileio.obj \t&\n\tfilelib.obj \t&\n\tfilestub.obj \t&\n\tfindfile.obj \t&\n\tdevices.obj \t&\n\tdevtable.obj \t&\n\tffirst.obj \t&\n\tharderr.obj \n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WWLIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WWFLAT32/FILE/_FILE.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library - Filio header stuff.            *\n;*                                                                         *\n;*                    File Name : FILE.H                                 \t*\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : September 13, 1993                       *\n;*                                                                         *\n;*                  Last Update : April 11, 1994\t\t\t\t\t\t\t\t\t*\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FILE_H\n#include \"file.h\"\n#endif\n\n#ifndef _FILE_H\n#define _FILE_H\n\n\n/*=========================================================================*/\n/* Fileio defines\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#define\tLIB_CDROM TRUE\n\n#define MODE_OLDFILE\t\t\t\t(O_RDONLY | O_BINARY)\n#define MODE_NEWFILE\t\t\t\t(O_WRONLY | O_BINARY | O_CREAT | O_TRUNC)\n#define MODE_READWRITE\t\t\t(O_RDWR   | O_BINARY)\n\n#define FILEOPENERROR\t\t\t-1\n#define FILEOPEN(f,m)\t\t\tibm_open(f, m, (((UWORD) m) == MODE_OLDFILE) ? S_IREAD : (S_IREAD | S_IWRITE))\n\n#define FILECLOSE(fd)\t\t\tibm_close(fd)\n#define FILEREAD(f,b,n)\t\t\tibm_read(f,b,(WORD)(n))\n#define FILEWRITE(f,b,n)\t\tibm_write(f,b,(WORD)(n))\n#define FILESEEK(f,b,n)\t\t\tibm_lseek(f, b, n)\n#define FILEDELETE(f)\t\t\tibm_unlink(f)\n#define CHANGEDIR(p)\t\t\t\tibm_chdir(p)\n\n#define FILENAMESIZE\t\t\t\t13\n#define IO_CHUNK_SIZE\t\t\t0xfff0UL\n\n/* \n**\tMaximum number of file handles \n*/\n#define TABLE_MAX\t\t\t20\n\n \n/*=========================================================================*/\n/* The file handle table */\n/*=========================================================================*/\ntypedef struct {\n\tBOOL\t\t\t\t\t\tEmpty;\t\t// Is this handle empty?\n\tWORD\t\t\t\t\t\tHandle;\t\t// DOS file handle (0 = resident).\n\tLONG\t\t\t\t\t\tPos;\t\t\t// Current file position.\n\tLONG\t\t\t\t\t\tStart;\t\t// Offset of file from pointer.\n\tWORD\t\t\t\t\t\tIndex;\t\t// FileData[] index.\n\tWORD\t\t\t\t\t\tMode;\t\t\t// Access mode (WW).\n\tBYTE\t\t\t\t\t\t*Name;\t\t// File name pointer.\n} FileHandleType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILEIO.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD ibm_getdisk(VOID);\nWORD ibm_setdisk(WORD drive);\nWORD ibm_close(WORD handle);\nWORD ibm_unlink(BYTE const *name);\nLONG ibm_lseek(WORD handle, LONG offset, WORD where);\nUWORD ibm_read(WORD handle, VOID *ptr, UWORD bytes);\nUWORD ibm_write(WORD handle, VOID *ptr, UWORD bytes);\nWORD ibm_open(BYTE const *name, UWORD mode, WORD attrib);\nWORD ibm_chdir(BYTE const *path);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILELIB.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD cdecl Do_Open_Error(FileErrorType errormsgnum, BYTE const *file_name);\nVOID cdecl Do_IO_Error(FileErrorType errormsgnum, BYTE const *filename);\nLONG cdecl Read_File_With_Recovery( WORD handle, VOID *buf, UWORD bytes );\nWORD cdecl Open_File_With_Recovery( BYTE const *file_name, UWORD mode );\nBOOL cdecl Cache_File(WORD index, WORD file_handle);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DEVICES.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Get_Devices(VOID);\nextern WORD Is_Device_Real(WORD device);\n\n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DEVTABLE.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Init_Device_Table(BYTE *table);\nextern WORD Max_Device(VOID);\n\n\n#ifdef __cplusplus\n}\n#endif\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: HARDERR.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Install_Hard_Error_Handler(VOID);\nextern VOID Remove_Hard_Error_Handler(VOID);\n\n#ifdef __cplusplus\n}\n#endif\n\n\n/*=========================================================================*/\n/* Globale variables in the fileio system.\t\t\t\t\t\t               */\n/*=========================================================================*/\n\nextern BYTE CallingDOSInt;\t\t\t\t\t \nextern \"C\" extern BYTE MaxDevice,DefaultDrive;\nextern BYTE MultiDriveSearch;\t\nextern FileDataType *FileDataPtr;\nextern FileHandleType FileHandleTable[TABLE_MAX];\nextern UWORD NumFiles;\t\t\t\t\t\t\t \t// Number of files, except PAK, in file table.\nextern UWORD NumPAKFiles;\t\t\t\t\t\t\t// Number of PAK files in filetable.\nextern VOID *FileCacheHeap;\t\t\t\t\t\t// Pointer to the cache in memory.\nextern WORD DiskNumber;\t\t\t\t\t\t \nextern WORD MaxDirNum;\n\n\n/*=========================================================================*/\n\t \n\n\n#endif // _FILE_H\n\n\n"
  },
  {
    "path": "WWFLAT32/FILE/_FILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library - Filio header stuff.            *\n;*                                                                         *\n;*                    File Name : FILE.H                                 \t*\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : September 13, 1993                       *\n;*                                                                         *\n;*                  Last Update : April 11, 1994\t\t\t\t\t\t\t\t\t*\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FILE_H\n#include \"file.h\"\n#endif\n\n#ifndef _FILE_H\n#define _FILE_H\n\n\n/*=========================================================================*/\n/* Fileio defines\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#define\tLIB_CDROM TRUE\n\n#define MODE_OLDFILE\t\t\t\t(O_RDONLY | O_BINARY)\n#define MODE_NEWFILE\t\t\t\t(O_WRONLY | O_BINARY | O_CREAT | O_TRUNC)\n#define MODE_READWRITE\t\t\t(O_RDWR   | O_BINARY)\n\n#define FILEOPENERROR\t\t\t-1\n#define FILEOPEN(f,m)\t\t\tibm_open(f, m, (((UWORD) m) == MODE_OLDFILE) ? S_IREAD : (S_IREAD | S_IWRITE))\n\n#define FILECLOSE(fd)\t\t\tibm_close(fd)\n#define FILEREAD(f,b,n)\t\t\tibm_read(f,b,(WORD)(n))\n#define FILEWRITE(f,b,n)\t\tibm_write(f,b,(WORD)(n))\n#define FILESEEK(f,b,n)\t\t\tibm_lseek(f, b, n)\n#define FILEDELETE(f)\t\t\tibm_unlink(f)\n#define CHANGEDIR(p)\t\t\t\tibm_chdir(p)\n\n#define FILENAMESIZE\t\t\t\t13\n#define IO_CHUNK_SIZE\t\t\t0xfff0UL\n\n/* \n**\tMaximum number of file handles \n*/\n#define TABLE_MAX\t\t\t20\n\n \n/*=========================================================================*/\n/* The file handle table */\n/*=========================================================================*/\ntypedef struct {\n\tBOOL\t\t\t\t\t\tEmpty;\t\t// Is this handle empty?\n\tWORD\t\t\t\t\t\tHandle;\t\t// DOS file handle (0 = resident).\n\tLONG\t\t\t\t\t\tPos;\t\t\t// Current file position.\n\tLONG\t\t\t\t\t\tStart;\t\t// Offset of file from pointer.\n\tWORD\t\t\t\t\t\tIndex;\t\t// FileData[] index.\n\tWORD\t\t\t\t\t\tMode;\t\t\t// Access mode (WW).\n\tBYTE\t\t\t\t\t\t*Name;\t\t// File name pointer.\n} FileHandleType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILEIO.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD ibm_getdisk(VOID);\nWORD ibm_setdisk(WORD drive);\nWORD ibm_close(WORD handle);\nWORD ibm_unlink(BYTE const *name);\nLONG ibm_lseek(WORD handle, LONG offset, WORD where);\nUWORD ibm_read(WORD handle, VOID *ptr, UWORD bytes);\nUWORD ibm_write(WORD handle, VOID *ptr, UWORD bytes);\nWORD ibm_open(BYTE const *name, UWORD mode, WORD attrib);\nWORD ibm_chdir(BYTE const *path);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILELIB.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD cdecl Do_Open_Error(FileErrorType errormsgnum, BYTE const *file_name);\nVOID cdecl Do_IO_Error(FileErrorType errormsgnum, BYTE const *filename);\nLONG cdecl Read_File_With_Recovery( WORD handle, VOID *buf, UWORD bytes );\nint cdecl Open_File_With_Recovery( BYTE const *file_name, unsigned int mode );\nBOOL cdecl Cache_File(WORD index, WORD file_handle);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DEVICES.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Get_Devices(VOID);\nextern WORD Is_Device_Real(WORD device);\n\n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DEVTABLE.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Init_Device_Table(BYTE *table);\nextern WORD Max_Device(VOID);\n\n\n#ifdef __cplusplus\n}\n#endif\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: HARDERR.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Install_Hard_Error_Handler(VOID);\nextern VOID Remove_Hard_Error_Handler(VOID);\n\n#ifdef __cplusplus\n}\n#endif\n\n\n/*=========================================================================*/\n/* Globale variables in the fileio system.\t\t\t\t\t\t               */\n/*=========================================================================*/\n\nextern BYTE CallingDOSInt;\t\t\t\t\t \nextern \"C\" extern BYTE MaxDevice,DefaultDrive;\nextern BYTE MultiDriveSearch;\t\nextern FileDataType *FileDataPtr;\nextern FileHandleType FileHandleTable[TABLE_MAX];\nextern UWORD NumFiles;\t\t\t\t\t\t\t \t// Number of files, except PAK, in file table.\nextern UWORD NumPAKFiles;\t\t\t\t\t\t\t// Number of PAK files in filetable.\nextern VOID *FileCacheHeap;\t\t\t\t\t\t// Pointer to the cache in memory.\nextern WORD DiskNumber;\t\t\t\t\t\t \nextern WORD MaxDirNum;\n\n\n/*=========================================================================*/\n\t \n\n\n#endif // _FILE_H\n\n\n"
  },
  {
    "path": "WWFLAT32/FONT/FONT.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Font and text print 32 bit library       *\n *                                                                         *\n *                    File Name : FONT.H                                   *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : June 27, 1994                            *\n *                                                                         *\n *                  Last Update : June 29, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   VVPC::Text_Print -- Text print into a virtual viewport.               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FONT_H\n#define FONT_H\n\n#ifndef GBUFFER_H\n#include <gbuffer.h>\n#endif\n\n#ifndef VBUFFER_H\n#include <vbuffer.h>\n#endif\n\n//////////////////////////////////////// Defines //////////////////////////////////////////\n\n// defines for font header, offsets to block offsets\n\n#define FONTINFOBLOCK\t\t\t4\n#define FONTOFFSETBLOCK\t\t\t6\n#define FONTWIDTHBLOCK\t\t\t8\n#define FONTDATABLOCK\t\t\t10\n#define FONTHEIGHTBLOCK\t\t\t12\n\n// defines for font info block\n\n#define FONTINFOMAXHEIGHT\t\t4\n#define FONTINFOMAXWIDTH\t\t5\n\n//////////////////////////////////////// Prototypes //////////////////////////////////////////\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SET_FONT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nVOID *cdecl Set_Font(VOID const *fontptr);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FONT.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD cdecl Char_Pixel_Width(BYTE chr);\nUWORD cdecl String_Pixel_Width(BYTE const *string);\nVOID cdecl Get_Next_Text_Print_XY(GraphicViewPortClass& vp, ULONG offset, INT *x, INT *y);\nVOID cdecl Get_Next_Text_Print_XY(VideoViewPortClass& vp, ULONG offset, INT *x, INT *y);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOADFONT.CPP\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\nVOID *cdecl Load_Font(BYTE  const *name);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TEXTPRNT.ASM\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\nVOID Set_Font_Palette_Range(VOID const *palette, INT start_idx, INT end_idx);\n\n\n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n\n\n\n\n\n//////////////////////////////////////// External varables ///////////////////////////////////////\nextern \"C\" int FontXSpacing;\nextern \"C\" int FontYSpacing;\nextern BYTE FontWidth ;\nextern BYTE FontHeight;\nextern BYTE *FontWidthBlockPtr;\n\n\nextern \"C\" VOID const *FontPtr;\n\n\n\n\n#endif // FONT_H\n"
  },
  {
    "path": "WWFLAT32/FONT/FONT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : FONT.C                                   *\n *                                                                         *\n *                   Programmer : David Dettmer                            *\n *                                                                         *\n *                  Last Update : July 20, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Char_Pixel_Width -- Return pixel width of a character.\t\t\t\t\t\t*\n *   String_Pixel_Width -- Return pixel width of a string of characters.   *\n *   Get_Next_Text_Print_XY -- Calculates X and Y given ret value from Text_P*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"font.h\"\n#include <malloc.h>\n#include <dos.h>\n#include <fcntl.h>\n#include <io.h>\n#include <sys\\stat.h>\n#include <string.h>\n\n\n/***************************************************************************\n * CHAR_PIXEL_WIDTH -- Return pixel width of a character.\t\t\t\t\t\t*\n *                                                                         *\n *    Retreives the pixel width of a character from the font width block.\t*\n *                                                                         *\n * INPUT:      Character.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     Pixel width of a string of characters.                      *\n *                                                                         *\n * WARNINGS:   Set_Font must have been called first.                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/31/1992 DRD : Created.                                             *\n *   06/30/1994 SKB : Converted to 32 bit library.                         *\n *=========================================================================*/\nWORD cdecl Char_Pixel_Width(BYTE chr)\n{\n\tWORD\twidth;\n\n\twidth = (UBYTE)*(FontWidthBlockPtr + (UBYTE)chr) + FontXSpacing;\n\n\treturn(width);\n}\n\n\n/***************************************************************************\n * STRING_PIXEL_WIDTH -- Return pixel width of a string of characters.     *\n *                                                                         *\n *    Calculates the pixel width of a string of characters.  This uses     *\n *\t\tthe font width block for the widths.\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:      Pointer to string of characters.                            *\n *                                                                         *\n * OUTPUT:     Pixel width of a string of characters.                      *\n *                                                                         *\n * WARNINGS:   Set_Font must have been called first.                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/30/1992 DRD : Created.                                             *\n *   01/31/1992 DRD : Use Char_Pixel_Width.                                *\n *   06/30/1994 SKB : Converted to 32 bit library.                         *\n *=========================================================================*/\nUWORD cdecl String_Pixel_Width(BYTE const *string)\n{\n\tWORD\twidth;\t\t\t\t// Working accumulator of string width.\n\tWORD\tlargest = 0;\t\t// Largest recorded width of the string.\n\n\tif (!string) return(0);\n\n\twidth = 0;\n\twhile (*string) {\n\t\tif (*string == '\\r') {\n\t\t\tstring++;\n\t\t\tlargest = MAX(largest, width);\n\t\t\twidth = 0;\n\t\t} else {\n\t\t\twidth += Char_Pixel_Width(*string++);\t// add each char's width\n\t\t}\n\t}\n\tlargest = MAX(largest, width);\n\treturn(largest);\n}\n\n\n\n/***************************************************************************\n * GET_NEXT_TEXT_PRINT_XY -- Calculates X and Y given ret value from Text_P*\n *                                                                         *\n *                                                                         *\n * INPUT:   VVPC& vp - viewport that was printed to.                       *\n *          ULONG offset - offset that Text_Print returned.                *\n *          INT *x - x return value.                                       *\n *          INT *y - y return value.                                       *\n *                                                                         *\n * OUTPUT:  x and y are set.                                               *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/20/1994 SKB : Created.                                             *\n *=========================================================================*/\nVOID cdecl Get_Next_Text_Print_XY(VideoViewPortClass& vp, ULONG offset, INT *x, INT *y)\n{\n\tINT\tbuffwidth;\n\n\tif (offset) {\n\t\tbuffwidth = vp.Get_Width() + vp.Get_XAdd();\n\t\toffset -= vp.Get_Offset();\n\t\t*x = offset % buffwidth;\n\t\t*y = offset / buffwidth;\n\t} else {\n\t \t*x = *y = 0;\n\t}\n}\n/***************************************************************************\n * GET_NEXT_TEXT_PRINT_XY -- Calculates X and Y given ret value from Text_P*\n *                                                                         *\n *                                                                         *\n * INPUT:   VVPC& vp - viewport that was printed to.                       *\n *          ULONG offset - offset that Text_Print returned.                *\n *          INT *x - x return value.                                       *\n *          INT *y - y return value.                                       *\n *                                                                         *\n * OUTPUT:  x and y are set.                                               *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/20/1994 SKB : Created.                                             *\n *=========================================================================*/\nVOID cdecl Get_Next_Text_Print_XY(GraphicViewPortClass& vp, ULONG offset, INT *x, INT *y)\n{\n\tINT\tbuffwidth;\n\n\tif (offset) {\n\t\tbuffwidth = vp.Get_Width() + vp.Get_XAdd();\n\t\toffset -= vp.Get_Offset();\n\t\t*x = offset % buffwidth;\n\t\t*y = offset / buffwidth;\n\t} else {\n\t \t*x = *y = 0;\n\t}\n}\n"
  },
  {
    "path": "WWFLAT32/FONT/FONT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Font and text print 32 bit library       *\n *                                                                         *\n *                    File Name : FONT.H                                   *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : June 27, 1994                            *\n *                                                                         *\n *                  Last Update : June 29, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   VVPC::Text_Print -- Text print into a virtual viewport.               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FONT_H\n#define FONT_H\n\n#ifndef GBUFFER_H\n#include <gbuffer.h>\n#endif\n\n#ifndef VBUFFER_H\n#include <vbuffer.h>\n#endif\n\n//////////////////////////////////////// Defines //////////////////////////////////////////\n\n// defines for font header, offsets to block offsets\n\n#define FONTINFOBLOCK\t\t\t4\n#define FONTOFFSETBLOCK\t\t\t6\n#define FONTWIDTHBLOCK\t\t\t8\n#define FONTDATABLOCK\t\t\t10\n#define FONTHEIGHTBLOCK\t\t\t12\n\n// defines for font info block\n\n#define FONTINFOMAXHEIGHT\t\t4\n#define FONTINFOMAXWIDTH\t\t5\n\n//////////////////////////////////////// Prototypes //////////////////////////////////////////\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SET_FONT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nVOID *cdecl Set_Font(VOID const *fontptr);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FONT.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD cdecl Char_Pixel_Width(BYTE chr);\nUWORD cdecl String_Pixel_Width(BYTE const *string);\nVOID cdecl Get_Next_Text_Print_XY(GraphicViewPortClass& vp, ULONG offset, INT *x, INT *y);\nVOID cdecl Get_Next_Text_Print_XY(VideoViewPortClass& vp, ULONG offset, INT *x, INT *y);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOADFONT.CPP\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\nVOID *cdecl Load_Font(BYTE  const *name);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TEXTPRNT.ASM\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\nVOID Set_Font_Palette_Range(VOID const *palette, INT start_idx, INT end_idx);\n\n\n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n\n\n\n\n\n//////////////////////////////////////// External varables ///////////////////////////////////////\nextern \"C\" int FontXSpacing;\nextern \"C\" int FontYSpacing;\nextern BYTE FontWidth ;\nextern BYTE FontHeight;\nextern BYTE *FontWidthBlockPtr;\n\n\nextern \"C\" void const *FontPtr;\n\n\n\n\n#endif // FONT_H\n"
  },
  {
    "path": "WWFLAT32/FONT/LOADFONT.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : LOADFONT.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : September 6, 1991                        *\n *                                                                         *\n *                  Last Update : June 27, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Load_Font -- Loads a font from disk.                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"font.h\"\n#include <file.h>\n#include <wwmem.h>\n\n#if(IBM)\n#include <fcntl.h>\n#include <io.h>\n#endif\n\n\n\nextern \"C\" {\n\tint FontXSpacing = 0;\n\tint FontYSpacing = 0;\n\tvoid const *FontPtr = NULL;\n}\nBYTE FontWidth  = 8;\nBYTE FontHeight = 8;\n\n// only font.c and set_font.c use the following\nBYTE *FontWidthBlockPtr = NULL;\n\n\n\n/***************************************************************************\n * LOAD_FONT -- Loads a font from disk.                                    *\n *                                                                         *\n *    This loads a font from disk.  This function must be called as a    \t*\n *    precursor to calling Set_Font().  You need only call this function \t*\n *    once per desired font at the beginning of your code, but AFTER     \t*\n *    Prog_Init() is called.                                             \t*\n *                                                                         *\n * INPUT:      name  - Pointer to font name to use (eg. \"topaz.font\")    \t*\n *                                                                       \t*\n *             fontsize - Size in points of the font loaded.             \t*\n *                                                                       \t*\n * OUTPUT:     Pointer to font data or NULL if unable to load.           \t*\n *                                                                       \t*\n * WARNINGS:   Some system memory is grabbed by this routine.            \t*\n *                                                                       \t*\n * HISTORY:                                                                *\n *   4/10/91    BS  : 2.0 compatibily                                     \t*\n *   6/09/91    JLB : IBM and Amiga compatability.                        \t*\n *   11/27/1991 JLB : Uses file I/O routines for disk access.              *\n *   01/29/1992 DRD : Modified to use new font format.                     *\n *   02/01/1992 DRD : Added font file verification.                        *\n *   06/29/1994 SKB : modified for 32 bit library                          *\n *=========================================================================*/\nVOID *cdecl Load_Font(BYTE const *name)\n{\n\tBYTE\tvalid;\n\tWORD\tfh;\t\t// DOS file handle for font file.\n\tUWORD\tsize;\t\t// Size of the data in the file (-2);\n\tBYTE\t*ptr = NULL;\t\t// Pointer to newly loaded font.\n\n\tif (Find_File(name)) {\n\t\tfh = Open_File(name, READ);\n\t\tif (Read_File(fh, (BYTE *) &size, 2) != 2) return(NULL);\n\n\t\tptr = (BYTE *) Alloc(size, MEM_NORMAL);\n\t\t*(WORD *)ptr = size;\n\t\tRead_File(fh, ptr + 2, size - 2);\n\t\tClose_File(fh);\n\t} else {\n\t\treturn (NULL);\n\t}\n\n\t//\n\t// verify that the file loaded is a valid font file.\n\t//\n\n\tvalid = FALSE;\n\tif (*(ptr + 2) == 0) {\t\t// no compression\n\t\tif (*(ptr + 3) == 5) {\t\t// currently only 5 data blocks are used.\n\t\t\tvalid = TRUE;\n\t\t}\n\t}\n\n\tif ( !valid ) {\n\t\treturn (NULL);\n\t}\n\n   return(ptr);\n}\n"
  },
  {
    "path": "WWFLAT32/FONT/LOADFONT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : LOADFONT.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : September 6, 1991                        *\n *                                                                         *\n *                  Last Update : June 27, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Load_Font -- Loads a font from disk.                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"font.h\"\n#include <file.h>\n#include <wwmem.h>\n\n#if(IBM)\n#include <fcntl.h>\n#include <io.h>\n#endif\n\n\n\nint FontXSpacing = 0;\nint FontYSpacing = 0;\nvoid const *FontPtr = NULL;\nBYTE FontWidth  = 8;\nBYTE FontHeight = 8;\n\n// only font.c and set_font.c use the following\nBYTE *FontWidthBlockPtr = NULL;\n\n\n\n/***************************************************************************\n * LOAD_FONT -- Loads a font from disk.                                    *\n *                                                                         *\n *    This loads a font from disk.  This function must be called as a    \t*\n *    precursor to calling Set_Font().  You need only call this function \t*\n *    once per desired font at the beginning of your code, but AFTER     \t*\n *    Prog_Init() is called.                                             \t*\n *                                                                         *\n * INPUT:      name  - Pointer to font name to use (eg. \"topaz.font\")    \t*\n *                                                                       \t*\n *             fontsize - Size in points of the font loaded.             \t*\n *                                                                       \t*\n * OUTPUT:     Pointer to font data or NULL if unable to load.           \t*\n *                                                                       \t*\n * WARNINGS:   Some system memory is grabbed by this routine.            \t*\n *                                                                       \t*\n * HISTORY:                                                                *\n *   4/10/91    BS  : 2.0 compatibily                                     \t*\n *   6/09/91    JLB : IBM and Amiga compatability.                        \t*\n *   11/27/1991 JLB : Uses file I/O routines for disk access.              *\n *   01/29/1992 DRD : Modified to use new font format.                     *\n *   02/01/1992 DRD : Added font file verification.                        *\n *   06/29/1994 SKB : modified for 32 bit library                          *\n *=========================================================================*/\nVOID *cdecl Load_Font(BYTE const *name)\n{\n\tBYTE\tvalid;\n\tWORD\tfh;\t\t// DOS file handle for font file.\n\tUWORD\tsize;\t\t// Size of the data in the file (-2);\n\tBYTE\t*ptr = NULL;\t\t// Pointer to newly loaded font.\n\n\tif (Find_File(name)) {\n\t\tfh = Open_File(name, READ);\n\t\tif (Read_File(fh, (BYTE *) &size, 2) != 2) return(NULL);\n\n\t\tptr = (BYTE *) Alloc(size, MEM_NORMAL);\n\t\t*(WORD *)ptr = size;\n\t\tRead_File(fh, ptr + 2, size - 2);\n\t\tClose_File(fh);\n\t} else {\n\t\treturn (NULL);\n\t}\n\n\t//\n\t// verify that the file loaded is a valid font file.\n\t//\n\n\tvalid = FALSE;\n\tif (*(ptr + 2) == 0) {\t\t// no compression\n\t\tif (*(ptr + 3) == 5) {\t\t// currently only 5 data blocks are used.\n\t\t\tvalid = TRUE;\n\t\t}\n\t}\n\n\tif ( !valid ) {\n\t\treturn (NULL);\n\t}\n\n   return(ptr);\n}\n"
  },
  {
    "path": "WWFLAT32/FONT/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : jan 24, 1995                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = font\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tfont.obj\t&\n\tloadfont.obj\t&\n\tset_font.obj\t&\n\tsetfpal.obj\t&\n\ttextprnt.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\tmkdir run\n\tcd run\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\run\\vcs.cfg\n\tupdate\n\tcd..\n\tmkdir art\n\tcd art\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\art\\vcs.cfg\n\tupdate\n\tcd..\n\twmake \n\tcd ..\n\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WWFLAT32/FONT/SETFPAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : 32 bit library Text Print                *\n;*                                                                         *\n;*                    File Name : TEXTPRNT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : July 2, 1994                             *\n;*                                                                         *\n;*                  Last Update : July 2, 1994   [SKB]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Text_Print -- Assembly text print routine.                            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nGLOBAL  ColorXlat:BYTE\nGLOBAL\tSet_Font_Palette_Range:NEAR\n\n\tCODESEG\n\n;***********************************************************\n; SET_FONT_PALETTE_RANGE\n;\n; VOID Set_Font_Palette_Range(VOID *palette, WORD start, WORD end);\n;\n; This routine changes the local Draw_Char color translation table\n; with the color numbers in palette.\n;\n; Bounds Checking: forces start and end to a range of 0-15\n;*\n\tPROC\tSet_Font_Palette_Range C near \n\tUSES\teax, ebx, ecx,edi,esi\n\tARG\tpalette:DWORD\n\tARG\tstart:DWORD\n\tARG\tendval:DWORD\n\n\tcld\n\n\tmov\tesi,[palette]\n\n\tmov\tebx,[start]\n\tand\tebx,0FH\t\t\t; value 0-15\n\n\tmov\tecx,[endval]\n\tand\tecx,0FH\t\t\t; value 0-15\n\n\tcmp\tecx,ebx\t\t\t; if end < start then exit\n\tjl\tshort ??exit\n\n\tsub\tecx,ebx\t\t\t; number of colors = end - start + 1\n\tinc\tecx\n\n\tmov\tedi,OFFSET ColorXlat\t; get start of xlat table\n\tadd\tedi,ebx\t\t\t; add starting offset\n\tshl\tebx,4\t\t\t; multiply start offset by 16\n\tadd\tebx,OFFSET ColorXlat\t; add start of xlat table\n\n; updates 0-15 for lonibble xlat\n; updates 0,16,32,...,240 for hinibble xlat\n\n??setpal:\n\tlodsb\t\t\t\t; get color number\n\tstosb\t\t\t\t; save color number for lonibble xlat\n\tmov\t[ebx],al\t\t; save color number for hinibble xlat\n\tadd\tebx,010H    \t\t; add 16 to index for hinibble offset\n\tdec\tecx\n\tjnz\t??setpal\n\n??exit:\n\tret\n\n\tENDP\tSet_Font_Palette_Range\n\n;***********************************************************\n\n\n;***********************************************************\n\n\tEND\n"
  },
  {
    "path": "WWFLAT32/FONT/SET_FONT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : SET_FONT.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : September 6, 1991                        *\n *                                                                         *\n *                  Last Update : June 29, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Set_Font -- Changes the default text printing font.                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"font.h\"\n\n\n\n/***************************************************************************\n * SET_FONT -- Changes the default text printing font.                     *\n *                                                                         *\n *    This routine will change the default text printing font for all      *\n *    text output.  It handles updating the system where necessary.        *\n *                                                                         *\n * INPUT:   fontptr  -- Pointer to the font to change to.                  *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the previous font.                   *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/06/1991 JLB : Created.                                             *\n *   09/17/1991 JLB : Fixed return value bug.                              *\n *   01/31/1992 DRD : Modified to use new font format.                     *\n *   06/29/1994 SKB : modified for 32 bit library                          *\n *=========================================================================*/\nVOID *cdecl Set_Font(VOID const *fontptr)\n{\n\tVOID *oldfont;\n\tBYTE\tconst *blockptr;\n\n\toldfont = (VOID *) FontPtr;\n\n\tif (fontptr) {\n\t\tFontPtr    = (VOID *) fontptr;\n\n\t\t/*\n\t\t**\tInform the system about the new font.\n\t\t*/\n\n\t\tFontWidthBlockPtr = (BYTE*)fontptr + *(UWORD *)((BYTE*)fontptr + FONTWIDTHBLOCK);\n\t\tblockptr  = (BYTE*)fontptr + *(UWORD *)((BYTE*)fontptr + FONTINFOBLOCK);\n\t\tFontHeight = *(blockptr + FONTINFOMAXHEIGHT);\n\t\tFontWidth  = *(blockptr + FONTINFOMAXWIDTH);\n\t\t//Draw_Char_Setup();\n\n#if FALSE\n\t\tWindowLines = WinH / FontHeight;\n\t\tWindowWidth = WinW << 3;\n\t\tWindowColumns = WindowWidth / FontWidth;\n#endif\n\t}\n\n\treturn(oldfont);\n}\n"
  },
  {
    "path": "WWFLAT32/FONT/TEXTPRNT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : 32 bit library Text Print                *\n;*                                                                         *\n;*                    File Name : TEXTPRNT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : July 2, 1994                             *\n;*                                                                         *\n;*                  Last Update : July 2, 1994   [SKB]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Text_Print -- Assembly text print routine.                            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n\nGLOBAL\tC FontPtr:DWORD\nGLOBAL\tText_Print:NEAR\n\n; The header of the font file looks like this:\n; \tUWORD\tFontLength;\t\t0\n; \tBYTE\tFontCompress;\t\t2\n;\tBYTE\tFontDataBlocks;\t\t3\n;\tUWORD\tInfoBlockOffset;\t4\n;\tUWORD\tOffsetBlockOffset;\t6\n;\tUWORD\tWidthBlockOffset;\t8\n;\tUWORD\tDataBlockOffset;\t10\n;\tUWORD\tHeightOffset;\t\t12\n; For this reason the following equates have these values:\nFONTINFOBLOCK\t\tEQU\t4\nFONTOFFSETBLOCK\t\tEQU\t6\nFONTWIDTHBLOCK\t\tEQU\t8\nFONTDATABLOCK\t\tEQU\t10\nFONTHEIGHTBLOCK\t\tEQU\t12\n\nFONTINFOMAXHEIGHT\tEQU\t4\nFONTINFOMAXWIDTH\tEQU\t5\n\nLOCALS ??\n\n\tDATASEG\n\nColorXlat\tDB\t000H,001H,002H,003H,004H,005H,006H,007H\n\t\tDB\t008H,009H,00AH,00BH,00CH,00DH,00EH,00FH\n\n\t\tDB\t001H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t002H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t003H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t004H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t005H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t006H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t007H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t008H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t009H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00AH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00BH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00CH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00DH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00EH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00FH\n\n\tCODESEG\n\n\n;***************************************************************************\n;* TEXT_PRINT -- Assembly text print routine.                              *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/28/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tText_Print C near\n\tUSES\tebx,ecx,edx,esi,edi\n\tARG\tvpselector:WORD\n\tARG\tvpoffset:DWORD\n\tARG\tvpwidth:DWORD\n\tARG\tvpheight:DWORD\n\tARG\tvpxadd:DWORD\n\tARG\tstring:DWORD\n\tARG\tx_pixel:DWORD\n\tARG\ty_pixel:DWORD\n\tARG\tfcolor:DWORD\n\tARG\tbcolor:DWORD\n\t\t\n\tLOCAL\tinfoblock:DWORD\t\t; pointer to info block\n\tLOCAL\toffsetblock:DWORD\t; pointer to offset block  (UWORD *)\n\tLOCAL\twidthblock:DWORD\t; pointer to width block   (BYTE  *)\n\tLOCAL\theightblock:DWORD\t; pointer to height block  (UWORD *)\n\n\tLOCAL\tcurline:DWORD\t\t; pointer to first column of current row.\n\tLOCAL\tbufferwidth:DWORD    \t; width of buffer (vpwidth + Xadd)\n\tLOCAL\tnextdraw:DWORD\t\t; bufferwidth - width of cur character.\n\tLOCAL\tstartdraw:DWORD\t\t; where next character will start being drawn.\n\n\tLOCAL\tchar:DWORD\t\t; current character value.\t\n\n\tLOCAL\tmaxheight:BYTE\t\t; max height of characters in font.\n\tLOCAL\tbottomblank:BYTE\t; amount of empty space below current character.\n\tLOCAL\tcharheight:BYTE\t\t; true height of current character.\n\n\n;-------------------------------- Where to draw -----------------------------------------------\n\t; Set up memory location to start drawing.\n\tmovzx\teax,[vpselector]\n\tmov\tes,ax\t\t\t; Set up selector to write to.\n\n\tmov\teax,[vpwidth]\t\t; get the width of the viewport\n\tadd\teax,[vpxadd]\t\t; add amount to add to get to left edge of next line.\t\n\tmov\t[bufferwidth],eax     \t; save it off for later use.\n\n\tmul\t[y_pixel]\t\t; multiply rowsize * y_pixel start.\n\tmov\tedi,[vpoffset]\t\t; get start of the viewport\n\tadd\tedi,eax\t\t\t; add x,y position to start of vp to get starting row address.\t\n\tmov\t[curline],edi\t\t; save 0,y address for line feed stuff.\n\tadd\tedi,[x_pixel]\t\t; add to get starting column in starting row.\n\tmov\t[startdraw],edi\t\t; save it off.\n\n\n;-------------------------------- Create block pointers ----------------------------------------\n\t; Get the pointer to the font.\n\t; We could check for NULL but why waste the time.\n\t; It is up to programmer to make sure it is set.\n\tmov\tesi,[FontPtr]\t\t; Get the font pointer\n\n\t; Set up some pointers to the different memory blocks.\n\t; esi (FontPtr) is added to each to get the true address of each block.\n\t; Many registers are used for P5 optimizations.\n\t; ebx is used for InfoBlock which is then used in the next section.\n\tmovzx\teax,[WORD PTR esi+FONTOFFSETBLOCK]\t; get offset to offset block\n\tmovzx\tebx,[WORD PTR esi+FONTINFOBLOCK]      \t; get offset to info block (must be ebx for height test)\n\tmovzx\tecx,[WORD PTR esi+FONTWIDTHBLOCK] \t; get offset to width block\n\tmovzx\tedx,[WORD PTR esi+FONTHEIGHTBLOCK]\t; get offset to height block\n\n\tadd\teax,esi\t\t\t\t; add offset of FontPtr to offset block  \n\tadd\tebx,esi\t\t\t\t; add offset of FontPtr to info block \n\tadd\tecx,esi\t\t\t\t; add offset of FontPtr to width block\n\tadd\tedx,esi\t\t\t\t; add offset of FontPtr to height block\n\n\tmov\t[offsetblock],eax\t\t; save offset to offset block\n\tmov\t[infoblock],ebx\t\t\t; save offset to info block\n\tmov\t[widthblock],ecx   \t\t; save offset to width block\n\tmov\t[heightblock],edx\t\t; save offset to height block\n\n;------------------------------------------ Test for fit ----------------------------------------------\n\t; Test to make sure the height of the max character will fit on this line\n\t; and and not fall out of the viewport.\n\t; remember we set ebx to FONTINFOBLOCK above.\n\tmovzx\teax,[BYTE PTR ebx + FONTINFOMAXHEIGHT]; get the max height in font.\n\tmov\t[maxheight],al\t\t\t; save it for later use.\n\tadd\teax,[y_pixel]\t\t\t; add current y_value.\n\tcmp\teax,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we're outa here.\n\n\tmov\t[y_pixel],eax\t\t\t; save for next line feed. y value for next line.\n\n\tcld\t\t\t\t\t; Make sure we are always forward copying.\n\n;------------------------ Set palette foreground and background ----------------------------------\n\tmov\teax,[fcolor]\t\t; foreground color\n\tmov\t[ColorXlat+1],al\n\tmov\t[ColorXlat+16],al\n\n\tmov\teax,[bcolor]\t\t; background color\n\tmov\t[ColorXlat],al\n\n;-------------------------------------------------------------------------------------------------\n;----------------------------------------- Main loop ----------------------------------------------\n\t; Now we go into the main loop of reading each character in the string and doing\n\t; something with it.\n??next_char:\n\t; while (*string++)\n\txor\teax,eax\t\t\t\t; zero out since we will just load al.\t\n\tmov\tesi,[string]\t\t\t; get address on next character.\t\n\tlodsb\t\t\t\t\t; load the character into al.\n\ttest\teax,0FFH\t\t\t; test to see if character is a NULL\n\tjz\t??done\t\t\t\t; character is NULL, get outa here.\n\n\tmov\tedi,[startdraw]\t\t\t; Load the starting address.\n\n\tmov\t[string],esi\t\t\t; save index into string. (incremented by lodsb)\t\n\t\n\tcmp\teax,13\t\t\t\t; is the character a line feed?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\n\tmov\t[char],eax\t\t\t; save the character off for later reference.\n\tmov\tebx,eax\t\t\t\t; save it in ebx for later use also.\n\n\tadd\teax,[widthblock]\t\t; figure address of width of character.\n\tmov\tecx,[x_pixel]\t\t\t; get current x_pixel.\n\tmovzx\tedx,[BYTE PTR eax]\t \t; get the width of the character in dl.\n\tadd\tecx,edx\t\t\t\t; add width of char to current x_pixel.\n\tadd\t[startdraw],edx\t\t\t; save start draw for next character.\n\n\tcmp\tecx,[vpwidth]\t\t\t; is the pixel greater then the vp width?\n\tjg\t??force_line_feed\t\t; if so, force a line feed.\n\n\tmov\t[x_pixel],ecx\t\t\t; save value of start of next character.\n\tmov\tecx,[bufferwidth]\t\t; get amount to next y same x (one row down)\n\tsub\tecx,edx\t\t\t\t; take the current width off.\n\tmov\t[nextdraw],ecx\t\t\t; save it to add to edi when done with a row.\n\n\t; At this point we got the character. It is now time to find out specifics\n\t; about drawing the darn thing.\n\t; ebx = char so they can be used as an indexes.\n\t; edx = width of character for loop later.\n\n\t; get offset of data for character into esi.\n\tshl\tebx,1\t\t\t\t; mult by 2 to later use as a WORD index.\n\tmov\tesi,[offsetblock]\t\t; get pointer to begining of offset block.\n\tadd\tesi,ebx\t\t\t\t; index into offset block.\t\n\tmovzx\tesi,[WORD PTR esi]\t\t; get true offset into data block from FontPtr.\n\tadd\tesi,[FontPtr]\t\t\t; Now add FontPtr address to get true address.\n\n\t; Get top and bottom blank sizes and the true height of the character.\n\tadd\tebx,[heightblock]\t\t; point ebx to element in height array.\n\tmov\tal,[ebx+1]\t\t\t; load the data height into dl.\n\tmov\tcl,[ebx]\t\t\t; load the first data row into cl.\n\tmov\tbl,[maxheight]\t\t\t; get the max height of characters.\n\tmov\t[charheight],al\t\t\t; get number of rows with data.\n\tadd\tal,cl\t\t\t\t; add the two heights.\n\tsub\tbl,al\t\t\t\t; subract topblank + char height from maxheight.\n\tmov\t[bottomblank],bl\t\t; save off the number of blank rows on the bottom.\n\t; leaving this section:\n\t; dl is still the width of the character.\n\t; cl is the height of the top blank area.\n\n\tmov\tebx,OFFSET ColorXlat\t\t; setup ebx for xlat commands.\n\tmov\tdh,dl\t\t\t\t; save the width of the character to restore each loop.\n\n\tcmp\tcl,0\t\t\t\t; is there any blank rows on top?\n\tjz\t??draw_char\t\t\t; if not go and draw the real character.\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjnz\t??loop_top\t\t\t; if not go and write the color\n\n;----------------------------------------- skip Top blank area ----------------------------------------\n\t; this case, the top is transparrent, but we need to increase our dest pointer to correct row.\n\tmovzx\teax,cl\t\t\t\t; get number of rows into eax;\n\tmov\tecx,edx\t\t\t\t; save width since edx will be destroyed by mul.\n\tmul\t[bufferwidth]\t\t\t; multiply that by the width of the buffer.\n\tmov\tedx,ecx\t\t\t\t; restore the width\n\tadd\tedi,eax\t\t\t\t; update the pointer.\t\n\tjmp\tshort ??draw_char\t\t; now go draw the character.\n\n;----------------------------------------- fill Top blank area ----------------------------------------\n\t; edi was set a long time ago.\n\t; al is the translated color\n??loop_top:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_top\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tdec\tcl\t\t\t\t; decrement or row count\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tjz\t??draw_char\t\t\t; we are done here, go draw the character.\n\tjmp\tshort ??loop_top\t\t; go back to top of loop.\n\n\n;----------------------------------------- Draw character ----------------------------------------------\n??draw_char:\n\tmovzx\tecx,[charheight]\t\t; get the height of character to count down rows.\n\ttest\tecx,ecx\t\t\t\t; is there any data? (blank would not have any)\n\tjz\t??next_char\t\t\t; if no data, go on to next character.\t\n\n??while_data:\n\tlodsb\t\t\t\t\t; get byte value from font data\n\tmov\tah,al\t\t\t\t; save hinibble\n\tand\teax,0F00FH\t       \t\t; mask of low nibble in al hi nibble in ah.\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiplo\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiplo:\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjz\tshort ??nextrow\t\t\t; check if done with width of char\n\n\tmov\tal,ah\t\t\t\t; restore to get\n\t; test the time difference between looking up in a large table when shr al,4 is not done as\n\t; compared to using only a 16 byte table when using the shr al,4\n\t;shr\tal,4\t\t\t\t; shift the hi nibble down to low nibble\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiphi\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiphi:\n\t\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\tshort ??while_data\t\t; check if done with width of char\n\n??nextrow:\n\tadd\tedi,[nextdraw]\t\t\t; go to next line.\n\tdec\tecx\t\t\t\t; decrement the number of rows to go\n\tmov\tdh,dl\t\t\t\t; restore our column count for row.\n\tjnz\t??while_data\t\t\t; more data for character.\n\n\t; Now it is time to setup for clearing out the bottom of the character.\n\tmovzx\tecx,[bottomblank]\t\t; get amount on bottom that is blank\n\tcmp\tecx,0\t\t\t\t; if there is no blank bottom...\n\tjz\t??next_char\t\t\t; then skip to go to next character\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjz\t??next_char\t\t\t; skip the top black section to let the background through\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\n;----------------------------------------- Blank below character -----------------------------------\n??loop_bottom:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_bottom\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tdec\tcl\t\t\t\t; decrement or row count\n\tjz\t??next_char\t\t\t; we are done here, go to the next character.\n\tjmp\tshort ??loop_bottom\t\t; go back to top of loop.\n\n;----------------------------------- end of next_char (main) loop ------------------------------------\n;-------------------------------------------------------------------------------------------------\n\n\n;----------------------------------- special case line feeds ----------------------------------------\n\n??force_line_feed:\t\n\t; decrement pointer *string so that it will be back at same character\n\t; when it goes through the loop.\n\tmov\teax,[string]\t\t\t; get string pointer.\n\tdec\teax\t\t\t\t; decrement it to point to previos char\n\tmov\t[string],eax\t\t\t; save it back off.\n\t; Now go into the line feed code.....\n\n??line_feed:\n\tmov\tedx,[y_pixel]\t\t\t; get the current y pixel value.\n\tmovzx\tecx,[maxheight]\t\t\t; get max height for later use.\n\tadd\tedx,ecx\t\t\t\t; add max height to y_pixel\n\tcmp\tedx,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we are outa here.\n\n\tmov\teax,[bufferwidth]      \t\t; get bytes to next line.\n\tmov\tedi,[curline]\t\t\t; get start of current line.\t\n\tmul\tecx\t\t\t\t; mult max height * next line.\t\n\n\tadd\tedi,eax\t\t\t\t; add adjustment to current line.\n\tadd\t[y_pixel],ecx\t\t\t; increment to our next y position.\n\tmov\t[curline],edi\t\t\t; save it off for next line_feed.\n\tmov\t[startdraw],edi\t\t\t; save it off so we know where to draw next char.w\n\n\tmov\t[x_pixel],0\t\t\t; zero out x_pixel\n\n\tjmp\t??next_char\n\n??overflow:\n\tmov\t[startdraw],0\t\t\t; Indicate that there is no valid next pos.\n??done:\n\tmov\teax,[startdraw]\t\t\t; return this so calling routine\n\tret\t\t\t\t\t; can figure out where to draw next.\n\t\t\n\tENDP\tText_Print\n\n\n\n;***********************************************************\n\n\tEND\n"
  },
  {
    "path": "WWFLAT32/FONT/TEXTPRNT.BAK",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : 32 bit library Text Print                *\n;*                                                                         *\n;*                    File Name : TEXTPRNT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : July 2, 1994                             *\n;*                                                                         *\n;*                  Last Update : July 2, 1994   [SKB]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Text_Print -- Assembly text print routine.                            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n\nGLOBAL\tFontPtr:DWORD\nGLOBAL\tText_Print:NEAR\n\n; The header of the font file looks like this:\n; \tUWORD\tFontLength;\t\t0\n; \tBYTE\tFontCompress;\t\t2\n;\tBYTE\tFontDataBlocks;\t\t3\n;\tUWORD\tInfoBlockOffset;\t4\n;\tUWORD\tOffsetBlockOffset;\t6\n;\tUWORD\tWidthBlockOffset;\t8\n;\tUWORD\tDataBlockOffset;\t10\n;\tUWORD\tHeightOffset;\t\t12\n; For this reason the following equates have these values:\nFONTINFOBLOCK\t\tEQU\t4\nFONTOFFSETBLOCK\t\tEQU\t6\nFONTWIDTHBLOCK\t\tEQU\t8\nFONTDATABLOCK\t\tEQU\t10\nFONTHEIGHTBLOCK\t\tEQU\t12\n\nFONTINFOMAXHEIGHT\tEQU\t4\nFONTINFOMAXWIDTH\tEQU\t5\n\nLOCALS ??\n\n\tDATASEG\n\nColorXlat\tDB\t000H,001H,002H,003H,004H,005H,006H,007H\n\t\tDB\t008H,009H,00AH,00BH,00CH,00DH,00EH,00FH\n\n\t\tDB\t001H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t002H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t003H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t004H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t005H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t006H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t007H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t008H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t009H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00AH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00BH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00CH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00DH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00EH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00FH\n\n\tCODESEG\n\n\n;***************************************************************************\n;* TEXT_PRINT -- Assembly text print routine.                              *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/28/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tText_Print C near\n\tUSES\tebx,ecx,edx,esi,edi\n\tARG\tvpselector:WORD\n\tARG\tvpoffset:DWORD\n\tARG\tvpwidth:DWORD\n\tARG\tvpheight:DWORD\n\tARG\tvpxadd:DWORD\n\tARG\tstring:DWORD\n\tARG\tx_pixel:DWORD\n\tARG\ty_pixel:DWORD\n\tARG\tfcolor:DWORD\n\tARG\tbcolor:DWORD\n\t\t\n\tLOCAL\tinfoblock:DWORD\t\t; pointer to info block\n\tLOCAL\toffsetblock:DWORD\t; pointer to offset block  (UWORD *)\n\tLOCAL\twidthblock:DWORD\t; pointer to width block   (BYTE  *)\n\tLOCAL\theightblock:DWORD\t; pointer to height block  (UWORD *)\n\n\tLOCAL\tcurline:DWORD\t\t; pointer to first column of current row.\n\tLOCAL\tbufferwidth:DWORD    \t; width of buffer (vpwidth + Xadd)\n\tLOCAL\tnextdraw:DWORD\t\t; bufferwidth - width of cur character.\n\tLOCAL\tstartdraw:DWORD\t\t; where next character will start being drawn.\n\n\tLOCAL\tchar:DWORD\t\t; current character value.\t\n\n\tLOCAL\tmaxheight:BYTE\t\t; max height of characters in font.\n\tLOCAL\tbottomblank:BYTE\t; amount of empty space below current character.\n\tLOCAL\tcharheight:BYTE\t\t; true height of current character.\n\n\n;-------------------------------- Where to draw -----------------------------------------------\n\t; Set up memory location to start drawing.\n\tmovzx\teax,[vpselector]\n\tmov\tes,ax\t\t\t; Set up selector to write to.\n\n\tmov\teax,[vpwidth]\t\t; get the width of the viewport\n\tadd\teax,[vpxadd]\t\t; add amount to add to get to left edge of next line.\t\n\tmov\t[bufferwidth],eax     \t; save it off for later use.\n\n\tmul\t[y_pixel]\t\t; multiply rowsize * y_pixel start.\n\tmov\tedi,[vpoffset]\t\t; get start of the viewport\n\tadd\tedi,eax\t\t\t; add x,y position to start of vp to get starting row address.\t\n\tmov\t[curline],edi\t\t; save 0,y address for line feed stuff.\n\tadd\tedi,[x_pixel]\t\t; add to get starting column in starting row.\n\tmov\t[startdraw],edi\t\t; save it off.\n\n\n;-------------------------------- Create block pointers ----------------------------------------\n\t; Get the pointer to the font.\n\t; We could check for NULL but why waste the time.\n\t; It is up to programmer to make sure it is set.\n\tmov\tesi,[FontPtr]\t\t; Get the font pointer\n\n\t; Set up some pointers to the different memory blocks.\n\t; esi (FontPtr) is added to each to get the true address of each block.\n\t; Many registers are used for P5 optimizations.\n\t; ebx is used for InfoBlock which is then used in the next section.\n\tmovzx\teax,[WORD PTR esi+FONTOFFSETBLOCK]\t; get offset to offset block\n\tmovzx\tebx,[WORD PTR esi+FONTINFOBLOCK]      \t; get offset to info block (must be ebx for height test)\n\tmovzx\tecx,[WORD PTR esi+FONTWIDTHBLOCK] \t; get offset to width block\n\tmovzx\tedx,[WORD PTR esi+FONTHEIGHTBLOCK]\t; get offset to height block\n\n\tadd\teax,esi\t\t\t\t; add offset of FontPtr to offset block  \n\tadd\tebx,esi\t\t\t\t; add offset of FontPtr to info block \n\tadd\tecx,esi\t\t\t\t; add offset of FontPtr to width block\n\tadd\tedx,esi\t\t\t\t; add offset of FontPtr to height block\n\n\tmov\t[offsetblock],eax\t\t; save offset to offset block\n\tmov\t[infoblock],ebx\t\t\t; save offset to info block\n\tmov\t[widthblock],ecx   \t\t; save offset to width block\n\tmov\t[heightblock],edx\t\t; save offset to height block\n\n;------------------------------------------ Test for fit ----------------------------------------------\n\t; Test to make sure the height of the max character will fit on this line\n\t; and and not fall out of the viewport.\n\t; remember we set ebx to FONTINFOBLOCK above.\n\tmovzx\teax,[BYTE PTR ebx + FONTINFOMAXHEIGHT]; get the max height in font.\n\tmov\t[maxheight],al\t\t\t; save it for later use.\n\tadd\teax,[y_pixel]\t\t\t; add current y_value.\n\tcmp\teax,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we're outa here.\n\n\tmov\t[y_pixel],eax\t\t\t; save for next line feed. y value for next line.\n\n\tcld\t\t\t\t\t; Make sure we are always forward copying.\n\n;------------------------ Set palette foreground and background ----------------------------------\n\tmov\teax,[fcolor]\t\t; foreground color\n\tmov\t[ColorXlat+1],al\n\tmov\t[ColorXlat+16],al\n\n\tmov\teax,[bcolor]\t\t; background color\n\tmov\t[ColorXlat],al\n\n;-------------------------------------------------------------------------------------------------\n;----------------------------------------- Main loop ----------------------------------------------\n\t; Now we go into the main loop of reading each character in the string and doing\n\t; something with it.\n??next_char:\n\t; while (*string++)\n\txor\teax,eax\t\t\t\t; zero out since we will just load al.\t\n\tmov\tesi,[string]\t\t\t; get address on next character.\t\n\tlodsb\t\t\t\t\t; load the character into al.\n\ttest\teax,0FFH\t\t\t; test to see if character is a NULL\n\tjz\t??done\t\t\t\t; character is NULL, get outa here.\n\n\tmov\tedi,[startdraw]\t\t\t; Load the starting address.\n\n\tmov\t[string],esi\t\t\t; save index into string. (incremented by lodsb)\t\n\t\n\tcmp\teax,13\t\t\t\t; is the character a line feed?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\n\tmov\t[char],eax\t\t\t; save the character off for later reference.\n\tmov\tebx,eax\t\t\t\t; save it in ebx for later use also.\n\n\tadd\teax,[widthblock]\t\t; figure address of width of character.\n\tmov\tecx,[x_pixel]\t\t\t; get current x_pixel.\n\tmovzx\tedx,[BYTE PTR eax]\t \t; get the width of the character in dl.\n\tadd\tecx,edx\t\t\t\t; add width of char to current x_pixel.\n\tadd\t[startdraw],edx\t\t\t; save start draw for next character.\n\n\tcmp\tecx,[vpwidth]\t\t\t; is the pixel greater then the vp width?\n\tjg\t??force_line_feed\t\t; if so, force a line feed.\n\n\tmov\t[x_pixel],ecx\t\t\t; save value of start of next character.\n\tmov\tecx,[bufferwidth]\t\t; get amount to next y same x (one row down)\n\tsub\tecx,edx\t\t\t\t; take the current width off.\n\tmov\t[nextdraw],ecx\t\t\t; save it to add to edi when done with a row.\n\n\t; At this point we got the character. It is now time to find out specifics\n\t; about drawing the darn thing.\n\t; ebx = char so they can be used as an indexes.\n\t; edx = width of character for loop later.\n\n\t; get offset of data for character into esi.\n\tshl\tebx,1\t\t\t\t; mult by 2 to later use as a WORD index.\n\tmov\tesi,[offsetblock]\t\t; get pointer to begining of offset block.\n\tadd\tesi,ebx\t\t\t\t; index into offset block.\t\n\tmovzx\tesi,[WORD PTR esi]\t\t; get true offset into data block from FontPtr.\n\tadd\tesi,[FontPtr]\t\t\t; Now add FontPtr address to get true address.\n\n\t; Get top and bottom blank sizes and the true height of the character.\n\tadd\tebx,[heightblock]\t\t; point ebx to element in height array.\n\tmov\tal,[ebx+1]\t\t\t; load the data height into dl.\n\tmov\tcl,[ebx]\t\t\t; load the first data row into cl.\n\tmov\tbl,[maxheight]\t\t\t; get the max height of characters.\n\tmov\t[charheight],al\t\t\t; get number of rows with data.\n\tadd\tal,cl\t\t\t\t; add the two heights.\n\tsub\tbl,al\t\t\t\t; subract topblank + char height from maxheight.\n\tmov\t[bottomblank],bl\t\t; save off the number of blank rows on the bottom.\n\t; leaving this section:\n\t; dl is still the width of the character.\n\t; cl is the height of the top blank area.\n\n\tmov\tebx,OFFSET ColorXlat\t\t; setup ebx for xlat commands.\n\tmov\tdh,dl\t\t\t\t; save the width of the character to restore each loop.\n\n\tcmp\tcl,0\t\t\t\t; is there any blank rows on top?\n\tjz\t??draw_char\t\t\t; if not go and draw the real character.\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjnz\t??loop_top\t\t\t; if not go and write the color\n\n;----------------------------------------- skip Top blank area ----------------------------------------\n\t; this case, the top is transparrent, but we need to increase our dest pointer to correct row.\n\tmovzx\teax,cl\t\t\t\t; get number of rows into eax;\n\tmov\tecx,edx\t\t\t\t; save width since edx will be destroyed by mul.\n\tmul\t[bufferwidth]\t\t\t; multiply that by the width of the buffer.\n\tmov\tedx,ecx\t\t\t\t; restore the width\n\tadd\tedi,eax\t\t\t\t; update the pointer.\t\n\tjmp\tshort ??draw_char\t\t; now go draw the character.\n\n;----------------------------------------- fill Top blank area ----------------------------------------\n\t; edi was set a long time ago.\n\t; al is the translated color\n??loop_top:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_top\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tdec\tcl\t\t\t\t; decrement or row count\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tjz\t??draw_char\t\t\t; we are done here, go draw the character.\n\tjmp\tshort ??loop_top\t\t; go back to top of loop.\n\n\n;----------------------------------------- Draw character ----------------------------------------------\n??draw_char:\n\tmovzx\tecx,[charheight]\t\t; get the height of character to count down rows.\n\ttest\tecx,ecx\t\t\t\t; is there any data? (blank would not have any)\n\tjz\t??next_char\t\t\t; if no data, go on to next character.\t\n\n??while_data:\n\tlodsb\t\t\t\t\t; get byte value from font data\n\tmov\tah,al\t\t\t\t; save hinibble\n\tand\teax,0F00FH\t       \t\t; mask of low nibble in al hi nibble in ah.\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiplo\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiplo:\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjz\tshort ??nextrow\t\t\t; check if done with width of char\n\n\tmov\tal,ah\t\t\t\t; restore to get\n\t; test the time difference between looking up in a large table when shr al,4 is not done as\n\t; compared to using only a 16 byte table when using the shr al,4\n\t;shr\tal,4\t\t\t\t; shift the hi nibble down to low nibble\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiphi\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiphi:\n\t\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\tshort ??while_data\t\t; check if done with width of char\n\n??nextrow:\n\tadd\tedi,[nextdraw]\t\t\t; go to next line.\n\tdec\tecx\t\t\t\t; decrement the number of rows to go\n\tmov\tdh,dl\t\t\t\t; restore our column count for row.\n\tjnz\t??while_data\t\t\t; more data for character.\n\n\t; Now it is time to setup for clearing out the bottom of the character.\n\tmovzx\tecx,[bottomblank]\t\t; get amount on bottom that is blank\n\tcmp\tecx,0\t\t\t\t; if there is no blank bottom...\n\tjz\t??next_char\t\t\t; then skip to go to next character\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjz\t??next_char\t\t\t; skip the top black section to let the background through\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\n;----------------------------------------- Blank below character -----------------------------------\n??loop_bottom:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_bottom\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tdec\tcl\t\t\t\t; decrement or row count\n\tjz\t??next_char\t\t\t; we are done here, go to the next character.\n\tjmp\tshort ??loop_bottom\t\t; go back to top of loop.\n\n;----------------------------------- end of next_char (main) loop ------------------------------------\n;-------------------------------------------------------------------------------------------------\n\n\n;----------------------------------- special case line feeds ----------------------------------------\n\n??force_line_feed:\t\n\t; decrement pointer *string so that it will be back at same character\n\t; when it goes through the loop.\n\tmov\teax,[string]\t\t\t; get string pointer.\n\tdec\teax\t\t\t\t; decrement it to point to previos char\n\tmov\t[string],eax\t\t\t; save it back off.\n\t; Now go into the line feed code.....\n\n??line_feed:\n\tmov\tedx,[y_pixel]\t\t\t; get the current y pixel value.\n\tmovzx\tecx,[maxheight]\t\t\t; get max height for later use.\n\tadd\tedx,ecx\t\t\t\t; add max height to y_pixel\n\tcmp\tedx,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we are outa here.\n\n\tmov\teax,[bufferwidth]      \t\t; get bytes to next line.\n\tmov\tedi,[curline]\t\t\t; get start of current line.\t\n\tmul\tecx\t\t\t\t; mult max height * next line.\t\n\n\tadd\tedi,eax\t\t\t\t; add adjustment to current line.\n\tadd\t[y_pixel],ecx\t\t\t; increment to our next y position.\n\tmov\t[curline],edi\t\t\t; save it off for next line_feed.\n\tmov\t[startdraw],edi\t\t\t; save it off so we know where to draw next char.w\n\n\tmov\t[x_pixel],0\t\t\t; zero out x_pixel\n\n\tjmp\t??next_char\n\n??overflow:\n\tmov\t[startdraw],0\t\t\t; Indicate that there is no valid next pos.\n??done:\n\tmov\teax,[startdraw]\t\t\t; return this so calling routine\n\tret\t\t\t\t\t; can figure out where to draw next.\n\t\t\n\tENDP\tText_Print\n\n\n\n;***********************************************************\n\n\tEND\n"
  },
  {
    "path": "WWFLAT32/IFF/FILEPCX.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : iff                                      *\n;*                                                                         *\n;*                    File Name : FILEPCX.H                                *\n;*                                                                         *\n;*                   Programmer : Julio R. Jerez                           *\n;*                                                                         *\n;*                   Start Date : May 2, 1995                              *\n;*                                                                         *\n;*                  Last Update : May 2, 1995   [JRJ]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* GraphicBufferClass* Read_PCX_File (char* name, BYTE* palette,void *buff, long size);\n;* GraphicBufferClass* Read_PCX_File (char* name, BYTE* palette, BufferClass& Buff); \n;* int Write_PCX_File (char* name, GraphicViewPortClass& pic, BYTE* palette );*\n;*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n#include <string.h>\n#include <buffer.h>\n#include <gbuffer.h>\n#include\t<file.h>\n\n#ifndef PCX_H\n#define PCX_H\n\n\ntypedef\tstruct {\n\t\t\t\t\t\t  char\tred ;\n\t\t\t\t\t\t  char\tgreen ;\n\t\t\t\t\t\t  char\tblue ;\n\t\t\t\t\t} RGB ;\n\ntypedef\tstruct\t{\n\t\t\t\t\t\t  char      id ;\n\t\t\t\t\t\t  char\t   version ;\n\t\t\t\t\t\t  char\t   encoding ;\n\t\t\t\t\t\t  char\t   pixelsize ;\n\t\t\t\t\t\t  short \t   x ;\n\t\t\t\t\t\t  short\t\ty ;\n\t\t\t\t\t\t  short     width ;\n\t\t\t\t\t\t  short\t\theight ;\n\t\t\t\t\t\t  short \t   xres ;\n\t\t\t\t\t\t  short\t\tyres ;\n\t\t\t\t\t\t  RGB       ega_palette [ 16 ] ;\n\t\t\t\t\t\t  char\t   nothing ;\n\t\t\t\t\t\t  char      color_planes ;\n\t\t\t\t\t\t  short \t\tbyte_per_line ;\n\t\t\t\t\t\t  short \t \tpalette_type ;\n\t\t\t\t\t\t  char\t   filler [ 58 ] ;\n\t\t\t\t\t\t} PCX_HEADER ;\n\nGraphicBufferClass* Read_PCX_File (char* name, BYTE* palette= NULL,void *buff=NULL, long size=0);\nGraphicBufferClass* Read_PCX_File (char* name, BufferClass& Buff,BYTE* palette= NULL) ;\nint Write_PCX_File (char* name, GraphicViewPortClass& pic ,BYTE* palette ) ;\t\t\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/IFF/IFF.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the FILEIO Library               *\n *                                                                         *\n *                    File Name : IFF.H                                    *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 20, 1994                           *\n *                                                                         *\n *                  Last Update : April 20, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef IFF_H\n#define IFF_H\n\n#ifndef MISC_H\n#include <misc.h>\t\t// This is needed fro Reverse_WORD and _LONG\n#endif\n\n#ifndef MEMFLAGS_H\n#include <memflag.h>\t// This is needed for MemoryFlagType.\n#endif\n\n#ifndef GBUFFER_H\n#include <gbuffer.h>\n#endif \n\n#define LZW_SUPPORTED\t\t\tFALSE\n\n/*=========================================================================*/\n/* Iff and Load Picture system defines and enumerations\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#define \tMAKE_ID(a,b,c,d)\t\t\t((LONG) ((LONG) d << 24) | ((LONG) c << 16) | ((LONG) b <<  8) | (LONG)(a))\n#define\tIFFize_WORD(a)\t\t\tReverse_WORD(a)\n#define\tIFFize_LONG(a)\t\t\tReverse_LONG(a)\n\n\n//lint -strong(AJX,PicturePlaneType)\ntypedef enum {\n\tBM_AMIGA,\t// Bit plane format (8K per bitplane).\n\tBM_MCGA,\t\t// Byte per pixel format (64K).\n\n\tBM_DEFAULT=BM_MCGA\t// Default picture format.\n} PicturePlaneType;\n\n/*\n**\tThis is the compression type code.  This value is used in the compressed\n**\tfile header to indicate the method of compression used.  Note that the\n**\tLZW method may not be supported.\n*/\n//lint -strong(AJX,CompressionType)\ntypedef enum {\n\tNOCOMPRESS,\t\t// No compression (raw data).\n\tLZW12,\t\t\t// LZW 12 bit codes.\n\tLZW14,\t\t\t// LZW 14 bit codes.\n\tHORIZONTAL,\t\t// Run length encoding (RLE).\n\tLCW\t\t\t\t// Westwood proprietary compression.\n} CompressionType;\n\n/*\n**\tCompressed blocks of data must start with this header structure.\n**\tNote that disk based compressed files have an additional two\n**\tleading bytes that indicate the size of the entire file.\n*/\n//lint -strong(AJX,CompHeaderType)\ntypedef struct {\n\tBYTE\tMethod;\t\t// Compression method (CompressionType).\n\tBYTE\tpad;\t\t\t// Reserved pad byte (always 0).\n\tLONG\tSize;\t\t\t// Size of the uncompressed data.\n\tWORD\tSkip;\t\t\t// Number of bytes to skip before data.\n} CompHeaderType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: IFF.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD cdecl Open_Iff_File(BYTE const *filename);\nVOID cdecl Close_Iff_File(WORD fh);\nULONG cdecl Get_Iff_Chunk_Size(WORD fh, LONG id);\nULONG cdecl Read_Iff_Chunk(WORD fh, LONG id, VOID *buffer, ULONG maxsize);\nVOID cdecl Write_Iff_Chunk(WORD file, LONG id, VOID *buffer, LONG length);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOADPICT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD cdecl Load_Picture(BYTE const *filename, BufferClass& scratchbuf, BufferClass& destbuf, UBYTE *palette=NULL, PicturePlaneType format=BM_DEFAULT);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOAD.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nULONG cdecl Load_Data(BYTE const *name, VOID *ptr, ULONG size);\nULONG cdecl Write_Data(BYTE const *name, VOID *ptr, ULONG size);\nVOID * cdecl Load_Alloc_Data(BYTE const *name, MemoryFlagType flags);\nULONG cdecl Load_Uncompress(BYTE const *file, BufferClass& uncomp_buff, BufferClass& dest_buff, VOID *reserved_data=NULL);\nULONG cdecl Uncompress_Data(VOID const *src, VOID *dst);\nVOID cdecl Set_Uncomp_Buffer(WORD buffer_segment, UWORD size_of_buffer);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WRITELBM.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nPUBLIC BOOL Write_LBM_File(WORD lbmhandle, BufferClass& buff, WORD bitplanes, UBYTE *palette);\n\n\n\n/*========================= Assembly Functions ============================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*=========================================================================*/\n/* The following prototypes are for the file: PACK2PLN.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern VOID Pack_2_Plane(VOID *buffer, VOID * pageptr, WORD planebit);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LCWCOMP.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern ULONG LCW_Compress(VOID *source, VOID *dest, ULONG length);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LCWUNCMP.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern ULONG LCW_Uncompress(VOID *source, VOID *dest, ULONG length);\n\n#ifdef __cplusplus\n}\n#endif\n/*=========================================================================*/\n\n\n\n#endif //IFF_H\n\u001a"
  },
  {
    "path": "WWFLAT32/IFF/IFF.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : IFF.C                                    *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : May 16, 1991                             *\n *                                                                         *\n *                  Last Update : April 19, 1994   [SKB]                   *\n *                                                                         *\n *                                                                         *\n * IFF reader code designed for loading pictures (ILBM or PBM).            *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Close_Iff_File -- Closes an IFF file handle.                          *\n *   Get_Iff_Chunk_Size -- Get the size of the given IFF chunk.            *\n *   Open_Iff_File -- Opens an IFF file for reading.                       *\n *   Read_Iff_Chunk -- Reads a chunk from an IFF file.                     *\n *   Write_Iff_Chunk -- Writes an IFF chuck out.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n \n#include <wwstd.h>\n#include \"iff.h\"\n#include \"file.h\"\n\n#define ID_FORM\t\t\tMAKE_ID('F','O','R','M')\n\n/***************************************************************************\n * OPEN_IFF_FILE -- Opens an IFF file for reading.                         *\n *                                                                         *\n *    This function will open an IFF file for reading.  It will perform    *\n *    a the simple validity test of checking the first four bytes to make  *\n *    sure they are \"FORM\".  The value returned is the filehandle of the   *\n *    opened file.                                                         *\n *                                                                         *\n * INPUT:   filename - ASCII name of the IFF file to be opened.            *\n *                                                                         *\n * OUTPUT:  Returns the filehandle.  If there is an error or the file      *\n *          is not an IFF FORM then -1 will be returned.                   *\n *                                                                         *\n * WARNINGS:   You are responsible for error handling if this function     *\n *             returns -1 (not an IFF file).                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1991 JLB : Created.                                             *\n *   04/19/1994 SKB : Update to 32 bit library.                            *\n *=========================================================================*/\nWORD cdecl Open_Iff_File(BYTE const *filename)\n{\n\tWORD\tfh;\t\t// File handle.\n\tLONG\ttype;\t\t// IFF file type.\n\n\n\t/* We want to be able to open the file for READ | WRITE, but we do not\n\t   want the Open_File to create it.  So check to see if it exists before\n\t\tthe Open_File */\n\n//\tfh = Open_File(filename, READ);\t\t// Open the source file for READ\n//\tClose_File(fh);\n\n\t//fh = Open_File(filename, READ | WRITE);\t// Open the source file again\n\tfh = Open_File(filename, READ);\t// Open the source file again\n\n\t//\tValidate that it is a FORM type.\n\n\tRead_File(fh, &type, 4L);\n\n\tif (type == ID_FORM) {\n\n\t\t//\tThe file is valid (so far).  Position the read so that the actual\n\t\t//\tIFF file type code can be read.\n\n\t\tSeek_File(fh, 4L, SEEK_CUR);\t\t// Skip the filesize bytes.\n\n\t} else {\n\n\t\t// This is NOT an IFF file.  Close the source file and return with\n\t\t//\tthe error code.\n\t\tClose_File(fh);\n\t\tfh = ERROR;\n\t}\n\treturn fh;\n}\n\n\n/***************************************************************************\n * CLOSE_IFF_FILE -- Closes an IFF file handle.                            *\n *                                                                         *\n *    The routine will close the file that was opened with the             *\n *    Open_Iff_File() function.                                            *\n *                                                                         *\n * INPUT:   fh - File handle that was returned from Open_Iff_File().       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1991 JLB : Created.                                             *\n *   04/19/1994 SKB : Update to 32 bit library.                            *\n *=========================================================================*/\nVOID cdecl Close_Iff_File(WORD fh)\n{\n\tif (fh != ERROR) Close_File(fh);\n}\n\n\n/***************************************************************************\n * GET_IFF_CHUNK_SIZE -- Get the size of the given IFF chunk.              *\n *                                                                         *\n * INPUT:      WORD file handle to open IFF file, LONG id to get size of   *\n *                                                                         *\n * OUTPUT:     LONG size of the chunk or 0L if it was not found            *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/03/1991  CY : Created.                                             *\n *   04/19/1994 SKB : Update to 32 bit library.                            *\n *=========================================================================*/\nULONG cdecl Get_Iff_Chunk_Size(WORD fh, LONG id)\n{\n\tLONG\tform;\t\t\t\t\t// Chunk iff form name.\n\tLONG\tchunksize;\t\t\t// Size of the chunk.\n\tBYTE\tfirst_iteration;\t// Check once the current chunk name\n\n\n\tfirst_iteration = TRUE;\n\n\tfor (;;) {\n\t\tif (Read_File(fh, &form, 4L) != 4L && !first_iteration) break;\n\n\n\t\tif (Read_File(fh, (BYTE *) &chunksize, 4L) != 4L && !first_iteration) break;\n\n#if(IBM)\n\t\tchunksize = Reverse_LONG(chunksize);\n#endif\n\n\t\tif (id == form) {\n\t\t\tSeek_File(fh, -8L, SEEK_CUR);\t\t\t// Seek back to the start of\n\t\t\treturn(chunksize);\t\t\t\t\t\t// the chunk & return size\n\t\t} else {\n\n\t\t\tif (first_iteration) {\n\t\t\t\tSeek_File(fh, 12L, SEEK_SET);\t\t// Start at beginning of file.\n\t\t\t\tfirst_iteration = FALSE;\t\t\t// Don't do this again\n\t\t\t} else {\n\n\t\t\t\t/* Otherwise, go to the next chunk in the file */\n\n\t\t\t\tchunksize = (chunksize + 1) & 0xFFFFFFFEL;\n\t\t\t\tSeek_File(fh, chunksize, SEEK_CUR);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(0L);\n}\n\n\n/***************************************************************************\n * READ_IFF_CHUNK -- Reads a chunk from an IFF file.                       *\n *                                                                         *\n *    Once an IFF file is opened, various chunks must be read from it.     *\n *    This routine will search through the IFF file and load in the        *\n *    specified chunk.  It will scan through the entire file when          *\n *    searching for the chunk.  It will load the FIRST chunk of the given  *\n *    type.                                                                *\n *                                                                         *\n * INPUT:   fh       - File handle of IFF file.                            *\n *                                                                         *\n *          id       - Chunk ID code.                                      *\n *                                                                         *\n *          buffer   - Pointer to buffer to load the chunk.                *\n *                                                                         *\n *          maxsize  - Maximum data bytes to read.                         *\n *                                                                         *\n * OUTPUT:     Returns with the number of bytes read from the chunk.       *\n *             If 0 is returned, this indicates that the chunk wasn't      *\n *             found.                                                      *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1991 JLB : Created.                                             *\n *   04/19/1994 SKB : Update to 32 bit library.                            *\n *=========================================================================*/\nULONG cdecl Read_Iff_Chunk(WORD fh, LONG id, VOID *buffer, ULONG maxsize)\n{\n\tLONG\tform;\t\t\t\t\t// Chunk iff form name.\n\tULONG\tchunksize;\t\t\t// Size of the chunk.\n\tBYTE\tfirst_iteration;\t// Check once the current chunk name\n\n\tfirst_iteration = TRUE;\n\n\tfor (;;) {\n\t\tif (Read_File(fh, &form, 4L) != 4L && !first_iteration) break;\n\n\t\tif (Read_File(fh, (BYTE *) &chunksize, 4L) != 4L && !first_iteration) break;\n\n#if(IBM)\n\t\tchunksize = Reverse_LONG(chunksize);\n#endif\n\n\t\tif (id == form) {\n\n\t\t\tmaxsize = MIN(maxsize, chunksize);\n\t\t\tRead_File(fh, buffer, maxsize);\t\t// Read the buffer.\n\n\t\t\tchunksize = (chunksize + 1) & 0xFFFFFFFEL;\n\t\t\tif (maxsize < chunksize) {\n\t\t\t\tSeek_File(fh, chunksize - maxsize, SEEK_CUR);\n\t\t\t}\n\t\t\treturn(maxsize);\n\t\t} else {\n\n\t\t\tif (first_iteration) {\n\t\t\t\tSeek_File(fh, 12L, SEEK_SET);\t\t// Start at beginning of file.\n\t\t\t\tfirst_iteration = FALSE;\t\t\t// Don't do this again\n\n\t\t\t} else {\n\n\t\t\t\t/* Otherwise, go to the next chunk in the file */\n\n\t\t\t\tchunksize = (chunksize + 1) & 0xFFFFFFFEL;\n\t\t\t\tSeek_File(fh, chunksize, SEEK_CUR);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(0L);\n}\n\n\n\n/***************************************************************************\n * WRITE_IFF_CHUNK -- Writes an IFF chuck out.                             *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1994 SKB : Created.                                             *\n *=========================================================================*/\nVOID cdecl Write_Iff_Chunk(WORD file, LONG id, VOID *buffer, LONG length)\n{\n\tLONG\tpos;\t\t// Current position in the IFF file.\n\tLONG\toldpos;\t// Record of start of chunk offset.\n\tLONG\tendpos;\t// end of file offset before we write our data\n\tLONG\tvalue;\n\tBOOL\todd;\t\t// Is length odd?\n\tBYTE\tpad = 0;\t// Optional padding byte for even sized chunks.\n\n\t/*\n\t** Get the current end of file (before we write more data to the file)\n\t*/\n\tpos \t = Seek_File (file, 0L, SEEK_CUR);\n\tendpos = Seek_File (file, 0L, SEEK_END);\n\tSeek_File (file, pos, SEEK_SET);\n\n\tif (length) {\n\t\tvalue = id;\n\t\todd = (WORD)length & 0x01;\n\n\t\tWrite_File(file, &value, 4L);\n\t\toldpos = Seek_File(file, 0L, SEEK_CUR);\n\t\tWrite_File(file, &value, 4L);\n\t\tWrite_File(file, buffer, length);\n\t\tpos = Seek_File(file, 0L, SEEK_CUR);\n\t\tif (odd) {\n\t\t\tWrite_File(file, &pad, 1L);\n\t\t}\n\n\t\t/*\n\t\t**\tUpdate the chunk size LONG.\n\t\t*/\n\t\tSeek_File(file, oldpos, SEEK_SET);\n\t\tvalue = IFFize_LONG((pos - oldpos)-4);\n\t\tWrite_File(file, &value, 4L);\n\n\t\t/*\n\t\t**\tUpdate the file size LONG. if we are not just overwriting existing data\n\t\t*/\n\t\t// (MCC)\n\t\tif ( endpos < pos ) {\n\t\t\tSeek_File(file, 4L, SEEK_SET);\n\t\t\tvalue = IFFize_LONG((pos+odd) - 8);\n\t\t\tWrite_File(file, &value, 4L);\n\t\t}\n\n\t\t/*\n\t\t**\tReturn to end of file.\n\t\t*/\n\t\tSeek_File(file, 0L, SEEK_END);\n\t}\n}\n\n\n"
  },
  {
    "path": "WWFLAT32/IFF/IFF.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the FILEIO Library               *\n *                                                                         *\n *                    File Name : IFF.H                                    *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 20, 1994                           *\n *                                                                         *\n *                  Last Update : April 20, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef IFF_H\n#define IFF_H\n\n#ifndef MISC_H\n#include <misc.h>\t\t// This is needed fro Reverse_WORD and _LONG\n#endif\n\n#ifndef MEMFLAGS_H\n#include <memflag.h>\t// This is needed for MemoryFlagType.\n#endif\n\n#ifndef GBUFFER_H\n#include <gbuffer.h>\n#endif \n\n#define LZW_SUPPORTED\t\t\tFALSE\n\n/*=========================================================================*/\n/* Iff and Load Picture system defines and enumerations\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#define \tMAKE_ID(a,b,c,d)\t\t\t((LONG) ((LONG) d << 24) | ((LONG) c << 16) | ((LONG) b <<  8) | (LONG)(a))\n#define\tIFFize_WORD(a)\t\t\tReverse_WORD(a)\n#define\tIFFize_LONG(a)\t\t\tReverse_LONG(a)\n\n\n//lint -strong(AJX,PicturePlaneType)\ntypedef enum {\n\tBM_AMIGA,\t// Bit plane format (8K per bitplane).\n\tBM_MCGA,\t\t// Byte per pixel format (64K).\n\n\tBM_DEFAULT=BM_MCGA\t// Default picture format.\n} PicturePlaneType;\n\n/*\n**\tThis is the compression type code.  This value is used in the compressed\n**\tfile header to indicate the method of compression used.  Note that the\n**\tLZW method may not be supported.\n*/\n//lint -strong(AJX,CompressionType)\ntypedef enum {\n\tNOCOMPRESS,\t\t// No compression (raw data).\n\tLZW12,\t\t\t// LZW 12 bit codes.\n\tLZW14,\t\t\t// LZW 14 bit codes.\n\tHORIZONTAL,\t\t// Run length encoding (RLE).\n\tLCW\t\t\t\t// Westwood proprietary compression.\n} CompressionType;\n\n/*\n**\tCompressed blocks of data must start with this header structure.\n**\tNote that disk based compressed files have an additional two\n**\tleading bytes that indicate the size of the entire file.\n*/\n//lint -strong(AJX,CompHeaderType)\ntypedef struct {\n\tBYTE\tMethod;\t\t// Compression method (CompressionType).\n\tBYTE\tpad;\t\t\t// Reserved pad byte (always 0).\n\tLONG\tSize;\t\t\t// Size of the uncompressed data.\n\tWORD\tSkip;\t\t\t// Number of bytes to skip before data.\n} CompHeaderType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: IFF.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD cdecl Open_Iff_File(BYTE const *filename);\nVOID cdecl Close_Iff_File(WORD fh);\nULONG cdecl Get_Iff_Chunk_Size(WORD fh, LONG id);\nULONG cdecl Read_Iff_Chunk(WORD fh, LONG id, VOID *buffer, ULONG maxsize);\nVOID cdecl Write_Iff_Chunk(WORD file, LONG id, VOID *buffer, LONG length);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOADPICT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//WORD cdecl Load_Picture(BYTE const *filename, BufferClass& scratchbuf, BufferClass& destbuf, UBYTE *palette=NULL, PicturePlaneType format=BM_DEFAULT);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOAD.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nULONG cdecl Load_Data(BYTE const *name, VOID *ptr, ULONG size);\nULONG cdecl Write_Data(BYTE const *name, VOID *ptr, ULONG size);\nVOID * cdecl Load_Alloc_Data(BYTE const *name, MemoryFlagType flags);\n//ULONG cdecl Load_Uncompress(BYTE const *file, BufferClass& uncomp_buff, BufferClass& dest_buff, VOID *reserved_data=NULL);\nULONG cdecl Uncompress_Data(VOID const *src, VOID *dst);\nVOID cdecl Set_Uncomp_Buffer(WORD buffer_segment, UWORD size_of_buffer);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WRITELBM.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nPUBLIC BOOL Write_LBM_File(WORD lbmhandle, BufferClass& buff, WORD bitplanes, UBYTE *palette);\n\n\n\n/*========================= Assembly Functions ============================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*=========================================================================*/\n/* The following prototypes are for the file: PACK2PLN.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern VOID Pack_2_Plane(VOID *buffer, VOID * pageptr, WORD planebit);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LCWCOMP.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern ULONG LCW_Compress(VOID *source, VOID *dest, ULONG length);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LCWUNCMP.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern ULONG LCW_Uncompress(VOID *source, VOID *dest, ULONG length);\n\n#ifdef __cplusplus\n}\n#endif\n/*=========================================================================*/\n\n\n\n#endif //IFF_H\n\u001a\n"
  },
  {
    "path": "WWFLAT32/IFF/LCWCOMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/misc/rcs/lcwcomp.asm 1.1 1994/04/11 15:31:10 jeff_wilson Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library routine                          *\n;*                                                                         *\n;*                    File Name : COMPRESS.ASM                             *\n;*                                                                         *\n;*                   Programmer : Louis Castle                             *\n;*                                                                         *\n;*                  Last Update : 20 August, 1990   [CY]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n; ULONG LCW_Compress(BYTE *source,BYTE *dest, ULONG length);                *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL    LCW_Compress          :NEAR\n\nCODESEG\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; ULONG LCW_Compress(BYTE *source,BYTE *dest, ULONG length);\n;\n; ----------------------------------------------------------------\n\n\n\n;***********************************************************\n;\n; ULONG LCW_Compress(BYTE *source, BYTE *dest, ULONG length)\n;\n; returns the size of the compressed data in bytes\n;\n;*\nPROC\tLCW_Compress C near \n\tUSES ebx,ecx,edx,edi,esi\n\t\n\tARG\tsource:DWORD   \n\tARG\tdest:DWORD\n\tARG\tdatasize:DWORD\n\n\tLOCAL inlen:DWORD\n\tLOCAL a1stdest:DWORD\n\tLOCAL a1stsrc:DWORD\n\tLOCAL lenoff:DWORD\n\tLOCAL ndest:DWORD\n\tLOCAL count:DWORD\n\tLOCAL matchoff:DWORD\n\tLOCAL end_of_data:DWORD\n\n\n\tcld\n \tmov\tedi,[dest]\n \tmov\tesi,[source]\n \tmov\tedx,[datasize]\t\t; get length of data to compress\n\t\n;\tmov\tax,ds\n;\tmov\tes,ax\n\n;\n; compress data to the following codes in the format b = byte, w = word\n; n = byte code pulled from compressed data\n;   Bit field of n\t\tcommand\t\tdescription\n; n=0xxxyyyy,yyyyyyyy\t\tshort run\tback y bytes and run x+3\n; n=10xxxxxx,n1,n2,...,nx+1\tmed length\tcopy the next x+1 bytes\n; n=11xxxxxx,w1\t\t\tmed run\t\trun x+3 bytes from offset w1\n; n=11111111,w1,w2\t\tlong run\trun w1 bytes from offset w2\n; n=10000000\t\t\tend\t\tend of data reached\n;\n\tcld\t\t\t; make sure all string commands are forward\n\tmov\tebx,esi\n\tadd\tebx,edx\n\tmov\t[end_of_data],ebx\n\tmov\t[inlen],1\t; set the in-length flag\n\tmov\t[a1stdest],edi\t; save original dest offset for size calc\n\tmov\t[a1stsrc],esi\t; save offset of first byte of data\n\tmov\t[lenoff],edi\t; save the offset of the legth of this len\n\tsub\teax,eax\n\tmov\tal,081h\t\t; the first byte is always a len\n\tstosb\t\t\t; write out a len of 1\n\tlodsb\t\t\t; get the byte\n\tstosb\t\t\t; save it\n??loop:\n\tmov\t[ndest],edi\t; save offset of compressed data\n\tmov\tedi,[a1stsrc]\t; get the offset to the first byte of data\n\tmov\t[count],1\t; set the count of run to 0\n??searchloop:\n\tsub\teax,eax\n\tmov\tal,[esi]\t; get the current byte of data\n\tcmp\tal,[esi+64]\n\tjne\tshort ??notrunlength\n\t\n\tmov\tebx,edi\t\t \n\t\n\tmov\tedi,esi\n\tmov\tecx,[end_of_data]\n\tsub\tecx,edi\n   \trepe\tscasb\n\tdec\tedi\n\tmov\tecx,edi\n\tsub\tecx,esi\n\tcmp\tecx,65\n\tjb\tshort ??notlongenough\n\t\n\tmov\t[DWORD PTR inlen],0\t; clear the in-length flag\n\tmov\tesi,edi\n\tmov\tedi,[ndest]\t; get the offset of our compressed data\n\t\n\tmov\tah,al\n\tmov\tal,0FEh\n\tstosb\n\txchg\tecx,eax\n\tstosw\n\tmov\tal,ch\n\tstosb\n\t\n\tmov\t[ndest],edi\t; save offset of compressed data\n\tmov\tedi,ebx\n\tjmp\t??searchloop\n??notlongenough:\n\tmov\tedi,ebx\n??notrunlength:\n\n??oploop:\n\tmov\tecx,esi\t\t; get the address of the last byte +1\n\tsub\tecx,edi\t\t; get the total number of bytes left to comp\n\tjz\tshort ??searchdone\n\t\n\trepne\tscasb\t\t; look for a match\n\tjne\tshort ??searchdone\t; if we don't find one we're done\n\n\tmov\tebx,[count]\n\tmov\tah,[esi+ebx-1]\n\tcmp\tah,[edi+ebx-2]\n\n\tjne\t??oploop\n\n\tmov\tedx,esi\t\t; save this spot for the next search\n\tmov\tebx,edi\t\t; save this spot for the length calc\n\tdec\tedi\t\t; back up one for compare\n\tmov\tecx,[end_of_data]\t\t; get the end of data\n\tsub\tecx,esi\t\t; sub current source for max len\n\t\n\trepe\tcmpsb\t\t; see how many bytes match\n\n; start of change MH 9-24-91\n\tjne\tshort ??notend\t; if found mismatch then di - bx = match count\n\n\tinc\tedi\t\t; else cx = 0 and di + 1 - bx = match count\n\t\n??notend:\n; end of change MH 9-24-91\n\n\tmov\tesi,edx\t\t; restore si\n\tmov\teax,edi\t\t; get the dest\n\tsub\teax,ebx\t\t; sub the start for total bytes that match\n\tmov\tedi,ebx\t\t; restore dest\n\tcmp\teax,[count]\t; see if its better than before\n\tjb\t??searchloop\t; if not keep looking\n\t\n\tmov\t[count],eax\t; if so keep the count\n\tdec\tebx\t\t; back it up for the actual match offset\n\tmov\t[matchoff],ebx ; save the offset for later\n\tjmp\t??searchloop\t; loop until we searched it all\n\t\n??searchdone:\n\t\n\tmov\tecx,[count]\t; get the count of the longest run\n\tmov\tedi,[ndest]\t; get the offset of our compressed data\n\tcmp\tecx,2\t\t; see if its not enough run to matter\n\tjbe\tshort ??lenin\t\t; if its 0,1, or 2 its too small\n\t\n\tcmp\tecx,10\t\t; if not, see if it would fit in a short\n\tja\tshort ??medrun\t; if not, see if its a medium run\n\t\n\tmov\teax,esi\t\t; if its short get the current address\n\tsub\teax,[matchoff] ; sub the offset of the match\n\tcmp\teax,0FFFh\t; if its less than 12 bits its a short\n\tja\tshort ??medrun\t; if its not, its a medium\n\t\n??shortrun:\n\tsub\tebx,ebx\n\tmov\tbl,cl\t\t; get the length (3-10)\n\tsub\tbl,3\t\t; sub 3 for a 3 bit number 0-7\n\tshl\tbl,4\t\t; shift it left 4\n\tadd\tah,bl\t\t; add in the length for the high nibble\n\txchg\tah,al\t\t; reverse the bytes for a word store\n\tjmp\tshort ??srunnxt\t; do the run fixup code\n\n??medrun:\n\tcmp\tecx,64\t\t; see if its a short run\n\tja\tshort ??longrun\t; if not, oh well at least its long\n\t\n\tsub\tcl,3\t\t; back down 3 to keep it in 6 bits\n\tor\tcl,0C0h\t\t; the highest bits are always on\n\tmov\tal,cl\t\t; put it in al for the stosb\n\tstosb\t\t\t; store it\n\tjmp\tshort ??medrunnxt ; do the run fixup code\n\n??lenin:\n\tcmp\t[DWORD PTR inlen],0\t; is it doing a length?\n\tjnz\tshort ??len\t; if so, skip code\n\t\n??lenin1:\n\tmov\t[lenoff],edi\t; save the length code offset\n\tmov\tal,80h\t\t; set the length to 0\n\tstosb\t\t\t; save it\n\t\n??len:\n\tmov\tebx,[lenoff]\t; get the offset of the length code\n\tcmp\t[BYTE PTR ebx],0BFh\t; see if its maxed out\n\tje\t??lenin1\t; if so put out a new len code\n\t\n??stolen:\n\tinc\t[BYTE PTR ebx] ; inc the count code\n\tlodsb\t\t\t; get the byte\n\tstosb\t\t\t; store it\n\tmov\t[DWORD PTR inlen],1\t; we are now in a length so save it\n\tjmp\tshort ??nxt\t; do the next code\n\t\n??longrun:\n\tmov\tal,0ffh\t\t; its a long so set a code of FF\n\tstosb\t\t\t; store it\n\t\n\tmov\teax,[count]\t; send out the count\n\tstosw\t\t\t; store it\n??medrunnxt:\n\tmov\teax,[matchoff] ; get the offset\n\tsub\teax,[a1stsrc]\t; make it relative tot he start of data\n??srunnxt:\n\tstosw\t\t\t; store it\n; this code common to all runs\n\tadd\tesi,[count]\t; add in the length of the run to the source\n\tmov\t[DWORD PTR inlen],0\t; set the in leght flag to false\n\t\n;=======================================================================\t\n\n??nxt:\n\tcmp\tesi,[end_of_data]\t\t; see if we did the whole pic\n\tjae\tshort ??out\t\t; if so, cool! were done\n\t\n\tjmp\t??loop\n\t\n??out:\n\tmov\tax,080h\t\t; remember to send an end of data code\n\tstosb\t\t\t; store it\n\tmov\teax,edi\t\t; get the last compressed address\n\tsub\teax,[a1stdest]\t; sub the first for the compressed size\n\n\n\tret\n\nENDP\tLCW_Compress\n\n\nEND\n\u001a"
  },
  {
    "path": "WWFLAT32/IFF/LCWUNCMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/misc/rcs/lcwuncmp.asm 1.1 1994/04/11 15:31:21 jeff_wilson Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library routine                          *\n;*                                                                         *\n;*                    File Name : UNCOMP.ASM                               *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : 20 August, 1990   [CY]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length);\t\t   *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL            LCW_Uncompress          :NEAR\n\nCODESEG\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length);\n;\n; ----------------------------------------------------------------\n\n\n\nPROC\tLCW_Uncompress C near \n\n\tUSES ebx,ecx,edx,edi,esi\n\t\n\tARG\tsource:DWORD \t   \n\tARG\tdest:DWORD\n\tARG\tlength:DWORD\n;LOCALS\n\tLOCAL a1stdest:DWORD\n\tLOCAL maxlen:DWORD\n\tLOCAL lastbyte:DWORD\n\tLOCAL lastcom:DWORD\n\tLOCAL lastcom1:DWORD\n\n\n\tmov\tedi,[dest]\n\tmov\tesi,[source]\n\tmov\tedx,[length]\n\n;\n;\n; uncompress data to the following codes in the format b = byte, w = word\n; n = byte code pulled from compressed data\n;   Bit field of n\t\tcommand\t\tdescription\n; n=0xxxyyyy,yyyyyyyy\t\tshort run\tback y bytes and run x+3\n; n=10xxxxxx,n1,n2,...,nx+1\tmed length\tcopy the next x+1 bytes\n; n=11xxxxxx,w1\t\t\tmed run\t\trun x+3 bytes from offset w1\n; n=11111111,w1,w2\t\tlong copy\tcopy w1 bytes from offset w2\n; n=11111110,w1,b1\t\tlong run\trun byte b1 for w1 bytes\n; n=10000000\t\t\tend\t\tend of data reached\n;\n\n\tmov\t[a1stdest],edi\n\tadd\tedx,edi\n\tmov\t[lastbyte],edx\n\tcld\t\t\t; make sure all lod and sto are forward\n\tmov\tebx,esi\t\t; save the source offset\n\n??loop:\n\tmov\teax,[lastbyte]\n\tsub\teax,edi\t\t; get the remaining byte to uncomp\n\tjz\tshort ??out\t\t; were done\n\t\n\tmov\t[maxlen],eax\t; save for string commands\n\tmov\tesi,ebx\t\t; mov in the source index\n\n\tsub\teax,eax\n\tlodsb\n\tor\tal,al\t\t; see if its a short run\n\tjs\tshort ??notshort\n\t\n\tmov\tah,al\t\t; put rel offset high nibble in ah\n\tand\tah,0Fh\t\t; only 4 bits count\n\t\n\tsub\tecx,ecx\n\tmov\tcl,al\t\t; put count nibble in ch\n\tshr\tcl,4\t\t; get run -3\n\tadd\tecx,3\t\t; get actual run length\n\t\n\tcmp\tecx,[maxlen]\t; is it too big to fit?\n\tjbe\tshort ??rsok\t\t; if not, its ok\n\t\n\tmov\tecx,[maxlen]\t; if so, max it out so it dosen't overrun\n\n??rsok:\n\tlodsb\t\t\t; get rel offset low byte\n\tmov\tebx,esi\t\t; save the source offset\n\tmov\tesi,edi\t\t; get the current dest\n\tsub\tesi,eax\t\t; get relative offset\n\t\n\trep movsb\n\n\tjmp\t??loop\n\n??notshort:\n\ttest\tal,40h\t\t; is it a length?\n\tjne\tshort ??notlength\t; if not it could be med or long run\n\t\n\tcmp\tal,80h\t\t; is it the end?\n\tje\tshort ??out\t\t; if so its over\n\t\n\tmov\tcl,al\t\t; put the byte in count register\n\tand\tecx,3Fh\t\t; and off the extra bits\n\t\n\tcmp\tecx,[maxlen]\t; is it too big to fit?\n\tjbe\tshort ??lenok\t\t; if not, its ok\n\t\n\tmov\tecx,[maxlen]\t; if so, max it out so it dosen't overrun\n\n??lenok:\n\trep movsb\n\n\tmov\tebx,esi\t\t; save the source offset\n\tjmp\t??loop\n\n??out:\n      \tmov\teax,edi\n\tsub\teax,[a1stdest]\n\tjmp\tshort ??exit\n\n??notlength:\n\tmov\tcl,al\t\t; get the entire code\n\tand\tecx,3Fh\t\t; and off all but the size -3\n\tadd\tecx,3\t\t; add 3 for byte count\n\t\n\tcmp\tal,0FEh\n\tjne\tshort ??notrunlength\n\t\n\tsub\teax,eax\n\tlodsw\n\t\n\tmov\tecx,eax\n\t\n\tsub\teax,eax\n\tlodsb\n\t\n\tmov\tebx,esi\t\t; save the source offset\n\tcmp\tecx,[maxlen]\t; is it too big to fit?\n\tjbe\tshort ??runlenok\t\t; if not, its ok\n\t\n\tmov\tecx,[maxlen]\t; if so, max it out so it dosen't overrun\n\n??runlenok:\n\trep stosb\n\n\tjmp\t??loop\n\n??notrunlength:\n\tcmp\tal,0FFh\t\t; is it a long run?\n\tjne\tshort ??notlong\t; if not use the code as the size\n\t\n\tsub\teax,eax\n\tlodsw\t\t\t; if so, get the size\n\tmov\tecx,eax\t\t; put int the count byte\n\n??notlong:\n\tlodsw\t\t\t; get the rel index\n\tmov\tebx,esi\t\t; save the source offset\n\tadd\teax,[a1stdest]\t; add in the first index\n\tmov\tesi,eax\t\t; use this as a source\n\tcmp\tecx,[maxlen]\t; is it too big to fit?\n\tjbe\tshort ??runok\t\t; if not, its ok\n\t\n\tmov\tecx,[maxlen]\t; if so, max it out so it dosen't overrun\n\n??runok:\n\trep movsb\n\n\tjmp\t??loop\n\n??exit:\n\tmov\teax,edi\n\tmov\tebx,[dest]\n\tsub\teax,ebx\n\t\n\tret\n\nENDP\tLCW_Uncompress\n\n;***********************************************************\n\n\n\tEND\n        \n\u001a"
  },
  {
    "path": "WWFLAT32/IFF/LOAD.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/wwlib32/file/rcs/load.cpp 1.4 1994/04/22 12:42:21 scott_bowen Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : LOAD.C                                   *\n *                                                                         *\n *                   Programmer : Christopher Yates                        *\n *                                                                         *\n *                  Last Update : September 17, 1993   [JLB]               *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Load_Uncompress -- Load and uncompress the given file.                *\n *   Uncompress_Data -- Uncompress standard CPS buffer.                    *\n *   Load_Data -- Loads a data file from disk.                             *\n *   Load_Alloc_Data -- Loads and allocates buffer for a file.             *\n *   Write_Data -- Writes a block of data as a file to disk.               *\n *   Uncompress_Data -- Uncompresses data from one buffer to another.      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"file.h\"\n#include \"iff.h\"\n#include <misc.h>\n#include <dos.h>\n#include <wwmem.h>\n\n\n\n#if(LZW_SUPPORTED)\n\n/* These are our local pointer and size variables for the LZW table.  They\n   are set through the Set_Uncomp_Buffer routine. */\n\nPRIVATE int  LZW_Table      = 0;\t\t\t/* No current paragraph */\nPRIVATE unsigned int LZW_Table_Size = 0;\t\t\t/* No current size */\n\n#endif\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * LOAD_DATA -- Loads a data file from disk.                               *\n *                                                                         *\n *    This routine will load a data file from disk.  It does no translation*\n *    on the data.                                                         *\n *                                                                         *\n * INPUT:   name  -- Pointer to ASCII filename of the data file.           *\n *                                                                         *\n *          ptr   -- Buffer to load the data file into.                    *\n *                                                                         *\n *          size  -- Maximum size of the buffer (in bytes).                *\n *                                                                         *\n * OUTPUT:  Returns with the number of bytes read.                         *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/24/1991 JLB : Created.                                             *\n *=========================================================================*/\nunsigned long cdecl Load_Data(char const *name, VOID *ptr, unsigned long size)\n{\n\tint fd;\n\n\tfd = Open_File(name, READ);\n\tsize = Read_File(fd, ptr, size);\n\tClose_File(fd);\n\treturn(size);\n}\n\n\n/***************************************************************************\n * WRITE_DATA -- Writes a block of data as a file to disk.                 *\n *                                                                         *\n *    This routine will write a block of data as a file to the disk.  It   *\n *    is the compliment of Load_Data.                                      *\n *                                                                         *\n * INPUT:   name     -- Name of the file to create.                        *\n *                                                                         *\n *          ptr      -- Pointer to the block of data to write.             *\n *                                                                         *\n *          size     -- Size of the data block to be written.              *\n *                                                                         *\n * OUTPUT:  Returns with the number of bytes actually written.             *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/05/1992 JLB : Created.                                             *\n *=========================================================================*/\nunsigned long cdecl Write_Data(char const *name, VOID *ptr, unsigned long size)\n{\n\tint fd;\n\n\tfd = Open_File(name, WRITE);\n\tsize = Write_File(fd, ptr, size);\n\tClose_File(fd);\n\treturn(size);\n}\n\n\n/***************************************************************************\n * LOAD_ALLOC_DATA -- Loads and allocates buffer for a file.               *\n *                                                                         *\n *    The routine will allocate a buffer and load the specified file into  *\n *    it.  The kind of memory used for the buffer is determined by the     *\n *    memory allocation flags passed in.                                   *\n *                                                                         *\n * INPUT:   name  -- Name of the file to load.                             *\n *                                                                         *\n *          flags -- Memory allocation flags to use when allocating.       *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the buffer that contains the file's  *\n *          data.                                                          *\n *                                                                         *\n * WARNINGS:   A memory error could occur if regular memory flags are      *\n *             specified.  If XMS memory is specified, then this routine   *\n *             could likely return NULL.                                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/28/1992 JLB : Created.                                             *\n *=========================================================================*/\nVOID * cdecl Load_Alloc_Data(char const *name, MemoryFlagType flags)\n{\n\tint\tfd;\t\t// Working file handle.\n\tunsigned long\tsize;\t\t// Size of the file to load.\n\tVOID\t*buffer;\t// Buffer to hold the file.\n\n\tfd = Open_File(name, READ);\n\tsize = File_Size(fd);\n\tbuffer = Alloc(size, flags);\n\tif (buffer) {\n\t\tRead_File(fd, buffer, size);\n\t}\n\tClose_File(fd);\n\treturn(buffer);\n}\n\n\n/***************************************************************************\n * LOAD_UNCOMPRESS -- Load and uncompress the given file.                  *\n *                                                                         *\n * INPUT:      BYTE *\t\t\t\t\t- file name to uncompress \t\t\t\t\t*\n *\t\t\t\t\tGraphicBufferClass&\t- to load the source data into\t\t\t*\n *\t\t\t\t\tGraphicBufferClass&\t- for the picture\t\t\t\t\t\t\t\t*\n *             VOID *\t\t\t\t\t- ptr for header uncompressed data     *\n *                                                                         *\n * OUTPUT:     unsigned long size of uncompressed data                             *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/28/1991  CY : Created.                                             *\n *   06/26/1991 JLB : Handles load & uncompress to same buffer.            *\n *=========================================================================*/\nunsigned long cdecl Load_Uncompress(char const *file, BufferClass& uncomp_buff, BufferClass& dest_buff, VOID *reserved_data)\n{\n\tint\tfd;\t\t\t\t// Source file handle.\n\tunsigned int\tisize;\t\t\t// Size of the file.\n\tunsigned int\tskipsize;\t\t// Size of the skip data bytes.\n\tVOID\t*uncomp_ptr;\t//\tSource buffer pointer.\n\tchar\t*newuncomp_ptr;\t// Adjusted source pointer.\n\n\n\tuncomp_ptr = uncomp_buff.Get_Buffer();\t\t// get a pointer to buffer\n\n\t/*======================================================================*/\n\t/* Read the file into the uncompression buffer.\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\n\tfd = Open_File(file, READ);\t\t\t\t\t// Open up the file to read from\n\tRead_File(fd, (char *) &isize,\t2L);\t\t// Read the file size\n\tRead_File(fd, uncomp_ptr, \t\t\t8L);\t\t// Read the header bytes in.\n\tisize -= 8; \t\t\t\t\t\t\t\t\t\t// Remaining data in file.\n\n\t/*======================================================================*/\n\t/* Check for and read in the skip data block.\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\n\tskipsize = *(((int*)uncomp_ptr) + 3);\n\n\tif (reserved_data && skipsize) {\n\t\tRead_File(fd, reserved_data, (unsigned long) skipsize);\n\t} else {\n\t\tSeek_File(fd, skipsize, SEEK_CUR);\n\t}\n\n\t*( ((int*)uncomp_ptr+3) )\t = 0;\t\t\t\t// K/O any skip value.\n\tisize \t\t\t\t\t\t\t-= skipsize;\n\n\t/*======================================================================*/\n\t/*\tIf the source and dest buffer are the same, we adjust the pointer so */\n\t/* that the compressed data is loaded into the end of the buffer.  In \t*/\n\t/* this way the uncompress code can write to the same buffer.\t\t\t\t*/\n\t/*======================================================================*/\n\tnewuncomp_ptr = (char *)Add_Long_To_Pointer(uncomp_buff.Get_Buffer(), uncomp_buff.Get_Size() - (isize+8L));\n\n\t/*======================================================================*/\n\t/*\tDuplicate the header bytes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tMem_Copy(uncomp_ptr,newuncomp_ptr,8);\n\n\t/*======================================================================*/\n\t/*\tRead in the main compressed part of the file.\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tRead_File(fd, newuncomp_ptr + 8, (unsigned long)isize);\n\tClose_File(fd);\n\n\t/*======================================================================*/\n\t/* Uncompress the file into the destination buffer (which may very well\t*/\n\t/*\t\tbe the source buffer).\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\treturn(Uncompress_Data(newuncomp_ptr, dest_buff.Get_Buffer()));\n}\n#if(0)\n/***************************************************************************\n * LOAD_UNCOMPRESS -- Load and uncompress the given file.                  *\n *                                                                         *\n * INPUT:      BYTE *file name to uncompress, BuffType uncomp_buff to load *\n *             the source data into, BuffType dest_buff for the picture,   *\n *             VOID *reserved_data pointer for header uncompressed data    *\n *                                                                         *\n * OUTPUT:     unsigned long size of uncompressed data                             *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/28/1991  CY : Created.                                             *\n *   06/26/1991 JLB : Handles load & uncompress to same buffer.            *\n *=========================================================================*/\nunsigned long cdecl Load_Uncompress(char const *file, BuffType uncomp_buff, BuffType dest_buff, VOID *reserved_data)\n{\n\tint\tfd;\t\t\t\t// Source file handle.\n\tunsigned int\tisize;\t\t\t// Size of the file.\n\tunsigned int\tskipsize;\t\t// Size of the skip data bytes.\n\tVOID\t*uncomp_ptr;\t//\tSource buffer pointer.\n\tchar\t*newuncomp_ptr;\t// Adjusted source pointer.\n\n\n\tuncomp_ptr = Get_Buff(uncomp_buff);\t\t/* Get pointer to uncomp buffer */\n\n\t/* Read the file into the uncomp_buff */\n\n\tfd = Open_File(file, READ);\n\tRead_File(fd, (char *) &isize, 2L);\t\t\t\t/* Read the file size \t\t*/\n\t#if(AMIGA)\n\t\tisize = Reverse_WORD(isize);\n\t#endif\n\n\tRead_File(fd, uncomp_ptr, 8L);\t\t// Read the header bytes in.\n\tisize -= 8; \t\t\t\t\t\t\t\t// Remaining data in file.\n\n\t/*\n\t**\tCheck for and read in the skip data block.\n\t*/\n\n\tskipsize = *(((int*)uncomp_ptr) + 3);\n\t#if(AMIGA)\n\t\tskipsize = Reverse_WORD(skipsize);\n\t#endif\n\n\tif (reserved_data && skipsize) {\n\t\tRead_File(fd, reserved_data, (unsigned long) skipsize);\n\t} else {\n\t\tSeek_File(fd, skipsize, SEEK_CUR);\n\t}\n\t*( ((int*)uncomp_ptr+3) ) = 0;\t\t// K/O any skip value.\n\tisize -= skipsize;\n\n\t/*\n\t**\tIf the source and dest buffer are the same, we\n\t**\tadjust the pointer so that the compressed data is\n\t**\tloaded into the end of the buffer.  In this way the\n\t**\tuncompress code can write to the same buffer.\n\t*/\n\t#if(IBM)\n\t\tnewuncomp_ptr = (char *)Add_Long_To_Pointer(Get_Buff(uncomp_buff), PageArraySize[uncomp_buff] - (isize+8L));\n\t\t//newuncomp_ptr = (char*)MK_FP(PageArray[uncomp_buff],0);\n\t\t//newuncomp_ptr += (unsigned int)(PageArraySize[uncomp_buff] - (isize+8));\n\t\t//newuncomp_ptr = Normalize_Pointer(newuncomp_ptr);\n\t\t//newuncomp_ptr = MK_FP(FP_SEG(newuncomp_ptr),0);\n\t#else\n\t\tnewuncomp_ptr = Get_Buff(uncomp_buff);\n\t\tnewuncomp_ptr += PageArraySize[uncomp_buff] - ((isize+10) & 0xFFFE);\n\t#endif\n\n\t/*\n\t**\tDuplicate the header bytes.\n\t*/\n\tMem_Copy(uncomp_ptr,newuncomp_ptr,8);\n\n\t/*\n\t**\tRead in the main compressed part of the file.\n\t*/\n\tRead_File(fd, newuncomp_ptr + 8, (unsigned long)isize);\n\tClose_File(fd);\n\n\treturn(Uncompress_Data(newuncomp_ptr, Get_Buff(dest_buff)));\n}\n\n#endif\n/***************************************************************************\n * Uncompress_Data -- Uncompresses data from one buffer to another.        *\n *                                                                         *\n *    This routine takes data from a compressed file (sans the first two   *\n *    size bytes) and uncompresses it to a destination buffer.  The source *\n *    data MUST have the CompHeaderType at its start.                      *\n *                                                                         *\n * INPUT:   src   -- Source compressed data pointer.                       *\n *                                                                         *\n *          dst   -- Destination (paragraph aligned) pointer.              *\n *                                                                         *\n * OUTPUT:  Returns with the size of the uncompressed data.                *\n *                                                                         *\n * WARNINGS:   If LCW compression is used, the destination buffer must     *\n *             be paragraph aligned.                                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/17/1993 JLB : Created.                                             *\n *=========================================================================*/\nunsigned long cdecl Uncompress_Data(VOID const *src, VOID *dst)\n{\n\tunsigned int\t\t\t\t\tskip;\t\t\t// Number of leading data to skip.\n\tCompressionType\tmethod;\t\t// Compression method used.\n\tunsigned long\t\t\t\t\tuncomp_size=NULL;\n#if(LZW_SUPPORTED)\n\tVOID\t\t\t\t\t*table_buffer;\n#endif\n\n\tif (!src || !dst) return(NULL);\n\n\t/*\n\t**\tInterpret the data block header structure to determine\n\t**\tcompression method, size, and skip data amount.\n\t*/\n\tuncomp_size = ((CompHeaderType*)src)->Size;\n\t#if(AMIGA)\n\t\tuncomp_size = Reverse_LONG(uncomp_size);\n\t#endif\n\tskip = ((CompHeaderType*)src)->Skip;\n\t#if(AMIGA)\n\t\tskip = Reverse_WORD(skip);\n\t#endif\n\tmethod = (CompressionType) ((CompHeaderType*)src)->Method;\n\tsrc = Add_Long_To_Pointer((VOID *)src, (long)sizeof(CompHeaderType) + (long)skip);\n\n\tswitch (method) {\n\n\t\tdefault:\n\t\tcase NOCOMPRESS:\n\t\t\tMem_Copy((VOID *) src, dst, uncomp_size);\n\t\t\tbreak;\n\n\t\tcase HORIZONTAL:\n#if LIB_EXTERNS_RESOLVED\n\t\t\tRLE_Uncompress((VOID *) src, dst, uncomp_size);\n#endif\n\t\t\tbreak;\n\n\t\tcase LCW:\n\t\t\tLCW_Uncompress((VOID *) src, (VOID *) dst, (unsigned long) uncomp_size);\n\t\t\tbreak;\n\n#if(LZW_SUPPORTED)\n\t\tcase LZW12:\n\t\t\t/* If the current buffer isn't big enough, try to\n\t\t\t\tallocate one that is */\n\n\t\t\tif (LZW_Table_Size < LZW12BUFFERSIZE) {\n\t\t\t\ttable_buffer = Alloc((long) LZW12BUFFERSIZE, MEM_PARA);\n\t\t\t\tLZW12_Uncompress(FP_SEG(src), FP_SEG(dst),\n\t\t\t\t\t\t            FP_SEG(table_buffer));\n\t\t\t\tFree(table_buffer);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tLZW12_Uncompress(FP_SEG(src), FP_SEG(dst), LZW_Table);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase LZW14:\n\t\t\t/* If the current buffer isn't big enough, try to\n\t\t\t\tallocate one that is */\n\n\t\t\tif (LZW_Table_Size < LZW14BUFFERSIZE) {\n\t\t\t\ttable_buffer = Alloc((long) LZW14BUFFERSIZE, MEM_PARA);\n\t\t\t\tLZW14_Uncompress(FP_SEG(src), FP_SEG(dst),\n\t\t\t\t\t\t            FP_SEG(table_buffer));\n\t\t\t\tFree(table_buffer);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tLZW14_Uncompress(FP_SEG(src), FP_SEG(dst), LZW_Table);\n\t\t\t}\n\t\t\tbreak;\n#endif\n\t}\n\n\treturn(uncomp_size);\n}                  \n\n\n#if(LZW_SUPPORTED)\n/* ARGSUSED */\n#pragma argsused\nVOID cdecl Set_Uncomp_Buffer(int buffer_segment, unsigned int size_of_buffer)\n{\n\n\tif ((LZW_Table = buffer_segment) == NULL) {\n\t\t/* ERROR HERE */\n\t}\n\tif ((LZW_Table_Size = size_of_buffer) == 0U) {\n\t\t/* ERROR HERE */\n\t}\n}\n#endif\n\u001a\n"
  },
  {
    "path": "WWFLAT32/IFF/LOAD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/wwlib32/file/rcs/load.cpp 1.4 1994/04/22 12:42:21 scott_bowen Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : LOAD.C                                   *\n *                                                                         *\n *                   Programmer : Christopher Yates                        *\n *                                                                         *\n *                  Last Update : September 17, 1993   [JLB]               *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Load_Uncompress -- Load and uncompress the given file.                *\n *   Uncompress_Data -- Uncompress standard CPS buffer.                    *\n *   Load_Data -- Loads a data file from disk.                             *\n *   Load_Alloc_Data -- Loads and allocates buffer for a file.             *\n *   Write_Data -- Writes a block of data as a file to disk.               *\n *   Uncompress_Data -- Uncompresses data from one buffer to another.      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"file.h\"\n#include \"iff.h\"\n#include <misc.h>\n#include <dos.h>\n#include <wwmem.h>\n\n\n\n#if(LZW_SUPPORTED)\n\n/* These are our local pointer and size variables for the LZW table.  They\n   are set through the Set_Uncomp_Buffer routine. */\n\nPRIVATE int  LZW_Table      = 0;\t\t\t/* No current paragraph */\nPRIVATE unsigned int LZW_Table_Size = 0;\t\t\t/* No current size */\n\n#endif\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * LOAD_DATA -- Loads a data file from disk.                               *\n *                                                                         *\n *    This routine will load a data file from disk.  It does no translation*\n *    on the data.                                                         *\n *                                                                         *\n * INPUT:   name  -- Pointer to ASCII filename of the data file.           *\n *                                                                         *\n *          ptr   -- Buffer to load the data file into.                    *\n *                                                                         *\n *          size  -- Maximum size of the buffer (in bytes).                *\n *                                                                         *\n * OUTPUT:  Returns with the number of bytes read.                         *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/24/1991 JLB : Created.                                             *\n *=========================================================================*/\nunsigned long cdecl Load_Data(char const *name, VOID *ptr, unsigned long size)\n{\n\tint fd;\n\n\tfd = Open_File(name, READ);\n\tsize = Read_File(fd, ptr, size);\n\tClose_File(fd);\n\treturn(size);\n}\n\n\n/***************************************************************************\n * WRITE_DATA -- Writes a block of data as a file to disk.                 *\n *                                                                         *\n *    This routine will write a block of data as a file to the disk.  It   *\n *    is the compliment of Load_Data.                                      *\n *                                                                         *\n * INPUT:   name     -- Name of the file to create.                        *\n *                                                                         *\n *          ptr      -- Pointer to the block of data to write.             *\n *                                                                         *\n *          size     -- Size of the data block to be written.              *\n *                                                                         *\n * OUTPUT:  Returns with the number of bytes actually written.             *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/05/1992 JLB : Created.                                             *\n *=========================================================================*/\nunsigned long cdecl Write_Data(char const *name, VOID *ptr, unsigned long size)\n{\n\tint fd;\n\n\tfd = Open_File(name, WRITE);\n\tsize = Write_File(fd, ptr, size);\n\tClose_File(fd);\n\treturn(size);\n}\n\n#ifdef NEVER\n/***************************************************************************\n * LOAD_ALLOC_DATA -- Loads and allocates buffer for a file.               *\n *                                                                         *\n *    The routine will allocate a buffer and load the specified file into  *\n *    it.  The kind of memory used for the buffer is determined by the     *\n *    memory allocation flags passed in.                                   *\n *                                                                         *\n * INPUT:   name  -- Name of the file to load.                             *\n *                                                                         *\n *          flags -- Memory allocation flags to use when allocating.       *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the buffer that contains the file's  *\n *          data.                                                          *\n *                                                                         *\n * WARNINGS:   A memory error could occur if regular memory flags are      *\n *             specified.  If XMS memory is specified, then this routine   *\n *             could likely return NULL.                                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/28/1992 JLB : Created.                                             *\n *=========================================================================*/\nVOID * cdecl Load_Alloc_Data(char const *name, MemoryFlagType flags)\n{\n\tint\tfd;\t\t// Working file handle.\n\tunsigned long\tsize;\t\t// Size of the file to load.\n\tVOID\t*buffer;\t// Buffer to hold the file.\n\n\tfd = Open_File(name, READ);\n\tsize = File_Size(fd);\n\tbuffer = Alloc(size, flags);\n\tif (buffer) {\n\t\tRead_File(fd, buffer, size);\n\t}\n\tClose_File(fd);\n\treturn(buffer);\n}\n#endif\n\n\n/***************************************************************************\n * LOAD_UNCOMPRESS -- Load and uncompress the given file.                  *\n *                                                                         *\n * INPUT:      BYTE *\t\t\t\t\t- file name to uncompress \t\t\t\t\t*\n *\t\t\t\t\tGraphicBufferClass&\t- to load the source data into\t\t\t*\n *\t\t\t\t\tGraphicBufferClass&\t- for the picture\t\t\t\t\t\t\t\t*\n *             VOID *\t\t\t\t\t- ptr for header uncompressed data     *\n *                                                                         *\n * OUTPUT:     unsigned long size of uncompressed data                             *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/28/1991  CY : Created.                                             *\n *   06/26/1991 JLB : Handles load & uncompress to same buffer.            *\n *=========================================================================*/\nunsigned long cdecl Load_Uncompress(char const *file, BufferClass& uncomp_buff, BufferClass& dest_buff, VOID *reserved_data)\n{\n\tint\tfd;\t\t\t\t// Source file handle.\n\tunsigned int\tisize;\t\t\t// Size of the file.\n\tunsigned int\tskipsize;\t\t// Size of the skip data bytes.\n\tVOID\t*uncomp_ptr;\t//\tSource buffer pointer.\n\tchar\t*newuncomp_ptr;\t// Adjusted source pointer.\n\n\n\tuncomp_ptr = uncomp_buff.Get_Buffer();\t\t// get a pointer to buffer\n\n\t/*======================================================================*/\n\t/* Read the file into the uncompression buffer.\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\n\tfd = Open_File(file, READ);\t\t\t\t\t// Open up the file to read from\n\tRead_File(fd, (char *) &isize,\t2L);\t\t// Read the file size\n\tRead_File(fd, uncomp_ptr, \t\t\t8L);\t\t// Read the header bytes in.\n\tisize -= 8; \t\t\t\t\t\t\t\t\t\t// Remaining data in file.\n\n\t/*======================================================================*/\n\t/* Check for and read in the skip data block.\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\n\tskipsize = *(((int*)uncomp_ptr) + 3);\n\n\tif (reserved_data && skipsize) {\n\t\tRead_File(fd, reserved_data, (unsigned long) skipsize);\n\t} else {\n\t\tSeek_File(fd, skipsize, SEEK_CUR);\n\t}\n\n\t*( ((int*)uncomp_ptr+3) )\t = 0;\t\t\t\t// K/O any skip value.\n\tisize \t\t\t\t\t\t\t-= skipsize;\n\n\t/*======================================================================*/\n\t/*\tIf the source and dest buffer are the same, we adjust the pointer so */\n\t/* that the compressed data is loaded into the end of the buffer.  In \t*/\n\t/* this way the uncompress code can write to the same buffer.\t\t\t\t*/\n\t/*======================================================================*/\n\tnewuncomp_ptr = (char *)Add_Long_To_Pointer(uncomp_buff.Get_Buffer(), uncomp_buff.Get_Size() - (isize+8L));\n\n\t/*======================================================================*/\n\t/*\tDuplicate the header bytes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tMem_Copy(uncomp_ptr,newuncomp_ptr,8);\n\n\t/*======================================================================*/\n\t/*\tRead in the main compressed part of the file.\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tRead_File(fd, newuncomp_ptr + 8, (unsigned long)isize);\n\tClose_File(fd);\n\n\t/*======================================================================*/\n\t/* Uncompress the file into the destination buffer (which may very well\t*/\n\t/*\t\tbe the source buffer).\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\treturn(Uncompress_Data(newuncomp_ptr, dest_buff.Get_Buffer()));\n}\n#if(0)\n/***************************************************************************\n * LOAD_UNCOMPRESS -- Load and uncompress the given file.                  *\n *                                                                         *\n * INPUT:      BYTE *file name to uncompress, BuffType uncomp_buff to load *\n *             the source data into, BuffType dest_buff for the picture,   *\n *             VOID *reserved_data pointer for header uncompressed data    *\n *                                                                         *\n * OUTPUT:     unsigned long size of uncompressed data                             *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/28/1991  CY : Created.                                             *\n *   06/26/1991 JLB : Handles load & uncompress to same buffer.            *\n *=========================================================================*/\nunsigned long cdecl Load_Uncompress(char const *file, BuffType uncomp_buff, BuffType dest_buff, VOID *reserved_data)\n{\n\tint\tfd;\t\t\t\t// Source file handle.\n\tunsigned int\tisize;\t\t\t// Size of the file.\n\tunsigned int\tskipsize;\t\t// Size of the skip data bytes.\n\tVOID\t*uncomp_ptr;\t//\tSource buffer pointer.\n\tchar\t*newuncomp_ptr;\t// Adjusted source pointer.\n\n\n\tuncomp_ptr = Get_Buff(uncomp_buff);\t\t/* Get pointer to uncomp buffer */\n\n\t/* Read the file into the uncomp_buff */\n\n\tfd = Open_File(file, READ);\n\tRead_File(fd, (char *) &isize, 2L);\t\t\t\t/* Read the file size \t\t*/\n\t#if(AMIGA)\n\t\tisize = Reverse_WORD(isize);\n\t#endif\n\n\tRead_File(fd, uncomp_ptr, 8L);\t\t// Read the header bytes in.\n\tisize -= 8; \t\t\t\t\t\t\t\t// Remaining data in file.\n\n\t/*\n\t**\tCheck for and read in the skip data block.\n\t*/\n\n\tskipsize = *(((int*)uncomp_ptr) + 3);\n\t#if(AMIGA)\n\t\tskipsize = Reverse_WORD(skipsize);\n\t#endif\n\n\tif (reserved_data && skipsize) {\n\t\tRead_File(fd, reserved_data, (unsigned long) skipsize);\n\t} else {\n\t\tSeek_File(fd, skipsize, SEEK_CUR);\n\t}\n\t*( ((int*)uncomp_ptr+3) ) = 0;\t\t// K/O any skip value.\n\tisize -= skipsize;\n\n\t/*\n\t**\tIf the source and dest buffer are the same, we\n\t**\tadjust the pointer so that the compressed data is\n\t**\tloaded into the end of the buffer.  In this way the\n\t**\tuncompress code can write to the same buffer.\n\t*/\n\t#if(IBM)\n\t\tnewuncomp_ptr = (char *)Add_Long_To_Pointer(Get_Buff(uncomp_buff), PageArraySize[uncomp_buff] - (isize+8L));\n\t\t//newuncomp_ptr = (char*)MK_FP(PageArray[uncomp_buff],0);\n\t\t//newuncomp_ptr += (unsigned int)(PageArraySize[uncomp_buff] - (isize+8));\n\t\t//newuncomp_ptr = Normalize_Pointer(newuncomp_ptr);\n\t\t//newuncomp_ptr = MK_FP(FP_SEG(newuncomp_ptr),0);\n\t#else\n\t\tnewuncomp_ptr = Get_Buff(uncomp_buff);\n\t\tnewuncomp_ptr += PageArraySize[uncomp_buff] - ((isize+10) & 0xFFFE);\n\t#endif\n\n\t/*\n\t**\tDuplicate the header bytes.\n\t*/\n\tMem_Copy(uncomp_ptr,newuncomp_ptr,8);\n\n\t/*\n\t**\tRead in the main compressed part of the file.\n\t*/\n\tRead_File(fd, newuncomp_ptr + 8, (unsigned long)isize);\n\tClose_File(fd);\n\n\treturn(Uncompress_Data(newuncomp_ptr, Get_Buff(dest_buff)));\n}\n\n#endif\n/***************************************************************************\n * Uncompress_Data -- Uncompresses data from one buffer to another.        *\n *                                                                         *\n *    This routine takes data from a compressed file (sans the first two   *\n *    size bytes) and uncompresses it to a destination buffer.  The source *\n *    data MUST have the CompHeaderType at its start.                      *\n *                                                                         *\n * INPUT:   src   -- Source compressed data pointer.                       *\n *                                                                         *\n *          dst   -- Destination (paragraph aligned) pointer.              *\n *                                                                         *\n * OUTPUT:  Returns with the size of the uncompressed data.                *\n *                                                                         *\n * WARNINGS:   If LCW compression is used, the destination buffer must     *\n *             be paragraph aligned.                                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/17/1993 JLB : Created.                                             *\n *=========================================================================*/\nunsigned long cdecl Uncompress_Data(VOID const *src, VOID *dst)\n{\n\tunsigned int\t\t\t\t\tskip;\t\t\t// Number of leading data to skip.\n\tCompressionType\tmethod;\t\t// Compression method used.\n\tunsigned long\t\t\t\t\tuncomp_size=NULL;\n#if(LZW_SUPPORTED)\n\tVOID\t\t\t\t\t*table_buffer;\n#endif\n\n\tif (!src || !dst) return(NULL);\n\n\t/*\n\t**\tInterpret the data block header structure to determine\n\t**\tcompression method, size, and skip data amount.\n\t*/\n\tuncomp_size = ((CompHeaderType*)src)->Size;\n\t#if(AMIGA)\n\t\tuncomp_size = Reverse_LONG(uncomp_size);\n\t#endif\n\tskip = ((CompHeaderType*)src)->Skip;\n\t#if(AMIGA)\n\t\tskip = Reverse_WORD(skip);\n\t#endif\n\tmethod = (CompressionType) ((CompHeaderType*)src)->Method;\n\tsrc = Add_Long_To_Pointer((VOID *)src, (long)sizeof(CompHeaderType) + (long)skip);\n\n\tswitch (method) {\n\n\t\tdefault:\n\t\tcase NOCOMPRESS:\n\t\t\tMem_Copy((VOID *) src, dst, uncomp_size);\n\t\t\tbreak;\n\n\t\tcase HORIZONTAL:\n#if LIB_EXTERNS_RESOLVED\n\t\t\tRLE_Uncompress((VOID *) src, dst, uncomp_size);\n#endif\n\t\t\tbreak;\n\n\t\tcase LCW:\n\t\t\tLCW_Uncompress((VOID *) src, (VOID *) dst, (unsigned long) uncomp_size);\n\t\t\tbreak;\n\n#if(LZW_SUPPORTED)\n\t\tcase LZW12:\n\t\t\t/* If the current buffer isn't big enough, try to\n\t\t\t\tallocate one that is */\n\n\t\t\tif (LZW_Table_Size < LZW12BUFFERSIZE) {\n\t\t\t\ttable_buffer = Alloc((long) LZW12BUFFERSIZE, MEM_PARA);\n\t\t\t\tLZW12_Uncompress(FP_SEG(src), FP_SEG(dst),\n\t\t\t\t\t\t            FP_SEG(table_buffer));\n\t\t\t\tFree(table_buffer);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tLZW12_Uncompress(FP_SEG(src), FP_SEG(dst), LZW_Table);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase LZW14:\n\t\t\t/* If the current buffer isn't big enough, try to\n\t\t\t\tallocate one that is */\n\n\t\t\tif (LZW_Table_Size < LZW14BUFFERSIZE) {\n\t\t\t\ttable_buffer = Alloc((long) LZW14BUFFERSIZE, MEM_PARA);\n\t\t\t\tLZW14_Uncompress(FP_SEG(src), FP_SEG(dst),\n\t\t\t\t\t\t            FP_SEG(table_buffer));\n\t\t\t\tFree(table_buffer);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tLZW14_Uncompress(FP_SEG(src), FP_SEG(dst), LZW_Table);\n\t\t\t}\n\t\t\tbreak;\n#endif\n\t}\n\n\treturn(uncomp_size);\n}                  \n\n\n#if(LZW_SUPPORTED)\n/* ARGSUSED */\n#pragma argsused\nVOID cdecl Set_Uncomp_Buffer(int buffer_segment, unsigned int size_of_buffer)\n{\n\n\tif ((LZW_Table = buffer_segment) == NULL) {\n\t\t/* ERROR HERE */\n\t}\n\tif ((LZW_Table_Size = size_of_buffer) == 0U) {\n\t\t/* ERROR HERE */\n\t}\n}\n#endif\n\u001a\n"
  },
  {
    "path": "WWFLAT32/IFF/LOADPCX.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : IFF                                      *\n *                                                                         *\n *                    File Name : LOADPCX.CPP                              *\n *                                                                         *\n *                   Programmer : Julio R. Jerez                           *\n *                                                                         *\n *                   Start Date : May 2, 1995                              *\n *                                                                         *\n *                  Last Update : May 3, 1995   [JRJ]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * GraphicBufferClass* Read_PCX_File (char* name, void *Buff, long size ); *\n * int Get_PCX_Palette (char * name, void& palette )\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include  <wwlib32.h>\n#include \"filepcx.h\"\n\n/***************************************************************************\n * READ_PCX_FILE -- read a pcx file into a Graphic Buffer                  *\n *                                                                         *\n *\tGraphicBufferClass* Read_PCX_File (char* name, char* palette ,void *Buff, long size );\t*\n *  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT: name is a NULL terminated string of the fromat [xxxx.pcx]        *\n *        palette is optional, if palette != NULL the the color palette of *\n *\t\t\t\t\t the pcx file will be place in the memory block pointed\t   *\n *               by palette.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t Buff is optinal, if Buff == NULL a new memory Buffer\t\t \t\t\t*\n *\t\t\t\t\t will be allocated, otherwise the file will be placed \t\t*\n *\t\t\t\t\t at location pointd by Buffer;\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tSize is the size in bytes of the memory block pointed by Buff\t\t*\n *\t\t\t\t  is also optional;\t\n *                                                                         *\n * OUTPUT: on succes a pointer to a GraphicBufferClass cointaining the     *\n *         pcx file, NULL othewise.                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1995 JRJ : Created.                                             *\n *=========================================================================*/\n\n#define\tPOOL_SIZE 2048 \n#define\tREAD_CHAR()  * file_ptr\t++ ; \\\n\t\t\t\t\t\t\t if ( file_ptr\t>= & pool [ POOL_SIZE ]\t) { \\\n\t\t\t\t\t\t\t\t Read_File ( file_handle, pool , POOL_SIZE ) ; \\\n\t\t\t\t\t\t\t\t file_ptr = pool ; \\\n\t\t\t\t\t\t\t }\n\nGraphicBufferClass* Read_PCX_File (char* name, BYTE* Palette,void *Buff, long Size)\n{\n  unsigned     i , j ;\n  unsigned     rle ;\n  unsigned     color ;\n  unsigned\t\tscan_pos ;\n  unsigned\t\tfile_size ;\n  char\t\t * file_ptr ;\n  int\t\t\t\twidth\t;\n  int\t\t\t\theight ;\n  int \t      file_handle ;\n  char\t\t * buffer ;\n  PCX_HEADER   header ;\n  RGB  \t\t * pal ;\n  char \t\t\tpool [ POOL_SIZE ] ;\n  GraphicBufferClass * pic\t;\n\n  // Open file name\n  file_handle = Open_File ( name , READ ) ;\n  if ( file_handle == ERROR ) return NULL ;\n\n  Read_File ( file_handle, & header , sizeof (PCX_HEADER)) ;\n  if ( header.id != 10 &&  header.version != 5 &&\n       header.pixelsize != 8 ) return NULL ;\n\n  width = header.width - header.x + 1 ;\n  height = header.height - header.y + 1 ;\n\n  if ( Buff ) {\n\t  buffer = ( char * ) Buff;\n\t  i = Size / width;\n\t  height = MIN ( i - 1, height);\n\t  pic = new GraphicBufferClass( Size, width, height, buffer);\n\t  if ( !(pic && pic->Get_Buffer()))return NULL ;\n  } else {\n\t  pic = new GraphicBufferClass(width*(height+4), width, height);\n\t  if ( !(pic && pic->Get_Buffer()))return NULL ;\n  }\n\n  buffer = (char *) pic->Get_Buffer() ;\n  file_ptr = pool ;\n  Read_File ( file_handle, pool , POOL_SIZE ) ;\n\n  if ( header.byte_per_line != width )\n\t for ( scan_pos = j = 0 ; j < height ; j ++, scan_pos += width ) {\n      for ( i = 0 ; i < width ; ) {\n\t\t\t\t rle = READ_CHAR ();\n\t\t\t\t if ( rle > 192 ) {\n\t\t\t\t rle -= 192 ;\n\t\t\t\t color =\tREAD_CHAR (); ;\n\t\t \t\t memset ( buffer + scan_pos + i , color , rle ) ;\n\t\t \t\t i += rle ;\n\t        } else * ( buffer + scan_pos + i ++ ) = rle ;\n\t    }\n\t\t if ( i == width )\n\t\t rle = READ_CHAR () ;\n//\t\t if ( rle > 192 ) rle = READ_CHAR ();\n    }\n\n\n  else for ( i = 0 ; i < width * height ; ) {\n\t\trle = READ_CHAR ();\n\t\tif ( rle > 192 ) {\n\t      rle -= 192 ;\n\t      color = READ_CHAR ();\n\t\t\tmemset ( buffer + i , color , rle ) ;\n\t      i += rle ;\n\t    }\telse * ( buffer + i ++ ) = rle ;\n  }\n\n if ( Palette ) {\n\t  Seek_File ( file_handle , - 256 * sizeof ( RGB ) , SEEK_END ) ;\n\t  Read_File ( file_handle, Palette , 256 * sizeof ( RGB )) ;\n\n\t  pal = ( RGB * ) Palette ;\n\t  for ( i = 0 ; i < 256 ; i ++ ) {\n\t\t pal -> red >>= 2 ;\n\t\t pal -> green >>= 2 ;\n\t\t pal -> blue >>= 2 ;\n\t\t pal ++ ;\n\t  }\n  }\n Close_File (file_handle) ;\n return pic ;\n}\n\n/***************************************************************************\n * READ_PCX_FILE -- read a pcx file into a Graphic Buffer                  *\n *                                                                         *\n *\tGraphicBufferClass* Read_PCX_File (char* name, BufferClass& Buff,\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  char* palette)\t*\t\t\t*\n *  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT: name is a NULL terminated string of the fromat [xxxx.pcx]        *\n *\t\t\t Buff is a pointer to a BufferClass the will hold the pcx file \t*\n *\t\t\t\t\t at location pointd by Buffer;\t\t\t\t\t\t\t\t\t\t*\n *        palette is optional, if palette != NULL the the color palette of *\n *\t\t\t\t\t the pcx file will be place in the memory block pointed\t   *\n *               by palette.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT: on succes a pointer to a GraphicBufferClass cointaining the     *\n *         pcx file, NULL othewise.                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1995 JRJ : Created.                                             *\n *=========================================================================*/\n\nGraphicBufferClass* Read_PCX_File (char* name, BufferClass& Buff,char* palette) \n{\n  return Read_PCX_File(name, palette, (void*)Buff.Get_Buffer(), Buff.Get_Size());\n}\n"
  },
  {
    "path": "WWFLAT32/IFF/LOADPICT.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/wwlib32/file/rcs/loadpict.cpp 1.1 1994/04/20 14:38:08 scott_bowen Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : IFFEXTRA.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : June 11, 1991                            *\n *                                                                         *\n *                  Last Update : April 20, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   ILBM_To_Amiga -- Convert ILBM to bitplane Amiga format.               *\n *   ILBM_To_MCGA -- Converts ILBM picture into MCGA format.               *\n *   PBM_To_Amiga -- Converts a PBM picture into Amiga format.             *\n *   Load_Picture -- Loads a picture file (CPS or LBM format).             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"iff.h\"\n#include \"file.h\"\n#include <video.h>\t// For GraphicMode and MCGA_MODE.\n#include <wwmem.h>\t// For Alloc.\n\n#if(IBM)\n#include <mem.h>\n#endif\n\n// Since we are not currently using AMIGA, this has been put in to \n// give us back some code space.  If it is needed for a utility,\n// this module should be recompiled with that utility and set the\n// define to TRUE.\n#define\tMAKE_AMIGA_ART\tFALSE\n\n/*\n** An IFF picture file can have one of two formats:\n**\tILBM\t- InterLeaved Bit Map\n**\tPBM\t- Packed Bit Map\n*/\ntypedef enum {\n\tFORM_ILBM,\n\tFORM_PBM\n} IFFForm_Type;\n\n/*\n**\tThese are the various chunks that compose an IFF picture file.\n*/\n#define ID_FORM\t\t\tMAKE_ID('F','O','R','M')\n#define ID_ILBM\t\t\tMAKE_ID('I','L','B','M')\n#define ID_PBM \t\t\tMAKE_ID('P','B','M',' ')\n#define ID_CMAP \t\t\tMAKE_ID('C','M','A','P')\n#define ID_BODY \t\t\tMAKE_ID('B','O','D','Y')\n#define ID_BMHD \t\t\tMAKE_ID('B','M','H','D')\n\n\n/*\n**\tThe BMHD (Bit Map HeaDer) chunk in an IFF picture file contains the\n**\tinformation necessary to extract that picture from the BODY chunk.\n**\tIt also indicates the size and depth of the source art.\n*/\ntypedef struct {\n\tUWORD\tW, H;\t\t\t\t// Raster width and height in pixels.\n\tWORD \tX, Y;\t\t\t\t// Pixel postion for this image.\n\tBYTE\tBPlanes;\t\t\t// Number of bitplanes.\n\tUBYTE\tMasking;\t\t\t// Masking control byte.\n\t\t\t\t\t\t\t\t// 0 = No masking.\n\t\t\t\t\t\t\t\t//\t1 = Has a mask.\n\t\t\t\t\t\t\t\t//\t2 = Has transparent color.\n\t\t\t\t\t\t\t\t//\t3 = Lasso.\n\tUBYTE\tCompression;\t// Compression method.\n\t\t\t\t\t\t\t\t// 0 = No compression.\n\t\t\t\t\t\t\t\t// 1 = Byte run compression.\n\tBYTE\tpad;\n\tUWORD\tTransparent;\t// Transparent color number.\n\tUBYTE\tXAspect,\t\t\t// Pixel aspect ratio of source art.\n\t\t\tYAspect;\n\tWORD\tPageWidth, \t\t// Source 'page' size in pixels.\n\t\t\tPageHeight;\n} BitMapHeader_Type;\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE VOID cdecl ILBM_To_MCGA(BufferClass& src, BufferClass& dest, WORD planes);\nPRIVATE VOID cdecl ILBM_To_Amiga(BufferClass& src, BufferClass& dest, WORD planes);\nPRIVATE VOID cdecl PBM_To_Amiga(BufferClass& src, BufferClass& dest, WORD planes);\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n/***************************************************************************\n * ILBM_TO_MCGA -- Converts ILBM picture into MCGA format.                 *\n *                                                                         *\n *    This converts an ILBM picture (typical of DPaint LBM files) and      *\n *    converts it to MCGA mode (byte per pixel).  This function would be   *\n *    used after the body of an ILBM picture is loaded.  Because the       *\n *    number of bitplanes can vary greatly, it is necessary to pass the    *\n *    bitplane count to this function.  The size (320 by 200) of the       *\n *    source picture is presumed.                                          *\n *                                                                         *\n * INPUT:   src   - Buffer number for source ILBM picture.                 *\n *                                                                         *\n *          dest  - Buffer number for place to put MCGA format.            *\n *                                                                         *\n *          planes- The number of bitplanes in the ILBM picture.           *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1991 JLB : Created.                                             *\n *   04/20/1994 SKB : Update to 32 bit library and make private.           *\n *=========================================================================*/\nPRIVATE VOID cdecl ILBM_To_MCGA(BufferClass& src, BufferClass& dest, WORD planes)\n{\n\tBYTE\t*source;\t\t\t// Source pointer.\n\tBYTE\t*destination;\t// Destination pointer.\n\tWORD\tindex,j,i;\t\t// Working index values.\n\tWORD\tbplane;\t\t\t// Bit plane counter.\n\tBYTE\tbytes[8];\t\t// Byte array holding max bitplanes (8).\n\tBYTE\tvalue;\t\t\t// Composed byte(pixel) value.\n\n\tsource = (BYTE *) src.Get_Buffer();\n\tdestination = (BYTE *) dest.Get_Buffer();\n\n\tmemset(bytes, '\\0', 8);\t// Makes sure upper bits will be clear.\n\n\t// Each row is grouped and processed together.\n\n\tfor (index = 0; index < 200 /*bmhd.H*/; index++) {\n\n\t\t// Process each line in groups of 8 bytes.\n\n\t\tfor (j = 0; j < 40 /*(bmhd.W>>3)*/; j++) {\n\n\t\t\t// Get the bitplane bytes.\n\n\t\t\tfor (bplane = 0; bplane < planes /*bmhd.BPlanes*/; bplane++) {\n\t\t\t\tbytes[bplane] = *(source + (bplane * 40 /*(bmhd.W>>3)*/));\n\t\t\t}\n\t\t\tsource++;\n\n\t\t\t// Roll the bits out to create 8 pixels (by bytes).\n\t\t\tfor (i = 0; i < 8; i++) {\n\n\t\t\t\t// 8 bits per byte.\n\t\t\t\tvalue = 0;\n\t\t\t\tfor (bplane = planes - 1/*bmhd.BPlanes-1*/; bplane >= 0; bplane--) {\n\t\t\t\t\tvalue <<= 1;\t\t\t// Make room for next bit.\n\t\t\t\t\tif (bytes[bplane] & 0x80) value |= 1;\t// Set the bit.\n\t\t\t\t\tbytes[bplane] <<= 1;\n\t\t\t\t}\n\t\t\t\t*destination++ = value;\t// Output the pixel byte.\n\t\t\t}\n\t\t}\n\n\t\t// Advance to next scan line.\n\t\tsource += 40 /* (bmhd.W >> 3)*/ * (planes /* bmhd.BPlanes */ - 1);\n\t}\n}\n\n\n/***************************************************************************\n * ILBM_TO_AMIGA -- Convert ILBM to bitplane Amiga format.                 *\n *                                                                         *\n *    This converts an InterLeaved BitMap picture into Amiga bitplane      *\n *    format (8K per bitplane).  The data of an ILBM picture is controlled *\n *    by the number of bitplanes it contains.  The bitplane count is       *\n *    passed into this program.                                            *\n *                                                                         *\n * INPUT:   src   - Buffer number for source ILBM picture data.            *\n *                                                                         *\n *          dest  - Buffer number for destination Amiga picture data.      *\n *                                                                         *\n *          planes- The number of bitplanes in the source ILBM data.       *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   The amount of data placed into the destination buffer is    *\n *             controlled by the number of bitplanes specified.  It is     *\n *             8000 per bitplane.                                          *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/20/1991 JLB : Created.                                             *\n *   04/20/1994 SKB : Update to 32 bit library and make private.           *\n *   04/20/1994 SKB : #if out for main library.  Only used in utils maybe. *\n *=========================================================================*/\n#if MAKE_AMIGA_ART\nPRIVATE VOID cdecl ILBM_To_Amiga(BufferClass& src, BufferClass& dest, WORD planes)\n{\n\tWORD\trow;\t\t\t// Working row counter.\n\tWORD\tbp;\t\t\t// Working bitplane counter.\n\tBYTE\t*srcptr,\t\t// Source buffer pointer.\n\t\t\t*dstptr;\t\t// Destination buffer pointer.\n\n\tsrcptr = (BYTE *) src.Get_Buffer();\t\t// Source buffer pointer.\n\tdstptr = (BYTE *) dest.Get_Buffer();\t// Destination buffer pointer.\n\n\tfor (row = 0; row < 200; row++) {\n\t\tfor (bp = 0; bp < planes; bp++) {\n\t\t\tMem_Copy(srcptr,dstptr+(8000*bp),40);\n\t\t\tsrcptr += 40;\n\t\t}\n\t\tdstptr += 40;\n\t}\n}\n#endif\n\n\n/***************************************************************************\n * PBM_TO_AMIGA -- Converts a PBM picture into Amiga format.               *\n *                                                                         *\n *    This converts a PBM (Packed Bit Map) MCGA picture into Amiga         *\n *    bitplane format.  A PBM picture presumes 8 bitplanes, but this       *\n *    can be controlled by the 'plane' parameter passed in.                *\n *                                                                         *\n * INPUT:   src   - Buffer number for the source PBM data.                 *\n *                                                                         *\n *          dest  - Buffer number to place the Amiga format picture.       *\n *                                                                         *\n *          planes- The number of bitplanes to extract from the PBM source *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   The amount of data placed into the destination buffer is    *\n *             controlled by the number of bitplanes specified.  It is     *\n *             8000 per bitplane.                                          *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/20/1991 JLB : Created.                                             *\n *   04/20/1994 SKB : Update to 32 bit library and make private.           *\n *   04/20/1994 SKB : #if out for main library.  Only used in utils maybe. *\n *=========================================================================*/\n#if MAKE_AMIGA_ART\nPRIVATE VOID cdecl PBM_To_Amiga(BufferClass& src, BufferClass& dest, WORD planes)\n{\n\tWORD\trow,\t\t\t\t// Working row counter.\n\t\t\tcol,\t\t\t\t// Working column (by byte) counter.\n\t\t\tbit;\t\t\t\t// Working bitplane counter.\n\tUBYTE\t*destptr,\t\t// Destination byte pointer.\n\t\t\t*srcptr;\t\t\t// Source byte pointer.\n\tUBYTE\tvalue;\t\t\t// Working input MCGA pixel number.\n\n\n\tdestptr = (UBYTE *) dest.Get_Buffer();\n\tsrcptr = (UBYTE *) src.Get_Buffer();\n\n\tmemset(destptr, 0, 32000);\n\tmemset(destptr+32000, 0, 32000);\n\n\tfor (row = 0; row < 200; row++) {\n\t\t\n\t\tfor (col = 0; col < 320; col++) {\n\t\t\tvalue = *srcptr++;\n\n\t\t\tfor (bit = 0; bit < planes; bit++) {\n\t\t\t\tif (value & (0x01 << bit)) {\n\t\t\t\t\tdestptr[(WORD)((8000L * (LONG)bit) + (col>>3))] |= 0x80 >> (col & 0x07);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tdestptr += 40;\n\t}\n}\n#endif\n\n/***************************************************************************\n * LOAD_PICTURE -- Loads a picture file (CPS or LBM format).               *\n *                                                                         *\n *    This loads a picture file into a page buffer.  The loaded file will  *\n *    be in MCGA or Amiga mode as requested.  Supported source formats     *\n *    are CPS or all forms of IFF dpaint files.                            *\n *                                                                         *\n * INPUT:   filename    - Source filename.  The only files that are        *\n *                        processed as IFF are those files that end with   *\n *                        \".LBM\".                                          *\n *                                                                         *\n *          loadbuf     - Buffer type number for the temporary loading     *\n *                        buffer.  It will be trashed.                     *\n *                                                                         *\n *          destbuf     - Buffer type number for the picture to be placed. *\n *                                                                         *\n *          palette     - Palette buffer pointer.  If this value is NULL   *\n *                        then no palette is loaded.                       *\n *                                                                         *\n *          format      - Desired destination format.                      *\n *                      BM_AMIGA - Destination buffer will contain the     *\n *                                 picture in bitplane format (Amiga).     *\n *                                 The buffer will contain data equal to   *\n *                                 8K times the number of bit planes.      *\n *                                                                         *\n *                      BM_MCGA  - Destination buffer will contain the     *\n *                                 picture in MCGA format (byte per pixel).*\n *                                 The buffer will be 64K in size.         *\n *                                                                         *\n * OUTPUT:  WORD number of bitplanes read into the dest buffer\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1991 JLB : Created.                                             *\n *   05/20/1991 JLB : Handles Amiga and IBM destination formats.           *\n *=========================================================================*/\nWORD cdecl Load_Picture(BYTE const *filename, BufferClass& scratchbuf, BufferClass& destbuf, UBYTE *palette, PicturePlaneType format)\n{\n\tint\tfh;\t\t\t\t\t\t// Input file handle.\n\tlong\tifftype;\t\t\t\t\t// Iff form type.\n\tint\tcounter;\t\t\t\t\t// Count of the bytes decompressed.\n\tint\tvalue;\t\t\t\t\t// Working compression code value.\n\tint\tlen;\t\t\t\t\t\t// WORD sized length value.\n\tint\tindex;\t\t\t\t\t// Working index values.\n\tBitMapHeader_Type\tbmhd;\t\t// BMHD chunk data.\n\tIFFForm_Type\t   formtype; // ILBM, PBM.\n\tchar\t*src;\t\t\t\t\t\t // Working source body pointer.\n\tchar\t*dest;\t\t\t\t\t // Working destination body pointer.\n\n\n\t//len = strlen(filename);\n\t//strupr(filename);\n\n\tfh = Open_File(filename,READ);\n\tif (fh == ERROR) return(FALSE);\n\tRead_File(fh,&ifftype,4L);\n\tClose_File(fh);\n\n\tif (ifftype != ID_FORM) \n\t{\n\t\tUBYTE * ptr = NULL ;\n\n\t\tif ( GraphicMode == MCGA_MODE || \n           ( GraphicMode >= VESA_MIN && GraphicMode <= VESA_MAX ) )\n\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t ptr = palette ;\n\n//\t\treturn((WORD)Load_Uncompress(filename, scratchbuf, destbuf, (GraphicMode == MCGA_MODE) ? palette : NULL) / 8000);\n\t\treturn((WORD)Load_Uncompress(filename, scratchbuf, destbuf,  palette ) / 8000 ) ;\n\t} \n\telse \n\t{\n\n\t\tfh = Open_Iff_File(filename);\t// Opens and checks for IFF form.\n\t\tif (fh == ERROR) return(FALSE);\n\n\t\tRead_File(fh, &ifftype, 4L);\n\t\tif (ifftype == ID_ILBM) {\n\t\t\tformtype = FORM_ILBM;\t\t\t\t// Inter-Leaved Bit Map.\n\t\t} else {\n\t\t\tif (ifftype == ID_PBM) {\n\t\t\t\tformtype = FORM_PBM;\t\t\t// Packed Bit Map.\n\t\t\t} else {\n\t\t\t\treturn FALSE;\t\t\t\t// Not a recognizable picture file.\n\t\t\t}\n\t\t}\n\n\t\t// Load the BMHD chunk.\n\t\tif (Read_Iff_Chunk(fh,ID_BMHD,(BYTE*)&bmhd,sizeof(BitMapHeader_Type))) {\n\n\t\t\t#if(IBM)\n\t\t\t\t// Perform necessary IBM conversions to the data.\n\t\t\t\tbmhd.W = Reverse_WORD(bmhd.W);\n\t\t\t\tbmhd.H = Reverse_WORD(bmhd.H);\n\t\t\t\tbmhd.X = Reverse_WORD(bmhd.X);\n\t\t\t\tbmhd.Y = Reverse_WORD(bmhd.Y);\n\n\t\t\t\t// this is a mistake Xaspect and YAspect are char type\n\t\t\t\t// bmhd.XAspect = Reverse_WORD(bmhd.XAspect);\n\t\t\t\t// bmhd.YAspect = Reverse_WORD(bmhd.YAspect);\n\t\t\t\t  value = bmhd.XAspect\t;\n\t\t\t\t  bmhd.XAspect = bmhd.YAspect ;\n\t\t\t\t  bmhd.YAspect = ( unsigned char ) value ;\n\t\t\t\t  \t\t\t\t\n\t\t\t\tbmhd.PageWidth = Reverse_WORD(bmhd.PageWidth);\n\t\t\t\tbmhd.PageHeight = Reverse_WORD(bmhd.PageHeight);\n\t\t\t#endif\n\n\t\t\tif (bmhd.Masking > 2) return FALSE;\t\t\t// Don't allow brushes.\n\t\t\tif (bmhd.Compression > 1) return FALSE;\t// Unknown compression.\n\n\t\t} else {\n\t\t\treturn FALSE;\t\t\t\t// Unable to read the required BMHD chunk.\n\t\t}\n\n\t\t// Load the palette if asked.\n\t\tif (palette) \n\t\t{\n\t\t\tint\tpbytes ;\t\t\t       \t// Number of CMAP bytes required.\n\t\t\tunsigned char\tcolor;\t\t\t// Palette color value.\n\t\t\tunsigned char *paletteptr;\t\t// Allocated buffer for palette conversions.\n\t\t\tunsigned char *source;\t\t  \t// Scratch source CMAP data pointer.\n\t\t\tunsigned char *dest2;\t\t  \t// Scratch destination palette pointer.\n\n\t\t\t//\tNumber of CMAP bytes that are needed.\n\t\t\tpbytes = (1 << bmhd.BPlanes) * 3;\n\n\t\t\t// Allocate the temporary palette buffer.\n\t\t\tpaletteptr = (UBYTE *)Alloc(pbytes, MEM_CLEAR);\n\t\t\tsource = paletteptr;\n\t\t\tdest2 = palette;\n\n\t\t\t//\tRead in only the bytes that are needed.\n\t\t\tpbytes = (WORD)Read_Iff_Chunk(fh, ID_CMAP, (BYTE *) paletteptr, pbytes);\n\n#if(IBM)\n\t\t\tif ( pbytes && \n              ( ( GraphicMode >= VESA_MIN && GraphicMode <= VESA_MAX ) ||\n\t\t\t         GraphicMode == MCGA_MODE ) ) \n\t\t  {\n#else\n\t\t\tif (pbytes) {\n#endif\n\n\t\t\t\t/*\n\t\t\t\t** CMAP to machine specific palette conversion code.  Conversion\n\t\t\t\t**\tgoes from CMAP three bytes per color register to the machine\n\t\t\t\t**\tspecific form.\n\t\t\t\t*/\n\t\t\t\tswitch(format) {\n\t\t\t\t\tdefault:\n\t\t\t\t\tcase BM_MCGA:\n\t\t\t\t\t\t// Convert CMAP to IBM MCGA palette form.\n\t\t\t\t\t\tfor (index = 0; index < pbytes; index++) {\n\t\t\t\t\t\t\t*dest2++ = *source++ >> 2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n#if MAKE_AMIGA_ART\n\n\t\t\t\t\tcase BM_AMIGA:\n\t\t\t\t\t\t// Convert CMAP to Amiga nibble packed palette form.\n\t\t\t\t\t\tfor (index = 0; index < pbytes; index += 3) {\n\t\t\t\t\t\t\t*dest2++   = *(source++) >> 4;\n\t\t\t\t\t\t\tcolor \t = (*(source++) & 0xf0);\n\t\t\t\t\t\t\tcolor \t+= *(source++) >> 4;\n\t\t\t\t\t\t\t*dest2++\t = color;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n#endif\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tFree(paletteptr);\n\t\t}\n\n\n\t\t//\tLoad in BODY chunk.\n\t\tdest = (BYTE *) scratchbuf.Get_Buffer();\n\t\tsrc  = (BYTE *) destbuf.Get_Buffer();\n\n\t\tif (Read_Iff_Chunk(fh, ID_BODY, src, destbuf.Get_Size())) \n\t\t{\n\t\t\tfor (index = 0; index < (WORD)bmhd.H; index++) \n\t\t\t{\t\n\t\t\t   /* Height of source */\n\t\t\t\t//\tTransfer (possibly uncompress) one row of data.\n\t\t\t\t// PBM or ILBM reader. Bytes per row (all bitplanes).\n\n\t\t\t\tcounter = bmhd.BPlanes * (bmhd.W >> 3);\n\n\t\t\t\t//\tIf there is a mask then there is one more bitplane.\n\t\t\t\tif (bmhd.Masking == 1) \t\n\t\t\t\t\t\t\t\t\t\t\tcounter += bmhd.W >> 3 ;\n\n\t\t\t\tif (bmhd.Compression == 1) \n\t\t\t\t{\t\n\t\t\t\t   // The data is compressed.\n\t\t\t\t\t//\tDecompress one scanline (all bitplanes) at a time.\n\t\t\t\t\twhile (counter) \n\t\t\t\t\t{\n\t\t\t\t\t\tvalue = ( signed char ) *src++; \t\t\t// Decompression code.\n\t\t\t\t\t\tif (value == -128) continue;\t// NOOP code.\n\n\t\t\t\t\t\tif (value >= 0) \n\t\t\t\t\t\t{\t\t\n\t\t\t\t\t\t\t// Copy N+1 bytes.\n\t\t\t\t\t\t\tlen = ((WORD) value) + 1;\n\n\t\t\t\t\t\t\t//\tIgnore the masking bitplane.\n\t\t\t\t\t\t\tif ( bmhd.Masking != 1 || \n\t\t\t\t\t\t\t     (bmhd.Masking==1 && counter > ((WORD)bmhd.W >> 3) ) ) \n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmemcpy(dest, src, len);\n\t\t\t\t\t\t\t\tdest += len;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcounter -= len;\n\t\t\t\t\t\t\tsrc += len;\n\n\t\t\t\t\t\t} \n\t\t\t\t\t\telse \n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Replicate -N+1 bytes.\n\t\t\t\t\t\t\tlen = (-((WORD) value)) + 1;\n\t\t\t\t\t\t\tvalue = *src++;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t//\tIgnore the masking bitplane.\n\t\t\t\t\t\t\tif (bmhd.Masking != 1 || (bmhd.Masking==1 && counter > ((WORD)bmhd.W >> 3))) \n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmemset(dest,value,len);\n\t\t\t\t\t\t\t\tdest += len;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcounter -= len;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} \n\n\t\t\t\telse \n\t\t\t\t{\n\t\t\t\t   // Plain data is just copied.\n\t\t\t\t\tmemcpy(dest,src,counter);\n\t\t\t\t\tdest += counter;\n\t\t\t\t\tsrc += counter;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tPerform necessary conversions to the data in order to reach \n\t\t\t**\tthe desired format.\n\t\t\t*/\n\t\t\tswitch (format) {\n\t\t\t\tdefault:\n\t\t\t\tcase BM_MCGA:\t\t\t// Byte per pixel desired.\n\t\t\t\t\tif (formtype == FORM_ILBM) {\n\t\t\t\t\t\tILBM_To_MCGA(scratchbuf, destbuf, bmhd.BPlanes);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMem_Copy(scratchbuf.Get_Buffer(), destbuf.Get_Buffer(), 64000L);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t\n#if MAKE_AMIGA_ART\n\t\t\t\tcase BM_AMIGA:\t\t\t// Bitplane format desired.\n\t\t\t\t\tif (formtype == FORM_ILBM) {\n\t\t\t\t\t\tILBM_To_Amiga(scratchbuf, destbuf, bmhd.BPlanes);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tPBM_To_Amiga(scratchbuf, destbuf, bmhd.BPlanes);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n#endif\n\t\t\t}\n\t\t}\n\n\t\tClose_Iff_File(fh);\n\t}\n\t\t\t\n\treturn((WORD)bmhd.BPlanes);\t\t\t// Loaded the picture successfully.\n}\n"
  },
  {
    "path": "WWFLAT32/IFF/LOADPICT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/wwlib32/file/rcs/loadpict.cpp 1.1 1994/04/20 14:38:08 scott_bowen Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : IFFEXTRA.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : June 11, 1991                            *\n *                                                                         *\n *                  Last Update : April 20, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   ILBM_To_Amiga -- Convert ILBM to bitplane Amiga format.               *\n *   ILBM_To_MCGA -- Converts ILBM picture into MCGA format.               *\n *   PBM_To_Amiga -- Converts a PBM picture into Amiga format.             *\n *   Load_Picture -- Loads a picture file (CPS or LBM format).             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"iff.h\"\n#include \"file.h\"\n#include <video.h>\t// For GraphicMode and MCGA_MODE.\n#include <wwmem.h>\t// For Alloc.\n\n#if(IBM)\n#include <mem.h>\n#endif\n\n// Since we are not currently using AMIGA, this has been put in to \n// give us back some code space.  If it is needed for a utility,\n// this module should be recompiled with that utility and set the\n// define to TRUE.\n#define\tMAKE_AMIGA_ART\tFALSE\n\n/*\n** An IFF picture file can have one of two formats:\n**\tILBM\t- InterLeaved Bit Map\n**\tPBM\t- Packed Bit Map\n*/\ntypedef enum {\n\tFORM_ILBM,\n\tFORM_PBM\n} IFFForm_Type;\n\n/*\n**\tThese are the various chunks that compose an IFF picture file.\n*/\n#define ID_FORM\t\t\tMAKE_ID('F','O','R','M')\n#define ID_ILBM\t\t\tMAKE_ID('I','L','B','M')\n#define ID_PBM \t\t\tMAKE_ID('P','B','M',' ')\n#define ID_CMAP \t\t\tMAKE_ID('C','M','A','P')\n#define ID_BODY \t\t\tMAKE_ID('B','O','D','Y')\n#define ID_BMHD \t\t\tMAKE_ID('B','M','H','D')\n\n\n/*\n**\tThe BMHD (Bit Map HeaDer) chunk in an IFF picture file contains the\n**\tinformation necessary to extract that picture from the BODY chunk.\n**\tIt also indicates the size and depth of the source art.\n*/\ntypedef struct {\n\tUWORD\tW, H;\t\t\t\t// Raster width and height in pixels.\n\tWORD \tX, Y;\t\t\t\t// Pixel postion for this image.\n\tBYTE\tBPlanes;\t\t\t// Number of bitplanes.\n\tUBYTE\tMasking;\t\t\t// Masking control byte.\n\t\t\t\t\t\t\t\t// 0 = No masking.\n\t\t\t\t\t\t\t\t//\t1 = Has a mask.\n\t\t\t\t\t\t\t\t//\t2 = Has transparent color.\n\t\t\t\t\t\t\t\t//\t3 = Lasso.\n\tUBYTE\tCompression;\t// Compression method.\n\t\t\t\t\t\t\t\t// 0 = No compression.\n\t\t\t\t\t\t\t\t// 1 = Byte run compression.\n\tBYTE\tpad;\n\tUWORD\tTransparent;\t// Transparent color number.\n\tUBYTE\tXAspect,\t\t\t// Pixel aspect ratio of source art.\n\t\t\tYAspect;\n\tWORD\tPageWidth, \t\t// Source 'page' size in pixels.\n\t\t\tPageHeight;\n} BitMapHeader_Type;\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE VOID cdecl ILBM_To_MCGA(BufferClass& src, BufferClass& dest, WORD planes);\nPRIVATE VOID cdecl ILBM_To_Amiga(BufferClass& src, BufferClass& dest, WORD planes);\nPRIVATE VOID cdecl PBM_To_Amiga(BufferClass& src, BufferClass& dest, WORD planes);\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n/***************************************************************************\n * ILBM_TO_MCGA -- Converts ILBM picture into MCGA format.                 *\n *                                                                         *\n *    This converts an ILBM picture (typical of DPaint LBM files) and      *\n *    converts it to MCGA mode (byte per pixel).  This function would be   *\n *    used after the body of an ILBM picture is loaded.  Because the       *\n *    number of bitplanes can vary greatly, it is necessary to pass the    *\n *    bitplane count to this function.  The size (320 by 200) of the       *\n *    source picture is presumed.                                          *\n *                                                                         *\n * INPUT:   src   - Buffer number for source ILBM picture.                 *\n *                                                                         *\n *          dest  - Buffer number for place to put MCGA format.            *\n *                                                                         *\n *          planes- The number of bitplanes in the ILBM picture.           *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1991 JLB : Created.                                             *\n *   04/20/1994 SKB : Update to 32 bit library and make private.           *\n *=========================================================================*/\nPRIVATE VOID cdecl ILBM_To_MCGA(BufferClass& src, BufferClass& dest, WORD planes)\n{\n\tBYTE\t*source;\t\t\t// Source pointer.\n\tBYTE\t*destination;\t// Destination pointer.\n\tWORD\tindex,j,i;\t\t// Working index values.\n\tWORD\tbplane;\t\t\t// Bit plane counter.\n\tBYTE\tbytes[8];\t\t// Byte array holding max bitplanes (8).\n\tBYTE\tvalue;\t\t\t// Composed byte(pixel) value.\n\n\tsource = (BYTE *) src.Get_Buffer();\n\tdestination = (BYTE *) dest.Get_Buffer();\n\n\tmemset(bytes, '\\0', 8);\t// Makes sure upper bits will be clear.\n\n\t// Each row is grouped and processed together.\n\n\tfor (index = 0; index < 200 /*bmhd.H*/; index++) {\n\n\t\t// Process each line in groups of 8 bytes.\n\n\t\tfor (j = 0; j < 40 /*(bmhd.W>>3)*/; j++) {\n\n\t\t\t// Get the bitplane bytes.\n\n\t\t\tfor (bplane = 0; bplane < planes /*bmhd.BPlanes*/; bplane++) {\n\t\t\t\tbytes[bplane] = *(source + (bplane * 40 /*(bmhd.W>>3)*/));\n\t\t\t}\n\t\t\tsource++;\n\n\t\t\t// Roll the bits out to create 8 pixels (by bytes).\n\t\t\tfor (i = 0; i < 8; i++) {\n\n\t\t\t\t// 8 bits per byte.\n\t\t\t\tvalue = 0;\n\t\t\t\tfor (bplane = planes - 1/*bmhd.BPlanes-1*/; bplane >= 0; bplane--) {\n\t\t\t\t\tvalue <<= 1;\t\t\t// Make room for next bit.\n\t\t\t\t\tif (bytes[bplane] & 0x80) value |= 1;\t// Set the bit.\n\t\t\t\t\tbytes[bplane] <<= 1;\n\t\t\t\t}\n\t\t\t\t*destination++ = value;\t// Output the pixel byte.\n\t\t\t}\n\t\t}\n\n\t\t// Advance to next scan line.\n\t\tsource += 40 /* (bmhd.W >> 3)*/ * (planes /* bmhd.BPlanes */ - 1);\n\t}\n}\n\n\n/***************************************************************************\n * ILBM_TO_AMIGA -- Convert ILBM to bitplane Amiga format.                 *\n *                                                                         *\n *    This converts an InterLeaved BitMap picture into Amiga bitplane      *\n *    format (8K per bitplane).  The data of an ILBM picture is controlled *\n *    by the number of bitplanes it contains.  The bitplane count is       *\n *    passed into this program.                                            *\n *                                                                         *\n * INPUT:   src   - Buffer number for source ILBM picture data.            *\n *                                                                         *\n *          dest  - Buffer number for destination Amiga picture data.      *\n *                                                                         *\n *          planes- The number of bitplanes in the source ILBM data.       *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   The amount of data placed into the destination buffer is    *\n *             controlled by the number of bitplanes specified.  It is     *\n *             8000 per bitplane.                                          *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/20/1991 JLB : Created.                                             *\n *   04/20/1994 SKB : Update to 32 bit library and make private.           *\n *   04/20/1994 SKB : #if out for main library.  Only used in utils maybe. *\n *=========================================================================*/\n#if MAKE_AMIGA_ART\nPRIVATE VOID cdecl ILBM_To_Amiga(BufferClass& src, BufferClass& dest, WORD planes)\n{\n\tWORD\trow;\t\t\t// Working row counter.\n\tWORD\tbp;\t\t\t// Working bitplane counter.\n\tBYTE\t*srcptr,\t\t// Source buffer pointer.\n\t\t\t*dstptr;\t\t// Destination buffer pointer.\n\n\tsrcptr = (BYTE *) src.Get_Buffer();\t\t// Source buffer pointer.\n\tdstptr = (BYTE *) dest.Get_Buffer();\t// Destination buffer pointer.\n\n\tfor (row = 0; row < 200; row++) {\n\t\tfor (bp = 0; bp < planes; bp++) {\n\t\t\tMem_Copy(srcptr,dstptr+(8000*bp),40);\n\t\t\tsrcptr += 40;\n\t\t}\n\t\tdstptr += 40;\n\t}\n}\n#endif\n\n\n/***************************************************************************\n * PBM_TO_AMIGA -- Converts a PBM picture into Amiga format.               *\n *                                                                         *\n *    This converts a PBM (Packed Bit Map) MCGA picture into Amiga         *\n *    bitplane format.  A PBM picture presumes 8 bitplanes, but this       *\n *    can be controlled by the 'plane' parameter passed in.                *\n *                                                                         *\n * INPUT:   src   - Buffer number for the source PBM data.                 *\n *                                                                         *\n *          dest  - Buffer number to place the Amiga format picture.       *\n *                                                                         *\n *          planes- The number of bitplanes to extract from the PBM source *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   The amount of data placed into the destination buffer is    *\n *             controlled by the number of bitplanes specified.  It is     *\n *             8000 per bitplane.                                          *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/20/1991 JLB : Created.                                             *\n *   04/20/1994 SKB : Update to 32 bit library and make private.           *\n *   04/20/1994 SKB : #if out for main library.  Only used in utils maybe. *\n *=========================================================================*/\n#if MAKE_AMIGA_ART\nPRIVATE VOID cdecl PBM_To_Amiga(BufferClass& src, BufferClass& dest, WORD planes)\n{\n\tWORD\trow,\t\t\t\t// Working row counter.\n\t\t\tcol,\t\t\t\t// Working column (by byte) counter.\n\t\t\tbit;\t\t\t\t// Working bitplane counter.\n\tUBYTE\t*destptr,\t\t// Destination byte pointer.\n\t\t\t*srcptr;\t\t\t// Source byte pointer.\n\tUBYTE\tvalue;\t\t\t// Working input MCGA pixel number.\n\n\n\tdestptr = (UBYTE *) dest.Get_Buffer();\n\tsrcptr = (UBYTE *) src.Get_Buffer();\n\n\tmemset(destptr, 0, 32000);\n\tmemset(destptr+32000, 0, 32000);\n\n\tfor (row = 0; row < 200; row++) {\n\t\t\n\t\tfor (col = 0; col < 320; col++) {\n\t\t\tvalue = *srcptr++;\n\n\t\t\tfor (bit = 0; bit < planes; bit++) {\n\t\t\t\tif (value & (0x01 << bit)) {\n\t\t\t\t\tdestptr[(WORD)((8000L * (LONG)bit) + (col>>3))] |= 0x80 >> (col & 0x07);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tdestptr += 40;\n\t}\n}\n#endif\n\n\n#ifdef NEVER\n/***************************************************************************\n * LOAD_PICTURE -- Loads a picture file (CPS or LBM format).               *\n *                                                                         *\n *    This loads a picture file into a page buffer.  The loaded file will  *\n *    be in MCGA or Amiga mode as requested.  Supported source formats     *\n *    are CPS or all forms of IFF dpaint files.                            *\n *                                                                         *\n * INPUT:   filename    - Source filename.  The only files that are        *\n *                        processed as IFF are those files that end with   *\n *                        \".LBM\".                                          *\n *                                                                         *\n *          loadbuf     - Buffer type number for the temporary loading     *\n *                        buffer.  It will be trashed.                     *\n *                                                                         *\n *          destbuf     - Buffer type number for the picture to be placed. *\n *                                                                         *\n *          palette     - Palette buffer pointer.  If this value is NULL   *\n *                        then no palette is loaded.                       *\n *                                                                         *\n *          format      - Desired destination format.                      *\n *                      BM_AMIGA - Destination buffer will contain the     *\n *                                 picture in bitplane format (Amiga).     *\n *                                 The buffer will contain data equal to   *\n *                                 8K times the number of bit planes.      *\n *                                                                         *\n *                      BM_MCGA  - Destination buffer will contain the     *\n *                                 picture in MCGA format (byte per pixel).*\n *                                 The buffer will be 64K in size.         *\n *                                                                         *\n * OUTPUT:  WORD number of bitplanes read into the dest buffer\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1991 JLB : Created.                                             *\n *   05/20/1991 JLB : Handles Amiga and IBM destination formats.           *\n *=========================================================================*/\nWORD cdecl Load_Picture(BYTE const *filename, BufferClass& scratchbuf, BufferClass& destbuf, UBYTE *palette, PicturePlaneType format)\n{\n\tint\tfh;\t\t\t\t\t\t// Input file handle.\n\tlong\tifftype;\t\t\t\t\t// Iff form type.\n\tint\tcounter;\t\t\t\t\t// Count of the bytes decompressed.\n\tint\tvalue;\t\t\t\t\t// Working compression code value.\n\tint\tlen;\t\t\t\t\t\t// WORD sized length value.\n\tint\tindex;\t\t\t\t\t// Working index values.\n\tBitMapHeader_Type\tbmhd;\t\t// BMHD chunk data.\n\tIFFForm_Type\t   formtype; // ILBM, PBM.\n\tchar\t*src;\t\t\t\t\t\t // Working source body pointer.\n\tchar\t*dest;\t\t\t\t\t // Working destination body pointer.\n\n\n\t//len = strlen(filename);\n\t//strupr(filename);\n\n\tfh = Open_File(filename,READ);\n\tif (fh == ERROR) return(FALSE);\n\tRead_File(fh,&ifftype,4L);\n\tClose_File(fh);\n\n\tif (ifftype != ID_FORM) \n\t{\n\t\tUBYTE * ptr = NULL ;\n\n\t\tif ( GraphicMode == MCGA_MODE || \n           ( GraphicMode >= VESA_MIN && GraphicMode <= VESA_MAX ) )\n\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t ptr = palette ;\n\n//\t\treturn((WORD)Load_Uncompress(filename, scratchbuf, destbuf, (GraphicMode == MCGA_MODE) ? palette : NULL) / 8000);\n\t\treturn((WORD)Load_Uncompress(filename, scratchbuf, destbuf,  palette ) / 8000 ) ;\n\t} \n\telse \n\t{\n\n\t\tfh = Open_Iff_File(filename);\t// Opens and checks for IFF form.\n\t\tif (fh == ERROR) return(FALSE);\n\n\t\tRead_File(fh, &ifftype, 4L);\n\t\tif (ifftype == ID_ILBM) {\n\t\t\tformtype = FORM_ILBM;\t\t\t\t// Inter-Leaved Bit Map.\n\t\t} else {\n\t\t\tif (ifftype == ID_PBM) {\n\t\t\t\tformtype = FORM_PBM;\t\t\t// Packed Bit Map.\n\t\t\t} else {\n\t\t\t\treturn FALSE;\t\t\t\t// Not a recognizable picture file.\n\t\t\t}\n\t\t}\n\n\t\t// Load the BMHD chunk.\n\t\tif (Read_Iff_Chunk(fh,ID_BMHD,(BYTE*)&bmhd,sizeof(BitMapHeader_Type))) {\n\n\t\t\t#if(IBM)\n\t\t\t\t// Perform necessary IBM conversions to the data.\n\t\t\t\tbmhd.W = Reverse_WORD(bmhd.W);\n\t\t\t\tbmhd.H = Reverse_WORD(bmhd.H);\n\t\t\t\tbmhd.X = Reverse_WORD(bmhd.X);\n\t\t\t\tbmhd.Y = Reverse_WORD(bmhd.Y);\n\n\t\t\t\t// this is a mistake Xaspect and YAspect are char type\n\t\t\t\t// bmhd.XAspect = Reverse_WORD(bmhd.XAspect);\n\t\t\t\t// bmhd.YAspect = Reverse_WORD(bmhd.YAspect);\n\t\t\t\t  value = bmhd.XAspect\t;\n\t\t\t\t  bmhd.XAspect = bmhd.YAspect ;\n\t\t\t\t  bmhd.YAspect = ( unsigned char ) value ;\n\t\t\t\t  \t\t\t\t\n\t\t\t\tbmhd.PageWidth = Reverse_WORD(bmhd.PageWidth);\n\t\t\t\tbmhd.PageHeight = Reverse_WORD(bmhd.PageHeight);\n\t\t\t#endif\n\n\t\t\tif (bmhd.Masking > 2) return FALSE;\t\t\t// Don't allow brushes.\n\t\t\tif (bmhd.Compression > 1) return FALSE;\t// Unknown compression.\n\n\t\t} else {\n\t\t\treturn FALSE;\t\t\t\t// Unable to read the required BMHD chunk.\n\t\t}\n\n\t\t// Load the palette if asked.\n\t\tif (palette) \n\t\t{\n\t\t\tint\tpbytes ;\t\t\t       \t// Number of CMAP bytes required.\n\t\t\tunsigned char\tcolor;\t\t\t// Palette color value.\n\t\t\tunsigned char *paletteptr;\t\t// Allocated buffer for palette conversions.\n\t\t\tunsigned char *source;\t\t  \t// Scratch source CMAP data pointer.\n\t\t\tunsigned char *dest2;\t\t  \t// Scratch destination palette pointer.\n\n\t\t\t//\tNumber of CMAP bytes that are needed.\n\t\t\tpbytes = (1 << bmhd.BPlanes) * 3;\n\n\t\t\t// Allocate the temporary palette buffer.\n\t\t\tpaletteptr = (UBYTE *)Alloc(pbytes, MEM_CLEAR);\n\t\t\tsource = paletteptr;\n\t\t\tdest2 = palette;\n\n\t\t\t//\tRead in only the bytes that are needed.\n\t\t\tpbytes = (WORD)Read_Iff_Chunk(fh, ID_CMAP, (BYTE *) paletteptr, pbytes);\n\n#if(IBM)\n\t\t\tif ( pbytes && \n              ( ( GraphicMode >= VESA_MIN && GraphicMode <= VESA_MAX ) ||\n\t\t\t         GraphicMode == MCGA_MODE ) ) \n\t\t  {\n#else\n\t\t\tif (pbytes) {\n#endif\n\n\t\t\t\t/*\n\t\t\t\t** CMAP to machine specific palette conversion code.  Conversion\n\t\t\t\t**\tgoes from CMAP three bytes per color register to the machine\n\t\t\t\t**\tspecific form.\n\t\t\t\t*/\n\t\t\t\tswitch(format) {\n\t\t\t\t\tdefault:\n\t\t\t\t\tcase BM_MCGA:\n\t\t\t\t\t\t// Convert CMAP to IBM MCGA palette form.\n\t\t\t\t\t\tfor (index = 0; index < pbytes; index++) {\n\t\t\t\t\t\t\t*dest2++ = *source++ >> 2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n#if MAKE_AMIGA_ART\n\n\t\t\t\t\tcase BM_AMIGA:\n\t\t\t\t\t\t// Convert CMAP to Amiga nibble packed palette form.\n\t\t\t\t\t\tfor (index = 0; index < pbytes; index += 3) {\n\t\t\t\t\t\t\t*dest2++   = *(source++) >> 4;\n\t\t\t\t\t\t\tcolor \t = (*(source++) & 0xf0);\n\t\t\t\t\t\t\tcolor \t+= *(source++) >> 4;\n\t\t\t\t\t\t\t*dest2++\t = color;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n#endif\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tFree(paletteptr);\n\t\t}\n\n\n\t\t//\tLoad in BODY chunk.\n\t\tdest = (BYTE *) scratchbuf.Get_Buffer();\n\t\tsrc  = (BYTE *) destbuf.Get_Buffer();\n\n\t\tif (Read_Iff_Chunk(fh, ID_BODY, src, destbuf.Get_Size())) \n\t\t{\n\t\t\tfor (index = 0; index < (WORD)bmhd.H; index++) \n\t\t\t{\t\n\t\t\t   /* Height of source */\n\t\t\t\t//\tTransfer (possibly uncompress) one row of data.\n\t\t\t\t// PBM or ILBM reader. Bytes per row (all bitplanes).\n\n\t\t\t\tcounter = bmhd.BPlanes * (bmhd.W >> 3);\n\n\t\t\t\t//\tIf there is a mask then there is one more bitplane.\n\t\t\t\tif (bmhd.Masking == 1) \t\n\t\t\t\t\t\t\t\t\t\t\tcounter += bmhd.W >> 3 ;\n\n\t\t\t\tif (bmhd.Compression == 1) \n\t\t\t\t{\t\n\t\t\t\t   // The data is compressed.\n\t\t\t\t\t//\tDecompress one scanline (all bitplanes) at a time.\n\t\t\t\t\twhile (counter) \n\t\t\t\t\t{\n\t\t\t\t\t\tvalue = ( signed char ) *src++; \t\t\t// Decompression code.\n\t\t\t\t\t\tif (value == -128) continue;\t// NOOP code.\n\n\t\t\t\t\t\tif (value >= 0) \n\t\t\t\t\t\t{\t\t\n\t\t\t\t\t\t\t// Copy N+1 bytes.\n\t\t\t\t\t\t\tlen = ((WORD) value) + 1;\n\n\t\t\t\t\t\t\t//\tIgnore the masking bitplane.\n\t\t\t\t\t\t\tif ( bmhd.Masking != 1 || \n\t\t\t\t\t\t\t     (bmhd.Masking==1 && counter > ((WORD)bmhd.W >> 3) ) ) \n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmemcpy(dest, src, len);\n\t\t\t\t\t\t\t\tdest += len;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcounter -= len;\n\t\t\t\t\t\t\tsrc += len;\n\n\t\t\t\t\t\t} \n\t\t\t\t\t\telse \n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Replicate -N+1 bytes.\n\t\t\t\t\t\t\tlen = (-((WORD) value)) + 1;\n\t\t\t\t\t\t\tvalue = *src++;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t//\tIgnore the masking bitplane.\n\t\t\t\t\t\t\tif (bmhd.Masking != 1 || (bmhd.Masking==1 && counter > ((WORD)bmhd.W >> 3))) \n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmemset(dest,value,len);\n\t\t\t\t\t\t\t\tdest += len;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcounter -= len;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} \n\n\t\t\t\telse \n\t\t\t\t{\n\t\t\t\t   // Plain data is just copied.\n\t\t\t\t\tmemcpy(dest,src,counter);\n\t\t\t\t\tdest += counter;\n\t\t\t\t\tsrc += counter;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tPerform necessary conversions to the data in order to reach \n\t\t\t**\tthe desired format.\n\t\t\t*/\n\t\t\tswitch (format) {\n\t\t\t\tdefault:\n\t\t\t\tcase BM_MCGA:\t\t\t// Byte per pixel desired.\n\t\t\t\t\tif (formtype == FORM_ILBM) {\n\t\t\t\t\t\tILBM_To_MCGA(scratchbuf, destbuf, bmhd.BPlanes);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMem_Copy(scratchbuf.Get_Buffer(), destbuf.Get_Buffer(), 64000L);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t\n#if MAKE_AMIGA_ART\n\t\t\t\tcase BM_AMIGA:\t\t\t// Bitplane format desired.\n\t\t\t\t\tif (formtype == FORM_ILBM) {\n\t\t\t\t\t\tILBM_To_Amiga(scratchbuf, destbuf, bmhd.BPlanes);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tPBM_To_Amiga(scratchbuf, destbuf, bmhd.BPlanes);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n#endif\n\t\t\t}\n\t\t}\n\n\t\tClose_Iff_File(fh);\n\t}\n\t\t\t\n\treturn((WORD)bmhd.BPlanes);\t\t\t// Loaded the picture successfully.\n}\n#endif\n"
  },
  {
    "path": "WWFLAT32/IFF/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : jan 24, 1995\t                           *\n#*                                                                         *\n#*                  Last Update : \t\t\t                   *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = iff\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tiff.obj \t&\n\tload.obj \t&\n\tloadpict.obj \t&\n\twritelbm.obj \t&\n\tlcwcomp.obj \t&\n\tlcwuncmp.obj \t&\n\tpack2pln.obj \n\n\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WWLIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\srcdEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WWFLAT32/IFF/PACK2PLN.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/file/rcs/pack2pln.asm 1.1 1994/04/22 18:07:46 scott_bowen Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : PACK2PLN.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen\t\t\t   *\n;*                                                                         *\n;*                   Start Date : November 20, 1991                        *\n;*                                                                         *\n;*                  Last Update : April 22, 1994   [SKB]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nLOCALS ??\n\n\n;******************************************************************************\n; External declares so these functions can be called\n;\nGLOBAL  \t\tPack_2_Plane:NEAR\n\n\tCODESEG\n\n;***************************************************************************\n;* PACK_2_PLANE -- packed to planar scanline conversion                    *\n;*                                                                         *\n;* INPUT:  BYTE *buffer (far) -- pointer to planar output buffer           *\n;*         BYTE *pageptr (far) -- pointer to current row in packed page    *\n;*         WORD planebit -- current bit used in plane -- use only low byte *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*         Return result in buffer.                                        *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/20/1991  SB : Created.                                             *\n;*   04/22/1994 SKB : Converted to 32 bit library.                         *\n;*=========================================================================*\n;\t\t\t\t\t\t\t\t\t   *\n;\tThis is the original function that is converted to asm\n;  \n;PRIVATE VOID Pack_2_Plane(UBYTE * buffer, BYTE * pageptr, BYTE planebit)\n;{\n;  WORD currbit=0x80;\t\t// current bit to be written to\n;  WORD pixel;\t  \t\t// current pixel in row used as a counter;\n;\n;  buffer--;\t\t\t// will be incremented at the start\n;  for (currbit = 0, pixel = 0; pixel < 320; pixel++) {\n;    if (!currbit) {\n;      currbit = 0x80;\t\t// reset bit 7\n;      buffer++;\t\t// go to next byte in buffer\n;      *buffer = 0;\t\t// clear byte so we only need to set bits needed\n;    }\n;  if (planebit & *pageptr++)\n;    *buffer |= currbit;\t// set bit in destination if plane was set is source\n;\n;  currbit >>= 1;\t\t// shift destination bit one right\n;  }\n;}\n\nPROC\tPack_2_Plane C NEAR \n\tUSES\tebx,ecx,esi,edi\n \tARG\tbuffer:DWORD\n\tARG\tpage:DWORD\n\tARG\tplanebit:WORD\n\n\n\tmov\tedi,[buffer]\n\tmov\tesi,[page]\n\n\tmov\tax,[planebit]\t\t; move bit set for current plane (planebit) to ax\n\t\t\t\t\t; the low byte will only be used\n\t      \n\tmov\tecx,320d\t      \t; set counter to 320 columns (320x200 picture)\n\tmov\tah,80h\t\t\t; set bit 7 of current_bit \n\tdec\tedi\t\t\t; this will get incremented at the start\n\n??top_loop:\t\t\t\t; while (columns left)\n\tcmp\tah,80h\t\t\t;   if current_bit is bit 7\n\tjnz\tshort ??same_dest\t\t\t\n\t\t\t\t\t;   Then\n\tinc\tedi\t\t\t;     buffer++  increment pointer\n\tmov\t[BYTE PTR edi],0\t;     *buffer = 0 \n\n??same_dest:\t\t\t\t;   EndIf\n\tmov\tbl,al\n\tand\tbl,[esi]\t\t;   if (planebit & *pageptr)\n\tjz\tshort ??no_set_bit\n\n\tor\t[BYTE PTR edi],ah     \t;     Then *buffer |= current_bit\n\n??no_set_bit:\n\tinc\tesi\t\t\t;   pageptr++\tgoto next in source byte\n\tror\tah,1\t\t\t;   rotate current_bit right one\n\tdec\tecx\t\t\t; \n\tjnz\t??top_loop\n\n\tret\n\n\tENDP\tPack_2_Plane\n\n\tEND\n\u001a"
  },
  {
    "path": "WWFLAT32/IFF/WRITELBM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/wwlib32/file/rcs/writelbm.cpp 1.1 1994/04/20 14:38:57 scott_bowen Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Write LBM File                           *\n *                                                                         *\n *                    File Name : writelbm.c                               *\n *                                                                         *\n *                   Programmer : Scott Bowen                              *\n *                                                                         *\n *                   Start Date :  November 18, 1991                       *\n *                                                                         *\n *                  Last Update : November 19, 1991   [SB]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Get_Line -- convert one plane of one row to a packed plane            *\n *   Write_BMHD -- writes out the bit map header (LocalHeader)             *\n *   Write_Body -- writes out compressed data in an LBM file               *\n *   Write_CMAP -- Writes out CMAP (palette) information                   *\n *   Write_LBM_File -- Writes out a file in LBM format                     *\n *   Write_Row -- compresses and writes a row plane to .lbm file           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n// At the end of this file there is an IFF definition for a .LBM file.\n\n#include <wwstd.h>\n#include \"iff.h\"\n#include \"file.h\"\n#include <stdio.h>\n#include <string.h>\n\n\n\t// A BitMapHeader is stored in a BMHD chunk.  This structure MUST be an even size\ntypedef struct {\n    UWORD w, h;\t\t\t\t\t\t\t// raster width & height in pixels \n    UWORD x, y;\t\t\t\t\t\t\t// position for this image\n    UBYTE planes;\t\t\t\t\t\t\t// # source bitplanes \n    UBYTE masking;\t\t\t\t\t\t// masking technique \n    UBYTE compression;\t\t\t\t\t// compression algoithm\n    UBYTE pad1;\t\t\t\t\t\t\t// UNUSED.  For consistency, put 0 here.\n    UWORD transcolor;\t\t\t\t\t// transparent \"color number\"\n    UBYTE xaspect, yaspect;\t\t\t// aspect ratio, a rational number x/y\n    UWORD pagewidth, pageheight;\t\t// source \"page\" size in pixels\n} BitMapHeaderType;\n\n\n// All values in LocalHeader are always the same except planes.  This is set in Write_BMHD\n// the WORD values must be in low-high order for compatibility.\n\nPRIVATE BitMapHeaderType LocalHeader = {\n\t0x4001, 0xc800, 0, 0, 0, 0,\t\t// width, height, x, y, planes, mask\n\t1,   0, 0xFF00, 5, 6, \t\t\t\t// compress, pad1, transcolor, xasptect, yaspect\n\t0x4001,\t0xC800 };\t\t\t\t\t// pagewidth, pageheight\n\n\t\n\t// Used to verify that the write of the header was valid\n#define BM_HEADER_SIZE\t\t(((sizeof(BitMapHeaderType) + 1) & 0xFFFE) + 8L)\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE LONG Write_BMHD(WORD lbmhandle, WORD bitplanes);\nPRIVATE LONG Write_CMAP(WORD lbmhandle, UBYTE * palette, WORD bitplanes);\nPRIVATE LONG Write_BODY(WORD lbmhandle, BufferClass& buff, WORD bitplanes);\nPRIVATE LONG Write_Row(WORD lbmhandle, UBYTE *buffer);\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * WRITE_LBM_FILE -- Writes out a file in LBM format                       *\n *                                                                         *\n * INPUT:  WORD lbmhandle -- lbm file handle already opened by caller      *\n *         BufferClass buff -- buff where MCGA picture is                     *\n *         WORD bitplane -- number of bitplanes to convert to              *\n *         BYTE *palette -- pointer to palette for buff                    *\n *                                                                         *\n * OUTPUT: Returns BOOL -- successfull or not                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/18/1991  SB : Created.                                             *\n *=========================================================================*/\n\nPUBLIC BOOL Write_LBM_File(WORD lbmhandle, BufferClass& buff, WORD bitplanes, UBYTE *palette)\n{\n\tLONG filesize;\n\n\n\tSeek_File(lbmhandle, 0L, SEEK_SET);\t\t\t\t\t\t// goto beginning of file \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\tWrite_File(lbmhandle, \"FORM????ILBM\", 12L);\t\t\t// First 12 bytes of all .lbm files \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// size is unkown so write ????\n\tfilesize = 12L; \t\t\t\t\t\t\t\t\t\t\t\t// 4 bytes for \"ILBM\" \n\n\tfilesize += Write_BMHD(lbmhandle, bitplanes);\t\t// write out BMHD (fixed size)\n\tfilesize += Write_CMAP(lbmhandle, palette, bitplanes);\t// write out CMAP \n\n\t\t// Write out the body, or compressed picture image.  This size will depend\n\t\t// on the compression, but the value passed back is what the compressor\n\t\t// assumed was written to file\n\n\tfilesize += Write_BODY(lbmhandle, buff, bitplanes);\n\n\t\t// Verify that we were able to write out the file without running out of space\n\tif (Seek_File(lbmhandle, 0L, SEEK_END) != filesize) {\n\t\treturn(FALSE);\n\t}\n\n\tSeek_File(lbmhandle, 4L, SEEK_SET);\t\t\t\t\t\t// goto beginning of file \n\tfilesize = Reverse_LONG(filesize - 8L);\t\t\t\t// - 8 because of \"FORM\" + WORD (size)\n\tWrite_File(lbmhandle, (BYTE *) &filesize, 4L);\t\t// patch in filesize \n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * WRITE_BMHD -- writes out the bit map header (LocalHeader)               *\n *                                                                         *\n * INPUT:  WORD lbmhandle -- file handle for lbm file                      *\n *         WORD pitplanes -- number of bitplanes to write out              *\n *                                                                         *\n * OUTPUT: LONG number of bytes hopefully written out to .LBM file         *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/19/1991  SB : Created.                                             *\n *=========================================================================*/\nPRIVATE LONG Write_BMHD(WORD lbmhandle, WORD bitplanes)\n{\n\tLONG size;\n\t\n\tWrite_File(lbmhandle, \"BMHD\", 4L);\t\t\t\t\t// write out chunk title \n\tsize = Reverse_LONG(sizeof(LocalHeader));\t\t\t// write out size of LocalHeader chunk\n\tWrite_File(lbmhandle, (BYTE *) &size, 4L);\n\n\tLocalHeader.planes\t= bitplanes;\t\t\t\t\t// only nonconstant value in LocalHeader\n\n\t\t// Make sure size is even. Return 8 = \"BMHD\" + size of the bitmap header structure\n\n\treturn(Write_File(lbmhandle, (BYTE *) &LocalHeader,\n\t                 (sizeof(LocalHeader) + 1) & 0xFFFE) + 8L);\n}\n\n\n/***************************************************************************\n * WRITE_CMAP -- Writes out CMAP (palette) information                     *\n *                                                                         *\n *                                                                         *\n * INPUT:  WORD lbmhandle -- file handle of lbm file                       *\n *         BYTE * palette -- pointer to paletter information       \t\t\t*\n *         WORD bitplanes -- used to figure out size of palette            *\n *                                                                         *\n * OUTPUT: LONG number of bytes that should have been written out to .LBM. *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/19/1991  SB : Created.                                             *\n *=========================================================================*/\n\nPRIVATE LONG Write_CMAP(WORD lbmhandle, UBYTE * palette, WORD bitplanes)\n{\n\tWORD color, r, g, b, colors;\n\tLONG size;\n\tUBYTE *pal_ptr;\n\tBYTE rgb[3];\n\n\n\tWrite_File(lbmhandle, \"CMAP\", 4L);\t\t\t\t\t\t// write out palette info\n\tcolors = 1 << bitplanes;\t\t\t\t\t\t\t\t\t// colors = 2 to the bitplanes\n\tsize = Reverse_LONG(colors * 3L);\t\t\t\t\t\t// size = colors * 3 guns\n\n \tWrite_File(lbmhandle, (BYTE *) &size, 4L);\n\n\tfor (pal_ptr = palette, color = 0; color < colors; color++) { // for each color\n\n\t\tif ((r = *pal_ptr++) != 0) {\t\t\t// DPaint changes allows 0 - 100 for gun values\t\t\n\t\t\tr = (r << 2) | 0x03;\t\t\t\t\t// this must be converted to 0 - 256 for LBM\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t// so LBM_val = (DP_val * 4) | 3 if DP_val != 0\n\t\tif ((g = *pal_ptr++) != 0) {\t\t\t\n\t\t\tg = (g << 2) | 0x03;\n\t\t}\n\t\tif ((b = *pal_ptr++) != 0) {\n\t\t\tb = (b << 2) | 0x03;\n\t\t}\n\t\trgb[0] = r;\t\t\t\t\t\t\t\t\t// assign gun values to an array to write out\n\t\trgb[1] = g;\n\t\trgb[2] = b;\n\t\t\n\t\tWrite_File(lbmhandle, rgb, 3L);\n\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// size = colors * 3\n\treturn(((colors << 1) + colors) + 8L);\t// total size of CMAP 8 = \"CMAP\" + WORD (size)\n}\n\n\n/***************************************************************************\n * WRITE_BODY -- writes out compressed data in an LBM file                 *\n *                                                                         *\n * INPUT: WORD lbmhandle -- file handle of lbm file                        *\n *                                                                         *\n * OUTPUT: LONG - number of byte written                                   *\n *  \t                                                                     *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/19/1991  SB : Created.                                             *\n *=========================================================================*/\n\nPRIVATE LONG Write_BODY(WORD lbmhandle, BufferClass& buff, WORD bitplanes)\n{\n\tLONG bodysize = 0;\n\tLONG actualsize;\n\tLONG size;\n\tWORD planebit;\n\tWORD line, plane;\n\tUBYTE buffer[40];\n\tUBYTE *buffptr;\n\n\tWrite_File(lbmhandle, \"BODY????\", 8L);\t\t// BODY chunk ID, ???? reserved for chuncksize \n\n\tbuffptr = (UBYTE *) buff.Get_Buffer();\t\t\t\t\t\t// point to beginning of buff\n\n\tfor (line = 0; line < 200; line++) {\n\t\tplanebit = 1;\t\t\t\t\t\t\t\t\t\t\t// start with bit 1 set \n\n\t\tfor (plane = 0; plane < bitplanes; plane++) {\n\t\t\tPack_2_Plane(buffer, buffptr, planebit);\t// convert to planar\n\t\t\tbodysize += Write_Row(lbmhandle, buffer); // write to to the BODY in the LBM\n\n\t\t\tplanebit <<= 1;\t\t\t\t\t\t\t\t\t// set next bit\n\t\t}\n\n\t\tbuffptr += 320;\t\t\t\t\t\t\t\t\t\t// row size is 320\n\t}\n\n\tactualsize = bodysize + (bodysize&0x01);\n\n\tif (actualsize != bodysize) {\n\t\tWrite_File(lbmhandle, buffer, 1);\t\t// Padd the block.\n\t}\n\n\tSeek_File(lbmhandle, -(actualsize + 4L), SEEK_CUR);\t\t// Patch in chunksize\n\tsize = Reverse_LONG(bodysize);\n\tWrite_File(lbmhandle, (BYTE *) &size ,4L);\t\t\t\n\n\treturn(actualsize + 8L);\t\t// total size of BODY,  \"BODY????\" = 8 bytes\n}\n\n/***************************************************************************\n * WRITE_ROW -- compresses and writes a row plane to .lbm file             *\n *                                                                         *\n * INPUT:  WORD lbmhandle -- lbm file handle                               *\n *         UBYTE *buffer -- pointer to buffer to be written out            *\n *                                                                         *\n * OUTPUT: LONG size of chunk that should have been written out            *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/19/1991  SB : Created.                                             *\n *=========================================================================*/\n// this algorithm was taken from WILBM.c written by EA that was in the\n// 1985 yearbook.  This is the compression method that DP.EXE uses.\n// Change only if DP.EXE changes.\n\nPRIVATE LONG Write_Row(WORD lbmhandle, UBYTE *buffer)\n{\n\tWORD i;\n\tWORD chunksize = 0;\n\tWORD dataLength = 40;\t  \t\t\t\t\t// 320 rows / 8 ( 1 plane per row)\n\tUBYTE repCode, current, curr_plus_2;\n\tUBYTE *buffptr;\n\n\twhile (dataLength) {\n\n  \t\t// If at least 2 more bytes and they are equal, then replicate \n\n\t\tif ((dataLength >= 2) && (buffer[0] == buffer[1])) {\n\t\t\tbuffptr = buffer;\n\t\t\tfor (i = 0; (i <= 128) &&  (i < (dataLength - 1)); i++) {\n\t\t\t\tif (*buffptr != buffptr[1]) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbuffptr++;\n\t\t\t}\n\t\t\ti++;\n\t\t\trepCode = -i + 1;\n\t\t\tWrite_File(lbmhandle, &repCode, 1L);\t\t\t// Write count as -count+1\n\t\t\tWrite_File(lbmhandle, buffer,   1L);\t\t\t// Write byte to replicate\n\t\t\tbuffer += i;\n\t\t\tdataLength -= i;\n\t\t\tchunksize  += 2;\n\n\t\t}\n\t\telse { // Copy literally till 3 byte run or two 2 byte runs found \n\n\t\t\tfor (i = 0; (i <= 128) && (i < dataLength); i++) {\n\t\t\t\tcurrent     = buffer[i];\n\t\t\t\tcurr_plus_2 = buffer[i + 2];\n\n\t\t\t\tif (i == dataLength - 1)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (current != buffer[i + 1])\n\t\t\t\t\tcontinue;\n\t\t\t\tif (i == dataLength - 2)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (current == curr_plus_2)\n\t\t\t\t\tbreak;\n\t\t\t\tif (i == dataLength - 3)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (curr_plus_2 == buffer[i + 3])\n\t\t\t\t\t break;\n\t\t\t}\n\t\t\trepCode = i - 1;\n\t\t\tWrite_File(lbmhandle, &repCode, 1L);\t\t\t// Write count as count-1 \n\t\t\tWrite_File(lbmhandle, buffer, (LONG) i);\t\t// Write 'count' bytes\n\t\t\tbuffer += i;\n\t\t\tdataLength -= i;\n\t\t\tchunksize += i + 1;\n\t\t}\n\t}  // end while\n\n\treturn(chunksize);\n}\n\n\n#if(FALSE)\n\nThis is a definition of a DPII .LBM file.\nBelow this definition are differences in DPIIe .LMB files.\n\nCreated by : Scott K. Bowen Nov 18, 1991\n\t\nStart with .LBM to read definition :\n\n.LBM\t\t-> \"FORM\" + FILESIZE + \"ILMB\" + CHUNKS\n\nBITPLANES\t-> (word) // number of bit planes used\nBLUE\t\t\t-> (byte) // blue color gun value\nBMHD \t\t\t-> \"BMHD\" + CHUNKSIZE + CONTEXT\nBODY\t\t\t->\n\nCHUNKS\t\t-> BMHD | BODY | CMAP | DPPV | CRNG | ????\nCHUNKSIZE\t-> (long) // size of chunk not including header or size.\nCMAP\t\t\t-> \"CMAP\" + CHUNKSIZE + PALETTE_INFO\nCOMPRESS_METHOD -> (byte) // compression method used\nCONTEXT\t\t-> WIDTH + HEIGHT + POSX + POSY + #_BITPLANES + MASKING +\n\t\t\t\t   COMPRESS_METHOD + PAD + TRANS_COL + XASPECT + YASPECT +\n\t\t\t\t\tPAGEWIDTH + PAGEHEIGHT\nCRNG\t\t\t-> // we do not use\n\nDPPV\t\t\t-> // we do not use\n\nFILESIZE\t\t-> (long)   //size of file minus (sizeof(FORM) + sizeof(FILESIZE)\n\nGREEN\t\t\t-> (byte) // green color gun value\n\nHEIGHT\t\t-> (word) // of picture\n\nMASKING\t\t-> (byte) // masking type ?\n\nNUM_COLORS\t-> //number of colors used depending on format\n\nPAGE_WIDTH\t-> (word) // width of page\nPAGE_HEIGHT\t-> (word) // height of page\nPALETTE_INFO-> (RED+GREEN+BLUE) @ NUM_COLORS\nPAD \t\t\t-> (byte) // not used.  used as a padding\nPOSX \t\t\t-> (word) // staring position\nPOSY\t\t\t-> (word) // staring position\n\nRED\t\t\t-> (byte) // red color gun value\n\nTRANS_COL\t-> (word) // transparrent color\n\nWIDTH\t\t\t-> (word) // of picture \n\nXASPECT\t\t-> (byte) // x aspect ratio\n\nYASPECT\t\t-> (byte) // y aspect ratio\n\n????\t\t\t-> // other possibilities\n\n\nDifferences in DPII enhance version\n\n.LBM \t\t-> \"FORM\" + FILESIZE + \"PBM \" + CHUNKS\nDPPV\t\t-> DPPS\t\t// uses dpps instead of dppv\nCHUNKS\t\t-> + TINY\t// add these to old definition\n \n\n\n\n#endif\n\u001a\n"
  },
  {
    "path": "WWFLAT32/IFF/WRITEPCX.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : iff                                      *\n *                                                                         *\n *                    File Name : WRITEPCX.CPP                             *\n *                                                                         *\n *                   Programmer : Julio R. Jerez                           *\n *                                                                         *\n *                   Start Date : May 2, 1995                              *\n *                                                                         *\n *                  Last Update : May 2, 1995   [JRJ]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * int Save_PCX_File (char* name, GraphicViewPortClass& pic, char* palette)*\n *= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n#include  <wwlib32.h>\n#include \"filepcx.h\"\nstatic void Write_Pcx_ScanLine ( int file_handle , int scansize , char * ptr );\n\n\n/***************************************************************************\n * WRITE_PCX_FILE -- Write the data in ViewPort to a pcx file              *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:  name is a NULL terminated string of the fromat [xxxx.pcx]\t\t\t*\n *\t\t\t  pic\t is a pointer to a GraphicViewPortClass or to a \t\t\t\t*\n *\t\t\t\t\t GraphicBufferClass holding the picture. \t\t\t\t\t\t\t*\n *        palette is a pointer the the memry block holding the color \t\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *              palette of the picture.                                    *\n *                                                                         *\n * OUTPUT: FALSE  if the function fails zero otherwise             \t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/04/1995 JRJ : Created.                                             *\n *=========================================================================*/\n\nint Write_PCX_File (char* name, GraphicViewPortClass& pic, BYTE* palette )\n{\n  unsigned     i ;\n  unsigned\t   width ;\n  int \t      file_handle ;\n  int\t\t\t\tVP_Scan_Line ;\n  char\t     * ptr ;\n  RGB  \t\t  * pal ;\n  GraphicBufferClass\t* Graphic_Buffer ;\n  PCX_HEADER   header = { 10 , 5 , 1 , 8 , 0 , 0 , 319 , 199 ,\n\t\t\t\t\t\t\t\t  320 , 200 , { 0 } , 0 , 1 , 320 , 1 , {0} } ;\n\n  // Open file name\n  file_handle = Open_File ( name , WRITE ) ;\n  if ( file_handle == ERROR ) return FALSE ;\n\n\n  header.width  = pic.Get_Width() - 1 ;\n  header.height = pic.Get_Height() - 1 ;\n  header.byte_per_line = pic.Get_Width() ;\n  Write_File ( file_handle, & header , sizeof (PCX_HEADER)) ;\n\n  VP_Scan_Line = pic.Get_Width()\t+ pic.Get_XAdd();\n  Graphic_Buffer = pic.Get_Graphic_Buffer() ;\n  ptr = ( char * ) Graphic_Buffer->Get_Buffer() ;\n  ptr += ( (pic.Get_YPos() * VP_Scan_Line) + pic.Get_XPos() );\n  for ( i = 0 ; i < header.height + 1 ; i ++ ) \n   \tWrite_Pcx_ScanLine ( file_handle , header.byte_per_line, ptr + i *VP_Scan_Line ) ;\n\n  pal = ( RGB * ) palette ;\n  for ( i = 0 ; i < 256 ; i ++ ) {\n\t pal -> red <<= 2 ;\n\t pal -> green <<= 2 ;\n\t pal -> blue <<= 2 ;\n\t pal ++ ;\n  }\n i = 0x0c ;\n Write_File ( file_handle, & i , 1 ) ;\n Write_File ( file_handle, palette , 256 * sizeof (RGB) ) ;\n\n Close_File (file_handle) ;\n return 0 ;\n}\n\n\n\n\n/***************************************************************************\n * WRITE_PCX_SCANLINE -- function to write a single pcx scanline to a file *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/04/1995 JRJ : Created.                                             *\n *=========================================================================*/\n\n#define\tPOOL_SIZE 2048 \n#define WRITE_CHAR(x) {\t\\\n\t\t\t\t\t\t\t\t* file_ptr ++ = x ; \\\n\t\t\t\t\t\t\t   if ( file_ptr >= & pool [ POOL_SIZE ]\t) { \\\n\t\t\t\t\t\t\t\t  Write_File ( file_handle, pool , POOL_SIZE ) ; \\\n\t\t\t\t\t\t\t\t  file_ptr = pool ; \\\n\t\t\t\t\t\t\t }\t}\n\nvoid Write_Pcx_ScanLine ( int file_handle , int scansize , char * ptr )\n{\n  unsigned     i ;\n  unsigned     rle ;\n  unsigned     color ;\n  unsigned\t\tlast ;\n  char\t\t  * file_ptr ;\t\n  char\t\t \tpool [ POOL_SIZE ] ;\n\n  file_ptr = pool ;\n  last = * ptr ; \n  rle = 1 ;\n  for ( i = 1 ; i < scansize ; i ++ ) {\n     color = 0xff & * ++ ptr ;\n\t  if ( color == last ) {\n\t\t rle ++ ;\n\t\t if ( rle == 63 )\t {\n\t\t\t\t WRITE_CHAR ( 255 ) ;\n\t\t\t\t WRITE_CHAR ( color ) ;\n\t\t\t\t rle = 0 ;\n\t\t }\n\t  } else if ( rle ) {\n\t\t if ( rle == 1 && ( 192 != ( 192 & last ))) {\n\t\t\t    WRITE_CHAR ( last ) ;\n\t\t } else {\n\t\t\t    WRITE_CHAR ( rle + 192 ) ;\n\t   \t\t WRITE_CHAR ( last ) ;\n\t\t }\n\t\t last = color ;\n\t\t rle = 1 ;\n\t  }\n   }\n\tif ( rle ) {\n\t\t if ( rle == 1 && ( 192 != ( 192 & last ))) {\n\t\t\t    WRITE_CHAR ( last ) ;\n\t\t } else {\n\t\t\t    WRITE_CHAR ( rle + 192 ) ;\n\t   \t\t WRITE_CHAR ( last) ;\n\t\t }\n\t}\n\n\tWrite_File ( file_handle, pool , ( int ) file_ptr - ( int ) pool ) ; \n}\n\n\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/AUDIO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : AUDIO.H                                  *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : March 10, 1995                           *\n *                                                                         *\n *                  Last Update : March 10, 1995   [PWG]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwstd.h\"\n\n/*=========================================================================*/\n/* AUD file header type\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tAUD_FLAG_STEREO\t1\n#define\tAUD_FLAG_16BIT\t\t2\n\n// PWG 3-14-95: This structure used to have bit fields defined for Stereo\n//   and Bits.  These were removed because watcom packs them into a 32 bit\n//   flag entry even though they could have fit in a 8 bit entry.\n#pragma pack(1);\ntypedef struct {\n\tshort int\tRate;\t\t\t\t// Playback rate (hertz).\n\tlong\tSize;\t\t\t\t// Size of data (bytes).\n\tlong\tUncompSize;\t\t\t\t// Size of data (bytes).\n\tunsigned char Flags;\t// Holds flags for info\n\t\t\t\t\t\t\t\t//  1: Is the sample stereo?\n\t\t\t\t\t\t\t\t//  2: Is the sample 16 bits?\n\tunsigned char Compression;\t// What kind of compression for this sample?\n} AUDHeaderType;\n\n\n/*=========================================================================*/\n/*\tThere can be a different sound driver for sound effects, digitized\t\t*/\n/*\tsamples, and musical scores.  Each one must be of these specified\t\t\t*/\n/*\ttypes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\ntypedef enum {\n\tSAMPLE_NONE,\t\t// No digitized sounds will be played.\n\tSAMPLE_SB,\t\t\t// Sound Blaster digitized driver.\n\tSAMPLE_SBPRO,\t\t// Sound Blaster Pro digitized driver.\n\tSAMPLE_PAS,\t\t\t// Pro-Audio Spectrum digitized driver.\n\tSAMPLE_ADLIBG,\t\t// Adlib-Gold digitized driver.\n\tSAMPLE_TANDY,\t\t// Tandy 'compatible' driver.\n\tSAMPLE_PCSPKR,\t\t// PC speaker digitized driver (The Audio Solution driver).\n\tSAMPLE_ADLIB,\t\t// Adlib digitized driver (The Audio Solution driver).\n\tSAMPLE_TEMP=0x1000,\n\tSAMPLE_LAST\n} Sample_Type;\n\ntypedef enum {\n\tSCORE_NONE,\t\t\t// No scores will be played.\n\tSCORE_ALFX,\t\t\t// Westwood's ALFX adlib compatable driver.\n\tSCORE_WWPCSPKR,\t// Westwood's PC-speaker driver (obsolete).\n\tSCORE_WWTANDY,\t\t// Westwood's PC-speaker driver with Tandy mod (obsolete).\n\tSCORE_PCSPKR,\t\t// PC speaker XMIDI driver.\n\tSCORE_TANDY,\t\t// Tandy XMIDI driver.\n\tSCORE_MT32,\t\t\t// MT-32 / LAPC-1 Roland XMIDI driver.\n\tSCORE_CANVAS,\t\t// Sound Canvas SC-55.\n\tSCORE_ADLIB,\t\t// Adlib XMIDI driver.\n\tSCORE_ADLIBG,\t\t// Adlib Gold XMIDI driver.\n\tSCORE_PASFM,\t\t// Pro Audio Spectrum XMIDI driver.\n\tSCORE_SBFM,\t\t\t// Sound Blaster XMIDI driver.\n\tSCORE_SBP1FM,\t\t// Sound Blaster Pro (YM3812) XMIDI driver.\n\tSCORE_SBP2FM,\t\t// Sound Blaster Pro (OPL3) XMIDI driver (Can't use with SFX_ALFX).\n\tSCORE_TEMP=0x1000,\n\tSCORE_LAST\n} Score_Type;\n\ntypedef enum {\n\tSFX_NONE,\t\t\t// No sound effects will be played.\n\tSFX_ALFX,\t\t\t// Westwood's ALFX adlib compatable driver.\n\tSFX_WWPCSPKR,\t\t// Westwood's PC-speaker driver.\n\tSFX_WWTANDY,\t\t// Westwood's PC-speaker driver with Tandy mod.\n\tSFX_PCSPKR,\t\t\t// PC speaker XMIDI driver.\n\tSFX_TANDY,\t\t\t// Tandy XMIDI driver.\n\tSFX_MT32,\t\t\t// MT-32 / LAPC-1 Roland XMIDI driver.\n\tSFX_CANVAS,\t\t\t// Sound Canvas SC-55.\n\tSFX_ADLIB,\t\t\t// Adlib XMIDI driver.\n\tSFX_ADLIBG,\t\t\t// Adlib Gold XMIDI driver.\n\tSFX_PASFM,\t\t\t// Pro Audio Spectrum XMIDI driver.\n\tSFX_SBFM,\t\t\t// Sound Blaster XMIDI driver.\n\tSFX_SBP1FM,\t\t\t// Sound Blaster Pro (YM3812) XMIDI driver.\n\tSFX_SBP2FM,\t\t\t// Sound Blaster Pro (OPL3) XMIDI driver.\n\tSFX_TEMP=0x1000,\n\tSFX_LAST\n} SFX_Type;\n\ntypedef enum RateEnum {\n\tPLAYBACK_RATE_SLOW =11025,\n\tPLAYBACK_RATE_NORMAL =(11025 * 2),\n\tPLAYBACK_RATE_FAST =(11025 * 4),\n} RateType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SOUNDIO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nint File_Stream_Sample(char const *filename, BOOL real_time_start = FALSE);\nint File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start = FALSE);\nvoid cdecl _saveregs Sound_Callback(void);\nvoid cdecl far __saveregs __loadds maintenance_callback(void);\nvoid *Load_Sample(char const *filename);\nlong Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);\nlong Sample_Read(int fh, void *buffer, long size);\nvoid Free_Sample(void const *sample);\nBOOL Sound_Init(int sfx, int score, int sample, RateType rate, int bits_per_sample, int max_samples, int reverse_channels);\nBOOL Audio_Init(int sample, int address, int inter, int dma, RateType rate, int bits_per_sample, int max_samples, int reverse_channels = FALSE);\nvoid Sound_End(void);\nvoid Stop_Sample(int handle);\nBOOL Sample_Status(int handle);\nBOOL Is_Sample_Playing(void const * sample);\nvoid Stop_Sample_Playing(void const * sample);\nint Play_Sample(void const *sample, int priority=0xFF, int volume=0xFF, signed short panloc = 0x0);\nint Play_Sample_Handle(void const *sample, int priority, int volume, signed short panloc, int id);\nint Set_Sound_Vol(int volume);\nint Set_Score_Vol(int volume);\nvoid Fade_Sample(int handle, int ticks);\nint Get_Free_Sample_Handle(int priority);\nint Get_Digi_Handle(void);\nlong Sample_Length(void const *sample);\n\nextern int Misc;\nextern SFX_Type SoundType;\nextern Sample_Type SampleType;\nextern short StreamLowImpact;\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/BUFFER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : GBUFFER.H                                *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 26, 1994                             *\n *                                                                         *\n *                  Last Update : July 5, 1994   [PWG]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   BC::Get_Size -- Returns the buffer size of the BufferClass instance   *\n *   BC::Get_Buffer -- Returns pointer to buffer inherent to BufferClass \t*\n *   BC::BufferClass -- inline constructor for BufferClass with size only  *\n *   BC::To_Page -- Copys a buffer class to a page with definable x, y, w, h*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BUFFER_H\n#define BUFFER_H\n\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\nclass GraphicViewPortClass;\nclass VideoViewPortClass;\n\n/*=========================================================================*/\n/* BufferClass - A base class which holds buffer information including a\t*/\n/*\t\tpointer and the size of the buffer.\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nclass BufferClass {\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBufferClass(void *ptr, long size);\n\t\tBufferClass(long size);\n\t\tBufferClass();\n\t\t~BufferClass();\n\t\t/*===================================================================*/\n\t\t/* Define functions which work with the buffer class.\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong To_Page(GraphicViewPortClass &view);\n\t\tlong To_Page(int w, int h, GraphicViewPortClass &view);\n\t\tlong To_Page(int x, int y, int w, int h, GraphicViewPortClass &view);\n\t\tlong To_Page(VideoViewPortClass &view);\n\t\tlong To_Page(int w, int h, VideoViewPortClass &view);\n\t\tlong To_Page(int x, int y, int w, int h, VideoViewPortClass &view);\n\n\t\t/*===================================================================*/\n\t\t/* define functions to get at the protected data members\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tvoid\t*Get_Buffer(void);\n\t\tlong\tGet_Size(void);\n\n\tprivate:\n\t\t/*===================================================================*/\n\t\t/* Define the operators we do not want to happen which are the copy\t*/\n\t\t/* and equal constructors.  These are bad because the Allocated flag\t*/\n\t\t/*\tcould be copied and the associated buffer freed.  If this were to\t*/\n\t\t/*\tgappen it could cause weird general protection fault.\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBufferClass(BufferClass const &);\n\t\tBufferClass &operator=(BufferClass const &);\n\n\tprotected:\n\t\tvoid\t*Buffer;\n\t\tlong\tSize;\n\t\tBOOL\tAllocated;\n};\n/***************************************************************************\n * BC::GET_SIZE -- Returns the buffer size of the BufferClass instance     *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long the size of the buffer                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::Get_Size(void)\n{\n\treturn(Size);\n}\n/***************************************************************************\n * BC::GET_BUFFER -- Returns pointer to buffer inherent to BufferClass \t\t*\n *                                                                         *\n * INPUT:\t\t\tnone                                                     *\n *                                                                         *\n * OUTPUT:        void * to the inherent buffer.                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline void *BufferClass::Get_Buffer(void)\n{\n\treturn(Buffer);\n}\n#endif\n\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/DESCMGMT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 library                          *\n *                                                                         *\n *                    File Name : DESCMGMT.H                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef DESCMGMT_H\n#define DESCMGMT_H\n\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n//=====================================================================\n// C type include files\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <dos.h>\n#include <bios.h>\n\n#ifdef __cplusplus\n}\n#endif\n\n// ====================================================================\n\n\n// types\n// These where taken from dos.h\n//==========================================\n\n// external functions\n// ===================================================\nextern ULONG Map_Segment_To_Address(ULONG address, ULONG length);\n\nextern \"C\" {\n\t// Assemble functions\n\textern UWORD FixSelector(UWORD sel);\n\textern UWORD GetDs(void);\n\textern UWORD GetCs(void);\n\textern VOID  GetDefaultSelectors(VOID);\n\textern UWORD Get_Standard_Selector(void);\n\n\t\n\t// Assembly data variables\n\textern UWORD CodeSelector;\n\textern UWORD DataSelector;\n\textern UWORD ScreenSelector;\n\textern UWORD GraphicsSelector;\n\textern UWORD PspSelector;\n\textern UWORD EnvSelector;\n\textern UWORD DosMemSelector;\n\textern UWORD Fp1167Selector;\n\textern UWORD FpWeitekSelector;\n\textern UWORD FpCyrixSelector;\n}\n\n#endif  // DESCMGMT_H\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/DIFFTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* dwDiffTable - ADPCM Lookup table for sample differences\n;****************************************************************************\n\n\t\talign\t4\n\ndwDiffTable\tDD\t0\t; Index = 0 Token = 0\n\t\tDD\t1\t; Index = 0 Token = 1\n\t\tDD\t3\t; Index = 0 Token = 2\n\t\tDD\t4\t; Index = 0 Token = 3\n\t\tDD\t7\t; Index = 0 Token = 4\n\t\tDD\t8\t; Index = 0 Token = 5\n\t\tDD\t10\t; Index = 0 Token = 6\n\t\tDD\t11\t; Index = 0 Token = 7\n\t\tDD\t0\t; Index = 0 Token = 8\n\t\tDD\t-1\t; Index = 0 Token = 9\n\t\tDD\t-3\t; Index = 0 Token = 10\n\t\tDD\t-4\t; Index = 0 Token = 11\n\t\tDD\t-7\t; Index = 0 Token = 12\n\t\tDD\t-8\t; Index = 0 Token = 13\n\t\tDD\t-10\t; Index = 0 Token = 14\n\t\tDD\t-11\t; Index = 0 Token = 15\n\t\tDD\t1\t; Index = 1 Token = 0\n\t\tDD\t3\t; Index = 1 Token = 1\n\t\tDD\t5\t; Index = 1 Token = 2\n\t\tDD\t7\t; Index = 1 Token = 3\n\t\tDD\t9\t; Index = 1 Token = 4\n\t\tDD\t11\t; Index = 1 Token = 5\n\t\tDD\t13\t; Index = 1 Token = 6\n\t\tDD\t15\t; Index = 1 Token = 7\n\t\tDD\t-1\t; Index = 1 Token = 8\n\t\tDD\t-3\t; Index = 1 Token = 9\n\t\tDD\t-5\t; Index = 1 Token = 10\n\t\tDD\t-7\t; Index = 1 Token = 11\n\t\tDD\t-9\t; Index = 1 Token = 12\n\t\tDD\t-11\t; Index = 1 Token = 13\n\t\tDD\t-13\t; Index = 1 Token = 14\n\t\tDD\t-15\t; Index = 1 Token = 15\n\t\tDD\t1\t; Index = 2 Token = 0\n\t\tDD\t3\t; Index = 2 Token = 1\n\t\tDD\t5\t; Index = 2 Token = 2\n\t\tDD\t7\t; Index = 2 Token = 3\n\t\tDD\t10\t; Index = 2 Token = 4\n\t\tDD\t12\t; Index = 2 Token = 5\n\t\tDD\t14\t; Index = 2 Token = 6\n\t\tDD\t16\t; Index = 2 Token = 7\n\t\tDD\t-1\t; Index = 2 Token = 8\n\t\tDD\t-3\t; Index = 2 Token = 9\n\t\tDD\t-5\t; Index = 2 Token = 10\n\t\tDD\t-7\t; Index = 2 Token = 11\n\t\tDD\t-10\t; Index = 2 Token = 12\n\t\tDD\t-12\t; Index = 2 Token = 13\n\t\tDD\t-14\t; Index = 2 Token = 14\n\t\tDD\t-16\t; Index = 2 Token = 15\n\t\tDD\t1\t; Index = 3 Token = 0\n\t\tDD\t3\t; Index = 3 Token = 1\n\t\tDD\t6\t; Index = 3 Token = 2\n\t\tDD\t8\t; Index = 3 Token = 3\n\t\tDD\t11\t; Index = 3 Token = 4\n\t\tDD\t13\t; Index = 3 Token = 5\n\t\tDD\t16\t; Index = 3 Token = 6\n\t\tDD\t18\t; Index = 3 Token = 7\n\t\tDD\t-1\t; Index = 3 Token = 8\n\t\tDD\t-3\t; Index = 3 Token = 9\n\t\tDD\t-6\t; Index = 3 Token = 10\n\t\tDD\t-8\t; Index = 3 Token = 11\n\t\tDD\t-11\t; Index = 3 Token = 12\n\t\tDD\t-13\t; Index = 3 Token = 13\n\t\tDD\t-16\t; Index = 3 Token = 14\n\t\tDD\t-18\t; Index = 3 Token = 15\n\t\tDD\t1\t; Index = 4 Token = 0\n\t\tDD\t3\t; Index = 4 Token = 1\n\t\tDD\t6\t; Index = 4 Token = 2\n\t\tDD\t8\t; Index = 4 Token = 3\n\t\tDD\t12\t; Index = 4 Token = 4\n\t\tDD\t14\t; Index = 4 Token = 5\n\t\tDD\t17\t; Index = 4 Token = 6\n\t\tDD\t19\t; Index = 4 Token = 7\n\t\tDD\t-1\t; Index = 4 Token = 8\n\t\tDD\t-3\t; Index = 4 Token = 9\n\t\tDD\t-6\t; Index = 4 Token = 10\n\t\tDD\t-8\t; Index = 4 Token = 11\n\t\tDD\t-12\t; Index = 4 Token = 12\n\t\tDD\t-14\t; Index = 4 Token = 13\n\t\tDD\t-17\t; Index = 4 Token = 14\n\t\tDD\t-19\t; Index = 4 Token = 15\n\t\tDD\t1\t; Index = 5 Token = 0\n\t\tDD\t4\t; Index = 5 Token = 1\n\t\tDD\t7\t; Index = 5 Token = 2\n\t\tDD\t10\t; Index = 5 Token = 3\n\t\tDD\t13\t; Index = 5 Token = 4\n\t\tDD\t16\t; Index = 5 Token = 5\n\t\tDD\t19\t; Index = 5 Token = 6\n\t\tDD\t22\t; Index = 5 Token = 7\n\t\tDD\t-1\t; Index = 5 Token = 8\n\t\tDD\t-4\t; Index = 5 Token = 9\n\t\tDD\t-7\t; Index = 5 Token = 10\n\t\tDD\t-10\t; Index = 5 Token = 11\n\t\tDD\t-13\t; Index = 5 Token = 12\n\t\tDD\t-16\t; Index = 5 Token = 13\n\t\tDD\t-19\t; Index = 5 Token = 14\n\t\tDD\t-22\t; Index = 5 Token = 15\n\t\tDD\t1\t; Index = 6 Token = 0\n\t\tDD\t4\t; Index = 6 Token = 1\n\t\tDD\t7\t; Index = 6 Token = 2\n\t\tDD\t10\t; Index = 6 Token = 3\n\t\tDD\t14\t; Index = 6 Token = 4\n\t\tDD\t17\t; Index = 6 Token = 5\n\t\tDD\t20\t; Index = 6 Token = 6\n\t\tDD\t23\t; Index = 6 Token = 7\n\t\tDD\t-1\t; Index = 6 Token = 8\n\t\tDD\t-4\t; Index = 6 Token = 9\n\t\tDD\t-7\t; Index = 6 Token = 10\n\t\tDD\t-10\t; Index = 6 Token = 11\n\t\tDD\t-14\t; Index = 6 Token = 12\n\t\tDD\t-17\t; Index = 6 Token = 13\n\t\tDD\t-20\t; Index = 6 Token = 14\n\t\tDD\t-23\t; Index = 6 Token = 15\n\t\tDD\t1\t; Index = 7 Token = 0\n\t\tDD\t4\t; Index = 7 Token = 1\n\t\tDD\t8\t; Index = 7 Token = 2\n\t\tDD\t11\t; Index = 7 Token = 3\n\t\tDD\t15\t; Index = 7 Token = 4\n\t\tDD\t18\t; Index = 7 Token = 5\n\t\tDD\t22\t; Index = 7 Token = 6\n\t\tDD\t25\t; Index = 7 Token = 7\n\t\tDD\t-1\t; Index = 7 Token = 8\n\t\tDD\t-4\t; Index = 7 Token = 9\n\t\tDD\t-8\t; Index = 7 Token = 10\n\t\tDD\t-11\t; Index = 7 Token = 11\n\t\tDD\t-15\t; Index = 7 Token = 12\n\t\tDD\t-18\t; Index = 7 Token = 13\n\t\tDD\t-22\t; Index = 7 Token = 14\n\t\tDD\t-25\t; Index = 7 Token = 15\n\t\tDD\t2\t; Index = 8 Token = 0\n\t\tDD\t6\t; Index = 8 Token = 1\n\t\tDD\t10\t; Index = 8 Token = 2\n\t\tDD\t14\t; Index = 8 Token = 3\n\t\tDD\t18\t; Index = 8 Token = 4\n\t\tDD\t22\t; Index = 8 Token = 5\n\t\tDD\t26\t; Index = 8 Token = 6\n\t\tDD\t30\t; Index = 8 Token = 7\n\t\tDD\t-2\t; Index = 8 Token = 8\n\t\tDD\t-6\t; Index = 8 Token = 9\n\t\tDD\t-10\t; Index = 8 Token = 10\n\t\tDD\t-14\t; Index = 8 Token = 11\n\t\tDD\t-18\t; Index = 8 Token = 12\n\t\tDD\t-22\t; Index = 8 Token = 13\n\t\tDD\t-26\t; Index = 8 Token = 14\n\t\tDD\t-30\t; Index = 8 Token = 15\n\t\tDD\t2\t; Index = 9 Token = 0\n\t\tDD\t6\t; Index = 9 Token = 1\n\t\tDD\t10\t; Index = 9 Token = 2\n\t\tDD\t14\t; Index = 9 Token = 3\n\t\tDD\t19\t; Index = 9 Token = 4\n\t\tDD\t23\t; Index = 9 Token = 5\n\t\tDD\t27\t; Index = 9 Token = 6\n\t\tDD\t31\t; Index = 9 Token = 7\n\t\tDD\t-2\t; Index = 9 Token = 8\n\t\tDD\t-6\t; Index = 9 Token = 9\n\t\tDD\t-10\t; Index = 9 Token = 10\n\t\tDD\t-14\t; Index = 9 Token = 11\n\t\tDD\t-19\t; Index = 9 Token = 12\n\t\tDD\t-23\t; Index = 9 Token = 13\n\t\tDD\t-27\t; Index = 9 Token = 14\n\t\tDD\t-31\t; Index = 9 Token = 15\n\t\tDD\t2\t; Index = 10 Token = 0\n\t\tDD\t6\t; Index = 10 Token = 1\n\t\tDD\t11\t; Index = 10 Token = 2\n\t\tDD\t15\t; Index = 10 Token = 3\n\t\tDD\t21\t; Index = 10 Token = 4\n\t\tDD\t25\t; Index = 10 Token = 5\n\t\tDD\t30\t; Index = 10 Token = 6\n\t\tDD\t34\t; Index = 10 Token = 7\n\t\tDD\t-2\t; Index = 10 Token = 8\n\t\tDD\t-6\t; Index = 10 Token = 9\n\t\tDD\t-11\t; Index = 10 Token = 10\n\t\tDD\t-15\t; Index = 10 Token = 11\n\t\tDD\t-21\t; Index = 10 Token = 12\n\t\tDD\t-25\t; Index = 10 Token = 13\n\t\tDD\t-30\t; Index = 10 Token = 14\n\t\tDD\t-34\t; Index = 10 Token = 15\n\t\tDD\t2\t; Index = 11 Token = 0\n\t\tDD\t7\t; Index = 11 Token = 1\n\t\tDD\t12\t; Index = 11 Token = 2\n\t\tDD\t17\t; Index = 11 Token = 3\n\t\tDD\t23\t; Index = 11 Token = 4\n\t\tDD\t28\t; Index = 11 Token = 5\n\t\tDD\t33\t; Index = 11 Token = 6\n\t\tDD\t38\t; Index = 11 Token = 7\n\t\tDD\t-2\t; Index = 11 Token = 8\n\t\tDD\t-7\t; Index = 11 Token = 9\n\t\tDD\t-12\t; Index = 11 Token = 10\n\t\tDD\t-17\t; Index = 11 Token = 11\n\t\tDD\t-23\t; Index = 11 Token = 12\n\t\tDD\t-28\t; Index = 11 Token = 13\n\t\tDD\t-33\t; Index = 11 Token = 14\n\t\tDD\t-38\t; Index = 11 Token = 15\n\t\tDD\t2\t; Index = 12 Token = 0\n\t\tDD\t7\t; Index = 12 Token = 1\n\t\tDD\t13\t; Index = 12 Token = 2\n\t\tDD\t18\t; Index = 12 Token = 3\n\t\tDD\t25\t; Index = 12 Token = 4\n\t\tDD\t30\t; Index = 12 Token = 5\n\t\tDD\t36\t; Index = 12 Token = 6\n\t\tDD\t41\t; Index = 12 Token = 7\n\t\tDD\t-2\t; Index = 12 Token = 8\n\t\tDD\t-7\t; Index = 12 Token = 9\n\t\tDD\t-13\t; Index = 12 Token = 10\n\t\tDD\t-18\t; Index = 12 Token = 11\n\t\tDD\t-25\t; Index = 12 Token = 12\n\t\tDD\t-30\t; Index = 12 Token = 13\n\t\tDD\t-36\t; Index = 12 Token = 14\n\t\tDD\t-41\t; Index = 12 Token = 15\n\t\tDD\t3\t; Index = 13 Token = 0\n\t\tDD\t9\t; Index = 13 Token = 1\n\t\tDD\t15\t; Index = 13 Token = 2\n\t\tDD\t21\t; Index = 13 Token = 3\n\t\tDD\t28\t; Index = 13 Token = 4\n\t\tDD\t34\t; Index = 13 Token = 5\n\t\tDD\t40\t; Index = 13 Token = 6\n\t\tDD\t46\t; Index = 13 Token = 7\n\t\tDD\t-3\t; Index = 13 Token = 8\n\t\tDD\t-9\t; Index = 13 Token = 9\n\t\tDD\t-15\t; Index = 13 Token = 10\n\t\tDD\t-21\t; Index = 13 Token = 11\n\t\tDD\t-28\t; Index = 13 Token = 12\n\t\tDD\t-34\t; Index = 13 Token = 13\n\t\tDD\t-40\t; Index = 13 Token = 14\n\t\tDD\t-46\t; Index = 13 Token = 15\n\t\tDD\t3\t; Index = 14 Token = 0\n\t\tDD\t10\t; Index = 14 Token = 1\n\t\tDD\t17\t; Index = 14 Token = 2\n\t\tDD\t24\t; Index = 14 Token = 3\n\t\tDD\t31\t; Index = 14 Token = 4\n\t\tDD\t38\t; Index = 14 Token = 5\n\t\tDD\t45\t; Index = 14 Token = 6\n\t\tDD\t52\t; Index = 14 Token = 7\n\t\tDD\t-3\t; Index = 14 Token = 8\n\t\tDD\t-10\t; Index = 14 Token = 9\n\t\tDD\t-17\t; Index = 14 Token = 10\n\t\tDD\t-24\t; Index = 14 Token = 11\n\t\tDD\t-31\t; Index = 14 Token = 12\n\t\tDD\t-38\t; Index = 14 Token = 13\n\t\tDD\t-45\t; Index = 14 Token = 14\n\t\tDD\t-52\t; Index = 14 Token = 15\n\t\tDD\t3\t; Index = 15 Token = 0\n\t\tDD\t10\t; Index = 15 Token = 1\n\t\tDD\t18\t; Index = 15 Token = 2\n\t\tDD\t25\t; Index = 15 Token = 3\n\t\tDD\t34\t; Index = 15 Token = 4\n\t\tDD\t41\t; Index = 15 Token = 5\n\t\tDD\t49\t; Index = 15 Token = 6\n\t\tDD\t56\t; Index = 15 Token = 7\n\t\tDD\t-3\t; Index = 15 Token = 8\n\t\tDD\t-10\t; Index = 15 Token = 9\n\t\tDD\t-18\t; Index = 15 Token = 10\n\t\tDD\t-25\t; Index = 15 Token = 11\n\t\tDD\t-34\t; Index = 15 Token = 12\n\t\tDD\t-41\t; Index = 15 Token = 13\n\t\tDD\t-49\t; Index = 15 Token = 14\n\t\tDD\t-56\t; Index = 15 Token = 15\n\t\tDD\t4\t; Index = 16 Token = 0\n\t\tDD\t12\t; Index = 16 Token = 1\n\t\tDD\t21\t; Index = 16 Token = 2\n\t\tDD\t29\t; Index = 16 Token = 3\n\t\tDD\t38\t; Index = 16 Token = 4\n\t\tDD\t46\t; Index = 16 Token = 5\n\t\tDD\t55\t; Index = 16 Token = 6\n\t\tDD\t63\t; Index = 16 Token = 7\n\t\tDD\t-4\t; Index = 16 Token = 8\n\t\tDD\t-12\t; Index = 16 Token = 9\n\t\tDD\t-21\t; Index = 16 Token = 10\n\t\tDD\t-29\t; Index = 16 Token = 11\n\t\tDD\t-38\t; Index = 16 Token = 12\n\t\tDD\t-46\t; Index = 16 Token = 13\n\t\tDD\t-55\t; Index = 16 Token = 14\n\t\tDD\t-63\t; Index = 16 Token = 15\n\t\tDD\t4\t; Index = 17 Token = 0\n\t\tDD\t13\t; Index = 17 Token = 1\n\t\tDD\t22\t; Index = 17 Token = 2\n\t\tDD\t31\t; Index = 17 Token = 3\n\t\tDD\t41\t; Index = 17 Token = 4\n\t\tDD\t50\t; Index = 17 Token = 5\n\t\tDD\t59\t; Index = 17 Token = 6\n\t\tDD\t68\t; Index = 17 Token = 7\n\t\tDD\t-4\t; Index = 17 Token = 8\n\t\tDD\t-13\t; Index = 17 Token = 9\n\t\tDD\t-22\t; Index = 17 Token = 10\n\t\tDD\t-31\t; Index = 17 Token = 11\n\t\tDD\t-41\t; Index = 17 Token = 12\n\t\tDD\t-50\t; Index = 17 Token = 13\n\t\tDD\t-59\t; Index = 17 Token = 14\n\t\tDD\t-68\t; Index = 17 Token = 15\n\t\tDD\t5\t; Index = 18 Token = 0\n\t\tDD\t15\t; Index = 18 Token = 1\n\t\tDD\t25\t; Index = 18 Token = 2\n\t\tDD\t35\t; Index = 18 Token = 3\n\t\tDD\t46\t; Index = 18 Token = 4\n\t\tDD\t56\t; Index = 18 Token = 5\n\t\tDD\t66\t; Index = 18 Token = 6\n\t\tDD\t76\t; Index = 18 Token = 7\n\t\tDD\t-5\t; Index = 18 Token = 8\n\t\tDD\t-15\t; Index = 18 Token = 9\n\t\tDD\t-25\t; Index = 18 Token = 10\n\t\tDD\t-35\t; Index = 18 Token = 11\n\t\tDD\t-46\t; Index = 18 Token = 12\n\t\tDD\t-56\t; Index = 18 Token = 13\n\t\tDD\t-66\t; Index = 18 Token = 14\n\t\tDD\t-76\t; Index = 18 Token = 15\n\t\tDD\t5\t; Index = 19 Token = 0\n\t\tDD\t16\t; Index = 19 Token = 1\n\t\tDD\t27\t; Index = 19 Token = 2\n\t\tDD\t38\t; Index = 19 Token = 3\n\t\tDD\t50\t; Index = 19 Token = 4\n\t\tDD\t61\t; Index = 19 Token = 5\n\t\tDD\t72\t; Index = 19 Token = 6\n\t\tDD\t83\t; Index = 19 Token = 7\n\t\tDD\t-5\t; Index = 19 Token = 8\n\t\tDD\t-16\t; Index = 19 Token = 9\n\t\tDD\t-27\t; Index = 19 Token = 10\n\t\tDD\t-38\t; Index = 19 Token = 11\n\t\tDD\t-50\t; Index = 19 Token = 12\n\t\tDD\t-61\t; Index = 19 Token = 13\n\t\tDD\t-72\t; Index = 19 Token = 14\n\t\tDD\t-83\t; Index = 19 Token = 15\n\t\tDD\t6\t; Index = 20 Token = 0\n\t\tDD\t18\t; Index = 20 Token = 1\n\t\tDD\t31\t; Index = 20 Token = 2\n\t\tDD\t43\t; Index = 20 Token = 3\n\t\tDD\t56\t; Index = 20 Token = 4\n\t\tDD\t68\t; Index = 20 Token = 5\n\t\tDD\t81\t; Index = 20 Token = 6\n\t\tDD\t93\t; Index = 20 Token = 7\n\t\tDD\t-6\t; Index = 20 Token = 8\n\t\tDD\t-18\t; Index = 20 Token = 9\n\t\tDD\t-31\t; Index = 20 Token = 10\n\t\tDD\t-43\t; Index = 20 Token = 11\n\t\tDD\t-56\t; Index = 20 Token = 12\n\t\tDD\t-68\t; Index = 20 Token = 13\n\t\tDD\t-81\t; Index = 20 Token = 14\n\t\tDD\t-93\t; Index = 20 Token = 15\n\t\tDD\t6\t; Index = 21 Token = 0\n\t\tDD\t19\t; Index = 21 Token = 1\n\t\tDD\t33\t; Index = 21 Token = 2\n\t\tDD\t46\t; Index = 21 Token = 3\n\t\tDD\t61\t; Index = 21 Token = 4\n\t\tDD\t74\t; Index = 21 Token = 5\n\t\tDD\t88\t; Index = 21 Token = 6\n\t\tDD\t101\t; Index = 21 Token = 7\n\t\tDD\t-6\t; Index = 21 Token = 8\n\t\tDD\t-19\t; Index = 21 Token = 9\n\t\tDD\t-33\t; Index = 21 Token = 10\n\t\tDD\t-46\t; Index = 21 Token = 11\n\t\tDD\t-61\t; Index = 21 Token = 12\n\t\tDD\t-74\t; Index = 21 Token = 13\n\t\tDD\t-88\t; Index = 21 Token = 14\n\t\tDD\t-101\t; Index = 21 Token = 15\n\t\tDD\t7\t; Index = 22 Token = 0\n\t\tDD\t22\t; Index = 22 Token = 1\n\t\tDD\t37\t; Index = 22 Token = 2\n\t\tDD\t52\t; Index = 22 Token = 3\n\t\tDD\t67\t; Index = 22 Token = 4\n\t\tDD\t82\t; Index = 22 Token = 5\n\t\tDD\t97\t; Index = 22 Token = 6\n\t\tDD\t112\t; Index = 22 Token = 7\n\t\tDD\t-7\t; Index = 22 Token = 8\n\t\tDD\t-22\t; Index = 22 Token = 9\n\t\tDD\t-37\t; Index = 22 Token = 10\n\t\tDD\t-52\t; Index = 22 Token = 11\n\t\tDD\t-67\t; Index = 22 Token = 12\n\t\tDD\t-82\t; Index = 22 Token = 13\n\t\tDD\t-97\t; Index = 22 Token = 14\n\t\tDD\t-112\t; Index = 22 Token = 15\n\t\tDD\t8\t; Index = 23 Token = 0\n\t\tDD\t24\t; Index = 23 Token = 1\n\t\tDD\t41\t; Index = 23 Token = 2\n\t\tDD\t57\t; Index = 23 Token = 3\n\t\tDD\t74\t; Index = 23 Token = 4\n\t\tDD\t90\t; Index = 23 Token = 5\n\t\tDD\t107\t; Index = 23 Token = 6\n\t\tDD\t123\t; Index = 23 Token = 7\n\t\tDD\t-8\t; Index = 23 Token = 8\n\t\tDD\t-24\t; Index = 23 Token = 9\n\t\tDD\t-41\t; Index = 23 Token = 10\n\t\tDD\t-57\t; Index = 23 Token = 11\n\t\tDD\t-74\t; Index = 23 Token = 12\n\t\tDD\t-90\t; Index = 23 Token = 13\n\t\tDD\t-107\t; Index = 23 Token = 14\n\t\tDD\t-123\t; Index = 23 Token = 15\n\t\tDD\t9\t; Index = 24 Token = 0\n\t\tDD\t27\t; Index = 24 Token = 1\n\t\tDD\t45\t; Index = 24 Token = 2\n\t\tDD\t63\t; Index = 24 Token = 3\n\t\tDD\t82\t; Index = 24 Token = 4\n\t\tDD\t100\t; Index = 24 Token = 5\n\t\tDD\t118\t; Index = 24 Token = 6\n\t\tDD\t136\t; Index = 24 Token = 7\n\t\tDD\t-9\t; Index = 24 Token = 8\n\t\tDD\t-27\t; Index = 24 Token = 9\n\t\tDD\t-45\t; Index = 24 Token = 10\n\t\tDD\t-63\t; Index = 24 Token = 11\n\t\tDD\t-82\t; Index = 24 Token = 12\n\t\tDD\t-100\t; Index = 24 Token = 13\n\t\tDD\t-118\t; Index = 24 Token = 14\n\t\tDD\t-136\t; Index = 24 Token = 15\n\t\tDD\t10\t; Index = 25 Token = 0\n\t\tDD\t30\t; Index = 25 Token = 1\n\t\tDD\t50\t; Index = 25 Token = 2\n\t\tDD\t70\t; Index = 25 Token = 3\n\t\tDD\t90\t; Index = 25 Token = 4\n\t\tDD\t110\t; Index = 25 Token = 5\n\t\tDD\t130\t; Index = 25 Token = 6\n\t\tDD\t150\t; Index = 25 Token = 7\n\t\tDD\t-10\t; Index = 25 Token = 8\n\t\tDD\t-30\t; Index = 25 Token = 9\n\t\tDD\t-50\t; Index = 25 Token = 10\n\t\tDD\t-70\t; Index = 25 Token = 11\n\t\tDD\t-90\t; Index = 25 Token = 12\n\t\tDD\t-110\t; Index = 25 Token = 13\n\t\tDD\t-130\t; Index = 25 Token = 14\n\t\tDD\t-150\t; Index = 25 Token = 15\n\t\tDD\t11\t; Index = 26 Token = 0\n\t\tDD\t33\t; Index = 26 Token = 1\n\t\tDD\t55\t; Index = 26 Token = 2\n\t\tDD\t77\t; Index = 26 Token = 3\n\t\tDD\t99\t; Index = 26 Token = 4\n\t\tDD\t121\t; Index = 26 Token = 5\n\t\tDD\t143\t; Index = 26 Token = 6\n\t\tDD\t165\t; Index = 26 Token = 7\n\t\tDD\t-11\t; Index = 26 Token = 8\n\t\tDD\t-33\t; Index = 26 Token = 9\n\t\tDD\t-55\t; Index = 26 Token = 10\n\t\tDD\t-77\t; Index = 26 Token = 11\n\t\tDD\t-99\t; Index = 26 Token = 12\n\t\tDD\t-121\t; Index = 26 Token = 13\n\t\tDD\t-143\t; Index = 26 Token = 14\n\t\tDD\t-165\t; Index = 26 Token = 15\n\t\tDD\t12\t; Index = 27 Token = 0\n\t\tDD\t36\t; Index = 27 Token = 1\n\t\tDD\t60\t; Index = 27 Token = 2\n\t\tDD\t84\t; Index = 27 Token = 3\n\t\tDD\t109\t; Index = 27 Token = 4\n\t\tDD\t133\t; Index = 27 Token = 5\n\t\tDD\t157\t; Index = 27 Token = 6\n\t\tDD\t181\t; Index = 27 Token = 7\n\t\tDD\t-12\t; Index = 27 Token = 8\n\t\tDD\t-36\t; Index = 27 Token = 9\n\t\tDD\t-60\t; Index = 27 Token = 10\n\t\tDD\t-84\t; Index = 27 Token = 11\n\t\tDD\t-109\t; Index = 27 Token = 12\n\t\tDD\t-133\t; Index = 27 Token = 13\n\t\tDD\t-157\t; Index = 27 Token = 14\n\t\tDD\t-181\t; Index = 27 Token = 15\n\t\tDD\t13\t; Index = 28 Token = 0\n\t\tDD\t39\t; Index = 28 Token = 1\n\t\tDD\t66\t; Index = 28 Token = 2\n\t\tDD\t92\t; Index = 28 Token = 3\n\t\tDD\t120\t; Index = 28 Token = 4\n\t\tDD\t146\t; Index = 28 Token = 5\n\t\tDD\t173\t; Index = 28 Token = 6\n\t\tDD\t199\t; Index = 28 Token = 7\n\t\tDD\t-13\t; Index = 28 Token = 8\n\t\tDD\t-39\t; Index = 28 Token = 9\n\t\tDD\t-66\t; Index = 28 Token = 10\n\t\tDD\t-92\t; Index = 28 Token = 11\n\t\tDD\t-120\t; Index = 28 Token = 12\n\t\tDD\t-146\t; Index = 28 Token = 13\n\t\tDD\t-173\t; Index = 28 Token = 14\n\t\tDD\t-199\t; Index = 28 Token = 15\n\t\tDD\t14\t; Index = 29 Token = 0\n\t\tDD\t43\t; Index = 29 Token = 1\n\t\tDD\t73\t; Index = 29 Token = 2\n\t\tDD\t102\t; Index = 29 Token = 3\n\t\tDD\t132\t; Index = 29 Token = 4\n\t\tDD\t161\t; Index = 29 Token = 5\n\t\tDD\t191\t; Index = 29 Token = 6\n\t\tDD\t220\t; Index = 29 Token = 7\n\t\tDD\t-14\t; Index = 29 Token = 8\n\t\tDD\t-43\t; Index = 29 Token = 9\n\t\tDD\t-73\t; Index = 29 Token = 10\n\t\tDD\t-102\t; Index = 29 Token = 11\n\t\tDD\t-132\t; Index = 29 Token = 12\n\t\tDD\t-161\t; Index = 29 Token = 13\n\t\tDD\t-191\t; Index = 29 Token = 14\n\t\tDD\t-220\t; Index = 29 Token = 15\n\t\tDD\t16\t; Index = 30 Token = 0\n\t\tDD\t48\t; Index = 30 Token = 1\n\t\tDD\t81\t; Index = 30 Token = 2\n\t\tDD\t113\t; Index = 30 Token = 3\n\t\tDD\t146\t; Index = 30 Token = 4\n\t\tDD\t178\t; Index = 30 Token = 5\n\t\tDD\t211\t; Index = 30 Token = 6\n\t\tDD\t243\t; Index = 30 Token = 7\n\t\tDD\t-16\t; Index = 30 Token = 8\n\t\tDD\t-48\t; Index = 30 Token = 9\n\t\tDD\t-81\t; Index = 30 Token = 10\n\t\tDD\t-113\t; Index = 30 Token = 11\n\t\tDD\t-146\t; Index = 30 Token = 12\n\t\tDD\t-178\t; Index = 30 Token = 13\n\t\tDD\t-211\t; Index = 30 Token = 14\n\t\tDD\t-243\t; Index = 30 Token = 15\n\t\tDD\t17\t; Index = 31 Token = 0\n\t\tDD\t52\t; Index = 31 Token = 1\n\t\tDD\t88\t; Index = 31 Token = 2\n\t\tDD\t123\t; Index = 31 Token = 3\n\t\tDD\t160\t; Index = 31 Token = 4\n\t\tDD\t195\t; Index = 31 Token = 5\n\t\tDD\t231\t; Index = 31 Token = 6\n\t\tDD\t266\t; Index = 31 Token = 7\n\t\tDD\t-17\t; Index = 31 Token = 8\n\t\tDD\t-52\t; Index = 31 Token = 9\n\t\tDD\t-88\t; Index = 31 Token = 10\n\t\tDD\t-123\t; Index = 31 Token = 11\n\t\tDD\t-160\t; Index = 31 Token = 12\n\t\tDD\t-195\t; Index = 31 Token = 13\n\t\tDD\t-231\t; Index = 31 Token = 14\n\t\tDD\t-266\t; Index = 31 Token = 15\n\t\tDD\t19\t; Index = 32 Token = 0\n\t\tDD\t58\t; Index = 32 Token = 1\n\t\tDD\t97\t; Index = 32 Token = 2\n\t\tDD\t136\t; Index = 32 Token = 3\n\t\tDD\t176\t; Index = 32 Token = 4\n\t\tDD\t215\t; Index = 32 Token = 5\n\t\tDD\t254\t; Index = 32 Token = 6\n\t\tDD\t293\t; Index = 32 Token = 7\n\t\tDD\t-19\t; Index = 32 Token = 8\n\t\tDD\t-58\t; Index = 32 Token = 9\n\t\tDD\t-97\t; Index = 32 Token = 10\n\t\tDD\t-136\t; Index = 32 Token = 11\n\t\tDD\t-176\t; Index = 32 Token = 12\n\t\tDD\t-215\t; Index = 32 Token = 13\n\t\tDD\t-254\t; Index = 32 Token = 14\n\t\tDD\t-293\t; Index = 32 Token = 15\n\t\tDD\t21\t; Index = 33 Token = 0\n\t\tDD\t64\t; Index = 33 Token = 1\n\t\tDD\t107\t; Index = 33 Token = 2\n\t\tDD\t150\t; Index = 33 Token = 3\n\t\tDD\t194\t; Index = 33 Token = 4\n\t\tDD\t237\t; Index = 33 Token = 5\n\t\tDD\t280\t; Index = 33 Token = 6\n\t\tDD\t323\t; Index = 33 Token = 7\n\t\tDD\t-21\t; Index = 33 Token = 8\n\t\tDD\t-64\t; Index = 33 Token = 9\n\t\tDD\t-107\t; Index = 33 Token = 10\n\t\tDD\t-150\t; Index = 33 Token = 11\n\t\tDD\t-194\t; Index = 33 Token = 12\n\t\tDD\t-237\t; Index = 33 Token = 13\n\t\tDD\t-280\t; Index = 33 Token = 14\n\t\tDD\t-323\t; Index = 33 Token = 15\n\t\tDD\t23\t; Index = 34 Token = 0\n\t\tDD\t70\t; Index = 34 Token = 1\n\t\tDD\t118\t; Index = 34 Token = 2\n\t\tDD\t165\t; Index = 34 Token = 3\n\t\tDD\t213\t; Index = 34 Token = 4\n\t\tDD\t260\t; Index = 34 Token = 5\n\t\tDD\t308\t; Index = 34 Token = 6\n\t\tDD\t355\t; Index = 34 Token = 7\n\t\tDD\t-23\t; Index = 34 Token = 8\n\t\tDD\t-70\t; Index = 34 Token = 9\n\t\tDD\t-118\t; Index = 34 Token = 10\n\t\tDD\t-165\t; Index = 34 Token = 11\n\t\tDD\t-213\t; Index = 34 Token = 12\n\t\tDD\t-260\t; Index = 34 Token = 13\n\t\tDD\t-308\t; Index = 34 Token = 14\n\t\tDD\t-355\t; Index = 34 Token = 15\n\t\tDD\t26\t; Index = 35 Token = 0\n\t\tDD\t78\t; Index = 35 Token = 1\n\t\tDD\t130\t; Index = 35 Token = 2\n\t\tDD\t182\t; Index = 35 Token = 3\n\t\tDD\t235\t; Index = 35 Token = 4\n\t\tDD\t287\t; Index = 35 Token = 5\n\t\tDD\t339\t; Index = 35 Token = 6\n\t\tDD\t391\t; Index = 35 Token = 7\n\t\tDD\t-26\t; Index = 35 Token = 8\n\t\tDD\t-78\t; Index = 35 Token = 9\n\t\tDD\t-130\t; Index = 35 Token = 10\n\t\tDD\t-182\t; Index = 35 Token = 11\n\t\tDD\t-235\t; Index = 35 Token = 12\n\t\tDD\t-287\t; Index = 35 Token = 13\n\t\tDD\t-339\t; Index = 35 Token = 14\n\t\tDD\t-391\t; Index = 35 Token = 15\n\t\tDD\t28\t; Index = 36 Token = 0\n\t\tDD\t85\t; Index = 36 Token = 1\n\t\tDD\t143\t; Index = 36 Token = 2\n\t\tDD\t200\t; Index = 36 Token = 3\n\t\tDD\t258\t; Index = 36 Token = 4\n\t\tDD\t315\t; Index = 36 Token = 5\n\t\tDD\t373\t; Index = 36 Token = 6\n\t\tDD\t430\t; Index = 36 Token = 7\n\t\tDD\t-28\t; Index = 36 Token = 8\n\t\tDD\t-85\t; Index = 36 Token = 9\n\t\tDD\t-143\t; Index = 36 Token = 10\n\t\tDD\t-200\t; Index = 36 Token = 11\n\t\tDD\t-258\t; Index = 36 Token = 12\n\t\tDD\t-315\t; Index = 36 Token = 13\n\t\tDD\t-373\t; Index = 36 Token = 14\n\t\tDD\t-430\t; Index = 36 Token = 15\n\t\tDD\t31\t; Index = 37 Token = 0\n\t\tDD\t94\t; Index = 37 Token = 1\n\t\tDD\t157\t; Index = 37 Token = 2\n\t\tDD\t220\t; Index = 37 Token = 3\n\t\tDD\t284\t; Index = 37 Token = 4\n\t\tDD\t347\t; Index = 37 Token = 5\n\t\tDD\t410\t; Index = 37 Token = 6\n\t\tDD\t473\t; Index = 37 Token = 7\n\t\tDD\t-31\t; Index = 37 Token = 8\n\t\tDD\t-94\t; Index = 37 Token = 9\n\t\tDD\t-157\t; Index = 37 Token = 10\n\t\tDD\t-220\t; Index = 37 Token = 11\n\t\tDD\t-284\t; Index = 37 Token = 12\n\t\tDD\t-347\t; Index = 37 Token = 13\n\t\tDD\t-410\t; Index = 37 Token = 14\n\t\tDD\t-473\t; Index = 37 Token = 15\n\t\tDD\t34\t; Index = 38 Token = 0\n\t\tDD\t103\t; Index = 38 Token = 1\n\t\tDD\t173\t; Index = 38 Token = 2\n\t\tDD\t242\t; Index = 38 Token = 3\n\t\tDD\t313\t; Index = 38 Token = 4\n\t\tDD\t382\t; Index = 38 Token = 5\n\t\tDD\t452\t; Index = 38 Token = 6\n\t\tDD\t521\t; Index = 38 Token = 7\n\t\tDD\t-34\t; Index = 38 Token = 8\n\t\tDD\t-103\t; Index = 38 Token = 9\n\t\tDD\t-173\t; Index = 38 Token = 10\n\t\tDD\t-242\t; Index = 38 Token = 11\n\t\tDD\t-313\t; Index = 38 Token = 12\n\t\tDD\t-382\t; Index = 38 Token = 13\n\t\tDD\t-452\t; Index = 38 Token = 14\n\t\tDD\t-521\t; Index = 38 Token = 15\n\t\tDD\t38\t; Index = 39 Token = 0\n\t\tDD\t114\t; Index = 39 Token = 1\n\t\tDD\t191\t; Index = 39 Token = 2\n\t\tDD\t267\t; Index = 39 Token = 3\n\t\tDD\t345\t; Index = 39 Token = 4\n\t\tDD\t421\t; Index = 39 Token = 5\n\t\tDD\t498\t; Index = 39 Token = 6\n\t\tDD\t574\t; Index = 39 Token = 7\n\t\tDD\t-38\t; Index = 39 Token = 8\n\t\tDD\t-114\t; Index = 39 Token = 9\n\t\tDD\t-191\t; Index = 39 Token = 10\n\t\tDD\t-267\t; Index = 39 Token = 11\n\t\tDD\t-345\t; Index = 39 Token = 12\n\t\tDD\t-421\t; Index = 39 Token = 13\n\t\tDD\t-498\t; Index = 39 Token = 14\n\t\tDD\t-574\t; Index = 39 Token = 15\n\t\tDD\t42\t; Index = 40 Token = 0\n\t\tDD\t126\t; Index = 40 Token = 1\n\t\tDD\t210\t; Index = 40 Token = 2\n\t\tDD\t294\t; Index = 40 Token = 3\n\t\tDD\t379\t; Index = 40 Token = 4\n\t\tDD\t463\t; Index = 40 Token = 5\n\t\tDD\t547\t; Index = 40 Token = 6\n\t\tDD\t631\t; Index = 40 Token = 7\n\t\tDD\t-42\t; Index = 40 Token = 8\n\t\tDD\t-126\t; Index = 40 Token = 9\n\t\tDD\t-210\t; Index = 40 Token = 10\n\t\tDD\t-294\t; Index = 40 Token = 11\n\t\tDD\t-379\t; Index = 40 Token = 12\n\t\tDD\t-463\t; Index = 40 Token = 13\n\t\tDD\t-547\t; Index = 40 Token = 14\n\t\tDD\t-631\t; Index = 40 Token = 15\n\t\tDD\t46\t; Index = 41 Token = 0\n\t\tDD\t138\t; Index = 41 Token = 1\n\t\tDD\t231\t; Index = 41 Token = 2\n\t\tDD\t323\t; Index = 41 Token = 3\n\t\tDD\t417\t; Index = 41 Token = 4\n\t\tDD\t509\t; Index = 41 Token = 5\n\t\tDD\t602\t; Index = 41 Token = 6\n\t\tDD\t694\t; Index = 41 Token = 7\n\t\tDD\t-46\t; Index = 41 Token = 8\n\t\tDD\t-138\t; Index = 41 Token = 9\n\t\tDD\t-231\t; Index = 41 Token = 10\n\t\tDD\t-323\t; Index = 41 Token = 11\n\t\tDD\t-417\t; Index = 41 Token = 12\n\t\tDD\t-509\t; Index = 41 Token = 13\n\t\tDD\t-602\t; Index = 41 Token = 14\n\t\tDD\t-694\t; Index = 41 Token = 15\n\t\tDD\t51\t; Index = 42 Token = 0\n\t\tDD\t153\t; Index = 42 Token = 1\n\t\tDD\t255\t; Index = 42 Token = 2\n\t\tDD\t357\t; Index = 42 Token = 3\n\t\tDD\t459\t; Index = 42 Token = 4\n\t\tDD\t561\t; Index = 42 Token = 5\n\t\tDD\t663\t; Index = 42 Token = 6\n\t\tDD\t765\t; Index = 42 Token = 7\n\t\tDD\t-51\t; Index = 42 Token = 8\n\t\tDD\t-153\t; Index = 42 Token = 9\n\t\tDD\t-255\t; Index = 42 Token = 10\n\t\tDD\t-357\t; Index = 42 Token = 11\n\t\tDD\t-459\t; Index = 42 Token = 12\n\t\tDD\t-561\t; Index = 42 Token = 13\n\t\tDD\t-663\t; Index = 42 Token = 14\n\t\tDD\t-765\t; Index = 42 Token = 15\n\t\tDD\t56\t; Index = 43 Token = 0\n\t\tDD\t168\t; Index = 43 Token = 1\n\t\tDD\t280\t; Index = 43 Token = 2\n\t\tDD\t392\t; Index = 43 Token = 3\n\t\tDD\t505\t; Index = 43 Token = 4\n\t\tDD\t617\t; Index = 43 Token = 5\n\t\tDD\t729\t; Index = 43 Token = 6\n\t\tDD\t841\t; Index = 43 Token = 7\n\t\tDD\t-56\t; Index = 43 Token = 8\n\t\tDD\t-168\t; Index = 43 Token = 9\n\t\tDD\t-280\t; Index = 43 Token = 10\n\t\tDD\t-392\t; Index = 43 Token = 11\n\t\tDD\t-505\t; Index = 43 Token = 12\n\t\tDD\t-617\t; Index = 43 Token = 13\n\t\tDD\t-729\t; Index = 43 Token = 14\n\t\tDD\t-841\t; Index = 43 Token = 15\n\t\tDD\t61\t; Index = 44 Token = 0\n\t\tDD\t184\t; Index = 44 Token = 1\n\t\tDD\t308\t; Index = 44 Token = 2\n\t\tDD\t431\t; Index = 44 Token = 3\n\t\tDD\t555\t; Index = 44 Token = 4\n\t\tDD\t678\t; Index = 44 Token = 5\n\t\tDD\t802\t; Index = 44 Token = 6\n\t\tDD\t925\t; Index = 44 Token = 7\n\t\tDD\t-61\t; Index = 44 Token = 8\n\t\tDD\t-184\t; Index = 44 Token = 9\n\t\tDD\t-308\t; Index = 44 Token = 10\n\t\tDD\t-431\t; Index = 44 Token = 11\n\t\tDD\t-555\t; Index = 44 Token = 12\n\t\tDD\t-678\t; Index = 44 Token = 13\n\t\tDD\t-802\t; Index = 44 Token = 14\n\t\tDD\t-925\t; Index = 44 Token = 15\n\t\tDD\t68\t; Index = 45 Token = 0\n\t\tDD\t204\t; Index = 45 Token = 1\n\t\tDD\t340\t; Index = 45 Token = 2\n\t\tDD\t476\t; Index = 45 Token = 3\n\t\tDD\t612\t; Index = 45 Token = 4\n\t\tDD\t748\t; Index = 45 Token = 5\n\t\tDD\t884\t; Index = 45 Token = 6\n\t\tDD\t1020\t; Index = 45 Token = 7\n\t\tDD\t-68\t; Index = 45 Token = 8\n\t\tDD\t-204\t; Index = 45 Token = 9\n\t\tDD\t-340\t; Index = 45 Token = 10\n\t\tDD\t-476\t; Index = 45 Token = 11\n\t\tDD\t-612\t; Index = 45 Token = 12\n\t\tDD\t-748\t; Index = 45 Token = 13\n\t\tDD\t-884\t; Index = 45 Token = 14\n\t\tDD\t-1020\t; Index = 45 Token = 15\n\t\tDD\t74\t; Index = 46 Token = 0\n\t\tDD\t223\t; Index = 46 Token = 1\n\t\tDD\t373\t; Index = 46 Token = 2\n\t\tDD\t522\t; Index = 46 Token = 3\n\t\tDD\t672\t; Index = 46 Token = 4\n\t\tDD\t821\t; Index = 46 Token = 5\n\t\tDD\t971\t; Index = 46 Token = 6\n\t\tDD\t1120\t; Index = 46 Token = 7\n\t\tDD\t-74\t; Index = 46 Token = 8\n\t\tDD\t-223\t; Index = 46 Token = 9\n\t\tDD\t-373\t; Index = 46 Token = 10\n\t\tDD\t-522\t; Index = 46 Token = 11\n\t\tDD\t-672\t; Index = 46 Token = 12\n\t\tDD\t-821\t; Index = 46 Token = 13\n\t\tDD\t-971\t; Index = 46 Token = 14\n\t\tDD\t-1120\t; Index = 46 Token = 15\n\t\tDD\t82\t; Index = 47 Token = 0\n\t\tDD\t246\t; Index = 47 Token = 1\n\t\tDD\t411\t; Index = 47 Token = 2\n\t\tDD\t575\t; Index = 47 Token = 3\n\t\tDD\t740\t; Index = 47 Token = 4\n\t\tDD\t904\t; Index = 47 Token = 5\n\t\tDD\t1069\t; Index = 47 Token = 6\n\t\tDD\t1233\t; Index = 47 Token = 7\n\t\tDD\t-82\t; Index = 47 Token = 8\n\t\tDD\t-246\t; Index = 47 Token = 9\n\t\tDD\t-411\t; Index = 47 Token = 10\n\t\tDD\t-575\t; Index = 47 Token = 11\n\t\tDD\t-740\t; Index = 47 Token = 12\n\t\tDD\t-904\t; Index = 47 Token = 13\n\t\tDD\t-1069\t; Index = 47 Token = 14\n\t\tDD\t-1233\t; Index = 47 Token = 15\n\t\tDD\t90\t; Index = 48 Token = 0\n\t\tDD\t271\t; Index = 48 Token = 1\n\t\tDD\t452\t; Index = 48 Token = 2\n\t\tDD\t633\t; Index = 48 Token = 3\n\t\tDD\t814\t; Index = 48 Token = 4\n\t\tDD\t995\t; Index = 48 Token = 5\n\t\tDD\t1176\t; Index = 48 Token = 6\n\t\tDD\t1357\t; Index = 48 Token = 7\n\t\tDD\t-90\t; Index = 48 Token = 8\n\t\tDD\t-271\t; Index = 48 Token = 9\n\t\tDD\t-452\t; Index = 48 Token = 10\n\t\tDD\t-633\t; Index = 48 Token = 11\n\t\tDD\t-814\t; Index = 48 Token = 12\n\t\tDD\t-995\t; Index = 48 Token = 13\n\t\tDD\t-1176\t; Index = 48 Token = 14\n\t\tDD\t-1357\t; Index = 48 Token = 15\n\t\tDD\t99\t; Index = 49 Token = 0\n\t\tDD\t298\t; Index = 49 Token = 1\n\t\tDD\t497\t; Index = 49 Token = 2\n\t\tDD\t696\t; Index = 49 Token = 3\n\t\tDD\t895\t; Index = 49 Token = 4\n\t\tDD\t1094\t; Index = 49 Token = 5\n\t\tDD\t1293\t; Index = 49 Token = 6\n\t\tDD\t1492\t; Index = 49 Token = 7\n\t\tDD\t-99\t; Index = 49 Token = 8\n\t\tDD\t-298\t; Index = 49 Token = 9\n\t\tDD\t-497\t; Index = 49 Token = 10\n\t\tDD\t-696\t; Index = 49 Token = 11\n\t\tDD\t-895\t; Index = 49 Token = 12\n\t\tDD\t-1094\t; Index = 49 Token = 13\n\t\tDD\t-1293\t; Index = 49 Token = 14\n\t\tDD\t-1492\t; Index = 49 Token = 15\n\t\tDD\t109\t; Index = 50 Token = 0\n\t\tDD\t328\t; Index = 50 Token = 1\n\t\tDD\t547\t; Index = 50 Token = 2\n\t\tDD\t766\t; Index = 50 Token = 3\n\t\tDD\t985\t; Index = 50 Token = 4\n\t\tDD\t1204\t; Index = 50 Token = 5\n\t\tDD\t1423\t; Index = 50 Token = 6\n\t\tDD\t1642\t; Index = 50 Token = 7\n\t\tDD\t-109\t; Index = 50 Token = 8\n\t\tDD\t-328\t; Index = 50 Token = 9\n\t\tDD\t-547\t; Index = 50 Token = 10\n\t\tDD\t-766\t; Index = 50 Token = 11\n\t\tDD\t-985\t; Index = 50 Token = 12\n\t\tDD\t-1204\t; Index = 50 Token = 13\n\t\tDD\t-1423\t; Index = 50 Token = 14\n\t\tDD\t-1642\t; Index = 50 Token = 15\n\t\tDD\t120\t; Index = 51 Token = 0\n\t\tDD\t360\t; Index = 51 Token = 1\n\t\tDD\t601\t; Index = 51 Token = 2\n\t\tDD\t841\t; Index = 51 Token = 3\n\t\tDD\t1083\t; Index = 51 Token = 4\n\t\tDD\t1323\t; Index = 51 Token = 5\n\t\tDD\t1564\t; Index = 51 Token = 6\n\t\tDD\t1804\t; Index = 51 Token = 7\n\t\tDD\t-120\t; Index = 51 Token = 8\n\t\tDD\t-360\t; Index = 51 Token = 9\n\t\tDD\t-601\t; Index = 51 Token = 10\n\t\tDD\t-841\t; Index = 51 Token = 11\n\t\tDD\t-1083\t; Index = 51 Token = 12\n\t\tDD\t-1323\t; Index = 51 Token = 13\n\t\tDD\t-1564\t; Index = 51 Token = 14\n\t\tDD\t-1804\t; Index = 51 Token = 15\n\t\tDD\t132\t; Index = 52 Token = 0\n\t\tDD\t397\t; Index = 52 Token = 1\n\t\tDD\t662\t; Index = 52 Token = 2\n\t\tDD\t927\t; Index = 52 Token = 3\n\t\tDD\t1192\t; Index = 52 Token = 4\n\t\tDD\t1457\t; Index = 52 Token = 5\n\t\tDD\t1722\t; Index = 52 Token = 6\n\t\tDD\t1987\t; Index = 52 Token = 7\n\t\tDD\t-132\t; Index = 52 Token = 8\n\t\tDD\t-397\t; Index = 52 Token = 9\n\t\tDD\t-662\t; Index = 52 Token = 10\n\t\tDD\t-927\t; Index = 52 Token = 11\n\t\tDD\t-1192\t; Index = 52 Token = 12\n\t\tDD\t-1457\t; Index = 52 Token = 13\n\t\tDD\t-1722\t; Index = 52 Token = 14\n\t\tDD\t-1987\t; Index = 52 Token = 15\n\t\tDD\t145\t; Index = 53 Token = 0\n\t\tDD\t436\t; Index = 53 Token = 1\n\t\tDD\t728\t; Index = 53 Token = 2\n\t\tDD\t1019\t; Index = 53 Token = 3\n\t\tDD\t1311\t; Index = 53 Token = 4\n\t\tDD\t1602\t; Index = 53 Token = 5\n\t\tDD\t1894\t; Index = 53 Token = 6\n\t\tDD\t2185\t; Index = 53 Token = 7\n\t\tDD\t-145\t; Index = 53 Token = 8\n\t\tDD\t-436\t; Index = 53 Token = 9\n\t\tDD\t-728\t; Index = 53 Token = 10\n\t\tDD\t-1019\t; Index = 53 Token = 11\n\t\tDD\t-1311\t; Index = 53 Token = 12\n\t\tDD\t-1602\t; Index = 53 Token = 13\n\t\tDD\t-1894\t; Index = 53 Token = 14\n\t\tDD\t-2185\t; Index = 53 Token = 15\n\t\tDD\t160\t; Index = 54 Token = 0\n\t\tDD\t480\t; Index = 54 Token = 1\n\t\tDD\t801\t; Index = 54 Token = 2\n\t\tDD\t1121\t; Index = 54 Token = 3\n\t\tDD\t1442\t; Index = 54 Token = 4\n\t\tDD\t1762\t; Index = 54 Token = 5\n\t\tDD\t2083\t; Index = 54 Token = 6\n\t\tDD\t2403\t; Index = 54 Token = 7\n\t\tDD\t-160\t; Index = 54 Token = 8\n\t\tDD\t-480\t; Index = 54 Token = 9\n\t\tDD\t-801\t; Index = 54 Token = 10\n\t\tDD\t-1121\t; Index = 54 Token = 11\n\t\tDD\t-1442\t; Index = 54 Token = 12\n\t\tDD\t-1762\t; Index = 54 Token = 13\n\t\tDD\t-2083\t; Index = 54 Token = 14\n\t\tDD\t-2403\t; Index = 54 Token = 15\n\t\tDD\t176\t; Index = 55 Token = 0\n\t\tDD\t528\t; Index = 55 Token = 1\n\t\tDD\t881\t; Index = 55 Token = 2\n\t\tDD\t1233\t; Index = 55 Token = 3\n\t\tDD\t1587\t; Index = 55 Token = 4\n\t\tDD\t1939\t; Index = 55 Token = 5\n\t\tDD\t2292\t; Index = 55 Token = 6\n\t\tDD\t2644\t; Index = 55 Token = 7\n\t\tDD\t-176\t; Index = 55 Token = 8\n\t\tDD\t-528\t; Index = 55 Token = 9\n\t\tDD\t-881\t; Index = 55 Token = 10\n\t\tDD\t-1233\t; Index = 55 Token = 11\n\t\tDD\t-1587\t; Index = 55 Token = 12\n\t\tDD\t-1939\t; Index = 55 Token = 13\n\t\tDD\t-2292\t; Index = 55 Token = 14\n\t\tDD\t-2644\t; Index = 55 Token = 15\n\t\tDD\t194\t; Index = 56 Token = 0\n\t\tDD\t582\t; Index = 56 Token = 1\n\t\tDD\t970\t; Index = 56 Token = 2\n\t\tDD\t1358\t; Index = 56 Token = 3\n\t\tDD\t1746\t; Index = 56 Token = 4\n\t\tDD\t2134\t; Index = 56 Token = 5\n\t\tDD\t2522\t; Index = 56 Token = 6\n\t\tDD\t2910\t; Index = 56 Token = 7\n\t\tDD\t-194\t; Index = 56 Token = 8\n\t\tDD\t-582\t; Index = 56 Token = 9\n\t\tDD\t-970\t; Index = 56 Token = 10\n\t\tDD\t-1358\t; Index = 56 Token = 11\n\t\tDD\t-1746\t; Index = 56 Token = 12\n\t\tDD\t-2134\t; Index = 56 Token = 13\n\t\tDD\t-2522\t; Index = 56 Token = 14\n\t\tDD\t-2910\t; Index = 56 Token = 15\n\t\tDD\t213\t; Index = 57 Token = 0\n\t\tDD\t639\t; Index = 57 Token = 1\n\t\tDD\t1066\t; Index = 57 Token = 2\n\t\tDD\t1492\t; Index = 57 Token = 3\n\t\tDD\t1920\t; Index = 57 Token = 4\n\t\tDD\t2346\t; Index = 57 Token = 5\n\t\tDD\t2773\t; Index = 57 Token = 6\n\t\tDD\t3199\t; Index = 57 Token = 7\n\t\tDD\t-213\t; Index = 57 Token = 8\n\t\tDD\t-639\t; Index = 57 Token = 9\n\t\tDD\t-1066\t; Index = 57 Token = 10\n\t\tDD\t-1492\t; Index = 57 Token = 11\n\t\tDD\t-1920\t; Index = 57 Token = 12\n\t\tDD\t-2346\t; Index = 57 Token = 13\n\t\tDD\t-2773\t; Index = 57 Token = 14\n\t\tDD\t-3199\t; Index = 57 Token = 15\n\t\tDD\t234\t; Index = 58 Token = 0\n\t\tDD\t703\t; Index = 58 Token = 1\n\t\tDD\t1173\t; Index = 58 Token = 2\n\t\tDD\t1642\t; Index = 58 Token = 3\n\t\tDD\t2112\t; Index = 58 Token = 4\n\t\tDD\t2581\t; Index = 58 Token = 5\n\t\tDD\t3051\t; Index = 58 Token = 6\n\t\tDD\t3520\t; Index = 58 Token = 7\n\t\tDD\t-234\t; Index = 58 Token = 8\n\t\tDD\t-703\t; Index = 58 Token = 9\n\t\tDD\t-1173\t; Index = 58 Token = 10\n\t\tDD\t-1642\t; Index = 58 Token = 11\n\t\tDD\t-2112\t; Index = 58 Token = 12\n\t\tDD\t-2581\t; Index = 58 Token = 13\n\t\tDD\t-3051\t; Index = 58 Token = 14\n\t\tDD\t-3520\t; Index = 58 Token = 15\n\t\tDD\t258\t; Index = 59 Token = 0\n\t\tDD\t774\t; Index = 59 Token = 1\n\t\tDD\t1291\t; Index = 59 Token = 2\n\t\tDD\t1807\t; Index = 59 Token = 3\n\t\tDD\t2324\t; Index = 59 Token = 4\n\t\tDD\t2840\t; Index = 59 Token = 5\n\t\tDD\t3357\t; Index = 59 Token = 6\n\t\tDD\t3873\t; Index = 59 Token = 7\n\t\tDD\t-258\t; Index = 59 Token = 8\n\t\tDD\t-774\t; Index = 59 Token = 9\n\t\tDD\t-1291\t; Index = 59 Token = 10\n\t\tDD\t-1807\t; Index = 59 Token = 11\n\t\tDD\t-2324\t; Index = 59 Token = 12\n\t\tDD\t-2840\t; Index = 59 Token = 13\n\t\tDD\t-3357\t; Index = 59 Token = 14\n\t\tDD\t-3873\t; Index = 59 Token = 15\n\t\tDD\t284\t; Index = 60 Token = 0\n\t\tDD\t852\t; Index = 60 Token = 1\n\t\tDD\t1420\t; Index = 60 Token = 2\n\t\tDD\t1988\t; Index = 60 Token = 3\n\t\tDD\t2556\t; Index = 60 Token = 4\n\t\tDD\t3124\t; Index = 60 Token = 5\n\t\tDD\t3692\t; Index = 60 Token = 6\n\t\tDD\t4260\t; Index = 60 Token = 7\n\t\tDD\t-284\t; Index = 60 Token = 8\n\t\tDD\t-852\t; Index = 60 Token = 9\n\t\tDD\t-1420\t; Index = 60 Token = 10\n\t\tDD\t-1988\t; Index = 60 Token = 11\n\t\tDD\t-2556\t; Index = 60 Token = 12\n\t\tDD\t-3124\t; Index = 60 Token = 13\n\t\tDD\t-3692\t; Index = 60 Token = 14\n\t\tDD\t-4260\t; Index = 60 Token = 15\n\t\tDD\t312\t; Index = 61 Token = 0\n\t\tDD\t936\t; Index = 61 Token = 1\n\t\tDD\t1561\t; Index = 61 Token = 2\n\t\tDD\t2185\t; Index = 61 Token = 3\n\t\tDD\t2811\t; Index = 61 Token = 4\n\t\tDD\t3435\t; Index = 61 Token = 5\n\t\tDD\t4060\t; Index = 61 Token = 6\n\t\tDD\t4684\t; Index = 61 Token = 7\n\t\tDD\t-312\t; Index = 61 Token = 8\n\t\tDD\t-936\t; Index = 61 Token = 9\n\t\tDD\t-1561\t; Index = 61 Token = 10\n\t\tDD\t-2185\t; Index = 61 Token = 11\n\t\tDD\t-2811\t; Index = 61 Token = 12\n\t\tDD\t-3435\t; Index = 61 Token = 13\n\t\tDD\t-4060\t; Index = 61 Token = 14\n\t\tDD\t-4684\t; Index = 61 Token = 15\n\t\tDD\t343\t; Index = 62 Token = 0\n\t\tDD\t1030\t; Index = 62 Token = 1\n\t\tDD\t1717\t; Index = 62 Token = 2\n\t\tDD\t2404\t; Index = 62 Token = 3\n\t\tDD\t3092\t; Index = 62 Token = 4\n\t\tDD\t3779\t; Index = 62 Token = 5\n\t\tDD\t4466\t; Index = 62 Token = 6\n\t\tDD\t5153\t; Index = 62 Token = 7\n\t\tDD\t-343\t; Index = 62 Token = 8\n\t\tDD\t-1030\t; Index = 62 Token = 9\n\t\tDD\t-1717\t; Index = 62 Token = 10\n\t\tDD\t-2404\t; Index = 62 Token = 11\n\t\tDD\t-3092\t; Index = 62 Token = 12\n\t\tDD\t-3779\t; Index = 62 Token = 13\n\t\tDD\t-4466\t; Index = 62 Token = 14\n\t\tDD\t-5153\t; Index = 62 Token = 15\n\t\tDD\t378\t; Index = 63 Token = 0\n\t\tDD\t1134\t; Index = 63 Token = 1\n\t\tDD\t1890\t; Index = 63 Token = 2\n\t\tDD\t2646\t; Index = 63 Token = 3\n\t\tDD\t3402\t; Index = 63 Token = 4\n\t\tDD\t4158\t; Index = 63 Token = 5\n\t\tDD\t4914\t; Index = 63 Token = 6\n\t\tDD\t5670\t; Index = 63 Token = 7\n\t\tDD\t-378\t; Index = 63 Token = 8\n\t\tDD\t-1134\t; Index = 63 Token = 9\n\t\tDD\t-1890\t; Index = 63 Token = 10\n\t\tDD\t-2646\t; Index = 63 Token = 11\n\t\tDD\t-3402\t; Index = 63 Token = 12\n\t\tDD\t-4158\t; Index = 63 Token = 13\n\t\tDD\t-4914\t; Index = 63 Token = 14\n\t\tDD\t-5670\t; Index = 63 Token = 15\n\t\tDD\t415\t; Index = 64 Token = 0\n\t\tDD\t1246\t; Index = 64 Token = 1\n\t\tDD\t2078\t; Index = 64 Token = 2\n\t\tDD\t2909\t; Index = 64 Token = 3\n\t\tDD\t3742\t; Index = 64 Token = 4\n\t\tDD\t4573\t; Index = 64 Token = 5\n\t\tDD\t5405\t; Index = 64 Token = 6\n\t\tDD\t6236\t; Index = 64 Token = 7\n\t\tDD\t-415\t; Index = 64 Token = 8\n\t\tDD\t-1246\t; Index = 64 Token = 9\n\t\tDD\t-2078\t; Index = 64 Token = 10\n\t\tDD\t-2909\t; Index = 64 Token = 11\n\t\tDD\t-3742\t; Index = 64 Token = 12\n\t\tDD\t-4573\t; Index = 64 Token = 13\n\t\tDD\t-5405\t; Index = 64 Token = 14\n\t\tDD\t-6236\t; Index = 64 Token = 15\n\t\tDD\t457\t; Index = 65 Token = 0\n\t\tDD\t1372\t; Index = 65 Token = 1\n\t\tDD\t2287\t; Index = 65 Token = 2\n\t\tDD\t3202\t; Index = 65 Token = 3\n\t\tDD\t4117\t; Index = 65 Token = 4\n\t\tDD\t5032\t; Index = 65 Token = 5\n\t\tDD\t5947\t; Index = 65 Token = 6\n\t\tDD\t6862\t; Index = 65 Token = 7\n\t\tDD\t-457\t; Index = 65 Token = 8\n\t\tDD\t-1372\t; Index = 65 Token = 9\n\t\tDD\t-2287\t; Index = 65 Token = 10\n\t\tDD\t-3202\t; Index = 65 Token = 11\n\t\tDD\t-4117\t; Index = 65 Token = 12\n\t\tDD\t-5032\t; Index = 65 Token = 13\n\t\tDD\t-5947\t; Index = 65 Token = 14\n\t\tDD\t-6862\t; Index = 65 Token = 15\n\t\tDD\t503\t; Index = 66 Token = 0\n\t\tDD\t1509\t; Index = 66 Token = 1\n\t\tDD\t2516\t; Index = 66 Token = 2\n\t\tDD\t3522\t; Index = 66 Token = 3\n\t\tDD\t4529\t; Index = 66 Token = 4\n\t\tDD\t5535\t; Index = 66 Token = 5\n\t\tDD\t6542\t; Index = 66 Token = 6\n\t\tDD\t7548\t; Index = 66 Token = 7\n\t\tDD\t-503\t; Index = 66 Token = 8\n\t\tDD\t-1509\t; Index = 66 Token = 9\n\t\tDD\t-2516\t; Index = 66 Token = 10\n\t\tDD\t-3522\t; Index = 66 Token = 11\n\t\tDD\t-4529\t; Index = 66 Token = 12\n\t\tDD\t-5535\t; Index = 66 Token = 13\n\t\tDD\t-6542\t; Index = 66 Token = 14\n\t\tDD\t-7548\t; Index = 66 Token = 15\n\t\tDD\t553\t; Index = 67 Token = 0\n\t\tDD\t1660\t; Index = 67 Token = 1\n\t\tDD\t2767\t; Index = 67 Token = 2\n\t\tDD\t3874\t; Index = 67 Token = 3\n\t\tDD\t4981\t; Index = 67 Token = 4\n\t\tDD\t6088\t; Index = 67 Token = 5\n\t\tDD\t7195\t; Index = 67 Token = 6\n\t\tDD\t8302\t; Index = 67 Token = 7\n\t\tDD\t-553\t; Index = 67 Token = 8\n\t\tDD\t-1660\t; Index = 67 Token = 9\n\t\tDD\t-2767\t; Index = 67 Token = 10\n\t\tDD\t-3874\t; Index = 67 Token = 11\n\t\tDD\t-4981\t; Index = 67 Token = 12\n\t\tDD\t-6088\t; Index = 67 Token = 13\n\t\tDD\t-7195\t; Index = 67 Token = 14\n\t\tDD\t-8302\t; Index = 67 Token = 15\n\t\tDD\t608\t; Index = 68 Token = 0\n\t\tDD\t1825\t; Index = 68 Token = 1\n\t\tDD\t3043\t; Index = 68 Token = 2\n\t\tDD\t4260\t; Index = 68 Token = 3\n\t\tDD\t5479\t; Index = 68 Token = 4\n\t\tDD\t6696\t; Index = 68 Token = 5\n\t\tDD\t7914\t; Index = 68 Token = 6\n\t\tDD\t9131\t; Index = 68 Token = 7\n\t\tDD\t-608\t; Index = 68 Token = 8\n\t\tDD\t-1825\t; Index = 68 Token = 9\n\t\tDD\t-3043\t; Index = 68 Token = 10\n\t\tDD\t-4260\t; Index = 68 Token = 11\n\t\tDD\t-5479\t; Index = 68 Token = 12\n\t\tDD\t-6696\t; Index = 68 Token = 13\n\t\tDD\t-7914\t; Index = 68 Token = 14\n\t\tDD\t-9131\t; Index = 68 Token = 15\n\t\tDD\t669\t; Index = 69 Token = 0\n\t\tDD\t2008\t; Index = 69 Token = 1\n\t\tDD\t3348\t; Index = 69 Token = 2\n\t\tDD\t4687\t; Index = 69 Token = 3\n\t\tDD\t6027\t; Index = 69 Token = 4\n\t\tDD\t7366\t; Index = 69 Token = 5\n\t\tDD\t8706\t; Index = 69 Token = 6\n\t\tDD\t10045\t; Index = 69 Token = 7\n\t\tDD\t-669\t; Index = 69 Token = 8\n\t\tDD\t-2008\t; Index = 69 Token = 9\n\t\tDD\t-3348\t; Index = 69 Token = 10\n\t\tDD\t-4687\t; Index = 69 Token = 11\n\t\tDD\t-6027\t; Index = 69 Token = 12\n\t\tDD\t-7366\t; Index = 69 Token = 13\n\t\tDD\t-8706\t; Index = 69 Token = 14\n\t\tDD\t-10045\t; Index = 69 Token = 15\n\t\tDD\t736\t; Index = 70 Token = 0\n\t\tDD\t2209\t; Index = 70 Token = 1\n\t\tDD\t3683\t; Index = 70 Token = 2\n\t\tDD\t5156\t; Index = 70 Token = 3\n\t\tDD\t6630\t; Index = 70 Token = 4\n\t\tDD\t8103\t; Index = 70 Token = 5\n\t\tDD\t9577\t; Index = 70 Token = 6\n\t\tDD\t11050\t; Index = 70 Token = 7\n\t\tDD\t-736\t; Index = 70 Token = 8\n\t\tDD\t-2209\t; Index = 70 Token = 9\n\t\tDD\t-3683\t; Index = 70 Token = 10\n\t\tDD\t-5156\t; Index = 70 Token = 11\n\t\tDD\t-6630\t; Index = 70 Token = 12\n\t\tDD\t-8103\t; Index = 70 Token = 13\n\t\tDD\t-9577\t; Index = 70 Token = 14\n\t\tDD\t-11050\t; Index = 70 Token = 15\n\t\tDD\t810\t; Index = 71 Token = 0\n\t\tDD\t2431\t; Index = 71 Token = 1\n\t\tDD\t4052\t; Index = 71 Token = 2\n\t\tDD\t5673\t; Index = 71 Token = 3\n\t\tDD\t7294\t; Index = 71 Token = 4\n\t\tDD\t8915\t; Index = 71 Token = 5\n\t\tDD\t10536\t; Index = 71 Token = 6\n\t\tDD\t12157\t; Index = 71 Token = 7\n\t\tDD\t-810\t; Index = 71 Token = 8\n\t\tDD\t-2431\t; Index = 71 Token = 9\n\t\tDD\t-4052\t; Index = 71 Token = 10\n\t\tDD\t-5673\t; Index = 71 Token = 11\n\t\tDD\t-7294\t; Index = 71 Token = 12\n\t\tDD\t-8915\t; Index = 71 Token = 13\n\t\tDD\t-10536\t; Index = 71 Token = 14\n\t\tDD\t-12157\t; Index = 71 Token = 15\n\t\tDD\t891\t; Index = 72 Token = 0\n\t\tDD\t2674\t; Index = 72 Token = 1\n\t\tDD\t4457\t; Index = 72 Token = 2\n\t\tDD\t6240\t; Index = 72 Token = 3\n\t\tDD\t8023\t; Index = 72 Token = 4\n\t\tDD\t9806\t; Index = 72 Token = 5\n\t\tDD\t11589\t; Index = 72 Token = 6\n\t\tDD\t13372\t; Index = 72 Token = 7\n\t\tDD\t-891\t; Index = 72 Token = 8\n\t\tDD\t-2674\t; Index = 72 Token = 9\n\t\tDD\t-4457\t; Index = 72 Token = 10\n\t\tDD\t-6240\t; Index = 72 Token = 11\n\t\tDD\t-8023\t; Index = 72 Token = 12\n\t\tDD\t-9806\t; Index = 72 Token = 13\n\t\tDD\t-11589\t; Index = 72 Token = 14\n\t\tDD\t-13372\t; Index = 72 Token = 15\n\t\tDD\t980\t; Index = 73 Token = 0\n\t\tDD\t2941\t; Index = 73 Token = 1\n\t\tDD\t4902\t; Index = 73 Token = 2\n\t\tDD\t6863\t; Index = 73 Token = 3\n\t\tDD\t8825\t; Index = 73 Token = 4\n\t\tDD\t10786\t; Index = 73 Token = 5\n\t\tDD\t12747\t; Index = 73 Token = 6\n\t\tDD\t14708\t; Index = 73 Token = 7\n\t\tDD\t-980\t; Index = 73 Token = 8\n\t\tDD\t-2941\t; Index = 73 Token = 9\n\t\tDD\t-4902\t; Index = 73 Token = 10\n\t\tDD\t-6863\t; Index = 73 Token = 11\n\t\tDD\t-8825\t; Index = 73 Token = 12\n\t\tDD\t-10786\t; Index = 73 Token = 13\n\t\tDD\t-12747\t; Index = 73 Token = 14\n\t\tDD\t-14708\t; Index = 73 Token = 15\n\t\tDD\t1078\t; Index = 74 Token = 0\n\t\tDD\t3235\t; Index = 74 Token = 1\n\t\tDD\t5393\t; Index = 74 Token = 2\n\t\tDD\t7550\t; Index = 74 Token = 3\n\t\tDD\t9708\t; Index = 74 Token = 4\n\t\tDD\t11865\t; Index = 74 Token = 5\n\t\tDD\t14023\t; Index = 74 Token = 6\n\t\tDD\t16180\t; Index = 74 Token = 7\n\t\tDD\t-1078\t; Index = 74 Token = 8\n\t\tDD\t-3235\t; Index = 74 Token = 9\n\t\tDD\t-5393\t; Index = 74 Token = 10\n\t\tDD\t-7550\t; Index = 74 Token = 11\n\t\tDD\t-9708\t; Index = 74 Token = 12\n\t\tDD\t-11865\t; Index = 74 Token = 13\n\t\tDD\t-14023\t; Index = 74 Token = 14\n\t\tDD\t-16180\t; Index = 74 Token = 15\n\t\tDD\t1186\t; Index = 75 Token = 0\n\t\tDD\t3559\t; Index = 75 Token = 1\n\t\tDD\t5932\t; Index = 75 Token = 2\n\t\tDD\t8305\t; Index = 75 Token = 3\n\t\tDD\t10679\t; Index = 75 Token = 4\n\t\tDD\t13052\t; Index = 75 Token = 5\n\t\tDD\t15425\t; Index = 75 Token = 6\n\t\tDD\t17798\t; Index = 75 Token = 7\n\t\tDD\t-1186\t; Index = 75 Token = 8\n\t\tDD\t-3559\t; Index = 75 Token = 9\n\t\tDD\t-5932\t; Index = 75 Token = 10\n\t\tDD\t-8305\t; Index = 75 Token = 11\n\t\tDD\t-10679\t; Index = 75 Token = 12\n\t\tDD\t-13052\t; Index = 75 Token = 13\n\t\tDD\t-15425\t; Index = 75 Token = 14\n\t\tDD\t-17798\t; Index = 75 Token = 15\n\t\tDD\t1305\t; Index = 76 Token = 0\n\t\tDD\t3915\t; Index = 76 Token = 1\n\t\tDD\t6526\t; Index = 76 Token = 2\n\t\tDD\t9136\t; Index = 76 Token = 3\n\t\tDD\t11747\t; Index = 76 Token = 4\n\t\tDD\t14357\t; Index = 76 Token = 5\n\t\tDD\t16968\t; Index = 76 Token = 6\n\t\tDD\t19578\t; Index = 76 Token = 7\n\t\tDD\t-1305\t; Index = 76 Token = 8\n\t\tDD\t-3915\t; Index = 76 Token = 9\n\t\tDD\t-6526\t; Index = 76 Token = 10\n\t\tDD\t-9136\t; Index = 76 Token = 11\n\t\tDD\t-11747\t; Index = 76 Token = 12\n\t\tDD\t-14357\t; Index = 76 Token = 13\n\t\tDD\t-16968\t; Index = 76 Token = 14\n\t\tDD\t-19578\t; Index = 76 Token = 15\n\t\tDD\t1435\t; Index = 77 Token = 0\n\t\tDD\t4306\t; Index = 77 Token = 1\n\t\tDD\t7178\t; Index = 77 Token = 2\n\t\tDD\t10049\t; Index = 77 Token = 3\n\t\tDD\t12922\t; Index = 77 Token = 4\n\t\tDD\t15793\t; Index = 77 Token = 5\n\t\tDD\t18665\t; Index = 77 Token = 6\n\t\tDD\t21536\t; Index = 77 Token = 7\n\t\tDD\t-1435\t; Index = 77 Token = 8\n\t\tDD\t-4306\t; Index = 77 Token = 9\n\t\tDD\t-7178\t; Index = 77 Token = 10\n\t\tDD\t-10049\t; Index = 77 Token = 11\n\t\tDD\t-12922\t; Index = 77 Token = 12\n\t\tDD\t-15793\t; Index = 77 Token = 13\n\t\tDD\t-18665\t; Index = 77 Token = 14\n\t\tDD\t-21536\t; Index = 77 Token = 15\n\t\tDD\t1579\t; Index = 78 Token = 0\n\t\tDD\t4737\t; Index = 78 Token = 1\n\t\tDD\t7896\t; Index = 78 Token = 2\n\t\tDD\t11054\t; Index = 78 Token = 3\n\t\tDD\t14214\t; Index = 78 Token = 4\n\t\tDD\t17372\t; Index = 78 Token = 5\n\t\tDD\t20531\t; Index = 78 Token = 6\n\t\tDD\t23689\t; Index = 78 Token = 7\n\t\tDD\t-1579\t; Index = 78 Token = 8\n\t\tDD\t-4737\t; Index = 78 Token = 9\n\t\tDD\t-7896\t; Index = 78 Token = 10\n\t\tDD\t-11054\t; Index = 78 Token = 11\n\t\tDD\t-14214\t; Index = 78 Token = 12\n\t\tDD\t-17372\t; Index = 78 Token = 13\n\t\tDD\t-20531\t; Index = 78 Token = 14\n\t\tDD\t-23689\t; Index = 78 Token = 15\n\t\tDD\t1737\t; Index = 79 Token = 0\n\t\tDD\t5211\t; Index = 79 Token = 1\n\t\tDD\t8686\t; Index = 79 Token = 2\n\t\tDD\t12160\t; Index = 79 Token = 3\n\t\tDD\t15636\t; Index = 79 Token = 4\n\t\tDD\t19110\t; Index = 79 Token = 5\n\t\tDD\t22585\t; Index = 79 Token = 6\n\t\tDD\t26059\t; Index = 79 Token = 7\n\t\tDD\t-1737\t; Index = 79 Token = 8\n\t\tDD\t-5211\t; Index = 79 Token = 9\n\t\tDD\t-8686\t; Index = 79 Token = 10\n\t\tDD\t-12160\t; Index = 79 Token = 11\n\t\tDD\t-15636\t; Index = 79 Token = 12\n\t\tDD\t-19110\t; Index = 79 Token = 13\n\t\tDD\t-22585\t; Index = 79 Token = 14\n\t\tDD\t-26059\t; Index = 79 Token = 15\n\t\tDD\t1911\t; Index = 80 Token = 0\n\t\tDD\t5733\t; Index = 80 Token = 1\n\t\tDD\t9555\t; Index = 80 Token = 2\n\t\tDD\t13377\t; Index = 80 Token = 3\n\t\tDD\t17200\t; Index = 80 Token = 4\n\t\tDD\t21022\t; Index = 80 Token = 5\n\t\tDD\t24844\t; Index = 80 Token = 6\n\t\tDD\t28666\t; Index = 80 Token = 7\n\t\tDD\t-1911\t; Index = 80 Token = 8\n\t\tDD\t-5733\t; Index = 80 Token = 9\n\t\tDD\t-9555\t; Index = 80 Token = 10\n\t\tDD\t-13377\t; Index = 80 Token = 11\n\t\tDD\t-17200\t; Index = 80 Token = 12\n\t\tDD\t-21022\t; Index = 80 Token = 13\n\t\tDD\t-24844\t; Index = 80 Token = 14\n\t\tDD\t-28666\t; Index = 80 Token = 15\n\t\tDD\t2102\t; Index = 81 Token = 0\n\t\tDD\t6306\t; Index = 81 Token = 1\n\t\tDD\t10511\t; Index = 81 Token = 2\n\t\tDD\t14715\t; Index = 81 Token = 3\n\t\tDD\t18920\t; Index = 81 Token = 4\n\t\tDD\t23124\t; Index = 81 Token = 5\n\t\tDD\t27329\t; Index = 81 Token = 6\n\t\tDD\t31533\t; Index = 81 Token = 7\n\t\tDD\t-2102\t; Index = 81 Token = 8\n\t\tDD\t-6306\t; Index = 81 Token = 9\n\t\tDD\t-10511\t; Index = 81 Token = 10\n\t\tDD\t-14715\t; Index = 81 Token = 11\n\t\tDD\t-18920\t; Index = 81 Token = 12\n\t\tDD\t-23124\t; Index = 81 Token = 13\n\t\tDD\t-27329\t; Index = 81 Token = 14\n\t\tDD\t-31533\t; Index = 81 Token = 15\n\t\tDD\t2312\t; Index = 82 Token = 0\n\t\tDD\t6937\t; Index = 82 Token = 1\n\t\tDD\t11562\t; Index = 82 Token = 2\n\t\tDD\t16187\t; Index = 82 Token = 3\n\t\tDD\t20812\t; Index = 82 Token = 4\n\t\tDD\t25437\t; Index = 82 Token = 5\n\t\tDD\t30062\t; Index = 82 Token = 6\n\t\tDD\t34687\t; Index = 82 Token = 7\n\t\tDD\t-2312\t; Index = 82 Token = 8\n\t\tDD\t-6937\t; Index = 82 Token = 9\n\t\tDD\t-11562\t; Index = 82 Token = 10\n\t\tDD\t-16187\t; Index = 82 Token = 11\n\t\tDD\t-20812\t; Index = 82 Token = 12\n\t\tDD\t-25437\t; Index = 82 Token = 13\n\t\tDD\t-30062\t; Index = 82 Token = 14\n\t\tDD\t-34687\t; Index = 82 Token = 15\n\t\tDD\t2543\t; Index = 83 Token = 0\n\t\tDD\t7630\t; Index = 83 Token = 1\n\t\tDD\t12718\t; Index = 83 Token = 2\n\t\tDD\t17805\t; Index = 83 Token = 3\n\t\tDD\t22893\t; Index = 83 Token = 4\n\t\tDD\t27980\t; Index = 83 Token = 5\n\t\tDD\t33068\t; Index = 83 Token = 6\n\t\tDD\t38155\t; Index = 83 Token = 7\n\t\tDD\t-2543\t; Index = 83 Token = 8\n\t\tDD\t-7630\t; Index = 83 Token = 9\n\t\tDD\t-12718\t; Index = 83 Token = 10\n\t\tDD\t-17805\t; Index = 83 Token = 11\n\t\tDD\t-22893\t; Index = 83 Token = 12\n\t\tDD\t-27980\t; Index = 83 Token = 13\n\t\tDD\t-33068\t; Index = 83 Token = 14\n\t\tDD\t-38155\t; Index = 83 Token = 15\n\t\tDD\t2798\t; Index = 84 Token = 0\n\t\tDD\t8394\t; Index = 84 Token = 1\n\t\tDD\t13990\t; Index = 84 Token = 2\n\t\tDD\t19586\t; Index = 84 Token = 3\n\t\tDD\t25183\t; Index = 84 Token = 4\n\t\tDD\t30779\t; Index = 84 Token = 5\n\t\tDD\t36375\t; Index = 84 Token = 6\n\t\tDD\t41971\t; Index = 84 Token = 7\n\t\tDD\t-2798\t; Index = 84 Token = 8\n\t\tDD\t-8394\t; Index = 84 Token = 9\n\t\tDD\t-13990\t; Index = 84 Token = 10\n\t\tDD\t-19586\t; Index = 84 Token = 11\n\t\tDD\t-25183\t; Index = 84 Token = 12\n\t\tDD\t-30779\t; Index = 84 Token = 13\n\t\tDD\t-36375\t; Index = 84 Token = 14\n\t\tDD\t-41971\t; Index = 84 Token = 15\n\t\tDD\t3077\t; Index = 85 Token = 0\n\t\tDD\t9232\t; Index = 85 Token = 1\n\t\tDD\t15388\t; Index = 85 Token = 2\n\t\tDD\t21543\t; Index = 85 Token = 3\n\t\tDD\t27700\t; Index = 85 Token = 4\n\t\tDD\t33855\t; Index = 85 Token = 5\n\t\tDD\t40011\t; Index = 85 Token = 6\n\t\tDD\t46166\t; Index = 85 Token = 7\n\t\tDD\t-3077\t; Index = 85 Token = 8\n\t\tDD\t-9232\t; Index = 85 Token = 9\n\t\tDD\t-15388\t; Index = 85 Token = 10\n\t\tDD\t-21543\t; Index = 85 Token = 11\n\t\tDD\t-27700\t; Index = 85 Token = 12\n\t\tDD\t-33855\t; Index = 85 Token = 13\n\t\tDD\t-40011\t; Index = 85 Token = 14\n\t\tDD\t-46166\t; Index = 85 Token = 15\n\t\tDD\t3385\t; Index = 86 Token = 0\n\t\tDD\t10156\t; Index = 86 Token = 1\n\t\tDD\t16928\t; Index = 86 Token = 2\n\t\tDD\t23699\t; Index = 86 Token = 3\n\t\tDD\t30471\t; Index = 86 Token = 4\n\t\tDD\t37242\t; Index = 86 Token = 5\n\t\tDD\t44014\t; Index = 86 Token = 6\n\t\tDD\t50785\t; Index = 86 Token = 7\n\t\tDD\t-3385\t; Index = 86 Token = 8\n\t\tDD\t-10156\t; Index = 86 Token = 9\n\t\tDD\t-16928\t; Index = 86 Token = 10\n\t\tDD\t-23699\t; Index = 86 Token = 11\n\t\tDD\t-30471\t; Index = 86 Token = 12\n\t\tDD\t-37242\t; Index = 86 Token = 13\n\t\tDD\t-44014\t; Index = 86 Token = 14\n\t\tDD\t-50785\t; Index = 86 Token = 15\n\t\tDD\t3724\t; Index = 87 Token = 0\n\t\tDD\t11172\t; Index = 87 Token = 1\n\t\tDD\t18621\t; Index = 87 Token = 2\n\t\tDD\t26069\t; Index = 87 Token = 3\n\t\tDD\t33518\t; Index = 87 Token = 4\n\t\tDD\t40966\t; Index = 87 Token = 5\n\t\tDD\t48415\t; Index = 87 Token = 6\n\t\tDD\t55863\t; Index = 87 Token = 7\n\t\tDD\t-3724\t; Index = 87 Token = 8\n\t\tDD\t-11172\t; Index = 87 Token = 9\n\t\tDD\t-18621\t; Index = 87 Token = 10\n\t\tDD\t-26069\t; Index = 87 Token = 11\n\t\tDD\t-33518\t; Index = 87 Token = 12\n\t\tDD\t-40966\t; Index = 87 Token = 13\n\t\tDD\t-48415\t; Index = 87 Token = 14\n\t\tDD\t-55863\t; Index = 87 Token = 15\n\t\tDD\t4095\t; Index = 88 Token = 0\n\t\tDD\t12286\t; Index = 88 Token = 1\n\t\tDD\t20478\t; Index = 88 Token = 2\n\t\tDD\t28669\t; Index = 88 Token = 3\n\t\tDD\t36862\t; Index = 88 Token = 4\n\t\tDD\t45053\t; Index = 88 Token = 5\n\t\tDD\t53245\t; Index = 88 Token = 6\n\t\tDD\t61436\t; Index = 88 Token = 7\n\t\tDD\t-4095\t; Index = 88 Token = 8\n\t\tDD\t-12286\t; Index = 88 Token = 9\n\t\tDD\t-20478\t; Index = 88 Token = 10\n\t\tDD\t-28669\t; Index = 88 Token = 11\n\t\tDD\t-36862\t; Index = 88 Token = 12\n\t\tDD\t-45053\t; Index = 88 Token = 13\n\t\tDD\t-53245\t; Index = 88 Token = 14\n\t\tDD\t-61436\t; Index = 88 Token = 15\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/DIPTHONG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\nint Dip_Text(char const *source, char *dest);\nint UnDip_Text(char const *source, char *dest);\nchar *Extract_String(void const *data, int string);\nvoid Fixup_Text(char const *source, char *dest);\nextern char Common[];\nextern char Dipthong[16][8];\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/FILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library - Filio header stuff.            *\n *                                                                         *\n *                    File Name : FILE.H                                 \t*\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : September 13, 1993                       *\n *                                                                         *\n *                  Last Update : April 11, 1994\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FILE_H\n#define FILE_H\n\n\n#ifndef ERROR\n#define\tERROR\t-1\n#endif\n\n#ifndef FILETEMP_H\n// This should be removed once the library is all intacked.\n#include \"filetemp.h\"\n#endif\n\n/*=========================================================================*/\n/* File IO system defines and enumerations\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#define\tXMAXPATH\t80\n\n/*\n**\tThese are the Open_File, Read_File, and Seek_File constants.\n*/\n#define READ\t\t\t\t\t\t1\t// Read access.\n#define WRITE\t\t\t\t\t\t2\t// Write access.\n#ifndef SEEK_SET\n#define SEEK_SET\t\t\t\t\t0\t// Seek from start of file.\n#define SEEK_CUR\t\t\t\t\t1\t// Seek relative from current location.\n#define SEEK_END\t\t\t\t\t2\t// Seek from end of file.\n#endif\n\n\ntypedef enum {\n\tFILEB_PROCESSED=8,// Was the packed file header of this file processed?\n\tFILEB_PRELOAD,\t\t// Scan for and make file resident at WWDOS_Init time?\n\tFILEB_RESIDENT,\t// Make resident at Open_File time?\n\tFILEB_FLUSH,\t\t// Un-resident at Close_File time?\n\tFILEB_PACKED,\t\t// Is this file packed?\n\tFILEB_KEEP,\t\t\t// Don't ever flush this resident file?\n\tFILEB_PRIORITY,\t// Flush this file last?\n\n\tFILEB_LAST\n} FileFlags_Type;\n\n#define\tFILEF_NONE\t\t\t0\n#define\tFILEF_PROCESSED\t(1<<FILEB_PROCESSED)\n#define\tFILEF_PRELOAD\t\t(1<<FILEB_PRELOAD)\n#define\tFILEF_RESIDENT\t\t(1<<FILEB_RESIDENT)\n#define\tFILEF_FLUSH\t\t\t(1<<FILEB_FLUSH)\n#define\tFILEF_PACKED\t\t(1<<FILEB_PACKED)\n#define\tFILEF_KEEP\t\t\t(1<<FILEB_KEEP)\n#define\tFILEF_PRIORITY\t\t(1<<FILEB_PRIORITY)\n\n/*\n** These errors are returned by WWDOS_Init().  All errors encountered are\n** or'd together so there may be more then one error returned.  Not all\n** errors are fatal, such as the cache errors.\n*/\ntypedef enum {\n\tFI_SUCCESS\t\t\t\t\t\t= 0x00,\n\tFI_CACHE_TOO_BIG\t\t\t\t= 0x01,\n\tFI_CACHE_ALREADY_INIT\t\t= 0x02,\n\tFI_FILEDATA_FILE_NOT_FOUND\t= 0x04,\n\tFI_FILEDATA_TOO_BIG\t\t\t= 0x08,\n \tFI_SEARCH_PATH_NOT_FOUND\t= 0x10,\n \tFI_STARTUP_PATH_NOT_FOUND\t= 0x20,\n\tFI_NO_CACHE_FOR_PRELOAD\t\t= 0x40,\n\tFI_FILETABLE_NOT_INIT\t\t= 0x80,\n} FileInitErrorType;\n\n\n/*\n**\tThese are the errors that are detected by the File I/O system and\n**\tpassed to the io error routine.\n*/\n//lint -strong(AJX,FileErrorType)\ntypedef enum {\n\tCANT_CREATE_FILE,\n\tBAD_OPEN_MODE,\n\tCOULD_NOT_OPEN,\n\tTOO_MANY_FILES,\n\tCLOSING_NON_HANDLE,\n\tREADING_NON_HANDLE,\n\tWRITING_NON_HANDLE,\n\tSEEKING_NON_HANDLE,\n\tSEEKING_BAD_OFFSET,\n\tWRITING_RESIDENT,\n\tUNKNOWN_INDEX,\n\tDID_NOT_CLOSE,\n\tFATAL_ERROR,\n\tFILE_NOT_LISTED,\n\tFILE_LENGTH_MISMATCH,\n\tINTERNAL_ERROR,\n\tMAKE_RESIDENT_ZERO_SIZE,\n\tRESIDENT_SORT_FAILURE,\n\n\tNUMBER_OF_ERRORS\t\t\t\t/* MAKE SURE THIS IS THE LAST ENTRY */\n} FileErrorType;\n\n// This is here tempararaly until library is put together.\n//extern WORD cdecl (*cdecl IO_Error)(FileErrorType error, BYTE const *filename);\nextern short (*Open_Error)(FileErrorType, BYTE const *);\n\n/*=========================================================================*/\n/* File IO system structures\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//lint -strong(AJX,FileDataType)\ntypedef struct {\n\tchar\t*Name;\t\t// File name (include sub-directory but not volume).\n\tlong\tSize;\t\t\t// File size (0=indeterminate).\n\tvoid\t*Ptr;\t\t\t// Resident file pointer.\n\tlong\tStart;\t\t// Starting offset in DOS handle file.\n\tunsigned char\tDisk;\t\t\t// Disk number location.\n\tunsigned char\tOpenCount;\t// Count of open locks on resident file.\n\tunsigned short\tFlag;\t\t\t// File control flags.\n} FileDataType;\n\n\n/*=========================================================================*/\n/* FIle IO system globals.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n// These are cpp errors in funtions declarations\tJULIO JEREZ\n\n// extern FileDataType cdecl FileData[];\n// extern BYTE cdecl ExecPath[XMAXPATH + 1];\n// extern BYTE cdecl DataPath[XMAXPATH + 1];\n// extern BYTE cdecl StartPath[XMAXPATH + 1];\n// extern BOOL cdecl UseCD;\n\n// The correct syntax is  NO TYPE MODIFIER APPLY TO DATA DECLARATIONS\nextern FileDataType FileData[];\nextern char ExecPath[XMAXPATH + 1];\nextern char DataPath[XMAXPATH + 1];\nextern char StartPath[XMAXPATH + 1];\nextern BOOL UseCD;\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILEINIT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid cdecl WWDOS_Shutdown(void);\nFileInitErrorType cdecl WWDOS_Init(unsigned long cachesize, char *filedata, char *cdpath);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILE.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint cdecl Open_File(char const *file_name, int mode);\nvoid cdecl Close_File(int handle);\nlong cdecl Read_File(int handle, void *buf, unsigned long bytes);\nlong cdecl Write_File(int handle, void const *buf, unsigned long bytes);\nunsigned long cdecl Seek_File(int handle, long offset, int starting);\nint cdecl File_Exists(char const *file_name);\nunsigned long cdecl File_Size(int handle);\nBOOL cdecl Is_Handle_Valid(int handle, FileErrorType error, char const *name);\nint cdecl Open_File_With_Recovery( char const *file_name, unsigned int mode );\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILECACH.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid Unfragment_File_Cache(void);\nBOOL cdecl Make_File_Resident(char const *filename);\nshort cdecl Flush_Unused_File_Cache(short flush_keeps);\nBOOL cdecl Free_Resident_File(char const *file);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILECHNG.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort cdecl Create_File(char const *file_name);\nshort cdecl Delete_File(char const *file_name);\nBOOL cdecl Change_File_Size(short handle, unsigned long new_size);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILEINFO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort cdecl Get_DOS_Handle(short fh);\nshort cdecl Free_Handles(void);\nshort cdecl Find_Disk_Number(char const *file_name);\nshort cdecl Set_File_Flags(char const *filename, short flags);\nshort cdecl Clear_File_Flags(char const *filename, short flags);\nshort cdecl Get_File_Flags(char const *filename);\nBOOL cdecl Multi_Drive_Search(BOOL on);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FINDFILE.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint cdecl Find_File(char const *file_name);\nint cdecl Find_File_Index(char const *filename);\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FFIRST.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#include <dos.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern short Find_First(unsigned char *fname, unsigned short mode, struct find_t *ffblk);\nextern short Find_Next(struct find_t *ffblk);\n\n#ifdef __cplusplus\n}\n#endif\n\n\n\n\n#endif // FILE_H\n\u001a\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/FILEPCX.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : iff                                      *\n;*                                                                         *\n;*                    File Name : FILEPCX.H                                *\n;*                                                                         *\n;*                   Programmer : Julio R. Jerez                           *\n;*                                                                         *\n;*                   Start Date : May 2, 1995                              *\n;*                                                                         *\n;*                  Last Update : May 2, 1995   [JRJ]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* GraphicBufferClass* Read_PCX_File (char* name, BYTE* palette,void *buff, long size);\n;* GraphicBufferClass* Read_PCX_File (char* name, BYTE* palette, BufferClass& Buff); \n;* int Write_PCX_File (char* name, GraphicViewPortClass& pic, BYTE* palette );*\n;*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n#include <string.h>\n#include <buffer.h>\n#include <gbuffer.h>\n#include\t<file.h>\n\n#ifndef PCX_H\n#define PCX_H\n\n\ntypedef\tstruct {\n\t\t\t\t\t\t  char\tred ;\n\t\t\t\t\t\t  char\tgreen ;\n\t\t\t\t\t\t  char\tblue ;\n\t\t\t\t\t} RGB ;\n\ntypedef\tstruct\t{\n\t\t\t\t\t\t  char      id ;\n\t\t\t\t\t\t  char\t   version ;\n\t\t\t\t\t\t  char\t   encoding ;\n\t\t\t\t\t\t  char\t   pixelsize ;\n\t\t\t\t\t\t  short \t   x ;\n\t\t\t\t\t\t  short\t\ty ;\n\t\t\t\t\t\t  short     width ;\n\t\t\t\t\t\t  short\t\theight ;\n\t\t\t\t\t\t  short \t   xres ;\n\t\t\t\t\t\t  short\t\tyres ;\n\t\t\t\t\t\t  RGB       ega_palette [ 16 ] ;\n\t\t\t\t\t\t  char\t   nothing ;\n\t\t\t\t\t\t  char      color_planes ;\n\t\t\t\t\t\t  short \t\tbyte_per_line ;\n\t\t\t\t\t\t  short \t \tpalette_type ;\n\t\t\t\t\t\t  char\t   filler [ 58 ] ;\n\t\t\t\t\t\t} PCX_HEADER ;\n\nGraphicBufferClass* Read_PCX_File (char* name, BYTE* palette= NULL,void *buff=NULL, long size=0);\nGraphicBufferClass* Read_PCX_File (char* name, BufferClass& Buff,BYTE* palette= NULL) ;\nint Write_PCX_File (char* name, GraphicViewPortClass& pic ,BYTE* palette ) ;\t\t\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/FILETEMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Temp header for file routines.           *\n *                                                                         *\n *                    File Name : FILETEMP.H                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 20, 1994                           *\n *                                                                         *\n *                  Last Update : April 20, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FILETEMP_H\n#define FILETEMP_H\n\n/////////////////////////////////////////////////////////////////////\n// THIS DOES NOT BELONG HERE.  IT WAS PUT HERE JUST TO GET THE THING\n// TO COMPILE.  ONCE THE BUFFER AND PAGE SYSTEMS ARE PUT IN, THESE\n// WILL NEED TO BE TAKEN OUT AND MODS MADE TO ANY FUNCTION USING BuffType.\n// SKB 4/20/94.\n\n\n\n/*=========================================================================*/\n/* Defines and such that must go into wwstd.h\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n// Look at FileErrorType below for the IO_Error function.\n//extern WORD cdecl (*cdecl IO_Error)(FileErrorType error, BYTE const *filename);\nVOID cdecl Prog_End(VOID);\nextern WORD Hard_Error_Occured;\n\n\n\n//////////////////////// END OF DON'T BELONG //////////////////////////////////\n\n#endif //FILETEMP_H\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/FONT.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Font and text print 32 bit library       *\n *                                                                         *\n *                    File Name : FONT.H                                   *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : June 27, 1994                            *\n *                                                                         *\n *                  Last Update : June 29, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   VVPC::Text_Print -- Text print into a virtual viewport.               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FONT_H\n#define FONT_H\n\n#ifndef GBUFFER_H\n#include <gbuffer.h>\n#endif\n\n#ifndef VBUFFER_H\n#include <vbuffer.h>\n#endif\n\n//////////////////////////////////////// Defines //////////////////////////////////////////\n\n// defines for font header, offsets to block offsets\n\n#define FONTINFOBLOCK\t\t\t4\n#define FONTOFFSETBLOCK\t\t\t6\n#define FONTWIDTHBLOCK\t\t\t8\n#define FONTDATABLOCK\t\t\t10\n#define FONTHEIGHTBLOCK\t\t\t12\n\n// defines for font info block\n\n#define FONTINFOMAXHEIGHT\t\t4\n#define FONTINFOMAXWIDTH\t\t5\n\n//////////////////////////////////////// Prototypes //////////////////////////////////////////\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SET_FONT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nVOID *cdecl Set_Font(VOID const *fontptr);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FONT.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD cdecl Char_Pixel_Width(BYTE chr);\nUWORD cdecl String_Pixel_Width(BYTE const *string);\nVOID cdecl Get_Next_Text_Print_XY(GraphicViewPortClass& vp, ULONG offset, INT *x, INT *y);\nVOID cdecl Get_Next_Text_Print_XY(VideoViewPortClass& vp, ULONG offset, INT *x, INT *y);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOADFONT.CPP\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\nVOID *cdecl Load_Font(BYTE  const *name);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TEXTPRNT.ASM\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\nVOID Set_Font_Palette_Range(VOID const *palette, INT start_idx, INT end_idx);\n\n\n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n\n\n\n\n\n//////////////////////////////////////// External varables ///////////////////////////////////////\nextern \"C\" int FontXSpacing;\nextern \"C\" int FontYSpacing;\nextern BYTE FontWidth ;\nextern BYTE FontHeight;\nextern BYTE *FontWidthBlockPtr;\n\n\nextern \"C\" VOID const *FontPtr;\n\n\n\n\n#endif // FONT_H\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/FONT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Font and text print 32 bit library       *\n *                                                                         *\n *                    File Name : FONT.H                                   *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : June 27, 1994                            *\n *                                                                         *\n *                  Last Update : June 29, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   VVPC::Text_Print -- Text print into a virtual viewport.               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FONT_H\n#define FONT_H\n\n#ifndef GBUFFER_H\n#include <gbuffer.h>\n#endif\n\n#ifndef VBUFFER_H\n#include <vbuffer.h>\n#endif\n\n//////////////////////////////////////// Defines //////////////////////////////////////////\n\n// defines for font header, offsets to block offsets\n\n#define FONTINFOBLOCK\t\t\t4\n#define FONTOFFSETBLOCK\t\t\t6\n#define FONTWIDTHBLOCK\t\t\t8\n#define FONTDATABLOCK\t\t\t10\n#define FONTHEIGHTBLOCK\t\t\t12\n\n// defines for font info block\n\n#define FONTINFOMAXHEIGHT\t\t4\n#define FONTINFOMAXWIDTH\t\t5\n\n//////////////////////////////////////// Prototypes //////////////////////////////////////////\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SET_FONT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nVOID *cdecl Set_Font(VOID const *fontptr);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FONT.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD cdecl Char_Pixel_Width(BYTE chr);\nUWORD cdecl String_Pixel_Width(BYTE const *string);\nVOID cdecl Get_Next_Text_Print_XY(GraphicViewPortClass& vp, ULONG offset, INT *x, INT *y);\nVOID cdecl Get_Next_Text_Print_XY(VideoViewPortClass& vp, ULONG offset, INT *x, INT *y);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOADFONT.CPP\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\nVOID *cdecl Load_Font(BYTE  const *name);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TEXTPRNT.ASM\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\nVOID Set_Font_Palette_Range(VOID const *palette, INT start_idx, INT end_idx);\n\n\n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n\n\n\n\n\n//////////////////////////////////////// External varables ///////////////////////////////////////\nextern \"C\" int FontXSpacing;\nextern \"C\" int FontYSpacing;\nextern BYTE FontWidth ;\nextern BYTE FontHeight;\nextern BYTE *FontWidthBlockPtr;\n\n\nextern \"C\" void const *FontPtr;\n\n\n\n\n#endif // FONT_H\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/FUNCTION.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: SOUNDIO.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nshort Decompress_Frame(void * source, void * dest, short size);\nint cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback);\nint cdecl Stream_Sample(void *buffer, long size, BOOL (*callback);\nint cdecl File_Stream_Sample(char const *filename);\nint cdecl File_Stream_Sample_Vol(char const *filename, int volume);\nvoid cdecl _saveregs _loadds Sound_Callback(void);\nvoid cdecl far _saveregs _loadds maintenance_callback(void);\nvoid *cdecl Load_Sample(char const *filename);\nlong cdecl Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);\nlong cdecl Sample_Read(int fh, void *buffer, long size);\nvoid cdecl Free_Sample(void const *sample);\nBOOL cdecl Sound_Init(int sfx, int score, int sample);\nvoid far VQA_TimerCallback(void);\nBOOL Audio_Init(int sample, int address, int inter, int dma);\nvoid cdecl Sound_End(void);\nvoid cdecl Stop_Sample(int handle);\nBOOL cdecl Sample_Status(int handle);\nBOOL cdecl Is_Sample_Playing(void const * sample);\nvoid cdecl Stop_Sample_Playing(void const * sample);\nint cdecl Play_Sample(void const *sample);\nint cdecl Play_Sample_Vol(void const *sample, int priority, int volume);\nint cdecl Set_Sound_Vol(int volume);\nint cdecl Set_Score_Vol(int volume);\nvoid cdecl Fade_Sample(int handle, int ticks);\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/GBUFFER.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : GBUFFER.H                                *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 26, 1994                             *\n *                                                                         *\n *                  Last Update : January 17, 1995   [PWG]                 *\n *                                                                         *\n ***************************************************************************\n *                                                                         *\n *\tThis module contains the definition for the graphic buffer class.  The\t*\n * primary functionality of the graphic buffer class is handled by inline\t*\n * functions that make a call through function pointers to the correct\t\t*\n * routine.  This has two benefits:\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t1) C++ name mangling is not a big deal since the function pointers\t*\n *\t\t   point to functions in standard C format.\t\t\t\t\t\t\t\t\t*\n *\t\t2) The function pointers can be changed when we set a different\t\t*\n *       graphic mode.  This allows us to have both supervga and mcga\t\t*\n *\t\t\troutines present in memory at once.\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * In the basic library, these functions point to stub routines which just\t*\n * return.  This makes a product that just uses a graphic buffer take the\t*\n * minimum amount of code space.  For programs that require MCGA or VESA\t*\n * support, all that is necessary to do is link either the MCGA or VESA\t\t*\n * specific libraries in, previous to WWLIB32.  The linker will then \t\t*\n * overide the the necessary stub functions automatically.\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * In addition, there are helpful inline function calls for parameter\t\t*\n * ellimination.  This header file gives the defintion for all\t\t\t\t\t*\n * GraphicViewPort and GraphicBuffer classes.  \t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Terminology:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tBuffer Class - A class which consists of a pointer to an allocated\t\t* \n *\t\tbuffer and the size of the buffer that was allocated.\t\t\t\t\t\t* \n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n *\tGraphic ViewPort - The Graphic ViewPort defines a window into a \t\t\t*\n *\t\tGraphic Buffer.  This means that although a Graphic Buffer \t\t\t\t*\n *\t\trepresents linear memory, this may not be true with a Graphic\t\t\t*\n *\t\tViewport.  All low level functions that act directly on a graphic\t\t*\n *\t\tviewport are included within this class.  This includes but is not\t*\n *\t\tlimited to most of the functions which can act on a Video Viewport\t*\n *\t\tVideo Buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n * Graphic Buffer - A Graphic Buffer is an instance of an allocated buffer\t* \n *\t\tused to represent a rectangular region of graphics memory.\t\t\t\t*\n *\t\tThe HidBuff\tand BackBuff are excellent examples of a Graphic Buffer.\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n * Below is a tree which shows the relationship of the VideoBuffer and \t\t*\n * Buffer classes to the GraphicBuffer class:\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t  BUFFER.H\t\t\t\t GBUFFER.H\t\t\t  BUFFER.H\t\t\t\t VBUFFER.H\t*\n *  ----------          ----------         ----------          ----------\t*\n * |  Buffer  |        | Graphic  |       |  Buffer  |        |  Video   |\t*\n * |  Class   |        | ViewPort |       |  Class   |        | ViewPort |\t*\n *  ----------          ----------         ----------          ----------\t*\n *            \\        /                             \\        /\t\t\t\t*\n *             \\      /                               \\      /\t\t\t\t\t*\n *            ----------                             ----------\t\t\t\t*\n *           |  Graphic |                           |  Video   |\t\t\t\t*\n *           |  Buffer  |                           |  Buffer  |\t\t\t\t*\n *            ----------                             ---------- \t\t\t\t*\n *\t  \t\t\t  GBUFFER.H\t\t\t                       VBUFFER.H\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   GBC::GraphicBufferClass -- inline constructor for GraphicBufferClass  *\n *   GVPC::Remap -- Short form to remap an entire graphic view port        *\n *   GVPC::Get_XPos -- Returns x offset for a graphic viewport class       *\n *   GVPC::Get_Ypos -- Return y offset in a GraphicViewPortClass           *\n *   VVPC::Get_XPos -- Get the x pos of the VP on the Video                *\n *   VVPC::Get_YPos -- Get the y pos of the VP on the video                *\n *   GBC::Get_Graphic_Buffer -- Get the graphic buffer of the VP.          *\n *   GVPC::Draw_Line -- Stub function to draw line in Graphic Viewport Class*\n *   GVPC::Fill_Rect -- Stub function to fill rectangle in a GVPC          *\n *   GVPC::Remap -- Stub function to remap a GVPC                          *\n *   GVPC::Print -- stub func to print a text string                       *\n *   GVPC::Print -- Stub function to print an integer                      *\n *   GVPC::Print -- Stub function to print a short to a graphic viewport   *\n *   GVPC::Print -- stub function to print a long on a graphic view port   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"window.h\"\n\n#ifndef GBUFFER_H\n#define GBUFFER_H\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n#ifndef MCGAPRIM_H\n#include \"mcgaprim.h\"\n#endif\n\n#ifndef BUFFER_H\n#include \"buffer.h\"\n#endif\n\n#include <stdlib.h>\n\n\n/*=========================================================================*/\n/* Define the screen width and height to make portability to other modules\t*/\n/*\t\teasier.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tDEFAULT_SCREEN_WIDTH\t\t320\n#define\tDEFAULT_SCREEN_HEIGHT\t200\n\n/*=========================================================================*/\n/* Let the compiler know that a GraphicBufferClass exists so that it can\t*/\n/*\t\tkeep a pointer to it in a VideoViewPortClass.\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nclass GraphicViewPortClass;\nclass GraphicBufferClass;\nclass VideoViewPortClass;\nclass VideoBufferClass;\n\nGraphicBufferClass *Set_Logic_Page(GraphicBufferClass *ptr);\nGraphicBufferClass *Set_Logic_Page(GraphicBufferClass &ptr);\n\n/*=========================================================================*/\n/* GraphicViewPortClass - Holds viewport information on a viewport which\t*/\n/*\t\thas been attached to a GraphicBuffer.  A viewport is effectively a\t*/\n/*\t\trectangular subset of the full buffer which is used for clipping and\t*/\n/*\t\tthe like.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tchar\t  \t*Buffer\t-\t\tis the offset to view port buffer\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis the width of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis the height of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis add value to go from the end of a line\t*/\n/*\t\t\t\t\t\t\t\t\t\t\tto the beginning of the next line\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\tx offset into its associated VideoBuffer\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\ty offset into its associated VideoBuffer\t*/\n/*=========================================================================*/\nclass GraphicViewPortClass {\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tGraphicViewPortClass(GraphicBufferClass* graphic_buff, int x, int y, int w, int h);\n\t\tGraphicViewPortClass();\n\t\t~GraphicViewPortClass();\n\n\t\t/*===================================================================*/\n\t\t/* define functions to get at the private data members\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\tGet_Offset(void);\n\t\tint\tGet_Height(void);\n\t\tint\tGet_Width(void);\n\t\tint\tGet_XAdd(void);\n\t\tint\tGet_XPos(void);\n\t\tint\tGet_YPos(void);\n\t\tGraphicBufferClass\t*Get_Graphic_Buffer(void);\n\n\t\tint Lock(void) const {return(TRUE);}\n\t\tvoid Unlock(void) const {}\n\n\t\t/*===================================================================*/\n\t\t/* Define a function which allows us to change a video viewport on\t*/\n\t\t/*\t\tthe fly.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBOOL Change(int x, int y, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the set of common graphic functions that are supported by\t*/\n\t\t/*\t\tboth Graphic ViewPorts and VideoViewPorts.\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\tSize_Of_Region(int w, int h);\n\t\tvoid\tPut_Pixel(int x, int y, unsigned char color);\n\t\tint\tGet_Pixel(int x, int y);\n\t\tvoid\tClear(unsigned char color = 0);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, void *buff, long size);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, BufferClass *buff);\n\t\tlong\tTo_Buffer(BufferClass *buff);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, char *remap);\n\t\tunsigned long\tPrint(char const *string, int x_pixel, int y_pixel, int fcolor, int bcolor);\n\t\tunsigned long\tPrint(short num, int x_pixel, int y_pixel, int fcol, int bcol);\n\t\tunsigned long\tPrint(int num, int x_pixel, int y_pixel, int fcol, int bcol);\n\t\tunsigned long\tPrint(long num, int x_pixel, int y_pixel, int fcol, int bcol);\n\n\t\t/*===================================================================*/\n\t\t/* Define the list of graphic functions which work only with a \t\t*/\n\t\t/*\t\tgraphic buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Draw_Line(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Draw_Rect(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Fill_Rect(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Fill_Quad(VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\tint x2, int y2, int x3, int y3, int color);\n\t\tVOID Remap(int sx, int sy, int width, int height, VOID *remap);\n\t\tVOID Remap(VOID *remap);\n\t\tvoid Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap);\n\t\tvoid Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int clip_window);\n\t\tVOID Grey_Out_Region(int x, int y, int width, int height, int color);\n\tprotected:\n\t\t/*===================================================================*/\n\t\t/* Define functions to attach the viewport to a graphicbuffer\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Attach(GraphicBufferClass *graphic_buff, int x, int y, int w, int h);\n\t\tvoid Attach(GraphicBufferClass *video_buff, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the data used by a GraphicViewPortClass\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\t\t\t\t\t\tOffset;\t\t\t\t\t// offset to graphic page\n\t\tint\t\t\t\t\t\tWidth;\t\t\t\t\t// width of graphic page\n\t\tint\t\t\t\t\t\tHeight;\t\t\t\t\t// height of graphic page\n\t\tint\t\t\t\t\t\tXAdd;\t\t\t\t\t\t// xadd for graphic page (0)\n\t\tint\t\t\t\t\t\tXPos;\t\t\t\t\t\t// x offset in relation to graphicbuff\n\t\tint\t\t\t\t\t\tYPos;\t\t\t\t\t\t// y offset in relation to graphicbuff\n\t\tGraphicBufferClass\t*GraphicBuff;\t\t\t// related graphic buff\n};\n\n/*=========================================================================*/\n/* GraphicBufferClass - A GraphicBuffer refers to an actual instance of an\t*/\n/*\t\tallocated buffer.  The GraphicBuffer may be drawn to directly \t\t\t*/\n/*\t\tbecuase it inherits a ViewPort which represents its physcial size.\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tBYTE\t  \t*Buffer\t-\t\tis the offset to graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis the width of graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis the height of graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis the xadd of graphic buffer\t\t\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\twill be 0 because it is graphicbuff\t\t\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\twill be 0 because it is graphicbuff\t\t\t*/\n/*=========================================================================*/\nclass GraphicBufferClass : public GraphicViewPortClass, public BufferClass {\n\tpublic:\n\t\tGraphicBufferClass(\tlong size = 64500, int w = DEFAULT_SCREEN_WIDTH, int h = DEFAULT_SCREEN_HEIGHT, \n\t\t\t\t\t\t\t\t\tVOID *buffer = 0);\n\t\tGraphicBufferClass(int w, int h, void *buffer = 0);\n\t\t~GraphicBufferClass();\n\n//\t\tvoid Scale_Rotate(BitmapClass &bmp,const TPoint2D &pt,long scale=0x0100,unsigned char angle=0);\n};\n\n/***************************************************************************\n * GVPC::GET_OFFSET -- Get offset for virtual view port class instance     *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long the offset for the virtual viewport instance           *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long GraphicViewPortClass::Get_Offset(void)\n{\n\treturn(Offset);\n}\n\n/***************************************************************************\n * GVPC::GET_HEIGHT -- Gets the height of a virtual viewport instance      *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the height of the virtual viewport instance            *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_Height(void)\n{\n\treturn(Height);\n}\n\n/***************************************************************************\n * GVPC::GET_WIDTH -- Get the width of a virtual viewport instance\t\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the width of the virtual viewport instance             *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_Width(void)\n{\n\treturn(Width);\n}\n\n\n/***************************************************************************\n * GVPC::GET_XADD -- Get the X add offset for virtual viewport instance    *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the xadd for a virtual viewport instance               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_XAdd(void)\n{\t\n\treturn(XAdd);\n}\n/***************************************************************************\n * GVPC::GET_XPOS -- Get the x pos of the VP on the Video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n;*   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_XPos(void)\n{\n\treturn(XPos);\n}\n\n\n/***************************************************************************\n * GVPC::GET_YPOS -- Get the y pos of the VP on the video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n;*   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_YPos(void)\n{\n\treturn(YPos);\n}\n\n/***************************************************************************\n * GVPC::GET_GRAPHIC_BUFFER -- Get the graphic buffer of the VP.            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline GraphicBufferClass *GraphicViewPortClass::Get_Graphic_Buffer(void)\n{\n \treturn (GraphicBuff);\n}\n\n/***************************************************************************\n * GVPC::SIZE_OF_REGION -- stub to call curr graphic mode Size_Of_Region\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/01/1995 BWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::Size_Of_Region(int w, int h)\n{\n\treturn MCGA_Size_Of_Region(this, w, h);\n}\n\n/***************************************************************************\n * GVPC::PUT_PIXEL -- stub to call curr graphic mode Put_Pixel\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tGraphicViewPortClass::Put_Pixel(int x, int y, unsigned char color)\n{\n\tMCGA_Put_Pixel(this, x, y, color);\n}\n\n/***************************************************************************\n * GVPC::GET_PIXEL -- stub to call curr graphic mode Get_Pixel          \t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline int\tGraphicViewPortClass::Get_Pixel(int x, int y)\n{\n\treturn(MCGA_Get_Pixel(this, x, y));\n}\n\n/***************************************************************************\n * GVPC::CLEAR -- stub to call curr graphic mode Clear\t                  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tGraphicViewPortClass::Clear(unsigned char color)\n{\n\tMCGA_Clear(this, color);\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 1 to call curr graphic mode To_Buffer\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(int x, int y, int w, int h, void *buff, long size)\n{\n\treturn(MCGA_To_Buffer(this, x, y, w, h, buff, size));\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 2 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(int x, int y, int w, int h, BufferClass *buff)\n{\n\treturn(MCGA_To_Buffer(this, x, y, w, h, buff->Get_Buffer(), buff->Get_Size()));\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 3 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(BufferClass *buff)\n{\n\treturn(MCGA_To_Buffer(this, 0, 0, Width, Height, buff->Get_Buffer(), buff->Get_Size()));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 1 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans)\n{\n\treturn(Linear_Blit_To_Linear(this, &dest, x_pixel, y_pixel, dx_pixel, dy_pixel, pixel_width, pixel_height, trans));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- Stub 2 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans)\n{\n\treturn(Linear_Blit_To_Linear(this, &dest, 0, 0, dx, dy, Width, Height, trans));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 3 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, BOOL trans)\n{\n\treturn(Linear_Blit_To_Linear(this, &dest, 0, 0, 0, 0, Width, Height, trans));\n}\n\n\n/***************************************************************************\n * GVPC::SCALE -- stub 1 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, trans, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 2 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, FALSE, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 3 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, BOOL trans, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this,\t&dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), trans, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 4 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), FALSE, remap));\n}\n/***************************************************************************\n * GVPC::PRINT -- stub func to print a text string                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/17/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(char const *str, int x, int y, int fcol, int bcol)\n{\n\treturn(MCGA_Print(this, str, x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::PRINT -- Stub function to print an integer                        *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(int num, int x, int y, int fcol, int bcol)\n{\n\tchar str[17];\n\n\t\n\treturn(MCGA_Print(this, itoa(num, str, 10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::PRINT -- Stub function to print a short to a graphic viewport     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(short num, int x, int y, int fcol, int bcol)\n{\n\tchar str[17];\n\n\treturn(MCGA_Print(this, itoa(num, str, 10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::PRINT -- stub function to print a long on a graphic view port     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(long num, int x, int y, int fcol, int bcol)\n{\n\tchar str[33];\n\n\treturn(MCGA_Print(this, ltoa(num, str,10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::DRAW_STAMP -- stub function to draw a tile on a graphic view port *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline void GraphicViewPortClass::Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap)\n{\n\tMCGA_Draw_Stamp(this, icondata, icon, x_pixel, y_pixel, remap);\n}\n\n/***************************************************************************\n * GVPC::DRAW_STAMP -- stub function to draw a tile on a graphic view port *\n *                     This version clips the tile to a window             *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *    07/31/1995 BWG : Created.                                            *\n *=========================================================================*/\ninline void GraphicViewPortClass::Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int clip_window)\n{\n\tMCGA_Draw_Stamp_Clip(this, icondata, icon, x_pixel, y_pixel, remap, WindowList[clip_window][WINDOWX], WindowList[clip_window][WINDOWY], WindowList[clip_window][WINDOWWIDTH], WindowList[clip_window][WINDOWHEIGHT]);\n}\n\n/***************************************************************************\n * GVPC::DRAW_LINE -- Stub function to draw line in Graphic Viewport Class *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Draw_Line(int sx, int sy, int dx, int dy, unsigned char color)\n{\n\tMCGA_Draw_Line(this, sx, sy, dx, dy, color);\n}\n\n/***************************************************************************\n * GVPC::FILL_RECT -- Stub function to fill rectangle in a GVPC            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Fill_Rect(int sx, int sy, int dx, int dy, unsigned char color)\n{\n\tMCGA_Fill_Rect(this, sx, sy, dx, dy, color);\n}\n\n\n/***************************************************************************\n * GVPC::REMAP -- Stub function to remap a GVPC                            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Remap(int sx, int sy, int width, int height, VOID *remap)\n{\n\tMCGA_Remap(this, sx, sy, width, height, remap);\n}\ninline VOID GraphicViewPortClass::Fill_Quad(VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\tint x2, int y2, int x3, int y3, int color)\n{\n\tMCGA_Fill_Quad(this, span_buff, x0, y0, x1, y1, x2, y2, x3, y3, color);\n}\n\n/***************************************************************************\n * GVPC::REMAP -- Short form to remap an entire graphic view port          *\n *                                                                         *\n * INPUT:\t\tBYTE * to the remap table to use\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Remap(VOID *remap)\n{\n\tMCGA_Remap(this, 0, 0, Width, Height, remap);\n}\n/*=========================================================================*/\n/* The following BufferClass functions are defined here because they act\t*/\n/*\t\ton graphic viewports.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n\n/***************************************************************************\n * BUFFER_TO_PAGE -- Generic 'c' callable form of Buffer_To_Page           *\n *                                                                         *\n * INPUT: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/12/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long Buffer_To_Page(int x, int y, int w, int h, void *Buffer, GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(x, y, w, h, Buffer, &view));\n}\n\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t*\n *\t\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t*\n *\t\t\t\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int w, int h, GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(0, 0, w, h, Buffer, &view));\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport.  width and height are assumed to be the\t\t\t*\n *\t\t\t\t\t\tviewport's width and height.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(0, 0, view.Get_Width(), view.Get_Height(), Buffer, &view));\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable x, y, w, h *\n *                                                                         *\n * INPUT:\tint\tx\t\t\t- x pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\ty\t\t\t- y pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t\t*\n *\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t\t*\n *\t\t\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\tnone                                                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int x, int y, int w, int h, GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(x, y, w, h, Buffer, &view));\n}\n\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/GBUFFER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : GBUFFER.H                                *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 26, 1994                             *\n *                                                                         *\n *                  Last Update : January 17, 1995   [PWG]                 *\n *                                                                         *\n ***************************************************************************\n *                                                                         *\n *\tThis module contains the definition for the graphic buffer class.  The\t*\n * primary functionality of the graphic buffer class is handled by inline\t*\n * functions that make a call through function pointers to the correct\t\t*\n * routine.  This has two benefits:\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t1) C++ name mangling is not a big deal since the function pointers\t*\n *\t\t   point to functions in standard C format.\t\t\t\t\t\t\t\t\t*\n *\t\t2) The function pointers can be changed when we set a different\t\t*\n *       graphic mode.  This allows us to have both supervga and mcga\t\t*\n *\t\t\troutines present in memory at once.\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * In the basic library, these functions point to stub routines which just\t*\n * return.  This makes a product that just uses a graphic buffer take the\t*\n * minimum amount of code space.  For programs that require MCGA or VESA\t*\n * support, all that is necessary to do is link either the MCGA or VESA\t\t*\n * specific libraries in, previous to WWLIB32.  The linker will then \t\t*\n * overide the the necessary stub functions automatically.\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * In addition, there are helpful inline function calls for parameter\t\t*\n * ellimination.  This header file gives the defintion for all\t\t\t\t\t*\n * GraphicViewPort and GraphicBuffer classes.  \t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Terminology:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tBuffer Class - A class which consists of a pointer to an allocated\t\t*\n *\t\tbuffer and the size of the buffer that was allocated.\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tGraphic ViewPort - The Graphic ViewPort defines a window into a \t\t\t*\n *\t\tGraphic Buffer.  This means that although a Graphic Buffer \t\t\t\t*\n *\t\trepresents linear memory, this may not be true with a Graphic\t\t\t*\n *\t\tViewport.  All low level functions that act directly on a graphic\t\t*\n *\t\tviewport are included within this class.  This includes but is not\t*\n *\t\tlimited to most of the functions which can act on a Video Viewport\t*\n *\t\tVideo Buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Graphic Buffer - A Graphic Buffer is an instance of an allocated buffer\t*\n *\t\tused to represent a rectangular region of graphics memory.\t\t\t\t*\n *\t\tThe HidBuff\tand BackBuff are excellent examples of a Graphic Buffer.\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Below is a tree which shows the relationship of the VideoBuffer and \t\t*\n * Buffer classes to the GraphicBuffer class:\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t  BUFFER.H\t\t\t\t GBUFFER.H\t\t\t  BUFFER.H\t\t\t\t VBUFFER.H\t*\n *  ----------          ----------         ----------          ----------\t*\n * |  Buffer  |        | Graphic  |       |  Buffer  |        |  Video   |\t*\n * |  Class   |        | ViewPort |       |  Class   |        | ViewPort |\t*\n *  ----------          ----------         ----------          ----------\t*\n *            \\        /                             \\        /\t\t\t\t*\n *             \\      /                               \\      /\t\t\t\t\t*\n *            ----------                             ----------\t\t\t\t*\n *           |  Graphic |                           |  Video   |\t\t\t\t*\n *           |  Buffer  |                           |  Buffer  |\t\t\t\t*\n *            ----------                             ---------- \t\t\t\t*\n *\t  \t\t\t  GBUFFER.H\t\t\t                       VBUFFER.H\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   GBC::GraphicBufferClass -- inline constructor for GraphicBufferClass  *\n *   GVPC::Remap -- Short form to remap an entire graphic view port        *\n *   GVPC::Get_XPos -- Returns x offset for a graphic viewport class       *\n *   GVPC::Get_Ypos -- Return y offset in a GraphicViewPortClass           *\n *   VVPC::Get_XPos -- Get the x pos of the VP on the Video                *\n *   VVPC::Get_YPos -- Get the y pos of the VP on the video                *\n *   GBC::Get_Graphic_Buffer -- Get the graphic buffer of the VP.          *\n *   GVPC::Draw_Line -- Stub function to draw line in Graphic Viewport Class*\n *   GVPC::Fill_Rect -- Stub function to fill rectangle in a GVPC          *\n *   GVPC::Remap -- Stub function to remap a GVPC                          *\n *   GVPC::Print -- stub func to print a text string                       *\n *   GVPC::Print -- Stub function to print an integer                      *\n *   GVPC::Print -- Stub function to print a short to a graphic viewport   *\n *   GVPC::Print -- stub function to print a long on a graphic view port   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"window.h\"\n\n#ifndef GBUFFER_H\n#define GBUFFER_H\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n#ifndef MCGAPRIM_H\n#include \"mcgaprim.h\"\n#endif\n\n#ifndef BUFFER_H\n#include \"buffer.h\"\n#endif\n\n#include <stdlib.h>\n\n\n/*=========================================================================*/\n/* Define the screen width and height to make portability to other modules\t*/\n/*\t\teasier.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tDEFAULT_SCREEN_WIDTH\t\t320\n#define\tDEFAULT_SCREEN_HEIGHT\t200\n\n/*=========================================================================*/\n/* Let the compiler know that a GraphicBufferClass exists so that it can\t*/\n/*\t\tkeep a pointer to it in a VideoViewPortClass.\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nclass GraphicViewPortClass;\nclass GraphicBufferClass;\nclass VideoViewPortClass;\nclass VideoBufferClass;\n\nGraphicBufferClass *Set_Logic_Page(GraphicBufferClass *ptr);\nGraphicBufferClass *Set_Logic_Page(GraphicBufferClass &ptr);\n\n/*=========================================================================*/\n/* GraphicViewPortClass - Holds viewport information on a viewport which\t*/\n/*\t\thas been attached to a GraphicBuffer.  A viewport is effectively a\t*/\n/*\t\trectangular subset of the full buffer which is used for clipping and\t*/\n/*\t\tthe like.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tchar\t  \t*Buffer\t-\t\tis the offset to view port buffer\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis the width of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis the height of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis add value to go from the end of a line\t*/\n/*\t\t\t\t\t\t\t\t\t\t\tto the beginning of the next line\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\tx offset into its associated VideoBuffer\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\ty offset into its associated VideoBuffer\t*/\n/*=========================================================================*/\nclass GraphicViewPortClass {\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tGraphicViewPortClass(GraphicBufferClass* graphic_buff, int x, int y, int w, int h);\n\t\tGraphicViewPortClass();\n\t\t~GraphicViewPortClass();\n\n\t\t/*===================================================================*/\n\t\t/* define functions to get at the private data members\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\tGet_Offset(void);\n\t\tint\tGet_Height(void);\n\t\tint\tGet_Width(void);\n\t\tint\tGet_XAdd(void);\n\t\tint\tGet_XPos(void);\n\t\tint\tGet_YPos(void);\n\t\tGraphicBufferClass\t*Get_Graphic_Buffer(void);\n\n\t\tint Lock(void) const {return(TRUE);}\n\t\tvoid Unlock(void) const {}\n\n\t\t/*===================================================================*/\n\t\t/* Define a function which allows us to change a video viewport on\t*/\n\t\t/*\t\tthe fly.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBOOL Change(int x, int y, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the set of common graphic functions that are supported by\t*/\n\t\t/*\t\tboth Graphic ViewPorts and VideoViewPorts.\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\tSize_Of_Region(int w, int h);\n\t\tvoid\tPut_Pixel(int x, int y, unsigned char color);\n\t\tint\tGet_Pixel(int x, int y);\n\t\tvoid\tClear(unsigned char color = 0);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, void *buff, long size);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, BufferClass *buff);\n\t\tlong\tTo_Buffer(BufferClass *buff);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel,\n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel,\n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, char *remap);\n\t\tunsigned long\tPrint(char const *string, int x_pixel, int y_pixel, int fcolor, int bcolor);\n\t\tunsigned long\tPrint(short num, int x_pixel, int y_pixel, int fcol, int bcol);\n\t\tunsigned long\tPrint(int num, int x_pixel, int y_pixel, int fcol, int bcol);\n\t\tunsigned long\tPrint(long num, int x_pixel, int y_pixel, int fcol, int bcol);\n\n\t\t/*===================================================================*/\n\t\t/* Define the list of graphic functions which work only with a \t\t*/\n\t\t/*\t\tgraphic buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Draw_Line(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Draw_Rect(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Fill_Rect(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Fill_Quad(VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\tint x2, int y2, int x3, int y3, int color);\n\t\tVOID Remap(int sx, int sy, int width, int height, VOID *remap);\n\t\tVOID Remap(VOID *remap);\n\t\tvoid Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap);\n\t\tvoid Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int clip_window);\n\t\tVOID Grey_Out_Region(int x, int y, int width, int height, int color);\n\tprotected:\n\t\t/*===================================================================*/\n\t\t/* Define functions to attach the viewport to a graphicbuffer\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Attach(GraphicBufferClass *graphic_buff, int x, int y, int w, int h);\n\t\tvoid Attach(GraphicBufferClass *video_buff, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the data used by a GraphicViewPortClass\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\t\t\t\t\t\tOffset;\t\t\t\t\t// offset to graphic page\n\t\tint\t\t\t\t\t\tWidth;\t\t\t\t\t// width of graphic page\n\t\tint\t\t\t\t\t\tHeight;\t\t\t\t\t// height of graphic page\n\t\tint\t\t\t\t\t\tXAdd;\t\t\t\t\t\t// xadd for graphic page (0)\n\t\tint\t\t\t\t\t\tXPos;\t\t\t\t\t\t// x offset in relation to graphicbuff\n\t\tint\t\t\t\t\t\tYPos;\t\t\t\t\t\t// y offset in relation to graphicbuff\n\t\tGraphicBufferClass\t*GraphicBuff;\t\t\t// related graphic buff\n};\n\n/*=========================================================================*/\n/* GraphicBufferClass - A GraphicBuffer refers to an actual instance of an\t*/\n/*\t\tallocated buffer.  The GraphicBuffer may be drawn to directly \t\t\t*/\n/*\t\tbecuase it inherits a ViewPort which represents its physcial size.\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tBYTE\t  \t*Buffer\t-\t\tis the offset to graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis the width of graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis the height of graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis the xadd of graphic buffer\t\t\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\twill be 0 because it is graphicbuff\t\t\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\twill be 0 because it is graphicbuff\t\t\t*/\n/*=========================================================================*/\nclass GraphicBufferClass : public GraphicViewPortClass, public BufferClass {\n\tpublic:\n\t\tGraphicBufferClass(\tlong size = 64500, int w = DEFAULT_SCREEN_WIDTH, int h = DEFAULT_SCREEN_HEIGHT,\n\t\t\t\t\t\t\t\t\tVOID *buffer = 0);\n\t\tGraphicBufferClass(int w, int h, void *buffer = 0);\n\t\t~GraphicBufferClass();\n\n\t\tvoid Scale_Rotate(BitmapClass &bmp,const TPoint2D &pt,long scale=0x0100,unsigned char angle=0);\n};\n\n/***************************************************************************\n * GVPC::GET_OFFSET -- Get offset for virtual view port class instance     *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long the offset for the virtual viewport instance           *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long GraphicViewPortClass::Get_Offset(void)\n{\n\treturn(Offset);\n}\n\n/***************************************************************************\n * GVPC::GET_HEIGHT -- Gets the height of a virtual viewport instance      *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the height of the virtual viewport instance            *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_Height(void)\n{\n\treturn(Height);\n}\n\n/***************************************************************************\n * GVPC::GET_WIDTH -- Get the width of a virtual viewport instance\t\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the width of the virtual viewport instance             *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_Width(void)\n{\n\treturn(Width);\n}\n\n\n/***************************************************************************\n * GVPC::GET_XADD -- Get the X add offset for virtual viewport instance    *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the xadd for a virtual viewport instance               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_XAdd(void)\n{\n\treturn(XAdd);\n}\n/***************************************************************************\n * GVPC::GET_XPOS -- Get the x pos of the VP on the Video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n;*   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_XPos(void)\n{\n\treturn(XPos);\n}\n\n\n/***************************************************************************\n * GVPC::GET_YPOS -- Get the y pos of the VP on the video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n;*   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_YPos(void)\n{\n\treturn(YPos);\n}\n\n/***************************************************************************\n * GVPC::GET_GRAPHIC_BUFFER -- Get the graphic buffer of the VP.            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline GraphicBufferClass *GraphicViewPortClass::Get_Graphic_Buffer(void)\n{\n \treturn (GraphicBuff);\n}\n\n/***************************************************************************\n * GVPC::SIZE_OF_REGION -- stub to call curr graphic mode Size_Of_Region\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/01/1995 BWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::Size_Of_Region(int w, int h)\n{\n\treturn MCGA_Size_Of_Region(this, w, h);\n}\n\n/***************************************************************************\n * GVPC::PUT_PIXEL -- stub to call curr graphic mode Put_Pixel\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tGraphicViewPortClass::Put_Pixel(int x, int y, unsigned char color)\n{\n\tMCGA_Put_Pixel(this, x, y, color);\n}\n\n/***************************************************************************\n * GVPC::GET_PIXEL -- stub to call curr graphic mode Get_Pixel          \t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline int\tGraphicViewPortClass::Get_Pixel(int x, int y)\n{\n\treturn(MCGA_Get_Pixel(this, x, y));\n}\n\n/***************************************************************************\n * GVPC::CLEAR -- stub to call curr graphic mode Clear\t                  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tGraphicViewPortClass::Clear(unsigned char color)\n{\n\tMCGA_Clear(this, color);\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 1 to call curr graphic mode To_Buffer\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(int x, int y, int w, int h, void *buff, long size)\n{\n\treturn(MCGA_To_Buffer(this, x, y, w, h, buff, size));\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 2 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(int x, int y, int w, int h, BufferClass *buff)\n{\n\treturn(MCGA_To_Buffer(this, x, y, w, h, buff->Get_Buffer(), buff->Get_Size()));\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 3 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(BufferClass *buff)\n{\n\treturn(MCGA_To_Buffer(this, 0, 0, Width, Height, buff->Get_Buffer(), buff->Get_Size()));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 1 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel,\n\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans)\n{\n\treturn(Linear_Blit_To_Linear(this, &dest, x_pixel, y_pixel, dx_pixel, dy_pixel, pixel_width, pixel_height, trans));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- Stub 2 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans)\n{\n\treturn(Linear_Blit_To_Linear(this, &dest, 0, 0, dx, dy, Width, Height, trans));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 3 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, BOOL trans)\n{\n\treturn(Linear_Blit_To_Linear(this, &dest, 0, 0, 0, 0, Width, Height, trans));\n}\n\n\n/***************************************************************************\n * GVPC::SCALE -- stub 1 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, trans, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 2 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x,\n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, FALSE, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 3 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, BOOL trans, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this,\t&dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), trans, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 4 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), FALSE, remap));\n}\n/***************************************************************************\n * GVPC::PRINT -- stub func to print a text string                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/17/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(char const *str, int x, int y, int fcol, int bcol)\n{\n\treturn(MCGA_Print(this, str, x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::PRINT -- Stub function to print an integer                        *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(int num, int x, int y, int fcol, int bcol)\n{\n\tchar str[17];\n\n\n\treturn(MCGA_Print(this, itoa(num, str, 10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::PRINT -- Stub function to print a short to a graphic viewport     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(short num, int x, int y, int fcol, int bcol)\n{\n\tchar str[17];\n\n\treturn(MCGA_Print(this, itoa(num, str, 10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::PRINT -- stub function to print a long on a graphic view port     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(long num, int x, int y, int fcol, int bcol)\n{\n\tchar str[33];\n\n\treturn(MCGA_Print(this, ltoa(num, str,10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::DRAW_STAMP -- stub function to draw a tile on a graphic view port *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline void GraphicViewPortClass::Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap)\n{\n\tMCGA_Draw_Stamp(this, icondata, icon, x_pixel, y_pixel, remap);\n}\n\n/***************************************************************************\n * GVPC::DRAW_STAMP -- stub function to draw a tile on a graphic view port *\n *                     This version clips the tile to a window             *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *    07/31/1995 BWG : Created.                                            *\n *=========================================================================*/\ninline void GraphicViewPortClass::Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int clip_window)\n{\n\tMCGA_Draw_Stamp_Clip(this, icondata, icon, x_pixel, y_pixel, remap, WindowList[clip_window][WINDOWX], WindowList[clip_window][WINDOWY], WindowList[clip_window][WINDOWWIDTH], WindowList[clip_window][WINDOWHEIGHT]);\n}\n\n/***************************************************************************\n * GVPC::DRAW_LINE -- Stub function to draw line in Graphic Viewport Class *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Draw_Line(int sx, int sy, int dx, int dy, unsigned char color)\n{\n\tMCGA_Draw_Line(this, sx, sy, dx, dy, color);\n}\n\n/***************************************************************************\n * GVPC::FILL_RECT -- Stub function to fill rectangle in a GVPC            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Fill_Rect(int sx, int sy, int dx, int dy, unsigned char color)\n{\n\tMCGA_Fill_Rect(this, sx, sy, dx, dy, color);\n}\n\n\n/***************************************************************************\n * GVPC::REMAP -- Stub function to remap a GVPC                            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Remap(int sx, int sy, int width, int height, VOID *remap)\n{\n\tMCGA_Remap(this, sx, sy, width, height, remap);\n}\ninline VOID GraphicViewPortClass::Fill_Quad(VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\tint x2, int y2, int x3, int y3, int color)\n{\n\tMCGA_Fill_Quad(this, span_buff, x0, y0, x1, y1, x2, y2, x3, y3, color);\n}\n\n/***************************************************************************\n * GVPC::REMAP -- Short form to remap an entire graphic view port          *\n *                                                                         *\n * INPUT:\t\tBYTE * to the remap table to use\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Remap(VOID *remap)\n{\n\tMCGA_Remap(this, 0, 0, Width, Height, remap);\n}\n/*=========================================================================*/\n/* The following BufferClass functions are defined here because they act\t*/\n/*\t\ton graphic viewports.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n\n/***************************************************************************\n * BUFFER_TO_PAGE -- Generic 'c' callable form of Buffer_To_Page           *\n *                                                                         *\n * INPUT: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/12/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long Buffer_To_Page(int x, int y, int w, int h, void *Buffer, GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(x, y, w, h, Buffer, &view));\n}\n\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t*\n *\t\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t*\n *\t\t\t\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int w, int h, GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(0, 0, w, h, Buffer, &view));\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport.  width and height are assumed to be the\t\t\t*\n *\t\t\t\t\t\tviewport's width and height.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(0, 0, view.Get_Width(), view.Get_Height(), Buffer, &view));\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable x, y, w, h *\n *                                                                         *\n * INPUT:\tint\tx\t\t\t- x pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\ty\t\t\t- y pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t\t*\n *\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t\t*\n *\t\t\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\tnone                                                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int x, int y, int w, int h, GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(x, y, w, h, Buffer, &view));\n}\n\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/GBUFFER.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 Bit Library\t\t   *\n;*                                                                         *\n;*                    File Name : GBUFFER.INC                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : May 26, 1994                             *\n;*                                                                         *\n;*                  Last Update : May 26, 1994   [PWG]                     *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n;******************************************************************************\n; Much testing was done to determine that only when there are 14 or more bytes\n; being copied does it speed the time it takes to do copies in this algorithm.\n; For this reason and because 1 and 2 byte copies crash, is the special case\n; used.  SKB 4/21/94.  Tested on 486 66mhz.  Copied by PWG 6/7/04.\nOPTIMAL_BYTE_COPY\tequ\t14\n\nSTRUC GraphicViewPort \nGVPOffset\t\tDD\t\t?\t\t; offset to virtual viewport\nGVPWidth\t\t\tDD\t\t?\t\t; width of virtual viewport\nGVPHeight\t\tDD\t\t?\t\t; height of virtual viewport\nGVPXAdd\t\t\tDD\t\t?\t\t; x mod to get to next line\nGVPXPos\t\t\tDD\t\t?\t\t; x pos relative to Graphic Buff\nGVPYPos\t\t\tDD\t\t?\t\t; y pos relative to Graphic Buff\nGVPBuffPtr\t\tDD\t\t?\t\t; ptr to associated Graphic Buff\nENDS\n\nSTRUC VideoViewPort \nVIVPOffset\t\t\tDD\t\t?\t\t; offset to virtual viewport\nVIVPWidth\t\t\tDD\t\t?\t\t; width of virtual viewport\nVIVPHeight\t\t\tDD\t\t?\t\t; height of virtual viewport\nVIVPXAdd\t\t\t\tDD\t\t?\t\t; x mod to get to next line\nVIVPXPos\t\t\t\tDD\t\t?\t\t; x pos relative to Graphic Buff\nVIVPYPos\t\t\t\tDD\t\t?\t\t; y pos relative to Graphic Buff\nVIVPBuffPtr\t\t\tDD\t\t?\t\t; ptr to associated Graphic Buff\nENDS\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/IFF.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the FILEIO Library               *\n *                                                                         *\n *                    File Name : IFF.H                                    *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 20, 1994                           *\n *                                                                         *\n *                  Last Update : April 20, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef IFF_H\n#define IFF_H\n\n#ifndef MISC_H\n#include <misc.h>\t\t// This is needed fro Reverse_WORD and _LONG\n#endif\n\n#ifndef MEMFLAGS_H\n#include <memflag.h>\t// This is needed for MemoryFlagType.\n#endif\n\n#ifndef GBUFFER_H\n#include <gbuffer.h>\n#endif \n\n#define LZW_SUPPORTED\t\t\tFALSE\n\n/*=========================================================================*/\n/* Iff and Load Picture system defines and enumerations\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#define \tMAKE_ID(a,b,c,d)\t\t\t((LONG) ((LONG) d << 24) | ((LONG) c << 16) | ((LONG) b <<  8) | (LONG)(a))\n#define\tIFFize_WORD(a)\t\t\tReverse_WORD(a)\n#define\tIFFize_LONG(a)\t\t\tReverse_LONG(a)\n\n\n//lint -strong(AJX,PicturePlaneType)\ntypedef enum {\n\tBM_AMIGA,\t// Bit plane format (8K per bitplane).\n\tBM_MCGA,\t\t// Byte per pixel format (64K).\n\n\tBM_DEFAULT=BM_MCGA\t// Default picture format.\n} PicturePlaneType;\n\n/*\n**\tThis is the compression type code.  This value is used in the compressed\n**\tfile header to indicate the method of compression used.  Note that the\n**\tLZW method may not be supported.\n*/\n//lint -strong(AJX,CompressionType)\ntypedef enum {\n\tNOCOMPRESS,\t\t// No compression (raw data).\n\tLZW12,\t\t\t// LZW 12 bit codes.\n\tLZW14,\t\t\t// LZW 14 bit codes.\n\tHORIZONTAL,\t\t// Run length encoding (RLE).\n\tLCW\t\t\t\t// Westwood proprietary compression.\n} CompressionType;\n\n/*\n**\tCompressed blocks of data must start with this header structure.\n**\tNote that disk based compressed files have an additional two\n**\tleading bytes that indicate the size of the entire file.\n*/\n//lint -strong(AJX,CompHeaderType)\ntypedef struct {\n\tBYTE\tMethod;\t\t// Compression method (CompressionType).\n\tBYTE\tpad;\t\t\t// Reserved pad byte (always 0).\n\tLONG\tSize;\t\t\t// Size of the uncompressed data.\n\tWORD\tSkip;\t\t\t// Number of bytes to skip before data.\n} CompHeaderType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: IFF.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD cdecl Open_Iff_File(BYTE const *filename);\nVOID cdecl Close_Iff_File(WORD fh);\nULONG cdecl Get_Iff_Chunk_Size(WORD fh, LONG id);\nULONG cdecl Read_Iff_Chunk(WORD fh, LONG id, VOID *buffer, ULONG maxsize);\nVOID cdecl Write_Iff_Chunk(WORD file, LONG id, VOID *buffer, LONG length);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOADPICT.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//WORD cdecl Load_Picture(BYTE const *filename, BufferClass& scratchbuf, BufferClass& destbuf, UBYTE *palette=NULL, PicturePlaneType format=BM_DEFAULT);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LOAD.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nULONG cdecl Load_Data(BYTE const *name, VOID *ptr, ULONG size);\nULONG cdecl Write_Data(BYTE const *name, VOID *ptr, ULONG size);\nVOID * cdecl Load_Alloc_Data(BYTE const *name, MemoryFlagType flags);\n//ULONG cdecl Load_Uncompress(BYTE const *file, BufferClass& uncomp_buff, BufferClass& dest_buff, VOID *reserved_data=NULL);\nULONG cdecl Uncompress_Data(VOID const *src, VOID *dst);\nVOID cdecl Set_Uncomp_Buffer(WORD buffer_segment, UWORD size_of_buffer);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WRITELBM.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nPUBLIC BOOL Write_LBM_File(WORD lbmhandle, BufferClass& buff, WORD bitplanes, UBYTE *palette);\n\n\n\n/*========================= Assembly Functions ============================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*=========================================================================*/\n/* The following prototypes are for the file: PACK2PLN.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern VOID Pack_2_Plane(VOID *buffer, VOID * pageptr, WORD planebit);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LCWCOMP.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern ULONG LCW_Compress(VOID *source, VOID *dest, ULONG length);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LCWUNCMP.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern ULONG LCW_Uncompress(VOID *source, VOID *dest, ULONG length);\n\n#ifdef __cplusplus\n}\n#endif\n/*=========================================================================*/\n\n\n\n#endif //IFF_H\n\u001a\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/INDEXTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* wIndexTable - ADPCM Lookup table for indexes\n;****************************************************************************\n\n\t\talign\t4\n\nwIndexTable\tDW\t0\t* 2\t; Index = 0 Token = 0\n\t\tDW\t0\t* 2\t; Index = 0 Token = 1\n\t\tDW\t0\t* 2\t; Index = 0 Token = 2\n\t\tDW\t0\t* 2\t; Index = 0 Token = 3\n\t\tDW\t32\t* 2\t; Index = 0 Token = 4\n\t\tDW\t64\t* 2\t; Index = 0 Token = 5\n\t\tDW\t96\t* 2\t; Index = 0 Token = 6\n\t\tDW\t128\t* 2\t; Index = 0 Token = 7\n\t\tDW\t0\t* 2\t; Index = 0 Token = 8\n\t\tDW\t0\t* 2\t; Index = 0 Token = 9\n\t\tDW\t0\t* 2\t; Index = 0 Token = 10\n\t\tDW\t0\t* 2\t; Index = 0 Token = 11\n\t\tDW\t32\t* 2\t; Index = 0 Token = 12\n\t\tDW\t64\t* 2\t; Index = 0 Token = 13\n\t\tDW\t96\t* 2\t; Index = 0 Token = 14\n\t\tDW\t128\t* 2\t; Index = 0 Token = 15\n\t\tDW\t0\t* 2\t; Index = 1 Token = 0\n\t\tDW\t0\t* 2\t; Index = 1 Token = 1\n\t\tDW\t0\t* 2\t; Index = 1 Token = 2\n\t\tDW\t0\t* 2\t; Index = 1 Token = 3\n\t\tDW\t48\t* 2\t; Index = 1 Token = 4\n\t\tDW\t80\t* 2\t; Index = 1 Token = 5\n\t\tDW\t112\t* 2\t; Index = 1 Token = 6\n\t\tDW\t144\t* 2\t; Index = 1 Token = 7\n\t\tDW\t0\t* 2\t; Index = 1 Token = 8\n\t\tDW\t0\t* 2\t; Index = 1 Token = 9\n\t\tDW\t0\t* 2\t; Index = 1 Token = 10\n\t\tDW\t0\t* 2\t; Index = 1 Token = 11\n\t\tDW\t48\t* 2\t; Index = 1 Token = 12\n\t\tDW\t80\t* 2\t; Index = 1 Token = 13\n\t\tDW\t112\t* 2\t; Index = 1 Token = 14\n\t\tDW\t144\t* 2\t; Index = 1 Token = 15\n\t\tDW\t16\t* 2\t; Index = 2 Token = 0\n\t\tDW\t16\t* 2\t; Index = 2 Token = 1\n\t\tDW\t16\t* 2\t; Index = 2 Token = 2\n\t\tDW\t16\t* 2\t; Index = 2 Token = 3\n\t\tDW\t64\t* 2\t; Index = 2 Token = 4\n\t\tDW\t96\t* 2\t; Index = 2 Token = 5\n\t\tDW\t128\t* 2\t; Index = 2 Token = 6\n\t\tDW\t160\t* 2\t; Index = 2 Token = 7\n\t\tDW\t16\t* 2\t; Index = 2 Token = 8\n\t\tDW\t16\t* 2\t; Index = 2 Token = 9\n\t\tDW\t16\t* 2\t; Index = 2 Token = 10\n\t\tDW\t16\t* 2\t; Index = 2 Token = 11\n\t\tDW\t64\t* 2\t; Index = 2 Token = 12\n\t\tDW\t96\t* 2\t; Index = 2 Token = 13\n\t\tDW\t128\t* 2\t; Index = 2 Token = 14\n\t\tDW\t160\t* 2\t; Index = 2 Token = 15\n\t\tDW\t32\t* 2\t; Index = 3 Token = 0\n\t\tDW\t32\t* 2\t; Index = 3 Token = 1\n\t\tDW\t32\t* 2\t; Index = 3 Token = 2\n\t\tDW\t32\t* 2\t; Index = 3 Token = 3\n\t\tDW\t80\t* 2\t; Index = 3 Token = 4\n\t\tDW\t112\t* 2\t; Index = 3 Token = 5\n\t\tDW\t144\t* 2\t; Index = 3 Token = 6\n\t\tDW\t176\t* 2\t; Index = 3 Token = 7\n\t\tDW\t32\t* 2\t; Index = 3 Token = 8\n\t\tDW\t32\t* 2\t; Index = 3 Token = 9\n\t\tDW\t32\t* 2\t; Index = 3 Token = 10\n\t\tDW\t32\t* 2\t; Index = 3 Token = 11\n\t\tDW\t80\t* 2\t; Index = 3 Token = 12\n\t\tDW\t112\t* 2\t; Index = 3 Token = 13\n\t\tDW\t144\t* 2\t; Index = 3 Token = 14\n\t\tDW\t176\t* 2\t; Index = 3 Token = 15\n\t\tDW\t48\t* 2\t; Index = 4 Token = 0\n\t\tDW\t48\t* 2\t; Index = 4 Token = 1\n\t\tDW\t48\t* 2\t; Index = 4 Token = 2\n\t\tDW\t48\t* 2\t; Index = 4 Token = 3\n\t\tDW\t96\t* 2\t; Index = 4 Token = 4\n\t\tDW\t128\t* 2\t; Index = 4 Token = 5\n\t\tDW\t160\t* 2\t; Index = 4 Token = 6\n\t\tDW\t192\t* 2\t; Index = 4 Token = 7\n\t\tDW\t48\t* 2\t; Index = 4 Token = 8\n\t\tDW\t48\t* 2\t; Index = 4 Token = 9\n\t\tDW\t48\t* 2\t; Index = 4 Token = 10\n\t\tDW\t48\t* 2\t; Index = 4 Token = 11\n\t\tDW\t96\t* 2\t; Index = 4 Token = 12\n\t\tDW\t128\t* 2\t; Index = 4 Token = 13\n\t\tDW\t160\t* 2\t; Index = 4 Token = 14\n\t\tDW\t192\t* 2\t; Index = 4 Token = 15\n\t\tDW\t64\t* 2\t; Index = 5 Token = 0\n\t\tDW\t64\t* 2\t; Index = 5 Token = 1\n\t\tDW\t64\t* 2\t; Index = 5 Token = 2\n\t\tDW\t64\t* 2\t; Index = 5 Token = 3\n\t\tDW\t112\t* 2\t; Index = 5 Token = 4\n\t\tDW\t144\t* 2\t; Index = 5 Token = 5\n\t\tDW\t176\t* 2\t; Index = 5 Token = 6\n\t\tDW\t208\t* 2\t; Index = 5 Token = 7\n\t\tDW\t64\t* 2\t; Index = 5 Token = 8\n\t\tDW\t64\t* 2\t; Index = 5 Token = 9\n\t\tDW\t64\t* 2\t; Index = 5 Token = 10\n\t\tDW\t64\t* 2\t; Index = 5 Token = 11\n\t\tDW\t112\t* 2\t; Index = 5 Token = 12\n\t\tDW\t144\t* 2\t; Index = 5 Token = 13\n\t\tDW\t176\t* 2\t; Index = 5 Token = 14\n\t\tDW\t208\t* 2\t; Index = 5 Token = 15\n\t\tDW\t80\t* 2\t; Index = 6 Token = 0\n\t\tDW\t80\t* 2\t; Index = 6 Token = 1\n\t\tDW\t80\t* 2\t; Index = 6 Token = 2\n\t\tDW\t80\t* 2\t; Index = 6 Token = 3\n\t\tDW\t128\t* 2\t; Index = 6 Token = 4\n\t\tDW\t160\t* 2\t; Index = 6 Token = 5\n\t\tDW\t192\t* 2\t; Index = 6 Token = 6\n\t\tDW\t224\t* 2\t; Index = 6 Token = 7\n\t\tDW\t80\t* 2\t; Index = 6 Token = 8\n\t\tDW\t80\t* 2\t; Index = 6 Token = 9\n\t\tDW\t80\t* 2\t; Index = 6 Token = 10\n\t\tDW\t80\t* 2\t; Index = 6 Token = 11\n\t\tDW\t128\t* 2\t; Index = 6 Token = 12\n\t\tDW\t160\t* 2\t; Index = 6 Token = 13\n\t\tDW\t192\t* 2\t; Index = 6 Token = 14\n\t\tDW\t224\t* 2\t; Index = 6 Token = 15\n\t\tDW\t96\t* 2\t; Index = 7 Token = 0\n\t\tDW\t96\t* 2\t; Index = 7 Token = 1\n\t\tDW\t96\t* 2\t; Index = 7 Token = 2\n\t\tDW\t96\t* 2\t; Index = 7 Token = 3\n\t\tDW\t144\t* 2\t; Index = 7 Token = 4\n\t\tDW\t176\t* 2\t; Index = 7 Token = 5\n\t\tDW\t208\t* 2\t; Index = 7 Token = 6\n\t\tDW\t240\t* 2\t; Index = 7 Token = 7\n\t\tDW\t96\t* 2\t; Index = 7 Token = 8\n\t\tDW\t96\t* 2\t; Index = 7 Token = 9\n\t\tDW\t96\t* 2\t; Index = 7 Token = 10\n\t\tDW\t96\t* 2\t; Index = 7 Token = 11\n\t\tDW\t144\t* 2\t; Index = 7 Token = 12\n\t\tDW\t176\t* 2\t; Index = 7 Token = 13\n\t\tDW\t208\t* 2\t; Index = 7 Token = 14\n\t\tDW\t240\t* 2\t; Index = 7 Token = 15\n\t\tDW\t112\t* 2\t; Index = 8 Token = 0\n\t\tDW\t112\t* 2\t; Index = 8 Token = 1\n\t\tDW\t112\t* 2\t; Index = 8 Token = 2\n\t\tDW\t112\t* 2\t; Index = 8 Token = 3\n\t\tDW\t160\t* 2\t; Index = 8 Token = 4\n\t\tDW\t192\t* 2\t; Index = 8 Token = 5\n\t\tDW\t224\t* 2\t; Index = 8 Token = 6\n\t\tDW\t256\t* 2\t; Index = 8 Token = 7\n\t\tDW\t112\t* 2\t; Index = 8 Token = 8\n\t\tDW\t112\t* 2\t; Index = 8 Token = 9\n\t\tDW\t112\t* 2\t; Index = 8 Token = 10\n\t\tDW\t112\t* 2\t; Index = 8 Token = 11\n\t\tDW\t160\t* 2\t; Index = 8 Token = 12\n\t\tDW\t192\t* 2\t; Index = 8 Token = 13\n\t\tDW\t224\t* 2\t; Index = 8 Token = 14\n\t\tDW\t256\t* 2\t; Index = 8 Token = 15\n\t\tDW\t128\t* 2\t; Index = 9 Token = 0\n\t\tDW\t128\t* 2\t; Index = 9 Token = 1\n\t\tDW\t128\t* 2\t; Index = 9 Token = 2\n\t\tDW\t128\t* 2\t; Index = 9 Token = 3\n\t\tDW\t176\t* 2\t; Index = 9 Token = 4\n\t\tDW\t208\t* 2\t; Index = 9 Token = 5\n\t\tDW\t240\t* 2\t; Index = 9 Token = 6\n\t\tDW\t272\t* 2\t; Index = 9 Token = 7\n\t\tDW\t128\t* 2\t; Index = 9 Token = 8\n\t\tDW\t128\t* 2\t; Index = 9 Token = 9\n\t\tDW\t128\t* 2\t; Index = 9 Token = 10\n\t\tDW\t128\t* 2\t; Index = 9 Token = 11\n\t\tDW\t176\t* 2\t; Index = 9 Token = 12\n\t\tDW\t208\t* 2\t; Index = 9 Token = 13\n\t\tDW\t240\t* 2\t; Index = 9 Token = 14\n\t\tDW\t272\t* 2\t; Index = 9 Token = 15\n\t\tDW\t144\t* 2\t; Index = 10 Token = 0\n\t\tDW\t144\t* 2\t; Index = 10 Token = 1\n\t\tDW\t144\t* 2\t; Index = 10 Token = 2\n\t\tDW\t144\t* 2\t; Index = 10 Token = 3\n\t\tDW\t192\t* 2\t; Index = 10 Token = 4\n\t\tDW\t224\t* 2\t; Index = 10 Token = 5\n\t\tDW\t256\t* 2\t; Index = 10 Token = 6\n\t\tDW\t288\t* 2\t; Index = 10 Token = 7\n\t\tDW\t144\t* 2\t; Index = 10 Token = 8\n\t\tDW\t144\t* 2\t; Index = 10 Token = 9\n\t\tDW\t144\t* 2\t; Index = 10 Token = 10\n\t\tDW\t144\t* 2\t; Index = 10 Token = 11\n\t\tDW\t192\t* 2\t; Index = 10 Token = 12\n\t\tDW\t224\t* 2\t; Index = 10 Token = 13\n\t\tDW\t256\t* 2\t; Index = 10 Token = 14\n\t\tDW\t288\t* 2\t; Index = 10 Token = 15\n\t\tDW\t160\t* 2\t; Index = 11 Token = 0\n\t\tDW\t160\t* 2\t; Index = 11 Token = 1\n\t\tDW\t160\t* 2\t; Index = 11 Token = 2\n\t\tDW\t160\t* 2\t; Index = 11 Token = 3\n\t\tDW\t208\t* 2\t; Index = 11 Token = 4\n\t\tDW\t240\t* 2\t; Index = 11 Token = 5\n\t\tDW\t272\t* 2\t; Index = 11 Token = 6\n\t\tDW\t304\t* 2\t; Index = 11 Token = 7\n\t\tDW\t160\t* 2\t; Index = 11 Token = 8\n\t\tDW\t160\t* 2\t; Index = 11 Token = 9\n\t\tDW\t160\t* 2\t; Index = 11 Token = 10\n\t\tDW\t160\t* 2\t; Index = 11 Token = 11\n\t\tDW\t208\t* 2\t; Index = 11 Token = 12\n\t\tDW\t240\t* 2\t; Index = 11 Token = 13\n\t\tDW\t272\t* 2\t; Index = 11 Token = 14\n\t\tDW\t304\t* 2\t; Index = 11 Token = 15\n\t\tDW\t176\t* 2\t; Index = 12 Token = 0\n\t\tDW\t176\t* 2\t; Index = 12 Token = 1\n\t\tDW\t176\t* 2\t; Index = 12 Token = 2\n\t\tDW\t176\t* 2\t; Index = 12 Token = 3\n\t\tDW\t224\t* 2\t; Index = 12 Token = 4\n\t\tDW\t256\t* 2\t; Index = 12 Token = 5\n\t\tDW\t288\t* 2\t; Index = 12 Token = 6\n\t\tDW\t320\t* 2\t; Index = 12 Token = 7\n\t\tDW\t176\t* 2\t; Index = 12 Token = 8\n\t\tDW\t176\t* 2\t; Index = 12 Token = 9\n\t\tDW\t176\t* 2\t; Index = 12 Token = 10\n\t\tDW\t176\t* 2\t; Index = 12 Token = 11\n\t\tDW\t224\t* 2\t; Index = 12 Token = 12\n\t\tDW\t256\t* 2\t; Index = 12 Token = 13\n\t\tDW\t288\t* 2\t; Index = 12 Token = 14\n\t\tDW\t320\t* 2\t; Index = 12 Token = 15\n\t\tDW\t192\t* 2\t; Index = 13 Token = 0\n\t\tDW\t192\t* 2\t; Index = 13 Token = 1\n\t\tDW\t192\t* 2\t; Index = 13 Token = 2\n\t\tDW\t192\t* 2\t; Index = 13 Token = 3\n\t\tDW\t240\t* 2\t; Index = 13 Token = 4\n\t\tDW\t272\t* 2\t; Index = 13 Token = 5\n\t\tDW\t304\t* 2\t; Index = 13 Token = 6\n\t\tDW\t336\t* 2\t; Index = 13 Token = 7\n\t\tDW\t192\t* 2\t; Index = 13 Token = 8\n\t\tDW\t192\t* 2\t; Index = 13 Token = 9\n\t\tDW\t192\t* 2\t; Index = 13 Token = 10\n\t\tDW\t192\t* 2\t; Index = 13 Token = 11\n\t\tDW\t240\t* 2\t; Index = 13 Token = 12\n\t\tDW\t272\t* 2\t; Index = 13 Token = 13\n\t\tDW\t304\t* 2\t; Index = 13 Token = 14\n\t\tDW\t336\t* 2\t; Index = 13 Token = 15\n\t\tDW\t208\t* 2\t; Index = 14 Token = 0\n\t\tDW\t208\t* 2\t; Index = 14 Token = 1\n\t\tDW\t208\t* 2\t; Index = 14 Token = 2\n\t\tDW\t208\t* 2\t; Index = 14 Token = 3\n\t\tDW\t256\t* 2\t; Index = 14 Token = 4\n\t\tDW\t288\t* 2\t; Index = 14 Token = 5\n\t\tDW\t320\t* 2\t; Index = 14 Token = 6\n\t\tDW\t352\t* 2\t; Index = 14 Token = 7\n\t\tDW\t208\t* 2\t; Index = 14 Token = 8\n\t\tDW\t208\t* 2\t; Index = 14 Token = 9\n\t\tDW\t208\t* 2\t; Index = 14 Token = 10\n\t\tDW\t208\t* 2\t; Index = 14 Token = 11\n\t\tDW\t256\t* 2\t; Index = 14 Token = 12\n\t\tDW\t288\t* 2\t; Index = 14 Token = 13\n\t\tDW\t320\t* 2\t; Index = 14 Token = 14\n\t\tDW\t352\t* 2\t; Index = 14 Token = 15\n\t\tDW\t224\t* 2\t; Index = 15 Token = 0\n\t\tDW\t224\t* 2\t; Index = 15 Token = 1\n\t\tDW\t224\t* 2\t; Index = 15 Token = 2\n\t\tDW\t224\t* 2\t; Index = 15 Token = 3\n\t\tDW\t272\t* 2\t; Index = 15 Token = 4\n\t\tDW\t304\t* 2\t; Index = 15 Token = 5\n\t\tDW\t336\t* 2\t; Index = 15 Token = 6\n\t\tDW\t368\t* 2\t; Index = 15 Token = 7\n\t\tDW\t224\t* 2\t; Index = 15 Token = 8\n\t\tDW\t224\t* 2\t; Index = 15 Token = 9\n\t\tDW\t224\t* 2\t; Index = 15 Token = 10\n\t\tDW\t224\t* 2\t; Index = 15 Token = 11\n\t\tDW\t272\t* 2\t; Index = 15 Token = 12\n\t\tDW\t304\t* 2\t; Index = 15 Token = 13\n\t\tDW\t336\t* 2\t; Index = 15 Token = 14\n\t\tDW\t368\t* 2\t; Index = 15 Token = 15\n\t\tDW\t240\t* 2\t; Index = 16 Token = 0\n\t\tDW\t240\t* 2\t; Index = 16 Token = 1\n\t\tDW\t240\t* 2\t; Index = 16 Token = 2\n\t\tDW\t240\t* 2\t; Index = 16 Token = 3\n\t\tDW\t288\t* 2\t; Index = 16 Token = 4\n\t\tDW\t320\t* 2\t; Index = 16 Token = 5\n\t\tDW\t352\t* 2\t; Index = 16 Token = 6\n\t\tDW\t384\t* 2\t; Index = 16 Token = 7\n\t\tDW\t240\t* 2\t; Index = 16 Token = 8\n\t\tDW\t240\t* 2\t; Index = 16 Token = 9\n\t\tDW\t240\t* 2\t; Index = 16 Token = 10\n\t\tDW\t240\t* 2\t; Index = 16 Token = 11\n\t\tDW\t288\t* 2\t; Index = 16 Token = 12\n\t\tDW\t320\t* 2\t; Index = 16 Token = 13\n\t\tDW\t352\t* 2\t; Index = 16 Token = 14\n\t\tDW\t384\t* 2\t; Index = 16 Token = 15\n\t\tDW\t256\t* 2\t; Index = 17 Token = 0\n\t\tDW\t256\t* 2\t; Index = 17 Token = 1\n\t\tDW\t256\t* 2\t; Index = 17 Token = 2\n\t\tDW\t256\t* 2\t; Index = 17 Token = 3\n\t\tDW\t304\t* 2\t; Index = 17 Token = 4\n\t\tDW\t336\t* 2\t; Index = 17 Token = 5\n\t\tDW\t368\t* 2\t; Index = 17 Token = 6\n\t\tDW\t400\t* 2\t; Index = 17 Token = 7\n\t\tDW\t256\t* 2\t; Index = 17 Token = 8\n\t\tDW\t256\t* 2\t; Index = 17 Token = 9\n\t\tDW\t256\t* 2\t; Index = 17 Token = 10\n\t\tDW\t256\t* 2\t; Index = 17 Token = 11\n\t\tDW\t304\t* 2\t; Index = 17 Token = 12\n\t\tDW\t336\t* 2\t; Index = 17 Token = 13\n\t\tDW\t368\t* 2\t; Index = 17 Token = 14\n\t\tDW\t400\t* 2\t; Index = 17 Token = 15\n\t\tDW\t272\t* 2\t; Index = 18 Token = 0\n\t\tDW\t272\t* 2\t; Index = 18 Token = 1\n\t\tDW\t272\t* 2\t; Index = 18 Token = 2\n\t\tDW\t272\t* 2\t; Index = 18 Token = 3\n\t\tDW\t320\t* 2\t; Index = 18 Token = 4\n\t\tDW\t352\t* 2\t; Index = 18 Token = 5\n\t\tDW\t384\t* 2\t; Index = 18 Token = 6\n\t\tDW\t416\t* 2\t; Index = 18 Token = 7\n\t\tDW\t272\t* 2\t; Index = 18 Token = 8\n\t\tDW\t272\t* 2\t; Index = 18 Token = 9\n\t\tDW\t272\t* 2\t; Index = 18 Token = 10\n\t\tDW\t272\t* 2\t; Index = 18 Token = 11\n\t\tDW\t320\t* 2\t; Index = 18 Token = 12\n\t\tDW\t352\t* 2\t; Index = 18 Token = 13\n\t\tDW\t384\t* 2\t; Index = 18 Token = 14\n\t\tDW\t416\t* 2\t; Index = 18 Token = 15\n\t\tDW\t288\t* 2\t; Index = 19 Token = 0\n\t\tDW\t288\t* 2\t; Index = 19 Token = 1\n\t\tDW\t288\t* 2\t; Index = 19 Token = 2\n\t\tDW\t288\t* 2\t; Index = 19 Token = 3\n\t\tDW\t336\t* 2\t; Index = 19 Token = 4\n\t\tDW\t368\t* 2\t; Index = 19 Token = 5\n\t\tDW\t400\t* 2\t; Index = 19 Token = 6\n\t\tDW\t432\t* 2\t; Index = 19 Token = 7\n\t\tDW\t288\t* 2\t; Index = 19 Token = 8\n\t\tDW\t288\t* 2\t; Index = 19 Token = 9\n\t\tDW\t288\t* 2\t; Index = 19 Token = 10\n\t\tDW\t288\t* 2\t; Index = 19 Token = 11\n\t\tDW\t336\t* 2\t; Index = 19 Token = 12\n\t\tDW\t368\t* 2\t; Index = 19 Token = 13\n\t\tDW\t400\t* 2\t; Index = 19 Token = 14\n\t\tDW\t432\t* 2\t; Index = 19 Token = 15\n\t\tDW\t304\t* 2\t; Index = 20 Token = 0\n\t\tDW\t304\t* 2\t; Index = 20 Token = 1\n\t\tDW\t304\t* 2\t; Index = 20 Token = 2\n\t\tDW\t304\t* 2\t; Index = 20 Token = 3\n\t\tDW\t352\t* 2\t; Index = 20 Token = 4\n\t\tDW\t384\t* 2\t; Index = 20 Token = 5\n\t\tDW\t416\t* 2\t; Index = 20 Token = 6\n\t\tDW\t448\t* 2\t; Index = 20 Token = 7\n\t\tDW\t304\t* 2\t; Index = 20 Token = 8\n\t\tDW\t304\t* 2\t; Index = 20 Token = 9\n\t\tDW\t304\t* 2\t; Index = 20 Token = 10\n\t\tDW\t304\t* 2\t; Index = 20 Token = 11\n\t\tDW\t352\t* 2\t; Index = 20 Token = 12\n\t\tDW\t384\t* 2\t; Index = 20 Token = 13\n\t\tDW\t416\t* 2\t; Index = 20 Token = 14\n\t\tDW\t448\t* 2\t; Index = 20 Token = 15\n\t\tDW\t320\t* 2\t; Index = 21 Token = 0\n\t\tDW\t320\t* 2\t; Index = 21 Token = 1\n\t\tDW\t320\t* 2\t; Index = 21 Token = 2\n\t\tDW\t320\t* 2\t; Index = 21 Token = 3\n\t\tDW\t368\t* 2\t; Index = 21 Token = 4\n\t\tDW\t400\t* 2\t; Index = 21 Token = 5\n\t\tDW\t432\t* 2\t; Index = 21 Token = 6\n\t\tDW\t464\t* 2\t; Index = 21 Token = 7\n\t\tDW\t320\t* 2\t; Index = 21 Token = 8\n\t\tDW\t320\t* 2\t; Index = 21 Token = 9\n\t\tDW\t320\t* 2\t; Index = 21 Token = 10\n\t\tDW\t320\t* 2\t; Index = 21 Token = 11\n\t\tDW\t368\t* 2\t; Index = 21 Token = 12\n\t\tDW\t400\t* 2\t; Index = 21 Token = 13\n\t\tDW\t432\t* 2\t; Index = 21 Token = 14\n\t\tDW\t464\t* 2\t; Index = 21 Token = 15\n\t\tDW\t336\t* 2\t; Index = 22 Token = 0\n\t\tDW\t336\t* 2\t; Index = 22 Token = 1\n\t\tDW\t336\t* 2\t; Index = 22 Token = 2\n\t\tDW\t336\t* 2\t; Index = 22 Token = 3\n\t\tDW\t384\t* 2\t; Index = 22 Token = 4\n\t\tDW\t416\t* 2\t; Index = 22 Token = 5\n\t\tDW\t448\t* 2\t; Index = 22 Token = 6\n\t\tDW\t480\t* 2\t; Index = 22 Token = 7\n\t\tDW\t336\t* 2\t; Index = 22 Token = 8\n\t\tDW\t336\t* 2\t; Index = 22 Token = 9\n\t\tDW\t336\t* 2\t; Index = 22 Token = 10\n\t\tDW\t336\t* 2\t; Index = 22 Token = 11\n\t\tDW\t384\t* 2\t; Index = 22 Token = 12\n\t\tDW\t416\t* 2\t; Index = 22 Token = 13\n\t\tDW\t448\t* 2\t; Index = 22 Token = 14\n\t\tDW\t480\t* 2\t; Index = 22 Token = 15\n\t\tDW\t352\t* 2\t; Index = 23 Token = 0\n\t\tDW\t352\t* 2\t; Index = 23 Token = 1\n\t\tDW\t352\t* 2\t; Index = 23 Token = 2\n\t\tDW\t352\t* 2\t; Index = 23 Token = 3\n\t\tDW\t400\t* 2\t; Index = 23 Token = 4\n\t\tDW\t432\t* 2\t; Index = 23 Token = 5\n\t\tDW\t464\t* 2\t; Index = 23 Token = 6\n\t\tDW\t496\t* 2\t; Index = 23 Token = 7\n\t\tDW\t352\t* 2\t; Index = 23 Token = 8\n\t\tDW\t352\t* 2\t; Index = 23 Token = 9\n\t\tDW\t352\t* 2\t; Index = 23 Token = 10\n\t\tDW\t352\t* 2\t; Index = 23 Token = 11\n\t\tDW\t400\t* 2\t; Index = 23 Token = 12\n\t\tDW\t432\t* 2\t; Index = 23 Token = 13\n\t\tDW\t464\t* 2\t; Index = 23 Token = 14\n\t\tDW\t496\t* 2\t; Index = 23 Token = 15\n\t\tDW\t368\t* 2\t; Index = 24 Token = 0\n\t\tDW\t368\t* 2\t; Index = 24 Token = 1\n\t\tDW\t368\t* 2\t; Index = 24 Token = 2\n\t\tDW\t368\t* 2\t; Index = 24 Token = 3\n\t\tDW\t416\t* 2\t; Index = 24 Token = 4\n\t\tDW\t448\t* 2\t; Index = 24 Token = 5\n\t\tDW\t480\t* 2\t; Index = 24 Token = 6\n\t\tDW\t512\t* 2\t; Index = 24 Token = 7\n\t\tDW\t368\t* 2\t; Index = 24 Token = 8\n\t\tDW\t368\t* 2\t; Index = 24 Token = 9\n\t\tDW\t368\t* 2\t; Index = 24 Token = 10\n\t\tDW\t368\t* 2\t; Index = 24 Token = 11\n\t\tDW\t416\t* 2\t; Index = 24 Token = 12\n\t\tDW\t448\t* 2\t; Index = 24 Token = 13\n\t\tDW\t480\t* 2\t; Index = 24 Token = 14\n\t\tDW\t512\t* 2\t; Index = 24 Token = 15\n\t\tDW\t384\t* 2\t; Index = 25 Token = 0\n\t\tDW\t384\t* 2\t; Index = 25 Token = 1\n\t\tDW\t384\t* 2\t; Index = 25 Token = 2\n\t\tDW\t384\t* 2\t; Index = 25 Token = 3\n\t\tDW\t432\t* 2\t; Index = 25 Token = 4\n\t\tDW\t464\t* 2\t; Index = 25 Token = 5\n\t\tDW\t496\t* 2\t; Index = 25 Token = 6\n\t\tDW\t528\t* 2\t; Index = 25 Token = 7\n\t\tDW\t384\t* 2\t; Index = 25 Token = 8\n\t\tDW\t384\t* 2\t; Index = 25 Token = 9\n\t\tDW\t384\t* 2\t; Index = 25 Token = 10\n\t\tDW\t384\t* 2\t; Index = 25 Token = 11\n\t\tDW\t432\t* 2\t; Index = 25 Token = 12\n\t\tDW\t464\t* 2\t; Index = 25 Token = 13\n\t\tDW\t496\t* 2\t; Index = 25 Token = 14\n\t\tDW\t528\t* 2\t; Index = 25 Token = 15\n\t\tDW\t400\t* 2\t; Index = 26 Token = 0\n\t\tDW\t400\t* 2\t; Index = 26 Token = 1\n\t\tDW\t400\t* 2\t; Index = 26 Token = 2\n\t\tDW\t400\t* 2\t; Index = 26 Token = 3\n\t\tDW\t448\t* 2\t; Index = 26 Token = 4\n\t\tDW\t480\t* 2\t; Index = 26 Token = 5\n\t\tDW\t512\t* 2\t; Index = 26 Token = 6\n\t\tDW\t544\t* 2\t; Index = 26 Token = 7\n\t\tDW\t400\t* 2\t; Index = 26 Token = 8\n\t\tDW\t400\t* 2\t; Index = 26 Token = 9\n\t\tDW\t400\t* 2\t; Index = 26 Token = 10\n\t\tDW\t400\t* 2\t; Index = 26 Token = 11\n\t\tDW\t448\t* 2\t; Index = 26 Token = 12\n\t\tDW\t480\t* 2\t; Index = 26 Token = 13\n\t\tDW\t512\t* 2\t; Index = 26 Token = 14\n\t\tDW\t544\t* 2\t; Index = 26 Token = 15\n\t\tDW\t416\t* 2\t; Index = 27 Token = 0\n\t\tDW\t416\t* 2\t; Index = 27 Token = 1\n\t\tDW\t416\t* 2\t; Index = 27 Token = 2\n\t\tDW\t416\t* 2\t; Index = 27 Token = 3\n\t\tDW\t464\t* 2\t; Index = 27 Token = 4\n\t\tDW\t496\t* 2\t; Index = 27 Token = 5\n\t\tDW\t528\t* 2\t; Index = 27 Token = 6\n\t\tDW\t560\t* 2\t; Index = 27 Token = 7\n\t\tDW\t416\t* 2\t; Index = 27 Token = 8\n\t\tDW\t416\t* 2\t; Index = 27 Token = 9\n\t\tDW\t416\t* 2\t; Index = 27 Token = 10\n\t\tDW\t416\t* 2\t; Index = 27 Token = 11\n\t\tDW\t464\t* 2\t; Index = 27 Token = 12\n\t\tDW\t496\t* 2\t; Index = 27 Token = 13\n\t\tDW\t528\t* 2\t; Index = 27 Token = 14\n\t\tDW\t560\t* 2\t; Index = 27 Token = 15\n\t\tDW\t432\t* 2\t; Index = 28 Token = 0\n\t\tDW\t432\t* 2\t; Index = 28 Token = 1\n\t\tDW\t432\t* 2\t; Index = 28 Token = 2\n\t\tDW\t432\t* 2\t; Index = 28 Token = 3\n\t\tDW\t480\t* 2\t; Index = 28 Token = 4\n\t\tDW\t512\t* 2\t; Index = 28 Token = 5\n\t\tDW\t544\t* 2\t; Index = 28 Token = 6\n\t\tDW\t576\t* 2\t; Index = 28 Token = 7\n\t\tDW\t432\t* 2\t; Index = 28 Token = 8\n\t\tDW\t432\t* 2\t; Index = 28 Token = 9\n\t\tDW\t432\t* 2\t; Index = 28 Token = 10\n\t\tDW\t432\t* 2\t; Index = 28 Token = 11\n\t\tDW\t480\t* 2\t; Index = 28 Token = 12\n\t\tDW\t512\t* 2\t; Index = 28 Token = 13\n\t\tDW\t544\t* 2\t; Index = 28 Token = 14\n\t\tDW\t576\t* 2\t; Index = 28 Token = 15\n\t\tDW\t448\t* 2\t; Index = 29 Token = 0\n\t\tDW\t448\t* 2\t; Index = 29 Token = 1\n\t\tDW\t448\t* 2\t; Index = 29 Token = 2\n\t\tDW\t448\t* 2\t; Index = 29 Token = 3\n\t\tDW\t496\t* 2\t; Index = 29 Token = 4\n\t\tDW\t528\t* 2\t; Index = 29 Token = 5\n\t\tDW\t560\t* 2\t; Index = 29 Token = 6\n\t\tDW\t592\t* 2\t; Index = 29 Token = 7\n\t\tDW\t448\t* 2\t; Index = 29 Token = 8\n\t\tDW\t448\t* 2\t; Index = 29 Token = 9\n\t\tDW\t448\t* 2\t; Index = 29 Token = 10\n\t\tDW\t448\t* 2\t; Index = 29 Token = 11\n\t\tDW\t496\t* 2\t; Index = 29 Token = 12\n\t\tDW\t528\t* 2\t; Index = 29 Token = 13\n\t\tDW\t560\t* 2\t; Index = 29 Token = 14\n\t\tDW\t592\t* 2\t; Index = 29 Token = 15\n\t\tDW\t464\t* 2\t; Index = 30 Token = 0\n\t\tDW\t464\t* 2\t; Index = 30 Token = 1\n\t\tDW\t464\t* 2\t; Index = 30 Token = 2\n\t\tDW\t464\t* 2\t; Index = 30 Token = 3\n\t\tDW\t512\t* 2\t; Index = 30 Token = 4\n\t\tDW\t544\t* 2\t; Index = 30 Token = 5\n\t\tDW\t576\t* 2\t; Index = 30 Token = 6\n\t\tDW\t608\t* 2\t; Index = 30 Token = 7\n\t\tDW\t464\t* 2\t; Index = 30 Token = 8\n\t\tDW\t464\t* 2\t; Index = 30 Token = 9\n\t\tDW\t464\t* 2\t; Index = 30 Token = 10\n\t\tDW\t464\t* 2\t; Index = 30 Token = 11\n\t\tDW\t512\t* 2\t; Index = 30 Token = 12\n\t\tDW\t544\t* 2\t; Index = 30 Token = 13\n\t\tDW\t576\t* 2\t; Index = 30 Token = 14\n\t\tDW\t608\t* 2\t; Index = 30 Token = 15\n\t\tDW\t480\t* 2\t; Index = 31 Token = 0\n\t\tDW\t480\t* 2\t; Index = 31 Token = 1\n\t\tDW\t480\t* 2\t; Index = 31 Token = 2\n\t\tDW\t480\t* 2\t; Index = 31 Token = 3\n\t\tDW\t528\t* 2\t; Index = 31 Token = 4\n\t\tDW\t560\t* 2\t; Index = 31 Token = 5\n\t\tDW\t592\t* 2\t; Index = 31 Token = 6\n\t\tDW\t624\t* 2\t; Index = 31 Token = 7\n\t\tDW\t480\t* 2\t; Index = 31 Token = 8\n\t\tDW\t480\t* 2\t; Index = 31 Token = 9\n\t\tDW\t480\t* 2\t; Index = 31 Token = 10\n\t\tDW\t480\t* 2\t; Index = 31 Token = 11\n\t\tDW\t528\t* 2\t; Index = 31 Token = 12\n\t\tDW\t560\t* 2\t; Index = 31 Token = 13\n\t\tDW\t592\t* 2\t; Index = 31 Token = 14\n\t\tDW\t624\t* 2\t; Index = 31 Token = 15\n\t\tDW\t496\t* 2\t; Index = 32 Token = 0\n\t\tDW\t496\t* 2\t; Index = 32 Token = 1\n\t\tDW\t496\t* 2\t; Index = 32 Token = 2\n\t\tDW\t496\t* 2\t; Index = 32 Token = 3\n\t\tDW\t544\t* 2\t; Index = 32 Token = 4\n\t\tDW\t576\t* 2\t; Index = 32 Token = 5\n\t\tDW\t608\t* 2\t; Index = 32 Token = 6\n\t\tDW\t640\t* 2\t; Index = 32 Token = 7\n\t\tDW\t496\t* 2\t; Index = 32 Token = 8\n\t\tDW\t496\t* 2\t; Index = 32 Token = 9\n\t\tDW\t496\t* 2\t; Index = 32 Token = 10\n\t\tDW\t496\t* 2\t; Index = 32 Token = 11\n\t\tDW\t544\t* 2\t; Index = 32 Token = 12\n\t\tDW\t576\t* 2\t; Index = 32 Token = 13\n\t\tDW\t608\t* 2\t; Index = 32 Token = 14\n\t\tDW\t640\t* 2\t; Index = 32 Token = 15\n\t\tDW\t512\t* 2\t; Index = 33 Token = 0\n\t\tDW\t512\t* 2\t; Index = 33 Token = 1\n\t\tDW\t512\t* 2\t; Index = 33 Token = 2\n\t\tDW\t512\t* 2\t; Index = 33 Token = 3\n\t\tDW\t560\t* 2\t; Index = 33 Token = 4\n\t\tDW\t592\t* 2\t; Index = 33 Token = 5\n\t\tDW\t624\t* 2\t; Index = 33 Token = 6\n\t\tDW\t656\t* 2\t; Index = 33 Token = 7\n\t\tDW\t512\t* 2\t; Index = 33 Token = 8\n\t\tDW\t512\t* 2\t; Index = 33 Token = 9\n\t\tDW\t512\t* 2\t; Index = 33 Token = 10\n\t\tDW\t512\t* 2\t; Index = 33 Token = 11\n\t\tDW\t560\t* 2\t; Index = 33 Token = 12\n\t\tDW\t592\t* 2\t; Index = 33 Token = 13\n\t\tDW\t624\t* 2\t; Index = 33 Token = 14\n\t\tDW\t656\t* 2\t; Index = 33 Token = 15\n\t\tDW\t528\t* 2\t; Index = 34 Token = 0\n\t\tDW\t528\t* 2\t; Index = 34 Token = 1\n\t\tDW\t528\t* 2\t; Index = 34 Token = 2\n\t\tDW\t528\t* 2\t; Index = 34 Token = 3\n\t\tDW\t576\t* 2\t; Index = 34 Token = 4\n\t\tDW\t608\t* 2\t; Index = 34 Token = 5\n\t\tDW\t640\t* 2\t; Index = 34 Token = 6\n\t\tDW\t672\t* 2\t; Index = 34 Token = 7\n\t\tDW\t528\t* 2\t; Index = 34 Token = 8\n\t\tDW\t528\t* 2\t; Index = 34 Token = 9\n\t\tDW\t528\t* 2\t; Index = 34 Token = 10\n\t\tDW\t528\t* 2\t; Index = 34 Token = 11\n\t\tDW\t576\t* 2\t; Index = 34 Token = 12\n\t\tDW\t608\t* 2\t; Index = 34 Token = 13\n\t\tDW\t640\t* 2\t; Index = 34 Token = 14\n\t\tDW\t672\t* 2\t; Index = 34 Token = 15\n\t\tDW\t544\t* 2\t; Index = 35 Token = 0\n\t\tDW\t544\t* 2\t; Index = 35 Token = 1\n\t\tDW\t544\t* 2\t; Index = 35 Token = 2\n\t\tDW\t544\t* 2\t; Index = 35 Token = 3\n\t\tDW\t592\t* 2\t; Index = 35 Token = 4\n\t\tDW\t624\t* 2\t; Index = 35 Token = 5\n\t\tDW\t656\t* 2\t; Index = 35 Token = 6\n\t\tDW\t688\t* 2\t; Index = 35 Token = 7\n\t\tDW\t544\t* 2\t; Index = 35 Token = 8\n\t\tDW\t544\t* 2\t; Index = 35 Token = 9\n\t\tDW\t544\t* 2\t; Index = 35 Token = 10\n\t\tDW\t544\t* 2\t; Index = 35 Token = 11\n\t\tDW\t592\t* 2\t; Index = 35 Token = 12\n\t\tDW\t624\t* 2\t; Index = 35 Token = 13\n\t\tDW\t656\t* 2\t; Index = 35 Token = 14\n\t\tDW\t688\t* 2\t; Index = 35 Token = 15\n\t\tDW\t560\t* 2\t; Index = 36 Token = 0\n\t\tDW\t560\t* 2\t; Index = 36 Token = 1\n\t\tDW\t560\t* 2\t; Index = 36 Token = 2\n\t\tDW\t560\t* 2\t; Index = 36 Token = 3\n\t\tDW\t608\t* 2\t; Index = 36 Token = 4\n\t\tDW\t640\t* 2\t; Index = 36 Token = 5\n\t\tDW\t672\t* 2\t; Index = 36 Token = 6\n\t\tDW\t704\t* 2\t; Index = 36 Token = 7\n\t\tDW\t560\t* 2\t; Index = 36 Token = 8\n\t\tDW\t560\t* 2\t; Index = 36 Token = 9\n\t\tDW\t560\t* 2\t; Index = 36 Token = 10\n\t\tDW\t560\t* 2\t; Index = 36 Token = 11\n\t\tDW\t608\t* 2\t; Index = 36 Token = 12\n\t\tDW\t640\t* 2\t; Index = 36 Token = 13\n\t\tDW\t672\t* 2\t; Index = 36 Token = 14\n\t\tDW\t704\t* 2\t; Index = 36 Token = 15\n\t\tDW\t576\t* 2\t; Index = 37 Token = 0\n\t\tDW\t576\t* 2\t; Index = 37 Token = 1\n\t\tDW\t576\t* 2\t; Index = 37 Token = 2\n\t\tDW\t576\t* 2\t; Index = 37 Token = 3\n\t\tDW\t624\t* 2\t; Index = 37 Token = 4\n\t\tDW\t656\t* 2\t; Index = 37 Token = 5\n\t\tDW\t688\t* 2\t; Index = 37 Token = 6\n\t\tDW\t720\t* 2\t; Index = 37 Token = 7\n\t\tDW\t576\t* 2\t; Index = 37 Token = 8\n\t\tDW\t576\t* 2\t; Index = 37 Token = 9\n\t\tDW\t576\t* 2\t; Index = 37 Token = 10\n\t\tDW\t576\t* 2\t; Index = 37 Token = 11\n\t\tDW\t624\t* 2\t; Index = 37 Token = 12\n\t\tDW\t656\t* 2\t; Index = 37 Token = 13\n\t\tDW\t688\t* 2\t; Index = 37 Token = 14\n\t\tDW\t720\t* 2\t; Index = 37 Token = 15\n\t\tDW\t592\t* 2\t; Index = 38 Token = 0\n\t\tDW\t592\t* 2\t; Index = 38 Token = 1\n\t\tDW\t592\t* 2\t; Index = 38 Token = 2\n\t\tDW\t592\t* 2\t; Index = 38 Token = 3\n\t\tDW\t640\t* 2\t; Index = 38 Token = 4\n\t\tDW\t672\t* 2\t; Index = 38 Token = 5\n\t\tDW\t704\t* 2\t; Index = 38 Token = 6\n\t\tDW\t736\t* 2\t; Index = 38 Token = 7\n\t\tDW\t592\t* 2\t; Index = 38 Token = 8\n\t\tDW\t592\t* 2\t; Index = 38 Token = 9\n\t\tDW\t592\t* 2\t; Index = 38 Token = 10\n\t\tDW\t592\t* 2\t; Index = 38 Token = 11\n\t\tDW\t640\t* 2\t; Index = 38 Token = 12\n\t\tDW\t672\t* 2\t; Index = 38 Token = 13\n\t\tDW\t704\t* 2\t; Index = 38 Token = 14\n\t\tDW\t736\t* 2\t; Index = 38 Token = 15\n\t\tDW\t608\t* 2\t; Index = 39 Token = 0\n\t\tDW\t608\t* 2\t; Index = 39 Token = 1\n\t\tDW\t608\t* 2\t; Index = 39 Token = 2\n\t\tDW\t608\t* 2\t; Index = 39 Token = 3\n\t\tDW\t656\t* 2\t; Index = 39 Token = 4\n\t\tDW\t688\t* 2\t; Index = 39 Token = 5\n\t\tDW\t720\t* 2\t; Index = 39 Token = 6\n\t\tDW\t752\t* 2\t; Index = 39 Token = 7\n\t\tDW\t608\t* 2\t; Index = 39 Token = 8\n\t\tDW\t608\t* 2\t; Index = 39 Token = 9\n\t\tDW\t608\t* 2\t; Index = 39 Token = 10\n\t\tDW\t608\t* 2\t; Index = 39 Token = 11\n\t\tDW\t656\t* 2\t; Index = 39 Token = 12\n\t\tDW\t688\t* 2\t; Index = 39 Token = 13\n\t\tDW\t720\t* 2\t; Index = 39 Token = 14\n\t\tDW\t752\t* 2\t; Index = 39 Token = 15\n\t\tDW\t624\t* 2\t; Index = 40 Token = 0\n\t\tDW\t624\t* 2\t; Index = 40 Token = 1\n\t\tDW\t624\t* 2\t; Index = 40 Token = 2\n\t\tDW\t624\t* 2\t; Index = 40 Token = 3\n\t\tDW\t672\t* 2\t; Index = 40 Token = 4\n\t\tDW\t704\t* 2\t; Index = 40 Token = 5\n\t\tDW\t736\t* 2\t; Index = 40 Token = 6\n\t\tDW\t768\t* 2\t; Index = 40 Token = 7\n\t\tDW\t624\t* 2\t; Index = 40 Token = 8\n\t\tDW\t624\t* 2\t; Index = 40 Token = 9\n\t\tDW\t624\t* 2\t; Index = 40 Token = 10\n\t\tDW\t624\t* 2\t; Index = 40 Token = 11\n\t\tDW\t672\t* 2\t; Index = 40 Token = 12\n\t\tDW\t704\t* 2\t; Index = 40 Token = 13\n\t\tDW\t736\t* 2\t; Index = 40 Token = 14\n\t\tDW\t768\t* 2\t; Index = 40 Token = 15\n\t\tDW\t640\t* 2\t; Index = 41 Token = 0\n\t\tDW\t640\t* 2\t; Index = 41 Token = 1\n\t\tDW\t640\t* 2\t; Index = 41 Token = 2\n\t\tDW\t640\t* 2\t; Index = 41 Token = 3\n\t\tDW\t688\t* 2\t; Index = 41 Token = 4\n\t\tDW\t720\t* 2\t; Index = 41 Token = 5\n\t\tDW\t752\t* 2\t; Index = 41 Token = 6\n\t\tDW\t784\t* 2\t; Index = 41 Token = 7\n\t\tDW\t640\t* 2\t; Index = 41 Token = 8\n\t\tDW\t640\t* 2\t; Index = 41 Token = 9\n\t\tDW\t640\t* 2\t; Index = 41 Token = 10\n\t\tDW\t640\t* 2\t; Index = 41 Token = 11\n\t\tDW\t688\t* 2\t; Index = 41 Token = 12\n\t\tDW\t720\t* 2\t; Index = 41 Token = 13\n\t\tDW\t752\t* 2\t; Index = 41 Token = 14\n\t\tDW\t784\t* 2\t; Index = 41 Token = 15\n\t\tDW\t656\t* 2\t; Index = 42 Token = 0\n\t\tDW\t656\t* 2\t; Index = 42 Token = 1\n\t\tDW\t656\t* 2\t; Index = 42 Token = 2\n\t\tDW\t656\t* 2\t; Index = 42 Token = 3\n\t\tDW\t704\t* 2\t; Index = 42 Token = 4\n\t\tDW\t736\t* 2\t; Index = 42 Token = 5\n\t\tDW\t768\t* 2\t; Index = 42 Token = 6\n\t\tDW\t800\t* 2\t; Index = 42 Token = 7\n\t\tDW\t656\t* 2\t; Index = 42 Token = 8\n\t\tDW\t656\t* 2\t; Index = 42 Token = 9\n\t\tDW\t656\t* 2\t; Index = 42 Token = 10\n\t\tDW\t656\t* 2\t; Index = 42 Token = 11\n\t\tDW\t704\t* 2\t; Index = 42 Token = 12\n\t\tDW\t736\t* 2\t; Index = 42 Token = 13\n\t\tDW\t768\t* 2\t; Index = 42 Token = 14\n\t\tDW\t800\t* 2\t; Index = 42 Token = 15\n\t\tDW\t672\t* 2\t; Index = 43 Token = 0\n\t\tDW\t672\t* 2\t; Index = 43 Token = 1\n\t\tDW\t672\t* 2\t; Index = 43 Token = 2\n\t\tDW\t672\t* 2\t; Index = 43 Token = 3\n\t\tDW\t720\t* 2\t; Index = 43 Token = 4\n\t\tDW\t752\t* 2\t; Index = 43 Token = 5\n\t\tDW\t784\t* 2\t; Index = 43 Token = 6\n\t\tDW\t816\t* 2\t; Index = 43 Token = 7\n\t\tDW\t672\t* 2\t; Index = 43 Token = 8\n\t\tDW\t672\t* 2\t; Index = 43 Token = 9\n\t\tDW\t672\t* 2\t; Index = 43 Token = 10\n\t\tDW\t672\t* 2\t; Index = 43 Token = 11\n\t\tDW\t720\t* 2\t; Index = 43 Token = 12\n\t\tDW\t752\t* 2\t; Index = 43 Token = 13\n\t\tDW\t784\t* 2\t; Index = 43 Token = 14\n\t\tDW\t816\t* 2\t; Index = 43 Token = 15\n\t\tDW\t688\t* 2\t; Index = 44 Token = 0\n\t\tDW\t688\t* 2\t; Index = 44 Token = 1\n\t\tDW\t688\t* 2\t; Index = 44 Token = 2\n\t\tDW\t688\t* 2\t; Index = 44 Token = 3\n\t\tDW\t736\t* 2\t; Index = 44 Token = 4\n\t\tDW\t768\t* 2\t; Index = 44 Token = 5\n\t\tDW\t800\t* 2\t; Index = 44 Token = 6\n\t\tDW\t832\t* 2\t; Index = 44 Token = 7\n\t\tDW\t688\t* 2\t; Index = 44 Token = 8\n\t\tDW\t688\t* 2\t; Index = 44 Token = 9\n\t\tDW\t688\t* 2\t; Index = 44 Token = 10\n\t\tDW\t688\t* 2\t; Index = 44 Token = 11\n\t\tDW\t736\t* 2\t; Index = 44 Token = 12\n\t\tDW\t768\t* 2\t; Index = 44 Token = 13\n\t\tDW\t800\t* 2\t; Index = 44 Token = 14\n\t\tDW\t832\t* 2\t; Index = 44 Token = 15\n\t\tDW\t704\t* 2\t; Index = 45 Token = 0\n\t\tDW\t704\t* 2\t; Index = 45 Token = 1\n\t\tDW\t704\t* 2\t; Index = 45 Token = 2\n\t\tDW\t704\t* 2\t; Index = 45 Token = 3\n\t\tDW\t752\t* 2\t; Index = 45 Token = 4\n\t\tDW\t784\t* 2\t; Index = 45 Token = 5\n\t\tDW\t816\t* 2\t; Index = 45 Token = 6\n\t\tDW\t848\t* 2\t; Index = 45 Token = 7\n\t\tDW\t704\t* 2\t; Index = 45 Token = 8\n\t\tDW\t704\t* 2\t; Index = 45 Token = 9\n\t\tDW\t704\t* 2\t; Index = 45 Token = 10\n\t\tDW\t704\t* 2\t; Index = 45 Token = 11\n\t\tDW\t752\t* 2\t; Index = 45 Token = 12\n\t\tDW\t784\t* 2\t; Index = 45 Token = 13\n\t\tDW\t816\t* 2\t; Index = 45 Token = 14\n\t\tDW\t848\t* 2\t; Index = 45 Token = 15\n\t\tDW\t720\t* 2\t; Index = 46 Token = 0\n\t\tDW\t720\t* 2\t; Index = 46 Token = 1\n\t\tDW\t720\t* 2\t; Index = 46 Token = 2\n\t\tDW\t720\t* 2\t; Index = 46 Token = 3\n\t\tDW\t768\t* 2\t; Index = 46 Token = 4\n\t\tDW\t800\t* 2\t; Index = 46 Token = 5\n\t\tDW\t832\t* 2\t; Index = 46 Token = 6\n\t\tDW\t864\t* 2\t; Index = 46 Token = 7\n\t\tDW\t720\t* 2\t; Index = 46 Token = 8\n\t\tDW\t720\t* 2\t; Index = 46 Token = 9\n\t\tDW\t720\t* 2\t; Index = 46 Token = 10\n\t\tDW\t720\t* 2\t; Index = 46 Token = 11\n\t\tDW\t768\t* 2\t; Index = 46 Token = 12\n\t\tDW\t800\t* 2\t; Index = 46 Token = 13\n\t\tDW\t832\t* 2\t; Index = 46 Token = 14\n\t\tDW\t864\t* 2\t; Index = 46 Token = 15\n\t\tDW\t736\t* 2\t; Index = 47 Token = 0\n\t\tDW\t736\t* 2\t; Index = 47 Token = 1\n\t\tDW\t736\t* 2\t; Index = 47 Token = 2\n\t\tDW\t736\t* 2\t; Index = 47 Token = 3\n\t\tDW\t784\t* 2\t; Index = 47 Token = 4\n\t\tDW\t816\t* 2\t; Index = 47 Token = 5\n\t\tDW\t848\t* 2\t; Index = 47 Token = 6\n\t\tDW\t880\t* 2\t; Index = 47 Token = 7\n\t\tDW\t736\t* 2\t; Index = 47 Token = 8\n\t\tDW\t736\t* 2\t; Index = 47 Token = 9\n\t\tDW\t736\t* 2\t; Index = 47 Token = 10\n\t\tDW\t736\t* 2\t; Index = 47 Token = 11\n\t\tDW\t784\t* 2\t; Index = 47 Token = 12\n\t\tDW\t816\t* 2\t; Index = 47 Token = 13\n\t\tDW\t848\t* 2\t; Index = 47 Token = 14\n\t\tDW\t880\t* 2\t; Index = 47 Token = 15\n\t\tDW\t752\t* 2\t; Index = 48 Token = 0\n\t\tDW\t752\t* 2\t; Index = 48 Token = 1\n\t\tDW\t752\t* 2\t; Index = 48 Token = 2\n\t\tDW\t752\t* 2\t; Index = 48 Token = 3\n\t\tDW\t800\t* 2\t; Index = 48 Token = 4\n\t\tDW\t832\t* 2\t; Index = 48 Token = 5\n\t\tDW\t864\t* 2\t; Index = 48 Token = 6\n\t\tDW\t896\t* 2\t; Index = 48 Token = 7\n\t\tDW\t752\t* 2\t; Index = 48 Token = 8\n\t\tDW\t752\t* 2\t; Index = 48 Token = 9\n\t\tDW\t752\t* 2\t; Index = 48 Token = 10\n\t\tDW\t752\t* 2\t; Index = 48 Token = 11\n\t\tDW\t800\t* 2\t; Index = 48 Token = 12\n\t\tDW\t832\t* 2\t; Index = 48 Token = 13\n\t\tDW\t864\t* 2\t; Index = 48 Token = 14\n\t\tDW\t896\t* 2\t; Index = 48 Token = 15\n\t\tDW\t768\t* 2\t; Index = 49 Token = 0\n\t\tDW\t768\t* 2\t; Index = 49 Token = 1\n\t\tDW\t768\t* 2\t; Index = 49 Token = 2\n\t\tDW\t768\t* 2\t; Index = 49 Token = 3\n\t\tDW\t816\t* 2\t; Index = 49 Token = 4\n\t\tDW\t848\t* 2\t; Index = 49 Token = 5\n\t\tDW\t880\t* 2\t; Index = 49 Token = 6\n\t\tDW\t912\t* 2\t; Index = 49 Token = 7\n\t\tDW\t768\t* 2\t; Index = 49 Token = 8\n\t\tDW\t768\t* 2\t; Index = 49 Token = 9\n\t\tDW\t768\t* 2\t; Index = 49 Token = 10\n\t\tDW\t768\t* 2\t; Index = 49 Token = 11\n\t\tDW\t816\t* 2\t; Index = 49 Token = 12\n\t\tDW\t848\t* 2\t; Index = 49 Token = 13\n\t\tDW\t880\t* 2\t; Index = 49 Token = 14\n\t\tDW\t912\t* 2\t; Index = 49 Token = 15\n\t\tDW\t784\t* 2\t; Index = 50 Token = 0\n\t\tDW\t784\t* 2\t; Index = 50 Token = 1\n\t\tDW\t784\t* 2\t; Index = 50 Token = 2\n\t\tDW\t784\t* 2\t; Index = 50 Token = 3\n\t\tDW\t832\t* 2\t; Index = 50 Token = 4\n\t\tDW\t864\t* 2\t; Index = 50 Token = 5\n\t\tDW\t896\t* 2\t; Index = 50 Token = 6\n\t\tDW\t928\t* 2\t; Index = 50 Token = 7\n\t\tDW\t784\t* 2\t; Index = 50 Token = 8\n\t\tDW\t784\t* 2\t; Index = 50 Token = 9\n\t\tDW\t784\t* 2\t; Index = 50 Token = 10\n\t\tDW\t784\t* 2\t; Index = 50 Token = 11\n\t\tDW\t832\t* 2\t; Index = 50 Token = 12\n\t\tDW\t864\t* 2\t; Index = 50 Token = 13\n\t\tDW\t896\t* 2\t; Index = 50 Token = 14\n\t\tDW\t928\t* 2\t; Index = 50 Token = 15\n\t\tDW\t800\t* 2\t; Index = 51 Token = 0\n\t\tDW\t800\t* 2\t; Index = 51 Token = 1\n\t\tDW\t800\t* 2\t; Index = 51 Token = 2\n\t\tDW\t800\t* 2\t; Index = 51 Token = 3\n\t\tDW\t848\t* 2\t; Index = 51 Token = 4\n\t\tDW\t880\t* 2\t; Index = 51 Token = 5\n\t\tDW\t912\t* 2\t; Index = 51 Token = 6\n\t\tDW\t944\t* 2\t; Index = 51 Token = 7\n\t\tDW\t800\t* 2\t; Index = 51 Token = 8\n\t\tDW\t800\t* 2\t; Index = 51 Token = 9\n\t\tDW\t800\t* 2\t; Index = 51 Token = 10\n\t\tDW\t800\t* 2\t; Index = 51 Token = 11\n\t\tDW\t848\t* 2\t; Index = 51 Token = 12\n\t\tDW\t880\t* 2\t; Index = 51 Token = 13\n\t\tDW\t912\t* 2\t; Index = 51 Token = 14\n\t\tDW\t944\t* 2\t; Index = 51 Token = 15\n\t\tDW\t816\t* 2\t; Index = 52 Token = 0\n\t\tDW\t816\t* 2\t; Index = 52 Token = 1\n\t\tDW\t816\t* 2\t; Index = 52 Token = 2\n\t\tDW\t816\t* 2\t; Index = 52 Token = 3\n\t\tDW\t864\t* 2\t; Index = 52 Token = 4\n\t\tDW\t896\t* 2\t; Index = 52 Token = 5\n\t\tDW\t928\t* 2\t; Index = 52 Token = 6\n\t\tDW\t960\t* 2\t; Index = 52 Token = 7\n\t\tDW\t816\t* 2\t; Index = 52 Token = 8\n\t\tDW\t816\t* 2\t; Index = 52 Token = 9\n\t\tDW\t816\t* 2\t; Index = 52 Token = 10\n\t\tDW\t816\t* 2\t; Index = 52 Token = 11\n\t\tDW\t864\t* 2\t; Index = 52 Token = 12\n\t\tDW\t896\t* 2\t; Index = 52 Token = 13\n\t\tDW\t928\t* 2\t; Index = 52 Token = 14\n\t\tDW\t960\t* 2\t; Index = 52 Token = 15\n\t\tDW\t832\t* 2\t; Index = 53 Token = 0\n\t\tDW\t832\t* 2\t; Index = 53 Token = 1\n\t\tDW\t832\t* 2\t; Index = 53 Token = 2\n\t\tDW\t832\t* 2\t; Index = 53 Token = 3\n\t\tDW\t880\t* 2\t; Index = 53 Token = 4\n\t\tDW\t912\t* 2\t; Index = 53 Token = 5\n\t\tDW\t944\t* 2\t; Index = 53 Token = 6\n\t\tDW\t976\t* 2\t; Index = 53 Token = 7\n\t\tDW\t832\t* 2\t; Index = 53 Token = 8\n\t\tDW\t832\t* 2\t; Index = 53 Token = 9\n\t\tDW\t832\t* 2\t; Index = 53 Token = 10\n\t\tDW\t832\t* 2\t; Index = 53 Token = 11\n\t\tDW\t880\t* 2\t; Index = 53 Token = 12\n\t\tDW\t912\t* 2\t; Index = 53 Token = 13\n\t\tDW\t944\t* 2\t; Index = 53 Token = 14\n\t\tDW\t976\t* 2\t; Index = 53 Token = 15\n\t\tDW\t848\t* 2\t; Index = 54 Token = 0\n\t\tDW\t848\t* 2\t; Index = 54 Token = 1\n\t\tDW\t848\t* 2\t; Index = 54 Token = 2\n\t\tDW\t848\t* 2\t; Index = 54 Token = 3\n\t\tDW\t896\t* 2\t; Index = 54 Token = 4\n\t\tDW\t928\t* 2\t; Index = 54 Token = 5\n\t\tDW\t960\t* 2\t; Index = 54 Token = 6\n\t\tDW\t992\t* 2\t; Index = 54 Token = 7\n\t\tDW\t848\t* 2\t; Index = 54 Token = 8\n\t\tDW\t848\t* 2\t; Index = 54 Token = 9\n\t\tDW\t848\t* 2\t; Index = 54 Token = 10\n\t\tDW\t848\t* 2\t; Index = 54 Token = 11\n\t\tDW\t896\t* 2\t; Index = 54 Token = 12\n\t\tDW\t928\t* 2\t; Index = 54 Token = 13\n\t\tDW\t960\t* 2\t; Index = 54 Token = 14\n\t\tDW\t992\t* 2\t; Index = 54 Token = 15\n\t\tDW\t864\t* 2\t; Index = 55 Token = 0\n\t\tDW\t864\t* 2\t; Index = 55 Token = 1\n\t\tDW\t864\t* 2\t; Index = 55 Token = 2\n\t\tDW\t864\t* 2\t; Index = 55 Token = 3\n\t\tDW\t912\t* 2\t; Index = 55 Token = 4\n\t\tDW\t944\t* 2\t; Index = 55 Token = 5\n\t\tDW\t976\t* 2\t; Index = 55 Token = 6\n\t\tDW\t1008\t* 2\t; Index = 55 Token = 7\n\t\tDW\t864\t* 2\t; Index = 55 Token = 8\n\t\tDW\t864\t* 2\t; Index = 55 Token = 9\n\t\tDW\t864\t* 2\t; Index = 55 Token = 10\n\t\tDW\t864\t* 2\t; Index = 55 Token = 11\n\t\tDW\t912\t* 2\t; Index = 55 Token = 12\n\t\tDW\t944\t* 2\t; Index = 55 Token = 13\n\t\tDW\t976\t* 2\t; Index = 55 Token = 14\n\t\tDW\t1008\t* 2\t; Index = 55 Token = 15\n\t\tDW\t880\t* 2\t; Index = 56 Token = 0\n\t\tDW\t880\t* 2\t; Index = 56 Token = 1\n\t\tDW\t880\t* 2\t; Index = 56 Token = 2\n\t\tDW\t880\t* 2\t; Index = 56 Token = 3\n\t\tDW\t928\t* 2\t; Index = 56 Token = 4\n\t\tDW\t960\t* 2\t; Index = 56 Token = 5\n\t\tDW\t992\t* 2\t; Index = 56 Token = 6\n\t\tDW\t1024\t* 2\t; Index = 56 Token = 7\n\t\tDW\t880\t* 2\t; Index = 56 Token = 8\n\t\tDW\t880\t* 2\t; Index = 56 Token = 9\n\t\tDW\t880\t* 2\t; Index = 56 Token = 10\n\t\tDW\t880\t* 2\t; Index = 56 Token = 11\n\t\tDW\t928\t* 2\t; Index = 56 Token = 12\n\t\tDW\t960\t* 2\t; Index = 56 Token = 13\n\t\tDW\t992\t* 2\t; Index = 56 Token = 14\n\t\tDW\t1024\t* 2\t; Index = 56 Token = 15\n\t\tDW\t896\t* 2\t; Index = 57 Token = 0\n\t\tDW\t896\t* 2\t; Index = 57 Token = 1\n\t\tDW\t896\t* 2\t; Index = 57 Token = 2\n\t\tDW\t896\t* 2\t; Index = 57 Token = 3\n\t\tDW\t944\t* 2\t; Index = 57 Token = 4\n\t\tDW\t976\t* 2\t; Index = 57 Token = 5\n\t\tDW\t1008\t* 2\t; Index = 57 Token = 6\n\t\tDW\t1040\t* 2\t; Index = 57 Token = 7\n\t\tDW\t896\t* 2\t; Index = 57 Token = 8\n\t\tDW\t896\t* 2\t; Index = 57 Token = 9\n\t\tDW\t896\t* 2\t; Index = 57 Token = 10\n\t\tDW\t896\t* 2\t; Index = 57 Token = 11\n\t\tDW\t944\t* 2\t; Index = 57 Token = 12\n\t\tDW\t976\t* 2\t; Index = 57 Token = 13\n\t\tDW\t1008\t* 2\t; Index = 57 Token = 14\n\t\tDW\t1040\t* 2\t; Index = 57 Token = 15\n\t\tDW\t912\t* 2\t; Index = 58 Token = 0\n\t\tDW\t912\t* 2\t; Index = 58 Token = 1\n\t\tDW\t912\t* 2\t; Index = 58 Token = 2\n\t\tDW\t912\t* 2\t; Index = 58 Token = 3\n\t\tDW\t960\t* 2\t; Index = 58 Token = 4\n\t\tDW\t992\t* 2\t; Index = 58 Token = 5\n\t\tDW\t1024\t* 2\t; Index = 58 Token = 6\n\t\tDW\t1056\t* 2\t; Index = 58 Token = 7\n\t\tDW\t912\t* 2\t; Index = 58 Token = 8\n\t\tDW\t912\t* 2\t; Index = 58 Token = 9\n\t\tDW\t912\t* 2\t; Index = 58 Token = 10\n\t\tDW\t912\t* 2\t; Index = 58 Token = 11\n\t\tDW\t960\t* 2\t; Index = 58 Token = 12\n\t\tDW\t992\t* 2\t; Index = 58 Token = 13\n\t\tDW\t1024\t* 2\t; Index = 58 Token = 14\n\t\tDW\t1056\t* 2\t; Index = 58 Token = 15\n\t\tDW\t928\t* 2\t; Index = 59 Token = 0\n\t\tDW\t928\t* 2\t; Index = 59 Token = 1\n\t\tDW\t928\t* 2\t; Index = 59 Token = 2\n\t\tDW\t928\t* 2\t; Index = 59 Token = 3\n\t\tDW\t976\t* 2\t; Index = 59 Token = 4\n\t\tDW\t1008\t* 2\t; Index = 59 Token = 5\n\t\tDW\t1040\t* 2\t; Index = 59 Token = 6\n\t\tDW\t1072\t* 2\t; Index = 59 Token = 7\n\t\tDW\t928\t* 2\t; Index = 59 Token = 8\n\t\tDW\t928\t* 2\t; Index = 59 Token = 9\n\t\tDW\t928\t* 2\t; Index = 59 Token = 10\n\t\tDW\t928\t* 2\t; Index = 59 Token = 11\n\t\tDW\t976\t* 2\t; Index = 59 Token = 12\n\t\tDW\t1008\t* 2\t; Index = 59 Token = 13\n\t\tDW\t1040\t* 2\t; Index = 59 Token = 14\n\t\tDW\t1072\t* 2\t; Index = 59 Token = 15\n\t\tDW\t944\t* 2\t; Index = 60 Token = 0\n\t\tDW\t944\t* 2\t; Index = 60 Token = 1\n\t\tDW\t944\t* 2\t; Index = 60 Token = 2\n\t\tDW\t944\t* 2\t; Index = 60 Token = 3\n\t\tDW\t992\t* 2\t; Index = 60 Token = 4\n\t\tDW\t1024\t* 2\t; Index = 60 Token = 5\n\t\tDW\t1056\t* 2\t; Index = 60 Token = 6\n\t\tDW\t1088\t* 2\t; Index = 60 Token = 7\n\t\tDW\t944\t* 2\t; Index = 60 Token = 8\n\t\tDW\t944\t* 2\t; Index = 60 Token = 9\n\t\tDW\t944\t* 2\t; Index = 60 Token = 10\n\t\tDW\t944\t* 2\t; Index = 60 Token = 11\n\t\tDW\t992\t* 2\t; Index = 60 Token = 12\n\t\tDW\t1024\t* 2\t; Index = 60 Token = 13\n\t\tDW\t1056\t* 2\t; Index = 60 Token = 14\n\t\tDW\t1088\t* 2\t; Index = 60 Token = 15\n\t\tDW\t960\t* 2\t; Index = 61 Token = 0\n\t\tDW\t960\t* 2\t; Index = 61 Token = 1\n\t\tDW\t960\t* 2\t; Index = 61 Token = 2\n\t\tDW\t960\t* 2\t; Index = 61 Token = 3\n\t\tDW\t1008\t* 2\t; Index = 61 Token = 4\n\t\tDW\t1040\t* 2\t; Index = 61 Token = 5\n\t\tDW\t1072\t* 2\t; Index = 61 Token = 6\n\t\tDW\t1104\t* 2\t; Index = 61 Token = 7\n\t\tDW\t960\t* 2\t; Index = 61 Token = 8\n\t\tDW\t960\t* 2\t; Index = 61 Token = 9\n\t\tDW\t960\t* 2\t; Index = 61 Token = 10\n\t\tDW\t960\t* 2\t; Index = 61 Token = 11\n\t\tDW\t1008\t* 2\t; Index = 61 Token = 12\n\t\tDW\t1040\t* 2\t; Index = 61 Token = 13\n\t\tDW\t1072\t* 2\t; Index = 61 Token = 14\n\t\tDW\t1104\t* 2\t; Index = 61 Token = 15\n\t\tDW\t976\t* 2\t; Index = 62 Token = 0\n\t\tDW\t976\t* 2\t; Index = 62 Token = 1\n\t\tDW\t976\t* 2\t; Index = 62 Token = 2\n\t\tDW\t976\t* 2\t; Index = 62 Token = 3\n\t\tDW\t1024\t* 2\t; Index = 62 Token = 4\n\t\tDW\t1056\t* 2\t; Index = 62 Token = 5\n\t\tDW\t1088\t* 2\t; Index = 62 Token = 6\n\t\tDW\t1120\t* 2\t; Index = 62 Token = 7\n\t\tDW\t976\t* 2\t; Index = 62 Token = 8\n\t\tDW\t976\t* 2\t; Index = 62 Token = 9\n\t\tDW\t976\t* 2\t; Index = 62 Token = 10\n\t\tDW\t976\t* 2\t; Index = 62 Token = 11\n\t\tDW\t1024\t* 2\t; Index = 62 Token = 12\n\t\tDW\t1056\t* 2\t; Index = 62 Token = 13\n\t\tDW\t1088\t* 2\t; Index = 62 Token = 14\n\t\tDW\t1120\t* 2\t; Index = 62 Token = 15\n\t\tDW\t992\t* 2\t; Index = 63 Token = 0\n\t\tDW\t992\t* 2\t; Index = 63 Token = 1\n\t\tDW\t992\t* 2\t; Index = 63 Token = 2\n\t\tDW\t992\t* 2\t; Index = 63 Token = 3\n\t\tDW\t1040\t* 2\t; Index = 63 Token = 4\n\t\tDW\t1072\t* 2\t; Index = 63 Token = 5\n\t\tDW\t1104\t* 2\t; Index = 63 Token = 6\n\t\tDW\t1136\t* 2\t; Index = 63 Token = 7\n\t\tDW\t992\t* 2\t; Index = 63 Token = 8\n\t\tDW\t992\t* 2\t; Index = 63 Token = 9\n\t\tDW\t992\t* 2\t; Index = 63 Token = 10\n\t\tDW\t992\t* 2\t; Index = 63 Token = 11\n\t\tDW\t1040\t* 2\t; Index = 63 Token = 12\n\t\tDW\t1072\t* 2\t; Index = 63 Token = 13\n\t\tDW\t1104\t* 2\t; Index = 63 Token = 14\n\t\tDW\t1136\t* 2\t; Index = 63 Token = 15\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 0\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 1\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 2\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 3\n\t\tDW\t1056\t* 2\t; Index = 64 Token = 4\n\t\tDW\t1088\t* 2\t; Index = 64 Token = 5\n\t\tDW\t1120\t* 2\t; Index = 64 Token = 6\n\t\tDW\t1152\t* 2\t; Index = 64 Token = 7\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 8\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 9\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 10\n\t\tDW\t1008\t* 2\t; Index = 64 Token = 11\n\t\tDW\t1056\t* 2\t; Index = 64 Token = 12\n\t\tDW\t1088\t* 2\t; Index = 64 Token = 13\n\t\tDW\t1120\t* 2\t; Index = 64 Token = 14\n\t\tDW\t1152\t* 2\t; Index = 64 Token = 15\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 0\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 1\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 2\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 3\n\t\tDW\t1072\t* 2\t; Index = 65 Token = 4\n\t\tDW\t1104\t* 2\t; Index = 65 Token = 5\n\t\tDW\t1136\t* 2\t; Index = 65 Token = 6\n\t\tDW\t1168\t* 2\t; Index = 65 Token = 7\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 8\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 9\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 10\n\t\tDW\t1024\t* 2\t; Index = 65 Token = 11\n\t\tDW\t1072\t* 2\t; Index = 65 Token = 12\n\t\tDW\t1104\t* 2\t; Index = 65 Token = 13\n\t\tDW\t1136\t* 2\t; Index = 65 Token = 14\n\t\tDW\t1168\t* 2\t; Index = 65 Token = 15\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 0\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 1\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 2\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 3\n\t\tDW\t1088\t* 2\t; Index = 66 Token = 4\n\t\tDW\t1120\t* 2\t; Index = 66 Token = 5\n\t\tDW\t1152\t* 2\t; Index = 66 Token = 6\n\t\tDW\t1184\t* 2\t; Index = 66 Token = 7\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 8\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 9\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 10\n\t\tDW\t1040\t* 2\t; Index = 66 Token = 11\n\t\tDW\t1088\t* 2\t; Index = 66 Token = 12\n\t\tDW\t1120\t* 2\t; Index = 66 Token = 13\n\t\tDW\t1152\t* 2\t; Index = 66 Token = 14\n\t\tDW\t1184\t* 2\t; Index = 66 Token = 15\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 0\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 1\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 2\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 3\n\t\tDW\t1104\t* 2\t; Index = 67 Token = 4\n\t\tDW\t1136\t* 2\t; Index = 67 Token = 5\n\t\tDW\t1168\t* 2\t; Index = 67 Token = 6\n\t\tDW\t1200\t* 2\t; Index = 67 Token = 7\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 8\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 9\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 10\n\t\tDW\t1056\t* 2\t; Index = 67 Token = 11\n\t\tDW\t1104\t* 2\t; Index = 67 Token = 12\n\t\tDW\t1136\t* 2\t; Index = 67 Token = 13\n\t\tDW\t1168\t* 2\t; Index = 67 Token = 14\n\t\tDW\t1200\t* 2\t; Index = 67 Token = 15\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 0\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 1\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 2\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 3\n\t\tDW\t1120\t* 2\t; Index = 68 Token = 4\n\t\tDW\t1152\t* 2\t; Index = 68 Token = 5\n\t\tDW\t1184\t* 2\t; Index = 68 Token = 6\n\t\tDW\t1216\t* 2\t; Index = 68 Token = 7\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 8\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 9\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 10\n\t\tDW\t1072\t* 2\t; Index = 68 Token = 11\n\t\tDW\t1120\t* 2\t; Index = 68 Token = 12\n\t\tDW\t1152\t* 2\t; Index = 68 Token = 13\n\t\tDW\t1184\t* 2\t; Index = 68 Token = 14\n\t\tDW\t1216\t* 2\t; Index = 68 Token = 15\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 0\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 1\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 2\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 3\n\t\tDW\t1136\t* 2\t; Index = 69 Token = 4\n\t\tDW\t1168\t* 2\t; Index = 69 Token = 5\n\t\tDW\t1200\t* 2\t; Index = 69 Token = 6\n\t\tDW\t1232\t* 2\t; Index = 69 Token = 7\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 8\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 9\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 10\n\t\tDW\t1088\t* 2\t; Index = 69 Token = 11\n\t\tDW\t1136\t* 2\t; Index = 69 Token = 12\n\t\tDW\t1168\t* 2\t; Index = 69 Token = 13\n\t\tDW\t1200\t* 2\t; Index = 69 Token = 14\n\t\tDW\t1232\t* 2\t; Index = 69 Token = 15\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 0\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 1\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 2\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 3\n\t\tDW\t1152\t* 2\t; Index = 70 Token = 4\n\t\tDW\t1184\t* 2\t; Index = 70 Token = 5\n\t\tDW\t1216\t* 2\t; Index = 70 Token = 6\n\t\tDW\t1248\t* 2\t; Index = 70 Token = 7\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 8\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 9\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 10\n\t\tDW\t1104\t* 2\t; Index = 70 Token = 11\n\t\tDW\t1152\t* 2\t; Index = 70 Token = 12\n\t\tDW\t1184\t* 2\t; Index = 70 Token = 13\n\t\tDW\t1216\t* 2\t; Index = 70 Token = 14\n\t\tDW\t1248\t* 2\t; Index = 70 Token = 15\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 0\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 1\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 2\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 3\n\t\tDW\t1168\t* 2\t; Index = 71 Token = 4\n\t\tDW\t1200\t* 2\t; Index = 71 Token = 5\n\t\tDW\t1232\t* 2\t; Index = 71 Token = 6\n\t\tDW\t1264\t* 2\t; Index = 71 Token = 7\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 8\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 9\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 10\n\t\tDW\t1120\t* 2\t; Index = 71 Token = 11\n\t\tDW\t1168\t* 2\t; Index = 71 Token = 12\n\t\tDW\t1200\t* 2\t; Index = 71 Token = 13\n\t\tDW\t1232\t* 2\t; Index = 71 Token = 14\n\t\tDW\t1264\t* 2\t; Index = 71 Token = 15\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 0\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 1\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 2\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 3\n\t\tDW\t1184\t* 2\t; Index = 72 Token = 4\n\t\tDW\t1216\t* 2\t; Index = 72 Token = 5\n\t\tDW\t1248\t* 2\t; Index = 72 Token = 6\n\t\tDW\t1280\t* 2\t; Index = 72 Token = 7\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 8\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 9\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 10\n\t\tDW\t1136\t* 2\t; Index = 72 Token = 11\n\t\tDW\t1184\t* 2\t; Index = 72 Token = 12\n\t\tDW\t1216\t* 2\t; Index = 72 Token = 13\n\t\tDW\t1248\t* 2\t; Index = 72 Token = 14\n\t\tDW\t1280\t* 2\t; Index = 72 Token = 15\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 0\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 1\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 2\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 3\n\t\tDW\t1200\t* 2\t; Index = 73 Token = 4\n\t\tDW\t1232\t* 2\t; Index = 73 Token = 5\n\t\tDW\t1264\t* 2\t; Index = 73 Token = 6\n\t\tDW\t1296\t* 2\t; Index = 73 Token = 7\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 8\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 9\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 10\n\t\tDW\t1152\t* 2\t; Index = 73 Token = 11\n\t\tDW\t1200\t* 2\t; Index = 73 Token = 12\n\t\tDW\t1232\t* 2\t; Index = 73 Token = 13\n\t\tDW\t1264\t* 2\t; Index = 73 Token = 14\n\t\tDW\t1296\t* 2\t; Index = 73 Token = 15\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 0\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 1\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 2\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 3\n\t\tDW\t1216\t* 2\t; Index = 74 Token = 4\n\t\tDW\t1248\t* 2\t; Index = 74 Token = 5\n\t\tDW\t1280\t* 2\t; Index = 74 Token = 6\n\t\tDW\t1312\t* 2\t; Index = 74 Token = 7\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 8\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 9\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 10\n\t\tDW\t1168\t* 2\t; Index = 74 Token = 11\n\t\tDW\t1216\t* 2\t; Index = 74 Token = 12\n\t\tDW\t1248\t* 2\t; Index = 74 Token = 13\n\t\tDW\t1280\t* 2\t; Index = 74 Token = 14\n\t\tDW\t1312\t* 2\t; Index = 74 Token = 15\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 0\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 1\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 2\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 3\n\t\tDW\t1232\t* 2\t; Index = 75 Token = 4\n\t\tDW\t1264\t* 2\t; Index = 75 Token = 5\n\t\tDW\t1296\t* 2\t; Index = 75 Token = 6\n\t\tDW\t1328\t* 2\t; Index = 75 Token = 7\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 8\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 9\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 10\n\t\tDW\t1184\t* 2\t; Index = 75 Token = 11\n\t\tDW\t1232\t* 2\t; Index = 75 Token = 12\n\t\tDW\t1264\t* 2\t; Index = 75 Token = 13\n\t\tDW\t1296\t* 2\t; Index = 75 Token = 14\n\t\tDW\t1328\t* 2\t; Index = 75 Token = 15\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 0\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 1\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 2\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 3\n\t\tDW\t1248\t* 2\t; Index = 76 Token = 4\n\t\tDW\t1280\t* 2\t; Index = 76 Token = 5\n\t\tDW\t1312\t* 2\t; Index = 76 Token = 6\n\t\tDW\t1344\t* 2\t; Index = 76 Token = 7\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 8\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 9\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 10\n\t\tDW\t1200\t* 2\t; Index = 76 Token = 11\n\t\tDW\t1248\t* 2\t; Index = 76 Token = 12\n\t\tDW\t1280\t* 2\t; Index = 76 Token = 13\n\t\tDW\t1312\t* 2\t; Index = 76 Token = 14\n\t\tDW\t1344\t* 2\t; Index = 76 Token = 15\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 0\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 1\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 2\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 3\n\t\tDW\t1264\t* 2\t; Index = 77 Token = 4\n\t\tDW\t1296\t* 2\t; Index = 77 Token = 5\n\t\tDW\t1328\t* 2\t; Index = 77 Token = 6\n\t\tDW\t1360\t* 2\t; Index = 77 Token = 7\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 8\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 9\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 10\n\t\tDW\t1216\t* 2\t; Index = 77 Token = 11\n\t\tDW\t1264\t* 2\t; Index = 77 Token = 12\n\t\tDW\t1296\t* 2\t; Index = 77 Token = 13\n\t\tDW\t1328\t* 2\t; Index = 77 Token = 14\n\t\tDW\t1360\t* 2\t; Index = 77 Token = 15\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 0\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 1\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 2\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 3\n\t\tDW\t1280\t* 2\t; Index = 78 Token = 4\n\t\tDW\t1312\t* 2\t; Index = 78 Token = 5\n\t\tDW\t1344\t* 2\t; Index = 78 Token = 6\n\t\tDW\t1376\t* 2\t; Index = 78 Token = 7\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 8\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 9\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 10\n\t\tDW\t1232\t* 2\t; Index = 78 Token = 11\n\t\tDW\t1280\t* 2\t; Index = 78 Token = 12\n\t\tDW\t1312\t* 2\t; Index = 78 Token = 13\n\t\tDW\t1344\t* 2\t; Index = 78 Token = 14\n\t\tDW\t1376\t* 2\t; Index = 78 Token = 15\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 0\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 1\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 2\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 3\n\t\tDW\t1296\t* 2\t; Index = 79 Token = 4\n\t\tDW\t1328\t* 2\t; Index = 79 Token = 5\n\t\tDW\t1360\t* 2\t; Index = 79 Token = 6\n\t\tDW\t1392\t* 2\t; Index = 79 Token = 7\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 8\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 9\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 10\n\t\tDW\t1248\t* 2\t; Index = 79 Token = 11\n\t\tDW\t1296\t* 2\t; Index = 79 Token = 12\n\t\tDW\t1328\t* 2\t; Index = 79 Token = 13\n\t\tDW\t1360\t* 2\t; Index = 79 Token = 14\n\t\tDW\t1392\t* 2\t; Index = 79 Token = 15\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 0\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 1\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 2\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 3\n\t\tDW\t1312\t* 2\t; Index = 80 Token = 4\n\t\tDW\t1344\t* 2\t; Index = 80 Token = 5\n\t\tDW\t1376\t* 2\t; Index = 80 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 80 Token = 7\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 8\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 9\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 10\n\t\tDW\t1264\t* 2\t; Index = 80 Token = 11\n\t\tDW\t1312\t* 2\t; Index = 80 Token = 12\n\t\tDW\t1344\t* 2\t; Index = 80 Token = 13\n\t\tDW\t1376\t* 2\t; Index = 80 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 80 Token = 15\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 0\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 1\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 2\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 3\n\t\tDW\t1328\t* 2\t; Index = 81 Token = 4\n\t\tDW\t1360\t* 2\t; Index = 81 Token = 5\n\t\tDW\t1392\t* 2\t; Index = 81 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 81 Token = 7\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 8\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 9\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 10\n\t\tDW\t1280\t* 2\t; Index = 81 Token = 11\n\t\tDW\t1328\t* 2\t; Index = 81 Token = 12\n\t\tDW\t1360\t* 2\t; Index = 81 Token = 13\n\t\tDW\t1392\t* 2\t; Index = 81 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 81 Token = 15\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 0\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 1\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 2\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 3\n\t\tDW\t1344\t* 2\t; Index = 82 Token = 4\n\t\tDW\t1376\t* 2\t; Index = 82 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 7\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 8\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 9\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 10\n\t\tDW\t1296\t* 2\t; Index = 82 Token = 11\n\t\tDW\t1344\t* 2\t; Index = 82 Token = 12\n\t\tDW\t1376\t* 2\t; Index = 82 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 82 Token = 15\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 0\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 1\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 2\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 3\n\t\tDW\t1360\t* 2\t; Index = 83 Token = 4\n\t\tDW\t1392\t* 2\t; Index = 83 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 7\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 8\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 9\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 10\n\t\tDW\t1312\t* 2\t; Index = 83 Token = 11\n\t\tDW\t1360\t* 2\t; Index = 83 Token = 12\n\t\tDW\t1392\t* 2\t; Index = 83 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 83 Token = 15\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 0\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 1\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 2\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 3\n\t\tDW\t1376\t* 2\t; Index = 84 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 7\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 8\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 9\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 10\n\t\tDW\t1328\t* 2\t; Index = 84 Token = 11\n\t\tDW\t1376\t* 2\t; Index = 84 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 84 Token = 15\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 0\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 1\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 2\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 3\n\t\tDW\t1392\t* 2\t; Index = 85 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 7\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 8\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 9\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 10\n\t\tDW\t1344\t* 2\t; Index = 85 Token = 11\n\t\tDW\t1392\t* 2\t; Index = 85 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 85 Token = 15\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 0\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 1\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 2\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 7\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 8\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 9\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 10\n\t\tDW\t1360\t* 2\t; Index = 86 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 86 Token = 15\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 0\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 1\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 2\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 7\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 8\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 9\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 10\n\t\tDW\t1376\t* 2\t; Index = 87 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 87 Token = 15\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 0\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 1\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 2\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 3\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 4\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 5\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 6\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 7\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 8\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 9\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 10\n\t\tDW\t1392\t* 2\t; Index = 88 Token = 11\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 12\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 13\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 14\n\t\tDW\t1408\t* 2\t; Index = 88 Token = 15\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/KEYBOARD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : KEYBOARD.H                               *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : July 13, 1994                            *\n *                                                                         *\n *                  Last Update : July 13, 1994   [PWG]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef KEYBOARD_H\n#define KEYBOARD_H\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n\nextern \"C\" {\n\tvoid Install_Keyboard_Interrupt(void *addr, long size);\n\tvoid Install_Page_Fault_Handle(void) ;\n\tvoid\t*Get_RM_Keyboard_Address(void);\n\tlong\tGet_RM_Keyboard_Size(void);\n\tvoid\tRemove_Keyboard_Interrupt(void);\n\tint\tCheck_Key_Num(void);\n\tint\tCheck_Key_Bits(void);\n\tint\tCheck_Key(void);\n\tshort\tGet_Key_Num(void);\n\tshort\tGet_Key_Bits(void);\n\tint\tGet_Key(void);\n\tint\tKN_To_KA(int keynum);\n\tint\tKeyboard_Attributes_On(int key_flags);\n\tint\tKeyboard_Attributes_Off(int key_flags);\n\tvoid\tClear_KeyBuffer(void);\n\tint\tKey_Down(int key);\n\tint\tKey_Satisfied(int key);\n\tvoid\tStuff_Key_WORD(int code);\n\tvoid\tStuff_Key_Num(int key);\n\tint   Install_Mouse(int max_width, int max_height, int scr_width, int scr_height);\n\tvoid\tReset_Mouse (void) ;\n\tvoid\tRemove_Mouse(void);\n\tint\tGet_Mouse_State(void);\n\tint\tGet_Mouse_X(void);\n\tint\tGet_Mouse_Y(void);\n\tint\tGet_Mouse_Disabled(void);\n\tvoid  *Set_Mouse_Cursor(int xhotspot,\tint yhotspot,\tvoid *cursor);\n\tvoid\tHide_Mouse(void);\n\tvoid\tShow_Mouse(void);\n\tvoid\tConditional_Hide_Mouse(int sx_pixel, int sy_pixel, int dx_pixel, int dy_pixel);\n\tvoid\tConditional_Show_Mouse(void);\n\n\n\tvoid  __interrupt far Keyboard_Interrupt(void);\n\textern int MouseQX;\n\textern int MouseQY;\n\n}\n\n\nenum {\n\tREPEATON     = 0x0001,\t/* 1:all makes into buffer, 0:only 1st make */\n\tTRACKEXT     = 0x0002,\t/* 1:Home != keypad Home, 0:Home=keypad Home */\n\tFILTERONLY   = 0x0004,\t/* 1:Normal BIOS operation with filter */\n\tCTRLALTTURBO = 0x0010,\t/* 1:Allow turbo up and down in application */\n\tNONUMLOCK    = 0x0200,\t/* 1:do NOT remap keypad to numbers */\n\tTASKSWITCHABLE = 0x400, /* 1:allows task switching keys thru ALT-TAB, */\n\t\t\t\t\t\t\t\t\t/*   ALT-ESC,CTRL-ESC */\n\tPASSBREAKS\t = 0x0800,\t// Pass all breaks to the keyboard buffer.\n\n\t/* The following flags, if turned on, should only be used for\n\t   debugging purposes (remember to take out the calls when BETA */\n\n\tCTRLSON      = 0x0008,\t/* 1:pass scroll lock sequence into BIOS */\n\tCTRLCON      = 0x0020,\t/* 1:pass stop code to BIOS */\n\tSCROLLLOCKON = 0x0040,\t/* 1:pass scroll lock key into BIOS */\n\tPAUSEON      = 0x0080,\t/* 1:pass the pause key and seq to BIOS */\n\t\t\t\t\t\t\t\t\t/*   make sure FILTERONLY is set */\n\tBREAKON      = 0x0100,\t/* 1:pass the ctrl break seq to BIOS */\n\tKEYMOUSE     = 0x1000,\t/* 1:keypad translates into mouse moves */\n\tSIMLBUTTON   = 0x2000,\t/* 1:have space and enter keys simulate Left */\n\t\t\t\t\t\t\t\t\t/*   mouse button when KEYMOUSE is set */\n\tDEBUGINT\t\t = 0x4000\t/* Use scroll lock to disable keyboard int */\n};\n\n\n/*\n**\tThese are the codes for the various key codes that are returned from the\n**\tkeyboard input routines Get_Key() and Input_ASCII().\n*/\ntypedef enum {\n\tKA_CTRL_AT = 0,\n\tKA_CTRL_A,\n\tKA_MORE = KA_CTRL_A,\n\tKA_CTRL_B,\n\tKA_SETBKGDCOL = KA_CTRL_B,\n\tKA_CTRL_C,\n\tKA_CTRL_D,\n\tKA_CTRL_E,\n\tKA_CTRL_F,\n\tKA_SETFORECOL = KA_CTRL_F,\n\tKA_CTRL_G,\n\tKA_CTRL_H,\n\tKA_BACKSPACE = KA_CTRL_H,\n\tKA_CTRL_I,\n\tKA_TAB = KA_CTRL_I,\n\tKA_CTRL_J,\n\tKA_CTRL_K,\n\tKA_CTRL_L,\n\tKA_FORMFEED = KA_CTRL_L,\n\tKA_CTRL_M,\n\tKA_RETURN = KA_CTRL_M,\n\tKA_CTRL_N,\n\n\tKA_CTRL_O,\n\tKA_CTRL_P,\n\tKA_CTRL_Q,\n\tKA_CTRL_R,\n\tKA_CTRL_S,\n\tKA_SPCTAB = KA_CTRL_S,\n\tKA_CTRL_T,\n\tKA_CTRL_U,\n\tKA_CTRL_V,\n\tKA_CTRL_W,\n\tKA_CTRL_X,\n\tKA_SETX = KA_CTRL_X,\n\tKA_CTRL_Y,\n\tKA_SETY = KA_CTRL_Y,\n\tKA_CTRL_Z,\n\tKA_CTRL_LBRACKET,\n\tKA_ESC = KA_CTRL_LBRACKET,\n\tKA_EXTEND = KA_ESC,\n\tKA_CTRL_BACKSLASH,\n\tKA_CTRL_RBRACKET,\n\tKA_LITERAL = KA_CTRL_RBRACKET,\n\tKA_CTRL_CARROT,\n\tKA_CTRL_UNDERLINE,\n\n\tKA_SPACE,\t\t\t\t\t\t\t\t\t/*   */\n\tKA_EXCLAMATION,\t\t\t\t\t\t\t/* ! */\n\tKA_DQUOTE,\t\t\t\t\t\t\t\t\t/* \" */\n\tKA_POUND,\t\t\t\t\t\t\t\t\t/* # */\n\tKA_DOLLAR,\t\t\t\t\t\t\t\t\t/* $ */\n\tKA_PERCENT,\t\t\t\t\t\t\t\t\t/* % */\n\tKA_AMPER,\t\t\t\t\t\t\t\t\t/* & */\n\tKA_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKA_LPAREN,\t\t\t\t\t\t\t\t\t/* ( */\n\tKA_RPAREN,\t\t\t\t\t\t\t\t\t/* ) */\n\tKA_ASTERISK,\t\t\t\t\t\t\t\t/* * */\n\tKA_PLUS,\t\t\t\t\t\t\t\t\t\t/* + */\n\tKA_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKA_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKA_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKA_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKA_0, KA_1, KA_2, KA_3, KA_4, KA_5, KA_6, KA_7, KA_8, KA_9,\n\tKA_COLON,\t\t\t\t\t\t\t\t\t/* : */\n\tKA_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKA_LESS_THAN,\t\t\t\t\t\t\t\t/* < */\n\tKA_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\tKA_GREATER_THAN,\t\t\t\t\t\t\t/* > */\n\tKA_QUESTION,\t\t\t\t\t\t\t\t/* ? */\n\n\tKA_AT,\t\t\t\t\t\t\t\t\t\t/* @ */\n\tKA_A,\t\t\t\t\t\t\t\t\t\t\t/* A */\n\tKA_B,\t\t\t\t\t\t\t\t\t\t\t/* B */\n\tKA_C,\t\t\t\t\t\t\t\t\t\t\t/* C */\n\tKA_D,\t\t\t\t\t\t\t\t\t\t\t/* D */\n\tKA_E,\t\t\t\t\t\t\t\t\t\t\t/* E */\n\tKA_F,\t\t\t\t\t\t\t\t\t\t\t/* F */\n\tKA_G,\t\t\t\t\t\t\t\t\t\t\t/* G */\n\tKA_H,\t\t\t\t\t\t\t\t\t\t\t/* H */\n\tKA_I,\t\t\t\t\t\t\t\t\t\t\t/* I */\n\tKA_J,\t\t\t\t\t\t\t\t\t\t\t/* J */\n\tKA_K,\t\t\t\t\t\t\t\t\t\t\t/* K */\n\tKA_L,\t\t\t\t\t\t\t\t\t\t\t/* L */\n\tKA_M,\t\t\t\t\t\t\t\t\t\t\t/* M */\n\tKA_N,\t\t\t\t\t\t\t\t\t\t\t/* N */\n\tKA_O,\t\t\t\t\t\t\t\t\t\t\t/* O */\n\n\tKA_P,\t\t\t\t\t\t\t\t\t\t\t/* P */\n\tKA_Q,\t\t\t\t\t\t\t\t\t\t\t/* Q */\n\tKA_R,\t\t\t\t\t\t\t\t\t\t\t/* R */\n\tKA_S,\t\t\t\t\t\t\t\t\t\t\t/* S */\n\tKA_T,\t\t\t\t\t\t\t\t\t\t\t/* T */\n\tKA_U,\t\t\t\t\t\t\t\t\t\t\t/* U */\n\tKA_V,\t\t\t\t\t\t\t\t\t\t\t/* V */\n\tKA_W,\t\t\t\t\t\t\t\t\t\t\t/* W */\n\tKA_X,\t\t\t\t\t\t\t\t\t\t\t/* X */\n\tKA_Y,\t\t\t\t\t\t\t\t\t\t\t/* Y */\n\tKA_Z,\t\t\t\t\t\t\t\t\t\t\t/* Z */\n\tKA_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKA_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\tKA_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKA_CARROT,\t\t\t\t\t\t\t\t\t/* ^ */\n\tKA_UNDERLINE,\t\t\t\t\t\t\t\t/* _ */\n\n\tKA_GRAVE,\t\t\t\t\t\t\t\t\t/* ` */\n\tKA_a,\t\t\t\t\t\t\t\t\t\t\t/* a */\n\tKA_b,\t\t\t\t\t\t\t\t\t\t\t/* b */\n\tKA_c,\t\t\t\t\t\t\t\t\t\t\t/* c */\n\tKA_d,\t\t\t\t\t\t\t\t\t\t\t/* d */\n\tKA_e,\t\t\t\t\t\t\t\t\t\t\t/* e */\n\tKA_f,\t\t\t\t\t\t\t\t\t\t\t/* f */\n\tKA_g,\t\t\t\t\t\t\t\t\t\t\t/* g */\n\tKA_h,\t\t\t\t\t\t\t\t\t\t\t/* h */\n\tKA_i,\t\t\t\t\t\t\t\t\t\t\t/* i */\n\tKA_j,\t\t\t\t\t\t\t\t\t\t\t/* j */\n\tKA_k,\t\t\t\t\t\t\t\t\t\t\t/* k */\n\tKA_l,\t\t\t\t\t\t\t\t\t\t\t/* l */\n\tKA_m,\t\t\t\t\t\t\t\t\t\t\t/* m */\n\tKA_n,\t\t\t\t\t\t\t\t\t\t\t/* n */\n\tKA_o,\t\t\t\t\t\t\t\t\t\t\t/* o */\n\n\tKA_p,\t\t\t\t\t\t\t\t\t\t\t/* p */\n\tKA_q,\t\t\t\t\t\t\t\t\t\t\t/* q */\n\tKA_r,\t\t\t\t\t\t\t\t\t\t\t/* r */\n\tKA_s,\t\t\t\t\t\t\t\t\t\t\t/* s */\n\tKA_t,\t\t\t\t\t\t\t\t\t\t\t/* t */\n\tKA_u,\t\t\t\t\t\t\t\t\t\t\t/* u */\n\tKA_v,\t\t\t\t\t\t\t\t\t\t\t/* v */\n\tKA_w,\t\t\t\t\t\t\t\t\t\t\t/* w */\n\tKA_x,\t\t\t\t\t\t\t\t\t\t\t/* x */\n\tKA_y,\t\t\t\t\t\t\t\t\t\t\t/* y */\n\tKA_z,\t\t\t\t\t\t\t\t\t\t\t/* z */\n\tKA_LBRACE,\t\t\t\t\t\t\t\t\t/* { */\n\tKA_BAR,\t\t\t\t\t\t\t\t\t\t/* | */\n\tKA_RBRACE,\t\t\t\t\t\t\t\t\t/* ] */\n\tKA_TILDA,\t\t\t\t\t\t\t\t\t/* ~ */\n\tKA_DEL,\t\t\t\t\t\t\t\t\t\t/* not used */\n\n\tKA_ALT_F10 = 143,\n\tKA_ALT_F9,    KA_ALT_F8,   KA_ALT_F7,   KA_ALT_F6,   KA_ALT_F5,\n\tKA_ALT_F4,    KA_ALT_F3,   KA_ALT_F2,   KA_ALT_F1,\n\n\tKA_CTRL_F10,  KA_CTRL_F9,  KA_CTRL_F8,  KA_CTRL_F7,  KA_CTRL_F6,\n\tKA_CTRL_F5,   KA_CTRL_F4,  KA_CTRL_F3,  KA_CTRL_F2,  KA_CTRL_F1,\n\n\tKA_SHIFT_F10, KA_SHIFT_F9, KA_SHIFT_F8, KA_SHIFT_F7, KA_SHIFT_F6,\n\tKA_SHIFT_F5,  KA_SHIFT_F4, KA_SHIFT_F3, KA_SHIFT_F2, KA_SHIFT_F1,\n\n\tKA_DELETE,\t\t\t\t\t\t\t\t\t/* <DELETE> */\n\tKA_INSERT,\t\t\t\t\t\t\t\t\t/* <INSERT> */\n\tKA_PGDN,\t\t\t\t\t\t\t\t\t\t/* <PAGE DOWN> */\n\tKA_DOWNRIGHT = KA_PGDN,\n\tKA_DOWN,\t\t\t\t\t\t\t\t\t\t/* <DOWN ARROW> */\n\tKA_END,\t\t\t\t\t\t\t\t\t\t/* <END> */\n\tKA_DOWNLEFT = KA_END,\n\n\tKA_RESERVED1,\n\n\tKA_RIGHT,\t\t\t\t\t\t\t\t\t/* <RIGHT ARROW> */\n\tKA_KEYPAD5,\t\t\t\t\t\t\t\t\t/* NUMERIC KEY PAD <5> */\n\tKA_LEFT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ARROW> */\n\n\tKA_RESERVED2,\n\n\tKA_PGUP,\t\t\t\t\t\t\t\t\t\t/* <PAGE UP> */\n\tKA_UPRIGHT = KA_PGUP,\n\tKA_UP,\t\t\t\t\t\t\t\t\t\t/* <UP ARROW> */\n\tKA_HOME,\t\t\t\t\t\t\t\t\t\t/* <HOME> */\n\tKA_UPLEFT = KA_HOME,\n\t\n\tKA_RESERVED3,\n\tKA_RESERVED4,\n\n\tKA_F10, KA_F9, KA_F8, KA_F7, KA_F6, KA_F5, KA_F4, KA_F3, KA_F2, KA_F1,\n\n\tKA_LMOUSE,\n\tKA_RMOUSE,\n\tKA_JBUTTON1,\n\tKA_JBUTTON2,\n\tKA_J_UP,\n\tKA_J_RIGHT,\n\tKA_J_DOWN,\n\tKA_J_LEFT,\n\n\tKA_SHIFT_BIT = 0x0100,\n\tKA_CTRL_BIT  = 0x0200,\n\tKA_ALT_BIT   = 0x0400,\n\tKA_RLSE_BIT  = 0x0800,\n\tKA_LCOMM_BIT = 0x1000,\t\t\t\t\t/* Amiga Left Comm key\t*/\n\tKA_RCOMM_BIT = 0x2000\t\t\t\t\t/* Amiga Right Comm key\t*/\n} KeyASCIIType;\n\n/*\n**\tThese are the keyboard codes that are returned from the input routines\n**\tGet_Key_Num and Input_Num.\n*/\ntypedef enum {\n\tKN_NONE = 0,\n\tKN_GRAVE = 1,\t\t\t\t\t\t\t\t/* ` */\n\tKN_1, KN_2, KN_3, KN_4, KN_5, KN_6, KN_7, KN_8, KN_9, KN_0,\n\tKN_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKN_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\n\tKN_RESERVED1,\n\n\tKN_BACKSPACE,\t\t\t\t\t\t\t\t/* <BACKSPACE> */\n\n\tKN_TAB,\t\t\t\t\t\t\t\t\t\t/* <TAB> */\n\tKN_Q, KN_W, KN_E, KN_R, KN_T, KN_Y, KN_U, KN_I, KN_O, KN_P,\n\tKN_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKN_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKN_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\n\tKN_CAPSLOCK,\t\t\t\t\t\t\t\t/* <CAPS LOCK> */\n\tKN_A, KN_S, KN_D, KN_F, KN_G, KN_H, KN_J, KN_K, KN_L,\n\tKN_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKN_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKN_BACKSLASH2,\n\tKN_RETURN,\t\t\t\t\t\t\t\t\t/* <RETURN> or <ENTER> */\n\n\tKN_LSHIFT,\t\t\t\t\t\t\t\t\t/* <LEFT SHIFT> */\n\n\tKN_MOUSE_MOVE,\t\t\t\t\t\t\t\t// Indicate a mouse move (for playback of\n\n\tKN_Z, KN_X, KN_C, KN_V, KN_B, KN_N, KN_M,\n\tKN_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKN_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKN_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKN_RESERVED3,\n\n\tKN_RSHIFT,\t\t\t\t\t\t\t\t\t/* <RIGHT SHIFT> */\n\n\tKN_LCTRL,\t\t\t\t\t\t\t\t\t/* <LEFT CTRL> */\n\tKN_LCOMM,\t\t\t\t\t\t\t\t\t/* for AMIGA */\n\tKN_LALT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ALT> */\n\tKN_SPACE,\t\t\t\t\t\t\t\t\t/* <SPACE BAR> */\n\tKN_RALT,\t\t\t\t\t\t\t\t\t\t/* <RIGHT ALT> */\n\tKN_RCOMM,\t\t\t\t\t\t\t\t\t/* for AMIGA */\n\tKN_RCTRL,\t\t\t\t\t\t\t\t\t/* <RIGHT CTRL> */\n\t\t\t\t\t\t\t/* the following are forced into key buffer */\n\tKN_LMOUSE,\n\tKN_RMOUSE,\n\tKN_JBUTTON1,\n\tKN_JBUTTON2,\n\tKN_J_UP,\n\tKN_J_RIGHT,\n\tKN_J_DOWN,\n\tKN_J_LEFT,\n\n\tKN_SPECIAL9,\n\n\tKN_SPECIAL10,\n\n\tKN_E_INSERT,\t\t\t\t\t\t\t\t/* extended <INSERT> */\n\tKN_E_DELETE,\t\t\t\t\t\t\t\t/* extended <DELETE> */\n\n\tKN_RESERVED4,\n\tKN_RESERVED5,\n\n\tKN_E_LEFT,\t\t\t\t\t\t\t\t\t/* extended <LEFT ARROW> */\n\tKN_E_HOME,\t\t\t\t\t\t\t\t\t/* extended <HOME> */\n\tKN_E_END,\t\t\t\t\t\t\t\t\t/* extended <END> */\n\n\tKN_RESERVED6,\n\n\tKN_E_UP,\t\t\t\t\t\t\t\t\t\t/* extended <UP ARROW> */\n\tKN_E_DOWN,\t\t\t\t\t\t\t\t\t/* extended <DOWN ARROW> */\n\tKN_E_PGUP,\t\t\t\t\t\t\t\t\t/* extended <PAGE UP> */\n\tKN_E_PGDN,\t\t\t\t\t\t\t\t\t/* extended <PAGE DOWN> */\n\tKN_K_LPAREN,\t\t\t/* for AMIGA */\n\tKN_K_RPAREN,\t\t\t/* for AMIGA */\n\tKN_E_RIGHT,\t\t\t\t\t\t\t\t\t/* extended <RIGHT ARROW> */\n\n\tKN_NUMLOCK,\t\t\t\t\t\t\t\t\t/* <NUM LOCK> */\n\tKN_HOME,\t\t\t\t\t\t\t\t\t\t/* num key pad 7 */\n\tKN_UPLEFT = KN_HOME,\n\tKN_LEFT,\t\t\t\t\t\t\t\t\t\t/* num key pad 4 */\n\tKN_END,\t\t\t\t\t\t\t\t\t\t/* num key pad 1 */\n\tKN_DOWNLEFT = KN_END,\n\n\tKN_RESERVED7,\n\n\tKN_KEYPAD_SLASH,\t\t\t\t\t\t\t/* num key pad / */\n\tKN_UP,\t\t\t\t\t\t\t\t\t\t/* num key pad 8 */\n\tKN_CENTER,\t\t\t\t\t\t\t\t\t/* num key pad 5 */\n\tKN_DOWN,\t\t\t\t\t\t\t\t\t\t/* num key pad 2 */\n\tKN_INSERT,\t\t\t\t\t\t\t\t\t/* num key pad 0 */\n\tKN_KEYPAD_ASTERISK,\t\t\t\t\t\t/* num key pad * */\n\tKN_PGUP,\t\t\t\t\t\t\t\t\t\t/* num key pad 9 */\n\tKN_UPRIGHT = KN_PGUP,\n\tKN_RIGHT,\t\t\t\t\t\t\t\t\t/* num key pad 6 */\n\tKN_PGDN,\t\t\t\t\t\t\t\t\t\t/* num key pad 3 */\n\tKN_DOWNRIGHT = KN_PGDN,\n\tKN_DELETE,\t\t\t\t\t\t\t\t\t/* num key pad . */\n\tKN_KEYPAD_MINUS,\t\t\t\t\t\t\t/* num key pad - */\n\tKN_KEYPAD_PLUS,\t\t\t\t\t\t\t/* num key pad + */\n\n\tKN_RESERVED8,\n\n\tKN_KEYPAD_RETURN,\t\t\t\t\t\t\t/* num key pad <ENTER> */\n\n\tKN_RESERVED9,\n\n\tKN_ESC,\n\tKN_HELP,\t\t\t\t\t\t\t\t\t\t/* for AMIGA */\n\tKN_F1, KN_F2, KN_F3, KN_F4, KN_F5, KN_F6, KN_F7, KN_F8, KN_F9, KN_F10,\n\tKN_F11,\n\tKN_F12,\n\tKN_PRNTSCRN,\t\t\t\t\t\t\t\t/* <PRINT SCRN> */\n\tKN_SCROLLLOCK,\t\t\t\t\t\t\t\t/* <SCROLL LOCK> */\n\tKN_PAUSE,\t\t\t\t\t\t\t\t\t/* <PAUSE> */\n\n\tKN_SHIFT_BIT = 0x0100,\n\tKN_CTRL_BIT  = 0x0200,\n\tKN_ALT_BIT   = 0x0400,\n\tKN_RLSE_BIT  = 0x0800,\n\tKN_LCOMM_BIT = 0x1000,\t\t\t\t\t/* Amiga Left Comm key\t*/\n\tKN_RCOMM_BIT = 0x2000,\t\t\t\t\t/* Amiga Right Comm key\t*/\n\tKN_BUTTON    = 0x8000\t\t\t\t\t/* Amiga Right Comm key\t*/\n} KeyNumType;\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/KEYBOARD.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : KEYBOARD.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 12, 1994                            *\n;*                                                                         *\n;*                  Last Update : July 12, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Contains all the defines used by the keyboard interrupt for assembly    *\n;*   includes.                                                             *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nTRUE\t\tEQU\t1\t\t\t; numerical true\nFALSE\t\tEQU\t0\t\t\t; numerical false\nDEBUG\t\tEQU\t1\n\nMAX_X_PIXEL\t\tEQU\t319\nMAX_Y_PIXEL\t\tEQU\t199\n\n\nKN_RESERVED1\t\tEQU\t14\nKN_RESERVED2\t\tEQU\t45\nKN_RESERVED3\t\tEQU\t56\n\n\n; these two are reserved for AMIGA open and close.\nKN_LCOMM\t\tEQU\t59\nKN_RCOMM\t\tEQU\t63\n\nKN_LMOUSE\t\tEQU\t65\nKN_RMOUSE\t\tEQU\t66\nKN_JBUTTON1\t\tEQU\t67\nKN_JBUTTON2\t\tEQU\t68\nKN_J_UP\t\t\tEQU\t69\nKN_J_RIGHT\t\tEQU\t70\nKN_J_DOWN\t\tEQU\t71\nKN_J_LEFT\t\tEQU\t72\n\nKN_LEFT\t\t\tEQU\t92\nKN_UPLEFT\t\tEQU\t91\nKN_UP\t\t\tEQU\t96\nKN_UPRIGHT\t\tEQU\t101\nKN_RIGHT\t\tEQU\t102\nKN_DOWNRIGHT\t\tEQU\t103\nKN_DOWN\t\t\tEQU\t98\nKN_DOWNLEFT\t\tEQU\t93\nKN_CENTER\t\tEQU\t97\n\nKN_INSERT\t\tEQU\t99\nKN_DELETE\t\tEQU\t104\n\nKN_RETURN\t\tEQU\t43\nKN_SPACE\t\tEQU\t61\nKN_KEYPAD_RETURN\tEQU\t108\n\n\n; these two are reserved for AMIGA K left and right paren\nKN_KLPAREN\t\tEQU\t87\nKN_KRPAREN\t\tEQU\t88\n\n\nKN_NUMLOCK\t\tEQU\t90\n\nKN_SCROLLOCK\t\tEQU\t125\t\t; key ignored by the logging system\n\nKN_MOUSE_MOVE\tEQU\t45\t; Indicate a mouse move (for playback of logged data)\n\n; ----------------------------------------------------------------\n; flags used in Keyflags to customize keystroke interrupt.\n\nREPEATON\tEQU\t0001H\t; 1:all makes into buffer, 0:only 1st make\nTRACKEXT\tEQU\t0002H\t; 1:Home != keypad Home, 0:Home=keypad Home\nFILTERONLY\tEQU\t0004H\t; 1:Normal BIOS operation with filter\nCTRLSON\t\tEQU\t0008H\t; 1:pass scroll lock sequence into BIOS\nCTRLALTTURBO\tEQU\t0010H\t; 1:Allow turbo up and down in application\nCTRLCON\t\tEQU\t0020H\t; 1:pass stop code to BIOS\nSCROLLLOCKON\tEQU\t0040H\t; 1:pass scroll lock key into BIOS\nPAUSEON\t\tEQU\t0080H\t; 1:pass the pause key and seq to BIOS\nBREAKON\t\tEQU\t0100H\t; 1:pass the ctrl break seq to BIOS\nNONUMLOCK\tEQU\t0200H\t; 1:do NOT remap keypad to numbers\nTASKSWITCHABLE\tEQU\t0400H\t; 1:allows task switching keys thru ALT-TAB,\n\t\t\t\t;   ALT-ESC,CTRL-ESC\nPASSBREAKS\tEQU\t0800H\t; 1:Pass all break codes to keyboard buffer.\nKEYMOUSE\tEQU\t1000H\t; 1:Numeric keypad moves mouse\nSIMLBUTTON\tEQU\t2000H\t; 1:have space and enter keys simulate Left\nDEBUGINT\tEQU\t4000H\t;   mouse button when KEYMOUSE is set\n\n\nSHIFTPRESS\tEQU\t001H\t; bit 0 for shift key pressed\nCTRLPRESS\tEQU\t002H\t; bit 1 for ctrl key pressed\nALTPRESS\tEQU\t004H\t; bit 2 for alt key pressed\nKEYRELEASE\tEQU\t008H\t; bit 3 for key released\nNOTKEYRELEASE\tEQU\t0F7H\t; not of key released\n\nCAPSLOCK\tEQU\t00001H\t; bit 0 for caps locked\nNUMLOCK\tEQU\t00002H\t; bit 1 for num locked\n\n\n\nCLEARISR\tEQU\t020H\t; value to clear In Service Register\nDOS\t\tEQU \t021H\nINTCHIP0\tEQU\t020H\t; 8259 interrupt chip controller 0\nKEYCTRL\t\tEQU\t061H\t; control bits for KB sense data\nKEYDATA\t\tEQU\t060H\t; keyboard scan code port\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/KEYSTRUC.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : KEYSTRUC.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 13, 1994                            *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nSTRUC\tKeyboardType\n\tSoundOn\t\t\tDW\t?\t; toggled by alt S\n\tMusicOn\t\t\tDW\t?\t; toggled by alt M\n\tKeyFlags\t\t\tDD\t?\t; all but repeat for now\n\tBreak\t\t\t\tDW\t?\n\tKeyMouseMove\tDB\t6  DUP(?)\n\tScreenEdge\t\tDW\t18 DUP (?)\n\tBits\t\t\t\tDB\t8  DUP (?)\n\tCondPassKey\t\tDW\t17 DUP (?) \n\tCondPassCond\tDW\t17 DUP (?)\n\tEscRoutine\t\tDD\t?\n\tExtCodes\t\t\tDB\t16 DUP (?)\n\tExtNums\t\t\tDB\t16 DUP (?)\n\tExtRemap\t\t\tDB\t16 DUP (?)\n\tExtRemapEnd\t\tDB\t?\n\tExtKeyboard\t\tDB\t?\n\tKeyBuffer\t\tDW\t128 DUP(?) ; set to empty\n\tKeyBufferHead\tDD\t?\t; set to first entry\n\tKeyBufferTail\tDD\t?\t; set to head for empty buffer\n\tKeyLock\t\t\tDW\t?\t; num and caps lock bits\n\tKeyNums\t\t\tDB\t89 DUP (?)\n\tKeysCapsLock\tDB\t16 DUP (?)\n\tKeysNumLock\t\tDB\t16 DUP (?)\n\tKeysUpDown\t\tDB\t16 DUP (?)\n\tKeyStream\t\tDB\t16 DUP (?)\n\tPassCount\t\tDW\t?\n\tKeyStreamIndex\tDW\t?\n\tLastKeyE0\t\tDB\t?\n\tLastKeyE1\t\tDB\t?\n\tPassAlways\t\tDB\t10 DUP (?)\n\tPassAlwaysEnd\tDB\t?\t\t; invalid code to END PassAlways\n\tCtrlFlags\t\tDB\t?\n\tBuffer\t\t\tDW\t?\n\tTime\t\t\t\tDW\t?\n\tXYAdjust\t\t\tDB\t26 DUP (?)\n\tEdgeConv\t\t\tDW\t16 DUP (?)\n\tMouseUpdate\t\tDW\t?\n\tMouseX\t\t\tDD\t?\n\tLocalMouseX\t\tDW\t?\n\tMouseY\t\t\tDD\t?\n\tLocalMouseY\t\tDW\t?\n\tIsExtKey\t\t\tDB\t?\n\tExtIndex\t\t\tDW\t?\n\n\tKeyOldRMI\t\t\tDD\t?\t; The origianl RM interrupt seg:off.\n\tKeyOldPMIOffset\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tKeyOldPMISelector\tDD\t?\t; The original PM interrupt segment.\n\n\tKeyCodeOffset\t\t\tDW\t?\t; Offset of the code in the RM stuff.\n\tCallKeyRMIntOffset\tDW\t?\t; Offset of function to call DOS timer interrupt.\n\tCallKeyRMIntAddr\t\tDD\t?\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedKeyInt\t\t\tDD\t?\t; did Protected mode pass this through?\n\n\tBrkOldRMI\t\t\t\tDD\t?\t; The origianl RM interrupt seg:off.\n\tBrkOldPMIOffset\t\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tBrkOldPMISelector\t\tDD\t?\t; The original PM interrupt segment.\n\n\tBrkCodeOffset\t\t\tDW\t?\t; Offset of the code in the RM stuff.\n\tCallBrkRMIntOffset\tDW\t?\t; Offset of function to call DOS timer interrupt.\n\tCallBrkRMIntAddr\t\tDD\t?\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedBrkInt\t\t\tDD\t?\t; did Protected mode pass this through?\n\tKeyIntDisabled\t\t\tDD\t?\n\n\tDbgOldPMIOffset\t\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tDbgOldPMISelector\t\tDD\t?\t; The original PM interrupt segment.\n\n\t;---------------------------------------------------------------------------\n\t; Begin definition of Mouse Specific Variables for real mode\n\t;---------------------------------------------------------------------------\n\tButton\t\t\t\tDB\t?\t; current value of the mouse button\n\tMDisabled\t\t\tDB\t?\t; Is the mouse driver disabled\n\tMInput\t\t\t\tDB\t?\t; Defaults to mouse input allowed.\n\tAdjust\t\t\t\tDW\t?\t; flag to adjust coordinates if necessary\n\tMouseStepX\t\t\tDW\t?\t; step values if the mouse moves at\n\tMouseStepY\t\t\tDW\t?\t;   more than one pixel at a time\n\tMouseOffsetX\t\tDW\t?\t; Fractional step values used if a mouse\n\tMouseOffsetY\t\tDW\t?\t;   moves at less than one pixel at a time\n\tMState\t\t\t\tDD\t?\t; Tracks if mouse is hidden (TRUE) or not (FALSE)\n\tMouseXOld     \t\tDW\t?\t; Holds last MouseX and MouseY to determine if \n\tMouseYOld     \t\tDW\t?\t;   mouse needs to be redrawn\n\tMCState\t\t\t\tDW\t?\t; Tracks if mouse conditional hidden (TRUE) or not\n\tMouseCXLeft\t\t\tDD\t?\t; Conditional hide mouse left x position\n\tMouseCYUpper\t\tDD\t?\t; Conditional hide mouse top y position\n\tMouseCXRight\t\tDD\t?\t; Conditional hide mouse right x position\n\tMouseCYLower\t\tDD\t?\t; Conditional hide mouse lower y position\n\tMouseCursor   \t\tDD\t?\t; Pointer to the mouse cursor to draw\n\tMouseCursorSize\tDW\t?\t; Size of mouse cursor draw area\n\tMouseBuffer   \t\tDD\t?\t; Pointer to buffer mouse is saved in\n\tMouseXHot     \t\tDD\t?\t; Offset to mouse's x hot spot\n\tMouseYHot     \t\tDD\t?\t; Offset to mouse's y hot spot\n\tMouseBuffX\t\t\tDD\t?\t; X position background was saved at\n\tMouseBuffY\t\t\tDD\t?\t; Y position background was saved at\n\tMouseBuffW\t\t\tDD\t?\t; Width of the region saved for mouse\n\tMouseBuffH\t\t\tDD\t?\t; Height of the region saved for mouse\n\tMouseWidth\t\t\tDD\t?\t; Mouse cursor theoretical width\n\tMouseHeight\t\t\tDD\t?\t; Mouse cursor theoretical height\n\tMouseCodeOffset\tDW\t?\t; Offset to the real mode code offset\n\tMouseRight\t\t\tDD\t?\t; Right hand side of the screen\n\tMouseBottom\t\t\tDD\t?\t; Bottom of the screen\n\n\n\tShadowPtr\t\t\tdw\t?\n\tDrawMousePtr \t\tdw\t?\n\n\tVGAMouseDraw\t\tdw\t?\n\tVGAMouseShadow\t\tdw\t?\n\n\tVESAMouseDraw\t\tdw\t?\n\tVESAMouseShadow\tdw\t?\n\n\tVesaPtr\t\t\t\tdd ?\t\n\tVesaBankTable\t   DD\t8 dup (?)\n\tAdjust_XPos\t\t\tdd ?\n\tAdjust_YPos\t\t\tdd ?\n\n\nENDS\n\n; InitFlags that are set to have a fully functional interrupt.\nIF_ALLOC_RM\t\t\tequ\t1\t\t; Allocation of RM was successful.\nIF_SET_VECTORS\t\tequ\t2\t\t; Vectors have been set.\nIF_LOCKED_PM_CODE\tequ\t4\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t8\t\t; Locked PM code for DPMI.\nIF_RATE_CHANGE\t\tequ\t10\t\t; Timer rate was changed.\nIF_FUNCTIONAL\t\tequ\t20\t\t; Timer is in and functional.\nIF_LOCKED_RM_CODE\tequ\t40\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/MCGAPRIM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n\n#ifndef MCGAPRIM_H\n#define MCGAPRIM_H\n\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\nclass GraphicViewPortClass;\nclass GraphicBufferClass;\nclass VideoBufferClass;\n/*=========================================================================*/\n/* Define functions which have not under-gone name mangling\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\t/*======================================================================*/\n\t/* Externs for all of the common functions between the video buffer\t\t*/\n\t/*\t\tclass and the graphic buffer class.\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\textern long MCGA_Size_Of_Region(void *thisptr, int w, int h);\n\n\textern void\tMCGA_Put_Pixel(void * thisptr, int x, int y, unsigned char color);\n\textern int\tMCGA_Get_Pixel(void * thisptr, int x, int y);\n\textern void\tMCGA_Clear(void *thisptr, unsigned char color);\n\textern long\tMCGA_To_Buffer(void *thisptr, int x, int y, int w, int h, void *buff, long size);\n\textern long MCGA_Buffer_To_Page(int x, int y, int w, int h, void *Buffer, void *view);\n\textern BOOL\tLinear_Blit_To_Linear(\tvoid *thisptr, void * dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\t\t\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans);\n\textern BOOL Linear_Scale_To_Linear(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\n\n\textern void\tVesa_Put_Pixel(void * thisptr, int x, int y, unsigned char color);\n\textern int\tVesa_Get_Pixel(void * thisptr, int x, int y);\n\textern void\tVesa_Clear(void *thisptr, unsigned char color);\n\textern long\tVesa_To_Buffer(void *thisptr, int x, int y, int w, int h, void *buff, long size);\n\textern long Vesa_Buffer_To_Page(int x, int y, int w, int h, void *Buffer, void *view);\n\n\textern BOOL\tLinear_Blit_To_Vesa(\t\tvoid *thisptr, void * dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\t\t\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans);\n\textern BOOL\tVesa_Blit_To_Linear(\t\tvoid *thisptr, void * dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\t\t\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans);\n\textern BOOL\tVesa_Blit_To_Vesa(\t\tvoid *thisptr, void * dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\t\t\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans);\n\textern BOOL Linear_Scale_To_Vesa(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\n\textern BOOL Vesa_Scale_To_Linear(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\n\textern BOOL Vesa_Scale_To_Vesa(\t\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\n\textern LONG MCGA_Print(\t\t\t\t\tvoid *thisptr, const char *str, int x, int y, int fcolor, int bcolor);\n\textern LONG Vesa_Print(\t\t\t\t\tvoid *thisptr, const char *str, int x, int y, int fcolor, int bcolor);\n\n\t/*======================================================================*/\n\t/* Externs for all of the graphic buffer class only functions\t\t\t\t*/\n\t/*======================================================================*/\n\textern VOID MCGA_Draw_Line(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color);\n\textern VOID MCGA_Fill_Rect(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color);\n\textern VOID MCGA_Remap(void * thisptr, int sx, int sy, int width, int height, void *remap);\t\n\textern VOID MCGA_Fill_Quad(void * thisptr, VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\tint x2, int y2, int x3, int y3, int color);\n\textern void MCGA_Draw_Stamp(void const *thisptr, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap);\n\textern void MCGA_Draw_Stamp_Clip(void const *thisptr, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int min_x, int min_y, int max_x, int max_y);\n\n\textern void Shadow_Blit(long int xpix, long int ypix, long int width, long int height, GraphicViewPortClass &src, VideoBufferClass &dst, void *shadowbuff);\n\n\textern void *Get_Font_Palette_Ptr(void);\n//\textern int Get_Standard_Selector(VOID);\n//\textern VOID Set_Selector(UWORD sel);\n#ifdef __cplusplus\n}\n#endif\n\nextern BOOL (*VVPC_Blit_to_GVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nextern BOOL (*VVPC_Blit_to_VVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nextern void (*VVPC_Clear_Func)(void *, unsigned char);\nextern long (*VVPC_To_Buffer_Func)(void *,int x, int y, int w, int h, void *buff, long size);\nextern void (*VVPC_Put_Pixel_Func)(void *,int x, int y, unsigned char color);\nextern int  (*VVPC_Get_Pixel_Func)(void *, int x, int y);\nextern long (*VVPC_Buffer_To_Page)(int x, int y, int w, int h, void *buffer, void *view);\nextern BOOL (*GVPC_Blit_to_VVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nextern BOOL (*VVPC_Blit_to_GVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nextern BOOL (*VVPC_Blit_to_VVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nextern BOOL (*VVPC_Scale_To_GVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\nextern BOOL (*VVPC_Scale_To_VVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\nextern BOOL (*GVPC_Scale_To_VVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\nextern LONG (*VVPC_Print_Func)(void *, const char *, int, int, int, int);\nextern GraphicBufferClass *LogicPage;\n#endif\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/MCGAPRIM.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : MCGAPRIM.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 16, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n; Externs from REGIONSZ.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Size_Of_Region\t:NEAR\n\n; Externs from GETPIX.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Get_Pixel          \t:NEAR\n\n; Externs from VGETPIX.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Get_Pixel          \t:NEAR\n\n; Externs from PUTPIX.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Put_Pixel \t\t:NEAR\n\n; Externs from VPUTTPIX.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Put_Pixel \t\t:NEAR\n\n; Externs from CLEAR.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Clear\t          \t:NEAR\n\n; Externs from VCLEAR.ASM module of the MCGA/SVGAPRIM library\nGLOBAL Vesa_Clear\t\t\t:NEAR\n; Externs from BITBLIT.ASM module of the MCGAPRIM library\nGLOBAL Linear_Blit_To_Linear\t\t:NEAR\n\n; Externs from VBITBLIT.ASM module of the MCGA/SVGAPRIM library\nGLOBAL Linear_Blit_To_Vesa\t\t:NEAR\nGLOBAL Vesa_Blit_To_Linear\t\t:NEAR\nGLOBAL Vesa_Blit_To_Vesa\t\t:NEAR\n\n; Externs from TOBUFF.ASM module of the MCGAPRIM library\nGLOBAL MCGA_To_Buffer\t\t:NEAR\n\n; Externs from VTOBUFF.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_To_Buffer\t\t:NEAR\n\n; Externs from TOPAGE.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Buffer_To_Page\t\t:NEAR\n\n; Externs from VTOPAGE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Buffer_To_Page\t\t:NEAR\n\n; Externs from SCALE.ASM module of the MCGAPRIM library\nGLOBAL Linear_Scale_To_Linear \t:NEAR\n\n; Externs from VSCALE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Linear_Scale_To_Vesa \t\t:NEAR\nGLOBAL Vesa_Scale_To_Linear\t\t:NEAR\nGLOBAL Vesa_Scale_To_Vesa \t\t:NEAR\n\n; Externs from TXTPRNT.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Print\t\t\t:NEAR\nGLOBAL C Get_Font_Palette_Ptr\t\t:NEAR\n\n; Externs from VTXTPRNT.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Print\t\t\t:NEAR\n\n;*-------------------------------------------------------------------------*\n;* Define MCGA only assembly GLOBALS\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n\n; Externs from DRAWLINE.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Draw_Line \t\t:NEAR\n\n; Externs from FILLQUAD.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Fill_Quad \t\t:NEAR\n\n; Externs from FILLRECT.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Fill_Rect \t\t:NEAR\n\n; Externs from REMAP.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Remap      \t\t:NEAR\n\n; Externs from STAMP.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Draw_Stamp \t\t:NEAR\nGLOBAL MCGA_Draw_Stamp_Clip\t:NEAR\n\nGLOBAL get_clip\t \t   : NEAR\n\nstruc  RECTANGLE\n\t\t  x0\tdd\t?\n\t\t  y0 dd\t?\n\t\t  x1\tdd\t?\n\t\t  y1 dd ?\nends \t RECTANGLE\n\n\n\n\u001a\n\u001a\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/MEMFLAG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory System                            *\n *                                                                         *\n *                    File Name : MEMFLAG.H                                *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : April 4, 1994                            *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef MEMFLAG_H\n#define MEMFLAG_H\n// Memory Flags\n/*\n**\tMemory allocation flags.  These are the flags that are passed into Alloc\n**\tin order to control the type of memory allocated.\n*/\ntypedef enum {\n\tMEM_NORMAL = 0x0000,\t\t// Default memory (normal).\n\tMEM_NEW\t  = 0x0001,\t\t// Called by the operator new and was overloaded.\n\tMEM_CLEAR  = 0x0002,\t\t// Clear memory before returning.\n\tMEM_REAL   = 0x0004,\t\t// Clear memory before returning.\n\tMEM_TEMP   = 0x0008,\t\t// Clear memory before returning.\n\tMEM_LOCK   = 0x0010,\t\t// Lock the memory that we allocated\n} MemoryFlagType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: ALLOC.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid * operator new(size_t size, MemoryFlagType flag);\nvoid * operator new[] (size_t size, MemoryFlagType flag);\nvoid\t*Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags);\nvoid\tFree(void const *pointer);\nvoid\tDPMI_Lock(VOID const *ptr, long const size);\nvoid\tDPMI_Unlock(void const *ptr, long const size);\nvoid\t*Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes);\nlong\tRam_Free(MemoryFlagType flag);\nlong\tHeap_Size(MemoryFlagType flag);\nlong\tTotal_Ram_Free(MemoryFlagType flag);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MEM_COPY.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\textern void Mem_Copy(void const *source, void *dest, unsigned long bytes_to_copy);\n\n#ifdef __cplusplus\n}\n#endif\n\n\ninline void *Add_Long_To_Pointer(void const *ptr, long size) \n{\n \treturn ((void *) ( (char const *) ptr + size));\n}\n\nextern void (*Memory_Error)(void);\nextern void (*Memory_Error_Exit)(char *string);\n\nextern unsigned long MinRam;\t\t// Record of least memory at worst case.\nextern unsigned long MaxRam;\t\t// Record of total allocated at worst case.\n\n\n#endif\n\n\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/MISC.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : 32 bit library                           *\n *                                                                         *\n *                    File Name : MISC.H                                   *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MISC_H\n#define MISC_H\n\n/*========================= C++ Routines ==================================*/\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: EXIT.CPP\t\t\t\t\t\t\t*/\n/* Prog_End Must be supplied by the user program in startup.cpp\t\t\t\t*/\n/*=========================================================================*/\nVOID cdecl Prog_End(VOID);\nVOID cdecl Exit(INT errorval, const BYTE *message, ...);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DELAY.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Delay(int duration);\nvoid Vsync(void);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FINDARGV.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nBYTE *cdecl Find_Argv(BYTE const *str);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LIB.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nchar *Find_Argv(char const *str);\nvoid Mono_Mem_Dump(void const *databuf, int bytes, int y);\nvoid Convert_RGB_To_HSV(unsigned int r, unsigned int g, unsigned int b, unsigned int *h, unsigned int *s, unsigned int *v);\nvoid Convert_HSV_To_RGB(unsigned int h, unsigned int s, unsigned int v, unsigned int *r, unsigned int *g, unsigned int *b);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: VERSION.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nBYTE *cdecl Version(VOID);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: IRANDOM.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nint IRandom(int minval, int maxval);\n\n\n/*========================= Assembly Routines ==============================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*=========================================================================*/\n/* The following prototypes are for the file: PROC.ASM\t\t\t\t\t\t\t*/\n/* Prog_End Must be supplied by the user program in startup.cpp\t\t\t\t*/\n/*=========================================================================*/\nint Get_CPU(VOID);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: RANDOM.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nUBYTE Random(VOID);\nint Get_Random_Mask(int maxval);\n\n/*=========================================================================*/\n/* The following prototype is for the file: SHAKESCR.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid Shake_Screen(int shakes);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: REVERSE.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nLONG Reverse_LONG(LONG number);\nWORD Reverse_WORD(WORD number);\nLONG Swap_LONG(LONG number);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FACING8.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//int Desired_Facing8(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FACING16.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint Desired_Facing16(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FACINGFF.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//int Desired_Facing256(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FADING.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid *Build_Fading_Table(void const *palette, void const *dest, long int color, long int frac);\n\n/*=========================================================================*/\n/* The following prototype is for the file: CRC.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nlong Calculate_CRC(void *buffer, long length);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DETPROC.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern WORD  Processor(VOID);\nextern WORD  Operating_System(VOID);\nextern ULONG random ( ULONG mod )  ;\nextern void  randomize ( void ) ;\n\nextern int Clip_Rect ( int * x , int * y , int * dw , int * dh ,\n\t       \t   \t\t\t int width , int height ) ;          \t\t\t   \nextern int Confine_Rect ( int * x , int * y , int dw , int dh , \n\t      \t      \t\t\t int width , int height ) ;          \t\t   \n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: OPSYS.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern WORD OperationgSystem;\n\t\t\t\t\t\t\t\t\t\t  \n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n\n#endif // MISC_H\n\u001a\n\u001a\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/MISC.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : 32 bit library                           *\n *                                                                         *\n *                    File Name : MISC.H                                   *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MISC_H\n#define MISC_H\n\n/*========================= C++ Routines ==================================*/\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: EXIT.CPP\t\t\t\t\t\t\t*/\n/* Prog_End Must be supplied by the user program in startup.cpp\t\t\t\t*/\n/*=========================================================================*/\nVOID cdecl Prog_End(VOID);\nVOID cdecl Exit(INT errorval, const BYTE *message, ...);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DELAY.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Delay(int duration);\nvoid Vsync(void);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FINDARGV.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nBYTE *cdecl Find_Argv(BYTE const *str);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LIB.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n//char *Find_Argv(char const *str);\nvoid Mono_Mem_Dump(void const *databuf, int bytes, int y);\nvoid Convert_RGB_To_HSV(unsigned int r, unsigned int g, unsigned int b, unsigned int *h, unsigned int *s, unsigned int *v);\nvoid Convert_HSV_To_RGB(unsigned int h, unsigned int s, unsigned int v, unsigned int *r, unsigned int *g, unsigned int *b);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: VERSION.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nBYTE *cdecl Version(VOID);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: IRANDOM.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nint IRandom(int minval, int maxval);\n\n\n/*========================= Assembly Routines ==============================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*=========================================================================*/\n/* The following prototypes are for the file: PROC.ASM\t\t\t\t\t\t\t*/\n/* Prog_End Must be supplied by the user program in startup.cpp\t\t\t\t*/\n/*=========================================================================*/\nint Get_CPU(VOID);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: RANDOM.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nUBYTE Random(VOID);\nint Get_Random_Mask(int maxval);\n\n/*=========================================================================*/\n/* The following prototype is for the file: SHAKESCR.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid Shake_Screen(int shakes);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: REVERSE.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nLONG Reverse_LONG(LONG number);\nWORD Reverse_WORD(WORD number);\nLONG Swap_LONG(LONG number);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FACING8.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//int Desired_Facing8(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FACING16.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint Desired_Facing16(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FACINGFF.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//int Desired_Facing256(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FADING.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid *Build_Fading_Table(void const *palette, void const *dest, long int color, long int frac);\n\n/*=========================================================================*/\n/* The following prototype is for the file: CRC.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nlong Calculate_CRC(void *buffer, long length);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DETPROC.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern WORD  Processor(VOID);\nextern WORD  Operating_System(VOID);\nextern ULONG random ( ULONG mod )  ;\nextern void  randomize ( void ) ;\n\nextern int Clip_Rect ( int * x , int * y , int * dw , int * dh ,\n\t       \t   \t\t\t int width , int height ) ;\nextern int Confine_Rect ( int * x , int * y , int dw , int dh ,\n\t      \t      \t\t\t int width , int height ) ;\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: OPSYS.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern WORD OperationgSystem;\n\n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n\n#endif // MISC_H\n\u001a\n\u001a\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/MONO.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Mono Sub-system                          *\n *                                                                         *\n *                    File Name : MONO.H                                   *\n *                                                                         *\n *                   Programmer : Joe Bostic                               *\n *             32Bit Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : March 28, 1994                           *\n *                                                                         *\n *                  Last Update : March 28, 1994   []                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef MONO_H\n#define MONO_H\n\n// C++ Routines\n//==================================================================\n\n// Mono Screen routines\n//==================================================================\nint\tInitialize_Mono_Screen ( void );\n\t\t\t\t\t\t\t   \n\n// C Routines\n//==================================================================\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// Mono Screen routines\n//===================================================================\n\textern\tunsigned\tMonoScreen;\n\textern\tunsigned\tMonoEnabled;\n\t\t\t\n\textern\tvoid Mono_Set_Cursor(int x, int y);\n\textern \tvoid Mono_Clear_Screen(void); \n\textern \tvoid Mono_Scroll(int lines);\n\textern \tvoid Mono_Put_Char(char character, int attrib=2);\n\textern \tvoid Mono_Draw_Rect(int x, int y, int w, int h, int attrib=2, int thick=0);\n\textern\tvoid Mono_Text_Print(void const *text, int x, int y, int attrib=2);\n\textern\tvoid Mono_Print(void const *text);\n\textern \tvoid Mono_View_Page(int page);\n\textern\tint Mono_Printf(char const *string, ...);\n\t\t\t\t\t\t\t\t\n#ifdef __cplusplus\n}\n#endif\n\n\n#endif\n\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/MONO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Mono Sub-system                          *\n *                                                                         *\n *                    File Name : MONO.H                                   *\n *                                                                         *\n *                   Programmer : Joe Bostic                               *\n *             32Bit Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : March 28, 1994                           *\n *                                                                         *\n *                  Last Update : March 28, 1994   []                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef MONO_H\n#define MONO_H\n\n// C++ Routines\n//==================================================================\n\n// Mono Screen routines\n//==================================================================\nint\tInitialize_Mono_Screen ( void );\n\n\n// C Routines\n//==================================================================\n#ifdef __cplusplus\n//extern \"C\" {\n#endif\n\n// Mono Screen routines\n//===================================================================\n\textern\tunsigned\tMonoScreen;\n\textern\tunsigned\tMonoEnabled;\n\n\textern\tvoid Mono_Set_Cursor(int x, int y);\n\textern \tvoid Mono_Clear_Screen(void);\n\textern \tvoid Mono_Scroll(int lines);\n\textern \tvoid Mono_Put_Char(char character, int attrib=2);\n\textern \tvoid Mono_Draw_Rect(int x, int y, int w, int h, int attrib=2, int thick=0);\n\textern\tvoid Mono_Text_Print(void const *text, int x, int y, int attrib=2);\n\textern\tvoid Mono_Print(void const *text);\n\textern \tvoid Mono_View_Page(int page);\n\textern\tint Mono_Printf(char const *string, ...);\n\n#ifdef __cplusplus\n//}\n#endif\n\n\n#endif\n\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/NYBBTB.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;****************************************************************************\n;* bNybbleTablexxxx - ADPCM Lookup table for nybbles\n;****************************************************************************\n\n\t\talign\t4\n\nbNybbleTableLow\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\t\tDB\t00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2\n\n\t\talign 4\n\nbNybbleTableHigh\tDB\t00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2\n\t\tDB\t01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2\n\t\tDB\t02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2\n\t\tDB\t03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2\n\t\tDB\t04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2\n\t\tDB\t05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2\n\t\tDB\t06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2\n\t\tDB\t07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2\n\t\tDB\t08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2\n\t\tDB\t09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2\n\t\tDB\t0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2\n\t\tDB\t0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2\n\t\tDB\t0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2\n\t\tDB\t0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2\n\t\tDB\t0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2\n\t\tDB\t0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/PALETTE.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Palette 32bit Library.                   *\n;*                                                                         *\n;*                    File Name : PALETTE.H                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : April 25, 1994                           *\n;*                                                                         *\n;*                  Last Update : April 27, 1994 [BRR]\t\t\t\t\t\t\t*\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef PALETTE_H\n#define PALETTE_H\n\n/*\n********************************* Constants *********************************\n*/\n#define RGB_BYTES\t\t\t3\n#define PALETTE_SIZE\t\t256\n#define PALETTE_BYTES\t768\n\n/*\n******************************** Prototypes *********************************\n*/\n/*\n-------------------------------- Palette.cpp --------------------------------\n*/\nVOID cdecl Set_Palette(VOID *palette);\nVOID cdecl Set_Palette_Color(VOID *palette, WORD color, VOID *data);\nVOID Fade_Palette_To(VOID *palette1, UWORD delay, VOID (*callback)() );\n\n/*\n-------------------------------- loadpal.cpp --------------------------------\n*/\nVOID cdecl Load_Palette(BYTE *palette_file_name, VOID *palette_pointer);\n\n/*\n------------------------------- morphpal.cpp --------------------------------\n*/\nVOID cdecl Morph_Palette (VOID *src_palette, VOID *dst_palette, UWORD delay,\n\tVOID *callback);\n\n/*\n---------------------------------- pal.asm ----------------------------------\n*/\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Set_Palette_Range(VOID *palette);\nextern BOOL Bump_Color(VOID *palette, WORD changable, WORD target);\n\n#ifdef __cplusplus\n}\n#endif\nextern \"C\" extern UBYTE  CurrentPalette[];\t\t/* in pal.asm */\n\n\n#endif // PALETTE_H\n\n/***************************** End of palette.h ****************************/\n\u001a\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/PALETTE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Palette 32bit Library.                   *\n;*                                                                         *\n;*                    File Name : PALETTE.H                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : April 25, 1994                           *\n;*                                                                         *\n;*                  Last Update : April 27, 1994 [BRR]\t\t\t\t\t\t\t*\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef PALETTE_H\n#define PALETTE_H\n\n/*\n********************************* Constants *********************************\n*/\n#define RGB_BYTES\t\t\t3\n#define PALETTE_SIZE\t\t256\n#define PALETTE_BYTES\t768\n\n/*\n******************************** Prototypes *********************************\n*/\n/*\n-------------------------------- Palette.cpp --------------------------------\n*/\nVOID cdecl Set_Palette(VOID *palette);\nVOID cdecl Set_Palette_Color(VOID *palette, WORD color, VOID *data);\nVOID Fade_Palette_To(VOID *palette1, UWORD delay, VOID (*callback)() );\n\n/*\n-------------------------------- loadpal.cpp --------------------------------\n*/\nVOID cdecl Load_Palette(BYTE *palette_file_name, VOID *palette_pointer);\n\n/*\n------------------------------- morphpal.cpp --------------------------------\n*/\nVOID cdecl Morph_Palette (VOID *src_palette, VOID *dst_palette, UWORD delay,\n\tVOID *callback);\n\n/*\n---------------------------------- pal.asm ----------------------------------\n*/\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Set_Palette_Range(VOID *palette);\nextern BOOL Bump_Color(VOID *palette, WORD changable, WORD target);\nextern UBYTE  CurrentPalette[];\t\t/* in pal.asm */\n\n#ifdef __cplusplus\n}\n#endif\n\n\n#endif // PALETTE_H\n\n/***************************** End of palette.h ****************************/\n\u001a\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/PLAYCD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB\t  \t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : PLAYCD.H\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : STEVE WETHERILL\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Start Date : 5/13/94\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : June 4, 1994   [SW]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*/\n\n#ifndef PLAYCD_H\n#define PLAYCD_H\n\n/* ==================================================================== */\n/* Defines */\n/* ==================================================================== */\n\n#define\tCHLEFT\t0\n#define\tCHRIGHT\t1\n#define\tCHBOTH\t2\n\n#define\tAUDIO_START_MIN\t1\n#define\tAUDIO_START_SEC  44\n\ntypedef struct {\n\t\t\t\t\t  unsigned short seg ;\n \t\t\t\t\t  unsigned short sel ;\n\t\t\t\t\t} SEGSEL ;\n\n\n\n\nextern \"C\" int  DPMI_real_alloc ( UINT , SEGSEL * , USHORT * ) ;\nextern \"C\" int  DPMI_real_free ( SEGSEL  ) ;\nextern \"C\" void DPMI_real_intr ( int , union REGS * , struct SREGS * );\nextern \"C\" void DPMI_real_call ( void * funct , union REGS * , struct SREGS * );\n\n\n\n\n/* ==================================================================== */\n/* Data structures */\n/* ==================================================================== */\n\n// Audio Track Info request block\n\nstruct\tTinfoType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tTrInfo;\n\tUBYTE\t\tTrack;\n\tULONG\t\tStart;\n\tUBYTE\t\tTrCtrl;\n};\n\n// Audio Track Status Control Block\n\nstruct\tStatType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tStatInfo;\n\tUWORD\t\tStat;\n\tULONG\t\tStart;\n\tULONG\t\tEnd;\n\t};\n\n// Audio Track Volume control block\n\nstruct\tVolmType\t{\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tTrInfo;\n\tUBYTE\t\tIn0;\n\tUBYTE\t\tVol0;   \n\tUBYTE\t\tIn1;\n\tUBYTE\t\tVol1;   \n\tUBYTE\t\tIn2;\n\tUBYTE\t\tVol2;   \n\tUBYTE\t\tIn3;\n\tUBYTE\t\tVol3;   \n\t};\n\n// Audio Track Play request block\n\nstruct\tPlayType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tAddrMd;\n\tULONG\t\tStart;\n\tULONG\t\tCntSect;\n\t};\n\n\n// Audio Track Stop request block\n\nstruct\tStopType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\t};\n\n\n/***************************************************************************\n * GetCDClass -- object which will return logical CD drive\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/04/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n#define MAX_CD_DRIVES 26\n#define NO_CD_DRIVE -1\n\nclass\tGetCDClass {\n\nprotected:\n\n\tunion   REGS \tregs;\n\tstruct SREGS  sregs;\n\n\tSEGSEL \t\tcdDrive_addrp;\n\tUWORD\t\t\tlargestp;\n\n\tint\tCDDrives[MAX_CD_DRIVES];\t//Array containing CD drive letters\n\tint\tCDCount;\t\t\t\t\t\t\t//Number of available CD drives\n\tint\tCDIndex;\n\t\npublic:\n\n\tGetCDClass(VOID);\t\t\t\t\t// This is the default constructor\n\t~GetCDClass(VOID);\t\t\t\t// This is the destructor\n\n\tinline\tint\tGet_First_CD_Drive(void);\n\tinline\tint\tGet_Next_CD_Drive(void);\n\tinline\tint\tGet_Number_Of_Drives(void) {return (CDCount);};\n\nprivate:\n        VOID  GetCDDrives(VOID);\n\t\n};\n\n/***********************************************************************************************\n * GCDC::Get_Next_CD_Drive -- return the logical drive number of the next CD drive             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Logical drive number of a cd drive or -1 if none                                  *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/21/96 3:50PM ST : Created                                                              *\n *=============================================================================================*/\ninline int GetCDClass::Get_Next_CD_Drive(void)\n{\n\tif (CDCount){\n\t\tif (CDIndex == CDCount) CDIndex = 0;\n\t\treturn (CDDrives[CDIndex++]);\n\t}else{\n\t\treturn (-1);\n\t}\n}\n\n\n\n/***************************************************************************\n * GCDC::Get_First_CD_Drive -- return the number of the first CD drive     *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * OUTPUT:                                                                 *\n *\t\t\tlogical drive number \t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *   12/4/95    ST : fixed for Win95                                       *\n *=========================================================================*/\ninline int GetCDClass::Get_First_CD_Drive(void)\n{\n\tCDIndex = 0;\n\treturn (Get_Next_CD_Drive());\n}\n\n/***************************************************************************\n * RedBookClass -- adds red book functionality\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tthis class inherits from GetCDClass and adds red book play functionality*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/04/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n\nclass RedBookClass : public GetCDClass {\n\nprivate:\n\n\tSEGSEL\t\tTinfo_addrp;\n\tSEGSEL\t\tStat_addrp;\n\tSEGSEL\t\tStop_addrp;\n\tSEGSEL\t\tVolm_addrp;\n\tSEGSEL  \t   Play_addrp;\n\n\tStopType \tStop;\n\tPlayType\t\tPlay;\n\tVolmType\t\tVolm;\n\tStatType\t\tStat;\n\tTinfoType\tTinfo;\n\npublic:\n\n\tRedBookClass(VOID);\t\t\t\t\t// This is the default constructor\n\t~RedBookClass(VOID);\t\t\t\t\t// This is the destructor\n\n\tULONG\tRedToHS(ULONG i);\n\tULONG MSFtoRed(UBYTE m, UBYTE s, UBYTE f);\n\tVOID  FullCDVolume(UBYTE chan);\n\tVOID  PlayTrack(UWORD track);\n\tVOID  Play_CD_MSL(UWORD min_sec, UWORD len);\n\tVOID  PlayMSF(UBYTE startM, UBYTE startS, UBYTE startF, \n\t\t\t\tUBYTE endM, UBYTE endS, UBYTE endF, UBYTE chan);\n\tUWORD CheckCDMusic(VOID);\n\tVOID  StopCDMusic(VOID);\n\n};\n\n\n/***************************** End of Playcd.h ****************************/\n\n#endif // PLAYCD_H\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/SHAPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32                                  *\n *                                                                         *\n *                    File Name : SHAPE.H                                  *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : May 25, 1994                             *\n *                                                                         *\n *                  Last Update : September 14, 1994   [IML]               *\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef SHAPE_H\n#define SHAPE_H\n\n#ifndef GBUFFER_H\n#include \"gbuffer.h\"\n#endif\n/*\n*********************************** Types ***********************************\n*/\n/*\n--------------------------- Shape creation flags ----------------------------\n*/\ntypedef enum {\n\tMAKESHAPE_NORMAL\t = 0x0000,\t// 256-color compressed shape\n\tMAKESHAPE_COMPACT  = 0x0001,\t// 16-color shape (with built-in color table)\n\tMAKESHAPE_NOCOMP\t = 0x0002,\t// Uncompressed shape\n\tMAKESHAPE_VARIABLE =\t0x0004\t// <16-color shape\n} MakeShapeFlags_Type;\n\n/*---------------------------------------------------------------------------\nShape drawing flags:\n- The low byte is for coordinate transformations.\n- The high byte is for drawing effects.\n---------------------------------------------------------------------------*/\ntypedef enum {\n\tSHAPE_NORMAL \t\t\t= 0x0000,\t\t// Standard shape\n\tSHAPE_HORZ_REV \t\t= 0x0001,\t\t// Flipped horizontally\n\tSHAPE_VERT_REV \t\t= 0x0002,\t\t// Flipped vertically\n\tSHAPE_SCALING \t\t\t= 0x0004,\t\t// Scaled (WORD scale_x, WORD scale_y)\n\tSHAPE_VIEWPORT_REL \t= 0x0010,\t\t// Coords are window-relative \n\tSHAPE_WIN_REL \t\t\t= 0x0010,\t\t// Coordinates are window relative instead of absolute.\n\tSHAPE_CENTER \t\t\t= 0x0020,\t\t// Coords are based on shape's center pt\n\tSHAPE_FADING \t\t\t= 0x0100,\t\t// Fading effect (VOID * fading_table, \n\t\t\t\t\t\t\t\t\t\t\t\t\t//  WORD fading_num)\n\tSHAPE_PREDATOR \t\t= 0x0200,\t\t// Transparent warping effect\n\tSHAPE_COMPACT \t\t\t= 0x0400,\t\t// Never use this bit \n\tSHAPE_PRIORITY \t\t= 0x0800,\t\t// Use priority system when drawing\n\tSHAPE_GHOST\t\t\t\t= 0x1000,\t\t// Shape is drawn ghosted\n\tSHAPE_SHADOW\t\t\t= 0x2000,\n\tSHAPE_PARTIAL  \t\t= 0x4000,\n\tSHAPE_COLOR \t\t\t= 0x8000\t\t\t// Remap the shape's colors \n\t\t\t\t\t\t\t\t\t\t\t\t\t//  (VOID * color_table)\n} ShapeFlags_Type;\n\n/*\n------------------------------- Shape header --------------------------------\n*/\ntypedef struct {\n\tUWORD\t\tShapeType;\t\t\t// 0 = normal, 1 = 16 colors, \n\t\t\t\t\t\t\t\t\t\t//  2 = uncompressed, 4 = \t<16 colors\n\tUBYTE\t\tHeight;\t\t\t\t// Height of the shape in scan lines\n\tUWORD\t\tWidth;\t\t\t\t// Width of the shape in bytes\n\tUBYTE\t\tOriginalHeight;\t// Original height of shape in scan lines\n\tUWORD\t\tShapeSize;\t\t\t// Size of the shape, including header\n\tUWORD\t\tDataLength;\t\t\t// Size of the uncompressed shape (just data)\n\tUBYTE\t\tColortable[16];\t// Optional color table for compact shape\n} Shape_Type;\n\n/*\n------------------------------- Shape block ---------------------------------\n*/\ntypedef struct {\n\tUWORD\t\tNumShapes;\t\t\t// number of shapes in the block\n\tLONG\t\tOffsets[];\t\t\t// array of offsets to shape data\n\t\t\t\t\t\t\t\t\t\t//  (offsets within the shape block, with\n\t\t\t\t\t\t\t\t\t\t//  0 being the first offset value, not the\n\t\t\t\t\t\t\t\t\t\t//  start of the shape block)\n} ShapeBlock_Type;\n\n\n/*\n******************************** Prototypes *********************************\n*/\n\n/*\n-------------------------------- prioinit.c ---------------------------------\n*/\n\nextern \"C\" {\nextern VOID  *MaskPage;\nextern VOID  *BackGroundPage;\nextern LONG  _ShapeBufferSize;\nextern BYTE  *_ShapeBuffer;\n}\n\n\nVOID cdecl Init_Priority_System (GraphicBufferClass *mask,\n\t\t\t\t\t\t\t\t\t\t\tGraphicBufferClass *back);\n\n\n/*\n-------------------------------- drawshp.asm --------------------------------\n*/\n\nextern \"C\" {\nWORD Draw_Shape(GraphicViewPortClass *gvp, VOID const *shape, LONG x, LONG y, LONG flags, ...);\n}\n\n/*\n---------------------------------- shape.c ----------------------------------\n*/\nshort cdecl Get_Shape_Data(VOID const *shape, WORD data);\nint cdecl Extract_Shape_Count(VOID const *buffer);\nvoid * cdecl Extract_Shape(VOID const *buffer, int shape);\nint cdecl Restore_Shape_Height(VOID *shape);\nint cdecl Set_Shape_Height(VOID const *shape, WORD newheight);\n\nextern \"C\" {\nint Get_Shape_Width(VOID const *shape);\nint Get_Shape_Height(VOID const *shape);\nint Get_Shape_Original_Height(VOID const *shape);\nint Get_Shape_Uncomp_Size(VOID const *shape);\n}\n\n\n/*\n------------------------------- setshape.asm --------------------------------\n*/\nextern \"C\" {\nVOID Set_Shape_Buffer(void const *buffer, int size);\n}\n/*\n------------------------------- shapeinf.asm --------------------------------\n*/\nWORD cdecl Get_Shape_Flags(VOID const *shape);\nint  cdecl Get_Shape_Size(VOID const *shape);\nint  cdecl Get_Shape_Scaled_Width(VOID const *shape, WORD scale);\nint  cdecl Get_Shape_Scaled_Height(VOID const *shape, WORD scale);\n\n#endif // SHAPE_H\n\n/****************************** End of shape.h *****************************/\n\u001a\n\u001a\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/SHAPE.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : WWLIB32                                  *\n;*                                                                         *\n;*                    File Name : SHAPE.INC                                *\n;*                                                                         *\n;*                   Programmer : Scott Bowen\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : May 25, 1994                             *\n;*                                                                         *\n;*                  Last Update : September 14, 1994   [IML]               *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;****************************** Equates ************************************\n;\n\n\n\n\n\n\n;............................ Shape Types ..................................\n;\nTRUE\tequ\t1\t\t\t; Boolean 'true' value\nFALSE\tequ\t0\t\t\t; Boolean 'false' value\n\nMAKESHAPE_NORMAL\t\tEQU\t0\t; 256-color compressed shape\nMAKESHAPE_COMPACT\t\tEQU\t1\t; 16-color shape (built-in color table)\nMAKESHAPE_NOCOMP\t\tEQU\t2\t; non-wwcomped shape\nMAKESHAPE_VARIABLE\tEQU\t4\t; <16-color shape with variable #\n\t\t\t\t\t; of colors (ColorTable[0] = # of colors)\n; old names:\n;COLOR_SHAPE\t\tEQU\t1\t; flag which determines a color shape\n;NORM_SHAPE\t\t\tEQU\t2\t; flag that indicates non wwcomped shp\n;NORM_SHAPE_16\t\tEQU\t4\t; flag that tells us if we have a variable sized table\n\t\t\t\t\t;  variable sized table\n;\n;...........................................................................\n; Drawing flags:\n; The low byte is for coordinate transformations.\n; The high byte is for drawing effects.\n;...........................................................................\n;\nSHAPE_NORMAL\t\t\tEQU\t0000h\t; no options; just a copy\nSHAPE_HORZ_REV\t\t\tEQU\t0001h\t; reverse horizontally\nSHAPE_VERT_REV\t\t\tEQU\t0002h\t; reverse vertically\nSHAPE_SCALING\t\t\tEQU\t0004h\t; scale\nSHAPE_VIEWPORT_REL\tEQU\t0010h\t; viewport-relative coordinates\nSHAPE_CENTER\t\t\tEQU\t0020h\t; use centered coordinates\nSHAPE_FADING\t\t\tEQU\t0100h\t; fading effect shape\nSHAPE_PREDATOR\t\t\tEQU\t0200h\t; predator effect shape\nSHAPE_COMPACT\t\t\tEQU\t0400h\t; shape is in 16 colors\nSHAPE_PRIORITY\t\t\tEQU\t0800h\t; priority draw shape\nSHAPE_GHOST\t\t\t\tEQU\t1000h\t; ghosting effect\nSHAPE_SHADOW\t\t\tEQU\t2000h\t; shadow effect\nSHAPE_PARTIAL\t\t\tEQU\t4000h\t; partial predator effect\nSHAPE_COLOR\t\t\t\tEQU\t8000h\t; use alternative color table effect\n\nSHAPE_EFFECTS\t\t\tEQU    03F00h\t; shape effect flags \n\n;\n;.......................... Shadow Effect ..................................\n;\nSHADOW_COL\t\tEQU\t00FFh\t; magic number for shadows\n\n;......................... Priority System .................................\n;\nCLEAR_UNUSED_BITS  \tEQU\t0007h\t; and with 0000-0111 to clear \n\t\t\t\t\t;  non-walkable high bit and\n\t\t\t\t\t;  scaling id bits\nNON_WALKABLE_BIT  \tEQU\t0080h\t; and with 1000-0000 to clear all \n\t\t\t\t\t;  but non-walkable bit\n;\n;......................... Predator Effect .................................\n;\nPRED_MASK\t\tEQU\t0007h\t; mask used for predator pixel puts\n\n;---------------------------------------------------------------------------\n; This table is a list of the local stack variables in the function\n; Draw_Shape.  Many other functions in other modules access these variables\n; on the stack.  Since the BP is not changed when these other functions are\n; called by Draw_Shape (possibly indirectly), they can also access these\n; stack varibles.  When adding or removing from the table, one must be very\n; careful to change the offsets.  \n;---------------------------------------------------------------------------\n;.......................... proc addresses .................................\nLSkipRout\tEQU DWORD PTR ebp - 04h\t\t;DWORD  pointer to the skip routine\nRSkipRout\tEQU DWORD PTR ebp - 08h\t\t;DWORD  pointer to the skip routine\nDrawRout\tEQU DWORD PTR ebp - 0Ch\t\t\t;DWORD  pointer to the draw routine\n;........................ optional arguments ...............................\nColorTable\tEQU DWORD PTR ebp - 10h\t\t;DWORD\tptr to the shapes color table\nFadingTable\tEQU DWORD PTR ebp - 14h\t\t;DWORD  ptr to the fading table\n\nFadingNum\tEQU DWORD PTR ebp - 18h\t\t;DWORD  number of times to fade\nIsTranslucent\tEQU DWORD PTR ebp - 1Ch\t;DWORD\tptr to is_translucent table\nTranslucent\tEQU DWORD PTR ebp - 20h\t\t;DWORD\tptr to actual translucent tbl\nPriLevel\tEQU BYTE  PTR ebp - 24h\t\t\t;BYTE\tpriority level of the object \nScaleX\t\tEQU DWORD PTR ebp - 28h\t\t;DWORD  the x increment to scale by\nScaleY\t\tEQU DWORD PTR ebp - 2Ch\t\t;DWORD  the y increment to scale by\nShadowingTable\tEQU DWORD PTR ebp - 30h\t;DWORD\tptr to the shadowing table\n;........................ Shape header values ..............................\nShapeType\tEQU DWORD PTR ebp - 34h \t;DWORD\tshape type\nShapeWidth\tEQU DWORD PTR ebp - 38h \t;DWORD\tshape's unscaled width\nShapeHeight\tEQU DWORD PTR ebp - 3Ch \t;DWORD\tshape's unscaled height\nUncompDataLen\tEQU DWORD PTR ebp - 40h ;DWORD\tuncompressed data length\nShapeData\tEQU DWORD PTR ebp - 44h \t;DWORD\tpointer to shape data\n;...................... Scaled shape dimensions ............................\nScaledWidth\tEQU DWORD PTR ebp - 48h \t;DWORD\tshape's scaled width\nScaledHeight\tEQU DWORD PTR ebp - 4Ch ;DWORD\tshape's scaled height\n;...................... Pixel clipping variables ...........................\nLeftClipPixels\tEQU DWORD PTR ebp - 50h ;DWORD\t# left-clipped pixels\nRightClipPixels\tEQU DWORD PTR ebp - 54h ;DWORD\t# right-clipped pixels\nTopClipPixels\tEQU DWORD PTR ebp - 58h ;DWORD\t# top-clipped pixels\nBotClipPixels\tEQU DWORD PTR ebp - 5Ch ;DWORD\t# bottom-clipped pixels\nPixelWidth\tEQU DWORD PTR ebp - 60h \t;DWORD\tdrawable area in pixels\nPixelHeight\tEQU DWORD PTR ebp - 64h \t;DWORD\tdrawable area in pixels\n;......................... Drawing variables ...............................\nNumColors\tEQU DWORD PTR ebp - 68h ;DWORD\t# colors for 16-color shapes\nStartDraw\tEQU DWORD PTR ebp - 6Ch ;DWORD\toffset of drawing start pos\nNextLine\tEQU DWORD PTR ebp - 70h ;DWORD\toffset of next drawing line\nLeftClipBytes\tEQU DWORD PTR ebp - 74h ;DWORD\t# left-clipped bytes\nXTotal\t\tEQU DWORD PTR ebp - 78h ;DWORD\taccumulated x-pixels\nXTotalInit\tEQU DWORD PTR ebp - 7Ch ;DWORD\tinitial roundoff for XTotal\nYTotal\t\tEQU DWORD PTR ebp - 80h ;DWORD\taccumulated y-pixels\nHeightCount\tEQU DWORD PTR ebp - 84h ;DWORD\tht counter for drawing lines\nLineStart\tEQU DWORD PTR ebp - 88h ;DWORD\taddress of start of line\nWidthCount\tEQU DWORD PTR ebp - 8Ch ;DWORD\tcounts down # bytes skipped\nStashReg\tEQU DWORD PTR ebp - 90h \t;DWORD\ttemp variable for draw routines\nMaskAdjust\tEQU DWORD PTR ebp - 94h ;DWORD  priority buffer offset\nBackAdjust\tEQU DWORD PTR ebp - 98h ;DWORD  background buffer offset\nStashECX\tEQU DWORD PTR ebp - 9Ch \t;DWORD  temp variable for ECX register\nStashEDX\tEQU DWORD PTR ebp -0A0h \t;DWORD  temp variable for EDX register\n\nLocal_Size\tEQU 00A4h\t\t; Amt of data on stack: 4+last offset\n\n;****************************** Declarations *******************************\n;---------------------------------------------------------------------------\n; Global variables used by the shape routines, defined in drawshp.asm\n;---------------------------------------------------------------------------\nGLOBAL _ShapeBuffer:DWORD\nGLOBAL _ShapeBufferSize:DWORD\nGLOBAL _MaskPage:DWORD\nGLOBAL _BackGroundPage:DWORD\nGLOBAL PredCount:DWORD\nGLOBAL PredTable:BYTE\nGLOBAL PredValue:DWORD\nGLOBAL PartialPred:DWORD\nGLOBAL PartialCount:DWORD\nGLOBAL Flags:DWORD\n\n;---------------------------------------------------------------------------\n; External tables that are defined in ds_table.asm.\n;---------------------------------------------------------------------------\nGLOBAL LSkipTable:DWORD\nGLOBAL RSkipTable:DWORD\nGLOBAL DrawTable:DWORD \n\n;------------------------------------------------------------------------------\n; Public functions, declared in the order they appear in the function tables.\n;--------------------------------------------------------------------------------\nGLOBAL\tC Not_Supported:NEAR\n;\tLSkipTable:\nGLOBAL Left_Skip:NEAR\t\t\t\t\t\t; ds_ls\nGLOBAL Left_Reverse_Skip:NEAR\t\t\t\t; ds_lrs\nGLOBAL Left_Skip:NEAR\t\t\t\t\t\t; ds_ls\nGLOBAL Left_Reverse_Skip:NEAR\t\t\t\t; ds_lrs\nGLOBAL Left_Scale_Skip:NEAR\t\t\t\t; ds_lss\nGLOBAL Left_Scale_Reverse_Skip:NEAR\t\t; ds_lsrs\nGLOBAL Left_Scale_Skip:NEAR\t\t\t\t; ds_lss\nGLOBAL Left_Scale_Reverse_Skip:NEAR\t\t; ds_lsrs\n\n;\tRSkipTable:\nGLOBAL Right_Skip:NEAR\t\t\t\t\t   ; ds_rs\nGLOBAL Right_Reverse_Skip:NEAR\t\t\t; ds_rrs\nGLOBAL Right_Skip:NEAR\t\t\t\t\t   ; ds_rs\nGLOBAL Right_Reverse_Skip:NEAR\t\t\t; ds_rrs\nGLOBAL Right_Scale_Skip:NEAR\t\t\t\t; ds_rss\nGLOBAL Right_Scale_Reverse_Skip:NEAR\t; ds_rsrs\nGLOBAL Right_Scale_Skip:NEAR\t\t\t\t; ds_rss\nGLOBAL Right_Scale_Reverse_Skip:NEAR\t; ds_rsrs\n\n;\tDrawTable:\nGLOBAL Draw_Normal:NEAR\t\t\t\t\t; ds_dn\nGLOBAL Draw_Reverse:NEAR\t\t\t\t; ds_dr\nGLOBAL Draw_Normal:NEAR\t\t\t\t\t; ds_dn\nGLOBAL Draw_Reverse:NEAR\t\t\t\t; ds_dr\nGLOBAL Draw_Scale:NEAR\t\t\t\t\t; ds_ds\nGLOBAL Draw_Scale_Reverse:NEAR\t\t; ds_dsr\nGLOBAL Draw_Scale:NEAR\t\t\t\t\t; ds_ds\nGLOBAL Draw_Scale_Reverse:NEAR\t\t; ds_dsr\n\n\n;************************* End of shape.inc ********************************\n\u001a\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/SOS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sos.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DEFINED   \n#define  _SOS_DEFINED   \n#include \"sosdefs.h\"\n\n#pragma pack(4)\n \n// error definition for sound operating system  \n#define  _SOS_ERR          -1\n\n// number of drivers allowed to be open at one time\n#define  _SOS_MAX_DRIVERS  5\n\n// structure definition for the capabilities\ntypedef struct _tagCAPABILITIES\n{\n   BYTE  szDeviceName[ 32 ];  // device name\n   WORD  wDeviceVersion;      // device version\n   WORD  wBitsPerSample;      // bits per sound sample\n   WORD  wChannels;           // stereo/mono sound card\n   WORD  wMinRate;            // minimum rate\n   WORD  wMaxRate;            // maximum rate\n   WORD  wMixerOnBoard;       // board contains mixer\n   WORD  wMixerFlags;         // mixer capabilities\n   WORD  wFlags;              // miscellaneous flags   \n   short far * lpPortList;         // list of usable ports\n   short far * lpDMAList;          // list of usable dma channels\n   short far * lpIRQList;          // list of usable irq channels\n   short far * lpRateList;         // list of usable rates, -1 if any in min to max\n   WORD  fBackground;         // foreground or background driver\n   WORD  wDeviceID;           // ID for the device\n   WORD  wTimerID;            // ID for the timer\n   \n} _SOS_CAPABILITIES; \n\n// far pointer to the device capabilities structure\ntypedef _SOS_CAPABILITIES far *  LPSOSDEVICECAPS;\n\n// flag types for driver\n#define  _FLAGS_SIGNED              0x8000\n  \n// devices that can be loaded\n#define  _SOUND_BLASTER_8_MONO      0xe000\n#define  _SOUND_BLASTER_8_ST        0xe001\n#define  _SBPRO_8_ST                _SOUND_BLASTER_8_ST\n#define  _SBPRO_8_MONO              0xe00f\n#define  _SOUND_MASTER_II_8_MONO    0xe002\n#define  _MV_PAS_8_MONO             0xe003\n#define  _MV_PAS_16_MONO            0xe004\n#define  _MV_PAS_8_ST               0xe005\n#define  _MV_PAS_16_ST              0xe006\n#define  _ADLIB_GOLD_8_ST           0xe007\n#define  _ADLIB_GOLD_16_ST          0xe008\n#define  _ADLIB_GOLD_8_MONO         0xe009\n#define  _ADLIB_GOLD_16_MONO        0xe00a\n#define  _MICROSOFT_8_MONO          0xe00b\n#define  _MICROSOFT_8_ST            0xe00c\n#define  _MICROSOFT_16_MONO         0xe00d\n#define  _MICROSOFT_16_ST           0xe00e\n#define  _SOUND_SOURCE_8_MONO_PC    0xe010\n#define  _SOUND_SOURCE_8_MONO_TANDY 0xe011\n#define  _GENERAL_PORT_8_MONO       0xe012\n#define  _GENERAL_PORT_8_MONO_R     0xe013\n#define  _SIERRA_8_MONO             0xe014\n#define  _SB16_8_MONO               0xe015\n#define  _SB16_8_ST                 0xe016\n#define  _SB16_16_MONO              0xe017\n#define  _SB16_16_ST                0xe018\n#define  _ESS_AUDIODRIVE_8_MONO     0xe019\n#define  _ESS_AUDIODRIVE_8_ST       0xe01a\n#define  _ESS_AUDIODRIVE_16_MONO    0xe01b\n#define  _ESS_AUDIODRIVE_16_ST      0xe01c\n#define  _SOUNDSCAPE_8_MONO         0xe01d\n#define  _SOUNDSCAPE_8_ST           0xe01e\n#define  _SOUNDSCAPE_16_MONO        0xe01f\n#define  _SOUNDSCAPE_16_ST          0xe020\n#define  _RAP10_8_MONO              0xe021\n#define  _RAP10_16_MONO             0xe022\n#define  _GUS_8_MONO                0xe023\n#define  _GUS_8_ST                  0xe024\n#define  _GUS_16_MONO               0xe025\n#define  _GUS_16_ST                 0xe026\n#define  _GUS_MAX_8_MONO            0xe027\n#define  _GUS_MAX_8_ST              0xe028\n#define  _GUS_MAX_16_MONO           0xe029\n#define  _GUS_MAX_16_ST             0xe02a\n#define  _WAVEJAMMER_8_MONO         0xe02b\n#define  _WAVEJAMMER_8_ST           0xe02c\n#define  _WAVEJAMMER_16_MONO        0xe02d\n#define  _WAVEJAMMER_16_ST          0xe02e\n#define  _TEMPOCS_8_MONO            0xe02f\n#define  _TEMPOCS_8_ST              0xe030\n#define  _TEMPOCS_16_MONO           0xe031\n#define  _TEMPOCS_16_ST             0xe032\n#define  _WAVEJAMMERCD_8_MONO       0xe033\n#define  _WAVEJAMMERCD_8_ST         0xe034\n#define  _WAVEJAMMERCD_16_MONO      0xe035\n#define  _WAVEJAMMERCD_16_ST        0xe036\n#define  _SOUND_BLASTER_8_MONO_R    0xe050\n#define  _MICROSOFT_8_MONO_R        0xe051\n#define  _SOUND_MASTER_II_8_MONO_R  0xe052\n#define  _ADLIB_GOLD_8_MONO_R       0xe053\n#define  _MV_PAS_8_MONO_R           0xe054\n#define  _RAP10_8_MONO_R            0xe058\n#define  _RAP10_16_MONO_R           0xe059\n#define  _SB16_8_MONO_R             0xe05a\n#define  _SB16_8_ST_R               0xe05b\n#define  _SB16_16_MONO_R            0xe05c\n#define  _SB16_16_ST_R              0xe05d\n#define  _MV_PAS_16_MONO_R          0xe060\n#define  _SOUNDSCAPE_8_MONO_R       0xe061\n#define  _SOUNDSCAPE_8_ST_R         0xe062\n#define  _SOUNDSCAPE_16_MONO_R      0xe063\n#define  _SOUNDSCAPE_16_ST_R        0xe064\n#define  _ESS_AUDIODRIVE_8_MONO_R   0xe065\n#define  _ESS_AUDIODRIVE_8_ST_R     0xe066\n#define  _ESS_AUDIODRIVE_16_MONO_R  0xe067\n#define  _ESS_AUDIODRIVE_16_ST_R    0xe068\n#define  _SPEECH_THING_8_MONO       0xe090\n#define  _YAMAHA_8_MONO             0xe106\n#define  _INT_SPEAKER_8_MONO        0xe107\n\n// call indexes for the loadable drivers\nenum\n{ \n   _DRV_INIT,\n   _DRV_UNINIT,\n   _DRV_SETRATE,\n   _DRV_SETACTION,\n   _DRV_START,\n   _DRV_STOP,\n   _DRV_PAUSE,\n   _DRV_RESUME,\n   _DRV_CAPABILITIES,\n   _DRV_PLAY_FOREGROUND,\n   _DRV_GET_FILL_INFO, \n   _DRV_GET_CALL_FUNCTIONS,\n   _DRV_SET_CALL_FUNCTIONS\n};\n\n// fill info\ntypedef  struct   _tagFillInfo\n         {\n\n            LPSTR lpFillHandler;                   // pointer to fill handler\n            LPWORD lpDMAFillCount;                 // pointer to dma count\n            LPSTR lpSampleList;                    // pointer to sample list\n            LPWORD lpDMAMasterVolume;              // pointer to dma count\n\n         } _SOS_FILL_INFO;\n\n// caps info structure\ntypedef  struct   _tagCapsInfo\n         {\n\n            LPSTR    lpPortList;                   // pointer to port list\n            LPSTR    lpDMAList;                    // pointer to DMA list\n            LPSTR    lpIRQList;                    // pointer to IRQ list\n            LPSTR    lpRateList;                   // pointer to rate list\n\n         } _SOS_CAPS_INFO;\n\n// maximum number of available voice\n#define  _MAX_VOICES    32\n\n// structure definition\ntypedef  struct   _tagSAMPLE\n{\n   LPSTR    samplePtr;                 // pointer to data buffer\n   LPSTR    sampleData;                // pointer to active data\n   LPSTR    sampleLoopPtr;             // pointer for loop back\n\n   WORD     sampleLength;              // length of sample\n   WORD     sampleIndex;               // index into sample\n   WORD     sampleLoopLength;          // length of loop\n   \n   WORD     sampleBytesLeft;           // bytes left to play in sample\n\n   WORD     sampleLoopPoint;           // byte count for loop point\n   WORD     sampleLoopEndLength;       // length of remaining chunk\n\n   short    sampleFlags;               // control sample\n   short    sampleVolume;              // volume control\n   short    sampleID;                  // sample ID\n\n   short    sampleChannel;             // channel to play sample on\n   short    sampleLoopCount;           // loop count\n   short    sampleLastFill;            // last fill position\n   VOID ( far cdecl * sampleCallback )( WORD, WORD, WORD ); // callback function for sample\n\n   WORD     samplePitchAdd;\n   short    samplePitchFraction;\n\n   short    samplePort;                // port to use for non-dma digitized\n\n   WORD     sampleTotalBytes;\n   WORD     sampleByteLength;\n\n   short    samplePanLocation;\n   short    samplePanSpeed;\n   short    samplePanDirection;\n   short    samplePanStart;\n   short    samplePanEnd;\n   \n   short    sampleDelayBytes;\n   short    sampleDelayRepeat;\n   \n   WORD     sampleADPCMPredicted;\n   short    sampleADPCMIndex;\n\n   short    sampleRootNoteMIDI;   \n\n   WORD  sampleTemp1;   \n   \n} _SOS_SAMPLE;\n\n// enumeration for left or right channel\nenum\n{\n   _LEFT_CHANNEL,\n   _RIGHT_CHANNEL,\n   _CENTER_CHANNEL,\n   _INTERLEAVED\n};\n\n// enumeration for foreground and background\nenum\n{ \n   _FOREGROUND,\n   _BACKGROUND \n};\n\n// defines for the sample flags\n#define  _ACTIVE           0x8000\n#define  _LOOPING          0x4000\n#define  _FIRST_TIME       0x2000\n#define  _PENDING_RELEASE  0x1000\n#define  _CONTINUE_BLOCK   0x0800\n#define  _PITCH_SHIFT      0x0400\n#define  _PANNING          0x0200\n#define  _VOLUME           0x0100\n#define  _TRANSLATE16TO8   0x0080\n#define  _STAGE_LOOP       0x0040\n#define  _TRANSLATE8TO16   0x0020\n#define  _STEREOTOMONO     0x0010\n\n// defines for the wParam flags \n#define  _SINGLE_SAMPLE 0x01\n\n#define  _SOS_DCAPS_AUTO_REINIT     0x01\n#define  _SOS_DCAPS_MPU_401         0x02\n#define  _SOS_DCAPS_OPL2            0x04\n#define  _SOS_DCAPS_OPL3            0x08\n#define  _SOS_DCAPS_OPL4            0x10\n#define  _SOS_DCAPS_WAVETABLE       0x20\n#define  _SOS_DCAPS_DL_SAMPLES      0x40\n#define  _SOS_DCAPS_FIFO_DEVICE     0x80\n#define  _SOS_DCAPS_ENV_NEEDED      0x100\n#define  _SOS_DCAPS_PSEUDO_DMA1     0x200\n#define  _SOS_DCAPS_SIGNED_DATA     0x8000\n\n// file header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // number of drivers in the file\n   WORD  wDrivers;\n\n   // offset of first driver\n   WORD  lOffset;\n\n   // size of the file\n   WORD  lFileSize;\n\n} _FILEHEADER;\n\n// driver header structure\ntypedef struct\n{\n   // name ID\n   BYTE  szName[ 32 ];\n\n   // offset of next driver\n   WORD  lNextDriver;\n\n   // size of current driver\n   WORD  wSize;\n\n   // id for the current device\n   WORD  wDeviceID;\n\n   // id for the type of DOS extender\n   WORD  wExtenderType;\n\n} _DRIVERHEADER;\n\n// device hardware information\ntypedef struct\n{\n   // port to be used\n   WORD  wPort;\n\n   // irq to use\n   WORD  wIRQ;\n\n   // dma channel to se\n   WORD  wDMA; \n  \n   // extra parameter\n   WORD  wParam;\n\n} _SOS_HARDWARE;\n\n// structure definition for start sample\ntypedef struct\n{\n   // pointer to sample\n   LPSTR lpSamplePtr;\n\n   // size of the sample\n   WORD  dwSampleSize;\n\n   // number of times to loop the sample -1 is infinite\n   WORD  wLoopCount;\n\n   // channel to play sample on\n   WORD  wChannel;\n\n   // volume to play sample at\n   WORD wVolume;\n\n   // id for the sample\n   WORD  wSampleID;\n\n   // far pointer to the callback function\n   VOID ( far cdecl *lpCallback )( WORD, WORD, WORD );\n\n   // port to use if driver is a non-dma background driver\n   WORD  wSamplePort; \n\n   // flags field\n   WORD  wSampleFlags;\n\n   // total length of sample including loops, etc..\n   WORD     dwSampleByteLength;\n\n   // loop point for the sample\n   WORD  dwSampleLoopPoint;\n   WORD  dwSampleLoopLength;\n\n   // pitch shifting components \n   WORD     dwSamplePitchAdd;\n   WORD    wSamplePitchFraction;\n\n   // pan components\n   WORD    wSamplePanLocation;\n   WORD    wSamplePanSpeed;\n   WORD    wSamplePanDirection;\n   WORD    wSamplePanStart;\n   WORD    wSamplePanEnd;\n   \n   // delay parts\n   WORD    wSampleDelayBytes;\n   WORD    wSampleDelayRepeat;\n\n   // compression components   \n   WORD     dwSampleADPCMPredicted;\n   WORD    wSampleADPCMIndex;\n\n   // root note for pitch shifting \n   WORD    wSampleRootNoteMIDI;   \n\n   // filler for future upgrades\n   WORD  dwSampleTemp1;   \n   WORD  dwSampleTemp2;   \n   WORD  dwSampleTemp3;   \n\n} _SOS_START_SAMPLE;\n\n// structure for initializing a driver\ntypedef struct\n{  \n   WORD  wBufferSize;\n   LPSTR lpBuffer;\n   BOOL  wAllocateBuffer;\n   WORD  wSampleRate;\n   WORD  wParam;\n   LONG  dwParam;\n   VOID ( far *lpFillHandler )( VOID );\n   LPSTR lpDriverMemory;\n   LPSTR lpDriverMemoryCS;\n   LPSTR lpTimerMemory;\n   LPSTR lpTimerMemoryCS;\n   WORD  wTimerID;\n   WORD  wPhysical;\n\n} _SOS_INIT_DRIVER;\n\n// define for the timer types to use\n#define  _SOS_NORMAL_TIMER          0x00\n\n// enumeration for the timer types\nenum\n{\n   _TIMER_8_MONO   =     0x1000,\n   _TIMER_8_ST,          \n   _TIMER_16_MONO,       \n   _TIMER_16_ST,         \n   _TIMER_8_MONO_ULAW,  \n   _TIMER_8_ST_ULAW,    \n   _TIMER_16_MONO_ULAW, \n   _TIMER_16_ST_ULAW,   \n   _TIMER_8_MONO_REC,   \n   _TIMER_8_MONO_ULAW_REC,\n   _TIMER_UNDEFINED_1,      \n   _TIMER_UNDEFINED_2,\n   _TIMER_UNDEFINED_3,\n   _TIMER_UNDEFINED_4,\n   _TIMER_UNDEFINED_5,\n   _TIMER_UNDEFINED_6,\n   _TIMER_UNDEFINED_7,\n   _TIMER_UNDEFINED_8,\n   _TIMER_UNDEFINED_9,\n   _TIMER_UNDEFINED_A,\n   _TIMER_UNDEFINED_B,\n   _TIMER_UNDEFINED_C,\n   _TIMER_UNDEFINED_D,\n   _TIMER_UNDEFINED_E,\n   _TIMER_UNDEFINED_F,\n   _TIMER_UNDEFINED_10,\n   _TIMER_UNDEFINED_11,\n   _TIMER_UNDEFINED_12,\n   _TIMER_UNDEFINED_13,\n   _TIMER_UNDEFINED_14,\n   _TIMER_UNDEFINED_15,\n   _TIMER_UNDEFINED_16,\n   _TIMER_8_SOUND_SOURCE,\n   _TIMER_8_SOUND_SOURCE_TANDY,\n   _TIMER_8_GENERAL_PORT,\n   _TIMER_8_GENERAL_PORT_REC   \n};\n\n// define for no slots available\n#define  _ERR_NO_SLOTS ( WORD )-1\n\n// error codes for the system\nenum\n{\n   _ERR_NO_ERROR,\n   _ERR_DRIVER_NOT_LOADED,\n   _ERR_INVALID_POINTER,\n   _ERR_DETECT_INITIALIZED,\n   _ERR_FAIL_ON_FILE_OPEN,\n   _ERR_MEMORY_FAIL,\n   _ERR_INVALID_DRIVER_ID,\n   _ERR_NO_DRIVER_FOUND,\n   _ERR_DETECTION_FAILURE,\n   _ERR_DRIVER_LOADED,\n   _ERR_INVALID_HANDLE,\n   _ERR_NO_HANDLES,\n   _ERR_PAUSED,   \n   _ERR_NOT_PAUSED,\n   _ERR_INVALID_DATA,\n   _ERR_DRV_FILE_FAIL,\n   _ERR_INVALID_PORT,\n   _ERR_INVALID_IRQ,\n   _ERR_INVALID_DMA,\n   _ERR_INVALID_DMA_IRQ\n};   \n\n// maximum number of timer events that can be registered \n#define  _TIMER_MAX_EVENTS    0x10  \n\n// flags for the debugging system\n#define  _SOS_DEBUG_NORMAL       0x0000\n#define  _SOS_DEBUG_NO_TIMER     0x0001\n#define  _SOS_TIMER_DPMI         0x0002\n\n// define for types of DOS extenders\n#define  _SOS_RATIONAL           0x8000\n#define  _SOS_FLASHTECK          0x4000\n\n// defines for the types of timers for different\n// dos extenders\n#define  _SOS_TIMER_NEAR         0x8000\n#define  _SOS_TIMER_FAR          0x4000\n \n// values for callback information\nenum\n{\n   _SAMPLE_PROCESSED,\n   _SAMPLE_LOOPING,\n   _SAMPLE_DONE\n};\n\n// define for special 18.2 callback rate to dos\n#define  _TIMER_DOS_RATE   0xff00\n\n#pragma pack()\n\n#pragma aux int_3 = \"int 3\"\n \n#pragma pack( 1 ) \ntypedef struct\n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned       segment;\n\tunsigned short\tnumber_available;\n\tunsigned short number_used;\n\tunsigned       page0;\n\n} EVDS_STRUCT;\n\ntypedef struct \n{\n\tunsigned       region_size;\n\tunsigned       offset;\n\tunsigned short segment;\n\tunsigned short\tID;\n\tunsigned       physical;\n\n} VDS_STRUCT;\n\n#pragma pack() \n\n#include \"sosdata.h\"\n#include \"sosfnct.h\"\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/SOSCOMP.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n*\n*  File              : soscomp.h\n*  Date Created      : 6/1/94\n*  Description       : \n*\n*  Programmer(s)     : Nick Skrepetos\n*  Last Modification : 10/1/94 - 11:37:9 AM\n*  Additional Notes  : Modified by Denzil E. Long, Jr.\n*\n*****************************************************************************\n*            Copyright (c) 1994,  HMI, Inc.  All Rights Reserved            *\n****************************************************************************/\n\n#ifndef  _SOS_COMPRESS\n#define  _SOS_COMPRESS\n\n/* compression types */\nenum {\n\t_ADPCM_TYPE_1,\n\t};\n\n/* define compression structure */\ntypedef struct _tagCOMPRESS_INFO {\n\tchar       *lpSource;\n\tchar       *lpDest;\n\tunsigned long dwCompSize;\n\tunsigned long dwUnCompSize;\n\tunsigned long dwSampleIndex;\n\tlong          dwPredicted;\n\tlong          dwDifference;\n\tshort         wCodeBuf;\n\tshort         wCode;\n\tshort         wStep;\n\tshort         wIndex;\n\n\tunsigned long dwSampleIndex2; //added BP for channel 2\n\tlong          dwPredicted2;   //added BP for channel 2\n\tlong          dwDifference2; \t//added BP for channel 2\n\tshort         wCodeBuf2; \t\t//added BP for channel 2\n\tshort         wCode2; \t\t\t//added BP for channel 2\n\tshort         wStep2; \t\t\t//added BP for channel 2\n\tshort         wIndex2; \t\t\t//added BP for channel 2\n\tshort         wBitSize;\n\tshort\t\t\t  wChannels;\t\t//added BP for # of channels\n\t} _SOS_COMPRESS_INFO;\n\n/* compressed file type header */\ntypedef struct _tagCOMPRESS_HEADER {\n\tunsigned long dwType;              // type of compression\n\tunsigned long dwCompressedSize;    // compressed file size\n\tunsigned long dwUnCompressedSize;  // uncompressed file size\n\tunsigned long dwSourceBitSize;     // original bit size\n\tchar          szName[16];          // file type, for error checking\n\t} _SOS_COMPRESS_HEADER;\n\n/* Prototypes */\nextern \"C\" {\n\tvoid sosCODECInitStream(_SOS_COMPRESS_INFO *);\n\tunsigned long sosCODECCompressData(_SOS_COMPRESS_INFO *,\tunsigned long);\n\tunsigned long sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);\n}\n\n#endif\n\u001a\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/SOSDATA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdata.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_DATA\n#define  _SOS_DATA\n\n#include <stddef.h>\n\n#pragma pack(4) \nextern   WORD     _sosDIGIData_Start;\nextern   WORD     _sosDIGIData_End;\nextern   WORD     _wSOSDriverLinear[];\nextern   WORD     _wSOSTimerLinear[];\nextern   LPSTR    _lpSOSDriver[];\nextern   LPSTR    _lpSOSTimer[];\nextern   LPSTR    _lpSOSDriverCS[];\nextern   LPSTR    _lpSOSTimerCS[];\nextern   BOOL     _wSOSDriverLoaded[];\nextern   BOOL     _wSOSTimerLoaded[];\nextern   BOOL     _wSOSDriverInitialized[];\nextern   WORD     _wSOSOutputRate[];\nextern   WORD     _wSOSDMABuffersize[];\nextern   LONG     _dwSOSDMABufferPhysical[];\nextern   LPSTR    _lpSOSDMABuffer[];\nextern   BOOL     _wTimerUsed;\nextern   VOID ( far *_lpSOSFillHandler[] )( VOID );\nextern   WORD     _wSOSTimerType[];\nextern   WORD     _wSOSDriverType[];\nextern   _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ];\nextern   LPWORD      _lpSOSDMAIrqCount[];\nextern   LPWORD      _lpSOSDMAFillCount[];\nextern   WORD        _wSOSTmrNextCount;\nextern   VOID ( interrupt far *_lpSOSOldTimer )( VOID );\nextern   WORD     _wSOSDriverID[];\nextern   _SOS_CAPABILITIES _sSOSDriverCaps[];\nextern   WORD        _wSOSDMAPortList[];\nextern   BYTE        _bSOSDMAChannel[];\nextern   _SOS_INIT_DRIVER     _sSOSDIGIInitDriver[];\nextern   BYTE  _pSOSDriverPath[];\nextern   BYTE  _pSOSTempDriverPath[];\nextern   BOOL  _wTIMERUsed;\nextern   WORD  _wTIMERValue;\nextern   VOID ( far * _lpTIMEREvents[] )( VOID );\nextern   WORD _wTIMEREventRate[];\nextern   WORD _dwTIMEREventFraction[];\nextern   WORD _dwTIMEREventFractionCurrent[];\nextern   BYTE  _bSOSMIDITimerSongHandler[];\nextern   BYTE  _bSOSMIDISongHandle;\nextern   WORD  _wSOSTimerMemHandle[];\nextern   WORD  _wSOSDriverMemHandle[];\nextern   WORD  _wSOSRealSeg[];\n\nextern   _FILEHEADER    _sDETFileHeader;\nextern   _DRIVERHEADER  _sDETDriverHeader;\nextern   _FILEHEADER    sLOADFileHeader;\nextern   _DRIVERHEADER  sLOADDriverHeader;\nextern   BOOL           _wDETInitialized;\nextern   WORD           _wDETLinear;\nextern   LPSTR          _lpDETDriverBuffer;    \nextern   LPSTR          _lpDETDriverBufferCS;\nextern   WORD           _hDETFile;\nextern   DWORD          _dwDETDriverIndex;\nextern   WORD           _wDETDriverIndexCur;\nextern   WORD           _wDETMemHandle;\nextern   LPSOSDEVICECAPS _lpDETDeviceCaps;\nextern   _SOS_CAPABILITIES _sDETCaps;  \nextern   PSTR _pSOSErrorStrings[];\nextern   BOOL _wSOSBufferAllocated[];\nextern   BOOL _wSOSSystemInitialized;\nextern   VDS_STRUCT _sSOSVDSInfo;\nextern   _SOS_FILL_INFO _sSOSFillInfo;\nextern   WORD    _wSOSTimerEventIndex;\nextern   WORD  _wSOSTimerEntered;\nextern   WORD  _wSOSDriverSize[];\nextern   WORD  _wSOSTimerSize[];\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nextern   WORD  _sosDIGIData1_Start;\nextern   WORD  _sosDIGIData1_End;\nextern   WORD  _sosDIGIData2_Start;\nextern   WORD  _sosDIGIData2_End;\nextern   BYTE  _bTIMERInstalled;\nextern   BYTE  _bTIMERDPMI;\nextern   WORD  wDetectPort;\nextern   WORD  wDetectIRQ;\nextern   WORD  wDetectDMA;\nextern   WORD  wDetectParam;\n#ifdef __cplusplus\n}\n#endif \n\n#pragma pack()\n\n#endif\n\u001a\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/SOSDEFS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosdefs.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n\n#ifndef  _SOSDEFS_DEFINED\n#define  _SOSDEFS_DEFINED\n\n#undef   _TRUE\n#undef   _FALSE\n#undef   _NULL\nenum  \n      { \n         _FALSE, \n         _TRUE \n      };\n\n#define  _NULL  0\n\n#ifndef  VOID\n#define  VOID           void\n#endif\ntypedef  int            BOOL;\ntypedef  unsigned int   UINT;\ntypedef  unsigned char  BYTE;\ntypedef  unsigned       WORD;\n#ifndef  LONG\ntypedef  signed long    LONG;\n#endif\ntypedef  unsigned long  DWORD;\n\ntypedef  BYTE  *        PBYTE;\ntypedef  char near *    PSTR;\ntypedef  WORD  *        PWORD;\ntypedef  LONG  *        PLONG;\ntypedef  VOID  *        PVOID;\n\ntypedef  BYTE  far   *  LPBYTE;\ntypedef  BYTE  far   *  LPSTR;\ntypedef  WORD  far   *  LPWORD;\ntypedef  LONG  far   *  LPLONG;\ntypedef  VOID  far   *  LPVOID;\n\ntypedef  BYTE  huge  *  HPBYTE;\ntypedef  BYTE  huge  *  HPSTR;\ntypedef  WORD  huge  *  HPWORD;\ntypedef  LONG  huge  *  HPLONG;\ntypedef  VOID  huge  *  HPVOID;\n\ntypedef  unsigned       HANDLE;\n\n#endif\n\u001a\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/SOSFNCT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosfnct.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#ifndef  _SOS_FUNCTIONS\n#define  _SOS_FUNCTIONS\n\n#pragma pack(4)\n\nWORD sosDIGILockMemory          (  VOID  );\nWORD sosDIGIUnLockMemory        (  VOID  );\nWORD sosDIGIInitSystem           (  LPSTR, WORD  );\nWORD sosDIGIUnInitSystem         (  VOID  );\nWORD sosDIGIInitDriver           (  WORD, _SOS_HARDWARE far *,\n                                    _SOS_INIT_DRIVER far *, WORD far *   );\nWORD sosDIGIUnInitDriver         (  WORD, BOOL, BOOL  );\nWORD sosDIGILoadDriver          (  WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD sosDIGIUnLoadDriver         (  WORD  );\nWORD sosDIGIGetDeviceCaps        (  WORD, LPSOSDEVICECAPS  );\n\n#ifdef PHARLAP\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#else\nLPSTR sosDIGIAllocateBuffer      (  WORD , WORD *, WORD * );\n#endif\n\nWORD sosDIGIStopSample           (  WORD, WORD  );\nWORD sosDIGISamplesPlaying       (  WORD  );\nBOOL sosDIGISampleDone           (  WORD, WORD  );\nBOOL sosDIGISampleFilling        (  WORD, WORD  );\nWORD sosDIGIStartSample          (  WORD, _SOS_START_SAMPLE far *  );\nWORD sosDIGIContinueSample       (  WORD, WORD, _SOS_START_SAMPLE far * );\n\n\nWORD  sosDIGIDetectInit          (  LPSTR  );\nWORD  sosDIGIDetectUnInit        (  VOID  );\nWORD  sosDIGIDetectFindHardware  (  WORD, _SOS_CAPABILITIES far *, WORD far * );\nWORD  sosDIGIDetectFindFirst     (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectFindNext      (  _SOS_CAPABILITIES far *, WORD far *  );\nWORD  sosDIGIDetectGetSettings   (  _SOS_HARDWARE far *  );\nWORD  sosDIGIDetectGetCaps       (  WORD, _SOS_CAPABILITIES far *  );\nWORD  sosDIGIDetectVerifySettings(  _SOS_HARDWARE far *  );\nPSTR  sosGetErrorString          (  WORD  );\n\nWORD  sosDIGILoadTimer           (  WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );\nWORD  sosDIGIUnLoadTimer         (  WORD  );\n\nWORD  sosTIMERRegisterEvent      ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle );\nWORD  sosTIMERInitSystem               (  WORD, WORD  );\nWORD  sosTIMERUnInitSystem             (  WORD  );\nWORD  sosTIMERSetRate                  (  WORD  );  \nWORD  sosTIMERRemoveEvent              (  WORD );\nWORD  sosTIMERAlterEventRate           (  WORD, WORD  );\nWORD  sosTIMERGetEventRate             (  WORD  );\nVOID far sosTIMEROldHandler            (  VOID  );\nVOID far sosTIMERHandler               (  VOID  );\n\n// functions in soscntl.c\nWORD  sosDIGISetSampleVolume     ( WORD, WORD, WORD );\nWORD  sosDIGIGetSampleVolume     ( WORD, WORD );\nWORD  sosDIGISetChannel          ( WORD, WORD, WORD );\nWORD  sosDIGIGetChannel          ( WORD, WORD );\nWORD  sosDIGIGetBytesProcessed   ( WORD, WORD );\nWORD  sosDIGIGetLoopCount        ( WORD, WORD );\nWORD  sosDIGISetPanLocation      ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanLocation      ( WORD, WORD );\nDWORD sosDIGISetPitch            ( WORD, WORD, DWORD );\nDWORD sosDIGIGetPitch            ( WORD, WORD );\nWORD  sosDIGIGetDMAPosition      ( WORD );\nWORD  sosDIGISetPanSpeed         ( WORD, WORD, WORD );\nWORD  sosDIGIGetPanSpeed         ( WORD, WORD );\nWORD  sosDIGIGetSampleID         ( WORD, WORD );\nWORD  sosDIGIGetSampleHandle     ( WORD, WORD );\nWORD  sosDIGISetMasterVolume     ( WORD, WORD );\n#ifdef PHARLAP\nVOID  sosFreeVDSPage          ( unsigned short, unsigned short, DWORD );\nWORD  sosAllocVDSPage         ( unsigned short *, unsigned short *, DWORD * );\n#else\nWORD  sosAllocVDSPage            ( LPSTR *, WORD *, WORD * );\nVOID  sosFreeVDSPage             ( WORD, WORD, LONG );\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef PHARLAP\nextern   int   cdecl sosRealFree          ( int );\nextern   BOOL  cdecl  _sos_read( WORD, LPSTR, WORD, WORD * );\nextern   int   cdecl sosRealAlloc( int, int *, int * );\nextern   void  cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD );\nextern   int   cdecl sosGetCS( VOID );\nextern   int   cdecl sosGetES( VOID );\n#else\nextern   int   cdecl sosRealAlloc         ( int, int *, int * );\nextern   int   cdecl sosRealFree          ( int );\n#endif\n\n// sos driver functions\nextern   WORD  cdecl sosDRVLockMemory     ( DWORD, DWORD );\nextern   WORD  cdecl sosDRVUnLockMemory   ( DWORD, DWORD );\nextern   void  cdecl sosDRVGetCapsInfo    ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVGetCapsPtr     ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );\nextern   void  cdecl sosDRVInit           ( LPSTR, LPSTR, int, int, int, int, int, int );  \nextern   void  cdecl sosDRVStart          ( LPSTR, LPSTR, int, int );\nextern   void  cdecl sosDRVSetRate        ( LPSTR, LPSTR, int );\nextern   void  cdecl sosDRVSetAction      ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVStop           ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVUnInit         ( LPSTR, LPSTR );\nextern   void  cdecl sosDRVGetFillInfo    ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * );\nextern   void  cdecl sosFillSampleStructs ( PSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVExist       ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVGetSettings ( LPSTR, LPSTR );\nextern   WORD  cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR );\nextern   WORD  cdecl sosDIGIInitForWindows( WORD );\nextern   WORD  cdecl sosDIGIUnInitForWindows( WORD );\nextern   LPSTR cdecl sosAllocateFarMem      ( WORD, PSTR, WORD * );\nextern   LPSTR cdecl sosCreateAliasCS       ( LPSTR );\nextern   VOID  cdecl sosFreeSelector        ( LPSTR, DWORD );\nextern   LPSTR cdecl sosMAKEDOSPtr          ( PSTR );\nextern   VOID  cdecl sosDetDRVSetEnvString  ( DWORD, PSTR );\nextern   PSTR  cdecl sosDetDRVGetEnvString  ( DWORD );\nextern   VOID  cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR );\nextern   VOID  cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR );\nextern   WORD  cdecl sosDRVGetFreeMemory     ( VOID );\nextern   WORD  cdecl sosDRVAllocVDSStruct    ( WORD, WORD *, WORD * );\nextern   WORD  cdecl sosDRVFreeVDSStruct     ( WORD, WORD );\nextern   WORD  cdecl sosDRVIsWindowsActive   ( VOID );\nextern   WORD  cdecl sosDRVVDSGetBuffer    ( WORD );\nextern   WORD  cdecl sosDRVVDSFreeBuffer   ( WORD );\nextern   WORD  cdecl getDS( VOID );\nextern   WORD  cdecl sosDRVMakeDMASelector   ( WORD );  \nextern   WORD  cdecl sosDRVFreeDMASelector   ( WORD );  \n\n\nextern   void  cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) );\nextern   void  cdecl sosTIMERDRVUnInit( void );\nextern   void  cdecl sosTIMERDRVHandler( void );\nextern   void  cdecl sosTIMERDRVFHandler( void );\nextern   void  cdecl sosTIMERDRVEnable( void );\nextern   void  cdecl sosTIMERDRVDisable( void );\nextern   void  cdecl sosTIMERDRVCallOld( void );\nextern   void  cdecl sosTIMERDRVSetRate( WORD );    \nextern   void  cdecl sosDIGITimer_Start( void );\nextern   void  cdecl sosDIGITimer_End( void );\nextern   void  cdecl sosDIGIDrv_Start( void );\nextern   void  cdecl sosDIGIDrv_End( void );\n#ifdef __cplusplus\n}\n#endif \n\n// external functions for handling system initialization and \n// uninitialization\nWORD  sosEXDIGInitDriver               (  WORD, WORD, WORD, LPSTR,\n                                          _SOS_HARDWARE far *, WORD *  );\nWORD  sosEXDIGIUnInitDriver            (  VOID  );\n\nWORD  sosEXDETFindDriver               (  WORD, LPSTR, _SOS_HARDWARE far *,\n                                          _SOS_CAPABILITIES far *  );\n\n// memory locking prototypes\nVOID  sosDIGICaps_Start( VOID );\nVOID  sosDIGICaps_End( VOID );\nVOID  sosDIGIErr_Start( VOID );\nVOID  sosDIGIErr_End( VOID );\nVOID  sosDIGITmr_Start( VOID );\nVOID  sosDIGITmr_End( VOID );\nVOID  sosDIGIStart_Start( VOID );\nVOID  sosDIGIStart_End( VOID );\nVOID  sosDIGIPlyng_Start( VOID );\nVOID  sosDIGIPlyng_End( VOID );\nVOID  sosDIGIRate_Start( VOID );\nVOID  sosDIGIRate_End( VOID );\nVOID  sosDIGIDone_Start( VOID );\nVOID  sosDIGIDone_End( VOID );\nVOID  sosDIGIDetec_Start( VOID );\nVOID  sosDIGIDetec_End( VOID );\nVOID  sosDIGIInit_Start( VOID );\nVOID  sosDIGIInit_End( VOID );\nVOID  sosDIGILoad_Start( VOID );\nVOID  sosDIGILoad_End( VOID );\nVOID  sosDIGICntl_Start( VOID );\nVOID  sosDIGICntl_End( VOID );\n\n#pragma pack()\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/SOSRES.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/****************************************************************************\n\n   File              : sosres.h\n\n   Programmer(s)     : Don Fowler, Nick Skrepetos\n   Date              :\n\n   Purpose           : Include Files For Zortech C++ Compiler\n\n   Last Updated      :\n\n****************************************************************************\n               Copyright(c) 1993,1994 Human Machine Interfaces \n                            All Rights Reserved\n****************************************************************************/\n\n#define  _SOS_RESOURCE\n#ifndef  _SOS_RESOURCE\n#define  _SOS_RESOURCE\n\n// structure for resource file header\ntypedef struct\n{\n   // file version\n   WORD     wVersion;\n\n   // file size\n   LONG     dwFileSize;\n\n   // number of resources in file\n   WORD     wResCount;\n\n   // offset of resource data from top of file\n   LONG     dwResOffset;\n\n   // offset of sync track from top of file\n   LONG     dwSyncTrackOffset;\n\n}  _RES_FILE_HEADER;\n\n// structure for resource block header\ntypedef struct\n{\n   // resource id\n   WORD     wID;\n\n   // resource type\n   WORD     wResType;\n\n   // offset of next block\n   LONG     dwNextBlock; \n\n   // size of the current resource information\n   LONG     dwResSize;\n\n   // rate to play block at\n   WORD     wBlockRate;\n\n   // id for the sync track to use\n   WORD     wSyncTrackID;\n\n}  _RES_BLOCK_HEADER;\n\n// structure for sync mark tag\ntypedef struct _tagSYNCMARK\n{\n   // ID of the type of mark being used\n   WORD  wID;\n\n   // location in data of sync mark\n   LONG  dwSyncOffset;\n\n   // length of sync block\n   LONG  dwSyncSize;\n\n   // start sample data\n   _SOS_START_SAMPLE sampleData;\n    \n} _RES_SYNCMARK;\n\ntypedef union\n{\n   // structure for sync mark tag\n   _RES_SYNCMARK  syncMark; \n\n} _RES_TAG;\n\n// union for filter information for prepareWave\ntypedef union\n{\n   // filter type\n   WORD     wFilterID;\n\n   // structure for volume\n   struct   volume \n   {\n      WORD  wVolume;\n   };\n\n   // structure for delay\n   struct   delay\n   {  \n      WORD  wDelaySamples;\n   };\n\n} _SOS_FILTER; \n\n \n#endif\n\n\u001a"
  },
  {
    "path": "WWFLAT32/INCLUDE/SOUND.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : SOUND.H                                  *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : September 1, 1993                        *\n *                                                                         *\n *                  Last Update : September 1, 1993   [JLB]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SOUND_H\n#define SOUND_H\n\n#define\tHMI_DRIVER\tTRUE\n#include\t\"sos.h\"\n#include\t\"soscomp.h\"\n\n/*\n**\tMaximum number of sound effects that may run at once.\n*/\n#define\tMAX_SFX\t\t4\n\n/*\n** Size of temp HMI low memory staging buffer.\n*/\n#define\tSFX_MINI_STAGE_BUFFER_SIZE\t\t(1024*4)\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/SOUNDINT.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : SOUNDINT.H                               *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : June 23, 1995                            *\n *                                                                         *\n *                  Last Update : June 23, 1995   [PWG]                    *\n *                                                                         *\n * This file is the include file for the Westwood Sound Sytem defines and  *\n * routines that are handled in an interrupt.\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"sound.h\"\n\n/*\n** Defines for true and false.  These are included because we do not allow\n** the sound int to include any of the westwood standard headers.  If we\n** did, there might be too much temptation to call another library function.\n** this would be bad, because then that function would not be locked.\n*/\n#define\tFALSE\t\t0\n#define\tTRUE\t\t1\n\n/*\n** Define the different type of sound compression avaliable to the westwood\n** library.\n*/\ntypedef enum {\n\tSCOMP_NONE=0,\t\t\t// No compression -- raw data.\n\tSCOMP_WESTWOOD=1,\t\t// Special sliding window delta compression.\n\tSCOMP_SONARC=33,\t\t// Sonarc frame compression.\n\tSCOMP_SOS=99\t\t\t// SOS frame compression.\n} SCompressType;\n\n/*\n**\tThis is the safety overrun margin for the sonarc compressed\n** data frames.  This value should be equal the maximum 'order' times\n**\tthe maximum number of bytes per sample.  It should be evenly divisible\n**\tby 16 to aid paragraph alignment.\n*/\n#define\tSONARC_MARGIN\t\t\t\t32\n\n\n/*\n** Define the sample control structure which helps us to handle feeding\n** data to the sound interrupt.\n*/\n#pragma pack(1);\ntypedef struct {\n\t/*\n\t**\tThis flags whether this sample structure is active or not.\n\t*/\n\tunsigned Active:1;\n\n\t/*\n\t**\tThis flags whether the sample is loading or has been started.\n\t*/\n\tunsigned Loading:1;\n\n\t/*\n\t**\tThis semaphore ensures that simultaneous update of this structure won't\n\t**\toccur.  This is necessary since both interrupt and regular code can modify\n\t**\tthis structure.\n\t*/\n\tunsigned DontTouch:1;\n\n\t/*\n\t**\tIf this sample is really to be considered a score rather than\n\t**\ta sound effect, then special rules apply.  These largely fall into\n\t**\tthe area of volume control.\n\t*/\n\tunsigned IsScore:1;\n\n\t/*\n\t**\tThis is the original sample pointer. It is used to control the sample based on\n\t**\tpointer rather than handle. The handle method is necessary when more than one\n\t**\tsample could be playing simultaneously. The pointer method is necessary when\n\t**\tthe dealing with a sample that may have stopped behind the programmer's back and\n\t**\tthis occurance is not otherwise determinable.  It is also used in\n\t** conjunction with original size to unlock a sample which has been DPMI\n\t** locked.\n\t*/\n\tvoid const *Original;\n\tlong OriginalSize;\n\n\t/*\n\t**\tThese are pointers to the double buffers in low ram.\n\t*/\n\tVOID *Buffer[2];\n\n\t/*\n\t**\tThe number of bytes in the buffer that has been filled but is not\n\t**\tyet playing.  This value is normally the size of the buffer,\n\t**\texcept for the case of the last bit of the sample.\n\t*/\n\tLONG DataLength;\n\n\t/*\n\t**\tThis is the buffer index for the low buffer that\n\t**\thas been filled with data but not yet being\n\t**\tplayed.\n\t*/\n\tWORD Index;\n\n\t/*\n\t**\tPointer to the sound data that has not yet been copied\n\t**\tto the playback buffers.\n\t*/\n\tVOID *Source;\n\n\t/*\n\t**\tThis is the number of bytes remaining in the source data as\n\t**\tpointed to by the \"Source\" element.\n\t*/\n\tLONG Remainder;\n\n\t/*\n\t**\tSamples maintain a priority which is used to determine\n\t**\twhich sounds live or die when the maximum number of\n\t**\tsounds are being played.\n\t*/\n\tWORD Priority;\n\n\t/*\n\t**\tThis is the handle as returned by sosDIGIStartSample function.\n\t*/\n\tWORD Handle;\n\n\t/*\n\t**\tThis is the current volume of the sample as it is being played.\n\t*/\n\tWORD Volume;\n\tWORD Reducer;\t\t// Amount to reduce volume per tick.\n\n\t/*\n\t**\tThis flags whether the sample is in stereo.\n\t*/\n\tWORD Stereo;\n\n\t/*\n\t**\tThis is the compression that the sound data is using.\n\t*/\n\tSCompressType Compression;\n\tWORD TrailerLen;\t\t\t\t\t\t// Number of trailer bytes in buffer.\n\tBYTE Trailer[SONARC_MARGIN];\t\t// Maximum number of 'order' samples needed.\n\n\n\tDWORD Pitch;\n\tWORD Flags;\n\n\t/*\n\t**\tThis flag indicates whether this sample needs servicing.  \n\t**\tServicing entails filling one of the empty low buffers.\n\t*/\n\tWORD Service;\n\n\t/*\n\t**\tThis flag is TRUE when the sample has stopped playing,\n\t**\tBUT there is more data available.  The sample must be\n\t**\trestarted upon filling the low buffer.\n\t*/\n\tBOOL Restart;\n\n\t/*\n\t**\tStreaming control handlers.\n\t*/\n\tBOOL (*Callback)(WORD id, WORD *odd, VOID **buffer, LONG *size);\n\tVOID\t*QueueBuffer;\t// Pointer to continued sample data.\n\tLONG\tQueueSize;\t\t// Size of queue buffer attached.\n\tWORD\tOdd;\t\t\t\t// Block number tracker (0..StreamBufferCount-1).\n\tint\tFilePending;\t// Number of buffers already filled ahead.\n\tlong\tFilePendingSize;\t// Number of bytes in last filled buffer.\n\n\t/*\n\t**\tThe file variables are used when streaming directly off of the \n\t**\thard drive.\n\t*/\n\tWORD\tFileHandle;\t\t// Streaming file handle (ERROR = not in use).\n\tVOID\t*FileBuffer;\t// Temporary streaming buffer (allowed to be freed).\n\t/*\n\t** The following structure is used if the sample if compressed using\n\t** the sos 16 bit compression Codec.\n\t*/\n\t_SOS_COMPRESS_INFO sosinfo;\n\n} SampleTrackerType;\n\n\ntypedef struct LockedData {\n\tunsigned int \t\tDigiHandle; \t\t\t// = -1;\n\tBOOL \t\t\t\t\tServiceSomething;\t\t// = FALSE;\n\tlong \t\t\t\t\tMagicNumber; \t\t\t// = 0xDEAF;\n\tVOID \t\t\t\t\t*UncompBuffer;\t\t\t// = NULL;\n\tlong \t\t\t\t\tStreamBufferSize; \t// = (2*SFX_MINI_STAGE_BUFFER_SIZE)+128;\n\tshort \t\t\t\tStreamBufferCount; \t// = 32;\n\tSampleTrackerType SampleTracker[MAX_SFX];\n\tunsigned int\t\tSoundVolume;\n\tunsigned int\t\tScoreVolume;\n\tBOOL\t\t\t\t\t_int;\n\tint\t\t\t\t\tMaxSamples;\t\t\t\t\n\tint\t\t\t\t\tRate;\t\t\t\t\n} LockedDataType;\n\nextern LockedDataType LockedData;\n#pragma pack(4);\n\nvoid Init_Locked_Data(void);\nvoid Unlock_Locked_Data(void);\nlong Simple_Copy(void ** source, long * ssize, void ** alternate, long * altsize, void **dest, long size);\nlong Sample_Copy(SampleTrackerType *st, void ** source, long * ssize, void ** alternate, long * altsize, void * dest, long size, SCompressType scomp, void * trailer, WORD *trailersize);\nVOID far cdecl maintenance_callback(VOID);\nVOID cdecl far DigiCallback(unsigned int driverhandle, unsigned int callsource, unsigned int sampleid);\nvoid far HMI_TimerCallback(void);\nvoid *Audio_Add_Long_To_Pointer(void const *ptr, long size);\nvoid\tDPMI_Unlock(VOID const *ptr, long const size);\nextern \"C\" {\n\tvoid\tAudio_Mem_Set(void const *ptr, unsigned char value, long size);\n\tvoid\tMem_Copy(void const *source, void *dest, unsigned long bytes_to_copy);\n\tlong  Decompress_Frame(void * source, void * dest, long size);\n\tint\tDecompress_Frame_Lock(void);\n\tint\tDecompress_Frame_Unlock(void);\n\tint\tsosCODEC_Lock(void);\n\tint\tsosCODEC_Unlock(void);\n\tvoid\t__GETDS(void);\n}\t\t\n\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/STAMP.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; This is the control structure at the start of a loaded icon set.  It must match\n; the structure in ICONSET.C!\n\tSTRUC\tIControl_Type\nWidth\t\tDW\t?\t; Width in pixels (per icon).\nHeight\t\tDW\t?\t; Height in pixels (per icon).\nCount\t\tDW\t?\t; Number of icons in this set.\nAllocated\tDW\t?\t; Was this iconset allocated?\nMapWidth\tDW\t?\t; Width of icon map (in icons).\nMapHeight\tDW\t?\t; Height of icon map (in icons).\nSize\t\tDD\t?\t; Size of entire iconset memory block.\nIcons\t\tDD\t?\t; Offset from buffer start to icon data.\nPalettes\tDD\t?\t; Offset from buffer start to palette data.\nRemaps\t\tDD\t?\t; Offset from buffer start to remap index data.\nTransFlag\tDD\t?\t; Offset for transparency flag data.\nColorMap\tDD\t?\t; Color control map offset.\nMap\t\tDD\t?\t; Icon map offset.\n\tENDS\n\nICON256\tEQU\t1\n\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/SVGAPRIM.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : SVGAPRIM.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : December 8, 1994                         *\n;*                                                                         *\n;*                  Last Update : December 8, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n\n; Externs from VIDEO.CPP module of the VIDEO library\nGLOBAL BankTable\t\t\t:DWORD\nGLOBAL VesaFunc\t\t\t:DWORD\nGLOBAL XRes\t\t\t\t\t:DWORD\nGLOBAL YRes\t\t\t\t\t:DWORD\nGLOBAL CurrentMode\t\t:DWORD\nglobal cpu_video_page\t:dword\nglobal cpu_page_limit   :dword\n\n\n; Externs from VESA.ASM module of the SVGAPRIM library\nGLOBAL Vesa_Asm_Set_Win\t\t:NEAR\nGLOBAL Vesa_Asm_Next_Win\t\t:NEAR\n\n; Externs from VGETPIX.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Get_Pixel          \t:NEAR\n\n; Externs from VPUTTPIX.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Put_Pixel \t\t:NEAR\n\n\n; Externs from VCLEAR.ASM module of the MCGA/SVGAPRIM library\nGLOBAL Vesa_Clear\t\t\t:NEAR\n\n; Externs from VBITBLIT.ASM module of the MCGA/SVGAPRIM library\nGLOBAL Linear_Blit_To_Vesa\t\t:NEAR\nGLOBAL Vesa_Blit_To_Linear\t\t:NEAR\nGLOBAL Vesa_Blit_To_Vesa\t\t:NEAR\n\n; Externs from VTOBUFF.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_To_Buffer\t\t:NEAR\n\n; Externs from VTOPAGE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Buffer_To_Page\t\t:NEAR\n\n; Externs from VSCALE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Linear_Scale_To_Vesa \t\t:NEAR\nGLOBAL Vesa_Scale_To_Linear\t\t:NEAR\nGLOBAL Vesa_Scale_To_Vesa \t\t:NEAR\n\n\n; Externs from VSCALE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Print\t \t\t:NEAR\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/TILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the TILE Library                 *\n *                                                                         *\n *                    File Name : TILE.H                                   *\n *                                                                         *\n *                   Programmer : Barry W. Green                           *\n *                                                                         *\n *                   Start Date : February 2, 1995                         *\n *                                                                         *\n *                  Last Update : February 2, 1995 [BWG]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TILE_H\n#define TILE_H\n\n/*=========================================================================*/\n/* The following prototypes are for the file: ICONSET.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid * Load_Icon_Set(char const *filename, void *iconsetptr, long buffsize);\nvoid Free_Icon_Set(void const *iconset);\nlong Get_Icon_Set_Size(void const *iconset);\nint Get_Icon_Set_Width(void const *iconset);\nint Get_Icon_Set_Height(void const *iconset);\nvoid * Get_Icon_Set_Icondata(void const *iconset);\nvoid * Get_Icon_Set_Trans(void const *iconset);\nvoid * Get_Icon_Set_Remapdata(void const *iconset);\nvoid * Get_Icon_Set_Palettedata(void const *iconset);\nint Get_Icon_Set_Count(void const *iconset);\nvoid * Get_Icon_Set_Map(void const *iconset);\n\n#endif //TILE_H\n\n\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/TIMER.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Timer Class Functions                    *\n *                                                                         *\n *                    File Name : TIMER.H                                  *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : July 6, 1994                             *\n *                                                                         *\n *                  Last Update : July 12, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TIMER_H\n#define TIMER_H\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TIMERA.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// Externs /////////////////////////////////////////////\nextern BOOL TimerSystemOn;\n\n\n/*=========================================================================*/\ntypedef enum BaseTimerEnum {\n\tBT_SYSTEM,\t\t\t// System timer (60 / second).\n\tBT_USER\t\t\t\t// User controllable timer (? / second).\n} BaseTimerEnum;\n\nclass TimerClass {\n \tpublic:\n\t\t// Constructor.  Timers set before low level init has been done will not\n\t\t// be able to be 'Started' or 'on' until timer system is in place.\t\n\t\tTimerClass(BaseTimerEnum timer=BT_SYSTEM, BOOL start=FALSE);\n\n\t\t// No destructor.\n\t\t~TimerClass(void){}\n\n\t\t// \n\t\tlong Set(long value, BOOL start=TRUE);\t// Set initial timer value.\n\t\tlong Stop(void);\t\t\t\t// Pause timer.\n\t\tlong Start(void);\t\t\t\t// Resume timer.\n\t\tlong Reset(BOOL start=TRUE);\t// Reset timer to zero.\n\t\tlong Time(void);\t\t\t\t// Fetch current timer value.\n\n\tprotected:\n\t\tlong Started;\t\t\t\t\t// Time last started (0 == not paused).\n\t\tlong Accumulated;\t\t\t\t//\tTotal accumulated ticks.\n\n\tprivate:\n\t\tlong (*Get_Ticks)(void);\t// System timer fetch.\n};\n\n\ninline long TimerClass::Reset(BOOL start)\n{\n\treturn(Set(0, start));\n}\n\n\nclass CountDownTimerClass : private TimerClass {\n\tpublic:\n\t\t// Constructor.  Timers set before low level init has been done will not\n\t\t// be able to be 'Started' or 'on' until timer system is in place.\t\n\t\tCountDownTimerClass(BaseTimerEnum timer, long set, int on=FALSE);\n\t\tCountDownTimerClass(BaseTimerEnum timer=BT_SYSTEM, int on=FALSE);\n\n\t\t// No destructor.\n\t\t~CountDownTimerClass(void){}\n\n\t\t// Public functions\n\t\tlong Set(long set, BOOL start=TRUE);\t// Set count down value.\n\t\tlong Reset(BOOL start=TRUE);\t// Reset timer to zero.\n\t\tlong Stop(void);\t\t\t// Pause timer.\n\t\tlong Start(void);\t\t\t// Resume timer.\n\t\tlong Time(void);\t\t\t// Fetch current count down value.\n\n\tprotected:\n\t\tlong DelayTime;\t\t\t// Ticks remaining before countdown timer expires.\n};\n\ninline long CountDownTimerClass::Stop(void)\n{\n\tTimerClass::Stop();\n\treturn(Time());\n}\n\ninline long CountDownTimerClass::Start(void)\n{\n\tTimerClass::Start();\n\treturn(Time());\n}\n\ninline long CountDownTimerClass::Reset(BOOL start)\n{\n\treturn (TimerClass::Reset(start));\n}\n\n\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// externs  //////////////////////////////////////////\n\n//extern TimerClass\t\t\t\t\tTickCount;\nextern CountDownTimerClass\t\tCountDown;\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// Prototypes //////////////////////////////////////////\n\nextern \"C\" {\n\tlong Get_System_Tick_Count(void);\n\tlong Get_User_Tick_Count(void);\n\tvoid far Timer_Interrupt_Func(void);\n//\tlong Get_Num_Interrupts(unsigned int realmode);\n\tvoid Disable_Timer_Interrupt(void);\n\tvoid Enable_Timer_Interrupt(void);\n}\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TIMER.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nBOOL Init_Timer_System(unsigned int freq, int partial = FALSE);\nBOOL Remove_Timer_System(VOID);\n\n\n#endif // TIMER_H\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/TIMER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Timer Class Functions                    *\n *                                                                         *\n *                    File Name : TIMER.H                                  *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : July 6, 1994                             *\n *                                                                         *\n *                  Last Update : July 12, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TIMER_H\n#define TIMER_H\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TIMERA.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// Externs /////////////////////////////////////////////\nextern BOOL TimerSystemOn;\n\n\n/*=========================================================================*/\ntypedef enum BaseTimerEnum {\n\tBT_SYSTEM,\t\t\t// System timer (60 / second).\n\tBT_USER\t\t\t\t// User controllable timer (? / second).\n} BaseTimerEnum;\n\nclass TimerClass {\n \tpublic:\n\t\t// Constructor.  Timers set before low level init has been done will not\n\t\t// be able to be 'Started' or 'on' until timer system is in place.\n\t\tTimerClass(BaseTimerEnum timer=BT_SYSTEM, BOOL start=FALSE);\n\n\t\t// No destructor.\n\t\t~TimerClass(void){}\n\n\t\t//\n\t\tlong Set(long value, BOOL start=TRUE);\t// Set initial timer value.\n\t\tlong Stop(void);\t\t\t\t// Pause timer.\n\t\tlong Start(void);\t\t\t\t// Resume timer.\n\t\tlong Reset(BOOL start=TRUE);\t// Reset timer to zero.\n\t\tlong Time(void);\t\t\t\t// Fetch current timer value.\n\n\tprotected:\n\t\tlong Started;\t\t\t\t\t// Time last started (0 == not paused).\n\t\tlong Accumulated;\t\t\t\t//\tTotal accumulated ticks.\n\n\tprivate:\n\t\tlong (*Get_Ticks)(void);\t// System timer fetch.\n};\n\n\ninline long TimerClass::Reset(BOOL start)\n{\n\treturn(Set(0, start));\n}\n\n\n//lint -esym(1509,TimerClass)\nclass CountDownTimerClass : private TimerClass {\n\tpublic:\n\t\t// Constructor.  Timers set before low level init has been done will not\n\t\t// be able to be 'Started' or 'on' until timer system is in place.\n\t\tCountDownTimerClass(BaseTimerEnum timer, long set, int on=FALSE);\n\t\tCountDownTimerClass(BaseTimerEnum timer=BT_SYSTEM, int on=FALSE);\n\n\t\t// No destructor.\n\t\t~CountDownTimerClass(void){}\n\n\t\t// Public functions\n\t\tlong Set(long set, BOOL start=TRUE);\t// Set count down value.\n\t\tlong Reset(BOOL start=TRUE);\t// Reset timer to zero.\n\t\tlong Stop(void);\t\t\t// Pause timer.\n\t\tlong Start(void);\t\t\t// Resume timer.\n\t\tlong Time(void);\t\t\t// Fetch current count down value.\n\n\tprotected:\n\t\tlong DelayTime;\t\t\t// Ticks remaining before countdown timer expires.\n};\n\ninline long CountDownTimerClass::Stop(void)\n{\n\tTimerClass::Stop();\n\treturn(Time());\n}\n\ninline long CountDownTimerClass::Start(void)\n{\n\tTimerClass::Start();\n\treturn(Time());\n}\n\ninline long CountDownTimerClass::Reset(BOOL start)\n{\n\treturn (TimerClass::Reset(start));\n}\n\n\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// externs  //////////////////////////////////////////\n\n//extern TimerClass\t\t\t\t\tTickCount;\nextern CountDownTimerClass\t\tCountDown;\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// Prototypes //////////////////////////////////////////\n\nextern \"C\" {\n\tlong Get_System_Tick_Count(void);\n\tlong Get_User_Tick_Count(void);\n\tvoid far Timer_Interrupt_Func(void);\n//\tlong Get_Num_Interrupts(unsigned int realmode);\n\tvoid Disable_Timer_Interrupt(void);\n\tvoid Enable_Timer_Interrupt(void);\n}\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TIMER.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nBOOL Init_Timer_System(unsigned int freq, int partial = FALSE);\nBOOL Remove_Timer_System(VOID);\n\n\n#endif // TIMER_H\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/VBUFFER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : VBUFFER.H                                *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : January 6, 1995                          *\n *                                                                         *\n *                  Last Update : January 17, 1995   [PWG]                 *\n *                                                                         *\n *\tThis module contains the definition for the video buffer class.  The\t\t*\n * primary functionality of the video buffer class is handled by inline\t\t*\n * functions that make a call through function pointers to the correct\t\t*\n * routine.  This has two benefits:\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t1) C++ name mangling is not a big deal since the function pointers\t*\n *\t\t   point to functions in standard C format.\t\t\t\t\t\t\t\t\t*\n *\t\t2) The function pointers can be changed when we set a different\t\t*\n *       graphic mode.  This allows us to have both supervga and mcga\t\t*\n *\t\t\troutines present in memory at once.\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * In the basic library, these functions point to stub routines which just\t*\n * return.  This makes a product that just uses a graphic buffer take the\t*\n * minimum amount of code space.  For programs that require MCGA or VESA\t*\n * support, all that is necessary to do is link either the MCGA or VESA\t\t*\n * specific libraries in, previous to WWLIB32.  The linker will then \t\t*\n * overide the the necessary stub functions automatically.\t\t\t\t\t\t*\n * \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This header files gives the definition for all VideoViewPort and \t\t\t*\n * VideoBuffer functions.  These functions mirror some of the basic\t\t\t*\n * functionality of the GraphicViewPort and GraphicBuffer classes.\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Terminology:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Video ViewPort - The Video ViewPort holds all of the functions which\t\t* \n *\t\tcan be used on a Video Buffer.  The video viewport but cannot be \t\t*\n *\t\tattached to a Graphic Buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n *\tVideo Buffer - A refers to a physical object which has been mapped to\t* \n *\t\tram, like a graphic card.  The SeenPage is a good example of a Video\t* \n *\t\tBuffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n\n * Below is a tree which shows the relationship of the GraphicBuffer and \t*\n * Buffer classes to the VideoBuffer class:\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t  BUFFER.H\t\t\t\t GBUFFER.H\t\t\t  BUFFER.H\t\t\t\t VBUFFER.H\t*\n *  ----------          ----------         ----------          ----------\t*\n * |  Buffer  |        | Graphic  |       |  Buffer  |        |  Video   |\t*\n * |  Class   |        | ViewPort |       |  Class   |        | ViewPort |\t*\n *  ----------          ----------         ----------          ----------\t*\n *            \\        /                             \\        /\t\t\t\t*\n *             \\      /                               \\      /\t\t\t\t\t*\n *            ----------                             ----------\t\t\t\t*\n *           |  Graphic |                           |  Video   |\t\t\t\t*\n *           |  Buffer  |                           |  Buffer  |\t\t\t\t*\n *            ----------                             ---------- \t\t\t\t*\n *\t  \t\t\t  GBUFFER.H\t\t\t                       VBUFFER.H\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   VVPC::Get_Selector -- Get selector for virtual viewport instance\t\t*\n *   VVPC::Get_Offset -- Get offset for virtual view port class instance   *\n *   VVPC::Get_Height -- Gets the height of a virtual viewport instance    *\n *   VVPC::Get_Width -- Get the width of a virtual viewport instance\t\t\t*\n *   VVPC::Get_XAdd -- Get the X add offset for virtual viewport instance  *\n *   VVPC::Get_XPos -- Get the x pos of the VP on the Video                *\n *   VVPC::Get_YPos -- Get the y pos of the VP on the video                *\n *   VVPC::Get_Grasphic_Buffer -- Get the graphic buffer of the VP.        *\n *   VVPC::Put_Pixel -- stub to call curr graphic mode Put_Pixel\t\t\t\t*\n *   VVPC::Get_Pixel -- stub to call curr graphic mode Get_Pixel\t\t\t\t*\n *   VVPC::Clear -- stub to call curr graphic mode Clear        \t\t\t\t*\n *   VVPC::To_Buffer -- stub func 1 to call curr graphic mode To_Buffer\t\t*\n *   VVPC::To_Buffer -- stub func 2 to call curr graphic mode To_Buffer\t\t*\n *   VVPC::To_Buffer -- stub func 3 to call curr graphic mode To_Buffer\t\t*\n *   VVPC::Blit -- stub 1 to call curr graphic mode Blit to GVPC\t\t\t\t*\n *   VVPC::Blit -- stub 2 to call curr graphic mode Blit\tto GVPC\t\t\t\t*\n *   VVPC::Blit -- stub 3 to call curr graphic mode Blit\tto GVPC\t\t\t\t*\n *   VVPC::Blit -- stub 1 to call curr graphic mode Blit\tto VVPC\t\t\t\t*\n *   VVPC::Blit -- stub 2 to call curr graphic mode Blit\tto VVPC\t\t\t\t*\n *   VVPC::Blit -- stub 3 to call curr graphic mode Blit\tto VVPC\t\t\t\t*\n *   VVPC::Scale -- stub 1 to call curr graphic mode Scale to GVPC\t\t\t*\n *   VVPC::Scale -- stub 2 to call curr graphic mode Scale to GVPC\t\t\t*\n *   VVPC::Scale -- stub 3  to call curr graphic mode Scale\tto GVPC\t\t\t*\n *   VVPC::Scale -- stub 4 to call curr graphic mode Scale to GVPC\t\t\t*\n *   VVPC::Scale -- stub 1 to call curr graphic mode Scale to VVPC\t\t\t*\n *   VVPC::Scale -- stub 2 to call curr graphic mode Scale to VVPC\t\t\t*\n *   VVPC::Scale -- stub 3  to call curr graphic mode Scale\tto VVPC\t\t\t*\n *   VVPC::Scale -- stub 4 to call curr graphic mode Scale to VVPC\t\t\t*\n *   BC::To_Page -- Copys buffer class to page with definable w, h \t\t\t*\n *   BC::To_Page -- Copys buffer class to page with definable w, h \t\t\t*\n *   BC::To_Page -- Copys buffer class to page with definable x, y, w, h \t*\n *   Buffer_To_Page -- Generic 'c' callable form of Buffer_To_Page         *\n *   GVPC::Blit -- stub 1 to call curr graphic mode Blit to VVPC\t\t\t\t*\n *   GVPC::Blit -- stub 2 to call curr graphic mode Blit to VVPC\t\t\t\t*\n *   GVPC::Blit -- stub 3 to call curr graphic mode Blit to VVPC\t\t\t\t*\n *   GVPC::SCALE -- stub 1 to call curr graphic mode Scale to VVPC\t\t\t*\n *   GVPC::SCALE -- stub 2 to call curr graphic mode Scale to VVPC\t\t\t*\n *   GVPC::SCALE -- stub 3 to call curr graphic mode Scale to VVPC\t\t\t*\n *   GVPC::SCALE -- stub 4 to call curr graphic mode Scale to VVPC\t\t\t*\n *   VVPC::Print -- Stub function to print string on a Video View Port     *\n *   VVPC::Print -- Stub function to print an int on a Graphic Viewport Class*\n *   VVPC::Print -- Stub function to print long on a graphic viewport class*\n *   VVPC::Print -- Stub function to print a short on a Video Viewport     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef VBUFFER_H\n#define VBUFFER_H\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n\n/*=========================================================================*/\n/* The video buffer class is dependant on a buffer class so we need to\t\t*/\n/*\t\tinclude the definitions for that as well.\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#ifndef BUFFER_H\n#include \"buffer.h\"\n#endif\n\n/*=========================================================================*/\n/* The video buffer class is dependant on a buffer class so we need to\t\t*/\n/*\t\tinclude the definitions for that as well.\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#ifndef GBUFFER_H\n#include \"gbuffer.h\"\n#endif\n\n/*=========================================================================*/\n/* Define external assembly funcs which deals with buffers and viewports.\t*/\n/*=========================================================================*/\nlong Buffer_To_Page(int x, int y, int w, int h, void *Buffer, VideoViewPortClass &view);\n\n/*=========================================================================*/\n/* Define the screen width and height to make portability to other modules\t*/\n/*\t\teasier.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tDEFAULT_SCREEN_WIDTH\t\t320\n#define\tDEFAULT_SCREEN_HEIGHT\t200\n\n/*=========================================================================*/\n/* Define functions which have not under-gone name mangling\t\t\t\t\t\t*/\n/*=========================================================================*/\n#ifdef __cplusplus\nextern \"C\" {\n\textern UWORD Get_MCGA_Selector(VOID);\n}\n#endif\n\n/*=========================================================================*/\n/* Let the compiler know that a VideoBufferClass exists so that it can\t\t*/\n/*\t\tkeep a pointer to it in a VideoViewPortClass.\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nclass VideoBufferClass;\n\n\n/*=========================================================================*/\n/* VideoViewPortClass - Holds viewport information which has been attached\t*/\n/*\t\tto a VideoBuffer.  A viewport is effectively a\trectangular subset   */\n/*    of the full buffer which is used for clipping and the like.\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tint \t\tSelector\t-\t\tis the selector to view port buffer\t\t\t*/\n/*\t\t\tchar\t  \t*Buffer\t-\t\tis the offset to view port buffer\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis the width of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis the height of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis add value to go from the end of a line\t*/\n/*\t\t\t\t\t\t\t\t\t\t\tto the beginning of the next line\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\tx offset into its associated VideoBuffer\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\ty offset into its associated VideoBuffer\t*/\n/*=========================================================================*/\nclass VideoViewPortClass {\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVideoViewPortClass(VideoBufferClass* graphic_buff, int x, int y, int w, int h);\n\t\tVideoViewPortClass();\n\t\t~VideoViewPortClass();\n\t\t/*===================================================================*/\n\t\t/* Define functions to get at the private data members\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\tGet_Offset(void);\n\t\tint\tGet_Height(void);\n\t\tint\tGet_Width(void);\n\t\tint\tGet_XAdd(void);\n\t\tint\tGet_XPos(void);\n\t\tint\tGet_YPos(void);\n\t\tVideoBufferClass *Get_Video_Buffer(void);\n\n\t\t/*===================================================================*/\n\t\t/* Define a function which allows us to change a video viewport on\t*/\n\t\t/*\t\tthe fly.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBOOL Change(int x, int y, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the set of graphic functions that are members of a Video   */\n\t\t/*\t\tViewPort class.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tvoid\tPut_Pixel(int x, int y, unsigned char color);\n\t\tint\tGet_Pixel(int x, int y);\n\t\tvoid\tClear(unsigned char color = 0);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, void *buff, long size);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, BufferClass *buff);\n\t\tlong\tTo_Buffer(BufferClass *buff);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, char *remap);\n\t\tunsigned long  Print(char const *string, int x, int y, int fcolor, int bcolor);\n\t\tunsigned long\tPrint(int num, int x, int y, int fcol, int bcol);\n\t\tunsigned long\tPrint(short num, int x, int y, int fcol, int bcol);\n\t\tunsigned long\tPrint(long num, int x, int y, int fcol, int bcol);\n\n\tprotected:\n\t\t/*===================================================================*/\n\t\t/* Define functions to attach the viewport to a graphicbuffer\t\t\t*/\n\t\t/*===================================================================*/\n\t\tvoid Attach(VideoBufferClass *video_buff, int x, int y, int w, int h);\n\t\tvoid Attach(VideoBufferClass *video_buff, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the data used by a GraphicViewPortClass\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\t\t\t\t\t\tOffset;\t\t\t\t\t// offset to graphic page\n\t\tint\t\t\t\t\t\tWidth;\t\t\t\t\t// width of graphic page\n\t\tint\t\t\t\t\t\tHeight;\t\t\t\t\t// height of graphic page\n\t\tint\t\t\t\t\t\tXAdd;\t\t\t\t\t\t// xadd for graphic page (0)\n\t\tint\t\t\t\t\t\tXPos;\t\t\t\t\t\t// x offset in relation to graphicbuff\n\t\tint\t\t\t\t\t\tYPos;\t\t\t\t\t\t// y offset in relation to graphicbuff\n\t\tVideoBufferClass\t   *VideoBuff;\t\t\t\t// related graphic buff\n};\n\n\n/*=========================================================================*/\n/* VideoBufferClass - A VideoBuffer refers to an actual instance of a\t\t*/\n/*\t\tphyscial device which has been mapped to a memory address like a \t\t*/\n/*\t\tvideo card.  The VideoBuffer can be drawn to directly because it\t\t*/\n/*\t\tinherits a Video ViewPort which represent its full size.\t\t\t\t\t*/\n/*\t\tsize.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tSelector\t-\t\tis now the selector to graphic buffer\t\t*/\n/*\t\t\tchar\t  \t*Buffer\t-\t\tis now the offset to graphic buffer\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis now the width of graphic buffer\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis now the height of graphic buffer\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis now the xadd of graphic buffer\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\twill be 0 because it is graphicbuff\t\t\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\twill be 0 because it is graphicbuff\t\t\t*/\n/*=========================================================================*/\nclass VideoBufferClass: public VideoViewPortClass {\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVideoBufferClass(unsigned short selector, long offset, int w, int h);\n\t\tVideoBufferClass(int w = DEFAULT_SCREEN_WIDTH, int h = DEFAULT_SCREEN_HEIGHT);\n\t\t~VideoBufferClass();\n};\n\n/***************************************************************************\n * VVPC::GET_OFFSET -- Get offset for virtual view port class instance     *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long the offset for the virtual viewport instance           *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long VideoViewPortClass::Get_Offset(void)\n{\n\treturn(Offset);\n}\n\n/***************************************************************************\n * VVPC::GET_HEIGHT -- Gets the height of a virtual viewport instance      *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     int the height of the virtual viewport instance             *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int VideoViewPortClass::Get_Height(void)\n{\n\treturn(Height);\n}\n\n/***************************************************************************\n * VVPC::GET_WIDTH -- Get the width of a virtual viewport instance\t\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     int the width of the virtual viewport instance              *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int VideoViewPortClass::Get_Width(void)\n{\n\treturn(Width);\n}\n\n\n/***************************************************************************\n * VVPC::GET_XADD -- Get the X add offset for virtual viewport instance    *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     int the xadd for a virtual viewport instance                *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int VideoViewPortClass::Get_XAdd(void)\n{\t\n\treturn(XAdd);\n}\n/***************************************************************************\n * VVPC::GET_XPOS -- Get the x pos of the VP on the Video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     int the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n;*   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int VideoViewPortClass::Get_XPos(void)\n{\n\treturn(XPos);\n}\n\n\n/***************************************************************************\n * VVPC::GET_YPOS -- Get the y pos of the VP on the video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     int the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n;*   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int VideoViewPortClass::Get_YPos(void)\n{\n\treturn(YPos);\n}\n\n/***************************************************************************\n * VVPC::GET_GRAPHIC_BUFFER -- Get the graphic buffer of the VP.           *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline VideoBufferClass *VideoViewPortClass::Get_Video_Buffer(void)\n{\n \treturn (VideoBuff);\n}\n\n/***************************************************************************\n * VVPC::PUT_PIXEL -- stub to call curr graphic mode Put_Pixel\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tVideoViewPortClass::Put_Pixel(int x, int y, unsigned char color)\n{\n\tVVPC_Put_Pixel_Func(this, x, y, color);\n}\n\n/***************************************************************************\n * VVPC::GET_PIXEL -- stub to call curr graphic mode Get_Pixel          \t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline int\tVideoViewPortClass::Get_Pixel(int x, int y)\n{\n\treturn(VVPC_Get_Pixel_Func(this, x, y));\n}\n\n/***************************************************************************\n * VVPC::CLEAR -- stub to call curr graphic mode Clear\t                  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tVideoViewPortClass::Clear(unsigned char color)\n{\n\tVVPC_Clear_Func(this, color);\n}\n\n/***************************************************************************\n * VVPC::TO_BUFFER -- stub 1 to call curr graphic mode To_Buffer\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tVideoViewPortClass::To_Buffer(int x, int y, int w, int h, void *buff, long size)\n{\n\treturn(VVPC_To_Buffer_Func(this, x, y, w, h, buff, size));\n}\n\n/***************************************************************************\n * VVPC::TO_BUFFER -- stub 2 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tVideoViewPortClass::To_Buffer(int x, int y, int w, int h, BufferClass *buff)\n{\n\treturn(VVPC_To_Buffer_Func(this, x, y, w, h, buff->Get_Buffer(), buff->Get_Size()));\n}\n\n/***************************************************************************\n * VVPC::TO_BUFFER -- stub 3 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tVideoViewPortClass::To_Buffer(BufferClass *buff)\n{\n\treturn(VVPC_To_Buffer_Func(this, 0, 0, Width, Height, buff->Get_Buffer(), buff->Get_Size()));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- stub 1 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans)\n{\n\treturn(VVPC_Blit_to_GVPC_Func(this, &dest, x_pixel, y_pixel, dx_pixel, dy_pixel, pixel_width, pixel_height, trans));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- Stub 2 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans)\n{\n\treturn(VVPC_Blit_to_GVPC_Func(this, &dest, 0, 0, dx, dy, Width, Height, trans));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- stub 3 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tGraphicViewPortClass& dest, BOOL trans)\n{\n\treturn(VVPC_Blit_to_GVPC_Func(this, &dest, 0, 0, 0, 0, Width, Height, trans));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- stub 1 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tVideoViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans)\n{\n\treturn(VVPC_Blit_to_VVPC_Func(this, &dest, x_pixel, y_pixel, dx_pixel, dy_pixel, pixel_width, pixel_height, trans));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- stub 2 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tVideoViewPortClass& dest, int dx, int dy, BOOL trans)\n{\n\treturn(VVPC_Blit_to_VVPC_Func(this, &dest, 0, 0, dx, dy, Width, Height, trans));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- stub 3 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tVideoViewPortClass& dest, BOOL trans)\n{\n\treturn(VVPC_Blit_to_VVPC_Func(this, &dest, 0, 0, 0, 0, Width, Height, trans));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 1 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans, char *remap)\n{\n\treturn(VVPC_Scale_To_GVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, trans, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 2 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap)\n{\n\treturn(VVPC_Scale_To_GVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, FALSE, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 3 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tGraphicViewPortClass &dest, BOOL trans, char *remap)\n{\n\treturn(VVPC_Scale_To_GVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), trans, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 4 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tGraphicViewPortClass &dest, char *remap)\n{\n\treturn(VVPC_Scale_To_GVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), FALSE, remap));\n}\n/***************************************************************************\n * VVPC::SCALE -- stub 1 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans, char *remap)\n{\n\treturn(VVPC_Scale_To_VVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, trans, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 2 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap)\n{\n\treturn(VVPC_Scale_To_VVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, FALSE, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 3 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tVideoViewPortClass &dest, BOOL trans, char *remap)\n{\n\treturn(VVPC_Scale_To_VVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), trans, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 4 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tVideoViewPortClass &dest, char *remap)\n{\n\treturn(VVPC_Scale_To_VVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), FALSE, remap));\n}\n\n/***************************************************************************\n * VVPC::PRINT -- Stub function to print string on a Video View Port       *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tVideoViewPortClass::Print(char const *str, int x, int y, int fcol, int bcol)\n{\n\treturn(VVPC_Print_Func(this, str, x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * VVPC::PRINT -- Stub function to print an int on a Video Viewport\t\t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tVideoViewPortClass::Print(int num, int x, int y, int fcol, int bcol)\n{\n\tBYTE str[17];\n\n\treturn(VVPC_Print_Func(this, itoa(num, str, 10), x, y, fcol, bcol));\n}\n\n\n/***************************************************************************\n * VVPC::PRINT -- Stub function to print a short on a Video Viewport       *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tVideoViewPortClass::Print(short num, int x, int y, int fcol, int bcol)\n{\n\tBYTE str[17];\n\n\t\n\treturn(VVPC_Print_Func(this, itoa(num, str, 10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * VVPC::PRINT -- Stub function to print long on a Video Viewport\t\t\t\t*\n *                                                                         *\n * INPUT:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/17/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline unsigned long\tVideoViewPortClass::Print(long num, int x, int y, int fcol, int bcol)\n{\n\tBYTE str[33];\n\n\treturn(VVPC_Print_Func(this, ltoa(num, str, 10), x, y, fcol, bcol));\n}\n\n\n/*=========================================================================*/\n/*= The following BufferClass functions are defined here because they act =*/\n/*=\ton video viewports.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  =*/\n/*=========================================================================*/\n\n\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t*\n *\t\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t*\n *\t\t\t\t\tVIVC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int w, int h, VideoViewPortClass &view)\n{\n\treturn(VVPC_Buffer_To_Page(0, 0, w, h, Buffer, &view));\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tVIVC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport.  width and height are assumed to be the\t\t\t*\n *\t\t\t\t\t\tviewport's width and height.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(VideoViewPortClass &view)\n{\n\treturn(VVPC_Buffer_To_Page(0, 0, view.Get_Width(), view.Get_Height(), Buffer, &view));\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable x, y, w, h *\n *                                                                         *\n * INPUT:\tint\tx\t\t\t- x pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\ty\t\t\t- y pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t\t*\n *\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t\t*\n *\t\t\t\tVIVC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\tnone                                                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int x, int y, int w, int h, VideoViewPortClass &view)\n{\n\treturn(VVPC_Buffer_To_Page(x, y, w, h, Buffer, &view));\n}\n\n/***************************************************************************\n * BUFFER_TO_PAGE -- Generic 'c' callable form of Buffer_To_Page           *\n *                                                                         *\n * INPUT: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/12/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long Buffer_To_Page(int x, int y, int w, int h, void *Buffer, VideoViewPortClass &view)\n{\n\treturn(VVPC_Buffer_To_Page(x, y, w, h, Buffer, &view));\n}\n\n/*=========================================================================*/\n/* The following GraphicBufferClass functions are defined here because \t\t*/\n/* they act\ton graphic viewports.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n/***************************************************************************\n * GVPC::BLIT -- stub 1 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tVideoViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans)\n{\n\treturn(GVPC_Blit_to_VVPC_Func(this, &dest, x_pixel, y_pixel, dx_pixel, dy_pixel, pixel_width, pixel_height, trans));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 2 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tVideoViewPortClass& dest, int dx, int dy, BOOL trans)\n{\n\treturn(GVPC_Blit_to_VVPC_Func(this, &dest, 0, 0, dx, dy, Width, Height, trans));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 3 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tVideoViewPortClass& dest, BOOL trans)\n{\n\treturn(GVPC_Blit_to_VVPC_Func(this, &dest, 0, 0, 0, 0, Width, Height, trans));\n}\n/***************************************************************************\n * GVPC::SCALE -- stub 1 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans, char *remap)\n{\n\treturn(GVPC_Scale_To_VVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, trans, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 2 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap)\n{\n\treturn(GVPC_Scale_To_VVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, FALSE, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 3 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tVideoViewPortClass &dest, BOOL trans, char *remap)\n{\n\treturn(GVPC_Scale_To_VVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), trans, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 4 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tVideoViewPortClass &dest, char *remap)\n{\n\treturn(GVPC_Scale_To_VVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), FALSE, remap));\n}\n\n#endif // VBUFFER_H\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/VIDEO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : 32 bit library                           *\n *                                                                         *\n *                    File Name : VIDEO.H                                  *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef VIDEO_H\n#define VIDEO_H\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\t\t\t\t\t   \n/*=========================================================================*/\n/*\tThe machine can be in one of the following graphic modes.  The global\t*/\n/*\tGraphicMode is set to one of these values.\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tCGA_MODE\t\t\t\t\t4\t\t\t// DOS 320x200 4 color mode\n#define\tTGA_MODE\t\t\t\t\t9\t\t\t// TANDY 320x200 16 color mode\n#define\tEGA_MODE\t\t\t\t\t13\t\t\t// DOS 320x200 16 color mode\n#define\tMCGA_MODE\t\t\t\t0x13\t\t// DOS 320x200 256 color mode\n#define\tVGA_MODE\t\t\t\t\t0x13\t\t// DOS 320x200 256 color mode\n#define\tEEGA_MODE\t\t\t\t14\t\t\t// DOS 640x400 16 color mode\n#define\tETGA_MODE\t\t\t\t9\t\t\t// TANDY 640x400 16 color mode\n#define\tHGA_MODE\t\t\t\t\t7\t\t\t// DOS 768x400 2 color mode\n#define\tTXT_MODE\t\t\t\t\t3\t\t\t// DOS plain old color text mode\n#define\tVESA_640X400_256\t\t0x100\t\t// VESA 640x400 256 color mode\n#define\tVESA_640X480_256\t\t0x101\t\t// VESA 640x480 256 color mode\n#define\tVESA_800X600_256\t\t0x103\t\t// VESA 800x600 256 color mode\n#define\tVESA_1024X768_256\t\t0x105\t\t//\tVESA 1024x768 256 color mode\n#define\tVESA_1280X400_256\t\t0x107\t\t// VESA 1280x400 256 color mode\n#define\tVESA_TEXT_80X60\t\t0x108\t\t// VESA 80x60 text mode\n#define\tVESA_TEXT_132X25\t\t0x109\t\t// VESA 132x25 text mode\n#define\tVESA_TEXT_132X60\t\t0x10C\t\t// VESA 132x60 text mode\n#define\tRESET_MODE\t\t\t\t-1\n#define\tUNINITIALIZED_MODE\t-1\n#define\tVESA_MIN \t\t\t\tVESA_640X400_256\n#define\tVESA_MAX\t\t\t\t\tVESA_TEXT_132X60\n\n/*=========================================================================*/\n/* Define the maximum number of bank entries\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tMAX_BANK_ENTRIES\t\t((1280L*1024L)/65536L)\n\n\n/*=========================================================================*\n * VesaInfoType - General info about this VESA implementation\t\t\t\t\t*\n *                (Filled in by VESA BIOS Function 0)\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Signature    - Will always be 'VESA'\t\t\t\t\t\t\t\t\t\t\t\t*\n * Version      - Version #\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OEMString    - OEM ID string\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Capabilities - Not defined by VESA yet\t\t\t\t\t\t\t\t\t\t\t\t*\n * AvailModes   - List of available modes; terminated with -1 (0xffff)\t\t*\n * TotalMemory  - ???\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Reserved     - Pads structure to 256 bytes total\t\t\t\t\t\t\t\t*\n *=========================================================================*/\ntypedef struct {\n\tchar    Signature[4];\n\tshort   Version;\n\tREALPTR OEMString;\n\tlong    Capabilities;\n\tREALPTR AvailModes;\n\tshort   TotalMemory;\n\tchar    Reserved[236];\n} VesaInfoType;\n\n\n/*=========================================================================*\n * VesaModeInfoType - Info about this VESA mode\t\t\t\t\t\t\t\t\t\t*\n *                    (Filled in by VESA BIOS Function 1)\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Attributes       - bit 0: 1 = mode is supported\t\t\t\t\t\t\t\t\t*\n *                    bit 1: 1 = optional info available\t\t\t\t\t\t\t*\n *                    bit 2: 1 = std BIOS output funcs valid in this mode\t*\n *                    bit 3: 0 = monochrome, 1 = color\t\t\t\t\t\t\t*\n *                    bit 4: 0 = text mode, 1 = graphics\t\t\t\t\t\t\t*\n * WinA_Attributes  - bit 0 = win exists, bit 1=readable, bit 2= writable\t*\n * WinB_Attributes  - bit 0 = win exists, bit 1=readable, bit 2= writable\t*\n * WinGranularity   - smallest address boundary window can be placed upon;\t*\n *                    size is in KB (ie 64, 32, 4)\t\t\t\t\t\t\t\t\t*\n * WinSize          - size of windows in KB (ie 64, 32)\t\t\t\t\t\t\t*\n * WinA_Segment     - location of Window A in CPU space (usually 0xa000)\t*\n * WinB_Segment     - location of Window B in CPU space (usually 0xb000)\t*\n * WinFunc          - address of window-setting function (This is provided *\n *                    as an alternative to Int 10 for speed.)\t\t\t\t\t*\n * BytesPerScanline - # bytes per scan line\t\t\t\t\t\t\t\t\t\t\t*\n * \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Optional info (available if bit 1 of Attributes is set):\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * XRes             - X-resolution\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * YRes             - Y-resolution\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * XCharSize        - Horizontal size of char cell\t\t\t\t\t\t\t\t\t*\n * YCharSize        - Vertical size of char cell\t\t\t\t\t\t\t\t\t*\n * NumPlanes        - # of memory planes (???)\t\t\t\t\t\t\t\t\t\t*\n * BitsPerPixel     - # bites per pixel\t\t\t\t\t\t\t\t\t\t\t\t*\n * NumBanks         - # of banks (ie planes)\t\t\t\t\t\t\t\t\t\t\t*\n * MemoryModel      - 00h = Text mode\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                    01h = CGA mode\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                    02h = Hercules\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                    03h = 4 plane planar mode\t\t\t\t\t\t\t\t\t\t*\n *                    04h = packed pixel mode (1 byte/pixel)\t\t\t\t\t*\n *                    05h = non-chain 4, 256-color mode\t\t\t\t\t\t\t*\n *                    06-0Fh = \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                    10-FFh = OEM-specific\t\t\t\t\t\t\t\t\t\t\t*\n * BankSize         - Bank size in KB\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\ntypedef struct {\n\tshort   Attributes;\n\tchar    WinA_Attributes;\n\tchar    WinB_Attributes;\n\tshort   WinGranularity;\n\tshort   WinSize;\n\tshort   WinA_Segment;\n\tshort   WinB_Segment;\n\tREALPTR WinFunc;\n\tshort   BytesPerScanline;\n\tshort   XRes;\n\tshort   YRes;\n\tchar    XCharSize;\n\tchar    YCharSize;\n\tchar    NumPlanes;\n\tchar    BitsPerPixel;\n\tchar    NumBanks;\n\tchar    MemoryModel;\n\tchar    BankSize;\n\tchar    NumInputPages;\n\tchar    Reserved;\n\tchar    RedMaskSize;\n\tchar    RedFieldPosition;\n\tchar    GreenMaskSize;\n\tchar    GreenFieldPosition;\n\tchar    BlueMaskSize; \n\tchar    BlueFieldPosition;\n\tchar    RsvdMaskSize;\n\tchar    RsvdFieldPosition;\n\tchar    DirectColorModeInfo;\n\tchar    pad[216];\n} VesaModeInfoType;\n\n\nextern \"C\" {\nextern\tint\tGraphicMode;\nextern\tlong\tXRes;\nextern\tlong\tYRes;\n\nextern long\t\t BankTable [];\nextern REALPTR\t VesaFunc;\nextern unsigned long RMVesaVector ;\nextern unsigned long RMVesaRegs ;\n}\n\n/*=========================================================================*/\n/* The following prototypes are for the file: VIDEO.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern \"C\" int Set_Video_Mode(int mode);\nint Get_Video_Mode(void);\nvoid Update_Video_Mode (void) ;\nvoid Vesa_Info(void);\nvoid Vesa_Set_Window(long grain_num);\nint Get_Original_Video_Mode(void);\nvoid Set_Original_Video_Mode(int mode);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: INITDLAY.CPP\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\nextern VOID Init_Delay(VOID);\nextern BOOL VertBlank;\n\n/*=========================================================================*/\n/* The following prototypes are for the file: VERTBLNK.ASM\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\t\t\t\t \t\t\t\t   \nextern \"C\" {\n\textern WORD Get_Vert_Blank(VOID);\n\textern VOID Wait_Vert_Blank(BOOL blank);\n}\n\n/*=========================================================================*/\n\n#endif // VIDEO_H\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/WINDOW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the WINDOWS Library              *\n *                                                                         *\n *                    File Name : WINDOWS.H                                *\n *                                                                         *\n *                   Programmer : Barry W. Green                           *\n *                                                                         *\n *                   Start Date : February 16, 1995                        *\n *                                                                         *\n *                  Last Update : February 16, 1995 [BWG]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WINDOWSs_H\n#define WINDOWSs_H\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WINHIDE.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Window_Hide_Mouse(int window);\nvoid Window_Show_Mouse(void);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WINDOWS.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Standard_More_Prompt(char const *prompt, int space, int fcolor, int bcolor);\nvoid Set_More_Prompt(char const *prompt, int space, int fcolor, int bcolor);\nvoid Set_More_On(void);\nvoid Set_More_Off(void);\nint Change_Window(int windnum);\nint Change_New_Window(int windnum);\nvoid New_Window(void);\nvoid Window_Int_Print(int num);\nvoid Window_Print(char const string[], ...);\n\n/*\n**\tThe WindowList[][8] array contains the following elements.  Use these\n**\tdefines when accessing the WindowList.\n*/\ntypedef enum {\n\tWINDOWX,\t\t\t// X byte position of left edge.\n\tWINDOWY,\t\t\t// Y pixel position of top edge.\n\tWINDOWWIDTH,\t// Width in bytes of the window.\n\tWINDOWHEIGHT,\t// Height in pixels of the window.\n\tWINDOWFCOL,\t\t// Default foreground color.\n\tWINDOWBCOL,\t\t// Default background color.\n\tWINDOWCURSORX,\t// Current cursor X position (in rows).\n\tWINDOWCURSORY,\t// Current cursor Y position (in lines).\n\tWINDOWPADDING=0x1000\n} WindowIndexType;\n\nextern int WindowList[][8];\nextern int WindowColumns;\nextern int WindowLines;\nextern int WindowWidth;\nextern unsigned int WinB;\nextern unsigned int WinC;\nextern unsigned int WinX;\nextern unsigned int WinY;\nextern unsigned int WinCx;\nextern unsigned int WinCy;\nextern unsigned int WinH;\nextern unsigned int WinW;\nextern unsigned int Window;\n\nextern int MoreOn;\nextern char *TXT_MoreText;\n\nextern void (*Window_More_Ptr)(char const *, int, int, int);\n\n#endif //WINDOWS_H\n\n\u001a"
  },
  {
    "path": "WWFLAT32/INCLUDE/WSA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WSA 32bit LIbrary                        *\n *                                                                         *\n *                    File Name : WSA.H                                    *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : May 23, 1994                             *\n *                                                                         *\n *                  Last Update : May 25, 1994   [SKB]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Open_Animation -- file name and flags, system allocates buffer.       *\n *   Open_Animation -- file name, flags, palette, system allocates buffer. *\n *   Open_Animation -- file_name, graphic buffer, flags.                   *\n *   Open_Animation -- file name, bufferclass, flags, palette.             *\n *   Open_Animation -- filename, ptr, size, flags, no palette.             *\n *   Animate_Frame -- Animate a frame to a page with magic colors.         *\n *   Animate_Frame -- Animate a frame to a viewport with magic colors.     *\n *   Animate_Frame -- Animate a frame to a page.                           *\n *   Animate_Frame -- Animate a frame to a viewport.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WSA_H\n#define WSA_H\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n#ifndef GBUFFER_H\n#include \"gbuffer.h\"\n#endif\n\n#ifndef VBUFFER_H\n#include \"vbuffer.h\"\n#endif\n\n//lint -strong(AJX,WSAType)\ntypedef enum {\n\tWSA_NORMAL,\t\t\t\t\t\t\t\t// Normal WSA animation\n\tWSA_GHOST\t \t= 0x1000,\t\t\t// Or'd with the above flags to get ghosting\n\tWSA_PRIORITY2 \t= 0x2000,\t\t\t// Copy using a priority (or in the priority)\n\tWSA_TRANS    \t= 0x4000,\t\t\t// Copy frame, ignoring transparent colors\n\tWSA_PRIORITY \t= 0x8000\t\t\t\t// Copy using a priority (or in the priority)\n} WSAType;\n\n\n//lint -strong(AJX,WSAOpenType)\ntypedef enum {\n\tWSA_OPEN_FROM_MEM\t\t= 0x0000,\t// Try to load entire anim into memory.\n\tWSA_OPEN_INDIRECT\t\t= 0x0000,\t// First animate to internal buffer, then copy to page/viewport.\n\tWSA_OPEN_FROM_DISK\t= 0x0001,\t// Force the animation to be disk based.\t\n\tWSA_OPEN_DIRECT\t\t= 0x0002,\t// Animate directly to page or viewport.\n\n\t// These next two have been added for the 32 bit library to give a better idea of what is\n\t// happening.  You may want to animate directly to the destination or indirectly to the\n\t// destination by using the animations buffer.  Indirecly is best if the dest is a seenpage\n\t// and the animation is not linear or if the destination is modified between frames.\n\tWSA_OPEN_TO_PAGE  = WSA_OPEN_DIRECT ,\n\tWSA_OPEN_TO_BUFFER= WSA_OPEN_INDIRECT ,\n\n} WSAOpenType;\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WSA.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nVOID * cdecl Open_Animation(BYTE const *file_name, BYTE *user_buffer, LONG user_buffer_size, WSAOpenType user_flags, UBYTE *palette=NULL);\nVOID cdecl Close_Animation( VOID *handle );\nBOOL cdecl Animate_Frame(VOID *handle, GraphicViewPortClass& view,\n                         WORD frame_number, WORD x_pixel=0, WORD y_pixel=0,\n                         WSAType flags_and_prio = WSA_NORMAL, VOID *magic_cols=NULL, VOID *magic=NULL);\nWORD cdecl Get_Animation_Frame_Count(VOID *handle);\nBOOL cdecl Animate_Frame(VOID *handle, VideoViewPortClass& view,\n                         WORD frame_number, WORD x_pixel=0, WORD y_pixel=0,\n                         WSAType flags_and_prio = WSA_NORMAL, VOID *magic_cols=NULL, VOID *magic=NULL);\nWORD cdecl Get_Animation_Frame_Count(VOID *handle);\nWORD cdecl Get_Animation_X(VOID const *handle);\nWORD cdecl Get_Animation_Y(VOID const *handle);\nWORD cdecl Get_Animation_Width(VOID const *handle);\nWORD cdecl Get_Animation_Height(VOID const *handle);\nWORD cdecl Get_Animation_Palette(VOID const *handle);\nULONG cdecl Get_Animation_Size(VOID const *handle);\n\n\n/***************************************************************************\n * OPEN_ANIMATION -- file name, flags, palette, system allocates buffer.   *\n *                                                                         *\n *                                                                         *\n * INPUT:   BYTE *file_name - name of file to open.                        *\n *          WSAOpenType user_flags - flags on how to open.                 *\n *          UBYTE *palette - pointer to a palette buffer to fill.          *\n *                                                                         *\n * OUTPUT:  VOID *pointer to animation data.  Must be used for all \t\t\t*\n *               other WSA calls.                                          *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/24/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline VOID *cdecl Open_Animation(BYTE *file_name, WSAOpenType user_flags, UBYTE *palette=NULL) \n{\n\treturn (Open_Animation(file_name, NULL, 0L, user_flags,  palette));\n}\n\n\n/***************************************************************************\n * OPEN_ANIMATION -- file_name, bufferclass, flags. \t\t\t\t\t\t\t\t*\n *                                                                         *\n *                                                                         *\n * INPUT:   BYTE *file_name - name of file to open.                        *\n *          GraphicBufferClass - pointer to a buffer.                      *\n *          WSAOpenType user_flags - flags on how to open.                 *\n *          UBYTE *palette - pointer to a palette buffer to fill.          *\n *                                                                         *\n * OUTPUT:  VOID *pointer to animation data.  Must be used for all \t\t\t*\n *               other WSA calls.                                          *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/24/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline VOID *cdecl Open_Animation(BYTE *file_name, BufferClass& buffer, WSAOpenType user_flags,  UBYTE *palette=NULL) \n{\n\treturn (Open_Animation(file_name, (BYTE *)buffer.Get_Buffer(), buffer.Get_Size(), user_flags, palette));\n}\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LP_ASM.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n\nextern \"C\" {\nUWORD Apply_XOR_Delta(BYTE *source_ptr, BYTE *delta_ptr);\nVOID  Apply_XOR_Delta_To_Page_Or_Viewport(VOID *target, VOID *delta, WORD width, WORD nextrow, WORD copy);\n}\n\n\n\n#endif // WSA_H\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/WWLIB32.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 User include file                *\n *                                                                         *\n *                    File Name : WWLIB32.H                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWLIB32_H\n#define WWLIB32_H\n\n#include <wwstd.h>\n\n#include <audio.h>\n#include <buffer.h>\n#include <descmgmt.h>\n#include\t<dipthong.h>\n#include <file.h>\n#include <font.h>\n#include <gbuffer.h>\n#include <iff.h>\n#include <keyboard.h>\n#include <mcgaprim.h>\n#include <misc.h>\n#include <mono.h>\n#include <palette.h>\n#include <playcd.h>\n#include <shape.h>\n#include <tile.h>\n#include <timer.h>\n#include <video.h>\n#include <vbuffer.h>\n#include <window.h>\n#include <wsa.h>\n#include <wwmem.h>\n\n\n\n\n#endif // WWLIB32_H\n\u001a\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/WWMEM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory System                            *\n *                                                                         *\n *                    File Name : MEM.H                                    *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : April 4, 1994                            *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWMEM_H\n#define WWMEM_H\n\n#include \"wwstd.h\"\n#include \"new.h\"\n#include \"memflag.h\"\n\n// Defines\n//==============\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MEM.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint  Mem_Init(void *buffer, long size);\nvoid *Mem_Alloc(void *poolptr, long lsize, unsigned long id);\nint  Mem_Free(void *poolptr, void *buffer);\nvoid Mem_Reference(void *node);\nvoid Mem_Lock_Block(void *node);\nvoid Mem_In_Use(void *node);\nvoid *Mem_Find(void *poolptr, unsigned long id);\nunsigned long Mem_Get_ID(void *node);\nvoid *Mem_Find_Oldest(void *poolptr);\nvoid *Mem_Free_Oldest(void *poolptr);\nlong Mem_Pool_Size(void *poolptr);\nlong Mem_Avail(void *poolptr);\nlong Mem_Largest_Avail(void *poolptr);\nvoid Mem_Cleanup(void *poolptr);\n\n\n#endif\n\u001a\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/WWMEM.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Memory System                            *\n;*                                                                         *\n;*                    File Name : WWMEM.INC                                *\n;*                                                                         *\n;*                   Programmer : Ian M. Leslie                            *\n;*                                                                         *\n;*                   Start Date : August 11, 1994                          *\n;*                                                                         *\n;*                  Last Update : August 17, 1994   [IML]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nMEM_NORMAL EQU 0000h\t\t; Default memory (normal).\nMEM_NEW\t   EQU 0001h\t\t; Called by the operator new and was overloaded.\nMEM_CLEAR  EQU 0002h \t\t;\n\nGLOBAL\t\t@Alloc$qul14MemoryFlagType:PROC\nGLOBAL\t\t@Free$qpv:PROC\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/WWSTD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : wwstd.h                                  *\n *                                                                         *\n *                    File Name : WWLIB.H                                  *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : March 1, 1994                            *\n *                                                                         *\n *                  Last Update : March 1, 1994   []                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#define\tWWSTD_H\n\n\n// Note: SKB 4/11/94\n// Before this library is done, this needs to be able to be set to TRUE.\n// Once it is, the FALSE parts should be removed from the source code.\n#define LIB_EXTERNS_RESOLVED FALSE\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <dos.h>\n#include <bios.h>\n\n//================================\n\n// TRUE and FALSE are defined in pltypes.h\n\n#ifndef IBM\n#define IBM\t\t\t\tTRUE\n#endif\n\n#ifndef AMIGA\n#define AMIGA\t\t\tFALSE\n#endif\n\n#ifndef\tSEGA\n#define\tSEGA\t\t\tFALSE\n#endif\n\n/*\n**\tCommon constants used in normal code.\n*/\n#define WWERROR\t\t-1\n\n#ifdef NULL\n#undef\tNULL\n#endif\n\n#ifndef NULL\n#define NULL\t\t0L\n#endif\n\n#ifdef VOID\n#undef VOID\n#endif\n\n#define PRIVATE\t\tstatic\n#define PUBLIC\t\t\t/* Routines & data don't have a specifier */\n\n#ifdef __cplusplus\n#define\t__CPPARGS\t...\n#else\n#define\t__CPPARGS\n#endif\n\n// This macro will get the size (in elements) of the specified array.\n#ifdef GET_SIZE\n#undef GET_SIZE\n#endif\n#define GET_SIZE(a)\t\t\t\t\t((sizeof(a) / sizeof(*a)))\n\n// Returns the absolute value of the number.\n#ifdef ABS\n#undef ABS\n#endif\ntemplate<class T> T ABS(T a)\n{\n\treturn (a < 0) ? -a : a;\n}\ninline int ABS(int);\ninline long ABS(long);\n\n// Returns the minimum of the two numbers.\n#ifdef MIN\n#undef MIN\n#endif\ntemplate<class T> T MIN(T a, T b)\n{\n\treturn (b < a) ? b : a;\n};\ninline short MIN(short, short);\ninline int MIN(int, int);\ninline long MIN(long, long);\n\n// Returns the maximum of the two numbers.\n#ifdef MAX\n#undef MAX\n#endif\ntemplate<class T> T MAX(T a, T b)\n{\n\treturn (b > a) ? b : a;\n};\ninline short MAX(short, short);\ninline int MAX(int, int);\ninline long MAX(long, long);\n\n// Returns the low word of a long\n#define\tLOW_WORD(a)\t\t((unsigned short)((long)(a) & 0x0000FFFFL))\n\n// Returns the high word of a long\n#define\tHIGH_WORD(a)\t((unsigned long)(a) >> 16)\n\n// Merges to shorts to become a long\n#define\tMAKE_LONG(a,b) (((long)(a) << 16) | (long)((b)&0x0000FFFFL))\n\n/*\n** Macro allows our routines to act like\n** sprintf etc..\n*/\n#ifdef AssembleTo\n#undef AssembleTo\n#endif\n\n#define AssembleTo(dest,fmt)\\\n{\\\n\tva_list argptr;\\\n\tif (fmt != (dest))\\\n\t\t{\\\n\t\tva_start (argptr, fmt);\\\n\t\tvsprintf ((dest), fmt, argptr);\\\n\t\tva_end (argptr);\\\n\t\t}\\\n}\n\n// type definitions\n//=======================================\ntypedef void \tVOID;\n\n//==================================================\n// Pharlape defines these for use so we use their\n// typedefs!\n//\t\ttypedef\tunsigned char\tBOOL;\n//\t\ttypedef signed long\t\tLONG;\n//\t\ttypedef unsigned long\tULONG;\n//==================================================\n#ifndef PRIVATE\n#define  PRIVATE\tstatic\n#endif\n\n// The purpose of the INT and UINT is for efficiency.  It says that while a short int (16 bit)\n// has enough precision, it is more efficient to pass in an int (32 bits).  For efficiency, most\n// WORD and UWORD should be an INT or UINT, especially on the stack and structures that will\n// not be in large arrays.  When size efficiency is more important then speed, use WORD UWORD.\n\n#define\tVOID\t\tvoid\n\n#pragma\twarn -eas\n#define\tTRUE\t\t1\n#define\tFALSE\t\t0\n\n#define\tBOOL\t\tint\t\t\t\t\t// 32 bits for speed. use CHAR for size optimizations.\n\n#ifndef HMI_DRIVER\n#define\tINT\t\tint\n#define\tUINT\t\tunsigned int\n#define\tBYTE\t\tchar\n#define\tUBYTE\t\tunsigned char\n#define  UCHAR\t   unsigned char\n#define\tWORD\t\tsigned \tshort\n#define\tUWORD\t\tunsigned short\n#define  USHORT\tunsigned short\n\n#define\tLONG\t\tsigned \tlong\n#define\tULONG\t\tunsigned long\n#define  REALPTR\tunsigned long\n\n#define\tFARPTR  char far *\n\n#endif\n\n\n/*\n**\tThe type of processor running on this system as\n**\treturned by Processor().\n*/\n#define\tPROC_80386\t\t0\n#define\tPROC_80486\t\t1\n#define\tPROC_PENTIUM\t2\n\n\n// Inline Routines\n//\n//\n// These Template functions are generally used\n// by classes when they havce over loaded > and <.\n//\n#ifdef __cplusplus\ntemplate<class T> T Min(T a, T b)\n{\n\treturn (a<b ? a : b);\n}\n\ntemplate<class T> inline  T Max(T a, T b)\n{\n\treturn (a>b ? a : b);\n}\n\ntemplate<class T> T Abs(T a)\n{\n\treturn ((a<0) ? -(a) : a);\n}\n\ntemplate<class T> VOID minimize(T &a, T b)\n{\n\tif( b<a )\n\t\ta=b;\n}\n\ntemplate<class T> VOID maximize(T &a, T b)\n{\n\tif( b>a )\n\t\ta=b;\n}\n#endif\n\n/*\n**\tMacros that control bit settings in a variable.\n*/\n#define Bit_Flags_On(a,b)\t\t\t(a |= (b))\n#define Bit_Flags_Off(a,b)\t\t\t(a &= (~(b)))\n#define Bit_Flags_Value(a,b)\t\t(a & (b))\n#define Bit_Flags_Flip(a,b)\t\t(a ^= (b))\n\n// Template replacements for the user defines above\n#ifdef __cplusplus\ntemplate<class T> VOID BitFlagsOn(T &a, T b)\n{\n\ta |= (b);\n}\n\ntemplate<class T> VOID BitFlagsOff(T &a, T b)\n{\n\ta &= (~(b));\n}\n\ntemplate<class T> T BitFlagsValue(T a, T b)\n{\n\treturn (a & (b));\n}\n\ntemplate<class T> VOID BitFlagsFlip(T &a, T b)\n{\n\ta ^= (b);\n}\n#endif\n\ntypedef enum {\n\tTBLACK,\n\tPURPLE,\n\tCYAN,\n\tGREEN,\n\tLTGREEN,\n\tYELLOW,\n\tPINK,\n\tBROWN,\n\tRED,\n\tLTCYAN,\n\tLTBLUE,\n\tBLUE,\n\tBLACK,\n\tGREY,\n\tLTGREY,\n\tWHITE,\n\tCOLOR_PADDING=0x1000\n} ColorType;\n\n\n#endif\n\n\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/WWSTD.H.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : wwstd.h                                  *\n *                                                                         *\n *                    File Name : WWLIB.H                                  *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : March 1, 1994                            *\n *                                                                         *\n *                  Last Update : March 1, 1994   []                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#define\tWWSTD_H\n\n\n// Note: SKB 4/11/94\n// Before this library is done, this needs to be able to be set to TRUE.\n// Once it is, the FALSE parts should be removed from the source code.\n#define LIB_EXTERNS_RESOLVED FALSE\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <dos.h>\n#include <bios.h>\n\n//================================\n\n// TRUE and FALSE are defined in pltypes.h\n\n#ifndef IBM\n#define IBM\t\t\t\tTRUE\n#endif\n\n#ifndef AMIGA\n#define AMIGA\t\t\tFALSE\n#endif\n\n#ifndef\tSEGA\n#define\tSEGA\t\t\tFALSE\n#endif\n\n/*\n**\tCommon constants used in normal code.\n*/\n#define ERROR\t\t-1\n\n#ifdef NULL\n#undef\tNULL\n#endif\n\n#ifndef NULL\n#define NULL\t\t0L\n#endif\n\n#ifdef VOID\n#undef VOID\n#endif\n\n#define PRIVATE\t\tstatic\n#define PUBLIC\t\t\t/* Routines & data don't have a specifier */\n\n#ifdef __cplusplus\n#define\t__CPPARGS\t...\n#else\n#define\t__CPPARGS\n#endif\n\n// This macro will get the size (in elements) of the specified array.\n#ifdef GET_SIZE\n#undef GET_SIZE\n#endif\n#define GET_SIZE(a)\t\t\t\t\t((sizeof(a) / sizeof(*a)))\n\n// Returns the absolute value of the number.\n#ifdef ABS\n#undef ABS\n#endif\ntemplate<class T> T ABS(T a)\n{\n\treturn (a < 0) ? -a : a;\n}\ninline int ABS(int);\ninline long ABS(long);\n\n// Returns the minimum of the two numbers.\n#ifdef MIN\n#undef MIN\n#endif\ntemplate<class T> T MIN(T a, T b)\n{\n\treturn (b < a) ? b : a;\n};\ninline short MIN(short, short);\ninline int MIN(int, int);\ninline long MIN(long, long);\n\n// Returns the maximum of the two numbers.\n#ifdef MAX\n#undef MAX\n#endif\ntemplate<class T> T MAX(T a, T b)\n{\n\treturn (b > a) ? b : a;\n};\ninline short MAX(short, short);\ninline int MAX(int, int);\ninline long MAX(long, long);\n\n// Returns the low word of a long\n#define\tLOW_WORD(a)\t\t((unsigned short)((long)(a) & 0x0000FFFFL))\n\n// Returns the high word of a long\n#define\tHIGH_WORD(a)\t((unsigned long)(a) >> 16)\n\n// Merges to shorts to become a long\n#define\tMAKE_LONG(a,b) (((long)(a) << 16) | (long)((b)&0x0000FFFFL))\n\n/*\n** Macro allows our routines to act like\n** sprintf etc..\n*/\n#ifdef AssembleTo\n#undef AssembleTo\n#endif\n\n#define AssembleTo(dest,fmt)\\\n{\\\n\tva_list argptr;\\\n\tif (fmt != (dest))\\\n\t\t{\\\n\t\tva_start (argptr, fmt);\\\n\t\tvsprintf ((dest), fmt, argptr);\\\n\t\tva_end (argptr);\\\n\t\t}\\\n}\n\n// type definitions\n//=======================================\ntypedef void \tVOID;\n\n//==================================================\n// Pharlape defines these for use so we use their\n// typedefs!\n//\t\ttypedef\tunsigned char\tBOOL;\n//\t\ttypedef signed long\t\tLONG;\n//\t\ttypedef unsigned long\tULONG;\n//==================================================\n#ifndef PRIVATE\n#define  PRIVATE\tstatic\n#endif\n\n// The purpose of the INT and UINT is for efficiency.  It says that while a short int (16 bit)\n// has enough precision, it is more efficient to pass in an int (32 bits).  For efficiency, most\n// WORD and UWORD should be an INT or UINT, especially on the stack and structures that will\n// not be in large arrays.  When size efficiency is more important then speed, use WORD UWORD.\n\n#define\tVOID\t\tvoid\n\n#pragma\twarn -eas\n#define\tTRUE\t\t1\n#define\tFALSE\t\t0\n\n#define\tBOOL\t\tint\t\t\t\t\t// 32 bits for speed. use CHAR for size optimizations.\n\n#ifndef HMI_DRIVER\n#define\tINT\t\tint\n#define\tUINT\t\tunsigned int\n#define\tBYTE\t\tchar\n#define\tUBYTE\t\tunsigned char\n#define  UCHAR\t   unsigned char\n#define\tWORD\t\tsigned \tshort\n#define\tUWORD\t\tunsigned short\n#define  USHORT\tunsigned short\n\n#define\tLONG\t\tsigned \tlong\n#define\tULONG\t\tunsigned long\n#define  REALPTR\tunsigned long\n\n#define\tFARPTR  char far *\n\n#endif\n\n\n/*\n**\tThe type of processor running on this system as\n**\treturned by Processor().\n*/\n#define\tPROC_80386\t\t0\n#define\tPROC_80486\t\t1\n#define\tPROC_PENTIUM\t2\n\n\n// Inline Routines\n//\n//\n// These Template functions are generally used\n// by classes when they havce over loaded > and <.\n//\n#ifdef __cplusplus\ntemplate<class T> T Min(T a, T b)\n{\n\treturn (a<b ? a : b);\n}\n\ntemplate<class T> inline  T Max(T a, T b)\n{\n\treturn (a>b ? a : b);\n}\n\ntemplate<class T> T Abs(T a)\n{\n\treturn ((a<0) ? -(a) : a);\n}\n\ntemplate<class T> VOID minimize(T &a, T b)\n{\n\tif( b<a )\n\t\ta=b;\n}\n\ntemplate<class T> VOID maximize(T &a, T b)\n{\n\tif( b>a )\n\t\ta=b;\n}\n#endif\n\n/*\n**\tMacros that control bit settings in a variable.\n*/\n#define Bit_Flags_On(a,b)\t\t\t(a) |= (b)\n#define Bit_Flags_Off(a,b)\t\t\ta &= (~(b))\n#define Bit_Flags_Value(a,b)\t\t(a & (b))\n#define Bit_Flags_Flip(a,b)\t\ta ^= (b)\n\n// Template replacements for the user defines above\n#ifdef __cplusplus\ntemplate<class T> VOID BitFlagsOn(T &a, T b)\n{\n\ta |= (b);\n}\n\ntemplate<class T> VOID BitFlagsOff(T &a, T b)\n{\n\ta &= (~(b));\n}\n\ntemplate<class T> T BitFlagsValue(T a, T b)\n{\n\treturn (a & (b));\n}\n\ntemplate<class T> VOID BitFlagsFlip(T &a, T b)\n{\n\ta ^= (b);\n}\n#endif\n\ntypedef enum {\n\tTBLACK,\n\tPURPLE,\n\tCYAN,\n\tGREEN,\n\tLTGREEN,\n\tYELLOW,\n\tPINK,\n\tBROWN,\n\tRED,\n\tLTCYAN,\n\tLTBLUE,\n\tBLUE,\n\tBLACK,\n\tGREY,\n\tLTGREY,\n\tWHITE,\n\tCOLOR_PADDING=0x1000\n} ColorType;\n\n\n#endif\n\n\n"
  },
  {
    "path": "WWFLAT32/INCLUDE/_FILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library - Filio header stuff.            *\n;*                                                                         *\n;*                    File Name : FILE.H                                 \t*\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : September 13, 1993                       *\n;*                                                                         *\n;*                  Last Update : April 11, 1994\t\t\t\t\t\t\t\t\t*\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FILE_H\n#include \"file.h\"\n#endif\n\n#ifndef _FILE_H\n#define _FILE_H\n\n\n/*=========================================================================*/\n/* Fileio defines\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#define\tLIB_CDROM TRUE\n\n#define MODE_OLDFILE\t\t\t\t(O_RDONLY | O_BINARY)\n#define MODE_NEWFILE\t\t\t\t(O_WRONLY | O_BINARY | O_CREAT | O_TRUNC)\n#define MODE_READWRITE\t\t\t(O_RDWR   | O_BINARY)\n\n#define FILEOPENERROR\t\t\t-1\n#define FILEOPEN(f,m)\t\t\tibm_open(f, m, (((UWORD) m) == MODE_OLDFILE) ? S_IREAD : (S_IREAD | S_IWRITE))\n\n#define FILECLOSE(fd)\t\t\tibm_close(fd)\n#define FILEREAD(f,b,n)\t\t\tibm_read(f,b,(WORD)(n))\n#define FILEWRITE(f,b,n)\t\tibm_write(f,b,(WORD)(n))\n#define FILESEEK(f,b,n)\t\t\tibm_lseek(f, b, n)\n#define FILEDELETE(f)\t\t\tibm_unlink(f)\n#define CHANGEDIR(p)\t\t\t\tibm_chdir(p)\n\n#define FILENAMESIZE\t\t\t\t13\n#define IO_CHUNK_SIZE\t\t\t0xfff0UL\n\n/* \n**\tMaximum number of file handles \n*/\n#define TABLE_MAX\t\t\t20\n\n \n/*=========================================================================*/\n/* The file handle table */\n/*=========================================================================*/\ntypedef struct {\n\tBOOL\t\t\t\t\t\tEmpty;\t\t// Is this handle empty?\n\tWORD\t\t\t\t\t\tHandle;\t\t// DOS file handle (0 = resident).\n\tLONG\t\t\t\t\t\tPos;\t\t\t// Current file position.\n\tLONG\t\t\t\t\t\tStart;\t\t// Offset of file from pointer.\n\tWORD\t\t\t\t\t\tIndex;\t\t// FileData[] index.\n\tWORD\t\t\t\t\t\tMode;\t\t\t// Access mode (WW).\n\tBYTE\t\t\t\t\t\t*Name;\t\t// File name pointer.\n} FileHandleType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILEIO.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD ibm_getdisk(VOID);\nWORD ibm_setdisk(WORD drive);\nWORD ibm_close(WORD handle);\nWORD ibm_unlink(BYTE const *name);\nLONG ibm_lseek(WORD handle, LONG offset, WORD where);\nUWORD ibm_read(WORD handle, VOID *ptr, UWORD bytes);\nUWORD ibm_write(WORD handle, VOID *ptr, UWORD bytes);\nWORD ibm_open(BYTE const *name, UWORD mode, WORD attrib);\nWORD ibm_chdir(BYTE const *path);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FILELIB.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nWORD cdecl Do_Open_Error(FileErrorType errormsgnum, BYTE const *file_name);\nVOID cdecl Do_IO_Error(FileErrorType errormsgnum, BYTE const *filename);\nLONG cdecl Read_File_With_Recovery( WORD handle, VOID *buf, UWORD bytes );\nint cdecl Open_File_With_Recovery( BYTE const *file_name, unsigned int mode );\nBOOL cdecl Cache_File(WORD index, WORD file_handle);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DEVICES.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Get_Devices(VOID);\nextern WORD Is_Device_Real(WORD device);\n\n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DEVTABLE.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Init_Device_Table(BYTE *table);\nextern WORD Max_Device(VOID);\n\n\n#ifdef __cplusplus\n}\n#endif\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: HARDERR.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Install_Hard_Error_Handler(VOID);\nextern VOID Remove_Hard_Error_Handler(VOID);\n\n#ifdef __cplusplus\n}\n#endif\n\n\n/*=========================================================================*/\n/* Globale variables in the fileio system.\t\t\t\t\t\t               */\n/*=========================================================================*/\n\nextern BYTE CallingDOSInt;\t\t\t\t\t \nextern \"C\" extern BYTE MaxDevice,DefaultDrive;\nextern BYTE MultiDriveSearch;\t\nextern FileDataType *FileDataPtr;\nextern FileHandleType FileHandleTable[TABLE_MAX];\nextern UWORD NumFiles;\t\t\t\t\t\t\t \t// Number of files, except PAK, in file table.\nextern UWORD NumPAKFiles;\t\t\t\t\t\t\t// Number of PAK files in filetable.\nextern VOID *FileCacheHeap;\t\t\t\t\t\t// Pointer to the cache in memory.\nextern WORD DiskNumber;\t\t\t\t\t\t \nextern WORD MaxDirNum;\n\n\n/*=========================================================================*/\n\t \n\n\n#endif // _FILE_H\n\n\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/KEYBOARD.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : KEYBOARD.ASM                             *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 15, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Get_RM_Timer_Address -- Return address of real mode code for copy.    *\n;*   Get_RM_Keyboard_Size -- return size of real mode timer code.          *\n;*   Check_Key -- checks queue for key (make)                              *\n;*   Check_Key_Num -- Checks if key in queue, return key num               *\n;*   Get_Key_Num -- Returns the next key num in ax                         *\n;*   KN_To_KA -- Translates a key num to an ASCII key                      *\n;*   Low_Get_Key -- low level get key returns key num and bits             *\n;*   Convert_Num_To_ASCII -- Assembly routine converts keynum to ASCII key *\n;*   KeyNum_Translate -- Performs a lowlevel xlate to a keycode            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\n;*\tKeyboard driver -- 80386 Protected Mode Assembly portion\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   \n;***************************************************************************\n;\n; ----------------------------------------------------------------\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\n;WARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Make some general equates for easy compatability\n;---------------------------------------------------------------------------\nPROT_INT_ENABLE\tEQU\t1\t\t; if false protected int just calls real mode int\n\nDPMI_INTR\tEQU\t31h\t\nIRQ1INTNUM\tEQU\t09h\t\t; IRQ1 interrupt vector number.\nBRKINTNUM\tEQU\t23h\t\t; Crtl-C (Break) interrupt vector number\nDBGINTNUM\tEQU\t3h\t\t; Debug interrupt vector number\nDOS_SYS_CALL\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nLOCK_PAGES\tEQU\t5\t\t; Lock pages subfunction using DX_MEM_MGT\nUNLOCK_PAGES\tEQU\t6\t\t; Unlock pages subfunction using DX_MEM_MGT\nCLEARISR\tEQU\t020H\t; value to clear In Service Register\nINTCHIP0\tEQU\t020H\t; 8259 interrupt chip controller 0\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\n\tINCLUDE \"keyboard.inc\"\n\tINCLUDE \"keystruc.inc\"\n\tINCLUDE \"mcgaprim.inc\"\n\n\tGLOBAL\t RealModePtr:DWORD\n\n\tGLOBAL\t Install_Keyboard_Interrupt:NEAR\n\tGLOBAL\t Get_RM_Keyboard_Address:Near\n\tGLOBAL\t Get_RM_Keyboard_Size:Near\n\tGLOBAL\t Remove_Keyboard_Interrupt:NEAR\n\tGLOBAL\t Check_Key_Num:NEAR\n\tGLOBAL\t Get_Key_Num:NEAR\n\tGLOBAL\t KN_To_KA:NEAR\n\tGLOBAL\t KeyNum_Translate:NEAR\n\tGLOBAL\t Check_Key:NEAR\n\tGLOBAL\t Get_Key:NEAR\n\tGLOBAL\t Keyboard_Attributes_On:NEAR\n\tGLOBAL\t Clear_KeyBuffer:NEAR\n\tGLOBAL\t Key_Down:NEAR\n\tGLOBAL\t Keyboard_Attributes_Off:NEAR\n\tGLOBAL\t Check_Key_Bits:NEAR\n\tGLOBAL\t Get_Key_Bits:NEAR\n\tGLOBAL\t Key_Satisfied:NEAR\n\tGLOBAL\t Stuff_Key_WORD:NEAR\n\tGLOBAL\t Stuff_Key_Num:NEAR\n\tGLOBAL\t MouseQX:DWORD\n\tGLOBAL\t MouseQY:DWORD\n;DBG\n\tGLOBAL   Keyboard_Interrupt:NEAR\n\n\n\tDATASEG\n; For the current time we will just include the real mode stuff\n; into the protected mode code and then copy it down.  The C side of\n; this will handle this method or reading it off of disk in the real\n; method.\n\nLABEL \tRealBinStart\tBYTE\ninclude \"keyireal.ibn\"\nLABEL\tRealBinEnd\tBYTE\n\nLABEL\tLockedDataStart\tBYTE\t\nRMVector\tDD\t0\nRealModeSel\tDD\t0\nRealModePtr\tDD\t0\t\t; Pointer to real mode memory.\nRealModeSize\tDD\t0\t\t; Pointer to real mode memory.\n\nKeyboard_App_Stack_ESP\tDD 0\t\t; This the System Stack Offsset\nKeyboard_App_Stack_SS\tDD 0\t\t; This the System Stack Selector\nKeyboard_StackPointer\tDD 0DEADDEADh\t; We Create a Local Application\nKeyboard_Stack          DD 512 dup (0)\nKeyboard_StackStart\tDD 0\n\t\t\t\t\t; StackPointer \t\nLABEL\tLockedDataEnd\tBYTE\n\n\n\nAscii\tDB\t0,\"`1234567890-=\",0,8,9,\"qwertyuiop[]\\\",0,\"asdfghjkl;'\"\n\tDB\t0,13,0,45,\"zxcvbnm,./\",0,0,0,0,0,\" \"\n\nShift\tDB\t0,\"~!@#$%^&*()_+\",0,8,9,\"QWERTYUIOP{}|\",0,\"ASDFGHJKL:\",22H\n\tDB\t0,13,0,45,\"ZXCVBNM<>?\",0,0,0,0,0,\" \"\n\nAlpha_Lower\tDB\t0\n\tDB\t\"~!@#$%^&*()_+\",0,8,9,\"qwertyuiop{}|\",0,\"asdfghjkl:\",22H\n\tDB\t0,13,0,45,\"zxcvbnm<>?\",0,0,0,0,0,\" \"\n\nAlpha_Shift\tDB\t0\n\tDB\t\"`1234567890-=\",0,8,9,\"QWERTYUIOP[]\\\",0,\"ASDFGHJKL;'\"\n\tDB\t0,13,0,45,\"ZXCVBNM,./\",0,0,0,0,0,\" \"\n\nEdit\tDB\t0AEH,0ADH,000H,000H,0B5H,0B9H,0B1H,000H,0B8H,0B0H,0B7H,0AFH\n\tDB\t000H,000H,0B3H,000H,0B9H,0B5H,0B1H,000H, \"/\",0B8H,0B4H,0B0H\n\tDB\t0AEH, \"*\",0B7H,0B3H,0AFH,0ADH, \"-\", \"+\",000H,00DH,000H\n\nNumPad\tDB\t0,\"741\",0,\"/8520*963.-+\",0,13,0\n\n\nGetKeyLock\tDW\t0\t; snap shot of num and caps lock bits\nInitFlags\tDW\t0\nMouseQX\t\tDD\t0\nMouseQY\t\tDD\t0\n\n\tCODESEG\n;***************************************************************************\n;* GET_RM_TIMER_ADDRESS -- Return address of real mode code for copy.      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      VOID * to the address of the real mode timer               *\n;*                                                                         *\n;* PROTO:\tVOID\t*Get_RM_Keyboard_Address(VOID);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Address C Near\n\n\tmov\teax, OFFSET RealBinStart\n\tret\n\n\tENDP\n\n;***************************************************************************\n;* GET_RM_KEYBOARD_SIZE -- return size of real mode timer code.            *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      LONG size of the real mode timer code                      *\n;*                                                                         *\n;* PROTO:\tLONG\tGet_RM_Keyboard_Size(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Size C Near\n\n\tmov\teax, OFFSET RealBinEnd - OFFSET RealBinStart\n\tret\n\n\tENDP\n;***************************************************************************\n;* INSTALL_KEYBOARD_INTERRUPT -- Installs the keyboard interrupt           *\n;*                                                                         *\n;* INPUT:\tint rm_ptr  - ptr to the real mode handler\t\t   *\t   *\n;*\t\tint rm_size - size of the real mode handler\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Install_Keyboard_Interrupt(int rm_ptr, int rm_size);  *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tInstall_Keyboard_Interrupt C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\tARG\trm_ptr:DWORD\n\tARG\trm_size:DWORD\n\n\t; Are they attempting to set timer again?\n\tcmp\t[RealModePtr],0\n\tjnz\t??error\n\n\t; Make sure all flags are cleared.\n\tcmp\t[InitFlags],0\n\tjnz\t??error\n\n\n\t; Before setting the interrupt vectors, the code needs to be locked\n\t; for DPMI compatability.  Any code or data accessed must be lockded\n\t; so that no page faults accure during an interrupt.\n\t; First lock the code, then the data.  The stack will already be locked.\n\t; The real mode code is also already locked be default.\n\t; To lock a page set up registers :\n\t; AX = 0600h\n\t; BX:CX\t= starting linear address of memory block\n\t; SI:DI = size of region\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_CODE\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_DATA\n\n\t; now allocate real mode memory and copy the rm binary down to it.\n\tmov\teax,0100h\t; set function number\n\tmov\tebx,[rm_size]\t\t; get size of RM binary.\n\tmov\t[RealModeSize],ebx\n\tadd\tebx,15\t\t\t; round up \n\tshr\tebx,4\t\t\t; convert to pages.\n\tint\tDPMI_INTR\t \t; do call.\n\tjc\t??error\t\t \t; check for error.\n\tor\t[InitFlags],IF_ALLOC_RM ; set successful\n\tmov\t[RealModeSel],edx\n\tshl\teax,4\t\t\t; convert segment to offset.\n\tmov\t[RealModePtr],eax\t; save offset to global variable.\n\n\t; now lock the real mode memory that we allocated\n\tmov\teax,0600h\t\t; function number.\n\tmov\tecx,[RealModePtr]\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_RM_CODE\n\n\n\n\t; set up source and destination pointers for the copy.\n\tmov\teax,[RealModePtr];\t; set up our dest pointer\n\tmov\tesi,[rm_ptr]\t\t; Set up our source pointer.\n\tmov\tedi,eax\t\t\t; put it into esi for copy.\n\tmov\tecx,[rm_size]\n\trep\tmovsb\t\t\t; write RM bin to RM memory.\n\n\t; restore esi to point to data and initialize some of it.\n\tmov\tesi,[RealModePtr]\n\tmov\teax,esi\n\tshl\teax,12\t\t\t\t\t\t; make seg in high eax.\n\tmov\tax,[(KeyboardType PTR esi).CallKeyRMIntOffset]\t; create RM addr of call chain.\n\tmov\t[(KeyboardType PTR esi).CallKeyRMIntAddr],eax\t; save it for use in PM int.\n\nIF NOT PROT_INT_ENABLE\n       ; Chain the Real Keyboard interrupt to any avilable\n       ; Interrupt vector so We make sure that the Real Mode\n       ; Keyboard Interrupt service get called at debuging time\n       ; of the library.\n\n       mov\tedi , eax\n       mov\tbl , 060h\n       mov\tbh , 6\n       mov\teax , 200h\n ??find:\n       int\tDPMI_INTR\n       jc\t??error\n       or\tcx,dx\n       jz\t??found\n       inc\tbl\n       dec\tbh\n       jnz\t??find\n       jmp\t??error\n ??found:\n       movzx\tebx , bl\n       mov\t[ byte ptr RMVector ] , bl\n       mov\t[ 4 * ebx ] , edi\nENDIF\n\n\n\n\t;-------------------------------------------------------\n\t; Initialize all of the keyboard specific information\n\t;-------------------------------------------------------\n\txor\teax,eax\t\t\t; clear the high bits of eax\n\tmov\tal,[417H]\t\t; get keyboard status flags\n\ttest\teax,040H \t\t; caps lock active?\n\tje \tshort ??nocap\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\n\n??nocap:\n\ttest\teax,020H\t\t\t; num lock active?\n\tje\tshort ??nonumlock\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\n\n??nonumlock:\n\ttest\teax,002H\t\t\t; is left shift key down?\n\tje\tshort ??noleftshift\t\t; try the right\n\tor\t[(KeyboardType PTR esi+5).KeysUpDown],010H\n\n??noleftshift:\n\tand\teax,001H\t\t\t; get right shift bit\n\tshl\teax,9\t\t\t; put it into the proper position (shl al,1 mov ah,al)\n\tmov\tal,[418H]\t\t; get alt and ctrl bits\n\tshl\tal,2\t\t\t; put in proper position\n\tshl\tal,1\n\tand\tal,00CH\t\t\t; only alt and ctrl bits\n\tor\tah,al\t\t\t; put them ah for Keys+7 later\n\tmov\tal,[496H]\t\t; get extended keys\n\ttest\tal,008H\t\t\t; check for right alt key\n\tje\tshort ??noralt\n\tor\tah,040H\n??noralt:\n\tmov\t[(KeyboardType PTR esi+7).KeysUpDown],ah\n\ttest\tal,004H\t\t\t; test for right ctrl\n\tje \tshort ??norctrl\n\tor\t[(KeyboardType PTR esi+8).KeysUpDown],001h\n??norctrl:\n\ttest\tal,002H\t\t\t; last code E0?\n\tje short ??noe0\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],001h\n??noe0:\n\ttest\tal,001H\t\t\t; last code E1?\n\tje short ??noe1\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],002h\n??noe1:\n\t;==========================================================================\n\t; Get the protected mode interrupt vector keyboard.\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).KeyOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).KeyOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 2503, cl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).KeyOldRMI],ecx\n\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt Keyboard\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Keyboard_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt Keyboard\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).KeyCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the break interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\t\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).BrkOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).BrkOldPMISelector],ecx\t; save selector.\n\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector - for the break interrupt\n\t; input ax = 0200, bl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).BrkOldRMI],ecx\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Break_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).BrkCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\nIF DEBUG\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the Debug interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\t\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,DBGINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).DbgOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).DbgOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Debug_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\nENDIF\n\n\t; we have finished with success.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n??exit:\n\tret\n\tENDP\tInstall_Keyboard_Interrupt\n\n;***************************************************************************\n;* REMOVE_INTERRUPT -- Removes keyboard interrupt and restores chain\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Remove_Interrupt(VOID)                                *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tRemove_Keyboard_Interrupt C NEAR \n\tUSES\tebx,ecx,edx\n\n\t; verifie that the keyboard was previosly install\n\t; this is here in case of a page fault crash\n\tmov\tesi,[RealModePtr]\n\ttest    esi,esi\n\tjz      ??error\n\n\ttest\t[InitFlags],IF_SET_VECTORS\n\tjz\t??vectors_not_set\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tedx,[(KeyboardType esi).KeyOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[(KeyboardType esi).KeyOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).KeyOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\n\t; disengage Control Break Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tedx,[(KeyboardType esi).BrkOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[(KeyboardType esi).BrkOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).BrkOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\nIF DEBUG\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tecx,[(KeyboardType esi).DbgOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).DbgOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\nENDIF\n\nIF NOT PROT_INT_ENABLE\n       ; Clean up the Users interrupt table\n        mov\teax , 201h\n       mov\tbl , [ byte ptr RMVector ]\n       xor\tecx , ecx\n       xor\tedx , edx\n       int\tDPMI_INTR\n       jc\t??error\nENDIF\n\n\n??vectors_not_set:\n\t; now free up the real mode memory.\n\ttest\t[InitFlags],IF_LOCKED_RM_CODE\n\tjz\t??rm_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,[RealModePtr]\t\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t\t; edx will have size of region in bytes.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??rm_not_locked:\n\ttest\t[InitFlags],IF_ALLOC_RM\n\tjz\t??mem_not_allocated\n\tmov\teax , 0101h\n\tmov\tedx,[ RealModeSel ] \t\t; get physical address of real mode buffer.\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n??mem_not_allocated:\n\n\t; Now we can unlock all stuff needed for the interrupt.  \n\t; Unlock Code\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??code_not_locked:\n\n\t; Unlock data\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??data_not_locked:\n\n\t; we have finished with success.\n\tmov\t[RealModePtr],0\t\t; To say we can do it again sometime.\n\tmov\t[InitFlags],0\t\t; To say we can do it again sometime.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n\tret\n\tENDP\tRemove_Keyboard_Interrupt\n\n\n;***************************************************************************\n;* CHECK_KEY_NUM -- Checks if key in queue, return key num                 *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      Keynum of the key that was pressed, FALSE otherwise        *\n;*\n;* PROTO:\tINT Check_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Num C NEAR \n\tUSES\tebx,esi\n\tpushf\t\t\t\t\t; save off the flags\n\tcli\t\t\t\t\t; disable interrupts\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t\t\n\txor\teax,[(KeyboardType PTR esi).KeyBufferTail]\t\t\n\tor\teax,eax\t\t\t\t; check to see if head == tail\n\tjz\tshort ??fini\t\t\t; if so we are done\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t; get the head\n\tmov\tax,[(KeyboardType PTR esi+eax).KeyBuffer]\t; get key num\n\n??fini:\n\tsti\n\tpopf\n\tret\n\n\tENDP\tCheck_Key_Num\n\n;***************************************************************************\n;* GET_KEY_NUM -- Returns the next key num in ax                           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      WORD key flags are in the high byte of return word, key    *\n;*\t\t  num is in the low byte.\n;*                                                                         *\n;* PROTO:\tWORD Get_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Num C NEAR\n\tUSES\tesi,edi\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n??wait:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t\t; get the head\n\tcmp\teax,[(KeyboardType PTR esi).KeyBufferTail]\t\t; get the head\n\tjne\tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??wait\n\n??getkey:\n\tcall\tLow_Get_Key\n\tsti\t\t\t\t; enable interrupts\n\tret\n\n\tENDP\tGet_Key_Num\n\n;***************************************************************************\n;* KN_TO_KA -- Translates a key num to an ASCII key                        *\n;*                                                                         *\n;* INPUT:\tWORD the keynum to translate                               *\n;*                                                                         *\n;* OUTPUT:      WORD the ASCII key that is returned                        *\n;*                                                                         *\n;* PROTO:\tINT KN_To_KA(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tKN_To_KA C NEAR\n\tARG\tkeynum:DWORD\n\n\tmov\teax,[keynum]\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\tret\n\n\tENDP\tKN_To_KA\n\n\n;***************************************************************************\n;* LOW_GET_KEY -- low level get key returns key num and bits               *\n;*                                                                         *\n;* INPUT:\tAX - index into the buffer                                 *\n;*                                                                         *\n;* OUTPUT:      AX - key num with bits                                     *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tLow_Get_Key C NEAR \n\tUSES\tebx,esi,edi\n\n\tmov\tedi,eax\t\t\t\t; save off value in ax\n\n; We should set up both DS & ES because we are a low level function\n; and don't know who might have called us or what the registers\n; currently are.\n\n; No reason to set DS & ES.\n; This is not a hardware interrupt and if the funtion is being called\n; from within a hardware interrupt then DS and ES will be preset to\n; DGROUP _DATA\n\t\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tcmp\tal,KN_LMOUSE\n\tjb \tshort ??cont\n\tcmp\tal,KN_RMOUSE\n\tja \tshort ??chkjoy\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t; 128 word circular buffer\n\n\tmov\t[MouseQX],eax\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\t[MouseQY],eax\n\n\tpop\teax\t\t\t; restore keynum for return\n\n\tjmp\tshort ??cont\n\n??chkjoy:\n\tcmp\tal,KN_JBUTTON2\t\t; mouse button before joystick button\n\tja \tshort ??cont\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tpop\teax\t\t\t; restore keynum for return\n??cont:\n\tmov\t[(KeyboardType PTR esi).KeyBufferHead],edi\t; set the head\n\n??out:\n\tret\n\n\tENDP\tLow_Get_Key\n\n;***************************************************************************\n;* CONVERT_NUM_TO_ASCII -- Assembly routine converts keynum to ASCII key   *\n;*                                                                         *\n;* INPUT:\tEAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - holds the key num bits                        *\n;*\t\t\tAL - holds the key num value\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      EAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - hold the key bits                             *\n;*\t\t\tAL - holds the ASCII key value\t\t\t   *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* WARNINGS:    GetKeyLock must be set prior to calling this function\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tConvert_Num_To_ASCII C NEAR \n\tUSES\tebx,ecx,esi,edi\n\n\t;*===================================================================\n\t;* Force all breaks to be thrown out.\n\t;*===================================================================\n\ttest\teax,08000h\t\t; If it is a button number\n\tjne\tshort ??button\t\t;  don't process it\n\n\ttest\tah,KEYRELEASE\t\t; If it is not key release\n\tje\tshort ??ok\t\t;  then go process it\n\n??button:\n\txor\teax,eax\t\t\t; no ascii value for a button\n\tret\n\n??ok:\n\t;*===================================================================\n\t;* ES points to the DOSMEM selector, esi is the offset of the \n\t;*   protected mode structure.\n\t;*===================================================================\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\n\t;*===================================================================\n\t;* Start dealing with the keys.\t\t\t\t\t  \n\t;*===================================================================\n\tcmp\tal,110\t\t\t; is it esc\n\tje\t??esc\t\t\t; if so then deal with it\n\n;??chkext:\n\tcmp\tal,62\t\t\t; is it extended?\n\tjae\tshort ??extended\t; its extended so return ext code\n\n\tmov\tebx,eax\t\t\t; get an index\n\tand\tebx,03FH\t\t; only 0-63 allowed\n\ttest\tah,1\t\t\t; if not, test for shift\n\tjnz\tshort ??shifted\t\t; if shifted get shift value\n\n\t;*===================================================================\n\t;* Here when we have an unshifted ascii key\n\t;*===================================================================\n\tmov\tal,[Ascii+ebx]\t\t; get the ascii code for this number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_lowered:\n\tmov\tal,[Alpha_Lower+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_shifted:\n\tmov\tal,[Alpha_Shift+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* Shift'ed character\n\t;*===================================================================\n??shifted:\n\tmov\tal,[Shift+ebx] \t\t; get ascii shift code for number\n\n??ctrlkey:\n\ttest\tah,2\t\t\t; is it ctrl?\n\tjz \tshort ??jexit\t\t; izf not skip ctrl check\n\n\tmov\tedi,ebx\t\t\t; get index\n\tand\tedi,7\t\t\t; only bits 0-7\n\n\tmov\tcl,[(KeyboardType PTR esi+edi).Bits]\n\n\tshr\tebx,3\t\t\t; div by 8 for byte offset\n\ttest\t[(KeyboardType PTR esi+ebx).KeysCapsLock],cl\t\n\tje \tshort ??jexit\n\tand\tal,01FH\t\t\t; force to ctrl value\n\n??jexit:\n\tjmp short ??exit\n\n??extended:\n\tcmp\tal,75\t\t\t; if less than insert\n\tjb \tshort ??special\n\tcmp\tal,110\t\t\t; if >= esc\n\tjae \tshort ??funckey\n\n??editkeys:\n\txor\tebx,ebx\n\tmov\tbl,al\n\tsub\tebx,75\t\t\t; get value from 0-34\n\ttest\t[(KeyboardType PTR esi).KeyFlags],NONUMLOCK\n\tjne \tshort ??no_numpad\n\ttest\t[GetKeyLock],NUMLOCK\t; look at the snap shot of bits\n\tjne \tshort ??numpad\n\ttest\tah,SHIFTPRESS\n\tjne \tshort ??numpad\n\n??no_numpad:\n\tmov\tal,[Edit+ebx] \t\t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??numpad:\n\tsub\tebx,15\t\t\t; adjust to numpad entries\n\tmov\tal,[NumPad+ebx] \t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??funckey:\n\tcmp\tal,112\t\t\t; if less than function keys\n\tjb \tshort ??extout\n\tcmp\tal,121\t\t\t; if greater than function keys 1-10\n\tja \tshort ??extout\n\tmov\tbl,al\n\tsub\tbl,112\t\t\t; get value 0-9\n\tmov\tbh,0C5H\t\t\t; function key 1 no shift-ctrl-alt\n\ttest\tah,7\t\t\t; any shift-ctrl-alt\n\tje\tshort ??funcadj\n\tmov\tbh,098H\t\t\t; function key 1 alt\n\ttest\tah,ALTPRESS\t\t; (highest prescendence)\n\tjne \tshort ??funcadj\n\tmov\tbh,0A2H\t\t\t; function key 1 ctrl (next highest)\n\ttest\tah,CTRLPRESS\n\tjne\tshort ??funcadj\n\tmov\tbh,0ACH\t\t\t; function key 1 shift (lowest)\n\n??funcadj:\n\tsub\tbh,bl\t\t\t; adjust function key to a\n\tmov\tal,bh\t\t\t; shift/no shift etc\n\tjmp\tshort ??exit\n\n??special:\n\tcmp\tal,65\t\t\t; if less than specials\n\tjb\tshort ??extout\n\n\tadd\tal,133\t\t\t; make value between 198-207 or\n\tjmp\tshort ??exit\t\t; 0C6H-0CFH\n\t\n??extout:\n\tor\tal,080H\n\tjmp\tshort ??exit\n\n??esc:\n\tmov\tal,01BH\n\n??exit:\n\tret\n\tENDP\tConvert_Num_To_ASCII\n\n;***************************************************************************\n;* CHECK_KEY -- checks for ASCII keys sitting in the keybuffer             *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      INT the ASCII sequence for the key that was pressed        *\n;*                                                                         *\n;* PROTO:\tINT Check_Key(VOID);                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key C NEAR\n\tUSES\tebx,edi,esi\n\n\tpushf\n\tcld\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tcmp\tal,KN_LMOUSE\t\t; check if it is a mouse or joystick\n\tjb\tshort ??contget\n\tcmp\tal,KN_JBUTTON2\n\tja\tshort ??contget\n\tadd\tsi,4\t\t\t; get rid of the x and y values\n\n??contget:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\teax,eax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\tsti\t\t\t\t; enable interrupts\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tcall\tnear ptr Convert_Num_To_ASCII\n\t\t\t\t\t; AX has ASCII code with bits\n\n\txor\tah,ah\t\t\t; clear key bits\n??exit:\n\tpopf\n\tret\n\tENDP\tCheck_Key\n\n\n;***************************************************************************\n;* GET_KEY -- Gets the next available ASCII keystroke.\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      AH - hold the key bits                                     *\n;*\t\tAL - holds the ASCII key value\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tINT Get_Key(VOID);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key C NEAR \n\tUSES \tebx,ecx,edi\n\n\tcld\t\t\t\t; clear the direction flag for speed\n\n\t; Check_Key had to be copied because of enable and disable of ints\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\t\t\t\t\t; AX has key num code with bits\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\txor\tah,ah\n\tret\n\n\tENDP\tGet_Key\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_ON -- Sets the specified keyflags on                *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned on                 *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are on                       *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_On(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_On C NEAR\n\tUSES\tesi,edi\n\tARG\tbits:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tor\t[(KeyboardType PTR esi).KeyFlags],eax\n\n\t; Only do this if in playback or record mode.\n\ttest\teax,PASSBREAKS\n\tje\tshort ??fini\n\n\txor\teax,eax\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).KeysUpDown\n\tmov\t[edi],eax\n\tmov\t[edi+4],eax\n\tmov\t[edi+8],eax\n\tmov\t[edi+12],eax\n??fini:\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\n\tret\n\tENDP\tKeyboard_Attributes_On\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_OFF -- Sets the specified keyflags off              *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned off                *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are off                      *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_Off(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_Off C NEAR\n\tUSES\tesi\n\tARG\tbits:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tnot\teax\n\tand\t[(KeyboardType PTR esi).KeyFlags],eax\n\txor\teax,eax\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\n\tret \n\n\tENDP\tKeyboard_Attributes_Off\n;***************************************************************************\n;* CLEAR_KEYBUFFER -- Clears keystrokes out of the key buffer              *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Clear_KeyBuffer(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tClear_KeyBuffer C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tcli\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\tsti\n\n\tret\n\n\tENDP\tClear_KeyBuffer\n\n;***************************************************************************\n;* KEY_DOWN -- tests the status of a keyboard key                          *\n;*                                                                         *\n;* INPUT:\tINT the key num to check                                   *\n;*                                                                         *\n;* OUTPUT:      INT zero if the key is up, none zero if the key is down    *\n;*                                                                         *\n;* PROTO:\tINT Key_Down(INT key);\t\t\t\t   \t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Down C NEAR\n\tUSES\tebx,ecx,edi,esi\n\tARG\tkey:DWORD\n\n\tpush\t[key]\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\txor\tah,ah\t\t\t\t; Always ignore the control bits.\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tedi,eax\n\tshr\tedi,3\n\tmov\tcl,al\n\tand\tcl,0111b\n\tmov\tal,01b\n\tshl\tal,cl\n\tand\tal,[(KeyboardType PTR esi+edi).KeysUpDown]\n\tret\n\n\tENDP\tKey_Down\n\n;***************************************************************************\n;* CHECK_KEY_BITS -- checks ascii key in key buff with shift,ctrl,alt bits *\n;*                                                                         *\n;* INPUT:\tnone \t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set     *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Bits C NEAR\n\tUSES\tebx,ecx,edi,esi\n\n\tpushf\t\t\t\t\t; save off the direction flag\n\tcld\t\t\t\t\t; we will go forward\n\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n??playback:\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\t;------ If there is a NULL in the keyboard buffer, we must NOT treat it\n\t;\tas a valid ASCII value because the calling code will falsely\n\t;\tassume that the NULL return value indicates an empty buffer.\n\tor\tal,al\n\tje\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\tax,ax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tCheck_Key_Bits\n;***************************************************************************\n;* GET_KEY_BITS -- Gets ascii key in key buff with shift,ctrl,alt bits     *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set\t   *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Bits C NEAR \n\tUSES\tebx,ecx,edi\n\n\tcld\n\n\t; Check_Key_Bits was copied because of enable and disable of interrupts\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\tret\n\n\tENDP\tGet_Key_Bits\n\n;***************************************************************************\n;* KEY_SATISFIED -- checks to see if the given key is satisfied            *\n;*                                                                         *\n;* INPUT:   INT the key flags/number to check                          \t   *\n;*                                                                         *\n;* OUTPUT:  INT 0 if the key is not satisfied, !0 if the key is satisfied  *\n;*                                                                         *\n;* PROTO:   VOID Key_Satisfied(INT key);                                    *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Satisfied C NEAR\n\tUSES\tebx,ecx,esi,edi\n\tARG\tkey:DWORD\n\n\tmov\teax,[key]\n\tmov\tebx,eax\t\t\t; save key code\n\tpush\teax\n\tcall\tKey_Down\t\t; see it its even down\n\tadd\tesp,4\n\tcmp\teax,0\n\tje\t??out\t\t\t; if not it can't be satisfied\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,ebx\t\t\t; if so, restore code\n\txor\tah,ah\t\t\t; clear out flags area\n\tmov\tedi,eax\t\t\t; set as an index\n\tshr\tedi,3\t\t\t; div by 8 for bytes\n\tmov\tch,1h\t\t\t; set a bit for mask\n\tmov\tcl,al\t\t\t; get the code number\n\tand\tcl,7\t\t\t; get the actual bit this code is\n\tshl\tch,cl\t\t\t; move bit into mask position\n\n; now test the ctrl,alt and shift bits\n\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],04h\t; is the left ctrl down?\n\tjne \tshort ??ctrlon\t\t; if so, ctrl is on\n\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],01h\t; is the right ctrl down?\n\tje \tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n??ctrlon:\n\tor\tah,02h\t\t\t; or on the ctrl bit in flags\n??ctrloff:\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],50h\t; is either alt key down?\n\tje \tshort ??altoff\n\tor\tah,04h\t\t\t; or on the alt bit in flags\n??altoff:\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],10h\t; is the left shift down?\n\tjne \tshort ??shifton\t\t; if so the sift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],02h\t; is the right shift down?\n\tje \tshort ??shiftoff\t\t; if not then neither shift is down\n??shifton:\n\tor\tah,01h\t\t\t; or on the shift bit in flags\n??shiftoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje \tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje \tshort ??capsoff\t\t; its not effected\n\txor\tah,1h\t\t\t; toggle the shift flag\n??capsoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t\t; is the num lock key on?\n\tje \tshort ??numlockoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje \tshort ??numlockoff\t\t; if not effected skip toggle\n\txor\tah,1h\t\t\t; toggle the shift flag if effected\n\n??numlockoff:\n\tmov\tal,0ffh\t\t\t; set to match by default\n\tcmp\tah,bh\t\t\t; if flags match return !0\n\tje \tshort ??out\t\t\t; just exit\n\txor\teax,eax\t\t\t; otherwise, clear all bits FALSE\n\n??out:\n\tor\teax,eax\n\tret\n\n\tENDP\tKey_Satisfied\n\n\n;***************************************************************************\n;* Interrupt routines start here - Interrupts must be within the Locked \n;*   code area for DPMI compatability.\n;***************************************************************************\n\n\n\n\nLABEL \tLockedCodeStart\tBYTE\n\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Performs a lowlevel xlate to a keycode              *\n;*                                                                         *\n;* INPUT:\tWORD the code that needs to be translated                  *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated code                                   *\n;*                                                                         *\n;* PROTO:\tINT KeyNum_Translate(INT keynum);                          *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyNum_Translate C NEAR \n\tUSES \tebx,ecx,esi,edi\n\tARG\tkeycode:DWORD\n\n;*===================================================================\n;* ES points to the DOSMEM selector, esi is the offset of the \n;*   protected mode structure.\n;*===================================================================\n\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\tmov\teax,[keycode]\n\ttest\t[(KeyboardType PTR esi).KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\n\tmov\tecx,OFFSET ((KeyboardType PTR 0).ExtRemap)- OFFSET((KeyboardType PTR 0).ExtNums)\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtNums\n\tadd\tedi,esi\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).ExtRemapEnd\n\tdec\tedi\n\tsub\tedi,ecx\n\tmov\tal,[edi]\n??fini:\n\tret\n\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(INT code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_WORD C NEAR\n\tUSES\tebx,esi,edi\n\tARG\tcode:WORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\tedi,eax\n\tadd\teax,2\n\tand\teax,0FFh\t\t\t; New KeyBufferTail value.\n\tcmp\t[(KeyboardType PTR esi).KeyBufferHead],eax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[(KeyboardType PTR esi+edi).KeyBuffer],bx\t\t; Record the keystroke.\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\n\tret\n\n??noroom:\n\tmov\teax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_Num C NEAR\n\tUSES\tebx,ecx,edx,edi,esi\n\tARG\tkeycode:DWORD\n\tLOCAL\ttail:DWORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n; for the moment we do not check for the interrupt flag\n;\tmov\teax,2534h \t\t; function to get the interrupt status\n;\tint\t21\t\t\t; eax = interrupt status\n;\tpush\teax\t\t\t; save the result on the stack\n\n\tpushf\t\t\t\t; store off the flags\n\tcli\t\t\t\t; disable interrupts\n\n; We need to set the data segment because we might be being called\n; from within an interrupt\n; Soo, if that is the case then DS & ES point to DGROUP _DATA \n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\teax,[(KeyboardType PTR esi).MouseX]\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\teax,[(KeyboardType PTR esi).MouseY]\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],ax\n\n??cando:\n\tmov\teax,[keycode]\t\t; get the code\n\tor\teax,eax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[(KeyboardType PTR esi).Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[(KeyboardType PTR esi).Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\txor\tebx,ebx\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tebx,1\t\t\t; double for WORD index\n\tmov\tax,[WORD PTR ((KeyboardType PTR esi+ebx).XYAdjust)]\n\n\tmovsx\tebx,ah\n\tmovsx\teax,al\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tedx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tedx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tebx,edx\t\t\t; add speed for y index\n\tmov\tbl,[(KeyboardType PTR esi+ebx).KeyMouseMove] \t; get speed for y delta\n\tmovsx\tebx,bl\n\txchg\tebx,edx\t\t\t; save mouse y delta\n\tadd\tebx,eax\t\t\t; add speed for x index\n\tmov\tal,[(KeyboardType PTR esi+ebx).KeyMouseMove]\t; get speed for x delta\n\tmovsx\teax,al\n\txchg\tebx,edx\t\t\t; restore mouse y delta\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tebx,011b\t\t\t; Y = 1, 0, 3\n\tand\teax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tebx,011b\t\t\t; Y = 3, 0, 1\n\tand\teax,011b\t\t\t; X = 3, 0, 1\n\tshl\tebx,2\n\tor\tebx,eax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tebx,1\n\tmovzx\tebx,[(KeyboardType PTR esi+ebx).EdgeConv]\n\tshl\tebx,2\n\tmov\tax,[(KeyboardType PTR esi+ebx).ScreenEdge]\t; New absolute X\n\tmov\tbx,[(KeyboardType PTR esi+ebx+2).ScreenEdge] ; New absolute Y\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\teax,eax\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tebx,ebx\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseX],ax\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseY],bx\n\tcmp\t[(KeyboardType PTR esi).MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n; PWG: ARRGGGHHHH!\n;\tcall\tLow_Hide_Mouse\n;\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\teax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],eax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tedi,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\t[tail],edi\t\t; Safety record.\n\n\t; Record the base keycode (if there is room).\n\tcwde\t\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\teax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tmovzx\teax,[(KeyboardType esi).LocalMouseX]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tmovzx\teax,[(KeyboardType esi).LocalMouseY]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tebx,0101h\t\t; Bit control tools.\n\tmov\teax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[(KeyboardType PTR esi).KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[(KeyboardType esi).KeyBufferTail],edi\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tmov\tcl,3\n\tshr\tedi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[(KeyboardType esi+edi).KeysUpDown]\n\tje\tshort ??notalready\n\ttest\t[(KeyboardType PTR esi).KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\tedx,[tail]\n\tmov\t[(KeyboardType esi).KeyBufferTail],edx\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[(KeyboardType esi+edi).KeysUpDown],bh\t; Force key bit to zero.\n\tor\t[(KeyboardType esi+edi).KeysUpDown],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\teax,1\n\tjmp\tshort ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\teax,[tail]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\t\t\t; Signal an error.\n\n??exit:\n\tsti\n\tpopf\n\n;\tpopf\n;\tpop\tebx\n;\tor\tebx,ebx\n;\tjz\t??final_exit\n;\tsti\n\n??final_exit:\n\tret\n\n\tENDP\tStuff_Key_Num\n\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles break interrupt for protected mode           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBreak_Interrupt C NEAR\n\n\tiret\n\tENDP\tBreak_Interrupt\n\nIF DEBUG\n;***************************************************************************\n;* DEBUG_INTERRUPT -- Handles debug (INT 3) interrupt for protected mode   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tDebug_Interrupt C NEAR\n\n\t;*==================================================================\n\t;* Setup fake Interrupt entry sequence so that we can execute our\n\t;*   code and then IRET painlessly into the debuggers interrupt\n\t;*   handler.\n\t;*==================================================================\n\tpushfd\t\t\t; Step 1\n\tsub\tesp,8\t\t; Step 2\n\tpush\tebp\t\t; Step 3\n\tmov\tebp,esp\t\t; Set up a stack frame to know where to poke address.\n\n\t;*==================================================================\n\t;* Preserve all of the registers that we intend to use.\n\t;*=======================================Dbg========================\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n\tmov\tax , _DATA\n\tmov\tds , ax\n\tmov\tes , ax\n\tinc\t[BYTE PTR 0B0000h]\n\n\t;*==================================================================\n\t;* Setup the pointers to the real mode data and the protected mode\n\t;*   data and selectors.\n\t;*==================================================================\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t;*==================================================================\n\t;* Do the deed.\n\t;*==================================================================\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\n\t;*==================================================================\n\t;* Now get the address of the real debug handler and poke it into\n\t;*   the stack so we can IRET to it.\n\t;*==================================================================\n\tmov\teax,[(KeyboardType PTR esi).DbgOldPMIOffset]\t; Get orig offset.\n\tmov\tebx,[(KeyboardType PTR esi).DbgOldPMISelector]\t; Get orig selector.\n\tmov\t[ss:ebp+4],eax\t\t\t\t\t; Poke offset.\n\tmov\t[ss:ebp+8],ebx\t\t\t\t\t; Poke selector.\n\n\t;*==================================================================\n\t;* Restore the stack so it looks like we just did an IRET entry\n\t;*==================================================================\n\tpop\tfs gs es ds\n\tpopad\n\tpop\tebp\n\n\t;*==================================================================\n\t;* This iret should go directly to the real debugger handler\n\t;*\tpainlessly and effectively.\n\t;*==================================================================\n\tiretd\n\n\tENDP\tDebug_Interrupt\nENDIF\n\n\n\nIF PROT_INT_ENABLE\n\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Handles input that comes from the keyboard        *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Interrupt C NEAR\n\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n; this is the part of the interrupt that set the segment registers\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov cx, ss\t\t\t\t; get SS\n\tmov [Keyboard_App_Stack_ESP], esp\t; Protect ESP\n\tmov [Keyboard_App_Stack_SS], ecx\t; Protect SS\n\tlea edx, [Keyboard_StackStart ]\t; Compute Local Stack size\n\tand edx, -4 ;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov esp, edx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\t\n\tmov\tedx,[(KeyboardType PTR esi).KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[(KeyboardType PTR esi).KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\ttest\t[BYTE PTR 417H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR 417H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR 496H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tebx,0101H\t\t; set key to a make by default \n\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\t;\n\t; New CODE to montior key stream\n\t;\n\txor\tebx,ebx\n\tmov\tbx,[(KeyboardType PTR esi).KeyStreamIndex]\n\tmov\t[(KeyboardType PTR esi+ebx).KeyStream],al\n\tinc\tebx\n\tand\tebx,15\n\tmov\t[(KeyboardType PTR esi).KeyStreamIndex],bx\n\tmov\tebx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[(KeyboardType PTR esi).LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[(KeyboardType PTR esi).LastKeyE1]\t\t; yes, dec the count\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[(KeyboardType PTR esi).IsExtKey],TRUE\t; it is an extended key\n\n\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtCodes\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).ExtNums-OFFSET (KeyboardType PTR 0).ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\n\tmov\tal,[(OFFSET (KeyboardType PTR 0).ExtNums - OFFSET (KeyboardType PTR 0).ExtCodes) - 1 + edi] ; get the match\n\tmov\t[(KeyboardType PTR esi).IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tedi,eax\t\t\t; use code as an index\n\tand\tedi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[(KeyboardType PTR esi+edi).KeyNums]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[(KeyboardType PTR esi).ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n;------\tSet the shift bit if necessary.\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tshr\tedi,3\n\tmov\tebx,eax\n\tand\tebx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[(KeyboardType PTR esi+ebx).Bits]\t\t; get the bit to test\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[(KeyboardType PTR esi).CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\n\t\t\t\t\t; keyboard buffer.\n\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\teax\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\n\tmov\tecx,eax\n\txor\teax,eax\n\tmov\tax,cx\n\n\ttest\tedx,DEBUGINT\n\tjz\t??not_toggle\n\n\tcmp\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\n\tinc\t[BYTE PTR 0B0002h]\n\n\tcmp\teax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\teax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\teax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\t\n\tcmp\teax,125\n\tjne\t??not_toggle\n\n\tinc\t[BYTE PTR 0B0000h]\n\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjmp\t??absorbcode\n\n??not_toggle:\n\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\teax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\teax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\teax,0230h\n\tje\tshort ??breaker\n\tcmp\teax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[(KeyboardType PTR esi).Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n;\tcmp\tax,0420H\t\t; is this an alt s\n;\tjne\tshort ??checkmusic\t; toggle the Sound variable\n;\tpush\tax\n;\tmov\tax,[SoundOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??checkmusic:\n;\tcmp\tax,0434H\t\t; is this an alt m\n;\tjne\tshort ??esc\t\t; toggle the Music variable\n;\tpush\tax\n;\tmov\tax,[MusicOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??esc:\n\n\tpush\teax\n\tcall\tStuff_Key_Num\n\tpop\teax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[(KeyboardType PTR esi).EscRoutine],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\teax\n\tcall\t[(KeyboardType PTR esi).EscRoutine]\n\tpop\teax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tedi,OFFSET (KeyboardType PTR 0).PassAlways\t; get offset to table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd - OFFSET (KeyboardType PTR 0).PassAlways) ; get number of pass always CDY JLB MOD 7/11 was \n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tedi,OFFSET (KeyboardType PTR 0).CondPassKey\t; get offset to cond key table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).CondPassCond-OFFSET (KeyboardType PTR 0).CondPassKey) ; get number of entries\n\tshr\tecx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(OFFSET (KeyboardType PTR 0).CondPassCond - OFFSET (KeyboardType PTR 0).CondPassKey) - 2 + edi]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tedx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\tinc\t[(KeyboardType PTR esi).PassCount]\n\tmov\t[(KeyboardType PTR esi).PMIssuedKeyInt],1     ; Make it TRUE\n\n\t; Now it is time to set up for the call to the System Keyboard\n\t; interrupt handler.\n\t; 1 -Restore System Stack Pointer Selector before exit Interrupt\n\t; 2- We Create a Returning Point from Interrupt by Push A\n \t;    Interupt Stack Frame into the Stack Pointer\n\t; 3- We make a Far jump to the interuupt handler\n\n\tcmp  [Keyboard_StackPointer],0DEADDEADh\n\tje   ??pass_stack_good\n\n\tpush ecx\n\tpush edi\n\tpush eax\n\tmov  edi,0A0000h\n\tmov  ecx,64000\n\tmov  eax,1\n\trep  stosb\n\tpop  eax\n\tpop  edi\n\tpop  ecx\n\n??pass_stack_good:\n\tcli\t\t\t\t       ; disable Interrupts\n\tmov edx, [Keyboard_App_Stack_SS]       \n\tmov ss, dx\t\t\t       ; Set System Stack Selector\n\tmov esp, [Keyboard_App_Stack_ESP]      ; Set System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n\tlea\tedx, [??Call_Back_Keyboard]   ; Get Return address offset\n \tpushfd\t\t\t\t      ; push flags\t\n\tpush\tcs\t\t\t      ; push Code Selector\n\tpush\tedx\t\t\t      ; push Offset\n\n\t; Now we need to simulate an interrup call by using ired\n\t; because we still want to come back here from the\n\t; Old Keyboard interrupt handle.\n\tpushfd\n\tpush\t[(KeyboardType PTR esi).KeyOldPMISelector] ; push orig selector.\n\tpush    [(KeyboardType PTR esi).KeyOldPMIOffset]   ; push orig offset.\n\tiretd\n\n??absorbcode:\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tal,[496h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[496h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\n\tcmp  [Keyboard_StackPointer],0DEADDEADh\n\tje   ??call_stack_good\n\tpush ecx\n\tpush edi\n\tpush eax\n\tmov  edi,0A0000h\n\tmov  ecx,64000\n\tmov  eax,1\n\trep  stosb\n\tpop  eax\n\tpop  edi\n\tpop  ecx\n\n??call_stack_good:\n\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov edx, [Keyboard_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, dx\t\t\t       ; Set System Stack Selector\n\tmov esp, [Keyboard_App_Stack_ESP]      ; Set System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n??Call_Back_Keyboard:\n\tpop\tfs gs es ds\n\tpopad\n\tiret\t\n\n\tENDP\tKeyboard_Interrupt\n\nELSE\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Stub for the keyboard interrupt call real mode    *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\n \nDATASEG\nSTRUC\tRealModeCallStruc\n\t_EDI  DD\t0\n\t_ESI  DD\t0\n\t_EBP  DD\t0\n\t      DD        0\n\t_EBX  DD\t0\n\t_EDX  DD\t0\n\t_ECX  DD\t0\n\t_EAX  DD        0\n\tFLAGS DW\t0\n\t_ES   DW\t0\n\t_DS   DW\t0\n\t_FS   DW\t0\n\t_GS   DW\t0\n\t_IP   DW\t0\n\t_CS   DW\t0\n\t_SP   DW\t0\n\t_SS   DW\t0\n\t      dd\t0\n\t      dd\t0\n  nothing     dd\t0\t\nENDS \n\nRMDS RealModeCallStruc  <>\n\nCODESEG\n\nPROC\tKeyboard_Interrupt\tNear\n\n; This option of the keyboard interrupt handle will not be\n; available at this moment because the light version of Rational System DOS\n; Extender do not allow a DPMI real mode call which is\n; DMPI INT 31h funtion 0301h\n\n\tpushad\t\n\tpush\tfs gs es ds\n\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\n\tlea\tedi , [ RMDS ]\n\tlea\tecx , [ RMDS . nothing ]\n\tsub\tecx , edi\n\txor\teax , eax\n\tshr\tecx , 2\n\trep\tstosd\n\t\n\tmov\teax , 0300h\n\tmov\tbl , [ byte ptr RMVector ]\n\txor\tbh , bh\n\txor\tcx , cx\n\tlea\tedi , [RMDS]\n\tint\tDPMI_INTR\n\n; this is here only for testing to make sure\n; that a real mode interrupt is bieng issued. \nmov\tax , _DATA\nmov\tes , ax\nmov\tds , ax\nmov [ byte ptr 0b0000h + 10 * 80 + 40 ] , 040h\njc\t??error\nmov [ byte ptr 0b0000h + 10 * 80 + 42 ] , 041h\n\n??error:\n\tpop\tds es gs fs\n\tpopad\t\n\tiretd\n\tENDP\n\nENDIF\n\nLABEL \tLockedCodeEnd\t\tBYTE\n\n;***************************************************************************\n;* End of File.\t\t\t\t\t\t\t\t   *\n;***************************************************************************\nEND\n\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/KEYBOARD.BAK",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : KEYBOARD.ASM                             *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 15, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Get_RM_Timer_Address -- Return address of real mode code for copy.    *\n;*   Get_RM_Keyboard_Size -- return size of real mode timer code.          *\n;*   Check_Key -- checks queue for key (make)                              *\n;*   Check_Key_Num -- Checks if key in queue, return key num               *\n;*   Get_Key_Num -- Returns the next key num in ax                         *\n;*   KN_To_KA -- Translates a key num to an ASCII key                      *\n;*   Low_Get_Key -- low level get key returns key num and bits             *\n;*   Convert_Num_To_ASCII -- Assembly routine converts keynum to ASCII key *\n;*   KeyNum_Translate -- Performs a lowlevel xlate to a keycode            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\n;*\tKeyboard driver -- 80386 Protected Mode Assembly portion\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   \n;***************************************************************************\n;\n; ----------------------------------------------------------------\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\n;WARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Make some general equates for easy compatability\n;---------------------------------------------------------------------------\nPROT_INT_ENABLE\tEQU\t1\t\t; if false protected int just calls real mode int\n\nDPMI_INTR\tEQU\t31h\t\nIRQ1INTNUM\tEQU\t09h\t\t; IRQ1 interrupt vector number.\nBRKINTNUM\tEQU\t23h\t\t; Crtl-C (Break) interrupt vector number\nDBGINTNUM\tEQU\t3h\t\t; Debug interrupt vector number\nDOS_SYS_CALL\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nLOCK_PAGES\tEQU\t5\t\t; Lock pages subfunction using DX_MEM_MGT\nUNLOCK_PAGES\tEQU\t6\t\t; Unlock pages subfunction using DX_MEM_MGT\nCLEARISR\tEQU\t020H\t; value to clear In Service Register\nINTCHIP0\tEQU\t020H\t; 8259 interrupt chip controller 0\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\n\tINCLUDE \"keyboard.inc\"\n\tINCLUDE \"keystruc.inc\"\n\tINCLUDE \"mcgaprim.inc\"\n\n\tGLOBAL\t RealModePtr:DWORD\n\n\tGLOBAL\t Install_Keyboard_Interrupt:NEAR\n\tGLOBAL\t Get_RM_Keyboard_Address:Near\n\tGLOBAL\t Get_RM_Keyboard_Size:Near\n\tGLOBAL\t Remove_Keyboard_Interrupt:NEAR\n\tGLOBAL\t Check_Key_Num:NEAR\n\tGLOBAL\t Get_Key_Num:NEAR\n\tGLOBAL\t KN_To_KA:NEAR\n\tGLOBAL\t KeyNum_Translate:NEAR\n\tGLOBAL\t Check_Key:NEAR\n\tGLOBAL\t Get_Key:NEAR\n\tGLOBAL\t Keyboard_Attributes_On:NEAR\n\tGLOBAL\t Clear_KeyBuffer:NEAR\n\tGLOBAL\t Key_Down:NEAR\n\tGLOBAL\t Keyboard_Attributes_Off:NEAR\n\tGLOBAL\t Check_Key_Bits:NEAR\n\tGLOBAL\t Get_Key_Bits:NEAR\n\tGLOBAL\t Key_Satisfied:NEAR\n\tGLOBAL\t Stuff_Key_WORD:NEAR\n\tGLOBAL\t Stuff_Key_Num:NEAR\n\tGLOBAL\t MouseQX:DWORD\n\tGLOBAL\t MouseQY:DWORD\n;DBG\n\tGLOBAL   Keyboard_Interrupt:NEAR\n\n\n\tDATASEG\n; For the current time we will just include the real mode stuff\n; into the protected mode code and then copy it down.  The C side of\n; this will handle this method or reading it off of disk in the real\n; method.\n\nLABEL \tRealBinStart\tBYTE\ninclude \"keyireal.ibn\"\nLABEL\tRealBinEnd\tBYTE\n\nLABEL\tLockedDataStart\tBYTE\t\nRMVector\tDD\t0\nRealModeSel\tDD\t0\nRealModePtr\tDD\t0\t\t; Pointer to real mode memory.\nRealModeSize\tDD\t0\t\t; Pointer to real mode memory.\n\nKeyboard_App_Stack_ESP\tDD 0\t\t; This the System Stack Offsset\nKeyboard_App_Stack_SS\tDD 0\t\t; This the System Stack Selector\nKeyboard_StackPointer\tDD 0DEADDEADh\t; We Create a Local Application\nKeyboard_Stack          DD 255 dup (0)\nKeyboard_StackStart\tDD 0\n\t\t\t\t\t; StackPointer \t\nLABEL\tLockedDataEnd\tBYTE\n\n\n\nAscii\tDB\t0,\"`1234567890-=\",0,8,9,\"qwertyuiop[]\\\",0,\"asdfghjkl;'\"\n\tDB\t0,13,0,45,\"zxcvbnm,./\",0,0,0,0,0,\" \"\n\nShift\tDB\t0,\"~!@#$%^&*()_+\",0,8,9,\"QWERTYUIOP{}|\",0,\"ASDFGHJKL:\",22H\n\tDB\t0,13,0,45,\"ZXCVBNM<>?\",0,0,0,0,0,\" \"\n\nAlpha_Lower\tDB\t0\n\tDB\t\"~!@#$%^&*()_+\",0,8,9,\"qwertyuiop{}|\",0,\"asdfghjkl:\",22H\n\tDB\t0,13,0,45,\"zxcvbnm<>?\",0,0,0,0,0,\" \"\n\nAlpha_Shift\tDB\t0\n\tDB\t\"`1234567890-=\",0,8,9,\"QWERTYUIOP[]\\\",0,\"ASDFGHJKL;'\"\n\tDB\t0,13,0,45,\"ZXCVBNM,./\",0,0,0,0,0,\" \"\n\nEdit\tDB\t0AEH,0ADH,000H,000H,0B5H,0B9H,0B1H,000H,0B8H,0B0H,0B7H,0AFH\n\tDB\t000H,000H,0B3H,000H,0B9H,0B5H,0B1H,000H, \"/\",0B8H,0B4H,0B0H\n\tDB\t0AEH, \"*\",0B7H,0B3H,0AFH,0ADH, \"-\", \"+\",000H,00DH,000H\n\nNumPad\tDB\t0,\"741\",0,\"/8520*963.-+\",0,13,0\n\n\nGetKeyLock\tDW\t0\t; snap shot of num and caps lock bits\nInitFlags\tDW\t0\nMouseQX\t\tDD\t0\nMouseQY\t\tDD\t0\n\n\tCODESEG\n;***************************************************************************\n;* GET_RM_TIMER_ADDRESS -- Return address of real mode code for copy.      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      VOID * to the address of the real mode timer               *\n;*                                                                         *\n;* PROTO:\tVOID\t*Get_RM_Keyboard_Address(VOID);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Address C Near\n\n\tmov\teax, OFFSET RealBinStart\n\tret\n\n\tENDP\n\n;***************************************************************************\n;* GET_RM_KEYBOARD_SIZE -- return size of real mode timer code.            *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      LONG size of the real mode timer code                      *\n;*                                                                         *\n;* PROTO:\tLONG\tGet_RM_Keyboard_Size(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Size C Near\n\n\tmov\teax, OFFSET RealBinEnd - OFFSET RealBinStart\n\tret\n\n\tENDP\n;***************************************************************************\n;* INSTALL_KEYBOARD_INTERRUPT -- Installs the keyboard interrupt           *\n;*                                                                         *\n;* INPUT:\tint rm_ptr  - ptr to the real mode handler\t\t   *\t   *\n;*\t\tint rm_size - size of the real mode handler\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Install_Keyboard_Interrupt(int rm_ptr, int rm_size);  *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tInstall_Keyboard_Interrupt C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\tARG\trm_ptr:DWORD\n\tARG\trm_size:DWORD\n\n\t; Are they attempting to set timer again?\n\tcmp\t[RealModePtr],0\n\tjnz\t??error\n\n\t; Make sure all flags are cleared.\n\tcmp\t[InitFlags],0\n\tjnz\t??error\n\n\n\t; Before setting the interrupt vectors, the code needs to be locked\n\t; for DPMI compatability.  Any code or data accessed must be lockded\n\t; so that no page faults accure during an interrupt.\n\t; First lock the code, then the data.  The stack will already be locked.\n\t; The real mode code is also already locked be default.\n\t; To lock a page set up registers :\n\t; AX = 0600h\n\t; BX:CX\t= starting linear address of memory block\n\t; SI:DI = size of region\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_CODE\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_DATA\n\n\t; now allocate real mode memory and copy the rm binary down to it.\n\tmov\teax,0100h\t; set function number\n\tmov\tebx,[rm_size]\t\t; get size of RM binary.\n\tmov\t[RealModeSize],ebx\n\tadd\tebx,15\t\t\t; round up \n\tshr\tebx,4\t\t\t; convert to pages.\n\tint\tDPMI_INTR\t \t; do call.\n\tjc\t??error\t\t \t; check for error.\n\tor\t[InitFlags],IF_ALLOC_RM ; set successful\n\tmov\t[RealModeSel],edx\n\tshl\teax,4\t\t\t; convert segment to offset.\n\tmov\t[RealModePtr],eax\t; save offset to global variable.\n\n\t; now lock the real mode memory that we allocated\n\tmov\teax,0600h\t\t; function number.\n\tmov\tecx,[RealModePtr]\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_RM_CODE\n\n\n\n\t; set up source and destination pointers for the copy.\n\tmov\teax,[RealModePtr];\t; set up our dest pointer\n\tmov\tesi,[rm_ptr]\t\t; Set up our source pointer.\n\tmov\tedi,eax\t\t\t; put it into esi for copy.\n\tmov\tecx,[rm_size]\n\trep\tmovsb\t\t\t; write RM bin to RM memory.\n\n\t; restore esi to point to data and initialize some of it.\n\tmov\tesi,[RealModePtr]\n\tmov\teax,esi\n\tshl\teax,12\t\t\t\t\t\t; make seg in high eax.\n\tmov\tax,[(KeyboardType PTR esi).CallKeyRMIntOffset]\t; create RM addr of call chain.\n\tmov\t[(KeyboardType PTR esi).CallKeyRMIntAddr],eax\t; save it for use in PM int.\n\nIF NOT PROT_INT_ENABLE\n       ; Chain the Real Keyboard interrupt to any avilable\n       ; Interrupt vector so We make sure that the Real Mode\n       ; Keyboard Interrupt service get called at debuging time\n       ; of the library.\n\n       mov\tedi , eax\n       mov\tbl , 060h\n       mov\tbh , 6\n       mov\teax , 200h\n ??find:\n       int\tDPMI_INTR\n       jc\t??error\n       or\tcx,dx\n       jz\t??found\n       inc\tbl\n       dec\tbh\n       jnz\t??find\n       jmp\t??error\n ??found:\n       movzx\tebx , bl\n       mov\t[ byte ptr RMVector ] , bl\n       mov\t[ 4 * ebx ] , edi\nENDIF\n\n\n\n\t;-------------------------------------------------------\n\t; Initialize all of the keyboard specific information\n\t;-------------------------------------------------------\n\txor\teax,eax\t\t\t; clear the high bits of eax\n\tmov\tal,[417H]\t\t; get keyboard status flags\n\ttest\teax,040H \t\t; caps lock active?\n\tje \tshort ??nocap\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\n\n??nocap:\n\ttest\teax,020H\t\t\t; num lock active?\n\tje\tshort ??nonumlock\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\n\n??nonumlock:\n\ttest\teax,002H\t\t\t; is left shift key down?\n\tje\tshort ??noleftshift\t\t; try the right\n\tor\t[(KeyboardType PTR esi+5).KeysUpDown],010H\n\n??noleftshift:\n\tand\teax,001H\t\t\t; get right shift bit\n\tshl\teax,9\t\t\t; put it into the proper position (shl al,1 mov ah,al)\n\tmov\tal,[418H]\t\t; get alt and ctrl bits\n\tshl\tal,2\t\t\t; put in proper position\n\tshl\tal,1\n\tand\tal,00CH\t\t\t; only alt and ctrl bits\n\tor\tah,al\t\t\t; put them ah for Keys+7 later\n\tmov\tal,[496H]\t\t; get extended keys\n\ttest\tal,008H\t\t\t; check for right alt key\n\tje\tshort ??noralt\n\tor\tah,040H\n??noralt:\n\tmov\t[(KeyboardType PTR esi+7).KeysUpDown],ah\n\ttest\tal,004H\t\t\t; test for right ctrl\n\tje \tshort ??norctrl\n\tor\t[(KeyboardType PTR esi+8).KeysUpDown],001h\n??norctrl:\n\ttest\tal,002H\t\t\t; last code E0?\n\tje short ??noe0\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],001h\n??noe0:\n\ttest\tal,001H\t\t\t; last code E1?\n\tje short ??noe1\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],002h\n??noe1:\n\t;==========================================================================\n\t; Get the protected mode interrupt vector keyboard.\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).KeyOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).KeyOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 2503, cl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).KeyOldRMI],ecx\n\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt Keyboard\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Keyboard_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt Keyboard\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).KeyCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the break interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\t\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).BrkOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).BrkOldPMISelector],ecx\t; save selector.\n\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector - for the break interrupt\n\t; input ax = 0200, bl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).BrkOldRMI],ecx\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Break_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).BrkCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\nIF DEBUG\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the Debug interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\t\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,DBGINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).DbgOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).DbgOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Debug_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\nENDIF\n\n\t; we have finished with success.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n??exit:\n\tret\n\tENDP\tInstall_Keyboard_Interrupt\n\n;***************************************************************************\n;* REMOVE_INTERRUPT -- Removes keyboard interrupt and restores chain\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Remove_Interrupt(VOID)                                *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tRemove_Keyboard_Interrupt C NEAR \n\tUSES\tebx,ecx,edx\n\n\t; verifie that the keyboard was previosly install\n\t; this is here in case of a page fault crash\n\tmov\tesi,[RealModePtr]\n\ttest    esi,esi\n\tjz      ??error\n\n\ttest\t[InitFlags],IF_SET_VECTORS\n\tjz\t??vectors_not_set\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tedx,[(KeyboardType esi).KeyOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[(KeyboardType esi).KeyOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).KeyOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\n\t; disengage Control Break Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tedx,[(KeyboardType esi).BrkOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[(KeyboardType esi).BrkOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).BrkOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\nIF DEBUG\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tecx,[(KeyboardType esi).DbgOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).DbgOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\nENDIF\n\nIF NOT PROT_INT_ENABLE\n       ; Clean up the Users interrupt table\n        mov\teax , 201h\n       mov\tbl , [ byte ptr RMVector ]\n       xor\tecx , ecx\n       xor\tedx , edx\n       int\tDPMI_INTR\n       jc\t??error\nENDIF\n\n\n??vectors_not_set:\n\t; now free up the real mode memory.\n\ttest\t[InitFlags],IF_LOCKED_RM_CODE\n\tjz\t??rm_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,[RealModePtr]\t\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t\t; edx will have size of region in bytes.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??rm_not_locked:\n\ttest\t[InitFlags],IF_ALLOC_RM\n\tjz\t??mem_not_allocated\n\tmov\teax , 0101h\n\tmov\tedx,[ RealModeSel ] \t\t; get physical address of real mode buffer.\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n??mem_not_allocated:\n\n\t; Now we can unlock all stuff needed for the interrupt.  \n\t; Unlock Code\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??code_not_locked:\n\n\t; Unlock data\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??data_not_locked:\n\n\t; we have finished with success.\n\tmov\t[RealModePtr],0\t\t; To say we can do it again sometime.\n\tmov\t[InitFlags],0\t\t; To say we can do it again sometime.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n\tret\n\tENDP\tRemove_Keyboard_Interrupt\n\n\n;***************************************************************************\n;* CHECK_KEY_NUM -- Checks if key in queue, return key num                 *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      Keynum of the key that was pressed, FALSE otherwise        *\n;*\n;* PROTO:\tINT Check_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Num C NEAR \n\tUSES\tebx,esi\n\tpushf\t\t\t\t\t; save off the flags\n\tcli\t\t\t\t\t; disable interrupts\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t\t\n\txor\teax,[(KeyboardType PTR esi).KeyBufferTail]\t\t\n\tor\teax,eax\t\t\t\t; check to see if head == tail\n\tjz\tshort ??fini\t\t\t; if so we are done\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t; get the head\n\tmov\tax,[(KeyboardType PTR esi+eax).KeyBuffer]\t; get key num\n\n??fini:\n\tsti\n\tpopf\n\tret\n\n\tENDP\tCheck_Key_Num\n\n;***************************************************************************\n;* GET_KEY_NUM -- Returns the next key num in ax                           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      WORD key flags are in the high byte of return word, key    *\n;*\t\t  num is in the low byte.\n;*                                                                         *\n;* PROTO:\tWORD Get_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Num C NEAR\n\tUSES\tesi,edi\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n??wait:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t\t; get the head\n\tcmp\teax,[(KeyboardType PTR esi).KeyBufferTail]\t\t; get the head\n\tjne\tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??wait\n\n??getkey:\n\tcall\tLow_Get_Key\n\tsti\t\t\t\t; enable interrupts\n\tret\n\n\tENDP\tGet_Key_Num\n\n;***************************************************************************\n;* KN_TO_KA -- Translates a key num to an ASCII key                        *\n;*                                                                         *\n;* INPUT:\tWORD the keynum to translate                               *\n;*                                                                         *\n;* OUTPUT:      WORD the ASCII key that is returned                        *\n;*                                                                         *\n;* PROTO:\tINT KN_To_KA(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tKN_To_KA C NEAR\n\tARG\tkeynum:DWORD\n\n\tmov\teax,[keynum]\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\tret\n\n\tENDP\tKN_To_KA\n\n\n;***************************************************************************\n;* LOW_GET_KEY -- low level get key returns key num and bits               *\n;*                                                                         *\n;* INPUT:\tAX - index into the buffer                                 *\n;*                                                                         *\n;* OUTPUT:      AX - key num with bits                                     *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tLow_Get_Key C NEAR \n\tUSES\tebx,esi,edi\n\n\tmov\tedi,eax\t\t\t\t; save off value in ax\n\n; We should set up both DS & ES because we are a low level function\n; and don't know who might have called us or what the registers\n; currently are.\n\n; No reason to set DS & ES.\n; This is not a hardware interrupt and if the funtion is being called\n; from within a hardware interrupt then DS and ES will be preset to\n; DGROUP _DATA\n\t\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tcmp\tal,KN_LMOUSE\n\tjb \tshort ??cont\n\tcmp\tal,KN_RMOUSE\n\tja \tshort ??chkjoy\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t; 128 word circular buffer\n\n\tmov\t[MouseQX],eax\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\t[MouseQY],eax\n\n\tpop\teax\t\t\t; restore keynum for return\n\n\tjmp\tshort ??cont\n\n??chkjoy:\n\tcmp\tal,KN_JBUTTON2\t\t; mouse button before joystick button\n\tja \tshort ??cont\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tpop\teax\t\t\t; restore keynum for return\n??cont:\n\tmov\t[(KeyboardType PTR esi).KeyBufferHead],edi\t; set the head\n\n??out:\n\tret\n\n\tENDP\tLow_Get_Key\n\n;***************************************************************************\n;* CONVERT_NUM_TO_ASCII -- Assembly routine converts keynum to ASCII key   *\n;*                                                                         *\n;* INPUT:\tEAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - holds the key num bits                        *\n;*\t\t\tAL - holds the key num value\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      EAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - hold the key bits                             *\n;*\t\t\tAL - holds the ASCII key value\t\t\t   *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* WARNINGS:    GetKeyLock must be set prior to calling this function\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tConvert_Num_To_ASCII C NEAR \n\tUSES\tebx,ecx,esi,edi\n\n\t;*===================================================================\n\t;* Force all breaks to be thrown out.\n\t;*===================================================================\n\ttest\teax,08000h\t\t; If it is a button number\n\tjne\tshort ??button\t\t;  don't process it\n\n\ttest\tah,KEYRELEASE\t\t; If it is not key release\n\tje\tshort ??ok\t\t;  then go process it\n\n??button:\n\txor\teax,eax\t\t\t; no ascii value for a button\n\tret\n\n??ok:\n\t;*===================================================================\n\t;* ES points to the DOSMEM selector, esi is the offset of the \n\t;*   protected mode structure.\n\t;*===================================================================\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\n\t;*===================================================================\n\t;* Start dealing with the keys.\t\t\t\t\t  \n\t;*===================================================================\n\tcmp\tal,110\t\t\t; is it esc\n\tje\t??esc\t\t\t; if so then deal with it\n\n;??chkext:\n\tcmp\tal,62\t\t\t; is it extended?\n\tjae\tshort ??extended\t; its extended so return ext code\n\n\tmov\tebx,eax\t\t\t; get an index\n\tand\tebx,03FH\t\t; only 0-63 allowed\n\ttest\tah,1\t\t\t; if not, test for shift\n\tjnz\tshort ??shifted\t\t; if shifted get shift value\n\n\t;*===================================================================\n\t;* Here when we have an unshifted ascii key\n\t;*===================================================================\n\tmov\tal,[Ascii+ebx]\t\t; get the ascii code for this number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_lowered:\n\tmov\tal,[Alpha_Lower+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_shifted:\n\tmov\tal,[Alpha_Shift+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* Shift'ed character\n\t;*===================================================================\n??shifted:\n\tmov\tal,[Shift+ebx] \t\t; get ascii shift code for number\n\n??ctrlkey:\n\ttest\tah,2\t\t\t; is it ctrl?\n\tjz \tshort ??jexit\t\t; izf not skip ctrl check\n\n\tmov\tedi,ebx\t\t\t; get index\n\tand\tedi,7\t\t\t; only bits 0-7\n\n\tmov\tcl,[(KeyboardType PTR esi+edi).Bits]\n\n\tshr\tebx,3\t\t\t; div by 8 for byte offset\n\ttest\t[(KeyboardType PTR esi+ebx).KeysCapsLock],cl\t\n\tje \tshort ??jexit\n\tand\tal,01FH\t\t\t; force to ctrl value\n\n??jexit:\n\tjmp short ??exit\n\n??extended:\n\tcmp\tal,75\t\t\t; if less than insert\n\tjb \tshort ??special\n\tcmp\tal,110\t\t\t; if >= esc\n\tjae \tshort ??funckey\n\n??editkeys:\n\txor\tebx,ebx\n\tmov\tbl,al\n\tsub\tebx,75\t\t\t; get value from 0-34\n\ttest\t[(KeyboardType PTR esi).KeyFlags],NONUMLOCK\n\tjne \tshort ??no_numpad\n\ttest\t[GetKeyLock],NUMLOCK\t; look at the snap shot of bits\n\tjne \tshort ??numpad\n\n??no_numpad:\n\tmov\tal,[Edit+ebx] \t\t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??numpad:\n\tsub\tebx,15\t\t\t; adjust to numpad entries\n\tmov\tal,[NumPad+ebx] \t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??funckey:\n\tcmp\tal,112\t\t\t; if less than function keys\n\tjb \tshort ??extout\n\tcmp\tal,121\t\t\t; if greater than function keys 1-10\n\tja \tshort ??extout\n\tmov\tbl,al\n\tsub\tbl,112\t\t\t; get value 0-9\n\tmov\tbh,0C5H\t\t\t; function key 1 no shift-ctrl-alt\n\ttest\tah,7\t\t\t; any shift-ctrl-alt\n\tje\tshort ??funcadj\n\tmov\tbh,098H\t\t\t; function key 1 alt\n\ttest\tah,ALTPRESS\t\t; (highest prescendence)\n\tjne \tshort ??funcadj\n\tmov\tbh,0A2H\t\t\t; function key 1 ctrl (next highest)\n\ttest\tah,CTRLPRESS\n\tjne\tshort ??funcadj\n\tmov\tbh,0ACH\t\t\t; function key 1 shift (lowest)\n\n??funcadj:\n\tsub\tbh,bl\t\t\t; adjust function key to a\n\tmov\tal,bh\t\t\t; shift/no shift etc\n\tjmp\tshort ??exit\n\n??special:\n\tcmp\tal,65\t\t\t; if less than specials\n\tjb\tshort ??extout\n\n\tadd\tal,133\t\t\t; make value between 198-207 or\n\tjmp\tshort ??exit\t\t; 0C6H-0CFH\n\t\n??extout:\n\tor\tal,080H\n\tjmp\tshort ??exit\n\n??esc:\n\tmov\tal,01BH\n\n??exit:\n\tret\n\tENDP\tConvert_Num_To_ASCII\n\n;***************************************************************************\n;* CHECK_KEY -- checks for ASCII keys sitting in the keybuffer             *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      INT the ASCII sequence for the key that was pressed        *\n;*                                                                         *\n;* PROTO:\tINT Check_Key(VOID);                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key C NEAR\n\tUSES\tebx,edi,esi\n\n\tpushf\n\tcld\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tcmp\tal,KN_LMOUSE\t\t; check if it is a mouse or joystick\n\tjb\tshort ??contget\n\tcmp\tal,KN_JBUTTON2\n\tja\tshort ??contget\n\tadd\tsi,4\t\t\t; get rid of the x and y values\n\n??contget:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\teax,eax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\tsti\t\t\t\t; enable interrupts\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tcall\tnear ptr Convert_Num_To_ASCII\n\t\t\t\t\t; AX has ASCII code with bits\n\n\txor\tah,ah\t\t\t; clear key bits\n??exit:\n\tpopf\n\tret\n\tENDP\tCheck_Key\n\n\n;***************************************************************************\n;* GET_KEY -- Gets the next available ASCII keystroke.\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      AH - hold the key bits                                     *\n;*\t\tAL - holds the ASCII key value\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tINT Get_Key(VOID);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key C NEAR \n\tUSES \tebx,ecx,edi\n\n\tcld\t\t\t\t; clear the direction flag for speed\n\n\t; Check_Key had to be copied because of enable and disable of ints\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\t\t\t\t\t; AX has key num code with bits\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\txor\tah,ah\n\tret\n\n\tENDP\tGet_Key\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_ON -- Sets the specified keyflags on                *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned on                 *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are on                       *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_On(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_On C NEAR\n\tUSES\tesi,edi\n\tARG\tbits:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tor\t[(KeyboardType PTR esi).KeyFlags],eax\n\n\t; Only do this if in playback or record mode.\n\ttest\teax,PASSBREAKS\n\tje\tshort ??fini\n\n\txor\teax,eax\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).KeysUpDown\n\tmov\t[edi],eax\n\tmov\t[edi+4],eax\n\tmov\t[edi+8],eax\n\tmov\t[edi+12],eax\n??fini:\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\n\tret\n\tENDP\tKeyboard_Attributes_On\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_OFF -- Sets the specified keyflags off              *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned off                *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are off                      *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_Off(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_Off C NEAR\n\tUSES\tesi\n\tARG\tbits:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tnot\teax\n\tand\t[(KeyboardType PTR esi).KeyFlags],eax\n\txor\teax,eax\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\n\tret \n\n\tENDP\tKeyboard_Attributes_Off\n;***************************************************************************\n;* CLEAR_KEYBUFFER -- Clears keystrokes out of the key buffer              *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Clear_KeyBuffer(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tClear_KeyBuffer C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tcli\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\tsti\n\n\tret\n\n\tENDP\tClear_KeyBuffer\n\n;***************************************************************************\n;* KEY_DOWN -- tests the status of a keyboard key                          *\n;*                                                                         *\n;* INPUT:\tINT the key num to check                                   *\n;*                                                                         *\n;* OUTPUT:      INT zero if the key is up, none zero if the key is down    *\n;*                                                                         *\n;* PROTO:\tINT Key_Down(INT key);\t\t\t\t   \t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Down C NEAR\n\tUSES\tebx,ecx,edi,esi\n\tARG\tkey:DWORD\n\n\tpush\t[key]\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\txor\tah,ah\t\t\t\t; Always ignore the control bits.\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tedi,eax\n\tshr\tedi,3\n\tmov\tcl,al\n\tand\tcl,0111b\n\tmov\tal,01b\n\tshl\tal,cl\n\tand\tal,[(KeyboardType PTR esi+edi).KeysUpDown]\n\tret\n\n\tENDP\tKey_Down\n\n;***************************************************************************\n;* CHECK_KEY_BITS -- checks ascii key in key buff with shift,ctrl,alt bits *\n;*                                                                         *\n;* INPUT:\tnone \t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set     *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Bits C NEAR\n\tUSES\tebx,ecx,edi,esi\n\n\tpushf\t\t\t\t\t; save off the direction flag\n\tcld\t\t\t\t\t; we will go forward\n\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n??playback:\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\t;------ If there is a NULL in the keyboard buffer, we must NOT treat it\n\t;\tas a valid ASCII value because the calling code will falsely\n\t;\tassume that the NULL return value indicates an empty buffer.\n\tor\tal,al\n\tje\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\tax,ax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tCheck_Key_Bits\n;***************************************************************************\n;* GET_KEY_BITS -- Gets ascii key in key buff with shift,ctrl,alt bits     *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set\t   *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Bits C NEAR \n\tUSES\tebx,ecx,edi\n\n\tcld\n\n\t; Check_Key_Bits was copied because of enable and disable of interrupts\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\tret\n\n\tENDP\tGet_Key_Bits\n\n;***************************************************************************\n;* KEY_SATISFIED -- checks to see if the given key is satisfied            *\n;*                                                                         *\n;* INPUT:   INT the key flags/number to check                          \t   *\n;*                                                                         *\n;* OUTPUT:  INT 0 if the key is not satisfied, !0 if the key is satisfied  *\n;*                                                                         *\n;* PROTO:   VOID Key_Satisfied(INT key);                                    *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Satisfied C NEAR\n\tUSES\tebx,ecx,esi,edi\n\tARG\tkey:DWORD\n\n\tmov\teax,[key]\n\tmov\tebx,eax\t\t\t; save key code\n\tpush\teax\n\tcall\tKey_Down\t\t; see it its even down\n\tadd\tesp,4\n\tcmp\teax,0\n\tje\t??out\t\t\t; if not it can't be satisfied\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,ebx\t\t\t; if so, restore code\n\txor\tah,ah\t\t\t; clear out flags area\n\tmov\tedi,eax\t\t\t; set as an index\n\tshr\tedi,3\t\t\t; div by 8 for bytes\n\tmov\tch,1h\t\t\t; set a bit for mask\n\tmov\tcl,al\t\t\t; get the code number\n\tand\tcl,7\t\t\t; get the actual bit this code is\n\tshl\tch,cl\t\t\t; move bit into mask position\n\n; now test the ctrl,alt and shift bits\n\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],04h\t; is the left ctrl down?\n\tjne \tshort ??ctrlon\t\t; if so, ctrl is on\n\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],01h\t; is the right ctrl down?\n\tje \tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n??ctrlon:\n\tor\tah,02h\t\t\t; or on the ctrl bit in flags\n??ctrloff:\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],50h\t; is either alt key down?\n\tje \tshort ??altoff\n\tor\tah,04h\t\t\t; or on the alt bit in flags\n??altoff:\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],10h\t; is the left shift down?\n\tjne \tshort ??shifton\t\t; if so the sift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],02h\t; is the right shift down?\n\tje \tshort ??shiftoff\t\t; if not then neither shift is down\n??shifton:\n\tor\tah,01h\t\t\t; or on the shift bit in flags\n??shiftoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje \tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje \tshort ??capsoff\t\t; its not effected\n\txor\tah,1h\t\t\t; toggle the shift flag\n??capsoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t\t; is the num lock key on?\n\tje \tshort ??numlockoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje \tshort ??numlockoff\t\t; if not effected skip toggle\n\txor\tah,1h\t\t\t; toggle the shift flag if effected\n\n??numlockoff:\n\tmov\tal,0ffh\t\t\t; set to match by default\n\tcmp\tah,bh\t\t\t; if flags match return !0\n\tje \tshort ??out\t\t\t; just exit\n\txor\teax,eax\t\t\t; otherwise, clear all bits FALSE\n\n??out:\n\tor\teax,eax\n\tret\n\n\tENDP\tKey_Satisfied\n\n\n;***************************************************************************\n;* Interrupt routines start here - Interrupts must be within the Locked \n;*   code area for DPMI compatability.\n;***************************************************************************\n\n\n\n\nLABEL \tLockedCodeStart\tBYTE\n\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Performs a lowlevel xlate to a keycode              *\n;*                                                                         *\n;* INPUT:\tWORD the code that needs to be translated                  *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated code                                   *\n;*                                                                         *\n;* PROTO:\tINT KeyNum_Translate(INT keynum);                          *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyNum_Translate C NEAR \n\tUSES \tebx,ecx,esi,edi\n\tARG\tkeycode:DWORD\n\n;*===================================================================\n;* ES points to the DOSMEM selector, esi is the offset of the \n;*   protected mode structure.\n;*===================================================================\n\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\tmov\teax,[keycode]\n\ttest\t[(KeyboardType PTR esi).KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\n\tmov\tecx,OFFSET ((KeyboardType PTR 0).ExtRemap)- OFFSET((KeyboardType PTR 0).ExtNums)\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtNums\n\tadd\tedi,esi\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).ExtRemapEnd\n\tdec\tedi\n\tsub\tedi,ecx\n\tmov\tal,[edi]\n??fini:\n\tret\n\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(INT code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_WORD C NEAR\n\tUSES\tebx,esi,edi\n\tARG\tcode:WORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\tedi,eax\n\tadd\teax,2\n\tand\teax,0FFh\t\t\t; New KeyBufferTail value.\n\tcmp\t[(KeyboardType PTR esi).KeyBufferHead],eax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[(KeyboardType PTR esi+edi).KeyBuffer],bx\t\t; Record the keystroke.\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\n\tret\n\n??noroom:\n\tmov\teax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_Num C NEAR\n\tUSES\tebx,ecx,edx,edi,esi\n\tARG\tkeycode:DWORD\n\tLOCAL\ttail:DWORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n; for the moment we do not check for the interrupt flag\n;\tmov\teax,2534h \t\t; function to get the interrupt status\n;\tint\t21\t\t\t; eax = interrupt status\n;\tpush\teax\t\t\t; save the result on the stack\n\n\tpushf\t\t\t\t; store off the flags\n\tcli\t\t\t\t; disable interrupts\n\n; We need to set the data segment because we might be being called\n; from within an interrupt\n; Soo, if that is the case then DS & ES point to DGROUP _DATA \n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\teax,[(KeyboardType PTR esi).MouseX]\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\teax,[(KeyboardType PTR esi).MouseY]\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],ax\n\n??cando:\n\tmov\teax,[keycode]\t\t; get the code\n\tor\teax,eax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[(KeyboardType PTR esi).Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[(KeyboardType PTR esi).Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\txor\tebx,ebx\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tebx,1\t\t\t; double for WORD index\n\tmov\tax,[WORD PTR ((KeyboardType PTR esi+ebx).XYAdjust)]\n\n\tmovsx\tebx,ah\n\tmovsx\teax,al\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tedx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tedx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tebx,edx\t\t\t; add speed for y index\n\tmov\tbl,[(KeyboardType PTR esi+ebx).KeyMouseMove] \t; get speed for y delta\n\tmovsx\tebx,bl\n\txchg\tebx,edx\t\t\t; save mouse y delta\n\tadd\tebx,eax\t\t\t; add speed for x index\n\tmov\tal,[(KeyboardType PTR esi+ebx).KeyMouseMove]\t; get speed for x delta\n\tmovsx\teax,al\n\txchg\tebx,edx\t\t\t; restore mouse y delta\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tebx,011b\t\t\t; Y = 1, 0, 3\n\tand\teax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tebx,011b\t\t\t; Y = 3, 0, 1\n\tand\teax,011b\t\t\t; X = 3, 0, 1\n\tshl\tebx,2\n\tor\tebx,eax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tebx,1\n\tmovzx\tebx,[(KeyboardType PTR esi+ebx).EdgeConv]\n\tshl\tebx,2\n\tmov\tax,[(KeyboardType PTR esi+ebx).ScreenEdge]\t; New absolute X\n\tmov\tbx,[(KeyboardType PTR esi+ebx+2).ScreenEdge] ; New absolute Y\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\teax,eax\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tebx,ebx\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseX],ax\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseY],bx\n\tcmp\t[(KeyboardType PTR esi).MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n; PWG: ARRGGGHHHH!\n;\tcall\tLow_Hide_Mouse\n;\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\teax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],eax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tedi,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\t[tail],edi\t\t; Safety record.\n\n\t; Record the base keycode (if there is room).\n\tcwde\t\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\teax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tmovzx\teax,[(KeyboardType esi).LocalMouseX]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tmovzx\teax,[(KeyboardType esi).LocalMouseY]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tebx,0101h\t\t; Bit control tools.\n\tmov\teax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[(KeyboardType PTR esi).KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[(KeyboardType esi).KeyBufferTail],edi\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tmov\tcl,3\n\tshr\tedi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[(KeyboardType esi+edi).KeysUpDown]\n\tje\tshort ??notalready\n\ttest\t[(KeyboardType PTR esi).KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\tedx,[tail]\n\tmov\t[(KeyboardType esi).KeyBufferTail],edx\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[(KeyboardType esi+edi).KeysUpDown],bh\t; Force key bit to zero.\n\tor\t[(KeyboardType esi+edi).KeysUpDown],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\teax,1\n\tjmp\tshort ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\teax,[tail]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\t\t\t; Signal an error.\n\n??exit:\n\tsti\n\tpopf\n\n;\tpopf\n;\tpop\tebx\n;\tor\tebx,ebx\n;\tjz\t??final_exit\n;\tsti\n\n??final_exit:\n\tret\n\n\tENDP\tStuff_Key_Num\n\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles break interrupt for protected mode           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBreak_Interrupt C NEAR\n\n\tiret\n\tENDP\tBreak_Interrupt\n\nIF DEBUG\n;***************************************************************************\n;* DEBUG_INTERRUPT -- Handles debug (INT 3) interrupt for protected mode   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tDebug_Interrupt C NEAR\n\n\t;*==================================================================\n\t;* Setup fake Interrupt entry sequence so that we can execute our\n\t;*   code and then IRET painlessly into the debuggers interrupt\n\t;*   handler.\n\t;*==================================================================\n\tpushfd\t\t\t; Step 1\n\tsub\tesp,8\t\t; Step 2\n\tpush\tebp\t\t; Step 3\n\tmov\tebp,esp\t\t; Set up a stack frame to know where to poke address.\n\n\t;*==================================================================\n\t;* Preserve all of the registers that we intend to use.\n\t;*=======================================Dbg========================\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n\tmov\tax , _DATA\n\tmov\tds , ax\n\tmov\tes , ax\n\tinc\t[BYTE PTR 0B0000h]\n\n\t;*==================================================================\n\t;* Setup the pointers to the real mode data and the protected mode\n\t;*   data and selectors.\n\t;*==================================================================\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t;*==================================================================\n\t;* Do the deed.\n\t;*==================================================================\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\n\t;*==================================================================\n\t;* Now get the address of the real debug handler and poke it into\n\t;*   the stack so we can IRET to it.\n\t;*==================================================================\n\tmov\teax,[(KeyboardType PTR esi).DbgOldPMIOffset]\t; Get orig offset.\n\tmov\tebx,[(KeyboardType PTR esi).DbgOldPMISelector]\t; Get orig selector.\n\tmov\t[ss:ebp+4],eax\t\t\t\t\t; Poke offset.\n\tmov\t[ss:ebp+8],ebx\t\t\t\t\t; Poke selector.\n\n\t;*==================================================================\n\t;* Restore the stack so it looks like we just did an IRET entry\n\t;*==================================================================\n\tpop\tfs gs es ds\n\tpopad\n\tpop\tebp\n\n\t;*==================================================================\n\t;* This iret should go directly to the real debugger handler\n\t;*\tpainlessly and effectively.\n\t;*==================================================================\n\tiretd\n\n\tENDP\tDebug_Interrupt\nENDIF\n\n\n\nIF PROT_INT_ENABLE\n\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Handles input that comes from the keyboard        *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Interrupt C NEAR\n\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n; this is the part of the interrupt that set the segment registers\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov cx, ss\t\t\t\t; get SS\n\tmov [Keyboard_App_Stack_ESP], esp\t; Protect ESP\n\tmov [Keyboard_App_Stack_SS], ecx\t; Protect SS\n\tlea edx, [Keyboard_StackStart ]\t; Compute Local Stack size\n\tand edx, -4 ;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov esp, edx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\t\n\tmov\tedx,[(KeyboardType PTR esi).KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[(KeyboardType PTR esi).KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\ttest\t[BYTE PTR 417H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR 417H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR 496H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tebx,0101H\t\t; set key to a make by default \n\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\t;\n\t; New CODE to montior key stream\n\t;\n\txor\tebx,ebx\n\tmov\tbx,[(KeyboardType PTR esi).KeyStreamIndex]\n\tmov\t[(KeyboardType PTR esi+ebx).KeyStream],al\n\tinc\tebx\n\tand\tebx,15\n\tmov\t[(KeyboardType PTR esi).KeyStreamIndex],bx\n\tmov\tebx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[(KeyboardType PTR esi).LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[(KeyboardType PTR esi).LastKeyE1]\t\t; yes, dec the count\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[(KeyboardType PTR esi).IsExtKey],TRUE\t; it is an extended key\n\n\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtCodes\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).ExtNums-OFFSET (KeyboardType PTR 0).ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\n\tmov\tal,[(OFFSET (KeyboardType PTR 0).ExtNums - OFFSET (KeyboardType PTR 0).ExtCodes) - 1 + edi] ; get the match\n\tmov\t[(KeyboardType PTR esi).IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tedi,eax\t\t\t; use code as an index\n\tand\tedi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[(KeyboardType PTR esi+edi).KeyNums]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[(KeyboardType PTR esi).ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\teax\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\n;------\tSet the shift bit if necessary.\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tshr\tedi,3\n\tmov\tebx,eax\n\tand\tebx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[(KeyboardType PTR esi+ebx).Bits]\t\t; get the bit to test\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[(KeyboardType PTR esi).CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\n\t\t\t\t\t; keyboard buffer.\n\n\tmov\tecx,eax\n\txor\teax,eax\n\tmov\tax,cx\n\n\ttest\tedx,DEBUGINT\n\tjz\t??not_toggle\n\n\tcmp\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\n\tinc\t[BYTE PTR 0B0002h]\n\n\tcmp\teax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\teax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\teax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\t\n\tcmp\teax,125\n\tjne\t??not_toggle\n\n\tinc\t[BYTE PTR 0B0000h]\n\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjmp\t??absorbcode\n\n??not_toggle:\n\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\teax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\teax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\teax,0230h\n\tje\tshort ??breaker\n\tcmp\teax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[(KeyboardType PTR esi).Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n;\tcmp\tax,0420H\t\t; is this an alt s\n;\tjne\tshort ??checkmusic\t; toggle the Sound variable\n;\tpush\tax\n;\tmov\tax,[SoundOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??checkmusic:\n;\tcmp\tax,0434H\t\t; is this an alt m\n;\tjne\tshort ??esc\t\t; toggle the Music variable\n;\tpush\tax\n;\tmov\tax,[MusicOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??esc:\n\n\tpush\teax\n\tcall\tStuff_Key_Num\n\tpop\teax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[(KeyboardType PTR esi).EscRoutine],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\teax\n\tcall\t[(KeyboardType PTR esi).EscRoutine]\n\tpop\teax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tedi,OFFSET (KeyboardType PTR 0).PassAlways\t; get offset to table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd - OFFSET (KeyboardType PTR 0).PassAlways) ; get number of pass always CDY JLB MOD 7/11 was \n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tedi,OFFSET (KeyboardType PTR 0).CondPassKey\t; get offset to cond key table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).CondPassCond-OFFSET (KeyboardType PTR 0).CondPassKey) ; get number of entries\n\tshr\tecx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(OFFSET (KeyboardType PTR 0).CondPassCond - OFFSET (KeyboardType PTR 0).CondPassKey) - 2 + edi]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tedx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\tinc\t[(KeyboardType PTR esi).PassCount]\n\tmov\t[(KeyboardType PTR esi).PMIssuedKeyInt],1     ; Make it TRUE\n\n\t; Now it is time to set up for the call to the System Keyboard\n\t; interrupt handler.\n\t; 1 -Restore System Stack Pointer Selector before exit Interrupt\n\t; 2- We Create a Returning Point from Interrupt by Push A\n \t;    Interupt Stack Frame into the Stack Pointer\n\t; 3- We make a Far jump to the interuupt handler\n\n\tcmp  [Keyboard_StackPointer],0DEADDEADh\n\tje   ??pass_stack_good\n\n\tpush ecx\n\tpush edi\n\tpush eax\n\tmov  edi,0A0000h\n\tmov  ecx,64000\n\tmov  eax,1\n\trep  stosb\n\tpop  eax\n\tpop  edi\n\tpop  ecx\n\n??pass_stack_good:\n\tcli\t\t\t\t       ; disable Interrupts\n\tmov edx, [Keyboard_App_Stack_SS]       \n\tmov ss, dx\t\t\t       ; Set System Stack Selector\n\tmov esp, [Keyboard_App_Stack_ESP]      ; Set System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n\tlea\tedx, [??Call_Back_Keyboard]   ; Get Return address offset\n \tpushfd\t\t\t\t      ; push flags\t\n\tpush\tcs\t\t\t      ; push Code Selector\n\tpush\tedx\t\t\t      ; push Offset\n\n\t; Now we need to simulate an interrup call by using ired\n\t; because we still want to come back here from the\n\t; Old Keyboard interrupt handle.\n\tpushfd\n\tpush\t[(KeyboardType PTR esi).KeyOldPMISelector] ; push orig selector.\n\tpush    [(KeyboardType PTR esi).KeyOldPMIOffset]   ; push orig offset.\n\tiretd\n\n??absorbcode:\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tal,[496h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[496h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\n\tcmp  [Keyboard_StackPointer],0DEADDEADh\n\tje   ??call_stack_good\n\tpush ecx\n\tpush edi\n\tpush eax\n\tmov  edi,0A0000h\n\tmov  ecx,64000\n\tmov  eax,1\n\trep  stosb\n\tpop  eax\n\tpop  edi\n\tpop  ecx\n\n??call_stack_good:\n\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov edx, [Keyboard_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, dx\t\t\t       ; Set System Stack Selector\n\tmov esp, [Keyboard_App_Stack_ESP]      ; Set System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n??Call_Back_Keyboard:\n\tpop\tfs gs es ds\n\tpopad\n\tiret\t\n\n\tENDP\tKeyboard_Interrupt\n\nELSE\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Stub for the keyboard interrupt call real mode    *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\n \nDATASEG\nSTRUC\tRealModeCallStruc\n\t_EDI  DD\t0\n\t_ESI  DD\t0\n\t_EBP  DD\t0\n\t      DD        0\n\t_EBX  DD\t0\n\t_EDX  DD\t0\n\t_ECX  DD\t0\n\t_EAX  DD        0\n\tFLAGS DW\t0\n\t_ES   DW\t0\n\t_DS   DW\t0\n\t_FS   DW\t0\n\t_GS   DW\t0\n\t_IP   DW\t0\n\t_CS   DW\t0\n\t_SP   DW\t0\n\t_SS   DW\t0\n\t      dd\t0\n\t      dd\t0\n  nothing     dd\t0\t\nENDS \n\nRMDS RealModeCallStruc  <>\n\nCODESEG\n\nPROC\tKeyboard_Interrupt\tNear\n\n; This option of the keyboard interrupt handle will not be\n; available at this moment because the light version of Rational System DOS\n; Extender do not allow a DPMI real mode call which is\n; DMPI INT 31h funtion 0301h\n\n\tpushad\t\n\tpush\tfs gs es ds\n\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\n\tlea\tedi , [ RMDS ]\n\tlea\tecx , [ RMDS . nothing ]\n\tsub\tecx , edi\n\txor\teax , eax\n\tshr\tecx , 2\n\trep\tstosd\n\t\n\tmov\teax , 0300h\n\tmov\tbl , [ byte ptr RMVector ]\n\txor\tbh , bh\n\txor\tcx , cx\n\tlea\tedi , [RMDS]\n\tint\tDPMI_INTR\n\n; this is here only for testing to make sure\n; that a real mode interrupt is bieng issued. \nmov\tax , _DATA\nmov\tes , ax\nmov\tds , ax\nmov [ byte ptr 0b0000h + 10 * 80 + 40 ] , 040h\njc\t??error\nmov [ byte ptr 0b0000h + 10 * 80 + 42 ] , 041h\n\n??error:\n\tpop\tds es gs fs\n\tpopad\t\n\tiretd\n\tENDP\n\nENDIF\n\nLABEL \tLockedCodeEnd\t\tBYTE\n\n;***************************************************************************\n;* End of File.\t\t\t\t\t\t\t\t   *\n;***************************************************************************\nEND\n\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/KEYBOARD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : KEYBOARD.H                               *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : July 13, 1994                            *\n *                                                                         *\n *                  Last Update : July 13, 1994   [PWG]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef KEYBOARD_H\n#define KEYBOARD_H\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n\nextern \"C\" {\n\tvoid Install_Keyboard_Interrupt(void *addr, long size);\n\tvoid Install_Page_Fault_Handle(void) ;\n\tvoid\t*Get_RM_Keyboard_Address(void);\n\tlong\tGet_RM_Keyboard_Size(void);\n\tvoid\tRemove_Keyboard_Interrupt(void);\n\tint\tCheck_Key_Num(void);\n\tint\tCheck_Key_Bits(void);\n\tint\tCheck_Key(void);\n\tshort\tGet_Key_Num(void);\n\tshort\tGet_Key_Bits(void);\n\tint\tGet_Key(void);\n\tint\tKN_To_KA(int keynum);\n\tint\tKeyboard_Attributes_On(int key_flags);\n\tint\tKeyboard_Attributes_Off(int key_flags);\n\tvoid\tClear_KeyBuffer(void);\n\tint\tKey_Down(int key);\n\tint\tKey_Satisfied(int key);\n\tvoid\tStuff_Key_WORD(int code);\n\tvoid\tStuff_Key_Num(int key);\n\tint   Install_Mouse(int max_width, int max_height, int scr_width, int scr_height);\n\tvoid\tReset_Mouse (void) ;\n\tvoid\tRemove_Mouse(void);\n\tint\tGet_Mouse_State(void);\n\tint\tGet_Mouse_X(void);\n\tint\tGet_Mouse_Y(void);\n\tint\tGet_Mouse_Disabled(void);\n\tvoid  *Set_Mouse_Cursor(int xhotspot,\tint yhotspot,\tvoid *cursor);\n\tvoid\tHide_Mouse(void);\n\tvoid\tShow_Mouse(void);\n\tvoid\tConditional_Hide_Mouse(int sx_pixel, int sy_pixel, int dx_pixel, int dy_pixel);\n\tvoid\tConditional_Show_Mouse(void);\n\n\n\tvoid  __interrupt far Keyboard_Interrupt(void);\n\textern int MouseQX;\n\textern int MouseQY;\n\n}\n\n\nenum {\n\tREPEATON     = 0x0001,\t/* 1:all makes into buffer, 0:only 1st make */\n\tTRACKEXT     = 0x0002,\t/* 1:Home != keypad Home, 0:Home=keypad Home */\n\tFILTERONLY   = 0x0004,\t/* 1:Normal BIOS operation with filter */\n\tCTRLALTTURBO = 0x0010,\t/* 1:Allow turbo up and down in application */\n\tNONUMLOCK    = 0x0200,\t/* 1:do NOT remap keypad to numbers */\n\tTASKSWITCHABLE = 0x400, /* 1:allows task switching keys thru ALT-TAB, */\n\t\t\t\t\t\t\t\t\t/*   ALT-ESC,CTRL-ESC */\n\tPASSBREAKS\t = 0x0800,\t// Pass all breaks to the keyboard buffer.\n\n\t/* The following flags, if turned on, should only be used for\n\t   debugging purposes (remember to take out the calls when BETA */\n\n\tCTRLSON      = 0x0008,\t/* 1:pass scroll lock sequence into BIOS */\n\tCTRLCON      = 0x0020,\t/* 1:pass stop code to BIOS */\n\tSCROLLLOCKON = 0x0040,\t/* 1:pass scroll lock key into BIOS */\n\tPAUSEON      = 0x0080,\t/* 1:pass the pause key and seq to BIOS */\n\t\t\t\t\t\t\t\t\t/*   make sure FILTERONLY is set */\n\tBREAKON      = 0x0100,\t/* 1:pass the ctrl break seq to BIOS */\n\tKEYMOUSE     = 0x1000,\t/* 1:keypad translates into mouse moves */\n\tSIMLBUTTON   = 0x2000,\t/* 1:have space and enter keys simulate Left */\n\t\t\t\t\t\t\t\t\t/*   mouse button when KEYMOUSE is set */\n\tDEBUGINT\t\t = 0x4000\t/* Use scroll lock to disable keyboard int */\n};\n\n\n/*\n**\tThese are the codes for the various key codes that are returned from the\n**\tkeyboard input routines Get_Key() and Input_ASCII().\n*/\ntypedef enum {\n\tKA_CTRL_AT = 0,\n\tKA_CTRL_A,\n\tKA_MORE = KA_CTRL_A,\n\tKA_CTRL_B,\n\tKA_SETBKGDCOL = KA_CTRL_B,\n\tKA_CTRL_C,\n\tKA_CTRL_D,\n\tKA_CTRL_E,\n\tKA_CTRL_F,\n\tKA_SETFORECOL = KA_CTRL_F,\n\tKA_CTRL_G,\n\tKA_CTRL_H,\n\tKA_BACKSPACE = KA_CTRL_H,\n\tKA_CTRL_I,\n\tKA_TAB = KA_CTRL_I,\n\tKA_CTRL_J,\n\tKA_CTRL_K,\n\tKA_CTRL_L,\n\tKA_FORMFEED = KA_CTRL_L,\n\tKA_CTRL_M,\n\tKA_RETURN = KA_CTRL_M,\n\tKA_CTRL_N,\n\n\tKA_CTRL_O,\n\tKA_CTRL_P,\n\tKA_CTRL_Q,\n\tKA_CTRL_R,\n\tKA_CTRL_S,\n\tKA_SPCTAB = KA_CTRL_S,\n\tKA_CTRL_T,\n\tKA_CTRL_U,\n\tKA_CTRL_V,\n\tKA_CTRL_W,\n\tKA_CTRL_X,\n\tKA_SETX = KA_CTRL_X,\n\tKA_CTRL_Y,\n\tKA_SETY = KA_CTRL_Y,\n\tKA_CTRL_Z,\n\tKA_CTRL_LBRACKET,\n\tKA_ESC = KA_CTRL_LBRACKET,\n\tKA_EXTEND = KA_ESC,\n\tKA_CTRL_BACKSLASH,\n\tKA_CTRL_RBRACKET,\n\tKA_LITERAL = KA_CTRL_RBRACKET,\n\tKA_CTRL_CARROT,\n\tKA_CTRL_UNDERLINE,\n\n\tKA_SPACE,\t\t\t\t\t\t\t\t\t/*   */\n\tKA_EXCLAMATION,\t\t\t\t\t\t\t/* ! */\n\tKA_DQUOTE,\t\t\t\t\t\t\t\t\t/* \" */\n\tKA_POUND,\t\t\t\t\t\t\t\t\t/* # */\n\tKA_DOLLAR,\t\t\t\t\t\t\t\t\t/* $ */\n\tKA_PERCENT,\t\t\t\t\t\t\t\t\t/* % */\n\tKA_AMPER,\t\t\t\t\t\t\t\t\t/* & */\n\tKA_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKA_LPAREN,\t\t\t\t\t\t\t\t\t/* ( */\n\tKA_RPAREN,\t\t\t\t\t\t\t\t\t/* ) */\n\tKA_ASTERISK,\t\t\t\t\t\t\t\t/* * */\n\tKA_PLUS,\t\t\t\t\t\t\t\t\t\t/* + */\n\tKA_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKA_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKA_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKA_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKA_0, KA_1, KA_2, KA_3, KA_4, KA_5, KA_6, KA_7, KA_8, KA_9,\n\tKA_COLON,\t\t\t\t\t\t\t\t\t/* : */\n\tKA_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKA_LESS_THAN,\t\t\t\t\t\t\t\t/* < */\n\tKA_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\tKA_GREATER_THAN,\t\t\t\t\t\t\t/* > */\n\tKA_QUESTION,\t\t\t\t\t\t\t\t/* ? */\n\n\tKA_AT,\t\t\t\t\t\t\t\t\t\t/* @ */\n\tKA_A,\t\t\t\t\t\t\t\t\t\t\t/* A */\n\tKA_B,\t\t\t\t\t\t\t\t\t\t\t/* B */\n\tKA_C,\t\t\t\t\t\t\t\t\t\t\t/* C */\n\tKA_D,\t\t\t\t\t\t\t\t\t\t\t/* D */\n\tKA_E,\t\t\t\t\t\t\t\t\t\t\t/* E */\n\tKA_F,\t\t\t\t\t\t\t\t\t\t\t/* F */\n\tKA_G,\t\t\t\t\t\t\t\t\t\t\t/* G */\n\tKA_H,\t\t\t\t\t\t\t\t\t\t\t/* H */\n\tKA_I,\t\t\t\t\t\t\t\t\t\t\t/* I */\n\tKA_J,\t\t\t\t\t\t\t\t\t\t\t/* J */\n\tKA_K,\t\t\t\t\t\t\t\t\t\t\t/* K */\n\tKA_L,\t\t\t\t\t\t\t\t\t\t\t/* L */\n\tKA_M,\t\t\t\t\t\t\t\t\t\t\t/* M */\n\tKA_N,\t\t\t\t\t\t\t\t\t\t\t/* N */\n\tKA_O,\t\t\t\t\t\t\t\t\t\t\t/* O */\n\n\tKA_P,\t\t\t\t\t\t\t\t\t\t\t/* P */\n\tKA_Q,\t\t\t\t\t\t\t\t\t\t\t/* Q */\n\tKA_R,\t\t\t\t\t\t\t\t\t\t\t/* R */\n\tKA_S,\t\t\t\t\t\t\t\t\t\t\t/* S */\n\tKA_T,\t\t\t\t\t\t\t\t\t\t\t/* T */\n\tKA_U,\t\t\t\t\t\t\t\t\t\t\t/* U */\n\tKA_V,\t\t\t\t\t\t\t\t\t\t\t/* V */\n\tKA_W,\t\t\t\t\t\t\t\t\t\t\t/* W */\n\tKA_X,\t\t\t\t\t\t\t\t\t\t\t/* X */\n\tKA_Y,\t\t\t\t\t\t\t\t\t\t\t/* Y */\n\tKA_Z,\t\t\t\t\t\t\t\t\t\t\t/* Z */\n\tKA_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKA_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\tKA_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKA_CARROT,\t\t\t\t\t\t\t\t\t/* ^ */\n\tKA_UNDERLINE,\t\t\t\t\t\t\t\t/* _ */\n\n\tKA_GRAVE,\t\t\t\t\t\t\t\t\t/* ` */\n\tKA_a,\t\t\t\t\t\t\t\t\t\t\t/* a */\n\tKA_b,\t\t\t\t\t\t\t\t\t\t\t/* b */\n\tKA_c,\t\t\t\t\t\t\t\t\t\t\t/* c */\n\tKA_d,\t\t\t\t\t\t\t\t\t\t\t/* d */\n\tKA_e,\t\t\t\t\t\t\t\t\t\t\t/* e */\n\tKA_f,\t\t\t\t\t\t\t\t\t\t\t/* f */\n\tKA_g,\t\t\t\t\t\t\t\t\t\t\t/* g */\n\tKA_h,\t\t\t\t\t\t\t\t\t\t\t/* h */\n\tKA_i,\t\t\t\t\t\t\t\t\t\t\t/* i */\n\tKA_j,\t\t\t\t\t\t\t\t\t\t\t/* j */\n\tKA_k,\t\t\t\t\t\t\t\t\t\t\t/* k */\n\tKA_l,\t\t\t\t\t\t\t\t\t\t\t/* l */\n\tKA_m,\t\t\t\t\t\t\t\t\t\t\t/* m */\n\tKA_n,\t\t\t\t\t\t\t\t\t\t\t/* n */\n\tKA_o,\t\t\t\t\t\t\t\t\t\t\t/* o */\n\n\tKA_p,\t\t\t\t\t\t\t\t\t\t\t/* p */\n\tKA_q,\t\t\t\t\t\t\t\t\t\t\t/* q */\n\tKA_r,\t\t\t\t\t\t\t\t\t\t\t/* r */\n\tKA_s,\t\t\t\t\t\t\t\t\t\t\t/* s */\n\tKA_t,\t\t\t\t\t\t\t\t\t\t\t/* t */\n\tKA_u,\t\t\t\t\t\t\t\t\t\t\t/* u */\n\tKA_v,\t\t\t\t\t\t\t\t\t\t\t/* v */\n\tKA_w,\t\t\t\t\t\t\t\t\t\t\t/* w */\n\tKA_x,\t\t\t\t\t\t\t\t\t\t\t/* x */\n\tKA_y,\t\t\t\t\t\t\t\t\t\t\t/* y */\n\tKA_z,\t\t\t\t\t\t\t\t\t\t\t/* z */\n\tKA_LBRACE,\t\t\t\t\t\t\t\t\t/* { */\n\tKA_BAR,\t\t\t\t\t\t\t\t\t\t/* | */\n\tKA_RBRACE,\t\t\t\t\t\t\t\t\t/* ] */\n\tKA_TILDA,\t\t\t\t\t\t\t\t\t/* ~ */\n\tKA_DEL,\t\t\t\t\t\t\t\t\t\t/* not used */\n\n\tKA_ALT_F10 = 143,\n\tKA_ALT_F9,    KA_ALT_F8,   KA_ALT_F7,   KA_ALT_F6,   KA_ALT_F5,\n\tKA_ALT_F4,    KA_ALT_F3,   KA_ALT_F2,   KA_ALT_F1,\n\n\tKA_CTRL_F10,  KA_CTRL_F9,  KA_CTRL_F8,  KA_CTRL_F7,  KA_CTRL_F6,\n\tKA_CTRL_F5,   KA_CTRL_F4,  KA_CTRL_F3,  KA_CTRL_F2,  KA_CTRL_F1,\n\n\tKA_SHIFT_F10, KA_SHIFT_F9, KA_SHIFT_F8, KA_SHIFT_F7, KA_SHIFT_F6,\n\tKA_SHIFT_F5,  KA_SHIFT_F4, KA_SHIFT_F3, KA_SHIFT_F2, KA_SHIFT_F1,\n\n\tKA_DELETE,\t\t\t\t\t\t\t\t\t/* <DELETE> */\n\tKA_INSERT,\t\t\t\t\t\t\t\t\t/* <INSERT> */\n\tKA_PGDN,\t\t\t\t\t\t\t\t\t\t/* <PAGE DOWN> */\n\tKA_DOWNRIGHT = KA_PGDN,\n\tKA_DOWN,\t\t\t\t\t\t\t\t\t\t/* <DOWN ARROW> */\n\tKA_END,\t\t\t\t\t\t\t\t\t\t/* <END> */\n\tKA_DOWNLEFT = KA_END,\n\n\tKA_RESERVED1,\n\n\tKA_RIGHT,\t\t\t\t\t\t\t\t\t/* <RIGHT ARROW> */\n\tKA_KEYPAD5,\t\t\t\t\t\t\t\t\t/* NUMERIC KEY PAD <5> */\n\tKA_LEFT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ARROW> */\n\n\tKA_RESERVED2,\n\n\tKA_PGUP,\t\t\t\t\t\t\t\t\t\t/* <PAGE UP> */\n\tKA_UPRIGHT = KA_PGUP,\n\tKA_UP,\t\t\t\t\t\t\t\t\t\t/* <UP ARROW> */\n\tKA_HOME,\t\t\t\t\t\t\t\t\t\t/* <HOME> */\n\tKA_UPLEFT = KA_HOME,\n\t\n\tKA_RESERVED3,\n\tKA_RESERVED4,\n\n\tKA_F10, KA_F9, KA_F8, KA_F7, KA_F6, KA_F5, KA_F4, KA_F3, KA_F2, KA_F1,\n\n\tKA_LMOUSE,\n\tKA_RMOUSE,\n\tKA_JBUTTON1,\n\tKA_JBUTTON2,\n\tKA_J_UP,\n\tKA_J_RIGHT,\n\tKA_J_DOWN,\n\tKA_J_LEFT,\n\n\tKA_SHIFT_BIT = 0x0100,\n\tKA_CTRL_BIT  = 0x0200,\n\tKA_ALT_BIT   = 0x0400,\n\tKA_RLSE_BIT  = 0x0800,\n\tKA_LCOMM_BIT = 0x1000,\t\t\t\t\t/* Amiga Left Comm key\t*/\n\tKA_RCOMM_BIT = 0x2000\t\t\t\t\t/* Amiga Right Comm key\t*/\n} KeyASCIIType;\n\n/*\n**\tThese are the keyboard codes that are returned from the input routines\n**\tGet_Key_Num and Input_Num.\n*/\ntypedef enum {\n\tKN_NONE = 0,\n\tKN_GRAVE = 1,\t\t\t\t\t\t\t\t/* ` */\n\tKN_1, KN_2, KN_3, KN_4, KN_5, KN_6, KN_7, KN_8, KN_9, KN_0,\n\tKN_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKN_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\n\tKN_RESERVED1,\n\n\tKN_BACKSPACE,\t\t\t\t\t\t\t\t/* <BACKSPACE> */\n\n\tKN_TAB,\t\t\t\t\t\t\t\t\t\t/* <TAB> */\n\tKN_Q, KN_W, KN_E, KN_R, KN_T, KN_Y, KN_U, KN_I, KN_O, KN_P,\n\tKN_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKN_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKN_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\n\tKN_CAPSLOCK,\t\t\t\t\t\t\t\t/* <CAPS LOCK> */\n\tKN_A, KN_S, KN_D, KN_F, KN_G, KN_H, KN_J, KN_K, KN_L,\n\tKN_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKN_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKN_BACKSLASH2,\n\tKN_RETURN,\t\t\t\t\t\t\t\t\t/* <RETURN> or <ENTER> */\n\n\tKN_LSHIFT,\t\t\t\t\t\t\t\t\t/* <LEFT SHIFT> */\n\n\tKN_MOUSE_MOVE,\t\t\t\t\t\t\t\t// Indicate a mouse move (for playback of\n\n\tKN_Z, KN_X, KN_C, KN_V, KN_B, KN_N, KN_M,\n\tKN_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKN_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKN_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKN_RESERVED3,\n\n\tKN_RSHIFT,\t\t\t\t\t\t\t\t\t/* <RIGHT SHIFT> */\n\n\tKN_LCTRL,\t\t\t\t\t\t\t\t\t/* <LEFT CTRL> */\n\tKN_LCOMM,\t\t\t\t\t\t\t\t\t/* for AMIGA */\n\tKN_LALT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ALT> */\n\tKN_SPACE,\t\t\t\t\t\t\t\t\t/* <SPACE BAR> */\n\tKN_RALT,\t\t\t\t\t\t\t\t\t\t/* <RIGHT ALT> */\n\tKN_RCOMM,\t\t\t\t\t\t\t\t\t/* for AMIGA */\n\tKN_RCTRL,\t\t\t\t\t\t\t\t\t/* <RIGHT CTRL> */\n\t\t\t\t\t\t\t/* the following are forced into key buffer */\n\tKN_LMOUSE,\n\tKN_RMOUSE,\n\tKN_JBUTTON1,\n\tKN_JBUTTON2,\n\tKN_J_UP,\n\tKN_J_RIGHT,\n\tKN_J_DOWN,\n\tKN_J_LEFT,\n\n\tKN_SPECIAL9,\n\n\tKN_SPECIAL10,\n\n\tKN_E_INSERT,\t\t\t\t\t\t\t\t/* extended <INSERT> */\n\tKN_E_DELETE,\t\t\t\t\t\t\t\t/* extended <DELETE> */\n\n\tKN_RESERVED4,\n\tKN_RESERVED5,\n\n\tKN_E_LEFT,\t\t\t\t\t\t\t\t\t/* extended <LEFT ARROW> */\n\tKN_E_HOME,\t\t\t\t\t\t\t\t\t/* extended <HOME> */\n\tKN_E_END,\t\t\t\t\t\t\t\t\t/* extended <END> */\n\n\tKN_RESERVED6,\n\n\tKN_E_UP,\t\t\t\t\t\t\t\t\t\t/* extended <UP ARROW> */\n\tKN_E_DOWN,\t\t\t\t\t\t\t\t\t/* extended <DOWN ARROW> */\n\tKN_E_PGUP,\t\t\t\t\t\t\t\t\t/* extended <PAGE UP> */\n\tKN_E_PGDN,\t\t\t\t\t\t\t\t\t/* extended <PAGE DOWN> */\n\tKN_K_LPAREN,\t\t\t/* for AMIGA */\n\tKN_K_RPAREN,\t\t\t/* for AMIGA */\n\tKN_E_RIGHT,\t\t\t\t\t\t\t\t\t/* extended <RIGHT ARROW> */\n\n\tKN_NUMLOCK,\t\t\t\t\t\t\t\t\t/* <NUM LOCK> */\n\tKN_HOME,\t\t\t\t\t\t\t\t\t\t/* num key pad 7 */\n\tKN_UPLEFT = KN_HOME,\n\tKN_LEFT,\t\t\t\t\t\t\t\t\t\t/* num key pad 4 */\n\tKN_END,\t\t\t\t\t\t\t\t\t\t/* num key pad 1 */\n\tKN_DOWNLEFT = KN_END,\n\n\tKN_RESERVED7,\n\n\tKN_KEYPAD_SLASH,\t\t\t\t\t\t\t/* num key pad / */\n\tKN_UP,\t\t\t\t\t\t\t\t\t\t/* num key pad 8 */\n\tKN_CENTER,\t\t\t\t\t\t\t\t\t/* num key pad 5 */\n\tKN_DOWN,\t\t\t\t\t\t\t\t\t\t/* num key pad 2 */\n\tKN_INSERT,\t\t\t\t\t\t\t\t\t/* num key pad 0 */\n\tKN_KEYPAD_ASTERISK,\t\t\t\t\t\t/* num key pad * */\n\tKN_PGUP,\t\t\t\t\t\t\t\t\t\t/* num key pad 9 */\n\tKN_UPRIGHT = KN_PGUP,\n\tKN_RIGHT,\t\t\t\t\t\t\t\t\t/* num key pad 6 */\n\tKN_PGDN,\t\t\t\t\t\t\t\t\t\t/* num key pad 3 */\n\tKN_DOWNRIGHT = KN_PGDN,\n\tKN_DELETE,\t\t\t\t\t\t\t\t\t/* num key pad . */\n\tKN_KEYPAD_MINUS,\t\t\t\t\t\t\t/* num key pad - */\n\tKN_KEYPAD_PLUS,\t\t\t\t\t\t\t/* num key pad + */\n\n\tKN_RESERVED8,\n\n\tKN_KEYPAD_RETURN,\t\t\t\t\t\t\t/* num key pad <ENTER> */\n\n\tKN_RESERVED9,\n\n\tKN_ESC,\n\tKN_HELP,\t\t\t\t\t\t\t\t\t\t/* for AMIGA */\n\tKN_F1, KN_F2, KN_F3, KN_F4, KN_F5, KN_F6, KN_F7, KN_F8, KN_F9, KN_F10,\n\tKN_F11,\n\tKN_F12,\n\tKN_PRNTSCRN,\t\t\t\t\t\t\t\t/* <PRINT SCRN> */\n\tKN_SCROLLLOCK,\t\t\t\t\t\t\t\t/* <SCROLL LOCK> */\n\tKN_PAUSE,\t\t\t\t\t\t\t\t\t/* <PAUSE> */\n\n\tKN_SHIFT_BIT = 0x0100,\n\tKN_CTRL_BIT  = 0x0200,\n\tKN_ALT_BIT   = 0x0400,\n\tKN_RLSE_BIT  = 0x0800,\n\tKN_LCOMM_BIT = 0x1000,\t\t\t\t\t/* Amiga Left Comm key\t*/\n\tKN_RCOMM_BIT = 0x2000,\t\t\t\t\t/* Amiga Right Comm key\t*/\n\tKN_BUTTON    = 0x8000\t\t\t\t\t/* Amiga Right Comm key\t*/\n} KeyNumType;\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/KEYBOARD.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : KEYBOARD.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 12, 1994                            *\n;*                                                                         *\n;*                  Last Update : July 12, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Contains all the defines used by the keyboard interrupt for assembly    *\n;*   includes.                                                             *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nTRUE\t\tEQU\t1\t\t\t; numerical true\nFALSE\t\tEQU\t0\t\t\t; numerical false\nDEBUG\t\tEQU\t1\n\nMAX_X_PIXEL\t\tEQU\t319\nMAX_Y_PIXEL\t\tEQU\t199\n\n\nKN_RESERVED1\t\tEQU\t14\nKN_RESERVED2\t\tEQU\t45\nKN_RESERVED3\t\tEQU\t56\n\n\n; these two are reserved for AMIGA open and close.\nKN_LCOMM\t\tEQU\t59\nKN_RCOMM\t\tEQU\t63\n\nKN_LMOUSE\t\tEQU\t65\nKN_RMOUSE\t\tEQU\t66\nKN_JBUTTON1\t\tEQU\t67\nKN_JBUTTON2\t\tEQU\t68\nKN_J_UP\t\t\tEQU\t69\nKN_J_RIGHT\t\tEQU\t70\nKN_J_DOWN\t\tEQU\t71\nKN_J_LEFT\t\tEQU\t72\n\nKN_LEFT\t\t\tEQU\t92\nKN_UPLEFT\t\tEQU\t91\nKN_UP\t\t\tEQU\t96\nKN_UPRIGHT\t\tEQU\t101\nKN_RIGHT\t\tEQU\t102\nKN_DOWNRIGHT\t\tEQU\t103\nKN_DOWN\t\t\tEQU\t98\nKN_DOWNLEFT\t\tEQU\t93\nKN_CENTER\t\tEQU\t97\n\nKN_INSERT\t\tEQU\t99\nKN_DELETE\t\tEQU\t104\n\nKN_RETURN\t\tEQU\t43\nKN_SPACE\t\tEQU\t61\nKN_KEYPAD_RETURN\tEQU\t108\n\n\n; these two are reserved for AMIGA K left and right paren\nKN_KLPAREN\t\tEQU\t87\nKN_KRPAREN\t\tEQU\t88\n\n\nKN_NUMLOCK\t\tEQU\t90\n\nKN_SCROLLOCK\t\tEQU\t125\t\t; key ignored by the logging system\n\nKN_MOUSE_MOVE\tEQU\t45\t; Indicate a mouse move (for playback of logged data)\n\n; ----------------------------------------------------------------\n; flags used in Keyflags to customize keystroke interrupt.\n\nREPEATON\tEQU\t0001H\t; 1:all makes into buffer, 0:only 1st make\nTRACKEXT\tEQU\t0002H\t; 1:Home != keypad Home, 0:Home=keypad Home\nFILTERONLY\tEQU\t0004H\t; 1:Normal BIOS operation with filter\nCTRLSON\t\tEQU\t0008H\t; 1:pass scroll lock sequence into BIOS\nCTRLALTTURBO\tEQU\t0010H\t; 1:Allow turbo up and down in application\nCTRLCON\t\tEQU\t0020H\t; 1:pass stop code to BIOS\nSCROLLLOCKON\tEQU\t0040H\t; 1:pass scroll lock key into BIOS\nPAUSEON\t\tEQU\t0080H\t; 1:pass the pause key and seq to BIOS\nBREAKON\t\tEQU\t0100H\t; 1:pass the ctrl break seq to BIOS\nNONUMLOCK\tEQU\t0200H\t; 1:do NOT remap keypad to numbers\nTASKSWITCHABLE\tEQU\t0400H\t; 1:allows task switching keys thru ALT-TAB,\n\t\t\t\t;   ALT-ESC,CTRL-ESC\nPASSBREAKS\tEQU\t0800H\t; 1:Pass all break codes to keyboard buffer.\nKEYMOUSE\tEQU\t1000H\t; 1:Numeric keypad moves mouse\nSIMLBUTTON\tEQU\t2000H\t; 1:have space and enter keys simulate Left\nDEBUGINT\tEQU\t4000H\t;   mouse button when KEYMOUSE is set\n\n\nSHIFTPRESS\tEQU\t001H\t; bit 0 for shift key pressed\nCTRLPRESS\tEQU\t002H\t; bit 1 for ctrl key pressed\nALTPRESS\tEQU\t004H\t; bit 2 for alt key pressed\nKEYRELEASE\tEQU\t008H\t; bit 3 for key released\nNOTKEYRELEASE\tEQU\t0F7H\t; not of key released\n\nCAPSLOCK\tEQU\t00001H\t; bit 0 for caps locked\nNUMLOCK\tEQU\t00002H\t; bit 1 for num locked\n\n\n\nCLEARISR\tEQU\t020H\t; value to clear In Service Register\nDOS\t\tEQU \t021H\nINTCHIP0\tEQU\t020H\t; 8259 interrupt chip controller 0\nKEYCTRL\t\tEQU\t061H\t; control bits for KB sense data\nKEYDATA\t\tEQU\t060H\t; keyboard scan code port\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/KEYIPROT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : KEYINTR.ASM                              *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   KeyNum_Translate -- Translates the given keynum to ???                *\n;*   Install_Interrupt -- Installs the keyboard interrupt                  *\n;*   Stuff_Key_Word -- Stuffs a word of data into keyboard buffer          *\n;*   Stuff_Key_Num -- Stuffs a key num code into the circular buffer       *\n;*   Remove_Interrupt -- Removes the keyboard interrupt and restores the chai*\n;*   Keystroke_Interrupt -- Handles input that comes from the keyboard     *\n;*   Break_Interrupt -- Handles the break key interrupt                    *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tKeyboard driver -- 8086 Assembly portion;\t\t\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   *\n;***************************************************************************\n\n;---------------------------------------------------------------------------\n; Set the assembly directives\n;---------------------------------------------------------------------------\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386N\t\t\t\t; use 386 real mode instructions\nMODEL TINY\t\t\t; code must be tiny so it fits\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keyboard.inc\"\n\nCODESEG\n\n\nSoundOn\t\tDW\t1\t; toggled by alt S\nMusicOn\t\tDW\t1\t; toggled by alt M\nKeyFlags\tDW\tREPEATON+CTRLALTTURBO\t; all but repeat for now\n\n\nBreak\t\tDW\t0\n\nKeyMouseMove\tDB\t-1,0,1\n\t\tDB\t-16,0,16\n\nScreenEdge\tDW\t320/2,0\t\t; North\n\t\tDW\t319,0\t\t; North-East\n\t\tDW\t319,138/2\t; East\n\t\tDW\t319,137\t\t; South-East\n\t\tDW\t320/2,137\t; South\n\t\tDW\t0,137\t\t; South-West\n\t\tDW\t0,138/2\t\t; West\n\t\tDW\t0,0\t\t; North-West\n\t\tDW\t320/2,138/2\t; Center\n\n\nBits\t\tDB\t01H,02H,04H,08H,10H,20H,40H,80H\n\nCondPassKey\tDW\t0220H, 0320H, 060CH, 070DH, 066AH\n\t\tDW\t0669H, 0230H, 0330H, 007DH, 017DH\n\t\tDW\t025AH, 035AH, 0200H, 0410H, 046EH\n\t\tDW\t026EH, 007CH\n\nCondPassCond\tDW\tCTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO\n\t\tDW\tCTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON\n\t\tDW\tPAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE\n\t\tDW\tTASKSWITCHABLE, BREAKON\n\nEscRoutine\tDD\t0\t; vector to execute on esc key press (0=none)\n\n; Extended raw keycodes to be converted to Westwood keycodes.\nExtCodes\tDB\t038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H\n\t\tDB\t051H,04DH,035H,01CH,037H\n\t\tDB\t046H\n; The matching Westwood keycodes.\nExtNums\t\tDB\t62,  64,  75,  76,  79,  80,  81,  83,  84,  85\n\t\tDB\t86,  89,  95, 108, 124,  0\n; If extended mapping is disabled, then these codes really are...\nExtRemap\tDB\t60,  58,  99, 104,  92,  91,  93,  96,  98, 101\n\t\tDB\t103, 102, 55,  43, 124,  0\nExtRemapEnd\tDB\t0\n\nExtKeyboard\tDB\t0\t; flag for 101/102-key keyboard\n\n\nKeyBuffer\tDW\t128 DUP(0) ; set to empty\nKeyBufferHead\tDW\t0\t; set to first entry\nKeyBufferTail\tDW\t0\t; set to head for empty buffer\nKeyLock\t\tDW\t0\t; num and caps lock bits\nKeyNums\t\tDB\t127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016\n\t\tDB\t017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032\n\t\tDB\t033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049\n\t\tDB\t050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116\n\t\tDB\t117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093\n\t\tDB\t098,103,099,104,127,127,127,122,123\n\nKeysCapsLock\tDB\t0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0\nKeysNumLock\tDB\t0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0\nKeysUpDown\tDB\t16 DUP(0) ; set to all keys up\nKeyStream\tDB\t16 DUP(0) ; set to all keys up\nPassCount\tDW\t0\nKeyStreamIndex\tDW\t0\nLastKeyE0\tDB\t0\nLastKeyE1\tDB\t0\n\n;\n; Westwood key number values of keys to pass through\n;\n;\t\t\tCAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT,\n;\t\t\tRIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN\nPassAlways\tDB\t30, 44, 57, 58, 60, 62, 64, 90, 128, 128\nPassAlwaysEnd\tDB\t128\t\t; invalid code to END PassAlways\nCtrlFlags\tDB\t0\n\nBuffer\t\tDW\t?\nTime\t\tDW\t?\n\nADJUST\t= 1\t\t\t; do not modify DRD\n\nXYAdjust\tDB\t-ADJUST, -ADJUST\t; 91 -> upleft\n\t\tDB\t-ADJUST,  0\t\t; 92 -> left\n\t\tDB\t-ADJUST,  ADJUST\t; 93 -> downleft\n\t\tDB\t 0,  0\t\t\t; 94 illegal\n\t\tDB\t 0,  0\t\t\t; 95 illegal\n\t\tDB\t 0, -ADJUST\t\t; 96 -> up\n\t\tDB\t 0,  0\t\t\t; 97 illegal (center)\n\t\tDB\t 0,  ADJUST\t\t; 98 -> down\n\t\tDB\t 0,  0\t\t\t; 99 illegal\n\t\tDB\t 0,  0\t\t\t; 100 illegal\n\t\tDB\t ADJUST, -ADJUST\t; 101 -> upright\n\t\tDB\t ADJUST,  0\t\t; 102 -> right\n\t\tDB\t ADJUST,  ADJUST\t; 103 -> downright\nEdgeConv\tDW\t8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7\n\nMouseUpdate\t\tDW\t0\nMouseX\t\t\tDW\t0\nLocalMouseX\t\tDW\t0\nMouseY\t\t\tDW\t0\nLocalMouseY\t\tDW\t0\nButton\t\t\tDW\t0\nIsExtKey\t\tDB\t0\nExtIndex\t\tDW\t0\n\nOldRMI\t\t\tDD\t0\t; The origianl RM interrupt seg:off.\nOldPMIOffset\t\tDD\t0\t; The origianl PM interrupt offset\t\t\nOldPMISelector\t\tDD\t0\t; The original PM interrupt segment.\n\nCodeOffset\t\tDW\tRM_Keystroke_Interrupt\t; Offset of the code in the RM stuff.\nCallRMIntOffset\t\tDW\tCall_Interrupt_Chain\t\t; Offset of function to call DOS timer interrupt.\nCallRMIntAddr\t\tDD\t0\t; PM address of CallRealIntOffset for speed.\n\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Translates the given keynum to ???                  *\n;*                                                                         *\n;* INPUT:\tUWORD the keynum to translate\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated keynum                                 *\n;*                                                                         *\n;* PROTO:\tUWORD KeyNum_Translate(UWORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tKeyNum_Translate:FAR\n\tPROC\tKeyNum_Translate C FAR \n\tUSES\tcx,di,es,ds\n\tARG\tkeycode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\tmov\tes,ax\t\t\t\t; set es up for scansb\n\n\tmov\tax,[keycode]\n\ttest\t[KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\tmov\tcx,ExtRemap-ExtNums\n\tmov\tdi,OFFSET ExtNums\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tdi,OFFSET ExtRemapEnd\n\tdec\tdi\n\tsub\tdi,cx\n\tmov\tal,[es:di]\n??fini:\n\tret\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(WORD code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_WORD:FAR\n\tPROC\tStuff_Key_WORD C FAR \n\tUSES\tsi,bx,ds\n\tARG\tcode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\tax,[KeyBufferTail]\n\tmov\tsi,ax\n\tadd\tax,2\n\tand\tax,0FFh\t\t\t\t; New KeyBufferTail value.\n\tcmp\t[KeyBufferHead],ax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[KeyBuffer+si],bx\t\t; Record the keystroke.\n\tmov\t[KeyBufferTail],ax\n\txor\tax,ax\n\tret\n\n??noroom:\n\tmov\tax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(WORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_Num:FAR\n\tPROC\tStuff_Key_Num C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds\n\tARG\tkeycode:WORD\n\tLOCAL\ttail:WORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n\tpushf\n\tcli\t\t\t\t; disable interrupts\n\n\t; Abort key recognition if in record mode and unable\n\t; to output key due to simultaneous DOS operation.\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\tax,[MouseX]\n\tmov\t[LocalMouseX],ax\n\tmov\tax,[MouseY]\n\tmov\t[LocalMouseY],ax\n\n??cando:\n\tmov\tax,[keycode]\t\t; get the code\n\tor\tax,ax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tbx,1\t\t\t; double for WORD index\n\tadd\tbx,OFFSET XYAdjust\n\tmov\tax,[bx]\t\t\t; get x,y add value\n\n\tmov\tbl,ah\n\tcbw\n\txchg\tax,bx\n\tcbw\n\txchg\tax,bx\t\t\t; AX = mouse x delta, BX = mouse y delta\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tdx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tdx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tbx,dx\t\t\t; add speed for y index\n\tmov\tbl,[KeyMouseMove+bx] \t; get speed for y delta\n\txchg\tax,bx\t\t\t; swap with ax to extend sign\n\tcbw\n\txchg\tax,bx\n\txchg\tbx,dx\t\t\t; save mouse y delta\n\tadd\tbx,ax\t\t\t; add speed for x index\n\tmov\tal,[KeyMouseMove+bx]\t; get speed for x delta\n\tcbw\n\txchg\tbx,dx\t\t\t; restore mouse y delta\n\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tbx,011b\t\t\t; Y = 1, 0, 3\n\tand\tax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tbx,011b\t\t\t; Y = 3, 0, 1\n\tand\tax,011b\t\t\t; X = 3, 0, 1\n\tshl\tbx,1\n\tshl\tbx,1\n\tor\tbx,ax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tbx,1\n\tmov\tbx,[EdgeConv+bx]\n\tshl\tbx,1\n\tshl\tbx,1\n\tmov\tax,[ScreenEdge+bx]\t; New absolute X\n\tmov\tbx,[ScreenEdge+bx+2] ; New absolute Y\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\tax,ax\n\tmov\t[LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tbx,bx\n\tmov\t[LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\tmov\t[MouseX],ax\n\tmov\t[MouseY],bx\n\tcmp\t[MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n; PWG: ARRGGGHHHH!\n;\tcall\tLow_Hide_Mouse\n;\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\tax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],ax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tsi,[KeyBufferTail]\n\tmov\t[tail],si\t\t; Safety record.\n\tmov\tdi,[KeyBufferHead]\n\n\t; Record the base keycode (if there is room).\n\tpush\tax\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\tax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tpush\t[LocalMouseX]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tpush\t[LocalMouseY]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tbx,0101h\t\t; Bit control tools.\n\tmov\tax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tmov\tcl,3\n\tshr\tdi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[KeysUpDown+di]\n\tje\tshort ??notalready\n\ttest\t[KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\t[KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[KeysUpDown+di],bh\t; Force key bit to zero.\n\tor\t[KeysUpDown+di],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\tax,1\n\tjmp short ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\tax,[tail]\n\tmov\t[KeyBufferTail],ax\n\txor\tax,ax\t\t\t; Signal an error.\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tStuff_Key_Num\n;***********************************************************\n\n\n\n;***************************************************************************\n;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard       *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Keystroke_Interrupt\n\tGLOBAL\tC Keystroke_Interrupt:FAR\n\tPROC\tKeystroke_Interrupt C FAR \n\nIF 0\n\tpush\tax\n\tinc\tax\n\tpop\tax\n\tiret\n\nELSE\n\tpush\tax\n\tpush\tbx\n\tpush\tcx\n\tpush\tdi\n\tpush\tds\n\tpush\tdx\n\tpush\tes\n\tpush\tsi\n\tcld\n\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tds,ax\n\tmov\tdx,[KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\tmov\tax,040H\t\t\t; BIOS segment\n\tmov\tes,ax\t\t\t; put in es\n\ttest\t[BYTE PTR es:017H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR es:017H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR es:096H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tes,ax\n\n\tcld\t\t\t\t; clear direction flag for strings\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tbx,0101H\t\t; set key to a make by default\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\n\t;\n\t; New CODE to montior key stream\n\t;\n\tmov\tbx,[KeyStreamIndex]\n\tmov\t[KeyStream+bx],al\n\tinc\tbx\n\tand\tbx,15\n\tmov\t[KeyStreamIndex],bx\n\tmov\tbx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[LastKeyE1]\t\t; yes, dec the count\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[IsExtKey],TRUE\t; it is an extended key\n\tmov\tdi,OFFSET ExtCodes\t; get offset of extended codes table\n\tmov\tcx,(ExtNums-ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\tmov\tal,[(ExtNums - ExtCodes) - 1 + di] ; get the match\n\tmov\t[IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tdi,ax\t\t\t; use code as an index\n\tand\tdi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[KeyNums+di]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[KeysUpDown+8],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[KeysUpDown+7],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[KeysUpDown + 7],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\tax\n\tcall\tKeyNum_Translate\n\tadd\tsp,2\n\n;------\tSet the shift bit if necessary.\n\ttest\t[KeysUpDown+5],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[KeysUpDown+7],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tshr\tdi,1\n\tshr\tdi,1\n\tshr\tdi,1\n\tmov\tbx,ax\n\tand\tbx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[Bits+bx]\t\t; get the bit to test\n\ttest\t[KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[KeysCapsLock+di]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[KeysNumLock+di]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\n\t\t\t\t\t; keyboard buffer.\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\tax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\tax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\tax,0230h\n\tje\tshort ??breaker\n\tcmp\tax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n\tcmp\tax,0420H\t\t; is this an alt s\n\tjne\tshort ??checkmusic\t; toggle the Sound variable\n\tpush\tax\n\tmov\tax,[SoundOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??checkmusic:\n\tcmp\tax,0434H\t\t; is this an alt m\n\tjne\tshort ??esc\t\t; toggle the Music variable\n\tpush\tax\n\tmov\tax,[MusicOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??esc:\n\n\tpush\tax\n\tcall\tStuff_Key_Num\n\tpop\tax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\tax\n\tcall\t[EscRoutine]\n\tpop\tax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tdi,OFFSET PassAlways\t; get offset to table\n\tmov\tcx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1\n\trepne\tscasb\t\t\t; look for a match\n\tor\tcx,cx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n\n\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tdi,OFFSET CondPassKey\t; get offset to cond key table\n\tmov\tcx,(CondPassCond-CondPassKey) ; get number of entries\n\tshr\tcx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(CondPassCond - CondPassKey) - 2 + di]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tdx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n;***********************************************************\n\tpushf\n;\tpush\tdi\n;\tpush\tes\n\t\n\tmov\tax,0B000h\n\tmov\tes,ax\n\tinc\t[BYTE PTR es:0]\n\n;\tpop\tes\n;\tpop\tdi\n\tpopf\n;***********************************************************\n\n??passcode:\n\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tinc\t[cs:PassCount]\n\tjmp\t[cs:OldRMI]\n\n??absorbcode:\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tax,040h\t\t\t\t; BIOS paragraph is always @ 040h\n\tmov\tes,ax\t\t\t\t; put in es as BIOS paragraph\n\tmov\tal,[es:96h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[es:96h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tiret\t\nENDIF\n\n\tENDP\tKeystroke_Interrupt\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles the break key interrupt                      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Break_Interrupt:FAR\n\tPROC\tBreak_Interrupt C FAR\n\n\tiret\t\n\n\tENDP\tBreak_Interrupt\n\n;**************************************************************************\n;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nCall_Interrupt_Chain:\nIF 0\n\tpushf\n\tpush\tax\n\tpush\tdi\n\tpush\tes\n\n\tmov\tax,0B000h\t\t; ES:DI = Mono RAM address.\n\tmov\tes,ax\n\t\t\n\tmov\tal,'A'\n\tmov\tah,2\n\tand\tdi,63\n\n\tstosw\n\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\tmov\tal,CLEARISR\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t; 8259 interrupt chip controller 0\n\n\n\tpop\tes\n\tpop\tdi\n\tpop\tax\n\tpopf\nENDIF\n\tpushf\n\tcall\tKeystroke_Interrupt ;[OldRMI]\n\tretf\n\nSTACK\t   ; Don't really need this\n\n;***********************************************************\nEND\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/KEYIREAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*\t\t\t\t  (Mouse Routines)\n;*                                                                         *\n;*                    File Name : KEYIREAL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Philip W. Gorrow                         *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;* This file sort of breaks the standard of keeping all of the keyboard    *\n;* and mouse routines isolated.  This is done because the mouse and\t   *\n;* the keyboard share data, and the best way to do this is to put\t   *\n;* them in the same segment.  This should probably be split into several   *\n;* include files to help make the code clearer once it is finally put\t   *\n;* together.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   KeyNum_Translate -- Translates extended keynums to normal keynums\t   *\n;*   Stuff_Key_Word -- Stuffs a word of data into keyboard buffer          *\n;*   Stuff_Key_Num -- Stuffs a key num code into the circular buffer       *\n;*   Keystroke_Interrupt -- Real mode handler of input from the keyboard   *\n;*   Break_Interrupt -- Handles the break key interrupt                    *\n;*   Call_Interrupt_Chain -- Function PM calls to call RM interrupt chain  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tKeyboard driver -- 8086 Assembly portion;\t\t\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   *\n;***************************************************************************\n\n;---------------------------------------------------------------------------\n; Set the assembly directives\n;---------------------------------------------------------------------------\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386N\t\t\t\t; use 386 real mode instructions\nMODEL TINY\t\t\t; code must be tiny so it fits\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keyboard.inc\"\n\nCONDHIDE\t\tEQU\t08000H\t\t; bit for testing conditional region\nCONDHIDDEN\t\tEQU\t04000H\t\t; bit for testing conditional hidden\nRESTORE_VISIBLE_PAGE\tEQU\t0\nSTORE_VISIBLE_PAGE\tEQU\t1\n\n\nGLOBAL\tset_vesa_page \t:near\nGLOBAL\tset_vesa_window :near\nGLOBAL\tget_vesa_window :near\nGLOBAL\tnext_vesa_page\t:near\n\nECHOON\tequ 0\n;---------------------------------------------------------------------------\n; WARNING!!!!  All of the following code segment variables are shared by\n;   the protected mode interrupt.  Do not change these unless you make the\n;   proper changes to KEYSTRUC.INC.  If you do not know what you are doing,\n;   find someone who does!!!\n;---------------------------------------------------------------------------\nCODESEG\n\n;---------------------------------------------------------------------------\n; Begin definition of Keyboard specific variables\n;---------------------------------------------------------------------------\nSoundOn\t\tDW\t1\t; toggled by alt S\nMusicOn\t\tDW\t1\t; toggled by alt M\nKeyFlags\tDD\tREPEATON+CTRLALTTURBO\t; all but repeat for now\n\n\nBreak\t\tDW\t0\n\nKeyMouseMove\tDB\t-1,0,1\n\t\tDB\t-16,0,16\n\nScreenEdge\tDW\t320/2,0\t\t; North\n\t\tDW\t319,0\t\t; North-East\n\t\tDW\t319,138/2\t; East\n\t\tDW\t319,137\t\t; South-East\n\t\tDW\t320/2,137\t; South\n\t\tDW\t0,137\t\t; South-West\n\t\tDW\t0,138/2\t\t; West\n\t\tDW\t0,0\t\t; North-West\n\t\tDW\t320/2,138/2\t; Center\n\n\nBits\t\tDB\t01H,02H,04H,08H,10H,20H,40H,80H\n\nCondPassKey\tDW\t0220H, 0320H, 060CH, 070DH, 066AH\n\t\tDW\t0669H, 0230H, 0330H, 007DH, 017DH\n\t\tDW\t025AH, 035AH, 0200H, 0410H, 046EH\n\t\tDW\t026EH, 007CH\n\nCondPassCond\tDW\tCTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO\n\t\tDW\tCTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON\n\t\tDW\tPAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE\n\t\tDW\tTASKSWITCHABLE, BREAKON\n\nEscRoutine\tDD\t0\t; vector to execute on esc key press (0=none)\n\n; Extended raw keycodes to be converted to Westwood keycodes.\nExtCodes\tDB\t038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H\n\t\tDB\t051H,04DH,035H,01CH,037H\n\t\tDB\t046H\n; The matching Westwood keycodes.\nExtNums\t\tDB\t62,  64,  75,  76,  79,  80,  81,  83,  84,  85\n\t\tDB\t86,  89,  95, 108, 124,  0\n; If extended mapping is disabled, then these codes really are...\nExtRemap\tDB\t60,  58,  99, 104,  92,  91,  93,  96,  98, 101\n\t\tDB\t103, 102, 55,  43, 124,  0\nExtRemapEnd\tDB\t0\n\nExtKeyboard\tDB\t0\t; flag for 101/102-key keyboard\n\n\nKeyBuffer\tDW\t128 DUP(0) ; set to empty\nKeyBufferHead\tDD\t0\t; set to first entry\nKeyBufferTail\tDD\t0\t; set to head for empty buffer\nKeyLock\t\tDW\t0\t; num and caps lock bits\nKeyNums\t\tDB\t127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016\n\t\tDB\t017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032\n\t\tDB\t033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049\n\t\tDB\t050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116\n\t\tDB\t117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093\n\t\tDB\t098,103,099,104,127,127,127,122,123\n\nKeysCapsLock\tDB\t0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0\nKeysNumLock\tDB\t0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0\nKeysUpDown\tDB\t16 DUP(0) ; set to all keys up\nKeyStream\tDB\t16 DUP(0) ; set to all keys up\nPassCount\tDW\t0\nKeyStreamIndex\tDW\t0\nLastKeyE0\tDB\t0\nLastKeyE1\tDB\t0\n\n;\n; Westwood key number values of keys to pass through\n;\n;\t\t\tCAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT,\n;\t\t\tRIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN\nPassAlways\tDB\t30, 44, 57, 58, 60, 62, 64, 90, 128, 128\nPassAlwaysEnd\tDB\t128\t\t; invalid code to END PassAlways\nCtrlFlags\tDB\t0\n\nBuffer\t\tDW\t?\nTime\t\tDW\t?\n\nADJUST\t= 1\t\t\t; do not modify DRD\n\nXYAdjust\tDB\t-ADJUST, -ADJUST\t; 91 -> upleft\n\t\tDB\t-ADJUST,  0\t\t; 92 -> left\n\t\tDB\t-ADJUST,  ADJUST\t; 93 -> downleft\n\t\tDB\t 0,  0\t\t\t; 94 illegal\n\t\tDB\t 0,  0\t\t\t; 95 illegal\n\t\tDB\t 0, -ADJUST\t\t; 96 -> up\n\t\tDB\t 0,  0\t\t\t; 97 illegal (center)\n\t\tDB\t 0,  ADJUST\t\t; 98 -> down\n\t\tDB\t 0,  0\t\t\t; 99 illegal\n\t\tDB\t 0,  0\t\t\t; 100 illegal\n\t\tDB\t ADJUST, -ADJUST\t; 101 -> upright\n\t\tDB\t ADJUST,  0\t\t; 102 -> right\n\t\tDB\t ADJUST,  ADJUST\t; 103 -> downright\n\tEdgeConv\t\tDW\t8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7\n\tMouseUpdate\t\tDW\t0\n\tMouseX\t\t\tDW\t0,0\n\tLocalMouseX\t\tDW\t0\n\tMouseY\t\t\tDW\t0,0\n\tLocalMouseY\t\tDW\t0\n\tIsExtKey\t\tDB\t0\n\tExtIndex\t\tDW\t0\n\n\tKeyOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tKeyOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\t\t\n\tKeyOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tKeyCodeOffset\t\tDW\tRM_Keystroke_Interrupt\t; Offset of the code in the RM stuff.\n\tCallKeyRMIntOffset\tDW\tCall_Interrupt_Chain\t; Offset of function to call DOS timer interrupt.\n\tCallKeyRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedKeyInt\t\tDD\t0\n\n\tBrkOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tBrkOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\t\t\n\tBrkOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tBrkCodeOffset\t\tDW\tRM_Break_Interrupt\t; Offset of the code in the RM stuff.\n\tCallBrkRMIntOffset\tDW\t0\n\tCallBrkRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedBrkInt\t\tDD\t0\n\tKeyIntDisabled\t\tDD\t0\n\n\tDbgOldPMIOffset\t\tDD\t0\t; The origianl PM interrupt offset\t\t\n\tDbgOldPMISelector\tDD\t0\t; The original PM interrupt segment.\n\n;---------------------------------------------------------------------------\n; Begin definition of Mouse Specific Variables for real mode\n;---------------------------------------------------------------------------\nButton\t\t\tDB\t0\t; current value of the mouse button\nMDisabled\t\tDB\t0\t; Is the mouse driver disabled\nMInput\t\t\tDB\t1\t; Defaults to mouse input allowed.\nAdjust\t\t\tDW\t0\t; flag to adjust coordinates if necessary\nMouseStepX\t\tDW\t0\t; step values if the mouse moves at\nMouseStepY\t\tDW\t0\t;   more than one pixel at a time\nMouseOffsetX\t\tDW\t0\t; Fractional step values used if a mouse\nMouseOffsetY\t\tDW\t0\t;   moves at less than one pixel at a time\nMState\t\t\tDW\t0,0\t; Tracks if mouse is hidden (TRUE) or not (FALSE)\nMouseXOld     \t\tDW\t0\t; Holds last MouseX and MouseY to determine if \nMouseYOld     \t\tDW\t0\t;   mouse needs to be redrawn\nMCState\t\t\tDW\t0\t; Tracks if mouse conditional hidden (TRUE) or not\nMouseCXLeft\t\tDW\t0,0\t; Conditional hide mouse left x position\nMouseCYUpper\t\tDW\t0,0\t; Conditional hide mouse top y position\nMouseCXRight\t\tDW\t0,0\t; Conditional hide mouse right x position\nMouseCYLower\t\tDW\t0,0\t; Conditional hide mouse lower y position\nMouseCursor   \t\tDD\t0\t; Pointer to the mouse cursor to draw\nMouseCursorSize\t\tDW\t0\t; Pointer to buffer mouse is saved in\nMouseBuffer   \t\tDD\t0\t; Pointer to buffer mouse is saved in\nMouseXHot     \t\tDW\t0,0\t; Offset to mouse's x hot spot\nMouseYHot     \t\tDW\t0,0\t; Offset to mouse's y hot spot\nMouseBuffX\t\tDW\t0,0\t; X position background was saved at\nMouseBuffY\t\tDW\t0,0\t; Y position background was saved at\nMouseBuffW\t\tDW\t0,0\t; Width of the region saved for mouse\nMouseBuffH\t\tDW\t0,0\t; Height of the region saved for mouse\nMouseWidth\t\tDW\t0,0\t; Mouse cursor theoretical width\nMouseHeight\t\tDW\t0,0\t; Mouse cursor theoretical height\nMouseCodeOffset\t\tDW\tRM_Mouse_Interrupt\t; Offset of the code in the RM stuff.\nMouseRight\t\tDW\t0,0\nMouseBottom\t\tDW\t0,0\n\n\nShadowPtr\t\tdw\t0\nDrawMousePtr \t\tdw\t0\n\nVGAMouseDraw\t\tdw\tVGA_Draw_Mouse\nVGAMouseShadow\t\tdw\tVGA_Mouse_Shadow_Buffer\n\nVESAMouseDraw\t\tdw\tVESA_Draw_Mouse\nVESAMouseShadow\t\tdw\tVESA_Mouse_Shadow_Buffer\n\nVesaPtr\t\t\tdd\t0\t\nbanktable\t\tdd      8 dup ( 0 )\nAdjust_XPos\t\tdw \t0 , 0\nAdjust_YPos\t\tdw \t0 , 0 \n\n\t\talign 2\nKeyboard_App_Stack_ES\tdw 0\t\t; This the System Stack Offsset\nKeyboard_App_Stack_SS\tdw 0\t\t; This the System Stack Selector\nKeyboard_StackPointer\tdw 0DEADh\t; We Create a Local Application\nKeyboard_Stack\t\tdw 512 dup (0)\nKeyboard_StackStart\tdw 0\n\nMouse_State\t\tdw 0\t\t; Mouse Temp Variable\nMouse_Cond\t\tdw 0\t\t; Mouse Temp Variable\nMouse_App_Stack_ES\tdw 0\t\t; This the System Stack Offsset\nMouse_App_Stack_SS\tdw 0\t\t; This the System Stack Selector\nMouse_StackPointer\tdw 0DEADh\t; We Create a Local Application\nMouse_Stack\t\tdw 512 dup (0)\nMouse_StackStart\tdw 0\n\n\n\ncurrent_page\t\tdw\t0\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Translates extended keynums to normal keynums\t   *\n;*                                                                         *\n;* INPUT:\tUWORD the keynum to translate\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated keynum                                 *\n;*                                                                         *\n;* PROTO:\tUWORD KeyNum_Translate(UWORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tKeyNum_Translate:FAR\n\tPROC\tKeyNum_Translate C FAR \n\tUSES\tcx,di,es,ds\n\tARG\tkeycode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\tmov\tes,ax\t\t\t\t; set es up for scansb\n\n\tmov\tax,[keycode]\n\ttest\t[WORD PTR KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\tmov\tcx,ExtRemap-ExtNums\n\tmov\tdi,OFFSET ExtNums\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tdi,OFFSET ExtRemapEnd\n\tdec\tdi\n\tsub\tdi,cx\n\tmov\tal,[es:di]\n??fini:\n\tret\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(WORD code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_WORD:FAR\n\tPROC\tStuff_Key_WORD C FAR \n\tUSES\tsi,bx,ds\n\tARG\tcode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\tax,[WORD PTR KeyBufferTail]\n\tmov\tsi,ax\n\tadd\tax,2\n\tand\tax,0FFh\t\t\t\t; New KeyBufferTail value.\n\tcmp\t[WORD PTR KeyBufferHead],ax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[KeyBuffer+si],bx\t\t; Record the keystroke.\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\n\tret\n\n??noroom:\n\tmov\tax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(WORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_Num:FAR\n\tPROC\tStuff_Key_Num C FAR \n\tUSES\tbx,cx,dx,di,si,ds\n\tARG\tkeycode:WORD\n\tLOCAL\ttail:WORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n\tpushf\n\tcli\t\t\t\t; disable interrupts\n\n\t; Abort key recognition if in record mode and unable\n\t; to output key due to simultaneous DOS operation.\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\tax,[MouseX]\n\tmov\t[LocalMouseX],ax\n\tmov\tax,[MouseY]\n\tmov\t[LocalMouseY],ax\n\n??cando:\n\tmov\tax,[keycode]\t\t; get the code\n\tor\tax,ax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[WORD PTR KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[WORD PTR KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tbx,1\t\t\t; double for WORD index\n\tadd\tbx,OFFSET XYAdjust\n\tmov\tax,[bx]\t\t\t; get x,y add value\n\n\tmov\tbl,ah\n\tcbw\n\txchg\tax,bx\n\tcbw\n\txchg\tax,bx\t\t\t; AX = mouse x delta, BX = mouse y delta\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tdx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tdx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tbx,dx\t\t\t; add speed for y index\n\tmov\tbl,[KeyMouseMove+bx] \t; get speed for y delta\n\txchg\tax,bx\t\t\t; swap with ax to extend sign\n\tcbw\n\txchg\tax,bx\n\txchg\tbx,dx\t\t\t; save mouse y delta\n\tadd\tbx,ax\t\t\t; add speed for x index\n\tmov\tal,[KeyMouseMove+bx]\t; get speed for x delta\n\tcbw\n\txchg\tbx,dx\t\t\t; restore mouse y delta\n\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tbx,011b\t\t\t; Y = 1, 0, 3\n\tand\tax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tbx,011b\t\t\t; Y = 3, 0, 1\n\tand\tax,011b\t\t\t; X = 3, 0, 1\n\tshl\tbx,1\n\tshl\tbx,1\n\tor\tbx,ax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tbx,1\n\tmov\tbx,[EdgeConv+bx]\n\tshl\tbx,1\n\tshl\tbx,1\n\tmov\tax,[ScreenEdge+bx]\t; New absolute X\n\tmov\tbx,[ScreenEdge+bx+2] ; New absolute Y\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\tax,ax\n\tmov\t[LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tbx,bx\n\tmov\t[LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\tmov\t[MouseX],ax\n\tmov\t[MouseY],bx\n\tcmp\t[MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n\n\tcall\tLow_Hide_Mouse\n\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\tax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],ax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tsi,[WORD KeyBufferTail]\n\tmov\t[tail],si\t\t; Safety record.\n\tmov\tdi,[WORD PTR KeyBufferHead]\n\n\t; Record the base keycode (if there is room).\n\tpush\tax\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\tax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tpush\t[LocalMouseX]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tpush\t[LocalMouseY]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tbx,0101h\t\t; Bit control tools.\n\tmov\tax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[WORD PTR KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tmov\tcl,3\n\tshr\tdi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[KeysUpDown+di]\n\tje\tshort ??notalready\n\ttest\t[WORD PTR KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[KeysUpDown+di],bh\t; Force key bit to zero.\n\tor\t[KeysUpDown+di],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\tax,1\n\tjmp short ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\tax,[tail]\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\t\t\t; Signal an error.\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tStuff_Key_Num\n;***********************************************************\n\n\n\n;***************************************************************************\n;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard       *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Keystroke_Interrupt\n\tGLOBAL\tC Keystroke_Interrupt:FAR\n\tPROC\tKeystroke_Interrupt C FAR \n\nIF 0\n\tpush\tax\n\tinc\tax\n\tpop\tax\n\tiret\n\nELSE\n\tpush\tax\n\tpush\tbx\n\tpush\tcx\n\tpush\tdi\n\tpush\tds\n\tpush\tdx\n\tpush\tes\n\tpush\tsi\n\tcld\n\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tds,ax\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov cx, ss\t\t\t\t; get SS\n\tmov [Keyboard_App_Stack_ES], sp\t\t; Protect ES\n\tmov [Keyboard_App_Stack_SS], cx\t\t; Protect SS\n\tlea dx, [Keyboard_StackStart ]\t\t; Compute Local Stack size\n\tand dx, -2;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov sp, dx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n\tcmp\t[WORD PTR PMIssuedKeyInt],0; Check to see if PM made Int call.\n\tmov\t[WORD PTR PMIssuedKeyInt],0; Make it false.\t\t\n\tjne\t??passcode\t; if so, just call Int Chain.\n\n\n\tmov\tdx,[WORD PTR KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\tmov\tax,040H\t\t\t; BIOS segment\n\tmov\tes,ax\t\t\t; put in es\n\ttest\t[BYTE PTR es:017H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR es:017H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR es:096H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tes,ax\n\n\tcld\t\t\t\t; clear direction flag for strings\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tbx,0101H\t\t; set key to a make by default\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\n\t;\n\t; New CODE to montior key stream\n\t;\n\tmov\tbx,[KeyStreamIndex]\n\tmov\t[KeyStream+bx],al\n\tinc\tbx\n\tand\tbx,15\n\tmov\t[KeyStreamIndex],bx\n\tmov\tbx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[LastKeyE1]\t\t; yes, dec the count\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[IsExtKey],TRUE\t; it is an extended key\n\tmov\tdi,OFFSET ExtCodes\t; get offset of extended codes table\n\tmov\tcx,(ExtNums-ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\tmov\tal,[(ExtNums - ExtCodes) - 1 + di] ; get the match\n\tmov\t[IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tdi,ax\t\t\t; use code as an index\n\tand\tdi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[KeyNums+di]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[KeysUpDown+8],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[KeysUpDown+7],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[KeysUpDown + 7],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\tax\n\tcall\tKeyNum_Translate\n\tadd\tsp,2\n\n;------\tSet the shift bit if necessary.\n\ttest\t[KeysUpDown+5],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[KeysUpDown+7],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tshr\tdi,1\n\tshr\tdi,1\n\tshr\tdi,1\n\tmov\tbx,ax\n\tand\tbx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[Bits+bx]\t\t; get the bit to test\n\ttest\t[KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[KeysCapsLock+di]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[KeysNumLock+di]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\t\n\t\t\t\t\t; keyboard buffer.\n\ttest\tdx,DEBUGINT\n\tjz\t??not_toggle \n\n\nIF DEBUG\n\tcmp\t[KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\tcmp\tax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\tax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\tax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\t\n\tcmp\tax,125\n\tjne\t??not_toggle\n\tmov\t[KeyIntDisabled],1\n\tjmp\t??absorbcode\nENDIF\n\n??not_toggle:\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\tax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\tax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\tax,0230h\n\tje\tshort ??breaker\n\tcmp\tax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n\tcmp\tax,0420H\t\t; is this an alt s\n\tjne\tshort ??checkmusic\t; toggle the Sound variable\n\tpush\tax\n\tmov\tax,[SoundOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??checkmusic:\n\tcmp\tax,0434H\t\t; is this an alt m\n\tjne\tshort ??esc\t\t; toggle the Music variable\n\tpush\tax\n\tmov\tax,[MusicOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??esc:\n\n\tpush\tax\n\tcall\tStuff_Key_Num\n\tpop\tax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\tax\n\tcall\t[EscRoutine]\n\tpop\tax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tdi,OFFSET PassAlways\t; get offset to table\n\tmov\tcx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1\n\trepne\tscasb\t\t\t; look for a match\n\tor\tcx,cx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n\n\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tdi,OFFSET CondPassKey\t; get offset to cond key table\n\tmov\tcx,(CondPassCond-CondPassKey) ; get number of entries\n\tshr\tcx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(CondPassCond - CondPassKey) - 2 + di]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tdx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\n\tinc\t[cs:PassCount]\n\n;mov   ax , 0B000h\n;mov   es, ax \n;inc   [BYTE PTR es : 40h]\n\n\t; Now it is time to set up for the call to the System Keyboard\n\t; interrupt handler.\n\t; 1 -Restore System Stack Pointer Selector before exit Interrupt\n\t; 2- We Create a Returning Point from Interrupt by Push A\n \t;    Interupt Stack Frame into the Stack Pointer\n\t; 3- We make a Far jump to the interuupt handler\n\tcmp [Keyboard_StackPointer],0DEADh\n\tje  ??stackok\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n??stackok:\n\tcli\t\t\t\t       ; disable Interrupts\n\tmov dx, [Keyboard_App_Stack_SS]       \n\tmov ss, dx\t\t\t       ; Get System Stack Selector\n\tmov sp, [Keyboard_App_Stack_ES]      ; Get System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n\tlea\tdx, [??Call_Back_Keyboard]   ; Get Return address offset\n \tpushf\t\t\t\t      ; push flags\t\n\tpush\tcs\t\t\t      ; push Code segment\n\tpush\tdx\t\t\t      ; push Offset\n\n\t; Now we need to simulate an interrup call by using ired\n\t; because we still want to come back here from the\n\t; Old Keyboard interrupt handle.\n\tpushf\n\tpush\t[word ptr KeyOldRMI + 2] \t; push orig segment.\n\tpush    [word ptr KeyOldRMI]   \t\t; push orig offset.\n\tiret\t \t\t        \t; call interrupt\t\n\n??absorbcode:\n\n;mov   ax , 0B000h\n;mov   es, ax \n;inc   [BYTE PTR es : 0h]\n\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tax,040h\t\t\t\t; BIOS paragraph is always @ 040h\n\tmov\tes,ax\t\t\t\t; put in es as BIOS paragraph\n\tmov\tal,[es:96h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[es:96h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\n\tcmp [Keyboard_StackPointer],0DEADh\n\tje  ??stackok2\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n??stackok2:\n\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov dx, [Keyboard_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, dx\t\t\t       ; Get Syatem Stack Selector\n\tmov sp, [Keyboard_App_Stack_ES]        ; Get Syatem Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n??Call_Back_Keyboard:\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tiret\t\nENDIF\n\n\tENDP\tKeystroke_Interrupt\n\n;***************************************************************************\n;* Break interrupt routines begin here!\n;***************************************************************************\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles the break key interrupt                      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Break_Interrupt\n\tGLOBAL\tC Break_Interrupt:FAR\n\tPROC\tBreak_Interrupt C FAR\n\n\n\tpushf\n\tpush\tax\n\tpush\tes\n\n\tmov\tax,0B000h\t\t; ES:DI = Mono RAM address.\n\tmov\tes,ax\n\tinc\t[BYTE PTR es:0]\n\t\t\n\n\tpop\tes\n\tpop\tax\n\tpopf\n\n\n\tiret\t\n\n\tENDP\tBreak_Interrupt\n\n;**************************************************************************\n;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                                  *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nCall_Interrupt_Chain:\n\tpushf\n\tcall\tKeystroke_Interrupt ;[KeyOldRMI]\n\tretf\n\n;----------------------------------------------------------------------------\n; LOW_HIDE_MOUSE:\n;\n; This function hides the mouse cursor on the screen if it was shown.  It \n; will not hide the mouse if it is already hidden.\n;\n; PROTOTYPE:\n;\n;\tVOID Low_Hide_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Hide_Mouse:FAR\n\tPROC\tLow_Hide_Mouse C FAR \n\tUSES\tax,bx,cx,dx,ds\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n   \tcmp\t[MDisabled],0\t\t; check if mouse is disabled\n\tjne\tshort ??end\n\n   \tcmp\t[MState],0\t\t; check if it was hidden before\n\tjne\tshort ??endnodraw\t\t; no need to hide again\n\n;------\tMove the saved graphic buffer to the seenpage to hide the mouse.\n;\tcall\tBuffer_To_Page C,[buffx],[buffy],[buffw],[buffh],[MouseBuffer],SEENPAGE\n\tmov\tax,RESTORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tRecord that the mouse has been hidden.\n??endnodraw:\n\tadd\t[MState],1\n\tadc\t[MState],0\n\n??end:\n\tret\n\n\tENDP\tLow_Hide_Mouse\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; LOW_SHOW_MOUSE:\n;\n; This function displays the mouse cursor on the screen if it was hidden.\n;\n; PROTOTYPE:\n;\tVOID Low_Show_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Show_Mouse:FAR\n\tPROC\tLow_Show_Mouse C FAR \n\tUSES \tax,bx,cx,dx,si,di,ds,es\n\tLOCAL\tmousex:WORD\t\t; Draw X position.\n\tLOCAL\tmousey:WORD\t\t; Draw Y position.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n;-----\tDon't show the mouse if it is not hidden, disabled.\n\tcmp\t[MDisabled],0\t\t; is the mouse disabled\n\tjne\t??exit\t\t\t; if so then exit\n\n\tcmp\t[MState],0\t\t; is the mouse already visible\n       \tje\t??exit\t\t\t; if so then exit\n\n\tdec\t[MState]\n\tcmp\t[MState],0\t\t; can the mouse be shown\n       \tjne\tshort ??exit\n\n;------\tDetermine the drawing position of the mouse.\n\tmov\tcx,[MouseWidth]\t\t; Theoretical buffer width (pixel).\n\tmov\tdx,[MouseHeight]\t; Theoretical buffer height (pixel).\n\n\tmov\tax,[MouseX]\n;\tsub\tax,[MouseXHot]\n\tmov\t[mousex],ax\t\t; Draw X pixel.\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??xnotneg\n;\tadd\tcx,ax\t\t\t; Reduce width accordingly.\n;\tmov\tax,0\n??xnotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n\tmov\tbx,[MouseY]\n;\tsub\tbx,[MouseYHot]\n\tmov\t[mousey],bx\t\t; Draw Y pixel.\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??ynotneg\n;\tadd\tdx,bx\t\t\t; Reduce height of mouse accordingly.\n;\tmov\tbx,0\n??ynotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n;------\tDetermine the theoretical coordinates and dimensions of the\n;\tarea the mouse shape will be rendered upon.\n\tmov\t[MouseBuffX],ax\n\tmov\t[MouseBuffY],bx\n\tmov\t[MouseBuffW],cx\n\tmov\t[MouseBuffH],dx\n\n;------\tMove the area that will be drawn upon, to the graphic buffer.\n\tmov\tax,STORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tDraw the mouse shape to the seenpage.\n\tpush\t[mousey]\n\tpush\t[mousex]\n\tpush\tcs\n\tcall\t[ DrawMousePtr ]\n\tadd\tsp,4\n??exit:\n\tret\n\n\tENDP\tLow_Show_Mouse\n\n;----------------------------------------------------------------------------\n;----------------------------------------------------------------------------\n\tGLOBAL\tC Mouse_KeyNum:FAR\n\tPROC\tMouse_KeyNum C FAR \n\tUSES\tbx\n\tARG\tstate:WORD\t\t; Current mouse state.\n\tLOCAL\tkeynum:WORD\t\t; Determined keynum.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\t[keynum],KN_MOUSE_MOVE\t; Presume just a mouse move.\n\tmov\tbx,[state]\n\tmov\tax,bx\n\txor\tbl,[Button]\t\t; Bits of state change.\n\tje\tshort ??fini\n\tmov\t[Button],al\t\t; Record new mouse state.\n\n\ttest\tbl,0010b\n\tje\tshort ??notright\n\tmov\t[keynum],KN_RMOUSE\n\ttest\tal,0010b\n\tjne\tshort ??notright\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notright:\n\n; DRD\n; note:  the left mouse button has priority over the right mouse button\n; this should be changed at a later date to process them independently\n\n\ttest\tbl,0001b\n\tje\tshort ??notleft\n\tmov\t[keynum],KN_LMOUSE\n\ttest\tal,0001b\n\tjne\tshort ??notleft\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notleft:\n\n??fini:\n\tmov\tax,[keynum]\n\tret\n\n\tENDP\tMouse_KeyNum\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; MOUSE_INT:\n;\n; This routine is called automatically when the Mouse_Int is installed.  It\n; automatically updates the global variables stored in the code segment so\n; that the mouse information is automatically known at all times.\n;\n; INPUTS (from int):\tAX = condition mask ( bit 0 == cursor position chg,\n;\t\t\t\t\t      bit 1 == left button press,\n;\t\t\t\t\t      bit 2 == left button release,\n;\t\t\t\t\t      bit 3 == right button press,\n;\t\t\t\t\t      bit 4 == right button release,\n;\t\t\t\t\t      5-15  == not used )\n;\t\t\tBX = button state   ( bit 0 == left button down,\n;\t\t\t\t\t      bit 1 == right button down,\n;                                             bit 2 == middle button down.\n;\t\t\t\t\t      3-15  == not used )\n;\t\t\tCX = cursor coordinate (horizontal axis)\n;\t\t\tDX = cursor coordinate (vertical axis)\n;\t\t\tDI = horizontal mouse count (mickeys)\n;\t\t\tSI = vertical mouse count (mickeys)\n;\n; RETURNS:\t\tnone\n;\n; MODIFIES:\t\tmodifies the variables _Button, _ButtonChange,\n;\t\t\t_MouseX,_MouseY,_ButtonLatch\n;\n; PROTOTYPE:\n;\tThis routine is called from an interrupt.\n;----------------------------------------------------------------------------\nlabel RM_Mouse_Interrupt\n\tPROC\tMouse_Int C FAR \n\tUSES\tax,bx,cx,dx,ds,si,es,di\n\tLOCAL\tcond:WORD\t\t; Local copy of mouse event.\n\tLOCAL\tstate:WORD\t\t; Local copy of button state.\n\n\tmov\t[cs:Mouse_State],bx\n\tmov\t[cs:Mouse_Cond],ax\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov bx, ss\t\t\t\t; get SS\n\tmov [Mouse_App_Stack_ES], sp\t\t; Protect ES\n\tmov [Mouse_App_Stack_SS], bx\t\t; Protect SS\n\tlea bx, [Mouse_StackStart ]\t; Compute Local Stack size\n\tand bx, -2;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov sp, bx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n;------\tProcess the mouse interrupt only if the mouse is enabled (whether\n;\tpresent or not).\n\tcmp\t[MDisabled],0\n\tjne\t??exit\n\n\tcmp\t[MInput],0\n\tje\t??exit\n\n\n;------ This was added because of missing mouse presses and\n;\treleases during a mouse update.\n\tmov\tax,[Mouse_Cond]\n\tand\tax,0001EH \t; bits for left and right press and release\n\tjne\tshort ??dopress_release\n\n\tcmp\t[MouseUpdate],0 ; if mouse move and mouse updating exit\n\tjne\t??exit\n\n??dopress_release:\n\n;------\tIn EEGA mode mouse X coordinates as 0..639.  Make adjustment\n;\tto keep within 0..319 range.\n\tcmp\t[Adjust],1\t\t; if the x coordinate is returned\n\tjne\tshort ??noadjust\t; incorrectly then\n\tshr\tcx,1\t\t\t; adjust x coord from 640 pixel screen\n??noadjust:\n\n\n; scale mouse posX and PosY\n;\tcmp\t[Adjust_XPos] , 0\n;\tjz\tshort ??no_scaleX\n;\tpush\tdx\n;\tmov\tax , [MouseRight]\n;\timul\tcx\n;\tidiv\t[Adjust_XPos]\n;\tmov\tcx , ax\n;\tpop\tdx\n??no_scaleX:\n;\tcmp\t[Adjust_YPos] , 0\n;\tjz\tshort ??no_scaleY\n;\tmov\tax , [MouseBottom]\n;\timul\tdx\n;\tidiv\t[Adjust_YPos]\n;\tmov\tdx , ax\n??no_scaleY:\n\n;------\tKeep mouse within screen bounds.\n\tcmp\tcx,[MouseRight]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundX_ok\t\t; force it to stay at least one pixel\n\tmov\tcx,[MouseRight]\t\t\t; on the screen\n\tdec\tcx\n??boundX_ok:\n\tcmp\tdx,[MouseBottom]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundY_ok\t\t; force it to stay at least one pixel\n\tmov\tdx,[MouseBottom]\t\t\t; on the screen\n\tdec\tdx\n??boundY_ok:\n\n\tIF 0\n;------\tRemap the middle button to equal the right button.\n\ttest\tbx,04h\n\tje\t??noremap\n\tor\tbx,0010b\t\t; Set the right button bit.\n??noremap:\n\tENDIF\n\n\tmov\t[MouseX],cx\t\t; and store in mouse x\n\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\ttest\t[KeyFlags],KEYMOUSE\n\tjne\tshort ??nostuffit\n\n\tcall\tMouse_KeyNum C,[Mouse_State]\t; Convert mouse state to key number code.\n\tcall\tStuff_Key_Num C,ax\t; Record mouse keynumber code.\n??nostuffit:\n\n\n\n;------ The check for Mouse in the middle of updating CAN NOT BE MOVED\n;\tany farther up because mouse presses and releases will be LOST!!\n \tcmp\t[MouseUpdate],0\n\tjne\t??exit\n;??jexit:\n;\tjmp\t??exit\n\n\nchristopher:\n??chkxy:\n\n;------\tSignal that no mouse updating can occur at this time.\n;\tcmp\t[_MouseUpdate],0\n;\tjne\t??exit\n;\tmov\t[_MouseUpdate],1\n\n;------\tPerform any X movement grid adjustment.\n\tcmp\t[MouseStepX],0\t\t; are we stepping on the X?\n\tje\tshort ??no_x_step\t\t; no x\n\tmov\tax,cx\t\t\t; get current x_pixel\n\tmov\tcx,dx\t\t\t; save dx - it is trashed by idiv\n\tsub\tax,[MouseOffsetX]\t; get offset difference\n\tmov\tbx,[MouseStepX]\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step X\n\timul\tbx\t\t\t; ax = div * Step X\n\tadd\tax,[MouseOffsetX]\t; normalize to region offset\n\tmov\tdx,cx\t\t\t; restore dx (new MouseY)\n\tmov\tcx,ax\t\t\t; set cx (new MouseX)\n??no_x_step:\n\n;------\tPerform any Y movement grid adjustment.\n\tcmp\t[MouseStepY],0\t\t; are we stepping on the Y\n\tje\tshort ??no_step\t\t; no y\n\tmov\tax,dx\t\t\t; get current y_pixel\n\tsub\tax,[MouseOffsetY]\t; get offset difference\n\tmov\tbx,[MouseStepY]\t\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step Y\n\timul\tbx\t\t\t; ax = div * Step Y\n\tadd\tax,[MouseOffsetY]\t; normalize to region offset\n\tmov\tdx,ax\t\t\t; set dx (new MouseY)\n??no_step:\n\n;------ Here is where we store the new MouseX and MouseY values\n;\tmov\t[MouseX],cx\t\t; and store in mouse x\n;\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\n;------\tIf the mouse is hidden or its position hasn't changed, then\n;\tperform no action.\n\tcmp\t[MState],0\n\tjne\tshort ??updateend\n\tcmp\t[MouseXOld],cx\n\tjne\tshort ??doit\n\tcmp\t[MouseYOld],dx\n\tje\tshort ??updateend\n??doit:\n\n;------\tAt this point we KNOW the mouse has moved.\n\tmov\tax,[MCState]\n\tand\tax,CONDHIDE+CONDHIDDEN\n\tcmp\tax,CONDHIDE+CONDHIDDEN\n\tje\tshort ??condcheck\t\t; If already hidden.\n\n;------\tWe know that the mouse is visible, we must hide it\n;\tbefore we update its position.\n\tcall\tLow_Hide_Mouse\n\n;------\tConditional region check goes here.  If the mouse falls within the \n;\tconditional region, it gets marked as hidden and no other processing\n;\toccurs.\n\ttest\t[MCState],CONDHIDE\n\tje\tshort ??condok\n\n??condcheck:\n\tcmp\tcx,[MouseCXLeft]\t\t; check adjusted x region\n\tjb\tshort ??condok\n\tcmp\tcx,[MouseCXRight]\n\tja\tshort ??condok\n\tcmp\tdx,[MouseCYUpper]\t; check adjusted y region\n\tjb\tshort ??condok\n\tcmp\tdx,[MouseCYLower]\n\tja\tshort ??condok\n\n\tor\t[MCState],CONDHIDDEN\t; flag as conditional hidden\n\tjmp short ??updateend\n\n;------\tThe mouse coordinates and flags pass all of the tests, proceed\n;\twith rendering the mouse.\n??condok:\n\tcall\tLow_Show_Mouse\n\n;------\tFinal clean up and exit.\n??updateend:\n\tmov\t[MouseXOld],cx\n\tmov\t[MouseYOld],dx\n\n??exit:\n\tcmp\t[Mouse_StackPointer],0DEADh\n\tje\t??mouse_stk_ok\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n\n??mouse_stk_ok:\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov ax, [Mouse_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, ax\t\t\t       ; Get Syatem Stack Selector\n\tmov sp, [Mouse_App_Stack_ES]           ; Get Syatem Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\tret\n\tENDP\tMouse_Int\n\n\n\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VGA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVGA_Mouse_Shadow_Buffer C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\tpush\tbp\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tbp , cx\n??restore_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 10\nmov es, ax\nmov al , 'V'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tsi,di\t\t\t\t\t; xchg the source and the dest\n\tmov\tbp , cx\n\tpush\tes\t\t\t\t\t; need to swap es and ds but\n\tpush\tds\t\t\t\t\t;   cant xchg so pop them on the\n\tpop\tes\t\t\t\t\t;   stack and pop them off the\n\tpop\tds\t\t\t\t\t;   wrong way intentionally.\n??store_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,dx\t\t\t\t\t; move past right clipped pixels\n\tadd\tdi,bx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 12\nmov es, ax\nmov al , 'G'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tret\n\n\tENDP\tVGA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n\n\tGLOBAL\tC VGA_Draw_Mouse:FAR\n\tPROC\tVGA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tbx , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , bx\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tbx , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , bx\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 14\nmov es, ax\nmov al , 'A'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tret\nENDP\tVGA_Draw_Mouse\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VESA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVESA_Mouse_Shadow_Buffer C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\t\n\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??restore_loop:\n\tmov\tah,al\n??res_inner_loop:\n\tmov\tch , [si]\n\tmov\t[es:di],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??res_same_page\n\tcall\tnext_vesa_page\n ??res_same_page:\n \tdec\tah\n\tjnz\t??res_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??res_same_page1\n\tcall\tnext_vesa_page\n ??res_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 10\nmov es,ax\nmov al ,'v'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tjmp\t??out\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\tmov\tah,al\n??store_inner_loop:\n\tmov\tch , [es:di]\n\tmov\t[si],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??store_same_page\n\tcall\tnext_vesa_page\n ??store_same_page:\n \tdec\tah\n\tjnz\t??store_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??store_same_page1\n\tcall\tnext_vesa_page\n ??store_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_entry\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 14\nmov es,ax\nmov al ,'e'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\n\tmov\tdx , [ app_vesa_window ] \n\tcall\tset_vesa_window\n\tret\n\n\tENDP\tVESA_Mouse_Shadow_Buffer\n\n\n\n;***************************************************************************\n\n\tGLOBAL\tC VESA_Draw_Mouse:FAR\n\tPROC\tVESA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\tlocal\tapp_vesa_window : word\n\n   \n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tsi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tjnz\t??same_page\n\tcall\tnext_vesa_page\n ??same_page:\n \tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??same_page1\n\tcall\tnext_vesa_page\n ??same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 14\nmov es, ax\nmov al , 's'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nmov di , 10 * 80 + 16\nmov al , 'a'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tmov\tdx , [ app_vesa_window ] \n\tcall\tset_vesa_window\n\tret\n\n\nENDP\tVESA_Draw_Mouse\n\n\n\n;************************************************************************\n\nPROC\tget_vesa_window C near\nuses\tax,bx\n\tmov\tax , 04f05h\n\tmov\tbh , 1\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\t\n\n;************************************************************************\n\nPROC\tset_vesa_window C near\nuses\tax,bx,dx\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]  \t\n\tret\nENDP\t\n\n\n;***************************************************************************\n\nPROC\tset_vesa_page C near\nUSES\tax,bx,dx\n\n\tmov\tbx , dx\n\tshl\tbx , 2\n\tmov\t[ cs: current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tset_vesa_page\n\nPROC\tnext_vesa_page C near\nUSES\tax,bx,dx\n\tmov\tbx , [ cs: current_page ]\n\tadd\tbx , 4\n\tmov\t[ cs:current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n       \tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tnext_vesa_page\n\n\n\n;***********************************************************\nEND\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/KEYIREAL.BAK",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*\t\t\t\t  (Mouse Routines)\n;*                                                                         *\n;*                    File Name : KEYIREAL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Philip W. Gorrow                         *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;* This file sort of breaks the standard of keeping all of the keyboard    *\n;* and mouse routines isolated.  This is done because the mouse and\t   *\n;* the keyboard share data, and the best way to do this is to put\t   *\n;* them in the same segment.  This should probably be split into several   *\n;* include files to help make the code clearer once it is finally put\t   *\n;* together.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   KeyNum_Translate -- Translates extended keynums to normal keynums\t   *\n;*   Stuff_Key_Word -- Stuffs a word of data into keyboard buffer          *\n;*   Stuff_Key_Num -- Stuffs a key num code into the circular buffer       *\n;*   Keystroke_Interrupt -- Real mode handler of input from the keyboard   *\n;*   Break_Interrupt -- Handles the break key interrupt                    *\n;*   Call_Interrupt_Chain -- Function PM calls to call RM interrupt chain  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tKeyboard driver -- 8086 Assembly portion;\t\t\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   *\n;***************************************************************************\n\n;---------------------------------------------------------------------------\n; Set the assembly directives\n;---------------------------------------------------------------------------\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386N\t\t\t\t; use 386 real mode instructions\nMODEL TINY\t\t\t; code must be tiny so it fits\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keyboard.inc\"\n\nCONDHIDE\t\tEQU\t08000H\t\t; bit for testing conditional region\nCONDHIDDEN\t\tEQU\t04000H\t\t; bit for testing conditional hidden\nRESTORE_VISIBLE_PAGE\tEQU\t0\nSTORE_VISIBLE_PAGE\tEQU\t1\n\n\nGLOBAL\tset_vesa_page \t:near\nGLOBAL\tset_vesa_window :near\nGLOBAL\tget_vesa_window :near\nGLOBAL\tnext_vesa_page\t:near\n\nECHOON\tequ 0\n;---------------------------------------------------------------------------\n; WARNING!!!!  All of the following code segment variables are shared by\n;   the protected mode interrupt.  Do not change these unless you make the\n;   proper changes to KEYSTRUC.INC.  If you do not know what you are doing,\n;   find someone who does!!!\n;---------------------------------------------------------------------------\nCODESEG\n\n;---------------------------------------------------------------------------\n; Begin definition of Keyboard specific variables\n;---------------------------------------------------------------------------\nSoundOn\t\tDW\t1\t; toggled by alt S\nMusicOn\t\tDW\t1\t; toggled by alt M\nKeyFlags\tDD\tREPEATON+CTRLALTTURBO\t; all but repeat for now\n\n\nBreak\t\tDW\t0\n\nKeyMouseMove\tDB\t-1,0,1\n\t\tDB\t-16,0,16\n\nScreenEdge\tDW\t320/2,0\t\t; North\n\t\tDW\t319,0\t\t; North-East\n\t\tDW\t319,138/2\t; East\n\t\tDW\t319,137\t\t; South-East\n\t\tDW\t320/2,137\t; South\n\t\tDW\t0,137\t\t; South-West\n\t\tDW\t0,138/2\t\t; West\n\t\tDW\t0,0\t\t; North-West\n\t\tDW\t320/2,138/2\t; Center\n\n\nBits\t\tDB\t01H,02H,04H,08H,10H,20H,40H,80H\n\nCondPassKey\tDW\t0220H, 0320H, 060CH, 070DH, 066AH\n\t\tDW\t0669H, 0230H, 0330H, 007DH, 017DH\n\t\tDW\t025AH, 035AH, 0200H, 0410H, 046EH\n\t\tDW\t026EH, 007CH\n\nCondPassCond\tDW\tCTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO\n\t\tDW\tCTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON\n\t\tDW\tPAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE\n\t\tDW\tTASKSWITCHABLE, BREAKON\n\nEscRoutine\tDD\t0\t; vector to execute on esc key press (0=none)\n\n; Extended raw keycodes to be converted to Westwood keycodes.\nExtCodes\tDB\t038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H\n\t\tDB\t051H,04DH,035H,01CH,037H\n\t\tDB\t046H\n; The matching Westwood keycodes.\nExtNums\t\tDB\t62,  64,  75,  76,  79,  80,  81,  83,  84,  85\n\t\tDB\t86,  89,  95, 108, 124,  0\n; If extended mapping is disabled, then these codes really are...\nExtRemap\tDB\t60,  58,  99, 104,  92,  91,  93,  96,  98, 101\n\t\tDB\t103, 102, 55,  43, 124,  0\nExtRemapEnd\tDB\t0\n\nExtKeyboard\tDB\t0\t; flag for 101/102-key keyboard\n\n\nKeyBuffer\tDW\t128 DUP(0) ; set to empty\nKeyBufferHead\tDD\t0\t; set to first entry\nKeyBufferTail\tDD\t0\t; set to head for empty buffer\nKeyLock\t\tDW\t0\t; num and caps lock bits\nKeyNums\t\tDB\t127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016\n\t\tDB\t017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032\n\t\tDB\t033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049\n\t\tDB\t050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116\n\t\tDB\t117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093\n\t\tDB\t098,103,099,104,127,127,127,122,123\n\nKeysCapsLock\tDB\t0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0\nKeysNumLock\tDB\t0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0\nKeysUpDown\tDB\t16 DUP(0) ; set to all keys up\nKeyStream\tDB\t16 DUP(0) ; set to all keys up\nPassCount\tDW\t0\nKeyStreamIndex\tDW\t0\nLastKeyE0\tDB\t0\nLastKeyE1\tDB\t0\n\n;\n; Westwood key number values of keys to pass through\n;\n;\t\t\tCAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT,\n;\t\t\tRIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN\nPassAlways\tDB\t30, 44, 57, 58, 60, 62, 64, 90, 128, 128\nPassAlwaysEnd\tDB\t128\t\t; invalid code to END PassAlways\nCtrlFlags\tDB\t0\n\nBuffer\t\tDW\t?\nTime\t\tDW\t?\n\nADJUST\t= 1\t\t\t; do not modify DRD\n\nXYAdjust\tDB\t-ADJUST, -ADJUST\t; 91 -> upleft\n\t\tDB\t-ADJUST,  0\t\t; 92 -> left\n\t\tDB\t-ADJUST,  ADJUST\t; 93 -> downleft\n\t\tDB\t 0,  0\t\t\t; 94 illegal\n\t\tDB\t 0,  0\t\t\t; 95 illegal\n\t\tDB\t 0, -ADJUST\t\t; 96 -> up\n\t\tDB\t 0,  0\t\t\t; 97 illegal (center)\n\t\tDB\t 0,  ADJUST\t\t; 98 -> down\n\t\tDB\t 0,  0\t\t\t; 99 illegal\n\t\tDB\t 0,  0\t\t\t; 100 illegal\n\t\tDB\t ADJUST, -ADJUST\t; 101 -> upright\n\t\tDB\t ADJUST,  0\t\t; 102 -> right\n\t\tDB\t ADJUST,  ADJUST\t; 103 -> downright\n\tEdgeConv\t\tDW\t8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7\n\tMouseUpdate\t\tDW\t0\n\tMouseX\t\t\tDW\t0,0\n\tLocalMouseX\t\tDW\t0\n\tMouseY\t\t\tDW\t0,0\n\tLocalMouseY\t\tDW\t0\n\tIsExtKey\t\tDB\t0\n\tExtIndex\t\tDW\t0\n\n\tKeyOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tKeyOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\t\t\n\tKeyOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tKeyCodeOffset\t\tDW\tRM_Keystroke_Interrupt\t; Offset of the code in the RM stuff.\n\tCallKeyRMIntOffset\tDW\tCall_Interrupt_Chain\t; Offset of function to call DOS timer interrupt.\n\tCallKeyRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedKeyInt\t\tDD\t0\n\n\tBrkOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tBrkOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\t\t\n\tBrkOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tBrkCodeOffset\t\tDW\tRM_Break_Interrupt\t; Offset of the code in the RM stuff.\n\tCallBrkRMIntOffset\tDW\t0\n\tCallBrkRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedBrkInt\t\tDD\t0\n\tKeyIntDisabled\t\tDD\t0\n\n\tDbgOldPMIOffset\t\tDD\t0\t; The origianl PM interrupt offset\t\t\n\tDbgOldPMISelector\tDD\t0\t; The original PM interrupt segment.\n\n;---------------------------------------------------------------------------\n; Begin definition of Mouse Specific Variables for real mode\n;---------------------------------------------------------------------------\nButton\t\t\tDB\t0\t; current value of the mouse button\nMDisabled\t\tDB\t0\t; Is the mouse driver disabled\nMInput\t\t\tDB\t1\t; Defaults to mouse input allowed.\nAdjust\t\t\tDW\t0\t; flag to adjust coordinates if necessary\nMouseStepX\t\tDW\t0\t; step values if the mouse moves at\nMouseStepY\t\tDW\t0\t;   more than one pixel at a time\nMouseOffsetX\t\tDW\t0\t; Fractional step values used if a mouse\nMouseOffsetY\t\tDW\t0\t;   moves at less than one pixel at a time\nMState\t\t\tDW\t0,0\t; Tracks if mouse is hidden (TRUE) or not (FALSE)\nMouseXOld     \t\tDW\t0\t; Holds last MouseX and MouseY to determine if \nMouseYOld     \t\tDW\t0\t;   mouse needs to be redrawn\nMCState\t\t\tDW\t0\t; Tracks if mouse conditional hidden (TRUE) or not\nMouseCXLeft\t\tDW\t0,0\t; Conditional hide mouse left x position\nMouseCYUpper\t\tDW\t0,0\t; Conditional hide mouse top y position\nMouseCXRight\t\tDW\t0,0\t; Conditional hide mouse right x position\nMouseCYLower\t\tDW\t0,0\t; Conditional hide mouse lower y position\nMouseCursor   \t\tDD\t0\t; Pointer to the mouse cursor to draw\nMouseCursorSize\t\tDW\t0\t; Pointer to buffer mouse is saved in\nMouseBuffer   \t\tDD\t0\t; Pointer to buffer mouse is saved in\nMouseXHot     \t\tDW\t0,0\t; Offset to mouse's x hot spot\nMouseYHot     \t\tDW\t0,0\t; Offset to mouse's y hot spot\nMouseBuffX\t\tDW\t0,0\t; X position background was saved at\nMouseBuffY\t\tDW\t0,0\t; Y position background was saved at\nMouseBuffW\t\tDW\t0,0\t; Width of the region saved for mouse\nMouseBuffH\t\tDW\t0,0\t; Height of the region saved for mouse\nMouseWidth\t\tDW\t0,0\t; Mouse cursor theoretical width\nMouseHeight\t\tDW\t0,0\t; Mouse cursor theoretical height\nMouseCodeOffset\t\tDW\tRM_Mouse_Interrupt\t; Offset of the code in the RM stuff.\nMouseRight\t\tDW\t0,0\nMouseBottom\t\tDW\t0,0\n\n\nShadowPtr\t\tdw\t0\nDrawMousePtr \t\tdw\t0\n\nVGAMouseDraw\t\tdw\tVGA_Draw_Mouse\nVGAMouseShadow\t\tdw\tVGA_Mouse_Shadow_Buffer\n\nVESAMouseDraw\t\tdw\tVESA_Draw_Mouse\nVESAMouseShadow\t\tdw\tVESA_Mouse_Shadow_Buffer\n\nVesaPtr\t\t\tdd\t0\t\nbanktable\t\tdd      8 dup ( 0 )\nAdjust_XPos\t\tdw \t0 , 0\nAdjust_YPos\t\tdw \t0 , 0 \n\n\t\talign 2\nKeyboard_App_Stack_ES\tdw 0\t\t; This the System Stack Offsset\nKeyboard_App_Stack_SS\tdw 0\t\t; This the System Stack Selector\nKeyboard_StackPointer\tdw 0DEADh\t; We Create a Local Application\nKeyboard_Stack\t\tdw 255 dup (0)\nKeyboard_StackStart\tdw 0\n\nMouse_State\t\tdw 0\t\t; Mouse Temp Variable\nMouse_Cond\t\tdw 0\t\t; Mouse Temp Variable\nMouse_App_Stack_ES\tdw 0\t\t; This the System Stack Offsset\nMouse_App_Stack_SS\tdw 0\t\t; This the System Stack Selector\nMouse_StackPointer\tdw 0DEADh\t; We Create a Local Application\nMouse_Stack\t\tdw 255 dup (0)\nMouse_StackStart\tdw 0\n\n\n\ncurrent_page\t\tdw\t0\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Translates extended keynums to normal keynums\t   *\n;*                                                                         *\n;* INPUT:\tUWORD the keynum to translate\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated keynum                                 *\n;*                                                                         *\n;* PROTO:\tUWORD KeyNum_Translate(UWORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tKeyNum_Translate:FAR\n\tPROC\tKeyNum_Translate C FAR \n\tUSES\tcx,di,es,ds\n\tARG\tkeycode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\tmov\tes,ax\t\t\t\t; set es up for scansb\n\n\tmov\tax,[keycode]\n\ttest\t[WORD PTR KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\tmov\tcx,ExtRemap-ExtNums\n\tmov\tdi,OFFSET ExtNums\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tdi,OFFSET ExtRemapEnd\n\tdec\tdi\n\tsub\tdi,cx\n\tmov\tal,[es:di]\n??fini:\n\tret\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(WORD code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_WORD:FAR\n\tPROC\tStuff_Key_WORD C FAR \n\tUSES\tsi,bx,ds\n\tARG\tcode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\tax,[WORD PTR KeyBufferTail]\n\tmov\tsi,ax\n\tadd\tax,2\n\tand\tax,0FFh\t\t\t\t; New KeyBufferTail value.\n\tcmp\t[WORD PTR KeyBufferHead],ax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[KeyBuffer+si],bx\t\t; Record the keystroke.\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\n\tret\n\n??noroom:\n\tmov\tax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(WORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_Num:FAR\n\tPROC\tStuff_Key_Num C FAR \n\tUSES\tbx,cx,dx,di,si,ds\n\tARG\tkeycode:WORD\n\tLOCAL\ttail:WORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n\tpushf\n\tcli\t\t\t\t; disable interrupts\n\n\t; Abort key recognition if in record mode and unable\n\t; to output key due to simultaneous DOS operation.\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\tax,[MouseX]\n\tmov\t[LocalMouseX],ax\n\tmov\tax,[MouseY]\n\tmov\t[LocalMouseY],ax\n\n??cando:\n\tmov\tax,[keycode]\t\t; get the code\n\tor\tax,ax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[WORD PTR KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[WORD PTR KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tbx,1\t\t\t; double for WORD index\n\tadd\tbx,OFFSET XYAdjust\n\tmov\tax,[bx]\t\t\t; get x,y add value\n\n\tmov\tbl,ah\n\tcbw\n\txchg\tax,bx\n\tcbw\n\txchg\tax,bx\t\t\t; AX = mouse x delta, BX = mouse y delta\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tdx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tdx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tbx,dx\t\t\t; add speed for y index\n\tmov\tbl,[KeyMouseMove+bx] \t; get speed for y delta\n\txchg\tax,bx\t\t\t; swap with ax to extend sign\n\tcbw\n\txchg\tax,bx\n\txchg\tbx,dx\t\t\t; save mouse y delta\n\tadd\tbx,ax\t\t\t; add speed for x index\n\tmov\tal,[KeyMouseMove+bx]\t; get speed for x delta\n\tcbw\n\txchg\tbx,dx\t\t\t; restore mouse y delta\n\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tbx,011b\t\t\t; Y = 1, 0, 3\n\tand\tax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tbx,011b\t\t\t; Y = 3, 0, 1\n\tand\tax,011b\t\t\t; X = 3, 0, 1\n\tshl\tbx,1\n\tshl\tbx,1\n\tor\tbx,ax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tbx,1\n\tmov\tbx,[EdgeConv+bx]\n\tshl\tbx,1\n\tshl\tbx,1\n\tmov\tax,[ScreenEdge+bx]\t; New absolute X\n\tmov\tbx,[ScreenEdge+bx+2] ; New absolute Y\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\tax,ax\n\tmov\t[LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tbx,bx\n\tmov\t[LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\tmov\t[MouseX],ax\n\tmov\t[MouseY],bx\n\tcmp\t[MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n\n\tcall\tLow_Hide_Mouse\n\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\tax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],ax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tsi,[WORD KeyBufferTail]\n\tmov\t[tail],si\t\t; Safety record.\n\tmov\tdi,[WORD PTR KeyBufferHead]\n\n\t; Record the base keycode (if there is room).\n\tpush\tax\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\tax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tpush\t[LocalMouseX]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tpush\t[LocalMouseY]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tbx,0101h\t\t; Bit control tools.\n\tmov\tax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[WORD PTR KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tmov\tcl,3\n\tshr\tdi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[KeysUpDown+di]\n\tje\tshort ??notalready\n\ttest\t[WORD PTR KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[KeysUpDown+di],bh\t; Force key bit to zero.\n\tor\t[KeysUpDown+di],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\tax,1\n\tjmp short ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\tax,[tail]\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\t\t\t; Signal an error.\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tStuff_Key_Num\n;***********************************************************\n\n\n\n;***************************************************************************\n;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard       *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Keystroke_Interrupt\n\tGLOBAL\tC Keystroke_Interrupt:FAR\n\tPROC\tKeystroke_Interrupt C FAR \n\nIF 0\n\tpush\tax\n\tinc\tax\n\tpop\tax\n\tiret\n\nELSE\n\tpush\tax\n\tpush\tbx\n\tpush\tcx\n\tpush\tdi\n\tpush\tds\n\tpush\tdx\n\tpush\tes\n\tpush\tsi\n\tcld\n\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tds,ax\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov cx, ss\t\t\t\t; get SS\n\tmov [Keyboard_App_Stack_ES], sp\t\t; Protect ES\n\tmov [Keyboard_App_Stack_SS], cx\t\t; Protect SS\n\tlea dx, [Keyboard_StackStart ]\t\t; Compute Local Stack size\n\tand dx, -2;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov sp, dx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n\tcmp\t[WORD PTR PMIssuedKeyInt],0; Check to see if PM made Int call.\n\tmov\t[WORD PTR PMIssuedKeyInt],0; Make it false.\t\t\n\tjne\t??passcode\t; if so, just call Int Chain.\n\n\n\tmov\tdx,[WORD PTR KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\tmov\tax,040H\t\t\t; BIOS segment\n\tmov\tes,ax\t\t\t; put in es\n\ttest\t[BYTE PTR es:017H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR es:017H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR es:096H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tes,ax\n\n\tcld\t\t\t\t; clear direction flag for strings\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tbx,0101H\t\t; set key to a make by default\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\n\t;\n\t; New CODE to montior key stream\n\t;\n\tmov\tbx,[KeyStreamIndex]\n\tmov\t[KeyStream+bx],al\n\tinc\tbx\n\tand\tbx,15\n\tmov\t[KeyStreamIndex],bx\n\tmov\tbx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[LastKeyE1]\t\t; yes, dec the count\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[IsExtKey],TRUE\t; it is an extended key\n\tmov\tdi,OFFSET ExtCodes\t; get offset of extended codes table\n\tmov\tcx,(ExtNums-ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\tmov\tal,[(ExtNums - ExtCodes) - 1 + di] ; get the match\n\tmov\t[IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tdi,ax\t\t\t; use code as an index\n\tand\tdi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[KeyNums+di]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[KeysUpDown+8],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[KeysUpDown+7],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[KeysUpDown + 7],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\tax\n\tcall\tKeyNum_Translate\n\tadd\tsp,2\n\n;------\tSet the shift bit if necessary.\n\ttest\t[KeysUpDown+5],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[KeysUpDown+7],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tshr\tdi,1\n\tshr\tdi,1\n\tshr\tdi,1\n\tmov\tbx,ax\n\tand\tbx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[Bits+bx]\t\t; get the bit to test\n\ttest\t[KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[KeysCapsLock+di]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[KeysNumLock+di]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\t\n\t\t\t\t\t; keyboard buffer.\n\ttest\tdx,DEBUGINT\n\tjz\t??not_toggle \n\n\nIF DEBUG\n\tcmp\t[KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\tcmp\tax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\tax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\tax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\t\n\tcmp\tax,125\n\tjne\t??not_toggle\n\tmov\t[KeyIntDisabled],1\n\tjmp\t??absorbcode\nENDIF\n\n??not_toggle:\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\tax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\tax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\tax,0230h\n\tje\tshort ??breaker\n\tcmp\tax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n\tcmp\tax,0420H\t\t; is this an alt s\n\tjne\tshort ??checkmusic\t; toggle the Sound variable\n\tpush\tax\n\tmov\tax,[SoundOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??checkmusic:\n\tcmp\tax,0434H\t\t; is this an alt m\n\tjne\tshort ??esc\t\t; toggle the Music variable\n\tpush\tax\n\tmov\tax,[MusicOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??esc:\n\n\tpush\tax\n\tcall\tStuff_Key_Num\n\tpop\tax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\tax\n\tcall\t[EscRoutine]\n\tpop\tax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tdi,OFFSET PassAlways\t; get offset to table\n\tmov\tcx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1\n\trepne\tscasb\t\t\t; look for a match\n\tor\tcx,cx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n\n\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tdi,OFFSET CondPassKey\t; get offset to cond key table\n\tmov\tcx,(CondPassCond-CondPassKey) ; get number of entries\n\tshr\tcx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(CondPassCond - CondPassKey) - 2 + di]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tdx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\n\tinc\t[cs:PassCount]\n\n;mov   ax , 0B000h\n;mov   es, ax \n;inc   [BYTE PTR es : 40h]\n\n\t; Now it is time to set up for the call to the System Keyboard\n\t; interrupt handler.\n\t; 1 -Restore System Stack Pointer Selector before exit Interrupt\n\t; 2- We Create a Returning Point from Interrupt by Push A\n \t;    Interupt Stack Frame into the Stack Pointer\n\t; 3- We make a Far jump to the interuupt handler\n\tcmp [Keyboard_StackPointer],0DEADh\n\tje  ??stackok\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n??stackok:\n\tcli\t\t\t\t       ; disable Interrupts\n\tmov dx, [Keyboard_App_Stack_SS]       \n\tmov ss, dx\t\t\t       ; Get System Stack Selector\n\tmov sp, [Keyboard_App_Stack_ES]      ; Get System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n\tlea\tdx, [??Call_Back_Keyboard]   ; Get Return address offset\n \tpushf\t\t\t\t      ; push flags\t\n\tpush\tcs\t\t\t      ; push Code segment\n\tpush\tdx\t\t\t      ; push Offset\n\n\t; Now we need to simulate an interrup call by using ired\n\t; because we still want to come back here from the\n\t; Old Keyboard interrupt handle.\n\tpushf\n\tpush\t[word ptr KeyOldRMI + 2] \t; push orig segment.\n\tpush    [word ptr KeyOldRMI]   \t\t; push orig offset.\n\tiret\t \t\t        \t; call interrupt\t\n\n??absorbcode:\n\n;mov   ax , 0B000h\n;mov   es, ax \n;inc   [BYTE PTR es : 0h]\n\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tax,040h\t\t\t\t; BIOS paragraph is always @ 040h\n\tmov\tes,ax\t\t\t\t; put in es as BIOS paragraph\n\tmov\tal,[es:96h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[es:96h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\n\tcmp [Keyboard_StackPointer],0DEADh\n\tje  ??stackok2\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n??stackok2:\n\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov dx, [Keyboard_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, dx\t\t\t       ; Get Syatem Stack Selector\n\tmov sp, [Keyboard_App_Stack_ES]        ; Get Syatem Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n??Call_Back_Keyboard:\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tiret\t\nENDIF\n\n\tENDP\tKeystroke_Interrupt\n\n;***************************************************************************\n;* Break interrupt routines begin here!\n;***************************************************************************\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles the break key interrupt                      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Break_Interrupt\n\tGLOBAL\tC Break_Interrupt:FAR\n\tPROC\tBreak_Interrupt C FAR\n\n\n\tpushf\n\tpush\tax\n\tpush\tes\n\n\tmov\tax,0B000h\t\t; ES:DI = Mono RAM address.\n\tmov\tes,ax\n\tinc\t[BYTE PTR es:0]\n\t\t\n\n\tpop\tes\n\tpop\tax\n\tpopf\n\n\n\tiret\t\n\n\tENDP\tBreak_Interrupt\n\n;**************************************************************************\n;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                                  *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nCall_Interrupt_Chain:\n\tpushf\n\tcall\tKeystroke_Interrupt ;[KeyOldRMI]\n\tretf\n\n;----------------------------------------------------------------------------\n; LOW_HIDE_MOUSE:\n;\n; This function hides the mouse cursor on the screen if it was shown.  It \n; will not hide the mouse if it is already hidden.\n;\n; PROTOTYPE:\n;\n;\tVOID Low_Hide_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Hide_Mouse:FAR\n\tPROC\tLow_Hide_Mouse C FAR \n\tUSES\tax,bx,cx,dx,ds\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n   \tcmp\t[MDisabled],0\t\t; check if mouse is disabled\n\tjne\tshort ??end\n\n   \tcmp\t[MState],0\t\t; check if it was hidden before\n\tjne\tshort ??endnodraw\t\t; no need to hide again\n\n;------\tMove the saved graphic buffer to the seenpage to hide the mouse.\n;\tcall\tBuffer_To_Page C,[buffx],[buffy],[buffw],[buffh],[MouseBuffer],SEENPAGE\n\tmov\tax,RESTORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tRecord that the mouse has been hidden.\n??endnodraw:\n\tadd\t[MState],1\n\tadc\t[MState],0\n\n??end:\n\tret\n\n\tENDP\tLow_Hide_Mouse\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; LOW_SHOW_MOUSE:\n;\n; This function displays the mouse cursor on the screen if it was hidden.\n;\n; PROTOTYPE:\n;\tVOID Low_Show_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Show_Mouse:FAR\n\tPROC\tLow_Show_Mouse C FAR \n\tUSES \tax,bx,cx,dx,si,di,ds,es\n\tLOCAL\tmousex:WORD\t\t; Draw X position.\n\tLOCAL\tmousey:WORD\t\t; Draw Y position.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n;-----\tDon't show the mouse if it is not hidden, disabled.\n\tcmp\t[MDisabled],0\t\t; is the mouse disabled\n\tjne\t??exit\t\t\t; if so then exit\n\n\tcmp\t[MState],0\t\t; is the mouse already visible\n       \tje\t??exit\t\t\t; if so then exit\n\n\tdec\t[MState]\n\tcmp\t[MState],0\t\t; can the mouse be shown\n       \tjne\tshort ??exit\n\n;------\tDetermine the drawing position of the mouse.\n\tmov\tcx,[MouseWidth]\t\t; Theoretical buffer width (pixel).\n\tmov\tdx,[MouseHeight]\t; Theoretical buffer height (pixel).\n\n\tmov\tax,[MouseX]\n;\tsub\tax,[MouseXHot]\n\tmov\t[mousex],ax\t\t; Draw X pixel.\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??xnotneg\n;\tadd\tcx,ax\t\t\t; Reduce width accordingly.\n;\tmov\tax,0\n??xnotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n\tmov\tbx,[MouseY]\n;\tsub\tbx,[MouseYHot]\n\tmov\t[mousey],bx\t\t; Draw Y pixel.\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??ynotneg\n;\tadd\tdx,bx\t\t\t; Reduce height of mouse accordingly.\n;\tmov\tbx,0\n??ynotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n;------\tDetermine the theoretical coordinates and dimensions of the\n;\tarea the mouse shape will be rendered upon.\n\tmov\t[MouseBuffX],ax\n\tmov\t[MouseBuffY],bx\n\tmov\t[MouseBuffW],cx\n\tmov\t[MouseBuffH],dx\n\n;------\tMove the area that will be drawn upon, to the graphic buffer.\n\tmov\tax,STORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tDraw the mouse shape to the seenpage.\n\tpush\t[mousey]\n\tpush\t[mousex]\n\tpush\tcs\n\tcall\t[ DrawMousePtr ]\n\tadd\tsp,4\n??exit:\n\tret\n\n\tENDP\tLow_Show_Mouse\n\n;----------------------------------------------------------------------------\n;----------------------------------------------------------------------------\n\tGLOBAL\tC Mouse_KeyNum:FAR\n\tPROC\tMouse_KeyNum C FAR \n\tUSES\tbx\n\tARG\tstate:WORD\t\t; Current mouse state.\n\tLOCAL\tkeynum:WORD\t\t; Determined keynum.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\t[keynum],KN_MOUSE_MOVE\t; Presume just a mouse move.\n\tmov\tbx,[state]\n\tmov\tax,bx\n\txor\tbl,[Button]\t\t; Bits of state change.\n\tje\tshort ??fini\n\tmov\t[Button],al\t\t; Record new mouse state.\n\n\ttest\tbl,0010b\n\tje\tshort ??notright\n\tmov\t[keynum],KN_RMOUSE\n\ttest\tal,0010b\n\tjne\tshort ??notright\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notright:\n\n; DRD\n; note:  the left mouse button has priority over the right mouse button\n; this should be changed at a later date to process them independently\n\n\ttest\tbl,0001b\n\tje\tshort ??notleft\n\tmov\t[keynum],KN_LMOUSE\n\ttest\tal,0001b\n\tjne\tshort ??notleft\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notleft:\n\n??fini:\n\tmov\tax,[keynum]\n\tret\n\n\tENDP\tMouse_KeyNum\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; MOUSE_INT:\n;\n; This routine is called automatically when the Mouse_Int is installed.  It\n; automatically updates the global variables stored in the code segment so\n; that the mouse information is automatically known at all times.\n;\n; INPUTS (from int):\tAX = condition mask ( bit 0 == cursor position chg,\n;\t\t\t\t\t      bit 1 == left button press,\n;\t\t\t\t\t      bit 2 == left button release,\n;\t\t\t\t\t      bit 3 == right button press,\n;\t\t\t\t\t      bit 4 == right button release,\n;\t\t\t\t\t      5-15  == not used )\n;\t\t\tBX = button state   ( bit 0 == left button down,\n;\t\t\t\t\t      bit 1 == right button down,\n;                                             bit 2 == middle button down.\n;\t\t\t\t\t      3-15  == not used )\n;\t\t\tCX = cursor coordinate (horizontal axis)\n;\t\t\tDX = cursor coordinate (vertical axis)\n;\t\t\tDI = horizontal mouse count (mickeys)\n;\t\t\tSI = vertical mouse count (mickeys)\n;\n; RETURNS:\t\tnone\n;\n; MODIFIES:\t\tmodifies the variables _Button, _ButtonChange,\n;\t\t\t_MouseX,_MouseY,_ButtonLatch\n;\n; PROTOTYPE:\n;\tThis routine is called from an interrupt.\n;----------------------------------------------------------------------------\nlabel RM_Mouse_Interrupt\n\tPROC\tMouse_Int C FAR \n\tUSES\tax,bx,cx,dx,ds,si,es,di\n\tLOCAL\tcond:WORD\t\t; Local copy of mouse event.\n\tLOCAL\tstate:WORD\t\t; Local copy of button state.\n\n\tmov\t[cs:Mouse_State],bx\n\tmov\t[cs:Mouse_Cond],ax\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov bx, ss\t\t\t\t; get SS\n\tmov [Mouse_App_Stack_ES], sp\t\t; Protect ES\n\tmov [Mouse_App_Stack_SS], bx\t\t; Protect SS\n\tlea bx, [Mouse_StackStart ]\t; Compute Local Stack size\n\tand bx, -2;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov sp, bx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n;------\tProcess the mouse interrupt only if the mouse is enabled (whether\n;\tpresent or not).\n\tcmp\t[MDisabled],0\n\tjne\t??exit\n\n\tcmp\t[MInput],0\n\tje\t??exit\n\n\n;------ This was added because of missing mouse presses and\n;\treleases during a mouse update.\n\tmov\tax,[Mouse_Cond]\n\tand\tax,0001EH \t; bits for left and right press and release\n\tjne\tshort ??dopress_release\n\n\tcmp\t[MouseUpdate],0 ; if mouse move and mouse updating exit\n\tjne\t??exit\n\n??dopress_release:\n\n;------\tIn EEGA mode mouse X coordinates as 0..639.  Make adjustment\n;\tto keep within 0..319 range.\n\tcmp\t[Adjust],1\t\t; if the x coordinate is returned\n\tjne\tshort ??noadjust\t; incorrectly then\n\tshr\tcx,1\t\t\t; adjust x coord from 640 pixel screen\n??noadjust:\n\n\n; scale mouse posX and PosY\n;\tcmp\t[Adjust_XPos] , 0\n;\tjz\tshort ??no_scaleX\n;\tpush\tdx\n;\tmov\tax , [MouseRight]\n;\timul\tcx\n;\tidiv\t[Adjust_XPos]\n;\tmov\tcx , ax\n;\tpop\tdx\n??no_scaleX:\n;\tcmp\t[Adjust_YPos] , 0\n;\tjz\tshort ??no_scaleY\n;\tmov\tax , [MouseBottom]\n;\timul\tdx\n;\tidiv\t[Adjust_YPos]\n;\tmov\tdx , ax\n??no_scaleY:\n\n;------\tKeep mouse within screen bounds.\n\tcmp\tcx,[MouseRight]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundX_ok\t\t; force it to stay at least one pixel\n\tmov\tcx,[MouseRight]\t\t\t; on the screen\n\tdec\tcx\n??boundX_ok:\n\tcmp\tdx,[MouseBottom]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundY_ok\t\t; force it to stay at least one pixel\n\tmov\tdx,[MouseBottom]\t\t\t; on the screen\n\tdec\tdx\n??boundY_ok:\n\n\tIF 0\n;------\tRemap the middle button to equal the right button.\n\ttest\tbx,04h\n\tje\t??noremap\n\tor\tbx,0010b\t\t; Set the right button bit.\n??noremap:\n\tENDIF\n\n\tmov\t[MouseX],cx\t\t; and store in mouse x\n\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\ttest\t[KeyFlags],KEYMOUSE\n\tjne\tshort ??nostuffit\n\n\tcall\tMouse_KeyNum C,[Mouse_State]\t; Convert mouse state to key number code.\n\tcall\tStuff_Key_Num C,ax\t; Record mouse keynumber code.\n??nostuffit:\n\n\n\n;------ The check for Mouse in the middle of updating CAN NOT BE MOVED\n;\tany farther up because mouse presses and releases will be LOST!!\n \tcmp\t[MouseUpdate],0\n\tjne\t??exit\n;??jexit:\n;\tjmp\t??exit\n\n\nchristopher:\n??chkxy:\n\n;------\tSignal that no mouse updating can occur at this time.\n;\tcmp\t[_MouseUpdate],0\n;\tjne\t??exit\n;\tmov\t[_MouseUpdate],1\n\n;------\tPerform any X movement grid adjustment.\n\tcmp\t[MouseStepX],0\t\t; are we stepping on the X?\n\tje\tshort ??no_x_step\t\t; no x\n\tmov\tax,cx\t\t\t; get current x_pixel\n\tmov\tcx,dx\t\t\t; save dx - it is trashed by idiv\n\tsub\tax,[MouseOffsetX]\t; get offset difference\n\tmov\tbx,[MouseStepX]\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step X\n\timul\tbx\t\t\t; ax = div * Step X\n\tadd\tax,[MouseOffsetX]\t; normalize to region offset\n\tmov\tdx,cx\t\t\t; restore dx (new MouseY)\n\tmov\tcx,ax\t\t\t; set cx (new MouseX)\n??no_x_step:\n\n;------\tPerform any Y movement grid adjustment.\n\tcmp\t[MouseStepY],0\t\t; are we stepping on the Y\n\tje\tshort ??no_step\t\t; no y\n\tmov\tax,dx\t\t\t; get current y_pixel\n\tsub\tax,[MouseOffsetY]\t; get offset difference\n\tmov\tbx,[MouseStepY]\t\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step Y\n\timul\tbx\t\t\t; ax = div * Step Y\n\tadd\tax,[MouseOffsetY]\t; normalize to region offset\n\tmov\tdx,ax\t\t\t; set dx (new MouseY)\n??no_step:\n\n;------ Here is where we store the new MouseX and MouseY values\n;\tmov\t[MouseX],cx\t\t; and store in mouse x\n;\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\n;------\tIf the mouse is hidden or its position hasn't changed, then\n;\tperform no action.\n\tcmp\t[MState],0\n\tjne\tshort ??updateend\n\tcmp\t[MouseXOld],cx\n\tjne\tshort ??doit\n\tcmp\t[MouseYOld],dx\n\tje\tshort ??updateend\n??doit:\n\n;------\tAt this point we KNOW the mouse has moved.\n\tmov\tax,[MCState]\n\tand\tax,CONDHIDE+CONDHIDDEN\n\tcmp\tax,CONDHIDE+CONDHIDDEN\n\tje\tshort ??condcheck\t\t; If already hidden.\n\n;------\tWe know that the mouse is visible, we must hide it\n;\tbefore we update its position.\n\tcall\tLow_Hide_Mouse\n\n;------\tConditional region check goes here.  If the mouse falls within the \n;\tconditional region, it gets marked as hidden and no other processing\n;\toccurs.\n\ttest\t[MCState],CONDHIDE\n\tje\tshort ??condok\n\n??condcheck:\n\tcmp\tcx,[MouseCXLeft]\t\t; check adjusted x region\n\tjb\tshort ??condok\n\tcmp\tcx,[MouseCXRight]\n\tja\tshort ??condok\n\tcmp\tdx,[MouseCYUpper]\t; check adjusted y region\n\tjb\tshort ??condok\n\tcmp\tdx,[MouseCYLower]\n\tja\tshort ??condok\n\n\tor\t[MCState],CONDHIDDEN\t; flag as conditional hidden\n\tjmp short ??updateend\n\n;------\tThe mouse coordinates and flags pass all of the tests, proceed\n;\twith rendering the mouse.\n??condok:\n\tcall\tLow_Show_Mouse\n\n;------\tFinal clean up and exit.\n??updateend:\n\tmov\t[MouseXOld],cx\n\tmov\t[MouseYOld],dx\n\n??exit:\n\tcmp\t[Mouse_StackPointer],0DEADh\n\tje\t??mouse_stk_ok\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n\n??mouse_stk_ok:\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov ax, [Mouse_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, ax\t\t\t       ; Get Syatem Stack Selector\n\tmov sp, [Mouse_App_Stack_ES]           ; Get Syatem Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\tret\n\tENDP\tMouse_Int\n\n\n\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VGA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVGA_Mouse_Shadow_Buffer C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\tpush\tbp\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tbp , cx\n??restore_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 10\nmov es, ax\nmov al , 'V'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tsi,di\t\t\t\t\t; xchg the source and the dest\n\tmov\tbp , cx\n\tpush\tes\t\t\t\t\t; need to swap es and ds but\n\tpush\tds\t\t\t\t\t;   cant xchg so pop them on the\n\tpop\tes\t\t\t\t\t;   stack and pop them off the\n\tpop\tds\t\t\t\t\t;   wrong way intentionally.\n??store_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,dx\t\t\t\t\t; move past right clipped pixels\n\tadd\tdi,bx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 12\nmov es, ax\nmov al , 'G'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tret\n\n\tENDP\tVGA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n\n\tGLOBAL\tC VGA_Draw_Mouse:FAR\n\tPROC\tVGA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tbx , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , bx\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tbx , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , bx\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 14\nmov es, ax\nmov al , 'A'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tret\nENDP\tVGA_Draw_Mouse\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VESA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVESA_Mouse_Shadow_Buffer C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\t\n\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??restore_loop:\n\tmov\tah,al\n??res_inner_loop:\n\tmov\tch , [si]\n\tmov\t[es:di],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??res_same_page\n\tcall\tnext_vesa_page\n ??res_same_page:\n \tdec\tah\n\tjnz\t??res_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??res_same_page1\n\tcall\tnext_vesa_page\n ??res_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 10\nmov es,ax\nmov al ,'v'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tjmp\t??out\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\tmov\tah,al\n??store_inner_loop:\n\tmov\tch , [es:di]\n\tmov\t[si],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??store_same_page\n\tcall\tnext_vesa_page\n ??store_same_page:\n \tdec\tah\n\tjnz\t??store_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??store_same_page1\n\tcall\tnext_vesa_page\n ??store_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_entry\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 14\nmov es,ax\nmov al ,'e'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\n\tmov\tdx , [ app_vesa_window ] \n\tcall\tset_vesa_window\n\tret\n\n\tENDP\tVESA_Mouse_Shadow_Buffer\n\n\n\n;***************************************************************************\n\n\tGLOBAL\tC VESA_Draw_Mouse:FAR\n\tPROC\tVESA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\tlocal\tapp_vesa_window : word\n\n   \n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tsi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tjnz\t??same_page\n\tcall\tnext_vesa_page\n ??same_page:\n \tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??same_page1\n\tcall\tnext_vesa_page\n ??same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 14\nmov es, ax\nmov al , 's'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nmov di , 10 * 80 + 16\nmov al , 'a'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tmov\tdx , [ app_vesa_window ] \n\tcall\tset_vesa_window\n\tret\n\n\nENDP\tVESA_Draw_Mouse\n\n\n\n;************************************************************************\n\nPROC\tget_vesa_window C near\nuses\tax,bx\n\tmov\tax , 04f05h\n\tmov\tbh , 1\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\t\n\n;************************************************************************\n\nPROC\tset_vesa_window C near\nuses\tax,bx,dx\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]  \t\n\tret\nENDP\t\n\n\n;***************************************************************************\n\nPROC\tset_vesa_page C near\nUSES\tax,bx,dx\n\n\tmov\tbx , dx\n\tshl\tbx , 2\n\tmov\t[ cs: current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tset_vesa_page\n\nPROC\tnext_vesa_page C near\nUSES\tax,bx,dx\n\tmov\tbx , [ cs: current_page ]\n\tadd\tbx , 4\n\tmov\t[ cs:current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n       \tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tnext_vesa_page\n\n\n\n;***********************************************************\nEND\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/KEYIREAL.IBN",
    "content": "\tDB  001h,000h,001h,000h,011h,000h,000h,000h,000h,000h,0FFh,000h,001h,0F0h,000h\n\tDB  010h,0A0h,000h,000h,000h,03Fh,001h,000h,000h,03Fh,001h,045h,000h,03Fh,001h\n\tDB  089h,000h,0A0h,000h,089h,000h,000h,000h,089h,000h,000h,000h,045h,000h,000h\n\tDB  000h,000h,000h,0A0h,000h,045h,000h,001h,002h,004h,008h,010h,020h,040h,080h\n\tDB  020h,002h,020h,003h,00Ch,006h,00Dh,007h,06Ah,006h,069h,006h,030h,002h,030h\n\tDB  003h,07Dh,000h,07Dh,001h,05Ah,002h,05Ah,003h,000h,002h,010h,004h,06Eh,004h\n\tDB  06Eh,002h,07Ch,000h,008h,000h,008h,000h,010h,000h,010h,000h,010h,000h,010h\n\tDB  000h,020h,000h,020h,000h,040h,000h,040h,000h,080h,000h,080h,000h,000h,001h\n\tDB  000h,004h,000h,004h,000h,004h,000h,001h,000h,000h,000h,000h,038h,01Dh,052h\n\tDB  053h,04Bh,047h,04Fh,048h,050h,049h,051h,04Dh,035h,01Ch,037h,046h,03Eh,040h\n\tDB  04Bh,04Ch,04Fh,050h,051h,053h,054h,055h,056h,059h,05Fh,06Ch,07Ch,000h,03Ch\n\tDB  03Ah,063h,068h,05Ch,05Bh,05Dh,060h,062h,065h,067h,066h,037h,02Bh,07Ch,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,07Fh,06Eh\n\tDB  002h,003h,004h,005h,006h,007h,008h,009h,00Ah,00Bh,00Ch,00Dh,00Fh,010h,011h\n\tDB  012h,013h,014h,015h,016h,017h,018h,019h,01Ah,01Bh,01Ch,02Bh,03Ah,01Fh,020h\n\tDB  021h,022h,023h,024h,025h,026h,027h,028h,029h,001h,02Ch,01Dh,02Eh,02Fh,030h\n\tDB  031h,032h,033h,034h,035h,036h,037h,039h,064h,03Ch,03Dh,01Eh,070h,071h,072h\n\tDB  073h,074h,075h,076h,077h,078h,079h,05Ah,07Dh,05Bh,060h,065h,069h,05Ch,061h\n\tDB  066h,06Ah,05Dh,062h,067h,063h,068h,07Fh,07Fh,07Fh,07Ah,07Bh,000h,000h,0FEh\n\tDB  087h,0FFh,0C0h,01Fh,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,038h,0EFh,001h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,01Eh,02Ch,039h,03Ah,03Ch,03Eh,040h,05Ah\n\tDB  080h,080h,080h,000h,000h,000h,000h,000h,0FFh,0FFh,0FFh,000h,0FFh,001h,000h\n\tDB  000h,000h,000h,000h,0FFh,000h,000h,000h,001h,000h,000h,000h,000h,001h,0FFh\n\tDB  001h,000h,001h,001h,008h,000h,002h,000h,008h,000h,006h,000h,004h,000h,003h\n\tDB  000h,008h,000h,005h,000h,008h,000h,008h,000h,008h,000h,008h,000h,000h,000h\n\tDB  001h,000h,008h,000h,007h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,02Dh,00Eh,006h,011h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,0F5h\n\tDB  010h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,001h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,0F8h\n\tDB  011h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,0B2h,014h\n\tDB  05Eh,013h,063h,017h,0EAh,015h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,090h,000h,000h,000h,000h,0ADh,0DEh,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,0ADh,0DEh,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,0C8h,000h,000h,000h,051h,057h,006h,01Eh,08Ch\n\tDB  0C8h,08Eh,0D8h,08Eh,0C0h,08Bh,046h,006h,0F7h,006h,004h,000h,002h,000h,075h\n\tDB  013h,0B9h,010h,000h,0BFh,094h,000h,0F2h,0AEh,0E3h,009h,0BFh,0B4h,000h,04Fh\n\tDB  02Bh,0F9h,026h,08Ah,005h,01Fh,007h,05Fh,059h,0C9h,0CBh,0C8h,000h,000h,000h\n\tDB  056h,053h,01Eh,08Ch,0C8h,08Eh,0D8h,0A1h,0BAh,001h,08Bh,0F0h,005h,002h,000h\n\tDB  025h,0FFh,000h,039h,006h,0B6h,001h,074h,011h,08Bh,05Eh,006h,089h,09Ch,0B6h\n\tDB  000h,0A3h,0BAh,001h,033h,0C0h,01Fh,05Bh,05Eh,0C9h,0CBh,0B8h,001h,000h,01Fh\n\tDB  05Bh,05Eh,0C9h,0CBh,0C8h,004h,000h,000h,053h,051h,052h,057h,056h,01Eh,09Ch\n\tDB  0FAh,08Ch,0C8h,08Eh,0D8h,0A1h,0ABh,002h,0A3h,0AFh,002h,0A1h,0B1h,002h,0A3h\n\tDB  0B5h,002h,08Bh,046h,006h,00Bh,0C0h,075h,003h,0E9h,0F7h,001h,0F7h,006h,004h\n\tDB  000h,000h,010h,00Fh,084h,03Ah,001h,0F6h,0C4h,004h,00Fh,085h,033h,001h,0F7h\n\tDB  006h,004h,000h,000h,020h,074h,00Ch,03Ch,02Bh,074h,00Ch,03Ch,03Dh,074h,008h\n\tDB  03Ch,06Ch,074h,004h,03Ch,063h,075h,016h,0B0h,041h,080h,00Eh,0F6h,002h,001h\n\tDB  0F6h,0C4h,008h,00Fh,084h,00Ah,001h,080h,026h,0F6h,002h,0FEh,0E9h,002h,001h\n\tDB  03Ch,068h,075h,016h,0B0h,042h,080h,00Eh,0F6h,002h,002h,0F6h,0C4h,008h,00Fh\n\tDB  084h,0F0h,000h,080h,026h,0F6h,002h,0FDh,0E9h,0E8h,000h,0F6h,0C4h,008h,00Fh\n\tDB  085h,0E4h,000h,03Ch,061h,074h,01Eh,03Ch,05Bh,00Fh,082h,0DAh,000h,03Ch,067h\n\tDB  00Fh,087h,0D4h,000h,03Ch,05Dh,076h,00Eh,03Ch,065h,073h,00Ah,03Ch,060h,074h\n\tDB  006h,03Ch,062h,00Fh,085h,0C2h,000h,08Ah,0ECh,032h,0E4h,02Ch,05Bh,08Bh,0D8h\n\tDB  0D1h,0E3h,081h,0C3h,06Fh,002h,08Bh,007h,08Ah,0DCh,098h,093h,098h,093h,0F6h\n\tDB  0C5h,002h,075h,021h,0BAh,001h,000h,0F6h,0C5h,001h,074h,003h,083h,0C2h,003h\n\tDB  003h,0DAh,08Ah,09Fh,00Ah,000h,093h,098h,093h,087h,0DAh,003h,0D8h,08Ah,087h\n\tDB  00Ah,000h,098h,087h,0DAh,0EBh,034h,083h,0E3h,003h,025h,003h,000h,083h,0E3h\n\tDB  003h,025h,003h,000h,0D1h,0E3h,0D1h,0E3h,00Bh,0D8h,0D1h,0E3h,08Bh,09Fh,089h\n\tDB  002h,0D1h,0E3h,0D1h,0E3h,08Bh,087h,010h,000h,08Bh,09Fh,012h,000h,0A3h,0AFh\n\tDB  002h,089h,01Eh,0B5h,002h,0A1h,0AFh,002h,08Bh,01Eh,0B5h,002h,0EBh,02Fh,001h\n\tDB  006h,0AFh,002h,079h,005h,033h,0C0h,0A3h,0AFh,002h,001h,01Eh,0B5h,002h,079h\n\tDB  006h,033h,0DBh,089h,01Eh,0B5h,002h,0A1h,0AFh,002h,08Bh,01Eh,0B5h,002h,03Dh\n\tDB  03Fh,001h,07Eh,003h,0B8h,03Fh,001h,081h,0FBh,0C7h,000h,07Eh,003h,0BBh,0C7h\n\tDB  000h,0A3h,0AFh,002h,089h,01Eh,0B5h,002h,0A3h,0ABh,002h,089h,01Eh,0B1h,002h\n\tDB  083h,03Eh,0A9h,002h,000h,075h,008h,00Eh,0E8h,0A5h,003h,00Eh,0E8h,0D4h,003h\n\tDB  0B8h,02Dh,000h,089h,046h,006h,08Bh,036h,0BAh,001h,089h,076h,0FEh,08Bh,03Eh\n\tDB  0B6h,001h,050h,00Eh,0E8h,051h,0FEh,083h,0C4h,002h,00Bh,0C0h,075h,011h,08Bh\n\tDB  046h,006h,03Ch,02Dh,074h,00Dh,03Ch,041h,074h,009h,03Ch,042h,074h,005h,0EBh\n\tDB  029h,0E9h,080h,000h,0FFh,036h,0AFh,002h,00Eh,0E8h,02Eh,0FEh,083h,0C4h,002h\n\tDB  00Bh,0C0h,075h,0EEh,083h,046h,0FCh,002h,0FFh,036h,0B5h,002h,00Eh,0E8h,01Bh\n\tDB  0FEh,083h,0C4h,002h,00Bh,0C0h,075h,0DBh,083h,046h,0FCh,002h,0BBh,001h,001h\n\tDB  08Bh,046h,006h,03Ch,02Dh,074h,01Bh,03Ch,07Fh,074h,017h,0F6h,0C4h,008h,074h\n\tDB  016h,032h,0DBh,0F7h,006h,004h,000h,000h,008h,075h,00Ch,03Ch,041h,074h,008h\n\tDB  03Ch,042h,074h,004h,089h,036h,0BAh,001h,08Bh,0F8h,083h,0E7h,07Fh,0B1h,003h\n\tDB  0D3h,0EFh,08Ah,0C8h,080h,0E1h,007h,0D3h,0E3h,0F6h,0D7h,084h,09Dh,039h,002h\n\tDB  074h,00Ch,0F7h,006h,004h,000h,001h,000h,075h,004h,089h,036h,0BAh,001h,020h\n\tDB  0BDh,039h,002h,008h,09Dh,039h,002h,0B8h,001h,000h,0EBh,008h,08Bh,046h,0FEh\n\tDB  0A3h,0BAh,001h,033h,0C0h,09Dh,01Fh,05Eh,05Fh,05Ah,059h,05Bh,0C9h,0CBh,050h\n\tDB  053h,051h,057h,01Eh,052h,006h,056h,0FCh,08Ch,0C8h,08Eh,0D8h,08Ch,0D1h,089h\n\tDB  026h,08Ah,003h,089h,00Eh,08Ch,003h,0BAh,090h,007h,083h,0E2h,0FEh,0FAh,08Eh\n\tDB  0D0h,08Bh,0E2h,0FBh,083h,03Eh,0CEh,002h,000h,0C7h,006h,0CEh,002h,000h,000h\n\tDB  00Fh,085h,003h,002h,08Bh,016h,004h,000h,083h,026h,0BEh,001h,0FCh,0B8h,040h\n\tDB  000h,08Eh,0C0h,026h,0F6h,006h,017h,000h,040h,074h,005h,083h,00Eh,0BEh,001h\n\tDB  001h,026h,0F6h,006h,017h,000h,020h,074h,005h,083h,00Eh,0BEh,001h,002h,0C6h\n\tDB  006h,0B5h,000h,001h,026h,0F6h,006h,096h,000h,010h,075h,005h,0C6h,006h,0B5h\n\tDB  000h,000h,08Ch,0C8h,08Eh,0C0h,0FCh,032h,0E4h,0BBh,001h,001h,0E4h,060h,08Bh\n\tDB  01Eh,05Bh,002h,088h,087h,049h,002h,043h,083h,0E3h,00Fh,089h,01Eh,05Bh,002h\n\tDB  0BBh,001h,001h,03Ch,0E1h,075h,005h,0C6h,006h,05Eh,002h,003h,080h,03Eh,05Eh\n\tDB  002h,000h,074h,00Fh,0FEh,00Eh,05Eh,002h,0F7h,0C2h,080h,000h,00Fh,085h,08Eh\n\tDB  001h,0E9h,0CBh,001h,03Ch,0E0h,075h,008h,0C6h,006h,05Dh,002h,001h,0E9h,07Fh\n\tDB  001h,0A8h,080h,074h,007h,032h,0DBh,024h,07Fh,080h,0CCh,008h,080h,03Eh,05Dh\n\tDB  002h,000h,074h,023h,0C6h,006h,05Dh,002h,000h,0C6h,006h,0B7h,002h,001h,0BFh\n\tDB  084h,000h,0B9h,010h,000h,0F2h,0AEh,0E3h,002h,0EBh,003h,0E9h,094h,001h,08Ah\n\tDB  045h,00Fh,0C6h,006h,0B7h,002h,000h,0EBh,011h,03Ch,07Ah,075h,004h,0B0h,080h\n\tDB  0EBh,009h,08Bh,0F8h,083h,0E7h,07Fh,08Ah,085h,0C0h,001h,0F6h,006h,041h,002h\n\tDB  001h,075h,01Bh,0F6h,006h,040h,002h,004h,074h,017h,03Ch,05Ah,075h,010h,080h\n\tDB  03Eh,0B5h,000h,001h,074h,009h,0F7h,0C2h,080h,000h,075h,003h,0E9h,057h,001h\n\tDB  080h,0CCh,002h,0F6h,006h,040h,002h,050h,074h,003h,080h,0CCh,004h,050h,00Eh\n\tDB  0E8h,043h,0FCh,083h,0C4h,002h,0F6h,006h,03Eh,002h,010h,075h,007h,0F6h,006h\n\tDB  040h,002h,002h,074h,003h,080h,0CCh,001h,08Bh,0F8h,083h,0E7h,07Fh,0D1h,0EFh\n\tDB  0D1h,0EFh,0D1h,0EFh,08Bh,0D8h,083h,0E3h,07Fh,080h,0E3h,007h,08Ah,0AFh,034h\n\tDB  000h,0F7h,006h,0BEh,001h,001h,000h,074h,009h,084h,0ADh,019h,002h,074h,003h\n\tDB  080h,0F4h,001h,0F7h,006h,0BEh,001h,002h,000h,074h,009h,084h,0ADh,029h,002h\n\tDB  074h,003h,080h,0F4h,001h,088h,026h,06Ah,002h,0F7h,0C2h,000h,040h,074h,034h\n\tDB  066h,083h,03Eh,0EAh,002h,001h,075h,01Bh,03Dh,073h,000h,074h,00Ah,03Dh,076h\n\tDB  000h,072h,00Eh,03Dh,078h,000h,077h,009h,066h,0C7h,006h,0EAh,002h,000h,000h\n\tDB  000h,000h,0E9h,08Bh,000h,03Dh,07Dh,000h,075h,00Ch,066h,0C7h,006h,0EAh,002h\n\tDB  001h,000h,000h,000h,0E9h,0BAh,000h,03Dh,068h,006h,074h,075h,03Dh,04Ch,006h\n\tDB  074h,070h,03Dh,030h,002h,074h,005h,03Dh,07Eh,002h,075h,006h,0C7h,006h,008h\n\tDB  000h,001h,000h,03Dh,020h,004h,075h,00Ch,050h,0A1h,000h,000h,035h,001h,000h\n\tDB  050h,083h,0C4h,002h,058h,03Dh,034h,004h,075h,00Ch,050h,0A1h,002h,000h,035h\n\tDB  001h,000h,050h,083h,0C4h,002h,058h,050h,00Eh,0E8h,0DEh,0FBh,058h,03Ch,06Eh\n\tDB  075h,00Dh,083h,03Eh,082h,000h,000h,074h,006h,050h,0FFh,01Eh,080h,000h,058h\n\tDB  0BFh,05Fh,002h,0B9h,00Ah,000h,0F2h,0AEh,00Bh,0C9h,075h,01Bh,0BFh,03Ch,000h\n\tDB  0B9h,022h,000h,0D1h,0E9h,0F2h,0AFh,0E3h,009h,08Bh,05Dh,020h,023h,0DAh,074h\n\tDB  002h,0EBh,006h,0F7h,0C2h,004h,000h,074h,040h,02Eh,0FFh,006h,059h,002h,081h\n\tDB  03Eh,08Eh,003h,0ADh,0DEh,074h,017h,051h,057h,050h,006h,0B8h,000h,0A0h,08Eh\n\tDB  0C0h,033h,0FFh,0B9h,000h,0FAh,0B8h,001h,000h,0F3h,0AAh,007h,058h,05Fh,059h\n\tDB  0FAh,08Bh,016h,08Ch,003h,08Eh,0D2h,08Bh,026h,08Ah,003h,0FBh,0BAh,0ECh,010h\n\tDB  09Ch,00Eh,052h,09Ch,0FFh,036h,0BCh,002h,0FFh,036h,0BAh,002h,0CFh,0E4h,061h\n\tDB  08Ah,0E0h,00Ch,080h,0E6h,061h,086h,0E0h,0E6h,061h,0B8h,040h,000h,08Eh,0C0h\n\tDB  026h,0A0h,096h,000h,024h,0FDh,026h,0A2h,096h,000h,0B0h,020h,0E6h,020h,081h\n\tDB  03Eh,08Eh,003h,0ADh,0DEh,074h,017h,051h,057h,050h,006h,0B8h,000h,0A0h,08Eh\n\tDB  0C0h,033h,0FFh,0B9h,000h,0FAh,0B8h,001h,000h,0F3h,0AAh,007h,058h,05Fh,059h\n\tDB  08Bh,016h,08Ch,003h,0FAh,08Eh,0D2h,08Bh,026h,08Ah,003h,0FBh,05Eh,007h,05Ah\n\tDB  01Fh,05Fh,059h,05Bh,058h,0CFh,09Ch,050h,006h,0B8h,000h,0B0h,08Eh,0C0h,026h\n\tDB  0FEh,006h,000h,000h,007h,058h,09Dh,0CFh,09Ch,00Eh,0E8h,022h,0FDh,0CBh,050h\n\tDB  053h,051h,052h,01Eh,08Ch,0C8h,08Eh,0D8h,080h,03Eh,0F7h,002h,000h,075h,01Dh\n\tDB  083h,03Eh,003h,003h,000h,075h,00Ch,0B8h,000h,000h,050h,00Eh,0FFh,016h,051h\n\tDB  003h,083h,0C4h,002h,083h,006h,003h,003h,001h,083h,016h,003h,003h,000h,01Fh\n\tDB  05Ah,059h,05Bh,058h,0CBh,0C8h,004h,000h,000h,050h,053h,051h,052h,056h,057h\n\tDB  01Eh,006h,08Ch,0C8h,08Eh,0D8h,080h,03Eh,0F7h,002h,000h,075h,050h,083h,03Eh\n\tDB  003h,003h,000h,074h,049h,0FFh,00Eh,003h,003h,083h,03Eh,003h,003h,000h,075h\n\tDB  03Eh,08Bh,00Eh,03Fh,003h,08Bh,016h,043h,003h,0A1h,0ABh,002h,089h,046h,0FEh\n\tDB  08Bh,01Eh,0B1h,002h,089h,05Eh,0FCh,0A3h,02Fh,003h,089h,01Eh,033h,003h,089h\n\tDB  00Eh,037h,003h,089h,016h,03Bh,003h,0B8h,001h,000h,050h,00Eh,0FFh,016h,051h\n\tDB  003h,083h,0C4h,002h,0FFh,076h,0FCh,0FFh,076h,0FEh,00Eh,0FFh,016h,053h,003h\n\tDB  083h,0C4h,004h,007h,01Fh,05Fh,05Eh,05Ah,059h,05Bh,058h,0C9h,0CBh,0C8h,002h\n\tDB  000h,000h,053h,08Ch,0C8h,08Eh,0D8h,0C7h,046h,0FEh,02Dh,000h,08Bh,05Eh,006h\n\tDB  08Bh,0C3h,032h,01Eh,0F6h,002h,074h,029h,0A2h,0F6h,002h,0F6h,0C3h,002h,074h\n\tDB  00Eh,0C7h,046h,0FEh,042h,000h,0A8h,002h,075h,005h,081h,04Eh,0FEh,000h,008h\n\tDB  0F6h,0C3h,001h,074h,00Eh,0C7h,046h,0FEh,041h,000h,0A8h,001h,075h,005h,081h\n\tDB  04Eh,0FEh,000h,008h,08Bh,046h,0FEh,05Bh,0C9h,0CBh,0C8h,004h,000h,000h,050h\n\tDB  053h,051h,052h,01Eh,056h,006h,057h,02Eh,089h,01Eh,092h,007h,02Eh,0A3h,094h\n\tDB  007h,08Ch,0C8h,08Eh,0D8h,08Ch,0D3h,089h,026h,096h,007h,089h,01Eh,098h,007h\n\tDB  0BBh,09Ch,00Bh,083h,0E3h,0FEh,0FAh,08Eh,0D0h,08Bh,0E3h,0FBh,080h,03Eh,0F7h\n\tDB  002h,000h,00Fh,085h,0FAh,000h,080h,03Eh,0F8h,002h,000h,00Fh,084h,0F1h,000h\n\tDB  0A1h,094h,007h,025h,01Eh,000h,075h,009h,083h,03Eh,0A9h,002h,000h,00Fh,085h\n\tDB  0E0h,000h,083h,03Eh,0F9h,002h,001h,075h,002h,0D1h,0E9h,03Bh,00Eh,049h,003h\n\tDB  072h,005h,08Bh,00Eh,049h,003h,049h,03Bh,016h,04Dh,003h,072h,005h,08Bh,016h\n\tDB  04Dh,003h,04Ah,089h,00Eh,0ABh,002h,089h,016h,0B1h,002h,066h,0F7h,006h,004h\n\tDB  000h,000h,010h,000h,000h,075h,013h,0FFh,036h,092h,007h,00Eh,0E8h,02Ch,0FFh\n\tDB  083h,0C4h,002h,050h,00Eh,0E8h,07Bh,0F9h,083h,0C4h,002h,083h,03Eh,0A9h,002h\n\tDB  000h,00Fh,085h,092h,000h,083h,03Eh,0FBh,002h,000h,074h,019h,08Bh,0C1h,08Bh\n\tDB  0CAh,02Bh,006h,0FFh,002h,08Bh,01Eh,0FBh,002h,099h,0F7h,0FBh,0F7h,0EBh,003h\n\tDB  006h,0FFh,002h,08Bh,0D1h,08Bh,0C8h,083h,03Eh,0FDh,002h,000h,074h,015h,08Bh\n\tDB  0C2h,02Bh,006h,001h,003h,08Bh,01Eh,0FDh,002h,099h,0F7h,0FBh,0F7h,0EBh,003h\n\tDB  006h,001h,003h,08Bh,0D0h,083h,03Eh,003h,003h,000h,075h,047h,039h,00Eh,007h\n\tDB  003h,075h,006h,039h,016h,009h,003h,074h,03Bh,0A1h,00Bh,003h,025h,000h,0C0h\n\tDB  03Dh,000h,0C0h,074h,00Ch,00Eh,0E8h,016h,0FEh,0F7h,006h,00Bh,003h,000h,080h\n\tDB  074h,020h,03Bh,00Eh,00Dh,003h,072h,01Ah,03Bh,00Eh,015h,003h,077h,014h,03Bh\n\tDB  016h,011h,003h,072h,00Eh,03Bh,016h,019h,003h,077h,008h,081h,00Eh,00Bh,003h\n\tDB  000h,040h,0EBh,004h,00Eh,0E8h,01Dh,0FEh,089h,00Eh,007h,003h,089h,016h,009h\n\tDB  003h,081h,03Eh,09Ah,007h,0ADh,0DEh,074h,017h,051h,057h,050h,006h,0B8h,000h\n\tDB  0A0h,08Eh,0C0h,033h,0FFh,0B9h,000h,0FAh,0B8h,001h,000h,0F3h,0AAh,007h,058h\n\tDB  05Fh,059h,0A1h,098h,007h,0FAh,08Eh,0D0h,08Bh,026h,096h,007h,0FBh,05Fh,007h\n\tDB  05Eh,01Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,0C8h,00Ch,000h,000h,050h,053h,051h\n\tDB  052h,057h,056h,01Eh,006h,08Ch,0C8h,08Eh,0D8h,0FCh,0A1h,02Fh,003h,08Bh,01Eh\n\tDB  033h,003h,02Bh,006h,027h,003h,02Bh,01Eh,02Bh,003h,089h,046h,0FEh,089h,05Eh\n\tDB  0FCh,003h,006h,037h,003h,003h,01Eh,03Bh,003h,089h,046h,0FAh,089h,05Eh,0F8h\n\tDB  0C7h,046h,0F6h,000h,000h,0A1h,023h,003h,089h,046h,0F4h,033h,0C0h,033h,0D2h\n\tDB  08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh\n\tDB  04Eh,0FEh,08Bh,05Eh,0FAh,02Bh,00Eh,049h,003h,02Bh,01Eh,049h,003h,049h,04Bh\n\tDB  003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,003h\n\tDB  0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,02Bh,00Eh\n\tDB  04Dh,003h,02Bh,01Eh,04Dh,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h\n\tDB  0D2h,034h,005h,080h,0F2h,005h,08Ah,0E0h,084h,0D0h,00Fh,085h,0AEh,000h,00Ah\n\tDB  0C2h,074h,040h,0F6h,0C4h,008h,074h,00Dh,08Bh,05Eh,0FEh,0F7h,0DBh,089h,05Eh\n\tDB  0F6h,0C7h,046h,0FEh,000h,000h,0F6h,0C4h,002h,074h,013h,052h,08Bh,046h,0FCh\n\tDB  0F7h,0D8h,0F7h,026h,037h,003h,001h,046h,0F4h,0C7h,046h,0FCh,000h,000h,05Ah\n\tDB  0F6h,0C2h,004h,074h,006h,0A1h,049h,003h,089h,046h,0FAh,0F6h,0C2h,001h,074h\n\tDB  006h,0A1h,04Dh,003h,089h,046h,0F8h,0B8h,000h,0A0h,08Eh,0C0h,08Bh,046h,0FCh\n\tDB  0F7h,026h,049h,003h,08Bh,016h,049h,003h,08Bh,0F8h,003h,07Eh,0FEh,08Bh,01Eh\n\tDB  03Fh,003h,0C5h,036h,023h,003h,08Bh,076h,0F4h,003h,076h,0F6h,08Bh,046h,0FAh\n\tDB  08Bh,04Eh,0F8h,02Bh,046h,0FEh,07Eh,03Ch,02Bh,04Eh,0FCh,07Eh,037h,02Bh,0D0h\n\tDB  02Bh,0D8h,055h,083h,07Eh,006h,000h,075h,018h,08Bh,0E9h,08Bh,0C8h,0F3h,0A4h\n\tDB  003h,0F3h,003h,0FAh,04Dh,075h,0F5h,05Dh,007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh\n\tDB  058h,0C9h,0CBh,087h,0F7h,08Bh,0E9h,006h,01Eh,007h,01Fh,08Bh,0C8h,0F3h,0A4h\n\tDB  003h,0F2h,003h,0FBh,04Dh,075h,0F5h,05Dh,007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh\n\tDB  058h,0C9h,0CBh,0C8h,00Ch,000h,000h,050h,053h,051h,052h,057h,056h,01Eh,006h\n\tDB  08Ch,0C8h,08Eh,0D8h,08Bh,046h,006h,08Bh,05Eh,008h,02Bh,006h,027h,003h,02Bh\n\tDB  01Eh,02Bh,003h,089h,046h,0FEh,089h,05Eh,0FCh,003h,006h,03Fh,003h,003h,01Eh\n\tDB  043h,003h,089h,046h,0FAh,089h,05Eh,0F8h,0C7h,046h,0F6h,000h,000h,0C4h,006h\n\tDB  01Dh,003h,089h,046h,0F4h,033h,0C0h,033h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh\n\tDB  003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,02Bh\n\tDB  00Eh,049h,003h,02Bh,01Eh,049h,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh\n\tDB  013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,003h,0C9h,013h,0C0h,003h,0DBh,013h\n\tDB  0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,02Bh,00Eh,04Dh,003h,02Bh,01Eh,04Dh,003h\n\tDB  049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,034h,005h,080h,0F2h,005h\n\tDB  08Ah,0E0h,084h,0D0h,00Fh,085h,093h,000h,00Ah,0C2h,074h,042h,0F6h,0C4h,008h\n\tDB  074h,00Dh,08Bh,05Eh,0FEh,0F7h,0DBh,089h,05Eh,0F6h,0C7h,046h,0FEh,000h,000h\n\tDB  0F6h,0C4h,002h,074h,013h,052h,08Bh,046h,0FCh,0F7h,0D8h,0F7h,026h,03Fh,003h\n\tDB  001h,046h,0F4h,0C7h,046h,0FCh,000h,000h,05Ah,0F6h,0C2h,004h,074h,007h,08Bh\n\tDB  01Eh,049h,003h,089h,05Eh,0FAh,0F6h,0C2h,001h,074h,007h,08Bh,01Eh,04Dh,003h\n\tDB  089h,05Eh,0F8h,08Bh,046h,0FCh,0F7h,026h,049h,003h,08Bh,016h,049h,003h,08Bh\n\tDB  0F8h,003h,07Eh,0FEh,08Bh,01Eh,03Fh,003h,08Bh,076h,0F4h,003h,076h,0F6h,0B8h\n\tDB  000h,0A0h,08Eh,0D8h,08Bh,046h,0FAh,08Bh,04Eh,0F8h,02Bh,046h,0FEh,07Eh,023h\n\tDB  02Bh,04Eh,0FCh,07Eh,01Eh,02Bh,0D0h,02Bh,0D8h,08Ah,0E0h,026h,08Ah,02Ch,066h\n\tDB  046h,00Ah,0EDh,074h,002h,088h,02Dh,047h,0FEh,0CCh,075h,0F0h,003h,0F3h,003h\n\tDB  0FAh,0FEh,0C9h,075h,0E6h,007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh\n\tDB  0C8h,00Ch,000h,000h,050h,053h,051h,052h,057h,056h,01Eh,006h,08Ch,0C8h,08Eh\n\tDB  0D8h,0E8h,0B7h,002h,089h,056h,0F2h,0FCh,0A1h,02Fh,003h,08Bh,01Eh,033h,003h\n\tDB  02Bh,006h,027h,003h,02Bh,01Eh,02Bh,003h,089h,046h,0FEh,089h,05Eh,0FCh,003h\n\tDB  006h,037h,003h,003h,01Eh,03Bh,003h,089h,046h,0FAh,089h,05Eh,0F8h,0C7h,046h\n\tDB  0F6h,000h,000h,0A1h,023h,003h,089h,046h,0F4h,033h,0C0h,033h,0D2h,08Bh,04Eh\n\tDB  0FEh,08Bh,05Eh,0FAh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FEh\n\tDB  08Bh,05Eh,0FAh,02Bh,00Eh,049h,003h,02Bh,01Eh,049h,003h,049h,04Bh,003h,0C9h\n\tDB  013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,003h,0C9h,013h\n\tDB  0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,02Bh,00Eh,04Dh,003h\n\tDB  02Bh,01Eh,04Dh,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,034h\n\tDB  005h,080h,0F2h,005h,08Ah,0E0h,084h,0D0h,00Fh,085h,0C7h,000h,00Ah,0C2h,074h\n\tDB  040h,0F6h,0C4h,008h,074h,00Dh,08Bh,05Eh,0FEh,0F7h,0DBh,089h,05Eh,0F6h,0C7h\n\tDB  046h,0FEh,000h,000h,0F6h,0C4h,002h,074h,013h,052h,08Bh,046h,0FCh,0F7h,0D8h\n\tDB  0F7h,026h,037h,003h,001h,046h,0F4h,0C7h,046h,0FCh,000h,000h,05Ah,0F6h,0C2h\n\tDB  004h,074h,006h,0A1h,049h,003h,089h,046h,0FAh,0F6h,0C2h,001h,074h,006h,0A1h\n\tDB  04Dh,003h,089h,046h,0F8h,0B8h,000h,0A0h,08Eh,0C0h,08Bh,046h,0FCh,0F7h,026h\n\tDB  049h,003h,003h,046h,0FEh,083h,0D2h,000h,08Bh,0F8h,0E8h,0F1h,001h,08Bh,016h\n\tDB  049h,003h,08Bh,01Eh,03Fh,003h,0C5h,036h,023h,003h,08Bh,076h,0F4h,003h,076h\n\tDB  0F6h,08Bh,046h,0FAh,08Bh,04Eh,0F8h,02Bh,046h,0FEh,07Eh,04Fh,02Bh,04Eh,0FCh\n\tDB  07Eh,04Ah,02Bh,0D0h,02Bh,0D8h,083h,07Eh,006h,000h,075h,021h,08Ah,0E0h,08Ah\n\tDB  02Ch,026h,088h,02Dh,046h,047h,075h,003h,0E8h,0D9h,001h,0FEh,0CCh,075h,0F0h\n\tDB  003h,0F3h,003h,0FAh,073h,003h,0E8h,0CCh,001h,0FEh,0C9h,075h,0E1h,0EBh,01Fh\n\tDB  08Ah,0E0h,026h,08Ah,02Dh,088h,02Ch,046h,047h,075h,003h,0E8h,0B8h,001h,0FEh\n\tDB  0CCh,075h,0F0h,003h,0F3h,003h,0FAh,073h,003h,0E8h,0ABh,001h,0FEh,0C9h,075h\n\tDB  0E1h,08Bh,056h,0F2h,0E8h,06Ch,001h,007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h\n\tDB  0C9h,0CBh,0C8h,00Eh,000h,000h,050h,053h,051h,052h,057h,056h,01Eh,006h,08Ch\n\tDB  0C8h,08Eh,0D8h,0E8h,03Eh,001h,089h,056h,0F2h,08Bh,046h,006h,08Bh,05Eh,008h\n\tDB  02Bh,006h,027h,003h,02Bh,01Eh,02Bh,003h,089h,046h,0FEh,089h,05Eh,0FCh,003h\n\tDB  006h,03Fh,003h,003h,01Eh,043h,003h,089h,046h,0FAh,089h,05Eh,0F8h,0C7h,046h\n\tDB  0F6h,000h,000h,0C4h,006h,01Dh,003h,089h,046h,0F4h,033h,0C0h,033h,0D2h,08Bh\n\tDB  04Eh,0FEh,08Bh,05Eh,0FAh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh\n\tDB  0FEh,08Bh,05Eh,0FAh,02Bh,00Eh,049h,003h,02Bh,01Eh,049h,003h,049h,04Bh,003h\n\tDB  0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,003h,0C9h\n\tDB  013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,02Bh,00Eh,04Dh\n\tDB  003h,02Bh,01Eh,04Dh,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h\n\tDB  034h,005h,080h,0F2h,005h,08Ah,0E0h,084h,0D0h,00Fh,085h,0A0h,000h,00Ah,0C2h\n\tDB  074h,040h,0F6h,0C4h,008h,074h,00Dh,08Bh,05Eh,0FEh,0F7h,0DBh,089h,05Eh,0F6h\n\tDB  0C7h,046h,0FEh,000h,000h,0F6h,0C4h,002h,074h,013h,052h,08Bh,046h,0FCh,0F7h\n\tDB  0D8h,0F7h,026h,03Fh,003h,001h,046h,0F4h,0C7h,046h,0FCh,000h,000h,05Ah,0F6h\n\tDB  0C2h,004h,074h,006h,0A1h,049h,003h,089h,046h,0FAh,0F6h,0C2h,001h,074h,006h\n\tDB  0A1h,04Dh,003h,089h,046h,0F8h,08Bh,046h,0FCh,0F7h,026h,049h,003h,003h,046h\n\tDB  0FEh,083h,0D2h,000h,08Bh,0F8h,0E8h,07Eh,000h,08Bh,016h,049h,003h,08Bh,01Eh\n\tDB  03Fh,003h,08Bh,076h,0F4h,003h,076h,0F6h,0B8h,000h,0A0h,08Eh,0D8h,08Bh,046h\n\tDB  0FAh,08Bh,04Eh,0F8h,02Bh,046h,0FEh,07Eh,02Ch,02Bh,04Eh,0FCh,07Eh,027h,02Bh\n\tDB  0D0h,02Bh,0D8h,08Ah,0E0h,026h,08Ah,02Ch,046h,00Ah,0EDh,074h,002h,088h,02Dh\n\tDB  047h,075h,003h,0E8h,067h,000h,0FEh,0CCh,075h,0ECh,003h,0F3h,003h,0FAh,073h\n\tDB  003h,0E8h,05Ah,000h,0FEh,0C9h,075h,0DDh,08Bh,056h,0F2h,0E8h,01Bh,000h,007h\n\tDB  01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,050h,053h,0B8h,005h,04Fh,0B7h\n\tDB  001h,0B3h,000h,02Eh,0FFh,01Eh,05Dh,003h,05Bh,058h,0C3h,050h,053h,052h,0B8h\n\tDB  005h,04Fh,0B7h,000h,0B3h,000h,02Eh,0FFh,01Eh,05Dh,003h,05Ah,05Bh,058h,0C3h\n\tDB  050h,053h,052h,08Bh,0DAh,0C1h,0E3h,002h,02Eh,089h,01Eh,09Eh,00Bh,02Eh,08Bh\n\tDB  097h,061h,003h,0B8h,005h,04Fh,0B7h,000h,0B3h,000h,02Eh,0FFh,01Eh,05Dh,003h\n\tDB  05Ah,05Bh,058h,0C3h,050h,053h,052h,02Eh,08Bh,01Eh,09Eh,00Bh,083h,0C3h,004h\n\tDB  02Eh,089h,01Eh,09Eh,00Bh,02Eh,08Bh,097h,061h,003h,0B8h,005h,04Fh,0B7h,000h\n\tDB  0B3h,000h,02Eh,0FFh,01Eh,05Dh,003h,05Ah,05Bh,058h,0C3h\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/KEYSTRUC.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : KEYSTRUC.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 13, 1994                            *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nSTRUC\tKeyboardType\n\tSoundOn\t\t\tDW\t?\t; toggled by alt S\n\tMusicOn\t\t\tDW\t?\t; toggled by alt M\n\tKeyFlags\t\t\tDD\t?\t; all but repeat for now\n\tBreak\t\t\t\tDW\t?\n\tKeyMouseMove\tDB\t6  DUP(?)\n\tScreenEdge\t\tDW\t18 DUP (?)\n\tBits\t\t\t\tDB\t8  DUP (?)\n\tCondPassKey\t\tDW\t17 DUP (?) \n\tCondPassCond\tDW\t17 DUP (?)\n\tEscRoutine\t\tDD\t?\n\tExtCodes\t\t\tDB\t16 DUP (?)\n\tExtNums\t\t\tDB\t16 DUP (?)\n\tExtRemap\t\t\tDB\t16 DUP (?)\n\tExtRemapEnd\t\tDB\t?\n\tExtKeyboard\t\tDB\t?\n\tKeyBuffer\t\tDW\t128 DUP(?) ; set to empty\n\tKeyBufferHead\tDD\t?\t; set to first entry\n\tKeyBufferTail\tDD\t?\t; set to head for empty buffer\n\tKeyLock\t\t\tDW\t?\t; num and caps lock bits\n\tKeyNums\t\t\tDB\t89 DUP (?)\n\tKeysCapsLock\tDB\t16 DUP (?)\n\tKeysNumLock\t\tDB\t16 DUP (?)\n\tKeysUpDown\t\tDB\t16 DUP (?)\n\tKeyStream\t\tDB\t16 DUP (?)\n\tPassCount\t\tDW\t?\n\tKeyStreamIndex\tDW\t?\n\tLastKeyE0\t\tDB\t?\n\tLastKeyE1\t\tDB\t?\n\tPassAlways\t\tDB\t10 DUP (?)\n\tPassAlwaysEnd\tDB\t?\t\t; invalid code to END PassAlways\n\tCtrlFlags\t\tDB\t?\n\tBuffer\t\t\tDW\t?\n\tTime\t\t\t\tDW\t?\n\tXYAdjust\t\t\tDB\t26 DUP (?)\n\tEdgeConv\t\t\tDW\t16 DUP (?)\n\tMouseUpdate\t\tDW\t?\n\tMouseX\t\t\tDD\t?\n\tLocalMouseX\t\tDW\t?\n\tMouseY\t\t\tDD\t?\n\tLocalMouseY\t\tDW\t?\n\tIsExtKey\t\t\tDB\t?\n\tExtIndex\t\t\tDW\t?\n\n\tKeyOldRMI\t\t\tDD\t?\t; The origianl RM interrupt seg:off.\n\tKeyOldPMIOffset\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tKeyOldPMISelector\tDD\t?\t; The original PM interrupt segment.\n\n\tKeyCodeOffset\t\t\tDW\t?\t; Offset of the code in the RM stuff.\n\tCallKeyRMIntOffset\tDW\t?\t; Offset of function to call DOS timer interrupt.\n\tCallKeyRMIntAddr\t\tDD\t?\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedKeyInt\t\t\tDD\t?\t; did Protected mode pass this through?\n\n\tBrkOldRMI\t\t\t\tDD\t?\t; The origianl RM interrupt seg:off.\n\tBrkOldPMIOffset\t\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tBrkOldPMISelector\t\tDD\t?\t; The original PM interrupt segment.\n\n\tBrkCodeOffset\t\t\tDW\t?\t; Offset of the code in the RM stuff.\n\tCallBrkRMIntOffset\tDW\t?\t; Offset of function to call DOS timer interrupt.\n\tCallBrkRMIntAddr\t\tDD\t?\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedBrkInt\t\t\tDD\t?\t; did Protected mode pass this through?\n\tKeyIntDisabled\t\t\tDD\t?\n\n\tDbgOldPMIOffset\t\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tDbgOldPMISelector\t\tDD\t?\t; The original PM interrupt segment.\n\n\t;---------------------------------------------------------------------------\n\t; Begin definition of Mouse Specific Variables for real mode\n\t;---------------------------------------------------------------------------\n\tButton\t\t\t\tDB\t?\t; current value of the mouse button\n\tMDisabled\t\t\tDB\t?\t; Is the mouse driver disabled\n\tMInput\t\t\t\tDB\t?\t; Defaults to mouse input allowed.\n\tAdjust\t\t\t\tDW\t?\t; flag to adjust coordinates if necessary\n\tMouseStepX\t\t\tDW\t?\t; step values if the mouse moves at\n\tMouseStepY\t\t\tDW\t?\t;   more than one pixel at a time\n\tMouseOffsetX\t\tDW\t?\t; Fractional step values used if a mouse\n\tMouseOffsetY\t\tDW\t?\t;   moves at less than one pixel at a time\n\tMState\t\t\t\tDD\t?\t; Tracks if mouse is hidden (TRUE) or not (FALSE)\n\tMouseXOld     \t\tDW\t?\t; Holds last MouseX and MouseY to determine if \n\tMouseYOld     \t\tDW\t?\t;   mouse needs to be redrawn\n\tMCState\t\t\t\tDW\t?\t; Tracks if mouse conditional hidden (TRUE) or not\n\tMouseCXLeft\t\t\tDD\t?\t; Conditional hide mouse left x position\n\tMouseCYUpper\t\tDD\t?\t; Conditional hide mouse top y position\n\tMouseCXRight\t\tDD\t?\t; Conditional hide mouse right x position\n\tMouseCYLower\t\tDD\t?\t; Conditional hide mouse lower y position\n\tMouseCursor   \t\tDD\t?\t; Pointer to the mouse cursor to draw\n\tMouseCursorSize\tDW\t?\t; Size of mouse cursor draw area\n\tMouseBuffer   \t\tDD\t?\t; Pointer to buffer mouse is saved in\n\tMouseXHot     \t\tDD\t?\t; Offset to mouse's x hot spot\n\tMouseYHot     \t\tDD\t?\t; Offset to mouse's y hot spot\n\tMouseBuffX\t\t\tDD\t?\t; X position background was saved at\n\tMouseBuffY\t\t\tDD\t?\t; Y position background was saved at\n\tMouseBuffW\t\t\tDD\t?\t; Width of the region saved for mouse\n\tMouseBuffH\t\t\tDD\t?\t; Height of the region saved for mouse\n\tMouseWidth\t\t\tDD\t?\t; Mouse cursor theoretical width\n\tMouseHeight\t\t\tDD\t?\t; Mouse cursor theoretical height\n\tMouseCodeOffset\tDW\t?\t; Offset to the real mode code offset\n\tMouseRight\t\t\tDD\t?\t; Right hand side of the screen\n\tMouseBottom\t\t\tDD\t?\t; Bottom of the screen\n\n\n\tShadowPtr\t\t\tdw\t?\n\tDrawMousePtr \t\tdw\t?\n\n\tVGAMouseDraw\t\tdw\t?\n\tVGAMouseShadow\t\tdw\t?\n\n\tVESAMouseDraw\t\tdw\t?\n\tVESAMouseShadow\tdw\t?\n\n\tVesaPtr\t\t\t\tdd ?\t\n\tVesaBankTable\t   DD\t8 dup (?)\n\tAdjust_XPos\t\t\tdd ?\n\tAdjust_YPos\t\t\tdd ?\n\n\nENDS\n\n; InitFlags that are set to have a fully functional interrupt.\nIF_ALLOC_RM\t\t\tequ\t1\t\t; Allocation of RM was successful.\nIF_SET_VECTORS\t\tequ\t2\t\t; Vectors have been set.\nIF_LOCKED_PM_CODE\tequ\t4\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t8\t\t; Locked PM code for DPMI.\nIF_RATE_CHANGE\t\tequ\t10\t\t; Timer rate was changed.\nIF_FUNCTIONAL\t\tequ\t20\t\t; Timer is in and functional.\nIF_LOCKED_RM_CODE\tequ\t40\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 25, 1994                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = keyboard\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tkeyboard.obj\t&\n\tmouse.obj\t\t&\n\tpagfault.obj\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WWLIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# The keyboard object files is also dependant on an IBN file which is \n#   generated from KEYIREAL.ASM\n#---------------------------------------------------------------------------\nkeyireal.ibn: keyireal.obj\n\t%create\t$^*.rsp\n\t%append $^*.rsp $^&.obj\n\t%append $^*.rsp $^&.exe\n\t%append $^*.rsp $^&.map\n\ttlink @$^*.rsp\n        tdstrip keyireal.exe\n        ebn\tkeyireal.exe\n\nkeyireal.obj:\tkeyireal.asm\n\ttasm /zn /la /ml /m2 keyireal.asm\n\nkeyboard.obj: keyireal.ibn keyboard.asm\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/MOUSE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*\t\t\t\t  (Mouse Routines)\t\t\t   *\n;*                                                                         *\n;*                    File Name : MOUSE.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : August 26, 1994                          *\n;*                                                                         *\n;*                  Last Update : November 3, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Install_Mouse -- Initializes mouse driver and verifies mouse exists   *\n;*   Remove_Mouse -- uninstalls the mouse interrupt by disabling the call  *\n;*   Get_Mouse_X -- Returns the mouses x pixel position                    *\n;*   Get_Mouse_Y -- Returns the mouse's y pixel position                   *\n;*   Get_Mouse_Button -- Gets the values of the mouse button               *\n;*   Set_Mouse_Cursor -- Sets the shape to be used as the mouse.           *\n;*   Low_Hide_Mouse -- Low-level routine which hides the mouse\t\t   *\n;*   Low_Show_Mouse -- Low level routine which shows the mouse\t\t   *\n;*   Mouse_Shadow_Buffer -- Handles storing and restoring the mouse buffer *\n;*   Draw_Mouse -- Handles drawing the mouse cursor\t\t\t   *\n;*   Hide_Mouse -- Hides mouse cursor on screen if it was show             *\n;*   Show_Mouse -- Display mouse cursor on screen if it was hidden         *\n;*   Conditional_Hide_Mouse -- Hides mouse if its with given region        *\n;*   Conditional_Show_Mouse -- shows mouse if it was conditionally hidden  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\n;WARN\t\t\t\t; generate all warnings we can\n;JUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keystruc.inc\"\nINCLUDE \"shape.inc\"\ninclude \"svgaprim.inc\"\n\nDOS_SYS_CALL\t\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nRESTORE_VISIBLE_PAGE\tEQU\t0\nSTORE_VISIBLE_PAGE\tEQU\t1\nCONDHIDE\t\tEQU\t08000H\t\t; bit for testing conditional region\nCONDHIDDEN\t\tEQU\t04000H\t\t; bit for testing conditional hidden\n;---------------------------------------------------------------------------\n; Define any data which needs to be global...\n;---------------------------------------------------------------------------\n\nGLOBAL\tRealModePtr:DWORD\nGLOBAL\tMInstalled:DWORD\nGLOBAL\tMouseBuffer:DWORD\nGLOBAL\tLCW_Uncompress:NEAR\n\nGLOBAL\tGet_Shape_Uncomp_Size     :NEAR\nGLOBAL\tGet_Shape_Width      \t  :NEAR\nGLOBAL\tGet_Shape_Original_Height :NEAR\nGLOBAL  Size_Of_Region\t\t  :NEAR\nGLOBAL\t_ShapeBuffer\t\t  :DWORD\n\nGLOBAL  XRes\t: dword\nGLOBAL  YRes\t: dword\n\n\nGLOBAL\tVesaFunc : dword\nGLOBAL\tVesa_XRes : near\nGLOBAL\tVesa_YRes : near\n\n\n\n\n\nDPMI_INTR\tEQU\t31h\t\n\n\nSTRUC DPMI_REGS\n       _edi  dd ?\n       _esi  dd ?\t\n       _ebp  dd ?\t\n       \t     dd ?\n       _ebx  dd ?\t\n       _edx  dd ?\t\n       _ecx  dd ?\t\n       _eax  dd ?\t\n       Flags dw ?\n       _es   dw ?\n       _ds   dw ?\n       _fs   dw ?\n       _gs   dw ?\n       _ip   dw ?\n       _cs   dw ?\n       _sp   dw ?\n       _ss   dw ?\n       \t     dd ?\n\t     dd ?\n  nothing    dd ?\t\t\t\nENDS\n\n\n\n;---------------------------------------------------------------------------\n; Now lets handle any data in the data segment\n;---------------------------------------------------------------------------\n\tDATASEG\n\nRealInt\t\tDPMI_REGS <>\t; structure to call a real mode int\nMInstalled\tDD\t0\t\t; is the mouse installed?\nMouseCursor\tDD\t0\nMouseBuffer\tDD\t0\nBufferWidth\tDD\t0\nBufferHeight\tDD\t0\nBufferSize\tDD\t0\nPrevMousePtr\tDD\t0\nMouseBufferSel\tDD\t0\n\n\nDraw_Mouse\t\tdd\tVGA_Draw_Mouse\nMouse_Shadow_Buffer\tdd\tVGA_Mouse_Shadow_Buffer\n\n;---------------------------------------------------------------------------\n; Time to write some code\n;---------------------------------------------------------------------------\n\tCODESEG\n\n;***************************************************************************\n;* INSTALL_MOUSE -- Initializes mouse driver and verifies mouse connected  *\n;*                                                                         *\n;* First check the mouse interupt to see if the vector is pointing to zero *\n;* page.  If it is not then make sure it is not pointing to an IRET.  If   *\n;* not call the mouse reset to verify that the hardware is attached.\t   *\n;*                                                                         *\n;* INPUT:\tint mouse_max_width  - the max width of the mouse cursor   *\n;*\t\tint mouse_max_height - the max height of the mouse cursor  *\n;*\t\tint screen_width     - width of the physical screen\t   *\n;*\t\tint screen_height    - height of the physical screen\t   *\n;*                                                                         *\n;* OUTPUT:      TRUE is mouse driver is initialized, FALSE if unable to    *\n;*\t\tinitialize mouse driver.\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tint Install_Mouse(\tint mouse_max_width,\t\t   *\n;*\t\t\t\t\tint mouse_max_height,\t\t   *\n;*\t\t\t\t\tint screen_width,\t\t   *\n;*\t\t\t\t\tint screen_height);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/26/1994 PWG : Created.                                             *\n;*=========================================================================*\nGLOBAL\tInstall_Mouse:NEAR\nPROC\tInstall_Mouse C NEAR \n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\tmouse_max_width:DWORD\n\tARG\tmouse_max_height:DWORD\n\tARG\tscreen_width:DWORD\n\tARG\tscreen_height:DWORD\n\n\n\t;*=========================================================================*\n\t;* Initialize all of the general mouse variables\n\t;*=========================================================================*\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\ttest\tesi , esi\t\t\t; mouse driver should be install\n\tjz \t??exit\t\t\t\t; after keyboard interrup is install\n\tmov\teax , [ XRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseX],eax\t; set the mouses x coordinate to 160\n\tmov\teax , [ YRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseY],eax\t; set the mouses y coordinate to 100\n\tmov\t[(KeyboardType esi).MState],1\t; flag the mouse as hidden\n\tmov\t[(KeyboardType esi).MCState],0\t; turn off conditional region\n\tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi).MouseRight],eax\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi).MouseBottom],eax\n\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 0200, bl = number of interrupt to get\n\t; output cf error, cx,dx= address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,033h\t\t\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\t\t\t; no mouse driver present\n\n\t;*=========================================================================*\n\t;* If the interupt vector is pointing to 0000:0000h, there is no mouse\n\t;*=========================================================================*\n\tmov\tax,cx\n\tor\tax,dx\t\t\n\tjz\tshort ??nomouse\n\n\tand\tedx , 0ffffh\n\tand\tecx , 0ffffh\n\tshl\tecx,4\n\tadd\tecx,edx\n\n\t;*=========================================================================*\n\t;* If the first instruction is an IRET, there is no mouse\n\t;*=========================================================================*\n\n\tcmp\t[byte ptr ecx],0CFH\t; is this an IRET\n\tjne\tshort ??mouse_buff\t; if it isnt then reset the mouse\n\n??nomouse:\n\tmov\teax,FALSE\t\t\t\t; flag no mouse driver\n\tmov\t[MInstalled],FALSE\t\t\t; flag no mouse driver\n    \tjmp\t??exit\t\t\t\t\t; exit\n\n??mouse_buff:\n\t;*=========================================================================*\n\t;* Allocate two real mode memory buffers for the mouse cursor and the \n\t;*\tmouse shadow\n\t;*=========================================================================*\n\tmov\teax,[mouse_max_width]\t       \t; get the is max width\n\tmov\t[BufferWidth],eax\t       \t; save it off for set cursor\n\tmov\tedx,[mouse_max_height]\t       \t; get the max height\n\tmov\t[BufferHeight],edx\t       \t; save it off for set cursor\n\tmul\tedx\t\t\t       \t; size = max_width * max_height\n\tadd\teax,22\t\t\t       \t; add width/height(8) + para align(15)\n\tand\tal, 0f0h\t\t       \t; now size is even paragraphs\n\tmov\t[BufferSize],eax\t       \t; store off the buffer size\n\tshl\teax,1\t\t\t       \t; make two of them\n\n \tmov\tebx,eax\t\t\t\t; get size of RM binary.\n\tmov\tecx,eax\t\t\t\t; ecx will use it later.\n\tadd\tebx,15\t\t\t\t; round up \n\tshr\tebx,4\t\t\t\t; convert to pages.\n\tmov\teax,0100h\t\t\t; alloc real buffer\n\tint\tDPMI_INTR\t \t\t; do call.\n\tjc\t??error\t\t \t\t; check for error.\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tmov\t[MouseBufferSel], edx\n\tshl\teax , 16\n\tmov\t[(KeyboardType esi).MouseCursor],eax\t; store off the real mode segment\n\tmov\tedx,eax\t\t\t\t\t; get the buffer position\n\tadd\tedx,[BufferSize]\t\t\t; add in the buffer size\n\tmov\t[(KeyboardType esi).MouseBuffer],edx\t; store off the real mode segment\n\tshr\teax,12\t\t\t\t\t; convert the seg/off to 32 bit offset\n\tmov\tedx,eax\n\tadd\tedx,[BufferSize]\n\tmov\t[MouseCursor],eax\t\t\t; store it off in the mouse buffer\n\tmov\t[MouseBuffer],edx\t\t\t; store it off in the mouse buffer\n\n\tmov\teax,0600h\t\t\t\t; function number.\n\tmov\tecx,[MouseCursor]\t\t\t; ecx must have start of memory.\n\tmov\tedi,[BufferSize]\n\tshl\tedi,1\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n       \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n\n??begin:\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\t; Reset mouse thru int 33h funtion 0\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\txor\tecx , ecx\n\tmov\t[RealInt . _eax ] , 0\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\tmov\teax ,[RealInt . _eax]\n\tcmp\tax,-1\t\t\t\t\t; was the mouse attached to system\n      \tjne\t??nomouse\t\t\t\t; if not exit out of the routine\n\t\n\tmov\t[(KeyboardType esi).Adjust],0\t\t; assume we do not need to adjust mouse\n\n;***************************************************************************\n; Set the Vesa Parameters \n\n\tmov\teax , [ VesaFunc ]\n\ttest\teax , eax\n\tjz\t??set_vga_mouse\n\tmov\t[(KeyboardType esi). VesaPtr ] , eax\n\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VESA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VESA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n \tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi). MouseRight ] , eax\n\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi). MouseBottom ] , eax\n\n\tlea\tedi , [(KeyboardType esi). VesaBankTable]\n\tlea\tesi , [ BankTable ]\n\tmov\tecx , 8\n\trep\tmovsd\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tjmp\t??end_vesa\n\n??set_vga_mouse:\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VGA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VGA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n??end_vesa:\n\tcall \tReset_Mouse \n\tmov\teax , TRUE\n\tret\n\n??error:\n\tmov\teax,FALSE\n??exit:\n\tret\n\tENDP\tInstall_Mouse\n\n;***************************************************************************\n;* ResET_MOUSE -- Reset mouse to a new graphif mode\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* reset mouse driver funtions to a a currently graphic mode\t\t   *\t\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;* PROTO:\tReset_Mouse ( void ) \t\t\t\t\t   *\t\n;*\t\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/26/1994 JRJ : Created.                                             *\n;*=========================================================================*\nGLOBAL\tReset_Mouse:NEAR\nPROC\tReset_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\n\t;*=========================================================================*\n\t;* Initialize all of the general mouse variables\n\t;*=========================================================================*\n\tmov\tesi , [RealModePtr]\t\t; get offset of real mode data start\n\ttest\tesi , esi\n\tjz\t??exit\n\tmov\teax , [ XRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseX],eax\t; set the mouses x coordinate to 160\n\tmov\teax , [ YRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseY],eax\t; set the mouses y coordinate to 100\n\tmov\t[(KeyboardType esi).MState],1\t; flag the mouse as hidden\n\tmov\t[(KeyboardType esi).MCState],0\t; turn off conditional region\n\tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi).MouseRight],eax\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi).MouseBottom],eax\n\n\n\tmov\t[(KeyboardType esi).Adjust],0\t\t; assume we do not need to adjust mouse\n\n;***************************************************************************\n; Set the Vesa Parameters \n\n\tmov\teax , [ VesaFunc ]\n\ttest\teax , eax\n\tjz\t??set_vga_mouse\n\tmov\t[(KeyboardType esi). VesaPtr ] , eax\n\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VESA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VESA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n \tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi). MouseRight ] , eax\n\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi). MouseBottom ] , eax\n\n\tlea\tedi , [(KeyboardType esi). VesaBankTable]\n\tlea\tesi , [ BankTable ]\n\tmov\tecx , 8\n\trep\tmovsd\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tjmp\t??end_vesa\n\n??set_vga_mouse:\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VGA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VGA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n\n??end_vesa:\n       ; S Mickey/pixel Ratio cursor limits \n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 8\n\tmov\tedx , 16\n\tmov\t[RealInt . _eax ] , 0fh\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\t; Set Min/Max X pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 0\t \n\tmov\tedx , [ XRes ]\n\tcmp\tedx , 320\n\tjne\t??set_it\n\tshl\tedx , 1\n\tmov\t[(KeyboardType esi).Adjust],1\n\n??set_it:\n;\tdec\tedx\n\tmov\t[RealInt . _eax ] , 7\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\t; Set Min/Max Y pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 0\n\tmov\tedx , [ YRes ]\n\tdec\tedx\n\tmov\t[RealInt . _eax ] , 8\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\nIF 0\n\t; Check for scale factors in X and Y pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , [ XRes ]\n\tmov\tedx , [ YRes ]\n\tsub\tecx , 8\n\tsub  \tedx , 16\n\tmov\t[RealInt . _eax ] , 4\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\t; Read mouse position thru int 33 funtion 3\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\txor\tecx , ecx\n\tmov\t[RealInt . _eax ] , 3\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\tmov\tecx ,[RealInt . _ecx]\n\tmov\tedx ,[RealInt . _edx]\n\n      ; compute Scale values X Y for different vendor mouse driver if nessesary\n\tadd \tecx , 8\n\tadd\tedx , 16\n\tcmp\tecx , [ XRes ]\n\tmov\t[(KeyboardType esi).Adjust_XPos],0\n\tjz\t??No_scaleX\n\tmov\t[(KeyboardType esi).Adjust_XPos],ecx\n??No_scaleX:\n\tcmp\tedx , [ YRes ]\n\tmov\t[(KeyboardType esi).Adjust_YPos],0\n\tjz\t??No_scaleY\n\tmov\t[(KeyboardType esi).Adjust_YPos],edx\n??No_scaleY:\t\nENDIF\n\n\tmov\tecx, [ XRes ]\t\t\t\t; set the mouses x coordinate to 160\n\tmov\tedx, [ YRes ]\t\t\t\t; set the mouses x coordinate to 160\n\tcmp\t[(KeyboardType esi).Adjust],1\n\tje\t??no_ecx_shift\n\tshr\tecx , 1\n??no_ecx_shift:\n\tshr\tedx , 1\n\tmov\t[MInstalled],TRUE\t\t\t; set the fact that mouse is installed\n\tmov\t[(KeyboardType esi).MDisabled],TRUE\t; disable mouse until the overlay is loaded\n\n\t; Set new Mouse position any way\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\t[RealInt . _eax ] , 4\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\tcall\tClear_RM_regs\n\tmov\teax, 0300h\n\tmov\tebx ,33h\t\t\t\t; mouse is in 33h\n\tmov\tecx,0\t\t\t\t\t; any mouse condition generates int\n\tmov\tedx,[RealModePtr]\t\t\t; get real mode memory address\n\tshr\tedx,4\t\t\t\t\t; convert it to a segment\n\tmov\t[RealInt. _es],dx\t\t\t; store it in the real mode es\n\tmovzx\tedx,[(KeyboardType PTR esi).MouseCodeOffset] ; Get address of code\n\tmov\t[RealInt._edx],edx\t\t\t; set edx to offset of code\n\tmov\t[RealInt._eax],12\t\t\t; set eax to set interrupt routine\n\tmov\t[RealInt._ecx],31\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n??installed:\n\tmov\teax,TRUE  \t\t\t\t; return TRUE if all is well\n\tmov\t[(KeyboardType esi).MDisabled],FALSE\t; no 32 bit overlays installed\n\tje\t??exit\n\n??error:\n\tmov\teax,FALSE\n\n??exit:\n\tret\n\tENDP\tReset_Mouse\n\n\n\n;***************************************************************************\n;* REMOVE_MOUSE -- uninstalls the mouse interrupt by disabling the call\t   *\n;*                                                                         *\n;* This routine will uninstall the mouse interrupt.  It does this by\t   *\n;* simply disabling the call condition.  The interrupt itself is still\t   *\n;* present, just uncalled until dos removes it at program termination.\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Remove_Mouse(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tRemove_Mouse:NEAR\n\tPROC\tRemove_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\t\n\n\tcall\tClear_RM_regs\n\tcmp \t[MInstalled],FALSE\t; check to see if mouse installed\n\tje\t??exit\t\t\t; if not then no need to remove it\n\n\tmov\t[MInstalled],FALSE\t; Force to NOT-Installed.\n\n;;PWG\tcmp \t[_MSWIFTDevice],1\t; check to see if SWIFT device installed\n;;PWG\tje\tshort ??prevSWIFT\t\t; if so use previous SWIFT event handler\n\n\tmov\tebx , 033h\n\tmov\tedx,[RealModePtr]\t\t\t; get real mode memory address\n\ttest\tedx,edx\t\t\t\t\t; check that the memory block is valid\n\tjz\t??exit\n\n\tshr\tedx,4\t\t\t\t\t; convert it to a segment\n\tmov\t[RealInt._es],dx\t\t\t; store it in the real mode es\n\txor\tedx,edx\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\tmov\tdx,[(KeyboardType PTR esi).MouseCodeOffset] ; Get address of code\n\tmov\t[RealInt._edx],edx\t\t\t; set edx to offset of code\n\tmov\t[RealInt._eax],12\t\t\t; set eax to set interrupt routine\n\tmov\t[RealInt._ecx],0\n\tmov\tecx,0\t\t\t\t\t; no mouse condition generates an int\n\tmov\teax,0300h\n\tlea\tedi,[RealInt]\n\tint\tDPMI_INTR\n\n\tmov\teax,0601h\t\t\t\t; function number.\n\tmov\tecx,[MouseCursor]\t\t\t; ecx must have start of memory.\n\tmov\tedi,[BufferSize]\n\tshl\tedi,1\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n       \tint\tDPMI_INTR\t\t\t; do call.\n\n\n\t; Deallocate real memory buffer\n\tmov\tedx ,[MouseBufferSel]\n\ttest\tdx ,dx\n\tjz\t??exit\n\tmov\teax ,0101h\n\tint\tDPMI_INTR\n\n??exit:\n\tret\n\tENDP\tRemove_Mouse\n\n\n;***************************************************************************\n\nGLOBAL\tClear_RM_regs :NEAR\nPROC\tClear_RM_regs  NEAR \n\n\tpush\teax\n\tpush\tecx\n\tpush\tedi\n\tlea\tedi , [ RealInt ]\n\tlea\tecx , [ RealInt . nothing ]\n\tsub\tecx , edi\n\txor\teax , eax\n\tshr\tecx , 2\n\trep\tstosd\n\tpop\tedi\n\tpop\tecx\n\tpop\teax\n\tret\nENDP\tClear_RM_regs\n\n\n;***************************************************************************\n;* GET_MOUSE_X -- Returns the mouses x pixel position                      *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse x position in pixels\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_X(void);                                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_X:NEAR\n\tPROC\tGet_Mouse_X C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MouseX]\n\tret\n\n\tENDP\tGet_Mouse_X\n\n;***************************************************************************\n;* GET_MOUSE_STATE -- Returns the current mouse state\t\t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse's current state\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_State(void);                                 *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_State:NEAR\n\tPROC\tGet_Mouse_State C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MState]\n\tret\n\n\tENDP\tGet_Mouse_State\n\n;***************************************************************************\n;* GET_MOUSE_X -- Returns the mouses x pixel position                      *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse x position in pixels\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_X(void);                                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_Disabled:NEAR\n\tPROC\tGet_Mouse_Disabled C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmovzx\teax,[(KeyboardType esi).MDisabled]\n\tret\n\n\tENDP\tGet_Mouse_Disabled\n\t\t\t\t  \n;***************************************************************************\n;* GET_MOUSE_Y -- Returns the mouse's y pixel position                     *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:       none\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      int - the mouses y position in pixels                      *\n;*                                                                         *\n;* PROTO:\tint Get_Mouse_Y(void);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_Y:NEAR\n\tPROC\tGet_Mouse_Y C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MouseY]\n\tret\n\n\tENDP\tGet_Mouse_Y\n\n;***************************************************************************\n;* GET_MOUSE_BUTTON -- Gets the values of the mouse button                 *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_Button:NEAR\n\tPROC\tGet_Mouse_Button C NEAR \n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\n\txor\teax,eax\n\tmov\tal,[(KeyboardType esi).Button]\n\tret\n\n\tENDP\tGet_Mouse_Button\n\n;***************************************************************************\n;* SET_MOUSE_CURSOR -- Sets the shape to be used as the mouse.             *\n;*                                                                         *\n;*    This will inform the system of the shape desired as the mouse        *\n;*    cursor.                                                              *\n;*                                                                         *\n;* INPUT:    xhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           yhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           cursor      -- Shape to use as the new mouse shape.           *\n;*                                                                         *\n;* OUTPUT:   Returns with a pointer to the original mouse shape.           *\n;*                                                                         *\n;* PROTO:\tVOID  *Set_Mouse_Cursor(\tint  xhotspot, \t\t   *\n;*\t\t\t\t\t\tint  yhotspot, \t\t   *\n;*\t\t\t\t\t\tvoid *cursor);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   02/13/1992 JLB : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tSet_Mouse_Cursor:NEAR\n\tPROC\tSet_Mouse_Cursor C NEAR \n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\txhotspot:DWORD\t\t\t\t; the x hot spot of the mouse\n\tARG\tyhotspot:DWORD\t\t\t\t; the y hot spot of the mouse\n\tARG\tcursor:DWORD\t\t\t\t; ptr to the new mouse cursor\n\n\tLOCAL\tdatasize:DWORD\n\tLOCAL\tstype:WORD\n\tLOCAL\tswidth:DWORD\t\t; Shape width.\n\tLOCAL\tsheight:DWORD\t\t; Shape height.\n\tLOCAL\tssize:DWORD\t\t; Size of raw shape.\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\n\t;-------------------------------------------------------------------\n\t; Make sure the mouse is Enabled and Installed before continuing\n\t;-------------------------------------------------------------------\n\tmov\teax,[cursor]\n\tcmp\teax,0\t\t\t; if the mouse cursor is in zero page\n\tje\t??exit\t\t\t; it is completely invalid\n\n\tcmp\teax,[PrevMousePtr]\n\tje \t??exit\n\n\tcmp\t[(KeyboardType esi).MDisabled],FALSE\t; make sure the mouse is not disabled\n\tjne\t??exit\t\t\t; if it is not then give it a try\n\n\t;-------------------------------------------------------------------\n\t; We need to wait if a mouse interrupt is in progress.  Once the\n\t; interrupt is finished flag that it is occuring so that it will\n\t; not attempt to draw the mouse while we are changing the cursor.\n\t;-------------------------------------------------------------------\n??try:\n\tinc\t[(KeyboardType esi).MouseUpdate] ; flag that mouse can not be drawn\n\n\t;-------------------------------------------------------------------\n\t; If the mouse is currently on the screen hide it.\n\t;-------------------------------------------------------------------\n\tcall\tLow_Hide_Mouse\n\n\t;-------------------------------------------------------------------\n\t; Calculate the size of the buffer needed.\n\t;-------------------------------------------------------------------\n\tpush\t[cursor]\n\tcall\tGet_Shape_Uncomp_Size\n\tpop\tedx\n\tmov\t[datasize],eax\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Width\n\tpop\tedx\n\tmov\t[swidth],eax\n\tcmp\teax,[BufferWidth]\n\tjg\t??end\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Original_Height\n\tpop\tedx\n\tmov\t[sheight],eax\n\tcmp\teax,[BufferHeight]\n\tjg\t??end\n\n\n\tmov\tebx,[sheight]\n\tmov\teax,[swidth]\n\timul\tebx,eax\n\n??copy_mouse:\n\tmov\tesi,[cursor]\t\t\t; set esi to point to mouse shape\n\tmov\tax,[esi]\t\t\t; get the shape type byte\n\tmov\t[stype],ax\t\t\t; save off the shape type\n\ttest\tax,MAKESHAPE_NOCOMP\t\t; is it marked as no compression?\n\tje\t??comp_shape\t\t\t; if not go to the comped shape code\n\tmov\tedi,[MouseCursor]\t\t; set edi to point to mouse buffer\n??copy_type:\n\n\ttest\t[stype],MAKESHAPE_COMPACT\t; if the shape a 16 color shape?\n\tjne\t??16_color_copy\t\t\t; if it is then go handle it\n\n??normal_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed NORMAL shapes just get run-length uncompressed\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t\t; find size of shape in pixels\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes \n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??norm_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??norm_trans\t\t\t; if its a zero its transparent\n\tmov\t[edi],al\t\t\t; write out the pixel to dest\n\tinc\tedi\t\t\t\t; move to next dest position\n\tdec\tedx\t\t\t\t; we have now written another pix\n\tjnz\t??norm_unrle\t\t\t; if more to write then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are all done\n\n??norm_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\n\tjnz\t??norm_unrle\t\t\t; if more to do then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are done\n\n??16_color_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed 16 color shapes just get remaped and UN-RLE'd\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\tebx,esi\t\t\t\t; save of position of remap\n\tadd\tesi,16\t\t\t\t; move past remap table\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t; load up the height\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes \n\txor\teax,eax\t\t\t\t; clear high of lookup variable\n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??16_color_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??16_color_trans\t\t; if its a zero its transparent\n\tmov\tal,[ebx+eax]\t\t\t; remap the pixel from 16 color table\n\tmov\t[edi],al\t\t\t; store it out to the dest address\n\tinc\tedi\t\t\t\t; move to next dest address\n\tdec\tedx\t\t\t\t; we have now written a pixel\n\tjnz\t??16_color_unrle\n\tjmp\t??done_copy\n??16_color_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\t\t\t\t; subtract off count ahead of time\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\t\t\t\t; or edx to test for zero\n\tjnz\t??16_color_unrle\t\t\n\tjmp\t??done_copy\n\n\t;-------------------------------------------------------------------\n\t; Deal with the compressed shape by copying it into the shape\n\t;   staging buffer.\n\t;-------------------------------------------------------------------\n??comp_shape:\n\tmov\tedi,[_ShapeBuffer]\t; get a pointer to ShapeBuffer\n\tmov\tax,[esi]\t\t; load in the shape type\n\tadd\tesi,2\t\t\t; increment the shape pointer\n\tor\tax,MAKESHAPE_NOCOMP\t; make the shape as uncompressed\n\tmov\t[stype],ax\t\t; save off the shape type\n\tmov\t[edi],ax\t\t; write out uncompressed shape\n\tadd\tedi,2\n\n\t;-------------------------------------------------------------------\n\t; Process the shape header information and copy it over to the new\n\t;   location.\n\t;-------------------------------------------------------------------\n\tmov\tecx,4 \t\t\t; transfer height, width, org and\n\ttest\teax,MAKESHAPE_COMPACT\t; is it a 16 color shape?\n\tje\t??copy_head\t\t; no - don't worry about it\n\tadd\tecx,8\t\t\t; otherwise adjust ecx for header\n??copy_head:\n\trep\tmovsw\t\t\t; copy the necessary bytes\n\t\n\tmov \teax,[datasize]\t\t; get uncompressed length\n\tpush\teax\t\t\t; push as third param\n\tpush\tedi\t\t\t; push the destination offset\n\tpush\tesi\t\t\t; push the source offset\n\tcall\tLCW_Uncompress\t\t; do the uncompress\n\tpop\teax\n\tpop\teax\n\tpop\teax\n\tmov\tesi,[_ShapeBuffer]\n\tmov\tedi,[MouseCursor]\t\t; set edi to point to mouse buffer\n\tjmp\t??copy_type\n\n??done_copy:\n\tmov\tesi,[RealModePtr]\t; get offset of real mode data start\n\n\tmov\teax,[xhotspot]\t\t; get the mouse cursors x hotspot\n\tmov\t[(KeyboardType esi).MouseXHot],eax\n\tmov\teax,[yhotspot]\t\t; get the mouse cursors y hotspot\n\tmov\t[(KeyboardType esi).MouseYHot],eax\n\n\tmov\tebx,[sheight]\t\t; get shape height\n\tmov\t[(KeyboardType esi).MouseHeight],ebx\n\tmov\tebx,[swidth]\n\tmov\t[(KeyboardType esi).MouseWidth],ebx\n\n??error:\n\tcall\tLow_Show_Mouse\n\n\t;-------------------------------------------------------------------\n\t; Final cleanup and exit.\n\t;-------------------------------------------------------------------\n??end:\n\tdec\t[(KeyboardType esi).MouseUpdate]\t\t; we are done modifying the cursor\n??exit:\n\tpush\t[cursor]\n\tpush\t[PrevMousePtr]\n\tpop\teax\n\tpop\t[PrevMousePtr]\n\tret\t\t\t\t; and return back to the world\n\n\tENDP\tSet_Mouse_Cursor\n\n\n;***************************************************************************\n;* LOW_HIDE_MOUSE -- Low-level routine which hides the mouse\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Low_Hide_Mouse:NEAR\n\tPROC\tLow_Hide_Mouse C NEAR \n\tUSES\teax,ebx,esi\n\n\tmov\tebx,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\n\t;*=========================================================================*\n\t;* Is the mouse disabled or hidden?\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType ebx).MDisabled],0 \t; is the mouse disabled?\n\tjne\tshort ??end\n\n   \tcmp\t[(KeyboardType ebx).MState],0 \t; is the mouse hidden?\n\tjne\tshort ??endnodraw\t\t\t; no need to hide again\n\n\t;*=========================================================================*\n\t;* Take care of restoring the mouse cursor\n\t;*=========================================================================*\n\tmov\teax,RESTORE_VISIBLE_PAGE\n\tpush\teax\n\tcall\t[ Mouse_Shadow_Buffer]\n\tpop\teax\n\t;*=========================================================================*\n\t;* The mouse is now hidden -- again.\n\t;*=========================================================================*\n??endnodraw:\n\tadd\t[(KeyboardType ebx).MState],1\n\tadc\t[(KeyboardType ebx).MState],0\n\n??end:\n\tret\n\tENDP\tLow_Hide_Mouse\n\n;***************************************************************************\n;* LOW_SHOW_MOUSE -- Low level routine which shows the mouse\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Low_Show_Mouse:NEAR\n\tPROC\tLow_Show_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tLOCAL\tmousex:DWORD\n\tLOCAL\tmousey:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\n\t;*=========================================================================*\n\t;* Don't show the mouse if it is not hidden or it is disabled\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType esi).MDisabled],0\t; is the mouse disabled\n\tjne\t??exit\t\t\t\t\t; if so then exit\n\n\tcmp\t[(KeyboardType esi).MState],0\t; is the mouse already visible\n       \tje\t??exit\t\t\t\t\t; if so then exit\n\n\t;*=========================================================================*\n\t;* Don't show the mouse if it was hidden multiple times\n\t;*=========================================================================*\n\tdec\t[(KeyboardType esi).MState]\t\t; show the mouse one level\n\tcmp\t[(KeyboardType esi).MState],0\t; can the mouse be shown\n       \tjne\tshort ??exit\n\n\t;*=========================================================================*\n\t;* Determine the theoretcial drawing position of the mouse\n\t;*=========================================================================*\n\tmov\tecx,[(KeyboardType esi).MouseWidth]\t\t; Theoretical buffer width (pixel).\n\tmov\tedx,[(KeyboardType esi).MouseHeight]\t; Theoretical buffer height (pixel).\n\tmov\teax,[(KeyboardType esi).MouseX]\n\tmov\t[mousex],eax\t\t; Draw X pixel.\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\tmov\tebx,[(KeyboardType esi).MouseY]\n\tmov\t[mousey],ebx\t\t; Draw Y pixel.\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\t;*=========================================================================*\n\t;* Determine the theoretical coordinates and dimensions of the\n\t;*\tarea the mouse shape will be rendered upon.\n\t;*=========================================================================*\n\tmov\t[(KeyboardType esi).MouseBuffX],eax\n\tmov\t[(KeyboardType esi).MouseBuffY],ebx\n\tmov\t[(KeyboardType esi).MouseBuffW],ecx\n\tmov\t[(KeyboardType esi).MouseBuffH],edx\n\n;------\tMove the area that will be drawn upon, to the graphic buffer.\n\tmov\teax,STORE_VISIBLE_PAGE\n\tpush\teax\n\tcall\t[ Mouse_Shadow_Buffer ]\n\tpop\teax\n\n;------\tDraw the mouse shape to the seenpage.\n\tpush\t[mousey]\n\tpush\t[mousex]\n\tcall\t[ Draw_Mouse ]\n\tpop\teax\n\tpop\teax\n??exit:\n\tret\n\tENDP\tLow_Show_Mouse\n\n;***************************************************************************\n;* HIDE_MOUSE -- Hides mouse cursor on screen if it was show               *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Hide_Mouse(void);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tHide_Mouse:NEAR\n\tPROC\tHide_Mouse C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Mark us as updating the mouse and then run and do the update\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\t; were drawing the mouse\n\tcall\tLow_Hide_Mouse\t\t\t\t; make the function call\n\tdec\t[(KeyboardType esi).MouseUpdate]\t; were done drawing mouse\n\tret\n\t\n\tENDP\tHide_Mouse\n\n;----------------------------------------------------------------------------\n\n\n;***************************************************************************\n;* SHOW_MOUSE -- Display mouse cursor on screen if it was hidden           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Show_Mouse(void)                                      *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tShow_Mouse:NEAR\n\tPROC\tShow_Mouse C NEAR \n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Mark us as updating the mouse and then run and do the update\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\t; were drawing the mouse\n\tcall\tLow_Show_Mouse\t\t\t\t; make the function call\n\tdec\t[(KeyboardType esi).MouseUpdate]\t; were done drawing mouse\n\tret\n\tENDP\tShow_Mouse\n\n;***************************************************************************\n;* CONDITIONAL_HIDE_MOUSE -- Hides mouse if its with given region          *\n;*                                                                         *\n;* INPUT:\tint sx_pixel - the left-most pixel position of the region  *\n;*\t\tint sy_pixel - the upper-most pixel position of the region *\n;*\t\tint dx_pixel - the right most pixel position of the region *\n;*\t\tint dy_pixel - the lower most pixel position of the region *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Conditional_Hide_Mouse(\tint sx_pixel, \t\t   *\n;*\t\t\t\t\t\tint sy_pixel,\t\t   *\n;*\t\t\t\t\t\tint dx_pixel,\t\t   *\n;*\t\t\t\t\t\tint dy_pixel);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tConditional_Hide_Mouse:NEAR\n\tPROC\tConditional_Hide_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tARG\tsx_pixel:DWORD\t\t\t\t; left x pixel pos\n\tARG     sy_pixel:DWORD\t\t\t\t; upper y pixel pos\n\tARG\tdx_pixel:DWORD\t\t\t\t; right x pixel pos\n\tARG\tdy_pixel:DWORD\t\t\t\t; lower y pixel pos\n\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Widen region leftward by amount mouse shape spills to the right of\n\t;* its hot point.  Limited to the left edge of the screen.\n\t;*=========================================================================*\n\tmov\teax,[(KeyboardType esi).MouseWidth]\t\n\tsub\teax,[(KeyboardType esi).MouseXHot]\t\n\tneg\teax\t\t\t\t\t\n\tadd\teax,[sx_pixel]\n\tjns\tshort ??noleftlimit\n\txor\teax,eax\n??noleftlimit:\n\t;*=========================================================================*\n\t;* Widen region upward by amount mouse shape spills below the\n\t;* mouse's hot point.  Limited by the top edge of the screen.\n\t;*=========================================================================*\n\tmov\tebx,[(KeyboardType esi).MouseHeight]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\tneg\tebx\n\tadd\tebx,[sy_pixel]\n\tjns\tshort ??notoplimit\n\txor\tebx,ebx\n??notoplimit:\n\t;*=========================================================================*\n\t;* Widen region rightward by amount mouse shape spills to the\n\t;* left of its hot point.  Limited by the right edge of the\n\t;* screen.\n\t;*=========================================================================*\n\tmov\tecx,[dx_pixel]\n\tadd\tecx,[(KeyboardType esi).MouseXHot]\n\tcmp\tecx,[(KeyboardType esi).MouseRight]\n\tjb\tshort ??norightlimit\n\tmov\tecx,[(KeyboardType esi).MouseRight]\n\tdec\tecx\n??norightlimit:\n\t;*=========================================================================*\n\t;* Widen region downward by amout the mouse shape extends above\n\t;* its hot point.  Limited to the bottom of the screen.\n\t;*=========================================================================*\n\tmov\tedx,[dy_pixel]\n\tadd\tedx,[(KeyboardType esi).MouseYHot]\n\tcmp\tedx,[(KeyboardType esi).MouseBottom]\n\tjb\tshort ??nobottomlimit\n\tmov\tedx,[(KeyboardType esi).MouseBottom]\n\tdec\tedx\n\n??nobottomlimit:\n\tinc\t[(KeyboardType esi).MouseUpdate]\t\t; don't let interrupt scrag variables\n\n\t;*=========================================================================*\n\t;* The mouse could be in one of four conditions.\n\t;* 1) The mouse is visible and no conditional hide has been specified.\n\t;* \t(perform normal region checking with possible hide)\n\t;* 2) The mouse is hidden and no conditional hide as been specified.\n\t;* \t(record region and do nothing)\n\t;* 3) The mouse is visible and a conditional region has been specified\n\t;* \t(expand region and perform check with possible hide).\n\t;* 4) The mouse is already hidden by a previous conditional.\n\t;* \t(expand region and do nothing)\n\t;*\n\t;* First: Set or expand the region according to the specified parameters\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType esi).MCState],0\n\tjne\tshort ??expand\n\tmov\t[(KeyboardType esi).MouseCXLeft],eax\n\tmov\t[(KeyboardType esi).MouseCYUpper],ebx\n\tmov\t[(KeyboardType esi).MouseCXRight],ecx\n\tmov\t[(KeyboardType esi).MouseCYLower],edx\n\tjmp\t??noylower\n??expand:\n\n\t;*=========================================================================*\n\t;* Expand the clipping rectangle.\n\t;*=========================================================================*\n\tcmp\teax,[(KeyboardType esi).MouseCXLeft]\n\tjb\tshort ??noxleft\n\tmov\t[(KeyboardType esi).MouseCXLeft],eax\n??noxleft:\n\tcmp\tebx,[(KeyboardType esi).MouseCYUpper]\n\tjb\tshort ??noyupper\n\tmov\t[(KeyboardType esi).MouseCYUpper],ebx\n??noyupper:\n\tcmp\tecx,[(KeyboardType esi).MouseCXRight]\n\tja\tshort ??noxright\n\tmov\t[(KeyboardType esi).MouseCXRight],ecx\n??noxright:\n\tcmp\tedx,[(KeyboardType esi).MouseCYLower]\n\tja\tshort ??noylower\n\tmov\t[(KeyboardType esi).MouseCYLower],edx\n??noylower:\n\t;*=========================================================================*\n\t;* If the mouse isn't already hidden, then check its location against\n\t;* the hiding region and hide if necessary.\n\t;*=========================================================================*\n\ttest\t[(KeyboardType esi).MCState],CONDHIDDEN\n\tjne\tshort ??nohide\n\n\tmov\teax,[(KeyboardType esi).MouseX]\n\tmov\tebx,[(KeyboardType esi).MouseY]\n\tcmp\teax,[(KeyboardType esi).MouseCXLeft]\n\tjb\tshort ??nohide\n\tcmp\teax,[(KeyboardType esi).MouseCXRight]\n\tja\tshort ??nohide\n\tcmp\tebx,[(KeyboardType esi).MouseCYUpper]\n\tjb\tshort ??nohide\n\tcmp\tebx,[(KeyboardType esi).MouseCYLower]\n\tja\tshort ??nohide\n\n\t;*=========================================================================*\n\t;* The mouse falls within the region for hiding, so hide it.\n\t;*=========================================================================*\n\n\tcall\tLow_Hide_Mouse\t\t\t\t; make the function call\n\tor\t[(KeyboardType esi).MCState],CONDHIDDEN\n??nohide:\n\n\t;*=========================================================================*\n\t;* Record the fact that a Conditional_Hide_Mouse was\n\t;* called and then exit.\n\t;*=========================================================================*\n\tor\t[(KeyboardType esi).MCState],CONDHIDE\n\tadd\t[BYTE PTR (KeyboardType esi).MCState],1\n\tadc\t[BYTE PTR (KeyboardType esi).MCState],0\n\tdec\t[(KeyboardType esi).MouseUpdate]\n\tret\n\n\tENDP\tConditional_Hide_Mouse\n\n;***************************************************************************\n;* CONDITIONAL_SHOW_MOUSE -- shows mouse if it was conditionally hidden    *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Conditional_Show_Mouse(void);                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tConditional_Show_Mouse:NEAR\n\tPROC\tConditional_Show_Mouse C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]    ; get the real mode offset\n\n\t;*=========================================================================*\n\t; Notify the interrupt that we are updating the mouse\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\n\n\tmov\tax,[(KeyboardType esi).MCState]\n\tcmp\tal,0\n\tje\tshort ??exit\t\t\t; if no more nesting clear cond\n\n\t;*=========================================================================*\n\t;* Decrement the conditional hide counter.\n\t;*=========================================================================*\n\tdec\tal\n\n\t;*=========================================================================*\n\t;* If there are more conditional levels to undo, then just abort the show.\n\t;*=========================================================================*\n\tjne\tshort ??exit\n\n\t;*=========================================================================*\n\t;* Yup, the mouse should be show, but only if it was previously hidden.\n\t;*=========================================================================*\n\ttest\tax,CONDHIDDEN\t\t\t; was it hidden by interrupt??\n\tje\tshort ??exit1\t\t\t; or initial check for level 0\n\n\tcall\tLow_Show_Mouse\n\n??exit1:\n\tmov\tax,0\n\n??exit:\n\tmov\t[(KeyboardType esi).MCState],ax\n\tdec\t[(KeyboardType esi).MouseUpdate]\n\tret\n\tENDP\tConditional_Show_Mouse\n\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VGA_Mouse_Shadow_Buffer:NEAR\n\tPROC\tVGA_Mouse_Shadow_Buffer C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tstore:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\n\tmov\tesi,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[(KeyboardType esi).MouseBuffX]\n\tmov\tebx,[(KeyboardType esi).MouseBuffY]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseBuffW]\n\tadd\tebx,[(KeyboardType esi).MouseBuffH]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseBuffer ]\n\tmov\t[ buffy0 ] , eax\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseBuffW]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseBuffW]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\tpush\tebp\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tebp , ecx\n??restore_loop:\n\tmov\tecx,eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi,ebx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tesi,edi\t\t\t\t\t; xchg the source and the dest\n\tmov\tebp , ecx\n??store_loop:\n\tmov\tecx,eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi,edx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,ebx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n??out:\n\tret\n\tENDP\tVGA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n;* DRAW_MOUSE -- Handles drawing the mouse cursor\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tVGA_Draw_Mouse:NEAR\n\tPROC\tVGA_Draw_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tmousex:DWORD\n\tARG\tmousey:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\n\n\tmov\tesi,[RealModePtr]    \t; get 32 bit offset of dos data\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[mousex]\n\tmov\tebx,[mousey]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseWidth]\n\tadd\tebx,[(KeyboardType esi).MouseHeight]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , eax\n\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseWidth]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseWidth]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch ,[esi]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[edi],ch\n??inc_edi:\n\tinc\tedi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tesi,ebx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t\t\t\t; adjust dest to next line\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\tret\n\n\tENDP\tVGA_Draw_Mouse\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VESA_Mouse_Shadow_Buffer:NEAR\n\tPROC\tVESA_Mouse_Shadow_Buffer C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tstore:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\tlocal\tvesa_linear : dword\n\n\tmov\teax , [ cpu_video_page ]\n\tmov\t[ vesa_linear ] ,  eax\n\n\tmov\tesi,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[(KeyboardType esi).MouseBuffX]\n\tmov\tebx,[(KeyboardType esi).MouseBuffY]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseBuffW]\n\tadd\tebx,[(KeyboardType esi).MouseBuffH]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseBuffer ]\n\tmov\t[ buffy0 ] , eax\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseBuffW]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\tcall\tVesa_Asm_Set_Win\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseBuffW]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\n\tmov\t[ tempreg ] , ebx\n??restore__top_loop:\n\tmov\tah,al\n??restore__inner_loop:\n\tmov\tch ,[esi]\n\tmov\t[edi],ch\n\tinc\tesi\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??restore__in_range\n\tadd\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??restore__in_range:\n\tdec\tah\n\tjnz\t??restore__inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??restore__in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??restore__in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore__top_loop\t\t\t\t; if more to do, do it\n\tjmp\t??out\t\t\t\t\t; get the heck outta the routine\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\tmov\t[ tempreg ] , ebx\n??store_top_loop:\n\tmov\tah,al\n??store_inner_loop:\n\tmov\tch ,[edi]\n\tmov\t[esi],ch\n\tinc\tesi\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??store_in_range\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??store_in_range:\n\tdec\tah\n\tjnz\t??store_inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??store_in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??store_in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_top_loop\t\t\t\t; if more to do, do it\n\n??out:\n\tmov\tedi , [ vesa_linear ]\n\tadd\tedi , 0a0000h\n\tcall\tVesa_Asm_Set_Win\n\n\tret\n\tENDP\tVESA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n;* DRAW_MOUSE -- Handles drawing the mouse cursor\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tVESA_Draw_Mouse:NEAR\n\tPROC\tVESA_Draw_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tmousex:DWORD\n\tARG\tmousey:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\tlocal\ttempreg : dword\n\tlocal\tvesa_linear : dword\n\n\tmov\teax , [ cpu_video_page ]\n\tmov\t[ vesa_linear ] ,  eax\n\n\tmov\tesi,[RealModePtr]    \t; get 32 bit offset of dos data\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[mousex]\n\tmov\tebx,[mousey]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseWidth]\n\tadd\tebx,[(KeyboardType esi).MouseHeight]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , eax\n\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseWidth]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\tcall\tVesa_Asm_Set_Win\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseWidth]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\t[ tempreg ] , ebx\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch ,[esi]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[edi],ch\n??inc_edi:\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??in_range\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??in_range:\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n\n??out:\n\tmov\tedi , [ vesa_linear ]\n\tadd\tedi , 0a0000h\n\tcall\tVesa_Asm_Set_Win\n\n\tret\n\n\tENDP\tVESA_Draw_Mouse\n\n\n;----------------------------------------------------------------------------\nEND\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/NEW/KEYBOARD.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : KEYBOARD.ASM                             *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 15, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Get_RM_Timer_Address -- Return address of real mode code for copy.    *\n;*   Get_RM_Keyboard_Size -- return size of real mode timer code.          *\n;*   Check_Key -- checks queue for key (make)                              *\n;*   Check_Key_Num -- Checks if key in queue, return key num               *\n;*   Get_Key_Num -- Returns the next key num in ax                         *\n;*   KN_To_KA -- Translates a key num to an ASCII key                      *\n;*   Low_Get_Key -- low level get key returns key num and bits             *\n;*   Convert_Num_To_ASCII -- Assembly routine converts keynum to ASCII key *\n;*   KeyNum_Translate -- Performs a lowlevel xlate to a keycode            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\n;*\tKeyboard driver -- 80386 Protected Mode Assembly portion\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   \n;***************************************************************************\n;\n; ----------------------------------------------------------------\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\n;WARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Make some general equates for easy compatability\n;---------------------------------------------------------------------------\nPROT_INT_ENABLE\tEQU\t1\t\t; if false protected int just calls real mode int\n\nDPMI_INTR\tEQU\t31h\t\nIRQ1INTNUM\tEQU\t09h\t\t; IRQ1 interrupt vector number.\nBRKINTNUM\tEQU\t23h\t\t; Crtl-C (Break) interrupt vector number\nDBGINTNUM\tEQU\t3h\t\t; Debug interrupt vector number\nDOS_SYS_CALL\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nLOCK_PAGES\tEQU\t5\t\t; Lock pages subfunction using DX_MEM_MGT\nUNLOCK_PAGES\tEQU\t6\t\t; Unlock pages subfunction using DX_MEM_MGT\nCLEARISR\tEQU\t020H\t; value to clear In Service Register\nINTCHIP0\tEQU\t020H\t; 8259 interrupt chip controller 0\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\n\tINCLUDE \"keyboard.inc\"\n\tINCLUDE \"keystruc.inc\"\n\tINCLUDE \"mcgaprim.inc\"\n\n\tGLOBAL\t RealModePtr:DWORD\n\n\tGLOBAL\t Install_Keyboard_Interrupt:NEAR\n\tGLOBAL\t Get_RM_Keyboard_Address:Near\n\tGLOBAL\t Get_RM_Keyboard_Size:Near\n\tGLOBAL\t Remove_Keyboard_Interrupt:NEAR\n\tGLOBAL\t Check_Key_Num:NEAR\n\tGLOBAL\t Get_Key_Num:NEAR\n\tGLOBAL\t KN_To_KA:NEAR\n\tGLOBAL\t KeyNum_Translate:NEAR\n\tGLOBAL\t Check_Key:NEAR\n\tGLOBAL\t Get_Key:NEAR\n\tGLOBAL\t Keyboard_Attributes_On:NEAR\n\tGLOBAL\t Clear_KeyBuffer:NEAR\n\tGLOBAL\t Key_Down:NEAR\n\tGLOBAL\t Keyboard_Attributes_Off:NEAR\n\tGLOBAL\t Check_Key_Bits:NEAR\n\tGLOBAL\t Get_Key_Bits:NEAR\n\tGLOBAL\t Key_Satisfied:NEAR\n\tGLOBAL\t Stuff_Key_WORD:NEAR\n\tGLOBAL\t Stuff_Key_Num:NEAR\n\tGLOBAL\t MouseQX:DWORD\n\tGLOBAL\t MouseQY:DWORD\n;DBG\n\tGLOBAL   Keyboard_Interrupt:NEAR\n\n\n\tDATASEG\n; For the current time we will just include the real mode stuff\n; into the protected mode code and then copy it down.  The C side of\n; this will handle this method or reading it off of disk in the real\n; method.\n\nLABEL \tRealBinStart\tBYTE\ninclude \"keyireal.ibn\"\nLABEL\tRealBinEnd\tBYTE\n\nLABEL\tLockedDataStart\tBYTE\t\nRMVector\tDD\t0\nRealModeSel\tDD\t0\nRealModePtr\tDD\t0\t\t; Pointer to real mode memory.\nRealModeSize\tDD\t0\t\t; Pointer to real mode memory.\n\nKeyboard_App_Stack_ESP\tDD 0\t\t; This the System Stack Offsset\nKeyboard_App_Stack_SS\tDD 0\t\t; This the System Stack Selector\nKeyboard_StackPointer\tDD 0DEADDEADh\t; We Create a Local Application\nKeyboard_Stack          DD 255 dup (0)\nKeyboard_StackStart\tDD 0\n\t\t\t\t\t; StackPointer \t\nLABEL\tLockedDataEnd\tBYTE\n\n\n\nAscii\tDB\t0,\"`1234567890-=\",0,8,9,\"qwertyuiop[]\\\",0,\"asdfghjkl;'\"\n\tDB\t0,13,0,45,\"zxcvbnm,./\",0,0,0,0,0,\" \"\n\nShift\tDB\t0,\"~!@#$%^&*()_+\",0,8,9,\"QWERTYUIOP{}|\",0,\"ASDFGHJKL:\",22H\n\tDB\t0,13,0,45,\"ZXCVBNM<>?\",0,0,0,0,0,\" \"\n\nAlpha_Lower\tDB\t0\n\tDB\t\"~!@#$%^&*()_+\",0,8,9,\"qwertyuiop{}|\",0,\"asdfghjkl:\",22H\n\tDB\t0,13,0,45,\"zxcvbnm<>?\",0,0,0,0,0,\" \"\n\nAlpha_Shift\tDB\t0\n\tDB\t\"`1234567890-=\",0,8,9,\"QWERTYUIOP[]\\\",0,\"ASDFGHJKL;'\"\n\tDB\t0,13,0,45,\"ZXCVBNM,./\",0,0,0,0,0,\" \"\n\nEdit\tDB\t0AEH,0ADH,000H,000H,0B5H,0B9H,0B1H,000H,0B8H,0B0H,0B7H,0AFH\n\tDB\t000H,000H,0B3H,000H,0B9H,0B5H,0B1H,000H, \"/\",0B8H,0B4H,0B0H\n\tDB\t0AEH, \"*\",0B7H,0B3H,0AFH,0ADH, \"-\", \"+\",000H,00DH,000H\n\nNumPad\tDB\t0,\"741\",0,\"/8520*963.-+\",0,13,0\n\n\nGetKeyLock\tDW\t0\t; snap shot of num and caps lock bits\nInitFlags\tDW\t0\nMouseQX\t\tDD\t0\nMouseQY\t\tDD\t0\n\n\tCODESEG\n;***************************************************************************\n;* GET_RM_TIMER_ADDRESS -- Return address of real mode code for copy.      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      VOID * to the address of the real mode timer               *\n;*                                                                         *\n;* PROTO:\tVOID\t*Get_RM_Keyboard_Address(VOID);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Address C Near\n\n\tmov\teax, OFFSET RealBinStart\n\tret\n\n\tENDP\n\n;***************************************************************************\n;* GET_RM_KEYBOARD_SIZE -- return size of real mode timer code.            *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      LONG size of the real mode timer code                      *\n;*                                                                         *\n;* PROTO:\tLONG\tGet_RM_Keyboard_Size(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Size C Near\n\n\tmov\teax, OFFSET RealBinEnd - OFFSET RealBinStart\n\tret\n\n\tENDP\n;***************************************************************************\n;* INSTALL_KEYBOARD_INTERRUPT -- Installs the keyboard interrupt           *\n;*                                                                         *\n;* INPUT:\tint rm_ptr  - ptr to the real mode handler\t\t   *\t   *\n;*\t\tint rm_size - size of the real mode handler\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Install_Keyboard_Interrupt(int rm_ptr, int rm_size);  *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tInstall_Keyboard_Interrupt C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\tARG\trm_ptr:DWORD\n\tARG\trm_size:DWORD\n\n\t; Are they attempting to set timer again?\n\tcmp\t[RealModePtr],0\n\tjnz\t??error\n\n\t; Make sure all flags are cleared.\n\tcmp\t[InitFlags],0\n\tjnz\t??error\n\n\n\t; Before setting the interrupt vectors, the code needs to be locked\n\t; for DPMI compatability.  Any code or data accessed must be lockded\n\t; so that no page faults accure during an interrupt.\n\t; First lock the code, then the data.  The stack will already be locked.\n\t; The real mode code is also already locked be default.\n\t; To lock a page set up registers :\n\t; AX = 0600h\n\t; BX:CX\t= starting linear address of memory block\n\t; SI:DI = size of region\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_CODE\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_DATA\n\n\t; now allocate real mode memory and copy the rm binary down to it.\n\tmov\teax,0100h\t; set function number\n\tmov\tebx,[rm_size]\t\t; get size of RM binary.\n\tmov\t[RealModeSize],ebx\n\tadd\tebx,15\t\t\t; round up \n\tshr\tebx,4\t\t\t; convert to pages.\n\tint\tDPMI_INTR\t \t; do call.\n\tjc\t??error\t\t \t; check for error.\n\tor\t[InitFlags],IF_ALLOC_RM ; set successful\n\tmov\t[RealModeSel],edx\n\tshl\teax,4\t\t\t; convert segment to offset.\n\tmov\t[RealModePtr],eax\t; save offset to global variable.\n\n\t; now lock the real mode memory that we allocated\n\tmov\teax,0600h\t\t; function number.\n\tmov\tecx,[RealModePtr]\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_RM_CODE\n\n\n\n\t; set up source and destination pointers for the copy.\n\tmov\teax,[RealModePtr];\t; set up our dest pointer\n\tmov\tesi,[rm_ptr]\t\t; Set up our source pointer.\n\tmov\tedi,eax\t\t\t; put it into esi for copy.\n\tmov\tecx,[rm_size]\n\trep\tmovsb\t\t\t; write RM bin to RM memory.\n\n\t; restore esi to point to data and initialize some of it.\n\tmov\tesi,[RealModePtr]\n\tmov\teax,esi\n\tshl\teax,12\t\t\t\t\t\t; make seg in high eax.\n\tmov\tax,[(KeyboardType PTR esi).CallKeyRMIntOffset]\t; create RM addr of call chain.\n\tmov\t[(KeyboardType PTR esi).CallKeyRMIntAddr],eax\t; save it for use in PM int.\n\nIF NOT PROT_INT_ENABLE\n       ; Chain the Real Keyboard interrupt to any avilable\n       ; Interrupt vector so We make sure that the Real Mode\n       ; Keyboard Interrupt service get called at debuging time\n       ; of the library.\n\n       mov\tedi , eax\n       mov\tbl , 060h\n       mov\tbh , 6\n       mov\teax , 200h\n ??find:\n       int\tDPMI_INTR\n       jc\t??error\n       or\tcx,dx\n       jz\t??found\n       inc\tbl\n       dec\tbh\n       jnz\t??find\n       jmp\t??error\n ??found:\n       movzx\tebx , bl\n       mov\t[ byte ptr RMVector ] , bl\n       mov\t[ 4 * ebx ] , edi\nENDIF\n\n\n\n\t;-------------------------------------------------------\n\t; Initialize all of the keyboard specific information\n\t;-------------------------------------------------------\n\txor\teax,eax\t\t\t; clear the high bits of eax\n\tmov\tal,[417H]\t\t; get keyboard status flags\n\ttest\teax,040H \t\t; caps lock active?\n\tje \tshort ??nocap\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\n\n??nocap:\n\ttest\teax,020H\t\t\t; num lock active?\n\tje\tshort ??nonumlock\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\n\n??nonumlock:\n\ttest\teax,002H\t\t\t; is left shift key down?\n\tje\tshort ??noleftshift\t\t; try the right\n\tor\t[(KeyboardType PTR esi+5).KeysUpDown],010H\n\n??noleftshift:\n\tand\teax,001H\t\t\t; get right shift bit\n\tshl\teax,9\t\t\t; put it into the proper position (shl al,1 mov ah,al)\n\tmov\tal,[418H]\t\t; get alt and ctrl bits\n\tshl\tal,2\t\t\t; put in proper position\n\tshl\tal,1\n\tand\tal,00CH\t\t\t; only alt and ctrl bits\n\tor\tah,al\t\t\t; put them ah for Keys+7 later\n\tmov\tal,[496H]\t\t; get extended keys\n\ttest\tal,008H\t\t\t; check for right alt key\n\tje\tshort ??noralt\n\tor\tah,040H\n??noralt:\n\tmov\t[(KeyboardType PTR esi+7).KeysUpDown],ah\n\ttest\tal,004H\t\t\t; test for right ctrl\n\tje \tshort ??norctrl\n\tor\t[(KeyboardType PTR esi+8).KeysUpDown],001h\n??norctrl:\n\ttest\tal,002H\t\t\t; last code E0?\n\tje short ??noe0\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],001h\n??noe0:\n\ttest\tal,001H\t\t\t; last code E1?\n\tje short ??noe1\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],002h\n??noe1:\n\t;==========================================================================\n\t; Get the protected mode interrupt vector keyboard.\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).KeyOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).KeyOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 2503, cl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).KeyOldRMI],ecx\n\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt Keyboard\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Keyboard_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt Keyboard\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).KeyCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the break interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\t\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).BrkOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).BrkOldPMISelector],ecx\t; save selector.\n\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector - for the break interrupt\n\t; input ax = 0200, bl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).BrkOldRMI],ecx\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Break_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).BrkCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\nIF DEBUG\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the Debug interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\t\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,DBGINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).DbgOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).DbgOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Debug_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\nENDIF\n\n\t; we have finished with success.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n??exit:\n\tret\n\tENDP\tInstall_Keyboard_Interrupt\n\n;***************************************************************************\n;* REMOVE_INTERRUPT -- Removes keyboard interrupt and restores chain\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Remove_Interrupt(VOID)                                *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tRemove_Keyboard_Interrupt C NEAR \n\tUSES\tebx,ecx,edx\n\n\t; verifie that the keyboard was previosly install\n\t; this is here in case of a page fault crash\n\tmov\tesi,[RealModePtr]\n\ttest    esi,esi\n\tjz      ??error\n\n\ttest\t[InitFlags],IF_SET_VECTORS\n\tjz\t??vectors_not_set\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tedx,[(KeyboardType esi).KeyOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[(KeyboardType esi).KeyOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).KeyOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\n\t; disengage Control Break Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tedx,[(KeyboardType esi).BrkOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[(KeyboardType esi).BrkOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).BrkOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\nIF DEBUG\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tecx,[(KeyboardType esi).DbgOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).DbgOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\nENDIF\n\nIF NOT PROT_INT_ENABLE\n       ; Clean up the Users interrupt table\n        mov\teax , 201h\n       mov\tbl , [ byte ptr RMVector ]\n       xor\tecx , ecx\n       xor\tedx , edx\n       int\tDPMI_INTR\n       jc\t??error\nENDIF\n\n\n??vectors_not_set:\n\t; now free up the real mode memory.\n\ttest\t[InitFlags],IF_LOCKED_RM_CODE\n\tjz\t??rm_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,[RealModePtr]\t\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t\t; edx will have size of region in bytes.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??rm_not_locked:\n\ttest\t[InitFlags],IF_ALLOC_RM\n\tjz\t??mem_not_allocated\n\tmov\teax , 0101h\n\tmov\tedx,[ RealModeSel ] \t\t; get physical address of real mode buffer.\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n??mem_not_allocated:\n\n\t; Now we can unlock all stuff needed for the interrupt.  \n\t; Unlock Code\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??code_not_locked:\n\n\t; Unlock data\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??data_not_locked:\n\n\t; we have finished with success.\n\tmov\t[RealModePtr],0\t\t; To say we can do it again sometime.\n\tmov\t[InitFlags],0\t\t; To say we can do it again sometime.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n\tret\n\tENDP\tRemove_Keyboard_Interrupt\n\n\n;***************************************************************************\n;* CHECK_KEY_NUM -- Checks if key in queue, return key num                 *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      Keynum of the key that was pressed, FALSE otherwise        *\n;*\n;* PROTO:\tINT Check_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Num C NEAR \n\tUSES\tebx,esi\n\tpushf\t\t\t\t\t; save off the flags\n\tcli\t\t\t\t\t; disable interrupts\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t\t\n\txor\teax,[(KeyboardType PTR esi).KeyBufferTail]\t\t\n\tor\teax,eax\t\t\t\t; check to see if head == tail\n\tjz\tshort ??fini\t\t\t; if so we are done\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t; get the head\n\tmov\tax,[(KeyboardType PTR esi+eax).KeyBuffer]\t; get key num\n\n??fini:\n\tsti\n\tpopf\n\tret\n\n\tENDP\tCheck_Key_Num\n\n;***************************************************************************\n;* GET_KEY_NUM -- Returns the next key num in ax                           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      WORD key flags are in the high byte of return word, key    *\n;*\t\t  num is in the low byte.\n;*                                                                         *\n;* PROTO:\tWORD Get_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Num C NEAR\n\tUSES\tesi,edi\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n??wait:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t\t; get the head\n\tcmp\teax,[(KeyboardType PTR esi).KeyBufferTail]\t\t; get the head\n\tjne\tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??wait\n\n??getkey:\n\tcall\tLow_Get_Key\n\tsti\t\t\t\t; enable interrupts\n\tret\n\n\tENDP\tGet_Key_Num\n\n;***************************************************************************\n;* KN_TO_KA -- Translates a key num to an ASCII key                        *\n;*                                                                         *\n;* INPUT:\tWORD the keynum to translate                               *\n;*                                                                         *\n;* OUTPUT:      WORD the ASCII key that is returned                        *\n;*                                                                         *\n;* PROTO:\tINT KN_To_KA(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tKN_To_KA C NEAR\n\tARG\tkeynum:DWORD\n\n\tmov\teax,[keynum]\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\tret\n\n\tENDP\tKN_To_KA\n\n\n;***************************************************************************\n;* LOW_GET_KEY -- low level get key returns key num and bits               *\n;*                                                                         *\n;* INPUT:\tAX - index into the buffer                                 *\n;*                                                                         *\n;* OUTPUT:      AX - key num with bits                                     *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tLow_Get_Key C NEAR \n\tUSES\tebx,esi,edi\n\n\tmov\tedi,eax\t\t\t\t; save off value in ax\n\n; We should set up both DS & ES because we are a low level function\n; and don't know who might have called us or what the registers\n; currently are.\n\n; No reason to set DS & ES.\n; This is not a hardware interrupt and if the funtion is being called\n; from within a hardware interrupt then DS and ES will be preset to\n; DGROUP _DATA\n\t\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tcmp\tal,KN_LMOUSE\n\tjb \tshort ??cont\n\tcmp\tal,KN_RMOUSE\n\tja \tshort ??chkjoy\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t; 128 word circular buffer\n\n\tmov\t[MouseQX],eax\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\t[MouseQY],eax\n\n\tpop\teax\t\t\t; restore keynum for return\n\n\tjmp\tshort ??cont\n\n??chkjoy:\n\tcmp\tal,KN_JBUTTON2\t\t; mouse button before joystick button\n\tja \tshort ??cont\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tpop\teax\t\t\t; restore keynum for return\n??cont:\n\tmov\t[(KeyboardType PTR esi).KeyBufferHead],edi\t; set the head\n\n??out:\n\tret\n\n\tENDP\tLow_Get_Key\n\n;***************************************************************************\n;* CONVERT_NUM_TO_ASCII -- Assembly routine converts keynum to ASCII key   *\n;*                                                                         *\n;* INPUT:\tEAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - holds the key num bits                        *\n;*\t\t\tAL - holds the key num value\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      EAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - hold the key bits                             *\n;*\t\t\tAL - holds the ASCII key value\t\t\t   *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* WARNINGS:    GetKeyLock must be set prior to calling this function\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tConvert_Num_To_ASCII C NEAR \n\tUSES\tebx,ecx,esi,edi\n\n\t;*===================================================================\n\t;* Force all breaks to be thrown out.\n\t;*===================================================================\n\ttest\teax,08000h\t\t; If it is a button number\n\tjne\tshort ??button\t\t;  don't process it\n\n\ttest\tah,KEYRELEASE\t\t; If it is not key release\n\tje\tshort ??ok\t\t;  then go process it\n\n??button:\n\txor\teax,eax\t\t\t; no ascii value for a button\n\tret\n\n??ok:\n\t;*===================================================================\n\t;* ES points to the DOSMEM selector, esi is the offset of the \n\t;*   protected mode structure.\n\t;*===================================================================\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\n\t;*===================================================================\n\t;* Start dealing with the keys.\t\t\t\t\t  \n\t;*===================================================================\n\tcmp\tal,110\t\t\t; is it esc\n\tje\t??esc\t\t\t; if so then deal with it\n\n;??chkext:\n\tcmp\tal,62\t\t\t; is it extended?\n\tjae\tshort ??extended\t; its extended so return ext code\n\n\tmov\tebx,eax\t\t\t; get an index\n\tand\tebx,03FH\t\t; only 0-63 allowed\n\ttest\tah,1\t\t\t; if not, test for shift\n\tjnz\tshort ??shifted\t\t; if shifted get shift value\n\n\t;*===================================================================\n\t;* Here when we have an unshifted ascii key\n\t;*===================================================================\n\tmov\tal,[Ascii+ebx]\t\t; get the ascii code for this number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_lowered:\n\tmov\tal,[Alpha_Lower+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_shifted:\n\tmov\tal,[Alpha_Shift+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* Shift'ed character\n\t;*===================================================================\n??shifted:\n\tmov\tal,[Shift+ebx] \t\t; get ascii shift code for number\n\n??ctrlkey:\n\ttest\tah,2\t\t\t; is it ctrl?\n\tjz \tshort ??jexit\t\t; izf not skip ctrl check\n\n\tmov\tedi,ebx\t\t\t; get index\n\tand\tedi,7\t\t\t; only bits 0-7\n\n\tmov\tcl,[(KeyboardType PTR esi+edi).Bits]\n\n\tshr\tebx,3\t\t\t; div by 8 for byte offset\n\ttest\t[(KeyboardType PTR esi+ebx).KeysCapsLock],cl\t\n\tje \tshort ??jexit\n\tand\tal,01FH\t\t\t; force to ctrl value\n\n??jexit:\n\tjmp short ??exit\n\n??extended:\n\tcmp\tal,75\t\t\t; if less than insert\n\tjb \tshort ??special\n\tcmp\tal,110\t\t\t; if >= esc\n\tjae \tshort ??funckey\n\n??editkeys:\n\txor\tebx,ebx\n\tmov\tbl,al\n\tsub\tebx,75\t\t\t; get value from 0-34\n\ttest\t[(KeyboardType PTR esi).KeyFlags],NONUMLOCK\n\tjne \tshort ??no_numpad\n\ttest\t[GetKeyLock],NUMLOCK\t; look at the snap shot of bits\n\tjne \tshort ??numpad\n\n??no_numpad:\n\tmov\tal,[Edit+ebx] \t\t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??numpad:\n\tsub\tebx,15\t\t\t; adjust to numpad entries\n\tmov\tal,[NumPad+ebx] \t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??funckey:\n\tcmp\tal,112\t\t\t; if less than function keys\n\tjb \tshort ??extout\n\tcmp\tal,121\t\t\t; if greater than function keys 1-10\n\tja \tshort ??extout\n\tmov\tbl,al\n\tsub\tbl,112\t\t\t; get value 0-9\n\tmov\tbh,0C5H\t\t\t; function key 1 no shift-ctrl-alt\n\ttest\tah,7\t\t\t; any shift-ctrl-alt\n\tje\tshort ??funcadj\n\tmov\tbh,098H\t\t\t; function key 1 alt\n\ttest\tah,ALTPRESS\t\t; (highest prescendence)\n\tjne \tshort ??funcadj\n\tmov\tbh,0A2H\t\t\t; function key 1 ctrl (next highest)\n\ttest\tah,CTRLPRESS\n\tjne\tshort ??funcadj\n\tmov\tbh,0ACH\t\t\t; function key 1 shift (lowest)\n\n??funcadj:\n\tsub\tbh,bl\t\t\t; adjust function key to a\n\tmov\tal,bh\t\t\t; shift/no shift etc\n\tjmp\tshort ??exit\n\n??special:\n\tcmp\tal,65\t\t\t; if less than specials\n\tjb\tshort ??extout\n\n\tadd\tal,133\t\t\t; make value between 198-207 or\n\tjmp\tshort ??exit\t\t; 0C6H-0CFH\n\t\n??extout:\n\tor\tal,080H\n\tjmp\tshort ??exit\n\n??esc:\n\tmov\tal,01BH\n\n??exit:\n\tret\n\tENDP\tConvert_Num_To_ASCII\n\n;***************************************************************************\n;* CHECK_KEY -- checks for ASCII keys sitting in the keybuffer             *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      INT the ASCII sequence for the key that was pressed        *\n;*                                                                         *\n;* PROTO:\tINT Check_Key(VOID);                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key C NEAR\n\tUSES\tebx,edi,esi\n\n\tpushf\n\tcld\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tcmp\tal,KN_LMOUSE\t\t; check if it is a mouse or joystick\n\tjb\tshort ??contget\n\tcmp\tal,KN_JBUTTON2\n\tja\tshort ??contget\n\tadd\tsi,4\t\t\t; get rid of the x and y values\n\n??contget:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\teax,eax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\tsti\t\t\t\t; enable interrupts\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tcall\tnear ptr Convert_Num_To_ASCII\n\t\t\t\t\t; AX has ASCII code with bits\n\n\txor\tah,ah\t\t\t; clear key bits\n??exit:\n\tpopf\n\tret\n\tENDP\tCheck_Key\n\n\n;***************************************************************************\n;* GET_KEY -- Gets the next available ASCII keystroke.\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      AH - hold the key bits                                     *\n;*\t\tAL - holds the ASCII key value\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tINT Get_Key(VOID);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key C NEAR \n\tUSES \tebx,ecx,edi\n\n\tcld\t\t\t\t; clear the direction flag for speed\n\n\t; Check_Key had to be copied because of enable and disable of ints\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\t\t\t\t\t; AX has key num code with bits\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\txor\tah,ah\n\tret\n\n\tENDP\tGet_Key\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_ON -- Sets the specified keyflags on                *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned on                 *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are on                       *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_On(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_On C NEAR\n\tUSES\tesi,edi\n\tARG\tbits:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tor\t[(KeyboardType PTR esi).KeyFlags],eax\n\n\t; Only do this if in playback or record mode.\n\ttest\teax,PASSBREAKS\n\tje\tshort ??fini\n\n\txor\teax,eax\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).KeysUpDown\n\tmov\t[edi],eax\n\tmov\t[edi+4],eax\n\tmov\t[edi+8],eax\n\tmov\t[edi+12],eax\n??fini:\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\n\tret\n\tENDP\tKeyboard_Attributes_On\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_OFF -- Sets the specified keyflags off              *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned off                *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are off                      *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_Off(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_Off C NEAR\n\tUSES\tesi\n\tARG\tbits:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tnot\teax\n\tand\t[(KeyboardType PTR esi).KeyFlags],eax\n\txor\teax,eax\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\n\tret \n\n\tENDP\tKeyboard_Attributes_Off\n;***************************************************************************\n;* CLEAR_KEYBUFFER -- Clears keystrokes out of the key buffer              *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Clear_KeyBuffer(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tClear_KeyBuffer C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tcli\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\tsti\n\n\tret\n\n\tENDP\tClear_KeyBuffer\n\n;***************************************************************************\n;* KEY_DOWN -- tests the status of a keyboard key                          *\n;*                                                                         *\n;* INPUT:\tINT the key num to check                                   *\n;*                                                                         *\n;* OUTPUT:      INT zero if the key is up, none zero if the key is down    *\n;*                                                                         *\n;* PROTO:\tINT Key_Down(INT key);\t\t\t\t   \t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Down C NEAR\n\tUSES\tebx,ecx,edi,esi\n\tARG\tkey:DWORD\n\n\tpush\t[key]\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\txor\tah,ah\t\t\t\t; Always ignore the control bits.\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tedi,eax\n\tshr\tedi,3\n\tmov\tcl,al\n\tand\tcl,0111b\n\tmov\tal,01b\n\tshl\tal,cl\n\tand\tal,[(KeyboardType PTR esi+edi).KeysUpDown]\n\tret\n\n\tENDP\tKey_Down\n\n;***************************************************************************\n;* CHECK_KEY_BITS -- checks ascii key in key buff with shift,ctrl,alt bits *\n;*                                                                         *\n;* INPUT:\tnone \t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set     *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Bits C NEAR\n\tUSES\tebx,ecx,edi,esi\n\n\tpushf\t\t\t\t\t; save off the direction flag\n\tcld\t\t\t\t\t; we will go forward\n\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n??playback:\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\t;------ If there is a NULL in the keyboard buffer, we must NOT treat it\n\t;\tas a valid ASCII value because the calling code will falsely\n\t;\tassume that the NULL return value indicates an empty buffer.\n\tor\tal,al\n\tje\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\tax,ax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tCheck_Key_Bits\n;***************************************************************************\n;* GET_KEY_BITS -- Gets ascii key in key buff with shift,ctrl,alt bits     *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set\t   *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Bits C NEAR \n\tUSES\tebx,ecx,edi\n\n\tcld\n\n\t; Check_Key_Bits was copied because of enable and disable of interrupts\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\tret\n\n\tENDP\tGet_Key_Bits\n\n;***************************************************************************\n;* KEY_SATISFIED -- checks to see if the given key is satisfied            *\n;*                                                                         *\n;* INPUT:   INT the key flags/number to check                          \t   *\n;*                                                                         *\n;* OUTPUT:  INT 0 if the key is not satisfied, !0 if the key is satisfied  *\n;*                                                                         *\n;* PROTO:   VOID Key_Satisfied(INT key);                                    *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Satisfied C NEAR\n\tUSES\tebx,ecx,esi,edi\n\tARG\tkey:DWORD\n\n\tmov\teax,[key]\n\tmov\tebx,eax\t\t\t; save key code\n\tpush\teax\n\tcall\tKey_Down\t\t; see it its even down\n\tadd\tesp,4\n\tcmp\teax,0\n\tje\t??out\t\t\t; if not it can't be satisfied\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,ebx\t\t\t; if so, restore code\n\txor\tah,ah\t\t\t; clear out flags area\n\tmov\tedi,eax\t\t\t; set as an index\n\tshr\tedi,3\t\t\t; div by 8 for bytes\n\tmov\tch,1h\t\t\t; set a bit for mask\n\tmov\tcl,al\t\t\t; get the code number\n\tand\tcl,7\t\t\t; get the actual bit this code is\n\tshl\tch,cl\t\t\t; move bit into mask position\n\n; now test the ctrl,alt and shift bits\n\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],04h\t; is the left ctrl down?\n\tjne \tshort ??ctrlon\t\t; if so, ctrl is on\n\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],01h\t; is the right ctrl down?\n\tje \tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n??ctrlon:\n\tor\tah,02h\t\t\t; or on the ctrl bit in flags\n??ctrloff:\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],50h\t; is either alt key down?\n\tje \tshort ??altoff\n\tor\tah,04h\t\t\t; or on the alt bit in flags\n??altoff:\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],10h\t; is the left shift down?\n\tjne \tshort ??shifton\t\t; if so the sift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],02h\t; is the right shift down?\n\tje \tshort ??shiftoff\t\t; if not then neither shift is down\n??shifton:\n\tor\tah,01h\t\t\t; or on the shift bit in flags\n??shiftoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje \tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje \tshort ??capsoff\t\t; its not effected\n\txor\tah,1h\t\t\t; toggle the shift flag\n??capsoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t\t; is the num lock key on?\n\tje \tshort ??numlockoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje \tshort ??numlockoff\t\t; if not effected skip toggle\n\txor\tah,1h\t\t\t; toggle the shift flag if effected\n\n??numlockoff:\n\tmov\tal,0ffh\t\t\t; set to match by default\n\tcmp\tah,bh\t\t\t; if flags match return !0\n\tje \tshort ??out\t\t\t; just exit\n\txor\teax,eax\t\t\t; otherwise, clear all bits FALSE\n\n??out:\n\tor\teax,eax\n\tret\n\n\tENDP\tKey_Satisfied\n\n\n;***************************************************************************\n;* Interrupt routines start here - Interrupts must be within the Locked \n;*   code area for DPMI compatability.\n;***************************************************************************\n\n\n\n\nLABEL \tLockedCodeStart\tBYTE\n\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Performs a lowlevel xlate to a keycode              *\n;*                                                                         *\n;* INPUT:\tWORD the code that needs to be translated                  *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated code                                   *\n;*                                                                         *\n;* PROTO:\tINT KeyNum_Translate(INT keynum);                          *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyNum_Translate C NEAR \n\tUSES \tebx,ecx,esi,edi\n\tARG\tkeycode:DWORD\n\n;*===================================================================\n;* ES points to the DOSMEM selector, esi is the offset of the \n;*   protected mode structure.\n;*===================================================================\n\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\tmov\teax,[keycode]\n\ttest\t[(KeyboardType PTR esi).KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\n\tmov\tecx,OFFSET ((KeyboardType PTR 0).ExtRemap)- OFFSET((KeyboardType PTR 0).ExtNums)\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtNums\n\tadd\tedi,esi\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).ExtRemapEnd\n\tdec\tedi\n\tsub\tedi,ecx\n\tmov\tal,[edi]\n??fini:\n\tret\n\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(INT code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_WORD C NEAR\n\tUSES\tebx,esi,edi\n\tARG\tcode:WORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\tedi,eax\n\tadd\teax,2\n\tand\teax,0FFh\t\t\t; New KeyBufferTail value.\n\tcmp\t[(KeyboardType PTR esi).KeyBufferHead],eax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[(KeyboardType PTR esi+edi).KeyBuffer],bx\t\t; Record the keystroke.\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\n\tret\n\n??noroom:\n\tmov\teax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_Num C NEAR\n\tUSES\tebx,ecx,edx,edi,esi\n\tARG\tkeycode:DWORD\n\tLOCAL\ttail:DWORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n; for the moment we do not check for the interrupt flag\n;\tmov\teax,2534h \t\t; function to get the interrupt status\n;\tint\t21\t\t\t; eax = interrupt status\n;\tpush\teax\t\t\t; save the result on the stack\n\n\tpushf\t\t\t\t; store off the flags\n\tcli\t\t\t\t; disable interrupts\n\n; We need to set the data segment because we might be being called\n; from within an interrupt\n; Soo, if that is the case then DS & ES point to DGROUP _DATA \n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\teax,[(KeyboardType PTR esi).MouseX]\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\teax,[(KeyboardType PTR esi).MouseY]\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],ax\n\n??cando:\n\tmov\teax,[keycode]\t\t; get the code\n\tor\teax,eax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[(KeyboardType PTR esi).Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[(KeyboardType PTR esi).Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\txor\tebx,ebx\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tebx,1\t\t\t; double for WORD index\n\tmov\tax,[WORD PTR ((KeyboardType PTR esi+ebx).XYAdjust)]\n\n\tmovsx\tebx,ah\n\tmovsx\teax,al\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tedx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tedx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tebx,edx\t\t\t; add speed for y index\n\tmov\tbl,[(KeyboardType PTR esi+ebx).KeyMouseMove] \t; get speed for y delta\n\tmovsx\tebx,bl\n\txchg\tebx,edx\t\t\t; save mouse y delta\n\tadd\tebx,eax\t\t\t; add speed for x index\n\tmov\tal,[(KeyboardType PTR esi+ebx).KeyMouseMove]\t; get speed for x delta\n\tmovsx\teax,al\n\txchg\tebx,edx\t\t\t; restore mouse y delta\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tebx,011b\t\t\t; Y = 1, 0, 3\n\tand\teax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tebx,011b\t\t\t; Y = 3, 0, 1\n\tand\teax,011b\t\t\t; X = 3, 0, 1\n\tshl\tebx,2\n\tor\tebx,eax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tebx,1\n\tmovzx\tebx,[(KeyboardType PTR esi+ebx).EdgeConv]\n\tshl\tebx,2\n\tmov\tax,[(KeyboardType PTR esi+ebx).ScreenEdge]\t; New absolute X\n\tmov\tbx,[(KeyboardType PTR esi+ebx+2).ScreenEdge] ; New absolute Y\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\teax,eax\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tebx,ebx\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseX],ax\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseY],bx\n\tcmp\t[(KeyboardType PTR esi).MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n; PWG: ARRGGGHHHH!\n;\tcall\tLow_Hide_Mouse\n;\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\teax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],eax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tedi,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\t[tail],edi\t\t; Safety record.\n\n\t; Record the base keycode (if there is room).\n\tcwde\t\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\teax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tmovzx\teax,[(KeyboardType esi).LocalMouseX]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tmovzx\teax,[(KeyboardType esi).LocalMouseY]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tebx,0101h\t\t; Bit control tools.\n\tmov\teax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[(KeyboardType PTR esi).KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[(KeyboardType esi).KeyBufferTail],edi\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tmov\tcl,3\n\tshr\tedi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[(KeyboardType esi+edi).KeysUpDown]\n\tje\tshort ??notalready\n\ttest\t[(KeyboardType PTR esi).KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\tedx,[tail]\n\tmov\t[(KeyboardType esi).KeyBufferTail],edx\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[(KeyboardType esi+edi).KeysUpDown],bh\t; Force key bit to zero.\n\tor\t[(KeyboardType esi+edi).KeysUpDown],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\teax,1\n\tjmp\tshort ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\teax,[tail]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\t\t\t; Signal an error.\n\n??exit:\n\tsti\n\tpopf\n\n;\tpopf\n;\tpop\tebx\n;\tor\tebx,ebx\n;\tjz\t??final_exit\n;\tsti\n\n??final_exit:\n\tret\n\n\tENDP\tStuff_Key_Num\n\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles break interrupt for protected mode           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBreak_Interrupt C NEAR\n\n\tiret\n\tENDP\tBreak_Interrupt\n\nIF DEBUG\n;***************************************************************************\n;* DEBUG_INTERRUPT -- Handles debug (INT 3) interrupt for protected mode   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tDebug_Interrupt C NEAR\n\n\t;*==================================================================\n\t;* Setup fake Interrupt entry sequence so that we can execute our\n\t;*   code and then IRET painlessly into the debuggers interrupt\n\t;*   handler.\n\t;*==================================================================\n\tpushfd\t\t\t; Step 1\n\tsub\tesp,8\t\t; Step 2\n\tpush\tebp\t\t; Step 3\n\tmov\tebp,esp\t\t; Set up a stack frame to know where to poke address.\n\n\t;*==================================================================\n\t;* Preserve all of the registers that we intend to use.\n\t;*=======================================Dbg========================\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n\tmov\tax , _DATA\n\tmov\tds , ax\n\tmov\tes , ax\n\tinc\t[BYTE PTR 0B0000h]\n\n\t;*==================================================================\n\t;* Setup the pointers to the real mode data and the protected mode\n\t;*   data and selectors.\n\t;*==================================================================\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t;*==================================================================\n\t;* Do the deed.\n\t;*==================================================================\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\n\t;*==================================================================\n\t;* Now get the address of the real debug handler and poke it into\n\t;*   the stack so we can IRET to it.\n\t;*==================================================================\n\tmov\teax,[(KeyboardType PTR esi).DbgOldPMIOffset]\t; Get orig offset.\n\tmov\tebx,[(KeyboardType PTR esi).DbgOldPMISelector]\t; Get orig selector.\n\tmov\t[ss:ebp+4],eax\t\t\t\t\t; Poke offset.\n\tmov\t[ss:ebp+8],ebx\t\t\t\t\t; Poke selector.\n\n\t;*==================================================================\n\t;* Restore the stack so it looks like we just did an IRET entry\n\t;*==================================================================\n\tpop\tfs gs es ds\n\tpopad\n\tpop\tebp\n\n\t;*==================================================================\n\t;* This iret should go directly to the real debugger handler\n\t;*\tpainlessly and effectively.\n\t;*==================================================================\n\tiretd\n\n\tENDP\tDebug_Interrupt\nENDIF\n\n\n\nIF PROT_INT_ENABLE\n\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Handles input that comes from the keyboard        *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Interrupt C NEAR\n\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n; this is the part of the interrupt that set the segment registers\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov cx, ss\t\t\t\t; get SS\n\tmov [Keyboard_App_Stack_ESP], esp\t; Protect ESP\n\tmov [Keyboard_App_Stack_SS], ecx\t; Protect SS\n\tlea edx, [Keyboard_StackStart ]\t; Compute Local Stack size\n\tand edx, -4 ;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov esp, edx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\t\n\tmov\tedx,[(KeyboardType PTR esi).KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[(KeyboardType PTR esi).KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\ttest\t[BYTE PTR 417H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR 417H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR 496H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tebx,0101H\t\t; set key to a make by default \n\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\t;\n\t; New CODE to montior key stream\n\t;\n\txor\tebx,ebx\n\tmov\tbx,[(KeyboardType PTR esi).KeyStreamIndex]\n\tmov\t[(KeyboardType PTR esi+ebx).KeyStream],al\n\tinc\tebx\n\tand\tebx,15\n\tmov\t[(KeyboardType PTR esi).KeyStreamIndex],bx\n\tmov\tebx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[(KeyboardType PTR esi).LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[(KeyboardType PTR esi).LastKeyE1]\t\t; yes, dec the count\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[(KeyboardType PTR esi).IsExtKey],TRUE\t; it is an extended key\n\n\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtCodes\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).ExtNums-OFFSET (KeyboardType PTR 0).ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\n\tmov\tal,[(OFFSET (KeyboardType PTR 0).ExtNums - OFFSET (KeyboardType PTR 0).ExtCodes) - 1 + edi] ; get the match\n\tmov\t[(KeyboardType PTR esi).IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tedi,eax\t\t\t; use code as an index\n\tand\tedi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[(KeyboardType PTR esi+edi).KeyNums]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[(KeyboardType PTR esi).ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\teax\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\n;------\tSet the shift bit if necessary.\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tshr\tedi,3\n\tmov\tebx,eax\n\tand\tebx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[(KeyboardType PTR esi+ebx).Bits]\t\t; get the bit to test\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[(KeyboardType PTR esi).CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\n\t\t\t\t\t; keyboard buffer.\n\n\tmov\tecx,eax\n\txor\teax,eax\n\tmov\tax,cx\n\n\ttest\tedx,DEBUGINT\n\tjz\t??not_toggle\n\n\tcmp\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\n\tinc\t[BYTE PTR 0B0002h]\n\n\tcmp\teax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\teax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\teax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\t\n\tcmp\teax,125\n\tjne\t??not_toggle\n\n\tinc\t[BYTE PTR 0B0000h]\n\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjmp\t??absorbcode\n\n??not_toggle:\n\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\teax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\teax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\teax,0230h\n\tje\tshort ??breaker\n\tcmp\teax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[(KeyboardType PTR esi).Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n;\tcmp\tax,0420H\t\t; is this an alt s\n;\tjne\tshort ??checkmusic\t; toggle the Sound variable\n;\tpush\tax\n;\tmov\tax,[SoundOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??checkmusic:\n;\tcmp\tax,0434H\t\t; is this an alt m\n;\tjne\tshort ??esc\t\t; toggle the Music variable\n;\tpush\tax\n;\tmov\tax,[MusicOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??esc:\n\n\tpush\teax\n\tcall\tStuff_Key_Num\n\tpop\teax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[(KeyboardType PTR esi).EscRoutine],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\teax\n\tcall\t[(KeyboardType PTR esi).EscRoutine]\n\tpop\teax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tedi,OFFSET (KeyboardType PTR 0).PassAlways\t; get offset to table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd - OFFSET (KeyboardType PTR 0).PassAlways) ; get number of pass always CDY JLB MOD 7/11 was \n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tedi,OFFSET (KeyboardType PTR 0).CondPassKey\t; get offset to cond key table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).CondPassCond-OFFSET (KeyboardType PTR 0).CondPassKey) ; get number of entries\n\tshr\tecx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(OFFSET (KeyboardType PTR 0).CondPassCond - OFFSET (KeyboardType PTR 0).CondPassKey) - 2 + edi]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tedx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\tinc\t[(KeyboardType PTR esi).PassCount]\n\tmov\t[(KeyboardType PTR esi).PMIssuedKeyInt],1     ; Make it TRUE\n\n\t; Now it is time to set up for the call to the System Keyboard\n\t; interrupt handler.\n\t; 1 -Restore System Stack Pointer Selector before exit Interrupt\n\t; 2- We Create a Returning Point from Interrupt by Push A\n \t;    Interupt Stack Frame into the Stack Pointer\n\t; 3- We make a Far jump to the interuupt handler\n\n\tcmp  [Keyboard_StackPointer],0DEADDEADh\n\tje   ??pass_stack_good\n\n\tpush ecx\n\tpush edi\n\tpush eax\n\tmov  edi,0A0000h\n\tmov  ecx,64000\n\tmov  eax,1\n\trep  stosb\n\tpop  eax\n\tpop  edi\n\tpop  ecx\n\n??pass_stack_good:\n\tcli\t\t\t\t       ; disable Interrupts\n\tmov edx, [Keyboard_App_Stack_SS]       \n\tmov ss, dx\t\t\t       ; Set System Stack Selector\n\tmov esp, [Keyboard_App_Stack_ESP]      ; Set System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n\tlea\tedx, [??Call_Back_Keyboard]   ; Get Return address offset\n \tpushfd\t\t\t\t      ; push flags\t\n\tpush\tcs\t\t\t      ; push Code Selector\n\tpush\tedx\t\t\t      ; push Offset\n\n\t; Now we need to simulate an interrup call by using ired\n\t; because we still want to come back here from the\n\t; Old Keyboard interrupt handle.\n\tpushfd\n\tpush\t[(KeyboardType PTR esi).KeyOldPMISelector] ; push orig selector.\n\tpush    [(KeyboardType PTR esi).KeyOldPMIOffset]   ; push orig offset.\n\tiretd\n\n??absorbcode:\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tal,[496h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[496h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\n\tcmp  [Keyboard_StackPointer],0DEADDEADh\n\tje   ??call_stack_good\n\tpush ecx\n\tpush edi\n\tpush eax\n\tmov  edi,0A0000h\n\tmov  ecx,64000\n\tmov  eax,1\n\trep  stosb\n\tpop  eax\n\tpop  edi\n\tpop  ecx\n\n??call_stack_good:\n\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov edx, [Keyboard_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, dx\t\t\t       ; Set System Stack Selector\n\tmov esp, [Keyboard_App_Stack_ESP]      ; Set System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n??Call_Back_Keyboard:\n\tpop\tfs gs es ds\n\tpopad\n\tiret\t\n\n\tENDP\tKeyboard_Interrupt\n\nELSE\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Stub for the keyboard interrupt call real mode    *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\n \nDATASEG\nSTRUC\tRealModeCallStruc\n\t_EDI  DD\t0\n\t_ESI  DD\t0\n\t_EBP  DD\t0\n\t      DD        0\n\t_EBX  DD\t0\n\t_EDX  DD\t0\n\t_ECX  DD\t0\n\t_EAX  DD        0\n\tFLAGS DW\t0\n\t_ES   DW\t0\n\t_DS   DW\t0\n\t_FS   DW\t0\n\t_GS   DW\t0\n\t_IP   DW\t0\n\t_CS   DW\t0\n\t_SP   DW\t0\n\t_SS   DW\t0\n\t      dd\t0\n\t      dd\t0\n  nothing     dd\t0\t\nENDS \n\nRMDS RealModeCallStruc  <>\n\nCODESEG\n\nPROC\tKeyboard_Interrupt\tNear\n\n; This option of the keyboard interrupt handle will not be\n; available at this moment because the light version of Rational System DOS\n; Extender do not allow a DPMI real mode call which is\n; DMPI INT 31h funtion 0301h\n\n\tpushad\t\n\tpush\tfs gs es ds\n\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\n\tlea\tedi , [ RMDS ]\n\tlea\tecx , [ RMDS . nothing ]\n\tsub\tecx , edi\n\txor\teax , eax\n\tshr\tecx , 2\n\trep\tstosd\n\t\n\tmov\teax , 0300h\n\tmov\tbl , [ byte ptr RMVector ]\n\txor\tbh , bh\n\txor\tcx , cx\n\tlea\tedi , [RMDS]\n\tint\tDPMI_INTR\n\n; this is here only for testing to make sure\n; that a real mode interrupt is bieng issued. \nmov\tax , _DATA\nmov\tes , ax\nmov\tds , ax\nmov [ byte ptr 0b0000h + 10 * 80 + 40 ] , 040h\njc\t??error\nmov [ byte ptr 0b0000h + 10 * 80 + 42 ] , 041h\n\n??error:\n\tpop\tds es gs fs\n\tpopad\t\n\tiretd\n\tENDP\n\nENDIF\n\nLABEL \tLockedCodeEnd\t\tBYTE\n\n;***************************************************************************\n;* End of File.\t\t\t\t\t\t\t\t   *\n;***************************************************************************\nEND\n\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/NEW/KEYBOARD.BAK",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : KEYBOARD.ASM                             *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 15, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Get_RM_Timer_Address -- Return address of real mode code for copy.    *\n;*   Get_RM_Keyboard_Size -- return size of real mode timer code.          *\n;*   Check_Key -- checks queue for key (make)                              *\n;*   Check_Key_Num -- Checks if key in queue, return key num               *\n;*   Get_Key_Num -- Returns the next key num in ax                         *\n;*   KN_To_KA -- Translates a key num to an ASCII key                      *\n;*   Low_Get_Key -- low level get key returns key num and bits             *\n;*   Convert_Num_To_ASCII -- Assembly routine converts keynum to ASCII key *\n;*   KeyNum_Translate -- Performs a lowlevel xlate to a keycode            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\n;*\tKeyboard driver -- 80386 Protected Mode Assembly portion\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   \n;***************************************************************************\n;\n; ----------------------------------------------------------------\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\n;WARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Make some general equates for easy compatability\n;---------------------------------------------------------------------------\nPROT_INT_ENABLE\tEQU\t1\t\t; if false protected int just calls real mode int\n\nDPMI_INTR\tEQU\t31h\t\nIRQ1INTNUM\tEQU\t09h\t\t; IRQ1 interrupt vector number.\nBRKINTNUM\tEQU\t23h\t\t; Crtl-C (Break) interrupt vector number\nDBGINTNUM\tEQU\t3h\t\t; Debug interrupt vector number\nDOS_SYS_CALL\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nLOCK_PAGES\tEQU\t5\t\t; Lock pages subfunction using DX_MEM_MGT\nUNLOCK_PAGES\tEQU\t6\t\t; Unlock pages subfunction using DX_MEM_MGT\nCLEARISR\tEQU\t020H\t; value to clear In Service Register\nINTCHIP0\tEQU\t020H\t; 8259 interrupt chip controller 0\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\n\tINCLUDE \"keyboard.inc\"\n\tINCLUDE \"keystruc.inc\"\n\tINCLUDE \"mcgaprim.inc\"\n\n\tGLOBAL\t RealModePtr:DWORD\n\n\tGLOBAL\t Install_Keyboard_Interrupt:NEAR\n\tGLOBAL\t Get_RM_Keyboard_Address:Near\n\tGLOBAL\t Get_RM_Keyboard_Size:Near\n\tGLOBAL\t Remove_Keyboard_Interrupt:NEAR\n\tGLOBAL\t Check_Key_Num:NEAR\n\tGLOBAL\t Get_Key_Num:NEAR\n\tGLOBAL\t KN_To_KA:NEAR\n\tGLOBAL\t KeyNum_Translate:NEAR\n\tGLOBAL\t Check_Key:NEAR\n\tGLOBAL\t Get_Key:NEAR\n\tGLOBAL\t Keyboard_Attributes_On:NEAR\n\tGLOBAL\t Clear_KeyBuffer:NEAR\n\tGLOBAL\t Key_Down:NEAR\n\tGLOBAL\t Keyboard_Attributes_Off:NEAR\n\tGLOBAL\t Check_Key_Bits:NEAR\n\tGLOBAL\t Get_Key_Bits:NEAR\n\tGLOBAL\t Key_Satisfied:NEAR\n\tGLOBAL\t Stuff_Key_WORD:NEAR\n\tGLOBAL\t Stuff_Key_Num:NEAR\n\tGLOBAL\t MouseQX:DWORD\n\tGLOBAL\t MouseQY:DWORD\n;DBG\n\tGLOBAL   Keyboard_Interrupt:NEAR\n\n\n\tDATASEG\n; For the current time we will just include the real mode stuff\n; into the protected mode code and then copy it down.  The C side of\n; this will handle this method or reading it off of disk in the real\n; method.\n\nLABEL \tRealBinStart\tBYTE\ninclude \"keyireal.ibn\"\nLABEL\tRealBinEnd\tBYTE\n\nLABEL\tLockedDataStart\tBYTE\t\nRMVector\tDD\t0\nRealModeSel\tDD\t0\nRealModePtr\tDD\t0\t\t; Pointer to real mode memory.\nRealModeSize\tDD\t0\t\t; Pointer to real mode memory.\n\nKeyboard_App_Stack_ESP\tDD 0\t\t; This the System Stack Offsset\nKeyboard_App_Stack_SS\tDD 0\t\t; This the System Stack Selector\nKeyboard_StackPointer\tDD 0DEADDEADh\t; We Create a Local Application\nKeyboard_Stack          DD 255 dup (0)\nKeyboard_StackStart\tDD 0\n\t\t\t\t\t; StackPointer \t\nLABEL\tLockedDataEnd\tBYTE\n\n\n\nAscii\tDB\t0,\"`1234567890-=\",0,8,9,\"qwertyuiop[]\\\",0,\"asdfghjkl;'\"\n\tDB\t0,13,0,45,\"zxcvbnm,./\",0,0,0,0,0,\" \"\n\nShift\tDB\t0,\"~!@#$%^&*()_+\",0,8,9,\"QWERTYUIOP{}|\",0,\"ASDFGHJKL:\",22H\n\tDB\t0,13,0,45,\"ZXCVBNM<>?\",0,0,0,0,0,\" \"\n\nAlpha_Lower\tDB\t0\n\tDB\t\"~!@#$%^&*()_+\",0,8,9,\"qwertyuiop{}|\",0,\"asdfghjkl:\",22H\n\tDB\t0,13,0,45,\"zxcvbnm<>?\",0,0,0,0,0,\" \"\n\nAlpha_Shift\tDB\t0\n\tDB\t\"`1234567890-=\",0,8,9,\"QWERTYUIOP[]\\\",0,\"ASDFGHJKL;'\"\n\tDB\t0,13,0,45,\"ZXCVBNM,./\",0,0,0,0,0,\" \"\n\nEdit\tDB\t0AEH,0ADH,000H,000H,0B5H,0B9H,0B1H,000H,0B8H,0B0H,0B7H,0AFH\n\tDB\t000H,000H,0B3H,000H,0B9H,0B5H,0B1H,000H, \"/\",0B8H,0B4H,0B0H\n\tDB\t0AEH, \"*\",0B7H,0B3H,0AFH,0ADH, \"-\", \"+\",000H,00DH,000H\n\nNumPad\tDB\t0,\"741\",0,\"/8520*963.-+\",0,13,0\n\n\nGetKeyLock\tDW\t0\t; snap shot of num and caps lock bits\nInitFlags\tDW\t0\nMouseQX\t\tDD\t0\nMouseQY\t\tDD\t0\n\n\tCODESEG\n;***************************************************************************\n;* GET_RM_TIMER_ADDRESS -- Return address of real mode code for copy.      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      VOID * to the address of the real mode timer               *\n;*                                                                         *\n;* PROTO:\tVOID\t*Get_RM_Keyboard_Address(VOID);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Address C Near\n\n\tmov\teax, OFFSET RealBinStart\n\tret\n\n\tENDP\n\n;***************************************************************************\n;* GET_RM_KEYBOARD_SIZE -- return size of real mode timer code.            *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      LONG size of the real mode timer code                      *\n;*                                                                         *\n;* PROTO:\tLONG\tGet_RM_Keyboard_Size(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Size C Near\n\n\tmov\teax, OFFSET RealBinEnd - OFFSET RealBinStart\n\tret\n\n\tENDP\n;***************************************************************************\n;* INSTALL_KEYBOARD_INTERRUPT -- Installs the keyboard interrupt           *\n;*                                                                         *\n;* INPUT:\tint rm_ptr  - ptr to the real mode handler\t\t   *\t   *\n;*\t\tint rm_size - size of the real mode handler\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Install_Keyboard_Interrupt(int rm_ptr, int rm_size);  *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tInstall_Keyboard_Interrupt C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\tARG\trm_ptr:DWORD\n\tARG\trm_size:DWORD\n\n\t; Are they attempting to set timer again?\n\tcmp\t[RealModePtr],0\n\tjnz\t??error\n\n\t; Make sure all flags are cleared.\n\tcmp\t[InitFlags],0\n\tjnz\t??error\n\n\n\t; Before setting the interrupt vectors, the code needs to be locked\n\t; for DPMI compatability.  Any code or data accessed must be lockded\n\t; so that no page faults accure during an interrupt.\n\t; First lock the code, then the data.  The stack will already be locked.\n\t; The real mode code is also already locked be default.\n\t; To lock a page set up registers :\n\t; AX = 0600h\n\t; BX:CX\t= starting linear address of memory block\n\t; SI:DI = size of region\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_CODE\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_DATA\n\n\t; now allocate real mode memory and copy the rm binary down to it.\n\tmov\teax,0100h\t; set function number\n\tmov\tebx,[rm_size]\t\t; get size of RM binary.\n\tmov\t[RealModeSize],ebx\n\tadd\tebx,15\t\t\t; round up \n\tshr\tebx,4\t\t\t; convert to pages.\n\tint\tDPMI_INTR\t \t; do call.\n\tjc\t??error\t\t \t; check for error.\n\tor\t[InitFlags],IF_ALLOC_RM ; set successful\n\tmov\t[RealModeSel],edx\n\tshl\teax,4\t\t\t; convert segment to offset.\n\tmov\t[RealModePtr],eax\t; save offset to global variable.\n\n\t; now lock the real mode memory that we allocated\n\tmov\teax,0600h\t\t; function number.\n\tmov\tecx,[RealModePtr]\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_RM_CODE\n\n\n\n\t; set up source and destination pointers for the copy.\n\tmov\teax,[RealModePtr];\t; set up our dest pointer\n\tmov\tesi,[rm_ptr]\t\t; Set up our source pointer.\n\tmov\tedi,eax\t\t\t; put it into esi for copy.\n\tmov\tecx,[rm_size]\n\trep\tmovsb\t\t\t; write RM bin to RM memory.\n\n\t; restore esi to point to data and initialize some of it.\n\tmov\tesi,[RealModePtr]\n\tmov\teax,esi\n\tshl\teax,12\t\t\t\t\t\t; make seg in high eax.\n\tmov\tax,[(KeyboardType PTR esi).CallKeyRMIntOffset]\t; create RM addr of call chain.\n\tmov\t[(KeyboardType PTR esi).CallKeyRMIntAddr],eax\t; save it for use in PM int.\n\nIF NOT PROT_INT_ENABLE\n       ; Chain the Real Keyboard interrupt to any avilable\n       ; Interrupt vector so We make sure that the Real Mode\n       ; Keyboard Interrupt service get called at debuging time\n       ; of the library.\n\n       mov\tedi , eax\n       mov\tbl , 060h\n       mov\tbh , 6\n       mov\teax , 200h\n ??find:\n       int\tDPMI_INTR\n       jc\t??error\n       or\tcx,dx\n       jz\t??found\n       inc\tbl\n       dec\tbh\n       jnz\t??find\n       jmp\t??error\n ??found:\n       movzx\tebx , bl\n       mov\t[ byte ptr RMVector ] , bl\n       mov\t[ 4 * ebx ] , edi\nENDIF\n\n\n\n\t;-------------------------------------------------------\n\t; Initialize all of the keyboard specific information\n\t;-------------------------------------------------------\n\txor\teax,eax\t\t\t; clear the high bits of eax\n\tmov\tal,[417H]\t\t; get keyboard status flags\n\ttest\teax,040H \t\t; caps lock active?\n\tje \tshort ??nocap\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\n\n??nocap:\n\ttest\teax,020H\t\t\t; num lock active?\n\tje\tshort ??nonumlock\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\n\n??nonumlock:\n\ttest\teax,002H\t\t\t; is left shift key down?\n\tje\tshort ??noleftshift\t\t; try the right\n\tor\t[(KeyboardType PTR esi+5).KeysUpDown],010H\n\n??noleftshift:\n\tand\teax,001H\t\t\t; get right shift bit\n\tshl\teax,9\t\t\t; put it into the proper position (shl al,1 mov ah,al)\n\tmov\tal,[418H]\t\t; get alt and ctrl bits\n\tshl\tal,2\t\t\t; put in proper position\n\tshl\tal,1\n\tand\tal,00CH\t\t\t; only alt and ctrl bits\n\tor\tah,al\t\t\t; put them ah for Keys+7 later\n\tmov\tal,[496H]\t\t; get extended keys\n\ttest\tal,008H\t\t\t; check for right alt key\n\tje\tshort ??noralt\n\tor\tah,040H\n??noralt:\n\tmov\t[(KeyboardType PTR esi+7).KeysUpDown],ah\n\ttest\tal,004H\t\t\t; test for right ctrl\n\tje \tshort ??norctrl\n\tor\t[(KeyboardType PTR esi+8).KeysUpDown],001h\n??norctrl:\n\ttest\tal,002H\t\t\t; last code E0?\n\tje short ??noe0\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],001h\n??noe0:\n\ttest\tal,001H\t\t\t; last code E1?\n\tje short ??noe1\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],002h\n??noe1:\n\t;==========================================================================\n\t; Get the protected mode interrupt vector keyboard.\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).KeyOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).KeyOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 2503, cl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).KeyOldRMI],ecx\n\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt Keyboard\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Keyboard_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt Keyboard\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).KeyCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the break interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\t\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).BrkOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).BrkOldPMISelector],ecx\t; save selector.\n\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector - for the break interrupt\n\t; input ax = 0200, bl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).BrkOldRMI],ecx\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Break_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).BrkCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\nIF DEBUG\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the Debug interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\t\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,DBGINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).DbgOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).DbgOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Debug_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\nENDIF\n\n\t; we have finished with success.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n??exit:\n\tret\n\tENDP\tInstall_Keyboard_Interrupt\n\n;***************************************************************************\n;* REMOVE_INTERRUPT -- Removes keyboard interrupt and restores chain\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Remove_Interrupt(VOID)                                *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tRemove_Keyboard_Interrupt C NEAR \n\tUSES\tebx,ecx,edx\n\n\t; verifie that the keyboard was previosly install\n\t; this is here in case of a page fault crash\n\tmov\tesi,[RealModePtr]\n\ttest    esi,esi\n\tjz      ??error\n\n\ttest\t[InitFlags],IF_SET_VECTORS\n\tjz\t??vectors_not_set\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tedx,[(KeyboardType esi).KeyOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[(KeyboardType esi).KeyOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).KeyOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\n\t; disengage Control Break Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tedx,[(KeyboardType esi).BrkOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[(KeyboardType esi).BrkOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).BrkOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\nIF DEBUG\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tecx,[(KeyboardType esi).DbgOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).DbgOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\nENDIF\n\nIF NOT PROT_INT_ENABLE\n       ; Clean up the Users interrupt table\n        mov\teax , 201h\n       mov\tbl , [ byte ptr RMVector ]\n       xor\tecx , ecx\n       xor\tedx , edx\n       int\tDPMI_INTR\n       jc\t??error\nENDIF\n\n\n??vectors_not_set:\n\t; now free up the real mode memory.\n\ttest\t[InitFlags],IF_LOCKED_RM_CODE\n\tjz\t??rm_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,[RealModePtr]\t\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t\t; edx will have size of region in bytes.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??rm_not_locked:\n\ttest\t[InitFlags],IF_ALLOC_RM\n\tjz\t??mem_not_allocated\n\tmov\teax , 0101h\n\tmov\tedx,[ RealModeSel ] \t\t; get physical address of real mode buffer.\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n??mem_not_allocated:\n\n\t; Now we can unlock all stuff needed for the interrupt.  \n\t; Unlock Code\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??code_not_locked:\n\n\t; Unlock data\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??data_not_locked:\n\n\t; we have finished with success.\n\tmov\t[RealModePtr],0\t\t; To say we can do it again sometime.\n\tmov\t[InitFlags],0\t\t; To say we can do it again sometime.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n\tret\n\tENDP\tRemove_Keyboard_Interrupt\n\n\n;***************************************************************************\n;* CHECK_KEY_NUM -- Checks if key in queue, return key num                 *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      Keynum of the key that was pressed, FALSE otherwise        *\n;*\n;* PROTO:\tINT Check_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Num C NEAR \n\tUSES\tebx,esi\n\tpushf\t\t\t\t\t; save off the flags\n\tcli\t\t\t\t\t; disable interrupts\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t\t\n\txor\teax,[(KeyboardType PTR esi).KeyBufferTail]\t\t\n\tor\teax,eax\t\t\t\t; check to see if head == tail\n\tjz\tshort ??fini\t\t\t; if so we are done\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t; get the head\n\tmov\tax,[(KeyboardType PTR esi+eax).KeyBuffer]\t; get key num\n\n??fini:\n\tsti\n\tpopf\n\tret\n\n\tENDP\tCheck_Key_Num\n\n;***************************************************************************\n;* GET_KEY_NUM -- Returns the next key num in ax                           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      WORD key flags are in the high byte of return word, key    *\n;*\t\t  num is in the low byte.\n;*                                                                         *\n;* PROTO:\tWORD Get_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Num C NEAR\n\tUSES\tesi,edi\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n??wait:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t\t; get the head\n\tcmp\teax,[(KeyboardType PTR esi).KeyBufferTail]\t\t; get the head\n\tjne\tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??wait\n\n??getkey:\n\tcall\tLow_Get_Key\n\tsti\t\t\t\t; enable interrupts\n\tret\n\n\tENDP\tGet_Key_Num\n\n;***************************************************************************\n;* KN_TO_KA -- Translates a key num to an ASCII key                        *\n;*                                                                         *\n;* INPUT:\tWORD the keynum to translate                               *\n;*                                                                         *\n;* OUTPUT:      WORD the ASCII key that is returned                        *\n;*                                                                         *\n;* PROTO:\tINT KN_To_KA(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tKN_To_KA C NEAR\n\tARG\tkeynum:DWORD\n\n\tmov\teax,[keynum]\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\tret\n\n\tENDP\tKN_To_KA\n\n\n;***************************************************************************\n;* LOW_GET_KEY -- low level get key returns key num and bits               *\n;*                                                                         *\n;* INPUT:\tAX - index into the buffer                                 *\n;*                                                                         *\n;* OUTPUT:      AX - key num with bits                                     *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tLow_Get_Key C NEAR \n\tUSES\tebx,esi,edi\n\n\tmov\tedi,eax\t\t\t\t; save off value in ax\n\n; We should set up both DS & ES because we are a low level function\n; and don't know who might have called us or what the registers\n; currently are.\n\n; No reason to set DS & ES.\n; This is not a hardware interrupt and if the funtion is being called\n; from within a hardware interrupt then DS and ES will be preset to\n; DGROUP _DATA\n\t\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tcmp\tal,KN_LMOUSE\n\tjb \tshort ??cont\n\tcmp\tal,KN_RMOUSE\n\tja \tshort ??chkjoy\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t; 128 word circular buffer\n\n\tmov\t[MouseQX],eax\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\t[MouseQY],eax\n\n\tpop\teax\t\t\t; restore keynum for return\n\n\tjmp\tshort ??cont\n\n??chkjoy:\n\tcmp\tal,KN_JBUTTON2\t\t; mouse button before joystick button\n\tja \tshort ??cont\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tpop\teax\t\t\t; restore keynum for return\n??cont:\n\tmov\t[(KeyboardType PTR esi).KeyBufferHead],edi\t; set the head\n\n??out:\n\tret\n\n\tENDP\tLow_Get_Key\n\n;***************************************************************************\n;* CONVERT_NUM_TO_ASCII -- Assembly routine converts keynum to ASCII key   *\n;*                                                                         *\n;* INPUT:\tEAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - holds the key num bits                        *\n;*\t\t\tAL - holds the key num value\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      EAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - hold the key bits                             *\n;*\t\t\tAL - holds the ASCII key value\t\t\t   *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* WARNINGS:    GetKeyLock must be set prior to calling this function\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tConvert_Num_To_ASCII C NEAR \n\tUSES\tebx,ecx,esi,edi\n\n\t;*===================================================================\n\t;* Force all breaks to be thrown out.\n\t;*===================================================================\n\ttest\teax,08000h\t\t; If it is a button number\n\tjne\tshort ??button\t\t;  don't process it\n\n\ttest\tah,KEYRELEASE\t\t; If it is not key release\n\tje\tshort ??ok\t\t;  then go process it\n\n??button:\n\txor\teax,eax\t\t\t; no ascii value for a button\n\tret\n\n??ok:\n\t;*===================================================================\n\t;* ES points to the DOSMEM selector, esi is the offset of the \n\t;*   protected mode structure.\n\t;*===================================================================\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\n\t;*===================================================================\n\t;* Start dealing with the keys.\t\t\t\t\t  \n\t;*===================================================================\n\tcmp\tal,110\t\t\t; is it esc\n\tje\t??esc\t\t\t; if so then deal with it\n\n;??chkext:\n\tcmp\tal,62\t\t\t; is it extended?\n\tjae\tshort ??extended\t; its extended so return ext code\n\n\tmov\tebx,eax\t\t\t; get an index\n\tand\tebx,03FH\t\t; only 0-63 allowed\n\ttest\tah,1\t\t\t; if not, test for shift\n\tjnz\tshort ??shifted\t\t; if shifted get shift value\n\n\t;*===================================================================\n\t;* Here when we have an unshifted ascii key\n\t;*===================================================================\n\tmov\tal,[Ascii+ebx]\t\t; get the ascii code for this number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_lowered:\n\tmov\tal,[Alpha_Lower+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_shifted:\n\tmov\tal,[Alpha_Shift+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* Shift'ed character\n\t;*===================================================================\n??shifted:\n\tmov\tal,[Shift+ebx] \t\t; get ascii shift code for number\n\n??ctrlkey:\n\ttest\tah,2\t\t\t; is it ctrl?\n\tjz \tshort ??jexit\t\t; izf not skip ctrl check\n\n\tmov\tedi,ebx\t\t\t; get index\n\tand\tedi,7\t\t\t; only bits 0-7\n\n\tmov\tcl,[(KeyboardType PTR esi+edi).Bits]\n\n\tshr\tebx,3\t\t\t; div by 8 for byte offset\n\ttest\t[(KeyboardType PTR esi+ebx).KeysCapsLock],cl\t\n\tje \tshort ??jexit\n\tand\tal,01FH\t\t\t; force to ctrl value\n\n??jexit:\n\tjmp short ??exit\n\n??extended:\n\tcmp\tal,75\t\t\t; if less than insert\n\tjb \tshort ??special\n\tcmp\tal,110\t\t\t; if >= esc\n\tjae \tshort ??funckey\n\n??editkeys:\n\txor\tebx,ebx\n\tmov\tbl,al\n\tsub\tebx,75\t\t\t; get value from 0-34\n\ttest\t[(KeyboardType PTR esi).KeyFlags],NONUMLOCK\n\tjne \tshort ??no_numpad\n\ttest\t[GetKeyLock],NUMLOCK\t; look at the snap shot of bits\n\tjne \tshort ??numpad\n\n??no_numpad:\n\tmov\tal,[Edit+ebx] \t\t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??numpad:\n\tsub\tebx,15\t\t\t; adjust to numpad entries\n\tmov\tal,[NumPad+ebx] \t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??funckey:\n\tcmp\tal,112\t\t\t; if less than function keys\n\tjb \tshort ??extout\n\tcmp\tal,121\t\t\t; if greater than function keys 1-10\n\tja \tshort ??extout\n\tmov\tbl,al\n\tsub\tbl,112\t\t\t; get value 0-9\n\tmov\tbh,0C5H\t\t\t; function key 1 no shift-ctrl-alt\n\ttest\tah,7\t\t\t; any shift-ctrl-alt\n\tje\tshort ??funcadj\n\tmov\tbh,098H\t\t\t; function key 1 alt\n\ttest\tah,ALTPRESS\t\t; (highest prescendence)\n\tjne \tshort ??funcadj\n\tmov\tbh,0A2H\t\t\t; function key 1 ctrl (next highest)\n\ttest\tah,CTRLPRESS\n\tjne\tshort ??funcadj\n\tmov\tbh,0ACH\t\t\t; function key 1 shift (lowest)\n\n??funcadj:\n\tsub\tbh,bl\t\t\t; adjust function key to a\n\tmov\tal,bh\t\t\t; shift/no shift etc\n\tjmp\tshort ??exit\n\n??special:\n\tcmp\tal,65\t\t\t; if less than specials\n\tjb\tshort ??extout\n\n\tadd\tal,133\t\t\t; make value between 198-207 or\n\tjmp\tshort ??exit\t\t; 0C6H-0CFH\n\t\n??extout:\n\tor\tal,080H\n\tjmp\tshort ??exit\n\n??esc:\n\tmov\tal,01BH\n\n??exit:\n\tret\n\tENDP\tConvert_Num_To_ASCII\n\n;***************************************************************************\n;* CHECK_KEY -- checks for ASCII keys sitting in the keybuffer             *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      INT the ASCII sequence for the key that was pressed        *\n;*                                                                         *\n;* PROTO:\tINT Check_Key(VOID);                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key C NEAR\n\tUSES\tebx,edi,esi\n\n\tpushf\n\tcld\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tcmp\tal,KN_LMOUSE\t\t; check if it is a mouse or joystick\n\tjb\tshort ??contget\n\tcmp\tal,KN_JBUTTON2\n\tja\tshort ??contget\n\tadd\tsi,4\t\t\t; get rid of the x and y values\n\n??contget:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\teax,eax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\tsti\t\t\t\t; enable interrupts\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tcall\tnear ptr Convert_Num_To_ASCII\n\t\t\t\t\t; AX has ASCII code with bits\n\n\txor\tah,ah\t\t\t; clear key bits\n??exit:\n\tpopf\n\tret\n\tENDP\tCheck_Key\n\n\n;***************************************************************************\n;* GET_KEY -- Gets the next available ASCII keystroke.\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      AH - hold the key bits                                     *\n;*\t\tAL - holds the ASCII key value\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tINT Get_Key(VOID);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key C NEAR \n\tUSES \tebx,ecx,edi\n\n\tcld\t\t\t\t; clear the direction flag for speed\n\n\t; Check_Key had to be copied because of enable and disable of ints\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\t\t\t\t\t; AX has key num code with bits\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\txor\tah,ah\n\tret\n\n\tENDP\tGet_Key\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_ON -- Sets the specified keyflags on                *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned on                 *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are on                       *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_On(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_On C NEAR\n\tUSES\tesi,edi\n\tARG\tbits:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tor\t[(KeyboardType PTR esi).KeyFlags],eax\n\n\t; Only do this if in playback or record mode.\n\ttest\teax,PASSBREAKS\n\tje\tshort ??fini\n\n\txor\teax,eax\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).KeysUpDown\n\tmov\t[edi],eax\n\tmov\t[edi+4],eax\n\tmov\t[edi+8],eax\n\tmov\t[edi+12],eax\n??fini:\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\n\tret\n\tENDP\tKeyboard_Attributes_On\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_OFF -- Sets the specified keyflags off              *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned off                *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are off                      *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_Off(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_Off C NEAR\n\tUSES\tesi\n\tARG\tbits:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tnot\teax\n\tand\t[(KeyboardType PTR esi).KeyFlags],eax\n\txor\teax,eax\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\n\tret \n\n\tENDP\tKeyboard_Attributes_Off\n;***************************************************************************\n;* CLEAR_KEYBUFFER -- Clears keystrokes out of the key buffer              *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Clear_KeyBuffer(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tClear_KeyBuffer C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tcli\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\tsti\n\n\tret\n\n\tENDP\tClear_KeyBuffer\n\n;***************************************************************************\n;* KEY_DOWN -- tests the status of a keyboard key                          *\n;*                                                                         *\n;* INPUT:\tINT the key num to check                                   *\n;*                                                                         *\n;* OUTPUT:      INT zero if the key is up, none zero if the key is down    *\n;*                                                                         *\n;* PROTO:\tINT Key_Down(INT key);\t\t\t\t   \t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Down C NEAR\n\tUSES\tebx,ecx,edi,esi\n\tARG\tkey:DWORD\n\n\tpush\t[key]\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\txor\tah,ah\t\t\t\t; Always ignore the control bits.\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tedi,eax\n\tshr\tedi,3\n\tmov\tcl,al\n\tand\tcl,0111b\n\tmov\tal,01b\n\tshl\tal,cl\n\tand\tal,[(KeyboardType PTR esi+edi).KeysUpDown]\n\tret\n\n\tENDP\tKey_Down\n\n;***************************************************************************\n;* CHECK_KEY_BITS -- checks ascii key in key buff with shift,ctrl,alt bits *\n;*                                                                         *\n;* INPUT:\tnone \t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set     *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Bits C NEAR\n\tUSES\tebx,ecx,edi,esi\n\n\tpushf\t\t\t\t\t; save off the direction flag\n\tcld\t\t\t\t\t; we will go forward\n\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n??playback:\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\t;------ If there is a NULL in the keyboard buffer, we must NOT treat it\n\t;\tas a valid ASCII value because the calling code will falsely\n\t;\tassume that the NULL return value indicates an empty buffer.\n\tor\tal,al\n\tje\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\tax,ax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tCheck_Key_Bits\n;***************************************************************************\n;* GET_KEY_BITS -- Gets ascii key in key buff with shift,ctrl,alt bits     *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set\t   *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Bits C NEAR \n\tUSES\tebx,ecx,edi\n\n\tcld\n\n\t; Check_Key_Bits was copied because of enable and disable of interrupts\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\tret\n\n\tENDP\tGet_Key_Bits\n\n;***************************************************************************\n;* KEY_SATISFIED -- checks to see if the given key is satisfied            *\n;*                                                                         *\n;* INPUT:   INT the key flags/number to check                          \t   *\n;*                                                                         *\n;* OUTPUT:  INT 0 if the key is not satisfied, !0 if the key is satisfied  *\n;*                                                                         *\n;* PROTO:   VOID Key_Satisfied(INT key);                                    *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Satisfied C NEAR\n\tUSES\tebx,ecx,esi,edi\n\tARG\tkey:DWORD\n\n\tmov\teax,[key]\n\tmov\tebx,eax\t\t\t; save key code\n\tpush\teax\n\tcall\tKey_Down\t\t; see it its even down\n\tadd\tesp,4\n\tcmp\teax,0\n\tje\t??out\t\t\t; if not it can't be satisfied\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,ebx\t\t\t; if so, restore code\n\txor\tah,ah\t\t\t; clear out flags area\n\tmov\tedi,eax\t\t\t; set as an index\n\tshr\tedi,3\t\t\t; div by 8 for bytes\n\tmov\tch,1h\t\t\t; set a bit for mask\n\tmov\tcl,al\t\t\t; get the code number\n\tand\tcl,7\t\t\t; get the actual bit this code is\n\tshl\tch,cl\t\t\t; move bit into mask position\n\n; now test the ctrl,alt and shift bits\n\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],04h\t; is the left ctrl down?\n\tjne \tshort ??ctrlon\t\t; if so, ctrl is on\n\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],01h\t; is the right ctrl down?\n\tje \tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n??ctrlon:\n\tor\tah,02h\t\t\t; or on the ctrl bit in flags\n??ctrloff:\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],50h\t; is either alt key down?\n\tje \tshort ??altoff\n\tor\tah,04h\t\t\t; or on the alt bit in flags\n??altoff:\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],10h\t; is the left shift down?\n\tjne \tshort ??shifton\t\t; if so the sift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],02h\t; is the right shift down?\n\tje \tshort ??shiftoff\t\t; if not then neither shift is down\n??shifton:\n\tor\tah,01h\t\t\t; or on the shift bit in flags\n??shiftoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje \tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje \tshort ??capsoff\t\t; its not effected\n\txor\tah,1h\t\t\t; toggle the shift flag\n??capsoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t\t; is the num lock key on?\n\tje \tshort ??numlockoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje \tshort ??numlockoff\t\t; if not effected skip toggle\n\txor\tah,1h\t\t\t; toggle the shift flag if effected\n\n??numlockoff:\n\tmov\tal,0ffh\t\t\t; set to match by default\n\tcmp\tah,bh\t\t\t; if flags match return !0\n\tje \tshort ??out\t\t\t; just exit\n\txor\teax,eax\t\t\t; otherwise, clear all bits FALSE\n\n??out:\n\tor\teax,eax\n\tret\n\n\tENDP\tKey_Satisfied\n\n\n;***************************************************************************\n;* Interrupt routines start here - Interrupts must be within the Locked \n;*   code area for DPMI compatability.\n;***************************************************************************\n\n\n\n\nLABEL \tLockedCodeStart\tBYTE\n\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Performs a lowlevel xlate to a keycode              *\n;*                                                                         *\n;* INPUT:\tWORD the code that needs to be translated                  *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated code                                   *\n;*                                                                         *\n;* PROTO:\tINT KeyNum_Translate(INT keynum);                          *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyNum_Translate C NEAR \n\tUSES \tebx,ecx,esi,edi\n\tARG\tkeycode:DWORD\n\n;*===================================================================\n;* ES points to the DOSMEM selector, esi is the offset of the \n;*   protected mode structure.\n;*===================================================================\n\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\tmov\teax,[keycode]\n\ttest\t[(KeyboardType PTR esi).KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\n\tmov\tecx,OFFSET ((KeyboardType PTR 0).ExtRemap)- OFFSET((KeyboardType PTR 0).ExtNums)\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtNums\n\tadd\tedi,esi\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).ExtRemapEnd\n\tdec\tedi\n\tsub\tedi,ecx\n\tmov\tal,[edi]\n??fini:\n\tret\n\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(INT code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_WORD C NEAR\n\tUSES\tebx,esi,edi\n\tARG\tcode:WORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\tedi,eax\n\tadd\teax,2\n\tand\teax,0FFh\t\t\t; New KeyBufferTail value.\n\tcmp\t[(KeyboardType PTR esi).KeyBufferHead],eax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[(KeyboardType PTR esi+edi).KeyBuffer],bx\t\t; Record the keystroke.\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\n\tret\n\n??noroom:\n\tmov\teax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_Num C NEAR\n\tUSES\tebx,ecx,edx,edi,esi\n\tARG\tkeycode:DWORD\n\tLOCAL\ttail:DWORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n; for the moment we do not check for the interrupt flag\n;\tmov\teax,2534h \t\t; function to get the interrupt status\n;\tint\t21\t\t\t; eax = interrupt status\n;\tpush\teax\t\t\t; save the result on the stack\n\n\tpushf\t\t\t\t; store off the flags\n\tcli\t\t\t\t; disable interrupts\n\n; We need to set the data segment because we might be being called\n; from within an interrupt\n; Soo, if that is the case then DS & ES point to DGROUP _DATA \n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\teax,[(KeyboardType PTR esi).MouseX]\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\teax,[(KeyboardType PTR esi).MouseY]\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],ax\n\n??cando:\n\tmov\teax,[keycode]\t\t; get the code\n\tor\teax,eax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[(KeyboardType PTR esi).Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[(KeyboardType PTR esi).Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\txor\tebx,ebx\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tebx,1\t\t\t; double for WORD index\n\tmov\tax,[WORD PTR ((KeyboardType PTR esi+ebx).XYAdjust)]\n\n\tmovsx\tebx,ah\n\tmovsx\teax,al\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tedx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tedx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tebx,edx\t\t\t; add speed for y index\n\tmov\tbl,[(KeyboardType PTR esi+ebx).KeyMouseMove] \t; get speed for y delta\n\tmovsx\tebx,bl\n\txchg\tebx,edx\t\t\t; save mouse y delta\n\tadd\tebx,eax\t\t\t; add speed for x index\n\tmov\tal,[(KeyboardType PTR esi+ebx).KeyMouseMove]\t; get speed for x delta\n\tmovsx\teax,al\n\txchg\tebx,edx\t\t\t; restore mouse y delta\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tebx,011b\t\t\t; Y = 1, 0, 3\n\tand\teax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tebx,011b\t\t\t; Y = 3, 0, 1\n\tand\teax,011b\t\t\t; X = 3, 0, 1\n\tshl\tebx,2\n\tor\tebx,eax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tebx,1\n\tmovzx\tebx,[(KeyboardType PTR esi+ebx).EdgeConv]\n\tshl\tebx,2\n\tmov\tax,[(KeyboardType PTR esi+ebx).ScreenEdge]\t; New absolute X\n\tmov\tbx,[(KeyboardType PTR esi+ebx+2).ScreenEdge] ; New absolute Y\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\teax,eax\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tebx,ebx\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseX],ax\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseY],bx\n\tcmp\t[(KeyboardType PTR esi).MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n; PWG: ARRGGGHHHH!\n;\tcall\tLow_Hide_Mouse\n;\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\teax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],eax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tedi,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\t[tail],edi\t\t; Safety record.\n\n\t; Record the base keycode (if there is room).\n\tcwde\t\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\teax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tmovzx\teax,[(KeyboardType esi).LocalMouseX]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tmovzx\teax,[(KeyboardType esi).LocalMouseY]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tebx,0101h\t\t; Bit control tools.\n\tmov\teax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[(KeyboardType PTR esi).KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[(KeyboardType esi).KeyBufferTail],edi\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tmov\tcl,3\n\tshr\tedi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[(KeyboardType esi+edi).KeysUpDown]\n\tje\tshort ??notalready\n\ttest\t[(KeyboardType PTR esi).KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\tedx,[tail]\n\tmov\t[(KeyboardType esi).KeyBufferTail],edx\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[(KeyboardType esi+edi).KeysUpDown],bh\t; Force key bit to zero.\n\tor\t[(KeyboardType esi+edi).KeysUpDown],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\teax,1\n\tjmp\tshort ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\teax,[tail]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\t\t\t; Signal an error.\n\n??exit:\n\tsti\n\tpopf\n\n;\tpopf\n;\tpop\tebx\n;\tor\tebx,ebx\n;\tjz\t??final_exit\n;\tsti\n\n??final_exit:\n\tret\n\n\tENDP\tStuff_Key_Num\n\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles break interrupt for protected mode           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBreak_Interrupt C NEAR\n\n\tiret\n\tENDP\tBreak_Interrupt\n\nIF DEBUG\n;***************************************************************************\n;* DEBUG_INTERRUPT -- Handles debug (INT 3) interrupt for protected mode   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tDebug_Interrupt C NEAR\n\n\t;*==================================================================\n\t;* Setup fake Interrupt entry sequence so that we can execute our\n\t;*   code and then IRET painlessly into the debuggers interrupt\n\t;*   handler.\n\t;*==================================================================\n\tpushfd\t\t\t; Step 1\n\tsub\tesp,8\t\t; Step 2\n\tpush\tebp\t\t; Step 3\n\tmov\tebp,esp\t\t; Set up a stack frame to know where to poke address.\n\n\t;*==================================================================\n\t;* Preserve all of the registers that we intend to use.\n\t;*=======================================Dbg========================\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n\tmov\tax , _DATA\n\tmov\tds , ax\n\tmov\tes , ax\n\tinc\t[BYTE PTR 0B0000h]\n\n\t;*==================================================================\n\t;* Setup the pointers to the real mode data and the protected mode\n\t;*   data and selectors.\n\t;*==================================================================\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t;*==================================================================\n\t;* Do the deed.\n\t;*==================================================================\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\n\t;*==================================================================\n\t;* Now get the address of the real debug handler and poke it into\n\t;*   the stack so we can IRET to it.\n\t;*==================================================================\n\tmov\teax,[(KeyboardType PTR esi).DbgOldPMIOffset]\t; Get orig offset.\n\tmov\tebx,[(KeyboardType PTR esi).DbgOldPMISelector]\t; Get orig selector.\n\tmov\t[ss:ebp+4],eax\t\t\t\t\t; Poke offset.\n\tmov\t[ss:ebp+8],ebx\t\t\t\t\t; Poke selector.\n\n\t;*==================================================================\n\t;* Restore the stack so it looks like we just did an IRET entry\n\t;*==================================================================\n\tpop\tfs gs es ds\n\tpopad\n\tpop\tebp\n\n\t;*==================================================================\n\t;* This iret should go directly to the real debugger handler\n\t;*\tpainlessly and effectively.\n\t;*==================================================================\n\tiretd\n\n\tENDP\tDebug_Interrupt\nENDIF\n\n\n\nIF PROT_INT_ENABLE\n\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Handles input that comes from the keyboard        *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Interrupt C NEAR\n\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n; this is the part of the interrupt that set the segment registers\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov cx, ss\t\t\t\t; get SS\n\tmov [Keyboard_App_Stack_ESP], esp\t; Protect ESP\n\tmov [Keyboard_App_Stack_SS], ecx\t; Protect SS\n\tlea edx, [Keyboard_StackStart ]\t; Compute Local Stack size\n\tand edx, -4 ;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov esp, edx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\t\n\tmov\tedx,[(KeyboardType PTR esi).KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[(KeyboardType PTR esi).KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\ttest\t[BYTE PTR 417H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR 417H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR 496H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tebx,0101H\t\t; set key to a make by default \n\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\t;\n\t; New CODE to montior key stream\n\t;\n\txor\tebx,ebx\n\tmov\tbx,[(KeyboardType PTR esi).KeyStreamIndex]\n\tmov\t[(KeyboardType PTR esi+ebx).KeyStream],al\n\tinc\tebx\n\tand\tebx,15\n\tmov\t[(KeyboardType PTR esi).KeyStreamIndex],bx\n\tmov\tebx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[(KeyboardType PTR esi).LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[(KeyboardType PTR esi).LastKeyE1]\t\t; yes, dec the count\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[(KeyboardType PTR esi).IsExtKey],TRUE\t; it is an extended key\n\n\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtCodes\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).ExtNums-OFFSET (KeyboardType PTR 0).ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\n\tmov\tal,[(OFFSET (KeyboardType PTR 0).ExtNums - OFFSET (KeyboardType PTR 0).ExtCodes) - 1 + edi] ; get the match\n\tmov\t[(KeyboardType PTR esi).IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tedi,eax\t\t\t; use code as an index\n\tand\tedi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[(KeyboardType PTR esi+edi).KeyNums]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[(KeyboardType PTR esi).ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\teax\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\n;------\tSet the shift bit if necessary.\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tshr\tedi,3\n\tmov\tebx,eax\n\tand\tebx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[(KeyboardType PTR esi+ebx).Bits]\t\t; get the bit to test\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[(KeyboardType PTR esi).CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\n\t\t\t\t\t; keyboard buffer.\n\n\tmov\tecx,eax\n\txor\teax,eax\n\tmov\tax,cx\n\n\ttest\tedx,DEBUGINT\n\tjz\t??not_toggle\n\n\tcmp\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\n\tinc\t[BYTE PTR 0B0002h]\n\n\tcmp\teax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\teax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\teax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\t\n\tcmp\teax,125\n\tjne\t??not_toggle\n\n\tinc\t[BYTE PTR 0B0000h]\n\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjmp\t??absorbcode\n\n??not_toggle:\n\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\teax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\teax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\teax,0230h\n\tje\tshort ??breaker\n\tcmp\teax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[(KeyboardType PTR esi).Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n;\tcmp\tax,0420H\t\t; is this an alt s\n;\tjne\tshort ??checkmusic\t; toggle the Sound variable\n;\tpush\tax\n;\tmov\tax,[SoundOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??checkmusic:\n;\tcmp\tax,0434H\t\t; is this an alt m\n;\tjne\tshort ??esc\t\t; toggle the Music variable\n;\tpush\tax\n;\tmov\tax,[MusicOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??esc:\n\n\tpush\teax\n\tcall\tStuff_Key_Num\n\tpop\teax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[(KeyboardType PTR esi).EscRoutine],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\teax\n\tcall\t[(KeyboardType PTR esi).EscRoutine]\n\tpop\teax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tedi,OFFSET (KeyboardType PTR 0).PassAlways\t; get offset to table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd - OFFSET (KeyboardType PTR 0).PassAlways) ; get number of pass always CDY JLB MOD 7/11 was \n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tedi,OFFSET (KeyboardType PTR 0).CondPassKey\t; get offset to cond key table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).CondPassCond-OFFSET (KeyboardType PTR 0).CondPassKey) ; get number of entries\n\tshr\tecx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(OFFSET (KeyboardType PTR 0).CondPassCond - OFFSET (KeyboardType PTR 0).CondPassKey) - 2 + edi]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tedx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\tinc\t[(KeyboardType PTR esi).PassCount]\n\tmov\t[(KeyboardType PTR esi).PMIssuedKeyInt],1     ; Make it TRUE\n\n\t; Now it is time to set up for the call to the System Keyboard\n\t; interrupt handler.\n\t; 1 -Restore System Stack Pointer Selector before exit Interrupt\n\t; 2- We Create a Returning Point from Interrupt by Push A\n \t;    Interupt Stack Frame into the Stack Pointer\n\t; 3- We make a Far jump to the interuupt handler\n\n\tcmp  [Keyboard_StackPointer],0DEADDEADh\n\tje   ??pass_stack_good\n\n\tmov  [BYTE PTR 0B0000h],'*'\n\n??pass_stack_good:\n\tcli\t\t\t\t       ; disable Interrupts\n\tmov edx, [Keyboard_App_Stack_SS]       \n\tmov ss, dx\t\t\t       ; Set System Stack Selector\n\tmov esp, [Keyboard_App_Stack_ESP]      ; Set System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n\tlea\tedx, [??Call_Back_Keyboard]   ; Get Return address offset\n \tpushfd\t\t\t\t      ; push flags\t\n\tpush\tcs\t\t\t      ; push Code Selector\n\tpush\tedx\t\t\t      ; push Offset\n\n\t; Now we need to simulate an interrup call by using ired\n\t; because we still want to come back here from the\n\t; Old Keyboard interrupt handle.\n\tpushfd\n\tpush\t[(KeyboardType PTR esi).KeyOldPMISelector] ; push orig selector.\n\tpush    [(KeyboardType PTR esi).KeyOldPMIOffset]   ; push orig offset.\n\tiretd\n\n??absorbcode:\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tal,[496h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[496h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\n\tcmp  [Keyboard_StackPointer],0DEADDEADh\n\tje   ??call_stack_good\n\tmov  [BYTE PTR 0B0000h],'*'\n\n??call_stack_good:\n\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov edx, [Keyboard_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, dx\t\t\t       ; Set System Stack Selector\n\tmov esp, [Keyboard_App_Stack_ESP]      ; Set System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n??Call_Back_Keyboard:\n\tpop\tfs gs es ds\n\tpopad\n\tiret\t\n\n\tENDP\tKeyboard_Interrupt\n\nELSE\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Stub for the keyboard interrupt call real mode    *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\n \nDATASEG\nSTRUC\tRealModeCallStruc\n\t_EDI  DD\t0\n\t_ESI  DD\t0\n\t_EBP  DD\t0\n\t      DD        0\n\t_EBX  DD\t0\n\t_EDX  DD\t0\n\t_ECX  DD\t0\n\t_EAX  DD        0\n\tFLAGS DW\t0\n\t_ES   DW\t0\n\t_DS   DW\t0\n\t_FS   DW\t0\n\t_GS   DW\t0\n\t_IP   DW\t0\n\t_CS   DW\t0\n\t_SP   DW\t0\n\t_SS   DW\t0\n\t      dd\t0\n\t      dd\t0\n  nothing     dd\t0\t\nENDS \n\nRMDS RealModeCallStruc  <>\n\nCODESEG\n\nPROC\tKeyboard_Interrupt\tNear\n\n; This option of the keyboard interrupt handle will not be\n; available at this moment because the light version of Rational System DOS\n; Extender do not allow a DPMI real mode call which is\n; DMPI INT 31h funtion 0301h\n\n\tpushad\t\n\tpush\tfs gs es ds\n\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\n\tlea\tedi , [ RMDS ]\n\tlea\tecx , [ RMDS . nothing ]\n\tsub\tecx , edi\n\txor\teax , eax\n\tshr\tecx , 2\n\trep\tstosd\n\t\n\tmov\teax , 0300h\n\tmov\tbl , [ byte ptr RMVector ]\n\txor\tbh , bh\n\txor\tcx , cx\n\tlea\tedi , [RMDS]\n\tint\tDPMI_INTR\n\n; this is here only for testing to make sure\n; that a real mode interrupt is bieng issued. \nmov\tax , _DATA\nmov\tes , ax\nmov\tds , ax\nmov [ byte ptr 0b0000h + 10 * 80 + 40 ] , 040h\njc\t??error\nmov [ byte ptr 0b0000h + 10 * 80 + 42 ] , 041h\n\n??error:\n\tpop\tds es gs fs\n\tpopad\t\n\tiretd\n\tENDP\n\nENDIF\n\nLABEL \tLockedCodeEnd\t\tBYTE\n\n;***************************************************************************\n;* End of File.\t\t\t\t\t\t\t\t   *\n;***************************************************************************\nEND\n\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/NEW/KEYBOARD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : KEYBOARD.H                               *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : July 13, 1994                            *\n *                                                                         *\n *                  Last Update : July 13, 1994   [PWG]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef KEYBOARD_H\n#define KEYBOARD_H\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n\nextern \"C\" {\n\tvoid Install_Keyboard_Interrupt(void *addr, long size);\n\tvoid Install_Page_Fault_Handle(void) ;\n\tvoid\t*Get_RM_Keyboard_Address(void);\n\tlong\tGet_RM_Keyboard_Size(void);\n\tvoid\tRemove_Keyboard_Interrupt(void);\n\tint\tCheck_Key_Num(void);\n\tint\tCheck_Key_Bits(void);\n\tint\tCheck_Key(void);\n\tshort\tGet_Key_Num(void);\n\tshort\tGet_Key_Bits(void);\n\tint\tGet_Key(void);\n\tint\tKN_To_KA(int keynum);\n\tint\tKeyboard_Attributes_On(int key_flags);\n\tint\tKeyboard_Attributes_Off(int key_flags);\n\tvoid\tClear_KeyBuffer(void);\n\tint\tKey_Down(int key);\n\tint\tKey_Satisfied(int key);\n\tvoid\tStuff_Key_WORD(int code);\n\tvoid\tStuff_Key_Num(int key);\n\tint   Install_Mouse(int max_width, int max_height, int scr_width, int scr_height);\n\tvoid\tReset_Mouse (void) ;\n\tvoid\tRemove_Mouse(void);\n\tint\tGet_Mouse_State(void);\n\tint\tGet_Mouse_X(void);\n\tint\tGet_Mouse_Y(void);\n\tint\tGet_Mouse_Disabled(void);\n\tvoid  *Set_Mouse_Cursor(int xhotspot,\tint yhotspot,\tvoid *cursor);\n\tvoid\tHide_Mouse(void);\n\tvoid\tShow_Mouse(void);\n\tvoid\tConditional_Hide_Mouse(int sx_pixel, int sy_pixel, int dx_pixel, int dy_pixel);\n\tvoid\tConditional_Show_Mouse(void);\n\n\n\tvoid  __interrupt far Keyboard_Interrupt(void);\n\textern int MouseQX;\n\textern int MouseQY;\n\n}\n\n\nenum {\n\tREPEATON     = 0x0001,\t/* 1:all makes into buffer, 0:only 1st make */\n\tTRACKEXT     = 0x0002,\t/* 1:Home != keypad Home, 0:Home=keypad Home */\n\tFILTERONLY   = 0x0004,\t/* 1:Normal BIOS operation with filter */\n\tCTRLALTTURBO = 0x0010,\t/* 1:Allow turbo up and down in application */\n\tNONUMLOCK    = 0x0200,\t/* 1:do NOT remap keypad to numbers */\n\tTASKSWITCHABLE = 0x400, /* 1:allows task switching keys thru ALT-TAB, */\n\t\t\t\t\t\t\t\t\t/*   ALT-ESC,CTRL-ESC */\n\tPASSBREAKS\t = 0x0800,\t// Pass all breaks to the keyboard buffer.\n\n\t/* The following flags, if turned on, should only be used for\n\t   debugging purposes (remember to take out the calls when BETA */\n\n\tCTRLSON      = 0x0008,\t/* 1:pass scroll lock sequence into BIOS */\n\tCTRLCON      = 0x0020,\t/* 1:pass stop code to BIOS */\n\tSCROLLLOCKON = 0x0040,\t/* 1:pass scroll lock key into BIOS */\n\tPAUSEON      = 0x0080,\t/* 1:pass the pause key and seq to BIOS */\n\t\t\t\t\t\t\t\t\t/*   make sure FILTERONLY is set */\n\tBREAKON      = 0x0100,\t/* 1:pass the ctrl break seq to BIOS */\n\tKEYMOUSE     = 0x1000,\t/* 1:keypad translates into mouse moves */\n\tSIMLBUTTON   = 0x2000,\t/* 1:have space and enter keys simulate Left */\n\t\t\t\t\t\t\t\t\t/*   mouse button when KEYMOUSE is set */\n\tDEBUGINT\t\t = 0x4000\t/* Use scroll lock to disable keyboard int */\n};\n\n\n/*\n**\tThese are the codes for the various key codes that are returned from the\n**\tkeyboard input routines Get_Key() and Input_ASCII().\n*/\ntypedef enum {\n\tKA_CTRL_AT = 0,\n\tKA_CTRL_A,\n\tKA_MORE = KA_CTRL_A,\n\tKA_CTRL_B,\n\tKA_SETBKGDCOL = KA_CTRL_B,\n\tKA_CTRL_C,\n\tKA_CTRL_D,\n\tKA_CTRL_E,\n\tKA_CTRL_F,\n\tKA_SETFORECOL = KA_CTRL_F,\n\tKA_CTRL_G,\n\tKA_CTRL_H,\n\tKA_BACKSPACE = KA_CTRL_H,\n\tKA_CTRL_I,\n\tKA_TAB = KA_CTRL_I,\n\tKA_CTRL_J,\n\tKA_CTRL_K,\n\tKA_CTRL_L,\n\tKA_FORMFEED = KA_CTRL_L,\n\tKA_CTRL_M,\n\tKA_RETURN = KA_CTRL_M,\n\tKA_CTRL_N,\n\n\tKA_CTRL_O,\n\tKA_CTRL_P,\n\tKA_CTRL_Q,\n\tKA_CTRL_R,\n\tKA_CTRL_S,\n\tKA_SPCTAB = KA_CTRL_S,\n\tKA_CTRL_T,\n\tKA_CTRL_U,\n\tKA_CTRL_V,\n\tKA_CTRL_W,\n\tKA_CTRL_X,\n\tKA_SETX = KA_CTRL_X,\n\tKA_CTRL_Y,\n\tKA_SETY = KA_CTRL_Y,\n\tKA_CTRL_Z,\n\tKA_CTRL_LBRACKET,\n\tKA_ESC = KA_CTRL_LBRACKET,\n\tKA_EXTEND = KA_ESC,\n\tKA_CTRL_BACKSLASH,\n\tKA_CTRL_RBRACKET,\n\tKA_LITERAL = KA_CTRL_RBRACKET,\n\tKA_CTRL_CARROT,\n\tKA_CTRL_UNDERLINE,\n\n\tKA_SPACE,\t\t\t\t\t\t\t\t\t/*   */\n\tKA_EXCLAMATION,\t\t\t\t\t\t\t/* ! */\n\tKA_DQUOTE,\t\t\t\t\t\t\t\t\t/* \" */\n\tKA_POUND,\t\t\t\t\t\t\t\t\t/* # */\n\tKA_DOLLAR,\t\t\t\t\t\t\t\t\t/* $ */\n\tKA_PERCENT,\t\t\t\t\t\t\t\t\t/* % */\n\tKA_AMPER,\t\t\t\t\t\t\t\t\t/* & */\n\tKA_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKA_LPAREN,\t\t\t\t\t\t\t\t\t/* ( */\n\tKA_RPAREN,\t\t\t\t\t\t\t\t\t/* ) */\n\tKA_ASTERISK,\t\t\t\t\t\t\t\t/* * */\n\tKA_PLUS,\t\t\t\t\t\t\t\t\t\t/* + */\n\tKA_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKA_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKA_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKA_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKA_0, KA_1, KA_2, KA_3, KA_4, KA_5, KA_6, KA_7, KA_8, KA_9,\n\tKA_COLON,\t\t\t\t\t\t\t\t\t/* : */\n\tKA_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKA_LESS_THAN,\t\t\t\t\t\t\t\t/* < */\n\tKA_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\tKA_GREATER_THAN,\t\t\t\t\t\t\t/* > */\n\tKA_QUESTION,\t\t\t\t\t\t\t\t/* ? */\n\n\tKA_AT,\t\t\t\t\t\t\t\t\t\t/* @ */\n\tKA_A,\t\t\t\t\t\t\t\t\t\t\t/* A */\n\tKA_B,\t\t\t\t\t\t\t\t\t\t\t/* B */\n\tKA_C,\t\t\t\t\t\t\t\t\t\t\t/* C */\n\tKA_D,\t\t\t\t\t\t\t\t\t\t\t/* D */\n\tKA_E,\t\t\t\t\t\t\t\t\t\t\t/* E */\n\tKA_F,\t\t\t\t\t\t\t\t\t\t\t/* F */\n\tKA_G,\t\t\t\t\t\t\t\t\t\t\t/* G */\n\tKA_H,\t\t\t\t\t\t\t\t\t\t\t/* H */\n\tKA_I,\t\t\t\t\t\t\t\t\t\t\t/* I */\n\tKA_J,\t\t\t\t\t\t\t\t\t\t\t/* J */\n\tKA_K,\t\t\t\t\t\t\t\t\t\t\t/* K */\n\tKA_L,\t\t\t\t\t\t\t\t\t\t\t/* L */\n\tKA_M,\t\t\t\t\t\t\t\t\t\t\t/* M */\n\tKA_N,\t\t\t\t\t\t\t\t\t\t\t/* N */\n\tKA_O,\t\t\t\t\t\t\t\t\t\t\t/* O */\n\n\tKA_P,\t\t\t\t\t\t\t\t\t\t\t/* P */\n\tKA_Q,\t\t\t\t\t\t\t\t\t\t\t/* Q */\n\tKA_R,\t\t\t\t\t\t\t\t\t\t\t/* R */\n\tKA_S,\t\t\t\t\t\t\t\t\t\t\t/* S */\n\tKA_T,\t\t\t\t\t\t\t\t\t\t\t/* T */\n\tKA_U,\t\t\t\t\t\t\t\t\t\t\t/* U */\n\tKA_V,\t\t\t\t\t\t\t\t\t\t\t/* V */\n\tKA_W,\t\t\t\t\t\t\t\t\t\t\t/* W */\n\tKA_X,\t\t\t\t\t\t\t\t\t\t\t/* X */\n\tKA_Y,\t\t\t\t\t\t\t\t\t\t\t/* Y */\n\tKA_Z,\t\t\t\t\t\t\t\t\t\t\t/* Z */\n\tKA_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKA_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\tKA_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKA_CARROT,\t\t\t\t\t\t\t\t\t/* ^ */\n\tKA_UNDERLINE,\t\t\t\t\t\t\t\t/* _ */\n\n\tKA_GRAVE,\t\t\t\t\t\t\t\t\t/* ` */\n\tKA_a,\t\t\t\t\t\t\t\t\t\t\t/* a */\n\tKA_b,\t\t\t\t\t\t\t\t\t\t\t/* b */\n\tKA_c,\t\t\t\t\t\t\t\t\t\t\t/* c */\n\tKA_d,\t\t\t\t\t\t\t\t\t\t\t/* d */\n\tKA_e,\t\t\t\t\t\t\t\t\t\t\t/* e */\n\tKA_f,\t\t\t\t\t\t\t\t\t\t\t/* f */\n\tKA_g,\t\t\t\t\t\t\t\t\t\t\t/* g */\n\tKA_h,\t\t\t\t\t\t\t\t\t\t\t/* h */\n\tKA_i,\t\t\t\t\t\t\t\t\t\t\t/* i */\n\tKA_j,\t\t\t\t\t\t\t\t\t\t\t/* j */\n\tKA_k,\t\t\t\t\t\t\t\t\t\t\t/* k */\n\tKA_l,\t\t\t\t\t\t\t\t\t\t\t/* l */\n\tKA_m,\t\t\t\t\t\t\t\t\t\t\t/* m */\n\tKA_n,\t\t\t\t\t\t\t\t\t\t\t/* n */\n\tKA_o,\t\t\t\t\t\t\t\t\t\t\t/* o */\n\n\tKA_p,\t\t\t\t\t\t\t\t\t\t\t/* p */\n\tKA_q,\t\t\t\t\t\t\t\t\t\t\t/* q */\n\tKA_r,\t\t\t\t\t\t\t\t\t\t\t/* r */\n\tKA_s,\t\t\t\t\t\t\t\t\t\t\t/* s */\n\tKA_t,\t\t\t\t\t\t\t\t\t\t\t/* t */\n\tKA_u,\t\t\t\t\t\t\t\t\t\t\t/* u */\n\tKA_v,\t\t\t\t\t\t\t\t\t\t\t/* v */\n\tKA_w,\t\t\t\t\t\t\t\t\t\t\t/* w */\n\tKA_x,\t\t\t\t\t\t\t\t\t\t\t/* x */\n\tKA_y,\t\t\t\t\t\t\t\t\t\t\t/* y */\n\tKA_z,\t\t\t\t\t\t\t\t\t\t\t/* z */\n\tKA_LBRACE,\t\t\t\t\t\t\t\t\t/* { */\n\tKA_BAR,\t\t\t\t\t\t\t\t\t\t/* | */\n\tKA_RBRACE,\t\t\t\t\t\t\t\t\t/* ] */\n\tKA_TILDA,\t\t\t\t\t\t\t\t\t/* ~ */\n\tKA_DEL,\t\t\t\t\t\t\t\t\t\t/* not used */\n\n\tKA_ALT_F10 = 143,\n\tKA_ALT_F9,    KA_ALT_F8,   KA_ALT_F7,   KA_ALT_F6,   KA_ALT_F5,\n\tKA_ALT_F4,    KA_ALT_F3,   KA_ALT_F2,   KA_ALT_F1,\n\n\tKA_CTRL_F10,  KA_CTRL_F9,  KA_CTRL_F8,  KA_CTRL_F7,  KA_CTRL_F6,\n\tKA_CTRL_F5,   KA_CTRL_F4,  KA_CTRL_F3,  KA_CTRL_F2,  KA_CTRL_F1,\n\n\tKA_SHIFT_F10, KA_SHIFT_F9, KA_SHIFT_F8, KA_SHIFT_F7, KA_SHIFT_F6,\n\tKA_SHIFT_F5,  KA_SHIFT_F4, KA_SHIFT_F3, KA_SHIFT_F2, KA_SHIFT_F1,\n\n\tKA_DELETE,\t\t\t\t\t\t\t\t\t/* <DELETE> */\n\tKA_INSERT,\t\t\t\t\t\t\t\t\t/* <INSERT> */\n\tKA_PGDN,\t\t\t\t\t\t\t\t\t\t/* <PAGE DOWN> */\n\tKA_DOWNRIGHT = KA_PGDN,\n\tKA_DOWN,\t\t\t\t\t\t\t\t\t\t/* <DOWN ARROW> */\n\tKA_END,\t\t\t\t\t\t\t\t\t\t/* <END> */\n\tKA_DOWNLEFT = KA_END,\n\n\tKA_RESERVED1,\n\n\tKA_RIGHT,\t\t\t\t\t\t\t\t\t/* <RIGHT ARROW> */\n\tKA_KEYPAD5,\t\t\t\t\t\t\t\t\t/* NUMERIC KEY PAD <5> */\n\tKA_LEFT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ARROW> */\n\n\tKA_RESERVED2,\n\n\tKA_PGUP,\t\t\t\t\t\t\t\t\t\t/* <PAGE UP> */\n\tKA_UPRIGHT = KA_PGUP,\n\tKA_UP,\t\t\t\t\t\t\t\t\t\t/* <UP ARROW> */\n\tKA_HOME,\t\t\t\t\t\t\t\t\t\t/* <HOME> */\n\tKA_UPLEFT = KA_HOME,\n\t\n\tKA_RESERVED3,\n\tKA_RESERVED4,\n\n\tKA_F10, KA_F9, KA_F8, KA_F7, KA_F6, KA_F5, KA_F4, KA_F3, KA_F2, KA_F1,\n\n\tKA_LMOUSE,\n\tKA_RMOUSE,\n\tKA_JBUTTON1,\n\tKA_JBUTTON2,\n\tKA_J_UP,\n\tKA_J_RIGHT,\n\tKA_J_DOWN,\n\tKA_J_LEFT,\n\n\tKA_SHIFT_BIT = 0x0100,\n\tKA_CTRL_BIT  = 0x0200,\n\tKA_ALT_BIT   = 0x0400,\n\tKA_RLSE_BIT  = 0x0800,\n\tKA_LCOMM_BIT = 0x1000,\t\t\t\t\t/* Amiga Left Comm key\t*/\n\tKA_RCOMM_BIT = 0x2000\t\t\t\t\t/* Amiga Right Comm key\t*/\n} KeyASCIIType;\n\n/*\n**\tThese are the keyboard codes that are returned from the input routines\n**\tGet_Key_Num and Input_Num.\n*/\ntypedef enum {\n\tKN_NONE = 0,\n\tKN_GRAVE = 1,\t\t\t\t\t\t\t\t/* ` */\n\tKN_1, KN_2, KN_3, KN_4, KN_5, KN_6, KN_7, KN_8, KN_9, KN_0,\n\tKN_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKN_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\n\tKN_RESERVED1,\n\n\tKN_BACKSPACE,\t\t\t\t\t\t\t\t/* <BACKSPACE> */\n\n\tKN_TAB,\t\t\t\t\t\t\t\t\t\t/* <TAB> */\n\tKN_Q, KN_W, KN_E, KN_R, KN_T, KN_Y, KN_U, KN_I, KN_O, KN_P,\n\tKN_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKN_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKN_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\n\tKN_CAPSLOCK,\t\t\t\t\t\t\t\t/* <CAPS LOCK> */\n\tKN_A, KN_S, KN_D, KN_F, KN_G, KN_H, KN_J, KN_K, KN_L,\n\tKN_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKN_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKN_BACKSLASH2,\n\tKN_RETURN,\t\t\t\t\t\t\t\t\t/* <RETURN> or <ENTER> */\n\n\tKN_LSHIFT,\t\t\t\t\t\t\t\t\t/* <LEFT SHIFT> */\n\n\tKN_MOUSE_MOVE,\t\t\t\t\t\t\t\t// Indicate a mouse move (for playback of\n\n\tKN_Z, KN_X, KN_C, KN_V, KN_B, KN_N, KN_M,\n\tKN_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKN_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKN_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKN_RESERVED3,\n\n\tKN_RSHIFT,\t\t\t\t\t\t\t\t\t/* <RIGHT SHIFT> */\n\n\tKN_LCTRL,\t\t\t\t\t\t\t\t\t/* <LEFT CTRL> */\n\tKN_LCOMM,\t\t\t\t\t\t\t\t\t/* for AMIGA */\n\tKN_LALT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ALT> */\n\tKN_SPACE,\t\t\t\t\t\t\t\t\t/* <SPACE BAR> */\n\tKN_RALT,\t\t\t\t\t\t\t\t\t\t/* <RIGHT ALT> */\n\tKN_RCOMM,\t\t\t\t\t\t\t\t\t/* for AMIGA */\n\tKN_RCTRL,\t\t\t\t\t\t\t\t\t/* <RIGHT CTRL> */\n\t\t\t\t\t\t\t/* the following are forced into key buffer */\n\tKN_LMOUSE,\n\tKN_RMOUSE,\n\tKN_JBUTTON1,\n\tKN_JBUTTON2,\n\tKN_J_UP,\n\tKN_J_RIGHT,\n\tKN_J_DOWN,\n\tKN_J_LEFT,\n\n\tKN_SPECIAL9,\n\n\tKN_SPECIAL10,\n\n\tKN_E_INSERT,\t\t\t\t\t\t\t\t/* extended <INSERT> */\n\tKN_E_DELETE,\t\t\t\t\t\t\t\t/* extended <DELETE> */\n\n\tKN_RESERVED4,\n\tKN_RESERVED5,\n\n\tKN_E_LEFT,\t\t\t\t\t\t\t\t\t/* extended <LEFT ARROW> */\n\tKN_E_HOME,\t\t\t\t\t\t\t\t\t/* extended <HOME> */\n\tKN_E_END,\t\t\t\t\t\t\t\t\t/* extended <END> */\n\n\tKN_RESERVED6,\n\n\tKN_E_UP,\t\t\t\t\t\t\t\t\t\t/* extended <UP ARROW> */\n\tKN_E_DOWN,\t\t\t\t\t\t\t\t\t/* extended <DOWN ARROW> */\n\tKN_E_PGUP,\t\t\t\t\t\t\t\t\t/* extended <PAGE UP> */\n\tKN_E_PGDN,\t\t\t\t\t\t\t\t\t/* extended <PAGE DOWN> */\n\tKN_K_LPAREN,\t\t\t/* for AMIGA */\n\tKN_K_RPAREN,\t\t\t/* for AMIGA */\n\tKN_E_RIGHT,\t\t\t\t\t\t\t\t\t/* extended <RIGHT ARROW> */\n\n\tKN_NUMLOCK,\t\t\t\t\t\t\t\t\t/* <NUM LOCK> */\n\tKN_HOME,\t\t\t\t\t\t\t\t\t\t/* num key pad 7 */\n\tKN_UPLEFT = KN_HOME,\n\tKN_LEFT,\t\t\t\t\t\t\t\t\t\t/* num key pad 4 */\n\tKN_END,\t\t\t\t\t\t\t\t\t\t/* num key pad 1 */\n\tKN_DOWNLEFT = KN_END,\n\n\tKN_RESERVED7,\n\n\tKN_KEYPAD_SLASH,\t\t\t\t\t\t\t/* num key pad / */\n\tKN_UP,\t\t\t\t\t\t\t\t\t\t/* num key pad 8 */\n\tKN_CENTER,\t\t\t\t\t\t\t\t\t/* num key pad 5 */\n\tKN_DOWN,\t\t\t\t\t\t\t\t\t\t/* num key pad 2 */\n\tKN_INSERT,\t\t\t\t\t\t\t\t\t/* num key pad 0 */\n\tKN_KEYPAD_ASTERISK,\t\t\t\t\t\t/* num key pad * */\n\tKN_PGUP,\t\t\t\t\t\t\t\t\t\t/* num key pad 9 */\n\tKN_UPRIGHT = KN_PGUP,\n\tKN_RIGHT,\t\t\t\t\t\t\t\t\t/* num key pad 6 */\n\tKN_PGDN,\t\t\t\t\t\t\t\t\t\t/* num key pad 3 */\n\tKN_DOWNRIGHT = KN_PGDN,\n\tKN_DELETE,\t\t\t\t\t\t\t\t\t/* num key pad . */\n\tKN_KEYPAD_MINUS,\t\t\t\t\t\t\t/* num key pad - */\n\tKN_KEYPAD_PLUS,\t\t\t\t\t\t\t/* num key pad + */\n\n\tKN_RESERVED8,\n\n\tKN_KEYPAD_RETURN,\t\t\t\t\t\t\t/* num key pad <ENTER> */\n\n\tKN_RESERVED9,\n\n\tKN_ESC,\n\tKN_HELP,\t\t\t\t\t\t\t\t\t\t/* for AMIGA */\n\tKN_F1, KN_F2, KN_F3, KN_F4, KN_F5, KN_F6, KN_F7, KN_F8, KN_F9, KN_F10,\n\tKN_F11,\n\tKN_F12,\n\tKN_PRNTSCRN,\t\t\t\t\t\t\t\t/* <PRINT SCRN> */\n\tKN_SCROLLLOCK,\t\t\t\t\t\t\t\t/* <SCROLL LOCK> */\n\tKN_PAUSE,\t\t\t\t\t\t\t\t\t/* <PAUSE> */\n\n\tKN_SHIFT_BIT = 0x0100,\n\tKN_CTRL_BIT  = 0x0200,\n\tKN_ALT_BIT   = 0x0400,\n\tKN_RLSE_BIT  = 0x0800,\n\tKN_LCOMM_BIT = 0x1000,\t\t\t\t\t/* Amiga Left Comm key\t*/\n\tKN_RCOMM_BIT = 0x2000,\t\t\t\t\t/* Amiga Right Comm key\t*/\n\tKN_BUTTON    = 0x8000\t\t\t\t\t/* Amiga Right Comm key\t*/\n} KeyNumType;\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/NEW/KEYBOARD.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : KEYBOARD.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 12, 1994                            *\n;*                                                                         *\n;*                  Last Update : July 12, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Contains all the defines used by the keyboard interrupt for assembly    *\n;*   includes.                                                             *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nTRUE\t\tEQU\t1\t\t\t; numerical true\nFALSE\t\tEQU\t0\t\t\t; numerical false\nDEBUG\t\tEQU\t1\n\nMAX_X_PIXEL\t\tEQU\t319\nMAX_Y_PIXEL\t\tEQU\t199\n\n\nKN_RESERVED1\t\tEQU\t14\nKN_RESERVED2\t\tEQU\t45\nKN_RESERVED3\t\tEQU\t56\n\n\n; these two are reserved for AMIGA open and close.\nKN_LCOMM\t\tEQU\t59\nKN_RCOMM\t\tEQU\t63\n\nKN_LMOUSE\t\tEQU\t65\nKN_RMOUSE\t\tEQU\t66\nKN_JBUTTON1\t\tEQU\t67\nKN_JBUTTON2\t\tEQU\t68\nKN_J_UP\t\t\tEQU\t69\nKN_J_RIGHT\t\tEQU\t70\nKN_J_DOWN\t\tEQU\t71\nKN_J_LEFT\t\tEQU\t72\n\nKN_LEFT\t\t\tEQU\t92\nKN_UPLEFT\t\tEQU\t91\nKN_UP\t\t\tEQU\t96\nKN_UPRIGHT\t\tEQU\t101\nKN_RIGHT\t\tEQU\t102\nKN_DOWNRIGHT\t\tEQU\t103\nKN_DOWN\t\t\tEQU\t98\nKN_DOWNLEFT\t\tEQU\t93\nKN_CENTER\t\tEQU\t97\n\nKN_INSERT\t\tEQU\t99\nKN_DELETE\t\tEQU\t104\n\nKN_RETURN\t\tEQU\t43\nKN_SPACE\t\tEQU\t61\nKN_KEYPAD_RETURN\tEQU\t108\n\n\n; these two are reserved for AMIGA K left and right paren\nKN_KLPAREN\t\tEQU\t87\nKN_KRPAREN\t\tEQU\t88\n\n\nKN_NUMLOCK\t\tEQU\t90\n\nKN_SCROLLOCK\t\tEQU\t125\t\t; key ignored by the logging system\n\nKN_MOUSE_MOVE\tEQU\t45\t; Indicate a mouse move (for playback of logged data)\n\n; ----------------------------------------------------------------\n; flags used in Keyflags to customize keystroke interrupt.\n\nREPEATON\tEQU\t0001H\t; 1:all makes into buffer, 0:only 1st make\nTRACKEXT\tEQU\t0002H\t; 1:Home != keypad Home, 0:Home=keypad Home\nFILTERONLY\tEQU\t0004H\t; 1:Normal BIOS operation with filter\nCTRLSON\t\tEQU\t0008H\t; 1:pass scroll lock sequence into BIOS\nCTRLALTTURBO\tEQU\t0010H\t; 1:Allow turbo up and down in application\nCTRLCON\t\tEQU\t0020H\t; 1:pass stop code to BIOS\nSCROLLLOCKON\tEQU\t0040H\t; 1:pass scroll lock key into BIOS\nPAUSEON\t\tEQU\t0080H\t; 1:pass the pause key and seq to BIOS\nBREAKON\t\tEQU\t0100H\t; 1:pass the ctrl break seq to BIOS\nNONUMLOCK\tEQU\t0200H\t; 1:do NOT remap keypad to numbers\nTASKSWITCHABLE\tEQU\t0400H\t; 1:allows task switching keys thru ALT-TAB,\n\t\t\t\t;   ALT-ESC,CTRL-ESC\nPASSBREAKS\tEQU\t0800H\t; 1:Pass all break codes to keyboard buffer.\nKEYMOUSE\tEQU\t1000H\t; 1:Numeric keypad moves mouse\nSIMLBUTTON\tEQU\t2000H\t; 1:have space and enter keys simulate Left\nDEBUGINT\tEQU\t4000H\t;   mouse button when KEYMOUSE is set\n\n\nSHIFTPRESS\tEQU\t001H\t; bit 0 for shift key pressed\nCTRLPRESS\tEQU\t002H\t; bit 1 for ctrl key pressed\nALTPRESS\tEQU\t004H\t; bit 2 for alt key pressed\nKEYRELEASE\tEQU\t008H\t; bit 3 for key released\nNOTKEYRELEASE\tEQU\t0F7H\t; not of key released\n\nCAPSLOCK\tEQU\t00001H\t; bit 0 for caps locked\nNUMLOCK\tEQU\t00002H\t; bit 1 for num locked\n\n\n\nCLEARISR\tEQU\t020H\t; value to clear In Service Register\nDOS\t\tEQU \t021H\nINTCHIP0\tEQU\t020H\t; 8259 interrupt chip controller 0\nKEYCTRL\t\tEQU\t061H\t; control bits for KB sense data\nKEYDATA\t\tEQU\t060H\t; keyboard scan code port\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/NEW/KEYIPROT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : KEYINTR.ASM                              *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   KeyNum_Translate -- Translates the given keynum to ???                *\n;*   Install_Interrupt -- Installs the keyboard interrupt                  *\n;*   Stuff_Key_Word -- Stuffs a word of data into keyboard buffer          *\n;*   Stuff_Key_Num -- Stuffs a key num code into the circular buffer       *\n;*   Remove_Interrupt -- Removes the keyboard interrupt and restores the chai*\n;*   Keystroke_Interrupt -- Handles input that comes from the keyboard     *\n;*   Break_Interrupt -- Handles the break key interrupt                    *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tKeyboard driver -- 8086 Assembly portion;\t\t\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   *\n;***************************************************************************\n\n;---------------------------------------------------------------------------\n; Set the assembly directives\n;---------------------------------------------------------------------------\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386N\t\t\t\t; use 386 real mode instructions\nMODEL TINY\t\t\t; code must be tiny so it fits\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keyboard.inc\"\n\nCODESEG\n\n\nSoundOn\t\tDW\t1\t; toggled by alt S\nMusicOn\t\tDW\t1\t; toggled by alt M\nKeyFlags\tDW\tREPEATON+CTRLALTTURBO\t; all but repeat for now\n\n\nBreak\t\tDW\t0\n\nKeyMouseMove\tDB\t-1,0,1\n\t\tDB\t-16,0,16\n\nScreenEdge\tDW\t320/2,0\t\t; North\n\t\tDW\t319,0\t\t; North-East\n\t\tDW\t319,138/2\t; East\n\t\tDW\t319,137\t\t; South-East\n\t\tDW\t320/2,137\t; South\n\t\tDW\t0,137\t\t; South-West\n\t\tDW\t0,138/2\t\t; West\n\t\tDW\t0,0\t\t; North-West\n\t\tDW\t320/2,138/2\t; Center\n\n\nBits\t\tDB\t01H,02H,04H,08H,10H,20H,40H,80H\n\nCondPassKey\tDW\t0220H, 0320H, 060CH, 070DH, 066AH\n\t\tDW\t0669H, 0230H, 0330H, 007DH, 017DH\n\t\tDW\t025AH, 035AH, 0200H, 0410H, 046EH\n\t\tDW\t026EH, 007CH\n\nCondPassCond\tDW\tCTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO\n\t\tDW\tCTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON\n\t\tDW\tPAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE\n\t\tDW\tTASKSWITCHABLE, BREAKON\n\nEscRoutine\tDD\t0\t; vector to execute on esc key press (0=none)\n\n; Extended raw keycodes to be converted to Westwood keycodes.\nExtCodes\tDB\t038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H\n\t\tDB\t051H,04DH,035H,01CH,037H\n\t\tDB\t046H\n; The matching Westwood keycodes.\nExtNums\t\tDB\t62,  64,  75,  76,  79,  80,  81,  83,  84,  85\n\t\tDB\t86,  89,  95, 108, 124,  0\n; If extended mapping is disabled, then these codes really are...\nExtRemap\tDB\t60,  58,  99, 104,  92,  91,  93,  96,  98, 101\n\t\tDB\t103, 102, 55,  43, 124,  0\nExtRemapEnd\tDB\t0\n\nExtKeyboard\tDB\t0\t; flag for 101/102-key keyboard\n\n\nKeyBuffer\tDW\t128 DUP(0) ; set to empty\nKeyBufferHead\tDW\t0\t; set to first entry\nKeyBufferTail\tDW\t0\t; set to head for empty buffer\nKeyLock\t\tDW\t0\t; num and caps lock bits\nKeyNums\t\tDB\t127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016\n\t\tDB\t017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032\n\t\tDB\t033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049\n\t\tDB\t050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116\n\t\tDB\t117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093\n\t\tDB\t098,103,099,104,127,127,127,122,123\n\nKeysCapsLock\tDB\t0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0\nKeysNumLock\tDB\t0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0\nKeysUpDown\tDB\t16 DUP(0) ; set to all keys up\nKeyStream\tDB\t16 DUP(0) ; set to all keys up\nPassCount\tDW\t0\nKeyStreamIndex\tDW\t0\nLastKeyE0\tDB\t0\nLastKeyE1\tDB\t0\n\n;\n; Westwood key number values of keys to pass through\n;\n;\t\t\tCAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT,\n;\t\t\tRIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN\nPassAlways\tDB\t30, 44, 57, 58, 60, 62, 64, 90, 128, 128\nPassAlwaysEnd\tDB\t128\t\t; invalid code to END PassAlways\nCtrlFlags\tDB\t0\n\nBuffer\t\tDW\t?\nTime\t\tDW\t?\n\nADJUST\t= 1\t\t\t; do not modify DRD\n\nXYAdjust\tDB\t-ADJUST, -ADJUST\t; 91 -> upleft\n\t\tDB\t-ADJUST,  0\t\t; 92 -> left\n\t\tDB\t-ADJUST,  ADJUST\t; 93 -> downleft\n\t\tDB\t 0,  0\t\t\t; 94 illegal\n\t\tDB\t 0,  0\t\t\t; 95 illegal\n\t\tDB\t 0, -ADJUST\t\t; 96 -> up\n\t\tDB\t 0,  0\t\t\t; 97 illegal (center)\n\t\tDB\t 0,  ADJUST\t\t; 98 -> down\n\t\tDB\t 0,  0\t\t\t; 99 illegal\n\t\tDB\t 0,  0\t\t\t; 100 illegal\n\t\tDB\t ADJUST, -ADJUST\t; 101 -> upright\n\t\tDB\t ADJUST,  0\t\t; 102 -> right\n\t\tDB\t ADJUST,  ADJUST\t; 103 -> downright\nEdgeConv\tDW\t8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7\n\nMouseUpdate\t\tDW\t0\nMouseX\t\t\tDW\t0\nLocalMouseX\t\tDW\t0\nMouseY\t\t\tDW\t0\nLocalMouseY\t\tDW\t0\nButton\t\t\tDW\t0\nIsExtKey\t\tDB\t0\nExtIndex\t\tDW\t0\n\nOldRMI\t\t\tDD\t0\t; The origianl RM interrupt seg:off.\nOldPMIOffset\t\tDD\t0\t; The origianl PM interrupt offset\t\t\nOldPMISelector\t\tDD\t0\t; The original PM interrupt segment.\n\nCodeOffset\t\tDW\tRM_Keystroke_Interrupt\t; Offset of the code in the RM stuff.\nCallRMIntOffset\t\tDW\tCall_Interrupt_Chain\t\t; Offset of function to call DOS timer interrupt.\nCallRMIntAddr\t\tDD\t0\t; PM address of CallRealIntOffset for speed.\n\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Translates the given keynum to ???                  *\n;*                                                                         *\n;* INPUT:\tUWORD the keynum to translate\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated keynum                                 *\n;*                                                                         *\n;* PROTO:\tUWORD KeyNum_Translate(UWORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tKeyNum_Translate:FAR\n\tPROC\tKeyNum_Translate C FAR \n\tUSES\tcx,di,es,ds\n\tARG\tkeycode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\tmov\tes,ax\t\t\t\t; set es up for scansb\n\n\tmov\tax,[keycode]\n\ttest\t[KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\tmov\tcx,ExtRemap-ExtNums\n\tmov\tdi,OFFSET ExtNums\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tdi,OFFSET ExtRemapEnd\n\tdec\tdi\n\tsub\tdi,cx\n\tmov\tal,[es:di]\n??fini:\n\tret\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(WORD code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_WORD:FAR\n\tPROC\tStuff_Key_WORD C FAR \n\tUSES\tsi,bx,ds\n\tARG\tcode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\tax,[KeyBufferTail]\n\tmov\tsi,ax\n\tadd\tax,2\n\tand\tax,0FFh\t\t\t\t; New KeyBufferTail value.\n\tcmp\t[KeyBufferHead],ax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[KeyBuffer+si],bx\t\t; Record the keystroke.\n\tmov\t[KeyBufferTail],ax\n\txor\tax,ax\n\tret\n\n??noroom:\n\tmov\tax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(WORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_Num:FAR\n\tPROC\tStuff_Key_Num C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds\n\tARG\tkeycode:WORD\n\tLOCAL\ttail:WORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n\tpushf\n\tcli\t\t\t\t; disable interrupts\n\n\t; Abort key recognition if in record mode and unable\n\t; to output key due to simultaneous DOS operation.\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\tax,[MouseX]\n\tmov\t[LocalMouseX],ax\n\tmov\tax,[MouseY]\n\tmov\t[LocalMouseY],ax\n\n??cando:\n\tmov\tax,[keycode]\t\t; get the code\n\tor\tax,ax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tbx,1\t\t\t; double for WORD index\n\tadd\tbx,OFFSET XYAdjust\n\tmov\tax,[bx]\t\t\t; get x,y add value\n\n\tmov\tbl,ah\n\tcbw\n\txchg\tax,bx\n\tcbw\n\txchg\tax,bx\t\t\t; AX = mouse x delta, BX = mouse y delta\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tdx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tdx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tbx,dx\t\t\t; add speed for y index\n\tmov\tbl,[KeyMouseMove+bx] \t; get speed for y delta\n\txchg\tax,bx\t\t\t; swap with ax to extend sign\n\tcbw\n\txchg\tax,bx\n\txchg\tbx,dx\t\t\t; save mouse y delta\n\tadd\tbx,ax\t\t\t; add speed for x index\n\tmov\tal,[KeyMouseMove+bx]\t; get speed for x delta\n\tcbw\n\txchg\tbx,dx\t\t\t; restore mouse y delta\n\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tbx,011b\t\t\t; Y = 1, 0, 3\n\tand\tax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tbx,011b\t\t\t; Y = 3, 0, 1\n\tand\tax,011b\t\t\t; X = 3, 0, 1\n\tshl\tbx,1\n\tshl\tbx,1\n\tor\tbx,ax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tbx,1\n\tmov\tbx,[EdgeConv+bx]\n\tshl\tbx,1\n\tshl\tbx,1\n\tmov\tax,[ScreenEdge+bx]\t; New absolute X\n\tmov\tbx,[ScreenEdge+bx+2] ; New absolute Y\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\tax,ax\n\tmov\t[LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tbx,bx\n\tmov\t[LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\tmov\t[MouseX],ax\n\tmov\t[MouseY],bx\n\tcmp\t[MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n; PWG: ARRGGGHHHH!\n;\tcall\tLow_Hide_Mouse\n;\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\tax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],ax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tsi,[KeyBufferTail]\n\tmov\t[tail],si\t\t; Safety record.\n\tmov\tdi,[KeyBufferHead]\n\n\t; Record the base keycode (if there is room).\n\tpush\tax\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\tax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tpush\t[LocalMouseX]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tpush\t[LocalMouseY]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tbx,0101h\t\t; Bit control tools.\n\tmov\tax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tmov\tcl,3\n\tshr\tdi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[KeysUpDown+di]\n\tje\tshort ??notalready\n\ttest\t[KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\t[KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[KeysUpDown+di],bh\t; Force key bit to zero.\n\tor\t[KeysUpDown+di],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\tax,1\n\tjmp short ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\tax,[tail]\n\tmov\t[KeyBufferTail],ax\n\txor\tax,ax\t\t\t; Signal an error.\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tStuff_Key_Num\n;***********************************************************\n\n\n\n;***************************************************************************\n;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard       *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Keystroke_Interrupt\n\tGLOBAL\tC Keystroke_Interrupt:FAR\n\tPROC\tKeystroke_Interrupt C FAR \n\nIF 0\n\tpush\tax\n\tinc\tax\n\tpop\tax\n\tiret\n\nELSE\n\tpush\tax\n\tpush\tbx\n\tpush\tcx\n\tpush\tdi\n\tpush\tds\n\tpush\tdx\n\tpush\tes\n\tpush\tsi\n\tcld\n\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tds,ax\n\tmov\tdx,[KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\tmov\tax,040H\t\t\t; BIOS segment\n\tmov\tes,ax\t\t\t; put in es\n\ttest\t[BYTE PTR es:017H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR es:017H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR es:096H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tes,ax\n\n\tcld\t\t\t\t; clear direction flag for strings\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tbx,0101H\t\t; set key to a make by default\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\n\t;\n\t; New CODE to montior key stream\n\t;\n\tmov\tbx,[KeyStreamIndex]\n\tmov\t[KeyStream+bx],al\n\tinc\tbx\n\tand\tbx,15\n\tmov\t[KeyStreamIndex],bx\n\tmov\tbx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[LastKeyE1]\t\t; yes, dec the count\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[IsExtKey],TRUE\t; it is an extended key\n\tmov\tdi,OFFSET ExtCodes\t; get offset of extended codes table\n\tmov\tcx,(ExtNums-ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\tmov\tal,[(ExtNums - ExtCodes) - 1 + di] ; get the match\n\tmov\t[IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tdi,ax\t\t\t; use code as an index\n\tand\tdi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[KeyNums+di]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[KeysUpDown+8],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[KeysUpDown+7],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[KeysUpDown + 7],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\tax\n\tcall\tKeyNum_Translate\n\tadd\tsp,2\n\n;------\tSet the shift bit if necessary.\n\ttest\t[KeysUpDown+5],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[KeysUpDown+7],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tshr\tdi,1\n\tshr\tdi,1\n\tshr\tdi,1\n\tmov\tbx,ax\n\tand\tbx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[Bits+bx]\t\t; get the bit to test\n\ttest\t[KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[KeysCapsLock+di]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[KeysNumLock+di]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\n\t\t\t\t\t; keyboard buffer.\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\tax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\tax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\tax,0230h\n\tje\tshort ??breaker\n\tcmp\tax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n\tcmp\tax,0420H\t\t; is this an alt s\n\tjne\tshort ??checkmusic\t; toggle the Sound variable\n\tpush\tax\n\tmov\tax,[SoundOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??checkmusic:\n\tcmp\tax,0434H\t\t; is this an alt m\n\tjne\tshort ??esc\t\t; toggle the Music variable\n\tpush\tax\n\tmov\tax,[MusicOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??esc:\n\n\tpush\tax\n\tcall\tStuff_Key_Num\n\tpop\tax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\tax\n\tcall\t[EscRoutine]\n\tpop\tax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tdi,OFFSET PassAlways\t; get offset to table\n\tmov\tcx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1\n\trepne\tscasb\t\t\t; look for a match\n\tor\tcx,cx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n\n\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tdi,OFFSET CondPassKey\t; get offset to cond key table\n\tmov\tcx,(CondPassCond-CondPassKey) ; get number of entries\n\tshr\tcx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(CondPassCond - CondPassKey) - 2 + di]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tdx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n;***********************************************************\n\tpushf\n;\tpush\tdi\n;\tpush\tes\n\t\n\tmov\tax,0B000h\n\tmov\tes,ax\n\tinc\t[BYTE PTR es:0]\n\n;\tpop\tes\n;\tpop\tdi\n\tpopf\n;***********************************************************\n\n??passcode:\n\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tinc\t[cs:PassCount]\n\tjmp\t[cs:OldRMI]\n\n??absorbcode:\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tax,040h\t\t\t\t; BIOS paragraph is always @ 040h\n\tmov\tes,ax\t\t\t\t; put in es as BIOS paragraph\n\tmov\tal,[es:96h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[es:96h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tiret\t\nENDIF\n\n\tENDP\tKeystroke_Interrupt\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles the break key interrupt                      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Break_Interrupt:FAR\n\tPROC\tBreak_Interrupt C FAR\n\n\tiret\t\n\n\tENDP\tBreak_Interrupt\n\n;**************************************************************************\n;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nCall_Interrupt_Chain:\nIF 0\n\tpushf\n\tpush\tax\n\tpush\tdi\n\tpush\tes\n\n\tmov\tax,0B000h\t\t; ES:DI = Mono RAM address.\n\tmov\tes,ax\n\t\t\n\tmov\tal,'A'\n\tmov\tah,2\n\tand\tdi,63\n\n\tstosw\n\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\tmov\tal,CLEARISR\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t; 8259 interrupt chip controller 0\n\n\n\tpop\tes\n\tpop\tdi\n\tpop\tax\n\tpopf\nENDIF\n\tpushf\n\tcall\tKeystroke_Interrupt ;[OldRMI]\n\tretf\n\nSTACK\t   ; Don't really need this\n\n;***********************************************************\nEND\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/NEW/KEYIREAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*\t\t\t\t  (Mouse Routines)\n;*                                                                         *\n;*                    File Name : KEYIREAL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Philip W. Gorrow                         *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;* This file sort of breaks the standard of keeping all of the keyboard    *\n;* and mouse routines isolated.  This is done because the mouse and\t   *\n;* the keyboard share data, and the best way to do this is to put\t   *\n;* them in the same segment.  This should probably be split into several   *\n;* include files to help make the code clearer once it is finally put\t   *\n;* together.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   KeyNum_Translate -- Translates extended keynums to normal keynums\t   *\n;*   Stuff_Key_Word -- Stuffs a word of data into keyboard buffer          *\n;*   Stuff_Key_Num -- Stuffs a key num code into the circular buffer       *\n;*   Keystroke_Interrupt -- Real mode handler of input from the keyboard   *\n;*   Break_Interrupt -- Handles the break key interrupt                    *\n;*   Call_Interrupt_Chain -- Function PM calls to call RM interrupt chain  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tKeyboard driver -- 8086 Assembly portion;\t\t\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   *\n;***************************************************************************\n\n;---------------------------------------------------------------------------\n; Set the assembly directives\n;---------------------------------------------------------------------------\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386N\t\t\t\t; use 386 real mode instructions\nMODEL TINY\t\t\t; code must be tiny so it fits\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keyboard.inc\"\n\nCONDHIDE\t\tEQU\t08000H\t\t; bit for testing conditional region\nCONDHIDDEN\t\tEQU\t04000H\t\t; bit for testing conditional hidden\nRESTORE_VISIBLE_PAGE\tEQU\t0\nSTORE_VISIBLE_PAGE\tEQU\t1\n\n\nGLOBAL\tset_vesa_page \t:near\nGLOBAL\tset_vesa_window :near\nGLOBAL\tget_vesa_window :near\nGLOBAL\tnext_vesa_page\t:near\n\nECHOON\tequ 0\n;---------------------------------------------------------------------------\n; WARNING!!!!  All of the following code segment variables are shared by\n;   the protected mode interrupt.  Do not change these unless you make the\n;   proper changes to KEYSTRUC.INC.  If you do not know what you are doing,\n;   find someone who does!!!\n;---------------------------------------------------------------------------\nCODESEG\n\n;---------------------------------------------------------------------------\n; Begin definition of Keyboard specific variables\n;---------------------------------------------------------------------------\nSoundOn\t\tDW\t1\t; toggled by alt S\nMusicOn\t\tDW\t1\t; toggled by alt M\nKeyFlags\tDD\tREPEATON+CTRLALTTURBO\t; all but repeat for now\n\n\nBreak\t\tDW\t0\n\nKeyMouseMove\tDB\t-1,0,1\n\t\tDB\t-16,0,16\n\nScreenEdge\tDW\t320/2,0\t\t; North\n\t\tDW\t319,0\t\t; North-East\n\t\tDW\t319,138/2\t; East\n\t\tDW\t319,137\t\t; South-East\n\t\tDW\t320/2,137\t; South\n\t\tDW\t0,137\t\t; South-West\n\t\tDW\t0,138/2\t\t; West\n\t\tDW\t0,0\t\t; North-West\n\t\tDW\t320/2,138/2\t; Center\n\n\nBits\t\tDB\t01H,02H,04H,08H,10H,20H,40H,80H\n\nCondPassKey\tDW\t0220H, 0320H, 060CH, 070DH, 066AH\n\t\tDW\t0669H, 0230H, 0330H, 007DH, 017DH\n\t\tDW\t025AH, 035AH, 0200H, 0410H, 046EH\n\t\tDW\t026EH, 007CH\n\nCondPassCond\tDW\tCTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO\n\t\tDW\tCTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON\n\t\tDW\tPAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE\n\t\tDW\tTASKSWITCHABLE, BREAKON\n\nEscRoutine\tDD\t0\t; vector to execute on esc key press (0=none)\n\n; Extended raw keycodes to be converted to Westwood keycodes.\nExtCodes\tDB\t038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H\n\t\tDB\t051H,04DH,035H,01CH,037H\n\t\tDB\t046H\n; The matching Westwood keycodes.\nExtNums\t\tDB\t62,  64,  75,  76,  79,  80,  81,  83,  84,  85\n\t\tDB\t86,  89,  95, 108, 124,  0\n; If extended mapping is disabled, then these codes really are...\nExtRemap\tDB\t60,  58,  99, 104,  92,  91,  93,  96,  98, 101\n\t\tDB\t103, 102, 55,  43, 124,  0\nExtRemapEnd\tDB\t0\n\nExtKeyboard\tDB\t0\t; flag for 101/102-key keyboard\n\n\nKeyBuffer\tDW\t128 DUP(0) ; set to empty\nKeyBufferHead\tDD\t0\t; set to first entry\nKeyBufferTail\tDD\t0\t; set to head for empty buffer\nKeyLock\t\tDW\t0\t; num and caps lock bits\nKeyNums\t\tDB\t127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016\n\t\tDB\t017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032\n\t\tDB\t033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049\n\t\tDB\t050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116\n\t\tDB\t117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093\n\t\tDB\t098,103,099,104,127,127,127,122,123\n\nKeysCapsLock\tDB\t0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0\nKeysNumLock\tDB\t0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0\nKeysUpDown\tDB\t16 DUP(0) ; set to all keys up\nKeyStream\tDB\t16 DUP(0) ; set to all keys up\nPassCount\tDW\t0\nKeyStreamIndex\tDW\t0\nLastKeyE0\tDB\t0\nLastKeyE1\tDB\t0\n\n;\n; Westwood key number values of keys to pass through\n;\n;\t\t\tCAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT,\n;\t\t\tRIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN\nPassAlways\tDB\t30, 44, 57, 58, 60, 62, 64, 90, 128, 128\nPassAlwaysEnd\tDB\t128\t\t; invalid code to END PassAlways\nCtrlFlags\tDB\t0\n\nBuffer\t\tDW\t?\nTime\t\tDW\t?\n\nADJUST\t= 1\t\t\t; do not modify DRD\n\nXYAdjust\tDB\t-ADJUST, -ADJUST\t; 91 -> upleft\n\t\tDB\t-ADJUST,  0\t\t; 92 -> left\n\t\tDB\t-ADJUST,  ADJUST\t; 93 -> downleft\n\t\tDB\t 0,  0\t\t\t; 94 illegal\n\t\tDB\t 0,  0\t\t\t; 95 illegal\n\t\tDB\t 0, -ADJUST\t\t; 96 -> up\n\t\tDB\t 0,  0\t\t\t; 97 illegal (center)\n\t\tDB\t 0,  ADJUST\t\t; 98 -> down\n\t\tDB\t 0,  0\t\t\t; 99 illegal\n\t\tDB\t 0,  0\t\t\t; 100 illegal\n\t\tDB\t ADJUST, -ADJUST\t; 101 -> upright\n\t\tDB\t ADJUST,  0\t\t; 102 -> right\n\t\tDB\t ADJUST,  ADJUST\t; 103 -> downright\n\tEdgeConv\t\tDW\t8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7\n\tMouseUpdate\t\tDW\t0\n\tMouseX\t\t\tDW\t0,0\n\tLocalMouseX\t\tDW\t0\n\tMouseY\t\t\tDW\t0,0\n\tLocalMouseY\t\tDW\t0\n\tIsExtKey\t\tDB\t0\n\tExtIndex\t\tDW\t0\n\n\tKeyOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tKeyOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\t\t\n\tKeyOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tKeyCodeOffset\t\tDW\tRM_Keystroke_Interrupt\t; Offset of the code in the RM stuff.\n\tCallKeyRMIntOffset\tDW\tCall_Interrupt_Chain\t; Offset of function to call DOS timer interrupt.\n\tCallKeyRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedKeyInt\t\tDD\t0\n\n\tBrkOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tBrkOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\t\t\n\tBrkOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tBrkCodeOffset\t\tDW\tRM_Break_Interrupt\t; Offset of the code in the RM stuff.\n\tCallBrkRMIntOffset\tDW\t0\n\tCallBrkRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedBrkInt\t\tDD\t0\n\tKeyIntDisabled\t\tDD\t0\n\n\tDbgOldPMIOffset\t\tDD\t0\t; The origianl PM interrupt offset\t\t\n\tDbgOldPMISelector\tDD\t0\t; The original PM interrupt segment.\n\n;---------------------------------------------------------------------------\n; Begin definition of Mouse Specific Variables for real mode\n;---------------------------------------------------------------------------\nButton\t\t\tDB\t0\t; current value of the mouse button\nMDisabled\t\tDB\t0\t; Is the mouse driver disabled\nMInput\t\t\tDB\t1\t; Defaults to mouse input allowed.\nAdjust\t\t\tDW\t0\t; flag to adjust coordinates if necessary\nMouseStepX\t\tDW\t0\t; step values if the mouse moves at\nMouseStepY\t\tDW\t0\t;   more than one pixel at a time\nMouseOffsetX\t\tDW\t0\t; Fractional step values used if a mouse\nMouseOffsetY\t\tDW\t0\t;   moves at less than one pixel at a time\nMState\t\t\tDW\t0,0\t; Tracks if mouse is hidden (TRUE) or not (FALSE)\nMouseXOld     \t\tDW\t0\t; Holds last MouseX and MouseY to determine if \nMouseYOld     \t\tDW\t0\t;   mouse needs to be redrawn\nMCState\t\t\tDW\t0\t; Tracks if mouse conditional hidden (TRUE) or not\nMouseCXLeft\t\tDW\t0,0\t; Conditional hide mouse left x position\nMouseCYUpper\t\tDW\t0,0\t; Conditional hide mouse top y position\nMouseCXRight\t\tDW\t0,0\t; Conditional hide mouse right x position\nMouseCYLower\t\tDW\t0,0\t; Conditional hide mouse lower y position\nMouseCursor   \t\tDD\t0\t; Pointer to the mouse cursor to draw\nMouseCursorSize\t\tDW\t0\t; Pointer to buffer mouse is saved in\nMouseBuffer   \t\tDD\t0\t; Pointer to buffer mouse is saved in\nMouseXHot     \t\tDW\t0,0\t; Offset to mouse's x hot spot\nMouseYHot     \t\tDW\t0,0\t; Offset to mouse's y hot spot\nMouseBuffX\t\tDW\t0,0\t; X position background was saved at\nMouseBuffY\t\tDW\t0,0\t; Y position background was saved at\nMouseBuffW\t\tDW\t0,0\t; Width of the region saved for mouse\nMouseBuffH\t\tDW\t0,0\t; Height of the region saved for mouse\nMouseWidth\t\tDW\t0,0\t; Mouse cursor theoretical width\nMouseHeight\t\tDW\t0,0\t; Mouse cursor theoretical height\nMouseCodeOffset\t\tDW\tRM_Mouse_Interrupt\t; Offset of the code in the RM stuff.\nMouseRight\t\tDW\t0,0\nMouseBottom\t\tDW\t0,0\n\n\nShadowPtr\t\tdw\t0\nDrawMousePtr \t\tdw\t0\n\nVGAMouseDraw\t\tdw\tVGA_Draw_Mouse\nVGAMouseShadow\t\tdw\tVGA_Mouse_Shadow_Buffer\n\nVESAMouseDraw\t\tdw\tVESA_Draw_Mouse\nVESAMouseShadow\t\tdw\tVESA_Mouse_Shadow_Buffer\n\nVesaPtr\t\t\tdd\t0\t\nbanktable\t\tdd      8 dup ( 0 )\nAdjust_XPos\t\tdw \t0 , 0\nAdjust_YPos\t\tdw \t0 , 0 \n\n\t\talign 2\nKeyboard_App_Stack_ES\tdw 0\t\t; This the System Stack Offsset\nKeyboard_App_Stack_SS\tdw 0\t\t; This the System Stack Selector\nKeyboard_StackPointer\tdw 0DEADh\t; We Create a Local Application\nKeyboard_Stack\t\tdw 255 dup (0)\nKeyboard_StackStart\tdw 0\n\nMouse_State\t\tdw 0\t\t; Mouse Temp Variable\nMouse_Cond\t\tdw 0\t\t; Mouse Temp Variable\nMouse_App_Stack_ES\tdw 0\t\t; This the System Stack Offsset\nMouse_App_Stack_SS\tdw 0\t\t; This the System Stack Selector\nMouse_StackPointer\tdw 0DEADh\t; We Create a Local Application\nMouse_Stack\t\tdw 255 dup (0)\nMouse_StackStart\tdw 0\n\n\n\ncurrent_page\t\tdw\t0\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Translates extended keynums to normal keynums\t   *\n;*                                                                         *\n;* INPUT:\tUWORD the keynum to translate\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated keynum                                 *\n;*                                                                         *\n;* PROTO:\tUWORD KeyNum_Translate(UWORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tKeyNum_Translate:FAR\n\tPROC\tKeyNum_Translate C FAR \n\tUSES\tcx,di,es,ds\n\tARG\tkeycode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\tmov\tes,ax\t\t\t\t; set es up for scansb\n\n\tmov\tax,[keycode]\n\ttest\t[WORD PTR KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\tmov\tcx,ExtRemap-ExtNums\n\tmov\tdi,OFFSET ExtNums\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tdi,OFFSET ExtRemapEnd\n\tdec\tdi\n\tsub\tdi,cx\n\tmov\tal,[es:di]\n??fini:\n\tret\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(WORD code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_WORD:FAR\n\tPROC\tStuff_Key_WORD C FAR \n\tUSES\tsi,bx,ds\n\tARG\tcode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\tax,[WORD PTR KeyBufferTail]\n\tmov\tsi,ax\n\tadd\tax,2\n\tand\tax,0FFh\t\t\t\t; New KeyBufferTail value.\n\tcmp\t[WORD PTR KeyBufferHead],ax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[KeyBuffer+si],bx\t\t; Record the keystroke.\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\n\tret\n\n??noroom:\n\tmov\tax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(WORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_Num:FAR\n\tPROC\tStuff_Key_Num C FAR \n\tUSES\tbx,cx,dx,di,si,ds\n\tARG\tkeycode:WORD\n\tLOCAL\ttail:WORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n\tpushf\n\tcli\t\t\t\t; disable interrupts\n\n\t; Abort key recognition if in record mode and unable\n\t; to output key due to simultaneous DOS operation.\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\tax,[MouseX]\n\tmov\t[LocalMouseX],ax\n\tmov\tax,[MouseY]\n\tmov\t[LocalMouseY],ax\n\n??cando:\n\tmov\tax,[keycode]\t\t; get the code\n\tor\tax,ax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[WORD PTR KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[WORD PTR KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tbx,1\t\t\t; double for WORD index\n\tadd\tbx,OFFSET XYAdjust\n\tmov\tax,[bx]\t\t\t; get x,y add value\n\n\tmov\tbl,ah\n\tcbw\n\txchg\tax,bx\n\tcbw\n\txchg\tax,bx\t\t\t; AX = mouse x delta, BX = mouse y delta\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tdx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tdx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tbx,dx\t\t\t; add speed for y index\n\tmov\tbl,[KeyMouseMove+bx] \t; get speed for y delta\n\txchg\tax,bx\t\t\t; swap with ax to extend sign\n\tcbw\n\txchg\tax,bx\n\txchg\tbx,dx\t\t\t; save mouse y delta\n\tadd\tbx,ax\t\t\t; add speed for x index\n\tmov\tal,[KeyMouseMove+bx]\t; get speed for x delta\n\tcbw\n\txchg\tbx,dx\t\t\t; restore mouse y delta\n\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tbx,011b\t\t\t; Y = 1, 0, 3\n\tand\tax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tbx,011b\t\t\t; Y = 3, 0, 1\n\tand\tax,011b\t\t\t; X = 3, 0, 1\n\tshl\tbx,1\n\tshl\tbx,1\n\tor\tbx,ax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tbx,1\n\tmov\tbx,[EdgeConv+bx]\n\tshl\tbx,1\n\tshl\tbx,1\n\tmov\tax,[ScreenEdge+bx]\t; New absolute X\n\tmov\tbx,[ScreenEdge+bx+2] ; New absolute Y\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\tax,ax\n\tmov\t[LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tbx,bx\n\tmov\t[LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\tmov\t[MouseX],ax\n\tmov\t[MouseY],bx\n\tcmp\t[MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n\n\tcall\tLow_Hide_Mouse\n\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\tax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],ax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tsi,[WORD KeyBufferTail]\n\tmov\t[tail],si\t\t; Safety record.\n\tmov\tdi,[WORD PTR KeyBufferHead]\n\n\t; Record the base keycode (if there is room).\n\tpush\tax\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\tax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tpush\t[LocalMouseX]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tpush\t[LocalMouseY]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tbx,0101h\t\t; Bit control tools.\n\tmov\tax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[WORD PTR KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tmov\tcl,3\n\tshr\tdi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[KeysUpDown+di]\n\tje\tshort ??notalready\n\ttest\t[WORD PTR KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[KeysUpDown+di],bh\t; Force key bit to zero.\n\tor\t[KeysUpDown+di],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\tax,1\n\tjmp short ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\tax,[tail]\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\t\t\t; Signal an error.\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tStuff_Key_Num\n;***********************************************************\n\n\n\n;***************************************************************************\n;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard       *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Keystroke_Interrupt\n\tGLOBAL\tC Keystroke_Interrupt:FAR\n\tPROC\tKeystroke_Interrupt C FAR \n\nIF 0\n\tpush\tax\n\tinc\tax\n\tpop\tax\n\tiret\n\nELSE\n\tpush\tax\n\tpush\tbx\n\tpush\tcx\n\tpush\tdi\n\tpush\tds\n\tpush\tdx\n\tpush\tes\n\tpush\tsi\n\tcld\n\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tds,ax\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov cx, ss\t\t\t\t; get SS\n\tmov [Keyboard_App_Stack_ES], sp\t\t; Protect ES\n\tmov [Keyboard_App_Stack_SS], cx\t\t; Protect SS\n\tlea dx, [Keyboard_StackStart ]\t\t; Compute Local Stack size\n\tand dx, -2;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov sp, dx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n\tcmp\t[WORD PTR PMIssuedKeyInt],0; Check to see if PM made Int call.\n\tmov\t[WORD PTR PMIssuedKeyInt],0; Make it false.\t\t\n\tjne\t??passcode\t; if so, just call Int Chain.\n\n\n\tmov\tdx,[WORD PTR KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\tmov\tax,040H\t\t\t; BIOS segment\n\tmov\tes,ax\t\t\t; put in es\n\ttest\t[BYTE PTR es:017H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR es:017H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR es:096H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tes,ax\n\n\tcld\t\t\t\t; clear direction flag for strings\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tbx,0101H\t\t; set key to a make by default\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\n\t;\n\t; New CODE to montior key stream\n\t;\n\tmov\tbx,[KeyStreamIndex]\n\tmov\t[KeyStream+bx],al\n\tinc\tbx\n\tand\tbx,15\n\tmov\t[KeyStreamIndex],bx\n\tmov\tbx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[LastKeyE1]\t\t; yes, dec the count\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[IsExtKey],TRUE\t; it is an extended key\n\tmov\tdi,OFFSET ExtCodes\t; get offset of extended codes table\n\tmov\tcx,(ExtNums-ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\tmov\tal,[(ExtNums - ExtCodes) - 1 + di] ; get the match\n\tmov\t[IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tdi,ax\t\t\t; use code as an index\n\tand\tdi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[KeyNums+di]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[KeysUpDown+8],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[KeysUpDown+7],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[KeysUpDown + 7],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\tax\n\tcall\tKeyNum_Translate\n\tadd\tsp,2\n\n;------\tSet the shift bit if necessary.\n\ttest\t[KeysUpDown+5],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[KeysUpDown+7],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tshr\tdi,1\n\tshr\tdi,1\n\tshr\tdi,1\n\tmov\tbx,ax\n\tand\tbx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[Bits+bx]\t\t; get the bit to test\n\ttest\t[KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[KeysCapsLock+di]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[KeysNumLock+di]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\t\n\t\t\t\t\t; keyboard buffer.\n\ttest\tdx,DEBUGINT\n\tjz\t??not_toggle \n\n\nIF DEBUG\n\tcmp\t[KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\tcmp\tax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\tax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\tax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\t\n\tcmp\tax,125\n\tjne\t??not_toggle\n\tmov\t[KeyIntDisabled],1\n\tjmp\t??absorbcode\nENDIF\n\n??not_toggle:\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\tax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\tax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\tax,0230h\n\tje\tshort ??breaker\n\tcmp\tax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n\tcmp\tax,0420H\t\t; is this an alt s\n\tjne\tshort ??checkmusic\t; toggle the Sound variable\n\tpush\tax\n\tmov\tax,[SoundOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??checkmusic:\n\tcmp\tax,0434H\t\t; is this an alt m\n\tjne\tshort ??esc\t\t; toggle the Music variable\n\tpush\tax\n\tmov\tax,[MusicOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??esc:\n\n\tpush\tax\n\tcall\tStuff_Key_Num\n\tpop\tax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\tax\n\tcall\t[EscRoutine]\n\tpop\tax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tdi,OFFSET PassAlways\t; get offset to table\n\tmov\tcx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1\n\trepne\tscasb\t\t\t; look for a match\n\tor\tcx,cx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n\n\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tdi,OFFSET CondPassKey\t; get offset to cond key table\n\tmov\tcx,(CondPassCond-CondPassKey) ; get number of entries\n\tshr\tcx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(CondPassCond - CondPassKey) - 2 + di]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tdx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\n\tinc\t[cs:PassCount]\n\n;mov   ax , 0B000h\n;mov   es, ax \n;inc   [BYTE PTR es : 40h]\n\n\t; Now it is time to set up for the call to the System Keyboard\n\t; interrupt handler.\n\t; 1 -Restore System Stack Pointer Selector before exit Interrupt\n\t; 2- We Create a Returning Point from Interrupt by Push A\n \t;    Interupt Stack Frame into the Stack Pointer\n\t; 3- We make a Far jump to the interuupt handler\n\tcmp [Keyboard_StackPointer],0DEADh\n\tje  ??stackok\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n??stackok:\n\tcli\t\t\t\t       ; disable Interrupts\n\tmov dx, [Keyboard_App_Stack_SS]       \n\tmov ss, dx\t\t\t       ; Get System Stack Selector\n\tmov sp, [Keyboard_App_Stack_ES]      ; Get System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n\tlea\tdx, [??Call_Back_Keyboard]   ; Get Return address offset\n \tpushf\t\t\t\t      ; push flags\t\n\tpush\tcs\t\t\t      ; push Code segment\n\tpush\tdx\t\t\t      ; push Offset\n\n\t; Now we need to simulate an interrup call by using ired\n\t; because we still want to come back here from the\n\t; Old Keyboard interrupt handle.\n\tpushf\n\tpush\t[word ptr KeyOldRMI + 2] \t; push orig segment.\n\tpush    [word ptr KeyOldRMI]   \t\t; push orig offset.\n\tiret\t \t\t        \t; call interrupt\t\n\n??absorbcode:\n\n;mov   ax , 0B000h\n;mov   es, ax \n;inc   [BYTE PTR es : 0h]\n\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tax,040h\t\t\t\t; BIOS paragraph is always @ 040h\n\tmov\tes,ax\t\t\t\t; put in es as BIOS paragraph\n\tmov\tal,[es:96h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[es:96h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\n\tcmp [Keyboard_StackPointer],0DEADh\n\tje  ??stackok2\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n??stackok2:\n\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov dx, [Keyboard_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, dx\t\t\t       ; Get Syatem Stack Selector\n\tmov sp, [Keyboard_App_Stack_ES]        ; Get Syatem Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n??Call_Back_Keyboard:\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tiret\t\nENDIF\n\n\tENDP\tKeystroke_Interrupt\n\n;***************************************************************************\n;* Break interrupt routines begin here!\n;***************************************************************************\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles the break key interrupt                      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Break_Interrupt\n\tGLOBAL\tC Break_Interrupt:FAR\n\tPROC\tBreak_Interrupt C FAR\n\n\n\tpushf\n\tpush\tax\n\tpush\tes\n\n\tmov\tax,0B000h\t\t; ES:DI = Mono RAM address.\n\tmov\tes,ax\n\tinc\t[BYTE PTR es:0]\n\t\t\n\n\tpop\tes\n\tpop\tax\n\tpopf\n\n\n\tiret\t\n\n\tENDP\tBreak_Interrupt\n\n;**************************************************************************\n;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                                  *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nCall_Interrupt_Chain:\n\tpushf\n\tcall\tKeystroke_Interrupt ;[KeyOldRMI]\n\tretf\n\n;----------------------------------------------------------------------------\n; LOW_HIDE_MOUSE:\n;\n; This function hides the mouse cursor on the screen if it was shown.  It \n; will not hide the mouse if it is already hidden.\n;\n; PROTOTYPE:\n;\n;\tVOID Low_Hide_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Hide_Mouse:FAR\n\tPROC\tLow_Hide_Mouse C FAR \n\tUSES\tax,bx,cx,dx,ds\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n   \tcmp\t[MDisabled],0\t\t; check if mouse is disabled\n\tjne\tshort ??end\n\n   \tcmp\t[MState],0\t\t; check if it was hidden before\n\tjne\tshort ??endnodraw\t\t; no need to hide again\n\n;------\tMove the saved graphic buffer to the seenpage to hide the mouse.\n;\tcall\tBuffer_To_Page C,[buffx],[buffy],[buffw],[buffh],[MouseBuffer],SEENPAGE\n\tmov\tax,RESTORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tRecord that the mouse has been hidden.\n??endnodraw:\n\tadd\t[MState],1\n\tadc\t[MState],0\n\n??end:\n\tret\n\n\tENDP\tLow_Hide_Mouse\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; LOW_SHOW_MOUSE:\n;\n; This function displays the mouse cursor on the screen if it was hidden.\n;\n; PROTOTYPE:\n;\tVOID Low_Show_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Show_Mouse:FAR\n\tPROC\tLow_Show_Mouse C FAR \n\tUSES \tax,bx,cx,dx,si,di,ds,es\n\tLOCAL\tmousex:WORD\t\t; Draw X position.\n\tLOCAL\tmousey:WORD\t\t; Draw Y position.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n;-----\tDon't show the mouse if it is not hidden, disabled.\n\tcmp\t[MDisabled],0\t\t; is the mouse disabled\n\tjne\t??exit\t\t\t; if so then exit\n\n\tcmp\t[MState],0\t\t; is the mouse already visible\n       \tje\t??exit\t\t\t; if so then exit\n\n\tdec\t[MState]\n\tcmp\t[MState],0\t\t; can the mouse be shown\n       \tjne\tshort ??exit\n\n;------\tDetermine the drawing position of the mouse.\n\tmov\tcx,[MouseWidth]\t\t; Theoretical buffer width (pixel).\n\tmov\tdx,[MouseHeight]\t; Theoretical buffer height (pixel).\n\n\tmov\tax,[MouseX]\n;\tsub\tax,[MouseXHot]\n\tmov\t[mousex],ax\t\t; Draw X pixel.\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??xnotneg\n;\tadd\tcx,ax\t\t\t; Reduce width accordingly.\n;\tmov\tax,0\n??xnotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n\tmov\tbx,[MouseY]\n;\tsub\tbx,[MouseYHot]\n\tmov\t[mousey],bx\t\t; Draw Y pixel.\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??ynotneg\n;\tadd\tdx,bx\t\t\t; Reduce height of mouse accordingly.\n;\tmov\tbx,0\n??ynotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n;------\tDetermine the theoretical coordinates and dimensions of the\n;\tarea the mouse shape will be rendered upon.\n\tmov\t[MouseBuffX],ax\n\tmov\t[MouseBuffY],bx\n\tmov\t[MouseBuffW],cx\n\tmov\t[MouseBuffH],dx\n\n;------\tMove the area that will be drawn upon, to the graphic buffer.\n\tmov\tax,STORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tDraw the mouse shape to the seenpage.\n\tpush\t[mousey]\n\tpush\t[mousex]\n\tpush\tcs\n\tcall\t[ DrawMousePtr ]\n\tadd\tsp,4\n??exit:\n\tret\n\n\tENDP\tLow_Show_Mouse\n\n;----------------------------------------------------------------------------\n;----------------------------------------------------------------------------\n\tGLOBAL\tC Mouse_KeyNum:FAR\n\tPROC\tMouse_KeyNum C FAR \n\tUSES\tbx\n\tARG\tstate:WORD\t\t; Current mouse state.\n\tLOCAL\tkeynum:WORD\t\t; Determined keynum.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\t[keynum],KN_MOUSE_MOVE\t; Presume just a mouse move.\n\tmov\tbx,[state]\n\tmov\tax,bx\n\txor\tbl,[Button]\t\t; Bits of state change.\n\tje\tshort ??fini\n\tmov\t[Button],al\t\t; Record new mouse state.\n\n\ttest\tbl,0010b\n\tje\tshort ??notright\n\tmov\t[keynum],KN_RMOUSE\n\ttest\tal,0010b\n\tjne\tshort ??notright\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notright:\n\n; DRD\n; note:  the left mouse button has priority over the right mouse button\n; this should be changed at a later date to process them independently\n\n\ttest\tbl,0001b\n\tje\tshort ??notleft\n\tmov\t[keynum],KN_LMOUSE\n\ttest\tal,0001b\n\tjne\tshort ??notleft\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notleft:\n\n??fini:\n\tmov\tax,[keynum]\n\tret\n\n\tENDP\tMouse_KeyNum\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; MOUSE_INT:\n;\n; This routine is called automatically when the Mouse_Int is installed.  It\n; automatically updates the global variables stored in the code segment so\n; that the mouse information is automatically known at all times.\n;\n; INPUTS (from int):\tAX = condition mask ( bit 0 == cursor position chg,\n;\t\t\t\t\t      bit 1 == left button press,\n;\t\t\t\t\t      bit 2 == left button release,\n;\t\t\t\t\t      bit 3 == right button press,\n;\t\t\t\t\t      bit 4 == right button release,\n;\t\t\t\t\t      5-15  == not used )\n;\t\t\tBX = button state   ( bit 0 == left button down,\n;\t\t\t\t\t      bit 1 == right button down,\n;                                             bit 2 == middle button down.\n;\t\t\t\t\t      3-15  == not used )\n;\t\t\tCX = cursor coordinate (horizontal axis)\n;\t\t\tDX = cursor coordinate (vertical axis)\n;\t\t\tDI = horizontal mouse count (mickeys)\n;\t\t\tSI = vertical mouse count (mickeys)\n;\n; RETURNS:\t\tnone\n;\n; MODIFIES:\t\tmodifies the variables _Button, _ButtonChange,\n;\t\t\t_MouseX,_MouseY,_ButtonLatch\n;\n; PROTOTYPE:\n;\tThis routine is called from an interrupt.\n;----------------------------------------------------------------------------\nlabel RM_Mouse_Interrupt\n\tPROC\tMouse_Int C FAR \n\tUSES\tax,bx,cx,dx,ds,si,es,di\n\tLOCAL\tcond:WORD\t\t; Local copy of mouse event.\n\tLOCAL\tstate:WORD\t\t; Local copy of button state.\n\n\tmov\t[cs:Mouse_State],bx\n\tmov\t[cs:Mouse_Cond],ax\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov bx, ss\t\t\t\t; get SS\n\tmov [Mouse_App_Stack_ES], sp\t\t; Protect ES\n\tmov [Mouse_App_Stack_SS], bx\t\t; Protect SS\n\tlea bx, [Mouse_StackStart ]\t; Compute Local Stack size\n\tand bx, -2;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov sp, bx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n;------\tProcess the mouse interrupt only if the mouse is enabled (whether\n;\tpresent or not).\n\tcmp\t[MDisabled],0\n\tjne\t??exit\n\n\tcmp\t[MInput],0\n\tje\t??exit\n\n\n;------ This was added because of missing mouse presses and\n;\treleases during a mouse update.\n\tmov\tax,[Mouse_Cond]\n\tand\tax,0001EH \t; bits for left and right press and release\n\tjne\tshort ??dopress_release\n\n\tcmp\t[MouseUpdate],0 ; if mouse move and mouse updating exit\n\tjne\t??exit\n\n??dopress_release:\n\n;------\tIn EEGA mode mouse X coordinates as 0..639.  Make adjustment\n;\tto keep within 0..319 range.\n\tcmp\t[Adjust],1\t\t; if the x coordinate is returned\n\tjne\tshort ??noadjust\t; incorrectly then\n\tshr\tcx,1\t\t\t; adjust x coord from 640 pixel screen\n??noadjust:\n\n\n; scale mouse posX and PosY\n;\tcmp\t[Adjust_XPos] , 0\n;\tjz\tshort ??no_scaleX\n;\tpush\tdx\n;\tmov\tax , [MouseRight]\n;\timul\tcx\n;\tidiv\t[Adjust_XPos]\n;\tmov\tcx , ax\n;\tpop\tdx\n??no_scaleX:\n;\tcmp\t[Adjust_YPos] , 0\n;\tjz\tshort ??no_scaleY\n;\tmov\tax , [MouseBottom]\n;\timul\tdx\n;\tidiv\t[Adjust_YPos]\n;\tmov\tdx , ax\n??no_scaleY:\n\n;------\tKeep mouse within screen bounds.\n\tcmp\tcx,[MouseRight]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundX_ok\t\t; force it to stay at least one pixel\n\tmov\tcx,[MouseRight]\t\t\t; on the screen\n\tdec\tcx\n??boundX_ok:\n\tcmp\tdx,[MouseBottom]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundY_ok\t\t; force it to stay at least one pixel\n\tmov\tdx,[MouseBottom]\t\t\t; on the screen\n\tdec\tdx\n??boundY_ok:\n\n\tIF 0\n;------\tRemap the middle button to equal the right button.\n\ttest\tbx,04h\n\tje\t??noremap\n\tor\tbx,0010b\t\t; Set the right button bit.\n??noremap:\n\tENDIF\n\n\tmov\t[MouseX],cx\t\t; and store in mouse x\n\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\ttest\t[KeyFlags],KEYMOUSE\n\tjne\tshort ??nostuffit\n\n\tcall\tMouse_KeyNum C,[Mouse_State]\t; Convert mouse state to key number code.\n\tcall\tStuff_Key_Num C,ax\t; Record mouse keynumber code.\n??nostuffit:\n\n\n\n;------ The check for Mouse in the middle of updating CAN NOT BE MOVED\n;\tany farther up because mouse presses and releases will be LOST!!\n \tcmp\t[MouseUpdate],0\n\tjne\t??exit\n;??jexit:\n;\tjmp\t??exit\n\n\nchristopher:\n??chkxy:\n\n;------\tSignal that no mouse updating can occur at this time.\n;\tcmp\t[_MouseUpdate],0\n;\tjne\t??exit\n;\tmov\t[_MouseUpdate],1\n\n;------\tPerform any X movement grid adjustment.\n\tcmp\t[MouseStepX],0\t\t; are we stepping on the X?\n\tje\tshort ??no_x_step\t\t; no x\n\tmov\tax,cx\t\t\t; get current x_pixel\n\tmov\tcx,dx\t\t\t; save dx - it is trashed by idiv\n\tsub\tax,[MouseOffsetX]\t; get offset difference\n\tmov\tbx,[MouseStepX]\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step X\n\timul\tbx\t\t\t; ax = div * Step X\n\tadd\tax,[MouseOffsetX]\t; normalize to region offset\n\tmov\tdx,cx\t\t\t; restore dx (new MouseY)\n\tmov\tcx,ax\t\t\t; set cx (new MouseX)\n??no_x_step:\n\n;------\tPerform any Y movement grid adjustment.\n\tcmp\t[MouseStepY],0\t\t; are we stepping on the Y\n\tje\tshort ??no_step\t\t; no y\n\tmov\tax,dx\t\t\t; get current y_pixel\n\tsub\tax,[MouseOffsetY]\t; get offset difference\n\tmov\tbx,[MouseStepY]\t\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step Y\n\timul\tbx\t\t\t; ax = div * Step Y\n\tadd\tax,[MouseOffsetY]\t; normalize to region offset\n\tmov\tdx,ax\t\t\t; set dx (new MouseY)\n??no_step:\n\n;------ Here is where we store the new MouseX and MouseY values\n;\tmov\t[MouseX],cx\t\t; and store in mouse x\n;\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\n;------\tIf the mouse is hidden or its position hasn't changed, then\n;\tperform no action.\n\tcmp\t[MState],0\n\tjne\tshort ??updateend\n\tcmp\t[MouseXOld],cx\n\tjne\tshort ??doit\n\tcmp\t[MouseYOld],dx\n\tje\tshort ??updateend\n??doit:\n\n;------\tAt this point we KNOW the mouse has moved.\n\tmov\tax,[MCState]\n\tand\tax,CONDHIDE+CONDHIDDEN\n\tcmp\tax,CONDHIDE+CONDHIDDEN\n\tje\tshort ??condcheck\t\t; If already hidden.\n\n;------\tWe know that the mouse is visible, we must hide it\n;\tbefore we update its position.\n\tcall\tLow_Hide_Mouse\n\n;------\tConditional region check goes here.  If the mouse falls within the \n;\tconditional region, it gets marked as hidden and no other processing\n;\toccurs.\n\ttest\t[MCState],CONDHIDE\n\tje\tshort ??condok\n\n??condcheck:\n\tcmp\tcx,[MouseCXLeft]\t\t; check adjusted x region\n\tjb\tshort ??condok\n\tcmp\tcx,[MouseCXRight]\n\tja\tshort ??condok\n\tcmp\tdx,[MouseCYUpper]\t; check adjusted y region\n\tjb\tshort ??condok\n\tcmp\tdx,[MouseCYLower]\n\tja\tshort ??condok\n\n\tor\t[MCState],CONDHIDDEN\t; flag as conditional hidden\n\tjmp short ??updateend\n\n;------\tThe mouse coordinates and flags pass all of the tests, proceed\n;\twith rendering the mouse.\n??condok:\n\tcall\tLow_Show_Mouse\n\n;------\tFinal clean up and exit.\n??updateend:\n\tmov\t[MouseXOld],cx\n\tmov\t[MouseYOld],dx\n\n??exit:\n\tcmp\t[Mouse_StackPointer],0DEADh\n\tje\t??mouse_stk_ok\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n\n??mouse_stk_ok:\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov ax, [Mouse_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, ax\t\t\t       ; Get Syatem Stack Selector\n\tmov sp, [Mouse_App_Stack_ES]           ; Get Syatem Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\tret\n\tENDP\tMouse_Int\n\n\n\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VGA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVGA_Mouse_Shadow_Buffer C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\tpush\tbp\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tbp , cx\n??restore_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 10\nmov es, ax\nmov al , 'V'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tsi,di\t\t\t\t\t; xchg the source and the dest\n\tmov\tbp , cx\n\tpush\tes\t\t\t\t\t; need to swap es and ds but\n\tpush\tds\t\t\t\t\t;   cant xchg so pop them on the\n\tpop\tes\t\t\t\t\t;   stack and pop them off the\n\tpop\tds\t\t\t\t\t;   wrong way intentionally.\n??store_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,dx\t\t\t\t\t; move past right clipped pixels\n\tadd\tdi,bx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 12\nmov es, ax\nmov al , 'G'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tret\n\n\tENDP\tVGA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n\n\tGLOBAL\tC VGA_Draw_Mouse:FAR\n\tPROC\tVGA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tbx , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , bx\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tbx , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , bx\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 14\nmov es, ax\nmov al , 'A'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tret\nENDP\tVGA_Draw_Mouse\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VESA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVESA_Mouse_Shadow_Buffer C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\t\n\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??restore_loop:\n\tmov\tah,al\n??res_inner_loop:\n\tmov\tch , [si]\n\tmov\t[es:di],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??res_same_page\n\tcall\tnext_vesa_page\n ??res_same_page:\n \tdec\tah\n\tjnz\t??res_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??res_same_page1\n\tcall\tnext_vesa_page\n ??res_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 10\nmov es,ax\nmov al ,'v'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tjmp\t??out\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\tmov\tah,al\n??store_inner_loop:\n\tmov\tch , [es:di]\n\tmov\t[si],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??store_same_page\n\tcall\tnext_vesa_page\n ??store_same_page:\n \tdec\tah\n\tjnz\t??store_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??store_same_page1\n\tcall\tnext_vesa_page\n ??store_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_entry\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 14\nmov es,ax\nmov al ,'e'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\n\tmov\tdx , [ app_vesa_window ] \n\tcall\tset_vesa_window\n\tret\n\n\tENDP\tVESA_Mouse_Shadow_Buffer\n\n\n\n;***************************************************************************\n\n\tGLOBAL\tC VESA_Draw_Mouse:FAR\n\tPROC\tVESA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\tlocal\tapp_vesa_window : word\n\n   \n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tsi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tjnz\t??same_page\n\tcall\tnext_vesa_page\n ??same_page:\n \tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??same_page1\n\tcall\tnext_vesa_page\n ??same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 14\nmov es, ax\nmov al , 's'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nmov di , 10 * 80 + 16\nmov al , 'a'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tmov\tdx , [ app_vesa_window ] \n\tcall\tset_vesa_window\n\tret\n\n\nENDP\tVESA_Draw_Mouse\n\n\n\n;************************************************************************\n\nPROC\tget_vesa_window C near\nuses\tax,bx\n\tmov\tax , 04f05h\n\tmov\tbh , 1\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\t\n\n;************************************************************************\n\nPROC\tset_vesa_window C near\nuses\tax,bx,dx\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]  \t\n\tret\nENDP\t\n\n\n;***************************************************************************\n\nPROC\tset_vesa_page C near\nUSES\tax,bx,dx\n\n\tmov\tbx , dx\n\tshl\tbx , 2\n\tmov\t[ cs: current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tset_vesa_page\n\nPROC\tnext_vesa_page C near\nUSES\tax,bx,dx\n\tmov\tbx , [ cs: current_page ]\n\tadd\tbx , 4\n\tmov\t[ cs:current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n       \tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tnext_vesa_page\n\n\n\n;***********************************************************\nEND\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/NEW/KEYIREAL.BAK",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*\t\t\t\t  (Mouse Routines)\n;*                                                                         *\n;*                    File Name : KEYIREAL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Philip W. Gorrow                         *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;* This file sort of breaks the standard of keeping all of the keyboard    *\n;* and mouse routines isolated.  This is done because the mouse and\t   *\n;* the keyboard share data, and the best way to do this is to put\t   *\n;* them in the same segment.  This should probably be split into several   *\n;* include files to help make the code clearer once it is finally put\t   *\n;* together.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   KeyNum_Translate -- Translates extended keynums to normal keynums\t   *\n;*   Stuff_Key_Word -- Stuffs a word of data into keyboard buffer          *\n;*   Stuff_Key_Num -- Stuffs a key num code into the circular buffer       *\n;*   Keystroke_Interrupt -- Real mode handler of input from the keyboard   *\n;*   Break_Interrupt -- Handles the break key interrupt                    *\n;*   Call_Interrupt_Chain -- Function PM calls to call RM interrupt chain  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tKeyboard driver -- 8086 Assembly portion;\t\t\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   *\n;***************************************************************************\n\n;---------------------------------------------------------------------------\n; Set the assembly directives\n;---------------------------------------------------------------------------\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386N\t\t\t\t; use 386 real mode instructions\nMODEL TINY\t\t\t; code must be tiny so it fits\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keyboard.inc\"\n\nCONDHIDE\t\tEQU\t08000H\t\t; bit for testing conditional region\nCONDHIDDEN\t\tEQU\t04000H\t\t; bit for testing conditional hidden\nRESTORE_VISIBLE_PAGE\tEQU\t0\nSTORE_VISIBLE_PAGE\tEQU\t1\n\n\nGLOBAL\tset_vesa_page \t:near\nGLOBAL\tset_vesa_window :near\nGLOBAL\tget_vesa_window :near\nGLOBAL\tnext_vesa_page\t:near\n\nECHOON\tequ 0\n;---------------------------------------------------------------------------\n; WARNING!!!!  All of the following code segment variables are shared by\n;   the protected mode interrupt.  Do not change these unless you make the\n;   proper changes to KEYSTRUC.INC.  If you do not know what you are doing,\n;   find someone who does!!!\n;---------------------------------------------------------------------------\nCODESEG\n\n;---------------------------------------------------------------------------\n; Begin definition of Keyboard specific variables\n;---------------------------------------------------------------------------\nSoundOn\t\tDW\t1\t; toggled by alt S\nMusicOn\t\tDW\t1\t; toggled by alt M\nKeyFlags\tDD\tREPEATON+CTRLALTTURBO\t; all but repeat for now\n\n\nBreak\t\tDW\t0\n\nKeyMouseMove\tDB\t-1,0,1\n\t\tDB\t-16,0,16\n\nScreenEdge\tDW\t320/2,0\t\t; North\n\t\tDW\t319,0\t\t; North-East\n\t\tDW\t319,138/2\t; East\n\t\tDW\t319,137\t\t; South-East\n\t\tDW\t320/2,137\t; South\n\t\tDW\t0,137\t\t; South-West\n\t\tDW\t0,138/2\t\t; West\n\t\tDW\t0,0\t\t; North-West\n\t\tDW\t320/2,138/2\t; Center\n\n\nBits\t\tDB\t01H,02H,04H,08H,10H,20H,40H,80H\n\nCondPassKey\tDW\t0220H, 0320H, 060CH, 070DH, 066AH\n\t\tDW\t0669H, 0230H, 0330H, 007DH, 017DH\n\t\tDW\t025AH, 035AH, 0200H, 0410H, 046EH\n\t\tDW\t026EH, 007CH\n\nCondPassCond\tDW\tCTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO\n\t\tDW\tCTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON\n\t\tDW\tPAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE\n\t\tDW\tTASKSWITCHABLE, BREAKON\n\nEscRoutine\tDD\t0\t; vector to execute on esc key press (0=none)\n\n; Extended raw keycodes to be converted to Westwood keycodes.\nExtCodes\tDB\t038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H\n\t\tDB\t051H,04DH,035H,01CH,037H\n\t\tDB\t046H\n; The matching Westwood keycodes.\nExtNums\t\tDB\t62,  64,  75,  76,  79,  80,  81,  83,  84,  85\n\t\tDB\t86,  89,  95, 108, 124,  0\n; If extended mapping is disabled, then these codes really are...\nExtRemap\tDB\t60,  58,  99, 104,  92,  91,  93,  96,  98, 101\n\t\tDB\t103, 102, 55,  43, 124,  0\nExtRemapEnd\tDB\t0\n\nExtKeyboard\tDB\t0\t; flag for 101/102-key keyboard\n\n\nKeyBuffer\tDW\t128 DUP(0) ; set to empty\nKeyBufferHead\tDD\t0\t; set to first entry\nKeyBufferTail\tDD\t0\t; set to head for empty buffer\nKeyLock\t\tDW\t0\t; num and caps lock bits\nKeyNums\t\tDB\t127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016\n\t\tDB\t017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032\n\t\tDB\t033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049\n\t\tDB\t050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116\n\t\tDB\t117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093\n\t\tDB\t098,103,099,104,127,127,127,122,123\n\nKeysCapsLock\tDB\t0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0\nKeysNumLock\tDB\t0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0\nKeysUpDown\tDB\t16 DUP(0) ; set to all keys up\nKeyStream\tDB\t16 DUP(0) ; set to all keys up\nPassCount\tDW\t0\nKeyStreamIndex\tDW\t0\nLastKeyE0\tDB\t0\nLastKeyE1\tDB\t0\n\n;\n; Westwood key number values of keys to pass through\n;\n;\t\t\tCAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT,\n;\t\t\tRIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN\nPassAlways\tDB\t30, 44, 57, 58, 60, 62, 64, 90, 128, 128\nPassAlwaysEnd\tDB\t128\t\t; invalid code to END PassAlways\nCtrlFlags\tDB\t0\n\nBuffer\t\tDW\t?\nTime\t\tDW\t?\n\nADJUST\t= 1\t\t\t; do not modify DRD\n\nXYAdjust\tDB\t-ADJUST, -ADJUST\t; 91 -> upleft\n\t\tDB\t-ADJUST,  0\t\t; 92 -> left\n\t\tDB\t-ADJUST,  ADJUST\t; 93 -> downleft\n\t\tDB\t 0,  0\t\t\t; 94 illegal\n\t\tDB\t 0,  0\t\t\t; 95 illegal\n\t\tDB\t 0, -ADJUST\t\t; 96 -> up\n\t\tDB\t 0,  0\t\t\t; 97 illegal (center)\n\t\tDB\t 0,  ADJUST\t\t; 98 -> down\n\t\tDB\t 0,  0\t\t\t; 99 illegal\n\t\tDB\t 0,  0\t\t\t; 100 illegal\n\t\tDB\t ADJUST, -ADJUST\t; 101 -> upright\n\t\tDB\t ADJUST,  0\t\t; 102 -> right\n\t\tDB\t ADJUST,  ADJUST\t; 103 -> downright\n\tEdgeConv\t\tDW\t8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7\n\tMouseUpdate\t\tDW\t0\n\tMouseX\t\t\tDW\t0,0\n\tLocalMouseX\t\tDW\t0\n\tMouseY\t\t\tDW\t0,0\n\tLocalMouseY\t\tDW\t0\n\tIsExtKey\t\tDB\t0\n\tExtIndex\t\tDW\t0\n\n\tKeyOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tKeyOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\t\t\n\tKeyOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tKeyCodeOffset\t\tDW\tRM_Keystroke_Interrupt\t; Offset of the code in the RM stuff.\n\tCallKeyRMIntOffset\tDW\tCall_Interrupt_Chain\t; Offset of function to call DOS timer interrupt.\n\tCallKeyRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedKeyInt\t\tDD\t0\n\n\tBrkOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tBrkOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\t\t\n\tBrkOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tBrkCodeOffset\t\tDW\tRM_Break_Interrupt\t; Offset of the code in the RM stuff.\n\tCallBrkRMIntOffset\tDW\t0\n\tCallBrkRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedBrkInt\t\tDD\t0\n\tKeyIntDisabled\t\tDD\t0\n\n\tDbgOldPMIOffset\t\tDD\t0\t; The origianl PM interrupt offset\t\t\n\tDbgOldPMISelector\tDD\t0\t; The original PM interrupt segment.\n\n;---------------------------------------------------------------------------\n; Begin definition of Mouse Specific Variables for real mode\n;---------------------------------------------------------------------------\nButton\t\t\tDB\t0\t; current value of the mouse button\nMDisabled\t\tDB\t0\t; Is the mouse driver disabled\nMInput\t\t\tDB\t1\t; Defaults to mouse input allowed.\nAdjust\t\t\tDW\t0\t; flag to adjust coordinates if necessary\nMouseStepX\t\tDW\t0\t; step values if the mouse moves at\nMouseStepY\t\tDW\t0\t;   more than one pixel at a time\nMouseOffsetX\t\tDW\t0\t; Fractional step values used if a mouse\nMouseOffsetY\t\tDW\t0\t;   moves at less than one pixel at a time\nMState\t\t\tDW\t0,0\t; Tracks if mouse is hidden (TRUE) or not (FALSE)\nMouseXOld     \t\tDW\t0\t; Holds last MouseX and MouseY to determine if \nMouseYOld     \t\tDW\t0\t;   mouse needs to be redrawn\nMCState\t\t\tDW\t0\t; Tracks if mouse conditional hidden (TRUE) or not\nMouseCXLeft\t\tDW\t0,0\t; Conditional hide mouse left x position\nMouseCYUpper\t\tDW\t0,0\t; Conditional hide mouse top y position\nMouseCXRight\t\tDW\t0,0\t; Conditional hide mouse right x position\nMouseCYLower\t\tDW\t0,0\t; Conditional hide mouse lower y position\nMouseCursor   \t\tDD\t0\t; Pointer to the mouse cursor to draw\nMouseCursorSize\t\tDW\t0\t; Pointer to buffer mouse is saved in\nMouseBuffer   \t\tDD\t0\t; Pointer to buffer mouse is saved in\nMouseXHot     \t\tDW\t0,0\t; Offset to mouse's x hot spot\nMouseYHot     \t\tDW\t0,0\t; Offset to mouse's y hot spot\nMouseBuffX\t\tDW\t0,0\t; X position background was saved at\nMouseBuffY\t\tDW\t0,0\t; Y position background was saved at\nMouseBuffW\t\tDW\t0,0\t; Width of the region saved for mouse\nMouseBuffH\t\tDW\t0,0\t; Height of the region saved for mouse\nMouseWidth\t\tDW\t0,0\t; Mouse cursor theoretical width\nMouseHeight\t\tDW\t0,0\t; Mouse cursor theoretical height\nMouseCodeOffset\t\tDW\tRM_Mouse_Interrupt\t; Offset of the code in the RM stuff.\nMouseRight\t\tDW\t0,0\nMouseBottom\t\tDW\t0,0\n\n\nShadowPtr\t\tdw\t0\nDrawMousePtr \t\tdw\t0\n\nVGAMouseDraw\t\tdw\tVGA_Draw_Mouse\nVGAMouseShadow\t\tdw\tVGA_Mouse_Shadow_Buffer\n\nVESAMouseDraw\t\tdw\tVESA_Draw_Mouse\nVESAMouseShadow\t\tdw\tVESA_Mouse_Shadow_Buffer\n\nVesaPtr\t\t\tdd\t0\t\nbanktable\t\tdd      8 dup ( 0 )\nAdjust_XPos\t\tdw \t0 , 0\nAdjust_YPos\t\tdw \t0 , 0 \n\n\t\talign 2\nKeyboard_App_Stack_ES\tdw 0\t\t; This the System Stack Offsset\nKeyboard_App_Stack_SS\tdw 0\t\t; This the System Stack Selector\nKeyboard_StackPointer\tdw 0DEADh\t; We Create a Local Application\nKeyboard_Stack\t\tdw 255 dup (0)\nKeyboard_StackStart\tdw 0\n\nMouse_State\t\tdw 0\t\t; Mouse Temp Variable\nMouse_Cond\t\tdw 0\t\t; Mouse Temp Variable\nMouse_App_Stack_ES\tdw 0\t\t; This the System Stack Offsset\nMouse_App_Stack_SS\tdw 0\t\t; This the System Stack Selector\nMouse_StackPointer\tdw 0DEADh\t; We Create a Local Application\nMouse_Stack\t\tdw 255 dup (0)\nMouse_StackStart\tdw 0\n\n\n\ncurrent_page\t\tdw\t0\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Translates extended keynums to normal keynums\t   *\n;*                                                                         *\n;* INPUT:\tUWORD the keynum to translate\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated keynum                                 *\n;*                                                                         *\n;* PROTO:\tUWORD KeyNum_Translate(UWORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tKeyNum_Translate:FAR\n\tPROC\tKeyNum_Translate C FAR \n\tUSES\tcx,di,es,ds\n\tARG\tkeycode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\tmov\tes,ax\t\t\t\t; set es up for scansb\n\n\tmov\tax,[keycode]\n\ttest\t[WORD PTR KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\tmov\tcx,ExtRemap-ExtNums\n\tmov\tdi,OFFSET ExtNums\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tdi,OFFSET ExtRemapEnd\n\tdec\tdi\n\tsub\tdi,cx\n\tmov\tal,[es:di]\n??fini:\n\tret\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(WORD code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_WORD:FAR\n\tPROC\tStuff_Key_WORD C FAR \n\tUSES\tsi,bx,ds\n\tARG\tcode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\tax,[WORD PTR KeyBufferTail]\n\tmov\tsi,ax\n\tadd\tax,2\n\tand\tax,0FFh\t\t\t\t; New KeyBufferTail value.\n\tcmp\t[WORD PTR KeyBufferHead],ax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[KeyBuffer+si],bx\t\t; Record the keystroke.\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\n\tret\n\n??noroom:\n\tmov\tax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(WORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_Num:FAR\n\tPROC\tStuff_Key_Num C FAR \n\tUSES\tbx,cx,dx,di,si,ds\n\tARG\tkeycode:WORD\n\tLOCAL\ttail:WORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n\tpushf\n\tcli\t\t\t\t; disable interrupts\n\n\t; Abort key recognition if in record mode and unable\n\t; to output key due to simultaneous DOS operation.\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\tax,[MouseX]\n\tmov\t[LocalMouseX],ax\n\tmov\tax,[MouseY]\n\tmov\t[LocalMouseY],ax\n\n??cando:\n\tmov\tax,[keycode]\t\t; get the code\n\tor\tax,ax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[WORD PTR KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[WORD PTR KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tbx,1\t\t\t; double for WORD index\n\tadd\tbx,OFFSET XYAdjust\n\tmov\tax,[bx]\t\t\t; get x,y add value\n\n\tmov\tbl,ah\n\tcbw\n\txchg\tax,bx\n\tcbw\n\txchg\tax,bx\t\t\t; AX = mouse x delta, BX = mouse y delta\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tdx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tdx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tbx,dx\t\t\t; add speed for y index\n\tmov\tbl,[KeyMouseMove+bx] \t; get speed for y delta\n\txchg\tax,bx\t\t\t; swap with ax to extend sign\n\tcbw\n\txchg\tax,bx\n\txchg\tbx,dx\t\t\t; save mouse y delta\n\tadd\tbx,ax\t\t\t; add speed for x index\n\tmov\tal,[KeyMouseMove+bx]\t; get speed for x delta\n\tcbw\n\txchg\tbx,dx\t\t\t; restore mouse y delta\n\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tbx,011b\t\t\t; Y = 1, 0, 3\n\tand\tax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tbx,011b\t\t\t; Y = 3, 0, 1\n\tand\tax,011b\t\t\t; X = 3, 0, 1\n\tshl\tbx,1\n\tshl\tbx,1\n\tor\tbx,ax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tbx,1\n\tmov\tbx,[EdgeConv+bx]\n\tshl\tbx,1\n\tshl\tbx,1\n\tmov\tax,[ScreenEdge+bx]\t; New absolute X\n\tmov\tbx,[ScreenEdge+bx+2] ; New absolute Y\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\tax,ax\n\tmov\t[LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tbx,bx\n\tmov\t[LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\tmov\t[MouseX],ax\n\tmov\t[MouseY],bx\n\tcmp\t[MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n\n\tcall\tLow_Hide_Mouse\n\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\tax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],ax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tsi,[WORD KeyBufferTail]\n\tmov\t[tail],si\t\t; Safety record.\n\tmov\tdi,[WORD PTR KeyBufferHead]\n\n\t; Record the base keycode (if there is room).\n\tpush\tax\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\tax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tpush\t[LocalMouseX]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tpush\t[LocalMouseY]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tbx,0101h\t\t; Bit control tools.\n\tmov\tax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[WORD PTR KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tmov\tcl,3\n\tshr\tdi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[KeysUpDown+di]\n\tje\tshort ??notalready\n\ttest\t[WORD PTR KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[KeysUpDown+di],bh\t; Force key bit to zero.\n\tor\t[KeysUpDown+di],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\tax,1\n\tjmp short ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\tax,[tail]\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\t\t\t; Signal an error.\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tStuff_Key_Num\n;***********************************************************\n\n\n\n;***************************************************************************\n;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard       *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Keystroke_Interrupt\n\tGLOBAL\tC Keystroke_Interrupt:FAR\n\tPROC\tKeystroke_Interrupt C FAR \n\nIF 0\n\tpush\tax\n\tinc\tax\n\tpop\tax\n\tiret\n\nELSE\n\tpush\tax\n\tpush\tbx\n\tpush\tcx\n\tpush\tdi\n\tpush\tds\n\tpush\tdx\n\tpush\tes\n\tpush\tsi\n\tcld\n\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tds,ax\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov cx, ss\t\t\t\t; get SS\n\tmov [Keyboard_App_Stack_ES], sp\t\t; Protect ES\n\tmov [Keyboard_App_Stack_SS], cx\t\t; Protect SS\n\tlea dx, [Keyboard_StackStart ]\t\t; Compute Local Stack size\n\tand dx, -2;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov sp, dx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n\tcmp\t[WORD PTR PMIssuedKeyInt],0; Check to see if PM made Int call.\n\tmov\t[WORD PTR PMIssuedKeyInt],0; Make it false.\t\t\n\tjne\t??passcode\t; if so, just call Int Chain.\n\n\n\tmov\tdx,[WORD PTR KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\tmov\tax,040H\t\t\t; BIOS segment\n\tmov\tes,ax\t\t\t; put in es\n\ttest\t[BYTE PTR es:017H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR es:017H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR es:096H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tes,ax\n\n\tcld\t\t\t\t; clear direction flag for strings\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tbx,0101H\t\t; set key to a make by default\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\n\t;\n\t; New CODE to montior key stream\n\t;\n\tmov\tbx,[KeyStreamIndex]\n\tmov\t[KeyStream+bx],al\n\tinc\tbx\n\tand\tbx,15\n\tmov\t[KeyStreamIndex],bx\n\tmov\tbx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[LastKeyE1]\t\t; yes, dec the count\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[IsExtKey],TRUE\t; it is an extended key\n\tmov\tdi,OFFSET ExtCodes\t; get offset of extended codes table\n\tmov\tcx,(ExtNums-ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\tmov\tal,[(ExtNums - ExtCodes) - 1 + di] ; get the match\n\tmov\t[IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tdi,ax\t\t\t; use code as an index\n\tand\tdi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[KeyNums+di]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[KeysUpDown+8],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[KeysUpDown+7],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[KeysUpDown + 7],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\tax\n\tcall\tKeyNum_Translate\n\tadd\tsp,2\n\n;------\tSet the shift bit if necessary.\n\ttest\t[KeysUpDown+5],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[KeysUpDown+7],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tshr\tdi,1\n\tshr\tdi,1\n\tshr\tdi,1\n\tmov\tbx,ax\n\tand\tbx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[Bits+bx]\t\t; get the bit to test\n\ttest\t[KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[KeysCapsLock+di]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[KeysNumLock+di]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\t\n\t\t\t\t\t; keyboard buffer.\n\ttest\tdx,DEBUGINT\n\tjz\t??not_toggle \n\n\nIF DEBUG\n\tcmp\t[KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\tcmp\tax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\tax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\tax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\t\n\tcmp\tax,125\n\tjne\t??not_toggle\n\tmov\t[KeyIntDisabled],1\n\tjmp\t??absorbcode\nENDIF\n\n??not_toggle:\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\tax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\tax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\tax,0230h\n\tje\tshort ??breaker\n\tcmp\tax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n\tcmp\tax,0420H\t\t; is this an alt s\n\tjne\tshort ??checkmusic\t; toggle the Sound variable\n\tpush\tax\n\tmov\tax,[SoundOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??checkmusic:\n\tcmp\tax,0434H\t\t; is this an alt m\n\tjne\tshort ??esc\t\t; toggle the Music variable\n\tpush\tax\n\tmov\tax,[MusicOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??esc:\n\n\tpush\tax\n\tcall\tStuff_Key_Num\n\tpop\tax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\tax\n\tcall\t[EscRoutine]\n\tpop\tax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tdi,OFFSET PassAlways\t; get offset to table\n\tmov\tcx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1\n\trepne\tscasb\t\t\t; look for a match\n\tor\tcx,cx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n\n\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tdi,OFFSET CondPassKey\t; get offset to cond key table\n\tmov\tcx,(CondPassCond-CondPassKey) ; get number of entries\n\tshr\tcx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(CondPassCond - CondPassKey) - 2 + di]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tdx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\n\tinc\t[cs:PassCount]\n\n;mov   ax , 0B000h\n;mov   es, ax \n;inc   [BYTE PTR es : 40h]\n\n\t; Now it is time to set up for the call to the System Keyboard\n\t; interrupt handler.\n\t; 1 -Restore System Stack Pointer Selector before exit Interrupt\n\t; 2- We Create a Returning Point from Interrupt by Push A\n \t;    Interupt Stack Frame into the Stack Pointer\n\t; 3- We make a Far jump to the interuupt handler\n\tcmp [Keyboard_StackPointer],0DEADh\n\tje  ??stackok\n\tmov [BYTE PTR 0B000h:0h],'&'\n??stackok:\n\tcli\t\t\t\t       ; disable Interrupts\n\tmov dx, [Keyboard_App_Stack_SS]       \n\tmov ss, dx\t\t\t       ; Get System Stack Selector\n\tmov sp, [Keyboard_App_Stack_ES]      ; Get System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n\tlea\tdx, [??Call_Back_Keyboard]   ; Get Return address offset\n \tpushf\t\t\t\t      ; push flags\t\n\tpush\tcs\t\t\t      ; push Code segment\n\tpush\tdx\t\t\t      ; push Offset\n\n\t; Now we need to simulate an interrup call by using ired\n\t; because we still want to come back here from the\n\t; Old Keyboard interrupt handle.\n\tpushf\n\tpush\t[word ptr KeyOldRMI + 2] \t; push orig segment.\n\tpush    [word ptr KeyOldRMI]   \t\t; push orig offset.\n\tiret\t \t\t        \t; call interrupt\t\n\n??absorbcode:\n\n;mov   ax , 0B000h\n;mov   es, ax \n;inc   [BYTE PTR es : 0h]\n\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tax,040h\t\t\t\t; BIOS paragraph is always @ 040h\n\tmov\tes,ax\t\t\t\t; put in es as BIOS paragraph\n\tmov\tal,[es:96h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[es:96h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\n\tcmp [Keyboard_StackPointer],0DEADh\n\tje  ??stackok2\n\tmov [BYTE PTR 0B000h:0h],'&'\n??stackok2:\n\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov dx, [Keyboard_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, dx\t\t\t       ; Get Syatem Stack Selector\n\tmov sp, [Keyboard_App_Stack_ES]        ; Get Syatem Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n??Call_Back_Keyboard:\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tiret\t\nENDIF\n\n\tENDP\tKeystroke_Interrupt\n\n;***************************************************************************\n;* Break interrupt routines begin here!\n;***************************************************************************\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles the break key interrupt                      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Break_Interrupt\n\tGLOBAL\tC Break_Interrupt:FAR\n\tPROC\tBreak_Interrupt C FAR\n\n\n\tpushf\n\tpush\tax\n\tpush\tes\n\n\tmov\tax,0B000h\t\t; ES:DI = Mono RAM address.\n\tmov\tes,ax\n\tinc\t[BYTE PTR es:0]\n\t\t\n\n\tpop\tes\n\tpop\tax\n\tpopf\n\n\n\tiret\t\n\n\tENDP\tBreak_Interrupt\n\n;**************************************************************************\n;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                                  *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nCall_Interrupt_Chain:\n\tpushf\n\tcall\tKeystroke_Interrupt ;[KeyOldRMI]\n\tretf\n\n;----------------------------------------------------------------------------\n; LOW_HIDE_MOUSE:\n;\n; This function hides the mouse cursor on the screen if it was shown.  It \n; will not hide the mouse if it is already hidden.\n;\n; PROTOTYPE:\n;\n;\tVOID Low_Hide_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Hide_Mouse:FAR\n\tPROC\tLow_Hide_Mouse C FAR \n\tUSES\tax,bx,cx,dx,ds\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n   \tcmp\t[MDisabled],0\t\t; check if mouse is disabled\n\tjne\tshort ??end\n\n   \tcmp\t[MState],0\t\t; check if it was hidden before\n\tjne\tshort ??endnodraw\t\t; no need to hide again\n\n;------\tMove the saved graphic buffer to the seenpage to hide the mouse.\n;\tcall\tBuffer_To_Page C,[buffx],[buffy],[buffw],[buffh],[MouseBuffer],SEENPAGE\n\tmov\tax,RESTORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tRecord that the mouse has been hidden.\n??endnodraw:\n\tadd\t[MState],1\n\tadc\t[MState],0\n\n??end:\n\tret\n\n\tENDP\tLow_Hide_Mouse\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; LOW_SHOW_MOUSE:\n;\n; This function displays the mouse cursor on the screen if it was hidden.\n;\n; PROTOTYPE:\n;\tVOID Low_Show_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Show_Mouse:FAR\n\tPROC\tLow_Show_Mouse C FAR \n\tUSES \tax,bx,cx,dx,si,di,ds,es\n\tLOCAL\tmousex:WORD\t\t; Draw X position.\n\tLOCAL\tmousey:WORD\t\t; Draw Y position.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n;-----\tDon't show the mouse if it is not hidden, disabled.\n\tcmp\t[MDisabled],0\t\t; is the mouse disabled\n\tjne\t??exit\t\t\t; if so then exit\n\n\tcmp\t[MState],0\t\t; is the mouse already visible\n       \tje\t??exit\t\t\t; if so then exit\n\n\tdec\t[MState]\n\tcmp\t[MState],0\t\t; can the mouse be shown\n       \tjne\tshort ??exit\n\n;------\tDetermine the drawing position of the mouse.\n\tmov\tcx,[MouseWidth]\t\t; Theoretical buffer width (pixel).\n\tmov\tdx,[MouseHeight]\t; Theoretical buffer height (pixel).\n\n\tmov\tax,[MouseX]\n;\tsub\tax,[MouseXHot]\n\tmov\t[mousex],ax\t\t; Draw X pixel.\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??xnotneg\n;\tadd\tcx,ax\t\t\t; Reduce width accordingly.\n;\tmov\tax,0\n??xnotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n\tmov\tbx,[MouseY]\n;\tsub\tbx,[MouseYHot]\n\tmov\t[mousey],bx\t\t; Draw Y pixel.\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??ynotneg\n;\tadd\tdx,bx\t\t\t; Reduce height of mouse accordingly.\n;\tmov\tbx,0\n??ynotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n;------\tDetermine the theoretical coordinates and dimensions of the\n;\tarea the mouse shape will be rendered upon.\n\tmov\t[MouseBuffX],ax\n\tmov\t[MouseBuffY],bx\n\tmov\t[MouseBuffW],cx\n\tmov\t[MouseBuffH],dx\n\n;------\tMove the area that will be drawn upon, to the graphic buffer.\n\tmov\tax,STORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tDraw the mouse shape to the seenpage.\n\tpush\t[mousey]\n\tpush\t[mousex]\n\tpush\tcs\n\tcall\t[ DrawMousePtr ]\n\tadd\tsp,4\n??exit:\n\tret\n\n\tENDP\tLow_Show_Mouse\n\n;----------------------------------------------------------------------------\n;----------------------------------------------------------------------------\n\tGLOBAL\tC Mouse_KeyNum:FAR\n\tPROC\tMouse_KeyNum C FAR \n\tUSES\tbx\n\tARG\tstate:WORD\t\t; Current mouse state.\n\tLOCAL\tkeynum:WORD\t\t; Determined keynum.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\t[keynum],KN_MOUSE_MOVE\t; Presume just a mouse move.\n\tmov\tbx,[state]\n\tmov\tax,bx\n\txor\tbl,[Button]\t\t; Bits of state change.\n\tje\tshort ??fini\n\tmov\t[Button],al\t\t; Record new mouse state.\n\n\ttest\tbl,0010b\n\tje\tshort ??notright\n\tmov\t[keynum],KN_RMOUSE\n\ttest\tal,0010b\n\tjne\tshort ??notright\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notright:\n\n; DRD\n; note:  the left mouse button has priority over the right mouse button\n; this should be changed at a later date to process them independently\n\n\ttest\tbl,0001b\n\tje\tshort ??notleft\n\tmov\t[keynum],KN_LMOUSE\n\ttest\tal,0001b\n\tjne\tshort ??notleft\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notleft:\n\n??fini:\n\tmov\tax,[keynum]\n\tret\n\n\tENDP\tMouse_KeyNum\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; MOUSE_INT:\n;\n; This routine is called automatically when the Mouse_Int is installed.  It\n; automatically updates the global variables stored in the code segment so\n; that the mouse information is automatically known at all times.\n;\n; INPUTS (from int):\tAX = condition mask ( bit 0 == cursor position chg,\n;\t\t\t\t\t      bit 1 == left button press,\n;\t\t\t\t\t      bit 2 == left button release,\n;\t\t\t\t\t      bit 3 == right button press,\n;\t\t\t\t\t      bit 4 == right button release,\n;\t\t\t\t\t      5-15  == not used )\n;\t\t\tBX = button state   ( bit 0 == left button down,\n;\t\t\t\t\t      bit 1 == right button down,\n;                                             bit 2 == middle button down.\n;\t\t\t\t\t      3-15  == not used )\n;\t\t\tCX = cursor coordinate (horizontal axis)\n;\t\t\tDX = cursor coordinate (vertical axis)\n;\t\t\tDI = horizontal mouse count (mickeys)\n;\t\t\tSI = vertical mouse count (mickeys)\n;\n; RETURNS:\t\tnone\n;\n; MODIFIES:\t\tmodifies the variables _Button, _ButtonChange,\n;\t\t\t_MouseX,_MouseY,_ButtonLatch\n;\n; PROTOTYPE:\n;\tThis routine is called from an interrupt.\n;----------------------------------------------------------------------------\nlabel RM_Mouse_Interrupt\n\tPROC\tMouse_Int C FAR \n\tUSES\tax,bx,cx,dx,ds,si,es,di\n\tLOCAL\tcond:WORD\t\t; Local copy of mouse event.\n\tLOCAL\tstate:WORD\t\t; Local copy of button state.\n\n\tmov\t[cs:Mouse_State],bx\n\tmov\t[cs:Mouse_Cond],ax\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov bx, ss\t\t\t\t; get SS\n\tmov [Mouse_App_Stack_ES], sp\t\t; Protect ES\n\tmov [Mouse_App_Stack_SS], bx\t\t; Protect SS\n\tlea bx, [Mouse_StackStart ]\t; Compute Local Stack size\n\tand bx, -2;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov sp, bx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n;------\tProcess the mouse interrupt only if the mouse is enabled (whether\n;\tpresent or not).\n\tcmp\t[MDisabled],0\n\tjne\t??exit\n\n\tcmp\t[MInput],0\n\tje\t??exit\n\n\n;------ This was added because of missing mouse presses and\n;\treleases during a mouse update.\n\tmov\tax,[Mouse_Cond]\n\tand\tax,0001EH \t; bits for left and right press and release\n\tjne\tshort ??dopress_release\n\n\tcmp\t[MouseUpdate],0 ; if mouse move and mouse updating exit\n\tjne\t??exit\n\n??dopress_release:\n\n;------\tIn EEGA mode mouse X coordinates as 0..639.  Make adjustment\n;\tto keep within 0..319 range.\n\tcmp\t[Adjust],1\t\t; if the x coordinate is returned\n\tjne\tshort ??noadjust\t; incorrectly then\n\tshr\tcx,1\t\t\t; adjust x coord from 640 pixel screen\n??noadjust:\n\n\n; scale mouse posX and PosY\n;\tcmp\t[Adjust_XPos] , 0\n;\tjz\tshort ??no_scaleX\n;\tpush\tdx\n;\tmov\tax , [MouseRight]\n;\timul\tcx\n;\tidiv\t[Adjust_XPos]\n;\tmov\tcx , ax\n;\tpop\tdx\n??no_scaleX:\n;\tcmp\t[Adjust_YPos] , 0\n;\tjz\tshort ??no_scaleY\n;\tmov\tax , [MouseBottom]\n;\timul\tdx\n;\tidiv\t[Adjust_YPos]\n;\tmov\tdx , ax\n??no_scaleY:\n\n;------\tKeep mouse within screen bounds.\n\tcmp\tcx,[MouseRight]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundX_ok\t\t; force it to stay at least one pixel\n\tmov\tcx,[MouseRight]\t\t\t; on the screen\n\tdec\tcx\n??boundX_ok:\n\tcmp\tdx,[MouseBottom]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundY_ok\t\t; force it to stay at least one pixel\n\tmov\tdx,[MouseBottom]\t\t\t; on the screen\n\tdec\tdx\n??boundY_ok:\n\n\tIF 0\n;------\tRemap the middle button to equal the right button.\n\ttest\tbx,04h\n\tje\t??noremap\n\tor\tbx,0010b\t\t; Set the right button bit.\n??noremap:\n\tENDIF\n\n\tmov\t[MouseX],cx\t\t; and store in mouse x\n\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\ttest\t[KeyFlags],KEYMOUSE\n\tjne\tshort ??nostuffit\n\n\tcall\tMouse_KeyNum C,[Mouse_State]\t; Convert mouse state to key number code.\n\tcall\tStuff_Key_Num C,ax\t; Record mouse keynumber code.\n??nostuffit:\n\n\n\n;------ The check for Mouse in the middle of updating CAN NOT BE MOVED\n;\tany farther up because mouse presses and releases will be LOST!!\n \tcmp\t[MouseUpdate],0\n\tjne\t??exit\n;??jexit:\n;\tjmp\t??exit\n\n\nchristopher:\n??chkxy:\n\n;------\tSignal that no mouse updating can occur at this time.\n;\tcmp\t[_MouseUpdate],0\n;\tjne\t??exit\n;\tmov\t[_MouseUpdate],1\n\n;------\tPerform any X movement grid adjustment.\n\tcmp\t[MouseStepX],0\t\t; are we stepping on the X?\n\tje\tshort ??no_x_step\t\t; no x\n\tmov\tax,cx\t\t\t; get current x_pixel\n\tmov\tcx,dx\t\t\t; save dx - it is trashed by idiv\n\tsub\tax,[MouseOffsetX]\t; get offset difference\n\tmov\tbx,[MouseStepX]\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step X\n\timul\tbx\t\t\t; ax = div * Step X\n\tadd\tax,[MouseOffsetX]\t; normalize to region offset\n\tmov\tdx,cx\t\t\t; restore dx (new MouseY)\n\tmov\tcx,ax\t\t\t; set cx (new MouseX)\n??no_x_step:\n\n;------\tPerform any Y movement grid adjustment.\n\tcmp\t[MouseStepY],0\t\t; are we stepping on the Y\n\tje\tshort ??no_step\t\t; no y\n\tmov\tax,dx\t\t\t; get current y_pixel\n\tsub\tax,[MouseOffsetY]\t; get offset difference\n\tmov\tbx,[MouseStepY]\t\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step Y\n\timul\tbx\t\t\t; ax = div * Step Y\n\tadd\tax,[MouseOffsetY]\t; normalize to region offset\n\tmov\tdx,ax\t\t\t; set dx (new MouseY)\n??no_step:\n\n;------ Here is where we store the new MouseX and MouseY values\n;\tmov\t[MouseX],cx\t\t; and store in mouse x\n;\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\n;------\tIf the mouse is hidden or its position hasn't changed, then\n;\tperform no action.\n\tcmp\t[MState],0\n\tjne\tshort ??updateend\n\tcmp\t[MouseXOld],cx\n\tjne\tshort ??doit\n\tcmp\t[MouseYOld],dx\n\tje\tshort ??updateend\n??doit:\n\n;------\tAt this point we KNOW the mouse has moved.\n\tmov\tax,[MCState]\n\tand\tax,CONDHIDE+CONDHIDDEN\n\tcmp\tax,CONDHIDE+CONDHIDDEN\n\tje\tshort ??condcheck\t\t; If already hidden.\n\n;------\tWe know that the mouse is visible, we must hide it\n;\tbefore we update its position.\n\tcall\tLow_Hide_Mouse\n\n;------\tConditional region check goes here.  If the mouse falls within the \n;\tconditional region, it gets marked as hidden and no other processing\n;\toccurs.\n\ttest\t[MCState],CONDHIDE\n\tje\tshort ??condok\n\n??condcheck:\n\tcmp\tcx,[MouseCXLeft]\t\t; check adjusted x region\n\tjb\tshort ??condok\n\tcmp\tcx,[MouseCXRight]\n\tja\tshort ??condok\n\tcmp\tdx,[MouseCYUpper]\t; check adjusted y region\n\tjb\tshort ??condok\n\tcmp\tdx,[MouseCYLower]\n\tja\tshort ??condok\n\n\tor\t[MCState],CONDHIDDEN\t; flag as conditional hidden\n\tjmp short ??updateend\n\n;------\tThe mouse coordinates and flags pass all of the tests, proceed\n;\twith rendering the mouse.\n??condok:\n\tcall\tLow_Show_Mouse\n\n;------\tFinal clean up and exit.\n??updateend:\n\tmov\t[MouseXOld],cx\n\tmov\t[MouseYOld],dx\n\n??exit:\n\tcmp\t[Mouse_StackPointer],0DEADh\n\tje\t??mouse_stk_ok\n\tmov\t[BYTE PTR 0B000h:0h],'#'\n\n??mouse_stk_ok:\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov ax, [Mouse_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, ax\t\t\t       ; Get Syatem Stack Selector\n\tmov sp, [Mouse_App_Stack_ES]           ; Get Syatem Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\tret\n\tENDP\tMouse_Int\n\n\n\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VGA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVGA_Mouse_Shadow_Buffer C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\tpush\tbp\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tbp , cx\n??restore_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 10\nmov es, ax\nmov al , 'V'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tsi,di\t\t\t\t\t; xchg the source and the dest\n\tmov\tbp , cx\n\tpush\tes\t\t\t\t\t; need to swap es and ds but\n\tpush\tds\t\t\t\t\t;   cant xchg so pop them on the\n\tpop\tes\t\t\t\t\t;   stack and pop them off the\n\tpop\tds\t\t\t\t\t;   wrong way intentionally.\n??store_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,dx\t\t\t\t\t; move past right clipped pixels\n\tadd\tdi,bx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 12\nmov es, ax\nmov al , 'G'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tret\n\n\tENDP\tVGA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n\n\tGLOBAL\tC VGA_Draw_Mouse:FAR\n\tPROC\tVGA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tbx , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , bx\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tbx , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , bx\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 14\nmov es, ax\nmov al , 'A'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tret\nENDP\tVGA_Draw_Mouse\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VESA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVESA_Mouse_Shadow_Buffer C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\t\n\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??restore_loop:\n\tmov\tah,al\n??res_inner_loop:\n\tmov\tch , [si]\n\tmov\t[es:di],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??res_same_page\n\tcall\tnext_vesa_page\n ??res_same_page:\n \tdec\tah\n\tjnz\t??res_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??res_same_page1\n\tcall\tnext_vesa_page\n ??res_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 10\nmov es,ax\nmov al ,'v'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tjmp\t??out\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\tmov\tah,al\n??store_inner_loop:\n\tmov\tch , [es:di]\n\tmov\t[si],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??store_same_page\n\tcall\tnext_vesa_page\n ??store_same_page:\n \tdec\tah\n\tjnz\t??store_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??store_same_page1\n\tcall\tnext_vesa_page\n ??store_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_entry\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 14\nmov es,ax\nmov al ,'e'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\n\tmov\tdx , [ app_vesa_window ] \n\tcall\tset_vesa_window\n\tret\n\n\tENDP\tVESA_Mouse_Shadow_Buffer\n\n\n\n;***************************************************************************\n\n\tGLOBAL\tC VESA_Draw_Mouse:FAR\n\tPROC\tVESA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\tlocal\tapp_vesa_window : word\n\n   \n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tsi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tjnz\t??same_page\n\tcall\tnext_vesa_page\n ??same_page:\n \tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??same_page1\n\tcall\tnext_vesa_page\n ??same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 14\nmov es, ax\nmov al , 's'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nmov di , 10 * 80 + 16\nmov al , 'a'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tmov\tdx , [ app_vesa_window ] \n\tcall\tset_vesa_window\n\tret\n\n\nENDP\tVESA_Draw_Mouse\n\n\n\n;************************************************************************\n\nPROC\tget_vesa_window C near\nuses\tax,bx\n\tmov\tax , 04f05h\n\tmov\tbh , 1\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\t\n\n;************************************************************************\n\nPROC\tset_vesa_window C near\nuses\tax,bx,dx\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]  \t\n\tret\nENDP\t\n\n\n;***************************************************************************\n\nPROC\tset_vesa_page C near\nUSES\tax,bx,dx\n\n\tmov\tbx , dx\n\tshl\tbx , 2\n\tmov\t[ cs: current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tset_vesa_page\n\nPROC\tnext_vesa_page C near\nUSES\tax,bx,dx\n\tmov\tbx , [ cs: current_page ]\n\tadd\tbx , 4\n\tmov\t[ cs:current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n       \tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tnext_vesa_page\n\n\n\n;***********************************************************\nEND\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/NEW/KEYIREAL.IBN",
    "content": "\tDB  001h,000h,001h,000h,011h,000h,000h,000h,000h,000h,0FFh,000h,001h,0F0h,000h\n\tDB  010h,0A0h,000h,000h,000h,03Fh,001h,000h,000h,03Fh,001h,045h,000h,03Fh,001h\n\tDB  089h,000h,0A0h,000h,089h,000h,000h,000h,089h,000h,000h,000h,045h,000h,000h\n\tDB  000h,000h,000h,0A0h,000h,045h,000h,001h,002h,004h,008h,010h,020h,040h,080h\n\tDB  020h,002h,020h,003h,00Ch,006h,00Dh,007h,06Ah,006h,069h,006h,030h,002h,030h\n\tDB  003h,07Dh,000h,07Dh,001h,05Ah,002h,05Ah,003h,000h,002h,010h,004h,06Eh,004h\n\tDB  06Eh,002h,07Ch,000h,008h,000h,008h,000h,010h,000h,010h,000h,010h,000h,010h\n\tDB  000h,020h,000h,020h,000h,040h,000h,040h,000h,080h,000h,080h,000h,000h,001h\n\tDB  000h,004h,000h,004h,000h,004h,000h,001h,000h,000h,000h,000h,038h,01Dh,052h\n\tDB  053h,04Bh,047h,04Fh,048h,050h,049h,051h,04Dh,035h,01Ch,037h,046h,03Eh,040h\n\tDB  04Bh,04Ch,04Fh,050h,051h,053h,054h,055h,056h,059h,05Fh,06Ch,07Ch,000h,03Ch\n\tDB  03Ah,063h,068h,05Ch,05Bh,05Dh,060h,062h,065h,067h,066h,037h,02Bh,07Ch,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,07Fh,06Eh\n\tDB  002h,003h,004h,005h,006h,007h,008h,009h,00Ah,00Bh,00Ch,00Dh,00Fh,010h,011h\n\tDB  012h,013h,014h,015h,016h,017h,018h,019h,01Ah,01Bh,01Ch,02Bh,03Ah,01Fh,020h\n\tDB  021h,022h,023h,024h,025h,026h,027h,028h,029h,001h,02Ch,01Dh,02Eh,02Fh,030h\n\tDB  031h,032h,033h,034h,035h,036h,037h,039h,064h,03Ch,03Dh,01Eh,070h,071h,072h\n\tDB  073h,074h,075h,076h,077h,078h,079h,05Ah,07Dh,05Bh,060h,065h,069h,05Ch,061h\n\tDB  066h,06Ah,05Dh,062h,067h,063h,068h,07Fh,07Fh,07Fh,07Ah,07Bh,000h,000h,0FEh\n\tDB  087h,0FFh,0C0h,01Fh,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,038h,0EFh,001h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,01Eh,02Ch,039h,03Ah,03Ch,03Eh,040h,05Ah\n\tDB  080h,080h,080h,000h,000h,000h,000h,000h,0FFh,0FFh,0FFh,000h,0FFh,001h,000h\n\tDB  000h,000h,000h,000h,0FFh,000h,000h,000h,001h,000h,000h,000h,000h,001h,0FFh\n\tDB  001h,000h,001h,001h,008h,000h,002h,000h,008h,000h,006h,000h,004h,000h,003h\n\tDB  000h,008h,000h,005h,000h,008h,000h,008h,000h,008h,000h,008h,000h,000h,000h\n\tDB  001h,000h,008h,000h,007h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,029h,00Ah,002h,00Dh,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,0F1h\n\tDB  00Ch,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,001h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,0F4h\n\tDB  00Dh,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,0AEh,010h\n\tDB  05Ah,00Fh,05Fh,013h,0E6h,011h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,090h,000h,000h,000h,000h,0ADh,0DEh,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,0ADh,0DEh,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,0C8h,000h\n\tDB  000h,000h,051h,057h,006h,01Eh,08Ch,0C8h,08Eh,0D8h,08Eh,0C0h,08Bh,046h,006h\n\tDB  0F7h,006h,004h,000h,002h,000h,075h,013h,0B9h,010h,000h,0BFh,094h,000h,0F2h\n\tDB  0AEh,0E3h,009h,0BFh,0B4h,000h,04Fh,02Bh,0F9h,026h,08Ah,005h,01Fh,007h,05Fh\n\tDB  059h,0C9h,0CBh,0C8h,000h,000h,000h,056h,053h,01Eh,08Ch,0C8h,08Eh,0D8h,0A1h\n\tDB  0BAh,001h,08Bh,0F0h,005h,002h,000h,025h,0FFh,000h,039h,006h,0B6h,001h,074h\n\tDB  011h,08Bh,05Eh,006h,089h,09Ch,0B6h,000h,0A3h,0BAh,001h,033h,0C0h,01Fh,05Bh\n\tDB  05Eh,0C9h,0CBh,0B8h,001h,000h,01Fh,05Bh,05Eh,0C9h,0CBh,0C8h,004h,000h,000h\n\tDB  053h,051h,052h,057h,056h,01Eh,09Ch,0FAh,08Ch,0C8h,08Eh,0D8h,0A1h,0ABh,002h\n\tDB  0A3h,0AFh,002h,0A1h,0B1h,002h,0A3h,0B5h,002h,08Bh,046h,006h,00Bh,0C0h,075h\n\tDB  003h,0E9h,0F7h,001h,0F7h,006h,004h,000h,000h,010h,00Fh,084h,03Ah,001h,0F6h\n\tDB  0C4h,004h,00Fh,085h,033h,001h,0F7h,006h,004h,000h,000h,020h,074h,00Ch,03Ch\n\tDB  02Bh,074h,00Ch,03Ch,03Dh,074h,008h,03Ch,06Ch,074h,004h,03Ch,063h,075h,016h\n\tDB  0B0h,041h,080h,00Eh,0F6h,002h,001h,0F6h,0C4h,008h,00Fh,084h,00Ah,001h,080h\n\tDB  026h,0F6h,002h,0FEh,0E9h,002h,001h,03Ch,068h,075h,016h,0B0h,042h,080h,00Eh\n\tDB  0F6h,002h,002h,0F6h,0C4h,008h,00Fh,084h,0F0h,000h,080h,026h,0F6h,002h,0FDh\n\tDB  0E9h,0E8h,000h,0F6h,0C4h,008h,00Fh,085h,0E4h,000h,03Ch,061h,074h,01Eh,03Ch\n\tDB  05Bh,00Fh,082h,0DAh,000h,03Ch,067h,00Fh,087h,0D4h,000h,03Ch,05Dh,076h,00Eh\n\tDB  03Ch,065h,073h,00Ah,03Ch,060h,074h,006h,03Ch,062h,00Fh,085h,0C2h,000h,08Ah\n\tDB  0ECh,032h,0E4h,02Ch,05Bh,08Bh,0D8h,0D1h,0E3h,081h,0C3h,06Fh,002h,08Bh,007h\n\tDB  08Ah,0DCh,098h,093h,098h,093h,0F6h,0C5h,002h,075h,021h,0BAh,001h,000h,0F6h\n\tDB  0C5h,001h,074h,003h,083h,0C2h,003h,003h,0DAh,08Ah,09Fh,00Ah,000h,093h,098h\n\tDB  093h,087h,0DAh,003h,0D8h,08Ah,087h,00Ah,000h,098h,087h,0DAh,0EBh,034h,083h\n\tDB  0E3h,003h,025h,003h,000h,083h,0E3h,003h,025h,003h,000h,0D1h,0E3h,0D1h,0E3h\n\tDB  00Bh,0D8h,0D1h,0E3h,08Bh,09Fh,089h,002h,0D1h,0E3h,0D1h,0E3h,08Bh,087h,010h\n\tDB  000h,08Bh,09Fh,012h,000h,0A3h,0AFh,002h,089h,01Eh,0B5h,002h,0A1h,0AFh,002h\n\tDB  08Bh,01Eh,0B5h,002h,0EBh,02Fh,001h,006h,0AFh,002h,079h,005h,033h,0C0h,0A3h\n\tDB  0AFh,002h,001h,01Eh,0B5h,002h,079h,006h,033h,0DBh,089h,01Eh,0B5h,002h,0A1h\n\tDB  0AFh,002h,08Bh,01Eh,0B5h,002h,03Dh,03Fh,001h,07Eh,003h,0B8h,03Fh,001h,081h\n\tDB  0FBh,0C7h,000h,07Eh,003h,0BBh,0C7h,000h,0A3h,0AFh,002h,089h,01Eh,0B5h,002h\n\tDB  0A3h,0ABh,002h,089h,01Eh,0B1h,002h,083h,03Eh,0A9h,002h,000h,075h,008h,00Eh\n\tDB  0E8h,0A5h,003h,00Eh,0E8h,0D4h,003h,0B8h,02Dh,000h,089h,046h,006h,08Bh,036h\n\tDB  0BAh,001h,089h,076h,0FEh,08Bh,03Eh,0B6h,001h,050h,00Eh,0E8h,051h,0FEh,083h\n\tDB  0C4h,002h,00Bh,0C0h,075h,011h,08Bh,046h,006h,03Ch,02Dh,074h,00Dh,03Ch,041h\n\tDB  074h,009h,03Ch,042h,074h,005h,0EBh,029h,0E9h,080h,000h,0FFh,036h,0AFh,002h\n\tDB  00Eh,0E8h,02Eh,0FEh,083h,0C4h,002h,00Bh,0C0h,075h,0EEh,083h,046h,0FCh,002h\n\tDB  0FFh,036h,0B5h,002h,00Eh,0E8h,01Bh,0FEh,083h,0C4h,002h,00Bh,0C0h,075h,0DBh\n\tDB  083h,046h,0FCh,002h,0BBh,001h,001h,08Bh,046h,006h,03Ch,02Dh,074h,01Bh,03Ch\n\tDB  07Fh,074h,017h,0F6h,0C4h,008h,074h,016h,032h,0DBh,0F7h,006h,004h,000h,000h\n\tDB  008h,075h,00Ch,03Ch,041h,074h,008h,03Ch,042h,074h,004h,089h,036h,0BAh,001h\n\tDB  08Bh,0F8h,083h,0E7h,07Fh,0B1h,003h,0D3h,0EFh,08Ah,0C8h,080h,0E1h,007h,0D3h\n\tDB  0E3h,0F6h,0D7h,084h,09Dh,039h,002h,074h,00Ch,0F7h,006h,004h,000h,001h,000h\n\tDB  075h,004h,089h,036h,0BAh,001h,020h,0BDh,039h,002h,008h,09Dh,039h,002h,0B8h\n\tDB  001h,000h,0EBh,008h,08Bh,046h,0FEh,0A3h,0BAh,001h,033h,0C0h,09Dh,01Fh,05Eh\n\tDB  05Fh,05Ah,059h,05Bh,0C9h,0CBh,050h,053h,051h,057h,01Eh,052h,006h,056h,0FCh\n\tDB  08Ch,0C8h,08Eh,0D8h,08Ch,0D1h,089h,026h,08Ah,003h,089h,00Eh,08Ch,003h,0BAh\n\tDB  08Eh,005h,083h,0E2h,0FEh,0FAh,08Eh,0D0h,08Bh,0E2h,0FBh,083h,03Eh,0CEh,002h\n\tDB  000h,0C7h,006h,0CEh,002h,000h,000h,00Fh,085h,003h,002h,08Bh,016h,004h,000h\n\tDB  083h,026h,0BEh,001h,0FCh,0B8h,040h,000h,08Eh,0C0h,026h,0F6h,006h,017h,000h\n\tDB  040h,074h,005h,083h,00Eh,0BEh,001h,001h,026h,0F6h,006h,017h,000h,020h,074h\n\tDB  005h,083h,00Eh,0BEh,001h,002h,0C6h,006h,0B5h,000h,001h,026h,0F6h,006h,096h\n\tDB  000h,010h,075h,005h,0C6h,006h,0B5h,000h,000h,08Ch,0C8h,08Eh,0C0h,0FCh,032h\n\tDB  0E4h,0BBh,001h,001h,0E4h,060h,08Bh,01Eh,05Bh,002h,088h,087h,049h,002h,043h\n\tDB  083h,0E3h,00Fh,089h,01Eh,05Bh,002h,0BBh,001h,001h,03Ch,0E1h,075h,005h,0C6h\n\tDB  006h,05Eh,002h,003h,080h,03Eh,05Eh,002h,000h,074h,00Fh,0FEh,00Eh,05Eh,002h\n\tDB  0F7h,0C2h,080h,000h,00Fh,085h,08Eh,001h,0E9h,0CBh,001h,03Ch,0E0h,075h,008h\n\tDB  0C6h,006h,05Dh,002h,001h,0E9h,07Fh,001h,0A8h,080h,074h,007h,032h,0DBh,024h\n\tDB  07Fh,080h,0CCh,008h,080h,03Eh,05Dh,002h,000h,074h,023h,0C6h,006h,05Dh,002h\n\tDB  000h,0C6h,006h,0B7h,002h,001h,0BFh,084h,000h,0B9h,010h,000h,0F2h,0AEh,0E3h\n\tDB  002h,0EBh,003h,0E9h,094h,001h,08Ah,045h,00Fh,0C6h,006h,0B7h,002h,000h,0EBh\n\tDB  011h,03Ch,07Ah,075h,004h,0B0h,080h,0EBh,009h,08Bh,0F8h,083h,0E7h,07Fh,08Ah\n\tDB  085h,0C0h,001h,0F6h,006h,041h,002h,001h,075h,01Bh,0F6h,006h,040h,002h,004h\n\tDB  074h,017h,03Ch,05Ah,075h,010h,080h,03Eh,0B5h,000h,001h,074h,009h,0F7h,0C2h\n\tDB  080h,000h,075h,003h,0E9h,057h,001h,080h,0CCh,002h,0F6h,006h,040h,002h,050h\n\tDB  074h,003h,080h,0CCh,004h,050h,00Eh,0E8h,043h,0FCh,083h,0C4h,002h,0F6h,006h\n\tDB  03Eh,002h,010h,075h,007h,0F6h,006h,040h,002h,002h,074h,003h,080h,0CCh,001h\n\tDB  08Bh,0F8h,083h,0E7h,07Fh,0D1h,0EFh,0D1h,0EFh,0D1h,0EFh,08Bh,0D8h,083h,0E3h\n\tDB  07Fh,080h,0E3h,007h,08Ah,0AFh,034h,000h,0F7h,006h,0BEh,001h,001h,000h,074h\n\tDB  009h,084h,0ADh,019h,002h,074h,003h,080h,0F4h,001h,0F7h,006h,0BEh,001h,002h\n\tDB  000h,074h,009h,084h,0ADh,029h,002h,074h,003h,080h,0F4h,001h,088h,026h,06Ah\n\tDB  002h,0F7h,0C2h,000h,040h,074h,034h,066h,083h,03Eh,0EAh,002h,001h,075h,01Bh\n\tDB  03Dh,073h,000h,074h,00Ah,03Dh,076h,000h,072h,00Eh,03Dh,078h,000h,077h,009h\n\tDB  066h,0C7h,006h,0EAh,002h,000h,000h,000h,000h,0E9h,08Bh,000h,03Dh,07Dh,000h\n\tDB  075h,00Ch,066h,0C7h,006h,0EAh,002h,001h,000h,000h,000h,0E9h,0BAh,000h,03Dh\n\tDB  068h,006h,074h,075h,03Dh,04Ch,006h,074h,070h,03Dh,030h,002h,074h,005h,03Dh\n\tDB  07Eh,002h,075h,006h,0C7h,006h,008h,000h,001h,000h,03Dh,020h,004h,075h,00Ch\n\tDB  050h,0A1h,000h,000h,035h,001h,000h,050h,083h,0C4h,002h,058h,03Dh,034h,004h\n\tDB  075h,00Ch,050h,0A1h,002h,000h,035h,001h,000h,050h,083h,0C4h,002h,058h,050h\n\tDB  00Eh,0E8h,0DEh,0FBh,058h,03Ch,06Eh,075h,00Dh,083h,03Eh,082h,000h,000h,074h\n\tDB  006h,050h,0FFh,01Eh,080h,000h,058h,0BFh,05Fh,002h,0B9h,00Ah,000h,0F2h,0AEh\n\tDB  00Bh,0C9h,075h,01Bh,0BFh,03Ch,000h,0B9h,022h,000h,0D1h,0E9h,0F2h,0AFh,0E3h\n\tDB  009h,08Bh,05Dh,020h,023h,0DAh,074h,002h,0EBh,006h,0F7h,0C2h,004h,000h,074h\n\tDB  040h,02Eh,0FFh,006h,059h,002h,081h,03Eh,08Eh,003h,0ADh,0DEh,074h,017h,051h\n\tDB  057h,050h,006h,0B8h,000h,0A0h,08Eh,0C0h,033h,0FFh,0B9h,000h,0FAh,0B8h,001h\n\tDB  000h,0F3h,0AAh,007h,058h,05Fh,059h,0FAh,08Bh,016h,08Ch,003h,08Eh,0D2h,08Bh\n\tDB  026h,08Ah,003h,0FBh,0BAh,0E8h,00Ch,09Ch,00Eh,052h,09Ch,0FFh,036h,0BCh,002h\n\tDB  0FFh,036h,0BAh,002h,0CFh,0E4h,061h,08Ah,0E0h,00Ch,080h,0E6h,061h,086h,0E0h\n\tDB  0E6h,061h,0B8h,040h,000h,08Eh,0C0h,026h,0A0h,096h,000h,024h,0FDh,026h,0A2h\n\tDB  096h,000h,0B0h,020h,0E6h,020h,081h,03Eh,08Eh,003h,0ADh,0DEh,074h,017h,051h\n\tDB  057h,050h,006h,0B8h,000h,0A0h,08Eh,0C0h,033h,0FFh,0B9h,000h,0FAh,0B8h,001h\n\tDB  000h,0F3h,0AAh,007h,058h,05Fh,059h,08Bh,016h,08Ch,003h,0FAh,08Eh,0D2h,08Bh\n\tDB  026h,08Ah,003h,0FBh,05Eh,007h,05Ah,01Fh,05Fh,059h,05Bh,058h,0CFh,09Ch,050h\n\tDB  006h,0B8h,000h,0B0h,08Eh,0C0h,026h,0FEh,006h,000h,000h,007h,058h,09Dh,0CFh\n\tDB  09Ch,00Eh,0E8h,022h,0FDh,0CBh,050h,053h,051h,052h,01Eh,08Ch,0C8h,08Eh,0D8h\n\tDB  080h,03Eh,0F7h,002h,000h,075h,01Dh,083h,03Eh,003h,003h,000h,075h,00Ch,0B8h\n\tDB  000h,000h,050h,00Eh,0FFh,016h,051h,003h,083h,0C4h,002h,083h,006h,003h,003h\n\tDB  001h,083h,016h,003h,003h,000h,01Fh,05Ah,059h,05Bh,058h,0CBh,0C8h,004h,000h\n\tDB  000h,050h,053h,051h,052h,056h,057h,01Eh,006h,08Ch,0C8h,08Eh,0D8h,080h,03Eh\n\tDB  0F7h,002h,000h,075h,050h,083h,03Eh,003h,003h,000h,074h,049h,0FFh,00Eh,003h\n\tDB  003h,083h,03Eh,003h,003h,000h,075h,03Eh,08Bh,00Eh,03Fh,003h,08Bh,016h,043h\n\tDB  003h,0A1h,0ABh,002h,089h,046h,0FEh,08Bh,01Eh,0B1h,002h,089h,05Eh,0FCh,0A3h\n\tDB  02Fh,003h,089h,01Eh,033h,003h,089h,00Eh,037h,003h,089h,016h,03Bh,003h,0B8h\n\tDB  001h,000h,050h,00Eh,0FFh,016h,051h,003h,083h,0C4h,002h,0FFh,076h,0FCh,0FFh\n\tDB  076h,0FEh,00Eh,0FFh,016h,053h,003h,083h,0C4h,004h,007h,01Fh,05Fh,05Eh,05Ah\n\tDB  059h,05Bh,058h,0C9h,0CBh,0C8h,002h,000h,000h,053h,08Ch,0C8h,08Eh,0D8h,0C7h\n\tDB  046h,0FEh,02Dh,000h,08Bh,05Eh,006h,08Bh,0C3h,032h,01Eh,0F6h,002h,074h,029h\n\tDB  0A2h,0F6h,002h,0F6h,0C3h,002h,074h,00Eh,0C7h,046h,0FEh,042h,000h,0A8h,002h\n\tDB  075h,005h,081h,04Eh,0FEh,000h,008h,0F6h,0C3h,001h,074h,00Eh,0C7h,046h,0FEh\n\tDB  041h,000h,0A8h,001h,075h,005h,081h,04Eh,0FEh,000h,008h,08Bh,046h,0FEh,05Bh\n\tDB  0C9h,0CBh,0C8h,004h,000h,000h,050h,053h,051h,052h,01Eh,056h,006h,057h,02Eh\n\tDB  089h,01Eh,090h,005h,02Eh,0A3h,092h,005h,08Ch,0C8h,08Eh,0D8h,08Ch,0D3h,089h\n\tDB  026h,094h,005h,089h,01Eh,096h,005h,0BBh,098h,007h,083h,0E3h,0FEh,0FAh,08Eh\n\tDB  0D0h,08Bh,0E3h,0FBh,080h,03Eh,0F7h,002h,000h,00Fh,085h,0FAh,000h,080h,03Eh\n\tDB  0F8h,002h,000h,00Fh,084h,0F1h,000h,0A1h,092h,005h,025h,01Eh,000h,075h,009h\n\tDB  083h,03Eh,0A9h,002h,000h,00Fh,085h,0E0h,000h,083h,03Eh,0F9h,002h,001h,075h\n\tDB  002h,0D1h,0E9h,03Bh,00Eh,049h,003h,072h,005h,08Bh,00Eh,049h,003h,049h,03Bh\n\tDB  016h,04Dh,003h,072h,005h,08Bh,016h,04Dh,003h,04Ah,089h,00Eh,0ABh,002h,089h\n\tDB  016h,0B1h,002h,066h,0F7h,006h,004h,000h,000h,010h,000h,000h,075h,013h,0FFh\n\tDB  036h,090h,005h,00Eh,0E8h,02Ch,0FFh,083h,0C4h,002h,050h,00Eh,0E8h,07Bh,0F9h\n\tDB  083h,0C4h,002h,083h,03Eh,0A9h,002h,000h,00Fh,085h,092h,000h,083h,03Eh,0FBh\n\tDB  002h,000h,074h,019h,08Bh,0C1h,08Bh,0CAh,02Bh,006h,0FFh,002h,08Bh,01Eh,0FBh\n\tDB  002h,099h,0F7h,0FBh,0F7h,0EBh,003h,006h,0FFh,002h,08Bh,0D1h,08Bh,0C8h,083h\n\tDB  03Eh,0FDh,002h,000h,074h,015h,08Bh,0C2h,02Bh,006h,001h,003h,08Bh,01Eh,0FDh\n\tDB  002h,099h,0F7h,0FBh,0F7h,0EBh,003h,006h,001h,003h,08Bh,0D0h,083h,03Eh,003h\n\tDB  003h,000h,075h,047h,039h,00Eh,007h,003h,075h,006h,039h,016h,009h,003h,074h\n\tDB  03Bh,0A1h,00Bh,003h,025h,000h,0C0h,03Dh,000h,0C0h,074h,00Ch,00Eh,0E8h,016h\n\tDB  0FEh,0F7h,006h,00Bh,003h,000h,080h,074h,020h,03Bh,00Eh,00Dh,003h,072h,01Ah\n\tDB  03Bh,00Eh,015h,003h,077h,014h,03Bh,016h,011h,003h,072h,00Eh,03Bh,016h,019h\n\tDB  003h,077h,008h,081h,00Eh,00Bh,003h,000h,040h,0EBh,004h,00Eh,0E8h,01Dh,0FEh\n\tDB  089h,00Eh,007h,003h,089h,016h,009h,003h,081h,03Eh,098h,005h,0ADh,0DEh,074h\n\tDB  017h,051h,057h,050h,006h,0B8h,000h,0A0h,08Eh,0C0h,033h,0FFh,0B9h,000h,0FAh\n\tDB  0B8h,001h,000h,0F3h,0AAh,007h,058h,05Fh,059h,0A1h,096h,005h,0FAh,08Eh,0D0h\n\tDB  08Bh,026h,094h,005h,0FBh,05Fh,007h,05Eh,01Fh,05Ah,059h,05Bh,058h,0C9h,0CBh\n\tDB  0C8h,00Ch,000h,000h,050h,053h,051h,052h,057h,056h,01Eh,006h,08Ch,0C8h,08Eh\n\tDB  0D8h,0FCh,0A1h,02Fh,003h,08Bh,01Eh,033h,003h,02Bh,006h,027h,003h,02Bh,01Eh\n\tDB  02Bh,003h,089h,046h,0FEh,089h,05Eh,0FCh,003h,006h,037h,003h,003h,01Eh,03Bh\n\tDB  003h,089h,046h,0FAh,089h,05Eh,0F8h,0C7h,046h,0F6h,000h,000h,0A1h,023h,003h\n\tDB  089h,046h,0F4h,033h,0C0h,033h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,003h,0C9h\n\tDB  013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,02Bh,00Eh,049h\n\tDB  003h,02Bh,01Eh,049h,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h\n\tDB  08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh\n\tDB  04Eh,0FCh,08Bh,05Eh,0F8h,02Bh,00Eh,04Dh,003h,02Bh,01Eh,04Dh,003h,049h,04Bh\n\tDB  003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,034h,005h,080h,0F2h,005h,08Ah,0E0h\n\tDB  084h,0D0h,00Fh,085h,0AEh,000h,00Ah,0C2h,074h,040h,0F6h,0C4h,008h,074h,00Dh\n\tDB  08Bh,05Eh,0FEh,0F7h,0DBh,089h,05Eh,0F6h,0C7h,046h,0FEh,000h,000h,0F6h,0C4h\n\tDB  002h,074h,013h,052h,08Bh,046h,0FCh,0F7h,0D8h,0F7h,026h,037h,003h,001h,046h\n\tDB  0F4h,0C7h,046h,0FCh,000h,000h,05Ah,0F6h,0C2h,004h,074h,006h,0A1h,049h,003h\n\tDB  089h,046h,0FAh,0F6h,0C2h,001h,074h,006h,0A1h,04Dh,003h,089h,046h,0F8h,0B8h\n\tDB  000h,0A0h,08Eh,0C0h,08Bh,046h,0FCh,0F7h,026h,049h,003h,08Bh,016h,049h,003h\n\tDB  08Bh,0F8h,003h,07Eh,0FEh,08Bh,01Eh,03Fh,003h,0C5h,036h,023h,003h,08Bh,076h\n\tDB  0F4h,003h,076h,0F6h,08Bh,046h,0FAh,08Bh,04Eh,0F8h,02Bh,046h,0FEh,07Eh,03Ch\n\tDB  02Bh,04Eh,0FCh,07Eh,037h,02Bh,0D0h,02Bh,0D8h,055h,083h,07Eh,006h,000h,075h\n\tDB  018h,08Bh,0E9h,08Bh,0C8h,0F3h,0A4h,003h,0F3h,003h,0FAh,04Dh,075h,0F5h,05Dh\n\tDB  007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,087h,0F7h,08Bh,0E9h,006h\n\tDB  01Eh,007h,01Fh,08Bh,0C8h,0F3h,0A4h,003h,0F2h,003h,0FBh,04Dh,075h,0F5h,05Dh\n\tDB  007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,0C8h,00Ch,000h,000h,050h\n\tDB  053h,051h,052h,057h,056h,01Eh,006h,08Ch,0C8h,08Eh,0D8h,08Bh,046h,006h,08Bh\n\tDB  05Eh,008h,02Bh,006h,027h,003h,02Bh,01Eh,02Bh,003h,089h,046h,0FEh,089h,05Eh\n\tDB  0FCh,003h,006h,03Fh,003h,003h,01Eh,043h,003h,089h,046h,0FAh,089h,05Eh,0F8h\n\tDB  0C7h,046h,0F6h,000h,000h,0C4h,006h,01Dh,003h,089h,046h,0F4h,033h,0C0h,033h\n\tDB  0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h\n\tDB  08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,02Bh,00Eh,049h,003h,02Bh,01Eh,049h,003h,049h\n\tDB  04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h\n\tDB  003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,02Bh\n\tDB  00Eh,04Dh,003h,02Bh,01Eh,04Dh,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh\n\tDB  013h,0D2h,034h,005h,080h,0F2h,005h,08Ah,0E0h,084h,0D0h,00Fh,085h,093h,000h\n\tDB  00Ah,0C2h,074h,042h,0F6h,0C4h,008h,074h,00Dh,08Bh,05Eh,0FEh,0F7h,0DBh,089h\n\tDB  05Eh,0F6h,0C7h,046h,0FEh,000h,000h,0F6h,0C4h,002h,074h,013h,052h,08Bh,046h\n\tDB  0FCh,0F7h,0D8h,0F7h,026h,03Fh,003h,001h,046h,0F4h,0C7h,046h,0FCh,000h,000h\n\tDB  05Ah,0F6h,0C2h,004h,074h,007h,08Bh,01Eh,049h,003h,089h,05Eh,0FAh,0F6h,0C2h\n\tDB  001h,074h,007h,08Bh,01Eh,04Dh,003h,089h,05Eh,0F8h,08Bh,046h,0FCh,0F7h,026h\n\tDB  049h,003h,08Bh,016h,049h,003h,08Bh,0F8h,003h,07Eh,0FEh,08Bh,01Eh,03Fh,003h\n\tDB  08Bh,076h,0F4h,003h,076h,0F6h,0B8h,000h,0A0h,08Eh,0D8h,08Bh,046h,0FAh,08Bh\n\tDB  04Eh,0F8h,02Bh,046h,0FEh,07Eh,023h,02Bh,04Eh,0FCh,07Eh,01Eh,02Bh,0D0h,02Bh\n\tDB  0D8h,08Ah,0E0h,026h,08Ah,02Ch,066h,046h,00Ah,0EDh,074h,002h,088h,02Dh,047h\n\tDB  0FEh,0CCh,075h,0F0h,003h,0F3h,003h,0FAh,0FEh,0C9h,075h,0E6h,007h,01Fh,05Eh\n\tDB  05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,0C8h,00Ch,000h,000h,050h,053h,051h,052h\n\tDB  057h,056h,01Eh,006h,08Ch,0C8h,08Eh,0D8h,0E8h,0B7h,002h,089h,056h,0F2h,0FCh\n\tDB  0A1h,02Fh,003h,08Bh,01Eh,033h,003h,02Bh,006h,027h,003h,02Bh,01Eh,02Bh,003h\n\tDB  089h,046h,0FEh,089h,05Eh,0FCh,003h,006h,037h,003h,003h,01Eh,03Bh,003h,089h\n\tDB  046h,0FAh,089h,05Eh,0F8h,0C7h,046h,0F6h,000h,000h,0A1h,023h,003h,089h,046h\n\tDB  0F4h,033h,0C0h,033h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,003h,0C9h,013h,0C0h\n\tDB  003h,0DBh,013h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,02Bh,00Eh,049h,003h,02Bh\n\tDB  01Eh,049h,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh\n\tDB  0FCh,08Bh,05Eh,0F8h,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FCh\n\tDB  08Bh,05Eh,0F8h,02Bh,00Eh,04Dh,003h,02Bh,01Eh,04Dh,003h,049h,04Bh,003h,0C9h\n\tDB  013h,0C0h,003h,0DBh,013h,0D2h,034h,005h,080h,0F2h,005h,08Ah,0E0h,084h,0D0h\n\tDB  00Fh,085h,0C7h,000h,00Ah,0C2h,074h,040h,0F6h,0C4h,008h,074h,00Dh,08Bh,05Eh\n\tDB  0FEh,0F7h,0DBh,089h,05Eh,0F6h,0C7h,046h,0FEh,000h,000h,0F6h,0C4h,002h,074h\n\tDB  013h,052h,08Bh,046h,0FCh,0F7h,0D8h,0F7h,026h,037h,003h,001h,046h,0F4h,0C7h\n\tDB  046h,0FCh,000h,000h,05Ah,0F6h,0C2h,004h,074h,006h,0A1h,049h,003h,089h,046h\n\tDB  0FAh,0F6h,0C2h,001h,074h,006h,0A1h,04Dh,003h,089h,046h,0F8h,0B8h,000h,0A0h\n\tDB  08Eh,0C0h,08Bh,046h,0FCh,0F7h,026h,049h,003h,003h,046h,0FEh,083h,0D2h,000h\n\tDB  08Bh,0F8h,0E8h,0F1h,001h,08Bh,016h,049h,003h,08Bh,01Eh,03Fh,003h,0C5h,036h\n\tDB  023h,003h,08Bh,076h,0F4h,003h,076h,0F6h,08Bh,046h,0FAh,08Bh,04Eh,0F8h,02Bh\n\tDB  046h,0FEh,07Eh,04Fh,02Bh,04Eh,0FCh,07Eh,04Ah,02Bh,0D0h,02Bh,0D8h,083h,07Eh\n\tDB  006h,000h,075h,021h,08Ah,0E0h,08Ah,02Ch,026h,088h,02Dh,046h,047h,075h,003h\n\tDB  0E8h,0D9h,001h,0FEh,0CCh,075h,0F0h,003h,0F3h,003h,0FAh,073h,003h,0E8h,0CCh\n\tDB  001h,0FEh,0C9h,075h,0E1h,0EBh,01Fh,08Ah,0E0h,026h,08Ah,02Dh,088h,02Ch,046h\n\tDB  047h,075h,003h,0E8h,0B8h,001h,0FEh,0CCh,075h,0F0h,003h,0F3h,003h,0FAh,073h\n\tDB  003h,0E8h,0ABh,001h,0FEh,0C9h,075h,0E1h,08Bh,056h,0F2h,0E8h,06Ch,001h,007h\n\tDB  01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,0C8h,00Eh,000h,000h,050h,053h\n\tDB  051h,052h,057h,056h,01Eh,006h,08Ch,0C8h,08Eh,0D8h,0E8h,03Eh,001h,089h,056h\n\tDB  0F2h,08Bh,046h,006h,08Bh,05Eh,008h,02Bh,006h,027h,003h,02Bh,01Eh,02Bh,003h\n\tDB  089h,046h,0FEh,089h,05Eh,0FCh,003h,006h,03Fh,003h,003h,01Eh,043h,003h,089h\n\tDB  046h,0FAh,089h,05Eh,0F8h,0C7h,046h,0F6h,000h,000h,0C4h,006h,01Dh,003h,089h\n\tDB  046h,0F4h,033h,0C0h,033h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,003h,0C9h,013h\n\tDB  0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,02Bh,00Eh,049h,003h\n\tDB  02Bh,01Eh,049h,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh\n\tDB  04Eh,0FCh,08Bh,05Eh,0F8h,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh\n\tDB  0FCh,08Bh,05Eh,0F8h,02Bh,00Eh,04Dh,003h,02Bh,01Eh,04Dh,003h,049h,04Bh,003h\n\tDB  0C9h,013h,0C0h,003h,0DBh,013h,0D2h,034h,005h,080h,0F2h,005h,08Ah,0E0h,084h\n\tDB  0D0h,00Fh,085h,0A0h,000h,00Ah,0C2h,074h,040h,0F6h,0C4h,008h,074h,00Dh,08Bh\n\tDB  05Eh,0FEh,0F7h,0DBh,089h,05Eh,0F6h,0C7h,046h,0FEh,000h,000h,0F6h,0C4h,002h\n\tDB  074h,013h,052h,08Bh,046h,0FCh,0F7h,0D8h,0F7h,026h,03Fh,003h,001h,046h,0F4h\n\tDB  0C7h,046h,0FCh,000h,000h,05Ah,0F6h,0C2h,004h,074h,006h,0A1h,049h,003h,089h\n\tDB  046h,0FAh,0F6h,0C2h,001h,074h,006h,0A1h,04Dh,003h,089h,046h,0F8h,08Bh,046h\n\tDB  0FCh,0F7h,026h,049h,003h,003h,046h,0FEh,083h,0D2h,000h,08Bh,0F8h,0E8h,07Eh\n\tDB  000h,08Bh,016h,049h,003h,08Bh,01Eh,03Fh,003h,08Bh,076h,0F4h,003h,076h,0F6h\n\tDB  0B8h,000h,0A0h,08Eh,0D8h,08Bh,046h,0FAh,08Bh,04Eh,0F8h,02Bh,046h,0FEh,07Eh\n\tDB  02Ch,02Bh,04Eh,0FCh,07Eh,027h,02Bh,0D0h,02Bh,0D8h,08Ah,0E0h,026h,08Ah,02Ch\n\tDB  046h,00Ah,0EDh,074h,002h,088h,02Dh,047h,075h,003h,0E8h,067h,000h,0FEh,0CCh\n\tDB  075h,0ECh,003h,0F3h,003h,0FAh,073h,003h,0E8h,05Ah,000h,0FEh,0C9h,075h,0DDh\n\tDB  08Bh,056h,0F2h,0E8h,01Bh,000h,007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h\n\tDB  0CBh,050h,053h,0B8h,005h,04Fh,0B7h,001h,0B3h,000h,02Eh,0FFh,01Eh,05Dh,003h\n\tDB  05Bh,058h,0C3h,050h,053h,052h,0B8h,005h,04Fh,0B7h,000h,0B3h,000h,02Eh,0FFh\n\tDB  01Eh,05Dh,003h,05Ah,05Bh,058h,0C3h,050h,053h,052h,08Bh,0DAh,0C1h,0E3h,002h\n\tDB  02Eh,089h,01Eh,09Ah,007h,02Eh,08Bh,097h,061h,003h,0B8h,005h,04Fh,0B7h,000h\n\tDB  0B3h,000h,02Eh,0FFh,01Eh,05Dh,003h,05Ah,05Bh,058h,0C3h,050h,053h,052h,02Eh\n\tDB  08Bh,01Eh,09Ah,007h,083h,0C3h,004h,02Eh,089h,01Eh,09Ah,007h,02Eh,08Bh,097h\n\tDB  061h,003h,0B8h,005h,04Fh,0B7h,000h,0B3h,000h,02Eh,0FFh,01Eh,05Dh,003h,05Ah\n\tDB  05Bh,058h,0C3h\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/NEW/KEYSTRUC.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : KEYSTRUC.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 13, 1994                            *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nSTRUC\tKeyboardType\n\tSoundOn\t\t\tDW\t?\t; toggled by alt S\n\tMusicOn\t\t\tDW\t?\t; toggled by alt M\n\tKeyFlags\t\t\tDD\t?\t; all but repeat for now\n\tBreak\t\t\t\tDW\t?\n\tKeyMouseMove\tDB\t6  DUP(?)\n\tScreenEdge\t\tDW\t18 DUP (?)\n\tBits\t\t\t\tDB\t8  DUP (?)\n\tCondPassKey\t\tDW\t17 DUP (?) \n\tCondPassCond\tDW\t17 DUP (?)\n\tEscRoutine\t\tDD\t?\n\tExtCodes\t\t\tDB\t16 DUP (?)\n\tExtNums\t\t\tDB\t16 DUP (?)\n\tExtRemap\t\t\tDB\t16 DUP (?)\n\tExtRemapEnd\t\tDB\t?\n\tExtKeyboard\t\tDB\t?\n\tKeyBuffer\t\tDW\t128 DUP(?) ; set to empty\n\tKeyBufferHead\tDD\t?\t; set to first entry\n\tKeyBufferTail\tDD\t?\t; set to head for empty buffer\n\tKeyLock\t\t\tDW\t?\t; num and caps lock bits\n\tKeyNums\t\t\tDB\t89 DUP (?)\n\tKeysCapsLock\tDB\t16 DUP (?)\n\tKeysNumLock\t\tDB\t16 DUP (?)\n\tKeysUpDown\t\tDB\t16 DUP (?)\n\tKeyStream\t\tDB\t16 DUP (?)\n\tPassCount\t\tDW\t?\n\tKeyStreamIndex\tDW\t?\n\tLastKeyE0\t\tDB\t?\n\tLastKeyE1\t\tDB\t?\n\tPassAlways\t\tDB\t10 DUP (?)\n\tPassAlwaysEnd\tDB\t?\t\t; invalid code to END PassAlways\n\tCtrlFlags\t\tDB\t?\n\tBuffer\t\t\tDW\t?\n\tTime\t\t\t\tDW\t?\n\tXYAdjust\t\t\tDB\t26 DUP (?)\n\tEdgeConv\t\t\tDW\t16 DUP (?)\n\tMouseUpdate\t\tDW\t?\n\tMouseX\t\t\tDD\t?\n\tLocalMouseX\t\tDW\t?\n\tMouseY\t\t\tDD\t?\n\tLocalMouseY\t\tDW\t?\n\tIsExtKey\t\t\tDB\t?\n\tExtIndex\t\t\tDW\t?\n\n\tKeyOldRMI\t\t\tDD\t?\t; The origianl RM interrupt seg:off.\n\tKeyOldPMIOffset\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tKeyOldPMISelector\tDD\t?\t; The original PM interrupt segment.\n\n\tKeyCodeOffset\t\t\tDW\t?\t; Offset of the code in the RM stuff.\n\tCallKeyRMIntOffset\tDW\t?\t; Offset of function to call DOS timer interrupt.\n\tCallKeyRMIntAddr\t\tDD\t?\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedKeyInt\t\t\tDD\t?\t; did Protected mode pass this through?\n\n\tBrkOldRMI\t\t\t\tDD\t?\t; The origianl RM interrupt seg:off.\n\tBrkOldPMIOffset\t\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tBrkOldPMISelector\t\tDD\t?\t; The original PM interrupt segment.\n\n\tBrkCodeOffset\t\t\tDW\t?\t; Offset of the code in the RM stuff.\n\tCallBrkRMIntOffset\tDW\t?\t; Offset of function to call DOS timer interrupt.\n\tCallBrkRMIntAddr\t\tDD\t?\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedBrkInt\t\t\tDD\t?\t; did Protected mode pass this through?\n\tKeyIntDisabled\t\t\tDD\t?\n\n\tDbgOldPMIOffset\t\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tDbgOldPMISelector\t\tDD\t?\t; The original PM interrupt segment.\n\n\t;---------------------------------------------------------------------------\n\t; Begin definition of Mouse Specific Variables for real mode\n\t;---------------------------------------------------------------------------\n\tButton\t\t\t\tDB\t?\t; current value of the mouse button\n\tMDisabled\t\t\tDB\t?\t; Is the mouse driver disabled\n\tMInput\t\t\t\tDB\t?\t; Defaults to mouse input allowed.\n\tAdjust\t\t\t\tDW\t?\t; flag to adjust coordinates if necessary\n\tMouseStepX\t\t\tDW\t?\t; step values if the mouse moves at\n\tMouseStepY\t\t\tDW\t?\t;   more than one pixel at a time\n\tMouseOffsetX\t\tDW\t?\t; Fractional step values used if a mouse\n\tMouseOffsetY\t\tDW\t?\t;   moves at less than one pixel at a time\n\tMState\t\t\t\tDD\t?\t; Tracks if mouse is hidden (TRUE) or not (FALSE)\n\tMouseXOld     \t\tDW\t?\t; Holds last MouseX and MouseY to determine if \n\tMouseYOld     \t\tDW\t?\t;   mouse needs to be redrawn\n\tMCState\t\t\t\tDW\t?\t; Tracks if mouse conditional hidden (TRUE) or not\n\tMouseCXLeft\t\t\tDD\t?\t; Conditional hide mouse left x position\n\tMouseCYUpper\t\tDD\t?\t; Conditional hide mouse top y position\n\tMouseCXRight\t\tDD\t?\t; Conditional hide mouse right x position\n\tMouseCYLower\t\tDD\t?\t; Conditional hide mouse lower y position\n\tMouseCursor   \t\tDD\t?\t; Pointer to the mouse cursor to draw\n\tMouseCursorSize\tDW\t?\t; Size of mouse cursor draw area\n\tMouseBuffer   \t\tDD\t?\t; Pointer to buffer mouse is saved in\n\tMouseXHot     \t\tDD\t?\t; Offset to mouse's x hot spot\n\tMouseYHot     \t\tDD\t?\t; Offset to mouse's y hot spot\n\tMouseBuffX\t\t\tDD\t?\t; X position background was saved at\n\tMouseBuffY\t\t\tDD\t?\t; Y position background was saved at\n\tMouseBuffW\t\t\tDD\t?\t; Width of the region saved for mouse\n\tMouseBuffH\t\t\tDD\t?\t; Height of the region saved for mouse\n\tMouseWidth\t\t\tDD\t?\t; Mouse cursor theoretical width\n\tMouseHeight\t\t\tDD\t?\t; Mouse cursor theoretical height\n\tMouseCodeOffset\tDW\t?\t; Offset to the real mode code offset\n\tMouseRight\t\t\tDD\t?\t; Right hand side of the screen\n\tMouseBottom\t\t\tDD\t?\t; Bottom of the screen\n\n\n\tShadowPtr\t\t\tdw\t?\n\tDrawMousePtr \t\tdw\t?\n\n\tVGAMouseDraw\t\tdw\t?\n\tVGAMouseShadow\t\tdw\t?\n\n\tVESAMouseDraw\t\tdw\t?\n\tVESAMouseShadow\tdw\t?\n\n\tVesaPtr\t\t\t\tdd ?\t\n\tVesaBankTable\t   DD\t8 dup (?)\n\tAdjust_XPos\t\t\tdd ?\n\tAdjust_YPos\t\t\tdd ?\n\n\nENDS\n\n; InitFlags that are set to have a fully functional interrupt.\nIF_ALLOC_RM\t\t\tequ\t1\t\t; Allocation of RM was successful.\nIF_SET_VECTORS\t\tequ\t2\t\t; Vectors have been set.\nIF_LOCKED_PM_CODE\tequ\t4\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t8\t\t; Locked PM code for DPMI.\nIF_RATE_CHANGE\t\tequ\t10\t\t; Timer rate was changed.\nIF_FUNCTIONAL\t\tequ\t20\t\t; Timer is in and functional.\nIF_LOCKED_RM_CODE\tequ\t40\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/NEW/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 25, 1994                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = keyboard\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tkeyboard.obj\t&\n\tmouse.obj\t\t&\n\tpagfault.obj\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WWLIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# The keyboard object files is also dependant on an IBN file which is \n#   generated from KEYIREAL.ASM\n#---------------------------------------------------------------------------\nkeyireal.ibn: keyireal.obj\n\t%create\t$^*.rsp\n\t%append $^*.rsp $^&.obj\n\t%append $^*.rsp $^&.exe\n\t%append $^*.rsp $^&.map\n\ttlink @$^*.rsp\n        tdstrip keyireal.exe\n        ebn\tkeyireal.exe\n\nkeyireal.obj:\tkeyireal.asm\n\ttasm /zn /la /ml /m2 keyireal.asm\n\nkeyboard.obj: keyireal.ibn keyboard.asm\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/NEW/MOUSE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*\t\t\t\t  (Mouse Routines)\t\t\t   *\n;*                                                                         *\n;*                    File Name : MOUSE.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : August 26, 1994                          *\n;*                                                                         *\n;*                  Last Update : November 3, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Install_Mouse -- Initializes mouse driver and verifies mouse exists   *\n;*   Remove_Mouse -- uninstalls the mouse interrupt by disabling the call  *\n;*   Get_Mouse_X -- Returns the mouses x pixel position                    *\n;*   Get_Mouse_Y -- Returns the mouse's y pixel position                   *\n;*   Get_Mouse_Button -- Gets the values of the mouse button               *\n;*   Set_Mouse_Cursor -- Sets the shape to be used as the mouse.           *\n;*   Low_Hide_Mouse -- Low-level routine which hides the mouse\t\t   *\n;*   Low_Show_Mouse -- Low level routine which shows the mouse\t\t   *\n;*   Mouse_Shadow_Buffer -- Handles storing and restoring the mouse buffer *\n;*   Draw_Mouse -- Handles drawing the mouse cursor\t\t\t   *\n;*   Hide_Mouse -- Hides mouse cursor on screen if it was show             *\n;*   Show_Mouse -- Display mouse cursor on screen if it was hidden         *\n;*   Conditional_Hide_Mouse -- Hides mouse if its with given region        *\n;*   Conditional_Show_Mouse -- shows mouse if it was conditionally hidden  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\n;WARN\t\t\t\t; generate all warnings we can\n;JUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keystruc.inc\"\nINCLUDE \"shape.inc\"\ninclude \"svgaprim.inc\"\n\nDOS_SYS_CALL\t\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nRESTORE_VISIBLE_PAGE\tEQU\t0\nSTORE_VISIBLE_PAGE\tEQU\t1\nCONDHIDE\t\tEQU\t08000H\t\t; bit for testing conditional region\nCONDHIDDEN\t\tEQU\t04000H\t\t; bit for testing conditional hidden\n;---------------------------------------------------------------------------\n; Define any data which needs to be global...\n;---------------------------------------------------------------------------\n\nGLOBAL\tRealModePtr:DWORD\nGLOBAL\tMInstalled:DWORD\nGLOBAL\tMouseBuffer:DWORD\nGLOBAL\tLCW_Uncompress:NEAR\n\nGLOBAL\tGet_Shape_Uncomp_Size     :NEAR\nGLOBAL\tGet_Shape_Width      \t  :NEAR\nGLOBAL\tGet_Shape_Original_Height :NEAR\nGLOBAL  Size_Of_Region\t\t  :NEAR\nGLOBAL\t_ShapeBuffer\t\t  :DWORD\n\nGLOBAL  XRes\t: dword\nGLOBAL  YRes\t: dword\n\n\nGLOBAL\tVesaFunc : dword\nGLOBAL\tVesa_XRes : near\nGLOBAL\tVesa_YRes : near\n\n\n\n\n\nDPMI_INTR\tEQU\t31h\t\n\n\nSTRUC DPMI_REGS\n       _edi  dd ?\n       _esi  dd ?\t\n       _ebp  dd ?\t\n       \t     dd ?\n       _ebx  dd ?\t\n       _edx  dd ?\t\n       _ecx  dd ?\t\n       _eax  dd ?\t\n       Flags dw ?\n       _es   dw ?\n       _ds   dw ?\n       _fs   dw ?\n       _gs   dw ?\n       _ip   dw ?\n       _cs   dw ?\n       _sp   dw ?\n       _ss   dw ?\n       \t     dd ?\n\t     dd ?\n  nothing    dd ?\t\t\t\nENDS\n\n\n\n;---------------------------------------------------------------------------\n; Now lets handle any data in the data segment\n;---------------------------------------------------------------------------\n\tDATASEG\n\nRealInt\t\tDPMI_REGS <>\t; structure to call a real mode int\nMInstalled\tDD\t0\t\t; is the mouse installed?\nMouseCursor\tDD\t0\nMouseBuffer\tDD\t0\nBufferWidth\tDD\t0\nBufferHeight\tDD\t0\nBufferSize\tDD\t0\nPrevMousePtr\tDD\t0\nMouseBufferSel\tDD\t0\n\n\nDraw_Mouse\t\tdd\tVGA_Draw_Mouse\nMouse_Shadow_Buffer\tdd\tVGA_Mouse_Shadow_Buffer\n\n;---------------------------------------------------------------------------\n; Time to write some code\n;---------------------------------------------------------------------------\n\tCODESEG\n\n;***************************************************************************\n;* INSTALL_MOUSE -- Initializes mouse driver and verifies mouse connected  *\n;*                                                                         *\n;* First check the mouse interupt to see if the vector is pointing to zero *\n;* page.  If it is not then make sure it is not pointing to an IRET.  If   *\n;* not call the mouse reset to verify that the hardware is attached.\t   *\n;*                                                                         *\n;* INPUT:\tint mouse_max_width  - the max width of the mouse cursor   *\n;*\t\tint mouse_max_height - the max height of the mouse cursor  *\n;*\t\tint screen_width     - width of the physical screen\t   *\n;*\t\tint screen_height    - height of the physical screen\t   *\n;*                                                                         *\n;* OUTPUT:      TRUE is mouse driver is initialized, FALSE if unable to    *\n;*\t\tinitialize mouse driver.\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tint Install_Mouse(\tint mouse_max_width,\t\t   *\n;*\t\t\t\t\tint mouse_max_height,\t\t   *\n;*\t\t\t\t\tint screen_width,\t\t   *\n;*\t\t\t\t\tint screen_height);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/26/1994 PWG : Created.                                             *\n;*=========================================================================*\nGLOBAL\tInstall_Mouse:NEAR\nPROC\tInstall_Mouse C NEAR \n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\tmouse_max_width:DWORD\n\tARG\tmouse_max_height:DWORD\n\tARG\tscreen_width:DWORD\n\tARG\tscreen_height:DWORD\n\n\n\t;*=========================================================================*\n\t;* Initialize all of the general mouse variables\n\t;*=========================================================================*\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\ttest\tesi , esi\t\t\t; mouse driver should be install\n\tjz \t??exit\t\t\t\t; after keyboard interrup is install\n\tmov\teax , [ XRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseX],eax\t; set the mouses x coordinate to 160\n\tmov\teax , [ YRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseY],eax\t; set the mouses y coordinate to 100\n\tmov\t[(KeyboardType esi).MState],1\t; flag the mouse as hidden\n\tmov\t[(KeyboardType esi).MCState],0\t; turn off conditional region\n\tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi).MouseRight],eax\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi).MouseBottom],eax\n\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 0200, bl = number of interrupt to get\n\t; output cf error, cx,dx= address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,033h\t\t\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\t\t\t; no mouse driver present\n\n\t;*=========================================================================*\n\t;* If the interupt vector is pointing to 0000:0000h, there is no mouse\n\t;*=========================================================================*\n\tmov\tax,cx\n\tor\tax,dx\t\t\n\tjz\tshort ??nomouse\n\n\tand\tedx , 0ffffh\n\tand\tecx , 0ffffh\n\tshl\tecx,4\n\tadd\tecx,edx\n\n\t;*=========================================================================*\n\t;* If the first instruction is an IRET, there is no mouse\n\t;*=========================================================================*\n\n\tcmp\t[byte ptr ecx],0CFH\t; is this an IRET\n\tjne\tshort ??mouse_buff\t; if it isnt then reset the mouse\n\n??nomouse:\n\tmov\teax,FALSE\t\t\t\t; flag no mouse driver\n\tmov\t[MInstalled],FALSE\t\t\t; flag no mouse driver\n    \tjmp\t??exit\t\t\t\t\t; exit\n\n??mouse_buff:\n\t;*=========================================================================*\n\t;* Allocate two real mode memory buffers for the mouse cursor and the \n\t;*\tmouse shadow\n\t;*=========================================================================*\n\tmov\teax,[mouse_max_width]\t       \t; get the is max width\n\tmov\t[BufferWidth],eax\t       \t; save it off for set cursor\n\tmov\tedx,[mouse_max_height]\t       \t; get the max height\n\tmov\t[BufferHeight],edx\t       \t; save it off for set cursor\n\tmul\tedx\t\t\t       \t; size = max_width * max_height\n\tadd\teax,22\t\t\t       \t; add width/height(8) + para align(15)\n\tand\tal, 0f0h\t\t       \t; now size is even paragraphs\n\tmov\t[BufferSize],eax\t       \t; store off the buffer size\n\tshl\teax,1\t\t\t       \t; make two of them\n\n \tmov\tebx,eax\t\t\t\t; get size of RM binary.\n\tmov\tecx,eax\t\t\t\t; ecx will use it later.\n\tadd\tebx,15\t\t\t\t; round up \n\tshr\tebx,4\t\t\t\t; convert to pages.\n\tmov\teax,0100h\t\t\t; alloc real buffer\n\tint\tDPMI_INTR\t \t\t; do call.\n\tjc\t??error\t\t \t\t; check for error.\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tmov\t[MouseBufferSel], edx\n\tshl\teax , 16\n\tmov\t[(KeyboardType esi).MouseCursor],eax\t; store off the real mode segment\n\tmov\tedx,eax\t\t\t\t\t; get the buffer position\n\tadd\tedx,[BufferSize]\t\t\t; add in the buffer size\n\tmov\t[(KeyboardType esi).MouseBuffer],edx\t; store off the real mode segment\n\tshr\teax,12\t\t\t\t\t; convert the seg/off to 32 bit offset\n\tmov\tedx,eax\n\tadd\tedx,[BufferSize]\n\tmov\t[MouseCursor],eax\t\t\t; store it off in the mouse buffer\n\tmov\t[MouseBuffer],edx\t\t\t; store it off in the mouse buffer\n\n\tmov\teax,0600h\t\t\t\t; function number.\n\tmov\tecx,[MouseCursor]\t\t\t; ecx must have start of memory.\n\tmov\tedi,[BufferSize]\n\tshl\tedi,1\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n       \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n\n??begin:\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\t; Reset mouse thru int 33h funtion 0\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\txor\tecx , ecx\n\tmov\t[RealInt . _eax ] , 0\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\tmov\teax ,[RealInt . _eax]\n\tcmp\tax,-1\t\t\t\t\t; was the mouse attached to system\n      \tjne\t??nomouse\t\t\t\t; if not exit out of the routine\n\t\n\tmov\t[(KeyboardType esi).Adjust],0\t\t; assume we do not need to adjust mouse\n\n;***************************************************************************\n; Set the Vesa Parameters \n\n\tmov\teax , [ VesaFunc ]\n\ttest\teax , eax\n\tjz\t??set_vga_mouse\n\tmov\t[(KeyboardType esi). VesaPtr ] , eax\n\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VESA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VESA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n \tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi). MouseRight ] , eax\n\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi). MouseBottom ] , eax\n\n\tlea\tedi , [(KeyboardType esi). VesaBankTable]\n\tlea\tesi , [ BankTable ]\n\tmov\tecx , 8\n\trep\tmovsd\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tjmp\t??end_vesa\n\n??set_vga_mouse:\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VGA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VGA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n??end_vesa:\n\tcall \tReset_Mouse \n\tmov\teax , TRUE\n\tret\n\n??error:\n\tmov\teax,FALSE\n??exit:\n\tret\n\tENDP\tInstall_Mouse\n\n;***************************************************************************\n;* ResET_MOUSE -- Reset mouse to a new graphif mode\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* reset mouse driver funtions to a a currently graphic mode\t\t   *\t\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;* PROTO:\tReset_Mouse ( void ) \t\t\t\t\t   *\t\n;*\t\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/26/1994 JRJ : Created.                                             *\n;*=========================================================================*\nGLOBAL\tReset_Mouse:NEAR\nPROC\tReset_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\n\t;*=========================================================================*\n\t;* Initialize all of the general mouse variables\n\t;*=========================================================================*\n\tmov\tesi , [RealModePtr]\t\t; get offset of real mode data start\n\ttest\tesi , esi\n\tjz\t??exit\n\tmov\teax , [ XRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseX],eax\t; set the mouses x coordinate to 160\n\tmov\teax , [ YRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseY],eax\t; set the mouses y coordinate to 100\n\tmov\t[(KeyboardType esi).MState],1\t; flag the mouse as hidden\n\tmov\t[(KeyboardType esi).MCState],0\t; turn off conditional region\n\tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi).MouseRight],eax\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi).MouseBottom],eax\n\n\n\tmov\t[(KeyboardType esi).Adjust],0\t\t; assume we do not need to adjust mouse\n\n;***************************************************************************\n; Set the Vesa Parameters \n\n\tmov\teax , [ VesaFunc ]\n\ttest\teax , eax\n\tjz\t??set_vga_mouse\n\tmov\t[(KeyboardType esi). VesaPtr ] , eax\n\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VESA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VESA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n \tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi). MouseRight ] , eax\n\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi). MouseBottom ] , eax\n\n\tlea\tedi , [(KeyboardType esi). VesaBankTable]\n\tlea\tesi , [ BankTable ]\n\tmov\tecx , 8\n\trep\tmovsd\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tjmp\t??end_vesa\n\n??set_vga_mouse:\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VGA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VGA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n\n??end_vesa:\n       ; S Mickey/pixel Ratio cursor limits \n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 8\n\tmov\tedx , 16\n\tmov\t[RealInt . _eax ] , 0fh\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\t; Set Min/Max X pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 0\t \n\tmov\tedx , [ XRes ]\n\tcmp\tedx , 320\n\tjne\t??set_it\n\tshl\tedx , 1\n\tmov\t[(KeyboardType esi).Adjust],1\n\n??set_it:\n;\tdec\tedx\n\tmov\t[RealInt . _eax ] , 7\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\t; Set Min/Max Y pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 0\n\tmov\tedx , [ YRes ]\n\tdec\tedx\n\tmov\t[RealInt . _eax ] , 8\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\nIF 0\n\t; Check for scale factors in X and Y pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , [ XRes ]\n\tmov\tedx , [ YRes ]\n\tsub\tecx , 8\n\tsub  \tedx , 16\n\tmov\t[RealInt . _eax ] , 4\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\t; Read mouse position thru int 33 funtion 3\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\txor\tecx , ecx\n\tmov\t[RealInt . _eax ] , 3\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\tmov\tecx ,[RealInt . _ecx]\n\tmov\tedx ,[RealInt . _edx]\n\n      ; compute Scale values X Y for different vendor mouse driver if nessesary\n\tadd \tecx , 8\n\tadd\tedx , 16\n\tcmp\tecx , [ XRes ]\n\tmov\t[(KeyboardType esi).Adjust_XPos],0\n\tjz\t??No_scaleX\n\tmov\t[(KeyboardType esi).Adjust_XPos],ecx\n??No_scaleX:\n\tcmp\tedx , [ YRes ]\n\tmov\t[(KeyboardType esi).Adjust_YPos],0\n\tjz\t??No_scaleY\n\tmov\t[(KeyboardType esi).Adjust_YPos],edx\n??No_scaleY:\t\nENDIF\n\n\tmov\tecx, [ XRes ]\t\t\t\t; set the mouses x coordinate to 160\n\tmov\tedx, [ YRes ]\t\t\t\t; set the mouses x coordinate to 160\n\tcmp\t[(KeyboardType esi).Adjust],1\n\tje\t??no_ecx_shift\n\tshr\tecx , 1\n??no_ecx_shift:\n\tshr\tedx , 1\n\tmov\t[MInstalled],TRUE\t\t\t; set the fact that mouse is installed\n\tmov\t[(KeyboardType esi).MDisabled],TRUE\t; disable mouse until the overlay is loaded\n\n\t; Set new Mouse position any way\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\t[RealInt . _eax ] , 4\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\tcall\tClear_RM_regs\n\tmov\teax, 0300h\n\tmov\tebx ,33h\t\t\t\t; mouse is in 33h\n\tmov\tecx,0\t\t\t\t\t; any mouse condition generates int\n\tmov\tedx,[RealModePtr]\t\t\t; get real mode memory address\n\tshr\tedx,4\t\t\t\t\t; convert it to a segment\n\tmov\t[RealInt. _es],dx\t\t\t; store it in the real mode es\n\tmovzx\tedx,[(KeyboardType PTR esi).MouseCodeOffset] ; Get address of code\n\tmov\t[RealInt._edx],edx\t\t\t; set edx to offset of code\n\tmov\t[RealInt._eax],12\t\t\t; set eax to set interrupt routine\n\tmov\t[RealInt._ecx],31\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n??installed:\n\tmov\teax,TRUE  \t\t\t\t; return TRUE if all is well\n\tmov\t[(KeyboardType esi).MDisabled],FALSE\t; no 32 bit overlays installed\n\tje\t??exit\n\n??error:\n\tmov\teax,FALSE\n\n??exit:\n\tret\n\tENDP\tReset_Mouse\n\n\n\n;***************************************************************************\n;* REMOVE_MOUSE -- uninstalls the mouse interrupt by disabling the call\t   *\n;*                                                                         *\n;* This routine will uninstall the mouse interrupt.  It does this by\t   *\n;* simply disabling the call condition.  The interrupt itself is still\t   *\n;* present, just uncalled until dos removes it at program termination.\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Remove_Mouse(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tRemove_Mouse:NEAR\n\tPROC\tRemove_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\t\n\n\tcall\tClear_RM_regs\n\tcmp \t[MInstalled],FALSE\t; check to see if mouse installed\n\tje\t??exit\t\t\t; if not then no need to remove it\n\n\tmov\t[MInstalled],FALSE\t; Force to NOT-Installed.\n\n;;PWG\tcmp \t[_MSWIFTDevice],1\t; check to see if SWIFT device installed\n;;PWG\tje\tshort ??prevSWIFT\t\t; if so use previous SWIFT event handler\n\n\tmov\tebx , 033h\n\tmov\tedx,[RealModePtr]\t\t\t; get real mode memory address\n\ttest\tedx,edx\t\t\t\t\t; check that the memory block is valid\n\tjz\t??exit\n\n\tshr\tedx,4\t\t\t\t\t; convert it to a segment\n\tmov\t[RealInt._es],dx\t\t\t; store it in the real mode es\n\txor\tedx,edx\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\tmov\tdx,[(KeyboardType PTR esi).MouseCodeOffset] ; Get address of code\n\tmov\t[RealInt._edx],edx\t\t\t; set edx to offset of code\n\tmov\t[RealInt._eax],12\t\t\t; set eax to set interrupt routine\n\tmov\t[RealInt._ecx],0\n\tmov\tecx,0\t\t\t\t\t; no mouse condition generates an int\n\tmov\teax,0300h\n\tlea\tedi,[RealInt]\n\tint\tDPMI_INTR\n\n\tmov\teax,0601h\t\t\t\t; function number.\n\tmov\tecx,[MouseCursor]\t\t\t; ecx must have start of memory.\n\tmov\tedi,[BufferSize]\n\tshl\tedi,1\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n       \tint\tDPMI_INTR\t\t\t; do call.\n\n\n\t; Deallocate real memory buffer\n\tmov\tedx ,[MouseBufferSel]\n\ttest\tdx ,dx\n\tjz\t??exit\n\tmov\teax ,0101h\n\tint\tDPMI_INTR\n\n??exit:\n\tret\n\tENDP\tRemove_Mouse\n\n\n;***************************************************************************\n\nGLOBAL\tClear_RM_regs :NEAR\nPROC\tClear_RM_regs  NEAR \n\n\tpush\teax\n\tpush\tecx\n\tpush\tedi\n\tlea\tedi , [ RealInt ]\n\tlea\tecx , [ RealInt . nothing ]\n\tsub\tecx , edi\n\txor\teax , eax\n\tshr\tecx , 2\n\trep\tstosd\n\tpop\tedi\n\tpop\tecx\n\tpop\teax\n\tret\nENDP\tClear_RM_regs\n\n\n;***************************************************************************\n;* GET_MOUSE_X -- Returns the mouses x pixel position                      *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse x position in pixels\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_X(void);                                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_X:NEAR\n\tPROC\tGet_Mouse_X C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MouseX]\n\tret\n\n\tENDP\tGet_Mouse_X\n\n;***************************************************************************\n;* GET_MOUSE_STATE -- Returns the current mouse state\t\t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse's current state\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_State(void);                                 *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_State:NEAR\n\tPROC\tGet_Mouse_State C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MState]\n\tret\n\n\tENDP\tGet_Mouse_State\n\n;***************************************************************************\n;* GET_MOUSE_X -- Returns the mouses x pixel position                      *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse x position in pixels\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_X(void);                                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_Disabled:NEAR\n\tPROC\tGet_Mouse_Disabled C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmovzx\teax,[(KeyboardType esi).MDisabled]\n\tret\n\n\tENDP\tGet_Mouse_Disabled\n\t\t\t\t  \n;***************************************************************************\n;* GET_MOUSE_Y -- Returns the mouse's y pixel position                     *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:       none\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      int - the mouses y position in pixels                      *\n;*                                                                         *\n;* PROTO:\tint Get_Mouse_Y(void);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_Y:NEAR\n\tPROC\tGet_Mouse_Y C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MouseY]\n\tret\n\n\tENDP\tGet_Mouse_Y\n\n;***************************************************************************\n;* GET_MOUSE_BUTTON -- Gets the values of the mouse button                 *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_Button:NEAR\n\tPROC\tGet_Mouse_Button C NEAR \n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\n\txor\teax,eax\n\tmov\tal,[(KeyboardType esi).Button]\n\tret\n\n\tENDP\tGet_Mouse_Button\n\n;***************************************************************************\n;* SET_MOUSE_CURSOR -- Sets the shape to be used as the mouse.             *\n;*                                                                         *\n;*    This will inform the system of the shape desired as the mouse        *\n;*    cursor.                                                              *\n;*                                                                         *\n;* INPUT:    xhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           yhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           cursor      -- Shape to use as the new mouse shape.           *\n;*                                                                         *\n;* OUTPUT:   Returns with a pointer to the original mouse shape.           *\n;*                                                                         *\n;* PROTO:\tVOID  *Set_Mouse_Cursor(\tint  xhotspot, \t\t   *\n;*\t\t\t\t\t\tint  yhotspot, \t\t   *\n;*\t\t\t\t\t\tvoid *cursor);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   02/13/1992 JLB : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tSet_Mouse_Cursor:NEAR\n\tPROC\tSet_Mouse_Cursor C NEAR \n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\txhotspot:DWORD\t\t\t\t; the x hot spot of the mouse\n\tARG\tyhotspot:DWORD\t\t\t\t; the y hot spot of the mouse\n\tARG\tcursor:DWORD\t\t\t\t; ptr to the new mouse cursor\n\n\tLOCAL\tdatasize:DWORD\n\tLOCAL\tstype:WORD\n\tLOCAL\tswidth:DWORD\t\t; Shape width.\n\tLOCAL\tsheight:DWORD\t\t; Shape height.\n\tLOCAL\tssize:DWORD\t\t; Size of raw shape.\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\n\t;-------------------------------------------------------------------\n\t; Make sure the mouse is Enabled and Installed before continuing\n\t;-------------------------------------------------------------------\n\tmov\teax,[cursor]\n\tcmp\teax,0\t\t\t; if the mouse cursor is in zero page\n\tje\t??exit\t\t\t; it is completely invalid\n\n\tcmp\teax,[PrevMousePtr]\n\tje \t??exit\n\n\tcmp\t[(KeyboardType esi).MDisabled],FALSE\t; make sure the mouse is not disabled\n\tjne\t??exit\t\t\t; if it is not then give it a try\n\n\t;-------------------------------------------------------------------\n\t; We need to wait if a mouse interrupt is in progress.  Once the\n\t; interrupt is finished flag that it is occuring so that it will\n\t; not attempt to draw the mouse while we are changing the cursor.\n\t;-------------------------------------------------------------------\n??try:\n\tinc\t[(KeyboardType esi).MouseUpdate] ; flag that mouse can not be drawn\n\n\t;-------------------------------------------------------------------\n\t; If the mouse is currently on the screen hide it.\n\t;-------------------------------------------------------------------\n\tcall\tLow_Hide_Mouse\n\n\t;-------------------------------------------------------------------\n\t; Calculate the size of the buffer needed.\n\t;-------------------------------------------------------------------\n\tpush\t[cursor]\n\tcall\tGet_Shape_Uncomp_Size\n\tpop\tedx\n\tmov\t[datasize],eax\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Width\n\tpop\tedx\n\tmov\t[swidth],eax\n\tcmp\teax,[BufferWidth]\n\tjg\t??end\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Original_Height\n\tpop\tedx\n\tmov\t[sheight],eax\n\tcmp\teax,[BufferHeight]\n\tjg\t??end\n\n\n\tmov\tebx,[sheight]\n\tmov\teax,[swidth]\n\timul\tebx,eax\n\n??copy_mouse:\n\tmov\tesi,[cursor]\t\t\t; set esi to point to mouse shape\n\tmov\tax,[esi]\t\t\t; get the shape type byte\n\tmov\t[stype],ax\t\t\t; save off the shape type\n\ttest\tax,MAKESHAPE_NOCOMP\t\t; is it marked as no compression?\n\tje\t??comp_shape\t\t\t; if not go to the comped shape code\n\tmov\tedi,[MouseCursor]\t\t; set edi to point to mouse buffer\n??copy_type:\n\n\ttest\t[stype],MAKESHAPE_COMPACT\t; if the shape a 16 color shape?\n\tjne\t??16_color_copy\t\t\t; if it is then go handle it\n\n??normal_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed NORMAL shapes just get run-length uncompressed\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t\t; find size of shape in pixels\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes \n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??norm_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??norm_trans\t\t\t; if its a zero its transparent\n\tmov\t[edi],al\t\t\t; write out the pixel to dest\n\tinc\tedi\t\t\t\t; move to next dest position\n\tdec\tedx\t\t\t\t; we have now written another pix\n\tjnz\t??norm_unrle\t\t\t; if more to write then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are all done\n\n??norm_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\n\tjnz\t??norm_unrle\t\t\t; if more to do then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are done\n\n??16_color_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed 16 color shapes just get remaped and UN-RLE'd\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\tebx,esi\t\t\t\t; save of position of remap\n\tadd\tesi,16\t\t\t\t; move past remap table\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t; load up the height\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes \n\txor\teax,eax\t\t\t\t; clear high of lookup variable\n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??16_color_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??16_color_trans\t\t; if its a zero its transparent\n\tmov\tal,[ebx+eax]\t\t\t; remap the pixel from 16 color table\n\tmov\t[edi],al\t\t\t; store it out to the dest address\n\tinc\tedi\t\t\t\t; move to next dest address\n\tdec\tedx\t\t\t\t; we have now written a pixel\n\tjnz\t??16_color_unrle\n\tjmp\t??done_copy\n??16_color_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\t\t\t\t; subtract off count ahead of time\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\t\t\t\t; or edx to test for zero\n\tjnz\t??16_color_unrle\t\t\n\tjmp\t??done_copy\n\n\t;-------------------------------------------------------------------\n\t; Deal with the compressed shape by copying it into the shape\n\t;   staging buffer.\n\t;-------------------------------------------------------------------\n??comp_shape:\n\tmov\tedi,[_ShapeBuffer]\t; get a pointer to ShapeBuffer\n\tmov\tax,[esi]\t\t; load in the shape type\n\tadd\tesi,2\t\t\t; increment the shape pointer\n\tor\tax,MAKESHAPE_NOCOMP\t; make the shape as uncompressed\n\tmov\t[stype],ax\t\t; save off the shape type\n\tmov\t[edi],ax\t\t; write out uncompressed shape\n\tadd\tedi,2\n\n\t;-------------------------------------------------------------------\n\t; Process the shape header information and copy it over to the new\n\t;   location.\n\t;-------------------------------------------------------------------\n\tmov\tecx,4 \t\t\t; transfer height, width, org and\n\ttest\teax,MAKESHAPE_COMPACT\t; is it a 16 color shape?\n\tje\t??copy_head\t\t; no - don't worry about it\n\tadd\tecx,8\t\t\t; otherwise adjust ecx for header\n??copy_head:\n\trep\tmovsw\t\t\t; copy the necessary bytes\n\t\n\tmov \teax,[datasize]\t\t; get uncompressed length\n\tpush\teax\t\t\t; push as third param\n\tpush\tedi\t\t\t; push the destination offset\n\tpush\tesi\t\t\t; push the source offset\n\tcall\tLCW_Uncompress\t\t; do the uncompress\n\tpop\teax\n\tpop\teax\n\tpop\teax\n\tmov\tesi,[_ShapeBuffer]\n\tmov\tedi,[MouseCursor]\t\t; set edi to point to mouse buffer\n\tjmp\t??copy_type\n\n??done_copy:\n\tmov\tesi,[RealModePtr]\t; get offset of real mode data start\n\n\tmov\teax,[xhotspot]\t\t; get the mouse cursors x hotspot\n\tmov\t[(KeyboardType esi).MouseXHot],eax\n\tmov\teax,[yhotspot]\t\t; get the mouse cursors y hotspot\n\tmov\t[(KeyboardType esi).MouseYHot],eax\n\n\tmov\tebx,[sheight]\t\t; get shape height\n\tmov\t[(KeyboardType esi).MouseHeight],ebx\n\tmov\tebx,[swidth]\n\tmov\t[(KeyboardType esi).MouseWidth],ebx\n\n??error:\n\tcall\tLow_Show_Mouse\n\n\t;-------------------------------------------------------------------\n\t; Final cleanup and exit.\n\t;-------------------------------------------------------------------\n??end:\n\tdec\t[(KeyboardType esi).MouseUpdate]\t\t; we are done modifying the cursor\n??exit:\n\tpush\t[cursor]\n\tpush\t[PrevMousePtr]\n\tpop\teax\n\tpop\t[PrevMousePtr]\n\tret\t\t\t\t; and return back to the world\n\n\tENDP\tSet_Mouse_Cursor\n\n\n;***************************************************************************\n;* LOW_HIDE_MOUSE -- Low-level routine which hides the mouse\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Low_Hide_Mouse:NEAR\n\tPROC\tLow_Hide_Mouse C NEAR \n\tUSES\teax,ebx,esi\n\n\tmov\tebx,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\n\t;*=========================================================================*\n\t;* Is the mouse disabled or hidden?\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType ebx).MDisabled],0 \t; is the mouse disabled?\n\tjne\tshort ??end\n\n   \tcmp\t[(KeyboardType ebx).MState],0 \t; is the mouse hidden?\n\tjne\tshort ??endnodraw\t\t\t; no need to hide again\n\n\t;*=========================================================================*\n\t;* Take care of restoring the mouse cursor\n\t;*=========================================================================*\n\tmov\teax,RESTORE_VISIBLE_PAGE\n\tpush\teax\n\tcall\t[ Mouse_Shadow_Buffer]\n\tpop\teax\n\t;*=========================================================================*\n\t;* The mouse is now hidden -- again.\n\t;*=========================================================================*\n??endnodraw:\n\tadd\t[(KeyboardType ebx).MState],1\n\tadc\t[(KeyboardType ebx).MState],0\n\n??end:\n\tret\n\tENDP\tLow_Hide_Mouse\n\n;***************************************************************************\n;* LOW_SHOW_MOUSE -- Low level routine which shows the mouse\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Low_Show_Mouse:NEAR\n\tPROC\tLow_Show_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tLOCAL\tmousex:DWORD\n\tLOCAL\tmousey:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\n\t;*=========================================================================*\n\t;* Don't show the mouse if it is not hidden or it is disabled\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType esi).MDisabled],0\t; is the mouse disabled\n\tjne\t??exit\t\t\t\t\t; if so then exit\n\n\tcmp\t[(KeyboardType esi).MState],0\t; is the mouse already visible\n       \tje\t??exit\t\t\t\t\t; if so then exit\n\n\t;*=========================================================================*\n\t;* Don't show the mouse if it was hidden multiple times\n\t;*=========================================================================*\n\tdec\t[(KeyboardType esi).MState]\t\t; show the mouse one level\n\tcmp\t[(KeyboardType esi).MState],0\t; can the mouse be shown\n       \tjne\tshort ??exit\n\n\t;*=========================================================================*\n\t;* Determine the theoretcial drawing position of the mouse\n\t;*=========================================================================*\n\tmov\tecx,[(KeyboardType esi).MouseWidth]\t\t; Theoretical buffer width (pixel).\n\tmov\tedx,[(KeyboardType esi).MouseHeight]\t; Theoretical buffer height (pixel).\n\tmov\teax,[(KeyboardType esi).MouseX]\n\tmov\t[mousex],eax\t\t; Draw X pixel.\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\tmov\tebx,[(KeyboardType esi).MouseY]\n\tmov\t[mousey],ebx\t\t; Draw Y pixel.\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\t;*=========================================================================*\n\t;* Determine the theoretical coordinates and dimensions of the\n\t;*\tarea the mouse shape will be rendered upon.\n\t;*=========================================================================*\n\tmov\t[(KeyboardType esi).MouseBuffX],eax\n\tmov\t[(KeyboardType esi).MouseBuffY],ebx\n\tmov\t[(KeyboardType esi).MouseBuffW],ecx\n\tmov\t[(KeyboardType esi).MouseBuffH],edx\n\n;------\tMove the area that will be drawn upon, to the graphic buffer.\n\tmov\teax,STORE_VISIBLE_PAGE\n\tpush\teax\n\tcall\t[ Mouse_Shadow_Buffer ]\n\tpop\teax\n\n;------\tDraw the mouse shape to the seenpage.\n\tpush\t[mousey]\n\tpush\t[mousex]\n\tcall\t[ Draw_Mouse ]\n\tpop\teax\n\tpop\teax\n??exit:\n\tret\n\tENDP\tLow_Show_Mouse\n\n;***************************************************************************\n;* HIDE_MOUSE -- Hides mouse cursor on screen if it was show               *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Hide_Mouse(void);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tHide_Mouse:NEAR\n\tPROC\tHide_Mouse C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Mark us as updating the mouse and then run and do the update\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\t; were drawing the mouse\n\tcall\tLow_Hide_Mouse\t\t\t\t; make the function call\n\tdec\t[(KeyboardType esi).MouseUpdate]\t; were done drawing mouse\n\tret\n\t\n\tENDP\tHide_Mouse\n\n;----------------------------------------------------------------------------\n\n\n;***************************************************************************\n;* SHOW_MOUSE -- Display mouse cursor on screen if it was hidden           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Show_Mouse(void)                                      *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tShow_Mouse:NEAR\n\tPROC\tShow_Mouse C NEAR \n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Mark us as updating the mouse and then run and do the update\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\t; were drawing the mouse\n\tcall\tLow_Show_Mouse\t\t\t\t; make the function call\n\tdec\t[(KeyboardType esi).MouseUpdate]\t; were done drawing mouse\n\tret\n\tENDP\tShow_Mouse\n\n;***************************************************************************\n;* CONDITIONAL_HIDE_MOUSE -- Hides mouse if its with given region          *\n;*                                                                         *\n;* INPUT:\tint sx_pixel - the left-most pixel position of the region  *\n;*\t\tint sy_pixel - the upper-most pixel position of the region *\n;*\t\tint dx_pixel - the right most pixel position of the region *\n;*\t\tint dy_pixel - the lower most pixel position of the region *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Conditional_Hide_Mouse(\tint sx_pixel, \t\t   *\n;*\t\t\t\t\t\tint sy_pixel,\t\t   *\n;*\t\t\t\t\t\tint dx_pixel,\t\t   *\n;*\t\t\t\t\t\tint dy_pixel);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tConditional_Hide_Mouse:NEAR\n\tPROC\tConditional_Hide_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tARG\tsx_pixel:DWORD\t\t\t\t; left x pixel pos\n\tARG     sy_pixel:DWORD\t\t\t\t; upper y pixel pos\n\tARG\tdx_pixel:DWORD\t\t\t\t; right x pixel pos\n\tARG\tdy_pixel:DWORD\t\t\t\t; lower y pixel pos\n\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Widen region leftward by amount mouse shape spills to the right of\n\t;* its hot point.  Limited to the left edge of the screen.\n\t;*=========================================================================*\n\tmov\teax,[(KeyboardType esi).MouseWidth]\t\n\tsub\teax,[(KeyboardType esi).MouseXHot]\t\n\tneg\teax\t\t\t\t\t\n\tadd\teax,[sx_pixel]\n\tjns\tshort ??noleftlimit\n\txor\teax,eax\n??noleftlimit:\n\t;*=========================================================================*\n\t;* Widen region upward by amount mouse shape spills below the\n\t;* mouse's hot point.  Limited by the top edge of the screen.\n\t;*=========================================================================*\n\tmov\tebx,[(KeyboardType esi).MouseHeight]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\tneg\tebx\n\tadd\tebx,[sy_pixel]\n\tjns\tshort ??notoplimit\n\txor\tebx,ebx\n??notoplimit:\n\t;*=========================================================================*\n\t;* Widen region rightward by amount mouse shape spills to the\n\t;* left of its hot point.  Limited by the right edge of the\n\t;* screen.\n\t;*=========================================================================*\n\tmov\tecx,[dx_pixel]\n\tadd\tecx,[(KeyboardType esi).MouseXHot]\n\tcmp\tecx,[(KeyboardType esi).MouseRight]\n\tjb\tshort ??norightlimit\n\tmov\tecx,[(KeyboardType esi).MouseRight]\n\tdec\tecx\n??norightlimit:\n\t;*=========================================================================*\n\t;* Widen region downward by amout the mouse shape extends above\n\t;* its hot point.  Limited to the bottom of the screen.\n\t;*=========================================================================*\n\tmov\tedx,[dy_pixel]\n\tadd\tedx,[(KeyboardType esi).MouseYHot]\n\tcmp\tedx,[(KeyboardType esi).MouseBottom]\n\tjb\tshort ??nobottomlimit\n\tmov\tedx,[(KeyboardType esi).MouseBottom]\n\tdec\tedx\n\n??nobottomlimit:\n\tinc\t[(KeyboardType esi).MouseUpdate]\t\t; don't let interrupt scrag variables\n\n\t;*=========================================================================*\n\t;* The mouse could be in one of four conditions.\n\t;* 1) The mouse is visible and no conditional hide has been specified.\n\t;* \t(perform normal region checking with possible hide)\n\t;* 2) The mouse is hidden and no conditional hide as been specified.\n\t;* \t(record region and do nothing)\n\t;* 3) The mouse is visible and a conditional region has been specified\n\t;* \t(expand region and perform check with possible hide).\n\t;* 4) The mouse is already hidden by a previous conditional.\n\t;* \t(expand region and do nothing)\n\t;*\n\t;* First: Set or expand the region according to the specified parameters\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType esi).MCState],0\n\tjne\tshort ??expand\n\tmov\t[(KeyboardType esi).MouseCXLeft],eax\n\tmov\t[(KeyboardType esi).MouseCYUpper],ebx\n\tmov\t[(KeyboardType esi).MouseCXRight],ecx\n\tmov\t[(KeyboardType esi).MouseCYLower],edx\n\tjmp\t??noylower\n??expand:\n\n\t;*=========================================================================*\n\t;* Expand the clipping rectangle.\n\t;*=========================================================================*\n\tcmp\teax,[(KeyboardType esi).MouseCXLeft]\n\tjb\tshort ??noxleft\n\tmov\t[(KeyboardType esi).MouseCXLeft],eax\n??noxleft:\n\tcmp\tebx,[(KeyboardType esi).MouseCYUpper]\n\tjb\tshort ??noyupper\n\tmov\t[(KeyboardType esi).MouseCYUpper],ebx\n??noyupper:\n\tcmp\tecx,[(KeyboardType esi).MouseCXRight]\n\tja\tshort ??noxright\n\tmov\t[(KeyboardType esi).MouseCXRight],ecx\n??noxright:\n\tcmp\tedx,[(KeyboardType esi).MouseCYLower]\n\tja\tshort ??noylower\n\tmov\t[(KeyboardType esi).MouseCYLower],edx\n??noylower:\n\t;*=========================================================================*\n\t;* If the mouse isn't already hidden, then check its location against\n\t;* the hiding region and hide if necessary.\n\t;*=========================================================================*\n\ttest\t[(KeyboardType esi).MCState],CONDHIDDEN\n\tjne\tshort ??nohide\n\n\tmov\teax,[(KeyboardType esi).MouseX]\n\tmov\tebx,[(KeyboardType esi).MouseY]\n\tcmp\teax,[(KeyboardType esi).MouseCXLeft]\n\tjb\tshort ??nohide\n\tcmp\teax,[(KeyboardType esi).MouseCXRight]\n\tja\tshort ??nohide\n\tcmp\tebx,[(KeyboardType esi).MouseCYUpper]\n\tjb\tshort ??nohide\n\tcmp\tebx,[(KeyboardType esi).MouseCYLower]\n\tja\tshort ??nohide\n\n\t;*=========================================================================*\n\t;* The mouse falls within the region for hiding, so hide it.\n\t;*=========================================================================*\n\n\tcall\tLow_Hide_Mouse\t\t\t\t; make the function call\n\tor\t[(KeyboardType esi).MCState],CONDHIDDEN\n??nohide:\n\n\t;*=========================================================================*\n\t;* Record the fact that a Conditional_Hide_Mouse was\n\t;* called and then exit.\n\t;*=========================================================================*\n\tor\t[(KeyboardType esi).MCState],CONDHIDE\n\tadd\t[BYTE PTR (KeyboardType esi).MCState],1\n\tadc\t[BYTE PTR (KeyboardType esi).MCState],0\n\tdec\t[(KeyboardType esi).MouseUpdate]\n\tret\n\n\tENDP\tConditional_Hide_Mouse\n\n;***************************************************************************\n;* CONDITIONAL_SHOW_MOUSE -- shows mouse if it was conditionally hidden    *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Conditional_Show_Mouse(void);                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tConditional_Show_Mouse:NEAR\n\tPROC\tConditional_Show_Mouse C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]    ; get the real mode offset\n\n\t;*=========================================================================*\n\t; Notify the interrupt that we are updating the mouse\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\n\n\tmov\tax,[(KeyboardType esi).MCState]\n\tcmp\tal,0\n\tje\tshort ??exit\t\t\t; if no more nesting clear cond\n\n\t;*=========================================================================*\n\t;* Decrement the conditional hide counter.\n\t;*=========================================================================*\n\tdec\tal\n\n\t;*=========================================================================*\n\t;* If there are more conditional levels to undo, then just abort the show.\n\t;*=========================================================================*\n\tjne\tshort ??exit\n\n\t;*=========================================================================*\n\t;* Yup, the mouse should be show, but only if it was previously hidden.\n\t;*=========================================================================*\n\ttest\tax,CONDHIDDEN\t\t\t; was it hidden by interrupt??\n\tje\tshort ??exit1\t\t\t; or initial check for level 0\n\n\tcall\tLow_Show_Mouse\n\n??exit1:\n\tmov\tax,0\n\n??exit:\n\tmov\t[(KeyboardType esi).MCState],ax\n\tdec\t[(KeyboardType esi).MouseUpdate]\n\tret\n\tENDP\tConditional_Show_Mouse\n\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VGA_Mouse_Shadow_Buffer:NEAR\n\tPROC\tVGA_Mouse_Shadow_Buffer C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tstore:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\n\tmov\tesi,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[(KeyboardType esi).MouseBuffX]\n\tmov\tebx,[(KeyboardType esi).MouseBuffY]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseBuffW]\n\tadd\tebx,[(KeyboardType esi).MouseBuffH]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseBuffer ]\n\tmov\t[ buffy0 ] , eax\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseBuffW]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseBuffW]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\tpush\tebp\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tebp , ecx\n??restore_loop:\n\tmov\tecx,eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi,ebx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tesi,edi\t\t\t\t\t; xchg the source and the dest\n\tmov\tebp , ecx\n??store_loop:\n\tmov\tecx,eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi,edx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,ebx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n??out:\n\tret\n\tENDP\tVGA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n;* DRAW_MOUSE -- Handles drawing the mouse cursor\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tVGA_Draw_Mouse:NEAR\n\tPROC\tVGA_Draw_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tmousex:DWORD\n\tARG\tmousey:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\n\n\tmov\tesi,[RealModePtr]    \t; get 32 bit offset of dos data\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[mousex]\n\tmov\tebx,[mousey]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseWidth]\n\tadd\tebx,[(KeyboardType esi).MouseHeight]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , eax\n\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseWidth]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseWidth]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch ,[esi]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[edi],ch\n??inc_edi:\n\tinc\tedi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tesi,ebx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t\t\t\t; adjust dest to next line\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\tret\n\n\tENDP\tVGA_Draw_Mouse\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VESA_Mouse_Shadow_Buffer:NEAR\n\tPROC\tVESA_Mouse_Shadow_Buffer C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tstore:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\tlocal\tvesa_linear : dword\n\n\tmov\teax , [ cpu_video_page ]\n\tmov\t[ vesa_linear ] ,  eax\n\n\tmov\tesi,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[(KeyboardType esi).MouseBuffX]\n\tmov\tebx,[(KeyboardType esi).MouseBuffY]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseBuffW]\n\tadd\tebx,[(KeyboardType esi).MouseBuffH]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseBuffer ]\n\tmov\t[ buffy0 ] , eax\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseBuffW]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\tcall\tVesa_Asm_Set_Win\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseBuffW]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\n\tmov\t[ tempreg ] , ebx\n??restore__top_loop:\n\tmov\tah,al\n??restore__inner_loop:\n\tmov\tch ,[esi]\n\tmov\t[edi],ch\n\tinc\tesi\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??restore__in_range\n\tadd\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??restore__in_range:\n\tdec\tah\n\tjnz\t??restore__inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??restore__in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??restore__in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore__top_loop\t\t\t\t; if more to do, do it\n\tjmp\t??out\t\t\t\t\t; get the heck outta the routine\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\tmov\t[ tempreg ] , ebx\n??store_top_loop:\n\tmov\tah,al\n??store_inner_loop:\n\tmov\tch ,[edi]\n\tmov\t[esi],ch\n\tinc\tesi\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??store_in_range\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??store_in_range:\n\tdec\tah\n\tjnz\t??store_inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??store_in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??store_in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_top_loop\t\t\t\t; if more to do, do it\n\n??out:\n\tmov\tedi , [ vesa_linear ]\n\tadd\tedi , 0a0000h\n\tcall\tVesa_Asm_Set_Win\n\n\tret\n\tENDP\tVESA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n;* DRAW_MOUSE -- Handles drawing the mouse cursor\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tVESA_Draw_Mouse:NEAR\n\tPROC\tVESA_Draw_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tmousex:DWORD\n\tARG\tmousey:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\tlocal\ttempreg : dword\n\tlocal\tvesa_linear : dword\n\n\tmov\teax , [ cpu_video_page ]\n\tmov\t[ vesa_linear ] ,  eax\n\n\tmov\tesi,[RealModePtr]    \t; get 32 bit offset of dos data\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[mousex]\n\tmov\tebx,[mousey]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseWidth]\n\tadd\tebx,[(KeyboardType esi).MouseHeight]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , eax\n\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseWidth]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\tcall\tVesa_Asm_Set_Win\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseWidth]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\t[ tempreg ] , ebx\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch ,[esi]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[edi],ch\n??inc_edi:\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??in_range\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??in_range:\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n\n??out:\n\tmov\tedi , [ vesa_linear ]\n\tadd\tedi , 0a0000h\n\tcall\tVesa_Asm_Set_Win\n\n\tret\n\n\tENDP\tVESA_Draw_Mouse\n\n\n;----------------------------------------------------------------------------\nEND\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/NEW/PAGFAULT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : PAGFAULT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Julio R Jerez \t                   *\n;*                                                                         *\n;*                   \t   Date : April 25,1995                            *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;\n; Here are prototypes for the routines defined within this module:\n; VOID Install_Page_Fault_Handle (void) ;\n;\n; ----------------------------------------------------------------\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Make some general equates for easy compatability\n;---------------------------------------------------------------------------\nDPMI_INTR\t EQU\t31h  \nPAGE_FAULT\t equ\t0eh\nRESET_VIDEO_MODE  equ\t-1\n\nGLOBAL\t Install_Page_Fault_Handle : NEAR\nGLOBAL\t Set_Video_Mode\t\t   : NEAR\t\t\nGLOBAL\t Remove_Mouse\t\t   : NEAR\nGLOBAL\t Remove_Keyboard_Interrupt : NEAR\nGLOBAL\t Remove_Timer_Interrupt\t   : NEAR\t\n\nDATASEG\n\tOld_Page_Fault_handle DF ?\n\tPage_Fault_SS \tDD\t?\n\tPage_Fault_ESP\tDD\t?\n\nCODESEG\n;***************************************************************************\n;* INSTALL_PAGE_FAULT_HANDLE -- Installs new page fault handle             *\n;*\tThis function will install a new page fault handle \t\t   *\n;*\tso in the event that we have a program crash thi handle will\t   *\n;*\tremove all interrupts and then will chain to the default Page\t   *\n;*\tFault handle\t\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Install_Page_Fault_Handle( void);  \t\t   *\n;*                                                                         *\n;* HISTORY:  04/25/96 Created                                              *\n;*=========================================================================*\n\tPROC\tInstall_Page_Fault_Handle C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tmov\teax,0202h \t; get address of exception handle\n\tmov\tbl,PAGE_FAULT\n\tint\tDPMI_INTR\n\tjc\t??exit\t\t; not action is taken \n\n\t; save addrees of default handle\n\tmov\t[dword ptr Old_Page_Fault_handle],edx\n\tmov\t[word ptr  Old_Page_Fault_handle+4],cx\n\n\t; redirect default handle to a new Page Fault Handle\n\tmov eax,0203h\t\t\n\tmov bl,PAGE_FAULT\n\tmov cx,cs\n\tlea edx,[Page_Fault_Handle]\n\tint DPMI_INTR \n\n  ??exit:\n\tret\n\tENDP\tInstall_Page_Fault_Handle\n\n\n;***************************************************************************\n;* PAGE_FAULT_HANDLE --  This           \t\t   \t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* HISTORY:  04/25/96 Created                                              *\n;*=========================================================================*\nPROC\tPage_Fault_Handle far \n\n\t; preserve used  registers\n\tpush\teax\n\tpush\tebx\n\t; save Page Fault satck frame\n\tmov\tax,ss\t\n\tmov\t[Page_Fault_SS],eax\n\tmov\t[Page_Fault_ESP],esp\n\n\t; retrieve application original stack frame\n\tmov eax , [ esp + ( 6 + 2 ) * 4 ] \n\tmov ebx , [ esp + ( 7 + 2 ) * 4 ]\n\tmov ss , bx\n\tmov esp , eax\n\n\t; set video mode to standard text mode\n\tpush\tRESET_VIDEO_MODE\n\tcall \tSet_Video_Mode\n\tpop\teax\n\tcall \tRemove_Mouse\n\tcall \tRemove_Keyboard_Interrupt\n\tcall\tRemove_Timer_Interrupt\n\n\t; restore Page Fault stack frame\n\tmov\teax,[Page_Fault_SS]\n\tmov \tss , ax\n\tmov\tesp, [Page_Fault_ESP]\n\n\t; restore used registers and chain to default Page Fault Handle\n\tpop\tebx\n\tpop\teax\n\tjmp\t[fword Old_Page_Fault_handle]\n\n\tENDP\tPage_Fault_Handle\n\n\n;***************************************************************************\n;* End of File.\t\t\t\t\t\t\t\t   *\n;***************************************************************************\nEND\n\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/PAGFAULT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : PAGFAULT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Julio R Jerez \t                   *\n;*                                                                         *\n;*                   \t   Date : April 25,1995                            *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;\n; Here are prototypes for the routines defined within this module:\n; VOID Install_Page_Fault_Handle (void) ;\n;\n; ----------------------------------------------------------------\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Make some general equates for easy compatability\n;---------------------------------------------------------------------------\nDPMI_INTR\t EQU\t31h  \nPAGE_FAULT\t equ\t0eh\nRESET_VIDEO_MODE  equ\t-1\n\nGLOBAL\t Install_Page_Fault_Handle : NEAR\nGLOBAL\t Set_Video_Mode\t\t   : NEAR\t\t\nGLOBAL\t Remove_Mouse\t\t   : NEAR\nGLOBAL\t Remove_Keyboard_Interrupt : NEAR\nGLOBAL\t Remove_Timer_Interrupt\t   : NEAR\t\n\nDATASEG\n\tOld_Page_Fault_handle DF ?\n\tPage_Fault_SS \tDD\t?\n\tPage_Fault_ESP\tDD\t?\n\nCODESEG\n;***************************************************************************\n;* INSTALL_PAGE_FAULT_HANDLE -- Installs new page fault handle             *\n;*\tThis function will install a new page fault handle \t\t   *\n;*\tso in the event that we have a program crash thi handle will\t   *\n;*\tremove all interrupts and then will chain to the default Page\t   *\n;*\tFault handle\t\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Install_Page_Fault_Handle( void);  \t\t   *\n;*                                                                         *\n;* HISTORY:  04/25/96 Created                                              *\n;*=========================================================================*\n\tPROC\tInstall_Page_Fault_Handle C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tmov\teax,0202h \t; get address of exception handle\n\tmov\tbl,PAGE_FAULT\n\tint\tDPMI_INTR\n\tjc\t??exit\t\t; not action is taken \n\n\t; save addrees of default handle\n\tmov\t[dword ptr Old_Page_Fault_handle],edx\n\tmov\t[word ptr  Old_Page_Fault_handle+4],cx\n\n\t; redirect default handle to a new Page Fault Handle\n\tmov eax,0203h\t\t\n\tmov bl,PAGE_FAULT\n\tmov cx,cs\n\tlea edx,[Page_Fault_Handle]\n\tint DPMI_INTR \n\n  ??exit:\n\tret\n\tENDP\tInstall_Page_Fault_Handle\n\n\n;***************************************************************************\n;* PAGE_FAULT_HANDLE --  This           \t\t   \t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* HISTORY:  04/25/96 Created                                              *\n;*=========================================================================*\nPROC\tPage_Fault_Handle far \n\n\t; preserve used  registers\n\tpush\teax\n\tpush\tebx\n\t; save Page Fault satck frame\n\tmov\tax,ss\t\n\tmov\t[Page_Fault_SS],eax\n\tmov\t[Page_Fault_ESP],esp\n\n\t; retrieve application original stack frame\n\tmov eax , [ esp + ( 6 + 2 ) * 4 ] \n\tmov ebx , [ esp + ( 7 + 2 ) * 4 ]\n\tmov ss , bx\n\tmov esp , eax\n\n\t; set video mode to standard text mode\n\tpush\tRESET_VIDEO_MODE\n\tcall \tSet_Video_Mode\n\tpop\teax\n\tcall \tRemove_Mouse\n\tcall \tRemove_Keyboard_Interrupt\n\tcall\tRemove_Timer_Interrupt\n\n\t; restore Page Fault stack frame\n\tmov\teax,[Page_Fault_SS]\n\tmov \tss , ax\n\tmov\tesp, [Page_Fault_ESP]\n\n\t; restore used registers and chain to default Page Fault Handle\n\tpop\tebx\n\tpop\teax\n\tjmp\t[fword Old_Page_Fault_handle]\n\n\tENDP\tPage_Fault_Handle\n\n\n;***************************************************************************\n;* End of File.\t\t\t\t\t\t\t\t   *\n;***************************************************************************\nEND\n\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/X/KEYBOARD.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : KEYBOARD.ASM                             *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 15, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Get_RM_Timer_Address -- Return address of real mode code for copy.    *\n;*   Get_RM_Keyboard_Size -- return size of real mode timer code.          *\n;*   Check_Key -- checks queue for key (make)                              *\n;*   Check_Key_Num -- Checks if key in queue, return key num               *\n;*   Get_Key_Num -- Returns the next key num in ax                         *\n;*   KN_To_KA -- Translates a key num to an ASCII key                      *\n;*   Low_Get_Key -- low level get key returns key num and bits             *\n;*   Convert_Num_To_ASCII -- Assembly routine converts keynum to ASCII key *\n;*   KeyNum_Translate -- Performs a lowlevel xlate to a keycode            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\n;*\tKeyboard driver -- 80386 Protected Mode Assembly portion\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   \n;***************************************************************************\n;\n; ----------------------------------------------------------------\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\n;WARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Make some general equates for easy compatability\n;---------------------------------------------------------------------------\nPROT_INT_ENABLE\tEQU\t1\t\t; if false protected int just calls real mode int\n\nDPMI_INTR\tEQU\t31h\t\nIRQ1INTNUM\tEQU\t09h\t\t; IRQ1 interrupt vector number.\nBRKINTNUM\tEQU\t23h\t\t; Crtl-C (Break) interrupt vector number\nDBGINTNUM\tEQU\t3h\t\t; Debug interrupt vector number\nDOS_SYS_CALL\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nLOCK_PAGES\tEQU\t5\t\t; Lock pages subfunction using DX_MEM_MGT\nUNLOCK_PAGES\tEQU\t6\t\t; Unlock pages subfunction using DX_MEM_MGT\nCLEARISR\tEQU\t020H\t; value to clear In Service Register\nINTCHIP0\tEQU\t020H\t; 8259 interrupt chip controller 0\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\n\tINCLUDE \"keyboard.inc\"\n\tINCLUDE \"keystruc.inc\"\n\tINCLUDE \"mcgaprim.inc\"\n\n\tGLOBAL\t RealModePtr:DWORD\n\n\tGLOBAL\t Install_Keyboard_Interrupt:NEAR\n\tGLOBAL\t Get_RM_Keyboard_Address:Near\n\tGLOBAL\t Get_RM_Keyboard_Size:Near\n\tGLOBAL\t Remove_Keyboard_Interrupt:NEAR\n\tGLOBAL\t Check_Key_Num:NEAR\n\tGLOBAL\t Get_Key_Num:NEAR\n\tGLOBAL\t KN_To_KA:NEAR\n\tGLOBAL\t KeyNum_Translate:NEAR\n\tGLOBAL\t Check_Key:NEAR\n\tGLOBAL\t Get_Key:NEAR\n\tGLOBAL\t Keyboard_Attributes_On:NEAR\n\tGLOBAL\t Clear_KeyBuffer:NEAR\n\tGLOBAL\t Key_Down:NEAR\n\tGLOBAL\t Keyboard_Attributes_Off:NEAR\n\tGLOBAL\t Check_Key_Bits:NEAR\n\tGLOBAL\t Get_Key_Bits:NEAR\n\tGLOBAL\t Key_Satisfied:NEAR\n\tGLOBAL\t Stuff_Key_WORD:NEAR\n\tGLOBAL\t Stuff_Key_Num:NEAR\n\tGLOBAL\t MouseQX:DWORD\n\tGLOBAL\t MouseQY:DWORD\n;DBG\n\tGLOBAL   Keyboard_Interrupt:NEAR\n\n\n\tDATASEG\n; For the current time we will just include the real mode stuff\n; into the protected mode code and then copy it down.  The C side of\n; this will handle this method or reading it off of disk in the real\n; method.\n\nLABEL \tRealBinStart\tBYTE\ninclude \"keyireal.ibn\"\nLABEL\tRealBinEnd\tBYTE\n\nLABEL\tLockedDataStart\tBYTE\t\nRMVector\tDD\t0\nRealModeSel\tDD\t0\nRealModePtr\tDD\t0\t\t; Pointer to real mode memory.\nRealModeSize\tDD\t0\t\t; Pointer to real mode memory.\n\nKeyboard_App_Stack_ESP\tDD 0\t\t; This the System Stack Offsset\nKeyboard_App_Stack_SS\tDD 0\t\t; This the System Stack Selector\nKeyboard_StackPointer\tDD 0DEADDEADh\t; We Create a Local Application\nKeyboard_Stack          DD 255 dup (0)\nKeyboard_StackStart\tDD 0\n\t\t\t\t\t; StackPointer \t\nLABEL\tLockedDataEnd\tBYTE\n\n\n\nAscii\tDB\t0,\"`1234567890-=\",0,8,9,\"qwertyuiop[]\\\",0,\"asdfghjkl;'\"\n\tDB\t0,13,0,45,\"zxcvbnm,./\",0,0,0,0,0,\" \"\n\nShift\tDB\t0,\"~!@#$%^&*()_+\",0,8,9,\"QWERTYUIOP{}|\",0,\"ASDFGHJKL:\",22H\n\tDB\t0,13,0,45,\"ZXCVBNM<>?\",0,0,0,0,0,\" \"\n\nAlpha_Lower\tDB\t0\n\tDB\t\"~!@#$%^&*()_+\",0,8,9,\"qwertyuiop{}|\",0,\"asdfghjkl:\",22H\n\tDB\t0,13,0,45,\"zxcvbnm<>?\",0,0,0,0,0,\" \"\n\nAlpha_Shift\tDB\t0\n\tDB\t\"`1234567890-=\",0,8,9,\"QWERTYUIOP[]\\\",0,\"ASDFGHJKL;'\"\n\tDB\t0,13,0,45,\"ZXCVBNM,./\",0,0,0,0,0,\" \"\n\nEdit\tDB\t0AEH,0ADH,000H,000H,0B5H,0B9H,0B1H,000H,0B8H,0B0H,0B7H,0AFH\n\tDB\t000H,000H,0B3H,000H,0B9H,0B5H,0B1H,000H, \"/\",0B8H,0B4H,0B0H\n\tDB\t0AEH, \"*\",0B7H,0B3H,0AFH,0ADH, \"-\", \"+\",000H,00DH,000H\n\nNumPad\tDB\t0,\"741\",0,\"/8520*963.-+\",0,13,0\n\n\nGetKeyLock\tDW\t0\t; snap shot of num and caps lock bits\nInitFlags\tDW\t0\nMouseQX\t\tDD\t0\nMouseQY\t\tDD\t0\n\n\tCODESEG\n;***************************************************************************\n;* GET_RM_TIMER_ADDRESS -- Return address of real mode code for copy.      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      VOID * to the address of the real mode timer               *\n;*                                                                         *\n;* PROTO:\tVOID\t*Get_RM_Keyboard_Address(VOID);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Address C Near\n\n\tmov\teax, OFFSET RealBinStart\n\tret\n\n\tENDP\n\n;***************************************************************************\n;* GET_RM_KEYBOARD_SIZE -- return size of real mode timer code.            *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      LONG size of the real mode timer code                      *\n;*                                                                         *\n;* PROTO:\tLONG\tGet_RM_Keyboard_Size(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Size C Near\n\n\tmov\teax, OFFSET RealBinEnd - OFFSET RealBinStart\n\tret\n\n\tENDP\n;***************************************************************************\n;* INSTALL_KEYBOARD_INTERRUPT -- Installs the keyboard interrupt           *\n;*                                                                         *\n;* INPUT:\tint rm_ptr  - ptr to the real mode handler\t\t   *\t   *\n;*\t\tint rm_size - size of the real mode handler\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Install_Keyboard_Interrupt(int rm_ptr, int rm_size);  *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tInstall_Keyboard_Interrupt C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\tARG\trm_ptr:DWORD\n\tARG\trm_size:DWORD\n\n\t; Are they attempting to set timer again?\n\tcmp\t[RealModePtr],0\n\tjnz\t??error\n\n\t; Make sure all flags are cleared.\n\tcmp\t[InitFlags],0\n\tjnz\t??error\n\n\n\t; Before setting the interrupt vectors, the code needs to be locked\n\t; for DPMI compatability.  Any code or data accessed must be lockded\n\t; so that no page faults accure during an interrupt.\n\t; First lock the code, then the data.  The stack will already be locked.\n\t; The real mode code is also already locked be default.\n\t; To lock a page set up registers :\n\t; AX = 0600h\n\t; BX:CX\t= starting linear address of memory block\n\t; SI:DI = size of region\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_CODE\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_DATA\n\n\t; now allocate real mode memory and copy the rm binary down to it.\n\tmov\teax,0100h\t; set function number\n\tmov\tebx,[rm_size]\t\t; get size of RM binary.\n\tmov\t[RealModeSize],ebx\n\tadd\tebx,15\t\t\t; round up \n\tshr\tebx,4\t\t\t; convert to pages.\n\tint\tDPMI_INTR\t \t; do call.\n\tjc\t??error\t\t \t; check for error.\n\tor\t[InitFlags],IF_ALLOC_RM ; set successful\n\tmov\t[RealModeSel],edx\n\tshl\teax,4\t\t\t; convert segment to offset.\n\tmov\t[RealModePtr],eax\t; save offset to global variable.\n\n\t; now lock the real mode memory that we allocated\n\tmov\teax,0600h\t\t; function number.\n\tmov\tecx,[RealModePtr]\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_RM_CODE\n\n\n\n\t; set up source and destination pointers for the copy.\n\tmov\teax,[RealModePtr];\t; set up our dest pointer\n\tmov\tesi,[rm_ptr]\t\t; Set up our source pointer.\n\tmov\tedi,eax\t\t\t; put it into esi for copy.\n\tmov\tecx,[rm_size]\n\trep\tmovsb\t\t\t; write RM bin to RM memory.\n\n\t; restore esi to point to data and initialize some of it.\n\tmov\tesi,[RealModePtr]\n\tmov\teax,esi\n\tshl\teax,12\t\t\t\t\t\t; make seg in high eax.\n\tmov\tax,[(KeyboardType PTR esi).CallKeyRMIntOffset]\t; create RM addr of call chain.\n\tmov\t[(KeyboardType PTR esi).CallKeyRMIntAddr],eax\t; save it for use in PM int.\n\nIF NOT PROT_INT_ENABLE\n       ; Chain the Real Keyboard interrupt to any avilable\n       ; Interrupt vector so We make sure that the Real Mode\n       ; Keyboard Interrupt service get called at debuging time\n       ; of the library.\n\n       mov\tedi , eax\n       mov\tbl , 060h\n       mov\tbh , 6\n       mov\teax , 200h\n ??find:\n       int\tDPMI_INTR\n       jc\t??error\n       or\tcx,dx\n       jz\t??found\n       inc\tbl\n       dec\tbh\n       jnz\t??find\n       jmp\t??error\n ??found:\n       movzx\tebx , bl\n       mov\t[ byte ptr RMVector ] , bl\n       mov\t[ 4 * ebx ] , edi\nENDIF\n\n\n\n\t;-------------------------------------------------------\n\t; Initialize all of the keyboard specific information\n\t;-------------------------------------------------------\n\txor\teax,eax\t\t\t; clear the high bits of eax\n\tmov\tal,[417H]\t\t; get keyboard status flags\n\ttest\teax,040H \t\t; caps lock active?\n\tje \tshort ??nocap\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\n\n??nocap:\n\ttest\teax,020H\t\t\t; num lock active?\n\tje\tshort ??nonumlock\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\n\n??nonumlock:\n\ttest\teax,002H\t\t\t; is left shift key down?\n\tje\tshort ??noleftshift\t\t; try the right\n\tor\t[(KeyboardType PTR esi+5).KeysUpDown],010H\n\n??noleftshift:\n\tand\teax,001H\t\t\t; get right shift bit\n\tshl\teax,9\t\t\t; put it into the proper position (shl al,1 mov ah,al)\n\tmov\tal,[418H]\t\t; get alt and ctrl bits\n\tshl\tal,2\t\t\t; put in proper position\n\tshl\tal,1\n\tand\tal,00CH\t\t\t; only alt and ctrl bits\n\tor\tah,al\t\t\t; put them ah for Keys+7 later\n\tmov\tal,[496H]\t\t; get extended keys\n\ttest\tal,008H\t\t\t; check for right alt key\n\tje\tshort ??noralt\n\tor\tah,040H\n??noralt:\n\tmov\t[(KeyboardType PTR esi+7).KeysUpDown],ah\n\ttest\tal,004H\t\t\t; test for right ctrl\n\tje \tshort ??norctrl\n\tor\t[(KeyboardType PTR esi+8).KeysUpDown],001h\n??norctrl:\n\ttest\tal,002H\t\t\t; last code E0?\n\tje short ??noe0\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],001h\n??noe0:\n\ttest\tal,001H\t\t\t; last code E1?\n\tje short ??noe1\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],002h\n??noe1:\n\t;==========================================================================\n\t; Get the protected mode interrupt vector keyboard.\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).KeyOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).KeyOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 2503, cl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).KeyOldRMI],ecx\n\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt Keyboard\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Keyboard_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt Keyboard\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).KeyCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the break interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\t\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).BrkOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).BrkOldPMISelector],ecx\t; save selector.\n\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector - for the break interrupt\n\t; input ax = 0200, bl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).BrkOldRMI],ecx\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Break_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).BrkCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\nIF DEBUG\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the Debug interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\t\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,DBGINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).DbgOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).DbgOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Debug_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\nENDIF\n\n\t; we have finished with success.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n??exit:\n\tret\n\tENDP\tInstall_Keyboard_Interrupt\n\n;***************************************************************************\n;* REMOVE_INTERRUPT -- Removes keyboard interrupt and restores chain\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Remove_Interrupt(VOID)                                *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tRemove_Keyboard_Interrupt C NEAR \n\tUSES\tebx,ecx,edx\n\n\t; verifie that the keyboard was previosly install\n\t; this is here in case of a page fault crash\n\tmov\tesi,[RealModePtr]\n\ttest    esi,esi\n\tjz      ??error\n\n\ttest\t[InitFlags],IF_SET_VECTORS\n\tjz\t??vectors_not_set\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tedx,[(KeyboardType esi).KeyOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[(KeyboardType esi).KeyOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).KeyOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\n\t; disengage Control Break Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tedx,[(KeyboardType esi).BrkOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[(KeyboardType esi).BrkOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).BrkOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\nIF DEBUG\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tecx,[(KeyboardType esi).DbgOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).DbgOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\nENDIF\n\nIF NOT PROT_INT_ENABLE\n       ; Clean up the Users interrupt table\n        mov\teax , 201h\n       mov\tbl , [ byte ptr RMVector ]\n       xor\tecx , ecx\n       xor\tedx , edx\n       int\tDPMI_INTR\n       jc\t??error\nENDIF\n\n\n??vectors_not_set:\n\t; now free up the real mode memory.\n\ttest\t[InitFlags],IF_LOCKED_RM_CODE\n\tjz\t??rm_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,[RealModePtr]\t\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t\t; edx will have size of region in bytes.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??rm_not_locked:\n\ttest\t[InitFlags],IF_ALLOC_RM\n\tjz\t??mem_not_allocated\n\tmov\teax , 0101h\n\tmov\tedx,[ RealModeSel ] \t\t; get physical address of real mode buffer.\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n??mem_not_allocated:\n\n\t; Now we can unlock all stuff needed for the interrupt.  \n\t; Unlock Code\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??code_not_locked:\n\n\t; Unlock data\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??data_not_locked:\n\n\t; we have finished with success.\n\tmov\t[RealModePtr],0\t\t; To say we can do it again sometime.\n\tmov\t[InitFlags],0\t\t; To say we can do it again sometime.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n\tret\n\tENDP\tRemove_Keyboard_Interrupt\n\n\n;***************************************************************************\n;* CHECK_KEY_NUM -- Checks if key in queue, return key num                 *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      Keynum of the key that was pressed, FALSE otherwise        *\n;*\n;* PROTO:\tINT Check_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Num C NEAR \n\tUSES\tebx,esi\n\tpushf\t\t\t\t\t; save off the flags\n\tcli\t\t\t\t\t; disable interrupts\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t\t\n\txor\teax,[(KeyboardType PTR esi).KeyBufferTail]\t\t\n\tor\teax,eax\t\t\t\t; check to see if head == tail\n\tjz\tshort ??fini\t\t\t; if so we are done\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t; get the head\n\tmov\tax,[(KeyboardType PTR esi+eax).KeyBuffer]\t; get key num\n\n??fini:\n\tsti\n\tpopf\n\tret\n\n\tENDP\tCheck_Key_Num\n\n;***************************************************************************\n;* GET_KEY_NUM -- Returns the next key num in ax                           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      WORD key flags are in the high byte of return word, key    *\n;*\t\t  num is in the low byte.\n;*                                                                         *\n;* PROTO:\tWORD Get_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Num C NEAR\n\tUSES\tesi,edi\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n??wait:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t\t; get the head\n\tcmp\teax,[(KeyboardType PTR esi).KeyBufferTail]\t\t; get the head\n\tjne\tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??wait\n\n??getkey:\n\tcall\tLow_Get_Key\n\tsti\t\t\t\t; enable interrupts\n\tret\n\n\tENDP\tGet_Key_Num\n\n;***************************************************************************\n;* KN_TO_KA -- Translates a key num to an ASCII key                        *\n;*                                                                         *\n;* INPUT:\tWORD the keynum to translate                               *\n;*                                                                         *\n;* OUTPUT:      WORD the ASCII key that is returned                        *\n;*                                                                         *\n;* PROTO:\tINT KN_To_KA(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tKN_To_KA C NEAR\n\tARG\tkeynum:DWORD\n\n\tmov\teax,[keynum]\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\tret\n\n\tENDP\tKN_To_KA\n\n\n;***************************************************************************\n;* LOW_GET_KEY -- low level get key returns key num and bits               *\n;*                                                                         *\n;* INPUT:\tAX - index into the buffer                                 *\n;*                                                                         *\n;* OUTPUT:      AX - key num with bits                                     *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tLow_Get_Key C NEAR \n\tUSES\tebx,esi,edi\n\n\tmov\tedi,eax\t\t\t\t; save off value in ax\n\n; We should set up both DS & ES because we are a low level function\n; and don't know who might have called us or what the registers\n; currently are.\n\n; No reason to set DS & ES.\n; This is not a hardware interrupt and if the funtion is being called\n; from within a hardware interrupt then DS and ES will be preset to\n; DGROUP _DATA\n\t\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tcmp\tal,KN_LMOUSE\n\tjb \tshort ??cont\n\tcmp\tal,KN_RMOUSE\n\tja \tshort ??chkjoy\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t; 128 word circular buffer\n\n\tmov\t[MouseQX],eax\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\t[MouseQY],eax\n\n\tpop\teax\t\t\t; restore keynum for return\n\n\tjmp\tshort ??cont\n\n??chkjoy:\n\tcmp\tal,KN_JBUTTON2\t\t; mouse button before joystick button\n\tja \tshort ??cont\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tpop\teax\t\t\t; restore keynum for return\n??cont:\n\tmov\t[(KeyboardType PTR esi).KeyBufferHead],edi\t; set the head\n\n??out:\n\tret\n\n\tENDP\tLow_Get_Key\n\n;***************************************************************************\n;* CONVERT_NUM_TO_ASCII -- Assembly routine converts keynum to ASCII key   *\n;*                                                                         *\n;* INPUT:\tEAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - holds the key num bits                        *\n;*\t\t\tAL - holds the key num value\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      EAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - hold the key bits                             *\n;*\t\t\tAL - holds the ASCII key value\t\t\t   *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* WARNINGS:    GetKeyLock must be set prior to calling this function\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tConvert_Num_To_ASCII C NEAR \n\tUSES\tebx,ecx,esi,edi\n\n\t;*===================================================================\n\t;* Force all breaks to be thrown out.\n\t;*===================================================================\n\ttest\teax,08000h\t\t; If it is a button number\n\tjne\tshort ??button\t\t;  don't process it\n\n\ttest\tah,KEYRELEASE\t\t; If it is not key release\n\tje\tshort ??ok\t\t;  then go process it\n\n??button:\n\txor\teax,eax\t\t\t; no ascii value for a button\n\tret\n\n??ok:\n\t;*===================================================================\n\t;* ES points to the DOSMEM selector, esi is the offset of the \n\t;*   protected mode structure.\n\t;*===================================================================\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\n\t;*===================================================================\n\t;* Start dealing with the keys.\t\t\t\t\t  \n\t;*===================================================================\n\tcmp\tal,110\t\t\t; is it esc\n\tje\t??esc\t\t\t; if so then deal with it\n\n;??chkext:\n\tcmp\tal,62\t\t\t; is it extended?\n\tjae\tshort ??extended\t; its extended so return ext code\n\n\tmov\tebx,eax\t\t\t; get an index\n\tand\tebx,03FH\t\t; only 0-63 allowed\n\ttest\tah,1\t\t\t; if not, test for shift\n\tjnz\tshort ??shifted\t\t; if shifted get shift value\n\n\t;*===================================================================\n\t;* Here when we have an unshifted ascii key\n\t;*===================================================================\n\tmov\tal,[Ascii+ebx]\t\t; get the ascii code for this number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_lowered:\n\tmov\tal,[Alpha_Lower+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_shifted:\n\tmov\tal,[Alpha_Shift+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* Shift'ed character\n\t;*===================================================================\n??shifted:\n\tmov\tal,[Shift+ebx] \t\t; get ascii shift code for number\n\n??ctrlkey:\n\ttest\tah,2\t\t\t; is it ctrl?\n\tjz \tshort ??jexit\t\t; izf not skip ctrl check\n\n\tmov\tedi,ebx\t\t\t; get index\n\tand\tedi,7\t\t\t; only bits 0-7\n\n\tmov\tcl,[(KeyboardType PTR esi+edi).Bits]\n\n\tshr\tebx,3\t\t\t; div by 8 for byte offset\n\ttest\t[(KeyboardType PTR esi+ebx).KeysCapsLock],cl\t\n\tje \tshort ??jexit\n\tand\tal,01FH\t\t\t; force to ctrl value\n\n??jexit:\n\tjmp short ??exit\n\n??extended:\n\tcmp\tal,75\t\t\t; if less than insert\n\tjb \tshort ??special\n\tcmp\tal,110\t\t\t; if >= esc\n\tjae \tshort ??funckey\n\n??editkeys:\n\txor\tebx,ebx\n\tmov\tbl,al\n\tsub\tebx,75\t\t\t; get value from 0-34\n\ttest\t[(KeyboardType PTR esi).KeyFlags],NONUMLOCK\n\tjne \tshort ??no_numpad\n\ttest\t[GetKeyLock],NUMLOCK\t; look at the snap shot of bits\n\tjne \tshort ??numpad\n\n??no_numpad:\n\tmov\tal,[Edit+ebx] \t\t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??numpad:\n\tsub\tebx,15\t\t\t; adjust to numpad entries\n\tmov\tal,[NumPad+ebx] \t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??funckey:\n\tcmp\tal,112\t\t\t; if less than function keys\n\tjb \tshort ??extout\n\tcmp\tal,121\t\t\t; if greater than function keys 1-10\n\tja \tshort ??extout\n\tmov\tbl,al\n\tsub\tbl,112\t\t\t; get value 0-9\n\tmov\tbh,0C5H\t\t\t; function key 1 no shift-ctrl-alt\n\ttest\tah,7\t\t\t; any shift-ctrl-alt\n\tje\tshort ??funcadj\n\tmov\tbh,098H\t\t\t; function key 1 alt\n\ttest\tah,ALTPRESS\t\t; (highest prescendence)\n\tjne \tshort ??funcadj\n\tmov\tbh,0A2H\t\t\t; function key 1 ctrl (next highest)\n\ttest\tah,CTRLPRESS\n\tjne\tshort ??funcadj\n\tmov\tbh,0ACH\t\t\t; function key 1 shift (lowest)\n\n??funcadj:\n\tsub\tbh,bl\t\t\t; adjust function key to a\n\tmov\tal,bh\t\t\t; shift/no shift etc\n\tjmp\tshort ??exit\n\n??special:\n\tcmp\tal,65\t\t\t; if less than specials\n\tjb\tshort ??extout\n\n\tadd\tal,133\t\t\t; make value between 198-207 or\n\tjmp\tshort ??exit\t\t; 0C6H-0CFH\n\t\n??extout:\n\tor\tal,080H\n\tjmp\tshort ??exit\n\n??esc:\n\tmov\tal,01BH\n\n??exit:\n\tret\n\tENDP\tConvert_Num_To_ASCII\n\n;***************************************************************************\n;* CHECK_KEY -- checks for ASCII keys sitting in the keybuffer             *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      INT the ASCII sequence for the key that was pressed        *\n;*                                                                         *\n;* PROTO:\tINT Check_Key(VOID);                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key C NEAR\n\tUSES\tebx,edi,esi\n\n\tpushf\n\tcld\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tcmp\tal,KN_LMOUSE\t\t; check if it is a mouse or joystick\n\tjb\tshort ??contget\n\tcmp\tal,KN_JBUTTON2\n\tja\tshort ??contget\n\tadd\tsi,4\t\t\t; get rid of the x and y values\n\n??contget:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\teax,eax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\tsti\t\t\t\t; enable interrupts\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tcall\tnear ptr Convert_Num_To_ASCII\n\t\t\t\t\t; AX has ASCII code with bits\n\n\txor\tah,ah\t\t\t; clear key bits\n??exit:\n\tpopf\n\tret\n\tENDP\tCheck_Key\n\n\n;***************************************************************************\n;* GET_KEY -- Gets the next available ASCII keystroke.\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      AH - hold the key bits                                     *\n;*\t\tAL - holds the ASCII key value\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tINT Get_Key(VOID);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key C NEAR \n\tUSES \tebx,ecx,edi\n\n\tcld\t\t\t\t; clear the direction flag for speed\n\n\t; Check_Key had to be copied because of enable and disable of ints\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\t\t\t\t\t; AX has key num code with bits\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\txor\tah,ah\n\tret\n\n\tENDP\tGet_Key\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_ON -- Sets the specified keyflags on                *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned on                 *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are on                       *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_On(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_On C NEAR\n\tUSES\tesi,edi\n\tARG\tbits:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tor\t[(KeyboardType PTR esi).KeyFlags],eax\n\n\t; Only do this if in playback or record mode.\n\ttest\teax,PASSBREAKS\n\tje\tshort ??fini\n\n\txor\teax,eax\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).KeysUpDown\n\tmov\t[edi],eax\n\tmov\t[edi+4],eax\n\tmov\t[edi+8],eax\n\tmov\t[edi+12],eax\n??fini:\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\n\tret\n\tENDP\tKeyboard_Attributes_On\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_OFF -- Sets the specified keyflags off              *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned off                *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are off                      *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_Off(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_Off C NEAR\n\tUSES\tesi\n\tARG\tbits:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tnot\teax\n\tand\t[(KeyboardType PTR esi).KeyFlags],eax\n\txor\teax,eax\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\n\tret \n\n\tENDP\tKeyboard_Attributes_Off\n;***************************************************************************\n;* CLEAR_KEYBUFFER -- Clears keystrokes out of the key buffer              *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Clear_KeyBuffer(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tClear_KeyBuffer C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tcli\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\tsti\n\n\tret\n\n\tENDP\tClear_KeyBuffer\n\n;***************************************************************************\n;* KEY_DOWN -- tests the status of a keyboard key                          *\n;*                                                                         *\n;* INPUT:\tINT the key num to check                                   *\n;*                                                                         *\n;* OUTPUT:      INT zero if the key is up, none zero if the key is down    *\n;*                                                                         *\n;* PROTO:\tINT Key_Down(INT key);\t\t\t\t   \t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Down C NEAR\n\tUSES\tebx,ecx,edi,esi\n\tARG\tkey:DWORD\n\n\tpush\t[key]\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\txor\tah,ah\t\t\t\t; Always ignore the control bits.\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tedi,eax\n\tshr\tedi,3\n\tmov\tcl,al\n\tand\tcl,0111b\n\tmov\tal,01b\n\tshl\tal,cl\n\tand\tal,[(KeyboardType PTR esi+edi).KeysUpDown]\n\tret\n\n\tENDP\tKey_Down\n\n;***************************************************************************\n;* CHECK_KEY_BITS -- checks ascii key in key buff with shift,ctrl,alt bits *\n;*                                                                         *\n;* INPUT:\tnone \t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set     *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Bits C NEAR\n\tUSES\tebx,ecx,edi,esi\n\n\tpushf\t\t\t\t\t; save off the direction flag\n\tcld\t\t\t\t\t; we will go forward\n\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n??playback:\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\t;------ If there is a NULL in the keyboard buffer, we must NOT treat it\n\t;\tas a valid ASCII value because the calling code will falsely\n\t;\tassume that the NULL return value indicates an empty buffer.\n\tor\tal,al\n\tje\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\tax,ax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tCheck_Key_Bits\n;***************************************************************************\n;* GET_KEY_BITS -- Gets ascii key in key buff with shift,ctrl,alt bits     *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set\t   *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Bits C NEAR \n\tUSES\tebx,ecx,edi\n\n\tcld\n\n\t; Check_Key_Bits was copied because of enable and disable of interrupts\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\tret\n\n\tENDP\tGet_Key_Bits\n\n;***************************************************************************\n;* KEY_SATISFIED -- checks to see if the given key is satisfied            *\n;*                                                                         *\n;* INPUT:   INT the key flags/number to check                          \t   *\n;*                                                                         *\n;* OUTPUT:  INT 0 if the key is not satisfied, !0 if the key is satisfied  *\n;*                                                                         *\n;* PROTO:   VOID Key_Satisfied(INT key);                                    *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Satisfied C NEAR\n\tUSES\tebx,ecx,esi,edi\n\tARG\tkey:DWORD\n\n\tmov\teax,[key]\n\tmov\tebx,eax\t\t\t; save key code\n\tpush\teax\n\tcall\tKey_Down\t\t; see it its even down\n\tadd\tesp,4\n\tcmp\teax,0\n\tje\t??out\t\t\t; if not it can't be satisfied\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,ebx\t\t\t; if so, restore code\n\txor\tah,ah\t\t\t; clear out flags area\n\tmov\tedi,eax\t\t\t; set as an index\n\tshr\tedi,3\t\t\t; div by 8 for bytes\n\tmov\tch,1h\t\t\t; set a bit for mask\n\tmov\tcl,al\t\t\t; get the code number\n\tand\tcl,7\t\t\t; get the actual bit this code is\n\tshl\tch,cl\t\t\t; move bit into mask position\n\n; now test the ctrl,alt and shift bits\n\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],04h\t; is the left ctrl down?\n\tjne \tshort ??ctrlon\t\t; if so, ctrl is on\n\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],01h\t; is the right ctrl down?\n\tje \tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n??ctrlon:\n\tor\tah,02h\t\t\t; or on the ctrl bit in flags\n??ctrloff:\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],50h\t; is either alt key down?\n\tje \tshort ??altoff\n\tor\tah,04h\t\t\t; or on the alt bit in flags\n??altoff:\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],10h\t; is the left shift down?\n\tjne \tshort ??shifton\t\t; if so the sift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],02h\t; is the right shift down?\n\tje \tshort ??shiftoff\t\t; if not then neither shift is down\n??shifton:\n\tor\tah,01h\t\t\t; or on the shift bit in flags\n??shiftoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje \tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje \tshort ??capsoff\t\t; its not effected\n\txor\tah,1h\t\t\t; toggle the shift flag\n??capsoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t\t; is the num lock key on?\n\tje \tshort ??numlockoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje \tshort ??numlockoff\t\t; if not effected skip toggle\n\txor\tah,1h\t\t\t; toggle the shift flag if effected\n\n??numlockoff:\n\tmov\tal,0ffh\t\t\t; set to match by default\n\tcmp\tah,bh\t\t\t; if flags match return !0\n\tje \tshort ??out\t\t\t; just exit\n\txor\teax,eax\t\t\t; otherwise, clear all bits FALSE\n\n??out:\n\tor\teax,eax\n\tret\n\n\tENDP\tKey_Satisfied\n\n\n;***************************************************************************\n;* Interrupt routines start here - Interrupts must be within the Locked \n;*   code area for DPMI compatability.\n;***************************************************************************\n\n\n\n\nLABEL \tLockedCodeStart\tBYTE\n\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Performs a lowlevel xlate to a keycode              *\n;*                                                                         *\n;* INPUT:\tWORD the code that needs to be translated                  *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated code                                   *\n;*                                                                         *\n;* PROTO:\tINT KeyNum_Translate(INT keynum);                          *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyNum_Translate C NEAR \n\tUSES \tebx,ecx,esi,edi\n\tARG\tkeycode:DWORD\n\n;*===================================================================\n;* ES points to the DOSMEM selector, esi is the offset of the \n;*   protected mode structure.\n;*===================================================================\n\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\tmov\teax,[keycode]\n\ttest\t[(KeyboardType PTR esi).KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\n\tmov\tecx,OFFSET ((KeyboardType PTR 0).ExtRemap)- OFFSET((KeyboardType PTR 0).ExtNums)\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtNums\n\tadd\tedi,esi\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).ExtRemapEnd\n\tdec\tedi\n\tsub\tedi,ecx\n\tmov\tal,[edi]\n??fini:\n\tret\n\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(INT code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_WORD C NEAR\n\tUSES\tebx,esi,edi\n\tARG\tcode:WORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\tedi,eax\n\tadd\teax,2\n\tand\teax,0FFh\t\t\t; New KeyBufferTail value.\n\tcmp\t[(KeyboardType PTR esi).KeyBufferHead],eax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[(KeyboardType PTR esi+edi).KeyBuffer],bx\t\t; Record the keystroke.\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\n\tret\n\n??noroom:\n\tmov\teax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_Num C NEAR\n\tUSES\tebx,ecx,edx,edi,esi\n\tARG\tkeycode:DWORD\n\tLOCAL\ttail:DWORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n; for the moment we do not check for the interrupt flag\n;\tmov\teax,2534h \t\t; function to get the interrupt status\n;\tint\t21\t\t\t; eax = interrupt status\n;\tpush\teax\t\t\t; save the result on the stack\n\n\tpushf\t\t\t\t; store off the flags\n\tcli\t\t\t\t; disable interrupts\n\n; We need to set the data segment because we might be being called\n; from within an interrupt\n; Soo, if that is the case then DS & ES point to DGROUP _DATA \n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\teax,[(KeyboardType PTR esi).MouseX]\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\teax,[(KeyboardType PTR esi).MouseY]\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],ax\n\n??cando:\n\tmov\teax,[keycode]\t\t; get the code\n\tor\teax,eax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[(KeyboardType PTR esi).Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[(KeyboardType PTR esi).Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\txor\tebx,ebx\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tebx,1\t\t\t; double for WORD index\n\tmov\tax,[WORD PTR ((KeyboardType PTR esi+ebx).XYAdjust)]\n\n\tmovsx\tebx,ah\n\tmovsx\teax,al\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tedx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tedx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tebx,edx\t\t\t; add speed for y index\n\tmov\tbl,[(KeyboardType PTR esi+ebx).KeyMouseMove] \t; get speed for y delta\n\tmovsx\tebx,bl\n\txchg\tebx,edx\t\t\t; save mouse y delta\n\tadd\tebx,eax\t\t\t; add speed for x index\n\tmov\tal,[(KeyboardType PTR esi+ebx).KeyMouseMove]\t; get speed for x delta\n\tmovsx\teax,al\n\txchg\tebx,edx\t\t\t; restore mouse y delta\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tebx,011b\t\t\t; Y = 1, 0, 3\n\tand\teax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tebx,011b\t\t\t; Y = 3, 0, 1\n\tand\teax,011b\t\t\t; X = 3, 0, 1\n\tshl\tebx,2\n\tor\tebx,eax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tebx,1\n\tmovzx\tebx,[(KeyboardType PTR esi+ebx).EdgeConv]\n\tshl\tebx,2\n\tmov\tax,[(KeyboardType PTR esi+ebx).ScreenEdge]\t; New absolute X\n\tmov\tbx,[(KeyboardType PTR esi+ebx+2).ScreenEdge] ; New absolute Y\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\teax,eax\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tebx,ebx\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseX],ax\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseY],bx\n\tcmp\t[(KeyboardType PTR esi).MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n; PWG: ARRGGGHHHH!\n;\tcall\tLow_Hide_Mouse\n;\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\teax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],eax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tedi,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\t[tail],edi\t\t; Safety record.\n\n\t; Record the base keycode (if there is room).\n\tcwde\t\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\teax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tmovzx\teax,[(KeyboardType esi).LocalMouseX]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tmovzx\teax,[(KeyboardType esi).LocalMouseY]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tebx,0101h\t\t; Bit control tools.\n\tmov\teax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[(KeyboardType PTR esi).KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[(KeyboardType esi).KeyBufferTail],edi\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tmov\tcl,3\n\tshr\tedi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[(KeyboardType esi+edi).KeysUpDown]\n\tje\tshort ??notalready\n\ttest\t[(KeyboardType PTR esi).KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\tedx,[tail]\n\tmov\t[(KeyboardType esi).KeyBufferTail],edx\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[(KeyboardType esi+edi).KeysUpDown],bh\t; Force key bit to zero.\n\tor\t[(KeyboardType esi+edi).KeysUpDown],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\teax,1\n\tjmp\tshort ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\teax,[tail]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\t\t\t; Signal an error.\n\n??exit:\n\tsti\n\tpopf\n\n;\tpopf\n;\tpop\tebx\n;\tor\tebx,ebx\n;\tjz\t??final_exit\n;\tsti\n\n??final_exit:\n\tret\n\n\tENDP\tStuff_Key_Num\n\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles break interrupt for protected mode           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBreak_Interrupt C NEAR\n\n\tiret\n\tENDP\tBreak_Interrupt\n\nIF DEBUG\n;***************************************************************************\n;* DEBUG_INTERRUPT -- Handles debug (INT 3) interrupt for protected mode   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tDebug_Interrupt C NEAR\n\n\t;*==================================================================\n\t;* Setup fake Interrupt entry sequence so that we can execute our\n\t;*   code and then IRET painlessly into the debuggers interrupt\n\t;*   handler.\n\t;*==================================================================\n\tpushfd\t\t\t; Step 1\n\tsub\tesp,8\t\t; Step 2\n\tpush\tebp\t\t; Step 3\n\tmov\tebp,esp\t\t; Set up a stack frame to know where to poke address.\n\n\t;*==================================================================\n\t;* Preserve all of the registers that we intend to use.\n\t;*=======================================Dbg========================\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n\tmov\tax , _DATA\n\tmov\tds , ax\n\tmov\tes , ax\n\tinc\t[BYTE PTR 0B0000h]\n\n\t;*==================================================================\n\t;* Setup the pointers to the real mode data and the protected mode\n\t;*   data and selectors.\n\t;*==================================================================\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t;*==================================================================\n\t;* Do the deed.\n\t;*==================================================================\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\n\t;*==================================================================\n\t;* Now get the address of the real debug handler and poke it into\n\t;*   the stack so we can IRET to it.\n\t;*==================================================================\n\tmov\teax,[(KeyboardType PTR esi).DbgOldPMIOffset]\t; Get orig offset.\n\tmov\tebx,[(KeyboardType PTR esi).DbgOldPMISelector]\t; Get orig selector.\n\tmov\t[ss:ebp+4],eax\t\t\t\t\t; Poke offset.\n\tmov\t[ss:ebp+8],ebx\t\t\t\t\t; Poke selector.\n\n\t;*==================================================================\n\t;* Restore the stack so it looks like we just did an IRET entry\n\t;*==================================================================\n\tpop\tfs gs es ds\n\tpopad\n\tpop\tebp\n\n\t;*==================================================================\n\t;* This iret should go directly to the real debugger handler\n\t;*\tpainlessly and effectively.\n\t;*==================================================================\n\tiretd\n\n\tENDP\tDebug_Interrupt\nENDIF\n\n\n\nIF PROT_INT_ENABLE\n\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Handles input that comes from the keyboard        *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Interrupt C NEAR\n\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n; this is the part of the interrupt that set the segment registers\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov cx, ss\t\t\t\t; get SS\n\tmov [Keyboard_App_Stack_ESP], esp\t; Protect ESP\n\tmov [Keyboard_App_Stack_SS], ecx\t; Protect SS\n\tlea edx, [Keyboard_StackStart ]\t; Compute Local Stack size\n\tand edx, -4 ;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov esp, edx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\t\n\tmov\tedx,[(KeyboardType PTR esi).KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[(KeyboardType PTR esi).KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\ttest\t[BYTE PTR 417H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR 417H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR 496H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tebx,0101H\t\t; set key to a make by default \n\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\t;\n\t; New CODE to montior key stream\n\t;\n\txor\tebx,ebx\n\tmov\tbx,[(KeyboardType PTR esi).KeyStreamIndex]\n\tmov\t[(KeyboardType PTR esi+ebx).KeyStream],al\n\tinc\tebx\n\tand\tebx,15\n\tmov\t[(KeyboardType PTR esi).KeyStreamIndex],bx\n\tmov\tebx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[(KeyboardType PTR esi).LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[(KeyboardType PTR esi).LastKeyE1]\t\t; yes, dec the count\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[(KeyboardType PTR esi).IsExtKey],TRUE\t; it is an extended key\n\n\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtCodes\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).ExtNums-OFFSET (KeyboardType PTR 0).ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\n\tmov\tal,[(OFFSET (KeyboardType PTR 0).ExtNums - OFFSET (KeyboardType PTR 0).ExtCodes) - 1 + edi] ; get the match\n\tmov\t[(KeyboardType PTR esi).IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tedi,eax\t\t\t; use code as an index\n\tand\tedi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[(KeyboardType PTR esi+edi).KeyNums]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[(KeyboardType PTR esi).ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\teax\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\n;------\tSet the shift bit if necessary.\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tshr\tedi,3\n\tmov\tebx,eax\n\tand\tebx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[(KeyboardType PTR esi+ebx).Bits]\t\t; get the bit to test\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[(KeyboardType PTR esi).CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\n\t\t\t\t\t; keyboard buffer.\n\n\tmov\tecx,eax\n\txor\teax,eax\n\tmov\tax,cx\n\n\ttest\tedx,DEBUGINT\n\tjz\t??not_toggle\n\n\tcmp\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\n\tinc\t[BYTE PTR 0B0002h]\n\n\tcmp\teax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\teax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\teax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\t\n\tcmp\teax,125\n\tjne\t??not_toggle\n\n\tinc\t[BYTE PTR 0B0000h]\n\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjmp\t??absorbcode\n\n??not_toggle:\n\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\teax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\teax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\teax,0230h\n\tje\tshort ??breaker\n\tcmp\teax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[(KeyboardType PTR esi).Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n;\tcmp\tax,0420H\t\t; is this an alt s\n;\tjne\tshort ??checkmusic\t; toggle the Sound variable\n;\tpush\tax\n;\tmov\tax,[SoundOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??checkmusic:\n;\tcmp\tax,0434H\t\t; is this an alt m\n;\tjne\tshort ??esc\t\t; toggle the Music variable\n;\tpush\tax\n;\tmov\tax,[MusicOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??esc:\n\n\tpush\teax\n\tcall\tStuff_Key_Num\n\tpop\teax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[(KeyboardType PTR esi).EscRoutine],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\teax\n\tcall\t[(KeyboardType PTR esi).EscRoutine]\n\tpop\teax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tedi,OFFSET (KeyboardType PTR 0).PassAlways\t; get offset to table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd - OFFSET (KeyboardType PTR 0).PassAlways) ; get number of pass always CDY JLB MOD 7/11 was \n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tedi,OFFSET (KeyboardType PTR 0).CondPassKey\t; get offset to cond key table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).CondPassCond-OFFSET (KeyboardType PTR 0).CondPassKey) ; get number of entries\n\tshr\tecx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(OFFSET (KeyboardType PTR 0).CondPassCond - OFFSET (KeyboardType PTR 0).CondPassKey) - 2 + edi]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tedx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\tinc\t[(KeyboardType PTR esi).PassCount]\n\tmov\t[(KeyboardType PTR esi).PMIssuedKeyInt],1     ; Make it TRUE\n\n\t; Now it is time to set up for the call to the System Keyboard\n\t; interrupt handler.\n\t; 1 -Restore System Stack Pointer Selector before exit Interrupt\n\t; 2- We Create a Returning Point from Interrupt by Push A\n \t;    Interupt Stack Frame into the Stack Pointer\n\t; 3- We make a Far jump to the interuupt handler\n\n\tcmp  [Keyboard_StackPointer],0DEADDEADh\n\tje   ??pass_stack_good\n\n\tpush ecx\n\tpush edi\n\tpush eax\n\tmov  edi,0A0000h\n\tmov  ecx,64000\n\tmov  eax,1\n\trep  stosb\n\tpop  eax\n\tpop  edi\n\tpop  ecx\n\n??pass_stack_good:\n\tcli\t\t\t\t       ; disable Interrupts\n\tmov edx, [Keyboard_App_Stack_SS]       \n\tmov ss, dx\t\t\t       ; Set System Stack Selector\n\tmov esp, [Keyboard_App_Stack_ESP]      ; Set System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n\tlea\tedx, [??Call_Back_Keyboard]   ; Get Return address offset\n \tpushfd\t\t\t\t      ; push flags\t\n\tpush\tcs\t\t\t      ; push Code Selector\n\tpush\tedx\t\t\t      ; push Offset\n\n\t; Now we need to simulate an interrup call by using ired\n\t; because we still want to come back here from the\n\t; Old Keyboard interrupt handle.\n\tpushfd\n\tpush\t[(KeyboardType PTR esi).KeyOldPMISelector] ; push orig selector.\n\tpush    [(KeyboardType PTR esi).KeyOldPMIOffset]   ; push orig offset.\n\tiretd\n\n??absorbcode:\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tal,[496h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[496h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\n\tcmp  [Keyboard_StackPointer],0DEADDEADh\n\tje   ??call_stack_good\n\tpush ecx\n\tpush edi\n\tpush eax\n\tmov  edi,0A0000h\n\tmov  ecx,64000\n\tmov  eax,1\n\trep  stosb\n\tpop  eax\n\tpop  edi\n\tpop  ecx\n\n??call_stack_good:\n\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov edx, [Keyboard_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, dx\t\t\t       ; Set System Stack Selector\n\tmov esp, [Keyboard_App_Stack_ESP]      ; Set System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n??Call_Back_Keyboard:\n\tpop\tfs gs es ds\n\tpopad\n\tiret\t\n\n\tENDP\tKeyboard_Interrupt\n\nELSE\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Stub for the keyboard interrupt call real mode    *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\n \nDATASEG\nSTRUC\tRealModeCallStruc\n\t_EDI  DD\t0\n\t_ESI  DD\t0\n\t_EBP  DD\t0\n\t      DD        0\n\t_EBX  DD\t0\n\t_EDX  DD\t0\n\t_ECX  DD\t0\n\t_EAX  DD        0\n\tFLAGS DW\t0\n\t_ES   DW\t0\n\t_DS   DW\t0\n\t_FS   DW\t0\n\t_GS   DW\t0\n\t_IP   DW\t0\n\t_CS   DW\t0\n\t_SP   DW\t0\n\t_SS   DW\t0\n\t      dd\t0\n\t      dd\t0\n  nothing     dd\t0\t\nENDS \n\nRMDS RealModeCallStruc  <>\n\nCODESEG\n\nPROC\tKeyboard_Interrupt\tNear\n\n; This option of the keyboard interrupt handle will not be\n; available at this moment because the light version of Rational System DOS\n; Extender do not allow a DPMI real mode call which is\n; DMPI INT 31h funtion 0301h\n\n\tpushad\t\n\tpush\tfs gs es ds\n\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\n\tlea\tedi , [ RMDS ]\n\tlea\tecx , [ RMDS . nothing ]\n\tsub\tecx , edi\n\txor\teax , eax\n\tshr\tecx , 2\n\trep\tstosd\n\t\n\tmov\teax , 0300h\n\tmov\tbl , [ byte ptr RMVector ]\n\txor\tbh , bh\n\txor\tcx , cx\n\tlea\tedi , [RMDS]\n\tint\tDPMI_INTR\n\n; this is here only for testing to make sure\n; that a real mode interrupt is bieng issued. \nmov\tax , _DATA\nmov\tes , ax\nmov\tds , ax\nmov [ byte ptr 0b0000h + 10 * 80 + 40 ] , 040h\njc\t??error\nmov [ byte ptr 0b0000h + 10 * 80 + 42 ] , 041h\n\n??error:\n\tpop\tds es gs fs\n\tpopad\t\n\tiretd\n\tENDP\n\nENDIF\n\nLABEL \tLockedCodeEnd\t\tBYTE\n\n;***************************************************************************\n;* End of File.\t\t\t\t\t\t\t\t   *\n;***************************************************************************\nEND\n\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/X/KEYBOARD.BAK",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : KEYBOARD.ASM                             *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 15, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Get_RM_Timer_Address -- Return address of real mode code for copy.    *\n;*   Get_RM_Keyboard_Size -- return size of real mode timer code.          *\n;*   Check_Key -- checks queue for key (make)                              *\n;*   Check_Key_Num -- Checks if key in queue, return key num               *\n;*   Get_Key_Num -- Returns the next key num in ax                         *\n;*   KN_To_KA -- Translates a key num to an ASCII key                      *\n;*   Low_Get_Key -- low level get key returns key num and bits             *\n;*   Convert_Num_To_ASCII -- Assembly routine converts keynum to ASCII key *\n;*   KeyNum_Translate -- Performs a lowlevel xlate to a keycode            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\n;*\tKeyboard driver -- 80386 Protected Mode Assembly portion\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   \n;***************************************************************************\n;\n; ----------------------------------------------------------------\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\n;WARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Make some general equates for easy compatability\n;---------------------------------------------------------------------------\nPROT_INT_ENABLE\tEQU\t1\t\t; if false protected int just calls real mode int\n\nDPMI_INTR\tEQU\t31h\t\nIRQ1INTNUM\tEQU\t09h\t\t; IRQ1 interrupt vector number.\nBRKINTNUM\tEQU\t23h\t\t; Crtl-C (Break) interrupt vector number\nDBGINTNUM\tEQU\t3h\t\t; Debug interrupt vector number\nDOS_SYS_CALL\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nLOCK_PAGES\tEQU\t5\t\t; Lock pages subfunction using DX_MEM_MGT\nUNLOCK_PAGES\tEQU\t6\t\t; Unlock pages subfunction using DX_MEM_MGT\nCLEARISR\tEQU\t020H\t; value to clear In Service Register\nINTCHIP0\tEQU\t020H\t; 8259 interrupt chip controller 0\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\n\tINCLUDE \"keyboard.inc\"\n\tINCLUDE \"keystruc.inc\"\n\tINCLUDE \"mcgaprim.inc\"\n\n\tGLOBAL\t RealModePtr:DWORD\n\n\tGLOBAL\t Install_Keyboard_Interrupt:NEAR\n\tGLOBAL\t Get_RM_Keyboard_Address:Near\n\tGLOBAL\t Get_RM_Keyboard_Size:Near\n\tGLOBAL\t Remove_Keyboard_Interrupt:NEAR\n\tGLOBAL\t Check_Key_Num:NEAR\n\tGLOBAL\t Get_Key_Num:NEAR\n\tGLOBAL\t KN_To_KA:NEAR\n\tGLOBAL\t KeyNum_Translate:NEAR\n\tGLOBAL\t Check_Key:NEAR\n\tGLOBAL\t Get_Key:NEAR\n\tGLOBAL\t Keyboard_Attributes_On:NEAR\n\tGLOBAL\t Clear_KeyBuffer:NEAR\n\tGLOBAL\t Key_Down:NEAR\n\tGLOBAL\t Keyboard_Attributes_Off:NEAR\n\tGLOBAL\t Check_Key_Bits:NEAR\n\tGLOBAL\t Get_Key_Bits:NEAR\n\tGLOBAL\t Key_Satisfied:NEAR\n\tGLOBAL\t Stuff_Key_WORD:NEAR\n\tGLOBAL\t Stuff_Key_Num:NEAR\n\tGLOBAL\t MouseQX:DWORD\n\tGLOBAL\t MouseQY:DWORD\n;DBG\n\tGLOBAL   Keyboard_Interrupt:NEAR\n\n\n\tDATASEG\n; For the current time we will just include the real mode stuff\n; into the protected mode code and then copy it down.  The C side of\n; this will handle this method or reading it off of disk in the real\n; method.\n\nLABEL \tRealBinStart\tBYTE\ninclude \"keyireal.ibn\"\nLABEL\tRealBinEnd\tBYTE\n\nLABEL\tLockedDataStart\tBYTE\t\nRMVector\tDD\t0\nRealModeSel\tDD\t0\nRealModePtr\tDD\t0\t\t; Pointer to real mode memory.\nRealModeSize\tDD\t0\t\t; Pointer to real mode memory.\n\nKeyboard_App_Stack_ESP\tDD 0\t\t; This the System Stack Offsset\nKeyboard_App_Stack_SS\tDD 0\t\t; This the System Stack Selector\nKeyboard_StackPointer\tDD 0DEADDEADh\t; We Create a Local Application\nKeyboard_Stack          DD 255 dup (0)\nKeyboard_StackStart\tDD 0\n\t\t\t\t\t; StackPointer \t\nLABEL\tLockedDataEnd\tBYTE\n\n\n\nAscii\tDB\t0,\"`1234567890-=\",0,8,9,\"qwertyuiop[]\\\",0,\"asdfghjkl;'\"\n\tDB\t0,13,0,45,\"zxcvbnm,./\",0,0,0,0,0,\" \"\n\nShift\tDB\t0,\"~!@#$%^&*()_+\",0,8,9,\"QWERTYUIOP{}|\",0,\"ASDFGHJKL:\",22H\n\tDB\t0,13,0,45,\"ZXCVBNM<>?\",0,0,0,0,0,\" \"\n\nAlpha_Lower\tDB\t0\n\tDB\t\"~!@#$%^&*()_+\",0,8,9,\"qwertyuiop{}|\",0,\"asdfghjkl:\",22H\n\tDB\t0,13,0,45,\"zxcvbnm<>?\",0,0,0,0,0,\" \"\n\nAlpha_Shift\tDB\t0\n\tDB\t\"`1234567890-=\",0,8,9,\"QWERTYUIOP[]\\\",0,\"ASDFGHJKL;'\"\n\tDB\t0,13,0,45,\"ZXCVBNM,./\",0,0,0,0,0,\" \"\n\nEdit\tDB\t0AEH,0ADH,000H,000H,0B5H,0B9H,0B1H,000H,0B8H,0B0H,0B7H,0AFH\n\tDB\t000H,000H,0B3H,000H,0B9H,0B5H,0B1H,000H, \"/\",0B8H,0B4H,0B0H\n\tDB\t0AEH, \"*\",0B7H,0B3H,0AFH,0ADH, \"-\", \"+\",000H,00DH,000H\n\nNumPad\tDB\t0,\"741\",0,\"/8520*963.-+\",0,13,0\n\n\nGetKeyLock\tDW\t0\t; snap shot of num and caps lock bits\nInitFlags\tDW\t0\nMouseQX\t\tDD\t0\nMouseQY\t\tDD\t0\n\n\tCODESEG\n;***************************************************************************\n;* GET_RM_TIMER_ADDRESS -- Return address of real mode code for copy.      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      VOID * to the address of the real mode timer               *\n;*                                                                         *\n;* PROTO:\tVOID\t*Get_RM_Keyboard_Address(VOID);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Address C Near\n\n\tmov\teax, OFFSET RealBinStart\n\tret\n\n\tENDP\n\n;***************************************************************************\n;* GET_RM_KEYBOARD_SIZE -- return size of real mode timer code.            *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      LONG size of the real mode timer code                      *\n;*                                                                         *\n;* PROTO:\tLONG\tGet_RM_Keyboard_Size(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Size C Near\n\n\tmov\teax, OFFSET RealBinEnd - OFFSET RealBinStart\n\tret\n\n\tENDP\n;***************************************************************************\n;* INSTALL_KEYBOARD_INTERRUPT -- Installs the keyboard interrupt           *\n;*                                                                         *\n;* INPUT:\tint rm_ptr  - ptr to the real mode handler\t\t   *\t   *\n;*\t\tint rm_size - size of the real mode handler\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Install_Keyboard_Interrupt(int rm_ptr, int rm_size);  *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tInstall_Keyboard_Interrupt C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\tARG\trm_ptr:DWORD\n\tARG\trm_size:DWORD\n\n\t; Are they attempting to set timer again?\n\tcmp\t[RealModePtr],0\n\tjnz\t??error\n\n\t; Make sure all flags are cleared.\n\tcmp\t[InitFlags],0\n\tjnz\t??error\n\n\n\t; Before setting the interrupt vectors, the code needs to be locked\n\t; for DPMI compatability.  Any code or data accessed must be lockded\n\t; so that no page faults accure during an interrupt.\n\t; First lock the code, then the data.  The stack will already be locked.\n\t; The real mode code is also already locked be default.\n\t; To lock a page set up registers :\n\t; AX = 0600h\n\t; BX:CX\t= starting linear address of memory block\n\t; SI:DI = size of region\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_CODE\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_DATA\n\n\t; now allocate real mode memory and copy the rm binary down to it.\n\tmov\teax,0100h\t; set function number\n\tmov\tebx,[rm_size]\t\t; get size of RM binary.\n\tmov\t[RealModeSize],ebx\n\tadd\tebx,15\t\t\t; round up \n\tshr\tebx,4\t\t\t; convert to pages.\n\tint\tDPMI_INTR\t \t; do call.\n\tjc\t??error\t\t \t; check for error.\n\tor\t[InitFlags],IF_ALLOC_RM ; set successful\n\tmov\t[RealModeSel],edx\n\tshl\teax,4\t\t\t; convert segment to offset.\n\tmov\t[RealModePtr],eax\t; save offset to global variable.\n\n\t; now lock the real mode memory that we allocated\n\tmov\teax,0600h\t\t; function number.\n\tmov\tecx,[RealModePtr]\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_RM_CODE\n\n\n\n\t; set up source and destination pointers for the copy.\n\tmov\teax,[RealModePtr];\t; set up our dest pointer\n\tmov\tesi,[rm_ptr]\t\t; Set up our source pointer.\n\tmov\tedi,eax\t\t\t; put it into esi for copy.\n\tmov\tecx,[rm_size]\n\trep\tmovsb\t\t\t; write RM bin to RM memory.\n\n\t; restore esi to point to data and initialize some of it.\n\tmov\tesi,[RealModePtr]\n\tmov\teax,esi\n\tshl\teax,12\t\t\t\t\t\t; make seg in high eax.\n\tmov\tax,[(KeyboardType PTR esi).CallKeyRMIntOffset]\t; create RM addr of call chain.\n\tmov\t[(KeyboardType PTR esi).CallKeyRMIntAddr],eax\t; save it for use in PM int.\n\nIF NOT PROT_INT_ENABLE\n       ; Chain the Real Keyboard interrupt to any avilable\n       ; Interrupt vector so We make sure that the Real Mode\n       ; Keyboard Interrupt service get called at debuging time\n       ; of the library.\n\n       mov\tedi , eax\n       mov\tbl , 060h\n       mov\tbh , 6\n       mov\teax , 200h\n ??find:\n       int\tDPMI_INTR\n       jc\t??error\n       or\tcx,dx\n       jz\t??found\n       inc\tbl\n       dec\tbh\n       jnz\t??find\n       jmp\t??error\n ??found:\n       movzx\tebx , bl\n       mov\t[ byte ptr RMVector ] , bl\n       mov\t[ 4 * ebx ] , edi\nENDIF\n\n\n\n\t;-------------------------------------------------------\n\t; Initialize all of the keyboard specific information\n\t;-------------------------------------------------------\n\txor\teax,eax\t\t\t; clear the high bits of eax\n\tmov\tal,[417H]\t\t; get keyboard status flags\n\ttest\teax,040H \t\t; caps lock active?\n\tje \tshort ??nocap\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\n\n??nocap:\n\ttest\teax,020H\t\t\t; num lock active?\n\tje\tshort ??nonumlock\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\n\n??nonumlock:\n\ttest\teax,002H\t\t\t; is left shift key down?\n\tje\tshort ??noleftshift\t\t; try the right\n\tor\t[(KeyboardType PTR esi+5).KeysUpDown],010H\n\n??noleftshift:\n\tand\teax,001H\t\t\t; get right shift bit\n\tshl\teax,9\t\t\t; put it into the proper position (shl al,1 mov ah,al)\n\tmov\tal,[418H]\t\t; get alt and ctrl bits\n\tshl\tal,2\t\t\t; put in proper position\n\tshl\tal,1\n\tand\tal,00CH\t\t\t; only alt and ctrl bits\n\tor\tah,al\t\t\t; put them ah for Keys+7 later\n\tmov\tal,[496H]\t\t; get extended keys\n\ttest\tal,008H\t\t\t; check for right alt key\n\tje\tshort ??noralt\n\tor\tah,040H\n??noralt:\n\tmov\t[(KeyboardType PTR esi+7).KeysUpDown],ah\n\ttest\tal,004H\t\t\t; test for right ctrl\n\tje \tshort ??norctrl\n\tor\t[(KeyboardType PTR esi+8).KeysUpDown],001h\n??norctrl:\n\ttest\tal,002H\t\t\t; last code E0?\n\tje short ??noe0\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],001h\n??noe0:\n\ttest\tal,001H\t\t\t; last code E1?\n\tje short ??noe1\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],002h\n??noe1:\n\t;==========================================================================\n\t; Get the protected mode interrupt vector keyboard.\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).KeyOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).KeyOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 2503, cl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).KeyOldRMI],ecx\n\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt Keyboard\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Keyboard_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt Keyboard\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).KeyCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the break interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\t\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).BrkOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).BrkOldPMISelector],ecx\t; save selector.\n\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector - for the break interrupt\n\t; input ax = 0200, bl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).BrkOldRMI],ecx\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Break_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).BrkCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\nIF DEBUG\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the Debug interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\t\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,DBGINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).DbgOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).DbgOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Debug_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\nENDIF\n\n\t; we have finished with success.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n??exit:\n\tret\n\tENDP\tInstall_Keyboard_Interrupt\n\n;***************************************************************************\n;* REMOVE_INTERRUPT -- Removes keyboard interrupt and restores chain\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Remove_Interrupt(VOID)                                *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tRemove_Keyboard_Interrupt C NEAR \n\tUSES\tebx,ecx,edx\n\n\t; verifie that the keyboard was previosly install\n\t; this is here in case of a page fault crash\n\tmov\tesi,[RealModePtr]\n\ttest    esi,esi\n\tjz      ??error\n\n\ttest\t[InitFlags],IF_SET_VECTORS\n\tjz\t??vectors_not_set\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tedx,[(KeyboardType esi).KeyOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[(KeyboardType esi).KeyOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).KeyOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\n\t; disengage Control Break Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tedx,[(KeyboardType esi).BrkOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[(KeyboardType esi).BrkOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).BrkOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\nIF DEBUG\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tecx,[(KeyboardType esi).DbgOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).DbgOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\nENDIF\n\nIF NOT PROT_INT_ENABLE\n       ; Clean up the Users interrupt table\n        mov\teax , 201h\n       mov\tbl , [ byte ptr RMVector ]\n       xor\tecx , ecx\n       xor\tedx , edx\n       int\tDPMI_INTR\n       jc\t??error\nENDIF\n\n\n??vectors_not_set:\n\t; now free up the real mode memory.\n\ttest\t[InitFlags],IF_LOCKED_RM_CODE\n\tjz\t??rm_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,[RealModePtr]\t\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t\t; edx will have size of region in bytes.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??rm_not_locked:\n\ttest\t[InitFlags],IF_ALLOC_RM\n\tjz\t??mem_not_allocated\n\tmov\teax , 0101h\n\tmov\tedx,[ RealModeSel ] \t\t; get physical address of real mode buffer.\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n??mem_not_allocated:\n\n\t; Now we can unlock all stuff needed for the interrupt.  \n\t; Unlock Code\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??code_not_locked:\n\n\t; Unlock data\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??data_not_locked:\n\n\t; we have finished with success.\n\tmov\t[RealModePtr],0\t\t; To say we can do it again sometime.\n\tmov\t[InitFlags],0\t\t; To say we can do it again sometime.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n\tret\n\tENDP\tRemove_Keyboard_Interrupt\n\n\n;***************************************************************************\n;* CHECK_KEY_NUM -- Checks if key in queue, return key num                 *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      Keynum of the key that was pressed, FALSE otherwise        *\n;*\n;* PROTO:\tINT Check_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Num C NEAR \n\tUSES\tebx,esi\n\tpushf\t\t\t\t\t; save off the flags\n\tcli\t\t\t\t\t; disable interrupts\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t\t\n\txor\teax,[(KeyboardType PTR esi).KeyBufferTail]\t\t\n\tor\teax,eax\t\t\t\t; check to see if head == tail\n\tjz\tshort ??fini\t\t\t; if so we are done\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t; get the head\n\tmov\tax,[(KeyboardType PTR esi+eax).KeyBuffer]\t; get key num\n\n??fini:\n\tsti\n\tpopf\n\tret\n\n\tENDP\tCheck_Key_Num\n\n;***************************************************************************\n;* GET_KEY_NUM -- Returns the next key num in ax                           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      WORD key flags are in the high byte of return word, key    *\n;*\t\t  num is in the low byte.\n;*                                                                         *\n;* PROTO:\tWORD Get_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Num C NEAR\n\tUSES\tesi,edi\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n??wait:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t\t; get the head\n\tcmp\teax,[(KeyboardType PTR esi).KeyBufferTail]\t\t; get the head\n\tjne\tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??wait\n\n??getkey:\n\tcall\tLow_Get_Key\n\tsti\t\t\t\t; enable interrupts\n\tret\n\n\tENDP\tGet_Key_Num\n\n;***************************************************************************\n;* KN_TO_KA -- Translates a key num to an ASCII key                        *\n;*                                                                         *\n;* INPUT:\tWORD the keynum to translate                               *\n;*                                                                         *\n;* OUTPUT:      WORD the ASCII key that is returned                        *\n;*                                                                         *\n;* PROTO:\tINT KN_To_KA(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tKN_To_KA C NEAR\n\tARG\tkeynum:DWORD\n\n\tmov\teax,[keynum]\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\tret\n\n\tENDP\tKN_To_KA\n\n\n;***************************************************************************\n;* LOW_GET_KEY -- low level get key returns key num and bits               *\n;*                                                                         *\n;* INPUT:\tAX - index into the buffer                                 *\n;*                                                                         *\n;* OUTPUT:      AX - key num with bits                                     *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tLow_Get_Key C NEAR \n\tUSES\tebx,esi,edi\n\n\tmov\tedi,eax\t\t\t\t; save off value in ax\n\n; We should set up both DS & ES because we are a low level function\n; and don't know who might have called us or what the registers\n; currently are.\n\n; No reason to set DS & ES.\n; This is not a hardware interrupt and if the funtion is being called\n; from within a hardware interrupt then DS and ES will be preset to\n; DGROUP _DATA\n\t\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tcmp\tal,KN_LMOUSE\n\tjb \tshort ??cont\n\tcmp\tal,KN_RMOUSE\n\tja \tshort ??chkjoy\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t; 128 word circular buffer\n\n\tmov\t[MouseQX],eax\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\t[MouseQY],eax\n\n\tpop\teax\t\t\t; restore keynum for return\n\n\tjmp\tshort ??cont\n\n??chkjoy:\n\tcmp\tal,KN_JBUTTON2\t\t; mouse button before joystick button\n\tja \tshort ??cont\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tpop\teax\t\t\t; restore keynum for return\n??cont:\n\tmov\t[(KeyboardType PTR esi).KeyBufferHead],edi\t; set the head\n\n??out:\n\tret\n\n\tENDP\tLow_Get_Key\n\n;***************************************************************************\n;* CONVERT_NUM_TO_ASCII -- Assembly routine converts keynum to ASCII key   *\n;*                                                                         *\n;* INPUT:\tEAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - holds the key num bits                        *\n;*\t\t\tAL - holds the key num value\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      EAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - hold the key bits                             *\n;*\t\t\tAL - holds the ASCII key value\t\t\t   *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* WARNINGS:    GetKeyLock must be set prior to calling this function\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tConvert_Num_To_ASCII C NEAR \n\tUSES\tebx,ecx,esi,edi\n\n\t;*===================================================================\n\t;* Force all breaks to be thrown out.\n\t;*===================================================================\n\ttest\teax,08000h\t\t; If it is a button number\n\tjne\tshort ??button\t\t;  don't process it\n\n\ttest\tah,KEYRELEASE\t\t; If it is not key release\n\tje\tshort ??ok\t\t;  then go process it\n\n??button:\n\txor\teax,eax\t\t\t; no ascii value for a button\n\tret\n\n??ok:\n\t;*===================================================================\n\t;* ES points to the DOSMEM selector, esi is the offset of the \n\t;*   protected mode structure.\n\t;*===================================================================\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\n\t;*===================================================================\n\t;* Start dealing with the keys.\t\t\t\t\t  \n\t;*===================================================================\n\tcmp\tal,110\t\t\t; is it esc\n\tje\t??esc\t\t\t; if so then deal with it\n\n;??chkext:\n\tcmp\tal,62\t\t\t; is it extended?\n\tjae\tshort ??extended\t; its extended so return ext code\n\n\tmov\tebx,eax\t\t\t; get an index\n\tand\tebx,03FH\t\t; only 0-63 allowed\n\ttest\tah,1\t\t\t; if not, test for shift\n\tjnz\tshort ??shifted\t\t; if shifted get shift value\n\n\t;*===================================================================\n\t;* Here when we have an unshifted ascii key\n\t;*===================================================================\n\tmov\tal,[Ascii+ebx]\t\t; get the ascii code for this number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_lowered:\n\tmov\tal,[Alpha_Lower+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_shifted:\n\tmov\tal,[Alpha_Shift+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* Shift'ed character\n\t;*===================================================================\n??shifted:\n\tmov\tal,[Shift+ebx] \t\t; get ascii shift code for number\n\n??ctrlkey:\n\ttest\tah,2\t\t\t; is it ctrl?\n\tjz \tshort ??jexit\t\t; izf not skip ctrl check\n\n\tmov\tedi,ebx\t\t\t; get index\n\tand\tedi,7\t\t\t; only bits 0-7\n\n\tmov\tcl,[(KeyboardType PTR esi+edi).Bits]\n\n\tshr\tebx,3\t\t\t; div by 8 for byte offset\n\ttest\t[(KeyboardType PTR esi+ebx).KeysCapsLock],cl\t\n\tje \tshort ??jexit\n\tand\tal,01FH\t\t\t; force to ctrl value\n\n??jexit:\n\tjmp short ??exit\n\n??extended:\n\tcmp\tal,75\t\t\t; if less than insert\n\tjb \tshort ??special\n\tcmp\tal,110\t\t\t; if >= esc\n\tjae \tshort ??funckey\n\n??editkeys:\n\txor\tebx,ebx\n\tmov\tbl,al\n\tsub\tebx,75\t\t\t; get value from 0-34\n\ttest\t[(KeyboardType PTR esi).KeyFlags],NONUMLOCK\n\tjne \tshort ??no_numpad\n\ttest\t[GetKeyLock],NUMLOCK\t; look at the snap shot of bits\n\tjne \tshort ??numpad\n\n??no_numpad:\n\tmov\tal,[Edit+ebx] \t\t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??numpad:\n\tsub\tebx,15\t\t\t; adjust to numpad entries\n\tmov\tal,[NumPad+ebx] \t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??funckey:\n\tcmp\tal,112\t\t\t; if less than function keys\n\tjb \tshort ??extout\n\tcmp\tal,121\t\t\t; if greater than function keys 1-10\n\tja \tshort ??extout\n\tmov\tbl,al\n\tsub\tbl,112\t\t\t; get value 0-9\n\tmov\tbh,0C5H\t\t\t; function key 1 no shift-ctrl-alt\n\ttest\tah,7\t\t\t; any shift-ctrl-alt\n\tje\tshort ??funcadj\n\tmov\tbh,098H\t\t\t; function key 1 alt\n\ttest\tah,ALTPRESS\t\t; (highest prescendence)\n\tjne \tshort ??funcadj\n\tmov\tbh,0A2H\t\t\t; function key 1 ctrl (next highest)\n\ttest\tah,CTRLPRESS\n\tjne\tshort ??funcadj\n\tmov\tbh,0ACH\t\t\t; function key 1 shift (lowest)\n\n??funcadj:\n\tsub\tbh,bl\t\t\t; adjust function key to a\n\tmov\tal,bh\t\t\t; shift/no shift etc\n\tjmp\tshort ??exit\n\n??special:\n\tcmp\tal,65\t\t\t; if less than specials\n\tjb\tshort ??extout\n\n\tadd\tal,133\t\t\t; make value between 198-207 or\n\tjmp\tshort ??exit\t\t; 0C6H-0CFH\n\t\n??extout:\n\tor\tal,080H\n\tjmp\tshort ??exit\n\n??esc:\n\tmov\tal,01BH\n\n??exit:\n\tret\n\tENDP\tConvert_Num_To_ASCII\n\n;***************************************************************************\n;* CHECK_KEY -- checks for ASCII keys sitting in the keybuffer             *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      INT the ASCII sequence for the key that was pressed        *\n;*                                                                         *\n;* PROTO:\tINT Check_Key(VOID);                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key C NEAR\n\tUSES\tebx,edi,esi\n\n\tpushf\n\tcld\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tcmp\tal,KN_LMOUSE\t\t; check if it is a mouse or joystick\n\tjb\tshort ??contget\n\tcmp\tal,KN_JBUTTON2\n\tja\tshort ??contget\n\tadd\tsi,4\t\t\t; get rid of the x and y values\n\n??contget:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\teax,eax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\tsti\t\t\t\t; enable interrupts\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tcall\tnear ptr Convert_Num_To_ASCII\n\t\t\t\t\t; AX has ASCII code with bits\n\n\txor\tah,ah\t\t\t; clear key bits\n??exit:\n\tpopf\n\tret\n\tENDP\tCheck_Key\n\n\n;***************************************************************************\n;* GET_KEY -- Gets the next available ASCII keystroke.\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      AH - hold the key bits                                     *\n;*\t\tAL - holds the ASCII key value\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tINT Get_Key(VOID);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key C NEAR \n\tUSES \tebx,ecx,edi\n\n\tcld\t\t\t\t; clear the direction flag for speed\n\n\t; Check_Key had to be copied because of enable and disable of ints\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\t\t\t\t\t; AX has key num code with bits\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\txor\tah,ah\n\tret\n\n\tENDP\tGet_Key\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_ON -- Sets the specified keyflags on                *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned on                 *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are on                       *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_On(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_On C NEAR\n\tUSES\tesi,edi\n\tARG\tbits:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tor\t[(KeyboardType PTR esi).KeyFlags],eax\n\n\t; Only do this if in playback or record mode.\n\ttest\teax,PASSBREAKS\n\tje\tshort ??fini\n\n\txor\teax,eax\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).KeysUpDown\n\tmov\t[edi],eax\n\tmov\t[edi+4],eax\n\tmov\t[edi+8],eax\n\tmov\t[edi+12],eax\n??fini:\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\n\tret\n\tENDP\tKeyboard_Attributes_On\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_OFF -- Sets the specified keyflags off              *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned off                *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are off                      *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_Off(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_Off C NEAR\n\tUSES\tesi\n\tARG\tbits:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tnot\teax\n\tand\t[(KeyboardType PTR esi).KeyFlags],eax\n\txor\teax,eax\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\n\tret \n\n\tENDP\tKeyboard_Attributes_Off\n;***************************************************************************\n;* CLEAR_KEYBUFFER -- Clears keystrokes out of the key buffer              *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Clear_KeyBuffer(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tClear_KeyBuffer C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tcli\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\tsti\n\n\tret\n\n\tENDP\tClear_KeyBuffer\n\n;***************************************************************************\n;* KEY_DOWN -- tests the status of a keyboard key                          *\n;*                                                                         *\n;* INPUT:\tINT the key num to check                                   *\n;*                                                                         *\n;* OUTPUT:      INT zero if the key is up, none zero if the key is down    *\n;*                                                                         *\n;* PROTO:\tINT Key_Down(INT key);\t\t\t\t   \t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Down C NEAR\n\tUSES\tebx,ecx,edi,esi\n\tARG\tkey:DWORD\n\n\tpush\t[key]\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\txor\tah,ah\t\t\t\t; Always ignore the control bits.\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tedi,eax\n\tshr\tedi,3\n\tmov\tcl,al\n\tand\tcl,0111b\n\tmov\tal,01b\n\tshl\tal,cl\n\tand\tal,[(KeyboardType PTR esi+edi).KeysUpDown]\n\tret\n\n\tENDP\tKey_Down\n\n;***************************************************************************\n;* CHECK_KEY_BITS -- checks ascii key in key buff with shift,ctrl,alt bits *\n;*                                                                         *\n;* INPUT:\tnone \t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set     *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Bits C NEAR\n\tUSES\tebx,ecx,edi,esi\n\n\tpushf\t\t\t\t\t; save off the direction flag\n\tcld\t\t\t\t\t; we will go forward\n\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n??playback:\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\t;------ If there is a NULL in the keyboard buffer, we must NOT treat it\n\t;\tas a valid ASCII value because the calling code will falsely\n\t;\tassume that the NULL return value indicates an empty buffer.\n\tor\tal,al\n\tje\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\tax,ax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tCheck_Key_Bits\n;***************************************************************************\n;* GET_KEY_BITS -- Gets ascii key in key buff with shift,ctrl,alt bits     *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set\t   *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Bits C NEAR \n\tUSES\tebx,ecx,edi\n\n\tcld\n\n\t; Check_Key_Bits was copied because of enable and disable of interrupts\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\tret\n\n\tENDP\tGet_Key_Bits\n\n;***************************************************************************\n;* KEY_SATISFIED -- checks to see if the given key is satisfied            *\n;*                                                                         *\n;* INPUT:   INT the key flags/number to check                          \t   *\n;*                                                                         *\n;* OUTPUT:  INT 0 if the key is not satisfied, !0 if the key is satisfied  *\n;*                                                                         *\n;* PROTO:   VOID Key_Satisfied(INT key);                                    *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Satisfied C NEAR\n\tUSES\tebx,ecx,esi,edi\n\tARG\tkey:DWORD\n\n\tmov\teax,[key]\n\tmov\tebx,eax\t\t\t; save key code\n\tpush\teax\n\tcall\tKey_Down\t\t; see it its even down\n\tadd\tesp,4\n\tcmp\teax,0\n\tje\t??out\t\t\t; if not it can't be satisfied\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,ebx\t\t\t; if so, restore code\n\txor\tah,ah\t\t\t; clear out flags area\n\tmov\tedi,eax\t\t\t; set as an index\n\tshr\tedi,3\t\t\t; div by 8 for bytes\n\tmov\tch,1h\t\t\t; set a bit for mask\n\tmov\tcl,al\t\t\t; get the code number\n\tand\tcl,7\t\t\t; get the actual bit this code is\n\tshl\tch,cl\t\t\t; move bit into mask position\n\n; now test the ctrl,alt and shift bits\n\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],04h\t; is the left ctrl down?\n\tjne \tshort ??ctrlon\t\t; if so, ctrl is on\n\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],01h\t; is the right ctrl down?\n\tje \tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n??ctrlon:\n\tor\tah,02h\t\t\t; or on the ctrl bit in flags\n??ctrloff:\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],50h\t; is either alt key down?\n\tje \tshort ??altoff\n\tor\tah,04h\t\t\t; or on the alt bit in flags\n??altoff:\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],10h\t; is the left shift down?\n\tjne \tshort ??shifton\t\t; if so the sift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],02h\t; is the right shift down?\n\tje \tshort ??shiftoff\t\t; if not then neither shift is down\n??shifton:\n\tor\tah,01h\t\t\t; or on the shift bit in flags\n??shiftoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje \tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje \tshort ??capsoff\t\t; its not effected\n\txor\tah,1h\t\t\t; toggle the shift flag\n??capsoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t\t; is the num lock key on?\n\tje \tshort ??numlockoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje \tshort ??numlockoff\t\t; if not effected skip toggle\n\txor\tah,1h\t\t\t; toggle the shift flag if effected\n\n??numlockoff:\n\tmov\tal,0ffh\t\t\t; set to match by default\n\tcmp\tah,bh\t\t\t; if flags match return !0\n\tje \tshort ??out\t\t\t; just exit\n\txor\teax,eax\t\t\t; otherwise, clear all bits FALSE\n\n??out:\n\tor\teax,eax\n\tret\n\n\tENDP\tKey_Satisfied\n\n\n;***************************************************************************\n;* Interrupt routines start here - Interrupts must be within the Locked \n;*   code area for DPMI compatability.\n;***************************************************************************\n\n\n\n\nLABEL \tLockedCodeStart\tBYTE\n\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Performs a lowlevel xlate to a keycode              *\n;*                                                                         *\n;* INPUT:\tWORD the code that needs to be translated                  *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated code                                   *\n;*                                                                         *\n;* PROTO:\tINT KeyNum_Translate(INT keynum);                          *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyNum_Translate C NEAR \n\tUSES \tebx,ecx,esi,edi\n\tARG\tkeycode:DWORD\n\n;*===================================================================\n;* ES points to the DOSMEM selector, esi is the offset of the \n;*   protected mode structure.\n;*===================================================================\n\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\tmov\teax,[keycode]\n\ttest\t[(KeyboardType PTR esi).KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\n\tmov\tecx,OFFSET ((KeyboardType PTR 0).ExtRemap)- OFFSET((KeyboardType PTR 0).ExtNums)\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtNums\n\tadd\tedi,esi\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).ExtRemapEnd\n\tdec\tedi\n\tsub\tedi,ecx\n\tmov\tal,[edi]\n??fini:\n\tret\n\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(INT code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_WORD C NEAR\n\tUSES\tebx,esi,edi\n\tARG\tcode:WORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\tedi,eax\n\tadd\teax,2\n\tand\teax,0FFh\t\t\t; New KeyBufferTail value.\n\tcmp\t[(KeyboardType PTR esi).KeyBufferHead],eax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[(KeyboardType PTR esi+edi).KeyBuffer],bx\t\t; Record the keystroke.\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\n\tret\n\n??noroom:\n\tmov\teax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_Num C NEAR\n\tUSES\tebx,ecx,edx,edi,esi\n\tARG\tkeycode:DWORD\n\tLOCAL\ttail:DWORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n; for the moment we do not check for the interrupt flag\n;\tmov\teax,2534h \t\t; function to get the interrupt status\n;\tint\t21\t\t\t; eax = interrupt status\n;\tpush\teax\t\t\t; save the result on the stack\n\n\tpushf\t\t\t\t; store off the flags\n\tcli\t\t\t\t; disable interrupts\n\n; We need to set the data segment because we might be being called\n; from within an interrupt\n; Soo, if that is the case then DS & ES point to DGROUP _DATA \n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\teax,[(KeyboardType PTR esi).MouseX]\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\teax,[(KeyboardType PTR esi).MouseY]\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],ax\n\n??cando:\n\tmov\teax,[keycode]\t\t; get the code\n\tor\teax,eax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[(KeyboardType PTR esi).Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[(KeyboardType PTR esi).Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\txor\tebx,ebx\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tebx,1\t\t\t; double for WORD index\n\tmov\tax,[WORD PTR ((KeyboardType PTR esi+ebx).XYAdjust)]\n\n\tmovsx\tebx,ah\n\tmovsx\teax,al\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tedx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tedx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tebx,edx\t\t\t; add speed for y index\n\tmov\tbl,[(KeyboardType PTR esi+ebx).KeyMouseMove] \t; get speed for y delta\n\tmovsx\tebx,bl\n\txchg\tebx,edx\t\t\t; save mouse y delta\n\tadd\tebx,eax\t\t\t; add speed for x index\n\tmov\tal,[(KeyboardType PTR esi+ebx).KeyMouseMove]\t; get speed for x delta\n\tmovsx\teax,al\n\txchg\tebx,edx\t\t\t; restore mouse y delta\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tebx,011b\t\t\t; Y = 1, 0, 3\n\tand\teax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tebx,011b\t\t\t; Y = 3, 0, 1\n\tand\teax,011b\t\t\t; X = 3, 0, 1\n\tshl\tebx,2\n\tor\tebx,eax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tebx,1\n\tmovzx\tebx,[(KeyboardType PTR esi+ebx).EdgeConv]\n\tshl\tebx,2\n\tmov\tax,[(KeyboardType PTR esi+ebx).ScreenEdge]\t; New absolute X\n\tmov\tbx,[(KeyboardType PTR esi+ebx+2).ScreenEdge] ; New absolute Y\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\teax,eax\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tebx,ebx\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseX],ax\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseY],bx\n\tcmp\t[(KeyboardType PTR esi).MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n; PWG: ARRGGGHHHH!\n;\tcall\tLow_Hide_Mouse\n;\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\teax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],eax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tedi,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\t[tail],edi\t\t; Safety record.\n\n\t; Record the base keycode (if there is room).\n\tcwde\t\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\teax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tmovzx\teax,[(KeyboardType esi).LocalMouseX]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tmovzx\teax,[(KeyboardType esi).LocalMouseY]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tebx,0101h\t\t; Bit control tools.\n\tmov\teax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[(KeyboardType PTR esi).KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[(KeyboardType esi).KeyBufferTail],edi\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tmov\tcl,3\n\tshr\tedi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[(KeyboardType esi+edi).KeysUpDown]\n\tje\tshort ??notalready\n\ttest\t[(KeyboardType PTR esi).KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\tedx,[tail]\n\tmov\t[(KeyboardType esi).KeyBufferTail],edx\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[(KeyboardType esi+edi).KeysUpDown],bh\t; Force key bit to zero.\n\tor\t[(KeyboardType esi+edi).KeysUpDown],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\teax,1\n\tjmp\tshort ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\teax,[tail]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\t\t\t; Signal an error.\n\n??exit:\n\tsti\n\tpopf\n\n;\tpopf\n;\tpop\tebx\n;\tor\tebx,ebx\n;\tjz\t??final_exit\n;\tsti\n\n??final_exit:\n\tret\n\n\tENDP\tStuff_Key_Num\n\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles break interrupt for protected mode           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBreak_Interrupt C NEAR\n\n\tiret\n\tENDP\tBreak_Interrupt\n\nIF DEBUG\n;***************************************************************************\n;* DEBUG_INTERRUPT -- Handles debug (INT 3) interrupt for protected mode   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tDebug_Interrupt C NEAR\n\n\t;*==================================================================\n\t;* Setup fake Interrupt entry sequence so that we can execute our\n\t;*   code and then IRET painlessly into the debuggers interrupt\n\t;*   handler.\n\t;*==================================================================\n\tpushfd\t\t\t; Step 1\n\tsub\tesp,8\t\t; Step 2\n\tpush\tebp\t\t; Step 3\n\tmov\tebp,esp\t\t; Set up a stack frame to know where to poke address.\n\n\t;*==================================================================\n\t;* Preserve all of the registers that we intend to use.\n\t;*=======================================Dbg========================\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n\tmov\tax , _DATA\n\tmov\tds , ax\n\tmov\tes , ax\n\tinc\t[BYTE PTR 0B0000h]\n\n\t;*==================================================================\n\t;* Setup the pointers to the real mode data and the protected mode\n\t;*   data and selectors.\n\t;*==================================================================\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t;*==================================================================\n\t;* Do the deed.\n\t;*==================================================================\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\n\t;*==================================================================\n\t;* Now get the address of the real debug handler and poke it into\n\t;*   the stack so we can IRET to it.\n\t;*==================================================================\n\tmov\teax,[(KeyboardType PTR esi).DbgOldPMIOffset]\t; Get orig offset.\n\tmov\tebx,[(KeyboardType PTR esi).DbgOldPMISelector]\t; Get orig selector.\n\tmov\t[ss:ebp+4],eax\t\t\t\t\t; Poke offset.\n\tmov\t[ss:ebp+8],ebx\t\t\t\t\t; Poke selector.\n\n\t;*==================================================================\n\t;* Restore the stack so it looks like we just did an IRET entry\n\t;*==================================================================\n\tpop\tfs gs es ds\n\tpopad\n\tpop\tebp\n\n\t;*==================================================================\n\t;* This iret should go directly to the real debugger handler\n\t;*\tpainlessly and effectively.\n\t;*==================================================================\n\tiretd\n\n\tENDP\tDebug_Interrupt\nENDIF\n\n\n\nIF PROT_INT_ENABLE\n\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Handles input that comes from the keyboard        *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Interrupt C NEAR\n\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n; this is the part of the interrupt that set the segment registers\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov cx, ss\t\t\t\t; get SS\n\tmov [Keyboard_App_Stack_ESP], esp\t; Protect ESP\n\tmov [Keyboard_App_Stack_SS], ecx\t; Protect SS\n\tlea edx, [Keyboard_StackStart ]\t; Compute Local Stack size\n\tand edx, -4 ;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov esp, edx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\t\n\tmov\tedx,[(KeyboardType PTR esi).KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[(KeyboardType PTR esi).KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\ttest\t[BYTE PTR 417H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR 417H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR 496H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tebx,0101H\t\t; set key to a make by default \n\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\t;\n\t; New CODE to montior key stream\n\t;\n\txor\tebx,ebx\n\tmov\tbx,[(KeyboardType PTR esi).KeyStreamIndex]\n\tmov\t[(KeyboardType PTR esi+ebx).KeyStream],al\n\tinc\tebx\n\tand\tebx,15\n\tmov\t[(KeyboardType PTR esi).KeyStreamIndex],bx\n\tmov\tebx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[(KeyboardType PTR esi).LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[(KeyboardType PTR esi).LastKeyE1]\t\t; yes, dec the count\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[(KeyboardType PTR esi).IsExtKey],TRUE\t; it is an extended key\n\n\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtCodes\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).ExtNums-OFFSET (KeyboardType PTR 0).ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\n\tmov\tal,[(OFFSET (KeyboardType PTR 0).ExtNums - OFFSET (KeyboardType PTR 0).ExtCodes) - 1 + edi] ; get the match\n\tmov\t[(KeyboardType PTR esi).IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tedi,eax\t\t\t; use code as an index\n\tand\tedi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[(KeyboardType PTR esi+edi).KeyNums]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[(KeyboardType PTR esi).ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\teax\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\n;------\tSet the shift bit if necessary.\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tshr\tedi,3\n\tmov\tebx,eax\n\tand\tebx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[(KeyboardType PTR esi+ebx).Bits]\t\t; get the bit to test\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[(KeyboardType PTR esi).CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\n\t\t\t\t\t; keyboard buffer.\n\n\tmov\tecx,eax\n\txor\teax,eax\n\tmov\tax,cx\n\n\ttest\tedx,DEBUGINT\n\tjz\t??not_toggle\n\n\tcmp\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\n\tinc\t[BYTE PTR 0B0002h]\n\n\tcmp\teax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\teax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\teax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\t\n\tcmp\teax,125\n\tjne\t??not_toggle\n\n\tinc\t[BYTE PTR 0B0000h]\n\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjmp\t??absorbcode\n\n??not_toggle:\n\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\teax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\teax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\teax,0230h\n\tje\tshort ??breaker\n\tcmp\teax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[(KeyboardType PTR esi).Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n;\tcmp\tax,0420H\t\t; is this an alt s\n;\tjne\tshort ??checkmusic\t; toggle the Sound variable\n;\tpush\tax\n;\tmov\tax,[SoundOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??checkmusic:\n;\tcmp\tax,0434H\t\t; is this an alt m\n;\tjne\tshort ??esc\t\t; toggle the Music variable\n;\tpush\tax\n;\tmov\tax,[MusicOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??esc:\n\n\tpush\teax\n\tcall\tStuff_Key_Num\n\tpop\teax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[(KeyboardType PTR esi).EscRoutine],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\teax\n\tcall\t[(KeyboardType PTR esi).EscRoutine]\n\tpop\teax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tedi,OFFSET (KeyboardType PTR 0).PassAlways\t; get offset to table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd - OFFSET (KeyboardType PTR 0).PassAlways) ; get number of pass always CDY JLB MOD 7/11 was \n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tedi,OFFSET (KeyboardType PTR 0).CondPassKey\t; get offset to cond key table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).CondPassCond-OFFSET (KeyboardType PTR 0).CondPassKey) ; get number of entries\n\tshr\tecx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(OFFSET (KeyboardType PTR 0).CondPassCond - OFFSET (KeyboardType PTR 0).CondPassKey) - 2 + edi]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tedx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\tinc\t[(KeyboardType PTR esi).PassCount]\n\tmov\t[(KeyboardType PTR esi).PMIssuedKeyInt],1     ; Make it TRUE\n\n\t; Now it is time to set up for the call to the System Keyboard\n\t; interrupt handler.\n\t; 1 -Restore System Stack Pointer Selector before exit Interrupt\n\t; 2- We Create a Returning Point from Interrupt by Push A\n \t;    Interupt Stack Frame into the Stack Pointer\n\t; 3- We make a Far jump to the interuupt handler\n\n\tcmp  [Keyboard_StackPointer],0DEADDEADh\n\tje   ??pass_stack_good\n\n\tmov  [BYTE PTR 0B0000h],'*'\n\n??pass_stack_good:\n\tcli\t\t\t\t       ; disable Interrupts\n\tmov edx, [Keyboard_App_Stack_SS]       \n\tmov ss, dx\t\t\t       ; Set System Stack Selector\n\tmov esp, [Keyboard_App_Stack_ESP]      ; Set System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n\tlea\tedx, [??Call_Back_Keyboard]   ; Get Return address offset\n \tpushfd\t\t\t\t      ; push flags\t\n\tpush\tcs\t\t\t      ; push Code Selector\n\tpush\tedx\t\t\t      ; push Offset\n\n\t; Now we need to simulate an interrup call by using ired\n\t; because we still want to come back here from the\n\t; Old Keyboard interrupt handle.\n\tpushfd\n\tpush\t[(KeyboardType PTR esi).KeyOldPMISelector] ; push orig selector.\n\tpush    [(KeyboardType PTR esi).KeyOldPMIOffset]   ; push orig offset.\n\tiretd\n\n??absorbcode:\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tal,[496h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[496h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\n\tcmp  [Keyboard_StackPointer],0DEADDEADh\n\tje   ??call_stack_good\n\tmov  [BYTE PTR 0B0000h],'*'\n\n??call_stack_good:\n\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov edx, [Keyboard_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, dx\t\t\t       ; Set System Stack Selector\n\tmov esp, [Keyboard_App_Stack_ESP]      ; Set System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n??Call_Back_Keyboard:\n\tpop\tfs gs es ds\n\tpopad\n\tiret\t\n\n\tENDP\tKeyboard_Interrupt\n\nELSE\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Stub for the keyboard interrupt call real mode    *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\n \nDATASEG\nSTRUC\tRealModeCallStruc\n\t_EDI  DD\t0\n\t_ESI  DD\t0\n\t_EBP  DD\t0\n\t      DD        0\n\t_EBX  DD\t0\n\t_EDX  DD\t0\n\t_ECX  DD\t0\n\t_EAX  DD        0\n\tFLAGS DW\t0\n\t_ES   DW\t0\n\t_DS   DW\t0\n\t_FS   DW\t0\n\t_GS   DW\t0\n\t_IP   DW\t0\n\t_CS   DW\t0\n\t_SP   DW\t0\n\t_SS   DW\t0\n\t      dd\t0\n\t      dd\t0\n  nothing     dd\t0\t\nENDS \n\nRMDS RealModeCallStruc  <>\n\nCODESEG\n\nPROC\tKeyboard_Interrupt\tNear\n\n; This option of the keyboard interrupt handle will not be\n; available at this moment because the light version of Rational System DOS\n; Extender do not allow a DPMI real mode call which is\n; DMPI INT 31h funtion 0301h\n\n\tpushad\t\n\tpush\tfs gs es ds\n\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\n\tlea\tedi , [ RMDS ]\n\tlea\tecx , [ RMDS . nothing ]\n\tsub\tecx , edi\n\txor\teax , eax\n\tshr\tecx , 2\n\trep\tstosd\n\t\n\tmov\teax , 0300h\n\tmov\tbl , [ byte ptr RMVector ]\n\txor\tbh , bh\n\txor\tcx , cx\n\tlea\tedi , [RMDS]\n\tint\tDPMI_INTR\n\n; this is here only for testing to make sure\n; that a real mode interrupt is bieng issued. \nmov\tax , _DATA\nmov\tes , ax\nmov\tds , ax\nmov [ byte ptr 0b0000h + 10 * 80 + 40 ] , 040h\njc\t??error\nmov [ byte ptr 0b0000h + 10 * 80 + 42 ] , 041h\n\n??error:\n\tpop\tds es gs fs\n\tpopad\t\n\tiretd\n\tENDP\n\nENDIF\n\nLABEL \tLockedCodeEnd\t\tBYTE\n\n;***************************************************************************\n;* End of File.\t\t\t\t\t\t\t\t   *\n;***************************************************************************\nEND\n\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/X/KEYBOARD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : KEYBOARD.H                               *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : July 13, 1994                            *\n *                                                                         *\n *                  Last Update : July 13, 1994   [PWG]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef KEYBOARD_H\n#define KEYBOARD_H\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n\nextern \"C\" {\n\tvoid Install_Keyboard_Interrupt(void *addr, long size);\n\tvoid Install_Page_Fault_Handle(void) ;\n\tvoid\t*Get_RM_Keyboard_Address(void);\n\tlong\tGet_RM_Keyboard_Size(void);\n\tvoid\tRemove_Keyboard_Interrupt(void);\n\tint\tCheck_Key_Num(void);\n\tint\tCheck_Key_Bits(void);\n\tint\tCheck_Key(void);\n\tshort\tGet_Key_Num(void);\n\tshort\tGet_Key_Bits(void);\n\tint\tGet_Key(void);\n\tint\tKN_To_KA(int keynum);\n\tint\tKeyboard_Attributes_On(int key_flags);\n\tint\tKeyboard_Attributes_Off(int key_flags);\n\tvoid\tClear_KeyBuffer(void);\n\tint\tKey_Down(int key);\n\tint\tKey_Satisfied(int key);\n\tvoid\tStuff_Key_WORD(int code);\n\tvoid\tStuff_Key_Num(int key);\n\tint   Install_Mouse(int max_width, int max_height, int scr_width, int scr_height);\n\tvoid\tReset_Mouse (void) ;\n\tvoid\tRemove_Mouse(void);\n\tint\tGet_Mouse_State(void);\n\tint\tGet_Mouse_X(void);\n\tint\tGet_Mouse_Y(void);\n\tint\tGet_Mouse_Disabled(void);\n\tvoid  *Set_Mouse_Cursor(int xhotspot,\tint yhotspot,\tvoid *cursor);\n\tvoid\tHide_Mouse(void);\n\tvoid\tShow_Mouse(void);\n\tvoid\tConditional_Hide_Mouse(int sx_pixel, int sy_pixel, int dx_pixel, int dy_pixel);\n\tvoid\tConditional_Show_Mouse(void);\n\n\n\tvoid  __interrupt far Keyboard_Interrupt(void);\n\textern int MouseQX;\n\textern int MouseQY;\n\n}\n\n\nenum {\n\tREPEATON     = 0x0001,\t/* 1:all makes into buffer, 0:only 1st make */\n\tTRACKEXT     = 0x0002,\t/* 1:Home != keypad Home, 0:Home=keypad Home */\n\tFILTERONLY   = 0x0004,\t/* 1:Normal BIOS operation with filter */\n\tCTRLALTTURBO = 0x0010,\t/* 1:Allow turbo up and down in application */\n\tNONUMLOCK    = 0x0200,\t/* 1:do NOT remap keypad to numbers */\n\tTASKSWITCHABLE = 0x400, /* 1:allows task switching keys thru ALT-TAB, */\n\t\t\t\t\t\t\t\t\t/*   ALT-ESC,CTRL-ESC */\n\tPASSBREAKS\t = 0x0800,\t// Pass all breaks to the keyboard buffer.\n\n\t/* The following flags, if turned on, should only be used for\n\t   debugging purposes (remember to take out the calls when BETA */\n\n\tCTRLSON      = 0x0008,\t/* 1:pass scroll lock sequence into BIOS */\n\tCTRLCON      = 0x0020,\t/* 1:pass stop code to BIOS */\n\tSCROLLLOCKON = 0x0040,\t/* 1:pass scroll lock key into BIOS */\n\tPAUSEON      = 0x0080,\t/* 1:pass the pause key and seq to BIOS */\n\t\t\t\t\t\t\t\t\t/*   make sure FILTERONLY is set */\n\tBREAKON      = 0x0100,\t/* 1:pass the ctrl break seq to BIOS */\n\tKEYMOUSE     = 0x1000,\t/* 1:keypad translates into mouse moves */\n\tSIMLBUTTON   = 0x2000,\t/* 1:have space and enter keys simulate Left */\n\t\t\t\t\t\t\t\t\t/*   mouse button when KEYMOUSE is set */\n\tDEBUGINT\t\t = 0x4000\t/* Use scroll lock to disable keyboard int */\n};\n\n\n/*\n**\tThese are the codes for the various key codes that are returned from the\n**\tkeyboard input routines Get_Key() and Input_ASCII().\n*/\ntypedef enum {\n\tKA_CTRL_AT = 0,\n\tKA_CTRL_A,\n\tKA_MORE = KA_CTRL_A,\n\tKA_CTRL_B,\n\tKA_SETBKGDCOL = KA_CTRL_B,\n\tKA_CTRL_C,\n\tKA_CTRL_D,\n\tKA_CTRL_E,\n\tKA_CTRL_F,\n\tKA_SETFORECOL = KA_CTRL_F,\n\tKA_CTRL_G,\n\tKA_CTRL_H,\n\tKA_BACKSPACE = KA_CTRL_H,\n\tKA_CTRL_I,\n\tKA_TAB = KA_CTRL_I,\n\tKA_CTRL_J,\n\tKA_CTRL_K,\n\tKA_CTRL_L,\n\tKA_FORMFEED = KA_CTRL_L,\n\tKA_CTRL_M,\n\tKA_RETURN = KA_CTRL_M,\n\tKA_CTRL_N,\n\n\tKA_CTRL_O,\n\tKA_CTRL_P,\n\tKA_CTRL_Q,\n\tKA_CTRL_R,\n\tKA_CTRL_S,\n\tKA_SPCTAB = KA_CTRL_S,\n\tKA_CTRL_T,\n\tKA_CTRL_U,\n\tKA_CTRL_V,\n\tKA_CTRL_W,\n\tKA_CTRL_X,\n\tKA_SETX = KA_CTRL_X,\n\tKA_CTRL_Y,\n\tKA_SETY = KA_CTRL_Y,\n\tKA_CTRL_Z,\n\tKA_CTRL_LBRACKET,\n\tKA_ESC = KA_CTRL_LBRACKET,\n\tKA_EXTEND = KA_ESC,\n\tKA_CTRL_BACKSLASH,\n\tKA_CTRL_RBRACKET,\n\tKA_LITERAL = KA_CTRL_RBRACKET,\n\tKA_CTRL_CARROT,\n\tKA_CTRL_UNDERLINE,\n\n\tKA_SPACE,\t\t\t\t\t\t\t\t\t/*   */\n\tKA_EXCLAMATION,\t\t\t\t\t\t\t/* ! */\n\tKA_DQUOTE,\t\t\t\t\t\t\t\t\t/* \" */\n\tKA_POUND,\t\t\t\t\t\t\t\t\t/* # */\n\tKA_DOLLAR,\t\t\t\t\t\t\t\t\t/* $ */\n\tKA_PERCENT,\t\t\t\t\t\t\t\t\t/* % */\n\tKA_AMPER,\t\t\t\t\t\t\t\t\t/* & */\n\tKA_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKA_LPAREN,\t\t\t\t\t\t\t\t\t/* ( */\n\tKA_RPAREN,\t\t\t\t\t\t\t\t\t/* ) */\n\tKA_ASTERISK,\t\t\t\t\t\t\t\t/* * */\n\tKA_PLUS,\t\t\t\t\t\t\t\t\t\t/* + */\n\tKA_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKA_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKA_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKA_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKA_0, KA_1, KA_2, KA_3, KA_4, KA_5, KA_6, KA_7, KA_8, KA_9,\n\tKA_COLON,\t\t\t\t\t\t\t\t\t/* : */\n\tKA_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKA_LESS_THAN,\t\t\t\t\t\t\t\t/* < */\n\tKA_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\tKA_GREATER_THAN,\t\t\t\t\t\t\t/* > */\n\tKA_QUESTION,\t\t\t\t\t\t\t\t/* ? */\n\n\tKA_AT,\t\t\t\t\t\t\t\t\t\t/* @ */\n\tKA_A,\t\t\t\t\t\t\t\t\t\t\t/* A */\n\tKA_B,\t\t\t\t\t\t\t\t\t\t\t/* B */\n\tKA_C,\t\t\t\t\t\t\t\t\t\t\t/* C */\n\tKA_D,\t\t\t\t\t\t\t\t\t\t\t/* D */\n\tKA_E,\t\t\t\t\t\t\t\t\t\t\t/* E */\n\tKA_F,\t\t\t\t\t\t\t\t\t\t\t/* F */\n\tKA_G,\t\t\t\t\t\t\t\t\t\t\t/* G */\n\tKA_H,\t\t\t\t\t\t\t\t\t\t\t/* H */\n\tKA_I,\t\t\t\t\t\t\t\t\t\t\t/* I */\n\tKA_J,\t\t\t\t\t\t\t\t\t\t\t/* J */\n\tKA_K,\t\t\t\t\t\t\t\t\t\t\t/* K */\n\tKA_L,\t\t\t\t\t\t\t\t\t\t\t/* L */\n\tKA_M,\t\t\t\t\t\t\t\t\t\t\t/* M */\n\tKA_N,\t\t\t\t\t\t\t\t\t\t\t/* N */\n\tKA_O,\t\t\t\t\t\t\t\t\t\t\t/* O */\n\n\tKA_P,\t\t\t\t\t\t\t\t\t\t\t/* P */\n\tKA_Q,\t\t\t\t\t\t\t\t\t\t\t/* Q */\n\tKA_R,\t\t\t\t\t\t\t\t\t\t\t/* R */\n\tKA_S,\t\t\t\t\t\t\t\t\t\t\t/* S */\n\tKA_T,\t\t\t\t\t\t\t\t\t\t\t/* T */\n\tKA_U,\t\t\t\t\t\t\t\t\t\t\t/* U */\n\tKA_V,\t\t\t\t\t\t\t\t\t\t\t/* V */\n\tKA_W,\t\t\t\t\t\t\t\t\t\t\t/* W */\n\tKA_X,\t\t\t\t\t\t\t\t\t\t\t/* X */\n\tKA_Y,\t\t\t\t\t\t\t\t\t\t\t/* Y */\n\tKA_Z,\t\t\t\t\t\t\t\t\t\t\t/* Z */\n\tKA_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKA_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\tKA_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKA_CARROT,\t\t\t\t\t\t\t\t\t/* ^ */\n\tKA_UNDERLINE,\t\t\t\t\t\t\t\t/* _ */\n\n\tKA_GRAVE,\t\t\t\t\t\t\t\t\t/* ` */\n\tKA_a,\t\t\t\t\t\t\t\t\t\t\t/* a */\n\tKA_b,\t\t\t\t\t\t\t\t\t\t\t/* b */\n\tKA_c,\t\t\t\t\t\t\t\t\t\t\t/* c */\n\tKA_d,\t\t\t\t\t\t\t\t\t\t\t/* d */\n\tKA_e,\t\t\t\t\t\t\t\t\t\t\t/* e */\n\tKA_f,\t\t\t\t\t\t\t\t\t\t\t/* f */\n\tKA_g,\t\t\t\t\t\t\t\t\t\t\t/* g */\n\tKA_h,\t\t\t\t\t\t\t\t\t\t\t/* h */\n\tKA_i,\t\t\t\t\t\t\t\t\t\t\t/* i */\n\tKA_j,\t\t\t\t\t\t\t\t\t\t\t/* j */\n\tKA_k,\t\t\t\t\t\t\t\t\t\t\t/* k */\n\tKA_l,\t\t\t\t\t\t\t\t\t\t\t/* l */\n\tKA_m,\t\t\t\t\t\t\t\t\t\t\t/* m */\n\tKA_n,\t\t\t\t\t\t\t\t\t\t\t/* n */\n\tKA_o,\t\t\t\t\t\t\t\t\t\t\t/* o */\n\n\tKA_p,\t\t\t\t\t\t\t\t\t\t\t/* p */\n\tKA_q,\t\t\t\t\t\t\t\t\t\t\t/* q */\n\tKA_r,\t\t\t\t\t\t\t\t\t\t\t/* r */\n\tKA_s,\t\t\t\t\t\t\t\t\t\t\t/* s */\n\tKA_t,\t\t\t\t\t\t\t\t\t\t\t/* t */\n\tKA_u,\t\t\t\t\t\t\t\t\t\t\t/* u */\n\tKA_v,\t\t\t\t\t\t\t\t\t\t\t/* v */\n\tKA_w,\t\t\t\t\t\t\t\t\t\t\t/* w */\n\tKA_x,\t\t\t\t\t\t\t\t\t\t\t/* x */\n\tKA_y,\t\t\t\t\t\t\t\t\t\t\t/* y */\n\tKA_z,\t\t\t\t\t\t\t\t\t\t\t/* z */\n\tKA_LBRACE,\t\t\t\t\t\t\t\t\t/* { */\n\tKA_BAR,\t\t\t\t\t\t\t\t\t\t/* | */\n\tKA_RBRACE,\t\t\t\t\t\t\t\t\t/* ] */\n\tKA_TILDA,\t\t\t\t\t\t\t\t\t/* ~ */\n\tKA_DEL,\t\t\t\t\t\t\t\t\t\t/* not used */\n\n\tKA_ALT_F10 = 143,\n\tKA_ALT_F9,    KA_ALT_F8,   KA_ALT_F7,   KA_ALT_F6,   KA_ALT_F5,\n\tKA_ALT_F4,    KA_ALT_F3,   KA_ALT_F2,   KA_ALT_F1,\n\n\tKA_CTRL_F10,  KA_CTRL_F9,  KA_CTRL_F8,  KA_CTRL_F7,  KA_CTRL_F6,\n\tKA_CTRL_F5,   KA_CTRL_F4,  KA_CTRL_F3,  KA_CTRL_F2,  KA_CTRL_F1,\n\n\tKA_SHIFT_F10, KA_SHIFT_F9, KA_SHIFT_F8, KA_SHIFT_F7, KA_SHIFT_F6,\n\tKA_SHIFT_F5,  KA_SHIFT_F4, KA_SHIFT_F3, KA_SHIFT_F2, KA_SHIFT_F1,\n\n\tKA_DELETE,\t\t\t\t\t\t\t\t\t/* <DELETE> */\n\tKA_INSERT,\t\t\t\t\t\t\t\t\t/* <INSERT> */\n\tKA_PGDN,\t\t\t\t\t\t\t\t\t\t/* <PAGE DOWN> */\n\tKA_DOWNRIGHT = KA_PGDN,\n\tKA_DOWN,\t\t\t\t\t\t\t\t\t\t/* <DOWN ARROW> */\n\tKA_END,\t\t\t\t\t\t\t\t\t\t/* <END> */\n\tKA_DOWNLEFT = KA_END,\n\n\tKA_RESERVED1,\n\n\tKA_RIGHT,\t\t\t\t\t\t\t\t\t/* <RIGHT ARROW> */\n\tKA_KEYPAD5,\t\t\t\t\t\t\t\t\t/* NUMERIC KEY PAD <5> */\n\tKA_LEFT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ARROW> */\n\n\tKA_RESERVED2,\n\n\tKA_PGUP,\t\t\t\t\t\t\t\t\t\t/* <PAGE UP> */\n\tKA_UPRIGHT = KA_PGUP,\n\tKA_UP,\t\t\t\t\t\t\t\t\t\t/* <UP ARROW> */\n\tKA_HOME,\t\t\t\t\t\t\t\t\t\t/* <HOME> */\n\tKA_UPLEFT = KA_HOME,\n\t\n\tKA_RESERVED3,\n\tKA_RESERVED4,\n\n\tKA_F10, KA_F9, KA_F8, KA_F7, KA_F6, KA_F5, KA_F4, KA_F3, KA_F2, KA_F1,\n\n\tKA_LMOUSE,\n\tKA_RMOUSE,\n\tKA_JBUTTON1,\n\tKA_JBUTTON2,\n\tKA_J_UP,\n\tKA_J_RIGHT,\n\tKA_J_DOWN,\n\tKA_J_LEFT,\n\n\tKA_SHIFT_BIT = 0x0100,\n\tKA_CTRL_BIT  = 0x0200,\n\tKA_ALT_BIT   = 0x0400,\n\tKA_RLSE_BIT  = 0x0800,\n\tKA_LCOMM_BIT = 0x1000,\t\t\t\t\t/* Amiga Left Comm key\t*/\n\tKA_RCOMM_BIT = 0x2000\t\t\t\t\t/* Amiga Right Comm key\t*/\n} KeyASCIIType;\n\n/*\n**\tThese are the keyboard codes that are returned from the input routines\n**\tGet_Key_Num and Input_Num.\n*/\ntypedef enum {\n\tKN_NONE = 0,\n\tKN_GRAVE = 1,\t\t\t\t\t\t\t\t/* ` */\n\tKN_1, KN_2, KN_3, KN_4, KN_5, KN_6, KN_7, KN_8, KN_9, KN_0,\n\tKN_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKN_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\n\tKN_RESERVED1,\n\n\tKN_BACKSPACE,\t\t\t\t\t\t\t\t/* <BACKSPACE> */\n\n\tKN_TAB,\t\t\t\t\t\t\t\t\t\t/* <TAB> */\n\tKN_Q, KN_W, KN_E, KN_R, KN_T, KN_Y, KN_U, KN_I, KN_O, KN_P,\n\tKN_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKN_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKN_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\n\tKN_CAPSLOCK,\t\t\t\t\t\t\t\t/* <CAPS LOCK> */\n\tKN_A, KN_S, KN_D, KN_F, KN_G, KN_H, KN_J, KN_K, KN_L,\n\tKN_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKN_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKN_BACKSLASH2,\n\tKN_RETURN,\t\t\t\t\t\t\t\t\t/* <RETURN> or <ENTER> */\n\n\tKN_LSHIFT,\t\t\t\t\t\t\t\t\t/* <LEFT SHIFT> */\n\n\tKN_MOUSE_MOVE,\t\t\t\t\t\t\t\t// Indicate a mouse move (for playback of\n\n\tKN_Z, KN_X, KN_C, KN_V, KN_B, KN_N, KN_M,\n\tKN_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKN_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKN_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKN_RESERVED3,\n\n\tKN_RSHIFT,\t\t\t\t\t\t\t\t\t/* <RIGHT SHIFT> */\n\n\tKN_LCTRL,\t\t\t\t\t\t\t\t\t/* <LEFT CTRL> */\n\tKN_LCOMM,\t\t\t\t\t\t\t\t\t/* for AMIGA */\n\tKN_LALT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ALT> */\n\tKN_SPACE,\t\t\t\t\t\t\t\t\t/* <SPACE BAR> */\n\tKN_RALT,\t\t\t\t\t\t\t\t\t\t/* <RIGHT ALT> */\n\tKN_RCOMM,\t\t\t\t\t\t\t\t\t/* for AMIGA */\n\tKN_RCTRL,\t\t\t\t\t\t\t\t\t/* <RIGHT CTRL> */\n\t\t\t\t\t\t\t/* the following are forced into key buffer */\n\tKN_LMOUSE,\n\tKN_RMOUSE,\n\tKN_JBUTTON1,\n\tKN_JBUTTON2,\n\tKN_J_UP,\n\tKN_J_RIGHT,\n\tKN_J_DOWN,\n\tKN_J_LEFT,\n\n\tKN_SPECIAL9,\n\n\tKN_SPECIAL10,\n\n\tKN_E_INSERT,\t\t\t\t\t\t\t\t/* extended <INSERT> */\n\tKN_E_DELETE,\t\t\t\t\t\t\t\t/* extended <DELETE> */\n\n\tKN_RESERVED4,\n\tKN_RESERVED5,\n\n\tKN_E_LEFT,\t\t\t\t\t\t\t\t\t/* extended <LEFT ARROW> */\n\tKN_E_HOME,\t\t\t\t\t\t\t\t\t/* extended <HOME> */\n\tKN_E_END,\t\t\t\t\t\t\t\t\t/* extended <END> */\n\n\tKN_RESERVED6,\n\n\tKN_E_UP,\t\t\t\t\t\t\t\t\t\t/* extended <UP ARROW> */\n\tKN_E_DOWN,\t\t\t\t\t\t\t\t\t/* extended <DOWN ARROW> */\n\tKN_E_PGUP,\t\t\t\t\t\t\t\t\t/* extended <PAGE UP> */\n\tKN_E_PGDN,\t\t\t\t\t\t\t\t\t/* extended <PAGE DOWN> */\n\tKN_K_LPAREN,\t\t\t/* for AMIGA */\n\tKN_K_RPAREN,\t\t\t/* for AMIGA */\n\tKN_E_RIGHT,\t\t\t\t\t\t\t\t\t/* extended <RIGHT ARROW> */\n\n\tKN_NUMLOCK,\t\t\t\t\t\t\t\t\t/* <NUM LOCK> */\n\tKN_HOME,\t\t\t\t\t\t\t\t\t\t/* num key pad 7 */\n\tKN_UPLEFT = KN_HOME,\n\tKN_LEFT,\t\t\t\t\t\t\t\t\t\t/* num key pad 4 */\n\tKN_END,\t\t\t\t\t\t\t\t\t\t/* num key pad 1 */\n\tKN_DOWNLEFT = KN_END,\n\n\tKN_RESERVED7,\n\n\tKN_KEYPAD_SLASH,\t\t\t\t\t\t\t/* num key pad / */\n\tKN_UP,\t\t\t\t\t\t\t\t\t\t/* num key pad 8 */\n\tKN_CENTER,\t\t\t\t\t\t\t\t\t/* num key pad 5 */\n\tKN_DOWN,\t\t\t\t\t\t\t\t\t\t/* num key pad 2 */\n\tKN_INSERT,\t\t\t\t\t\t\t\t\t/* num key pad 0 */\n\tKN_KEYPAD_ASTERISK,\t\t\t\t\t\t/* num key pad * */\n\tKN_PGUP,\t\t\t\t\t\t\t\t\t\t/* num key pad 9 */\n\tKN_UPRIGHT = KN_PGUP,\n\tKN_RIGHT,\t\t\t\t\t\t\t\t\t/* num key pad 6 */\n\tKN_PGDN,\t\t\t\t\t\t\t\t\t\t/* num key pad 3 */\n\tKN_DOWNRIGHT = KN_PGDN,\n\tKN_DELETE,\t\t\t\t\t\t\t\t\t/* num key pad . */\n\tKN_KEYPAD_MINUS,\t\t\t\t\t\t\t/* num key pad - */\n\tKN_KEYPAD_PLUS,\t\t\t\t\t\t\t/* num key pad + */\n\n\tKN_RESERVED8,\n\n\tKN_KEYPAD_RETURN,\t\t\t\t\t\t\t/* num key pad <ENTER> */\n\n\tKN_RESERVED9,\n\n\tKN_ESC,\n\tKN_HELP,\t\t\t\t\t\t\t\t\t\t/* for AMIGA */\n\tKN_F1, KN_F2, KN_F3, KN_F4, KN_F5, KN_F6, KN_F7, KN_F8, KN_F9, KN_F10,\n\tKN_F11,\n\tKN_F12,\n\tKN_PRNTSCRN,\t\t\t\t\t\t\t\t/* <PRINT SCRN> */\n\tKN_SCROLLLOCK,\t\t\t\t\t\t\t\t/* <SCROLL LOCK> */\n\tKN_PAUSE,\t\t\t\t\t\t\t\t\t/* <PAUSE> */\n\n\tKN_SHIFT_BIT = 0x0100,\n\tKN_CTRL_BIT  = 0x0200,\n\tKN_ALT_BIT   = 0x0400,\n\tKN_RLSE_BIT  = 0x0800,\n\tKN_LCOMM_BIT = 0x1000,\t\t\t\t\t/* Amiga Left Comm key\t*/\n\tKN_RCOMM_BIT = 0x2000,\t\t\t\t\t/* Amiga Right Comm key\t*/\n\tKN_BUTTON    = 0x8000\t\t\t\t\t/* Amiga Right Comm key\t*/\n} KeyNumType;\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/X/KEYBOARD.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : KEYBOARD.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 12, 1994                            *\n;*                                                                         *\n;*                  Last Update : July 12, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Contains all the defines used by the keyboard interrupt for assembly    *\n;*   includes.                                                             *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nTRUE\t\tEQU\t1\t\t\t; numerical true\nFALSE\t\tEQU\t0\t\t\t; numerical false\nDEBUG\t\tEQU\t1\n\nMAX_X_PIXEL\t\tEQU\t319\nMAX_Y_PIXEL\t\tEQU\t199\n\n\nKN_RESERVED1\t\tEQU\t14\nKN_RESERVED2\t\tEQU\t45\nKN_RESERVED3\t\tEQU\t56\n\n\n; these two are reserved for AMIGA open and close.\nKN_LCOMM\t\tEQU\t59\nKN_RCOMM\t\tEQU\t63\n\nKN_LMOUSE\t\tEQU\t65\nKN_RMOUSE\t\tEQU\t66\nKN_JBUTTON1\t\tEQU\t67\nKN_JBUTTON2\t\tEQU\t68\nKN_J_UP\t\t\tEQU\t69\nKN_J_RIGHT\t\tEQU\t70\nKN_J_DOWN\t\tEQU\t71\nKN_J_LEFT\t\tEQU\t72\n\nKN_LEFT\t\t\tEQU\t92\nKN_UPLEFT\t\tEQU\t91\nKN_UP\t\t\tEQU\t96\nKN_UPRIGHT\t\tEQU\t101\nKN_RIGHT\t\tEQU\t102\nKN_DOWNRIGHT\t\tEQU\t103\nKN_DOWN\t\t\tEQU\t98\nKN_DOWNLEFT\t\tEQU\t93\nKN_CENTER\t\tEQU\t97\n\nKN_INSERT\t\tEQU\t99\nKN_DELETE\t\tEQU\t104\n\nKN_RETURN\t\tEQU\t43\nKN_SPACE\t\tEQU\t61\nKN_KEYPAD_RETURN\tEQU\t108\n\n\n; these two are reserved for AMIGA K left and right paren\nKN_KLPAREN\t\tEQU\t87\nKN_KRPAREN\t\tEQU\t88\n\n\nKN_NUMLOCK\t\tEQU\t90\n\nKN_SCROLLOCK\t\tEQU\t125\t\t; key ignored by the logging system\n\nKN_MOUSE_MOVE\tEQU\t45\t; Indicate a mouse move (for playback of logged data)\n\n; ----------------------------------------------------------------\n; flags used in Keyflags to customize keystroke interrupt.\n\nREPEATON\tEQU\t0001H\t; 1:all makes into buffer, 0:only 1st make\nTRACKEXT\tEQU\t0002H\t; 1:Home != keypad Home, 0:Home=keypad Home\nFILTERONLY\tEQU\t0004H\t; 1:Normal BIOS operation with filter\nCTRLSON\t\tEQU\t0008H\t; 1:pass scroll lock sequence into BIOS\nCTRLALTTURBO\tEQU\t0010H\t; 1:Allow turbo up and down in application\nCTRLCON\t\tEQU\t0020H\t; 1:pass stop code to BIOS\nSCROLLLOCKON\tEQU\t0040H\t; 1:pass scroll lock key into BIOS\nPAUSEON\t\tEQU\t0080H\t; 1:pass the pause key and seq to BIOS\nBREAKON\t\tEQU\t0100H\t; 1:pass the ctrl break seq to BIOS\nNONUMLOCK\tEQU\t0200H\t; 1:do NOT remap keypad to numbers\nTASKSWITCHABLE\tEQU\t0400H\t; 1:allows task switching keys thru ALT-TAB,\n\t\t\t\t;   ALT-ESC,CTRL-ESC\nPASSBREAKS\tEQU\t0800H\t; 1:Pass all break codes to keyboard buffer.\nKEYMOUSE\tEQU\t1000H\t; 1:Numeric keypad moves mouse\nSIMLBUTTON\tEQU\t2000H\t; 1:have space and enter keys simulate Left\nDEBUGINT\tEQU\t4000H\t;   mouse button when KEYMOUSE is set\n\n\nSHIFTPRESS\tEQU\t001H\t; bit 0 for shift key pressed\nCTRLPRESS\tEQU\t002H\t; bit 1 for ctrl key pressed\nALTPRESS\tEQU\t004H\t; bit 2 for alt key pressed\nKEYRELEASE\tEQU\t008H\t; bit 3 for key released\nNOTKEYRELEASE\tEQU\t0F7H\t; not of key released\n\nCAPSLOCK\tEQU\t00001H\t; bit 0 for caps locked\nNUMLOCK\tEQU\t00002H\t; bit 1 for num locked\n\n\n\nCLEARISR\tEQU\t020H\t; value to clear In Service Register\nDOS\t\tEQU \t021H\nINTCHIP0\tEQU\t020H\t; 8259 interrupt chip controller 0\nKEYCTRL\t\tEQU\t061H\t; control bits for KB sense data\nKEYDATA\t\tEQU\t060H\t; keyboard scan code port\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/X/KEYIPROT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : KEYINTR.ASM                              *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   KeyNum_Translate -- Translates the given keynum to ???                *\n;*   Install_Interrupt -- Installs the keyboard interrupt                  *\n;*   Stuff_Key_Word -- Stuffs a word of data into keyboard buffer          *\n;*   Stuff_Key_Num -- Stuffs a key num code into the circular buffer       *\n;*   Remove_Interrupt -- Removes the keyboard interrupt and restores the chai*\n;*   Keystroke_Interrupt -- Handles input that comes from the keyboard     *\n;*   Break_Interrupt -- Handles the break key interrupt                    *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tKeyboard driver -- 8086 Assembly portion;\t\t\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   *\n;***************************************************************************\n\n;---------------------------------------------------------------------------\n; Set the assembly directives\n;---------------------------------------------------------------------------\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386N\t\t\t\t; use 386 real mode instructions\nMODEL TINY\t\t\t; code must be tiny so it fits\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keyboard.inc\"\n\nCODESEG\n\n\nSoundOn\t\tDW\t1\t; toggled by alt S\nMusicOn\t\tDW\t1\t; toggled by alt M\nKeyFlags\tDW\tREPEATON+CTRLALTTURBO\t; all but repeat for now\n\n\nBreak\t\tDW\t0\n\nKeyMouseMove\tDB\t-1,0,1\n\t\tDB\t-16,0,16\n\nScreenEdge\tDW\t320/2,0\t\t; North\n\t\tDW\t319,0\t\t; North-East\n\t\tDW\t319,138/2\t; East\n\t\tDW\t319,137\t\t; South-East\n\t\tDW\t320/2,137\t; South\n\t\tDW\t0,137\t\t; South-West\n\t\tDW\t0,138/2\t\t; West\n\t\tDW\t0,0\t\t; North-West\n\t\tDW\t320/2,138/2\t; Center\n\n\nBits\t\tDB\t01H,02H,04H,08H,10H,20H,40H,80H\n\nCondPassKey\tDW\t0220H, 0320H, 060CH, 070DH, 066AH\n\t\tDW\t0669H, 0230H, 0330H, 007DH, 017DH\n\t\tDW\t025AH, 035AH, 0200H, 0410H, 046EH\n\t\tDW\t026EH, 007CH\n\nCondPassCond\tDW\tCTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO\n\t\tDW\tCTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON\n\t\tDW\tPAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE\n\t\tDW\tTASKSWITCHABLE, BREAKON\n\nEscRoutine\tDD\t0\t; vector to execute on esc key press (0=none)\n\n; Extended raw keycodes to be converted to Westwood keycodes.\nExtCodes\tDB\t038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H\n\t\tDB\t051H,04DH,035H,01CH,037H\n\t\tDB\t046H\n; The matching Westwood keycodes.\nExtNums\t\tDB\t62,  64,  75,  76,  79,  80,  81,  83,  84,  85\n\t\tDB\t86,  89,  95, 108, 124,  0\n; If extended mapping is disabled, then these codes really are...\nExtRemap\tDB\t60,  58,  99, 104,  92,  91,  93,  96,  98, 101\n\t\tDB\t103, 102, 55,  43, 124,  0\nExtRemapEnd\tDB\t0\n\nExtKeyboard\tDB\t0\t; flag for 101/102-key keyboard\n\n\nKeyBuffer\tDW\t128 DUP(0) ; set to empty\nKeyBufferHead\tDW\t0\t; set to first entry\nKeyBufferTail\tDW\t0\t; set to head for empty buffer\nKeyLock\t\tDW\t0\t; num and caps lock bits\nKeyNums\t\tDB\t127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016\n\t\tDB\t017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032\n\t\tDB\t033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049\n\t\tDB\t050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116\n\t\tDB\t117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093\n\t\tDB\t098,103,099,104,127,127,127,122,123\n\nKeysCapsLock\tDB\t0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0\nKeysNumLock\tDB\t0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0\nKeysUpDown\tDB\t16 DUP(0) ; set to all keys up\nKeyStream\tDB\t16 DUP(0) ; set to all keys up\nPassCount\tDW\t0\nKeyStreamIndex\tDW\t0\nLastKeyE0\tDB\t0\nLastKeyE1\tDB\t0\n\n;\n; Westwood key number values of keys to pass through\n;\n;\t\t\tCAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT,\n;\t\t\tRIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN\nPassAlways\tDB\t30, 44, 57, 58, 60, 62, 64, 90, 128, 128\nPassAlwaysEnd\tDB\t128\t\t; invalid code to END PassAlways\nCtrlFlags\tDB\t0\n\nBuffer\t\tDW\t?\nTime\t\tDW\t?\n\nADJUST\t= 1\t\t\t; do not modify DRD\n\nXYAdjust\tDB\t-ADJUST, -ADJUST\t; 91 -> upleft\n\t\tDB\t-ADJUST,  0\t\t; 92 -> left\n\t\tDB\t-ADJUST,  ADJUST\t; 93 -> downleft\n\t\tDB\t 0,  0\t\t\t; 94 illegal\n\t\tDB\t 0,  0\t\t\t; 95 illegal\n\t\tDB\t 0, -ADJUST\t\t; 96 -> up\n\t\tDB\t 0,  0\t\t\t; 97 illegal (center)\n\t\tDB\t 0,  ADJUST\t\t; 98 -> down\n\t\tDB\t 0,  0\t\t\t; 99 illegal\n\t\tDB\t 0,  0\t\t\t; 100 illegal\n\t\tDB\t ADJUST, -ADJUST\t; 101 -> upright\n\t\tDB\t ADJUST,  0\t\t; 102 -> right\n\t\tDB\t ADJUST,  ADJUST\t; 103 -> downright\nEdgeConv\tDW\t8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7\n\nMouseUpdate\t\tDW\t0\nMouseX\t\t\tDW\t0\nLocalMouseX\t\tDW\t0\nMouseY\t\t\tDW\t0\nLocalMouseY\t\tDW\t0\nButton\t\t\tDW\t0\nIsExtKey\t\tDB\t0\nExtIndex\t\tDW\t0\n\nOldRMI\t\t\tDD\t0\t; The origianl RM interrupt seg:off.\nOldPMIOffset\t\tDD\t0\t; The origianl PM interrupt offset\t\t\nOldPMISelector\t\tDD\t0\t; The original PM interrupt segment.\n\nCodeOffset\t\tDW\tRM_Keystroke_Interrupt\t; Offset of the code in the RM stuff.\nCallRMIntOffset\t\tDW\tCall_Interrupt_Chain\t\t; Offset of function to call DOS timer interrupt.\nCallRMIntAddr\t\tDD\t0\t; PM address of CallRealIntOffset for speed.\n\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Translates the given keynum to ???                  *\n;*                                                                         *\n;* INPUT:\tUWORD the keynum to translate\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated keynum                                 *\n;*                                                                         *\n;* PROTO:\tUWORD KeyNum_Translate(UWORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tKeyNum_Translate:FAR\n\tPROC\tKeyNum_Translate C FAR \n\tUSES\tcx,di,es,ds\n\tARG\tkeycode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\tmov\tes,ax\t\t\t\t; set es up for scansb\n\n\tmov\tax,[keycode]\n\ttest\t[KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\tmov\tcx,ExtRemap-ExtNums\n\tmov\tdi,OFFSET ExtNums\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tdi,OFFSET ExtRemapEnd\n\tdec\tdi\n\tsub\tdi,cx\n\tmov\tal,[es:di]\n??fini:\n\tret\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(WORD code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_WORD:FAR\n\tPROC\tStuff_Key_WORD C FAR \n\tUSES\tsi,bx,ds\n\tARG\tcode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\tax,[KeyBufferTail]\n\tmov\tsi,ax\n\tadd\tax,2\n\tand\tax,0FFh\t\t\t\t; New KeyBufferTail value.\n\tcmp\t[KeyBufferHead],ax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[KeyBuffer+si],bx\t\t; Record the keystroke.\n\tmov\t[KeyBufferTail],ax\n\txor\tax,ax\n\tret\n\n??noroom:\n\tmov\tax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(WORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_Num:FAR\n\tPROC\tStuff_Key_Num C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds\n\tARG\tkeycode:WORD\n\tLOCAL\ttail:WORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n\tpushf\n\tcli\t\t\t\t; disable interrupts\n\n\t; Abort key recognition if in record mode and unable\n\t; to output key due to simultaneous DOS operation.\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\tax,[MouseX]\n\tmov\t[LocalMouseX],ax\n\tmov\tax,[MouseY]\n\tmov\t[LocalMouseY],ax\n\n??cando:\n\tmov\tax,[keycode]\t\t; get the code\n\tor\tax,ax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tbx,1\t\t\t; double for WORD index\n\tadd\tbx,OFFSET XYAdjust\n\tmov\tax,[bx]\t\t\t; get x,y add value\n\n\tmov\tbl,ah\n\tcbw\n\txchg\tax,bx\n\tcbw\n\txchg\tax,bx\t\t\t; AX = mouse x delta, BX = mouse y delta\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tdx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tdx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tbx,dx\t\t\t; add speed for y index\n\tmov\tbl,[KeyMouseMove+bx] \t; get speed for y delta\n\txchg\tax,bx\t\t\t; swap with ax to extend sign\n\tcbw\n\txchg\tax,bx\n\txchg\tbx,dx\t\t\t; save mouse y delta\n\tadd\tbx,ax\t\t\t; add speed for x index\n\tmov\tal,[KeyMouseMove+bx]\t; get speed for x delta\n\tcbw\n\txchg\tbx,dx\t\t\t; restore mouse y delta\n\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tbx,011b\t\t\t; Y = 1, 0, 3\n\tand\tax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tbx,011b\t\t\t; Y = 3, 0, 1\n\tand\tax,011b\t\t\t; X = 3, 0, 1\n\tshl\tbx,1\n\tshl\tbx,1\n\tor\tbx,ax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tbx,1\n\tmov\tbx,[EdgeConv+bx]\n\tshl\tbx,1\n\tshl\tbx,1\n\tmov\tax,[ScreenEdge+bx]\t; New absolute X\n\tmov\tbx,[ScreenEdge+bx+2] ; New absolute Y\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\tax,ax\n\tmov\t[LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tbx,bx\n\tmov\t[LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\tmov\t[MouseX],ax\n\tmov\t[MouseY],bx\n\tcmp\t[MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n; PWG: ARRGGGHHHH!\n;\tcall\tLow_Hide_Mouse\n;\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\tax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],ax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tsi,[KeyBufferTail]\n\tmov\t[tail],si\t\t; Safety record.\n\tmov\tdi,[KeyBufferHead]\n\n\t; Record the base keycode (if there is room).\n\tpush\tax\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\tax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tpush\t[LocalMouseX]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tpush\t[LocalMouseY]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tbx,0101h\t\t; Bit control tools.\n\tmov\tax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tmov\tcl,3\n\tshr\tdi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[KeysUpDown+di]\n\tje\tshort ??notalready\n\ttest\t[KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\t[KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[KeysUpDown+di],bh\t; Force key bit to zero.\n\tor\t[KeysUpDown+di],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\tax,1\n\tjmp short ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\tax,[tail]\n\tmov\t[KeyBufferTail],ax\n\txor\tax,ax\t\t\t; Signal an error.\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tStuff_Key_Num\n;***********************************************************\n\n\n\n;***************************************************************************\n;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard       *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Keystroke_Interrupt\n\tGLOBAL\tC Keystroke_Interrupt:FAR\n\tPROC\tKeystroke_Interrupt C FAR \n\nIF 0\n\tpush\tax\n\tinc\tax\n\tpop\tax\n\tiret\n\nELSE\n\tpush\tax\n\tpush\tbx\n\tpush\tcx\n\tpush\tdi\n\tpush\tds\n\tpush\tdx\n\tpush\tes\n\tpush\tsi\n\tcld\n\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tds,ax\n\tmov\tdx,[KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\tmov\tax,040H\t\t\t; BIOS segment\n\tmov\tes,ax\t\t\t; put in es\n\ttest\t[BYTE PTR es:017H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR es:017H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR es:096H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tes,ax\n\n\tcld\t\t\t\t; clear direction flag for strings\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tbx,0101H\t\t; set key to a make by default\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\n\t;\n\t; New CODE to montior key stream\n\t;\n\tmov\tbx,[KeyStreamIndex]\n\tmov\t[KeyStream+bx],al\n\tinc\tbx\n\tand\tbx,15\n\tmov\t[KeyStreamIndex],bx\n\tmov\tbx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[LastKeyE1]\t\t; yes, dec the count\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[IsExtKey],TRUE\t; it is an extended key\n\tmov\tdi,OFFSET ExtCodes\t; get offset of extended codes table\n\tmov\tcx,(ExtNums-ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\tmov\tal,[(ExtNums - ExtCodes) - 1 + di] ; get the match\n\tmov\t[IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tdi,ax\t\t\t; use code as an index\n\tand\tdi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[KeyNums+di]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[KeysUpDown+8],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[KeysUpDown+7],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[KeysUpDown + 7],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\tax\n\tcall\tKeyNum_Translate\n\tadd\tsp,2\n\n;------\tSet the shift bit if necessary.\n\ttest\t[KeysUpDown+5],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[KeysUpDown+7],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tshr\tdi,1\n\tshr\tdi,1\n\tshr\tdi,1\n\tmov\tbx,ax\n\tand\tbx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[Bits+bx]\t\t; get the bit to test\n\ttest\t[KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[KeysCapsLock+di]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[KeysNumLock+di]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\n\t\t\t\t\t; keyboard buffer.\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\tax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\tax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\tax,0230h\n\tje\tshort ??breaker\n\tcmp\tax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n\tcmp\tax,0420H\t\t; is this an alt s\n\tjne\tshort ??checkmusic\t; toggle the Sound variable\n\tpush\tax\n\tmov\tax,[SoundOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??checkmusic:\n\tcmp\tax,0434H\t\t; is this an alt m\n\tjne\tshort ??esc\t\t; toggle the Music variable\n\tpush\tax\n\tmov\tax,[MusicOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??esc:\n\n\tpush\tax\n\tcall\tStuff_Key_Num\n\tpop\tax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\tax\n\tcall\t[EscRoutine]\n\tpop\tax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tdi,OFFSET PassAlways\t; get offset to table\n\tmov\tcx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1\n\trepne\tscasb\t\t\t; look for a match\n\tor\tcx,cx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n\n\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tdi,OFFSET CondPassKey\t; get offset to cond key table\n\tmov\tcx,(CondPassCond-CondPassKey) ; get number of entries\n\tshr\tcx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(CondPassCond - CondPassKey) - 2 + di]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tdx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n;***********************************************************\n\tpushf\n;\tpush\tdi\n;\tpush\tes\n\t\n\tmov\tax,0B000h\n\tmov\tes,ax\n\tinc\t[BYTE PTR es:0]\n\n;\tpop\tes\n;\tpop\tdi\n\tpopf\n;***********************************************************\n\n??passcode:\n\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tinc\t[cs:PassCount]\n\tjmp\t[cs:OldRMI]\n\n??absorbcode:\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tax,040h\t\t\t\t; BIOS paragraph is always @ 040h\n\tmov\tes,ax\t\t\t\t; put in es as BIOS paragraph\n\tmov\tal,[es:96h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[es:96h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tiret\t\nENDIF\n\n\tENDP\tKeystroke_Interrupt\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles the break key interrupt                      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Break_Interrupt:FAR\n\tPROC\tBreak_Interrupt C FAR\n\n\tiret\t\n\n\tENDP\tBreak_Interrupt\n\n;**************************************************************************\n;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nCall_Interrupt_Chain:\nIF 0\n\tpushf\n\tpush\tax\n\tpush\tdi\n\tpush\tes\n\n\tmov\tax,0B000h\t\t; ES:DI = Mono RAM address.\n\tmov\tes,ax\n\t\t\n\tmov\tal,'A'\n\tmov\tah,2\n\tand\tdi,63\n\n\tstosw\n\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\tmov\tal,CLEARISR\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t; 8259 interrupt chip controller 0\n\n\n\tpop\tes\n\tpop\tdi\n\tpop\tax\n\tpopf\nENDIF\n\tpushf\n\tcall\tKeystroke_Interrupt ;[OldRMI]\n\tretf\n\nSTACK\t   ; Don't really need this\n\n;***********************************************************\nEND\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/X/KEYIREAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*\t\t\t\t  (Mouse Routines)\n;*                                                                         *\n;*                    File Name : KEYIREAL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Philip W. Gorrow                         *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;* This file sort of breaks the standard of keeping all of the keyboard    *\n;* and mouse routines isolated.  This is done because the mouse and\t   *\n;* the keyboard share data, and the best way to do this is to put\t   *\n;* them in the same segment.  This should probably be split into several   *\n;* include files to help make the code clearer once it is finally put\t   *\n;* together.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   KeyNum_Translate -- Translates extended keynums to normal keynums\t   *\n;*   Stuff_Key_Word -- Stuffs a word of data into keyboard buffer          *\n;*   Stuff_Key_Num -- Stuffs a key num code into the circular buffer       *\n;*   Keystroke_Interrupt -- Real mode handler of input from the keyboard   *\n;*   Break_Interrupt -- Handles the break key interrupt                    *\n;*   Call_Interrupt_Chain -- Function PM calls to call RM interrupt chain  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tKeyboard driver -- 8086 Assembly portion;\t\t\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   *\n;***************************************************************************\n\n;---------------------------------------------------------------------------\n; Set the assembly directives\n;---------------------------------------------------------------------------\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386N\t\t\t\t; use 386 real mode instructions\nMODEL TINY\t\t\t; code must be tiny so it fits\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keyboard.inc\"\n\nCONDHIDE\t\tEQU\t08000H\t\t; bit for testing conditional region\nCONDHIDDEN\t\tEQU\t04000H\t\t; bit for testing conditional hidden\nRESTORE_VISIBLE_PAGE\tEQU\t0\nSTORE_VISIBLE_PAGE\tEQU\t1\n\n\nGLOBAL\tset_vesa_page \t:near\nGLOBAL\tset_vesa_window :near\nGLOBAL\tget_vesa_window :near\nGLOBAL\tnext_vesa_page\t:near\n\nECHOON\tequ 0\n;---------------------------------------------------------------------------\n; WARNING!!!!  All of the following code segment variables are shared by\n;   the protected mode interrupt.  Do not change these unless you make the\n;   proper changes to KEYSTRUC.INC.  If you do not know what you are doing,\n;   find someone who does!!!\n;---------------------------------------------------------------------------\nCODESEG\n\n;---------------------------------------------------------------------------\n; Begin definition of Keyboard specific variables\n;---------------------------------------------------------------------------\nSoundOn\t\tDW\t1\t; toggled by alt S\nMusicOn\t\tDW\t1\t; toggled by alt M\nKeyFlags\tDD\tREPEATON+CTRLALTTURBO\t; all but repeat for now\n\n\nBreak\t\tDW\t0\n\nKeyMouseMove\tDB\t-1,0,1\n\t\tDB\t-16,0,16\n\nScreenEdge\tDW\t320/2,0\t\t; North\n\t\tDW\t319,0\t\t; North-East\n\t\tDW\t319,138/2\t; East\n\t\tDW\t319,137\t\t; South-East\n\t\tDW\t320/2,137\t; South\n\t\tDW\t0,137\t\t; South-West\n\t\tDW\t0,138/2\t\t; West\n\t\tDW\t0,0\t\t; North-West\n\t\tDW\t320/2,138/2\t; Center\n\n\nBits\t\tDB\t01H,02H,04H,08H,10H,20H,40H,80H\n\nCondPassKey\tDW\t0220H, 0320H, 060CH, 070DH, 066AH\n\t\tDW\t0669H, 0230H, 0330H, 007DH, 017DH\n\t\tDW\t025AH, 035AH, 0200H, 0410H, 046EH\n\t\tDW\t026EH, 007CH\n\nCondPassCond\tDW\tCTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO\n\t\tDW\tCTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON\n\t\tDW\tPAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE\n\t\tDW\tTASKSWITCHABLE, BREAKON\n\nEscRoutine\tDD\t0\t; vector to execute on esc key press (0=none)\n\n; Extended raw keycodes to be converted to Westwood keycodes.\nExtCodes\tDB\t038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H\n\t\tDB\t051H,04DH,035H,01CH,037H\n\t\tDB\t046H\n; The matching Westwood keycodes.\nExtNums\t\tDB\t62,  64,  75,  76,  79,  80,  81,  83,  84,  85\n\t\tDB\t86,  89,  95, 108, 124,  0\n; If extended mapping is disabled, then these codes really are...\nExtRemap\tDB\t60,  58,  99, 104,  92,  91,  93,  96,  98, 101\n\t\tDB\t103, 102, 55,  43, 124,  0\nExtRemapEnd\tDB\t0\n\nExtKeyboard\tDB\t0\t; flag for 101/102-key keyboard\n\n\nKeyBuffer\tDW\t128 DUP(0) ; set to empty\nKeyBufferHead\tDD\t0\t; set to first entry\nKeyBufferTail\tDD\t0\t; set to head for empty buffer\nKeyLock\t\tDW\t0\t; num and caps lock bits\nKeyNums\t\tDB\t127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016\n\t\tDB\t017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032\n\t\tDB\t033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049\n\t\tDB\t050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116\n\t\tDB\t117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093\n\t\tDB\t098,103,099,104,127,127,127,122,123\n\nKeysCapsLock\tDB\t0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0\nKeysNumLock\tDB\t0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0\nKeysUpDown\tDB\t16 DUP(0) ; set to all keys up\nKeyStream\tDB\t16 DUP(0) ; set to all keys up\nPassCount\tDW\t0\nKeyStreamIndex\tDW\t0\nLastKeyE0\tDB\t0\nLastKeyE1\tDB\t0\n\n;\n; Westwood key number values of keys to pass through\n;\n;\t\t\tCAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT,\n;\t\t\tRIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN\nPassAlways\tDB\t30, 44, 57, 58, 60, 62, 64, 90, 128, 128\nPassAlwaysEnd\tDB\t128\t\t; invalid code to END PassAlways\nCtrlFlags\tDB\t0\n\nBuffer\t\tDW\t?\nTime\t\tDW\t?\n\nADJUST\t= 1\t\t\t; do not modify DRD\n\nXYAdjust\tDB\t-ADJUST, -ADJUST\t; 91 -> upleft\n\t\tDB\t-ADJUST,  0\t\t; 92 -> left\n\t\tDB\t-ADJUST,  ADJUST\t; 93 -> downleft\n\t\tDB\t 0,  0\t\t\t; 94 illegal\n\t\tDB\t 0,  0\t\t\t; 95 illegal\n\t\tDB\t 0, -ADJUST\t\t; 96 -> up\n\t\tDB\t 0,  0\t\t\t; 97 illegal (center)\n\t\tDB\t 0,  ADJUST\t\t; 98 -> down\n\t\tDB\t 0,  0\t\t\t; 99 illegal\n\t\tDB\t 0,  0\t\t\t; 100 illegal\n\t\tDB\t ADJUST, -ADJUST\t; 101 -> upright\n\t\tDB\t ADJUST,  0\t\t; 102 -> right\n\t\tDB\t ADJUST,  ADJUST\t; 103 -> downright\n\tEdgeConv\t\tDW\t8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7\n\tMouseUpdate\t\tDW\t0\n\tMouseX\t\t\tDW\t0,0\n\tLocalMouseX\t\tDW\t0\n\tMouseY\t\t\tDW\t0,0\n\tLocalMouseY\t\tDW\t0\n\tIsExtKey\t\tDB\t0\n\tExtIndex\t\tDW\t0\n\n\tKeyOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tKeyOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\t\t\n\tKeyOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tKeyCodeOffset\t\tDW\tRM_Keystroke_Interrupt\t; Offset of the code in the RM stuff.\n\tCallKeyRMIntOffset\tDW\tCall_Interrupt_Chain\t; Offset of function to call DOS timer interrupt.\n\tCallKeyRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedKeyInt\t\tDD\t0\n\n\tBrkOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tBrkOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\t\t\n\tBrkOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tBrkCodeOffset\t\tDW\tRM_Break_Interrupt\t; Offset of the code in the RM stuff.\n\tCallBrkRMIntOffset\tDW\t0\n\tCallBrkRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedBrkInt\t\tDD\t0\n\tKeyIntDisabled\t\tDD\t0\n\n\tDbgOldPMIOffset\t\tDD\t0\t; The origianl PM interrupt offset\t\t\n\tDbgOldPMISelector\tDD\t0\t; The original PM interrupt segment.\n\n;---------------------------------------------------------------------------\n; Begin definition of Mouse Specific Variables for real mode\n;---------------------------------------------------------------------------\nButton\t\t\tDB\t0\t; current value of the mouse button\nMDisabled\t\tDB\t0\t; Is the mouse driver disabled\nMInput\t\t\tDB\t1\t; Defaults to mouse input allowed.\nAdjust\t\t\tDW\t0\t; flag to adjust coordinates if necessary\nMouseStepX\t\tDW\t0\t; step values if the mouse moves at\nMouseStepY\t\tDW\t0\t;   more than one pixel at a time\nMouseOffsetX\t\tDW\t0\t; Fractional step values used if a mouse\nMouseOffsetY\t\tDW\t0\t;   moves at less than one pixel at a time\nMState\t\t\tDW\t0,0\t; Tracks if mouse is hidden (TRUE) or not (FALSE)\nMouseXOld     \t\tDW\t0\t; Holds last MouseX and MouseY to determine if \nMouseYOld     \t\tDW\t0\t;   mouse needs to be redrawn\nMCState\t\t\tDW\t0\t; Tracks if mouse conditional hidden (TRUE) or not\nMouseCXLeft\t\tDW\t0,0\t; Conditional hide mouse left x position\nMouseCYUpper\t\tDW\t0,0\t; Conditional hide mouse top y position\nMouseCXRight\t\tDW\t0,0\t; Conditional hide mouse right x position\nMouseCYLower\t\tDW\t0,0\t; Conditional hide mouse lower y position\nMouseCursor   \t\tDD\t0\t; Pointer to the mouse cursor to draw\nMouseCursorSize\t\tDW\t0\t; Pointer to buffer mouse is saved in\nMouseBuffer   \t\tDD\t0\t; Pointer to buffer mouse is saved in\nMouseXHot     \t\tDW\t0,0\t; Offset to mouse's x hot spot\nMouseYHot     \t\tDW\t0,0\t; Offset to mouse's y hot spot\nMouseBuffX\t\tDW\t0,0\t; X position background was saved at\nMouseBuffY\t\tDW\t0,0\t; Y position background was saved at\nMouseBuffW\t\tDW\t0,0\t; Width of the region saved for mouse\nMouseBuffH\t\tDW\t0,0\t; Height of the region saved for mouse\nMouseWidth\t\tDW\t0,0\t; Mouse cursor theoretical width\nMouseHeight\t\tDW\t0,0\t; Mouse cursor theoretical height\nMouseCodeOffset\t\tDW\tRM_Mouse_Interrupt\t; Offset of the code in the RM stuff.\nMouseRight\t\tDW\t0,0\nMouseBottom\t\tDW\t0,0\n\n\nShadowPtr\t\tdw\t0\nDrawMousePtr \t\tdw\t0\n\nVGAMouseDraw\t\tdw\tVGA_Draw_Mouse\nVGAMouseShadow\t\tdw\tVGA_Mouse_Shadow_Buffer\n\nVESAMouseDraw\t\tdw\tVESA_Draw_Mouse\nVESAMouseShadow\t\tdw\tVESA_Mouse_Shadow_Buffer\n\nVesaPtr\t\t\tdd\t0\t\nbanktable\t\tdd      8 dup ( 0 )\nAdjust_XPos\t\tdw \t0 , 0\nAdjust_YPos\t\tdw \t0 , 0 \n\n\t\talign 2\nKeyboard_App_Stack_ES\tdw 0\t\t; This the System Stack Offsset\nKeyboard_App_Stack_SS\tdw 0\t\t; This the System Stack Selector\nKeyboard_StackPointer\tdw 0DEADh\t; We Create a Local Application\nKeyboard_Stack\t\tdw 255 dup (0)\nKeyboard_StackStart\tdw 0\n\nMouse_State\t\tdw 0\t\t; Mouse Temp Variable\nMouse_Cond\t\tdw 0\t\t; Mouse Temp Variable\nMouse_App_Stack_ES\tdw 0\t\t; This the System Stack Offsset\nMouse_App_Stack_SS\tdw 0\t\t; This the System Stack Selector\nMouse_StackPointer\tdw 0DEADh\t; We Create a Local Application\nMouse_Stack\t\tdw 255 dup (0)\nMouse_StackStart\tdw 0\n\n\n\ncurrent_page\t\tdw\t0\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Translates extended keynums to normal keynums\t   *\n;*                                                                         *\n;* INPUT:\tUWORD the keynum to translate\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated keynum                                 *\n;*                                                                         *\n;* PROTO:\tUWORD KeyNum_Translate(UWORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tKeyNum_Translate:FAR\n\tPROC\tKeyNum_Translate C FAR \n\tUSES\tcx,di,es,ds\n\tARG\tkeycode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\tmov\tes,ax\t\t\t\t; set es up for scansb\n\n\tmov\tax,[keycode]\n\ttest\t[WORD PTR KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\tmov\tcx,ExtRemap-ExtNums\n\tmov\tdi,OFFSET ExtNums\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tdi,OFFSET ExtRemapEnd\n\tdec\tdi\n\tsub\tdi,cx\n\tmov\tal,[es:di]\n??fini:\n\tret\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(WORD code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_WORD:FAR\n\tPROC\tStuff_Key_WORD C FAR \n\tUSES\tsi,bx,ds\n\tARG\tcode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\tax,[WORD PTR KeyBufferTail]\n\tmov\tsi,ax\n\tadd\tax,2\n\tand\tax,0FFh\t\t\t\t; New KeyBufferTail value.\n\tcmp\t[WORD PTR KeyBufferHead],ax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[KeyBuffer+si],bx\t\t; Record the keystroke.\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\n\tret\n\n??noroom:\n\tmov\tax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(WORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_Num:FAR\n\tPROC\tStuff_Key_Num C FAR \n\tUSES\tbx,cx,dx,di,si,ds\n\tARG\tkeycode:WORD\n\tLOCAL\ttail:WORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n\tpushf\n\tcli\t\t\t\t; disable interrupts\n\n\t; Abort key recognition if in record mode and unable\n\t; to output key due to simultaneous DOS operation.\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\tax,[MouseX]\n\tmov\t[LocalMouseX],ax\n\tmov\tax,[MouseY]\n\tmov\t[LocalMouseY],ax\n\n??cando:\n\tmov\tax,[keycode]\t\t; get the code\n\tor\tax,ax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[WORD PTR KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[WORD PTR KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tbx,1\t\t\t; double for WORD index\n\tadd\tbx,OFFSET XYAdjust\n\tmov\tax,[bx]\t\t\t; get x,y add value\n\n\tmov\tbl,ah\n\tcbw\n\txchg\tax,bx\n\tcbw\n\txchg\tax,bx\t\t\t; AX = mouse x delta, BX = mouse y delta\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tdx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tdx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tbx,dx\t\t\t; add speed for y index\n\tmov\tbl,[KeyMouseMove+bx] \t; get speed for y delta\n\txchg\tax,bx\t\t\t; swap with ax to extend sign\n\tcbw\n\txchg\tax,bx\n\txchg\tbx,dx\t\t\t; save mouse y delta\n\tadd\tbx,ax\t\t\t; add speed for x index\n\tmov\tal,[KeyMouseMove+bx]\t; get speed for x delta\n\tcbw\n\txchg\tbx,dx\t\t\t; restore mouse y delta\n\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tbx,011b\t\t\t; Y = 1, 0, 3\n\tand\tax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tbx,011b\t\t\t; Y = 3, 0, 1\n\tand\tax,011b\t\t\t; X = 3, 0, 1\n\tshl\tbx,1\n\tshl\tbx,1\n\tor\tbx,ax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tbx,1\n\tmov\tbx,[EdgeConv+bx]\n\tshl\tbx,1\n\tshl\tbx,1\n\tmov\tax,[ScreenEdge+bx]\t; New absolute X\n\tmov\tbx,[ScreenEdge+bx+2] ; New absolute Y\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\tax,ax\n\tmov\t[LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tbx,bx\n\tmov\t[LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\tmov\t[MouseX],ax\n\tmov\t[MouseY],bx\n\tcmp\t[MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n\n\tcall\tLow_Hide_Mouse\n\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\tax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],ax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tsi,[WORD KeyBufferTail]\n\tmov\t[tail],si\t\t; Safety record.\n\tmov\tdi,[WORD PTR KeyBufferHead]\n\n\t; Record the base keycode (if there is room).\n\tpush\tax\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\tax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tpush\t[LocalMouseX]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tpush\t[LocalMouseY]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tbx,0101h\t\t; Bit control tools.\n\tmov\tax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[WORD PTR KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tmov\tcl,3\n\tshr\tdi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[KeysUpDown+di]\n\tje\tshort ??notalready\n\ttest\t[WORD PTR KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[KeysUpDown+di],bh\t; Force key bit to zero.\n\tor\t[KeysUpDown+di],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\tax,1\n\tjmp short ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\tax,[tail]\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\t\t\t; Signal an error.\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tStuff_Key_Num\n;***********************************************************\n\n\n\n;***************************************************************************\n;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard       *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Keystroke_Interrupt\n\tGLOBAL\tC Keystroke_Interrupt:FAR\n\tPROC\tKeystroke_Interrupt C FAR \n\nIF 0\n\tpush\tax\n\tinc\tax\n\tpop\tax\n\tiret\n\nELSE\n\tpush\tax\n\tpush\tbx\n\tpush\tcx\n\tpush\tdi\n\tpush\tds\n\tpush\tdx\n\tpush\tes\n\tpush\tsi\n\tcld\n\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tds,ax\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov cx, ss\t\t\t\t; get SS\n\tmov [Keyboard_App_Stack_ES], sp\t\t; Protect ES\n\tmov [Keyboard_App_Stack_SS], cx\t\t; Protect SS\n\tlea dx, [Keyboard_StackStart ]\t\t; Compute Local Stack size\n\tand dx, -2;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov sp, dx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n\tcmp\t[WORD PTR PMIssuedKeyInt],0; Check to see if PM made Int call.\n\tmov\t[WORD PTR PMIssuedKeyInt],0; Make it false.\t\t\n\tjne\t??passcode\t; if so, just call Int Chain.\n\n\n\tmov\tdx,[WORD PTR KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\tmov\tax,040H\t\t\t; BIOS segment\n\tmov\tes,ax\t\t\t; put in es\n\ttest\t[BYTE PTR es:017H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR es:017H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR es:096H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tes,ax\n\n\tcld\t\t\t\t; clear direction flag for strings\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tbx,0101H\t\t; set key to a make by default\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\n\t;\n\t; New CODE to montior key stream\n\t;\n\tmov\tbx,[KeyStreamIndex]\n\tmov\t[KeyStream+bx],al\n\tinc\tbx\n\tand\tbx,15\n\tmov\t[KeyStreamIndex],bx\n\tmov\tbx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[LastKeyE1]\t\t; yes, dec the count\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[IsExtKey],TRUE\t; it is an extended key\n\tmov\tdi,OFFSET ExtCodes\t; get offset of extended codes table\n\tmov\tcx,(ExtNums-ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\tmov\tal,[(ExtNums - ExtCodes) - 1 + di] ; get the match\n\tmov\t[IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tdi,ax\t\t\t; use code as an index\n\tand\tdi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[KeyNums+di]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[KeysUpDown+8],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[KeysUpDown+7],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[KeysUpDown + 7],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\tax\n\tcall\tKeyNum_Translate\n\tadd\tsp,2\n\n;------\tSet the shift bit if necessary.\n\ttest\t[KeysUpDown+5],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[KeysUpDown+7],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tshr\tdi,1\n\tshr\tdi,1\n\tshr\tdi,1\n\tmov\tbx,ax\n\tand\tbx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[Bits+bx]\t\t; get the bit to test\n\ttest\t[KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[KeysCapsLock+di]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[KeysNumLock+di]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\t\n\t\t\t\t\t; keyboard buffer.\n\ttest\tdx,DEBUGINT\n\tjz\t??not_toggle \n\n\nIF DEBUG\n\tcmp\t[KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\tcmp\tax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\tax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\tax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\t\n\tcmp\tax,125\n\tjne\t??not_toggle\n\tmov\t[KeyIntDisabled],1\n\tjmp\t??absorbcode\nENDIF\n\n??not_toggle:\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\tax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\tax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\tax,0230h\n\tje\tshort ??breaker\n\tcmp\tax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n\tcmp\tax,0420H\t\t; is this an alt s\n\tjne\tshort ??checkmusic\t; toggle the Sound variable\n\tpush\tax\n\tmov\tax,[SoundOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??checkmusic:\n\tcmp\tax,0434H\t\t; is this an alt m\n\tjne\tshort ??esc\t\t; toggle the Music variable\n\tpush\tax\n\tmov\tax,[MusicOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??esc:\n\n\tpush\tax\n\tcall\tStuff_Key_Num\n\tpop\tax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\tax\n\tcall\t[EscRoutine]\n\tpop\tax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tdi,OFFSET PassAlways\t; get offset to table\n\tmov\tcx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1\n\trepne\tscasb\t\t\t; look for a match\n\tor\tcx,cx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n\n\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tdi,OFFSET CondPassKey\t; get offset to cond key table\n\tmov\tcx,(CondPassCond-CondPassKey) ; get number of entries\n\tshr\tcx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(CondPassCond - CondPassKey) - 2 + di]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tdx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\n\tinc\t[cs:PassCount]\n\n;mov   ax , 0B000h\n;mov   es, ax \n;inc   [BYTE PTR es : 40h]\n\n\t; Now it is time to set up for the call to the System Keyboard\n\t; interrupt handler.\n\t; 1 -Restore System Stack Pointer Selector before exit Interrupt\n\t; 2- We Create a Returning Point from Interrupt by Push A\n \t;    Interupt Stack Frame into the Stack Pointer\n\t; 3- We make a Far jump to the interuupt handler\n\tcmp [Keyboard_StackPointer],0DEADh\n\tje  ??stackok\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n??stackok:\n\tcli\t\t\t\t       ; disable Interrupts\n\tmov dx, [Keyboard_App_Stack_SS]       \n\tmov ss, dx\t\t\t       ; Get System Stack Selector\n\tmov sp, [Keyboard_App_Stack_ES]      ; Get System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n\tlea\tdx, [??Call_Back_Keyboard]   ; Get Return address offset\n \tpushf\t\t\t\t      ; push flags\t\n\tpush\tcs\t\t\t      ; push Code segment\n\tpush\tdx\t\t\t      ; push Offset\n\n\t; Now we need to simulate an interrup call by using ired\n\t; because we still want to come back here from the\n\t; Old Keyboard interrupt handle.\n\tpushf\n\tpush\t[word ptr KeyOldRMI + 2] \t; push orig segment.\n\tpush    [word ptr KeyOldRMI]   \t\t; push orig offset.\n\tiret\t \t\t        \t; call interrupt\t\n\n??absorbcode:\n\n;mov   ax , 0B000h\n;mov   es, ax \n;inc   [BYTE PTR es : 0h]\n\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tax,040h\t\t\t\t; BIOS paragraph is always @ 040h\n\tmov\tes,ax\t\t\t\t; put in es as BIOS paragraph\n\tmov\tal,[es:96h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[es:96h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\n\tcmp [Keyboard_StackPointer],0DEADh\n\tje  ??stackok2\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n??stackok2:\n\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov dx, [Keyboard_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, dx\t\t\t       ; Get Syatem Stack Selector\n\tmov sp, [Keyboard_App_Stack_ES]        ; Get Syatem Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n??Call_Back_Keyboard:\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tiret\t\nENDIF\n\n\tENDP\tKeystroke_Interrupt\n\n;***************************************************************************\n;* Break interrupt routines begin here!\n;***************************************************************************\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles the break key interrupt                      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Break_Interrupt\n\tGLOBAL\tC Break_Interrupt:FAR\n\tPROC\tBreak_Interrupt C FAR\n\n\n\tpushf\n\tpush\tax\n\tpush\tes\n\n\tmov\tax,0B000h\t\t; ES:DI = Mono RAM address.\n\tmov\tes,ax\n\tinc\t[BYTE PTR es:0]\n\t\t\n\n\tpop\tes\n\tpop\tax\n\tpopf\n\n\n\tiret\t\n\n\tENDP\tBreak_Interrupt\n\n;**************************************************************************\n;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                                  *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nCall_Interrupt_Chain:\n\tpushf\n\tcall\tKeystroke_Interrupt ;[KeyOldRMI]\n\tretf\n\n;----------------------------------------------------------------------------\n; LOW_HIDE_MOUSE:\n;\n; This function hides the mouse cursor on the screen if it was shown.  It \n; will not hide the mouse if it is already hidden.\n;\n; PROTOTYPE:\n;\n;\tVOID Low_Hide_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Hide_Mouse:FAR\n\tPROC\tLow_Hide_Mouse C FAR \n\tUSES\tax,bx,cx,dx,ds\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n   \tcmp\t[MDisabled],0\t\t; check if mouse is disabled\n\tjne\tshort ??end\n\n   \tcmp\t[MState],0\t\t; check if it was hidden before\n\tjne\tshort ??endnodraw\t\t; no need to hide again\n\n;------\tMove the saved graphic buffer to the seenpage to hide the mouse.\n;\tcall\tBuffer_To_Page C,[buffx],[buffy],[buffw],[buffh],[MouseBuffer],SEENPAGE\n\tmov\tax,RESTORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tRecord that the mouse has been hidden.\n??endnodraw:\n\tadd\t[MState],1\n\tadc\t[MState],0\n\n??end:\n\tret\n\n\tENDP\tLow_Hide_Mouse\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; LOW_SHOW_MOUSE:\n;\n; This function displays the mouse cursor on the screen if it was hidden.\n;\n; PROTOTYPE:\n;\tVOID Low_Show_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Show_Mouse:FAR\n\tPROC\tLow_Show_Mouse C FAR \n\tUSES \tax,bx,cx,dx,si,di,ds,es\n\tLOCAL\tmousex:WORD\t\t; Draw X position.\n\tLOCAL\tmousey:WORD\t\t; Draw Y position.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n;-----\tDon't show the mouse if it is not hidden, disabled.\n\tcmp\t[MDisabled],0\t\t; is the mouse disabled\n\tjne\t??exit\t\t\t; if so then exit\n\n\tcmp\t[MState],0\t\t; is the mouse already visible\n       \tje\t??exit\t\t\t; if so then exit\n\n\tdec\t[MState]\n\tcmp\t[MState],0\t\t; can the mouse be shown\n       \tjne\tshort ??exit\n\n;------\tDetermine the drawing position of the mouse.\n\tmov\tcx,[MouseWidth]\t\t; Theoretical buffer width (pixel).\n\tmov\tdx,[MouseHeight]\t; Theoretical buffer height (pixel).\n\n\tmov\tax,[MouseX]\n;\tsub\tax,[MouseXHot]\n\tmov\t[mousex],ax\t\t; Draw X pixel.\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??xnotneg\n;\tadd\tcx,ax\t\t\t; Reduce width accordingly.\n;\tmov\tax,0\n??xnotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n\tmov\tbx,[MouseY]\n;\tsub\tbx,[MouseYHot]\n\tmov\t[mousey],bx\t\t; Draw Y pixel.\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??ynotneg\n;\tadd\tdx,bx\t\t\t; Reduce height of mouse accordingly.\n;\tmov\tbx,0\n??ynotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n;------\tDetermine the theoretical coordinates and dimensions of the\n;\tarea the mouse shape will be rendered upon.\n\tmov\t[MouseBuffX],ax\n\tmov\t[MouseBuffY],bx\n\tmov\t[MouseBuffW],cx\n\tmov\t[MouseBuffH],dx\n\n;------\tMove the area that will be drawn upon, to the graphic buffer.\n\tmov\tax,STORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tDraw the mouse shape to the seenpage.\n\tpush\t[mousey]\n\tpush\t[mousex]\n\tpush\tcs\n\tcall\t[ DrawMousePtr ]\n\tadd\tsp,4\n??exit:\n\tret\n\n\tENDP\tLow_Show_Mouse\n\n;----------------------------------------------------------------------------\n;----------------------------------------------------------------------------\n\tGLOBAL\tC Mouse_KeyNum:FAR\n\tPROC\tMouse_KeyNum C FAR \n\tUSES\tbx\n\tARG\tstate:WORD\t\t; Current mouse state.\n\tLOCAL\tkeynum:WORD\t\t; Determined keynum.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\t[keynum],KN_MOUSE_MOVE\t; Presume just a mouse move.\n\tmov\tbx,[state]\n\tmov\tax,bx\n\txor\tbl,[Button]\t\t; Bits of state change.\n\tje\tshort ??fini\n\tmov\t[Button],al\t\t; Record new mouse state.\n\n\ttest\tbl,0010b\n\tje\tshort ??notright\n\tmov\t[keynum],KN_RMOUSE\n\ttest\tal,0010b\n\tjne\tshort ??notright\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notright:\n\n; DRD\n; note:  the left mouse button has priority over the right mouse button\n; this should be changed at a later date to process them independently\n\n\ttest\tbl,0001b\n\tje\tshort ??notleft\n\tmov\t[keynum],KN_LMOUSE\n\ttest\tal,0001b\n\tjne\tshort ??notleft\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notleft:\n\n??fini:\n\tmov\tax,[keynum]\n\tret\n\n\tENDP\tMouse_KeyNum\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; MOUSE_INT:\n;\n; This routine is called automatically when the Mouse_Int is installed.  It\n; automatically updates the global variables stored in the code segment so\n; that the mouse information is automatically known at all times.\n;\n; INPUTS (from int):\tAX = condition mask ( bit 0 == cursor position chg,\n;\t\t\t\t\t      bit 1 == left button press,\n;\t\t\t\t\t      bit 2 == left button release,\n;\t\t\t\t\t      bit 3 == right button press,\n;\t\t\t\t\t      bit 4 == right button release,\n;\t\t\t\t\t      5-15  == not used )\n;\t\t\tBX = button state   ( bit 0 == left button down,\n;\t\t\t\t\t      bit 1 == right button down,\n;                                             bit 2 == middle button down.\n;\t\t\t\t\t      3-15  == not used )\n;\t\t\tCX = cursor coordinate (horizontal axis)\n;\t\t\tDX = cursor coordinate (vertical axis)\n;\t\t\tDI = horizontal mouse count (mickeys)\n;\t\t\tSI = vertical mouse count (mickeys)\n;\n; RETURNS:\t\tnone\n;\n; MODIFIES:\t\tmodifies the variables _Button, _ButtonChange,\n;\t\t\t_MouseX,_MouseY,_ButtonLatch\n;\n; PROTOTYPE:\n;\tThis routine is called from an interrupt.\n;----------------------------------------------------------------------------\nlabel RM_Mouse_Interrupt\n\tPROC\tMouse_Int C FAR \n\tUSES\tax,bx,cx,dx,ds,si,es,di\n\tLOCAL\tcond:WORD\t\t; Local copy of mouse event.\n\tLOCAL\tstate:WORD\t\t; Local copy of button state.\n\n\tmov\t[cs:Mouse_State],bx\n\tmov\t[cs:Mouse_Cond],ax\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov bx, ss\t\t\t\t; get SS\n\tmov [Mouse_App_Stack_ES], sp\t\t; Protect ES\n\tmov [Mouse_App_Stack_SS], bx\t\t; Protect SS\n\tlea bx, [Mouse_StackStart ]\t; Compute Local Stack size\n\tand bx, -2;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov sp, bx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n;------\tProcess the mouse interrupt only if the mouse is enabled (whether\n;\tpresent or not).\n\tcmp\t[MDisabled],0\n\tjne\t??exit\n\n\tcmp\t[MInput],0\n\tje\t??exit\n\n\n;------ This was added because of missing mouse presses and\n;\treleases during a mouse update.\n\tmov\tax,[Mouse_Cond]\n\tand\tax,0001EH \t; bits for left and right press and release\n\tjne\tshort ??dopress_release\n\n\tcmp\t[MouseUpdate],0 ; if mouse move and mouse updating exit\n\tjne\t??exit\n\n??dopress_release:\n\n;------\tIn EEGA mode mouse X coordinates as 0..639.  Make adjustment\n;\tto keep within 0..319 range.\n\tcmp\t[Adjust],1\t\t; if the x coordinate is returned\n\tjne\tshort ??noadjust\t; incorrectly then\n\tshr\tcx,1\t\t\t; adjust x coord from 640 pixel screen\n??noadjust:\n\n\n; scale mouse posX and PosY\n;\tcmp\t[Adjust_XPos] , 0\n;\tjz\tshort ??no_scaleX\n;\tpush\tdx\n;\tmov\tax , [MouseRight]\n;\timul\tcx\n;\tidiv\t[Adjust_XPos]\n;\tmov\tcx , ax\n;\tpop\tdx\n??no_scaleX:\n;\tcmp\t[Adjust_YPos] , 0\n;\tjz\tshort ??no_scaleY\n;\tmov\tax , [MouseBottom]\n;\timul\tdx\n;\tidiv\t[Adjust_YPos]\n;\tmov\tdx , ax\n??no_scaleY:\n\n;------\tKeep mouse within screen bounds.\n\tcmp\tcx,[MouseRight]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundX_ok\t\t; force it to stay at least one pixel\n\tmov\tcx,[MouseRight]\t\t\t; on the screen\n\tdec\tcx\n??boundX_ok:\n\tcmp\tdx,[MouseBottom]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundY_ok\t\t; force it to stay at least one pixel\n\tmov\tdx,[MouseBottom]\t\t\t; on the screen\n\tdec\tdx\n??boundY_ok:\n\n\tIF 0\n;------\tRemap the middle button to equal the right button.\n\ttest\tbx,04h\n\tje\t??noremap\n\tor\tbx,0010b\t\t; Set the right button bit.\n??noremap:\n\tENDIF\n\n\tmov\t[MouseX],cx\t\t; and store in mouse x\n\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\ttest\t[KeyFlags],KEYMOUSE\n\tjne\tshort ??nostuffit\n\n\tcall\tMouse_KeyNum C,[Mouse_State]\t; Convert mouse state to key number code.\n\tcall\tStuff_Key_Num C,ax\t; Record mouse keynumber code.\n??nostuffit:\n\n\n\n;------ The check for Mouse in the middle of updating CAN NOT BE MOVED\n;\tany farther up because mouse presses and releases will be LOST!!\n \tcmp\t[MouseUpdate],0\n\tjne\t??exit\n;??jexit:\n;\tjmp\t??exit\n\n\nchristopher:\n??chkxy:\n\n;------\tSignal that no mouse updating can occur at this time.\n;\tcmp\t[_MouseUpdate],0\n;\tjne\t??exit\n;\tmov\t[_MouseUpdate],1\n\n;------\tPerform any X movement grid adjustment.\n\tcmp\t[MouseStepX],0\t\t; are we stepping on the X?\n\tje\tshort ??no_x_step\t\t; no x\n\tmov\tax,cx\t\t\t; get current x_pixel\n\tmov\tcx,dx\t\t\t; save dx - it is trashed by idiv\n\tsub\tax,[MouseOffsetX]\t; get offset difference\n\tmov\tbx,[MouseStepX]\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step X\n\timul\tbx\t\t\t; ax = div * Step X\n\tadd\tax,[MouseOffsetX]\t; normalize to region offset\n\tmov\tdx,cx\t\t\t; restore dx (new MouseY)\n\tmov\tcx,ax\t\t\t; set cx (new MouseX)\n??no_x_step:\n\n;------\tPerform any Y movement grid adjustment.\n\tcmp\t[MouseStepY],0\t\t; are we stepping on the Y\n\tje\tshort ??no_step\t\t; no y\n\tmov\tax,dx\t\t\t; get current y_pixel\n\tsub\tax,[MouseOffsetY]\t; get offset difference\n\tmov\tbx,[MouseStepY]\t\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step Y\n\timul\tbx\t\t\t; ax = div * Step Y\n\tadd\tax,[MouseOffsetY]\t; normalize to region offset\n\tmov\tdx,ax\t\t\t; set dx (new MouseY)\n??no_step:\n\n;------ Here is where we store the new MouseX and MouseY values\n;\tmov\t[MouseX],cx\t\t; and store in mouse x\n;\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\n;------\tIf the mouse is hidden or its position hasn't changed, then\n;\tperform no action.\n\tcmp\t[MState],0\n\tjne\tshort ??updateend\n\tcmp\t[MouseXOld],cx\n\tjne\tshort ??doit\n\tcmp\t[MouseYOld],dx\n\tje\tshort ??updateend\n??doit:\n\n;------\tAt this point we KNOW the mouse has moved.\n\tmov\tax,[MCState]\n\tand\tax,CONDHIDE+CONDHIDDEN\n\tcmp\tax,CONDHIDE+CONDHIDDEN\n\tje\tshort ??condcheck\t\t; If already hidden.\n\n;------\tWe know that the mouse is visible, we must hide it\n;\tbefore we update its position.\n\tcall\tLow_Hide_Mouse\n\n;------\tConditional region check goes here.  If the mouse falls within the \n;\tconditional region, it gets marked as hidden and no other processing\n;\toccurs.\n\ttest\t[MCState],CONDHIDE\n\tje\tshort ??condok\n\n??condcheck:\n\tcmp\tcx,[MouseCXLeft]\t\t; check adjusted x region\n\tjb\tshort ??condok\n\tcmp\tcx,[MouseCXRight]\n\tja\tshort ??condok\n\tcmp\tdx,[MouseCYUpper]\t; check adjusted y region\n\tjb\tshort ??condok\n\tcmp\tdx,[MouseCYLower]\n\tja\tshort ??condok\n\n\tor\t[MCState],CONDHIDDEN\t; flag as conditional hidden\n\tjmp short ??updateend\n\n;------\tThe mouse coordinates and flags pass all of the tests, proceed\n;\twith rendering the mouse.\n??condok:\n\tcall\tLow_Show_Mouse\n\n;------\tFinal clean up and exit.\n??updateend:\n\tmov\t[MouseXOld],cx\n\tmov\t[MouseYOld],dx\n\n??exit:\n\tcmp\t[Mouse_StackPointer],0DEADh\n\tje\t??mouse_stk_ok\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n\n??mouse_stk_ok:\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov ax, [Mouse_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, ax\t\t\t       ; Get Syatem Stack Selector\n\tmov sp, [Mouse_App_Stack_ES]           ; Get Syatem Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\tret\n\tENDP\tMouse_Int\n\n\n\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VGA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVGA_Mouse_Shadow_Buffer C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\tpush\tbp\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tbp , cx\n??restore_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 10\nmov es, ax\nmov al , 'V'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tsi,di\t\t\t\t\t; xchg the source and the dest\n\tmov\tbp , cx\n\tpush\tes\t\t\t\t\t; need to swap es and ds but\n\tpush\tds\t\t\t\t\t;   cant xchg so pop them on the\n\tpop\tes\t\t\t\t\t;   stack and pop them off the\n\tpop\tds\t\t\t\t\t;   wrong way intentionally.\n??store_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,dx\t\t\t\t\t; move past right clipped pixels\n\tadd\tdi,bx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 12\nmov es, ax\nmov al , 'G'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tret\n\n\tENDP\tVGA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n\n\tGLOBAL\tC VGA_Draw_Mouse:FAR\n\tPROC\tVGA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tbx , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , bx\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tbx , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , bx\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 14\nmov es, ax\nmov al , 'A'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tret\nENDP\tVGA_Draw_Mouse\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VESA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVESA_Mouse_Shadow_Buffer C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\t\n\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??restore_loop:\n\tmov\tah,al\n??res_inner_loop:\n\tmov\tch , [si]\n\tmov\t[es:di],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??res_same_page\n\tcall\tnext_vesa_page\n ??res_same_page:\n \tdec\tah\n\tjnz\t??res_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??res_same_page1\n\tcall\tnext_vesa_page\n ??res_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 10\nmov es,ax\nmov al ,'v'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tjmp\t??out\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\tmov\tah,al\n??store_inner_loop:\n\tmov\tch , [es:di]\n\tmov\t[si],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??store_same_page\n\tcall\tnext_vesa_page\n ??store_same_page:\n \tdec\tah\n\tjnz\t??store_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??store_same_page1\n\tcall\tnext_vesa_page\n ??store_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_entry\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 14\nmov es,ax\nmov al ,'e'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\n\tmov\tdx , [ app_vesa_window ] \n\tcall\tset_vesa_window\n\tret\n\n\tENDP\tVESA_Mouse_Shadow_Buffer\n\n\n\n;***************************************************************************\n\n\tGLOBAL\tC VESA_Draw_Mouse:FAR\n\tPROC\tVESA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\tlocal\tapp_vesa_window : word\n\n   \n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tsi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tjnz\t??same_page\n\tcall\tnext_vesa_page\n ??same_page:\n \tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??same_page1\n\tcall\tnext_vesa_page\n ??same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 14\nmov es, ax\nmov al , 's'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nmov di , 10 * 80 + 16\nmov al , 'a'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tmov\tdx , [ app_vesa_window ] \n\tcall\tset_vesa_window\n\tret\n\n\nENDP\tVESA_Draw_Mouse\n\n\n\n;************************************************************************\n\nPROC\tget_vesa_window C near\nuses\tax,bx\n\tmov\tax , 04f05h\n\tmov\tbh , 1\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\t\n\n;************************************************************************\n\nPROC\tset_vesa_window C near\nuses\tax,bx,dx\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]  \t\n\tret\nENDP\t\n\n\n;***************************************************************************\n\nPROC\tset_vesa_page C near\nUSES\tax,bx,dx\n\n\tmov\tbx , dx\n\tshl\tbx , 2\n\tmov\t[ cs: current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tset_vesa_page\n\nPROC\tnext_vesa_page C near\nUSES\tax,bx,dx\n\tmov\tbx , [ cs: current_page ]\n\tadd\tbx , 4\n\tmov\t[ cs:current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n       \tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tnext_vesa_page\n\n\n\n;***********************************************************\nEND\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/X/KEYIREAL.BAK",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*\t\t\t\t  (Mouse Routines)\n;*                                                                         *\n;*                    File Name : KEYIREAL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Philip W. Gorrow                         *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;* This file sort of breaks the standard of keeping all of the keyboard    *\n;* and mouse routines isolated.  This is done because the mouse and\t   *\n;* the keyboard share data, and the best way to do this is to put\t   *\n;* them in the same segment.  This should probably be split into several   *\n;* include files to help make the code clearer once it is finally put\t   *\n;* together.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   KeyNum_Translate -- Translates extended keynums to normal keynums\t   *\n;*   Stuff_Key_Word -- Stuffs a word of data into keyboard buffer          *\n;*   Stuff_Key_Num -- Stuffs a key num code into the circular buffer       *\n;*   Keystroke_Interrupt -- Real mode handler of input from the keyboard   *\n;*   Break_Interrupt -- Handles the break key interrupt                    *\n;*   Call_Interrupt_Chain -- Function PM calls to call RM interrupt chain  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tKeyboard driver -- 8086 Assembly portion;\t\t\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   *\n;***************************************************************************\n\n;---------------------------------------------------------------------------\n; Set the assembly directives\n;---------------------------------------------------------------------------\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386N\t\t\t\t; use 386 real mode instructions\nMODEL TINY\t\t\t; code must be tiny so it fits\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keyboard.inc\"\n\nCONDHIDE\t\tEQU\t08000H\t\t; bit for testing conditional region\nCONDHIDDEN\t\tEQU\t04000H\t\t; bit for testing conditional hidden\nRESTORE_VISIBLE_PAGE\tEQU\t0\nSTORE_VISIBLE_PAGE\tEQU\t1\n\n\nGLOBAL\tset_vesa_page \t:near\nGLOBAL\tset_vesa_window :near\nGLOBAL\tget_vesa_window :near\nGLOBAL\tnext_vesa_page\t:near\n\nECHOON\tequ 0\n;---------------------------------------------------------------------------\n; WARNING!!!!  All of the following code segment variables are shared by\n;   the protected mode interrupt.  Do not change these unless you make the\n;   proper changes to KEYSTRUC.INC.  If you do not know what you are doing,\n;   find someone who does!!!\n;---------------------------------------------------------------------------\nCODESEG\n\n;---------------------------------------------------------------------------\n; Begin definition of Keyboard specific variables\n;---------------------------------------------------------------------------\nSoundOn\t\tDW\t1\t; toggled by alt S\nMusicOn\t\tDW\t1\t; toggled by alt M\nKeyFlags\tDD\tREPEATON+CTRLALTTURBO\t; all but repeat for now\n\n\nBreak\t\tDW\t0\n\nKeyMouseMove\tDB\t-1,0,1\n\t\tDB\t-16,0,16\n\nScreenEdge\tDW\t320/2,0\t\t; North\n\t\tDW\t319,0\t\t; North-East\n\t\tDW\t319,138/2\t; East\n\t\tDW\t319,137\t\t; South-East\n\t\tDW\t320/2,137\t; South\n\t\tDW\t0,137\t\t; South-West\n\t\tDW\t0,138/2\t\t; West\n\t\tDW\t0,0\t\t; North-West\n\t\tDW\t320/2,138/2\t; Center\n\n\nBits\t\tDB\t01H,02H,04H,08H,10H,20H,40H,80H\n\nCondPassKey\tDW\t0220H, 0320H, 060CH, 070DH, 066AH\n\t\tDW\t0669H, 0230H, 0330H, 007DH, 017DH\n\t\tDW\t025AH, 035AH, 0200H, 0410H, 046EH\n\t\tDW\t026EH, 007CH\n\nCondPassCond\tDW\tCTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO\n\t\tDW\tCTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON\n\t\tDW\tPAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE\n\t\tDW\tTASKSWITCHABLE, BREAKON\n\nEscRoutine\tDD\t0\t; vector to execute on esc key press (0=none)\n\n; Extended raw keycodes to be converted to Westwood keycodes.\nExtCodes\tDB\t038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H\n\t\tDB\t051H,04DH,035H,01CH,037H\n\t\tDB\t046H\n; The matching Westwood keycodes.\nExtNums\t\tDB\t62,  64,  75,  76,  79,  80,  81,  83,  84,  85\n\t\tDB\t86,  89,  95, 108, 124,  0\n; If extended mapping is disabled, then these codes really are...\nExtRemap\tDB\t60,  58,  99, 104,  92,  91,  93,  96,  98, 101\n\t\tDB\t103, 102, 55,  43, 124,  0\nExtRemapEnd\tDB\t0\n\nExtKeyboard\tDB\t0\t; flag for 101/102-key keyboard\n\n\nKeyBuffer\tDW\t128 DUP(0) ; set to empty\nKeyBufferHead\tDD\t0\t; set to first entry\nKeyBufferTail\tDD\t0\t; set to head for empty buffer\nKeyLock\t\tDW\t0\t; num and caps lock bits\nKeyNums\t\tDB\t127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016\n\t\tDB\t017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032\n\t\tDB\t033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049\n\t\tDB\t050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116\n\t\tDB\t117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093\n\t\tDB\t098,103,099,104,127,127,127,122,123\n\nKeysCapsLock\tDB\t0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0\nKeysNumLock\tDB\t0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0\nKeysUpDown\tDB\t16 DUP(0) ; set to all keys up\nKeyStream\tDB\t16 DUP(0) ; set to all keys up\nPassCount\tDW\t0\nKeyStreamIndex\tDW\t0\nLastKeyE0\tDB\t0\nLastKeyE1\tDB\t0\n\n;\n; Westwood key number values of keys to pass through\n;\n;\t\t\tCAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT,\n;\t\t\tRIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN\nPassAlways\tDB\t30, 44, 57, 58, 60, 62, 64, 90, 128, 128\nPassAlwaysEnd\tDB\t128\t\t; invalid code to END PassAlways\nCtrlFlags\tDB\t0\n\nBuffer\t\tDW\t?\nTime\t\tDW\t?\n\nADJUST\t= 1\t\t\t; do not modify DRD\n\nXYAdjust\tDB\t-ADJUST, -ADJUST\t; 91 -> upleft\n\t\tDB\t-ADJUST,  0\t\t; 92 -> left\n\t\tDB\t-ADJUST,  ADJUST\t; 93 -> downleft\n\t\tDB\t 0,  0\t\t\t; 94 illegal\n\t\tDB\t 0,  0\t\t\t; 95 illegal\n\t\tDB\t 0, -ADJUST\t\t; 96 -> up\n\t\tDB\t 0,  0\t\t\t; 97 illegal (center)\n\t\tDB\t 0,  ADJUST\t\t; 98 -> down\n\t\tDB\t 0,  0\t\t\t; 99 illegal\n\t\tDB\t 0,  0\t\t\t; 100 illegal\n\t\tDB\t ADJUST, -ADJUST\t; 101 -> upright\n\t\tDB\t ADJUST,  0\t\t; 102 -> right\n\t\tDB\t ADJUST,  ADJUST\t; 103 -> downright\n\tEdgeConv\t\tDW\t8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7\n\tMouseUpdate\t\tDW\t0\n\tMouseX\t\t\tDW\t0,0\n\tLocalMouseX\t\tDW\t0\n\tMouseY\t\t\tDW\t0,0\n\tLocalMouseY\t\tDW\t0\n\tIsExtKey\t\tDB\t0\n\tExtIndex\t\tDW\t0\n\n\tKeyOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tKeyOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\t\t\n\tKeyOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tKeyCodeOffset\t\tDW\tRM_Keystroke_Interrupt\t; Offset of the code in the RM stuff.\n\tCallKeyRMIntOffset\tDW\tCall_Interrupt_Chain\t; Offset of function to call DOS timer interrupt.\n\tCallKeyRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedKeyInt\t\tDD\t0\n\n\tBrkOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tBrkOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\t\t\n\tBrkOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tBrkCodeOffset\t\tDW\tRM_Break_Interrupt\t; Offset of the code in the RM stuff.\n\tCallBrkRMIntOffset\tDW\t0\n\tCallBrkRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedBrkInt\t\tDD\t0\n\tKeyIntDisabled\t\tDD\t0\n\n\tDbgOldPMIOffset\t\tDD\t0\t; The origianl PM interrupt offset\t\t\n\tDbgOldPMISelector\tDD\t0\t; The original PM interrupt segment.\n\n;---------------------------------------------------------------------------\n; Begin definition of Mouse Specific Variables for real mode\n;---------------------------------------------------------------------------\nButton\t\t\tDB\t0\t; current value of the mouse button\nMDisabled\t\tDB\t0\t; Is the mouse driver disabled\nMInput\t\t\tDB\t1\t; Defaults to mouse input allowed.\nAdjust\t\t\tDW\t0\t; flag to adjust coordinates if necessary\nMouseStepX\t\tDW\t0\t; step values if the mouse moves at\nMouseStepY\t\tDW\t0\t;   more than one pixel at a time\nMouseOffsetX\t\tDW\t0\t; Fractional step values used if a mouse\nMouseOffsetY\t\tDW\t0\t;   moves at less than one pixel at a time\nMState\t\t\tDW\t0,0\t; Tracks if mouse is hidden (TRUE) or not (FALSE)\nMouseXOld     \t\tDW\t0\t; Holds last MouseX and MouseY to determine if \nMouseYOld     \t\tDW\t0\t;   mouse needs to be redrawn\nMCState\t\t\tDW\t0\t; Tracks if mouse conditional hidden (TRUE) or not\nMouseCXLeft\t\tDW\t0,0\t; Conditional hide mouse left x position\nMouseCYUpper\t\tDW\t0,0\t; Conditional hide mouse top y position\nMouseCXRight\t\tDW\t0,0\t; Conditional hide mouse right x position\nMouseCYLower\t\tDW\t0,0\t; Conditional hide mouse lower y position\nMouseCursor   \t\tDD\t0\t; Pointer to the mouse cursor to draw\nMouseCursorSize\t\tDW\t0\t; Pointer to buffer mouse is saved in\nMouseBuffer   \t\tDD\t0\t; Pointer to buffer mouse is saved in\nMouseXHot     \t\tDW\t0,0\t; Offset to mouse's x hot spot\nMouseYHot     \t\tDW\t0,0\t; Offset to mouse's y hot spot\nMouseBuffX\t\tDW\t0,0\t; X position background was saved at\nMouseBuffY\t\tDW\t0,0\t; Y position background was saved at\nMouseBuffW\t\tDW\t0,0\t; Width of the region saved for mouse\nMouseBuffH\t\tDW\t0,0\t; Height of the region saved for mouse\nMouseWidth\t\tDW\t0,0\t; Mouse cursor theoretical width\nMouseHeight\t\tDW\t0,0\t; Mouse cursor theoretical height\nMouseCodeOffset\t\tDW\tRM_Mouse_Interrupt\t; Offset of the code in the RM stuff.\nMouseRight\t\tDW\t0,0\nMouseBottom\t\tDW\t0,0\n\n\nShadowPtr\t\tdw\t0\nDrawMousePtr \t\tdw\t0\n\nVGAMouseDraw\t\tdw\tVGA_Draw_Mouse\nVGAMouseShadow\t\tdw\tVGA_Mouse_Shadow_Buffer\n\nVESAMouseDraw\t\tdw\tVESA_Draw_Mouse\nVESAMouseShadow\t\tdw\tVESA_Mouse_Shadow_Buffer\n\nVesaPtr\t\t\tdd\t0\t\nbanktable\t\tdd      8 dup ( 0 )\nAdjust_XPos\t\tdw \t0 , 0\nAdjust_YPos\t\tdw \t0 , 0 \n\n\t\talign 2\nKeyboard_App_Stack_ES\tdw 0\t\t; This the System Stack Offsset\nKeyboard_App_Stack_SS\tdw 0\t\t; This the System Stack Selector\nKeyboard_StackPointer\tdw 0DEADh\t; We Create a Local Application\nKeyboard_Stack\t\tdw 255 dup (0)\nKeyboard_StackStart\tdw 0\n\nMouse_State\t\tdw 0\t\t; Mouse Temp Variable\nMouse_Cond\t\tdw 0\t\t; Mouse Temp Variable\nMouse_App_Stack_ES\tdw 0\t\t; This the System Stack Offsset\nMouse_App_Stack_SS\tdw 0\t\t; This the System Stack Selector\nMouse_StackPointer\tdw 0DEADh\t; We Create a Local Application\nMouse_Stack\t\tdw 255 dup (0)\nMouse_StackStart\tdw 0\n\n\n\ncurrent_page\t\tdw\t0\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Translates extended keynums to normal keynums\t   *\n;*                                                                         *\n;* INPUT:\tUWORD the keynum to translate\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated keynum                                 *\n;*                                                                         *\n;* PROTO:\tUWORD KeyNum_Translate(UWORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tKeyNum_Translate:FAR\n\tPROC\tKeyNum_Translate C FAR \n\tUSES\tcx,di,es,ds\n\tARG\tkeycode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\tmov\tes,ax\t\t\t\t; set es up for scansb\n\n\tmov\tax,[keycode]\n\ttest\t[WORD PTR KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\tmov\tcx,ExtRemap-ExtNums\n\tmov\tdi,OFFSET ExtNums\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tdi,OFFSET ExtRemapEnd\n\tdec\tdi\n\tsub\tdi,cx\n\tmov\tal,[es:di]\n??fini:\n\tret\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(WORD code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_WORD:FAR\n\tPROC\tStuff_Key_WORD C FAR \n\tUSES\tsi,bx,ds\n\tARG\tcode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\tax,[WORD PTR KeyBufferTail]\n\tmov\tsi,ax\n\tadd\tax,2\n\tand\tax,0FFh\t\t\t\t; New KeyBufferTail value.\n\tcmp\t[WORD PTR KeyBufferHead],ax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[KeyBuffer+si],bx\t\t; Record the keystroke.\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\n\tret\n\n??noroom:\n\tmov\tax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(WORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_Num:FAR\n\tPROC\tStuff_Key_Num C FAR \n\tUSES\tbx,cx,dx,di,si,ds\n\tARG\tkeycode:WORD\n\tLOCAL\ttail:WORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n\tpushf\n\tcli\t\t\t\t; disable interrupts\n\n\t; Abort key recognition if in record mode and unable\n\t; to output key due to simultaneous DOS operation.\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\tax,[MouseX]\n\tmov\t[LocalMouseX],ax\n\tmov\tax,[MouseY]\n\tmov\t[LocalMouseY],ax\n\n??cando:\n\tmov\tax,[keycode]\t\t; get the code\n\tor\tax,ax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[WORD PTR KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[WORD PTR KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tbx,1\t\t\t; double for WORD index\n\tadd\tbx,OFFSET XYAdjust\n\tmov\tax,[bx]\t\t\t; get x,y add value\n\n\tmov\tbl,ah\n\tcbw\n\txchg\tax,bx\n\tcbw\n\txchg\tax,bx\t\t\t; AX = mouse x delta, BX = mouse y delta\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tdx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tdx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tbx,dx\t\t\t; add speed for y index\n\tmov\tbl,[KeyMouseMove+bx] \t; get speed for y delta\n\txchg\tax,bx\t\t\t; swap with ax to extend sign\n\tcbw\n\txchg\tax,bx\n\txchg\tbx,dx\t\t\t; save mouse y delta\n\tadd\tbx,ax\t\t\t; add speed for x index\n\tmov\tal,[KeyMouseMove+bx]\t; get speed for x delta\n\tcbw\n\txchg\tbx,dx\t\t\t; restore mouse y delta\n\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tbx,011b\t\t\t; Y = 1, 0, 3\n\tand\tax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tbx,011b\t\t\t; Y = 3, 0, 1\n\tand\tax,011b\t\t\t; X = 3, 0, 1\n\tshl\tbx,1\n\tshl\tbx,1\n\tor\tbx,ax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tbx,1\n\tmov\tbx,[EdgeConv+bx]\n\tshl\tbx,1\n\tshl\tbx,1\n\tmov\tax,[ScreenEdge+bx]\t; New absolute X\n\tmov\tbx,[ScreenEdge+bx+2] ; New absolute Y\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\tax,ax\n\tmov\t[LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tbx,bx\n\tmov\t[LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\tmov\t[MouseX],ax\n\tmov\t[MouseY],bx\n\tcmp\t[MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n\n\tcall\tLow_Hide_Mouse\n\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\tax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],ax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tsi,[WORD KeyBufferTail]\n\tmov\t[tail],si\t\t; Safety record.\n\tmov\tdi,[WORD PTR KeyBufferHead]\n\n\t; Record the base keycode (if there is room).\n\tpush\tax\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\tax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tpush\t[LocalMouseX]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tpush\t[LocalMouseY]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tbx,0101h\t\t; Bit control tools.\n\tmov\tax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[WORD PTR KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tmov\tcl,3\n\tshr\tdi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[KeysUpDown+di]\n\tje\tshort ??notalready\n\ttest\t[WORD PTR KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[KeysUpDown+di],bh\t; Force key bit to zero.\n\tor\t[KeysUpDown+di],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\tax,1\n\tjmp short ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\tax,[tail]\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\t\t\t; Signal an error.\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tStuff_Key_Num\n;***********************************************************\n\n\n\n;***************************************************************************\n;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard       *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Keystroke_Interrupt\n\tGLOBAL\tC Keystroke_Interrupt:FAR\n\tPROC\tKeystroke_Interrupt C FAR \n\nIF 0\n\tpush\tax\n\tinc\tax\n\tpop\tax\n\tiret\n\nELSE\n\tpush\tax\n\tpush\tbx\n\tpush\tcx\n\tpush\tdi\n\tpush\tds\n\tpush\tdx\n\tpush\tes\n\tpush\tsi\n\tcld\n\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tds,ax\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov cx, ss\t\t\t\t; get SS\n\tmov [Keyboard_App_Stack_ES], sp\t\t; Protect ES\n\tmov [Keyboard_App_Stack_SS], cx\t\t; Protect SS\n\tlea dx, [Keyboard_StackStart ]\t\t; Compute Local Stack size\n\tand dx, -2;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov sp, dx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n\tcmp\t[WORD PTR PMIssuedKeyInt],0; Check to see if PM made Int call.\n\tmov\t[WORD PTR PMIssuedKeyInt],0; Make it false.\t\t\n\tjne\t??passcode\t; if so, just call Int Chain.\n\n\n\tmov\tdx,[WORD PTR KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\tmov\tax,040H\t\t\t; BIOS segment\n\tmov\tes,ax\t\t\t; put in es\n\ttest\t[BYTE PTR es:017H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR es:017H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR es:096H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tes,ax\n\n\tcld\t\t\t\t; clear direction flag for strings\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tbx,0101H\t\t; set key to a make by default\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\n\t;\n\t; New CODE to montior key stream\n\t;\n\tmov\tbx,[KeyStreamIndex]\n\tmov\t[KeyStream+bx],al\n\tinc\tbx\n\tand\tbx,15\n\tmov\t[KeyStreamIndex],bx\n\tmov\tbx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[LastKeyE1]\t\t; yes, dec the count\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[IsExtKey],TRUE\t; it is an extended key\n\tmov\tdi,OFFSET ExtCodes\t; get offset of extended codes table\n\tmov\tcx,(ExtNums-ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\tmov\tal,[(ExtNums - ExtCodes) - 1 + di] ; get the match\n\tmov\t[IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tdi,ax\t\t\t; use code as an index\n\tand\tdi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[KeyNums+di]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[KeysUpDown+8],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[KeysUpDown+7],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[KeysUpDown + 7],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\tax\n\tcall\tKeyNum_Translate\n\tadd\tsp,2\n\n;------\tSet the shift bit if necessary.\n\ttest\t[KeysUpDown+5],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[KeysUpDown+7],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tshr\tdi,1\n\tshr\tdi,1\n\tshr\tdi,1\n\tmov\tbx,ax\n\tand\tbx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[Bits+bx]\t\t; get the bit to test\n\ttest\t[KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[KeysCapsLock+di]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[KeysNumLock+di]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\t\n\t\t\t\t\t; keyboard buffer.\n\ttest\tdx,DEBUGINT\n\tjz\t??not_toggle \n\n\nIF DEBUG\n\tcmp\t[KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\tcmp\tax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\tax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\tax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\t\n\tcmp\tax,125\n\tjne\t??not_toggle\n\tmov\t[KeyIntDisabled],1\n\tjmp\t??absorbcode\nENDIF\n\n??not_toggle:\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\tax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\tax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\tax,0230h\n\tje\tshort ??breaker\n\tcmp\tax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n\tcmp\tax,0420H\t\t; is this an alt s\n\tjne\tshort ??checkmusic\t; toggle the Sound variable\n\tpush\tax\n\tmov\tax,[SoundOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??checkmusic:\n\tcmp\tax,0434H\t\t; is this an alt m\n\tjne\tshort ??esc\t\t; toggle the Music variable\n\tpush\tax\n\tmov\tax,[MusicOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??esc:\n\n\tpush\tax\n\tcall\tStuff_Key_Num\n\tpop\tax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\tax\n\tcall\t[EscRoutine]\n\tpop\tax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tdi,OFFSET PassAlways\t; get offset to table\n\tmov\tcx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1\n\trepne\tscasb\t\t\t; look for a match\n\tor\tcx,cx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n\n\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tdi,OFFSET CondPassKey\t; get offset to cond key table\n\tmov\tcx,(CondPassCond-CondPassKey) ; get number of entries\n\tshr\tcx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(CondPassCond - CondPassKey) - 2 + di]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tdx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\n\tinc\t[cs:PassCount]\n\n;mov   ax , 0B000h\n;mov   es, ax \n;inc   [BYTE PTR es : 40h]\n\n\t; Now it is time to set up for the call to the System Keyboard\n\t; interrupt handler.\n\t; 1 -Restore System Stack Pointer Selector before exit Interrupt\n\t; 2- We Create a Returning Point from Interrupt by Push A\n \t;    Interupt Stack Frame into the Stack Pointer\n\t; 3- We make a Far jump to the interuupt handler\n\tcmp [Keyboard_StackPointer],0DEADh\n\tje  ??stackok\n\tmov [BYTE PTR 0B000h:0h],'&'\n??stackok:\n\tcli\t\t\t\t       ; disable Interrupts\n\tmov dx, [Keyboard_App_Stack_SS]       \n\tmov ss, dx\t\t\t       ; Get System Stack Selector\n\tmov sp, [Keyboard_App_Stack_ES]      ; Get System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n\tlea\tdx, [??Call_Back_Keyboard]   ; Get Return address offset\n \tpushf\t\t\t\t      ; push flags\t\n\tpush\tcs\t\t\t      ; push Code segment\n\tpush\tdx\t\t\t      ; push Offset\n\n\t; Now we need to simulate an interrup call by using ired\n\t; because we still want to come back here from the\n\t; Old Keyboard interrupt handle.\n\tpushf\n\tpush\t[word ptr KeyOldRMI + 2] \t; push orig segment.\n\tpush    [word ptr KeyOldRMI]   \t\t; push orig offset.\n\tiret\t \t\t        \t; call interrupt\t\n\n??absorbcode:\n\n;mov   ax , 0B000h\n;mov   es, ax \n;inc   [BYTE PTR es : 0h]\n\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tax,040h\t\t\t\t; BIOS paragraph is always @ 040h\n\tmov\tes,ax\t\t\t\t; put in es as BIOS paragraph\n\tmov\tal,[es:96h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[es:96h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\n\tcmp [Keyboard_StackPointer],0DEADh\n\tje  ??stackok2\n\tmov [BYTE PTR 0B000h:0h],'&'\n??stackok2:\n\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov dx, [Keyboard_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, dx\t\t\t       ; Get Syatem Stack Selector\n\tmov sp, [Keyboard_App_Stack_ES]        ; Get Syatem Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n??Call_Back_Keyboard:\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tiret\t\nENDIF\n\n\tENDP\tKeystroke_Interrupt\n\n;***************************************************************************\n;* Break interrupt routines begin here!\n;***************************************************************************\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles the break key interrupt                      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Break_Interrupt\n\tGLOBAL\tC Break_Interrupt:FAR\n\tPROC\tBreak_Interrupt C FAR\n\n\n\tpushf\n\tpush\tax\n\tpush\tes\n\n\tmov\tax,0B000h\t\t; ES:DI = Mono RAM address.\n\tmov\tes,ax\n\tinc\t[BYTE PTR es:0]\n\t\t\n\n\tpop\tes\n\tpop\tax\n\tpopf\n\n\n\tiret\t\n\n\tENDP\tBreak_Interrupt\n\n;**************************************************************************\n;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                                  *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nCall_Interrupt_Chain:\n\tpushf\n\tcall\tKeystroke_Interrupt ;[KeyOldRMI]\n\tretf\n\n;----------------------------------------------------------------------------\n; LOW_HIDE_MOUSE:\n;\n; This function hides the mouse cursor on the screen if it was shown.  It \n; will not hide the mouse if it is already hidden.\n;\n; PROTOTYPE:\n;\n;\tVOID Low_Hide_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Hide_Mouse:FAR\n\tPROC\tLow_Hide_Mouse C FAR \n\tUSES\tax,bx,cx,dx,ds\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n   \tcmp\t[MDisabled],0\t\t; check if mouse is disabled\n\tjne\tshort ??end\n\n   \tcmp\t[MState],0\t\t; check if it was hidden before\n\tjne\tshort ??endnodraw\t\t; no need to hide again\n\n;------\tMove the saved graphic buffer to the seenpage to hide the mouse.\n;\tcall\tBuffer_To_Page C,[buffx],[buffy],[buffw],[buffh],[MouseBuffer],SEENPAGE\n\tmov\tax,RESTORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tRecord that the mouse has been hidden.\n??endnodraw:\n\tadd\t[MState],1\n\tadc\t[MState],0\n\n??end:\n\tret\n\n\tENDP\tLow_Hide_Mouse\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; LOW_SHOW_MOUSE:\n;\n; This function displays the mouse cursor on the screen if it was hidden.\n;\n; PROTOTYPE:\n;\tVOID Low_Show_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Show_Mouse:FAR\n\tPROC\tLow_Show_Mouse C FAR \n\tUSES \tax,bx,cx,dx,si,di,ds,es\n\tLOCAL\tmousex:WORD\t\t; Draw X position.\n\tLOCAL\tmousey:WORD\t\t; Draw Y position.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n;-----\tDon't show the mouse if it is not hidden, disabled.\n\tcmp\t[MDisabled],0\t\t; is the mouse disabled\n\tjne\t??exit\t\t\t; if so then exit\n\n\tcmp\t[MState],0\t\t; is the mouse already visible\n       \tje\t??exit\t\t\t; if so then exit\n\n\tdec\t[MState]\n\tcmp\t[MState],0\t\t; can the mouse be shown\n       \tjne\tshort ??exit\n\n;------\tDetermine the drawing position of the mouse.\n\tmov\tcx,[MouseWidth]\t\t; Theoretical buffer width (pixel).\n\tmov\tdx,[MouseHeight]\t; Theoretical buffer height (pixel).\n\n\tmov\tax,[MouseX]\n;\tsub\tax,[MouseXHot]\n\tmov\t[mousex],ax\t\t; Draw X pixel.\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??xnotneg\n;\tadd\tcx,ax\t\t\t; Reduce width accordingly.\n;\tmov\tax,0\n??xnotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n\tmov\tbx,[MouseY]\n;\tsub\tbx,[MouseYHot]\n\tmov\t[mousey],bx\t\t; Draw Y pixel.\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??ynotneg\n;\tadd\tdx,bx\t\t\t; Reduce height of mouse accordingly.\n;\tmov\tbx,0\n??ynotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n;------\tDetermine the theoretical coordinates and dimensions of the\n;\tarea the mouse shape will be rendered upon.\n\tmov\t[MouseBuffX],ax\n\tmov\t[MouseBuffY],bx\n\tmov\t[MouseBuffW],cx\n\tmov\t[MouseBuffH],dx\n\n;------\tMove the area that will be drawn upon, to the graphic buffer.\n\tmov\tax,STORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tDraw the mouse shape to the seenpage.\n\tpush\t[mousey]\n\tpush\t[mousex]\n\tpush\tcs\n\tcall\t[ DrawMousePtr ]\n\tadd\tsp,4\n??exit:\n\tret\n\n\tENDP\tLow_Show_Mouse\n\n;----------------------------------------------------------------------------\n;----------------------------------------------------------------------------\n\tGLOBAL\tC Mouse_KeyNum:FAR\n\tPROC\tMouse_KeyNum C FAR \n\tUSES\tbx\n\tARG\tstate:WORD\t\t; Current mouse state.\n\tLOCAL\tkeynum:WORD\t\t; Determined keynum.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\t[keynum],KN_MOUSE_MOVE\t; Presume just a mouse move.\n\tmov\tbx,[state]\n\tmov\tax,bx\n\txor\tbl,[Button]\t\t; Bits of state change.\n\tje\tshort ??fini\n\tmov\t[Button],al\t\t; Record new mouse state.\n\n\ttest\tbl,0010b\n\tje\tshort ??notright\n\tmov\t[keynum],KN_RMOUSE\n\ttest\tal,0010b\n\tjne\tshort ??notright\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notright:\n\n; DRD\n; note:  the left mouse button has priority over the right mouse button\n; this should be changed at a later date to process them independently\n\n\ttest\tbl,0001b\n\tje\tshort ??notleft\n\tmov\t[keynum],KN_LMOUSE\n\ttest\tal,0001b\n\tjne\tshort ??notleft\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notleft:\n\n??fini:\n\tmov\tax,[keynum]\n\tret\n\n\tENDP\tMouse_KeyNum\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; MOUSE_INT:\n;\n; This routine is called automatically when the Mouse_Int is installed.  It\n; automatically updates the global variables stored in the code segment so\n; that the mouse information is automatically known at all times.\n;\n; INPUTS (from int):\tAX = condition mask ( bit 0 == cursor position chg,\n;\t\t\t\t\t      bit 1 == left button press,\n;\t\t\t\t\t      bit 2 == left button release,\n;\t\t\t\t\t      bit 3 == right button press,\n;\t\t\t\t\t      bit 4 == right button release,\n;\t\t\t\t\t      5-15  == not used )\n;\t\t\tBX = button state   ( bit 0 == left button down,\n;\t\t\t\t\t      bit 1 == right button down,\n;                                             bit 2 == middle button down.\n;\t\t\t\t\t      3-15  == not used )\n;\t\t\tCX = cursor coordinate (horizontal axis)\n;\t\t\tDX = cursor coordinate (vertical axis)\n;\t\t\tDI = horizontal mouse count (mickeys)\n;\t\t\tSI = vertical mouse count (mickeys)\n;\n; RETURNS:\t\tnone\n;\n; MODIFIES:\t\tmodifies the variables _Button, _ButtonChange,\n;\t\t\t_MouseX,_MouseY,_ButtonLatch\n;\n; PROTOTYPE:\n;\tThis routine is called from an interrupt.\n;----------------------------------------------------------------------------\nlabel RM_Mouse_Interrupt\n\tPROC\tMouse_Int C FAR \n\tUSES\tax,bx,cx,dx,ds,si,es,di\n\tLOCAL\tcond:WORD\t\t; Local copy of mouse event.\n\tLOCAL\tstate:WORD\t\t; Local copy of button state.\n\n\tmov\t[cs:Mouse_State],bx\n\tmov\t[cs:Mouse_Cond],ax\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov bx, ss\t\t\t\t; get SS\n\tmov [Mouse_App_Stack_ES], sp\t\t; Protect ES\n\tmov [Mouse_App_Stack_SS], bx\t\t; Protect SS\n\tlea bx, [Mouse_StackStart ]\t; Compute Local Stack size\n\tand bx, -2;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov sp, bx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n;------\tProcess the mouse interrupt only if the mouse is enabled (whether\n;\tpresent or not).\n\tcmp\t[MDisabled],0\n\tjne\t??exit\n\n\tcmp\t[MInput],0\n\tje\t??exit\n\n\n;------ This was added because of missing mouse presses and\n;\treleases during a mouse update.\n\tmov\tax,[Mouse_Cond]\n\tand\tax,0001EH \t; bits for left and right press and release\n\tjne\tshort ??dopress_release\n\n\tcmp\t[MouseUpdate],0 ; if mouse move and mouse updating exit\n\tjne\t??exit\n\n??dopress_release:\n\n;------\tIn EEGA mode mouse X coordinates as 0..639.  Make adjustment\n;\tto keep within 0..319 range.\n\tcmp\t[Adjust],1\t\t; if the x coordinate is returned\n\tjne\tshort ??noadjust\t; incorrectly then\n\tshr\tcx,1\t\t\t; adjust x coord from 640 pixel screen\n??noadjust:\n\n\n; scale mouse posX and PosY\n;\tcmp\t[Adjust_XPos] , 0\n;\tjz\tshort ??no_scaleX\n;\tpush\tdx\n;\tmov\tax , [MouseRight]\n;\timul\tcx\n;\tidiv\t[Adjust_XPos]\n;\tmov\tcx , ax\n;\tpop\tdx\n??no_scaleX:\n;\tcmp\t[Adjust_YPos] , 0\n;\tjz\tshort ??no_scaleY\n;\tmov\tax , [MouseBottom]\n;\timul\tdx\n;\tidiv\t[Adjust_YPos]\n;\tmov\tdx , ax\n??no_scaleY:\n\n;------\tKeep mouse within screen bounds.\n\tcmp\tcx,[MouseRight]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundX_ok\t\t; force it to stay at least one pixel\n\tmov\tcx,[MouseRight]\t\t\t; on the screen\n\tdec\tcx\n??boundX_ok:\n\tcmp\tdx,[MouseBottom]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundY_ok\t\t; force it to stay at least one pixel\n\tmov\tdx,[MouseBottom]\t\t\t; on the screen\n\tdec\tdx\n??boundY_ok:\n\n\tIF 0\n;------\tRemap the middle button to equal the right button.\n\ttest\tbx,04h\n\tje\t??noremap\n\tor\tbx,0010b\t\t; Set the right button bit.\n??noremap:\n\tENDIF\n\n\tmov\t[MouseX],cx\t\t; and store in mouse x\n\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\ttest\t[KeyFlags],KEYMOUSE\n\tjne\tshort ??nostuffit\n\n\tcall\tMouse_KeyNum C,[Mouse_State]\t; Convert mouse state to key number code.\n\tcall\tStuff_Key_Num C,ax\t; Record mouse keynumber code.\n??nostuffit:\n\n\n\n;------ The check for Mouse in the middle of updating CAN NOT BE MOVED\n;\tany farther up because mouse presses and releases will be LOST!!\n \tcmp\t[MouseUpdate],0\n\tjne\t??exit\n;??jexit:\n;\tjmp\t??exit\n\n\nchristopher:\n??chkxy:\n\n;------\tSignal that no mouse updating can occur at this time.\n;\tcmp\t[_MouseUpdate],0\n;\tjne\t??exit\n;\tmov\t[_MouseUpdate],1\n\n;------\tPerform any X movement grid adjustment.\n\tcmp\t[MouseStepX],0\t\t; are we stepping on the X?\n\tje\tshort ??no_x_step\t\t; no x\n\tmov\tax,cx\t\t\t; get current x_pixel\n\tmov\tcx,dx\t\t\t; save dx - it is trashed by idiv\n\tsub\tax,[MouseOffsetX]\t; get offset difference\n\tmov\tbx,[MouseStepX]\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step X\n\timul\tbx\t\t\t; ax = div * Step X\n\tadd\tax,[MouseOffsetX]\t; normalize to region offset\n\tmov\tdx,cx\t\t\t; restore dx (new MouseY)\n\tmov\tcx,ax\t\t\t; set cx (new MouseX)\n??no_x_step:\n\n;------\tPerform any Y movement grid adjustment.\n\tcmp\t[MouseStepY],0\t\t; are we stepping on the Y\n\tje\tshort ??no_step\t\t; no y\n\tmov\tax,dx\t\t\t; get current y_pixel\n\tsub\tax,[MouseOffsetY]\t; get offset difference\n\tmov\tbx,[MouseStepY]\t\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step Y\n\timul\tbx\t\t\t; ax = div * Step Y\n\tadd\tax,[MouseOffsetY]\t; normalize to region offset\n\tmov\tdx,ax\t\t\t; set dx (new MouseY)\n??no_step:\n\n;------ Here is where we store the new MouseX and MouseY values\n;\tmov\t[MouseX],cx\t\t; and store in mouse x\n;\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\n;------\tIf the mouse is hidden or its position hasn't changed, then\n;\tperform no action.\n\tcmp\t[MState],0\n\tjne\tshort ??updateend\n\tcmp\t[MouseXOld],cx\n\tjne\tshort ??doit\n\tcmp\t[MouseYOld],dx\n\tje\tshort ??updateend\n??doit:\n\n;------\tAt this point we KNOW the mouse has moved.\n\tmov\tax,[MCState]\n\tand\tax,CONDHIDE+CONDHIDDEN\n\tcmp\tax,CONDHIDE+CONDHIDDEN\n\tje\tshort ??condcheck\t\t; If already hidden.\n\n;------\tWe know that the mouse is visible, we must hide it\n;\tbefore we update its position.\n\tcall\tLow_Hide_Mouse\n\n;------\tConditional region check goes here.  If the mouse falls within the \n;\tconditional region, it gets marked as hidden and no other processing\n;\toccurs.\n\ttest\t[MCState],CONDHIDE\n\tje\tshort ??condok\n\n??condcheck:\n\tcmp\tcx,[MouseCXLeft]\t\t; check adjusted x region\n\tjb\tshort ??condok\n\tcmp\tcx,[MouseCXRight]\n\tja\tshort ??condok\n\tcmp\tdx,[MouseCYUpper]\t; check adjusted y region\n\tjb\tshort ??condok\n\tcmp\tdx,[MouseCYLower]\n\tja\tshort ??condok\n\n\tor\t[MCState],CONDHIDDEN\t; flag as conditional hidden\n\tjmp short ??updateend\n\n;------\tThe mouse coordinates and flags pass all of the tests, proceed\n;\twith rendering the mouse.\n??condok:\n\tcall\tLow_Show_Mouse\n\n;------\tFinal clean up and exit.\n??updateend:\n\tmov\t[MouseXOld],cx\n\tmov\t[MouseYOld],dx\n\n??exit:\n\tcmp\t[Mouse_StackPointer],0DEADh\n\tje\t??mouse_stk_ok\n\tmov\t[BYTE PTR 0B000h:0h],'#'\n\n??mouse_stk_ok:\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov ax, [Mouse_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, ax\t\t\t       ; Get Syatem Stack Selector\n\tmov sp, [Mouse_App_Stack_ES]           ; Get Syatem Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\tret\n\tENDP\tMouse_Int\n\n\n\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VGA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVGA_Mouse_Shadow_Buffer C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\tpush\tbp\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tbp , cx\n??restore_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 10\nmov es, ax\nmov al , 'V'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tsi,di\t\t\t\t\t; xchg the source and the dest\n\tmov\tbp , cx\n\tpush\tes\t\t\t\t\t; need to swap es and ds but\n\tpush\tds\t\t\t\t\t;   cant xchg so pop them on the\n\tpop\tes\t\t\t\t\t;   stack and pop them off the\n\tpop\tds\t\t\t\t\t;   wrong way intentionally.\n??store_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,dx\t\t\t\t\t; move past right clipped pixels\n\tadd\tdi,bx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 12\nmov es, ax\nmov al , 'G'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tret\n\n\tENDP\tVGA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n\n\tGLOBAL\tC VGA_Draw_Mouse:FAR\n\tPROC\tVGA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tbx , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , bx\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tbx , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , bx\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 14\nmov es, ax\nmov al , 'A'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tret\nENDP\tVGA_Draw_Mouse\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VESA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVESA_Mouse_Shadow_Buffer C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\t\n\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??restore_loop:\n\tmov\tah,al\n??res_inner_loop:\n\tmov\tch , [si]\n\tmov\t[es:di],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??res_same_page\n\tcall\tnext_vesa_page\n ??res_same_page:\n \tdec\tah\n\tjnz\t??res_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??res_same_page1\n\tcall\tnext_vesa_page\n ??res_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 10\nmov es,ax\nmov al ,'v'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tjmp\t??out\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\tmov\tah,al\n??store_inner_loop:\n\tmov\tch , [es:di]\n\tmov\t[si],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??store_same_page\n\tcall\tnext_vesa_page\n ??store_same_page:\n \tdec\tah\n\tjnz\t??store_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??store_same_page1\n\tcall\tnext_vesa_page\n ??store_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_entry\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 14\nmov es,ax\nmov al ,'e'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\n\tmov\tdx , [ app_vesa_window ] \n\tcall\tset_vesa_window\n\tret\n\n\tENDP\tVESA_Mouse_Shadow_Buffer\n\n\n\n;***************************************************************************\n\n\tGLOBAL\tC VESA_Draw_Mouse:FAR\n\tPROC\tVESA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\tlocal\tapp_vesa_window : word\n\n   \n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tsi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tjnz\t??same_page\n\tcall\tnext_vesa_page\n ??same_page:\n \tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??same_page1\n\tcall\tnext_vesa_page\n ??same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 14\nmov es, ax\nmov al , 's'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nmov di , 10 * 80 + 16\nmov al , 'a'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tmov\tdx , [ app_vesa_window ] \n\tcall\tset_vesa_window\n\tret\n\n\nENDP\tVESA_Draw_Mouse\n\n\n\n;************************************************************************\n\nPROC\tget_vesa_window C near\nuses\tax,bx\n\tmov\tax , 04f05h\n\tmov\tbh , 1\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\t\n\n;************************************************************************\n\nPROC\tset_vesa_window C near\nuses\tax,bx,dx\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]  \t\n\tret\nENDP\t\n\n\n;***************************************************************************\n\nPROC\tset_vesa_page C near\nUSES\tax,bx,dx\n\n\tmov\tbx , dx\n\tshl\tbx , 2\n\tmov\t[ cs: current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tset_vesa_page\n\nPROC\tnext_vesa_page C near\nUSES\tax,bx,dx\n\tmov\tbx , [ cs: current_page ]\n\tadd\tbx , 4\n\tmov\t[ cs:current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n       \tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tnext_vesa_page\n\n\n\n;***********************************************************\nEND\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/X/KEYIREAL.IBN",
    "content": "\tDB  001h,000h,001h,000h,011h,000h,000h,000h,000h,000h,0FFh,000h,001h,0F0h,000h\n\tDB  010h,0A0h,000h,000h,000h,03Fh,001h,000h,000h,03Fh,001h,045h,000h,03Fh,001h\n\tDB  089h,000h,0A0h,000h,089h,000h,000h,000h,089h,000h,000h,000h,045h,000h,000h\n\tDB  000h,000h,000h,0A0h,000h,045h,000h,001h,002h,004h,008h,010h,020h,040h,080h\n\tDB  020h,002h,020h,003h,00Ch,006h,00Dh,007h,06Ah,006h,069h,006h,030h,002h,030h\n\tDB  003h,07Dh,000h,07Dh,001h,05Ah,002h,05Ah,003h,000h,002h,010h,004h,06Eh,004h\n\tDB  06Eh,002h,07Ch,000h,008h,000h,008h,000h,010h,000h,010h,000h,010h,000h,010h\n\tDB  000h,020h,000h,020h,000h,040h,000h,040h,000h,080h,000h,080h,000h,000h,001h\n\tDB  000h,004h,000h,004h,000h,004h,000h,001h,000h,000h,000h,000h,038h,01Dh,052h\n\tDB  053h,04Bh,047h,04Fh,048h,050h,049h,051h,04Dh,035h,01Ch,037h,046h,03Eh,040h\n\tDB  04Bh,04Ch,04Fh,050h,051h,053h,054h,055h,056h,059h,05Fh,06Ch,07Ch,000h,03Ch\n\tDB  03Ah,063h,068h,05Ch,05Bh,05Dh,060h,062h,065h,067h,066h,037h,02Bh,07Ch,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,07Fh,06Eh\n\tDB  002h,003h,004h,005h,006h,007h,008h,009h,00Ah,00Bh,00Ch,00Dh,00Fh,010h,011h\n\tDB  012h,013h,014h,015h,016h,017h,018h,019h,01Ah,01Bh,01Ch,02Bh,03Ah,01Fh,020h\n\tDB  021h,022h,023h,024h,025h,026h,027h,028h,029h,001h,02Ch,01Dh,02Eh,02Fh,030h\n\tDB  031h,032h,033h,034h,035h,036h,037h,039h,064h,03Ch,03Dh,01Eh,070h,071h,072h\n\tDB  073h,074h,075h,076h,077h,078h,079h,05Ah,07Dh,05Bh,060h,065h,069h,05Ch,061h\n\tDB  066h,06Ah,05Dh,062h,067h,063h,068h,07Fh,07Fh,07Fh,07Ah,07Bh,000h,000h,0FEh\n\tDB  087h,0FFh,0C0h,01Fh,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,038h,0EFh,001h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,01Eh,02Ch,039h,03Ah,03Ch,03Eh,040h,05Ah\n\tDB  080h,080h,080h,000h,000h,000h,000h,000h,0FFh,0FFh,0FFh,000h,0FFh,001h,000h\n\tDB  000h,000h,000h,000h,0FFh,000h,000h,000h,001h,000h,000h,000h,000h,001h,0FFh\n\tDB  001h,000h,001h,001h,008h,000h,002h,000h,008h,000h,006h,000h,004h,000h,003h\n\tDB  000h,008h,000h,005h,000h,008h,000h,008h,000h,008h,000h,008h,000h,000h,000h\n\tDB  001h,000h,008h,000h,007h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,029h,00Ah,002h,00Dh,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,0F1h\n\tDB  00Ch,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,001h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,0F4h\n\tDB  00Dh,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,0AEh,010h\n\tDB  05Ah,00Fh,05Fh,013h,0E6h,011h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,090h,000h,000h,000h,000h,0ADh,0DEh,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,0ADh,0DEh,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,0C8h,000h\n\tDB  000h,000h,051h,057h,006h,01Eh,08Ch,0C8h,08Eh,0D8h,08Eh,0C0h,08Bh,046h,006h\n\tDB  0F7h,006h,004h,000h,002h,000h,075h,013h,0B9h,010h,000h,0BFh,094h,000h,0F2h\n\tDB  0AEh,0E3h,009h,0BFh,0B4h,000h,04Fh,02Bh,0F9h,026h,08Ah,005h,01Fh,007h,05Fh\n\tDB  059h,0C9h,0CBh,0C8h,000h,000h,000h,056h,053h,01Eh,08Ch,0C8h,08Eh,0D8h,0A1h\n\tDB  0BAh,001h,08Bh,0F0h,005h,002h,000h,025h,0FFh,000h,039h,006h,0B6h,001h,074h\n\tDB  011h,08Bh,05Eh,006h,089h,09Ch,0B6h,000h,0A3h,0BAh,001h,033h,0C0h,01Fh,05Bh\n\tDB  05Eh,0C9h,0CBh,0B8h,001h,000h,01Fh,05Bh,05Eh,0C9h,0CBh,0C8h,004h,000h,000h\n\tDB  053h,051h,052h,057h,056h,01Eh,09Ch,0FAh,08Ch,0C8h,08Eh,0D8h,0A1h,0ABh,002h\n\tDB  0A3h,0AFh,002h,0A1h,0B1h,002h,0A3h,0B5h,002h,08Bh,046h,006h,00Bh,0C0h,075h\n\tDB  003h,0E9h,0F7h,001h,0F7h,006h,004h,000h,000h,010h,00Fh,084h,03Ah,001h,0F6h\n\tDB  0C4h,004h,00Fh,085h,033h,001h,0F7h,006h,004h,000h,000h,020h,074h,00Ch,03Ch\n\tDB  02Bh,074h,00Ch,03Ch,03Dh,074h,008h,03Ch,06Ch,074h,004h,03Ch,063h,075h,016h\n\tDB  0B0h,041h,080h,00Eh,0F6h,002h,001h,0F6h,0C4h,008h,00Fh,084h,00Ah,001h,080h\n\tDB  026h,0F6h,002h,0FEh,0E9h,002h,001h,03Ch,068h,075h,016h,0B0h,042h,080h,00Eh\n\tDB  0F6h,002h,002h,0F6h,0C4h,008h,00Fh,084h,0F0h,000h,080h,026h,0F6h,002h,0FDh\n\tDB  0E9h,0E8h,000h,0F6h,0C4h,008h,00Fh,085h,0E4h,000h,03Ch,061h,074h,01Eh,03Ch\n\tDB  05Bh,00Fh,082h,0DAh,000h,03Ch,067h,00Fh,087h,0D4h,000h,03Ch,05Dh,076h,00Eh\n\tDB  03Ch,065h,073h,00Ah,03Ch,060h,074h,006h,03Ch,062h,00Fh,085h,0C2h,000h,08Ah\n\tDB  0ECh,032h,0E4h,02Ch,05Bh,08Bh,0D8h,0D1h,0E3h,081h,0C3h,06Fh,002h,08Bh,007h\n\tDB  08Ah,0DCh,098h,093h,098h,093h,0F6h,0C5h,002h,075h,021h,0BAh,001h,000h,0F6h\n\tDB  0C5h,001h,074h,003h,083h,0C2h,003h,003h,0DAh,08Ah,09Fh,00Ah,000h,093h,098h\n\tDB  093h,087h,0DAh,003h,0D8h,08Ah,087h,00Ah,000h,098h,087h,0DAh,0EBh,034h,083h\n\tDB  0E3h,003h,025h,003h,000h,083h,0E3h,003h,025h,003h,000h,0D1h,0E3h,0D1h,0E3h\n\tDB  00Bh,0D8h,0D1h,0E3h,08Bh,09Fh,089h,002h,0D1h,0E3h,0D1h,0E3h,08Bh,087h,010h\n\tDB  000h,08Bh,09Fh,012h,000h,0A3h,0AFh,002h,089h,01Eh,0B5h,002h,0A1h,0AFh,002h\n\tDB  08Bh,01Eh,0B5h,002h,0EBh,02Fh,001h,006h,0AFh,002h,079h,005h,033h,0C0h,0A3h\n\tDB  0AFh,002h,001h,01Eh,0B5h,002h,079h,006h,033h,0DBh,089h,01Eh,0B5h,002h,0A1h\n\tDB  0AFh,002h,08Bh,01Eh,0B5h,002h,03Dh,03Fh,001h,07Eh,003h,0B8h,03Fh,001h,081h\n\tDB  0FBh,0C7h,000h,07Eh,003h,0BBh,0C7h,000h,0A3h,0AFh,002h,089h,01Eh,0B5h,002h\n\tDB  0A3h,0ABh,002h,089h,01Eh,0B1h,002h,083h,03Eh,0A9h,002h,000h,075h,008h,00Eh\n\tDB  0E8h,0A5h,003h,00Eh,0E8h,0D4h,003h,0B8h,02Dh,000h,089h,046h,006h,08Bh,036h\n\tDB  0BAh,001h,089h,076h,0FEh,08Bh,03Eh,0B6h,001h,050h,00Eh,0E8h,051h,0FEh,083h\n\tDB  0C4h,002h,00Bh,0C0h,075h,011h,08Bh,046h,006h,03Ch,02Dh,074h,00Dh,03Ch,041h\n\tDB  074h,009h,03Ch,042h,074h,005h,0EBh,029h,0E9h,080h,000h,0FFh,036h,0AFh,002h\n\tDB  00Eh,0E8h,02Eh,0FEh,083h,0C4h,002h,00Bh,0C0h,075h,0EEh,083h,046h,0FCh,002h\n\tDB  0FFh,036h,0B5h,002h,00Eh,0E8h,01Bh,0FEh,083h,0C4h,002h,00Bh,0C0h,075h,0DBh\n\tDB  083h,046h,0FCh,002h,0BBh,001h,001h,08Bh,046h,006h,03Ch,02Dh,074h,01Bh,03Ch\n\tDB  07Fh,074h,017h,0F6h,0C4h,008h,074h,016h,032h,0DBh,0F7h,006h,004h,000h,000h\n\tDB  008h,075h,00Ch,03Ch,041h,074h,008h,03Ch,042h,074h,004h,089h,036h,0BAh,001h\n\tDB  08Bh,0F8h,083h,0E7h,07Fh,0B1h,003h,0D3h,0EFh,08Ah,0C8h,080h,0E1h,007h,0D3h\n\tDB  0E3h,0F6h,0D7h,084h,09Dh,039h,002h,074h,00Ch,0F7h,006h,004h,000h,001h,000h\n\tDB  075h,004h,089h,036h,0BAh,001h,020h,0BDh,039h,002h,008h,09Dh,039h,002h,0B8h\n\tDB  001h,000h,0EBh,008h,08Bh,046h,0FEh,0A3h,0BAh,001h,033h,0C0h,09Dh,01Fh,05Eh\n\tDB  05Fh,05Ah,059h,05Bh,0C9h,0CBh,050h,053h,051h,057h,01Eh,052h,006h,056h,0FCh\n\tDB  08Ch,0C8h,08Eh,0D8h,08Ch,0D1h,089h,026h,08Ah,003h,089h,00Eh,08Ch,003h,0BAh\n\tDB  08Eh,005h,083h,0E2h,0FEh,0FAh,08Eh,0D0h,08Bh,0E2h,0FBh,083h,03Eh,0CEh,002h\n\tDB  000h,0C7h,006h,0CEh,002h,000h,000h,00Fh,085h,003h,002h,08Bh,016h,004h,000h\n\tDB  083h,026h,0BEh,001h,0FCh,0B8h,040h,000h,08Eh,0C0h,026h,0F6h,006h,017h,000h\n\tDB  040h,074h,005h,083h,00Eh,0BEh,001h,001h,026h,0F6h,006h,017h,000h,020h,074h\n\tDB  005h,083h,00Eh,0BEh,001h,002h,0C6h,006h,0B5h,000h,001h,026h,0F6h,006h,096h\n\tDB  000h,010h,075h,005h,0C6h,006h,0B5h,000h,000h,08Ch,0C8h,08Eh,0C0h,0FCh,032h\n\tDB  0E4h,0BBh,001h,001h,0E4h,060h,08Bh,01Eh,05Bh,002h,088h,087h,049h,002h,043h\n\tDB  083h,0E3h,00Fh,089h,01Eh,05Bh,002h,0BBh,001h,001h,03Ch,0E1h,075h,005h,0C6h\n\tDB  006h,05Eh,002h,003h,080h,03Eh,05Eh,002h,000h,074h,00Fh,0FEh,00Eh,05Eh,002h\n\tDB  0F7h,0C2h,080h,000h,00Fh,085h,08Eh,001h,0E9h,0CBh,001h,03Ch,0E0h,075h,008h\n\tDB  0C6h,006h,05Dh,002h,001h,0E9h,07Fh,001h,0A8h,080h,074h,007h,032h,0DBh,024h\n\tDB  07Fh,080h,0CCh,008h,080h,03Eh,05Dh,002h,000h,074h,023h,0C6h,006h,05Dh,002h\n\tDB  000h,0C6h,006h,0B7h,002h,001h,0BFh,084h,000h,0B9h,010h,000h,0F2h,0AEh,0E3h\n\tDB  002h,0EBh,003h,0E9h,094h,001h,08Ah,045h,00Fh,0C6h,006h,0B7h,002h,000h,0EBh\n\tDB  011h,03Ch,07Ah,075h,004h,0B0h,080h,0EBh,009h,08Bh,0F8h,083h,0E7h,07Fh,08Ah\n\tDB  085h,0C0h,001h,0F6h,006h,041h,002h,001h,075h,01Bh,0F6h,006h,040h,002h,004h\n\tDB  074h,017h,03Ch,05Ah,075h,010h,080h,03Eh,0B5h,000h,001h,074h,009h,0F7h,0C2h\n\tDB  080h,000h,075h,003h,0E9h,057h,001h,080h,0CCh,002h,0F6h,006h,040h,002h,050h\n\tDB  074h,003h,080h,0CCh,004h,050h,00Eh,0E8h,043h,0FCh,083h,0C4h,002h,0F6h,006h\n\tDB  03Eh,002h,010h,075h,007h,0F6h,006h,040h,002h,002h,074h,003h,080h,0CCh,001h\n\tDB  08Bh,0F8h,083h,0E7h,07Fh,0D1h,0EFh,0D1h,0EFh,0D1h,0EFh,08Bh,0D8h,083h,0E3h\n\tDB  07Fh,080h,0E3h,007h,08Ah,0AFh,034h,000h,0F7h,006h,0BEh,001h,001h,000h,074h\n\tDB  009h,084h,0ADh,019h,002h,074h,003h,080h,0F4h,001h,0F7h,006h,0BEh,001h,002h\n\tDB  000h,074h,009h,084h,0ADh,029h,002h,074h,003h,080h,0F4h,001h,088h,026h,06Ah\n\tDB  002h,0F7h,0C2h,000h,040h,074h,034h,066h,083h,03Eh,0EAh,002h,001h,075h,01Bh\n\tDB  03Dh,073h,000h,074h,00Ah,03Dh,076h,000h,072h,00Eh,03Dh,078h,000h,077h,009h\n\tDB  066h,0C7h,006h,0EAh,002h,000h,000h,000h,000h,0E9h,08Bh,000h,03Dh,07Dh,000h\n\tDB  075h,00Ch,066h,0C7h,006h,0EAh,002h,001h,000h,000h,000h,0E9h,0BAh,000h,03Dh\n\tDB  068h,006h,074h,075h,03Dh,04Ch,006h,074h,070h,03Dh,030h,002h,074h,005h,03Dh\n\tDB  07Eh,002h,075h,006h,0C7h,006h,008h,000h,001h,000h,03Dh,020h,004h,075h,00Ch\n\tDB  050h,0A1h,000h,000h,035h,001h,000h,050h,083h,0C4h,002h,058h,03Dh,034h,004h\n\tDB  075h,00Ch,050h,0A1h,002h,000h,035h,001h,000h,050h,083h,0C4h,002h,058h,050h\n\tDB  00Eh,0E8h,0DEh,0FBh,058h,03Ch,06Eh,075h,00Dh,083h,03Eh,082h,000h,000h,074h\n\tDB  006h,050h,0FFh,01Eh,080h,000h,058h,0BFh,05Fh,002h,0B9h,00Ah,000h,0F2h,0AEh\n\tDB  00Bh,0C9h,075h,01Bh,0BFh,03Ch,000h,0B9h,022h,000h,0D1h,0E9h,0F2h,0AFh,0E3h\n\tDB  009h,08Bh,05Dh,020h,023h,0DAh,074h,002h,0EBh,006h,0F7h,0C2h,004h,000h,074h\n\tDB  040h,02Eh,0FFh,006h,059h,002h,081h,03Eh,08Eh,003h,0ADh,0DEh,074h,017h,051h\n\tDB  057h,050h,006h,0B8h,000h,0A0h,08Eh,0C0h,033h,0FFh,0B9h,000h,0FAh,0B8h,001h\n\tDB  000h,0F3h,0AAh,007h,058h,05Fh,059h,0FAh,08Bh,016h,08Ch,003h,08Eh,0D2h,08Bh\n\tDB  026h,08Ah,003h,0FBh,0BAh,0E8h,00Ch,09Ch,00Eh,052h,09Ch,0FFh,036h,0BCh,002h\n\tDB  0FFh,036h,0BAh,002h,0CFh,0E4h,061h,08Ah,0E0h,00Ch,080h,0E6h,061h,086h,0E0h\n\tDB  0E6h,061h,0B8h,040h,000h,08Eh,0C0h,026h,0A0h,096h,000h,024h,0FDh,026h,0A2h\n\tDB  096h,000h,0B0h,020h,0E6h,020h,081h,03Eh,08Eh,003h,0ADh,0DEh,074h,017h,051h\n\tDB  057h,050h,006h,0B8h,000h,0A0h,08Eh,0C0h,033h,0FFh,0B9h,000h,0FAh,0B8h,001h\n\tDB  000h,0F3h,0AAh,007h,058h,05Fh,059h,08Bh,016h,08Ch,003h,0FAh,08Eh,0D2h,08Bh\n\tDB  026h,08Ah,003h,0FBh,05Eh,007h,05Ah,01Fh,05Fh,059h,05Bh,058h,0CFh,09Ch,050h\n\tDB  006h,0B8h,000h,0B0h,08Eh,0C0h,026h,0FEh,006h,000h,000h,007h,058h,09Dh,0CFh\n\tDB  09Ch,00Eh,0E8h,022h,0FDh,0CBh,050h,053h,051h,052h,01Eh,08Ch,0C8h,08Eh,0D8h\n\tDB  080h,03Eh,0F7h,002h,000h,075h,01Dh,083h,03Eh,003h,003h,000h,075h,00Ch,0B8h\n\tDB  000h,000h,050h,00Eh,0FFh,016h,051h,003h,083h,0C4h,002h,083h,006h,003h,003h\n\tDB  001h,083h,016h,003h,003h,000h,01Fh,05Ah,059h,05Bh,058h,0CBh,0C8h,004h,000h\n\tDB  000h,050h,053h,051h,052h,056h,057h,01Eh,006h,08Ch,0C8h,08Eh,0D8h,080h,03Eh\n\tDB  0F7h,002h,000h,075h,050h,083h,03Eh,003h,003h,000h,074h,049h,0FFh,00Eh,003h\n\tDB  003h,083h,03Eh,003h,003h,000h,075h,03Eh,08Bh,00Eh,03Fh,003h,08Bh,016h,043h\n\tDB  003h,0A1h,0ABh,002h,089h,046h,0FEh,08Bh,01Eh,0B1h,002h,089h,05Eh,0FCh,0A3h\n\tDB  02Fh,003h,089h,01Eh,033h,003h,089h,00Eh,037h,003h,089h,016h,03Bh,003h,0B8h\n\tDB  001h,000h,050h,00Eh,0FFh,016h,051h,003h,083h,0C4h,002h,0FFh,076h,0FCh,0FFh\n\tDB  076h,0FEh,00Eh,0FFh,016h,053h,003h,083h,0C4h,004h,007h,01Fh,05Fh,05Eh,05Ah\n\tDB  059h,05Bh,058h,0C9h,0CBh,0C8h,002h,000h,000h,053h,08Ch,0C8h,08Eh,0D8h,0C7h\n\tDB  046h,0FEh,02Dh,000h,08Bh,05Eh,006h,08Bh,0C3h,032h,01Eh,0F6h,002h,074h,029h\n\tDB  0A2h,0F6h,002h,0F6h,0C3h,002h,074h,00Eh,0C7h,046h,0FEh,042h,000h,0A8h,002h\n\tDB  075h,005h,081h,04Eh,0FEh,000h,008h,0F6h,0C3h,001h,074h,00Eh,0C7h,046h,0FEh\n\tDB  041h,000h,0A8h,001h,075h,005h,081h,04Eh,0FEh,000h,008h,08Bh,046h,0FEh,05Bh\n\tDB  0C9h,0CBh,0C8h,004h,000h,000h,050h,053h,051h,052h,01Eh,056h,006h,057h,02Eh\n\tDB  089h,01Eh,090h,005h,02Eh,0A3h,092h,005h,08Ch,0C8h,08Eh,0D8h,08Ch,0D3h,089h\n\tDB  026h,094h,005h,089h,01Eh,096h,005h,0BBh,098h,007h,083h,0E3h,0FEh,0FAh,08Eh\n\tDB  0D0h,08Bh,0E3h,0FBh,080h,03Eh,0F7h,002h,000h,00Fh,085h,0FAh,000h,080h,03Eh\n\tDB  0F8h,002h,000h,00Fh,084h,0F1h,000h,0A1h,092h,005h,025h,01Eh,000h,075h,009h\n\tDB  083h,03Eh,0A9h,002h,000h,00Fh,085h,0E0h,000h,083h,03Eh,0F9h,002h,001h,075h\n\tDB  002h,0D1h,0E9h,03Bh,00Eh,049h,003h,072h,005h,08Bh,00Eh,049h,003h,049h,03Bh\n\tDB  016h,04Dh,003h,072h,005h,08Bh,016h,04Dh,003h,04Ah,089h,00Eh,0ABh,002h,089h\n\tDB  016h,0B1h,002h,066h,0F7h,006h,004h,000h,000h,010h,000h,000h,075h,013h,0FFh\n\tDB  036h,090h,005h,00Eh,0E8h,02Ch,0FFh,083h,0C4h,002h,050h,00Eh,0E8h,07Bh,0F9h\n\tDB  083h,0C4h,002h,083h,03Eh,0A9h,002h,000h,00Fh,085h,092h,000h,083h,03Eh,0FBh\n\tDB  002h,000h,074h,019h,08Bh,0C1h,08Bh,0CAh,02Bh,006h,0FFh,002h,08Bh,01Eh,0FBh\n\tDB  002h,099h,0F7h,0FBh,0F7h,0EBh,003h,006h,0FFh,002h,08Bh,0D1h,08Bh,0C8h,083h\n\tDB  03Eh,0FDh,002h,000h,074h,015h,08Bh,0C2h,02Bh,006h,001h,003h,08Bh,01Eh,0FDh\n\tDB  002h,099h,0F7h,0FBh,0F7h,0EBh,003h,006h,001h,003h,08Bh,0D0h,083h,03Eh,003h\n\tDB  003h,000h,075h,047h,039h,00Eh,007h,003h,075h,006h,039h,016h,009h,003h,074h\n\tDB  03Bh,0A1h,00Bh,003h,025h,000h,0C0h,03Dh,000h,0C0h,074h,00Ch,00Eh,0E8h,016h\n\tDB  0FEh,0F7h,006h,00Bh,003h,000h,080h,074h,020h,03Bh,00Eh,00Dh,003h,072h,01Ah\n\tDB  03Bh,00Eh,015h,003h,077h,014h,03Bh,016h,011h,003h,072h,00Eh,03Bh,016h,019h\n\tDB  003h,077h,008h,081h,00Eh,00Bh,003h,000h,040h,0EBh,004h,00Eh,0E8h,01Dh,0FEh\n\tDB  089h,00Eh,007h,003h,089h,016h,009h,003h,081h,03Eh,098h,005h,0ADh,0DEh,074h\n\tDB  017h,051h,057h,050h,006h,0B8h,000h,0A0h,08Eh,0C0h,033h,0FFh,0B9h,000h,0FAh\n\tDB  0B8h,001h,000h,0F3h,0AAh,007h,058h,05Fh,059h,0A1h,096h,005h,0FAh,08Eh,0D0h\n\tDB  08Bh,026h,094h,005h,0FBh,05Fh,007h,05Eh,01Fh,05Ah,059h,05Bh,058h,0C9h,0CBh\n\tDB  0C8h,00Ch,000h,000h,050h,053h,051h,052h,057h,056h,01Eh,006h,08Ch,0C8h,08Eh\n\tDB  0D8h,0FCh,0A1h,02Fh,003h,08Bh,01Eh,033h,003h,02Bh,006h,027h,003h,02Bh,01Eh\n\tDB  02Bh,003h,089h,046h,0FEh,089h,05Eh,0FCh,003h,006h,037h,003h,003h,01Eh,03Bh\n\tDB  003h,089h,046h,0FAh,089h,05Eh,0F8h,0C7h,046h,0F6h,000h,000h,0A1h,023h,003h\n\tDB  089h,046h,0F4h,033h,0C0h,033h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,003h,0C9h\n\tDB  013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,02Bh,00Eh,049h\n\tDB  003h,02Bh,01Eh,049h,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h\n\tDB  08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh\n\tDB  04Eh,0FCh,08Bh,05Eh,0F8h,02Bh,00Eh,04Dh,003h,02Bh,01Eh,04Dh,003h,049h,04Bh\n\tDB  003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,034h,005h,080h,0F2h,005h,08Ah,0E0h\n\tDB  084h,0D0h,00Fh,085h,0AEh,000h,00Ah,0C2h,074h,040h,0F6h,0C4h,008h,074h,00Dh\n\tDB  08Bh,05Eh,0FEh,0F7h,0DBh,089h,05Eh,0F6h,0C7h,046h,0FEh,000h,000h,0F6h,0C4h\n\tDB  002h,074h,013h,052h,08Bh,046h,0FCh,0F7h,0D8h,0F7h,026h,037h,003h,001h,046h\n\tDB  0F4h,0C7h,046h,0FCh,000h,000h,05Ah,0F6h,0C2h,004h,074h,006h,0A1h,049h,003h\n\tDB  089h,046h,0FAh,0F6h,0C2h,001h,074h,006h,0A1h,04Dh,003h,089h,046h,0F8h,0B8h\n\tDB  000h,0A0h,08Eh,0C0h,08Bh,046h,0FCh,0F7h,026h,049h,003h,08Bh,016h,049h,003h\n\tDB  08Bh,0F8h,003h,07Eh,0FEh,08Bh,01Eh,03Fh,003h,0C5h,036h,023h,003h,08Bh,076h\n\tDB  0F4h,003h,076h,0F6h,08Bh,046h,0FAh,08Bh,04Eh,0F8h,02Bh,046h,0FEh,07Eh,03Ch\n\tDB  02Bh,04Eh,0FCh,07Eh,037h,02Bh,0D0h,02Bh,0D8h,055h,083h,07Eh,006h,000h,075h\n\tDB  018h,08Bh,0E9h,08Bh,0C8h,0F3h,0A4h,003h,0F3h,003h,0FAh,04Dh,075h,0F5h,05Dh\n\tDB  007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,087h,0F7h,08Bh,0E9h,006h\n\tDB  01Eh,007h,01Fh,08Bh,0C8h,0F3h,0A4h,003h,0F2h,003h,0FBh,04Dh,075h,0F5h,05Dh\n\tDB  007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,0C8h,00Ch,000h,000h,050h\n\tDB  053h,051h,052h,057h,056h,01Eh,006h,08Ch,0C8h,08Eh,0D8h,08Bh,046h,006h,08Bh\n\tDB  05Eh,008h,02Bh,006h,027h,003h,02Bh,01Eh,02Bh,003h,089h,046h,0FEh,089h,05Eh\n\tDB  0FCh,003h,006h,03Fh,003h,003h,01Eh,043h,003h,089h,046h,0FAh,089h,05Eh,0F8h\n\tDB  0C7h,046h,0F6h,000h,000h,0C4h,006h,01Dh,003h,089h,046h,0F4h,033h,0C0h,033h\n\tDB  0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h\n\tDB  08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,02Bh,00Eh,049h,003h,02Bh,01Eh,049h,003h,049h\n\tDB  04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h\n\tDB  003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,02Bh\n\tDB  00Eh,04Dh,003h,02Bh,01Eh,04Dh,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh\n\tDB  013h,0D2h,034h,005h,080h,0F2h,005h,08Ah,0E0h,084h,0D0h,00Fh,085h,093h,000h\n\tDB  00Ah,0C2h,074h,042h,0F6h,0C4h,008h,074h,00Dh,08Bh,05Eh,0FEh,0F7h,0DBh,089h\n\tDB  05Eh,0F6h,0C7h,046h,0FEh,000h,000h,0F6h,0C4h,002h,074h,013h,052h,08Bh,046h\n\tDB  0FCh,0F7h,0D8h,0F7h,026h,03Fh,003h,001h,046h,0F4h,0C7h,046h,0FCh,000h,000h\n\tDB  05Ah,0F6h,0C2h,004h,074h,007h,08Bh,01Eh,049h,003h,089h,05Eh,0FAh,0F6h,0C2h\n\tDB  001h,074h,007h,08Bh,01Eh,04Dh,003h,089h,05Eh,0F8h,08Bh,046h,0FCh,0F7h,026h\n\tDB  049h,003h,08Bh,016h,049h,003h,08Bh,0F8h,003h,07Eh,0FEh,08Bh,01Eh,03Fh,003h\n\tDB  08Bh,076h,0F4h,003h,076h,0F6h,0B8h,000h,0A0h,08Eh,0D8h,08Bh,046h,0FAh,08Bh\n\tDB  04Eh,0F8h,02Bh,046h,0FEh,07Eh,023h,02Bh,04Eh,0FCh,07Eh,01Eh,02Bh,0D0h,02Bh\n\tDB  0D8h,08Ah,0E0h,026h,08Ah,02Ch,066h,046h,00Ah,0EDh,074h,002h,088h,02Dh,047h\n\tDB  0FEh,0CCh,075h,0F0h,003h,0F3h,003h,0FAh,0FEh,0C9h,075h,0E6h,007h,01Fh,05Eh\n\tDB  05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,0C8h,00Ch,000h,000h,050h,053h,051h,052h\n\tDB  057h,056h,01Eh,006h,08Ch,0C8h,08Eh,0D8h,0E8h,0B7h,002h,089h,056h,0F2h,0FCh\n\tDB  0A1h,02Fh,003h,08Bh,01Eh,033h,003h,02Bh,006h,027h,003h,02Bh,01Eh,02Bh,003h\n\tDB  089h,046h,0FEh,089h,05Eh,0FCh,003h,006h,037h,003h,003h,01Eh,03Bh,003h,089h\n\tDB  046h,0FAh,089h,05Eh,0F8h,0C7h,046h,0F6h,000h,000h,0A1h,023h,003h,089h,046h\n\tDB  0F4h,033h,0C0h,033h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,003h,0C9h,013h,0C0h\n\tDB  003h,0DBh,013h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,02Bh,00Eh,049h,003h,02Bh\n\tDB  01Eh,049h,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh\n\tDB  0FCh,08Bh,05Eh,0F8h,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FCh\n\tDB  08Bh,05Eh,0F8h,02Bh,00Eh,04Dh,003h,02Bh,01Eh,04Dh,003h,049h,04Bh,003h,0C9h\n\tDB  013h,0C0h,003h,0DBh,013h,0D2h,034h,005h,080h,0F2h,005h,08Ah,0E0h,084h,0D0h\n\tDB  00Fh,085h,0C7h,000h,00Ah,0C2h,074h,040h,0F6h,0C4h,008h,074h,00Dh,08Bh,05Eh\n\tDB  0FEh,0F7h,0DBh,089h,05Eh,0F6h,0C7h,046h,0FEh,000h,000h,0F6h,0C4h,002h,074h\n\tDB  013h,052h,08Bh,046h,0FCh,0F7h,0D8h,0F7h,026h,037h,003h,001h,046h,0F4h,0C7h\n\tDB  046h,0FCh,000h,000h,05Ah,0F6h,0C2h,004h,074h,006h,0A1h,049h,003h,089h,046h\n\tDB  0FAh,0F6h,0C2h,001h,074h,006h,0A1h,04Dh,003h,089h,046h,0F8h,0B8h,000h,0A0h\n\tDB  08Eh,0C0h,08Bh,046h,0FCh,0F7h,026h,049h,003h,003h,046h,0FEh,083h,0D2h,000h\n\tDB  08Bh,0F8h,0E8h,0F1h,001h,08Bh,016h,049h,003h,08Bh,01Eh,03Fh,003h,0C5h,036h\n\tDB  023h,003h,08Bh,076h,0F4h,003h,076h,0F6h,08Bh,046h,0FAh,08Bh,04Eh,0F8h,02Bh\n\tDB  046h,0FEh,07Eh,04Fh,02Bh,04Eh,0FCh,07Eh,04Ah,02Bh,0D0h,02Bh,0D8h,083h,07Eh\n\tDB  006h,000h,075h,021h,08Ah,0E0h,08Ah,02Ch,026h,088h,02Dh,046h,047h,075h,003h\n\tDB  0E8h,0D9h,001h,0FEh,0CCh,075h,0F0h,003h,0F3h,003h,0FAh,073h,003h,0E8h,0CCh\n\tDB  001h,0FEh,0C9h,075h,0E1h,0EBh,01Fh,08Ah,0E0h,026h,08Ah,02Dh,088h,02Ch,046h\n\tDB  047h,075h,003h,0E8h,0B8h,001h,0FEh,0CCh,075h,0F0h,003h,0F3h,003h,0FAh,073h\n\tDB  003h,0E8h,0ABh,001h,0FEh,0C9h,075h,0E1h,08Bh,056h,0F2h,0E8h,06Ch,001h,007h\n\tDB  01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,0C8h,00Eh,000h,000h,050h,053h\n\tDB  051h,052h,057h,056h,01Eh,006h,08Ch,0C8h,08Eh,0D8h,0E8h,03Eh,001h,089h,056h\n\tDB  0F2h,08Bh,046h,006h,08Bh,05Eh,008h,02Bh,006h,027h,003h,02Bh,01Eh,02Bh,003h\n\tDB  089h,046h,0FEh,089h,05Eh,0FCh,003h,006h,03Fh,003h,003h,01Eh,043h,003h,089h\n\tDB  046h,0FAh,089h,05Eh,0F8h,0C7h,046h,0F6h,000h,000h,0C4h,006h,01Dh,003h,089h\n\tDB  046h,0F4h,033h,0C0h,033h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,003h,0C9h,013h\n\tDB  0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,02Bh,00Eh,049h,003h\n\tDB  02Bh,01Eh,049h,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh\n\tDB  04Eh,0FCh,08Bh,05Eh,0F8h,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh\n\tDB  0FCh,08Bh,05Eh,0F8h,02Bh,00Eh,04Dh,003h,02Bh,01Eh,04Dh,003h,049h,04Bh,003h\n\tDB  0C9h,013h,0C0h,003h,0DBh,013h,0D2h,034h,005h,080h,0F2h,005h,08Ah,0E0h,084h\n\tDB  0D0h,00Fh,085h,0A0h,000h,00Ah,0C2h,074h,040h,0F6h,0C4h,008h,074h,00Dh,08Bh\n\tDB  05Eh,0FEh,0F7h,0DBh,089h,05Eh,0F6h,0C7h,046h,0FEh,000h,000h,0F6h,0C4h,002h\n\tDB  074h,013h,052h,08Bh,046h,0FCh,0F7h,0D8h,0F7h,026h,03Fh,003h,001h,046h,0F4h\n\tDB  0C7h,046h,0FCh,000h,000h,05Ah,0F6h,0C2h,004h,074h,006h,0A1h,049h,003h,089h\n\tDB  046h,0FAh,0F6h,0C2h,001h,074h,006h,0A1h,04Dh,003h,089h,046h,0F8h,08Bh,046h\n\tDB  0FCh,0F7h,026h,049h,003h,003h,046h,0FEh,083h,0D2h,000h,08Bh,0F8h,0E8h,07Eh\n\tDB  000h,08Bh,016h,049h,003h,08Bh,01Eh,03Fh,003h,08Bh,076h,0F4h,003h,076h,0F6h\n\tDB  0B8h,000h,0A0h,08Eh,0D8h,08Bh,046h,0FAh,08Bh,04Eh,0F8h,02Bh,046h,0FEh,07Eh\n\tDB  02Ch,02Bh,04Eh,0FCh,07Eh,027h,02Bh,0D0h,02Bh,0D8h,08Ah,0E0h,026h,08Ah,02Ch\n\tDB  046h,00Ah,0EDh,074h,002h,088h,02Dh,047h,075h,003h,0E8h,067h,000h,0FEh,0CCh\n\tDB  075h,0ECh,003h,0F3h,003h,0FAh,073h,003h,0E8h,05Ah,000h,0FEh,0C9h,075h,0DDh\n\tDB  08Bh,056h,0F2h,0E8h,01Bh,000h,007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h\n\tDB  0CBh,050h,053h,0B8h,005h,04Fh,0B7h,001h,0B3h,000h,02Eh,0FFh,01Eh,05Dh,003h\n\tDB  05Bh,058h,0C3h,050h,053h,052h,0B8h,005h,04Fh,0B7h,000h,0B3h,000h,02Eh,0FFh\n\tDB  01Eh,05Dh,003h,05Ah,05Bh,058h,0C3h,050h,053h,052h,08Bh,0DAh,0C1h,0E3h,002h\n\tDB  02Eh,089h,01Eh,09Ah,007h,02Eh,08Bh,097h,061h,003h,0B8h,005h,04Fh,0B7h,000h\n\tDB  0B3h,000h,02Eh,0FFh,01Eh,05Dh,003h,05Ah,05Bh,058h,0C3h,050h,053h,052h,02Eh\n\tDB  08Bh,01Eh,09Ah,007h,083h,0C3h,004h,02Eh,089h,01Eh,09Ah,007h,02Eh,08Bh,097h\n\tDB  061h,003h,0B8h,005h,04Fh,0B7h,000h,0B3h,000h,02Eh,0FFh,01Eh,05Dh,003h,05Ah\n\tDB  05Bh,058h,0C3h\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/X/KEYSTRUC.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : KEYSTRUC.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 13, 1994                            *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nSTRUC\tKeyboardType\n\tSoundOn\t\t\tDW\t?\t; toggled by alt S\n\tMusicOn\t\t\tDW\t?\t; toggled by alt M\n\tKeyFlags\t\t\tDD\t?\t; all but repeat for now\n\tBreak\t\t\t\tDW\t?\n\tKeyMouseMove\tDB\t6  DUP(?)\n\tScreenEdge\t\tDW\t18 DUP (?)\n\tBits\t\t\t\tDB\t8  DUP (?)\n\tCondPassKey\t\tDW\t17 DUP (?) \n\tCondPassCond\tDW\t17 DUP (?)\n\tEscRoutine\t\tDD\t?\n\tExtCodes\t\t\tDB\t16 DUP (?)\n\tExtNums\t\t\tDB\t16 DUP (?)\n\tExtRemap\t\t\tDB\t16 DUP (?)\n\tExtRemapEnd\t\tDB\t?\n\tExtKeyboard\t\tDB\t?\n\tKeyBuffer\t\tDW\t128 DUP(?) ; set to empty\n\tKeyBufferHead\tDD\t?\t; set to first entry\n\tKeyBufferTail\tDD\t?\t; set to head for empty buffer\n\tKeyLock\t\t\tDW\t?\t; num and caps lock bits\n\tKeyNums\t\t\tDB\t89 DUP (?)\n\tKeysCapsLock\tDB\t16 DUP (?)\n\tKeysNumLock\t\tDB\t16 DUP (?)\n\tKeysUpDown\t\tDB\t16 DUP (?)\n\tKeyStream\t\tDB\t16 DUP (?)\n\tPassCount\t\tDW\t?\n\tKeyStreamIndex\tDW\t?\n\tLastKeyE0\t\tDB\t?\n\tLastKeyE1\t\tDB\t?\n\tPassAlways\t\tDB\t10 DUP (?)\n\tPassAlwaysEnd\tDB\t?\t\t; invalid code to END PassAlways\n\tCtrlFlags\t\tDB\t?\n\tBuffer\t\t\tDW\t?\n\tTime\t\t\t\tDW\t?\n\tXYAdjust\t\t\tDB\t26 DUP (?)\n\tEdgeConv\t\t\tDW\t16 DUP (?)\n\tMouseUpdate\t\tDW\t?\n\tMouseX\t\t\tDD\t?\n\tLocalMouseX\t\tDW\t?\n\tMouseY\t\t\tDD\t?\n\tLocalMouseY\t\tDW\t?\n\tIsExtKey\t\t\tDB\t?\n\tExtIndex\t\t\tDW\t?\n\n\tKeyOldRMI\t\t\tDD\t?\t; The origianl RM interrupt seg:off.\n\tKeyOldPMIOffset\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tKeyOldPMISelector\tDD\t?\t; The original PM interrupt segment.\n\n\tKeyCodeOffset\t\t\tDW\t?\t; Offset of the code in the RM stuff.\n\tCallKeyRMIntOffset\tDW\t?\t; Offset of function to call DOS timer interrupt.\n\tCallKeyRMIntAddr\t\tDD\t?\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedKeyInt\t\t\tDD\t?\t; did Protected mode pass this through?\n\n\tBrkOldRMI\t\t\t\tDD\t?\t; The origianl RM interrupt seg:off.\n\tBrkOldPMIOffset\t\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tBrkOldPMISelector\t\tDD\t?\t; The original PM interrupt segment.\n\n\tBrkCodeOffset\t\t\tDW\t?\t; Offset of the code in the RM stuff.\n\tCallBrkRMIntOffset\tDW\t?\t; Offset of function to call DOS timer interrupt.\n\tCallBrkRMIntAddr\t\tDD\t?\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedBrkInt\t\t\tDD\t?\t; did Protected mode pass this through?\n\tKeyIntDisabled\t\t\tDD\t?\n\n\tDbgOldPMIOffset\t\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tDbgOldPMISelector\t\tDD\t?\t; The original PM interrupt segment.\n\n\t;---------------------------------------------------------------------------\n\t; Begin definition of Mouse Specific Variables for real mode\n\t;---------------------------------------------------------------------------\n\tButton\t\t\t\tDB\t?\t; current value of the mouse button\n\tMDisabled\t\t\tDB\t?\t; Is the mouse driver disabled\n\tMInput\t\t\t\tDB\t?\t; Defaults to mouse input allowed.\n\tAdjust\t\t\t\tDW\t?\t; flag to adjust coordinates if necessary\n\tMouseStepX\t\t\tDW\t?\t; step values if the mouse moves at\n\tMouseStepY\t\t\tDW\t?\t;   more than one pixel at a time\n\tMouseOffsetX\t\tDW\t?\t; Fractional step values used if a mouse\n\tMouseOffsetY\t\tDW\t?\t;   moves at less than one pixel at a time\n\tMState\t\t\t\tDD\t?\t; Tracks if mouse is hidden (TRUE) or not (FALSE)\n\tMouseXOld     \t\tDW\t?\t; Holds last MouseX and MouseY to determine if \n\tMouseYOld     \t\tDW\t?\t;   mouse needs to be redrawn\n\tMCState\t\t\t\tDW\t?\t; Tracks if mouse conditional hidden (TRUE) or not\n\tMouseCXLeft\t\t\tDD\t?\t; Conditional hide mouse left x position\n\tMouseCYUpper\t\tDD\t?\t; Conditional hide mouse top y position\n\tMouseCXRight\t\tDD\t?\t; Conditional hide mouse right x position\n\tMouseCYLower\t\tDD\t?\t; Conditional hide mouse lower y position\n\tMouseCursor   \t\tDD\t?\t; Pointer to the mouse cursor to draw\n\tMouseCursorSize\tDW\t?\t; Size of mouse cursor draw area\n\tMouseBuffer   \t\tDD\t?\t; Pointer to buffer mouse is saved in\n\tMouseXHot     \t\tDD\t?\t; Offset to mouse's x hot spot\n\tMouseYHot     \t\tDD\t?\t; Offset to mouse's y hot spot\n\tMouseBuffX\t\t\tDD\t?\t; X position background was saved at\n\tMouseBuffY\t\t\tDD\t?\t; Y position background was saved at\n\tMouseBuffW\t\t\tDD\t?\t; Width of the region saved for mouse\n\tMouseBuffH\t\t\tDD\t?\t; Height of the region saved for mouse\n\tMouseWidth\t\t\tDD\t?\t; Mouse cursor theoretical width\n\tMouseHeight\t\t\tDD\t?\t; Mouse cursor theoretical height\n\tMouseCodeOffset\tDW\t?\t; Offset to the real mode code offset\n\tMouseRight\t\t\tDD\t?\t; Right hand side of the screen\n\tMouseBottom\t\t\tDD\t?\t; Bottom of the screen\n\n\n\tShadowPtr\t\t\tdw\t?\n\tDrawMousePtr \t\tdw\t?\n\n\tVGAMouseDraw\t\tdw\t?\n\tVGAMouseShadow\t\tdw\t?\n\n\tVESAMouseDraw\t\tdw\t?\n\tVESAMouseShadow\tdw\t?\n\n\tVesaPtr\t\t\t\tdd ?\t\n\tVesaBankTable\t   DD\t8 dup (?)\n\tAdjust_XPos\t\t\tdd ?\n\tAdjust_YPos\t\t\tdd ?\n\n\nENDS\n\n; InitFlags that are set to have a fully functional interrupt.\nIF_ALLOC_RM\t\t\tequ\t1\t\t; Allocation of RM was successful.\nIF_SET_VECTORS\t\tequ\t2\t\t; Vectors have been set.\nIF_LOCKED_PM_CODE\tequ\t4\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t8\t\t; Locked PM code for DPMI.\nIF_RATE_CHANGE\t\tequ\t10\t\t; Timer rate was changed.\nIF_FUNCTIONAL\t\tequ\t20\t\t; Timer is in and functional.\nIF_LOCKED_RM_CODE\tequ\t40\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/X/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 25, 1994                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = keyboard\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tkeyboard.obj\t&\n\tmouse.obj\t\t&\n\tpagfault.obj\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WWLIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# The keyboard object files is also dependant on an IBN file which is \n#   generated from KEYIREAL.ASM\n#---------------------------------------------------------------------------\nkeyireal.ibn: keyireal.obj\n\t%create\t$^*.rsp\n\t%append $^*.rsp $^&.obj\n\t%append $^*.rsp $^&.exe\n\t%append $^*.rsp $^&.map\n\ttlink @$^*.rsp\n        tdstrip keyireal.exe\n        ebn\tkeyireal.exe\n\nkeyireal.obj:\tkeyireal.asm\n\ttasm /zn /la /ml /m2 keyireal.asm\n\nkeyboard.obj: keyireal.ibn keyboard.asm\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/X/MOUSE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*\t\t\t\t  (Mouse Routines)\t\t\t   *\n;*                                                                         *\n;*                    File Name : MOUSE.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : August 26, 1994                          *\n;*                                                                         *\n;*                  Last Update : November 3, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Install_Mouse -- Initializes mouse driver and verifies mouse exists   *\n;*   Remove_Mouse -- uninstalls the mouse interrupt by disabling the call  *\n;*   Get_Mouse_X -- Returns the mouses x pixel position                    *\n;*   Get_Mouse_Y -- Returns the mouse's y pixel position                   *\n;*   Get_Mouse_Button -- Gets the values of the mouse button               *\n;*   Set_Mouse_Cursor -- Sets the shape to be used as the mouse.           *\n;*   Low_Hide_Mouse -- Low-level routine which hides the mouse\t\t   *\n;*   Low_Show_Mouse -- Low level routine which shows the mouse\t\t   *\n;*   Mouse_Shadow_Buffer -- Handles storing and restoring the mouse buffer *\n;*   Draw_Mouse -- Handles drawing the mouse cursor\t\t\t   *\n;*   Hide_Mouse -- Hides mouse cursor on screen if it was show             *\n;*   Show_Mouse -- Display mouse cursor on screen if it was hidden         *\n;*   Conditional_Hide_Mouse -- Hides mouse if its with given region        *\n;*   Conditional_Show_Mouse -- shows mouse if it was conditionally hidden  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\n;WARN\t\t\t\t; generate all warnings we can\n;JUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keystruc.inc\"\nINCLUDE \"shape.inc\"\ninclude \"svgaprim.inc\"\n\nDOS_SYS_CALL\t\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nRESTORE_VISIBLE_PAGE\tEQU\t0\nSTORE_VISIBLE_PAGE\tEQU\t1\nCONDHIDE\t\tEQU\t08000H\t\t; bit for testing conditional region\nCONDHIDDEN\t\tEQU\t04000H\t\t; bit for testing conditional hidden\n;---------------------------------------------------------------------------\n; Define any data which needs to be global...\n;---------------------------------------------------------------------------\n\nGLOBAL\tRealModePtr:DWORD\nGLOBAL\tMInstalled:DWORD\nGLOBAL\tMouseBuffer:DWORD\nGLOBAL\tLCW_Uncompress:NEAR\n\nGLOBAL\tGet_Shape_Uncomp_Size     :NEAR\nGLOBAL\tGet_Shape_Width      \t  :NEAR\nGLOBAL\tGet_Shape_Original_Height :NEAR\nGLOBAL  Size_Of_Region\t\t  :NEAR\nGLOBAL\t_ShapeBuffer\t\t  :DWORD\n\nGLOBAL  XRes\t: dword\nGLOBAL  YRes\t: dword\n\n\nGLOBAL\tVesaFunc : dword\nGLOBAL\tVesa_XRes : near\nGLOBAL\tVesa_YRes : near\n\n\n\n\n\nDPMI_INTR\tEQU\t31h\t\n\n\nSTRUC DPMI_REGS\n       _edi  dd ?\n       _esi  dd ?\t\n       _ebp  dd ?\t\n       \t     dd ?\n       _ebx  dd ?\t\n       _edx  dd ?\t\n       _ecx  dd ?\t\n       _eax  dd ?\t\n       Flags dw ?\n       _es   dw ?\n       _ds   dw ?\n       _fs   dw ?\n       _gs   dw ?\n       _ip   dw ?\n       _cs   dw ?\n       _sp   dw ?\n       _ss   dw ?\n       \t     dd ?\n\t     dd ?\n  nothing    dd ?\t\t\t\nENDS\n\n\n\n;---------------------------------------------------------------------------\n; Now lets handle any data in the data segment\n;---------------------------------------------------------------------------\n\tDATASEG\n\nRealInt\t\tDPMI_REGS <>\t; structure to call a real mode int\nMInstalled\tDD\t0\t\t; is the mouse installed?\nMouseCursor\tDD\t0\nMouseBuffer\tDD\t0\nBufferWidth\tDD\t0\nBufferHeight\tDD\t0\nBufferSize\tDD\t0\nPrevMousePtr\tDD\t0\nMouseBufferSel\tDD\t0\n\n\nDraw_Mouse\t\tdd\tVGA_Draw_Mouse\nMouse_Shadow_Buffer\tdd\tVGA_Mouse_Shadow_Buffer\n\n;---------------------------------------------------------------------------\n; Time to write some code\n;---------------------------------------------------------------------------\n\tCODESEG\n\n;***************************************************************************\n;* INSTALL_MOUSE -- Initializes mouse driver and verifies mouse connected  *\n;*                                                                         *\n;* First check the mouse interupt to see if the vector is pointing to zero *\n;* page.  If it is not then make sure it is not pointing to an IRET.  If   *\n;* not call the mouse reset to verify that the hardware is attached.\t   *\n;*                                                                         *\n;* INPUT:\tint mouse_max_width  - the max width of the mouse cursor   *\n;*\t\tint mouse_max_height - the max height of the mouse cursor  *\n;*\t\tint screen_width     - width of the physical screen\t   *\n;*\t\tint screen_height    - height of the physical screen\t   *\n;*                                                                         *\n;* OUTPUT:      TRUE is mouse driver is initialized, FALSE if unable to    *\n;*\t\tinitialize mouse driver.\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tint Install_Mouse(\tint mouse_max_width,\t\t   *\n;*\t\t\t\t\tint mouse_max_height,\t\t   *\n;*\t\t\t\t\tint screen_width,\t\t   *\n;*\t\t\t\t\tint screen_height);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/26/1994 PWG : Created.                                             *\n;*=========================================================================*\nGLOBAL\tInstall_Mouse:NEAR\nPROC\tInstall_Mouse C NEAR \n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\tmouse_max_width:DWORD\n\tARG\tmouse_max_height:DWORD\n\tARG\tscreen_width:DWORD\n\tARG\tscreen_height:DWORD\n\n\n\t;*=========================================================================*\n\t;* Initialize all of the general mouse variables\n\t;*=========================================================================*\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\ttest\tesi , esi\t\t\t; mouse driver should be install\n\tjz \t??exit\t\t\t\t; after keyboard interrup is install\n\tmov\teax , [ XRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseX],eax\t; set the mouses x coordinate to 160\n\tmov\teax , [ YRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseY],eax\t; set the mouses y coordinate to 100\n\tmov\t[(KeyboardType esi).MState],1\t; flag the mouse as hidden\n\tmov\t[(KeyboardType esi).MCState],0\t; turn off conditional region\n\tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi).MouseRight],eax\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi).MouseBottom],eax\n\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 0200, bl = number of interrupt to get\n\t; output cf error, cx,dx= address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,033h\t\t\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\t\t\t; no mouse driver present\n\n\t;*=========================================================================*\n\t;* If the interupt vector is pointing to 0000:0000h, there is no mouse\n\t;*=========================================================================*\n\tmov\tax,cx\n\tor\tax,dx\t\t\n\tjz\tshort ??nomouse\n\n\tand\tedx , 0ffffh\n\tand\tecx , 0ffffh\n\tshl\tecx,4\n\tadd\tecx,edx\n\n\t;*=========================================================================*\n\t;* If the first instruction is an IRET, there is no mouse\n\t;*=========================================================================*\n\n\tcmp\t[byte ptr ecx],0CFH\t; is this an IRET\n\tjne\tshort ??mouse_buff\t; if it isnt then reset the mouse\n\n??nomouse:\n\tmov\teax,FALSE\t\t\t\t; flag no mouse driver\n\tmov\t[MInstalled],FALSE\t\t\t; flag no mouse driver\n    \tjmp\t??exit\t\t\t\t\t; exit\n\n??mouse_buff:\n\t;*=========================================================================*\n\t;* Allocate two real mode memory buffers for the mouse cursor and the \n\t;*\tmouse shadow\n\t;*=========================================================================*\n\tmov\teax,[mouse_max_width]\t       \t; get the is max width\n\tmov\t[BufferWidth],eax\t       \t; save it off for set cursor\n\tmov\tedx,[mouse_max_height]\t       \t; get the max height\n\tmov\t[BufferHeight],edx\t       \t; save it off for set cursor\n\tmul\tedx\t\t\t       \t; size = max_width * max_height\n\tadd\teax,22\t\t\t       \t; add width/height(8) + para align(15)\n\tand\tal, 0f0h\t\t       \t; now size is even paragraphs\n\tmov\t[BufferSize],eax\t       \t; store off the buffer size\n\tshl\teax,1\t\t\t       \t; make two of them\n\n \tmov\tebx,eax\t\t\t\t; get size of RM binary.\n\tmov\tecx,eax\t\t\t\t; ecx will use it later.\n\tadd\tebx,15\t\t\t\t; round up \n\tshr\tebx,4\t\t\t\t; convert to pages.\n\tmov\teax,0100h\t\t\t; alloc real buffer\n\tint\tDPMI_INTR\t \t\t; do call.\n\tjc\t??error\t\t \t\t; check for error.\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tmov\t[MouseBufferSel], edx\n\tshl\teax , 16\n\tmov\t[(KeyboardType esi).MouseCursor],eax\t; store off the real mode segment\n\tmov\tedx,eax\t\t\t\t\t; get the buffer position\n\tadd\tedx,[BufferSize]\t\t\t; add in the buffer size\n\tmov\t[(KeyboardType esi).MouseBuffer],edx\t; store off the real mode segment\n\tshr\teax,12\t\t\t\t\t; convert the seg/off to 32 bit offset\n\tmov\tedx,eax\n\tadd\tedx,[BufferSize]\n\tmov\t[MouseCursor],eax\t\t\t; store it off in the mouse buffer\n\tmov\t[MouseBuffer],edx\t\t\t; store it off in the mouse buffer\n\n\tmov\teax,0600h\t\t\t\t; function number.\n\tmov\tecx,[MouseCursor]\t\t\t; ecx must have start of memory.\n\tmov\tedi,[BufferSize]\n\tshl\tedi,1\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n       \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n\n??begin:\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\t; Reset mouse thru int 33h funtion 0\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\txor\tecx , ecx\n\tmov\t[RealInt . _eax ] , 0\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\tmov\teax ,[RealInt . _eax]\n\tcmp\tax,-1\t\t\t\t\t; was the mouse attached to system\n      \tjne\t??nomouse\t\t\t\t; if not exit out of the routine\n\t\n\tmov\t[(KeyboardType esi).Adjust],0\t\t; assume we do not need to adjust mouse\n\n;***************************************************************************\n; Set the Vesa Parameters \n\n\tmov\teax , [ VesaFunc ]\n\ttest\teax , eax\n\tjz\t??set_vga_mouse\n\tmov\t[(KeyboardType esi). VesaPtr ] , eax\n\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VESA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VESA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n \tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi). MouseRight ] , eax\n\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi). MouseBottom ] , eax\n\n\tlea\tedi , [(KeyboardType esi). VesaBankTable]\n\tlea\tesi , [ BankTable ]\n\tmov\tecx , 8\n\trep\tmovsd\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tjmp\t??end_vesa\n\n??set_vga_mouse:\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VGA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VGA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n??end_vesa:\n\tcall \tReset_Mouse \n\tmov\teax , TRUE\n\tret\n\n??error:\n\tmov\teax,FALSE\n??exit:\n\tret\n\tENDP\tInstall_Mouse\n\n;***************************************************************************\n;* ResET_MOUSE -- Reset mouse to a new graphif mode\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* reset mouse driver funtions to a a currently graphic mode\t\t   *\t\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;* PROTO:\tReset_Mouse ( void ) \t\t\t\t\t   *\t\n;*\t\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/26/1994 JRJ : Created.                                             *\n;*=========================================================================*\nGLOBAL\tReset_Mouse:NEAR\nPROC\tReset_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\n\t;*=========================================================================*\n\t;* Initialize all of the general mouse variables\n\t;*=========================================================================*\n\tmov\tesi , [RealModePtr]\t\t; get offset of real mode data start\n\ttest\tesi , esi\n\tjz\t??exit\n\tmov\teax , [ XRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseX],eax\t; set the mouses x coordinate to 160\n\tmov\teax , [ YRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseY],eax\t; set the mouses y coordinate to 100\n\tmov\t[(KeyboardType esi).MState],1\t; flag the mouse as hidden\n\tmov\t[(KeyboardType esi).MCState],0\t; turn off conditional region\n\tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi).MouseRight],eax\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi).MouseBottom],eax\n\n\n\tmov\t[(KeyboardType esi).Adjust],0\t\t; assume we do not need to adjust mouse\n\n;***************************************************************************\n; Set the Vesa Parameters \n\n\tmov\teax , [ VesaFunc ]\n\ttest\teax , eax\n\tjz\t??set_vga_mouse\n\tmov\t[(KeyboardType esi). VesaPtr ] , eax\n\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VESA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VESA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n \tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi). MouseRight ] , eax\n\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi). MouseBottom ] , eax\n\n\tlea\tedi , [(KeyboardType esi). VesaBankTable]\n\tlea\tesi , [ BankTable ]\n\tmov\tecx , 8\n\trep\tmovsd\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tjmp\t??end_vesa\n\n??set_vga_mouse:\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VGA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VGA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n\n??end_vesa:\n       ; S Mickey/pixel Ratio cursor limits \n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 8\n\tmov\tedx , 16\n\tmov\t[RealInt . _eax ] , 0fh\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\t; Set Min/Max X pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 0\t \n\tmov\tedx , [ XRes ]\n\tcmp\tedx , 320\n\tjne\t??set_it\n\tshl\tedx , 1\n\tmov\t[(KeyboardType esi).Adjust],1\n\n??set_it:\n;\tdec\tedx\n\tmov\t[RealInt . _eax ] , 7\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\t; Set Min/Max Y pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 0\n\tmov\tedx , [ YRes ]\n\tdec\tedx\n\tmov\t[RealInt . _eax ] , 8\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\nIF 0\n\t; Check for scale factors in X and Y pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , [ XRes ]\n\tmov\tedx , [ YRes ]\n\tsub\tecx , 8\n\tsub  \tedx , 16\n\tmov\t[RealInt . _eax ] , 4\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\t; Read mouse position thru int 33 funtion 3\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\txor\tecx , ecx\n\tmov\t[RealInt . _eax ] , 3\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\tmov\tecx ,[RealInt . _ecx]\n\tmov\tedx ,[RealInt . _edx]\n\n      ; compute Scale values X Y for different vendor mouse driver if nessesary\n\tadd \tecx , 8\n\tadd\tedx , 16\n\tcmp\tecx , [ XRes ]\n\tmov\t[(KeyboardType esi).Adjust_XPos],0\n\tjz\t??No_scaleX\n\tmov\t[(KeyboardType esi).Adjust_XPos],ecx\n??No_scaleX:\n\tcmp\tedx , [ YRes ]\n\tmov\t[(KeyboardType esi).Adjust_YPos],0\n\tjz\t??No_scaleY\n\tmov\t[(KeyboardType esi).Adjust_YPos],edx\n??No_scaleY:\t\nENDIF\n\n\tmov\tecx, [ XRes ]\t\t\t\t; set the mouses x coordinate to 160\n\tmov\tedx, [ YRes ]\t\t\t\t; set the mouses x coordinate to 160\n\tcmp\t[(KeyboardType esi).Adjust],1\n\tje\t??no_ecx_shift\n\tshr\tecx , 1\n??no_ecx_shift:\n\tshr\tedx , 1\n\tmov\t[MInstalled],TRUE\t\t\t; set the fact that mouse is installed\n\tmov\t[(KeyboardType esi).MDisabled],TRUE\t; disable mouse until the overlay is loaded\n\n\t; Set new Mouse position any way\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\t[RealInt . _eax ] , 4\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\tcall\tClear_RM_regs\n\tmov\teax, 0300h\n\tmov\tebx ,33h\t\t\t\t; mouse is in 33h\n\tmov\tecx,0\t\t\t\t\t; any mouse condition generates int\n\tmov\tedx,[RealModePtr]\t\t\t; get real mode memory address\n\tshr\tedx,4\t\t\t\t\t; convert it to a segment\n\tmov\t[RealInt. _es],dx\t\t\t; store it in the real mode es\n\tmovzx\tedx,[(KeyboardType PTR esi).MouseCodeOffset] ; Get address of code\n\tmov\t[RealInt._edx],edx\t\t\t; set edx to offset of code\n\tmov\t[RealInt._eax],12\t\t\t; set eax to set interrupt routine\n\tmov\t[RealInt._ecx],31\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n??installed:\n\tmov\teax,TRUE  \t\t\t\t; return TRUE if all is well\n\tmov\t[(KeyboardType esi).MDisabled],FALSE\t; no 32 bit overlays installed\n\tje\t??exit\n\n??error:\n\tmov\teax,FALSE\n\n??exit:\n\tret\n\tENDP\tReset_Mouse\n\n\n\n;***************************************************************************\n;* REMOVE_MOUSE -- uninstalls the mouse interrupt by disabling the call\t   *\n;*                                                                         *\n;* This routine will uninstall the mouse interrupt.  It does this by\t   *\n;* simply disabling the call condition.  The interrupt itself is still\t   *\n;* present, just uncalled until dos removes it at program termination.\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Remove_Mouse(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tRemove_Mouse:NEAR\n\tPROC\tRemove_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\t\n\n\tcall\tClear_RM_regs\n\tcmp \t[MInstalled],FALSE\t; check to see if mouse installed\n\tje\t??exit\t\t\t; if not then no need to remove it\n\n\tmov\t[MInstalled],FALSE\t; Force to NOT-Installed.\n\n;;PWG\tcmp \t[_MSWIFTDevice],1\t; check to see if SWIFT device installed\n;;PWG\tje\tshort ??prevSWIFT\t\t; if so use previous SWIFT event handler\n\n\tmov\tebx , 033h\n\tmov\tedx,[RealModePtr]\t\t\t; get real mode memory address\n\ttest\tedx,edx\t\t\t\t\t; check that the memory block is valid\n\tjz\t??exit\n\n\tshr\tedx,4\t\t\t\t\t; convert it to a segment\n\tmov\t[RealInt._es],dx\t\t\t; store it in the real mode es\n\txor\tedx,edx\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\tmov\tdx,[(KeyboardType PTR esi).MouseCodeOffset] ; Get address of code\n\tmov\t[RealInt._edx],edx\t\t\t; set edx to offset of code\n\tmov\t[RealInt._eax],12\t\t\t; set eax to set interrupt routine\n\tmov\t[RealInt._ecx],0\n\tmov\tecx,0\t\t\t\t\t; no mouse condition generates an int\n\tmov\teax,0300h\n\tlea\tedi,[RealInt]\n\tint\tDPMI_INTR\n\n\tmov\teax,0601h\t\t\t\t; function number.\n\tmov\tecx,[MouseCursor]\t\t\t; ecx must have start of memory.\n\tmov\tedi,[BufferSize]\n\tshl\tedi,1\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n       \tint\tDPMI_INTR\t\t\t; do call.\n\n\n\t; Deallocate real memory buffer\n\tmov\tedx ,[MouseBufferSel]\n\ttest\tdx ,dx\n\tjz\t??exit\n\tmov\teax ,0101h\n\tint\tDPMI_INTR\n\n??exit:\n\tret\n\tENDP\tRemove_Mouse\n\n\n;***************************************************************************\n\nGLOBAL\tClear_RM_regs :NEAR\nPROC\tClear_RM_regs  NEAR \n\n\tpush\teax\n\tpush\tecx\n\tpush\tedi\n\tlea\tedi , [ RealInt ]\n\tlea\tecx , [ RealInt . nothing ]\n\tsub\tecx , edi\n\txor\teax , eax\n\tshr\tecx , 2\n\trep\tstosd\n\tpop\tedi\n\tpop\tecx\n\tpop\teax\n\tret\nENDP\tClear_RM_regs\n\n\n;***************************************************************************\n;* GET_MOUSE_X -- Returns the mouses x pixel position                      *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse x position in pixels\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_X(void);                                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_X:NEAR\n\tPROC\tGet_Mouse_X C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MouseX]\n\tret\n\n\tENDP\tGet_Mouse_X\n\n;***************************************************************************\n;* GET_MOUSE_STATE -- Returns the current mouse state\t\t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse's current state\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_State(void);                                 *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_State:NEAR\n\tPROC\tGet_Mouse_State C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MState]\n\tret\n\n\tENDP\tGet_Mouse_State\n\n;***************************************************************************\n;* GET_MOUSE_X -- Returns the mouses x pixel position                      *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse x position in pixels\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_X(void);                                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_Disabled:NEAR\n\tPROC\tGet_Mouse_Disabled C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmovzx\teax,[(KeyboardType esi).MDisabled]\n\tret\n\n\tENDP\tGet_Mouse_Disabled\n\t\t\t\t  \n;***************************************************************************\n;* GET_MOUSE_Y -- Returns the mouse's y pixel position                     *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:       none\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      int - the mouses y position in pixels                      *\n;*                                                                         *\n;* PROTO:\tint Get_Mouse_Y(void);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_Y:NEAR\n\tPROC\tGet_Mouse_Y C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MouseY]\n\tret\n\n\tENDP\tGet_Mouse_Y\n\n;***************************************************************************\n;* GET_MOUSE_BUTTON -- Gets the values of the mouse button                 *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_Button:NEAR\n\tPROC\tGet_Mouse_Button C NEAR \n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\n\txor\teax,eax\n\tmov\tal,[(KeyboardType esi).Button]\n\tret\n\n\tENDP\tGet_Mouse_Button\n\n;***************************************************************************\n;* SET_MOUSE_CURSOR -- Sets the shape to be used as the mouse.             *\n;*                                                                         *\n;*    This will inform the system of the shape desired as the mouse        *\n;*    cursor.                                                              *\n;*                                                                         *\n;* INPUT:    xhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           yhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           cursor      -- Shape to use as the new mouse shape.           *\n;*                                                                         *\n;* OUTPUT:   Returns with a pointer to the original mouse shape.           *\n;*                                                                         *\n;* PROTO:\tVOID  *Set_Mouse_Cursor(\tint  xhotspot, \t\t   *\n;*\t\t\t\t\t\tint  yhotspot, \t\t   *\n;*\t\t\t\t\t\tvoid *cursor);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   02/13/1992 JLB : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tSet_Mouse_Cursor:NEAR\n\tPROC\tSet_Mouse_Cursor C NEAR \n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\txhotspot:DWORD\t\t\t\t; the x hot spot of the mouse\n\tARG\tyhotspot:DWORD\t\t\t\t; the y hot spot of the mouse\n\tARG\tcursor:DWORD\t\t\t\t; ptr to the new mouse cursor\n\n\tLOCAL\tdatasize:DWORD\n\tLOCAL\tstype:WORD\n\tLOCAL\tswidth:DWORD\t\t; Shape width.\n\tLOCAL\tsheight:DWORD\t\t; Shape height.\n\tLOCAL\tssize:DWORD\t\t; Size of raw shape.\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\n\t;-------------------------------------------------------------------\n\t; Make sure the mouse is Enabled and Installed before continuing\n\t;-------------------------------------------------------------------\n\tmov\teax,[cursor]\n\tcmp\teax,0\t\t\t; if the mouse cursor is in zero page\n\tje\t??exit\t\t\t; it is completely invalid\n\n\tcmp\teax,[PrevMousePtr]\n\tje \t??exit\n\n\tcmp\t[(KeyboardType esi).MDisabled],FALSE\t; make sure the mouse is not disabled\n\tjne\t??exit\t\t\t; if it is not then give it a try\n\n\t;-------------------------------------------------------------------\n\t; We need to wait if a mouse interrupt is in progress.  Once the\n\t; interrupt is finished flag that it is occuring so that it will\n\t; not attempt to draw the mouse while we are changing the cursor.\n\t;-------------------------------------------------------------------\n??try:\n\tinc\t[(KeyboardType esi).MouseUpdate] ; flag that mouse can not be drawn\n\n\t;-------------------------------------------------------------------\n\t; If the mouse is currently on the screen hide it.\n\t;-------------------------------------------------------------------\n\tcall\tLow_Hide_Mouse\n\n\t;-------------------------------------------------------------------\n\t; Calculate the size of the buffer needed.\n\t;-------------------------------------------------------------------\n\tpush\t[cursor]\n\tcall\tGet_Shape_Uncomp_Size\n\tpop\tedx\n\tmov\t[datasize],eax\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Width\n\tpop\tedx\n\tmov\t[swidth],eax\n\tcmp\teax,[BufferWidth]\n\tjg\t??end\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Original_Height\n\tpop\tedx\n\tmov\t[sheight],eax\n\tcmp\teax,[BufferHeight]\n\tjg\t??end\n\n\n\tmov\tebx,[sheight]\n\tmov\teax,[swidth]\n\timul\tebx,eax\n\n??copy_mouse:\n\tmov\tesi,[cursor]\t\t\t; set esi to point to mouse shape\n\tmov\tax,[esi]\t\t\t; get the shape type byte\n\tmov\t[stype],ax\t\t\t; save off the shape type\n\ttest\tax,MAKESHAPE_NOCOMP\t\t; is it marked as no compression?\n\tje\t??comp_shape\t\t\t; if not go to the comped shape code\n\tmov\tedi,[MouseCursor]\t\t; set edi to point to mouse buffer\n??copy_type:\n\n\ttest\t[stype],MAKESHAPE_COMPACT\t; if the shape a 16 color shape?\n\tjne\t??16_color_copy\t\t\t; if it is then go handle it\n\n??normal_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed NORMAL shapes just get run-length uncompressed\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t\t; find size of shape in pixels\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes \n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??norm_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??norm_trans\t\t\t; if its a zero its transparent\n\tmov\t[edi],al\t\t\t; write out the pixel to dest\n\tinc\tedi\t\t\t\t; move to next dest position\n\tdec\tedx\t\t\t\t; we have now written another pix\n\tjnz\t??norm_unrle\t\t\t; if more to write then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are all done\n\n??norm_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\n\tjnz\t??norm_unrle\t\t\t; if more to do then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are done\n\n??16_color_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed 16 color shapes just get remaped and UN-RLE'd\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\tebx,esi\t\t\t\t; save of position of remap\n\tadd\tesi,16\t\t\t\t; move past remap table\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t; load up the height\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes \n\txor\teax,eax\t\t\t\t; clear high of lookup variable\n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??16_color_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??16_color_trans\t\t; if its a zero its transparent\n\tmov\tal,[ebx+eax]\t\t\t; remap the pixel from 16 color table\n\tmov\t[edi],al\t\t\t; store it out to the dest address\n\tinc\tedi\t\t\t\t; move to next dest address\n\tdec\tedx\t\t\t\t; we have now written a pixel\n\tjnz\t??16_color_unrle\n\tjmp\t??done_copy\n??16_color_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\t\t\t\t; subtract off count ahead of time\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\t\t\t\t; or edx to test for zero\n\tjnz\t??16_color_unrle\t\t\n\tjmp\t??done_copy\n\n\t;-------------------------------------------------------------------\n\t; Deal with the compressed shape by copying it into the shape\n\t;   staging buffer.\n\t;-------------------------------------------------------------------\n??comp_shape:\n\tmov\tedi,[_ShapeBuffer]\t; get a pointer to ShapeBuffer\n\tmov\tax,[esi]\t\t; load in the shape type\n\tadd\tesi,2\t\t\t; increment the shape pointer\n\tor\tax,MAKESHAPE_NOCOMP\t; make the shape as uncompressed\n\tmov\t[stype],ax\t\t; save off the shape type\n\tmov\t[edi],ax\t\t; write out uncompressed shape\n\tadd\tedi,2\n\n\t;-------------------------------------------------------------------\n\t; Process the shape header information and copy it over to the new\n\t;   location.\n\t;-------------------------------------------------------------------\n\tmov\tecx,4 \t\t\t; transfer height, width, org and\n\ttest\teax,MAKESHAPE_COMPACT\t; is it a 16 color shape?\n\tje\t??copy_head\t\t; no - don't worry about it\n\tadd\tecx,8\t\t\t; otherwise adjust ecx for header\n??copy_head:\n\trep\tmovsw\t\t\t; copy the necessary bytes\n\t\n\tmov \teax,[datasize]\t\t; get uncompressed length\n\tpush\teax\t\t\t; push as third param\n\tpush\tedi\t\t\t; push the destination offset\n\tpush\tesi\t\t\t; push the source offset\n\tcall\tLCW_Uncompress\t\t; do the uncompress\n\tpop\teax\n\tpop\teax\n\tpop\teax\n\tmov\tesi,[_ShapeBuffer]\n\tmov\tedi,[MouseCursor]\t\t; set edi to point to mouse buffer\n\tjmp\t??copy_type\n\n??done_copy:\n\tmov\tesi,[RealModePtr]\t; get offset of real mode data start\n\n\tmov\teax,[xhotspot]\t\t; get the mouse cursors x hotspot\n\tmov\t[(KeyboardType esi).MouseXHot],eax\n\tmov\teax,[yhotspot]\t\t; get the mouse cursors y hotspot\n\tmov\t[(KeyboardType esi).MouseYHot],eax\n\n\tmov\tebx,[sheight]\t\t; get shape height\n\tmov\t[(KeyboardType esi).MouseHeight],ebx\n\tmov\tebx,[swidth]\n\tmov\t[(KeyboardType esi).MouseWidth],ebx\n\n??error:\n\tcall\tLow_Show_Mouse\n\n\t;-------------------------------------------------------------------\n\t; Final cleanup and exit.\n\t;-------------------------------------------------------------------\n??end:\n\tdec\t[(KeyboardType esi).MouseUpdate]\t\t; we are done modifying the cursor\n??exit:\n\tpush\t[cursor]\n\tpush\t[PrevMousePtr]\n\tpop\teax\n\tpop\t[PrevMousePtr]\n\tret\t\t\t\t; and return back to the world\n\n\tENDP\tSet_Mouse_Cursor\n\n\n;***************************************************************************\n;* LOW_HIDE_MOUSE -- Low-level routine which hides the mouse\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Low_Hide_Mouse:NEAR\n\tPROC\tLow_Hide_Mouse C NEAR \n\tUSES\teax,ebx,esi\n\n\tmov\tebx,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\n\t;*=========================================================================*\n\t;* Is the mouse disabled or hidden?\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType ebx).MDisabled],0 \t; is the mouse disabled?\n\tjne\tshort ??end\n\n   \tcmp\t[(KeyboardType ebx).MState],0 \t; is the mouse hidden?\n\tjne\tshort ??endnodraw\t\t\t; no need to hide again\n\n\t;*=========================================================================*\n\t;* Take care of restoring the mouse cursor\n\t;*=========================================================================*\n\tmov\teax,RESTORE_VISIBLE_PAGE\n\tpush\teax\n\tcall\t[ Mouse_Shadow_Buffer]\n\tpop\teax\n\t;*=========================================================================*\n\t;* The mouse is now hidden -- again.\n\t;*=========================================================================*\n??endnodraw:\n\tadd\t[(KeyboardType ebx).MState],1\n\tadc\t[(KeyboardType ebx).MState],0\n\n??end:\n\tret\n\tENDP\tLow_Hide_Mouse\n\n;***************************************************************************\n;* LOW_SHOW_MOUSE -- Low level routine which shows the mouse\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Low_Show_Mouse:NEAR\n\tPROC\tLow_Show_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tLOCAL\tmousex:DWORD\n\tLOCAL\tmousey:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\n\t;*=========================================================================*\n\t;* Don't show the mouse if it is not hidden or it is disabled\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType esi).MDisabled],0\t; is the mouse disabled\n\tjne\t??exit\t\t\t\t\t; if so then exit\n\n\tcmp\t[(KeyboardType esi).MState],0\t; is the mouse already visible\n       \tje\t??exit\t\t\t\t\t; if so then exit\n\n\t;*=========================================================================*\n\t;* Don't show the mouse if it was hidden multiple times\n\t;*=========================================================================*\n\tdec\t[(KeyboardType esi).MState]\t\t; show the mouse one level\n\tcmp\t[(KeyboardType esi).MState],0\t; can the mouse be shown\n       \tjne\tshort ??exit\n\n\t;*=========================================================================*\n\t;* Determine the theoretcial drawing position of the mouse\n\t;*=========================================================================*\n\tmov\tecx,[(KeyboardType esi).MouseWidth]\t\t; Theoretical buffer width (pixel).\n\tmov\tedx,[(KeyboardType esi).MouseHeight]\t; Theoretical buffer height (pixel).\n\tmov\teax,[(KeyboardType esi).MouseX]\n\tmov\t[mousex],eax\t\t; Draw X pixel.\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\tmov\tebx,[(KeyboardType esi).MouseY]\n\tmov\t[mousey],ebx\t\t; Draw Y pixel.\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\t;*=========================================================================*\n\t;* Determine the theoretical coordinates and dimensions of the\n\t;*\tarea the mouse shape will be rendered upon.\n\t;*=========================================================================*\n\tmov\t[(KeyboardType esi).MouseBuffX],eax\n\tmov\t[(KeyboardType esi).MouseBuffY],ebx\n\tmov\t[(KeyboardType esi).MouseBuffW],ecx\n\tmov\t[(KeyboardType esi).MouseBuffH],edx\n\n;------\tMove the area that will be drawn upon, to the graphic buffer.\n\tmov\teax,STORE_VISIBLE_PAGE\n\tpush\teax\n\tcall\t[ Mouse_Shadow_Buffer ]\n\tpop\teax\n\n;------\tDraw the mouse shape to the seenpage.\n\tpush\t[mousey]\n\tpush\t[mousex]\n\tcall\t[ Draw_Mouse ]\n\tpop\teax\n\tpop\teax\n??exit:\n\tret\n\tENDP\tLow_Show_Mouse\n\n;***************************************************************************\n;* HIDE_MOUSE -- Hides mouse cursor on screen if it was show               *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Hide_Mouse(void);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tHide_Mouse:NEAR\n\tPROC\tHide_Mouse C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Mark us as updating the mouse and then run and do the update\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\t; were drawing the mouse\n\tcall\tLow_Hide_Mouse\t\t\t\t; make the function call\n\tdec\t[(KeyboardType esi).MouseUpdate]\t; were done drawing mouse\n\tret\n\t\n\tENDP\tHide_Mouse\n\n;----------------------------------------------------------------------------\n\n\n;***************************************************************************\n;* SHOW_MOUSE -- Display mouse cursor on screen if it was hidden           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Show_Mouse(void)                                      *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tShow_Mouse:NEAR\n\tPROC\tShow_Mouse C NEAR \n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Mark us as updating the mouse and then run and do the update\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\t; were drawing the mouse\n\tcall\tLow_Show_Mouse\t\t\t\t; make the function call\n\tdec\t[(KeyboardType esi).MouseUpdate]\t; were done drawing mouse\n\tret\n\tENDP\tShow_Mouse\n\n;***************************************************************************\n;* CONDITIONAL_HIDE_MOUSE -- Hides mouse if its with given region          *\n;*                                                                         *\n;* INPUT:\tint sx_pixel - the left-most pixel position of the region  *\n;*\t\tint sy_pixel - the upper-most pixel position of the region *\n;*\t\tint dx_pixel - the right most pixel position of the region *\n;*\t\tint dy_pixel - the lower most pixel position of the region *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Conditional_Hide_Mouse(\tint sx_pixel, \t\t   *\n;*\t\t\t\t\t\tint sy_pixel,\t\t   *\n;*\t\t\t\t\t\tint dx_pixel,\t\t   *\n;*\t\t\t\t\t\tint dy_pixel);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tConditional_Hide_Mouse:NEAR\n\tPROC\tConditional_Hide_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tARG\tsx_pixel:DWORD\t\t\t\t; left x pixel pos\n\tARG     sy_pixel:DWORD\t\t\t\t; upper y pixel pos\n\tARG\tdx_pixel:DWORD\t\t\t\t; right x pixel pos\n\tARG\tdy_pixel:DWORD\t\t\t\t; lower y pixel pos\n\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Widen region leftward by amount mouse shape spills to the right of\n\t;* its hot point.  Limited to the left edge of the screen.\n\t;*=========================================================================*\n\tmov\teax,[(KeyboardType esi).MouseWidth]\t\n\tsub\teax,[(KeyboardType esi).MouseXHot]\t\n\tneg\teax\t\t\t\t\t\n\tadd\teax,[sx_pixel]\n\tjns\tshort ??noleftlimit\n\txor\teax,eax\n??noleftlimit:\n\t;*=========================================================================*\n\t;* Widen region upward by amount mouse shape spills below the\n\t;* mouse's hot point.  Limited by the top edge of the screen.\n\t;*=========================================================================*\n\tmov\tebx,[(KeyboardType esi).MouseHeight]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\tneg\tebx\n\tadd\tebx,[sy_pixel]\n\tjns\tshort ??notoplimit\n\txor\tebx,ebx\n??notoplimit:\n\t;*=========================================================================*\n\t;* Widen region rightward by amount mouse shape spills to the\n\t;* left of its hot point.  Limited by the right edge of the\n\t;* screen.\n\t;*=========================================================================*\n\tmov\tecx,[dx_pixel]\n\tadd\tecx,[(KeyboardType esi).MouseXHot]\n\tcmp\tecx,[(KeyboardType esi).MouseRight]\n\tjb\tshort ??norightlimit\n\tmov\tecx,[(KeyboardType esi).MouseRight]\n\tdec\tecx\n??norightlimit:\n\t;*=========================================================================*\n\t;* Widen region downward by amout the mouse shape extends above\n\t;* its hot point.  Limited to the bottom of the screen.\n\t;*=========================================================================*\n\tmov\tedx,[dy_pixel]\n\tadd\tedx,[(KeyboardType esi).MouseYHot]\n\tcmp\tedx,[(KeyboardType esi).MouseBottom]\n\tjb\tshort ??nobottomlimit\n\tmov\tedx,[(KeyboardType esi).MouseBottom]\n\tdec\tedx\n\n??nobottomlimit:\n\tinc\t[(KeyboardType esi).MouseUpdate]\t\t; don't let interrupt scrag variables\n\n\t;*=========================================================================*\n\t;* The mouse could be in one of four conditions.\n\t;* 1) The mouse is visible and no conditional hide has been specified.\n\t;* \t(perform normal region checking with possible hide)\n\t;* 2) The mouse is hidden and no conditional hide as been specified.\n\t;* \t(record region and do nothing)\n\t;* 3) The mouse is visible and a conditional region has been specified\n\t;* \t(expand region and perform check with possible hide).\n\t;* 4) The mouse is already hidden by a previous conditional.\n\t;* \t(expand region and do nothing)\n\t;*\n\t;* First: Set or expand the region according to the specified parameters\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType esi).MCState],0\n\tjne\tshort ??expand\n\tmov\t[(KeyboardType esi).MouseCXLeft],eax\n\tmov\t[(KeyboardType esi).MouseCYUpper],ebx\n\tmov\t[(KeyboardType esi).MouseCXRight],ecx\n\tmov\t[(KeyboardType esi).MouseCYLower],edx\n\tjmp\t??noylower\n??expand:\n\n\t;*=========================================================================*\n\t;* Expand the clipping rectangle.\n\t;*=========================================================================*\n\tcmp\teax,[(KeyboardType esi).MouseCXLeft]\n\tjb\tshort ??noxleft\n\tmov\t[(KeyboardType esi).MouseCXLeft],eax\n??noxleft:\n\tcmp\tebx,[(KeyboardType esi).MouseCYUpper]\n\tjb\tshort ??noyupper\n\tmov\t[(KeyboardType esi).MouseCYUpper],ebx\n??noyupper:\n\tcmp\tecx,[(KeyboardType esi).MouseCXRight]\n\tja\tshort ??noxright\n\tmov\t[(KeyboardType esi).MouseCXRight],ecx\n??noxright:\n\tcmp\tedx,[(KeyboardType esi).MouseCYLower]\n\tja\tshort ??noylower\n\tmov\t[(KeyboardType esi).MouseCYLower],edx\n??noylower:\n\t;*=========================================================================*\n\t;* If the mouse isn't already hidden, then check its location against\n\t;* the hiding region and hide if necessary.\n\t;*=========================================================================*\n\ttest\t[(KeyboardType esi).MCState],CONDHIDDEN\n\tjne\tshort ??nohide\n\n\tmov\teax,[(KeyboardType esi).MouseX]\n\tmov\tebx,[(KeyboardType esi).MouseY]\n\tcmp\teax,[(KeyboardType esi).MouseCXLeft]\n\tjb\tshort ??nohide\n\tcmp\teax,[(KeyboardType esi).MouseCXRight]\n\tja\tshort ??nohide\n\tcmp\tebx,[(KeyboardType esi).MouseCYUpper]\n\tjb\tshort ??nohide\n\tcmp\tebx,[(KeyboardType esi).MouseCYLower]\n\tja\tshort ??nohide\n\n\t;*=========================================================================*\n\t;* The mouse falls within the region for hiding, so hide it.\n\t;*=========================================================================*\n\n\tcall\tLow_Hide_Mouse\t\t\t\t; make the function call\n\tor\t[(KeyboardType esi).MCState],CONDHIDDEN\n??nohide:\n\n\t;*=========================================================================*\n\t;* Record the fact that a Conditional_Hide_Mouse was\n\t;* called and then exit.\n\t;*=========================================================================*\n\tor\t[(KeyboardType esi).MCState],CONDHIDE\n\tadd\t[BYTE PTR (KeyboardType esi).MCState],1\n\tadc\t[BYTE PTR (KeyboardType esi).MCState],0\n\tdec\t[(KeyboardType esi).MouseUpdate]\n\tret\n\n\tENDP\tConditional_Hide_Mouse\n\n;***************************************************************************\n;* CONDITIONAL_SHOW_MOUSE -- shows mouse if it was conditionally hidden    *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Conditional_Show_Mouse(void);                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tConditional_Show_Mouse:NEAR\n\tPROC\tConditional_Show_Mouse C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]    ; get the real mode offset\n\n\t;*=========================================================================*\n\t; Notify the interrupt that we are updating the mouse\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\n\n\tmov\tax,[(KeyboardType esi).MCState]\n\tcmp\tal,0\n\tje\tshort ??exit\t\t\t; if no more nesting clear cond\n\n\t;*=========================================================================*\n\t;* Decrement the conditional hide counter.\n\t;*=========================================================================*\n\tdec\tal\n\n\t;*=========================================================================*\n\t;* If there are more conditional levels to undo, then just abort the show.\n\t;*=========================================================================*\n\tjne\tshort ??exit\n\n\t;*=========================================================================*\n\t;* Yup, the mouse should be show, but only if it was previously hidden.\n\t;*=========================================================================*\n\ttest\tax,CONDHIDDEN\t\t\t; was it hidden by interrupt??\n\tje\tshort ??exit1\t\t\t; or initial check for level 0\n\n\tcall\tLow_Show_Mouse\n\n??exit1:\n\tmov\tax,0\n\n??exit:\n\tmov\t[(KeyboardType esi).MCState],ax\n\tdec\t[(KeyboardType esi).MouseUpdate]\n\tret\n\tENDP\tConditional_Show_Mouse\n\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VGA_Mouse_Shadow_Buffer:NEAR\n\tPROC\tVGA_Mouse_Shadow_Buffer C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tstore:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\n\tmov\tesi,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[(KeyboardType esi).MouseBuffX]\n\tmov\tebx,[(KeyboardType esi).MouseBuffY]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseBuffW]\n\tadd\tebx,[(KeyboardType esi).MouseBuffH]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseBuffer ]\n\tmov\t[ buffy0 ] , eax\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseBuffW]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseBuffW]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\tpush\tebp\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tebp , ecx\n??restore_loop:\n\tmov\tecx,eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi,ebx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tesi,edi\t\t\t\t\t; xchg the source and the dest\n\tmov\tebp , ecx\n??store_loop:\n\tmov\tecx,eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi,edx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,ebx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n??out:\n\tret\n\tENDP\tVGA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n;* DRAW_MOUSE -- Handles drawing the mouse cursor\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tVGA_Draw_Mouse:NEAR\n\tPROC\tVGA_Draw_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tmousex:DWORD\n\tARG\tmousey:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\n\n\tmov\tesi,[RealModePtr]    \t; get 32 bit offset of dos data\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[mousex]\n\tmov\tebx,[mousey]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseWidth]\n\tadd\tebx,[(KeyboardType esi).MouseHeight]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , eax\n\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseWidth]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseWidth]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch ,[esi]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[edi],ch\n??inc_edi:\n\tinc\tedi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tesi,ebx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t\t\t\t; adjust dest to next line\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\tret\n\n\tENDP\tVGA_Draw_Mouse\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VESA_Mouse_Shadow_Buffer:NEAR\n\tPROC\tVESA_Mouse_Shadow_Buffer C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tstore:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\tlocal\tvesa_linear : dword\n\n\tmov\teax , [ cpu_video_page ]\n\tmov\t[ vesa_linear ] ,  eax\n\n\tmov\tesi,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[(KeyboardType esi).MouseBuffX]\n\tmov\tebx,[(KeyboardType esi).MouseBuffY]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseBuffW]\n\tadd\tebx,[(KeyboardType esi).MouseBuffH]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseBuffer ]\n\tmov\t[ buffy0 ] , eax\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseBuffW]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\tcall\tVesa_Asm_Set_Win\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseBuffW]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\n\tmov\t[ tempreg ] , ebx\n??restore__top_loop:\n\tmov\tah,al\n??restore__inner_loop:\n\tmov\tch ,[esi]\n\tmov\t[edi],ch\n\tinc\tesi\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??restore__in_range\n\tadd\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??restore__in_range:\n\tdec\tah\n\tjnz\t??restore__inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??restore__in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??restore__in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore__top_loop\t\t\t\t; if more to do, do it\n\tjmp\t??out\t\t\t\t\t; get the heck outta the routine\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\tmov\t[ tempreg ] , ebx\n??store_top_loop:\n\tmov\tah,al\n??store_inner_loop:\n\tmov\tch ,[edi]\n\tmov\t[esi],ch\n\tinc\tesi\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??store_in_range\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??store_in_range:\n\tdec\tah\n\tjnz\t??store_inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??store_in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??store_in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_top_loop\t\t\t\t; if more to do, do it\n\n??out:\n\tmov\tedi , [ vesa_linear ]\n\tadd\tedi , 0a0000h\n\tcall\tVesa_Asm_Set_Win\n\n\tret\n\tENDP\tVESA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n;* DRAW_MOUSE -- Handles drawing the mouse cursor\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tVESA_Draw_Mouse:NEAR\n\tPROC\tVESA_Draw_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tmousex:DWORD\n\tARG\tmousey:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\tlocal\ttempreg : dword\n\tlocal\tvesa_linear : dword\n\n\tmov\teax , [ cpu_video_page ]\n\tmov\t[ vesa_linear ] ,  eax\n\n\tmov\tesi,[RealModePtr]    \t; get 32 bit offset of dos data\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[mousex]\n\tmov\tebx,[mousey]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseWidth]\n\tadd\tebx,[(KeyboardType esi).MouseHeight]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , eax\n\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseWidth]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\tcall\tVesa_Asm_Set_Win\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseWidth]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\t[ tempreg ] , ebx\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch ,[esi]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[edi],ch\n??inc_edi:\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??in_range\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??in_range:\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n\n??out:\n\tmov\tedi , [ vesa_linear ]\n\tadd\tedi , 0a0000h\n\tcall\tVesa_Asm_Set_Win\n\n\tret\n\n\tENDP\tVESA_Draw_Mouse\n\n\n;----------------------------------------------------------------------------\nEND\n"
  },
  {
    "path": "WWFLAT32/KEYBOARD/X/PAGFAULT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : PAGFAULT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Julio R Jerez \t                   *\n;*                                                                         *\n;*                   \t   Date : April 25,1995                            *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;\n; Here are prototypes for the routines defined within this module:\n; VOID Install_Page_Fault_Handle (void) ;\n;\n; ----------------------------------------------------------------\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Make some general equates for easy compatability\n;---------------------------------------------------------------------------\nDPMI_INTR\t EQU\t31h  \nPAGE_FAULT\t equ\t0eh\nRESET_VIDEO_MODE  equ\t-1\n\nGLOBAL\t Install_Page_Fault_Handle : NEAR\nGLOBAL\t Set_Video_Mode\t\t   : NEAR\t\t\nGLOBAL\t Remove_Mouse\t\t   : NEAR\nGLOBAL\t Remove_Keyboard_Interrupt : NEAR\nGLOBAL\t Remove_Timer_Interrupt\t   : NEAR\t\n\nDATASEG\n\tOld_Page_Fault_handle DF ?\n\tPage_Fault_SS \tDD\t?\n\tPage_Fault_ESP\tDD\t?\n\nCODESEG\n;***************************************************************************\n;* INSTALL_PAGE_FAULT_HANDLE -- Installs new page fault handle             *\n;*\tThis function will install a new page fault handle \t\t   *\n;*\tso in the event that we have a program crash thi handle will\t   *\n;*\tremove all interrupts and then will chain to the default Page\t   *\n;*\tFault handle\t\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Install_Page_Fault_Handle( void);  \t\t   *\n;*                                                                         *\n;* HISTORY:  04/25/96 Created                                              *\n;*=========================================================================*\n\tPROC\tInstall_Page_Fault_Handle C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tmov\teax,0202h \t; get address of exception handle\n\tmov\tbl,PAGE_FAULT\n\tint\tDPMI_INTR\n\tjc\t??exit\t\t; not action is taken \n\n\t; save addrees of default handle\n\tmov\t[dword ptr Old_Page_Fault_handle],edx\n\tmov\t[word ptr  Old_Page_Fault_handle+4],cx\n\n\t; redirect default handle to a new Page Fault Handle\n\tmov eax,0203h\t\t\n\tmov bl,PAGE_FAULT\n\tmov cx,cs\n\tlea edx,[Page_Fault_Handle]\n\tint DPMI_INTR \n\n  ??exit:\n\tret\n\tENDP\tInstall_Page_Fault_Handle\n\n\n;***************************************************************************\n;* PAGE_FAULT_HANDLE --  This           \t\t   \t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* HISTORY:  04/25/96 Created                                              *\n;*=========================================================================*\nPROC\tPage_Fault_Handle far \n\n\t; preserve used  registers\n\tpush\teax\n\tpush\tebx\n\t; save Page Fault satck frame\n\tmov\tax,ss\t\n\tmov\t[Page_Fault_SS],eax\n\tmov\t[Page_Fault_ESP],esp\n\n\t; retrieve application original stack frame\n\tmov eax , [ esp + ( 6 + 2 ) * 4 ] \n\tmov ebx , [ esp + ( 7 + 2 ) * 4 ]\n\tmov ss , bx\n\tmov esp , eax\n\n\t; set video mode to standard text mode\n\tpush\tRESET_VIDEO_MODE\n\tcall \tSet_Video_Mode\n\tpop\teax\n\tcall \tRemove_Mouse\n\tcall \tRemove_Keyboard_Interrupt\n\tcall\tRemove_Timer_Interrupt\n\n\t; restore Page Fault stack frame\n\tmov\teax,[Page_Fault_SS]\n\tmov \tss , ax\n\tmov\tesp, [Page_Fault_ESP]\n\n\t; restore used registers and chain to default Page Fault Handle\n\tpop\tebx\n\tpop\teax\n\tjmp\t[fword Old_Page_Fault_handle]\n\n\tENDP\tPage_Fault_Handle\n\n\n;***************************************************************************\n;* End of File.\t\t\t\t\t\t\t\t   *\n;***************************************************************************\nEND\n\n"
  },
  {
    "path": "WWFLAT32/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : April 27, 1994                           *\n#*                                                                         *\n#*                  Last Update : May 12, 1994   [BRR]                     *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* LIBS\t\t= list of all component libraries\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* NOTE: For this makefile to work, each library directory MUST have the   *\n#*\tsame name as its library.\t\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* \"make install\" installs the library on your drive\t\t\t   *\n#* \"make update\" updates all source files in your slice\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#*\tTo install or update just one library you may type:\t\t   *\n#*\t\t \"make -DLIBS=misc.lib install\"\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n\n#===========================================================================\n# User-defined section: list each library in this macro\n#\tNOTE: These are some order dependencies:\n#\t1. The directory MISC must always be made first.\n#\t2. The directory VIDEO must be made before the SYSTEM directory.\n#===========================================================================\nLIB_NAME = wwflat32\nLIB_DIR  = $(%WWFLAT)\\lib\n\n#---------------------------------------------------------------------------\n# LIBS macro: a list of all component libraries\n#\t\"make LIBS=xxxx.lib [target]\" makes/installs/updates only that library\n#---------------------------------------------------------------------------\n\nLIBS = \t\t\t&\n\taudio.lib\t&\n\tdescmgmt.lib\t&\n\tdipthong.lib\t&\n\tfile.lib    \t&\n\tfont.lib    \t&\n\tiff.lib\t    \t&\n\tkeyboard.lib\t&\n\tmcgaprim.lib\t&\n\tmem.lib\t    \t&\n\tmisc.lib    \t&\n\tmono.lib    \t&\n\tpalette.lib \t&\n\tplaycd.lib  \t&\n\tshape.lib   \t&\n\tsosdw1ps.lib\t&\n\tsvgaprim.lib\t&\n\ttile.lib \t&\n\ttimer.lib \t&\n\tvideo.lib \t&\n\twindows.lib \t&\n\twsa.lib\t  \n\nLIB_INSTALL = \t\t&\n\taudio.ins\t&\n\tdescmgmt.ins\t&\n\tdipthong.ins\t&\n\tfile.ins    \t&\n\tfont.ins    \t&\n\tiff.ins\t    \t&\n\tkeyboard.ins\t&\n\tmcgaprim.ins\t&\n\tmem.ins\t    \t&\n\tmisc.ins    \t&\n\tmono.ins    \t&\n\tpalette.ins \t&\n\tplaycd.ins  \t&\n\tshape.ins   \t&\n\tsvgaprim.ins\t&\n\ttile.ins \t&\n\ttimer.ins \t&\n\tvideo.ins \t&\n\twindows.ins \t&\n\twsa.ins\n\nLIB_UPDATE = \t\t&\n\taudio.upd\t&\n\tdescmgmt.upd\t&\n\tdipthong.upd\t&\n\tfile.upd    \t&\n\tfont.upd    \t&\n\tiff.upd\t    \t&\n\tkeyboard.upd\t&\n\tmcgaprim.upd\t&\n\tmem.upd\t    \t&\n\tmisc.upd    \t&\n\tmono.upd    \t&\n\tpalette.upd \t&\n\tplaycd.upd  \t&\n\tshape.upd   \t&\n\tsvgaprim.upd\t&\n\ttile.upd \t&\n\ttimer.upd \t&\n\tvideo.upd \t&\n\twindows.upd \t&\n\twsa.upd\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.lib: $(%WWFLAT)\\lib\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n# LIB_CMD:\tlibrary command\n# LIB_CFG:\tlibrary configuration file\n# VCS_UPDATE:\tversion control update command; this command should update\n# \t\tall relevant files in a given directory with read-only\n#\t\tcopies from the archive\n#---------------------------------------------------------------------------\n!include $(%WWFLAT)\\project.cfg\nLIB_CMD\t\t= wlib\nVCS_UPDATE\t= update\n\n#---------------------------------------------------------------------------\n# If you like to have this makefile switch to the mono screen automatically,\n# you will need to do a \"set MONO=Y\" or to anything you like.\n#---------------------------------------------------------------------------\n!ifdef %MONO\n.BEFORE\n\tmode mono\n\n.AFTER\n\tmode co80\n\n.ERROR\n\tmode co80\n!endif\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(LIB_NAME).lib .SYMBOLIC\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(LIB_NAME).lib: $(LIBS) libs.lbc\n\t$(LIB_CMD) $(LIB_CFG) $^@ @libs.lbc\n\n\n#---------------------------------------------------------------------------\n# This construct tells make how to make all component libraries\n# The commands get executed for every item in the macro.\n#\tThe macro $: extracts only the directory name from the macro item.\n#---------------------------------------------------------------------------\n$(LIBS):\n\techo Making $^&...\n\tcd $^&\n\twmake\n\tcd ..\n\n#---------------------------------------------------------------------------\n# Libs is librarian response file that is only genarated if any of the \n# sublibrary in the golbal variable LIBS was updated.\n#---------------------------------------------------------------------------\nlibs.lbc : $(LIBS)\n\t   %create $^@\n\t   for %index in ($(LIBS)) do %append $^@ +$(LIB_DIR)\\%index\n\n\n\n#---------------------------------------------------------------------------\n# \"make install\" installs the library on your drive\n#---------------------------------------------------------------------------\ninstall:  install_dirs $(LIB_INSTALL) .SYMBOLIC\n\techo Compiling library...\n \twmake\n\techo Library installation complete.\n\n#---------------------------------------------------------------------------\n# At installation time, this target makes all non-library directories\n#\tThis is a dependency for 'install'\n#---------------------------------------------------------------------------\ninstall_dirs: .SYMBOLIC\n\techo Making directories...\n\tmkdir example\n\tmkdir include\n\tmkdir lib   \n\tmkdir srcdebug\n\tmkdir tools\n\tcd tools  \n\tcopy $(%WWVCS)\\tools\\vcs.cfg\n\t$(VCS_UPDATE) \n\tcd..   \n\tcopy $(%WWVCS)\\vcs.cfg\n\t$(VCS_UPDATE) \n\tcd example \n\tcopy $(%WWVCS)\\example\\vcs.cfg \n\t$(VCS_UPDATE) \n\tcd ..\n\n\n#---------------------------------------------------------------------------\n# This target installs all library directories\n#\tThis is a dependency for 'install'\n#---------------------------------------------------------------------------\n$(LIB_INSTALL):\t.SYMBOLIC\n\techo Installing $^&...\n\tmd $^&\n\tcd $^&\n\tcopy $(%WWVCS)\\$^&\\vcs.cfg \n\t$(VCS_UPDATE) \n\tcopy *.h ..\\include\n\tcopy *.inc ..\\include\n\tcd ..\n\n\n\n\n\n#---------------------------------------------------------------------------\n# \"make update\" updates all source files in your slice\n#---------------------------------------------------------------------------\nupdate: $(LIB_UPDATE) .SYMBOLIC\n\techo Library updated.\n\n\n#---------------------------------------------------------------------------\n# This target updates all library directories\n#\tThis is a dependency for 'updates'\n#---------------------------------------------------------------------------\n$(LIB_UPDATE): .SYMBOLIC\n\techo Updating $^&...\n\tcd $^&\n\t$(VCS_UPDATE) \n\tcopy *.h ..\\include\n\tcopy *.inc ..\\include \n\tcd ..\n"
  },
  {
    "path": "WWFLAT32/MAKE_EXE.MAK",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .EXE makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 20, 1995  \t                   *\n#*                                                                         *\n#*                  Last Update : \t\t\t                   *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*                                                                         *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the executable program you're building \t   *\n#* PROJ_LIBS\t= Westwood libraries to link your EXE to \t           *\n#* OBJECTS\t= list of objects in your current working directory\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .xxx:\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n#---------------------------------------------------------------------------\n# PROJ_NAME = library name\n# PROJ_DIR = directory containing source & objects\n#---------------------------------------------------------------------------\nPROJ_NAME\t= TEST\nPROJ_DIR\t= $(%WWFLAT)\\MEM\\TEST\nLIB_DIR\t        = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t   \t&\n\t$(PROJ_NAME).obj\t&\n\tobject0.obj\t\t&\n\tobject1.obj\t\t\n\nPROJ_LIBS = \t\t\t&\n\t    lib1.lib\t\t&\n\t    lib2.lib\t\t&\n\t    wwflat32.lib\n\t\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t $(PROJ_DIR)\n.c:   \t $(PROJ_DIR)\n.cpp:\t $(PROJ_DIR)\n.h:   \t $(PROJ_DIR)\n.obj:\t $(PROJ_DIR)\n.lib:\t $(%WWFLAT)\\lib\n.exe:\t $(PROJ_DIR)\n\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n# If LIB & INCLUDE are already defined, they are used in addition to the\n# WWLIB32 lib & include; otherwise, they're constructed from\n# BCDIR \n#---------------------------------------------------------------------------\n\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n#---------------------------------------------------------------------------\n# Default target\n#---------------------------------------------------------------------------\nall:\t$(PROJ_NAME).exe \n\n#---------------------------------------------------------------------------\n# Build the EXE\n#---------------------------------------------------------------------------\n$(PROJ_NAME).exe: $(OBJECTS)  $(PROJ_NAME).lnk $(PROJ_LIBS)\n\t $(LINK_CMD) $(LINK_CFG) system dos4g name $^@ @$(PROJ_NAME).lnk\n\n\n$(PROJ_LIBS):\t\t\n\techo updating base library $^@\n\tcd ..\n\twmake\n\tcd $(PROJ_DIR)\n\n\n$(PROJ_NAME).lnk : $(OBJECTS)\n       %create $^@\n       for %index in ($(OBJECTS))  do %append $^@ file %index\n       for %index in ($(PROJ_LIBS)) do %append $^@ library $(LIB_DIR)\\%index\n\n#**************************** End of makefile ******************************\n\n\n"
  },
  {
    "path": "WWFLAT32/MAKE_LIB.MAK",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : jan 24, 1995\t                           *\n#*                                                                         *\n#*                  Last Update : \t\t\t                   *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = project_name\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tobject1.obj  \t&\n\tobject2.obj  \t&\n\tobject3.obj \n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(WWLIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/BITBLIT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : BITBLIT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Julio R. Jerez                           *\n;*                                                                         *\n;*                   Start Date : Feb 6, 1995                              *\n;*                                                                         *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\nCODESEG\n\n\tPROC\tLinear_Blit_To_Linear C near \n\tUSES\tebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG    \tthis        :DWORD\t\t; this is a member function\n\tARG\tdest        :DWORD\t\t; what are we blitting to\n\tARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\tARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\tARG\tdest_x0     :dword\n\tARG\tdest_y0     :dword\n\tARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\tARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\tARG\ttrans       :DWORD\t\t\t; do we deal with transparents?\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tLOCAL\tdest_x1 : dword\n\tLOCAL\tdest_y1 : dword\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_ajust_width:DWORD\n        LOCAL\tsource_area :  dword\n        LOCAL\tdest_area :  dword\n\n;This Clipping algorithm is a derivation of the very well known\n;Cohen-Sutherland Line-Clipping test. Due to its simplicity and efficiency\n;it is probably the most commontly implemented algorithm both in software \n;and hardware for clipping lines, rectangles, and convex polygons against \n;a rectagular clipping window. For reference see \n;\"COMPUTER GRAPHICS principles and practice by Foley, Vandam, Feiner, Hughes\n; pages 113 to 177\".\n; Briefly consist in computing the Sutherland code for both end point of\n; the rectangle to find out if the rectangle is:\n; - trivially accepted (no further clipping test, display rectangle) \n; - trivially rejected (return with no action)\n; - retangle must be iteratively clipped again edges of the clipping window\n;   and the remaining retangle is display.\n\n; Clip Source Rectangle against source Window boundaries.\n\tmov  \tesi,[this]\t    ; get ptr to src\n\txor \tecx,ecx\t\t    ; Set sutherland code to zero \t\n\txor \tedx,edx\t\t    ; Set sutherland code to zero\n\n   ; compute the difference in the X axis and get the bit signs into ecx , edx \n\tmov\tedi,[(VideoViewPort esi).VIVPWidth]  ; get width into register\n\tmov\tebx,[x_pixel]\t    ; Get first end point x_pixel into register\t\n\tmov\teax,[x_pixel]\t    ; Get second end point x_pixel into register\n\tadd\tebx,[pixel_width]   ; second point x1_pixel = x + width\n\tshld\tecx, eax,1\t    ; the sign bit of x_pixel is sutherland code0 bit4\n\tmov\t[x1_pixel],ebx\t    ; save second for future use \n\tinc\tedi\t\t    ; move the right edge by one unit\n\tshld\tedx,ebx,1\t    ; the sign bit of x1_pixel is sutherland code0 bit4\n\tsub\teax,edi\t\t    ; compute the difference x0_pixel - width\n\tsub\tebx,edi\t\t    ; compute the difference x1_pixel - width\n\tshld\tecx,eax,1\t    ; the sign bit of the difference is sutherland code0 bit3\n\tshld\tedx,ebx,1\t    ; the sign bit of the difference is sutherland code0 bit3\n\n   ; the following code is just a repeticion of the above code\n   ; in the Y axis.\n\tmov\tedi,[(VideoViewPort esi).VIVPHeight] ; get height into register\n\tmov\tebx,[y_pixel]\n\tmov\teax,[y_pixel]\n\tadd\tebx,[pixel_height]\n\tshld\tecx,eax,1\n\tmov\t[y1_pixel ],ebx\n\tinc\tedi\n\tshld\tedx,ebx,1\n\tsub\teax,edi\n\tsub\tebx,edi\n\tshld\tecx,eax,1\n\tshld\tedx,ebx,1\n\n    ; Here we have the to Sutherland code into cl and dl\n\txor\tcl,5\t\t       ; bit 2 and 0 are complented, reverse then\n\txor\tdl,5\t\t       ; bit 2 and 0 are complented, reverse then\n\tmov\tal,cl\t\t       ; save code1 in case we have to clip iteratively\n\ttest\tdl,cl\t\t       ; if any bit in code0 and its counter bit\n\tjnz\t??real_out\t       ; in code1 is set then the rectangle in outside\n\tor\tal,dl\t\t       ; if all bit of code0 the counter bit in\n\tjz\t??clip_against_dest    ; in code1 is set to zero, then all\n\t\t\t\t       ; end points of the rectangle are\n\t\t\t\t       ; inside the clipping window\n\n     ; if we are here the polygon have to be clip iteratively\n\ttest\tcl,1000b\t       ; if bit 4 in code0 is set then\n\tjz\t??scr_left_ok\t       ; x_pixel is smaller than zero\n\tmov\t[x_pixel],0\t       ; set x_pixel to cero.\n\n??scr_left_ok:\n\ttest\tcl,0010b\t       ; if bit 2 in code0 is set then\n\tjz\t??scr_bottom_ok\t       ; y_pixel is smaller than zero\n\tmov\t[ y_pixel ],0\t       ; set y_pixel to cero.\n\n??scr_bottom_ok:\n\ttest\tdl,0100b\t       ; if bit 3 in code1 is set then\n\tjz\t??scr_right_ok\t       ; x1_pixel is greater than the width\n\tmov\teax,[(VideoViewPort esi).VIVPWidth] ; get width into register\n\tmov\t[ x1_pixel ],eax       ; set x1_pixel to width. \n??scr_right_ok:\n\ttest\tdl,0001b\t       ; if bit 0 in code1 is set then\n\tjz\t??clip_against_dest    ; y1_pixel is greater than the width\n\tmov\teax,[(VideoViewPort esi).VIVPHeight]  ; get height into register\n\tmov\t[ y1_pixel ],eax       ; set y1_pixel to height. \n\n; Clip Source Rectangle against destination Window boundaries.\n??clip_against_dest:\n \n   ; build the destination rectangle before clipping \n   ; dest_x1 = dest_x0 + ( x1_pixel - x_pixel ) \n   ; dest_y1 = dest_y0 + ( y1_pixel - y_pixel ) \n\tmov\teax,[dest_x0]\t     ; get dest_x0 into eax\n\tmov\tebx,[dest_y0]\t     ; get dest_y0 into ebx\n\tsub\teax,[x_pixel]\t     ; subtract x_pixel from eax\n\tsub\tebx,[y_pixel]\t     ; subtract y_pixel from ebx\n\tadd\teax,[x1_pixel]\t     ; add x1_pixel to eax\n\tadd\tebx,[y1_pixel]\t     ; add y1_pixel to ebx\n\tmov\t[dest_x1],eax\t     ; save eax into dest_x1\n\tmov\t[dest_y1],ebx\t     ; save eax into dest_y1\n\n\n  ; The followin code is a repeticion of the Sutherland clipping \n  ; descrived above.\n\tmov  \tesi,[dest]\t    ; get ptr to src\n\txor \tecx,ecx\n\txor \tedx,edx\n\tmov\tedi,[(VideoViewPort esi).VIVPWidth]  ; get width into register\n\tmov\teax,[dest_x0]\n\tmov\tebx,[dest_x1]\n\tshld\tecx,eax,1\n\tinc\tedi\n\tshld\tedx,ebx,1\n\tsub\teax,edi\n\tsub\tebx,edi\n\tshld\tecx,eax,1\n\tshld\tedx,ebx,1\n\n\tmov\tedi,[( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\teax,[dest_y0]\n\tmov\tebx,[dest_y1]\n\tshld\tecx,eax,1\n\tinc\tedi\n\tshld\tedx,ebx,1\n\tsub\teax,edi\n\tsub\tebx,edi\n\tshld\tecx,eax,1\n\tshld\tedx,ebx,1\n\n\txor\tcl,5\n\txor\tdl,5\n\tmov\tal,cl\n\ttest\tdl,cl\n\tjnz\t??real_out\n\tor\tal,dl\n\tjz\t??do_blit\n\n\ttest\tcl,1000b\n\tjz\t??dest_left_ok\n\tmov\teax,[ dest_x0 ]\n\tmov\t[ dest_x0 ],0\n\tsub\t[ x_pixel ],eax\n\n??dest_left_ok:\n\ttest\tcl,0010b\n\tjz\t??dest_bottom_ok\n\tmov\teax,[ dest_y0 ]\n\tmov\t[ dest_y0 ],0\n\tsub\t[ y_pixel ],eax\n\n\n??dest_bottom_ok:\n\ttest\tdl,0100b\n\tjz\t??dest_right_ok\n\tmov\tebx,[ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax,[ dest_x1 ]\n\tmov\t[ dest_x1 ],ebx\n\tsub\teax,ebx\n\tsub\t[ x1_pixel ],eax\n\n??dest_right_ok:\n\ttest\tdl,0001b\n\tjz\t??do_blit\n\tmov\tebx,[ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\teax,[ dest_y1 ]\n\tmov\t[ dest_y1 ],ebx\n\tsub\teax,ebx\n\tsub\t[ y1_pixel ],eax\n\n\n; Here is where\twe do the actual blit\n??do_blit:\n       cld\t\n       mov\tebx,[this]\n       mov\tesi,[(VideoViewPort ebx).VIVPOffset]\n       mov\teax,[(VideoViewPort ebx).VIVPXAdd]\n       add\teax,[(VideoViewPort ebx).VIVPWidth]\n       mov\tecx,eax\n       mul\t[y_pixel]\n       add\tesi,[x_pixel]\n       mov\t[source_area],ecx\n       add\tesi,eax\n\n       add\tecx,[x_pixel ]\n       sub\tecx,[x1_pixel ]\n       mov\t[scr_ajust_width ],ecx\n\n       mov\tebx,[dest]\n       mov\tedi,[(VideoViewPort ebx).VIVPOffset]\n       mov\teax,[(VideoViewPort ebx).VIVPXAdd]\n       add\teax,[ (VideoViewPort ebx).VIVPWidth]\n       mov\tecx,eax\n       mul\t[ dest_y0 ]\n       add\tedi,[ dest_x0 ]\n       mov\t[ dest_area ],ecx\n       add\tedi,eax\n\n       mov\teax,[ dest_x1 ]\n       sub\teax,[ dest_x0 ]\n       jle\t??real_out\n       sub\tecx,eax\n       mov\t[ dest_ajust_width ],ecx\n\n       mov\tedx,[ dest_y1 ]\n       sub\tedx,[ dest_y0 ]\n       jle\t??real_out\n\n       cmp\tesi,edi\n       jz\t??real_out\n       jl\t??backupward_blit\n\n; ********************************************************************       \n; Forward bitblit\n\n       test\t[ trans ],1\n       jnz\t??forward_Blit_trans\n\n\n; the inner loop is so efficient that \n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax,10        \n       jl\t??forward_loop_bytes\n\n??forward_loop_dword:\n       mov\tecx,edi\n       mov\tebx,eax\n       neg\tecx\n       and\tecx,3\n       sub\tebx,ecx\n       rep\tmovsb\n       mov\tecx,ebx\n       shr\tecx,2\n       rep\tmovsd\n       mov\tecx,ebx\n       and\tecx,3\n       rep\tmovsb\n       add\tesi,[ scr_ajust_width ]\n       add\tedi,[ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_dword\n       ret\n\n??forward_loop_bytes:\n       mov\tecx,eax \n       rep\tmovsb\n       add\tesi,[ scr_ajust_width ]\n       add\tedi,[ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_bytes\n       ret\n\n??forward_Blit_trans:\n       mov\tecx,eax\n       and\tecx,01fh\n       lea\tecx,[ ecx + ecx * 4 ]\t\n       neg\tecx\n       shr\teax,5\n       lea\tecx,[ ??transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ],ecx\n\n??forward_loop_trans:\n       mov\tecx,eax \n       jmp\t[ y1_pixel ]\n??forward_trans_line:\n       REPT\t32\t\n       local\ttransp_pixel\n       \t\tmov\tbl,[ esi ]\n       \t\ttest\tbl,bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ],bl\n    \t    transp_pixel:\n       \t\tinc\tesi\n\t    \tinc\tedi\n\tENDM\n    ??transp_reference:\n       dec\tecx \n       jge\t??forward_trans_line\n       add\tesi,[ scr_ajust_width ]\n       add\tedi,[ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_trans\n       ret\n\n\n; ************************************************************************\n; backward bitblit\n\n??backupward_blit:\n\n\tmov\tebx,[ source_area ]\n\tdec\tedx\n\tadd\tesi,eax\n\timul    ebx,edx\n\tstd\n\tlea\tesi,[ esi + ebx - 1 ]\n\n\tmov\tebx,[ dest_area ]\n\tadd\tedi,eax\n\timul    ebx,edx\n\tlea\tedi,[ edi + ebx - 1]\n\n       test\t[ trans ],1\n       jnz\t??backward_Blit_trans\n\n        cmp\teax,15        \n        jl\t??backward_loop_bytes\t\n\t\t   \n??backward_loop_dword:\n\tpush\tedi\n\tpush\tesi\n\tlea\tecx,[edi+1]\n\tmov\tebx,eax\n\tand\tecx,3\t\t; Get non aligned bytes.\n\tsub\tebx,ecx\t\t; remove that from the total size to be copied later.\n\trep\tmovsb\t\t; do the copy.\n\tsub\tesi,3\n\tmov\tecx,ebx\t\t; Get number of bytes left.\n \tsub\tedi,3\n\tshr\tecx,2\t\t; Do 4 bytes at a time.\n\trep\tmovsd\t\t; do the dword copy.\n\tmov\tecx,ebx\n\tadd\tesi,3\n\tadd\tedi,3\n\tand\tecx,03h\n\trep\tmovsb\t\t; finnish the remaining bytes.\n\tpop\tesi\n\tpop\tedi\n        sub\tesi,[ source_area ]\n        sub\tedi,[ dest_area ]\n\tdec\tedx\n\tjge\t??backward_loop_dword\n\tcld\t\n\tret\n\n??backward_loop_bytes:\n\tpush\tedi\n\tmov\tecx,eax\t\t; remove that from the total size to be copied later.\n\tpush\tesi\n\trep\tmovsb\t\t; do the copy.\n\tpop\tesi\n\tpop\tedi\n        sub\tesi,[ source_area ]\n        sub\tedi,[ dest_area ]\n\tdec\tedx\n\tjge\t??backward_loop_bytes\n\tcld\t\n\tret\n\n??backward_Blit_trans:\n       mov\tecx,eax\n       and\tecx,01fh\n       lea\tecx,[ ecx + ecx * 4 ]\t\n       neg\tecx\n       shr\teax,5\n       lea\tecx,[ ??back_transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ],ecx\n\n??backward_loop_trans:\n       mov\tecx,eax \n       push\tedi\n       push\tesi\n       jmp\t[ y1_pixel ]\n??backward_trans_line:\n       REPT\t32\t\n       local\ttransp_pixel\n       \t\tmov\tbl,[ esi ]\n       \t\ttest\tbl,bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ],bl\n    \t    transp_pixel:\n       \t\tdec\tesi\n\t    \tdec\tedi\n\tENDM\n    ??back_transp_reference:\n       dec\tecx \n       jge\t??backward_trans_line\n       pop\tesi\n       pop\tedi\n       sub\tesi,[ source_area ]\n       sub\tedi,[ dest_area ]\n       dec\tedx \n       jge\t??backward_loop_trans\n       cld\n       ret\n\n??real_out:\n       ret\n       ENDP\tLinear_Blit_To_Linear\n\n\n\nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/BUFFER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library                  *\n *                                                                         *\n *                    File Name : BUFFER.CPP                               *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 18, 1994                             *\n *                                                                         *\n *                  Last Update : June 1, 1994   [PWG]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   BC::BufferClass -- The default (void) constructor for a buffer class  *\n *   BC::~BufferClass -- The destructor for the buffer class               *\n *   BC::BufferClass -- The standard constructor for a buffer class        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BUFFER_H\n#include \"buffer.h\"\n#endif\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * BC::BufferClass -- The standard constructor for a buffer class          *\n *                                                                         *\n * INPUT:\t\tVOID *\tbuffer to which should be included in buffer class *\n *\t\t\t\t\tLONG\t\tsize of the buffer which we included\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     NONE                                                        *\n *                                                                         *\n * WARNINGS:   If the buffer passed to this function is equal to NULL,     *\n *\t\t\t\t\tthe buffer will be allocated using new.\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\nBufferClass::BufferClass(VOID *buffer, LONG size)\n{\n\tSize\t\t\t= size;\t\t\t\t\t\t\t\t// find size of physical buffer\n\n\tif (buffer) {\t\t\t\t\t\t\t\t\t\t// if buffer is specified\n\t\tBuffer\t\t\t= (BYTE *)buffer;\t\t\t//\t\tpoint to it and mark\n\t\tAllocated\t\t= FALSE;\t\t\t\t\t\t//\t\tit as user allocated\n\t} else {\n\t\tBuffer\t\t\t= new BYTE[Size];\t\t\t// otherwise allocate it and\n\t\tAllocated\t\t= TRUE;\t\t\t\t\t\t//\t\tmark it system alloced\n\t}\n}\n\n/***************************************************************************\n * BC::BufferClass -- constructor for BufferClass with size only    \t\t\t*\n *                                                                         *\n * INPUT:\t\tLONG the size of the buffer that needs to be allocated\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\nBufferClass::BufferClass(LONG size)\n{\n\tSize\t\t\t\t= size;\n\tBuffer\t\t\t= new BYTE[Size];\t\t\t// otherwise allocate it and\n\tAllocated\t\t= TRUE;\t\t\t\t\t\t//\t\tmark it system alloced\n}\n\n/***************************************************************************\n * BC::BufferClass -- The default (void) constructor for a buffer class    *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * NOTES:   \tThe primary function of this class is to be called by a     *\n *\t\t\t\t\tderived class which will fill in the values after the\t\t\t*\n *\t\t\t\t\tfact.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\nBufferClass::BufferClass(VOID)\n{\n\tBuffer\t\t= NULL;\n\tSize\t\t\t= 0;\n\tAllocated\t= FALSE;\n}\n\n/***************************************************************************\n * BC::~BUFFERCLASS -- The destructor for the buffer class                 *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\nBufferClass::~BufferClass(VOID)\n{\n\tif (Allocated) {\n\t\tdelete[] Buffer;\n\t}\n}\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/BUFFER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : GBUFFER.H                                *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 26, 1994                             *\n *                                                                         *\n *                  Last Update : July 5, 1994   [PWG]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   BC::Get_Size -- Returns the buffer size of the BufferClass instance   *\n *   BC::Get_Buffer -- Returns pointer to buffer inherent to BufferClass \t*\n *   BC::BufferClass -- inline constructor for BufferClass with size only  *\n *   BC::To_Page -- Copys a buffer class to a page with definable x, y, w, h*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BUFFER_H\n#define BUFFER_H\n\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\nclass GraphicViewPortClass;\nclass VideoViewPortClass;\n\n/*=========================================================================*/\n/* BufferClass - A base class which holds buffer information including a\t*/\n/*\t\tpointer and the size of the buffer.\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nclass BufferClass {\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBufferClass(void *ptr, long size);\n\t\tBufferClass(long size);\n\t\tBufferClass();\n\t\t~BufferClass();\n\t\t/*===================================================================*/\n\t\t/* Define functions which work with the buffer class.\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong To_Page(GraphicViewPortClass &view);\n\t\tlong To_Page(int w, int h, GraphicViewPortClass &view);\n\t\tlong To_Page(int x, int y, int w, int h, GraphicViewPortClass &view);\n\t\tlong To_Page(VideoViewPortClass &view);\n\t\tlong To_Page(int w, int h, VideoViewPortClass &view);\n\t\tlong To_Page(int x, int y, int w, int h, VideoViewPortClass &view);\n\n\t\t/*===================================================================*/\n\t\t/* define functions to get at the protected data members\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tvoid\t*Get_Buffer(void);\n\t\tlong\tGet_Size(void);\n\n\tprivate:\n\t\t/*===================================================================*/\n\t\t/* Define the operators we do not want to happen which are the copy\t*/\n\t\t/* and equal constructors.  These are bad because the Allocated flag\t*/\n\t\t/*\tcould be copied and the associated buffer freed.  If this were to\t*/\n\t\t/*\tgappen it could cause weird general protection fault.\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBufferClass(BufferClass const &);\n\t\tBufferClass &operator=(BufferClass const &);\n\n\tprotected:\n\t\tvoid\t*Buffer;\n\t\tlong\tSize;\n\t\tBOOL\tAllocated;\n};\n/***************************************************************************\n * BC::GET_SIZE -- Returns the buffer size of the BufferClass instance     *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long the size of the buffer                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::Get_Size(void)\n{\n\treturn(Size);\n}\n/***************************************************************************\n * BC::GET_BUFFER -- Returns pointer to buffer inherent to BufferClass \t\t*\n *                                                                         *\n * INPUT:\t\t\tnone                                                     *\n *                                                                         *\n * OUTPUT:        void * to the inherent buffer.                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline void *BufferClass::Get_Buffer(void)\n{\n\treturn(Buffer);\n}\n#endif\n\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/BUFFGLBL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : BUFFGLBL.CPP                             *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : January 10, 1995                         *\n *                                                                         *\n *                  Last Update : January 10, 1995   [PWG]                 *\n *                                                                         *\n * This module holds the global fixup tables for the MCGA buffer class.    *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"wwstd.h\"\n#include \"gbuffer.h\"\n#include\t\"vbuffer.h\"\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/*=========================================================================*/\n/* Globals required by GraphicBufferClass for function pointers.  These\t\t*/\n/*   pointers will be set to the proper function when set mode is called.\t*/\n/*=========================================================================*/\nBOOL (*GVPC_Blit_to_VVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nBOOL (*GVPC_Scale_To_VVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\n\n/*=========================================================================*/\n/* Globals required by VideoBufferClass for function pointers.  These\t\t*/\n/*   pointers will be set to the proper function when set mode is called.\t*/\n/*=========================================================================*/\nvoid (*VVPC_Clear_Func)(void *, unsigned char);\nlong (*VVPC_To_Buffer_Func)(void *,int x, int y, int w, int h, void *buff, long size);\nvoid (*VVPC_Put_Pixel_Func)(void *,int x, int y, unsigned char color);\nint  (*VVPC_Get_Pixel_Func)(void *, int x, int y);\nlong (*VVPC_Buffer_To_Page)(int x, int y, int w, int h, void *Buffer, void *view);\nBOOL (*VVPC_Blit_to_GVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nBOOL (*VVPC_Blit_to_VVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nBOOL (*VVPC_Scale_To_GVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\nBOOL (*VVPC_Scale_To_VVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\nLONG (*VVPC_Print_Func)(\t\tvoid *, const char *, int, int, int, int);\nvoid (*VVPC_Draw_Stamp)(void *, void *, int, int, int, void *);\nlong (*VVPC_Size_Of_Region)(void *, int, int);\n\n/*=========================================================================*/\n/* We need to keep a pointer to the logic page hanging around somewhere\t\t*/\n/*=========================================================================*/\nGraphicBufferClass\t*LogicPage;\n\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/CLEAR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Clear the Full Mcga Screen\t\t   *\n;*                                                                         *\n;*                    File Name : CLEAR.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : August 23, 1994   [SKB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVPC::Clear -- Clears a virtual viewport instance                     *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nCODESEG\n\n;***************************************************************************\n;* VVPC::CLEAR -- Clears a virtual viewport instance                       *\n;*                                                                         *\n;* INPUT:\tUBYTE the color (optional) to clear the view port to\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* NOTE:\tThis function is optimized to handle viewport with no XAdd *\n;*\t\tvalue.  It also handles DWORD aligning the destination\t   *\n;*\t\twhen speed can be gained by doing it.\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/07/1994 PWG : Created.                                             *\n;*   08/23/1994 SKB : Clear the direction flag to always go forward.       *\n;*=========================================================================*\n\tPROC\tMCGA_Clear C near \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tARG    \tthis:DWORD\t\t\t\t; this is a member function\n\tARG    \tcolor:BYTE\t\t\t\t; what color should we clear to\n\n\tcld \t\t \t\t\t\t; always go forward\n\n\tmov\tebx,[this]\t\t\t\t; get a pointer to viewport\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get the correct offset\n\tmov\tedx,[(GraphicViewPort ebx).GVPHeight]\t; ecx = height of viewport\n\tmov\tesi,[(GraphicViewPort ebx).GVPWidth]\t; edx = width of viewport\n\tmov\tebx,[(GraphicViewPort ebx).GVPXAdd]\t; esi = add for each line\n\n\t;*===================================================================\n\t; Convert the color byte to a DWORD for fast storing\n\t;*===================================================================\n\tmov\tal,[color]\t\t\t\t; get color to clear to\n\tmov\tah,al\t\t\t\t\t; extend across WORD\n\tmov\tecx,eax\t\t\t\t\t; extend across DWORD in\n\tshl\teax,16\t\t\t\t\t;   several steps\n\tmov\tax,cx\t\t\n\n\t;*===================================================================\n\t; Find out if we should bother to align the row.\n\t;*===================================================================\n\n\tcmp\tesi , OPTIMAL_BYTE_COPY\t\t\t; is it worth aligning them?\n\tjl\t??byte_by_byte\t\t\t\t;   if not then skip\n\n\t;*===================================================================\n\t; Figure out the alignment offset if there is any\n\t;*===================================================================\n\tpush\tebx\n??dword_aligned_loop:\n       mov\tecx , edi\n       mov\tebx , esi\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tstosb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tstosd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tstosb\n       add\tedi , [ esp ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??dword_aligned_loop\t\t\t\t; if more to do than do it\n       pop\teax\n       ret\n\n\t;*===================================================================\n\t; If not enough bytes to bother aligning copy each line across a byte\n\t;    at a time.\n\t;*===================================================================\n??byte_by_byte:\n\tmov\tecx,esi\t\t\t\t\t; get total width in bytes\n\trep\tstosb\t\t\t\t\t; store the width\n\tadd\tedi,ebx\t\t\t\t\t; handle the xadd\n\tdec\tedx\t\t\t\t\t; decrement the height\n\tjnz\t??byte_by_byte\t\t\t\t; if any left then next line\n??exit:\n\tret\n\tENDP\tMCGA_Clear\nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/DRAWLINE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : DRAWLINE.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 16, 1994                            *\n;*                                                                         *\n;*                  Last Update : August 30, 1994   [IML]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVC::Scale -- Scales a virtual viewport to another virtual viewport   *\n;*   Normal_Draw -- jump loc for drawing  scaled line of normal pixel      *\n;*   __DRAW_LINE -- Assembly routine to draw a line                        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n;***************************************************************************\n;* VVC::DRAW_LINE -- Scales a virtual viewport to another virtual viewport *\n;*                                                                         *\n;* INPUT:\tWORD sx_pixel \t- the starting x pixel position\t\t   *\n;*\t\tWORD sy_pixel\t- the starting y pixel position\t\t   *\n;*\t\tWORD dx_pixel\t- the destination x pixel position\t   *\n;*\t\tWORD dy_pixel   - the destination y pixel position\t   *\n;*\t\tWORD color      - the color of the line to draw\t\t   *\n;*                                                                         *\n;* Bounds Checking: Compares sx_pixel, sy_pixel, dx_pixel and dy_pixel\t   *\n;*       with the graphic viewport it has been assigned to.\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/16/1994 PWG : Created.                                             *\n;*   08/30/1994 IML : Fixed clipping bug.\t\t\t\t   *\n;*=========================================================================*\n\tPROC\tMCGA_Draw_Line C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\t;*==================================================================\n\t;* Define the arguements that the function takes.\n\t;*==================================================================\n\tARG\tthis:DWORD\t\t; associated graphic view port\n\tARG\tx1_pixel:DWORD\t\t; the start x pixel position\n\tARG\ty1_pixel:DWORD\t\t; the start y pixel position\n\tARG\tx2_pixel:DWORD\t\t; the dest x pixel position\n\tARG\ty2_pixel:DWORD\t\t; the dest y pixel position\n\tARG\tcolor:DWORD\t\t; the color we are drawing\n\n\t;*==================================================================\n\t;* Define the local variables that we will use on the stack\n\t;*==================================================================\n\tLOCAL\tclip_min_x:DWORD\n\tLOCAL\tclip_max_x:DWORD\n\tLOCAL\tclip_min_y:DWORD\n\tLOCAL\tclip_max_y:DWORD\n\tLOCAL\tclip_var:DWORD\n\tLOCAL\taccum:DWORD\n\tLOCAL\tbpr:DWORD\n\n\t;*==================================================================\n\t;* Take care of find the clip minimum and maximums\n\t;*==================================================================\n\tmov\tebx,[this]\t\t\n\txor\teax,eax\n\tmov\t[clip_min_x],eax\t\n\tmov\t[clip_min_y],eax\t\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\n\tmov\t[clip_max_x],eax\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\n\tmov\t[bpr],eax\n\tmov\teax,[(GraphicViewPort ebx).GVPHeight]\n\tmov\t[clip_max_y],eax\n\n\t;*==================================================================\n\t;* Adjust max pixels as they are tested inclusively.\n\t;*==================================================================\n\tdec\t[clip_max_x]\t\n\tdec\t[clip_max_y]\n\n\t;*==================================================================\n\t;* Set the registers with the data for drawing the line\n\t;*==================================================================\n\tmov\teax,[x1_pixel]\t\t; eax = start x pixel position\n\tmov\tebx,[y1_pixel]\t\t; ebx = start y pixel position\n\tmov\tecx,[x2_pixel]\t\t; ecx = dest x pixel position\n\tmov\tedx,[y2_pixel]\t\t; edx = dest y pixel position\n\n\t;*==================================================================\n\t;* This is the section that \"pushes\" the line into bounds.\n\t;* I have marked the section with PORTABLE start and end to signify\n\t;* how much of this routine is 100% portable between graphics modes.\n\t;* It was just as easy to have variables as it would be for constants\n\t;* so the global vars ClipMaxX,ClipMinY,ClipMaxX,ClipMinY are used\n\t;* to clip the line (default is the screen)\n\t;* PORTABLE start\n\t;*==================================================================\n\n\tcmp\teax,[clip_min_x]\t\t\n\tjl\tshort ??clip_it\n\tcmp\teax,[clip_max_x]\n\tjg\tshort ??clip_it\n\tcmp\tebx,[clip_min_y]\n\tjl\tshort ??clip_it\n\tcmp\tebx,[clip_max_y]\n\tjg\tshort ??clip_it\n\tcmp\tecx,[clip_min_x]\n\tjl\tshort ??clip_it\n\tcmp\tecx,[clip_max_x]\n\tjg\tshort ??clip_it\n\tcmp\tedx,[clip_min_y]\n\tjl\tshort ??clip_it\n\tcmp\tedx,[clip_max_y]\n\tjle\tshort ??on_screen\n\n\t;*==================================================================\n\t;* Takes care off clipping the line.\n\t;*==================================================================\n??clip_it:\n\tcall\tNEAR PTR ??set_bits\n\txchg\teax,ecx\n\txchg\tebx,edx\n\tmov\tedi,esi\n\tcall\tNEAR PTR ??set_bits\n\tmov\t[clip_var],edi\n\tor\t[clip_var],esi\n\tjz\tshort ??on_screen\n\ttest\tedi,esi\n\tjne\tshort ??off_screen\n\tshl\tesi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+esi]\n\tjc\t??clip_it\n\txchg\teax,ecx\n\txchg\tebx,edx\n\tshl\tedi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+edi]\n\tjmp\t??clip_it\n\n??on_screen:\n\tjmp\t??draw_it\n\n??off_screen:\n\tjmp\t??out\n\n\t;*==================================================================\n\t;* Jump table for clipping conditions\n\t;*==================================================================\n??clip_tbl\tDD\t??nada,??a_up,??a_dwn,??nada\n\t\tDD\t??a_lft,??a_lft,??a_dwn,??nada\n\t\tDD\t??a_rgt,??a_up,??a_rgt,??nada\n\t\tDD\t??nada,??nada,??nada,??nada\n\n??nada:\n\tclc\n\tretn\n\n??a_up:\n\tmov\tesi,[clip_min_y]\n\tcall\tNEAR PTR ??clip_vert\n\tstc\n\tretn\n\n??a_dwn:\n\tmov\tesi,[clip_max_y]\n\tneg\tesi\n\tneg\tebx\n\tneg\tedx\n\tcall\tNEAR PTR ??clip_vert\n\tneg\tebx\n\tneg\tedx\n\tstc\n\tretn\n\n\t;*==================================================================\n\t;* xa'=xa+[(miny-ya)(xb-xa)/(yb-ya)]\n\t;*==================================================================\n??clip_vert:\n\tpush\tedx\n\tpush\teax\n\tmov\t[clip_var],edx\t\t; clip_var = yb\n\tsub\t[clip_var],ebx\t\t; clip_var = (yb-ya)\n\tneg\teax\t\t\t; eax=-xa\n\tadd\teax,ecx\t\t\t; (ebx-xa)\n\tmov\tedx,esi\t\t\t; edx=miny\n\tsub\tedx,ebx\t\t\t; edx=(miny-ya)\n\timul\tedx\n\tidiv\t[clip_var]\n\tpop\tedx\n\tadd\teax,edx\n\tpop\tedx\n\tmov\tebx,esi\n\tretn\n\n??a_lft:\n\tmov\tesi,[clip_min_x]\n\tcall\tNEAR PTR ??clip_horiz\n\tstc\n\tretn\n\n??a_rgt:\n\tmov\tesi,[clip_max_x]\n\tneg\teax\n\tneg\tecx\n\tneg\tesi\n\tcall\tNEAR PTR ??clip_horiz\n\tneg\teax\n\tneg\tecx\n\tstc\n\tretn\n\n\t;*==================================================================\n\t;* ya'=ya+[(minx-xa)(yb-ya)/(xb-xa)]\n\t;*==================================================================\n??clip_horiz:\n\tpush\tedx\n\tmov\t[clip_var],ecx\t\t; clip_var = xb\n\tsub\t[clip_var],eax\t\t; clip_var = (xb-xa)\n\tsub\tedx,ebx\t\t\t; edx = (yb-ya)\n\tneg\teax\t\t\t; eax = -xa\n\tadd\teax,esi\t\t\t; eax = (minx-xa)\n\timul\tedx\t\t\t; eax = (minx-xa)(yb-ya)\n\tidiv\t[clip_var]\t\t; eax = (minx-xa)(yb-ya)/(xb-xa)\n\tadd\tebx,eax\t\t\t; ebx = xa+[(minx-xa)(yb-ya)/(xb-xa)]\n\tpop\tedx\n\tmov\teax,esi\n\tretn\n\n\t;*==================================================================\n\t;* Sets the condition bits\n\t;*==================================================================\n??set_bits:\n\txor\tesi,esi\n\tcmp\tebx,[clip_min_y]\t; if y >= top its not up\n\tjge\tshort ??a_not_up\n\tor\tesi,1\n\n??a_not_up:\n\tcmp\tebx,[clip_max_y]\t; if y <= bottom its not down\n\tjle\tshort ??a_not_down\n\tor\tesi,2\n\n??a_not_down:\n\tcmp\teax,[clip_min_x]   \t; if x >= left its not left\n\tjge\tshort ??a_not_left\n\tor\tesi,4\n\n??a_not_left:\n\tcmp\teax,[clip_max_x]\t; if x <= right its not right\n\tjle\tshort ??a_not_right\n\tor\tesi,8\n\n??a_not_right:\n\tretn\t\n\n\t;*==================================================================\n\t;* Draw the line to the screen.\n\t;* PORTABLE end\n\t;*==================================================================\n??draw_it:\n\tsub\tedx,ebx\t\t\t; see if line is being draw down\n\tjnz\tshort ??not_hline\t; if not then its not a hline\n\tjmp\tshort ??hline\t\t; do special case h line\n\n??not_hline:\n\tjg\tshort ??down\t\t; if so there is no need to rev it\n\tneg\tedx\t\t\t; negate for actual pixel length\n\txchg\teax,ecx\t\t\t; swap x's to rev line draw\n\tsub\tebx,edx\t\t\t; get old edx\n\n??down:\n\tpush\tedx\n\tpush\teax\n\tmov\teax,[bpr]\n\tmul\tebx\n\tmov\tebx,eax\n\tmov\teax,[this]\n\tadd\tebx,[(GraphicViewPort eax).GVPOffset]\n\tpop\teax\n\tpop\tedx\n\n\tmov\tesi,1\t\t\t; assume a right mover\n\tsub\tecx,eax\t\t\t; see if line is right\n\tjnz\tshort ??not_vline\t; see if its a vertical line\n\tjmp\t??vline\n\n??not_vline:\n\tjg\tshort ??right\t\t; if so, the difference = length\n\n??left:\n\tneg\tecx\t\t\t; else negate for actual pixel length\n\tneg\tesi\t\t\t; negate counter to move left\n\n??right:\n\tcmp\tecx,edx\t\t\t; is it a horiz or vert line\n\tjge\tshort ??horiz\t\t; if ecx > edx then |x|>|y| or horiz\n\n??vert:\n\txchg\tecx,edx\t\t\t; make ecx greater and edx lesser\n\tmov\tedi,ecx\t\t\t; set greater\n\tmov\t[accum],ecx\t\t; set accumulator to 1/2 greater\n\tshr\t[accum],1\n\n\t;*==================================================================\n\t;* at this point ...\n\t;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;\n\t;* esi=adder; accum=accumulator\n\t;* in a vertical loop the adder is conditional and the inc constant\n\t;*==================================================================\n??vert_loop:\n\tadd\tebx,eax\n\tmov\teax,[color]\n\n??v_midloop:\n\tmov\t[ebx],al\n\tdec\tecx\n\tjl\tshort ??out\n\tadd\tebx,[bpr]\n\tsub\t[accum],edx\t\t; sub the lesser\n\tjge\t??v_midloop\t\t; any line could be new\n\tadd\t[accum],edi\t\t; add greater for new accum\n\tadd\tebx,esi\t\t\t; next pixel over\n\tjmp\t??v_midloop\n\n??horiz:\n\tmov\tedi,ecx\t\t\t; set greater\n\tmov\t[accum],ecx\t\t; set accumulator to 1/2 greater\n\tshr\t[accum],1\n\n\t;*==================================================================\n\t;* at this point ...\n\t;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;\n\t;* esi=adder; accum=accumulator\n\t;* in a vertical loop the adder is conditional and the inc constant\n\t;*==================================================================\n??horiz_loop:\n\tadd\tebx,eax\n\tmov\teax,[color]\n\n??h_midloop:\n\tmov\t[ebx],al\n\tdec\tecx\t\t\t\t; dec counter\n\tjl\tshort ??out\t\t\t; end of line\n\tadd\tebx,esi\n\tsub     [accum],edx\t\t\t; sub the lesser\n\tjge\t??h_midloop\n\tadd\t[accum],edi\t\t\t; add greater for new accum\n\tadd\tebx,[bpr]\t\t\t; goto next line\n\tjmp\t??h_midloop\n\n\t;*==================================================================\n\t;* Special case routine for horizontal line draws\n\t;*==================================================================\n??hline:\n\tcmp\teax,ecx\t\t\t; make eax < ecx\n\tjl\tshort ??hl_ac\n\txchg\teax,ecx\n\n??hl_ac:\n\tsub\tecx,eax\t\t\t; get len\n\tinc\tecx\n\n\tpush\tedx\n\tpush\teax\n\tmov\teax,[bpr]\n\tmul\tebx\n\tmov\tebx,eax\n\tmov\teax,[this]\n\tadd\tebx,[(GraphicViewPort eax).GVPOffset]\n\tpop\teax\n\tpop\tedx\n\tadd\tebx,eax\n\tmov\tedi,ebx\n\tmov\teax,[color]\n\tmov\tah,al\t\t\t; make it a word of color\n\tshr\tecx,1\t\t\t; convert to number of words to write\n\trep\tstosw\t\t\t; write as many words as possible\n\tadc\tecx,ecx\t\t\t; add the carry flag back in\n\trep\tstosb\t\t\t; move odd one if any are odd\n\tjmp\tshort ??out\t\t; get outt\n\n\t;*==================================================================\n\t;* a special case routine for vertical line draws\n\t;*==================================================================\n??vline:\n\tmov\tecx,edx\t\t\t; get length of line to draw\n\tinc\tecx\n\tadd\tebx,eax\n\tmov\teax,[color]\n\n??vl_loop:\n\tmov\t[ebx],al\t\t; store bit\n\tadd\tebx,[bpr]\n\tdec\tecx\n\tjnz\t??vl_loop\n\n??out:\n\tret\n\tENDP\tMCGA_Draw_Line\n\n\nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/DRAWRECT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : DRAWRECT.C                               *\n *                                                                         *\n *                   Programmer : Christopher Yates                        *\n *                                                                         *\n *                  Last Update : August 20, 1993   [JLB]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Draw_Rect -- Draws a rectangle to the LogicPage.                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"gbuffer.h\"\n\n/***************************************************************************\n * Draw_Rect -- Draws a rectangle to the LogicPage.                        *\n *                                                                         *\n *    This routine will draw a rectangle to the LogicPage.  The rectangle  *\n *    doesn't have to be aligned on the vertical or horizontal axis.  In   *\n *    fact, it doesn't even have to be a rectangle.  The \"square\" can be   *\n *    skewed.                                                              *\n *                                                                         *\n * INPUT:   x1_pixel, y1_pixel   -- One corner.                            *\n *                                                                         *\n *          x2_pixel, y2_pixel   -- The other corner.                      *\n *                                                                         *\n *          color                -- The color to draw the lines.           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   None, but the rectangle will be clipped to the current      *\n *             draw line clipping rectangle.                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/20/1993 JLB : Created.                                             *\n *=========================================================================*/\nVOID GraphicViewPortClass::Draw_Rect(int x1_pixel, int y1_pixel, int x2_pixel, int y2_pixel, unsigned char color)\n{\n\tDraw_Line(x1_pixel, y1_pixel, x2_pixel, y1_pixel, color);\n\tDraw_Line(x1_pixel, y2_pixel, x2_pixel, y2_pixel, color);\n\tDraw_Line(x1_pixel, y1_pixel, x1_pixel, y2_pixel, color);\n\tDraw_Line(x2_pixel, y1_pixel, x2_pixel, y2_pixel, color);\n}\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/DRAWRECT.CPP.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : DRAWRECT.C                               *\n *                                                                         *\n *                   Programmer : Christopher Yates                        *\n *                                                                         *\n *                  Last Update : August 20, 1993   [JLB]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Draw_Rect -- Draws a rectangle to the LogicPage.                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"gbuffer.h\"\n\n/***************************************************************************\n * Draw_Rect -- Draws a rectangle to the LogicPage.                        *\n *                                                                         *\n *    This routine will draw a rectangle to the LogicPage.  The rectangle  *\n *    doesn't have to be aligned on the vertical or horizontal axis.  In   *\n *    fact, it doesn't even have to be a rectangle.  The \"square\" can be   *\n *    skewed.                                                              *\n *                                                                         *\n * INPUT:   x1_pixel, y1_pixel   -- One corner.                            *\n *                                                                         *\n *          x2_pixel, y2_pixel   -- The other corner.                      *\n *                                                                         *\n *          color                -- The color to draw the lines.           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   None, but the rectangle will be clipped to the current      *\n *             draw line clipping rectangle.                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/20/1993 JLB : Created.                                             *\n *=========================================================================*/\nVOID GraphicViewPortClass::Draw_Rect(int x1_pixel, int y1_pixel, int x2_pixel, int y2_pixel, unsigned char color)\n{\n\tDraw_Line(x1_pixel, y1_pixel, x2_pixel, y1_pixel, color);\n\tDraw_Line(x1_pixel, y2_pixel, x2_pixel, y2_pixel, color);\n\tDraw_Line(x1_pixel, y1_pixel, x1_pixel, y2_pixel, color);\n\tDraw_Line(x2_pixel, y1_pixel, x2_pixel, y2_pixel, color);\n}\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/FILLQUAD.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : FILLQUAD.ASM                             *\n;*                                                                         *\n;*                   Programmer : Ian M. Leslie                            *\n;*                                                                         *\n;*                   Start Date : August 11, 1994                          *\n;*                                                                         *\n;*                  Last Update : August 30, 1994   [IML]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:\t\t\t\t\t\t\t\t   *\n;*\tFill_Quad -- Flood fills an arbitrary convex quadrilateral\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nSLOT_VACANT\tEQU\t80008000h\nNULL\t\tEQU\t0h\n\n\nCODESEG\n\n;***************************************************************************\n;* VVC::FILL_QUAD -- Flood fills an arbitrary convex quadrilateral\t   *\n;*                                                                         *\n;* INPUT:      \tDWORD this\t- associated graphic viewport\t\t   *\n;*\t\tDWORD span_buff - pointer to span array\t\t\t   *\n;*\t\tDWORD x0_pixel \t- the zeroth x pixel position\t\t   *\n;*\t       \tDWORD y0_pixel\t- the zeroth y pixel position\t\t   *\n;*\t       \tDWORD x1_pixel\t- the first x pixel position\t\t   *\n;*\t       \tDWORD y1_pixel  - the first y pixel position\t\t   *\n;*\t       \tDWORD x2_pixel\t- the second x pixel position\t\t   *\n;*\t       \tDWORD y2_pixel\t- the second y pixel position\t\t   *\n;*\t       \tDWORD x3_pixel\t- the third x pixel position\t\t   *\n;*\t       \tDWORD y3_pixel\t- the third y pixel position\t\t   *\n;*\t\tDWORD color     - the color of the quad to fill\t\t   *\n;*                                                                         *\n;* Bounds Checking: Compares quad points with the graphic viewport it \t   *\n;*\t\t    has been assigned to.\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* Rasterization Rules: FILL_QUAD is designed to be used within a quad\t   *\n;*\t\t\tmesh. There is no pixel overlapping or stitching   *\n;*\t\t\teffects at shared borders. FILL_QUAD is NOT\t   *\n;*                      recommended for isolated quads.                    *                                *\n;* HISTORY:                                                                *\n;*   08/11/1994 IML : Created.\t\t\t\t\t\t   *\n;*   08/26/1994 IML : Various optimizations.\t\t\t\t   *\n;*   08/30/1994 IML : Added rasterization rules for shared borders.\t   *\n;*=========================================================================*\n\tPROC\tMCGA_Fill_Quad C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\n\t;*==================================================================\n\t;* Define the arguments that the function takes.\n\t;*==================================================================\n\tARG\tthis:DWORD\t\t; associated graphic viewport\n\tARG\tspan_buff:DWORD\t\t; pointer to span array\n\tARG\tx0_pixel:DWORD\t\t; the zeroth x pixel position\n\tARG\ty0_pixel:DWORD\t\t; the zeroth y pixel position\n\tARG\tx1_pixel:DWORD\t\t; the first x pixel position\n\tARG\ty1_pixel:DWORD\t\t; the first y pixel position\n\tARG\tx2_pixel:DWORD\t\t; the second x pixel position\n\tARG\ty2_pixel:DWORD\t\t; the second y pixel position\n\tARG\tx3_pixel:DWORD\t\t; the third x pixel position\n\tARG\ty3_pixel:DWORD\t\t; the third y pixel position\n\tARG\tcolor:DWORD\t\t; the color of the quad\n\n\n\t;*==================================================================\t\n\t;* Define the local variables that we will use on the stack.\n\t;*==================================================================\n\tLOCAL\tclip_min_x:DWORD\t; boundary of viewport\n\tLOCAL\tclip_max_x:DWORD\t;\n\tLOCAL\tclip_min_y:DWORD\t;\n\tLOCAL\tclip_max_y:DWORD\t;\n\tLOCAL\tclip_var:DWORD\n\tLOCAL\tleft_clip_base:DWORD:2\t; storage for additional edges\n\tLOCAL\tleft_clip_index:DWORD\t;   generated by clipping\n\tLOCAL\tright_clip_base:DWORD:2\t;\n\tLOCAL\tright_clip_index:DWORD\t;\n\tLOCAL\tscanline_min:DWORD\t; vertical extent of quad\n\tLOCAL\tscanline_max:DWORD\n\tLOCAL\trealignment:DWORD\n\tLOCAL\tbpr:DWORD\t\t; bytes per row of associated buffer\n\t\n\t\n\t;*==================================================================\n\t;* Extract essential GraphicViewPort info.\n\t;*==================================================================\n\tmov\tebx,[this]\t\t\n\tmov\t[clip_min_x],eax\t\n\tmov\t[clip_min_y],eax\t\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\n\tmov\t[clip_max_x],eax\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\n\tmov\t[bpr],eax\n\tmov\teax,[(GraphicViewPort ebx).GVPHeight]\n\tmov\t[clip_max_y],eax\n\t\t\n\n\t;*==================================================================\n\t;* Adjust top and right edges of viewport for rasterization rules.\n\t;*==================================================================\n\tdec\t[clip_max_y]\n\tdec\t[clip_min_y]\n\n\t\n\t;*==================================================================\n\t;* Find the vertical extent of the quad BEFORE clipping.\n\t;* y0_pixel = y0, y1_pixel = y1, y2_pixel = y2, y3_pixel = y3\n\t;*==================================================================\n\tmov\teax,[y0_pixel]\n\tcmp\teax,[y1_pixel]\t\t   \n\tjle\tshort ??y1_not_smaller\n\tmov\teax,[y1_pixel]\n\n??y1_not_smaller:\n\tcmp\teax,[y2_pixel]\n\tjle\tshort ??y2_not_smaller\n\tmov\teax,[y2_pixel]\n\n??y2_not_smaller:\n\tcmp\teax,[y3_pixel]\n\tjle\tshort ??y3_not_smaller\n\tmov\teax,[y3_pixel]\n\n??y3_not_smaller:\n\tcmp\teax,[clip_min_y]\n\tjge\tshort ??no_clamp_min_min\n\tmov\teax,[clip_min_y]\n\n??no_clamp_min_min:\n\tcmp\teax,[clip_max_y]\n\tjle\tshort ??no_clamp_max_min\n\tmov\teax,[clip_max_y]\n\t\t\t\t\t; scanline_min = MIN (y0, y1, y2, y3)\n??no_clamp_max_min:\t\t\t; scanline_min = MAX (scanline_min, clip_min_y)\n\tmov\t[scanline_min],eax\t; scanline_min = MIN (scanline_min, clip_max_y)\n\t\t\t\t\t  \n\tmov\teax,[y0_pixel]\t\t  \n\tcmp\teax,[y1_pixel]\n\tjge\tshort ??y1_not_greater\n\tmov\teax,[y1_pixel]\n\n??y1_not_greater:\n\tcmp\teax,[y2_pixel]\n\tjge\tshort ??y2_not_greater\n\tmov\teax,[y2_pixel]\n\n??y2_not_greater:\n\tcmp\teax,[y3_pixel]\n\tjge\tshort ??y3_not_greater\n\tmov\teax,[y3_pixel]\n\n??y3_not_greater:\n\tcmp\teax,[clip_min_y]\n\tjge\tshort ??no_clamp_min_max\n\tmov\teax,[clip_min_y]\n\n??no_clamp_min_max:\n\tcmp\teax,[clip_max_y]\n\tjle\tshort ??no_clamp_max_max\n\tmov\teax,[clip_max_y]\n\t\t\t\t\t; scanline_max = MAX (y0, y1, y2, y3)\n??no_clamp_max_max:\t\t\t; scanline_max = MAX (scanline_max, clip_min_y)\n\tmov\t[scanline_max],eax\t; scanline_max = MIN (scanline_max, clip_max_y)\n\n\n\t;*==================================================================\n\t;* Initialize memory for spans.\n\t;*==================================================================\n\tsub\teax,[scanline_min]\n\tje\t??abort_fill_quad\t; don't render quads with zero height\n\tmov\tebx,eax\n\tmov\teax,[span_buff]\t\t; check span_buff for NULL ptr\n\tcmp\teax,NULL\n\tje\t??abort_fill_quad\n\tsal\tebx,2\n\t\n??span_initialize_loop:\t\t\t\n\tmov\t[DWORD PTR eax + ebx],SLOT_VACANT\n\tsub\tebx,4\n\tjl\tshort ??exit_span_initialize\n\tmov\t[DWORD PTR eax + ebx],SLOT_VACANT\n\tsub\tebx,4\n     \tjl\tshort ??exit_span_initialize\n\tmov\t[DWORD PTR eax + ebx],SLOT_VACANT\n\tsub\tebx,4\n     \tjl\tshort ??exit_span_initialize\n\tmov\t[DWORD PTR eax + ebx],SLOT_VACANT\n\tsub\tebx,4\n\tjge\tshort ??span_initialize_loop\n\n\n\t;*==================================================================\n\t;* Clip and scan convert the four edges defining the quad.\n\t;*==================================================================\n??exit_span_initialize:\n\tmov\t[left_clip_index],0\n\tmov\t[right_clip_index],0\n\t\n\tmov\teax,[x0_pixel]\n\tmov\tebx,[y0_pixel]\n\tmov\tecx,[x1_pixel]\n\tmov\tedx,[y1_pixel]\n\tcall\tNEAR PTR ??clip_and_scan_convert\n\tmov\teax,[x1_pixel]\n\tmov\tebx,[y1_pixel]\n\tmov\tecx,[x2_pixel]\n\tmov\tedx,[y2_pixel]\n\tcall\tNEAR PTR ??clip_and_scan_convert\n\tmov\teax,[x2_pixel]\n\tmov\tebx,[y2_pixel]\n\tmov\tecx,[x3_pixel]\n\tmov\tedx,[y3_pixel]\n\tcall\tNEAR PTR ??clip_and_scan_convert\n\tmov\teax,[x3_pixel]\n\tmov\tebx,[y3_pixel]\n\tmov\tecx,[x0_pixel]\n\tmov\tedx,[y0_pixel]\n\tcall\tNEAR PTR ??clip_and_scan_convert\n\n\n\t;*==================================================================\n\t;* Scan convert up to 2 additional left and right vertical edges \n\t;* generated by the clipping process.\n\t;*==================================================================\n\tcmp\t[left_clip_index],0\t\t \n\tje\tshort ??no_left_edge\n\tmov\teax,[clip_min_x]\t\t\n\tmov\tebx,[left_clip_base]\n\tmov\tecx,eax\n\tmov\tedx,[left_clip_base + 4]\n\tcall\tNEAR PTR ??scan_convert\n\n??no_left_edge:\n\tcmp\t[right_clip_index],0\n\tje\tshort ??no_right_edge\n\tmov\teax,[clip_max_x]\t\t\n\tmov\tebx,[right_clip_base]\n\tmov\tecx,eax\n\tmov\tedx,[right_clip_base + 4]\n\tcall\tNEAR PTR ??scan_convert\n\n\n\t;*==================================================================\n\t;* Fill the quad with specified color. Use DWORD copies where\n\t;* appropriate.\n\t;*==================================================================\n??no_right_edge:\n\tmov\teax,[this]\n\tmov\tedi,[(GraphicViewPort eax).GVPOffset]\t\n\tmov\teax,[scanline_min]\t\t; eax = scanline_min\n\n\tmov\tebx,[scanline_max]\n\tsub\tebx,[scanline_min]\t\t; ebx = span count\n\n\tmov\tesi,[span_buff]\t\t\t; esi = address of top span\n\n\tmul\t[bpr]\n\tadd\tedi,eax\t\t\t\t; edi = address of top scanline\n\t\t\t\t\t\t;  containing quad\n\tmov\tal,[BYTE PTR color]\t\t; extend pixel color into eax ready\n\tmov\tah,al\t\t\t\t;   for DWORD copies\n\tmov\tedx,eax\t\t\t\t\n\tshl\teax,16\t\t\t\t\n\tmov\tax,dx\t\t\t\t\n\n\tcld\t\t\t\t\t; only fill forwards\n\n\tjmp\t??skip_span\t\t\t; rasterization rule: don't \n\t\t\t\t\t\t;   render topmost span\n\n??quad_fill_loop:\n\tcmp\t[DWORD PTR esi],SLOT_VACANT\t; test for unused spans\tdue to clipping\n\tje\t??skip_span\n\txor\tecx,ecx\n\txor\tedx,edx\n\tmov\tcx,[WORD PTR esi]\n\tmov\tdx,[WORD PTR esi + 2]\n\tsub\tecx,edx\t\t\t\t \n\tpush\tedi\n\tjns\tshort ??not_negative_count\t \n\tadd\tedi,ecx\n\tneg\tecx\t\t\t\t; ecx = span width\n\n??not_negative_count:\n\tadd\tedi,edx\t\t\t\t; edi = address of start of span\n\tcmp\tecx,OPTIMAL_BYTE_COPY\t\t; does span width justify DWORD copies?\n\tjl\tshort ??byte_copy\n\tmov\tedx,ecx\n\tmov\tecx,edi\n\tand\tecx,3\t\t\t\t; if (ecx == 0) edi is already  \n\tjz\tshort ??dword_copy_no_alignment\t;   DWORD aligned\n\txor\tecx,3\n\tinc\tecx\t\t\t\t; ecx = number of pixels before alignment\n\tsub\tedx,ecx\t\t\t\t\n\trep\tstosb\n\n??dword_copy_no_alignment:\n\tmov\tecx,edx\t\t\t\t; ecx = remaining pixels on span \n\tshr\tecx,2\t\t\t\t; copy (ecx / 4) DWORDS\n\trep\tstosd\n\tmov\tecx,edx\t\t\t\t\n\tand\tecx,3\t\t\t\t; ecx = remaining pixels on span\n\n??byte_copy:\n\trep\tstosb\t\t\t\t; byte copy remaining pixels on span\n\tpop\tedi\n\n??skip_span:\n\tadd\tedi,[bpr]\t\t\t; edi = address of start of next scanline\n\tadd\tesi,4\t\t\t\t; esi = address of next span\n\tdec\tebx\n\tjge\tshort ??quad_fill_loop\t\t; is span count >= 0?\n\n??abort_fill_quad:\n\tret\n\n\n\t;*==================================================================\n\t;* This is the section that \"pushes\" the edge into bounds.\n\t;* I have marked the section with PORTABLE start and end to signify\n\t;* how much of this routine is 100% portable between graphics modes.\n\t;* It was just as easy to have variables as it would be for constants\n\t;* so the global vars clip_min_x, clip_min_y, clip_max_x, clip_max_y\n\t;* are used to clip the edge (default is the screen).\n\t;* PORTABLE start.\n\t;*==================================================================\n\n\n\t;*==================================================================\n\t;* Clip an edge against the viewport.\n\t;*==================================================================\n??clip_and_scan_convert:\n\tcall\tNEAR PTR ??set_left_right_bits\t\n\txchg\teax,ecx\t\t\t\t\n\txchg\tebx,edx\t\t\t\t\n\tmov\tedi,esi\n\tcall\tNEAR PTR ??set_left_right_bits\n\tmov\t[clip_var],edi\n\tor\t[clip_var],esi\n\tjz\t??clip_up_down\t\t\t; trivial acceptance?\n\ttest\tedi,esi\n\tjne\t??exit\t\t\t\t; trivial rejection?\n\tshl\tesi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+esi]\t \n\txchg\teax,ecx\n\txchg\tebx,edx\n\tshl\tedi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+edi]\n\n??clip_up_down:\n\tcall\tNEAR PTR ??set_up_down_bits\n\txchg\teax,ecx\n\txchg\tebx,edx\n\tmov\tedi,esi\n\tcall\tNEAR PTR ??set_up_down_bits\n\tmov\t[clip_var],edi\n\tor\t[clip_var],esi\n\tjz\t??scan_convert\t\t\t; trivial acceptance?\n\ttest\tedi,esi\n\tjne\t??exit\t\t\t\t; trivial rejection?\n\tshl\tesi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+esi]\n\txchg\teax,ecx\n\txchg\tebx,edx\n\tshl\tedi,2\n\tcall\t[DWORD PTR cs:??clip_tbl+edi]\n\tjmp\t??scan_convert\n\n\n\t;*==================================================================\n\t;* Subroutine table for clipping conditions.\n\t;*==================================================================\n??clip_tbl\tDD\t??nada,??a_lft,??a_rgt,??nada\n\t\tDD\t??a_up,??nada,??nada,??nada\n\t\tDD\t??a_dwn\n\n\t\t\n\t;*==================================================================\n\t;* Subroutines for clipping conditions.\n\t;*==================================================================\t\n??nada:\n\tretn\n\n??a_up:\n\tmov\tesi,[clip_min_y]\n\tcall\tNEAR PTR ??clip_vert\n\tretn\n\n??a_dwn:\n\tmov\tesi,[clip_max_y]\n\tcall\tNEAR PTR ??clip_vert\n\tretn\n\n??a_lft:\n\tmov\tesi,[clip_min_x]\n\tcall\tNEAR PTR ??clip_horiz\n\tpush\tebx\n\tmov\tesi,[left_clip_index]\n\tcmp\tebx,[clip_min_y]\n\tjge\t??no_left_min_clip\n\tmov\tebx,[clip_min_y]\n\n??no_left_min_clip:\n\tcmp\tebx,[clip_max_y]\n\tjle\t??no_left_max_clip\n\tmov\tebx,[clip_max_y]\n\n??no_left_max_clip:\n\tmov\t[left_clip_base + esi],ebx\t; a left edge will be generated\n\tmov\t[left_clip_index],4\t\t;   store off yb\n\tpop\tebx\n\tretn\n\n??a_rgt:\n\tmov\tesi,[clip_max_x]\n\tcall\tNEAR PTR ??clip_horiz\n\tpush\tebx\n\tmov\tesi,[right_clip_index]\n\tcmp\tebx,[clip_min_y]\n\tjge\t??no_right_min_clip\n\tmov\tebx,[clip_min_y]\n\n??no_right_min_clip:\n\tcmp\tebx,[clip_max_y]\n\tjle\t??no_right_max_clip\n\tmov\tebx,[clip_max_y]\n\n??no_right_max_clip:\n\tmov\t[right_clip_base + esi],ebx\t; a right edge will be generated\n\tmov\t[right_clip_index],4\t\t;   store off yb\n\tpop\tebx\n\tretn\n\n\n\t;*==================================================================\n\t;* Clip a line against a horizontal edge at clip_y.\n\t;* (eax,ebx) = (xa,ya), (ecx,edx) = (xb,yb)\n\t;* xa' = xa+[(clip_y-ya)(xb-xa)/(yb-ya)]\n\t;* ya' = clip_y\n\t;*==================================================================\n??clip_vert:\n\tpush\tedx\n\tpush\teax\n\tmov\t[clip_var],edx\t\t; clip_var = yb\n\tsub\t[clip_var],ebx\t\t; clip_var = (yb-ya)\n\tneg\teax\t\t\t; eax = -xa\n\tadd\teax,ecx\t\t\t; eax = (xb-xa)\n\tmov\tedx,esi\t\t\t; edx = clip_y\n\tsub\tedx,ebx\t\t\t; edx = (clip_y-ya)\n\timul\tedx\t\t\t; eax = (clip_y-ya)(xb-xa)\n\tidiv\t[clip_var]\t\t; eax = (clip_y-ya)(xb-xa)/(yb-ya)\n\tpop\tedx\n\tadd\teax,edx\t\t\t; eax = xa+[(clip_y-ya)(xb-xa)/(yb-ya)]\n\tpop\tedx\n\tmov\tebx,esi\t\t\t; ebx =\tclip_y\n\tretn\n\n\n\t;*==================================================================\n\t;* Clip a line against a vertical edge at clip_x.\n\t;* (eax,ebxx) = (xa,ya), (ecx,edxx) = (xb,yb)\n\t;* ya' = ya+[(clip_x-xa)(yb-ya)/(xb-xa)]\n\t;* xa' = clip_x\n\t;*==================================================================\n??clip_horiz:\n\tpush\tedx\n\tmov\t[clip_var],ecx\t\t; clip_var = xb\n\tsub\t[clip_var],eax\t\t; clip_var = (xb-xa)\n\tsub\tedx,ebx\t\t\t; edx = (yb-ya)\n\tneg\teax\t\t\t; eax = -xa\n\tadd\teax,esi\t\t\t; eax = (clip_x-xa)\n\timul\tedx\t\t\t; eax = (clip_x-xa)(yb-ya)\n\tidiv\t[clip_var]\t\t; eax = (clip_x-xa)(yb-ya)/(xb-xa)\n\tadd\tebx,eax\t\t\t; ebx = ya+[(clip_x-xa)(yb-ya)/(xb-xa)]\n\tpop\tedx\n\tmov\teax,esi\t\t\t; eax = clip_x\n\tretn\n\n\n\t;*==================================================================\n\t;* Set the condition bits for the subroutine table.\n\t;*==================================================================\n??set_left_right_bits:\n\txor\tesi,esi\n\tcmp\teax,[clip_min_x]   \t; if x >= left its not left\n\tjge\tshort ??a_not_left\n\tor\tesi,1\n\n??a_not_left:\n\tcmp\teax,[clip_max_x]\t; if x <= right its not right\n\tjle\tshort ??a_not_right\n\tor\tesi,2\n\n??a_not_right:\n\tretn\t\n\n??set_up_down_bits:\n\txor\tesi,esi\n\tcmp\tebx,[clip_min_y]\t; if y >= top its not up\n\tjge\tshort ??a_not_up\n\tor\tesi,4\n\n??a_not_up:\n\tcmp\tebx,[clip_max_y]\t; if y <= bottom its not down\n\tjle\tshort ??a_not_down\n\tor\tesi,8\n\n??a_not_down:\n\tretn\n\n\n\t;*==================================================================\n\t;* PORTABLE end.\n\t;*==================================================================\n\t\n\t;*==================================================================\n\t;* Scan convert an edge.\n\t;* (eax,ebx) = (xa,ya), (ecx,edx) = (xb,yb)\n\t;*==================================================================\n??scan_convert:\n\tcmp\tebx,edx\t\t\t \n\tje\t??exit\t\t       \t\t; if (ya == yb) don't scan convert \n\tjl\tshort ??no_swap\t\t\t; if (ya < yb)  swap vertices\n\txchg\teax,ecx\n\txchg\tebx,edx\n\n??no_swap:\n\tsub\tedx,ebx \t\t\t; edx = (yb - ya)\n\tsub\tebx,[scanline_min]\t\n\tsal\tebx,2\n\tadd\tebx,[span_buff]\t\t\t; ebx = span_buff + 4(ya - clip_min_y)\n\tsub\tecx,eax\t\t\t\t; ecx = (xb - xa)\n\tje\t??v_scan\t\t\t; if the edge is vertical use a\n\t\t\t\t\t\t;  special case routine\n\tpush\teax\t\t\t\t\n\tmov\teax,ecx\t\t\t\t; eax = (xb - xa)\n\tmov\tecx,edx\t\t\t\t; ecx = (yb - ya)\n\tsal\tedx,1\n\tmov\t[realignment],edx\t\t; realignment = 2(yb - ya)\n\tcwd\n\tidiv\tcx\n\tcwde\n\tmovsx\tedx,dx\n\tmov\tedi,eax\t\t\t\t; edi = (xb - xa) / (yb - ya)\n\tmov\tesi,edx\n\tmov\tedx,ecx\t\t\t \n\tpop\teax\t\t\t\t; eax = xa\n\tneg\tedx\t\t\t\t; edx = -(yb - ya)\n\tsal\tesi,1\t\t\t\t; esi = 2[(xb - xa) % (yb - ya)]\n\tjns\tshort ??r_scan\t\t\t; scan to the left or right?\n\tneg\tesi\n\n\t;*==================================================================\n\t;* Edge scan conversion DDA moving down and to the left.\n\t;* eax = xpos, ebx = span to reference \n\t;*==================================================================\n\tcmp\tebx,[span_buff]\n\tjg\t??l_scan_convert\n\n??l_scan_convert_loop:\n\tcmp\t[DWORD PTR ebx],SLOT_VACANT    ; if the left slot of span is \n\tjne\tshort ??l_next_slot\t       ;   vacant fill it with xpos\n\tmov\t[ebx],ax\t\t\n\n??l_next_slot:\n\tmov\t[ebx + 2],ax\t\t       ; otherwise fill the right slot\n\t\t\t\t\t       ;   with xpos\n??l_scan_convert:\n\tdec\tecx\n\tjl\tshort ??exit\n\tadd\tebx,4\n\tadd\teax,edi\n\tadd\tedx,esi\n\tjle\tshort ??l_scan_convert_loop\n\tdec\teax\n\tsub\tedx,[realignment]\n\tjmp\t??l_scan_convert_loop\n\t\n\n\t;*==================================================================\n\t;* Edge scan conversion DDA moving down and to the right.\n\t;* eax = xpos, ebx = span to reference\n\t;*==================================================================\n??r_scan:\n\tcmp\tebx,[span_buff]\n\tjg\t??r_scan_convert\n\n??r_scan_convert_loop:\n\tcmp\t[DWORD PTR ebx],SLOT_VACANT    ; if the left slot of span is\n\tjne\tshort ??r_next_slot\t       ;   vacant fill it with xpos\n\tmov\t[ebx],ax\t\t\n\n??r_next_slot:\n\tmov\t[ebx + 2],ax\t\t       ; otherwise fill the right slot\n\t\t\t\t\t       ;   with xpos\n??r_scan_convert:\n\tdec\tecx\n\tjl\tshort ??exit\n\tadd\tebx,4\n\tadd\teax,edi\n\tadd\tedx,esi\n\tjle\tshort ??r_scan_convert_loop\n\tinc\teax\n\tsub\tedx,[realignment]\n\tjmp\t??r_scan_convert_loop\n\n\n\t;*==================================================================\n\t;* Scan convert a vertical edge.\n\t;* eax = xpos, ebx = span to reference\n\t;*==================================================================\n??v_scan:\n\tcmp\tebx,[span_buff]\n\tjg\t??v_scan_convert\n\n??v_scan_convert_loop:\n\tcmp\t[DWORD PTR ebx],SLOT_VACANT   ; if the left slot of span is\n \tjne\tshort ??v_next_slot\t      ;   vacant fill it with xpos\n\tmov\t[ebx],ax\n\n??v_next_slot:\n\tmov\t[ebx + 2],ax\t\t      ; otherwise fill the right slot\n\t\t\t\t\t      ;   with xpos\n??v_scan_convert:\n\tadd\tebx,4\n\tdec\tedx\n\tjge\t??v_scan_convert_loop\n\n??exit:\n\tretn\n\n\tENDP\tMCGA_Fill_Quad\n\nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/FILLRECT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Clear the Full Mcga Screen\t\t   *\n;*                                                                         *\n;*                    File Name : CLEAR.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : June 7, 1994   [PWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVPC::Clear -- Clears a virtual viewport instance                     *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n;***************************************************************************\n;* GVPC::FILL_RECT -- Fills a rectangular region of a graphic view port\t   *\n;*                                                                         *\n;* INPUT:\tWORD the left hand x pixel position of region\t\t   *\n;*\t\tWORD the upper x pixel position of region\t\t   *\n;*\t\tWORD the right hand x pixel position of region\t\t   *\n;*\t\tWORD the lower x pixel position of region\t\t   *\n;*\t\tUBYTE the color (optional) to clear the view port to\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* NOTE:\tThis function is optimized to handle viewport with no XAdd *\n;*\t\tvalue.  It also handles DWORD aligning the destination\t   *\n;*\t\twhen speed can be gained by doing it.\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/07/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tMCGA_Fill_Rect C near \n\tUSES\teax,ebx,ecx,edx,esi,edi,ebp\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG    \tthis:DWORD\t\t\t; this is a member function\n\tARG\tx1_pixel:WORD\n\tARG\ty1_pixel:WORD\n\tARG\tx2_pixel:WORD\n\tARG\ty2_pixel:WORD\n\tARG    \tcolor:BYTE\t\t\t; what color should we clear to\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL\tVPwidth:DWORD\t\t; the width of the viewport\n\tLOCAL\tVPheight:DWORD\t\t; the height of the viewport\n\tLOCAL\tVPxadd:DWORD\t\t; the additional x offset of viewport\n\tLOCAL\tVPbpr:DWORD\t\t; the number of bytes per row of viewport\n\n\t;*===================================================================\n\t;* save off the viewport characteristics on the stack\n\t;*===================================================================\n\tmov\tebx,[this]\t\t\t\t; get a pointer to viewport\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\t; get width from viewport\n\tmov\tecx,[(GraphicViewPort ebx).GVPHeight]\t; get height from viewport\n\tmov\tedx,[(GraphicViewPort ebx).GVPXAdd]\t; get xadd from viewport\n\tmov\t[VPwidth],eax\t\t\t\t; store the width of locally\n\tmov\t[VPheight],ecx\n\tmov\t[VPxadd],edx\n\tadd\teax,edx\n\tmov\t[VPbpr],eax\n\n\t;*===================================================================\n\t;* move the important parameters into local registers\n\t;*===================================================================\n\tmovsx\teax,[x1_pixel]\t\t\t\t\n\tmovsx\tebx,[y1_pixel]\t\t\t\t\n\tmovsx\tecx,[x2_pixel]\t\t\t\t\n\tmovsx\tedx,[y2_pixel]\n\n\t;*===================================================================\n\t;* Convert the x2 and y2 pixel to a width and height\n\t;*===================================================================\n\tcmp\teax,ecx\n\tjl\t??no_swap_x\n\txchg\teax,ecx\n\n??no_swap_x:\n\tsub\tecx,eax\n\tcmp\tebx,edx\n\tjl\t??no_swap_y\n\txchg\tebx,edx\n??no_swap_y:\n\tsub\tedx,ebx\n\tinc\tecx\n\tinc\tedx\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\tcmp\teax, [VPwidth]\t\t\t; compare with the max\n\tjge\t??out\t\t\t\t; starts off screen, then later\n\tjb\tshort ??sx_done\t\t\t; if it's not negative, it's ok\n\n\t;------ Clip source X to left edge of screen.\n\tadd\tecx, eax\t\t\t; Reduce width (add in negative src X).\n\txor\teax, eax\t\t\t; Clip to left of screen.\n??sx_done:\n\n\t;*===================================================================\n\t;* Bounds check source Y.\n\t;*===================================================================\n\tcmp\tebx, [VPheight]\t\t\t; compare with the max\n\tjge\t??out\t\t\t\t; starts off screen, then later\n\tjb\tshort ??sy_done\t\t\t; if it's not negative, it's ok\n\n\t;------ Clip source Y to top edge of screen.\n\tadd\tedx, ebx\t\t\t; Reduce height (add in negative src Y).\n\txor\tebx, ebx\t\t\t; Clip to top of screen.\n\n??sy_done:\n\t;*===================================================================\n\t;* Bounds check width versus width of source and dest view ports\n\t;*===================================================================\n\tpush\tebx\t\t\t\t; save off ebx for later use\n\tmov\tebx,[VPwidth]\t\t\t; get the source width\n\tsub\tebx, eax\t\t\t; Maximum allowed pixel width (given coordinates).\n\tsub\tebx, ecx\t\t\t; Pixel width undershoot.\n\tjns\tshort ??width_ok\t\t; if not signed no adjustment necessary\n\tadd\tecx, ebx\t\t\t; Reduce width to screen limits.\n\n??width_ok:\n\tpop\tebx\t\t\t\t; restore ebx to old value\n\n\t;*===================================================================\n\t;* Bounds check height versus height of source view port\n\t;*===================================================================\n\tpush\teax\t\t\t\t; save of eax for later use\n\tmov\teax, [VPheight]\t\t\t; get the source height\n\tsub\teax, ebx\t\t\t; Maximum allowed pixel height (given coordinates).\n\tsub\teax, edx\t\t\t; Pixel height undershoot.\n\tjns\tshort ??height_ok\t\t; if not signed no adjustment necessary\n\tadd\tedx, eax\t\t\t; Reduce height to screen limits.\n??height_ok:\n\tpop\teax\t\t\t\t; restore eax to old value\n\n\t;*===================================================================\n\t;* Perform the last minute checks on the width and height\n\t;*===================================================================\n\tor\tecx,ecx\n\tjz\t??out\n\n\tor\tedx,edx\n\tjz\t??out\n\n\tcmp\tecx,[VPwidth]\n\tja\t??out\n\tcmp\tedx,[VPheight]\n\tja\t??out\n\t\n\t;*===================================================================\n\t;* Get the offset into the virtual viewport.\n\t;*===================================================================\n\txchg\tedi,eax\t\t\t; save off the contents of eax\n\txchg\tesi,edx\t\t\t;   and edx for size test\n\tmov\teax,ebx\t\t\t; move the y pixel into eax\n\tmul\t[VPbpr]\t\t\t; multiply by bytes per row\n\tadd\tedi,eax\t\t\t; add the result into the x position\n\tmov\tebx,[this]\t\t\n\tadd\tedi,[(GraphicViewPort ebx).GVPOffset]\n\n\tmov\tedx,esi\t\t\t; restore edx back to real value\n\tmov\teax,ecx\t\t\t; store total width in ecx\n\tsub\teax,[VPwidth]\t\t; modify xadd value to include clipped\n\tsub\t[VPxadd],eax\t\t;   width bytes (subtract a negative number)\n\n\t;*===================================================================\n\t; Convert the color byte to a DWORD for fast storing\n\t;*===================================================================\n\tmov\tal,[color]\t\t\t\t; get color to clear to\n\tmov\tah,al\t\t\t\t\t; extend across WORD\n\tmov\tebx,eax\t\t\t\t\t; extend across DWORD in\n\tshl\teax,16\t\t\t\t\t;   several steps\n\tmov\tax,bx\t\t\n\n\t;*===================================================================\n\t; If there is no row offset then adjust the width to be the size of \n\t;   the entire viewport and adjust the height to be 1\n\t;*===================================================================\n\tmov\tesi,[VPxadd]\n\tor\tesi,esi\t\t\t\t\t; set the flags for esi\n\tjnz\t??row_by_row_aligned\t\t\t;   and act on them\n\n\txchg\teax,ecx\t\t\t\t\t; switch bit pattern and width\n\tmul\tedx\t\t\t\t\t; multiply by edx to get size\n\txchg\teax,ecx\t\t\t\t\t; switch size and bit pattern\n\tmov\tedx,1\t\t\t\t\t; only 1 line off view port size to do\n\n\t;*===================================================================\n\t; Find out if we should bother to align the row.\n\t;*===================================================================\n??row_by_row_aligned:\n\tmov\tebp,ecx\t\t\t\t\t; width saved in ebp\n\tcmp\tecx,OPTIMAL_BYTE_COPY\t\t\t; is it worth aligning them?\n\tjl\t??row_by_row\t\t\t\t;   if not then skip\n\n\t;*===================================================================\n\t; Figure out the alignment offset if there is any\n\t;*===================================================================\n\tmov\tebx,edi\t\t\t\t\t; get output position\n\tand\tebx,3\t\t\t\t\t;   is there a remainder?\n\tjz\t??aligned_loop\t\t\t\t;   if not we are aligned\n\txor\tebx,3\t\t\t\t\t; find number of align bytes\n\tinc\tebx\t\t\t\t\t; this number is off by one\n\tsub\tebp,ebx\t\t\t\t\t; subtract from width\n\n\t;*===================================================================\n\t; Now that we have the alignment offset copy each row\n\t;*===================================================================\n??aligned_loop:\n\tmov\tecx,ebx\t\t\t\t\t; get number of bytes to align\n\trep\tstosb\t\t\t\t\t;   and move them over\n\tmov\tecx,ebp\t\t\t\t\t; get number of aligned bytes\n\tshr\tecx,2\t\t\t\t\t;   convert to DWORDS\n\trep\tstosd\t\t\t\t\t;   and move them over\n\tmov\tecx,ebp\t\t\t\t\t; get number of aligned bytes\n\tand\tecx,3\t\t\t\t\t;   find the remainder\n\trep\tstosb\t\t\t\t\t;   and move it over\n\tadd\tedi,esi\t\t\t\t\t; fix the line offset\n\tdec\tedx\t\t\t\t\t; decrement the height\n\tjnz\t??aligned_loop\t\t\t\t; if more to do than do it\n\tjmp\t??exit\t\t\t\t\t; we are all done\n\n\t;*===================================================================\n\t; If not enough bytes to bother aligning copy each line across a byte\n\t;    at a time.\n\t;*===================================================================\n??row_by_row:\n\tmov\tecx,ebp\t\t\t\t\t; get total width in bytes\n\trep\tstosb\t\t\t\t\t; store the width\n\tadd\tedi,esi\t\t\t\t\t; handle the xadd\n\tdec\tedx\t\t\t\t\t; decrement the height\n\tjnz\t??row_by_row\t\t\t\t; if any left then next line\n??out:\n??exit:\n\tret\n\tENDP\tMCGA_Fill_Rect\n\t\nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/GBUFFER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : GBUFFER.CPP                              *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 3, 1994                              *\n *                                                                         *\n *                  Last Update : February 23, 1995   [PWG]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   VVPC::VirtualViewPort -- Default constructor for a virtual viewport   *\n *   VVPC:~VirtualViewPortClass -- Destructor for a virtual viewport       *\n *   VVPC::Clear -- Clears a graphic page to correct color                 *\n *   VBC::VideoBufferClass -- Lowlevel constructor for video buffer class  *\n *   GVPC::Change -- Changes position and size of a Graphic View Port      *\n *   VVPC::Change -- Changes position and size of a Video View Port      \t*\n *   Set_Logic_Page -- Sets LogicPage to new buffer                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef GBUFFER_H\n#include \"gbuffer.h\"\n#endif\n#pragma inline\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n\n/***************************************************************************\n * GVPC::GRAPHICVIEWPORTCLASS -- Constructor for basic view port class     *\n *                                                   m                      *\n * INPUT:\t\tGraphicBufferClass * gbuffer\t- buffer to attach to\t\t\t*\n *\t\t\t\t\tint x\t\t\t\t\t\t\t\t- x offset into buffer\t\t\t*\n *\t\t\t\t\tint y\t\t\t\t\t\t\t\t- y offset into buffer\t\t\t*\n *\t\t\t\t\tint w\t\t\t\t\t\t\t\t- view port width in pixels   *\n *\t\t\t\t\tint h   \t\t\t\t\t\t\t- view port height in pixels\t*\n *                                                                         *\n * OUTPUT:     Constructors may not have a return value\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/09/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicViewPortClass::GraphicViewPortClass(GraphicBufferClass *gbuffer, int x, int y, int w, int h)\n{\n\tAttach(gbuffer, x, y, w, h);\n}\n\n/***************************************************************************\n * GVPC::GRAPHICVIEWPORTCLASS -- Default constructor for view port class   *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/09/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicViewPortClass::GraphicViewPortClass(void)\n{\n}\n\n/***************************************************************************\n * GVPC::~GRAPHICVIEWPORTCLASS -- Destructor for GraphicViewPortClass\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     A destructor may not return a value.                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/10/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicViewPortClass::~GraphicViewPortClass(void)\n{\n}\n\n/***************************************************************************\n * GVPC::ATTACH -- Attaches a viewport to a buffer class                   *\n *                                                                         *\n * INPUT:\t\tGraphicBufferClass *g_buff\t- pointer to gbuff to attach to  *\n *\t\t\t\t\tint x                     - x position to attach to\t\t\t*\n *\t\t\t\t\tint y \t\t\t\t\t\t\t- y position to attach to\t\t\t*\n *\t\t\t\t\tint w\t\t\t\t\t\t\t- width of the view port\t\t\t*\n *\t\t\t\t\tint h\t\t\t\t\t\t\t- height of the view port\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/10/1994 PWG : Created.                                             *\n *=========================================================================*/\nvoid GraphicViewPortClass::Attach(GraphicBufferClass *gbuffer, int x, int y, int w, int h)\n{\n\t/*======================================================================*/\n\t/* Verify that the x and y coordinates are valid and placed within the\t*/\n\t/*\t\tphysical buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (x < 0) \t\t\t\t\t\t\t\t\t\t// you cannot place view port off\n\t\tx = 0;\t\t\t\t\t\t\t\t\t\t//\t\tthe left edge of physical buf\n\tif (x >= gbuffer->Get_Width())\t\t\t// you cannot place left edge off\n\t\tx = gbuffer->Get_Width() - 1;\t\t\t//\t\tthe right edge of physical buf\n\tif (y < 0) \t\t\t\t\t\t\t\t\t\t// you cannot place view port off\n\t\ty = 0;\t\t\t\t\t\t\t\t\t\t//\t\tthe top edge of physical buf\n\tif (y >= gbuffer->Get_Height()) \t\t\t// you cannot place view port off\n\t\ty = gbuffer->Get_Height() - 1;\t\t//\t\tbottom edge of physical buf\n\n\t/*======================================================================*/\n\t/* Adjust the width and height of necessary\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (x + w > gbuffer->Get_Width()) \t\t// if the x plus width is larger\n\t\tw = gbuffer->Get_Width() - x;\t\t\t//\t\tthan physical, fix width\n\n\tif (y + h > gbuffer->Get_Height()) \t\t// if the y plus height is larger\n\t\th = gbuffer->Get_Height() - y;\t\t//\t\tthan physical, fix height\n\n\t/*======================================================================*/\n\t/* Get a pointer to the top left edge of the buffer.\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n \tOffset \t\t= gbuffer->Get_Offset() + (gbuffer->Get_Width() * y) + x;\n\n\t/*======================================================================*/\n\t/* Copy over all of the variables that we need to store.\t\t\t\t\t\t*/\n\t/*======================================================================*/\n \tXPos\t\t\t= x;\n \tYPos\t\t\t= y;\n \tXAdd\t\t\t= gbuffer->Get_Width() - w;\n \tWidth\t\t\t= w;\n \tHeight\t\t= h;\n \tGraphicBuff = gbuffer;\n}\n\n/***************************************************************************\n * GVPC::CHANGE -- Changes position and size of a Graphic View Port        *\n *                                                                         *\n * INPUT:   \tint the new x pixel position of the graphic view port      *\n *\t\t\t\t\tint the new y pixel position of the graphic view port\t\t*\n *\t\t\t\t\tint the new width of the viewport in pixels\t\t\t\t\t\t*\n *\t\t\t\t\tint the new height of the viewport in pixels\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:  \tBOOL whether the Graphic View Port could be sucessfully     *\n *\t\t\t\t      resized.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:   You may not resize a Graphic View Port which is derived \t\t*\n *\t\t\t\t\t\tfrom a Graphic View Port Buffer, \t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/14/1994 SKB : Created.                                             *\n *=========================================================================*/\nBOOL GraphicViewPortClass::Change(int x, int y, int w, int h)\n{\n\t/*======================================================================*/\n\t/* Can not change a Graphic View Port if it is actually the physical\t\t*/\n\t/*\t   representation of a Graphic Buffer.\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (this == Get_Graphic_Buffer())  {\n\t\treturn(FALSE);\n\t}\n\n\t/*======================================================================*/\n\t/* Since there is no allocated information, just re-attach it to the\t\t*/\n\t/*\t\texisting graphic buffer as if we were creating the\t\t\t\t\t\t*/\n\t/*\t\tGraphicViewPort.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tAttach(Get_Graphic_Buffer(), x, y, w, h);\n\treturn(TRUE);\n}\n\n/***************************************************************************\n * GBC::GRAPHICBUFFERCLASS -- Constructor for fixed size buffers           *\n *                                                                         *\n * INPUT:\t\tlong size\t\t- size of the buffer to create\t\t\t\t\t*\n *\t\t\t\t\tint w\t\t\t- width of buffer in pixels (default = 320)  *\n *\t\t\t\t\tint h\t\t\t- height of buffer in pixels (default = 200) *\n *\t\t\t\t\tvoid *buffer\t- a pointer to the buffer if any (optional)\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/13/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicBufferClass::GraphicBufferClass(long size, int w, int h, void *buffer)\n{\n\tSize\t\t\t= size;\t\t\t\t\t\t\t\t\t// find size of physical buffer\n\n\tif (buffer) {\t\t\t\t\t\t\t\t\t\t\t// if buffer is specified\n\t\tBuffer\t\t= (BYTE *)buffer;\t\t\t\t\t//\t\tpoint to it and mark\n\t\tAllocated\t= FALSE;\t\t\t\t\t\t\t\t//\t\tit as user allocated\n\t} else {\n\t\tBuffer\t\t= new BYTE[Size];\t\t\t\t\t// otherwise allocate it and\n\t\tAllocated\t= TRUE;\t\t\t\t\t\t\t\t//\t\tmark it system alloced\n\t}\n\n\tOffset\t\t= (long)Buffer;\t\t\t\t\t\t// Get offset to the buffer\n\tWidth\t\t\t= w;\t\t\t\t\t\t\t\t\t\t// Record width of Buffer\n\tHeight\t\t= h;\t\t\t\t\t\t\t\t\t\t// Record height of Buffer\n\tXAdd\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XAdd of Buffer\n\tXPos\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XPos of Buffer\n\tYPos\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record YPos of Buffer\n\tGraphicBuff\t= this;\t\t\t\t\t\t\t\t\t// Get a pointer to our self\n}\n/*=========================================================================*\n * GBC::GRAPHICBUFFERCLASS -- inline constructor for GraphicBufferClass\t\t*\n *                                                                         *\n * INPUT:\t\tint w\t\t\t- width of buffer in pixels (default = 320)  *\n *\t\t\t\t\tint h\t\t\t- height of buffer in pixels (default = 200) *\n *\t\t\t\t\tvoid *buffer\t- a pointer to the buffer if any (optional)\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicBufferClass::GraphicBufferClass(int w, int h, void *buffer)\n{\n\tSize\t\t\t= w * h;\t\t\t\t\t\t\t\t\t// find size of physical buffer\n\n\tif (buffer) {\t\t\t\t\t\t\t\t\t\t\t// if buffer is specified\n\t\tBuffer\t\t= (BYTE *)buffer;\t\t\t\t\t//\t\tpoint to it and mark\n\t\tAllocated\t= FALSE;\t\t\t\t\t\t\t\t//\t\tit as user allocated\n\t} else {\n\t\tBuffer\t\t= new BYTE[Size];\t\t\t\t\t// otherwise allocate it and\n\t\tAllocated\t= TRUE;\t\t\t\t\t\t\t\t//\t\tmark it system alloced\n\t}\n\n\tOffset\t\t= (long)Buffer;\t\t\t\t\t\t// Get offset to the buffer\n\tWidth\t\t\t= w;\t\t\t\t\t\t\t\t\t\t// Record width of Buffer\n\tHeight\t\t= h;\t\t\t\t\t\t\t\t\t\t// Record height of Buffer\n\tXAdd\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XAdd of Buffer\n\tXPos\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XPos of Buffer\n\tYPos\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record YPos of Buffer\n\tGraphicBuff\t= this;\t\t\t\t\t\t\t\t\t// Get a pointer to our self\n}\n/*=========================================================================*\n * GBC::~GRAPHICBUFFERCLASS -- Destructor for the graphic buffer class     *\n *                                                                         *\n *\tINPUT:\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1994 PWG : Created.                                             *\n *=========================================================================*/\nGraphicBufferClass::~GraphicBufferClass()\n{\n}\n\n\n\n/***************************************************************************\n * SET_LOGIC_PAGE -- Sets LogicPage to new buffer                          *\n *                                                                         *\n * INPUT:\t\tGraphicBufferClass * the buffer we are going to set         *\n *                                                                         *\n * OUTPUT:     GraphicBufferClass * the previous buffer type\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nGraphicBufferClass *Set_Logic_Page(GraphicBufferClass *ptr)\n{\n\tGraphicBufferClass *old = LogicPage;\n\tLogicPage\t\t\t\t\t= ptr;\n\treturn(old);\n}\n\n/***************************************************************************\n * SET_LOGIC_PAGE -- Sets LogicPage to new buffer                          *\n *                                                                         *\n * INPUT:\t\tGraphicBufferClass & the buffer we are going to set         *\n *                                                                         *\n * OUTPUT:     GraphicBufferClass * the previous buffer type\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nGraphicBufferClass *Set_Logic_Page(GraphicBufferClass &ptr)\n{\n\tGraphicBufferClass *old = LogicPage;\n\tLogicPage\t\t\t\t\t= &ptr;\n\treturn(old);\n}\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/GBUFFER.CPP.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : GBUFFER.H                                *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 26, 1994                             *\n *                                                                         *\n *                  Last Update : January 17, 1995   [PWG]                 *\n *                                                                         *\n ***************************************************************************\n *                                                                         *\n *\tThis module contains the definition for the graphic buffer class.  The\t*\n * primary functionality of the graphic buffer class is handled by inline\t*\n * functions that make a call through function pointers to the correct\t\t*\n * routine.  This has two benefits:\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t1) C++ name mangling is not a big deal since the function pointers\t*\n *\t\t   point to functions in standard C format.\t\t\t\t\t\t\t\t\t*\n *\t\t2) The function pointers can be changed when we set a different\t\t*\n *       graphic mode.  This allows us to have both supervga and mcga\t\t*\n *\t\t\troutines present in memory at once.\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * In the basic library, these functions point to stub routines which just\t*\n * return.  This makes a product that just uses a graphic buffer take the\t*\n * minimum amount of code space.  For programs that require MCGA or VESA\t*\n * support, all that is necessary to do is link either the MCGA or VESA\t\t*\n * specific libraries in, previous to WWLIB32.  The linker will then \t\t*\n * overide the the necessary stub functions automatically.\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * In addition, there are helpful inline function calls for parameter\t\t*\n * ellimination.  This header file gives the defintion for all\t\t\t\t\t*\n * GraphicViewPort and GraphicBuffer classes.  \t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Terminology:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tBuffer Class - A class which consists of a pointer to an allocated\t\t* \n *\t\tbuffer and the size of the buffer that was allocated.\t\t\t\t\t\t* \n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n *\tGraphic ViewPort - The Graphic ViewPort defines a window into a \t\t\t*\n *\t\tGraphic Buffer.  This means that although a Graphic Buffer \t\t\t\t*\n *\t\trepresents linear memory, this may not be true with a Graphic\t\t\t*\n *\t\tViewport.  All low level functions that act directly on a graphic\t\t*\n *\t\tviewport are included within this class.  This includes but is not\t*\n *\t\tlimited to most of the functions which can act on a Video Viewport\t*\n *\t\tVideo Buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n * Graphic Buffer - A Graphic Buffer is an instance of an allocated buffer\t* \n *\t\tused to represent a rectangular region of graphics memory.\t\t\t\t*\n *\t\tThe HidBuff\tand BackBuff are excellent examples of a Graphic Buffer.\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n * Below is a tree which shows the relationship of the VideoBuffer and \t\t*\n * Buffer classes to the GraphicBuffer class:\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t  BUFFER.H\t\t\t\t GBUFFER.H\t\t\t  BUFFER.H\t\t\t\t VBUFFER.H\t*\n *  ----------          ----------         ----------          ----------\t*\n * |  Buffer  |        | Graphic  |       |  Buffer  |        |  Video   |\t*\n * |  Class   |        | ViewPort |       |  Class   |        | ViewPort |\t*\n *  ----------          ----------         ----------          ----------\t*\n *            \\        /                             \\        /\t\t\t\t*\n *             \\      /                               \\      /\t\t\t\t\t*\n *            ----------                             ----------\t\t\t\t*\n *           |  Graphic |                           |  Video   |\t\t\t\t*\n *           |  Buffer  |                           |  Buffer  |\t\t\t\t*\n *            ----------                             ---------- \t\t\t\t*\n *\t  \t\t\t  GBUFFER.H\t\t\t                       VBUFFER.H\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   GBC::GraphicBufferClass -- inline constructor for GraphicBufferClass  *\n *   GVPC::Remap -- Short form to remap an entire graphic view port        *\n *   GVPC::Get_XPos -- Returns x offset for a graphic viewport class       *\n *   GVPC::Get_Ypos -- Return y offset in a GraphicViewPortClass           *\n *   VVPC::Get_XPos -- Get the x pos of the VP on the Video                *\n *   VVPC::Get_YPos -- Get the y pos of the VP on the video                *\n *   GBC::Get_Graphic_Buffer -- Get the graphic buffer of the VP.          *\n *   GVPC::Draw_Line -- Stub function to draw line in Graphic Viewport Class*\n *   GVPC::Fill_Rect -- Stub function to fill rectangle in a GVPC          *\n *   GVPC::Remap -- Stub function to remap a GVPC                          *\n *   GVPC::Print -- stub func to print a text string                       *\n *   GVPC::Print -- Stub function to print an integer                      *\n *   GVPC::Print -- Stub function to print a short to a graphic viewport   *\n *   GVPC::Print -- stub function to print a long on a graphic view port   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"window.h\"\n\n#ifndef GBUFFER_H\n#define GBUFFER_H\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n#ifndef MCGAPRIM_H\n#include \"mcgaprim.h\"\n#endif\n\n#ifndef BUFFER_H\n#include \"buffer.h\"\n#endif\n\n#include <stdlib.h>\n\n\n/*=========================================================================*/\n/* Define the screen width and height to make portability to other modules\t*/\n/*\t\teasier.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tDEFAULT_SCREEN_WIDTH\t\t320\n#define\tDEFAULT_SCREEN_HEIGHT\t200\n\n/*=========================================================================*/\n/* Let the compiler know that a GraphicBufferClass exists so that it can\t*/\n/*\t\tkeep a pointer to it in a VideoViewPortClass.\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nclass GraphicViewPortClass;\nclass GraphicBufferClass;\nclass VideoViewPortClass;\nclass VideoBufferClass;\n\nGraphicBufferClass *Set_Logic_Page(GraphicBufferClass *ptr);\nGraphicBufferClass *Set_Logic_Page(GraphicBufferClass &ptr);\n\n/*=========================================================================*/\n/* GraphicViewPortClass - Holds viewport information on a viewport which\t*/\n/*\t\thas been attached to a GraphicBuffer.  A viewport is effectively a\t*/\n/*\t\trectangular subset of the full buffer which is used for clipping and\t*/\n/*\t\tthe like.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tchar\t  \t*Buffer\t-\t\tis the offset to view port buffer\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis the width of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis the height of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis add value to go from the end of a line\t*/\n/*\t\t\t\t\t\t\t\t\t\t\tto the beginning of the next line\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\tx offset into its associated VideoBuffer\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\ty offset into its associated VideoBuffer\t*/\n/*=========================================================================*/\nclass GraphicViewPortClass {\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tGraphicViewPortClass(GraphicBufferClass* graphic_buff, int x, int y, int w, int h);\n\t\tGraphicViewPortClass();\n\t\t~GraphicViewPortClass();\n\n\t\t/*===================================================================*/\n\t\t/* define functions to get at the private data members\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\tGet_Offset(void);\n\t\tint\tGet_Height(void);\n\t\tint\tGet_Width(void);\n\t\tint\tGet_XAdd(void);\n\t\tint\tGet_XPos(void);\n\t\tint\tGet_YPos(void);\n\t\tGraphicBufferClass\t*Get_Graphic_Buffer(void);\n\n\t\tint Lock(void) const {return(TRUE);}\n\t\tvoid Unlock(void) const {}\n\n\t\t/*===================================================================*/\n\t\t/* Define a function which allows us to change a video viewport on\t*/\n\t\t/*\t\tthe fly.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBOOL Change(int x, int y, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the set of common graphic functions that are supported by\t*/\n\t\t/*\t\tboth Graphic ViewPorts and VideoViewPorts.\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\tSize_Of_Region(int w, int h);\n\t\tvoid\tPut_Pixel(int x, int y, unsigned char color);\n\t\tint\tGet_Pixel(int x, int y);\n\t\tvoid\tClear(unsigned char color = 0);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, void *buff, long size);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, BufferClass *buff);\n\t\tlong\tTo_Buffer(BufferClass *buff);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, char *remap);\n\t\tunsigned long\tPrint(char const *string, int x_pixel, int y_pixel, int fcolor, int bcolor);\n\t\tunsigned long\tPrint(short num, int x_pixel, int y_pixel, int fcol, int bcol);\n\t\tunsigned long\tPrint(int num, int x_pixel, int y_pixel, int fcol, int bcol);\n\t\tunsigned long\tPrint(long num, int x_pixel, int y_pixel, int fcol, int bcol);\n\n\t\t/*===================================================================*/\n\t\t/* Define the list of graphic functions which work only with a \t\t*/\n\t\t/*\t\tgraphic buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Draw_Line(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Draw_Rect(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Fill_Rect(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Fill_Quad(VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\tint x2, int y2, int x3, int y3, int color);\n\t\tVOID Remap(int sx, int sy, int width, int height, VOID *remap);\n\t\tVOID Remap(VOID *remap);\n\t\tvoid Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap);\n\t\tvoid Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int clip_window);\n\t\tVOID Grey_Out_Region(int x, int y, int width, int height, int color);\n\tprotected:\n\t\t/*===================================================================*/\n\t\t/* Define functions to attach the viewport to a graphicbuffer\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Attach(GraphicBufferClass *graphic_buff, int x, int y, int w, int h);\n\t\tvoid Attach(GraphicBufferClass *video_buff, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the data used by a GraphicViewPortClass\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\t\t\t\t\t\tOffset;\t\t\t\t\t// offset to graphic page\n\t\tint\t\t\t\t\t\tWidth;\t\t\t\t\t// width of graphic page\n\t\tint\t\t\t\t\t\tHeight;\t\t\t\t\t// height of graphic page\n\t\tint\t\t\t\t\t\tXAdd;\t\t\t\t\t\t// xadd for graphic page (0)\n\t\tint\t\t\t\t\t\tXPos;\t\t\t\t\t\t// x offset in relation to graphicbuff\n\t\tint\t\t\t\t\t\tYPos;\t\t\t\t\t\t// y offset in relation to graphicbuff\n\t\tGraphicBufferClass\t*GraphicBuff;\t\t\t// related graphic buff\n};\n\n/*=========================================================================*/\n/* GraphicBufferClass - A GraphicBuffer refers to an actual instance of an\t*/\n/*\t\tallocated buffer.  The GraphicBuffer may be drawn to directly \t\t\t*/\n/*\t\tbecuase it inherits a ViewPort which represents its physcial size.\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tBYTE\t  \t*Buffer\t-\t\tis the offset to graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis the width of graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis the height of graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis the xadd of graphic buffer\t\t\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\twill be 0 because it is graphicbuff\t\t\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\twill be 0 because it is graphicbuff\t\t\t*/\n/*=========================================================================*/\nclass GraphicBufferClass : public GraphicViewPortClass, public BufferClass {\n\tpublic:\n\t\tGraphicBufferClass(\tlong size = 64500, int w = DEFAULT_SCREEN_WIDTH, int h = DEFAULT_SCREEN_HEIGHT, \n\t\t\t\t\t\t\t\t\tVOID *buffer = 0);\n\t\tGraphicBufferClass(int w, int h, void *buffer = 0);\n\t\t~GraphicBufferClass();\n\n//\t\tvoid Scale_Rotate(BitmapClass &bmp,const TPoint2D &pt,long scale=0x0100,unsigned char angle=0);\n};\n\n/***************************************************************************\n * GVPC::GET_OFFSET -- Get offset for virtual view port class instance     *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long the offset for the virtual viewport instance           *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long GraphicViewPortClass::Get_Offset(void)\n{\n\treturn(Offset);\n}\n\n/***************************************************************************\n * GVPC::GET_HEIGHT -- Gets the height of a virtual viewport instance      *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the height of the virtual viewport instance            *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_Height(void)\n{\n\treturn(Height);\n}\n\n/***************************************************************************\n * GVPC::GET_WIDTH -- Get the width of a virtual viewport instance\t\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the width of the virtual viewport instance             *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_Width(void)\n{\n\treturn(Width);\n}\n\n\n/***************************************************************************\n * GVPC::GET_XADD -- Get the X add offset for virtual viewport instance    *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the xadd for a virtual viewport instance               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_XAdd(void)\n{\t\n\treturn(XAdd);\n}\n/***************************************************************************\n * GVPC::GET_XPOS -- Get the x pos of the VP on the Video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n;*   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_XPos(void)\n{\n\treturn(XPos);\n}\n\n\n/***************************************************************************\n * GVPC::GET_YPOS -- Get the y pos of the VP on the video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n;*   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_YPos(void)\n{\n\treturn(YPos);\n}\n\n/***************************************************************************\n * GVPC::GET_GRAPHIC_BUFFER -- Get the graphic buffer of the VP.            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline GraphicBufferClass *GraphicViewPortClass::Get_Graphic_Buffer(void)\n{\n \treturn (GraphicBuff);\n}\n\n/***************************************************************************\n * GVPC::SIZE_OF_REGION -- stub to call curr graphic mode Size_Of_Region\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/01/1995 BWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::Size_Of_Region(int w, int h)\n{\n\treturn MCGA_Size_Of_Region(this, w, h);\n}\n\n/***************************************************************************\n * GVPC::PUT_PIXEL -- stub to call curr graphic mode Put_Pixel\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tGraphicViewPortClass::Put_Pixel(int x, int y, unsigned char color)\n{\n\tMCGA_Put_Pixel(this, x, y, color);\n}\n\n/***************************************************************************\n * GVPC::GET_PIXEL -- stub to call curr graphic mode Get_Pixel          \t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline int\tGraphicViewPortClass::Get_Pixel(int x, int y)\n{\n\treturn(MCGA_Get_Pixel(this, x, y));\n}\n\n/***************************************************************************\n * GVPC::CLEAR -- stub to call curr graphic mode Clear\t                  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tGraphicViewPortClass::Clear(unsigned char color)\n{\n\tMCGA_Clear(this, color);\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 1 to call curr graphic mode To_Buffer\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(int x, int y, int w, int h, void *buff, long size)\n{\n\treturn(MCGA_To_Buffer(this, x, y, w, h, buff, size));\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 2 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(int x, int y, int w, int h, BufferClass *buff)\n{\n\treturn(MCGA_To_Buffer(this, x, y, w, h, buff->Get_Buffer(), buff->Get_Size()));\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 3 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(BufferClass *buff)\n{\n\treturn(MCGA_To_Buffer(this, 0, 0, Width, Height, buff->Get_Buffer(), buff->Get_Size()));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 1 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans)\n{\n\treturn(Linear_Blit_To_Linear(this, &dest, x_pixel, y_pixel, dx_pixel, dy_pixel, pixel_width, pixel_height, trans));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- Stub 2 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans)\n{\n\treturn(Linear_Blit_To_Linear(this, &dest, 0, 0, dx, dy, Width, Height, trans));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 3 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, BOOL trans)\n{\n\treturn(Linear_Blit_To_Linear(this, &dest, 0, 0, 0, 0, Width, Height, trans));\n}\n\n\n/***************************************************************************\n * GVPC::SCALE -- stub 1 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, trans, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 2 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, FALSE, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 3 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, BOOL trans, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this,\t&dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), trans, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 4 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), FALSE, remap));\n}\n/***************************************************************************\n * GVPC::PRINT -- stub func to print a text string                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/17/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(char const *str, int x, int y, int fcol, int bcol)\n{\n\treturn(MCGA_Print(this, str, x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::PRINT -- Stub function to print an integer                        *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(int num, int x, int y, int fcol, int bcol)\n{\n\tchar str[17];\n\n\t\n\treturn(MCGA_Print(this, itoa(num, str, 10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::PRINT -- Stub function to print a short to a graphic viewport     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(short num, int x, int y, int fcol, int bcol)\n{\n\tchar str[17];\n\n\treturn(MCGA_Print(this, itoa(num, str, 10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::PRINT -- stub function to print a long on a graphic view port     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(long num, int x, int y, int fcol, int bcol)\n{\n\tchar str[33];\n\n\treturn(MCGA_Print(this, ltoa(num, str,10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::DRAW_STAMP -- stub function to draw a tile on a graphic view port *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline void GraphicViewPortClass::Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap)\n{\n\tMCGA_Draw_Stamp(this, icondata, icon, x_pixel, y_pixel, remap);\n}\n\n/***************************************************************************\n * GVPC::DRAW_STAMP -- stub function to draw a tile on a graphic view port *\n *                     This version clips the tile to a window             *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *    07/31/1995 BWG : Created.                                            *\n *=========================================================================*/\ninline void GraphicViewPortClass::Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int clip_window)\n{\n\tMCGA_Draw_Stamp_Clip(this, icondata, icon, x_pixel, y_pixel, remap, WindowList[clip_window][WINDOWX]<<3, WindowList[clip_window][WINDOWY], WindowList[clip_window][WINDOWWIDTH]<<3, WindowList[clip_window][WINDOWHEIGHT]);\n}\n\n/***************************************************************************\n * GVPC::DRAW_LINE -- Stub function to draw line in Graphic Viewport Class *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Draw_Line(int sx, int sy, int dx, int dy, unsigned char color)\n{\n\tMCGA_Draw_Line(this, sx, sy, dx, dy, color);\n}\n\n/***************************************************************************\n * GVPC::FILL_RECT -- Stub function to fill rectangle in a GVPC            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Fill_Rect(int sx, int sy, int dx, int dy, unsigned char color)\n{\n\tMCGA_Fill_Rect(this, sx, sy, dx, dy, color);\n}\n\n\n/***************************************************************************\n * GVPC::REMAP -- Stub function to remap a GVPC                            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Remap(int sx, int sy, int width, int height, VOID *remap)\n{\n\tMCGA_Remap(this, sx, sy, width, height, remap);\n}\ninline VOID GraphicViewPortClass::Fill_Quad(VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\tint x2, int y2, int x3, int y3, int color)\n{\n\tMCGA_Fill_Quad(this, span_buff, x0, y0, x1, y1, x2, y2, x3, y3, color);\n}\n\n/***************************************************************************\n * GVPC::REMAP -- Short form to remap an entire graphic view port          *\n *                                                                         *\n * INPUT:\t\tBYTE * to the remap table to use\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Remap(VOID *remap)\n{\n\tMCGA_Remap(this, 0, 0, Width, Height, remap);\n}\n/*=========================================================================*/\n/* The following BufferClass functions are defined here because they act\t*/\n/*\t\ton graphic viewports.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n\n/***************************************************************************\n * BUFFER_TO_PAGE -- Generic 'c' callable form of Buffer_To_Page           *\n *                                                                         *\n * INPUT: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/12/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long Buffer_To_Page(int x, int y, int w, int h, void *Buffer, GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(x, y, w, h, Buffer, &view));\n}\n\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t*\n *\t\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t*\n *\t\t\t\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int w, int h, GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(0, 0, w, h, Buffer, &view));\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport.  width and height are assumed to be the\t\t\t*\n *\t\t\t\t\t\tviewport's width and height.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(0, 0, view.Get_Width(), view.Get_Height(), Buffer, &view));\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable x, y, w, h *\n *                                                                         *\n * INPUT:\tint\tx\t\t\t- x pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\ty\t\t\t- y pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t\t*\n *\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t\t*\n *\t\t\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\tnone                                                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int x, int y, int w, int h, GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(x, y, w, h, Buffer, &view));\n}\n\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/GBUFFER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 Bit Library\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : GBUFFER.H                                *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : May 26, 1994                             *\n *                                                                         *\n *                  Last Update : January 17, 1995   [PWG]                 *\n *                                                                         *\n ***************************************************************************\n *                                                                         *\n *\tThis module contains the definition for the graphic buffer class.  The\t*\n * primary functionality of the graphic buffer class is handled by inline\t*\n * functions that make a call through function pointers to the correct\t\t*\n * routine.  This has two benefits:\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t1) C++ name mangling is not a big deal since the function pointers\t*\n *\t\t   point to functions in standard C format.\t\t\t\t\t\t\t\t\t*\n *\t\t2) The function pointers can be changed when we set a different\t\t*\n *       graphic mode.  This allows us to have both supervga and mcga\t\t*\n *\t\t\troutines present in memory at once.\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * In the basic library, these functions point to stub routines which just\t*\n * return.  This makes a product that just uses a graphic buffer take the\t*\n * minimum amount of code space.  For programs that require MCGA or VESA\t*\n * support, all that is necessary to do is link either the MCGA or VESA\t\t*\n * specific libraries in, previous to WWLIB32.  The linker will then \t\t*\n * overide the the necessary stub functions automatically.\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * In addition, there are helpful inline function calls for parameter\t\t*\n * ellimination.  This header file gives the defintion for all\t\t\t\t\t*\n * GraphicViewPort and GraphicBuffer classes.  \t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Terminology:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tBuffer Class - A class which consists of a pointer to an allocated\t\t* \n *\t\tbuffer and the size of the buffer that was allocated.\t\t\t\t\t\t* \n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n *\tGraphic ViewPort - The Graphic ViewPort defines a window into a \t\t\t*\n *\t\tGraphic Buffer.  This means that although a Graphic Buffer \t\t\t\t*\n *\t\trepresents linear memory, this may not be true with a Graphic\t\t\t*\n *\t\tViewport.  All low level functions that act directly on a graphic\t\t*\n *\t\tviewport are included within this class.  This includes but is not\t*\n *\t\tlimited to most of the functions which can act on a Video Viewport\t*\n *\t\tVideo Buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n * Graphic Buffer - A Graphic Buffer is an instance of an allocated buffer\t* \n *\t\tused to represent a rectangular region of graphics memory.\t\t\t\t*\n *\t\tThe HidBuff\tand BackBuff are excellent examples of a Graphic Buffer.\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n * Below is a tree which shows the relationship of the VideoBuffer and \t\t*\n * Buffer classes to the GraphicBuffer class:\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t  BUFFER.H\t\t\t\t GBUFFER.H\t\t\t  BUFFER.H\t\t\t\t VBUFFER.H\t*\n *  ----------          ----------         ----------          ----------\t*\n * |  Buffer  |        | Graphic  |       |  Buffer  |        |  Video   |\t*\n * |  Class   |        | ViewPort |       |  Class   |        | ViewPort |\t*\n *  ----------          ----------         ----------          ----------\t*\n *            \\        /                             \\        /\t\t\t\t*\n *             \\      /                               \\      /\t\t\t\t\t*\n *            ----------                             ----------\t\t\t\t*\n *           |  Graphic |                           |  Video   |\t\t\t\t*\n *           |  Buffer  |                           |  Buffer  |\t\t\t\t*\n *            ----------                             ---------- \t\t\t\t*\n *\t  \t\t\t  GBUFFER.H\t\t\t                       VBUFFER.H\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   GBC::GraphicBufferClass -- inline constructor for GraphicBufferClass  *\n *   GVPC::Remap -- Short form to remap an entire graphic view port        *\n *   GVPC::Get_XPos -- Returns x offset for a graphic viewport class       *\n *   GVPC::Get_Ypos -- Return y offset in a GraphicViewPortClass           *\n *   VVPC::Get_XPos -- Get the x pos of the VP on the Video                *\n *   VVPC::Get_YPos -- Get the y pos of the VP on the video                *\n *   GBC::Get_Graphic_Buffer -- Get the graphic buffer of the VP.          *\n *   GVPC::Draw_Line -- Stub function to draw line in Graphic Viewport Class*\n *   GVPC::Fill_Rect -- Stub function to fill rectangle in a GVPC          *\n *   GVPC::Remap -- Stub function to remap a GVPC                          *\n *   GVPC::Print -- stub func to print a text string                       *\n *   GVPC::Print -- Stub function to print an integer                      *\n *   GVPC::Print -- Stub function to print a short to a graphic viewport   *\n *   GVPC::Print -- stub function to print a long on a graphic view port   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"window.h\"\n\n#ifndef GBUFFER_H\n#define GBUFFER_H\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n#ifndef MCGAPRIM_H\n#include \"mcgaprim.h\"\n#endif\n\n#ifndef BUFFER_H\n#include \"buffer.h\"\n#endif\n\n#include <stdlib.h>\n\n\n/*=========================================================================*/\n/* Define the screen width and height to make portability to other modules\t*/\n/*\t\teasier.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tDEFAULT_SCREEN_WIDTH\t\t320\n#define\tDEFAULT_SCREEN_HEIGHT\t200\n\n/*=========================================================================*/\n/* Let the compiler know that a GraphicBufferClass exists so that it can\t*/\n/*\t\tkeep a pointer to it in a VideoViewPortClass.\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nclass GraphicViewPortClass;\nclass GraphicBufferClass;\nclass VideoViewPortClass;\nclass VideoBufferClass;\n\nGraphicBufferClass *Set_Logic_Page(GraphicBufferClass *ptr);\nGraphicBufferClass *Set_Logic_Page(GraphicBufferClass &ptr);\n\n/*=========================================================================*/\n/* GraphicViewPortClass - Holds viewport information on a viewport which\t*/\n/*\t\thas been attached to a GraphicBuffer.  A viewport is effectively a\t*/\n/*\t\trectangular subset of the full buffer which is used for clipping and\t*/\n/*\t\tthe like.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tchar\t  \t*Buffer\t-\t\tis the offset to view port buffer\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis the width of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis the height of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis add value to go from the end of a line\t*/\n/*\t\t\t\t\t\t\t\t\t\t\tto the beginning of the next line\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\tx offset into its associated VideoBuffer\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\ty offset into its associated VideoBuffer\t*/\n/*=========================================================================*/\nclass GraphicViewPortClass {\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tGraphicViewPortClass(GraphicBufferClass* graphic_buff, int x, int y, int w, int h);\n\t\tGraphicViewPortClass();\n\t\t~GraphicViewPortClass();\n\n\t\t/*===================================================================*/\n\t\t/* define functions to get at the private data members\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\tGet_Offset(void);\n\t\tint\tGet_Height(void);\n\t\tint\tGet_Width(void);\n\t\tint\tGet_XAdd(void);\n\t\tint\tGet_XPos(void);\n\t\tint\tGet_YPos(void);\n\t\tGraphicBufferClass\t*Get_Graphic_Buffer(void);\n\n\t\tint Lock(void) const {return(TRUE);}\n\t\tvoid Unlock(void) const {}\n\n\t\t/*===================================================================*/\n\t\t/* Define a function which allows us to change a video viewport on\t*/\n\t\t/*\t\tthe fly.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBOOL Change(int x, int y, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the set of common graphic functions that are supported by\t*/\n\t\t/*\t\tboth Graphic ViewPorts and VideoViewPorts.\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\tSize_Of_Region(int w, int h);\n\t\tvoid\tPut_Pixel(int x, int y, unsigned char color);\n\t\tint\tGet_Pixel(int x, int y);\n\t\tvoid\tClear(unsigned char color = 0);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, void *buff, long size);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, BufferClass *buff);\n\t\tlong\tTo_Buffer(BufferClass *buff);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, char *remap);\n\t\tunsigned long\tPrint(char const *string, int x_pixel, int y_pixel, int fcolor, int bcolor);\n\t\tunsigned long\tPrint(short num, int x_pixel, int y_pixel, int fcol, int bcol);\n\t\tunsigned long\tPrint(int num, int x_pixel, int y_pixel, int fcol, int bcol);\n\t\tunsigned long\tPrint(long num, int x_pixel, int y_pixel, int fcol, int bcol);\n\n\t\t/*===================================================================*/\n\t\t/* Define the list of graphic functions which work only with a \t\t*/\n\t\t/*\t\tgraphic buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Draw_Line(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Draw_Rect(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Fill_Rect(int sx, int sy, int dx, int dy, unsigned char color);\n\t\tVOID Fill_Quad(VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\tint x2, int y2, int x3, int y3, int color);\n\t\tVOID Remap(int sx, int sy, int width, int height, VOID *remap);\n\t\tVOID Remap(VOID *remap);\n\t\tvoid Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap);\n\t\tvoid Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int clip_window);\n\t\tVOID Grey_Out_Region(int x, int y, int width, int height, int color);\n\tprotected:\n\t\t/*===================================================================*/\n\t\t/* Define functions to attach the viewport to a graphicbuffer\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVOID Attach(GraphicBufferClass *graphic_buff, int x, int y, int w, int h);\n\t\tvoid Attach(GraphicBufferClass *video_buff, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the data used by a GraphicViewPortClass\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\t\t\t\t\t\tOffset;\t\t\t\t\t// offset to graphic page\n\t\tint\t\t\t\t\t\tWidth;\t\t\t\t\t// width of graphic page\n\t\tint\t\t\t\t\t\tHeight;\t\t\t\t\t// height of graphic page\n\t\tint\t\t\t\t\t\tXAdd;\t\t\t\t\t\t// xadd for graphic page (0)\n\t\tint\t\t\t\t\t\tXPos;\t\t\t\t\t\t// x offset in relation to graphicbuff\n\t\tint\t\t\t\t\t\tYPos;\t\t\t\t\t\t// y offset in relation to graphicbuff\n\t\tGraphicBufferClass\t*GraphicBuff;\t\t\t// related graphic buff\n};\n\n/*=========================================================================*/\n/* GraphicBufferClass - A GraphicBuffer refers to an actual instance of an\t*/\n/*\t\tallocated buffer.  The GraphicBuffer may be drawn to directly \t\t\t*/\n/*\t\tbecuase it inherits a ViewPort which represents its physcial size.\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tBYTE\t  \t*Buffer\t-\t\tis the offset to graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis the width of graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis the height of graphic buffer\t\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis the xadd of graphic buffer\t\t\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\twill be 0 because it is graphicbuff\t\t\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\twill be 0 because it is graphicbuff\t\t\t*/\n/*=========================================================================*/\nclass GraphicBufferClass : public GraphicViewPortClass, public BufferClass {\n\tpublic:\n\t\tGraphicBufferClass(\tlong size = 64500, int w = DEFAULT_SCREEN_WIDTH, int h = DEFAULT_SCREEN_HEIGHT, \n\t\t\t\t\t\t\t\t\tVOID *buffer = 0);\n\t\tGraphicBufferClass(int w, int h, void *buffer = 0);\n\t\t~GraphicBufferClass();\n\n//\t\tvoid Scale_Rotate(BitmapClass &bmp,const TPoint2D &pt,long scale=0x0100,unsigned char angle=0);\n};\n\n/***************************************************************************\n * GVPC::GET_OFFSET -- Get offset for virtual view port class instance     *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long the offset for the virtual viewport instance           *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long GraphicViewPortClass::Get_Offset(void)\n{\n\treturn(Offset);\n}\n\n/***************************************************************************\n * GVPC::GET_HEIGHT -- Gets the height of a virtual viewport instance      *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the height of the virtual viewport instance            *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_Height(void)\n{\n\treturn(Height);\n}\n\n/***************************************************************************\n * GVPC::GET_WIDTH -- Get the width of a virtual viewport instance\t\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the width of the virtual viewport instance             *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_Width(void)\n{\n\treturn(Width);\n}\n\n\n/***************************************************************************\n * GVPC::GET_XADD -- Get the X add offset for virtual viewport instance    *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the xadd for a virtual viewport instance               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_XAdd(void)\n{\t\n\treturn(XAdd);\n}\n/***************************************************************************\n * GVPC::GET_XPOS -- Get the x pos of the VP on the Video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n;*   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_XPos(void)\n{\n\treturn(XPos);\n}\n\n\n/***************************************************************************\n * GVPC::GET_YPOS -- Get the y pos of the VP on the video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     WORD the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n;*   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int GraphicViewPortClass::Get_YPos(void)\n{\n\treturn(YPos);\n}\n\n/***************************************************************************\n * GVPC::GET_GRAPHIC_BUFFER -- Get the graphic buffer of the VP.            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline GraphicBufferClass *GraphicViewPortClass::Get_Graphic_Buffer(void)\n{\n \treturn (GraphicBuff);\n}\n\n/***************************************************************************\n * GVPC::SIZE_OF_REGION -- stub to call curr graphic mode Size_Of_Region\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/01/1995 BWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::Size_Of_Region(int w, int h)\n{\n\treturn MCGA_Size_Of_Region(this, w, h);\n}\n\n/***************************************************************************\n * GVPC::PUT_PIXEL -- stub to call curr graphic mode Put_Pixel\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tGraphicViewPortClass::Put_Pixel(int x, int y, unsigned char color)\n{\n\tMCGA_Put_Pixel(this, x, y, color);\n}\n\n/***************************************************************************\n * GVPC::GET_PIXEL -- stub to call curr graphic mode Get_Pixel          \t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline int\tGraphicViewPortClass::Get_Pixel(int x, int y)\n{\n\treturn(MCGA_Get_Pixel(this, x, y));\n}\n\n/***************************************************************************\n * GVPC::CLEAR -- stub to call curr graphic mode Clear\t                  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tGraphicViewPortClass::Clear(unsigned char color)\n{\n\tMCGA_Clear(this, color);\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 1 to call curr graphic mode To_Buffer\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(int x, int y, int w, int h, void *buff, long size)\n{\n\treturn(MCGA_To_Buffer(this, x, y, w, h, buff, size));\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 2 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(int x, int y, int w, int h, BufferClass *buff)\n{\n\treturn(MCGA_To_Buffer(this, x, y, w, h, buff->Get_Buffer(), buff->Get_Size()));\n}\n\n/***************************************************************************\n * GVPC::TO_BUFFER -- stub 3 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tGraphicViewPortClass::To_Buffer(BufferClass *buff)\n{\n\treturn(MCGA_To_Buffer(this, 0, 0, Width, Height, buff->Get_Buffer(), buff->Get_Size()));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 1 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans)\n{\n\treturn(Linear_Blit_To_Linear(this, &dest, x_pixel, y_pixel, dx_pixel, dy_pixel, pixel_width, pixel_height, trans));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- Stub 2 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans)\n{\n\treturn(Linear_Blit_To_Linear(this, &dest, 0, 0, dx, dy, Width, Height, trans));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 3 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tGraphicViewPortClass& dest, BOOL trans)\n{\n\treturn(Linear_Blit_To_Linear(this, &dest, 0, 0, 0, 0, Width, Height, trans));\n}\n\n\n/***************************************************************************\n * GVPC::SCALE -- stub 1 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, trans, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 2 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, FALSE, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 3 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, BOOL trans, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this,\t&dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), trans, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 4 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tGraphicViewPortClass &dest, char *remap)\n{\n\treturn(Linear_Scale_To_Linear(this, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), FALSE, remap));\n}\n/***************************************************************************\n * GVPC::PRINT -- stub func to print a text string                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/17/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(char const *str, int x, int y, int fcol, int bcol)\n{\n\treturn(MCGA_Print(this, str, x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::PRINT -- Stub function to print an integer                        *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(int num, int x, int y, int fcol, int bcol)\n{\n\tchar str[17];\n\n\t\n\treturn(MCGA_Print(this, itoa(num, str, 10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::PRINT -- Stub function to print a short to a graphic viewport     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(short num, int x, int y, int fcol, int bcol)\n{\n\tchar str[17];\n\n\treturn(MCGA_Print(this, itoa(num, str, 10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::PRINT -- stub function to print a long on a graphic view port     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tGraphicViewPortClass::Print(long num, int x, int y, int fcol, int bcol)\n{\n\tchar str[33];\n\n\treturn(MCGA_Print(this, ltoa(num, str,10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * GVPC::DRAW_STAMP -- stub function to draw a tile on a graphic view port *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline void GraphicViewPortClass::Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap)\n{\n\tMCGA_Draw_Stamp(this, icondata, icon, x_pixel, y_pixel, remap);\n}\n\n/***************************************************************************\n * GVPC::DRAW_STAMP -- stub function to draw a tile on a graphic view port *\n *                     This version clips the tile to a window             *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *    07/31/1995 BWG : Created.                                            *\n *=========================================================================*/\ninline void GraphicViewPortClass::Draw_Stamp(void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int clip_window)\n{\n\tMCGA_Draw_Stamp_Clip(this, icondata, icon, x_pixel, y_pixel, remap, WindowList[clip_window][WINDOWX], WindowList[clip_window][WINDOWY], WindowList[clip_window][WINDOWWIDTH], WindowList[clip_window][WINDOWHEIGHT]);\n}\n\n/***************************************************************************\n * GVPC::DRAW_LINE -- Stub function to draw line in Graphic Viewport Class *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Draw_Line(int sx, int sy, int dx, int dy, unsigned char color)\n{\n\tMCGA_Draw_Line(this, sx, sy, dx, dy, color);\n}\n\n/***************************************************************************\n * GVPC::FILL_RECT -- Stub function to fill rectangle in a GVPC            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Fill_Rect(int sx, int sy, int dx, int dy, unsigned char color)\n{\n\tMCGA_Fill_Rect(this, sx, sy, dx, dy, color);\n}\n\n\n/***************************************************************************\n * GVPC::REMAP -- Stub function to remap a GVPC                            *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/16/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Remap(int sx, int sy, int width, int height, VOID *remap)\n{\n\tMCGA_Remap(this, sx, sy, width, height, remap);\n}\ninline VOID GraphicViewPortClass::Fill_Quad(VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\tint x2, int y2, int x3, int y3, int color)\n{\n\tMCGA_Fill_Quad(this, span_buff, x0, y0, x1, y1, x2, y2, x3, y3, color);\n}\n\n/***************************************************************************\n * GVPC::REMAP -- Short form to remap an entire graphic view port          *\n *                                                                         *\n * INPUT:\t\tBYTE * to the remap table to use\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline VOID GraphicViewPortClass::Remap(VOID *remap)\n{\n\tMCGA_Remap(this, 0, 0, Width, Height, remap);\n}\n/*=========================================================================*/\n/* The following BufferClass functions are defined here because they act\t*/\n/*\t\ton graphic viewports.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n\n/***************************************************************************\n * BUFFER_TO_PAGE -- Generic 'c' callable form of Buffer_To_Page           *\n *                                                                         *\n * INPUT: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/12/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long Buffer_To_Page(int x, int y, int w, int h, void *Buffer, GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(x, y, w, h, Buffer, &view));\n}\n\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t*\n *\t\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t*\n *\t\t\t\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int w, int h, GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(0, 0, w, h, Buffer, &view));\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport.  width and height are assumed to be the\t\t\t*\n *\t\t\t\t\t\tviewport's width and height.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(0, 0, view.Get_Width(), view.Get_Height(), Buffer, &view));\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable x, y, w, h *\n *                                                                         *\n * INPUT:\tint\tx\t\t\t- x pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\ty\t\t\t- y pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t\t*\n *\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t\t*\n *\t\t\t\tGVPC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\tnone                                                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int x, int y, int w, int h, GraphicViewPortClass &view)\n{\n\treturn(MCGA_Buffer_To_Page(x, y, w, h, Buffer, &view));\n}\n\n\n#endif\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/GBUFFER.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 Bit Library\t\t   *\n;*                                                                         *\n;*                    File Name : GBUFFER.INC                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : May 26, 1994                             *\n;*                                                                         *\n;*                  Last Update : May 26, 1994   [PWG]                     *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n;******************************************************************************\n; Much testing was done to determine that only when there are 14 or more bytes\n; being copied does it speed the time it takes to do copies in this algorithm.\n; For this reason and because 1 and 2 byte copies crash, is the special case\n; used.  SKB 4/21/94.  Tested on 486 66mhz.  Copied by PWG 6/7/04.\nOPTIMAL_BYTE_COPY\tequ\t14\n\nSTRUC GraphicViewPort \nGVPOffset\t\tDD\t\t?\t\t; offset to virtual viewport\nGVPWidth\t\t\tDD\t\t?\t\t; width of virtual viewport\nGVPHeight\t\tDD\t\t?\t\t; height of virtual viewport\nGVPXAdd\t\t\tDD\t\t?\t\t; x mod to get to next line\nGVPXPos\t\t\tDD\t\t?\t\t; x pos relative to Graphic Buff\nGVPYPos\t\t\tDD\t\t?\t\t; y pos relative to Graphic Buff\nGVPBuffPtr\t\tDD\t\t?\t\t; ptr to associated Graphic Buff\nENDS\n\nSTRUC VideoViewPort \nVIVPOffset\t\t\tDD\t\t?\t\t; offset to virtual viewport\nVIVPWidth\t\t\tDD\t\t?\t\t; width of virtual viewport\nVIVPHeight\t\t\tDD\t\t?\t\t; height of virtual viewport\nVIVPXAdd\t\t\t\tDD\t\t?\t\t; x mod to get to next line\nVIVPXPos\t\t\t\tDD\t\t?\t\t; x pos relative to Graphic Buff\nVIVPYPos\t\t\t\tDD\t\t?\t\t; y pos relative to Graphic Buff\nVIVPBuffPtr\t\t\tDD\t\t?\t\t; ptr to associated Graphic Buff\nENDS\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/GETCLIP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : BITBLIT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Julio R. Jerez                           *\n;*                                                                         *\n;*                   Start Date : Feb 6, 1995                              *\n;*                                                                         *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\n; typedef struct {\n;\t\t     int x0 , y0 ;\n;\t\t     int x1 , y1 ;\n;\t\t } CLIP_WIN ;\n; Note for efficiency reasons x1 must be >= x0 and y1 >= y0\n; int get_clip ( CLIP_WIN * window , CLIP_WIN * sorce_rect ) ;\n\nCODESEG\n\n\tPROC\tget_clip C near \n\tUSES\teax , ebx\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG\twin\t    : dword\n\tARG     rect\t    : dword\n\n\n\tmov\tedi , [ rect ]\n\tmov  \tesi , [ win ]\t    \n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ (RECTANGLE edi) . x0 ]  \n\tmov\tebx , [ (RECTANGLE edi) . x1 ]  \n\tsub\tecx , [ (RECTANGLE esi) . x0 ]\n\tsub\tebx , [ (RECTANGLE esi) . x0 ]\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n;\tmov\tebx , [ (RECTANGLE esi) . x1 ]\n;\tinc\tebx\n;\tmov\t[ rect ] , ebx\n\tmov\tecx , [ (RECTANGLE edi) . x0 ]  \n\tmov\tebx , [ (RECTANGLE edi) . x1 ]  \n\tsub\tecx , [ (RECTANGLE esi) . x1 ]\n\tsub\tebx , [ (RECTANGLE esi) . x1 ]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ (RECTANGLE edi) . y0 ]  \n\tmov\tebx , [ (RECTANGLE edi) . y1 ]  \n\tsub\tecx , [ (RECTANGLE esi) . y0 ]\n\tsub\tebx , [ (RECTANGLE esi) . y0 ]\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n;\tmov\tebx , [ (RECTANGLE esi) . y1 ]\n;\tinc\tebx\n;\tmov\t[ rect ] , ebx\n\tmov\tecx , [ (RECTANGLE edi) . y0 ]  \n\tmov\tebx , [ (RECTANGLE edi) . y1 ]  \n\tsub\tecx , [ (RECTANGLE esi) . y1 ]\n\tsub\tebx , [ (RECTANGLE esi) . y1 ]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , dl\n\tret\n       ENDP\tget_clip\n\n\n\nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/GETPIX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Clear the Full Mcga Screen\t\t   *\n;*                                                                         *\n;*                    File Name : GETPIXEL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : June 7, 1994   [PWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVPC::Clear -- Clears a virtual viewport instance                     *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n;***************************************************************************\n;* VVPC::GET_PIXEL -- Gets a pixel from the current view port\t\t   *\n;*                                                                         *\n;* INPUT:\tWORD the x pixel on the screen.\t\t\t\t   *\n;*\t\tWORD the y pixel on the screen.\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      UBYTE the pixel at the specified location\t\t   *\n;*                                                                         *\n;* WARNING:\tIf pixel is to be placed outside of the viewport then\t   *\n;*\t\tthis routine will abort.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/07/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tMCGA_Get_Pixel C near \n\tUSES\tebx,ecx,edx,edi\n\n\tARG    \tthis:DWORD\t\t\t\t; this is a member function\n\tARG\tx_pixel:DWORD\t\t\t\t; x position of pixel to set\n\tARG\ty_pixel:DWORD\t\t\t\t; y position of pixel to set\n\n\t;*===================================================================\n\t; Get the viewport information and put bytes per row in ecx\n\t;*===================================================================\n\tmov\tebx,[this]\t\t\t\t; get a pointer to viewport\n\txor\teax,eax\t\t\t\t\t\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get the correct offset\n\tmov\tecx,[(GraphicViewPort ebx).GVPHeight]\t; edx = height of viewport\n\tmov\tedx,[(GraphicViewPort ebx).GVPWidth]\t; ecx = width of viewport\n\n\t;*===================================================================\n\t; Verify that the X pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[x_pixel]\t\t\t\t; find the x position\n\tcmp\teax,edx\t\t\t\t\t;   is it out of bounds\n\tjae\tshort ??exit\t\t\t\t; if so then get out\n\tadd\tedi,eax\t\t\t\t\t; otherwise add in offset\n\n\t;*===================================================================\n\t; Verify that the Y pixel offset if legal\n\t;*===================================================================\t\n\tmov\teax,[y_pixel]\t\t\t\t; get the y position\n\tcmp\teax,ecx\t\t\t\t\t;  is it out of bounds\n\tjae\t??exit\t\t\t\t\t; if so then get out\n\tadd\tedx,[(GraphicViewPort ebx).GVPXAdd]\t; otherwise find bytes per row\n\tmul\tedx\t\t\t\t\t; offset = bytes per row * y\n\tadd\tedi,eax\t\t\t\t\t; add it into the offset\n\n\t;*===================================================================\n\t; Write the pixel to the screen\n\t;*===================================================================\n\txor\teax,eax\t\t\t\t\t; clear the word\n\tmov\tal,[edi]\t\t\t\t; read in the pixel\n??exit:\n\tret\n\tENDP\tMCGA_Get_Pixel\n\nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 26, 1995                           *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = mcgaprim\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\n\nOBJECTS = \t\t&\n\tbitblit.obj \t&\n\tbuffer.obj \t&\n\tbuffglbl.obj\t&\n\tclear.obj \t&\n\tdrawline.obj \t&\n\tdrawrect.obj \t&\n\tfillquad.obj \t&\n\tfillrect.obj \t&\n\tgbuffer.obj \t&\n\tgetclip.obj\t&\n\tgetpix.obj \t&\n\tputpix.obj \t&\n\tremap.obj \t&\n\tscale.obj \t&\n\tshadow.obj\t&\n\tstamp.obj \t&\n\tszregion.obj \t&\n\ttobuff.obj \t&\n\ttopage.obj\t&\n\ttxtprnt.obj \t&\n\tvbuffer.obj\t&\n\tvclear.obj  \t&\n\tvesa.obj\t&\n\tvgetpix.obj \t&\n\tvlbtove.obj\t&\n\tvputpix.obj \t&\n\tvscale.obj  \t&\n\tvscltove.obj\t&\n\tvtobuff.obj \t&\n\tvtopage.obj \t&\n\tvtxtprnt.obj\t&\n\tvvblit.obj\t&\n\tvvetolb.obj\t&\n\tvvetoscl.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\u001a\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/MCGAPRIM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n\n#ifndef MCGAPRIM_H\n#define MCGAPRIM_H\n\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\nclass GraphicViewPortClass;\nclass GraphicBufferClass;\nclass VideoBufferClass;\n/*=========================================================================*/\n/* Define functions which have not under-gone name mangling\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\t/*======================================================================*/\n\t/* Externs for all of the common functions between the video buffer\t\t*/\n\t/*\t\tclass and the graphic buffer class.\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\textern long MCGA_Size_Of_Region(void *thisptr, int w, int h);\n\n\textern void\tMCGA_Put_Pixel(void * thisptr, int x, int y, unsigned char color);\n\textern int\tMCGA_Get_Pixel(void * thisptr, int x, int y);\n\textern void\tMCGA_Clear(void *thisptr, unsigned char color);\n\textern long\tMCGA_To_Buffer(void *thisptr, int x, int y, int w, int h, void *buff, long size);\n\textern long MCGA_Buffer_To_Page(int x, int y, int w, int h, void *Buffer, void *view);\n\textern BOOL\tLinear_Blit_To_Linear(\tvoid *thisptr, void * dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\t\t\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans);\n\textern BOOL Linear_Scale_To_Linear(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\n\n\textern void\tVesa_Put_Pixel(void * thisptr, int x, int y, unsigned char color);\n\textern int\tVesa_Get_Pixel(void * thisptr, int x, int y);\n\textern void\tVesa_Clear(void *thisptr, unsigned char color);\n\textern long\tVesa_To_Buffer(void *thisptr, int x, int y, int w, int h, void *buff, long size);\n\textern long Vesa_Buffer_To_Page(int x, int y, int w, int h, void *Buffer, void *view);\n\n\textern BOOL\tLinear_Blit_To_Vesa(\t\tvoid *thisptr, void * dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\t\t\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans);\n\textern BOOL\tVesa_Blit_To_Linear(\t\tvoid *thisptr, void * dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\t\t\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans);\n\textern BOOL\tVesa_Blit_To_Vesa(\t\tvoid *thisptr, void * dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\t\t\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans);\n\textern BOOL Linear_Scale_To_Vesa(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\n\textern BOOL Vesa_Scale_To_Linear(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\n\textern BOOL Vesa_Scale_To_Vesa(\t\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\n\textern LONG MCGA_Print(\t\t\t\t\tvoid *thisptr, const char *str, int x, int y, int fcolor, int bcolor);\n\textern LONG Vesa_Print(\t\t\t\t\tvoid *thisptr, const char *str, int x, int y, int fcolor, int bcolor);\n\n\t/*======================================================================*/\n\t/* Externs for all of the graphic buffer class only functions\t\t\t\t*/\n\t/*======================================================================*/\n\textern VOID MCGA_Draw_Line(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color);\n\textern VOID MCGA_Fill_Rect(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color);\n\textern VOID MCGA_Remap(void * thisptr, int sx, int sy, int width, int height, void *remap);\t\n\textern VOID MCGA_Fill_Quad(void * thisptr, VOID *span_buff, int x0, int y0, int x1, int y1,\n\t\t\t\t\t\t\tint x2, int y2, int x3, int y3, int color);\n\textern void MCGA_Draw_Stamp(void const *thisptr, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap);\n\textern void MCGA_Draw_Stamp_Clip(void const *thisptr, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int min_x, int min_y, int max_x, int max_y);\n\n\textern void Shadow_Blit(long int xpix, long int ypix, long int width, long int height, GraphicViewPortClass &src, VideoBufferClass &dst, void *shadowbuff);\n\n\textern void *Get_Font_Palette_Ptr(void);\n//\textern int Get_Standard_Selector(VOID);\n//\textern VOID Set_Selector(UWORD sel);\n#ifdef __cplusplus\n}\n#endif\n\nextern BOOL (*VVPC_Blit_to_GVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nextern BOOL (*VVPC_Blit_to_VVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nextern void (*VVPC_Clear_Func)(void *, unsigned char);\nextern long (*VVPC_To_Buffer_Func)(void *,int x, int y, int w, int h, void *buff, long size);\nextern void (*VVPC_Put_Pixel_Func)(void *,int x, int y, unsigned char color);\nextern int  (*VVPC_Get_Pixel_Func)(void *, int x, int y);\nextern long (*VVPC_Buffer_To_Page)(int x, int y, int w, int h, void *buffer, void *view);\nextern BOOL (*GVPC_Blit_to_VVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nextern BOOL (*VVPC_Blit_to_GVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nextern BOOL (*VVPC_Blit_to_VVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);\nextern BOOL (*VVPC_Scale_To_GVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\nextern BOOL (*VVPC_Scale_To_VVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\nextern BOOL (*GVPC_Scale_To_VVPC)(\tvoid *, void *, int, int, int, int, int, int, int, int, BOOL, char *);\nextern LONG (*VVPC_Print_Func)(void *, const char *, int, int, int, int);\nextern GraphicBufferClass *LogicPage;\n#endif\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/MCGAPRIM.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : MCGAPRIM.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 16, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n; Externs from REGIONSZ.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Size_Of_Region\t:NEAR\n\n; Externs from GETPIX.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Get_Pixel          \t:NEAR\n\n; Externs from VGETPIX.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Get_Pixel          \t:NEAR\n\n; Externs from PUTPIX.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Put_Pixel \t\t:NEAR\n\n; Externs from VPUTTPIX.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Put_Pixel \t\t:NEAR\n\n; Externs from CLEAR.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Clear\t          \t:NEAR\n\n; Externs from VCLEAR.ASM module of the MCGA/SVGAPRIM library\nGLOBAL Vesa_Clear\t\t\t:NEAR\n; Externs from BITBLIT.ASM module of the MCGAPRIM library\nGLOBAL Linear_Blit_To_Linear\t\t:NEAR\n\n; Externs from VBITBLIT.ASM module of the MCGA/SVGAPRIM library\nGLOBAL Linear_Blit_To_Vesa\t\t:NEAR\nGLOBAL Vesa_Blit_To_Linear\t\t:NEAR\nGLOBAL Vesa_Blit_To_Vesa\t\t:NEAR\n\n; Externs from TOBUFF.ASM module of the MCGAPRIM library\nGLOBAL MCGA_To_Buffer\t\t:NEAR\n\n; Externs from VTOBUFF.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_To_Buffer\t\t:NEAR\n\n; Externs from TOPAGE.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Buffer_To_Page\t\t:NEAR\n\n; Externs from VTOPAGE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Buffer_To_Page\t\t:NEAR\n\n; Externs from SCALE.ASM module of the MCGAPRIM library\nGLOBAL Linear_Scale_To_Linear \t:NEAR\n\n; Externs from VSCALE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Linear_Scale_To_Vesa \t\t:NEAR\nGLOBAL Vesa_Scale_To_Linear\t\t:NEAR\nGLOBAL Vesa_Scale_To_Vesa \t\t:NEAR\n\n; Externs from TXTPRNT.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Print\t\t\t:NEAR\nGLOBAL C Get_Font_Palette_Ptr\t\t:NEAR\n\n; Externs from VTXTPRNT.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Print\t\t\t:NEAR\n\n;*-------------------------------------------------------------------------*\n;* Define MCGA only assembly GLOBALS\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n\n; Externs from DRAWLINE.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Draw_Line \t\t:NEAR\n\n; Externs from FILLQUAD.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Fill_Quad \t\t:NEAR\n\n; Externs from FILLRECT.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Fill_Rect \t\t:NEAR\n\n; Externs from REMAP.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Remap      \t\t:NEAR\n\n; Externs from STAMP.ASM module of the MCGAPRIM library\nGLOBAL MCGA_Draw_Stamp \t\t:NEAR\nGLOBAL MCGA_Draw_Stamp_Clip\t:NEAR\n\nGLOBAL get_clip\t \t   : NEAR\n\nstruc  RECTANGLE\n\t\t  x0\tdd\t?\n\t\t  y0 dd\t?\n\t\t  x1\tdd\t?\n\t\t  y1 dd ?\nends \t RECTANGLE\n\n\n\n\u001a\n\u001a\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/MCGAPRIM.PJT",
    "content": ";Codewright Project File (do not remove or modify this line)\n[ProjInit]\nProjSetConfigFlags=0x00010140\n\n[Files]\nd:\\wwflat32\\mcgaprim\\bitblit.asm\nd:\\wwflat32\\mcgaprim\\buffer.cpp\nd:\\wwflat32\\mcgaprim\\buffer.h\nd:\\wwflat32\\mcgaprim\\buffglbl.cpp\nd:\\wwflat32\\mcgaprim\\clear.asm\nd:\\wwflat32\\mcgaprim\\drawline.asm\nd:\\wwflat32\\mcgaprim\\drawrect.cpp\nd:\\wwflat32\\mcgaprim\\fillquad.asm\nd:\\wwflat32\\mcgaprim\\fillrect.asm\nd:\\wwflat32\\mcgaprim\\gbuffer.cpp\nd:\\wwflat32\\mcgaprim\\gbuffer.h\nd:\\wwflat32\\mcgaprim\\gbuffer.inc\nd:\\wwflat32\\mcgaprim\\getclip.asm\nd:\\wwflat32\\mcgaprim\\getpix.asm\nd:\\wwflat32\\mcgaprim\\mcgaprim.h\nd:\\wwflat32\\mcgaprim\\mcgaprim.inc\nd:\\wwflat32\\mcgaprim\\putpix.asm\nd:\\wwflat32\\mcgaprim\\regionsz.cpp\nd:\\wwflat32\\mcgaprim\\remap.asm\nd:\\wwflat32\\mcgaprim\\scale.asm\nd:\\wwflat32\\mcgaprim\\shadow.asm\nd:\\wwflat32\\mcgaprim\\stamp.asm\nd:\\wwflat32\\mcgaprim\\stamp.inc\nd:\\wwflat32\\mcgaprim\\szregion.asm\nd:\\wwflat32\\mcgaprim\\tobuff.asm\nd:\\wwflat32\\mcgaprim\\topage.asm\nd:\\wwflat32\\mcgaprim\\txtprnt.asm\nd:\\wwflat32\\mcgaprim\\vbitblit.asm\nd:\\wwflat32\\mcgaprim\\vbuffer.cpp\nd:\\wwflat32\\mcgaprim\\vbuffer.h\nd:\\wwflat32\\mcgaprim\\vclear.asm\nd:\\wwflat32\\mcgaprim\\vesa.asm\nd:\\wwflat32\\mcgaprim\\vgetpix.asm\nd:\\wwflat32\\mcgaprim\\vlbtove.asm\nd:\\wwflat32\\mcgaprim\\vputpix.asm\nd:\\wwflat32\\mcgaprim\\vscale.asm\nd:\\wwflat32\\mcgaprim\\vscltove.asm\nd:\\wwflat32\\mcgaprim\\vtobuff.asm\nd:\\wwflat32\\mcgaprim\\vtopage.asm\nd:\\wwflat32\\mcgaprim\\vtxtprnt.asm\nd:\\wwflat32\\mcgaprim\\vvblit.asm\nd:\\wwflat32\\mcgaprim\\vvetolb.asm\nd:\\wwflat32\\mcgaprim\\vvetoscl.asm\n\n\n[State]\nSysSetCwd='C:\\PROJECTS\\C&CZERO\\WWFLAT32\\MCGAPRIM'\nSrchSetFlags=0x20aa\nFileSortMode=0x0\nStateWindowFrame=69,91,417,932,0x6989f5fa\n_OutputWindowPosition=1,-3,-3,1286,1030,0,0\n_StateWindow=87,87,990,623,0x00000118,'c:\\projects\\c&czero\\wwflat32\\mcgaprim\\stamp.inc',240,7,244,32,32,0,32,32,32,32,8,65535,65535,1,0,'Terminal',65520,255,49,0,4,243,14,15,247,247,253,2,1,400,0,246,252,245,242,241,247,0,0,0\n_StateBuffer='c:\\projects\\c&czero\\wwflat32\\mcgaprim\\stamp.inc',0x0400048e,2,1,25,'9 17','',0x0,''\n_StateBuffer='c:\\projects\\c&czero\\wwflat32\\mcgaprim\\stamp.asm',0x0400048e,1,9,25,'9 17','',0x0,''\nWrapEnable=0\n_StateHistory=FILELIST,'d:\\wwflat32\\mcgaprim\\stamp.asm','c:\\projects\\c&czero\\wwflat32\\mcgaprim\\stamp.asm','c:\\projects\\c&czero\\wwflat32\\mcgaprim\\stamp.inc'\n_StateHistory=DIRECTORY,'C:\\PROJECTS\\C&CZERO\\WWFLAT32\\MCGAPRIM'\n\n[Editor]\nClipboardSetTermStr='\\r\\n',0\nClipboardEnableTermStr=1\nClipboardSetSepStr='\\r\\n',0\nClipboardEnableSepStr=1\nScrapSetCount=1\n_RestoreSysFlags=0x6989f5fa, 0xfffffffc\n\n[Compiler]\nBrowseSetFile='c:\\projects\\c&czero\\wwflat32\\mcgaprim\\mcgaprim.ptg'\nTagSetFile='c:\\projects\\c&czero\\wwflat32\\mcgaprim\\mcgaprim.tag'\nCompilerAddBuild='Microsoft Assembler',1073741880,'ftee masm -w2 -zi %r%e;','','','','','_MicrosoftErrorInfo','','%v%p','','','','','',0\nCompilerAddResponse='Microsoft Assembler',\nCompilerAddBuild='Borland C++',1073741880,'ftee bcc -S %r.c','ftee make %r.obj','ftee make %r.obj','','','_BorlandCppErrorInfo','','%v%p','','','','','',0\nCompilerAddResponse='Borland C++',\nCompilerAddBuild='Borland Turbo Assembler',1073741880,'ftee make %r.obj','ftee make %r.obj','','','','_TasmErrorInfo','','%v%p','','','','','',0\nCompilerAddResponse='Borland Turbo Assembler',\nCompilerAddBuild='$_cw_proj_hash_$',1073741873,'','ftee wmake %r.obj','ftee wmake ','','','_MSLinkErrorInfo','proj.err','c:\\projects\\c&czero\\wwflat32\\mcgaprim','','_MicrosoftErrorInfo','_NMakeErrorInfo','','',197376\nCompilerAddResponse='$_cw_proj_hash_$',\nCompilerAddBuild='Default Project',1073741880,'','ftee make','ftee make','','','_ErrorInfoDefault','proj.err','%v%p','','','','','',0\nCompilerAddResponse='Default Project',\nCompilerAddBuild='Microsoft C',1073741880,'ftee cl -c -AL -Gsw -Ow -Zpe  %r%e','','','','','_MicrosoftErrorInfo','','%v%p','','','','','',0\nCompilerAddResponse='Microsoft C',\nCompilerAddBuild='Script',1073741880,'ftee make %r.inf','ftee make','ftee make','','','_BorlandCppErrorInfo','','','','','','','',0\nCompilerAddResponse='Script',\nCompilerAddBuild='Zortech C++',1073741880,'ftee ztc -a -b -c -g -ml -W %r%e','','','','','_ZortechCppErrorInfo','','%v%p','','','','','',0\nCompilerAddResponse='Zortech C++',\nCompilerAssign='Borland C++','.scr'\nCompilerNewExt=.bas\nCompilerAssign='Borland C++','.int'\nCompilerAssign='Borland C++','.c'\nCompilerNewExt=.prg\nCompilerAssign='Microsoft C','.h'\nCompilerAssign='Borland C++','.cpp'\nCompilerAssign='Default Project','.*'\nCompilerAssign='Zortech C++','.cxx'\nCompilerAssign='Borland Turbo Assembler','.asm'\nCompilerAssign='Borland C++','.hpp'\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/PUTPIX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Clear the Full Mcga Screen\t\t   *\n;*                                                                         *\n;*                    File Name : PUTPIXEL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : June 8, 1994   [PWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVPC::Put_Pixel -- Puts a pixel on a virtual viewport                 *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n;***************************************************************************\n;* VVPC::PUT_PIXEL -- Puts a pixel on a virtual viewport                   *\n;*                                                                         *\n;* INPUT:\tWORD the x position for the pixel relative to the upper    *\n;*\t\t\tleft corner of the viewport\t\t\t   *\n;*\t\tWORD the y pos for the pixel relative to the upper left\t   *\n;*\t\t\tcorner of the viewport\t\t\t\t   *\n;*\t\tUBYTE the color of the pixel to write\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNING:\tIf pixel is to be placed outside of the viewport then\t   *\n;*\t\tthis routine will abort.\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/08/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tMCGA_Put_Pixel C near \n\tUSES\teax,ebx,ecx,edx,edi\n\n\tARG    \tthis:DWORD\t\t\t\t; this is a member function\n\tARG\tx_pixel:DWORD\t\t\t\t; x position of pixel to set\n\tARG\ty_pixel:DWORD\t\t\t\t; y position of pixel to set\n\tARG    \tcolor:BYTE\t\t\t\t; what color should we clear to\n\n\t;*===================================================================\n\t; Get the viewport information and put bytes per row in ecx\n\t;*===================================================================\n\tmov\tebx,[this]\t\t\t\t; get a pointer to viewport\n\txor\teax,eax\t\t\t\t\t\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get the correct offset\n\tmov\tecx,[(GraphicViewPort ebx).GVPHeight]\t; edx = height of viewport\n\tmov\tedx,[(GraphicViewPort ebx).GVPWidth]\t; ecx = width of viewport\n\n\t;*===================================================================\n\t; Verify that the X pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[x_pixel]\t\t\t\t; find the x position\n\tcmp\teax,edx\t\t\t\t\t;   is it out of bounds\n\tjae\tshort ??exit\t\t\t\t; if so then get out\n\tadd\tedi,eax\t\t\t\t\t; otherwise add in offset\n\n\t;*===================================================================\n\t; Verify that the Y pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[y_pixel]\t\t\t\t; get the y position\n\tcmp\teax,ecx\t\t\t\t\t;  is it out of bounds\n\tjae\t??exit\t\t\t\t\t; if so then get out\n\tadd\tedx,[(GraphicViewPort ebx).GVPXAdd]\t; otherwise find bytes per row\n\tmul\tedx\t\t\t\t\t; offset = bytes per row * y\n\tadd\tedi,eax\t\t\t\t\t; add it into the offset\n\n\t;*===================================================================\n\t; Write the pixel to the screen\n\t;*===================================================================\n\tmov\tal,[color]\t\t\t\t; read in color value\n\tmov\t[edi],al\t\t\t\t; write it to the screen\n??exit:\n\tret\n\tENDP\tMCGA_Put_Pixel\n\nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/REGIONSZ.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB 32                                 *\n *                                                                         *\n *                    File Name : REGIONSZ.CPP                             *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : November 3, 1994                         *\n *                                                                         *\n *                  Last Update : November 3, 1994   [PWG]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Size_Of_Region -- Calculates the size of a given region               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * SIZE_OF_REGION -- Calculates the size of a given region                 *\n *                                                                         *\n * INPUT:\tint width  - the width of the region                           *\n *\t\t\t\tint height - the height of the region\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:  long - the size of the region                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/03/1994 PWG : Created.                                             *\n *=========================================================================*/\nlong Size_Of_Region(int width, int height)                                 \n{\n\treturn(width * height);\n}\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/REMAP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : REMAP.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 1, 1994                             *\n;*                                                                         *\n;*                  Last Update : July 1, 1994   [PWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n\tPROC\tMCGA_Remap C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* Define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tthis\t:DWORD\n\tARG\tx0_pixel:DWORD\n\tARG\ty0_pixel:DWORD\n\tARG\twidth\t:DWORD\n\tARG\theight\t:DWORD\n\tARG\tremap\t:DWORD\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tlocal\tx1_pixel  : DWORD\n\tlocal\ty1_pixel  : DWORD\n\tlocal\twin_width : dword\n\tlocal\tcounter_x : dword\n\n\n\tcmp\t[ remap ] , 0\n\tjz\t??real_out\n\n; Clip Source Rectangle against source Window boundaries.\n\tmov  \tesi , [ this ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\tebx , [ x0_pixel ]\n\tmov\teax , [ x0_pixel ]\n\tadd\tebx , [ width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\tebx , [ y0_pixel ]\n\tmov\teax , [ y0_pixel ]\n\tadd\tebx , [ height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_remap\n\n\ttest\tcl , 1000b\n\tjz\t??scr_left_ok\n\tmov\t[ x0_pixel ] , 0\n\n??scr_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\t[ y0_pixel ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_remap\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n\n??do_remap:\n       cld\t\n       mov\tedi , [ (VideoViewPort esi) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort esi) . VIVPXAdd ]\n       mov\tebx , [ x1_pixel ]\n       add\teax , [ (VideoViewPort esi) . VIVPWidth ]\n       mov\tesi , eax\n       mul\t[ y0_pixel ]\n       add\tedi , [ x0_pixel ]\n       sub\tebx , [ x0_pixel ]\n       jle\t??real_out\n       add\tedi , eax\n       sub\tesi , ebx\n\n       mov\tecx , [ y1_pixel ]\n       sub\tecx , [ y0_pixel ]\n       jle\t??real_out\n       mov\teax , [ remap ]\n       mov\t[ counter_x ] , ebx\n       xor\tedx , edx\n\n??outer_loop:\n       mov\tebx , [ counter_x ]\n??inner_loop:\n       mov\tdl , [ edi ]\n       mov\tdl , [ eax + edx ]\t\n       mov\t[ edi ] , dl\n       inc\tedi\n       dec\tebx\n       jnz\t??inner_loop\n       add\tedi , esi\n       dec\tecx\n       jnz\t??outer_loop\n\n\n\n\n??real_out:\n\tret\n\n\tENDP\tMCGA_Remap\n\n\tEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/SCALE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : SCALE.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 16, 1994                            *\n;*                                                                         *\n;*                  Last Update : June 21, 1994   [PWG]                    *\n;*                  New version : feb 12, 1995  [JRJ]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVC::Scale -- Scales a virtual viewport to another virtual viewport   *\n;*   Normal_Draw -- jump loc for drawing  scaled line of normal pixel      *\n;*   Normal_Remapped_Draw -- jump loc for draw scaled line of remap pixel  *\n;*   Transparent_Draw -- jump loc for scaled line of transparent pixels    *\n;*   Transparent_Remapped_Draw -- jump loc for scaled remap trans pixels   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n\n;***************************************************************************\n;* VVC::SCALE -- Scales a virtual viewport to another virtual viewport     *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/16/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tLinear_Scale_To_Linear C NEAR\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* Define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tthis:DWORD\t\t; pointer to source view port\n\tARG\tdest:DWORD\t\t; pointer to destination view port\n\tARG\tsrc_x:DWORD\t\t; source x offset into view port\n\tARG\tsrc_y:DWORD\t\t; source y offset into view port\n\tARG\tdst_x:DWORD\t\t; dest x offset into view port\n\tARG\tdst_y:DWORD\t\t; dest y offset into view port\n\tARG\tsrc_width:DWORD\t\t; width of source rectangle\n\tARG\tsrc_height:DWORD\t; height of source rectangle\n\tARG\tdst_width:DWORD\t\t; width of dest rectangle\n\tARG\tdst_height:DWORD\t; width of dest height\n\tARG\ttrans:DWORD\t\t; is this transparent?\n\tARG\tremap:DWORD\t\t; pointer to table to remap source\n\n\t;*===================================================================\n\t;* Define local variables to hold the viewport characteristics\n\t;*===================================================================\n\tlocal\tsrc_x0 : dword\n\tlocal\tsrc_y0 : dword\n\tlocal\tsrc_x1 : dword\n\tlocal\tsrc_y1 : dword\n\n\tlocal\tdst_x0 : dword\n\tlocal\tdst_y0 : dword\n\tlocal\tdst_x1 : dword\n\tlocal\tdst_y1 : dword\n\n\tlocal\tsrc_win_width : dword\n\tlocal\tdst_win_width : dword\n\tlocal\tdy_intr : dword\n\tlocal\tdy_frac : dword\n\tlocal\tdy_acc  : dword\n\tlocal\tdx_frac : dword\n\n\tlocal\tcounter_x     : dword\n\tlocal\tcounter_y     : dword\n\tlocal\tremap_counter :dword\n\tlocal\tentry : dword\n\n\t;*===================================================================\n\t;* Check for scale error when to or from size 0,0\n\t;*===================================================================\n\tcmp\t[dst_width],0\n\tje\t??all_done\n\tcmp\t[dst_height],0\n\tje\t??all_done\n\tcmp\t[src_width],0\n\tje\t??all_done\n\tcmp\t[src_height],0\n\tje\t??all_done\n\n\tmov\teax , [ src_x ]\n\tmov\tebx , [ src_y ]\n\tmov\t[ src_x0 ] , eax \n\tmov\t[ src_y0 ] , ebx \n\tadd\teax , [ src_width ]\n\tadd\tebx , [ src_height ]\n\tmov\t[ src_x1 ] , eax \n\tmov\t[ src_y1 ] , ebx \n\n\tmov\teax , [ dst_x ]\n\tmov\tebx , [ dst_y ]\n\tmov\t[ dst_x0 ] , eax \n\tmov\t[ dst_y0 ] , ebx \n\tadd\teax , [ dst_width ]\n\tadd\tebx , [ dst_height ]\n\tmov\t[ dst_x1 ] , eax \n\tmov\t[ dst_y1 ] , ebx \n\n; Clip Source Rectangle against source Window boundaries.\n\tmov  \tesi , [ this ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ src_x0 ]\n\tmov\tebx , [ src_x1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\teax , [ src_y0 ]\n\tmov\tebx , [ src_y1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??all_done\n\tor\tal , dl\n\tjz\t??clip_against_dest\n\tmov\tbl , dl\n\ttest\tcl , 1000b\n\tjz\t??src_left_ok\n\txor\teax , eax\n\tmov\t[ src_x0 ] , eax\n\tsub\teax , [ src_x ]\n\timul\t[ dst_width ]\n\tidiv\t[ src_width ]\n\tadd\teax , [ dst_x ]\n\tmov\t[ dst_x0 ] , eax\n\n??src_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??src_bottom_ok\n\txor\teax , eax\n\tmov\t[ src_y0 ] , eax\n\tsub\teax , [ src_y ]\n\timul\t[ dst_height ]\n\tidiv\t[ src_height ]\n\tadd\teax , [ dst_y ]\n\tmov\t[ dst_y0 ] , eax\n\n??src_bottom_ok:\n\ttest\tbl , 0100b\n\tjz\t??src_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ src_x1 ] , eax\n\tsub\teax , [ src_x ]\n\timul\t[ dst_width ]\n\tidiv\t[ src_width ]\n\tadd\teax , [ dst_x ]\n\tmov\t[ dst_x1 ] , eax\n\n??src_right_ok:\n\ttest\tbl , 0001b\n\tjz\t??clip_against_dest\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ src_y1 ] , eax\n\tsub\teax , [ src_y ]\n\timul\t[ dst_height ]\n\tidiv\t[ src_height ]\n\tadd\teax , [ dst_y ] \n\tmov\t[ dst_y1 ] , eax\n\n; Clip destination Rectangle against source Window boundaries.\n??clip_against_dest:\n\tmov  \tesi , [ dest ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ dst_x0 ]\n\tmov\tebx , [ dst_x1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\teax , [ dst_y0 ]\n\tmov\tebx , [ dst_y1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??all_done\n\tor\tal , dl\n\tjz\t??do_scaling\n\tmov\tbl , dl\n\ttest\tcl , 1000b\n\tjz\t??dst_left_ok\n\txor\teax , eax\n\tmov\t[ dst_x0 ] , eax\n\tsub\teax , [ dst_x ]\n\timul\t[ src_width ]\n\tidiv\t[ dst_width ]\n\tadd\teax , [ src_x ]\n\tmov\t[ src_x0 ] , eax\n\n??dst_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dst_bottom_ok\n\txor\teax , eax\n\tmov\t[ dst_y0 ] , eax\n\tsub\teax , [ dst_y ]\n\timul\t[ src_height ]\n\tidiv\t[ dst_height ]\n\tadd\teax , [ src_y ]\n\tmov\t[ src_y0 ] , eax\n\n??dst_bottom_ok:\n\ttest\tbl , 0100b\n\tjz\t??dst_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ dst_x1 ] , eax\n\tsub\teax , [ dst_x ]\n\timul\t[ src_width ]\n\tidiv\t[ dst_width ]\n\tadd\teax , [ src_x ]\n\tmov\t[ src_x1 ] , eax\n\n??dst_right_ok:\n\ttest\tbl , 0001b\n\tjz\t??do_scaling\n\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ dst_y1 ] , eax\n\tsub\teax , [ dst_y ]\n\timul\t[ src_height ]\n\tidiv\t[ dst_height ]\n\tadd\teax , [ src_y ]\n\tmov\t[ src_y1 ] , eax\n\n??do_scaling:\n\n       cld\t\n       mov\tebx , [ this ]\n       mov\tesi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\t[ src_win_width ] , eax\n       mul\t[ src_y0 ]\n       add\tesi , [ src_x0 ]\n       add\tesi , eax\n\n       mov\tebx , [ dest ]\n       mov\tedi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\t[ dst_win_width ] , eax\n       mul\t[ dst_y0 ]\n       add\tedi , [ dst_x0 ]\n       add\tedi , eax\n\n       mov\teax , [ src_height ]\n       xor\tedx , edx\n       mov\tebx , [ dst_height ]\n       idiv\t[ dst_height ]\n       imul\teax , [ src_win_width ]\n       neg\tebx\n       mov\t[ dy_intr ] , eax\n       mov\t[ dy_frac ] , edx\n       mov\t[ dy_acc ]  , ebx\n\n       mov\teax , [ src_width ]\n       xor\tedx , edx\n       shl\teax , 16\n       idiv\t[ dst_width ]\n       xor\tedx , edx\n       shld\tedx , eax , 16\n       shl\teax , 16\n\n       mov\tecx , [ dst_y1 ]\n       mov\tebx , [ dst_x1 ]\n       sub\tecx , [ dst_y0 ]\n       jle\t??all_done\n       sub\tebx , [ dst_x0 ]\n       jle\t??all_done\n\n       mov\t[ counter_y ] , ecx\n\n       cmp\t[ trans ] , 0\n       jnz\t??transparency\n\n       cmp\t[ remap ] , 0\n       jnz\t??normal_remap\n\n; *************************************************************************\n; normal scale\n       mov\tecx , ebx\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 2 ]\n       shr\tebx , 5\n       neg\tecx\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??ref_point + ecx + ecx * 2 ]\n       mov\t[ entry ] , ecx\n\t\n ??outter_loop:\n       push\tesi\n       push\tedi\n       xor\tecx , ecx\n       mov\tebx , [ counter_x ]\n       jmp\t[ entry ]\n ??inner_loop:\n       REPT\t32\t\n\t       mov\tcl , [ esi ]\n\t       add\tecx , eax\n\t       adc\tesi , edx\n\t       mov\t[ edi ] , cl\n\t       inc\tedi\n       ENDM\n ??ref_point:\n       dec\tebx\n       jge\t??inner_loop\n\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??skip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??skip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??outter_loop\n\tret\n\n\n; *************************************************************************\n; normal scale with remap\n\n??normal_remap:\t\n       mov\tecx , ebx\n       mov\t[ dx_frac ], eax\n       and\tecx , 01fh\n       mov\teax , [ remap ]\n       shr\tebx , 5\n       imul\tecx , - 13\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??remapref_point + ecx ]\n       mov\t[ entry ] , ecx\n\n ??remapoutter_loop:\n       mov\tebx , [ counter_x ]\n       push\tesi\n       mov\t[ remap_counter ] , ebx\n       push\tedi\n       xor\tecx , ecx\n       xor\tebx , ebx\n       jmp\t[ entry ]\n ??remapinner_loop:\n       REPT\t32\t\n\t       mov\tbl , [ esi ]\n\t       add\tecx , [ dx_frac ]\n\t       adc\tesi , edx\n\t       mov\tcl , [ eax + ebx ]\n\t       mov\t[ edi ] , cl\n\t       inc\tedi\n       ENDM\n ??remapref_point:\n       dec\t[ remap_counter ] \n       jge\t??remapinner_loop\n\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??remapskip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??remapskip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??remapoutter_loop\n\tret\n\n\n;****************************************************************************\n; scale with trnsparency\n\n??transparency:\n       cmp\t[ remap ] , 0\n       jnz\t??trans_remap\n\n; *************************************************************************\n; normal scale with transparency\n       mov\tecx , ebx\n       and\tecx , 01fh\n       imul\tecx , -13\n       shr\tebx , 5\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??trans_ref_point + ecx ]\n       mov\t[ entry ] , ecx\n\n ??trans_outter_loop:\n       xor\tecx , ecx\n       push\tesi\n       push\tedi\n       mov\tebx , [ counter_x ]\n       jmp\t[ entry ]\n ??trans_inner_loop:\n       REPT\t32\t\n       local\ttrans_pixel\n\t       mov\tcl , [ esi ]\n\t       test\tcl , cl\n\t       jz\ttrans_pixel\n\t       mov\t[ edi ] , cl\n       trans_pixel:\n\t       add\tecx , eax\n\t       adc\tesi , edx\n\t       inc\tedi\n       ENDM\n ??trans_ref_point:\n       dec\tebx\n       jge\t??trans_inner_loop\n\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??trans_skip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??trans_skip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??trans_outter_loop\n\tret\n\n\n; *************************************************************************\n; normal scale with remap\n\n??trans_remap:\t\n       mov\tecx , ebx\n       mov\t[ dx_frac ], eax\n       and\tecx , 01fh\n       mov\teax , [ remap ]\n       shr\tebx , 5\n       imul\tecx , - 17\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??trans_remapref_point + ecx ]\n       mov\t[ entry ] , ecx\n\n ??trans_remapoutter_loop:\n       mov\tebx , [ counter_x ]\n       push\tesi\n       mov\t[ remap_counter ] , ebx\n       push\tedi\n       xor\tecx , ecx\n       xor\tebx , ebx\n       jmp\t[ entry ]\n ??trans_remapinner_loop:\n       REPT\t32\t\n       local\ttrans_pixel\n\t       mov\tbl , [ esi ]\n\t       test\tbl , bl\n\t       jz\ttrans_pixel\n\t       mov\tcl , [ eax + ebx ]\n\t       mov\t[ edi ] , cl\n\t  trans_pixel:\n\t       add\tecx , [ dx_frac ]\n\t       adc\tesi , edx\n\t       inc\tedi\n       ENDM\n ??trans_remapref_point:\n       dec\t[ remap_counter ] \n       jge\t??trans_remapinner_loop\n\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??trans_remapskip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??trans_remapskip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??trans_remapoutter_loop\n\tret\n\n\n\n\n\n??all_done:\n\tret\nendp\n\n\nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/SHADOW.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/source/rcs/./shadow.asm 1.9 1994/05/20 15:30:49 joe_bostic Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : SHADOW.ASM                               *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : February 28, 1995   [BG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n;* void Shadow_Blit(int xpix, int ypix, int width, int height, GVPC src, GVPC dst, void *shadowbuff);\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\nINCLUDE \".\\keystruc.inc\"\n\nGLOBAL\tShadow_Blit\t: NEAR\n\nGLOBAL\tRealModePtr : DWORD\nGLOBAL\tHide_Mouse  : NEAR\nGLOBAL\tShow_Mouse  : NEAR\n\n\tCODESEG\n\n; void Shadow_Blit(int xpix, int ypix, int width, int height, GVPC src, VBC dst, void *shadowbuff);\n; Warning: Shadow_Blit appears to be relatively stupid, in that while it is\n;\t   optimized to perform word or dword blits, it only does so if the\n;\t   entire region is word or dword-sized.  In other words, if you blit\n;\t   a region that is 200 pixels wide (clearly dword-sized), then it\n;\t   will use the dword loop.  However, if you blit a region that is\n;\t   201 pixels wide, the dumb thing will use the byte loop for the\n;\t   entire blit.\n\tPROC    Shadow_Blit C near\n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tARG\tx:DWORD\n\tARG\ty:DWORD\n\tARG\twidth:DWORD\n\tARG\theight:DWORD\n\tARG     srcpage:DWORD\n\tARG     dstpage:DWORD\n\tARG     shadow:DWORD\n\n\tLOCAL\tmodulo:DWORD\t\t; Row modulo\n\tLOCAL\thidemouse:DWORD\t\t; Was the mouse hidden?\n\tLOCAL\tdwordwidth:DWORD\n\tLOCAL\tbytewidth:DWORD\n\n\tcld                             ; Always move forward.\n\tmov\t[hidemouse],0\t\t; Presume mouse hasn't been hidden.\n\n; Fetch the segment of the seenpage.\n\tmov\tebx,[dstpage]\n\tmov\tebx,[(GraphicViewPort ebx).GVPOffset]\n\n\t; Determine if the mouse needs to be hidden at all.  If this happens to be\n\t; a shadow blit to non visible page (who knows why!?) then don't bother to\n\t; hide the mouse since it isn't necessary.\n;\tcmp\tebx,0A0000h\n;\tsetne\t[BYTE PTR hidemouse]\t; Flag that mouse need not be hidden.\n;\tjne\tshort ??itsok\n\tmov\tesi,[RealModePtr]\n\tcmp\t[(KeyboardType esi).MState],0\n\tje\tshort ??itsok\n\tmov\t[hidemouse],1\n\tcall\tHide_Mouse C\t\t; Hides mouse again (just to be sure).\n??itsok:\n\tmov\tedi,[srcpage]\n\tmov\tesi,[(GraphicViewPort edi).GVPOffset]\n\n\tmov\teax,[(GraphicViewPort edi).GVPWidth]\n\tadd\teax,[(GraphicViewPort edi).GVPXAdd]\n\tpush\teax\t\t\t; save width+xadd for later calc\n\tmov\tedx,[y]\n\tmul\tedx\n\tadd\teax,[x]\n\tadd\tesi,eax\n; At this point, esi points to the source page and ebx points to the dest page\n\tsub\tebx,esi\t\t\t; esi+ebx == dest page pointer\n\n\tmov\tedi,[shadow]             ; EDI points to shadow buffer.\n\n\tmov     ecx,[height]\t\t; get the height of the window in cx\n\n\tmov\tedx,[RealModePtr]\n\n\t; Calculate the row add module.\n\tpop\teax\t\t\t; restore width+xadd\n\tsub\teax,[width]\n\tmov\t[modulo],eax\n\n\tmov\teax,[width]\n\tshr\teax,2\n\tmov\t[dwordwidth],eax\n\tmov\teax,[width]\n\tand\teax,3\n\tmov\t[bytewidth],eax\n\n;---------------------------------------\n; DOUBLE WORD shadow blit if possible.\n;---------------------------------------\n??dloop_top:\n\tpush\tecx\n\tmov\tecx,[dwordwidth]\n\n??lcontinue:\n\trepe    cmpsd                   ; check the entire row for changed longs\n\tje      short ??loop_top\n\n\t; If this row would interfere with the mouse image, then hide it.\n\tcmp\t[hidemouse],0\n\tjnz\tshort ??dok\n\tmov\teax,[(KeyboardType edx).MouseY]\n\tsub\teax,[(KeyboardType edx).MouseYHot]\n\tcmp\teax,[y]\n\tjg\tshort ??dok\n\tadd\teax,[(KeyboardType edx).MouseHeight]\n\tcmp\teax,[y]\n\tjb\tshort ??dok\n\tmov\t[hidemouse],1\t\t; Manual hide of the mouse.\n\tcall\tHide_Mouse C\n??dok:\n\n\tmov     eax,[esi-4]\n\tmov     [ebx+esi-4],eax\t\t; Update destination page.\n\tmov     [edi-4],eax\t\t; Update shadow buffer.\n\tor\tecx,ecx\n\tjne     short ??lcontinue\n\n;---------------------------------------\n; Row loop start for BYTES.\n;---------------------------------------\n??loop_top:\n\tmov\tecx,[bytewidth]\n\n; Column loop start -- by bytes.\n??continue:\n\trepe    cmpsb                   ; check the entire row for changed longs\n\tje      short ??done_x\n\n\t; If this row would interfere with the mouse image, then hide it.\n\tcmp\t[hidemouse],0\n\tjnz\tshort ??bok\n\tmov\teax,[(KeyboardType edx).MouseY]\n\tsub\teax,[(KeyboardType edx).MouseYHot]\n\tcmp\teax,[y]\n\tjg\tshort ??bok\n\tadd\teax,[(KeyboardType edx).MouseHeight]\n\tcmp\teax,[y]\n\tjl\tshort ??bok\n\tmov\t[hidemouse],1\t\t; Manual hide of the mouse.\n\tcall\tHide_Mouse C\n??bok:\n\n\tmov     al,[esi-1]\n\tmov     [ebx+esi-1],al\t\t; Update destination page.\n\tmov     [edi-1],al\t\t; Update shadow buffer.\n\n\tor\tecx,ecx\n\tjne     short ??continue\n\n??done_x:\n\tinc\t[y]\n\tadd     esi,[modulo]\n\tpop     ecx\n\tloop    ??dloop_top\n\n??fini:\n\t; Re show the mouse if it was hidden by this routine.\n\tcmp\t[hidemouse],0\n\tje\tshort ??reallyfini\n\tcall\tShow_Mouse C\n??reallyfini:\n\tret\n\n\tENDP    Shadow_Blit\n\n\tEND\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/STAMP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : STAMP.ASM                                *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : August 23, 1993                          *\n;*                                                                         *\n;*                  Last Update : August 23, 1993   [JLB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nINCLUDE\t\"stamp.inc\"\n\n\tDATASEG\n\n\nLastIconset\tDD\t0\t; Pointer to last iconset initialized.\nStampPtr\tDD\t0\t; Pointer to icon data.\n\nIsTrans\t\tDD\t0\t; Pointer to transparent icon flag table.\n\nMapPtr\t\tDD\t0\t; Pointer to icon map.\nIconWidth\tDD\t0\t; Width of icon in pixels.\nIconHeight\tDD\t0\t; Height of icon in pixels.\nIconSize\tDD\t0\t; Number of bytes for each icon data.\nIconCount\tDD\t0\t; Number of icons in the set.\n\n\tEVEN\n\n\tCODESEG\n\n; 256 color icon system.\n\n;***********************************************************\n; INIT_STAMPS\n;\n; VOID cdecl Init_Stamps(VOID *icondata);\n;\n; This routine initializes the stamp data.\n; Bounds Checking: NONE\n;\n;*\n\tPROC\tInit_Stamps C near USES eax ebx edi\n\tARG\ticondata:DWORD\n\n\t; Verify legality of parameter.\n\tcmp\t[icondata],0\n\tje\tshort ??fini\n\n\t; Don't initialize if already initialized to this set (speed reasons).\n\tmov\tedi,[icondata]\n\tcmp\t[LastIconset],edi\n\tje\tshort ??fini\n\tmov\t[LastIconset],edi\n\n\t; Record number of icons in set.\n\tmovzx\teax,[(IControl_Type edi).Count]\n\tmov\t[IconCount],eax\n\n\t; Record width of icon.\n\tmovzx\teax,[(IControl_Type edi).Width]\n\tmov\t[IconWidth],eax\n\n\t; Record height of icon.\n\tmovzx\tebx,[(IControl_Type edi).Height]\n\tmov\t[IconHeight],ebx\n\n\t; Record size of icon (in bytes).\n\tmul\tebx\n\tmov\t[IconSize],eax\n\n\t; Record hard pointer to icon map data.\n\tmov\teax,[(IControl_Type edi).Map]\n\tadd\teax,edi\n\tmov\t[MapPtr],eax\n\n??nomap:\n\t; Record hard pointer to icon data.\n\tmov\teax,edi\n\tadd\teax,[(IControl_Type edi).Icons]\n\tmov\t[StampPtr],eax\n\n\t; Record the transparent table.\n\tmov\teax,edi\n\tadd\teax,[(IControl_Type edi).TransFlag]\n\tmov\t[IsTrans],eax\n\n??fini:\n\tret\n\n\tENDP\tInit_Stamps\n\n\n;***********************************************************\n\n\n;***********************************************************\n; DRAW_STAMP\n;\n; VOID cdecl MCGA_Draw_Stamp(VOID *icondata, WORD icon, WORD x_pixel, WORD y_pixel, VOID *remap);\n;\n; This routine renders the icon at the given coordinate.\n;\n; The remap table is a 256 byte simple pixel translation table to use when\n; drawing the icon.  Transparency check is performed AFTER the remap so it is possible to\n; remap valid colors to be invisible (for special effect reasons).\n; This routine is fastest when no remap table is passed in.\n;*\n\tPROC\tMCGA_Draw_Stamp C near\n\n\tARG\tthis:DWORD\t\t; this is a member function\n\tARG\ticondata:DWORD\t\t; Pointer to icondata.\n\tARG\ticon:DWORD\t\t; Icon number to draw.\n\tARG\tx_pixel:DWORD\t\t; X coordinate of icon.\n\tARG\ty_pixel:DWORD\t\t; Y coordinate of icon.\n\tARG\tremap:DWORD \t\t; Remap table.\n\n\tLOCAL\tmodulo:DWORD\t\t; Modulo to get to next row.\n\tLOCAL\tiwidth:DWORD\t\t; Icon width (here for speedy access).\n\tLOCAL\tdoremap:BYTE\t\t; Should remapping occur?\n\n\tpushad\n\tcmp\t[icondata],0\n\tje\t??out\n\n\t; Initialize the stamp data if necessary.\n\tmov\teax,[icondata]\n\tcmp\t[LastIconset],eax\n\tje\tshort ??noreset\n\tcall\tInit_Stamps C,eax\n??noreset:\n\n\t; Determine if the icon number requested is actually in the set.\n\t; Perform the logical icon to actual icon number remap if necessary.\n\tmov\tebx,[icon]\n\tcmp\t[MapPtr],0\n\tje\tshort ??notmap\n\tmov\tedi,[MapPtr]\n\tmov\tbl,[edi+ebx]\n??notmap:\n\tcmp\tebx,[IconCount]\n\tjae\t??out\n\tmov\t[icon],ebx\t\t; Updated icon number.\n\n\t; If the remap table pointer passed in is NULL, then flag this condition\n\t; so that the faster (non-remapping) icon draw loop will be used.\n\tcmp\t[remap],0\n\tsetne\t[doremap]\n\n\t; Get pointer to position to render icon. EDI = ptr to destination page.\n\tmov\tebx,[this]\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\n\tpush\teax\t\t\t; save viewport full width for lower\n\tmul\t[y_pixel]\n\tadd\tedi,eax\n\tadd\tedi,[x_pixel]\n\n\t; Determine row modulo for advancing to next line.\n\tpop\teax\t\t\t; retrieve viewport width\n\tsub\teax,[IconWidth]\n\tmov\t[modulo],eax\n\n\t; Setup some working variables.\n\tmov\tecx,[IconHeight]\t; Row counter.\n\tmov\teax,[IconWidth]\n\tmov\t[iwidth],eax\t\t; Stack copy of byte width for easy BP access.\n\n\t; Fetch pointer to start of icon's data.  ESI = ptr to icon data.\n\tmov\teax,[icon]\n\tmul\t[IconSize]\n\tmov\tesi,[StampPtr]\n\tadd\tesi,eax\n\n\t; Determine whether simple icon draw is sufficient or whether the\n\t; extra remapping icon draw is needed.\n\tcmp\t[BYTE PTR doremap],0\n\tje\tshort ??istranscheck\n\n\t;************************************************************\n\t; Complex icon draw -- extended remap.\n\t; EBX = Palette pointer (ready for XLAT instruction).\n\t; EDI = Pointer to icon destination in page.\n\t; ESI = Pointer to icon data.\n\t; ECX = Number of pixel rows.\n;;;\tmov\tedx,[remap]\n mov ebx,[remap]\n\txor\teax,eax\n??xrowloop:\n\tpush\tecx\n\tmov\tecx,[iwidth]\n\n??xcolumnloop:\n\tlodsb\n;;;\tmov\tebx,edx\n;;;\tadd\tebx,eax\n;;;\tmov\tal,[ebx]\t\t; New real color to draw.\n xlatb\n\tor\tal,al\n\tjz\tshort ??xskip1\t\t; Transparency skip check.\n\tmov\t[edi],al\n??xskip1:\n\tinc\tedi\n\tloop\t??xcolumnloop\n\n\tpop\tecx\n\tadd\tedi,[modulo]\n\tloop\t??xrowloop\n\tjmp\tshort ??out\n\n\n\t;************************************************************\n\t; Check to see if transparent or generic draw is necessary.\n??istranscheck:\n\tmov\tebx,[IsTrans]\n\tadd\tebx,[icon]\n\tcmp\t[BYTE PTR ebx],0\n\tjne\tshort ??rowloop\n\n\t;************************************************************\n\t; Fast non-transparent icon draw routine.\n\t; ES:DI = Pointer to icon destination in page.\n\t; DS:SI = Pointer to icon data.\n\t; CX = Number of pixel rows.\n\tmov\tebx,ecx\n\tshr\tebx,2\n\tmov\tedx,[modulo]\n\tmov\teax,[iwidth]\n\tshr\teax,2\n??loop1:\n\tmov\tecx,eax\n\trep movsd\n\tadd\tedi,edx\n\n\tmov\tecx,eax\n\trep movsd\n\tadd\tedi,edx\n\n\tmov\tecx,eax\n\trep movsd\n\tadd\tedi,edx\n\n\tmov\tecx,eax\n\trep movsd\n\tadd\tedi,edx\n\n\tdec\tebx\n\tjnz\t??loop1\n\tjmp\tshort ??out\n\n\t;************************************************************\n\t; Transparent icon draw routine -- no extended remap.\n\t; ES:DI = Pointer to icon destination in page.\n\t; DS:SI = Pointer to icon data.\n\t; CX = Number of pixel rows.\n??rowloop:\n\tpush\tecx\n\tmov\tecx,[iwidth]\n\n??columnloop:\n\tlodsb\n\tor\tal,al\n\tjz\tshort ??skip1\t\t; Transparency check.\n\tmov\t[edi],al\n??skip1:\n\tinc\tedi\n\tloop\t??columnloop\n\n\tpop\tecx\n\tadd\tedi,[modulo]\n\tloop\t??rowloop\n\n\t; Cleanup and exit icon drawing routine.\n??out:\n\tpopad\n\tret\n\n\tENDP\tMCGA_Draw_Stamp\n\n;***********************************************************\n; DRAW_STAMP_CLIP\n;\n; VOID cdecl MCGA_Draw_Stamp_Clip(VOID *icondata, WORD icon, WORD x_pixel, WORD y_pixel, VOID *remap, LONG min_x, LONG min_y, LONG max_x, LONG max_y);\n;\n; This routine renders the icon at the given coordinate.\n;\n; The remap table is a 256 byte simple pixel translation table to use when\n; drawing the icon.  Transparency check is performed AFTER the remap so it is possible to\n; remap valid colors to be invisible (for special effect reasons).\n; This routine is fastest when no remap table is passed in.\n;*\n\tPROC\tMCGA_Draw_Stamp_Clip C near\n\n\tARG\tthis:DWORD\t\t; this is a member function\n\tARG\ticondata:DWORD\t\t; Pointer to icondata.\n\tARG\ticon:DWORD\t\t; Icon number to draw.\n\tARG\tx_pixel:DWORD\t\t; X coordinate of icon.\n\tARG\ty_pixel:DWORD\t\t; Y coordinate of icon.\n\tARG\tremap:DWORD \t\t; Remap table.\n\tARG\tmin_x:DWORD\t\t; Clipping rectangle boundary\n\tARG\tmin_y:DWORD\t\t; Clipping rectangle boundary\n\tARG\tmax_x:DWORD\t\t; Clipping rectangle boundary\n\tARG\tmax_y:DWORD\t\t; Clipping rectangle boundary\n\n\tLOCAL\tmodulo:DWORD\t\t; Modulo to get to next row.\n\tLOCAL\tiwidth:DWORD\t\t; Icon width (here for speedy access).\n\tLOCAL\tskip:DWORD\t\t; amount to skip per row of icon data\n\tLOCAL\tdoremap:BYTE\t\t; Should remapping occur?\n\n\tpushad\n\tcmp\t[icondata],0\n\tje\t??out2\n\n\t; Initialize the stamp data if necessary.\n\tmov\teax,[icondata]\n\tcmp\t[LastIconset],eax\n\tje\tshort ??noreset2\n\tcall\tInit_Stamps C,eax\n??noreset2:\n\n\t; Determine if the icon number requested is actually in the set.\n\t; Perform the logical icon to actual icon number remap if necessary.\n\tmov\tebx,[icon]\n\tcmp\t[MapPtr],0\n\tje\tshort ??notmap2\n\tmov\tedi,[MapPtr]\n\tmov\tbl,[edi+ebx]\n??notmap2:\n\tcmp\tebx,[IconCount]\n\tjae\t??out2\n\tmov\t[icon],ebx\t\t; Updated icon number.\n\n\t; Setup some working variables.\n\tmov\tecx,[IconHeight]\t; Row counter.\n\tmov\teax,[IconWidth]\n\tmov\t[iwidth],eax\t\t; Stack copy of byte width for easy BP access.\n\n\t; Fetch pointer to start of icon's data.  ESI = ptr to icon data.\n\tmov\teax,[icon]\n\tmul\t[IconSize]\n\tmov\tesi,[StampPtr]\n\tadd\tesi,eax\n\n\t; Update the clipping window coordinates to be valid maxes instead of width & height\n\t; , and change the coordinates to be window-relative\n\tmov\tebx,[min_x]\n\tadd\t[max_x],ebx\n\tadd\t[x_pixel],ebx\t\t; make it window-relative\n\tmov\tebx,[min_y]\n\tadd\t[max_y],ebx\n\tadd\t[y_pixel],ebx\t\t; make it window-relative\n\n\t; See if the icon is within the clipping window\n\t; First, verify that the icon position is less than the maximums\n\tmov\tebx,[x_pixel]\n\tcmp\tebx,[max_x]\n\tjge\t??out2\n\tmov\tebx,[y_pixel]\n\tcmp\tebx,[max_y]\n\tjge\t??out2\n\t; Now verify that the icon position is >= the minimums\n\tadd\tebx,[IconHeight]\n\tcmp\tebx,[min_y]\n\tjle\t??out2\n\tmov\tebx,[x_pixel]\n\tadd\tebx,[IconWidth]\n\tcmp\tebx,[min_x]\n\tjle\t??out2\n\n\t; Now, clip the x, y, width, and height variables to be within the\n\t; clipping rectangle\n\tmov\tebx,[x_pixel]\n\tcmp\tebx,[min_x]\n\tjge\t??nominxclip\n\t; x < minx, so must clip\n\tmov\tebx,[min_x]\n\tsub\tebx,[x_pixel]\t\n\tadd\tesi,ebx\t\t; source ptr += (minx - x)\n\tsub\t[iwidth],ebx\t; icon width -= (minx - x)\n\tmov\tebx,[min_x]\n\tmov\t[x_pixel],ebx\n\n??nominxclip:\n\tmov\teax,[IconWidth]\n\tsub\teax,[iwidth]\n\tmov\t[skip],eax\n\n\t; Check for x+width > max_x\n\tmov\teax,[x_pixel]\n\tadd\teax,[iwidth]\n\tcmp\teax,[max_x]\n\tjle\t??nomaxxclip\n\t; x+width is greater than max_x, so must clip width down\n\tmov\teax,[iwidth]\t; eax = old width\n\tmov\tebx,[max_x]\n\tsub\tebx,[x_pixel]\n\tmov\t[iwidth],ebx\t; iwidth = max_x - xpixel\n\tsub\teax,ebx\n\tadd\t[skip],eax\t; skip += (old width - iwidth)\n??nomaxxclip:\n\t; check if y < miny\n\tmov\teax,[min_y]\n\tcmp\teax,[y_pixel]\t; if(miny <= y_pixel), no clip needed\n\tjle\t??nominyclip\n\tsub\teax,[y_pixel]\n\tsub\tecx,eax\t\t; height -= (miny - y)\n\tmul\t[IconWidth]\n\tadd\tesi,eax\t\t; icon source ptr += (width * (miny - y))\n\tmov\teax,[min_y]\n\tmov\t[y_pixel],eax\t; y = miny\n??nominyclip:\n\t; check if (y+height) > max y\n\tmov\teax,[y_pixel]\n\tadd\teax,ecx\n\tcmp\teax,[max_y]\t; if (y + height <= max_y), no clip needed\n\tjle\t??nomaxyclip\n\tmov\tecx,[max_y]\t; height = max_y - y_pixel\n\tsub\tecx,[y_pixel]\n??nomaxyclip:\n\n\t; If the remap table pointer passed in is NULL, then flag this condition\n\t; so that the faster (non-remapping) icon draw loop will be used.\n\tcmp\t[remap],0\n\tsetne\t[doremap]\n\n\t; Get pointer to position to render icon. EDI = ptr to destination page.\n\tmov\tebx,[this]\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\n\tpush\teax\t\t\t; save viewport full width for lower\n\tmul\t[y_pixel]\n\tadd\tedi,eax\n\tadd\tedi,[x_pixel]\n\n\t; Determine row modulo for advancing to next line.\n\tpop\teax\t\t\t; retrieve viewport width\n\tsub\teax,[iwidth]\n\tmov\t[modulo],eax\n\n\t; Determine whether simple icon draw is sufficient or whether the\n\t; extra remapping icon draw is needed.\n\tcmp\t[BYTE PTR doremap],0\n\tje\tshort ??istranscheck2\n\n\t;************************************************************\n\t; Complex icon draw -- extended remap.\n\t; EBX = Palette pointer (ready for XLAT instruction).\n\t; EDI = Pointer to icon destination in page.\n\t; ESI = Pointer to icon data.\n\t; ECX = Number of pixel rows.\n\tmov\tebx,[remap]\n\txor\teax,eax\n??xrowloopc:\n\tpush\tecx\n\tmov\tecx,[iwidth]\n\n??xcolumnloopc:\n\tlodsb\n\txlatb\n\tor\tal,al\n\tjz\tshort ??xskip1c\t\t; Transparency skip check.\n\tmov\t[edi],al\n??xskip1c:\n\tinc\tedi\n\tloop\t??xcolumnloopc\n\n\tpop\tecx\n\tadd\tedi,[modulo]\n add esi,[skip]\n\tloop\t??xrowloopc\n\tjmp\tshort ??out2\n\n\n\t;************************************************************\n\t; Check to see if transparent or generic draw is necessary.\n??istranscheck2:\n\tmov\tebx,[IsTrans]\n\tadd\tebx,[icon]\n\tcmp\t[BYTE PTR ebx],0\n\tjne\tshort ??rowloopc\n\n\t;************************************************************\n\t; Fast non-transparent icon draw routine.\n\t; ES:DI = Pointer to icon destination in page.\n\t; DS:SI = Pointer to icon data.\n\t; CX = Number of pixel rows.\n\tmov\tebx,ecx\n\tmov\tedx,[modulo]\n\tmov\teax,[iwidth]\n\n\t; Check for dword-optimized loop possible\n\ttest\teax,3\n\tjnz\t??loop1c\t; if eax & 3, must use byte loop\n\tshr\teax,2\n??loop1dw:\n\tmov\tecx,eax\n\trep movsd\n\tadd\tedi,edx\n\tadd\tesi,[skip]\n\tdec\tebx\n\tjnz\t??loop1dw\n\tjmp\tshort ??out2\n\n??loop1c:\n\tmov\tecx,eax\n\trep movsb\n\tadd\tedi,edx\n\tadd\tesi,[skip]\n\n\tdec\tebx\n\tjnz\t??loop1c\n\tjmp\tshort ??out2\n\n\t;************************************************************\n\t; Transparent icon draw routine -- no extended remap.\n\t; ES:DI = Pointer to icon destination in page.\n\t; DS:SI = Pointer to icon data.\n\t; CX = Number of pixel rows.\n??rowloopc:\n\tpush\tecx\n\tmov\tecx,[iwidth]\n\n??columnloopc:\n\tlodsb\n\tor\tal,al\n\tjz\tshort ??skip1c\t\t; Transparency check.\n\tmov\t[edi],al\n??skip1c:\n\tinc\tedi\n\tloop\t??columnloopc\n\n\tpop\tecx\n\tadd\tedi,[modulo]\n add esi,[skip]\n\tloop\t??rowloopc\n\n\t; Cleanup and exit icon drawing routine.\n??out2:\n\tpopad\n\tret\n\n\tENDP\tMCGA_Draw_Stamp_Clip\n\n\tEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/STAMP.BAK",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; This is the control structure at the start of a loaded icon set.  It must match\n; the structure in ICONSET.C!  This structure MUST be a multiple of 16 bytes long.\n\tSTRUC\tIControl_Type\nWidth\t\tDW\t?\t; Width in pixels (per icon).\nHeight\t\tDW\t?\t; Height in pixels (per icon).\nCount\t\tDW\t?\t; Number of icons in this set.\nAllocated\tDW\t?\t; Was this iconset allocated?\nMapWidth\tDW\t?\t; Width of icon map (in icons).\nMapHeight\tDW\t?\t; Height of icon map (in icons).\nSize\t\tDD\t?\t; Size of entire iconset memory block.\nIcons\t\tDD\t?\t; Offset from buffer start to icon data.\nPalettes\tDD\t?\t; Offset from buffer start to palette data.\nRemaps\t\tDD\t?\t; Offset from buffer start to remap index data.\nTransFlag\tDD\t?\t; Offset for transparency flag data.\nColorMap\tDD ?\t; Color control map offset.\nMap\t\tDD\t?\t; Icon map offset.\n\tENDS\n\nICON256\tEQU\t1\n\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/STAMP.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; This is the control structure at the start of a loaded icon set.  It must match\n; the structure in ICONSET.C!\n\tSTRUC\tIControl_Type\nWidth\t\tDW\t?\t; Width in pixels (per icon).\nHeight\t\tDW\t?\t; Height in pixels (per icon).\nCount\t\tDW\t?\t; Number of icons in this set.\nAllocated\tDW\t?\t; Was this iconset allocated?\nMapWidth\tDW\t?\t; Width of icon map (in icons).\nMapHeight\tDW\t?\t; Height of icon map (in icons).\nSize\t\tDD\t?\t; Size of entire iconset memory block.\nIcons\t\tDD\t?\t; Offset from buffer start to icon data.\nPalettes\tDD\t?\t; Offset from buffer start to palette data.\nRemaps\t\tDD\t?\t; Offset from buffer start to remap index data.\nTransFlag\tDD\t?\t; Offset for transparency flag data.\nColorMap\tDD\t?\t; Color control map offset.\nMap\t\tDD\t?\t; Icon map offset.\n\tENDS\n\nICON256\tEQU\t1\n\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/SZREGION.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Calculate size of an MCGA region\t   *\n;*                                                                         *\n;*                    File Name : REGIONSZ.ASM                             *\n;*                                                                         *\n;*                   Programmer : Barry W. Green\t\t\t   *\n;*                                                                         *\n;*                   Start Date : March 1, 1995\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : March 1, 1995  [BWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVPC::Size_Of_Region - calculate MCGA region size\t\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nGLOBAL\tMCGA_Size_Of_Region\t: NEAR\n\nCODESEG\n\n;***************************************************************************\n;* VVPC::Size_Of_Region - calculate MCGA region size\t\t\t   *\n;*                                                                         *\n;* INPUT:\tDWORD the width of the region\t\t\t\t   *\n;*                                                                         *\n;*\t\tDWORD the height of the region\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      calculated size of the region (MCGA = width * height)      *\n;*                                                                         *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   03/01/1995 BWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tMCGA_Size_Of_Region C near \n\tUSES\tebx,ecx,edx\n\n\tARG    \tthis:DWORD\t\t\t\t; this is a member function\n\tARG\twidth:DWORD\t\t\t\t; width of region\n\tARG\theight:DWORD\t\t\t\t; height of region\n\n\t;*===================================================================\n\t; Get the viewport information\n\t;*===================================================================\n\tmov\tebx,[this]\t\t\t\t; get a pointer to viewport\n\txor\teax,eax\t\t\t\t\t\n\tmov\tecx,[(GraphicViewPort ebx).GVPHeight]\t; ecx = height of viewport\n\tmov\tedx,[(GraphicViewPort ebx).GVPWidth]\t; edx = width of viewport\n\n\t;*===================================================================\n\t; Verify that the width is legal\n\t;*===================================================================\n\tmov\teax,[width]\t\t\t\t; find the width\n\tcmp\teax,edx\t\t\t\t\t; is it too wide?\n\tjb\tshort ??wok\t\t\t\t; if not, leave it alone\n\tmov\teax,edx\t\t\t\t\t; otherwise clip it\n\n\t;*===================================================================\n\t; Verify that the height is ok\n\t;*===================================================================\n??wok:\tmov\tebx,[height]\t\t\t\t; get the height\n\tcmp\tebx,ecx\t\t\t\t\t; is it too tall?\n\tjb\t??hok\t\t\t\t\t; if not, leave it alone\n\tmov\tebx,ecx\t\t\t\t\t; otherwise clip it\n\n\t;*===================================================================\n\t; Now multiply 'em to calculate the size of the region\n\t;*===================================================================\n??hok:\tmul\tebx\t\t\t\t\t; size = w * h\n\n\tret\n\tENDP\tMCGA_Size_Of_Region\n\n\tEND\n\n\u001a"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/TOBUFF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TOBUFFER.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                  Last Update : Feb 10, 1995   [jrj]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVC::TOBUFFER -- Copies a virtual viewport to a linear buffer         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\n\nTRANSP equ 0\n\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n\n;***************************************************************************\n;* VIVC::TOBUFFER -- Copies a virtual viewport to a linear buffer          *\n;*                                                                         *\n;* INPUT:\tBYTE *\tdest\t\t- buffer to copy to\t\t   *\n;*\t\t\tsize\t\t- size of the buffer to copy to\t   *\n;*\t\t\tx_pixel\t\t- x pixel on viewport to copy from *\n;*\t\t\ty_pixel \t- y pixel on viewport to copy from *\n;*\t\t\tpixel_width\t- the width of copy region\t   *\n;*\t\t\tpixel_height\t- the height of copy region\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    Coordinates and dimensions will be adjusted if they exceed *\n;*\t        the boundaries.  In the event that no adjustment is \t   *\n;*\t        possible this routine will abort.  If the size of the \t   *\n;*\t\tregion to copy exceeds the size passed in for the buffer   *\n;*\t\tthe routine will automatically abort.\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tMCGA_To_Buffer C near \n\tUSES\tebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tthis:DWORD\t\t; this is a class member function\n\tARG\tx_pixel:DWORD\t\t; Page X pixel coordinate.\n\tARG\ty_pixel:DWORD\t\t; Page Y pixel coordinate.\n\tARG\tpixel_width:DWORD\t; Width of region in pixels.\n\tARG\tpixel_height:DWORD\t; Height of region in pixels.\n\tARG\tdest:DWORD\t\t; the buffer to copy to\n\tARG\tsize:DWORD\t\t; the size of the buffer\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tLOCAL\tdest_x1 : dword\n\tLOCAL\tdest_y1 : dword\n\tLOCAL\tdest_ajust_width:DWORD\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_area   :  dword\n\n; Clip dest Rectangle against source Window boundaries.\n\n\tmov\t[ dest_x1 ] , 0 \n\tmov\t[ dest_y1 ] , 0 \n\n\tmov  \tesi , [ this ]\t    ; get ptr to dest\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_blit\n\t\t\t    \n\ttest\tcl , 1000b\n\tjz\t??scr_left_ok\n\tmov\teax , [ x_pixel ] \n\tneg\teax\n\tmov\t[ x_pixel ] , 0\n\tmov\t[ dest_x1 ] , eax\n\n??scr_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??scr_bottom_ok\n \tmov\teax , [ y_pixel ] \n\tneg\teax\n\tmov\t[ y_pixel ] , 0\n\tmov\t[ dest_y1 ] , eax\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n??do_blit:\n\n       cld\t\n\n       mov\teax , [ (VideoViewPort esi) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort esi) . VIVPWidth ]\n       mov\tesi , [ (VideoViewPort esi) . VIVPOffset ]\n\n       mov\tecx , eax\n       mul\t[ y_pixel ]\n       add\tesi , [ x_pixel ]\n       add\tesi , eax\n\n       add\tecx , [ x_pixel ]\n       sub\tecx , [ x1_pixel ]\n       mov\t[ scr_ajust_width ] , ecx\n\n       mov\tedi , [ dest ]\n       mov\teax , [ pixel_width ]\n       sub\teax , [ x1_pixel ]\n       add\teax , [ x_pixel ]\n       mov\t[ dest_ajust_width ] , eax\n\n       mov\teax , [ dest_y1 ]\n       mul \t[ pixel_width ]\n       add\teax , [ dest_x1 ]\n       add\tedi , eax\n\n       mov\tedx , [ y1_pixel ]\n       mov\teax , [ x1_pixel ]\n       sub\tedx , [ y_pixel ]\n       jle\t??real_out\n       sub\teax , [ x_pixel ]\n       jle\t??real_out\n\n       mov\tebx , [ pixel_width ]\n       imul\tebx , edx\n       cmp\tebx , [ size ]\n       jg\t??real_out\t\t\n\n\n; ********************************************************************       \n; Forward bitblit only\n\nIF TRANSP\n       cmp\t[ transp ] , 0\n       jnz\t??forward_Blit_trans\nENDIF\n\n; the inner loop is so efficient that \n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10        \n       jl\t??forward_loop_bytes\n\n??forward_loop_dword:\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_dword\n       ret\n\n??forward_loop_bytes:\n       mov\tecx , eax\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_bytes\n       ret\n\n\nIF  TRANSP\n\n??forward_Blit_trans:\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\t\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n??forward_loop_trans:\n       mov\tecx , eax \n       jmp\t[ y1_pixel ]\n??forward_trans_line:\n       REPT\t32\t\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tesi\n\t    \tinc\tedi\n\tENDM\n    ??transp_reference:\n       dec\tecx \n       jge\t??forward_trans_line\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_trans\n       ret\nENDIF\n\n??real_out:\n       ret\n\nENDP\tMCGA_To_Buffer\n\nEND\n\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/TOPAGE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TOPAGE.ASM                               *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : June 15, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Buffer_To_Page -- Copies a linear buffer to a virtual viewport\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nTRANSP\tequ  0\n\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nCODESEG\n\n;***************************************************************************\n;* VVC::TOPAGE -- Copies a linear buffer to a virtual viewport\t\t   *\n;*                                                                         *\n;* INPUT:\tWORD\tx_pixel\t\t- x pixel on viewport to copy from *\n;*\t\tWORD\ty_pixel \t- y pixel on viewport to copy from *\n;*\t\tWORD\tpixel_width\t- the width of copy region\t   *\n;*\t\tWORD\tpixel_height\t- the height of copy region\t   *\n;*\t\tBYTE *\tsrc\t\t- buffer to copy from\t\t   *\n;*\t\tVVPC *  dest\t\t- virtual viewport to copy to\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    Coordinates and dimensions will be adjusted if they exceed *\n;*\t        the boundaries.  In the event that no adjustment is \t   *\n;*\t        possible this routine will abort.  If the size of the \t   *\n;*\t\tregion to copy exceeds the size passed in for the buffer   *\n;*\t\tthe routine will automatically abort.\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tMCGA_Buffer_To_Page C near \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\tARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\tARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\tARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\tARG    \tsrc         :DWORD\t\t; this is a member function\n\tARG\tdest        :DWORD\t\t; what are we blitting to\n\n;\tARG\ttrans       :DWORD\t\t\t; do we deal with transparents?\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tlocal\tscr_x \t: dword\t\n\tlocal\tscr_y \t: dword\t\n\tLOCAL\tdest_ajust_width:DWORD\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_area   :  dword\n\n\tcmp\t[ src ] , 0\n\tjz\t??real_out\n\n\n; Clip dest Rectangle against source Window boundaries.\n\n\tmov\t[ scr_x ] , 0 \n\tmov\t[ scr_y ] , 0 \n\tmov  \tesi , [ dest ]\t    ; get ptr to dest\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_blit\n\n\ttest\tcl , 1000b\n\tjz\t??dest_left_ok\n\tmov\teax , [ x_pixel ]\n\tneg\teax \n\tmov\t[ x_pixel ] , 0\n\tmov\t[ scr_x ] , eax\n\n??dest_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dest_bottom_ok\n\tmov\teax , [ y_pixel ]\n\tneg\teax \n\tmov\t[ y_pixel ] , 0\n\tmov\t[ scr_y ] , eax\n\n??dest_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??dest_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??dest_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n??do_blit:\n\n       cld\t\n\n       mov\teax , [ (VideoViewPort esi) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort esi) . VIVPWidth ]\n       mov\tedi , [ (VideoViewPort esi) . VIVPOffset ]\n\n       mov\tecx , eax\n       mul\t[ y_pixel ]\n       add\tedi , [ x_pixel ]\n       add\tedi , eax\n\n       add\tecx , [ x_pixel ]\n       sub\tecx , [ x1_pixel ]\n       mov\t[ dest_ajust_width ] , ecx\n\n\n       mov\tesi , [ src ]\n       mov\teax , [ pixel_width ]\n       sub\teax , [ x1_pixel ]\n       add\teax , [ x_pixel ]\n       mov\t[ scr_ajust_width ] , eax\n\n       mov\teax , [ scr_y ]\n       mul \t[ pixel_width ]\n       add\teax , [ scr_x ]\n       add\tesi , eax\n\n       mov\tedx , [ y1_pixel ]\n       mov\teax , [ x1_pixel ]\n\n       sub\tedx , [ y_pixel ]\n       jle\t??real_out\n       sub\teax , [ x_pixel ]\n       jle\t??real_out\n\n\n; ********************************************************************       \n; Forward bitblit only\n\nIF TRANSP\n       test\t[ trans ] , 1\n       jnz\t??forward_Blit_trans\nENDIF\n\n\n; the inner loop is so efficient that \n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10        \n       jl\t??forward_loop_bytes\n\n??forward_loop_dword:\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_dword\n       ret\n\n??forward_loop_bytes:\n       mov\tecx , eax\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_bytes\n       ret\n\nIF  TRANSP\n\n\n??forward_Blit_trans:\n\n\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\t\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n\n??forward_loop_trans:\n       mov\tecx , eax \n       jmp\t[ y1_pixel ]\n??forward_trans_line:\n       REPT\t32\t\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\tinc\tesi\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tedi\n\tENDM\n    ??transp_reference:\n       dec\tecx \n       jge\t??forward_trans_line\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_trans\n       ret\nENDIF\n\n??real_out:\n       ret\n\n\n\tENDP\tMCGA_Buffer_To_Page \nEND\n\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/TXTPRNT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TXTPRNT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 17, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 17, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   MCGA_Print -- Assembly MCGA text print routine                        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n;*=========================================================================*\n;* Extern the font pointer which is defined by the font class\t\t   *\n;*=========================================================================*\nGLOBAL\tFontPtr:DWORD\nGLOBAL\tFontXSpacing:DWORD\nGLOBAL\tFontYSpacing:DWORD\nGLOBAL\tColorXlat:BYTE\n\n;*=========================================================================*\n;* Define the necessary equates for structures and bounds checking\t   *\n;*=========================================================================*\n; The header of the font file looks like this:\n; \tUWORD\tFontLength;\t\t0\n; \tBYTE\tFontCompress;\t\t2\n;\tBYTE\tFontDataBlocks;\t\t3\n;\tUWORD\tInfoBlockOffset;\t4\n;\tUWORD\tOffsetBlockOffset;\t6\n;\tUWORD\tWidthBlockOffset;\t8\n;\tUWORD\tDataBlockOffset;\t10\n;\tUWORD\tHeightOffset;\t\t12\n; For this reason the following equates have these values:\nFONTINFOBLOCK\t\tEQU\t4\nFONTOFFSETBLOCK\t\tEQU\t6\nFONTWIDTHBLOCK\t\tEQU\t8\nFONTDATABLOCK\t\tEQU\t10\nFONTHEIGHTBLOCK\t\tEQU\t12\n\nFONTINFOMAXHEIGHT\tEQU\t4\nFONTINFOMAXWIDTH\tEQU\t5\n\n\nLOCALS ??\n;*=========================================================================*\n;* Define the color xlate table in the data segment\t\t\t   *\n;*=========================================================================*\n\tDATASEG\n\nColorXlat\tDB\t000H,001H,002H,003H,004H,005H,006H,007H\n\t\tDB\t008H,009H,00AH,00BH,00CH,00DH,00EH,00FH\n\n\t\tDB\t001H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t002H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t003H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t004H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t005H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t006H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t007H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t008H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t009H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00AH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00BH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00CH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00DH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00EH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00FH\n\n\tCODESEG\n\n\n;***************************************************************************\n;* MCGA_PRINT -- Assembly MCGA text print routine                          *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/17/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tMCGA_Print C near\n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\tthis:DWORD\n\tARG\tstring:DWORD\n\tARG\tx_pixel:DWORD\n\tARG\ty_pixel:DWORD\n\tARG\tfcolor:DWORD\n\tARG\tbcolor:DWORD\n\t\t\n\tLOCAL\tinfoblock:DWORD\t\t; pointer to info block\n\tLOCAL\toffsetblock:DWORD\t; pointer to offset block  (UWORD *)\n\tLOCAL\twidthblock:DWORD\t; pointer to width block   (BYTE  *)\n\tLOCAL\theightblock:DWORD\t; pointer to height block  (UWORD *)\n\n\tLOCAL\tcurline:DWORD\t\t; pointer to first column of current row.\n\tLOCAL\tbufferwidth:DWORD    \t; width of buffer (vpwidth + Xadd)\n\tLOCAL\tnextdraw:DWORD\t\t; bufferwidth - width of cur character.\n\tLOCAL\tstartdraw:DWORD\t\t; where next character will start being drawn.\n\n\tLOCAL\tchar:DWORD\t\t; current character value.\t\n\tlocal\tptr_string:dword\t\t; pointer to string\n\tLOCAL\tmaxheight:BYTE\t\t; max height of characters in font.\n\tLOCAL\tbottomblank:BYTE\t; amount of empty space below current character.\n\tLOCAL\tcharheight:BYTE\t\t; true height of current character.\n\tLOCAL\tvpwidth:DWORD\n\tLOCAL\tvpheight:DWORD\n\n\tmov\teax,[string]\t\t; check that the string is not NULL\n\tmov\t[ptr_string],eax\n\tcmp\teax,0\n\tjz\t??done\n\n;-------------------------------- Where to draw -----------------------------------------------\n\t; Set up memory location to start drawing.\n\tmov  \tebx,[this]\t\t\t\t; get a pointer to dest\n\tmov\teax,[(GraphicViewPort ebx).GVPHeight]\t; get height of viewport\n\tmov\t[vpheight],eax\t\t\t\t; save off height of viewport\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\t; get width of viewport\n\tmov\t[vpwidth],eax\t\t\t\t; save it off for later\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\t; add in xadd for bytes_per_line\n\tmov\t[bufferwidth],eax     \t\t\t; save it off for later use.\n\n\tmul\t[y_pixel]\t\t\t\t; multiply rowsize * y_pixel start.\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get start of the viewport\n\tadd\tedi,eax\t\t\t\t\t; add y position to start of vp \n\tmov\t[curline],edi\t\t\t\t; save 0,y address for line feed stuff.\n\tadd\tedi,[x_pixel]\t\t\t\t; add to get starting column in starting row.\n\tmov\t[startdraw],edi\t\t\t\t; save it off.\n\n\n;-------------------------------- Create block pointers ----------------------------------------\n\t; Get the pointer to the font.\n\t; We could check for NULL but why waste the time.\n\t; It is up to programmer to make sure it is set.\n\tmov\tesi,[FontPtr]\t\t; Get the font pointer\n\tor\tesi,esi\n\tjz\t??done\n\n\t; Set up some pointers to the different memory blocks.\n\t; esi (FontPtr) is added to each to get the true address of each block.\n\t; Many registers are used for P5 optimizations.\n\t; ebx is used for InfoBlock which is then used in the next section.\n\tmovzx\teax,[WORD PTR esi+FONTOFFSETBLOCK]\t; get offset to offset block\n\tmovzx\tebx,[WORD PTR esi+FONTINFOBLOCK]      \t; get offset to info block (must be ebx for height test)\n\tmovzx\tecx,[WORD PTR esi+FONTWIDTHBLOCK] \t; get offset to width block\n\tmovzx\tedx,[WORD PTR esi+FONTHEIGHTBLOCK]\t; get offset to height block\n\n\tadd\teax,esi\t\t\t\t; add offset of FontPtr to offset block  \n\tadd\tebx,esi\t\t\t\t; add offset of FontPtr to info block \n\tadd\tecx,esi\t\t\t\t; add offset of FontPtr to width block\n\tadd\tedx,esi\t\t\t\t; add offset of FontPtr to height block\n\n\tmov\t[offsetblock],eax\t\t; save offset to offset block\n\tmov\t[infoblock],ebx\t\t\t; save offset to info block\n\tmov\t[widthblock],ecx   \t\t; save offset to width block\n\tmov\t[heightblock],edx\t\t; save offset to height block\n\n;------------------------------------------ Test for fit ----------------------------------------------\n\t; Test x_pixel and y_pixel for negative values\n\tmov\tedx,[y_pixel]\t\t\t; get position  y \t\n\tmov\tecx,[x_pixel]\t\t\t; get position  x \t\n\tcmp\tedx,0\t\t\t\t; check for negative\n\tjl\t??done\t\t\t\t; if so, we're out let here.\n\tcmp\tecx,0\t\t\t\t; check for negative\n\tjl\t??done\t\t\t\t; if so, we're out let here.\n\n\t; Test to make sure the height of the max character will fit on this line\n\t; and and not fall out of the viewport.\n\t; remember we set ebx to FONTINFOBLOCK above.\n\tmovzx\teax,[BYTE PTR ebx + FONTINFOMAXHEIGHT]; get the max height in font.\n\tmov\t[maxheight],al\t\t\t; save it for later use.\n\tadd\teax,edx\t\t\t\t; add current y_value.\n\tcmp\teax,[vpheight]\t\t\t; are we over the edge?\n\tjge\t??done\t\t\t\t; if so, we're outa here.\n\tmov\t[y_pixel],eax\t\t\t; save for next line feed. y value for next line.\n\tcld\t\t\t\t\t; Make sure we are always forward copying.\n\n;------------------------ Set palette foreground and background ----------------------------------\n\tmov\teax,[fcolor]\t\t; foreground color\n\tmov\t[ColorXlat+1],al\n\tmov\t[ColorXlat+16],al\n\n\tmov\teax,[bcolor]\t\t; background color\n\tmov\t[ColorXlat],al\n\n;-------------------------------------------------------------------------------------------------\n;----------------------------------------- Main loop ----------------------------------------------\n\t; Now we go into the main loop of reading each character in the string and doing\n\t; something with it.\n??next_char:\n\t; while (*string++)\n\txor\teax,eax\t\t\t\t; zero out since we will just load al.\t\n\tmov\tesi,[string]\t\t\t; get address on next character.\t\n\tlodsb\t\t\t\t\t; load the character into al.\n\ttest\teax,0FFH\t\t\t; test to see if character is a NULL\n\tjz\t??done\t\t\t\t; character is NULL, get outa here.\n\n\tmov\tedi,[startdraw]\t\t\t; Load the starting address.\n\n\tmov\t[string],esi\t\t\t; save index into string. (incremented by lodsb)\t\n\n\tcmp\tal,10\t\t\t\t; is the character a carry return?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\t\n\tcmp\teax,13\t\t\t\t; is the character a line feed?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\n\tmov\t[char],eax\t\t\t; save the character off for later reference.\n\tmov\tebx,eax\t\t\t\t; save it in ebx for later use also.\n\n\tadd\teax,[widthblock]\t\t; figure address of width of character.\n\tmov\tecx,[x_pixel]\t\t\t; get current x_pixel.\n\tmovzx\tedx,[BYTE PTR eax]\t \t; get the width of the character in dl.\n\tadd\tecx,edx\t\t\t\t; add width of char to current x_pixel.\n\tmov\teax,[FontXSpacing]\n\tadd\tecx,eax\n\tadd\t[startdraw],edx\t\t\t; save start draw for next character.\n\tadd\t[startdraw],eax\t\t\t; adjust for the font spacing value\n\n\tcmp\tecx,[vpwidth]\t\t\t; is the pixel greater then the vp width?\n\tjg\t??force_line_feed\t\t; if so, force a line feed.\n\n\tmov\t[x_pixel],ecx\t\t\t; save value of start of next character.\n\tmov\tecx,[bufferwidth]\t\t; get amount to next y same x (one row down)\n\tsub\tecx,edx\t\t\t\t; take the current width off.\n\tmov\t[nextdraw],ecx\t\t\t; save it to add to edi when done with a row.\n\n\t; At this point we got the character. It is now time to find out specifics\n\t; about drawing the darn thing.\n\t; ebx = char so they can be used as an indexes.\n\t; edx = width of character for loop later.\n\n\t; get offset of data for character into esi.\n\tshl\tebx,1\t\t\t\t; mult by 2 to later use as a WORD index.\n\tmov\tesi,[offsetblock]\t\t; get pointer to begining of offset block.\n\tadd\tesi,ebx\t\t\t\t; index into offset block.\t\n\tmovzx\tesi,[WORD PTR esi]\t\t; get true offset into data block from FontPtr.\n\tadd\tesi,[FontPtr]\t\t\t; Now add FontPtr address to get true address.\n\n\t; Get top and bottom blank sizes and the true height of the character.\n\tadd\tebx,[heightblock]\t\t; point ebx to element in height array.\n\tmov\tal,[ebx+1]\t\t\t; load the data height into dl.\n\tmov\tcl,[ebx]\t\t\t; load the first data row into cl.\n\tmov\tbl,[maxheight]\t\t\t; get the max height of characters.\n\tmov\t[charheight],al\t\t\t; get number of rows with data.\n\tadd\tal,cl\t\t\t\t; add the two heights.\n\tsub\tbl,al\t\t\t\t; subract topblank + char height from maxheight.\n\tmov\t[bottomblank],bl\t\t; save off the number of blank rows on the bottom.\n\t; leaving this section:\n\t; dl is still the width of the character.\n\t; cl is the height of the top blank area.\n\n\tmov\tebx,OFFSET ColorXlat\t\t; setup ebx for xlat commands.\n\tmov\tdh,dl\t\t\t\t; save the width of the character to restore each loop.\n\n\tcmp\tcl,0\t\t\t\t; is there any blank rows on top?\n\tjz\t??draw_char\t\t\t; if not go and draw the real character.\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjnz\t??loop_top\t\t\t; if not go and write the color\n\n;----------------------------------------- skip Top blank area ----------------------------------------\n\t; this case, the top is transparrent, but we need to increase our dest pointer to correct row.\n\tmovzx\teax,cl\t\t\t\t; get number of rows into eax;\n\tmov\tecx,edx\t\t\t\t; save width since edx will be destroyed by mul.\n\tmul\t[bufferwidth]\t\t\t; multiply that by the width of the buffer.\n\tmov\tedx,ecx\t\t\t\t; restore the width\n\tadd\tedi,eax\t\t\t\t; update the pointer.\t\n\tjmp\tshort ??draw_char\t\t; now go draw the character.\n\n;----------------------------------------- fill Top blank area ----------------------------------------\n\t; edi was set a long time ago.\n\t; al is the translated color\n??loop_top:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_top\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tdec\tcl\t\t\t\t; decrement or row count\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tjz\t??draw_char\t\t\t; we are done here, go draw the character.\n\tjmp\tshort ??loop_top\t\t; go back to top of loop.\n\n\n;----------------------------------------- Draw character ----------------------------------------------\n??draw_char:\n\tmovzx\tecx,[charheight]\t\t; get the height of character to count down rows.\n\ttest\tecx,ecx\t\t\t\t; is there any data? (blank would not have any)\n\tjz\t??next_char\t\t\t; if no data, go on to next character.\t\n\n??while_data:\n\tlodsb\t\t\t\t\t; get byte value from font data\n\tmov\tah,al\t\t\t\t; save hinibble\n\tand\teax,0F00FH\t       \t\t; mask of low nibble in al hi nibble in ah.\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiplo\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiplo:\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjz\tshort ??nextrow\t\t\t; check if done with width of char\n\n\tmov\tal,ah\t\t\t\t; restore to get\n\t; test the time difference between looking up in a large table when shr al,4 is not done as\n\t; compared to using only a 16 byte table when using the shr al,4\n\t;shr\tal,4\t\t\t\t; shift the hi nibble down to low nibble\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiphi\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiphi:\n\t\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\tshort ??while_data\t\t; check if done with width of char\n\n??nextrow:\n\tadd\tedi,[nextdraw]\t\t\t; go to next line.\n\tdec\tecx\t\t\t\t; decrement the number of rows to go\n\tmov\tdh,dl\t\t\t\t; restore our column count for row.\n\tjnz\t??while_data\t\t\t; more data for character.\n\n\t; Now it is time to setup for clearing out the bottom of the character.\n\tmovzx\tecx,[bottomblank]\t\t; get amount on bottom that is blank\n\tcmp\tecx,0\t\t\t\t; if there is no blank bottom...\n\tjz\t??next_char\t\t\t; then skip to go to next character\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjz\t??next_char\t\t\t; skip the top black section to let the background through\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\n;----------------------------------------- Blank below character -----------------------------------\n??loop_bottom:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_bottom\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tdec\tcl\t\t\t\t; decrement or row count\n\tjz\t??next_char\t\t\t; we are done here, go to the next character.\n\tjmp\tshort ??loop_bottom\t\t; go back to top of loop.\n\n;----------------------------------- end of next_char (main) loop ------------------------------------\n;-------------------------------------------------------------------------------------------------\n\n\n;----------------------------------- special case line feeds ----------------------------------------\n; JRJ 05/01/95 This is the problem However made this change introduced\n; a error in the code, this function is not supposed to handle\n; Text wrapping\n??force_line_feed:\t\n\t; decrement pointer *string so that it will be back at same character\n\t; when it goes through the loop.\n\tdec\t[dword ptr string]\t\t  ; overflow by one charater\n\tjmp\t??done\n\n; Now go into the line feed code.....\n??line_feed:\n\tmov\tedx,[y_pixel]\t\t\t; get the current y pixel value.\n\tmovzx\tecx,[maxheight]\t\t\t; get max height for later use.\n\tadd\tecx,[FontYSpacing]\n\tadd\tedx,ecx\t\t\t\t; add max height to y_pixel\n\tcmp\tedx,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??done\t\t\t\t; if so, we are outa here.\n\n\tmov\teax,[bufferwidth]      \t\t; get bytes to next line.\n\tmov\tedi,[curline]\t\t\t; get start of current line.\t\n\tmul\tecx\t\t\t\t; mult max height * next line.\t\n\n\tadd\tedi,eax\t\t\t\t; add adjustment to current line.\n\tadd\t[y_pixel],ecx\t\t\t; increment to our next y position.\n\tmov\t[curline],edi\t\t\t; save it off for next line_feed.\n\tmov\t[startdraw],edi\t\t\t; save it off so we know where to draw next char.w\n\n\tmov\t[x_pixel],0\t\t\t; zero out x_pixel\n\tjmp\t??next_char\n\n??done:\n\tmov\teax,[string]\t\t\t; return the number of charaters \n\tsub\teax,[ptr_string]\t\t; printed\n\tret\t\t\t\t\t \n\t\t\n\tENDP\tMCGA_Print\n\nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/VBITBLIT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VBITBLIT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Linear_Blit_To_Vesa -- copies graphic buffer to vesa screen           *\n;*   Vesa_Blit_To_Linear -- Copies vesa screen to graphic buffer           *\n;*   Vesa_Blit_To_Vesa -- Copies a section of vesa screen to vesa screen   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nGLOBAL\tLinear_Blit_To_Vesa\t\t:NEAR\nGLOBAL\tVesa_Blit_To_Linear\t\t:NEAR\nGLOBAL\tVesa_Blit_To_Vesa\t\t:NEAR\n\nCODESEG\n\n;***************************************************************************\n;* LINEAR_BLIT_TO_VESA -- copies graphic buffer to vesa screen             *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n      \tPROC\tLinear_Blit_To_Vesa C near \n\tret\n\tENDP\tLinear_Blit_To_Vesa\n\n;***************************************************************************\n;* VESA_BLIT_TO_LINEAR -- Copies vesa screen to graphic buffer             *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n      \tPROC\tVesa_Blit_To_Linear C near \n\tret\n\tENDP\tVesa_Blit_To_Linear\n\n;***************************************************************************\n;* VESA_BLIT_TO_VESA -- Copies a section of vesa screen to vesa screen     *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n      \tPROC\tVesa_Blit_To_Vesa C near \n\tret\n\tENDP\tVesa_Blit_To_Vesa\nEND\t\n\n\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/VBUFFER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : VBUFFER.CPP                              *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : January 9, 1995                          *\n *                                                                         *\n *                  Last Update : January 9, 1995   [PWG]                  *\n *                                                                         *\n * This module contains the C++ class definitions for the video buffer     *\n * class.  This include routines for class creation and modification\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * VVPC::VideoViewPortClass -- Constructor for basic view port class     \t*\n * VVPC::VideoViewPortClass -- Default constructor for view port class\t\t*\n * VVPC::~VideoViewPortClass -- Destructor for GraphicViewPortClass\t\t\t*\n * VVPC::Attach -- Attaches a viewport to a buffer class                   *\n * VVPC::Change -- Changes position and size of a Video View Port   \t\t\t*\n * VBC::VideoBufferClass -- Default constuctor for video buffers\t\t\t\t*\n * VBC::VideoBufferClass -- Lowlevel constructor for video buffer class    *\n * VBC::~VideoBufferClass -- Destructor for the video buffer class      \t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"vbuffer.h\"\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * VVPC::VIDEOVIEWPORTCLASS -- Constructor for basic view port class     \t*\n *                                                                         *\n * INPUT:\t\tVideoBufferClass * vbuffer\t- buffer to attach to\t\t\t\t*\n *\t\t\t\t\tWORD x\t\t\t\t\t\t\t\t- x offset into buffer\t\t\t*\n *\t\t\t\t\tWORD y\t\t\t\t\t\t\t\t- y offset into buffer\t\t\t*\n *\t\t\t\t\tWORD w\t\t\t\t\t\t\t\t- view port width in pixels   *\n *\t\t\t\t\tWORD h   \t\t\t\t\t\t\t- view port height in pixels\t*\n *                                                                         *\n * OUTPUT:     Constructors may not have a return value\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/09/1994 PWG : Created.                                             *\n *=========================================================================*/\nVideoViewPortClass::VideoViewPortClass(VideoBufferClass *vbuffer, int x, int y, int w, int h)\n{\n\tAttach(vbuffer, x, y, w, h);\n}\n\n/***************************************************************************\n * VVPC::VIDEOVIEWPORTCLASS -- Default constructor for view port class   *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/09/1994 PWG : Created.                                             *\n *=========================================================================*/\nVideoViewPortClass::VideoViewPortClass(void)\n{\n}\n\n/***************************************************************************\n * VVPC::~VIDEOVIEWPORTCLASS -- Destructor for GraphicViewPortClass\t\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     A destructor may not return a value.                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/10/1994 PWG : Created.                                             *\n *=========================================================================*/\nVideoViewPortClass::~VideoViewPortClass(void)\n{\n}\n\n/***************************************************************************\n * VVPC::ATTACH -- Attaches a viewport to a buffer class                   *\n *                                                                         *\n * INPUT:\t\tGraphicBufferClass *g_buff\t- pointer to gbuff to attach to  *\n *\t\t\t\t\tWORD x                     - x position to attach to\t\t\t*\n *\t\t\t\t\tWORD y \t\t\t\t\t\t\t- y position to attach to\t\t\t*\n *\t\t\t\t\tWORD w\t\t\t\t\t\t\t- width of the view port\t\t\t*\n *\t\t\t\t\tWORD h\t\t\t\t\t\t\t- height of the view port\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/10/1994 PWG : Created.                                             *\n *=========================================================================*/\nvoid VideoViewPortClass::Attach(VideoBufferClass *vbuffer, int x, int y, int w, int h)\n{\n\t/*======================================================================*/\n\t/* Verify that the x and y coordinates are valid and placed within the\t*/\n\t/*\t\tphysical buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (x < 0) \t\t\t\t\t\t\t\t\t\t// you cannot place view port off\n\t\tx = 0;\t\t\t\t\t\t\t\t\t\t//\t\tthe left edge of physical buf\n\tif (x >= vbuffer->Get_Width())\t\t\t// you cannot place left edge off\n\t\tx = vbuffer->Get_Width() - 1;\t\t\t//\t\tthe right edge of physical buf\n\tif (y < 0) \t\t\t\t\t\t\t\t\t\t// you cannot place view port off\n\t\ty = 0;\t\t\t\t\t\t\t\t\t\t//\t\tthe top edge of physical buf\n\tif (y >= vbuffer->Get_Height()) \t\t\t// you cannot place view port off\n\t\ty = vbuffer->Get_Height() - 1;\t\t//\t\tbottom edge of physical buf\n\n\t/*======================================================================*/\n\t/* Adjust the width and height of necessary\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (x + w > vbuffer->Get_Width()) \t\t// if the x plus width is larger\n\t\tw = vbuffer->Get_Width() - x;\t\t\t//\t\tthan physical, fix width\n\n\tif (y + h > vbuffer->Get_Height()) \t\t// if the y plus height is larger\n\t\th = vbuffer->Get_Height() - y;\t\t//\t\tthan physical, fix height\n\n\t/*======================================================================*/\n\t/* Get a pointer to the top left edge of the buffer.\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n \tOffset \t\t= vbuffer->Get_Offset() + (vbuffer->Get_Width() * y) + x;\n\n\t/*======================================================================*/\n\t/* Copy over all of the variables that we need to store.\t\t\t\t\t\t*/\n\t/*======================================================================*/\n \tXPos\t\t\t= x;\n \tYPos\t\t\t= y;\n \tXAdd\t\t\t= vbuffer->Get_Width() - w;\n \tWidth\t\t\t= w;\n \tHeight\t\t= h;\n \tVideoBuff \t= vbuffer;\n}\n/***************************************************************************\n * VVPC::CHANGE -- Changes position and size of a Video View Port   \t\t\t*\n *                                                                  \t\t\t*\n * INPUT:   \tWORD the new x pixel position of the Video view port \t\t\t*\n *\t\t\t\t\tWORD the new y pixel position of the Video view port \t\t\t*\n *\t\t\t\t\tWORD the new width of the viewport in pixels\t\t\t  \t\t\t*\n *\t\t\t\t\tWORD the new height of the viewport in pixels\t\t  \t\t\t*\n *                                                                  \t\t\t*\n * OUTPUT:  \tBOOL whether the Video View Port could be sucessfully\t\t\t*\n *\t\t\t\t      resized.\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \t\t\t*\n *                                                                  \t\t\t*\n * WARNINGS:   You may not resize a Video View Port which is derived\t\t\t*\n *\t\t\t\t\t\tfrom a Video View Port Buffer, \t\t\t\t\t\t  \t\t\t*\n *                                                                  \t\t\t*\n * HISTORY:                                                         \t\t\t*\n *   09/14/1994 SKB : Created.                                      \t\t\t*\n *=========================================================================*/\nBOOL VideoViewPortClass::Change(int x, int y, int w, int h)\n{\n\t/*======================================================================*/\n\t/* Can not change a Video View Port if it is actually the physical\t\t*/\n\t/*\t   representation of a Video Buffer.\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif (this == Get_Video_Buffer())  {\n\t\treturn(FALSE);\n\t}\n\n\t/*======================================================================*/\n\t/* Since there is no allocated information, just re-attach it to the\t\t*/\n\t/*\t\texisting Video buffer as if we were creating the\t\t\t\t\t\t*/\n\t/*\t\tVideoViewPort.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tAttach(Get_Video_Buffer(), x, y, w, h);\n\treturn(TRUE);\n}\n/***************************************************************************\n * VBC::VIDEOBUFFERCLASS -- Default constuctor for video buffers\t\t\t\t*\n *                                                                         *\n * INPUT:\t\tWORD w\t\t\t- width of buffer in pixels (default = 320)  *\n *\t\t\t\t\tWORD h\t\t\t- height of buffer in pixels (default = 200) *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/13/1994 PWG : Created.                                             *\n *=========================================================================*/\nVideoBufferClass::VideoBufferClass(int w, int h)\n{\n\tOffset\t\t= 0xa0000;\t\t\t\t\t\t\t\t// Get offset to the buffer\n\tWidth\t\t\t= w;\t\t\t\t\t\t\t\t\t\t// Record width of Buffer\n\tHeight\t\t= h;\t\t\t\t\t\t\t\t\t\t// Record height of Buffer\n\tXAdd\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XAdd of Buffer\n\tXPos\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XPos of Buffer\n\tYPos\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record YPos of Buffer\n\tVideoBuff\t= this;\t\t\t\t\t\t\t\t\t// Get a pointer to our self\n}\n\n/***************************************************************************\n * VBC::VIDEOBUFFERCLASS -- Lowlevel constructor for video buffer class    *\n *                                                                         *\n * INPUT:\t\tUWORD\t\tthe selector of the memory reference\t\t\t\t\t*\n *\t\t\t\t\tlong\t\tthe offset of the memory reference\t\t\t\t\t\t*\n *\t\t\t\t\tWORD\t\tthe width of the video buffer\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tWORD\t\tthe height of the video buffer\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\nVideoBufferClass::VideoBufferClass(unsigned short selector, long offset, int w, int h)\n{\n\tOffset\t\t= offset;\t\t\t\t\t\t\t\t// Get offset to the buffer\n\tWidth\t\t\t= w;\t\t\t\t\t\t\t\t\t\t// Record width of Buffer\n\tHeight\t\t= h;\t\t\t\t\t\t\t\t\t\t// Record height of Buffer\n\tXAdd\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XAdd of Buffer\n\tXPos\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record XPos of Buffer\n\tYPos\t\t\t= 0;\t\t\t\t\t\t\t\t\t\t// Record YPos of Buffer\n\tVideoBuff\t= this;\t\t\t\t\t\t\t\t\t// Get a pointer to our self\n}\n/*=========================================================================*\n * VBC::~VIDEOBUFFERCLASS -- Destructor for the video buffer class      \t*\n *                                                                         *\n *\tINPUT:\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1994 PWG : Created.                                             *\n *=========================================================================*/\nVideoBufferClass::~VideoBufferClass()\n{\n}\n\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/VBUFFER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **      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      **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood 32 bit Library                  *\n *                                                                         *\n *                    File Name : VBUFFER.H                                *\n *                                                                         *\n *                   Programmer : Phil W. Gorrow                           *\n *                                                                         *\n *                   Start Date : January 6, 1995                          *\n *                                                                         *\n *                  Last Update : January 17, 1995   [PWG]                 *\n *                                                                         *\n *\tThis module contains the definition for the video buffer class.  The\t\t*\n * primary functionality of the video buffer class is handled by inline\t\t*\n * functions that make a call through function pointers to the correct\t\t*\n * routine.  This has two benefits:\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t1) C++ name mangling is not a big deal since the function pointers\t*\n *\t\t   point to functions in standard C format.\t\t\t\t\t\t\t\t\t*\n *\t\t2) The function pointers can be changed when we set a different\t\t*\n *       graphic mode.  This allows us to have both supervga and mcga\t\t*\n *\t\t\troutines present in memory at once.\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * In the basic library, these functions point to stub routines which just\t*\n * return.  This makes a product that just uses a graphic buffer take the\t*\n * minimum amount of code space.  For programs that require MCGA or VESA\t*\n * support, all that is necessary to do is link either the MCGA or VESA\t\t*\n * specific libraries in, previous to WWLIB32.  The linker will then \t\t*\n * overide the the necessary stub functions automatically.\t\t\t\t\t\t*\n * \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This header files gives the definition for all VideoViewPort and \t\t\t*\n * VideoBuffer functions.  These functions mirror some of the basic\t\t\t*\n * functionality of the GraphicViewPort and GraphicBuffer classes.\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Terminology:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Video ViewPort - The Video ViewPort holds all of the functions which\t\t* \n *\t\tcan be used on a Video Buffer.  The video viewport but cannot be \t\t*\n *\t\tattached to a Graphic Buffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n *\tVideo Buffer - A refers to a physical object which has been mapped to\t* \n *\t\tram, like a graphic card.  The SeenPage is a good example of a Video\t* \n *\t\tBuffer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t* \n\n * Below is a tree which shows the relationship of the GraphicBuffer and \t*\n * Buffer classes to the VideoBuffer class:\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t  BUFFER.H\t\t\t\t GBUFFER.H\t\t\t  BUFFER.H\t\t\t\t VBUFFER.H\t*\n *  ----------          ----------         ----------          ----------\t*\n * |  Buffer  |        | Graphic  |       |  Buffer  |        |  Video   |\t*\n * |  Class   |        | ViewPort |       |  Class   |        | ViewPort |\t*\n *  ----------          ----------         ----------          ----------\t*\n *            \\        /                             \\        /\t\t\t\t*\n *             \\      /                               \\      /\t\t\t\t\t*\n *            ----------                             ----------\t\t\t\t*\n *           |  Graphic |                           |  Video   |\t\t\t\t*\n *           |  Buffer  |                           |  Buffer  |\t\t\t\t*\n *            ----------                             ---------- \t\t\t\t*\n *\t  \t\t\t  GBUFFER.H\t\t\t                       VBUFFER.H\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   VVPC::Get_Selector -- Get selector for virtual viewport instance\t\t*\n *   VVPC::Get_Offset -- Get offset for virtual view port class instance   *\n *   VVPC::Get_Height -- Gets the height of a virtual viewport instance    *\n *   VVPC::Get_Width -- Get the width of a virtual viewport instance\t\t\t*\n *   VVPC::Get_XAdd -- Get the X add offset for virtual viewport instance  *\n *   VVPC::Get_XPos -- Get the x pos of the VP on the Video                *\n *   VVPC::Get_YPos -- Get the y pos of the VP on the video                *\n *   VVPC::Get_Grasphic_Buffer -- Get the graphic buffer of the VP.        *\n *   VVPC::Put_Pixel -- stub to call curr graphic mode Put_Pixel\t\t\t\t*\n *   VVPC::Get_Pixel -- stub to call curr graphic mode Get_Pixel\t\t\t\t*\n *   VVPC::Clear -- stub to call curr graphic mode Clear        \t\t\t\t*\n *   VVPC::To_Buffer -- stub func 1 to call curr graphic mode To_Buffer\t\t*\n *   VVPC::To_Buffer -- stub func 2 to call curr graphic mode To_Buffer\t\t*\n *   VVPC::To_Buffer -- stub func 3 to call curr graphic mode To_Buffer\t\t*\n *   VVPC::Blit -- stub 1 to call curr graphic mode Blit to GVPC\t\t\t\t*\n *   VVPC::Blit -- stub 2 to call curr graphic mode Blit\tto GVPC\t\t\t\t*\n *   VVPC::Blit -- stub 3 to call curr graphic mode Blit\tto GVPC\t\t\t\t*\n *   VVPC::Blit -- stub 1 to call curr graphic mode Blit\tto VVPC\t\t\t\t*\n *   VVPC::Blit -- stub 2 to call curr graphic mode Blit\tto VVPC\t\t\t\t*\n *   VVPC::Blit -- stub 3 to call curr graphic mode Blit\tto VVPC\t\t\t\t*\n *   VVPC::Scale -- stub 1 to call curr graphic mode Scale to GVPC\t\t\t*\n *   VVPC::Scale -- stub 2 to call curr graphic mode Scale to GVPC\t\t\t*\n *   VVPC::Scale -- stub 3  to call curr graphic mode Scale\tto GVPC\t\t\t*\n *   VVPC::Scale -- stub 4 to call curr graphic mode Scale to GVPC\t\t\t*\n *   VVPC::Scale -- stub 1 to call curr graphic mode Scale to VVPC\t\t\t*\n *   VVPC::Scale -- stub 2 to call curr graphic mode Scale to VVPC\t\t\t*\n *   VVPC::Scale -- stub 3  to call curr graphic mode Scale\tto VVPC\t\t\t*\n *   VVPC::Scale -- stub 4 to call curr graphic mode Scale to VVPC\t\t\t*\n *   BC::To_Page -- Copys buffer class to page with definable w, h \t\t\t*\n *   BC::To_Page -- Copys buffer class to page with definable w, h \t\t\t*\n *   BC::To_Page -- Copys buffer class to page with definable x, y, w, h \t*\n *   Buffer_To_Page -- Generic 'c' callable form of Buffer_To_Page         *\n *   GVPC::Blit -- stub 1 to call curr graphic mode Blit to VVPC\t\t\t\t*\n *   GVPC::Blit -- stub 2 to call curr graphic mode Blit to VVPC\t\t\t\t*\n *   GVPC::Blit -- stub 3 to call curr graphic mode Blit to VVPC\t\t\t\t*\n *   GVPC::SCALE -- stub 1 to call curr graphic mode Scale to VVPC\t\t\t*\n *   GVPC::SCALE -- stub 2 to call curr graphic mode Scale to VVPC\t\t\t*\n *   GVPC::SCALE -- stub 3 to call curr graphic mode Scale to VVPC\t\t\t*\n *   GVPC::SCALE -- stub 4 to call curr graphic mode Scale to VVPC\t\t\t*\n *   VVPC::Print -- Stub function to print string on a Video View Port     *\n *   VVPC::Print -- Stub function to print an int on a Graphic Viewport Class*\n *   VVPC::Print -- Stub function to print long on a graphic viewport class*\n *   VVPC::Print -- Stub function to print a short on a Video Viewport     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef VBUFFER_H\n#define VBUFFER_H\n\n/*=========================================================================*/\n/* If we have not already loaded the standard library header, than we can\t*/\n/*\t\tload it.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n\n/*=========================================================================*/\n/* The video buffer class is dependant on a buffer class so we need to\t\t*/\n/*\t\tinclude the definitions for that as well.\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#ifndef BUFFER_H\n#include \"buffer.h\"\n#endif\n\n/*=========================================================================*/\n/* The video buffer class is dependant on a buffer class so we need to\t\t*/\n/*\t\tinclude the definitions for that as well.\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#ifndef GBUFFER_H\n#include \"gbuffer.h\"\n#endif\n\n/*=========================================================================*/\n/* Define external assembly funcs which deals with buffers and viewports.\t*/\n/*=========================================================================*/\nlong Buffer_To_Page(int x, int y, int w, int h, void *Buffer, VideoViewPortClass &view);\n\n/*=========================================================================*/\n/* Define the screen width and height to make portability to other modules\t*/\n/*\t\teasier.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tDEFAULT_SCREEN_WIDTH\t\t320\n#define\tDEFAULT_SCREEN_HEIGHT\t200\n\n/*=========================================================================*/\n/* Define functions which have not under-gone name mangling\t\t\t\t\t\t*/\n/*=========================================================================*/\n#ifdef __cplusplus\nextern \"C\" {\n\textern UWORD Get_MCGA_Selector(VOID);\n}\n#endif\n\n/*=========================================================================*/\n/* Let the compiler know that a VideoBufferClass exists so that it can\t\t*/\n/*\t\tkeep a pointer to it in a VideoViewPortClass.\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nclass VideoBufferClass;\n\n\n/*=========================================================================*/\n/* VideoViewPortClass - Holds viewport information which has been attached\t*/\n/*\t\tto a VideoBuffer.  A viewport is effectively a\trectangular subset   */\n/*    of the full buffer which is used for clipping and the like.\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tint \t\tSelector\t-\t\tis the selector to view port buffer\t\t\t*/\n/*\t\t\tchar\t  \t*Buffer\t-\t\tis the offset to view port buffer\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis the width of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis the height of view port\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis add value to go from the end of a line\t*/\n/*\t\t\t\t\t\t\t\t\t\t\tto the beginning of the next line\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\tx offset into its associated VideoBuffer\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\ty offset into its associated VideoBuffer\t*/\n/*=========================================================================*/\nclass VideoViewPortClass {\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVideoViewPortClass(VideoBufferClass* graphic_buff, int x, int y, int w, int h);\n\t\tVideoViewPortClass();\n\t\t~VideoViewPortClass();\n\t\t/*===================================================================*/\n\t\t/* Define functions to get at the private data members\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\tGet_Offset(void);\n\t\tint\tGet_Height(void);\n\t\tint\tGet_Width(void);\n\t\tint\tGet_XAdd(void);\n\t\tint\tGet_XPos(void);\n\t\tint\tGet_YPos(void);\n\t\tVideoBufferClass *Get_Video_Buffer(void);\n\n\t\t/*===================================================================*/\n\t\t/* Define a function which allows us to change a video viewport on\t*/\n\t\t/*\t\tthe fly.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tBOOL Change(int x, int y, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the set of graphic functions that are members of a Video   */\n\t\t/*\t\tViewPort class.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tvoid\tPut_Pixel(int x, int y, unsigned char color);\n\t\tint\tGet_Pixel(int x, int y);\n\t\tvoid\tClear(unsigned char color = 0);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, void *buff, long size);\n\t\tlong\tTo_Buffer(int x, int y, int w, int h, BufferClass *buff);\n\t\tlong\tTo_Buffer(BufferClass *buff);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tGraphicViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, int dx, int dy, BOOL trans = FALSE);\n\t\tBOOL\tBlit(\tVideoViewPortClass& dest, BOOL trans = FALSE);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tGraphicViewPortClass &dest, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, BOOL trans = FALSE, char *remap = NULL);\n\t\tBOOL\tScale(\tVideoViewPortClass &dest, char *remap);\n\t\tunsigned long  Print(char const *string, int x, int y, int fcolor, int bcolor);\n\t\tunsigned long\tPrint(int num, int x, int y, int fcol, int bcol);\n\t\tunsigned long\tPrint(short num, int x, int y, int fcol, int bcol);\n\t\tunsigned long\tPrint(long num, int x, int y, int fcol, int bcol);\n\n\tprotected:\n\t\t/*===================================================================*/\n\t\t/* Define functions to attach the viewport to a graphicbuffer\t\t\t*/\n\t\t/*===================================================================*/\n\t\tvoid Attach(VideoBufferClass *video_buff, int x, int y, int w, int h);\n\t\tvoid Attach(VideoBufferClass *video_buff, int w, int h);\n\n\t\t/*===================================================================*/\n\t\t/* Define the data used by a GraphicViewPortClass\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tlong\t\t\t\t\t\tOffset;\t\t\t\t\t// offset to graphic page\n\t\tint\t\t\t\t\t\tWidth;\t\t\t\t\t// width of graphic page\n\t\tint\t\t\t\t\t\tHeight;\t\t\t\t\t// height of graphic page\n\t\tint\t\t\t\t\t\tXAdd;\t\t\t\t\t\t// xadd for graphic page (0)\n\t\tint\t\t\t\t\t\tXPos;\t\t\t\t\t\t// x offset in relation to graphicbuff\n\t\tint\t\t\t\t\t\tYPos;\t\t\t\t\t\t// y offset in relation to graphicbuff\n\t\tVideoBufferClass\t   *VideoBuff;\t\t\t\t// related graphic buff\n};\n\n\n/*=========================================================================*/\n/* VideoBufferClass - A VideoBuffer refers to an actual instance of a\t\t*/\n/*\t\tphyscial device which has been mapped to a memory address like a \t\t*/\n/*\t\tvideo card.  The VideoBuffer can be drawn to directly because it\t\t*/\n/*\t\tinherits a Video ViewPort which represent its full size.\t\t\t\t\t*/\n/*\t\tsize.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\tint\t  \tSelector\t-\t\tis now the selector to graphic buffer\t\t*/\n/*\t\t\tchar\t  \t*Buffer\t-\t\tis now the offset to graphic buffer\t\t\t*/\n/*\t\t\tint\t  \tWidth\t\t-\t\tis now the width of graphic buffer\t\t\t*/\n/*\t\t\tint\t  \tHeight\t-\t\tis now the height of graphic buffer\t\t\t*/\n/*\t\t\tint\t  \tXAdd\t\t-\t\tis now the xadd of graphic buffer\t\t\t*/\n/*\t\t\tint\t\tXPos;\t\t- \t\twill be 0 because it is graphicbuff\t\t\t*/\n/*\t\t\tint\t\tYPos;\t\t-\t\twill be 0 because it is graphicbuff\t\t\t*/\n/*=========================================================================*/\nclass VideoBufferClass: public VideoViewPortClass {\n\tpublic:\n\t\t/*===================================================================*/\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\t/*===================================================================*/\n\t\tVideoBufferClass(unsigned short selector, long offset, int w, int h);\n\t\tVideoBufferClass(int w = DEFAULT_SCREEN_WIDTH, int h = DEFAULT_SCREEN_HEIGHT);\n\t\t~VideoBufferClass();\n};\n\n/***************************************************************************\n * VVPC::GET_OFFSET -- Get offset for virtual view port class instance     *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long the offset for the virtual viewport instance           *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long VideoViewPortClass::Get_Offset(void)\n{\n\treturn(Offset);\n}\n\n/***************************************************************************\n * VVPC::GET_HEIGHT -- Gets the height of a virtual viewport instance      *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     int the height of the virtual viewport instance             *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int VideoViewPortClass::Get_Height(void)\n{\n\treturn(Height);\n}\n\n/***************************************************************************\n * VVPC::GET_WIDTH -- Get the width of a virtual viewport instance\t\t\t*\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     int the width of the virtual viewport instance              *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int VideoViewPortClass::Get_Width(void)\n{\n\treturn(Width);\n}\n\n\n/***************************************************************************\n * VVPC::GET_XADD -- Get the X add offset for virtual viewport instance    *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     int the xadd for a virtual viewport instance                *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/07/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline int VideoViewPortClass::Get_XAdd(void)\n{\t\n\treturn(XAdd);\n}\n/***************************************************************************\n * VVPC::GET_XPOS -- Get the x pos of the VP on the Video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     int the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n;*   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int VideoViewPortClass::Get_XPos(void)\n{\n\treturn(XPos);\n}\n\n\n/***************************************************************************\n * VVPC::GET_YPOS -- Get the y pos of the VP on the video                  *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     int the x offset to VideoBufferClass\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n;*   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline int VideoViewPortClass::Get_YPos(void)\n{\n\treturn(YPos);\n}\n\n/***************************************************************************\n * VVPC::GET_GRAPHIC_BUFFER -- Get the graphic buffer of the VP.           *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/22/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline VideoBufferClass *VideoViewPortClass::Get_Video_Buffer(void)\n{\n \treturn (VideoBuff);\n}\n\n/***************************************************************************\n * VVPC::PUT_PIXEL -- stub to call curr graphic mode Put_Pixel\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tVideoViewPortClass::Put_Pixel(int x, int y, unsigned char color)\n{\n\tVVPC_Put_Pixel_Func(this, x, y, color);\n}\n\n/***************************************************************************\n * VVPC::GET_PIXEL -- stub to call curr graphic mode Get_Pixel          \t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline int\tVideoViewPortClass::Get_Pixel(int x, int y)\n{\n\treturn(VVPC_Get_Pixel_Func(this, x, y));\n}\n\n/***************************************************************************\n * VVPC::CLEAR -- stub to call curr graphic mode Clear\t                  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline void\tVideoViewPortClass::Clear(unsigned char color)\n{\n\tVVPC_Clear_Func(this, color);\n}\n\n/***************************************************************************\n * VVPC::TO_BUFFER -- stub 1 to call curr graphic mode To_Buffer\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tVideoViewPortClass::To_Buffer(int x, int y, int w, int h, void *buff, long size)\n{\n\treturn(VVPC_To_Buffer_Func(this, x, y, w, h, buff, size));\n}\n\n/***************************************************************************\n * VVPC::TO_BUFFER -- stub 2 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tVideoViewPortClass::To_Buffer(int x, int y, int w, int h, BufferClass *buff)\n{\n\treturn(VVPC_To_Buffer_Func(this, x, y, w, h, buff->Get_Buffer(), buff->Get_Size()));\n}\n\n/***************************************************************************\n * VVPC::TO_BUFFER -- stub 3 to call curr graphic mode To_Buffer \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long\tVideoViewPortClass::To_Buffer(BufferClass *buff)\n{\n\treturn(VVPC_To_Buffer_Func(this, 0, 0, Width, Height, buff->Get_Buffer(), buff->Get_Size()));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- stub 1 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tGraphicViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans)\n{\n\treturn(VVPC_Blit_to_GVPC_Func(this, &dest, x_pixel, y_pixel, dx_pixel, dy_pixel, pixel_width, pixel_height, trans));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- Stub 2 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tGraphicViewPortClass& dest, int dx, int dy, BOOL trans)\n{\n\treturn(VVPC_Blit_to_GVPC_Func(this, &dest, 0, 0, dx, dy, Width, Height, trans));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- stub 3 to call curr graphic mode Blit to GVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tGraphicViewPortClass& dest, BOOL trans)\n{\n\treturn(VVPC_Blit_to_GVPC_Func(this, &dest, 0, 0, 0, 0, Width, Height, trans));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- stub 1 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tVideoViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans)\n{\n\treturn(VVPC_Blit_to_VVPC_Func(this, &dest, x_pixel, y_pixel, dx_pixel, dy_pixel, pixel_width, pixel_height, trans));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- stub 2 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tVideoViewPortClass& dest, int dx, int dy, BOOL trans)\n{\n\treturn(VVPC_Blit_to_VVPC_Func(this, &dest, 0, 0, dx, dy, Width, Height, trans));\n}\n\n/***************************************************************************\n * VVPC::BLIT -- stub 3 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Blit(\tVideoViewPortClass& dest, BOOL trans)\n{\n\treturn(VVPC_Blit_to_VVPC_Func(this, &dest, 0, 0, 0, 0, Width, Height, trans));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 1 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans, char *remap)\n{\n\treturn(VVPC_Scale_To_GVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, trans, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 2 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tGraphicViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap)\n{\n\treturn(VVPC_Scale_To_GVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, FALSE, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 3 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tGraphicViewPortClass &dest, BOOL trans, char *remap)\n{\n\treturn(VVPC_Scale_To_GVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), trans, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 4 to call curr graphic mode Scale to GVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tGraphicViewPortClass &dest, char *remap)\n{\n\treturn(VVPC_Scale_To_GVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), FALSE, remap));\n}\n/***************************************************************************\n * VVPC::SCALE -- stub 1 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans, char *remap)\n{\n\treturn(VVPC_Scale_To_VVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, trans, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 2 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap)\n{\n\treturn(VVPC_Scale_To_VVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, FALSE, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 3 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tVideoViewPortClass &dest, BOOL trans, char *remap)\n{\n\treturn(VVPC_Scale_To_VVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), trans, remap));\n}\n\n/***************************************************************************\n * VVPC::SCALE -- stub 4 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tVideoViewPortClass::Scale(\tVideoViewPortClass &dest, char *remap)\n{\n\treturn(VVPC_Scale_To_VVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), FALSE, remap));\n}\n\n/***************************************************************************\n * VVPC::PRINT -- Stub function to print string on a Video View Port       *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tVideoViewPortClass::Print(char const *str, int x, int y, int fcol, int bcol)\n{\n\treturn(VVPC_Print_Func(this, str, x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * VVPC::PRINT -- Stub function to print an int on a Video Viewport\t\t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tVideoViewPortClass::Print(int num, int x, int y, int fcol, int bcol)\n{\n\tBYTE str[17];\n\n\treturn(VVPC_Print_Func(this, itoa(num, str, 10), x, y, fcol, bcol));\n}\n\n\n/***************************************************************************\n * VVPC::PRINT -- Stub function to print a short on a Video Viewport       *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\ninline unsigned long\tVideoViewPortClass::Print(short num, int x, int y, int fcol, int bcol)\n{\n\tBYTE str[17];\n\n\t\n\treturn(VVPC_Print_Func(this, itoa(num, str, 10), x, y, fcol, bcol));\n}\n\n/***************************************************************************\n * VVPC::PRINT -- Stub function to print long on a Video Viewport\t\t\t\t*\n *                                                                         *\n * INPUT:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/17/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline unsigned long\tVideoViewPortClass::Print(long num, int x, int y, int fcol, int bcol)\n{\n\tBYTE str[33];\n\n\treturn(VVPC_Print_Func(this, ltoa(num, str, 10), x, y, fcol, bcol));\n}\n\n\n/*=========================================================================*/\n/*= The following BufferClass functions are defined here because they act =*/\n/*=\ton video viewports.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  =*/\n/*=========================================================================*/\n\n\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t*\n *\t\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t*\n *\t\t\t\t\tVIVC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int w, int h, VideoViewPortClass &view)\n{\n\treturn(VVPC_Buffer_To_Page(0, 0, w, h, Buffer, &view));\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable w, h \t\t*\n *                                                                         *\n * INPUT:\t\tVIVC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tx and y position are the upper left corner of the dest\t\t*\n *\t\t\t\t\t\tviewport.  width and height are assumed to be the\t\t\t*\n *\t\t\t\t\t\tviewport's width and height.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(VideoViewPortClass &view)\n{\n\treturn(VVPC_Buffer_To_Page(0, 0, view.Get_Width(), view.Get_Height(), Buffer, &view));\n}\n/***************************************************************************\n * BC::TO_PAGE -- Copys a buffer class to a page with definable x, y, w, h *\n *                                                                         *\n * INPUT:\tint\tx\t\t\t- x pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\ty\t\t\t- y pixel on viewport to copy from\t\t\t\t\t*\n *\t\t\t\tint\twidth\t\t- the width of copy region\t\t\t\t\t\t\t\t*\n *\t\t\t\tint\theight\t- the height of copy region\t\t\t\t\t\t\t*\n *\t\t\t\tVIVC&\tdest\t\t- virtual viewport to copy to\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\tnone                                                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/01/1994 PWG : Created.                                             *\n *=========================================================================*/\ninline long BufferClass::To_Page(int x, int y, int w, int h, VideoViewPortClass &view)\n{\n\treturn(VVPC_Buffer_To_Page(x, y, w, h, Buffer, &view));\n}\n\n/***************************************************************************\n * BUFFER_TO_PAGE -- Generic 'c' callable form of Buffer_To_Page           *\n *                                                                         *\n * INPUT: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/12/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline long Buffer_To_Page(int x, int y, int w, int h, void *Buffer, VideoViewPortClass &view)\n{\n\treturn(VVPC_Buffer_To_Page(x, y, w, h, Buffer, &view));\n}\n\n/*=========================================================================*/\n/* The following GraphicBufferClass functions are defined here because \t\t*/\n/* they act\ton graphic viewports.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n/***************************************************************************\n * GVPC::BLIT -- stub 1 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tVideoViewPortClass& dest, int x_pixel, int y_pixel, int dx_pixel, \n\t\t\t\tint dy_pixel, int pixel_width, int pixel_height, BOOL trans)\n{\n\treturn(GVPC_Blit_to_VVPC_Func(this, &dest, x_pixel, y_pixel, dx_pixel, dy_pixel, pixel_width, pixel_height, trans));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 2 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tVideoViewPortClass& dest, int dx, int dy, BOOL trans)\n{\n\treturn(GVPC_Blit_to_VVPC_Func(this, &dest, 0, 0, dx, dy, Width, Height, trans));\n}\n\n/***************************************************************************\n * GVPC::BLIT -- stub 3 to call curr graphic mode Blit to VVPC\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Blit(\tVideoViewPortClass& dest, BOOL trans)\n{\n\treturn(GVPC_Blit_to_VVPC_Func(this, &dest, 0, 0, 0, 0, Width, Height, trans));\n}\n/***************************************************************************\n * GVPC::SCALE -- stub 1 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, BOOL trans, char *remap)\n{\n\treturn(GVPC_Scale_To_VVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, trans, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 2 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tVideoViewPortClass &dest, int src_x, int src_y, int dst_x, \n\t\t\t\t\tint dst_y, int src_w, int src_h, int dst_w, int dst_h, char *remap)\n{\n\treturn(GVPC_Scale_To_VVPC(\tthis, &dest, src_x, src_y, dst_x, dst_y, src_w, src_h, dst_w, dst_h, FALSE, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 3 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tVideoViewPortClass &dest, BOOL trans, char *remap)\n{\n\treturn(GVPC_Scale_To_VVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), trans, remap));\n}\n\n/***************************************************************************\n * GVPC::SCALE -- stub 4 to call curr graphic mode Scale to VVPC\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/06/1995 PWG : Created.                                             *\n *=========================================================================*/\ninline BOOL\tGraphicViewPortClass::Scale(\tVideoViewPortClass &dest, char *remap)\n{\n\treturn(GVPC_Scale_To_VVPC(\tthis, &dest, 0, 0, 0, 0, Width, Height, dest.Get_Width(), dest.Get_Height(), FALSE, remap));\n}\n\n#endif // VBUFFER_H\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/VCLEAR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Clear the Full Mcga Screen\t\t   *\n;*                                                                         *\n;*                    File Name : CLEAR.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Vesa_Clear -- Clears a vesa video viewport                            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n\n;***************************************************************************\n;* VESA_CLEAR -- Clears a vesa video viewport                              *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n       \tPROC\tVesa_Clear C near \n\tret\n\tENDP\tVesa_Clear\nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/VESA.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VESA.ASM                                 *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : December 8, 1994                         *\n;*                                                                         *\n;*                  Last Update : December 8, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Vesa_Asm_Set_Win -- Sets the current vesa window from Asm             *\n;*   Vesa_Asm_Next_Window -- Sets to the next vesa window                  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS  ??\n\n\nGLOBAL\tVesa_Asm_Set_Win :near\n\nDATASEG\n\nCODESEG\n\n\n;***************************************************************************\n;* VESA_ASM_SET_WIN -- Sets the current vesa window from Asm               *\n;*                                                                         *\n;* INPUT:\tedi - offset to set the window for                         *\n;*                                                                         *\n;* OUTPUT:      edi - adjusted offset for window                           *\n;*                                                                         *\n;* PROTO:\tvoid Vesa_Asm_Set_Win(void);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   12/08/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_Asm_Set_Win C near \n\n\tret\n\tENDP\tVesa_Asm_Set_Win\n\n\n\nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/VGETPIX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Clear the Full Mcga Screen\t\t   *\n;*                                                                         *\n;*                    File Name : GETPIXEL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVPC::Clear -- Clears a virtual viewport instance                     *\n;*   Vesa_Get_Pixel -- Gets a pixel from a video viewport                  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\nCODESEG\n;***************************************************************************\n;* VESA_GET_PIXEL -- Gets a pixel from a video viewport                    *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n\n     \tPROC\tVesa_Get_Pixel C near \n\tret\n\tENDP\tVesa_Get_Pixel\nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/VLBTOVE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VBITBLIT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Linear_Blit_To_Vesa -- copies graphic buffer to vesa screen           *\n;*   Vesa_Blit_To_Linear -- Copies vesa screen to graphic buffer           *\n;*   Vesa_Blit_To_Vesa -- Copies a section of vesa screen to vesa screen   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nGLOBAL\tLinear_Blit_To_Vesa\t\t:NEAR\n\nCODESEG\n\n;***************************************************************************\n;* LINEAR_BLIT_TO_VESA -- copies graphic buffer to vesa screen             *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n      \tPROC\tLinear_Blit_To_Vesa C near \n\tret\n\tENDP\tLinear_Blit_To_Vesa\n\nEND\t\n\n\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/VPUTPIX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Clear the Full Mcga Screen\t\t   *\n;*                                                                         *\n;*                    File Name : PUTPIXEL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Vesa_Put_Pixel -- Puts a pixel on a video viewport                    *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n\n;***************************************************************************\n;* VESA_PUT_PIXEL -- Puts a pixel on a video viewport                      *\n;*                                                                         *\n;* INPUT:\t \t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_Put_Pixel C near\n\tret\n\tENDP\tVesa_Put_Pixel\nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/VSCALE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VSCALE.ASM                               *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 16, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Vesa_Scale_To_Vesa -- Scales a vesa viewport to a vesa viewport       *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\nCODESEG\n\n\n;***************************************************************************\n;* VESA_SCALE_TO_VESA -- Scales a vesa viewport to a vesa viewport         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_Scale_To_Vesa C near\n\tret\n\tENDP\tVesa_Scale_To_Vesa\n\n\nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/VSCLTOVE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VSCALE.ASM                               *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 16, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Linear_Scale_To_Vesa -- Scales a graphic viewport to a vesa viewport  *\n;*   Vesa_Scale_To_Linear -- Scales a Vesa viewport to a graphic viewport  *\n;*   Vesa_Scale_To_Vesa -- Scales a vesa viewport to a vesa viewport       *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\nCODESEG\n\n\n;***************************************************************************\n;* LINEAR_SCALE_TO_VESA -- Scales a graphic viewport to a vesa viewport\t   *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tLinear_Scale_To_Vesa C near\n\tret\n\tENDP\tLinear_Scale_To_Vesa\n\nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/VTOBUFF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VTOBUFF.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 16, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Vesa_To_Buffer -- Copies a vesa viewport to a linear buffer           *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n\n;***************************************************************************\n;* VESA_TO_BUFFER -- Copies a vesa viewport to a linear buffer             *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n      \tPROC\tVesa_To_Buffer C near\n\tret\n\tENDP\tVesa_To_Buffer\nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/VTOPAGE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VTOPAGE.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 16, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Vesa_Buffer_To_Page -- Copies a linear buffer to a vesa page          *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nCODESEG\n\n;***************************************************************************\n;* VESA_BUFFER_TO_PAGE -- Copies a linear buffer to a vesa page            *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_Buffer_To_Page C near \n\tret\n\tENDP\tVesa_Buffer_To_Page \nEND\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/VTXTPRNT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VTXTPRNT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 17, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 17, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Vesa_Print -- Prints a text string to a Vesa Viewport                 *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\nCODESEG\n\n\n;***************************************************************************\n;* VESA_PRINT -- Prints a text string to a Vesa Viewport                   *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/17/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_Print C near\n\tret\n\tENDP\tVesa_Print\n\n\nEND"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/VVBLIT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VBITBLIT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Linear_Blit_To_Vesa -- copies graphic buffer to vesa screen           *\n;*   Vesa_Blit_To_Linear -- Copies vesa screen to graphic buffer           *\n;*   Vesa_Blit_To_Vesa -- Copies a section of vesa screen to vesa screen   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nGLOBAL\tVesa_Blit_To_Vesa\t\t:NEAR\n\nCODESEG\n\n;***************************************************************************\n;* VESA_BLIT_TO_VESA -- Copies a section of vesa screen to vesa screen     *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n      \tPROC\tVesa_Blit_To_Vesa C near \n\tret\n\tENDP\tVesa_Blit_To_Vesa\nEND\t\n\n\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/VVETOLB.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VBITBLIT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Linear_Blit_To_Vesa -- copies graphic buffer to vesa screen           *\n;*   Vesa_Blit_To_Linear -- Copies vesa screen to graphic buffer           *\n;*   Vesa_Blit_To_Vesa -- Copies a section of vesa screen to vesa screen   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n\nGLOBAL\tVesa_Blit_To_Linear\t\t:NEAR\n\nCODESEG\n\n;***************************************************************************\n;* VESA_BLIT_TO_LINEAR -- Copies vesa screen to graphic buffer             *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n      \tPROC\tVesa_Blit_To_Linear C near \n\tret\n\tENDP\tVesa_Blit_To_Linear\n\nEND\t\n\n\n"
  },
  {
    "path": "WWFLAT32/MCGAPRIM/VVETOSCL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VSCALE.ASM                               *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 16, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Vesa_Scale_To_Linear -- Scales a Vesa viewport to a graphic viewport  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\nCODESEG\n;***************************************************************************\n;* VESA_SCALE_TO_LINEAR -- Scales a Vesa viewport to a graphic viewport    *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_Scale_To_Linear C near\n\tret\n\tENDP\tVesa_Scale_To_Linear\n\nEND\n"
  },
  {
    "path": "WWFLAT32/MEM/ALLOC.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : ALLOC.CPP                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : February 1, 1992                         *\n *                                                                         *\n *                  Last Update : March 9, 1995 [JLB]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Alloc -- Allocates system RAM.                                        *\n *   Ram_Free -- Determines the largest free chunk of RAM.                 *\n *   Free -- Free an Alloc'ed block of RAM.                                *\n *   Resize_Alloc -- Change the size of an allocated block.                *\n *   Heap_Size -- Size of the heap we have.                                *\n *   Total_Ram_Free -- Total amount of free RAM.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <malloc.h>\n#include <string.h>\n#include <stdlib.h>\n#include <dos.h>\n#include <bios.h>\n#include <stdio.h>\n\n\n#ifndef WWMEM_H\n#include \"wwmem.h\"\n#endif\n\n\nextern \"C\" unsigned long Largest_Mem_Block ( void ) ;\n\n//\n// use double-word alignment for allocs\n//\n#define LONG_ALIGNMENT\t\t\t1\n\n/*\n** Define the equates necessary to call a DPMI interrupt.\n*/\n#define\tDPMI_INT\t\t\t\t\t\t\t\t\t0x0031\n#define\tDPMI_LOCK_MEM\t\t\t\t\t\t\t0x0600\n#define\tDPMI_UNLOCK_MEM\t\t\t\t\t\t0x0601\n#define  LOGGING\t\t\t\t\t\t\t\t\tFALSE\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\nunsigned long MinRam=0L;\t\t// Record of least memory at worst case.\nunsigned long MaxRam=0L;\t\t// Record of total allocated at worst case.\nstatic unsigned long TotalRam = 0L;\nstatic unsigned long Memory_Calls = 0L;\nstatic unsigned long RequestedSystemRam = 16*1024*1024;\nstatic unsigned long LargestRamBlock = 0L;\n\t\t\nvoid (*Memory_Error)(void) = NULL;\nvoid (*Memory_Error_Exit)(char *string) = NULL;\n\n/***************************************************************************\n * DPMI_LOCK -- handles locking a block of DPMI memory                     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n#include\"mono.h\"\nvoid DPMI_Lock(VOID const *ptr, long const size)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\n\t/*\n\t** Lock memory\n\t** AX = 0x600\n\t** BX:CX = starting linear address of memory to lock\n\t** SI:DI = size of region to lock (in bytes)\n\t** - If Failure, carry flag is set.\n\t*/\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_LOCK_MEM;\n\tregs.x.ebx = ((long)ptr & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000ffff);\n\tregs.x.esi = ((long)size & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n//\tif (regs.x.cflag) {\n//\t}\n#if(0)\n\tchar *temp = (char *)ptr;\n\tchar hold;\n\tfor (int lp = 0; lp < size; lp += 2048) {\n\t\thold = *temp;\n\t\ttemp += 2048;\n\t}\n#endif\n\n}\n\n/***************************************************************************\n * DPMI_UNLOCK -- Handles unlocking a locked block of DPMI                 *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid DPMI_Unlock(void const *ptr, long const size)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\n\t/*\n\t** Unlock the memory\n\t*/\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_UNLOCK_MEM;\t\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = ((long)ptr & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000ffff);\n\tregs.x.esi = ((long)size & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n//\tif (regs.x.cflag) {\n//\t}\n\n}\n\n/***************************************************************************\n * Alloc -- Allocates system RAM.                                          *\n *                                                                         *\n *    This is the basic RAM allocation function.  It is used for all       *\n *    memory allocations needed by the system or the main program.         *\n *                                                                         *\n * INPUT:   bytes_to_alloc -- LONG value of the number of bytes to alloc.  *\n *                                                                         *\n *          flags          -- Memory allocation control flags.             *\n *             MEM_NORMAL: No special flags.                               *\n *             MEM_CLEAR:  Zero out memory block.                        \t*\n *             MEM_NEW:\t\tCalled by a new.                                *\n *                                                                         *\n * OUTPUT:  Returns with pointer to allocated block.  If NULL was returned *\n *          it indicates a failure to allocate.  Note: NULL will never be  *\n *          returned if the standard library allocation error routine is   *\n *          used.                                                          *\n *                                                                         *\n * WARNINGS:   If you replace the standard memory allocation error routine *\n *             and make it so that Alloc CAN return with a NULL, be sure   *\n *             and check for this in your code.                            *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Documented.                                          *\n *   08/09/1993 JLB : Updated with EMS memory support.                     *\n *   04/28/1994 JAW : Updated to 32bit Protected mode.                     *\n *   03/09/1995 JLB : Fixed                                                * \n *=========================================================================*/\nvoid *Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags)\n{\n\tunion REGS\t\tregs ;\n\tstruct SREGS \tsregs ;\n\tunsigned char *retval=NULL;\t// Pointer to allocated block.\n\tunsigned long\toriginal_size;\t// Original allocation size.\n\tunsigned long\tbytesfree;\t\t// Number of free bytes.\n\tlong \t\t\t\t*longptr=NULL;\t// Pointer used to store selector\n\tstatic unsigned char _allocinit=0;\n\n\n\t//\n\t// Init memory system by finding largest block to alloc\n\t// then allocate it to get one large heap and free it.\n\t// There may be more memory available from DPMI but we only are\n\t// for now allocating and freeing the first largest block.\n\t//\n\tif ( !_allocinit ) {\n\t\tunsigned long largestblock = Largest_Mem_Block();\n\t\tlargestblock -= 1024;\t\t\t\t// subtract for heap header and misc\n\t\tlargestblock &= 0xffff0000;\t\t// forcing to 64K boundary\n\n\t\tif ( largestblock ) {\n\t\t\tLargestRamBlock = MIN( largestblock, RequestedSystemRam );\n\t\t\tunsigned char *lptr = (unsigned char *)malloc( LargestRamBlock );\n\t\t\tif ( lptr ) {\n\t\t\t\tfree( (void *)lptr );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tInitialize the total ram available value.\n\t\t*/\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\n\t\t_allocinit = 1;\n\t}\n\n\t/* \n\t** Save the original allocated space size so that we can clear the\n\t** exact amount of RAM if they specified MEM_CLEAR.\n\t*/\n\toriginal_size = bytes_to_alloc;\n\n\t/*\n\t** Reserve one byte for the header of the memory we allocated.\n\t** We will store the flags variable there for later use.\n\t*/\n#if (LONG_ALIGNMENT)\n\tbytes_to_alloc += (flags & MEM_LOCK) ? 8 : 4;\n#else\n\tbytes_to_alloc += (flags & MEM_LOCK) ? 5 : 1;\n#endif\n\n\n\t// Try to allocate the memory out of the protected mode memory\n\t// chain if we did not require a real mode allocation.  If this \n\t// fails we will have to try to allocate it out of real mode memory.\n\t// Real mode memory is a last resort because some types of applications\n\t// require real mode memory.\n\tif (!(flags & MEM_REAL)) {\n\t\tretval = (unsigned char*)malloc(bytes_to_alloc);\n\t}\n\n\t// Try to allocate the memory out of the real mode memory using DPMI\n\t// service 0x100.  Note that retval will be null if we are requesting\n\t// real mode memory so that we do not have to explicitly check for the\n\t// real mode flag.  Remember we need to reserve room for the dos \n\t// selector value at the beginning of our allocated block so rather than\n\t// adding fifteen and rounding, we need to add 19 and round.\n\tif (!retval) {\n\t\tflags = (MemoryFlagType)(flags | MEM_REAL);\n\t\tregs.x.eax = 0x100;\n\t\tregs.x.ebx = (bytes_to_alloc + 19) >> 4;\n\t\tif (regs.x.ebx & 0xFFFF0000) {\n\t\t\tretval = NULL;\n\t\t} else {\n\t\t\tsegread ( & sregs ) ;\n\t\t\tint386x ( 0x31 , & regs, & regs , & sregs\t) ;\n\t\t\tif (regs.x.cflag)\n\t\t\t\tretval = NULL;\n\t\t\telse {\n#if (LONG_ALIGNMENT)\n\t\t\t\tlongptr\t\t= (long *)(((regs.x.eax & 0xFFFF) << 4)+ 4);\n#else\n\t\t\t\tlongptr\t\t= (long *)(((regs.x.eax & 0xFFFF) << 4)+ 1);\n#endif\n\t\t\t\t*longptr++\t= regs.x.edx & 0xFFFF;\n\t\t\t\tretval\t\t= (unsigned char *)longptr;\n\t\t\t}\n\t\t}\n\t}\n\n\t// If the alloc failed then we need to signify a memory error.\n\tif (retval == NULL) {\n\t\tif (Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\t\t\n\t}\n\n\t// If the memory needs to be DPMI locked then we should store the\n\t// original size in the header before we store the flags.\n\tif (flags & MEM_LOCK) {\n\t\tlongptr\t\t= (long *)retval;\n\t\t*longptr++\t= original_size;\n\t\tretval\t\t= (unsigned char *)longptr;\n\t}\n\n\n\t// Now that we know the alloc was sucessful (and for an extra byte\n\t// more than the user wanted) we need to stick in the memory flags.\n#if (LONG_ALIGNMENT)\n\tif ( !(flags & (MEM_LOCK|MEM_REAL)) ) {\n\t\t//\n\t\t// WARNING!!!!!!!!!!\n\t\t// USE this only with the WATCOM malloc ALLOCATION!!!!!!!!!\n\t\t// it reads the actual block size before the ptr returned.\n\t\t// then eors and uses the upper word for a validation later on free.\n\t\t//\n\t\tlongptr = (long *)retval;\n\t\t*longptr = ((*(longptr - 1)) ^ 0xffffffff) & 0xffff0000;\n\t\t*retval++ \t\t= flags;\n\t\t*retval++ \t\t= (unsigned char)(flags ^ 0xff);\n\t\tretval += 2;\n\t}\n\telse {\n\t\t*retval++ \t\t= flags;\n\t\t*retval++ \t\t= (unsigned char)(flags ^ 0xff);\n\t\t*retval++ \t\t= 0;\n\t\t*retval++ \t\t= 0;\n\t}\n#else\n\t*retval++ \t\t= (unsigned char)(flags | (((flags ^ 0x07) & 0x07) << 5));\n#endif\n\n\t// If the memory needed to be DPMI locked then set it up so it\n\t// is locked.\n\tif (flags & MEM_LOCK) {\n\t\tDPMI_Lock(retval, original_size);\n\t}\n\n\t/* Clear the space if they wanted it clear */\n\n\tif (flags & MEM_CLEAR) {\n\t\tunsigned char\t*ptr;\t\t// Working memory block pointer.\n\n\t\tptr = retval;\n\t\tmemset(ptr, '\\0', original_size);\n\t}\n\n\tbytesfree = Total_Ram_Free(MEM_NORMAL);\n\tif (bytesfree < MinRam) {\n\t\tMinRam = bytesfree;\n\t}\n\tif (TotalRam-bytesfree > MaxRam) {\n\t\tMaxRam = TotalRam-bytesfree;\n\t}\n\n\tMemory_Calls++;\n\n#if(LOGGING)\n\tint val = _heapchk();\n\n\tFILE *file = fopen(\"mem.txt\",\"at\");\n\tfprintf(file, \"%P Alloc size = %d, Actual Size = %d, flags = %d, heap = %d\\n\", \n\t\t\t\t\t\tretval,\n\t\t\t\t\t\toriginal_size,\n\t\t\t\t\t\tbytes_to_alloc,\n\t\t\t\t\t\tflags,\n\t\t\t\t\t\tval);\n\tfclose(file);\n#endif\n\n\treturn(retval);\n}\n\n\n/***************************************************************************\n * Free -- Free an Alloc'ed block of RAM.                                  *\n *                                                                         *\n * FUNCTION:                                                               *\n *                                                                         *\n * INPUT:       A pointer to a block of RAM from Alloc.                    *\n *                                                                         *\n * OUTPUT:      None.                                                      *\n *                                                                         *\n * WARNINGS:    Don't use this for an Alloc_Block'ed RAM block.            *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/25/1990     : Created.                                             *\n ***************************************************************************/\nvoid Free(void const *pointer)\n{\n\tunion REGS\t\tregs ;\n\tstruct SREGS \tsregs ;\n\n\tvoid const *original = pointer;\n\tchar string[80];\n\n\tif (pointer) {\n\t\t/*\n\t\t** Get a pointer to the flags that we stored off.\n\t\t*/\n#if (LONG_ALIGNMENT)\n\t\tunsigned char *byteptr\t= ((unsigned char *)pointer) - 4;\n\n\t\t//\n\t\t// validate the flags with and eor of the flags\n\t\t//\n\t\tif ( *byteptr != ((*(byteptr + 1)) ^ 0xff) ) {\n\t\t\tif (Memory_Error_Exit != NULL) {\n\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n\t\t\t\tMemory_Error_Exit( string );\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif ( !(*byteptr & (MEM_LOCK|MEM_REAL)) ) {\n\t\t\t\tunsigned short *wordptr = (unsigned short *)(byteptr - 2);\n\n\t\t\t\t//\n\t\t\t\t// WARNING!!!!!!!!!!\n\t\t\t\t// USE this only with the WATCOM malloc ALLOCATION!!!!!!!!!\n\t\t\t\t// it reads the actual block size before the ptr to be freed.\n\t\t\t\t// then compares with the EOR to the value stored during allocation.\n\t\t\t\t//\n\t\t\t\tif ( *wordptr != ((*(wordptr + 2)) ^ 0xffff) ) {\n\t\t\t\t\tif (Memory_Error_Exit != NULL) {\n\t\t\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n\t\t\t\t\t\tMemory_Error_Exit( string );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( *(byteptr + 2) || *(byteptr + 3) ) {\n\t\t\t\tif (Memory_Error_Exit != NULL) {\n\t\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n\t\t\t\t\tMemory_Error_Exit( string );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n//\t\tif ( *byteptr != (*(byteptr + 1) ^ 0xff) ||\n//\t\t\t*(byteptr + 2) || *(byteptr + 3) ) {\n//\t\t\tif (Memory_Error_Exit != NULL) {\n//\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n//\t\t\t\tMemory_Error_Exit( string );\n//\t\t\t}\n//\t\t}\n#else\n\t\tunsigned char *byteptr\t= ((unsigned char *)pointer) - 1;\n\n\t\tif ( (*byteptr & 0xe0) != (((*byteptr ^ 0x07) & 0x07) << 5) ) {\n\t\t\tif (Memory_Error_Exit != NULL) {\n\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n\t\t\t\tMemory_Error_Exit( string );\n\t\t\t}\n\t\t}\n#endif\n\n\t\t/*\n\t\t** Check to see if this was locked me and if it was unlock it.\n\t\t*/\n\t\tif (*byteptr & MEM_LOCK) {\n\t\t\tlong *longptr = ((long *)byteptr) - 1;\n\t\t\tDPMI_Unlock(pointer, *longptr);\n\t\t\tpointer = (void *)longptr;\n\t\t} else\n\t\t\tpointer = (void *)byteptr;\n\n#if(LOGGING)\t\t\n\t\tint val = _heapchk();\n\t\tFILE *file = fopen(\"mem.txt\",\"at\");\n\t\tfprintf(file, \"%P Free flags = %d, Heap = %d\\n\", \n\t\t\t\t\t\t\toriginal,\n\t\t\t\t\t\t\t*byteptr, \n\t\t\t\t\t\t\tval);\n\t\tfclose(file);\n#endif\n\n\t\t// If the pointer is a real mode pointer than it will point to the\n\t\t// first megabyte of system memory.  If it does than we need to \n\t\t// use DPMI to free it.\n\t\tif (*byteptr & MEM_REAL) {\n\t\t\tregs.x.eax\t= 0x101;\n\t\t\tregs.x.edx\t= *(((long *)pointer) - 1);\n\t\t\tsegread ( & sregs ) ;\n\t\t\tint386x(0x31, &regs, &regs, &sregs);\n\t\t} else {\n\t\t\tfree((void *)pointer);\n\t\t}\n\t\tMemory_Calls--;\n\t}\n}\n\n\n/***************************************************************************\n * Resize_Alloc -- Change the size of an allocated block.                  *\n *                                                                         *\n *    This routine will take a previously allocated block and change its   *\n *    size without unnecessarily altering its contents.                    *\n *                                                                         *\n * INPUT:   pointer  -- Pointer to the original memory allocation.         *\n *                                                                         *\n *          new_size -- Size in bytes that it will be converted to.        *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the new allocation.                  *\n *                                                                         *\n * WARNINGS:   ???                                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/01/1992 JLB : Commented.                                           *\n *=========================================================================*/\nvoid *Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes)\n{\n\n\tunsigned long *temp;\n//\tunsigned long diff, flags;\n\n\ttemp = (unsigned long*)original_ptr;\n\n\t/* ReAlloc the space */\n\ttemp = (unsigned long *)realloc(temp, new_size_in_bytes);\n\tif (temp == NULL) {\n\t\tif (Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\t\t\n\t}\t\t\t   \n\n\treturn(temp);\n}\n\n\n/***************************************************************************\n * Ram_Free -- Determines the largest free chunk of RAM.                   *\n *                                                                         *\n *    Use this routine to determine the largest free chunk of available    *\n *    RAM for allocation.  It also performs a check of the memory chain.   *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  Returns with the size of the largest free chunk of RAM.        *\n *                                                                         *\n * WARNINGS:   This does not return the TOTAL memory free, only the        *\n *             largest free chunk.                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Commented.                                           *\n *=========================================================================*/\nlong Ram_Free(MemoryFlagType)\n{\n\treturn(_memmax());\n//\treturn Largest_Mem_Block();\n}\n\n\n/***************************************************************************\n * Heap_Size -- Size of the heap we have.                                  *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Heap_Size(MemoryFlagType )\n{\n\tif (!TotalRam) {\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\t}\n\treturn(TotalRam);\n}\n\n\n/***************************************************************************\n * Total_Ram_Free -- Total amount of free RAM.                             *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *   03/09/1995 JLB : Uses prerecorded heap size maximum.                  * \n *=========================================================================*/\nlong Total_Ram_Free(MemoryFlagType )\n{\n\treturn(_memavl());\n//\treturn Largest_Mem_Block () ;\n}\n\n"
  },
  {
    "path": "WWFLAT32/MEM/ALLOC.CPP.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : ALLOC.CPP                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : February 1, 1992                         *\n *                                                                         *\n *                  Last Update : March 9, 1995 [JLB]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Alloc -- Allocates system RAM.                                        *\n *   Ram_Free -- Determines the largest free chunk of RAM.                 *\n *   Free -- Free an Alloc'ed block of RAM.                                *\n *   Resize_Alloc -- Change the size of an allocated block.                *\n *   Heap_Size -- Size of the heap we have.                                *\n *   Total_Ram_Free -- Total amount of free RAM.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <malloc.h>\n#include <string.h>\n#include <stdlib.h>\n#include <dos.h>\n#include <bios.h>\n#include <stdio.h>\n\n\n#ifndef WWMEM_H\n#include \"wwmem.h\"\n#endif\n\n\nextern \"C\" unsigned long Largest_Mem_Block ( void ) ;\n\n//\n// use double-word alignment for allocs\n//\n#define LONG_ALIGNMENT\t\t\t1\n\n/*\n** Define the equates necessary to call a DPMI interrupt.\n*/\n#define\tDPMI_INT\t\t\t\t\t\t\t\t\t0x0031\n#define\tDPMI_LOCK_MEM\t\t\t\t\t\t\t0x0600\n#define\tDPMI_UNLOCK_MEM\t\t\t\t\t\t0x0601\n#define  LOGGING\t\t\t\t\t\t\t\t\tFALSE\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\nunsigned long MinRam=0L;\t\t// Record of least memory at worst case.\nunsigned long MaxRam=0L;\t\t// Record of total allocated at worst case.\nstatic unsigned long TotalRam = 0L;\nstatic unsigned long Memory_Calls = 0L;\nstatic unsigned long RequestedSystemRam = 12*1024*1024;\nstatic unsigned long LargestRamBlock = 0L;\n\t\t\nvoid (*Memory_Error)(void) = NULL;\nvoid (*Memory_Error_Exit)(char *string) = NULL;\n\n/***************************************************************************\n * DPMI_LOCK -- handles locking a block of DPMI memory                     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n#include\"mono.h\"\nvoid DPMI_Lock(VOID const *ptr, long const size)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\n\t/*\n\t** Lock memory\n\t** AX = 0x600\n\t** BX:CX = starting linear address of memory to lock\n\t** SI:DI = size of region to lock (in bytes)\n\t** - If Failure, carry flag is set.\n\t*/\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_LOCK_MEM;\n\tregs.x.ebx = ((long)ptr & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000ffff);\n\tregs.x.esi = ((long)size & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n//\tif (regs.x.cflag) {\n//\t}\n#if(0)\n\tchar *temp = (char *)ptr;\n\tchar hold;\n\tfor (int lp = 0; lp < size; lp += 2048) {\n\t\thold = *temp;\n\t\ttemp += 2048;\n\t}\n#endif\n\n}\n\n/***************************************************************************\n * DPMI_UNLOCK -- Handles unlocking a locked block of DPMI                 *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid DPMI_Unlock(void const *ptr, long const size)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\n\t/*\n\t** Unlock the memory\n\t*/\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_UNLOCK_MEM;\t\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = ((long)ptr & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000ffff);\n\tregs.x.esi = ((long)size & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n//\tif (regs.x.cflag) {\n//\t}\n\n}\n\n/***************************************************************************\n * Alloc -- Allocates system RAM.                                          *\n *                                                                         *\n *    This is the basic RAM allocation function.  It is used for all       *\n *    memory allocations needed by the system or the main program.         *\n *                                                                         *\n * INPUT:   bytes_to_alloc -- LONG value of the number of bytes to alloc.  *\n *                                                                         *\n *          flags          -- Memory allocation control flags.             *\n *             MEM_NORMAL: No special flags.                               *\n *             MEM_CLEAR:  Zero out memory block.                        \t*\n *             MEM_NEW:\t\tCalled by a new.                                *\n *                                                                         *\n * OUTPUT:  Returns with pointer to allocated block.  If NULL was returned *\n *          it indicates a failure to allocate.  Note: NULL will never be  *\n *          returned if the standard library allocation error routine is   *\n *          used.                                                          *\n *                                                                         *\n * WARNINGS:   If you replace the standard memory allocation error routine *\n *             and make it so that Alloc CAN return with a NULL, be sure   *\n *             and check for this in your code.                            *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Documented.                                          *\n *   08/09/1993 JLB : Updated with EMS memory support.                     *\n *   04/28/1994 JAW : Updated to 32bit Protected mode.                     *\n *   03/09/1995 JLB : Fixed                                                * \n *=========================================================================*/\nvoid *Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags)\n{\n\tunion REGS\t\tregs ;\n\tstruct SREGS \tsregs ;\n\tunsigned char *retval=NULL;\t// Pointer to allocated block.\n\tunsigned long\toriginal_size;\t// Original allocation size.\n\tunsigned long\tbytesfree;\t\t// Number of free bytes.\n\tlong \t\t\t\t*longptr=NULL;\t// Pointer used to store selector\n\tstatic unsigned char _allocinit=0;\n\n\n\t//\n\t// Init memory system by finding largest block to alloc\n\t// then allocate it to get one large heap and free it.\n\t// There may be more memory available from DPMI but we only are\n\t// for now allocating and freeing the first largest block.\n\t//\n\tif ( !_allocinit ) {\n\t\tunsigned long largestblock = Largest_Mem_Block();\n\t\tlargestblock -= 1024;\t\t\t\t// subtract for heap header and misc\n\t\tlargestblock &= 0xffff0000;\t\t// forcing to 64K boundary\n\n\t\tif ( largestblock ) {\n\t\t\tLargestRamBlock = MIN( largestblock, RequestedSystemRam );\n\t\t\tunsigned char *lptr = (unsigned char *)malloc( LargestRamBlock );\n\t\t\tif ( lptr ) {\n\t\t\t\tfree( (void *)lptr );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tInitialize the total ram available value.\n\t\t*/\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\n\t\t_allocinit = 1;\n\t}\n\n\t/* \n\t** Save the original allocated space size so that we can clear the\n\t** exact amount of RAM if they specified MEM_CLEAR.\n\t*/\n\toriginal_size = bytes_to_alloc;\n\n\t/*\n\t** Reserve one byte for the header of the memory we allocated.\n\t** We will store the flags variable there for later use.\n\t*/\n#if (LONG_ALIGNMENT)\n\tbytes_to_alloc += (flags & MEM_LOCK) ? 8 : 4;\n#else\n\tbytes_to_alloc += (flags & MEM_LOCK) ? 5 : 1;\n#endif\n\n\n\t// Try to allocate the memory out of the protected mode memory\n\t// chain if we did not require a real mode allocation.  If this \n\t// fails we will have to try to allocate it out of real mode memory.\n\t// Real mode memory is a last resort because some types of applications\n\t// require real mode memory.\n\tif (!(flags & MEM_REAL)) {\n\t\tretval = (unsigned char*)malloc(bytes_to_alloc);\n\t}\n\n\t// Try to allocate the memory out of the real mode memory using DPMI\n\t// service 0x100.  Note that retval will be null if we are requesting\n\t// real mode memory so that we do not have to explicitly check for the\n\t// real mode flag.  Remember we need to reserve room for the dos \n\t// selector value at the beginning of our allocated block so rather than\n\t// adding fifteen and rounding, we need to add 19 and round.\n\tif (!retval) {\n\t\tflags = (MemoryFlagType)(flags | MEM_REAL);\n\t\tregs.x.eax = 0x100;\n\t\tregs.x.ebx = (bytes_to_alloc + 19) >> 4;\n\t\tif (regs.x.ebx & 0xFFFF0000) {\n\t\t\tretval = NULL;\n\t\t} else {\n\t\t\tsegread ( & sregs ) ;\n\t\t\tint386x ( 0x31 , & regs, & regs , & sregs\t) ;\n\t\t\tif (regs.x.cflag)\n\t\t\t\tretval = NULL;\n\t\t\telse {\n#if (LONG_ALIGNMENT)\n\t\t\t\tlongptr\t\t= (long *)(((regs.x.eax & 0xFFFF) << 4)+ 4);\n#else\n\t\t\t\tlongptr\t\t= (long *)(((regs.x.eax & 0xFFFF) << 4)+ 1);\n#endif\n\t\t\t\t*longptr++\t= regs.x.edx & 0xFFFF;\n\t\t\t\tretval\t\t= (unsigned char *)longptr;\n\t\t\t}\n\t\t}\n\t}\n\n\t// If the alloc failed then we need to signify a memory error.\n\tif (retval == NULL) {\n\t\tif (Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\t\t\n\t}\n\n\t// If the memory needs to be DPMI locked then we should store the\n\t// original size in the header before we store the flags.\n\tif (flags & MEM_LOCK) {\n\t\tlongptr\t\t= (long *)retval;\n\t\t*longptr++\t= original_size;\n\t\tretval\t\t= (unsigned char *)longptr;\n\t}\n\n\n\t// Now that we know the alloc was sucessful (and for an extra byte\n\t// more than the user wanted) we need to stick in the memory flags.\n#if (LONG_ALIGNMENT)\n\tif ( !(flags & (MEM_LOCK|MEM_REAL)) ) {\n\t\t//\n\t\t// WARNING!!!!!!!!!!\n\t\t// USE this only with the WATCOM malloc ALLOCATION!!!!!!!!!\n\t\t// it reads the actual block size before the ptr returned.\n\t\t// then eors and uses the upper word for a validation later on free.\n\t\t//\n\t\tlongptr = (long *)retval;\n\t\t*longptr = ((*(longptr - 1)) ^ 0xffffffff) & 0xffff0000;\n\t\t*retval++ \t\t= flags;\n\t\t*retval++ \t\t= (unsigned char)(flags ^ 0xff);\n\t\tretval += 2;\n\t}\n\telse {\n\t\t*retval++ \t\t= flags;\n\t\t*retval++ \t\t= (unsigned char)(flags ^ 0xff);\n\t\t*retval++ \t\t= 0;\n\t\t*retval++ \t\t= 0;\n\t}\n#else\n\t*retval++ \t\t= (unsigned char)(flags | (((flags ^ 0x07) & 0x07) << 5));\n#endif\n\n\t// If the memory needed to be DPMI locked then set it up so it\n\t// is locked.\n\tif (flags & MEM_LOCK) {\n\t\tDPMI_Lock(retval, original_size);\n\t}\n\n\t/* Clear the space if they wanted it clear */\n\n\tif (flags & MEM_CLEAR) {\n\t\tunsigned char\t*ptr;\t\t// Working memory block pointer.\n\n\t\tptr = retval;\n\t\tmemset(ptr, '\\0', original_size);\n\t}\n\n\tbytesfree = Total_Ram_Free(MEM_NORMAL);\n\tif (bytesfree < MinRam) {\n\t\tMinRam = bytesfree;\n\t}\n\tif (TotalRam-bytesfree > MaxRam) {\n\t\tMaxRam = TotalRam-bytesfree;\n\t}\n\n\tMemory_Calls++;\n\n#if(LOGGING)\n\tint val = _heapchk();\n\n\tFILE *file = fopen(\"mem.txt\",\"at\");\n\tfprintf(file, \"%P Alloc size = %d, Actual Size = %d, flags = %d, heap = %d\\n\", \n\t\t\t\t\t\tretval,\n\t\t\t\t\t\toriginal_size,\n\t\t\t\t\t\tbytes_to_alloc,\n\t\t\t\t\t\tflags,\n\t\t\t\t\t\tval);\n\tfclose(file);\n#endif\n\n\treturn(retval);\n}\n\n\n/***************************************************************************\n * Free -- Free an Alloc'ed block of RAM.                                  *\n *                                                                         *\n * FUNCTION:                                                               *\n *                                                                         *\n * INPUT:       A pointer to a block of RAM from Alloc.                    *\n *                                                                         *\n * OUTPUT:      None.                                                      *\n *                                                                         *\n * WARNINGS:    Don't use this for an Alloc_Block'ed RAM block.            *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/25/1990     : Created.                                             *\n ***************************************************************************/\nvoid Free(void const *pointer)\n{\n\tunion REGS\t\tregs ;\n\tstruct SREGS \tsregs ;\n\n\tvoid const *original = pointer;\n\tchar string[80];\n\n\tif (pointer) {\n\t\t/*\n\t\t** Get a pointer to the flags that we stored off.\n\t\t*/\n#if (LONG_ALIGNMENT)\n\t\tunsigned char *byteptr\t= ((unsigned char *)pointer) - 4;\n\n\t\t//\n\t\t// validate the flags with and eor of the flags\n\t\t//\n\t\tif ( *byteptr != ((*(byteptr + 1)) ^ 0xff) ) {\n\t\t\tif (Memory_Error_Exit != NULL) {\n\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n\t\t\t\tMemory_Error_Exit( string );\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif ( !(*byteptr & (MEM_LOCK|MEM_REAL)) ) {\n\t\t\t\tunsigned short *wordptr = (unsigned short *)(byteptr - 2);\n\n\t\t\t\t//\n\t\t\t\t// WARNING!!!!!!!!!!\n\t\t\t\t// USE this only with the WATCOM malloc ALLOCATION!!!!!!!!!\n\t\t\t\t// it reads the actual block size before the ptr to be freed.\n\t\t\t\t// then compares with the EOR to the value stored during allocation.\n\t\t\t\t//\n\t\t\t\tif ( *wordptr != ((*(wordptr + 2)) ^ 0xffff) ) {\n\t\t\t\t\tif (Memory_Error_Exit != NULL) {\n\t\t\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n\t\t\t\t\t\tMemory_Error_Exit( string );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( *(byteptr + 2) || *(byteptr + 3) ) {\n\t\t\t\tif (Memory_Error_Exit != NULL) {\n\t\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n\t\t\t\t\tMemory_Error_Exit( string );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n//\t\tif ( *byteptr != (*(byteptr + 1) ^ 0xff) ||\n//\t\t\t*(byteptr + 2) || *(byteptr + 3) ) {\n//\t\t\tif (Memory_Error_Exit != NULL) {\n//\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n//\t\t\t\tMemory_Error_Exit( string );\n//\t\t\t}\n//\t\t}\n#else\n\t\tunsigned char *byteptr\t= ((unsigned char *)pointer) - 1;\n\n\t\tif ( (*byteptr & 0xe0) != (((*byteptr ^ 0x07) & 0x07) << 5) ) {\n\t\t\tif (Memory_Error_Exit != NULL) {\n\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n\t\t\t\tMemory_Error_Exit( string );\n\t\t\t}\n\t\t}\n#endif\n\n\t\t/*\n\t\t** Check to see if this was locked me and if it was unlock it.\n\t\t*/\n\t\tif (*byteptr & MEM_LOCK) {\n\t\t\tlong *longptr = ((long *)byteptr) - 1;\n\t\t\tDPMI_Unlock(pointer, *longptr);\n\t\t\tpointer = (void *)longptr;\n\t\t} else\n\t\t\tpointer = (void *)byteptr;\n\n#if(LOGGING)\t\t\n\t\tint val = _heapchk();\n\t\tFILE *file = fopen(\"mem.txt\",\"at\");\n\t\tfprintf(file, \"%P Free flags = %d, Heap = %d\\n\", \n\t\t\t\t\t\t\toriginal,\n\t\t\t\t\t\t\t*byteptr, \n\t\t\t\t\t\t\tval);\n\t\tfclose(file);\n#endif\n\n\t\t// If the pointer is a real mode pointer than it will point to the\n\t\t// first megabyte of system memory.  If it does than we need to \n\t\t// use DPMI to free it.\n\t\tif (*byteptr & MEM_REAL) {\n\t\t\tregs.x.eax\t= 0x101;\n\t\t\tregs.x.edx\t= *(((long *)pointer) - 1);\n\t\t\tsegread ( & sregs ) ;\n\t\t\tint386x(0x31, &regs, &regs, &sregs);\n\t\t} else {\n\t\t\tfree((void *)pointer);\n\t\t}\n\t\tMemory_Calls--;\n\t}\n}\n\n\n/***************************************************************************\n * Resize_Alloc -- Change the size of an allocated block.                  *\n *                                                                         *\n *    This routine will take a previously allocated block and change its   *\n *    size without unnecessarily altering its contents.                    *\n *                                                                         *\n * INPUT:   pointer  -- Pointer to the original memory allocation.         *\n *                                                                         *\n *          new_size -- Size in bytes that it will be converted to.        *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the new allocation.                  *\n *                                                                         *\n * WARNINGS:   ???                                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/01/1992 JLB : Commented.                                           *\n *=========================================================================*/\nvoid *Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes)\n{\n\n\tunsigned long *temp;\n//\tunsigned long diff, flags;\n\n\ttemp = (unsigned long*)original_ptr;\n\n\t/* ReAlloc the space */\n\ttemp = (unsigned long *)realloc(temp, new_size_in_bytes);\n\tif (temp == NULL) {\n\t\tif (Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\t\t\n\t}\t\t\t   \n\n\treturn(temp);\n}\n\n\n/***************************************************************************\n * Ram_Free -- Determines the largest free chunk of RAM.                   *\n *                                                                         *\n *    Use this routine to determine the largest free chunk of available    *\n *    RAM for allocation.  It also performs a check of the memory chain.   *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  Returns with the size of the largest free chunk of RAM.        *\n *                                                                         *\n * WARNINGS:   This does not return the TOTAL memory free, only the        *\n *             largest free chunk.                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Commented.                                           *\n *=========================================================================*/\nlong Ram_Free(MemoryFlagType)\n{\n\treturn(_memmax());\n//\treturn Largest_Mem_Block();\n}\n\n\n/***************************************************************************\n * Heap_Size -- Size of the heap we have.                                  *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Heap_Size(MemoryFlagType )\n{\n\tif (!TotalRam) {\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\t}\n\treturn(TotalRam);\n}\n\n\n/***************************************************************************\n * Total_Ram_Free -- Total amount of free RAM.                             *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *   03/09/1995 JLB : Uses prerecorded heap size maximum.                  * \n *=========================================================================*/\nlong Total_Ram_Free(MemoryFlagType )\n{\n\treturn(_memavl());\n//\treturn Largest_Mem_Block () ;\n}\n\n"
  },
  {
    "path": "WWFLAT32/MEM/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 24, 1994                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = mem\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR\t    = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\nCC_CFG += /zm\t\t\t\t\t\t\t\t\t# Each routine to be in its own segment.\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\talloc.obj  \t&\n\tmem.obj  \t&\n\tnewdel.obj  \t&\n\tmem_copy.obj \n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WWFLAT32/MEM/MEM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : MEM.C                                    *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : March 31, 1993                           *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Mem_Free -- Free a block of memory from system.                       *\n *   Mem_Alloc -- Allocate a block of memory from the special memory pool. *\n *   Mem_Init -- Initialize the private memory allocation pool.            *\n *   Mem_Reference -- Updates the reference time for the specified memory blo*\n *   Mem_Find -- Returns with pointer to specified memory block.           *\n *   Mem_Find_Oldest -- Returns with the memory block with the oldest time st*\n *   Mem_Free_Oldest -- Find and free the oldest memory block.             *\n *   Mem_Avail -- Returns the amount of free memory available in the cache.*\n *   Mem_Cleanup -- Performes a garbage collection on the memory cache.    *\n *   MemNode_Unlink -- Unlinks a node from the cache.                      *\n *   MemNode_Insert -- Inserts a node into a cache chain.                  *\n *   Mem_Largest_Avail -- Largest free block available.                    *\n *   Mem_Lock_Block -- Locks a block so that it cannot be moved in cleanup.*\n *   Mem_In_Use -- Makes it so a block will never be returned as oldest*\n *   Mem_Pool_Size -- Returns total amount of memory in pool.              *\n *   Mem_Get_ID -- Returns ID of node.                                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"wwmem.h\"\n#include <timer.h>\n\n#include\t<stddef.h>\n#include\t<mem.h>\n\nextern TimerClass TickCount;\n\n#define DEBUG_FILL FALSE\n\n////////////////////////////////////////////////////////////////////////////\n\n\n\n/*******************************************************************************\n** A allocated block may have one of three meanings in the Time field.  The first\n** is the time stamp of the last time it was referenced.  The other two values\n** are defined below.  MEM_BLOCK_IN_USE means that it will never be returned as the\n** oldest since there is no valid time stamp.  LOCKED_BLOCK has the same meaning as\n** MEM_BLOCK_IN_USE with the added feature that the block will not be moved in a \n** Mem_Cleanup().  Therefore, there may be some fragmentation after the cleanup\n** if any blocks are LOCKED.  It would be good practice to seldomly lock blocks,\n** for instance, only when a sample is being played.\n** WARNING: If these values change to anything else, logic will need to be changed\n**          in Mem_Find_Oldest since it relies on these being small values.\n*/\n#define MEM_BLOCK_IN_USE\t0x00\n#define MEM_BLOCK_LOCKED\t0x01\n\n/*\n**\tEach block of memory in the pool is headed by this structure.\n*/\ntypedef struct MemChain {\n\tstruct MemChain\t*Next;\t// Pointer to next memory chain node.\n\tstruct MemChain\t*Prev;\t// Pointer to previous memory chain node.\n\tunsigned long\t\tID;\t\t// ID number of block.\n\tunsigned short\t\tTime;\t\t// TickCount of latest reference.\n\tunsigned short\t\tSize;\t\t// Size of memory block (in paragraphs).\n} MemChain_Type;\n\n\n/*\n**\tHolding tank memory management data.\n*/\ntypedef struct MemPool {\n\tMemChain_Type\t*FreeChain;\t// Pointer to first node in free chain.\n\tMemChain_Type\t*UsedChain;\t// Pointer to first node in used chain.\n\tunsigned short\tFreeMem;\t\t// Current amount of free ram (in paragraphs).\n\tunsigned short\tTotalMem;\t// Total quantity of memory.\n\tlong\t\t\t\tpad2;\n} MemPool_Type;\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE void MemNode_Unlink(MemPool_Type *pool, int freechain, MemChain_Type *node);\nPRIVATE void MemNode_Insert(MemPool_Type *pool, int freechain, MemChain_Type *node, unsigned int size, unsigned long id, int merge);\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * Mem_Init -- Initialize the private memory allocation pool.              *\n *                                                                         *\n *    This routine is used to initialize the private memory allocation     *\n *    pool.                                                                *\n *                                                                         *\n * INPUT:   buffer   -- Pointer to the buffer that is the allocation pool. *\n *                                                                         *\n *          size     -- Size of the buffer in bytes.                       *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Was it initialized successfully?                   *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nint Mem_Init(void *buffer, long size)\n{\n\tMemChain_Type\t*mem;\t\t\t// Working memory chain node.\n\tMemPool_Type\t*pool;\t\t// Memory pool control structure.\n\n\t/*\n\t**\tThe buffer is rounded down to the nearest paragraph.\n\t*/\n\tsize = size & 0xFFFFFFF0L;\n\n\tif (!buffer || !size) return(FALSE);\n\n\t/*\n\t**\tInitialize the pool control structure.\n\t*/\n\tpool = (MemPool_Type *)buffer;\n\tpool->FreeMem = (size - sizeof(MemPool_Type)) >> 4;\n\tpool->UsedChain = NULL;\n\tpool->TotalMem = pool->FreeMem;\n\tmem = pool->FreeChain = (MemChain_Type *) (pool + 1);\n\n\t/*\n\t**\tInitialize the free memory chain.\n\t*/\n\tmem->Next = NULL;\n\tmem->Prev = NULL;\n\tmem->Size = pool->FreeMem;\n\tmem->ID = -1;\n\tmem->Time = 0;\n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * Mem_Alloc -- Allocate a block of memory from the special memory pool.   *\n *                                                                         *\n *    This routine will allocate a block of memory from the special        *\n *    memory allocation pool.                                              *\n *                                                                         *\n * INPUT:   poolptr\t-- Pointer to the memory pool base address.           *\n *                                                                         *\n *          size  -- The size of the memory block to allocate.             *\n *                                                                         *\n *          id    -- ID number to give this memory block.                  *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the allocated block.  If there was   *\n *          insufficient room, then NULL is returned.                      *\n *                                                                         *\n * WARNINGS:   Be sure to check for the NULL return case.                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Alloc(void *poolptr, long lsize, unsigned long id)\n{\n\tMemPool_Type\t*pool;\n\tMemChain_Type\t*node;\t\t\t// Pointer to current memory node.\n\tunsigned int\tremainder=0;\t// Remaining bytes that are still free.\n\tint\t\t\t\tfound;\n\tint\t\t\t\tsize;\t\t\t\t// Paragraph size of allocation.\n\n\n\t/*\n\t**\tIf there is no free memory then the allocation will\n\t**\talways fail.\n\t*/\n\tif (!poolptr || !lsize) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\t\t\n\t/*\n\t**\tAllocations are forced to be paragraph sized.\n\t*/\n\tlsize += sizeof(MemChain_Type);\t// Account for header.\n\tlsize = (lsize + 0x0FL) & 0xFFFFFFF0L;\n\tsize = (int)(lsize >> 4);\n\n\t/*\n\t**\tIf the total free is less than the size of the desired allocation,\n\t**\tthen we KNOW that an allocation will fail -- just return.\n\t*/\n\tif (pool->TotalMem < size) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tWalk down free chain looking for the first block that will\n\t**\taccomodate the allocation.\n\t*/\n\tnode = pool->FreeChain;\n\tfound = FALSE;\n\twhile (!found && node) {\n\n\t\t/*\n\t\t**\tFetch free memory chunk block and see if it is big enough.\n\t\t*/\n\t\tif (node->Size >= size) {\n\t\t\tfound = TRUE;\n\t\t\tbreak;\n\t\t}\n\t\tnode = node->Next;\n\t}\n\tif (!found) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tDetermine if this allocation would split the block.\n\t*/\n\tremainder = node->Size - size;\n\n\t/*\n\t**\tIf only a very small free chunk would remain, just tack it on\n\t**\tto the current allocation.\n\t*/\n\tif (remainder <= 2) {\n\t\tremainder = 0;\n\t\tsize = node->Size;\n\t}\n\n\t/*\n\t**\tRemove the primary block from the free memory list.\n\t*/\n\tMemNode_Unlink(pool, TRUE, node);\n\n\t/*\n\t**\tIf a smaller block remains, then link it back into\n\t**\tthe free memory list.\n\t*/\n\tif (remainder) {\n\t\tMemNode_Insert(pool, TRUE, (MemChain_Type *)Add_Long_To_Pointer(node, (long)size << 4), remainder, -1, FALSE);\n\t}\n\n\t/*\n\t**\tLink in the allocated node into the used memory list.\n\t*/\n\tMemNode_Insert(pool, FALSE, node, size, id, FALSE);\n\n\t/*\n\t**\tReflect the change to the total free count.\n\t*/\n\tpool->FreeMem -= size;\n\n\t/*\n\t**\tReturn a pointer to the block of allocated memory just past\n\t**\tthe header.\n\t*/\n\n#if DEBUG_FILL\n\tmemset(node + 1, id, (size-1) << 4);\n#endif\n\treturn((void *) (node + 1));\n}\t\n\n\n/***************************************************************************\n * Mem_Free -- Free a block of memory from system.                         *\n *                                                                         *\n *    This routine will free a block of memory from the special memory     *\n *    buffer.                                                              *\n *                                                                         *\n * INPUT:   poolptr\t-- Pointer to the memory pool base address.           *\n *                                                                         *\n *          buffer   -- Pointer to memory block to free.                   *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Was the deallocation successful?                   *\n *                                                                         *\n * WARNINGS:   Be sure to only pass in to this routine a buffer that was   *\n *             returned from Mem_Alloc().                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nint Mem_Free(void *poolptr, void *buffer)\n{\n\tMemPool_Type\t*pool;\t\t\t// pointer to structure.\n\tMemChain_Type\t*node;\t\t\t// Copy of current memory node.\n\tunsigned int\tsize;\t\t\t\t// Size of the block being freed.\n\n\t/*\n\t**\tOne can't free what isn't there.\n\t*/\n\tif (!buffer || !poolptr) {\n\t\treturn(FALSE);\n\t}\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tThe node pointer is actually back a bit from the \"normal\" pointer.\n\t*/\n\tnode = (MemChain_Type *) buffer;\n\tnode--;\n\n\t/*\n\t**\tGet pointer to actual allocated node and unlink it from the used\n\t**\tmemory chain.\n\t*/\t\n\tsize = node->Size;\n\tMemNode_Unlink(pool, FALSE, node);\n\tMemNode_Insert(pool, TRUE, node, size, -1, TRUE);\n\n\t/*\n\t**\tReflect the new free memory into the total memory count.\n\t*/\n\tpool->FreeMem += size;\n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * Mem_Reference -- Updates the reference time for the specified memory blo*\n *                                                                         *\n *    This routine is used to update the memory reference time for the     *\n *    specified memory node.  Typically, this is called every time a       *\n *    memory block is used in order to make sure the memory block time     *\n *    tracking (Last Recently Used) system works properly.                 *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   The node pointer must be valid.  For maximum safety this    *\n *             routine should be called right after Mem_Find().            *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid Mem_Reference(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node;\n\tnodeptr--;\n\n\tnodeptr->Time = (unsigned short)(TickCount.Time() >> 4);\n\n}\n\n\n/***************************************************************************\n * MEM_LOCK_BLOCK -- Locks a block so that it cannot be moved in cleanup.  *\n * \tBy marking a memory block in use, the memory system will never return*\n *    it as the oldest memory block.  It also makes it so that the block\t*\n *    will never be moved during a Cleanup process.                        *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:  \tIf one or more blocks are locked in a heap, Mem_Avail might *\n *             not equal Mem_Largest_Avail after a call to Mem_Cleanup.    *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid Mem_Lock_Block(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node;\n\tnodeptr--;\n\tnodeptr->Time = MEM_BLOCK_LOCKED;\n}\n\n\n/***************************************************************************\n * MEM_IN_USE -- Makes it so a block will never be returned as oldest\t\t*\n * \tBy marking a memory block in use, the memory system will never return*\n *    it as the oldest memory block.  It still can be moved in the Cleanup *\n *    code.                                                                *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS: Mem_Find_Oldest() will return NULL if only IN_USE blocks are  *\n *           in memory.                                                    *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid Mem_In_Use(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node - 1;\n\tnodeptr->Time = MEM_BLOCK_IN_USE;\n}\n\n\n/***************************************************************************\n * Mem_Find -- Returns with pointer to specified memory block.             *\n *                                                                         *\n *    Use this routine to convert a memory ID value into an actual memory  *\n *    pointer.  It sweeps through all of the 'cached' memory blocks and    *\n *    returns with the matching block pointer.                             *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache block.                 *\n *                                                                         *\n *          id       -- The ID of the block desired.                       *\n *                                                                         *\n * OUTPUT:  Returns with the pointer to the memory block.  If NULL is      *\n *          returned then the desired block is not in the memory cache.    *\n *                                                                         *\n * WARNINGS:   This routine may return NULL if the memory block is not     *\n *             present in the cache.                                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Find(void *poolptr, unsigned long id)\n{\n\tMemPool_Type\t*pool;\t\t\t// pointer to structure.\n\tMemChain_Type\t*node;\t\t\t// Working node structure.\n\n\tif (!poolptr) return(NULL);\n\n\tpool = (MemPool_Type *) poolptr;\n\t\t\n\t/* \n\t** Cannot free a node that is not on the UsedChain list.\n\t*/\n\tif (!pool->UsedChain) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tSweep through entire allocation chain to find\n\t**\tthe one with the matching ID.\n\t*/\n\tnode = pool->UsedChain;\n\twhile (node) {\n\t\t\n\t\tif (node->ID == id) {\n\t\t\treturn(node + 1);\n\t\t}\n\t\tnode = node->Next;\n\t}\n\treturn(NULL);\n}\n\n\n/***************************************************************************\n * MEM_GET_ID -- Returns ID of node.                                       *\n *                                                                         *\n * INPUT:  void *node - pointer to node. \t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT: The ID of the node that was supplied by user during Mem_Alloc().*\n *                                                                         *\n * WARNINGS: pointer to node must be one that Mem_Alloc or                \t*\n *           Mem_Find returned.                                           **\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nunsigned long Mem_Get_ID(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return (0L);\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node - 1;\n\treturn (nodeptr->ID);\n}\n\n\n/***************************************************************************\n * Mem_Find_Oldest -- Returns with the memory block with the oldest time st*\n *                                                                         *\n *    Use this routine to find the memory block with the oldest time stamp *\n *    value.  Typically, this is used when freeing memory blocks in the    *\n *    cache in order to make room for a new memory block.                  *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns with the pointer to the oldest memory block.  If NULL  *\n *          is returned, then the memory cache is empty.                   *\n *                                                                         *\n * WARNINGS:   This routine could return NULL.                             *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *   04/15/1994 SKB : Handle time wrap, locked blocks, and no_refenece blocks*\n *=========================================================================*/\nvoid *Mem_Find_Oldest(void *poolptr)\n{\n\tMemChain_Type\t*node; \t\t\t\t// Working node pointer.\n\tMemChain_Type\t*oldnode;\t\t\t// Pointer to oldest block.\n\tunsigned int\toldtime;\t\t\t\t// Time of oldest block.\n\tunsigned int\tbasetime;\t\t\t// Time to mark our base time with.\n\tunsigned int\ttime;\t\t\t\t\t// basetime + time of node.\n\n\tif (!poolptr) return(NULL);\n\n\t/*\n\t**\tSweep through entire allocation chain to find\n\t**\tthe oldest referenced memory block.\n\t*/\n\toldnode = NULL;\n\toldtime = 0;\n\tnode = ((MemPool_Type*) poolptr)->UsedChain;\n\n  basetime = (unsigned int)(TickCount.Time() >> 4);\n\n\twhile (node) {\n\n\t\t/*\n\t\t** Don't allow MEM_BLOCK_IN_USE or MEM_BLOCK_LOCKED to be returned.\n\t\t*/\n\t\tif (node->Time > MEM_BLOCK_LOCKED) {\n\n\t\t\t/*\n\t\t\t** Adjust time for wrap around (after about 5 hrs).\n\t\t\t** times less then the base time will wrap up high while\n\t\t\t** and times greater then base time will then be lower since\n\t\t\t** any time greater has been on the thing a long time.\n\t\t\t*/\n\t\t\ttime = node->Time - basetime ;\n\n\t\t\tif (time < oldtime || !oldnode) {\n\t\t\t\toldtime = time;\n\t\t\t\toldnode = node;\n\t\t\t}\n\t\t}\n\t\tnode = node->Next;\n\t}\n\n\t/*\n\t**\tReturn with the value that matches the pointer that\n\t**\twas allocated by the system previously.\n\t*/\n\tif (oldnode) {\n\t\toldnode++;\n\t}\n\treturn(oldnode);\n}\n\n\n/***************************************************************************\n * Mem_Free_Oldest -- Find and free the oldest memory block.               *\n *                                                                         *\n *    This routine is used to free the oldest memory block in the memory   *\n *    cache.  This routine is typcially used in order to create more room  *\n *    in the cache for a new allocation.                                   *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns with the node that it freed.  Although this node is    *\n *          is no longer valid, it may be used to mark that pointer as     *\n *          invalid in the main code.                                      *\n *                                                                         *\n * WARNINGS:   If this routine returns NULL, then no memory was freed.     *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Free_Oldest(void *poolptr)\n{\n\tMemChain_Type\t*node;\t\t// Copy of pointer to oldest node.\n\n\tif (!poolptr) return(NULL);\n\tnode = (MemChain *) Mem_Find_Oldest(poolptr);\n\tif (Mem_Free(poolptr, node)) {\n\t\treturn(node);\n\t}\n\treturn(NULL);\n}\n\n/***************************************************************************\n * MEM_POOL_SIZE -- Returns total amount of memory in pool.                *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  long total size of pool. i.e. largest possible allocation if   *\n *          no memory was allocated.                                       *\n *                                                                         *\n * WARNINGS: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Mem_Pool_Size(void *poolptr)\n{\n\tMemPool_Type\t*pool;\t\t\t// Memory pool control structure.\n\tlong\t\t\t\tmemtotal;\t\t// Total amount of memory free.\n\n\tif (!poolptr) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\tmemtotal = ((long)pool->TotalMem) << 4;\n\tmemtotal -= sizeof(MemChain_Type);\n\tmemtotal = MAX(memtotal, (long)0);\n\treturn(memtotal);\n}\n\n/***************************************************************************\n * Mem_Avail -- Returns the amount of free memory available in the cache.  *\n *                                                                         *\n *    This routine examines the memory cache and returns the amount of     *\n *    free memory available.  This memory total MAY be fragmented but      *\n *    after Mem_Cleanup() is called, an allocation of the amount returned  *\n *    by this function is guaranteed.                                      *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns the largest allocation possible from the memory cache. *\n *                                                                         *\n * WARNINGS:   The value returned may represent the FRAGMENTED total       *\n *             amount of memory free in the cache.                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nlong Mem_Avail(void *poolptr)\n{\n\tMemPool_Type\t*pool;\t\t// Memory pool control structure.\n\tlong\t\t\t\tmemtotal;\t// Total amount of memory free.\n\n\tif (!poolptr) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\tmemtotal = ((long)pool->FreeMem) << 4;\n\tmemtotal -= sizeof(MemChain_Type);\n\t//memtotal -= sizeof(MemChain_Type) + 15;\n\tmemtotal = MAX(memtotal, (long)0);\n\treturn(memtotal);\n}\n\n\n/***************************************************************************\n * MEM_LARGEST_AVAIL -- Largest free block available.                      *\n * \tThis routine examines the free node list to find the largest block   *\n *\t\tavailable.  User can Mem_Alloc() this return size successfully.      *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns largest allocation currently possible from the cache. \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Mem_Largest_Avail(void *poolptr)\n{\n\tMemChain_Type\t*node;\t\t\t// Pointer to current memory node.\n\tunsigned int\tsize;\n\tlong\t\t\t\ttruesize;\t\n\n\t/*\n\t** Make sure that it is a buffer.\n\t*/\n\tif (!poolptr) return(NULL);\n\n\t/*\n\t** Go through the entire free chain looking for the largest block.\n\t*/\n\tnode = ((MemPool_Type *)poolptr)->FreeChain;\n\tsize = 0;\n\twhile (node) {\n\n\t\t/*\n\t\t**\tFetch free memory chunk block and see if it is big enough.\n\t\t*/\n\t\tif (node->Size >= size) {\n\t\t\tsize = node->Size;\n\t\t}\n\t\tnode = node->Next;\n\t}\n\n\ttruesize = (long)size << 4;\n\ttruesize -= sizeof(MemChain_Type);\n\ttruesize = MAX(truesize, 0L);\n\treturn (truesize);\n}\n\n\n/***************************************************************************\n * Mem_Cleanup -- Performs a garbage collection on the memory cache.       *\n *                                                                         *\n *    This routine is used to coalesce all adjacent free blocks of         *\n *    memory in the specified cache.  As a result, all previous pointers   *\n *    provided by Mem_Find() are invalidated.  This routine consumes a     *\n *    fair amount of time and should be called as infrequently as          *\n *    possible.                                                            *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine takes a significant amount of time!            *\n *             If there are locked block in memory, the pool may still     *\n *             be fragmented.                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Updated for low memory caches.                       *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid Mem_Cleanup(void *poolptr)\n{\n\tMemPool_Type\t*pool;  \t// Memory pool control structure.\n\tMemChain_Type\t*free,\t// Pointer to first free area.\n\t\t\t\t\t\t*cur;\t\t// Pointer to first used block that is after free.\n\tunsigned long\tsize;\n\tunsigned long\tfreesize;// Size of free heap at the end of the block.\n\n\tif (!poolptr) return;\n\n\t/*\n\t**\tFetch working copy of pool control structure.\n\t*/\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tBasic parameter and condition legality checks.  If the memory pool\n\t**\thas no free space, no free blocks, or no allocated blocks, then \n\t**\tmemory cleanup is unnecessary -- just exit.\n\t*/\n\tif (!pool->FreeMem || !pool->FreeChain || !pool->UsedChain) return;\n\n\tfreesize = pool->FreeMem;\n\tfree = pool->FreeChain;\n\tpool->FreeChain = NULL;\n\tcur = pool->UsedChain;\n\twhile (TRUE) {\n\n\t\t/*\n\t\t** Setup pointers so that free points to the first free block and cur\n\t\t** points to the next used block after the free block.\n\t\t*/\n\t\twhile (cur < free && cur) {\n\t \t\tcur = cur->Next;\n\t\t}\n\n\t\t// All used blocks are at the front of the free.  We are done.\n\t\tif (!cur) {\n\t \t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t** Do not allow a locked block to be moved.\n\t\t*/\n\t\tif (cur->Time == MEM_BLOCK_LOCKED) {\n\t\t\t/* \n\t\t\t** Figure the size of the new free block that we are creating.\n\t\t\t** Subtract off the total block size.\n\t\t\t** Add the node to the free list.\n\t\t\t*/\n\t\t\tsize = (char *) cur - (char  *) free;\n\t\t\tsize >>= 4;\n\t\t \tfreesize -= size;\n\t\t\tMemNode_Insert(pool, TRUE, free, (unsigned int) size, -1, FALSE);\n\n\t\t\t/*\n\t\t\t** Time to find a new free position to start working from.\n\t\t\t** Cur will be in the position just following.\n\t\t\t*/\n\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, (unsigned long)cur->Size << 4);\n\t\t\tcur = cur->Next;\n\t\t\twhile (free == cur) {\n\t\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, (unsigned long)cur->Size << 4);\n\t\t\t\tcur = cur->Next;\n\t\t\t}\n\n\t\t\t// All used blocks are at the front of the free.  We are done.\n\t\t\tif (!cur) {\n\t\t\t \tbreak;\n\t\t\t}\n\t\t} else {\n\n\t\t\t// Copy the block up.\n\t\t\tsize = (unsigned long)cur->Size << 4;\n\t\t\tMem_Copy(cur, free, size);\n\t\t\tcur = free;\n\n\t\t\t// Change pointers of surrounding blocks.\n\t\t\tif (cur->Next) {\n\t\t \t\tcur->Next->Prev = cur;\n\t\t\t}\n\t\t\tif (cur->Prev) {\n\t\t \t\tcur->Prev->Next = cur;\n\t\t\t} else {\n\t\t \t\tpool->UsedChain = cur;\n\t\t\t}\n\n\t\t\t// Change to next new free area.\n\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, size);\n\t\t}\n\t}\n\n\t/*\n\t**\tNow build the single free chunk.\n\t*/\n\tMemNode_Insert(pool, TRUE, free, freesize, -1, FALSE);\n}\n\n\n/***************************************************************************\n * MemNode_Unlink -- Unlinks a node from the cache.                        *\n *                                                                         *\n *    A private routine the actually unlinks a memory block from the       *\n *    memory cache.  It doesn't perform a complete update of the memory    *\n *    cache.                                                               *\n *                                                                         *\n * INPUT:   pool     -- Pointer to the memory cache header (copy in real   *\n *                      memory).                                           *\n *                                                                         *\n *          freechain-- Is the block part of the free memory chain?        *\n *                                                                         *\n *          node     -- Pointer to the node that will be unlinked.         *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine doesn't update memory totals.  It is a support *\n *             function.                                                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nPRIVATE void MemNode_Unlink(MemPool_Type *pool, int freechain, MemChain_Type *node)\n{\n\tMemChain_Type\t*other; \t\t// Copy of node data to unlink.\n\tMemChain_Type\t**chain;\t\t// A pointer to one of the chains pointer.\n\n\t/*\n\t**\tCheck for parameter validity.\n\t*/\n\tif (!pool || !node) return;\n\t\n\t/*\n\t**\tSetup working pointer for the particular chain desired.\n\t*/\t\n\tif (freechain) {\n\t\tchain = &pool->FreeChain;\n\t} else {\n\t\tchain = &pool->UsedChain;\n\t}\n\t\n\t/*\n\t**\tMake adjustments to the previous node.  If the pointer\n\t**\tto the previous node is NULL then this indicates the\n\t**\tfirst node in the list and thus the chain pointer needs\n\t**\tto be updated instead.\n\t*/\n\tif (node->Prev) {\n\t\tother = node->Prev;\n\t\tother->Next = node->Next;\n\t} else {\n\t\t*chain = node->Next;\n\t}\n\n\tif (node->Next) {\n\t\tother = node->Next;\n\t\tother->Prev = node->Prev;\n\t}\n}\n\n\n/***************************************************************************\n * MemNode_Insert -- Inserts a node into a cache chain.                    *\n *                                                                         *\n *    This routine is used to add a node to a cache chain.  Since nodes    *\n *    do not contain double links, they must be placed in sequence.        *\n *                                                                         *\n * INPUT:   pool     -- Pointer to memory pool (must be in real memory).   *\n *                                                                         *\n *          freechain-- Is the node to be inserted into the free chain?    *\n *                                                                         *\n *          node     -- Pointer to the node to insert.                     *\n *                                                                         *\n *          size     -- Size of the memory block (in paragraphs).          *\n *                                                                         *\n *          id       -- The ID number to associate with this block.        *\n *                                                                         *\n *          merge    -- Merge inserted block with adjacent blocks.         *\n *                                                                         *\n * OUTPUT:  return                                                         *\n *                                                                         *\n * WARNINGS:   This is a support routine.                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void MemNode_Insert(MemPool_Type *pool, int freechain, MemChain_Type *node, unsigned int size, unsigned long id, int merge)\n{\n\tMemChain_Type \t**chain;\t\t\t// Pointer to chain that will be linked.\n\tMemChain_Type \t*prev,\t\t\t// Successor node pointer.\n\t\t\t\t\t\t*next;\t\t\t// Predecessor node pointer.\n\tint\t\t\t\tdoit=TRUE;\t\t// Link the node into the list.\n\n\n\t/*\n\t**\tDetermine if the parameters are valid.\n\t*/\n\tif (!pool || !node || !size) return;\n\n\t/*\n\t**\tSetup working pointer for the particular chain desired.\n\t*/\t\n\tif (freechain) {\n\t\tchain = &pool->FreeChain;\n\t} else {\n\t\tchain = &pool->UsedChain;\n\t}\n\n\t/*\n\t**\tHandle the \"no node in list\" condition (easiest).\n\t*/\n\tif (!*chain) {\n\t\tnode->Next = NULL;\n\t\tnode->Prev = NULL;\n\t\tnode->Size = size;\n\t\tnode->Time = (unsigned short)(TickCount.Time() >> 4);\n\t\tnode->ID = id;\n\t\t*chain = node;\n\t\treturn;\n\t}\n\n\t/*\n\t**\tSweep through the memory chain looking for a likely spot\n\t**\tto insert the new node.  It will stop with \"next\" pointing\n\t**\tto the node to come after the block to be inserted and \"prev\"\n\t** will point to the node right before.\n\t*/\n\tprev = NULL;\n\tnext = *chain;\n\twhile (next && (next < node)) {\n\n\t\t/*\n\t\t**\tMove up the memory chain.\n\t\t*/\n\t\tprev = next;\n\t\tnext = next->Next;\n\t}\n\n\t/*\n\t**\tCoallescing of adjacent blocks (if requested).\n\t*/\n\tif (merge) {\n\t\t\n\t\t/*\n\t\t**\tIf the previous block is touching the block to insert\n\t\t**\tthen merely adjust the size of the previous block and\n\t\t**\tthat is all that is necessary.\n\t\t*/\n\t\tif (prev) {\n\t\t\tif (((char *)prev + ((long)prev->Size << 4)) == ((char *) node)) {\n\t\t\t\tprev->Size += size;\n\t\t\t\tsize = prev->Size;\n\t\t\t\tnode = prev;\n\t\t\t\tprev = prev->Prev;\n\t\t\t\tdoit = FALSE;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf the following block is touching the block to insert\n\t\t**\tthen remove the following block and increase the size of\n\t\t**\tthe original insertion block by the size of the other\n\t\t**\tblock.\n\t\t*/\n\t\tif (next) {\n\t\t\tif (((char *)node + ((long)size << 4)) == (char *)next) {\n\t\t\t\t\n\t\t\t\tif (!doit) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the node was already merged with the previous block\n\t\t\t\t\t**\tthen merely increase the previous block's size\n\t\t\t\t\t**\tand adjust it's next pointer appropriately.\n\t\t\t\t\t*/\n\t\t\t\t\tnode->Size += next->Size;\n\t\t\t\t\tnode->Next = next->Next;\n\t\t\t\t\tnext = next->Next;\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIncrease the size of the current block and adjust\n\t\t\t\t\t**\tthe \"next\" pointer so that it gets fixed up\n\t\t\t\t\t**\taccordingly.\n\t\t\t\t\t*/\n\t\t\t\t\tsize += next->Size;\n\t\t\t\t\tnext = next->Next;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n#if DEBUG_FILL\n\tif (doit) {\n\t\tmemset(node + 1, 0xFF, (size - 1) << 4);\n\t} else {\n\t\tmemset(node + 1, 0xFF, (node->Size - 1) << 4);\n\t}\n#endif\n\n\t/*\n\t**\tFixup the node pointers.\n\t*/\n\tif (prev) {\n\t\tprev->Next = node;\n\t}else{\n\t\t*chain = node;\n\t}\n\n\tif (next) {\n\t \tnext->Prev = node;\n\t}\n\n\tif (doit) {\n\t\tnode->Prev = prev;\n\t\tnode->Next = next;\n\t\tnode->Size = size;\n\t\tnode->Time = (unsigned short)(TickCount.Time() >> 4);\n\t\tnode->ID = id;\n\t}\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "WWFLAT32/MEM/MEM.CPP.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : MEM.C                                    *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : March 31, 1993                           *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Mem_Free -- Free a block of memory from system.                       *\n *   Mem_Alloc -- Allocate a block of memory from the special memory pool. *\n *   Mem_Init -- Initialize the private memory allocation pool.            *\n *   Mem_Reference -- Updates the reference time for the specified memory blo*\n *   Mem_Find -- Returns with pointer to specified memory block.           *\n *   Mem_Find_Oldest -- Returns with the memory block with the oldest time st*\n *   Mem_Free_Oldest -- Find and free the oldest memory block.             *\n *   Mem_Avail -- Returns the amount of free memory available in the cache.*\n *   Mem_Cleanup -- Performes a garbage collection on the memory cache.    *\n *   MemNode_Unlink -- Unlinks a node from the cache.                      *\n *   MemNode_Insert -- Inserts a node into a cache chain.                  *\n *   Mem_Largest_Avail -- Largest free block available.                    *\n *   Mem_Lock_Block -- Locks a block so that it cannot be moved in cleanup.*\n *   Mem_In_Use -- Makes it so a block will never be returned as oldest*\n *   Mem_Pool_Size -- Returns total amount of memory in pool.              *\n *   Mem_Get_ID -- Returns ID of node.                                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"wwmem.h\"\n#include <timer.h>\n\n#include\t<stddef.h>\n#include\t<mem.h>\n\n#define DEBUG_FILL FALSE\n\n////////////////////////////////////////////////////////////////////////////\n\n\n\n/*******************************************************************************\n** A allocated block may have one of three meanings in the Time field.  The first\n** is the time stamp of the last time it was referenced.  The other two values\n** are defined below.  MEM_BLOCK_IN_USE means that it will never be returned as the\n** oldest since there is no valid time stamp.  LOCKED_BLOCK has the same meaning as\n** MEM_BLOCK_IN_USE with the added feature that the block will not be moved in a \n** Mem_Cleanup().  Therefore, there may be some fragmentation after the cleanup\n** if any blocks are LOCKED.  It would be good practice to seldomly lock blocks,\n** for instance, only when a sample is being played.\n** WARNING: If these values change to anything else, logic will need to be changed\n**          in Mem_Find_Oldest since it relies on these being small values.\n*/\n#define MEM_BLOCK_IN_USE\t0x00\n#define MEM_BLOCK_LOCKED\t0x01\n\n/*\n**\tEach block of memory in the pool is headed by this structure.\n*/\ntypedef struct MemChain {\n\tstruct MemChain\t*Next;\t// Pointer to next memory chain node.\n\tstruct MemChain\t*Prev;\t// Pointer to previous memory chain node.\n\tunsigned long\t\tID;\t\t// ID number of block.\n\tunsigned short\t\tTime;\t\t// TickCount of latest reference.\n\tunsigned short\t\tSize;\t\t// Size of memory block (in paragraphs).\n} MemChain_Type;\n\n\n/*\n**\tHolding tank memory management data.\n*/\ntypedef struct MemPool {\n\tMemChain_Type\t*FreeChain;\t// Pointer to first node in free chain.\n\tMemChain_Type\t*UsedChain;\t// Pointer to first node in used chain.\n\tunsigned short\tFreeMem;\t\t// Current amount of free ram (in paragraphs).\n\tunsigned short\tTotalMem;\t// Total quantity of memory.\n\tlong\t\t\t\tpad2;\n} MemPool_Type;\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE void MemNode_Unlink(MemPool_Type *pool, int freechain, MemChain_Type *node);\nPRIVATE void MemNode_Insert(MemPool_Type *pool, int freechain, MemChain_Type *node, unsigned int size, unsigned long id, int merge);\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * Mem_Init -- Initialize the private memory allocation pool.              *\n *                                                                         *\n *    This routine is used to initialize the private memory allocation     *\n *    pool.                                                                *\n *                                                                         *\n * INPUT:   buffer   -- Pointer to the buffer that is the allocation pool. *\n *                                                                         *\n *          size     -- Size of the buffer in bytes.                       *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Was it initialized successfully?                   *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nint Mem_Init(void *buffer, long size)\n{\n\tMemChain_Type\t*mem;\t\t\t// Working memory chain node.\n\tMemPool_Type\t*pool;\t\t// Memory pool control structure.\n\n\t/*\n\t**\tThe buffer is rounded down to the nearest paragraph.\n\t*/\n\tsize = size & 0xFFFFFFF0L;\n\n\tif (!buffer || !size) return(FALSE);\n\n\t/*\n\t**\tInitialize the pool control structure.\n\t*/\n\tpool = (MemPool_Type *)buffer;\n\tpool->FreeMem = (size - sizeof(MemPool_Type)) >> 4;\n\tpool->UsedChain = NULL;\n\tpool->TotalMem = pool->FreeMem;\n\tmem = pool->FreeChain = (MemChain_Type *) (pool + 1);\n\n\t/*\n\t**\tInitialize the free memory chain.\n\t*/\n\tmem->Next = NULL;\n\tmem->Prev = NULL;\n\tmem->Size = pool->FreeMem;\n\tmem->ID = -1;\n\tmem->Time = 0;\n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * Mem_Alloc -- Allocate a block of memory from the special memory pool.   *\n *                                                                         *\n *    This routine will allocate a block of memory from the special        *\n *    memory allocation pool.                                              *\n *                                                                         *\n * INPUT:   poolptr\t-- Pointer to the memory pool base address.           *\n *                                                                         *\n *          size  -- The size of the memory block to allocate.             *\n *                                                                         *\n *          id    -- ID number to give this memory block.                  *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the allocated block.  If there was   *\n *          insufficient room, then NULL is returned.                      *\n *                                                                         *\n * WARNINGS:   Be sure to check for the NULL return case.                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Alloc(void *poolptr, long lsize, unsigned long id)\n{\n\tMemPool_Type\t*pool;\n\tMemChain_Type\t*node;\t\t\t// Pointer to current memory node.\n\tunsigned int\tremainder=0;\t// Remaining bytes that are still free.\n\tint\t\t\t\tfound;\n\tint\t\t\t\tsize;\t\t\t\t// Paragraph size of allocation.\n\n\n\t/*\n\t**\tIf there is no free memory then the allocation will\n\t**\talways fail.\n\t*/\n\tif (!poolptr || !lsize) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\t\t\n\t/*\n\t**\tAllocations are forced to be paragraph sized.\n\t*/\n\tlsize += sizeof(MemChain_Type);\t// Account for header.\n\tlsize = (lsize + 0x0FL) & 0xFFFFFFF0L;\n\tsize = (int)(lsize >> 4);\n\n\t/*\n\t**\tIf the total free is less than the size of the desired allocation,\n\t**\tthen we KNOW that an allocation will fail -- just return.\n\t*/\n\tif (pool->TotalMem < size) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tWalk down free chain looking for the first block that will\n\t**\taccomodate the allocation.\n\t*/\n\tnode = pool->FreeChain;\n\tfound = FALSE;\n\twhile (!found && node) {\n\n\t\t/*\n\t\t**\tFetch free memory chunk block and see if it is big enough.\n\t\t*/\n\t\tif (node->Size >= size) {\n\t\t\tfound = TRUE;\n\t\t\tbreak;\n\t\t}\n\t\tnode = node->Next;\n\t}\n\tif (!found) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tDetermine if this allocation would split the block.\n\t*/\n\tremainder = node->Size - size;\n\n\t/*\n\t**\tIf only a very small free chunk would remain, just tack it on\n\t**\tto the current allocation.\n\t*/\n\tif (remainder <= 2) {\n\t\tremainder = 0;\n\t\tsize = node->Size;\n\t}\n\n\t/*\n\t**\tRemove the primary block from the free memory list.\n\t*/\n\tMemNode_Unlink(pool, TRUE, node);\n\n\t/*\n\t**\tIf a smaller block remains, then link it back into\n\t**\tthe free memory list.\n\t*/\n\tif (remainder) {\n\t\tMemNode_Insert(pool, TRUE, (MemChain_Type *)Add_Long_To_Pointer(node, (long)size << 4), remainder, -1, FALSE);\n\t}\n\n\t/*\n\t**\tLink in the allocated node into the used memory list.\n\t*/\n\tMemNode_Insert(pool, FALSE, node, size, id, FALSE);\n\n\t/*\n\t**\tReflect the change to the total free count.\n\t*/\n\tpool->FreeMem -= size;\n\n\t/*\n\t**\tReturn a pointer to the block of allocated memory just past\n\t**\tthe header.\n\t*/\n\n#if DEBUG_FILL\n\tmemset(node + 1, id, (size-1) << 4);\n#endif\n\treturn((void *) (node + 1));\n}\t\n\n\n/***************************************************************************\n * Mem_Free -- Free a block of memory from system.                         *\n *                                                                         *\n *    This routine will free a block of memory from the special memory     *\n *    buffer.                                                              *\n *                                                                         *\n * INPUT:   poolptr\t-- Pointer to the memory pool base address.           *\n *                                                                         *\n *          buffer   -- Pointer to memory block to free.                   *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Was the deallocation successful?                   *\n *                                                                         *\n * WARNINGS:   Be sure to only pass in to this routine a buffer that was   *\n *             returned from Mem_Alloc().                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nint Mem_Free(void *poolptr, void *buffer)\n{\n\tMemPool_Type\t*pool;\t\t\t// pointer to structure.\n\tMemChain_Type\t*node;\t\t\t// Copy of current memory node.\n\tunsigned int\tsize;\t\t\t\t// Size of the block being freed.\n\n\t/*\n\t**\tOne can't free what isn't there.\n\t*/\n\tif (!buffer || !poolptr) {\n\t\treturn(FALSE);\n\t}\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tThe node pointer is actually back a bit from the \"normal\" pointer.\n\t*/\n\tnode = (MemChain_Type *) buffer;\n\tnode--;\n\n\t/*\n\t**\tGet pointer to actual allocated node and unlink it from the used\n\t**\tmemory chain.\n\t*/\t\n\tsize = node->Size;\n\tMemNode_Unlink(pool, FALSE, node);\n\tMemNode_Insert(pool, TRUE, node, size, -1, TRUE);\n\n\t/*\n\t**\tReflect the new free memory into the total memory count.\n\t*/\n\tpool->FreeMem += size;\n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * Mem_Reference -- Updates the reference time for the specified memory blo*\n *                                                                         *\n *    This routine is used to update the memory reference time for the     *\n *    specified memory node.  Typically, this is called every time a       *\n *    memory block is used in order to make sure the memory block time     *\n *    tracking (Last Recently Used) system works properly.                 *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   The node pointer must be valid.  For maximum safety this    *\n *             routine should be called right after Mem_Find().            *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid Mem_Reference(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node;\n\tnodeptr--;\n\n\tnodeptr->Time = (unsigned short)(TickCount.Time() >> 4);\n\n}\n\n\n/***************************************************************************\n * MEM_LOCK_BLOCK -- Locks a block so that it cannot be moved in cleanup.  *\n * \tBy marking a memory block in use, the memory system will never return*\n *    it as the oldest memory block.  It also makes it so that the block\t*\n *    will never be moved during a Cleanup process.                        *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:  \tIf one or more blocks are locked in a heap, Mem_Avail might *\n *             not equal Mem_Largest_Avail after a call to Mem_Cleanup.    *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid Mem_Lock_Block(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node;\n\tnodeptr--;\n\tnodeptr->Time = MEM_BLOCK_LOCKED;\n}\n\n\n/***************************************************************************\n * MEM_IN_USE -- Makes it so a block will never be returned as oldest\t\t*\n * \tBy marking a memory block in use, the memory system will never return*\n *    it as the oldest memory block.  It still can be moved in the Cleanup *\n *    code.                                                                *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS: Mem_Find_Oldest() will return NULL if only IN_USE blocks are  *\n *           in memory.                                                    *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid Mem_In_Use(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node - 1;\n\tnodeptr->Time = MEM_BLOCK_IN_USE;\n}\n\n\n/***************************************************************************\n * Mem_Find -- Returns with pointer to specified memory block.             *\n *                                                                         *\n *    Use this routine to convert a memory ID value into an actual memory  *\n *    pointer.  It sweeps through all of the 'cached' memory blocks and    *\n *    returns with the matching block pointer.                             *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache block.                 *\n *                                                                         *\n *          id       -- The ID of the block desired.                       *\n *                                                                         *\n * OUTPUT:  Returns with the pointer to the memory block.  If NULL is      *\n *          returned then the desired block is not in the memory cache.    *\n *                                                                         *\n * WARNINGS:   This routine may return NULL if the memory block is not     *\n *             present in the cache.                                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Find(void *poolptr, unsigned long id)\n{\n\tMemPool_Type\t*pool;\t\t\t// pointer to structure.\n\tMemChain_Type\t*node;\t\t\t// Working node structure.\n\n\tif (!poolptr) return(NULL);\n\n\tpool = (MemPool_Type *) poolptr;\n\t\t\n\t/* \n\t** Cannot free a node that is not on the UsedChain list.\n\t*/\n\tif (!pool->UsedChain) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tSweep through entire allocation chain to find\n\t**\tthe one with the matching ID.\n\t*/\n\tnode = pool->UsedChain;\n\twhile (node) {\n\t\t\n\t\tif (node->ID == id) {\n\t\t\treturn(node + 1);\n\t\t}\n\t\tnode = node->Next;\n\t}\n\treturn(NULL);\n}\n\n\n/***************************************************************************\n * MEM_GET_ID -- Returns ID of node.                                       *\n *                                                                         *\n * INPUT:  void *node - pointer to node. \t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT: The ID of the node that was supplied by user during Mem_Alloc().*\n *                                                                         *\n * WARNINGS: pointer to node must be one that Mem_Alloc or                \t*\n *           Mem_Find returned.                                           **\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nunsigned long Mem_Get_ID(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return (0L);\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node - 1;\n\treturn (nodeptr->ID);\n}\n\n\n/***************************************************************************\n * Mem_Find_Oldest -- Returns with the memory block with the oldest time st*\n *                                                                         *\n *    Use this routine to find the memory block with the oldest time stamp *\n *    value.  Typically, this is used when freeing memory blocks in the    *\n *    cache in order to make room for a new memory block.                  *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns with the pointer to the oldest memory block.  If NULL  *\n *          is returned, then the memory cache is empty.                   *\n *                                                                         *\n * WARNINGS:   This routine could return NULL.                             *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *   04/15/1994 SKB : Handle time wrap, locked blocks, and no_refenece blocks*\n *=========================================================================*/\nvoid *Mem_Find_Oldest(void *poolptr)\n{\n\tMemChain_Type\t*node; \t\t\t\t// Working node pointer.\n\tMemChain_Type\t*oldnode;\t\t\t// Pointer to oldest block.\n\tunsigned int\toldtime;\t\t\t\t// Time of oldest block.\n\tunsigned int\tbasetime;\t\t\t// Time to mark our base time with.\n\tunsigned int\ttime;\t\t\t\t\t// basetime + time of node.\n\n\tif (!poolptr) return(NULL);\n\n\t/*\n\t**\tSweep through entire allocation chain to find\n\t**\tthe oldest referenced memory block.\n\t*/\n\toldnode = NULL;\n\toldtime = 0;\n\tnode = ((MemPool_Type*) poolptr)->UsedChain;\n\n  basetime = (unsigned int)(TickCount.Time() >> 4);\n\n\twhile (node) {\n\n\t\t/*\n\t\t** Don't allow MEM_BLOCK_IN_USE or MEM_BLOCK_LOCKED to be returned.\n\t\t*/\n\t\tif (node->Time > MEM_BLOCK_LOCKED) {\n\n\t\t\t/*\n\t\t\t** Adjust time for wrap around (after about 5 hrs).\n\t\t\t** times less then the base time will wrap up high while\n\t\t\t** and times greater then base time will then be lower since\n\t\t\t** any time greater has been on the thing a long time.\n\t\t\t*/\n\t\t\ttime = node->Time - basetime ;\n\n\t\t\tif (time < oldtime || !oldnode) {\n\t\t\t\toldtime = time;\n\t\t\t\toldnode = node;\n\t\t\t}\n\t\t}\n\t\tnode = node->Next;\n\t}\n\n\t/*\n\t**\tReturn with the value that matches the pointer that\n\t**\twas allocated by the system previously.\n\t*/\n\tif (oldnode) {\n\t\toldnode++;\n\t}\n\treturn(oldnode);\n}\n\n\n/***************************************************************************\n * Mem_Free_Oldest -- Find and free the oldest memory block.               *\n *                                                                         *\n *    This routine is used to free the oldest memory block in the memory   *\n *    cache.  This routine is typcially used in order to create more room  *\n *    in the cache for a new allocation.                                   *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns with the node that it freed.  Although this node is    *\n *          is no longer valid, it may be used to mark that pointer as     *\n *          invalid in the main code.                                      *\n *                                                                         *\n * WARNINGS:   If this routine returns NULL, then no memory was freed.     *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Free_Oldest(void *poolptr)\n{\n\tMemChain_Type\t*node;\t\t// Copy of pointer to oldest node.\n\n\tif (!poolptr) return(NULL);\n\tnode = (MemChain *) Mem_Find_Oldest(poolptr);\n\tif (Mem_Free(poolptr, node)) {\n\t\treturn(node);\n\t}\n\treturn(NULL);\n}\n\n/***************************************************************************\n * MEM_POOL_SIZE -- Returns total amount of memory in pool.                *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  long total size of pool. i.e. largest possible allocation if   *\n *          no memory was allocated.                                       *\n *                                                                         *\n * WARNINGS: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Mem_Pool_Size(void *poolptr)\n{\n\tMemPool_Type\t*pool;\t\t\t// Memory pool control structure.\n\tlong\t\t\t\tmemtotal;\t\t// Total amount of memory free.\n\n\tif (!poolptr) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\tmemtotal = ((long)pool->TotalMem) << 4;\n\tmemtotal -= sizeof(MemChain_Type);\n\tmemtotal = MAX(memtotal, (long)0);\n\treturn(memtotal);\n}\n\n/***************************************************************************\n * Mem_Avail -- Returns the amount of free memory available in the cache.  *\n *                                                                         *\n *    This routine examines the memory cache and returns the amount of     *\n *    free memory available.  This memory total MAY be fragmented but      *\n *    after Mem_Cleanup() is called, an allocation of the amount returned  *\n *    by this function is guaranteed.                                      *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns the largest allocation possible from the memory cache. *\n *                                                                         *\n * WARNINGS:   The value returned may represent the FRAGMENTED total       *\n *             amount of memory free in the cache.                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nlong Mem_Avail(void *poolptr)\n{\n\tMemPool_Type\t*pool;\t\t// Memory pool control structure.\n\tlong\t\t\t\tmemtotal;\t// Total amount of memory free.\n\n\tif (!poolptr) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\tmemtotal = ((long)pool->FreeMem) << 4;\n\tmemtotal -= sizeof(MemChain_Type);\n\t//memtotal -= sizeof(MemChain_Type) + 15;\n\tmemtotal = MAX(memtotal, (long)0);\n\treturn(memtotal);\n}\n\n\n/***************************************************************************\n * MEM_LARGEST_AVAIL -- Largest free block available.                      *\n * \tThis routine examines the free node list to find the largest block   *\n *\t\tavailable.  User can Mem_Alloc() this return size successfully.      *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns largest allocation currently possible from the cache. \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Mem_Largest_Avail(void *poolptr)\n{\n\tMemChain_Type\t*node;\t\t\t// Pointer to current memory node.\n\tunsigned int\tsize;\n\tlong\t\t\t\ttruesize;\t\n\n\t/*\n\t** Make sure that it is a buffer.\n\t*/\n\tif (!poolptr) return(NULL);\n\n\t/*\n\t** Go through the entire free chain looking for the largest block.\n\t*/\n\tnode = ((MemPool_Type *)poolptr)->FreeChain;\n\tsize = 0;\n\twhile (node) {\n\n\t\t/*\n\t\t**\tFetch free memory chunk block and see if it is big enough.\n\t\t*/\n\t\tif (node->Size >= size) {\n\t\t\tsize = node->Size;\n\t\t}\n\t\tnode = node->Next;\n\t}\n\n\ttruesize = (long)size << 4;\n\ttruesize -= sizeof(MemChain_Type);\n\ttruesize = MAX(truesize, 0L);\n\treturn (truesize);\n}\n\n\n/***************************************************************************\n * Mem_Cleanup -- Performs a garbage collection on the memory cache.       *\n *                                                                         *\n *    This routine is used to coalesce all adjacent free blocks of         *\n *    memory in the specified cache.  As a result, all previous pointers   *\n *    provided by Mem_Find() are invalidated.  This routine consumes a     *\n *    fair amount of time and should be called as infrequently as          *\n *    possible.                                                            *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine takes a significant amount of time!            *\n *             If there are locked block in memory, the pool may still     *\n *             be fragmented.                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Updated for low memory caches.                       *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid Mem_Cleanup(void *poolptr)\n{\n\tMemPool_Type\t*pool;  \t// Memory pool control structure.\n\tMemChain_Type\t*free,\t// Pointer to first free area.\n\t\t\t\t\t\t*cur;\t\t// Pointer to first used block that is after free.\n\tunsigned long\tsize;\n\tunsigned long\tfreesize;// Size of free heap at the end of the block.\n\n\tif (!poolptr) return;\n\n\t/*\n\t**\tFetch working copy of pool control structure.\n\t*/\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tBasic parameter and condition legality checks.  If the memory pool\n\t**\thas no free space, no free blocks, or no allocated blocks, then \n\t**\tmemory cleanup is unnecessary -- just exit.\n\t*/\n\tif (!pool->FreeMem || !pool->FreeChain || !pool->UsedChain) return;\n\n\tfreesize = pool->FreeMem;\n\tfree = pool->FreeChain;\n\tpool->FreeChain = NULL;\n\tcur = pool->UsedChain;\n\twhile (TRUE) {\n\n\t\t/*\n\t\t** Setup pointers so that free points to the first free block and cur\n\t\t** points to the next used block after the free block.\n\t\t*/\n\t\twhile (cur < free && cur) {\n\t \t\tcur = cur->Next;\n\t\t}\n\n\t\t// All used blocks are at the front of the free.  We are done.\n\t\tif (!cur) {\n\t \t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t** Do not allow a locked block to be moved.\n\t\t*/\n\t\tif (cur->Time == MEM_BLOCK_LOCKED) {\n\t\t\t/* \n\t\t\t** Figure the size of the new free block that we are creating.\n\t\t\t** Subtract off the total block size.\n\t\t\t** Add the node to the free list.\n\t\t\t*/\n\t\t\tsize = (char *) cur - (char  *) free;\n\t\t\tsize >>= 4;\n\t\t \tfreesize -= size;\n\t\t\tMemNode_Insert(pool, TRUE, free, (unsigned int) size, -1, FALSE);\n\n\t\t\t/*\n\t\t\t** Time to find a new free position to start working from.\n\t\t\t** Cur will be in the position just following.\n\t\t\t*/\n\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, (unsigned long)cur->Size << 4);\n\t\t\tcur = cur->Next;\n\t\t\twhile (free == cur) {\n\t\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, (unsigned long)cur->Size << 4);\n\t\t\t\tcur = cur->Next;\n\t\t\t}\n\n\t\t\t// All used blocks are at the front of the free.  We are done.\n\t\t\tif (!cur) {\n\t\t\t \tbreak;\n\t\t\t}\n\t\t} else {\n\n\t\t\t// Copy the block up.\n\t\t\tsize = (unsigned long)cur->Size << 4;\n\t\t\tMem_Copy(cur, free, size);\n\t\t\tcur = free;\n\n\t\t\t// Change pointers of surrounding blocks.\n\t\t\tif (cur->Next) {\n\t\t \t\tcur->Next->Prev = cur;\n\t\t\t}\n\t\t\tif (cur->Prev) {\n\t\t \t\tcur->Prev->Next = cur;\n\t\t\t} else {\n\t\t \t\tpool->UsedChain = cur;\n\t\t\t}\n\n\t\t\t// Change to next new free area.\n\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, size);\n\t\t}\n\t}\n\n\t/*\n\t**\tNow build the single free chunk.\n\t*/\n\tMemNode_Insert(pool, TRUE, free, freesize, -1, FALSE);\n}\n\n\n/***************************************************************************\n * MemNode_Unlink -- Unlinks a node from the cache.                        *\n *                                                                         *\n *    A private routine the actually unlinks a memory block from the       *\n *    memory cache.  It doesn't perform a complete update of the memory    *\n *    cache.                                                               *\n *                                                                         *\n * INPUT:   pool     -- Pointer to the memory cache header (copy in real   *\n *                      memory).                                           *\n *                                                                         *\n *          freechain-- Is the block part of the free memory chain?        *\n *                                                                         *\n *          node     -- Pointer to the node that will be unlinked.         *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine doesn't update memory totals.  It is a support *\n *             function.                                                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nPRIVATE void MemNode_Unlink(MemPool_Type *pool, int freechain, MemChain_Type *node)\n{\n\tMemChain_Type\t*other; \t\t// Copy of node data to unlink.\n\tMemChain_Type\t**chain;\t\t// A pointer to one of the chains pointer.\n\n\t/*\n\t**\tCheck for parameter validity.\n\t*/\n\tif (!pool || !node) return;\n\t\n\t/*\n\t**\tSetup working pointer for the particular chain desired.\n\t*/\t\n\tif (freechain) {\n\t\tchain = &pool->FreeChain;\n\t} else {\n\t\tchain = &pool->UsedChain;\n\t}\n\t\n\t/*\n\t**\tMake adjustments to the previous node.  If the pointer\n\t**\tto the previous node is NULL then this indicates the\n\t**\tfirst node in the list and thus the chain pointer needs\n\t**\tto be updated instead.\n\t*/\n\tif (node->Prev) {\n\t\tother = node->Prev;\n\t\tother->Next = node->Next;\n\t} else {\n\t\t*chain = node->Next;\n\t}\n\n\tif (node->Next) {\n\t\tother = node->Next;\n\t\tother->Prev = node->Prev;\n\t}\n}\n\n\n/***************************************************************************\n * MemNode_Insert -- Inserts a node into a cache chain.                    *\n *                                                                         *\n *    This routine is used to add a node to a cache chain.  Since nodes    *\n *    do not contain double links, they must be placed in sequence.        *\n *                                                                         *\n * INPUT:   pool     -- Pointer to memory pool (must be in real memory).   *\n *                                                                         *\n *          freechain-- Is the node to be inserted into the free chain?    *\n *                                                                         *\n *          node     -- Pointer to the node to insert.                     *\n *                                                                         *\n *          size     -- Size of the memory block (in paragraphs).          *\n *                                                                         *\n *          id       -- The ID number to associate with this block.        *\n *                                                                         *\n *          merge    -- Merge inserted block with adjacent blocks.         *\n *                                                                         *\n * OUTPUT:  return                                                         *\n *                                                                         *\n * WARNINGS:   This is a support routine.                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void MemNode_Insert(MemPool_Type *pool, int freechain, MemChain_Type *node, unsigned int size, unsigned long id, int merge)\n{\n\tMemChain_Type \t**chain;\t\t\t// Pointer to chain that will be linked.\n\tMemChain_Type \t*prev,\t\t\t// Successor node pointer.\n\t\t\t\t\t\t*next;\t\t\t// Predecessor node pointer.\n\tint\t\t\t\tdoit=TRUE;\t\t// Link the node into the list.\n\n\n\t/*\n\t**\tDetermine if the parameters are valid.\n\t*/\n\tif (!pool || !node || !size) return;\n\n\t/*\n\t**\tSetup working pointer for the particular chain desired.\n\t*/\t\n\tif (freechain) {\n\t\tchain = &pool->FreeChain;\n\t} else {\n\t\tchain = &pool->UsedChain;\n\t}\n\n\t/*\n\t**\tHandle the \"no node in list\" condition (easiest).\n\t*/\n\tif (!*chain) {\n\t\tnode->Next = NULL;\n\t\tnode->Prev = NULL;\n\t\tnode->Size = size;\n\t\tnode->Time = (unsigned short)(TickCount.Time() >> 4);\n\t\tnode->ID = id;\n\t\t*chain = node;\n\t\treturn;\n\t}\n\n\t/*\n\t**\tSweep through the memory chain looking for a likely spot\n\t**\tto insert the new node.  It will stop with \"next\" pointing\n\t**\tto the node to come after the block to be inserted and \"prev\"\n\t** will point to the node right before.\n\t*/\n\tprev = NULL;\n\tnext = *chain;\n\twhile (next && (next < node)) {\n\n\t\t/*\n\t\t**\tMove up the memory chain.\n\t\t*/\n\t\tprev = next;\n\t\tnext = next->Next;\n\t}\n\n\t/*\n\t**\tCoallescing of adjacent blocks (if requested).\n\t*/\n\tif (merge) {\n\t\t\n\t\t/*\n\t\t**\tIf the previous block is touching the block to insert\n\t\t**\tthen merely adjust the size of the previous block and\n\t\t**\tthat is all that is necessary.\n\t\t*/\n\t\tif (prev) {\n\t\t\tif (((char *)prev + ((long)prev->Size << 4)) == ((char *) node)) {\n\t\t\t\tprev->Size += size;\n\t\t\t\tsize = prev->Size;\n\t\t\t\tnode = prev;\n\t\t\t\tprev = prev->Prev;\n\t\t\t\tdoit = FALSE;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf the following block is touching the block to insert\n\t\t**\tthen remove the following block and increase the size of\n\t\t**\tthe original insertion block by the size of the other\n\t\t**\tblock.\n\t\t*/\n\t\tif (next) {\n\t\t\tif (((char *)node + ((long)size << 4)) == (char *)next) {\n\t\t\t\t\n\t\t\t\tif (!doit) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the node was already merged with the previous block\n\t\t\t\t\t**\tthen merely increase the previous block's size\n\t\t\t\t\t**\tand adjust it's next pointer appropriately.\n\t\t\t\t\t*/\n\t\t\t\t\tnode->Size += next->Size;\n\t\t\t\t\tnode->Next = next->Next;\n\t\t\t\t\tnext = next->Next;\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIncrease the size of the current block and adjust\n\t\t\t\t\t**\tthe \"next\" pointer so that it gets fixed up\n\t\t\t\t\t**\taccordingly.\n\t\t\t\t\t*/\n\t\t\t\t\tsize += next->Size;\n\t\t\t\t\tnext = next->Next;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n#if DEBUG_FILL\n\tif (doit) {\n\t\tmemset(node + 1, 0xFF, (size - 1) << 4);\n\t} else {\n\t\tmemset(node + 1, 0xFF, (node->Size - 1) << 4);\n\t}\n#endif\n\n\t/*\n\t**\tFixup the node pointers.\n\t*/\n\tif (prev) {\n\t\tprev->Next = node;\n\t}else{\n\t\t*chain = node;\n\t}\n\n\tif (next) {\n\t \tnext->Prev = node;\n\t}\n\n\tif (doit) {\n\t\tnode->Prev = prev;\n\t\tnode->Next = next;\n\t\tnode->Size = size;\n\t\tnode->Time = (unsigned short)(TickCount.Time() >> 4);\n\t\tnode->ID = id;\n\t}\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "WWFLAT32/MEM/MEMFLAG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory System                            *\n *                                                                         *\n *                    File Name : MEMFLAG.H                                *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : April 4, 1994                            *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef MEMFLAG_H\n#define MEMFLAG_H\n// Memory Flags\n/*\n**\tMemory allocation flags.  These are the flags that are passed into Alloc\n**\tin order to control the type of memory allocated.\n*/\ntypedef enum {\n\tMEM_NORMAL = 0x0000,\t\t// Default memory (normal).\n\tMEM_NEW\t  = 0x0001,\t\t// Called by the operator new and was overloaded.\n\tMEM_CLEAR  = 0x0002,\t\t// Clear memory before returning.\n\tMEM_REAL   = 0x0004,\t\t// Clear memory before returning.\n\tMEM_TEMP   = 0x0008,\t\t// Clear memory before returning.\n\tMEM_LOCK   = 0x0010,\t\t// Lock the memory that we allocated\n} MemoryFlagType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: ALLOC.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid * operator new(size_t size, MemoryFlagType flag);\nvoid * operator new[] (size_t size, MemoryFlagType flag);\nvoid\t*Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags);\nvoid\tFree(void const *pointer);\nvoid\tDPMI_Lock(VOID const *ptr, long const size);\nvoid\tDPMI_Unlock(void const *ptr, long const size);\nvoid\t*Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes);\nlong\tRam_Free(MemoryFlagType flag);\nlong\tHeap_Size(MemoryFlagType flag);\nlong\tTotal_Ram_Free(MemoryFlagType flag);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MEM_COPY.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\textern void Mem_Copy(void const *source, void *dest, unsigned long bytes_to_copy);\n\n#ifdef __cplusplus\n}\n#endif\n\n\ninline void *Add_Long_To_Pointer(void const *ptr, long size) \n{\n \treturn ((void *) ( (char const *) ptr + size));\n}\n\nextern void (*Memory_Error)(void);\nextern void (*Memory_Error_Exit)(char *string);\n\nextern unsigned long MinRam;\t\t// Record of least memory at worst case.\nextern unsigned long MaxRam;\t\t// Record of total allocated at worst case.\n\n\n#endif\n\n\n"
  },
  {
    "path": "WWFLAT32/MEM/MEM_COPY.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : MEM_COPY.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott Bowen\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : September 8, 1994\t[IML]              *\n;*                  Ported to watcom c32 : 01/03/96     [JRJ]                                                                        *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Mem_Copy -- Copies from one pointer to another.                       *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nLOCALS ??\n\n\n;******************************************************************************\n; Much testing was done to determine that only when there are 14 or more bytes\n; being copied does it speed the time it takes to do copies in this algorithm.\n; For this reason and because 1 and 2 byte copies crash, is the special case\n; used.  SKB 4/21/94.  Tested on 486 66mhz.\nOPTIMAL_BYTE_COPY\tequ\t14\n\n\n;******************************************************************************\n; External declares so these functions can be called\n;\nGLOBAL \tMem_Copy\t: NEAR\nGLOBAL  Largest_Mem_Block : near\n\nCODESEG\n\n\n;***************************************************************************\n;* MEM_COPY -- Copies from one pointer to another.                         *\n;* This routine copies bytes from source to dest.  It takes care of\t   *\n;* overlapped memory, and unsigned long copies.\t\t\t\t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/18/1994 SKB : Created.                                             *\n;*=========================================================================*\n; void Mem_Copy(void *source, void *dest, unsigned long bytes_to_copy);\n\n\nPROC Mem_Copy \tC near \n\tUSES\tecx , esi , edi , ebx\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tbytes:DWORD\n\t\t\n;********************************* Setup ******************************************\n\tcld\n\tmov\tesi,[source]\n\tmov\tedi,[dest]\n\tmov\tecx,[bytes]\t; get number of bytes to copy.\t\n\n     ; check pointers for singularities\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tje\t??done\t\t; No sence in copying the same pointer.\t\n\tor\tesi,0\n\tjz\t??done\n\tor\tedi,0\n\tjz\t??done\n\n\tcmp\tecx,OPTIMAL_BYTE_COPY  ; see notes above about equate.\n\tjge\t??normal      \t       ; If >= MAX(2,OPTIMAL_BYTE_COPY), do normal dword copy.\n\n;******************************** Special case <= 2 *******************************\n;\n; This section must be called for bytes <= 2 since the other case will crash.  It\n; optionally uses OPTIMAL_BYTE_COPY for the cut off point.  This is because after\n; extensive testing, it was proved that only at that point (14 or more bytes) does\n; it become quicker to use the dword copy method.\n\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tjge\t??do_move\t; if source greater do forward copy.\n\tlea\tesi,[esi+ecx-1]\n\tstd\t\t\t; Opps, wrong, force the pointers to decrement.\n\tlea\tedi,[edi+ecx-1]\n??do_move:\n\trep\tmovsb\t\t; move the one or two bytes.\n\tcld\n??done:\n\tret\n\n;************************** back or forth, that is the question *******************\n\n??normal:\n\tmov\tebx,ecx\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tjge\t??forward\t; if source greater do forward copy.\n\n;********************************* Backward ***************************************\n??backward:\n\tlea\tecx,[edi+ebx]\n\tstd\n\tlea\tedi,[edi+ebx-1]\n\tand\tecx,3\t\t; Get non aligned bytes.\n\tlea\tesi,[esi+ebx-1]\n\tsub\tebx,ecx\t\t; remove that from the total size to be copied later.\n\trep\tmovsb\t\t; do the copy.\n\tsub\tesi,3\n\tmov\tecx,ebx\t\t; Get number of bytes left.\n \tsub\tedi,3\n\tshr\tecx,2\t\t; Do 4 bytes at a time.\n\trep\tmovsd\t\t; do the dword copy.\n\tmov\tecx,ebx\n\tadd\tesi,3\n\tadd\tedi,3\n\tand\tecx,03h\n\trep\tmovsb\t\t; finnish the remaining bytes.\n\tcld\n\tret\n\n;********************************* Forward ***************************************\n??forward:\n\tcld\n\tmov\tecx,edi\t\t; get destination pointer.\t\n\tneg\tecx\n\tand\tecx,3\t\t; Get non aligned bytes.\n\tsub\tebx,ecx\t\t; remove that from the total size to be copied later.\n\trep\tmovsb\t\t; do the copy.\n\tmov\tecx,ebx\t\t; Get number of bytes left.\n\tshr\tecx,2\t\t; Do 4 bytes at a time.\n\trep\tmovsd\t\t; do the dword copy.\n\tmov\tecx, ebx\n\tand\tecx,03h\n\trep\tmovsb\t\t; finnish the remaining bytes.\n\tret\n\nENDP\tMem_Copy\n\nPROC Largest_Mem_Block \tC near \n\tuses\tesi , edi , ebx , ecx , edx\n\tlocal\tmem_struct : dword : 16\n\n\tmov\teax , 0500h\n\tlea\tedi , [ mem_struct ]\n\tint\t31h\n\tmov\teax , [ mem_struct ]\n\n\tret\nENDP Largest_Mem_Block\n\nEND\n\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/MEM/NEWDEL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory system.                           *\n *                                                                         *\n *                    File Name : NEWDEL.CPP                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : June 21, 1994                            *\n *                                                                         *\n *                  Last Update : July 17, 1995   [PWG]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   operator NEW -- Overides the global new function.                     *\n *   operator delete -- Overides the global delete function.               *\n *   operator NEW[] -- Overides the array version of new.                  *\n *   operator delete[] -- Overides the array version of delete[]           *\n *    --                                                                   *\n *   OPERATOR NEW -- New opperator which takes a MEM_FLAG                  *\n *   OPERATOR NEW[] -- Global NEW[] which takes MEM_FLAG                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwmem.h\"\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * OPERATOR NEW -- Overides the global new function.                       *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid * operator new(size_t size) \n{\n\treturn (Alloc((unsigned long) size, MEM_NEW));\n}\n\n\n/***************************************************************************\n * OPERATOR NEW[] -- Overides the array version of new.                    *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid * operator new[](size_t size) \n{\n\treturn (Alloc((unsigned long) size, MEM_NEW));\n}\n \n/***************************************************************************\n * OPERATOR NEW -- New opperator which takes a MEM_FLAG                    *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid * operator new(size_t size, MemoryFlagType flag) \n{\n\treturn(Alloc(size, (MemoryFlagType)(flag|MEM_NEW)));\n}\n\n/***************************************************************************\n * OPERATOR NEW[] -- Global NEW[] which takes MEM_FLAG                     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid * operator new[] (size_t size, MemoryFlagType flag)\n{\n\treturn(Alloc(size, (MemoryFlagType)(flag|MEM_NEW)));\n}\n\n/***************************************************************************\n * OPERATOR DELETE -- Overides the global delete function.                 *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid operator delete(void *ptr) \n{\n\tFree(ptr);\n}\n\n/***************************************************************************\n * OPERATOR DELETE[] -- Overides the array version of delete[]           \t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/20/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid operator delete[](void *ptr) \n{\n\tFree(ptr);\n}\n\n\n\n"
  },
  {
    "path": "WWFLAT32/MEM/OLD/ALLOC.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : ALLOC.CPP                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : February 1, 1992                         *\n *                                                                         *\n *                  Last Update : March 9, 1995 [JLB]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Alloc -- Allocates system RAM.                                        *\n *   Ram_Free -- Determines the largest free chunk of RAM.                 *\n *   Free -- Free an Alloc'ed block of RAM.                                *\n *   Resize_Alloc -- Change the size of an allocated block.                *\n *   Heap_Size -- Size of the heap we have.                                *\n *   Total_Ram_Free -- Total amount of free RAM.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <malloc.h>\n#include <string.h>\n#include <stdlib.h>\n#include <dos.h>\n#include <bios.h>\n#include <stdio.h>\n\n\n#ifndef WWMEM_H\n#include \"wwmem.h\"\n#endif\n\n\nextern \"C\" unsigned long Largest_Mem_Block ( void ) ;\n\n/*\n** Define the equates necessary to call a DPMI interrupt.\n*/\n#define\tDPMI_INT\t\t\t\t\t\t\t\t\t0x0031\n#define\tDPMI_LOCK_MEM\t\t\t\t\t\t\t0x0600\n#define\tDPMI_UNLOCK_MEM\t\t\t\t\t\t0x0601\n#define  LOGGING\t\t\t\t\t\t\t\t\tFALSE\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\nunsigned long MinRam=0L;\t\t// Record of least memory at worst case.\nunsigned long MaxRam=0L;\t\t// Record of total allocated at worst case.\nstatic unsigned long TotalRam = 0L;\nstatic unsigned long Memory_Calls = 0L;\n\t\t\nvoid (*Memory_Error)(void) = NULL;\n\n/***************************************************************************\n * DPMI_LOCK -- handles locking a block of DPMI memory                     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n#include\"mono.h\"\nvoid DPMI_Lock(VOID const *ptr, long const size)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\n\t/*\n\t** Lock memory\n\t** AX = 0x600\n\t** BX:CX = starting linear address of memory to lock\n\t** SI:DI = size of region to lock (in bytes)\n\t** - If Failure, carry flag is set.\n\t*/\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_LOCK_MEM;\n\tregs.x.ebx = ((long)ptr & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000ffff);\n\tregs.x.esi = ((long)size & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n//\tif (regs.x.cflag) {\n//\t}\n#if(0)\n\tchar *temp = (char *)ptr;\n\tchar hold;\n\tfor (int lp = 0; lp < size; lp += 2048) {\n\t\thold = *temp;\n\t\ttemp += 2048;\n\t}\n#endif\n\n}\n\n/***************************************************************************\n * DPMI_UNLOCK -- Handles unlocking a locked block of DPMI                 *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid DPMI_Unlock(void const *ptr, long const size)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\n\t/*\n\t** Unlock the memory\n\t*/\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_UNLOCK_MEM;\t\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = ((long)ptr & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000ffff);\n\tregs.x.esi = ((long)size & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n//\tif (regs.x.cflag) {\n//\t}\n\n}\n\n/***************************************************************************\n * Alloc -- Allocates system RAM.                                          *\n *                                                                         *\n *    This is the basic RAM allocation function.  It is used for all       *\n *    memory allocations needed by the system or the main program.         *\n *                                                                         *\n * INPUT:   bytes_to_alloc -- LONG value of the number of bytes to alloc.  *\n *                                                                         *\n *          flags          -- Memory allocation control flags.             *\n *             MEM_NORMAL: No special flags.                               *\n *             MEM_CLEAR:  Zero out memory block.                        \t*\n *             MEM_NEW:\t\tCalled by a new.                                *\n *                                                                         *\n * OUTPUT:  Returns with pointer to allocated block.  If NULL was returned *\n *          it indicates a failure to allocate.  Note: NULL will never be  *\n *          returned if the standard library allocation error routine is   *\n *          used.                                                          *\n *                                                                         *\n * WARNINGS:   If you replace the standard memory allocation error routine *\n *             and make it so that Alloc CAN return with a NULL, be sure   *\n *             and check for this in your code.                            *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Documented.                                          *\n *   08/09/1993 JLB : Updated with EMS memory support.                     *\n *   04/28/1994 JAW : Updated to 32bit Protected mode.                     *\n *   03/09/1995 JLB : Fixed                                                * \n *=========================================================================*/\nvoid *Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags)\n{\n\tunion REGS\t\tregs ;\n\tstruct SREGS \tsregs ;\n\tunsigned char *retval=NULL;\t// Pointer to allocated block.\n\tunsigned long\toriginal_size;\t// Original allocation size.\n\tunsigned long\tbytesfree;\t\t// Number of free bytes.\n\tlong \t\t\t\t*longptr=NULL;\t// Pointer used to store selector\n\n\t/* \n\t** Save the original allocated space size so that we can clear the\n\t** exact amount of RAM if they specified MEM_CLEAR.\n\t*/\n\toriginal_size = bytes_to_alloc;\n\n\t/*\n\t** Reserve one byte for the header of the memory we allocated.\n\t** We will store the flags variable there for later use.\n\t*/\n\tbytes_to_alloc += (flags & MEM_LOCK) ? 5 : 1;\n\n\t/*\n\t**\tInitialize the total ram available value.\n\t*/\n\tif (!TotalRam) {\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\t}\n\n\n\t// Try to allocate the memory out of the protected mode memory\n\t// chain if we did not require a real mode allocation.  If this \n\t// fails we will have to try to allocate it out of real mode memory.\n\t// Real mode memory is a last resort because some types of applications\n\t// require real mode memory.\n\tif (!(flags & MEM_REAL)) {\n\t\tretval = (unsigned char*)malloc(bytes_to_alloc);\n\t}\n\n\t// Try to allocate the memory out of the real mode memory using DPMI\n\t// service 0x100.  Note that retval will be null if we are requesting\n\t// real mode memory so that we do not have to explicitly check for the\n\t// real mode flag.  Remember we need to reserve room for the dos \n\t// selector value at the beginning of our allocated block so rather than\n\t// adding fifteen and rounding, we need to add 19 and round.\n\tif (!retval) {\n\t\tflags = (MemoryFlagType)(flags | MEM_REAL);\n\t\tregs.x.eax = 0x100;\n\t\tregs.x.ebx = (bytes_to_alloc + 19) >> 4;\n\t\tif (regs.x.ebx & 0xFFFF0000) {\n\t\t\tretval = NULL;\n\t\t} else {\n\t\t\tsegread ( & sregs ) ;\n\t\t\tint386x ( 0x31 , & regs, & regs , & sregs\t) ;\n\t\t\tif (regs.x.cflag)\n\t\t\t\tretval = NULL;\n\t\t\telse {\n\t\t\t\tlongptr\t\t= (long *)(((regs.x.eax & 0xFFFF) << 4)+ 1);\n\t\t\t\t*longptr++\t= regs.x.edx & 0xFFFF;\n\t\t\t\tretval\t\t= (unsigned char *)longptr;\n\t\t\t}\n\t\t}\n\t}\n\n\t// If the alloc failed then we need to signify a memory error.\n\tif (retval == NULL) {\n\t\tif(Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\t\t\n\t}\n\n\t// If the memory needs to be DPMI locked then we should store the\n\t// original size in the header before we store the flags.\n\tif (flags & MEM_LOCK) {\n\t\tlongptr\t\t= (long *)retval;\n\t\t*longptr++\t= original_size;\n\t\tretval\t\t= (unsigned char *)longptr;\n\t}\n\n\n\t// Now that we know the alloc was sucessful (and for an extra byte\n\t// more than the user wanted) we need to stick in the memory flags.\n\t*retval++ \t\t= flags;\n\n\t// If the memory needed to be DPMI locked then set it up so it\n\t// is locked.\n\tif (flags & MEM_LOCK) {\n\t\tDPMI_Lock(retval, original_size);\n\t\t\n\t}\n\n\n\t/* Clear the space if they wanted it clear */\n\n\tif (flags & MEM_CLEAR) {\n\t\tunsigned char\t*ptr;\t\t// Working memory block pointer.\n\n\t\tptr = retval;\n\t\tmemset(ptr, '\\0', original_size);\n\t}\n\n\tbytesfree = Total_Ram_Free(MEM_NORMAL);\n\tif (bytesfree < MinRam) {\n\t\tMinRam = bytesfree;\n\t}\n\tif (TotalRam-bytesfree > MaxRam) {\n\t\tMaxRam = TotalRam-bytesfree;\n\t}\n\n\tMemory_Calls++;\n\n#if(LOGGING)\n\tint val = _heapchk();\n\n\tFILE *file = fopen(\"mem.txt\",\"at\");\n\tfprintf(file, \"%P Alloc size = %d, Actual Size = %d, flags = %d, heap = %d\\n\", \n\t\t\t\t\t\tretval,\n\t\t\t\t\t\toriginal_size,\n\t\t\t\t\t\tbytes_to_alloc,\n\t\t\t\t\t\tflags,\n\t\t\t\t\t\tval);\n\tfclose(file);\n#endif\n\n\treturn(retval);\n}\n\n\n/***************************************************************************\n * Free -- Free an Alloc'ed block of RAM.                                  *\n *                                                                         *\n * FUNCTION:                                                               *\n *                                                                         *\n * INPUT:       A pointer to a block of RAM from Alloc.                    *\n *                                                                         *\n * OUTPUT:      None.                                                      *\n *                                                                         *\n * WARNINGS:    Don't use this for an Alloc_Block'ed RAM block.            *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/25/1990     : Created.                                             *\n ***************************************************************************/\nvoid Free(void const *pointer)\n{\n\tunion REGS\t\tregs ;\n\tstruct SREGS \tsregs ;\n\n\tvoid const *original = pointer;\n\n\tif (pointer) {\n\t\t/*\n\t\t** Get a pointer to the flags that we stored off.\n\t\t*/\n\t\tchar *byteptr\t= ((char *)pointer) - 1;\n\n\t\t/*\n\t\t** Check to see if this was locked me and if it was unlock it.\n\t\t*/\n\t\tif (*byteptr & MEM_LOCK) {\n\t\t\tlong *longptr = ((long *)byteptr) - 1;\n\t\t\tDPMI_Unlock(pointer, *longptr);\n\t\t\tpointer = (void *)longptr;\n\t\t} else\n\t\t\tpointer = (void *)byteptr;\n\n#if(LOGGING)\t\t\n\t\tint val = _heapchk();\n\t\tFILE *file = fopen(\"mem.txt\",\"at\");\n\t\tfprintf(file, \"%P Free flags = %d, Heap = %d\\n\", \n\t\t\t\t\t\t\toriginal,\n\t\t\t\t\t\t\t*byteptr, \n\t\t\t\t\t\t\tval);\n\t\tfclose(file);\n#endif\n\n\t\t// If the pointer is a real mode pointer than it will point to the\n\t\t// first megabyte of system memory.  If it does than we need to \n\t\t// use DPMI to free it.\n\t\tif (*byteptr & MEM_REAL) {\n\t\t\tregs.x.eax\t= 0x101;\n\t\t\tregs.x.edx\t= *(((long *)pointer) - 1);\n\t\t\tsegread ( & sregs ) ;\n\t\t\tint386x(0x31, &regs, &regs, &sregs);\n\t\t} else {\n\t\t\tfree((void *)pointer);\n\t\t}\n\t\tMemory_Calls--;\n\t}\n}\n\n\n/***************************************************************************\n * Resize_Alloc -- Change the size of an allocated block.                  *\n *                                                                         *\n *    This routine will take a previously allocated block and change its   *\n *    size without unnecessarily altering its contents.                    *\n *                                                                         *\n * INPUT:   pointer  -- Pointer to the original memory allocation.         *\n *                                                                         *\n *          new_size -- Size in bytes that it will be converted to.        *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the new allocation.                  *\n *                                                                         *\n * WARNINGS:   ???                                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/01/1992 JLB : Commented.                                           *\n *=========================================================================*/\nvoid *Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes)\n{\n\n\tunsigned long *temp;\n\tunsigned long diff, flags;\n\n\ttemp = (unsigned long*)original_ptr;\n\n\t/* ReAlloc the space */\n\ttemp = (unsigned long *)realloc(temp, new_size_in_bytes);\n\tif (temp == NULL) {\n\t\tif(Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\t\t\n\t}\t\t\t   \n\n\treturn(temp);\n}\n\n\n/***************************************************************************\n * Ram_Free -- Determines the largest free chunk of RAM.                   *\n *                                                                         *\n *    Use this routine to determine the largest free chunk of available    *\n *    RAM for allocation.  It also performs a check of the memory chain.   *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  Returns with the size of the largest free chunk of RAM.        *\n *                                                                         *\n * WARNINGS:   This does not return the TOTAL memory free, only the        *\n *             largest free chunk.                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Commented.                                           *\n *=========================================================================*/\nlong Ram_Free(MemoryFlagType)\n{\n//\treturn(_memmax());\n\treturn Largest_Mem_Block();\n}\n\n\n/***************************************************************************\n * Heap_Size -- Size of the heap we have.                                  *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Heap_Size(MemoryFlagType )\n{\n\tif (!TotalRam) {\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\t}\n\treturn(TotalRam);\n}\n\n\n/***************************************************************************\n * Total_Ram_Free -- Total amount of free RAM.                             *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *   03/09/1995 JLB : Uses prerecorded heap size maximum.                  * \n *=========================================================================*/\nlong Total_Ram_Free(MemoryFlagType )\n{\n//\treturn(_memavl());\n\treturn Largest_Mem_Block () ;\n}\n\n"
  },
  {
    "path": "WWFLAT32/MEM/OLD/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 24, 1994                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = mem\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR\t    = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\nCC_CFG += /zm\t\t\t\t\t\t\t\t\t# Each routine to be in its own segment.\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\talloc.obj  \t&\n\tmem.obj  \t&\n\tnewdel.obj  \t&\n\tmem_copy.obj \n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WWFLAT32/MEM/OLD/MEM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : MEM.C                                    *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : March 31, 1993                           *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Mem_Free -- Free a block of memory from system.                       *\n *   Mem_Alloc -- Allocate a block of memory from the special memory pool. *\n *   Mem_Init -- Initialize the private memory allocation pool.            *\n *   Mem_Reference -- Updates the reference time for the specified memory blo*\n *   Mem_Find -- Returns with pointer to specified memory block.           *\n *   Mem_Find_Oldest -- Returns with the memory block with the oldest time st*\n *   Mem_Free_Oldest -- Find and free the oldest memory block.             *\n *   Mem_Avail -- Returns the amount of free memory available in the cache.*\n *   Mem_Cleanup -- Performes a garbage collection on the memory cache.    *\n *   MemNode_Unlink -- Unlinks a node from the cache.                      *\n *   MemNode_Insert -- Inserts a node into a cache chain.                  *\n *   Mem_Largest_Avail -- Largest free block available.                    *\n *   Mem_Lock_Block -- Locks a block so that it cannot be moved in cleanup.*\n *   Mem_In_Use -- Makes it so a block will never be returned as oldest*\n *   Mem_Pool_Size -- Returns total amount of memory in pool.              *\n *   Mem_Get_ID -- Returns ID of node.                                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"wwmem.h\"\n#include <timer.h>\n\n#include\t<stddef.h>\n#include\t<mem.h>\n\n#define DEBUG_FILL FALSE\n\n////////////////////////////////////////////////////////////////////////////\n\n\n\n/*******************************************************************************\n** A allocated block may have one of three meanings in the Time field.  The first\n** is the time stamp of the last time it was referenced.  The other two values\n** are defined below.  MEM_BLOCK_IN_USE means that it will never be returned as the\n** oldest since there is no valid time stamp.  LOCKED_BLOCK has the same meaning as\n** MEM_BLOCK_IN_USE with the added feature that the block will not be moved in a \n** Mem_Cleanup().  Therefore, there may be some fragmentation after the cleanup\n** if any blocks are LOCKED.  It would be good practice to seldomly lock blocks,\n** for instance, only when a sample is being played.\n** WARNING: If these values change to anything else, logic will need to be changed\n**          in Mem_Find_Oldest since it relies on these being small values.\n*/\n#define MEM_BLOCK_IN_USE\t0x00\n#define MEM_BLOCK_LOCKED\t0x01\n\n/*\n**\tEach block of memory in the pool is headed by this structure.\n*/\ntypedef struct MemChain {\n\tstruct MemChain\t*Next;\t// Pointer to next memory chain node.\n\tstruct MemChain\t*Prev;\t// Pointer to previous memory chain node.\n\tunsigned long\t\tID;\t\t// ID number of block.\n\tunsigned short\t\tTime;\t\t// TickCount of latest reference.\n\tunsigned short\t\tSize;\t\t// Size of memory block (in paragraphs).\n} MemChain_Type;\n\n\n/*\n**\tHolding tank memory management data.\n*/\ntypedef struct MemPool {\n\tMemChain_Type\t*FreeChain;\t// Pointer to first node in free chain.\n\tMemChain_Type\t*UsedChain;\t// Pointer to first node in used chain.\n\tunsigned short\tFreeMem;\t\t// Current amount of free ram (in paragraphs).\n\tunsigned short\tTotalMem;\t// Total quantity of memory.\n\tlong\t\t\t\tpad2;\n} MemPool_Type;\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE void MemNode_Unlink(MemPool_Type *pool, int freechain, MemChain_Type *node);\nPRIVATE void MemNode_Insert(MemPool_Type *pool, int freechain, MemChain_Type *node, unsigned int size, unsigned long id, int merge);\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * Mem_Init -- Initialize the private memory allocation pool.              *\n *                                                                         *\n *    This routine is used to initialize the private memory allocation     *\n *    pool.                                                                *\n *                                                                         *\n * INPUT:   buffer   -- Pointer to the buffer that is the allocation pool. *\n *                                                                         *\n *          size     -- Size of the buffer in bytes.                       *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Was it initialized successfully?                   *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nint Mem_Init(void *buffer, long size)\n{\n\tMemChain_Type\t*mem;\t\t\t// Working memory chain node.\n\tMemPool_Type\t*pool;\t\t// Memory pool control structure.\n\n\t/*\n\t**\tThe buffer is rounded down to the nearest paragraph.\n\t*/\n\tsize = size & 0xFFFFFFF0L;\n\n\tif (!buffer || !size) return(FALSE);\n\n\t/*\n\t**\tInitialize the pool control structure.\n\t*/\n\tpool = (MemPool_Type *)buffer;\n\tpool->FreeMem = (size - sizeof(MemPool_Type)) >> 4;\n\tpool->UsedChain = NULL;\n\tpool->TotalMem = pool->FreeMem;\n\tmem = pool->FreeChain = (MemChain_Type *) (pool + 1);\n\n\t/*\n\t**\tInitialize the free memory chain.\n\t*/\n\tmem->Next = NULL;\n\tmem->Prev = NULL;\n\tmem->Size = pool->FreeMem;\n\tmem->ID = -1;\n\tmem->Time = 0;\n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * Mem_Alloc -- Allocate a block of memory from the special memory pool.   *\n *                                                                         *\n *    This routine will allocate a block of memory from the special        *\n *    memory allocation pool.                                              *\n *                                                                         *\n * INPUT:   poolptr\t-- Pointer to the memory pool base address.           *\n *                                                                         *\n *          size  -- The size of the memory block to allocate.             *\n *                                                                         *\n *          id    -- ID number to give this memory block.                  *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the allocated block.  If there was   *\n *          insufficient room, then NULL is returned.                      *\n *                                                                         *\n * WARNINGS:   Be sure to check for the NULL return case.                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Alloc(void *poolptr, long lsize, unsigned long id)\n{\n\tMemPool_Type\t*pool;\n\tMemChain_Type\t*node;\t\t\t// Pointer to current memory node.\n\tunsigned int\tremainder=0;\t// Remaining bytes that are still free.\n\tint\t\t\t\tfound;\n\tint\t\t\t\tsize;\t\t\t\t// Paragraph size of allocation.\n\n\n\t/*\n\t**\tIf there is no free memory then the allocation will\n\t**\talways fail.\n\t*/\n\tif (!poolptr || !lsize) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\t\t\n\t/*\n\t**\tAllocations are forced to be paragraph sized.\n\t*/\n\tlsize += sizeof(MemChain_Type);\t// Account for header.\n\tlsize = (lsize + 0x0FL) & 0xFFFFFFF0L;\n\tsize = (int)(lsize >> 4);\n\n\t/*\n\t**\tIf the total free is less than the size of the desired allocation,\n\t**\tthen we KNOW that an allocation will fail -- just return.\n\t*/\n\tif (pool->TotalMem < size) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tWalk down free chain looking for the first block that will\n\t**\taccomodate the allocation.\n\t*/\n\tnode = pool->FreeChain;\n\tfound = FALSE;\n\twhile (!found && node) {\n\n\t\t/*\n\t\t**\tFetch free memory chunk block and see if it is big enough.\n\t\t*/\n\t\tif (node->Size >= size) {\n\t\t\tfound = TRUE;\n\t\t\tbreak;\n\t\t}\n\t\tnode = node->Next;\n\t}\n\tif (!found) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tDetermine if this allocation would split the block.\n\t*/\n\tremainder = node->Size - size;\n\n\t/*\n\t**\tIf only a very small free chunk would remain, just tack it on\n\t**\tto the current allocation.\n\t*/\n\tif (remainder <= 2) {\n\t\tremainder = 0;\n\t\tsize = node->Size;\n\t}\n\n\t/*\n\t**\tRemove the primary block from the free memory list.\n\t*/\n\tMemNode_Unlink(pool, TRUE, node);\n\n\t/*\n\t**\tIf a smaller block remains, then link it back into\n\t**\tthe free memory list.\n\t*/\n\tif (remainder) {\n\t\tMemNode_Insert(pool, TRUE, (MemChain_Type *)Add_Long_To_Pointer(node, (long)size << 4), remainder, -1, FALSE);\n\t}\n\n\t/*\n\t**\tLink in the allocated node into the used memory list.\n\t*/\n\tMemNode_Insert(pool, FALSE, node, size, id, FALSE);\n\n\t/*\n\t**\tReflect the change to the total free count.\n\t*/\n\tpool->FreeMem -= size;\n\n\t/*\n\t**\tReturn a pointer to the block of allocated memory just past\n\t**\tthe header.\n\t*/\n\n#if DEBUG_FILL\n\tmemset(node + 1, id, (size-1) << 4);\n#endif\n\treturn((void *) (node + 1));\n}\t\n\n\n/***************************************************************************\n * Mem_Free -- Free a block of memory from system.                         *\n *                                                                         *\n *    This routine will free a block of memory from the special memory     *\n *    buffer.                                                              *\n *                                                                         *\n * INPUT:   poolptr\t-- Pointer to the memory pool base address.           *\n *                                                                         *\n *          buffer   -- Pointer to memory block to free.                   *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Was the deallocation successful?                   *\n *                                                                         *\n * WARNINGS:   Be sure to only pass in to this routine a buffer that was   *\n *             returned from Mem_Alloc().                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nint Mem_Free(void *poolptr, void *buffer)\n{\n\tMemPool_Type\t*pool;\t\t\t// pointer to structure.\n\tMemChain_Type\t*node;\t\t\t// Copy of current memory node.\n\tunsigned int\tsize;\t\t\t\t// Size of the block being freed.\n\n\t/*\n\t**\tOne can't free what isn't there.\n\t*/\n\tif (!buffer || !poolptr) {\n\t\treturn(FALSE);\n\t}\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tThe node pointer is actually back a bit from the \"normal\" pointer.\n\t*/\n\tnode = (MemChain_Type *) buffer;\n\tnode--;\n\n\t/*\n\t**\tGet pointer to actual allocated node and unlink it from the used\n\t**\tmemory chain.\n\t*/\t\n\tsize = node->Size;\n\tMemNode_Unlink(pool, FALSE, node);\n\tMemNode_Insert(pool, TRUE, node, size, -1, TRUE);\n\n\t/*\n\t**\tReflect the new free memory into the total memory count.\n\t*/\n\tpool->FreeMem += size;\n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * Mem_Reference -- Updates the reference time for the specified memory blo*\n *                                                                         *\n *    This routine is used to update the memory reference time for the     *\n *    specified memory node.  Typically, this is called every time a       *\n *    memory block is used in order to make sure the memory block time     *\n *    tracking (Last Recently Used) system works properly.                 *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   The node pointer must be valid.  For maximum safety this    *\n *             routine should be called right after Mem_Find().            *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid Mem_Reference(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node;\n\tnodeptr--;\n\n\tnodeptr->Time = (unsigned short)(TickCount.Time() >> 4);\n\n}\n\n\n/***************************************************************************\n * MEM_LOCK_BLOCK -- Locks a block so that it cannot be moved in cleanup.  *\n * \tBy marking a memory block in use, the memory system will never return*\n *    it as the oldest memory block.  It also makes it so that the block\t*\n *    will never be moved during a Cleanup process.                        *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:  \tIf one or more blocks are locked in a heap, Mem_Avail might *\n *             not equal Mem_Largest_Avail after a call to Mem_Cleanup.    *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid Mem_Lock_Block(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node;\n\tnodeptr--;\n\tnodeptr->Time = MEM_BLOCK_LOCKED;\n}\n\n\n/***************************************************************************\n * MEM_IN_USE -- Makes it so a block will never be returned as oldest\t\t*\n * \tBy marking a memory block in use, the memory system will never return*\n *    it as the oldest memory block.  It still can be moved in the Cleanup *\n *    code.                                                                *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS: Mem_Find_Oldest() will return NULL if only IN_USE blocks are  *\n *           in memory.                                                    *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid Mem_In_Use(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node - 1;\n\tnodeptr->Time = MEM_BLOCK_IN_USE;\n}\n\n\n/***************************************************************************\n * Mem_Find -- Returns with pointer to specified memory block.             *\n *                                                                         *\n *    Use this routine to convert a memory ID value into an actual memory  *\n *    pointer.  It sweeps through all of the 'cached' memory blocks and    *\n *    returns with the matching block pointer.                             *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache block.                 *\n *                                                                         *\n *          id       -- The ID of the block desired.                       *\n *                                                                         *\n * OUTPUT:  Returns with the pointer to the memory block.  If NULL is      *\n *          returned then the desired block is not in the memory cache.    *\n *                                                                         *\n * WARNINGS:   This routine may return NULL if the memory block is not     *\n *             present in the cache.                                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Find(void *poolptr, unsigned long id)\n{\n\tMemPool_Type\t*pool;\t\t\t// pointer to structure.\n\tMemChain_Type\t*node;\t\t\t// Working node structure.\n\n\tif (!poolptr) return(NULL);\n\n\tpool = (MemPool_Type *) poolptr;\n\t\t\n\t/* \n\t** Cannot free a node that is not on the UsedChain list.\n\t*/\n\tif (!pool->UsedChain) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tSweep through entire allocation chain to find\n\t**\tthe one with the matching ID.\n\t*/\n\tnode = pool->UsedChain;\n\twhile (node) {\n\t\t\n\t\tif (node->ID == id) {\n\t\t\treturn(node + 1);\n\t\t}\n\t\tnode = node->Next;\n\t}\n\treturn(NULL);\n}\n\n\n/***************************************************************************\n * MEM_GET_ID -- Returns ID of node.                                       *\n *                                                                         *\n * INPUT:  void *node - pointer to node. \t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT: The ID of the node that was supplied by user during Mem_Alloc().*\n *                                                                         *\n * WARNINGS: pointer to node must be one that Mem_Alloc or                \t*\n *           Mem_Find returned.                                           **\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nunsigned long Mem_Get_ID(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return (0L);\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node - 1;\n\treturn (nodeptr->ID);\n}\n\n\n/***************************************************************************\n * Mem_Find_Oldest -- Returns with the memory block with the oldest time st*\n *                                                                         *\n *    Use this routine to find the memory block with the oldest time stamp *\n *    value.  Typically, this is used when freeing memory blocks in the    *\n *    cache in order to make room for a new memory block.                  *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns with the pointer to the oldest memory block.  If NULL  *\n *          is returned, then the memory cache is empty.                   *\n *                                                                         *\n * WARNINGS:   This routine could return NULL.                             *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *   04/15/1994 SKB : Handle time wrap, locked blocks, and no_refenece blocks*\n *=========================================================================*/\nvoid *Mem_Find_Oldest(void *poolptr)\n{\n\tMemChain_Type\t*node; \t\t\t\t// Working node pointer.\n\tMemChain_Type\t*oldnode;\t\t\t// Pointer to oldest block.\n\tunsigned int\toldtime;\t\t\t\t// Time of oldest block.\n\tunsigned int\tbasetime;\t\t\t// Time to mark our base time with.\n\tunsigned int\ttime;\t\t\t\t\t// basetime + time of node.\n\n\tif (!poolptr) return(NULL);\n\n\t/*\n\t**\tSweep through entire allocation chain to find\n\t**\tthe oldest referenced memory block.\n\t*/\n\toldnode = NULL;\n\toldtime = 0;\n\tnode = ((MemPool_Type*) poolptr)->UsedChain;\n\n  basetime = (unsigned int)(TickCount.Time() >> 4);\n\n\twhile (node) {\n\n\t\t/*\n\t\t** Don't allow MEM_BLOCK_IN_USE or MEM_BLOCK_LOCKED to be returned.\n\t\t*/\n\t\tif (node->Time > MEM_BLOCK_LOCKED) {\n\n\t\t\t/*\n\t\t\t** Adjust time for wrap around (after about 5 hrs).\n\t\t\t** times less then the base time will wrap up high while\n\t\t\t** and times greater then base time will then be lower since\n\t\t\t** any time greater has been on the thing a long time.\n\t\t\t*/\n\t\t\ttime = node->Time - basetime ;\n\n\t\t\tif (time < oldtime || !oldnode) {\n\t\t\t\toldtime = time;\n\t\t\t\toldnode = node;\n\t\t\t}\n\t\t}\n\t\tnode = node->Next;\n\t}\n\n\t/*\n\t**\tReturn with the value that matches the pointer that\n\t**\twas allocated by the system previously.\n\t*/\n\tif (oldnode) {\n\t\toldnode++;\n\t}\n\treturn(oldnode);\n}\n\n\n/***************************************************************************\n * Mem_Free_Oldest -- Find and free the oldest memory block.               *\n *                                                                         *\n *    This routine is used to free the oldest memory block in the memory   *\n *    cache.  This routine is typcially used in order to create more room  *\n *    in the cache for a new allocation.                                   *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns with the node that it freed.  Although this node is    *\n *          is no longer valid, it may be used to mark that pointer as     *\n *          invalid in the main code.                                      *\n *                                                                         *\n * WARNINGS:   If this routine returns NULL, then no memory was freed.     *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Free_Oldest(void *poolptr)\n{\n\tMemChain_Type\t*node;\t\t// Copy of pointer to oldest node.\n\n\tif (!poolptr) return(NULL);\n\tnode = (MemChain *) Mem_Find_Oldest(poolptr);\n\tif (Mem_Free(poolptr, node)) {\n\t\treturn(node);\n\t}\n\treturn(NULL);\n}\n\n/***************************************************************************\n * MEM_POOL_SIZE -- Returns total amount of memory in pool.                *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  long total size of pool. i.e. largest possible allocation if   *\n *          no memory was allocated.                                       *\n *                                                                         *\n * WARNINGS: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Mem_Pool_Size(void *poolptr)\n{\n\tMemPool_Type\t*pool;\t\t\t// Memory pool control structure.\n\tlong\t\t\t\tmemtotal;\t\t// Total amount of memory free.\n\n\tif (!poolptr) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\tmemtotal = ((long)pool->TotalMem) << 4;\n\tmemtotal -= sizeof(MemChain_Type);\n\tmemtotal = MAX(memtotal, (long)0);\n\treturn(memtotal);\n}\n\n/***************************************************************************\n * Mem_Avail -- Returns the amount of free memory available in the cache.  *\n *                                                                         *\n *    This routine examines the memory cache and returns the amount of     *\n *    free memory available.  This memory total MAY be fragmented but      *\n *    after Mem_Cleanup() is called, an allocation of the amount returned  *\n *    by this function is guaranteed.                                      *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns the largest allocation possible from the memory cache. *\n *                                                                         *\n * WARNINGS:   The value returned may represent the FRAGMENTED total       *\n *             amount of memory free in the cache.                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nlong Mem_Avail(void *poolptr)\n{\n\tMemPool_Type\t*pool;\t\t// Memory pool control structure.\n\tlong\t\t\t\tmemtotal;\t// Total amount of memory free.\n\n\tif (!poolptr) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\tmemtotal = ((long)pool->FreeMem) << 4;\n\tmemtotal -= sizeof(MemChain_Type);\n\t//memtotal -= sizeof(MemChain_Type) + 15;\n\tmemtotal = MAX(memtotal, (long)0);\n\treturn(memtotal);\n}\n\n\n/***************************************************************************\n * MEM_LARGEST_AVAIL -- Largest free block available.                      *\n * \tThis routine examines the free node list to find the largest block   *\n *\t\tavailable.  User can Mem_Alloc() this return size successfully.      *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns largest allocation currently possible from the cache. \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Mem_Largest_Avail(void *poolptr)\n{\n\tMemChain_Type\t*node;\t\t\t// Pointer to current memory node.\n\tunsigned int\tsize;\n\tlong\t\t\t\ttruesize;\t\n\n\t/*\n\t** Make sure that it is a buffer.\n\t*/\n\tif (!poolptr) return(NULL);\n\n\t/*\n\t** Go through the entire free chain looking for the largest block.\n\t*/\n\tnode = ((MemPool_Type *)poolptr)->FreeChain;\n\tsize = 0;\n\twhile (node) {\n\n\t\t/*\n\t\t**\tFetch free memory chunk block and see if it is big enough.\n\t\t*/\n\t\tif (node->Size >= size) {\n\t\t\tsize = node->Size;\n\t\t}\n\t\tnode = node->Next;\n\t}\n\n\ttruesize = (long)size << 4;\n\ttruesize -= sizeof(MemChain_Type);\n\ttruesize = MAX(truesize, 0L);\n\treturn (truesize);\n}\n\n\n/***************************************************************************\n * Mem_Cleanup -- Performs a garbage collection on the memory cache.       *\n *                                                                         *\n *    This routine is used to coalesce all adjacent free blocks of         *\n *    memory in the specified cache.  As a result, all previous pointers   *\n *    provided by Mem_Find() are invalidated.  This routine consumes a     *\n *    fair amount of time and should be called as infrequently as          *\n *    possible.                                                            *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine takes a significant amount of time!            *\n *             If there are locked block in memory, the pool may still     *\n *             be fragmented.                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Updated for low memory caches.                       *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid Mem_Cleanup(void *poolptr)\n{\n\tMemPool_Type\t*pool;  \t// Memory pool control structure.\n\tMemChain_Type\t*free,\t// Pointer to first free area.\n\t\t\t\t\t\t*cur;\t\t// Pointer to first used block that is after free.\n\tunsigned long\tsize;\n\tunsigned long\tfreesize;// Size of free heap at the end of the block.\n\n\tif (!poolptr) return;\n\n\t/*\n\t**\tFetch working copy of pool control structure.\n\t*/\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tBasic parameter and condition legality checks.  If the memory pool\n\t**\thas no free space, no free blocks, or no allocated blocks, then \n\t**\tmemory cleanup is unnecessary -- just exit.\n\t*/\n\tif (!pool->FreeMem || !pool->FreeChain || !pool->UsedChain) return;\n\n\tfreesize = pool->FreeMem;\n\tfree = pool->FreeChain;\n\tpool->FreeChain = NULL;\n\tcur = pool->UsedChain;\n\twhile (TRUE) {\n\n\t\t/*\n\t\t** Setup pointers so that free points to the first free block and cur\n\t\t** points to the next used block after the free block.\n\t\t*/\n\t\twhile (cur < free && cur) {\n\t \t\tcur = cur->Next;\n\t\t}\n\n\t\t// All used blocks are at the front of the free.  We are done.\n\t\tif (!cur) {\n\t \t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t** Do not allow a locked block to be moved.\n\t\t*/\n\t\tif (cur->Time == MEM_BLOCK_LOCKED) {\n\t\t\t/* \n\t\t\t** Figure the size of the new free block that we are creating.\n\t\t\t** Subtract off the total block size.\n\t\t\t** Add the node to the free list.\n\t\t\t*/\n\t\t\tsize = (char *) cur - (char  *) free;\n\t\t\tsize >>= 4;\n\t\t \tfreesize -= size;\n\t\t\tMemNode_Insert(pool, TRUE, free, (unsigned int) size, -1, FALSE);\n\n\t\t\t/*\n\t\t\t** Time to find a new free position to start working from.\n\t\t\t** Cur will be in the position just following.\n\t\t\t*/\n\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, (unsigned long)cur->Size << 4);\n\t\t\tcur = cur->Next;\n\t\t\twhile (free == cur) {\n\t\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, (unsigned long)cur->Size << 4);\n\t\t\t\tcur = cur->Next;\n\t\t\t}\n\n\t\t\t// All used blocks are at the front of the free.  We are done.\n\t\t\tif (!cur) {\n\t\t\t \tbreak;\n\t\t\t}\n\t\t} else {\n\n\t\t\t// Copy the block up.\n\t\t\tsize = (unsigned long)cur->Size << 4;\n\t\t\tMem_Copy(cur, free, size);\n\t\t\tcur = free;\n\n\t\t\t// Change pointers of surrounding blocks.\n\t\t\tif (cur->Next) {\n\t\t \t\tcur->Next->Prev = cur;\n\t\t\t}\n\t\t\tif (cur->Prev) {\n\t\t \t\tcur->Prev->Next = cur;\n\t\t\t} else {\n\t\t \t\tpool->UsedChain = cur;\n\t\t\t}\n\n\t\t\t// Change to next new free area.\n\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, size);\n\t\t}\n\t}\n\n\t/*\n\t**\tNow build the single free chunk.\n\t*/\n\tMemNode_Insert(pool, TRUE, free, freesize, -1, FALSE);\n}\n\n\n/***************************************************************************\n * MemNode_Unlink -- Unlinks a node from the cache.                        *\n *                                                                         *\n *    A private routine the actually unlinks a memory block from the       *\n *    memory cache.  It doesn't perform a complete update of the memory    *\n *    cache.                                                               *\n *                                                                         *\n * INPUT:   pool     -- Pointer to the memory cache header (copy in real   *\n *                      memory).                                           *\n *                                                                         *\n *          freechain-- Is the block part of the free memory chain?        *\n *                                                                         *\n *          node     -- Pointer to the node that will be unlinked.         *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine doesn't update memory totals.  It is a support *\n *             function.                                                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nPRIVATE void MemNode_Unlink(MemPool_Type *pool, int freechain, MemChain_Type *node)\n{\n\tMemChain_Type\t*other; \t\t// Copy of node data to unlink.\n\tMemChain_Type\t**chain;\t\t// A pointer to one of the chains pointer.\n\n\t/*\n\t**\tCheck for parameter validity.\n\t*/\n\tif (!pool || !node) return;\n\t\n\t/*\n\t**\tSetup working pointer for the particular chain desired.\n\t*/\t\n\tif (freechain) {\n\t\tchain = &pool->FreeChain;\n\t} else {\n\t\tchain = &pool->UsedChain;\n\t}\n\t\n\t/*\n\t**\tMake adjustments to the previous node.  If the pointer\n\t**\tto the previous node is NULL then this indicates the\n\t**\tfirst node in the list and thus the chain pointer needs\n\t**\tto be updated instead.\n\t*/\n\tif (node->Prev) {\n\t\tother = node->Prev;\n\t\tother->Next = node->Next;\n\t} else {\n\t\t*chain = node->Next;\n\t}\n\n\tif (node->Next) {\n\t\tother = node->Next;\n\t\tother->Prev = node->Prev;\n\t}\n}\n\n\n/***************************************************************************\n * MemNode_Insert -- Inserts a node into a cache chain.                    *\n *                                                                         *\n *    This routine is used to add a node to a cache chain.  Since nodes    *\n *    do not contain double links, they must be placed in sequence.        *\n *                                                                         *\n * INPUT:   pool     -- Pointer to memory pool (must be in real memory).   *\n *                                                                         *\n *          freechain-- Is the node to be inserted into the free chain?    *\n *                                                                         *\n *          node     -- Pointer to the node to insert.                     *\n *                                                                         *\n *          size     -- Size of the memory block (in paragraphs).          *\n *                                                                         *\n *          id       -- The ID number to associate with this block.        *\n *                                                                         *\n *          merge    -- Merge inserted block with adjacent blocks.         *\n *                                                                         *\n * OUTPUT:  return                                                         *\n *                                                                         *\n * WARNINGS:   This is a support routine.                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void MemNode_Insert(MemPool_Type *pool, int freechain, MemChain_Type *node, unsigned int size, unsigned long id, int merge)\n{\n\tMemChain_Type \t**chain;\t\t\t// Pointer to chain that will be linked.\n\tMemChain_Type \t*prev,\t\t\t// Successor node pointer.\n\t\t\t\t\t\t*next;\t\t\t// Predecessor node pointer.\n\tint\t\t\t\tdoit=TRUE;\t\t// Link the node into the list.\n\n\n\t/*\n\t**\tDetermine if the parameters are valid.\n\t*/\n\tif (!pool || !node || !size) return;\n\n\t/*\n\t**\tSetup working pointer for the particular chain desired.\n\t*/\t\n\tif (freechain) {\n\t\tchain = &pool->FreeChain;\n\t} else {\n\t\tchain = &pool->UsedChain;\n\t}\n\n\t/*\n\t**\tHandle the \"no node in list\" condition (easiest).\n\t*/\n\tif (!*chain) {\n\t\tnode->Next = NULL;\n\t\tnode->Prev = NULL;\n\t\tnode->Size = size;\n\t\tnode->Time = (unsigned short)(TickCount.Time() >> 4);\n\t\tnode->ID = id;\n\t\t*chain = node;\n\t\treturn;\n\t}\n\n\t/*\n\t**\tSweep through the memory chain looking for a likely spot\n\t**\tto insert the new node.  It will stop with \"next\" pointing\n\t**\tto the node to come after the block to be inserted and \"prev\"\n\t** will point to the node right before.\n\t*/\n\tprev = NULL;\n\tnext = *chain;\n\twhile (next && (next < node)) {\n\n\t\t/*\n\t\t**\tMove up the memory chain.\n\t\t*/\n\t\tprev = next;\n\t\tnext = next->Next;\n\t}\n\n\t/*\n\t**\tCoallescing of adjacent blocks (if requested).\n\t*/\n\tif (merge) {\n\t\t\n\t\t/*\n\t\t**\tIf the previous block is touching the block to insert\n\t\t**\tthen merely adjust the size of the previous block and\n\t\t**\tthat is all that is necessary.\n\t\t*/\n\t\tif (prev) {\n\t\t\tif (((char *)prev + ((long)prev->Size << 4)) == ((char *) node)) {\n\t\t\t\tprev->Size += size;\n\t\t\t\tsize = prev->Size;\n\t\t\t\tnode = prev;\n\t\t\t\tprev = prev->Prev;\n\t\t\t\tdoit = FALSE;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf the following block is touching the block to insert\n\t\t**\tthen remove the following block and increase the size of\n\t\t**\tthe original insertion block by the size of the other\n\t\t**\tblock.\n\t\t*/\n\t\tif (next) {\n\t\t\tif (((char *)node + ((long)size << 4)) == (char *)next) {\n\t\t\t\t\n\t\t\t\tif (!doit) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the node was already merged with the previous block\n\t\t\t\t\t**\tthen merely increase the previous block's size\n\t\t\t\t\t**\tand adjust it's next pointer appropriately.\n\t\t\t\t\t*/\n\t\t\t\t\tnode->Size += next->Size;\n\t\t\t\t\tnode->Next = next->Next;\n\t\t\t\t\tnext = next->Next;\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIncrease the size of the current block and adjust\n\t\t\t\t\t**\tthe \"next\" pointer so that it gets fixed up\n\t\t\t\t\t**\taccordingly.\n\t\t\t\t\t*/\n\t\t\t\t\tsize += next->Size;\n\t\t\t\t\tnext = next->Next;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n#if DEBUG_FILL\n\tif (doit) {\n\t\tmemset(node + 1, 0xFF, (size - 1) << 4);\n\t} else {\n\t\tmemset(node + 1, 0xFF, (node->Size - 1) << 4);\n\t}\n#endif\n\n\t/*\n\t**\tFixup the node pointers.\n\t*/\n\tif (prev) {\n\t\tprev->Next = node;\n\t}else{\n\t\t*chain = node;\n\t}\n\n\tif (next) {\n\t \tnext->Prev = node;\n\t}\n\n\tif (doit) {\n\t\tnode->Prev = prev;\n\t\tnode->Next = next;\n\t\tnode->Size = size;\n\t\tnode->Time = (unsigned short)(TickCount.Time() >> 4);\n\t\tnode->ID = id;\n\t}\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "WWFLAT32/MEM/OLD/MEMFLAG.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory System                            *\n *                                                                         *\n *                    File Name : MEMFLAG.H                                *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : April 4, 1994                            *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef MEMFLAG_H\n#define MEMFLAG_H\n// Memory Flags\n/*\n**\tMemory allocation flags.  These are the flags that are passed into Alloc\n**\tin order to control the type of memory allocated.\n*/\ntypedef enum {\n\tMEM_NORMAL = 0x0000,\t\t// Default memory (normal).\n\tMEM_NEW\t  = 0x0001,\t\t// Called by the operator new and was overloaded.\n\tMEM_CLEAR  = 0x0002,\t\t// Clear memory before returning.\n\tMEM_REAL   = 0x0004,\t\t// Clear memory before returning.\n\tMEM_TEMP   = 0x0008,\t\t// Clear memory before returning.\n\tMEM_LOCK   = 0x0010,\t\t// Lock the memory that we allocated\n} MemoryFlagType;\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: ALLOC.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid * operator new(size_t size, MemoryFlagType flag);\nvoid * operator new[] (size_t size, MemoryFlagType flag);\nvoid\t*Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags);\nvoid\tFree(void const *pointer);\nvoid\tDPMI_Lock(VOID const *ptr, long const size);\nvoid\tDPMI_Unlock(void const *ptr, long const size);\nvoid\t*Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes);\nlong\tRam_Free(MemoryFlagType flag);\nlong\tHeap_Size(MemoryFlagType flag);\nlong\tTotal_Ram_Free(MemoryFlagType flag);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MEM_COPY.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\textern void Mem_Copy(void const *source, void *dest, unsigned long bytes_to_copy);\n\n#ifdef __cplusplus\n}\n#endif\n\n\ninline void *Add_Long_To_Pointer(void const *ptr, long size) \n{\n \treturn ((void *) ( (char const *) ptr + size));\n}\n\nextern void (*Memory_Error)(void);\n\nextern unsigned long MinRam;\t\t// Record of least memory at worst case.\nextern unsigned long MaxRam;\t\t// Record of total allocated at worst case.\n\n\n#endif\n\n\n"
  },
  {
    "path": "WWFLAT32/MEM/OLD/MEM_COPY.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : MEM_COPY.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott Bowen\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : September 8, 1994\t[IML]              *\n;*                  Ported to watcom c32 : 01/03/96     [JRJ]                                                                        *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Mem_Copy -- Copies from one pointer to another.                       *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nLOCALS ??\n\n\n;******************************************************************************\n; Much testing was done to determine that only when there are 14 or more bytes\n; being copied does it speed the time it takes to do copies in this algorithm.\n; For this reason and because 1 and 2 byte copies crash, is the special case\n; used.  SKB 4/21/94.  Tested on 486 66mhz.\nOPTIMAL_BYTE_COPY\tequ\t14\n\n\n;******************************************************************************\n; External declares so these functions can be called\n;\nGLOBAL \tMem_Copy\t: NEAR\nGLOBAL  Largest_Mem_Block : near\n\nCODESEG\n\n\n;***************************************************************************\n;* MEM_COPY -- Copies from one pointer to another.                         *\n;* This routine copies bytes from source to dest.  It takes care of\t   *\n;* overlapped memory, and unsigned long copies.\t\t\t\t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/18/1994 SKB : Created.                                             *\n;*=========================================================================*\n; void Mem_Copy(void *source, void *dest, unsigned long bytes_to_copy);\n\n\nPROC Mem_Copy \tC near \n\tUSES\tecx , esi , edi , ebx\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tbytes:DWORD\n\t\t\n;********************************* Setup ******************************************\n\tcld\n\tmov\tesi,[source]\n\tmov\tedi,[dest]\n\tmov\tecx,[bytes]\t; get number of bytes to copy.\t\n\n     ; check pointers for singularities\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tje\t??done\t\t; No sence in copying the same pointer.\t\n\tor\tesi,0\n\tjz\t??done\n\tor\tedi,0\n\tjz\t??done\n\n\tcmp\tecx,OPTIMAL_BYTE_COPY  ; see notes above about equate.\n\tjge\t??normal      \t       ; If >= MAX(2,OPTIMAL_BYTE_COPY), do normal dword copy.\n\n;******************************** Special case <= 2 *******************************\n;\n; This section must be called for bytes <= 2 since the other case will crash.  It\n; optionally uses OPTIMAL_BYTE_COPY for the cut off point.  This is because after\n; extensive testing, it was proved that only at that point (14 or more bytes) does\n; it become quicker to use the dword copy method.\n\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tjge\t??do_move\t; if source greater do forward copy.\n\tlea\tesi,[esi+ecx-1]\n\tstd\t\t\t; Opps, wrong, force the pointers to decrement.\n\tlea\tedi,[edi+ecx-1]\n??do_move:\n\trep\tmovsb\t\t; move the one or two bytes.\n\tcld\n??done:\n\tret\n\n;************************** back or forth, that is the question *******************\n\n??normal:\n\tmov\tebx,ecx\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tjge\t??forward\t; if source greater do forward copy.\n\n;********************************* Backward ***************************************\n??backward:\n\tlea\tecx,[edi+ebx]\n\tstd\n\tlea\tedi,[edi+ebx-1]\n\tand\tecx,3\t\t; Get non aligned bytes.\n\tlea\tesi,[esi+ebx-1]\n\tsub\tebx,ecx\t\t; remove that from the total size to be copied later.\n\trep\tmovsb\t\t; do the copy.\n\tsub\tesi,3\n\tmov\tecx,ebx\t\t; Get number of bytes left.\n \tsub\tedi,3\n\tshr\tecx,2\t\t; Do 4 bytes at a time.\n\trep\tmovsd\t\t; do the dword copy.\n\tmov\tecx,ebx\n\tadd\tesi,3\n\tadd\tedi,3\n\tand\tecx,03h\n\trep\tmovsb\t\t; finnish the remaining bytes.\n\tcld\n\tret\n\n;********************************* Forward ***************************************\n??forward:\n\tcld\n\tmov\tecx,edi\t\t; get destination pointer.\t\n\tneg\tecx\n\tand\tecx,3\t\t; Get non aligned bytes.\n\tsub\tebx,ecx\t\t; remove that from the total size to be copied later.\n\trep\tmovsb\t\t; do the copy.\n\tmov\tecx,ebx\t\t; Get number of bytes left.\n\tshr\tecx,2\t\t; Do 4 bytes at a time.\n\trep\tmovsd\t\t; do the dword copy.\n\tmov\tecx, ebx\n\tand\tecx,03h\n\trep\tmovsb\t\t; finnish the remaining bytes.\n\tret\n\nENDP\tMem_Copy\n\nPROC Largest_Mem_Block \tC near \n\tuses\tesi , edi , ebx , ecx , edx\n\tlocal\tmem_struct : dword : 16\n\n\tmov\teax , 0500h\n\tlea\tedi , [ mem_struct ]\n\tint\t31h\n\tmov\teax , [ mem_struct ]\n\n\tret\nENDP Largest_Mem_Block\n\nEND\n\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/MEM/OLD/NEWDEL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory system.                           *\n *                                                                         *\n *                    File Name : NEWDEL.CPP                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : June 21, 1994                            *\n *                                                                         *\n *                  Last Update : July 17, 1995   [PWG]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   operator NEW -- Overides the global new function.                     *\n *   operator delete -- Overides the global delete function.               *\n *   operator NEW[] -- Overides the array version of new.                  *\n *   operator delete[] -- Overides the array version of delete[]           *\n *    --                                                                   *\n *   OPERATOR NEW -- New opperator which takes a MEM_FLAG                  *\n *   OPERATOR NEW[] -- Global NEW[] which takes MEM_FLAG                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwmem.h\"\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * OPERATOR NEW -- Overides the global new function.                       *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid * operator new(size_t size) \n{\n\treturn (Alloc((unsigned long) size, MEM_NEW));\n}\n\n\n/***************************************************************************\n * OPERATOR NEW[] -- Overides the array version of new.                    *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid * operator new[](size_t size) \n{\n\treturn (Alloc((unsigned long) size, MEM_NEW));\n}\n \n/***************************************************************************\n * OPERATOR NEW -- New opperator which takes a MEM_FLAG                    *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid * operator new(size_t size, MemoryFlagType flag) \n{\n\treturn(Alloc(size, (MemoryFlagType)(flag|MEM_NEW)));\n}\n\n/***************************************************************************\n * OPERATOR NEW[] -- Global NEW[] which takes MEM_FLAG                     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid * operator new[] (size_t size, MemoryFlagType flag)\n{\n\treturn(Alloc(size, (MemoryFlagType)(flag|MEM_NEW)));\n}\n\n/***************************************************************************\n * OPERATOR DELETE -- Overides the global delete function.                 *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid operator delete(void *ptr) \n{\n\tFree(ptr);\n}\n\n/***************************************************************************\n * OPERATOR DELETE[] -- Overides the array version of delete[]           \t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/20/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid operator delete[](void *ptr) \n{\n\tFree(ptr);\n}\n\n\n\n"
  },
  {
    "path": "WWFLAT32/MEM/OLD/WWMEM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory System                            *\n *                                                                         *\n *                    File Name : MEM.H                                    *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : April 4, 1994                            *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWMEM_H\n#define WWMEM_H\n\n#include \"wwstd.h\"\n#include \"new.h\"\n#include \"memflag.h\"\n\n// Defines\n//==============\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MEM.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint  Mem_Init(void *buffer, long size);\nvoid *Mem_Alloc(void *poolptr, long lsize, unsigned long id);\nint  Mem_Free(void *poolptr, void *buffer);\nvoid Mem_Reference(void *node);\nvoid Mem_Lock_Block(void *node);\nvoid Mem_In_Use(void *node);\nvoid *Mem_Find(void *poolptr, unsigned long id);\nunsigned long Mem_Get_ID(void *node);\nvoid *Mem_Find_Oldest(void *poolptr);\nvoid *Mem_Free_Oldest(void *poolptr);\nlong Mem_Pool_Size(void *poolptr);\nlong Mem_Avail(void *poolptr);\nlong Mem_Largest_Avail(void *poolptr);\nvoid Mem_Cleanup(void *poolptr);\n\n\n#endif\n\u001a\n"
  },
  {
    "path": "WWFLAT32/MEM/OLD/WWMEM.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Memory System                            *\n;*                                                                         *\n;*                    File Name : WWMEM.INC                                *\n;*                                                                         *\n;*                   Programmer : Ian M. Leslie                            *\n;*                                                                         *\n;*                   Start Date : August 11, 1994                          *\n;*                                                                         *\n;*                  Last Update : August 17, 1994   [IML]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nMEM_NORMAL EQU 0000h\t\t; Default memory (normal).\nMEM_NEW\t   EQU 0001h\t\t; Called by the operator new and was overloaded.\nMEM_CLEAR  EQU 0002h \t\t;\n\nGLOBAL\t\t@Alloc$qul14MemoryFlagType:PROC\nGLOBAL\t\t@Free$qpv:PROC\n"
  },
  {
    "path": "WWFLAT32/MEM/WWMEM.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory System                            *\n *                                                                         *\n *                    File Name : MEM.H                                    *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : April 4, 1994                            *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWMEM_H\n#define WWMEM_H\n\n#include \"wwstd.h\"\n#include \"new.h\"\n#include \"memflag.h\"\n\n// Defines\n//==============\n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: MEM.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint  Mem_Init(void *buffer, long size);\nvoid *Mem_Alloc(void *poolptr, long lsize, unsigned long id);\nint  Mem_Free(void *poolptr, void *buffer);\nvoid Mem_Reference(void *node);\nvoid Mem_Lock_Block(void *node);\nvoid Mem_In_Use(void *node);\nvoid *Mem_Find(void *poolptr, unsigned long id);\nunsigned long Mem_Get_ID(void *node);\nvoid *Mem_Find_Oldest(void *poolptr);\nvoid *Mem_Free_Oldest(void *poolptr);\nlong Mem_Pool_Size(void *poolptr);\nlong Mem_Avail(void *poolptr);\nlong Mem_Largest_Avail(void *poolptr);\nvoid Mem_Cleanup(void *poolptr);\n\n\n#endif\n\u001a\n"
  },
  {
    "path": "WWFLAT32/MEM/WWMEM.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Memory System                            *\n;*                                                                         *\n;*                    File Name : WWMEM.INC                                *\n;*                                                                         *\n;*                   Programmer : Ian M. Leslie                            *\n;*                                                                         *\n;*                   Start Date : August 11, 1994                          *\n;*                                                                         *\n;*                  Last Update : August 17, 1994   [IML]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nMEM_NORMAL EQU 0000h\t\t; Default memory (normal).\nMEM_NEW\t   EQU 0001h\t\t; Called by the operator new and was overloaded.\nMEM_CLEAR  EQU 0002h \t\t;\n\nGLOBAL\t\t@Alloc$qul14MemoryFlagType:PROC\nGLOBAL\t\t@Free$qpv:PROC\n"
  },
  {
    "path": "WWFLAT32/MISC/ASM.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : CRC.ASM                                  *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : June 12, 1992                            *\n;*                                                                         *\n;*                  Last Update : February 10, 1995 [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\n;MODEL USE32 FLAT\nMODEL\tLARGE\n\nGLOBAL\tC Calculate_CRC:FAR\n\n\tCODESEG\n\n; LONG Calculate_CRC(VOID *buffer, LONG length);\n\tPROC\tCalculate_CRC C far\n\tUSES \tesi,ebx,ecx\n\n\tARG\tbuffer:DWORD\n\tARG\tlength:DWORD\n\n\tLOCAL\tcrc:DWORD\n\n\t; Load pointer to data block.\n\tmov\t[crc],0\n\tpushf\n\tmov\tesi,[buffer]\n\tcld\n\n\t; Clear CRC to default (NULL) value.\n\txor\tebx,ebx\n\n\t; Fetch the length of the data block to CRC.\n\tmov\tecx,[length]\n\tjecxz\tshort ??fini\n\n\t; Prepare the length counters.\n\tmov\tedx,ecx\n\tand\tdl,011b\n\tshr\tecx,2\n\n\t; Perform the bulk of the CRC scanning.\n\tjecxz\tshort ??remainder\n??accumloop:\n\tlodsd\n\trol\tebx,1\n\tadd\tebx,eax\n\tloop\t??accumloop\n\n\t; Handle the remainder bytes.\n??remainder:\n\tor\tdl,dl\n\tjz\tshort ??fini\n\tmov\tecx,edx\n\txor\teax,eax\n\n\tand \tecx,0FFFFh\n\tpush\tecx\n??nextbyte:\n\tlodsb\n\tror\teax,8\n\tloop\t??nextbyte\n\tpop\tecx\n\tneg\tecx\n\tadd\tecx,4\n\tshl\tecx,3\n\tror\teax,cl\n\n;??nextbyte:\n;\tshl\teax,8\n;\tlodsb\n;\tloop\t??nextbyte\n\trol\tebx,1\n\tadd\tebx,eax\n\n??fini:\n\tmov\t[crc],ebx\n\tpopf\n\tmov\tdx,[WORD PTR crc+2]\n\tmov\tax,[WORD PTR crc]\n\tret\n\n\tENDP\tCalculate_CRC\n\n\tEND\n\n"
  },
  {
    "path": "WWFLAT32/MISC/ASM.ASM.BAK",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : CRC.ASM                                  *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : June 12, 1992                            *\n;*                                                                         *\n;*                  Last Update : February 10, 1995 [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\n;MODEL USE32 FLAT\nMODEL\tLARGE\n\nGLOBAL\tC Calculate_CRC:FAR\n\n\tCODESEG\n\n; LONG Calculate_CRC(VOID *buffer, LONG length);\n\tPROC\tCalculate_CRC C far\n\tUSES \tesi,ebx,ecx\n\n\tARG\tbuffer:DWORD\n\tARG\tlength:DWORD\n\n\tLOCAL\tcrc:DWORD\n\n\t; Load pointer to data block.\n\tmov\t[crc],0\n\tpushf\n\tmov\tesi,[buffer]\n\tcld\n\n\t; Clear CRC to default (NULL) value.\n\txor\tebx,ebx\n\n\t; Fetch the length of the data block to CRC.\n\tmov\tecx,[length]\n\tjecxz\tshort ??fini\n\n\t; Prepare the length counters.\n\tmov\tedx,ecx\n\tand\tdl,011b\n\tshr\tecx,2\n\n\t; Perform the bulk of the CRC scanning.\n\tjecxz\tshort ??remainder\n??accumloop:\n\tlodsd\n\trol\tebx,1\n\tadd\tebx,eax\n\tloop\t??accumloop\n\n\t; Handle the remainder bytes.\n??remainder:\n\tor\tdl,dl\n\tjz\tshort ??fini\n\tmov\tecx,edx\n\txor\teax,eax\n\n\tand \tecx,0FFFFh\n\tpush\tecx\n??nextbyte:\n\tlodsb\n\tror\teax,8\n\tloop\t??nextbyte\n\tpop\tecx\n\tneg\tecx\n\tadd\tecx,4\n\tshl\tecx,3\n\tror\teax,cl\n\n;??nextbyte:\n;\tshl\teax,8\n;\tlodsb\n;\tloop\t??nextbyte\n\trol\tebx,1\n\tadd\tebx,eax\n\n??fini:\n\tmov\t[crc],ebx\n\tpopf\n\tmov\tdx,[WORD PTR crc+2]\n\tmov\tax,[WORD PTR crc]\n\tret\n\n\tENDP\tCalculate_CRC\n\n\tEND\n\n"
  },
  {
    "path": "WWFLAT32/MISC/CLIPRECT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Support Library                          *\n;*                                                                         *\n;*                    File Name : cliprect.asm                             *\n;*                                                                         *\n;*                   Programmer : Julio R Jerez                            *\n;*                                                                         *\n;*                   Start Date : Mar, 2 1995                              *\n;*                                                                         *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* int Clip_Rect ( int * x , int * y , int * dw , int * dh , \t\t   *\n;*\t       \t   int width , int height ) ;          \t\t\t   *\n;* int Confine_Rect ( int * x , int * y , int * dw , int * dh , \t   *\n;*\t       \t      int width , int height ) ;          \t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\t Clip_Rect\t:NEAR\nGLOBAL\t Confine_Rect\t:NEAR\n\nCODESEG\n\n;***************************************************************************\n;* Clip_Rect -- clip a given rectangle against a given window\t\t   *\n;*                                                                         *\n;* INPUT:   &x , &y , &w , &h  -> Pointer to rectangle being clipped       *\n;*          width , height     -> dimension of clipping window             *\n;*                                                                         *\n;* OUTPUT: a) Zero if the rectangle is totally contained by the \t   *\n;*\t      clipping window.\t\t\t\t\t\t   *\n;*\t   b) A negative value if the rectangle is totally outside the     *\n;*            the clipping window\t\t\t\t\t   *\n;*\t   c) A positive value if the rectangle\twas clipped against the\t   *\n;*\t      clipping window, also the values pointed by x, y, w, h will  *\n;*\t      be modified to new clipped values\t \t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*   05/03/1995 JRJ : added comment                                        *\n;*=========================================================================*\n; int Clip_Rect (int* x, int* y, int* dw, int* dh, int width, int height);          \t\t\t   *\n\n\tPROC\tClip_Rect C near\n\tuses\tebx,ecx,edx,esi,edi\n\targ\tx:dword\n\targ\ty:dword\n\targ\tw:dword\n\targ\th:dword\n\targ\twidth:dword\n\targ\theight:dword\n\n;This Clipping algorithm is a derivation of the very well known\n;Cohen-Sutherland Line-Clipping test. Due to its simplicity and efficiency\n;it is probably the most commontly implemented algorithm both in software \n;and hardware for clipping lines, rectangles, and convex polygons against \n;a rectagular clipping window. For reference see \n;\"COMPUTER GRAPHICS principles and practice by Foley, Vandam, Feiner, Hughes\n; pages 113 to 177\".\n; Briefly consist in computing the Sutherland code for both end point of\n; the rectangle to find out if the rectangle is:\n; - trivially accepted (no further clipping test, return the oroginal data) \n; - trivially rejected (return with no action, return error code)\n; - retangle must be iteratively clipped again edges of the clipping window\n;   and return the clipped rectangle\n\n\t; get all four pointer into regisnters\n\tmov\tesi,[x]\t\t; esi = pointer to x\n\tmov\tedi,[y]\t\t; edi = pointer to x\n\tmov\teax,[w]\t\t; eax = pointer to dw\n\tmov\tebx,[h]\t\t; ebx = pointer to dh\n\n\t; load the actual data into reg\n\tmov\tesi,[esi]\t; esi = x0\n\tmov\tedi,[edi]\t; edi = y0\n\tmov\teax,[eax]\t; eax = dw\n\tmov\tebx,[ebx]\t; ebx = dh\n\n\t; create a wire frame of the type [x0,y0] , [x1,y1]\n\tadd\teax,esi\t\t; eax = x1 = x0 + dw\n\tadd\tebx,edi\t\t; ebx = y1 = y0 + dh\n\n\t; we start we suthenland code0 and code1 set to zero\n\txor \tecx,ecx\t\t; cl = sutherland boolean code0\n\txor \tedx,edx\t\t; dl = sutherland boolean code0\n\n\t; now we start computing the to suthenland boolean code for x0 , x1\n\tshld\tecx,esi,1\t; bit3 of code0 = sign bit of (x0 - 0)\n\tshld\tedx,eax,1 \t; bit3 of code1 = sign bit of (x1 - 0)\n\tsub\tesi,[width]\t; get the difference (x0 - (width + 1))\n\tsub\teax,[width]\t; get the difference (x1 - (width + 1))\n\tdec\tesi\t\t\n\tdec\teax\n\tshld\tecx,esi,1\t; bit2 of code0 = sign bit of (x0 - (width + 1))\n\tshld\tedx,eax,1\t; bit2 of code1 = sign bit of (x0 - (width + 1))\n\n\t; now we start computing the to suthenland boolean code for y0 , y1\n\tshld\tecx,edi,1   \t; bit1 of code0 = sign bit of (y0 - 0)\n\tshld\tedx,ebx,1\t; bit1 of code1 = sign bit of (y0 - 0)\n\tsub\tedi,[height]\t; get the difference (y0 - (height + 1))\n\tsub\tebx,[height]\t; get the difference (y1 - (height + 1))\n\tdec\tedi\n\tdec\tebx\n\tshld\tecx,edi,1\t; bit0 of code0 = sign bit of (y0 - (height + 1))\n\tshld\tedx,ebx,1\t; bit0 of code1 = sign bit of (y1 - (height + 1))\n\n\t; Bit 2 and 0 of cl and bl are complemented\n\txor\tcl,5\t\t; reverse bit2 and bit0 in code0\n\txor\tdl,5 \t\t; reverse bit2 and bit0 in code1\n\n\t; now perform the rejection test\n\tmov\teax,-1\t\t; set return code to false\n\tmov\tbl,cl \t\t; save code0 for future use\n\ttest\tdl,cl  \t\t; if any two pair of bit in code0 and code1 is set \n\tjnz\t??clip_out\t; then rectangle is outside the window\n\n\t; now perform the aceptance test\n\txor\teax,eax\t\t; set return code to true\t\n\tor\tbl,dl\t\t; if all pair of bits in code0 and code1 are reset\n\tjz\t??clip_out\t; then rectangle is insize the window.\t\t\t\t\t\t\t\t      '\n\n\t; we need to clip the rectangle iteratively\n\tmov\teax,-1\t\t; set return code to false\n\ttest\tcl,1000b\t; if bit3 of code0 is set then the rectangle\n\tjz\t??left_ok\t; spill out the left edge of the window\n\tmov\tedi,[x]\t\t; edi = a pointer to x0 \n\tmov\tebx,[w]\t\t; ebx = a pointer to dw\n\tmov\tesi,[edi]\t; esi = x0\n\tmov\t[dword ptr edi],0 ; set x0 to 0 \"this the left edge value\"\n\tadd\t[ebx],esi\t; adjust dw by x0, since x0 must be negative\n\n??left_ok:\n\ttest\tcl,0010b\t; if bit1 of code0 is set then the rectangle\n\tjz\t??bottom_ok\t; spill out the bottom edge of the window\n\tmov\tedi,[y]\t\t; edi = a pointer to y0 \n\tmov\tebx,[h]\t\t; ebx = a pointer to dh\n\tmov\tesi,[edi]\t; esi = y0\n\tmov\t[dword ptr edi],0 ; set y0 to 0 \"this the bottom edge value\"\n\tadd\t[ebx],esi\t; adjust dh by y0, since y0 must be negative\n\n??bottom_ok:\n\ttest\tdl,0100b\t; if bit2 of code1 is set then the rectangle\n\tjz\t??right_ok\t; spill out the right edge of the window\n\tmov\tedi,[w] \t; edi = a pointer to dw\n\tmov\tesi,[x]\t\t; esi = a pointer to x\n\tmov\tebx,[width]\t; ebx = the width of the window\n\tsub\tebx,[esi] \t; the new dw is the difference (width-x0)\n\tmov\t[edi],ebx\t; adjust dw to (width - x0)\n\tjle\t??clip_out\t; if (width-x0) = 0 then the clipped retangle\n\t\t\t\t; has no width we are done\n??right_ok:\n\ttest\tdl,0001b\t; if bit0 of code1 is set then the rectangle\n\tjz\t??clip_ok\t; spill out the top edge of the window\n\tmov\tedi,[h] \t; edi = a pointer to dh\n\tmov\tesi,[y]\t\t; esi = a pointer to y0\n\tmov\tebx,[height]\t; ebx = the height of the window\n\tsub\tebx,[esi] \t; the new dh is the difference (height-y0)\n\tmov\t[edi],ebx\t; adjust dh to (height-y0)\n\tjle\t??clip_out\t; if (width-x0) = 0 then the clipped retangle\n\t\t\t\t; has no width we are done\n??clip_ok:\n\tmov\teax,1  \t; signal the calling program that the rectangle was modify     \n??clip_out:\n\tret\n\tENDP\tClip_Rect\n\n\n;***************************************************************************\n;* Confine_Rect -- clip a given rectangle against a given window\t   *\n;*                                                                         *\n;* INPUT:   &x,&y,w,h    -> Pointer to rectangle being clipped       *\n;*          width,height     -> dimension of clipping window             *\n;*                                                                         *\n;* OUTPUT: a) Zero if the rectangle is totally contained by the \t   *\n;*\t      clipping window.\t\t\t\t\t\t   *\n;*\t   c) A positive value if the rectangle\twas shifted in position    *\t   \n;*\t      to fix inside the clipping window, also the values pointed   *\n;*\t      by x, y, will adjusted to a new values\t \t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*  NOTE:  this function make not attempt to verify if the rectangle is\t   *\t\n;*\t   bigger than the clipping window and at the same time wrap around*\n;*\t   it. If that is the case the result is meaningless\t\t   *\n;*=========================================================================*\n; int Confine_Rect (int* x, int* y, int dw, int dh, int width, int height);          \t\t\t   *\n\n\tPROC\tConfine_Rect C near\n\tuses\tebx, esi,edi\n\targ\tx:dword\n\targ\ty:dword\n\targ\tw:dword\n\targ\th:dword\n\targ\twidth :dword\n\targ\theight:dword\n\n\txor\teax,eax\n\tmov\tebx,[x]\n\tmov\tedi,[w]\n\n\tmov\tesi,[ebx]\n\tadd\tedi,[ebx] \n\n\tsub\tedi,[width]\n\tneg\tesi\n\tdec\tedi\n\n\ttest\tesi,edi\n\tjl\t??x_axix_ok\n\tmov\teax,1\n\n\ttest\tesi,esi\n\tjl\t??shift_right\n\tmov\t[dword ptr ebx],0\n\tjmp\t??x_axix_ok\n??shift_right:\n\tinc\tedi\n\tsub\t[ebx],edi\n??x_axix_ok:\n\tmov\tebx,[y]\n\tmov\tedi,[h]\n\n\tmov\tesi,[ebx]\n\tadd\tedi,[ebx] \n\n\tsub\tedi,[height]\n\tneg\tesi\n\tdec\tedi\n\n\ttest\tesi,edi\n\tjl\t??confi_out\n\tmov\teax,1\n\n\ttest\tesi,esi\n\tjl\t??shift_top\n\tmov\t[dword ptr ebx],0\n\tret\n??shift_top:\n\tinc\tedi\n\tsub\t[ebx],edi\n??confi_out:\n\tret\n\n\tENDP\tConfine_Rect\n\n \tEND\n\n"
  },
  {
    "path": "WWFLAT32/MISC/CRC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : CRC.ASM                                  *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : June 12, 1992                            *\n;*                                                                         *\n;*                  Last Update : February 10, 1995 [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\tCalculate_CRC\t:NEAR\n\n\tCODESEG\n\n; LONG Calculate_CRC(VOID *buffer, LONG length);\n\tPROC\tCalculate_CRC C near\n\tUSES \tesi\n\n\tARG\tbuffer:DWORD\n\tARG\tlength:DWORD\n\n\tLOCAL\tcrc:DWORD\n\n\t; Load pointer to data block.\n\tmov\t[crc],0\n\tpushad\n\tmov\tesi,[buffer]\n\tcld\n\n\t; Clear CRC to default (NULL) value.\n\txor\tebx,ebx\n\n\t; Fetch the length of the data block to CRC.\n\tmov\tecx,[length]\n\tjecxz\tshort ??fini\n\n\t; Prepare the length counters.\n\tmov\tedx,ecx\n\tand\tdl,011b\n\tshr\tecx,2\n\n\t; Perform the bulk of the CRC scanning.\n\tjecxz\tshort ??remainder\n??accumloop:\n\tlodsd\n\trol\tebx,1\n\tadd\tebx,eax\n\tloop\t??accumloop\n\n\t; Handle the remainder bytes.\n??remainder:\n\tor\tdl,dl\n\tjz\tshort ??fini\n\tmov\tecx,edx\n\txor\teax,eax\n\n\tand \tecx,0FFFFh\n\tpush\tecx\n??nextbyte:\n\tlodsb\n\tror\teax,8\n\tloop\t??nextbyte\n\tpop\tecx\n\tneg\tecx\n\tadd\tecx,4\n\tshl\tecx,3\n\tror\teax,cl\n\n;??nextbyte:\n;\tshl\teax,8\n;\tlodsb\n;\tloop\t??nextbyte\n\trol\tebx,1\n\tadd\tebx,eax\n\n??fini:\n\tmov\t[crc],ebx\n\tpopad\n\tmov\teax,[crc]\n\tret\n\n\tENDP\tCalculate_CRC\n\n\tEND\n\u001a"
  },
  {
    "path": "WWFLAT32/MISC/DELAY.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : DELAY.C                                  *\n *                                                                         *\n *                   Programmer : Christopher Yates                        *\n *                                                                         *\n *                  Last Update : 27 March, 1991   [CY]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"wwstd.h\"\n#include <timer.h>\n\nvoid Delay(int duration)\n{\n\tunsigned long count;\n\tTimerClass timer(BT_SYSTEM,TRUE);\n\n\twhile (duration--) {\n\t\tcount = timer.Time() + 1L;\n\t\twhile (count >= timer.Time()) {\n\t\t\t;\n\t\t}\n\t}\n\n#if(FALSE)\n\twhile (duration--)\n\t\tWait_Vert_Blank(VertBlank);\n#endif\n}\n\n#if(FALSE)\nvoid Vsync()\n{\n\tWait_Vert_Blank(VertBlank);\n}\n#endif\n\u001a"
  },
  {
    "path": "WWFLAT32/MISC/DETPROC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/system/rcs/detproc.asm 1.1 1994/04/18 09:13:53 jeff_wilson Exp $\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : PROC.ASM                                 *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : May 11, 1993                             *\n;*                                                                         *\n;*                  Last Update : May 11, 1993   [JLB]                     *\n;*                                                                         *\n;*  Converted to 32Bit -- JAW                                              *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL \t\tProcessor          :NEAR\n\t\t    \n\nPROC_80386\tequ\t0\nPROC_80486\tequ\t1\nPROC_80586\tequ\t2\n\nDATASEG\ncpu_id_586\tdw\t0\n\t\t\t\nCODESEG\n\nPROC\tProcessor C near\n\tUSES ebx\n\tLOCAL\tptype:WORD\n\n\tpushfd\t\n\n; At least a 386 -- check for 486.\n\tmov\t[WORD PTR ptype],PROC_80386\t; 80386\n\tpushfd\n\tpop\teax\n\tmov\tebx,eax\n\txor\teax,40000h\n\tpush\teax\n\tpopfd\t\n\tpushfd\t\n\tpop\teax\n\txor\teax,ebx\n\tje\tshort ??fini\n\n; At least a 486 -- check for 586(Pentium)\n\tmov\t[ptype],PROC_80486\t; 80486\n\t\t\t       \n\t; Some machines have a problem with this fLAG\n\t; and thus make us think they are a 586 but they are\n\t; really a 486. A possible way around this is to \n\t; capture the Illegal instruction vector, then  do\n\t; an instruction only available on the 586.\n\t\n\t; for now this is just commented out\n\tpushfd\t\n\tpop\teax\n\tmov\tebx,eax\n\txor\teax,200000h\n\tpush\teax\n\tpopfd\t\n\tpushfd\t\n\tpop\teax\n\txor\teax,ebx\n\tje\tshort ??fini\n\n; At least a 586(Pentium) -- check for higher.\n\tmov\t[ptype],PROC_80586\t; 80486\n;\tmov\teax,1\t       \n;\tDW\t0fA2h\t\t; CPUID opcode.\n;\tshr\tax,8\n;\tand\tax,0fh\n;\tinc\tax\n;\tinc\tax\n;\tmov\t[cpu_id_586],ax\n\n; Final cleanup and exit.\n??fini:\n\tpopfd\t\n\tsub\teax,eax\n\tmov\tax,[ptype]\n\tret\t\n\nENDP\tProcessor\n\nEND\n\u001a"
  },
  {
    "path": "WWFLAT32/MISC/EXIT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 library source                   *\n *                                                                         *\n *                    File Name : EXIT.CPP                                 *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Exit -- Exit routine with message.                                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwstd.h\"\n#include \"misc.h\"\n\n#include <time.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdarg.h>\n\n\n\n\n/***************************************************************************\n * EXIT -- Exit routine with message.                                      *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/03/1994 SKB : Created.                                             *\n *=========================================================================*/\nVOID cdecl Exit(INT errorval, const BYTE *message, ...)\n{\n\tva_list\t\targptr;\n\tBYTE\t\terrstring[256];\n\n\tProg_End();\n\n\tif (message && *message) {\n\t\tva_start (argptr, message);\n\t\tvsprintf ((char *)errstring, (const char *)message, argptr);\n\t\tva_end (argptr);\n\t\tprintf(errstring);\n\t}\n\n\t::exit(errorval);\n\n}\n\nvoid randomize\t( void ) \n{\n  srand ( time ( NULL ) ) ;\n}\n\n#if(0)\nULONG\trandom ( ULONG mod ) \n{\n  return rand () * mod / RAND_MAX ;\n}\n#endif\n"
  },
  {
    "path": "WWFLAT32/MISC/FACING16.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/source/rcs/./facing16.asm 1.10 1994/05/20 15:32:36 joe_bostic Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Support Library                          *\n;*                                                                         *\n;*                    File Name : FACING16.ASM                             *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : May 8, 1991                              *\n;*                                                                         *\n;*                  Last Update : February 6, 1995  [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Desired_Facing16 -- Converts coordinates into a facing number.        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\t Desired_Facing16\t:NEAR\n;\tINCLUDE\t\"wwlib.i\"\n\n\tDATASEG\n\n; 16 direction desired facing lookup table.  Build the index according\n; to the following bits:\n;\n; bit 4 = Is y2 < y1?\n; bit 3 = Is x2 < x1?\n; bit 2 = Is the ABS(x2-x1) < ABS(y2-y1)?\n; bit 1 = Is the lesser absolute difference very close to zero?\n; bit 0 = Is the lesser absolute difference very close to the greater dist?\nNewFacing16\tDB\t 3, 2, 4,-1, 1, 2,0,-1\n\t\tDB\t13,14,12,-1,15,14,0,-1\n\t\tDB\t 5, 6, 4,-1, 7, 6,8,-1\n\t\tDB\t11,10,12,-1, 9,10,8,-1\n\n\tCODESEG\n\n;***************************************************************************\n;* DESIRED_FACING16 -- Converts coordinates into a facing number.          *\n;*                                                                         *\n;*      This converts coordinates into a desired facing number that ranges *\n;*      from 0 to 15 (0 equals North and going clockwise).                 *\n;*                                                                         *\n;* INPUT:       x1,y1   -- Position of origin point.                       *\n;*                                                                         *\n;*              x2,y2   -- Position of target.                             *\n;*                                                                         *\n;* OUTPUT:      Returns desired facing as a number from 0 to 255 but       *\n;*              accurate to 22.5 degree increments.                        *\n;*                                                                         *\n;* WARNINGS:    If the two coordinates are the same, then -1 will be       *\n;*              returned.  It is up to you to handle this case.            *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/14/1991 JLB : Created.                                             *\n;*=========================================================================*\n; long Desired_Facing16(long x1, long y1, long x2, long y2);\n\n\tPROC\tDesired_Facing16 C near\n\tUSES\tebx, ecx, edx\n\n\tARG\tx1:DWORD\n\tARG\ty1:DWORD\n\tARG\tx2:DWORD\n\tARG\ty2:DWORD\n\n\txor\tebx,ebx\t\t\t; Index byte (built).\n\n\t; Determine Y axis difference.\n\tmov\tedx,[y1]\n\tmov\tecx,[y2]\n\tsub\tedx,ecx\t\t\t; DX = Y axis (signed).\n\tjns\tshort ??absy\n\tinc\tebx\t\t\t; Set the signed bit.\n\tneg\tedx\t\t\t; ABS(y)\n??absy:\n\n\t; Determine X axis difference.\n\tshl\tebx,1\n\tmov\teax,[x1]\n\tmov\tecx,[x2]\n\tsub\tecx,eax\t\t\t; CX = X axis (signed).\n\tjns\tshort ??absx\n\tinc\tebx\t\t\t; Set the signed bit.\n\tneg\tecx\t\t\t; ABS(x)\n??absx:\n\n\t; Determine the greater axis.\n\tcmp\tecx,edx\n\tjb\tshort ??dxisbig\n\txchg\tecx,edx\n??dxisbig:\n\trcl\tebx,1\t\t\t; Y > X flag bit.\n\n\t; Determine the closeness or farness of lesser axis.\n\tmov\teax,edx\n\tinc\teax\t\t\t; Round up.\n\tshr\teax,1\n\tinc\teax\t\t\t; Round up.\n\tshr\teax,1\t\t\t; 1/4 of greater axis.\n\n\tcmp\tecx,eax\n\trcl\tebx,1\t\t\t; Very close to major axis bit.\n\n\tsub\tedx,eax\n\tcmp\tedx,ecx\n\trcl\tebx,1\t\t\t; Very far from major axis bit.\n\n\txor\teax,eax\n\tmov\tal,[NewFacing16+ebx]\n\n\t; Normalize to 0..FF range.\n\tshl\teax,4\n\n\tret\n\n\tENDP\tDesired_Facing16\n\n\tEND\n\t\n\n\u001a\n\u001a"
  },
  {
    "path": "WWFLAT32/MISC/FACING8.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Support Library                          *\n;*                                                                         *\n;*                    File Name : FACING8.ASM                              *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : May 8, 1991                              *\n;*                                                                         *\n;*                  Last Update : February 6, 1995  [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Desired_Facing8 -- Determines facing to reach a position.             *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nGLOBAL\t Desired_Facing8\t:NEAR\n;\tINCLUDE\t\"wwlib.i\"\n\n\tDATASEG\n\n; 8 direction desired facing lookup table.  Build the index according\n; to the following bits:\n;\n; bit 3 = Is y2 < y1?\n; bit 2 = Is x2 < x1?\n; bit 1 = Is the ABS(x2-x1) < ABS(y2-y1)?\n; bit 0 = Is the facing closer to a major axis?\nNewFacing8\tDB\t1,2,1,0,7,6,7,0,3,2,3,4,5,6,5,4\n\n\tCODESEG\n\n;***************************************************************************\n;* DESIRED_FACING8 -- Determines facing to reach a position.               *\n;*                                                                         *\n;*    This routine will return with the most desirable facing to reach     *\n;*    one position from another.  It is accurate to a resolution of 0 to   *\n;*    7.                                                                   *\n;*                                                                         *\n;* INPUT:       x1,y1   -- Position of origin point.                       *\n;*                                                                         *\n;*              x2,y2   -- Position of target.                             *\n;*                                                                         *\n;* OUTPUT:      Returns desired facing as a number from 0..255 with an     *\n;*              accuracy of 32 degree increments.                          *\n;*                                                                         *\n;* WARNINGS:    If the two coordinates are the same, then -1 will be       *\n;*              returned.  It is up to you to handle this case.            *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1991 JLB : Documented.                                          *\n;*   08/08/1991 JLB : Same position check.                                 *\n;*   08/14/1991 JLB : New algorithm                                        *\n;*   02/06/1995 BWG : Convert to 32-bit                                    *\n;*=========================================================================*\n; long Desired_Facing8(long x1, long y1, long x2, long y2);\n\n\tPROC\tDesired_Facing8 C near\n\tUSES\tebx, ecx, edx\n\n\tARG\tx1:DWORD\n\tARG\ty1:DWORD\n\tARG\tx2:DWORD\n\tARG\ty2:DWORD\n\n\txor\tebx,ebx\t\t\t; Index byte (built).\n\n\t; Determine Y axis difference.\n\tmov\tedx,[y1]\n\tmov\tecx,[y2]\n\tsub\tedx,ecx\t\t\t; DX = Y axis (signed).\n\tjns\tshort ??absy\n\tinc\tebx\t\t\t; Set the signed bit.\n\tneg\tedx\t\t\t; ABS(y)\n??absy:\n\n\t; Determine X axis difference.\n\tshl\tebx,1\n\tmov\teax,[x1]\n\tmov\tecx,[x2]\n\tsub\tecx,eax\t\t\t; CX = X axis (signed).\n\tjns\tshort ??absx\n\tinc\tebx\t\t\t; Set the signed bit.\n\tneg\tecx\t\t\t; ABS(x)\n??absx:\n\n\t; Determine the greater axis.\n\tcmp\tecx,edx\n\tjb\tshort ??dxisbig\n\txchg\tecx,edx\n??dxisbig:\n\trcl\tebx,1\t\t\t; Y > X flag bit.\n\n\t; Determine the closeness or farness of lesser axis.\n\tmov\teax,edx\n\tinc\teax\t\t\t; Round up.\n\tshr\teax,1\n\n\tcmp\tecx,eax\n\trcl\tebx,1\t\t\t; Close to major axis bit.\n\n\txor\teax,eax\n\tmov\tal,[NewFacing8+ebx]\n\n\t; Normalize to 0..FF range.\n\tshl\teax,5\n\t\n\tret\n\n\tENDP\tDesired_Facing8\n\n\n\tEND\n\t\n\u001a"
  },
  {
    "path": "WWFLAT32/MISC/FACINGFF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Support Library                          *\n;*                                                                         *\n;*                    File Name : FACINGFF.ASM                             *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : May 8, 1991                              *\n;*                                                                         *\n;*                  Last Update : February 6, 1995  [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Desired_Facing256 -- Determines facing to reach a position.           *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\t Desired_Facing256\t:NEAR\n;\tINCLUDE\t\"wwlib.i\"\nINCLUDE \".\\gbuffer.inc\"\n\n\tCODESEG\n\n;***************************************************************************\n;* Desired_Facing256 -- Desired facing algorithm 0..255 resolution.        *\n;*                                                                         *\n;*    This is a desired facing algorithm that has a resolution of 0        *\n;*    through 255.                                                         *\n;*                                                                         *\n;* INPUT:   srcx,srcy   -- Source coordinate.                              *\n;*                                                                         *\n;*          dstx,dsty   -- Destination coordinate.                         *\n;*                                                                         *\n;* OUTPUT:  Returns with the desired facing to face the destination        *\n;*          coordinate from the position of the source coordinate.  North  *\n;*          is 0, East is 64, etc.                                         *\n;*                                                                         *\n;* WARNINGS:   This routine is slower than the other forms of desired      *\n;*             facing calculation.  Use this routine when accuracy is      *\n;*             required.                                                   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   12/24/1991 JLB : Adapted.                                             *\n;*=========================================================================*/\n; LONG cdecl Desired_Facing256(LONG srcx, LONG srcy, LONG dstx, LONG dsty)\n\tPROC\tDesired_Facing256 C near\n\tUSES\tebx, ecx, edx\n\n\tARG\tsrcx:DWORD\n\tARG\tsrcy:DWORD\n\tARG\tdstx:DWORD\n\tARG\tdsty:DWORD\n\n\txor\tebx,ebx\t\t\t; Facing number.\n\n\t; Determine absolute X delta and left/right direction.\n\tmov\tecx,[dstx]\n\tsub\tecx,[srcx]\n\tjge\tshort ??xnotneg\n\tneg\tecx\n\tmov\tebx,11000000b\t\t; Set bit 7 and 6 for leftward.\n??xnotneg:\n\n\t; Determine absolute Y delta and top/bottom direction.\n\tmov\teax,[srcy]\n\tsub\teax,[dsty]\n\tjge\tshort ??ynotneg\n\txor\tebx,01000000b\t\t; Complement bit 6 for downward.\n\tneg\teax\n??ynotneg:\n\n\t; Set DX=64 for quadrants 0 and 2.\n\tmov\tedx,ebx\n\tand\tedx,01000000b\n\txor\tedx,01000000b\n\n\t; Determine if the direction is closer to the Y axis and make sure that\n\t; CX holds the larger of the two deltas.  This is in preparation for the\n\t; divide.\n\tcmp\teax,ecx\n\tjb\tshort ??gotaxis\n\txchg\teax,ecx\n\txor\tedx,01000000b\t\t; Closer to Y axis so make DX=64 for quad 0 and 2.\n??gotaxis:\n\n\t; If closer to the X axis then add 64 for quadrants 0 and 2.  If\n\t; closer to the Y axis then add 64 for quadrants 1 and 3.  Determined\n\t; add value is in DX and save on stack.\n\tpush\tedx\n\n\t; Make sure that the division won't overflow.  Reduce precision until\n\t; the larger number is less than 256 if it appears that an overflow\n\t; will occur.  If the high byte of the divisor is not zero, then this\n\t; guarantees no overflow, so just abort shift operation.\n\ttest\teax,0FFFFFF00h\n\tjnz\tshort ??nooverflow\n??again:\n\ttest\tecx,0FFFFFF00h\n\tjz\tshort ??nooverflow\n\tshr\tecx,1\n\tshr\teax,1\n\tjmp\tshort ??again\n??nooverflow:\n\n\t; Make sure that the division won't underflow (divide by zero).  If\n\t; this would occur, then set the quotient to $FF and skip divide.\n\tor\tecx,ecx\n\tjnz\tshort ??nounderflow\n\tmov\teax,0FFFFFFFFh\n\tjmp\tshort ??divcomplete\n\n\t; Derive a pseudo angle number for the octant.  The angle is based\n\t; on $00 = angle matches long axis, $00 = angle matches $FF degrees.\n??nounderflow:\n\txor\tedx,edx\n\tshld\tedx,eax,8\t; shift high byte of eax into dl\n\tshl\teax,8\n\tdiv\tecx\n??divcomplete:\n\n\t; Integrate the 5 most significant bits into the angle index.  If DX\n\t; is not zero, then it is 64.  This means that the dividend must be negated\n\t; before it is added into the final angle value.\n\tshr\teax,3\n\tpop\tedx\n\tor\tedx,edx\n\tje\tshort ??noneg\n\tdec\tedx\n\tneg\teax\n??noneg:\n\tadd\teax,edx\n\tadd\teax,ebx\n\tand\teax,0FFH\n\tret\n\n\tENDP\tDesired_Facing256\n\n\n\n\tEND\n\u001a"
  },
  {
    "path": "WWFLAT32/MISC/FADING.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : FADING.ASM                               *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : August 20, 1993                          *\n;*                                                                         *\n;*                  Last Update : August 20, 1993   [JLB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\tBuild_Fading_Table\t:NEAR\n\n\tCODESEG\n\n;***********************************************************\n; BUILD_FADING_TABLE\n;\n; void *Build_Fading_Table(void *palette, void *dest, long int color, long int frac);\n;\n; This routine will create the fading effect table used to coerce colors\n; from toward a common value.  This table is used when Fading_Effect is\n; active.\n;\n; Bounds Checking: None\n;*\n\tPROC\tBuild_Fading_Table C near\n\tUSES\tebx, ecx, edi, esi\n\tARG\tpalette:DWORD\n\tARG\tdest:DWORD\n\tARG\tcolor:DWORD\n\tARG\tfrac:DWORD\n\n\tLOCAL\tmatchvalue:DWORD\t; Last recorded match value.\n\tLOCAL\ttargetred:BYTE\t\t; Target gun red.\n\tLOCAL\ttargetgreen:BYTE\t; Target gun green.\n\tLOCAL\ttargetblue:BYTE\t\t; Target gun blue.\n\tLOCAL\tidealred:BYTE\n\tLOCAL\tidealgreen:BYTE\n\tLOCAL\tidealblue:BYTE\n\tLOCAL\tmatchcolor:BYTE\t\t; Tentative match color.\n\n\tcld\n\n\t; If the source palette is NULL, then just return with current fading table pointer.\n\tcmp\t[palette],0\n\tje\t??fini\n\tcmp\t[dest],0\n\tje\t??fini\n\n\t; Fractions above 255 become 255.\n\tmov\teax,[frac]\n\tcmp\teax,0100h\n\tjb\tshort ??ok\n\tmov\t[frac],0FFh\n??ok:\n\n\t; Record the target gun values.\n\tmov\tesi,[palette]\n\tmov\tebx,[color]\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tlodsb\n\tmov\t[targetred],al\n\tlodsb\n\tmov\t[targetgreen],al\n\tlodsb\n\tmov\t[targetblue],al\n\n\t; Main loop.\n\txor\tebx,ebx\t\t\t; Remap table index.\n\n\t; Transparent black never gets remapped.\n\tmov\tedi,[dest]\n\tmov\t[edi],bl\n\tinc\tedi\n\n\t; EBX = source palette logical number (1..255).\n\t; EDI = running pointer into dest remap table.\n??mainloop:\n\tinc\tebx\n\tmov\tesi,[palette]\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\n\tmov\tedx,[frac]\n\tshr\tedx,1\n\t; new = orig - ((orig-target) * fraction);\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetred]\t\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\tax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealred],dh\t\t; preserve ideal color gun value.\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetgreen]\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\tax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealgreen],dh\t\t; preserve ideal color gun value.\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetblue]\t\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\tax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealblue],dh\t\t; preserve ideal color gun value.\n\n\t; Sweep through the entire existing palette to find the closest\n\t; matching color.  Never matches with color 0.\n\n\tmov\teax,[color]\n\tmov\t[matchcolor],al\t\t; Default color (self).\n\tmov\t[matchvalue],-1\t\t; Ridiculous match value init.\n\tmov\tecx,255\n\n\tmov\tesi,[palette]\t\t; Pointer to original palette.\n\tadd\tesi,3\n\n\t; BH = color index.\n\tmov\tbh,1\n??innerloop:\n\n\t; Recursion through the fading table won't work if a color is allowed\n\t; to remap to itself.  Prevent this from occuring.\n\tadd\tesi,3\n\tcmp\tbh,bl\n\tje\tshort ??notclose\n\tsub\tesi,3\n\n\txor\tedx,edx\t\t\t; Comparison value starts null.\n\tmov\teax,edx\n\t; Build the comparison value based on the sum of the differences of the color\n\t; guns squared.\n\tlodsb\n\tsub\tal,[idealred]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\t\n\tlodsb\n\tsub\tal,[idealgreen]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\n\tlodsb\n\tsub\tal,[idealblue]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\tjz\tshort ??perfect\t\t; If perfect match found then quit early.\n\n\tcmp\tedx,[matchvalue]\n\tja\tshort ??notclose\n\tmov\t[matchvalue],edx\t; Record new possible color.\n\tmov\t[matchcolor],bh\n??notclose:\n\tinc\tbh\t\t\t; Checking color index.\n\tloop\t??innerloop\n\tmov\tbh,[matchcolor]\n??perfect:\n\tmov\t[matchcolor],bh\n\txor\tbh,bh\t\t\t; Make BX valid main index again.\n\n\t; When the loop exits, we have found the closest match.\n\tmov\tal,[matchcolor]\n\tstosb\n\tcmp\tebx,255\n\tjne\t??mainloop\n\n??fini:\n\tmov\teax,[dest]\n\tret\n\n\tENDP\tBuild_Fading_Table\n\n\n\tEND\n\u001a"
  },
  {
    "path": "WWFLAT32/MISC/FINDARGV.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/wwlib32/misc/rcs/findargv.cpp 1.2 1994/04/22 10:29:28 scott_bowen Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : findargv \t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : findargv.C                               *\n *                                                                         *\n *                   Programmer : Jeff Wilson\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Start Date : January 14, 1993                         *\n *                                                                         *\n *                  Last Update : May 20, 1993   [PWG]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Find_Argv -- Checks to see if string is in arguement              \t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"wwstd.h\"\n#include <dos.h>\n#include <stdio.h>\n#include <string.h>\n#include <process.h>\n\n\n\n\n/***************************************************************************\n * Find_Argv -- Checks to see if string is in arguement                \t\t*\n *                                                                         *\n * INPUT: BYTE *str - string to search for.                                *\n *                                                                         *\n * OUTPUT: NULL if not found else pointer to string.                       *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/14/1993  SB : Created.                                             *\n *=========================================================================*/\n\nstatic char command [ 256 ] ;\n\nBYTE *cdecl Find_Argv(BYTE const *str)\n{\n\tchar   * ptr ;\n\tstatic   startup_flag = 0 ;\n\n\tif ( ! startup_flag ) \n\t{\n\t  startup_flag = 1 ;\n\t  getcmd ( command )\t;\n\t}\n\n\tif ( ! strlen(str) ) return NULL ;\n\treturn strstr ( command , str ) ;\n\n}\n\n\n\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/MISC/IRANDOM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : IRANDOM.C                                *\n *                                                                         *\n *                   Programmer : Barry W. Green                           *\n *                                                                         *\n *                  Last Update : 10 Feb, 1995     [BWG]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <stdlib.h>\n#include <time.h>\n#include \"wwstd.h\"\n#include \"misc.h\"\n\n\n\n\n\n\n/* IRANDOM ----------------------------------------------------------\n\n   IRandom returns a random value between min and max inclusive.\n\n   INPUTS:\tint min and int max\n\n   RETURNS:\tint random number\n*/\n\nint IRandom(int minval, int maxval)\n{\n\tint num,mask;\n\n\t// Keep minval and maxval straight.\n\tif (minval > maxval) {\n\t\tminval ^= maxval;\n\t\tmaxval ^= minval;\n\t\tminval ^= maxval;\n\t}\n\n\tmask = Get_Random_Mask(maxval - minval);\n\n\twhile( (num = (rand() & mask) + minval) > maxval ) ;\n\treturn(num);\n}\n\u001a\n"
  },
  {
    "path": "WWFLAT32/MISC/KEYCODE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n#include\t<stdio.h>\n#include\t<stdlib.h>\n#include\t<conio.h>\n#include\t<ctype.h>\n#include\t<string.h>\n\n#define\ttrue\t1\n#define\tfalse\t0\ntypedef int bool;\n\nchar KeyPhrase[128] = \"\";\nchar KeyCheck[128] = \"\";\nlong Code = 0x00000000L;\n\n\nextern \"C\" {\nlong Calculate_CRC(void const * buffer, long length);\n}\nlong Obfuscate(char const * string);\n\n\nint main(int , char ** )\n{\n\tchar buffer[128];\n\n\t/*\n\t**\tFetch the key phrase from the console.\n\t*/\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tFetch the pass phrase.\n\t\t*/\n\t\tputs(\"\\nEnter password phrase:\");\n\t\tint key = 0;\n\t\tint index = 0;\n\t\tKeyPhrase[0] = '\\0';\n\t\tbool process = true;\n\t\twhile (process) {\n\t\t\tkey = getche();\n\n\t\t\tswitch (key) {\n\t\t\t\tcase 0x08:\n\t\t\t\t\tif (index) {\n\t\t\t\t\t\tKeyPhrase[--index] = '\\0';\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 0x0D:\n\t\t\t\tcase 0x0A:\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tif (isprint(key)) {\n\t\t\t\t\t\tKeyPhrase[index++] = key;\n\t\t\t\t\t\tKeyPhrase[index] = '\\0';\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tputs(\"\");\n\n\t\t/*\n\t\t**\tVerify that it is long enough.\n\t\t*/\n\t\tif (strlen(KeyPhrase) == 0) break;\n\n\t\t/*\n\t\t**\tCalculate the code for the key phrase.\n\t\t*/\n\t\tCode = Obfuscate(KeyPhrase);\n\n\n\t\tsprintf(buffer, \"0x%08lX\", Code);\n\t\tputs(buffer);\n\t}\n\n\tputs(\"Terminated\");\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * Obfuscate -- Sufficiently transform parameter to thwart casual hackers.                     *\n *                                                                                             *\n *    This routine borrows from CRC and PGP technology to sufficiently alter the parameter     *\n *    in order to make it difficult to reverse engineer the key phrase. This is designed to    *\n *    be used for hidden game options that will be released at a later time over Westwood's    *\n *    Web page or through magazine hint articles.                                              *\n *                                                                                             *\n *    Since this is a one way transformation, it becomes much more difficult to reverse        *\n *    engineer the pass phrase even if the resultant pass code is known. This has an added     *\n *    benefit of making this algorithm immune to traditional cyrptographic attacks.            *\n *                                                                                             *\n *    The largest strength of this transformation algorithm lies in the restriction on the     *\n *    source vector being legal ASCII uppercase characters. This restriction alone makes even  *\n *    a simple CRC transformation practically impossible to reverse engineer. This algorithm   *\n *    uses far more than a simple CRC transformation to achieve added strength from advanced   *\n *    attack methods.                                                                          *\n *                                                                                             *\n * INPUT:   string   -- Pointer to the key phrase that will be transformed into a code.        *\n *                                                                                             *\n * OUTPUT:  Returns with the code that the key phrase is translated into.                      *\n *                                                                                             *\n * WARNINGS:   A zero length pass phrase results in a 0x00000000 result code.                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Obfuscate(char const * string)\n{\n\tchar buffer[128];\n\n\tif (!string) return(0);\n\tmemset(buffer, '\\xA5', sizeof(buffer));\n\n\t/*\n\t**\tCopy key phrase into a working buffer. This hides any transformation done\n\t**\tto the string.\n\t*/\n\tstrncpy(buffer, string, sizeof(buffer));\n\tbuffer[sizeof(buffer)-1] = '\\0';\n\tint length = strlen(buffer);\n\n\t/*\n\t**\tOnly upper case letters are significant.\n\t*/\n\tstrupr(buffer);\n\n\t/*\n\t**\tEnsure that only visible ASCII characters compose the key phrase. This\n\t**\tdiscourages the direct forced illegal character input method of attack.\n\t*/\n\tfor (int index = 0; index < length; index++) {\n\t\tif (!isgraph(buffer[index])) {\n\t\t\tbuffer[index] = 'A' + (index%26);\n\t\t}\n\t}\n\n\t/*\n\t**\tIncrease the strength of even short pass phrases by extending the\n\t**\tlength to be at least a minimum number of characters. This helps prevent\n\t**\ta weak pass phrase from compromising the obfuscation process. This\n\t**\tprocess also forces the key phrase to be an even multiple of four.\n\t**\tThis is necessary to support the cypher process that occurs later.\n\t*/\n\tif (length < 16 || (length & 0x03)) {\n\t\tint maxlen = 16;\n\t\tif (((length+3) & 0x00FC) > maxlen) {\n\t\t\tmaxlen = ((length+3) & 0x00FC);\n\t\t}\n\t\tfor (index = length; index < maxlen; index++) {\n\t\t\tbuffer[index] = 'A' + ((('?' ^ buffer[index-length]) + index) % 26);\n\t\t}\n\t\tlength = index;\n\t\tbuffer[length] = '\\0';\n\t}\n\n\t/*\n\t**\tTransform the buffer into a number. This transformation is character\n\t**\torder dependant.\n\t*/\n\tlong code = Calculate_CRC(buffer, length);\n\n\t/*\n\t**\tRecord a copy of this initial transformation to be used in a later\n\t**\tself referential transformation.\n\t*/\n\tlong copy = code;\n\n\t/*\n\t**\tReverse the character string and combine with the previous transformation.\n\t**\tThis doubles the workload of trying to reverse engineer the CRC calculation.\n\t*/\n\tstrrev(buffer);\n\tcode ^= Calculate_CRC(buffer, length);\n\n\t/*\n\t**\tPerform a self referential transformation. This makes a reverse engineering\n\t**\tby using a cause and effect attack more difficult.\n\t*/\n\tcode = code ^ copy;\n\n\t/*\n\t**\tUnroll and combine the code value into the pass phrase and then perform\n\t**\tanother self referential transformation. Although this is a trivial cypher\n\t**\tprocess, it gives the sophisticated hacker false hope since the strong\n\t**\tcypher process occurs later.\n\t*/\n\tstrrev(buffer);\t\t// Restore original string order.\n\tfor (index = 0; index < length; index++) {\n\t\tcode ^= (unsigned char)buffer[index];\n\t\tunsigned char temp = (unsigned char)code;\n\t\tbuffer[index] ^= temp;\n\t\tcode >>= 8;\n\t\tcode |= (((long)temp)<<24);\n\t}\n\n\t/*\n\t**\tIntroduce loss into the vector. This strengthens the key against traditional\n\t**\tcryptographic attack engines. Since this also weakens the key against\n\t**\tunconventional attacks, the loss is limited to less than 10%.\n\t*/\n\tfor (index = 0; index < length; index++) {\n\t\tstatic unsigned char _lossbits[] = {0x00,0x08,0x00,0x20,0x00,0x04,0x10,0x00};\n\t\tstatic unsigned char _addbits[] = {0x10,0x00,0x00,0x80,0x40,0x00,0x00,0x04};\n\n\t\tbuffer[index] |= _addbits[index % (sizeof(_addbits)/sizeof(_addbits[0]))];\n\t\tbuffer[index] &= ~_lossbits[index % (sizeof(_lossbits)/sizeof(_lossbits[0]))];\n\t}\n\n\t/*\n\t**\tPerform a general cypher transformation on the vector\n\t**\tand use the vector itself as the cypher key. This is a variation on the\n\t**\tcypher process used in PGP. It is a very strong cypher process with no known\n\t**\tweaknesses. However, in this case, the cypher key is the vector itself and this\n\t**\topens up a weakness against attacks that have access to this transformation\n\t**\talgorithm. The sheer workload of reversing this transformation should be enough\n\t**\tto discourage even the most determined hackers.\n\t*/\n\tfor (index = 0; index < length; index += 4) {\n\t\tshort key1 = buffer[index];\n\t\tshort key2 = buffer[index+1];\n\t\tshort key3 = buffer[index+2];\n\t\tshort key4 = buffer[index+3];\n\t\tshort val1 = key1;\n\t\tshort val2 = key2;\n\t\tshort val3 = key3;\n\t\tshort val4 = key4;\n\n\t\tval1 *= key1;\n\t\tval2 += key2;\n\t\tval3 += key3;\n\t\tval4 *= key4;\n\n\t\tshort s3 = val3;\n\t\tval3 ^= val1;\n\t\tval3 *= key1;\n\t\tshort s2 = val2;\n\t\tval2 ^= val4;\n\t\tval2 += val3;\n\t\tval2 *= key3;\n\t\tval3 += val2;\n\n\t\tval1 ^= val2;\n\t\tval4 ^= val3;\n\n\t\tval2 ^= s3;\n\t\tval3 ^= s2;\n\n\t\tbuffer[index] = val1;\n\t\tbuffer[index+1] = val2;\n\t\tbuffer[index+2] = val3;\n\t\tbuffer[index+3] = val4;\n\t}\n\n\t/*\n\t**\tConvert this final vector into a cypher key code to be\n\t**\treturned by this routine.\n\t*/\n\tcode = Calculate_CRC(buffer, length);\n\n\t/*\n\t**\tReturn the final code value.\n\t*/\n\treturn(code);\n}\n\n\n"
  },
  {
    "path": "WWFLAT32/MISC/KEYCODE.CPP.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include\t<stdio.h>\n#include\t<stdlib.h>\n#include\t<conio.h>\n#include\t<ctype.h>\n#include\t<string.h>\n\n#define\ttrue\t1\n#define\tfalse\t0\ntypedef int bool;\n\nchar KeyPhrase[128] = \"\";\nchar KeyCheck[128] = \"\";\nlong Code = 0x00000000L;\n\n\nextern \"C\" {\nlong Calculate_CRC(void const * buffer, long length);\n}\nlong Obfuscate(char const * string);\n\n\nint main(int , char ** )\n{\n\tchar buffer[128];\n\n\t/*\n\t**\tFetch the key phrase from the console.\n\t*/\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tFetch the pass phrase.\n\t\t*/\n\t\tputs(\"\\nEnter password phrase:\");\n\t\tint key = 0;\n\t\tint index = 0;\n\t\tKeyPhrase[0] = '\\0';\n\t\tbool process = true;\n\t\twhile (process) {\n\t\t\tkey = getche();\n\n\t\t\tswitch (key) {\n\t\t\t\tcase 0x08:\n\t\t\t\t\tif (index) {\n\t\t\t\t\t\tKeyPhrase[--index] = '\\0';\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 0x0D:\n\t\t\t\tcase 0x0A:\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tif (isprint(key)) {\n\t\t\t\t\t\tKeyPhrase[index++] = key;\n\t\t\t\t\t\tKeyPhrase[index] = '\\0';\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tputs(\"\");\n\n\t\t/*\n\t\t**\tVerify that it is long enough.\n\t\t*/\n\t\tif (strlen(KeyPhrase) == 0) break;\n\n\t\t/*\n\t\t**\tCalculate the code for the key phrase.\n\t\t*/\n\t\tCode = Obfuscate(KeyPhrase);\n\n\n\t\tsprintf(buffer, \"0x%08lX\", Code);\n\t\tputs(buffer);\n\t}\n\n\tputs(\"Terminated\");\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * Obfuscate -- Sufficiently transform parameter to thwart casual hackers.                     *\n *                                                                                             *\n *    This routine borrows from CRC and PGP technology to sufficiently alter the parameter     *\n *    in order to make it difficult to reverse engineer the key phrase. This is designed to    *\n *    be used for hidden game options that will be released at a later time over Westwood's    *\n *    Web page or through magazine hint articles.                                              *\n *                                                                                             *\n *    Since this is a one way transformation, it becomes much more difficult to reverse        *\n *    engineer the pass phrase even if the resultant pass code is known. This has an added     *\n *    benefit of making this algorithm immune to traditional cyrptographic attacks.            *\n *                                                                                             *\n *    The largest strength of this transformation algorithm lies in the restriction on the     *\n *    source vector being legal ASCII uppercase characters. This restriction alone makes even  *\n *    a simple CRC transformation practically impossible to reverse engineer. This algorithm   *\n *    uses far more than a simple CRC transformation to achieve added strength from advanced   *\n *    attack methods.                                                                          *\n *                                                                                             *\n * INPUT:   string   -- Pointer to the key phrase that will be transformed into a code.        *\n *                                                                                             *\n * OUTPUT:  Returns with the code that the key phrase is translated into.                      *\n *                                                                                             *\n * WARNINGS:   A zero length pass phrase results in a 0x00000000 result code.                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Obfuscate(char const * string)\n{\n\tchar buffer[128];\n\n\tif (!string) return(0);\n\tmemset(buffer, '\\xA5', sizeof(buffer));\n\n\t/*\n\t**\tCopy key phrase into a working buffer. This hides any transformation done\n\t**\tto the string.\n\t*/\n\tstrncpy(buffer, string, sizeof(buffer));\n\tbuffer[sizeof(buffer)-1] = '\\0';\n\tint length = strlen(buffer);\n\n\t/*\n\t**\tOnly upper case letters are significant.\n\t*/\n\tstrupr(buffer);\n\n\t/*\n\t**\tEnsure that only visible ASCII characters compose the key phrase. This\n\t**\tdiscourages the direct forced illegal character input method of attack.\n\t*/\n\tfor (int index = 0; index < length; index++) {\n\t\tif (!isgraph(buffer[index])) {\n\t\t\tbuffer[index] = 'A' + (index%26);\n\t\t}\n\t}\n\n\t/*\n\t**\tIncrease the strength of even short pass phrases by extending the\n\t**\tlength to be at least a minimum number of characters. This helps prevent\n\t**\ta weak pass phrase from compromising the obfuscation process. This\n\t**\tprocess also forces the key phrase to be an even multiple of four.\n\t**\tThis is necessary to support the cypher process that occurs later.\n\t*/\n\tif (length < 16 || (length & 0x03)) {\n\t\tint maxlen = 16;\n\t\tif (((length+3) & 0x00FC) > maxlen) {\n\t\t\tmaxlen = ((length+3) & 0x00FC);\n\t\t}\n\t\tfor (index = length; index < maxlen; index++) {\n\t\t\tbuffer[index] = 'A' + ((('?' ^ buffer[index-length]) + index) % 26);\n\t\t}\n\t\tlength = index;\n\t\tbuffer[length] = '\\0';\n\t}\n\n\t/*\n\t**\tTransform the buffer into a number. This transformation is character\n\t**\torder dependant.\n\t*/\n\tlong code = Calculate_CRC(buffer, length);\n\n\t/*\n\t**\tRecord a copy of this initial transformation to be used in a later\n\t**\tself referential transformation.\n\t*/\n\tlong copy = code;\n\n\t/*\n\t**\tReverse the character string and combine with the previous transformation.\n\t**\tThis doubles the workload of trying to reverse engineer the CRC calculation.\n\t*/\n\tstrrev(buffer);\n\tcode ^= Calculate_CRC(buffer, length);\n\n\t/*\n\t**\tPerform a self referential transformation. This makes a reverse engineering\n\t**\tby using a cause and effect attack more difficult.\n\t*/\n\tcode = code ^ copy;\n\n\t/*\n\t**\tUnroll and combine the code value into the pass phrase and then perform\n\t**\tanother self referential transformation. Although this is a trivial cypher\n\t**\tprocess, it gives the sophisticated hacker false hope since the strong\n\t**\tcypher process occurs later.\n\t*/\n\tstrrev(buffer);\t\t// Restore original string order.\n\tfor (index = 0; index < length; index++) {\n\t\tcode ^= (unsigned char)buffer[index];\n\t\tunsigned char temp = (unsigned char)code;\n\t\tbuffer[index] ^= temp;\n\t\tcode >>= 8;\n\t\tcode |= (((long)temp)<<24);\n\t}\n\n\t/*\n\t**\tIntroduce loss into the vector. This strengthens the key against traditional\n\t**\tcryptographic attack engines. Since this also weakens the key against\n\t**\tunconventional attacks, the loss is limited to less than 10%.\n\t*/\n\tfor (index = 0; index < length; index++) {\n\t\tstatic unsigned char _lossbits[] = {0x00,0x08,0x00,0x20,0x00,0x04,0x10,0x00};\n\t\tstatic unsigned char _addbits[] = {0x10,0x00,0x00,0x80,0x40,0x00,0x00,0x04};\n\n\t\tbuffer[index] |= _addbits[index % (sizeof(_addbits)/sizeof(_addbits[0]))];\n\t\tbuffer[index] &= ~_lossbits[index % (sizeof(_lossbits)/sizeof(_lossbits[0]))];\n\t}\n\n\t/*\n\t**\tPerform a general cypher transformation on the vector\n\t**\tand use the vector itself as the cypher key. This is a variation on the\n\t**\tcypher process used in PGP. It is a very strong cypher process with no known\n\t**\tweaknesses. However, in this case, the cypher key is the vector itself and this\n\t**\topens up a weakness against attacks that have access to this transformation\n\t**\talgorithm. The sheer workload of reversing this transformation should be enough\n\t**\tto discourage even the most determined hackers.\n\t*/\n\tfor (index = 0; index < length; index += 4) {\n\t\tshort key1 = buffer[index];\n\t\tshort key2 = buffer[index+1];\n\t\tshort key3 = buffer[index+2];\n\t\tshort key4 = buffer[index+3];\n\t\tshort val1 = key1;\n\t\tshort val2 = key2;\n\t\tshort val3 = key3;\n\t\tshort val4 = key4;\n\n\t\tval1 *= key1;\n\t\tval2 += key2;\n\t\tval3 += key3;\n\t\tval4 *= key4;\n\n\t\tshort s3 = val3;\n\t\tval3 ^= val1;\n\t\tval3 *= key1;\n\t\tshort s2 = val2;\n\t\tval2 ^= val4;\n\t\tval2 += val3;\n\t\tval2 *= key3;\n\t\tval3 += val2;\n\n\t\tval1 ^= val2;\n\t\tval4 ^= val3;\n\n\t\tval2 ^= s3;\n\t\tval3 ^= s2;\n\n\t\tbuffer[index] = val1;\n\t\tbuffer[index+1] = val2;\n\t\tbuffer[index+2] = val3;\n\t\tbuffer[index+3] = val4;\n\t}\n\n\t/*\n\t**\tConvert this final vector into a cypher key code to be\n\t**\treturned by this routine.\n\t*/\n\tcode = Calculate_CRC(buffer, length);\n\n\t/*\n\t**\tReturn the final code value.\n\t*/\n\treturn(code);\n}\n\n\n"
  },
  {
    "path": "WWFLAT32/MISC/LIB.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./lib.c 1.16 1994/05/20 15:34:33 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library Routines                         *\n *                                                                         *\n *                    File Name : LIB.C                                    *\n *                                                                         *\n *                   Programmer : Scott Bowen                              *\n *                                                                         *\n *                   Start Date : January 14, 1993                         *\n *                                                                         *\n *                  Last Update : May 20, 1993   [PWG]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Add_Long_To_Pointer -- Pointer arithmatic when pointer could be XMS.  *\n *   Find_Argv -- Checks to see if string is in arguement              \t\t*\n *   Mono_Mem_Dump -- Dumps memory to mono monitor with hex and char.      *\n *   Convert_HSV_To_RGB -- Converts HSV cordinates to RGB values           *\n *   Convert_RGB_To_HSV -- Converts RGB to RSV coordinates.                *\n *   Set_Search_Drives -- Sets up the CDRom and HardDrive paths.           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include <dos.h>\n#include <stdio.h>\n#include <string.h>\n#include \"wwstd.h\"\n#include \"misc.h\"\n\n//PRIVATE unsigned Divide_With_Round(unsigned num, unsigned den);\n\n\n/***************************************************************************\n * Divide_With_Round -- Divides integers and round to nearest integer.     *\n *                                                                         *\n * INPUT:         int numberator.                                         *\n *                int denominator.                                        *\n *                                                                         *\n * OUTPUT:        Returns value rounded.                                   *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/13/1992  SB : Created.                                             *\n *=========================================================================*/\nstatic unsigned Divide_With_Round(unsigned num, unsigned den)\n{\n\t// return num/den + (0 ro 1).  1 if the remainder is more than half the denominator.\n\treturn( (num / den) + (unsigned)((num % den) >= ((den + 1) >> 1)) );\n}\n\n#define HSV_BASE 255 // This is used to get a little better persion on HSV conversion.\n#define RGB_BASE 63  // Not 64, this is really the max value.\n\n\n/***************************************************************************\n * Convert_RGB_To_HSV -- Converts RGB to RSV coordinates.                  *\n *                                                                         *\n * INPUT:      int r,g, and b values.                                     *\n *             int *h, *s, and *v pointers.                              \t*\n *                                                                         *\n * OUTPUT:     Assigns values to *h, *s, and *v.                           *\n *                                                                         *\n * WARNINGS:   The reason we use a different base for HSV then RGB is      *\n *             because we loose alot of persision by not using floating    *\n *             point.  Using the same base value (63) made it so that      *\n *             about 50% of the time one RGB value would be one different  *\n *             then the original if you went from RGB to HSV to RGB.       *\n *             Using 255 drop it down to about 9% of the time we get an    *\n *             off value.  To get it perfect, we would have to make the    *\n *             HSV base larger - but then you need to do all calculations  *\n *             in long instead of unsigned int.                                   *\n * HISTORY:                                                                *\n *   02/11/1992  SB : Created.                                             *\n *=========================================================================*/\nvoid Convert_RGB_To_HSV(unsigned int r, unsigned int g, unsigned int b, unsigned int *h, unsigned int *s, unsigned int *v)\n{\n \tunsigned int m, r1, g1, b1, tmp;\n\n\t// Convert RGB base to HSV base.\n\tr = Divide_With_Round((r * HSV_BASE), RGB_BASE);\n\tg = Divide_With_Round((g * HSV_BASE), RGB_BASE);\n\tb = Divide_With_Round((b * HSV_BASE), RGB_BASE);\n\n\t// Set hue to default.\n\t*h = 0;\n\n\t// Set v = Max(r,g,b) to find dominant primary color.\n\t*v = (r > g) ? r : g;\n\tif (b > *v) *v = b;\n\n\t// Set m = min(r,g,b) to find amount of white.\n\tm = (r < g) ? r : g;\n\tif (b < m) m = b;\n\n\t// Determine the normalized saturation.\n\tif (*v != 0) {\n\t\t*s = Divide_With_Round( (*v - m) * HSV_BASE ,*v);\n\t} else {\n\t\t*s = 0;\n\t}\n\n\tif (*s != 0) {\n\t\ttmp = *v - m;\n\t \tr1 = Divide_With_Round( (*v - r) * HSV_BASE, tmp);\n\t \tg1 = Divide_With_Round( (*v - g) * HSV_BASE, tmp);\n\t \tb1 = Divide_With_Round( (*v - b) * HSV_BASE, tmp);\n\n\t\t// Find effect of second most predominant color.\n\t\t// In which section of the hexagon of colors does the color lie?\n\t\tif ((*v) == r) {\n\t\t \tif (m == g) {\n\t\t\t\t*h = 5 * HSV_BASE + b1;\n\t\t\t} else {\n\t\t\t\t*h = 1 * HSV_BASE - g1;\n\t\t\t}\n\t\t} else {\n\t\t\tif ((*v) == g) {\n\t\t\t \tif (m == b) {\n\t\t\t\t\t*h = 1 * HSV_BASE + r1;\n\t\t\t\t} else {\n\t\t\t\t\t*h = 3 * HSV_BASE - b1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// *v == b\n\t\t\t \tif (m == r) {\n\t\t\t\t\t*h = 3 * HSV_BASE + g1;\n\t\t\t\t} else {\n\t\t\t\t\t\n\t\t\t\t\t*h = 5 * HSV_BASE - r1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Divide by six and round.\n\t\t*h = Divide_With_Round(*h, 6);\n\t}\n}\n\n/***************************************************************************\n * Convert_HSV_To_RGB -- Converts HSV cordinates to RGB values             *\n *                                                                         *\n * INPUT:      int h,s, and v coordinates                                 *\n *             int *r, *g, and *b pointers.                              \t*\n *                                                                         *\n * OUTPUT:     Assigns values to *r, *g, and *b.                           *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/11/1992  SB : Created.                                             *\n *=========================================================================*/\nvoid Convert_HSV_To_RGB(unsigned int h, unsigned int s, unsigned int v, unsigned int *r, unsigned int *g, unsigned int *b)\n{\n\tunsigned int i;\t\t\t\t// Integer part.\n\tunsigned int f;\t\t\t\t// Fractional or remainder part.  f/HSV_BASE gives fraction.\n\tunsigned int tmp;\t\t\t// Tempary variable to help with calculations.\n\tunsigned int values[7];\t// Possible rgb values.  Don't use zero.\n\n\n\th *= 6;\n\tf = h % HSV_BASE;\n\n\t// Set up possible red, green and blue values.\n\tvalues[1] =\t\n\tvalues[2] = v;\n\n\t//\n\t// The following lines of code change \n\t//\tvalues[3] = (v * (HSV_BASE - ( (s * f) / HSV_BASE) )) / HSV_BASE;\n\t//\tvalues[4] = values[5] = (v * (HSV_BASE - s)) / HSV_BASE;\n\t// values[6] = (v * (HSV_BASE - (s * (HSV_BASE - f)) / HSV_BASE)) / HSV_BASE;\n\t// so that the are rounded divides.\n\t//\n\n\ttmp = Divide_With_Round(s * f, HSV_BASE);\n\tvalues[3] = Divide_With_Round(v * (HSV_BASE - tmp), HSV_BASE);\n\n\tvalues[4] = \n\tvalues[5] = Divide_With_Round(v * (HSV_BASE - s), HSV_BASE);\n\n\ttmp = HSV_BASE - Divide_With_Round(s * (HSV_BASE - f),  HSV_BASE);\n\tvalues[6] = Divide_With_Round(v * tmp, HSV_BASE);\n\n\n\t// This should not be rounded.\n\ti = h / HSV_BASE;\n\n\ti += (i > 4) ? -4 : 2;\n\t*r = Divide_With_Round(values[i] * RGB_BASE, HSV_BASE);\n\n\ti += (i > 4) ? -4 : 2;\n\t*b = Divide_With_Round(values[i] * RGB_BASE, HSV_BASE);\n\n\ti += (i > 4) ? -4 : 2;\n\t*g = Divide_With_Round(values[i] * RGB_BASE, HSV_BASE);\n} \n"
  },
  {
    "path": "WWFLAT32/MISC/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : jan 26, 1995                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = misc\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t\t&\n\tcrc.obj\t\t\t&\n\tdelay.obj\t\t&\n\tdetproc.obj  \t&\n\texit.obj     \t&\n\tfacing8.obj    &\n\tfacing16.obj   &\n\tfacingFF.obj   &\n\tfading.obj   \t&\n\tfindargv.obj \t&\n\tirandom.obj \t&\n\tlib.obj\t\t\t&\n\topsys.obj    \t&\n\trandom.obj    \t&\n\treverse.obj\t\t&\n\tshakescr.obj\t&\n\tcliprect.obj\t&\n\tproc.obj\t&\n\tversion.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\tmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/MISC/MISC.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : 32 bit library                           *\n *                                                                         *\n *                    File Name : MISC.H                                   *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MISC_H\n#define MISC_H\n\n/*========================= C++ Routines ==================================*/\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: EXIT.CPP\t\t\t\t\t\t\t*/\n/* Prog_End Must be supplied by the user program in startup.cpp\t\t\t\t*/\n/*=========================================================================*/\nVOID cdecl Prog_End(VOID);\nVOID cdecl Exit(INT errorval, const BYTE *message, ...);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DELAY.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Delay(int duration);\nvoid Vsync(void);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: FINDARGV.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nBYTE *cdecl Find_Argv(BYTE const *str);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LIB.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nchar *Find_Argv(char const *str);\nvoid Mono_Mem_Dump(void const *databuf, int bytes, int y);\nvoid Convert_RGB_To_HSV(unsigned int r, unsigned int g, unsigned int b, unsigned int *h, unsigned int *s, unsigned int *v);\nvoid Convert_HSV_To_RGB(unsigned int h, unsigned int s, unsigned int v, unsigned int *r, unsigned int *g, unsigned int *b);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: VERSION.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nBYTE *cdecl Version(VOID);\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: IRANDOM.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nint IRandom(int minval, int maxval);\n\n\n/*========================= Assembly Routines ==============================*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*=========================================================================*/\n/* The following prototypes are for the file: PROC.ASM\t\t\t\t\t\t\t*/\n/* Prog_End Must be supplied by the user program in startup.cpp\t\t\t\t*/\n/*=========================================================================*/\nint Get_CPU(VOID);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: RANDOM.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nUBYTE Random(VOID);\nint Get_Random_Mask(int maxval);\n\n/*=========================================================================*/\n/* The following prototype is for the file: SHAKESCR.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid Shake_Screen(int shakes);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: REVERSE.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nLONG Reverse_LONG(LONG number);\nWORD Reverse_WORD(WORD number);\nLONG Swap_LONG(LONG number);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FACING8.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint Desired_Facing8(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FACING16.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint Desired_Facing16(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FACINGFF.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nint Desired_Facing256(int x1, int y1, int x2, int y2);\n\n/*=========================================================================*/\n/* The following prototype is for the file: FADING.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nvoid *Build_Fading_Table(void const *palette, void const *dest, long int color, long int frac);\n\n/*=========================================================================*/\n/* The following prototype is for the file: CRC.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nlong Calculate_CRC(void *buffer, long length);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: DETPROC.ASM\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern WORD  Processor(VOID);\nextern WORD  Operating_System(VOID);\nextern ULONG random ( ULONG mod )  ;\nextern void  randomize ( void ) ;\n\nextern int Clip_Rect ( int * x , int * y , int * dw , int * dh ,\n\t       \t   \t\t\t int width , int height ) ;          \t\t\t   \nextern int Confine_Rect ( int * x , int * y , int dw , int dh , \n\t      \t      \t\t\t int width , int height ) ;          \t\t   \n\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: OPSYS.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern WORD OperationgSystem;\n\t\t\t\t\t\t\t\t\t\t  \n#ifdef __cplusplus\n}\n#endif\n\n/*=========================================================================*/\n\n#endif // MISC_H\n\u001a\n\u001a\n"
  },
  {
    "path": "WWFLAT32/MISC/OPSYS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/system/rcs/opsys.asm 1.1 1994/04/18 09:14:12 jeff_wilson Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Operating System Flags                   *\n;*                                                                         *\n;*                    File Name : OPSYS.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott Bowen                              *\n;*                                                                         *\n;*                   Start Date : January 26, 1993                         *\n;*                                                                         *\n;*                  Last Update : January 26, 1993   [SB]                  *\n;*                                                                         *\n;* Updated to 32bit protected mode JAW\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Operating_System -- Determines what the operating system is.          *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL             Operating_System         :NEAR\nGLOBAL             OperatingSystem          :WORD\n\t\t\t\t\t      \nDOS\t\tequ\t1\nWIN31STD\tequ\t2\nWIN31ENH\tequ\t3\nWIN30ENH\tequ\t4\nWIN30STD\tequ\t5\nWIN30REAL\tequ\t6\n\nDATASEG\n\nOperatingSystem\tdw\t0\n\n\nCODESEG\n\n;***************************************************************************\n;* Operating_System -- Determines what the operating system is.            *\n;*                                                                         *\n;* INPUT:   NONE.                                                          *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/26/1993  SB : Created.                                             *\n;*=========================================================================*\nPROC\tOperating_System C near \n\tUSES ebx,ecx,edx,es,edi\n\t\t      \t \t\n\n\t; Check for Windows 3.1\n\tmov\teax,160Ah\t\t; WIN31CHECK\n\tint\t2fh\t   \n\tor\tax,ax\n\tjz\tshort RunningUnderWin31\t\n\n\t;check for Windows 3.0 enhanced mode\n\tmov \teax,1600h\t\t; WIN386CHECK\n\tint\t2fh\n\tmov\tbl,al\n\tmov\teax,WIN30ENH\n\ttest\tbl,7fh\n\tjnz\tshort Exit\n\n\t;check for 3.0 WINOLDAP\n\tmov\teax,4680h\t\t; IS_WINOLDAP_ACTIVE\n\tint\t2fh\n\tor\teax,eax\n\tjnz\tshort NotRunningUnderWin\n\n\t; rule out MS-DOS 5.0 task switcher\n\tmov\teax,4b02h\t\t; detect switcher\n\tpush\tebx\n\tpush\tes\n\tpush\tedi\n\txor\tebx,ebx\n\tmov\tedi,ebx\n\tmov\tes,bx\n\tint\t2fh\n\tpop\tedi\n\tpop\tes\n\tpop\tebx\n\tor\teax,eax\n\tjz\tshort NotRunningUnderWin\t; MS-DOS 5.0 task switcher found.\n\n\t; check for standrd mode Windows 3.0\n\tmov\teax,1605h\t\t;PMODE_START\n\tint\t2fh\n\tmov\teax,WIN30STD\n\tcmp\tecx,-1\n\tjz\tshort Exit\n\n\t;check for real mode Windows 3.0\n\tmov\teax,1606h\t\t; PMODE_STOP\n\tint\t2fh\n\tmov\teax,WIN30REAL\n\tjmp\tSHORT Exit\n\nRunningUnderWin31:\n\t; At this point: CX == 3 means Windows 3.1 enhanced mode.\n\t;                CX == 2 means Windows 3.1 standard mode.\n\tmov\teax,WIN31STD\n\tcmp\tecx,2\n\tje\tshort Exit\n\n\tmov\teax,WIN31ENH\n\tjmp\tSHORT Exit\n\nNotRunningUnderWin:\n\tmov\teax,DOS\n\nExit:\n\tmov [WORD PTR OperatingSystem], ax\n\tret\n\nENDP\tOperating_System\n\n\n\n;----------------------------------------------------------------------------\n\nEND\n\u001a"
  },
  {
    "path": "WWFLAT32/MISC/PROC.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/system/rcs/opsys.asm 1.1 1994/04/18 09:14:12 jeff_wilson Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Operating System Flags                   *\n;*                                                                         *\n;*                    File Name : OPSYS.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott Bowen                              *\n;*                                                                         *\n;*                   Start Date : January 26, 1993                         *\n;*                                                                         *\n;*                  Last Update : January 26, 1993   [SB]                  *\n;*                                                                         *\n;* Updated to 32bit protected mode JAW\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Operating_System -- Determines what the operating system is.          *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL             Get_CPU\t\t    :NEAR\n\n\nDATASEG\n\nOperatingSystem\tdw\t0\n\n\nCODESEG\n\n;***************************************************************************\n;* Operating_System -- Determines what the operating system is.            *\n;*                                                                         *\n;* INPUT:   NONE.                                                          *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/26/1993  SB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_CPU C near \n\tUSES\tebx,ecx,edx,es,edi\nIF 0\t\n\txor\teax,eax      \t \t\n        mov     ax,1\n        pushf\n        pop     bx\n        and     bh,0fh\n        push    bx\n        popf\n        pushf\n        pop     cx\n        and     ch,0f0h\n        cmp     ch,0f0h\n        je      @@1                     ;8086 or below 80286\n\n        inc     ax\n        or      bh,0f0h\n        push    bx\n        popf\n        pushf\n        pop     cx\n        and     ch,0f0h\n        je      @@1                     ;80286\nENDIF\n        mov\teax,3\n        mov     ebx,esp\n        and     esp,0fffffffch\n        pushfd\n        pop     edx\n        mov     ecx,edx\n        xor     edx,000040000h\n        push    edx\n        popfd\n        pushfd\n        pop     edx\n        push    ecx\n        popfd\n        xor     edx,ecx\n        and     edx,000040000h          ;test alignment check bit\n        mov     esp,ebx\n        jz      @@1                     ;80386\n        ;.486\n        inc     eax\n        pushfd\n        pop     edx\n        mov     ecx,edx\n        xor     edx,000200000h\n        push    edx\n        popfd\n        pushfd\n        pop     edx\n        push    ecx\n        popfd\n        xor     edx,ecx                 ;test id bit\n        jz      @@1                     ;80486\nP586\n        mov     eax,1\n        ;.586 or higher, cpuid returns cpu generation number in ax bits 8-11\n        cpuid\n        and     eax,0f00h\n        shr     eax,8\nP386\n@@1:    ret\n\nENDP\tGet_CPU\n\n\n\n;----------------------------------------------------------------------------\n\nEND\n\u001a\n"
  },
  {
    "path": "WWFLAT32/MISC/RANDOM.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library routine                          *\n;*                                                                         *\n;*                    File Name : RANDOM.ASM                               *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : 20 August, 1990   [CY]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n;*  UBYTE Random(VOID);                                                    *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGlobal Random\t\t:NEAR\nGlobal Get_Random_Mask\t:NEAR\nGlobal RandNumb\t\t:DWORD\n\n\tDATASEG\n\nRandNumb\tDD\t12349876H\n\n\tCODESEG\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; UBYTE Random(VOID);\n; int Get_Random_Mask(int maxval);\n;\n; ----------------------------------------------------------------\n\n;-----------------------------------------------------------------\n; RANDOM\n;\n; UBYTE Random(VOID);\n;\n;*\n\n\tPROC\tRandom C near\n\tUSES\tesi\n\n\tlea\tesi, [RandNumb]\t\t; get offset in segment of RandNumb\n\txor\teax,eax\n\tmov\tal,[esi]\n\tshr\tal,1\t\t\t; shift right 1 bit (bit0 in carry)\n\tshr\tal,1\n\trcl\t[BYTE PTR esi+2],1\t; rcl byte 3 of RandNumb\n\trcl\t[BYTE PTR esi+1],1 \t; rcl byte 2 of RandNumb \n\tcmc\t\t\t\t; complement carry\n\tsbb\tal,[esi]\t\t; sbb byte 1 of RandNumb\n\tshr\tal,1\t\t\t; sets carry\n\trcr\t[BYTE PTR esi],1 \t; rcr byte 1 of RandNumb\n\tmov\tal,[esi]\t\t; reload byte 1 of RandNumb\n\txor\tal,[esi+1]\t\t; xor with byte 2 of RandNumb\n\n\tret\n\n\tENDP\tRandom\n\n\n;-----------------------------------------------------------------\n; GET_RANDOM_MASK - returns an AND value that is large enough that it\n; encloses the 'maxval' parameter.\n;\n; int Get_Random_Mask(int maxval);\n;\n;*\n\n\tPROC\tGet_Random_Mask C near\n\tUSES\tecx\n\tARG\tmaxval:DWORD\n\n; This function takes as a parameter a maximum value, for example, 61.  It\n; then tries to create an AND mask that is big enough to enclose that number.\n; For our example case, that AND mask would be 0x3F.  It does this by scanning\n; for the highest bit in the number, then making an all-1's mask from that\n; bit position down to bit 0.\n\tbsr\tecx,[maxval]\t\t; put bit position of highest bit in ecx\n\tmov\teax,1\t\t\t; set one bit on in eax\n\tjz\t??invalid\t\t; if BSR shows maxval==0, return eax=1\n\tinc\tecx\t\t\t; get one bit higher than count showed\n\tshl\teax,cl\t\t\t; move our EAX bit into position\n\tdec\teax\t\t\t; dec it to create the mask.\n??invalid:\n\tret\n\tENDP\tGet_Random_Mask\n;----------------------------------------------------------------------------\n\n\tEND\n\u001a"
  },
  {
    "path": "WWFLAT32/MISC/REVERSE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/misc/rcs/reverse.asm 1.3 1994/04/25 12:22:45 scott_bowen Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : REVERSE.ASM                              *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : April 20, 1994   [SKB]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n; LONG Reverse_LONG(LONG number);                                          *\n; WORD Reverse_WORD(WORD number);\t\t\t\t\t   *\n; LONG Swap_LONG(LONG number);\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\t Reverse_WORD\t:NEAR\nGLOBAL\t Swap_LONG\t:NEAR\nGLOBAL\t Reverse_LONG\t:NEAR\n\nCODESEG\n\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; LONG Reverse_LONG(LONG number);\n; WORD Reverse_WORD(WORD number);\n; LONG Swap_LONG(LONG number);\n;\n; ----------------------------------------------------------------\n\n;-----------------------------------------------------------------\n;\n; REVERSE_LONG\n;\n; LONG Reverse_LONG(LONG number);\n;\n;*\n\tPROC\tReverse_LONG C near\n\tARG\tnumber:DWORD\n\nIF 1\n\tmov\teax,[DWORD PTR number]\n\txchg\tal,ah\n\tror\teax,16\n\txchg\tal,ah\nELSE\n\n\t; This is old 16 bit code.\n\tmov\tax,[WORD PTR number]\n\tmov\tdx,[WORD PTR number+2]\n\txchg\tah,dl\n\txchg\tal,dh\nENDIF\n\n\tret\n\n\tENDP\tReverse_LONG\n\n;-----------------------------------------------------------------\n\n;-----------------------------------------------------------------\n;\n; REVERSE_WORD\n;\n; WORD Reverse_WORD(WORD number);\n;\n;*\n\tPROC\tReverse_WORD C near\n\tARG\tnumber:WORD\n\n\tmov\tax,[number]\n\txchg\tah,al\n\tret\n\n\tENDP\tReverse_WORD\n\n;-----------------------------------------------------------------\n\n\n;-----------------------------------------------------------------\n;\n; SWAP_LONG\n;\n; LONG Swap_LONG(LONG number);\n;\n;*\n\tPROC\tSwap_LONG C near\n\tARG\tnumber:DWORD\n\nIF 1\n\t; 32 bit code.\n    \tmov\teax,[DWORD PTR number]\n\tror\teax,16\nELSE\n\t; 16 bit code.\n\tmov\tax,[WORD PTR number+2]\n\tmov\tdx,[WORD PTR number]\nENDIF\n\n\tret\n\n\n\tENDP\tSwap_LONG\n\n;-----------------------------------------------------------------\n\n\tEND\n\u001a\n"
  },
  {
    "path": "WWFLAT32/MISC/SHAKESCR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : SHAKESCR.ASM                             *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : August 19, 1993                          *\n;*                                                                         *\n;*                  Last Update : February 10, 1995 [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\tShake_Screen\t:NEAR\n\n\tCODESEG\n\n;***********************************************************\n; SHAKE_SCREEN\n;\n; VOID Shake_Screen(int shakes);\n;\n; This routine shakes the screen the number of times indicated.\n;\n; Bounds Checking: None\n;\n;*\n\tPROC\tShake_Screen C near\n\tUSES\tecx, edx\n\n\tARG\tshakes:DWORD\n\n\tmov\tecx,[shakes]\n\n;;; push es\n;;; mov ax,40h\n;;; mov es,ax\n;;; mov dx,[es:63h]\n;;; pop es\n\tmov\teax,[0463h]\t\t; get CRTC I/O port\n\tmov\tdx,ax\n\tadd\tdl,6\t\t\t; video status port\n\n??top_loop:\n\n??start_retrace:\n\tin\tal,dx\n\ttest\tal,8\n\tjz\t??start_retrace\n\n??end_retrace:\n\tin\tal,dx\n\ttest\tal,8\n\tjnz\t??end_retrace\n\n\tcli\n\tsub\tdl,6\t\t\t; dx = 3B4H or 3D4H\n\n\tmov\tah,01\t\t\t; top word of start address\n\tmov\tal,0Ch\n\tout\tdx,al\n\txchg\tah,al\n\tinc\tdx\n\tout\tdx,al\n\txchg\tah,al\n\tdec\tdx\n\n\tmov\tah,040h\t\t\t; bottom word = 40 (140h)\n\tinc\tal\n\tout\tdx,al\n\txchg\tah,al\n\tinc\tdx\n\tout\tdx,al\n\txchg\tah,al\n\n\tsti\n\tadd\tdl,5\n\n??start_retrace2:\n\tin\tal,dx\n\ttest\tal,8\n\tjz\t??start_retrace2\n\n??end_retrace2:\n\tin\tal,dx\n\ttest\tal,8\n\tjnz\t??end_retrace2\n\n??start_retrace3:\n\tin\tal,dx\n\ttest\tal,8\n\tjz\t??start_retrace3\n\n??end_retrace3:\n\tin\tal,dx\n\ttest\tal,8\n\tjnz\t??end_retrace3\n\n\tcli\n\tsub\tdl,6\t\t\t; dx = 3B4H or 3D4H\n\n\tmov\tah,0\n\tmov\tal,0Ch\n\tout\tdx,al\n\txchg\tah,al\n\tinc\tdx\n\tout\tdx,al\n\txchg\tah,al\n\tdec\tdx\n\n\tmov\tah,0\n\tinc\tal\n\tout\tdx,al\n\txchg\tah,al\n\tinc\tdx\n\tout\tdx,al\n\txchg\tah,al\n\n\tsti\n\tadd\tdl,5\n\n\tloop\t??top_loop\n\n\tret\n\n\tENDP\tShake_Screen\n\n;***********************************************************\n\n\tEND\n\u001a"
  },
  {
    "path": "WWFLAT32/MISC/VERSION.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* \n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : VERSION.C                                *\n *                                                                         *\n *                   Programmer : Christopher Yates                        *\n *                                                                         *\n *                  Last Update : July 26, 1991   [JLB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Version -- Returns with current library version text.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwstd.h\"\n\t\t   \n\n\nPRIVATE BYTE *version = \"Westwood Studios - 32 Bit Library Version \" \n\t__DATE__\n\t\"\\r\\n\";\n\n/***************************************************************************\n * VERSION -- Returns with current library version text.                   *\n *                                                                         *\n *    Use this routine to determine the current library version.  The      *\n *    version text contains the date that it was created.                  *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  Returns pointer to version text.                               *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/26/1991 JLB : Created.                                             *\n *=========================================================================*/\nBYTE *cdecl Version(VOID)\n{\n\treturn(version);\n}\n"
  },
  {
    "path": "WWFLAT32/MISC/WWLIB32.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32 User include file                *\n *                                                                         *\n *                    File Name : WWLIB32.H                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WWLIB32_H\n#define WWLIB32_H\n\n#include <wwstd.h>\n\n#include <audio.h>\n#include <buffer.h>\n#include <descmgmt.h>\n#include\t<dipthong.h>\n#include <file.h>\n#include <font.h>\n#include <gbuffer.h>\n#include <iff.h>\n#include <keyboard.h>\n#include <mcgaprim.h>\n#include <misc.h>\n#include <mono.h>\n#include <palette.h>\n#include <playcd.h>\n#include <shape.h>\n#include <tile.h>\n#include <timer.h>\n#include <video.h>\n#include <vbuffer.h>\n#include <windows.h>\n#include <wsa.h>\n#include <wwmem.h>\n\n\n\n\n#endif // WWLIB32_H\n\u001a\n"
  },
  {
    "path": "WWFLAT32/MISC/WWSTD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : wwstd.h                                  *\n *                                                                         *\n *                    File Name : WWLIB.H                                  *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : March 1, 1994                            *\n *                                                                         *\n *                  Last Update : March 1, 1994   []                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#define\tWWSTD_H\n\n\n// Note: SKB 4/11/94\n// Before this library is done, this needs to be able to be set to TRUE.\n// Once it is, the FALSE parts should be removed from the source code.\n#define LIB_EXTERNS_RESOLVED FALSE \n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <dos.h>\n#include <bios.h>\n\n//================================\n\n// TRUE and FALSE are defined in pltypes.h\n\n#ifndef IBM\n#define IBM\t\t\t\tTRUE\n#endif\n\n#ifndef AMIGA\n#define AMIGA\t\t\tFALSE\n#endif\n\n#ifndef\tSEGA\n#define\tSEGA\t\t\tFALSE\n#endif\n\n/*\n**\tCommon constants used in normal code.\n*/\n#define ERROR\t\t-1\n\n#ifdef NULL\n#undef\tNULL\n#endif\n\n#ifndef NULL\n#define NULL\t\t0L\n#endif\n\n#ifdef VOID\n#undef VOID\n#endif\n\n#define PRIVATE\t\tstatic\n#define PUBLIC\t\t\t/* Routines & data don't have a specifier */\n\n#ifdef __cplusplus\n#define\t__CPPARGS\t...\n#else\n#define\t__CPPARGS\t\n#endif\n\n// This macro will get the size (in elements) of the specified array.\n#ifdef GET_SIZE\n#undef GET_SIZE\n#endif\n#define GET_SIZE(a)\t\t\t\t\t((sizeof(a) / sizeof(*a)))\n\n// Returns the absolute value of the number.\n#ifdef ABS\n#undef ABS\n#endif\ntemplate<class T> T ABS(T a)\n{\n\treturn (a < 0) ? -a : a;\n}\ninline int ABS(int);\ninline long ABS(long);\n\n// Returns the minimum of the two numbers.\n#ifdef MIN\n#undef MIN\n#endif\ntemplate<class T> T MIN(T a, T b)\n{\n\treturn (b < a) ? b : a;\n};\ninline short MIN(short, short);\ninline int MIN(int, int);\ninline long MIN(long, long);\n\n// Returns the maximum of the two numbers.\n#ifdef MAX\n#undef MAX\n#endif\ntemplate<class T> T MAX(T a, T b)\n{\n\treturn (b > a) ? b : a;\n};\ninline short MAX(short, short);\ninline int MAX(int, int);\ninline long MAX(long, long);\n\n// Returns the low word of a long\n#define\tLOW_WORD(a)\t\t((unsigned short)((long)(a) & 0x0000FFFFL))\n\n// Returns the high word of a long\n#define\tHIGH_WORD(a)\t((unsigned long)(a) >> 16)\n\n// Merges to shorts to become a long\n#define\tMAKE_LONG(a,b) (((long)(a) << 16) | (long)((b)&0x0000FFFFL))\n\n/*\n** Macro allows our routines to act like\n** sprintf etc..\n*/\n#ifdef AssembleTo\n#undef AssembleTo\n#endif\n\n#define AssembleTo(dest,fmt)\\\n{\\\n\tva_list argptr;\\\n\tif (fmt != (dest))\\\n\t\t{\\\n\t\tva_start (argptr, fmt);\\\n\t\tvsprintf ((dest), fmt, argptr);\\\n\t\tva_end (argptr);\\\n\t\t}\\\n}\n\n// type definitions\n//=======================================\ntypedef void \tVOID;\n\n//==================================================\n// Pharlape defines these for use so we use their\n// typedefs!\n//\t\ttypedef\tunsigned char\tBOOL;\n//\t\ttypedef signed long\t\tLONG;\n//\t\ttypedef unsigned long\tULONG;\n//==================================================\n#ifndef PRIVATE\n#define  PRIVATE\tstatic\n#endif\n\n// The purpose of the INT and UINT is for efficiency.  It says that while a short int (16 bit)\n// has enough precision, it is more efficient to pass in an int (32 bits).  For efficiency, most\n// WORD and UWORD should be an INT or UINT, especially on the stack and structures that will\n// not be in large arrays.  When size efficiency is more important then speed, use WORD UWORD.\n\n#define\tVOID\t\tvoid\n\n#pragma\twarn -eas\n#define\tTRUE\t\t1\n#define\tFALSE\t\t0\n\n#define\tBOOL\t\tint\t\t\t\t\t// 32 bits for speed. use CHAR for size optimizations.\n\n#ifndef HMI_DRIVER\n#define\tINT\t\tint\n#define\tUINT\t\tunsigned int\n#define\tBYTE\t\tchar\n#define\tUBYTE\t\tunsigned char\n#define  UCHAR\t   unsigned char\n#define\tWORD\t\tsigned \tshort\n#define\tUWORD\t\tunsigned short\n#define  USHORT\tunsigned short\n\n#define\tLONG\t\tsigned \tlong\n#define\tULONG\t\tunsigned long\n#define  REALPTR\tunsigned long\n\n#define\tFARPTR  char far *\n\n#endif\n\n\n/*\n**\tThe type of processor running on this system as\n**\treturned by Processor().\n*/\n#define\tPROC_80386\t\t0\n#define\tPROC_80486\t\t1\n#define\tPROC_PENTIUM\t2\n\n\n// Inline Routines\n//\n//\n// These Template functions are generally used \n// by classes when they havce over loaded > and <.\n//\n#ifdef __cplusplus\ntemplate<class T> T Min(T a, T b)\n{\n\treturn (a<b ? a : b);\n}\n\ntemplate<class T> inline  T Max(T a, T b)\n{\n\treturn (a>b ? a : b);\n}\n\ntemplate<class T> T Abs(T a)\n{\n\treturn ((a<0) ? -(a) : a);\n}\n\ntemplate<class T> VOID minimize(T &a, T b)\n{\n\tif( b<a )\n\t\ta=b;\n}\n\ntemplate<class T> VOID maximize(T &a, T b)\n{\n\tif( b>a )\n\t\ta=b;\n}\n#endif\n\n/*\n**\tMacros that control bit settings in a variable.\n*/\n#define Bit_Flags_On(a,b)\t\t\ta |= (b)\n#define Bit_Flags_Off(a,b)\t\t\ta &= (~(b))\n#define Bit_Flags_Value(a,b)\t\t(a & (b))\n#define Bit_Flags_Flip(a,b)\t\ta ^= (b)\n\n// Template replacements for the user defines above\n#ifdef __cplusplus\ntemplate<class T> VOID BitFlagsOn(T &a, T b)\n{\n\ta |= (b);\n}\n\ntemplate<class T> VOID BitFlagsOff(T &a, T b)\n{\n\ta &= (~(b));\n}\n\ntemplate<class T> T BitFlagsValue(T a, T b)\n{\n\treturn (a & (b));\n}\n\ntemplate<class T> VOID BitFlagsFlip(T &a, T b)\n{\n\ta ^= (b);\n}\n#endif\n\ntypedef enum {\t\n\tTBLACK, \n\tPURPLE, \n\tCYAN, \n\tGREEN, \n\tLTGREEN, \n\tYELLOW, \n\tPINK, \n\tBROWN, \n\tRED, \n\tLTCYAN, \n\tLTBLUE, \n\tBLUE, \n\tBLACK, \n\tGREY,\n\tLTGREY, \n\tWHITE,\n\tCOLOR_PADDING=0x1000\n} ColorType;\n\n\n#endif\n\n\n"
  },
  {
    "path": "WWFLAT32/MONO/INITMONO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Initialize mono                          *\n *                                                                         *\n *                    File Name : INITMONO.CPP                             *\n *                                                                         *\n *                   Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : March 28, 1994                           *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\t   \n\n#ifndef MONO_H\n#include \"mono.h\"\n#endif\n\n#ifndef DESCMGMT_H\n#include \"descmgmt.h\"\n#endif\n\n/***************************************************************************\n * INITIALIZE_MONO_SCREEN -- Initializes the Mono display data             *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/21/1994  jaw: Created.                                             *\n *========================================================================*/\n\t\t\t\t   \nint Initialize_Mono_Screen(void)\n{\t\t\t\t\t\t\t \n\t// get a valid selector to mono screen.\n//\tMap_Segment_To_Address(0x0b0000UL, 0x8000UL);\n\n\tMonoScreen = 0xb0000\t;\n\n\treturn (int)0;\n}\t\t\t\n\n\u001a\n\u001a\n"
  },
  {
    "path": "WWFLAT32/MONO/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 30, 1995                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = mono\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tmonoprnt.obj\t&\n\tmono.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/MONO/MONO.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\u001b;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Mono Screen system                       *\n;*                                                                         *\n;*                    File Name : MONO.ASM                                 *\n;*                                                                         *\n;*                   Programmer : Jeff Wilson                              *\n;*                                                                         *\n;*                   Start Date : March 28, 1994                           *\n;*                                                                         *\n;*                  Last Update : September 8, 1994   [IML]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;GLOBAL              MonoScreen           :DWORD\n;GLOBAL              MonoEnabled          :DWORD\n;\n;GLOBAL C            Mono_Set_Cursor      :NEAR\n;GLOBAL C            Mono_Clear_Screen    :NEAR\n;GLOBAL C            Mono_Scroll          :NEAR\n;GLOBAL C            Mono_Put_Char        :NEAR\n;GLOBAL C            Mono_Draw_Rect       :NEAR\n;\n;GLOBAL C            _Mono_Text_Print     :NEAR\n;GLOBAL C            Mono_Text_Print      :NEAR\n;\n;GLOBAL C            Mono_Print           :NEAR\n;\n;GLOBAL C            Mono_View_Page       :NEAR\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nLOCALS ??\n\n\n;\n; External declares so these functions can be called\n;\nGLOBAL          MonoScreen              :DWORD\nGLOBAL          MonoEnabled             :DWORD  \n\nGLOBAL         Mono_Set_Cursor         :NEAR\t; done\nGLOBAL         Mono_Clear_Screen       :NEAR\t; done\nGLOBAL         Mono_Scroll             :NEAR\t; done\nGLOBAL         Mono_Put_Char           :NEAR\t; done\nGLOBAL         Mono_Draw_Rect          :NEAR\t; done\nGLOBAL        _Mono_Text_Print         :NEAR\t; done\nGLOBAL         Mono_Text_Print         :NEAR\t; done\nGLOBAL         Mono_Print              :NEAR \t; done\nGLOBAL         Mono_View_Page          :NEAR\t; done\n\n;\n; Equates used in this file\n;\nNULL =  0       ; null code\nCR   =  13      ; carriage return code\nCPL  =  80      ; characters per line\nLPS  =  25      ; lines per screen\n\n\nDATASEG\n\nMonoX           DD      0\nMonoY           DD      0\nMonoOff         DD      0\nMonoScreen      DD      0b0000h                 ;Deffault to Real mode!\nMonoEnabled     DD      0                       ; Is mono printing enabled?\n\n;====================================================================\n\nCharData        DB      0DAh,0C4h,0BFh,0B3h,0D9h,0C4h,0C0h,0B3h ; Single line\n                DB      0D5h,0CDh,0B8h,0B3h,0BEh,0CDh,0D4h,0B3h ; Double horz.\n                DB      0D6h,0C4h,0B7h,0BAh,0BDh,0C4h,0D3h,0BAh ; Double vert.\n                DB      0C9h,0CDh,0BBh,0BAh,0BCh,0CDh,0C8h,0BAh ; Double line.\n\n\n;               x,y,dist\nBoxData DB      1,0,0           ; Upper left corner.\n        DB      1,0,1           ; Top edge.\n        DB      0,1,0           ; Upper right corner.\n        DB      0,1,2           ; Right edge.\n        DB      -1,0,0          ; Bottom right corner.\n        DB      -1,0,1          ; Bottom edge.\n        DB      0,-1,0          ; Bottom left corner.\n        DB      0,-1,2          ; Left edge.\n        DB      0,0,-1          ; End of list.\n\n; Mono page segment layout array.\nPageMap DD      0,1,2,3,4,5,6,7\n\n;===================================================================\n\nCODESEG\n\n\n;***************************************************************************\n;* Map_Segment_To_Address_ -- Translate a 16bit Seg:Offset address to a    *\n;*                            Linear address.                              *                            \n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; int Map_Segment_To_Address ( unsigned seg , unsigned offset );\n\n\n\n;***************************************************************************\n;* MONO_SET_CURSOR -- Sets the mono cursor to specified coordinates.       *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; void Mono_Set_Cursor(int x, int y);\n\n\nPROC Mono_Set_Cursor    C near \n\n        USES eax , ebx , edx \n\n        ARG     xpos : DWORD\n        ARG     ypos : DWORD\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n\n;       mov     ax,cs\n;       and     ax,7\n;       or      ax,SS_DATA\n\n;       mov     ds,ax\n;       mov     es,ax\n\n;       sub     eax,eax\n\n        mov     eax,[ypos]\n;        mov     ah,CPL\n;        imul    ah\n  lea  eax , [ eax + 4 * eax ]   ; multiply by CPL\n  shl  eax , 4\n\n;       sub     ebx,ebx\n        mov     ebx,[xpos]\n        add     ebx,eax\n\n        ; Update cursor position.\n        mov     edx,03B4h\n\n        mov     al,0Eh                  ; High byte register set.\n        out     dx,al\n        inc     edx\n        mov     al,bh\n        out     dx,al                   ; Set high byte.\n\n        dec     edx\n        mov     al,0Fh                  ; Low byte register set.\n        out     dx,al\n        inc     edx\n        mov     al,bl\n        out     dx,al                   ; Set low byte.\n\n        ; Update the globals.\n        add     ebx,ebx\n        mov     [MonoOff],ebx\n        mov     eax,[xpos]\n        mov     [MonoX],eax\n        mov     eax,[ypos]\n        mov     [MonoY],eax\n\n??exit:\n        ret\n\nENDP    Mono_Set_Cursor\n\n\n;***************************************************************************\n;* MONO_CLEAR_SCREEN -- Clears the mono screen and homes cursor.           *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; void Mono_Clear_Screen(void);\n\nPROC Mono_Clear_Screen  C near \n        \n        USES eax , ecx , edi\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n\n;       mov     ax,cs\n;       and     ax,7\n;       or      ax,SS_DATA\n\n;       mov     ds,ax\n;       mov     es,ax\n\n;       mov     eax,[MonoScreen]        ; ES:DI = Mono RAM address.\n;       mov     es,ax\n;       sub     edi,edi\n   mov  edi , [ MonoScreen ]\n        mov     eax,02000200h           ; Clear leave attrib bit normal.\n        mov     ecx,8000h/4             ; Number of longs to clear.\n        rep     stosd                       ; Clear the mono screen.\n\n        push    0\n        push    0\n\n        call    Mono_Set_Cursor\n        add     esp , 8\n\n??exit:\n        ret\n\nENDP    Mono_Clear_Screen\n\n\n;***************************************************************************\n;* MONO_SCROLL -- Scroll the mono screen up specified lines.               *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; void Mono_Scroll(DWORD lines);\nPROC Mono_Scroll        C near \n\n        USES \teax , ebx , ecx , edx , edi , esi\n        ARG     lines : DWORD\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n\n;       mov     ax,cs\n;       and     ax,7\n;       or      ax,SS_DATA\n\n;       mov     ds,ax\n;       mov     es,ax\n\n;       xor     eax,eax                 ; clear eax so no need for sign extend\n        mov     eax, [lines]             ; get lines available\n        or      eax,eax                 ; any lines  to scroll?\n        je      short ??fini            ; =>NO\n\n        mov     ebx,eax                 ; set line counter\n                                                    \n        mov     edx,[MonoY]             ; get row count\n        ror     edx,16                  ; store it in high half of register\n        mov     dx,[WORD PTR MonoOff]   ; get column offset\n        ror     edx,16\n                     \n;        mov     eax,[MonoScreen]        ; get selector for mono screen\n;        push    ds                      ; save off data seg for later\n;        mov     ds,ax                   ; set data source register\n;        mov     es,ax                   ;  and extra source register\n\n        sub     eax,eax                 ; set to clear clear line\n        \n??looper:\n        mov     ecx,(80*24)             ; Number of words to move.\n\n ;      xor     edi,edi                 ; dst start at top of screen area\n ;      mov     esi,80*2                ; src start at next line down\n    mov edi , [ MonoScreen ]\n    lea esi , [ 80 * 2 + edi ]       \n        rep     movsw                   ; Scroll the screen upward.\n\n        dec     dx                      ; decrement Y counter\n        ror     edx,16                  ; switch to mono offset\n        sub     dx,80*2                 ; fix MonoOffset\n        ror     edx,16                  ; switch to y counter\n\n        mov     ecx,40                  ; Clear out the last line.\n        rep     stosd                   ;   by storing words across it\n        dec     ebx                     ; last line?\n\n        jne     ??looper                ; =>NO\n\n        ; reset data values\n  ;     pop     ds                      ; restore the ds segment\n        mov     [WORD PTR MonoY],dx     ; store of the mono y position\n        ror     edx,16                  ; switch to screen offset\n        mov     [WORD PTR MonoOff],dx   ; store of the mono offset\n                \n??fini:\n??exit:\n        ret\n\nENDP    Mono_Scroll\n\n\n;***************************************************************************\n;* MONO_PUT_CHAR -- Output a character to the mono screen.                 *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; void Mono_Put_Char(char character, int attrib=2);\n\nPROC Mono_Put_Char      C near \n\n        USES    eax , edi\n\n        ARG     character : BYTE\n        ARG     attrib    : DWORD\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n                       \n;       mov     ax,cs\n;       and     ax,7\n;       or      ax,SS_DATA\n\n;       mov     ds,ax\n\n        mov     edi,[MonoOff]\n;        mov     eax,[MonoScreen]\n;        mov     es,ax                   ; ES:DI = First character output pointer.\n   add edi , [ MonoScreen ]\n\n        ; Output character to monochrome monitor.\n        mov     al,[character]\n        mov     ah,[BYTE PTR attrib]\n;       stosw       \n        mov     [ edi ] , ax\n\n        ; Update cursor position.\n        inc     [MonoX]         ; X position moves.\n\n        mov     eax,[MonoY]\n        push    eax\n        mov     eax,[MonoX]\n        push    eax\n\n        call    Mono_Set_Cursor \n        add     esp,8\n\n??exit:\n        ret\n\nENDP    Mono_Put_Char\n\n\n;***************************************************************************\n;* MONO_DRAW_RECT -- Draw a rectangle using mono characters.               *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; void Mono_Draw_Rect(int x, int y, int w, int h, int attrib=2, int thick=0);\n\nPROC Mono_Draw_Rect     C near \n\n        USES eax , ebx , ecx , esi , edi\n\n        ARG     xpos:DWORD\n        ARG     ypos:DWORD\n        ARG     width:DWORD\n        ARG     height:DWORD\n        ARG     attrib:DWORD\n        ARG     thick:DWORD\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n\n;       mov     ax,cs\n;       and     ax,7\n;       or      ax,SS_DATA\n\n;       mov     ds,ax\n;       mov     es,ax\n\n        mov     esi,OFFSET BoxData\n        mov     edi,OFFSET CharData\n\n;       mov     cl,3\n;       sub     eax,eax\n        mov     eax,[thick]\n        and     eax,011b\n        shl     eax,3\n        add     edi,eax\n\n        ; Prep width and height.\n        cmp     [width],2\n        jb      ??fini\n\n        cmp     [height],2\n        jb      ??fini\n\n        sub     [width],2\n        sub     [height],2\n\n        ; Preserve cursor position for later restore.\n        mov     ecx,[MonoX]\n        push    ecx\n        mov     ecx,[MonoY]\n        push    ecx\n\n        ; Cursor starts at upper left corner.\n        mov     ecx,[ypos]\n        push    ecx\n        mov     ecx,[xpos]\n        push    ecx\n        call    Mono_Set_Cursor \n        add     esp,8\n\n??drawloop:\n        ; Determine the number of characters to output.\n        mov     ecx,[width]\n        cmp     [BYTE PTR esi+2],1\n        je      short ??gotlen\n\n        mov     ecx,[height]\n        cmp     [BYTE PTR esi+2],2\n        je      short ??gotlen\n\n        mov     ecx,1\n??gotlen:\n\n        jecxz   ??donerun\n\n??runloop:\n        sub     ebx,ebx\n        mov     bl,[BYTE PTR edi]\n\n;       mov     ebx,eax\n        sub     eax,eax\n        mov     al,[BYTE PTR attrib]\n        push    eax\n        push    ebx\n\n        call    Mono_Put_Char \n        add     esp,8\n\n        movsx   eax,[BYTE PTR esi+1]\n;       cbw\n        add     eax,[MonoY]\n        push    eax\n        movsx   eax,[BYTE PTR esi]\n;       cbw\n        add     eax,[MonoX]\n        dec     eax                     ; Undo cursor advance.\n        push    eax\n\n        call    Mono_Set_Cursor         ; Properly advance cursor.\n        add     esp,8\n\n        loop    ??runloop\n\n??donerun:\n\n        ; Advance to next control entry.\n        add     esi,3\n        inc     edi\n        cmp     [BYTE PTR esi+2],-1\n        jne     ??drawloop\n\n        ; Restore cursor to original position.\n        call    Mono_Set_Cursor\n        add     esp,8\n\n??fini:\n??exit:\n        ret\n\nENDP    Mono_Draw_Rect\n\n\n;***************************************************************************\n;* MONO_TEXT_PRINT -- Prints text to the mono screen at coordinates.       *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; void Mono_Text_Print(void *text, int x, int y, int attrib, int update);\n\nPROC _Mono_Text_Print   C near \n\n        USES eax,ebx,ecx,edx,edi,esi\n\n        ARG     text:DWORD\n        ARG     xpos:DWORD\n        ARG     ypos:DWORD\n        ARG     attrib:DWORD\n        ARG     update:DWORD\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n\n;       mov     ax,cs\n;       and     ax,7\n;       or      ax,SS_DATA\n\n;       mov     ds,ax\n;       mov     es,ax\n\n        ; Preserve cursor coordinates for later restoration.\n        mov     eax,[MonoY]\n        push    eax\n        mov     eax,[MonoX]\n        push    eax\n\n        cmp     [text],NULL\n        je      ??fini\n\n        mov     eax,[ypos]\n        push    eax\n        mov     eax,[xpos]\n        push    eax\n        call    Mono_Set_Cursor \n        add     esp,8\n\n        mov     esi,[text]\n\n??charloop:\n        xor     eax,eax\n        mov     al,[BYTE PTR esi]               ; Fetch character to output.\n        inc     esi\n\n        ; Stop processing on a NULL character.\n        or      eax,eax\n        je      short ??fini\n\n        ; Special processing for a '\\r' characters.\n        cmp     eax,CR\n        je      short ??cr\n\n        ; Output character to monochrome monitor.\n??normal:\n;       xor     ah,ah\n\n        mov     ebx,eax\n        mov     eax,[attrib]\n        push    eax\n        push    ebx\n        call    Mono_Put_Char \n        add     esp,8\n\n        ; Perform adjustments if wrapping past right margin.\n        cmp     [WORD PTR MonoX],CPL\n        jb      short ??nowrap\n\n        inc     [ypos]\n\n        mov     eax,[ypos]\n        push    eax\n;       sub     eax,eax\n        push    0\n        call    Mono_Set_Cursor \n        add     esp,8\n\n        jmp short ??nowrap\n\n        ; Move to start of next line.\n??cr:\n        inc     [ypos]\n\n        mov     eax,[ypos]\n        push    eax\n        mov     eax,[xpos]\n        push    eax\n        call    Mono_Set_Cursor \n        add     esp,8\n\n        ; Scroll the monochrome screen if necessary.\n??nowrap:\n        cmp     [MonoY],LPS\n        jb      short ??noscroll\n\n        push    1\n        call    Mono_Scroll \n        add     esp,4\n\n        dec     [ypos]\n\n??noscroll:\n        jmp short ??charloop\n\n??fini:\n        cmp     [update],0\n        jne     short ??noupdate\n\n        call    Mono_Set_Cursor\n??noupdate:\n        add     esp,8\n\n??exit:\n        ret\n\nENDP    _Mono_Text_Print\n\n;=====================================================================\n\nPROC Mono_Text_Print    C near \n        USES    eax\n        ARG     text:DWORD\n        ARG     xpos:DWORD\n        ARG     ypos:DWORD\n        ARG     attrib:DWORD\n\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n\n;       sub     eax,eax\n        push    0\n        mov     eax,[attrib]\n        push    eax\n        mov     eax,[ypos]\n        push    eax\n        mov     eax,[xpos]\n        push    eax\n        mov     eax,[text]\n        push    eax\n\n        call    _Mono_Text_Print \n        add     esp,20\n\n??exit:\n        ret\n\nENDP    Mono_Text_Print\n\n\n\n;***************************************************************************\n;* MONO_PRINT -- Prints text to the mono screen at current pos.            *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; void Mono_Print(void *text);\n\nPROC Mono_Print         C near \n        \n        USES eax\n\n        ARG     text:DWORD\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n\n;       mov     ax,cs\n;       and     ax,7\n;       or      ax,SS_DATA\n\n;       mov     ds,ax\n;       mov     es,ax\n\n;       mov     eax,1\n        push    1\n;       mov     eax,2\n        push    2\n        mov     eax,[MonoY]\n        push    eax\n        mov     eax,[MonoX]\n        push    eax\n        mov     eax,[text]\n        push    eax\n\n        call    _Mono_Text_Print \n        add     esp,20\n\n??exit:\n        ret\n\nENDP    Mono_Print\n\n;***************************************************************************\n;* Mono_View_Page -- page in a mono screen                                 *\n;*                                                                         *\n;*   Displays the specified page in displayable mono memory area.          *\n;*                                                                         *\n;* INPUT:  WORD page = which page of memory we will use for storage        *\n;*                                                                         *\n;* OUTPUT: old_page                                                        *\n;*                                                                         *\n;* WARNINGS:    none.                                                      *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*=========================================================================*\n; int cdecl Mono_View_Page(int page);\n\n\nPROC Mono_View_Page     C near \n\n        USES eax,ebx,ecx,edx,edi,esi\n\n        ARG     page:DWORD\n\n        LOCAL   oldpage:DWORD\n\n        cmp     [MonoEnabled],0\n        je      ??exit\n\n        cld\n\n;       mov     ax,cs\n;       and     ax,7\n;       or      ax,SS_DATA\n\n;       mov     ds,ax\n;       mov     es,ax\n\n        ; Prepare the original page number for return to caller.\n        mov     ebx,[PageMap]\n        mov     [oldpage],ebx\n\n        ; If the desired page is already displayed, then don't do anything.\n        mov     eax,[page]\n        cmp     eax,ebx\n        je      short ??fini\n\n        ; Verify that page specified is legal.\n        cmp     eax,7\n        ja      short ??fini\n\n        ; Find where the logical page to display is actually located.\n        mov     ecx,8\n\n        mov     edi,OFFSET PageMap\n        repne   scasd\n        neg     ecx\n        add     ecx,7                   ; ECX = where desired page is located.\n\n        ; Swap the page ID bytes in the PageMap array.\n        sub     edi,4\n        mov     ebx,[PageMap]\n        mov     eax,[edi]\n        mov     [edi],ebx\n        mov     [PageMap],eax\n\n        ; Set DS and ES to point to each page.\n;        mov     eax,[MonoScreen]\n;        mov     ds,ax\n   mov esi , [ MonoScreen ]\n;        shl     ecx,8\n   shl ecx , 12\n;        add     ecx,edi                 ; NO Addition to selectors!\n   lea edi , [ esi + ecx ]\n\n;       mov     edi,ecx\n;       xor     esi,esi\n\n        ; Exchange the two pages.\n        mov     ecx,1000H/4\n\n??looper:\n        mov     edx,[edi]\n        mov     ebx,[esi]\n        mov     [edi],ebx\n        mov     [esi],edx\n        add     esi,4\n        add     edi,4\n        loop    ??looper\n\n        ; Return with the original page number.\n??fini:\n??exit:\n        mov     eax,[oldpage]\n        ret\n        \nENDP    Mono_View_Page\n\nEND\n\u001a\n"
  },
  {
    "path": "WWFLAT32/MONO/MONO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Mono Sub-system                          *\n *                                                                         *\n *                    File Name : MONO.H                                   *\n *                                                                         *\n *                   Programmer : Joe Bostic                               *\n *             32Bit Programmer : Jeff Wilson                              *\n *                                                                         *\n *                   Start Date : March 28, 1994                           *\n *                                                                         *\n *                  Last Update : March 28, 1994   []                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef MONO_H\n#define MONO_H\n\n// C++ Routines\n//==================================================================\n\n// Mono Screen routines\n//==================================================================\nint\tInitialize_Mono_Screen ( void );\n\t\t\t\t\t\t\t   \n\n// C Routines\n//==================================================================\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// Mono Screen routines\n//===================================================================\n\textern\tunsigned\tMonoScreen;\n\textern\tunsigned\tMonoEnabled;\n\t\t\t\n\textern\tvoid Mono_Set_Cursor(int x, int y);\n\textern \tvoid Mono_Clear_Screen(void); \n\textern \tvoid Mono_Scroll(int lines);\n\textern \tvoid Mono_Put_Char(char character, int attrib=2);\n\textern \tvoid Mono_Draw_Rect(int x, int y, int w, int h, int attrib=2, int thick=0);\n\textern\tvoid Mono_Text_Print(void const *text, int x, int y, int attrib=2);\n\textern\tvoid Mono_Print(void const *text);\n\textern \tvoid Mono_View_Page(int page);\n\textern\tint Mono_Printf(char const *string, ...);\n\t\t\t\t\t\t\t\t\n#ifdef __cplusplus\n}\n#endif\n\n\n#endif\n\n"
  },
  {
    "path": "WWFLAT32/MONO/MONOPRNT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : MONOPRNT.C                               *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : October 12, 1993                         *\n *                                                                         *\n *                  Last Update : November 2, 1993   [JLB]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Mono_Printf -- Prints formated text to the monochrome screen.         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t<stdarg.h>\n#include\t<string.h>\n#include\t<stdio.h>\n#include \"mono.h\"\n\n/***************************************************************************\n * Mono_Printf -- Prints formated text to the monochrome screen.           *\n *                                                                         *\n *    This routine is used to print formatted text (similar to printf) to  *\n *    the monochrome screen.                                               *\n *                                                                         *\n * INPUT:   string   -- The string that is to be printed.                  *\n *                                                                         *\n *          ...      -- Any optional parameters that the string requires   *\n *                      to format properly.                                *\n *                                                                         *\n * OUTPUT:  Returns with the length of the string that it printed to the   *\n *          monochrome screen.                                             *\n *                                                                         *\n * WARNINGS:   The total length of the formatted string must not exceed    *\n *             255 bytes.                                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/02/1993 JLB : Created.                                             *\n *=========================================================================*/\nint Mono_Printf(char const *string, ...)\n{\n\tva_list\tva;\n\tchar\t\tbuffer[256];\n\n\tif (!MonoEnabled) return(0);\n\t\t\n\tva_start(va, string);\n\n\tvsprintf(buffer, string, va);\n\tMono_Print(buffer);\n\n\tva_end(va);\n\treturn(strlen(buffer));\n}\n"
  },
  {
    "path": "WWFLAT32/PALETTE/LOADPAL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Load_Palette                             *\n *                                                                         *\n *                    File Name : LOADPAL.CPP                              *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 25, 1994                           *\n *                                                                         *\n *                  Last Update : April 27, 1994   [BR]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Note: This module contains dependencies upon the file I/O system,\t\t\t*\n * specifically Load_Data().\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *\t  Load_Palette -- Loads a palette file into the given palette buffer.\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n/*\n********************************* Includes **********************************\n*/\n#include <wwstd.h>\n#include \"wwstd.h\"\n#include \"iff.h\"\n#include \"palette.h\"\n\n/*\n********************************* Constants *********************************\n*/\n\n/*\n********************************** Globals **********************************\n*/\n\n/*\n******************************** Prototypes *********************************\n*/\n\n/*************************************************************************** \n *\tLoad_Palette -- Loads a palette file into the given palette buffer.\t\t*\n *                                                                         *\n * INPUT:      \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tBYTE * file_name \t\t\t- name of the file to load.\t\t\t\t\t\t*\n *\t\tBYTE * palette_pointer\t- pointer to palette buffer.\t      \t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:     \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tnone                                                        \t\t\t*\n *                                                                         *\n * WARNINGS:   \t                                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/20/1991 BS : Created.                                              *\n *   04/27/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nVOID cdecl Load_Palette(BYTE *palette_file_name, VOID *palette_pointer)\n{\t\n\t#if(IBM)\n\t\tLoad_Data(palette_file_name, palette_pointer, 768);\n\t#else\n\t\tLoad_Data(palette_file_name, palette_pointer, (ULONG)(2<<BIT_PLANES));\n\t#endif\n}\n\n/**************************** End of loadpal.cpp ***************************/\n"
  },
  {
    "path": "WWFLAT32/PALETTE/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : January 27, 1995                         *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = palette\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tloadpal.obj\t&\n\tmorphpal.obj\t&\n\tpalette.obj\t&\n\tpal.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WWFLAT32/PALETTE/MORPHPAL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : wwlib32                                  *\n *                                                                         *\n *                    File Name : PALTOPAL.CPP                             *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : May 2, 1994                              *\n *                                                                         *\n *                  Last Update : May 2, 1994   [BR]                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Morph_Palette -- morphs a palette from source to destination          *\n *   Palette_To_Palette -- morph src palette to a dst palette              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n/*\n********************************* Includes **********************************\n*/\n#include \"wwstd.h\"\n#include \"video.h\"\n#include \"palette.h\"\n#include \"timer.h\"\n\n/*\n********************************* Constants *********************************\n*/\n#define SCALE(a,b,c) (((((LONG)(a)<<8) / (LONG)(b) ) * (ULONG)(c)) >>8)\n\n\n/*\n********************************** Globals **********************************\n*/\n\n/*\n******************************** Prototypes *********************************\n*/\n\nPRIVATE WORD cdecl Palette_To_Palette(VOID *src_palette, VOID *dst_palette, ULONG current_time, ULONG delay);\n\n\n/***************************************************************************\n * Morph_Palette -- morphs a palette from source to destination            *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tVOID *src_pal\t- starting palette\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tVOID *dst_pal\t- ending palette\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tUWORD delay\t- time delay in 60ths of a second\t\t\t\t\t\t\t*\n *\t\tVOID *callback\t- user-defined callback, NULL if none\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/02/1994 BR : Created.                                              *\n *=========================================================================*/\nVOID cdecl Morph_Palette (VOID *src_pal, VOID *dst_pal, UWORD delay,\n\tVOID (*callback) (VOID) )\n{\n\tWORD\tresult;\n\tULONG\tpal_start = TickCount.Time();\n\tVOID   (*cb_ptr) ( VOID ) ;\t// callback function pointer\n\n//\t(VOID *)cb_ptr = callback;\n\tcb_ptr = callback ;\n\n\t/*===================================================================*/\n\t/* Make sure that we don't go too fast but also make sure we keep\t\t*/\n\t/*\t\tprocessing the morph palette if we have one.\t\t\t\t\t\t\t*/\n\t/*===================================================================*/\n\twhile (1) {\n\t\tif (src_pal && dst_pal) {\n\t\t\tresult = Palette_To_Palette (src_pal, dst_pal, \n\t\t\t\t(TickCount.Time() - pal_start), (ULONG)delay);\n\t\t\tif (!result)\n\t\t\t\tbreak;\n\n\t\t\tif (callback) {\n\t\t\t\t(*cb_ptr)();\n\t\t\t}\n\t\t}\n\t}\n\n\treturn;\n\n}\t/* end of Morph_Palette */\n\n\n/***************************************************************************\n * Palette_To_Palette -- morph src palette to a dst palette                *\n *                                                                         *\n * Creates & sets a palette that's in-between 'src_palette' & \t\t\t\t\t*\n * 'dst_palette'; how close it is to dst_palette is based on how close \t\t*\n * 'current_time' is to 'delay'.  'current_time' & 'delay' are based on\t\t*\n * 0 being the start time.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:               VOID *src_palette =  palette we want to morph from *\n *                      VOID *dst_palette =  palette we want to morph to   *\n *                      LONG current_time =  time we started morph pal\t\t*\n *                      LONG delay         = time we want the morph to take*\n *                                                                         *\n * OUTPUT:\t\t\t\t\tWORD if the time had elapsed and no chages were\t\t*\n *\t\t\t\t\t\t\t\t\t  necessary this routine returns FALSE\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t  otherwise it will always return TRUE (this\t\t*\n *\t\t\t\t\t\t\t\t\t  was necessary to detect the end of the ice\t\t*\n *\t\t\t\t\t\t\t\t\t  effect.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/24/1993  MC : Created.                                             *\n *=========================================================================*/\nPRIVATE WORD cdecl Palette_To_Palette(VOID *src_palette, VOID *dst_palette, \n\tULONG current_time, ULONG delay)\n{\n\tBYTE\tcolour;\n\tBYTE\tdiff;\n\tWORD\tchgval;\n\tWORD\tlp;\n\tWORD\tchange;\n\tstatic BYTE  palette[768];\n\n\t/*======================================================================*/\n\t/* Loop through each RGB value attempting to change it to the correct\t*/\n\t/*\t\tcolor.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tfor (change = lp = 0; lp < 768; lp++) {\n\t\tif (current_time < delay ) {\n\t\t\tdiff\t\t= ( ( ((BYTE *)dst_palette)[lp] & 63) - \n\t\t\t\t( ((BYTE *)src_palette)[lp] & 63) );\n\t\t\tif (diff) \n\t\t\t\tchange = TRUE;\n\t\t\tchgval\t= SCALE(diff, delay, current_time);\n\t\t\tcolour \t= ( ((BYTE *)src_palette)[lp] & 63) + chgval;\n\t\t} \n\t\telse {\n\t\t\tcolour = ((BYTE *)dst_palette)[lp] & 63;\n\t\t\tchange = FALSE;\n\t\t}\n\t\tpalette[lp] = colour;\n\t}\n\t/*======================================================================*/\n\t/* Set the palette to the color that we created.\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tSet_Palette(palette);\n\treturn(change);\n\n}\t/* end of Palette_To_Palette */\n\n\n/*************************** End of morphpal.cpp ***************************/\n\n\u001a"
  },
  {
    "path": "WWFLAT32/PALETTE/PAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : PAL.ASM                                  *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : May 30, 1992                             *\n;*                                                                         *\n;*                  Last Update : April 27, 1994   [BR]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Set_Palette_Range -- Sets changed values in the palette.              *\n;*   Bump_Color -- adjusts specified color in specified palette            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************** Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\ninclude \"keyboard.inc\"\n\n\n;****************************** Declarations ********************************\nGLOBAL \t\tSet_Palette_Range:NEAR\nGLOBAL \t\tBump_Color:NEAR\nGLOBAL  \tCurrentPalette:BYTE:768\nGLOBAL\t\tPaletteTable:byte:1024\n\n\n;********************************** Data ************************************\nLOCALS ??\n\n\tDATASEG\n\nCurrentPalette\tDB\t768 DUP(255)\t; copy of current values of DAC regs\nPaletteTable\tDB\t1024 DUP(0)\n\nIFNDEF LIB_EXTERNS_RESOLVED\nVertBlank\tDW\t0\t\t; !!!! this should go away\nENDIF\n\n\n;********************************** Code ************************************\n\tCODESEG\n\n\nIF 1\n;***************************************************************************\n;* SET_PALETTE_RANGE -- Sets a palette range to the new pal                *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:\tThis routine is optimized for changing a small number of   *\n;*\t\tcolors in the palette.\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/07/1995 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tSet_Palette_Range C NEAR\n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tpalette:DWORD\n\n\tcld\n\n\t;*=================================================================*/\n\t;* Set up pointers to begin making palette comparison\t\t   */\n\t;*=================================================================*/\n\tmov\tesi, [palette]\n\tmov\tedi, OFFSET CurrentPalette\n\tmov\tebx, OFFSET PaletteTable\n\tmov\tecx, 0\n\n??loop_top:\n\tmov\teax,[esi]\t\t\t; read a dword from palette source\n\tmov\tedx,[edi]\t\t\t; read a dword from compare palette\n\tand\teax,00FFFFFFh\t\t\t; palette entrys are only 3 bytes\n\tand\tedx,00FFFFFFh\t\t\t;   long so and of extra\n\tcmp\teax,edx\t\t\t\t; if they are not the same then\n\tjne\t??set_table\t\t\t;   add them into the table\n\tadd\tesi,3\n\tadd\tedi,3\n\tinc\tcl\t\t\t\t; adjust to next palette entry\n\tjnz\t??loop_top\t\t\t; if we dont wrap to zero we have more\n\tjmp\t??set_pal\t\t\t; so now go set the palette\n??set_table:\t\n\tshl\teax,8\t\t\t\t; shift bgr value up register\n\tmov\tal,cl\t\t\t\t; store which palette entry num\n\tmov\t[ebx],eax\n\tadd\tebx,4\n\tmovsw\t\t\t\t\t; copy the three gun values into\n\tmovsb\t\t\t\t\t;  the shadow palette.  Use movsb\n\tinc\tcl\t\t\t\t; adjust to next palette entry\n\tjnz\t??loop_top\t\t\t; if we dont wrap to zero we have more\n\n??set_pal:\n\tmov\tesi,ebx\n\tmov\tebx,OFFSET PaletteTable\n\tsub\tesi,ebx\t\t\t\t; if ebx didn't change there\n\tjz\t??exit\t\t\t\t;   is nothing to set\n\tshr\tesi,2\t\t\t\t; find how many entrys\n\n\tmov\teax,[ebx]\n\n\tmovzx\tecx,al\t\t\t\t; we are currently on entry 0\n\tadd\tebx,4\n\n\t; Tell DAC of the color gun to start setting.\n\tmov\tedx,03C8h\n\tout\tdx,al\t\t; First color set.\n\n\t; Set the colors only during a VSync.\n\tmov\tedx,03DAh\t; CRTC register.\n\n\tpush\tebx\n\tmov\tbx,[VertBlank]\n\tand\tbl,001h\n\tshl\tbl,3\n\n??in_vbi:\n\tin\tal,dx\t\t\t\t; read CRTC status\n\tand\tal,008h\t\t\t\t; only vertical sync bit\n\txor\tal,bl\n\tje\t??in_vbi\t\t\t; in vertical sync\n\n??out_vbi:\n\tin\tal,dx\t\t\t\t; read CRTC status\n\tand\tal,008h\t\t\t\t; only vertical sync bit\n\txor\tal,bl\n\tjne\t??out_vbi\t\t\t; not in vertical sync\n\tpop\tebx\n\t; Update the DAC data register.\n\tmov\tdx,03C9h\n\n;**************** Time Critical Section Start ******************\n\tcli\n??loop:\n\tshr\teax,8\t\t; shift down the red gun value\n\tout\tdx,al\t\t; write it to the video card\n\tjmp\t$ + 2\t\t; force cache to flush, to create a time\n\tshr\teax,8\t\t; shift down the blue gun value\n\tout\tdx,al\t\t; write it to the video card\n\tjmp\t$ + 2\t\t; force cache to flush, to create a time\n\tshr\teax,8\t\t; shift down the blue gun value\n\tout\tdx,al\t\t; write the green value to video card\n\tjmp\t$ + 2\t\t; force cache to flush, to create a time\n\tinc\tecx\t\t; move edx to next palette entry\n\n\tmov\teax,[ebx]\t; get next value to set\n\tadd\tebx,4\t\t;  and post increment the palette value\n\tcmp\tal,cl\t\t; check if DAC position already correct\n\tje\t??correct_pos\n\n\tmov\tedx,03C8h\t; Tell DAC of the color gun to start setting.\n\tout\tdx,al\t\t; First color set.\n\tmov\tdx,03C9h\n\n??correct_pos:\n\tdec\tesi\n\tjnz\t??loop\n\tsti\n;***************** Time Critical Section End *******************\n??exit:\n\tret\n\n\tENDP\tSet_Palette_Range\nELSE\n;***************************************************************************\n;* Set_Palette_Range -- Sets changed values in the palette.                *\n;*                                                                         *\n;* INPUT: \t\t\t\t\t\t\t\t   *\n;*\tVOID *palette - pointer to the new palette.                        *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*\tnone\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/25/1994 SKB : Created.                                             *\n;*   04/27/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\n; VOID cdecl Set_Palette_Range(VOID *palette);\n\tPROC Set_Palette_Range\tC NEAR\n\tUSES eax,ebx,ecx,edx,edi,esi\n\tARG\tpalette:DWORD\n\tLOCAL\tremain:DWORD\t; 32-bit: converted to LONG\n\n\tcld\n\n\tmov\tbx,[VertBlank]\n\tand\tbl,001h\n\tshl\tbl,3\n\n\t; Make a copy of the palette passed in.\n\tmov\tedi,OFFSET CurrentPalette\n\tmov\tesi,[palette]\n\tmov\t[remain],768\n\n\t; Search for differences between the current palette and the\n\t; new palette.  When a difference is found, output a block\n\t; of color registers and keep scanning.\n??bodyloop:\n\tmov\tecx,[remain]\n\n\trepe\tcmpsb\t\t; Search for differences.\n\tje\tshort ??exit\n\tdec\tesi\n\tdec\tedi\n\tinc\tecx\n\n\tmov\tedx,0\t\t; clear EDX\n\tmov\teax,ecx\n\tmov\tecx,3\n\tdiv\tecx\t\t; EAX = # of colors to set, EDX = Fraction.\n\tor\tedx,edx\n\tjz\tshort ??nofrac\n\tneg\tedx\n\tadd\tedx,3\t\t; Back offset skip needed.\n\tinc\teax\t\t; Fractional color rounds up to whole color to set.\n??nofrac:\n\n\t; Set CX to be the number of color guns to set.\n\tmov\tecx,eax\t\t; Colors * 3 bytes per color.\n\tadd\tecx,eax\n\tadd\tecx,eax\n\n\t; Chop this DAC dump short if necessary in order to reduce\n\t; sparkling.\n\tmov\t[remain],0\n\tcmp\tecx,86*3\t; Number of color guns to set per vert retrace\n\tjbe\tshort ??ok\n\tsub\tecx,86*3\n\tmov\t[remain],ecx\n\tmov\tecx,86*3\n??ok:\n\n\t; Adjust the palette offsets back to point to the RED color gun.\n\tsub\tesi,edx\n\tsub\tedi,edx\n\n\t; Determine the color number to start setting.\n\tneg\teax\n\tadd\teax,256\t\t; AX = Color to start setting (0..255).\n\n\t; Tell DAC of the color gun to start setting.\n\tmov\tedx,03C8h\n\tout\tdx,al\t\t; First color set.\n\n\t; Set the colors only during a VSync.\n\tmov\tedx,03DAh\t; CRTC register.\n\n??in_vbi:\n\tin\tal,dx\t\t; read CRTC status\n\tand\tal,008h\t\t; only vertical sync bit\n\txor\tal,bl\n\tje\t??in_vbi\t; in vertical sync\n\n??out_vbi:\n\tin\tal,dx\t\t; read CRTC status\n\tand\tal,008h\t\t; only vertical sync bit\n\txor\tal,bl\n\tjne\t??out_vbi\t; not in vertical sync\n\n;??wait:\n;\tin\tal,dx\n;\ttest\tal,01000b\n;\tjnz\t??wait\n\n;??retrace:\n;\tin\tal,dx\n;\ttest\tal,01000b\n;\tjz\t??retrace\n\n\t; Update the DAC data register.\n\tmov\tdx,03C9h\n\n;**************** Time Critical Section Start ******************\n\tpushf\n\tcli\n??loop:\n\tlodsb\n\tstosb\n\tout\tdx,al\n\tjmp\t$ + 2\t\t; force cache to flush, to create a time\n\t\t\t\t;  delay to give DAC time to get value\n\tloop\t??loop\n\tpopf\n;***************** Time Critical Section End *******************\n\n\tcmp\t[remain],0\n\tjnz\t??bodyloop\n\n??exit:\n\tret\n\n\tENDP\tSet_Palette_Range\nENDIF\n\n\n;***************************************************************************\n;* Bump_Color -- adjusts specified color in specified palette              *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*\tVOID *palette\t- palette to modify\t\t\t\t   *\n;*\tWORD changable\t- color # to change\t\t\t\t   *\n;*\tWORD target\t- color to bend toward\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/27/1994 BR : Converted to 32-bit.                                  *\n;*=========================================================================*\n; BOOL cdecl Bump_Color(VOID *palette, WORD changable, WORD target);\nPROC Bump_Color C NEAR \n\tUSES ebx,ecx,edi,esi\n\tARG\tpal:DWORD, color:WORD, desired:WORD\n\tLOCAL\tchanged:WORD\t\t; Has palette changed?\n\n\tmov\tedi,[pal]\t\t; Original palette pointer.\n\tmov\tesi,edi\n\tmov\teax,0\n\tmov\tax,[color]\n\tadd\tedi,eax\n\tadd\tedi,eax\n\tadd\tedi,eax\t\t\t; Offset to changable color.\n\tmov\tax,[desired]\n\tadd\tesi,eax\n\tadd\tesi,eax\n\tadd\tesi,eax\t\t\t; Offset to target color.\n\n\tmov\t[changed],FALSE\t\t; Presume no change.\n\tmov\tecx,3\t\t\t; Three color guns.\n\n\t; Check the color gun.\n??colorloop:\n\tmov\tal,[BYTE PTR esi]\n\tsub\tal,[BYTE PTR edi]\t; Carry flag is set if subtraction needed.\n\tjz\tshort ??gotit\n\tmov\t[changed],TRUE\n\tinc\t[BYTE PTR edi]\t\t; Presume addition.\n\tjnc\tshort ??gotit\t\t; oops, subtraction needed so dec twice.\n\tdec\t[BYTE PTR edi]\n\tdec\t[BYTE PTR edi]\n??gotit:\n\tinc\tedi\n\tinc\tesi\n\tloop\t??colorloop\n\n\tmov\tax,[changed]\n\tret\n\n\tENDP\tBump_Color\n\n\tEND\n\n;*************************** End of pal.asm ********************************\n\u001a\n"
  },
  {
    "path": "WWFLAT32/PALETTE/PALETTE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : PALETTE.C\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : BILL STOKES\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Start Date : 6/20/91\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : August 2, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Note: This module contains dependencies upon the video system,\t\t\t\t*\n * specifically Get_Video_Mode().\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Set_Palette -- sets the current palette\t\t\t\t\t\t\t\t\t\t\t*\n *   Set_Palette_Color -- Set a color number in a palette to the data.     *\n *\t  Fade_Palette_To -- Fades the current palette into another\t\t\t\t\t*\n *   Determine_Bump_Rate -- determines desired bump rate for fading        *\n *   Bump_Palette -- increments the palette one step, for fading           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n/*\n********************************* Includes **********************************\n*/\n#include <mem.h>\n#include \"wwstd.h\"\n#include \"video.h\"\n#include \"palette.h\"\n#include \"timer.h\"\n\n/*\n********************************* Constants *********************************\n*/\n\n/*\n********************************** Globals **********************************\n*/\nextern \"C\" extern UBYTE  CurrentPalette[];\t\t/* in pal.asm */\n\n/*\n******************************** Prototypes *********************************\n*/\n\nPRIVATE VOID cdecl Determine_Bump_Rate(VOID *palette, WORD delay, WORD *ticks, WORD *rate);\nPRIVATE BOOL cdecl Bump_Palette(VOID *palette1, UWORD step);\n\n/*\n******************************** Code *********************************\n*/\n\n/***************************************************************************\n * Set_Palette -- sets the current palette\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tVOID *palette\t\t- palette to set\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/25/1994 SKB : Created.                                             *\n *   04/27/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nVOID cdecl Set_Palette(VOID *palette)\n{\n\t#if(IBM)\n\t\tSet_Palette_Range(palette);\n\t#else\n\t\tCopy_Palette(palette,CurrentPalette);\n   \tLoadRGB4(&Main_Screen->ViewPort,palette,32L);\n\t   LoadRGB4(AltVPort,palette,32L);\n\t#endif\n\n}\t/* end of Set_Palette */\n\n\n/***************************************************************************\n * Set_Palette_Color -- Set a color number in a palette to the data.       *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tVOID *palette\t- palette to set color in\t\t\t\t\t\t\t\t\t\t*\n *\t\tWORD color\t\t- which color index to set\t\t\t\t\t\t\t\t\t\t*\n *\t\tVOID *data\t\t- RGB data for color\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/25/1994 SKB : Created.                                             *\n *   04/27/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nVOID cdecl Set_Palette_Color(VOID *palette, WORD color, VOID *data)\n{\n\t/*\n\t---------------------- Return if 'palette' is NULL -----------------------\n\t*/\n\tif (!palette) return;\n\n\t/*\n\t------------------- Change the color & set the palette -------------------\n\t*/\n\t#if(IBM)\n\t\tmemcpy(&((UBYTE *)palette)[color * RGB_BYTES], data, RGB_BYTES);\n\t\tSet_Palette_Range(palette);\n\t#else\n\t\tpalette[color] = *(UWORD*)data;\n\t\tSet_Palette(palette);\n\t#endif\n\n}\t/* end of Set_Palette */\n\n\n/***************************************************************************\n *\tFade_Palette_To -- Fades the current palette into another\t\t\t\t\t*\n *                                                                         *\n * This will allow the palette to fade from current palette into the \t\t*\n * palette that was passed in.  This can be used to fade in and fade out.\t*\n *                                                                         *\n * INPUT:      \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *    BYTE  *palette1 - this is the palette to fade to.           \t\t\t*\n *\t\tUWORD delay\t\t -\tfade with this timer count down\t\t\t\t\t\t\t*\n *\t\tVOID *callback  - user-defined callback function\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/20/1991  BS : Created.                                             *\n *=========================================================================*/\nVOID Fade_Palette_To(VOID *palette1, UWORD delay, VOID (*callback)() )\n{\n\tBOOL\tchanged;\t// Flag that palette has changed this tick.\n\tWORD\tjump;\t\t// Gun values to jump per palette set.\n\tULONG\ttimer;\t\t// Tick count timer used for timing.\n\tWORD\tticksper;\t// The ticks (fixed point) per bit jump.\n\tWORD\ttickaccum;\n\tVOID (*cb_ptr)(VOID);\t// callback function pointer\n\n//\t(VOID *)cb_ptr = callback;\n\tcb_ptr = callback;\n\n\t/*\n\t---------------------- Return if 'palette1' is NULL ----------------------\n\t*/\n\tif (!palette1) \n\t\treturn;\n\n\t/*\n\t--------------------- Fading only supported in MCGA ----------------------\n\t*/\n\tif (Get_Video_Mode() != MCGA_MODE) {\t// was global GraphicMode\n\t\tSet_Palette(palette1);\n\t\treturn;\n\t} \n\n\t/*\n\t--------------------------- Get the bump rate ----------------------------\n\t*/\n\tDetermine_Bump_Rate(palette1, delay, &ticksper, &jump);\n\n\ttickaccum = 0;\t\t\t\t\t\t\t// init accumulated elapsed time\n\ttimer = TickCount.Time(); \t\t\t\t// timer = current time\n\tdo {\n\t\tchanged = FALSE;\n\n\t\ttickaccum += ticksper;\t\t\t// tickaccum = time of next change * 256\n\t\ttimer += (tickaccum >> 8);\t\t// timer = time of next change (rounded)\n\t\ttickaccum &= 0x0FF;\t\t\t\t// shave off high byte, keep roundoff bits\n\n\t\tchanged = Bump_Palette(palette1, jump);\t// increment palette\n\n\t\t/*\n\t\t.................. Wait for time increment to elapse ..................\n\t\t*/\n\t\tif (changed) {\n\t\t\twhile (TickCount.Time() < timer) {\n\t\t\t\t/*\n\t\t\t\t................. Update callback while waiting .................\n\t\t\t\t*/\n\t\t\t\tif (callback) {\n#if LIB_EXTERNS_RESOLVED\n\t\t\t\t\tSound_Callback();\t\t// should be removed!\n#endif\n\t\t\t\t\t(*cb_ptr)();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n#if LIB_EXTERNS_RESOLVED\n\t\tSound_Callback();\t\t// should be removed!\n#endif\n\t\tif (callback) {\n\t\t\t(*cb_ptr)();\n\t\t}\n\t} while (changed);\n\n}\t/* end of Fade_Palette_To */\n\n\n/***************************************************************************\n * Determine_Bump_Rate -- determines desired bump rate for fading          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tUBYTE *palette\t- palette to fade to\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tWORD delay\t\t- desired time delay in 60ths of a second\t\t\t\t\t*\n *\t\tWORD *ticks\t\t- output: loop ticks per color jump\t\t\t\t\t\t\t*\n *\t\tWORD *rate\t\t- output: color gun increment rate\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/27/1994 BR : Converted to 32-bit                                   *\n *   08/02/1994 SKB : Made private                                         *\n *=========================================================================*/\nPRIVATE VOID cdecl Determine_Bump_Rate(VOID *palette, WORD delay, WORD *ticks, \n\tWORD *rate)\n{\n\tWORD gun1;\t\t// Palette 1 gun value.\n\tWORD gun2;\t\t// Palette 2 gun value.\n\tWORD diff;\t\t// Maximum color gun difference.\t\n\tWORD tp;\t\t\t// Temporary tick accumulator.\n\tWORD index;\t\t// Color gun working index.\n\tLONG t;\t\t\t// Working tick intermediate value.\n\tWORD adiff;\t\t// Absolute difference between guns.\n\n\t/*\n\t------------------------ Find max gun difference -------------------------\n\t*/\n\tdiff = 0;\n\tfor (index = 0; index < PALETTE_BYTES; index++) {\n\t\tgun1 = ((UBYTE *)palette)[index];\n\t\tgun2 = CurrentPalette[index];\n\t\tadiff = ABS(gun1-gun2);\n\t\tdiff = MAX(diff, adiff);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tticks = (total time delay ) / (max gun diff)\n\tThe value is computed based on (delay * 256), for fixed-point math;\n\tthe lower bits represent the leftover from the division;  'ticks' is\n\treturned still shifted, so the low bits can be used to accumulate the\n\ttime more accurately; the caller must shift the accumulated value down\n\t8 bits to determine the actual elapsed time!\n\t------------------------------------------------------------------------*/\n\tt = ((LONG)delay) << 8;\n\tif (diff) {\n\t\tt /= diff;\n\t\tt = MIN((long)t, (long)0x7FFF);\n\t}\n\t*ticks = (WORD)t;\n\n\t/*------------------------------------------------------------------------\n\tAdjust the color gun rate value if the time to fade is faster than can \n\treasonably be performed given the palette change, ie if (ticks>>8)==0,\n\tand thus less than 1/60 of a second\n\t------------------------------------------------------------------------*/\n\ttp = *ticks;\n\t*rate = 1;\n\twhile (*rate <= diff && *ticks < 256) {\n\t\t*ticks += tp;\n\t\t*rate += 1;\n\t}\n\n}\t/* end of Determine_Bump_Rate */\n\n\n/***************************************************************************\n * Bump_Palette -- increments the palette one step, for fading             *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tpalette1\t\t- palette to fade towards\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tstep\t\t\t- max step amount, determined by Determine_Bump_Rate\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tFALSE = no change, TRUE = changed\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/27/1994 BR : Created.                                              *\n *   08/02/1994 SKB : Made private                                         *\n *=========================================================================*/\n#if(IBM)\nPRIVATE BOOL cdecl Bump_Palette(VOID *palette1, UWORD step)\n{\n\tBOOL\tchanged=FALSE;\t\t\t\t// Flag that palette has changed this tick.\n\tWORD\tindex;\t\t\t\t\t\t// Index to DAC register gun.\n\tWORD\tgun1,gun2;\t\t\t\t\t// Palette 1 gun value.\n\tUBYTE\tpalette[PALETTE_BYTES];\t// copy of current palette\n\n\t/*\n\t---------------------- Return if 'palette1' is NULL ----------------------\n\t*/\n\tif (!palette1) \n\t\treturn (FALSE);\n\n\t/*\n\t--------------------- Fading only supported in MCGA ----------------------\n\t*/\n\tif (Get_Video_Mode() != MCGA_MODE) {\t// was global GraphicMode\n\t\tSet_Palette(palette1);\n\t\treturn (FALSE);\n\t} \n\n\t/*\n\t------------------------ Copy the current palette ------------------------\n\t*/\n\tmemcpy(palette, CurrentPalette, 768);\n\n\t/*\n\t----------------------- Loop through palette bytes -----------------------\n\t*/\n\tfor (index = 0; index < PALETTE_BYTES; index++) {\n\t\tgun1 = ((UBYTE *)palette1)[index];\n\t\tgun2 = palette[index];\n\n\t\t/*\n\t\t............. If the colors match, go on to the next one ..............\n\t\t*/\n\t\tif (gun1 == gun2) continue;\n\n\t\tchanged = TRUE;\n\n\t\t/*\n\t\t.................. Increment current palette's color ..................\n\t\t*/\n\t\tif (gun2 < gun1) {\n\t\t\tgun2 += step;\n\t\t\tgun2 = MIN(gun2, gun1);\t\t// make sure we didn't overshoot it\n\t\t} \n\t\t/*\n\t\t.................. Decrement current palette's color ..................\n\t\t*/\n\t\telse {\n\t\t\tgun2 -= step;\n\t\t\tgun2 = MAX(gun2, gun1);\t\t// make sure we didn't overshoot it\n\t\t}\n\n\t\tpalette[index] = gun2;\n\t}\n\n\t/*\n\t----------------- Set current palette to the new palette -----------------\n\t*/\n\tif (changed) {\n\t\tSet_Palette(&palette[0]);\n\t}\n\n\treturn (changed);\n\n}\t/* end of Bump_Palette */\n\n#else\n\n\t/* This is already implemented in asm on the Amiga */\n\n#endif\n\n/**************************** End of palette.cpp ***************************/\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/PALETTE/PALETTE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Palette 32bit Library.                   *\n;*                                                                         *\n;*                    File Name : PALETTE.H                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : April 25, 1994                           *\n;*                                                                         *\n;*                  Last Update : April 27, 1994 [BRR]\t\t\t\t\t\t\t*\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef PALETTE_H\n#define PALETTE_H\n\n/*\n********************************* Constants *********************************\n*/\n#define RGB_BYTES\t\t\t3\n#define PALETTE_SIZE\t\t256\n#define PALETTE_BYTES\t768\n\n/*\n******************************** Prototypes *********************************\n*/\n/*\n-------------------------------- Palette.cpp --------------------------------\n*/\nVOID cdecl Set_Palette(VOID *palette);\nVOID cdecl Set_Palette_Color(VOID *palette, WORD color, VOID *data);\nVOID Fade_Palette_To(VOID *palette1, UWORD delay, VOID (*callback)() );\n\n/*\n-------------------------------- loadpal.cpp --------------------------------\n*/\nVOID cdecl Load_Palette(BYTE *palette_file_name, VOID *palette_pointer);\n\n/*\n------------------------------- morphpal.cpp --------------------------------\n*/\nVOID cdecl Morph_Palette (VOID *src_palette, VOID *dst_palette, UWORD delay,\n\tVOID *callback);\n\n/*\n---------------------------------- pal.asm ----------------------------------\n*/\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID Set_Palette_Range(VOID *palette);\nextern BOOL Bump_Color(VOID *palette, WORD changable, WORD target);\n\n#ifdef __cplusplus\n}\n#endif\nextern \"C\" extern UBYTE  CurrentPalette[];\t\t/* in pal.asm */\n\n\n#endif // PALETTE_H\n\n/***************************** End of palette.h ****************************/\n\u001a\n"
  },
  {
    "path": "WWFLAT32/PLAYCD/GETCD.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : GETCD.CPP\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : STEVE WETHERILL BASED ON JOE BOSTIC CODE *\n *                                                                         *\n *                   Start Date : 5/13/94\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : June 4, 1994   [SW]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *\t\tGetCDClass::GetCDClass\t--\tdefault constructor                       *\n *\t\tGetCDClass::~GetCDClass\t--\tdestructor                                *\n *\t\tGetCDClass::GetCDDrive\t--\treturns the logical CD drive              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <dos.h>\n\n#include \"wwstd.h\"\n#include \"playcd.h\"\n#include \"wwmem.h\"\n\n\n/***************************************************************************\n * GetCDClass -- default constructor\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *       none \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone                          \t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW   : Created.                                            *\n *=========================================================================*/\n\nGetCDClass::GetCDClass(VOID)\n{\n\tmemset ( this , 0 , sizeof ( GetCDClass ) ) ;\n\n\tif\t(DPMI_real_alloc(2, &cdDrive_addrp, &largestp))\n\t\texit(1);\n\n\tCDCount = 0;\n\tCDIndex = 0;\n\n\t/*\n\t** Set all CD drive placeholders to empty\n\t*/\n\tmemset (CDDrives, NO_CD_DRIVE, MAX_CD_DRIVES);\n\n\t/*\n\t** Dos will only currently support one cd drive so just\n\t** set the first entry to it.\n\t*/\n\tGetCDDrives();\n}\n\n/***************************************************************************\n * GetCDClass -- destructor                                                *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW: Created.                                          \t   *\n *=========================================================================*/\n\nGetCDClass::~GetCDClass(VOID)\n{\n\tif(cdDrive_addrp.seg)\n\t\tDPMI_real_free(cdDrive_addrp);\t\t// free up those conventional buffers\n}\n\n/***************************************************************************\n * GetCDDrive -- returns the logical CD drive                              *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tWORD logical_drive\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *=========================================================================*/\n\nvoid  GetCDClass::GetCDDrives(VOID)\n\n{\n\tfor (int lp = 0; lp < 26; lp++ ) {\n\t\t/*\n\t\t** This call determines if the current specifed drive is a\n\t\t** CD ROM drive.\n\t\t** Input:\n\t\t** AX = 150Bh\n\t\t** CX = CD rom drive letter to check (A = 0, B = 1)\n\t\t** Output:\n\t\t** AX = non zero if drive is a CD ROM, zero if it is not.\n\t\t** BX = Signature word (ADADh if CD rom extension are installed)\n\t\t*/\n\t\tsregs . es \t= cdDrive_addrp . seg ;\n\t\tregs . x . ebx  = 0;\n\t\tregs . x . eax  = 0x150B;\n\t\tregs . x . ecx  = lp;\n\t\tDPMI_real_intr ( 0x2F , & regs , & sregs ) ;\n\n\t\tif (regs.x.ebx == 0xADAD && regs.x.eax != 0) {\n\t\t\tCDDrives[CDCount++] = lp;\n\t\t}\n\t}\n}\n/* ==================================================================== */\n\n"
  },
  {
    "path": "WWFLAT32/PLAYCD/GETCD.CPP.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : GETCD.CPP\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : STEVE WETHERILL BASED ON JOE BOSTIC CODE *\n *                                                                         *\n *                   Start Date : 5/13/94\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : June 4, 1994   [SW]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *\t\tGetCDClass::GetCDClass\t--\tdefault constructor                       *\n *\t\tGetCDClass::~GetCDClass\t--\tdestructor                                *\n *\t\tGetCDClass::GetCDDrive\t--\treturns the logical CD drive              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <dos.h>\n\n#include \"wwstd.h\"\n#include \"playcd.h\"\n#include \"wwmem.h\"\n\n\n/***************************************************************************\n * GetCDClass -- default constructor\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *       none \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone                          \t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW   : Created.                                            *\n *=========================================================================*/\n\nGetCDClass::GetCDClass(VOID)\n{\n\tmemset ( this , 0 , sizeof ( GetCDClass ) ) ;\n\n\tif\t(DPMI_real_alloc(2, &cdDrive_addrp, &largestp))\n\t\texit(1);\n\n\tCDCount = 0;\n\tCDIndex = 0;\n\n\t/*\n\t** Set all CD drive placeholders to empty\n\t*/\n\tmemset (CDDrives, NO_CD_DRIVE, MAX_CD_DRIVES);\n\n\t/*\n\t** Dos will only currently support one cd drive so just\n\t** set the first entry to it.\n\t*/\n\tGetCDDrives();\n}\n\n/***************************************************************************\n * GetCDClass -- destructor                                                *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW: Created.                                          \t   *\n *=========================================================================*/\n\nGetCDClass::~GetCDClass(VOID)\n{\n\tif(cdDrive_addrp.seg)\n\t\tDPMI_real_free(cdDrive_addrp);\t\t// free up those conventional buffers\n}\n\n/***************************************************************************\n * GetCDDrive -- returns the logical CD drive                              *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tWORD logical_drive\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *=========================================================================*/\n\nvoid  GetCDClass::GetCDDrives(VOID)\n\n{\n\tfor (int lp = 0; lp < 26; lp++ ) {\n\t\t/*\n\t\t** This call determines if the current specifed drive is a\n\t\t** CD ROM drive.\n\t\t** Input:\n\t\t** AX = 150Bh\n\t\t** CX = CD rom drive letter to check (A = 0, B = 1)\n\t\t** Output:\n\t\t** AX = non zero if drive is a CD ROM, zero if it is not.\n\t\t** BX = Signature word (ADADh if CD rom extension are installed)\n\t\t*/\n\t\tsregs . es \t= cdDrive_addrp . seg ;\n\t\tregs . x . ebx  = 0;\n\t\tregs . x . eax  = 0x150B;\n\t\tDPMI_real_intr ( 0x2F , & regs , & sregs ) ;\n\n\t\tif (regs.x.ebx == 0xADAD && regs.x.eax != 0) {\n\t\t\tCDDrives[CDCount++] = lp;\n\t\t}\n\t}\n}\n/* ==================================================================== */\n\n"
  },
  {
    "path": "WWFLAT32/PLAYCD/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 27, 1995                           *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = playcd\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n        getcd.obj              &\n        playcd.obj\n#        redbook.obj     \n#        playcd.obj\n\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WWFLAT32/PLAYCD/PLAYCD.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nLOCALS ??\n\n\nDPMI_INTR equ\t031h\n\nGLOBAL \tDPMI_real_alloc   : near\nGLOBAL  DPMI_real_free    : near\nGLOBAL  DPMI_real_intr    : near\nGLOBAL  DPMI_real_call    : near\n\n\nSTRUC SEGSEL\n\t  segmen  dw ?\n \t  select  dw ?\nENDS\n\nSTRUC REGS \n\t_eax   dd ?\n\t_ebx   dd ?\n\t_ecx   dd ?\n\t_edx   dd ?\n\t_esi   dd ?\n\t_edi   dd ?\n\t_cflag dd ?\nENDS\n\nSTRUC SREGS \n\t_es  dw ?\n\t_cs  dw ?\n\t_ss  dw ?\n\t_ds  dw ?\n        _fs  dw ?\n\t_gs  dw ?\nENDS\n\nSTRUC DPMI_REGS\n       _edi  dd ?\n       _esi  dd ?\t\n       _ebp  dd ?\t\n       \t     dd ?\n       _ebx  dd ?\t\n       _edx  dd ?\t\n       _ecx  dd ?\t\n       _eax  dd ?\t\n       Flags dw ?\n       _es   dw ?\n       _ds   dw ?\n       _fs   dw ?\n       _gs   dw ?\n       _ip   dw ?\n       _cs   dw ?\n       _sp   dw ?\n       _ss   dw ?\n       \t     dd ?\n\t     dd\t?\n   size_ref  db\t?\t\nENDS\n    \n    \nCODESEG\n\n; int  DPMI_real_alloc ( UINT , SEGREG * , USHORT * ) ;\n\nPROC DPMI_real_alloc C near \n\tUSES\tebx , edx\n\tARG\tparagra        : DWORD\n\tARG\tblk_segptr    : DWORD\n\tARG\tlargest_blkptr : DWORD\n\n\tmov\teax, 0100h\n\tmov\tebx, [paragra]\n\tint\tDPMI_INTR\n\n\tjnc\t??dpmi_succed\n\tmov\tebx, [largest_blkptr]\n\tmov\t[ word ptr ebx ] , bx\n\tmovzx\teax , al\n \tret\n\n??dpmi_succed:\n\tmov\tebx, [blk_segptr]\n\tmov\t[(type SEGSEL ptr ebx). segmen ] , ax\n\tmov\t[(type SEGSEL ptr ebx). select ] , dx\n\txor\teax , eax\n\tret\n\t\t\nENDP DPMI_real_alloc\t\n\n\n;**************************************************************************\n; int  DPMI_real_free ( UINT ) ;\n\nPROC DPMI_real_free C near \n\tUSES\teax , edx\n\tARG\tblk_selec  : DWORD\n\n\tmov\teax, 0101h\n\tmov\tedx, [blk_selec]\n\tshr\tedx , 16\n\tint\tDPMI_INTR\n \tret\nENDP DPMI_real_free\t\n\n\nPROC DPMI_real_intr C near \n\tUSES\teax , ebx , ecx , edx , edi , esi \n\tARG\tvector  : dword\n\tARG     regs_ptr: dword\n\tARG     sreg_ptr: dword\n\n\tLOCAL\tregblk : DPMI_REGS\n\n\tlea\tedi , [ regblk ]\n\txor\teax , eax\n\tlea\tecx , [ regblk . size_ref ]\n\tsub\tecx , edi\n\tshr\tecx , 2\n\trep\tstosd\n\n  \tmov\tebx , [ regs_ptr ]\n\tmov\teax , [ (type REGS ptr ebx) . _eax ] \n\tmov\t[ regblk . _eax ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _ebx ] \n\tmov\t[ regblk . _ebx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _ecx ] \n\tmov\t[ regblk . _ecx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _edx ] \n\tmov\t[ regblk . _edx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _esi ] \n\tmov\t[ regblk . _esi ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _edi ] \n\tmov\t[ regblk . _edi ] , eax\n\n\n  \tmov\tebx , [ sreg_ptr ]\n\tmov\tax , [ (type SREGS ptr ebx) . _es ] \n\tmov\t[ regblk . _es ] , ax\n\n\tmov\tax , [ (type SREGS ptr ebx) . _ds ] \n\tmov\t[ regblk . _ds ] , ax\n\n\tmov\teax , 0300h\n\tmov\tebx , [ vector ]\n\txor     bh , bh\n\txor \tecx , ecx\n\tlea\tedi , [ regblk ]\n\n\tint\tDPMI_INTR\n\n  \tmov\tebx , [ regs_ptr ]\n\tmov\teax , [ regblk . _eax ] \n\tmov\t[ (type REGS ptr ebx) . _eax ] , eax\n\n\tmov\teax , [ regblk . _ebx ] \n\tmov\t[ (type REGS ptr ebx) . _ebx ] , eax\n\n\tmov\teax , [ regblk . _ecx ] \n\tmov\t[ (type REGS ptr ebx) . _ecx ] , eax\n\n\tmov\teax , [ regblk . _edx ] \n\tmov\t[ (type REGS ptr ebx) . _edx ] , eax\n\n\tmov\teax , [ regblk . _esi ] \n\tmov\t[ (type REGS ptr ebx) . _esi ] , eax\n\n\tmov\teax , [ regblk . _edi ] \n\tmov\t[ (type REGS ptr ebx) . _edi ] , eax\n\n\n  \tmov\tebx , [ sreg_ptr ]\n\tmov\tax , [ regblk . _es ] \n\tmov\t[ (type SREGS ptr ebx) . _es ] , ax\n\n\tmov\tax , [ regblk . _ds ] \n\tmov\t[ (type SREGS ptr ebx) . _ds ] , ax\n\n \tret\nENDP DPMI_real_intr\t\n\n\nPROC DPMI_real_call C near \n\tUSES\teax , ebx , ecx , edx , edi , esi \n\tARG\tvector  : dword\n\tARG     regs_ptr: dword\n\tARG     sreg_ptr: dword\n\n\tLOCAL\tregblk : DPMI_REGS\n\n\n\tlea\tedi , [ regblk ]\n\txor\tal , al\n\tlea\tecx , [ regblk . size_ref ]\n\tsub\tecx , edi\n\trep\tmovsb\n\n\n  \tmov\tebx , [ regs_ptr ]\n\tmov\teax , [ (type REGS ptr ebx) . _eax ] \n\tmov\t[ regblk . _eax ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _ebx ] \n\tmov\t[ regblk . _ebx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _ecx ] \n\tmov\t[ regblk . _ecx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _edx ] \n\tmov\t[ regblk . _edx ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _esi ] \n\tmov\t[ regblk . _esi ] , eax\n\n\tmov\teax , [ (type REGS ptr ebx) . _edi ] \n\tmov\t[ regblk . _edi ] , eax\n\n\n  \tmov\tebx , [ sreg_ptr ]\n\tmov\tax , [ (type SREGS ptr ebx) . _es ] \n\tmov\t[ regblk . _es ] , ax\n\n\tmov\tax , [ (type SREGS ptr ebx) . _ds ] \n\tmov\t[ regblk . _ds ] , ax\n\n;\tmov\teax , 0300h\n;\tmov\tebx , [ vector ]\n;\txor     bh , bh\n;\txor \tecx , ecx\n;\tlea\tedi , [ regblk ]\n\n;\tint\tDPMI_INTR\n\n  \tmov\tebx , [ regs_ptr ]\n\tmov\teax , [ regblk . _eax ] \n\tmov\t[ (type REGS ptr ebx) . _eax ] , eax\n\tmov\teax , [ regblk . _ebx ] \n\tmov\t[ (type REGS ptr ebx) . _ebx ] , eax\n\tmov\teax , [ regblk . _ecx ] \n\tmov\t[ (type REGS ptr ebx) . _ecx ] , eax\n\tmov\teax , [ regblk . _edx ] \n\tmov\t[ (type REGS ptr ebx) . _edx ] , eax\n\n\tmov\teax , [ regblk . _esi ] \n\tmov\t[ (type REGS ptr ebx) . _esi ] , eax\n\tmov\teax , [ regblk . _edi ] \n\tmov\t[ (type REGS ptr ebx) . _edi ] , eax\n\n\n  \tmov\tebx , [ sreg_ptr ]\n\tmov\tax , [ regblk . _es ] \n\tmov\t[ (type SREGS ptr ebx) . _es ] , ax\n\n\tmov\tax , [ regblk . _ds ] \n\tmov\t[ (type SREGS ptr ebx) . _ds ] , ax\n\n \tret\nENDP DPMI_real_call\n\nEND\n\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/PLAYCD/PLAYCD.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB\t  \t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : PLAYCD.H\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : STEVE WETHERILL\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Start Date : 5/13/94\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : June 4, 1994   [SW]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*/\n\n#ifndef PLAYCD_H\n#define PLAYCD_H\n\n/* ==================================================================== */\n/* Defines */\n/* ==================================================================== */\n\n#define\tCHLEFT\t0\n#define\tCHRIGHT\t1\n#define\tCHBOTH\t2\n\n#define\tAUDIO_START_MIN\t1\n#define\tAUDIO_START_SEC  44\n\ntypedef struct {\n\t\t\t\t\t  unsigned short seg ;\n \t\t\t\t\t  unsigned short sel ;\n\t\t\t\t\t} SEGSEL ;\n\n\n\n\nextern \"C\" int  DPMI_real_alloc ( UINT , SEGSEL * , USHORT * ) ;\nextern \"C\" int  DPMI_real_free ( SEGSEL  ) ;\nextern \"C\" void DPMI_real_intr ( int , union REGS * , struct SREGS * );\nextern \"C\" void DPMI_real_call ( void * funct , union REGS * , struct SREGS * );\n\n\n\n\n/* ==================================================================== */\n/* Data structures */\n/* ==================================================================== */\n\n// Audio Track Info request block\n\nstruct\tTinfoType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tTrInfo;\n\tUBYTE\t\tTrack;\n\tULONG\t\tStart;\n\tUBYTE\t\tTrCtrl;\n};\n\n// Audio Track Status Control Block\n\nstruct\tStatType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tStatInfo;\n\tUWORD\t\tStat;\n\tULONG\t\tStart;\n\tULONG\t\tEnd;\n\t};\n\n// Audio Track Volume control block\n\nstruct\tVolmType\t{\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tTrInfo;\n\tUBYTE\t\tIn0;\n\tUBYTE\t\tVol0;   \n\tUBYTE\t\tIn1;\n\tUBYTE\t\tVol1;   \n\tUBYTE\t\tIn2;\n\tUBYTE\t\tVol2;   \n\tUBYTE\t\tIn3;\n\tUBYTE\t\tVol3;   \n\t};\n\n// Audio Track Play request block\n\nstruct\tPlayType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tAddrMd;\n\tULONG\t\tStart;\n\tULONG\t\tCntSect;\n\t};\n\n\n// Audio Track Stop request block\n\nstruct\tStopType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\t};\n\n\n/***************************************************************************\n * GetCDClass -- object which will return logical CD drive\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/04/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n#define MAX_CD_DRIVES 26\n#define NO_CD_DRIVE -1\n\nclass\tGetCDClass {\n\nprotected:\n\n\tunion   REGS \tregs;\n\tstruct SREGS  sregs;\n\n\tSEGSEL \t\tcdDrive_addrp;\n\tUWORD\t\t\tlargestp;\n\n\tint\tCDDrives[MAX_CD_DRIVES];\t//Array containing CD drive letters\n\tint\tCDCount;\t\t\t\t\t\t\t//Number of available CD drives\n\tint\tCDIndex;\n\t\npublic:\n\n\tGetCDClass(VOID);\t\t\t\t\t// This is the default constructor\n\t~GetCDClass(VOID);\t\t\t\t// This is the destructor\n\n\tinline\tint\tGet_First_CD_Drive(void);\n\tinline\tint\tGet_Next_CD_Drive(void);\n\tinline\tint\tGet_Number_Of_Drives(void) {return (CDCount);};\n\nprivate:\n        VOID  GetCDDrives(VOID);\n\t\n};\n\n/***********************************************************************************************\n * GCDC::Get_Next_CD_Drive -- return the logical drive number of the next CD drive             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Logical drive number of a cd drive or -1 if none                                  *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/21/96 3:50PM ST : Created                                                              *\n *=============================================================================================*/\ninline int GetCDClass::Get_Next_CD_Drive(void)\n{\n\tif (CDCount){\n\t\tif (CDIndex == CDCount) CDIndex = 0;\n\t\treturn (CDDrives[CDIndex++]);\n\t}else{\n\t\treturn (-1);\n\t}\n}\n\n\n\n/***************************************************************************\n * GCDC::Get_First_CD_Drive -- return the number of the first CD drive     *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * OUTPUT:                                                                 *\n *\t\t\tlogical drive number \t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *   12/4/95    ST : fixed for Win95                                       *\n *=========================================================================*/\ninline int GetCDClass::Get_First_CD_Drive(void)\n{\n\tCDIndex = 0;\n\treturn (Get_Next_CD_Drive());\n}\n\n/***************************************************************************\n * RedBookClass -- adds red book functionality\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tthis class inherits from GetCDClass and adds red book play functionality*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/04/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n\nclass RedBookClass : public GetCDClass {\n\nprivate:\n\n\tSEGSEL\t\tTinfo_addrp;\n\tSEGSEL\t\tStat_addrp;\n\tSEGSEL\t\tStop_addrp;\n\tSEGSEL\t\tVolm_addrp;\n\tSEGSEL  \t   Play_addrp;\n\n\tStopType \tStop;\n\tPlayType\t\tPlay;\n\tVolmType\t\tVolm;\n\tStatType\t\tStat;\n\tTinfoType\tTinfo;\n\npublic:\n\n\tRedBookClass(VOID);\t\t\t\t\t// This is the default constructor\n\t~RedBookClass(VOID);\t\t\t\t\t// This is the destructor\n\n\tULONG\tRedToHS(ULONG i);\n\tULONG MSFtoRed(UBYTE m, UBYTE s, UBYTE f);\n\tVOID  FullCDVolume(UBYTE chan);\n\tVOID  PlayTrack(UWORD track);\n\tVOID  Play_CD_MSL(UWORD min_sec, UWORD len);\n\tVOID  PlayMSF(UBYTE startM, UBYTE startS, UBYTE startF, \n\t\t\t\tUBYTE endM, UBYTE endS, UBYTE endF, UBYTE chan);\n\tUWORD CheckCDMusic(VOID);\n\tVOID  StopCDMusic(VOID);\n\n};\n\n\n/***************************** End of Playcd.h ****************************/\n\n#endif // PLAYCD_H\n"
  },
  {
    "path": "WWFLAT32/PLAYCD/PLAYCD.H.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB\t  \t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : PLAYCD.H\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : STEVE WETHERILL\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Start Date : 5/13/94\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : June 4, 1994   [SW]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*/\n\n#ifndef PLAYCD_H\n#define PLAYCD_H\n\n/* ==================================================================== */\n/* Defines */\n/* ==================================================================== */\n\n#define\tCHLEFT\t0\n#define\tCHRIGHT\t1\n#define\tCHBOTH\t2\n\n#define\tAUDIO_START_MIN\t1\n#define\tAUDIO_START_SEC  44\n\ntypedef struct {\n\t\t\t\t\t  unsigned short seg ;\n \t\t\t\t\t  unsigned short sel ;\n\t\t\t\t\t} SEGSEL ;\n\n\n\n\nextern \"C\" int  DPMI_real_alloc ( UINT , SEGSEL * , USHORT * ) ;\nextern \"C\" int  DPMI_real_free ( SEGSEL  ) ;\nextern \"C\" void DPMI_real_intr ( int , union REGS * , struct SREGS * );\nextern \"C\" void DPMI_real_call ( void * funct , union REGS * , struct SREGS * );\n\n\n\n\n/* ==================================================================== */\n/* Data structures */\n/* ==================================================================== */\n\n// Audio Track Info request block\n\nstruct\tTinfoType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tTrInfo;\n\tUBYTE\t\tTrack;\n\tULONG\t\tStart;\n\tUBYTE\t\tTrCtrl;\n};\n\n// Audio Track Status Control Block\n\nstruct\tStatType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tStatInfo;\n\tUWORD\t\tStat;\n\tULONG\t\tStart;\n\tULONG\t\tEnd;\n\t};\n\n// Audio Track Volume control block\n\nstruct\tVolmType\t{\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tMDescr;\n\n\tUWORD\t\tTrnsAdOff;\n\tUWORD\t\tTrnsAdSeg;\n\n\tUWORD\t\tCntTrns;\n\tUWORD\t\tStSect;\n\n\tUWORD\t\tVolIDOff;\n\tUWORD\t\tVolIDSeg;\n\n\tUBYTE\t\tTrInfo;\n\tUBYTE\t\tIn0;\n\tUBYTE\t\tVol0;   \n\tUBYTE\t\tIn1;\n\tUBYTE\t\tVol1;   \n\tUBYTE\t\tIn2;\n\tUBYTE\t\tVol2;   \n\tUBYTE\t\tIn3;\n\tUBYTE\t\tVol3;   \n\t};\n\n// Audio Track Play request block\n\nstruct\tPlayType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\tUBYTE\t\tAddrMd;\n\tULONG\t\tStart;\n\tULONG\t\tCntSect;\n\t};\n\n\n// Audio Track Stop request block\n\nstruct\tStopType {\n\tUBYTE\t\tLength;\n\tUBYTE\t\tSubCd;\n\tUBYTE\t\tCommand;\n\tUWORD\t\tStatus;\n\tUBYTE\t\tRsvd[8];\n\t};\n\n\n/***************************************************************************\n * GetCDClass -- object which will return logical CD drive\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/04/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n#define MAX_CD_DRIVES 26\n#define NO_CD_DRIVE -1\n\nclass\tGetCDClass {\n\nprotected:\n\n\tunion   REGS \tregs;\n\tstruct SREGS  sregs;\n\n\tSEGSEL \t\tcdDrive_addrp;\n\tUWORD\t\t\tlargestp;\n\n\tint\tCDDrives[MAX_CD_DRIVES];\t//Array containing CD drive letters\n\tint\tCDCount;\t\t\t\t\t\t\t//Number of available CD drives\n\tint\tCDIndex;\n\t\npublic:\n\n\tGetCDClass(VOID);\t\t\t\t\t// This is the default constructor\n\t~GetCDClass(VOID);\t\t\t\t// This is the destructor\n\n\tinline\tint\tGet_First_CD_Drive(void);\n\tinline\tint\tGet_Next_CD_Drive(void);\n\tinline\tint\tGet_Number_Of_Drives(void) {return (CDCount);};\n\nprivate:\n\tVOID  GetCDDrive(VOID);\n\t\n};\n\n/***********************************************************************************************\n * GCDC::Get_Next_CD_Drive -- return the logical drive number of the next CD drive             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Logical drive number of a cd drive or -1 if none                                  *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/21/96 3:50PM ST : Created                                                              *\n *=============================================================================================*/\ninline int GetCDClass::Get_Next_CD_Drive(void)\n{\n\tif (CDCount){\n\t\tif (CDIndex == CDCount) CDIndex = 0;\n\t\treturn (CDDrives[CDIndex++]);\n\t}else{\n\t\treturn (-1);\n\t}\n}\n\n\n\n/***************************************************************************\n * GCDC::Get_First_CD_Drive -- return the number of the first CD drive     *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * OUTPUT:                                                                 *\n *\t\t\tlogical drive number \t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *   12/4/95    ST : fixed for Win95                                       *\n *=========================================================================*/\ninline int GetCDClass::Get_First_CD_Drive(void)\n{\n\tCDIndex = 0;\n\treturn (Get_Next_CD_Drive());\n}\n\n/***************************************************************************\n * RedBookClass -- adds red book functionality\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tthis class inherits from GetCDClass and adds red book play functionality*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/04/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n\nclass RedBookClass : public GetCDClass {\n\nprivate:\n\n\tSEGSEL\t\tTinfo_addrp;\n\tSEGSEL\t\tStat_addrp;\n\tSEGSEL\t\tStop_addrp;\n\tSEGSEL\t\tVolm_addrp;\n\tSEGSEL  \t   Play_addrp;\n\n\tStopType \tStop;\n\tPlayType\t\tPlay;\n\tVolmType\t\tVolm;\n\tStatType\t\tStat;\n\tTinfoType\tTinfo;\n\npublic:\n\n\tRedBookClass(VOID);\t\t\t\t\t// This is the default constructor\n\t~RedBookClass(VOID);\t\t\t\t\t// This is the destructor\n\n\tULONG\tRedToHS(ULONG i);\n\tULONG MSFtoRed(UBYTE m, UBYTE s, UBYTE f);\n\tVOID  FullCDVolume(UBYTE chan);\n\tVOID  PlayTrack(UWORD track);\n\tVOID  Play_CD_MSL(UWORD min_sec, UWORD len);\n\tVOID  PlayMSF(UBYTE startM, UBYTE startS, UBYTE startF, \n\t\t\t\tUBYTE endM, UBYTE endS, UBYTE endF, UBYTE chan);\n\tUWORD CheckCDMusic(VOID);\n\tVOID  StopCDMusic(VOID);\n\n};\n\n\n/***************************** End of Playcd.h ****************************/\n\n#endif // PLAYCD_H\n\u001a\n"
  },
  {
    "path": "WWFLAT32/PLAYCD/REDBOOK.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB\t  \t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                    File Name : REDBOOK.CPP\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : STEVE WETHERILL (FROM SCOTT BOWEN CODE)  *\n *                                                                         *\n *                   Start Date : 5/13/94\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : June 4, 1994   [SW]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *\t\tRedBookClass::~RedBookClass(VOID)\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tRedBookClass::RedToHS(ULONG i)\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tRedBookClass::MSFtoRed(UBYTE m, UBYTE s, UBYTE f)\t\t\t\t\t\t\t*\n *\t\tRedBookClass::FullCDVolume(UBYTE chan)\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tRedBookClass::PlayTrack(UWORD track)\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tRedBookClass::Play_CD_MSL(UWORD min_sec, UWORD len)\t\t\t\t\t\t*\n *\t\tRedBookClass::PlayMSF(UBYTE startM, UBYTE startS, UBYTE startF,\t\t*\n * \t\t\t  \t\t\t\tUBYTE endM, UBYTE endS, UBYTE endF, UBYTE chan)\t\t*\n *\t\tRedBookClass::CheckCDMusic(VOID)\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tRedBookClass::StopCDMusic(VOID)\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <dos.h>\n\n#include \"wwstd.h\"\n#include \"playcd.h\"\n#include \"wwmem.h\"\n\n\n/***************************************************************************\n * RedBookClass -- default constructor\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *      \tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *\t\tcalls GetCDDrive()\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * HISTORY:                                                                *\n *   05/25/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n\nRedBookClass::RedBookClass(VOID)\n\t: GetCDClass()\t\t\t// call the base constructor\n\n{\n\tSEGSEL tmpadr ;\n\n\ttmpadr = cdDrive_addrp;\n\tmemset ( this  , 0 , sizeof ( RedBookClass )\t) ;\n\tcdDrive_addrp = tmpadr ;\n\n\tStop.Length\t\t=\t13;\n\tStop.Command\t=\t133;\n\n\tTinfo.Length\t=\t26;\n\tTinfo.Command\t=\t3;\n\tTinfo.CntTrns\t=\t7;\n\tTinfo.TrInfo\t=\t11;\n\n\tPlay.Length\t\t=\t22;\n\tPlay.Command\t=\t132;\n\tPlay.AddrMd\t\t=\t1;\n\t\n\tVolm.Length\t\t=\t26;\n\tVolm.Command\t=\t12;\n\tVolm.CntTrns\t=\t9;\n\tVolm.TrInfo\t\t=\t3;\n\tVolm.In1\t\t\t=\t1;\n\tVolm.In2\t\t\t=\t2;\n\tVolm.In3\t\t\t=\t3;\n\t\n\tStat.Length\t\t=\t26;\n\tStat.Command\t=\t3;\n\tStat.CntTrns\t=\t11;\n\tStat.StatInfo\t=\t15;\n\t\t\t\t\t\t\t\n\tif\t(DPMI_real_alloc(sizeof(TinfoType)/16+1, &Tinfo_addrp, &largestp))\n\t\texit(1);\n\n\tif\t(DPMI_real_alloc(sizeof(StatType)/16+1, &Stat_addrp, &largestp))\n\t\texit(1);\n\n\tif\t(DPMI_real_alloc(sizeof(VolmType)/16+1, &Volm_addrp, &largestp))\n\t\texit(1);\n\n\tif\t(DPMI_real_alloc(sizeof(PlayType)/16+1, &Play_addrp, &largestp))\n\t\texit(1);\n\n\tif\t(DPMI_real_alloc(sizeof(StopType)/16+1, &Stop_addrp, &largestp))\n\t\texit(1);\n\n\tGetCDDrive();\n\n}\n\n/***************************************************************************\n * REDBOOKCLASS -- destructor                                              *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *=========================================================================*/\n\nRedBookClass::~RedBookClass(VOID)\n{\n\tif(Tinfo_addrp.seg)\n\t\tDPMI_real_free(Tinfo_addrp);\t\t// free up those conventional buffers\n\n\tif(Stat_addrp.seg)\n\t\tDPMI_real_free(Stat_addrp);\n\n\tif(Volm_addrp.seg)\n\t\tDPMI_real_free(Volm_addrp);\n\n\tif(Play_addrp.seg)\n\t\tDPMI_real_free(Play_addrp);\n\n\tif(Stop_addrp.seg)\n\t\tDPMI_real_free(Stop_addrp);\n}\n\n/***************************************************************************\n * REDTOHS -- RedBook to High-Sierra conversion                            *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tULONG\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:    \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tULONG\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\n\nULONG RedBookClass::RedToHS(ULONG i)\n{\n\treturn( ((i>>16) & 0xFF) * 60 * 75) + ( ((i>>8) & 0xFF) * 75) + (i & 0xFF);\n}\n\n/***************************************************************************\n * MSFTORED -- Minute, Second, Frame to RedBook conversion                 *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *   \t\tUBYTE\tminute\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * \t\tUBYTE\tsecond\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t  \t\tUBYTE\tframe\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:          \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tULONG\tRedBook\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *=========================================================================*/\n\nULONG  RedBookClass::MSFtoRed(UBYTE m, UBYTE s, UBYTE f)\n{\n\treturn( ((ULONG)m << 16) + ((ULONG)s << 8) + (ULONG)f );\n}\n\n/***************************************************************************\n * FULLCDVOLUME -- set full volume                                         *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tUBYTE channel\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\tCHLEFT\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\tCHRIGHT\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\tCHBOTH\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *    \t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *=========================================================================*/\n\nVOID  RedBookClass::FullCDVolume(UBYTE chan)\n{\n\n\tVolm.Vol0 = Volm.Vol1 = Volm.Vol2 = Volm.Vol3 = 255;\n\n\tVolm.TrnsAdOff = offsetof\t(VolmType, TrInfo);\n\tVolm.TrnsAdSeg = Volm_addrp.seg;\n\n\tif(chan == CHLEFT)\n\t{\n//\t\tVolm.In0 = 0;\n//\t\tVolm.In1 = 3;\n//\t\tVolm.In2 = 3;\n//\t\tVolm.In3 = 3;\n\t\tVolm.Vol1 = 0;\n\t}\n\telse if(chan == CHRIGHT)\n\t{\n//\t\tVolm.In0 = 3;\n//\t\tVolm.In1 = 1;\n//\t\tVolm.In2 = 3;\n//\t\tVolm.In3 = 3;\n\t\tVolm.Vol0 = 0;\n\t}\n\telse\t\t\t/* both channels */\n\t{\n\t\tVolm.In0 = 0;\n\t\tVolm.In1 = 1;\n\t\tVolm.In2 = 2;\n\t\tVolm.In3 = 3;\n\t}\n\n//\tWriteRealMem(REALPTR(Volm_addrp) << 16, &Volm, sizeof(VolmType));\n\tMem_Copy ( &Volm , (void *) ( Volm_addrp.seg << 4 ) , sizeof(VolmType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = 0x0000;\n\tsregs.es   = Volm_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs, & sregs);\n\n//\tReadRealMem(&Volm, REALPTR(Volm_addrp) << 16, sizeof(VolmType));\n\tMem_Copy ( (void *) ( Volm_addrp . seg << 4 ), &Volm ,sizeof(VolmType));\n}\n\n\n\n/***************************************************************************\n * PLAYTRACK -- play a track                                               *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n * \t\tUWORD\ttrack\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *=========================================================================*/\n\nVOID  RedBookClass::PlayTrack(UWORD track)\n{\n\n\tStopCDMusic();\n\n\tTinfo.Track = track;\n\n\tTinfo.TrnsAdOff = offsetof\t(TinfoType, TrInfo);\n\tTinfo.TrnsAdSeg = Tinfo_addrp.seg;\n\n//\tWriteRealMem(REALPTR(Tinfo_addrp) << 16, &Tinfo, sizeof(TinfoType));\n\tMem_Copy ( &Tinfo , (void *) ( Tinfo_addrp.seg << 4 ) , sizeof(TinfoType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx\t= cdDrive[0];\n\tregs.x.ebx = 0x0000;\n\tsregs.es \t= Tinfo_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs, &sregs);\t\t// gets start time of track in Tinfo.Start\n\n//\tReadRealMem(&Tinfo, REALPTR(Tinfo_addrp) << 16, sizeof(TinfoType));\n\tMem_Copy ( (void *) ( Tinfo_addrp.seg << 4 ) , &Tinfo, sizeof(TinfoType));\n\n\n\n\n\tPlay.Start = Tinfo.Start;\n\tTinfo.Track++;\n\n\tTinfo.TrnsAdOff = offsetof\t(TinfoType, TrInfo);\n\tTinfo.TrnsAdSeg = Tinfo_addrp.seg;\n\n//\tWriteRealMem(REALPTR(Tinfo_addrp) << 16, &Tinfo, sizeof(TinfoType));\n\tMem_Copy ( &Tinfo , (void *) ( Tinfo_addrp.seg << 4 ) , sizeof(TinfoType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = 0x0000;\n\tsregs.es  = Tinfo_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs , &sregs);\t\t// gets start time of following track in Tinfo.Start\n\n//\tReadRealMem(&Tinfo, REALPTR(Tinfo_addrp) << 16, sizeof(TinfoType));\n\tMem_Copy ( (void *) ( Tinfo_addrp.seg << 4 ) , &Tinfo, sizeof(TinfoType));\n\n\n\n\tPlay.CntSect  = RedToHS(Tinfo.Start) - RedToHS(Play.Start) - 1;\n\n//\tWriteRealMem(REALPTR(Play_addrp) << 16, &Play, sizeof(PlayType));\n\tMem_Copy ( &Play , (void *) ( Play_addrp.seg << 4 ) , sizeof(PlayType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = 0x0000;\n\tsregs.es \t= Play_addrp.seg;\n\n  \tDPMI_real_intr(0x2F, &regs, &sregs);\n\n//\tReadRealMem(&Play, REALPTR(Play_addrp) << 16, sizeof(PlayType));\n\tMem_Copy ( (void *) ( Play_addrp.seg << 4 ) , &Play, sizeof(PlayType));\n\n\n\tFullCDVolume(CHBOTH);\n}\n\n\n/***************************************************************************\n * PLAY_CD_MSL -- play cd from start min_sec for len                       *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tUWORD\tmin_sec\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUWORD\tLen\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/26/1994 SW : Created.                                              *\n *=========================================================================*/\n\n\nVOID  RedBookClass::Play_CD_MSL(UWORD min_sec, UWORD len) \n{\n\tUWORD startM, startS, startF;\n\tUWORD endM, endS, endF;\n\n\tif (!len)\n\t\treturn;\n\n\tendM = startM = (min_sec >> 8) + AUDIO_START_MIN;\n\tendS = startS = (min_sec & 0xFF) + AUDIO_START_SEC;\n\tstartF = endF = 0;\n\n\twhile (len > 59) {\n\t\tendM++;\n\t\tlen -= 60;\n\t}\n\n\tendS += len;\n\tif (endS > 59) {\n\t\tendM++;\n\t\tendS -= 60;\n\t}\n\n\tPlayMSF((UBYTE) startM, (UBYTE)startS, (UBYTE)startF, (UBYTE)endM, (UBYTE)endS, (UBYTE)endF, 2 /* chan */);\n}\n\n\n/***************************************************************************\n * PlayMSF -- Play Minute, Second, Frame to Minute, Second, Frame\t\t\t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tUBYTE\tstartM\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tstartS\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tstartF\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *    \tUBYTE\tendM\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tendS\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tendF\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tchan\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/27/1994 SW : Created.                                              *\n *=========================================================================*/\n\n\nVOID  RedBookClass::PlayMSF(UBYTE startM, UBYTE startS, UBYTE startF, UBYTE endM, UBYTE endS, UBYTE endF, UBYTE chan)\n{\n\n\tPlay.Start = MSFtoRed(startM, startS, startF);\n\tPlay.CntSect  = RedToHS(MSFtoRed(endM, endS, endF)) - RedToHS(Play.Start) - 1;\n\n//\tWriteRealMem(REALPTR(Play_addrp) << 16, &Play, sizeof(PlayType));\n\tMem_Copy ( &Play , (void *) ( Play_addrp.seg << 4 ) , sizeof(PlayType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = offsetof (PlayType, Length);\n\tsregs.es \t= Play_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs, &sregs);\n\n//\tReadRealMem(&Play, REALPTR(Play_addrp) << 16, sizeof(PlayType));\n\tMem_Copy ( (void *) ( Play_addrp.seg << 4 ) , &Play, sizeof(PlayType));\n\n\tFullCDVolume(chan);\n\n}\n\n/***************************************************************************\n * CheckCDMusic -- Check for CD playing\t\t\t\t\t   \t\t\t\t\t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *    \tUBYTE\tstartM\t\t\t  \t\t\t\t\t\t\t\t\t\t \t\t\t\t\t*\n *\t\t\tUBYTE\tstartS\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tstartF\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t*\n *    \tUBYTE\tendM\t\t\t\t  \t\t\t\t\t\t\t\t\t\t \t\t\t\t\t*\n *\t\t\tUBYTE\tendS\t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tendF\t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tUBYTE\tchan\t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                             \t\t\t\t\t\t\t*\n *\t\t\tUWORD\tTRUE if playing else FALSE                 \t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/27/1994 SW : Created.                                              *\n *=========================================================================*/\n\n\nUWORD  RedBookClass::CheckCDMusic(VOID)\n{\n\t\n\tStat.TrnsAdOff = offsetof\t(StatType, StatInfo);\n\tStat.TrnsAdSeg = Stat_addrp.seg;\n\n//\tWriteRealMem(REALPTR(Stat_addrp) << 16, &Stat, sizeof(StatType));\n\tMem_Copy ( &Stat , (void *) ( Stat_addrp.seg << 4 ) , sizeof(StatType));\n\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = offsetof (StatType, Length);\n\tregs.x.eax = 0x1510;\n\tsregs.es \t= Stat_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs, &sregs);\n\n//\tReadRealMem(&Stat, REALPTR(Stat_addrp) << 16, sizeof(StatType));\n\tMem_Copy ( (void *) ( Stat_addrp.seg << 4 ) , &Stat, sizeof(StatType));\n\n\treturn (Stat.Status&0x200);\n}\n\n/***************************************************************************\n * STOPCDMUSIC -- stop CD playing                                          *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone\t\t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/27/1994  SW : Created.                                             *\n *=========================================================================*/\n\nVOID  RedBookClass::StopCDMusic(VOID)\n{\n\n//\tWriteRealMem(REALPTR(Stop_addrp) << 16, &Stop, sizeof(StopType));\n\tMem_Copy ( &Stop , (void *) ( Stop_addrp.seg << 4 ) , sizeof(StopType));\n\n\tregs.x.eax = 0x1510;\n\tregs.x.ecx = cdDrive[0];\n\tregs.x.ebx = offsetof (StopType, Length);\n\tsregs.es \t= Stop_addrp.seg;\n\n\tDPMI_real_intr(0x2F, &regs, &sregs);\n\n//\tReadRealMem(&Stop, REALPTR(Stop_addrp) << 16, sizeof(StopType));\n\tMem_Copy ( (void *) ( Stop_addrp.seg << 4 ) , &Stop, sizeof(StopType));\n\n}\n\n"
  },
  {
    "path": "WWFLAT32/PROJECT.CFG",
    "content": "#***************************************************************************\n# development configuration switches\n\nCC_CFG\t  \t= /i=$(%WWFLAT)\\include /d2 /fh /of+ /zp1 /5s /s\nASM_CFG\t\t= /i. /i$(%WWFLAT)\\include /zd /t /m /w+ /jJUMPS /ml\nLIB_CFG   \t= /b /n /n\nLINK_CFG  \t= option stack=32k debug all\n\n#***************************************************************************\n# Release configuration switches\n\n#CC_CFG\t  = /i=$(%WWFLAT)\\include /d1 /oateirl /s /fh /zp1 /5s\n#ASM_CFG\t  = /i$(%WWFLAT)\\include /zd /t /m /w+ /jJUMPS /ml\n#LIB_CFG   = /b /n /n\n#LINK_CFG  = option stack=32k debug all\n\n\n"
  },
  {
    "path": "WWFLAT32/SHAPE/DRAWSHP.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : WWLIB32                                  *\n;*                                                                         *\n;*                    File Name : DRAWSHP.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : April 13, 1992                           *\n;*                                                                         *\n;*                  Last Update : September 14, 1994   [IML]               *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Draw_Shape -- Draws a shape at given buffer coordinates and clips     *\n;*   Not_Supported -- Replacement function for Draw_Shape routines not used*\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n; this struct is here to remove the hardwire way of programing\n; implemented in the funtion Draw_Shape in ian image of \n\nSTRUC\tVVPC_IMAGE\n   \t\tOff  \tdd  ?  \n\t\tWidth  \tdd  ?  \n\t\tHeight  dd  ?  \n  \t\tPage    dd  ?  \nENDS\n\n\n\nSTRUC GVPC_IMAGE \n\t\t vvpc\t\tVVPC_IMAGE\t<>\n\t\t Xpos\t\tdd\t   \t?\n\t\t Ypos\t\tdd\t   \t?\n\t\t GraphicBuff\tdd\t   \t?\nENDS\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;****************************** Declarations ********************************\nGLOBAL\t Draw_Shape:NEAR\nGLOBAL\t LCW_Uncompress:NEAR\nGLOBAL\t_ShapeBuffer:DWORD\nGLOBAL\t_ShapeBufferSize:DWORD\n\nGLOBAL\tMaskPage\t       : dword\nGLOBAL\tBackGroundPage\t       : dword\n\n\n;********************************* Data ************************************\n\tDATASEG\n;---------------------------------------------------------------------------\n; Shape buffer & its size, set by Set_Shape_Buffer()\n;---------------------------------------------------------------------------\n_ShapeBuffer\t\tDD\t0\n_ShapeBufferSize\tDD\t0\n\n;---------------------------------------------------------------------------\n; Address of MaskPage & BackGroundPage, set by Init_Priority_System()\n;---------------------------------------------------------------------------\nMaskPage\t\tDD\t0\nBackGroundPage\t\tDD\t0\n\n;---------------------------------------------------------------------------\n; Predator effect variables \n;---------------------------------------------------------------------------\nPredCount\tDD\t0\nPredTable\tDB\t1, 3, 2, 5, 4, 3, 2, 1\nPredValue\tDD\t1\nPartialPred\tDD\t0\t; partially faded predator effect value\nPartialCount\tDD\t0\n\n;---------------------------------------------------------------------------\n; 32 bit versions of 16 bit stack variables\n;---------------------------------------------------------------------------\nFlags\t\tDD\t?\t; globally accessible copy of flags\n\nviewport_ptr\tDD\t?\t; pointer to upper-left corner of viewport \nviewport_width\tDD\t?\t; viewport width\nviewport_height DD\t?\t; viewport height\nviewport_yadd\tDD\t?\t; viewport y add\nviewport_x\tDD\t?\t; viewport x-coord\nviewport_y\tDD\t?\t; viewport y-coord\nbuff_ptr\tDD\t?\t; pointer to buffer containing viewport\n\n;********************************* Code ************************************\n\tCODESEG\n\n\n;***************************************************************************\n;* Draw_Shape -- Draws a shape at given buffer coordinates and clips       *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*  DWORD\tgvp_ptr\t\t; pointer to graphic viewport info\t   *\n;*  DWORD\tshape_ptr\t; the shape pointer to draw\t\t   *\n;*  DWORD\tdraw_x\t\t; x-coord of hotspot in viewport\t   *\n;*  DWORD\tdraw_y\t\t; y-coord of hotspot in viewport\t   *\n;*  DWORD\tflags\t\t; the flags for drawing the shape\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* Optional Arguments: If the following flags are used, the given args\t   *\n;* MUST be present.  Note that, if more than one one set of args is used,  *\n;* they must appear in this order (alphabetical).\t\t\t   *\n;*  SHAPE_COLOR:\tDWORD color_table (256 bytes)\t\t\t   *\n;*  SHAPE_FADING:\tDWORD fade_table (256 bytes), DWORD fade_count\t   *\n;*  SHAPE_GHOST:\tDWORD is_translucent tbl, DWORD translucent tbl    *\n;*  SHAPE_PARTIAL:\tDWORD predator partial_value (0-255)\t\t   *\n;*  SHAPE_PRIORITY:\tDWORD priority_level\t\t\t\t   *\n;*  SHAPE_SCALING:\tDWORD x_scale, WORD y_scale\t\t\t   *\n;*  SHAPE_SHADOW:\tDWORD shadowing_table (256 bytes)\t\t   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*  none.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:\t\t\t\t\t\t\t\t   *\n;*  none.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;*\t\t\t\t\t\t\t\t\t   *\n;* File Organization:\t\t\t\t\t\t\t   *\n;* drawshp.asm : this file\t\t\t\t\t\t   *\n;* shape.inc   : main shape header file; contains declarations for all\t   *\n;* \t\t  globals, procedures and constants\t\t\t   *\n;* ds_table.asm: contains the procedure address tables for LSkipRout,\t   *\n;*\t\t  RSkipRout, DrawRout, & PixelRout\t\t\t   *\n;* ds_l*.asm   : left-skip routines\t\t\t\t\t   *\n;* ds_r*.asm   : right-skip routines\t\t\t\t\t   *\n;* ds_d*.asm   : drawing routines\t\t\t\t\t   *\n;* \t\t\t\t\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* Shape format:\t\t\t\t\t\t\t   *\n;* Header:\t\t\t\t\t\t\t\t   *\n;*   UWORD  SType (0=normal, 1=16-color, 2=uncompressed, 4=variable-color) *\n;*   UBYTE  Height\t\t\t\t\t\t\t   *\n;*   UWORD  Width\t\t\t\t\t\t\t   *\n;*   UBYTE  unmodified height\t\t\t\t\t\t   *\n;*   UWORD  size of shape in memory, including this header\t\t   *\n;*   UWORD  uncompressed data size\t\t\t\t\t   *\n;* Normal Shape:\t\t\t\t\t\t\t   *\n;*   UBYTE  [compressed] Shape data\t\t\t\t\t   *\n;* 16-color shape:\t\t\t\t\t\t\t   *\n;*   UBYTE  16-color table\t\t\t\t\t\t   *\n;*   UBYTE  [compressed] Shape data\t\t\t\t\t   *\n;* variable-color shape:\t\t\t\t\t\t   *\n;*   UBYTE  # colors\t\t\t\t\t\t\t   *\n;*   UBYTE  color table (variable-length)\t\t\t\t   *\n;*   UBYTE  [compressed] Shape data\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* Uncompressed shape data format:\t\t\t\t\t   *\n;* Data is stored as a bitmap, with 0's treated as a special case.  Every  *\n;* 0 byte is followed by a repetition count byte.  Every scan line is\t   *\n;* compressed separately.  Thus, the following bitmap results in the\t   *\n;* following shape data:\t\t\t\t\t\t   *\n;*\t0 0 0 5 6 7 0 0 0 0\t\t\t\t\t\t   *\n;*\t0 0 0 5 6 7 0 0 0 0\t\t\t\t\t\t   *\n;*\t0 0 0 5 6 7 0 0 0 0\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\t0 3 5 6 7 0 4\t\t\t\t\t\t\t   *\n;*\t0 3 5 6 7 0 4\t\t\t\t\t\t\t   *\n;*\t0 3 5 6 7 0 4\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* How scaling is handled:\t\t\t\t\t\t   *\n;*  Scaling is done by accumulating the x & y scale values.  When the high *\n;*  byte of the accumulated value is set, the pixel (for x-scaling) or\t   *\n;*  the line (for y-scaling) is drawn.  The high byte is then cleared,\t   *\n;*  and the low byte is left so roundoffs continue to accumulate.\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* Drawing Procedures:\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\n;*                                                                         *\n;*  RSkipRout: skips given # bytes of data on the right-hand side of a\t   *\n;*  shape.  Just has to handle changing the current byte offset in the \t   *\n;*  shape data buffer, since the draw routine knows where the left-hand\t   *\n;*  side of the drawable region is.  The routine may skip more bytes than  *\n;*  it was told if it encounters a run of 0's, but it's assumed that a\t   *\n;*  run of 0's will never go past the right edge of a shape.\t\t   *\n;*    Input:\t\t\t\t\t\t\t\t   *\n;*\t\tECX - number of uncompressed bytes to skip\t\t   *\n;*\t\tESI - shape buffer data address\t\t\t\t   *\n;*    Output:\t\t\t\t\t\t\t\t   *\n;* \t\tECX - negative # bytes overrun, or 0\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\n;*                                                                         *\n;*  LSkipRout: skips given # bytes of data on the left-hand side of a\t   *\n;*  shape.  This routine must update the shape data byte offset, and it\t   *\n;*  must properly update the current drawing position due to scaling, so   *\n;*  it's a little more involved than the RSkip routine.  The routine may   *\n;*  skip more bytes than it's told if it encounters a run of 0's.  If this *\n;*  happens, the draw routine must take these extra bytes into \t\t   *\n;*  consideration.\t\t\t\t\t\t\t   *\n;*    Input:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape (source) buffer data address\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = shape's width in bytes\t\t\t   *\n;*    Output:\t\t\t\t\t\t\t\t   *\n;* \t\tECX - negative # pixels (not bytes) overrun, or 0\t   *\n;*\t\tEDX - accumulated XTotal value at new pixel location\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) overrun\t\t   *\n;*\t\t[WidthCount] - decremented by # bytes skipped\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\n;*\t\t\t\t\t\t\t\t\t   *\n;*  DrawRout: draws one row of pixels, handles scaling, reversal and \t   *\n;*\t      any per pixel effects like predator, shadow etc.\t\t   *\n;*  EDX must be set up as follows:\t\t\t\t\t   *\n;*  - No scaling: 0\t\t\t\t\t\t\t   *\n;*  - No left-clipping: 0\t\t\t\t\t\t   *\n;*  - Left clipping, but no overrun: set to computed initial value for\t   *\n;*    that viewport coordinate\t\t\t\t\t\t   *\n;*  - Left clipping, with overrun: set to XTotal value for that coordinate *\n;*  In any case, only the low byte of DL should contain data; the current  *\n;*  byte in the shapebuffer should always be the first drawable pixel,\t   *\n;*  even if it's partially clipped (in which case DL will contain data).   *\n;*    Input:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of pixels (not bytes) to draw\t\t   *\n;*\t\tEDX = XTotal initializer value\t\t\t\t   *\n;*\t\tESI = shape (source) buffer address\t\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = remaining bytes on the line\t\t   *\n;*    Output:\t\t\t\t\t\t\t\t   *\n;*\t\tESI - updated to current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) drawn/skipped\t   *\n;*\t\t[WidthCount] - decremented by # bytes (not pixels) drawn   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* Algorithm:\t\t\t\t\t\t\t\t   *\n;* - Initialize globals\t\t\t\t\t\t\t   *\n;* - Pull optional arguments off the stack\t\t\t\t   *\n;* - Set up drawing procedure pointers based on drawing flags\t\t   *\n;* - Read the values from the shape header\t\t\t\t   *\n;* - Compute the shape's scaled width & height\t\t\t\t   *\n;* - Adjust the shape's drawing coordinates based on centering & \t   *\n;*   viewport-relative flag settings\t\t\t\t\t   *\n;* - Compute the clipped areas of the shape\t\t\t\t   *\n;* - Compute the number of drawn pixels horizontally & vertically\t   *\n;* - Compute the starting drawing offset in the viewport\t\t   *\n;* - Draw the shape\t\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*-------------------------------------------------------------------------*\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/13/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   05/26/1994 BR  : Converted to 32-bit, restructured quite a bit.\t   *\n;*   08/09/1994 IML : Added C++ style interface. Various optimizations.\t   *\t\n;*   09/06/1994 IML : Ammendments for integration of p_* and ds_* routines.*\n;*   09/14/1994 IML : Now handles LCW compression.\t\t\t   *\t\t\n;*=========================================================================*\nPROC\tDraw_Shape C NEAR \t\n\tUSES eax,ebx,ecx,edx,edi,esi\n\n\t;--------------------------------------------------------------------\n\t; Arguments:\n\t;--------------------------------------------------------------------\n\tARG\tgvp_ptr:DWORD\t\t; pointer to graphic viewport info\n\tARG\tshape_ptr:DWORD\t\t; the shape pointer to draw\n\tARG\tdraw_x:DWORD\t\t; the destination x pixel\n\tARG\tdraw_y:DWORD\t\t; the destination y pixel\n\tARG\tflags:DWORD\t\t; the flags for drawing the shape\n\nIF FALSE\n\t;--------------------------------------------------------------------\n\t; Define the local stack variables that Draw_Shape needs. These \n\t; parameters are defined in shape.inc.  They're included here \n\t; just for reference.\n\t;--------------------------------------------------------------------\n\t;\n\t;...................... proc addresses ..............................\n\t;\n\tLOCAL\tLSkipRout:DWORD\t\t; pointer to the skip routine\n\tLOCAL\tRSkipRout:DWORD\t\t; pointer to the skip routine\n\tLOCAL\tDrawRout:DWORD\t\t; pointer to the draw routine\n\t;\n\t;.................... optional arguments ............................\n\t;\n\tLOCAL\tColorTable:DWORD\t; ptr to the shapes color table\n\tLOCAL\tFadingTable:DWORD\t; extracted fading table pointer\n\tLOCAL\tFadingNum:DWORD\t\t; get the number of times to fade\n\tLOCAL\tIsTranslucent:DWORD\t; ptr to \"are we translucent?\" tbl\n\tLOCAL\tTranslucent:DWORD\t; ptr to \"ok we are translucent!\" tbl\n\tLOCAL\tPriLevel:BYTE\t\t; the priority level of the object\n\tLOCAL\tScaleX:DWORD\t\t; the x increment to scale by\n\tLOCAL\tScaleY:DWORD\t\t; the y increment to scale by\n\tLOCAL\tShadowingTable:DWORD\t; ptr to the shadowing table\n\t;\n\t;.................... Shape header values ...........................\n\t;\n\tLOCAL\tShapeType:DWORD\t\t; shape type\n\tLOCAL\tShapeWidth:DWORD\t; shape's unscaled width\n\tLOCAL\tShapeHeight:DWORD\t; shape's unscaled height\n\tLOCAL\tUncompDataLen:DWORD\t; uncompressed data length\n\tLOCAL\tShapeData:DWORD\t\t; pointer to [compressed] shape data\n\t;\n\t;.................. Scaled shape dimensions .........................\n\t;\n\tLOCAL\tScaledWidth:DWORD\t; shape's scaled width\n\tLOCAL\tScaledHeight:DWORD\t; shape's scaled height\n\t;\n\t;.................. Pixel clipping variables ........................\n\t;\n\tLOCAL\tLeftClipPixels:DWORD\t; # left-clipped pixels\n\tLOCAL\tRightClipPixels:DWORD\t; # right-clipped pixels\n\tLOCAL\tTopClipPixels:DWORD\t; # top-clipped pixels\n\tLOCAL\tBotClipPixels:DWORD\t; # bottom-clipped pixels\n\tLOCAL\tPixelWidth:DWORD\t; width of drawable area in pixels\n\tLOCAL\tPixelHeight:DWORD\t; height of drawable area in pixels\n\t;\n\t;..................... Drawing variables ............................\n\t;\n\tLOCAL\tNumColors:DWORD\t\t; # colors for 16-color shapes\n\tLOCAL\tStartDraw:DWORD\t\t; ptr to starting draw position\n\tLOCAL\tNextLine:DWORD\t\t; offset of next drawing line\n\tLOCAL\tLeftClipBytes:DWORD\t; # left-clipped bytes\n\tLOCAL\tXTotal:DWORD\t\t; accumulated x-pixels for scaling\n\tLOCAL\tXTotalInit:DWORD\t; initial roundoff bits for XTotal\n\tLOCAL\tYTotal:DWORD\t\t; accumulated y-pixels for scaling\n\tLOCAL\tHeightCount:DWORD\t; height counter for drawing lines\n\tLOCAL\tLineStart:DWORD\t\t; address of start of line\n\tLOCAL\tWidthCount:DWORD\t; counts down # bytes skipped\n\tLOCAL\tStashReg:DWORD\t\t; temp variable for draw routines\n\tLOCAL\tMaskAdjust:DWORD\t; priority buffer offset\n\tLOCAL\tBackAdjust:DWORD\t; background buffer offset\n\tLOCAL\tStashECX:DWORD\t\t; temp variable for ECX register\n\tLOCAL\tStashEDX:DWORD\t\t; temp variable for EDX register\n\nENDIF\n\n\t;====================================================================\n\t; Initialization:\n\t; - allocate space for globals\n\t; - validate shape pointer\n\t; - set SHAPE_COMPACT flag if needed\n\t;====================================================================\n\t;--------------------------------------------------------------------\n\t; Allocate stack space for our local variables.\n\t;--------------------------------------------------------------------\n\tLOCAL\tLocal_Stack:BYTE:Local_Size\n\n\t;--------------------------------------------------------------------\n\t; Make sure the shape pointer is not NULL\n\t;--------------------------------------------------------------------\n\tcmp\t[shape_ptr],0\t\t\t; compare shape ptr value to NULL\n\tjnz\t??valid_shp\t\t\t; if non-zero, it's valid\n\tjmp\t??exit\t\t\t\t; otherwise get the heck outta here\n\n\t;--------------------------------------------------------------------\n\t; Move gvp info into local variables\n\t;--------------------------------------------------------------------\n??valid_shp:\n\tmov\tedi,[gvp_ptr]\t\t\t\t\t; get pointer to graphic viewport info\n\tmov\tesi, [(type GVPC_IMAGE  ptr edi). vvpc . Off ] ; extract viewport pointer\n\tmov\t[viewport_ptr],esi\n\tmov\tebx,[(type GVPC_IMAGE ptr edi) . vvpc . Width ]\t; extract viewport width\n\tmov\t[viewport_width],ebx\t\t\t\n\tmov\teax,[(type GVPC_IMAGE ptr edi) . vvpc . Height ]\t; extract viewport height\n\tmov\t[viewport_height],eax\t\t\t\t\n\tmov\tecx,[(type GVPC_IMAGE ptr edi) . vvpc . Page ]\t; calculate y add value\n\tadd\tecx,ebx\n\tmov\t[viewport_yadd],ecx\n\tmov\teax,[(type GVPC_IMAGE ptr edi) . Xpos ]\t\t; extract viewport x-coord\n\tmov\t[viewport_x],eax\n\tmov\teax, [(type GVPC_IMAGE ptr edi) . Ypos ]\t; extract viewport y-coord\n\tmov\t[viewport_y],eax\n\tmul\tecx\t\t\t\t; calculate buffer pointer\n\tadd\teax,[viewport_x]\n\tsub\tesi,eax\n\tmov\t[buff_ptr],esi\n\n\n\t;--------------------------------------------------------------------\n\t; If this shape is a compact shape, set that bit in the flags arg\n\t;--------------------------------------------------------------------\n\tmov\tedi,[shape_ptr]\t\t\t; check for compact shape flag\n\ttest\t[BYTE PTR edi],MAKESHAPE_COMPACT\t \n\t\t\t\t\t\t\t\n\tjz\t??do_args\t\t\t; if not process flags as is\n\tor\t[flags],SHAPE_COMPACT\t\t; mark it as a compact shape\n\n\t;====================================================================\n\t; Pull off optional arguments:\n\t; EDI is used as an offset from the 'flags' parameter, to point\n\t; to the optional argument currently being processed.\n\t;====================================================================\n??do_args:\n\tmov\tedi,4\t \t\t\t; optional params start past flags\n\n\t;--------------------------------------------------------------------\n\t; Initialize optional argument values:\n\t;--------------------------------------------------------------------\n\tmov\t[ColorTable],0\t\t\t; default = NULL\n\tmov\t[FadingTable],0\t\t\t; default = NULL\n\tmov\t[FadingNum],0\t\t\t; default = no fading\n\tmov\t[IsTranslucent],0\t\t; default = NULL\n\tmov\t[Translucent],0\t\t\t; default = NULL\n\tmov\t[PriLevel],0\t\t\t; default = no priority\n\tmov\t[ScaleX],100h\t\t\t; default = unity X scaling\n\tmov\t[ScaleY],100h\t\t\t; default = unity Y scaling\n\tmov\t[ShadowingTable],0\t\t; default = NULL\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_COLOR: DWORD color_table[256]\n\t;--------------------------------------------------------------------\n??color:\n\ttest\t[flags],SHAPE_COLOR \t\t; does it have a color table\n\tjz\t??fading \t\t\t; if not skip to fading \n\tor\t[flags],SHAPE_COMPACT\t\t; mark it as a compact shape\n\t\t\t\t\t\t;  (for remapping purposes only)\n\tmov\teax,[flags + edi]\n\tmov\t[ColorTable],eax\t\t; save address of color table\n\tadd\tedi,4\t\t\t\t; point to next optional argument\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_FADING: DWORD fade_table[256], DWORD fade_count\n\t;--------------------------------------------------------------------\n??fading:\n\ttest\t[flags],SHAPE_FADING\t\t; are we fading this shape\n\tjz\t??ghost\t\t\t\t; skip to ghosting check\n\tmov\teax,[flags + edi]\n\tmov\t[FadingTable],eax\t\t; save address of fading tbl\n\n\tmov\teax,[flags + edi + 4]\t\t; get fade num\n\n\tadd\tedi,8\t\t\t\t; next argument\n\tcmp\teax,0\t\t\t\t; check if it's 0\n\tjnz\t??set_fading\t\t\t; if not, store fade num\n\tand\t[flags],NOT SHAPE_FADING\t; otherwise, don't fade\n\n??set_fading:\n\tmov\t[FadingNum],eax\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_GHOST: DWORD is_translucent tbl, DWORD translucent tbl\n\t;--------------------------------------------------------------------\n??ghost:\n\ttest\t[flags],SHAPE_GHOST\t\t; are we ghosting this shape\n\tjz\t??init_predator\t\t\t; skip to predator check\n\tmov\teax,[flags + edi]\n\tmov\t[IsTranslucent],eax\t\t; save ptr to is_trans. tbl\n\tmov\teax,[flags + edi + 4]\n\tmov\t[Translucent],eax\t\t; save ptr to translucent tbl\n\tadd\tedi,8\t\t\t\t; next argument\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_PREDATOR: Initialize the predator effect variables\n\t;--------------------------------------------------------------------\n??init_predator:\n\ttest\t[flags],SHAPE_PREDATOR\t\t; is predator effect on\n\tjz\t??partial\t\t\t; if not skip to partial \n\tinc\t[PredCount]\t\t\t; the pred table is byte aligned\n\tand\t[PredCount],PRED_MASK\t\t; keep entries within bounds\n\tmov\teax,[PredCount]\t\t \n\tmov\tal,[BYTE PTR PredTable + eax]\n\tmov\t[PredValue],eax\t\t\t; put the pred value cs\n\tmov\t[PartialCount],0\t\t; clear the partial count\n\tmov\t[PartialPred],100h\t\t; init partial to off\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_PARTIAL: DWORD partial_pred_value (0-255)\n\t;--------------------------------------------------------------------\n??partial:\n\ttest\t[flags],SHAPE_PARTIAL\t\t; is this a partial pred?\n\tjz\t??priority\t\t\t; if not check priority\n\tmov\teax,[flags + edi]\t\t; pull the partial value\n\tmov\t[PartialPred],eax\t\t; store it off\n\tadd\tedi,4\t\t\t\t; next argument\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_PRIORITY: DWORD priority_level\n\t;--------------------------------------------------------------------\n??priority:\n\ttest\t[flags],SHAPE_PRIORITY\t\t; is this a priority draw\n\tjz\t??scale\t\t\t\t; if not skip to scale\n\tmov\teax,[flags + edi]\n\tmov\t[PriLevel],al\t\t\t; store priority level\n\tadd\tedi,4\t\t\t\t; next argument\n\tmov\teax,[MaskPage]\t\t\t; calculate priority buffer\n\tsub\teax,[buff_ptr]\t\t\t;  offset\n\tmov\t[MaskAdjust],eax\n\tmov\teax,[BackGroundPage]\t\t; calculate background buffer\n\tsub\teax,[buff_ptr]\t\t\t;  offset\n\tmov\t[BackAdjust],eax\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_SCALING: DWORD x_scale, WORD y_scale\n\t;--------------------------------------------------------------------\n??scale:\n\ttest\t[flags],SHAPE_SCALING\t\t; are we scaling this shape.\n\tjz\t??shadow\t\t\t; if not then skip scale y value\n\tmov\teax,[flags + edi]\t\n\tmov\t[ScaleX],eax\n\tmov\teax,[flags + edi + 4]\t\n\tmov\t[ScaleY],eax\n\tadd\tedi,8\t\t\t\t; next argument\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_SHADOW: DWORD shadow_table[256]\n\t;--------------------------------------------------------------------\n??shadow:\n\ttest\t[flags],SHAPE_SHADOW\t\t; are we ghosting this shape\n\tjz\tshort ??get_header\t\t; if not then skip\n\tmov\teax,[flags + edi]\n\tmov\t[ShadowingTable],eax\t\t; save address of shadow table \n\tadd\tedi,4\t\t\t\t; next argument\n\n\n??get_header:\t\n\t;====================================================================\n\t; Get Shape header values\n\t;====================================================================\n\tmov\tesi,[shape_ptr]\t\t\t; prepare to read header\n\tmovzx\teax,[WORD PTR esi]\n\tmov\t[ShapeType],eax\t\t\t; extract shape type\n\tmovzx\teax,[BYTE PTR esi + 2]\n\tmov\t[ShapeHeight],eax\n\tmovzx\teax,[WORD PTR esi + 3]\t\t; extract shape height\n\tmov\t[ShapeWidth],eax\n\tmovzx\teax,[WORD PTR esi + 8]\t\t; extract uncompressed data length\n\tmov\t[UncompDataLen],eax\n\tadd\tesi,10\t\t\t\t; reposition index\n\n\t;--------------------------------------------------------------------\n\t; Now get NumColors, ColorTable address, & data pointer:\n\t; <16-color shape:\n\t;   shape.Colortable[0] = # colors\n\t;   shape data is after that many colors\n\t; 16-color shape:\n\t;   shape.Colortable[] contains colors\n\t;   shape data is after those colors\n\t; default 256-color shape:\n\t;   shape data starts at shape.Colortable[0]\n\t; Note: ColorTable is set only if flags & SHAPE_COLOR is 0; otherwise,\n\t;   the color table was passed in & we already have a pointer to it\n\t;--------------------------------------------------------------------\n\t;\n\t;....................... <16-color shape: ...........................\n\t;\n\ttest\t[ShapeType],MAKESHAPE_VARIABLE\n\tjz\t??check_16\n\tmovzx\teax,[BYTE PTR esi]\t\t; read # colors\n\tmov\t[NumColors],eax\t\t\t; save # colors\n\tinc\tesi\n\ttest\t[flags],SHAPE_COLOR\t\t; don't set ColorTable if\n\tjnz\t??norm_get_data_addr\t\t;  it was passed in\n\tmov\t[ColorTable],esi\t\t; save color table pointer\n\n??norm_get_data_addr:\n\tadd\tesi,[NumColors]\t\t\t; skip past color data\n\tmov\t[ShapeData],esi\t\t\t; set data address\n\tjmp\t??setup_procs\n\n\t;....................... 16-color shape: ............................\n??check_16:\n\ttest\t[ShapeType],MAKESHAPE_COMPACT\n\tjz\t??256_get_data_addr\n\tmov\t[NumColors],16\t\t\t; save # colors\n\ttest\t[flags],SHAPE_COLOR\t\t; don't set ColorTable if\n\tjnz\t??16_get_data_addr\t\t;  it was passed in\n\tmov\t[ColorTable],esi\t\t; save color table pointer\n\n??16_get_data_addr:\n\tadd\tesi,[NumColors]\t\t\t; skip past color data\n\tmov\t[ShapeData],esi\t\t\t; set data address\n\tjmp\t??setup_procs\n\t;\n\t;....................... 256-color shape: ...........................\n\t;\n??256_get_data_addr:\n\tmov\t[ShapeData],esi\t\t\t; set data address\n\n\t;====================================================================\n\t; Set up the drawing procedure addresses\n\t;====================================================================\n\t;--------------------------------------------------------------------\n\t; This code uses HORZ_REV, VERT_REV, & SCALING flags as an \n\t; offset into the LSkipTable, RSkipTable, and DrawTable.  These\n\t; flags combined have values from 00h-07h, so each table must have\n\t; at least 8 entries.\n\t;--------------------------------------------------------------------\n??setup_procs:\n\tmov\tebx,[flags]\t\t; load flags value\n\tand\tebx,07h\t\t\t; clip high bits\n\tadd\tebx,ebx\t\t\t; mult by 4 to get DWORD offset\n\tadd\tebx,ebx\n\tmov\teax,[LSkipTable + ebx]\t; get table value\n\tmov\t[LSkipRout],eax\t\t; store it in the function pointer\n\tmov\teax,[RSkipTable + ebx]\t; get table value\n\tmov\t[RSkipRout],eax\t\t; store it in the function pointer\n\tmov\teax,[DrawTable + ebx]\t; get table value\n\tmov\t[DrawRout],eax\t\t; store it in the function pointer\n\n??compute_scalevals:\n\t;====================================================================\n\t; Now compute scaled width & height.  If the shape scales down to 0 \n\t; either horizontally or vertically, exit.\n\t;====================================================================\n\ttest\t[flags],SHAPE_SCALING\t; skip if no scaling\n\tjz\t??no_scaling\n\t;\n\t;........................ scaled width: .............................\n\t;\n\tmov\teax,[ShapeWidth]\t; get byte width\n\tmov\tebx,[ScaleX]\t\t; prepare for register mul\n\tmul\tebx\t\t\t; EDX:EAX = result\n\tshrd\teax,edx,8\t\t; EAX = result rounded down\n\tor\teax,eax\n\tjz\t??exit\t\t\t; exit if EAX is 0\n\tmov\t[ScaledWidth],eax\t; save the scaled width\n\t;\n\t;........................ scaled height: ............................\n\t;\n\tmov\teax,[ShapeHeight]\t; get byte height\n\tmov\tebx,[ScaleY]\t\t; prepare for register mul\n\tmul\tebx\t\t\t; EDX:EAX = result\n\tshrd\teax,edx,8\t\t; EAX = result rounded down\n\tor\teax,eax\n\tjz\t??exit\t\t\t; exit if EAX is 0\n\tmov\t[ScaledHeight],eax\t; save the scaled height\n\tjmp\t??handle_centering\n\t;\n\t;......................... no scaling: ..............................\n\t;\n??no_scaling:\n\tmov\teax,[ShapeWidth]\n\tmov\t[ScaledWidth],eax\t; pixel width = byte width\n\tmov\teax,[ShapeHeight]\n\tmov\t[ScaledHeight],eax\t; pixel height = byte height\n\n\t;====================================================================\n\t; Allow for SHAPE_CENTER by adjusting the draw_x & draw_y arguments:\n\t; draw_x -= ScaledWidth / 2\n\t; draw_y -= ScaledHeight / 2\n\t;====================================================================\n??handle_centering:\n\t;\n\t;........................ adjust draw_x .............................\n\t;\n\ttest\t[flags],SHAPE_CENTER\t; skip if not centered\n\tjz\t??handle_vp_rel\n\tmov\teax,[draw_x]\t\t; load in draw_x\n\tmov\tedx,[ScaledWidth]\t; load in ScaledWidth\n\tshr\tedx,1\t\t\t; divide it by 2\n\tsub\teax,edx\t\t\t; subract it from eax\n\tmov\t[draw_x],eax\t\t; store it back into draw_x\n\t;\n\t;........................ adjust draw_y .............................\n\t;\n\tmov\teax,[draw_y]\t\t; load in draw_y\n\tmov\tedx,[ScaledHeight]\t; load in ScaledHeight\n\tshr\tedx,1\t\t\t; divide it by 2\n\tsub\teax,edx\t\t\t; subract it from eax\n\tmov\t[draw_y],eax\t\t; store it back into draw_y\n\n\t;====================================================================\n\t; Allow for SHAPE_VIEWPORT_REL by adjusting draw_x & draw_y by the \n\t; viewport's coordinates\n\t;====================================================================\n??handle_vp_rel:\n\ttest\t[flags],SHAPE_VIEWPORT_REL\t; skip if not vp-relative\n\tjz\t??compute_horz_clip\n\tmov\teax,[viewport_x]\n\tadd\t[draw_x],eax\t\t\t; draw_x += viewport_x\n\tmov\teax,[viewport_y]\n\tadd\t[draw_y],eax\t\t\t; draw_y += viewport_y\n\n\t;====================================================================\n\t; Now that we have the scaled size and adjusted x & y drawing\n\t; coordinates, we can compute the clipped areas of the shape:\n\t;   LeftClipPixels =\tviewport_x - draw_x\n\t;\t- if negative, set to 0\n\t;   RightClipPixels =\t(draw_x + ScaledWidth) - \n\t;\t\t\t\t(viewport_x + viewport_width)\n\t;\t- if negative, set to 0\n\t;\n\t;   TopClipPixels =\tviewport_y - draw_y\n\t;\t- if negative, set to 0\n\t;   BotClipPixels =\t(draw_y + ScaledHeight) -\n\t;\t\t\t\t(viewport_y + viewport_height)\n\t;\t- if negative, set to 0\n\t;====================================================================\n??compute_horz_clip:\n\t;\n\t;...................... left-clipped pixels .........................\n\t;\n\tmov\teax,[viewport_x]\n\tsub\teax,[draw_x]\t\t; EAX = viewport_x - draw_x\n\tjge\t??set_left_clip\n\tmov\teax,0\t\t\t; if EAX<0, set to 0\n??set_left_clip:\n\tmov\t[LeftClipPixels],eax\t; store # left-clipped pixels\n\t;\n\t;...................... right-clipped pixels ........................\n\t;\n\tmov\teax,[draw_x]\n\tadd\teax,[ScaledWidth]\t; EAX = draw_x + ScaledWidth\n\tmov\tedx,[viewport_x]\n\tadd\tedx,[viewport_width]\t; EDX = viewport_x + viewport_width\n\tsub\teax,edx\n\tjge\t??set_right_clip\n\tmov\teax,0\t\t\t; if EAX<0, set to 0\n??set_right_clip:\n\tmov\t[RightClipPixels],eax\t; store # right-clipped pixels\n\t;\n\t;...................... top-clipped pixels ..........................\n\t;\n??compute_vert_clip:\n\tmov\teax,[viewport_y]\n\tsub\teax,[draw_y]\t\t; EAX = viewport_y - draw_y\n\tjge\t??set_top_clip\n\tmov\teax,0\t\t\t; if EAX<0, set to 0\n??set_top_clip:\n\tmov\t[TopClipPixels],eax\t; store # top-clipped pixels\n\t;\n\t;.................... bottom-clipped pixels .........................\n\t;\n\tmov\teax,[draw_y]\n\tadd\teax,[ScaledHeight]\t; EAX = draw_y + ScaledHeight\n\tmov\tedx,[viewport_y]\n\tadd\tedx,[viewport_height]\t; EDX = viewport_y + viewport_height\n\tsub\teax,edx\n\tjge\t??set_bottom_clip\n\tmov\teax,0\t\t\t; if EAX<0, set to 0\n??set_bottom_clip:\n\tmov\t[BotClipPixels],eax\t; store # bottom-clipped pixels\n\n\t;====================================================================\n\t; Now compute the number of pixels actually drawn, horizontally and\n\t; vertically; exit if either is <= 0\n\t;====================================================================\n??compute_drawn_pixels:\n\t;\n\t;.................... pixel width of drawn area .....................\n\t;\n\tmov\teax,[ScaledWidth]\t; get total width in pixels\n\tsub\teax,[LeftClipPixels]\t; subtract off left-clipped pixels\n\tsub\teax,[RightClipPixels]\t; subtract off right-clipped pixels\n\tjle\t??exit\t\t\t; exit if no horizontal pixels drawn\n\tmov\t[PixelWidth],eax\t; store drawn pixel width\n\t;\n\t;.................... pixel height of drawn area ....................\n\t;\n\tmov\teax,[ScaledHeight]\t; get total height in pixels\n\tsub\teax,[TopClipPixels]\t; subtract off top-clipped pixels\n\tsub\teax,[BotClipPixels]\t; subtract off bottom-clipped pixels\n\tjle\t??exit\t\t\t; exit if no horizontal pixels drawn\n\tmov\t[PixelHeight],eax\t; store drawn pixel height\n\n\t;====================================================================\n\t; So, we're actually going to draw something; if (ShapeType & \n\t; MAKESHAPE_NOCOMP == 0) decompress the shape data into _ShapeBuffer:\n\t; LCW_Uncompress(ShapeData, _ShapeBuffer, UncompDataLen);\n\t;\tshape.DataLength\n\t;\t&_ShapeBuffer\n\t;\t&(shape's data)\n\t; - otherwise the shape data is already uncompressed\n\t;====================================================================\n\ttest\t[ShapeType],MAKESHAPE_NOCOMP\n\tjnz\t??uncompressed\n\n\tmov\teax,[UncompDataLen]\n\tpush\teax\t\t\t; push arg 3\n\tmov\teax,[_ShapeBuffer]\n\tpush\teax\t\t\t; push arg 2\n\tmov\teax,[ShapeData]\n\tpush\teax\t\t\t; push arg 1\n\tcall\tLCW_Uncompress\t\t; call routine\n\tadd\tesp,12\t\t\t; restore stack\n\tmov\teax,[_ShapeBuffer]\n\tmov\t[ShapeData],eax\n\tjmp\t??copy_flags\n\n??uncompressed:\n;\tmov\teax,[ShapeData]\t\t; set up pointer to shape data\n;\tmov\t[_ShapeBuffer],eax\n\n\n\t;--------------------------------------------------------------------\n\t; Set the global Flags variable\n\t;--------------------------------------------------------------------\n??copy_flags:\n\tmov\teax,[flags]\n\tmov\t[Flags],eax\t\t\n\n\t;====================================================================\n\t; Now compute the actual buffer offset where drawing (not skipping)\n\t; will begin\n\t;====================================================================\n\t;--------------------------------------------------------------------\n\t; First, compute the x & y offsets of the shape's clipped upper-left \n\t; corner,  relative to the viewport's upper-left corner:\n\t; x-offset = draw_x + LeftClipPixels - viewport_x\n\t; y-offset = draw_y + TopClipPixels - viewport_y\n\t;--------------------------------------------------------------------\n\tmov\tebx,[draw_x]\n\tadd\tebx,[LeftClipPixels]\n\tsub\tebx,[viewport_x]\t; EBX = viewport x-offset\n\n\tmov\teax,[draw_y]\n\tadd\teax,[TopClipPixels]\n\tsub\teax,[viewport_y]\t; EAX = viewport y-offset\n\n\t;--------------------------------------------------------------------\n\t; Then, adjust the viewport offsets due to horizontal & vertical\n\t; reversal:\n\t; if HORZ_REV, x-offset += (PixelWidth - 1)\n\t; if VERT_REV, y-offset += (PixelHeight - 1)\n\t;--------------------------------------------------------------------\n\t;\n\t;................. Adjust for horizontal reversal ...................\n\t;\n\ttest\t[flags],SHAPE_HORZ_REV\n\tjz\t??adjust_vert_offset\n\tadd\tebx,[PixelWidth]\n\tdec\tebx\t\t\t; EBX = true x-offset\n\t;\n\t;................ Swap LeftClip & RightClip pixels ..................\n\t;\n\tmov\tedx,[LeftClipPixels]\t; exchange left & right-clipped pixels\n\txchg\tedx,[RightClipPixels]\n\tmov\t[LeftClipPixels],edx\n\n\t;\n\t;.................. Adjust for vertical reversal ....................\n\t;\n??adjust_vert_offset:\n\ttest\t[flags],SHAPE_VERT_REV\n\tjz\t??adjust_pointer\n\tadd\teax,[PixelHeight]\n\tdec\teax\t\t\t; EAX = true y-offset\n\t;\n\t;.................. Swap TopClip & BotClip pixels ...................\n\t;\n\tmov\tedx,[TopClipPixels]\n\txchg\tedx,[BotClipPixels]\n\tmov\t[TopClipPixels],edx\n\n\t;--------------------------------------------------------------------\n\t; Now, adjust the starting position pointer:\n\t;--------------------------------------------------------------------\n??adjust_pointer:\t;!!!!!!! convert to register mul for speed !!!!!!!!\n\tadd\tebx,[viewport_ptr]\t; add initial ptr to x-offset\n\tmul\t[viewport_yadd]\t\t; convert y-offset (EAX) to bytes\n\tadd\tebx,eax\t\t\t; add those bytes in\n\tmov\t[StartDraw],ebx\t\t; store the starting pointer\n\n\t;--------------------------------------------------------------------\n\t; Finally, if VERT_REV, negate yadd to move up not down:\n\t;--------------------------------------------------------------------\n\ttest\t[flags],SHAPE_VERT_REV\n\tjz\t??init_xtotal\n\tneg\t[viewport_yadd]\t\t; move up, not down\n\n\t;====================================================================\n\t; Initialize the horizontal scale accumulation value:\n\t;   If there are any left-clipped pixels, the scale accumulator will\n\t;   have to be initialized with the value it >would< have by stepping\n\t;   over that many pixels.  This initial value can be computed by\n\t;   dividing the # of left-clipped pixels by the x-scale value itself,\n\t;   picking off the remainder from this division & negating it.  This\n\t;   sets the low byte of the remainder to the correct accumulation\n\t;   value (the high bytes will be garbage).\n\t;   (The alternative to this approach would be to multiply the\n\t;   scale factor by the # clipped bytes, which is the result of the\n\t;   division; however, negating the remainder is much faster than\n\t;   the multiply would be.)\n\t;====================================================================\n??init_xtotal:\n\tmov\tedx,0\t\t\t; prepare for divide\n\tmov\teax,[LeftClipPixels]\t; get # left-clipped pixels\n\tshl\teax,8\t\t\t; multiply by 100h\n\tmov\tebx,[ScaleX]\t\t; load ScaleX value\n\tdiv\tbx\t\t\t; 16-bit div: AX = rslt, DX = rem\n\tmov\t[LeftClipBytes],eax\t; save # left-clipped bytes\n\tneg\tedx\t\t\t; generate roundoff bits\n\tand\tedx,0Fh\t\t\t; only save low byte\n\tmov\t[XTotalInit],edx\t; save initial roundoff value\n\n\t;====================================================================\n\t; Initialize drawing variables:\n\t;====================================================================\n\tmov\tesi,[ShapeData]\t\t; ESI = shape buffer starting point\n\tmov\tedi,[StartDraw]\t\t; EDI = drawing address\n\tmov\t[YTotal],0\t\t; initialize accumulated scale\n\n\t;====================================================================\n\t; Clip the top-clipped lines. The object here is to set ESI to the \n\t; first drawable line in the _ShapeBuffer, and YTotal to: \n\t;   high byte = # times to draw that line, \n\t;   low byte = roundoff bits\n\t;\n\t; - Initialize values (ESI, HeightCount, YTotal)\n\t; - Skip loop if no top lines to clip\n\t; - Loop:\n\t;   - save this line's byte position in _ShapeBuffer, in case we\n\t;     overrun\n\t;   - call RSkipRout with ECX set to # bytes to skip (one row)\n\t;   - accumulate ScaleY into YTotal\n\t;   - if high byte is non-zero, there are that many drawn lines:\n\t;     - decrement HeightCount by that many lines\n\t;     - clear the high byte in YTotal, but keep the roundoff bits\n\t;     - if HeightCount > 0, loop again to clip more lines\n\t;     - if HeightCount is 0, start drawing:\n\t;\t- ESI points to first non-clipped line in _ShapeBuffer\n\t;\t- YTotal contains 0 in high byte, roundoff bits in low byte\n\t;     - otherwise, we've clipped too many lines:\n\t;\t- put ESI back to the line we just clipped\n\t;\t- set high byte of YTotal to # lines overrun\n\t;\t- subtract ScaleY from YTotal, to set it up for drawing loop\n\t;====================================================================\n\t;\n\t;..................... skip if nothing to clip ......................\n\t;\n\tmov\teax,[TopClipPixels]\n\tcmp\teax,0\t\t\t; see if any top-clipped pixels\n\tjz\t??draw_loop\t\t; if not, skip this\n\tmov\t[HeightCount],eax\t; save off # lines to clip\n\n??clip_y_loop:\n\t;\n\t;...................... skip this row of bytes ......................\n\t;\n\tmov\t[LineStart],esi\t\t; save this line's byte position\n\tmov\tecx,[ShapeWidth]\t; set up ECX for RSkipRout\n\tcall\t[RSkipRout]\t\t; skip 'ShapeWidth' bytes\n\t;\n\t;............... see if this row would have been drawn ..............\n\t;\n\tmov\teax,[ScaleY]\n\tadd\t[YTotal],eax\t\t; accumulate scale factor\n\ttest\t[YTotal],0FF00h\t\t; check to see if we draw the line\n\tjz\t??clip_y_loop\t\t; if not loop again\n\t;\n\t;...................... decrement HeightCount .......................\n\t;\n\tmov\teax,0\t\t\t; clear EAX\n\txchg\tal,[BYTE PTR YTotal+1]\t; get # lines, clear it in YTotal\n\tsub\t[HeightCount],eax\t; subtract # drawn lines from HtCt\n\tjg\t??clip_y_loop\t\t; if more lines remain, loop again\n\tjns\t??draw_loop\t\t; is exactly 0; we're done clipping\n\t;\n\t;....................... adjust for overrun .........................\n\t;\n\tmov\tesi,[LineStart]\t\t; point ESI back to this line\n\tmov\teax,[HeightCount]\n\tneg\teax\t\t\t; EAX = # lines overrun\n\tshl\teax,8\t\t\t; multiply by 100h\n\tadd\teax,[YTotal]\t\t; add in roundoff bits\n\tsub\teax,[ScaleY]\t\t; adjust down by y-scale\n\tmov\t[YTotal],eax\t\t; store in YTotal\n\n\t;====================================================================\n\t; The drawing loop (at long last!):\n\t; - Accumulate YTotal; if high byte is 0, skip this row of bytes & \n\t;   loop again\n\t; - Skip left-clipped pixels:\n\t;   - If we've skipped all the bytes on the line, just go to the\n\t;     next line\n\t; - Draw middle pixels:\n\t;   - Add the shape's pixel width to ECX (which could be negative \n\t;     if we left-skipped into the drawable area)\n\t;   - If ECX is still 0, there are no pixels to draw\n\t;   - Otherwise, leave ECX as is & draw the pixels\n\t; - Skip right-clipped pixels:\n\t;   - Add # right-clipped pixels to ECX (which could be negative if\n\t;     the draw routine  uncompressed 0's into the right-clipped \n\t;     region)\n\t;   - if ECX > 0, skip the remaining bytes\n\t; - Go to the next line:\n\t;   - point EDI to the start of the next line in the viewport\n\t;   - decrement the height counter, exit if it's 0\n\t;   - decrement YTotal's high byte\n\t;     - if it's 0, go to the loop top\n\t;     - otherwise, reset ESI to this line's start & redraw the line,\n\t;       starting at left-clipped pixels\n\t;       (NOTE: why not start drawing at middle pixels??????????)\n\t;====================================================================\n??draw_loop:\n\t;\n\t;................... accumulate YTotal & test it ....................\n\t;\n\tmov\teax,[ScaleY]\t\t; get y scaling factor\n\tadd\t[YTotal],eax\t\t; accumulate YTotal\n\ttest\t[YTotal],0FF00h\t\t; see if we need to draw anything\n\tjnz  \t??draw_line\t\t; draw this line\n\t;\n\t;......................... skip this line ...........................\n\t;\n\tmov\tecx,[ShapeWidth]\t; load shape's width in bytes\n\tcall\t[RSkipRout]\t\t; skip this row & loop again\n\tjmp\t??draw_loop\n\n\t;\n\t;--------------------- start drawing this line ----------------------\n\t;\n??draw_line:\n\tmov\t[LineStart],esi\t\t; save current byte position\n\t;....................................................................\n\t; Skip left-clipped pixels:\n\t; - initialize [WidthCount] to total shape width in bytes\n\t; - set ECX to # >bytes< to clip\n\t; When LSkipRout returns: \n\t;\t- ECX will contain # >pixels< overrun\n\t;\t- EDX will contain the XTotal init value\n\t;\t- [WidthCount] will be decremented by total bytes skipped\n\t;....................................................................\n??draw_left:\n\tmov\teax,[ShapeWidth]\t; load shape width\n\tmov\t[WidthCount],eax\t; set up for LSkipRout\n\tmov\tecx,[LeftClipBytes]\t; bytes, not pixels!\n\tcall\t[LSkipRout]\t\t; skip the bytes\n\tcmp\t[WidthCount],0\n\tjz\t??next_line\t\t; The whole line was 0's\n\t;....................................................................\n\t; Draw middle pixels:\n\t; - add PixelWidth to ECX (which may be negative)\n\t; - if ECX is 0, don't bother drawing\n\t; When DrawRout returns:\n\t;\t- ECX will contain # >pixels< overrun\n\t;\t- [WidthCount] will be decremented by # bytes drawn\n\t;....................................................................\n??draw_middle:\n\tadd\tecx,[PixelWidth]\t; since ECX could overrun, add width\n\tjle\t??draw_right\t\t; if ECX<=0, no middle pixels to draw\n\tcall\t[DrawRout]\t\t; draw the pixels\n\t;\n\t;................... skip past right-clipped pixels .................\n\t;\n??draw_right:\n\tmov\tecx,[WidthCount]\t; ECX = remaining # bytes\n\tjecxz\t??next_line\t\t; don't bother if no bytes remain\n\tcall\t[RSkipRout]\t\t; skip right-clipped bytes\n\t;\n\t;----------------------- go to the next line ------------------------\n\t;\n??next_line:\n\t;\n\t;................. adjust EDI to start of next line .................\n\t;\n\tmov\teax,[viewport_yadd]\t; get yadd\n\tadd\t[StartDraw],eax\t\t; add it to this line's position\n\tmov\tedi,[StartDraw]\t\t; EDI = next line\n\t;\n\t;................. decrement our pixel row counter ..................\n\t;\n\tdec\t[PixelHeight]\t\t; count down a line\n\tjz\t??exit\t\t\t; we're done!\n\t;\n\t;.................. decrement YTotal's high byte ....................\n\t;\n\tdec\t[BYTE PTR YTotal + 1]\t; decrement high byte\n\tjz\t??draw_loop\t\t; draw next line if 0\n\t;\n\t;....................... re-draw this line ..........................\n\t;\n\tmov\tesi,[LineStart]\t\t; reset to this line's start\n\tjmp\t??draw_left\t\t; redraw this line\n\n??exit:\n\tret\n\n\tENDP\tDraw_Shape\n\n\n;***************************************************************************\n;* Not_Supported -- Replacement function for Draw_Shape routines not used. *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*\tnone.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*\tnone.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*\tnone.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/24/1993 SKB : Created.                                             *\n;*=========================================================================*\nPROC\tNot_Supported NOLANGUAGE NEAR\n\n\tret\n\n\tENDP Not_Supported \n\n\tEND\n\n;************************** End of drawshp.asm *****************************\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/SHAPE/DS_DN.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_DN.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : September 6, 1994   [IML]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Draw_Normal -- Draws a normal row of pixels to the viewport           *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Draw_Normal -- Draws a normal row of pixels to the viewport             *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of pixels (not bytes) to draw\t\t   *\n;*\t\tEDX = XTotal initializer value\t\t\t\t   *\n;*\t\tESI = shape (source) buffer address\t\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = remaining bytes on the line\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;*\t\tESI - updated to current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) drawn/skipped\t   *\n;*\t\t[WidthCount] - bytes remaining on the line\t\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR  : Converted to 32-bit.\t\t\t\t   *\n;*   08/09/1994 IML : Optimized for 32-bit.                                *\n;*   09/06/1994 IML : Integrated p_* and ds_* routines.\t\t\t   *\n;*=========================================================================*\nPROC\tDraw_Normal NOLANGUAGE NEAR\n\n\tmov\t[StashEDX],edx\t\t\t; save edx\n\tmov\tedx,[Flags]\n\tmov\teax,0\t\t\t\t; init to zero\n\tsub\t[WidthCount],ecx\t\t; decrement bytes remaining by pixels\n\t\t\t\t\t\t;   to draw\n\t\t\t\t\t\t\n\t;--------------------------------------------------------------------\n\t; Drawing Loop:\n\t; - Get a data byte\n\t; - If it's a 0, handle the run:\n\t;\t- get repetition value\n\t;\t- add it to EDI\n\t;\t- subtract it from [WidthCount]\n\t;\t- subtract it from ECX\n\t;\t- if ECX>0, draw again, else exit\n\t; - Otherwise:\n\t;\t- draw the pixel\n\t;\t- increment EDI to next pixel location\n\t;\t- decrement [WidthCount]\n\t;\t- loop until ECX is 0\n\t;--------------------------------------------------------------------\n\ttest\tedx,SHAPE_EFFECTS\t\t; are any effects flags set?\n\tjnz\tshort ??general_draw_continue\t;   if so use the general purpose loop\n\n\n\t;--------------------------------------------------------------------\n\t; Extra fast draw loop for shapes with no flags set.\n\t;--------------------------------------------------------------------\n??fast_draw_loop:\n\tmov\tal,[esi]\t\t\t; get a byte of the source\n\tinc\tesi\n\tor\teax,eax\t\t\t\t; is the byte a transparent run?\n\tjz\tshort ??fast_is_run\t\t;   if yes then handle the run\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\tinc\tedi\t\t\t\t; point to next viewport pixel\n\tdec\tecx\t\t\t\t; any source pixels left?\n\tjnz\tshort ??fast_draw_loop\t\t;   if not then go home\n\tjmp\t??out\n\n??fast_is_run:\n\tmov\tal,[esi]\n\tinc\tesi\n\tadd\tedi,eax\t\t\t\t; move the viewport pointer\n\tsub\tecx,eax\t\t\t\t; chop down the width to do\n\tjg\tshort ??fast_draw_loop\t\t; while more to do, loop back up\n\tjmp\t??out\n\n\n\t;--------------------------------------------------------------------\n\t; General purpose draw loop for shapes with one or more flags set.\n\t;--------------------------------------------------------------------\n??general_draw_loop:\n\ttest\tedx,SHAPE_FADING\t\t; if fading is enabled test for\n\tjz\tshort ??no_fading_draw_loop\t;   transparency\n\tor\teax,eax\n\tjz\tshort ??is_transparent\n\n??no_fading_draw_loop:\t\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\n??is_transparent:\n\tinc\tedi\t\t\t\t; point to next viewport pixel\n\tdec\tecx\t\t\t\t; any source pixels left?\n\tjz\t??out\t\t\t\t;   if not then go home\n\n??general_draw_continue:\n\tmov\tal,[esi]\t\t\t; get a byte of the source\n\tinc\tesi\n\tor\teax,eax\t\t\t\t; is the byte a transparent run?\n\tjz\t??general_is_run\t\t;   if yes then handle the run\n\t\n??test_priority:\n\ttest\tedx,SHAPE_PRIORITY\t\t\n\tjnz\tshort ??priority\n\n??test_predator:\n\ttest\tedx,SHAPE_PREDATOR\n\tjnz\tshort ??predator\n\n??test_compact:\n\ttest\tedx,SHAPE_COMPACT\n\tjnz\t??compact\n\n??test_shadow:\n\ttest\tedx,SHAPE_SHADOW\n\tjnz\t??shadow\n\n??test_translucency:\n\ttest\tedx,SHAPE_GHOST\n\tjz\tshort ??test_fading\n\n\tmov\tebx,[IsTranslucent]\t\t; is it a translucent color?\n\tmov\tbh,[BYTE PTR ebx + eax]\n\tor\tbh,bh\n\tjs\tshort ??test_fading\n\n\tand\tebx,0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tmov\tal,[edi]\t\t\t; mov pixel at destination to al\n\tadd\tebx,[Translucent]\t\t; get the ptr to it!\n\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; get new pixel in al\n\tjmp\tshort ??test_fading\n\n??test_fading:\n\ttest\tedx,SHAPE_FADING\n\tjnz\t??fading\n\tjmp\tshort ??general_draw_loop\n\n??priority:\t\n\tmov\tebx,[MaskAdjust]\t\t; get mask page\toffset\n\tmov\tbl,[BYTE PTR ebx + edi]\t\t; get mask value  \n\n\tand\tbl,CLEAR_UNUSED_BITS\t\t; clear unused bits\n\n\tcmp\t[PriLevel],bl\t\t\t; are we in front of\n\tjge\tshort ??test_predator\t\t;  background?\n\n\tmov\tebx,[BackAdjust]\t\t; get background page offset\n\tmov\tal,[BYTE PTR ebx + edi]\t\t; get background pixel\n\tjmp\t??general_draw_loop\n\n??predator:\n\tmov\tebx,[PartialCount]\n\tadd\tebx,[PartialPred]\t\n\tor\tbh,bh\n\tjnz\tshort ??draw_pred\t\t; is this a predator pixel?\n\tmov\t[PartialCount],ebx\n\tjmp\tshort ??test_compact\n\n??draw_pred:\n\txor\tbh,bh\n\tmov\t[PartialCount],ebx\n\tmov\tebx,[PredValue]\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\tmov\tal,[edi + ebx]\t\t\t;  viewport address\n\tjmp\t??general_draw_loop\n\n??compact:\n\tmov\tebx,[ColorTable]\t\t; get the address of the color table\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; convert it into the proper byte\n\tjmp\t??test_shadow\n\n??shadow:\n\tcmp\tal,SHADOW_COL\n\tjne\t??test_translucency\t\t; is the table value a magic number?\n\n\tmov\tal,[edi]\t\t\t; get the destination color and\n\tmov\tebx,[ShadowingTable]\t\t;  index into the shadow table\n\tmov\tal,[BYTE PTR ebx + eax]\n\tjmp\t??general_draw_loop\t\t\t\n\n??fading:\n\tmov\t[StashECX],ecx\t\t\t; preserve ecx for later\n\tmov\tebx,[FadingTable]\t\t; run color through fading table\n\tmov\tecx,[FadingNum]\n\n??fade_loop:\n\tmov\tal, [BYTE PTR ebx + eax]\n\tdec\tecx\n\tjnz\tshort ??fade_loop\n\n\tmov\tecx,[StashECX]\t\t\t; restore ecx for main draw loop\n\tjmp\t??general_draw_loop\t\t\t\n\n??general_is_run:\n\tmov\tal,[esi]\n\tinc\tesi\n\tadd\tedi,eax\t\t\t\t; move the viewport pointer\n\tsub\tecx,eax\t\t\t\t; chop down the width to do\n\tjg\t??general_draw_continue\t\t; while more to do, loop back up\n\n??out:\t\n\tadd\t[WidthCount],ecx\t\t; adjust for source ending in a run\n\tmov\tedx,[StashEDX]\n\tret\t\n\n\tENDP\tDraw_Normal\n\n\tEND\n\n;**************************** End of ds_dn.asm *****************************\n"
  },
  {
    "path": "WWFLAT32/SHAPE/DS_DR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_DR.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : September 6, 1994   [IML]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Draw_Reverse -- Draws a reversed row of pixels to the viewport        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Draw_Reverse -- Draws a reversed row of pixels to the viewport          *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of pixels (not bytes) to draw\t\t   *\n;*\t\tEDX = XTotal initializer value\t\t\t\t   *\n;*\t\tESI = shape (source) buffer address\t\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = remaining bytes on the line\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;*\t\tESI - updated to current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) drawn/skipped\t   *\n;*\t\t[WidthCount] - bytes remaining on the line\t\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR  : Converted to 32-bit.\t\t\t\t   *\t\n;*   08/09/1994 IML : Optimized for 32-bit.\t\t\t\t   *\n;*   09/06/1994 IML : Integrated p_* and ds_* routines.\t\t\t   *\n;*=========================================================================*\nPROC\tDraw_Reverse NOLANGUAGE NEAR\n\n\tmov\t[StashEDX],edx\t\t\t; save edx\n\tmov\tedx,[Flags]\t\t\t\n\tmov\teax,0\t\t\t\t; init to zero\n\tsub\t[WidthCount],ecx\t\t; decrement bytes remaining by pixels\n\t\t\t\t\t\t;   to draw\n\n\t;--------------------------------------------------------------------\n\t; Drawing Loop:\n\t; - Get a data byte\n\t; - If it's a 0, handle the run:\n\t;\t- get repetition value\n\t;\t- subtract it from EDI\n\t;\t- subtract it from [WidthCount]\n\t;\t- subtract it from ECX\n\t;\t- if ECX>0, draw again, else exit\n\t; - Otherwise:\n\t;\t- draw the pixel\n\t;\t- increment EDI to next pixel location\n\t;\t- decrement [WidthCount]\n\t;\t- loop until ECX is 0\n\t;--------------------------------------------------------------------\n\ttest\tedx,SHAPE_EFFECTS\t\t; are any effects flags set?\n\tjnz\tshort ??general_draw_continue\t;   if so use the general purpose loop\n\n\n\t;--------------------------------------------------------------------\n\t; Extra fast draw loop for shapes with no flags set.\n\t;--------------------------------------------------------------------\n??fast_draw_loop:\n\tmov\tal,[esi]\t\t\t; get a byte of the source\n\tinc\tesi\n\tor\teax,eax\t\t\t\t; is the byte a transparent run?\n\tjz\tshort ??fast_is_run\t\t;   if yes then handle the run\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\tdec\tedi\t\t\t\t; point to next viewport pixel\n\tdec\tecx\t\t\t\t; any source pixels left?\n\tjnz\tshort ??fast_draw_loop\t\t;   if not then go home\n\tjmp\t??out\n\n??fast_is_run:\n\tmov\tal,[esi]\n\tinc\tesi\n\tsub\tedi,eax\t\t\t\t; move the viewport pointer\n\tsub\tecx,eax\t\t\t\t; chop down the width to do\n\tjg\tshort ??fast_draw_loop\t\t; while more to do, loop back up\n\tjmp\t??out\n\n\n\t;--------------------------------------------------------------------\n\t; General purpose draw loop for shapes with one or more flags set.\n\t;--------------------------------------------------------------------\n??general_draw_loop:\n\ttest\tedx,SHAPE_FADING\t\t; if fading is enabled test for\n\tjz\tshort ??no_fading_draw_loop\t;   transparency\n\tor\teax,eax\n\tjz\tshort ??is_transparent\n\n??no_fading_draw_loop:\t\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\n??is_transparent:\n\tdec\tedi\t\t\t\t; point to next viewport pixel\n\tdec\tecx\t\t\t\t; any source pixels left?\n\tjz\t??out\t\t\t\t;   if not then go home\n\n??general_draw_continue:\n\tmov\tal,[esi]\t\t\t; get a byte of the source\n\tinc\tesi\n\tor\teax,eax\t\t\t\t; is the byte a transparent run?\n\tjz\t??general_is_run\t\t;   if yes then handle the run\n\t\n??test_priority:\n\ttest\tedx,SHAPE_PRIORITY\t\t\n\tjnz\tshort ??priority\n\n??test_predator:\n\ttest\tedx,SHAPE_PREDATOR\n\tjnz\tshort ??predator\n\n??test_compact:\n\ttest\tedx,SHAPE_COMPACT\n\tjnz\t??compact\n\n??test_shadow:\n\ttest\tedx,SHAPE_SHADOW\n\tjnz\t??shadow\n\n??test_translucency:\n\ttest\tedx,SHAPE_GHOST\n\tjz\tshort ??test_fading\n\n\tmov\tebx,[IsTranslucent]\t\t; is it a translucent color?\n\tmov\tbh,[BYTE PTR ebx + eax]\n\tor\tbh,bh\n\tjs\tshort ??test_fading\t\t\n\n\tand\tebx,0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tmov\tal,[edi]\t\t\t; mov pixel at destination to al\n\tadd\tebx,[Translucent]\t\t; get the ptr to it!\n\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; get new pixel in al\n\n??test_fading:\n\ttest\tedx,SHAPE_FADING\n\tjnz\t??fading\n\tjmp\tshort ??general_draw_loop\n\n??priority:\t\n\tmov\tebx,[MaskAdjust]\t\t; get mask page\toffset\n\tmov\tbl,[BYTE PTR ebx + edi]\t\t; get mask value  \n\n\tand\tbl,CLEAR_UNUSED_BITS\t\t; clear unused bits\n\n\tcmp\t[PriLevel],bl\t\t\t; are we in front of\n\tjge\tshort ??test_predator\t\t;  background?\n\n\tmov\tebx,[BackAdjust]\t\t; get background page offset\n\tmov\tal,[BYTE PTR ebx + edi]\t\t; get background pixel\n\tjmp\t??general_draw_loop\n\n??predator:\n\tmov\tebx,[PartialCount]\n\tadd\tebx,[PartialPred]\t\n\tor\tbh,bh\n\tjnz\tshort ??draw_pred\t\t; is this a predator pixel?\n\tmov\t[PartialCount],ebx\n\tjmp\tshort ??test_compact\n\n??draw_pred:\n\txor\tbh,bh\n\tmov\t[PartialCount],ebx\n\tmov\tebx,[PredValue]\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\tmov\tal,[edi + ebx]\t\t\t;  viewport address\n\tjmp\t??general_draw_loop\n\n??compact:\n\tmov\tebx,[ColorTable]\t\t; get the address of the color table\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; convert it into the proper byte\n\tjmp\t??test_shadow\n\n??shadow:\n\tcmp\tal,SHADOW_COL\n\tjne\t??test_translucency\t\t; is the table value a magic number?\n\n\tmov\tal,[edi]\t\t\t; get the destination color and\n\tmov\tebx,[ShadowingTable]\t\t;  index into the shadow table\n\tmov\tal,[BYTE PTR ebx + eax]\n\tjmp\t??general_draw_loop\t\t\t\n\n??fading:\n\tmov\t[StashECX],ecx\t\t\t; preserve ecx for later\n\tmov\tebx,[FadingTable]\t\t; run color through fading table\n\tmov\tecx,[FadingNum]\n\n??fade_loop:\n\tmov\tal, [BYTE PTR ebx + eax]\n\tdec\tecx\n\tjnz\tshort ??fade_loop\n\n\tmov\tecx,[StashECX]\t\t\t; restore ecx for main draw loop\n\tjmp\t??general_draw_loop\t\t\t\n\n??general_is_run:\n\tmov\tal,[esi]\n\tinc\tesi\n\tsub\tedi,eax\t\t\t\t; move the viewport pointer\n\tsub\tecx,eax\t\t\t\t; chop down the width to do\n\tjg\t??general_draw_continue\t\t\t; while more to do, loop back up\n\n??out:\t\n\tadd\t[WidthCount],ecx\t\t; adjust for source ending in a run\n\tmov\tedx,[StashEDX]\n\tret\t\n\n\tENDP\tDraw_Reverse\n\n\n\tEND\n\n;**************************** End of ds_dr.asm *****************************\n"
  },
  {
    "path": "WWFLAT32/SHAPE/DS_DS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_DS.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : September 6, 1994   [IML]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Draw_Scale -- Draws a scaled row of pixels to the viewport            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Draw_Scale -- Draws a scaled row of pixels to the viewport              *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of pixels (not bytes) to draw\t\t   *\n;*\t\tEDX = XTotal initializer value\t\t\t\t   *\n;*\t\tESI = shape (source) buffer address\t\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = remaining bytes on the line\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;*\t\tESI - updated to current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) drawn/skipped\t   *\n;*\t\t[WidthCount] - bytes remaining on the line\t\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR  : Converted to 32-bit.                                 *\n;*   08/09/1994 IML : Optimized for 32-bit.\t\t\t\t   *\n;*   09/06/1994 IML : Integrated p_* and ds_* routines.\t\t\t   *\n;*=========================================================================*\nPROC\tDraw_Scale NOLANGUAGE NEAR\n\n\tmov\teax,0\t\t\t\t; init to 0\n\ttest\t[Flags],SHAPE_EFFECTS\n\tjnz\tshort ??general_draw_continue\n\tjmp\tshort ??fast_draw_continue\n\n\n\t;--------------------------------------------------------------------\n\t; Extra fast draw loop for shapes with no flags set.\n\t;--------------------------------------------------------------------\n\t\n\t;--------------------------------------------------------------------\n\t; Load a new byte:\n\t; - read the byte into AL\n\t; - if it's a run, deal with it\n\t; - otherwise, \n\t;\t- decrement [WidthCount]\n\t;\t- update EDX with [ScaleX]\n\t;\t- see if it's drawable (upon proc entry, it won't be)\n\t;\t\t- yes: draw a pixel\n\t;\t\t- no : load a new byte\n\t;--------------------------------------------------------------------\n??fast_draw_loop:\n\tmov\tal,[esi]\t\t\t; get the next pixel from the source\n\tinc\tesi\n\tor\teax,eax\n\tjz\tshort ??fast_is_run\t\t; deal with a run\n\tdec\t[WidthCount]\t\t\t; count down # bytes processed\n\tadd\tedx,[ScaleX]\t\t\t; add in the scale value\n\n??fast_draw_continue:\n\tor\tdh,dh\t\t\t\t; are there any pixels to draw?\n\tjz\tshort ??fast_draw_loop\n\n\n\t;--------------------------------------------------------------------\n\t; Draw one pixel:\n\t; - draw the pixel\n\t; - increment destination pointer\n\t; - decrement high byte of EDX (X-scale accumulator)\n\t; - loop (while ECX>0) to see if it's drawable\n\t;--------------------------------------------------------------------\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\tinc\tedi\t\t\t\t; increment the destination index\n\tdec\tdh\t\t\t\t; decrement the pixels to write\n\tdec\tecx\n\tjnz\tshort ??fast_draw_continue\n\tjmp\t??out\t\t\t\t; get the heck outta here\n\n\n\t;--------------------------------------------------------------------\n\t; Handle a run:\n\t; - Get the run repetition value\n\t; - subract it from [WidthCount]\n\t; - multiply it by [ScaleX]\n\t; - put high bytes from mul into EAX, low byte into DL (roundoff bits)\n\t; - add high bytes (# pixels) to EDI\n\t; - subtract them from ECX\n\t; - clear EAX\n\t; - if ECX>0, go get next byte\n\t;--------------------------------------------------------------------\n??fast_is_run:\n\tmov\tal,[esi]\t\t\t; get number of repeated values\n\tinc\tesi\n\tsub\t[WidthCount],eax\t\t; adjust the remaining byte width\n\tmov\tebx,edx\t\t\t\t; preserve dx for the multiply\n\tmul\t[ScaleX]\t\t\t; EDX:EAX = # pixels + roundoff bits\n\tadd\teax,ebx\t\t\t\t; add in the current x-total\n\tmov\tedx,eax\t\t\t\t; (assume EDX is empty)\n\tshr\teax,8\t\t\t\t; EAX = # pixels skipped\n\tand\tedx,00FFh\t\t\t; keep only low byte\n\tadd\tedi,eax\t\t\t\t; add to EDI\n     \tsub\tecx,eax\t\t\t\t; subtract it from ECX\n\tmov\teax,0\t\t\t\t; clear EAX\n\tor\tecx,ecx\n\tjg\tshort ??fast_draw_loop\t\t; if more to draw, process new byte\n\tjmp\t??out\n\n\n\t;--------------------------------------------------------------------\n\t; General purpose draw loop for shapes with one or more flags set.\n\t;--------------------------------------------------------------------\n\n\t;--------------------------------------------------------------------\n\t; Load a new byte:\n\t; - read the byte into AL\n\t; - if it's a run, deal with it\n\t; - otherwise, \n\t;\t- decrement [WidthCount]\n\t;\t- update EDX with [ScaleX]\n\t;\t- see if it's drawable (upon proc entry, it won't be)\n\t;\t\t- yes: draw a pixel\n\t;\t\t- no : load a new byte\n\t;--------------------------------------------------------------------\n??general_draw_loop:\n\tmov\tal,[esi]\t\t\t; get the next pixel from the source\n\tinc\tesi\n\tor\teax,eax\n\tjz\t??general_is_run\t\t; deal with a run\n\tdec\t[WidthCount]\t\t\t; count down # bytes processed\n\tadd\tedx,[ScaleX]\t\t\t; add in the scale value\n\n??general_draw_continue:\n\tor\tdh,dh\t\t\t\t; are there any pixels to draw?\n\tjz\tshort ??general_draw_loop\n\n\t;--------------------------------------------------------------------\n\t; Draw one pixel:\n\t; - draw the pixel\n\t; - increment destination pointer\n\t; - decrement high byte of EDX (X-scale accumulator)\n\t; - loop (while ECX>0) to see if it's drawable\n\t;--------------------------------------------------------------------\n??draw:\n\tmov\t[StashReg],eax\t\t\t; save eax\n\tmov\t[StashEDX],edx\t\t\t; save edx\n\tmov\tedx,[Flags]\n\n??test_priority:\n\ttest\tedx,SHAPE_PRIORITY\t\t\n\tjnz\tshort ??priority\n\n??test_predator:\n\ttest\tedx,SHAPE_PREDATOR\n\tjnz\tshort ??predator\n\n??test_compact:\n\ttest\tedx,SHAPE_COMPACT\n\tjnz\t??compact\n\n??test_shadow:\n\ttest\tedx,SHAPE_SHADOW\n\tjnz\t??shadow\n\n??test_translucency:\n\ttest\tedx,SHAPE_GHOST\n\tjnz\t??translucency\n\n??test_fading:\n\ttest\tedx,SHAPE_FADING\n\tjnz\t??fading\n\n\n??test_transparency:\t\n\ttest\tedx,SHAPE_FADING\t\t; if fading is enabled test for\n\tjz\tshort ??no_fading_draw_loop\t;   transparency\n\tor\teax,eax\n\tjz\tshort ??is_transparent\n\n??no_fading_draw_loop:\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\t\n??is_transparent:\n\tmov\teax,[StashReg]\t\t\t; restore eax\n\tmov\tedx,[StashEDX]\t\t\t; restore edx\n\tinc\tedi\t\t\t\t; increment the destination index\n\tdec\tdh\t\t\t\t; decrement the pixels to write\n\tdec\tecx\n\tjnz\t??general_draw_continue\n\tjmp\t??out\t\t\t\t; get the heck outta here\n\n??priority:\t\n\tmov\tebx,[MaskAdjust]\t\t; get mask page\toffset\n\tmov\tbl,[BYTE PTR ebx + edi]\t\t; get mask value  \n\n\tand\tbl,CLEAR_UNUSED_BITS\t\t; clear unused bits\n\n\tcmp\t[PriLevel],bl\t\t\t; are we in front of\n\tjge\tshort ??test_predator\t\t;  background?\n\n\tmov\tebx,[BackAdjust]\t\t; get background page offset\n\tmov\tal,[BYTE PTR ebx + edi]\t\t; get background pixel\n\tjmp\tshort ??test_transparency\n\n??predator:\n\tmov\tebx,[PartialCount]\n\tadd\tebx,[PartialPred]\t\n\tor\tbh,bh\n\tjnz\tshort ??draw_pred\t\t; is this a predator pixel?\n\tmov\t[PartialCount],ebx\n\tjmp\t??test_compact\n\n??draw_pred:\n\txor\tbh,bh\n\tmov\t[PartialCount],ebx\n\tmov\tebx,[PredValue]\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\tmov\tal,[edi + ebx]\t\t\t;  viewport address\n\tjmp\tshort ??test_transparency\n\n??compact:\n\tmov\tebx,[ColorTable]\t\t; get the address of the color table\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; convert it into the proper byte\n\tjmp\t??test_shadow\n\n??shadow:\n\tcmp\tal,SHADOW_COL\n\tjne\t??test_translucency\t\t; is the table value a magic number?\n\n\tmov\tal,[edi]\t\t\t; get the destination color and\n\tmov\tebx,[ShadowingTable]\t\t;  index into the shadow table\n\tmov\tal,[BYTE PTR ebx + eax]\n\tjmp\t??test_transparency\t\t\t\n\n??fading:\n\tmov\t[StashECX],ecx\t\t\t; preserve ecx for later\n\tmov\tebx,[FadingTable]\t\t; run color through fading table\n\tmov\tecx,[FadingNum]\n\n??fade_loop:\n\tmov\tal, [BYTE PTR ebx + eax]\n\tdec\tecx\n\tjnz\tshort ??fade_loop\n\n\tmov\tecx,[StashECX]\t\t\t; restore ecx for main draw loop\n\tjmp\t??test_transparency\n\n??translucency:\n\tmov\tebx,[IsTranslucent]\t\t; is it a translucent color?\n\tmov\tbh,[BYTE PTR ebx + eax]\n\tor\tbh,bh\n\tjs\t??test_fading\n\n\tand\tebx,0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tmov\tal,[edi]\t\t\t; mov pixel at destination to al\n\tadd\tebx,[Translucent]\t\t; get the ptr to it!\n\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; get new pixel in al\n\tjmp\t??test_fading\n\n\n\t;--------------------------------------------------------------------\n\t; Handle a run:\n\t; - Get the run repetition value\n\t; - subract it from [WidthCount]\n\t; - multiply it by [ScaleX]\n\t; - put high bytes from mul into EAX, low byte into DL (roundoff bits)\n\t; - add high bytes (# pixels) to EDI\n\t; - subtract them from ECX\n\t; - clear EAX\n\t; - if ECX>0, go get next byte\n\t;--------------------------------------------------------------------\n??general_is_run:\n\tmov\tal,[esi]\t\t\t; get number of repeated values\n\tinc\tesi\n\tsub\t[WidthCount],eax\t\t; adjust the remaining byte width\n\tmov\tebx,edx\t\t\t\t; preserve dx for the multiply\n\tmul\t[ScaleX]\t\t\t; EDX:EAX = # pixels + roundoff bits\n\tadd\teax,ebx\t\t\t\t; add in the current x-total\n\tmov\tedx,eax\t\t\t\t; (assume EDX is empty)\n\tshr\teax,8\t\t\t\t; EAX = # pixels skipped\n\tand\tedx,00FFh\t\t\t; keep only low byte\n\tadd\tedi,eax\t\t\t\t; add to EDI\n     \tsub\tecx,eax\t\t\t\t; subtract it from ECX\n\tmov\teax,0\t\t\t\t; clear EAX\n\tor\tecx,ecx\n\tjg\t??general_draw_loop\t\t; if more to draw, process new byte\n\n??out:\n\tret\t\t\t\t\t; lets get out of here\n\n\tENDP\tDraw_Scale\n\n\tEND\n\n;**************************** End of ds_ds.asm ******************************\n"
  },
  {
    "path": "WWFLAT32/SHAPE/DS_DSR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_DSR.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : September 6, 1994   [IML]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Draw_Scale_Reverse -- Draws a scaled row of pixels to the viewport    *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;*******p********************************************************************\n;* Draw_Scale_Reverse -- Draws a scaled row of pixels to the viewport      *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of pixels (not bytes) to draw\t\t   *\n;*\t\tEDX = XTotal initializer value\t\t\t\t   *\n;*\t\tESI = shape (source) buffer address\t\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = remaining bytes on the line\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;*\t\tESI - updated to current location in the shape data\t   *\n;*\t\tEDI - incr/decr by # pixels (not bytes) drawn/skipped\t   *\n;*\t\t[WidthCount] - bytes remaining on the line\t\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR  : Converted to 32-bit.                                 *\n;*   08/09/1994 IML : Optimized for 32-bit\t\t\t\t   *\n;*   09/06/1994 IML : Integrated p_* and ds_* routines.\t\t\t   *\n;*=========================================================================*\nPROC\tDraw_Scale_Reverse NOLANGUAGE NEAR\n\n\tmov\teax,0\t\t\t\t; init to 0\n\ttest\t[Flags],SHAPE_EFFECTS\n\tjnz\tshort ??general_draw_continue\n\tjmp\tshort ??fast_draw_continue\n\n\n\t;--------------------------------------------------------------------\n\t; Extra fast draw loop for shapes with no flags set.\n\t;--------------------------------------------------------------------\n\t\n\t;--------------------------------------------------------------------\n\t; Load a new byte:\n\t; - read the byte into AL\n\t; - if it's a run, deal with it\n\t; - otherwise, \n\t;\t- decrement [WidthCount]\n\t;\t- update EDX with [ScaleX]\n\t;\t- see if it's drawable (upon proc entry, it won't be)\n\t;\t\t- yes: draw a pixel\n\t;\t\t- no : load a new byte\n\t;--------------------------------------------------------------------\n??fast_draw_loop:\n\tmov\tal,[esi]\t\t\t; get the next pixel from the source\n\tinc\tesi\n\tor\teax,eax\n\tjz\tshort ??fast_is_run\t\t; deal with a run\n\tdec\t[WidthCount]\t\t\t; count down # bytes processed\n\tadd\tedx,[ScaleX]\t\t\t; add in the scale value\n\n??fast_draw_continue:\n\tor\tdh,dh\t\t\t\t; are there any pixels to draw?\n\tjz\tshort ??fast_draw_loop\n\n\n\t;--------------------------------------------------------------------\n\t; Draw one pixel:\n\t; - draw the pixel\n\t; - increment destination pointer\n\t; - decrement high byte of EDX (X-scale accumulator)\n\t; - loop (while ECX>0) to see if it's drawable\n\t;--------------------------------------------------------------------\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\tdec\tedi\t\t\t\t; decrement the destination index\n\tdec\tdh\t\t\t\t; decrement the pixels to write\n\tdec\tecx\n\tjnz\tshort ??fast_draw_continue\n\tjmp\t??out\t\t\t\t; get the heck outta here\n\n\n\t;--------------------------------------------------------------------\n\t; Handle a run:\n\t; - Get the run repetition value\n\t; - subract it from [WidthCount]\n\t; - multiply it by [ScaleX]\n\t; - put high bytes from mul into EAX, low byte into DL (roundoff bits)\n\t; - add high bytes (# pixels) to EDI\n\t; - subtract them from ECX\n\t; - clear EAX\n\t; - if ECX>0, go get next byte\n\t;--------------------------------------------------------------------\n??fast_is_run:\n\tmov\tal,[esi]\t\t\t; get number of repeated values\n\tinc\tesi\n\tsub\t[WidthCount],eax\t\t; adjust the remaining byte width\n\tmov\tebx,edx\t\t\t\t; preserve dx for the multiply\n\tmul\t[ScaleX]\t\t\t; EDX:EAX = # pixels + roundoff bits\n\tadd\teax,ebx\t\t\t\t; add in the current x-total\n\tmov\tedx,eax\t\t\t\t; (assume EDX is empty)\n\tshr\teax,8\t\t\t\t; EAX = # pixels skipped\n\tand\tedx,00FFh\t\t\t; keep only low byte\n\tsub\tedi,eax\t\t\t\t; sub from EDI\n     \tsub\tecx,eax\t\t\t\t; subtract it from ECX\n\tmov\teax,0\t\t\t\t; clear EAX\n\tor\tecx,ecx\n\tjg\tshort ??fast_draw_loop\t\t; if more to draw, process new byte\n\tjmp\t??out\n\n\n\t;--------------------------------------------------------------------\n\t; General purpose draw loop for shapes with one or more flags set.\n\t;--------------------------------------------------------------------\n\n\t;--------------------------------------------------------------------\n\t; Load a new byte:\n\t; - read the byte into AL\n\t; - if it's a run, deal with it\n\t; - otherwise, \n\t;\t- decrement [WidthCount]\n\t;\t- update EDX with [ScaleX]\n\t;\t- see if it's drawable (upon proc entry, it won't be)\n\t;\t\t- yes: draw a pixel\n\t;\t\t- no : load a new byte\n\t;--------------------------------------------------------------------\n??general_draw_loop:\n\tmov\tal,[esi]\t\t\t; get the next pixel from the source\n\tinc\tesi\n\tor\teax,eax\n\tjz\t??general_is_run\t\t; deal with a run\n\tdec\t[WidthCount]\t\t\t; count down # bytes processed\n\tadd\tedx,[ScaleX]\t\t\t; add in the scale value\n\n??general_draw_continue:\n\tor\tdh,dh\t\t\t\t; are there any pixels to draw?\n\tjz\tshort ??general_draw_loop\n\n\t;--------------------------------------------------------------------\n\t; Draw one pixel:\n\t; - draw the pixel\n\t; - increment destination pointer\n\t; - decrement high byte of EDX (X-scale accumulator)\n\t; - loop (while ECX>0) to see if it's drawable\n\t;--------------------------------------------------------------------\n??draw:\n\tmov\t[StashReg],eax\t\t\t; save eax\n\tmov\t[StashEDX],edx\t\t\t; save edx\n\tmov\tedx,[Flags]\n\n??test_priority:\n\ttest\tedx,SHAPE_PRIORITY\t\t\n\tjnz\tshort ??priority\n\n??test_predator:\n\ttest\tedx,SHAPE_PREDATOR\n\tjnz\tshort ??predator\n\n??test_compact:\n\ttest\tedx,SHAPE_COMPACT\n\tjnz\t??compact\n\n??test_shadow:\n\ttest\tedx,SHAPE_SHADOW\n\tjnz\t??shadow\n\n??test_translucency:\n\ttest\tedx,SHAPE_GHOST\n\tjnz\t??translucency\n\n??test_fading:\n\ttest\tedx,SHAPE_FADING\n\tjnz\t??fading\n\n??test_transparency:\t\n\ttest\tedx,SHAPE_FADING\t\t; if fading is enabled test for\n\tjz\tshort ??no_fading_draw_loop\t;   transparency\n\tor\teax,eax\n\tjz\tshort ??is_transparent\n\n??no_fading_draw_loop:\n\tmov\t[edi],al\t\t\t; store color value to viewport\n\t\n??is_transparent:\n\tmov\teax,[StashReg]\t\t\t; restore eax\n\tmov\tedx,[StashEDX]\t\t\t; restore edx\n\tdec\tedi\t\t\t\t; decrement the destination index\n\tdec\tdh\t\t\t\t; decrement the pixels to write\n\tdec\tecx\n\tjnz\t??general_draw_continue\n\tjmp\t??out\t\t\t\t; get the heck outta here\n\n??priority:\t\n\tmov\tebx,[MaskAdjust]\t\t; get mask page\toffset\n\tmov\tbl,[BYTE PTR ebx + edi]\t\t; get mask value  \n\n\tand\tbl,CLEAR_UNUSED_BITS\t\t; clear unused bits\n\n\tcmp\t[PriLevel],bl\t\t\t; are we in front of\n\tjge\tshort ??test_predator\t\t;  background?\n\n\tmov\tebx,[BackAdjust]\t\t; get background page offset\n\tmov\tal,[BYTE PTR ebx + edi]\t\t; get background pixel\n\tjmp\tshort ??test_transparency\n\n??predator:\n\tmov\tebx,[PartialCount]\n\tadd\tebx,[PartialPred]\t\n\tor\tbh,bh\n\tjnz\tshort ??draw_pred\t\t; is this a predator pixel?\n\tmov\t[PartialCount],ebx\n\tjmp\t??test_compact\n\n??draw_pred:\n\txor\tbh,bh\n\tmov\t[PartialCount],ebx\n\tmov\tebx,[PredValue]\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\tmov\tal,[edi + ebx]\t\t\t;  viewport address\n\tjmp\tshort ??test_transparency\n\n??compact:\n\tmov\tebx,[ColorTable]\t\t; get the address of the color table\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; convert it into the proper byte\n\tjmp\t??test_shadow\n\n??shadow:\n\tcmp\tal,SHADOW_COL\n\tjne\t??test_translucency\t\t; is the table value a magic number?\n\n\tmov\tal,[edi]\t\t\t; get the destination color and\n\tmov\tebx,[ShadowingTable]\t\t;  index into the shadow table\n\tmov\tal,[BYTE PTR ebx + eax]\n\tjmp\t??test_transparency\t\t\t\n\n??fading:\n\tmov\t[StashECX],ecx\t\t\t; preserve ecx for later\n\tmov\tebx,[FadingTable]\t\t; run color through fading table\n\tmov\tecx,[FadingNum]\n\n??fade_loop:\n\tmov\tal, [BYTE PTR ebx + eax]\n\tdec\tecx\n\tjnz\tshort ??fade_loop\n\n\tmov\tecx,[StashECX]\t\t\t; restore ecx for main draw loop\n\tjmp\t??test_transparency\n\n??translucency:\n\tmov\tebx,[IsTranslucent]\t\t; is it a translucent color?\n\tmov\tbh,[BYTE PTR ebx + eax]\n\tor\tbh,bh\n\tjs\t??test_fading\n\n\tand\tebx,0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tmov\tal,[edi]\t\t\t; mov pixel at destination to al\n\tadd\tebx,[Translucent]\t\t; get the ptr to it!\n\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\tmov\tal,[BYTE PTR ebx + eax]\t\t; get new pixel in al\n\tjmp\t??test_fading\n\n\n\t;--------------------------------------------------------------------\n\t; Handle a run:\n\t; - Get the run repetition value\n\t; - subract it from [WidthCount]\n\t; - multiply it by [ScaleX]\n\t; - put high bytes from mul into EAX, low byte into DL (roundoff bits)\n\t; - add high bytes (# pixels) to EDI\n\t; - subtract them from ECX\n\t; - clear EAX\n\t; - if ECX>0, go get next byte\n\t;--------------------------------------------------------------------\n??general_is_run:\n\tmov\tal,[esi]\t\t\t; get number of repeated values\n\tinc\tesi\n\tsub\t[WidthCount],eax\t\t; adjust the remaining byte width\n\tmov\tebx,edx\t\t\t\t; preserve dx for the multiply\n\tmul\t[ScaleX]\t\t\t; EDX:EAX = # pixels + roundoff bits\n\tadd\teax,ebx\t\t\t\t; add in the current x-total\n\tmov\tedx,eax\t\t\t\t; (assume EDX is empty)\n\tshr\teax,8\t\t\t\t; EAX = # pixels skipped\n\tand\tedx,00FFh\t\t\t; keep only low byte\n\tsub\tedi,eax\t\t\t\t; sub from EDI\n     \tsub\tecx,eax\t\t\t\t; subtract it from ECX\n\tmov\teax,0\t\t\t\t; clear EAX\n\tor\tecx,ecx\n\tjg\t??general_draw_loop\t\t; if more to draw, process new byte\n\n??out:\n\tret\t\t\t\t\t; lets get out of here\n\n\n\tENDP\tDraw_Scale_Reverse\n\t\n\tEND\n\n;*************************** End of ds_dsr.asm ******************************\n"
  },
  {
    "path": "WWFLAT32/SHAPE/DS_LRS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_LRS.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 2, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Left_Reverse_Skip -- Skips bytes in a data stream\t\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Left_Reverse_Skip -- Skips bytes in a data stream\t\t\t   *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape (source) buffer data address\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = shape's width\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX - negative # pixels overrun, or 0\t\t\t   *\n;*\t\tEDX - XTotal initializer value (0 since there's no scaling)*\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\tEDI - decremented by # pixels overrun\t\t\t   *\n;*\t\t[WidthCount] - decremented by # bytes skipped\t\t   *\n;*                                                                         *\n;* WARNINGS:\tnone                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   05/28/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tLeft_Reverse_Skip NOLANGUAGE NEAR\n\n\tsub \t[WidthCount],ecx\t; we process ECX bytes of real width\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out\t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tadd\tedi,ecx\t\t\t; decrement EDI by overrun pixels\n\tadd\t[WidthCount],ecx\t; adjust by # bytes overrun\n\tmov\tedx,0\t\t\t; no scaling, so clear EDX\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tLeft_Reverse_Skip\n\n\tEND\n\n;*************************** End of ds_lrs.asm *****************************\n\u001a"
  },
  {
    "path": "WWFLAT32/SHAPE/DS_LS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_LS.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 2, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Left_Skip -- Skips bytes in a data stream\t\t\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Left_Skip -- Skips bytes in a data stream\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape (source) buffer data address\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = shape's width\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX - negative # pixels overrun, or 0\t\t\t   *\n;*\t\tEDX - XTotal initializer value (0 since there's no scaling)*\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\tEDI - incremented by # pixels overrun\t\t\t   *\n;*\t\t[WidthCount] - decremented by # bytes skipped\t\t   *\n;*                                                                         *\n;* WARNINGS:\tnone                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tLeft_Skip NOLANGUAGE NEAR\n\n\tsub \t[WidthCount],ecx\t; we process ECX bytes of real width\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out\t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tsub\tedi,ecx\t\t\t; increment EDI by overrun pixels\n\tadd\t[WidthCount],ecx\t; adjust by # bytes overrun\n\tmov\tedx,0\t\t\t; no scaling, so clear EDX\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tLeft_Skip\n\n\tEND\n\n;**************************** End of ds_ls.asm *****************************\n\u001a"
  },
  {
    "path": "WWFLAT32/SHAPE/DS_LSRS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_LSRS.ASM                              *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 2, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Left_Scale_Reverse_Skip -- Skips past a scaled row of pixels          *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Left_Scale_Reverse_Skip -- Skips past a scaled row of pixels            *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape (source) buffer data address\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = shape's width\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX - negative # pixels (not bytes) overrun, or 0\t   *\n;*\t\tEDX - XTotal initializer value\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\tEDI - decremented by # pixels (not bytes) overrun\t   *\n;*\t\t[WidthCount] - decremented by # bytes skipped\t\t   *\n;*                                                                         *\n;* The value returned in EDX reflects what XTotal's accumulated value \t   *\n;* should be at the new pixel location.  If no bytes are overrun, this\t   *\n;* will be whatever is stored in [XTotalInit] (which will be 0 if no\t   *\n;* pixels are left-clipped).\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:\tnone                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/20/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tLeft_Scale_Reverse_Skip NOLANGUAGE NEAR\n\n\tsub \t[WidthCount],ecx\t; we process ECX bytes of real width\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjcxz\t??getrem\t\t; exit if no bytes to skip\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\tshort ??on_run\t\t; if it is a run then deal with it\n\n\t;--------------------------------------------------------------------\n\t; Default exit point: store default x-scale bits & exit\n\t;--------------------------------------------------------------------\n??getrem:\n\tmov\tedx,[XTotalInit]\t; store out the remainder\n\tjmp\tshort ??out \t\t; we're done, get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\tjz\t??getrem\t\t; exactly enough bytes; exit\n\n\t;--------------------------------------------------------------------\n\t; Overrun exit point: ECX is negative by the # of bytes overrun.\n\t; - adjust [WidthCount] by # of overrun bytes\n\t; - compute the remainder at the new location (EDX)\n\t; - compute the number of destination pixels to skip (ECX)\n\t; - adjust EDI by # of overrun bytes\n\t;--------------------------------------------------------------------\n\t;\n\t;............... adjust [WidthCount] by overrun bytes ...............\n\t;\n\tadd\t[WidthCount],ecx\t; adjust overrun in bytes\n\t;\n\t;................. put x-scale roundoff bits in EDX .................\n\t;\n\tmov\teax,ecx\t\t\t; get the number of bytes we overran\n\tneg\teax\t\t\t; negate it since overun is negative\n\tadd\teax,[LeftClipBytes]\t; add the number of bytes we leftclip\n\tmul \t[ScaleX]\t\t; convert to pixels plus roundoff bits\n\tmov\tedx,0\t\t\t; clear EDX\n\tmov\tdl,al\t\t\t; DL = x-scaling roundoff bits\n\t;\n\t;................ put negative overrun pixels in ECX ................\n\t;\n\tshr\teax,8\t\t\t; EAX = total # left pixels\n\tsub\teax,[LeftClipPixels]\t; EAX = # pixels overrun\n\tmov\tecx,eax\t\t\t; store # overrun pixels\n\tneg\tecx\t\t\t; make it negative\n\t;\n\t;................ adjust dest ptr by overrun pixels .................\n\t;\n\tsub\tesi,eax\t\t\t; decrement ESI (EDI) by overrun pixels\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tLeft_Scale_Reverse_Skip\n\n\tEND\n\n;**************************** End of ds_lsrs.asm ****************************\n\u001a"
  },
  {
    "path": "WWFLAT32/SHAPE/DS_LSS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_LSS.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 2, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Left_Scale_Skip -- Skips past a scaled row of pixels on left side     *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Left_Scale_Skip -- Skips past a scaled row of pixels on left side       *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape (source) buffer data address\t\t   *\n;*\t\tEDI = viewport (destination) address\t\t\t   *\n;*\t\t[WidthCount] = shape's width\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX - negative # pixels (not bytes) overrun, or 0\t   *\n;*\t\tEDX - XTotal initializer value\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*\t\tEDI - incremented by # pixels (not bytes) overrun\t   *\n;*\t\t[WidthCount] - decremented by # bytes skipped\t\t   *\n;*                                                                         *\n;* The value returned in EDX reflects what XTotal's accumulated value \t   *\n;* should be at the new pixel location.  If no bytes are overrun, this\t   *\n;* will be whatever is stored in [XTotalInit] (which will be 0 if no\t   *\n;* pixels are left-clipped).\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:\tnone                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/08/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/02/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tLeft_Scale_Skip NOLANGUAGE NEAR\n\n\tsub \t[WidthCount],ecx\t; we process ECX bytes of real width\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjcxz\t??getrem\t\t; exit if no bytes to skip\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\tshort ??on_run\t\t; if it is a run then deal with it\n\n\t;--------------------------------------------------------------------\n\t; Default exit point: store default x-scale bits & exit\n\t;--------------------------------------------------------------------\n??getrem:\n\tmov\tedx,[XTotalInit]\t; store out the remainder\n\tjmp\tshort ??out \t\t; we're done, get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\tjz\t??getrem\t\t; exactly enough bytes; exit\n\n\t;--------------------------------------------------------------------\n\t; Overrun exit point: ECX is negative by the # of bytes overrun.\n\t; - adjust [WidthCount] by # of overrun bytes\n\t; - compute the remainder at the new location (EDX)\n\t; - compute the number of destination pixels to skip (ECX)\n\t; - adjust EDI by # of overrun bytes\n\t;--------------------------------------------------------------------\n\t;\n\t;............... adjust [WidthCount] by overrun bytes ...............\n\t;\n\tadd\t[WidthCount],ecx\t; adjust overrun in bytes\n\t;\n\t;................. put x-scale roundoff bits in EDX .................\n\t;\n\tmov\teax,ecx\t\t\t; get the number of bytes we overran\n\tneg\teax\t\t\t; negate it since overun is negative\n\tadd\teax,[LeftClipBytes]\t; add the number of bytes we leftclip\n\tmul \t[ScaleX]\t\t; convert to pixels plus roundoff bits\n\tmov\tedx,0\t\t\t; clear EDX\n\tmov\tdl,al\t\t\t; DL = x-scaling roundoff bits\n\t;\n\t;................ put negative overrun pixels in ECX ................\n\t;\n\tshr\teax,8\t\t\t; EAX = total # left pixels\n\tsub\teax,[LeftClipPixels]\t; EAX = # pixels overrun\n\tmov\tecx,eax\t\t\t; store # overrun pixels\n\tneg\tecx\t\t\t; make it negative\n\t;\n\t;................ adjust dest ptr by overrun pixels .................\n\t;\n\tadd\tesi,eax\t\t\t; increment ESI (EDI) by overrun pixels\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tLeft_Scale_Skip\n\n\tEND\n\n;**************************** End of ds_lss.asm *****************************\n\u001a"
  },
  {
    "path": "WWFLAT32/SHAPE/DS_RRS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_RRS.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : May 28, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Right_Reverse_Skip -- Skips bytes in a data stream\t\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Right_Reverse_Skip -- Skips bytes in a data stream\t\t\t   *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape buffer data address\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*                                                                         *\n;* WARNINGS:\tThis routine may overrun the number of requested bytes\t   *\n;*\t\tif it encounters a run of 0's; however, it's assumed that  *\n;*\t\tthe shape data will never contain a run that goes past the *\n;*\t\tright-hand edge of the shape.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   05/28/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tRight_Reverse_Skip NOLANGUAGE NEAR\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out\t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tRight_Reverse_Skip\n\n\tEND\n\n;**************************** End of ds_rrs.asm ****************************\n\u001a"
  },
  {
    "path": "WWFLAT32/SHAPE/DS_RS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_RS.ASM                                *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : May 28, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Right_Skip -- Skips bytes in a data stream\t\t\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Right_Skip -- Skips bytes in a data stream\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape buffer data address\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*                                                                         *\n;* WARNINGS:\tThis routine may overrun the number of requested bytes\t   *\n;*\t\tif it encounters a run of 0's; however, it's assumed that  *\n;*\t\tthe shape data will never contain a run that goes past the *\n;*\t\tright-hand edge of the shape.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/14/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   05/28/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tRight_Skip NOLANGUAGE NEAR\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out\t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tRight_Skip\n\n\tEND\n\n;**************************** End of ds_rs.asm ******************************\n\u001a"
  },
  {
    "path": "WWFLAT32/SHAPE/DS_RSRS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_RSRS.ASM                              *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 1, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Right_Scale_Reverse_Skip -- Skips past a scaled row of pixels         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Right_Scale_Reverse_Skip -- Skips past a scaled row of pixels           *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape buffer data address\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*                                                                         *\n;* WARNINGS:\tThis routine may overrun the number of requested bytes\t   *\n;*\t\tif it encounters a run of 0's; however, it's assumed that  *\n;*\t\tthe shape data will never contain a run that goes past the *\n;*\t\tright-hand edge of the shape.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/20/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/01/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tRight_Scale_Reverse_Skip NOLANGUAGE NEAR\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out \t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tRight_Scale_Reverse_Skip\n\n\tEND\n\n;*************************** End of ds_rsrs.asm ****************************\n\u001a"
  },
  {
    "path": "WWFLAT32/SHAPE/DS_RSS.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_RSS.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 24, 1993                          *\n;*                                                                         *\n;*                  Last Update : June 1, 1994   [BR]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Right_Scale_Skip -- Skips past a scaled row of pixels on right side   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Right_Scale_Skip -- Skips past a scaled row of pixels on the right side *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tECX = number of uncompressed bytes to skip\t\t   *\n;*\t\tESI = shape buffer data address\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT:\t\t\t\t\t\t\t\t   *\n;*\t\tESI - updated to the current location in the shape data\t   *\n;*                                                                         *\n;* WARNINGS:\tThis routine may overrun the number of requested bytes\t   *\n;*\t\tif it encounters a run of 0's; however, it's assumed that  *\n;*\t\tthe shape data will never contain a run that goes past the *\n;*\t\tright-hand edge of the shape.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/20/1992 PWG : Created.                                             *\n;*   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n;*   06/01/1994 BR : Converted to 32-bit                                   *\n;*=========================================================================*\nPROC\tRight_Scale_Skip NOLANGUAGE NEAR\n\n\t;--------------------------------------------------------------------\n\t; Put shape data address in EDI so we can do a scasb on it\n\t;--------------------------------------------------------------------\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tjecxz\t??out\t\t\t; exit if ECX is 0 (no bytes to skip)\n\n\t;--------------------------------------------------------------------\n\t; Search through the string and count down the info we have handled.\n\t; If we find a run (0 followed by a count byte), then handle it.\n\t;--------------------------------------------------------------------\n??cliptop:\n\tmov\teax,0\t\t\t; set al to 0 (we're scanning for 0)\n\trepne\tscasb\t\t\t; scan through source data\n\tjz\t??on_run\t\t; if it is a run then deal with it\n\tjecxz\t??out \t\t\t; if we're done then get outta here\n\n\t;--------------------------------------------------------------------\n\t; If we have a run then get the next byte which is the length.  \n\t;--------------------------------------------------------------------\n??on_run:\n\tmov\tal,[BYTE PTR edi]\t; get the count of zeros to run\n\tinc\tedi\t\t\t; advance past the count\n\tinc\tecx\t\t\t; the 0 found doesn't count\n\tsub\tecx,eax\t\t\t; subtract the count from remaining\n\tjg\t??cliptop\t\t; if more bytes left, scan again\n\n\t;--------------------------------------------------------------------\n\t; Put shape address back into ESI, adjust EDI\n\t;--------------------------------------------------------------------\n??out:\n\txchg\tesi,edi\t\t\t; xchange ESI and EDI\n\tret\t\t\t\t; return back to the real function\n\n\tENDP\tRight_Scale_Skip\n\n\tEND\n\n;*************************** End of ds_rss.asm *****************************\n\u001a"
  },
  {
    "path": "WWFLAT32/SHAPE/DS_TABLE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Draw Shape Routines for library.         *\n;*                                                                         *\n;*                    File Name : DS_TABLE.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : August 20, 1993                          *\n;*                                                                         *\n;*                  Last Update : September 6, 1994   [IML]                *\n;*                                                                         *\n;* This module sets up a table of procedure addresses for combinations of  *\n;* NORMAL, HORZ_REV and SCALING\tflags.\t\t\t\t\t   *\t\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************** Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\n\n;******************************** Equates **********************************\n;*=========================================================================*/\n;* The following are defines used to control what functions are linked\t   *\n;* in for Draw_Shape.\t\t\t\t\t\t\t   *\n;*=========================================================================*/\nUSE_NORMAL\tEQU\tTRUE\nUSE_HORZ_REV \tEQU\tTRUE\nUSE_VERT_REV \tEQU\tTRUE\nUSE_SCALING \tEQU\tTRUE\n\n\n;---------------------------------------------------------------------------\n;\n; Use a macro to make code a little cleaner.\n; The parameter varname is optional.\n; Syntax to use macro is :\n;  WANT equ expression\n;  USE func [,varname]\n; If the 'varname' is defined, a table declaration is created like:\n;\tGLOBAL\tTableName:DWORD\n; Then, the table entry is created:\n;  If WANT is true, the table entry is created for the given function:\n;\tvarname\tDD\tfunc\n;  If WANT is not TRUE, a Not_Supported entry is put in the table:\n;\tvarname\tDD\tNot_Supported\n; The resulting tables look like:\n;\n;\tGLOBAL\tExampTable:DWORD\n;\tExampTable\tDD\troutine1\n;\t\t\tDD\troutine2\n;\t\t\tDD\troutine3\n;\t\t\t...\n; Thus, each table is an array of function pointers.\n;\n;---------------------------------------------------------------------------\nMACRO USE func, varname\n IFNB <varname>\n\tGLOBAL\tvarname:DWORD\n ENDIF\n IF WANT\n  varname \tDD\tfunc\n ELSE\n  varname\tDD\tNot_Supported\n ENDIF\nENDM\n\n\n;---------------------------------------------------------------------------\n; Data Segment Tables:\n; This code uses the USE macro to set up tables of function addresses.\n; The tables have the following format:\n; Tables defined are:\n;\tLSkipTable\n;\tRSkipTable\n;\tDrawTable\n;---------------------------------------------------------------------------\n\n\tDATASEG\n\n;---------------------------------------------------------------------------\n\nWANT\tequ \t<TRUE>\nUSE\tLeft_Skip, LSkipTable\n\nWANT\tequ \t<TRUE>\nUSE\tLeft_Reverse_Skip\n\nWANT\tequ \t<TRUE>\nUSE\tLeft_Skip\n\nWANT\tequ \t<TRUE>\nUSE\tLeft_Reverse_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tLeft_Scale_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tLeft_Scale_Reverse_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tLeft_Scale_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tLeft_Scale_Reverse_Skip\n;---------------------------------------------------------------------------\n\nWANT\tequ \t<TRUE>\nUSE\tRight_Skip, RSkipTable\n\nWANT\tequ \t<TRUE>\nUSE\tRight_Reverse_Skip\n\nWANT\tequ \t<TRUE>\nUSE\tRight_Skip\n\nWANT\tequ \t<TRUE>\nUSE\tRight_Reverse_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tRight_Scale_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tRight_Scale_Reverse_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tRight_Scale_Skip\n\nWANT\tequ \t<USE_SCALING>\nUSE\tRight_Scale_Reverse_Skip\n;---------------------------------------------------------------------------\n\nWANT\tequ \t<TRUE>\nUSE\tDraw_Normal, DrawTable\n\nWANT\tequ \t<TRUE>\nUSE\tDraw_Reverse\n\nWANT\tequ \t<TRUE>\nUSE\tDraw_Normal\n\nWANT\tequ \t<TRUE>\nUSE\tDraw_Reverse\n\nWANT\tequ \t<USE_SCALING>\nUSE\tDraw_Scale\n\nWANT\tequ \t<USE_SCALING>\nUSE\tDraw_Scale_Reverse\n\nWANT\tequ \t<USE_SCALING>\nUSE\tDraw_Scale\n\nWANT\tequ \t<USE_SCALING>\nUSE\tDraw_Scale_Reverse\n;---------------------------------------------------------------------------\n\n;---------------------------------------------------------------------------\n\tEND\n\n;************************** End of ds_table.asm ****************************\n"
  },
  {
    "path": "WWFLAT32/SHAPE/GETSHAPE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : GETSHAPE.CPP                             *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : April 5, 1992                            *\n *                                                                         *\n *                  Last Update : May 25, 1994   [BR]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Get_Shape_Size -- Fetch the size of the shape in memory.              *\n *   Get_Shape_Uncomp_Size -- gets shape's uncompressed size in bytes\t\t*\n *   Get_Shape_Data -- retrieves a shape's special prefix data\t\t\t\t\t*\n *   Extract_Shape_Count -- returns # of shapes in the given shape block\t*\n *   Extract_Shape -- Gets pointer to shape in given shape block\t\t\t\t*\n *   Get_Shape_Width -- gets shape width in pixels\t\t\t\t\t\t\t\t\t*\n *   Get_Shape_Height -- gets shape height in pixels\t\t\t\t\t\t\t\t*\n *   Set_Shape_Height -- modifies shape's height\t\t\t\t\t\t\t\t\t*\n *   Restore_Shape_Height -- restores a shape to its original height\t\t\t*\n *   Get_Shape_Original_Height -- gets shape's unmodified height\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n/*\n********************************* Includes **********************************\n*/\n#include \"wwstd.h\"\n#include\t\"shape.h\"\n\n\n/***************************************************************************\n * Get_Shape_Size -- Fetch the size of the shape in memory.                *\n *                                                                         *\n * The shape size returned includes both the shape header & its data.\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * INPUT:                                                                  *\n *\tshape\t\tpointer to shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * shape's size in memory\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n * none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint cdecl Get_Shape_Size(VOID const *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\n\t/*\n\t------------------------- Return if NULL pointer -------------------------\n\t*/\n\tif (!shape) \n\t\treturn(0);\n\n\t/*\n\t-------------------------- Returns shape's size --------------------------\n\t*/\n\treturn (shp->ShapeSize);\n\n}\t/* end of Get_Shape_Size */\n\n\n/***************************************************************************\n * Get_Shape_Uncomp_Size -- gets shape's uncompressed size in bytes\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\tshape\t\tpointer to shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\tshape's size in bytes when uncompressed\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n * none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint Get_Shape_Uncomp_Size(VOID const *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\n\treturn (shp->DataLength);\n\n}\t/* end of Get_Shape_Uncomp_Size */\n\n\n/***************************************************************************\n * Get_Shape_Data -- retrieves a shape's special prefix data\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * MAKESHPS.EXE can store special data values along with a shape.  These\t*\n * values are inserted in the shape table >before< the shape's header.\t\t*\n * So, this routine uses the 'data' parameter as a negative index from\t\t*\n * the given shape pointer.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\tshape\t\tpointer to shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * data\t\tindex of WORD data value to get\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * data value\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\tThe shape pointer must be a pointer into a shape table created by\t\t\t*\n * MAKESHPS.EXE; it >cannot< be a pointer to shape returned by Make_Shape!\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nWORD cdecl Get_Shape_Data(VOID const *shape, WORD data)\n{\n\tWORD *word_ptr = (WORD *)shape;\n\tWORD retval;\n\n\tretval = *(word_ptr - (data+1));\n\n\treturn (retval);\n\n}\t/* end of Get_Shape_Data */\n\n\n/***************************************************************************\n * Extract_Shape_Count -- returns # of shapes in the given shape block\t\t*\n *                                                                         *\n * The # of shapes in a shape block is the first WORD in the block, so\t\t*\n * this is the value returned.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * INPUT:                                                                  *\n * buffer\tpointer to shape block, created with MAKESHPS.EXE\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * # shapes in the block\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint cdecl Extract_Shape_Count(VOID const *buffer)\n{\n\tShapeBlock_Type *block = (ShapeBlock_Type *)buffer;\n\n\treturn (block->NumShapes);\n\n}\t/* end of Extract_Shape_Count */\n\n\n/***************************************************************************\n * Extract_Shape -- Gets pointer to shape in given shape block\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n * buffer\tpointer to shape block, created with MAKESHPS.EXE\t\t\t\t\t*\n * shape\t\tindex of shape to get\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * pointer to shape in the shape block\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nVOID * cdecl Extract_Shape(VOID const *buffer, int shape)\n{\n\tShapeBlock_Type *block = (ShapeBlock_Type*) buffer;\n\tint numshapes;\t\t// Number of shapes\n\tlong offset;\t\t\t// Offset of shape data, from start of block\n\tchar *bytebuf = (char*) buffer;\n\n\t/*\n\t----------------------- Return if invalid argument -----------------------\n\t*/\n\tif (!buffer || shape < 0 || shape >= block->NumShapes)\n\t\treturn(NULL);\n\n\toffset = block->Offsets[shape];\n\n\treturn(bytebuf + 2 + offset);\n\n}\t/* end of Extract_Shape */\n\n\n/***************************************************************************\n * Get_Shape_Width -- gets shape width in pixels\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n * shape\t\tpointer to a shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\tshape width in pixels\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n * none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint Get_Shape_Width(VOID const *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\n\treturn (shp->Width);\n\n}\t/* end of Get_Shape_Width */\n\n\n/***************************************************************************\n * Get_Shape_Height -- gets shape height in pixels\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n * shape\t\tpointer to a shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * shape height in pixels\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n * none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint Get_Shape_Height(VOID const *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\n\treturn (shp->Height);\n\n}\t/* end of Get_Shape_Height */\n\n\n/***************************************************************************\n * Set_Shape_Height -- modifies shape's height\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The new height must be shorter than the original height.  This effect\t*\n * chops off the lower portion of the shape, like it's sinking into the\t\t*\n * ground.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * INPUT:                                                                  *\n * shape\t\t\tpointer to a shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * newheight\tnew shape height\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * old shape height\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n * none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint cdecl Set_Shape_Height(VOID const *shape, WORD newheight)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\tWORD oldheight;\n\n\toldheight = shp->Height;\n\tshp->Height = newheight;\n\n\treturn(oldheight);\n\n}\t/* end of Set_Shape_Height */\n\n\n/***************************************************************************\n * Restore_Shape_Height -- restores a shape to its original height\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n * shape\t\tpointer to a shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * old shape height\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint cdecl Restore_Shape_Height(VOID *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\tWORD oldheight;\n\n\toldheight = shp->Height;\n\tshp->Height = shp->OriginalHeight;\n\n\treturn(oldheight);\n\n}\t/* end of Restore_Shape_Height */\n\n\n/***************************************************************************\n * Get_Shape_Original_Height -- gets shape's unmodified height\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\tshape\t\tpointer to a shape\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n * shape's unmodified height\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/09/1992 JLB : Created.                                             *\n *   08/19/1993 SKB : Split drawshp.asm into several modules.              *\n *   05/25/1994 BR : Converted to 32-bit                                   *\n *=========================================================================*/\nint Get_Shape_Original_Height(VOID const *shape)\n{\n\tShape_Type *shp = (Shape_Type *)shape;\n\t\n\treturn (shp->OriginalHeight);\n\n}\t/* end of Get_Shape_Original_Height */\n\n\n/************************* end of getshape.cpp *****************************/\n\n"
  },
  {
    "path": "WWFLAT32/SHAPE/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 25, 1995\t                           *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = shape\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tgetshape.obj \t&\n\tprioinit.obj \t&\n\tdrawshp.obj \t&\n\tds_dn.obj \t&\n\tds_dr.obj \t&\n\tds_ds.obj \t&\n\tds_dsr.obj \t&\n\tds_lrs.obj \t&\n\tds_ls.obj \t&\n\tds_lsrs.obj \t&\n\tds_lss.obj \t&\n\tds_rrs.obj \t&\n\tds_rs.obj \t&\n\tds_rsrs.obj \t&\n\tds_rss.obj \t&\n\tds_table.obj\t&\n\tsetshape.obj\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WWFLAT32/SHAPE/PRIOINIT.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory system.                           *\n *                                                                         *\n *                    File Name : PRIOINIT.CPP                             *\n *                                                                         *\n *                   Programmer : Ian M. Leslie                            *\n *                                                                         *\n *                   Start Date : August 9, 1993                           *\n *                                                                         *\n *                  Last Update : August 9, 1994   [IML]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   INIT_PRIORITY_SYSTEM -- \tSets the buffer addresses for the priority   *\n *   \t\t\t\t\t\t\t\t\tsystem.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"shape.h\"\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * Init_Priority_System -- set the buffer addresses for the priority\t\t   *\n *   \t\t\t\t\t\t\t\tsystem.                       \t\t\t\t\t\t*\n *                                                                         *\n * INPUT:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tmask - pointer\tto priority buffer class\t\t\t\t\t\t\t\t\t\t*\n *\t\tback - pointer to background buffer class\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   08/09/1994 IML : Created.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n *=========================================================================*/\n\nVOID cdecl Init_Priority_System (GraphicBufferClass *mask,\n\t\t\t\t\t\t\t\t\t\t\tGraphicBufferClass *back)\n{\n MaskPage = mask->Get_Buffer();\n BackGroundPage = back->Get_Buffer();\n}\n\n\n/************************** end of prioinit.cpp ****************************/\n"
  },
  {
    "path": "WWFLAT32/SHAPE/SETSHAPE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : WWLIB32                                  *\n;*                                                                         *\n;*                    File Name : SETSHAPE.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : October 26, 1994                         *\n;*                                                                         *\n;*                  Last Update : October 26, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Set_Shape_Buffer -- Sets the shape buffer to the given pointer        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n;******************************** Includes *********************************\nINCLUDE \"shape.inc\"\n\nCODESEG\n\n;***************************************************************************\n;* SET_SHAPE_BUFFER -- Sets the shape buffer to the given pointer          *\n;*                                                                         *\n;* This routine will set the shape buffer to the given value and make sure *\n;* that the system does not try to compress any shapes that will be larger *\n;* than the shape buffer.\t\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tvoid * - pointer to the shape buffer                       *\n;*\t\tint    - size of the buffer which has been passed in\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       VOID *Set_Shape_Bufer(void *buffer, int size);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/26/1994 PWG : Created.                                             *\n;*=========================================================================*\nGLOBAL\tSet_Shape_Buffer:NEAR\n\nPROC\tSet_Shape_Buffer C near \n\tUSES\teax\n\n\tARG\tbuff:DWORD\n\tARG\tsize:DWORD\n\n\tmov\teax,[size]\n\tmov\t[_ShapeBufferSize],eax\n\n\tmov\teax,[buff]\n\tmov\t[_ShapeBuffer],eax\n\tret\n\n\tENDP\tSet_Shape_Buffer\nEND\n\u001a\n"
  },
  {
    "path": "WWFLAT32/SHAPE/SHAPE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WWLIB32                                  *\n *                                                                         *\n *                    File Name : SHAPE.H                                  *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : May 25, 1994                             *\n *                                                                         *\n *                  Last Update : September 14, 1994   [IML]               *\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef SHAPE_H\n#define SHAPE_H\n\n#ifndef GBUFFER_H\n#include \"gbuffer.h\"\n#endif\n/*\n*********************************** Types ***********************************\n*/\n/*\n--------------------------- Shape creation flags ----------------------------\n*/\ntypedef enum {\n\tMAKESHAPE_NORMAL\t = 0x0000,\t// 256-color compressed shape\n\tMAKESHAPE_COMPACT  = 0x0001,\t// 16-color shape (with built-in color table)\n\tMAKESHAPE_NOCOMP\t = 0x0002,\t// Uncompressed shape\n\tMAKESHAPE_VARIABLE =\t0x0004\t// <16-color shape\n} MakeShapeFlags_Type;\n\n/*---------------------------------------------------------------------------\nShape drawing flags:\n- The low byte is for coordinate transformations.\n- The high byte is for drawing effects.\n---------------------------------------------------------------------------*/\ntypedef enum {\n\tSHAPE_NORMAL \t\t\t= 0x0000,\t\t// Standard shape\n\tSHAPE_HORZ_REV \t\t= 0x0001,\t\t// Flipped horizontally\n\tSHAPE_VERT_REV \t\t= 0x0002,\t\t// Flipped vertically\n\tSHAPE_SCALING \t\t\t= 0x0004,\t\t// Scaled (WORD scale_x, WORD scale_y)\n\tSHAPE_VIEWPORT_REL \t= 0x0010,\t\t// Coords are window-relative \n\tSHAPE_WIN_REL \t\t\t= 0x0010,\t\t// Coordinates are window relative instead of absolute.\n\tSHAPE_CENTER \t\t\t= 0x0020,\t\t// Coords are based on shape's center pt\n\tSHAPE_FADING \t\t\t= 0x0100,\t\t// Fading effect (VOID * fading_table, \n\t\t\t\t\t\t\t\t\t\t\t\t\t//  WORD fading_num)\n\tSHAPE_PREDATOR \t\t= 0x0200,\t\t// Transparent warping effect\n\tSHAPE_COMPACT \t\t\t= 0x0400,\t\t// Never use this bit \n\tSHAPE_PRIORITY \t\t= 0x0800,\t\t// Use priority system when drawing\n\tSHAPE_GHOST\t\t\t\t= 0x1000,\t\t// Shape is drawn ghosted\n\tSHAPE_SHADOW\t\t\t= 0x2000,\n\tSHAPE_PARTIAL  \t\t= 0x4000,\n\tSHAPE_COLOR \t\t\t= 0x8000\t\t\t// Remap the shape's colors \n\t\t\t\t\t\t\t\t\t\t\t\t\t//  (VOID * color_table)\n} ShapeFlags_Type;\n\n/*\n------------------------------- Shape header --------------------------------\n*/\ntypedef struct {\n\tUWORD\t\tShapeType;\t\t\t// 0 = normal, 1 = 16 colors, \n\t\t\t\t\t\t\t\t\t\t//  2 = uncompressed, 4 = \t<16 colors\n\tUBYTE\t\tHeight;\t\t\t\t// Height of the shape in scan lines\n\tUWORD\t\tWidth;\t\t\t\t// Width of the shape in bytes\n\tUBYTE\t\tOriginalHeight;\t// Original height of shape in scan lines\n\tUWORD\t\tShapeSize;\t\t\t// Size of the shape, including header\n\tUWORD\t\tDataLength;\t\t\t// Size of the uncompressed shape (just data)\n\tUBYTE\t\tColortable[16];\t// Optional color table for compact shape\n} Shape_Type;\n\n/*\n------------------------------- Shape block ---------------------------------\n*/\ntypedef struct {\n\tUWORD\t\tNumShapes;\t\t\t// number of shapes in the block\n\tLONG\t\tOffsets[];\t\t\t// array of offsets to shape data\n\t\t\t\t\t\t\t\t\t\t//  (offsets within the shape block, with\n\t\t\t\t\t\t\t\t\t\t//  0 being the first offset value, not the\n\t\t\t\t\t\t\t\t\t\t//  start of the shape block)\n} ShapeBlock_Type;\n\n\n/*\n******************************** Prototypes *********************************\n*/\n\n/*\n-------------------------------- prioinit.c ---------------------------------\n*/\n\nextern \"C\" {\nextern VOID  *MaskPage;\nextern VOID  *BackGroundPage;\nextern LONG  _ShapeBufferSize;\nextern BYTE  *_ShapeBuffer;\n}\n\n\nVOID cdecl Init_Priority_System (GraphicBufferClass *mask,\n\t\t\t\t\t\t\t\t\t\t\tGraphicBufferClass *back);\n\n\n/*\n-------------------------------- drawshp.asm --------------------------------\n*/\n\nextern \"C\" {\nWORD Draw_Shape(GraphicViewPortClass *gvp, VOID const *shape, LONG x, LONG y, LONG flags, ...);\n}\n\n/*\n---------------------------------- shape.c ----------------------------------\n*/\nshort cdecl Get_Shape_Data(VOID const *shape, WORD data);\nint cdecl Extract_Shape_Count(VOID const *buffer);\nvoid * cdecl Extract_Shape(VOID const *buffer, int shape);\nint cdecl Restore_Shape_Height(VOID *shape);\nint cdecl Set_Shape_Height(VOID const *shape, WORD newheight);\n\nextern \"C\" {\nint Get_Shape_Width(VOID const *shape);\nint Get_Shape_Height(VOID const *shape);\nint Get_Shape_Original_Height(VOID const *shape);\nint Get_Shape_Uncomp_Size(VOID const *shape);\n}\n\n\n/*\n------------------------------- setshape.asm --------------------------------\n*/\nextern \"C\" {\nVOID Set_Shape_Buffer(void const *buffer, int size);\n}\n/*\n------------------------------- shapeinf.asm --------------------------------\n*/\nWORD cdecl Get_Shape_Flags(VOID const *shape);\nint  cdecl Get_Shape_Size(VOID const *shape);\nint  cdecl Get_Shape_Scaled_Width(VOID const *shape, WORD scale);\nint  cdecl Get_Shape_Scaled_Height(VOID const *shape, WORD scale);\n\n#endif // SHAPE_H\n\n/****************************** End of shape.h *****************************/\n\u001a\n\u001a\n"
  },
  {
    "path": "WWFLAT32/SHAPE/SHAPE.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : WWLIB32                                  *\n;*                                                                         *\n;*                    File Name : SHAPE.INC                                *\n;*                                                                         *\n;*                   Programmer : Scott Bowen\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : May 25, 1994                             *\n;*                                                                         *\n;*                  Last Update : September 14, 1994   [IML]               *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;****************************** Equates ************************************\n;\n\n\n\n\n\n\n;............................ Shape Types ..................................\n;\nTRUE\tequ\t1\t\t\t; Boolean 'true' value\nFALSE\tequ\t0\t\t\t; Boolean 'false' value\n\nMAKESHAPE_NORMAL\t\tEQU\t0\t; 256-color compressed shape\nMAKESHAPE_COMPACT\t\tEQU\t1\t; 16-color shape (built-in color table)\nMAKESHAPE_NOCOMP\t\tEQU\t2\t; non-wwcomped shape\nMAKESHAPE_VARIABLE\tEQU\t4\t; <16-color shape with variable #\n\t\t\t\t\t; of colors (ColorTable[0] = # of colors)\n; old names:\n;COLOR_SHAPE\t\tEQU\t1\t; flag which determines a color shape\n;NORM_SHAPE\t\t\tEQU\t2\t; flag that indicates non wwcomped shp\n;NORM_SHAPE_16\t\tEQU\t4\t; flag that tells us if we have a variable sized table\n\t\t\t\t\t;  variable sized table\n;\n;...........................................................................\n; Drawing flags:\n; The low byte is for coordinate transformations.\n; The high byte is for drawing effects.\n;...........................................................................\n;\nSHAPE_NORMAL\t\t\tEQU\t0000h\t; no options; just a copy\nSHAPE_HORZ_REV\t\t\tEQU\t0001h\t; reverse horizontally\nSHAPE_VERT_REV\t\t\tEQU\t0002h\t; reverse vertically\nSHAPE_SCALING\t\t\tEQU\t0004h\t; scale\nSHAPE_VIEWPORT_REL\tEQU\t0010h\t; viewport-relative coordinates\nSHAPE_CENTER\t\t\tEQU\t0020h\t; use centered coordinates\nSHAPE_FADING\t\t\tEQU\t0100h\t; fading effect shape\nSHAPE_PREDATOR\t\t\tEQU\t0200h\t; predator effect shape\nSHAPE_COMPACT\t\t\tEQU\t0400h\t; shape is in 16 colors\nSHAPE_PRIORITY\t\t\tEQU\t0800h\t; priority draw shape\nSHAPE_GHOST\t\t\t\tEQU\t1000h\t; ghosting effect\nSHAPE_SHADOW\t\t\tEQU\t2000h\t; shadow effect\nSHAPE_PARTIAL\t\t\tEQU\t4000h\t; partial predator effect\nSHAPE_COLOR\t\t\t\tEQU\t8000h\t; use alternative color table effect\n\nSHAPE_EFFECTS\t\t\tEQU    03F00h\t; shape effect flags \n\n;\n;.......................... Shadow Effect ..................................\n;\nSHADOW_COL\t\tEQU\t00FFh\t; magic number for shadows\n\n;......................... Priority System .................................\n;\nCLEAR_UNUSED_BITS  \tEQU\t0007h\t; and with 0000-0111 to clear \n\t\t\t\t\t;  non-walkable high bit and\n\t\t\t\t\t;  scaling id bits\nNON_WALKABLE_BIT  \tEQU\t0080h\t; and with 1000-0000 to clear all \n\t\t\t\t\t;  but non-walkable bit\n;\n;......................... Predator Effect .................................\n;\nPRED_MASK\t\tEQU\t0007h\t; mask used for predator pixel puts\n\n;---------------------------------------------------------------------------\n; This table is a list of the local stack variables in the function\n; Draw_Shape.  Many other functions in other modules access these variables\n; on the stack.  Since the BP is not changed when these other functions are\n; called by Draw_Shape (possibly indirectly), they can also access these\n; stack varibles.  When adding or removing from the table, one must be very\n; careful to change the offsets.  \n;---------------------------------------------------------------------------\n;.......................... proc addresses .................................\nLSkipRout\tEQU DWORD PTR ebp - 04h\t\t;DWORD  pointer to the skip routine\nRSkipRout\tEQU DWORD PTR ebp - 08h\t\t;DWORD  pointer to the skip routine\nDrawRout\tEQU DWORD PTR ebp - 0Ch\t\t\t;DWORD  pointer to the draw routine\n;........................ optional arguments ...............................\nColorTable\tEQU DWORD PTR ebp - 10h\t\t;DWORD\tptr to the shapes color table\nFadingTable\tEQU DWORD PTR ebp - 14h\t\t;DWORD  ptr to the fading table\n\nFadingNum\tEQU DWORD PTR ebp - 18h\t\t;DWORD  number of times to fade\nIsTranslucent\tEQU DWORD PTR ebp - 1Ch\t;DWORD\tptr to is_translucent table\nTranslucent\tEQU DWORD PTR ebp - 20h\t\t;DWORD\tptr to actual translucent tbl\nPriLevel\tEQU BYTE  PTR ebp - 24h\t\t\t;BYTE\tpriority level of the object \nScaleX\t\tEQU DWORD PTR ebp - 28h\t\t;DWORD  the x increment to scale by\nScaleY\t\tEQU DWORD PTR ebp - 2Ch\t\t;DWORD  the y increment to scale by\nShadowingTable\tEQU DWORD PTR ebp - 30h\t;DWORD\tptr to the shadowing table\n;........................ Shape header values ..............................\nShapeType\tEQU DWORD PTR ebp - 34h \t;DWORD\tshape type\nShapeWidth\tEQU DWORD PTR ebp - 38h \t;DWORD\tshape's unscaled width\nShapeHeight\tEQU DWORD PTR ebp - 3Ch \t;DWORD\tshape's unscaled height\nUncompDataLen\tEQU DWORD PTR ebp - 40h ;DWORD\tuncompressed data length\nShapeData\tEQU DWORD PTR ebp - 44h \t;DWORD\tpointer to shape data\n;...................... Scaled shape dimensions ............................\nScaledWidth\tEQU DWORD PTR ebp - 48h \t;DWORD\tshape's scaled width\nScaledHeight\tEQU DWORD PTR ebp - 4Ch ;DWORD\tshape's scaled height\n;...................... Pixel clipping variables ...........................\nLeftClipPixels\tEQU DWORD PTR ebp - 50h ;DWORD\t# left-clipped pixels\nRightClipPixels\tEQU DWORD PTR ebp - 54h ;DWORD\t# right-clipped pixels\nTopClipPixels\tEQU DWORD PTR ebp - 58h ;DWORD\t# top-clipped pixels\nBotClipPixels\tEQU DWORD PTR ebp - 5Ch ;DWORD\t# bottom-clipped pixels\nPixelWidth\tEQU DWORD PTR ebp - 60h \t;DWORD\tdrawable area in pixels\nPixelHeight\tEQU DWORD PTR ebp - 64h \t;DWORD\tdrawable area in pixels\n;......................... Drawing variables ...............................\nNumColors\tEQU DWORD PTR ebp - 68h ;DWORD\t# colors for 16-color shapes\nStartDraw\tEQU DWORD PTR ebp - 6Ch ;DWORD\toffset of drawing start pos\nNextLine\tEQU DWORD PTR ebp - 70h ;DWORD\toffset of next drawing line\nLeftClipBytes\tEQU DWORD PTR ebp - 74h ;DWORD\t# left-clipped bytes\nXTotal\t\tEQU DWORD PTR ebp - 78h ;DWORD\taccumulated x-pixels\nXTotalInit\tEQU DWORD PTR ebp - 7Ch ;DWORD\tinitial roundoff for XTotal\nYTotal\t\tEQU DWORD PTR ebp - 80h ;DWORD\taccumulated y-pixels\nHeightCount\tEQU DWORD PTR ebp - 84h ;DWORD\tht counter for drawing lines\nLineStart\tEQU DWORD PTR ebp - 88h ;DWORD\taddress of start of line\nWidthCount\tEQU DWORD PTR ebp - 8Ch ;DWORD\tcounts down # bytes skipped\nStashReg\tEQU DWORD PTR ebp - 90h \t;DWORD\ttemp variable for draw routines\nMaskAdjust\tEQU DWORD PTR ebp - 94h ;DWORD  priority buffer offset\nBackAdjust\tEQU DWORD PTR ebp - 98h ;DWORD  background buffer offset\nStashECX\tEQU DWORD PTR ebp - 9Ch \t;DWORD  temp variable for ECX register\nStashEDX\tEQU DWORD PTR ebp -0A0h \t;DWORD  temp variable for EDX register\n\nLocal_Size\tEQU 00A4h\t\t; Amt of data on stack: 4+last offset\n\n;****************************** Declarations *******************************\n;---------------------------------------------------------------------------\n; Global variables used by the shape routines, defined in drawshp.asm\n;---------------------------------------------------------------------------\nGLOBAL _ShapeBuffer:DWORD\nGLOBAL _ShapeBufferSize:DWORD\nGLOBAL _MaskPage:DWORD\nGLOBAL _BackGroundPage:DWORD\nGLOBAL PredCount:DWORD\nGLOBAL PredTable:BYTE\nGLOBAL PredValue:DWORD\nGLOBAL PartialPred:DWORD\nGLOBAL PartialCount:DWORD\nGLOBAL Flags:DWORD\n\n;---------------------------------------------------------------------------\n; External tables that are defined in ds_table.asm.\n;---------------------------------------------------------------------------\nGLOBAL LSkipTable:DWORD\nGLOBAL RSkipTable:DWORD\nGLOBAL DrawTable:DWORD \n\n;------------------------------------------------------------------------------\n; Public functions, declared in the order they appear in the function tables.\n;--------------------------------------------------------------------------------\nGLOBAL\tC Not_Supported:NEAR\n;\tLSkipTable:\nGLOBAL Left_Skip:NEAR\t\t\t\t\t\t; ds_ls\nGLOBAL Left_Reverse_Skip:NEAR\t\t\t\t; ds_lrs\nGLOBAL Left_Skip:NEAR\t\t\t\t\t\t; ds_ls\nGLOBAL Left_Reverse_Skip:NEAR\t\t\t\t; ds_lrs\nGLOBAL Left_Scale_Skip:NEAR\t\t\t\t; ds_lss\nGLOBAL Left_Scale_Reverse_Skip:NEAR\t\t; ds_lsrs\nGLOBAL Left_Scale_Skip:NEAR\t\t\t\t; ds_lss\nGLOBAL Left_Scale_Reverse_Skip:NEAR\t\t; ds_lsrs\n\n;\tRSkipTable:\nGLOBAL Right_Skip:NEAR\t\t\t\t\t   ; ds_rs\nGLOBAL Right_Reverse_Skip:NEAR\t\t\t; ds_rrs\nGLOBAL Right_Skip:NEAR\t\t\t\t\t   ; ds_rs\nGLOBAL Right_Reverse_Skip:NEAR\t\t\t; ds_rrs\nGLOBAL Right_Scale_Skip:NEAR\t\t\t\t; ds_rss\nGLOBAL Right_Scale_Reverse_Skip:NEAR\t; ds_rsrs\nGLOBAL Right_Scale_Skip:NEAR\t\t\t\t; ds_rss\nGLOBAL Right_Scale_Reverse_Skip:NEAR\t; ds_rsrs\n\n;\tDrawTable:\nGLOBAL Draw_Normal:NEAR\t\t\t\t\t; ds_dn\nGLOBAL Draw_Reverse:NEAR\t\t\t\t; ds_dr\nGLOBAL Draw_Normal:NEAR\t\t\t\t\t; ds_dn\nGLOBAL Draw_Reverse:NEAR\t\t\t\t; ds_dr\nGLOBAL Draw_Scale:NEAR\t\t\t\t\t; ds_ds\nGLOBAL Draw_Scale_Reverse:NEAR\t\t; ds_dsr\nGLOBAL Draw_Scale:NEAR\t\t\t\t\t; ds_ds\nGLOBAL Draw_Scale_Reverse:NEAR\t\t; ds_dsr\n\n\n;************************* End of shape.inc ********************************\n\u001a\n"
  },
  {
    "path": "WWFLAT32/SRCDEBUG/ALLOC.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : ALLOC.CPP                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : February 1, 1992                         *\n *                                                                         *\n *                  Last Update : March 9, 1995 [JLB]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Alloc -- Allocates system RAM.                                        *\n *   Ram_Free -- Determines the largest free chunk of RAM.                 *\n *   Free -- Free an Alloc'ed block of RAM.                                *\n *   Resize_Alloc -- Change the size of an allocated block.                *\n *   Heap_Size -- Size of the heap we have.                                *\n *   Total_Ram_Free -- Total amount of free RAM.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <malloc.h>\n#include <string.h>\n#include <stdlib.h>\n#include <dos.h>\n#include <bios.h>\n#include <stdio.h>\n\n\n#ifndef WWMEM_H\n#include \"wwmem.h\"\n#endif\n\n\nextern \"C\" unsigned long Largest_Mem_Block ( void ) ;\n\n//\n// use double-word alignment for allocs\n//\n#define LONG_ALIGNMENT\t\t\t1\n\n/*\n** Define the equates necessary to call a DPMI interrupt.\n*/\n#define\tDPMI_INT\t\t\t\t\t\t\t\t\t0x0031\n#define\tDPMI_LOCK_MEM\t\t\t\t\t\t\t0x0600\n#define\tDPMI_UNLOCK_MEM\t\t\t\t\t\t0x0601\n#define  LOGGING\t\t\t\t\t\t\t\t\tFALSE\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\nunsigned long MinRam=0L;\t\t// Record of least memory at worst case.\nunsigned long MaxRam=0L;\t\t// Record of total allocated at worst case.\nstatic unsigned long TotalRam = 0L;\nstatic unsigned long Memory_Calls = 0L;\nstatic unsigned long RequestedSystemRam = 16*1024*1024;\nstatic unsigned long LargestRamBlock = 0L;\n\t\t\nvoid (*Memory_Error)(void) = NULL;\nvoid (*Memory_Error_Exit)(char *string) = NULL;\n\n/***************************************************************************\n * DPMI_LOCK -- handles locking a block of DPMI memory                     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\n#include\"mono.h\"\nvoid DPMI_Lock(VOID const *ptr, long const size)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\n\t/*\n\t** Lock memory\n\t** AX = 0x600\n\t** BX:CX = starting linear address of memory to lock\n\t** SI:DI = size of region to lock (in bytes)\n\t** - If Failure, carry flag is set.\n\t*/\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_LOCK_MEM;\n\tregs.x.ebx = ((long)ptr & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000ffff);\n\tregs.x.esi = ((long)size & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n//\tif (regs.x.cflag) {\n//\t}\n#if(0)\n\tchar *temp = (char *)ptr;\n\tchar hold;\n\tfor (int lp = 0; lp < size; lp += 2048) {\n\t\thold = *temp;\n\t\ttemp += 2048;\n\t}\n#endif\n\n}\n\n/***************************************************************************\n * DPMI_UNLOCK -- Handles unlocking a locked block of DPMI                 *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid DPMI_Unlock(void const *ptr, long const size)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\n\t/*\n\t** Unlock the memory\n\t*/\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_UNLOCK_MEM;\t\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = ((long)ptr & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)ptr & 0x0000ffff);\n\tregs.x.esi = ((long)size & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)size & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n//\tif (regs.x.cflag) {\n//\t}\n\n}\n\n/***************************************************************************\n * Alloc -- Allocates system RAM.                                          *\n *                                                                         *\n *    This is the basic RAM allocation function.  It is used for all       *\n *    memory allocations needed by the system or the main program.         *\n *                                                                         *\n * INPUT:   bytes_to_alloc -- LONG value of the number of bytes to alloc.  *\n *                                                                         *\n *          flags          -- Memory allocation control flags.             *\n *             MEM_NORMAL: No special flags.                               *\n *             MEM_CLEAR:  Zero out memory block.                        \t*\n *             MEM_NEW:\t\tCalled by a new.                                *\n *                                                                         *\n * OUTPUT:  Returns with pointer to allocated block.  If NULL was returned *\n *          it indicates a failure to allocate.  Note: NULL will never be  *\n *          returned if the standard library allocation error routine is   *\n *          used.                                                          *\n *                                                                         *\n * WARNINGS:   If you replace the standard memory allocation error routine *\n *             and make it so that Alloc CAN return with a NULL, be sure   *\n *             and check for this in your code.                            *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Documented.                                          *\n *   08/09/1993 JLB : Updated with EMS memory support.                     *\n *   04/28/1994 JAW : Updated to 32bit Protected mode.                     *\n *   03/09/1995 JLB : Fixed                                                * \n *=========================================================================*/\nvoid *Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags)\n{\n\tunion REGS\t\tregs ;\n\tstruct SREGS \tsregs ;\n\tunsigned char *retval=NULL;\t// Pointer to allocated block.\n\tunsigned long\toriginal_size;\t// Original allocation size.\n\tunsigned long\tbytesfree;\t\t// Number of free bytes.\n\tlong \t\t\t\t*longptr=NULL;\t// Pointer used to store selector\n\tstatic unsigned char _allocinit=0;\n\n\n\t//\n\t// Init memory system by finding largest block to alloc\n\t// then allocate it to get one large heap and free it.\n\t// There may be more memory available from DPMI but we only are\n\t// for now allocating and freeing the first largest block.\n\t//\n\tif ( !_allocinit ) {\n\t\tunsigned long largestblock = Largest_Mem_Block();\n\t\tlargestblock -= 1024;\t\t\t\t// subtract for heap header and misc\n\t\tlargestblock &= 0xffff0000;\t\t// forcing to 64K boundary\n\n\t\tif ( largestblock ) {\n\t\t\tLargestRamBlock = MIN( largestblock, RequestedSystemRam );\n\t\t\tunsigned char *lptr = (unsigned char *)malloc( LargestRamBlock );\n\t\t\tif ( lptr ) {\n\t\t\t\tfree( (void *)lptr );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tInitialize the total ram available value.\n\t\t*/\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\n\t\t_allocinit = 1;\n\t}\n\n\t/* \n\t** Save the original allocated space size so that we can clear the\n\t** exact amount of RAM if they specified MEM_CLEAR.\n\t*/\n\toriginal_size = bytes_to_alloc;\n\n\t/*\n\t** Reserve one byte for the header of the memory we allocated.\n\t** We will store the flags variable there for later use.\n\t*/\n#if (LONG_ALIGNMENT)\n\tbytes_to_alloc += (flags & MEM_LOCK) ? 8 : 4;\n#else\n\tbytes_to_alloc += (flags & MEM_LOCK) ? 5 : 1;\n#endif\n\n\n\t// Try to allocate the memory out of the protected mode memory\n\t// chain if we did not require a real mode allocation.  If this \n\t// fails we will have to try to allocate it out of real mode memory.\n\t// Real mode memory is a last resort because some types of applications\n\t// require real mode memory.\n\tif (!(flags & MEM_REAL)) {\n\t\tretval = (unsigned char*)malloc(bytes_to_alloc);\n\t}\n\n\t// Try to allocate the memory out of the real mode memory using DPMI\n\t// service 0x100.  Note that retval will be null if we are requesting\n\t// real mode memory so that we do not have to explicitly check for the\n\t// real mode flag.  Remember we need to reserve room for the dos \n\t// selector value at the beginning of our allocated block so rather than\n\t// adding fifteen and rounding, we need to add 19 and round.\n\tif (!retval) {\n\t\tflags = (MemoryFlagType)(flags | MEM_REAL);\n\t\tregs.x.eax = 0x100;\n\t\tregs.x.ebx = (bytes_to_alloc + 19) >> 4;\n\t\tif (regs.x.ebx & 0xFFFF0000) {\n\t\t\tretval = NULL;\n\t\t} else {\n\t\t\tsegread ( & sregs ) ;\n\t\t\tint386x ( 0x31 , & regs, & regs , & sregs\t) ;\n\t\t\tif (regs.x.cflag)\n\t\t\t\tretval = NULL;\n\t\t\telse {\n#if (LONG_ALIGNMENT)\n\t\t\t\tlongptr\t\t= (long *)(((regs.x.eax & 0xFFFF) << 4)+ 4);\n#else\n\t\t\t\tlongptr\t\t= (long *)(((regs.x.eax & 0xFFFF) << 4)+ 1);\n#endif\n\t\t\t\t*longptr++\t= regs.x.edx & 0xFFFF;\n\t\t\t\tretval\t\t= (unsigned char *)longptr;\n\t\t\t}\n\t\t}\n\t}\n\n\t// If the alloc failed then we need to signify a memory error.\n\tif (retval == NULL) {\n\t\tif (Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\t\t\n\t}\n\n\t// If the memory needs to be DPMI locked then we should store the\n\t// original size in the header before we store the flags.\n\tif (flags & MEM_LOCK) {\n\t\tlongptr\t\t= (long *)retval;\n\t\t*longptr++\t= original_size;\n\t\tretval\t\t= (unsigned char *)longptr;\n\t}\n\n\n\t// Now that we know the alloc was sucessful (and for an extra byte\n\t// more than the user wanted) we need to stick in the memory flags.\n#if (LONG_ALIGNMENT)\n\tif ( !(flags & (MEM_LOCK|MEM_REAL)) ) {\n\t\t//\n\t\t// WARNING!!!!!!!!!!\n\t\t// USE this only with the WATCOM malloc ALLOCATION!!!!!!!!!\n\t\t// it reads the actual block size before the ptr returned.\n\t\t// then eors and uses the upper word for a validation later on free.\n\t\t//\n\t\tlongptr = (long *)retval;\n\t\t*longptr = ((*(longptr - 1)) ^ 0xffffffff) & 0xffff0000;\n\t\t*retval++ \t\t= flags;\n\t\t*retval++ \t\t= (unsigned char)(flags ^ 0xff);\n\t\tretval += 2;\n\t}\n\telse {\n\t\t*retval++ \t\t= flags;\n\t\t*retval++ \t\t= (unsigned char)(flags ^ 0xff);\n\t\t*retval++ \t\t= 0;\n\t\t*retval++ \t\t= 0;\n\t}\n#else\n\t*retval++ \t\t= (unsigned char)(flags | (((flags ^ 0x07) & 0x07) << 5));\n#endif\n\n\t// If the memory needed to be DPMI locked then set it up so it\n\t// is locked.\n\tif (flags & MEM_LOCK) {\n\t\tDPMI_Lock(retval, original_size);\n\t}\n\n\t/* Clear the space if they wanted it clear */\n\n\tif (flags & MEM_CLEAR) {\n\t\tunsigned char\t*ptr;\t\t// Working memory block pointer.\n\n\t\tptr = retval;\n\t\tmemset(ptr, '\\0', original_size);\n\t}\n\n\tbytesfree = Total_Ram_Free(MEM_NORMAL);\n\tif (bytesfree < MinRam) {\n\t\tMinRam = bytesfree;\n\t}\n\tif (TotalRam-bytesfree > MaxRam) {\n\t\tMaxRam = TotalRam-bytesfree;\n\t}\n\n\tMemory_Calls++;\n\n#if(LOGGING)\n\tint val = _heapchk();\n\n\tFILE *file = fopen(\"mem.txt\",\"at\");\n\tfprintf(file, \"%P Alloc size = %d, Actual Size = %d, flags = %d, heap = %d\\n\", \n\t\t\t\t\t\tretval,\n\t\t\t\t\t\toriginal_size,\n\t\t\t\t\t\tbytes_to_alloc,\n\t\t\t\t\t\tflags,\n\t\t\t\t\t\tval);\n\tfclose(file);\n#endif\n\n\treturn(retval);\n}\n\n\n/***************************************************************************\n * Free -- Free an Alloc'ed block of RAM.                                  *\n *                                                                         *\n * FUNCTION:                                                               *\n *                                                                         *\n * INPUT:       A pointer to a block of RAM from Alloc.                    *\n *                                                                         *\n * OUTPUT:      None.                                                      *\n *                                                                         *\n * WARNINGS:    Don't use this for an Alloc_Block'ed RAM block.            *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/25/1990     : Created.                                             *\n ***************************************************************************/\nvoid Free(void const *pointer)\n{\n\tunion REGS\t\tregs ;\n\tstruct SREGS \tsregs ;\n\n\tvoid const *original = pointer;\n\tchar string[80];\n\n\tif (pointer) {\n\t\t/*\n\t\t** Get a pointer to the flags that we stored off.\n\t\t*/\n#if (LONG_ALIGNMENT)\n\t\tunsigned char *byteptr\t= ((unsigned char *)pointer) - 4;\n\n\t\t//\n\t\t// validate the flags with and eor of the flags\n\t\t//\n\t\tif ( *byteptr != ((*(byteptr + 1)) ^ 0xff) ) {\n\t\t\tif (Memory_Error_Exit != NULL) {\n\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n\t\t\t\tMemory_Error_Exit( string );\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif ( !(*byteptr & (MEM_LOCK|MEM_REAL)) ) {\n\t\t\t\tunsigned short *wordptr = (unsigned short *)(byteptr - 2);\n\n\t\t\t\t//\n\t\t\t\t// WARNING!!!!!!!!!!\n\t\t\t\t// USE this only with the WATCOM malloc ALLOCATION!!!!!!!!!\n\t\t\t\t// it reads the actual block size before the ptr to be freed.\n\t\t\t\t// then compares with the EOR to the value stored during allocation.\n\t\t\t\t//\n\t\t\t\tif ( *wordptr != ((*(wordptr + 2)) ^ 0xffff) ) {\n\t\t\t\t\tif (Memory_Error_Exit != NULL) {\n\t\t\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n\t\t\t\t\t\tMemory_Error_Exit( string );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( *(byteptr + 2) || *(byteptr + 3) ) {\n\t\t\t\tif (Memory_Error_Exit != NULL) {\n\t\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n\t\t\t\t\tMemory_Error_Exit( string );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n//\t\tif ( *byteptr != (*(byteptr + 1) ^ 0xff) ||\n//\t\t\t*(byteptr + 2) || *(byteptr + 3) ) {\n//\t\t\tif (Memory_Error_Exit != NULL) {\n//\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n//\t\t\t\tMemory_Error_Exit( string );\n//\t\t\t}\n//\t\t}\n#else\n\t\tunsigned char *byteptr\t= ((unsigned char *)pointer) - 1;\n\n\t\tif ( (*byteptr & 0xe0) != (((*byteptr ^ 0x07) & 0x07) << 5) ) {\n\t\t\tif (Memory_Error_Exit != NULL) {\n\t\t\t\tsprintf( string, \"Error freeing pointer %p.  Header invalid!!!\\n\", pointer );\n\t\t\t\tMemory_Error_Exit( string );\n\t\t\t}\n\t\t}\n#endif\n\n\t\t/*\n\t\t** Check to see if this was locked me and if it was unlock it.\n\t\t*/\n\t\tif (*byteptr & MEM_LOCK) {\n\t\t\tlong *longptr = ((long *)byteptr) - 1;\n\t\t\tDPMI_Unlock(pointer, *longptr);\n\t\t\tpointer = (void *)longptr;\n\t\t} else\n\t\t\tpointer = (void *)byteptr;\n\n#if(LOGGING)\t\t\n\t\tint val = _heapchk();\n\t\tFILE *file = fopen(\"mem.txt\",\"at\");\n\t\tfprintf(file, \"%P Free flags = %d, Heap = %d\\n\", \n\t\t\t\t\t\t\toriginal,\n\t\t\t\t\t\t\t*byteptr, \n\t\t\t\t\t\t\tval);\n\t\tfclose(file);\n#endif\n\n\t\t// If the pointer is a real mode pointer than it will point to the\n\t\t// first megabyte of system memory.  If it does than we need to \n\t\t// use DPMI to free it.\n\t\tif (*byteptr & MEM_REAL) {\n\t\t\tregs.x.eax\t= 0x101;\n\t\t\tregs.x.edx\t= *(((long *)pointer) - 1);\n\t\t\tsegread ( & sregs ) ;\n\t\t\tint386x(0x31, &regs, &regs, &sregs);\n\t\t} else {\n\t\t\tfree((void *)pointer);\n\t\t}\n\t\tMemory_Calls--;\n\t}\n}\n\n\n/***************************************************************************\n * Resize_Alloc -- Change the size of an allocated block.                  *\n *                                                                         *\n *    This routine will take a previously allocated block and change its   *\n *    size without unnecessarily altering its contents.                    *\n *                                                                         *\n * INPUT:   pointer  -- Pointer to the original memory allocation.         *\n *                                                                         *\n *          new_size -- Size in bytes that it will be converted to.        *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the new allocation.                  *\n *                                                                         *\n * WARNINGS:   ???                                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/01/1992 JLB : Commented.                                           *\n *=========================================================================*/\nvoid *Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes)\n{\n\n\tunsigned long *temp;\n//\tunsigned long diff, flags;\n\n\ttemp = (unsigned long*)original_ptr;\n\n\t/* ReAlloc the space */\n\ttemp = (unsigned long *)realloc(temp, new_size_in_bytes);\n\tif (temp == NULL) {\n\t\tif (Memory_Error != NULL)\n\t\t\tMemory_Error();\n\t\treturn NULL;\t\t\n\t}\t\t\t   \n\n\treturn(temp);\n}\n\n\n/***************************************************************************\n * Ram_Free -- Determines the largest free chunk of RAM.                   *\n *                                                                         *\n *    Use this routine to determine the largest free chunk of available    *\n *    RAM for allocation.  It also performs a check of the memory chain.   *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  Returns with the size of the largest free chunk of RAM.        *\n *                                                                         *\n * WARNINGS:   This does not return the TOTAL memory free, only the        *\n *             largest free chunk.                                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/03/1991 JLB : Commented.                                           *\n *=========================================================================*/\nlong Ram_Free(MemoryFlagType)\n{\n\treturn(_memmax());\n//\treturn Largest_Mem_Block();\n}\n\n\n/***************************************************************************\n * Heap_Size -- Size of the heap we have.                                  *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Heap_Size(MemoryFlagType )\n{\n\tif (!TotalRam) {\n\t\tTotalRam = Total_Ram_Free(MEM_NORMAL);\n\t}\n\treturn(TotalRam);\n}\n\n\n/***************************************************************************\n * Total_Ram_Free -- Total amount of free RAM.                             *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *   03/09/1995 JLB : Uses prerecorded heap size maximum.                  * \n *=========================================================================*/\nlong Total_Ram_Free(MemoryFlagType )\n{\n\treturn(_memavl());\n//\treturn Largest_Mem_Block () ;\n}\n\n"
  },
  {
    "path": "WWFLAT32/SRCDEBUG/KEYBOARD.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : KEYBOARD.ASM                             *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 15, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Get_RM_Timer_Address -- Return address of real mode code for copy.    *\n;*   Get_RM_Keyboard_Size -- return size of real mode timer code.          *\n;*   Check_Key -- checks queue for key (make)                              *\n;*   Check_Key_Num -- Checks if key in queue, return key num               *\n;*   Get_Key_Num -- Returns the next key num in ax                         *\n;*   KN_To_KA -- Translates a key num to an ASCII key                      *\n;*   Low_Get_Key -- low level get key returns key num and bits             *\n;*   Convert_Num_To_ASCII -- Assembly routine converts keynum to ASCII key *\n;*   KeyNum_Translate -- Performs a lowlevel xlate to a keycode            *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\n;*\tKeyboard driver -- 80386 Protected Mode Assembly portion\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   \n;***************************************************************************\n;\n; ----------------------------------------------------------------\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\n;WARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Make some general equates for easy compatability\n;---------------------------------------------------------------------------\nPROT_INT_ENABLE\tEQU\t1\t\t; if false protected int just calls real mode int\n\nDPMI_INTR\tEQU\t31h\t\nIRQ1INTNUM\tEQU\t09h\t\t; IRQ1 interrupt vector number.\nBRKINTNUM\tEQU\t23h\t\t; Crtl-C (Break) interrupt vector number\nDBGINTNUM\tEQU\t3h\t\t; Debug interrupt vector number\nDOS_SYS_CALL\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nLOCK_PAGES\tEQU\t5\t\t; Lock pages subfunction using DX_MEM_MGT\nUNLOCK_PAGES\tEQU\t6\t\t; Unlock pages subfunction using DX_MEM_MGT\nCLEARISR\tEQU\t020H\t; value to clear In Service Register\nINTCHIP0\tEQU\t020H\t; 8259 interrupt chip controller 0\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\n\tINCLUDE \"keyboard.inc\"\n\tINCLUDE \"keystruc.inc\"\n\tINCLUDE \"mcgaprim.inc\"\n\n\tGLOBAL\t RealModePtr:DWORD\n\n\tGLOBAL\t Install_Keyboard_Interrupt:NEAR\n\tGLOBAL\t Get_RM_Keyboard_Address:Near\n\tGLOBAL\t Get_RM_Keyboard_Size:Near\n\tGLOBAL\t Remove_Keyboard_Interrupt:NEAR\n\tGLOBAL\t Check_Key_Num:NEAR\n\tGLOBAL\t Get_Key_Num:NEAR\n\tGLOBAL\t KN_To_KA:NEAR\n\tGLOBAL\t KeyNum_Translate:NEAR\n\tGLOBAL\t Check_Key:NEAR\n\tGLOBAL\t Get_Key:NEAR\n\tGLOBAL\t Keyboard_Attributes_On:NEAR\n\tGLOBAL\t Clear_KeyBuffer:NEAR\n\tGLOBAL\t Key_Down:NEAR\n\tGLOBAL\t Keyboard_Attributes_Off:NEAR\n\tGLOBAL\t Check_Key_Bits:NEAR\n\tGLOBAL\t Get_Key_Bits:NEAR\n\tGLOBAL\t Key_Satisfied:NEAR\n\tGLOBAL\t Stuff_Key_WORD:NEAR\n\tGLOBAL\t Stuff_Key_Num:NEAR\n\tGLOBAL\t MouseQX:DWORD\n\tGLOBAL\t MouseQY:DWORD\n;DBG\n\tGLOBAL   Keyboard_Interrupt:NEAR\n\n\n\tDATASEG\n; For the current time we will just include the real mode stuff\n; into the protected mode code and then copy it down.  The C side of\n; this will handle this method or reading it off of disk in the real\n; method.\n\nLABEL \tRealBinStart\tBYTE\ninclude \"keyireal.ibn\"\nLABEL\tRealBinEnd\tBYTE\n\nLABEL\tLockedDataStart\tBYTE\t\nRMVector\tDD\t0\nRealModeSel\tDD\t0\nRealModePtr\tDD\t0\t\t; Pointer to real mode memory.\nRealModeSize\tDD\t0\t\t; Pointer to real mode memory.\n\nKeyboard_App_Stack_ESP\tDD 0\t\t; This the System Stack Offsset\nKeyboard_App_Stack_SS\tDD 0\t\t; This the System Stack Selector\nKeyboard_StackPointer\tDD 0DEADDEADh\t; We Create a Local Application\nKeyboard_Stack          DD 512 dup (0)\nKeyboard_StackStart\tDD 0\n\t\t\t\t\t; StackPointer \t\nLABEL\tLockedDataEnd\tBYTE\n\n\n\nAscii\tDB\t0,\"`1234567890-=\",0,8,9,\"qwertyuiop[]\\\",0,\"asdfghjkl;'\"\n\tDB\t0,13,0,45,\"zxcvbnm,./\",0,0,0,0,0,\" \"\n\nShift\tDB\t0,\"~!@#$%^&*()_+\",0,8,9,\"QWERTYUIOP{}|\",0,\"ASDFGHJKL:\",22H\n\tDB\t0,13,0,45,\"ZXCVBNM<>?\",0,0,0,0,0,\" \"\n\nAlpha_Lower\tDB\t0\n\tDB\t\"~!@#$%^&*()_+\",0,8,9,\"qwertyuiop{}|\",0,\"asdfghjkl:\",22H\n\tDB\t0,13,0,45,\"zxcvbnm<>?\",0,0,0,0,0,\" \"\n\nAlpha_Shift\tDB\t0\n\tDB\t\"`1234567890-=\",0,8,9,\"QWERTYUIOP[]\\\",0,\"ASDFGHJKL;'\"\n\tDB\t0,13,0,45,\"ZXCVBNM,./\",0,0,0,0,0,\" \"\n\nEdit\tDB\t0AEH,0ADH,000H,000H,0B5H,0B9H,0B1H,000H,0B8H,0B0H,0B7H,0AFH\n\tDB\t000H,000H,0B3H,000H,0B9H,0B5H,0B1H,000H, \"/\",0B8H,0B4H,0B0H\n\tDB\t0AEH, \"*\",0B7H,0B3H,0AFH,0ADH, \"-\", \"+\",000H,00DH,000H\n\nNumPad\tDB\t0,\"741\",0,\"/8520*963.-+\",0,13,0\n\n\nGetKeyLock\tDW\t0\t; snap shot of num and caps lock bits\nInitFlags\tDW\t0\nMouseQX\t\tDD\t0\nMouseQY\t\tDD\t0\n\n\tCODESEG\n;***************************************************************************\n;* GET_RM_TIMER_ADDRESS -- Return address of real mode code for copy.      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      VOID * to the address of the real mode timer               *\n;*                                                                         *\n;* PROTO:\tVOID\t*Get_RM_Keyboard_Address(VOID);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Address C Near\n\n\tmov\teax, OFFSET RealBinStart\n\tret\n\n\tENDP\n\n;***************************************************************************\n;* GET_RM_KEYBOARD_SIZE -- return size of real mode timer code.            *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      LONG size of the real mode timer code                      *\n;*                                                                         *\n;* PROTO:\tLONG\tGet_RM_Keyboard_Size(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Keyboard_Size C Near\n\n\tmov\teax, OFFSET RealBinEnd - OFFSET RealBinStart\n\tret\n\n\tENDP\n;***************************************************************************\n;* INSTALL_KEYBOARD_INTERRUPT -- Installs the keyboard interrupt           *\n;*                                                                         *\n;* INPUT:\tint rm_ptr  - ptr to the real mode handler\t\t   *\t   *\n;*\t\tint rm_size - size of the real mode handler\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Install_Keyboard_Interrupt(int rm_ptr, int rm_size);  *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tInstall_Keyboard_Interrupt C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\tARG\trm_ptr:DWORD\n\tARG\trm_size:DWORD\n\n\t; Are they attempting to set timer again?\n\tcmp\t[RealModePtr],0\n\tjnz\t??error\n\n\t; Make sure all flags are cleared.\n\tcmp\t[InitFlags],0\n\tjnz\t??error\n\n\n\t; Before setting the interrupt vectors, the code needs to be locked\n\t; for DPMI compatability.  Any code or data accessed must be lockded\n\t; so that no page faults accure during an interrupt.\n\t; First lock the code, then the data.  The stack will already be locked.\n\t; The real mode code is also already locked be default.\n\t; To lock a page set up registers :\n\t; AX = 0600h\n\t; BX:CX\t= starting linear address of memory block\n\t; SI:DI = size of region\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_CODE\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_DATA\n\n\t; now allocate real mode memory and copy the rm binary down to it.\n\tmov\teax,0100h\t; set function number\n\tmov\tebx,[rm_size]\t\t; get size of RM binary.\n\tmov\t[RealModeSize],ebx\n\tadd\tebx,15\t\t\t; round up \n\tshr\tebx,4\t\t\t; convert to pages.\n\tint\tDPMI_INTR\t \t; do call.\n\tjc\t??error\t\t \t; check for error.\n\tor\t[InitFlags],IF_ALLOC_RM ; set successful\n\tmov\t[RealModeSel],edx\n\tshl\teax,4\t\t\t; convert segment to offset.\n\tmov\t[RealModePtr],eax\t; save offset to global variable.\n\n\t; now lock the real mode memory that we allocated\n\tmov\teax,0600h\t\t; function number.\n\tmov\tecx,[RealModePtr]\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_RM_CODE\n\n\n\n\t; set up source and destination pointers for the copy.\n\tmov\teax,[RealModePtr];\t; set up our dest pointer\n\tmov\tesi,[rm_ptr]\t\t; Set up our source pointer.\n\tmov\tedi,eax\t\t\t; put it into esi for copy.\n\tmov\tecx,[rm_size]\n\trep\tmovsb\t\t\t; write RM bin to RM memory.\n\n\t; restore esi to point to data and initialize some of it.\n\tmov\tesi,[RealModePtr]\n\tmov\teax,esi\n\tshl\teax,12\t\t\t\t\t\t; make seg in high eax.\n\tmov\tax,[(KeyboardType PTR esi).CallKeyRMIntOffset]\t; create RM addr of call chain.\n\tmov\t[(KeyboardType PTR esi).CallKeyRMIntAddr],eax\t; save it for use in PM int.\n\nIF NOT PROT_INT_ENABLE\n       ; Chain the Real Keyboard interrupt to any avilable\n       ; Interrupt vector so We make sure that the Real Mode\n       ; Keyboard Interrupt service get called at debuging time\n       ; of the library.\n\n       mov\tedi , eax\n       mov\tbl , 060h\n       mov\tbh , 6\n       mov\teax , 200h\n ??find:\n       int\tDPMI_INTR\n       jc\t??error\n       or\tcx,dx\n       jz\t??found\n       inc\tbl\n       dec\tbh\n       jnz\t??find\n       jmp\t??error\n ??found:\n       movzx\tebx , bl\n       mov\t[ byte ptr RMVector ] , bl\n       mov\t[ 4 * ebx ] , edi\nENDIF\n\n\n\n\t;-------------------------------------------------------\n\t; Initialize all of the keyboard specific information\n\t;-------------------------------------------------------\n\txor\teax,eax\t\t\t; clear the high bits of eax\n\tmov\tal,[417H]\t\t; get keyboard status flags\n\ttest\teax,040H \t\t; caps lock active?\n\tje \tshort ??nocap\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\n\n??nocap:\n\ttest\teax,020H\t\t\t; num lock active?\n\tje\tshort ??nonumlock\t\t; not active\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\n\n??nonumlock:\n\ttest\teax,002H\t\t\t; is left shift key down?\n\tje\tshort ??noleftshift\t\t; try the right\n\tor\t[(KeyboardType PTR esi+5).KeysUpDown],010H\n\n??noleftshift:\n\tand\teax,001H\t\t\t; get right shift bit\n\tshl\teax,9\t\t\t; put it into the proper position (shl al,1 mov ah,al)\n\tmov\tal,[418H]\t\t; get alt and ctrl bits\n\tshl\tal,2\t\t\t; put in proper position\n\tshl\tal,1\n\tand\tal,00CH\t\t\t; only alt and ctrl bits\n\tor\tah,al\t\t\t; put them ah for Keys+7 later\n\tmov\tal,[496H]\t\t; get extended keys\n\ttest\tal,008H\t\t\t; check for right alt key\n\tje\tshort ??noralt\n\tor\tah,040H\n??noralt:\n\tmov\t[(KeyboardType PTR esi+7).KeysUpDown],ah\n\ttest\tal,004H\t\t\t; test for right ctrl\n\tje \tshort ??norctrl\n\tor\t[(KeyboardType PTR esi+8).KeysUpDown],001h\n??norctrl:\n\ttest\tal,002H\t\t\t; last code E0?\n\tje short ??noe0\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],001h\n??noe0:\n\ttest\tal,001H\t\t\t; last code E1?\n\tje short ??noe1\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],002h\n??noe1:\n\t;==========================================================================\n\t; Get the protected mode interrupt vector keyboard.\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).KeyOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).KeyOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 2503, cl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,IRQ1INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).KeyOldRMI],ecx\n\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt Keyboard\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Keyboard_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt Keyboard\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).KeyCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the break interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\t\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).BrkOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).BrkOldPMISelector],ecx\t; save selector.\n\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector - for the break interrupt\n\t; input ax = 0200, bl = number of interrupt to get\n\t; output cf error, EBX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,BRKINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(KeyboardType PTR esi).BrkOldRMI],ecx\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Break_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[RealModePtr]     \t; get address of real code int hand.\n\tshr\tecx,4\t\t\t; put segment in hi word.\n\tmov\tdx,[(KeyboardType PTR esi).BrkCodeOffset] ; Get address of code\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\nIF DEBUG\n\t;==========================================================================\n\t; Get the protected mode interrupt vector - for the Debug interrupt\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t; ES:EBX = address of PM int handler routine.\n\t;==========================================================================\n\t\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,DBGINTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(KeyboardType PTR esi).DbgOldPMIOffset],edx\t; save offset.\n\tmov\t[(KeyboardType PTR esi).DbgOldPMISelector],ecx\t; save selector.\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Debug_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\nENDIF\n\n\t; we have finished with success.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n??exit:\n\tret\n\tENDP\tInstall_Keyboard_Interrupt\n\n;***************************************************************************\n;* REMOVE_INTERRUPT -- Removes keyboard interrupt and restores chain\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Remove_Interrupt(VOID)                                *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tRemove_Keyboard_Interrupt C NEAR \n\tUSES\tebx,ecx,edx\n\n\t; verifie that the keyboard was previosly install\n\t; this is here in case of a page fault crash\n\tmov\tesi,[RealModePtr]\n\ttest    esi,esi\n\tjz      ??error\n\n\ttest\t[InitFlags],IF_SET_VECTORS\n\tjz\t??vectors_not_set\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\tmov\teax, 0201h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tedx,[(KeyboardType esi).KeyOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ1INTNUM\n\tmov\tecx,[(KeyboardType esi).KeyOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).KeyOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\n\t; disengage Control Break Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,BRKINTNUM\n\tmov\tedx,[(KeyboardType esi).BrkOldRMI]     \t; get address of real code int hand.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,BRKINTNUM\n\tmov\tecx,[(KeyboardType esi).BrkOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).BrkOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\n\nIF DEBUG\n\n\t; disengage Keyboard Interrupt handle\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,DBGINTNUM\n\tmov\tecx,[(KeyboardType esi).DbgOldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(KeyboardType esi).DbgOldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n\nENDIF\n\nIF NOT PROT_INT_ENABLE\n       ; Clean up the Users interrupt table\n        mov\teax , 201h\n       mov\tbl , [ byte ptr RMVector ]\n       xor\tecx , ecx\n       xor\tedx , edx\n       int\tDPMI_INTR\n       jc\t??error\nENDIF\n\n\n??vectors_not_set:\n\t; now free up the real mode memory.\n\ttest\t[InitFlags],IF_LOCKED_RM_CODE\n\tjz\t??rm_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,[RealModePtr]\t\t; ecx must have start of memory.\n\tmov\tedi,[RealModeSize]\t\t; edx will have size of region in bytes.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??rm_not_locked:\n\ttest\t[InitFlags],IF_ALLOC_RM\n\tjz\t??mem_not_allocated\n\tmov\teax , 0101h\n\tmov\tedx,[ RealModeSel ] \t\t; get physical address of real mode buffer.\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n??mem_not_allocated:\n\n\t; Now we can unlock all stuff needed for the interrupt.  \n\t; Unlock Code\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??code_not_locked:\n\n\t; Unlock data\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??data_not_locked:\n\n\t; we have finished with success.\n\tmov\t[RealModePtr],0\t\t; To say we can do it again sometime.\n\tmov\t[InitFlags],0\t\t; To say we can do it again sometime.\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n\tret\n\tENDP\tRemove_Keyboard_Interrupt\n\n\n;***************************************************************************\n;* CHECK_KEY_NUM -- Checks if key in queue, return key num                 *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      Keynum of the key that was pressed, FALSE otherwise        *\n;*\n;* PROTO:\tINT Check_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Num C NEAR \n\tUSES\tebx,esi\n\tpushf\t\t\t\t\t; save off the flags\n\tcli\t\t\t\t\t; disable interrupts\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t\t\n\txor\teax,[(KeyboardType PTR esi).KeyBufferTail]\t\t\n\tor\teax,eax\t\t\t\t; check to see if head == tail\n\tjz\tshort ??fini\t\t\t; if so we are done\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t; get the head\n\tmov\tax,[(KeyboardType PTR esi+eax).KeyBuffer]\t; get key num\n\n??fini:\n\tsti\n\tpopf\n\tret\n\n\tENDP\tCheck_Key_Num\n\n;***************************************************************************\n;* GET_KEY_NUM -- Returns the next key num in ax                           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      WORD key flags are in the high byte of return word, key    *\n;*\t\t  num is in the low byte.\n;*                                                                         *\n;* PROTO:\tWORD Get_Key_Num(VOID);\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Num C NEAR\n\tUSES\tesi,edi\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n??wait:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\t\t; get the head\n\tcmp\teax,[(KeyboardType PTR esi).KeyBufferTail]\t\t; get the head\n\tjne\tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??wait\n\n??getkey:\n\tcall\tLow_Get_Key\n\tsti\t\t\t\t; enable interrupts\n\tret\n\n\tENDP\tGet_Key_Num\n\n;***************************************************************************\n;* KN_TO_KA -- Translates a key num to an ASCII key                        *\n;*                                                                         *\n;* INPUT:\tWORD the keynum to translate                               *\n;*                                                                         *\n;* OUTPUT:      WORD the ASCII key that is returned                        *\n;*                                                                         *\n;* PROTO:\tINT KN_To_KA(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tKN_To_KA C NEAR\n\tARG\tkeynum:DWORD\n\n\tmov\teax,[keynum]\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\tret\n\n\tENDP\tKN_To_KA\n\n\n;***************************************************************************\n;* LOW_GET_KEY -- low level get key returns key num and bits               *\n;*                                                                         *\n;* INPUT:\tAX - index into the buffer                                 *\n;*                                                                         *\n;* OUTPUT:      AX - key num with bits                                     *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/14/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tLow_Get_Key C NEAR \n\tUSES\tebx,esi,edi\n\n\tmov\tedi,eax\t\t\t\t; save off value in ax\n\n; We should set up both DS & ES because we are a low level function\n; and don't know who might have called us or what the registers\n; currently are.\n\n; No reason to set DS & ES.\n; This is not a hardware interrupt and if the funtion is being called\n; from within a hardware interrupt then DS and ES will be preset to\n; DGROUP _DATA\n\t\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tcmp\tal,KN_LMOUSE\n\tjb \tshort ??cont\n\tcmp\tal,KN_RMOUSE\n\tja \tshort ??chkjoy\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t; 128 word circular buffer\n\n\tmov\t[MouseQX],eax\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\t[MouseQY],eax\n\n\tpop\teax\t\t\t; restore keynum for return\n\n\tjmp\tshort ??cont\n\n??chkjoy:\n\tcmp\tal,KN_JBUTTON2\t\t; mouse button before joystick button\n\tja \tshort ??cont\n\n\tpush\teax\t\t\t; save off the keynum we got\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tmov\tax,[(KeyboardType PTR esi+edi).KeyBuffer]\t\t; get the head\n\tadd\tedi,2\n\tand\tedi,0FFH\t\t\t; 128 word circular buffer\n\n\tpop\teax\t\t\t; restore keynum for return\n??cont:\n\tmov\t[(KeyboardType PTR esi).KeyBufferHead],edi\t; set the head\n\n??out:\n\tret\n\n\tENDP\tLow_Get_Key\n\n;***************************************************************************\n;* CONVERT_NUM_TO_ASCII -- Assembly routine converts keynum to ASCII key   *\n;*                                                                         *\n;* INPUT:\tEAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - holds the key num bits                        *\n;*\t\t\tAL - holds the key num value\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      EAX where:\t\t\t\t\t\t   *\n;*\t\t\tAH - hold the key bits                             *\n;*\t\t\tAL - holds the ASCII key value\t\t\t   *\n;*                                                                         *\n;* PROTO:\tnone - assembly callable routine only.                     *\n;*                                                                         *\n;* WARNINGS:    GetKeyLock must be set prior to calling this function\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tConvert_Num_To_ASCII C NEAR \n\tUSES\tebx,ecx,esi,edi\n\n\t;*===================================================================\n\t;* Force all breaks to be thrown out.\n\t;*===================================================================\n\ttest\teax,08000h\t\t; If it is a button number\n\tjne\tshort ??button\t\t;  don't process it\n\n\ttest\tah,KEYRELEASE\t\t; If it is not key release\n\tje\tshort ??ok\t\t;  then go process it\n\n??button:\n\txor\teax,eax\t\t\t; no ascii value for a button\n\tret\n\n??ok:\n\t;*===================================================================\n\t;* ES points to the DOSMEM selector, esi is the offset of the \n\t;*   protected mode structure.\n\t;*===================================================================\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\n\t;*===================================================================\n\t;* Start dealing with the keys.\t\t\t\t\t  \n\t;*===================================================================\n\tcmp\tal,110\t\t\t; is it esc\n\tje\t??esc\t\t\t; if so then deal with it\n\n;??chkext:\n\tcmp\tal,62\t\t\t; is it extended?\n\tjae\tshort ??extended\t; its extended so return ext code\n\n\tmov\tebx,eax\t\t\t; get an index\n\tand\tebx,03FH\t\t; only 0-63 allowed\n\ttest\tah,1\t\t\t; if not, test for shift\n\tjnz\tshort ??shifted\t\t; if shifted get shift value\n\n\t;*===================================================================\n\t;* Here when we have an unshifted ascii key\n\t;*===================================================================\n\tmov\tal,[Ascii+ebx]\t\t; get the ascii code for this number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_lowered:\n\tmov\tal,[Alpha_Lower+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* CAPS key is on, forcing all alphabetic characters to lower case (all\n\t;* others are shifted)\n\t;*===================================================================\n??alpha_shifted:\n\tmov\tal,[Alpha_Shift+ebx]\t; get the s_ascii code for number\n\tjmp\tshort ??ctrlkey\n\n\t;*===================================================================\n\t;* Shift'ed character\n\t;*===================================================================\n??shifted:\n\tmov\tal,[Shift+ebx] \t\t; get ascii shift code for number\n\n??ctrlkey:\n\ttest\tah,2\t\t\t; is it ctrl?\n\tjz \tshort ??jexit\t\t; izf not skip ctrl check\n\n\tmov\tedi,ebx\t\t\t; get index\n\tand\tedi,7\t\t\t; only bits 0-7\n\n\tmov\tcl,[(KeyboardType PTR esi+edi).Bits]\n\n\tshr\tebx,3\t\t\t; div by 8 for byte offset\n\ttest\t[(KeyboardType PTR esi+ebx).KeysCapsLock],cl\t\n\tje \tshort ??jexit\n\tand\tal,01FH\t\t\t; force to ctrl value\n\n??jexit:\n\tjmp short ??exit\n\n??extended:\n\tcmp\tal,75\t\t\t; if less than insert\n\tjb \tshort ??special\n\tcmp\tal,110\t\t\t; if >= esc\n\tjae \tshort ??funckey\n\n??editkeys:\n\txor\tebx,ebx\n\tmov\tbl,al\n\tsub\tebx,75\t\t\t; get value from 0-34\n\ttest\t[(KeyboardType PTR esi).KeyFlags],NONUMLOCK\n\tjne \tshort ??no_numpad\n\ttest\t[GetKeyLock],NUMLOCK\t; look at the snap shot of bits\n\tjne \tshort ??numpad\n\ttest\tah,SHIFTPRESS\n\tjne \tshort ??numpad\n\n??no_numpad:\n\tmov\tal,[Edit+ebx] \t\t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??numpad:\n\tsub\tebx,15\t\t\t; adjust to numpad entries\n\tmov\tal,[NumPad+ebx] \t; get the ascii code for this number\n\tjmp\tshort ??exit\n\n??funckey:\n\tcmp\tal,112\t\t\t; if less than function keys\n\tjb \tshort ??extout\n\tcmp\tal,121\t\t\t; if greater than function keys 1-10\n\tja \tshort ??extout\n\tmov\tbl,al\n\tsub\tbl,112\t\t\t; get value 0-9\n\tmov\tbh,0C5H\t\t\t; function key 1 no shift-ctrl-alt\n\ttest\tah,7\t\t\t; any shift-ctrl-alt\n\tje\tshort ??funcadj\n\tmov\tbh,098H\t\t\t; function key 1 alt\n\ttest\tah,ALTPRESS\t\t; (highest prescendence)\n\tjne \tshort ??funcadj\n\tmov\tbh,0A2H\t\t\t; function key 1 ctrl (next highest)\n\ttest\tah,CTRLPRESS\n\tjne\tshort ??funcadj\n\tmov\tbh,0ACH\t\t\t; function key 1 shift (lowest)\n\n??funcadj:\n\tsub\tbh,bl\t\t\t; adjust function key to a\n\tmov\tal,bh\t\t\t; shift/no shift etc\n\tjmp\tshort ??exit\n\n??special:\n\tcmp\tal,65\t\t\t; if less than specials\n\tjb\tshort ??extout\n\n\tadd\tal,133\t\t\t; make value between 198-207 or\n\tjmp\tshort ??exit\t\t; 0C6H-0CFH\n\t\n??extout:\n\tor\tal,080H\n\tjmp\tshort ??exit\n\n??esc:\n\tmov\tal,01BH\n\n??exit:\n\tret\n\tENDP\tConvert_Num_To_ASCII\n\n;***************************************************************************\n;* CHECK_KEY -- checks for ASCII keys sitting in the keybuffer             *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      INT the ASCII sequence for the key that was pressed        *\n;*                                                                         *\n;* PROTO:\tINT Check_Key(VOID);                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key C NEAR\n\tUSES\tebx,edi,esi\n\n\tpushf\n\tcld\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tcmp\tal,KN_LMOUSE\t\t; check if it is a mouse or joystick\n\tjb\tshort ??contget\n\tcmp\tal,KN_JBUTTON2\n\tja\tshort ??contget\n\tadd\tsi,4\t\t\t; get rid of the x and y values\n\n??contget:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\teax,eax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\tsti\t\t\t\t; enable interrupts\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tcall\tnear ptr Convert_Num_To_ASCII\n\t\t\t\t\t; AX has ASCII code with bits\n\n\txor\tah,ah\t\t\t; clear key bits\n??exit:\n\tpopf\n\tret\n\tENDP\tCheck_Key\n\n\n;***************************************************************************\n;* GET_KEY -- Gets the next available ASCII keystroke.\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      AH - hold the key bits                                     *\n;*\t\tAL - holds the ASCII key value\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tINT Get_Key(VOID);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key C NEAR \n\tUSES \tebx,ecx,edi\n\n\tcld\t\t\t\t; clear the direction flag for speed\n\n\t; Check_Key had to be copied because of enable and disable of ints\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\ttest\tah,KEYRELEASE\t\t; is this a break?\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\t\t\t\t\t; AX has key num code with bits\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\txor\tah,ah\n\tret\n\n\tENDP\tGet_Key\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_ON -- Sets the specified keyflags on                *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned on                 *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are on                       *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_On(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_On C NEAR\n\tUSES\tesi,edi\n\tARG\tbits:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tor\t[(KeyboardType PTR esi).KeyFlags],eax\n\n\t; Only do this if in playback or record mode.\n\ttest\teax,PASSBREAKS\n\tje\tshort ??fini\n\n\txor\teax,eax\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).KeysUpDown\n\tmov\t[edi],eax\n\tmov\t[edi+4],eax\n\tmov\t[edi+8],eax\n\tmov\t[edi+12],eax\n??fini:\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\n\tret\n\tENDP\tKeyboard_Attributes_On\n\n;***************************************************************************\n;* KEYBOARD_ATTRIBUTES_OFF -- Sets the specified keyflags off              *\n;*                                                                         *\n;* INPUT:\tINT the keyflags that need to be turned off                *\n;*                                                                         *\n;* OUTPUT:      INT the current keyflags that are off                      *\n;*                                                                         *\n;* PROTO:\tINT Keyboard_Attributes_Off(INT key_flags);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Attributes_Off C NEAR\n\tUSES\tesi\n\tARG\tbits:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[bits]\n\tnot\teax\n\tand\t[(KeyboardType PTR esi).KeyFlags],eax\n\txor\teax,eax\n\tmov\teax,[(KeyboardType PTR esi).KeyFlags]\n\tret \n\n\tENDP\tKeyboard_Attributes_Off\n;***************************************************************************\n;* CLEAR_KEYBUFFER -- Clears keystrokes out of the key buffer              *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Clear_KeyBuffer(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tClear_KeyBuffer C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\tcli\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferHead]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\tsti\n\n\tret\n\n\tENDP\tClear_KeyBuffer\n\n;***************************************************************************\n;* KEY_DOWN -- tests the status of a keyboard key                          *\n;*                                                                         *\n;* INPUT:\tINT the key num to check                                   *\n;*                                                                         *\n;* OUTPUT:      INT zero if the key is up, none zero if the key is down    *\n;*                                                                         *\n;* PROTO:\tINT Key_Down(INT key);\t\t\t\t   \t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Down C NEAR\n\tUSES\tebx,ecx,edi,esi\n\tARG\tkey:DWORD\n\n\tpush\t[key]\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\txor\tah,ah\t\t\t\t; Always ignore the control bits.\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\tedi,eax\n\tshr\tedi,3\n\tmov\tcl,al\n\tand\tcl,0111b\n\tmov\tal,01b\n\tshl\tal,cl\n\tand\tal,[(KeyboardType PTR esi+edi).KeysUpDown]\n\tret\n\n\tENDP\tKey_Down\n\n;***************************************************************************\n;* CHECK_KEY_BITS -- checks ascii key in key buff with shift,ctrl,alt bits *\n;*                                                                         *\n;* INPUT:\tnone \t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set     *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tCheck_Key_Bits C NEAR\n\tUSES\tebx,ecx,edi,esi\n\n\tpushf\t\t\t\t\t; save off the direction flag\n\tcld\t\t\t\t\t; we will go forward\n\n\tmov\tebx,[RealModePtr]\t\t; Point to start of RM data.\n??clrloop:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tje\tshort ??clrexit\n??playback:\n\tmov\tesi,eax\n\tmov\tax,[(KeyboardType PTR ebx+eax).KeyBuffer]\t; get key num\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\tshort ??getinvalid\n\n\t;------ If there is a NULL in the keyboard buffer, we must NOT treat it\n\t;\tas a valid ASCII value because the calling code will falsely\n\t;\tassume that the NULL return value indicates an empty buffer.\n\tor\tal,al\n\tje\tshort ??getinvalid\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjb\tshort ??convkey\n\n??getinvalid:\n\tadd\tesi,2\t\t\t; get rid of invalid ascii key\n\tand\tesi,0FFH\t\t\t; 128 word circular buffer\n\tmov\t[(KeyboardType PTR ebx).KeyBufferHead],esi\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??clrloop\n\n??clrexit:\n\txor\tax,ax\n\n??convkey:\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tor\teax,eax\n\tje \tshort ??exit\t\t; exit if no key\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tCheck_Key_Bits\n;***************************************************************************\n;* GET_KEY_BITS -- Gets ascii key in key buff with shift,ctrl,alt bits     *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tINT 0 = no key in buffer, !0 = a key with the bits set\t   *\n;*                                                                         *\n;* PROTO:\tINT Check_Key_Bits(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Key_Bits C NEAR \n\tUSES\tebx,ecx,edi\n\n\tcld\n\n\t; Check_Key_Bits was copied because of enable and disable of interrupts\n\t;  with mod to get the key\n\n\tmov\tebx,[RealModePtr]\t; Point to start of RM data.\n\n??chkkey:\n\tcli\t\t\t\t; disable interrupts\n\tmov\teax,[(KeyboardType PTR ebx).KeyBufferHead]\n\tcmp\teax,[(KeyboardType PTR ebx).KeyBufferTail]\n\tjne \tshort ??getkey\n\tsti\t\t\t\t; enable interrupts\n\tjmp\t??chkkey\n\n??getkey:\n\t\t\t\t\t; AX has index into keybuffer\n\tcall\tnear ptr Low_Get_Key\n\t\t\t\t\t; AX has key num code with bits\n\n\tmov\tcx,[(KeyboardType PTR ebx).KeyLock]\n\tmov\t[GetKeyLock],cx\t\t; save status for convert to ASCII\n\n\tsti\t\t\t\t; enable interrupts\n\n\tmov\tedi,ebx\n\tadd\tedi,OFFSET (KeyboardType PTR 0).PassAlways\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always\n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was a match\n\tjne\t??chkkey\n\n\tcmp\tal,122\t\t\t; is code a valid ascii key??\n\tjae\t??chkkey\n\n\t\t\t\t\t; AX has key num code with bits\n\tmov\tch,ah\n\tand\tch,KEYRELEASE\t\t; keep only KEYRELEASE bit\n\tand\tah,NOTKEYRELEASE\t; keep everything but KEYRELEASE bit\n\n\tcall\tnear ptr Convert_Num_To_ASCII\n\n\t\t\t\t\t; AX has ASCII code with bits\n\tor\tah,ch\t\t\t; replace KEYRELEASE bit\n\tret\n\n\tENDP\tGet_Key_Bits\n\n;***************************************************************************\n;* KEY_SATISFIED -- checks to see if the given key is satisfied            *\n;*                                                                         *\n;* INPUT:   INT the key flags/number to check                          \t   *\n;*                                                                         *\n;* OUTPUT:  INT 0 if the key is not satisfied, !0 if the key is satisfied  *\n;*                                                                         *\n;* PROTO:   VOID Key_Satisfied(INT key);                                    *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/20/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKey_Satisfied C NEAR\n\tUSES\tebx,ecx,esi,edi\n\tARG\tkey:DWORD\n\n\tmov\teax,[key]\n\tmov\tebx,eax\t\t\t; save key code\n\tpush\teax\n\tcall\tKey_Down\t\t; see it its even down\n\tadd\tesp,4\n\tcmp\teax,0\n\tje\t??out\t\t\t; if not it can't be satisfied\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,ebx\t\t\t; if so, restore code\n\txor\tah,ah\t\t\t; clear out flags area\n\tmov\tedi,eax\t\t\t; set as an index\n\tshr\tedi,3\t\t\t; div by 8 for bytes\n\tmov\tch,1h\t\t\t; set a bit for mask\n\tmov\tcl,al\t\t\t; get the code number\n\tand\tcl,7\t\t\t; get the actual bit this code is\n\tshl\tch,cl\t\t\t; move bit into mask position\n\n; now test the ctrl,alt and shift bits\n\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],04h\t; is the left ctrl down?\n\tjne \tshort ??ctrlon\t\t; if so, ctrl is on\n\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],01h\t; is the right ctrl down?\n\tje \tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n??ctrlon:\n\tor\tah,02h\t\t\t; or on the ctrl bit in flags\n??ctrloff:\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],50h\t; is either alt key down?\n\tje \tshort ??altoff\n\tor\tah,04h\t\t\t; or on the alt bit in flags\n??altoff:\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],10h\t; is the left shift down?\n\tjne \tshort ??shifton\t\t; if so the sift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],02h\t; is the right shift down?\n\tje \tshort ??shiftoff\t\t; if not then neither shift is down\n??shifton:\n\tor\tah,01h\t\t\t; or on the shift bit in flags\n??shiftoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje \tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje \tshort ??capsoff\t\t; its not effected\n\txor\tah,1h\t\t\t; toggle the shift flag\n??capsoff:\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t\t; is the num lock key on?\n\tje \tshort ??numlockoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje \tshort ??numlockoff\t\t; if not effected skip toggle\n\txor\tah,1h\t\t\t; toggle the shift flag if effected\n\n??numlockoff:\n\tmov\tal,0ffh\t\t\t; set to match by default\n\tcmp\tah,bh\t\t\t; if flags match return !0\n\tje \tshort ??out\t\t\t; just exit\n\txor\teax,eax\t\t\t; otherwise, clear all bits FALSE\n\n??out:\n\tor\teax,eax\n\tret\n\n\tENDP\tKey_Satisfied\n\n\n;***************************************************************************\n;* Interrupt routines start here - Interrupts must be within the Locked \n;*   code area for DPMI compatability.\n;***************************************************************************\n\n\n\n\nLABEL \tLockedCodeStart\tBYTE\n\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Performs a lowlevel xlate to a keycode              *\n;*                                                                         *\n;* INPUT:\tWORD the code that needs to be translated                  *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated code                                   *\n;*                                                                         *\n;* PROTO:\tINT KeyNum_Translate(INT keynum);                          *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyNum_Translate C NEAR \n\tUSES \tebx,ecx,esi,edi\n\tARG\tkeycode:DWORD\n\n;*===================================================================\n;* ES points to the DOSMEM selector, esi is the offset of the \n;*   protected mode structure.\n;*===================================================================\n\n\tmov\tesi,[RealModePtr]\t; Point to start of RM data.\n\tmov\teax,[keycode]\n\ttest\t[(KeyboardType PTR esi).KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\n\tmov\tecx,OFFSET ((KeyboardType PTR 0).ExtRemap)- OFFSET((KeyboardType PTR 0).ExtNums)\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtNums\n\tadd\tedi,esi\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tedi,esi\n\tadd\tedi,OFFSET (KeyboardType PTR 0).ExtRemapEnd\n\tdec\tedi\n\tsub\tedi,ecx\n\tmov\tal,[edi]\n??fini:\n\tret\n\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(INT code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_WORD C NEAR\n\tUSES\tebx,esi,edi\n\tARG\tcode:WORD\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\tmov\teax,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\tedi,eax\n\tadd\teax,2\n\tand\teax,0FFh\t\t\t; New KeyBufferTail value.\n\tcmp\t[(KeyboardType PTR esi).KeyBufferHead],eax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[(KeyboardType PTR esi+edi).KeyBuffer],bx\t\t; Record the keystroke.\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\n\tret\n\n??noroom:\n\tmov\teax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(INT keynum);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tStuff_Key_Num C NEAR\n\tUSES\tebx,ecx,edx,edi,esi\n\tARG\tkeycode:DWORD\n\tLOCAL\ttail:DWORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n; for the moment we do not check for the interrupt flag\n;\tmov\teax,2534h \t\t; function to get the interrupt status\n;\tint\t21\t\t\t; eax = interrupt status\n;\tpush\teax\t\t\t; save the result on the stack\n\n\tpushf\t\t\t\t; store off the flags\n\tcli\t\t\t\t; disable interrupts\n\n; We need to set the data segment because we might be being called\n; from within an interrupt\n; Soo, if that is the case then DS & ES point to DGROUP _DATA \n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\teax,[(KeyboardType PTR esi).MouseX]\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\teax,[(KeyboardType PTR esi).MouseY]\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],ax\n\n??cando:\n\tmov\teax,[keycode]\t\t; get the code\n\tor\teax,eax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[(KeyboardType PTR esi).KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[(KeyboardType PTR esi).Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[(KeyboardType PTR esi).Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[(KeyboardType PTR esi).Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\txor\tebx,ebx\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tebx,1\t\t\t; double for WORD index\n\tmov\tax,[WORD PTR ((KeyboardType PTR esi+ebx).XYAdjust)]\n\n\tmovsx\tebx,ah\n\tmovsx\teax,al\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tedx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tedx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tebx,edx\t\t\t; add speed for y index\n\tmov\tbl,[(KeyboardType PTR esi+ebx).KeyMouseMove] \t; get speed for y delta\n\tmovsx\tebx,bl\n\txchg\tebx,edx\t\t\t; save mouse y delta\n\tadd\tebx,eax\t\t\t; add speed for x index\n\tmov\tal,[(KeyboardType PTR esi+ebx).KeyMouseMove]\t; get speed for x delta\n\tmovsx\teax,al\n\txchg\tebx,edx\t\t\t; restore mouse y delta\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tebx,011b\t\t\t; Y = 1, 0, 3\n\tand\teax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tebx,011b\t\t\t; Y = 3, 0, 1\n\tand\teax,011b\t\t\t; X = 3, 0, 1\n\tshl\tebx,2\n\tor\tebx,eax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tebx,1\n\tmovzx\tebx,[(KeyboardType PTR esi+ebx).EdgeConv]\n\tshl\tebx,2\n\tmov\tax,[(KeyboardType PTR esi+ebx).ScreenEdge]\t; New absolute X\n\tmov\tbx,[(KeyboardType PTR esi+ebx+2).ScreenEdge] ; New absolute Y\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\teax,eax\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[(KeyboardType PTR esi).LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tebx,ebx\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[(KeyboardType PTR esi).LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[(KeyboardType PTR esi).LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[(KeyboardType PTR esi).LocalMouseX],ax\n\tmov\t[(KeyboardType PTR esi).LocalMouseY],bx\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseX],ax\n\tmov\t[WORD PTR (KeyboardType PTR esi).MouseY],bx\n\tcmp\t[(KeyboardType PTR esi).MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n; PWG: ARRGGGHHHH!\n;\tcall\tLow_Hide_Mouse\n;\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\teax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],eax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tedi,[(KeyboardType PTR esi).KeyBufferTail]\n\tmov\t[tail],edi\t\t; Safety record.\n\n\t; Record the base keycode (if there is room).\n\tcwde\t\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\teax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tmovzx\teax,[(KeyboardType esi).LocalMouseX]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tmovzx\teax,[(KeyboardType esi).LocalMouseY]\n\tpush\teax\n\tcall\tStuff_Key_WORD\n\tadd\tesp,4\n\tor\teax,eax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tebx,0101h\t\t; Bit control tools.\n\tmov\teax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[(KeyboardType PTR esi).KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[(KeyboardType esi).KeyBufferTail],edi\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tmov\tcl,3\n\tshr\tedi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[(KeyboardType esi+edi).KeysUpDown]\n\tje\tshort ??notalready\n\ttest\t[(KeyboardType PTR esi).KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\tedx,[tail]\n\tmov\t[(KeyboardType esi).KeyBufferTail],edx\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[(KeyboardType esi+edi).KeysUpDown],bh\t; Force key bit to zero.\n\tor\t[(KeyboardType esi+edi).KeysUpDown],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\teax,1\n\tjmp\tshort ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\teax,[tail]\n\tmov\t[(KeyboardType PTR esi).KeyBufferTail],eax\n\txor\teax,eax\t\t\t; Signal an error.\n\n??exit:\n\tsti\n\tpopf\n\n;\tpopf\n;\tpop\tebx\n;\tor\tebx,ebx\n;\tjz\t??final_exit\n;\tsti\n\n??final_exit:\n\tret\n\n\tENDP\tStuff_Key_Num\n\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles break interrupt for protected mode           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBreak_Interrupt C NEAR\n\n\tiret\n\tENDP\tBreak_Interrupt\n\nIF DEBUG\n;***************************************************************************\n;* DEBUG_INTERRUPT -- Handles debug (INT 3) interrupt for protected mode   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/28/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tDebug_Interrupt C NEAR\n\n\t;*==================================================================\n\t;* Setup fake Interrupt entry sequence so that we can execute our\n\t;*   code and then IRET painlessly into the debuggers interrupt\n\t;*   handler.\n\t;*==================================================================\n\tpushfd\t\t\t; Step 1\n\tsub\tesp,8\t\t; Step 2\n\tpush\tebp\t\t; Step 3\n\tmov\tebp,esp\t\t; Set up a stack frame to know where to poke address.\n\n\t;*==================================================================\n\t;* Preserve all of the registers that we intend to use.\n\t;*=======================================Dbg========================\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n\tmov\tax , _DATA\n\tmov\tds , ax\n\tmov\tes , ax\n\tinc\t[BYTE PTR 0B0000h]\n\n\t;*==================================================================\n\t;* Setup the pointers to the real mode data and the protected mode\n\t;*   data and selectors.\n\t;*==================================================================\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\n\t;*==================================================================\n\t;* Do the deed.\n\t;*==================================================================\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\n\t;*==================================================================\n\t;* Now get the address of the real debug handler and poke it into\n\t;*   the stack so we can IRET to it.\n\t;*==================================================================\n\tmov\teax,[(KeyboardType PTR esi).DbgOldPMIOffset]\t; Get orig offset.\n\tmov\tebx,[(KeyboardType PTR esi).DbgOldPMISelector]\t; Get orig selector.\n\tmov\t[ss:ebp+4],eax\t\t\t\t\t; Poke offset.\n\tmov\t[ss:ebp+8],ebx\t\t\t\t\t; Poke selector.\n\n\t;*==================================================================\n\t;* Restore the stack so it looks like we just did an IRET entry\n\t;*==================================================================\n\tpop\tfs gs es ds\n\tpopad\n\tpop\tebp\n\n\t;*==================================================================\n\t;* This iret should go directly to the real debugger handler\n\t;*\tpainlessly and effectively.\n\t;*==================================================================\n\tiretd\n\n\tENDP\tDebug_Interrupt\nENDIF\n\n\n\nIF PROT_INT_ENABLE\n\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Handles input that comes from the keyboard        *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tKeyboard_Interrupt C NEAR\n\n\tpushad\n\tpush\tds es gs fs\n\tcld\n\n; this is the part of the interrupt that set the segment registers\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov cx, ss\t\t\t\t; get SS\n\tmov [Keyboard_App_Stack_ESP], esp\t; Protect ESP\n\tmov [Keyboard_App_Stack_SS], ecx\t; Protect SS\n\tlea edx, [Keyboard_StackStart ]\t; Compute Local Stack size\n\tand edx, -4 ;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov esp, edx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\n\t\n\tmov\tedx,[(KeyboardType PTR esi).KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[(KeyboardType PTR esi).KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\ttest\t[BYTE PTR 417H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR 417H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[(KeyboardType PTR esi).KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR 496H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[(KeyboardType PTR esi).ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tebx,0101H\t\t; set key to a make by default \n\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\t;\n\t; New CODE to montior key stream\n\t;\n\txor\tebx,ebx\n\tmov\tbx,[(KeyboardType PTR esi).KeyStreamIndex]\n\tmov\t[(KeyboardType PTR esi+ebx).KeyStream],al\n\tinc\tebx\n\tand\tebx,15\n\tmov\t[(KeyboardType PTR esi).KeyStreamIndex],bx\n\tmov\tebx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[(KeyboardType PTR esi).LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[(KeyboardType PTR esi).LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[(KeyboardType PTR esi).LastKeyE1]\t\t; yes, dec the count\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[(KeyboardType PTR esi).LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[(KeyboardType PTR esi).IsExtKey],TRUE\t; it is an extended key\n\n\n\tmov\tedi,OFFSET (KeyboardType PTR 0).ExtCodes\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).ExtNums-OFFSET (KeyboardType PTR 0).ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\n\tmov\tal,[(OFFSET (KeyboardType PTR 0).ExtNums - OFFSET (KeyboardType PTR 0).ExtCodes) - 1 + edi] ; get the match\n\tmov\t[(KeyboardType PTR esi).IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tedi,eax\t\t\t; use code as an index\n\tand\tedi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[(KeyboardType PTR esi+edi).KeyNums]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+8).KeysUpDown],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[(KeyboardType PTR esi).ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tedx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n;------\tSet the shift bit if necessary.\n\ttest\t[(KeyboardType PTR esi+5).KeysUpDown],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[(KeyboardType PTR esi+7).KeysUpDown],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tedi,eax\n\tand\tedi,07Fh\n\tshr\tedi,3\n\tmov\tebx,eax\n\tand\tebx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[(KeyboardType PTR esi+ebx).Bits]\t\t; get the bit to test\n\ttest\t[(KeyboardType PTR esi).KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysCapsLock]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[(KeyboardType PTR esi).KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[(KeyboardType PTR esi+edi).KeysNumLock]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[(KeyboardType PTR esi).CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\n\t\t\t\t\t; keyboard buffer.\n\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\teax\n\tcall\tKeyNum_Translate\n\tadd\tesp,4\n\n\tmov\tecx,eax\n\txor\teax,eax\n\tmov\tax,cx\n\n\ttest\tedx,DEBUGINT\n\tjz\t??not_toggle\n\n\tcmp\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\n\tinc\t[BYTE PTR 0B0002h]\n\n\tcmp\teax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\teax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\teax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\t\n\tcmp\teax,125\n\tjne\t??not_toggle\n\n\tinc\t[BYTE PTR 0B0000h]\n\n\tmov\t[(KeyboardType PTR esi).KeyIntDisabled],1\n\tjmp\t??absorbcode\n\n??not_toggle:\n\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\teax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\teax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\teax,0230h\n\tje\tshort ??breaker\n\tcmp\teax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[(KeyboardType PTR esi).Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n;\tcmp\tax,0420H\t\t; is this an alt s\n;\tjne\tshort ??checkmusic\t; toggle the Sound variable\n;\tpush\tax\n;\tmov\tax,[SoundOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??checkmusic:\n;\tcmp\tax,0434H\t\t; is this an alt m\n;\tjne\tshort ??esc\t\t; toggle the Music variable\n;\tpush\tax\n;\tmov\tax,[MusicOn]\n;\txor\tax,01H\n;\tpush\tax\n;\tadd\tsp,2\n;\tpop\tax\n\n;??esc:\n\n\tpush\teax\n\tcall\tStuff_Key_Num\n\tpop\teax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[(KeyboardType PTR esi).EscRoutine],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\teax\n\tcall\t[(KeyboardType PTR esi).EscRoutine]\n\tpop\teax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tedi,OFFSET (KeyboardType PTR 0).PassAlways\t; get offset to table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd - OFFSET (KeyboardType PTR 0).PassAlways) ; get number of pass always CDY JLB MOD 7/11 was \n\trepne\tscasb\t\t\t; look for a match\n\tor\tecx,ecx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tedi,OFFSET (KeyboardType PTR 0).CondPassKey\t; get offset to cond key table\n\tadd\tedi,esi\n\tmov\tecx,(OFFSET (KeyboardType PTR 0).CondPassCond-OFFSET (KeyboardType PTR 0).CondPassKey) ; get number of entries\n\tshr\tecx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(OFFSET (KeyboardType PTR 0).CondPassCond - OFFSET (KeyboardType PTR 0).CondPassKey) - 2 + edi]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tedx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\tinc\t[(KeyboardType PTR esi).PassCount]\n\tmov\t[(KeyboardType PTR esi).PMIssuedKeyInt],1     ; Make it TRUE\n\n\t; Now it is time to set up for the call to the System Keyboard\n\t; interrupt handler.\n\t; 1 -Restore System Stack Pointer Selector before exit Interrupt\n\t; 2- We Create a Returning Point from Interrupt by Push A\n \t;    Interupt Stack Frame into the Stack Pointer\n\t; 3- We make a Far jump to the interuupt handler\n\n\tcmp  [Keyboard_StackPointer],0DEADDEADh\n\tje   ??pass_stack_good\n\n\tpush ecx\n\tpush edi\n\tpush eax\n\tmov  edi,0A0000h\n\tmov  ecx,64000\n\tmov  eax,1\n\trep  stosb\n\tpop  eax\n\tpop  edi\n\tpop  ecx\n\n??pass_stack_good:\n\tcli\t\t\t\t       ; disable Interrupts\n\tmov edx, [Keyboard_App_Stack_SS]       \n\tmov ss, dx\t\t\t       ; Set System Stack Selector\n\tmov esp, [Keyboard_App_Stack_ESP]      ; Set System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n\tlea\tedx, [??Call_Back_Keyboard]   ; Get Return address offset\n \tpushfd\t\t\t\t      ; push flags\t\n\tpush\tcs\t\t\t      ; push Code Selector\n\tpush\tedx\t\t\t      ; push Offset\n\n\t; Now we need to simulate an interrup call by using ired\n\t; because we still want to come back here from the\n\t; Old Keyboard interrupt handle.\n\tpushfd\n\tpush\t[(KeyboardType PTR esi).KeyOldPMISelector] ; push orig selector.\n\tpush    [(KeyboardType PTR esi).KeyOldPMIOffset]   ; push orig offset.\n\tiretd\n\n??absorbcode:\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tal,[496h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[496h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\n\tcmp  [Keyboard_StackPointer],0DEADDEADh\n\tje   ??call_stack_good\n\tpush ecx\n\tpush edi\n\tpush eax\n\tmov  edi,0A0000h\n\tmov  ecx,64000\n\tmov  eax,1\n\trep  stosb\n\tpop  eax\n\tpop  edi\n\tpop  ecx\n\n??call_stack_good:\n\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov edx, [Keyboard_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, dx\t\t\t       ; Set System Stack Selector\n\tmov esp, [Keyboard_App_Stack_ESP]      ; Set System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n??Call_Back_Keyboard:\n\tpop\tfs gs es ds\n\tpopad\n\tiret\t\n\n\tENDP\tKeyboard_Interrupt\n\nELSE\n;***************************************************************************\n;* KEYBOARD_INTERRUPT -- Stub for the keyboard interrupt call real mode    *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\n \nDATASEG\nSTRUC\tRealModeCallStruc\n\t_EDI  DD\t0\n\t_ESI  DD\t0\n\t_EBP  DD\t0\n\t      DD        0\n\t_EBX  DD\t0\n\t_EDX  DD\t0\n\t_ECX  DD\t0\n\t_EAX  DD        0\n\tFLAGS DW\t0\n\t_ES   DW\t0\n\t_DS   DW\t0\n\t_FS   DW\t0\n\t_GS   DW\t0\n\t_IP   DW\t0\n\t_CS   DW\t0\n\t_SP   DW\t0\n\t_SS   DW\t0\n\t      dd\t0\n\t      dd\t0\n  nothing     dd\t0\t\nENDS \n\nRMDS RealModeCallStruc  <>\n\nCODESEG\n\nPROC\tKeyboard_Interrupt\tNear\n\n; This option of the keyboard interrupt handle will not be\n; available at this moment because the light version of Rational System DOS\n; Extender do not allow a DPMI real mode call which is\n; DMPI INT 31h funtion 0301h\n\n\tpushad\t\n\tpush\tfs gs es ds\n\n\tmov\tax , _DATA\n\tmov\tes , ax\n\tmov\tds , ax\n\n\tlea\tedi , [ RMDS ]\n\tlea\tecx , [ RMDS . nothing ]\n\tsub\tecx , edi\n\txor\teax , eax\n\tshr\tecx , 2\n\trep\tstosd\n\t\n\tmov\teax , 0300h\n\tmov\tbl , [ byte ptr RMVector ]\n\txor\tbh , bh\n\txor\tcx , cx\n\tlea\tedi , [RMDS]\n\tint\tDPMI_INTR\n\n; this is here only for testing to make sure\n; that a real mode interrupt is bieng issued. \nmov\tax , _DATA\nmov\tes , ax\nmov\tds , ax\nmov [ byte ptr 0b0000h + 10 * 80 + 40 ] , 040h\njc\t??error\nmov [ byte ptr 0b0000h + 10 * 80 + 42 ] , 041h\n\n??error:\n\tpop\tds es gs fs\n\tpopad\t\n\tiretd\n\tENDP\n\nENDIF\n\nLABEL \tLockedCodeEnd\t\tBYTE\n\n;***************************************************************************\n;* End of File.\t\t\t\t\t\t\t\t   *\n;***************************************************************************\nEND\n\n"
  },
  {
    "path": "WWFLAT32/SRCDEBUG/KEYIPROT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : KEYINTR.ASM                              *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   KeyNum_Translate -- Translates the given keynum to ???                *\n;*   Install_Interrupt -- Installs the keyboard interrupt                  *\n;*   Stuff_Key_Word -- Stuffs a word of data into keyboard buffer          *\n;*   Stuff_Key_Num -- Stuffs a key num code into the circular buffer       *\n;*   Remove_Interrupt -- Removes the keyboard interrupt and restores the chai*\n;*   Keystroke_Interrupt -- Handles input that comes from the keyboard     *\n;*   Break_Interrupt -- Handles the break key interrupt                    *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tKeyboard driver -- 8086 Assembly portion;\t\t\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   *\n;***************************************************************************\n\n;---------------------------------------------------------------------------\n; Set the assembly directives\n;---------------------------------------------------------------------------\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386N\t\t\t\t; use 386 real mode instructions\nMODEL TINY\t\t\t; code must be tiny so it fits\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keyboard.inc\"\n\nCODESEG\n\n\nSoundOn\t\tDW\t1\t; toggled by alt S\nMusicOn\t\tDW\t1\t; toggled by alt M\nKeyFlags\tDW\tREPEATON+CTRLALTTURBO\t; all but repeat for now\n\n\nBreak\t\tDW\t0\n\nKeyMouseMove\tDB\t-1,0,1\n\t\tDB\t-16,0,16\n\nScreenEdge\tDW\t320/2,0\t\t; North\n\t\tDW\t319,0\t\t; North-East\n\t\tDW\t319,138/2\t; East\n\t\tDW\t319,137\t\t; South-East\n\t\tDW\t320/2,137\t; South\n\t\tDW\t0,137\t\t; South-West\n\t\tDW\t0,138/2\t\t; West\n\t\tDW\t0,0\t\t; North-West\n\t\tDW\t320/2,138/2\t; Center\n\n\nBits\t\tDB\t01H,02H,04H,08H,10H,20H,40H,80H\n\nCondPassKey\tDW\t0220H, 0320H, 060CH, 070DH, 066AH\n\t\tDW\t0669H, 0230H, 0330H, 007DH, 017DH\n\t\tDW\t025AH, 035AH, 0200H, 0410H, 046EH\n\t\tDW\t026EH, 007CH\n\nCondPassCond\tDW\tCTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO\n\t\tDW\tCTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON\n\t\tDW\tPAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE\n\t\tDW\tTASKSWITCHABLE, BREAKON\n\nEscRoutine\tDD\t0\t; vector to execute on esc key press (0=none)\n\n; Extended raw keycodes to be converted to Westwood keycodes.\nExtCodes\tDB\t038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H\n\t\tDB\t051H,04DH,035H,01CH,037H\n\t\tDB\t046H\n; The matching Westwood keycodes.\nExtNums\t\tDB\t62,  64,  75,  76,  79,  80,  81,  83,  84,  85\n\t\tDB\t86,  89,  95, 108, 124,  0\n; If extended mapping is disabled, then these codes really are...\nExtRemap\tDB\t60,  58,  99, 104,  92,  91,  93,  96,  98, 101\n\t\tDB\t103, 102, 55,  43, 124,  0\nExtRemapEnd\tDB\t0\n\nExtKeyboard\tDB\t0\t; flag for 101/102-key keyboard\n\n\nKeyBuffer\tDW\t128 DUP(0) ; set to empty\nKeyBufferHead\tDW\t0\t; set to first entry\nKeyBufferTail\tDW\t0\t; set to head for empty buffer\nKeyLock\t\tDW\t0\t; num and caps lock bits\nKeyNums\t\tDB\t127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016\n\t\tDB\t017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032\n\t\tDB\t033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049\n\t\tDB\t050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116\n\t\tDB\t117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093\n\t\tDB\t098,103,099,104,127,127,127,122,123\n\nKeysCapsLock\tDB\t0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0\nKeysNumLock\tDB\t0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0\nKeysUpDown\tDB\t16 DUP(0) ; set to all keys up\nKeyStream\tDB\t16 DUP(0) ; set to all keys up\nPassCount\tDW\t0\nKeyStreamIndex\tDW\t0\nLastKeyE0\tDB\t0\nLastKeyE1\tDB\t0\n\n;\n; Westwood key number values of keys to pass through\n;\n;\t\t\tCAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT,\n;\t\t\tRIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN\nPassAlways\tDB\t30, 44, 57, 58, 60, 62, 64, 90, 128, 128\nPassAlwaysEnd\tDB\t128\t\t; invalid code to END PassAlways\nCtrlFlags\tDB\t0\n\nBuffer\t\tDW\t?\nTime\t\tDW\t?\n\nADJUST\t= 1\t\t\t; do not modify DRD\n\nXYAdjust\tDB\t-ADJUST, -ADJUST\t; 91 -> upleft\n\t\tDB\t-ADJUST,  0\t\t; 92 -> left\n\t\tDB\t-ADJUST,  ADJUST\t; 93 -> downleft\n\t\tDB\t 0,  0\t\t\t; 94 illegal\n\t\tDB\t 0,  0\t\t\t; 95 illegal\n\t\tDB\t 0, -ADJUST\t\t; 96 -> up\n\t\tDB\t 0,  0\t\t\t; 97 illegal (center)\n\t\tDB\t 0,  ADJUST\t\t; 98 -> down\n\t\tDB\t 0,  0\t\t\t; 99 illegal\n\t\tDB\t 0,  0\t\t\t; 100 illegal\n\t\tDB\t ADJUST, -ADJUST\t; 101 -> upright\n\t\tDB\t ADJUST,  0\t\t; 102 -> right\n\t\tDB\t ADJUST,  ADJUST\t; 103 -> downright\nEdgeConv\tDW\t8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7\n\nMouseUpdate\t\tDW\t0\nMouseX\t\t\tDW\t0\nLocalMouseX\t\tDW\t0\nMouseY\t\t\tDW\t0\nLocalMouseY\t\tDW\t0\nButton\t\t\tDW\t0\nIsExtKey\t\tDB\t0\nExtIndex\t\tDW\t0\n\nOldRMI\t\t\tDD\t0\t; The origianl RM interrupt seg:off.\nOldPMIOffset\t\tDD\t0\t; The origianl PM interrupt offset\t\t\nOldPMISelector\t\tDD\t0\t; The original PM interrupt segment.\n\nCodeOffset\t\tDW\tRM_Keystroke_Interrupt\t; Offset of the code in the RM stuff.\nCallRMIntOffset\t\tDW\tCall_Interrupt_Chain\t\t; Offset of function to call DOS timer interrupt.\nCallRMIntAddr\t\tDD\t0\t; PM address of CallRealIntOffset for speed.\n\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Translates the given keynum to ???                  *\n;*                                                                         *\n;* INPUT:\tUWORD the keynum to translate\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated keynum                                 *\n;*                                                                         *\n;* PROTO:\tUWORD KeyNum_Translate(UWORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tKeyNum_Translate:FAR\n\tPROC\tKeyNum_Translate C FAR \n\tUSES\tcx,di,es,ds\n\tARG\tkeycode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\tmov\tes,ax\t\t\t\t; set es up for scansb\n\n\tmov\tax,[keycode]\n\ttest\t[KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\tmov\tcx,ExtRemap-ExtNums\n\tmov\tdi,OFFSET ExtNums\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tdi,OFFSET ExtRemapEnd\n\tdec\tdi\n\tsub\tdi,cx\n\tmov\tal,[es:di]\n??fini:\n\tret\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(WORD code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_WORD:FAR\n\tPROC\tStuff_Key_WORD C FAR \n\tUSES\tsi,bx,ds\n\tARG\tcode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\tax,[KeyBufferTail]\n\tmov\tsi,ax\n\tadd\tax,2\n\tand\tax,0FFh\t\t\t\t; New KeyBufferTail value.\n\tcmp\t[KeyBufferHead],ax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[KeyBuffer+si],bx\t\t; Record the keystroke.\n\tmov\t[KeyBufferTail],ax\n\txor\tax,ax\n\tret\n\n??noroom:\n\tmov\tax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(WORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_Num:FAR\n\tPROC\tStuff_Key_Num C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds\n\tARG\tkeycode:WORD\n\tLOCAL\ttail:WORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n\tpushf\n\tcli\t\t\t\t; disable interrupts\n\n\t; Abort key recognition if in record mode and unable\n\t; to output key due to simultaneous DOS operation.\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\tax,[MouseX]\n\tmov\t[LocalMouseX],ax\n\tmov\tax,[MouseY]\n\tmov\t[LocalMouseY],ax\n\n??cando:\n\tmov\tax,[keycode]\t\t; get the code\n\tor\tax,ax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tbx,1\t\t\t; double for WORD index\n\tadd\tbx,OFFSET XYAdjust\n\tmov\tax,[bx]\t\t\t; get x,y add value\n\n\tmov\tbl,ah\n\tcbw\n\txchg\tax,bx\n\tcbw\n\txchg\tax,bx\t\t\t; AX = mouse x delta, BX = mouse y delta\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tdx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tdx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tbx,dx\t\t\t; add speed for y index\n\tmov\tbl,[KeyMouseMove+bx] \t; get speed for y delta\n\txchg\tax,bx\t\t\t; swap with ax to extend sign\n\tcbw\n\txchg\tax,bx\n\txchg\tbx,dx\t\t\t; save mouse y delta\n\tadd\tbx,ax\t\t\t; add speed for x index\n\tmov\tal,[KeyMouseMove+bx]\t; get speed for x delta\n\tcbw\n\txchg\tbx,dx\t\t\t; restore mouse y delta\n\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tbx,011b\t\t\t; Y = 1, 0, 3\n\tand\tax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tbx,011b\t\t\t; Y = 3, 0, 1\n\tand\tax,011b\t\t\t; X = 3, 0, 1\n\tshl\tbx,1\n\tshl\tbx,1\n\tor\tbx,ax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tbx,1\n\tmov\tbx,[EdgeConv+bx]\n\tshl\tbx,1\n\tshl\tbx,1\n\tmov\tax,[ScreenEdge+bx]\t; New absolute X\n\tmov\tbx,[ScreenEdge+bx+2] ; New absolute Y\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\tax,ax\n\tmov\t[LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tbx,bx\n\tmov\t[LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\tmov\t[MouseX],ax\n\tmov\t[MouseY],bx\n\tcmp\t[MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n; PWG: ARRGGGHHHH!\n;\tcall\tLow_Hide_Mouse\n;\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\tax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],ax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tsi,[KeyBufferTail]\n\tmov\t[tail],si\t\t; Safety record.\n\tmov\tdi,[KeyBufferHead]\n\n\t; Record the base keycode (if there is room).\n\tpush\tax\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\tax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tpush\t[LocalMouseX]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tpush\t[LocalMouseY]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tbx,0101h\t\t; Bit control tools.\n\tmov\tax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tmov\tcl,3\n\tshr\tdi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[KeysUpDown+di]\n\tje\tshort ??notalready\n\ttest\t[KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\t[KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[KeysUpDown+di],bh\t; Force key bit to zero.\n\tor\t[KeysUpDown+di],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\tax,1\n\tjmp short ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\tax,[tail]\n\tmov\t[KeyBufferTail],ax\n\txor\tax,ax\t\t\t; Signal an error.\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tStuff_Key_Num\n;***********************************************************\n\n\n\n;***************************************************************************\n;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard       *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Keystroke_Interrupt\n\tGLOBAL\tC Keystroke_Interrupt:FAR\n\tPROC\tKeystroke_Interrupt C FAR \n\nIF 0\n\tpush\tax\n\tinc\tax\n\tpop\tax\n\tiret\n\nELSE\n\tpush\tax\n\tpush\tbx\n\tpush\tcx\n\tpush\tdi\n\tpush\tds\n\tpush\tdx\n\tpush\tes\n\tpush\tsi\n\tcld\n\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tds,ax\n\tmov\tdx,[KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\tmov\tax,040H\t\t\t; BIOS segment\n\tmov\tes,ax\t\t\t; put in es\n\ttest\t[BYTE PTR es:017H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR es:017H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR es:096H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tes,ax\n\n\tcld\t\t\t\t; clear direction flag for strings\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tbx,0101H\t\t; set key to a make by default\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\n\t;\n\t; New CODE to montior key stream\n\t;\n\tmov\tbx,[KeyStreamIndex]\n\tmov\t[KeyStream+bx],al\n\tinc\tbx\n\tand\tbx,15\n\tmov\t[KeyStreamIndex],bx\n\tmov\tbx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[LastKeyE1]\t\t; yes, dec the count\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[IsExtKey],TRUE\t; it is an extended key\n\tmov\tdi,OFFSET ExtCodes\t; get offset of extended codes table\n\tmov\tcx,(ExtNums-ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\tmov\tal,[(ExtNums - ExtCodes) - 1 + di] ; get the match\n\tmov\t[IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tdi,ax\t\t\t; use code as an index\n\tand\tdi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[KeyNums+di]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[KeysUpDown+8],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[KeysUpDown+7],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[KeysUpDown + 7],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\tax\n\tcall\tKeyNum_Translate\n\tadd\tsp,2\n\n;------\tSet the shift bit if necessary.\n\ttest\t[KeysUpDown+5],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[KeysUpDown+7],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tshr\tdi,1\n\tshr\tdi,1\n\tshr\tdi,1\n\tmov\tbx,ax\n\tand\tbx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[Bits+bx]\t\t; get the bit to test\n\ttest\t[KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[KeysCapsLock+di]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[KeysNumLock+di]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\n\t\t\t\t\t; keyboard buffer.\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\tax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\tax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\tax,0230h\n\tje\tshort ??breaker\n\tcmp\tax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n\tcmp\tax,0420H\t\t; is this an alt s\n\tjne\tshort ??checkmusic\t; toggle the Sound variable\n\tpush\tax\n\tmov\tax,[SoundOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??checkmusic:\n\tcmp\tax,0434H\t\t; is this an alt m\n\tjne\tshort ??esc\t\t; toggle the Music variable\n\tpush\tax\n\tmov\tax,[MusicOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??esc:\n\n\tpush\tax\n\tcall\tStuff_Key_Num\n\tpop\tax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\tax\n\tcall\t[EscRoutine]\n\tpop\tax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tdi,OFFSET PassAlways\t; get offset to table\n\tmov\tcx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1\n\trepne\tscasb\t\t\t; look for a match\n\tor\tcx,cx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n\n\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tdi,OFFSET CondPassKey\t; get offset to cond key table\n\tmov\tcx,(CondPassCond-CondPassKey) ; get number of entries\n\tshr\tcx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(CondPassCond - CondPassKey) - 2 + di]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tdx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n;***********************************************************\n\tpushf\n;\tpush\tdi\n;\tpush\tes\n\t\n\tmov\tax,0B000h\n\tmov\tes,ax\n\tinc\t[BYTE PTR es:0]\n\n;\tpop\tes\n;\tpop\tdi\n\tpopf\n;***********************************************************\n\n??passcode:\n\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tinc\t[cs:PassCount]\n\tjmp\t[cs:OldRMI]\n\n??absorbcode:\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tax,040h\t\t\t\t; BIOS paragraph is always @ 040h\n\tmov\tes,ax\t\t\t\t; put in es as BIOS paragraph\n\tmov\tal,[es:96h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[es:96h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tiret\t\nENDIF\n\n\tENDP\tKeystroke_Interrupt\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles the break key interrupt                      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Break_Interrupt:FAR\n\tPROC\tBreak_Interrupt C FAR\n\n\tiret\t\n\n\tENDP\tBreak_Interrupt\n\n;**************************************************************************\n;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nCall_Interrupt_Chain:\nIF 0\n\tpushf\n\tpush\tax\n\tpush\tdi\n\tpush\tes\n\n\tmov\tax,0B000h\t\t; ES:DI = Mono RAM address.\n\tmov\tes,ax\n\t\t\n\tmov\tal,'A'\n\tmov\tah,2\n\tand\tdi,63\n\n\tstosw\n\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\tmov\tal,CLEARISR\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t; 8259 interrupt chip controller 0\n\n\n\tpop\tes\n\tpop\tdi\n\tpop\tax\n\tpopf\nENDIF\n\tpushf\n\tcall\tKeystroke_Interrupt ;[OldRMI]\n\tretf\n\nSTACK\t   ; Don't really need this\n\n;***********************************************************\nEND\n"
  },
  {
    "path": "WWFLAT32/SRCDEBUG/KEYIREAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*\t\t\t\t  (Mouse Routines)\n;*                                                                         *\n;*                    File Name : KEYIREAL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Philip W. Gorrow                         *\n;*                                                                         *\n;*                   Start Date : May 21, 1992                             *\n;*                                                                         *\n;*                  Last Update : July 13, 1994   [PWG]                    *\n;*                                                                         *\n;* This file sort of breaks the standard of keeping all of the keyboard    *\n;* and mouse routines isolated.  This is done because the mouse and\t   *\n;* the keyboard share data, and the best way to do this is to put\t   *\n;* them in the same segment.  This should probably be split into several   *\n;* include files to help make the code clearer once it is finally put\t   *\n;* together.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   KeyNum_Translate -- Translates extended keynums to normal keynums\t   *\n;*   Stuff_Key_Word -- Stuffs a word of data into keyboard buffer          *\n;*   Stuff_Key_Num -- Stuffs a key num code into the circular buffer       *\n;*   Keystroke_Interrupt -- Real mode handler of input from the keyboard   *\n;*   Break_Interrupt -- Handles the break key interrupt                    *\n;*   Call_Interrupt_Chain -- Function PM calls to call RM interrupt chain  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tKeyboard driver -- 8086 Assembly portion;\t\t\t   *\n;*\tupdated by: Phil Gorrow for 32 bit Protected Mode\t\t   *\n;***************************************************************************\n\n;---------------------------------------------------------------------------\n; Set the assembly directives\n;---------------------------------------------------------------------------\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386N\t\t\t\t; use 386 real mode instructions\nMODEL TINY\t\t\t; code must be tiny so it fits\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keyboard.inc\"\n\nCONDHIDE\t\tEQU\t08000H\t\t; bit for testing conditional region\nCONDHIDDEN\t\tEQU\t04000H\t\t; bit for testing conditional hidden\nRESTORE_VISIBLE_PAGE\tEQU\t0\nSTORE_VISIBLE_PAGE\tEQU\t1\n\n\nGLOBAL\tset_vesa_page \t:near\nGLOBAL\tset_vesa_window :near\nGLOBAL\tget_vesa_window :near\nGLOBAL\tnext_vesa_page\t:near\n\nECHOON\tequ 0\n;---------------------------------------------------------------------------\n; WARNING!!!!  All of the following code segment variables are shared by\n;   the protected mode interrupt.  Do not change these unless you make the\n;   proper changes to KEYSTRUC.INC.  If you do not know what you are doing,\n;   find someone who does!!!\n;---------------------------------------------------------------------------\nCODESEG\n\n;---------------------------------------------------------------------------\n; Begin definition of Keyboard specific variables\n;---------------------------------------------------------------------------\nSoundOn\t\tDW\t1\t; toggled by alt S\nMusicOn\t\tDW\t1\t; toggled by alt M\nKeyFlags\tDD\tREPEATON+CTRLALTTURBO\t; all but repeat for now\n\n\nBreak\t\tDW\t0\n\nKeyMouseMove\tDB\t-1,0,1\n\t\tDB\t-16,0,16\n\nScreenEdge\tDW\t320/2,0\t\t; North\n\t\tDW\t319,0\t\t; North-East\n\t\tDW\t319,138/2\t; East\n\t\tDW\t319,137\t\t; South-East\n\t\tDW\t320/2,137\t; South\n\t\tDW\t0,137\t\t; South-West\n\t\tDW\t0,138/2\t\t; West\n\t\tDW\t0,0\t\t; North-West\n\t\tDW\t320/2,138/2\t; Center\n\n\nBits\t\tDB\t01H,02H,04H,08H,10H,20H,40H,80H\n\nCondPassKey\tDW\t0220H, 0320H, 060CH, 070DH, 066AH\n\t\tDW\t0669H, 0230H, 0330H, 007DH, 017DH\n\t\tDW\t025AH, 035AH, 0200H, 0410H, 046EH\n\t\tDW\t026EH, 007CH\n\nCondPassCond\tDW\tCTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO\n\t\tDW\tCTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON\n\t\tDW\tPAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE\n\t\tDW\tTASKSWITCHABLE, BREAKON\n\nEscRoutine\tDD\t0\t; vector to execute on esc key press (0=none)\n\n; Extended raw keycodes to be converted to Westwood keycodes.\nExtCodes\tDB\t038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H\n\t\tDB\t051H,04DH,035H,01CH,037H\n\t\tDB\t046H\n; The matching Westwood keycodes.\nExtNums\t\tDB\t62,  64,  75,  76,  79,  80,  81,  83,  84,  85\n\t\tDB\t86,  89,  95, 108, 124,  0\n; If extended mapping is disabled, then these codes really are...\nExtRemap\tDB\t60,  58,  99, 104,  92,  91,  93,  96,  98, 101\n\t\tDB\t103, 102, 55,  43, 124,  0\nExtRemapEnd\tDB\t0\n\nExtKeyboard\tDB\t0\t; flag for 101/102-key keyboard\n\n\nKeyBuffer\tDW\t128 DUP(0) ; set to empty\nKeyBufferHead\tDD\t0\t; set to first entry\nKeyBufferTail\tDD\t0\t; set to head for empty buffer\nKeyLock\t\tDW\t0\t; num and caps lock bits\nKeyNums\t\tDB\t127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016\n\t\tDB\t017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032\n\t\tDB\t033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049\n\t\tDB\t050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116\n\t\tDB\t117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093\n\t\tDB\t098,103,099,104,127,127,127,122,123\n\nKeysCapsLock\tDB\t0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0\nKeysNumLock\tDB\t0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0\nKeysUpDown\tDB\t16 DUP(0) ; set to all keys up\nKeyStream\tDB\t16 DUP(0) ; set to all keys up\nPassCount\tDW\t0\nKeyStreamIndex\tDW\t0\nLastKeyE0\tDB\t0\nLastKeyE1\tDB\t0\n\n;\n; Westwood key number values of keys to pass through\n;\n;\t\t\tCAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT,\n;\t\t\tRIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN\nPassAlways\tDB\t30, 44, 57, 58, 60, 62, 64, 90, 128, 128\nPassAlwaysEnd\tDB\t128\t\t; invalid code to END PassAlways\nCtrlFlags\tDB\t0\n\nBuffer\t\tDW\t?\nTime\t\tDW\t?\n\nADJUST\t= 1\t\t\t; do not modify DRD\n\nXYAdjust\tDB\t-ADJUST, -ADJUST\t; 91 -> upleft\n\t\tDB\t-ADJUST,  0\t\t; 92 -> left\n\t\tDB\t-ADJUST,  ADJUST\t; 93 -> downleft\n\t\tDB\t 0,  0\t\t\t; 94 illegal\n\t\tDB\t 0,  0\t\t\t; 95 illegal\n\t\tDB\t 0, -ADJUST\t\t; 96 -> up\n\t\tDB\t 0,  0\t\t\t; 97 illegal (center)\n\t\tDB\t 0,  ADJUST\t\t; 98 -> down\n\t\tDB\t 0,  0\t\t\t; 99 illegal\n\t\tDB\t 0,  0\t\t\t; 100 illegal\n\t\tDB\t ADJUST, -ADJUST\t; 101 -> upright\n\t\tDB\t ADJUST,  0\t\t; 102 -> right\n\t\tDB\t ADJUST,  ADJUST\t; 103 -> downright\n\tEdgeConv\t\tDW\t8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7\n\tMouseUpdate\t\tDW\t0\n\tMouseX\t\t\tDW\t0,0\n\tLocalMouseX\t\tDW\t0\n\tMouseY\t\t\tDW\t0,0\n\tLocalMouseY\t\tDW\t0\n\tIsExtKey\t\tDB\t0\n\tExtIndex\t\tDW\t0\n\n\tKeyOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tKeyOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\t\t\n\tKeyOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tKeyCodeOffset\t\tDW\tRM_Keystroke_Interrupt\t; Offset of the code in the RM stuff.\n\tCallKeyRMIntOffset\tDW\tCall_Interrupt_Chain\t; Offset of function to call DOS timer interrupt.\n\tCallKeyRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedKeyInt\t\tDD\t0\n\n\tBrkOldRMI\t\tDD\t0\t\t\t; The origianl RM interrupt seg:off.\n\tBrkOldPMIOffset\t\tDD\t0\t\t\t; The origianl PM interrupt offset\t\t\n\tBrkOldPMISelector\tDD\t0\t\t\t; The original PM interrupt segment.\n\n\tBrkCodeOffset\t\tDW\tRM_Break_Interrupt\t; Offset of the code in the RM stuff.\n\tCallBrkRMIntOffset\tDW\t0\n\tCallBrkRMIntAddr\tDD\t0\t\t\t; PM address of CallRealIntOffset for speed.\n\tPMIssuedBrkInt\t\tDD\t0\n\tKeyIntDisabled\t\tDD\t0\n\n\tDbgOldPMIOffset\t\tDD\t0\t; The origianl PM interrupt offset\t\t\n\tDbgOldPMISelector\tDD\t0\t; The original PM interrupt segment.\n\n;---------------------------------------------------------------------------\n; Begin definition of Mouse Specific Variables for real mode\n;---------------------------------------------------------------------------\nButton\t\t\tDB\t0\t; current value of the mouse button\nMDisabled\t\tDB\t0\t; Is the mouse driver disabled\nMInput\t\t\tDB\t1\t; Defaults to mouse input allowed.\nAdjust\t\t\tDW\t0\t; flag to adjust coordinates if necessary\nMouseStepX\t\tDW\t0\t; step values if the mouse moves at\nMouseStepY\t\tDW\t0\t;   more than one pixel at a time\nMouseOffsetX\t\tDW\t0\t; Fractional step values used if a mouse\nMouseOffsetY\t\tDW\t0\t;   moves at less than one pixel at a time\nMState\t\t\tDW\t0,0\t; Tracks if mouse is hidden (TRUE) or not (FALSE)\nMouseXOld     \t\tDW\t0\t; Holds last MouseX and MouseY to determine if \nMouseYOld     \t\tDW\t0\t;   mouse needs to be redrawn\nMCState\t\t\tDW\t0\t; Tracks if mouse conditional hidden (TRUE) or not\nMouseCXLeft\t\tDW\t0,0\t; Conditional hide mouse left x position\nMouseCYUpper\t\tDW\t0,0\t; Conditional hide mouse top y position\nMouseCXRight\t\tDW\t0,0\t; Conditional hide mouse right x position\nMouseCYLower\t\tDW\t0,0\t; Conditional hide mouse lower y position\nMouseCursor   \t\tDD\t0\t; Pointer to the mouse cursor to draw\nMouseCursorSize\t\tDW\t0\t; Pointer to buffer mouse is saved in\nMouseBuffer   \t\tDD\t0\t; Pointer to buffer mouse is saved in\nMouseXHot     \t\tDW\t0,0\t; Offset to mouse's x hot spot\nMouseYHot     \t\tDW\t0,0\t; Offset to mouse's y hot spot\nMouseBuffX\t\tDW\t0,0\t; X position background was saved at\nMouseBuffY\t\tDW\t0,0\t; Y position background was saved at\nMouseBuffW\t\tDW\t0,0\t; Width of the region saved for mouse\nMouseBuffH\t\tDW\t0,0\t; Height of the region saved for mouse\nMouseWidth\t\tDW\t0,0\t; Mouse cursor theoretical width\nMouseHeight\t\tDW\t0,0\t; Mouse cursor theoretical height\nMouseCodeOffset\t\tDW\tRM_Mouse_Interrupt\t; Offset of the code in the RM stuff.\nMouseRight\t\tDW\t0,0\nMouseBottom\t\tDW\t0,0\n\n\nShadowPtr\t\tdw\t0\nDrawMousePtr \t\tdw\t0\n\nVGAMouseDraw\t\tdw\tVGA_Draw_Mouse\nVGAMouseShadow\t\tdw\tVGA_Mouse_Shadow_Buffer\n\nVESAMouseDraw\t\tdw\tVESA_Draw_Mouse\nVESAMouseShadow\t\tdw\tVESA_Mouse_Shadow_Buffer\n\nVesaPtr\t\t\tdd\t0\t\nbanktable\t\tdd      8 dup ( 0 )\nAdjust_XPos\t\tdw \t0 , 0\nAdjust_YPos\t\tdw \t0 , 0 \n\n\t\talign 2\nKeyboard_App_Stack_ES\tdw 0\t\t; This the System Stack Offsset\nKeyboard_App_Stack_SS\tdw 0\t\t; This the System Stack Selector\nKeyboard_StackPointer\tdw 0DEADh\t; We Create a Local Application\nKeyboard_Stack\t\tdw 512 dup (0)\nKeyboard_StackStart\tdw 0\n\nMouse_State\t\tdw 0\t\t; Mouse Temp Variable\nMouse_Cond\t\tdw 0\t\t; Mouse Temp Variable\nMouse_App_Stack_ES\tdw 0\t\t; This the System Stack Offsset\nMouse_App_Stack_SS\tdw 0\t\t; This the System Stack Selector\nMouse_StackPointer\tdw 0DEADh\t; We Create a Local Application\nMouse_Stack\t\tdw 512 dup (0)\nMouse_StackStart\tdw 0\n\n\n\ncurrent_page\t\tdw\t0\n;***************************************************************************\n;* KEYNUM_TRANSLATE -- Translates extended keynums to normal keynums\t   *\n;*                                                                         *\n;* INPUT:\tUWORD the keynum to translate\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tWORD the translated keynum                                 *\n;*                                                                         *\n;* PROTO:\tUWORD KeyNum_Translate(UWORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tKeyNum_Translate:FAR\n\tPROC\tKeyNum_Translate C FAR \n\tUSES\tcx,di,es,ds\n\tARG\tkeycode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\tmov\tes,ax\t\t\t\t; set es up for scansb\n\n\tmov\tax,[keycode]\n\ttest\t[WORD PTR KeyFlags],TRACKEXT\n\tjne \tshort ??fini\n\n\tmov\tcx,ExtRemap-ExtNums\n\tmov\tdi,OFFSET ExtNums\n\n\trepne\tscasb\n\tjcxz\tshort ??fini\t\t\t; No match found.\n\n\tmov\tdi,OFFSET ExtRemapEnd\n\tdec\tdi\n\tsub\tdi,cx\n\tmov\tal,[es:di]\n??fini:\n\tret\n\tENDP\tKeyNum_Translate\n\n;***************************************************************************\n;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *\n;*                                                                         *\n;* INPUT:\tWORD the code to stick into the circular buffer            *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_WORD(WORD code);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_WORD:FAR\n\tPROC\tStuff_Key_WORD C FAR \n\tUSES\tsi,bx,ds\n\tARG\tcode:WORD\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\tax,[WORD PTR KeyBufferTail]\n\tmov\tsi,ax\n\tadd\tax,2\n\tand\tax,0FFh\t\t\t\t; New KeyBufferTail value.\n\tcmp\t[WORD PTR KeyBufferHead],ax\n\tje \tshort ??noroom\n\n\tmov\tbx,[code]\n\tmov\t[KeyBuffer+si],bx\t\t; Record the keystroke.\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\n\tret\n\n??noroom:\n\tmov\tax,1\n\tret\n\n\tENDP\tStuff_Key_WORD\n\n;***************************************************************************\n;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *\n;*                                                                         *\n;* INPUT:\tWORD the keycode to stuff                                  *\n;*                                                                         *\n;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room\t\t   *\n;*                                                                         *\n;* PROTO:\tVOID Stuff_Key_Num(WORD keynum);\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Stuff_Key_Num:FAR\n\tPROC\tStuff_Key_Num C FAR \n\tUSES\tbx,cx,dx,di,si,ds\n\tARG\tkeycode:WORD\n\tLOCAL\ttail:WORD\t\t; Original keybuffer tail (safety copy).\n\tLOCAL\tsize:WORD\t\t; Size of write.\n\n\tpushf\n\tcli\t\t\t\t; disable interrupts\n\n\t; Abort key recognition if in record mode and unable\n\t; to output key due to simultaneous DOS operation.\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\n\t; Record the mouse position to be stuffed into buffer.\n\tmov\tax,[MouseX]\n\tmov\t[LocalMouseX],ax\n\tmov\tax,[MouseY]\n\tmov\t[LocalMouseY],ax\n\n??cando:\n\tmov\tax,[keycode]\t\t; get the code\n\tor\tax,ax\t\t\t; Null keycodes are not recorded.\n\tjne\tshort ??validkey\n\tjmp\t??exit\n\n\n??validkey:\n\n\ttest\t[WORD PTR KeyFlags],KEYMOUSE\t; is the numeric keypad moving the mouse?\n\tje\t??no_pad_move\n\n\t; ALT-cursor keys are undefined.  Pass them on to the program.\n\ttest\tah,ALTPRESS\t\t; is either alt key down?\n\tjne\t??no_pad_move\n\n\ttest\t[WORD PTR KeyFlags],SIMLBUTTON\t; are we simulating left mouse presses\n\tje\tshort ??chkinsert\n\n\tcmp\tal,KN_RETURN\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_SPACE\n\tje\tshort ??forceleft\n\n\tcmp\tal,KN_KEYPAD_RETURN\n\tje\tshort ??forceleft\n\n??chkinsert:\n\tcmp\tal,KN_INSERT\n\tjne\tshort ??regular\n\n??forceleft:\n\tmov\tal,KN_LMOUSE\n\tor\t[Button],1\t\t; Left mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 1\n\tjmp\t??mousefake\n\n??regular:\n\tcmp\tal,KN_DELETE\n\tjne\tshort ??regular2\n\tmov\tal,KN_RMOUSE\n\tor\t[Button],2\t\t; Right mouse bit.\n\ttest\tah,KEYRELEASE\n\tje\t??mousefake\n\tand\t[Button],NOT 2\n\tjmp\t??mousefake\n\n??regular2:\n\t; DRD correction to ignore key releases for key mouse movement\n\ttest\tah,KEYRELEASE\n\tjne\t??no_pad_move\n\n\tcmp\tal,KN_CENTER\n\tje\tshort ??pad_move\n\tcmp\tal,KN_UPLEFT\t\t; less than upleft?\n\tjb\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNRIGHT\t\t; greater than downright?\n\tja\t??no_pad_move\t\t; yes, then it isn't a keypad key\n\tcmp\tal,KN_DOWNLEFT\t\t; is it UPLEFT, LEFT, or DOWNLEFT?\n\tjbe\tshort ??pad_move\n\tcmp\tal,KN_UPRIGHT\t\t; is it UPRIGHT, RIGHT, or DOWNRIGHT?\n\tjae\tshort ??pad_move\n\tcmp\tal,KN_UP\t\t; up?\n\tje\tshort ??pad_move\n\tcmp\tal,KN_DOWN\t\t; down?\n\tjne\t??no_pad_move\n\n??pad_move:\n\t; DRD correction to use ch for ah\n\tmov\tch,ah\t\t\t; save shift-ctrl-alt-rlse status\n\n\txor\tah,ah\t\t\t; get rid of any bits\n\tsub\tal,KN_UPLEFT\t\t; get a number between 0 and 12\n\tmov\tbx,ax\n\tshl\tbx,1\t\t\t; double for WORD index\n\tadd\tbx,OFFSET XYAdjust\n\tmov\tax,[bx]\t\t\t; get x,y add value\n\n\tmov\tbl,ah\n\tcbw\n\txchg\tax,bx\n\tcbw\n\txchg\tax,bx\t\t\t; AX = mouse x delta, BX = mouse y delta\n\n\t; DRD correction to use ch\n\t; The CTRL key moves the mouse to the edge of the screen.\n\ttest\tch,CTRLPRESS\t\t; is either ctrl key down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\n\t; DRD correction to use ch\n\t; use fast speed of the mouse move if the shift key is held down.\n\tmov\tdx,1\t\t\t; for slow speed\n\ttest\tch,SHIFTPRESS\t\t; is either shift key down?\n\tje\tshort ??normspeed\t; if not then neither shift is down\n??doublespeed:\n\tadd\tdx,3\t\t\t; for fast speed\n??normspeed:\n\tadd\tbx,dx\t\t\t; add speed for y index\n\tmov\tbl,[KeyMouseMove+bx] \t; get speed for y delta\n\txchg\tax,bx\t\t\t; swap with ax to extend sign\n\tcbw\n\txchg\tax,bx\n\txchg\tbx,dx\t\t\t; save mouse y delta\n\tadd\tbx,ax\t\t\t; add speed for x index\n\tmov\tal,[KeyMouseMove+bx]\t; get speed for x delta\n\tcbw\n\txchg\tbx,dx\t\t\t; restore mouse y delta\n\n\tjmp\tshort ??ctrloff\n\n??ctrlon:\n\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded for an ADJUST\n\t; value of 3.  If this value changed, then this section will also\n\t; have to be modified.\n\tand\tbx,011b\t\t\t; Y = 1, 0, 3\n\tand\tax,011b\t\t\t; X = 1, 0, 3\n\t; Table lookup method for determining hotkey positions for CTRL\n\t; cursor combination.  This algorithm is hard coded.\n\t\t\t\t\t;    -1, 0, 1\n\tand\tbx,011b\t\t\t; Y = 3, 0, 1\n\tand\tax,011b\t\t\t; X = 3, 0, 1\n\tshl\tbx,1\n\tshl\tbx,1\n\tor\tbx,ax\t\t\t; Lookup index.\n\n\t; Convert raw index into logical (clockwise) index.\n\tshl\tbx,1\n\tmov\tbx,[EdgeConv+bx]\n\tshl\tbx,1\n\tshl\tbx,1\n\tmov\tax,[ScreenEdge+bx]\t; New absolute X\n\tmov\tbx,[ScreenEdge+bx+2] ; New absolute Y\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\n??set_xyz:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tjmp\tshort ??set_xy\n\n\t; Process a normal faked mouse move.\n??ctrloff:\n\t; DRD change\n\tadd\t[LocalMouseX],ax\t; save it in our local\n\tjns\tshort ??not_negative_x\n\txor\tax,ax\n\tmov\t[LocalMouseX],ax\t; clear our local\n\n??not_negative_x:\n; DRD change\n\tadd\t[LocalMouseY],bx\t; save it in our local\n\tjns\tshort ??not_negative_y\n\txor\tbx,bx\n\tmov\t[LocalMouseY],bx\t; clear our local\n\n??not_negative_y:\n\tmov\tax,[LocalMouseX]\t; get new mouse x,y\n\tmov\tbx,[LocalMouseY]\n\tcmp\tax,MAX_X_PIXEL\t\t; bigger than\n\tjle\tshort ??check_y\n\tmov\tax,MAX_X_PIXEL\n\n??check_y:\n\tcmp\tbx,MAX_Y_PIXEL\t\t; bigger than\n\tjle\tshort ??set_xy\n\tmov\tbx,MAX_Y_PIXEL\n\n??set_xy:\n\tmov\t[LocalMouseX],ax\n\tmov\t[LocalMouseY],bx\n\tmov\t[MouseX],ax\n\tmov\t[MouseY],bx\n\tcmp\t[MouseUpdate],0\t; wait until mouse interrupt is done\n\tjne\tshort ??noshow\n\n\tcall\tLow_Hide_Mouse\n\tcall\tLow_Show_Mouse\n??noshow:\n\tmov\tax,KN_MOUSE_MOVE\n??mousefake:\n\tmov\t[keycode],ax\t\t; Fake a MOUSE_MOVE event.\n\n??no_pad_move:\n\t; Fetch working pointers to the keyboard ends.\n\tmov\tsi,[WORD KeyBufferTail]\n\tmov\t[tail],si\t\t; Safety record.\n\tmov\tdi,[WORD PTR KeyBufferHead]\n\n\t; Record the base keycode (if there is room).\n\tpush\tax\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\tshort ??jmpnoroom\n\n\t; Also record the mouse coordinates if necessary.\n\tmov\tax,[keycode]\t\t; get key code\n\tcmp\tal,KN_MOUSE_MOVE\t; mouse move?\n\tje\tshort ??recordmouse\t; yes? then record the mouse cooordinates\n\tcmp\tal,KN_LMOUSE\n\tje\tshort ??recordmouse\n\tcmp\tal,KN_RMOUSE\n\tje\tshort ??recordmouse\n\tjmp\tshort ??ok\n??jmpnoroom:\n\tjmp\t??noroom\n\n\t; Record mouse coordinate X.\n??recordmouse:\n\tpush\t[LocalMouseX]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\n\t; Record mouse coordinate Y.\n\tpush\t[LocalMouseY]\n\tcall\tStuff_Key_WORD\n\tadd\tsp,2\n\tor\tax,ax\n\tjne\t??jmpnoroom\n\tadd\t[size],2\n\t\n??ok:\n\t; If PASSBREAKS is not active and this is a keyboard\n\t; break AND it is not a mouse event, then don't put\n\t; it into the buffer.\n\tmov\tbx,0101h\t\t; Bit control tools.\n\tmov\tax,[keycode]\n\tcmp\tal,KN_MOUSE_MOVE\n\tje \tshort ??notreal\n\tcmp\tal,127\n\tje\tshort ??notreal\n\ttest\tah,KEYRELEASE\n\tje\tshort ??real\n\txor\tbl,bl\n\ttest\t[WORD PTR KeyFlags],PASSBREAKS\n\tjne \tshort ??real\n\tcmp\tal,KN_LMOUSE\n\tje \tshort ??real\n\tcmp\tal,KN_RMOUSE\n\tje \tshort ??real\n??notreal:\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??real:\n\n\t; Update the KeysUpDown bit array.\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tmov\tcl,3\n\tshr\tdi,cl\t\t\t; DI = Byte offset into bit table.\n\tmov\tcl,al\n\tand\tcl,0111b\t\t; CL = Bit offset into bit table byte.\n\tshl\tbx,cl\n\tnot\tbh\n\n\t; If this is a reapeat key and the key is already being held\n\t; down, then don't stuff it into the keyboard buffer.\n\ttest\tbl,[KeysUpDown+di]\n\tje\tshort ??notalready\n\ttest\t[WORD PTR KeyFlags],REPEATON\n\tjne\tshort ??notalready\n\tmov\t[WORD PTR KeyBufferTail],si\t; Nullify any KeyBufferTail changes.\n??notalready:\n\tand\t[KeysUpDown+di],bh\t; Force key bit to zero.\n\tor\t[KeysUpDown+di],bl\t; Insert key bit as appropriate.\n;??notreal:\n\n\t; Successful keybuffer stuff could result in a\n??norecord:\n\tmov\tax,1\n\tjmp short ??exit\n\n\t; Unsuccessful keybuffer stuff.\n??noroom:\n\tmov\tax,[tail]\n\tmov\t[WORD PTR KeyBufferTail],ax\n\txor\tax,ax\t\t\t; Signal an error.\n\n??exit:\n\tpopf\n\tret\n\n\tENDP\tStuff_Key_Num\n;***********************************************************\n\n\n\n;***************************************************************************\n;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard       *\n;*                                                                         *\n;* This routine intercepts the key codes on their way to the\t\t   *\n;* BIOS.  With the adjustment of the Flags described above\t\t   *\n;* you can get a wide variety of effects.\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt function                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Keystroke_Interrupt\n\tGLOBAL\tC Keystroke_Interrupt:FAR\n\tPROC\tKeystroke_Interrupt C FAR \n\nIF 0\n\tpush\tax\n\tinc\tax\n\tpop\tax\n\tiret\n\nELSE\n\tpush\tax\n\tpush\tbx\n\tpush\tcx\n\tpush\tdi\n\tpush\tds\n\tpush\tdx\n\tpush\tes\n\tpush\tsi\n\tcld\n\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tds,ax\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov cx, ss\t\t\t\t; get SS\n\tmov [Keyboard_App_Stack_ES], sp\t\t; Protect ES\n\tmov [Keyboard_App_Stack_SS], cx\t\t; Protect SS\n\tlea dx, [Keyboard_StackStart ]\t\t; Compute Local Stack size\n\tand dx, -2;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov sp, dx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n\tcmp\t[WORD PTR PMIssuedKeyInt],0; Check to see if PM made Int call.\n\tmov\t[WORD PTR PMIssuedKeyInt],0; Make it false.\t\t\n\tjne\t??passcode\t; if so, just call Int Chain.\n\n\n\tmov\tdx,[WORD PTR KeyFlags]\n\t;*** The following fix allows proper caps and num lock tracking on Tandy\n\t; 10-6-89 LJC, DRD\n\t\t\t\t\t\n\tand\t[KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive\n\tmov\tax,040H\t\t\t; BIOS segment\n\tmov\tes,ax\t\t\t; put in es\n\ttest\t[BYTE PTR es:017H],040H\t; test Caps lock bit in BIOS\n\tje\tshort ??bioscapsoff\t; skip activate code\n\tor\t[KeyLock],CAPSLOCK\t; Caps Lock active\n\n??bioscapsoff:\n\ttest\t[BYTE PTR es:017H],020H\t; test Num lock bit in BIOS\n\tje\tshort ??biosnumoff\t; skip activate code\n\tor\t[KeyLock],NUMLOCK \t; Num Lock active\n\n??biosnumoff:\n\tmov\t[ExtKeyboard],TRUE \t; assume 101/102-key keyboard\n\ttest\t[BYTE PTR es:096H],010H\t; test for 101/102-key keyboard\n\tjne\tshort ??extkeyboard\t; skip deactivate code\n\tmov\t[ExtKeyboard],FALSE \t; no 101/102-key keyboard\n\n??extkeyboard:\n\tmov\tax,cs\t\t\t; set ds to cs to avoid cs overide\n\tmov\tes,ax\n\n\tcld\t\t\t\t; clear direction flag for strings\n\txor\tah,ah\t\t\t; clear ctrl flags to 0\n\tmov\tbx,0101H\t\t; set key to a make by default\n\tin\tal,KEYDATA\t\t; get a code from the keyboard\n\n\t;\n\t; New CODE to montior key stream\n\t;\n\tmov\tbx,[KeyStreamIndex]\n\tmov\t[KeyStream+bx],al\n\tinc\tbx\n\tand\tbx,15\n\tmov\t[KeyStreamIndex],bx\n\tmov\tbx,0101H\t\t; set key to a make by default\n\t;\n\t; END OF SEQUENCE\n\t;\n\n\t;\n\t; Handle the PAUSE key being pressed.  If it is pressed, then\n\t; signal that the next two input codes are to be thrown out.\n\t;\n\tcmp\tal,0E1H\t\t\t; see if this is a pause/break\n\tjne\tshort ??notpcode\t; not a pause/break start code\n\tmov\t[LastKeyE1],3\t\t; absorb this and next two codes\n\n??notpcode:\n\tcmp\t[LastKeyE1],0\t\t; are we in a pause/break code\n\tje\tshort ??notpause\t; no, just keep going\n\tdec\t[LastKeyE1]\t\t; yes, dec the count\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne \t??passcode\t\t; pass the code\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??notpause:\n\t;\n\t; Record any extended key codes that arrive.  They will be\n\t; taken into account with the next code.\n\t;\n\tcmp\tal,0E0H\t\t\t; is it an extended code\n\tjne\tshort ??notextcode\t; if not skip to handle key\n\tmov\t[LastKeyE0],TRUE\t; set the extended code to 1\n??jmppasscode:\n\tjmp\t??passcode\t\t; always pass E0s\n\n??notextcode:\n\n\t;\n\t; Check and acknowledge if the key is a make or a break.\n\t;\n\ttest\tal,080H\t\t\t; test for high bit\n\tje\tshort ??make\t\t; if off its a make\n\txor\tbl,bl\t\t\t; set make/break to break\n\tand\tal,07FH\t\t\t; clear high bit\n\tor\tah,KEYRELEASE\t\t; CDY NEW -- ABSENT IN OLD CODE\n\n??make:\n\t;\n\t; Translate the raw keycode into the Westwood keycode.\n\t;\n\tcmp\t[LastKeyE0],FALSE\t; was the prev byte an E0?\n\tje \tshort ??normal\t\t; if not it is a normal key\n\tmov\t[LastKeyE0],FALSE\t; if so clear for next read\n\tmov\t[IsExtKey],TRUE\t; it is an extended key\n\tmov\tdi,OFFSET ExtCodes\t; get offset of extended codes table\n\tmov\tcx,(ExtNums-ExtCodes)\t; get number of entrys in ext table\n\trepne\tscasb\t\t\t; look for a match\n\tjcxz\t??absorbcode\t\t; Not recognized, so throw it away.\n\tmov\tal,[(ExtNums - ExtCodes) - 1 + di] ; get the match\n\tmov\t[IsExtKey],FALSE\t; it is not an extended key\n\tjmp \tshort ??notext\n\n??normal:\n\tcmp\tal,07Ah\n\tjne\tshort ??normok\n\tmov\tal,128\n\tjmp\tshort ??notext\n??normok:\n\tmov\tdi,ax\t\t\t; use code as an index\n\tand\tdi,007Fh\t\t; Mask off any release bit.\n\tmov\tal,[KeyNums+di]\t\t; get the key number of this key\n\n??notext:\n\t;\n\t; Test and set the CTRL bit.\n\t;\n\ttest\t[KeysUpDown+8],001H\t; is the right ctrl down?\n\tjne\tshort ??ctrlon\t\t; if so, ctrl is on\n\ttest\t[KeysUpDown+7],004H\t; is the left ctrl down?\n\tje\tshort ??ctrloff\t\t; if not, neither are down, no ctrl\n\n\t; DRD\n\t; check for CTRL-NUMLOCK for pause on some keyboards\n\n\tcmp\tal,KN_NUMLOCK\t\t; check for CTRL-NUMLOCK\n\tjne\tshort ??ctrlon\n\n\tcmp\t[ExtKeyboard],TRUE\t; if 101/102-key keyboard it is ok\n\tje\tshort ??ctrlon\n\n\ttest\tdx,PAUSEON\t\t; should it pass these codes\n\tjne\tshort ??ctrlon\t\t; pass the code\n\n\tjmp\t??absorbcode\t\t; don't pass code\n\n??ctrlon:\n\tor\tah,CTRLPRESS\t\t; or on the ctrl bit in flags\n\n??ctrloff:\n\t;\n\t; Test and set the ALT bit.\n\t;\n\ttest\t[KeysUpDown + 7],050H\t; is either alt key down?\n\tje\tshort ??altoff\n\tor\tah,ALTPRESS\t\t; or on the alt bit in flags\n\n??altoff:\n\t;\n\t; Remap the keyboard keys if this is requested. (Do not set DGROUP\n\t;   as it is unecessary)\n\tpush\tax\n\tcall\tKeyNum_Translate\n\tadd\tsp,2\n\n;------\tSet the shift bit if necessary.\n\ttest\t[KeysUpDown+5],010H\t; is the left shift down?\n\tjne\tshort ??shifton\t\t; if so the shift is on\n\ttest\t[KeysUpDown+7],002H\t; is the right shift down?\n\tje\tshort ??shiftoff\t; if not then neither shift is down\n\n??shifton:\n\tor\tah,SHIFTPRESS\t\t; or on the shift bit in flags\n\n??shiftoff:\n\t;\n\t;------\tToggle the shift state if the caps lock key is on (if necessary).\n\t;\n\tmov\tdi,ax\n\tand\tdi,07Fh\n\tshr\tdi,1\n\tshr\tdi,1\n\tshr\tdi,1\n\tmov\tbx,ax\n\tand\tbx,07Fh\n\tand\tbl,0111b\n\tmov\tch,[Bits+bx]\t\t; get the bit to test\n\ttest\t[KeyLock],CAPSLOCK\t; is the caps lock on?\n\tje\tshort ??capsoff\t\t; if not don't worry about it\n\ttest\tch,[KeysCapsLock+di]\t; get code for keycaps\n\tje\tshort ??capsoff\t\t; its not effected\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag\n\n??capsoff:\n\t;\n\t;------\tToggle the shift state if the num-lock key is on (if necessary).\n\t;\n\ttest\t[KeyLock],NUMLOCK\t; is the num lock key on?\n\tje\tshort ??numlockoff\t; if not don't worry about it\n\ttest\tch,[KeysNumLock+di]\t; get code for numlock\n\tje\tshort ??numlockoff\t; if not effected skip toggle\n\txor\tah,SHIFTPRESS\t\t; toggle the shift flag if effected\n\n??numlockoff:\n;------ Remember the current control/shift/alt bit settings for later use.\n\n;??noshiftever:\n\tmov\t[CtrlFlags],ah\t\t; save off shift-ctrl-alt flags\n\t\t\t\t\t; for the mouse and joystick routines\n\t\t\t\t\t; to use in stuffing key into the\t\n\t\t\t\t\t; keyboard buffer.\n\ttest\tdx,DEBUGINT\n\tjz\t??not_toggle \n\n\nIF DEBUG\n\tcmp\t[KeyIntDisabled],1\n\tjne\t??not_currently_disabled\n\tcmp\tax,115\t\t\t; is it the F4 key\n\tje\t??disable\n\tcmp\tax,118\t\t\t; is it less then F7 key\n\tjb\t??justpass\n\tcmp\tax,120\t\t\t; is it greater than F9 key\n\tja\t??justpass\n??disable:\n\tmov\t[KeyIntDisabled],0\n??justpass:\n\tjmp\t??passcode\n\n??not_currently_disabled:\t\n\tcmp\tax,125\n\tjne\t??not_toggle\n\tmov\t[KeyIntDisabled],1\n\tjmp\t??absorbcode\nENDIF\n\n??not_toggle:\n\n;------\tThe CTRL-ALT-DEL key combination always gets passed to the system.\n\tcmp\tax,0668H\t\t; is it ctrl alt del?\n\tje\t??passcode\n\tcmp\tax,064CH\t\t; is it ctrl alt ext del?\n\tje\t??passcode\t; if so don't add it to the buffer\n\n;------ Special Ctrl-C check.\n\tcmp\tax,0230h\n\tje\tshort ??breaker\n\tcmp\tax,027Eh\n\tjne\tshort ??nobreak\n??breaker:\n\tmov\t[Break],1\n\n??nobreak:\n;------\tCheck for Music and Sound control keys.\n\tcmp\tax,0420H\t\t; is this an alt s\n\tjne\tshort ??checkmusic\t; toggle the Sound variable\n\tpush\tax\n\tmov\tax,[SoundOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??checkmusic:\n\tcmp\tax,0434H\t\t; is this an alt m\n\tjne\tshort ??esc\t\t; toggle the Music variable\n\tpush\tax\n\tmov\tax,[MusicOn]\n\txor\tax,01H\n\tpush\tax\n\tadd\tsp,2\n\tpop\tax\n\n??esc:\n\n\tpush\tax\n\tcall\tStuff_Key_Num\n\tpop\tax\n??skipstuff:\n\n;------\tDo the special ESC routine if necessary.\n\tcmp\tal,110\t\t\t; is this the esc key?\n\tjne\tshort ??noroutine\t; if not goto the pass always\n\tcmp\t[WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump\n\tje\tshort ??noroutine\n\tpush\tax\n\tcall\t[EscRoutine]\n\tpop\tax\n\n??noroutine:\n;------\tCheck to see if the key is to be passed to the system or not.\n\tmov\tdi,OFFSET PassAlways\t; get offset to table\n\tmov\tcx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1\n\trepne\tscasb\t\t\t; look for a match\n\tor\tcx,cx\t\t\t; see if there was no match\n\tjne\t??passcode\t; CDY JLB 7/11 optimization\n\n\n\n\n??passalways:\n\t; now check for conditional passes\n\tmov\tdi,OFFSET CondPassKey\t; get offset to cond key table\n\tmov\tcx,(CondPassCond-CondPassKey) ; get number of entries\n\tshr\tcx,1\t\t\t; cut in half for words\n\trepne\tscasw\t\t\t; look for a match\n\tjcxz\tshort ??notcondpass\t; OPTIMIZATION CDY JLB\n\tmov\tbx,[(CondPassCond - CondPassKey) - 2 + di]\n\tand\tbx,dx\t\t\t; are the conditions met?\n\tje\tshort ??notcondpass\t; NO... check normally.\n\tjmp\tshort ??passcode\t; YES... pass back to system.\n;\n;------\tLast check before passing keycode back to the system.\n;\n??notcondpass:\n\ttest\tdx,FILTERONLY\t\t; is the filter only flag on?\n\tje\tshort ??absorbcode\t; if not, absorb the code.\n\n??passcode:\n\n\tinc\t[cs:PassCount]\n\n;mov   ax , 0B000h\n;mov   es, ax \n;inc   [BYTE PTR es : 40h]\n\n\t; Now it is time to set up for the call to the System Keyboard\n\t; interrupt handler.\n\t; 1 -Restore System Stack Pointer Selector before exit Interrupt\n\t; 2- We Create a Returning Point from Interrupt by Push A\n \t;    Interupt Stack Frame into the Stack Pointer\n\t; 3- We make a Far jump to the interuupt handler\n\tcmp [Keyboard_StackPointer],0DEADh\n\tje  ??stackok\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n??stackok:\n\tcli\t\t\t\t       ; disable Interrupts\n\tmov dx, [Keyboard_App_Stack_SS]       \n\tmov ss, dx\t\t\t       ; Get System Stack Selector\n\tmov sp, [Keyboard_App_Stack_ES]      ; Get System Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n\tlea\tdx, [??Call_Back_Keyboard]   ; Get Return address offset\n \tpushf\t\t\t\t      ; push flags\t\n\tpush\tcs\t\t\t      ; push Code segment\n\tpush\tdx\t\t\t      ; push Offset\n\n\t; Now we need to simulate an interrup call by using ired\n\t; because we still want to come back here from the\n\t; Old Keyboard interrupt handle.\n\tpushf\n\tpush\t[word ptr KeyOldRMI + 2] \t; push orig segment.\n\tpush    [word ptr KeyOldRMI]   \t\t; push orig offset.\n\tiret\t \t\t        \t; call interrupt\t\n\n??absorbcode:\n\n;mov   ax , 0B000h\n;mov   es, ax \n;inc   [BYTE PTR es : 0h]\n\n\tin\tal,KEYCTRL\t\t\t; get the control port\n\tmov\tah,al\n\tor\tal,080H\t\t\t\t; reset bit for keyboard\n\tout\tKEYCTRL,al\n\txchg\tah,al\t\t\t\t; get orig control data\n\tout\tKEYCTRL,al\t\t\t; restore control data\n\n\tmov\tax,040h\t\t\t\t; BIOS paragraph is always @ 040h\n\tmov\tes,ax\t\t\t\t; put in es as BIOS paragraph\n\tmov\tal,[es:96h]\t\t\t; get extended keys\n\tand\tal,0FDh\t\t\t\t; turn off last key e0 flag\n\tmov\t[es:96h],al\t\t\t; set extended keys\n\n\tmov\tal,CLEARISR\t\t\t; value to clear In Service Register\n\tout\tINTCHIP0,al\t\t\t; 8259 interrupt chip controller 0\n\n\tcmp [Keyboard_StackPointer],0DEADh\n\tje  ??stackok2\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n??stackok2:\n\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov dx, [Keyboard_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, dx\t\t\t       ; Get Syatem Stack Selector\n\tmov sp, [Keyboard_App_Stack_ES]        ; Get Syatem Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\n??Call_Back_Keyboard:\n\tpop\tsi\n\tpop\tes\n\tpop\tdx\n\tpop\tds\n\tpop\tdi\n\tpop\tcx\n\tpop\tbx\n\tpop\tax\n\tiret\t\nENDIF\n\n\tENDP\tKeystroke_Interrupt\n\n;***************************************************************************\n;* Break interrupt routines begin here!\n;***************************************************************************\n\n;***************************************************************************\n;* BREAK_INTERRUPT -- Handles the break key interrupt                      *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    This is an interrupt routine.                              *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/13/1994 PWG : Created.                                             *\n;*=========================================================================*\nlabel RM_Break_Interrupt\n\tGLOBAL\tC Break_Interrupt:FAR\n\tPROC\tBreak_Interrupt C FAR\n\n\n\tpushf\n\tpush\tax\n\tpush\tes\n\n\tmov\tax,0B000h\t\t; ES:DI = Mono RAM address.\n\tmov\tes,ax\n\tinc\t[BYTE PTR es:0]\n\t\t\n\n\tpop\tes\n\tpop\tax\n\tpopf\n\n\n\tiret\t\n\n\tENDP\tBreak_Interrupt\n\n;**************************************************************************\n;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                                  *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nCall_Interrupt_Chain:\n\tpushf\n\tcall\tKeystroke_Interrupt ;[KeyOldRMI]\n\tretf\n\n;----------------------------------------------------------------------------\n; LOW_HIDE_MOUSE:\n;\n; This function hides the mouse cursor on the screen if it was shown.  It \n; will not hide the mouse if it is already hidden.\n;\n; PROTOTYPE:\n;\n;\tVOID Low_Hide_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Hide_Mouse:FAR\n\tPROC\tLow_Hide_Mouse C FAR \n\tUSES\tax,bx,cx,dx,ds\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n   \tcmp\t[MDisabled],0\t\t; check if mouse is disabled\n\tjne\tshort ??end\n\n   \tcmp\t[MState],0\t\t; check if it was hidden before\n\tjne\tshort ??endnodraw\t\t; no need to hide again\n\n;------\tMove the saved graphic buffer to the seenpage to hide the mouse.\n;\tcall\tBuffer_To_Page C,[buffx],[buffy],[buffw],[buffh],[MouseBuffer],SEENPAGE\n\tmov\tax,RESTORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tRecord that the mouse has been hidden.\n??endnodraw:\n\tadd\t[MState],1\n\tadc\t[MState],0\n\n??end:\n\tret\n\n\tENDP\tLow_Hide_Mouse\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; LOW_SHOW_MOUSE:\n;\n; This function displays the mouse cursor on the screen if it was hidden.\n;\n; PROTOTYPE:\n;\tVOID Low_Show_Mouse(VOID);\n;\n; NOTE: does not check if mouse is currently being updated.\n;----------------------------------------------------------------------------\n\n \tGLOBAL\tC Low_Show_Mouse:FAR\n\tPROC\tLow_Show_Mouse C FAR \n\tUSES \tax,bx,cx,dx,si,di,ds,es\n\tLOCAL\tmousex:WORD\t\t; Draw X position.\n\tLOCAL\tmousey:WORD\t\t; Draw Y position.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n;-----\tDon't show the mouse if it is not hidden, disabled.\n\tcmp\t[MDisabled],0\t\t; is the mouse disabled\n\tjne\t??exit\t\t\t; if so then exit\n\n\tcmp\t[MState],0\t\t; is the mouse already visible\n       \tje\t??exit\t\t\t; if so then exit\n\n\tdec\t[MState]\n\tcmp\t[MState],0\t\t; can the mouse be shown\n       \tjne\tshort ??exit\n\n;------\tDetermine the drawing position of the mouse.\n\tmov\tcx,[MouseWidth]\t\t; Theoretical buffer width (pixel).\n\tmov\tdx,[MouseHeight]\t; Theoretical buffer height (pixel).\n\n\tmov\tax,[MouseX]\n;\tsub\tax,[MouseXHot]\n\tmov\t[mousex],ax\t\t; Draw X pixel.\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??xnotneg\n;\tadd\tcx,ax\t\t\t; Reduce width accordingly.\n;\tmov\tax,0\n??xnotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n\tmov\tbx,[MouseY]\n;\tsub\tbx,[MouseYHot]\n\tmov\t[mousey],bx\t\t; Draw Y pixel.\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nIF 0\n;\tjns\tshort ??ynotneg\n;\tadd\tdx,bx\t\t\t; Reduce height of mouse accordingly.\n;\tmov\tbx,0\n??ynotneg:\nENDIF\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n;------\tDetermine the theoretical coordinates and dimensions of the\n;\tarea the mouse shape will be rendered upon.\n\tmov\t[MouseBuffX],ax\n\tmov\t[MouseBuffY],bx\n\tmov\t[MouseBuffW],cx\n\tmov\t[MouseBuffH],dx\n\n;------\tMove the area that will be drawn upon, to the graphic buffer.\n\tmov\tax,STORE_VISIBLE_PAGE\n\tpush\tax\n\tpush\tcs\n\tcall\t[ ShadowPtr ]\n\tadd\tsp,2\n\n;------\tDraw the mouse shape to the seenpage.\n\tpush\t[mousey]\n\tpush\t[mousex]\n\tpush\tcs\n\tcall\t[ DrawMousePtr ]\n\tadd\tsp,4\n??exit:\n\tret\n\n\tENDP\tLow_Show_Mouse\n\n;----------------------------------------------------------------------------\n;----------------------------------------------------------------------------\n\tGLOBAL\tC Mouse_KeyNum:FAR\n\tPROC\tMouse_KeyNum C FAR \n\tUSES\tbx\n\tARG\tstate:WORD\t\t; Current mouse state.\n\tLOCAL\tkeynum:WORD\t\t; Determined keynum.\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tmov\t[keynum],KN_MOUSE_MOVE\t; Presume just a mouse move.\n\tmov\tbx,[state]\n\tmov\tax,bx\n\txor\tbl,[Button]\t\t; Bits of state change.\n\tje\tshort ??fini\n\tmov\t[Button],al\t\t; Record new mouse state.\n\n\ttest\tbl,0010b\n\tje\tshort ??notright\n\tmov\t[keynum],KN_RMOUSE\n\ttest\tal,0010b\n\tjne\tshort ??notright\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notright:\n\n; DRD\n; note:  the left mouse button has priority over the right mouse button\n; this should be changed at a later date to process them independently\n\n\ttest\tbl,0001b\n\tje\tshort ??notleft\n\tmov\t[keynum],KN_LMOUSE\n\ttest\tal,0001b\n\tjne\tshort ??notleft\n\tor\t[keynum],0800h\t\t; Release bit on.\n??notleft:\n\n??fini:\n\tmov\tax,[keynum]\n\tret\n\n\tENDP\tMouse_KeyNum\n\n;----------------------------------------------------------------------------\n\n\n;----------------------------------------------------------------------------\n; MOUSE_INT:\n;\n; This routine is called automatically when the Mouse_Int is installed.  It\n; automatically updates the global variables stored in the code segment so\n; that the mouse information is automatically known at all times.\n;\n; INPUTS (from int):\tAX = condition mask ( bit 0 == cursor position chg,\n;\t\t\t\t\t      bit 1 == left button press,\n;\t\t\t\t\t      bit 2 == left button release,\n;\t\t\t\t\t      bit 3 == right button press,\n;\t\t\t\t\t      bit 4 == right button release,\n;\t\t\t\t\t      5-15  == not used )\n;\t\t\tBX = button state   ( bit 0 == left button down,\n;\t\t\t\t\t      bit 1 == right button down,\n;                                             bit 2 == middle button down.\n;\t\t\t\t\t      3-15  == not used )\n;\t\t\tCX = cursor coordinate (horizontal axis)\n;\t\t\tDX = cursor coordinate (vertical axis)\n;\t\t\tDI = horizontal mouse count (mickeys)\n;\t\t\tSI = vertical mouse count (mickeys)\n;\n; RETURNS:\t\tnone\n;\n; MODIFIES:\t\tmodifies the variables _Button, _ButtonChange,\n;\t\t\t_MouseX,_MouseY,_ButtonLatch\n;\n; PROTOTYPE:\n;\tThis routine is called from an interrupt.\n;----------------------------------------------------------------------------\nlabel RM_Mouse_Interrupt\n\tPROC\tMouse_Int C FAR \n\tUSES\tax,bx,cx,dx,ds,si,es,di\n\tLOCAL\tcond:WORD\t\t; Local copy of mouse event.\n\tLOCAL\tstate:WORD\t\t; Local copy of button state.\n\n\tmov\t[cs:Mouse_State],bx\n\tmov\t[cs:Mouse_Cond],ax\n\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t; At this point we do not know if the SS selector is a\n \t; System Stack or the Application Stack pointer.\n\t; Soo to be in the safe side we create our own local\n\t; Stack Pointer\tSelector Relative to DS\n\t; Note Do not try this trick in a reentrant interrupt\n\tmov bx, ss\t\t\t\t; get SS\n\tmov [Mouse_App_Stack_ES], sp\t\t; Protect ES\n\tmov [Mouse_App_Stack_SS], bx\t\t; Protect SS\n\tlea bx, [Mouse_StackStart ]\t; Compute Local Stack size\n\tand bx, -2;\n\tcli\t\t\t\t\t; Disable All interrupts\n\tmov ss, ax\t\t\t\t; Set new SS Selector\n\tmov sp, bx\t\t\t\t; Set new Stack Offset\n\tsti\t\t\t\t\t; Enable Interrupts\n\n;------\tProcess the mouse interrupt only if the mouse is enabled (whether\n;\tpresent or not).\n\tcmp\t[MDisabled],0\n\tjne\t??exit\n\n\tcmp\t[MInput],0\n\tje\t??exit\n\n\n;------ This was added because of missing mouse presses and\n;\treleases during a mouse update.\n\tmov\tax,[Mouse_Cond]\n\tand\tax,0001EH \t; bits for left and right press and release\n\tjne\tshort ??dopress_release\n\n\tcmp\t[MouseUpdate],0 ; if mouse move and mouse updating exit\n\tjne\t??exit\n\n??dopress_release:\n\n;------\tIn EEGA mode mouse X coordinates as 0..639.  Make adjustment\n;\tto keep within 0..319 range.\n\tcmp\t[Adjust],1\t\t; if the x coordinate is returned\n\tjne\tshort ??noadjust\t; incorrectly then\n\tshr\tcx,1\t\t\t; adjust x coord from 640 pixel screen\n??noadjust:\n\n\n; scale mouse posX and PosY\n;\tcmp\t[Adjust_XPos] , 0\n;\tjz\tshort ??no_scaleX\n;\tpush\tdx\n;\tmov\tax , [MouseRight]\n;\timul\tcx\n;\tidiv\t[Adjust_XPos]\n;\tmov\tcx , ax\n;\tpop\tdx\n??no_scaleX:\n;\tcmp\t[Adjust_YPos] , 0\n;\tjz\tshort ??no_scaleY\n;\tmov\tax , [MouseBottom]\n;\timul\tdx\n;\tidiv\t[Adjust_YPos]\n;\tmov\tdx , ax\n??no_scaleY:\n\n;------\tKeep mouse within screen bounds.\n\tcmp\tcx,[MouseRight]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundX_ok\t\t; force it to stay at least one pixel\n\tmov\tcx,[MouseRight]\t\t\t; on the screen\n\tdec\tcx\n??boundX_ok:\n\tcmp\tdx,[MouseBottom]\t\t\t; in EGAMODE, the mouse may go to 320\n\tjb\tshort ??boundY_ok\t\t; force it to stay at least one pixel\n\tmov\tdx,[MouseBottom]\t\t\t; on the screen\n\tdec\tdx\n??boundY_ok:\n\n\tIF 0\n;------\tRemap the middle button to equal the right button.\n\ttest\tbx,04h\n\tje\t??noremap\n\tor\tbx,0010b\t\t; Set the right button bit.\n??noremap:\n\tENDIF\n\n\tmov\t[MouseX],cx\t\t; and store in mouse x\n\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\ttest\t[KeyFlags],KEYMOUSE\n\tjne\tshort ??nostuffit\n\n\tcall\tMouse_KeyNum C,[Mouse_State]\t; Convert mouse state to key number code.\n\tcall\tStuff_Key_Num C,ax\t; Record mouse keynumber code.\n??nostuffit:\n\n\n\n;------ The check for Mouse in the middle of updating CAN NOT BE MOVED\n;\tany farther up because mouse presses and releases will be LOST!!\n \tcmp\t[MouseUpdate],0\n\tjne\t??exit\n;??jexit:\n;\tjmp\t??exit\n\n\nchristopher:\n??chkxy:\n\n;------\tSignal that no mouse updating can occur at this time.\n;\tcmp\t[_MouseUpdate],0\n;\tjne\t??exit\n;\tmov\t[_MouseUpdate],1\n\n;------\tPerform any X movement grid adjustment.\n\tcmp\t[MouseStepX],0\t\t; are we stepping on the X?\n\tje\tshort ??no_x_step\t\t; no x\n\tmov\tax,cx\t\t\t; get current x_pixel\n\tmov\tcx,dx\t\t\t; save dx - it is trashed by idiv\n\tsub\tax,[MouseOffsetX]\t; get offset difference\n\tmov\tbx,[MouseStepX]\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step X\n\timul\tbx\t\t\t; ax = div * Step X\n\tadd\tax,[MouseOffsetX]\t; normalize to region offset\n\tmov\tdx,cx\t\t\t; restore dx (new MouseY)\n\tmov\tcx,ax\t\t\t; set cx (new MouseX)\n??no_x_step:\n\n;------\tPerform any Y movement grid adjustment.\n\tcmp\t[MouseStepY],0\t\t; are we stepping on the Y\n\tje\tshort ??no_step\t\t; no y\n\tmov\tax,dx\t\t\t; get current y_pixel\n\tsub\tax,[MouseOffsetY]\t; get offset difference\n\tmov\tbx,[MouseStepY]\t\t; get step in bx for idiv\n\tcwd\t\t\t\t; extend ax -> dx:ax\n\tidiv\tbx\t\t\t; divide by Step Y\n\timul\tbx\t\t\t; ax = div * Step Y\n\tadd\tax,[MouseOffsetY]\t; normalize to region offset\n\tmov\tdx,ax\t\t\t; set dx (new MouseY)\n??no_step:\n\n;------ Here is where we store the new MouseX and MouseY values\n;\tmov\t[MouseX],cx\t\t; and store in mouse x\n;\tmov\t[MouseY],dx\t\t; store y coord in mouse y\n\n;------\tIf the mouse is hidden or its position hasn't changed, then\n;\tperform no action.\n\tcmp\t[MState],0\n\tjne\tshort ??updateend\n\tcmp\t[MouseXOld],cx\n\tjne\tshort ??doit\n\tcmp\t[MouseYOld],dx\n\tje\tshort ??updateend\n??doit:\n\n;------\tAt this point we KNOW the mouse has moved.\n\tmov\tax,[MCState]\n\tand\tax,CONDHIDE+CONDHIDDEN\n\tcmp\tax,CONDHIDE+CONDHIDDEN\n\tje\tshort ??condcheck\t\t; If already hidden.\n\n;------\tWe know that the mouse is visible, we must hide it\n;\tbefore we update its position.\n\tcall\tLow_Hide_Mouse\n\n;------\tConditional region check goes here.  If the mouse falls within the \n;\tconditional region, it gets marked as hidden and no other processing\n;\toccurs.\n\ttest\t[MCState],CONDHIDE\n\tje\tshort ??condok\n\n??condcheck:\n\tcmp\tcx,[MouseCXLeft]\t\t; check adjusted x region\n\tjb\tshort ??condok\n\tcmp\tcx,[MouseCXRight]\n\tja\tshort ??condok\n\tcmp\tdx,[MouseCYUpper]\t; check adjusted y region\n\tjb\tshort ??condok\n\tcmp\tdx,[MouseCYLower]\n\tja\tshort ??condok\n\n\tor\t[MCState],CONDHIDDEN\t; flag as conditional hidden\n\tjmp short ??updateend\n\n;------\tThe mouse coordinates and flags pass all of the tests, proceed\n;\twith rendering the mouse.\n??condok:\n\tcall\tLow_Show_Mouse\n\n;------\tFinal clean up and exit.\n??updateend:\n\tmov\t[MouseXOld],cx\n\tmov\t[MouseYOld],dx\n\n??exit:\n\tcmp\t[Mouse_StackPointer],0DEADh\n\tje\t??mouse_stk_ok\n\tpush cx\n\tpush di\n\tpush ax\n\tpush es\n\tmov  ax,0A000h\n\tmov  es,ax\n\txor  di,di\n\tmov  cx,64000\n\tmov  ax,1\n\trep  stosb\n\tpop  es\n\tpop  ax\n\tpop  di\n\tpop  cx\n\n??mouse_stk_ok:\n\t; Restore System Stack Pointer Selector before exit Interrupt\n\tmov ax, [Mouse_App_Stack_SS]       \n\tcli\t\t\t\t       ; disable Interrupts\n\tmov ss, ax\t\t\t       ; Get Syatem Stack Selector\n\tmov sp, [Mouse_App_Stack_ES]           ; Get Syatem Stack offset\n\tsti\t\t\t\t       ; Enable Interrupts\n\tret\n\tENDP\tMouse_Int\n\n\n\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VGA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVGA_Mouse_Shadow_Buffer C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\tpush\tbp\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tbp , cx\n??restore_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 10\nmov es, ax\nmov al , 'V'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tsi,di\t\t\t\t\t; xchg the source and the dest\n\tmov\tbp , cx\n\tpush\tes\t\t\t\t\t; need to swap es and ds but\n\tpush\tds\t\t\t\t\t;   cant xchg so pop them on the\n\tpop\tes\t\t\t\t\t;   stack and pop them off the\n\tpop\tds\t\t\t\t\t;   wrong way intentionally.\n??store_loop:\n\tmov\tcx,ax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tsi,dx\t\t\t\t\t; move past right clipped pixels\n\tadd\tdi,bx\t\t\t\t\t; adjust dest to next line\n\tdec\tbp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tbp\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 12\nmov es, ax\nmov al , 'G'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tret\n\n\tENDP\tVGA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n\n\tGLOBAL\tC VGA_Draw_Mouse:FAR\n\tPROC\tVGA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tbx , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , bx\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tbx , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , bx\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\tmov\tdx , [MouseRight]\n\tmov\tdi , ax\n\tadd\tdi , [ x0 ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 12 * 80 + 14\nmov es, ax\nmov al , 'A'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tret\nENDP\tVGA_Draw_Mouse\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VESA_Mouse_Shadow_Buffer:FAR\n\tPROC\tVESA_Mouse_Shadow_Buffer C FAR \n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tstore:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\tax,[MouseBuffX]\n\tmov\tbx,[MouseBuffY]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax , [MouseBuffW]\n\tadd\tbx , [MouseBuffH]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov \tax , [ word ptr MouseBuffer ]\n\tmov\t[ buffy0 ] , ax\n\n;*===================================================================\n;* Bounds check source X. Y.\n;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseBuffW]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\tax,0A000h\n\tmov\tes,ax\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\t\n\n\tmov\tbx , [ MouseWidth ]\t; turn this into an offset\n\tlds\tsi , [ MouseBuffer ]\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??restore_loop:\n\tmov\tah,al\n??res_inner_loop:\n\tmov\tch , [si]\n\tmov\t[es:di],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??res_same_page\n\tcall\tnext_vesa_page\n ??res_same_page:\n \tdec\tah\n\tjnz\t??res_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??res_same_page1\n\tcall\tnext_vesa_page\n ??res_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 10\nmov es,ax\nmov al ,'v'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tjmp\t??out\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\tmov\tah,al\n??store_inner_loop:\n\tmov\tch , [es:di]\n\tmov\t[si],ch\n\tinc\tsi\n\tinc\tdi\n\tjnz\t??store_same_page\n\tcall\tnext_vesa_page\n ??store_same_page:\n \tdec\tah\n\tjnz\t??store_inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??store_same_page1\n\tcall\tnext_vesa_page\n ??store_same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_entry\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 14\nmov es,ax\nmov al ,'e'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\n\tmov\tdx , [ app_vesa_window ] \n\tcall\tset_vesa_window\n\tret\n\n\tENDP\tVESA_Mouse_Shadow_Buffer\n\n\n\n;***************************************************************************\n\n\tGLOBAL\tC VESA_Draw_Mouse:FAR\n\tPROC\tVESA_Draw_Mouse C FAR\n\tUSES\tax,bx,cx,dx,di,si,ds,es\n\tARG\tmousex:WORD\n\tARG\tmousey:WORD\n\n\tlocal\tx0 : word\n\tlocal\ty0 : word\n\tlocal\tx1 : word\n\tlocal\ty1 : word\n\tlocal\tbuffx0 : word\n\tlocal\tbuffy0 : word\n\tlocal\tapp_vesa_window : word\n\n   \n\t;*=========================================================================*\n\t;* Since we are in tiny model point ds to cs\n\t;*=========================================================================*\n\tmov\tax,cs\t\t\t\t; since we are in tiny model\n\tmov\tds,ax\t\t\t\t; set cs = ds\n\n\tcall\tget_vesa_window\n\tmov\t[ app_vesa_window ] , dx\n\n\n\t;*===================================================================\n\t;* Pre-initialize the left, right and topclip values to zero.\n\t;*===================================================================\n\tmov\tax, [ mousex ]\n\tmov\tbx , [ mousey ]\n\tsub\tax , [ MouseXHot ]\n\tsub\tbx , [ MouseYHot ]\n\n\tmov\t[ x0 ] , ax  \n\tmov\t[ y0 ] , bx  \n\tadd\tax, [ MouseWidth ]\n\tadd\tbx, [ MouseHeight ]\n\tmov\t[ x1 ] , ax  \n\tmov\t[ y1 ] , bx  \n\n\tmov\t[ buffx0 ] , 0\n\tles\tax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , ax\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\n\txor \tax , ax\n\txor \tdx , dx\n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx\n\tadc\tdx , dx \n\n\tmov\tcx , [ x0 ]  \n\tmov\tbx , [ x1 ]  \n\tsub\tcx , [ MouseRight ]\n\tsub\tbx , [ MouseRight ]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\tmov\tcx , [ y0 ]  \n\tmov\tbx , [ y1 ]  \n\tsub\tcx , [MouseBottom]\n\tsub\tbx , [MouseBottom]\n\tdec\tcx\n\tdec\tbx\n\tadd\tcx , cx\n\tadc\tax , ax \n\tadd\tbx , bx \n\tadc\tdx , dx\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??acepted\n\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tbx , [ x0 ]\n\tneg\tbx\n\tmov\t[ buffx0 ] , bx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tpush\tdx\n\tmov\tax , [ y0 ]\n\tneg\tax\n\tmul\t[MouseWidth]\n\tadd\t[ buffy0 ] , ax\n\tmov\t[ y0 ] , 0\n\tpop\tdx\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\tax , [MouseRight]  ; get width into register\n\tmov\t[ x1 ] , ax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??acepted\n\tmov\tax , [MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , ax\n\n??acepted:\n\n\tmov\tax , [ y0 ]\n\tmul\t[ MouseRight ] \n\n\tadd\tax , [ x0 ]\n\tadc\tdx , 0\n\tmov\tdi , ax\n\tcall\tset_vesa_page\n\n\tmov\tdx , [MouseRight]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tbx , [MouseWidth]\t; turn this into an offset\n\tmov\tsi , [ buffy0 ]\t\t; edx points to source\n\tadd\tsi , [ buffx0 ]\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\tmov\tax , 0a000h\n\tmov\tds , ax\n\tmov\tax , [ x1 ]\n\tmov\tcx , [ y1 ]\n\tsub\tax , [ x0 ]\n\tjle\t??out\n\tsub\tcx , [ y0 ]\n\tjle\t??out\n\n\tsub\tdx , ax\n\tsub\tbx , ax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch , [es:si]\n\tinc\tsi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[di],ch\n??inc_edi:\n\tinc\tdi\n\tjnz\t??same_page\n\tcall\tnext_vesa_page\n ??same_page:\n \tdec\tah\n\tjnz\t??inner_loop\n\tadd\tsi,bx\t\t\t\t; move past right clipped pixels\n\tadd\tdi,dx\t\t\t\t; adjust dest to next line\n\tjnc\t??same_page1\n\tcall\tnext_vesa_page\n ??same_page1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\nIF  ECHOON\nmov ax , 0b000h \nmov di , 10 * 80 + 14\nmov es, ax\nmov al , 's'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nmov di , 10 * 80 + 16\nmov al , 'a'\nmov [es:di],al\t\nmov al,2\nmov [es:di+1],al\t\nENDIF\n\tmov\tdx , [ app_vesa_window ] \n\tcall\tset_vesa_window\n\tret\n\n\nENDP\tVESA_Draw_Mouse\n\n\n\n;************************************************************************\n\nPROC\tget_vesa_window C near\nuses\tax,bx\n\tmov\tax , 04f05h\n\tmov\tbh , 1\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\t\n\n;************************************************************************\n\nPROC\tset_vesa_window C near\nuses\tax,bx,dx\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]  \t\n\tret\nENDP\t\n\n\n;***************************************************************************\n\nPROC\tset_vesa_page C near\nUSES\tax,bx,dx\n\n\tmov\tbx , dx\n\tshl\tbx , 2\n\tmov\t[ cs: current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n\tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tset_vesa_page\n\nPROC\tnext_vesa_page C near\nUSES\tax,bx,dx\n\tmov\tbx , [ cs: current_page ]\n\tadd\tbx , 4\n\tmov\t[ cs:current_page ] , bx\n\tmov\tdx , [ word ptr cs:banktable + bx ]\n       \tmov\tax , 04f05h\n\tmov\tbh , 0\n\tmov\tbl , 0\n\tcall\t[ dword ptr cs: VesaPtr ]\n\tret\nENDP\tnext_vesa_page\n\n\n\n;***********************************************************\nEND\n"
  },
  {
    "path": "WWFLAT32/SRCDEBUG/MEM.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Library                         *\n *                                                                         *\n *                    File Name : MEM.C                                    *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : March 31, 1993                           *\n *                                                                         *\n *                  Last Update : September 8, 1994   [IML]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Mem_Free -- Free a block of memory from system.                       *\n *   Mem_Alloc -- Allocate a block of memory from the special memory pool. *\n *   Mem_Init -- Initialize the private memory allocation pool.            *\n *   Mem_Reference -- Updates the reference time for the specified memory blo*\n *   Mem_Find -- Returns with pointer to specified memory block.           *\n *   Mem_Find_Oldest -- Returns with the memory block with the oldest time st*\n *   Mem_Free_Oldest -- Find and free the oldest memory block.             *\n *   Mem_Avail -- Returns the amount of free memory available in the cache.*\n *   Mem_Cleanup -- Performes a garbage collection on the memory cache.    *\n *   MemNode_Unlink -- Unlinks a node from the cache.                      *\n *   MemNode_Insert -- Inserts a node into a cache chain.                  *\n *   Mem_Largest_Avail -- Largest free block available.                    *\n *   Mem_Lock_Block -- Locks a block so that it cannot be moved in cleanup.*\n *   Mem_In_Use -- Makes it so a block will never be returned as oldest*\n *   Mem_Pool_Size -- Returns total amount of memory in pool.              *\n *   Mem_Get_ID -- Returns ID of node.                                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"wwmem.h\"\n#include <timer.h>\n\n#include\t<stddef.h>\n#include\t<mem.h>\n\nextern TimerClass TickCount;\n\n#define DEBUG_FILL FALSE\n\n////////////////////////////////////////////////////////////////////////////\n\n\n\n/*******************************************************************************\n** A allocated block may have one of three meanings in the Time field.  The first\n** is the time stamp of the last time it was referenced.  The other two values\n** are defined below.  MEM_BLOCK_IN_USE means that it will never be returned as the\n** oldest since there is no valid time stamp.  LOCKED_BLOCK has the same meaning as\n** MEM_BLOCK_IN_USE with the added feature that the block will not be moved in a \n** Mem_Cleanup().  Therefore, there may be some fragmentation after the cleanup\n** if any blocks are LOCKED.  It would be good practice to seldomly lock blocks,\n** for instance, only when a sample is being played.\n** WARNING: If these values change to anything else, logic will need to be changed\n**          in Mem_Find_Oldest since it relies on these being small values.\n*/\n#define MEM_BLOCK_IN_USE\t0x00\n#define MEM_BLOCK_LOCKED\t0x01\n\n/*\n**\tEach block of memory in the pool is headed by this structure.\n*/\ntypedef struct MemChain {\n\tstruct MemChain\t*Next;\t// Pointer to next memory chain node.\n\tstruct MemChain\t*Prev;\t// Pointer to previous memory chain node.\n\tunsigned long\t\tID;\t\t// ID number of block.\n\tunsigned short\t\tTime;\t\t// TickCount of latest reference.\n\tunsigned short\t\tSize;\t\t// Size of memory block (in paragraphs).\n} MemChain_Type;\n\n\n/*\n**\tHolding tank memory management data.\n*/\ntypedef struct MemPool {\n\tMemChain_Type\t*FreeChain;\t// Pointer to first node in free chain.\n\tMemChain_Type\t*UsedChain;\t// Pointer to first node in used chain.\n\tunsigned short\tFreeMem;\t\t// Current amount of free ram (in paragraphs).\n\tunsigned short\tTotalMem;\t// Total quantity of memory.\n\tlong\t\t\t\tpad2;\n} MemPool_Type;\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE void MemNode_Unlink(MemPool_Type *pool, int freechain, MemChain_Type *node);\nPRIVATE void MemNode_Insert(MemPool_Type *pool, int freechain, MemChain_Type *node, unsigned int size, unsigned long id, int merge);\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * Mem_Init -- Initialize the private memory allocation pool.              *\n *                                                                         *\n *    This routine is used to initialize the private memory allocation     *\n *    pool.                                                                *\n *                                                                         *\n * INPUT:   buffer   -- Pointer to the buffer that is the allocation pool. *\n *                                                                         *\n *          size     -- Size of the buffer in bytes.                       *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Was it initialized successfully?                   *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nint Mem_Init(void *buffer, long size)\n{\n\tMemChain_Type\t*mem;\t\t\t// Working memory chain node.\n\tMemPool_Type\t*pool;\t\t// Memory pool control structure.\n\n\t/*\n\t**\tThe buffer is rounded down to the nearest paragraph.\n\t*/\n\tsize = size & 0xFFFFFFF0L;\n\n\tif (!buffer || !size) return(FALSE);\n\n\t/*\n\t**\tInitialize the pool control structure.\n\t*/\n\tpool = (MemPool_Type *)buffer;\n\tpool->FreeMem = (size - sizeof(MemPool_Type)) >> 4;\n\tpool->UsedChain = NULL;\n\tpool->TotalMem = pool->FreeMem;\n\tmem = pool->FreeChain = (MemChain_Type *) (pool + 1);\n\n\t/*\n\t**\tInitialize the free memory chain.\n\t*/\n\tmem->Next = NULL;\n\tmem->Prev = NULL;\n\tmem->Size = pool->FreeMem;\n\tmem->ID = -1;\n\tmem->Time = 0;\n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * Mem_Alloc -- Allocate a block of memory from the special memory pool.   *\n *                                                                         *\n *    This routine will allocate a block of memory from the special        *\n *    memory allocation pool.                                              *\n *                                                                         *\n * INPUT:   poolptr\t-- Pointer to the memory pool base address.           *\n *                                                                         *\n *          size  -- The size of the memory block to allocate.             *\n *                                                                         *\n *          id    -- ID number to give this memory block.                  *\n *                                                                         *\n * OUTPUT:  Returns with a pointer to the allocated block.  If there was   *\n *          insufficient room, then NULL is returned.                      *\n *                                                                         *\n * WARNINGS:   Be sure to check for the NULL return case.                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Alloc(void *poolptr, long lsize, unsigned long id)\n{\n\tMemPool_Type\t*pool;\n\tMemChain_Type\t*node;\t\t\t// Pointer to current memory node.\n\tunsigned int\tremainder=0;\t// Remaining bytes that are still free.\n\tint\t\t\t\tfound;\n\tint\t\t\t\tsize;\t\t\t\t// Paragraph size of allocation.\n\n\n\t/*\n\t**\tIf there is no free memory then the allocation will\n\t**\talways fail.\n\t*/\n\tif (!poolptr || !lsize) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\t\t\n\t/*\n\t**\tAllocations are forced to be paragraph sized.\n\t*/\n\tlsize += sizeof(MemChain_Type);\t// Account for header.\n\tlsize = (lsize + 0x0FL) & 0xFFFFFFF0L;\n\tsize = (int)(lsize >> 4);\n\n\t/*\n\t**\tIf the total free is less than the size of the desired allocation,\n\t**\tthen we KNOW that an allocation will fail -- just return.\n\t*/\n\tif (pool->TotalMem < size) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tWalk down free chain looking for the first block that will\n\t**\taccomodate the allocation.\n\t*/\n\tnode = pool->FreeChain;\n\tfound = FALSE;\n\twhile (!found && node) {\n\n\t\t/*\n\t\t**\tFetch free memory chunk block and see if it is big enough.\n\t\t*/\n\t\tif (node->Size >= size) {\n\t\t\tfound = TRUE;\n\t\t\tbreak;\n\t\t}\n\t\tnode = node->Next;\n\t}\n\tif (!found) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tDetermine if this allocation would split the block.\n\t*/\n\tremainder = node->Size - size;\n\n\t/*\n\t**\tIf only a very small free chunk would remain, just tack it on\n\t**\tto the current allocation.\n\t*/\n\tif (remainder <= 2) {\n\t\tremainder = 0;\n\t\tsize = node->Size;\n\t}\n\n\t/*\n\t**\tRemove the primary block from the free memory list.\n\t*/\n\tMemNode_Unlink(pool, TRUE, node);\n\n\t/*\n\t**\tIf a smaller block remains, then link it back into\n\t**\tthe free memory list.\n\t*/\n\tif (remainder) {\n\t\tMemNode_Insert(pool, TRUE, (MemChain_Type *)Add_Long_To_Pointer(node, (long)size << 4), remainder, -1, FALSE);\n\t}\n\n\t/*\n\t**\tLink in the allocated node into the used memory list.\n\t*/\n\tMemNode_Insert(pool, FALSE, node, size, id, FALSE);\n\n\t/*\n\t**\tReflect the change to the total free count.\n\t*/\n\tpool->FreeMem -= size;\n\n\t/*\n\t**\tReturn a pointer to the block of allocated memory just past\n\t**\tthe header.\n\t*/\n\n#if DEBUG_FILL\n\tmemset(node + 1, id, (size-1) << 4);\n#endif\n\treturn((void *) (node + 1));\n}\t\n\n\n/***************************************************************************\n * Mem_Free -- Free a block of memory from system.                         *\n *                                                                         *\n *    This routine will free a block of memory from the special memory     *\n *    buffer.                                                              *\n *                                                                         *\n * INPUT:   poolptr\t-- Pointer to the memory pool base address.           *\n *                                                                         *\n *          buffer   -- Pointer to memory block to free.                   *\n *                                                                         *\n * OUTPUT:  TRUE/FALSE; Was the deallocation successful?                   *\n *                                                                         *\n * WARNINGS:   Be sure to only pass in to this routine a buffer that was   *\n *             returned from Mem_Alloc().                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/31/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nint Mem_Free(void *poolptr, void *buffer)\n{\n\tMemPool_Type\t*pool;\t\t\t// pointer to structure.\n\tMemChain_Type\t*node;\t\t\t// Copy of current memory node.\n\tunsigned int\tsize;\t\t\t\t// Size of the block being freed.\n\n\t/*\n\t**\tOne can't free what isn't there.\n\t*/\n\tif (!buffer || !poolptr) {\n\t\treturn(FALSE);\n\t}\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tThe node pointer is actually back a bit from the \"normal\" pointer.\n\t*/\n\tnode = (MemChain_Type *) buffer;\n\tnode--;\n\n\t/*\n\t**\tGet pointer to actual allocated node and unlink it from the used\n\t**\tmemory chain.\n\t*/\t\n\tsize = node->Size;\n\tMemNode_Unlink(pool, FALSE, node);\n\tMemNode_Insert(pool, TRUE, node, size, -1, TRUE);\n\n\t/*\n\t**\tReflect the new free memory into the total memory count.\n\t*/\n\tpool->FreeMem += size;\n\n\treturn(TRUE);\n}\n\n\n/***************************************************************************\n * Mem_Reference -- Updates the reference time for the specified memory blo*\n *                                                                         *\n *    This routine is used to update the memory reference time for the     *\n *    specified memory node.  Typically, this is called every time a       *\n *    memory block is used in order to make sure the memory block time     *\n *    tracking (Last Recently Used) system works properly.                 *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   The node pointer must be valid.  For maximum safety this    *\n *             routine should be called right after Mem_Find().            *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid Mem_Reference(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node;\n\tnodeptr--;\n\n\tnodeptr->Time = (unsigned short)(TickCount.Time() >> 4);\n\n}\n\n\n/***************************************************************************\n * MEM_LOCK_BLOCK -- Locks a block so that it cannot be moved in cleanup.  *\n * \tBy marking a memory block in use, the memory system will never return*\n *    it as the oldest memory block.  It also makes it so that the block\t*\n *    will never be moved during a Cleanup process.                        *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:  \tIf one or more blocks are locked in a heap, Mem_Avail might *\n *             not equal Mem_Largest_Avail after a call to Mem_Cleanup.    *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid Mem_Lock_Block(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node;\n\tnodeptr--;\n\tnodeptr->Time = MEM_BLOCK_LOCKED;\n}\n\n\n/***************************************************************************\n * MEM_IN_USE -- Makes it so a block will never be returned as oldest\t\t*\n * \tBy marking a memory block in use, the memory system will never return*\n *    it as the oldest memory block.  It still can be moved in the Cleanup *\n *    code.                                                                *\n *                                                                         *\n * INPUT:   node  -- Pointer to memory block returned from Mem_Find.       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS: Mem_Find_Oldest() will return NULL if only IN_USE blocks are  *\n *           in memory.                                                    *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid Mem_In_Use(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return;\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node - 1;\n\tnodeptr->Time = MEM_BLOCK_IN_USE;\n}\n\n\n/***************************************************************************\n * Mem_Find -- Returns with pointer to specified memory block.             *\n *                                                                         *\n *    Use this routine to convert a memory ID value into an actual memory  *\n *    pointer.  It sweeps through all of the 'cached' memory blocks and    *\n *    returns with the matching block pointer.                             *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache block.                 *\n *                                                                         *\n *          id       -- The ID of the block desired.                       *\n *                                                                         *\n * OUTPUT:  Returns with the pointer to the memory block.  If NULL is      *\n *          returned then the desired block is not in the memory cache.    *\n *                                                                         *\n * WARNINGS:   This routine may return NULL if the memory block is not     *\n *             present in the cache.                                       *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Find(void *poolptr, unsigned long id)\n{\n\tMemPool_Type\t*pool;\t\t\t// pointer to structure.\n\tMemChain_Type\t*node;\t\t\t// Working node structure.\n\n\tif (!poolptr) return(NULL);\n\n\tpool = (MemPool_Type *) poolptr;\n\t\t\n\t/* \n\t** Cannot free a node that is not on the UsedChain list.\n\t*/\n\tif (!pool->UsedChain) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tSweep through entire allocation chain to find\n\t**\tthe one with the matching ID.\n\t*/\n\tnode = pool->UsedChain;\n\twhile (node) {\n\t\t\n\t\tif (node->ID == id) {\n\t\t\treturn(node + 1);\n\t\t}\n\t\tnode = node->Next;\n\t}\n\treturn(NULL);\n}\n\n\n/***************************************************************************\n * MEM_GET_ID -- Returns ID of node.                                       *\n *                                                                         *\n * INPUT:  void *node - pointer to node. \t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT: The ID of the node that was supplied by user during Mem_Alloc().*\n *                                                                         *\n * WARNINGS: pointer to node must be one that Mem_Alloc or                \t*\n *           Mem_Find returned.                                           **\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nunsigned long Mem_Get_ID(void *node)\n{\n\tMemChain_Type\t*nodeptr;\t\t// Pointer of current memory node.\n\n\tif (!node) return (0L);\n\n\t// Get to the node header.\n\tnodeptr = (MemChain_Type *) node - 1;\n\treturn (nodeptr->ID);\n}\n\n\n/***************************************************************************\n * Mem_Find_Oldest -- Returns with the memory block with the oldest time st*\n *                                                                         *\n *    Use this routine to find the memory block with the oldest time stamp *\n *    value.  Typically, this is used when freeing memory blocks in the    *\n *    cache in order to make room for a new memory block.                  *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns with the pointer to the oldest memory block.  If NULL  *\n *          is returned, then the memory cache is empty.                   *\n *                                                                         *\n * WARNINGS:   This routine could return NULL.                             *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Optimized for low memory caches.                     *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *   04/15/1994 SKB : Handle time wrap, locked blocks, and no_refenece blocks*\n *=========================================================================*/\nvoid *Mem_Find_Oldest(void *poolptr)\n{\n\tMemChain_Type\t*node; \t\t\t\t// Working node pointer.\n\tMemChain_Type\t*oldnode;\t\t\t// Pointer to oldest block.\n\tunsigned int\toldtime;\t\t\t\t// Time of oldest block.\n\tunsigned int\tbasetime;\t\t\t// Time to mark our base time with.\n\tunsigned int\ttime;\t\t\t\t\t// basetime + time of node.\n\n\tif (!poolptr) return(NULL);\n\n\t/*\n\t**\tSweep through entire allocation chain to find\n\t**\tthe oldest referenced memory block.\n\t*/\n\toldnode = NULL;\n\toldtime = 0;\n\tnode = ((MemPool_Type*) poolptr)->UsedChain;\n\n  basetime = (unsigned int)(TickCount.Time() >> 4);\n\n\twhile (node) {\n\n\t\t/*\n\t\t** Don't allow MEM_BLOCK_IN_USE or MEM_BLOCK_LOCKED to be returned.\n\t\t*/\n\t\tif (node->Time > MEM_BLOCK_LOCKED) {\n\n\t\t\t/*\n\t\t\t** Adjust time for wrap around (after about 5 hrs).\n\t\t\t** times less then the base time will wrap up high while\n\t\t\t** and times greater then base time will then be lower since\n\t\t\t** any time greater has been on the thing a long time.\n\t\t\t*/\n\t\t\ttime = node->Time - basetime ;\n\n\t\t\tif (time < oldtime || !oldnode) {\n\t\t\t\toldtime = time;\n\t\t\t\toldnode = node;\n\t\t\t}\n\t\t}\n\t\tnode = node->Next;\n\t}\n\n\t/*\n\t**\tReturn with the value that matches the pointer that\n\t**\twas allocated by the system previously.\n\t*/\n\tif (oldnode) {\n\t\toldnode++;\n\t}\n\treturn(oldnode);\n}\n\n\n/***************************************************************************\n * Mem_Free_Oldest -- Find and free the oldest memory block.               *\n *                                                                         *\n *    This routine is used to free the oldest memory block in the memory   *\n *    cache.  This routine is typcially used in order to create more room  *\n *    in the cache for a new allocation.                                   *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns with the node that it freed.  Although this node is    *\n *          is no longer valid, it may be used to mark that pointer as     *\n *          invalid in the main code.                                      *\n *                                                                         *\n * WARNINGS:   If this routine returns NULL, then no memory was freed.     *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid *Mem_Free_Oldest(void *poolptr)\n{\n\tMemChain_Type\t*node;\t\t// Copy of pointer to oldest node.\n\n\tif (!poolptr) return(NULL);\n\tnode = (MemChain *) Mem_Find_Oldest(poolptr);\n\tif (Mem_Free(poolptr, node)) {\n\t\treturn(node);\n\t}\n\treturn(NULL);\n}\n\n/***************************************************************************\n * MEM_POOL_SIZE -- Returns total amount of memory in pool.                *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  long total size of pool. i.e. largest possible allocation if   *\n *          no memory was allocated.                                       *\n *                                                                         *\n * WARNINGS: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Mem_Pool_Size(void *poolptr)\n{\n\tMemPool_Type\t*pool;\t\t\t// Memory pool control structure.\n\tlong\t\t\t\tmemtotal;\t\t// Total amount of memory free.\n\n\tif (!poolptr) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\tmemtotal = ((long)pool->TotalMem) << 4;\n\tmemtotal -= sizeof(MemChain_Type);\n\tmemtotal = MAX(memtotal, (long)0);\n\treturn(memtotal);\n}\n\n/***************************************************************************\n * Mem_Avail -- Returns the amount of free memory available in the cache.  *\n *                                                                         *\n *    This routine examines the memory cache and returns the amount of     *\n *    free memory available.  This memory total MAY be fragmented but      *\n *    after Mem_Cleanup() is called, an allocation of the amount returned  *\n *    by this function is guaranteed.                                      *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns the largest allocation possible from the memory cache. *\n *                                                                         *\n * WARNINGS:   The value returned may represent the FRAGMENTED total       *\n *             amount of memory free in the cache.                         *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nlong Mem_Avail(void *poolptr)\n{\n\tMemPool_Type\t*pool;\t\t// Memory pool control structure.\n\tlong\t\t\t\tmemtotal;\t// Total amount of memory free.\n\n\tif (!poolptr) return(NULL);\n\tpool = (MemPool_Type *) poolptr;\n\n\tmemtotal = ((long)pool->FreeMem) << 4;\n\tmemtotal -= sizeof(MemChain_Type);\n\t//memtotal -= sizeof(MemChain_Type) + 15;\n\tmemtotal = MAX(memtotal, (long)0);\n\treturn(memtotal);\n}\n\n\n/***************************************************************************\n * MEM_LARGEST_AVAIL -- Largest free block available.                      *\n * \tThis routine examines the free node list to find the largest block   *\n *\t\tavailable.  User can Mem_Alloc() this return size successfully.      *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  Returns largest allocation currently possible from the cache. \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/15/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong Mem_Largest_Avail(void *poolptr)\n{\n\tMemChain_Type\t*node;\t\t\t// Pointer to current memory node.\n\tunsigned int\tsize;\n\tlong\t\t\t\ttruesize;\t\n\n\t/*\n\t** Make sure that it is a buffer.\n\t*/\n\tif (!poolptr) return(NULL);\n\n\t/*\n\t** Go through the entire free chain looking for the largest block.\n\t*/\n\tnode = ((MemPool_Type *)poolptr)->FreeChain;\n\tsize = 0;\n\twhile (node) {\n\n\t\t/*\n\t\t**\tFetch free memory chunk block and see if it is big enough.\n\t\t*/\n\t\tif (node->Size >= size) {\n\t\t\tsize = node->Size;\n\t\t}\n\t\tnode = node->Next;\n\t}\n\n\ttruesize = (long)size << 4;\n\ttruesize -= sizeof(MemChain_Type);\n\ttruesize = MAX(truesize, 0L);\n\treturn (truesize);\n}\n\n\n/***************************************************************************\n * Mem_Cleanup -- Performs a garbage collection on the memory cache.       *\n *                                                                         *\n *    This routine is used to coalesce all adjacent free blocks of         *\n *    memory in the specified cache.  As a result, all previous pointers   *\n *    provided by Mem_Find() are invalidated.  This routine consumes a     *\n *    fair amount of time and should be called as infrequently as          *\n *    possible.                                                            *\n *                                                                         *\n * INPUT:   poolptr  -- Pointer to the memory cache.                       *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine takes a significant amount of time!            *\n *             If there are locked block in memory, the pool may still     *\n *             be fragmented.                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   08/06/1993 JLB : Updated for low memory caches.                       *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nvoid Mem_Cleanup(void *poolptr)\n{\n\tMemPool_Type\t*pool;  \t// Memory pool control structure.\n\tMemChain_Type\t*free,\t// Pointer to first free area.\n\t\t\t\t\t\t*cur;\t\t// Pointer to first used block that is after free.\n\tunsigned long\tsize;\n\tunsigned long\tfreesize;// Size of free heap at the end of the block.\n\n\tif (!poolptr) return;\n\n\t/*\n\t**\tFetch working copy of pool control structure.\n\t*/\n\tpool = (MemPool_Type *) poolptr;\n\n\t/*\n\t**\tBasic parameter and condition legality checks.  If the memory pool\n\t**\thas no free space, no free blocks, or no allocated blocks, then \n\t**\tmemory cleanup is unnecessary -- just exit.\n\t*/\n\tif (!pool->FreeMem || !pool->FreeChain || !pool->UsedChain) return;\n\n\tfreesize = pool->FreeMem;\n\tfree = pool->FreeChain;\n\tpool->FreeChain = NULL;\n\tcur = pool->UsedChain;\n\twhile (TRUE) {\n\n\t\t/*\n\t\t** Setup pointers so that free points to the first free block and cur\n\t\t** points to the next used block after the free block.\n\t\t*/\n\t\twhile (cur < free && cur) {\n\t \t\tcur = cur->Next;\n\t\t}\n\n\t\t// All used blocks are at the front of the free.  We are done.\n\t\tif (!cur) {\n\t \t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t** Do not allow a locked block to be moved.\n\t\t*/\n\t\tif (cur->Time == MEM_BLOCK_LOCKED) {\n\t\t\t/* \n\t\t\t** Figure the size of the new free block that we are creating.\n\t\t\t** Subtract off the total block size.\n\t\t\t** Add the node to the free list.\n\t\t\t*/\n\t\t\tsize = (char *) cur - (char  *) free;\n\t\t\tsize >>= 4;\n\t\t \tfreesize -= size;\n\t\t\tMemNode_Insert(pool, TRUE, free, (unsigned int) size, -1, FALSE);\n\n\t\t\t/*\n\t\t\t** Time to find a new free position to start working from.\n\t\t\t** Cur will be in the position just following.\n\t\t\t*/\n\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, (unsigned long)cur->Size << 4);\n\t\t\tcur = cur->Next;\n\t\t\twhile (free == cur) {\n\t\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, (unsigned long)cur->Size << 4);\n\t\t\t\tcur = cur->Next;\n\t\t\t}\n\n\t\t\t// All used blocks are at the front of the free.  We are done.\n\t\t\tif (!cur) {\n\t\t\t \tbreak;\n\t\t\t}\n\t\t} else {\n\n\t\t\t// Copy the block up.\n\t\t\tsize = (unsigned long)cur->Size << 4;\n\t\t\tMem_Copy(cur, free, size);\n\t\t\tcur = free;\n\n\t\t\t// Change pointers of surrounding blocks.\n\t\t\tif (cur->Next) {\n\t\t \t\tcur->Next->Prev = cur;\n\t\t\t}\n\t\t\tif (cur->Prev) {\n\t\t \t\tcur->Prev->Next = cur;\n\t\t\t} else {\n\t\t \t\tpool->UsedChain = cur;\n\t\t\t}\n\n\t\t\t// Change to next new free area.\n\t\t\tfree = (MemChain_Type *) Add_Long_To_Pointer(cur, size);\n\t\t}\n\t}\n\n\t/*\n\t**\tNow build the single free chunk.\n\t*/\n\tMemNode_Insert(pool, TRUE, free, freesize, -1, FALSE);\n}\n\n\n/***************************************************************************\n * MemNode_Unlink -- Unlinks a node from the cache.                        *\n *                                                                         *\n *    A private routine the actually unlinks a memory block from the       *\n *    memory cache.  It doesn't perform a complete update of the memory    *\n *    cache.                                                               *\n *                                                                         *\n * INPUT:   pool     -- Pointer to the memory cache header (copy in real   *\n *                      memory).                                           *\n *                                                                         *\n *          freechain-- Is the block part of the free memory chain?        *\n *                                                                         *\n *          node     -- Pointer to the node that will be unlinked.         *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine doesn't update memory totals.  It is a support *\n *             function.                                                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *   04/13/1994 SKB : Update for 32 bit library, removed XMS calls, \t\t\t*\n *\t\t\t\t\t\t\t optimized for low memory only.\t\t\t\t\t\t\t\t*\n *=========================================================================*/\nPRIVATE void MemNode_Unlink(MemPool_Type *pool, int freechain, MemChain_Type *node)\n{\n\tMemChain_Type\t*other; \t\t// Copy of node data to unlink.\n\tMemChain_Type\t**chain;\t\t// A pointer to one of the chains pointer.\n\n\t/*\n\t**\tCheck for parameter validity.\n\t*/\n\tif (!pool || !node) return;\n\t\n\t/*\n\t**\tSetup working pointer for the particular chain desired.\n\t*/\t\n\tif (freechain) {\n\t\tchain = &pool->FreeChain;\n\t} else {\n\t\tchain = &pool->UsedChain;\n\t}\n\t\n\t/*\n\t**\tMake adjustments to the previous node.  If the pointer\n\t**\tto the previous node is NULL then this indicates the\n\t**\tfirst node in the list and thus the chain pointer needs\n\t**\tto be updated instead.\n\t*/\n\tif (node->Prev) {\n\t\tother = node->Prev;\n\t\tother->Next = node->Next;\n\t} else {\n\t\t*chain = node->Next;\n\t}\n\n\tif (node->Next) {\n\t\tother = node->Next;\n\t\tother->Prev = node->Prev;\n\t}\n}\n\n\n/***************************************************************************\n * MemNode_Insert -- Inserts a node into a cache chain.                    *\n *                                                                         *\n *    This routine is used to add a node to a cache chain.  Since nodes    *\n *    do not contain double links, they must be placed in sequence.        *\n *                                                                         *\n * INPUT:   pool     -- Pointer to memory pool (must be in real memory).   *\n *                                                                         *\n *          freechain-- Is the node to be inserted into the free chain?    *\n *                                                                         *\n *          node     -- Pointer to the node to insert.                     *\n *                                                                         *\n *          size     -- Size of the memory block (in paragraphs).          *\n *                                                                         *\n *          id       -- The ID number to associate with this block.        *\n *                                                                         *\n *          merge    -- Merge inserted block with adjacent blocks.         *\n *                                                                         *\n * OUTPUT:  return                                                         *\n *                                                                         *\n * WARNINGS:   This is a support routine.                                  *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/06/1993 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void MemNode_Insert(MemPool_Type *pool, int freechain, MemChain_Type *node, unsigned int size, unsigned long id, int merge)\n{\n\tMemChain_Type \t**chain;\t\t\t// Pointer to chain that will be linked.\n\tMemChain_Type \t*prev,\t\t\t// Successor node pointer.\n\t\t\t\t\t\t*next;\t\t\t// Predecessor node pointer.\n\tint\t\t\t\tdoit=TRUE;\t\t// Link the node into the list.\n\n\n\t/*\n\t**\tDetermine if the parameters are valid.\n\t*/\n\tif (!pool || !node || !size) return;\n\n\t/*\n\t**\tSetup working pointer for the particular chain desired.\n\t*/\t\n\tif (freechain) {\n\t\tchain = &pool->FreeChain;\n\t} else {\n\t\tchain = &pool->UsedChain;\n\t}\n\n\t/*\n\t**\tHandle the \"no node in list\" condition (easiest).\n\t*/\n\tif (!*chain) {\n\t\tnode->Next = NULL;\n\t\tnode->Prev = NULL;\n\t\tnode->Size = size;\n\t\tnode->Time = (unsigned short)(TickCount.Time() >> 4);\n\t\tnode->ID = id;\n\t\t*chain = node;\n\t\treturn;\n\t}\n\n\t/*\n\t**\tSweep through the memory chain looking for a likely spot\n\t**\tto insert the new node.  It will stop with \"next\" pointing\n\t**\tto the node to come after the block to be inserted and \"prev\"\n\t** will point to the node right before.\n\t*/\n\tprev = NULL;\n\tnext = *chain;\n\twhile (next && (next < node)) {\n\n\t\t/*\n\t\t**\tMove up the memory chain.\n\t\t*/\n\t\tprev = next;\n\t\tnext = next->Next;\n\t}\n\n\t/*\n\t**\tCoallescing of adjacent blocks (if requested).\n\t*/\n\tif (merge) {\n\t\t\n\t\t/*\n\t\t**\tIf the previous block is touching the block to insert\n\t\t**\tthen merely adjust the size of the previous block and\n\t\t**\tthat is all that is necessary.\n\t\t*/\n\t\tif (prev) {\n\t\t\tif (((char *)prev + ((long)prev->Size << 4)) == ((char *) node)) {\n\t\t\t\tprev->Size += size;\n\t\t\t\tsize = prev->Size;\n\t\t\t\tnode = prev;\n\t\t\t\tprev = prev->Prev;\n\t\t\t\tdoit = FALSE;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf the following block is touching the block to insert\n\t\t**\tthen remove the following block and increase the size of\n\t\t**\tthe original insertion block by the size of the other\n\t\t**\tblock.\n\t\t*/\n\t\tif (next) {\n\t\t\tif (((char *)node + ((long)size << 4)) == (char *)next) {\n\t\t\t\t\n\t\t\t\tif (!doit) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the node was already merged with the previous block\n\t\t\t\t\t**\tthen merely increase the previous block's size\n\t\t\t\t\t**\tand adjust it's next pointer appropriately.\n\t\t\t\t\t*/\n\t\t\t\t\tnode->Size += next->Size;\n\t\t\t\t\tnode->Next = next->Next;\n\t\t\t\t\tnext = next->Next;\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIncrease the size of the current block and adjust\n\t\t\t\t\t**\tthe \"next\" pointer so that it gets fixed up\n\t\t\t\t\t**\taccordingly.\n\t\t\t\t\t*/\n\t\t\t\t\tsize += next->Size;\n\t\t\t\t\tnext = next->Next;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n#if DEBUG_FILL\n\tif (doit) {\n\t\tmemset(node + 1, 0xFF, (size - 1) << 4);\n\t} else {\n\t\tmemset(node + 1, 0xFF, (node->Size - 1) << 4);\n\t}\n#endif\n\n\t/*\n\t**\tFixup the node pointers.\n\t*/\n\tif (prev) {\n\t\tprev->Next = node;\n\t}else{\n\t\t*chain = node;\n\t}\n\n\tif (next) {\n\t \tnext->Prev = node;\n\t}\n\n\tif (doit) {\n\t\tnode->Prev = prev;\n\t\tnode->Next = next;\n\t\tnode->Size = size;\n\t\tnode->Time = (unsigned short)(TickCount.Time() >> 4);\n\t\tnode->ID = id;\n\t}\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "WWFLAT32/SRCDEBUG/MEM_COPY.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : LIBRARY                                  *\n;*                                                                         *\n;*                    File Name : MEM_COPY.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott Bowen\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : September 8, 1994\t[IML]              *\n;*                  Ported to watcom c32 : 01/03/96     [JRJ]                                                                        *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Mem_Copy -- Copies from one pointer to another.                       *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nLOCALS ??\n\n\n;******************************************************************************\n; Much testing was done to determine that only when there are 14 or more bytes\n; being copied does it speed the time it takes to do copies in this algorithm.\n; For this reason and because 1 and 2 byte copies crash, is the special case\n; used.  SKB 4/21/94.  Tested on 486 66mhz.\nOPTIMAL_BYTE_COPY\tequ\t14\n\n\n;******************************************************************************\n; External declares so these functions can be called\n;\nGLOBAL \tMem_Copy\t: NEAR\nGLOBAL  Largest_Mem_Block : near\n\nCODESEG\n\n\n;***************************************************************************\n;* MEM_COPY -- Copies from one pointer to another.                         *\n;* This routine copies bytes from source to dest.  It takes care of\t   *\n;* overlapped memory, and unsigned long copies.\t\t\t\t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/18/1994 SKB : Created.                                             *\n;*=========================================================================*\n; void Mem_Copy(void *source, void *dest, unsigned long bytes_to_copy);\n\n\nPROC Mem_Copy \tC near \n\tUSES\tecx , esi , edi , ebx\n\tARG\tsource:DWORD\n\tARG\tdest:DWORD\n\tARG\tbytes:DWORD\n\t\t\n;********************************* Setup ******************************************\n\tcld\n\tmov\tesi,[source]\n\tmov\tedi,[dest]\n\tmov\tecx,[bytes]\t; get number of bytes to copy.\t\n\n     ; check pointers for singularities\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tje\t??done\t\t; No sence in copying the same pointer.\t\n\tor\tesi,0\n\tjz\t??done\n\tor\tedi,0\n\tjz\t??done\n\n\tcmp\tecx,OPTIMAL_BYTE_COPY  ; see notes above about equate.\n\tjge\t??normal      \t       ; If >= MAX(2,OPTIMAL_BYTE_COPY), do normal dword copy.\n\n;******************************** Special case <= 2 *******************************\n;\n; This section must be called for bytes <= 2 since the other case will crash.  It\n; optionally uses OPTIMAL_BYTE_COPY for the cut off point.  This is because after\n; extensive testing, it was proved that only at that point (14 or more bytes) does\n; it become quicker to use the dword copy method.\n\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tjge\t??do_move\t; if source greater do forward copy.\n\tlea\tesi,[esi+ecx-1]\n\tstd\t\t\t; Opps, wrong, force the pointers to decrement.\n\tlea\tedi,[edi+ecx-1]\n??do_move:\n\trep\tmovsb\t\t; move the one or two bytes.\n\tcld\n??done:\n\tret\n\n;************************** back or forth, that is the question *******************\n\n??normal:\n\tmov\tebx,ecx\n\tcmp\tesi,edi\t\t; Compare source with dest.\n\tjge\t??forward\t; if source greater do forward copy.\n\n;********************************* Backward ***************************************\n??backward:\n\tlea\tecx,[edi+ebx]\n\tstd\n\tlea\tedi,[edi+ebx-1]\n\tand\tecx,3\t\t; Get non aligned bytes.\n\tlea\tesi,[esi+ebx-1]\n\tsub\tebx,ecx\t\t; remove that from the total size to be copied later.\n\trep\tmovsb\t\t; do the copy.\n\tsub\tesi,3\n\tmov\tecx,ebx\t\t; Get number of bytes left.\n \tsub\tedi,3\n\tshr\tecx,2\t\t; Do 4 bytes at a time.\n\trep\tmovsd\t\t; do the dword copy.\n\tmov\tecx,ebx\n\tadd\tesi,3\n\tadd\tedi,3\n\tand\tecx,03h\n\trep\tmovsb\t\t; finnish the remaining bytes.\n\tcld\n\tret\n\n;********************************* Forward ***************************************\n??forward:\n\tcld\n\tmov\tecx,edi\t\t; get destination pointer.\t\n\tneg\tecx\n\tand\tecx,3\t\t; Get non aligned bytes.\n\tsub\tebx,ecx\t\t; remove that from the total size to be copied later.\n\trep\tmovsb\t\t; do the copy.\n\tmov\tecx,ebx\t\t; Get number of bytes left.\n\tshr\tecx,2\t\t; Do 4 bytes at a time.\n\trep\tmovsd\t\t; do the dword copy.\n\tmov\tecx, ebx\n\tand\tecx,03h\n\trep\tmovsb\t\t; finnish the remaining bytes.\n\tret\n\nENDP\tMem_Copy\n\nPROC Largest_Mem_Block \tC near \n\tuses\tesi , edi , ebx , ecx , edx\n\tlocal\tmem_struct : dword : 16\n\n\tmov\teax , 0500h\n\tlea\tedi , [ mem_struct ]\n\tint\t31h\n\tmov\teax , [ mem_struct ]\n\n\tret\nENDP Largest_Mem_Block\n\nEND\n\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/SRCDEBUG/MOUSE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*\t\t\t\t  (Mouse Routines)\t\t\t   *\n;*                                                                         *\n;*                    File Name : MOUSE.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : August 26, 1994                          *\n;*                                                                         *\n;*                  Last Update : November 3, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Install_Mouse -- Initializes mouse driver and verifies mouse exists   *\n;*   Remove_Mouse -- uninstalls the mouse interrupt by disabling the call  *\n;*   Get_Mouse_X -- Returns the mouses x pixel position                    *\n;*   Get_Mouse_Y -- Returns the mouse's y pixel position                   *\n;*   Get_Mouse_Button -- Gets the values of the mouse button               *\n;*   Set_Mouse_Cursor -- Sets the shape to be used as the mouse.           *\n;*   Low_Hide_Mouse -- Low-level routine which hides the mouse\t\t   *\n;*   Low_Show_Mouse -- Low level routine which shows the mouse\t\t   *\n;*   Mouse_Shadow_Buffer -- Handles storing and restoring the mouse buffer *\n;*   Draw_Mouse -- Handles drawing the mouse cursor\t\t\t   *\n;*   Hide_Mouse -- Hides mouse cursor on screen if it was show             *\n;*   Show_Mouse -- Display mouse cursor on screen if it was hidden         *\n;*   Conditional_Hide_Mouse -- Hides mouse if its with given region        *\n;*   Conditional_Show_Mouse -- shows mouse if it was conditionally hidden  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\n;WARN\t\t\t\t; generate all warnings we can\n;JUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Include all of the keyboard specific defines\n;---------------------------------------------------------------------------\nINCLUDE \"keystruc.inc\"\nINCLUDE \"shape.inc\"\ninclude \"svgaprim.inc\"\n\nDOS_SYS_CALL\t\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nRESTORE_VISIBLE_PAGE\tEQU\t0\nSTORE_VISIBLE_PAGE\tEQU\t1\nCONDHIDE\t\tEQU\t08000H\t\t; bit for testing conditional region\nCONDHIDDEN\t\tEQU\t04000H\t\t; bit for testing conditional hidden\n;---------------------------------------------------------------------------\n; Define any data which needs to be global...\n;---------------------------------------------------------------------------\n\nGLOBAL\tRealModePtr:DWORD\nGLOBAL\tMInstalled:DWORD\nGLOBAL\tMouseBuffer:DWORD\nGLOBAL\tLCW_Uncompress:NEAR\n\nGLOBAL\tGet_Shape_Uncomp_Size     :NEAR\nGLOBAL\tGet_Shape_Width      \t  :NEAR\nGLOBAL\tGet_Shape_Original_Height :NEAR\nGLOBAL  Size_Of_Region\t\t  :NEAR\nGLOBAL\t_ShapeBuffer\t\t  :DWORD\n\nGLOBAL  XRes\t: dword\nGLOBAL  YRes\t: dword\n\n\nGLOBAL\tVesaFunc : dword\nGLOBAL\tVesa_XRes : near\nGLOBAL\tVesa_YRes : near\n\n\n\n\n\nDPMI_INTR\tEQU\t31h\t\n\n\nSTRUC DPMI_REGS\n       _edi  dd ?\n       _esi  dd ?\t\n       _ebp  dd ?\t\n       \t     dd ?\n       _ebx  dd ?\t\n       _edx  dd ?\t\n       _ecx  dd ?\t\n       _eax  dd ?\t\n       Flags dw ?\n       _es   dw ?\n       _ds   dw ?\n       _fs   dw ?\n       _gs   dw ?\n       _ip   dw ?\n       _cs   dw ?\n       _sp   dw ?\n       _ss   dw ?\n       \t     dd ?\n\t     dd ?\n  nothing    dd ?\t\t\t\nENDS\n\n\n\n;---------------------------------------------------------------------------\n; Now lets handle any data in the data segment\n;---------------------------------------------------------------------------\n\tDATASEG\n\nRealInt\t\tDPMI_REGS <>\t; structure to call a real mode int\nMInstalled\tDD\t0\t\t; is the mouse installed?\nMouseCursor\tDD\t0\nMouseBuffer\tDD\t0\nBufferWidth\tDD\t0\nBufferHeight\tDD\t0\nBufferSize\tDD\t0\nPrevMousePtr\tDD\t0\nMouseBufferSel\tDD\t0\n\n\nDraw_Mouse\t\tdd\tVGA_Draw_Mouse\nMouse_Shadow_Buffer\tdd\tVGA_Mouse_Shadow_Buffer\n\n;---------------------------------------------------------------------------\n; Time to write some code\n;---------------------------------------------------------------------------\n\tCODESEG\n\n;***************************************************************************\n;* INSTALL_MOUSE -- Initializes mouse driver and verifies mouse connected  *\n;*                                                                         *\n;* First check the mouse interupt to see if the vector is pointing to zero *\n;* page.  If it is not then make sure it is not pointing to an IRET.  If   *\n;* not call the mouse reset to verify that the hardware is attached.\t   *\n;*                                                                         *\n;* INPUT:\tint mouse_max_width  - the max width of the mouse cursor   *\n;*\t\tint mouse_max_height - the max height of the mouse cursor  *\n;*\t\tint screen_width     - width of the physical screen\t   *\n;*\t\tint screen_height    - height of the physical screen\t   *\n;*                                                                         *\n;* OUTPUT:      TRUE is mouse driver is initialized, FALSE if unable to    *\n;*\t\tinitialize mouse driver.\t\t\t\t   *\n;*                                                                         *\n;* PROTO:\tint Install_Mouse(\tint mouse_max_width,\t\t   *\n;*\t\t\t\t\tint mouse_max_height,\t\t   *\n;*\t\t\t\t\tint screen_width,\t\t   *\n;*\t\t\t\t\tint screen_height);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/26/1994 PWG : Created.                                             *\n;*=========================================================================*\nGLOBAL\tInstall_Mouse:NEAR\nPROC\tInstall_Mouse C NEAR \n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\tmouse_max_width:DWORD\n\tARG\tmouse_max_height:DWORD\n\tARG\tscreen_width:DWORD\n\tARG\tscreen_height:DWORD\n\n\n\t;*=========================================================================*\n\t;* Initialize all of the general mouse variables\n\t;*=========================================================================*\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\ttest\tesi , esi\t\t\t; mouse driver should be install\n\tjz \t??exit\t\t\t\t; after keyboard interrup is install\n\tmov\teax , [ XRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseX],eax\t; set the mouses x coordinate to 160\n\tmov\teax , [ YRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseY],eax\t; set the mouses y coordinate to 100\n\tmov\t[(KeyboardType esi).MState],1\t; flag the mouse as hidden\n\tmov\t[(KeyboardType esi).MCState],0\t; turn off conditional region\n\tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi).MouseRight],eax\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi).MouseBottom],eax\n\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 0200, bl = number of interrupt to get\n\t; output cf error, cx,dx= address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,033h\t\t\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\t\t\t; no mouse driver present\n\n\t;*=========================================================================*\n\t;* If the interupt vector is pointing to 0000:0000h, there is no mouse\n\t;*=========================================================================*\n\tmov\tax,cx\n\tor\tax,dx\t\t\n\tjz\tshort ??nomouse\n\n\tand\tedx , 0ffffh\n\tand\tecx , 0ffffh\n\tshl\tecx,4\n\tadd\tecx,edx\n\n\t;*=========================================================================*\n\t;* If the first instruction is an IRET, there is no mouse\n\t;*=========================================================================*\n\n\tcmp\t[byte ptr ecx],0CFH\t; is this an IRET\n\tjne\tshort ??mouse_buff\t; if it isnt then reset the mouse\n\n??nomouse:\n\tmov\teax,FALSE\t\t\t\t; flag no mouse driver\n\tmov\t[MInstalled],FALSE\t\t\t; flag no mouse driver\n    \tjmp\t??exit\t\t\t\t\t; exit\n\n??mouse_buff:\n\t;*=========================================================================*\n\t;* Allocate two real mode memory buffers for the mouse cursor and the \n\t;*\tmouse shadow\n\t;*=========================================================================*\n\tmov\teax,[mouse_max_width]\t       \t; get the is max width\n\tmov\t[BufferWidth],eax\t       \t; save it off for set cursor\n\tmov\tedx,[mouse_max_height]\t       \t; get the max height\n\tmov\t[BufferHeight],edx\t       \t; save it off for set cursor\n\tmul\tedx\t\t\t       \t; size = max_width * max_height\n\tadd\teax,22\t\t\t       \t; add width/height(8) + para align(15)\n\tand\tal, 0f0h\t\t       \t; now size is even paragraphs\n\tmov\t[BufferSize],eax\t       \t; store off the buffer size\n\tshl\teax,1\t\t\t       \t; make two of them\n\n \tmov\tebx,eax\t\t\t\t; get size of RM binary.\n\tmov\tecx,eax\t\t\t\t; ecx will use it later.\n\tadd\tebx,15\t\t\t\t; round up \n\tshr\tebx,4\t\t\t\t; convert to pages.\n\tmov\teax,0100h\t\t\t; alloc real buffer\n\tint\tDPMI_INTR\t \t\t; do call.\n\tjc\t??error\t\t \t\t; check for error.\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tmov\t[MouseBufferSel], edx\n\tshl\teax , 16\n\tmov\t[(KeyboardType esi).MouseCursor],eax\t; store off the real mode segment\n\tmov\tedx,eax\t\t\t\t\t; get the buffer position\n\tadd\tedx,[BufferSize]\t\t\t; add in the buffer size\n\tmov\t[(KeyboardType esi).MouseBuffer],edx\t; store off the real mode segment\n\tshr\teax,12\t\t\t\t\t; convert the seg/off to 32 bit offset\n\tmov\tedx,eax\n\tadd\tedx,[BufferSize]\n\tmov\t[MouseCursor],eax\t\t\t; store it off in the mouse buffer\n\tmov\t[MouseBuffer],edx\t\t\t; store it off in the mouse buffer\n\n\tmov\teax,0600h\t\t\t\t; function number.\n\tmov\tecx,[MouseCursor]\t\t\t; ecx must have start of memory.\n\tmov\tedi,[BufferSize]\n\tshl\tedi,1\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n       \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n\n??begin:\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\t; Reset mouse thru int 33h funtion 0\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\txor\tecx , ecx\n\tmov\t[RealInt . _eax ] , 0\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\tmov\teax ,[RealInt . _eax]\n\tcmp\tax,-1\t\t\t\t\t; was the mouse attached to system\n      \tjne\t??nomouse\t\t\t\t; if not exit out of the routine\n\t\n\tmov\t[(KeyboardType esi).Adjust],0\t\t; assume we do not need to adjust mouse\n\n;***************************************************************************\n; Set the Vesa Parameters \n\n\tmov\teax , [ VesaFunc ]\n\ttest\teax , eax\n\tjz\t??set_vga_mouse\n\tmov\t[(KeyboardType esi). VesaPtr ] , eax\n\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VESA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VESA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n \tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi). MouseRight ] , eax\n\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi). MouseBottom ] , eax\n\n\tlea\tedi , [(KeyboardType esi). VesaBankTable]\n\tlea\tesi , [ BankTable ]\n\tmov\tecx , 8\n\trep\tmovsd\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tjmp\t??end_vesa\n\n??set_vga_mouse:\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VGA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VGA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n??end_vesa:\n\tcall \tReset_Mouse \n\tmov\teax , TRUE\n\tret\n\n??error:\n\tmov\teax,FALSE\n??exit:\n\tret\n\tENDP\tInstall_Mouse\n\n;***************************************************************************\n;* ResET_MOUSE -- Reset mouse to a new graphif mode\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* reset mouse driver funtions to a a currently graphic mode\t\t   *\t\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;* PROTO:\tReset_Mouse ( void ) \t\t\t\t\t   *\t\n;*\t\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/26/1994 JRJ : Created.                                             *\n;*=========================================================================*\nGLOBAL\tReset_Mouse:NEAR\nPROC\tReset_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\n\t;*=========================================================================*\n\t;* Initialize all of the general mouse variables\n\t;*=========================================================================*\n\tmov\tesi , [RealModePtr]\t\t; get offset of real mode data start\n\ttest\tesi , esi\n\tjz\t??exit\n\tmov\teax , [ XRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseX],eax\t; set the mouses x coordinate to 160\n\tmov\teax , [ YRes ]\n\tshr\teax , 1\n\tmov\t[(KeyboardType esi).MouseY],eax\t; set the mouses y coordinate to 100\n\tmov\t[(KeyboardType esi).MState],1\t; flag the mouse as hidden\n\tmov\t[(KeyboardType esi).MCState],0\t; turn off conditional region\n\tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi).MouseRight],eax\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi).MouseBottom],eax\n\n\n\tmov\t[(KeyboardType esi).Adjust],0\t\t; assume we do not need to adjust mouse\n\n;***************************************************************************\n; Set the Vesa Parameters \n\n\tmov\teax , [ VesaFunc ]\n\ttest\teax , eax\n\tjz\t??set_vga_mouse\n\tmov\t[(KeyboardType esi). VesaPtr ] , eax\n\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VESAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VESA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VESA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n \tmov\teax , [ XRes ]\n\tmov\t[(KeyboardType esi). MouseRight ] , eax\n\n\tmov\teax , [ YRes ]\n\tmov\t[(KeyboardType esi). MouseBottom ] , eax\n\n\tlea\tedi , [(KeyboardType esi). VesaBankTable]\n\tlea\tesi , [ BankTable ]\n\tmov\tecx , 8\n\trep\tmovsd\n\n\tmov\tesi,[RealModePtr]\t\t; get offset of real mode data start\n\tjmp\t??end_vesa\n\n??set_vga_mouse:\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseShadow ]\n\tmov\t[(KeyboardType esi). ShadowPtr] , ax\n\n\tmov\tax ,  [(KeyboardType esi). VGAMouseDraw ]\n\tmov\t[(KeyboardType esi). DrawMousePtr ] , ax\n\n\tlea\teax , [ VGA_Draw_Mouse ]\n\tmov\t[ Draw_Mouse ] , eax\n\tlea\teax , [ VGA_Mouse_Shadow_Buffer ]\n\tmov\t[ Mouse_Shadow_Buffer ] , eax\n\n\n??end_vesa:\n       ; S Mickey/pixel Ratio cursor limits \n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 8\n\tmov\tedx , 16\n\tmov\t[RealInt . _eax ] , 0fh\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\t; Set Min/Max X pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 0\t \n\tmov\tedx , [ XRes ]\n\tcmp\tedx , 320\n\tjne\t??set_it\n\tshl\tedx , 1\n\tmov\t[(KeyboardType esi).Adjust],1\n\n??set_it:\n;\tdec\tedx\n\tmov\t[RealInt . _eax ] , 7\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\t; Set Min/Max Y pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , 0\n\tmov\tedx , [ YRes ]\n\tdec\tedx\n\tmov\t[RealInt . _eax ] , 8\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\nIF 0\n\t; Check for scale factors in X and Y pos\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\tecx , [ XRes ]\n\tmov\tedx , [ YRes ]\n\tsub\tecx , 8\n\tsub  \tedx , 16\n\tmov\t[RealInt . _eax ] , 4\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\t; Read mouse position thru int 33 funtion 3\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\txor\tecx , ecx\n\tmov\t[RealInt . _eax ] , 3\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\tmov\tecx ,[RealInt . _ecx]\n\tmov\tedx ,[RealInt . _edx]\n\n      ; compute Scale values X Y for different vendor mouse driver if nessesary\n\tadd \tecx , 8\n\tadd\tedx , 16\n\tcmp\tecx , [ XRes ]\n\tmov\t[(KeyboardType esi).Adjust_XPos],0\n\tjz\t??No_scaleX\n\tmov\t[(KeyboardType esi).Adjust_XPos],ecx\n??No_scaleX:\n\tcmp\tedx , [ YRes ]\n\tmov\t[(KeyboardType esi).Adjust_YPos],0\n\tjz\t??No_scaleY\n\tmov\t[(KeyboardType esi).Adjust_YPos],edx\n??No_scaleY:\t\nENDIF\n\n\tmov\tecx, [ XRes ]\t\t\t\t; set the mouses x coordinate to 160\n\tmov\tedx, [ YRes ]\t\t\t\t; set the mouses x coordinate to 160\n\tcmp\t[(KeyboardType esi).Adjust],1\n\tje\t??no_ecx_shift\n\tshr\tecx , 1\n??no_ecx_shift:\n\tshr\tedx , 1\n\tmov\t[MInstalled],TRUE\t\t\t; set the fact that mouse is installed\n\tmov\t[(KeyboardType esi).MDisabled],TRUE\t; disable mouse until the overlay is loaded\n\n\t; Set new Mouse position any way\n\tcall\tClear_RM_regs\n\tmov\teax , 0300h\n\tmov\tebx , 033h\n\tmov\t[RealInt . _eax ] , 4\n\tmov\t[RealInt . _ecx] , ecx \n\tmov\t[RealInt . _edx] , edx\n\txor\tecx , ecx\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n\tcall\tClear_RM_regs\n\tmov\teax, 0300h\n\tmov\tebx ,33h\t\t\t\t; mouse is in 33h\n\tmov\tecx,0\t\t\t\t\t; any mouse condition generates int\n\tmov\tedx,[RealModePtr]\t\t\t; get real mode memory address\n\tshr\tedx,4\t\t\t\t\t; convert it to a segment\n\tmov\t[RealInt. _es],dx\t\t\t; store it in the real mode es\n\tmovzx\tedx,[(KeyboardType PTR esi).MouseCodeOffset] ; Get address of code\n\tmov\t[RealInt._edx],edx\t\t\t; set edx to offset of code\n\tmov\t[RealInt._eax],12\t\t\t; set eax to set interrupt routine\n\tmov\t[RealInt._ecx],31\n\tlea\tedi, [RealInt]\n\tint\tDPMI_INTR\n\n??installed:\n\tmov\teax,TRUE  \t\t\t\t; return TRUE if all is well\n\tmov\t[(KeyboardType esi).MDisabled],FALSE\t; no 32 bit overlays installed\n\tje\t??exit\n\n??error:\n\tmov\teax,FALSE\n\n??exit:\n\tret\n\tENDP\tReset_Mouse\n\n\n\n;***************************************************************************\n;* REMOVE_MOUSE -- uninstalls the mouse interrupt by disabling the call\t   *\n;*                                                                         *\n;* This routine will uninstall the mouse interrupt.  It does this by\t   *\n;* simply disabling the call condition.  The interrupt itself is still\t   *\n;* present, just uncalled until dos removes it at program termination.\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Remove_Mouse(VOID);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tRemove_Mouse:NEAR\n\tPROC\tRemove_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\t\n\n\tcall\tClear_RM_regs\n\tcmp \t[MInstalled],FALSE\t; check to see if mouse installed\n\tje\t??exit\t\t\t; if not then no need to remove it\n\n\tmov\t[MInstalled],FALSE\t; Force to NOT-Installed.\n\n;;PWG\tcmp \t[_MSWIFTDevice],1\t; check to see if SWIFT device installed\n;;PWG\tje\tshort ??prevSWIFT\t\t; if so use previous SWIFT event handler\n\n\tmov\tebx , 033h\n\tmov\tedx,[RealModePtr]\t\t\t; get real mode memory address\n\ttest\tedx,edx\t\t\t\t\t; check that the memory block is valid\n\tjz\t??exit\n\n\tshr\tedx,4\t\t\t\t\t; convert it to a segment\n\tmov\t[RealInt._es],dx\t\t\t; store it in the real mode es\n\txor\tedx,edx\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\tmov\tdx,[(KeyboardType PTR esi).MouseCodeOffset] ; Get address of code\n\tmov\t[RealInt._edx],edx\t\t\t; set edx to offset of code\n\tmov\t[RealInt._eax],12\t\t\t; set eax to set interrupt routine\n\tmov\t[RealInt._ecx],0\n\tmov\tecx,0\t\t\t\t\t; no mouse condition generates an int\n\tmov\teax,0300h\n\tlea\tedi,[RealInt]\n\tint\tDPMI_INTR\n\n\tmov\teax,0601h\t\t\t\t; function number.\n\tmov\tecx,[MouseCursor]\t\t\t; ecx must have start of memory.\n\tmov\tedi,[BufferSize]\n\tshl\tedi,1\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n       \tint\tDPMI_INTR\t\t\t; do call.\n\n\n\t; Deallocate real memory buffer\n\tmov\tedx ,[MouseBufferSel]\n\ttest\tdx ,dx\n\tjz\t??exit\n\tmov\teax ,0101h\n\tint\tDPMI_INTR\n\n??exit:\n\tret\n\tENDP\tRemove_Mouse\n\n\n;***************************************************************************\n\nGLOBAL\tClear_RM_regs :NEAR\nPROC\tClear_RM_regs  NEAR \n\n\tpush\teax\n\tpush\tecx\n\tpush\tedi\n\tlea\tedi , [ RealInt ]\n\tlea\tecx , [ RealInt . nothing ]\n\tsub\tecx , edi\n\txor\teax , eax\n\tshr\tecx , 2\n\trep\tstosd\n\tpop\tedi\n\tpop\tecx\n\tpop\teax\n\tret\nENDP\tClear_RM_regs\n\n\n;***************************************************************************\n;* GET_MOUSE_X -- Returns the mouses x pixel position                      *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse x position in pixels\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_X(void);                                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_X:NEAR\n\tPROC\tGet_Mouse_X C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MouseX]\n\tret\n\n\tENDP\tGet_Mouse_X\n\n;***************************************************************************\n;* GET_MOUSE_STATE -- Returns the current mouse state\t\t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse's current state\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_State(void);                                 *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_State:NEAR\n\tPROC\tGet_Mouse_State C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MState]\n\tret\n\n\tENDP\tGet_Mouse_State\n\n;***************************************************************************\n;* GET_MOUSE_X -- Returns the mouses x pixel position                      *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      int - the mouse x position in pixels\t\t\t   *\n;*                                                                         *\n;* WARNINGS:    int Get_Mouse_X(void);                                     *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_Disabled:NEAR\n\tPROC\tGet_Mouse_Disabled C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmovzx\teax,[(KeyboardType esi).MDisabled]\n\tret\n\n\tENDP\tGet_Mouse_Disabled\n\t\t\t\t  \n;***************************************************************************\n;* GET_MOUSE_Y -- Returns the mouse's y pixel position                     *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:       none\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      int - the mouses y position in pixels                      *\n;*                                                                         *\n;* PROTO:\tint Get_Mouse_Y(void);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/29/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_Y:NEAR\n\tPROC\tGet_Mouse_Y C NEAR \n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(KeyboardType esi).MouseY]\n\tret\n\n\tENDP\tGet_Mouse_Y\n\n;***************************************************************************\n;* GET_MOUSE_BUTTON -- Gets the values of the mouse button                 *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tGet_Mouse_Button:NEAR\n\tPROC\tGet_Mouse_Button C NEAR \n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\n\txor\teax,eax\n\tmov\tal,[(KeyboardType esi).Button]\n\tret\n\n\tENDP\tGet_Mouse_Button\n\n;***************************************************************************\n;* SET_MOUSE_CURSOR -- Sets the shape to be used as the mouse.             *\n;*                                                                         *\n;*    This will inform the system of the shape desired as the mouse        *\n;*    cursor.                                                              *\n;*                                                                         *\n;* INPUT:    xhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           yhotspot    -- Offset of click point into shape.              *\n;*                                                                         *\n;*           cursor      -- Shape to use as the new mouse shape.           *\n;*                                                                         *\n;* OUTPUT:   Returns with a pointer to the original mouse shape.           *\n;*                                                                         *\n;* PROTO:\tVOID  *Set_Mouse_Cursor(\tint  xhotspot, \t\t   *\n;*\t\t\t\t\t\tint  yhotspot, \t\t   *\n;*\t\t\t\t\t\tvoid *cursor);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   02/13/1992 JLB : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tSet_Mouse_Cursor:NEAR\n\tPROC\tSet_Mouse_Cursor C NEAR \n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\txhotspot:DWORD\t\t\t\t; the x hot spot of the mouse\n\tARG\tyhotspot:DWORD\t\t\t\t; the y hot spot of the mouse\n\tARG\tcursor:DWORD\t\t\t\t; ptr to the new mouse cursor\n\n\tLOCAL\tdatasize:DWORD\n\tLOCAL\tstype:WORD\n\tLOCAL\tswidth:DWORD\t\t; Shape width.\n\tLOCAL\tsheight:DWORD\t\t; Shape height.\n\tLOCAL\tssize:DWORD\t\t; Size of raw shape.\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\n\t;-------------------------------------------------------------------\n\t; Make sure the mouse is Enabled and Installed before continuing\n\t;-------------------------------------------------------------------\n\tmov\teax,[cursor]\n\tcmp\teax,0\t\t\t; if the mouse cursor is in zero page\n\tje\t??exit\t\t\t; it is completely invalid\n\n\tcmp\teax,[PrevMousePtr]\n\tje \t??exit\n\n\tcmp\t[(KeyboardType esi).MDisabled],FALSE\t; make sure the mouse is not disabled\n\tjne\t??exit\t\t\t; if it is not then give it a try\n\n\t;-------------------------------------------------------------------\n\t; We need to wait if a mouse interrupt is in progress.  Once the\n\t; interrupt is finished flag that it is occuring so that it will\n\t; not attempt to draw the mouse while we are changing the cursor.\n\t;-------------------------------------------------------------------\n??try:\n\tinc\t[(KeyboardType esi).MouseUpdate] ; flag that mouse can not be drawn\n\n\t;-------------------------------------------------------------------\n\t; If the mouse is currently on the screen hide it.\n\t;-------------------------------------------------------------------\n\tcall\tLow_Hide_Mouse\n\n\t;-------------------------------------------------------------------\n\t; Calculate the size of the buffer needed.\n\t;-------------------------------------------------------------------\n\tpush\t[cursor]\n\tcall\tGet_Shape_Uncomp_Size\n\tpop\tedx\n\tmov\t[datasize],eax\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Width\n\tpop\tedx\n\tmov\t[swidth],eax\n\tcmp\teax,[BufferWidth]\n\tjg\t??end\n\n\tpush\t[cursor]\n\tcall\tGet_Shape_Original_Height\n\tpop\tedx\n\tmov\t[sheight],eax\n\tcmp\teax,[BufferHeight]\n\tjg\t??end\n\n\n\tmov\tebx,[sheight]\n\tmov\teax,[swidth]\n\timul\tebx,eax\n\n??copy_mouse:\n\tmov\tesi,[cursor]\t\t\t; set esi to point to mouse shape\n\tmov\tax,[esi]\t\t\t; get the shape type byte\n\tmov\t[stype],ax\t\t\t; save off the shape type\n\ttest\tax,MAKESHAPE_NOCOMP\t\t; is it marked as no compression?\n\tje\t??comp_shape\t\t\t; if not go to the comped shape code\n\tmov\tedi,[MouseCursor]\t\t; set edi to point to mouse buffer\n??copy_type:\n\n\ttest\t[stype],MAKESHAPE_COMPACT\t; if the shape a 16 color shape?\n\tjne\t??16_color_copy\t\t\t; if it is then go handle it\n\n??normal_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed NORMAL shapes just get run-length uncompressed\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t\t; find size of shape in pixels\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes \n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??norm_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??norm_trans\t\t\t; if its a zero its transparent\n\tmov\t[edi],al\t\t\t; write out the pixel to dest\n\tinc\tedi\t\t\t\t; move to next dest position\n\tdec\tedx\t\t\t\t; we have now written another pix\n\tjnz\t??norm_unrle\t\t\t; if more to write then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are all done\n\n??norm_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\n\tjnz\t??norm_unrle\t\t\t; if more to do then do it\n\tjmp\t??done_copy\t\t\t; otherwise we are done\n\n??16_color_copy:\n\t;-------------------------------------------------------------------\n\t;* Uncompressed 16 color shapes just get remaped and UN-RLE'd\n\t;-------------------------------------------------------------------\n\tadd\tesi,10\t\t\t\t; adjust past header of shape\n\tmov\tebx,esi\t\t\t\t; save of position of remap\n\tadd\tesi,16\t\t\t\t; move past remap table\n\tmov\teax,[swidth]\t\t\t; load up the width\n\tmul\t[sheight]\t\t\t; load up the height\n\tmov\tedx,eax\t\t\t\t; save this in number of bytes \n\txor\teax,eax\t\t\t\t; clear high of lookup variable\n\txor\tecx,ecx\t\t\t\t; clear high of loop variable\n??16_color_unrle:\n\tmov\tal,[esi]\t\t\t; get a byte out of the file\n\tinc\tesi\t\t\t\t; increment to the next pos\n\tor\tal,al\t\t\t\t; set the flags on register state\n\tjz\t??16_color_trans\t\t; if its a zero its transparent\n\tmov\tal,[ebx+eax]\t\t\t; remap the pixel from 16 color table\n\tmov\t[edi],al\t\t\t; store it out to the dest address\n\tinc\tedi\t\t\t\t; move to next dest address\n\tdec\tedx\t\t\t\t; we have now written a pixel\n\tjnz\t??16_color_unrle\n\tjmp\t??done_copy\n??16_color_trans:\n\tmov\tcl,[esi]\t\t\t; get how many zeros to write\n\tsub\tedx,ecx\t\t\t\t; subtract off count ahead of time\n\tinc\tesi\t\t\t\t; increment the source position\n\txor\tal,al\t\t\t\t; clear out al cuz we're writing zeros\n\trep\tstosb\t\t\t\t; write all of them out\n\tor\tedx,edx\t\t\t\t; or edx to test for zero\n\tjnz\t??16_color_unrle\t\t\n\tjmp\t??done_copy\n\n\t;-------------------------------------------------------------------\n\t; Deal with the compressed shape by copying it into the shape\n\t;   staging buffer.\n\t;-------------------------------------------------------------------\n??comp_shape:\n\tmov\tedi,[_ShapeBuffer]\t; get a pointer to ShapeBuffer\n\tmov\tax,[esi]\t\t; load in the shape type\n\tadd\tesi,2\t\t\t; increment the shape pointer\n\tor\tax,MAKESHAPE_NOCOMP\t; make the shape as uncompressed\n\tmov\t[stype],ax\t\t; save off the shape type\n\tmov\t[edi],ax\t\t; write out uncompressed shape\n\tadd\tedi,2\n\n\t;-------------------------------------------------------------------\n\t; Process the shape header information and copy it over to the new\n\t;   location.\n\t;-------------------------------------------------------------------\n\tmov\tecx,4 \t\t\t; transfer height, width, org and\n\ttest\teax,MAKESHAPE_COMPACT\t; is it a 16 color shape?\n\tje\t??copy_head\t\t; no - don't worry about it\n\tadd\tecx,8\t\t\t; otherwise adjust ecx for header\n??copy_head:\n\trep\tmovsw\t\t\t; copy the necessary bytes\n\t\n\tmov \teax,[datasize]\t\t; get uncompressed length\n\tpush\teax\t\t\t; push as third param\n\tpush\tedi\t\t\t; push the destination offset\n\tpush\tesi\t\t\t; push the source offset\n\tcall\tLCW_Uncompress\t\t; do the uncompress\n\tpop\teax\n\tpop\teax\n\tpop\teax\n\tmov\tesi,[_ShapeBuffer]\n\tmov\tedi,[MouseCursor]\t\t; set edi to point to mouse buffer\n\tjmp\t??copy_type\n\n??done_copy:\n\tmov\tesi,[RealModePtr]\t; get offset of real mode data start\n\n\tmov\teax,[xhotspot]\t\t; get the mouse cursors x hotspot\n\tmov\t[(KeyboardType esi).MouseXHot],eax\n\tmov\teax,[yhotspot]\t\t; get the mouse cursors y hotspot\n\tmov\t[(KeyboardType esi).MouseYHot],eax\n\n\tmov\tebx,[sheight]\t\t; get shape height\n\tmov\t[(KeyboardType esi).MouseHeight],ebx\n\tmov\tebx,[swidth]\n\tmov\t[(KeyboardType esi).MouseWidth],ebx\n\n??error:\n\tcall\tLow_Show_Mouse\n\n\t;-------------------------------------------------------------------\n\t; Final cleanup and exit.\n\t;-------------------------------------------------------------------\n??end:\n\tdec\t[(KeyboardType esi).MouseUpdate]\t\t; we are done modifying the cursor\n??exit:\n\tpush\t[cursor]\n\tpush\t[PrevMousePtr]\n\tpop\teax\n\tpop\t[PrevMousePtr]\n\tret\t\t\t\t; and return back to the world\n\n\tENDP\tSet_Mouse_Cursor\n\n\n;***************************************************************************\n;* LOW_HIDE_MOUSE -- Low-level routine which hides the mouse\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Low_Hide_Mouse:NEAR\n\tPROC\tLow_Hide_Mouse C NEAR \n\tUSES\teax,ebx,esi\n\n\tmov\tebx,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\n\t;*=========================================================================*\n\t;* Is the mouse disabled or hidden?\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType ebx).MDisabled],0 \t; is the mouse disabled?\n\tjne\tshort ??end\n\n   \tcmp\t[(KeyboardType ebx).MState],0 \t; is the mouse hidden?\n\tjne\tshort ??endnodraw\t\t\t; no need to hide again\n\n\t;*=========================================================================*\n\t;* Take care of restoring the mouse cursor\n\t;*=========================================================================*\n\tmov\teax,RESTORE_VISIBLE_PAGE\n\tpush\teax\n\tcall\t[ Mouse_Shadow_Buffer]\n\tpop\teax\n\t;*=========================================================================*\n\t;* The mouse is now hidden -- again.\n\t;*=========================================================================*\n??endnodraw:\n\tadd\t[(KeyboardType ebx).MState],1\n\tadc\t[(KeyboardType ebx).MState],0\n\n??end:\n\tret\n\tENDP\tLow_Hide_Mouse\n\n;***************************************************************************\n;* LOW_SHOW_MOUSE -- Low level routine which shows the mouse\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   09/19/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC Low_Show_Mouse:NEAR\n\tPROC\tLow_Show_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tLOCAL\tmousex:DWORD\n\tLOCAL\tmousey:DWORD\n\n\tmov\tesi,[RealModePtr]\t\t\t; get offset of real mode data start\n\n\t;*=========================================================================*\n\t;* Don't show the mouse if it is not hidden or it is disabled\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType esi).MDisabled],0\t; is the mouse disabled\n\tjne\t??exit\t\t\t\t\t; if so then exit\n\n\tcmp\t[(KeyboardType esi).MState],0\t; is the mouse already visible\n       \tje\t??exit\t\t\t\t\t; if so then exit\n\n\t;*=========================================================================*\n\t;* Don't show the mouse if it was hidden multiple times\n\t;*=========================================================================*\n\tdec\t[(KeyboardType esi).MState]\t\t; show the mouse one level\n\tcmp\t[(KeyboardType esi).MState],0\t; can the mouse be shown\n       \tjne\tshort ??exit\n\n\t;*=========================================================================*\n\t;* Determine the theoretcial drawing position of the mouse\n\t;*=========================================================================*\n\tmov\tecx,[(KeyboardType esi).MouseWidth]\t\t; Theoretical buffer width (pixel).\n\tmov\tedx,[(KeyboardType esi).MouseHeight]\t; Theoretical buffer height (pixel).\n\tmov\teax,[(KeyboardType esi).MouseX]\n\tmov\t[mousex],eax\t\t; Draw X pixel.\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\tmov\tebx,[(KeyboardType esi).MouseY]\n\tmov\t[mousey],ebx\t\t; Draw Y pixel.\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\t;*=========================================================================*\n\t;* Determine the theoretical coordinates and dimensions of the\n\t;*\tarea the mouse shape will be rendered upon.\n\t;*=========================================================================*\n\tmov\t[(KeyboardType esi).MouseBuffX],eax\n\tmov\t[(KeyboardType esi).MouseBuffY],ebx\n\tmov\t[(KeyboardType esi).MouseBuffW],ecx\n\tmov\t[(KeyboardType esi).MouseBuffH],edx\n\n;------\tMove the area that will be drawn upon, to the graphic buffer.\n\tmov\teax,STORE_VISIBLE_PAGE\n\tpush\teax\n\tcall\t[ Mouse_Shadow_Buffer ]\n\tpop\teax\n\n;------\tDraw the mouse shape to the seenpage.\n\tpush\t[mousey]\n\tpush\t[mousex]\n\tcall\t[ Draw_Mouse ]\n\tpop\teax\n\tpop\teax\n??exit:\n\tret\n\tENDP\tLow_Show_Mouse\n\n;***************************************************************************\n;* HIDE_MOUSE -- Hides mouse cursor on screen if it was show               *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Hide_Mouse(void);\t\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tHide_Mouse:NEAR\n\tPROC\tHide_Mouse C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Mark us as updating the mouse and then run and do the update\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\t; were drawing the mouse\n\tcall\tLow_Hide_Mouse\t\t\t\t; make the function call\n\tdec\t[(KeyboardType esi).MouseUpdate]\t; were done drawing mouse\n\tret\n\t\n\tENDP\tHide_Mouse\n\n;----------------------------------------------------------------------------\n\n\n;***************************************************************************\n;* SHOW_MOUSE -- Display mouse cursor on screen if it was hidden           *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Show_Mouse(void)                                      *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tShow_Mouse:NEAR\n\tPROC\tShow_Mouse C NEAR \n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Mark us as updating the mouse and then run and do the update\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\t; were drawing the mouse\n\tcall\tLow_Show_Mouse\t\t\t\t; make the function call\n\tdec\t[(KeyboardType esi).MouseUpdate]\t; were done drawing mouse\n\tret\n\tENDP\tShow_Mouse\n\n;***************************************************************************\n;* CONDITIONAL_HIDE_MOUSE -- Hides mouse if its with given region          *\n;*                                                                         *\n;* INPUT:\tint sx_pixel - the left-most pixel position of the region  *\n;*\t\tint sy_pixel - the upper-most pixel position of the region *\n;*\t\tint dx_pixel - the right most pixel position of the region *\n;*\t\tint dy_pixel - the lower most pixel position of the region *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Conditional_Hide_Mouse(\tint sx_pixel, \t\t   *\n;*\t\t\t\t\t\tint sy_pixel,\t\t   *\n;*\t\t\t\t\t\tint dx_pixel,\t\t   *\n;*\t\t\t\t\t\tint dy_pixel);\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tConditional_Hide_Mouse:NEAR\n\tPROC\tConditional_Hide_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tARG\tsx_pixel:DWORD\t\t\t\t; left x pixel pos\n\tARG     sy_pixel:DWORD\t\t\t\t; upper y pixel pos\n\tARG\tdx_pixel:DWORD\t\t\t\t; right x pixel pos\n\tARG\tdy_pixel:DWORD\t\t\t\t; lower y pixel pos\n\n\tmov\tesi,[RealModePtr]\t\t\t; get the real mode offset\n\n\t;*=========================================================================*\n\t;* Widen region leftward by amount mouse shape spills to the right of\n\t;* its hot point.  Limited to the left edge of the screen.\n\t;*=========================================================================*\n\tmov\teax,[(KeyboardType esi).MouseWidth]\t\n\tsub\teax,[(KeyboardType esi).MouseXHot]\t\n\tneg\teax\t\t\t\t\t\n\tadd\teax,[sx_pixel]\n\tjns\tshort ??noleftlimit\n\txor\teax,eax\n??noleftlimit:\n\t;*=========================================================================*\n\t;* Widen region upward by amount mouse shape spills below the\n\t;* mouse's hot point.  Limited by the top edge of the screen.\n\t;*=========================================================================*\n\tmov\tebx,[(KeyboardType esi).MouseHeight]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\tneg\tebx\n\tadd\tebx,[sy_pixel]\n\tjns\tshort ??notoplimit\n\txor\tebx,ebx\n??notoplimit:\n\t;*=========================================================================*\n\t;* Widen region rightward by amount mouse shape spills to the\n\t;* left of its hot point.  Limited by the right edge of the\n\t;* screen.\n\t;*=========================================================================*\n\tmov\tecx,[dx_pixel]\n\tadd\tecx,[(KeyboardType esi).MouseXHot]\n\tcmp\tecx,[(KeyboardType esi).MouseRight]\n\tjb\tshort ??norightlimit\n\tmov\tecx,[(KeyboardType esi).MouseRight]\n\tdec\tecx\n??norightlimit:\n\t;*=========================================================================*\n\t;* Widen region downward by amout the mouse shape extends above\n\t;* its hot point.  Limited to the bottom of the screen.\n\t;*=========================================================================*\n\tmov\tedx,[dy_pixel]\n\tadd\tedx,[(KeyboardType esi).MouseYHot]\n\tcmp\tedx,[(KeyboardType esi).MouseBottom]\n\tjb\tshort ??nobottomlimit\n\tmov\tedx,[(KeyboardType esi).MouseBottom]\n\tdec\tedx\n\n??nobottomlimit:\n\tinc\t[(KeyboardType esi).MouseUpdate]\t\t; don't let interrupt scrag variables\n\n\t;*=========================================================================*\n\t;* The mouse could be in one of four conditions.\n\t;* 1) The mouse is visible and no conditional hide has been specified.\n\t;* \t(perform normal region checking with possible hide)\n\t;* 2) The mouse is hidden and no conditional hide as been specified.\n\t;* \t(record region and do nothing)\n\t;* 3) The mouse is visible and a conditional region has been specified\n\t;* \t(expand region and perform check with possible hide).\n\t;* 4) The mouse is already hidden by a previous conditional.\n\t;* \t(expand region and do nothing)\n\t;*\n\t;* First: Set or expand the region according to the specified parameters\n\t;*=========================================================================*\n\tcmp\t[(KeyboardType esi).MCState],0\n\tjne\tshort ??expand\n\tmov\t[(KeyboardType esi).MouseCXLeft],eax\n\tmov\t[(KeyboardType esi).MouseCYUpper],ebx\n\tmov\t[(KeyboardType esi).MouseCXRight],ecx\n\tmov\t[(KeyboardType esi).MouseCYLower],edx\n\tjmp\t??noylower\n??expand:\n\n\t;*=========================================================================*\n\t;* Expand the clipping rectangle.\n\t;*=========================================================================*\n\tcmp\teax,[(KeyboardType esi).MouseCXLeft]\n\tjb\tshort ??noxleft\n\tmov\t[(KeyboardType esi).MouseCXLeft],eax\n??noxleft:\n\tcmp\tebx,[(KeyboardType esi).MouseCYUpper]\n\tjb\tshort ??noyupper\n\tmov\t[(KeyboardType esi).MouseCYUpper],ebx\n??noyupper:\n\tcmp\tecx,[(KeyboardType esi).MouseCXRight]\n\tja\tshort ??noxright\n\tmov\t[(KeyboardType esi).MouseCXRight],ecx\n??noxright:\n\tcmp\tedx,[(KeyboardType esi).MouseCYLower]\n\tja\tshort ??noylower\n\tmov\t[(KeyboardType esi).MouseCYLower],edx\n??noylower:\n\t;*=========================================================================*\n\t;* If the mouse isn't already hidden, then check its location against\n\t;* the hiding region and hide if necessary.\n\t;*=========================================================================*\n\ttest\t[(KeyboardType esi).MCState],CONDHIDDEN\n\tjne\tshort ??nohide\n\n\tmov\teax,[(KeyboardType esi).MouseX]\n\tmov\tebx,[(KeyboardType esi).MouseY]\n\tcmp\teax,[(KeyboardType esi).MouseCXLeft]\n\tjb\tshort ??nohide\n\tcmp\teax,[(KeyboardType esi).MouseCXRight]\n\tja\tshort ??nohide\n\tcmp\tebx,[(KeyboardType esi).MouseCYUpper]\n\tjb\tshort ??nohide\n\tcmp\tebx,[(KeyboardType esi).MouseCYLower]\n\tja\tshort ??nohide\n\n\t;*=========================================================================*\n\t;* The mouse falls within the region for hiding, so hide it.\n\t;*=========================================================================*\n\n\tcall\tLow_Hide_Mouse\t\t\t\t; make the function call\n\tor\t[(KeyboardType esi).MCState],CONDHIDDEN\n??nohide:\n\n\t;*=========================================================================*\n\t;* Record the fact that a Conditional_Hide_Mouse was\n\t;* called and then exit.\n\t;*=========================================================================*\n\tor\t[(KeyboardType esi).MCState],CONDHIDE\n\tadd\t[BYTE PTR (KeyboardType esi).MCState],1\n\tadc\t[BYTE PTR (KeyboardType esi).MCState],0\n\tdec\t[(KeyboardType esi).MouseUpdate]\n\tret\n\n\tENDP\tConditional_Hide_Mouse\n\n;***************************************************************************\n;* CONDITIONAL_SHOW_MOUSE -- shows mouse if it was conditionally hidden    *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:       void Conditional_Show_Mouse(void);                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   11/03/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tConditional_Show_Mouse:NEAR\n\tPROC\tConditional_Show_Mouse C NEAR\n\tUSES\teax,esi\n\n\tmov\tesi,[RealModePtr]    ; get the real mode offset\n\n\t;*=========================================================================*\n\t; Notify the interrupt that we are updating the mouse\n\t;*=========================================================================*\n\tinc\t[(KeyboardType esi).MouseUpdate]\n\n\tmov\tax,[(KeyboardType esi).MCState]\n\tcmp\tal,0\n\tje\tshort ??exit\t\t\t; if no more nesting clear cond\n\n\t;*=========================================================================*\n\t;* Decrement the conditional hide counter.\n\t;*=========================================================================*\n\tdec\tal\n\n\t;*=========================================================================*\n\t;* If there are more conditional levels to undo, then just abort the show.\n\t;*=========================================================================*\n\tjne\tshort ??exit\n\n\t;*=========================================================================*\n\t;* Yup, the mouse should be show, but only if it was previously hidden.\n\t;*=========================================================================*\n\ttest\tax,CONDHIDDEN\t\t\t; was it hidden by interrupt??\n\tje\tshort ??exit1\t\t\t; or initial check for level 0\n\n\tcall\tLow_Show_Mouse\n\n??exit1:\n\tmov\tax,0\n\n??exit:\n\tmov\t[(KeyboardType esi).MCState],ax\n\tdec\t[(KeyboardType esi).MouseUpdate]\n\tret\n\tENDP\tConditional_Show_Mouse\n\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VGA_Mouse_Shadow_Buffer:NEAR\n\tPROC\tVGA_Mouse_Shadow_Buffer C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tstore:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\n\tmov\tesi,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\tcld\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[(KeyboardType esi).MouseBuffX]\n\tmov\tebx,[(KeyboardType esi).MouseBuffY]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseBuffW]\n\tadd\tebx,[(KeyboardType esi).MouseBuffH]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseBuffer ]\n\tmov\t[ buffy0 ] , eax\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseBuffW]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseBuffW]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\tpush\tebp\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\tebp , ecx\n??restore_loop:\n\tmov\tecx,eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi,ebx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n\tret\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\txchg\tesi,edi\t\t\t\t\t; xchg the source and the dest\n\tmov\tebp , ecx\n??store_loop:\n\tmov\tecx,eax\t\t\t\t\t; get number to really write\n\trep\tmovsb\t\t\t\t\t; store them into the buffer\n\tadd\tesi,edx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,ebx\t\t\t\t\t; adjust dest to next line\n\tdec\tebp\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_loop\t\t\t\t; if more to do, do it\n\tpop\tebp\n??out:\n\tret\n\tENDP\tVGA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n;* DRAW_MOUSE -- Handles drawing the mouse cursor\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tVGA_Draw_Mouse:NEAR\n\tPROC\tVGA_Draw_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tmousex:DWORD\n\tARG\tmousey:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\n\n\tmov\tesi,[RealModePtr]    \t; get 32 bit offset of dos data\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[mousex]\n\tmov\tebx,[mousey]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseWidth]\n\tadd\tebx,[(KeyboardType esi).MouseHeight]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , eax\n\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseWidth]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseWidth]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch ,[esi]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[edi],ch\n??inc_edi:\n\tinc\tedi\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tesi,ebx\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t\t\t\t; adjust dest to next line\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n??out:\n\tret\n\n\tENDP\tVGA_Draw_Mouse\n\n\n;***************************************************************************\n;***************************************************************************\n;***************************************************************************\n\n;***************************************************************************\n;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *\n;*                                                                         *\n;* INPUT:\tint store - indicates whether we are storing the buffer or *\n;*\t\t\t    not.\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tC VESA_Mouse_Shadow_Buffer:NEAR\n\tPROC\tVESA_Mouse_Shadow_Buffer C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tstore:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\tlocal\tvesa_linear : dword\n\n\tmov\teax , [ cpu_video_page ]\n\tmov\t[ vesa_linear ] ,  eax\n\n\tmov\tesi,[RealModePtr]\t\t\t; get 32 bit offset of dos data\n\t;*=========================================================================*\n\t; Direction flag must be forward in this routine.\n\t;*=========================================================================*\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[(KeyboardType esi).MouseBuffX]\n\tmov\tebx,[(KeyboardType esi).MouseBuffY]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseBuffW]\n\tadd\tebx,[(KeyboardType esi).MouseBuffH]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseBuffer ]\n\tmov\t[ buffy0 ] , eax\n\n\t;*===================================================================\n\t;* Bounds check source X.\n\t;*===================================================================\n\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseBuffW]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\tcall\tVesa_Asm_Set_Win\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseBuffW]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\n\tcmp\t[store],RESTORE_VISIBLE_PAGE\t\t; are we restoring page?\n\tjne\t??store_entry\t\t\t\t; if not the go to store\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\n\tmov\t[ tempreg ] , ebx\n??restore__top_loop:\n\tmov\tah,al\n??restore__inner_loop:\n\tmov\tch ,[esi]\n\tmov\t[edi],ch\n\tinc\tesi\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??restore__in_range\n\tadd\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??restore__in_range:\n\tdec\tah\n\tjnz\t??restore__inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??restore__in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??restore__in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??restore__top_loop\t\t\t\t; if more to do, do it\n\tjmp\t??out\t\t\t\t\t; get the heck outta the routine\n\n\t;*===================================================================\n\t;* Handle soting the visible page into the Mouse Shadow Buffer\n\t;*===================================================================\n??store_entry:\n\tmov\t[ tempreg ] , ebx\n??store_top_loop:\n\tmov\tah,al\n??store_inner_loop:\n\tmov\tch ,[edi]\n\tmov\t[esi],ch\n\tinc\tesi\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??store_in_range\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??store_in_range:\n\tdec\tah\n\tjnz\t??store_inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??store_in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??store_in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??store_top_loop\t\t\t\t; if more to do, do it\n\n??out:\n\tmov\tedi , [ vesa_linear ]\n\tadd\tedi , 0a0000h\n\tcall\tVesa_Asm_Set_Win\n\n\tret\n\tENDP\tVESA_Mouse_Shadow_Buffer\n\n;***************************************************************************\n;* DRAW_MOUSE -- Handles drawing the mouse cursor\t\t\t   *\n;*                                                                         *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:\tnone                                                       *\n;*                                                                         *\n;* PROTO:       Asm callable only!                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/27/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tGLOBAL\tVESA_Draw_Mouse:NEAR\n\tPROC\tVESA_Draw_Mouse C NEAR \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\tARG\tmousex:DWORD\n\tARG\tmousey:DWORD\n\n\tlocal\tx0 : dword\n\tlocal\ty0 : dword\n\tlocal\tx1 : dword\n\tlocal\ty1 : dword\n\tlocal\tbuffx0 : dword\n\tlocal\tbuffy0 : dword\n\tlocal\ttempreg : dword\n\tlocal\tvesa_linear : dword\n\n\tmov\teax , [ cpu_video_page ]\n\tmov\t[ vesa_linear ] ,  eax\n\n\tmov\tesi,[RealModePtr]    \t; get 32 bit offset of dos data\n\n\t;*===================================================================\n\t;* Copy of X, Y, Width and Height into local registers\n\t;*===================================================================\n\tmov\teax,[mousex]\n\tmov\tebx,[mousey]\n\tsub\teax,[(KeyboardType esi).MouseXHot]\n\tsub\tebx,[(KeyboardType esi).MouseYHot]\n\n\tmov\t[ x0 ] , eax  \n\tmov\t[ y0 ] , ebx  \n\tadd\teax,[(KeyboardType esi).MouseWidth]\n\tadd\tebx,[(KeyboardType esi).MouseHeight]\n\tmov\t[ x1 ] , eax  \n\tmov\t[ y1 ] , ebx  \n\n\tmov\t[ buffx0 ] , 0\n\tmov\teax , [ MouseCursor ]\n\tmov\t[ buffy0 ] , eax\n\n\n\t;*===================================================================\n\t;* Bounds check source X. Y.\n\t;*===================================================================\n\txor \teax , eax\n\txor \tedx , edx\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ x0 ]  \n\tmov\tebx , [ x1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseRight]\n\tsub\tebx , [(KeyboardType esi).MouseRight]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tecx , [ y0 ]  \n\tmov\tebx , [ y1 ]  \n\tsub\tecx , [(KeyboardType esi).MouseBottom]\n\tsub\tebx , [(KeyboardType esi).MouseBottom]\n\tdec\tecx\n\tdec\tebx\n\tshld\teax , ecx , 1\n\tshld\tedx , ebx , 1\n\n\txor\tal , 5\n\txor\tdl , 5\n\tmov\tah , al\n\ttest\tdl , al\n\tjnz\t??out\n\tor\tal , dl\n\tjz\t??not_clip\n\n\ttest\tah , 1000b\n\tjz\t??scr_left_ok\n\tmov\tebx , [ x0 ]\n\tneg\tebx\n\tmov\t[ buffx0 ] , ebx\n\tmov\t[ x0 ] , 0\n\n??scr_left_ok:\n\ttest\tah , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\tebx , [ y0 ]\n\tneg\tebx\n\timul\tebx , [(KeyboardType esi).MouseWidth]\n\tadd\t[ buffy0 ] , ebx\n\tmov\t[ y0 ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [(KeyboardType esi).MouseRight]  ; get width into register\n\tmov\t[ x1 ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??not_clip\n\tmov\teax , [(KeyboardType esi).MouseBottom]  ; get width into register\n\tmov\t[ y1 ] , eax\n\n??not_clip:\n\n\t;*===================================================================\n\t;* Get the offset into the screen.\n\t;*===================================================================\n\tmov\teax , [ y0 ]\n\tmov\tedx , [(KeyboardType esi).MouseRight]\n\timul\teax , edx\n\tadd\teax , [ x0 ]\n\tlea\tedi , [ 0a0000h + eax ]\n\tcall\tVesa_Asm_Set_Win\n\n\t;*===================================================================\n\t;* Adjust the source for the top clip.\n\t;*===================================================================\n\tmov\tebx , [(KeyboardType esi).MouseWidth]\t; turn this into an offset\n\tmov\tesi , [ buffy0 ]\t\t\t; edx points to source\n\tadd\tesi , [ buffx0 ]\t\t\t\t\t; plus clipped lines\n\n\t;*===================================================================\n\t;* Calculate the bytes per row add value\n\t;*===================================================================\n\n\tmov\teax , [ x1 ]\n\tmov\tecx , [ y1 ]\n\tsub\teax , [ x0 ]\n\tjle\t??out\n\tsub\tecx , [ y0 ]\n\tjle\t??out\n\n\tsub\tedx , eax\n\tsub\tebx , eax\t\n\n\t;*===================================================================\n\t;* Handle restoring the buffer to the visible page\n\t;*===================================================================\n\tmov\t[ tempreg ] , ebx\n??top_loop:\n\tmov\tah,al\n??inner_loop:\n\tmov\tch ,[esi]\n\tinc\tesi\n\tor\tch,ch\n\tjz\t??inc_edi\n\tmov\t[edi],ch\n??inc_edi:\n\tinc\tedi\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??in_range\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??in_range:\n\tdec\tah\n\tjnz\t??inner_loop\n\tadd\tesi,[ tempreg ]\t\t\t\t; move past right clipped pixels\n\tadd\tedi,edx\t   \t\t\t\t; adjust dest to next line\n\n\tmov\tebx , edi\n\tadd\tebx , [ cpu_video_page ] \t\n\tcmp\tebx , [ cpu_page_limit ]\n\tjl\t??in_range1\n\tadd  \tedi ,[ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\n ??in_range1:\n\tdec\tcl\t\t\t\t\t; decrement number of rows to do\n\tjnz\t??top_loop\t\t\t\t; if more to do, do it\n\n??out:\n\tmov\tedi , [ vesa_linear ]\n\tadd\tedi , 0a0000h\n\tcall\tVesa_Asm_Set_Win\n\n\tret\n\n\tENDP\tVESA_Draw_Mouse\n\n\n;----------------------------------------------------------------------------\nEND\n"
  },
  {
    "path": "WWFLAT32/SRCDEBUG/NEWDEL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Memory system.                           *\n *                                                                         *\n *                    File Name : NEWDEL.CPP                               *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : June 21, 1994                            *\n *                                                                         *\n *                  Last Update : July 17, 1995   [PWG]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   operator NEW -- Overides the global new function.                     *\n *   operator delete -- Overides the global delete function.               *\n *   operator NEW[] -- Overides the array version of new.                  *\n *   operator delete[] -- Overides the array version of delete[]           *\n *    --                                                                   *\n *   OPERATOR NEW -- New opperator which takes a MEM_FLAG                  *\n *   OPERATOR NEW[] -- Global NEW[] which takes MEM_FLAG                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwmem.h\"\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * OPERATOR NEW -- Overides the global new function.                       *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid * operator new(size_t size) \n{\n\treturn (Alloc((unsigned long) size, MEM_NEW));\n}\n\n\n/***************************************************************************\n * OPERATOR NEW[] -- Overides the array version of new.                    *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid * operator new[](size_t size) \n{\n\treturn (Alloc((unsigned long) size, MEM_NEW));\n}\n \n/***************************************************************************\n * OPERATOR NEW -- New opperator which takes a MEM_FLAG                    *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid * operator new(size_t size, MemoryFlagType flag) \n{\n\treturn(Alloc(size, (MemoryFlagType)(flag|MEM_NEW)));\n}\n\n/***************************************************************************\n * OPERATOR NEW[] -- Global NEW[] which takes MEM_FLAG                     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/17/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid * operator new[] (size_t size, MemoryFlagType flag)\n{\n\treturn(Alloc(size, (MemoryFlagType)(flag|MEM_NEW)));\n}\n\n/***************************************************************************\n * OPERATOR DELETE -- Overides the global delete function.                 *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid operator delete(void *ptr) \n{\n\tFree(ptr);\n}\n\n/***************************************************************************\n * OPERATOR DELETE[] -- Overides the array version of delete[]           \t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/20/1994 SKB : Created.                                             *\n *=========================================================================*/\nvoid operator delete[](void *ptr) \n{\n\tFree(ptr);\n}\n\n\n\n"
  },
  {
    "path": "WWFLAT32/SRCDEBUG/PAGFAULT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library                                  *\n;*                                                                         *\n;*                    File Name : PAGFAULT.ASM                             *\n;*                                                                         *\n;*                   Programmer : Julio R Jerez \t                   *\n;*                                                                         *\n;*                   \t   Date : April 25,1995                            *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;\n; Here are prototypes for the routines defined within this module:\n; VOID Install_Page_Fault_Handle (void) ;\n;\n; ----------------------------------------------------------------\n\nIDEAL\t\t\t\t; the product runs in ideal mode\nP386\t\t\t\t; use 386 real mode instructions\nMODEL USE32 FLAT\nLOCALS ??\t\t\t; ?? is the symbol for a local\nWARN\t\t\t\t; generate all warnings we can\nJUMPS\t\t\t\t; optimize jumps if possible\n\n;---------------------------------------------------------------------------\n; Make some general equates for easy compatability\n;---------------------------------------------------------------------------\nDPMI_INTR\t EQU\t31h  \nPAGE_FAULT\t equ\t0eh\nRESET_VIDEO_MODE  equ\t-1\n\nGLOBAL\t Install_Page_Fault_Handle : NEAR\nGLOBAL\t Set_Video_Mode\t\t   : NEAR\t\t\nGLOBAL\t Remove_Mouse\t\t   : NEAR\nGLOBAL\t Remove_Keyboard_Interrupt : NEAR\nGLOBAL\t Remove_Timer_Interrupt\t   : NEAR\t\n\nDATASEG\n\tOld_Page_Fault_handle DF ?\n\tPage_Fault_SS \tDD\t?\n\tPage_Fault_ESP\tDD\t?\n\nCODESEG\n;***************************************************************************\n;* INSTALL_PAGE_FAULT_HANDLE -- Installs new page fault handle             *\n;*\tThis function will install a new page fault handle \t\t   *\n;*\tso in the event that we have a program crash thi handle will\t   *\n;*\tremove all interrupts and then will chain to the default Page\t   *\n;*\tFault handle\t\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* INPUT:\tnone\t\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tVOID Install_Page_Fault_Handle( void);  \t\t   *\n;*                                                                         *\n;* HISTORY:  04/25/96 Created                                              *\n;*=========================================================================*\n\tPROC\tInstall_Page_Fault_Handle C NEAR \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tmov\teax,0202h \t; get address of exception handle\n\tmov\tbl,PAGE_FAULT\n\tint\tDPMI_INTR\n\tjc\t??exit\t\t; not action is taken \n\n\t; save addrees of default handle\n\tmov\t[dword ptr Old_Page_Fault_handle],edx\n\tmov\t[word ptr  Old_Page_Fault_handle+4],cx\n\n\t; redirect default handle to a new Page Fault Handle\n\tmov eax,0203h\t\t\n\tmov bl,PAGE_FAULT\n\tmov cx,cs\n\tlea edx,[Page_Fault_Handle]\n\tint DPMI_INTR \n\n  ??exit:\n\tret\n\tENDP\tInstall_Page_Fault_Handle\n\n\n;***************************************************************************\n;* PAGE_FAULT_HANDLE --  This           \t\t   \t\t   *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* HISTORY:  04/25/96 Created                                              *\n;*=========================================================================*\nPROC\tPage_Fault_Handle far \n\n\t; preserve used  registers\n\tpush\teax\n\tpush\tebx\n\t; save Page Fault satck frame\n\tmov\tax,ss\t\n\tmov\t[Page_Fault_SS],eax\n\tmov\t[Page_Fault_ESP],esp\n\n\t; retrieve application original stack frame\n\tmov eax , [ esp + ( 6 + 2 ) * 4 ] \n\tmov ebx , [ esp + ( 7 + 2 ) * 4 ]\n\tmov ss , bx\n\tmov esp , eax\n\n\t; set video mode to standard text mode\n\tpush\tRESET_VIDEO_MODE\n\tcall \tSet_Video_Mode\n\tpop\teax\n\tcall \tRemove_Mouse\n\tcall \tRemove_Keyboard_Interrupt\n\tcall\tRemove_Timer_Interrupt\n\n\t; restore Page Fault stack frame\n\tmov\teax,[Page_Fault_SS]\n\tmov \tss , ax\n\tmov\tesp, [Page_Fault_ESP]\n\n\t; restore used registers and chain to default Page Fault Handle\n\tpop\tebx\n\tpop\teax\n\tjmp\t[fword Old_Page_Fault_handle]\n\n\tENDP\tPage_Fault_Handle\n\n\n;***************************************************************************\n;* End of File.\t\t\t\t\t\t\t\t   *\n;***************************************************************************\nEND\n\n"
  },
  {
    "path": "WWFLAT32/SVGAPRIM/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 27 , 1995                            *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = svgaprim\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tvesa.obj\t&\n\tvclear.obj\t&\n\tvgetpix.obj\t&\n\tvputpix.obj\t&\n\tvtobuff.obj\t&\n\tvtopage.obj\t&\n\tvlbtove.obj\t&\n\tvvetolb.obj\t&\n\tvvblit.obj\t&\n\tvtxtprnt.obj \t&\n\tvscltove.obj\t&\n\tvvetoscl.obj\t&\n\tvscale.obj\t\n\n\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WWFLAT32/SVGAPRIM/SVGAPRIM.INC",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : SVGAPRIM.INC                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : December 8, 1994                         *\n;*                                                                         *\n;*                  Last Update : December 8, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n\n; Externs from VIDEO.CPP module of the VIDEO library\nGLOBAL BankTable\t\t\t:DWORD\nGLOBAL VesaFunc\t\t\t:DWORD\nGLOBAL XRes\t\t\t\t\t:DWORD\nGLOBAL YRes\t\t\t\t\t:DWORD\nGLOBAL CurrentMode\t\t:DWORD\nglobal cpu_video_page\t:dword\nglobal cpu_page_limit   :dword\n\n\n; Externs from VESA.ASM module of the SVGAPRIM library\nGLOBAL Vesa_Asm_Set_Win\t\t:NEAR\nGLOBAL Vesa_Asm_Next_Win\t\t:NEAR\n\n; Externs from VGETPIX.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Get_Pixel          \t:NEAR\n\n; Externs from VPUTTPIX.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Put_Pixel \t\t:NEAR\n\n\n; Externs from VCLEAR.ASM module of the MCGA/SVGAPRIM library\nGLOBAL Vesa_Clear\t\t\t:NEAR\n\n; Externs from VBITBLIT.ASM module of the MCGA/SVGAPRIM library\nGLOBAL Linear_Blit_To_Vesa\t\t:NEAR\nGLOBAL Vesa_Blit_To_Linear\t\t:NEAR\nGLOBAL Vesa_Blit_To_Vesa\t\t:NEAR\n\n; Externs from VTOBUFF.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_To_Buffer\t\t:NEAR\n\n; Externs from VTOPAGE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Buffer_To_Page\t\t:NEAR\n\n; Externs from VSCALE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Linear_Scale_To_Vesa \t\t:NEAR\nGLOBAL Vesa_Scale_To_Linear\t\t:NEAR\nGLOBAL Vesa_Scale_To_Vesa \t\t:NEAR\n\n\n; Externs from VSCALE.ASM module of the SVGA/MCGAPRIM library\nGLOBAL Vesa_Print\t \t\t:NEAR\n"
  },
  {
    "path": "WWFLAT32/SVGAPRIM/VCLEAR.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Clear the Full Mcga Screen\t\t   *\n;*                                                                         *\n;*                    File Name : CLEAR.ASM                                *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : August 23, 1994   [SKB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVPC::Clear -- Clears a virtual viewport instance                     *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS  ??\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\nCODESEG\n\nPROC\tVesa_Clear C near \n\tUSES\teax,ebx,ecx,edx,esi,edi\n\n\tARG    \tthis:DWORD\t\t\t\t; this is a member function\n\tARG    \tcolor:BYTE\t\t\t\t; what color should we clear to\n\n\tcld \t\t \t\t\t\t; always go forward\n\n\tmov\tebx,[this]\t\t\t\t; get a pointer to viewport\n\tmov\tesi,[(GraphicViewPort ebx).GVPXAdd]\t; esi = add for each line\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get the correct offset\n\tpush\tesi\n\tmov\tedx,[(GraphicViewPort ebx).GVPHeight]\t; ecx = height of viewport\n\tmov\tesi,[(GraphicViewPort ebx).GVPWidth]\t; edx = width of viewport\n\n\n\t;*===================================================================\n\t; Convert the color byte to a DWORD for fast storing\n\t;*===================================================================\n\tmov\tal,[color]\t\t\t\t; get color to clear to\n\tmov\tah,al\t\t\t\t\t; extend across WORD\n\tmov\tecx,eax\t\t\t\t\t; extend across DWORD in\n\tshl\teax,16\t\t\t\t\t; several steps\n\tmov\tax,cx\t\t\n\n\tCall\tVesa_Asm_Set_Win\t\t\t; set the window\n\n\t;*===================================================================\n\t; Find out if we should bother to align the row.\n\t;*===================================================================\n\n??row_by_row_aligned:\n\tcmp\tesi , OPTIMAL_BYTE_COPY\t\t\t; is it worth aligning them?\n\tjl\t??row_by_row\t\t\t\t;   if not then skip\n\t\n\t;*===================================================================\n\t; Now that we have the alignment offset copy each row\n\t;*===================================================================\n\n\n??aligned_loop:\n       lea\tebx , [ edi + esi ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??in_range\n\n\n       xor\tecx , ecx\n       mov\tebx , esi\n       cmp\tedi , 0b0000h\n       jge\t??no_trailing\n       mov\tecx , 0b0000h\n       sub\tecx , edi \n       sub\tebx , ecx\n       rep\tstosb\n??no_trailing:  \n       add\tedi , [ cpu_video_page ]\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n\n       mov\tecx , ebx\n       rep\tstosb\n       add\tedi , [ esp ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??aligned_loop\t\t\t\t; if more to do than do it\n       pop\teax\n       ret\n\n??in_range:\n       mov\tecx , edi\n       mov\tebx , esi\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tstosb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tstosd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tstosb\n       add\tedi , [ esp ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??aligned_loop\t\t\t\t; if more to do than do it\n       pop\teax\n       ret\n\n\t;*===================================================================\n\t; If not enough bytes to bother aligning copy each line across a byte\n\t;    at a time.\n\t;*===================================================================\n??row_by_row:\n\n       lea\tebx , [ edi + esi ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       mov\tebx , esi \n       jl\t??in_range_bytes\n\n       xor\tecx , ecx\n       mov\tebx , esi\n       cmp\tedi , 0b0000h\n       jge \t??no_trailing_bytes\n       mov\tecx , 0b0000h\n       sub\tecx , edi \n       sub\tebx , ecx\n       rep\tstosb\n??no_trailing_bytes:  \n       add\tedi , [ cpu_video_page ]\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n\t\t\t\t\n??in_range_bytes:\n\n       mov\tecx , ebx\n       rep\tstosb\n       add\tedi , [ esp ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??row_by_row\t\t\t\t; if more to do than do it\n       pop\teax\n       ret\n\nENDP\tVesa_Clear\n\n\nEND\n"
  },
  {
    "path": "WWFLAT32/SVGAPRIM/VESA.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VESA.ASM                                 *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : December 8, 1994                         *\n;*                                                                         *\n;*                  Last Update : December 8, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Vesa_Asm_Set_Win -- Sets the current vesa window from Asm             *\n;*   Vesa_Asm_Next_Window -- Sets to the next vesa window                  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS  ??\n\nINCLUDE \"svgaprim.inc\"\n\nGLOBAL\tRMVesaVector\t: DWORD\nGLOBAL\tRMVesaRegs\t: DWORD\n\n\nDPMI_INTR\tEQU\t31h\t\n\nSTRUC DPMI_REGS\n       _edi  dd ?\n       _esi  dd ?\t\n       _ebp  dd ?\t\n       \t     dd ?\n       _ebx  dd ?\t\n       _edx  dd ?\t\n       _ecx  dd ?\t\n       _eax  dd ?\t\n       Flags dw ?\n       _es   dw ?\n       _ds   dw ?\n       _fs   dw ?\n       _gs   dw ?\n       _ip   dw ?\n       _cs   dw ?\n       _sp   dw ?\n       _ss   dw ?\n       \t     dd ?\t\nENDS\n\n\nDATASEG\n\ncpu_video_page\tdd           0h\ncpu_page_limit  dd\t0b0000h\nCurrentBank\tDD  \t     0h\t\t; current vesa bank  \nRealFunc\tDPMI_REGS   ?\t\t; structure to call a real mode int\n\n\n\tCODESEG\n\n\n;***************************************************************************\n;* VESA_ASM_SET_WIN -- Sets the current vesa window from Asm               *\n;*                                                                         *\n;* INPUT:\tedi - offset to set the window for                         *\n;*                                                                         *\n;* OUTPUT:      edi - adjusted offset for window                           *\n;*                                                                         *\n;* PROTO:\tvoid Vesa_Asm_Set_Win(void);\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   12/08/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_Asm_Set_Win C near \n\n\tpush\teax\n\tpush\tedi\n\tpush\tecx\n\tpush\tebx\n\n\n\tmov\teax , edi\n\tand\teax , 0ffff0000h\n\tadd\teax , 010000h\n\tmov\t[ cpu_page_limit ] , eax\n\n\tlea\teax , [ edi - 0a0000h ]\n\tand\teax , 0ffff0000h\n\tmov\t[ cpu_video_page ] , eax\n\n\tshr\teax , 14\n\tcmp\teax , [ CurrentBank ]\n\tjz\t ??no_change\n\tmov\t[CurrentBank],eax\t\t; it will be new current bank\n\tmov\tebx , [ BankTable + eax ]\t; find gran value of new bank\n\n\tmov     edi , [ RMVesaRegs ]\t\t; clean up RMRegister bank\n\txor\teax , eax\n\tmov\tecx , 34h / 4\t\t\t; size of RMRegs Bank\n\trep\tstosd\n\n\tmov     edi , [ RMVesaRegs ]\n\tmov\t[(type DPMI_REGS ptr edi ) . _eax ] , 04f05h\n\tmov\t[(type DPMI_REGS ptr edi ) . _ebx ] , 0\n\tmov\t[(type DPMI_REGS ptr edi ) . _edx ] , ebx\n\n\tmov\teax , 0300h\n\txor\tecx , ecx\t\t\t; set amount to copy of stack\n\tmov\tebx , [ RMVesaVector]\t\t; set pointer to func to call\n\tint\tDPMI_INTR\t\t\t; make the call\n ??no_change:\n\tpop\tebx\n\tpop\tecx\n\tpop\tedi\n\tpop\teax\n\tand\tedi,0000ffffh\t\t\t; adjust edi to be 64k\n\tadd\tedi,0a0000h\n\tret\n\tENDP\tVesa_Asm_Set_Win\n\nEND\n"
  },
  {
    "path": "WWFLAT32/SVGAPRIM/VGETPIX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Clear the Full Mcga Screen\t\t   *\n;*                                                                         *\n;*                    File Name : GETPIXEL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : June 7, 1994   [PWG]                     *\n;*                                                                         *\t     \n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   GVPC::Get_Pixel -- Gets a pixel from the current graphic view port\t   *\n;*   VVPC::Get_Pixel -- Gets a pixel from the current view port\t\t   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\nCODESEG\n\n\n;***************************************************************************\n;* VVPC::GET_PIXEL -- Gets a pixel from the current view port\t\t   *\n;*                                                                         *\n;* INPUT:\tWORD the x pixel on the screen.\t\t\t\t   *\n;*\t\tWORD the y pixel on the screen.\t\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      UBYTE the pixel at the specified location\t\t   *\n;*                                                                         *\n;* WARNING:\tIf pixel is to be placed outside of the viewport then\t   *\n;*\t\tthis routine will abort.\t\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/07/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_Get_Pixel C near \n\tUSES\tebx,ecx,edx,edi\n\n\tARG    \tthis:DWORD\t\t\t\t; this is a member function\n\tARG\tx_pixel:DWORD\t\t\t\t; x position of pixel to set\n\tARG\ty_pixel:DWORD\t\t\t\t; y position of pixel to set\n\n\t;*===================================================================\n\t; Get the viewport information and put bytes per row in ecx\n\t;*===================================================================\n\tmov\tebx,[this]\t\t\t\t; get a pointer to viewport\n\txor\teax,eax\t\t\t\t\t\n\tmov\tedi,[(VideoViewPort ebx).VIVPOffset]\t; get the correct offset\n\tmov\tecx,[(VideoViewPort ebx).VIVPHeight]\t; edx = height of viewport\n\tmov\tedx,[(VideoViewPort ebx).VIVPWidth]\t; ecx = width of viewport\n\n\t;*===================================================================\n\t; Verify that the X pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[x_pixel]\t\t\t\t; find the x position\n\tcmp\teax,edx\t\t\t\t\t;   is it out of bounds\n\tjae\tshort ??exit\t\t\t\t; if so then get out\n\tadd\tedi,eax\t\t\t\t\t; otherwise add in offset\n\n\t;*===================================================================\n\t; Verify that the Y pixel offset if legal\n\t;*===================================================================\t\n\tmov\teax,[y_pixel]\t\t\t\t; get the y position\n\tcmp\teax,ecx\t\t\t\t\t;  is it out of bounds\n\tjae\t??exit\t\t\t\t\t; if so then get out\n\tadd\tedx,[(VideoViewPort ebx).VIVPXAdd]\t; otherwise find bytes per row\n\tmul\tedx\t\t\t\t\t; offset = bytes per row * y\n\tadd\tedi,eax\t\t\t\t\t; add it into the offset\n\n\t;*===================================================================\n\t;* Figure out what bank we are in and set it, then adjust the\n\t;*   offset.\n\t;*===================================================================\n\n       call\tVesa_Asm_Set_Win\n\n\t;*===================================================================\n\t; Write the pixel to the screen\n\t;*===================================================================\n??in_range:\n\txor\teax,eax\t\t\t\t\t; clear the word\n\tmov\tal,[edi]\t\t\t\t; read in the pixel\n??exit:\n\tret\n\tENDP\tVesa_Get_Pixel\n\nEND\n"
  },
  {
    "path": "WWFLAT32/SVGAPRIM/VLBTOVE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : BITBLIT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : December 13, 1994   [PWG]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\nTRANSP   equ 0\n\nCODESEG\n\n\n;***************************************************************************\n;* GVC::BLIT -- Copies a buffer to a graphic page non-linearly             *\n;*                                                                         *\n;* NOTE:\t\tAll coordinate values are expressed in pixels      *\n;*                                                                         *\n;* INPUT:\tVideoViewPortClass *dest -   Video View Port to copy to    *\n;*\t\tWORD src_x\t     \t   - Src x position to copy from   *\n;*\t\tWORD src_y\t\t   - Src y position to copy from   *\n;*\t\tWORD dst_x\t\t   - Dest x position to copy to\t   *\n;*\t\tWORD dst_y\t\t   - Dest y position to copy to\t   *\n;*\t\tWORD w\t\t\t   - Width of region to copy\t   *\n;*\t\tWORD h\t\t\t   - Height of region to copy\t   *\n;*                                                                         *\n;* OUTPUT:     none                                                        *\n;*                                                                         *\n;* WARNINGS:   Coordinates and dimensions will be adjusted if they exceed  *\n;*\t       the boundaries.  In the event that no adjustment is \t   *\n;*\t       possible this routine will abort.\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   05/11/1994 PWG : Created.                                             *\n;*   08/05/1994 PWG : Fixed clipping problem                               *\n;*=========================================================================*\n\tPROC\tLinear_Blit_To_Vesa C near \n\tUSES\tebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG    \tthis        :DWORD\t\t; this is a member function\n\tARG\tdest        :DWORD\t\t; what are we blitting to\n\tARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\tARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\tARG\tdest_x0     :dword\n\tARG\tdest_y0     :dword\n\tARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\tARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\tARG\ttrans       :DWORD\t\t\t; do we deal with transparents?\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tLOCAL\tdest_x1 : dword\n\tLOCAL\tdest_y1 : dword\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_ajust_width:DWORD\n        LOCAL\tsource_area :  dword\n        LOCAL\tdest_area :  dword\n\n; Clip Source Rectangle against source Window boundaries.\n\tmov  \tesi , [ this ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??clip_against_dest\n\n\ttest\tcl , 1000b\n\tjz\t??scr_left_ok\n\tmov\t[ x_pixel ] , 0\n\n??scr_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\t[ y_pixel ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??clip_against_dest\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n\n; Clip Source Rectangle against destination Window boundaries.\n??clip_against_dest:\n\n\tmov\teax , [ dest_x0 ]\n\tmov\tebx , [ dest_y0 ]\n\tsub\teax , [ x_pixel ]\n\tsub\tebx , [ y_pixel ]\n\tadd\teax , [ x1_pixel ]\n\tadd\tebx , [ y1_pixel ]\n\tmov\t[ dest_x1 ] , eax\n\tmov\t[ dest_y1 ] , ebx\n\n\tmov  \tesi , [ dest ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ dest_x0 ]\n\tmov\tebx , [ dest_x1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\teax , [ dest_y0 ]\n\tmov\tebx , [ dest_y1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_blit\n\n\ttest\tcl , 1000b\n\tjz\t??dest_left_ok\n\tmov\teax , [ dest_x0 ]\n\tmov\t[ dest_x0 ] , 0\n\tsub\t[ x_pixel ] , eax\n\n??dest_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dest_bottom_ok\n\tmov\teax , [ dest_y0 ]\n\tmov\t[ dest_y0 ] , 0\n\tsub\t[ y_pixel ] , eax\n\n\n??dest_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??dest_right_ok\n\tmov\tebx , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ dest_x1 ]\n\tmov\t[ dest_x1 ] , ebx\n\tsub\teax , ebx\n\tsub\t[ x1_pixel ] , eax\n\n??dest_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\tmov\tebx , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\teax , [ dest_y1 ]\n\tmov\t[ dest_y1 ] , ebx\n\tsub\teax , ebx\n\tsub\t[ y1_pixel ] , eax\n\n??do_blit:\n\n       cld\t\n       mov\tebx , [ this ]\n       mov\tesi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\tecx , eax\n       mul\t[ y_pixel ]\n       add\tesi , [ x_pixel ]\n       mov\t[ source_area ] , ecx\n       add\tesi , eax\n\n       add\tecx , [ x_pixel ]\n       sub\tecx , [ x1_pixel ]\n       mov\t[ scr_ajust_width ] , ecx\n\n       mov\tebx , [ dest ]\n       mov\tedi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\tecx , eax\n       mul\t[ dest_y0 ]\n       add\tedi , [ dest_x0 ]\n       mov\t[ dest_area ] , ecx\n       add\tedi , eax\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n\n       mov\teax , [ dest_x1 ]\n       sub\teax , [ dest_x0 ]\n       jz\t??real_out\n       sub\tecx , eax\n       mov\t[ dest_ajust_width ] , ecx\n\n       mov\tedx , [ dest_y1 ]\n       sub\tedx , [ dest_y0 ]\n       jz\t??real_out\n\n\n; ********************************************************************       \n; Forward bitblit only\n\nIF TRANSP\n       test\t[ trans ] , 1\n       jnz\t??forward_Blit_trans\nENDIF\n\n\n; the inner loop is so efficient that \n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10        \n       jl\t??forward_loop_bytes\n\n??forward_loop_dword:\n       lea\tebx , [ edi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??in_range\n\n       xor\tecx , ecx\n       mov\tebx , eax\n       cmp\tedi , 0b0000h\n       jge\t??no_trailing\n       mov\tecx , 0b0000h\n       sub\tecx , edi \n       sub\tebx , ecx\n       rep\tmovsb\n??no_trailing:  \n       add\tedi , [ cpu_video_page ]\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_dword\n       ret\n\n??in_range:\n\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_dword\n       ret\n\n??forward_loop_bytes:\n       lea\tebx , [ edi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       mov\tebx , eax\n       jl\t??in_range_bytes\n\n       xor\tecx , ecx\n       cmp\tedi , 0b0000h\n       jge\t??no_trailing_bytes\n       mov\tecx , 0b0000h\n       sub\tecx , edi \n       sub\tebx , ecx\n       rep\tmovsb\n??no_trailing_bytes:  \n       add\tedi , [ cpu_video_page ]\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n??in_range_bytes:\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_bytes\n       ret\n\nIF\tTRANSP\n\n??forward_Blit_trans:\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\t\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n??forward_loop_trans:\n       mov\tecx , eax \n       jmp\t[ y1_pixel ]\n??forward_trans_line:\n       REPT\t32\t\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tesi\n\t    \tinc\tedi\n\tENDM\n    ??transp_reference:\n       dec\tecx \n       jge\t??forward_trans_line\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_trans\n       ret\nENDIF\n\n??real_out:\n       ret\nENDP\tLinear_Blit_To_Vesa\n\nEND\n"
  },
  {
    "path": "WWFLAT32/SVGAPRIM/VPUTPIX.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Clear the Full Mcga Screen\t\t   *\n;*                                                                         *\n;*                    File Name : PUTPIXEL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil Gorrow\t\t\t\t   *\n;*                                                                         *\n;*                   Start Date : June 7, 1994\t\t\t\t   *\n;*                                                                         *\n;*                  Last Update : June 8, 1994   [PWG]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   GVPC::Put_Pixel -- Puts a pixel on a graphic viewport                 *\n;*   VIVPC::Put_Pixel -- Puts a pixel on a virtual viewport                *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\n\tCODESEG\n\n;***************************************************************************\n;* VIVPC::PUT_PIXEL -- Puts a pixel on a video viewport                    *\n;*                                                                         *\n;* INPUT:\tWORD the x position for the pixel relative to the upper    *\n;*\t\t\tleft corner of the viewport\t\t\t   *\n;*\t\tWORD the y pos for the pixel relative to the upper left\t   *\n;*\t\t\tcorner of the viewport\t\t\t\t   *\n;*\t\tUBYTE the color of the pixel to write\t\t\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNING:\tIf pixel is to be placed outside of the viewport then\t   *\n;*\t\tthis routine will abort.\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/08/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_Put_Pixel C near \n\tUSES\teax,ebx,ecx,edx,edi,esi\n\n\tARG    \tthis:DWORD\t\t\t\t; this is a member function\n\tARG\tx_pixel:DWORD\t\t\t\t; x position of pixel to set\n\tARG\ty_pixel:DWORD\t\t\t\t; y position of pixel to set\n\tARG    \tcolor:BYTE\t\t\t\t; what color should we clear to\n\n\t;*===================================================================\n\t; Get the viewport information and put bytes per row in ecx\n\t;*===================================================================\n\tmov\tebx,[this]\t\t\t\t; get a pointer to viewport\n\tmov\tedi,[(VideoViewPort ebx).VIVPOffset]\t; get the correct offset\n\tmov\tecx,[(VideoViewPort ebx).VIVPHeight]\t; edx = height of viewport\n\tmov\tedx,[(VideoViewPort ebx).VIVPWidth]\t; ecx = width of viewport\n\n\t;*===================================================================\n\t; Verify that the X pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[x_pixel]\t\t\t\t; find the x position\n\tcmp\teax,edx\t\t\t\t\t;   is it out of bounds\n\tjae\tshort ??exit\t\t\t\t; if so then get out\n\tadd\tedi,eax\t\t\t\t\t; otherwise add in offset\n\n\t;*===================================================================\n\t; Verify that the Y pixel offset if legal\n\t;*===================================================================\n\tmov\teax,[y_pixel]\t\t\t\t; get the y position\n\tcmp\teax,ecx\t\t\t\t\t;  is it out of bounds\n\tjae\t??exit\t\t\t\t\t; if so then get out\n\tadd\tedx,[(VideoViewPort ebx).VIVPXAdd]\t; otherwise find bytes per row\n\tmul\tedx\t\t\t\t\t; offset = bytes per row * y\n\tadd\tedi,eax\t\t\t\t\t; add it into the offset\n\n\t;*===================================================================\n\t;* Figure out what bank we are in and set it, then adjust the\n\t;*   offset.\n\t;*===================================================================\n       call\tVesa_Asm_Set_Win\n\n\t;*===================================================================\n\t; Write the pixel to the screen\n\t;*===================================================================\n\tmov\tal,[color]\t\t\t\t; read in color value\n\tmov\t[edi],al\t\t\t\t; write it to the screen\n??exit:\n\tret\n\tENDP\tVesa_Put_Pixel\nEND\n"
  },
  {
    "path": "WWFLAT32/SVGAPRIM/VSCALE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Testing memory.                          *\n *                                                                         *\n *                    File Name : TEST.CPP                                 *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : April 14, 1994                           *\n *                                                                         *\n *                  Last Update : January 18, 1995   [PWG]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n*/\n#include <mcgaprim.h>\n#include <gbuffer.h>\n#include <vbuffer.h>\n\n//VideoBufferClass\t\tSeenPage(640,480);\n//GraphicBufferClass \tHidBuff;\n//GraphicBufferClass \tBackBuff;\n\nint Vesa_Scale_To_Vesa ( void * scr,  void * dst, \n\t\t\t\t\t\t\t\t int src_x  , int src_y  , int dst_x , int dst_y , \n\t\t\t\t\t\t\t\t int src_wd , int src_hg , int dst_wd, int dst_hg, \n\t\t\t\t\t\t\t\t BOOL trans , char * remap )\n{\n  int\t   area ;\n  int    width , height ;\n  char * temp ;\n\n  VideoViewPortClass * scr1 = ( VideoViewPortClass * ) scr ;\n\n  width  = src_wd - src_x ;\n  height = src_hg - src_y ;\n  area = width * height ;\n  temp = ( char * ) malloc ( area ) ;\n  if ( ! temp ) return 0 ;\n\n  scr1 -> To_Buffer ( 0, 0, width , height , temp, area );\n  GraphicBufferClass tempbuffer ( area , width , height , temp ) ;\n\n\n  tempbuffer . Scale ( * scr1 , \n                       0, 0, dst_x, dst_y, \n                       width, height , dst_wd, dst_hg , \n\t\t\t\t\t\t\t  trans , remap );\n\n\n  free ( temp ) ;\n  return 0 ;\n}\n"
  },
  {
    "path": "WWFLAT32/SVGAPRIM/VSCLTOVE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : VSCALE.ASM                               *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 16, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 16, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Linear_Scale_To_Vesa -- Scales a graphic viewport to a vesa viewport  *\n;*   Vesa_Scale_To_Linear -- Scales a Vesa viewport to a graphic viewport  *\n;*   Vesa_Scale_To_Vesa -- Scales a vesa viewport to a vesa viewport       *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"mcgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\nGLOBAL \tVesa_Asm_Set_Win   : near\t\t\t\nGLOBAL\tcpu_video_page     : dword\nGLOBAL\tcpu_page_limit     : dword\n\n\nCODESEG\n\n\n;***************************************************************************\n;* LINEAR_SCALE_TO_VESA -- Scales a graphic viewport to a vesa viewport\t   *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/16/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tLinear_Scale_To_Vesa C near\n\n\t;*===================================================================\n\t;* Define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tthis:DWORD\t\t; pointer to source view port\n\tARG\tdest:DWORD\t\t; pointer to destination view port\n\tARG\tsrc_x:DWORD\t\t; source x offset into view port\n\tARG\tsrc_y:DWORD\t\t; source y offset into view port\n\tARG\tdst_x:DWORD\t\t; dest x offset into view port\n\tARG\tdst_y:DWORD\t\t; dest y offset into view port\n\tARG\tsrc_width:DWORD\t\t; width of source rectangle\n\tARG\tsrc_height:DWORD\t; height of source rectangle\n\tARG\tdst_width:DWORD\t\t; width of dest rectangle\n\tARG\tdst_height:DWORD\t; width of dest height\n\tARG\ttrans:DWORD\t\t; is this transparent?\n\tARG\tremap:DWORD\t\t; pointer to table to remap source\n\n\t;*===================================================================\n\t;* Define local variables to hold the viewport characteristics\n\t;*===================================================================\n\tlocal\tsrc_x0 : dword\n\tlocal\tsrc_y0 : dword\n\tlocal\tsrc_x1 : dword\n\tlocal\tsrc_y1 : dword\n\n\tlocal\tdst_x0 : dword\n\tlocal\tdst_y0 : dword\n\tlocal\tdst_x1 : dword\n\tlocal\tdst_y1 : dword\n\n\tlocal\tsrc_win_width : dword\n\tlocal\tdst_win_width : dword\n\tlocal\tdy_intr : dword\n\tlocal\tdy_frac : dword\n\tlocal\tdy_acc  : dword\n\tlocal\tdx_frac : dword\n\tlocal\tdx_intr : dword\n\n\tlocal\tscan_line     : dword\t\n\tlocal\tcounter_x     : dword\n\tlocal\tcounter_y     : dword\n\tlocal\tremap_counter :dword\n\tlocal\tentry : dword\n\n\n\t;*===================================================================\n\t;* Check for scale error when to or from size 0,0\n\t;*===================================================================\n\tcmp\t[dst_width],0\n\tje\t??all_done\n\tcmp\t[dst_height],0\n\tje\t??all_done\n\tcmp\t[src_width],0\n\tje\t??all_done\n\tcmp\t[src_height],0\n\tje\t??all_done\n\n\tmov\teax , [ src_x ]\n\tmov\tebx , [ src_y ]\n\tmov\t[ src_x0 ] , eax \n\tmov\t[ src_y0 ] , ebx \n\tadd\teax , [ src_width ]\n\tadd\tebx , [ src_height ]\n\tmov\t[ src_x1 ] , eax \n\tmov\t[ src_y1 ] , ebx \n\n\tmov\teax , [ dst_x ]\n\tmov\tebx , [ dst_y ]\n\tmov\t[ dst_x0 ] , eax \n\tmov\t[ dst_y0 ] , ebx \n\tadd\teax , [ dst_width ]\n\tadd\tebx , [ dst_height ]\n\tmov\t[ dst_x1 ] , eax \n\tmov\t[ dst_y1 ] , ebx \n\n; Clip Source Rectangle against source Window boundaries.\n\tmov  \tesi , [ this ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ src_x0 ]\n\tmov\tebx , [ src_x1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\teax , [ src_y0 ]\n\tmov\tebx , [ src_y1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??all_done\n\tor\tal , dl\n\tjz\t??clip_against_dest\n\tmov\tbl , dl\n\ttest\tcl , 1000b\n\tjz\t??src_left_ok\n\txor\teax , eax\n\tmov\t[ src_x0 ] , eax\n\tsub\teax , [ src_x ]\n\timul\t[ dst_width ]\n\tidiv\t[ src_width ]\n\tadd\teax , [ dst_x ]\n\tmov\t[ dst_x0 ] , eax\n\n??src_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??src_bottom_ok\n\txor\teax , eax\n\tmov\t[ src_y0 ] , eax\n\tsub\teax , [ src_y ]\n\timul\t[ dst_height ]\n\tidiv\t[ src_height ]\n\tadd\teax , [ dst_y ]\n\tmov\t[ dst_y0 ] , eax\n\n??src_bottom_ok:\n\ttest\tbl , 0100b\n\tjz\t??src_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ src_x1 ] , eax\n\tsub\teax , [ src_x ]\n\timul\t[ dst_width ]\n\tidiv\t[ src_width ]\n\tadd\teax , [ dst_x ]\n\tmov\t[ dst_x1 ] , eax\n\n??src_right_ok:\n\ttest\tbl , 0001b\n\tjz\t??clip_against_dest\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ src_y1 ] , eax\n\tsub\teax , [ src_y ]\n\timul\t[ dst_height ]\n\tidiv\t[ src_height ]\n\tadd\teax , [ dst_y ] \n\tmov\t[ dst_y1 ] , eax\n\n; Clip destination Rectangle against source Window boundaries.\n??clip_against_dest:\n\tmov  \tesi , [ dest ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ dst_x0 ]\n\tmov\tebx , [ dst_x1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\teax , [ dst_y0 ]\n\tmov\tebx , [ dst_y1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??all_done\n\tor\tal , dl\n\tjz\t??do_scaling\n\tmov\tbl , dl\n\ttest\tcl , 1000b\n\tjz\t??dst_left_ok\n\txor\teax , eax\n\tmov\t[ dst_x0 ] , eax\n\tsub\teax , [ dst_x ]\n\timul\t[ src_width ]\n\tidiv\t[ dst_width ]\n\tadd\teax , [ src_x ]\n\tmov\t[ src_x0 ] , eax\n\n??dst_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dst_bottom_ok\n\txor\teax , eax\n\tmov\t[ dst_y0 ] , eax\n\tsub\teax , [ dst_y ]\n\timul\t[ src_height ]\n\tidiv\t[ dst_height ]\n\tadd\teax , [ src_y ]\n\tmov\t[ src_y0 ] , eax\n\n??dst_bottom_ok:\n\ttest\tbl , 0100b\n\tjz\t??dst_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ dst_x1 ] , eax\n\tsub\teax , [ dst_x ]\n\timul\t[ src_width ]\n\tidiv\t[ dst_width ]\n\tadd\teax , [ src_x ]\n\tmov\t[ src_x1 ] , eax\n\n??dst_right_ok:\n\ttest\tbl , 0001b\n\tjz\t??do_scaling\n\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ dst_y1 ] , eax\n\tsub\teax , [ dst_y ]\n\timul\t[ src_height ]\n\tidiv\t[ dst_height ]\n\tadd\teax , [ src_y ]\n\tmov\t[ src_y1 ] , eax\n\n??do_scaling:\n\n       cld\t\n       mov\tebx , [ this ]\n       mov\tesi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\t[ src_win_width ] , eax\n       mul\t[ src_y0 ]\n       add\tesi , [ src_x0 ]\n       add\tesi , eax\n\n       mov\tebx , [ dest ]\n       mov\tedi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\t[ dst_win_width ] , eax\n       mul\t[ dst_y0 ]\n       add\tedi , [ dst_x0 ]\n       add\tedi , eax\n       call\tVesa_Asm_Set_Win\t\t\t; set the window\n\n       mov\teax , [ src_height ]\n       xor\tedx , edx\n       mov\tebx , [ dst_height ]\n       idiv\t[ dst_height ]\n       imul\teax , [ src_win_width ]\n       neg\tebx\n       mov\t[ dy_intr ] , eax\n       mov\t[ dy_frac ] , edx\n       mov\t[ dy_acc ]  , ebx\n\n       mov\teax , [ src_width ]\n       xor\tedx , edx\n       shl\teax , 16\n       idiv\t[ dst_width ]\n       xor\tedx , edx\n       shld\tedx , eax , 16\n       shl\teax , 16\n\n       mov\tecx , [ dst_y1 ]\n       mov\tebx , [ dst_x1 ]\n       sub\tecx , [ dst_y0 ]\n       jz\t??all_done\n       sub\tebx , [ dst_x0 ]\n       jz\t??all_done\n\n       mov\t[ counter_y ] , ecx\n       mov\t[ scan_line ] , ebx\n\n       cmp\t[ trans ] , 0\n       jnz\t??transparency\n\n       cmp\t[ remap ] , 0\n       jnz\t??normal_remap\n\n; *************************************************************************\n; normal scale\n       mov\tecx , ebx\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 2 ]\n       shr\tebx , 5\n       neg\tecx\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??ref_point + ecx + ecx * 2 ]\n       mov\t[ entry ] , ecx\n\n ??outter_loop:\n       mov\tebx , [ scan_line ]\n       push\tesi\n       add\tebx , edi \n       xor\tecx , ecx\n       add\tebx , [ cpu_video_page ]\n       push\tedi\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??in_range\n       mov\tebx , [ scan_line ]\n       jmp      ??trailing_entry \n  ??trailing_bytes: \n       mov\tcl , [ esi ]\n       add\tecx , eax\n       adc\tesi , edx\n       mov\t[ edi ] , cl\n       inc\tedi\n       dec\tebx\n  ??trailing_entry: \n       cmp\tedi , 0b0000h\n       jl\t??trailing_bytes\n       add\tedi , [ cpu_video_page ]\n       call\tVesa_Asm_Set_Win\t\t\t; set the window\n??end_of_scanline:\n       mov\tcl , [ esi ]\n       add\tecx , eax\n       adc\tesi , edx\n       mov\t[ edi ] , cl\n       inc\tedi\n       dec\tebx\n       jg\t??end_of_scanline\n       sub\t[ dword ptr esp ] , 010000h\n       jmp\t??next_line\n\n??in_range:\n       mov\tebx , [ counter_x ]\n       jmp\t[ entry ]\n ??inner_loop:\n       REPT\t32\t\n\t       mov\tcl , [ esi ]\n\t       add\tecx , eax\n\t       adc\tesi , edx\n\t       mov\t[ edi ] , cl\n\t       inc\tedi\n       ENDM\n ??ref_point:\n       dec\tebx\n       jge\t??inner_loop\n  ??next_line:\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??skip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??skip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??outter_loop\n\tret\n\n\n; *************************************************************************\n; normal scale with remap\n\n??normal_remap:\t\n       mov\tecx , ebx\n       mov\t[ dx_frac ] , eax\n       mov\t[ dx_intr ] , edx\n\n       and\tecx , 01fh\n       mov\teax , [ remap ]\n       shr\tebx , 5\n       imul\tecx , - 13\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??remapref_point + ecx ]\n       mov\t[ entry ] , ecx\n\n ??remapoutter_loop:\n       mov\tebx , [ scan_line ]\n       push\tesi\n       add\tebx , edi \n       xor\tecx , ecx\n       add\tebx , [ cpu_video_page ]\n       push\tedi\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??remap_in_range\n       mov\tedx , [ scan_line ]\n       xor\tebx , ebx\n       jmp    ??remap_trailing_entry \n ??remap_trailing_bytes: \n       mov\tbl , [ esi ]\n       add\tecx , [ dx_frac ]\n       adc\tesi , [ dx_intr ]\n       mov\tcl , [ eax + ebx ]\n       mov\t[ edi ] , cl\n       inc\tedi\n       dec\tedx\n ??remap_trailing_entry:\n       cmp\tedi , 0b0000h\n       jl\t??remap_trailing_bytes\n??remap_no_trailing:  \n       add\tedi , [ cpu_video_page ]\n       call\tVesa_Asm_Set_Win\t\t\t; set the window\n??remap_end_of_scanline:\n       mov\tbl , [ esi ]\n       add\tecx , [ dx_frac ]\n       adc\tesi , [ dx_intr ]\n       mov\tcl , [ eax + ebx ] \n       mov\t[ edi ] , cl\n       inc\tedi\n       dec\tedx\n       jg\t??remap_end_of_scanline\n       sub\t[ dword ptr esp ] , 010000h\n       jmp\t??remap_next_line\n??remap_in_range:\n       mov\tebx , [ counter_x ]\n       push\tesi\n       mov\t[ remap_counter ] , ebx\n       push\tedi\n       mov\tedx , [ dx_intr ]\n       xor\tecx , ecx\n       xor\tebx , ebx\n       jmp\t[ entry ]\n ??remapinner_loop:\n       REPT\t32\t\n\t       mov\tbl , [ esi ]\n\t       add\tecx , [ dx_frac ]\n\t       adc\tesi , edx\n\t       mov\tcl , [ eax + ebx ]\n\t       mov\t[ edi ] , cl\n\t       inc\tedi\n       ENDM\n ??remapref_point:\n       dec\t[ remap_counter ] \n       jge\t??remapinner_loop\n ??remap_next_line:\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??remapskip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??remapskip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??remapoutter_loop\n\tret\n\n\n;****************************************************************************\n; scale with transparency\n\n??transparency:\n       cmp\t[ remap ] , 0\n       jnz\t??trans_remap\n\n; *************************************************************************\n; normal scale with transparency\n       mov\tecx , ebx\n       and\tecx , 01fh\n       imul\tecx , -13\n       shr\tebx , 5\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??tr_ref_point + ecx ]\n       mov\t[ entry ] , ecx\n\n ??tr_outter_loop:\n       mov\tebx , [ scan_line ]\n       push\tesi\n       add\tebx , edi \n       xor\tecx , ecx\n       add\tebx , [ cpu_video_page ]\n       push\tedi\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??tr_in_range\n\n       mov\tebx , [ scan_line ]\n       jmp     ??tr_trailing_entry \n  ??tr_trailing_bytes: \n       mov\tcl , [ esi ]\n       test\tcl , cl\n       jz\t??tr_skip\n      mov\t[ edi ] , cl\n   ??tr_skip:\n       add\tecx , eax\n       adc\tesi , edx\n       inc\tedi\n       dec\tebx\n  ??tr_trailing_entry: \n       cmp\tedi , 0b0000h\n       jl\t??tr_trailing_bytes\n       add\tedi , [ cpu_video_page ]\n       call\tVesa_Asm_Set_Win\t\t\t; set the window\n??tr_end_of_scanline:\n       mov\tcl , [ esi ]\n       test\tcl , cl\n       jz\t??tr_skip1\n       mov\t[ edi ] , cl\n   ??tr_skip1:\n       add\tecx , eax\n       adc\tesi , edx\n       inc\tedi\n       dec\tebx\n       jg\t??tr_end_of_scanline\n       sub\t[ dword ptr esp ] , 010000h\n       jmp\t??tr_next_line\n\n??tr_in_range:\n       mov\tebx , [ counter_x ]\n       jmp\t[ entry ]\n ??tr_inner_loop:\n       REPT\t32\t\n       local\tskip\n\t       mov\tcl , [ esi ]\n\t       test\tcl , cl\n\t       jz\tskip\n\t       mov\t[ edi ] , cl\n\t    skip:\n\t       add\tecx , eax\n\t       adc\tesi , edx\n\t       inc\tedi\n       ENDM\n ??tr_ref_point:\n       dec\tebx\n       jge\t??tr_inner_loop\n  ??tr_next_line:\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??tr_skip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??tr_skip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??tr_outter_loop\n\tret\n\n\n\n; *************************************************************************\n; normal scale with remap and transparency\n\n??trans_remap:\t\n       mov\tecx , ebx\n       mov\t[ dx_frac ], eax\n       mov\t[ dx_intr ] , edx\n\n       and\tecx , 01fh\n       mov\teax , [ remap ]\n       shr\tebx , 5\n       imul\tecx , - 17\n       mov\t[ counter_x ] , ebx\n       lea\tecx , [ ??trans_remapref_point + ecx ]\n       mov\t[ entry ] , ecx\n\n ??trans_remapoutter_loop:\n       mov\tebx , [ scan_line ]\n       push\tesi\n       add\tebx , edi \n       xor\tecx , ecx\n       add\tebx , [ cpu_video_page ]\n       push\tedi\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??trans_remap_in_range\n       mov\tedx , [ scan_line ]\n       xor\tebx , ebx\n       jmp    ??trans_remap_trailing_bytes1 \n  ??trans_remap_trailing_bytes: \n       mov\tbl , [ esi ]\n       test\tbl , bl\n       jz\t??trans_remp\n       mov\tcl , [ eax + ebx ]\n       mov\t[ edi ] , cl\n    ??trans_remp:\n       add\tecx , [ dx_frac ]\n       adc\tesi , [ dx_intr ]\n       inc\tedi\n       dec\tedx\n  ??trans_remap_trailing_bytes1: \n       cmp\tedi , 0b0000h\n       jl\t??trans_remap_trailing_bytes\n??trans_remap_no_trailing:  \n       add\tedi , [ cpu_video_page ]\n       call\tVesa_Asm_Set_Win\t\t\t; set the window\n??trans_remap_end_of_scanline:\n       mov\tbl , [ esi ]\n       test\tbl , bl\n       jz\t??trans_remp1\n       mov\tcl , [ eax + ebx ]\n       mov\t[ edi ] , cl\n   ??trans_remp1:\n       add\tecx , [ dx_frac ]\n       adc\tesi , [ dx_intr ]\n       inc\tedi\n       dec\tedx\n       jg\t??trans_remap_end_of_scanline\n       sub\t[ dword ptr esp ] , 010000h\n       jmp\t??trans_remap_next_line\n\n??trans_remap_in_range:\n       mov\tebx , [ counter_x ]\n       push\tesi\n       mov\t[ remap_counter ] , ebx\n       push\tedi\n       mov\tedx , [ dx_intr ]\n       xor\tecx , ecx\n       xor\tebx , ebx\n       jmp\t[ entry ]\n ??trans_remapinner_loop:\n       REPT\t32\t\n       local\tskip\n\t       mov\tbl , [ esi ]\n\t       test\tbl , bl\n\t       jz\tskip\n\t       mov\tcl , [ eax + ebx ]\n\t       mov\t[ edi ] , cl\n\t  skip:\n\n\t       add\tecx , [ dx_frac ]\n\t       adc\tesi , edx\n\t       inc\tedi\n       ENDM\n ??trans_remapref_point:\n       dec\t[ remap_counter ] \n       jge\t??trans_remapinner_loop\n ??trans_remap_next_line:\n       pop\tedi\n       pop\tesi\n       add\tedi , [ dst_win_width ]\n       add\tesi , [ dy_intr ]\n\n       mov\tebx , [ dy_acc ]\n       add\tebx , [ dy_frac ]\n       jle\t??trans_remapskip_line\n       add\tesi , [ src_win_width ]\n       sub\tebx , [ dst_height ]\n??trans_remapskip_line:\n\tdec\t[ counter_y ]\n\tmov\t[ dy_acc ] , ebx\n\tjnz\t??trans_remapoutter_loop\n\tret\n\n??all_done:\n\tret\n\n\tENDP\tLinear_Scale_To_Vesa\n\nEND\n"
  },
  {
    "path": "WWFLAT32/SVGAPRIM/VTOBUFF.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TOBUFFER.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : June 15, 1994   [PWG]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VVC::TOBUFFER -- Copies a virtual viewport to a linear buffer         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\n\nTRANSP equ 0\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\nCODESEG\n\n\n;***************************************************************************\n;* VIVC::TOBUFFER -- Copies a virtual viewport to a linear buffer          *\n;*                                                                         *\n;* INPUT:\tBYTE *\tdest\t\t- buffer to copy to\t\t   *\n;*\t\t\tsize\t\t- size of the buffer to copy to\t   *\n;*\t\t\tx_pixel\t\t- x pixel on viewport to copy from *\n;*\t\t\ty_pixel \t- y pixel on viewport to copy from *\n;*\t\t\tpixel_width\t- the width of copy region\t   *\n;*\t\t\tpixel_height\t- the height of copy region\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    Coordinates and dimensions will be adjusted if they exceed *\n;*\t        the boundaries.  In the event that no adjustment is \t   *\n;*\t        possible this routine will abort.  If the size of the \t   *\n;*\t\tregion to copy exceeds the size passed in for the buffer   *\n;*\t\tthe routine will automatically abort.\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/15/1994 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_To_Buffer C near \n\tUSES\tebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tthis:DWORD\t\t; this is a class member function\n\tARG\tx_pixel:DWORD\t\t; Page X pixel coordinate.\n\tARG\ty_pixel:DWORD\t\t; Page Y pixel coordinate.\n\tARG\tpixel_width:DWORD\t; Width of region in pixels.\n\tARG\tpixel_height:DWORD\t; Height of region in pixels.\n\tARG\tdest:DWORD\t\t; the buffer to copy to\n\tARG\tsize:DWORD\t\t; the size of the buffer\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tLOCAL\tdest_x1 : dword\n\tLOCAL\tdest_y1 : dword\n\tLOCAL\tdest_ajust_width:DWORD\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_area   :  dword\n\n; Clip dest Rectangle against source Window boundaries.\n\tmov\t[ dest_x1 ] , 0\n\tmov\t[ dest_y1 ] , 0\n\n\tmov  \tesi , [ this ]\t    ; get ptr to dest\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_blit\n\t\t\t    \n\ttest\tcl , 1000b\n\tjz\t??scr_left_ok\n\tmov\teax , [ x_pixel ] \n\tneg\teax\n\tmov\t[ x_pixel ] , 0\n\tmov\t[ dest_x1 ] , eax\n\n??scr_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??scr_bottom_ok\n \tmov\teax , [ y_pixel ] \n\tneg\teax\n\tmov\t[ y_pixel ] , 0\n\tmov\t[ dest_y1 ] , eax\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n??do_blit:\n\n       cld\t\n\n       mov\teax , [ (VideoViewPort esi) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort esi) . VIVPWidth ]\n       mov\tedi , [ (VideoViewPort esi) . VIVPOffset ]\n\n       mov\tecx , eax\n       mul\t[ y_pixel ]\n       add\tedi , [ x_pixel ]\n       add\tedi , eax\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n       mov\tesi , edi\n\n       add\tecx , [ x_pixel ]\n       sub\tecx , [ x1_pixel ]\n       mov\t[ scr_ajust_width ] , ecx\n\n       mov\tedi , [ dest ]\n       mov\teax , [ pixel_width ]\n       sub\teax , [ x1_pixel ]\n       add\teax , [ x_pixel ]\n       mov\t[ dest_ajust_width ] , eax\n\n       mov\teax , [ dest_y1 ]\n       mul \t[ pixel_width ]\n       add\teax , [ dest_x1 ]\n       add\tedi , eax\n\n       mov\tedx , [ y1_pixel ]\n       sub\tedx , [ y_pixel ]\n       jz\t??real_out\n\n       mov\teax , [ x1_pixel ]\n       sub\teax , [ x_pixel ]\n       jz\t??real_out\n\n       mov\tebx , [ pixel_width ]\n       imul\tebx , edx\n       cmp\tebx , [ size ]\n       jg\t??real_out\t\t\n\n\n; ********************************************************************       \n; Forward bitblit only\n\nIF  TRANSP\n       test\t[ trans ] , 1\n       jnz\t??forward_Blit_trans\nENDIF\n\n\n; the inner loop is so efficient that \n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10        \n       jl\t??forward_loop_bytes\n\n??forward_loop_dword:\n\n       lea\tebx , [ esi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??in_range\n\n       xor\tecx , ecx\n       cmp\tesi , 0b0000h\n       mov\tebx , eax\n       jge\t??no_trailing\n       mov\tecx , 0b0000h\n       sub\tecx , esi \n       sub\tebx , ecx\n       rep\tmovsb\n??no_trailing:  \n       add\tesi , [ cpu_video_page ]\n       xchg\tedi , esi\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n       xchg\tedi , esi\n\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_dword\n       ret\n\n??in_range:\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_dword\n       ret\n\n??forward_loop_bytes:\n       lea\tebx , [ esi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       mov\tebx , eax\n       jl\t??in_range_bytes\n\n       xor\tecx , ecx\n       cmp\tesi , 0b0000h\n       jge\t??no_trailing_bytes\n       mov\tecx , 0b0000h\n       sub\tecx , esi \n       sub\tebx , ecx\n       rep\tmovsb\n??no_trailing_bytes:  \n       add\tesi , [ cpu_video_page ]\n       xchg\tedi , esi\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n       xchg\tedi , esi\n??in_range_bytes:\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_bytes\n       ret\n\n\n\nIF  TRANSP\n\n\n??forward_Blit_trans:\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\t\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n??forward_loop_trans:\n       mov\tecx , eax \n       jmp\t[ y1_pixel ]\n??forward_trans_line:\n       REPT\t32\t\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tesi\n\t    \tinc\tedi\n\tENDM\n    ??transp_reference:\n       dec\tecx \n       jge\t??forward_trans_line\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_trans\n       ret\nENDIF\n\n??real_out:\n       ret\n\nENDP\tVesa_To_Buffer\nEND\n\n"
  },
  {
    "path": "WWFLAT32/SVGAPRIM/VTOPAGE.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TOPAGE.ASM                               *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : December 9, 1994   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Buffer_To_Page(GVC) -- Copies a linear buffer to a graphic viewport   *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nTRANSP\tequ  0\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\nCODESEG\n\n;***************************************************************************\n;* VVC::TOPAGE -- Copies a linear buffer to a virtual viewport\t\t   *\n;*                                                                         *\n;* INPUT:\tWORD\tx_pixel\t\t- x pixel on viewport to copy from *\n;*\t\tWORD\ty_pixel \t- y pixel on viewport to copy from *\n;*\t\tWORD\tpixel_width\t- the width of copy region\t   *\n;*\t\tWORD\tpixel_height\t- the height of copy region\t   *\n;*\t\tBYTE *\tsrc\t\t- buffer to copy from\t\t   *\n;*\t\tVVPC *  dest\t\t- virtual viewport to copy to\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    Coordinates and dimensions will be adjusted if they exceed *\n;*\t        the boundaries.  In the event that no adjustment is \t   *\n;*\t        possible this routine will abort.  If the size of the \t   *\n;*\t\tregion to copy exceeds the size passed in for the buffer   *\n;*\t\tthe routine will automatically abort.\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/15/1994 PWG : Created.                                             *\n;*   12/09/1994 PWG : Made SVGA Modifications                              *\n;*=========================================================================*\n\tPROC\tVesa_Buffer_To_Page C near \n\tUSES\tebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\tARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\tARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\tARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\tARG    \tsrc         :DWORD\t\t; this is a member function\n\tARG\tdest        :DWORD\t\t; what are we blitting to\n\n;\tARG\ttrans       :DWORD\t\t\t; do we deal with transparents?\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tLOCAL\tscr_x1 : dword\n\tLOCAL\tscr_y1 : dword\n\tLOCAL\tdest_ajust_width:DWORD\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_area   :  dword\n\n\tcmp\t[ src ] , 0\n\tjz\t??real_out\n\n\n; Clip dest Rectangle against source Window boundaries.\n\n\tmov\t[ scr_x1 ] , 0 \n\tmov\t[ scr_y1 ] , 0 \n\tmov  \tesi , [ dest ]\t    ; get ptr to dest\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_blit\n\n\ttest\tcl , 1000b\n\tjz\t??dest_left_ok\n\tmov\teax , [ x_pixel ]\n\tneg\teax \n\tmov\t[ x_pixel ] , 0\n\tmov\t[ scr_x1 ] , eax\n\n??dest_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dest_bottom_ok\n\tmov\teax , [ y_pixel ]\n\tneg\teax \n\tmov\t[ y_pixel ] , 0\n\tmov\t[ scr_y1 ] , eax\n\n??dest_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??dest_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??dest_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n??do_blit:\n\n       cld\t\n\n       mov\teax , [ (VideoViewPort esi) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort esi) . VIVPWidth ]\n       mov\tedi , [ (VideoViewPort esi) . VIVPOffset ]\n\n       mov\tecx , eax\n       mul\t[ y_pixel ]\n       add\tedi , [ x_pixel ]\n       add\tedi , eax\n       call\tVesa_Asm_Set_Win\t\t\t; set the window\n\n\n       add\tecx , [ x_pixel ]\n       sub\tecx , [ x1_pixel ]\n       mov\t[ dest_ajust_width ] , ecx\n\n\n       mov\tesi , [ src ]\n       mov\teax , [ pixel_width ]\n       sub\teax , [ x1_pixel ]\n       add\teax , [ x_pixel ]\n       mov\t[ scr_ajust_width ] , eax\n\n       mov\teax , [ scr_y1 ]\n       mul \t[ pixel_width ]\n       add\teax , [ scr_x1 ]\n       add\tesi , eax\n\n\n       mov\tedx , [ y1_pixel ]\n       sub\tedx , [ y_pixel ]\n       jz\t??real_out\n\n       mov\teax , [ x1_pixel ]\n       sub\teax , [ x_pixel ]\n       jz\t??real_out\n\n\n; ********************************************************************       \n; Forward bitblit only\n\nIF TRANSP\n       test\t[ trans ] , 1\n       jnz\t??forward_Blit_trans\nENDIF\n\n\n; the inner loop is so efficient that \n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10        \n       jl\t??forward_loop_bytes\n\n??forward_loop_dword:\n\n       lea\tebx , [ edi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??in_range\n\n       xor\tecx , ecx\n       mov\tebx , eax\n       cmp\tedi , 0b0000h\n       jge\t??no_trailing\n       mov\tecx , 0b0000h\n       sub\tecx , edi \n       sub\tebx , ecx\n       rep\tmovsb\n??no_trailing:  \n       add\tedi , [ cpu_video_page ]\n       call\tVesa_Asm_Set_Win\t\t\t; set the window\n\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_dword\n       ret\n\n??in_range:\n\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_dword\n       ret\n\n??forward_loop_bytes:\n       lea\tebx , [ edi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       mov\tebx , eax\n       jl\t??in_range_bytes\n\n       xor\tecx , ecx\n       cmp\tedi , 0b0000h\n       jge\t??no_trailing_bytes\n       mov\tecx , 0b0000h\n       sub\tecx , edi \n       sub\tebx , ecx\n       rep\tmovsb\n??no_trailing_bytes:  \n       add\tedi , [ cpu_video_page ]\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n??in_range_bytes:\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_bytes\n       ret\n\nIF  TRANSP\n\n\n??forward_Blit_trans:\n\n\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\t\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n\n??forward_loop_trans:\n       mov\tecx , eax \n       jmp\t[ y1_pixel ]\n??forward_trans_line:\n       REPT\t32\t\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tesi\n\t    \tinc\tedi\n\tENDM\n    ??transp_reference:\n       dec\tecx \n       jge\t??forward_trans_line\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_trans\n       ret\nENDIF\n\n??real_out:\n       ret\n\n\n\tENDP\tVesa_Buffer_To_Page\nEND\n\n"
  },
  {
    "path": "WWFLAT32/SVGAPRIM/VTXTPRNT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**      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      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TXTPRNT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 17, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 17, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   VESA_Print -- Assembly VESA text print routine                        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \".\\gbuffer.inc\"\n\n;*=========================================================================*\n;* Extern the font pointer which is defined by the font class\t\t   *\n;*=========================================================================*\n\tGLOBAL\tFontPtr:DWORD\n\tGLOBAL\tColorXlat:BYTE\n\n;*=========================================================================*\n;* Define the necessary equates for structures and bounds checking\t   *\n;*=========================================================================*\n; The header of the font file looks like this:\n; \tUWORD\tFontLength;\t\t0\n; \tBYTE\tFontCompress;\t\t2\n;\tBYTE\tFontDataBlocks;\t\t3\n;\tUWORD\tInfoBlockOffset;\t4\n;\tUWORD\tOffsetBlockOffset;\t6\n;\tUWORD\tWidthBlockOffset;\t8\n;\tUWORD\tDataBlockOffset;\t10\n;\tUWORD\tHeightOffset;\t\t12\n; For this reason the following equates have these values:\nFONTINFOBLOCK\t\tEQU\t4\nFONTOFFSETBLOCK\t\tEQU\t6\nFONTWIDTHBLOCK\t\tEQU\t8\nFONTDATABLOCK\t\tEQU\t10\nFONTHEIGHTBLOCK\t\tEQU\t12\n\nFONTINFOMAXHEIGHT\tEQU\t4\nFONTINFOMAXWIDTH\tEQU\t5\n\n\nLOCALS ??\n;*=========================================================================*\n;* Define the color xlate table in the data segment\t\t\t   *\n;*=========================================================================*\n\n\tCODESEG\n\n\n;***************************************************************************\n;* VESA_PRINT -- Assembly VESA text print routine                          *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/17/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tVesa_Print C near\n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\tthis:DWORD\n\tARG\tstring:DWORD\t \n\tARG\tx_pixel:DWORD\n\tARG\ty_pixel:DWORD\n\tARG\tfcolor:DWORD\n\tARG\tbcolor:DWORD\n\t\t\n\tLOCAL\tinfoblock:DWORD\t\t; pointer to info block\n\tLOCAL\toffsetblock:DWORD\t; pointer to offset block  (UWORD *)\n\tLOCAL\twidthblock:DWORD\t; pointer to width block   (BYTE  *)\n\tLOCAL\theightblock:DWORD\t; pointer to height block  (UWORD *)\n\n\tLOCAL\tcurline:DWORD\t\t; pointer to first column of current row.\n\tlocal\tptr_string:dword\t; pointer to string\n\tLOCAL\tbufferwidth:DWORD    \t; width of buffer (vpwidth + Xadd)\n\tLOCAL\tnextdraw:DWORD\t\t; bufferwidth - width of cur character.\n\tLOCAL\tstartdraw:DWORD\t\t; where next character will start being drawn.\n\n\tLOCAL\tchar:DWORD\t\t; current character value.\t\n\n\tLOCAL\tmaxheight:BYTE\t\t; max height of characters in font.\n\tLOCAL\tbottomblank:BYTE\t; amount of empty space below current character.\n\tLOCAL\tcharheight:BYTE\t\t; true height of current character.\n\tLOCAL\tvpwidth:DWORD\n\tLOCAL\tvpheight:DWORD\n\tLOCAL\tremainder:DWORD\n\tLOCAL\tfullwidth:DWORD\n\tLOCAL\tcurrwidth:DWORD\n\n\n;-------------------------------- Where to draw -----------------------------------------------\n\t; Set up memory location to start drawing.\n\tmov  \tebx,[this]\t\t\t\t; get a pointer to dest\n\tmov\teax,[(GraphicViewPort ebx).GVPHeight]\t; get height of viewport\n\tmov\t[vpheight],eax\t\t\t\t; save off height of viewport\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\t; get width of viewport\n\tmov\t[vpwidth],eax\t\t\t\t; save it off for later\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\t; add in xadd for bytes_per_line\n\tmov\t[bufferwidth],eax     \t\t\t; save it off for later use.\n\n\tmul\t[y_pixel]\t\t\t\t; multiply rowsize * y_pixel start.\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get start of the viewport\n\tadd\tedi,eax\t\t\t\t\t; add y position to start of vp \n\tmov\t[curline],edi\t\t\t\t; save 0,y address for line feed stuff.\n\tadd\tedi,[x_pixel]\t\t\t\t; add to get starting column in starting row.\n\n\tmov\t[startdraw],edi\t\t\t\t; save it off.\n\n\n;-------------------------------- Create block pointers ----------------------------------------\n\t; Get the pointer to the font.\n\t; We could check for NULL but why waste the time.\n\t; It is up to programmer to make sure it is set.\n\tmov\tesi,[FontPtr]\t\t; Get the font pointer\n\tor\tesi,esi\n\tjz\t??done\n\n\t; Set up some pointers to the different memory blocks.\n\t; esi (FontPtr) is added to each to get the true address of each block.\n\t; Many registers are used for P5 optimizations.\n\t; ebx is used for InfoBlock which is then used in the next section.\n\tmovzx\teax,[WORD PTR esi+FONTOFFSETBLOCK]\t; get offset to offset block\n\tmovzx\tebx,[WORD PTR esi+FONTINFOBLOCK]      \t; get offset to info block (must be ebx for height test)\n\tmovzx\tecx,[WORD PTR esi+FONTWIDTHBLOCK] \t; get offset to width block\n\tmovzx\tedx,[WORD PTR esi+FONTHEIGHTBLOCK]\t; get offset to height block\n\n\tadd\teax,esi\t\t\t\t; add offset of FontPtr to offset block  \n\tadd\tebx,esi\t\t\t\t; add offset of FontPtr to info block \n\tadd\tecx,esi\t\t\t\t; add offset of FontPtr to width block\n\tadd\tedx,esi\t\t\t\t; add offset of FontPtr to height block\n\n\tmov\t[offsetblock],eax\t\t; save offset to offset block\n\tmov\t[infoblock],ebx\t\t\t; save offset to info block\n\tmov\t[widthblock],ecx   \t\t; save offset to width block\n\tmov\t[heightblock],edx\t\t; save offset to height block\n\n;------------------------------------------ Test for fit ----------------------------------------------\n\t; Test to make sure the height of the max character will fit on this line\n\t; and and not fall out of the viewport.\n\t; remember we set ebx to FONTINFOBLOCK above.\n\tmovzx\teax,[BYTE PTR ebx + FONTINFOMAXHEIGHT]; get the max height in font.\n\tmov\t[maxheight],al\t\t\t; save it for later use.\n\tadd\teax,[y_pixel]\t\t\t; add current y_value.\n\tcmp\teax,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??done\t\t\t; if so, we're outa here.\n\n\tmov\t[y_pixel],eax\t\t\t; save for next line feed. y value for next line.\n\n\tcld\t\t\t\t\t; Make sure we are always forward copying.\n\n;------------------------ Set palette foreground and background ----------------------------------\n\tmov\teax,[fcolor]\t\t; foreground color\n\tmov\t[ColorXlat+1],al\n\tmov\t[ColorXlat+16],al\n\n\tmov\teax,[bcolor]\t\t; background color\n\tmov\t[ColorXlat],al\n\n;-------------------------------------------------------------------------------------------------\n;----------------------------------------- Main loop ----------------------------------------------\n\t; Now we go into the main loop of reading each character in the string and doing\n\t; something with it.\n??next_char:\n\t; while (*string++)\n\txor\teax,eax\t\t\t\t; zero out since we will just load al.\t\n\tmov\tesi,[string]\t\t\t; get address on next character.\t\n\tlodsb\t\t\t\t\t; load the character into al.\n\ttest\teax,0FFH\t\t\t; test to see if character is a NULL\n\tjz\t??done\t\t\t\t; character is NULL, get outa here.\n\tmov\tedi,[startdraw]\t\t\t; Load the starting address.\n\n\tmov\t[string],esi\t\t\t; save index into string. (incremented by lodsb)\t\n\n\tcmp\teax,10\t\t\t\t; is the character a line feed?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\t\n\tcmp\teax,13\t\t\t\t; is the character a line feed?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\n\tmov\t[char],eax\t\t\t; save the character off for later reference.\n\tmov\tebx,eax\t\t\t\t; save it in ebx for later use also.\n\n\tadd\teax,[widthblock]\t\t; figure address of width of character.\n\tmov\tecx,[x_pixel]\t\t\t; get current x_pixel.\n\tmovzx\tedx,[BYTE PTR eax]\t \t; get the width of the character in dl.\n\tadd\tecx,edx\t\t\t\t; add width of char to current x_pixel.\n\tadd\t[startdraw],edx\t\t\t; save start draw for next character.\n\n\tcmp\tecx,[vpwidth]\t\t\t; is the pixel greater then the vp width?\n\tjg\t??force_line_feed\t\t; if so, force a line feed.\n\n\tmov\t[x_pixel],ecx\t\t\t; save value of start of next character.\n\tmov\tecx,[bufferwidth]\t\t; get amount to next y same x (one row down)\n\tsub\tecx,edx\t\t\t\t; take the current width off.\n\tmov\t[nextdraw],ecx\t\t\t; save it to add to edi when done with a row.\n\n\t; At this point we got the character. It is now time to find out specifics\n\t; about drawing the darn thing.\n\t; ebx = char so they can be used as an indexes.\n\t; edx = width of character for loop later.\n\n\t; get offset of data for character into esi.\n\tshl\tebx,1\t\t\t\t; mult by 2 to later use as a WORD index.\n\tmov\tesi,[offsetblock]\t\t; get pointer to begining of offset block.\n\tadd\tesi,ebx\t\t\t\t; index into offset block.\t\n\tmovzx\tesi,[WORD PTR esi]\t\t; get true offset into data block from FontPtr.\n\tadd\tesi,[FontPtr]\t\t\t; Now add FontPtr address to get true address.\n\n\t; Get top and bottom blank sizes and the true height of the character.\n\tadd\tebx,[heightblock]\t\t; point ebx to element in height array.\n\tmov\tal,[ebx+1]\t\t\t; load the data height into dl.\n\tmov\tcl,[ebx]\t\t\t; load the first data row into cl.\n\tmov\tbl,[maxheight]\t\t\t; get the max height of characters.\n\tmov\t[charheight],al\t\t\t; get number of rows with data.\n\tadd\tal,cl\t\t\t\t; add the two heights.\n\tsub\tbl,al\t\t\t\t; subract topblank + char height from maxheight.\n\tmov\t[bottomblank],bl\t\t; save off the number of blank rows on the bottom.\n\t; leaving this section:\n\t; dl is still the width of the character.\n\t; cl is the height of the top blank area.\n\n\tmov\tebx,OFFSET ColorXlat\t\t; setup ebx for xlat commands.\n\tmov\tdh,dl\t\t\t\t; save the width of the character to restore each loop.\n\tcall\tVesa_Asm_Set_Win\t\t; adjust edi & vesa page\n\n\tcmp\tcl,0\t\t\t\t; is there any blank rows on top?\n\tjz\t??draw_char\t\t\t; if not go and draw the real character.\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjnz\t??loop_top\t\t\t; if not go and write the color\n\n;----------------------------------------- skip Top blank area ----------------------------------------\n\t; this case, the top is transparrent, but we need to increase our dest pointer to correct row.\n\tmovzx\teax,cl\t\t\t\t; get number of rows into eax;\n\tmov\tecx,edx\t\t\t\t; save width since edx will be destroyed by mul.\n\tmul\t[bufferwidth]\t\t\t; multiply that by the width of the buffer.\n\tmov\tedx,ecx\t\t\t\t; restore the width\n\tadd\tedi,eax\t\t\t\t; update the pointer.\t\n\tcmp\tedi,0b0000h\t\t\t; have we gone over win edge\n\tjl\t??draw_char\t\t\t; if not keep writing to window\n        add\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\t\t; instead switch to next window\n\tjmp\tshort ??draw_char\t\t; now go draw the character.\n\n;----------------------------------------- fill Top blank area ----------------------------------------\n\n??loop_top:\n\tstosb\t\t\t\t\t; store the value\n\tcmp\tedi,0b0000h\t\t\t; have we gone over win edge\n\tjl\t??top_no_window_change\t\t; if not keep writing to window\n        add\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\t\t; instead switch to next window\n??top_no_window_change:\n\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_top\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\tcmp\tedi,0b0000h\t\t\t; have we gone over win edge\n\tjl\t??top2_no_window_change\t; if not keep writing to window\n        add\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\t\t; instead switch to next window\n\n??top2_no_window_change:\n\n\tdec\tcl\t\t\t\t; decrement or row count\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tjz\t??draw_char\t\t\t; we are done here, go draw the character.\n\tjmp\tshort ??loop_top\t\t; go back to top of loop.\n;----------------------------------------- Draw character ----------------------------------------------\n??draw_char:\n\tmovzx\tecx,[charheight]\t\t; get the height of character to count down rows.\n\ttest\tecx,ecx\t\t\t\t; is there any data? (blank would not have any)\n\tjz\t??next_char\t\t\t; if no data, go on to next character.\t\n\n\n??while_data:\n\tlodsb\t\t\t\t\t; get byte value from font data\n\tmov\tah,al\t\t\t\t; save hinibble\n\tand\teax,0F00FH\t       \t\t; mask of low nibble in al hi nibble in ah.\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiplo\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiplo:\n\tinc\tedi\n\tcmp\tedi,0b0000h\t\t\t; have we gone over win edge\n\tjl\t??lo_no_window_change\t\t; if not keep writing to window\n        add\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\t\t; instead switch to next window\n??lo_no_window_change:\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjz\tshort ??nextrow\t\t\t; check if done with width of char\n\n\tmov\tal,ah\t\t\t\t; restore to get\n\t; test the time difference between looking up in a large table when shr al,4 is not done as\n\t; compared to using only a 16 byte table when using the shr al,4\n\t;shr\tal,4\t\t\t\t; shift the hi nibble down to low nibble\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiphi\t\t\t; skip over write\n\tmov\t[edi],al\t\t\t; write it out\n??skiphi:\n\tinc\tedi\n\tcmp\tedi,0b0000h\t\t\t; have we gone over win edge\n\tjl\t??hi_no_window_change\t\t; if not keep writing to window\n        add\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\t\t; instead switch to next window\n??hi_no_window_change:\n\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\tshort ??while_data\t\t; check if done with width of char\n\n??nextrow:\n\tadd\tedi,[nextdraw]\t\t\t; go to next line.\n\tcmp\tedi,0b0000h\t\t\t; have we gone over win edge\n\tjl\t??next_row_no_window_change\t; if not keep writing to window\n        add\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\t\t; instead switch to next window\n??next_row_no_window_change:\n\tdec\tecx\t\t\t\t; decrement the number of rows to go\n\tmov\tdh,dl\t\t\t\t; restore our column count for row.\n\tjnz\t??while_data\t\t\t; more data for character.\n\n\t; Now it is time to setup for clearing out the bottom of the character.\n\tmovzx\tecx,[bottomblank]\t\t; get amount on bottom that is blank\n\tcmp\tecx,0\t\t\t\t; if there is no blank bottom...\n\tjz\t??next_char\t\t\t; then skip to go to next character\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjz\t??next_char\t\t\t; skip the top black section to let the background through\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\n;----------------------------------------- Blank below character -----------------------------------\n??loop_bottom:\n\tstosb\t\t\t\t\t; store the value\n\tcmp\tedi,0b0000h\t\t\t; have we gone over win edge\n\tjl\t??bottom_no_window_change\t; if not keep writing to window\n        add\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\t\t; instead switch to next window\n??bottom_no_window_change:\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_bottom\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\tcmp\tedi,0b0000h\t\t\t; have we gone over win edge\n\tjl\t??bottom2_no_window_change\t; if not keep writing to window\n        add\tedi , [ cpu_video_page ]\n\tcall\tVesa_Asm_Set_Win\t\t; instead switch to next window\n??bottom2_no_window_change:\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tdec\tcl\t\t\t\t; decrement or row count\n\tjz\t??next_char\t\t\t; we are done here, go to the next character.\n\tjmp\tshort ??loop_bottom\t\t; go back to top of loop.\n\n;----------------------------------- end of next_char (main) loop ------------------------------------\n;-------------------------------------------------------------------------------------------------\n\n;----------------------------------- special case line feeds ----------------------------------------\n; JRJ 05/01/95 This is the problem However made this change introduced\n; a error in the code, this function is not supposed to handle\n; Text wrapping\n??force_line_feed:\t\n\t; decrement pointer *string so that it will be back at same character\n\t; when it goes through the loop.\n\tdec\t[dword ptr string]\t\t  ; overflow by one charater\n\tjmp\t??done\n\n\n??line_feed:\n\tmov\tedx,[y_pixel]\t\t\t; get the current y pixel value.\n\tmovzx\tecx,[maxheight]\t\t\t; get max height for later use.\n\tadd\tedx,ecx\t\t\t\t; add max height to y_pixel\n\tcmp\tedx,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??done\t\t\t; if so, we are outa here.\n\n\tmov\teax,[bufferwidth]      \t\t; get bytes to next line.\n\tmov\tedi,[curline]\t\t\t; get start of current line.\t\n\tmul\tecx\t\t\t\t; mult max height * next line.\t\n\n\tadd\tedi,eax\t\t\t\t; add adjustment to current line.\n\tadd\t[y_pixel],ecx\t\t\t; increment to our next y position.\n\tmov\t[curline],edi\t\t\t; save it off for next line_feed.\n\tmov\t[startdraw],edi\t\t\t; save it off so we know where to draw next char.w\n\n\tmov\t[x_pixel],0\t\t\t; zero out x_pixel\n\n\tjmp\t??next_char\n??done:\n\tmov\teax,[string]\t\t\t; return the number of charaters \n\tsub\teax,[ptr_string]\t\t; printed\n\tret\t\t\t\t\t\n\t\t\n\tENDP\tVesa_Print\n\nEND\n"
  },
  {
    "path": "WWFLAT32/SVGAPRIM/VVBLIT.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : BITBLIT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : December 13, 1994   [PWG]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\nTRANSP\tequ  0 \n\nPOOLSIZE equ\t8000\n\nCODESEG\n\n\tPROC\tVesa_Blit_To_Vesa C near \n\tUSES\tebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG    \tthis        :DWORD\t\t; this is a member function\n\tARG\tdest        :DWORD\t\t; what are we blitting to\n\tARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\tARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\tARG\tdest_x0     :dword\n\tARG\tdest_y0     :dword\n\tARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\tARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\tARG\ttrans       :DWORD\t\t\t; do we deal with transparents?\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tLOCAL\tdest_x1 : dword\n\tLOCAL\tdest_y1 : dword\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_ajust_width:DWORD\n        LOCAL\tsource_area :  dword\n        LOCAL\tdest_area :  dword\n\tlocal\ttotal_lines  : dword\n\tlocal\tcount_dy     : dword\n\tlocal\tmem_page     : dword\n\tlocal   vesa_page    : dword\n\tlocal\tmem_pool     : byte : POOLSIZE\n\n; Clip Source Rectangle against source Window boundaries.\n\tmov  \tesi , [ this ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??clip_against_dest\n\n\ttest\tcl , 1000b\n\tjz\t??scr_left_ok\n\tmov\t[ x_pixel ] , 0\n\n??scr_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\t[ y_pixel ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??clip_against_dest\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n\n; Clip Source Rectangle against destination Window boundaries.\n??clip_against_dest:\n\n\tmov\teax , [ dest_x0 ]\n\tmov\tebx , [ dest_y0 ]\n\tsub\teax , [ x_pixel ]\n\tsub\tebx , [ y_pixel ]\n\tadd\teax , [ x1_pixel ]\n\tadd\tebx , [ y1_pixel ]\n\tmov\t[ dest_x1 ] , eax\n\tmov\t[ dest_y1 ] , ebx\n\n\tmov  \tesi , [ dest ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ dest_x0 ]\n\tmov\tebx , [ dest_x1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\teax , [ dest_y0 ]\n\tmov\tebx , [ dest_y1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_blit\n\n\ttest\tcl , 1000b\n\tjz\t??dest_left_ok\n\tmov\teax , [ dest_x0 ]\n\tmov\t[ dest_x0 ] , 0\n\tsub\t[ x_pixel ] , eax\n\n??dest_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dest_bottom_ok\n\tmov\teax , [ dest_y0 ]\n\tmov\t[ dest_y0 ] , 0\n\tsub\t[ y_pixel ] , eax\n\n\n??dest_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??dest_right_ok\n\tmov\tebx , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ dest_x1 ]\n\tmov\t[ dest_x1 ] , ebx\n\tsub\teax , ebx\n\tsub\t[ x1_pixel ] , eax\n\n??dest_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\tmov\tebx , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\teax , [ dest_y1 ]\n\tmov\t[ dest_y1 ] , ebx\n\tsub\teax , ebx\n\tsub\t[ y1_pixel ] , eax\n\n??do_blit:\n\n       cld\t\n       mov\tebx , [ this ]\n       mov\tesi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\tecx , eax\n       mul\t[ y_pixel ]\n       add\tesi , [ x_pixel ]\n       mov\t[ source_area ] , ecx\n       add\tesi , eax\n\n       add\tecx , [ x_pixel ]\n       sub\tecx , [ x1_pixel ]\n       mov\t[ scr_ajust_width ] , ecx\n\n       mov\tebx , [ dest ]\n       mov\tedi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\tecx , eax\n       mul\t[ dest_y0 ]\n       add\tedi , [ dest_x0 ]\n       mov\t[ dest_area ] , ecx\n       add\tedi , eax\n\n       mov\teax , [ dest_x1 ]\n       sub\teax , [ dest_x0 ]\n       jz\t??real_out\n       sub\tecx , eax\n       mov\t[ dest_ajust_width ] , ecx\n\n       mov\tedx , [ dest_y1 ]\n       sub\tedx , [ dest_y0 ]\n       jz\t??real_out\n\n       push\teax\n       mov\t[ mem_page ] , 0\n       mov\t[ vesa_page ] , 0\n\n       mov\t[ total_lines ] , edx\t\n       mov\teax , POOLSIZE\n       xor\tedx , edx\n       idiv\t[ dword ptr esp ]\n       mov\t[ count_dy ] , eax\n       pop\teax\n\n; **************************************************************************\n; check direction of motions\n       cmp\tesi , edi\n       jl\t??backupward_blit\n\n       ret\n\n;***********************************************************************\n; Backupward blit\n\n??back_mem_loop:\n       push\tedi\n       lea\tedi , [ mem_pool ]\n       mov\tedx , [ count_dy ]\n       call\t??vesa_to_memory\n       pop\tedi\n\n       push\tesi\n       lea\tesi , [ mem_pool ]\n       mov\tedx , [ count_dy ]\n       call\t??memory_to_vesa\n       pop\tesi\n\n??backupward_blit:\n       mov\tedx , [ total_lines ]\n       sub\tedx , [ count_dy ]\n       mov\t[ total_lines ]\t, edx\n       jg\t??back_mem_loop\n\n       add\tedx , [ count_dy ]\n       push\tedi\n       push\tedx\n       lea\tedi , [ mem_pool ]\n       call\t??vesa_to_memory\n       pop\tedx\n       pop\tedi\n\n       push\tesi\n       lea\tesi , [ mem_pool ]\n       call\t??memory_to_vesa\n       pop\tesi\n       ret\n\n\n\n??real_out:\n       ret\n\n\n\n\n; ********************************************************************       \n; Move Vesa video page to memory buffer\n\n??vesa_to_memory:\n\n       xchg\tedi , esi\n       add\tedi , [ mem_page ]\n       call\tVesa_Asm_Set_Win  \n       xchg\tedi , esi\n\nIF  TRANSP\n       test\t[ trans ] , 1\n       jnz\t??tomem_forward_Blit_trans\nENDIF\n\n\n; the inner loop is so efficient that \n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10        \n       jl\t??tomem_forward_loop_bytes\n\n??tomem_forward_loop_dword:\n\n       lea\tebx , [ esi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??tomem_in_range\n\n       xor\tecx , ecx\n       mov\tebx , eax\n       cmp\tesi , 0b0000h\n       jge\t??tomem_no_trailing\n       mov\tecx , 0b0000h\n       sub\tecx , esi \n       sub\tebx , ecx\n       rep\tmovsb\n??tomem_no_trailing:  \n       add\tesi , [ cpu_video_page ]\n       xchg\tedi , esi\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n       xchg\tedi , esi\n\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??tomem_forward_loop_dword\n       mov\tedx , [ cpu_video_page ] \n       mov\t[ mem_page ] , edx \t\t\t\n       retn\n\n??tomem_in_range:\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       dec\tedx \n       jnz\t??tomem_forward_loop_dword\n       mov\tedx , [ cpu_video_page ] \n       mov\t[ mem_page ] , edx \t\t\t\n       retn\n\n??tomem_forward_loop_bytes:\n       lea\tebx , [ esi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       mov\tebx , eax\n       jl\t??tomem_in_range_bytes\n\n       xor\tecx , ecx\n       cmp\tesi , 0b0000h\n       jge\t??tomem_no_trailing_bytes\n       mov\tecx , 0b0000h\n       sub\tecx , esi \n       sub\tebx , ecx\n       rep\tmovsb\n??tomem_no_trailing_bytes:  \n       add\tesi , [ cpu_video_page ]\n       xchg\tedi , esi\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n       xchg\tedi , esi\n??tomem_in_range_bytes:\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??tomem_forward_loop_bytes\n       mov\tedx , [ cpu_video_page ] \n       mov\t[ mem_page ] , edx \t\t\t\n       retn\n\nIF  TRANSP\n??tomem_forward_Blit_trans:\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\t\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??tomem_transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n??tomem_forward_loop_trans:\n       mov\tecx , eax \n       jmp\t[ y1_pixel ]\n??tomem_forward_trans_line:\n       REPT\t32\t\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\tinc\tesi\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tedi\n\tENDM\n    ??tomem_transp_reference:\n       dec\tecx \n       jge\t??tomem_forward_trans_line\n       add\tesi , [ scr_ajust_width ]\n       dec\tedx \n       jnz\t??tomem_forward_loop_trans\n       mov\tedx , [ cpu_video_page ] \n       mov\t[ mem_page ] , edx \t\t\t\n       retn\nENDIF\n\n\n\n\n\n;*************************************************************************\n; copy from memory to vesa page\n\n??memory_to_vesa:\n       add\tedi , [ vesa_page ]\n       Call\tVesa_Asm_Set_Win  \n\nIF TRANSP\n       test\t[ trans ] , 1\n       jnz\t??tovesa_forward_Blit_trans\nENDIF\n\n\n; the inner loop is so efficient that \n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10        \n       jl\t??tovesa_forward_loop_bytes\n\n??tovesa_forward_loop_dword:\n\n       lea\tebx , [ edi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??tovesa_in_range\n\n       xor\tecx , ecx\n       cmp\tedi , 0b0000h\n       mov\tebx , eax\n       jge\t??tovesa_no_trailing\n       mov\tecx , 0b0000h\n       sub\tecx , edi \n       sub\tebx , ecx\n       rep\tmovsb\n??tovesa_no_trailing:  \n       add\tedi , [ cpu_video_page ]\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??tovesa_forward_loop_dword\n       mov\tedx , [ cpu_video_page ] \n       mov\t[ vesa_page ] , edx \n       retn\n\n??tovesa_in_range:\n\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??tovesa_forward_loop_dword\n       mov\tedx , [ cpu_video_page ] \n       mov\t[ vesa_page ] , edx \n       retn\n\n??tovesa_forward_loop_bytes:\n       lea\tebx , [ edi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       mov\tebx , eax\n       jl\t??tovesa_in_range_bytes\n\n       xor\tecx , ecx\n       cmp\tedi , 0b0000h\n       jge\t??tovesa_no_trailing_bytes\n       mov\tecx , 0b0000h\n       sub\tecx , edi \n       sub\tebx , ecx\n       rep\tmovsb\n??tovesa_no_trailing_bytes:  \n       add\tedi , [ cpu_video_page ]\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n??tovesa_in_range_bytes:\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??tovesa_forward_loop_bytes\n       mov\tedx , [ cpu_video_page ] \n       mov\t[ vesa_page ] , edx \n       retn\n\nIF  TRANSP\n\n\n??tovesa_forward_Blit_trans:\n\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\t\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??tovesa_transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n??tovesa_forward_loop_trans:\n       mov\tecx , eax \n       jmp\t[ y1_pixel ]\n??tovesa_forward_trans_line:\n       REPT\t32\t\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tesi\n\t    \tinc\tedi\n\tENDM\n    ??tovesa_transp_reference:\n       dec\tecx \n       jge\t??tovesa_forward_trans_line\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??tovesa_forward_loop_trans\n       mov\tedx , [ cpu_video_page ] \n       mov\t[ vesa_page ] , edx \n       retn\nENDIF\n\n\nENDP\tVesa_Blit_To_Vesa\n\n\n\nEND\n"
  },
  {
    "path": "WWFLAT32/SVGAPRIM/VVETOLB.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : BITBLIT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : June 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : December 13, 1994   [PWG]                *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\nINCLUDE \"svgaprim.inc\"\nINCLUDE \"gbuffer.inc\"\n\n\nTRANSP   equ 0\n\nCODESEG\n\n\n;***************************************************************************\n;* GVC::BLIT -- Copies a buffer to a graphic page non-linearly             *\n;*                                                                         *\n;* NOTE:\t\tAll coordinate values are expressed in pixels      *\n;*                                                                         *\n;* INPUT:\tVirtualViewPortClass *dest - Virtual View Port to copy to  *\n;*\t\tWORD src_x\t     \t   - Src x position to copy from   *\n;*\t\tWORD src_y\t\t   - Src y position to copy from   *\n;*\t\tWORD dst_x\t\t   - Dest x position to copy to\t   *\n;*\t\tWORD dst_y\t\t   - Dest y position to copy to\t   *\n;*\t\tWORD w\t\t\t   - Width of region to copy\t   *\n;*\t\tWORD h\t\t\t   - Height of region to copy\t   *\n;*                                                                         *\n;* OUTPUT:     none                                                        *\n;*                                                                         *\n;* WARNINGS:   Coordinates and dimensions will be adjusted if they exceed  *\n;*\t       the boundaries.  In the event that no adjustment is \t   *\n;*\t       possible this routine will abort.\t\t\t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   05/11/1994 PWG : Created.                                             *\n;*   08/05/1994 PWG : Fixed clipping problem                               *\n;*=========================================================================*\n\tPROC\tVesa_Blit_To_Linear C near \n\tUSES\tebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\tARG    \tthis        :DWORD\t\t; this is a member function\n\tARG\tdest        :DWORD\t\t; what are we blitting to\n\tARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\tARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\tARG\tdest_x0     :dword\n\tARG\tdest_y0     :dword\n\tARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\tARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\tARG\ttrans       :DWORD\t\t; do we deal with transparents?\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL \tx1_pixel :dword\n\tLOCAL\ty1_pixel :dword\n\tLOCAL\tdest_x1 : dword\n\tLOCAL\tdest_y1 : dword\n\tLOCAL\tscr_ajust_width:DWORD\n\tLOCAL\tdest_ajust_width:DWORD\n        LOCAL\tsource_area :  dword\n        LOCAL\tdest_area :  dword\n\n; Clip Source Rectangle against source Window boundaries.\n\tmov  \tesi , [ this ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??clip_against_dest\n\n\ttest\tcl , 1000b\n\tjz\t??scr_left_ok\n\tmov\t[ x_pixel ] , 0\n\n??scr_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??scr_bottom_ok\n\tmov\t[ y_pixel ] , 0\n\n??scr_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??scr_right_ok\n\tmov\teax , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n??scr_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??clip_against_dest\n\tmov\teax , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\n\n; Clip Source Rectangle against destination Window boundaries.\n??clip_against_dest:\n\n\tmov\teax , [ dest_x0 ]\n\tmov\tebx , [ dest_y0 ]\n\tsub\teax , [ x_pixel ]\n\tsub\tebx , [ y_pixel ]\n\tadd\teax , [ x1_pixel ]\n\tadd\tebx , [ y1_pixel ]\n\tmov\t[ dest_x1 ] , eax\n\tmov\t[ dest_y1 ] , ebx\n\n\tmov  \tesi , [ dest ]\t    ; get ptr to src\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ dest_x0 ]\n\tmov\tebx , [ dest_x1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register\n\tmov\teax , [ dest_y0 ]\n\tmov\tebx , [ dest_y1 ]\n\tshld\tecx , eax , 1\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\t??real_out\n\tor\tal , dl\n\tjz\t??do_blit\n\n\ttest\tcl , 1000b\n\tjz\t??dest_left_ok\n\tmov\teax , [ dest_x0 ]\n\tmov\t[ dest_x0 ] , 0\n\tsub\t[ x_pixel ] , eax\n\n??dest_left_ok:\n\ttest\tcl , 0010b\n\tjz\t??dest_bottom_ok\n\tmov\teax , [ dest_y0 ]\n\tmov\t[ dest_y0 ] , 0\n\tsub\t[ y_pixel ] , eax\n\n\n??dest_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\t??dest_right_ok\n\tmov\tebx , [ (VideoViewPort esi) . VIVPWidth ]  ; get width into register\n\tmov\teax , [ dest_x1 ]\n\tmov\t[ dest_x1 ] , ebx\n\tsub\teax , ebx\n\tsub\t[ x1_pixel ] , eax\n\n??dest_right_ok:\n\ttest\tdl , 0001b\n\tjz\t??do_blit\n\tmov\tebx , [ (VideoViewPort esi) . VIVPHeight ]  ; get width into register\n\tmov\teax , [ dest_y1 ]\n\tmov\t[ dest_y1 ] , ebx\n\tsub\teax , ebx\n\tsub\t[ y1_pixel ] , eax\n\n??do_blit:\n\n       cld\t\n       mov\tebx , [ this ]\n       mov\tedi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\tecx , eax\n       mul\t[ y_pixel ]\n       add\tedi , [ x_pixel ]\n       mov\t[ source_area ] , ecx\n       add\tedi , eax\n       call\tVesa_Asm_Set_Win\t\t\t; set the window\n       mov\tesi , edi\n\n       add\tecx , [ x_pixel ]\n       sub\tecx , [ x1_pixel ]\n       mov\t[ scr_ajust_width ] , ecx\n\n       mov\tebx , [ dest ]\n       mov\tedi , [ (VideoViewPort ebx) . VIVPOffset ]\n       mov\teax , [ (VideoViewPort ebx) . VIVPXAdd ]\n       add\teax , [ (VideoViewPort ebx) . VIVPWidth ]\n       mov\tecx , eax\n       mul\t[ dest_y0 ]\n       add\tedi , [ dest_x0 ]\n       mov\t[ dest_area ] , ecx\n       add\tedi , eax\n\n       mov\teax , [ dest_x1 ]\n       sub\teax , [ dest_x0 ]\n       jz\t??real_out\n       sub\tecx , eax\n       mov\t[ dest_ajust_width ] , ecx\n\n       mov\tedx , [ dest_y1 ]\n       sub\tedx , [ dest_y0 ]\n       jz\t??real_out\n\n; ********************************************************************       \n; Forward bitblit only\n\nIF TRANSP\n       test\t[ trans ] , 1\n       jnz\t??forward_Blit_trans\nENDIF\n\n\n; the inner loop is so efficient that \n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n       cmp\teax , 10        \n       jl\t??forward_loop_bytes\n\n??forward_loop_dword:\n       lea\tebx , [ esi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       jl\t??in_range\n\n       xor\tecx , ecx\n       mov\tebx , eax\n       cmp\tesi , 0b0000h\n       jge\t??no_trailing\n       mov\tecx , 0b0000h\n       sub\tecx , esi \n       sub\tebx , ecx\n       rep\tmovsb\n??no_trailing:  \n       add\tesi , [ cpu_video_page ]\n       xchg\tedi , esi\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n       xchg\tedi , esi\n\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_dword\n       ret\n\n??in_range:\n       mov\tecx , edi\n       mov\tebx , eax\n       neg\tecx\n       and\tecx , 3\n       sub\tebx , ecx\n       rep\tmovsb\n       mov\tecx , ebx\n       shr\tecx , 2\n       rep\tmovsd\n       mov\tecx , ebx\n       and\tecx , 3\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_dword\n       ret\n\n??forward_loop_bytes:\n       lea\tebx , [ esi + eax ]\n       add\tebx , [ cpu_video_page ]\n       cmp\tebx , [ cpu_page_limit ]\n       mov\tebx , eax\n       jl\t??in_range_bytes\n\n       xor\tecx , ecx\n       cmp\tesi , 0b0000h\n       jge\t??no_trailing_bytes\n       mov\tecx , 0b0000h\n       sub\tecx , esi \n       sub\tebx , ecx\n       rep\tmovsb\n??no_trailing_bytes:  \n       add\tesi , [ cpu_video_page ]\n       xchg\tedi , esi\n       Call\tVesa_Asm_Set_Win\t\t\t; set the window\n       xchg\tedi , esi\n??in_range_bytes:\n       mov\tecx , ebx\n       rep\tmovsb\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx\t\t\t\t\t; decrement the height\n       jnz\t??forward_loop_bytes\n       ret\n\nIF TRANSP\n\n??forward_Blit_trans:\n       mov\tecx , eax\n       and\tecx , 01fh\n       lea\tecx , [ ecx + ecx * 4 ]\t\n       neg\tecx\n       shr\teax , 5\n       lea\tecx , [ ??transp_reference + ecx * 2 ]\n       mov\t[ y1_pixel ] , ecx\n\n??forward_loop_trans:\n       mov\tecx , eax \n       jmp\t[ y1_pixel ]\n??forward_trans_line:\n       REPT\t32\t\n       local\ttransp_pixel\n       \t\tmov\tbl , [ esi ]\n       \t\ttest\tbl , bl\n       \t\tjz\ttransp_pixel\n       \t\tmov\t[ edi ] , bl\n    \t    transp_pixel:\n       \t\tinc\tesi\n\t    \tinc\tedi\n\tENDM\n    ??transp_reference:\n       dec\tecx \n       jge\t??forward_trans_line\n       add\tesi , [ scr_ajust_width ]\n       add\tedi , [ dest_ajust_width ]\n       dec\tedx \n       jnz\t??forward_loop_trans\n       ret\nENDIF\n\n??real_out:\n       ret\n\n\nENDP\tVesa_Blit_To_Linear\n\n\nEND\n"
  },
  {
    "path": "WWFLAT32/SVGAPRIM/VVETOSCL.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Testing memory.                          *\n *                                                                         *\n *                    File Name : TEST.CPP                                 *\n *                                                                         *\n *                   Programmer : Julio Jerez                              *\n *                                                                         *\n *                   Start Date : Feb 13, 1995                             *\n *                                                                         *\n *                                                                         *\n *-------------------------------------------------------------------------*\n*/\n#include <mcgaprim.h>\n#include <gbuffer.h>\n#include <vbuffer.h>\n\nint Vesa_Scale_To_Linear ( void * scr,  void * dst, \n\t\t\t\t\t\t\t\t\tint src_x  , int src_y  , int dst_x , int dst_y , \n\t\t\t\t\t\t\t\t\tint src_wd , int src_hg , int dst_wd, int dst_hg, \n\t\t\t\t\t\t\t\t\tBOOL trans , char * remap )\n{\n  int\t   area ;\n  int    width , height ;\n  char * temp ;\n\n  VideoViewPortClass * scr1 = ( VideoViewPortClass * ) scr ;\n\n  width  = src_wd - src_x ;\n  height = src_hg - src_y ;\n  area = width * height ;\n  temp = ( char * ) malloc ( area ) ;\n  if ( ! temp ) return 0 ;\n\n  scr1 -> To_Buffer ( 0, 0, width , height , temp, area );\n  GraphicBufferClass tempbuffer ( area , width , height , temp ) ;\n\n  Linear_Scale_To_Linear ( & tempbuffer , dst , \n  \t\t\t\t\t\t\t\t\t  0 , 0 , dst_x , dst_y ,\n  \t\t\t\t\t\t\t\t\t  width , height , dst_wd , dst_hg ,\n\t\t\t\t\t\t\t\t\t  trans , remap ) ;\n\n  free ( temp ) ;\n  return 0 ;\n}\n"
  },
  {
    "path": "WWFLAT32/TILE/ICONSET.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library                                  *\n *                                                                         *\n *                    File Name : ICONSET.C                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : June 9, 1991                             *\n *                                                                         *\n *                  Last Update : September 15, 1993   [JLB]               *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Load_Icon_Set -- Loads an icons set and initializes it.               *\n *   Free_Icon_Set -- Frees allocations made by Load_Icon_Set().           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n//#include\t\"function.h\"\n#include\t<dos.h>\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<mem.h>\n#include\t<wwstd.h>\n#include\t<file.h>\n#include\t<iff.h>\n\nunsigned long Misc;\n\nvoid * cdecl Load_Icon_Set(char const *filename, void *iconsetptr, long buffsize);\nvoid cdecl Free_Icon_Set(void const *iconset);\nlong cdecl Get_Icon_Set_Size(void const *iconset);\nint cdecl Get_Icon_Set_Width(void const *iconset);\nint cdecl Get_Icon_Set_Height(void const *iconset);\nvoid * cdecl Get_Icon_Set_Icondata(void const *iconset);\nvoid * cdecl Get_Icon_Set_Trans(void const *iconset);\nvoid * cdecl Get_Icon_Set_Remapdata(void const *iconset);\nvoid * cdecl Get_Icon_Set_Palettedata(void const *iconset);\nint cdecl Get_Icon_Set_Count(void const *iconset);\nvoid * cdecl Get_Icon_Set_Map(void const *iconset);\n\n\n//#define\tICON_PALETTE_BYTES\t16\n//#define\tICON_MAX\t\t\t\t\t256\n\n/***************************************************************************\n**\tThe terrain is rendered by using icons.  These are the buffers that hold\n**\tthe icon data, remap tables, and remap index arrays.\n*/\n//PRIVATE char *IconPalette = NULL;\t\t// MCGA only.\n//PRIVATE char *IconRemap = NULL;\t\t\t// MCGA only.\n\n#define\tFORM_RPAL\tMAKE_ID('R','P','A','L')\n#define\tFORM_RTBL\tMAKE_ID('R','T','B','L')\n#define\tFORM_SSET\tMAKE_ID('S','S','E','T')\n#define\tFORM_SINF\tMAKE_ID('S','I','N','F')\n#define\tFORM_ICON\tMAKE_ID('I','C','O','N')\n#define\tFORM_TRNS\tMAKE_ID('T','R','N','S')\n#define\tFORM_MAP\t\tMAKE_ID('M','A','P',' ')\n\n/*\n** This is the control structure at the start of a loaded icon set.  It must match\n** the structure in WWLIB.I!  This structure MUST be a multiple of 16 bytes long.\n*/\ntypedef struct {\n\tshort\tWidth;\t\t\t// Width of icons (pixels).\n\tshort\tHeight;\t\t\t// Height of icons (pixels).\n\tshort\tCount;\t\t\t// Number of (logical) icons in this set.\n//\tBOOL\tAllocated;\t\t// Was this iconset allocated?\n\tshort\tAllocated;\t\t// Was this iconset allocated?\n\tlong\tSize;\t\t\t\t// Size of entire iconset memory block.\n\tlong\tIcons;\t\t\t// Offset from buffer start to icon data.\n\tlong\tPalettes;\t\t// Offset from buffer start to palette data.\n\tlong\tRemaps;\t\t\t// Offset from buffer start to remap index data.\n\tlong\tTransFlag;\t\t// Offset for transparency flag table.\n\tlong\tColorMap;\n\tlong\tMap;\t\t\t\t// Icon map offset (if present).\n} IControl_Type;\n\n\n/***************************************************************************\n * LOAD_ICON_SET -- Loads an icons set and initializes it.                 *\n *                                                                         *\n *    This routine will load an IFF icon set from disk.  It handles all    *\n *    of the necessary allocations.                                        *\n *                                                                         *\n * INPUT:   filename -- Name of the icon file.                             *\n *                                                                         *\n *          buffer   -- Pointer to paragraph aligned buffer to hold data.  *\n *                                                                         *\n *          size     -- Size of the buffer (in bytes).                     *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   In EEGA mode the iconset buffer will be free because the    *\n *             icons will have been transferred to card ram.               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1991 JLB : Created.                                             *\n *   07/01/1991 JLB : Determines icon size from file.                      *\n *   07/15/1991 JLB : Load and uncompress onto the same buffer.            *\n *   09/15/1993 JLB : Added EMS support.                                   *\n *=========================================================================*/\nvoid * cdecl Load_Icon_Set(char const *filename, void *iconsetptr, long buffsize)\n{\n\tint\tfh;\t\t\t\t// File handle of iconset.\n\tint\tbytespericon;\t// The number of bytes per icon.\n\tunsigned long\ticons=0;\t\t\t// Number of icons loaded.\n\tunsigned long\tsize;\t\t\t\t// Size of the icon chunk (raw).\n\n\tunsigned long\ttranssize;\n\tvoid\t*transptr=NULL;\n\n\tunsigned long\tmapsize;\t\t\t\t// Icon map chunk size.\n\tvoid\t*mapptr=NULL;\t\t// Icon map pointer.\n\tvoid\t*returnptr=NULL;\t// Iconset pointer returned by routine.\n\tBOOL\tallocated=FALSE;\t// Was the iconset block allocated?\n\tIControl_Type\t*idata=NULL;\t// Icon data loaded.\n\tlong\tid;\t\t\t\t// ID of file openned.\n\tstruct {\n\t\tchar\tWidth;\t\t// Width of icon in bytes.\n\t\tchar\tHeight;\t\t// Height of icon in bytes.\n\t\tchar\tFormat;\t\t// Graphic mode.\n\t\t\t\t\t\t\t\t//lint -esym(754,Format)\n\t\tchar\tBitplanes;\t// Number of bitplanes per icon.\n\t} sinf;\n\n\t/*\n\t**\tOpen the icon set for loading.  If it is not a legal icon set\n\t**\tdata file, then abort.\n\t*/\n\tfh = Open_Iff_File(filename);\n\tif (fh != ERROR) {\n\t\tRead_File(fh, &id, sizeof(long));\n\t\tif (id == FORM_ICON) {\n\t\t\n\t\t\t/*\n\t\t\t**\tDetermine the size of the icons and set up the graphic\n\t\t\t**\tsystem accordingly.  Also get the sizes of the various\n\t\t\t**\tdata blocks that have to be loaded.\n\t\t\t*/\n\t\t\tRead_Iff_Chunk(fh, FORM_SINF, &sinf, sizeof(sinf));\n\t\t\tbytespericon = ((((int)sinf.Width)<<3)*(((int)sinf.Height)<<3)*(int)sinf.Bitplanes)>>3;\n\n\t\t\tsize = Get_Iff_Chunk_Size(fh,FORM_SSET);\n\t\t\t\ttranssize = Get_Iff_Chunk_Size(fh, FORM_TRNS);\n\t\t\tmapsize = Get_Iff_Chunk_Size(fh, FORM_MAP);\n\t\t\n\t\t\t/*\n\t\t\t**\tAllocate the icon buffer if one isn't provided.  First try EMS and\n\t\t\t**\tthen try conventional RAM.\n\t\t\t*/\n\t\t\tallocated = FALSE;\n\t\t\tif (!iconsetptr) {\n\t\t\t\t\tbuffsize = size + transsize + mapsize + sizeof(IControl_Type);\n\n\t\t\t\tMisc = buffsize;\n\t\t\t\ticonsetptr = Alloc(buffsize, MEM_NORMAL);\n\t\t\t\tallocated = (iconsetptr != NULL);\n\t\t\t}\n\n\t\t\tif (iconsetptr && (size+transsize+mapsize+sizeof(IControl_Type)) <= buffsize) {\n\n\t\t\t\tidata = (IControl_Type *)iconsetptr;\n\n\t\t\t\tmemset(idata, 0, sizeof(IControl_Type));\n\n\t\t\t\t/*\n\t\t\t\t**\tInitialize the iconset header structure.\n\t\t\t\t*/\n\t\t\t\tidata->Width = sinf.Width<<3;\n\t\t\t\tidata->Height = sinf.Height<<3;\n\t\t\t\tidata->Allocated = allocated;\n\t\t\t\tidata->Icons = sizeof(IControl_Type);\n\t\t\t\tidata->Map = idata->Icons + size;\n\t\t\t\t\tidata->TransFlag = idata->Map + mapsize;\n\t\t\t\tidata->Size = buffsize;\n\n\t\t\t\t\t{\n\t\t\t\t\t\tlong\tval;\n\n\t\t\t\t\t\tval = Read_Iff_Chunk(fh, FORM_SSET, Add_Long_To_Pointer(iconsetptr, sizeof(IControl_Type)), size);\n\t\t\t\t\t\ticons = (int)(val/(long)bytespericon);\n\t\t\t\t\t\tidata = (IControl_Type *)iconsetptr;\t\t\t\t\n\t\t\t\t\t}\n\n\t\t\t\tif (mapsize) {\n\t\t\t\t\ticons = mapsize;\n\t\t\t\t}\n\t\t\t\tidata->Count = (short)icons;\n\n\t\t\t\t/*\n\t\t\t\t**\tLimit buffer to only the size needed.  This is done AFTER loading of the\n\t\t\t\t**\traw icon data because it might have been compressed and thus need any\n\t\t\t\t**\textra space to perform an overlapped decompression.\n\t\t\t\t*/\n\t\t\t\t\tif (buffsize > size + transsize + mapsize + sizeof(IControl_Type)) {\n\t\t\t\t\t\tbuffsize = size + transsize + mapsize + sizeof(IControl_Type);\n\t\t\t\t\t}\n\n\t\t\t\t\ttransptr = Add_Long_To_Pointer(iconsetptr, idata->TransFlag);\n\t\t\t\t\tRead_Iff_Chunk(fh, FORM_TRNS, transptr, transsize);\n\t\t\t\t\tidata = (IControl_Type *)iconsetptr;\t\t\t\t\n\n\t\t\t\tmapptr = Add_Long_To_Pointer(iconsetptr, idata->Map);\n\t\t\t\tRead_Iff_Chunk(fh, FORM_MAP, mapptr, mapsize);\n\n\t\t\t\t/*\n\t\t\t\t**\tLet the graphic overlay know of the icon data.  This could involve\n\t\t\t\t**\ttranslation and other data manipulations.\n\t\t\t\t*/\n\t\t\t\t//Init_Stamps(iconsetptr);\n\n\t\t\t\treturnptr = iconsetptr;\n\t\t\t}\t\n\t\t}\n\t\tClose_Iff_File(fh);\n\t}\n\n\treturn (returnptr);\t\t// Return with icon pointer.\n}\n\n\n/***************************************************************************\n * FREE_ICON_SET -- Frees allocations made by Load_Icon_Set().             *\n *                                                                         *\n *    This routine is used to free up any allocations by Load_Icon_Set().  *\n *    Use this routine when a new icon set is to be loaded.                *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid cdecl Free_Icon_Set(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tif (icontrol->Allocated) {\n\t\t\tFree((void *)iconset);\n\t\t}\n\t}\n}\n\n\nlong cdecl Get_Icon_Set_Size(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tlong\t\t\t\tsize=0;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tsize = icontrol->Size;\n\t}\n\treturn(size);\n}\n\n\nint cdecl Get_Icon_Set_Width(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tint\t\t\t\twidth=0;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\twidth = icontrol->Width;\n\t}\n\treturn(width);\n}\n\n\nint cdecl Get_Icon_Set_Height(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tint\t\t\t\theight=0;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\theight = icontrol->Height;\n\t}\n\treturn(height);\n}\n\n\nvoid * cdecl Get_Icon_Set_Icondata(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tvoid\t\t\t\t*ptr=NULL;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tptr = Add_Long_To_Pointer((void *)iconset, icontrol->Icons);\n\t}\n\treturn(ptr);\n}\n\nvoid * cdecl Get_Icon_Set_Trans(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tvoid\t\t\t\t*ptr=NULL;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tptr = Add_Long_To_Pointer((void *)iconset, icontrol->TransFlag);\n\t}\n\treturn(ptr);\n}\n\n\nint cdecl Get_Icon_Set_Count(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tint\t\t\t\tcount;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tcount = icontrol->Count;\n\t}\n\treturn(count);\n}\n\n\nvoid * cdecl Get_Icon_Set_Map(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tvoid\t\t\t\t*ptr=NULL;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tptr = Add_Long_To_Pointer((void *)iconset, icontrol->Map);\n\t}\n\treturn(ptr);\n}\n\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/TILE/ICONSET.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library                                  *\n *                                                                         *\n *                    File Name : ICONSET.C                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : June 9, 1991                             *\n *                                                                         *\n *                  Last Update : September 15, 1993   [JLB]               *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Load_Icon_Set -- Loads an icons set and initializes it.               *\n *   Free_Icon_Set -- Frees allocations made by Load_Icon_Set().           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n//#include\t\"function.h\"\n#include\t<dos.h>\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<mem.h>\n#include\t<wwstd.h>\n#include\t<file.h>\n#include\t<iff.h>\n\nunsigned long Misc;\n\nvoid * cdecl Load_Icon_Set(char const *filename, void *iconsetptr, long buffsize);\nvoid cdecl Free_Icon_Set(void const *iconset);\nlong cdecl Get_Icon_Set_Size(void const *iconset);\nint cdecl Get_Icon_Set_Width(void const *iconset);\nint cdecl Get_Icon_Set_Height(void const *iconset);\nvoid * cdecl Get_Icon_Set_Icondata(void const *iconset);\nvoid * cdecl Get_Icon_Set_Trans(void const *iconset);\nvoid * cdecl Get_Icon_Set_Remapdata(void const *iconset);\nvoid * cdecl Get_Icon_Set_Palettedata(void const *iconset);\nint cdecl Get_Icon_Set_Count(void const *iconset);\nvoid * cdecl Get_Icon_Set_Map(void const *iconset);\n\n\n//#define\tICON_PALETTE_BYTES\t16\n//#define\tICON_MAX\t\t\t\t\t256\n\n/***************************************************************************\n**\tThe terrain is rendered by using icons.  These are the buffers that hold\n**\tthe icon data, remap tables, and remap index arrays.\n*/\n//PRIVATE char *IconPalette = NULL;\t\t// MCGA only.\n//PRIVATE char *IconRemap = NULL;\t\t\t// MCGA only.\n\n#define\tFORM_RPAL\tMAKE_ID('R','P','A','L')\n#define\tFORM_RTBL\tMAKE_ID('R','T','B','L')\n#define\tFORM_SSET\tMAKE_ID('S','S','E','T')\n#define\tFORM_SINF\tMAKE_ID('S','I','N','F')\n#define\tFORM_ICON\tMAKE_ID('I','C','O','N')\n#define\tFORM_TRNS\tMAKE_ID('T','R','N','S')\n#define\tFORM_MAP\t\tMAKE_ID('M','A','P',' ')\n\n/*\n** This is the control structure at the start of a loaded icon set.  It must match\n** the structure in WWLIB.I!  This structure MUST be a multiple of 16 bytes long.\n*/\ntypedef struct {\n\tshort\tWidth;\t\t\t// Width of icons (pixels).\n\tshort\tHeight;\t\t\t// Height of icons (pixels).\n\tshort\tCount;\t\t\t// Number of (logical) icons in this set.\n//\tBOOL\tAllocated;\t\t// Was this iconset allocated?\n\tshort\tAllocated;\t\t// Was this iconset allocated?\n\tshort\tMapWidth;\t\t// Width of map (in icons).\n\tshort\tMapHeight;\t\t// Height of map (in icons).\n\tlong\tSize;\t\t\t\t// Size of entire iconset memory block.\n\tlong\tIcons;\t\t\t// Offset from buffer start to icon data.\n\tlong\tPalettes;\t\t// Offset from buffer start to palette data.\n\tlong\tRemaps;\t\t\t// Offset from buffer start to remap index data.\n\tlong\tTransFlag;\t\t// Offset for transparency flag table.\n\tlong\tColorMap;\n\tlong\tMap;\t\t\t\t// Icon map offset (if present).\n} IControl_Type;\n\n\n/***************************************************************************\n * LOAD_ICON_SET -- Loads an icons set and initializes it.                 *\n *                                                                         *\n *    This routine will load an IFF icon set from disk.  It handles all    *\n *    of the necessary allocations.                                        *\n *                                                                         *\n * INPUT:   filename -- Name of the icon file.                             *\n *                                                                         *\n *          buffer   -- Pointer to paragraph aligned buffer to hold data.  *\n *                                                                         *\n *          size     -- Size of the buffer (in bytes).                     *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   In EEGA mode the iconset buffer will be free because the    *\n *             icons will have been transferred to card ram.               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1991 JLB : Created.                                             *\n *   07/01/1991 JLB : Determines icon size from file.                      *\n *   07/15/1991 JLB : Load and uncompress onto the same buffer.            *\n *   09/15/1993 JLB : Added EMS support.                                   *\n *=========================================================================*/\nvoid * cdecl Load_Icon_Set(char const *filename, void *iconsetptr, long buffsize)\n{\n\tint\tfh;\t\t\t\t// File handle of iconset.\n\tint\tbytespericon;\t// The number of bytes per icon.\n\tunsigned long\ticons=0;\t\t\t// Number of icons loaded.\n\tunsigned long\tsize;\t\t\t\t// Size of the icon chunk (raw).\n\n\tunsigned long\ttranssize;\n\tvoid\t*transptr=NULL;\n\n\tunsigned long\tmapsize;\t\t\t\t// Icon map chunk size.\n\tvoid\t*mapptr=NULL;\t\t// Icon map pointer.\n\tvoid\t*returnptr=NULL;\t// Iconset pointer returned by routine.\n\tBOOL\tallocated=FALSE;\t// Was the iconset block allocated?\n\tIControl_Type\t*idata=NULL;\t// Icon data loaded.\n\tlong\tid;\t\t\t\t// ID of file openned.\n\tstruct {\n\t\tchar\tWidth;\t\t// Width of icon in bytes.\n\t\tchar\tHeight;\t\t// Height of icon in bytes.\n\t\tchar\tFormat;\t\t// Graphic mode.\n\t\t\t\t\t\t\t\t//lint -esym(754,Format)\n\t\tchar\tBitplanes;\t// Number of bitplanes per icon.\n\t} sinf;\n\n\t/*\n\t**\tOpen the icon set for loading.  If it is not a legal icon set\n\t**\tdata file, then abort.\n\t*/\n\tfh = Open_Iff_File(filename);\n\tif (fh != ERROR) {\n\t\tRead_File(fh, &id, sizeof(long));\n\t\tif (id == FORM_ICON) {\n\t\t\n\t\t\t/*\n\t\t\t**\tDetermine the size of the icons and set up the graphic\n\t\t\t**\tsystem accordingly.  Also get the sizes of the various\n\t\t\t**\tdata blocks that have to be loaded.\n\t\t\t*/\n\t\t\tRead_Iff_Chunk(fh, FORM_SINF, &sinf, sizeof(sinf));\n\t\t\tbytespericon = ((((int)sinf.Width)<<3)*(((int)sinf.Height)<<3)*(int)sinf.Bitplanes)>>3;\n\n\t\t\tsize = Get_Iff_Chunk_Size(fh,FORM_SSET);\n\t\t\t\ttranssize = Get_Iff_Chunk_Size(fh, FORM_TRNS);\n\t\t\tmapsize = Get_Iff_Chunk_Size(fh, FORM_MAP);\n\t\t\n\t\t\t/*\n\t\t\t**\tAllocate the icon buffer if one isn't provided.  First try EMS and\n\t\t\t**\tthen try conventional RAM.\n\t\t\t*/\n\t\t\tallocated = FALSE;\n\t\t\tif (!iconsetptr) {\n\t\t\t\t\tbuffsize = size + transsize + mapsize + sizeof(IControl_Type);\n\n\t\t\t\tMisc = buffsize;\n\t\t\t\ticonsetptr = Alloc(buffsize, MEM_NORMAL);\n\t\t\t\tallocated = (iconsetptr != NULL);\n\t\t\t}\n\n\t\t\tif (iconsetptr && (size+transsize+mapsize+sizeof(IControl_Type)) <= buffsize) {\n\n\t\t\t\tidata = (IControl_Type *)iconsetptr;\n\n\t\t\t\tmemset(idata, 0, sizeof(IControl_Type));\n\n\t\t\t\t/*\n\t\t\t\t**\tInitialize the iconset header structure.\n\t\t\t\t*/\n\t\t\t\tidata->Width = sinf.Width<<3;\n\t\t\t\tidata->Height = sinf.Height<<3;\n\t\t\t\tidata->Allocated = allocated;\n\t\t\t\tidata->Icons = sizeof(IControl_Type);\n\t\t\t\tidata->Map = idata->Icons + size;\n\t\t\t\t\tidata->TransFlag = idata->Map + mapsize;\n\t\t\t\tidata->Size = buffsize;\n\n\t\t\t\t\t{\n\t\t\t\t\t\tlong\tval;\n\n\t\t\t\t\t\tval = Read_Iff_Chunk(fh, FORM_SSET, Add_Long_To_Pointer(iconsetptr, sizeof(IControl_Type)), size);\n\t\t\t\t\t\ticons = (int)(val/(long)bytespericon);\n\t\t\t\t\t\tidata = (IControl_Type *)iconsetptr;\t\t\t\t\n\t\t\t\t\t}\n\n\t\t\t\tif (mapsize) {\n\t\t\t\t\ticons = mapsize;\n\t\t\t\t}\n\t\t\t\tidata->Count = (short)icons;\n\n\t\t\t\t/*\n\t\t\t\t**\tLimit buffer to only the size needed.  This is done AFTER loading of the\n\t\t\t\t**\traw icon data because it might have been compressed and thus need any\n\t\t\t\t**\textra space to perform an overlapped decompression.\n\t\t\t\t*/\n\t\t\t\t\tif (buffsize > size + transsize + mapsize + sizeof(IControl_Type)) {\n\t\t\t\t\t\tbuffsize = size + transsize + mapsize + sizeof(IControl_Type);\n\t\t\t\t\t}\n\n\t\t\t\t\ttransptr = Add_Long_To_Pointer(iconsetptr, idata->TransFlag);\n\t\t\t\t\tRead_Iff_Chunk(fh, FORM_TRNS, transptr, transsize);\n\t\t\t\t\tidata = (IControl_Type *)iconsetptr;\t\t\t\t\n\n\t\t\t\tmapptr = Add_Long_To_Pointer(iconsetptr, idata->Map);\n\t\t\t\tRead_Iff_Chunk(fh, FORM_MAP, mapptr, mapsize);\n\n\t\t\t\t/*\n\t\t\t\t**\tLet the graphic overlay know of the icon data.  This could involve\n\t\t\t\t**\ttranslation and other data manipulations.\n\t\t\t\t*/\n\t\t\t\t//Init_Stamps(iconsetptr);\n\n\t\t\t\treturnptr = iconsetptr;\n\t\t\t}\t\n\t\t}\n\t\tClose_Iff_File(fh);\n\t}\n\n\treturn (returnptr);\t\t// Return with icon pointer.\n}\n\n\n/***************************************************************************\n * FREE_ICON_SET -- Frees allocations made by Load_Icon_Set().             *\n *                                                                         *\n *    This routine is used to free up any allocations by Load_Icon_Set().  *\n *    Use this routine when a new icon set is to be loaded.                *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/21/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid cdecl Free_Icon_Set(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tif (icontrol->Allocated) {\n\t\t\tFree((void *)iconset);\n\t\t}\n\t}\n}\n\n\nlong cdecl Get_Icon_Set_Size(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tlong\t\t\t\tsize=0;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tsize = icontrol->Size;\n\t}\n\treturn(size);\n}\n\n\nint cdecl Get_Icon_Set_Width(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tint\t\t\t\twidth=0;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\twidth = icontrol->Width;\n\t}\n\treturn(width);\n}\n\n\nint cdecl Get_Icon_Set_Height(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tint\t\t\t\theight=0;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\theight = icontrol->Height;\n\t}\n\treturn(height);\n}\n\n\nvoid * cdecl Get_Icon_Set_Icondata(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tvoid\t\t\t\t*ptr=NULL;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tptr = Add_Long_To_Pointer((void *)iconset, icontrol->Icons);\n\t}\n\treturn(ptr);\n}\n\nvoid * cdecl Get_Icon_Set_Trans(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tvoid\t\t\t\t*ptr=NULL;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tptr = Add_Long_To_Pointer((void *)iconset, icontrol->TransFlag);\n\t}\n\treturn(ptr);\n}\n\n\nint cdecl Get_Icon_Set_Count(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tint\t\t\t\tcount;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tcount = icontrol->Count;\n\t}\n\treturn(count);\n}\n\n\nvoid * cdecl Get_Icon_Set_Map(void const *iconset)\n{\n\tIControl_Type\t*icontrol;\n\tvoid\t\t\t\t*ptr=NULL;\n\n\ticontrol = (IControl_Type *)iconset;\n\tif (icontrol) {\n\t\tptr = Add_Long_To_Pointer((void *)iconset, icontrol->Map);\n\t}\n\treturn(ptr);\n}\n\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/TILE/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : jan 24, 1995                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = tile\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\t\ticonset.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\tmkdir run\n\tcd run\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\run\\vcs.cfg\n\tupdate\n\tcd..\n\tmkdir art\n\tcd art\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\art\\vcs.cfg\n\tupdate\n\tcd..\n\twmake \n\tcd ..\n\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/TILE/TILE.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the TILE Library                 *\n *                                                                         *\n *                    File Name : TILE.H                                   *\n *                                                                         *\n *                   Programmer : Barry W. Green                           *\n *                                                                         *\n *                   Start Date : February 2, 1995                         *\n *                                                                         *\n *                  Last Update : February 2, 1995 [BWG]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TILE_H\n#define TILE_H\n\n/*=========================================================================*/\n/* The following prototypes are for the file: ICONSET.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid * Load_Icon_Set(char const *filename, void *iconsetptr, long buffsize);\nvoid Free_Icon_Set(void const *iconset);\nlong Get_Icon_Set_Size(void const *iconset);\nint Get_Icon_Set_Width(void const *iconset);\nint Get_Icon_Set_Height(void const *iconset);\nvoid * Get_Icon_Set_Icondata(void const *iconset);\nvoid * Get_Icon_Set_Trans(void const *iconset);\nvoid * Get_Icon_Set_Remapdata(void const *iconset);\nvoid * Get_Icon_Set_Palettedata(void const *iconset);\nint Get_Icon_Set_Count(void const *iconset);\nvoid * Get_Icon_Set_Map(void const *iconset);\n\n#endif //TILE_H\n\n\n"
  },
  {
    "path": "WWFLAT32/TILE/TILE.H.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the TILE Library                 *\n *                                                                         *\n *                    File Name : TILE.H                                   *\n *                                                                         *\n *                   Programmer : Barry W. Green                           *\n *                                                                         *\n *                   Start Date : February 2, 1995                         *\n *                                                                         *\n *                  Last Update : February 2, 1995 [BWG]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TILE_H\n#define TILE_H\n\n/*=========================================================================*/\n/* The following prototypes are for the file: ICONSET.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid * Load_Icon_Set(char const *filename, void *iconsetptr, long buffsize);\nvoid Free_Icon_Set(void const *iconset);\nlong Get_Icon_Set_Size(void const *iconset);\nint Get_Icon_Set_Width(void const *iconset);\nint Get_Icon_Set_Height(void const *iconset);\nvoid * Get_Icon_Set_Icondata(void const *iconset);\nvoid * Get_Icon_Set_Trans(void const *iconset);\nvoid * Get_Icon_Set_Remapdata(void const *iconset);\nvoid * Get_Icon_Set_Palettedata(void const *iconset);\nint Get_Icon_Set_Count(void const *iconset);\nvoid * Get_Icon_Set_Map(void const *iconset);\n\n#endif //TILE_H\n\n\u001a"
  },
  {
    "path": "WWFLAT32/TIMER/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 27, 1995\t                           *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = timer\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\ttimer.obj\t&\n\ttimerdwn.obj\t&\n\ttimerini.obj\t&\n\ttimera.obj\n\n \n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n\n#---------------------------------------------------------------------------\n# The keyboard object files is also dependant on an IBN file which is \n#   generated from KEYIREAL.ASM\n#---------------------------------------------------------------------------\ntimereal.ibn: timereal.obj\n\t%create\t$^*.rsp\n\t%append $^*.rsp $^&.obj\n\t%append $^*.rsp $^&.exe\n\t%append $^*.rsp $^&.map\n\ttlink @$^*.rsp\n        tdstrip timereal.exe\n        ebn\ttimereal.exe\n\ntimereal.obj:\ttimereal.asm\n\ttasm /zn /la /ml /m2 timereal.asm\n\ntimera.obj: timereal.ibn timera.asm\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WWFLAT32/TIMER/TIMER.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Temp timer for 32bit lib                 *\n *                                                                         *\n *                    File Name : TIMER.CPP                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : July 6, 1994                             *\n *                                                                         *\n *                  Last Update : May 3, 1995   [SKB]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   TC::Time -- Return the time on the timer.                             *\n *   TC::TimerClass -- Construct a timer class object.                     *\n *   TC::Stop -- Stop the timer.                                           *\n *   TC::Start -- Start a timer.                                           *\n *   TC::Set -- Set the time of a timer.                                   *\n *   TC::Reset -- Clear the timer.                                         *\n *   TimerClass::Time -- Get the current time of timer.                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include \"timer.H\"\n#include <stdio.h>\n#include <stdlib.h>\n\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////////// Code ////////////////////////////////////////\n\n/***************************************************************************\n * TC::TIMERCLASS -- Construct a timer class object.                       *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nTimerClass::TimerClass(BaseTimerEnum timer, BOOL on)\n{\n\tAccumulated = 0;\n\tStarted = 0;\n\n\tswitch (timer) {\n\t\tcase BT_USER:\n\t\t\tGet_Ticks = Get_User_Tick_Count;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\tcase BT_SYSTEM:\n\t\t\tGet_Ticks = Get_System_Tick_Count;\n\t\t\tbreak;\n\t}\n\tif (on && TimerSystemOn) Start();\n}\n\n\n\n/***************************************************************************\n * TIMERCLASS::TIME -- Get the current time of timer.                      *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1995 SKB : Created.                                             *\n *=========================================================================*/\nlong TimerClass::Time(void)\n{\n\tif (Started) {\n\t\tlong ticks = Get_Ticks();\n\t\tAccumulated += ticks - (Started-1);\n\t\tStarted = ticks+1;\n\t}\n\treturn(Accumulated);\n}\n\n\n/***************************************************************************\n * TC::STOP -- Stop the timer.                                             *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong TimerClass::Stop(void)\n{\n\tlong time = Time();\n\tStarted = 0;\n\treturn(time);\n}\n\n\n/***************************************************************************\n * TC::START -- Start a timer.                                             *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong TimerClass::Start(void)\n{\n\tif (!Started) {\n\t\tStarted = Get_Ticks()+1;\n\t}\n\treturn(Time());\n}\n\n\n/***************************************************************************\n * TC::SET -- Set the time of a timer.                                     *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:  long value to set timer at.                                     *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *   05/03/1995 SKB : If start return Start since it returns Time          *\n *=========================================================================*/\nlong TimerClass::Set(long value, BOOL start)\n{\n\tStarted = 0;\n\tAccumulated = value;\n\tif (start) return (Start());\n\treturn(Time());\n}\n\n\n"
  },
  {
    "path": "WWFLAT32/TIMER/TIMER.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Timer Class Functions                    *\n *                                                                         *\n *                    File Name : TIMER.H                                  *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : July 6, 1994                             *\n *                                                                         *\n *                  Last Update : July 12, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TIMER_H\n#define TIMER_H\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TIMERA.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// Externs /////////////////////////////////////////////\nextern BOOL TimerSystemOn;\n\n\n/*=========================================================================*/\ntypedef enum BaseTimerEnum {\n\tBT_SYSTEM,\t\t\t// System timer (60 / second).\n\tBT_USER\t\t\t\t// User controllable timer (? / second).\n} BaseTimerEnum;\n\nclass TimerClass {\n \tpublic:\n\t\t// Constructor.  Timers set before low level init has been done will not\n\t\t// be able to be 'Started' or 'on' until timer system is in place.\t\n\t\tTimerClass(BaseTimerEnum timer=BT_SYSTEM, BOOL start=FALSE);\n\n\t\t// No destructor.\n\t\t~TimerClass(void){}\n\n\t\t// \n\t\tlong Set(long value, BOOL start=TRUE);\t// Set initial timer value.\n\t\tlong Stop(void);\t\t\t\t// Pause timer.\n\t\tlong Start(void);\t\t\t\t// Resume timer.\n\t\tlong Reset(BOOL start=TRUE);\t// Reset timer to zero.\n\t\tlong Time(void);\t\t\t\t// Fetch current timer value.\n\n\tprotected:\n\t\tlong Started;\t\t\t\t\t// Time last started (0 == not paused).\n\t\tlong Accumulated;\t\t\t\t//\tTotal accumulated ticks.\n\n\tprivate:\n\t\tlong (*Get_Ticks)(void);\t// System timer fetch.\n};\n\n\ninline long TimerClass::Reset(BOOL start)\n{\n\treturn(Set(0, start));\n}\n\n\nclass CountDownTimerClass : private TimerClass {\n\tpublic:\n\t\t// Constructor.  Timers set before low level init has been done will not\n\t\t// be able to be 'Started' or 'on' until timer system is in place.\t\n\t\tCountDownTimerClass(BaseTimerEnum timer, long set, int on=FALSE);\n\t\tCountDownTimerClass(BaseTimerEnum timer=BT_SYSTEM, int on=FALSE);\n\n\t\t// No destructor.\n\t\t~CountDownTimerClass(void){}\n\n\t\t// Public functions\n\t\tlong Set(long set, BOOL start=TRUE);\t// Set count down value.\n\t\tlong Reset(BOOL start=TRUE);\t// Reset timer to zero.\n\t\tlong Stop(void);\t\t\t// Pause timer.\n\t\tlong Start(void);\t\t\t// Resume timer.\n\t\tlong Time(void);\t\t\t// Fetch current count down value.\n\n\tprotected:\n\t\tlong DelayTime;\t\t\t// Ticks remaining before countdown timer expires.\n};\n\ninline long CountDownTimerClass::Stop(void)\n{\n\tTimerClass::Stop();\n\treturn(Time());\n}\n\ninline long CountDownTimerClass::Start(void)\n{\n\tTimerClass::Start();\n\treturn(Time());\n}\n\ninline long CountDownTimerClass::Reset(BOOL start)\n{\n\treturn (TimerClass::Reset(start));\n}\n\n\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// externs  //////////////////////////////////////////\n\nextern TimerClass\t\t\t\t\tTickCount;\nextern CountDownTimerClass\t\tCountDown;\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////// Prototypes //////////////////////////////////////////\n\nextern \"C\" {\n\tlong Get_System_Tick_Count(void);\n\tlong Get_User_Tick_Count(void);\n\tvoid far Timer_Interrupt_Func(void);\n//\tlong Get_Num_Interrupts(unsigned int realmode);\n\tvoid Disable_Timer_Interrupt(void);\n\tvoid Enable_Timer_Interrupt(void);\n}\n\n/*=========================================================================*/\n/* The following prototypes are for the file: TIMER.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nBOOL Init_Timer_System(unsigned int freq, int partial = FALSE);\nBOOL Remove_Timer_System(VOID);\n\n\n#endif // TIMER_H\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/TIMER/TIMERA.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Timer stuff                              *\n;*                                                                         *\n;*                    File Name : TIMERA.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : July 6, 1994                             *\n;*                                                                         *\n;*                  Last Update : March 14, 1995   [PWG]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Get_RM_Timer_Address -- Return address of real mode code for copy.    *\n;*   Get_RM_Timer_Size -- return size of real mode timer code.             *\n;*   Increment_Tick_Count -- Increments WW system timer.                   *\n;*   Timer_Interrupt -- Temp routine to mimic a timer system calling our.  *\n;*   Install_Timer_Interrupt -- Installs the timer interrupt routine.      *\n;*   Remove_Timer_Interrupt -- Removes the timer interrupt vectors.       **\n;*   Set_Timer_Frequency -- Set the frequency of the timer.                *\n;*   Set_Timer_Rate -- Set the rate of the timer.                          *\n;*   Get_System_Tick_Count -- Returns the system tick count.               *\n;*   Get_User_Tick_Count -- Get tick count of user clock.                  *\n;*   Increment_Timers -- Increments system and user timers.                *\n;*   Get_Num_Interrupts -- Returns the number of interrupts that have occured*\n;*   Timer_Interrupt_Func -- Handles core timer code                       *\n;*   Disable_Timer_Interrupt -- Disables at the hardware level             *\n;*   Enable_Timer_Interrupt -- Enables at the hardware level               *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nDPMI_INTR\tequ\t31h\t\nTRUE\t\tequ\t1\t\t\t; Boolean 'true' value\nFALSE\t\tequ\t0\t\t\t; Boolean 'false' value\n\nLOCALS ??\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////////// Equates ////////////////////////////////////////\n\nSYSTEM_TIMER_FREQ\tequ\t60\t; Frequency of system timer.\n\n;********************************************************************\n; There are two ways to call our interrupt chain in protected mode.  \n; The obvious way it to call the address that we replaced in the\n; PM interrupt chain.  This method is a little difficult but works and\n; should always work.\n\n\n;********************************************************************\n; The RM and PM interrupts can be installed at the same time or seperately.\n; Installing at the same time is the best method, the other method\n; can be used to faciliated debugging when you only want one or the other\n; called.  Both methods work.\n; -SKB July 21, 1994.\nINSTALL_SEPERATE\tequ\tFALSE\n\n\nINTCHIP0\tEQU\t20h\t\t; 8259 interrupt chip controller 0\nCLEARISR\tEQU\t20h\t\t; Value to write to 8259 to reenable interrupts.\nIRQ0INTNUM\tEQU\t08h\t\t; IRQ0 interrupt vector number.\nDOS_SYS_CALL\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nLOCK_PAGES\tEQU\t5\t\t; Lock pages subfunction using DX_MEM_MGT\nUNLOCK_PAGES\tEQU\t6\t\t; Unlock pages subfunction using DX_MEM_MGT\n\nTIMER_CONST\tEQU\t1193180\t\t; TIMER_CONST / FREQ = rate to set 8259 chip\n\nTIMERCMDREG\tEQU\t043H\t\t; timer command register port.\nTIMER0PORT\tEQU\t040H\t\t; timer channel 0 port\nTIMETYPE\tEQU\t036H\t\t; type of timer.\n\t;  36H = 0011 0110\t\t\t    \n\t;        --         select channel 0\t\t\t    \n\t;          --       read/load low byte then high byte for timer\t\t\t    \n\t;             ---   timer mode 3\t\t\t    \n\t;                -  0 - binary , 1 - BCD data\n\t\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////////// Structs ////////////////////////////////////////\n\n\n; Structure of memory in real mode handler.\n; This is at the very start of the real mode code.\n; This information may not change unless the real mode version is also changed.\n\nSTRUC TimerType\n; For speed, PM uses a DD while RM used DW\n; For speed, SysRate and SysError are DD in PM and are DW in real mode.\n\n\tTrueRate\t\tDD\t?\t; True rate of clock. (only use word)\n    \tSysTicks\t\tDD\t?\t; Tick count of timer.\n\tSysRate\t\t\tDD\t?\t; Desired rate of timer.\n\tSysError\t \tDD\t?\t; Amount of error in clock rate for desired frequency.\n\tSysCurRate\t \tDW\t?\t; Keeps track of when to increment timer.\n\tSysCurError\t\tDW\t?\t; Keeps track of amount of error in timer.\n\n    \tUserTicks\t\tDD\t?\t; Tick count of timer.\n\tUserRate\t \tDD\t?\t; Desired rate of timer.\n\tUserError\t \tDD\t?\t; Amount of error in clock rate for desired frequency.\n\tUserCurRate\t \tDW\t?\t; Keeps track of when to increment timer.\n\tUserCurError\t\tDW\t?\t; Keeps track of amount of error in timer.\n\n\tDosAdder\t\tDW\t? \t; amount to add to DosFraction each interrupt.\n\tDosFraction\t\tDW\t?\t; Call dos when overflowed.\n\n\tOldRMI\t\t\tDD\t?\t; The origianl RM interrupt seg:off.\n\tOldPMIOffset\t\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tOldPMISelector\t\tDD\t?\t; The original PM interrupt segment.\n\n\tCodeOffset\t\tDW\t?\t; Offset of the code in the RM stuff.\n\tCallRMIntOffset\t\tDW\t?\t; Offset of function to call DOS timer interrupt.\n\tCallRMIntAddr\t\tDD\t?\t; PM address of CallRealIntOffset for speed.\n\n\tPMIssuedInt\t\tDD\t0\t; PM signals RM to just call Int chain.\t\n\n; These are just used for information on testing.  When all is done, they can\n; be removed, but why?  The don't add too much proccessing time and can\n; be useful.\n\tNumPMInts\t\tDD\t?\t; Number of PM interrupts\n\tNumRMInts\t\tDD\t?\t; Number of RM interrupts.\n\nENDS\n\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;/////////////////////////////////// Prototypes //////////////////////////////////////\n\nGLOBAL\t \tGet_System_Tick_Count:NEAR\nGLOBAL\t \tGet_User_Tick_Count:NEAR\nGLOBAL\t \tGet_RM_Timer_Address:NEAR\nGLOBAL\t \tGet_RM_Timer_Size:NEAR\nGLOBAL\t \tSet_Timer_Frequency:NEAR\nGLOBAL\t \tTimer_Interrupt:NEAR\nGLOBAL\t \tInstall_Timer_Interrupt:NEAR\nGLOBAL\t \tRemove_Timer_Interrupt:NEAR\nGLOBAL\t \tGet_Num_Interrupts:NEAR\nGLOBAL\t\tTimer_Interrupt_Func:FAR\nGLOBAL\t\tDisable_Timer_Interrupt:NEAR\nGLOBAL\t\tEnable_Timer_Interrupt:NEAR\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;//////////////////////////////////////// Data ////////////////////////////////////////\n\tDATASEG\n\n; The current time we will just include the real mode stuff\n; into the protected mode code and then copy it down.  The C side of\n; this will handle this method or reading it off of disk in the real\n; method.\n\nLABEL \tRealBinStart\tBYTE\ninclude \"timereal.ibn\"\nLABEL\tRealBinEnd\tBYTE\n\n\n\n\nLABEL\tLockedDataStart\tBYTE\t\nRealModeSel\tDD\t0\nRealModePtr\tDD\t0\t\t; Pointer to real mode memory.\nRealModeSize\tDD\t0\t\t; Pointer to real mode memory.\nLABEL\tLockedDataEnd\tBYTE\n\n\t\nInitFlags\tDD\t0\t\t; Flags to indicate what has been initialized.\n\n; InitFlags that are set to have a fully functional interrupt.\nIF_ALLOC_RM\t\tequ\t1h\t\t; Allocation of RM was successful.\nIF_SET_VECTORS\t\tequ\t2h\t\t; Vectors have been set.\nIF_LOCKED_PM_CODE\tequ\t4h\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t8h\t\t; Locked PM code for DPMI.\nIF_RATE_CHANGE\t\tequ\t10h\t\t; Timer rate was changed.\nIF_FUNCTIONAL\t\tequ\t20h\t\t; Timer is in and functional.\nIF_LOCKED_RM_CODE\tequ\t40h\t\t; Timer is in and functional.\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;//////////////////////////////////////// Code ////////////////////////////////////////\n\n\tCODESEG\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;/////////////////////////////// Init routines ////////////////////////////////////////\n\n;***************************************************************************\n;* GET_RM_TIMER_ADDRESS -- Return address of real mode code for copy.      *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Timer_Address C Near\n\n\tmov\teax, OFFSET RealBinStart\n\tret\n\n\tENDP\n\n;***************************************************************************\n;* GET_RM_TIMER_SIZE -- return size of real mode timer code.               *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Timer_Size C Near\n\n\tmov\teax, OFFSET RealBinEnd - OFFSET RealBinStart\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* SET_TIMER_RATE -- Set the rate of the timer.                            *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:  ebx = rate to set timer were rate = 1193180 / freq              *\n;*                                                                         *\n;* OUTPUT: none                                                            *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 SKB : Created.                                             *\n;*=========================================================================*\nPROC\tSet_Timer_Rate Near\n\n\tpush\teax\n\tpushf\t\t\t\t\t; to save int enable flag\t\n\tcli\t\t\t\t\t; disable interupts while setting up swapper\n\n\tmov\tal,TIMETYPE\t\t\t; setup to modify timer 0\n\tout\tTIMERCMDREG,al\t\t\t; send command.\n\tmov\teax,ebx\t\t\t\t; get rate.\n\tout\tTIMER0PORT,al\t\t\t; output low byte\n\tmov\tal,ah\n\tout\tTIMER0PORT,al\t\t\t; output high byte\n\n\tsti\n\tpopf\t\t\t\t\t; get int enable flag.\n\tpop\teax\n\n\tret\nENDP\tSet_Timer_Rate\n\n;***************************************************************************\n;* SET_TIMER_FREQUENCY -- Set the frequency of the timer.                  *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:  INT Frequency of user timer.                                    *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\nPROC\tSet_Timer_Frequency C NEAR\n\tUSES\teax,ebx,ecx,edx\n\tARG\tfreq:DWORD\n\tLOCAL\tclockrate:DWORD\n\tLOCAL\tclockfreq:DWORD\n\n\ttest\t[InitFlags],IF_FUNCTIONAL\t; Is our timer system installed?\n\tjz\t??timer_not_installed\t\t; if not, this is not legal.\n\n\n\t; Find out the greater of the frequencies (user or system.)\n\t; Assign the True rate value based of of that.\n\t; store the max frequency in ecx.\n\tmov\tecx,[freq]\t\t\t; get user frequency.\n\tcmp\tecx,SYSTEM_TIMER_FREQ\t\t; compare it with system frequency\n\tjg\t??user_is_fastest\t\t; is user frequency faster?\n\tmov\tecx,SYSTEM_TIMER_FREQ\t\t; no, set clock freq to system frequency.\n??user_is_fastest:   \n\n\t; now get the rate that the clock will be set at.\n\t; ecx is still max frequency.\n\tmov\tesi,[RealModePtr]\n\n\tmov\teax,TIMER_CONST\t\t\t; get the clock constant value.\n\txor\tedx,edx\t\t\t\t; zero for divide.\n\tdiv\tecx\t\t\t\t; rate = TC/freq => eax = eax/ecx;\n\tmov\t[(TimerType PTR esi).TrueRate],eax ; Set our true rate.\n\tmov\tebx,eax\t\t\t\t; save for later. DO NOT USE UNTIL CALL\n\n\t; Set up variables to call DOS correctly.\n\t; When DosFraction overflows, DOS is called.\n\tmov\t[(TimerType PTR esi).DosAdder],ax\t; Init count to until call dos.\n\tmov\t[(TimerType PTR esi).DosFraction],0\t; init the fraction.\n\n\t; now set up the system timer.\n\tmov\tecx,SYSTEM_TIMER_FREQ\t\t\t; get frequency.\n\tmov\teax,TIMER_CONST\t\t\t\t; get constant for formula rate=C/freq.\n\txor\tedx,edx\t\t\t\t   \t; make sure zero for divide\n\tdiv\tecx\t\t\t\t\t; calculate rate\n\tmov\t[(TimerType PTR esi).SysCurRate],ax\t; Init current stuff.\n\tmov\t[(TimerType PTR esi).SysCurError],ax\t; Init current stuff.\n\tmov\t[(TimerType PTR esi).SysRate],eax\t; Save rate of timer\n\tmov\t[(TimerType PTR esi).SysError],edx\t; Save error of timer\n\t; Do not set SysTicks to zero since it always has the same frequency.  It\n\t; should be zero out only when the system clock is installed.\n\n\t; now set up the user timer.\n\tmov\tecx,[freq]\t\t\t\t; get frequency of user timer.\n\tmov\teax,TIMER_CONST\t\t\t\t; get constant for formula rate=C/freq.\n\txor\tedx,edx\t\t\t\t   \t; make sure zero for divide\n\tdiv\tecx\t\t\t\t\t; calculate rate\n\tmov\t[(TimerType PTR esi).UserCurRate],ax\t; Init current stuff.\n\tmov\t[(TimerType PTR esi).UserCurError],ax; Init current stuff.\n\tmov\t[(TimerType PTR esi).UserRate],eax\t; Save rate of timer\n\tmov\t[(TimerType PTR esi).UserError],edx\t; Save error of timer\n\tmov\t[(TimerType PTR esi).UserTicks],0\t; User timer sets to zero when freq change.\n\n\t; Call function to set the rate of the chip, ebx = rate from above.\n\tcall\tSet_Timer_Rate\n\n??timer_not_installed:\n\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* INSTALL_TIMER_Interrupt -- Installs the timer interrupt routine.        *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:  VOID * pointer to RM binary in PM memory.                       *\n;*         LONG Size of RM binary.                                         *\n;*         INT  frequency of user timer.                                   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tInstall_Timer_Interrupt C Near\n\tUSES\tebx,ecx,edx\n\tARG\trm_ptr:DWORD\n\tARG\trm_size:DWORD\n\tARG\tfreq:DWORD\n\tARG\tpartial:DWORD\n\n\t; Are they attempting to set timer again?\n\tcmp\t[RealModePtr],0\n\tjnz\t??error\n\n\t; Make sure all flags are cleared.\n\tcmp\t[InitFlags],0\n\tjnz\t??error\n\n\t; Before setting the interrupt vectors, the code needs to be locked\n\t; for DPMI compatability.  Any code or data accessed must be lockded\n\t; so that no page faults accure during an interrupt.\n\t; First lock the code, then the data.  The stack will already be locked.\n\t; The real mode code is also already locked be default.\n\t; To lock a page set up registers :\n\t; AX = 0600h\n\t; BX:CX\t= starting linear address of memory block\n\t; SI:DI = size of region\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_CODE\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_DATA\n\n\t; now allocate real mode memory and copy the rm binary down to it.\n\tmov\teax,0100h\t\t; set function number\n\tmov\tebx,[rm_size]\t\t; get size of RM binary.\n\tadd\tebx,15\t\t\t; round up \n\tshr\tebx,4\t\t\t; convert to pages.\n\tint\tDPMI_INTR\t \t; do call.\n\tjc\t??error\t\t \t; check for error.\n\tmov\t[ RealModeSel ]\t, edx\n\tshl\teax,4\t\t\t; convert segment to offset.\n\tmov\t[RealModePtr],eax\t; save offset to global variable.\n\n\t; now lock the real mode memory that we allocated, just in\n\t; case it needs to be.\n\n\tmov\teax,0600h\t \t; function number.\n\tmov\tecx,[RealModePtr]\t; ecx must have start of memory.\n\tmov\tedi,[rm_size]\t \t; edi will have size of region in bytes.\n\tmov\t[RealModeSize],edi\t; save off the size for the unlock\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_RM_CODE\n\n\n\t; set up source and destination pointers for the copy.\n\tmov\teax,[RealModePtr]\n\tmov\tesi,[rm_ptr]\t\t; Set up our source pointer.\n\tor\t[InitFlags],IF_ALLOC_RM ; set successful\n\tmov\tedi,eax\t\t\t; put it into esi for copy.\n\tmov\tecx,[rm_size]\n\trep\tmovsb\t\t\t; write RM bin to RM memory.\n\n\n\t; restore esi to point to data and initialize some of it.\n\tmov\tesi,[RealModePtr]\n\tmov\teax,esi\t\t\t\t\t\t; get real mode 32 offset.\n\tshl\teax,12\t\t\t\t\t\t; make seg in high eax.\n\tmov\tax,[(TimerType PTR esi).CallRMIntOffset]\t; create RM addr of call chain.\n\tmov\t[(TimerType PTR esi).CallRMIntAddr],eax\t\t; save it for use in PM int.\n\n\tcmp\t[partial],0\n\tjne\t??partial_exit\n\n\t;==========================================================================\n\t; Get the protected mode interrupt vector keyboard.\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t;==========================================================================\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,IRQ0INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(TimerType PTR esi).OldPMIOffset],edx\t ; save offset.\n\tmov\t[(TimerType PTR esi).OldPMISelector],ecx ; save selector.\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 2503, cl = number of interrupt to get\n\t; output cf error, CX:DX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,IRQ0INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(TimerType PTR esi).OldRMI],ecx\n\n\t;==========================================================================\n\t; only separate method of installation is posible. \n\t; Now it is time to set the Protected mode interrupt Keyboard\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\tmov\teax, 0205h\n\tmov\tbl,IRQ0INTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Timer_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt Keyboard\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,IRQ0INTNUM\n\tmov\tecx,[RealModePtr]     \t\t\t; get address of real code int hand.\n\tshr\tecx,4\t\t\t\t\t; put segment in hi word.\n\tmov\tdx,[(TimerType PTR esi).CodeOffset]  ; Get address of code\n\tint\tDPMI_INTR\t\t\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\t; now set the frequency.\n\tmov\teax,[freq]\n\tor\t[InitFlags],IF_FUNCTIONAL\n\tpush\teax\n\tcall\tNEAR Set_Timer_Frequency\n\tmov\t[(TimerType PTR esi).SysTicks],0\t; Only place SysTicks in inited.\n\tmov\t[(TimerType PTR esi).UserTicks],0\t; Timers start off on same foot.\n\tpop\teax\n\tor\t[InitFlags],IF_RATE_CHANGE\n\n\t; we have finished with success.\n??partial_exit:\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n\tret\t\t\n\n\tENDP\n\n\n;***************************************************************************\n;* REMOVE_TIMER_INTERRUPT -- Removes the timer interrupt vectors.         *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tRemove_Timer_Interrupt C NEAR\n\tUSES\tebx,ecx,edx\n\n\t; check if timer was previosly install\n\tmov\tesi,[RealModePtr]\n\ttest\tesi,esi\n\tjz\t??error\n\n\n\ttest\t[InitFlags],IF_SET_VECTORS\n\tjz\t??vectors_not_set\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt Keyboard\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;====================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,IRQ0INTNUM\n\tmov\tedx,[(TimerType esi).OldRMI]\t\t; get the RM address.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t\t\t; do call.\n\tjc\t??error\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ0INTNUM\n\tmov\tecx,[(TimerType esi).OldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(TimerType esi).OldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n??vectors_not_set:\n\n\t; Call function to set the rate of the chip, ebx = rate.\n\ttest\t[InitFlags],IF_RATE_CHANGE\t; was it changed?\t\n\tjz\t??rate_not_changed\n\tmov\tebx,0FFFFh\t\t\t; back to 18.2 time per second.\n\tcall\tSet_Timer_Rate\t\t\t; call function to set timer.\n??rate_not_changed:\n\t; now free up the real mode memory.\n\ttest\t[InitFlags],IF_LOCKED_RM_CODE\n\tjz\t??rm_not_locked\n\n\tmov\teax , 0601h\n\tmov\tecx, [RealModePtr]\n\tmov\tedi, [RealModeSize]\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??rm_not_locked:\n\ttest\t[InitFlags],IF_ALLOC_RM\n\tjz\t??mem_not_allocated\n\tmov\teax , 0101h\n\tmov\tedx,[ RealModeSel ] \t\t; get physical address of real mode buffer.\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\n??mem_not_allocated:\n\n\t; Now we can unlock all stuff needed for the interrupt.  \n\t; Unlock code\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??code_not_locked:\n\n\t; Unlock data\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??data_not_locked:\n\n\t; we have finished with success.\n\tmov\teax,1\t\t\t; signal success.\n\tmov\t[RealModePtr],0\t\t; To say we can do it again sometime.\n\tmov\t[InitFlags],0\t\t; To say we can do it again sometime.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n\tret\n\n\tENDP\t\n\n\n\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;/////////////////////////////// Access routines //////////////////////////////////////\n\n\n;***************************************************************************\n;* GET_NUM_INTERRUPTS -- Returns the number of interrupts that have occured*\n;*                                                                         *\n;* INPUT: TRUE - returns num RM ints.                                      *\n;*        FALSE - return num PM ints.                                      *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/12/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Num_Interrupts C Near\n\tUSES\tesi\n\tARG\trealmode:DWORD\n\n\tmov\tesi,[RealModePtr]\n\tcmp\t[realmode],0\n\tje\t??prot_mode\n\tmov\teax,[(TimerType PTR esi).NumRMInts]\n\tret\n??prot_mode:\n\tmov\teax,[(TimerType PTR esi).NumPMInts]\n\tret\n\n\tENDP\n\n;***************************************************************************\n;* GET_SYSTEM_TICK_COUNT -- Returns the system tick count.                 *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_System_Tick_Count C Near\n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\txor\teax,eax\n\tcmp\tesi,0\n\tje\t??fini\n\tmov\teax,[(TimerType PTR esi).SysTicks]\n??fini:\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GET_USER_TICK_COUNT -- Get tick count of user clock.                    *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/12/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_User_Tick_Count C Near\n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(TimerType PTR esi).UserTicks]\n\tret\n\n\tENDP\n\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;/////////////////////////////// Interrupt routines ///////////////////////////////////\n\n; These macros are placed here to handle to duplicate code in 2 methods in\n; the Timer_Interrupt function.\n\n\nMACRO\tSET_DS_ESI_TO_RM\n\t; Sets DS : ES to point to DGROUP _DATA selector\n\t; Set esi to point to RealModePtr\n\t; Corrupts eax\n\n\tmov\tax , _DATA\n\tmov\tds , ax\n\tmov\tes , ax\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\nENDM\n\n\t\nMACRO\tINCREMENT_TIMERS\n\t; Expects ESI to point to real mode memory.\n\n\tinc\t[(TimerType PTR esi).NumPMInts]\t\t; For testing.\n\n\tmov\teax,[(TimerType PTR esi).TrueRate]\t; Get the rate of the PC clock.\n\tsub\t[(TimerType PTR esi).SysCurRate],ax\t; Sub from our rate counter.\n\tja\t??end_sys\t\t\t\t; If !below zero, do not inc.\n\tmov\tebx,[(TimerType PTR esi).SysRate]\t; Get rate of timer.\n\tmov\tecx,[(TimerType PTR esi).SysError]\t; Get amount of error.\n\tadd\t[(TimerType PTR esi).SysCurRate],bx\t; Add rate to the current.\n\tsub\t[(TimerType PTR esi).SysCurError],cx\t; Subtract err from error count.\n\tjb\t??error_adj_sys\t\t\t\t; If wrapped don't inc.\n\tinc\t[(TimerType PTR esi).SysTicks]\t; increment the timer.\n\tjmp\tshort ??end_sys\n??error_adj_sys:\n\tadd\t[(TimerType PTR esi).SysCurError],bx\t; reajust the error by timer rate.\n??end_sys:\n\tsub\t[(TimerType PTR esi).UserCurRate],ax ; Sub from our rate counter.\n\tja\t??end_user\t     \t\t\t; If !below zero, do not inc.\n\tmov\tebx,[(TimerType PTR esi).UserRate]\t; Get rate of timer.\n\tmov\tecx,[(TimerType PTR esi).UserError]\t; Get amount of error.\n\tadd\t[(TimerType PTR esi).UserCurRate],bx\t; Add rate to the current.\n\tsub\t[(TimerType PTR esi).UserCurError],cx; Subtract err from error count.\n\tjb\t??error_adj_user       \t\t\t; If wrapped don't inc.\n\tinc\t[(TimerType PTR esi).UserTicks]\t; increment the timer.\n\tjmp\tshort ??end_user\n??error_adj_user:\n\tadd\t[(TimerType PTR esi).UserCurError],bx; reajust the error by timer rate.\n??end_user:\n\nENDM\n\n\nMACRO\tENABLE_CLOCK_INT\n\t; Signal 8259 that we are done and that it can bug us again.\n\t; Corrupts al.\n\n\tmov\tal,CLEARISR\t; Signal EOI\n\tsti\t\t\t; enable interrupts.\n\tout\tINTCHIP0,al \t; 8259 interrupt chip controller 0\nENDM\n\nLABEL \tLockedCodeStart\tBYTE\n\n;***************************************************************************\n;* TIMER_INTERRUPT -- Temp routine to mimic a timer system calling ours     *\n;*   This is a temp routine to call our tick count routine.  It will be    *\n;*   replaced once another timer system is put in (such as HMI).           *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tTimer_Interrupt\tNear\n;////////////////////////////// Call prot mode interrupt vector ////////////////////////////////////////\n; This routine will do what it needs to, \n; then it will decide if the old vector should be called.\n; if so, it calls it and never returns to this function.\n; if not, we do our own return.\n; the method for doing this is found in:\n; \"Phar Lap  TNT DOS-Extender Reference Manual, First Addition, p. 142\"\n; It says:\n; 1 - Execute a PUSHFD to save the current flags.\n; 2 - Dec the stack ptr by 8 bytes to save room for the addr of orig handler\n; 3 - Push register I use.\n; 4 - Do any processing.\n; 5 - Put the address of the original handler in the reserved slot.\n; 6 - Pop saved register values\n; 7 - Execute an IRETD to transfer control to original handler.\n\n\tpushfd\t\t\t; Step 1\n\tsub\tesp,8\t\t; Step 2\n\tpush\tebp\t\t; Step 3\n\tmov\tebp,esp\t\t; Set up a stack frame to know where to poke address.\n\n\t; Step 3 continued.  Push used varables.\n\tpushad\n\tpush\tfs gs es ds\n\n\n\t; Step 4.  Now do processing before I chain.\n\t; Set up ds:esi to point at start of real memory block (data is first)\n\n\tcall far Timer_Interrupt_Func\n\n\tSET_DS_ESI_TO_RM\t\t\t; Set ds:esi to point to real mode stuff.\n\n\t; Now take care of calling the old DOS timer interrupt vector.\n\t; This must be the last operation of this module since if we call\n\t; DOS, we will never return.\n\tmov\tax,[(TimerType PTR ds:esi).DosAdder] \n\tadd\t[(TimerType PTR esi).DosFraction],ax\n\tjnc\t??no_dos_call\t\t\t\t\t; if not, skip the call.\n\n\t; Tell RM that we forced the int and not to update timers.\n\tmov\t[(TimerType PTR esi).PMIssuedInt],1\t\t; Make it TRUE\n\n\t; Step 5.\n\t; Now it is time to set up for the call by returning by poking\n\t; the old interrupt handle address in.\n\tmov\teax,[(TimerType PTR esi).OldPMIOffset]\t\t; Get orig offset.\n\tmov\tebx,[(TimerType PTR esi).OldPMISelector]\t; Get orig selector.\n\tmov\t[ss:ebp+4],eax\t\t\t\t\t; Poke offset.\n\tmov\t[ss:ebp+8],ebx\t\t\t\t\t; Poke selector.\n\n\t; Step 6.\n\tpop\tds es gs fs\n\tpopad\n\tpop\tebp  \n\n\t; Step 7.\n\tiretd\t\t\t\t; transfer control to original handler.\n\n??no_dos_call:\n\n\tENABLE_CLOCK_INT\n\n\t; Restore all registers.\n\tpop\tds es gs fs\n\tpopad\n\n\tpop\tebp  \n\tadd\tesp,8\n\tpopfd\t\n\n\tiretd\n;////////////////////////////// Call prot mode interrupt vector ////////////////////////////////////////\n;//////////////////////////////////////////////////////////////////////////////////////////////////////\n\tENDP\n\n\n\n;***************************************************************************\n;* TIMER_INTERRUPT_FUNC -- Handles core timer code                         *\n;*                                                                         *\n;* This function exists so that we can call it from the core HMI driver    *\n;* code when our timer interrupt has not been installed.\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/14/1995 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tTimer_Interrupt_Func C Far\n\tpushfd\t\t\t\t\t; save off the flags\n\tpushad\t\t\t\t\t; save off the main registers\n\tpush\tfs gs es ds\t\t\t; save off the seg registers\n\t\n\tSET_DS_ESI_TO_RM\t\t\t; Set ds:esi to point to real mode stuff.\n\tINCREMENT_TIMERS\t\t\t; Increment Westwoods timers\t\n\n\tpop\tds es gs fs\n\tpopad\n\tpopfd\n\tretf\n\tENDP\n\nLABEL \tLockedCodeEnd\t\tBYTE\n\n;***************************************************************************\n;* DISABLE_TIMER_INTERRUPT_ONLY -- Disables at the hardware level          *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/07/1995 DRD : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tDisable_Timer_Interrupt C Near\n\tpush\teax\n\tpushf\n\n\tsti\t\t\t; disable all interrupts if not disabled\n\tin\tal,021h\t\t; read interrupt Mask register bits 0-7\n\t\t\t\t; apply to irq's 0-7\n\t\t\t\t;   value 0 of enabled\n\t\t\t\t;   value 1 of disabled\n\tor\tal,001h\t\t; setup to disable irq 0\n\tout\t021h,al\t\t; disable irq 0\n\n\tpopf\t\t\t; possibly enable all interrupts (except 0)\n\tpop\teax\n\tretf\n\tENDP\n\n\n;***************************************************************************\n;* ENABLE_TIMER_INTERRUPT_ONLY -- Enables at the hardware level            *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/07/1995 DRD : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tEnable_Timer_Interrupt C Near\n\tpush\teax\n\tpushf\n\n\tsti\t\t\t; disable all interrupts if not disabled\n\tin\tal,021h\t\t; read interrupt Mask register bits 0-7\n\t\t\t\t; apply to irq's 0-7\n\t\t\t\t;   value 0 of enabled\n\t\t\t\t;   value 1 of disabled\n\tand\tal,0FEh\t\t; setup to enable irq 0\n\tout\t021h,al\t\t; enable irq 0\n\n\tpopf\t\t\t; possibly enable all interrupts\n\tpop\teax\n\tretf\n\tENDP\n\n\n\tEND\n\n\n\n"
  },
  {
    "path": "WWFLAT32/TIMER/TIMERA.BAK",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Timer stuff                              *\n;*                                                                         *\n;*                    File Name : TIMERA.ASM                               *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : July 6, 1994                             *\n;*                                                                         *\n;*                  Last Update : March 14, 1995   [PWG]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Get_RM_Timer_Address -- Return address of real mode code for copy.    *\n;*   Get_RM_Timer_Size -- return size of real mode timer code.             *\n;*   Increment_Tick_Count -- Increments WW system timer.                   *\n;*   Timer_Interrupt -- Temp routine to mimic a timer system calling our.  *\n;*   Install_Timer_Interrupt -- Installs the timer interrupt routine.      *\n;*   Remove_Timer_Interrupt -- Removes the timer interrupt vectors.       **\n;*   Set_Timer_Frequency -- Set the frequency of the timer.                *\n;*   Set_Timer_Rate -- Set the rate of the timer.                          *\n;*   Get_System_Tick_Count -- Returns the system tick count.               *\n;*   Get_User_Tick_Count -- Get tick count of user clock.                  *\n;*   Increment_Timers -- Increments system and user timers.                *\n;*   Get_Num_Interrupts -- Returns the number of interrupts that have occured*\n;*   Timer_Interrupt_Func -- Handles core timer code                       *\n;*   Disable_Timer_Interrupt -- Disables at the hardware level             *\n;*   Enable_Timer_Interrupt -- Enables at the hardware level               *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\nDPMI_INTR\tequ\t31h\t\nTRUE\t\tequ\t1\t\t\t; Boolean 'true' value\nFALSE\t\tequ\t0\t\t\t; Boolean 'false' value\n\nLOCALS ??\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////////// Equates ////////////////////////////////////////\n\nSYSTEM_TIMER_FREQ\tequ\t60\t; Frequency of system timer.\n\n;********************************************************************\n; There are two ways to call our interrupt chain in protected mode.  \n; The obvious way it to call the address that we replaced in the\n; PM interrupt chain.  This method is a little difficult but works and\n; should always work.\n\n\n;********************************************************************\n; The RM and PM interrupts can be installed at the same time or seperately.\n; Installing at the same time is the best method, the other method\n; can be used to faciliated debugging when you only want one or the other\n; called.  Both methods work.\n; -SKB July 21, 1994.\nINSTALL_SEPERATE\tequ\tFALSE\n\n\nINTCHIP0\tEQU\t20h\t\t; 8259 interrupt chip controller 0\nCLEARISR\tEQU\t20h\t\t; Value to write to 8259 to reenable interrupts.\nIRQ0INTNUM\tEQU\t08h\t\t; IRQ0 interrupt vector number.\nDOS_SYS_CALL\tEQU\t21h\t\t; to do TNT DOS-XNDR system calls.\nLOCK_PAGES\tEQU\t5\t\t; Lock pages subfunction using DX_MEM_MGT\nUNLOCK_PAGES\tEQU\t6\t\t; Unlock pages subfunction using DX_MEM_MGT\n\nTIMER_CONST\tEQU\t1193180\t\t; TIMER_CONST / FREQ = rate to set 8259 chip\n\nTIMERCMDREG\tEQU\t043H\t\t; timer command register port.\nTIMER0PORT\tEQU\t040H\t\t; timer channel 0 port\nTIMETYPE\tEQU\t036H\t\t; type of timer.\n\t;  36H = 0011 0110\t\t\t    \n\t;        --         select channel 0\t\t\t    \n\t;          --       read/load low byte then high byte for timer\t\t\t    \n\t;             ---   timer mode 3\t\t\t    \n\t;                -  0 - binary , 1 - BCD data\n\t\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////////// Structs ////////////////////////////////////////\n\n\n; Structure of memory in real mode handler.\n; This is at the very start of the real mode code.\n; This information may not change unless the real mode version is also changed.\n\nSTRUC TimerType\n; For speed, PM uses a DD while RM used DW\n; For speed, SysRate and SysError are DD in PM and are DW in real mode.\n\n\tTrueRate\t\tDD\t?\t; True rate of clock. (only use word)\n    \tSysTicks\t\tDD\t?\t; Tick count of timer.\n\tSysRate\t\t\tDD\t?\t; Desired rate of timer.\n\tSysError\t \tDD\t?\t; Amount of error in clock rate for desired frequency.\n\tSysCurRate\t \tDW\t?\t; Keeps track of when to increment timer.\n\tSysCurError\t\tDW\t?\t; Keeps track of amount of error in timer.\n\n    \tUserTicks\t\tDD\t?\t; Tick count of timer.\n\tUserRate\t \tDD\t?\t; Desired rate of timer.\n\tUserError\t \tDD\t?\t; Amount of error in clock rate for desired frequency.\n\tUserCurRate\t \tDW\t?\t; Keeps track of when to increment timer.\n\tUserCurError\t\tDW\t?\t; Keeps track of amount of error in timer.\n\n\tDosAdder\t\tDW\t? \t; amount to add to DosFraction each interrupt.\n\tDosFraction\t\tDW\t?\t; Call dos when overflowed.\n\n\tOldRMI\t\t\tDD\t?\t; The origianl RM interrupt seg:off.\n\tOldPMIOffset\t\tDD\t?\t; The origianl PM interrupt offset\t\t\n\tOldPMISelector\t\tDD\t?\t; The original PM interrupt segment.\n\n\tCodeOffset\t\tDW\t?\t; Offset of the code in the RM stuff.\n\tCallRMIntOffset\t\tDW\t?\t; Offset of function to call DOS timer interrupt.\n\tCallRMIntAddr\t\tDD\t?\t; PM address of CallRealIntOffset for speed.\n\n\tPMIssuedInt\t\tDD\t0\t; PM signals RM to just call Int chain.\t\n\n; These are just used for information on testing.  When all is done, they can\n; be removed, but why?  The don't add too much proccessing time and can\n; be useful.\n\tNumPMInts\t\tDD\t?\t; Number of PM interrupts\n\tNumRMInts\t\tDD\t?\t; Number of RM interrupts.\n\nENDS\n\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;/////////////////////////////////// Prototypes //////////////////////////////////////\n\nGLOBAL\t \tGet_System_Tick_Count:NEAR\nGLOBAL\t \tGet_User_Tick_Count:NEAR\nGLOBAL\t \tGet_RM_Timer_Address:NEAR\nGLOBAL\t \tGet_RM_Timer_Size:NEAR\nGLOBAL\t \tSet_Timer_Frequency:NEAR\nGLOBAL\t \tTimer_Interrupt:NEAR\nGLOBAL\t \tInstall_Timer_Interrupt:NEAR\nGLOBAL\t \tRemove_Timer_Interrupt:NEAR\nGLOBAL\t \tGet_Num_Interrupts:NEAR\nGLOBAL\t\tTimer_Interrupt_Func:FAR\nGLOBAL\t\tDisable_Timer_Interrupt:NEAR\nGLOBAL\t\tEnable_Timer_Interrupt:NEAR\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;//////////////////////////////////////// Data ////////////////////////////////////////\n\tDATASEG\n\n; The current time we will just include the real mode stuff\n; into the protected mode code and then copy it down.  The C side of\n; this will handle this method or reading it off of disk in the real\n; method.\n\nLABEL \tRealBinStart\tBYTE\ninclude \"timereal.ibn\"\nLABEL\tRealBinEnd\tBYTE\n\n\n\n\nLABEL\tLockedDataStart\tBYTE\t\nRealModeSel\tDD\t0\nRealModePtr\tDD\t0\t\t; Pointer to real mode memory.\nRealModeSize\tDD\t0\t\t; Pointer to real mode memory.\nLABEL\tLockedDataEnd\tBYTE\n\n\t\nInitFlags\tDD\t0\t\t; Flags to indicate what has been initialized.\n\n; InitFlags that are set to have a fully functional interrupt.\nIF_ALLOC_RM\t\tequ\t1h\t\t; Allocation of RM was successful.\nIF_SET_VECTORS\t\tequ\t2h\t\t; Vectors have been set.\nIF_LOCKED_PM_CODE\tequ\t4h\t\t; Locked PM code for DPMI.\nIF_LOCKED_PM_DATA\tequ\t8h\t\t; Locked PM code for DPMI.\nIF_RATE_CHANGE\t\tequ\t10h\t\t; Timer rate was changed.\nIF_FUNCTIONAL\t\tequ\t20h\t\t; Timer is in and functional.\nIF_LOCKED_RM_CODE\tequ\t40h\t\t; Timer is in and functional.\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;//////////////////////////////////////// Code ////////////////////////////////////////\n\n\tCODESEG\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;/////////////////////////////// Init routines ////////////////////////////////////////\n\n;***************************************************************************\n;* GET_RM_TIMER_ADDRESS -- Return address of real mode code for copy.      *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Timer_Address C Near\n\n\tmov\teax, OFFSET RealBinStart\n\tret\n\n\tENDP\n\n;***************************************************************************\n;* GET_RM_TIMER_SIZE -- return size of real mode timer code.               *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_Timer_Size C Near\n\n\tmov\teax, OFFSET RealBinEnd - OFFSET RealBinStart\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* SET_TIMER_RATE -- Set the rate of the timer.                            *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:  ebx = rate to set timer were rate = 1193180 / freq              *\n;*                                                                         *\n;* OUTPUT: none                                                            *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/11/1994 SKB : Created.                                             *\n;*=========================================================================*\nPROC\tSet_Timer_Rate Near\n\n\tpush\teax\n\tpushf\t\t\t\t\t; to save int enable flag\t\n\tcli\t\t\t\t\t; disable interupts while setting up swapper\n\n\tmov\tal,TIMETYPE\t\t\t; setup to modify timer 0\n\tout\tTIMERCMDREG,al\t\t\t; send command.\n\tmov\teax,ebx\t\t\t\t; get rate.\n\tout\tTIMER0PORT,al\t\t\t; output low byte\n\tmov\tal,ah\n\tout\tTIMER0PORT,al\t\t\t; output high byte\n\n\tsti\n\tpopf\t\t\t\t\t; get int enable flag.\n\tpop\teax\n\n\tret\nENDP\tSet_Timer_Rate\n\n;***************************************************************************\n;* SET_TIMER_FREQUENCY -- Set the frequency of the timer.                  *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:  INT Frequency of user timer.                                    *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\nPROC\tSet_Timer_Frequency C NEAR\n\tUSES\teax,ebx,ecx,edx\n\tARG\tfreq:DWORD\n\tLOCAL\tclockrate:DWORD\n\tLOCAL\tclockfreq:DWORD\n\n\ttest\t[InitFlags],IF_FUNCTIONAL\t; Is our timer system installed?\n\tjz\t??timer_not_installed\t\t; if not, this is not legal.\n\n\n\t; Find out the greater of the frequencies (user or system.)\n\t; Assign the True rate value based of of that.\n\t; store the max frequency in ecx.\n\tmov\tecx,[freq]\t\t\t; get user frequency.\n\tcmp\tecx,SYSTEM_TIMER_FREQ\t\t; compare it with system frequency\n\tjg\t??user_is_fastest\t\t; is user frequency faster?\n\tmov\tecx,SYSTEM_TIMER_FREQ\t\t; no, set clock freq to system frequency.\n??user_is_fastest:   \n\n\t; now get the rate that the clock will be set at.\n\t; ecx is still max frequency.\n\tmov\tesi,[RealModePtr]\n\n\tmov\teax,TIMER_CONST\t\t\t; get the clock constant value.\n\txor\tedx,edx\t\t\t\t; zero for divide.\n\tdiv\tecx\t\t\t\t; rate = TC/freq => eax = eax/ecx;\n\tmov\t[(TimerType PTR esi).TrueRate],eax ; Set our true rate.\n\tmov\tebx,eax\t\t\t\t; save for later. DO NOT USE UNTIL CALL\n\n\t; Set up variables to call DOS correctly.\n\t; When DosFraction overflows, DOS is called.\n\tmov\t[(TimerType PTR esi).DosAdder],ax\t; Init count to until call dos.\n\tmov\t[(TimerType PTR esi).DosFraction],0\t; init the fraction.\n\n\t; now set up the system timer.\n\tmov\tecx,SYSTEM_TIMER_FREQ\t\t\t; get frequency.\n\tmov\teax,TIMER_CONST\t\t\t\t; get constant for formula rate=C/freq.\n\txor\tedx,edx\t\t\t\t   \t; make sure zero for divide\n\tdiv\tecx\t\t\t\t\t; calculate rate\n\tmov\t[(TimerType PTR esi).SysCurRate],ax\t; Init current stuff.\n\tmov\t[(TimerType PTR esi).SysCurError],ax\t; Init current stuff.\n\tmov\t[(TimerType PTR esi).SysRate],eax\t; Save rate of timer\n\tmov\t[(TimerType PTR esi).SysError],edx\t; Save error of timer\n\t; Do not set SysTicks to zero since it always has the same frequency.  It\n\t; should be zero out only when the system clock is installed.\n\n\t; now set up the user timer.\n\tmov\tecx,[freq]\t\t\t\t; get frequency of user timer.\n\tmov\teax,TIMER_CONST\t\t\t\t; get constant for formula rate=C/freq.\n\txor\tedx,edx\t\t\t\t   \t; make sure zero for divide\n\tdiv\tecx\t\t\t\t\t; calculate rate\n\tmov\t[(TimerType PTR esi).UserCurRate],ax\t; Init current stuff.\n\tmov\t[(TimerType PTR esi).UserCurError],ax; Init current stuff.\n\tmov\t[(TimerType PTR esi).UserRate],eax\t; Save rate of timer\n\tmov\t[(TimerType PTR esi).UserError],edx\t; Save error of timer\n\tmov\t[(TimerType PTR esi).UserTicks],0\t; User timer sets to zero when freq change.\n\n\t; Call function to set the rate of the chip, ebx = rate from above.\n\tcall\tSet_Timer_Rate\n\n??timer_not_installed:\n\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* INSTALL_TIMER_Interrupt -- Installs the timer interrupt routine.        *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:  VOID * pointer to RM binary in PM memory.                       *\n;*         LONG Size of RM binary.                                         *\n;*         INT  frequency of user timer.                                   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tInstall_Timer_Interrupt C Near\n\tUSES\tebx,ecx,edx\n\tARG\trm_ptr:DWORD\n\tARG\trm_size:DWORD\n\tARG\tfreq:DWORD\n\tARG\tpartial:DWORD\n\n\t; Are they attempting to set timer again?\n\tcmp\t[RealModePtr],0\n\tjnz\t??error\n\n\t; Make sure all flags are cleared.\n\tcmp\t[InitFlags],0\n\tjnz\t??error\n\n\t; Before setting the interrupt vectors, the code needs to be locked\n\t; for DPMI compatability.  Any code or data accessed must be lockded\n\t; so that no page faults accure during an interrupt.\n\t; First lock the code, then the data.  The stack will already be locked.\n\t; The real mode code is also already locked be default.\n\t; To lock a page set up registers :\n\t; AX = 0600h\n\t; BX:CX\t= starting linear address of memory block\n\t; SI:DI = size of region\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_CODE\n\n\tmov\teax,0600h\t\t\t; function number.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edi will have size of region in bytes.\n\tshld\tebx,ecx,16\n\tsub\tedi, ecx\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_PM_DATA\n\n\t; now allocate real mode memory and copy the rm binary down to it.\n\tmov\teax,0100h\t\t; set function number\n\tmov\tebx,[rm_size]\t\t; get size of RM binary.\n\tadd\tebx,15\t\t\t; round up \n\tshr\tebx,4\t\t\t; convert to pages.\n\tint\tDPMI_INTR\t \t; do call.\n\tjc\t??error\t\t \t; check for error.\n\tmov\t[ RealModeSel ]\t, edx\n\tshl\teax,4\t\t\t; convert segment to offset.\n\tmov\t[RealModePtr],eax\t; save offset to global variable.\n\n\t; now lock the real mode memory that we allocated, just in\n\t; case it needs to be.\n\n\tmov\teax,0600h\t \t; function number.\n\tmov\tecx,[RealModePtr]\t; ecx must have start of memory.\n\tmov\tedi,[rm_size]\t \t; edi will have size of region in bytes.\n\tmov\t[RealModeSize],edi\t; save off the size for the unlock\n\tshld\tebx,ecx,16\n\tshld\tesi,edi,16\n   \tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\tor\t[InitFlags],IF_LOCKED_RM_CODE\n\n\n\t; set up source and destination pointers for the copy.\n\tmov\teax,[RealModePtr]\n\tmov\tesi,[rm_ptr]\t\t; Set up our source pointer.\n\tor\t[InitFlags],IF_ALLOC_RM ; set successful\n\tmov\tedi,eax\t\t\t; put it into esi for copy.\n\tmov\tecx,[rm_size]\n\trep\tmovsb\t\t\t; write RM bin to RM memory.\n\n\n\t; restore esi to point to data and initialize some of it.\n\tmov\tesi,[RealModePtr]\n\tmov\teax,esi\t\t\t\t\t\t; get real mode 32 offset.\n\tshl\teax,12\t\t\t\t\t\t; make seg in high eax.\n\tmov\tax,[(TimerType PTR esi).CallRMIntOffset]\t; create RM addr of call chain.\n\tmov\t[(TimerType PTR esi).CallRMIntAddr],eax\t\t; save it for use in PM int.\n\n\tcmp\t[partial],0\n\tjne\t??partial_exit\n\n\t;==========================================================================\n\t; Get the protected mode interrupt vector keyboard.\n\t; input ax = 0204\n\t; bl = number of interrupt to get\n\t; output: cf error\n\t;==========================================================================\n\tmov\teax,0204h\t\t; Get proteced mode\n\tmov\tbl,IRQ0INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tmov\t[(TimerType PTR esi).OldPMIOffset],edx\t ; save offset.\n\tmov\t[(TimerType PTR esi).OldPMISelector],ecx ; save selector.\n\n\t;==========================================================================\n\t; Get the real mode interrupt vector keyboard\n\t; input ax = 2503, cl = number of interrupt to get\n\t; output cf error, CX:DX = address (seg:off) of RM int handler routine.\n\t; cl set above\n\t;==========================================================================\n\tmov\teax,0200h\n\tmov\tbl,IRQ0INTNUM\t\t; IRQ1 interrupt vector\n\tint\tDPMI_INTR\t\t; do call.\n\tjc\t??error\n\tshl \tedx,16\n\tshld\tecx,edx,16\n\tmov\t[(TimerType PTR esi).OldRMI],ecx\n\n\t;==========================================================================\n\t; only separate method of installation is posible. \n\t; Now it is time to set the Protected mode interrupt Keyboard\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\tmov\teax, 0205h\n\tmov\tbl,IRQ0INTNUM\n\tmov\tcx , cs\n\tlea\tedx, [Timer_Interrupt] ; get address of protected code int hand.\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt Keyboard\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,IRQ0INTNUM\n\tmov\tecx,[RealModePtr]     \t\t\t; get address of real code int hand.\n\tshr\tecx,4\t\t\t\t\t; put segment in hi word.\n\tmov\tdx,[(TimerType PTR esi).CodeOffset]  ; Get address of code\n\tint\tDPMI_INTR\t\t\t\t; do call.\n\tjc\t??error\n\tor\t[InitFlags],IF_SET_VECTORS\n\n\t; now set the frequency.\n\tmov\teax,[freq]\n\tor\t[InitFlags],IF_FUNCTIONAL\n\tpush\teax\n\tcall\tNEAR Set_Timer_Frequency\n\tmov\t[(TimerType PTR esi).SysTicks],0\t; Only place SysTicks in inited.\n\tmov\t[(TimerType PTR esi).UserTicks],0\t; Timers start off on same foot.\n\tpop\teax\n\tor\t[InitFlags],IF_RATE_CHANGE\n\n\t; we have finished with success.\n??partial_exit:\n\tmov\teax,1\t\t\t; signal success.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n\tret\t\t\n\n\tENDP\n\n\n;***************************************************************************\n;* REMOVE_TIMER_INTERRUPT -- Removes the timer interrupt vectors.         *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tRemove_Timer_Interrupt C NEAR\n\tUSES\tebx,ecx,edx\n\n\t; check if timer was previosly install\n\tmov\tesi,[RealModePtr]\n\ttest\tesi,esi\n\tjz\t??error\n\n\n\ttest\t[InitFlags],IF_SET_VECTORS\n\tjz\t??vectors_not_set\n\t;==========================================================================\n\t; Now it is time to set the real Interrupt Keyboard\n\t; ax = function number (0201\n\t; bl = number of interrupt to set\n\t; cx:dx = address of RM interrupt handler\n\t;====================================================================\n\n\tmov\teax, 0201h\n\tmov\tbl,IRQ0INTNUM\n\tmov\tedx,[(TimerType esi).OldRMI]\t\t; get the RM address.\n\tshld\tecx , edx , 16\n\tint\tDPMI_INTR\t\t\t\t; do call.\n\tjc\t??error\n\n\t;==========================================================================\n\t; Now it is time to set the Protected mode interrupt\n\t; ax = function number (0205\n\t; bl = number of interrupt to set\n\t; cx:edx = address of PM interrupt handler\n\t;==========================================================================\n\n\tmov\teax, 0205h\n\tmov\tbl,IRQ0INTNUM\n\tmov\tecx,[(TimerType esi).OldPMISelector] \t; Get PM segment to put int ds later.\n\tmov\tedx,[(TimerType esi).OldPMIOffset] \t; Get PM offset\n\tint\tDPMI_INTR\t\t  ; do call.\n\tjc\t??error\n\n??vectors_not_set:\n\n\t; Call function to set the rate of the chip, ebx = rate.\n\ttest\t[InitFlags],IF_RATE_CHANGE\t; was it changed?\t\n\tjz\t??rate_not_changed\n\tmov\tebx,0FFFFh\t\t\t; back to 18.2 time per second.\n\tcall\tSet_Timer_Rate\t\t\t; call function to set timer.\n??rate_not_changed:\n\t; now free up the real mode memory.\n\ttest\t[InitFlags],IF_LOCKED_RM_CODE\n\tjz\t??rm_not_locked\n\n\tmov\teax , 0601h\n\tmov\tecx, [RealModePtr]\n\tmov\tedi, [RealModeSize]\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??rm_not_locked:\n\ttest\t[InitFlags],IF_ALLOC_RM\n\tjz\t??mem_not_allocated\n\tmov\teax , 0101h\n\tmov\tedx,[ RealModeSel ] \t\t; get physical address of real mode buffer.\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\n\n??mem_not_allocated:\n\n\t; Now we can unlock all stuff needed for the interrupt.  \n\t; Unlock code\n\ttest\t[InitFlags],IF_LOCKED_PM_CODE\n\tjz\t??code_not_locked\n\tmov\teax , 0601h\n\tmov\tecx,OFFSET LockedCodeStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedCodeEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n??code_not_locked:\n\n\t; Unlock data\n\ttest\t[InitFlags],IF_LOCKED_PM_DATA\n\tjz\t??data_not_locked\n\tmov\tax,0601h\t\t\t\t; set es to descriptor of data.\n\tmov\tecx,OFFSET LockedDataStart\t; ecx must have start of memory.\n\tmov\tedi,OFFSET LockedDataEnd\t; edx will have size of region in bytes.\n\tsub\tedi,ecx\t\t\t\t;  - figure size.\n\tshld\tebx , ecx , 16\n\tshld\tesi , edi , 16\n\tint\tDPMI_INTR\t\t\t; do call.\n\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n??data_not_locked:\n\n\t; we have finished with success.\n\tmov\teax,1\t\t\t; signal success.\n\tmov\t[RealModePtr],0\t\t; To say we can do it again sometime.\n\tmov\t[InitFlags],0\t\t; To say we can do it again sometime.\n\tret\n??error:\n       \txor\teax,eax\t\t\t; signal an error.\n\tret\n\n\tENDP\t\n\n\n\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;/////////////////////////////// Access routines //////////////////////////////////////\n\n\n;***************************************************************************\n;* GET_NUM_INTERRUPTS -- Returns the number of interrupts that have occured*\n;*                                                                         *\n;* INPUT: TRUE - returns num RM ints.                                      *\n;*        FALSE - return num PM ints.                                      *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/12/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_Num_Interrupts C Near\n\tUSES\tesi\n\tARG\trealmode:DWORD\n\n\tmov\tesi,[RealModePtr]\n\tcmp\t[realmode],0\n\tje\t??prot_mode\n\tmov\teax,[(TimerType PTR esi).NumRMInts]\n\tret\n??prot_mode:\n\tmov\teax,[(TimerType PTR esi).NumPMInts]\n\tret\n\n\tENDP\n\n;***************************************************************************\n;* GET_SYSTEM_TICK_COUNT -- Returns the system tick count.                 *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_System_Tick_Count C Near\n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(TimerType PTR esi).SysTicks]\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GET_USER_TICK_COUNT -- Get tick count of user clock.                    *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/12/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_User_Tick_Count C Near\n\tUSES\tesi\n\n\tmov\tesi,[RealModePtr]\n\tmov\teax,[(TimerType PTR esi).UserTicks]\n\tret\n\n\tENDP\n\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;/////////////////////////////// Interrupt routines ///////////////////////////////////\n\n; These macros are placed here to handle to duplicate code in 2 methods in\n; the Timer_Interrupt function.\n\n\nMACRO\tSET_DS_ESI_TO_RM\n\t; Sets DS : ES to point to DGROUP _DATA selector\n\t; Set esi to point to RealModePtr\n\t; Corrupts eax\n\n\tmov\tax , _DATA\n\tmov\tds , ax\n\tmov\tes , ax\n\tmov\tesi,[RealModePtr]\t\t; Point to start of RM data.\nENDM\n\n\t\nMACRO\tINCREMENT_TIMERS\n\t; Expects ESI to point to real mode memory.\n\n\tinc\t[(TimerType PTR esi).NumPMInts]\t\t; For testing.\n\n\tmov\teax,[(TimerType PTR esi).TrueRate]\t; Get the rate of the PC clock.\n\tsub\t[(TimerType PTR esi).SysCurRate],ax\t; Sub from our rate counter.\n\tja\t??end_sys\t\t\t\t; If !below zero, do not inc.\n\tmov\tebx,[(TimerType PTR esi).SysRate]\t; Get rate of timer.\n\tmov\tecx,[(TimerType PTR esi).SysError]\t; Get amount of error.\n\tadd\t[(TimerType PTR esi).SysCurRate],bx\t; Add rate to the current.\n\tsub\t[(TimerType PTR esi).SysCurError],cx\t; Subtract err from error count.\n\tjb\t??error_adj_sys\t\t\t\t; If wrapped don't inc.\n\tinc\t[(TimerType PTR esi).SysTicks]\t; increment the timer.\n\tjmp\tshort ??end_sys\n??error_adj_sys:\n\tadd\t[(TimerType PTR esi).SysCurError],bx\t; reajust the error by timer rate.\n??end_sys:\n\tsub\t[(TimerType PTR esi).UserCurRate],ax ; Sub from our rate counter.\n\tja\t??end_user\t     \t\t\t; If !below zero, do not inc.\n\tmov\tebx,[(TimerType PTR esi).UserRate]\t; Get rate of timer.\n\tmov\tecx,[(TimerType PTR esi).UserError]\t; Get amount of error.\n\tadd\t[(TimerType PTR esi).UserCurRate],bx\t; Add rate to the current.\n\tsub\t[(TimerType PTR esi).UserCurError],cx; Subtract err from error count.\n\tjb\t??error_adj_user       \t\t\t; If wrapped don't inc.\n\tinc\t[(TimerType PTR esi).UserTicks]\t; increment the timer.\n\tjmp\tshort ??end_user\n??error_adj_user:\n\tadd\t[(TimerType PTR esi).UserCurError],bx; reajust the error by timer rate.\n??end_user:\n\nENDM\n\n\nMACRO\tENABLE_CLOCK_INT\n\t; Signal 8259 that we are done and that it can bug us again.\n\t; Corrupts al.\n\n\tmov\tal,CLEARISR\t; Signal EOI\n\tsti\t\t\t; enable interrupts.\n\tout\tINTCHIP0,al \t; 8259 interrupt chip controller 0\nENDM\n\nLABEL \tLockedCodeStart\tBYTE\n\n;***************************************************************************\n;* TIMER_INTERRUPT -- Temp routine to mimic a timer system calling ours     *\n;*   This is a temp routine to call our tick count routine.  It will be    *\n;*   replaced once another timer system is put in (such as HMI).           *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tTimer_Interrupt\tNear\n;////////////////////////////// Call prot mode interrupt vector ////////////////////////////////////////\n; This routine will do what it needs to, \n; then it will decide if the old vector should be called.\n; if so, it calls it and never returns to this function.\n; if not, we do our own return.\n; the method for doing this is found in:\n; \"Phar Lap  TNT DOS-Extender Reference Manual, First Addition, p. 142\"\n; It says:\n; 1 - Execute a PUSHFD to save the current flags.\n; 2 - Dec the stack ptr by 8 bytes to save room for the addr of orig handler\n; 3 - Push register I use.\n; 4 - Do any processing.\n; 5 - Put the address of the original handler in the reserved slot.\n; 6 - Pop saved register values\n; 7 - Execute an IRETD to transfer control to original handler.\n\n\tpushfd\t\t\t; Step 1\n\tsub\tesp,8\t\t; Step 2\n\tpush\tebp\t\t; Step 3\n\tmov\tebp,esp\t\t; Set up a stack frame to know where to poke address.\n\n\t; Step 3 continued.  Push used varables.\n\tpushad\n\tpush\tfs gs es ds\n\n\n\t; Step 4.  Now do processing before I chain.\n\t; Set up ds:esi to point at start of real memory block (data is first)\n\n\tcall far Timer_Interrupt_Func\n\n\tSET_DS_ESI_TO_RM\t\t\t; Set ds:esi to point to real mode stuff.\n\n\t; Now take care of calling the old DOS timer interrupt vector.\n\t; This must be the last operation of this module since if we call\n\t; DOS, we will never return.\n\tmov\tax,[(TimerType PTR ds:esi).DosAdder] \n\tadd\t[(TimerType PTR esi).DosFraction],ax\n\tjnc\t??no_dos_call\t\t\t\t\t; if not, skip the call.\n\n\t; Tell RM that we forced the int and not to update timers.\n\tmov\t[(TimerType PTR esi).PMIssuedInt],1\t\t; Make it TRUE\n\n\t; Step 5.\n\t; Now it is time to set up for the call by returning by poking\n\t; the old interrupt handle address in.\n\tmov\teax,[(TimerType PTR esi).OldPMIOffset]\t\t; Get orig offset.\n\tmov\tebx,[(TimerType PTR esi).OldPMISelector]\t; Get orig selector.\n\tmov\t[ss:ebp+4],eax\t\t\t\t\t; Poke offset.\n\tmov\t[ss:ebp+8],ebx\t\t\t\t\t; Poke selector.\n\n\t; Step 6.\n\tpop\tds es gs fs\n\tpopad\n\tpop\tebp  \n\n\t; Step 7.\n\tiretd\t\t\t\t; transfer control to original handler.\n\n??no_dos_call:\n\n\tENABLE_CLOCK_INT\n\n\t; Restore all registers.\n\tpop\tds es gs fs\n\tpopad\n\n\tpop\tebp  \n\tadd\tesp,8\n\tpopfd\t\n\n\tiretd\n;////////////////////////////// Call prot mode interrupt vector ////////////////////////////////////////\n;//////////////////////////////////////////////////////////////////////////////////////////////////////\n\tENDP\n\n\n\n;***************************************************************************\n;* TIMER_INTERRUPT_FUNC -- Handles core timer code                         *\n;*                                                                         *\n;* This function exists so that we can call it from the core HMI driver    *\n;* code when our timer interrupt has not been installed.\t\t   *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/14/1995 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tTimer_Interrupt_Func C Far\n\tpushfd\t\t\t\t\t; save off the flags\n\tpushad\t\t\t\t\t; save off the main registers\n\tpush\tfs gs es ds\t\t\t; save off the seg registers\n\t\n\tSET_DS_ESI_TO_RM\t\t\t; Set ds:esi to point to real mode stuff.\n\tINCREMENT_TIMERS\t\t\t; Increment Westwoods timers\t\n\n\tpop\tds es gs fs\n\tpopad\n\tpopfd\n\tretf\n\tENDP\n\nLABEL \tLockedCodeEnd\t\tBYTE\n\n;***************************************************************************\n;* DISABLE_TIMER_INTERRUPT_ONLY -- Disables at the hardware level          *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/07/1995 DRD : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tDisable_Timer_Interrupt C Near\n\tpush\teax\n\tpushf\n\n\tsti\t\t\t; disable all interrupts if not disabled\n\tin\tal,021h\t\t; read interrupt Mask register bits 0-7\n\t\t\t\t; apply to irq's 0-7\n\t\t\t\t;   value 0 of enabled\n\t\t\t\t;   value 1 of disabled\n\tor\tal,001h\t\t; setup to disable irq 0\n\tout\t021h,al\t\t; disable irq 0\n\n\tpopf\t\t\t; possibly enable all interrupts (except 0)\n\tpop\teax\n\tretf\n\tENDP\n\n\n;***************************************************************************\n;* ENABLE_TIMER_INTERRUPT_ONLY -- Enables at the hardware level            *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   06/07/1995 DRD : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tEnable_Timer_Interrupt C Near\n\tpush\teax\n\tpushf\n\n\tsti\t\t\t; disable all interrupts if not disabled\n\tin\tal,021h\t\t; read interrupt Mask register bits 0-7\n\t\t\t\t; apply to irq's 0-7\n\t\t\t\t;   value 0 of enabled\n\t\t\t\t;   value 1 of disabled\n\tand\tal,0FEh\t\t; setup to enable irq 0\n\tout\t021h,al\t\t; enable irq 0\n\n\tpopf\t\t\t; possibly enable all interrupts\n\tpop\teax\n\tretf\n\tENDP\n\n\n\tEND\n\n\n\n"
  },
  {
    "path": "WWFLAT32/TIMER/TIMERDWN.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Temp timer for 32bit lib                 *\n *                                                                         *\n *                    File Name : TIMER.CPP                                *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : July 6, 1994                             *\n *                                                                         *\n *                  Last Update : July 12, 1994   [SKB]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   CDTC::Time -- Return the time on the timer.                           *\n *   CDTC::Stop -- Stop the timer.                                         *\n *   CDTC::Start -- Start a timer.                                         *\n *   CDTC::DownTimerClass -- Construct a timer class object.               *\n *   CDTC::Set -- Set the time of a timer.                           \t\t*\n *   CDTC::Reset -- Clear the timer.                                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include <descmgmt.h>\n#include \"timer.H\"\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////////// Defines /////////////////////////////////////\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////////// Code ////////////////////////////////////////\n\n\n/***************************************************************************\n * TC::CountDownTimerClass -- Construct a timer class object.              *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nCountDownTimerClass::CountDownTimerClass(BaseTimerEnum timer, long set, int on)\n\t\t\t\t\t\t\t:TimerClass(timer, on)\n{\n\tSet(set, on);\n}\n\nCountDownTimerClass::CountDownTimerClass(BaseTimerEnum timer, int on)\n\t\t\t\t\t\t\t:TimerClass(timer, FALSE)\n{\n\tDelayTime = 0;\n\tif (on) Start();\n}\n\n\n/***************************************************************************\n * CDTC::TIME -- Return the time on the timer.                             *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong CountDownTimerClass::Time()\n{\n\tlong ticks = DelayTime - TimerClass::Time();\n\n\tif (ticks < 0) {\n\t\tticks = 0;\n\t}\n\treturn(ticks);\n}\n\n\n/***************************************************************************\n * CDTC::SET -- Set the time of a timer.                             \t\t*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:  ULONG value to set timer at.                                    *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/12/1994 SKB : Created.                                             *\n *=========================================================================*/\nlong CountDownTimerClass::Set(long value, BOOL start)\n{\n\tDelayTime = value;\n\tTimerClass::Reset(start);\n\treturn(Time());\n}\n\n\n\n"
  },
  {
    "path": "WWFLAT32/TIMER/TIMEREAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Timer interrupt for RM                   *\n;*                                                                         *\n;*                    File Name : TIMEREAL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Scott K. Bowen                           *\n;*                                                                         *\n;*                   Start Date : July 8, 1994                             *\n;*                                                                         *\n;*                  Last Update : July 8, 1994   [SKB]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nMODEL TINY\nP386N\n\nLOCALS ??\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////////// Equates ////////////////////////////////////////\n\nINTCHIP0\tEQU\t20h\t\t; 8259 interrupt chip controller 0\nCLEARISR\tEQU\t20h\t\t; Value to write to 8259 to reenable interrupts.\n\nCODESEG\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////////// Data ////////////////////////////////////////\n; This information may not change unless the protected mode version is\n; also changed.\n; For speed, PM uses a DD while RM used DW\nTrueRate\t\tDW\t0\t; True rate of clock. (only use word)\nTrueRateNA\t\tDW\t0\t\t; used for speed in prot mode.\n\n; For speed, SysRate and SysError are DD in PM and are DW in real mode.\nSysTicks\t\tDD\t0\t; Tick count of timer.\nSysRate\t\t\tDD\t0\t; Desired rate of timer.\nSysError\t \tDD\t0\t; Amount of error in clock rate for desired frequency.\nSysCurRate\t \tDW\t0\t; Keeps track of when to increment timer.\nSysCurError\t\tDW\t0\t; Keeps track of amount of error in timer.\n\nUserTicks\t\tDD\t0\t; Tick count of timer.\nUserRate\t \tDD\t0\t; Desired rate of timer.\nUserError\t \tDD\t0\t; Amount of error in clock rate for desired frequency.\nUserCurRate\t \tDW\t0\t; Keeps track of when to increment timer.\nUserCurError\t\tDW\t0\t; Keeps track of amount of error in timer.\n\nDosAdder\t\tDW\t0 \t; amount to add to DosFraction each interrupt.\nDosFraction\t\tDW\t0\t; Call dos when overflowed.\n\nOldRMI\t\t\tDD\t0\t; The origianl RM interrupt seg:off.\nOldPMIOffset\t\tDD\t0\t; The origianl PM interrupt offset\t\t\nOldPMISelector\t\tDD\t0\t; The original PM interrupt segment.\n\nCodeOffset\t\tDW\tRM_Timer_Interrupt_Handler\t; Offset of the code in the RM stuff.\nCallRMIntOffset\t\tDW\tCall_Interrupt_Chain\t\t; Offset of function to call DOS timer interrupt.\nCallRMIntAddr\t\tDD\t0\t; PM address of CallRealIntOffset for speed.\n\nPMIssuedInt\t\tDD\t0\t; PM signals RM to just call Int chain.\t\n\n; These are just used for information on testing.  When all is done, they can\n; be removed, but why?  The don't add too much proccessing time and can\n; be useful.\nNumPMInts\t\tDD\t0\t; Number of PM interrupts\nNumRMInts\t\tDD\t0\t; Number of RM interrupts.\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;///////////////////////////////////// Code ////////////////////////////////////////\n\n\n; This is here for easy comparison with the PM version.\nMACRO INCREMENT_TIMERS\n\tinc\t[NumRMInts]\t\t; For testing.\n\n\n\t; At this point, increment the system and user timers.\n\tmov\tax,[TrueRate]\t\t; Get the rate of the PC clock.\n\n\tsub\t[SysCurRate],ax\t\t; Sub from our rate counter.\n\tja\t??end_sys\t\t\t; If !below zero, do not inc.\n\n\tmov\tbx,[WORD PTR SysRate]\t; Get rate of timer.\n\tmov\tdx,[WORD PTR SysError]\t; Get amount of error.\n\tadd\t[SysCurRate],bx\t\t; Add rate to the current.\n\n\tsub\t[SysCurError],dx\t; Subtract err from error count.\n\tjb\t??error_adj_sys\t\t; If !below 0, increment counter.\n\n\tinc\t[SysTicks]\t\t; increment the timer.\n\tjmp\tshort ??end_sys\t\t; don't modify SysCurError.\n??error_adj_sys:\n\tadd\t[SysCurError],bx\t; reajust the error by timer rate.\n??end_sys:\n\n\tsub\t[UserCurRate],ax\t; Sub from our rate counter.\n\tja\t??end_user\t\t; If !below zero, do not inc.\n\n\tmov\tbx,[WORD PTR UserRate]\t; Get rate of timer.\n\tmov\tdx,[WORD PTR UserError]\t; Get amount of error.\n\tadd\t[UserCurRate],bx\t; Add rate to the current.\n\n\tsub\t[UserCurError],dx\t; Subtract err from error count.\n\tjb\t??error_adj_user\t; If !below 0, increment counter.\n\n\tinc\t[UserTicks]\t\t; increment the timer.\n\tjmp\tshort ??end_user\t; don't modify UserCurError.\n??error_adj_user:\n\tadd\t[UserCurError],bx\t; reajust the error by timer rate.\n??end_user:\n\nENDM\n\n\n\n\n;**************************************************************************\n;* RM_INTERRUPT_HANDLER -- Called when processor interrupted in real mode. *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nlabel RM_Timer_Interrupt_Handler\nstart_RM_Timer_Interrupt_Handler:\n\n\tpush\tax\n\tpush\tbx\n\tpush\tdx\n\tpush\tds\n\n\tmov\tax,cs\t\t\t; Set data segment to code segment \n\tmov\tds,ax\t\t\t;   since data is in code seg.\n\n\tcmp\t[WORD PTR PMIssuedInt],0; Check to see if PM made Int call.\n\tmov\t[WORD PTR PMIssuedInt],0; Make it false.\t\t\n\tjne\t??call_int_chain\t; if so, just call Int Chain.\n\n\n\tINCREMENT_TIMERS\n\n\n\t; Now check to see if we should call the old timer handler.\n\tmov\tax,[DosAdder]\t\t; Get amount to add each tick.\n\tadd\t[DosFraction],ax      \t; add it to the fraction.\n\tjnc\t??no_int_chain\t      \t; Skip call if no overflow.\n\n??call_int_chain:\n\tpushf\t\t\t\t; Push flags for interrupt call.\n       \tcall\t[OldRMI]\t\t; chain the call.\n\n??no_int_chain:\n\tsti\n\tmov\tal,CLEARISR   \t\t; value to clear In Service Register\n\tmov\tdx,INTCHIP0\n\tout\tdx,al\t\t\t; 8259 interrupt chip controller 0\nexit1:\n\n\tpop\tds\n\tpop\tdx\n\tpop\tbx\n\tpop\tax\n\tiret\n\n\n\n;**************************************************************************\n;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/08/1994 SKB : Created.                                             *\n;*=========================================================================*\nCall_Interrupt_Chain:\n\n\tpushf\n\tcall\t[OldRMI]\t\t;\n\tretf\n\nSTACK\t   ; Don't really need this\n\nEND\n\n\n\n\nIF 0\n; mono print stuff.\n\tpushf\n\tpush\tax\n\tpush\tdi\n\tpush\tes\n\n\tmov\tax,0B000h\t\t; ES:DI = Mono RAM address.\n\tmov\tes,ax\n\t\t\n\tmov\tal,'A'\n\tmov\tah,2\n\tand\tdi,63\n\n\tstosw\n\n\tpop\tes\n\tpop\tdi\n\tpop\tax\n\tpopf\nENDIF\n"
  },
  {
    "path": "WWFLAT32/TIMER/TIMEREAL.IBN",
    "content": "\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,048h,000h,0C5h,000h,000h,000h,000h,000h\n\tDB  000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,050h,053h,052h\n\tDB  01Eh,08Ch,0C8h,08Eh,0D8h,083h,03Eh,03Ch,000h,000h,0C7h,006h,03Ch,000h,000h\n\tDB  000h,075h,057h,066h,0FFh,006h,044h,000h,0A1h,000h,000h,029h,006h,010h,000h\n\tDB  077h,01Dh,08Bh,01Eh,008h,000h,08Bh,016h,00Ch,000h,001h,01Eh,010h,000h,029h\n\tDB  016h,012h,000h,072h,007h,066h,0FFh,006h,004h,000h,0EBh,004h,001h,01Eh,012h\n\tDB  000h,029h,006h,020h,000h,077h,01Dh,08Bh,01Eh,018h,000h,08Bh,016h,01Ch,000h\n\tDB  001h,01Eh,020h,000h,029h,016h,022h,000h,072h,007h,066h,0FFh,006h,014h,000h\n\tDB  0EBh,004h,001h,01Eh,022h,000h,0A1h,024h,000h,001h,006h,026h,000h,073h,005h\n\tDB  09Ch,0FFh,01Eh,028h,000h,0FBh,0B0h,020h,0BAh,020h,000h,0EEh,01Fh,05Ah,05Bh\n\tDB  058h,0CFh,09Ch,0FFh,01Eh,028h,000h,0CBh\n"
  },
  {
    "path": "WWFLAT32/TIMER/TIMERINI.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Temp timer for 32bit lib                 *\n *                                                                         *\n *                    File Name : TIMERINI.CPP                             *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : July 6, 1994                             *\n *                                                                         *\n *                  Last Update : July 6, 1994   [SKB]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Init_Timer_System -- Initialize the WW timer system.                  *\n *   Remove_Timer_System -- Removes the timer system.                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <wwstd.h>\n#include <descmgmt.h>\n#include \"timer.H\"\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////////// Defines /////////////////////////////////////\n\n#define COPY_FROM_MEM\tTRUE\n\n/////////////////////////////////////////////////////////////////////////////////\n////////////////////////////// timera.asm functions//////////////////////////////\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern VOID *Get_RM_Timer_Address(VOID);\nextern ULONG Get_RM_Timer_Size(VOID);\nextern BOOL Install_Timer_Interrupt(VOID *bin_ptr, UINT rm_size, UINT freq, BOOL partial);\nextern BOOL Remove_Timer_Interrupt(VOID);\n\n#ifdef __cplusplus\n}\n#endif\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////// Global Data /////////////////////////////////////\n\nBOOL\tTimerSystemOn\t= FALSE;\n\n// Global timers that the library or user can count on existing.\nTimerClass\t\t\t\t\tTickCount(BT_SYSTEM);\nCountDownTimerClass\t\tCountDown(BT_SYSTEM, 0);\n\n/////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////////// Code ////////////////////////////////////////\n\n/***************************************************************************\n * INIT_TIMER_SYSTEM -- Initialize the WW timer system.                    *\n *                                                                         *\n *                                                                         *\n * INPUT: UINT : user timer frequency.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:   BOOL success?                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/06/1994 SKB : Created.                                             *\n *=========================================================================*/\nBOOL Init_Timer_System(UINT freq, BOOL partial)\n{\n\tVOID\t\t*binary;\n\tUINT\t\tbinsize;\n\tBOOL\t\tsuccess;\n\n#if COPY_FROM_MEM\n\n\t// The binary is stuffed in an ASM module.\n\t// Get it's address and size.\n\tbinary = Get_RM_Timer_Address();\n\tbinsize = Get_RM_Timer_Size();\n\t\n#else\n\tWORD fd;\n\tVOID *mem;\n\n\t// \n\t// Open binary image of real mode timer code.\n\t// get its size and allocate a temp block for it.\n\t// Copy the file into the block and close the file\n\t//\n\tfd = Open(\"timer.ibn\", READ);\n\tbinsize = File_Size(fd);\n\tbinary = Alloc(binsize, MEM_NORMAL);\n\tRead_File(fd, binary, binsize);\n\tClose_File(fd);\n\n#endif // COPY_FROM_MEM\n\n\t// If no size, size too big or no address, then it's a bug.\n\tif (!binsize || (binsize > 0xFFFFL) || !binary) {\n\t\treturn (FALSE);\n\t}\n\n\tTimerSystemOn = success = Install_Timer_Interrupt(binary, binsize, freq, partial);\n\n#if !COPY_FROM_MEM\n\t// Free up the temp pointer.\n\tFree(mem);\n#endif // !COPY_FROM_MEM\n\n\tif (success)  {\n\t\tif (!partial)\n\t\t\tTickCount.Start();\n\t\treturn (TRUE);\n\t} else {\n\t\tRemove_Timer_Interrupt();\n\t\treturn (FALSE);\n\t}\n}\n\n\n\n/***************************************************************************\n * REMOVE_TIMER_SYSTEM -- Removes the timer system.                        *\n *                                                                         *\n *                                                                         *\n * INPUT:   NONE.                                                          *\n *                                                                         *\n * OUTPUT:  BOOL was it removed successfuly                                *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/06/1994 SKB : Created.                                             *\n *=========================================================================*/\nBOOL Remove_Timer_System(VOID)\n{\n\tTimerSystemOn = FALSE;\n\treturn(Remove_Timer_Interrupt());\n}\n\n"
  },
  {
    "path": "WWFLAT32/VIDEO/INITDLAY.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : INITDLAY.C                               *\n *                                                                         *\n *                   Programmer : Barry Green                              *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Init_Delay -- I am not sure                                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"wwstd.h\"\n#include \"timer.h\"\n#include \"video.h\"\n\t\t   \t \nBOOL VertBlank;\n\n/***************************************************************************\n * INIT_DELAY -- I am not sure                                             *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/03/1994 SKB : Created.                                             *\n *=========================================================================*/\nVOID Init_Delay(VOID)\n{\t  \n\tWORD nz, nnz;\n\n\tnz = nnz = 0;\n\n\tCountDown.Set(15, TRUE); // set to  1/4 second and start it\n\t\n\tdo {\n\t\tif (Get_Vert_Blank())\n\t\t\tnnz++;\n\t\telse\n\t\t\tnz++;\n\t} while (CountDown.Time());\n\n\tVertBlank = (nnz > nz);\n}\n"
  },
  {
    "path": "WWFLAT32/VIDEO/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 27, 1995                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = video\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\tvideo.obj\t\t&\n\tvesainfo.obj\t&\n\tinitdlay.obj\t&\n\tvertblnk.obj\t&\n\tvesahook.obj\n \n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWLIB)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# The keyboard object files is also dependant on an IBN file which is \n#   generated from KEYIREAL.ASM\n#---------------------------------------------------------------------------\nvesareal.ibn: vesareal.obj\n\t%create\t$^*.rsp\n\t%append $^*.rsp $^&.obj\n\t%append $^*.rsp $^&.exe\n\t%append $^*.rsp $^&.map\n\ttlink @$^*.rsp\n        tdstrip vesareal.exe\n        ebn\tvesareal.exe\n\nvesareal.obj:\tvesareal.asm\n\ttasm /zn /la /ml /m2 vesareal.asm\n\nvesahook.obj: vesareal.ibn vesahook.asm\n\n\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WWFLAT32/VIDEO/VERTBLNK.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; $Header: g:/library/wwlib32/video/rcs/vertblnk.asm 1.1 1994/04/18 09:34:51 jeff_wilson Exp $\n;***************************************************************************\n;**   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   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library routine                          *\n;*                                                                         *\n;*                    File Name : VERTBLNK.ASM                             *\n;*                                                                         *\n;*                   Programmer : Christopher Yates                        *\n;*                                                                         *\n;*                  Last Update : 20 August, 1990   [CY]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n; WORD Get_Vert_Blank(VOID);                                               *\n; VOID Wait_Vert_Blank(VOID);\t\t\t\t\t\t   *\n; WORD get_vga_state (VOID) ;\n; VOID set_vga_mode (WORD) ;\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nLOCALS ??\n\nGLOBAL             Get_Vert_Blank       : NEAR\nGLOBAL             Wait_Vert_Blank      : NEAR\nGLOBAL\t\t   get_vga_state\t: NEAR\nGLOBAL\t\t   set_vga_mode\t\t: NEAR\n\n\nCODESEG\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; WORD Get_Vert_Blank(VOID);\n; VOID Wait_Vert_Blank(VOID);\n; WORD get_vga_state (VOID) ;\n; VOID set_vga_mode (WORD) ;\n\n;\n; ----------------------------------------------------------------\n\n;----------------------------------------------------------------------------\n\nPROC\tGet_Vert_Blank C near\n\tUSES edx\n\t\t\n\tmov\tdx,03DAH\t; CRTC status register\n\tin\tal,dx\n\tand\tal,008H\t\t; look at bit 3 vertical sync\n\txor\tah,ah\t\t; zero ah\n\tret\n\nENDP\tGet_Vert_Blank\n\n;----------------------------------------------------------------------------\n\n;----------------------------------------------------------------------------\nPROC\tWait_Vert_Blank C near\n\tUSES eax,ebx,edx\n\tARG\tblank:DWORD\n\n\tmov\tebx,[blank]\t; get vertical blank 0 or 1 for on\n\n\tmov\tedx,03DAH\t; CRTC status register\n\n\tand\tbl,01b\n\tshl\tbl,3\n\n??in_vbi:\n\tin\tal,dx\t\t\t; read CRTC status\n\tand\tal,008h\t\t\t; only vertical sync bit\n\txor\tal,bl\n\tje\t??in_vbi\t\t; in vertical sync\n\n??out_vbi:\n\tin\tal,dx\t\t\t; read CRTC status\n\tand\tal,008h\t\t\t; only vertical sync bit\n\txor\tal,bl\n\tjne\t??out_vbi\t\t; not in vertical sync\n\n\tret\n\nENDP\tWait_Vert_Blank\n\n;----------------------------------------------------------------------------\n\n; WORD get_vga_state (VOID) ;\n\nPROC\tget_vga_state C near\n\tUSES  ebx\n\tmov   eax,0f00h\n\tint   10h\n\tand   eax, 0ffh\n\tret\nENDP\tget_vga_state\n\n;----------------------------------------------------------------------------\n\n; VOID set_vga_mode (WORD) ;\n\nPROC   set_vga_mode C near\n\tARG   mode:dword\n\tmov   eax , [mode]\n\tand   eax , 0ffh\t\n\tint   10h\n\tret\nENDP   set_vga_mode\n\n\n\nEND\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/VIDEO/VESAHOOK.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Vesa Hookup                              *\n;*                                                                         *\n;*                                                                         *\n;*                   Programmer : Julio R. Jerez                           *\n;*                                                                         *\n;*                   Start Date : Jan 31, 1995                             *\n;*                                                                         *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"svgaprim.inc\"\n\n\nDPMI_INTR equ 031h\n\n\nLOCALS ??\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;/////////////////////////////////// Prototypes //////////////////////////////////////\n\nGLOBAL\t  RMVesaVector    : DWORD\nGLOBAL\t  RMVesaRegs      : DWORD\t\nGLOBAL\t  RMVesaVectorSel : DWORD\nGLOBAL\t  Vesa_Hook    \t  : NEAR\nGLOBAL\t  Remove_Vesa \t  : NEAR\nGLOBAL\t  VesaFunc\t  : dword\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;//////////////////////////////////////// Data ////////////////////////////////////////\n\tDATASEG\n\n; The current time we will just include the real mode stuff\n; into the protected mode code and then copy it down.  The C side of\n; this will handle this method or reading it off of disk in the real\n; method.\n\nLABEL \tRealDataStart BYTE\ninclude \"VesaReal.ibn\"\nLABEL\tRealDataEnd BYTE\n\nRMVesaVectorSel DD\t0\n\n;//////////////////////////////////////////////////////////////////////////////////////\n;//////////////////////////////////////// Code ////////////////////////////////////////\n\n\tCODESEG\n\nPROC\tVesa_Hook C Near\n\tUSES\tebx,ecx,edx,ecx,edi,esi\n\tARG\tvesa_ptr:DWORD\n\n\t; Are they attempting to set timer again?\n\tcmp\t[RMVesaVectorSel],0\n\tjnz\t??exit\n\n\t; now allocate real mode memory and copy the rm binary down to it.\n\tmov\teax,0100h\t\t; set function number\n\tlea\tebx , [RealDataEnd]\n\tsub\tebx , offset RealDataStart\n\tpush\tebx\n\n\tadd\tebx , 15 + 040h\n\tshr\tebx,4\t\t\t; convert to pages.\n\tint\tDPMI_INTR\t \t; do call.\n\tpop\tecx\n\tjc\t??error\t\t \t; check for error.\n\n\t; set up source and destination pointers for the copy.\n\tshl\tedx , 16\n\tmov\t[ RMVesaVectorSel ] , edx\n\tshl\teax,4\t\t\t; convert segment to offset.\n\n\tmov\tedi , ecx\n\txor\tesi , esi\n\n;\tpush\tecx\n;\tpush\teax\n;\tmov\tecx , eax\n;\tshld\tebx,ecx,16\n;\tmov\teax,0600h\t\t\t; function number.\n;   \tint\tDPMI_INTR\t\t\t; do call.\n;\tpop\teax\n;\tpop\tecx\n;\tjc\t??error\t\t\t\t; eax = 8 if mem err, eax = 9 if invalid mem region.\n\n\tlea\tesi , [ RealDataStart]\n\tlea\tedi , [ eax + 040h ]\t; put it into esi for copy.\n\trep\tmovsb\t\t\t; write RM bin to RM memory.\n\n\tmov\tedx,[vesa_ptr]\t\t; Setup vesa funtion\n\tmov\t[ eax + 40h - 4 ] , edx\n\n\n       ; Chain the Real Vesa funcion interrupt to any avilable\n       ; Interrupt vector so We make sure that the Real Mode\n       ; Keyboard Interrupt service get called at debuging time\n       ; of the library.\n\n       mov\t[ RMVesaRegs ] , eax\n       shl\teax , 12\n       lea\tedi , [ eax + 040h ]  ; ofsset of VesaFunc\n       mov\tbl , 060h\n       mov\tbh , 6\n       mov\teax , 200h\n ??find:\n       int\tDPMI_INTR\n       jc\t??error\n       or\tcx,dx\n       jz\t??found\n       inc\tbl\n       dec\tbh\n       jnz\t??find\n       jmp\t??error\n ??found:\n       mov\teax , 0201h\t\n       mov\tedx , edi\n       shld\tecx , edx , 16\n       and\tebx , 0ffh\n       mov\t[ RMVesaVector ] , ebx\n       int\tDPMI_INTR\n       jc\t??error\n\n ??exit:\n       xor\teax,eax\t\t\t; signal an error.\n       ret\t       \n ??error:\t\n       mov \teax , -1 \n       ret\t\n      ENDP\n\n\n\nPROC\tRemove_Vesa C Near\n\tUSES\tebx,ecx,edx,ecx,edi,esi\n\tARG\tvesa_ptr:DWORD\n\n\n\t; Are they attempting to set timer again?\n\tmov     [VesaFunc],0\n\tcmp\t[RMVesaVectorSel],0\n\tjz\t??exit\n\n       mov\tebx , [ RMVesaVector ]\n       test\tebx , ebx\n       jz\t??exit\n       mov\teax , 0201h\t\n       xor\tedx , edx\n       xor\tecx , ecx \n       int\tDPMI_INTR\n       mov\t[ RMVesaVector ] , 0\n       jc\t??exit\n\n;       mov\teax , 0601h\n;       mov \tecx , [ RMVesaRegs ] \n;       shld\tebx , ecx , 16\n;       lea\tedi , [RealDataEnd]\n;       sub\tedi , offset RealDataStart\n;       add\tedi , 15 + 040h\n;       xor\tesi , esi\n;       int\tDPMI_INTR\n;       jc\t??exit\n\n\tmov\teax,0101h\t\t; set function number\n\tmov\tedx ,[RMVesaVectorSel]\n\ttest \tedx , edx\n\tjz\t??exit\n\tshr\tedx , 16\n\tint\tDPMI_INTR\t \t; do call.\n\tmov\t[RMVesaVectorSel],0\n??exit:\n       ret\t\n      ENDP\n\n\nEND\n\n\n\n"
  },
  {
    "path": "WWFLAT32/VIDEO/VESAINFO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : VIDEO.C                                  *\n *                                                                         *\n *                   Programmer : David Dettmer                            *\n *                                                                         *\n *                  Last Update : January 12, 1995   [PWG]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Find_Video_Mode -- Converts a dos video mode to a WWLIB video mode    *\n *   Get_Video_Mode -- Returns the current video mode.                     *\n *   Set_Video_Mode -- Sets the requested video mode                       *\n *   Set_Lores_Function_Pointers -- Sets up the lowres function pointers   *\n *   Set_HiRes_Function_Pointers -- Sets the HiRes function pointers       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <dos.h>\n#include \"iostream.h\"\n#include \"video.h\"\n#include \"descmgmt.h\"\n#include \"mcgaprim.h\"\n#include \"gbuffer.h\"\n#include \"vbuffer.h\"\n#include \"wwmem.h\"\n\n#include \"playcd.h\"\n\n\n/***************************************************************************\n * VESA_INFO -- Debug routine which displays vesa info to stdout           *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1994 PWG : Created.                                             *\n *=========================================================================*/\nvoid Vesa_Info(int vesa_mode)\n{\n\tUINT         paras;\n\tUSHORT   \t longest ;\n   union REGS \t regs;\n   struct SREGS sregs;\n\tSEGSEL\t\t   VInfoSel ;\t\t\t \n\tVesaInfoType *\tVInfo ;\n\tSEGSEL\t\t \tModeInfoSel ;\n\tVesaModeInfoType * ModeInfo ;\t\t\t \n\tunsigned   temp ;\n\tshort\t\t* ptr ;\n\tchar       buff [ 256 ] ;\n\tshort mode_table [][4] = { { 0x100 , 640 , 400 , 256 }, \n\t\t\t\t\t  \t\t\t\t   { 0x101 , 640 , 480 , 256 },\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t   { 0x103 , 800 , 600 , 256 },\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t } ;\n\n\tcout << \"\\n\\nWWESTWOOD STUDIOS. Vesa Driver attributes.\\n\" ;\n\n\t// verifie that this is a standard VESA MODE\n\tif ( (vesa_mode < VESA_640X400_256) || ( vesa_mode > VESA_TEXT_132X60 )) {\n\t  cout << \"this is not a standard VESA mode\\n\" ;\n\t  return ;\n\t}\n\n\t// Compute size of VesaInfo structure in paragraphs \n\tparas = ( sizeof(VesaInfoType) + 15 ) >> 4 ;\n\t\n\t// Alloc real-mode memory for VESA structure. \n   if ( DPMI_real_alloc ( paras , & VInfoSel  , & longest ) ) return ;\n\tVInfo = ( VesaInfoType * ) ( VInfoSel . seg << 4 ) ;\n\n\t// Compute size of VesaModeInfo structure in paragraphs \n\tparas = ( sizeof(VesaModeInfoType) + 15 ) >> 4 ;\n\n\t//Alloc real-mode memory for VesaModeInfoType structure. \n   if ( DPMI_real_alloc ( paras , & ModeInfoSel , & longest ) ) \n\t{ \n\t\tDPMI_real_free\t( VInfoSel ) ;\n\t\treturn ;\n\t}\n\tModeInfo = ( VesaModeInfoType * ) ( ModeInfoSel . seg << 4 ) ;\n\n\t// Get Read Vesa Driver Vesa\n\tregs . x . eax = 0x4f00 ;\t\n\tregs . x . edi = 0 ;\n\tsregs . es = VInfoSel . seg ;\n   DPMI_real_intr ( 0x10 , & regs , & sregs );\n\n\tregs . x . eax &= 0xffff ;\n\tif ( regs . x . eax != 0x004F) {\n\t  cout << \"\\nNot Vesa Driver Present\\n\" ;\n\t  DPMI_real_free\t( ModeInfoSel ) ;\n  \t  DPMI_real_free\t( VInfoSel ) ;\n\t  return\t;\n\t}\n\n\ttemp = ( unsigned ) VInfo->AvailModes ;\n\tptr = ( short * ) ( ( ( temp & 0xffff0000 ) >> 12 ) + ( temp & 0xffff ) ) ;\n\tcout << \"Available Video Modes\\n\" ;\n\tfor ( ; * ptr != -1 ; ptr ++ ) \n\t for ( temp = 0 ; temp < 3 ; temp ++ )\t\n\t\t if ( * ptr == mode_table [ temp ] [ 0 ] ) {\n\t\t\tsprintf ( buff , \"%d\\t%d x %d x %d\\n\" ,  \n\t\t\t\t\t\t\t      mode_table [ temp ] [ 0 ],\n\t\t\t\t\t\t\t      mode_table [ temp ] [ 1 ],\n\t\t\t\t\t\t\t      mode_table [ temp ] [ 2 ],\n\t\t\t\t\t\t\t      mode_table [ temp ] [ 3 ] ) ;\n\t\t\tcout << buff ;\n\t\t }\n\n   // Get Info for this particular graphic mode\n  \tregs . x . eax = 0x4F01;\n  \tregs . x . ecx = vesa_mode;\n  \tregs . x . edi = 0 ;\n  \tsregs . es = ModeInfoSel . seg ;\n   DPMI_real_intr ( 0x10 , & regs , & sregs );\n\tregs . x . eax &= 0xffff ;\n\tif ( regs . x . eax != 0x004F) {\n\t  cout << \"\\nGraphic mode \" << vesa_mode << \" is not supported by this video card\\n\" ;\n\t  DPMI_real_free\t( ModeInfoSel ) ;\n  \t  DPMI_real_free\t( VInfoSel ) ;\n\t  return\t;\n\t}\n\n\tcout << \"\\nMode attributes\\n\" ;\n\ttemp = ( unsigned ) ModeInfo->Attributes ;\n\tif ( temp & 0x01 ) cout << \"\\tMode supported in hardware\\n\" ;\n\telse\t\t\t\t    cout << \"\\tMode is not supported in hardware\\n\" ;\n\tif ( temp & 0x20 ) cout << \"\\tMode is not VGA Windowed memory compatible\\n\" ;\n\telse\t\t\t\t    cout << \"\\tMode is VGA Windowed memory compatible\\n\" ;\n\n\tcout << \"Window A attributes\\n\" ;\n\ttemp = ( unsigned ) ModeInfo->WinA_Attributes; ;\n\tif ( temp & 0x02 ) cout << \"\\tWindow A is Readable\\n\" ;\n\telse\t\t\t\t    cout << \"\\tWindow A is not Readable\\n\" ;\n\tif ( temp & 0x04 ) cout << \"\\tWindow A is Writeable\\n\" ;\n\telse\t\t\t\t    cout << \"\\tWindow A is not Writeable\\n\" ;\n\tsprintf ( buff , \"%P\\n\" , ModeInfo->WinA_Segment ) ;\n\tcout << \"\\tWindow A segment address 0x\" << buff + 4 ;\n\n\n\n\tcout << \"Window B attributes\\n\" ;\n\ttemp = ( unsigned ) ModeInfo->WinB_Attributes; ;\n\tif ( temp & 0x02 ) cout << \"\\tWindow B is Readable\\n\" ;\n\telse\t\t\t\t    cout << \"\\tWindow B is not Readable\\n\" ;\n\tif ( temp & 0x04 ) cout << \"\\tWindow B is Writeable\\n\" ;\n\telse\t\t\t\t    cout << \"\\tWindow B is not Writeable\\n\" ;\n\tsprintf ( buff , \"%P\\n\" , ModeInfo->WinB_Segment ) ;\n\tcout << \"\\tWindow B segment address 0x\" << buff + 4 ;\n\n\tcout << \"Window shared attributes\\n\" ;\n\tcout << \"\\tWindow Granularity (KB) :\"\t<< ModeInfo->WinGranularity << \"\\n\" ;\n\tcout << \"\\tWindow Size (KB) : \" << ModeInfo->WinSize\t<< \"\\n\";\n\tcout << \"\\tNumber of Banks : \" << (long)ModeInfo->NumBanks << \"\\n\";\n\tcout << \"\\tBytes per ScanLine : \" << (long)ModeInfo->BytesPerScanline << \"\\n\";\n\tcout << \"\\tXResolution : \" << (long)ModeInfo->XRes << \"\\n\";\n\tcout << \"\\tYResolution : \" << (long)ModeInfo->YRes << \"\\n\";\n\tcout << \"\\tX Char Size : \" << (long)ModeInfo->XCharSize << \"\\n\";\n\tcout << \"\\tY Char Size : \" << (long)ModeInfo->YCharSize << \"\\n\";\n\tcout << \"\\tMemory Model : \" << (long)ModeInfo->MemoryModel << \"\\n\";\n\tcout << \"\\tNumber of planes : \" << (long)ModeInfo->NumPlanes << \"\\n\"\t;\n\tcout << \"\\tBits per pixels : \" << (long)ModeInfo->BitsPerPixel\t<< \"\\n\" ;\n\n\n/*\n\tcout\t<< \"Bttributes:                    \" << (long)ModeInfo.Bttributes\t\t\t<< \"\\n\"\n\t\t\t<< \"Win B Bttributes:              \" << (long)ModeInfo.WinB_Bttributes\t<< \"\\n\"\n\t\t\t<< \"Win B Bttributes:              \" << (long)ModeInfo.WinB_Bttributes\t<< \"\\n\"\n\t\t\t<< \"Win Granularity                \" << (long)ModeInfo.WinGranularity   << \"\\n\"\n\t\t\t<< \"Win Size:                      \" << (long)ModeInfo.WinSize\t\t\t\t<< \"\\n\"\n\t\t\t<< \"Win B Segment:                 \" << hex << (unsigned short)ModeInfo.WinB_Segment\t\t<< \"\\n\"\n\t\t\t<< \"Win B Segment:                 \" << (unsigned short)ModeInfo.WinB_Segment\t\t<< \"\\n\"\n\t\t\t<< \"Bytes per scan line:           \" << dec << (unsigned short)ModeInfo.BytesPerScanline\t<< \"\\n\"\n\t\t\t<< \"X resolution:                  \" << (long)ModeInfo.XRes\t\t\t\t\t<< \"\\n\"\n\t\t\t<< \"Y resolution:                  \" << (long)ModeInfo.YRes             << \"\\n\"\n\t\t\t<< \"X Char Size:                   \" << (long)ModeInfo.XCharSize        << \"\\n\"\n\t\t\t<< \"Y Char Size:                   \" << (long)ModeInfo.YCharSize        << \"\\n\"\n\t\t\t<< \"Number of planes:              \" << (long)ModeInfo.NumPlanes\t\t\t<< \"\\n\"\n\t\t\t<< \"Bits per pixels:               \" << (long)ModeInfo.BitsPerPixel\t\t<< \"\\n\"\n\t\t\t<< \"Number of Banks:               \" << (long)ModeInfo.NumBanks\t\t\t<< \"\\n\"\n\t\t\t<< \"Memory Model:                  \" << (long)ModeInfo.MemoryModel\t\t<< \"\\n\"\n\t\t\t<< \"Bank Size:                     \" << (long)ModeInfo.BankSize         << \"\\n\";\n*/\n  \tDPMI_real_free\t( ModeInfoSel ) ;\n  \tDPMI_real_free\t( VInfoSel ) ;\n}\n"
  },
  {
    "path": "WWFLAT32/VIDEO/VESAREAL.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n;***************************************************************************\n;**     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       **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Timer interrupt for RM                   *\n;*                                                                         *\n;*                    File Name : TIMEREAL.ASM                             *\n;*                                                                         *\n;*                   Programmer : Julio R. Jerez                           *\n;*                                                                         *\n;*                   Start Date : jan 31 , 1995                            *\n;*                                                                         *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nMODEL TINY\nP386N\n\n\n\nLOCALS ??\n\nCODESEG\n;///////////////////////////////////// Code ////////////////////////////////////////\n\nlabel Vesa_Funcion_Call\nstart:\n \tcall\t[dword ptr cs: 40h - 4]\n\tiret\n\n\n\nEND\n\n"
  },
  {
    "path": "WWFLAT32/VIDEO/VESAREAL.IBN",
    "content": "\tDB  02Eh,0FFh,01Eh,03Ch,000h,0CFh\n"
  },
  {
    "path": "WWFLAT32/VIDEO/VIDEO.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : VIDEO.C                                  *\n *                                                                         *\n *                   Programmer : David Dettmer                            *\n *                                                                         *\n *                  Last Update : June 29, 1995   [PWG]                    *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Find_Video_Mode -- Converts a dos video mode to a WWLIB video mode    *\n *   Get_Video_Mode -- Returns the current video mode.                     *\n *   Set_Video_Mode -- Sets the requested video mode                       *\n *   Set_Lores_Function_Pointers -- Sets up the lowres function pointers   *\n *   Set_HiRes_Function_Pointers -- Sets the HiRes function pointers       *\n *   Set_Original_Video_Mode -- sets mode to restore system to on exit     *\n *   Get_Original_Video_Mode -- Gets the original video mode value         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <dos.h>\n#include \"iostream.h\"\n#include \"video.h\"\n#include \"descmgmt.h\"\n#include \"mcgaprim.h\"\n#include \"gbuffer.h\"\n#include \"vbuffer.h\"\n#include \"wwmem.h\"\n\n#include \"playcd.h\"\n\nextern \"C\" int MInstalled ;\nextern \"C\" void Hide_Mouse(void);\nextern \"C\" void Show_Mouse(void);\n\nextern \"C\" void Reset_Mouse (void) ;\nextern \"C\" int  Vesa_Hook ( REALPTR function ) ;\nextern \"C\" void Remove_Vesa (void) ;\nextern \"C\" SEGSEL\t RMVesaVectorSel ;\nextern \"C\" REALPTR VesaFunc;\n\n/*=========================================================================*/\n/* Define the global variables that we require.\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nlong\t\t\t\tBankTable[MAX_BANK_ENTRIES];\nint\t\t\t\tGraphicMode\t\t\t\t= UNINITIALIZED_MODE;\nlong\t\t\t\tXRes\t\t\t\t\t\t= 0;\nlong\t\t\t\tYRes\t\t\t\t\t\t= 0;\nREALPTR\t\t\tVesaFunc;\nunsigned long \tRMVesaVector ;\nunsigned\tlong\tRMVesaRegs ;\n\n/*=========================================================================*\n * Private Varirables\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * VInfo      - Protected mode copy of VInfo structure.\t\t\t\t\t\t\t*\n * ModeInfo   - Protected mode copy of ModeInfo structure.\t\t\t\t\t\t*\n * rpModeInfo - Real ptr to ModeInfo structure in conventional memory.\t\t*\n * rpVInfo    - Real ptr to VInfo structure in conventional memory.\t\t\t*\n * _regs      - Registers used for calling software interrupts.\t\t\t\t*\n *=========================================================================*/\nPRIVATE void \t* rpModeInfo  \t= NULL;\nPRIVATE SEGSEL\trpModeInfoSel ;\nPRIVATE void \t* rpVInfo\t  \t= NULL;\nPRIVATE SEGSEL\trpVInfoSel\t  ;\n\nPRIVATE long\t\t\t\t\t_OriginalVideoMode\t= UNINITIALIZED_MODE;\nPRIVATE VesaInfoType \t\tVInfo;\nPRIVATE VesaModeInfoType\tModeInfo;\n\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE long Install_Vesa(void);\nPRIVATE long Vesa_Get_Mode_Info(long mode);\nPRIVATE long Vesa_Set_Mode(long mode);\nPRIVATE void Init_Bank_Table(void);\nPRIVATE VOID Set_LoRes_Function_Pointers(VOID);\nPRIVATE VOID Set_HiRes_Function_Pointers(VOID);\n\nextern \"C\" long Vesa_XRes(void);\nextern \"C\" long Vesa_YRes(void);\n\nextern \"C\" char CurrentPalette  [ 256 * 3 ]\t;\nextern \"C\" char PaletteTable\t  [ 1024 ] ;\n\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n/***************************************************************************\n * GET_VIDEO_MODE -- Returns the current video mode.                       *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     returns the graphic mode as a WWLIB library define          *\n *                                                                         *\n * WARNINGS:\tnone                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1994     : Created.                                             *\n *=========================================================================*/\nint Get_Video_Mode(void)\t\t\t\n{\n  union REGS \t regs;\n\n\tif( GraphicMode == UNINITIALIZED_MODE ) \n\t{\t\t\n\t\tregs\t. x . eax = 0xf00 ;\t\t// get graphic mode\n\t\tint386 ( 0x10 , & regs , & regs ) ;\n\t\treturn ( regs . w . ax & 0xff ) ;\n\t}\n\treturn(GraphicMode);\t\t\t\t\t\t\t\t\t// return the graphic mode\n}\t\t   \n\n/***************************************************************************\n * Install_Vesa -- Initializes the vesa driver if it exists                *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     return -1 if error/VESA not supported.                      *\n *                                                                         *\n * WARNINGS:\tThis function will not work unless a vesa compatable driver *\n *\t\t\t\t\tis installed in either hardware or software.\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1994 PWG : Created.                                             *\n *=========================================================================*/\nPRIVATE long Install_Vesa(void)\n{\n\tUINT         paras;\n\tUSHORT   \t longest ;\n   union REGS \t regs;\n   struct SREGS sregs;\n\n\t/* Calculate size of VesaInfo structure in paragraphs */\n\tparas = ( sizeof(VesaInfoType) + 15 ) >> 4 ;\n\t\n\t/* Allocate real-mode memory for VESA structure. */\n   if ( DPMI_real_alloc ( paras , & rpVInfoSel  , & longest ) ) return - 1 ;\n\trpVInfo = ( void * ) ( rpVInfoSel . seg << 4 ) ;\n\n\t/* Calculate size of VesaModeInfo structure in paragraphs */\n\tparas = ( sizeof(VesaModeInfoType) + 15 ) >> 4 ;\n\n\t/* Allocate real-mode memory for VESA structure. */\n   if ( DPMI_real_alloc ( paras , & rpModeInfoSel , & longest ) ) \n\t{ \n\t\tRemove_Vesa();\n\t\treturn (-1);\n\t}\n\trpModeInfo = ( void * ) ( rpModeInfoSel . seg << 4 ) ;\n\n\t/* Clear the input buffer */\n\tmemset ( rpVInfo , 0 , sizeof ( VesaInfoType) ) ;\n\n\t\n\t/* Read Vesa information  */\n\tregs . x . eax = 0x4f00 ;\t\n\tregs . x . edi = 0 ;\n\tsregs . es = rpVInfoSel . seg ;\n   DPMI_real_intr ( 0x10 , & regs , & sregs );\n\n\tregs . x . eax &= 0xffff ;\n\tif ( regs . x . eax != 0x004F) return (-1);\n\tMem_Copy ( rpVInfo , & VInfo , sizeof(VesaInfoType)) ;\n\n\treturn 0;\n}\n\n\n/***************************************************************************\n * VESA_GET_MODE_INFO -- Gets info about specified video mode              *\n *                                                                         *\n * INPUT:\t\tlong - the mode we are requesting info about                *\n *                                                                         *\n * OUTPUT:     long - 0 if sucessful, -1 if failure                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1994 PWG : Created.                                             *\n *=========================================================================*/\nPRIVATE long Vesa_Get_Mode_Info(long mode)\n{\n   union REGS \t regs;\n   struct SREGS sregs;\n\n\tif (rpModeInfo ) \n\t{\n\t\t/* Clear the input buffer */\n\t\tmemset ( rpModeInfo, 0, sizeof(VesaModeInfoType));\n\n\t\t/* Set up function call */\n\t\tregs . x . eax = 0x4F01;\n\t\tregs . x . ecx = mode;\n\t\tregs . x . edi = 0 ;\n\t\tsregs . es = rpModeInfoSel . seg ;\n   \tDPMI_real_intr ( 0x10 , & regs , & sregs );\n\n\t\tregs . x . eax &= 0xffff ;\n\t\tif ( regs . x . eax == 0x004F)  \n\t\t{\n\t\t\tMem_Copy ( rpModeInfo , &ModeInfo , sizeof(VesaModeInfoType));\n\n\t\t// this part is only temporary until Phil get the documentation\n\t\t//\tfor DPMI funtion 0x301 simulate real call\n\t\t// in the mean time we will be making call to the vesa driver\n\t\t// thru a real interrupt\n\t\t  if ( Vesa_Hook ( ModeInfo . WinFunc ) ) return ( -1 ) ;\n\t\t  return (0);\n\t\t}\n\t} \n  return (-1);\n}\n\n/***************************************************************************\n * VESA_SET_MODE -- Sets the specified Vesa mode                           *\n *                                                                         *\n * INPUT:\t\tlong - the mode we wish to set                              *\n *                                                                         *\n * OUTPUT:\t\tlong - 0 if all is ok, -1 if we cannot set this mode        *\n *                                                                         *\n * WARNINGS:\tYou must call Install_Vesa before calling Vesa_Set_Mode     *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1994 PWG : Created.                                             *\n *=========================================================================*/\nPRIVATE long Vesa_Set_Mode(long mode)\n{\n   union REGS \t regs;\n   struct SREGS sregs;\n\n\t/* Get mode info */\n\tif ( Vesa_Get_Mode_Info(mode) ) return (-1) ;\n\n\tif ((ModeInfo.Attributes & 0x01) == 0) return (-1);\n\n\t/* Set vesa VIDEO MODE */\n\tregs . x . eax = 0x4F02;\t\t\t\t// \n\tregs . x . ebx = mode;\n\tint386 ( 0x10 , & regs , & regs ) ;\n//\tdelay ( 1000 ) ;\n\n\tif ( VInfo . Capabilities & 1 ) \n\t{\n\t\t/* Set DAC to 6 bit per color register */ \n\t\tregs . x . eax = 0x4F08;\t\t\t\t \n\t\tregs . h . bl  = 0;\n\t\tregs . h . bh = 6 ;\n\t\tint386 ( 0x10 , & regs , & regs ) ;\n//\t\tdelay ( 1000 ) ;\n\t}\n\n\tregs . x . eax &= 0xffff ;\n\tif ( regs . x . eax != 0x004F) return (-1);\n\n\tInit_Bank_Table();\n\treturn (0);\n\n}\n\n/***************************************************************************\n * VESA_XRES -- Returns horizontal resolution of vesa mode                 *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long - the horizontal resolution of vesa mode               *\n *                                                                         *\n * WARNINGS:\tYou must call Install_Vesa and Vesa_Set_Mode before calling *\n *\t\t\t\t\tVesa_XRes().\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1994 PWG : Created.                                             *\n *=========================================================================*/\nlong Vesa_XRes(void)\n{\n\treturn ((long)ModeInfo.XRes);\n}\n\n/***************************************************************************\n * VESA_YRES -- Returns vertical resolution of a vesa mode                 *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     long - the horizontal resolution of vesa mode               *\n *                                                                         *\n * WARNINGS:\tYou must call Install_Vesa and Vesa_Set_Mode before calling *\n *\t\t\t\t\tVesa_XRes().\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1994 PWG : Created.                                             *\n *=========================================================================*/\nlong Vesa_YRes(void)\n{\n\treturn ((long)ModeInfo.YRes);\n}\n\n/***************************************************************************\n * INIT_BANK_TABLE -- Initializes the values in the bank table             *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/02/1994 PWG : Created.                                             *\n *=========================================================================*/\nPRIVATE void Init_Bank_Table(void)\n{\n\tlong\tsize,bankval;\n\tint\tnum_banks,lp;\n\tunion REGS \t regs;\n   struct SREGS sregs;\n\n\n\tsize\t\t\t= Vesa_XRes() * Vesa_YRes();\t// get video mode size\n\tnum_banks\t= size / 65536;\t\t\t\t\t// get number of banks\n\n\tif (size % 65536) \t\t\t\t\t\t\t\t// adjust number of banks if\n\t\tnum_banks++;\t\t\t\t\t\t\t\t\t//   they dont break evenly\n\n\tbankval\t= 64 / ModeInfo.WinGranularity;\n\tVesaFunc\t= ModeInfo.WinFunc;\n\n\tfor (lp = 0; lp < num_banks; lp++) \n\t\tBankTable[lp] = lp * bankval;\n\n\n\tregs . x . eax = 0x4F05;\t\t\t\t// Reset Vesa to Point to Bank 0\n\tregs . x . ebx = 0x0000;\n\tregs . x . edx = 0x0000;\n\tint386 ( 0x10 , & regs , & regs ) ;\n\n}\n\n/***************************************************************************\n * SET_MODE -- Used to set a graphic mode                             \t\t*\n *                                                                         *\n * INPUT:\tint  - the mode that we are setting                            *\n *                                                                         *\n * OUTPUT:  int  - FALSE if failure, TRUE otherwise                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1994 PWG : Created.                                             *\n *=========================================================================*/\nint Set_Video_Mode(int mode)\n{\n\tunion   REGS inregs,outregs;\n\tstatic  first_time = 0 ;\n\tint\t  oldmode ;\n \n\t/*======================================================================*/\n\t/* If this is the first time we have set the mode we need to store\t\t*/\n\t/*\t\tof the original mode.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif ( ! first_time ) {\n\t\tfirst_time = 1 ;\n      Set_Original_Video_Mode(Get_Video_Mode());\n  }\n \n\t/*======================================================================*/\n\t/* If the mode we are trying to set is mode zero than we are actually\t*/\n\t/*\t\ttrying to restore the system to its original video mode.\t\t\t\t*/\n\t/*======================================================================*/\n\tif (mode == RESET_MODE) \n\t\tmode \t= Get_Original_Video_Mode();\t// set mode properly\n\n\tif (mode == GraphicMode)\t\t\t  \t// if mode already correct\n\t\treturn(TRUE);\t\t\t\t\t\t  \t//\t\tget out of here\n\n\toldmode = GraphicMode ;\n\tGraphicMode\t= mode ;\n\n\t/**********************************************************************/\n\t/* make sure the mouse is term off before any change */\n\t/*********************************************************************/\n\tif ( MInstalled == TRUE ) Hide_Mouse () ;\n\n\n\t/* clear color palette */\n\tmemset ( CurrentPalette  , 255 , sizeof ( CurrentPalette ) ) ;\n\tmemset ( PaletteTable  , 0 , sizeof ( PaletteTable ) ) ;\n\n\t/*======================================================================*/\n\t/* If we are currently in a vesa mode, free it up so that we can do it\t*/\n\t/*\t\tagain.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif ((oldmode >= VESA_MIN) && (oldmode <= VESA_MAX)) \n\t\tRemove_Vesa();\n\n\n\t/*======================================================================*/\n\t/* If we are requesting a vesa mode, than use the vesa calls to handle\t*/\n\t/*\t\tit.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif ( GraphicMode >= VESA_MIN && GraphicMode <= VESA_MAX) \n\t{\n\t\tinregs . x . eax = MCGA_MODE;\n\t\tint386 ( 0x10 , &inregs , &outregs);\n//\t\tdelay ( 1000 ) ;\n\n\t\tif ( Install_Vesa () != 0 ) {\n\t\t\t\tSet_Video_Mode(oldmode);\n\t\t\t\treturn(FALSE);\n\t  \t}\n\n\t\tif (Vesa_Set_Mode(GraphicMode) != 0) \n\t\t{\n\t\t\tSet_Video_Mode(oldmode);\n\t\t\treturn(FALSE);\n\t\t}\n\t\tXRes = Vesa_XRes();\n\t\tYRes = Vesa_YRes();\n\t\tSet_HiRes_Function_Pointers();\n\t} \n\telse \n\t{\n\t\t/*===================================================================*/\n\t\t/* If not a vesa mode, then handle that as well.\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tinregs . x . eax = GraphicMode ;\n\t\tint386( 0x10, &inregs, &outregs);\n//\t\tdelay ( 1000 ) ;\n\n\t\tif ( GraphicMode == \tMCGA_MODE ) {\n\t\t\tXRes = 320;\n\t\t\tYRes = 200;\n\t\t\tSet_LoRes_Function_Pointers();\n\t\t}\n\t}\n\tif (  MInstalled == TRUE ) {\n\t\tReset_Mouse () ;\n\t\tShow_Mouse () ;\n\t}\n\treturn(TRUE);\n}\n/***************************************************************************\n * VESA_INFO -- Debug routine which displays vesa info to stdout           *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   Must call Install_Vesa before attempting to get the vesa\t\t*\n *\t\t\t\t\tinfo.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1994 PWG : Created.                                             *\n *=========================================================================*/\nvoid Vesa_Info(void)\n{\n\tcout\t<< \"Attributes:                    \" << (long)ModeInfo.Attributes\t\t\t<< \"\\n\"\n\t\t\t<< \"Win A Attributes:              \" << (long)ModeInfo.WinA_Attributes\t<< \"\\n\"\n\t\t\t<< \"Win B Attributes:              \" << (long)ModeInfo.WinB_Attributes\t<< \"\\n\"\n\t\t\t<< \"Win Granularity                \" << (long)ModeInfo.WinGranularity   << \"\\n\"\n\t\t\t<< \"Win Size:                      \" << (long)ModeInfo.WinSize\t\t\t\t<< \"\\n\"\n\t\t\t<< \"Win A Segment:                 \" << hex << (unsigned short)ModeInfo.WinA_Segment\t\t<< \"\\n\"\n\t\t\t<< \"Win B Segment:                 \" << (unsigned short)ModeInfo.WinB_Segment\t\t<< \"\\n\"\n\t\t\t<< \"Bytes per scan line:           \" << dec << (unsigned short)ModeInfo.BytesPerScanline\t<< \"\\n\"\n\t\t\t<< \"X resolution:                  \" << (long)ModeInfo.XRes\t\t\t\t\t<< \"\\n\"\n\t\t\t<< \"Y resolution:                  \" << (long)ModeInfo.YRes             << \"\\n\"\n\t\t\t<< \"X Char Size:                   \" << (long)ModeInfo.XCharSize        << \"\\n\"\n\t\t\t<< \"Y Char Size:                   \" << (long)ModeInfo.YCharSize        << \"\\n\"\n\t\t\t<< \"Number of planes:              \" << (long)ModeInfo.NumPlanes\t\t\t<< \"\\n\"\n\t\t\t<< \"Bits per pixels:               \" << (long)ModeInfo.BitsPerPixel\t\t<< \"\\n\"\n\t\t\t<< \"Number of Banks:               \" << (long)ModeInfo.NumBanks\t\t\t<< \"\\n\"\n\t\t\t<< \"Memory Model:                  \" << (long)ModeInfo.MemoryModel\t\t<< \"\\n\"\n\t\t\t<< \"Bank Size:                     \" << (long)ModeInfo.BankSize         << \"\\n\";\n}\n\n\n/***************************************************************************\n * VESA_SET_WINDOW -- Sets given vesa window to given grain                *\n *                                                                         *\n * INPUT:\t\tint window\t- 0 for window A, 1 for window B                *\n *\t\t\t\t\tint grain   - the granularity point for window\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/05/1994 PWG : Created.                                             *\n *=========================================================================*/\nvoid Vesa_Set_Window(long grain_num)\n{\n    union REGS \t regs;\n    struct SREGS sregs;\n\n\tregs . x . eax = 0x4f05 ;\n\tregs . x . ebx = 0 ;\n\tregs . x . edx = grain_num;\n//\tDPMI_real_call ( ModeInfo.WinFunc , & regs , & sregs ) ;\n\tDPMI_real_intr ( VesaFunc , & regs , & sregs ) ;\n\n}\n\n\n/***************************************************************************\n * SET_LORES_FUNCTION_POINTERS -- Sets up the lowres function pointers     *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/12/1995 PWG : Created.                                             *\n *=========================================================================*/\nPRIVATE VOID Set_LoRes_Function_Pointers(VOID)\n{\n\tVVPC_Clear_Func\t\t\t= MCGA_Clear;\n\tVVPC_To_Buffer_Func\t\t= MCGA_To_Buffer;\n\tVVPC_Put_Pixel_Func\t\t= MCGA_Put_Pixel;\n\tVVPC_Get_Pixel_Func\t\t= MCGA_Get_Pixel;\n\tGVPC_Blit_to_VVPC_Func\t= Linear_Blit_To_Linear;\n\tVVPC_Blit_to_GVPC_Func\t= Linear_Blit_To_Linear;\n\tVVPC_Blit_to_VVPC_Func\t= Linear_Blit_To_Linear;\n\tVVPC_Buffer_To_Page\t\t= MCGA_Buffer_To_Page;\n\tGVPC_Scale_To_VVPC\t\t= Linear_Scale_To_Linear;\n\tVVPC_Scale_To_GVPC\t\t= Linear_Scale_To_Linear;\n\tVVPC_Scale_To_VVPC\t\t= Linear_Scale_To_Linear;\n\tVVPC_Print_Func\t\t\t= MCGA_Print;\n}\n/***************************************************************************\n * SET_HIRES_FUNCTION_POINTERS -- Sets the HiRes function pointers         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/12/1995 PWG : Created.                                             *\n *=========================================================================*/\nPRIVATE VOID Set_HiRes_Function_Pointers(VOID)\n{\n\tVVPC_Clear_Func\t\t\t= Vesa_Clear;\n\tVVPC_To_Buffer_Func\t\t= Vesa_To_Buffer;\n\tVVPC_Put_Pixel_Func\t\t= Vesa_Put_Pixel;\n\tVVPC_Get_Pixel_Func\t\t= Vesa_Get_Pixel;\n\tGVPC_Blit_to_VVPC_Func\t= Linear_Blit_To_Vesa;\n\tVVPC_Blit_to_GVPC_Func\t= Vesa_Blit_To_Linear;\n\tVVPC_Blit_to_VVPC_Func\t= Vesa_Blit_To_Vesa;\n\tVVPC_Buffer_To_Page\t\t= Vesa_Buffer_To_Page;\n\tGVPC_Scale_To_VVPC\t\t= Linear_Scale_To_Vesa;\n\tVVPC_Scale_To_GVPC\t\t= Vesa_Scale_To_Linear;\n\tVVPC_Scale_To_VVPC\t\t= Vesa_Scale_To_Vesa;\n\tVVPC_Print_Func\t\t\t= Vesa_Print;\n}\n\n/***************************************************************************\n * Update_Video_Mode -- used to reprogram the current graphic mode afte    *\n * \t\t\t\t\t\t\ta task swicthing from windows\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   03/18/94 JRJ : Created.                                               *\n *=========================================================================*/\nvoid Update_Video_Mode (void) \n{\n\tunion   REGS inregs,outregs;\n\n\t/* clear color palette */\n\tmemset ( CurrentPalette  , 255 , sizeof ( CurrentPalette ) ) ;\n\tmemset ( PaletteTable  , 0 , sizeof ( PaletteTable ) ) ;\n\n \n\t/**********************************************************************/\n\t/* make sure the mouse is term off before any change */\n\t/*********************************************************************/\n\tif ( MInstalled == TRUE ) \n\t\t\t\t\t\t\t\tHide_Mouse () ;\n\n\t/*======================================================================*/\n\t/* If we are requesting a vesa mode, than use the vesa calls to handle\t*/\n\t/*\t\tit.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\tif ( GraphicMode >= VESA_MIN && GraphicMode <= VESA_MAX) {\n\t\tinregs . x . eax = MCGA_MODE;\n\t\tint386 ( 0x10 , &inregs , &outregs);\n\t\tVesa_Set_Mode(GraphicMode);  \n\t} \n\telse {\n\t\t/*===================================================================*/\n\t\t/* If not a vesa mode, then handle that as well.\t\t\t\t\t\t\t*/\n\t\t/*===================================================================*/\n\t\tinregs . x . eax = GraphicMode ;\n\t\tint386( 0x10, &inregs, &outregs);\n\t}\n\tif (  MInstalled == TRUE ) {\n\t\tReset_Mouse () ;\n\t\tShow_Mouse () ;\n\t}\n}\n\n\n/***************************************************************************\n * SET_ORIGINAL_VIDEO_MODE -- sets mode to restore system to on exit       *\n *                                                                         *\n * INPUT:\t\tint video mode number                                       *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/29/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid Set_Original_Video_Mode(int mode)\n{\n\t_OriginalVideoMode = mode;\n}\n\n\n/***************************************************************************\n * GET_ORIGINAL_VIDEO_MODE -- Gets the original video mode value           *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     int the video mode set when we entered                      *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/29/1995 PWG : Created.                                             *\n *=========================================================================*/\n\nint Get_Original_Video_Mode(void)\n{\n\treturn(_OriginalVideoMode);\n}\n"
  },
  {
    "path": "WWFLAT32/VIDEO/VIDEO.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **     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       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : 32 bit library                           *\n *                                                                         *\n *                    File Name : VIDEO.H                                  *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : August 3, 1994                           *\n *                                                                         *\n *                  Last Update : August 3, 1994   [SKB]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef VIDEO_H\n#define VIDEO_H\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\t\t\t\t\t   \n/*=========================================================================*/\n/*\tThe machine can be in one of the following graphic modes.  The global\t*/\n/*\tGraphicMode is set to one of these values.\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tCGA_MODE\t\t\t\t\t4\t\t\t// DOS 320x200 4 color mode\n#define\tTGA_MODE\t\t\t\t\t9\t\t\t// TANDY 320x200 16 color mode\n#define\tEGA_MODE\t\t\t\t\t13\t\t\t// DOS 320x200 16 color mode\n#define\tMCGA_MODE\t\t\t\t0x13\t\t// DOS 320x200 256 color mode\n#define\tVGA_MODE\t\t\t\t\t0x13\t\t// DOS 320x200 256 color mode\n#define\tEEGA_MODE\t\t\t\t14\t\t\t// DOS 640x400 16 color mode\n#define\tETGA_MODE\t\t\t\t9\t\t\t// TANDY 640x400 16 color mode\n#define\tHGA_MODE\t\t\t\t\t7\t\t\t// DOS 768x400 2 color mode\n#define\tTXT_MODE\t\t\t\t\t3\t\t\t// DOS plain old color text mode\n#define\tVESA_640X400_256\t\t0x100\t\t// VESA 640x400 256 color mode\n#define\tVESA_640X480_256\t\t0x101\t\t// VESA 640x480 256 color mode\n#define\tVESA_800X600_256\t\t0x103\t\t// VESA 800x600 256 color mode\n#define\tVESA_1024X768_256\t\t0x105\t\t//\tVESA 1024x768 256 color mode\n#define\tVESA_1280X400_256\t\t0x107\t\t// VESA 1280x400 256 color mode\n#define\tVESA_TEXT_80X60\t\t0x108\t\t// VESA 80x60 text mode\n#define\tVESA_TEXT_132X25\t\t0x109\t\t// VESA 132x25 text mode\n#define\tVESA_TEXT_132X60\t\t0x10C\t\t// VESA 132x60 text mode\n#define\tRESET_MODE\t\t\t\t-1\n#define\tUNINITIALIZED_MODE\t-1\n#define\tVESA_MIN \t\t\t\tVESA_640X400_256\n#define\tVESA_MAX\t\t\t\t\tVESA_TEXT_132X60\n\n/*=========================================================================*/\n/* Define the maximum number of bank entries\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define\tMAX_BANK_ENTRIES\t\t((1280L*1024L)/65536L)\n\n\n/*=========================================================================*\n * VesaInfoType - General info about this VESA implementation\t\t\t\t\t*\n *                (Filled in by VESA BIOS Function 0)\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Signature    - Will always be 'VESA'\t\t\t\t\t\t\t\t\t\t\t\t*\n * Version      - Version #\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OEMString    - OEM ID string\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Capabilities - Not defined by VESA yet\t\t\t\t\t\t\t\t\t\t\t\t*\n * AvailModes   - List of available modes; terminated with -1 (0xffff)\t\t*\n * TotalMemory  - ???\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Reserved     - Pads structure to 256 bytes total\t\t\t\t\t\t\t\t*\n *=========================================================================*/\ntypedef struct {\n\tchar    Signature[4];\n\tshort   Version;\n\tREALPTR OEMString;\n\tlong    Capabilities;\n\tREALPTR AvailModes;\n\tshort   TotalMemory;\n\tchar    Reserved[236];\n} VesaInfoType;\n\n\n/*=========================================================================*\n * VesaModeInfoType - Info about this VESA mode\t\t\t\t\t\t\t\t\t\t*\n *                    (Filled in by VESA BIOS Function 1)\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Attributes       - bit 0: 1 = mode is supported\t\t\t\t\t\t\t\t\t*\n *                    bit 1: 1 = optional info available\t\t\t\t\t\t\t*\n *                    bit 2: 1 = std BIOS output funcs valid in this mode\t*\n *                    bit 3: 0 = monochrome, 1 = color\t\t\t\t\t\t\t*\n *                    bit 4: 0 = text mode, 1 = graphics\t\t\t\t\t\t\t*\n * WinA_Attributes  - bit 0 = win exists, bit 1=readable, bit 2= writable\t*\n * WinB_Attributes  - bit 0 = win exists, bit 1=readable, bit 2= writable\t*\n * WinGranularity   - smallest address boundary window can be placed upon;\t*\n *                    size is in KB (ie 64, 32, 4)\t\t\t\t\t\t\t\t\t*\n * WinSize          - size of windows in KB (ie 64, 32)\t\t\t\t\t\t\t*\n * WinA_Segment     - location of Window A in CPU space (usually 0xa000)\t*\n * WinB_Segment     - location of Window B in CPU space (usually 0xb000)\t*\n * WinFunc          - address of window-setting function (This is provided *\n *                    as an alternative to Int 10 for speed.)\t\t\t\t\t*\n * BytesPerScanline - # bytes per scan line\t\t\t\t\t\t\t\t\t\t\t*\n * \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Optional info (available if bit 1 of Attributes is set):\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * XRes             - X-resolution\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * YRes             - Y-resolution\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * XCharSize        - Horizontal size of char cell\t\t\t\t\t\t\t\t\t*\n * YCharSize        - Vertical size of char cell\t\t\t\t\t\t\t\t\t*\n * NumPlanes        - # of memory planes (???)\t\t\t\t\t\t\t\t\t\t*\n * BitsPerPixel     - # bites per pixel\t\t\t\t\t\t\t\t\t\t\t\t*\n * NumBanks         - # of banks (ie planes)\t\t\t\t\t\t\t\t\t\t\t*\n * MemoryModel      - 00h = Text mode\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                    01h = CGA mode\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                    02h = Hercules\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                    03h = 4 plane planar mode\t\t\t\t\t\t\t\t\t\t*\n *                    04h = packed pixel mode (1 byte/pixel)\t\t\t\t\t*\n *                    05h = non-chain 4, 256-color mode\t\t\t\t\t\t\t*\n *                    06-0Fh = \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                    10-FFh = OEM-specific\t\t\t\t\t\t\t\t\t\t\t*\n * BankSize         - Bank size in KB\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *=========================================================================*/\ntypedef struct {\n\tshort   Attributes;\n\tchar    WinA_Attributes;\n\tchar    WinB_Attributes;\n\tshort   WinGranularity;\n\tshort   WinSize;\n\tshort   WinA_Segment;\n\tshort   WinB_Segment;\n\tREALPTR WinFunc;\n\tshort   BytesPerScanline;\n\tshort   XRes;\n\tshort   YRes;\n\tchar    XCharSize;\n\tchar    YCharSize;\n\tchar    NumPlanes;\n\tchar    BitsPerPixel;\n\tchar    NumBanks;\n\tchar    MemoryModel;\n\tchar    BankSize;\n\tchar    NumInputPages;\n\tchar    Reserved;\n\tchar    RedMaskSize;\n\tchar    RedFieldPosition;\n\tchar    GreenMaskSize;\n\tchar    GreenFieldPosition;\n\tchar    BlueMaskSize; \n\tchar    BlueFieldPosition;\n\tchar    RsvdMaskSize;\n\tchar    RsvdFieldPosition;\n\tchar    DirectColorModeInfo;\n\tchar    pad[216];\n} VesaModeInfoType;\n\n\nextern \"C\" {\nextern\tint\tGraphicMode;\nextern\tlong\tXRes;\nextern\tlong\tYRes;\n\nextern long\t\t BankTable [];\nextern REALPTR\t VesaFunc;\nextern unsigned long RMVesaVector ;\nextern unsigned long RMVesaRegs ;\n}\n\n/*=========================================================================*/\n/* The following prototypes are for the file: VIDEO.CPP\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nextern \"C\" int Set_Video_Mode(int mode);\nint Get_Video_Mode(void);\nvoid Update_Video_Mode (void) ;\nvoid Vesa_Info(void);\nvoid Vesa_Set_Window(long grain_num);\nint Get_Original_Video_Mode(void);\nvoid Set_Original_Video_Mode(int mode);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: INITDLAY.CPP\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\nextern VOID Init_Delay(VOID);\nextern BOOL VertBlank;\n\n/*=========================================================================*/\n/* The following prototypes are for the file: VERTBLNK.ASM\t  \t\t\t\t\t*/\n/*=========================================================================*/\n\t\t\t\t \t\t\t\t   \nextern \"C\" {\n\textern WORD Get_Vert_Blank(VOID);\n\textern VOID Wait_Vert_Blank(BOOL blank);\n}\n\n/*=========================================================================*/\n\n#endif // VIDEO_H\n"
  },
  {
    "path": "WWFLAT32/WINDOWS/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : jan 24, 1995                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = windows\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\twindows.obj\t&\n\twinhide.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\tmkdir run\n\tcd run\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\run\\vcs.cfg\n\tupdate\n\tcd..\n\tmkdir art\n\tcd art\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\art\\vcs.cfg\n\tupdate\n\tcd..\n\twmake \n\tcd ..\n\n\n#**************************** End of makefile ******************************\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/WINDOWS/WINDOW.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the WINDOWS Library              *\n *                                                                         *\n *                    File Name : WINDOWS.H                                *\n *                                                                         *\n *                   Programmer : Barry W. Green                           *\n *                                                                         *\n *                   Start Date : February 16, 1995                        *\n *                                                                         *\n *                  Last Update : February 16, 1995 [BWG]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WINDOWS_H\n#define WINDOWS_H\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WINHIDE.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Window_Hide_Mouse(int window);\nvoid Window_Show_Mouse(void);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WINDOWS.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Standard_More_Prompt(char const *prompt, int space, int fcolor, int bcolor);\nvoid Set_More_Prompt(char const *prompt, int space, int fcolor, int bcolor);\nvoid Set_More_On(void);\nvoid Set_More_Off(void);\nint Change_Window(int windnum);\nint Change_New_Window(int windnum);\nvoid New_Window(void);\nvoid Window_Int_Print(int num);\nvoid Window_Print(char const string[], ...);\n\n/*\n**\tThe WindowList[][8] array contains the following elements.  Use these\n**\tdefines when accessing the WindowList.\n*/\ntypedef enum {\n\tWINDOWX,\t\t\t// X byte position of left edge.\n\tWINDOWY,\t\t\t// Y pixel position of top edge.\n\tWINDOWWIDTH,\t// Width in bytes of the window.\n\tWINDOWHEIGHT,\t// Height in pixels of the window.\n\tWINDOWFCOL,\t\t// Default foreground color.\n\tWINDOWBCOL,\t\t// Default background color.\n\tWINDOWCURSORX,\t// Current cursor X position (in rows).\n\tWINDOWCURSORY,\t// Current cursor Y position (in lines).\n\tWINDOWPADDING=0x1000\n} WindowIndexType;\n\nextern int WindowList[][8];\nextern int WindowColumns;\nextern int WindowLines;\nextern int WindowWidth;\nextern unsigned int WinB;\nextern unsigned int WinC;\nextern unsigned int WinX;\nextern unsigned int WinY;\nextern unsigned int WinCx;\nextern unsigned int WinCy;\nextern unsigned int WinH;\nextern unsigned int WinW;\nextern unsigned int Window;\n\nextern int MoreOn;\nextern char *TXT_MoreText;\n\nextern void (*Window_More_Ptr)(char const *, int, int, int);\n\n#endif //WINDOWS_H\n\n\u001a"
  },
  {
    "path": "WWFLAT32/WINDOWS/WINDOWS.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./windows.c 1.12 1994/05/20 15:35:25 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : WINDOWS.C                                *\n *                                                                         *\n *                   Programmer : Everyone                                 *\n *                                                                         *\n *                  Last Update : February 3, 1992   [DRD]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Change_New_Window -- Combined Change_Window and New_Window.           *\n *   Change_Window -- Changes the 'current' window in the system.          *\n *   Fetch_Char -- Gets one undipthonged char from input.                  *\n *   Flush_Line -- Outputs the accumulate text line to screen.             *\n *   In_Char -- Stores (un-dipped) character(s) from input to buffer.      *\n *   New_Window -- Clears the current window to the background color.      *\n *   Set_More_Off -- Turns the 'more' prompting off.                       *\n *   Set_More_On -- Turns the 'more' prompting on.                         *\n *   Set_More_Prompt -- Adjusts the more prompt text for default routine   *\n *   Standard_More_Prompt -- Default more prompt code for Window_Print     *\n *   Window_Int_Print -- Prints an integer to the window.                  *\n *   Window_Print -- Displays and wraps text into a window.                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <ctype.h>\n#include <stdlib.h>\n#include <string.h>\n#include\t<stdio.h>\n#include\t<stdarg.h>\n#include <wwstd.h>\n#include \"window.h\"\n#include <keyboard.h>\n#include\t<font.h>\n#include <dipthong.h>\n\nPRIVATE void Scroll_Window(void);\nPRIVATE void Flush_Line(void);\nPRIVATE void In_Char(char *str);\nPRIVATE char Fetch_Char(void);\n\n\nPRIVATE int ScrollCounter = 0;\t//\tCount of the lines displayed before a pause.\nPRIVATE char Line[84];\t// Staging line buffer.\nPRIVATE int Pos;\t\t\t// Char Position of next free character.\nPRIVATE int PPos;\t\t// Pixel position of next free character.\nPRIVATE int WPos;\t\t// Char position in window.\nPRIVATE char *MainSource;\nPRIVATE char *AltSource;\nPRIVATE char Char[2];\nPRIVATE char Stack;\nPRIVATE char WordWrapFlag = FALSE;\t// flag for a word wrap.\n\nPRIVATE int MoreSpace = 7;\nPRIVATE int MoreFColor = 0;\nPRIVATE int MoreBColor = 0;\n\n\nint WindowColumns=40;\nint WindowLines=25;\nint WindowWidth=40;\nunsigned int WinB=0;\nunsigned int WinC=1;\nunsigned int WinX=0;\nunsigned int WinY=0;\nunsigned int WinCx=0;\nunsigned int WinCy=0;\nunsigned int WinH=25;\nunsigned int WinW=40;\nunsigned int Window=0;\n\nint MoreOn = TRUE;\nchar *TXT_MoreText = \"--More--\";\nvoid (*Window_More_Ptr)(BYTE const *,int,int,int) = Standard_More_Prompt;\n\nextern GraphicBufferClass *LogicPage;\n/***************************************************************************\n * STANDARD_MORE_PROMPT -- Default more prompt code for Window_Print       *\n *                                                                         *\n *    This is the standard \"<more>\" prompting code that is used by         *\n *    Window_Print when a page is full of text and a pause is desired      *\n *    before the next page of text is printed.  This function is called    *\n *    through the Window_More_Ptr global.                                  *\n *                                                                         *\n * INPUT:   prompt   -- Pointer to ASCII text that will be window printed  *\n *                      at the right margin.                               *\n *                                                                         *\n *          space    -- The number of spaces to allow for the 'more' text. *\n *                                                                         *\n *          fcolor   -- The foreground color to use for the 'more' text.   *\n *                                                                         *\n *          bcolor   -- The background oclor to use for the 'more' text.   *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/29/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Standard_More_Prompt(char const *prompt, int space, int fcolor, int bcolor)\n{\n\tint\tx, y, moresize;\n\t\n\tmoresize = (space - 1) * (FontWidth+FontXSpacing);\n\tx = ((WinX+WinW) << 3) - moresize;\n\t//y = WinY + ((WinH/FontHeight)-1)*FontHeight;\n\ty = WinY + (WinCy-1) * (FontHeight+FontYSpacing);\n\n\t// Default \"more\" prompter.\n\tLogicPage->Print(prompt, x, y, fcolor ? fcolor : WindowList[Window][WINDOWBCOL], bcolor ? bcolor : WindowList[Window][WINDOWFCOL]);\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Show_Mouse();\n//BG\t}\n\n\tClear_KeyBuffer();\n\tGet_Key();\n\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Hide_Mouse(Window);\n//BG\t}\n\n\t// Erase the more prompt prompt.\n\t//\tText_Print(prompt, x, y, WinB, WinB);\n\tLogicPage->Fill_Rect(x, y, x + moresize - 1, y + (FontHeight+FontYSpacing) - 1, WinB);\n}\n\n\n/***************************************************************************\n * SET_MORE_PROMPT -- Adjusts the more prompt text for default routine     *\n *                                                                         *\n *    Use this routine to control the text of the \"<MORE>\" prompt that     *\n *    the default more prompt routine uses.  This can be useful for        *\n *    foreign language translations.                                       *\n *                                                                         *\n * INPUT:   prompt   -- Pointer to ASCII text that will be window printed  *\n *                      at the right margin.                               *\n *                                                                         *\n *          space    -- The number of spaces to allow for the 'more' text. *\n *                                                                         *\n *          fcolor   -- The foreground color to use for the 'more' text.   *\n *                                                                         *\n *          bcolor   -- The background color to use for the 'more' text.   *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/29/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Set_More_Prompt(char const *prompt, int space, int fcolor, int bcolor)\n{\n\tif (prompt) {\n\t\tTXT_MoreText = (char*)prompt;\n\t\tMoreSpace = space;\n\t\tMoreFColor = fcolor;\n\t\tMoreBColor = bcolor;\n\t}\n\telse {\n\t\tTXT_MoreText = \"<MORE>\";\n\t\tMoreSpace = 7;\n\t\tMoreFColor = MoreBColor = 0;\n\t}\n}\n\n\n/***************************************************************************\n * SET_MORE_ON -- Turns the 'more' prompting on.                           *\n *                                                                         *\n *    Use this routine to turn on the 'more' prompting that Window_Print   *\n *    does.  If you have a custom more function pointer, then that         *\n *    routine will be called, otherwise the library default 'more' prompt  *\n *    will be utilized.                                                    *\n *                                                                         *\n * INPUT:      none                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Set_More_On(void)\n{\n\tMoreOn = TRUE;\n\tScrollCounter = 0;\n}\n\n\n/***************************************************************************\n * SET_MORE_OFF -- Turns the 'more' prompting off.                         *\n *                                                                         *\n *    This routine will turn the 'more' prompting that Window_Print does   *\n *    off.                                                                 *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Set_More_Off(void)\n{\n\tMoreOn = FALSE;\n}\n\n\n/***************************************************************************\n * CHANGE_WINDOW -- Changes the 'current' window in the system.            *\n *                                                                         *\n *    Use this routine to change the 'current' window.  The current window *\n *    is used in Window_Print and some other graphic output routines.      *\n *                                                                         *\n * INPUT:   windnum  -- The window number to change to.                    *\n *                                                                         *\n * OUTPUT:  Returns with the previously current window.                    *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nint Change_Window(int windnum)\n{\n\tint\toldwindow;\n\tint\t*data;\n\n\toldwindow = Window;\n\tWindow = windnum;\n\tdata = &WindowList[windnum][0];\n\n\tWinX = *data++;\n\tWinY = *data++;\n\tWinW = *data++;\n\tWinH = *data++;\n\tWinC = *data++;\n\tWinB = *data++;\n\tWinCx = *data++;\n\tWinCy = *data++;\n\tScrollCounter = 0;\n\tWPos = WinCx / (FontWidth+FontXSpacing);\n\tWindowLines = (WinH-FontYSpacing) / (FontHeight+FontYSpacing);\n\tWindowWidth = WinW << 3;\n\tWindowColumns = WindowWidth / (FontWidth+FontXSpacing);\n\treturn (oldwindow);\n}\n\n\n/***************************************************************************\n * CHANGE_NEW_WINDOW -- Combined Change_Window and New_Window.             *\n *                                                                         *\n *    This is a combo-routine.  It merely combines the Change_Window       *\n *    with the New_Window routines.  It will save some (small) code if     *\n *    you use this routine instead of the two function calls.              *\n *                                                                         *\n * INPUT:   window   -- Window number to change to and clear.              *\n *                                                                         *\n * OUTPUT:  Returns with the previously current window.                    *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nint Change_New_Window(int windnum)\n{\n\tint\toldwindow;\n\n\toldwindow = Change_Window(windnum);\n\tNew_Window();\n\treturn(oldwindow);\n}\n\n\n/***************************************************************************\n * NEW_WINDOW -- Clears the current window to the background color.        *\n *                                                                         *\n *    This routine clears the current window to the background color.  It  *\n *    is used in preparation to Window_Print because it ensures a clean    *\n *    'slate' for the text.                                                *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid New_Window(void)\n{\n\tint\tx,y,w,h;\n\n\tx = WinX << 3;\n\ty = WinY;\n\tw = (WinX + WinW) << 3;\n\th = WinY + WinH;\n\n\tLogicPage->Fill_Rect(x, y, w - 1, h - 1, WinB);\n\n\tWinCx = WPos = 0;\n\tWinCy = 0;\n\tScrollCounter = 0;\n}\n\n\n/***************************************************************************\n * WINDOW_INT_PRINT -- Prints an integer to the window.                    *\n *                                                                         *\n *    Use this routine to print an integer to the window.  This routine    *\n *    as all other Window printing routines will handle word wrap.         *\n *                                                                         *\n * INPUT:   num   -- The integer to convert to ASCII and print.            *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Window_Int_Print(int num)\n{\n\tWindow_Print(\"%d\", num);\n}\n\t\t\t\n\n/***************************************************************************\n * WINDOW_PRINT -- Displays and wraps text into a window.                  *\n *                                                                         *\n *    This is the general purpos text output routine that will handle      *\n *    word wrap within a window.  It is useful for displaying arbitrary    *\n *    text.  This routine will handle dipthonged text and as such it       *\n *    can be quite useful in saving memory.                                *\n *                                                                         *\n * INPUT:   string   -- String to print.  This can be of ANY length and    *\n *                      can even contain some formatting codes.  The       *\n *                      codes supported are:                               *\n *                                                                         *\n *             KA_SETX        Forces the cursor X position to the value    *\n *                            specified.                                   *\n *                                                                         *\n *             KA_SETY        Forces the cursor Y position to the value    *\n *                            specified.                                   *\n *                                                                         *\n *             KA_MORE        Causes an immediate \"<MORE>\" prompt          *\n *                            regardless of the scroll situation.          *\n *                                                                         *\n *             KA_RETURN      Breaks line and continues output at the      *\n *                            left edge of following line.                 *\n *                                                                         *\n *                                                                         *\n *             KA_FORMFEED    Clears the window and continues printing at  *\n *                            the upper left corner.                       *\n *                                                                         *\n *             KA_SETBKGDCOL  Set the background color with the color      *\n *                            specified by the following byte.             *\n *                                                                         *\n *                                                                         *\n *             KA_SETFORECOL  Set the foreground color with the color      *\n *                            specified by the following byte.             *\n *                                                                         *\n *             KA_TAB         Move the cursor over to the next tabstop.    *\n *                            Tabstops are set every 8 columns.            *\n *                                                                         *\n *             KA_SPCTAB      Insert spaces until the cursor is positioned *\n *                            at the next tabstop.                         *\n *                                                                         *\n *             %s             Replace the \"%s\" with the text pointed to    *\n *                            by the pointer argument passed to the        *\n *                            routine (follows same method a printf).      *\n *                                                                         *\n *             %d             Replace the \"%d\" with an integer ASCII       *\n *                            number of the int passed to the routine.    *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *   07/29/1991 JLB : Added MORE, SETX, and SETY                           *\n *=========================================================================*/\nvoid Window_Print(char const string[], ...)\n{\n\tint\t\toldcx, x, y;\t// Scratch variables.\n\tchar\t\tc;\t\t\t\t\t// Current character.\n\tchar\t\tbuffer[10];\t\t// Working %d buffer.\n\tint\t\told_c, old_b;\t// Original window colors.\n\tva_list\targ;\t\t\t\t// Argument list var.\n\n\n\tva_start(arg, string);\n\n\tWordWrapFlag = FALSE;\t\t\t// initialize word wrap flag.\n\tPos = PPos = 0;\n\tLine[0] = '\\0';\n\tChar[0] = Char[1] = 0;\n\tMainSource = (char*)&string[0];\n\tAltSource = NULL;\n\told_c = WinC;\n\told_b = WinB;\n\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Hide_Mouse(Window);\n//BG\t}\n\n\twhile (TRUE) {\n\n\t\tc = Fetch_Char();\n\n\t\tif (!c) break;\t// Exit on NULL character.\n\n\t\t/*\n\t\t**\tSubstitution commands only work if not already expanding a\n\t\t**\tstring.\n\t\t*/\n\t\tif (!AltSource) {\n\t\t\tif (c == '%') {\n\t\t \t\tswitch(tolower(Char[0])) {\n\t\t\t\t\tcase 's':\n\t\t\t\t\t\tAltSource = va_arg(arg, char*);\n\t\t\t\t\t\tif (AltSource) {\n\t\t\t\t\t\t\tStack = Char[1];\n\t\t\t\t\t\t\tChar[0] = Char[1] = '\\0';\n\t\t\t\t\t\t\tc = Fetch_Char();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'd':\n\t\t\t\t\t\tAltSource = buffer;\n\t\t\t\t\t\tsprintf(buffer, \"%d\", va_arg(arg, int));\n\t\t\t\t\t\tStack = Char[1];\n\t\t\t\t\t\tChar[0] = Char[1] = '\\0';\n\t\t\t\t\t\tc = Fetch_Char();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tswitch(c) {\n\n#if(FALSE)\n\t// these are the positions of foreign language characters\n\t\t\t/*\n\t\t\t** These are characters that shouldn't be window printed because\n\t\t\t**\tthey are currently reserved.\n\t\t\t*/\n\t\t\tcase KA_CTRL_C:\n\t\t\tcase KA_CTRL_D:\n\t\t\tcase KA_CTRL_E:\n\t\t\tcase KA_CTRL_G:\n\t\t\tcase KA_CTRL_J:\n\t\t\tcase KA_CTRL_K:\n\t\t\tcase KA_CTRL_N:\n\t\t\tcase KA_CTRL_O:\n\t\t\tcase KA_CTRL_P:\n\t\t\tcase KA_CTRL_Q:\n\t\t\tcase KA_CTRL_R:\n\t\t\tcase KA_CTRL_T:\n\t\t\tcase KA_CTRL_U:\n\t\t\tcase KA_CTRL_V:\n\t\t\tcase KA_CTRL_W:\n\t\t\tcase KA_CTRL_Z:\n\t\t\tcase KA_CTRL_BACKSLASH:\n\t\t\tcase KA_CTRL_CARROT:\n\t\t\tcase KA_CTRL_UNDERLINE:\n\t\t\t\tbreak;\n#endif\n\t\t\t/*\n\t\t\t**\tForce cursor column to specified X value.\n\t\t\t*/\n\t\t\tcase KA_SETX:\n\t\t\t\tFlush_Line();\n\t\t\t\tWPos  = Fetch_Char();\n\t\t\t\tWPos  = MAX(0, WPos);\n\n\t\t\t\t// WPos is max width char position\n\n\t\t\t\tWPos  = MIN(WindowColumns-1, WPos);\n\t\t\t\tWinCx = WPos * (FontWidth+FontXSpacing);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tForce the cursor to specified Y value.\n\t\t\t*/\n\t\t\tcase KA_SETY:\n\t\t\t\tFlush_Line();\n\t\t\t\tWinCy = Fetch_Char();\n\t\t\t\t//WinCy = MAX(0, WinCy);\n\t\t\t\tWinCy = MIN((long)WindowLines-1, (long)WinCy);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tForce a \"<MORE>\" prompt.\n\t\t\t*/\n\t\t\tcase KA_MORE:\n\t\t\t\tFlush_Line();\n\t\t\t\tif (Window_More_Ptr) {\n//BG\t\t\t\t\tif (LogicPage == SEENPAGE) Window_Show_Mouse();\n\t\t\t\t\tWindow_More_Ptr(TXT_MoreText, MoreSpace, MoreFColor, MoreBColor);\n//BG\t\t\t\t\tif (LogicPage == SEENPAGE) Window_Hide_Mouse(Window);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tClear and home the window cursor.  This is the same\n\t\t\t**\tas New_Window().\n\t\t\t*/\n\t\t\tcase KA_FORMFEED:\n\t\t\t\tNew_Window();\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tMove cursor to start of next line.\n\t\t\t*/\n\t\t\tcase KA_RETURN:\n\t\t\t\tFlush_Line();\n\t\t\t\tScrollCounter++;\n\t\t\t\tWinCx = 0;\n\n#if(FALSE)\n\t\t\t\tif (WinCy >= WindowLines-1) {\n\t\t\t\t\tScroll_Window();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tWinCy++;\n\t\t\t\t}\n#else\n\t  \t\t\tWinCy++;\n#endif\n\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tSet the background color.\n\t\t\t*/\n\t\t\tcase KA_SETBKGDCOL:\n\t\t\t\tFlush_Line();\n\t\t\t\tWinB = Fetch_Char();\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tSet the foreground color.\n\t\t\t*/\n\t\t\tcase KA_SETFORECOL:\n\t\t\t\tFlush_Line();\n\t\t\t\tWinC = Fetch_Char();\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tMove cursor to next column.\n\t\t\t*/\n\t\t\tcase KA_TAB:\n\t\t\t\tFlush_Line();\n\t\t\t\tWPos = ((WPos + 8) & 0xFFF8) - 1;\n\t\t\t\tif (WPos >= WindowColumns) {\n\t\t\t\t\tWPos = 0;\n\t\t\t\t}\n\t\t\t\tWinCx = WPos * (FontWidth+FontXSpacing);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tTab to specified column but add spaces.\n\t\t\t*/\n\t\t\tcase KA_SPCTAB:\n\t\t\t\tFlush_Line();\n\t\t\t\toldcx = WinCx;\n\t\t\t\tx = WinX << 3;\n\t\t\t\ty = WinY + (WinCy * (FontHeight+FontYSpacing));\n\t\t\t\tWPos = ((WPos + 8) & 0xFFF8) - 1;\n\n\t\t\t\tif (WPos >= WindowColumns) {\n\t\t\t\t\tWinCx = WPos = 0;\n\n\t\t\t\t\t// Fill_Rect instead of printing spaces\n\n\t\t\t\t\tLogicPage->Fill_Rect(x + oldcx, y,\n\t\t\t\t\t\t\t\tx + WindowWidth - 1, y + (FontHeight+FontYSpacing) - 1, WinB);\n\n\t\t\t\t\tScrollCounter++;\n\t\t  \t\t\tWinCy++;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tWinCx = WPos * (FontWidth+FontXSpacing);\n\n\t\t\t\t\t// Fill_Rect instead of printing spaces\n\n\t\t\t\t\tLogicPage->Fill_Rect(x + oldcx, y,\n\t\t\t\t\t\t\t\tx + WinCx - 1, y + (FontHeight+FontYSpacing) - 1, WinB);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tnext character is a extended value 1-127, but 128 is added\n\t\t\t** for a value 129-255\n\t\t\t*/\n\t\t\tcase KA_EXTEND:\n\t\t\t\tc = 127;\n\n\t\t\t// NOTE: this falls thru to the default case DO NOT MOVE!!!!!\n\n\n\t\t\t/*\n\t\t\t**\tnext character is a literal value 1-127, except 13\n\t\t\t*/\n\t\t\tcase KA_LITERAL:\n\t\t\t\tif (c != (char) 127) {\t// check if fell thru from extend case\n\t\t\t\t\tc = 0;\t\t\t\t\t// set to zero for literal case\n\t\t\t\t}\n\t\t\t\tc += Fetch_Char();\n\n\t\t\t// NOTE: this falls thru to the default case DO NOT MOVE!!!!!\n\n\n\t\t\t/*\n\t\t\t**\tNormal character output.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\tPPos += Char_Pixel_Width(c);\t// get pixel location of next char\n\t\t\t\tLine[Pos++] = c;\n\t\t\t\tLine[Pos] = '\\0';\n\n\t\t\t\tif (WinCx + PPos > WindowWidth) {\n\t\t\t\t\tFlush_Line();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is text still pending, then display it before exiting.\n\t*/\n\tif (Pos) Flush_Line();\n\n\t/*\n\t**\tRecord changes in the cursor position.\n\t*/\n\tWindowList[Window][WINDOWCURSORX] = WinCx;\n\tWindowList[Window][WINDOWCURSORY] = WinCy;\n\n\t/*\n\t**\tRestore the window colors to their original values.\n\t*/\n\tWindowList[Window][WINDOWFCOL] = WinC = old_c;\n\tWindowList[Window][WINDOWBCOL] = WinB = old_b;\n\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Show_Mouse();\n//BG\t}\n\n\tva_end(arg);\n}\n\n\n/***************************************************************************\n * SCROLL_WINDOW -- Scrolls the text window up one line.                   *\n *                                                                         *\n *    This will scroll the text window up one line.  It will handle any    *\n *    pausing for \"more\" if the MoreOn flag is set.                        *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine assumes that the LogicPage is the SEENPAGE.    *\n *             If this is not the case, the program may appear to hang     *\n *             if a \"more\" prompt is generated.                            *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void Scroll_Window(void)\n{\n\tint\ty;\t\t// Top pixel row of bottom line of window.\n\n\t/*\n\t**\tPossibly prompt for more text.\n\t*/\n\tif (ScrollCounter >= WindowLines-1 && MoreOn) {\n\t\tScrollCounter = 0;\n\n\t\tif (Window_More_Ptr) {\n//BG\t\t\tif (LogicPage == SEENPAGE) Window_Show_Mouse();\n\t\t\tWindow_More_Ptr(TXT_MoreText, MoreSpace, MoreFColor, MoreBColor);\n//BG\t\t\tif (LogicPage == SEENPAGE) Window_Hide_Mouse(Window);\n\t\t}\n\t}\n\n\t/*\n\t**\tScroll the window up one line.\n\t*/\n\ty = ((WinH / (FontHeight+FontYSpacing)) - 1) * (FontHeight+FontYSpacing);\n\tLogicPage->Blit(*LogicPage,WinX<<3, WinY + (FontHeight+FontYSpacing), WinX<<3, WinY, WinW<<3, WinH - (FontHeight+FontYSpacing) );\n\tLogicPage->Fill_Rect(WinX<<3, \n\t\t\t\tWinY + y, \n\t\t\t\t((WinX+WinW)<<3) - 1,\n\t\t\t\tWinY + WinH - 1, \n\t\t\t\tWinB);\n}\n\n\n/***************************************************************************\n * FLUSH_LINE -- Outputs the accumulate text line to screen.               *\n *                                                                         *\n *    This will display the accumlated text line to the screen.  It will   *\n *    handle breaking the text line at an appropriate position.            *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void Flush_Line(void)\n{\n\tint\tbreakit, breaksize, breakwidth;\n\tint\tx, y;\t\t\t\t\t// Coordinates of text print.\n\tint\tbreakpoint;\t\t\t// Point to break the line (if possible).\n\tchar\tbreakchar;\t\t\t// Break replace character.\n\tint\tindex;\t\t\t\t// Backward moving index var.\n\n\t/*\n\t** There could be a held <CR> and this is implied by the cursor Y position\n\t** beyond the bottom of the window.  If this is the case, then scroll the\n\t**\twindow and proceed with the line flush.\n\t*/\n\twhile (WinCy >= WindowLines /*&& Pos > 0*/) {\n\t\tScroll_Window();\n\t\tif (WinCy >= WindowLines) WinCy--;\n\t}\n\t//if (WinCy >= WindowLines) WinCy = WindowLines-1;\n\n\tx = (WinX<<3) + WinCx;\n\ty = WinY + (WinCy*(FontHeight+FontYSpacing));\n\n\tbreakwidth = WindowWidth;\n//\tif (ScrollCounter >= WindowLines - 1 && MoreOn) {\n//\t\tbreakwidth -= (MoreSpace * (FontWidth+FontXSpacing));\t\t// use maximum font width\n//\t}\n\n\t/*\n\t**\tTry to break the line at the last space IF the line has reached the edge\n\t**\tof the window.\n\t*/\n\tbreakpoint = Pos;\n\tbreaksize = PPos;\n\tif (WinCx + breaksize > breakwidth) {\n\t\t\n\t\t/*\n\t\t**\tSince the text WILL spill past the edge of the window, determine the \n\t\t**\tpoint where the break should occur.  If this line is ready for the <MORE>\n\t\t**\tprompt, then breaking must account for the <MORE> text.\n\t\t*/\n\t\tif (ScrollCounter >= WindowLines - 1 && MoreOn) {\n\t\t\tbreakwidth -= (MoreSpace * (FontWidth+FontXSpacing));\t\t// use maximum font width\n\t\t}\n\t\tbreakwidth -= WinCx;\n\n\t\tbreakit = 0;\n\t\tfor (index = breakpoint - 1; index > 0; index--) {\n\t\t\tbreakchar = Line[index];\n\t\t\tbreaksize -= Char_Pixel_Width(breakchar);\n\n\t\t\t// only once, find largest text that can fit on the line\n\t\t\tif (!breakit) {\n\t\t\t\t// was this the char that went past the right edge\n\t\t\t\tif (breaksize <= breakwidth) {\n\t\t\t\t\tbreakit = index;\t// save this position if there is no spaces\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// after largest text is found then look for a space to break on\n\t\t\tif (breakit && breakchar == KA_SPACE) {\n\t\t\t\tbreakpoint = index;\n\t\t\t\tWordWrapFlag = FALSE; // word will start at beginning of next line\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tException: When the current text buffer cannot be broken at a logical\n\t\t**\tplace AND the text is starting past the left margin, THEN there is\n\t\t**\tan implied break between the previous text output and this one.\n\t\t**\tOutput the current text on the next line left margin.\n\t\t*/\n\t\tif (!index) {\n\t\t\tif (WinCx && !WordWrapFlag) {\n\t\t\t\tbreakpoint = breaksize = 0;\t\t// Continue text on next line.\n\t\t\t\tWordWrapFlag = TRUE;\t\t// indicate a word continuation.\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbreakpoint = breakit;\t// Just print as much as possible.\n\t\t\t}\n\t\t}\n\t}\n\n\tbreakchar = Line[breakpoint];\n\tLine[breakpoint] = '\\0';\n\n\tLogicPage->Print(Line, x, y, WinC, WinB);\n\tWinCx += breaksize;\t\t\t\t\t// add size of text string printed.\n\n\tLine[breakpoint] = breakchar;\n\tif (breakchar == KA_SPACE) {\t\t// take out a space between words.\n\t\tbreakpoint++;\n\t}\n\n\t// take out another space for double spacing after end of sentence.\n\tif (Line[breakpoint] == KA_SPACE) {\n\t\tbreakpoint++;\n\t}\n\n\tstrcpy(Line, &Line[breakpoint]);\n\tPos = strlen(Line);\n\tPPos = String_Pixel_Width(Line);\n\n\t/*\n\t**\tIf at this point there is still text in the buffer, then flushing has\n\t**\tnot been completed.  Scroll to next line and repeat the text flushing\n\t**\tprocess.\n\t*/\n\tif (Pos || WinCx >= WindowWidth) {\n\t\tWinCx = WPos = 0;\n\t\t#if(FALSE)\n\t\t\tif (WinCy >= WindowLines-1) {\n\t\t\t\tScroll_Window();\n\t\t\t} else {\n\t\t\t\tWinCy++;\n\t\t\t}\n\t\t#else\n\t\t\tWinCy++;\n\t\t#endif\n\t\tFlush_Line();\n\t\tScrollCounter++;\t// must be done after flush line for correct counting\n\t}\n}\n\n\n/***************************************************************************\n * IN_CHAR -- Stores (un-dipped) character(s) from input to buffer.        *\n *                                                                         *\n *    Use this routine to fetch the next character from the input stream.  *\n *    If the character was dipthonged, then it will be broken into its     *\n *    component ASCII characters and stored in the specified location.     *\n *    This is the core character stream reading code.                      *\n *                                                                         *\n * INPUT:   str   -- char pointer to the position to store the character(s)*\n *                   fetched from the input stream.                        *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void In_Char(char *str)\n{\n\tchar\tc;\t\t// Character to return.\n\tchar\tnext;\t// Following character (if any).\n\n\tc = next = '\\0';\n\n\t/*\n\t**\tFetch a raw byte from the input stream.\n\t*/\n\tif (AltSource) {\n\t\tif (*AltSource == '\\0') {\n\t\t\tAltSource = NULL;\n\t\t\tc = Stack;\n\t\t} else {\n\t\t\tc = *AltSource++;\n\t\t}\n\t}\n\n\tif (!c && MainSource) {\n\t\tif (*MainSource == '\\0') {\n\t\t\tMainSource = NULL;\n\t\t} else {\n\t\t\tc = *MainSource++;\n\t\t}\n\t}\n\n\t/*\n\t**\tConvert a dipthong character into it's component\n\t**\tASCII characters.\n\t*/\n\tif (c & 0x80) {\n\t\tc &= 0x7F;\n\t\tnext = c & 0x07;\n\t\tc = (c & 0x78) >> 3;\n\n\t\tnext = Dipthong[c][next];\t// Dipthong character.\n\t\tc = Common[c];\t\t\t\t// Common character.\n\t}\n\n\t*str++ = c;\n\t*str = next;\n}\n\n\n/***************************************************************************\n * FETCH_CHAR -- Gets one undipthonged char from input.                    *\n *                                                                         *\n *    This routine will fetch one character from the input stream.  The    *\n *    character has already been un-dipthonged.  It is a straight ASCII    *\n *    character.  This routine ensures that if the next character in the   *\n *    input stream needs to be examined, it is available in Char[0].       *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  Returns next character in the input stream (ASCII).  If NULL   *\n *          is returned, then this indicates the end of the input stream.  *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE char Fetch_Char(void)\n{\n\tchar\tc;\t\t// Character to return.\n\n\tif (!Char[0]) {\n\t\tIn_Char(&Char[0]);\n\t}\n\n\tc = Char[0];\n\tChar[0] = Char[1];\n\tChar[1] = '\\0';\n\n\tif (!Char[0]) {\n\t\tIn_Char(&Char[0]);\n\t}\n\n\treturn (c);\n}\n\u001a\n"
  },
  {
    "path": "WWFLAT32/WINDOWS/WINDOWS.CPP.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./windows.c 1.12 1994/05/20 15:35:25 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : LIBRARY                                  *\n *                                                                         *\n *                    File Name : WINDOWS.C                                *\n *                                                                         *\n *                   Programmer : Everyone                                 *\n *                                                                         *\n *                  Last Update : February 3, 1992   [DRD]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Change_New_Window -- Combined Change_Window and New_Window.           *\n *   Change_Window -- Changes the 'current' window in the system.          *\n *   Fetch_Char -- Gets one undipthonged char from input.                  *\n *   Flush_Line -- Outputs the accumulate text line to screen.             *\n *   In_Char -- Stores (un-dipped) character(s) from input to buffer.      *\n *   New_Window -- Clears the current window to the background color.      *\n *   Set_More_Off -- Turns the 'more' prompting off.                       *\n *   Set_More_On -- Turns the 'more' prompting on.                         *\n *   Set_More_Prompt -- Adjusts the more prompt text for default routine   *\n *   Standard_More_Prompt -- Default more prompt code for Window_Print     *\n *   Window_Int_Print -- Prints an integer to the window.                  *\n *   Window_Print -- Displays and wraps text into a window.                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <ctype.h>\n#include <stdlib.h>\n#include <string.h>\n#include\t<stdio.h>\n#include\t<stdarg.h>\n#include <wwstd.h>\n#include \"windows.h\"\n#include <keyboard.h>\n#include\t<font.h>\n#include <dipthong.h>\n\nPRIVATE void Scroll_Window(void);\nPRIVATE void Flush_Line(void);\nPRIVATE void In_Char(char *str);\nPRIVATE char Fetch_Char(void);\n\n\nPRIVATE int ScrollCounter = 0;\t//\tCount of the lines displayed before a pause.\nPRIVATE char Line[84];\t// Staging line buffer.\nPRIVATE int Pos;\t\t\t// Char Position of next free character.\nPRIVATE int PPos;\t\t// Pixel position of next free character.\nPRIVATE int WPos;\t\t// Char position in window.\nPRIVATE char *MainSource;\nPRIVATE char *AltSource;\nPRIVATE char Char[2];\nPRIVATE char Stack;\nPRIVATE char WordWrapFlag = FALSE;\t// flag for a word wrap.\n\nPRIVATE int MoreSpace = 7;\nPRIVATE int MoreFColor = 0;\nPRIVATE int MoreBColor = 0;\n\n\nint WindowColumns=40;\nint WindowLines=25;\nint WindowWidth=40;\nunsigned int WinB=0;\nunsigned int WinC=1;\nunsigned int WinX=0;\nunsigned int WinY=0;\nunsigned int WinCx=0;\nunsigned int WinCy=0;\nunsigned int WinH=25;\nunsigned int WinW=40;\nunsigned int Window=0;\n\nint MoreOn = TRUE;\nchar *TXT_MoreText = \"--More--\";\nvoid (*Window_More_Ptr)(BYTE const *,int,int,int) = Standard_More_Prompt;\n\nextern GraphicBufferClass *LogicPage;\n/***************************************************************************\n * STANDARD_MORE_PROMPT -- Default more prompt code for Window_Print       *\n *                                                                         *\n *    This is the standard \"<more>\" prompting code that is used by         *\n *    Window_Print when a page is full of text and a pause is desired      *\n *    before the next page of text is printed.  This function is called    *\n *    through the Window_More_Ptr global.                                  *\n *                                                                         *\n * INPUT:   prompt   -- Pointer to ASCII text that will be window printed  *\n *                      at the right margin.                               *\n *                                                                         *\n *          space    -- The number of spaces to allow for the 'more' text. *\n *                                                                         *\n *          fcolor   -- The foreground color to use for the 'more' text.   *\n *                                                                         *\n *          bcolor   -- The background oclor to use for the 'more' text.   *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/29/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Standard_More_Prompt(char const *prompt, int space, int fcolor, int bcolor)\n{\n\tint\tx, y, moresize;\n\t\n\tmoresize = (space - 1) * (FontWidth+FontXSpacing);\n\tx = ((WinX+WinW) << 3) - moresize;\n\t//y = WinY + ((WinH/FontHeight)-1)*FontHeight;\n\ty = WinY + (WinCy-1) * (FontHeight+FontYSpacing);\n\n\t// Default \"more\" prompter.\n\tLogicPage->Print(prompt, x, y, fcolor ? fcolor : WindowList[Window][WINDOWBCOL], bcolor ? bcolor : WindowList[Window][WINDOWFCOL]);\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Show_Mouse();\n//BG\t}\n\n\tClear_KeyBuffer();\n\tGet_Key();\n\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Hide_Mouse(Window);\n//BG\t}\n\n\t// Erase the more prompt prompt.\n\t//\tText_Print(prompt, x, y, WinB, WinB);\n\tLogicPage->Fill_Rect(x, y, x + moresize - 1, y + (FontHeight+FontYSpacing) - 1, WinB);\n}\n\n\n/***************************************************************************\n * SET_MORE_PROMPT -- Adjusts the more prompt text for default routine     *\n *                                                                         *\n *    Use this routine to control the text of the \"<MORE>\" prompt that     *\n *    the default more prompt routine uses.  This can be useful for        *\n *    foreign language translations.                                       *\n *                                                                         *\n * INPUT:   prompt   -- Pointer to ASCII text that will be window printed  *\n *                      at the right margin.                               *\n *                                                                         *\n *          space    -- The number of spaces to allow for the 'more' text. *\n *                                                                         *\n *          fcolor   -- The foreground color to use for the 'more' text.   *\n *                                                                         *\n *          bcolor   -- The background color to use for the 'more' text.   *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/29/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Set_More_Prompt(char const *prompt, int space, int fcolor, int bcolor)\n{\n\tif (prompt) {\n\t\tTXT_MoreText = (char*)prompt;\n\t\tMoreSpace = space;\n\t\tMoreFColor = fcolor;\n\t\tMoreBColor = bcolor;\n\t}\n\telse {\n\t\tTXT_MoreText = \"<MORE>\";\n\t\tMoreSpace = 7;\n\t\tMoreFColor = MoreBColor = 0;\n\t}\n}\n\n\n/***************************************************************************\n * SET_MORE_ON -- Turns the 'more' prompting on.                           *\n *                                                                         *\n *    Use this routine to turn on the 'more' prompting that Window_Print   *\n *    does.  If you have a custom more function pointer, then that         *\n *    routine will be called, otherwise the library default 'more' prompt  *\n *    will be utilized.                                                    *\n *                                                                         *\n * INPUT:      none                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Set_More_On(void)\n{\n\tMoreOn = TRUE;\n\tScrollCounter = 0;\n}\n\n\n/***************************************************************************\n * SET_MORE_OFF -- Turns the 'more' prompting off.                         *\n *                                                                         *\n *    This routine will turn the 'more' prompting that Window_Print does   *\n *    off.                                                                 *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Set_More_Off(void)\n{\n\tMoreOn = FALSE;\n}\n\n\n/***************************************************************************\n * CHANGE_WINDOW -- Changes the 'current' window in the system.            *\n *                                                                         *\n *    Use this routine to change the 'current' window.  The current window *\n *    is used in Window_Print and some other graphic output routines.      *\n *                                                                         *\n * INPUT:   windnum  -- The window number to change to.                    *\n *                                                                         *\n * OUTPUT:  Returns with the previously current window.                    *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nint Change_Window(int windnum)\n{\n\tint\toldwindow;\n\tint\t*data;\n\n\toldwindow = Window;\n\tWindow = windnum;\n\tdata = &WindowList[windnum][0];\n\n\tWinX = *data++;\n\tWinY = *data++;\n\tWinW = *data++;\n\tWinH = *data++;\n\tWinC = *data++;\n\tWinB = *data++;\n\tWinCx = *data++;\n\tWinCy = *data++;\n\tScrollCounter = 0;\n\tWPos = WinCx / (FontWidth+FontXSpacing);\n\tWindowLines = (WinH-FontYSpacing) / (FontHeight+FontYSpacing);\n\tWindowWidth = WinW << 3;\n\tWindowColumns = WindowWidth / (FontWidth+FontXSpacing);\n\treturn (oldwindow);\n}\n\n\n/***************************************************************************\n * CHANGE_NEW_WINDOW -- Combined Change_Window and New_Window.             *\n *                                                                         *\n *    This is a combo-routine.  It merely combines the Change_Window       *\n *    with the New_Window routines.  It will save some (small) code if     *\n *    you use this routine instead of the two function calls.              *\n *                                                                         *\n * INPUT:   window   -- Window number to change to and clear.              *\n *                                                                         *\n * OUTPUT:  Returns with the previously current window.                    *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nint Change_New_Window(int windnum)\n{\n\tint\toldwindow;\n\n\toldwindow = Change_Window(windnum);\n\tNew_Window();\n\treturn(oldwindow);\n}\n\n\n/***************************************************************************\n * NEW_WINDOW -- Clears the current window to the background color.        *\n *                                                                         *\n *    This routine clears the current window to the background color.  It  *\n *    is used in preparation to Window_Print because it ensures a clean    *\n *    'slate' for the text.                                                *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid New_Window(void)\n{\n\tint\tx,y,w,h;\n\n\tx = WinX << 3;\n\ty = WinY;\n\tw = (WinX + WinW) << 3;\n\th = WinY + WinH;\n\n\tLogicPage->Fill_Rect(x, y, w - 1, h - 1, WinB);\n\n\tWinCx = WPos = 0;\n\tWinCy = 0;\n\tScrollCounter = 0;\n}\n\n\n/***************************************************************************\n * WINDOW_INT_PRINT -- Prints an integer to the window.                    *\n *                                                                         *\n *    Use this routine to print an integer to the window.  This routine    *\n *    as all other Window printing routines will handle word wrap.         *\n *                                                                         *\n * INPUT:   num   -- The integer to convert to ASCII and print.            *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Window_Int_Print(int num)\n{\n\tWindow_Print(\"%d\", num);\n}\n\t\t\t\n\n/***************************************************************************\n * WINDOW_PRINT -- Displays and wraps text into a window.                  *\n *                                                                         *\n *    This is the general purpos text output routine that will handle      *\n *    word wrap within a window.  It is useful for displaying arbitrary    *\n *    text.  This routine will handle dipthonged text and as such it       *\n *    can be quite useful in saving memory.                                *\n *                                                                         *\n * INPUT:   string   -- String to print.  This can be of ANY length and    *\n *                      can even contain some formatting codes.  The       *\n *                      codes supported are:                               *\n *                                                                         *\n *             KA_SETX        Forces the cursor X position to the value    *\n *                            specified.                                   *\n *                                                                         *\n *             KA_SETY        Forces the cursor Y position to the value    *\n *                            specified.                                   *\n *                                                                         *\n *             KA_MORE        Causes an immediate \"<MORE>\" prompt          *\n *                            regardless of the scroll situation.          *\n *                                                                         *\n *             KA_RETURN      Breaks line and continues output at the      *\n *                            left edge of following line.                 *\n *                                                                         *\n *                                                                         *\n *             KA_FORMFEED    Clears the window and continues printing at  *\n *                            the upper left corner.                       *\n *                                                                         *\n *             KA_SETBKGDCOL  Set the background color with the color      *\n *                            specified by the following byte.             *\n *                                                                         *\n *                                                                         *\n *             KA_SETFORECOL  Set the foreground color with the color      *\n *                            specified by the following byte.             *\n *                                                                         *\n *             KA_TAB         Move the cursor over to the next tabstop.    *\n *                            Tabstops are set every 8 columns.            *\n *                                                                         *\n *             KA_SPCTAB      Insert spaces until the cursor is positioned *\n *                            at the next tabstop.                         *\n *                                                                         *\n *             %s             Replace the \"%s\" with the text pointed to    *\n *                            by the pointer argument passed to the        *\n *                            routine (follows same method a printf).      *\n *                                                                         *\n *             %d             Replace the \"%d\" with an integer ASCII       *\n *                            number of the int passed to the routine.    *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *   07/29/1991 JLB : Added MORE, SETX, and SETY                           *\n *=========================================================================*/\nvoid Window_Print(char const string[], ...)\n{\n\tint\t\toldcx, x, y;\t// Scratch variables.\n\tchar\t\tc;\t\t\t\t\t// Current character.\n\tchar\t\tbuffer[10];\t\t// Working %d buffer.\n\tint\t\told_c, old_b;\t// Original window colors.\n\tva_list\targ;\t\t\t\t// Argument list var.\n\n\n\tva_start(arg, string);\n\n\tWordWrapFlag = FALSE;\t\t\t// initialize word wrap flag.\n\tPos = PPos = 0;\n\tLine[0] = '\\0';\n\tChar[0] = Char[1] = 0;\n\tMainSource = (char*)&string[0];\n\tAltSource = NULL;\n\told_c = WinC;\n\told_b = WinB;\n\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Hide_Mouse(Window);\n//BG\t}\n\n\twhile (TRUE) {\n\n\t\tc = Fetch_Char();\n\n\t\tif (!c) break;\t// Exit on NULL character.\n\n\t\t/*\n\t\t**\tSubstitution commands only work if not already expanding a\n\t\t**\tstring.\n\t\t*/\n\t\tif (!AltSource) {\n\t\t\tif (c == '%') {\n\t\t \t\tswitch(tolower(Char[0])) {\n\t\t\t\t\tcase 's':\n\t\t\t\t\t\tAltSource = va_arg(arg, char*);\n\t\t\t\t\t\tif (AltSource) {\n\t\t\t\t\t\t\tStack = Char[1];\n\t\t\t\t\t\t\tChar[0] = Char[1] = '\\0';\n\t\t\t\t\t\t\tc = Fetch_Char();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'd':\n\t\t\t\t\t\tAltSource = buffer;\n\t\t\t\t\t\tsprintf(buffer, \"%d\", va_arg(arg, int));\n\t\t\t\t\t\tStack = Char[1];\n\t\t\t\t\t\tChar[0] = Char[1] = '\\0';\n\t\t\t\t\t\tc = Fetch_Char();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tswitch(c) {\n\n#if(FALSE)\n\t// these are the positions of foreign language characters\n\t\t\t/*\n\t\t\t** These are characters that shouldn't be window printed because\n\t\t\t**\tthey are currently reserved.\n\t\t\t*/\n\t\t\tcase KA_CTRL_C:\n\t\t\tcase KA_CTRL_D:\n\t\t\tcase KA_CTRL_E:\n\t\t\tcase KA_CTRL_G:\n\t\t\tcase KA_CTRL_J:\n\t\t\tcase KA_CTRL_K:\n\t\t\tcase KA_CTRL_N:\n\t\t\tcase KA_CTRL_O:\n\t\t\tcase KA_CTRL_P:\n\t\t\tcase KA_CTRL_Q:\n\t\t\tcase KA_CTRL_R:\n\t\t\tcase KA_CTRL_T:\n\t\t\tcase KA_CTRL_U:\n\t\t\tcase KA_CTRL_V:\n\t\t\tcase KA_CTRL_W:\n\t\t\tcase KA_CTRL_Z:\n\t\t\tcase KA_CTRL_BACKSLASH:\n\t\t\tcase KA_CTRL_CARROT:\n\t\t\tcase KA_CTRL_UNDERLINE:\n\t\t\t\tbreak;\n#endif\n\t\t\t/*\n\t\t\t**\tForce cursor column to specified X value.\n\t\t\t*/\n\t\t\tcase KA_SETX:\n\t\t\t\tFlush_Line();\n\t\t\t\tWPos  = Fetch_Char();\n\t\t\t\tWPos  = MAX(0, WPos);\n\n\t\t\t\t// WPos is max width char position\n\n\t\t\t\tWPos  = MIN(WindowColumns-1, WPos);\n\t\t\t\tWinCx = WPos * (FontWidth+FontXSpacing);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tForce the cursor to specified Y value.\n\t\t\t*/\n\t\t\tcase KA_SETY:\n\t\t\t\tFlush_Line();\n\t\t\t\tWinCy = Fetch_Char();\n\t\t\t\t//WinCy = MAX(0, WinCy);\n\t\t\t\tWinCy = MIN((long)WindowLines-1, (long)WinCy);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tForce a \"<MORE>\" prompt.\n\t\t\t*/\n\t\t\tcase KA_MORE:\n\t\t\t\tFlush_Line();\n\t\t\t\tif (Window_More_Ptr) {\n//BG\t\t\t\t\tif (LogicPage == SEENPAGE) Window_Show_Mouse();\n\t\t\t\t\tWindow_More_Ptr(TXT_MoreText, MoreSpace, MoreFColor, MoreBColor);\n//BG\t\t\t\t\tif (LogicPage == SEENPAGE) Window_Hide_Mouse(Window);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tClear and home the window cursor.  This is the same\n\t\t\t**\tas New_Window().\n\t\t\t*/\n\t\t\tcase KA_FORMFEED:\n\t\t\t\tNew_Window();\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tMove cursor to start of next line.\n\t\t\t*/\n\t\t\tcase KA_RETURN:\n\t\t\t\tFlush_Line();\n\t\t\t\tScrollCounter++;\n\t\t\t\tWinCx = 0;\n\n#if(FALSE)\n\t\t\t\tif (WinCy >= WindowLines-1) {\n\t\t\t\t\tScroll_Window();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tWinCy++;\n\t\t\t\t}\n#else\n\t  \t\t\tWinCy++;\n#endif\n\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tSet the background color.\n\t\t\t*/\n\t\t\tcase KA_SETBKGDCOL:\n\t\t\t\tFlush_Line();\n\t\t\t\tWinB = Fetch_Char();\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tSet the foreground color.\n\t\t\t*/\n\t\t\tcase KA_SETFORECOL:\n\t\t\t\tFlush_Line();\n\t\t\t\tWinC = Fetch_Char();\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tMove cursor to next column.\n\t\t\t*/\n\t\t\tcase KA_TAB:\n\t\t\t\tFlush_Line();\n\t\t\t\tWPos = ((WPos + 8) & 0xFFF8) - 1;\n\t\t\t\tif (WPos >= WindowColumns) {\n\t\t\t\t\tWPos = 0;\n\t\t\t\t}\n\t\t\t\tWinCx = WPos * (FontWidth+FontXSpacing);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tTab to specified column but add spaces.\n\t\t\t*/\n\t\t\tcase KA_SPCTAB:\n\t\t\t\tFlush_Line();\n\t\t\t\toldcx = WinCx;\n\t\t\t\tx = WinX << 3;\n\t\t\t\ty = WinY + (WinCy * (FontHeight+FontYSpacing));\n\t\t\t\tWPos = ((WPos + 8) & 0xFFF8) - 1;\n\n\t\t\t\tif (WPos >= WindowColumns) {\n\t\t\t\t\tWinCx = WPos = 0;\n\n\t\t\t\t\t// Fill_Rect instead of printing spaces\n\n\t\t\t\t\tLogicPage->Fill_Rect(x + oldcx, y,\n\t\t\t\t\t\t\t\tx + WindowWidth - 1, y + (FontHeight+FontYSpacing) - 1, WinB);\n\n\t\t\t\t\tScrollCounter++;\n\t\t  \t\t\tWinCy++;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tWinCx = WPos * (FontWidth+FontXSpacing);\n\n\t\t\t\t\t// Fill_Rect instead of printing spaces\n\n\t\t\t\t\tLogicPage->Fill_Rect(x + oldcx, y,\n\t\t\t\t\t\t\t\tx + WinCx - 1, y + (FontHeight+FontYSpacing) - 1, WinB);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tnext character is a extended value 1-127, but 128 is added\n\t\t\t** for a value 129-255\n\t\t\t*/\n\t\t\tcase KA_EXTEND:\n\t\t\t\tc = 127;\n\n\t\t\t// NOTE: this falls thru to the default case DO NOT MOVE!!!!!\n\n\n\t\t\t/*\n\t\t\t**\tnext character is a literal value 1-127, except 13\n\t\t\t*/\n\t\t\tcase KA_LITERAL:\n\t\t\t\tif (c != (char) 127) {\t// check if fell thru from extend case\n\t\t\t\t\tc = 0;\t\t\t\t\t// set to zero for literal case\n\t\t\t\t}\n\t\t\t\tc += Fetch_Char();\n\n\t\t\t// NOTE: this falls thru to the default case DO NOT MOVE!!!!!\n\n\n\t\t\t/*\n\t\t\t**\tNormal character output.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\tPPos += Char_Pixel_Width(c);\t// get pixel location of next char\n\t\t\t\tLine[Pos++] = c;\n\t\t\t\tLine[Pos] = '\\0';\n\n\t\t\t\tif (WinCx + PPos > WindowWidth) {\n\t\t\t\t\tFlush_Line();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is text still pending, then display it before exiting.\n\t*/\n\tif (Pos) Flush_Line();\n\n\t/*\n\t**\tRecord changes in the cursor position.\n\t*/\n\tWindowList[Window][WINDOWCURSORX] = WinCx;\n\tWindowList[Window][WINDOWCURSORY] = WinCy;\n\n\t/*\n\t**\tRestore the window colors to their original values.\n\t*/\n\tWindowList[Window][WINDOWFCOL] = WinC = old_c;\n\tWindowList[Window][WINDOWBCOL] = WinB = old_b;\n\n//BG\tif (LogicPage == SEENPAGE) {\n//BG\t\tWindow_Show_Mouse();\n//BG\t}\n\n\tva_end(arg);\n}\n\n\n/***************************************************************************\n * SCROLL_WINDOW -- Scrolls the text window up one line.                   *\n *                                                                         *\n *    This will scroll the text window up one line.  It will handle any    *\n *    pausing for \"more\" if the MoreOn flag is set.                        *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   This routine assumes that the LogicPage is the SEENPAGE.    *\n *             If this is not the case, the program may appear to hang     *\n *             if a \"more\" prompt is generated.                            *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void Scroll_Window(void)\n{\n\tint\ty;\t\t// Top pixel row of bottom line of window.\n\n\t/*\n\t**\tPossibly prompt for more text.\n\t*/\n\tif (ScrollCounter >= WindowLines-1 && MoreOn) {\n\t\tScrollCounter = 0;\n\n\t\tif (Window_More_Ptr) {\n//BG\t\t\tif (LogicPage == SEENPAGE) Window_Show_Mouse();\n\t\t\tWindow_More_Ptr(TXT_MoreText, MoreSpace, MoreFColor, MoreBColor);\n//BG\t\t\tif (LogicPage == SEENPAGE) Window_Hide_Mouse(Window);\n\t\t}\n\t}\n\n\t/*\n\t**\tScroll the window up one line.\n\t*/\n\ty = ((WinH / (FontHeight+FontYSpacing)) - 1) * (FontHeight+FontYSpacing);\n\tLogicPage->Blit(*LogicPage,WinX<<3, WinY + (FontHeight+FontYSpacing), WinX<<3, WinY, WinW<<3, WinH - (FontHeight+FontYSpacing) );\n\tLogicPage->Fill_Rect(WinX<<3, \n\t\t\t\tWinY + y, \n\t\t\t\t((WinX+WinW)<<3) - 1,\n\t\t\t\tWinY + WinH - 1, \n\t\t\t\tWinB);\n}\n\n\n/***************************************************************************\n * FLUSH_LINE -- Outputs the accumulate text line to screen.               *\n *                                                                         *\n *    This will display the accumlated text line to the screen.  It will   *\n *    handle breaking the text line at an appropriate position.            *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void Flush_Line(void)\n{\n\tint\tbreakit, breaksize, breakwidth;\n\tint\tx, y;\t\t\t\t\t// Coordinates of text print.\n\tint\tbreakpoint;\t\t\t// Point to break the line (if possible).\n\tchar\tbreakchar;\t\t\t// Break replace character.\n\tint\tindex;\t\t\t\t// Backward moving index var.\n\n\t/*\n\t** There could be a held <CR> and this is implied by the cursor Y position\n\t** beyond the bottom of the window.  If this is the case, then scroll the\n\t**\twindow and proceed with the line flush.\n\t*/\n\twhile (WinCy >= WindowLines /*&& Pos > 0*/) {\n\t\tScroll_Window();\n\t\tif (WinCy >= WindowLines) WinCy--;\n\t}\n\t//if (WinCy >= WindowLines) WinCy = WindowLines-1;\n\n\tx = (WinX<<3) + WinCx;\n\ty = WinY + (WinCy*(FontHeight+FontYSpacing));\n\n\tbreakwidth = WindowWidth;\n//\tif (ScrollCounter >= WindowLines - 1 && MoreOn) {\n//\t\tbreakwidth -= (MoreSpace * (FontWidth+FontXSpacing));\t\t// use maximum font width\n//\t}\n\n\t/*\n\t**\tTry to break the line at the last space IF the line has reached the edge\n\t**\tof the window.\n\t*/\n\tbreakpoint = Pos;\n\tbreaksize = PPos;\n\tif (WinCx + breaksize > breakwidth) {\n\t\t\n\t\t/*\n\t\t**\tSince the text WILL spill past the edge of the window, determine the \n\t\t**\tpoint where the break should occur.  If this line is ready for the <MORE>\n\t\t**\tprompt, then breaking must account for the <MORE> text.\n\t\t*/\n\t\tif (ScrollCounter >= WindowLines - 1 && MoreOn) {\n\t\t\tbreakwidth -= (MoreSpace * (FontWidth+FontXSpacing));\t\t// use maximum font width\n\t\t}\n\t\tbreakwidth -= WinCx;\n\n\t\tbreakit = 0;\n\t\tfor (index = breakpoint - 1; index > 0; index--) {\n\t\t\tbreakchar = Line[index];\n\t\t\tbreaksize -= Char_Pixel_Width(breakchar);\n\n\t\t\t// only once, find largest text that can fit on the line\n\t\t\tif (!breakit) {\n\t\t\t\t// was this the char that went past the right edge\n\t\t\t\tif (breaksize <= breakwidth) {\n\t\t\t\t\tbreakit = index;\t// save this position if there is no spaces\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// after largest text is found then look for a space to break on\n\t\t\tif (breakit && breakchar == KA_SPACE) {\n\t\t\t\tbreakpoint = index;\n\t\t\t\tWordWrapFlag = FALSE; // word will start at beginning of next line\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tException: When the current text buffer cannot be broken at a logical\n\t\t**\tplace AND the text is starting past the left margin, THEN there is\n\t\t**\tan implied break between the previous text output and this one.\n\t\t**\tOutput the current text on the next line left margin.\n\t\t*/\n\t\tif (!index) {\n\t\t\tif (WinCx && !WordWrapFlag) {\n\t\t\t\tbreakpoint = breaksize = 0;\t\t// Continue text on next line.\n\t\t\t\tWordWrapFlag = TRUE;\t\t// indicate a word continuation.\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbreakpoint = breakit;\t// Just print as much as possible.\n\t\t\t}\n\t\t}\n\t}\n\n\tbreakchar = Line[breakpoint];\n\tLine[breakpoint] = '\\0';\n\n\tLogicPage->Print(Line, x, y, WinC, WinB);\n\tWinCx += breaksize;\t\t\t\t\t// add size of text string printed.\n\n\tLine[breakpoint] = breakchar;\n\tif (breakchar == KA_SPACE) {\t\t// take out a space between words.\n\t\tbreakpoint++;\n\t}\n\n\t// take out another space for double spacing after end of sentence.\n\tif (Line[breakpoint] == KA_SPACE) {\n\t\tbreakpoint++;\n\t}\n\n\tstrcpy(Line, &Line[breakpoint]);\n\tPos = strlen(Line);\n\tPPos = String_Pixel_Width(Line);\n\n\t/*\n\t**\tIf at this point there is still text in the buffer, then flushing has\n\t**\tnot been completed.  Scroll to next line and repeat the text flushing\n\t**\tprocess.\n\t*/\n\tif (Pos || WinCx >= WindowWidth) {\n\t\tWinCx = WPos = 0;\n\t\t#if(FALSE)\n\t\t\tif (WinCy >= WindowLines-1) {\n\t\t\t\tScroll_Window();\n\t\t\t} else {\n\t\t\t\tWinCy++;\n\t\t\t}\n\t\t#else\n\t\t\tWinCy++;\n\t\t#endif\n\t\tFlush_Line();\n\t\tScrollCounter++;\t// must be done after flush line for correct counting\n\t}\n}\n\n\n/***************************************************************************\n * IN_CHAR -- Stores (un-dipped) character(s) from input to buffer.        *\n *                                                                         *\n *    Use this routine to fetch the next character from the input stream.  *\n *    If the character was dipthonged, then it will be broken into its     *\n *    component ASCII characters and stored in the specified location.     *\n *    This is the core character stream reading code.                      *\n *                                                                         *\n * INPUT:   str   -- char pointer to the position to store the character(s)*\n *                   fetched from the input stream.                        *\n *                                                                         *\n * OUTPUT:  none                                                           *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE void In_Char(char *str)\n{\n\tchar\tc;\t\t// Character to return.\n\tchar\tnext;\t// Following character (if any).\n\n\tc = next = '\\0';\n\n\t/*\n\t**\tFetch a raw byte from the input stream.\n\t*/\n\tif (AltSource) {\n\t\tif (*AltSource == '\\0') {\n\t\t\tAltSource = NULL;\n\t\t\tc = Stack;\n\t\t} else {\n\t\t\tc = *AltSource++;\n\t\t}\n\t}\n\n\tif (!c && MainSource) {\n\t\tif (*MainSource == '\\0') {\n\t\t\tMainSource = NULL;\n\t\t} else {\n\t\t\tc = *MainSource++;\n\t\t}\n\t}\n\n\t/*\n\t**\tConvert a dipthong character into it's component\n\t**\tASCII characters.\n\t*/\n\tif (c & 0x80) {\n\t\tc &= 0x7F;\n\t\tnext = c & 0x07;\n\t\tc = (c & 0x78) >> 3;\n\n\t\tnext = Dipthong[c][next];\t// Dipthong character.\n\t\tc = Common[c];\t\t\t\t// Common character.\n\t}\n\n\t*str++ = c;\n\t*str = next;\n}\n\n\n/***************************************************************************\n * FETCH_CHAR -- Gets one undipthonged char from input.                    *\n *                                                                         *\n *    This routine will fetch one character from the input stream.  The    *\n *    character has already been un-dipthonged.  It is a straight ASCII    *\n *    character.  This routine ensures that if the next character in the   *\n *    input stream needs to be examined, it is available in Char[0].       *\n *                                                                         *\n * INPUT:   none                                                           *\n *                                                                         *\n * OUTPUT:  Returns next character in the input stream (ASCII).  If NULL   *\n *          is returned, then this indicates the end of the input stream.  *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/25/1991 JLB : Created.                                             *\n *=========================================================================*/\nPRIVATE char Fetch_Char(void)\n{\n\tchar\tc;\t\t// Character to return.\n\n\tif (!Char[0]) {\n\t\tIn_Char(&Char[0]);\n\t}\n\n\tc = Char[0];\n\tChar[0] = Char[1];\n\tChar[1] = '\\0';\n\n\tif (!Char[0]) {\n\t\tIn_Char(&Char[0]);\n\t}\n\n\treturn (c);\n}\n\u001a\n"
  },
  {
    "path": "WWFLAT32/WINDOWS/WINDOWS.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Part of the WINDOWS Library              *\n *                                                                         *\n *                    File Name : WINDOWS.H                                *\n *                                                                         *\n *                   Programmer : Barry W. Green                           *\n *                                                                         *\n *                   Start Date : February 16, 1995                        *\n *                                                                         *\n *                  Last Update : February 16, 1995 [BWG]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WINDOWS_H\n#define WINDOWS_H\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WINHIDE.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Window_Hide_Mouse(int window);\nvoid Window_Show_Mouse(void);\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WINDOWS.CPP\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Standard_More_Prompt(char const *prompt, int space, int fcolor, int bcolor);\nvoid Set_More_Prompt(char const *prompt, int space, int fcolor, int bcolor);\nvoid Set_More_On(void);\nvoid Set_More_Off(void);\nint Change_Window(int windnum);\nint Change_New_Window(int windnum);\nvoid New_Window(void);\nvoid Window_Int_Print(int num);\nvoid Window_Print(char const string[], ...);\n\n/*\n**\tThe WindowList[][8] array contains the following elements.  Use these\n**\tdefines when accessing the WindowList.\n*/\ntypedef enum {\n\tWINDOWX,\t\t\t// X byte position of left edge.\n\tWINDOWY,\t\t\t// Y pixel position of top edge.\n\tWINDOWWIDTH,\t// Width in bytes of the window.\n\tWINDOWHEIGHT,\t// Height in pixels of the window.\n\tWINDOWFCOL,\t\t// Default foreground color.\n\tWINDOWBCOL,\t\t// Default background color.\n\tWINDOWCURSORX,\t// Current cursor X position (in rows).\n\tWINDOWCURSORY,\t// Current cursor Y position (in lines).\n\tWINDOWPADDING=0x1000\n} WindowIndexType;\n\nextern int WindowList[][8];\nextern int WindowColumns;\nextern int WindowLines;\nextern int WindowWidth;\nextern unsigned int WinB;\nextern unsigned int WinC;\nextern unsigned int WinX;\nextern unsigned int WinY;\nextern unsigned int WinCx;\nextern unsigned int WinCy;\nextern unsigned int WinH;\nextern unsigned int WinW;\nextern unsigned int Window;\n\nextern int MoreOn;\nextern char *TXT_MoreText;\n\nextern void (*Window_More_Ptr)(char const *, int, int, int);\n\n#endif //WINDOWS_H\n\n\u001a"
  },
  {
    "path": "WWFLAT32/WINDOWS/WINHIDE.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./winhide.c 1.10 1994/05/20 15:35:50 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Dune                                     *\n *                                                                         *\n *                    File Name : WINHIDE.C                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : May 30, 1991                             *\n *                                                                         *\n *                  Last Update : August 16, 1991   [JLB]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Window_Hide_Mouse -- Hides the mouse when it enters a window.         *\n *   Window_Show_Mouse -- Shows the mouse after Window_Hide_Mouse hides it.*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t<wwstd.h>\n#include\t<keyboard.h>\n#include \"window.h\"\n\n\n#if(IBM)\n/***************************************************************************\n * WINDOW_HIDE_MOUSE -- Hides the mouse when it enters a window.           *\n *                                                                         *\n *    This is an intelligent form of Conditional_Hide_Mouse().  It will    *\n *    hide the mouse if it enters the specified window (see the            *\n *    WindowList global).                                                  *\n *                                                                         *\n * INPUT:   window   - Window number.                                      *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   Just like Conditional_Hide_Mouse(), this function is NOT    *\n *             nestable.                                                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/26/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Window_Hide_Mouse(int window)\n{\n\tint\tx,y,w,h;\n\n\tx = WindowList[window][WINDOWX]<<3;\n\ty = WindowList[window][WINDOWY];\n\tw = WindowList[window][WINDOWWIDTH]<<3;\n\th = WindowList[window][WINDOWHEIGHT];\n\tConditional_Hide_Mouse(x,y,x+w-1,y+h-1);\n}\n\n\n/***************************************************************************\n * WINDOW_SHOW_MOUSE -- Shows the mouse after Window_Hide_Mouse hides it.  *\n *                                                                         *\n *    This routines will show the mouse after Window_Hide_Mouse has hidden *\n *    it.                                                                  *\n *                                                                         *\n * INPUT:      none                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/22/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Window_Show_Mouse(void)\n{\n\tConditional_Show_Mouse();\n}\n#endif\n\n\n\u001a\n"
  },
  {
    "path": "WWFLAT32/WINDOWS/WINHIDE.CPP.BAK",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./winhide.c 1.10 1994/05/20 15:35:50 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Dune                                     *\n *                                                                         *\n *                    File Name : WINHIDE.C                                *\n *                                                                         *\n *                   Programmer : Joe L. Bostic                            *\n *                                                                         *\n *                   Start Date : May 30, 1991                             *\n *                                                                         *\n *                  Last Update : August 16, 1991   [JLB]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Window_Hide_Mouse -- Hides the mouse when it enters a window.         *\n *   Window_Show_Mouse -- Shows the mouse after Window_Hide_Mouse hides it.*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t<wwstd.h>\n#include\t<keyboard.h>\n#include \"windows.h\"\n\n\n#if(IBM)\n/***************************************************************************\n * WINDOW_HIDE_MOUSE -- Hides the mouse when it enters a window.           *\n *                                                                         *\n *    This is an intelligent form of Conditional_Hide_Mouse().  It will    *\n *    hide the mouse if it enters the specified window (see the            *\n *    WindowList global).                                                  *\n *                                                                         *\n * INPUT:   window   - Window number.                                      *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   Just like Conditional_Hide_Mouse(), this function is NOT    *\n *             nestable.                                                   *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/26/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Window_Hide_Mouse(int window)\n{\n\tint\tx,y,w,h;\n\n\tx = WindowList[window][WINDOWX]<<3;\n\ty = WindowList[window][WINDOWY];\n\tw = WindowList[window][WINDOWWIDTH]<<3;\n\th = WindowList[window][WINDOWHEIGHT];\n\tConditional_Hide_Mouse(x,y,x+w-1,y+h-1);\n}\n\n\n/***************************************************************************\n * WINDOW_SHOW_MOUSE -- Shows the mouse after Window_Hide_Mouse hides it.  *\n *                                                                         *\n *    This routines will show the mouse after Window_Hide_Mouse has hidden *\n *    it.                                                                  *\n *                                                                         *\n * INPUT:      none                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/22/1991 JLB : Created.                                             *\n *=========================================================================*/\nvoid Window_Show_Mouse(void)\n{\n\tConditional_Show_Mouse();\n}\n#endif\n\n\n\u001a"
  },
  {
    "path": "WWFLAT32/WSA/MAKEFILE",
    "content": "#\n#\tCommand & Conquer Red Alert(tm)\n#\tCopyright 2025 Electronic Arts Inc.\n#\n#\tThis program is free software: you can redistribute it and/or modify\n#\tit under the terms of the GNU General Public License as published by\n#\tthe Free Software Foundation, either version 3 of the License, or\n#\t(at your option) any later version.\n#\n#\tThis program is distributed in the hope that it will be useful,\n#\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n#\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#\tGNU General Public License for more details.\n#\n#\tYou should have received a copy of the GNU General Public License\n#\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n#***************************************************************************\n#**     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       **\n#***************************************************************************\n#*                                                                         *\n#*                 Project Name : Westwood Library .LIB makefile\t   *\n#*                                                                         *\n#*                    File Name : MAKEFILE                                 *\n#*                                                                         *\n#*                   Programmer : Julio R. Jerez\t\t\t   *\n#*                                                                         *\n#*                   Start Date : Jan 30, 1995                             *\n#*                                                                         *\n#*                                                                         *\n#*-------------------------------------------------------------------------*\n#*                                                                         *\n#* Required environment variables:\t\t\t\t\t   *\n#* WWFLAT\t= your root WWFLAT path\t\t\t\t\t   *\n#* WWVCS\t= root directory for wwlib version control archive\t   *\n#* WATCOM\t= your Watcom installation path\t\t\t\t   *\n#*\t\t\t\t\t\t\t\t\t   *\n#* Required changes to makefile:\t\t\t\t\t   *\n#* PROJ_NAME\t= name of the library you're building\t\t\t   *\n#* OBJECTS\t= list of objects in your library\t\t\t   *\n#*                                                                         *\n#* Optional changes to makefile:\t\t\t\t\t   *\n#* PROJ_DIR\t= full pathname of your working directory\t\t   *\n#* .path.xxx\t= full pathname where various file types live\t\t   *\n#*                                                                         *\n#***************************************************************************\n\n#---------------------------------------------------------------------------\n# Verify user's environment\n#---------------------------------------------------------------------------\n!ifndef %WWFLAT\n!error WWFLAT Environment var not configured.\n!endif\n\n\n!ifndef %WWVCS  \n!error WWVCS Environment var not configured.\n!endif\n\n!ifndef %WATCOM \n!error WATCOM Environment var not configured.\n!endif\n\n\n#===========================================================================\n# User-defined section: the user should tailor this section for each project\n#===========================================================================\n\nPROJ_NAME   = wsa\nPROJ_DIR    = $(%WWFLAT)\\$(PROJ_NAME)\nLIB_DIR     = $(%WWFLAT)\\lib\n\n!include $(%WWFLAT)\\project.cfg\n\n#---------------------------------------------------------------------------\n# Project-dependent variables\n#---------------------------------------------------------------------------\nOBJECTS = \t\t&\n\twsa.obj\t\t&\n\txordelta.obj\n\n\n#---------------------------------------------------------------------------\n# Path macros: one path for each file type.\n#\tThese paths are used to tell make where to find/put each file type.\n#---------------------------------------------------------------------------\n.asm:\t$(PROJ_DIR)\n.c:\t$(PROJ_DIR)\n.cpp:\t$(PROJ_DIR)\n.h:\t$(PROJ_DIR)\n.obj:\t$(PROJ_DIR)\n.lib:\t$(%WWFLAT32)\\lib\n.exe:\t$(PROJ_DIR)\n\n#===========================================================================\n# Pre-defined section: there should be little need to modify this section.\n#===========================================================================\n\n#---------------------------------------------------------------------------\n# Tools/commands\n#---------------------------------------------------------------------------\nC_CMD\t  \t= wcc386\nCPP_CMD\t  \t= wpp386\nLIB_CMD\t  \t= wlib\nLINK_CMD  \t= wlink\nASM_CMD\t  \t= tasm32\n\n#---------------------------------------------------------------------------\n# Include & library paths\n#\tIf LIB & INCLUDE are already defined, they are used in addition to the\n#\tWWLIB32 lib & include; otherwise, they're constructed from\n#\tBCDIR & TNTDIR\n#---------------------------------------------------------------------------\nLIBPATH\t  \t= $(%WWFLAT)\\LIB;$(%WATCOM)\\LIB\nINCLUDEPATH\t= $(%WWFLAT)\\INCLUDE;$(%WATCOM)\\H\n\n\n#---------------------------------------------------------------------------\n# Implicit rules\n# Compiler: \n# \t($< = full dependent with path)\n# Assembler:\n# \toutput obj's are constructed from .obj: & the $& macro\n# \t($< = full dependent with path)\n# \ttasm's cfg file is not invoked as a response file.\n#---------------------------------------------------------------------------\n\n.c.obj:\t$(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(C_CMD) $(CC_CFG) $<\n\n.cpp.obj: $(%WWFLAT)\\project.cfg .AUTODEPEND \n\t$(CPP_CMD) $(CC_CFG) $<\n\n.asm.obj: $(%WWFLAT)\\project.cfg\n\t$(ASM_CMD) $(ASM_CFG) $<\n\n\n#---------------------------------------------------------------------------\n# Default target: configuration files & library (in that order)\n#---------------------------------------------------------------------------\nall:\t$(LIB_DIR)\\$(PROJ_NAME).lib .SYMBOLIC\n\n\n#---------------------------------------------------------------------------\n# Build the library\n# The original library is deleted by the librarian\n# Lib objects & -+ commands are constructed by substituting within the\n# $^@ macro (which expands to all target dependents, separated with\n# spaces)\n# Tlib's cfg file is not invoked as a response file.\n# All headers & source files are copied into WWFLAT\\SRCDEBUG, for debugging\n#---------------------------------------------------------------------------\n$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc\n\t copy *.h   $(%WWFLAT)\\include \n\t copy *.inc $(%WWFLAT)\\include \n\t copy *.cpp $(%WWFLAT)\\srcdebug \n\t copy *.asm $(%WWFLAT)\\srcdebug \n\t$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc\n\n#---------------------------------------------------------------------------\n# Objects now have a link file which is NOT generated everytime.  Instead\n# it just has its own dependacy rule.\n#---------------------------------------------------------------------------\nobjects.lbc : $(OBJECTS)\n\t      %create $^@\n\t      for %index in ($(OBJECTS)) do %append $^@ +%index\n\n#---------------------------------------------------------------------------\n# Create the test directory and make it.\n#---------------------------------------------------------------------------\ntest:\n\tmkdir test\n\tcd test\n\tcopy $(%WWVCS)\\$(PROJ_NAME)\\test\\vcs.cfg\n\tupdate\n\twmake \n\tcd ..\n\n#**************************** End of makefile ******************************\n\n"
  },
  {
    "path": "WWFLAT32/WSA/WSA.CPP",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* $Header: g:/library/source/rcs/./wsa.c 1.16 1994/05/20 15:35:27 joe_bostic Exp $ */\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Library Animation System                 *\n *                                                                         *\n *                    File Name : WSA.C                                    *\n *                                                                         *\n *                   Programmer : Michael Legg                             *\n *                                                                         *\n *                   Start Date : November 20, 1991                        *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *   There are many different ways that the user can use the WSA library   *\n * module.  The options are as follows :                                   *\n *                                                                         *\n *   System Allocation vs User Buffer - The user may request that the      *\n *       system allocate the needed buffer from the heap or the user may\t*\n *       pass his own buffer in for the animator to use.                   *\n *                                                                         *\n *   Resident vs File based - If there is enough RAM, the user may put the *\n *       entire animation into RAM for fastest animations.  If there is    *\n *       not enouph RAM, the system will automatically make it so each     *\n *       frame will be read off disk when needed.                          *\n *                                                                         *\n *   Direct to Page vs Use of a user buffer -- Noramally Direct to page\t\t*\n *       is the best method both in speed and in RAM need to hold anim.    *\n *       One may want to use the write to user buffer method if they       *\n *       are using the animation in a non sequencial order.                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Animate_Frame -- Displays a frame of a given animation                *\n *   Get_Animation_Frame_Count --  Return Number of frames in an animation.  *\n *   Get_Animation_X -- Gets the x from an animation                       *\n *   Get_Animation_Y -- Gets the y from an animation                       *\n *   Get_Animation_Width -- Gets the width from an animation               *\n *   Get_Animation_Height -- The height of the animation we are processing *\n *   Apply_Delta -- Copies frame into delta buffer, then applies to target *\n *   Close_Animation -- Close the animation, freeing the space if necessary*\n *   Get_File_Frame_Offset -- Get offset of a delta frame from animate file*\n *   Get_Resident_Frame_Offset -- Gets frame offset of animate file in RAM *\n *   Open_Animation -- Opens an animation file and reads into buffer       *\n *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include <wwstd.h>\n#include \"wsa.h\"\n#include <wwmem.h>\n#include <file.h>\n#include <misc.h>\n#include <iff.h>\n#include <mem.h> \n#include <string.h>\n\n//\n// WSA animation header allocation type.\n// If we need more then 8 flags for the flags variable, we can combine\n// USER_ALLOCATED with SYS_ALLOCATED  and combine FILE with RESIDENT.  \n//\n#define\tWSA_USER_ALLOCATED \t0x01\n#define\tWSA_SYS_ALLOCATED  \t0x02\n#define\tWSA_FILE           \t0x04\n#define\tWSA_RESIDENT       \t0x08\n#define\tWSA_TARGET_IN_BUFFER\t0x10\n#define\tWSA_LINEAR_ONLY\t\t0x20\n#define\tWSA_FRAME_0_ON_PAGE  0x40\n#define\tWSA_AMIGA_ANIMATION  0x80\n#define\tWSA_PALETTE_PRESENT\t0x100\n#define\tWSA_FRAME_0_IS_DELTA\t0x200\n\n// These are used to call Apply_XOR_Delta_To_Page_Or_Viewport() to setup flags parameter.  If\n// These change, make sure and change their values in lp_asm.asm.\n#define\tDO_XOR\t\t\t\t\t0x0\n#define\tDO_COPY\t\t\t\t\t0x01\n#define\tTO_VIEWPORT\t\t\t\t0x0\n#define\tTO_PAGE\t\t\t\t\t0x02\n\n\ntypedef struct {\n\tUWORD current_frame;\n\tUWORD total_frames;\n\tUWORD pixel_x;\n\tUWORD pixel_y;\n\tUWORD pixel_width;\n\tUWORD pixel_height;\n\tUWORD largest_frame_size;\n\tBYTE *delta_buffer;\n\tBYTE *file_buffer;\n\tBYTE file_name[ 13 ];\n\tWORD flags;\n\t// New fields that animate does not know about below this point. SEE EXTRA_BYTES_ANIMATE_NOT_KNOW_ABOUT\n\tWORD file_handle;\n\tULONG anim_mem_size;\n} SysAnimHeaderType;\n\n// NOTE:\"THIS IS A BAD THING. SINCE sizeof(SysAnimHeaderType) CHANGED, THE ANIMATE.EXE\n// UTILITY DID NOT KNOW I UPDATED IT, IT ADDS IT TO largest_frame_size BEFORE SAVING\n// IT TO THE FILE.  THIS MEANS I HAVE TO ADD THESE BYTES ON NOW FOR IT TO WORK.\n#define EXTRA_BYTES_ANIMATE_NOT_KNOW_ABOUT\t(sizeof(WORD) + sizeof(ULONG))\n\n\n//\n// Header structure for the file.\n// NOTE:  The 'total_frames' field is used to differentiate between Amiga and IBM\n// animations.  Amiga animations have the HIGH bit set.\n//\ntypedef struct {\n\tUWORD total_frames;\n\tUWORD pixel_x;\n\tUWORD pixel_y;\n\tUWORD pixel_width;\n\tUWORD pixel_height;\n\tUWORD largest_frame_size;\n\tWORD\tflags;\n\tULONG frame0_offset;\n\tULONG frame0_end;\n\t/* ULONG data_seek_offset, UWORD frame_size ... */\n} WSA_FileHeaderType;\n\n#define WSA_FILE_HEADER_SIZE\t( sizeof(WSA_FileHeaderType) - (2 * sizeof(ULONG)) )\n\n/*=========================================================================*/\n/* The following PRIVATE functions are in this file:                       */\n/*=========================================================================*/\n\nPRIVATE ULONG Get_Resident_Frame_Offset( BYTE *file_buffer, WORD frame );\nPRIVATE ULONG Get_File_Frame_Offset( WORD file_handle, WORD frame, WORD palette_adjust);\nPRIVATE BOOL Apply_Delta(SysAnimHeaderType *sys_header, WORD curr_frame, BYTE *dest_ptr, WORD dest_w);\n/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n\n\n/***************************************************************************\n * OPEN_ANIMATION -- Opens an animation file and reads into buffer         *\n *                                                                         *\n * INPUT:   BYTE *file_name of animation sequence file.                    *\n *          BYTE *user_buffer pointer if one exists  (NULL ok)             *\n *          ULONG user_buffer_size if known  (NULL ok)                     *\n *          WSAOpenType user_flags - flags on how to open.                 *\n *          UBYTE *palette - pointer to palette space for return (NULL ok) *\n *                                                                         *\n * OUTPUT:  VOID *pointer to animation data.  Must be used for all \t\t\t*\n *               other WSA calls.                                          *\n *                                                                         *\n * WARNINGS: May return NULL, please check.                                *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/26/1991  SB : Created.                                             *\n *=========================================================================*/\nVOID * cdecl Open_Animation(BYTE const *file_name, BYTE *user_buffer, LONG user_buffer_size, WSAOpenType user_flags, UBYTE *palette)\n{\n\tWORD\t\t\t\t\t\tfh, anim_flags;\n\tWORD\t\t\t\t\t\tpalette_adjust;\n\tUWORD\t\t\t\t\t\toffsets_size;\n\tUWORD\t\t\t\t\t\tframe0_size;\n\tLONG\t\t\t\t\t\ttarget_buffer_size, delta_buffer_size, file_buffer_size;\n\tLONG\t\t\t\t\t\tmax_buffer_size,    min_buffer_size;\n\tBYTE\t\t\t\t\t\t*sys_anim_header_buffer;\n\tBYTE\t\t\t\t\t\t*target_buffer;\n\tBYTE\t\t\t\t\t\t*delta_buffer, *delta_back;\n\tSysAnimHeaderType\t\t*sys_header;\n\tWSA_FileHeaderType\tfile_header;\n\n\t/*======================================================================*/\n\t/* Open the file to get the header information\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\n\tanim_flags\t= 0;\n\tfh\t\t\t\t= Open_File(file_name, READ);\n\tRead_File(fh, (BYTE *) &file_header, sizeof(WSA_FileHeaderType));\n\n\t/*======================================================================*/\n\t/* If the file has an attached palette then if we have a valid palette\t*/\n\t/*\t\tpointer we need to read it in.\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t/*======================================================================*/\n\n\tif (file_header.flags & 1) {\n\t\tanim_flags\t\t|= WSA_PALETTE_PRESENT;\n\t\tpalette_adjust\t = 768;\n\n\t\tif (palette != NULL) {\n\t\t\tSeek_File(fh, sizeof(ULONG) * (file_header.total_frames), SEEK_CUR);\n\t\t\tRead_File(fh, palette, 768L);\n\t\t}\n\n\t} else {\n\t\tpalette_adjust = 0;\n\t}\n\n\t// Check for flag from ANIMATE indicating that this animation was\n\t// created from a .LBM and a .ANM.  These means that the first\n\t// frame is a XOR Delta from a picture, not black.\n\tif (file_header.flags & 2) {\n\t\tanim_flags\t\t|= WSA_FRAME_0_IS_DELTA;\n\t}\n\n\n\t// Get the total file size minus the size of the first frame and the size\n\t// of the file header.  These will not be read in to save even more space.\n\tfile_buffer_size = Seek_File(fh, 0L, SEEK_END);\n\n\tif (file_header.frame0_offset) {\n\t\tLONG tlong;\n\n\t\ttlong = file_header.frame0_end - file_header.frame0_offset;\n\t\tframe0_size = (UWORD) tlong;\n\t}\n\telse {\n\t\tanim_flags |= WSA_FRAME_0_ON_PAGE;\n\t\tframe0_size = 0;\n\t}\n\n\tfile_buffer_size -= palette_adjust + frame0_size + WSA_FILE_HEADER_SIZE;\n\n\t// We need to determine the buffer sizes required for the animation.  At a\n\t// minimum, we need a target buffer for the uncompressed frame and a delta\n\t// buffer for the delta data.  We may be able to make the file resident,\n\t// so we will determine the file size.  \n\t//\n\t// If the target buffer is in the user buffer \n\t// Then figure its size \n\t// and set the allocation flag\n\t// Else size is zero.\n\t//\n\tif (user_flags & WSA_OPEN_DIRECT) {\n\t \ttarget_buffer_size = 0L;\n\t}\n\telse {\n\t\tanim_flags |= WSA_TARGET_IN_BUFFER;\n\t\ttarget_buffer_size = (ULONG) file_header.pixel_width * file_header.pixel_height;\n\t}\n\n\t// NOTE:\"THIS IS A BAD THING. SINCE sizeof(SysAnimHeaderType) CHANGED, THE ANIMATE.EXE\n\t// UTILITY DID NOT KNOW I UPDATED IT, IT ADDS IT TO largest_frame_size BEFORE SAVING\n\t// IT TO THE FILE.  THIS MEANS I HAVE TO ADD THESE BYTES ON NOW FOR IT TO WORK.\n\tdelta_buffer_size  = (ULONG) file_header.largest_frame_size + EXTRA_BYTES_ANIMATE_NOT_KNOW_ABOUT;\n\tmin_buffer_size = target_buffer_size + delta_buffer_size;\n\tmax_buffer_size = min_buffer_size + file_buffer_size;\n\n\t// check to see if buffer size is big enough for at least min required\n\tif (user_buffer && (user_buffer_size < min_buffer_size)) {\n\t\tClose_File(fh);\n\t\treturn(NULL);\n\t}\n\t\n\t// A buffer was not passed in, so do allocations\n\tif (user_buffer == NULL) { \n\n\t\t// If the user wants it from the disk, then let us give it to him,\n\t\t// otherwise, try to give a max allocation he can have.\n\t\tif (user_flags & WSA_OPEN_FROM_DISK) {\n\t\t\tuser_buffer_size = min_buffer_size;\n\t\t}\n\t\t// else no buffer size, then try max configuration.\n\t\telse if (!user_buffer_size) {\n\t\t\tuser_buffer_size = max_buffer_size;\n\t\t}\n\t\t// else if buffer specified is less then max needed, give min.\n\t\telse if (user_buffer_size < max_buffer_size) {\n\t\t\tuser_buffer_size = min_buffer_size;\n\t\t}\n\t\t// otherwise we only want to alloc what we need.\n\t\telse {\n\t\t\tuser_buffer_size = max_buffer_size;\n\t\t}\n\n\n\t\t// Check to see if enough RAM available for buffer_size.\n\t\tif (user_buffer_size > Ram_Free(MEM_NORMAL)) {\n \t\t\n \t\t\t// If not enough room for even the min, return no buffer.\n\n\t\t\tif (min_buffer_size > Ram_Free(MEM_NORMAL)) {\n\t\t\t\tClose_File(fh);\n\t\t\t\treturn(NULL);\n\t\t\t}\n\n\t\t\t// Else make buffer size the min and allocate it.\n\t\t\tuser_buffer_size = min_buffer_size;\n\t\t}\n\n\t\t// allocate buffer needed\n\t\tuser_buffer = (BYTE *) Alloc(user_buffer_size, MEM_CLEAR);\n\n\t\tanim_flags |= WSA_SYS_ALLOCATED;\n\t}\n\telse {\n\t\t// Check to see if the user_buffer_size should be min or max.\n\t\tif ((user_flags & WSA_OPEN_FROM_DISK) || (user_buffer_size < max_buffer_size)) {\n\t\t \tuser_buffer_size = min_buffer_size;\n\t\t}\n\t\telse {\n\t\t \tuser_buffer_size = max_buffer_size;\n\t\t}\n\t\tanim_flags |= WSA_USER_ALLOCATED;\n\t}\n\n\n\t// Set the pointers to the RAM buffers\n\tsys_anim_header_buffer = user_buffer;\n\ttarget_buffer = (BYTE *) Add_Long_To_Pointer(sys_anim_header_buffer, sizeof(SysAnimHeaderType));\n\tdelta_buffer  = (BYTE *) Add_Long_To_Pointer(target_buffer, target_buffer_size);\n\n\t//\tClear target buffer if it is in the user buffer.\n\tif (target_buffer_size) {\n\t\tmemset( target_buffer, 0, (UWORD) target_buffer_size );\n\t}\n\n\t// Poke data into the system animation header (start of user_buffer)\n\t// current_frame is set to total_frames so that Animate_Frame() knows that\n\t// it needs to clear the target buffer.\n\n\tsys_header = ( SysAnimHeaderType * ) sys_anim_header_buffer;\n\tsys_header -> current_frame = \n\tsys_header -> total_frames  = file_header.total_frames;\n\tsys_header -> pixel_x\t\t = file_header.pixel_x;\n\tsys_header -> pixel_y\t\t = file_header.pixel_y;\n\tsys_header -> pixel_width   = file_header.pixel_width;\n\tsys_header -> pixel_height  = file_header.pixel_height;\n\tsys_header -> anim_mem_size = user_buffer_size;\n\tsys_header -> delta_buffer  = delta_buffer;\n\tsys_header -> largest_frame_size = \n                 (UWORD) delta_buffer_size - sizeof(SysAnimHeaderType);\n\n\tstrcpy(sys_header->file_name, file_name);\n\n\t// Figure how much room the frame offsets take up in the file.\n\t// Add 2 - one for the wrap around and one for the final end offset.\n\toffsets_size = (file_header.total_frames + 2) << 2;\n\n\t// Can the user_buffer_size handle the maximum case buffer? \n\tif ( user_buffer_size == max_buffer_size) {\n\n\t\t//\n\t\t//\tset the file buffer pointer, \n\t\t// Skip over the header information.\n\t\t// Read in the offsets.\n\t\t// Skip over the first frame.\n\t\t// Read in remaining frames.\n\t\t//\n\n\t\tsys_header->file_buffer = (BYTE *)Add_Long_To_Pointer(delta_buffer,sys_header->largest_frame_size);\n\t\tSeek_File( fh, WSA_FILE_HEADER_SIZE, SEEK_SET);\n\t\tRead_File( fh, sys_header->file_buffer, offsets_size);\n\t\tSeek_File( fh, frame0_size + palette_adjust, SEEK_CUR);\n\t\tRead_File( fh, sys_header->file_buffer + offsets_size, \n\t\t           file_buffer_size - offsets_size);\n\n\t\t//\n\t\t// Find out if there is an ending value for the last frame. \n\t\t// If there is not, then this animation will not be able to\n\t\t// loop back to the beginning.\n\t\t//\n\t\tif (Get_Resident_Frame_Offset( sys_header->file_buffer, sys_header->total_frames + 1))\n\t\t\tanim_flags |= WSA_RESIDENT;\n\t\telse\n\t\t\tanim_flags |= WSA_LINEAR_ONLY | WSA_RESIDENT;\n\t}\n\telse {\t// buffer cannot handle max_size of buffer\n\n\t\tif(Get_File_Frame_Offset( fh, sys_header->total_frames + 1, palette_adjust))\n\t\t\tanim_flags |= WSA_FILE;\n\t\telse\n\t\t\tanim_flags |= WSA_LINEAR_ONLY | WSA_FILE;\n////\n\t\tsys_header->file_buffer = NULL;\n\t}\n\n\t// Figure where to back load frame 0 into the delta buffer.\n\tdelta_back = (BYTE *)Add_Long_To_Pointer(delta_buffer, \n\t\t\t\t\t sys_header->largest_frame_size - frame0_size);\n\n\t// Read the first frame into the delta buffer and uncompress it.\n\t// Then close it.\n\tSeek_File( fh, WSA_FILE_HEADER_SIZE + offsets_size + palette_adjust, SEEK_SET);\n\tRead_File( fh, delta_back, frame0_size);\n\n\t// We do not use the file handle when it is in RAM.\n\tif (anim_flags & WSA_RESIDENT) {\n\t\tsys_header -> file_handle = (WORD) -1;\n\t \tClose_File(fh);\n\t}\n\telse {\n\t\tsys_header -> file_handle = fh;\n\t}\n\n\tLCW_Uncompress(delta_back, delta_buffer, sys_header->largest_frame_size);\n\n\t// Finally set the flags,\n\tsys_header->flags = anim_flags;\n\n\t// return valid handle\n\treturn( user_buffer );\n}\n\n\n/***************************************************************************\n * CLOSE_ANIMATION -- Close the animation, freeing the space if necessary. *\n *                                                                         *\n * INPUT:      VOID *handle to the animation data buffer                   *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   handle MUST have been returned by Open_Animation            *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/23/1991  ML : Created.                                             *\n *=========================================================================*/\nVOID cdecl Close_Animation( VOID *handle )\n{\n\tSysAnimHeaderType *sys_header;\n\n\t// Assign our local system header pointer to the beginning of the handle space\n\tsys_header = (SysAnimHeaderType *) handle;\n\n\t// Close the WSA file in it was disk based.\n\tif (sys_header->flags & WSA_FILE) {\n\t\tClose_File(sys_header->file_handle);\t \n\t}\n\n\t// Check to see if the buffer was allocated OR the programmer provided the buffer\n\tif (handle && sys_header->flags & WSA_SYS_ALLOCATED) {\n\t\tFree(handle);\n\t}\n}\n\n/***************************************************************************\n * ANIMATE_FRAME -- Displays a frame of a given animation                  *\n *                                                                         *\n * INPUT:   VOID *handle to the animation.                                 *\n *          WORD frame_number wanted to be displayed                       *\n *          WORD x_pixel position of left side of animation on page        *\n *          WORD y_pixel position of top of animation on page              *\n *                                                                         *\n * OUTPUT:  BOOL if successfull or not.                                   *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/27/1991  SB : Created.                                             *\n *=========================================================================*/\n#pragma argsused\nBOOL cdecl Animate_Frame(VOID *handle, VideoViewPortClass& view,\n                         WORD frame_number, WORD x_pixel, WORD y_pixel,\n                         WSAType flags_and_prio, VOID *magic_cols, VOID *magic)\n{\n\tSysAnimHeaderType \t*sys_header;\t\t// fix up the VOID pointer past in.\n\tWORD \t\t\t\t\t\tcurr_frame;\t\t\t// current frame we are on.\n\tWORD\t\t\t\t\t\ttotal_frames;\t\t// number of frames in anim.\n\tWORD\t\t\t\t\t\tdistance;\t\t\t// distance to desired frame.\n\tWORD\t\t\t\t\t\tsearch_dir;\t\t\t// direcion to search for desired frame.\n\tWORD\t\t\t\t\t\tsearch_frames;\t\t// How many frames to search.\n\tWORD\t\t\t\t\t\tloop;\t\t\t\t\t// Just a loop varible.\n\tBYTE\t\t\t\t\t\t*frame_buffer;\t\t// our destination.\n\tBOOL\t\t\t\t\t\tdirect_to_dest;\t// are we going directly to the destination?\n\tWORD\t\t\t\t\t\tdest_width;\t\t\t// the width of the destination buffer or page.\n\n\n\t// Assign local pointer to the beginning of the buffer where the system information\n\t// resides\n\tsys_header = (SysAnimHeaderType \t*)handle;\n\n\t// Get the total number of frames\n\ttotal_frames = sys_header->total_frames;\n\n\t// Are the animation handle and the frame number valid?\n\tif (!handle || (total_frames <= frame_number)) {\n\t\treturn FALSE;\n\t}\n\n\n\t// Decide if we are going to a page or a viewport (part of a buffer).\n\tdest_width\t= view.Get_Width() + view.Get_XAdd();\n\n\t//\n\t// adjust x_pixel and y_pixel by system pixel_x and pixel_y respectively.\n\t//\n\tx_pixel += (WORD)sys_header->pixel_x;\n\ty_pixel += (WORD)sys_header->pixel_y;\n\n\t//\n\t// Check to see if we are using a buffer inside of the animation buffer or if\n\t// it is being drawn directly to the destination page or buffer.\n\t//\n\tif (sys_header->flags & WSA_TARGET_IN_BUFFER) {\n\t\t// Get a pointer to the frame in animation buffer.\n\t\tframe_buffer = (BYTE *)Add_Long_To_Pointer(sys_header, sizeof(SysAnimHeaderType));\n\t\tdirect_to_dest = FALSE;\n\t}\n\telse {\n\t\tframe_buffer\t= (BYTE *)view.Get_Offset();\n\t\tframe_buffer  += (y_pixel * dest_width) + x_pixel;\n\t\tdirect_to_dest\t= TRUE;\n\t}\n\t//\n\t// If current_frame is equal to tatal_frames, then no animations have taken place\n\t// so must uncompress frame 0 in delta buffer to the frame_buffer/page if it\n\t// exists.\n\t//\n\tif (sys_header->current_frame == total_frames) {\n\n\t\t// Call apply delta telling it wether to copy or to xor depending on if the \n\t\t// target is a page or a buffer.\n\n\t\tif (!(sys_header->flags & WSA_FRAME_0_ON_PAGE)) {\n\t\t\tif (direct_to_dest) {\n\n\t\t\t\t// The last parameter says weather to copy or to XOR.  If  the\n\t\t\t\t// first frame is a DELTA, then it must be XOR'd.  A TRUE is\n\t\t\t\t// copy while FALSE is XOR.\n\t\t\t\t\n\t\t\t\tApply_XOR_Delta_To_Page_Or_Viewport(frame_buffer, sys_header->delta_buffer, \n\t\t\t\t                        \tsys_header->pixel_width, dest_width, //dest_width - sys_header->pixel_width,\n\t\t\t\t\t\t\t\t\t\t\t\t\t(sys_header->flags & WSA_FRAME_0_IS_DELTA)? DO_XOR : DO_COPY);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tApply_XOR_Delta(frame_buffer, sys_header->delta_buffer);\n\t\t\t}\n\t\t}\n\t\tsys_header->current_frame = 0;\n\t}\n\n\t//\n\t// Get the current frame\n\t// If no looping aloud, are the trying to do it anyways?\n\t//\n\tcurr_frame = sys_header->current_frame;\n#if (FALSE)\n\t// This is commented out since we will let them loop even though they should\n\t// not - it will be slower.\n\tif ( (sys_header->flags & WSA_LINEAR_ONLY) && (frame_number < cur_frame) ) {\n\t \treturn FALSE;\n\t}\n#endif\n\n\t// Get absoulte distance from our current frame to the target frame\n\tdistance = ABS(curr_frame - frame_number);\n\n\t// Assume we are searching right\n\tsearch_dir = 1;\n\n\t// Calculate the number of frames to search if we go right and wrap\n\n\tif (frame_number > curr_frame) {\n\t\tsearch_frames = total_frames - frame_number + curr_frame;\n\n\t\t// Is going right faster than going backwards?\n\t\t// Or are they trying to loop when the should not?\n\t\tif ((search_frames < distance) && !(sys_header->flags & WSA_LINEAR_ONLY)) {\n\t\t\tsearch_dir = -1;\t\t\t\t\t\t\t\t// No, so go left\n\t\t}\n\t\telse {\n\t\t\tsearch_frames = distance;\n\t\t}\n\t}\n\telse {\n\t\tsearch_frames = total_frames - curr_frame + frame_number;\n\n\t\t// Is going right faster than going backwards?\n\t\t// Or are they trying to loop when the should not?\n\t\tif ((search_frames >= distance) || (sys_header->flags & WSA_LINEAR_ONLY)) {\n\t\t\tsearch_dir = -1;\t\t\t\t\t\t\t\t// No, so go left\n\t\t\tsearch_frames = distance;\n\t\t}\n\t}\n\n\t// Take care of the case when we are searching right (possibly right)\n\n\tif (search_dir > 0) {\n\t\tfor (loop = 0; loop < search_frames; loop++) {\n\n\t\t\t// Move the logical frame number ordinally right\n\t\t\tcurr_frame += search_dir;\n\n\t\t\tApply_Delta(sys_header, curr_frame, frame_buffer, dest_width);\n\n\t\t\t// Adjust the current frame number, taking into consideration that we could\n\t\t\t// have wrapped\n\n\t\t\tif (curr_frame == total_frames) {\n\t\t\t\tcurr_frame = 0;\n\t\t\t}\n\t\t}\n\t}\n\telse {\n\t\tfor (loop = 0; loop < search_frames; loop++) {\n\n\t\t\t// If we are going backwards and we are on frame 0, the delta to get\n\t\t\t// to the last frame is the n + 1 delta (wrap delta)\n\n\t\t\tif (curr_frame == 0) {\n\t\t\t\tcurr_frame = total_frames;\n\t\t\t}\n\n\t\t\tApply_Delta(sys_header, curr_frame, frame_buffer, dest_width);\n\n\t\t\tcurr_frame += search_dir;\n\t\t}\n\t}\n\n\tsys_header->current_frame = frame_number;\n\n\t// If we did this all in a hidden buffer, then copy it to the desired page or viewport.\n\tif (sys_header->flags & WSA_TARGET_IN_BUFFER) {\n#if TRUE\n\t\t\n\t\tBuffer_To_Page(x_pixel, y_pixel, sys_header->pixel_width, sys_header->pixel_height, frame_buffer, view);\n\n#else\n\t\tWORD\tflags = ((UWORD)flags_and_prio & 0xFF00u) >> 12u;\n\t\tWORD\tpri = flags_and_prio & 0x00FF;\n\n\t\tBuffer_Bitblit_To_LogicPage(x_pixel, y_pixel, sys_header->pixel_width,\n\t\t\t\t\t\t\t\t\t\t  sys_header->pixel_height, 0, flags, frame_buffer, pri,\n\t\t\t\t\t\t\t\t\t\t  magic_cols, magic);\n#endif\n\t}\n\n\n\treturn TRUE;\n}\n/***************************************************************************\n * ANIMATE_FRAME -- Displays a frame of a given animation                  *\n *                                                                         *\n * INPUT:   VOID *handle to the animation.                                 *\n *          WORD frame_number wanted to be displayed                       *\n *          WORD x_pixel position of left side of animation on page        *\n *          WORD y_pixel position of top of animation on page              *\n *                                                                         *\n * OUTPUT:  BOOL if successfull or not.                                   *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/27/1991  SB : Created.                                             *\n *=========================================================================*/\n#pragma argsused\nBOOL cdecl Animate_Frame(VOID *handle, GraphicViewPortClass& view,\n                         WORD frame_number, WORD x_pixel, WORD y_pixel,\n                         WSAType flags_and_prio, VOID *magic_cols, VOID *magic)\n{\n\tSysAnimHeaderType \t*sys_header;\t\t// fix up the VOID pointer past in.\n\tWORD \t\t\t\t\t\tcurr_frame;\t\t\t// current frame we are on.\n\tWORD\t\t\t\t\t\ttotal_frames;\t\t// number of frames in anim.\n\tWORD\t\t\t\t\t\tdistance;\t\t\t// distance to desired frame.\n\tWORD\t\t\t\t\t\tsearch_dir;\t\t\t// direcion to search for desired frame.\n\tWORD\t\t\t\t\t\tsearch_frames;\t\t// How many frames to search.\n\tWORD\t\t\t\t\t\tloop;\t\t\t\t\t// Just a loop varible.\n\tBYTE\t\t\t\t\t\t*frame_buffer;\t\t// our destination.\n\tBOOL\t\t\t\t\t\tdirect_to_dest;\t// are we going directly to the destination?\n\tWORD\t\t\t\t\t\tdest_width;\t\t\t// the width of the destination buffer or page.\n\n\t// Assign local pointer to the beginning of the buffer where the system information\n\t// resides\n\tsys_header = (SysAnimHeaderType \t*)handle;\n\n\t// Get the total number of frames\n\ttotal_frames = sys_header->total_frames;\n\n\t// Are the animation handle and the frame number valid?\n\tif (!handle || (total_frames <= frame_number)) {\n\t\treturn FALSE;\n\t}\n\n\n\t// Decide if we are going to a page or a viewport (part of a buffer).\n\tdest_width\t= view.Get_Width() + view.Get_XAdd();\n\n\t//\n\t// adjust x_pixel and y_pixel by system pixel_x and pixel_y respectively.\n\t//\n\tx_pixel += (WORD)sys_header->pixel_x;\n\ty_pixel += (WORD)sys_header->pixel_y;\n\n\t//\n\t// Check to see if we are using a buffer inside of the animation buffer or if\n\t// it is being drawn directly to the destination page or buffer.\n\t//\n\tif (sys_header->flags & WSA_TARGET_IN_BUFFER) {\n\t\t// Get a pointer to the frame in animation buffer.\n\t\tframe_buffer = (BYTE *)Add_Long_To_Pointer(sys_header, sizeof(SysAnimHeaderType));\n\t\tdirect_to_dest = FALSE;\n\t}\n\telse {\n\t\tframe_buffer\t= (BYTE *)view.Get_Offset();\n\t\tframe_buffer  += (y_pixel * dest_width) + x_pixel;\n\t\tdirect_to_dest\t= TRUE;\n\t}\n\t//\n\t// If current_frame is equal to tatal_frames, then no animations have taken place\n\t// so must uncompress frame 0 in delta buffer to the frame_buffer/page if it\n\t// exists.\n\t//\n\tif (sys_header->current_frame == total_frames) {\n\n\t\t// Call apply delta telling it wether to copy or to xor depending on if the \n\t\t// target is a page or a buffer.\n\n\t\tif (!(sys_header->flags & WSA_FRAME_0_ON_PAGE)) {\n\t\t\tif (direct_to_dest) {\n\n\t\t\t\t// The last parameter says weather to copy or to XOR.  If  the\n\t\t\t\t// first frame is a DELTA, then it must be XOR'd.  A TRUE is\n\t\t\t\t// copy while FALSE is XOR.\n\t\t\t\tApply_XOR_Delta_To_Page_Or_Viewport(frame_buffer, sys_header->delta_buffer, \n\t\t\t\t                        \tsys_header->pixel_width, dest_width, //dest_width - sys_header->pixel_width,\n\t\t\t\t\t\t\t\t\t\t\t\t\t(sys_header->flags & WSA_FRAME_0_IS_DELTA)? DO_XOR : DO_COPY);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tApply_XOR_Delta(frame_buffer, sys_header->delta_buffer);\n\t\t\t}\n\t\t}\n\t\tsys_header->current_frame = 0;\n\t}\n\n\t//\n\t// Get the current frame\n\t// If no looping aloud, are the trying to do it anyways?\n\t//\n\tcurr_frame = sys_header->current_frame;\n#if (FALSE)\n\t// This is commented out since we will let them loop even though they should\n\t// not - it will be slower.\n\tif ( (sys_header->flags & WSA_LINEAR_ONLY) && (frame_number < cur_frame) ) {\n\t \treturn FALSE;\n\t}\n#endif\n\n\t// Get absoulte distance from our current frame to the target frame\n\tdistance = ABS(curr_frame - frame_number);\n\n\t// Assume we are searching right\n\tsearch_dir = 1;\n\n\t// Calculate the number of frames to search if we go right and wrap\n\n\tif (frame_number > curr_frame) {\n\t\tsearch_frames = total_frames - frame_number + curr_frame;\n\n\t\t// Is going right faster than going backwards?\n\t\t// Or are they trying to loop when the should not?\n\t\tif ((search_frames < distance) && !(sys_header->flags & WSA_LINEAR_ONLY)) {\n\t\t\tsearch_dir = -1;\t\t\t\t\t\t\t\t// No, so go left\n\t\t}\n\t\telse {\n\t\t\tsearch_frames = distance;\n\t\t}\n\t}\n\telse {\n\t\tsearch_frames = total_frames - curr_frame + frame_number;\n\n\t\t// Is going right faster than going backwards?\n\t\t// Or are they trying to loop when the should not?\n\t\tif ((search_frames >= distance) || (sys_header->flags & WSA_LINEAR_ONLY)) {\n\t\t\tsearch_dir = -1;\t\t\t\t\t\t\t\t// No, so go left\n\t\t\tsearch_frames = distance;\n\t\t}\n\t}\n\n\t// Take care of the case when we are searching right (possibly right)\n\n\tif (search_dir > 0) {\n\t\tfor (loop = 0; loop < search_frames; loop++) {\n\n\t\t\t// Move the logical frame number ordinally right\n\t\t\tcurr_frame += search_dir;\n\n\t\t\tApply_Delta(sys_header, curr_frame, frame_buffer, dest_width);\n\n\t\t\t// Adjust the current frame number, taking into consideration that we could\n\t\t\t// have wrapped\n\n\t\t\tif (curr_frame == total_frames) {\n\t\t\t\tcurr_frame = 0;\n\t\t\t}\n\t\t}\n\t}\n\telse {\n\t\tfor (loop = 0; loop < search_frames; loop++) {\n\n\t\t\t// If we are going backwards and we are on frame 0, the delta to get\n\t\t\t// to the last frame is the n + 1 delta (wrap delta)\n\n\t\t\tif (curr_frame == 0) {\n\t\t\t\tcurr_frame = total_frames;\n\t\t\t}\n\n\t\t\tApply_Delta(sys_header, curr_frame, frame_buffer, dest_width);\n\n\t\t\tcurr_frame += search_dir;\n\t\t}\n\t}\n\n\tsys_header->current_frame = frame_number;\n\n\t// If we did this all in a hidden buffer, then copy it to the desired page or viewport.\n\tif (sys_header->flags & WSA_TARGET_IN_BUFFER) {\n#if TRUE\n\t\t\n\t\tBuffer_To_Page(x_pixel, y_pixel, sys_header->pixel_width, sys_header->pixel_height, frame_buffer, view);\n\n#else\n\t\tWORD\tflags = ((UWORD)flags_and_prio & 0xFF00u) >> 12u;\n\t\tWORD\tpri = flags_and_prio & 0x00FF;\n\n\t\tBuffer_Bitblit_To_LogicPage(x_pixel, y_pixel, sys_header->pixel_width,\n\t\t\t\t\t\t\t\t\t\t  sys_header->pixel_height, 0, flags, frame_buffer, pri,\n\t\t\t\t\t\t\t\t\t\t  magic_cols, magic);\n#endif\n\t}\n\n\n\treturn TRUE;\n}\n\n\n/***************************************************************************\n * ANIMATE_FRAME_COUNT -- Return Number of frames in an animation.         *\n *                                                                         *\n * INPUT:   VOID *handle to the animation.                                 *\n *                                                                         *\n * OUTPUT:  WORD number of frames in animation.                            *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/05/1991  SB : Created.                                             *\n *=========================================================================*/\nWORD cdecl Get_Animation_Frame_Count(VOID *handle)\n{\n\tSysAnimHeaderType *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn((WORD)sys_header->total_frames);\n}\n\n\n/***************************************************************************\n * GET_ANIM_X -- Gets the x from an animation                              *\n *                                                                         *\n *                                                                         *\n * INPUT:\t\tVOID * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:     WORD the x of the animation we are processing\t\t\t\t   *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/03/1992 DRD : Created.                                             *\n *=========================================================================*/\nWORD cdecl Get_Animation_X(VOID const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->pixel_x);\n}\n\n/***************************************************************************\n * GET_ANIM_Y -- Gets the y from an animation                              *\n *                                                                         *\n *                                                                         *\n * INPUT:\t\tVOID * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:     WORD the y of the animation we are processing\t\t\t\t   *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/14/1992 PWG : Created.                                             *\n *=========================================================================*/\nWORD cdecl Get_Animation_Y(VOID const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->pixel_y);\n}\n\n/***************************************************************************\n * GET_ANIM_WIDTH -- Gets the width from an animation                      *\n *                                                                         *\n *                                                                         *\n * INPUT:\t\tVOID * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:     WORD the width of the animation we are processing\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/14/1992 PWG : Created.                                             *\n *=========================================================================*/\nWORD cdecl Get_Animation_Width(VOID const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->pixel_width);\n}\n\n/***************************************************************************\n * GET_ANIM_HEIGHT -- The height of the animation we are processing        *\n *                                                                         *\n * INPUT:\t\tVOID * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:     WORD the height of the animation we are processing\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/14/1992 PWG : Created.                                             *\n *=========================================================================*/\nWORD cdecl Get_Animation_Height(VOID const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->pixel_height);\n}\n\n\n/***************************************************************************\n * GET_ANIM_PALETTE -- Returns true if the anim had an attached palette    *\n *                                                                         *\n * INPUT:\t\tVOID * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:\t\tWORD True if the animation has a set palette.  False if the\t*\n *\t\t\t\t\tanimation does not.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/14/1992 PWG : Created.                                             *\n *=========================================================================*/\nWORD cdecl Get_Animation_Palette(VOID const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->flags & WSA_PALETTE_PRESENT);\n}\n\n\n/***************************************************************************\n * GET_ANIMATION_SIZE -- Return the amount of memory the animation is using*\n *                                                                         *\n *                                                                         *\n * INPUT:\t\tVOID * to the animation that we are processing              *\n *                                                                         *\n * OUTPUT:\t\tULONG number of byte used by animation. \t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/23/1994 SKB : Created.                                             *\n *=========================================================================*/\nULONG cdecl Get_Animation_Size(VOID const *handle)\n{\n \tSysAnimHeaderType const *sys_header;\n\n\tif (!handle) {\n\t\treturn FALSE;\n\t}\n\tsys_header = (SysAnimHeaderType *) handle;\n\treturn(sys_header->anim_mem_size);\n}\n\n/* ::::::::::::::::::::::::::::  PRIVATE FUNCTIONS  :::::::::::::::::::::::::::::: */\n\n\n/***************************************************************************\n * GET_RESIDENT_FRAME_OFFSET -- Gets frame offset of animate file in RAM   *\n *                                                                         *\n * INPUT:      BYTE *file_buffer in RAM of animation file.                 *\n *             WORD frame number that we need the offset of.               *\n *                                                                         *\n * OUTPUT:     WORD offset of frame requested.                             *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/26/1991  SB : Created.                                             *\n *=========================================================================*/\nPRIVATE ULONG Get_Resident_Frame_Offset( BYTE *file_buffer, WORD frame )\n{\n\tULONG frame0_size;\n\tULONG *lptr;\n\n\t// If there is a frame 0, the calculate its size.\n\tlptr = (ULONG *) file_buffer;\n\n\tif (*lptr) {\n\t\tframe0_size = lptr[1] - *lptr;\n\t} else {\n\t \tframe0_size = 0;\n\t}\n\n\t// Return the offset into RAM for the frame.\n\tlptr += frame;\n\tif (*lptr)\n\t\t\treturn (*lptr - (frame0_size + WSA_FILE_HEADER_SIZE));\n\telse\n\t\treturn (0L);\n}\n\n\n/***************************************************************************\n * GET_FILE_FRAME_OFFSET -- Get offset of a delta frame from animate file. *\n *                                                                         *\n * INPUT:      WORD file_handle of animation file.                         *\n *             WORD frame number that we need the offset of.               *\n *                                                                         *\n * OUTPUT:     WORD offset of frame requested.                             *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/26/1991  SB : Created.                                             *\n *=========================================================================*/\nPRIVATE ULONG Get_File_Frame_Offset( WORD file_handle, WORD frame, WORD palette_adjust)\n{\n\tULONG offset;\n\t\n\tSeek_File(file_handle, (frame << 2) + WSA_FILE_HEADER_SIZE, SEEK_SET);\n\n\tif (Read_File(file_handle, (BYTE *) &offset, sizeof(ULONG)) != sizeof(ULONG)) {\n\t\toffset = 0L;\n\t}\n\toffset += palette_adjust;\n\treturn( offset );\n}\n\n\n/***************************************************************************\n * APPLY_DELTA -- Copies frame into delta buffer, then applies to target   *\n *                                                                         *\n * INPUT:      SysAnimHeaderType *sys_header - pointer to animation buffer.*\n *             WORD curr_frame - frame to put into target buffer.          *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * OUTPUT:     BOOL - Return wether or not it worked.                      *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/26/1991  SB : Created.                                             *\n *=========================================================================*/\nPRIVATE BOOL Apply_Delta(SysAnimHeaderType *sys_header, WORD curr_frame, BYTE *dest_ptr, WORD dest_w)\n{\n\tBYTE *data_ptr, *delta_back;\n\tWORD file_handle, palette_adjust;\n\tULONG frame_data_size, frame_offset;\n\n\n\tpalette_adjust = ((sys_header->flags & WSA_PALETTE_PRESENT) ? 768 : 0);\n\tdelta_back\t\t= sys_header->delta_buffer;\n\n\tif (sys_header->flags & WSA_RESIDENT) {\n\t\t// Get offset of the given frame in the resident file\n\t\t// Get the size of the frame <- (frame+1 offset) - (offset)\n\t\t// Point at the delta data\n\t\t// figure offset to load data into end of delta buffer\n\t\t// copy it into buffer\n\t\n\t\tframe_offset = Get_Resident_Frame_Offset(sys_header->file_buffer, curr_frame);\n\t\tframe_data_size = Get_Resident_Frame_Offset(sys_header->file_buffer, curr_frame + 1) -\tframe_offset;\n\t\n\t  \tdata_ptr \t= (BYTE *)Add_Long_To_Pointer(sys_header->file_buffer, frame_offset);\n\t  \tdelta_back \t= (BYTE *)Add_Long_To_Pointer(delta_back, \n\t  \t\t\t\t\t\t sys_header->largest_frame_size - frame_data_size);\n\n\t\tMem_Copy( data_ptr, delta_back, frame_data_size );\n\n\t} else if (sys_header -> flags & WSA_FILE) {\n\n\t\t//\tOpen up file because not file not in RAM.\n\t\t// Get offset of the given frame in the file on disk\n\t\t// Get the size of the frame <- (frame+1 offset) - (offset)\n\t\t// Return if Get_.._offset() failed.  -- need error handling????  \n\t\t//\tSeek to delta data.\n\t\t// figure offset to load data into end of delta buffer\n\t\t//\tRead it into buffer -- Return if correct amount not read.-- errors??\n\n\t\tfile_handle  = sys_header->file_handle;\n\t\tSeek_File(file_handle, 0L, SEEK_SET);\n\n\t\tframe_offset = Get_File_Frame_Offset(file_handle, curr_frame, palette_adjust);\n\t\tframe_data_size = Get_File_Frame_Offset(file_handle, curr_frame + 1, palette_adjust) - frame_offset;\n\t\t\n\t\tif (!frame_offset || !frame_data_size) {\n\t\t\treturn(FALSE);\t\n\t\t}\n\n\t\tSeek_File(file_handle, frame_offset, SEEK_SET);\t\t\n\t\tdelta_back \t= (BYTE *)Add_Long_To_Pointer(delta_back, sys_header->largest_frame_size - frame_data_size);\n\n\t\tif (Read_File(file_handle, delta_back, frame_data_size) != frame_data_size) {\n\t\t\treturn(FALSE);\n\t\t}\n\t}\n\n\t// Uncompress data at end of delta buffer to the beginning of delta buffer.\n\t// Find start of target buffer.\n\t// Apply the XOR delta.\n\n\tLCW_Uncompress(delta_back, sys_header->delta_buffer, sys_header->largest_frame_size);\n\n\tif (sys_header->flags & WSA_TARGET_IN_BUFFER) {\n\t\tApply_XOR_Delta(dest_ptr, sys_header->delta_buffer);\n\t}\n\telse {\n\t\tApply_XOR_Delta_To_Page_Or_Viewport(dest_ptr, sys_header->delta_buffer,\n\t\t                        sys_header->pixel_width,  dest_w, DO_XOR);\n\t}\n\n\treturn(TRUE);\n}\n\n"
  },
  {
    "path": "WWFLAT32/WSA/WSA.H",
    "content": "/*\n**\tCommand & Conquer Red Alert(tm)\n**\tCopyright 2025 Electronic Arts Inc.\n**\n**\tThis program is free software: you can redistribute it and/or modify\n**\tit under the terms of the GNU General Public License as published by\n**\tthe Free Software Foundation, either version 3 of the License, or\n**\t(at your option) any later version.\n**\n**\tThis program is distributed in the hope that it will be useful,\n**\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n**\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n**\tGNU General Public License for more details.\n**\n**\tYou should have received a copy of the GNU General Public License\n**\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/***************************************************************************\n **   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   **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : WSA 32bit LIbrary                        *\n *                                                                         *\n *                    File Name : WSA.H                                    *\n *                                                                         *\n *                   Programmer : Scott K. Bowen                           *\n *                                                                         *\n *                   Start Date : May 23, 1994                             *\n *                                                                         *\n *                  Last Update : May 25, 1994   [SKB]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Open_Animation -- file name and flags, system allocates buffer.       *\n *   Open_Animation -- file name, flags, palette, system allocates buffer. *\n *   Open_Animation -- file_name, graphic buffer, flags.                   *\n *   Open_Animation -- file name, bufferclass, flags, palette.             *\n *   Open_Animation -- filename, ptr, size, flags, no palette.             *\n *   Animate_Frame -- Animate a frame to a page with magic colors.         *\n *   Animate_Frame -- Animate a frame to a viewport with magic colors.     *\n *   Animate_Frame -- Animate a frame to a page.                           *\n *   Animate_Frame -- Animate a frame to a viewport.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WSA_H\n#define WSA_H\n\n#ifndef WWSTD_H\n#include \"wwstd.h\"\n#endif\n\n#ifndef GBUFFER_H\n#include \"gbuffer.h\"\n#endif\n\n#ifndef VBUFFER_H\n#include \"vbuffer.h\"\n#endif\n\n//lint -strong(AJX,WSAType)\ntypedef enum {\n\tWSA_NORMAL,\t\t\t\t\t\t\t\t// Normal WSA animation\n\tWSA_GHOST\t \t= 0x1000,\t\t\t// Or'd with the above flags to get ghosting\n\tWSA_PRIORITY2 \t= 0x2000,\t\t\t// Copy using a priority (or in the priority)\n\tWSA_TRANS    \t= 0x4000,\t\t\t// Copy frame, ignoring transparent colors\n\tWSA_PRIORITY \t= 0x8000\t\t\t\t// Copy using a priority (or in the priority)\n} WSAType;\n\n\n//lint -strong(AJX,WSAOpenType)\ntypedef enum {\n\tWSA_OPEN_FROM_MEM\t\t= 0x0000,\t// Try to load entire anim into memory.\n\tWSA_OPEN_INDIRECT\t\t= 0x0000,\t// First animate to internal buffer, then copy to page/viewport.\n\tWSA_OPEN_FROM_DISK\t= 0x0001,\t// Force the animation to be disk based.\t\n\tWSA_OPEN_DIRECT\t\t= 0x0002,\t// Animate directly to page or viewport.\n\n\t// These next two have been added for the 32 bit library to give a better idea of what is\n\t// happening.  You may want to animate directly to the destination or indirectly to the\n\t// destination by using the animations buffer.  Indirecly is best if the dest is a seenpage\n\t// and the animation is not linear or if the destination is modified between frames.\n\tWSA_OPEN_TO_PAGE  = WSA_OPEN_DIRECT ,\n\tWSA_OPEN_TO_BUFFER= WSA_OPEN_INDIRECT ,\n\n} WSAOpenType;\n\n/*=========================================================================*/\n/* The following prototypes are for the file: WSA.CPP\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\nVOID * cdecl Open_Animation(BYTE const *file_name, BYTE *user_buffer, LONG user_buffer_size, WSAOpenType user_flags, UBYTE *palette=NULL);\nVOID cdecl Close_Animation( VOID *handle );\nBOOL cdecl Animate_Frame(VOID *handle, GraphicViewPortClass& view,\n                         WORD frame_number, WORD x_pixel=0, WORD y_pixel=0,\n                         WSAType flags_and_prio = WSA_NORMAL, VOID *magic_cols=NULL, VOID *magic=NULL);\nWORD cdecl Get_Animation_Frame_Count(VOID *handle);\nBOOL cdecl Animate_Frame(VOID *handle, VideoViewPortClass& view,\n                         WORD frame_number, WORD x_pixel=0, WORD y_pixel=0,\n                         WSAType flags_and_prio = WSA_NORMAL, VOID *magic_cols=NULL, VOID *magic=NULL);\nWORD cdecl Get_Animation_Frame_Count(VOID *handle);\nWORD cdecl Get_Animation_X(VOID const *handle);\nWORD cdecl Get_Animation_Y(VOID const *handle);\nWORD cdecl Get_Animation_Width(VOID const *handle);\nWORD cdecl Get_Animation_Height(VOID const *handle);\nWORD cdecl Get_Animation_Palette(VOID const *handle);\nULONG cdecl Get_Animation_Size(VOID const *handle);\n\n\n/***************************************************************************\n * OPEN_ANIMATION -- file name, flags, palette, system allocates buffer.   *\n *                                                                         *\n *                                                                         *\n * INPUT:   BYTE *file_name - name of file to open.                        *\n *          WSAOpenType user_flags - flags on how to open.                 *\n *          UBYTE *palette - pointer to a palette buffer to fill.          *\n *                                                                         *\n * OUTPUT:  VOID *pointer to animation data.  Must be used for all \t\t\t*\n *               other WSA calls.                                          *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/24/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline VOID *cdecl Open_Animation(BYTE *file_name, WSAOpenType user_flags, UBYTE *palette=NULL) \n{\n\treturn (Open_Animation(file_name, NULL, 0L, user_flags,  palette));\n}\n\n\n/***************************************************************************\n * OPEN_ANIMATION -- file_name, bufferclass, flags. \t\t\t\t\t\t\t\t*\n *                                                                         *\n *                                                                         *\n * INPUT:   BYTE *file_name - name of file to open.                        *\n *          GraphicBufferClass - pointer to a buffer.                      *\n *          WSAOpenType user_flags - flags on how to open.                 *\n *          UBYTE *palette - pointer to a palette buffer to fill.          *\n *                                                                         *\n * OUTPUT:  VOID *pointer to animation data.  Must be used for all \t\t\t*\n *               other WSA calls.                                          *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/24/1994 SKB : Created.                                             *\n *=========================================================================*/\ninline VOID *cdecl Open_Animation(BYTE *file_name, BufferClass& buffer, WSAOpenType user_flags,  UBYTE *palette=NULL) \n{\n\treturn (Open_Animation(file_name, (BYTE *)buffer.Get_Buffer(), buffer.Get_Size(), user_flags, palette));\n}\n\n\n/*=========================================================================*/\n/* The following prototypes are for the file: LP_ASM.ASM\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n\n\nextern \"C\" {\nUWORD Apply_XOR_Delta(BYTE *source_ptr, BYTE *delta_ptr);\nVOID  Apply_XOR_Delta_To_Page_Or_Viewport(VOID *target, VOID *delta, WORD width, WORD nextrow, WORD copy);\n}\n\n\n\n#endif // WSA_H\n"
  },
  {
    "path": "WWFLAT32/WSA/XORDELTA.ASM",
    "content": ";\n;\tCommand & Conquer Red Alert(tm)\n;\tCopyright 2025 Electronic Arts Inc.\n;\n;\tThis program is free software: you can redistribute it and/or modify\n;\tit under the terms of the GNU General Public License as published by\n;\tthe Free Software Foundation, either version 3 of the License, or\n;\t(at your option) any later version.\n;\n;\tThis program is distributed in the hope that it will be useful,\n;\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n;\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;\tGNU General Public License for more details.\n;\n;\tYou should have received a copy of the GNU General Public License\n;\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n;\n\n; **************************************************************************\n; **   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   *\n; **************************************************************************\n; *                                                                        *\n; *                 Project Name : WSA Support routines\t\t\t   *\n; *                                                                        *\n; *                    File Name : XORDELTA.ASM                            *\n; *                                                                        *\n; *                   Programmer : Scott K. Bowen\t\t\t   *\n; *                                                                        *\n; *                  Last Update :May 23, 1994   [SKB]                     *\n; *                                                                        *\n; *------------------------------------------------------------------------*\n; * Functions:                                                             *\n;*   Apply_XOR_Delta -- Apply XOR delta data to a buffer.                  *\n;*   Apply_XOR_Delta_To_Page_Or_Viewport -- Calls the copy or the XOR funti*\n;*   Copy_Delta_buffer -- Copies XOR Delta Data to a section of a page.    *\n;*   XOR_Delta_Buffer -- Xor's the data in a XOR Delta format to a page.   *\n; * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n\n\n\nLOCALS ??\n\n; These are used to call Apply_XOR_Delta_To_Page_Or_Viewport() to setup flags parameter.  If\n; These change, make sure and change their values in wsa.cpp.\nDO_XOR\t\tequ\t0\nDO_COPY\t\tequ\t1\nTO_VIEWPORT\tequ\t0\nTO_PAGE\t\tequ\t2\n\n;\n; Routines defined in this module\n;\n;\n; UWORD Apply_XOR_Delta(UWORD page_seg, BYTE *delta_ptr);\n; PUBLIC Apply_XOR_Delta_To_Page_Or_Viewport(UWORD page_seg, BYTE *delta_ptr, WORD width, WORD copy)\n;\n;\tPROC\tC XOR_Delta_Buffer\n;\tPROC\tC Copy_Delta_Buffer\n;\n\nGLOBAL \tApply_XOR_Delta:NEAR\nGLOBAL \tApply_XOR_Delta_To_Page_Or_Viewport:NEAR\n\n\n\n\tCODESEG\n\n\n\n;***************************************************************************\n;* APPLY_XOR_DELTA -- Apply XOR delta data to a linear buffer.             *\n;*   AN example of this in C is at the botton of the file commented out.   *\n;*                                                                         *\n;* INPUT:  BYTE *target - destination buffer.                              *\n;*         BYTE *delta - xor data to be delta uncompress.                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   05/23/1994 SKB : Created.                                             *\n;*=========================================================================*\nPROC\tApply_XOR_Delta C near\n\tUSES \tebx,ecx,edx,edi,esi\n\tARG\ttarget:DWORD \t\t; pointers.\n\tARG\tdelta:DWORD\t\t; pointers.\n\n\t; Optimized for 486/pentium by rearanging instructions.\n\tmov\tedi,[target]\t\t; get our pointers into offset registers.\n\tmov\tesi,[delta]\n\n\tcld\t\t\t\t; make sure we go forward\n\txor\tecx,ecx\t\t\t; use cx for loop\n\n??top_loop:\n\txor\teax,eax\t\t\t; clear out eax.\t\n\tlodsb\t\t\t\t; get delta source byte\n\n\tor\tal,al\t\t\t; check for a SHORTDUMP ; check al incase of sign value.\n\tje\t??short_run\n\tjs\t??check_others\n\n;\n; SHORTDUMP\n;\n\tmov\tecx,eax\t\t\t; stick count in cx\n\n??dump_loop:\n\tlodsb\t\t\t\t; get delta XOR byte\n\txor\t[edi],al\t\t; xor that byte on the dest\n\tinc\tedi\n\tdec\tecx\n\tjnz\t??dump_loop\n\tjmp\t??top_loop\n\n;\n; SHORTRUN\n;\n\n??short_run:\n\tmov\tcl,[esi]\t\t; get count\n\tinc\tesi\t\t\t; inc delta source\n\n??do_run:\n\tlodsb\t\t\t\t; get XOR byte\n\n??run_loop:\n\txor\t[edi],al\t\t; xor that byte.\n\n\tinc\tedi\t\t\t; go to next dest pixel\n\tdec\tecx\t\t\t; one less to go.\t\n\tjnz\t??run_loop\n\tjmp\t??top_loop\n\n;\n; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP\n;\n\n??check_others:\n\tsub\teax,080h\t\t; opcode -= 0x80\n\tjnz\t??do_skip\t\t; if zero then get next word, otherwise use remainder.\n\n\tlodsw\t\t\t\t; get word code in ax\n\tor\tax,ax\t\t\t; set flags. (not 32bit register so neg flag works)\n\tjle\t??not_long_skip\n\n;\n; SHORTSKIP AND LONGSKIP\n;\t\t\n??do_skip:\n\tadd\tedi,eax\t\t\t; do the skip.\n\tjmp\t??top_loop\n\n\n??not_long_skip:\n\tjz\t??stop\t\t\t; long count of zero means stop\n\tsub\teax,08000h     \t\t; opcode -= 0x8000\n\ttest\teax,04000h\t\t; is it a LONGRUN (code & 0x4000)?\n\tje\t??long_dump\n\t\n;\n; LONGRUN\n;\n\tsub\teax,04000h\t\t; opcode -= 0x4000\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??do_run\t\t; jump to run code.\n\n\n;\n; LONGDUMP\n;\n\n??long_dump:\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??dump_loop\t\t; go to the dump loop.\n\n??stop:\n\n\tret\n\n\tENDP\tApply_XOR_Delta\n\n\n;----------------------------------------------------------------------------\n\n\n;***************************************************************************\n;* APPLY_XOR_DELTA_To_Page_Or_Viewport -- Calls the copy or the XOR funtion.           *\n;*                                                                         *\n;*\t\t\t\t\t\t\t\t\t   *\n;* \tThis funtion is call to either xor or copy XOR_Delta data onto a   *\n;*\tpage instead of a buffer.  The routine will set up the registers   *\n;*\tneed for the actual routines that will perform the copy or xor.\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;*\tThe registers are setup as follows :\t\t\t\t   *\n;*\t\tes:edi - destination segment:offset onto page.\t\t   *\n;*\t\tds:esi - source buffer segment:offset of delta data.\t   *\n;*\t\tdx,cx,ax - are all zeroed out before entry.\t\t   *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/09/1992  SB : Created.                                             *\n;*=========================================================================*\n\n;PUBLIC Apply_XOR_Delta_To_Page_Or_Viewport(UWORD page_seg, BYTE *delta_ptr, WORD width, WORD flags, WORD descriptor)\nPROC\tApply_XOR_Delta_To_Page_Or_Viewport C near\n\tUSES \tebx,ecx,edx,edi,esi\n\tARG\ttarget:DWORD\t\t; pointer to the destination buffer.\n\tARG\tdelta:DWORD\t\t; pointer to the delta buffer.\n\tARG\twidth:DWORD\t\t; width of animation.\n\tARG\tnextrow:DWORD\t\t; Page/Buffer width - anim width.\n\tARG\tcopy:DWORD\t\t; should it be copied or xor'd?\t\n\n\n\tmov\tedi,[target]\t\t; Get the target pointer.\n\tmov\tesi,[delta]\t\t; Get the destination pointer.\n\n\txor\teax,eax\t\t\t; clear eax, later put them into ecx and edx.\n\n\tcld\t\t\t\t; make sure we go forward\n\n\tmov\tebx,[nextrow]\t\t; get the amount to add to get to next row from end.  push it later...\n\n\tmov\tecx,eax\t\t\t; use cx for loop\n\tmov\tedx,eax\t\t\t; use dx to count the relative column.\n\n\tpush\tebx\t\t\t; push nextrow onto the stack for Copy/XOR_Delta_Buffer.\t\n\tmov\tebx,[width]\t\t; bx will hold the max column for speed compares\n\n; At this point, all the registers have been set up.  Now call the correct function\n; to either copy or xor the data.\n\n\tcmp\t[copy],DO_XOR\t\t; Do we want to copy or XOR\n\tje\t??xorfunct\t\t; Jump to XOR if not copy\n\tcall\tCopy_Delta_Buffer\t; Call the function to copy the delta buffer.\n\tjmp\t??didcopy\t\t; jump past XOR\n??xorfunct:\n\tcall\tXOR_Delta_Buffer\t; Call funtion to XOR the deltat buffer.\n??didcopy:\n\tpop\tebx\t\t\t; remove the push done to pass a value.\n\n\tret\n\n\tENDP\tApply_XOR_Delta_To_Page_Or_Viewport\n;----------------------------------------------------------------------------\n\n\n;***************************************************************************\n;* XOR_DELTA_BUFFER -- Xor's the data in a XOR Delta format to a page.     *\n;*\tThis will only work right if the page has the previous data on it. *\n;*\tThis function should only be called by XOR_Delta_Buffer_To_Page_Or_Viewport.   *\n;*      The registers must be setup as follows :                           *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*\tes:edi - destination segment:offset onto page.\t\t \t   *\n;*\tds:esi - source buffer segment:offset of delta data.\t \t   *\n;*\tedx,ecx,eax - are all zeroed out before entry.\t\t \t   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/09/1992  SB : Created.                                             *\n;*=========================================================================*\n\nPROC\tXOR_Delta_Buffer C near\n\tARG\tnextrow:DWORD\n\n??top_loop:\n\txor\teax,eax\t\t\t; clear out eax.\t\n\tlodsb\t\t\t\t; get delta source byte\n\n\tor\tal,al\t\t\t; check for a SHORTDUMP ; check al incase of sign value.\n\tje\t??short_run\n\tjs\t??check_others\n\n;\n; SHORTDUMP\n;\n\tmov\tecx,eax\t\t\t; stick count in cx\n\n??dump_loop:\n\tlodsb\t\t\t\t; get delta XOR byte\n\txor\t[edi],al\t\t; xor that byte on the dest\n\tinc\tedx\t\t\t; increment our count on current column\n\tinc\tedi\n\tcmp\tedx,ebx\t\t\t; are we at the final column\n\tjne\t??end_col1\t\t; if not the jmp over the code\n\n\tsub\tedi,edx\t\t\t; get our column back to the beginning.\n\txor\tedx,edx\t\t\t; zero out our column counter\n\tadd\tedi,[nextrow]\t\t; jump to start of next row\n??end_col1:\n\n\tdec\tecx\n\tjnz\t??dump_loop\n\tjmp\t??top_loop\n\n;\n; SHORTRUN\n;\n\n??short_run:\n\tmov\tcl,[esi]\t\t; get count\n\tinc\tesi\t\t\t; inc delta source\n\n??do_run:\n\tlodsb\t\t\t\t; get XOR byte\n\n??run_loop:\n\txor\t[edi],al\t\t; xor that byte.\n\n\tinc\tedx\t\t\t; increment our count on current column\n\tinc\tedi\t\t\t; go to next dest pixel\n\tcmp\tedx,ebx\t\t\t; are we at the final column\n\tjne\t??end_col2\t\t; if not the jmp over the code\n\n\tsub\tedi,ebx\t\t\t; get our column back to the beginning.\n\txor\tedx,edx\t\t\t; zero out our column counter\n\tadd\tedi,[nextrow]\t\t; jump to start of next row\n??end_col2:\n\n\n\tdec\tecx\n\tjnz\t??run_loop\n\tjmp\t??top_loop\n\n;\n; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP\n;\n\n??check_others:\n\tsub\teax,080h\t\t; opcode -= 0x80\n\tjnz\t??do_skip\t\t; if zero then get next word, otherwise use remainder.\n\n\tlodsw\t\t\t\t; get word code in ax\n\tor\tax,ax\t\t\t; set flags. (not 32bit register so neg flag works)\n\tjle\t??not_long_skip\n\n;\n; SHORTSKIP AND LONGSKIP\n;\t\t\n??do_skip:\n\tsub\tedi,edx\t\t\t; go back to beginning or row.\n\tadd\tedx,eax\t\t\t; incriment our count on current row\n??recheck3:\n\tcmp\tedx,ebx\t\t\t; are we past the end of the row\n\tjb\t??end_col3  \t\t; if not the jmp over the code\n\n\tsub\tedx,ebx\t\t\t; Subtract width from the col counter\n\tadd\tedi,[nextrow]  \t\t; jump to start of next row\n\tjmp\t??recheck3\t\t; jump up to see if we are at the right row\n??end_col3:\n\tadd\tedi,edx\t\t\t; get to correct position in row.\t\n\tjmp\t??top_loop\n\n\n??not_long_skip:\n\tjz\t??stop\t\t\t; long count of zero means stop\n\tsub\teax,08000h     \t\t; opcode -= 0x8000\n\ttest\teax,04000h\t\t; is it a LONGRUN (code & 0x4000)?\n\tje\t??long_dump\n\t\n;\n; LONGRUN\n;\n\tsub\teax,04000h\t\t; opcode -= 0x4000\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??do_run\t\t; jump to run code.\n\n\n;\n; LONGDUMP\n;\n\n??long_dump:\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??dump_loop\t\t; go to the dump loop.\n\n??stop:\n\n\tret\n\n\n\tENDP\tXOR_Delta_Buffer\n\n;----------------------------------------------------------------------------\n\n\n;***************************************************************************\n;* COPY_DELTA_BUFFER -- Copies XOR Delta Data to a section of a page.      *\n;*\tThis function should only be called by XOR_Delta_Buffer_To_Page_Or_Viewport.   *\n;*      The registers must be setup as follows :                           *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*\tes:edi - destination segment:offset onto page.\t\t \t   *\n;*\tds:esi - source buffer segment:offset of delta data.\t \t   *\n;*\tdx,cx,ax - are all zeroed out before entry.\t\t \t   *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/09/1992  SB : Created.                                             *\n;*=========================================================================*\nPROC\tCopy_Delta_Buffer C near\n\tARG\tnextrow:DWORD\n\n??top_loop:\n\txor\teax,eax\t\t\t; clear out eax.\t\n\tlodsb\t\t\t\t; get delta source byte\n\n\tor\tal,al\t\t\t; check for a SHORTDUMP ; check al incase of sign value.\n\tje\t??short_run\n\tjs\t??check_others\n\n;\n; SHORTDUMP\n;\n\tmov\tecx,eax\t\t\t; stick count in cx\n\n??dump_loop:\n\tlodsb\t\t\t\t; get delta XOR byte\n\n\tmov\t[edi],al\t\t; store that byte on the dest\n\n\tinc\tedx\t\t\t; increment our count on current column\n\tinc\tedi\n\tcmp\tedx,ebx\t\t\t; are we at the final column\n\tjne\t??end_col1\t\t; if not the jmp over the code\n\n\tsub\tedi,edx\t\t\t; get our column back to the beginning.\n\txor\tedx,edx\t\t\t; zero out our column counter\n\tadd\tedi,[nextrow]\t\t; jump to start of next row\n??end_col1:\n\n\tdec\tecx\n\tjnz\t??dump_loop\n\tjmp\t??top_loop\n\n;\n; SHORTRUN\n;\n\n??short_run:\n\tmov\tcl,[esi]\t\t; get count\n\tinc\tesi\t\t\t; inc delta source\n\n??do_run:\n\tlodsb\t\t\t\t; get XOR byte\n\n??run_loop:\n\tmov\t[edi],al\t\t; store the byte (instead of XOR against current color)\n\n\tinc\tedx\t\t\t; increment our count on current column\n\tinc\tedi\t\t\t; go to next dest pixel\n\tcmp\tedx,ebx\t\t\t; are we at the final column\n\tjne\t??end_col2\t\t; if not the jmp over the code\n\n\tsub\tedi,ebx\t\t\t; get our column back to the beginning.\n\txor\tedx,edx\t\t\t; zero out our column counter\n\tadd\tedi,[nextrow]\t\t; jump to start of next row\n??end_col2:\n\n\n\tdec\tecx\n\tjnz\t??run_loop\n\tjmp\t??top_loop\n\n;\n; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP\n;\n\n??check_others:\n\tsub\teax,080h\t\t; opcode -= 0x80\n\tjnz\t??do_skip\t\t; if zero then get next word, otherwise use remainder.\n\n\tlodsw\t\t\t\t; get word code in ax\n\tor\tax,ax\t\t\t; set flags. (not 32bit register so neg flag works)\n\tjle\t??not_long_skip\n\n;\n; SHORTSKIP AND LONGSKIP\n;\t\t\n??do_skip:\n\tsub\tedi,edx\t\t\t; go back to beginning or row.\n\tadd\tedx,eax\t\t\t; incriment our count on current row\n??recheck3:\n\tcmp\tedx,ebx\t\t\t; are we past the end of the row\n\tjb\t??end_col3  \t\t; if not the jmp over the code\n\n\tsub\tedx,ebx\t\t\t; Subtract width from the col counter\n\tadd\tedi,[nextrow]  \t\t; jump to start of next row\n\tjmp\t??recheck3\t\t; jump up to see if we are at the right row\n??end_col3:\n\tadd\tedi,edx\t\t\t; get to correct position in row.\t\n\tjmp\t??top_loop\n\n\n??not_long_skip:\n\tjz\t??stop\t\t\t; long count of zero means stop\n\tsub\teax,08000h     \t\t; opcode -= 0x8000\n\ttest\teax,04000h\t\t; is it a LONGRUN (code & 0x4000)?\n\tje\t??long_dump\n\t\n;\n; LONGRUN\n;\n\tsub\teax,04000h\t\t; opcode -= 0x4000\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??do_run\t\t; jump to run code.\n\n\n;\n; LONGDUMP\n;\n\n??long_dump:\n\tmov\tecx,eax\t\t\t; use cx as loop count\n\tjmp\t??dump_loop\t\t; go to the dump loop.\n\n??stop:\n\n\tret\n\n\tENDP\tCopy_Delta_Buffer\n\n;----------------------------------------------------------------------------\n\n\tEND\n\n\n;----------------------------------------------------------------------------\n;\n;PUBLIC UWORD Apply_XOR_Delta(UWORD page_seg, BYTE *delta_ptr)\n;{\n;\n;\tregister UWORD loop;\n;\tBYTE opcode, xor_byte;\n;\tUWORD bytes_to_uncompress = 64000U;\n;\n;\n;\t/* Make our buffer pointer */\n;\n;\tto    = MK_FP(page_seg, 0);\n;\tdelta = Normalize_Pointer(delta_ptr);\n;\n;\n;\twhile (bytes_to_uncompress) {\n;\n;\t\topcode = *delta++;\n;\n;\n;\t\t/* Check for SHORTDUMP */\n;\n;\t\tif (opcode > 0) {\n;\n;\n;\t\t\tbytes_to_uncompress -= opcode;\n;\n;\t\t\tfor (loop = 0; loop < opcode; loop++) {\n;\t\t\t\txor_byte = *delta++;\n;\t\t\t\t*to++ ^= xor_byte;\n;\t\t\t}\n;\t\t\tcontinue;\n;\t\t}\n;\n;\t\t/* Check for SHORTRUN */\n;\n;\t\tif (opcode == 0) {\n;\n;\t\t\tword_count = *delta++;\n;\t\t\txor_byte   = *delta++;\n;\n;\t\t\tbytes_to_uncompress -= word_count;\n;\n;\t\t\tfor (loop = 0; loop < word_count; loop++) {\n;\t\t\t\t*to++ ^= xor_byte;\n;\t\t\t}\n;\t\t\tcontinue;\n;\t\t}\n;\n;\t\t/* By now, we know it must be a LONGDUMP, SHORTSKIP, or LONGSKIP */\n;\n;\t\topcode -= 0x80;\n;\n;\n;\t\t/* Is it a SHORTSKIP? */\n;\n;\t\tif (opcode != 0) {\n;\n;\t\t\tto += opcode;\n;\t\t\tbytes_to_uncompress -= (WORD) opcode;\n;\t\t\tcontinue;\n;\t\t}\n;\n;\n;\t\tword_count = *((UWORD *) delta)++;\n;\n;\t\t/* Is it a LONGSKIP? */\n;\n;\t\tif ((WORD) word_count > 0) {\n;\n;\t\t\tto += word_count;\n;\t\t\tbytes_to_uncompress -= (WORD) word_count;\n;\t\t\tcontinue;\n;\t\t}\n;\n;\n;\t\tword_count -= 0x8000;\n;\n;\t\t/* Is it a LONGRUN? */\n;\n;\t\tif (word_count & 0x4000) {\n;\n;\t\t\tword_count -= 0x4000;\n;\n;\t\t\tbytes_to_uncompress -= word_count;\n;\n;\t\t\txor_byte = *delta++;\n;\n;\t\t\tfor (loop = 0; loop < word_count; loop++) {\n;\t\t\t\t*to++ ^= xor_byte;\n;\t\t\t}\n;\t\t\tcontinue;\n;\t\t}\n;\n;\n;\t\t/* It must be a LONGDUMP */\n;\n;\t\tbytes_to_uncompress -= word_count;\n;\n;\t\tfor (loop = 0; loop < word_count; loop++) {\n;\t\t\txor_byte = *delta++;\n;\t\t\t*to++ ^= xor_byte;\n;\t\t}\n;\t}\n;\n;\n;\treturn(64000U);\n;}\n;\n\n\u001a\n"
  }
]